[med-svn] [bioimagesuite] 01/04: New upstream version 2.0

Andreas Tille tille at debian.org
Mon Nov 20 15:20:37 UTC 2017


This is an automated email from the git hooks/post-receive script.

tille pushed a commit to branch master
in repository bioimagesuite.

commit c6d76e8194a944852d4960555c0db9734355eb0c
Author: Andreas Tille <tille at debian.org>
Date:   Mon Nov 20 18:14:37 2017 +0100

    New upstream version 2.0
---
 Registration/dvSparseMatrix.h                      |   465 +
 bioimagesuite30_src/BioImageSuiteMacros.cmake      |   366 +
 bioimagesuite30_src/BioImageSuite_Description.txt  |    36 +
 bioimagesuite30_src/BioImageSuite_License.txt      |   340 +
 bioimagesuite30_src/BioImageSuite_ShortLicense.txt |    50 +
 bioimagesuite30_src/CMakeLists.txt                 |   197 +
 bioimagesuite30_src/CMakeOptions.cmake             |   573 +
 bioimagesuite30_src/CPackOptions.cmake             |   319 +
 bioimagesuite30_src/CTestCustom.cmake.in           |     3 +
 bioimagesuite30_src/Common/CMakeLists.txt          |   231 +
 bioimagesuite30_src/Common/nifti1_io.c             |  6415 +++++
 bioimagesuite30_src/Common/vtkTemplateAliasMacro.h |   148 +
 bioimagesuite30_src/Common/vtkafBVImageReader.cpp  |   390 +
 bioimagesuite30_src/Common/vtkafBVImageReader.h    |   167 +
 bioimagesuite30_src/Common/vtkafBVImageWriter.cpp  |   236 +
 bioimagesuite30_src/Common/vtkafBVImageWriter.h    |   176 +
 .../Common/vtkbisCylinderSource.cpp                |   255 +
 bioimagesuite30_src/Common/vtkbisCylinderSource.h  |    85 +
 bioimagesuite30_src/Common/vtkbisDICOMReader.cpp   |   503 +
 bioimagesuite30_src/Common/vtkbisDICOMReader.h     |   142 +
 .../Common/vtkbisGDCMImageReader.cpp               |  1308 +
 bioimagesuite30_src/Common/vtkbisGDCMImageReader.h |   306 +
 bioimagesuite30_src/Common/vtkbisImageHeader.cpp   |  2954 ++
 bioimagesuite30_src/Common/vtkbisImageHeader.h     |   335 +
 bioimagesuite30_src/Common/vtkbisImageReOrient.cpp |   323 +
 bioimagesuite30_src/Common/vtkbisImageReOrient.h   |   145 +
 bioimagesuite30_src/Common/vtkbisImageResample.cpp |    54 +
 bioimagesuite30_src/Common/vtkbisImageResample.h   |    67 +
 bioimagesuite30_src/Common/vtkbisImageReslice.cpp  |    52 +
 bioimagesuite30_src/Common/vtkbisImageReslice.h    |    70 +
 .../Common/vtkbisNIFTIExtension.cpp                |   143 +
 bioimagesuite30_src/Common/vtkbisNIFTIExtension.h  |    80 +
 .../Common/vtkbisNIFTIExtensionsList.cpp           |   243 +
 .../Common/vtkbisNIFTIExtensionsList.h             |   106 +
 bioimagesuite30_src/Common/vtkbisTestUtil.cpp      |   412 +
 bioimagesuite30_src/Common/vtkbisTestUtil.h        |    87 +
 .../Common/vtkjoColoredSphereSource.cpp            |   361 +
 .../Common/vtkjoColoredSphereSource.h              |   113 +
 bioimagesuite30_src/Common/vtkjoROCFilter.cpp      |   212 +
 bioimagesuite30_src/Common/vtkjoROCFilter.h        |   111 +
 bioimagesuite30_src/Common/vtkjoSphereSource.cxx   |   566 +
 bioimagesuite30_src/Common/vtkjoSphereSource.h     |   176 +
 bioimagesuite30_src/Common/vtkjoStatistics.cpp     |    91 +
 bioimagesuite30_src/Common/vtkjoStatistics.h       |    60 +
 .../Common/vtkokImageAccumulate.cpp                |   440 +
 bioimagesuite30_src/Common/vtkokImageAccumulate.h  |   168 +
 bioimagesuite30_src/Common/vtkpxAbstractMatrix.cpp |   104 +
 bioimagesuite30_src/Common/vtkpxAbstractMatrix.h   |   155 +
 .../Common/vtkpxAnalyzeImageSource.cpp             |   589 +
 .../Common/vtkpxAnalyzeImageSource.h               |   183 +
 .../Common/vtkpxAnalyzeImageSourceOld.cpp          |   672 +
 .../Common/vtkpxAnalyzeImageSourceOld.h            |   191 +
 .../Common/vtkpxAnalyzeImageWriter.cpp             |   354 +
 .../Common/vtkpxAnalyzeImageWriter.h               |   139 +
 .../Common/vtkpxAppendComponents.cpp               |   185 +
 bioimagesuite30_src/Common/vtkpxAppendComponents.h |    89 +
 bioimagesuite30_src/Common/vtkpxBSpline.cpp        |   318 +
 bioimagesuite30_src/Common/vtkpxBSpline.h          |   141 +
 bioimagesuite30_src/Common/vtkpxBaseCurve.cpp      |  2357 ++
 bioimagesuite30_src/Common/vtkpxBaseCurve.h        |   309 +
 .../Common/vtkpxCrossHairSource.cpp                |   128 +
 bioimagesuite30_src/Common/vtkpxCrossHairSource.h  |   123 +
 .../Common/vtkpxDataArrayUndoStack.cpp             |    80 +
 .../Common/vtkpxDataArrayUndoStack.h               |    75 +
 .../Common/vtkpxEpilepsyCSIReader.cpp              |   236 +
 .../Common/vtkpxEpilepsyCSIReader.h                |   116 +
 .../Common/vtkpxGenericUndoStack.cpp               |   246 +
 bioimagesuite30_src/Common/vtkpxGenericUndoStack.h |    99 +
 .../Common/vtkpxImageComponentsToFrames.cpp        |   192 +
 .../Common/vtkpxImageComponentsToFrames.h          |   110 +
 bioimagesuite30_src/Common/vtkpxImageExtract.cpp   |   781 +
 bioimagesuite30_src/Common/vtkpxImageExtract.h     |   185 +
 .../Common/vtkpxImageExtractVOI.cpp                |   219 +
 bioimagesuite30_src/Common/vtkpxImageExtractVOI.h  |   121 +
 .../Common/vtkpxImageReplaceSlice.cpp              |   198 +
 .../Common/vtkpxImageReplaceSlice.h                |   133 +
 bioimagesuite30_src/Common/vtkpxMath.cpp           |  1126 +
 bioimagesuite30_src/Common/vtkpxMath.h             |   146 +
 bioimagesuite30_src/Common/vtkpxMatrix.cpp         |  3029 +++
 bioimagesuite30_src/Common/vtkpxMatrix.h           |   337 +
 .../Common/vtkpxOpenIGTLinkClient.cpp              |   421 +
 .../Common/vtkpxOpenIGTLinkClient.h                |   100 +
 .../Common/vtkpxOpenIGTLinkClientObserver.cpp      |    66 +
 .../Common/vtkpxOpenIGTLinkClientObserver.h        |    68 +
 .../Common/vtkpxOpenIGTLinkServer.cpp              |   646 +
 .../Common/vtkpxOpenIGTLinkServer.h                |   173 +
 .../Common/vtkpxOpenIGTLinkServerObserver.cpp      |    66 +
 .../Common/vtkpxOpenIGTLinkServerObserver.h        |    68 +
 bioimagesuite30_src/Common/vtkpxOptimizer.cpp      |   957 +
 bioimagesuite30_src/Common/vtkpxOptimizer.h        |   185 +
 .../Common/vtkpxPickerPrismSource.cpp              |   501 +
 .../Common/vtkpxPickerPrismSource.h                |    91 +
 .../Common/vtkpxSignaLXImageSource.cpp             |   364 +
 .../Common/vtkpxSignaLXImageSource.h               |   101 +
 .../Common/vtkpxSimpleImageToImageFilter.cpp       |   163 +
 .../Common/vtkpxSimpleImageToImageFilter.h         |   118 +
 ...kpxStructuredPointsToStructuredPointsFilter.cpp |   103 +
 ...vtkpxStructuredPointsToStructuredPointsFilter.h |    87 +
 .../Common/vtkpxTensorBSplineTransform.cpp         |  1472 +
 .../Common/vtkpxTensorBSplineTransform.h           |   290 +
 bioimagesuite30_src/Common/vtkpxTestOptimizer.cpp  |   217 +
 bioimagesuite30_src/Common/vtkpxTestOptimizer.h    |   115 +
 bioimagesuite30_src/Common/vtkpxUtil.cpp           |  1057 +
 bioimagesuite30_src/Common/vtkpxUtil.h             |   232 +
 .../Common/vtkpxVVLinkConnectorNew.cpp             |  1446 +
 .../Common/vtkpxVVLinkConnectorNew.h               |   216 +
 bioimagesuite30_src/Common/znzlib.c                |   309 +
 bioimagesuite30_src/CompilingBioImageSuite.html    |   212 +
 bioimagesuite30_src/Connectivity/CMakeLists.txt    |   107 +
 .../Connectivity/vtkbisConnectivityUtility.cpp     |   759 +
 .../Connectivity/vtkbisConnectivityUtility.h       |    77 +
 .../Connectivity/vtkbisCsfWmMotionCorrection.cpp   |   351 +
 .../Connectivity/vtkbisCsfWmMotionCorrection.h     |   104 +
 .../vtkbisDijkstraGraphGeodesicPath.cpp            |   615 +
 .../Connectivity/vtkbisDijkstraGraphGeodesicPath.h |   212 +
 .../Connectivity/vtkbisDisplayROIMean.cpp          |   151 +
 .../Connectivity/vtkbisDisplayROIMean.h            |    73 +
 .../Connectivity/vtkbisImageTemporalSmoothing.cpp  |   226 +
 .../Connectivity/vtkbisImageTemporalSmoothing.h    |    88 +
 .../vtkbisImageTimeSeriesNormalize.cpp             |   194 +
 .../Connectivity/vtkbisImageTimeSeriesNormalize.h  |    84 +
 .../Connectivity/vtkbisIntrinsicConnMap.cpp        |  1524 ++
 .../Connectivity/vtkbisIntrinsicConnMap.h          |   142 +
 .../Connectivity/vtkbisIpsilateralConnMap.cpp      |  2780 ++
 .../Connectivity/vtkbisIpsilateralConnMap.h        |   161 +
 .../Connectivity/vtkbisMedianTemporalSmoothing.cpp |   207 +
 .../Connectivity/vtkbisMedianTemporalSmoothing.h   |   100 +
 .../Connectivity/vtkbisROICorrelation.cpp          |   212 +
 .../Connectivity/vtkbisROICorrelation.h            |    94 +
 bioimagesuite30_src/Connectivity/vtkbisROIMean.cpp |   362 +
 bioimagesuite30_src/Connectivity/vtkbisROIMean.h   |   113 +
 .../Connectivity/vtkbisROIMean_rt.cpp              |   327 +
 .../Connectivity/vtkbisROIMean_rt.h                |   114 +
 .../vtkbisRemoveGlobalTemporalDrift.cpp            |   218 +
 .../Connectivity/vtkbisRemoveGlobalTemporalDrift.h |    79 +
 .../Connectivity/vtkbisRemoveSliceMean.cpp         |   256 +
 .../Connectivity/vtkbisRemoveSliceMean.h           |    76 +
 .../Connectivity/vtkbisRemoveTemporalDrift.cpp     |   309 +
 .../Connectivity/vtkbisRemoveTemporalDrift.h       |   104 +
 .../Connectivity/vtkbisRemoveVolumeMean.cpp        |   234 +
 .../Connectivity/vtkbisRemoveVolumeMean.h          |    76 +
 .../vtkbisTaskBasedSeedCorrelation.cpp             |   471 +
 .../Connectivity/vtkbisTaskBasedSeedCorrelation.h  |   108 +
 .../Connectivity/vtkbisTimeSeriesCorrelation.cpp   |   356 +
 .../Connectivity/vtkbisTimeSeriesCorrelation.h     |   104 +
 .../Connectivity/vtkbisTimeSeriesMean.cpp          |    94 +
 .../Connectivity/vtkbisTimeSeriesMean.h            |    69 +
 .../Connectivity/vtkbisTimeSeriesStat.cpp          |   129 +
 .../Connectivity/vtkbisTimeSeriesStat.h            |    78 +
 .../Connectivity/vtkbisfmriToolBox.cpp             |  1072 +
 .../Connectivity/vtkbisfmriToolBox.h               |   139 +
 .../Connectivity/vtkbisfmriToolBoxOptimize.cpp     |  1280 +
 .../Connectivity/vtkbisfmriToolBoxOptimize.h       |   143 +
 .../DemonsRegistration/CMakeLists.txt              |   175 +
 .../DemonsRegistration/DeformableRegistration.cxx  |   613 +
 .../DemonsRegistration/OtherFunctions.cxx          |   358 +
 .../DemonsRegistration/OtherFunctions.h            |    46 +
 .../DemonsRegistration/firstExtendedDemon.h        |   391 +
 .../firstExtendedSymmetricDemon.h                  |   393 +
 .../itkBinaryMorphologicalClosingImageFilter.h     |   159 +
 .../itkBinaryMorphologicalClosingImageFilter.txx   |   247 +
 .../itkjwsDemonsRegistrationFilter.h               |   183 +
 .../itkjwsDemonsRegistrationFilter.txx             |   248 +
 .../itkjwsDemonsRegistrationFunction.h             |   301 +
 .../itkjwsDemonsRegistrationFunction.txx           |   343 +
 .../itkjwsDenseFiniteDifferenceImageFilter.h       |   234 +
 .../itkjwsDenseFiniteDifferenceImageFilter.txx     |   342 +
 ...tkjwsMultiResolutionPDEDeformableRegistration.h |   293 +
 ...jwsMultiResolutionPDEDeformableRegistration.txx |   533 +
 .../itkjwsPDEDeformableRegistrationFilter.h        |   326 +
 .../itkjwsPDEDeformableRegistrationFilter.txx      |   574 +
 .../itkjwsPDEDeformableRegistrationFunction.h      |   171 +
 ...itkjwsSymmetricForcesDemonsRegistrationFilter.h |   184 +
 ...kjwsSymmetricForcesDemonsRegistrationFilter.txx |   270 +
 ...kjwsSymmetricForcesDemonsRegistrationFunction.h |   265 +
 ...wsSymmetricForcesDemonsRegistrationFunction.txx |   386 +
 .../jwsForRewritingPreprocess.cpp                  |   145 +
 .../DemonsRegistration/jwsNewMain.cxx              |   270 +
 .../DemonsRegistration/jwsReadWriteImages.cpp      |   284 +
 .../DemonsRegistration/jwsReadWriteImages.h        |    88 +
 .../DemonsRegistration/jwsReadWriteImagesTest.cpp  |    46 +
 .../DemonsRegistration/jwsSymmetricNewMain.cxx     |   270 +
 .../DemonsRegistration/secondExtendedDemon.h       |   742 +
 .../secondExtendedSymmetricDemon.h                 |   743 +
 .../DemonsRegistration/thirdDemon.h                |   437 +
 .../DemonsRegistration/thirdSymmetricDemon.h       |   438 +
 .../vtkjwsSymmetricDemonsRegistration.cpp          |   482 +
 .../vtkjwsSymmetricDemonsRegistration.h            |   134 +
 bioimagesuite30_src/DemonsRegistration/wook.h      |   148 +
 bioimagesuite30_src/GUI/CMakeLists.txt             |   178 +
 bioimagesuite30_src/GUI/pxtkanaheadercontrol.cpp   |   393 +
 bioimagesuite30_src/GUI/pxtkanaheadercontrol.h     |   114 +
 bioimagesuite30_src/GUI/pxvtkgadgets.cpp           |   313 +
 bioimagesuite30_src/GUI/pxvtkgadgets.h             |   154 +
 bioimagesuite30_src/GUI/pxvtktkdialog.cpp          |    71 +
 bioimagesuite30_src/GUI/pxvtktkdialog.h            |    90 +
 .../GUI/vtkbisGUINIFTIHeaderEditor.cpp             |   955 +
 .../GUI/vtkbisGUINIFTIHeaderEditor.h               |   150 +
 bioimagesuite30_src/GUI/vtkpxGUI2DImageEditor.cpp  |   130 +
 bioimagesuite30_src/GUI/vtkpxGUI2DImageEditor.h    |    99 +
 bioimagesuite30_src/GUI/vtkpxGUI2DImageViewer.cpp  |  1088 +
 bioimagesuite30_src/GUI/vtkpxGUI2DImageViewer.h    |   219 +
 .../GUI/vtkpxGUI2DSplineObjectmapViewer.cpp        |   599 +
 .../GUI/vtkpxGUI2DSplineObjectmapViewer.h          |   174 +
 bioimagesuite30_src/GUI/vtkpxGUI4DRenderer.cpp     |   262 +
 bioimagesuite30_src/GUI/vtkpxGUI4DRenderer.h       |   121 +
 .../GUI/vtkpxGUI4DSplineStackControl.cpp           |  1963 ++
 .../GUI/vtkpxGUI4DSplineStackControl.h             |   244 +
 .../GUI/vtkpxGUI4DTriangulatedStackControl.cpp     |   738 +
 .../GUI/vtkpxGUI4DTriangulatedStackControl.h       |   175 +
 .../GUI/vtkpxGUIAbstractMultisliceEditor.cpp       |  1321 +
 .../GUI/vtkpxGUIAbstractMultisliceEditor.h         |   238 +
 .../GUI/vtkpxGUIAnalyzeHeaderEditor.cpp            |   536 +
 .../GUI/vtkpxGUIAnalyzeHeaderEditor.h              |   121 +
 .../GUI/vtkpxGUIBaseCurveControl.cpp               |  2835 ++
 bioimagesuite30_src/GUI/vtkpxGUIBaseCurveControl.h |   218 +
 .../GUI/vtkpxGUIBaseCurveEditor.cpp                |    47 +
 bioimagesuite30_src/GUI/vtkpxGUIBaseCurveEditor.h  |   122 +
 .../GUI/vtkpxGUIBaseImageViewer.cpp                |  1015 +
 bioimagesuite30_src/GUI/vtkpxGUIBaseImageViewer.h  |   302 +
 bioimagesuite30_src/GUI/vtkpxGUIBaseRenderer.cpp   |    43 +
 bioimagesuite30_src/GUI/vtkpxGUIBaseRenderer.h     |    70 +
 bioimagesuite30_src/GUI/vtkpxGUICallback.cpp       |    76 +
 bioimagesuite30_src/GUI/vtkpxGUICallback.h         |    91 +
 bioimagesuite30_src/GUI/vtkpxGUIColormapEditor.cpp |  1904 ++
 bioimagesuite30_src/GUI/vtkpxGUIColormapEditor.h   |   196 +
 bioimagesuite30_src/GUI/vtkpxGUIComponent.cpp      |   377 +
 bioimagesuite30_src/GUI/vtkpxGUIComponent.h        |   143 +
 .../GUI/vtkpxGUIContourStackEditor.cpp             |  1027 +
 .../GUI/vtkpxGUIContourStackEditor.h               |   135 +
 .../GUI/vtkpxGUICurveImageEditor.cpp               |   380 +
 bioimagesuite30_src/GUI/vtkpxGUICurveImageEditor.h |    97 +
 bioimagesuite30_src/GUI/vtkpxGUIFemPostControl.cpp |   980 +
 bioimagesuite30_src/GUI/vtkpxGUIFemPostControl.h   |   188 +
 bioimagesuite30_src/GUI/vtkpxGUIMosaicViewer.cpp   |  1800 ++
 bioimagesuite30_src/GUI/vtkpxGUIMosaicViewer.h     |   220 +
 .../GUI/vtkpxGUIMultipleMosaicViewer.cpp           |   451 +
 .../GUI/vtkpxGUIMultipleMosaicViewer.h             |   100 +
 .../GUI/vtkpxGUIObjectmapMosaicEditor.cpp          |   125 +
 .../GUI/vtkpxGUIObjectmapMosaicEditor.h            |    99 +
 .../GUI/vtkpxGUIObjectmapMosaicViewer.cpp          |   402 +
 .../GUI/vtkpxGUIObjectmapMosaicViewer.h            |   155 +
 .../GUI/vtkpxGUIObjectmapOrthogonalEditor.cpp      |   126 +
 .../GUI/vtkpxGUIObjectmapOrthogonalEditor.h        |   100 +
 .../GUI/vtkpxGUIObjectmapOrthogonalViewer.cpp      |   829 +
 .../GUI/vtkpxGUIObjectmapOrthogonalViewer.h        |   182 +
 .../GUI/vtkpxGUIObjectmapSplineControl.cpp         |  1116 +
 .../GUI/vtkpxGUIObjectmapSplineControl.h           |   300 +
 .../GUI/vtkpxGUIObjectmapSplineStackControl.cpp    |  1035 +
 .../GUI/vtkpxGUIObjectmapSplineStackControl.h      |   192 +
 .../GUI/vtkpxGUIObliqueImageSliceControl.cpp       |   624 +
 .../GUI/vtkpxGUIObliqueImageSliceControl.h         |   135 +
 .../GUI/vtkpxGUIOrthogonal4DViewer.cpp             |  1063 +
 .../GUI/vtkpxGUIOrthogonal4DViewer.h               |   173 +
 .../GUI/vtkpxGUIOrthogonalViewer.cpp               |  3260 +++
 bioimagesuite30_src/GUI/vtkpxGUIOrthogonalViewer.h |   389 +
 .../GUI/vtkpxGUIPolyDataControl.cpp                |  2579 ++
 bioimagesuite30_src/GUI/vtkpxGUIPolyDataControl.h  |   262 +
 bioimagesuite30_src/GUI/vtkpxGUIRenderer.cpp       |  3120 +++
 bioimagesuite30_src/GUI/vtkpxGUIRenderer.h         |   284 +
 bioimagesuite30_src/GUI/vtkpxGUISplineControl.cpp  |  1616 ++
 bioimagesuite30_src/GUI/vtkpxGUISplineControl.h    |   324 +
 bioimagesuite30_src/GUI/vtkpxGUISplineEditor.cpp   |   320 +
 bioimagesuite30_src/GUI/vtkpxGUISplineEditor.h     |   174 +
 .../GUI/vtkpxGUISplineStackControl.cpp             |  1047 +
 .../GUI/vtkpxGUISplineStackControl.h               |   242 +
 .../GUI/vtkpxGUITriangulatedStackControl.cpp       |   613 +
 .../GUI/vtkpxGUITriangulatedStackControl.h         |   199 +
 bioimagesuite30_src/GUI/vtkpxGUIVolumeControl.cpp  |   865 +
 bioimagesuite30_src/GUI/vtkpxGUIVolumeControl.h    |   174 +
 .../GUI/vtkpxTalairachTransform.cpp                |  1289 +
 bioimagesuite30_src/GUI/vtkpxTalairachTransform.h  |   256 +
 .../GUI/vtkpxTalairachTransformHelper.cpp          |   167 +
 .../GUI/vtkpxTalairachTransformHelper.h            |   101 +
 bioimagesuite30_src/GUI/vtkpxtkGUIlib.cpp          |    62 +
 bioimagesuite30_src/Graphics/CMakeLists.txt        |   124 +
 .../vtkCropVolumeRayCastCompositeGOHelper.cxx      |  1393 +
 .../vtkCropVolumeRayCastCompositeGOHelper.h        |    89 +
 .../vtkCropVolumeRayCastCompositeGOShadeHelper.cxx |  1482 +
 .../vtkCropVolumeRayCastCompositeGOShadeHelper.h   |    88 +
 .../vtkCropVolumeRayCastCompositeHelper.cxx        |  1321 +
 .../Graphics/vtkCropVolumeRayCastCompositeHelper.h |    90 +
 .../vtkCropVolumeRayCastCompositeShadeHelper.cxx   |  1482 +
 .../vtkCropVolumeRayCastCompositeShadeHelper.h     |    88 +
 .../Graphics/vtkCropVolumeRayCastMapper.cxx        |  3719 +++
 .../Graphics/vtkCropVolumeRayCastMapper.h          |   825 +
 bioimagesuite30_src/Graphics/vtkEllipseSource.cxx  |   370 +
 bioimagesuite30_src/Graphics/vtkEllipseSource.h    |   164 +
 bioimagesuite30_src/Graphics/vtkpx2DImageSlice.cpp |   400 +
 bioimagesuite30_src/Graphics/vtkpx2DImageSlice.h   |   153 +
 .../vtkpxAddDisplacementVectorToPolyData.cpp       |   159 +
 .../vtkpxAddDisplacementVectorToPolyData.h         |   104 +
 .../Graphics/vtkpxAppendAndLabelPolyData.cpp       |   785 +
 .../Graphics/vtkpxAppendAndLabelPolyData.h         |   156 +
 bioimagesuite30_src/Graphics/vtkpxCameraInfo.cpp   |   270 +
 bioimagesuite30_src/Graphics/vtkpxCameraInfo.h     |   122 +
 bioimagesuite30_src/Graphics/vtkpxColorMapUtil.cpp |  1347 +
 bioimagesuite30_src/Graphics/vtkpxColorMapUtil.h   |   159 +
 .../Graphics/vtkpxCurveEditUtil.cpp                |   257 +
 bioimagesuite30_src/Graphics/vtkpxCurveEditUtil.h  |   103 +
 .../Graphics/vtkpxElectrodeGridSource.cpp          |   865 +
 .../Graphics/vtkpxElectrodeGridSource.h            |   267 +
 .../Graphics/vtkpxElectrodeGridToSurfaceFilter.cpp |   561 +
 .../Graphics/vtkpxElectrodeGridToSurfaceFilter.h   |   192 +
 .../Graphics/vtkpxElectrodeMultiGridSource.cpp     |   659 +
 .../Graphics/vtkpxElectrodeMultiGridSource.h       |   203 +
 .../Graphics/vtkpxElectrodeSource.cpp              |   657 +
 .../Graphics/vtkpxElectrodeSource.h                |   270 +
 .../Graphics/vtkpxEnclosedPipeline.cpp             |   117 +
 .../Graphics/vtkpxEnclosedPipeline.h               |   109 +
 bioimagesuite30_src/Graphics/vtkpxImageSlice.cpp   |   761 +
 bioimagesuite30_src/Graphics/vtkpxImageSlice.h     |   176 +
 .../Graphics/vtkpxMapActivationToPolyData.cpp      |   376 +
 .../Graphics/vtkpxMapActivationToPolyData.h        |   170 +
 .../Graphics/vtkpxNormalShrinkPolyData.cpp         |   146 +
 .../Graphics/vtkpxNormalShrinkPolyData.h           |   116 +
 .../Graphics/vtkpxObliqueImageSlice.cpp            |   900 +
 .../Graphics/vtkpxObliqueImageSlice.h              |   211 +
 .../Graphics/vtkpxOrthoImageSlice.cpp              |   333 +
 .../Graphics/vtkpxOrthoImageSlice.h                |   151 +
 .../Graphics/vtkpxPredictElectrodeStrip.cpp        |   197 +
 .../Graphics/vtkpxPredictElectrodeStrip.h          |   142 +
 bioimagesuite30_src/Graphics/vtkpxSurfaceUtil.cpp  |  1596 ++
 bioimagesuite30_src/Graphics/vtkpxSurfaceUtil.h    |   173 +
 bioimagesuite30_src/Graphics/vtkpxVolume.cpp       |  1284 +
 bioimagesuite30_src/Graphics/vtkpxVolume.h         |   316 +
 bioimagesuite30_src/Imaging/CMakeLists.txt         |   246 +
 bioimagesuite30_src/Imaging/vtkbisComputeGLM.cpp   |   675 +
 bioimagesuite30_src/Imaging/vtkbisComputeGLM.h     |   148 +
 .../Imaging/vtkbisCudaConvolution.cpp              |   253 +
 .../Imaging/vtkbisCudaConvolution.h                |    65 +
 .../Imaging/vtkbisCudaEdgeDetect.cpp               |   132 +
 bioimagesuite30_src/Imaging/vtkbisCudaEdgeDetect.h |    57 +
 bioimagesuite30_src/Imaging/vtkbisCudaFFT.cpp      |   147 +
 bioimagesuite30_src/Imaging/vtkbisCudaFFT.h        |    62 +
 bioimagesuite30_src/Imaging/vtkbisCudaHessian.cpp  |   196 +
 bioimagesuite30_src/Imaging/vtkbisCudaHessian.h    |    62 +
 bioimagesuite30_src/Imaging/vtkbisCudaRFFT.cpp     |   143 +
 bioimagesuite30_src/Imaging/vtkbisCudaRFFT.h       |    63 +
 bioimagesuite30_src/Imaging/vtkbisFDR.cpp          |   223 +
 bioimagesuite30_src/Imaging/vtkbisFDR.h            |    73 +
 .../Imaging/vtkbisImageAverageComponents.cpp       |   151 +
 .../Imaging/vtkbisImageAverageComponents.h         |    76 +
 bioimagesuite30_src/Imaging/vtkbisImageUtil.cpp    |    73 +
 bioimagesuite30_src/Imaging/vtkbisImageUtil.h      |    57 +
 .../Imaging/vtkbisObjectmapRegularization.cpp      |   406 +
 .../Imaging/vtkbisObjectmapRegularization.h        |   114 +
 bioimagesuite30_src/Imaging/vtkbisRtoPvalue.cpp    |   139 +
 bioimagesuite30_src/Imaging/vtkbisRtoPvalue.h      |    79 +
 bioimagesuite30_src/Imaging/vtkbisRtoTmap.cpp      |   128 +
 bioimagesuite30_src/Imaging/vtkbisRtoTmap.h        |    64 +
 .../Imaging/vtkbisSiemensDWIArrange.cpp            |   134 +
 .../Imaging/vtkbisSiemensDWIArrange.h              |   105 +
 .../Imaging/vtkbisSiemensMosaicConverter.cpp       |   181 +
 .../Imaging/vtkbisSiemensMosaicConverter.h         |   112 +
 .../Imaging/vtkbisTimeSeriesNormalize.cpp          |   148 +
 .../Imaging/vtkbisTimeSeriesNormalize.h            |    86 +
 bioimagesuite30_src/Imaging/vtkbisWaver.cpp        |   615 +
 bioimagesuite30_src/Imaging/vtkbisWaver.h          |   166 +
 .../Imaging/vtkbisZscoretoPvalue.cpp               |   112 +
 bioimagesuite30_src/Imaging/vtkbisZscoretoPvalue.h |    59 +
 bioimagesuite30_src/Imaging/vtkdsSpectUtil.cpp     |   412 +
 bioimagesuite30_src/Imaging/vtkdsSpectUtil.h       |    58 +
 bioimagesuite30_src/Imaging/vtknrImageCluster.cpp  |   537 +
 bioimagesuite30_src/Imaging/vtknrImageCluster.h    |   136 +
 .../Imaging/vtkpxAddMotionToTimeSeries.cpp         |   653 +
 .../Imaging/vtkpxAddMotionToTimeSeries.h           |   177 +
 bioimagesuite30_src/Imaging/vtkpxAverageImages.cpp |   312 +
 bioimagesuite30_src/Imaging/vtkpxAverageImages.h   |   136 +
 .../Imaging/vtkpxBinaryImageMedian3D.cpp           |   367 +
 .../Imaging/vtkpxBinaryImageMedian3D.h             |   103 +
 .../Imaging/vtkpxCSIOffsetCorrection.cpp           |   655 +
 .../Imaging/vtkpxCSIOffsetCorrection.h             |   183 +
 .../Imaging/vtkpxCSIStackImages.cpp                |   308 +
 bioimagesuite30_src/Imaging/vtkpxCSIStackImages.h  |   113 +
 bioimagesuite30_src/Imaging/vtkpxComputeTmap.cpp   |   361 +
 bioimagesuite30_src/Imaging/vtkpxComputeTmap.h     |   147 +
 .../Imaging/vtkpxCreateCheckerBoardImage.cpp       |   248 +
 .../Imaging/vtkpxCreateCheckerBoardImage.h         |   117 +
 .../Imaging/vtkpxCreateSyntheticFmri.cpp           |   508 +
 .../Imaging/vtkpxCreateSyntheticFmri.h             |   155 +
 .../Imaging/vtkpxCreateThickSlices.cpp             |   187 +
 .../Imaging/vtkpxCreateThickSlices.h               |   110 +
 .../Imaging/vtkpxImageAddGaussianNoise.cpp         |   151 +
 .../Imaging/vtkpxImageAddGaussianNoise.h           |   115 +
 .../Imaging/vtkpxImageAddPhaseCorrection.cpp       |   745 +
 .../Imaging/vtkpxImageAddPhaseCorrection.h         |   158 +
 bioimagesuite30_src/Imaging/vtkpxImageAlgebra.cpp  |   314 +
 bioimagesuite30_src/Imaging/vtkpxImageAlgebra.h    |   147 +
 .../Imaging/vtkpxImageAttenuationCorrection.cpp    |   155 +
 .../Imaging/vtkpxImageAttenuationCorrection.h      |   111 +
 .../vtkpxImageComputeNormalizedDifference.cpp      |   237 +
 .../vtkpxImageComputeNormalizedDifference.h        |   128 +
 .../Imaging/vtkpxImageComputeNormalizedRatio.cpp   |   223 +
 .../Imaging/vtkpxImageComputeNormalizedRatio.h     |   122 +
 .../Imaging/vtkpxImageComputeVOIStats.cpp          |   198 +
 .../Imaging/vtkpxImageComputeVOIStats.h            |   100 +
 .../Imaging/vtkpxImageCorrectNonUniformZ.cpp       |   236 +
 .../Imaging/vtkpxImageCorrectNonUniformZ.h         |   113 +
 .../Imaging/vtkpxImageCylindricalCrop.cpp          |   118 +
 .../Imaging/vtkpxImageCylindricalCrop.h            |    98 +
 .../Imaging/vtkpxImageFeatureExtract.cpp           |   314 +
 .../Imaging/vtkpxImageFeatureExtract.h             |   132 +
 .../Imaging/vtkpxImageGaussianNoiseSource.cpp      |   223 +
 .../Imaging/vtkpxImageGaussianNoiseSource.h        |   106 +
 .../Imaging/vtkpxImageHistogramEqualization.cpp    |   191 +
 .../Imaging/vtkpxImageHistogramEqualization.h      |   103 +
 bioimagesuite30_src/Imaging/vtkpxImageIDFilter.cpp |   212 +
 bioimagesuite30_src/Imaging/vtkpxImageIDFilter.h   |   133 +
 bioimagesuite30_src/Imaging/vtkpxImageMask.cpp     |   147 +
 bioimagesuite30_src/Imaging/vtkpxImageMask.h       |    90 +
 .../Imaging/vtkpxImageNormalizeIntensity.cpp       |   250 +
 .../Imaging/vtkpxImageNormalizeIntensity.h         |   164 +
 .../vtkpxImageNormalizeIntensityToReference.cpp    |   197 +
 .../vtkpxImageNormalizeIntensityToReference.h      |   104 +
 .../Imaging/vtkpxImagePolarToEuclidean.cpp         |   209 +
 .../Imaging/vtkpxImagePolarToEuclidean.h           |   102 +
 .../Imaging/vtkpxImageRemoveLinearPhase.cpp        |   279 +
 .../Imaging/vtkpxImageRemoveLinearPhase.h          |   110 +
 .../Imaging/vtkpxImageReorientTensorOrVector.cpp   |   500 +
 .../Imaging/vtkpxImageReorientTensorOrVector.h     |   150 +
 .../Imaging/vtkpxImageSincInterpolation.cpp        |   222 +
 .../Imaging/vtkpxImageSincInterpolation.h          |    93 +
 bioimagesuite30_src/Imaging/vtkpxImageStitch.cpp   |   188 +
 bioimagesuite30_src/Imaging/vtkpxImageStitch.h     |   113 +
 .../Imaging/vtkpxImageThresholdedIntersection.cpp  |   209 +
 .../Imaging/vtkpxImageThresholdedIntersection.h    |   103 +
 .../Imaging/vtkpxImageVariableSmoothing.cpp        |   179 +
 .../Imaging/vtkpxImageVariableSmoothing.h          |   117 +
 bioimagesuite30_src/Imaging/vtkpxMaximumImages.cpp |   183 +
 bioimagesuite30_src/Imaging/vtkpxMaximumImages.h   |   102 +
 .../Imaging/vtkpxMergeFmriConventional.cpp         |   998 +
 .../Imaging/vtkpxMergeFmriConventional.h           |   237 +
 .../Imaging/vtkpxNormalizedSmoothImage.cpp         |   160 +
 .../Imaging/vtkpxNormalizedSmoothImage.h           |   104 +
 .../Imaging/vtkpxPhaseCorrectCSIData.cpp           |  1401 +
 .../Imaging/vtkpxPhaseCorrectCSIData.h             |   252 +
 bioimagesuite30_src/Imaging/vtkpxProcessFmri.cpp   |   431 +
 bioimagesuite30_src/Imaging/vtkpxProcessFmri.h     |   132 +
 .../Imaging/vtkpxProcessRawBrukerFIDImage.cpp      |  1008 +
 .../Imaging/vtkpxProcessRawBrukerFIDImage.h        |   152 +
 .../Imaging/vtkpxSimpleImageThreshold.cpp          |   107 +
 .../Imaging/vtkpxSimpleImageThreshold.h            |    93 +
 .../Imaging/vtkpxWeightedSmoothImage.cpp           |   207 +
 .../Imaging/vtkpxWeightedSmoothImage.h             |   111 +
 .../Imaging/vtkxqImageFourierConvolution.cpp       |  1958 ++
 .../Imaging/vtkxqImageFourierConvolution.h         |   179 +
 bioimagesuite30_src/Imaging/vtkxqImageHessian.cpp  |   107 +
 bioimagesuite30_src/Imaging/vtkxqImageHessian.h    |    71 +
 .../Imaging/vtkxqImageKMeansVesselnessFilter.cpp   |   442 +
 .../Imaging/vtkxqImageKMeansVesselnessFilter.h     |   104 +
 .../Imaging/vtkxqImageODFVesselnessFilter.cpp      |   167 +
 .../Imaging/vtkxqImageODFVesselnessFilter.h        |    89 +
 .../Imaging/vtkxqImageVesselEnhancement.cpp        |   415 +
 .../Imaging/vtkxqImageVesselEnhancement.h          |   152 +
 bioimagesuite30_src/Legacy/CMakeLists.txt          |    94 +
 bioimagesuite30_src/Legacy/vtkpxComputeStrains.cpp |   318 +
 bioimagesuite30_src/Legacy/vtkpxComputeStrains.h   |   122 +
 bioimagesuite30_src/Legacy/vtkpxContourSource.cpp  |   819 +
 bioimagesuite30_src/Legacy/vtkpxContourSource.h    |   160 +
 bioimagesuite30_src/Legacy/vtkpxFemSolid.cpp       |  1412 +
 bioimagesuite30_src/Legacy/vtkpxFemSolid.h         |   183 +
 bioimagesuite30_src/Legacy/vtkpxShapeTracking.cpp  |   840 +
 bioimagesuite30_src/Legacy/vtkpxShapeTracking.h    |   222 +
 bioimagesuite30_src/Legacy/vtkpxSplineSource.cpp   |   971 +
 bioimagesuite30_src/Legacy/vtkpxSplineSource.h     |   254 +
 .../Legacy/vtkpxSplineSourceUndoStack.cpp          |    60 +
 .../Legacy/vtkpxSplineSourceUndoStack.h            |    62 +
 .../Legacy/vtkpxSplineStackSource.cpp              |  1903 ++
 .../Legacy/vtkpxSplineStackSource.h                |   289 +
 .../Legacy/vtkpxTriangulatedStackSource.cpp        |   409 +
 .../Legacy/vtkpxTriangulatedStackSource.h          |   149 +
 bioimagesuite30_src/Legacy/vtkpxTstackReader.cpp   |   241 +
 bioimagesuite30_src/Legacy/vtkpxTstackReader.h     |   105 +
 bioimagesuite30_src/Registration/CMakeLists.txt    |   224 +
 .../Registration/vtkbisTransformationTestUtil.cpp  |   212 +
 .../Registration/vtkbisTransformationTestUtil.h    |    96 +
 .../Registration/vtkokKochCoefficientSource.cpp    |   439 +
 .../Registration/vtkokKochCoefficientSource.h      |   218 +
 .../vtkpxAbstractIntensityRegistration.cpp         |   662 +
 .../vtkpxAbstractIntensityRegistration.h           |   369 +
 .../Registration/vtkpxAbstractRPMRegistration.cpp  |   154 +
 .../Registration/vtkpxAbstractRPMRegistration.h    |   152 +
 .../vtkpxArticulatedJointTransform.cpp             |  1271 +
 .../Registration/vtkpxArticulatedJointTransform.h  |   327 +
 .../vtkpxBSplinePriorRPMRegistration.cpp           |   434 +
 .../vtkpxBSplinePriorRPMRegistration.h             |   113 +
 .../Registration/vtkpxBSplineRPMRegistration.cpp   |   556 +
 .../Registration/vtkpxBSplineRPMRegistration.h     |   136 +
 .../Registration/vtkpxBaseGridTransform.cpp        |   802 +
 .../Registration/vtkpxBaseGridTransform.h          |   149 +
 .../Registration/vtkpxComboTransform.cpp           |   580 +
 .../Registration/vtkpxComboTransform.h             |   227 +
 .../Registration/vtkpxDistortionCorrection.cpp     |   428 +
 .../Registration/vtkpxDistortionCorrection.h       |   184 +
 .../Registration/vtkpxGridTransform.cpp            |  1791 ++
 .../Registration/vtkpxGridTransform.h              |   337 +
 .../Registration/vtkpxJointHistogram.cpp           |  1714 ++
 .../Registration/vtkpxJointHistogram.h             |   282 +
 .../Registration/vtkpxLinearMotionCorrect.cpp      |   628 +
 .../Registration/vtkpxLinearMotionCorrect.h        |   203 +
 .../Registration/vtkpxLinearRPMRegistration.cpp    |   241 +
 .../Registration/vtkpxLinearRPMRegistration.h      |   107 +
 .../Registration/vtkpxLinearRegistration.cpp       |   686 +
 .../Registration/vtkpxLinearRegistration.h         |   314 +
 .../Registration/vtkpxLinearTransform.cpp          |   866 +
 .../Registration/vtkpxLinearTransform.h            |   182 +
 .../vtkpxMidlineSymmetricRegistration.cpp          |   118 +
 .../vtkpxMidlineSymmetricRegistration.h            |    88 +
 .../vtkpxNonLinearIntegratedRegistration.cpp       |   553 +
 .../vtkpxNonLinearIntegratedRegistration.h         |   186 +
 .../vtkpxNonLinearLabelRegistration.cpp            |   846 +
 .../Registration/vtkpxNonLinearLabelRegistration.h |   344 +
 .../Registration/vtkpxNonLinearRegistration.cpp    |   873 +
 .../Registration/vtkpxNonLinearRegistration.h      |   371 +
 .../Registration/vtkpxPolyAbstractTransform.cpp    |   516 +
 .../Registration/vtkpxPolyAbstractTransform.h      |   163 +
 .../Registration/vtkpxPolySimilarityTransform.cpp  |  1279 +
 .../Registration/vtkpxPolySimilarityTransform.h    |   227 +
 .../Registration/vtkpxRPMCorrespondenceFinder.cpp  |  1319 +
 .../Registration/vtkpxRPMCorrespondenceFinder.h    |   346 +
 .../Registration/vtkpxRegistration.cpp             |  2134 ++
 .../Registration/vtkpxRegistration.h               |   224 +
 .../Registration/vtkpxSimilarityTransform.cpp      |  1061 +
 .../Registration/vtkpxSimilarityTransform.h        |   185 +
 .../Registration/vtkpxSparseMatrix.cpp             |   466 +
 .../Registration/vtkpxSparseMatrix.h               |   172 +
 .../Registration/vtkpxTPSRPMRegistration.cpp       |   388 +
 .../Registration/vtkpxTPSRPMRegistration.h         |   110 +
 .../Registration/vtkpxTransformationUtil.cpp       |  1169 +
 .../Registration/vtkpxTransformationUtil.h         |   170 +
 .../vtkpxWeightedLandmarkTransform.cpp             |   399 +
 .../Registration/vtkpxWeightedLandmarkTransform.h  |    78 +
 bioimagesuite30_src/Segmentation/CMakeLists.txt    |   169 +
 .../Segmentation/itkBinaryThinningImageFilter3D.h  |   185 +
 .../itkBinaryThinningImageFilter3D.txx             |  1000 +
 .../Segmentation/itkImageToVTKImageFilter.h        |   131 +
 .../Segmentation/itkImageToVTKImageFilter.txx      |   172 +
 .../Segmentation/itkVTKImageToImageFilter.h        |   133 +
 .../Segmentation/itkVTKImageToImageFilter.txx      |   172 +
 .../Segmentation/itkpxLevelSetCallback.h           |   133 +
 .../Segmentation/itkpxSaturateImageFilter.h        |   166 +
 .../Segmentation/itkpxSaturateImageFilter.txx      |   161 +
 ...tkpxTissueSegmentationCoupledLevelSetFunction.h |   356 +
 ...pxTissueSegmentationCoupledLevelSetFunction.txx |   420 +
 ...xTissueSegmentationCoupledLevelSetImageFilter.h |   281 +
 ...issueSegmentationCoupledLevelSetImageFilter.txx |    80 +
 .../itkpxTissueSegmentationLevelSetFunction.h      |   385 +
 .../itkpxTissueSegmentationLevelSetFunction.txx    |   378 +
 .../itkpxTissueSegmentationLevelSetImageFilter.h   |   278 +
 .../itkpxTissueSegmentationLevelSetImageFilter.txx |   179 +
 bioimagesuite30_src/Segmentation/vtkITKMyUtility.h |    54 +
 bioimagesuite30_src/Segmentation/vtkITKUtility.h   |   137 +
 .../Segmentation/vtkbisBinaryThinningFilter.cpp    |   168 +
 .../Segmentation/vtkbisBinaryThinningFilter.h      |    92 +
 .../Segmentation/vtkjoBETHistogram.cpp             |   336 +
 .../Segmentation/vtkjoBETHistogram.h               |   126 +
 .../Segmentation/vtkjoBETImageFilter.cpp           |   773 +
 .../Segmentation/vtkjoBETImageFilter.h             |   272 +
 .../vtkjoPolyDataRobustBETTraining.cpp             |   629 +
 .../Segmentation/vtkjoPolyDataRobustBETTraining.h  |   138 +
 .../Segmentation/vtkjoScalePolyData.cpp            |   196 +
 .../Segmentation/vtkjoScalePolyData.h              |   100 +
 ...tkjwsSignedDanielssonDistanceMapImageFilter.cpp |   204 +
 .../vtkjwsSignedDanielssonDistanceMapImageFilter.h |   122 +
 .../vtkpxAbstractBiasFieldCorrection.cpp           |  1042 +
 .../vtkpxAbstractBiasFieldCorrection.h             |   381 +
 .../Segmentation/vtkpxBaseLevelSetFilter.cpp       |   143 +
 .../Segmentation/vtkpxBaseLevelSetFilter.h         |   188 +
 .../Segmentation/vtkpxBrainPreSegment.cpp          |   557 +
 .../Segmentation/vtkpxBrainPreSegment.h            |   138 +
 .../vtkpxCoupledTissueLevelSetFilter.cpp           |   421 +
 .../vtkpxCoupledTissueLevelSetFilter.h             |   154 +
 .../Segmentation/vtkpxExponentialFitT1.cpp         |   676 +
 .../Segmentation/vtkpxExponentialFitT1.h           |   169 +
 .../Segmentation/vtkpxHistogramSegmentation.cpp    |   910 +
 .../Segmentation/vtkpxHistogramSegmentation.h      |   257 +
 .../Segmentation/vtkpxImageRobustHistogram.cpp     |   453 +
 .../Segmentation/vtkpxImageRobustHistogram.h       |   200 +
 .../Segmentation/vtkpxImageTensorSpline.cpp        |   879 +
 .../Segmentation/vtkpxImageTensorSpline.h          |   218 +
 .../Segmentation/vtkpxLevelSetUtil.cpp             |   382 +
 .../Segmentation/vtkpxLevelSetUtil.h               |   104 +
 .../Segmentation/vtkpxLogExponentialFit.cpp        |   313 +
 .../Segmentation/vtkpxLogExponentialFit.h          |   135 +
 .../Segmentation/vtkpxMRFSegmentation.cpp          |  1521 ++
 .../Segmentation/vtkpxMRFSegmentation.h            |   351 +
 .../vtkpxPolynomialBiasFieldCorrection.cpp         |   855 +
 .../vtkpxPolynomialBiasFieldCorrection.h           |   246 +
 .../Segmentation/vtkpxSliceBiasFieldCorrection.cpp |   659 +
 .../Segmentation/vtkpxSliceBiasFieldCorrection.h   |   151 +
 .../Segmentation/vtkpxTissueLevelSetFilter.cpp     |   362 +
 .../Segmentation/vtkpxTissueLevelSetFilter.h       |   156 +
 bioimagesuite30_src/Testing/CMakeLists.txt         |   131 +
 bioimagesuite30_src/Testing/Test_vnlmatrix.cpp     |   126 +
 bioimagesuite30_src/Testing/Test_vtkpxMatrix.cpp   |   645 +
 .../Testing/Test_vtkpxOptimizer.cpp                |    67 +
 bioimagesuite30_src/Testing/bisVersionTest.cpp     |   128 +
 bioimagesuite30_src/Testing/bisruntests.bat.in     |    87 +
 bioimagesuite30_src/Testing/bisruntests.sh.in      |    89 +
 bioimagesuite30_src/Testing/test.h                 |    34 +
 bioimagesuite30_src/Utilities/CMakeLists.txt       |    53 +
 .../Utilities/Doxygen/CMakeLists.txt               |    62 +
 .../Utilities/Doxygen/doc_class2example.pl         |   846 +
 .../Utilities/Doxygen/doc_cleanhtml.pl             |   113 +
 .../Utilities/Doxygen/doc_codematch.pl             |   565 +
 .../Utilities/Doxygen/doc_contributors.pl          |  1052 +
 .../Utilities/Doxygen/doc_header2doxygen.pl        |   555 +
 bioimagesuite30_src/Utilities/Doxygen/doc_index.pl |   670 +
 .../Utilities/Doxygen/doc_makeall.in               |     6 +
 .../Utilities/Doxygen/doc_readme.txt               |   358 +
 .../Utilities/Doxygen/doc_rmpath.pl                |   111 +
 .../Utilities/Doxygen/doc_version.pl               |   192 +
 bioimagesuite30_src/Utilities/Doxygen/doxyfile.in  |   165 +
 bioimagesuite30_src/Utilities/Doxygen/doxygen.css  |   196 +
 bioimagesuite30_src/Utilities/Doxygen/footer.html  |     5 +
 bioimagesuite30_src/Utilities/Doxygen/header.html  |     9 +
 bioimagesuite30_src/bioimagesuite/CMakeLists.txt   |    55 +
 .../bioimagesuite/apps/CMakeLists.txt              |    85 +
 .../bioimagesuite/apps/bisclient.tcl               |    81 +
 .../bioimagesuite/apps/biscomputecorrelations.tcl  |   226 +
 .../bioimagesuite/apps/bisserver.tcl               |   184 +
 .../bioimagesuite/apps/pkgIndex.tcl                |    46 +
 .../bioimagesuite/apps/pxappscommon.tcl            |   204 +
 .../bioimagesuite/apps/pxcomputeaverage.tcl        |   127 +
 .../bioimagesuite/apps/pxmat_biasfield.tcl         |   263 +
 .../apps/pxmat_computeaveragebrain.tcl             |   482 +
 .../bioimagesuite/apps/pxmat_computedistance.tcl   |    98 +
 .../bioimagesuite/apps/pxmat_computeoverlap.tcl    |   380 +
 .../bioimagesuite/apps/pxmat_computesimilarity.tcl |   157 +
 .../bioimagesuite/apps/pxmat_computestrains.tcl    |    86 +
 .../bioimagesuite/apps/pxmat_create4dimage.tcl     |    81 +
 .../bioimagesuite/apps/pxmat_displacementfield.tcl |   119 +
 .../apps/pxmat_distortioncorrection.tcl            |   218 +
 .../bioimagesuite/apps/pxmat_fastpostprocess.tcl   |   125 +
 .../bioimagesuite/apps/pxmat_flip.tcl              |   113 +
 .../bioimagesuite/apps/pxmat_headerinfo.tcl        |    80 +
 .../apps/pxmat_integratedregistration.tcl          |   218 +
 .../bioimagesuite/apps/pxmat_inverttransform.tcl   |   165 +
 .../bioimagesuite/apps/pxmat_pointregister.tcl     |   386 +
 .../bioimagesuite/apps/pxmat_register.tcl          |   377 +
 .../bioimagesuite/apps/pxmat_reorient_tensor.tcl   |   168 +
 .../bioimagesuite/apps/pxmat_reorientimage.tcl     |   105 +
 .../bioimagesuite/apps/pxmat_resampleimage.tcl     |   117 +
 .../bioimagesuite/apps/pxmat_reslicect.tcl         |   108 +
 .../bioimagesuite/apps/pxmat_resliceimage.tcl      |   145 +
 .../bioimagesuite/apps/pxmat_segment.tcl           |   173 +
 .../bioimagesuite/apps/pxmat_smoothimage.tcl       |    98 +
 .../bioimagesuite/apps/pxmat_split4dimage.tcl      |   114 +
 .../bioimagesuite/apps/pxmat_surfaceinfo.tcl       |   107 +
 .../bioimagesuite/apps/pxmat_thresholdimage.tcl    |    94 +
 .../bioimagesuite/apps/pxmultijacobian.tcl         |   258 +
 .../bioimagesuite/apps/pxmultiregister_int.tcl     |   838 +
 .../bioimagesuite/apps/pxmultisegment.tcl          |   225 +
 .../bioimagesuite/apps/pxpairwiseregister.tcl      |   290 +
 .../bioimagesuite/apps/pxroitoroi.tcl              |   161 +
 .../bioimagesuite/apps/pxsinglejacobian.tcl        |   254 +
 .../bioimagesuite/apps/pxtonifti.tcl               |    74 +
 .../bioimagesuite/base/CMakeLists.txt              |    68 +
 .../bioimagesuite/base/VisTree3.tcl                |   901 +
 .../bioimagesuite/base/biscmdline.tcl              |   950 +
 .../bioimagesuite/base/feedbackplus.tcl            |   128 +
 .../bioimagesuite/base/labelframe.tcl              |    51 +
 .../bioimagesuite/base/pkgIndex.tcl                |    73 +
 .../bioimagesuite/base/pxitclcamera.tcl            |   448 +
 .../base/pxitclelectrodemultigrid.tcl              |   378 +
 .../bioimagesuite/base/pxitclimage.tcl             |  1847 ++
 .../bioimagesuite/base/pxitcllandmarks.tcl         |   414 +
 .../bioimagesuite/base/pxitclmesh.tcl              |   565 +
 .../bioimagesuite/base/pxitclobject.tcl            |   731 +
 .../bioimagesuite/base/pxitclsurface.tcl           |   515 +
 .../bioimagesuite/base/pxitcltransform.tcl         |   539 +
 .../bioimagesuite/base/pxtclhelp.tcl               |   102 +
 .../bioimagesuite/base/pxtclreadsprheader.tcl      |   201 +
 .../bioimagesuite/base/pxtclreadvarianheader.tcl   |   239 +
 .../bioimagesuite/base/pxtclruncommand.tcl         |   200 +
 .../bioimagesuite/base/pxtcluserprefs.tcl          |   483 +
 .../bioimagesuite/base/pxtclutil.tcl               |   720 +
 .../bioimagesuite/base/pxvtable.tcl                |   228 +
 .../bioimagesuite/base/vtkImageInclude.tcl         |    65 +
 .../bioimagesuite/base/vtknrcontrib.tcl            |    41 +
 .../bioimagesuite/base/vtkpxcontrib.tcl            |   537 +
 .../bioimagesuite/bis_algorithm/CMakeLists.txt     |   335 +
 .../bioimagesuite/bis_algorithm/bis_ISAS.tcl       |   136 +
 .../bioimagesuite/bis_algorithm/bis_ISASHN.tcl     |   130 +
 .../bioimagesuite/bis_algorithm/bis_algorithm.tcl  |  2877 ++
 .../bis_algorithm/bis_algorithmdbaseinterface.tcl  |   500 +
 .../bis_algorithm/bis_basealgorithm.tcl            |  1389 +
 .../bis_algorithm/bis_basecontrolhelper.tcl        |    67 +
 .../bis_baseintensityregistration.tcl              |   500 +
 .../bis_algorithm/bis_baselevelset.tcl             |   259 +
 .../bis_basepointbasedregistration.tcl             |   415 +
 .../bis_algorithm/bis_basethresholdimage.tcl       |   166 +
 .../bioimagesuite/bis_algorithm/bis_biasfield.tcl  |   375 +
 .../bioimagesuite/bis_algorithm/bis_blendimage.tcl |   206 +
 .../bioimagesuite/bis_algorithm/bis_castimage.tcl  |   148 +
 .../bis_algorithm/bis_checkerboardimage.tcl        |   150 +
 .../bis_algorithm/bis_cleansurface.tcl             |   167 +
 .../bis_algorithm/bis_clipsurface.tcl              |   146 +
 .../bis_algorithm/bis_clusterthresholdimage.tcl    |   261 +
 .../bis_algorithm/bis_colorblendimage.tcl          |   252 +
 .../bis_algorithm/bis_combineframes.tcl            |   164 +
 .../bis_algorithm/bis_combineimages.tcl            |   166 +
 .../bis_algorithm/bis_combinetransformations.tcl   |   309 +
 .../bioimagesuite/bis_algorithm/bis_common.tcl     |    84 +
 .../bis_algorithm/bis_computecorrelations.tcl      |   306 +
 .../bis_algorithm/bis_computedisplacementfield.tcl |   151 +
 .../bioimagesuite/bis_algorithm/bis_computeglm.tcl |   180 +
 .../bis_algorithm/bis_computejointhistogram.tcl    |   198 +
 .../bis_algorithm/bis_computenormals.tcl           |   142 +
 .../bis_algorithm/bis_computeoverlap.tcl           |   533 +
 .../bis_algorithm/bis_computesimilarity.tcl        |   323 +
 .../bis_algorithm/bis_computetensor.tcl            |   284 +
 .../bioimagesuite/bis_algorithm/bis_connect.tcl    |   141 +
 .../bis_algorithm/bis_convolveimage.tcl            |   179 +
 .../bis_algorithm/bis_create4dimage.tcl            |   140 +
 .../bis_algorithm/bis_createoverlayimage.tcl       |   502 +
 .../bioimagesuite/bis_algorithm/bis_cropimage.tcl  |   402 +
 .../bis_algorithm/bis_csfwmmotioncorr.tcl          |   181 +
 .../bioimagesuite/bis_algorithm/bis_curvatures.tcl |   131 +
 .../bis_algorithm/bis_cylindricalcropimage.tcl     |   154 +
 .../bis_algorithm/bis_datamanager.tcl              |  1748 ++
 .../bioimagesuite/bis_algorithm/bis_decimate.tcl   |   143 +
 .../bioimagesuite/bis_algorithm/bis_delaunay3D.tcl |   141 +
 .../bis_algorithm/bis_dicom2nifti.tcl              |   326 +
 .../bis_algorithm/bis_displayroimean.tcl           |   166 +
 .../bis_algorithm/bis_distancemapimage.tcl         |   138 +
 .../bis_algorithm/bis_dualimagealgorithm.tcl       |   202 +
 ...bis_dualimagereslicetransformationalgorithm.tcl |   119 +
 .../bis_dualimagetransformationalgorithm.tcl       |   243 +
 .../bis_algorithm/bis_edgedetectimage.tcl          |   180 +
 .../bis_algorithm/bis_electrodeeditor.tcl          |  1926 ++
 .../bis_algorithm/bis_exponentialfitimage.tcl      |   217 +
 .../bis_algorithm/bis_exponentialfitt1.tcl         |   217 +
 .../bis_algorithm/bis_extractobjectmap.tcl         |   139 +
 .../bis_algorithm/bis_extractsurface.tcl           |   203 +
 .../bioimagesuite/bis_algorithm/bis_fdr.tcl        |   276 +
 .../bioimagesuite/bis_algorithm/bis_fftimage.tcl   |   141 +
 .../bioimagesuite/bis_algorithm/bis_flipimage.tcl  |   141 +
 .../bis_algorithm/bis_fmritoolbox.tcl              |   221 +
 .../bis_algorithm/bis_frangivesselness.tcl         |   372 +
 .../bioimagesuite/bis_algorithm/bis_graphvis.tcl   |   432 +
 .../bis_algorithm/bis_guicompareutility.tcl        |   296 +
 .../bis_algorithm/bis_guicontainer.tcl             |   284 +
 .../bis_algorithm/bis_guiimageutility.tcl          |   248 +
 .../bis_algorithm/bis_guioverlayutility.tcl        |   655 +
 .../bis_algorithm/bis_guirpmcontainer.tcl          |   274 +
 .../bis_algorithm/bis_guisurfacecontrol.tcl        |   440 +
 .../bis_algorithm/bis_guisurfaceutility.tcl        |   185 +
 .../bis_algorithm/bis_guitreecreate4d.tcl          |   135 +
 .../bis_algorithm/bis_guitreeimageutility.tcl      |   205 +
 .../bioimagesuite/bis_algorithm/bis_headerinfo.tcl |   148 +
 .../bioimagesuite/bis_algorithm/bis_help.tcl       |   495 +
 .../bis_imageandsurfacetosurfacealgorithm.tcl      |   198 +
 .../bis_algorithm/bis_imagecompare.tcl             |   177 +
 .../bis_algorithm/bis_imagedilate.tcl              |   154 +
 .../bis_imagelisttoimagealgorithm.tcl              |   171 +
 .../bis_algorithm/bis_imagemathoperations.tcl      |   220 +
 .../bis_algorithm/bis_imagemedian.tcl              |   146 +
 .../bis_algorithm/bis_imageremoveframes.tcl        |   257 +
 .../bis_algorithm/bis_imagetoimagealgorithm.tcl    |   200 +
 .../bis_algorithm/bis_imagetosurfacealgorithm.tcl  |   194 +
 .../bioimagesuite/bis_algorithm/bis_interleave.tcl |   156 +
 .../bis_algorithm/bis_intrinsicconnectivity.tcl    |   275 +
 .../bioimagesuite/bis_algorithm/bis_intsegment.tcl |   207 +
 .../bis_algorithm/bis_landmarkeditor.tcl           |   771 +
 .../bis_landmarkstolandmarksalgorithm.tcl          |   190 +
 .../bioimagesuite/bis_algorithm/bis_levelset.tcl   |   170 +
 .../bis_algorithm/bis_linearintensityregister.tcl  |   199 +
 .../bis_algorithm/bis_linearpointregister.tcl      |   146 +
 .../bis_algorithm/bis_listthresholdimage.tcl       |   181 +
 .../bioimagesuite/bis_algorithm/bis_logimage.tcl   |   174 +
 .../bioimagesuite/bis_algorithm/bis_makebatch.tcl  |   548 +
 .../bis_algorithm/bis_manualregistration.tcl       |   372 +
 .../bis_algorithm/bis_manualreslice.tcl            |   179 +
 .../bioimagesuite/bis_algorithm/bis_maskimage.tcl  |   165 +
 .../bis_algorithm/bis_matrixcorrelation.tcl        |   158 +
 .../bis_mediantemporalsmoothimage.tcl              |   195 +
 .../bis_algorithm/bis_multisubjectfmri.tcl         |   262 +
 .../bis_algorithm/bis_newreorientimage.tcl         |   133 +
 .../bis_nonlineardistortioncorrection.tcl          |   176 +
 .../bis_nonlinearintensityregister.tcl             |   195 +
 .../bis_algorithm/bis_nonlinearpointregister.tcl   |   178 +
 .../bis_algorithm/bis_nonlinearsmoothimage.tcl     |   172 +
 .../bioimagesuite/bis_algorithm/bis_object.tcl     |  1159 +
 .../bioimagesuite/bis_algorithm/bis_option.tcl     |  1058 +
 .../bis_algorithm/bis_optiondialog.tcl             |   495 +
 .../bis_algorithm/bis_piecewiseimagemap.tcl        |   240 +
 .../bis_pointbasedregistrationviewer.tcl           |   229 +
 .../bis_algorithm/bis_polygonaldisplaymanager.tcl  |  1013 +
 .../bis_algorithm/bis_preprocessimage.tcl          |   231 +
 .../bis_algorithm/bis_proportionalscale.tcl        |   150 +
 .../bis_algorithm/bis_qianvesselness.tcl           |   319 +
 .../bis_algorithm/bis_regularizeobjectmap.tcl      |   142 +
 .../bis_algorithm/bis_relabelimage.tcl             |   136 +
 .../bis_algorithm/bis_removeslicemean.tcl          |   182 +
 .../bis_algorithm/bis_removetemporaldrift.tcl      |   178 +
 .../bis_algorithm/bis_reorientimage.tcl            |   159 +
 .../bis_algorithm/bis_resampleimage.tcl            |   194 +
 .../bis_algorithm/bis_resamplelandmarks.tcl        |   131 +
 .../bis_algorithm/bis_resliceimage.tcl             |   213 +
 .../bis_algorithm/bis_reslicetensor.tcl            |   220 +
 .../bioimagesuite/bis_algorithm/bis_rfftimage.tcl  |   145 +
 .../bioimagesuite/bis_algorithm/bis_roimean.tcl    |   201 +
 .../bioimagesuite/bis_algorithm/bis_rtopvalue.tcl  |   156 +
 .../bioimagesuite/bis_algorithm/bis_rtotmap.tcl    |   140 +
 .../bis_algorithm/bis_seedcorrelation.tcl          |   231 +
 .../bis_algorithm/bis_serialdemonmousereg.tcl      |   528 +
 .../bis_algorithm/bis_shiftscaleimage.tcl          |   167 +
 .../bis_singleimagemathoperations.tcl              |   145 +
 .../bis_algorithm/bis_singlejacobian.tcl           |   182 +
 .../bis_algorithm/bis_singlesubjectfmri.tcl        |   218 +
 .../bis_algorithm/bis_skeletonizeimage.tcl         |   153 +
 .../bis_algorithm/bis_sliceinhomogeneity.tcl       |   179 +
 .../bis_algorithm/bis_smoothimage.tcl              |   156 +
 .../bis_algorithm/bis_smoothlandmarks.tcl          |   120 +
 .../bis_algorithm/bis_smoothsurface.tcl            |   150 +
 .../bioimagesuite/bis_algorithm/bis_spectbase.tcl  |   269 +
 .../bioimagesuite/bis_algorithm/bis_spectrf.tcl    |   215 +
 .../bis_algorithm/bis_split4dimage.tcl             |   184 +
 .../bis_algorithm/bis_stitchimage.tcl              |   251 +
 .../bioimagesuite/bis_algorithm/bis_stripskull.tcl |   318 +
 .../bioimagesuite/bis_algorithm/bis_subdivide.tcl  |   128 +
 .../bis_algorithm/bis_surfaceinfo.tcl              |   183 +
 .../bis_surfacetosurfacealgorithm.tcl              |   191 +
 .../bis_algorithm/bis_temporalsmoothimage.tcl      |   166 +
 .../bis_algorithm/bis_tensoranalysis.tcl           |   288 +
 .../bis_algorithm/bis_testdatabase.tcl             |   197 +
 .../bioimagesuite/bis_algorithm/bis_testmatrix.tcl |   135 +
 .../bioimagesuite/bis_algorithm/bis_testviewer.tcl |   221 +
 .../bis_algorithm/bis_thresholdimage.tcl           |   168 +
 .../bis_algorithm/bis_thresholdpoints.tcl          |   146 +
 .../bis_algorithm/bis_tmaptopvalue.tcl             |   140 +
 .../bis_algorithm/bis_tmaptozscore.tcl             |   136 +
 .../bis_algorithm/bis_transformsurface.tcl         |   173 +
 .../bioimagesuite/bis_algorithm/bis_treeapp.tcl    |   730 +
 .../bioimagesuite/bis_algorithm/bis_treewidget.tcl |  1684 ++
 .../bis_algorithm/bis_triangulate.tcl              |   151 +
 .../bioimagesuite/bis_algorithm/bis_ttest.tcl      |   259 +
 .../bioimagesuite/bis_algorithm/bis_util.tcl       |   140 +
 .../bis_algorithm/bis_varian2nifti.tcl             |   290 +
 .../bioimagesuite/bis_algorithm/bis_viewer.tcl     |  1062 +
 .../bis_algorithm/bis_visualizetransformation.tcl  |   169 +
 .../bis_algorithm/bis_xmlalgorithm.tcl             |   641 +
 .../bis_algorithm/bis_zscoretopvalue.tcl           |   137 +
 .../bioimagesuite/bis_algorithm/pkgIndex.tcl       |   298 +
 .../bioimagesuite/datatree/CMakeLists.txt          |    58 +
 .../bioimagesuite/datatree/ChellyGUI_exp.tcl       |  8259 ++++++
 .../datatree/ElectrodeAttributeTemplate.ele        |     6 +
 .../bioimagesuite/datatree/biodatatree.tcl         |   119 +
 .../bioimagesuite/datatree/bis_treegui.tcl         |  3931 +++
 .../bioimagesuite/datatree/dsitcltree.tcl          |   720 +
 bioimagesuite30_src/bioimagesuite/datatree/no.xbm  |    10 +
 .../bioimagesuite/datatree/packages/CMakeLists.txt |    57 +
 .../datatree/packages/ElectrodeAttrProg.tcl        |   244 +
 .../datatree/packages/ImageDialog.tcl              |    56 +
 .../bioimagesuite/datatree/packages/SPECTtools.tcl |   784 +
 .../bioimagesuite/datatree/packages/VisTree2.tcl   |   900 +
 .../bioimagesuite/datatree/packages/chellyDB.tcl   |  1297 +
 .../datatree/packages/mdImageUtils.tcl             |   689 +
 .../bioimagesuite/datatree/packages/metakitDB.tcl  |    98 +
 .../bioimagesuite/datatree/packages/pkgIndex.tcl   |    85 +
 .../datatree/packages/pxitclchellypackages.tcl     |    69 +
 .../datatree/packages/pxitcloverlaytab.tcl         |   198 +
 .../bioimagesuite/datatree/pkgIndex.tcl            |    64 +
 .../datatree/pxitclbraintreegadget.tcl             |   585 +
 .../bioimagesuite/images/CMakeLists.txt            |    88 +
 .../images/ISASHN_Standard_Deviation.nii.gz        |   Bin 0 -> 713625 bytes
 .../images/ISAS_Mean_Diff_SPECT.nii.gz             |   Bin 0 -> 663420 bytes
 .../bioimagesuite/images/ISAS_SPECT_Mask.nii.gz    |   Bin 0 -> 161119 bytes
 .../images/ISAS_SPECT_Template.nii.gz              |   Bin 0 -> 934601 bytes
 .../images/ISAS_Standard_Deviation.nii.gz          |   Bin 0 -> 713014 bytes
 .../bioimagesuite/images/MNI_T1_1mm.nii.gz         |   Bin 0 -> 8374661 bytes
 .../images/MNI_T1_1mm_graywhite.nii.gz             |   Bin 0 -> 237213 bytes
 .../bioimagesuite/images/MNI_T1_1mm_graywhite.txt  |     3 +
 .../bioimagesuite/images/MNI_T1_1mm_mask.nii.gz    |   Bin 0 -> 67029 bytes
 .../images/MNI_T1_1mm_stripped.nii.gz              |   Bin 0 -> 2434386 bytes
 .../bioimagesuite/images/MNI_T1_2mm.nii.gz         |   Bin 0 -> 607667 bytes
 .../images/MNI_T1_2mm_graywhite.nii.gz             |   Bin 0 -> 49489 bytes
 .../bioimagesuite/images/MNI_T1_2mm_mask.nii.gz    |   Bin 0 -> 12345 bytes
 .../images/MNI_T1_2mm_stripped.nii.gz              |   Bin 0 -> 204570 bytes
 .../bioimagesuite/images/README.txt                |     4 +
 .../bioimagesuite/images/avg152T1_LR_nifti.nii.gz  |   Bin 0 -> 531671 bytes
 .../bioimagesuite/images/bioimagesuite.ico         |   Bin 0 -> 3774 bytes
 .../bioimagesuite/images/bioimagesuite.png         |   Bin 0 -> 1582 bytes
 .../bioimagesuite/images/bioimagesuite.xbm         |    27 +
 .../bioimagesuite/images/bioimagesuite_atlas.txt   |     7 +
 .../images/bioimagesuite_logo_small_www.gif        |   Bin 0 -> 4293 bytes
 .../images/bioimagesuite_logo_www.gif              |   Bin 0 -> 51937 bytes
 .../images/bioimagesuite_setuplogo.bmp             |   Bin 0 -> 141982 bytes
 .../images/colin_talairach_lookup.nii.gz           |   Bin 0 -> 689066 bytes
 .../bioimagesuite/images/colinlookup.hdr           |   Bin 0 -> 348 bytes
 .../bioimagesuite/images/colinlookup.img.gz        |   Bin 0 -> 4803649 bytes
 .../bioimagesuite/images/sampledatabase.sqlite     |   Bin 0 -> 43008 bytes
 .../bioimagesuite/images/yale_broadmann.nii.gz     |   Bin 0 -> 301332 bytes
 .../bioimagesuite/images/yale_broadmann.txt        |    86 +
 .../bioimagesuite/main/CMakeLists.txt              |   105 +
 .../bioimagesuite/main/alarkutility.tcl            |   489 +
 .../bioimagesuite/main/alarkviewer.tcl             |    81 +
 bioimagesuite30_src/bioimagesuite/main/bis.tcl     |   411 +
 .../bioimagesuite/main/bis_databasetool.tcl        |  1717 ++
 .../bioimagesuite/main/bis_fmri.tcl                |  2918 ++
 .../bioimagesuite/main/bis_fmrisetup.tcl           |  4578 ++++
 .../bioimagesuite/main/bis_parameterGUI.tcl        |   151 +
 .../bioimagesuite/main/pkgIndex.tcl                |   108 +
 .../bioimagesuite/main/pxitcl4dsurfaceeditor.tcl   |   325 +
 .../main/pxitclElectrodeMultiControl.tcl           |  1978 ++
 .../bioimagesuite/main/pxitclHistogramWidget.tcl   |   557 +
 .../bioimagesuite/main/pxitclLandmarkControl.tcl   |   106 +
 .../bioimagesuite/main/pxitclPolyDataControl.tcl   |   114 +
 .../bioimagesuite/main/pxitclanimationgadget.tcl   |   735 +
 .../bioimagesuite/main/pxitclarticulatedmodel.tcl  |   563 +
 .../bioimagesuite/main/pxitclatlasgadget.tcl       |   183 +
 .../bioimagesuite/main/pxitclbaresimpleviewer.tcl  |    75 +
 .../bioimagesuite/main/pxitclbase4dimageviewer.tcl |   230 +
 .../bioimagesuite/main/pxitclbasecontrol.tcl       |   516 +
 .../bioimagesuite/main/pxitclbaseimagecontrol.tcl  |   265 +
 .../bioimagesuite/main/pxitclbaseimageviewer.tcl   |  2059 ++
 .../bioimagesuite/main/pxitclbrainregister.tcl     |   806 +
 .../bioimagesuite/main/pxitclbrainsegment.tcl      |    86 +
 .../bioimagesuite/main/pxitclbrainstrip.tcl        |  2891 ++
 .../main/pxitclcreatesolidcontrol.tcl              |   267 +
 .../bioimagesuite/main/pxitclcsigadget.tcl         |  1056 +
 .../main/pxitcldistributiontablegadget.tcl         |   222 +
 .../bioimagesuite/main/pxitcldualmultisubject.tcl  |    67 +
 .../bioimagesuite/main/pxitclelectrodeeditor.tcl   |   192 +
 .../bioimagesuite/main/pxitclexpfit.tcl            |   709 +
 .../bioimagesuite/main/pxitclfilelistmenu.tcl      |   560 +
 .../bioimagesuite/main/pxitclimageimport.tcl       |  1039 +
 .../main/pxitclimagenormalization.tcl              |   344 +
 .../bioimagesuite/main/pxitcllistselector.tcl      |   168 +
 .../main/pxitclmanualsurfacetransformation.tcl     |   452 +
 .../main/pxitclmanualtransformation.tcl            |   604 +
 .../bioimagesuite/main/pxitclmousechopper.tcl      |  2096 ++
 .../bioimagesuite/main/pxitclmouseregister.tcl     |   598 +
 .../bioimagesuite/main/pxitclmousesegment.tcl      |    78 +
 .../main/pxitclmultisubjectaverage.tcl             |  3263 +++
 .../bioimagesuite/main/pxitclopenigtlinkgadget.tcl |   553 +
 .../bioimagesuite/main/pxitclorthoviewer.tcl       |    77 +
 .../bioimagesuite/main/pxitcloverlaytool.tcl       |  3570 +++
 .../bioimagesuite/main/pxitclrpm.tcl               |  1334 +
 .../bioimagesuite/main/pxitclsimpleeditor.tcl      |    69 +
 .../bioimagesuite/main/pxitclsimpleviewer.tcl      |    67 +
 .../bioimagesuite/main/pxitclsplineeditor.tcl      |   146 +
 .../bioimagesuite/main/pxitclsplineobjectmap.tcl   |   155 +
 .../main/pxitclsplinestackobjectmap.tcl            |   272 +
 .../bioimagesuite/main/pxitclsubjectentry.tcl      |   409 +
 .../bioimagesuite/main/pxitclsurfaceeditor.tcl     |   558 +
 .../bioimagesuite/main/pxitclsurfaceobjectmap.tcl  |   664 +
 .../bioimagesuite/main/pxitclvolumeviewer.tcl      |   100 +
 .../bioimagesuite/main/pxitclvvlinkgadget.tcl      |  2183 ++
 .../main/pxitclvvlinkprojectorgadget.tcl           |   453 +
 .../bioimagesuite/main/pxitclvvlinkviewer.tcl      |    86 +
 .../bioimagesuite/main/pxitclwfuatlasgadget.tcl    |   474 +
 .../bioimagesuite/main/pxitclyaleatlasgadget.tcl   |   517 +
 .../bioimagesuite/mjack/CMakeLists.txt             |    69 +
 .../bioimagesuite/mjack/mpjdiffusiontool.tcl       |   129 +
 .../bioimagesuite/mjack/mpjfastmarching.tcl        |  3911 +++
 .../bioimagesuite/mjack/mpjfibertracking.tcl       |  3085 +++
 .../bioimagesuite/mjack/mpjguiicosahedron.tcl      |   455 +
 .../bioimagesuite/mjack/mpjguilookuptable.tcl      |   640 +
 .../bioimagesuite/mjack/mpjguiobject.tcl           |   134 +
 .../bioimagesuite/mjack/mpjguisphere.tcl           |   406 +
 .../bioimagesuite/mjack/mpjinterleave.tcl          |    96 +
 .../bioimagesuite/mjack/mpjmultibtensorutility.tcl |  2395 ++
 .../bioimagesuite/mjack/mpjmultiimagegui.tcl       |   118 +
 .../bioimagesuite/mjack/mpjmultiobjectgui.tcl      |   185 +
 .../bioimagesuite/mjack/mpjsigna2analyze.tcl       |   156 +
 .../bioimagesuite/mjack/mpjt2relax.tcl             |   148 +
 .../bioimagesuite/mjack/mpjtensoranalysis.tcl      |  3457 +++
 .../bioimagesuite/mjack/mpjtensorutility.tcl       |  2407 ++
 .../bioimagesuite/mjack/mpjvesselanalysis.tcl      |  3351 +++
 .../bioimagesuite/mjack/mpjvesseltool.tcl          |    92 +
 .../bioimagesuite/mjack/mpjvesseltracking.tcl      |  3421 +++
 .../bioimagesuite/mjack/mpjvesselutility.tcl       |  1259 +
 .../bioimagesuite/mjack/pkgIndex.tcl               |    60 +
 .../bioimagesuite/mjack/vtkmpjcontrib.tcl          |    42 +
 .../bioimagesuite/origscripts/CMakeLists.txt       |   141 +
 .../bioimagesuite/origscripts/bioimagesuite.bat.in |    19 +
 .../bioimagesuite/origscripts/bis_console.in       |    15 +
 .../bioimagesuite/origscripts/bisconsole.bat.in    |    14 +
 .../bioimagesuite/origscripts/biscppexec.bat.in    |    17 +
 .../bioimagesuite/origscripts/biscppexec.in        |    23 +
 .../bioimagesuite/origscripts/bisexec.bat.in       |    20 +
 .../bioimagesuite/origscripts/bisexec.in           |    23 +
 .../origscripts/createmenuentries.sh.in            |    19 +
 .../bioimagesuite/origscripts/runscript.bat.in     |    25 +
 .../bioimagesuite/origscripts/runscript.in         |    27 +
 .../bioimagesuite/origscripts/setpaths.bat.in      |    26 +
 .../bioimagesuite/origscripts/setpaths.csh.in      |    65 +
 .../bioimagesuite/origscripts/setpaths.sh.in       |    69 +
 .../origscripts/setpaths_console.sh.in             |    28 +
 .../origscripts/start_bioimagesuite.in             |    19 +
 bioimagesuite30_src/database/CMakeLists.txt        |   133 +
 .../database/vtkbisAlgorithmTable.cpp              |   374 +
 .../database/vtkbisAlgorithmTable.h                |    87 +
 .../database/vtkbisBaseProcedure.cpp               |    75 +
 bioimagesuite30_src/database/vtkbisBaseProcedure.h |    67 +
 bioimagesuite30_src/database/vtkbisDatabase.cpp    |   351 +
 bioimagesuite30_src/database/vtkbisDatabase.h      |   106 +
 .../database/vtkbisFilenameTable.cpp               |   323 +
 bioimagesuite30_src/database/vtkbisFilenameTable.h |    84 +
 bioimagesuite30_src/database/vtkbisInjection.cpp   |   215 +
 bioimagesuite30_src/database/vtkbisInjection.h     |    72 +
 bioimagesuite30_src/database/vtkbisPatient.cpp     |   206 +
 bioimagesuite30_src/database/vtkbisPatient.h       |    77 +
 bioimagesuite30_src/database/vtkbisProtocol.cpp    |   200 +
 bioimagesuite30_src/database/vtkbisProtocol.h      |    74 +
 bioimagesuite30_src/database/vtkbisQuery.cpp       |   332 +
 bioimagesuite30_src/database/vtkbisQuery.h         |   111 +
 .../database/vtkbisSQLiteDatabase.cpp              |    91 +
 .../database/vtkbisSQLiteDatabase.h                |    56 +
 bioimagesuite30_src/database/vtkbisSeries.cpp      |   238 +
 bioimagesuite30_src/database/vtkbisSeries.h        |    85 +
 bioimagesuite30_src/database/vtkbisStudy.cpp       |   236 +
 bioimagesuite30_src/database/vtkbisStudy.h         |    78 +
 bioimagesuite30_src/database/vtkbisVisit.cpp       |   226 +
 bioimagesuite30_src/database/vtkbisVisit.h         |    93 +
 bioimagesuite30_src/database/vtkimSQLite.cpp       |   190 +
 bioimagesuite30_src/database/vtkimSQLite.h         |    68 +
 bioimagesuite30_src/igtlutil/CMakeLists.txt        |    61 +
 bioimagesuite30_src/igtlutil/igtl_header.c         |    57 +
 bioimagesuite30_src/igtlutil/igtl_header.h         |    97 +
 bioimagesuite30_src/igtlutil/igtl_image.c          |   192 +
 bioimagesuite30_src/igtlutil/igtl_image.h          |   167 +
 bioimagesuite30_src/igtlutil/igtl_transform.c      |    73 +
 bioimagesuite30_src/igtlutil/igtl_transform.h      |    84 +
 bioimagesuite30_src/igtlutil/igtl_types.h          |   115 +
 bioimagesuite30_src/igtlutil/igtl_util.c           |   195 +
 bioimagesuite30_src/igtlutil/igtl_util.h           |    77 +
 bioimagesuite30_src/include/CMakeLists.txt         |    60 +
 bioimagesuite30_src/include/bio_f2c.h              |   420 +
 bioimagesuite30_src/include/bis_znzlib.h           |   137 +
 bioimagesuite30_src/include/clapack.h              |  5118 ++++
 bioimagesuite30_src/include/nifti1.h               |  1469 +
 bioimagesuite30_src/include/nifti1_io.h            |   446 +
 bioimagesuite30_src/include/pxisinf.h              |    80 +
 bioimagesuite30_src/include/vtkbisConfigure.h.in   |    59 +
 bioimagesuite30_src/installtools/CMakeLists.txt    |   101 +
 .../installtools/bis_creategnomeentries.cpp        |   113 +
 .../installtools/bis_fixlicense.cpp                |   306 +
 .../installtools/bis_fixscripts.cpp                |   370 +
 .../installtools/bis_fixscripts_base.cpp           |   345 +
 bioimagesuite30_src/mpjCommon/CMakeLists.txt       |   111 +
 .../mpjCommon/vtkmpjDiffusionProfile.cpp           |   284 +
 .../mpjCommon/vtkmpjDiffusionProfile.h             |   140 +
 .../mpjCommon/vtkmpjFrameAppend.cpp                |   159 +
 bioimagesuite30_src/mpjCommon/vtkmpjFrameAppend.h  |    77 +
 .../mpjCommon/vtkmpjFrameAverage.cpp               |   186 +
 bioimagesuite30_src/mpjCommon/vtkmpjFrameAverage.h |    77 +
 .../mpjCommon/vtkmpjFrameExtract.cpp               |   207 +
 bioimagesuite30_src/mpjCommon/vtkmpjFrameExtract.h |    84 +
 .../mpjCommon/vtkmpjFramePermutation.cpp           |   105 +
 .../mpjCommon/vtkmpjFramePermutation.h             |    67 +
 .../mpjCommon/vtkmpjIcosahedronSource.cpp          |   465 +
 .../mpjCommon/vtkmpjIcosahedronSource.h            |    94 +
 .../mpjCommon/vtkmpjImageBoundary.cpp              |   175 +
 .../mpjCommon/vtkmpjImageBoundary.h                |    92 +
 .../mpjCommon/vtkmpjImageHessian.cpp               |   184 +
 bioimagesuite30_src/mpjCommon/vtkmpjImageHessian.h |   100 +
 .../mpjCommon/vtkmpjImageInterleaving.cpp          |   158 +
 .../mpjCommon/vtkmpjImageInterleaving.h            |    79 +
 .../mpjCommon/vtkmpjImagePointSource.cpp           |   193 +
 .../mpjCommon/vtkmpjImagePointSource.h             |    96 +
 .../mpjCommon/vtkmpjImageSignalToNoiseRatio.cpp    |   163 +
 .../mpjCommon/vtkmpjImageSignalToNoiseRatio.h      |   107 +
 .../mpjCommon/vtkmpjImageStatistics.cpp            |   187 +
 .../mpjCommon/vtkmpjImageStatistics.h              |   108 +
 .../mpjCommon/vtkmpjImageT2Relax.cpp               |   206 +
 bioimagesuite30_src/mpjCommon/vtkmpjImageT2Relax.h |    88 +
 .../mpjCommon/vtkmpjImageTwoNorm.cpp               |   183 +
 bioimagesuite30_src/mpjCommon/vtkmpjImageTwoNorm.h |    72 +
 .../mpjCommon/vtkmpjImageVesselEnhancement.cpp     |   354 +
 .../mpjCommon/vtkmpjImageVesselEnhancement.h       |   154 +
 .../mpjCommon/vtkmpjImageVesselMaximum.cpp         |   190 +
 .../mpjCommon/vtkmpjImageVesselMaximum.h           |    77 +
 .../mpjCommon/vtkmpjPriorityQueue.cpp              |   266 +
 .../mpjCommon/vtkmpjPriorityQueue.h                |   194 +
 .../mpjCommon/vtkmpjScalarsToFieldData.cpp         |   104 +
 .../mpjCommon/vtkmpjScalarsToFieldData.h           |    64 +
 .../mpjCommon/vtkmpjSphereSubdivisionSource.cpp    |   371 +
 .../mpjCommon/vtkmpjSphereSubdivisionSource.h      |   117 +
 bioimagesuite30_src/mpjCommon/vtkmpjStreamer.cpp   |   771 +
 bioimagesuite30_src/mpjCommon/vtkmpjStreamer.h     |   319 +
 .../mpjCommon/vtkmpjStreamlineDistance.cpp         |   213 +
 .../mpjCommon/vtkmpjStreamlineDistance.h           |    90 +
 .../mpjCommon/vtkmpjStreamlineQuantization.cpp     |   179 +
 .../mpjCommon/vtkmpjStreamlineQuantization.h       |    81 +
 .../mpjCommon/vtkmpjTensorStreamline.cpp           |  1333 +
 .../mpjCommon/vtkmpjTensorStreamline.h             |   334 +
 .../vtkmpjTensorStreamlineRegionFilter.cpp         |   235 +
 .../mpjCommon/vtkmpjTensorStreamlineRegionFilter.h |    82 +
 .../mpjCommon/vtkmpjTensorStreamlineStatistics.cpp |   274 +
 .../mpjCommon/vtkmpjTensorStreamlineStatistics.h   |    82 +
 .../mpjCommon/vtkmpjTestOptimizer.cpp              |   187 +
 .../mpjCommon/vtkmpjTestOptimizer.h                |   107 +
 .../mpjCommon/vtkmpjThresholdPolyData.cpp          |   301 +
 .../mpjCommon/vtkmpjThresholdPolyData.h            |   130 +
 .../vtkmpjThresholdPolyDataByDistance.cpp          |   157 +
 .../mpjCommon/vtkmpjThresholdPolyDataByDistance.h  |    72 +
 bioimagesuite30_src/mpjCommon/vtkmpjTubeFilter.cpp |   801 +
 bioimagesuite30_src/mpjCommon/vtkmpjTubeFilter.h   |   207 +
 .../mpjCommon/vtkmpjVectorStreamline.cpp           |   303 +
 .../mpjCommon/vtkmpjVectorStreamline.h             |    73 +
 .../mpjCommon/vtkmpjVectorStreamlineStatistics.cpp |   105 +
 .../mpjCommon/vtkmpjVectorStreamlineStatistics.h   |    79 +
 .../mpjCommon/vtkmpjVertexSource.cpp               |    99 +
 bioimagesuite30_src/mpjCommon/vtkmpjVertexSource.h |    88 +
 bioimagesuite30_src/mpjDiffusion/CMakeLists.txt    |    95 +
 .../mpjDiffusion/vtkmpjApparentDiffusion.cpp       |   195 +
 .../mpjDiffusion/vtkmpjApparentDiffusion.h         |    95 +
 .../mpjDiffusion/vtkmpjHeartFiberAngle.cpp         |   180 +
 .../mpjDiffusion/vtkmpjHeartFiberAngle.h           |    81 +
 .../mpjDiffusion/vtkmpjHeartSheetAngle.cpp         |   184 +
 .../mpjDiffusion/vtkmpjHeartSheetAngle.h           |    81 +
 .../mpjDiffusion/vtkmpjImageDotProduct.cpp         |   172 +
 .../mpjDiffusion/vtkmpjImageDotProduct.h           |    79 +
 .../mpjDiffusion/vtkmpjImageSymmetricTensor.cpp    |   314 +
 .../mpjDiffusion/vtkmpjImageSymmetricTensor.h      |   128 +
 .../mpjDiffusion/vtkmpjImageTensorCoherence.cpp    |   196 +
 .../mpjDiffusion/vtkmpjImageTensorCoherence.h      |    87 +
 .../mpjDiffusion/vtkmpjImageTensorColor.cpp        |   482 +
 .../mpjDiffusion/vtkmpjImageTensorColor.h          |   120 +
 .../vtkmpjImageTensorEigenAnalysis.cpp             |   523 +
 .../mpjDiffusion/vtkmpjImageTensorEigenAnalysis.h  |   160 +
 .../mpjDiffusion/vtkmpjImageTensorInvariants.cpp   |   188 +
 .../mpjDiffusion/vtkmpjImageTensorInvariants.h     |   100 +
 .../mpjDiffusion/vtkmpjImageTensorMultiply.cpp     |   261 +
 .../mpjDiffusion/vtkmpjImageTensorMultiply.h       |    76 +
 .../mpjDiffusion/vtkmpjImageTensorProduct.cpp      |   232 +
 .../mpjDiffusion/vtkmpjImageTensorProduct.h        |    96 +
 .../mpjDiffusion/vtkmpjImageTensorSimilarity.cpp   |   360 +
 .../mpjDiffusion/vtkmpjImageTensorSimilarity.h     |   100 +
 .../mpjDiffusion/vtkmpjImageTensorTransform.cpp    |   232 +
 .../mpjDiffusion/vtkmpjImageTensorTransform.h      |    72 +
 .../mpjDiffusion/vtkmpjImageTensorVariance.cpp     |   212 +
 .../mpjDiffusion/vtkmpjImageTensorVariance.h       |    86 +
 .../mpjDiffusion/vtkmpjImageToTensors.cpp          |   138 +
 .../mpjDiffusion/vtkmpjImageToTensors.h            |    82 +
 .../mpjDiffusion/vtkmpjImageToVectors.cpp          |   102 +
 .../mpjDiffusion/vtkmpjImageToVectors.h            |    77 +
 .../mpjDiffusion/vtkmpjLatticeAnisotropy.cpp       |   264 +
 .../mpjDiffusion/vtkmpjLatticeAnisotropy.h         |   114 +
 .../mpjDiffusion/vtkmpjQBallImaging.cpp            |   315 +
 .../mpjDiffusion/vtkmpjQBallImaging.h              |   111 +
 .../vtkmpjTensorBMatrixLeastSquares.cpp            |   295 +
 .../mpjDiffusion/vtkmpjTensorBMatrixLeastSquares.h |   139 +
 .../mpjDiffusion/vtkmpjTensorGeometryMetrics.cpp   |   169 +
 .../mpjDiffusion/vtkmpjTensorGeometryMetrics.h     |    99 +
 .../mpjDiffusion/vtkmpjTensorLeastSquares.cpp      |   295 +
 .../mpjDiffusion/vtkmpjTensorLeastSquares.h        |   131 +
 .../vtkmpjTensorToApparentDiffusion.cpp            |   324 +
 .../mpjDiffusion/vtkmpjTensorToApparentDiffusion.h |   142 +
 bioimagesuite30_src/mpjLevelset/CMakeLists.txt     |    89 +
 .../mpjLevelset/vtkmpjExtractLevelSet.cpp          |   230 +
 .../mpjLevelset/vtkmpjExtractLevelSet.h            |   105 +
 .../mpjLevelset/vtkmpjFastMarchingConnectivity.cpp |   752 +
 .../mpjLevelset/vtkmpjFastMarchingConnectivity.h   |   166 +
 .../mpjLevelset/vtkmpjFastMarchingExtension.cpp    |   555 +
 .../mpjLevelset/vtkmpjFastMarchingExtension.h      |   141 +
 .../mpjLevelset/vtkmpjFastMarchingImageFilter.cpp  |   596 +
 .../mpjLevelset/vtkmpjFastMarchingImageFilter.h    |   289 +
 .../mpjLevelset/vtkmpjFastMarchingMethod.cpp       |   741 +
 .../mpjLevelset/vtkmpjFastMarchingMethod.h         |   159 +
 .../vtkmpjFastMarchingVesselConnectivity.cpp       |   786 +
 .../vtkmpjFastMarchingVesselConnectivity.h         |   173 +
 .../mpjLevelset/vtkmpjFastSweepingMethod.cpp       |   605 +
 .../mpjLevelset/vtkmpjFastSweepingMethod.h         |   126 +
 .../mpjLevelset/vtkmpjImageCharacteristics.cpp     |   323 +
 .../mpjLevelset/vtkmpjImageCharacteristics.h       |    98 +
 .../mpjLevelset/vtkmpjLaxConnectivity.cpp          |   741 +
 .../mpjLevelset/vtkmpjLaxConnectivity.h            |   186 +
 .../mpjLevelset/vtkmpjLaxFriedrichEuclidean.cpp    |   491 +
 .../mpjLevelset/vtkmpjLaxFriedrichEuclidean.h      |   132 +
 .../mpjLevelset/vtkmpjLaxFriedrichSweeping.cpp     |   560 +
 .../mpjLevelset/vtkmpjLaxFriedrichSweeping.h       |   177 +
 .../vtkmpjLaxFriedrichSweepingMethod.cpp           |   675 +
 .../mpjLevelset/vtkmpjLaxFriedrichSweepingMethod.h |   136 +
 .../mpjLevelset/vtkmpjLaxFriedrichTest.cpp         |   947 +
 .../mpjLevelset/vtkmpjLaxFriedrichTest.h           |   167 +
 .../mpjLevelset/vtkmpjLevelSetMethod.cpp           |   293 +
 .../mpjLevelset/vtkmpjLevelSetMethod.h             |   113 +
 .../mpjLevelset/vtkmpjLevelSetNarrowBandFilter.cpp |   122 +
 .../mpjLevelset/vtkmpjLevelSetNarrowBandFilter.h   |    96 +
 .../vtkmpjLevelSetNeighborhoodExtractor.cpp        |   397 +
 .../vtkmpjLevelSetNeighborhoodExtractor.h          |   183 +
 .../mpjLevelset/vtkmpjLevelSetNormal.cpp           |   207 +
 .../mpjLevelset/vtkmpjLevelSetNormal.h             |    75 +
 .../mpjLevelset/vtkmpjLevelSetSignedDistance.cpp   |   228 +
 .../mpjLevelset/vtkmpjLevelSetSignedDistance.h     |    96 +
 .../mpjLevelset/vtkmpjLevelSetTest.cpp             |   141 +
 .../mpjLevelset/vtkmpjLevelSetTest.h               |    83 +
 .../vtkmpjReinitializeLevelSetImageFilter.cpp      |   295 +
 .../vtkmpjReinitializeLevelSetImageFilter.h        |   166 +
 bioimagesuite30_src/numerics/CMakeLists.txt        |   119 +
 bioimagesuite30_src/numerics/f2cfix.c              |    41 +
 bioimagesuite30_src/numerics/f2cfix.h              |    43 +
 bioimagesuite30_src/numerics/fitpack.c             | 27140 +++++++++++++++++++
 bioimagesuite30_src/numerics/fitpack.h             |   213 +
 bioimagesuite30_src/numerics/linsystems.cpp        |   761 +
 bioimagesuite30_src/numerics/nr.h                  |    92 +
 bioimagesuite30_src/numerics/nrutil.cpp            |   813 +
 bioimagesuite30_src/numerics/nrutil.h              |   181 +
 bioimagesuite30_src/numerics/peng_cheng_util.cpp   |   588 +
 bioimagesuite30_src/numerics/px3dimage.cpp         |   832 +
 bioimagesuite30_src/numerics/px3dimage.h           |   258 +
 bioimagesuite30_src/numerics/pxabaqussolid.cpp     |  4647 ++++
 bioimagesuite30_src/numerics/pxabaqussolid.h       |   322 +
 .../numerics/pxabaqusstructures.cpp                |  2208 ++
 bioimagesuite30_src/numerics/pxabaqusstructures.h  |   320 +
 .../numerics/pxchamferdistancemap.cpp              |   867 +
 .../numerics/pxchamferdistancemap.h                |   150 +
 bioimagesuite30_src/numerics/pxcontour.cpp         |  1979 ++
 bioimagesuite30_src/numerics/pxcontour.h           |   281 +
 bioimagesuite30_src/numerics/pxcontourstack.cpp    |  1275 +
 bioimagesuite30_src/numerics/pxcontourstack.h      |   177 +
 bioimagesuite30_src/numerics/pxcrystalabaqus.cpp   |  2232 ++
 bioimagesuite30_src/numerics/pxcrystalabaqus.h     |   194 +
 bioimagesuite30_src/numerics/pxfloatimage.cpp      |   426 +
 bioimagesuite30_src/numerics/pxfloatimage.h        |   186 +
 bioimagesuite30_src/numerics/pxfloatmatrix.cpp     |   225 +
 bioimagesuite30_src/numerics/pxfloatmatrix.h       |   138 +
 bioimagesuite30_src/numerics/pxfpbspline.cpp       |  2512 ++
 bioimagesuite30_src/numerics/pxfpbspline.h         |   334 +
 bioimagesuite30_src/numerics/pxfpbsplinestack.cpp  |  1426 +
 bioimagesuite30_src/numerics/pxfpbsplinestack.h    |   191 +
 bioimagesuite30_src/numerics/pxgeometrystruct.cpp  |  1165 +
 bioimagesuite30_src/numerics/pxgeometrystruct.h    |   315 +
 bioimagesuite30_src/numerics/pximage.cpp           |  1540 ++
 bioimagesuite30_src/numerics/pximage.h             |   261 +
 bioimagesuite30_src/numerics/pxmarkerclass.cpp     |   454 +
 bioimagesuite30_src/numerics/pxmarkerclass.h       |   150 +
 bioimagesuite30_src/numerics/pxregion.cpp          |   756 +
 bioimagesuite30_src/numerics/pxregion.h            |   129 +
 .../numerics/pxshapetrackingclass.cpp              |  1665 ++
 .../numerics/pxshapetrackingclass.h                |   131 +
 .../numerics/pxtriangulatedstack.cpp               |  4770 ++++
 bioimagesuite30_src/numerics/pxtriangulatedstack.h |   249 +
 bioimagesuite30_src/numerics/pxutil.cpp            |  1015 +
 bioimagesuite30_src/numerics/pxutil.h              |  1174 +
 bioimagesuite30_src/numerics/tnt/jama_cholesky.h   |   286 +
 bioimagesuite30_src/numerics/tnt/jama_eig.h        |  1053 +
 bioimagesuite30_src/numerics/tnt/jama_lu.h         |   347 +
 bioimagesuite30_src/numerics/tnt/jama_qr.h         |   355 +
 bioimagesuite30_src/numerics/tnt/jama_svd.h        |   561 +
 bioimagesuite30_src/numerics/tnt/tnt.h             |    93 +
 bioimagesuite30_src/numerics/tnt/tnt_array1d.h     |   446 +
 .../numerics/tnt/tnt_array1d_utils.h               |    93 +
 bioimagesuite30_src/numerics/tnt/tnt_array2d.h     |   463 +
 .../numerics/tnt/tnt_array2d_utils.h               |   150 +
 bioimagesuite30_src/numerics/tnt/tnt_array3d.h     |   469 +
 .../numerics/tnt/tnt_array3d_utils.h               |   112 +
 bioimagesuite30_src/numerics/tnt/tnt_cmat.h        |   613 +
 .../numerics/tnt/tnt_fortran_array1d.h             |   340 +
 .../numerics/tnt/tnt_fortran_array1d_utils.h       |    92 +
 .../numerics/tnt/tnt_fortran_array2d.h             |   356 +
 .../numerics/tnt/tnt_fortran_array2d_utils.h       |   109 +
 .../numerics/tnt/tnt_fortran_array3d.h             |   367 +
 .../numerics/tnt/tnt_fortran_array3d_utils.h       |   112 +
 bioimagesuite30_src/numerics/tnt/tnt_math_utils.h  |    85 +
 .../numerics/tnt/tnt_sparse_matrix_csr.h           |   131 +
 bioimagesuite30_src/numerics/tnt/tnt_stopwatch.h   |   145 +
 bioimagesuite30_src/numerics/tnt/tnt_subscript.h   |    82 +
 bioimagesuite30_src/numerics/tnt/tnt_vec.h         |   432 +
 bioimagesuite30_src/numerics/tnt/tnt_version.h     |    67 +
 bioimagesuite30_src/pxtklib/CMakeLists.txt         |    90 +
 .../pxtklib/nrtk_iwidget_tabnotebook.cpp           |   136 +
 .../pxtklib/nrtk_iwidget_tabnotebook.h             |    68 +
 bioimagesuite30_src/pxtklib/pxitkcombobox.cpp      |   191 +
 bioimagesuite30_src/pxtklib/pxitkcombobox.h        |   105 +
 bioimagesuite30_src/pxtklib/pxtkapp.cpp            |   704 +
 bioimagesuite30_src/pxtklib/pxtkapp.h              |   235 +
 bioimagesuite30_src/pxtklib/pxtkbase.cpp           |   150 +
 bioimagesuite30_src/pxtklib/pxtkbase.h             |   114 +
 bioimagesuite30_src/pxtklib/pxtkbutton.cpp         |    87 +
 bioimagesuite30_src/pxtklib/pxtkbutton.h           |    85 +
 bioimagesuite30_src/pxtklib/pxtkcheckbutton.cpp    |   107 +
 bioimagesuite30_src/pxtklib/pxtkcheckbutton.h      |    88 +
 bioimagesuite30_src/pxtklib/pxtkcomplexwidgets.cpp |   571 +
 bioimagesuite30_src/pxtklib/pxtkcomplexwidgets.h   |   207 +
 bioimagesuite30_src/pxtklib/pxtkdialog.cpp         |   256 +
 bioimagesuite30_src/pxtklib/pxtkdialog.h           |   117 +
 bioimagesuite30_src/pxtklib/pxtkentry.cpp          |    88 +
 bioimagesuite30_src/pxtklib/pxtkentry.h            |    86 +
 bioimagesuite30_src/pxtklib/pxtkeventobj.cpp       |   348 +
 bioimagesuite30_src/pxtklib/pxtkeventobj.h         |   120 +
 bioimagesuite30_src/pxtklib/pxtkframe.cpp          |   256 +
 bioimagesuite30_src/pxtklib/pxtkframe.h            |   115 +
 bioimagesuite30_src/pxtklib/pxtkgadget.cpp         |   243 +
 bioimagesuite30_src/pxtklib/pxtkgadget.h           |   109 +
 bioimagesuite30_src/pxtklib/pxtkgadgets.h          |   121 +
 bioimagesuite30_src/pxtklib/pxtkinfodialog.cpp     |   141 +
 bioimagesuite30_src/pxtklib/pxtkinfodialog.h       |    93 +
 bioimagesuite30_src/pxtklib/pxtklabel.cpp          |   103 +
 bioimagesuite30_src/pxtklib/pxtklabel.h            |    83 +
 bioimagesuite30_src/pxtklib/pxtklistbox.cpp        |   160 +
 bioimagesuite30_src/pxtklib/pxtklistbox.h          |    95 +
 bioimagesuite30_src/pxtklib/pxtkmenu.cpp           |   169 +
 bioimagesuite30_src/pxtklib/pxtkmenu.h             |   100 +
 bioimagesuite30_src/pxtklib/pxtkmenubutton.cpp     |    77 +
 bioimagesuite30_src/pxtklib/pxtkmenubutton.h       |    84 +
 bioimagesuite30_src/pxtklib/pxtkmessage.cpp        |    75 +
 bioimagesuite30_src/pxtklib/pxtkmessage.h          |    82 +
 bioimagesuite30_src/pxtklib/pxtkoptionmenu.cpp     |   197 +
 bioimagesuite30_src/pxtklib/pxtkoptionmenu.h       |    97 +
 bioimagesuite30_src/pxtklib/pxtkradiobutton.cpp    |   104 +
 bioimagesuite30_src/pxtklib/pxtkradiobutton.h      |    92 +
 bioimagesuite30_src/pxtklib/pxtkscale.cpp          |   198 +
 bioimagesuite30_src/pxtklib/pxtkscale.h            |    95 +
 bioimagesuite30_src/pxtklib/pxtkscrollbar.cpp      |   101 +
 bioimagesuite30_src/pxtklib/pxtkscrollbar.h        |    89 +
 bioimagesuite30_src/pxtklib/pxtkseldialog.cpp      |   377 +
 bioimagesuite30_src/pxtklib/pxtkseldialog.h        |   139 +
 bioimagesuite30_src/pxtklib/pxtktext.cpp           |   149 +
 bioimagesuite30_src/pxtklib/pxtktext.h             |    83 +
 bioimagesuite30_src/pxtklib/pxtktoplevel.cpp       |   166 +
 bioimagesuite30_src/pxtklib/pxtktoplevel.h         |    94 +
 bioimagesuite30_src/pxtklib/pxtkwaitdialog.cpp     |   138 +
 bioimagesuite30_src/pxtklib/pxtkwaitdialog.h       |   102 +
 debian/bioimagesuite-data.dirs                     |     1 -
 debian/bioimagesuite-data.install                  |     1 -
 debian/bioimagesuite.dirs                          |     3 -
 debian/bioimagesuite.examples                      |     1 -
 debian/bioimagesuite.install                       |    12 -
 debian/bioimagesuite.links                         |     1 -
 debian/bioimagesuite.lintian-overrides             |     2 -
 debian/bioimagesuite.menu                          |     5 -
 debian/changelog                                   |     8 -
 debian/compat                                      |     1 -
 debian/control                                     |    67 -
 debian/copyright                                   |    33 -
 debian/get-orig-source                             |    23 -
 debian/libbioimagesuite2.dirs                      |     2 -
 debian/libbioimagesuite2.install                   |     1 -
 debian/libbioimagesuite2.lintian-overrides         |    33 -
 debian/libbioimagesuite2.postinst                  |    26 -
 debian/libbioimagesuite2.shlibs.local              |    19 -
 debian/old/README.Debian                           |     6 -
 debian/old/bioimagesuite-dev.dirs                  |     1 -
 debian/old/bioimagesuite-dev.install               |     1 -
 debian/old/control.old                             |    63 -
 debian/old/libbioimagesuite-dev.install            |     1 -
 debian/patches/edit_paths.patch                    |    88 -
 debian/patches/series                              |     1 -
 debian/rules                                       |    74 -
 debian/upstream/metadata                           |    30 -
 1346 files changed, 522403 insertions(+), 504 deletions(-)

diff --git a/Registration/dvSparseMatrix.h b/Registration/dvSparseMatrix.h
new file mode 100755
index 0000000..d4e0474
--- /dev/null
+++ b/Registration/dvSparseMatrix.h
@@ -0,0 +1,465 @@
+
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  All rights reserved. This file may not be edited/copied/redistributed
+//BIOIMAGESUITE_LICENSE  without the explicit permission of the authors.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#ifndef SPARSE_H
+#define SPARSE_H
+// $Id: dvSparseMatrix.h,v 1.1 2002/11/06 16:24:56 papad Exp papad $
+
+#include <utility>
+#include <map>
+#include "vtkpxMatrix.h"
+
+
+class vtkpxSparseMatrix; // forward declaration
+
+
+/*
+  See also examples in  Dirk Vermeier
+  "Multi-Paradigm Programming Using C+"
+
+  adapted and modified by Xenios Papademetris
+  papad at noodle.med.yale.edu
+
+  October 29th 2002
+  Used by permission of the original author, Dirk Vermeier, for release in GPL software.
+
+
+  e.g.
+
+  dvSparseMatrix<double> m(0.0); 
+  m[0][2]=1.0;
+  m[1][3]=4.0;
+  m.listall();
+  m.cleanup();
+
+
+*/
+
+class dvSparseRow;
+class dvSparseMatrix;
+
+class dvSparseElement {
+
+  public:
+  
+  dvSparseElement(dvSparseRow& r,int k2): row_(r), key2_(k2) {}
+  void operator=(const float& val);
+  operator float() { return Value();}
+  
+
+private:
+
+  dvSparseRow&	   row_; // E.g. a[k1][k2] returns element refering to a[k1] row, key2=k2.
+  unsigned long	  key2_;
+  float Value();
+};
+
+// ------------------------------------------------------------------------------------
+
+
+class dvSparseRow 
+{ 
+  // a row is a [Key2->float] map
+  friend class dvSparseElement;
+  friend class dvSparseMatrix;
+  
+private:
+  dvSparseRow& operator=(const dvSparseRow&);   // Forbid assignment
+  dvSparseMatrix&      matrix_;
+  
+  
+public:
+  dvSparseRow(dvSparseMatrix& matrix): matrix_(matrix) { columns_[0]=0.0;} // Remember matrix for getting default value.
+  dvSparseElement operator[](const unsigned long& k2) { return dvSparseElement(*this,k2); }
+
+  std::map<unsigned long,float>    columns_;  // one element for every non-default element in row
+  
+  // ------------------------------------------------------------------------------------
+  //
+  //
+  //            Additional Functions  Xenios Papademetris Oct 2002
+  //
+  //
+  // ------------------------------------------------------------------------------------
+  
+  unsigned long getsize()  { return columns_.size(); }
+  
+  void cleanup() { columns_.clear();}
+  
+  void getrange(unsigned long r[2]) {
+    
+    std::map<unsigned long,float>::iterator i = columns_.begin();    
+    r[0]=(*i).first;
+    r[1]=(*i).first;
+    ++i;
+    while (i != columns_.end())                    
+      {
+	if (r[0] >  (*i).first)
+	  r[0]=(*i).first;
+	if (r[1] <  (*i).first)
+	  r[1]=(*i).first;	
+	++i;
+      }
+  }
+  
+  
+  
+  float getsum()  { 
+    float sm=0.0;
+    std::map<unsigned long,float>::iterator i = columns_.begin();    
+    while (i != columns_.end())                    
+      {
+	sm+=(*i).second;
+	++i;
+      }
+    return sm;
+  }
+  
+
+  // ------------------------------------------------------
+  // RPM Stuff
+  // ------------------------------------------------------
+  void addtosum(float* sum) {
+    std::map<unsigned long,float>::iterator i = columns_.begin();    
+    while (i != columns_.end())                    
+      {
+	sum[(*i).first]+=(*i).second;
+	++i;
+      }
+  }
+
+  void scalebyarray(float* sum) {
+    std::map<unsigned long,float>::iterator i = columns_.begin();    
+    while (i != columns_.end())                    
+      {
+	(*i).second=(*i).second*sum[(*i).first];
+	++i;
+      }
+  }
+  
+
+  void scale(float s) {
+    std::map<unsigned long,float>::iterator i = columns_.begin();    
+    while (i != columns_.end())                    
+      {
+	(*i).second=(*i).second*s;
+	++i;
+      }
+  }
+  
+  
+  void multiplywith(int colindex,int rowindex,vtkpxMatrix*b,vtkpxMatrix*c) {
+    std::map<unsigned long,float>::iterator i = columns_.begin();    
+    float sum=0.0;
+    while (i != columns_.end())                    
+      {
+	sum+=(*i).second*b->GetDirectElement((*i).first,colindex);
+	++i;
+      }
+    c->SetDirectElement(rowindex,colindex,sum);
+  }
+  
+  
+  void multiplywith3vector(int rowindex,vtkpxMatrix*b,vtkpxMatrix*c,float newscale=1.0) {
+    
+    std::map<unsigned long,float>::iterator i = columns_.begin();    
+    float sum[3]={ 0.0,0.0,0.0 };
+    while (i != columns_.end())                    
+      {
+	for (int j=0;j<=2;j++)
+	  sum[j]+=(*i).second*b->GetDirectElement((*i).first,j);
+	++i;
+      }
+    for (int j=0;j<=2;j++)
+      c->SetDirectElement(rowindex,j,sum[j]*newscale);
+  }
+  
+  
+  // ------------------------------------------------------------------------------------
+  //
+  //   E n d   o f   A d d i t i o n s
+  //
+  //
+  // ------------------------------------------------------------------------------------
+  
+};
+
+// ------------------------------------------------------------------------------------
+// This class uses maps to implement 2-dimensional sparse matrices.
+// The default value is an argument of the constructor.
+// ------------------------------------------------------------------------------------
+
+class dvSparseMatrix 
+{
+public:
+  friend class vtkpxSparseMatrix;
+  std::map<unsigned long,dvSparseRow> rows_;
+
+
+  dvSparseMatrix(const float& default_vvalue=0): default_(default_vvalue) { index1_min=0; index1_max=0;}
+  const float&	default_value() const { return default_; }
+  dvSparseRow&	operator[](const unsigned long& k1) 
+  { 
+    // Return reference to row from rows_ (possibly after inserting it).
+
+    /* pair<iterator, bool>
+       insert(const value_type& x)
+       Unique Associative Container Inserts */
+
+    return (*((rows_.insert(std::make_pair(k1,dvSparseRow(*this)))).first)).second;
+  }
+
+
+protected:
+  float		default_;
+
+  unsigned long          index1_min,index1_max;
+  unsigned long          index2_min,index2_max;
+
+
+public:
+
+  // ------------------------------------------------------------------------------------
+  //
+  //
+  //            Additional Functions  Xenios Papademetris Oct 2002
+  //
+  //
+  // ------------------------------------------------------------------------------------
+
+
+
+  unsigned long getminindex1() { return index1_min; }
+  unsigned long getmaxindex1() { return index1_max; }
+  unsigned long getminindex2() { return index2_min; }
+  unsigned long getmaxindex2() { return index2_max; }
+
+  void setindices(int sz[2]) { index1_min=0;index2_min=0; index1_max=sz[0]-1; index2_max=sz[1]-1;}
+  
+
+  unsigned long totalsize() {
+    std::map<unsigned long,dvSparseRow>::iterator i = rows_.begin();    
+    unsigned long sz=0;
+    while (i != rows_.end())                    
+      {
+	dvSparseRow  b=(*i).second;
+	sz+=b.getsize();
+	++i;
+      }
+    return sz;
+  }
+
+
+  int getnumrowelements(int row) {
+    std::map<unsigned long,dvSparseRow>::iterator i = rows_.find(row);    
+    if (i!=rows_.end())
+      return (*i).second.getsize();
+    else
+      fprintf(stderr,"* %d * ",row);
+    
+    return 0;
+  }
+    
+  // ------------------------------------------------------------------------------------
+
+  void cleanup () {
+
+    std::map<unsigned long,dvSparseRow>::iterator i = rows_.begin();    
+    while (i != rows_.end())                    
+      {
+	dvSparseRow  b=(*i).second;
+        b.cleanup();
+	i++;
+      }
+    rows_.clear();
+
+  }
+
+  // ------------------------------------------------------------------------------------
+
+  void updaterange1() {
+    std::map<unsigned long,dvSparseRow>::iterator i = rows_.begin();    
+    index1_min=(*i).first;
+    index1_max=(*i).first;
+    ++i;
+    while (i != rows_.end())                    
+      {
+	
+	if (index1_min >  (*i).first)
+	  index1_min=(*i).first;
+	if (index1_max <  (*i).first)
+	  index1_max=(*i).first;	
+	++i;
+      }
+  }
+
+
+  void updaterange2() {
+
+    std::map<unsigned long,dvSparseRow>::iterator i = rows_.begin();    
+    unsigned long r[2];
+    (*i).second.getrange(r);
+    index2_min=r[0];
+    index2_max=r[1];
+    
+    while (i != rows_.end())                    
+      {
+	(*i).second.getrange(r);
+	if (index2_min>r[0]) index2_min=r[0];
+	if (index2_max<r[1]) index2_max=r[1];
+	i++;
+      }
+  }
+
+
+
+  // ------------------------------------------------------------------------------------
+
+  void print(unsigned long upd=0) {
+    if (upd)
+      {
+	updaterange1();
+	updaterange2();
+      }
+
+    for (unsigned long i=index1_min;i<=index1_max;i++)
+      {
+	fprintf(stderr,"%5d [ ",getnumrowelements(i));
+	for (unsigned long j=index2_min;j<=index2_max;j++)
+	  { 
+	    float a=(*this)[i][j];
+	    if (a!=default_ || j==0)
+	      fprintf(stderr,"%6.3f ",float(a));
+	    else
+	      fprintf(stderr,"...... ");
+	  }
+	fprintf(stderr,"]\n");
+      }
+  }
+
+  void printbw(unsigned long upd=0) {
+    if (upd)
+      {
+	updaterange1();
+	updaterange2();
+      }
+
+    for (unsigned long i=index1_min;i<=index1_max;i++)
+      {
+	fprintf(stderr,"%5d [ ",getnumrowelements(i));
+	for (unsigned long j=index2_min;j<=index2_max;j++)
+	  { 
+	    float a=(*this)[i][j];
+	    if (a!=default_ || j==0)
+	      fprintf(stderr,"*");
+	    else
+	      fprintf(stderr,".");
+	  }
+	fprintf(stderr,"]\n");
+      }
+  }
+
+
+  // ------------------------------------------------------------------------------------
+  void scale(float s) {
+    std::map<unsigned long,dvSparseRow>::iterator i = rows_.begin();    
+    while (i != rows_.end())                    
+      {
+	(*i).second.scale(s);
+	i++;
+      }
+  }
+
+  void multiplywith(int s1[2],vtkpxMatrix* b,vtkpxMatrix* c)
+  {
+    int s2[2],s3[2];
+    b->GetSize(s2);
+    
+    if (s1[1]!=s2[0])
+      {
+	fprintf(stderr,"Cannot multiply matrices bad size! a=%dx%d, b=%dx%d\n",s1[0],s1[1],s2[0],s2[1]);
+	return;
+      }
+    
+    c->Allocate(s1[0],s2[1]);
+    c->GetSize(s3);
+
+
+    std::map<unsigned long,dvSparseRow>::iterator iter = rows_.begin();    
+
+    while (iter!=rows_.end())
+      {
+	for(int col = 0; col < s3[1]; col++) 
+	  (*iter).second.multiplywith(col,(*iter).first,b,c);
+	++iter;
+      }
+  }
+
+
+  void multiplywith3vector(int s1[2],vtkpxMatrix* b,vtkpxMatrix* c)
+  {
+    int s2[2],s3[2];
+    b->GetSize(s2);
+    
+    if (s1[1]!=s2[0] || s2[1]!=3)
+      {
+	fprintf(stderr,"Cannot multiply matrice x col=3 bad size! a=%dx%d, b=%dx%d\n",s1[0],s1[1],s2[0],s2[1]);
+	return;
+      }
+    
+    c->Allocate(s1[0],s2[1]);
+    c->GetSize(s3);
+
+    std::map<unsigned long,dvSparseRow>::iterator iter = rows_.begin();    
+
+    while (iter!=rows_.end())
+      {
+	(*iter).second.multiplywith3vector((*iter).first,b,c);
+	++iter;
+      }
+  }
+
+
+  // ------------------------------------------------------------------------------------
+  //
+  //   E n d   o f   A d d i t i o n s
+  //
+  //
+  // ------------------------------------------------------------------------------------
+  
+};
+
+
+inline void dvSparseElement::operator=(const float& val) {  // E.g. a[k1][k2] = val.
+
+  if (val==row_.matrix_.default_value() &&    // Val is default, erase possible k2 entry from row
+      key2_ !=0  )  // Not Diagonal Element
+    row_.columns_.erase(key2_); 
+  else
+    row_.columns_[key2_] = val;  // Non-default val: store in row[k2].
+}
+
+inline float dvSparseElement::Value() { // Return value of a[k1][k2].
+  if (row_.columns_.count(key2_)>0) // A[k1][k2] explicitely stored: retrieve it.
+    return row_.columns_[key2_]; 
+  else // A[k1][k2] not stored: return default value.
+    return row_.matrix_.default_value();
+}
+
+
+
+
+#endif
+
diff --git a/bioimagesuite30_src/BioImageSuiteMacros.cmake b/bioimagesuite30_src/BioImageSuiteMacros.cmake
new file mode 100644
index 0000000..cc0dbcc
--- /dev/null
+++ b/bioimagesuite30_src/BioImageSuiteMacros.cmake
@@ -0,0 +1,366 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+# --------------------------------------------------------------------------------------------------
+IF (BIOIMAGESUITE3_WRAP_TCL)
+  INCLUDE(${VTK_CMAKE_DIR}/vtkWrapTcl.cmake)
+ENDIF (BIOIMAGESUITE3_WRAP_TCL)
+
+
+
+IF (BIOIMAGESUITE3_USE_JAVA)
+    INCLUDE (${CMAKE_ROOT}/Modules/FindJava.cmake)
+  INCLUDE(${VTK_CMAKE_DIR}/vtkWrapJava.cmake)
+  SET(VTK_WRAP_JAVA3_INIT_DIR "${BIOIMAGESUITE3_SOURCE_DIR}/include")
+  SET(VTK_JAVA_HOME ${BIOIMAGESUITE3_BINARY_DIR}/java/vtk)
+  MAKE_DIRECTORY(${VTK_JAVA_HOME})
+  SET (BISJAVALIST ${BIOIMAGESUITE3_BINARY_DIR}/java/bioimagesuite_javafiles.txt)
+  FILE(WRITE ${BISJAVALIST} "")
+
+  SET (BISJAVACLASSLIST ${BIOIMAGESUITE3_BINARY_DIR}/java/bioimagesuite_javaclassfiles.txt)
+  FILE(WRITE ${BISJAVACLASSLIST} "")
+
+  SET (BIOIMAGESUITE3_ECLIPSE_BISVTK_PATH
+    ${BIOIMAGESUITE3_BINARY_DIR}/bin
+    CACHE PATH
+    "If set then bisvtk.jar will also be copied to this location for the use of Eclipse/Java projects")
+  MARK_AS_ADVANCED(BIOIMAGESUITE_INSTALL_SRCPATH)
+
+
+  
+
+   get_filename_component(BIS_JAVA_INCL ${JAVA_COMPILE} PATH)
+#   INCLUDE_DIRECTORIES(${BIS_JAVA_INCL}/../include)
+#   IF(WIN32)
+#      INCLUDE_DIRECTORIES(${BIS_JAVA_INCL}/../include/win32)
+#      MESSAGE("Info on Win32")
+#   ENDIF(WIN32)
+  MESSAGE("Info using JAVA -- ${VTK_JAVA_HOME} -- ${BISJAVALIST} -- ${BISJAVACLASSLIST} -- ${BIS_JAVA_INCL}/../include")
+
+
+ENDIF (BIOIMAGESUITE3_USE_JAVA)
+
+macro(bis_static LIBNAME)
+  #  message ("Building static library= ${LIBNAME}")
+  ADD_LIBRARY (${LIBNAME} STATIC ${KITSRCS})
+  TARGET_LINK_LIBRARIES (${LIBNAME} ${KITLIBS})
+  install (TARGETS ${LIBNAME} DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/lib)
+endmacro(bis_static)
+
+macro(bis_dynamic LIBNAME)
+  ADD_LIBRARY (${LIBNAME}  ${KITSRCS})
+  TARGET_LINK_LIBRARIES (${LIBNAME} ${KITLIBS})
+  IF (BIOIMAGESUITE3_DEBIAN)
+    SET_TARGET_PROPERTIES(${LIBNAME}TCL PROPERTIES
+      SOVERSION ${BIOIMAGESUITE3_VERSION_MAJOR}.${BIOIMAGESUITE3_VERSION_MINOR}
+      VERSION ${BIOIMAGESUITE3_VERSION_MAJOR}.${BIOIMAGESUITE3_VERSION_MINOR}.${BIOIMAGESUITE3_VERSION_PATCH}
+    )
+  ENDIF(BIOIMAGESUITE3_DEBIAN)
+  install (TARGETS ${LIBNAME} DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/lib)
+endmacro(bis_dynamic)
+
+# --------------------------------------------------------------------------------------------------
+
+macro(bis_executable NAME OUTDIR)
+#  MESSAGE(Info "executable = ${NAME}, OUTDIR=${OUTDIR}")
+  ADD_EXECUTABLE(${NAME} ${NAME}.cpp)
+  TARGET_LINK_LIBRARIES (${NAME} ${KITLIBS})
+
+  if (MSVC)
+    get_target_property(FVAR ${NAME} LOCATION)
+    ADD_CUSTOM_COMMAND(
+      TARGET ${NAME}
+      POST_BUILD
+      COMMAND ${CMAKE_COMMAND} -E copy
+      ARGS ${FVAR} ${EXECUTABLE_OUTPUT_PATH})
+  endif (MSVC)
+
+  install (TARGETS ${NAME} DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/${OUTDIR})
+endmacro(bis_executable)
+
+# --------------------------------------------------------------------------------------------------
+macro(bis_executable_list OUTPUTDIR)
+  FOREACH (item ${KITSRCS})
+    STRING(REGEX REPLACE ".cpp$" "" OUTNAME ${item})
+    bis_executable(${OUTNAME} ${OUTPUTDIR})
+  ENDFOREACH (item ${KITSRCS})
+endmacro(bis_executable_list)
+
+# --------------------------------------------------------------------------------------------------
+macro(bis_wraplibraries LIBNAME)
+  #  message ("Building tcl library: LIBNAME= ${LIBNAME}")
+  IF (VTK_WRAP_TCL)
+    VTK_WRAP_TCL2 (${LIBNAME}TCL TCL_SRCS ${KITSRCS})
+    ADD_LIBRARY (${LIBNAME}TCL ${TCL_SRCS} ${KITTCLSRCS})
+    TARGET_LINK_LIBRARIES (${LIBNAME}TCL ${LIBNAME} ${KITLIBS})
+  
+    IF (BIOIMAGESUITE3_DEBIAN)
+      SET_TARGET_PROPERTIES(${LIBNAME}TCL PROPERTIES
+	SOVERSION ${BIOIMAGESUITE3_VERSION_MAJOR}.${BIOIMAGESUITE3_VERSION_MINOR}
+	VERSION ${BIOIMAGESUITE3_VERSION_MAJOR}.${BIOIMAGESUITE3_VERSION_MINOR}.${BIOIMAGESUITE3_VERSION_PATCH}
+	)
+    ENDIF(BIOIMAGESUITE3_DEBIAN)
+    install (TARGETS ${LIBNAME}TCL DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/lib)
+    
+    #  get_target_property(FVAR ${LIBNAME}TCL LOCATION)
+    
+    #  if (MSVC)
+    #    get_target_property(FVAR ${LIBNAME}TCL LOCATION)
+    #    MESSAGE("FVAR=${FVAR}")
+    #    ADD_CUSTOM_COMMAND(
+    #      TARGET ${LIBNAME}TCL
+    #      POST_BUILD
+    #      COMMAND ${CMAKE_COMMAND} -E copy
+    #      ARGS ${FVAR} ${LIBRARY_OUTPUT_PATH})
+    #  endif (MSVC)
+  ENDIF (VTK_WRAP_TCL)
+
+  IF (NOT KITBASE MATCHES GUI)
+    IF (BIOIMAGESUITE3_USE_JAVA)
+      VTK_WRAP_JAVA3 (${LIBNAME}Java JAVA_SRCS "${KITSRCS}")
+      ADD_LIBRARY (${LIBNAME}Java ${JAVA_SRCS} ${KIIJAVASRCS})
+      TARGET_LINK_LIBRARIES (${LIBNAME}Java ${LIBNAME} ${KITJAVALIBS})
+      
+      IF (BIOIMAGESUITE3_DEBIAN)
+	SET_TARGET_PROPERTIES(${LIBNAME}Java PROPERTIES
+	  SOVERSION ${BIOIMAGESUITE3_VERSION_MAJOR}.${BIOIMAGESUITE3_VERSION_MINOR}
+	  VERSION ${BIOIMAGESUITE3_VERSION_MAJOR}.${BIOIMAGESUITE3_VERSION_MINOR}.${BIOIMAGESUITE3_VERSION_PATCH}
+	  )
+      ENDIF(BIOIMAGESUITE3_DEBIAN)
+      install (TARGETS ${LIBNAME}Java DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/lib)
+
+      if (MSVC)
+	get_target_property(FVAR ${LIBNAME}Java LOCATION)
+#	MESSAGE("FVAR2=${FVAR}")
+	ADD_CUSTOM_COMMAND(
+	  TARGET ${LIBNAME}Java
+	  POST_BUILD
+	  COMMAND ${CMAKE_COMMAND} -E copy
+	  ARGS ${FVAR} ${LIBRARY_OUTPUT_PATH})
+      endif (MSVC)
+
+
+
+      
+      FOREACH (jitem ${JAVA_SRCS})
+	GET_FILENAME_COMPONENT(jitem2 ${jitem} NAME_WE)
+	GET_FILENAME_COMPONENT(extitem ${jitem} EXT)
+
+	STRING(REGEX REPLACE "Java$" "" jitem2 ${jitem2})
+
+#	IF (UNIX)
+	  FILE (APPEND ${BISJAVALIST} "vtk/${jitem2}.java\n")
+	  FILE (APPEND ${BISJAVACLASSLIST} "vtk/${jitem2}.class\n")
+	  FILE (APPEND ${BISJAVACLASSLIST} "vtk/${jitem2}.java\n")
+#	ELSE(UNIX)
+#	  FILE (APPEND ${BISJAVALIST} "${VTK_JAVA_HOME}\\${jitem2}.java\n")
+#	  FILE (APPEND ${BISJAVACLASSLIST} "vtk\\${jitem2}.class\n")
+#	ENDIF(UNIX)
+      ENDFOREACH (jitem ${KITSRCS})
+    ENDIF (BIOIMAGESUITE3_USE_JAVA)
+  ENDIF (NOT KITBASE MATCHES GUI)
+endmacro(bis_wraplibraries)
+
+# --------------------------------------------------------------------------------------------------
+
+macro(bis_libraries LIBNAME)
+  bis_static(${LIBNAME} ${KITSRCS} ${KITLIBS})
+  bis_wraplibraries(${LIBNAME} ${KITSRCS} ${KITTCLSRCS} ${KITLIBS})
+endmacro(bis_libraries)
+
+# --------------------------------------------------------------------------------------------------
+
+macro(bis_sourcelist_full PATHNAME LIBNAME FILEHANDLE EXTRAPATH)
+  
+  #  message("sourcelist, path=${PATHNAME}, lib=${LIBNAME}")
+
+  FILE(APPEND ${FILEHANDLE} "#-------------------------\n# ** ${LIBNAME} \n#-----------------------------\n")
+  
+  SET (COMPLIST 
+    ${KITEXTRAFILES}
+    ${PATHNAME}/CMakeLists.txt
+    )
+  
+  
+  SET (TMPLIST 
+    ${KITSRCS} 
+    ${KITTCLSRCS}
+    )
+
+  #message("sourcelist\n\ncomplist=${COMPLIST}\n\ntmplist=${TMPLIST}")
+
+  FOREACH (item ${TMPLIST})
+    SET(COMPLIST 
+      ${COMPLIST}
+      ${PATHNAME}/${item}
+      )
+    
+    SET (HEADER 0)
+    IF (${item} MATCHES "txx$")
+      STRING(REGEX REPLACE "txx$" "h" HEADER ${item})
+    ELSE(${item} MATCHES "txx$")
+      IF (${item} MATCHES "cxx$")
+	STRING(REGEX REPLACE "cxx$" "h" HEADER ${item})
+      ELSE(${item} MATCHES "cxx$")
+	IF (${item} MATCHES "cpp$")
+	  STRING(REGEX REPLACE "cpp$" "h" HEADER ${item})
+	ELSE(${item} MATCHES "cpp$")
+	  IF (${item} MATCHES "c$")
+	    STRING(REGEX REPLACE "c$" "h" HEADER ${item})
+	  ENDIF(${item} MATCHES "c$")
+	ENDIF(${item} MATCHES "cpp$")
+      ENDIF(${item} MATCHES "cxx$")
+    ENDIF(${item} MATCHES "txx$")
+    #message("\n\t\tforeach item=${item}, header=${HEADER}")
+
+    IF (NOT HEADER)
+      #      message("**************** foreach item=${item}, header=${HEADER} not found")
+    ELSE (NOT HEADER)
+      SET(HEADERNAME ${BIOIMAGESUITE3_SOURCE_DIR}/${PATHNAME}/${HEADER})
+      #message("**************** header=${HEADERNAME}")
+      IF (EXISTS ${HEADERNAME})
+	SET(COMPLIST 
+	  ${COMPLIST}
+	  ${PATHNAME}/${HEADER}
+	  )
+      ELSE (EXISTS ${HEADERNAME})
+	
+      ENDIF (EXISTS ${HEADERNAME})
+    ENDIF (NOT HEADER)
+  ENDFOREACH (item ${TMPLIST})
+
+
+
+  FOREACH (item ${COMPLIST})
+    FILE(APPEND ${FILEHANDLE} "${item}\n")
+  ENDFOREACH (item ${COMPLIST})
+
+
+  SET( COMPLIST2 "")
+  FOREACH (item ${COMPLIST})
+    set(item2 ${EXTRAPATH}/${item})
+    SET(COMPLIST2 
+      ${COMPLIST2}
+      ${item2})
+  ENDFOREACH (item ${COMPLIST})
+  
+  IF (BIOIMAGESUITE3_INSTALL_SOURCE)
+    FOREACH (item ${COMPLIST2})
+      GET_FILENAME_COMPONENT(EPATH ${item} PATH )        
+      #      message("installing ${item}  in ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/${PATHNAME}/${EPATH}")
+      install(FILES ${item}  DESTINATION ${BIOIMAGESUITE3_INSTALL_SRCPATH}/${PATHNAME}/${EPATH})
+    ENDFOREACH (item ${COMPLIST2})
+  ENDIF (BIOIMAGESUITE3_INSTALL_SOURCE)
+endmacro(bis_sourcelist_full)
+
+# --------------------------------------------------------------------------------------------------
+
+macro(bis_sourcelist PATHNAME LIBNAME FILEHANDLE)
+  bis_sourcelist_full(${PATHNAME} ${LIBNAME} ${FILEHANDLE} "..")
+endmacro(bis_sourcelist)
+
+macro(bis_sourcelist_tcl PATHNAME LIBNAME FILEHANDLE)
+  bis_sourcelist_full(${PATHNAME} ${LIBNAME} ${FILEHANDLE} "../..")
+endmacro(bis_sourcelist_tcl)
+# --------------------------------------------------------------------------------------------------
+macro(bis_simplesourcelist LIBNAME FILEHANDLE)
+
+  FILE(APPEND ${FILEHANDLE} "#-------------------------\n# ** ${LIBNAME} \n#-----------------------------\n")
+  FOREACH (item ${KITSRCS})
+    FILE(APPEND ${FILEHANDLE} "${item}\n")
+  ENDFOREACH (item ${COMPLIST})
+
+
+  IF (BIOIMAGESUITE3_INSTALL_SOURCE)
+    install (FILES ${KITSRCS} DESTINATION ${BIOIMAGESUITE3_INSTALL_SRCPATH})
+  ENDIF (BIOIMAGESUITE3_INSTALL_SOURCE)
+endmacro(bis_simplesourcelist)
+# --------------------------------------------------------------------------------------------------
+#  Implicitly defined KITSRCS KITLIBS KITTCLSRCS KITEXTRAFILES
+# --------------------------------------------------------------------------------------------------
+macro(bis_complex PATHNAME LIBNAME  FILEHANDLE)
+
+  bis_static(${LIBNAME})
+  bis_wraplibraries(${LIBNAME})
+  bis_sourcelist(${PATHNAME} ${LIBNAME}  ${FILEHANDLE})
+  
+endmacro(bis_complex)
+
+# --------------------------------------------------------------------------------------------------
+# Macros for the TCL side of things
+# --------------------------------------------------------------------------------------------------
+#  Implicitly defined KITSCRIPTS KITAPPS  
+# --------------------------------------------------------------------------------------------------
+macro(bis_complex_tcl3src PATHNAME SHORTPATH  FILEHANDLE)
+
+  IF (BIOIMAGESUITE3_INSTALL_SOURCE)
+    install(FILES ${KITSCRIPTS} DESTINATION  ${BIOIMAGESUITE3_INSTALL_SRCPATH}/${PATHNAME})
+    install(PROGRAMS ${KITAPPS} DESTINATION  ${BIOIMAGESUITE3_INSTALL_SRCPATH}/${PATHNAME})
+    install(FILES CMakeLists.txt DESTINATION ${BIOIMAGESUITE3_INSTALL_SRCPATH}/${PATHNAME})
+
+
+    SET (TMP  CMakeLists.txt ${KITSCRIPTS} ${KITAPPS} )
+    FILE(APPEND ${FILEHANDLE} "#-------------------------\n# ** ${SHORTPATH} \n#-----------------------------\n")
+    FOREACH (item ${TMP})
+      FILE(APPEND ${FILEHANDLE} "bioimagesuite/${SHORTPATH}/${item}\n")
+    ENDFOREACH (item ${SCRIPTLIST})
+
+
+
+  ENDIF (BIOIMAGESUITE3_INSTALL_SOURCE)
+endmacro(bis_complex_tcl3src PATHNAME SHORTPATH  FILEHANDLE)
+
+
+macro(bis_complex_tcl3 PATHNAME SHORTPATH  FILEHANDLE FILEHANDLE2)
+
+  GET_FILENAME_COMPONENT(SHORTPATH ${PATHNAME} NAME )        
+
+  install(FILES ${KITSCRIPTS}  DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/${SHORTPATH}
+    PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE WORLD_READ WORLD_EXECUTE )
+  install(FILES ${KITAPPS}  DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/${SHORTPATH}
+    PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE WORLD_READ WORLD_EXECUTE )
+
+  SET (TMP  ${KITSCRIPTS} ${KITAPPS} )
+  FILE(APPEND ${FILEHANDLE} "#-------------------------\n# ** ${SHORTPATH} \n#-----------------------------\n")
+  FOREACH (item ${TMP})
+    FILE(APPEND ${FILEHANDLE} "${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/${SHORTPATH}/${item}\n")
+  ENDFOREACH (item ${SCRIPTLIST})
+
+
+  bis_complex_tcl3src(${PATHNAME} ${SHORTPATH} ${FILEHANDLE2})
+
+  
+
+endmacro(bis_complex_tcl3)
+
+
+macro(bis_complex_tcl PATHNAME   FILEHANDLE FILEHANDLE2 )
+  GET_FILENAME_COMPONENT(SHORTPATH ${PATHNAME} NAME )        
+  bis_complex_tcl3(${PATHNAME} ${SHORTPATH} ${FILEHANDLE} ${FILEHANDLE2})
+endmacro(bis_complex_tcl)
+
diff --git a/bioimagesuite30_src/BioImageSuite_Description.txt b/bioimagesuite30_src/BioImageSuite_Description.txt
new file mode 100644
index 0000000..9248cb3
--- /dev/null
+++ b/bioimagesuite30_src/BioImageSuite_Description.txt
@@ -0,0 +1,36 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+BioImage Suite is a medical image analysis software suite distributed under
+the GNU GPL v2.
+
+X. Papademetris, M. Jackowski, A. Joshi, D. Scheinost, R.T. Constable, and
+L.H Staib. BioImage Suite: An integrated medical image analysis suite,
+Section of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School
+of Medicine. http://www.bioimagesuite.org.
+
+
diff --git a/bioimagesuite30_src/BioImageSuite_License.txt b/bioimagesuite30_src/BioImageSuite_License.txt
new file mode 100644
index 0000000..40f2766
--- /dev/null
+++ b/bioimagesuite30_src/BioImageSuite_License.txt
@@ -0,0 +1,340 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+BioImage Suite License
+----------------------
+
+BioImage Suite is distributed under the GPL v2 (see below)
+
+Additional Notes:
+
+   1. BioImage Suite is not FDA approved for clinical use. 
+
+   2. BioImage Suite is provided freely for research purposes.
+
+   3. If you use BioImage Suite extensively for your research, we request
+   that you mail us a letter (preferably on letterhead) acknowledging
+   this. Such letters are useful in obtaining support for continuing
+   support and maintenance of the software.  
+
+   4. If using BioImage Suite in a publication please reference this
+   properly as:
+
+   X. Papademetris, M. Jackowski, N. Rajeevan, R.T. Constable, and L.H
+   Staib. BioImage Suite: An integrated medical image analysis suite,
+   Section of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale
+   School of Medicine. http://www.bioimagesuite.org.
+
+--------------------------------------------------------------------------------
+The following is the GPL v2 license as available from 
+    http://www.gnu.org/licenses/gpl.txt
+--------------------------------------------------------------------------------
+
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+--------------------------------------------------------------------------------
+
+
diff --git a/bioimagesuite30_src/BioImageSuite_ShortLicense.txt b/bioimagesuite30_src/BioImageSuite_ShortLicense.txt
new file mode 100644
index 0000000..c3958f2
--- /dev/null
+++ b/bioimagesuite30_src/BioImageSuite_ShortLicense.txt
@@ -0,0 +1,50 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+BioImage Suite is distributed under the GPL v2.
+
+Additional Notes:
+
+1. BioImage Suite is not FDA approved for clinical use. 
+
+2. BioImage Suite is provided freely for research purposes.
+
+3. If you use BioImage Suite extensively for your research, we request
+that you mail us a letter (preferably on letterhead) acknowledging
+this. Such letters are useful in obtaining support for continuing
+support and maintenance of the software.  
+
+4. If using BioImage Suite in a publication please reference this
+properly as:
+
+X. Papademetris, M. Jackowski, A. Joshi, D. Scheinost, R.T. Constable, and L.H
+Staib. BioImage Suite: An integrated medical image analysis suite,
+Section of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale
+School of Medicine. http://www.bioimagesuite.org.
+
+
+
diff --git a/bioimagesuite30_src/CMakeLists.txt b/bioimagesuite30_src/CMakeLists.txt
new file mode 100644
index 0000000..8df87be
--- /dev/null
+++ b/bioimagesuite30_src/CMakeLists.txt
@@ -0,0 +1,197 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#
+#  Master File for BioImage Suite build
+#
+#
+# Set the project name.
+#
+cmake_minimum_required(VERSION 2.6)
+if( COMMAND cmake_policy )
+  cmake_policy( VERSION 2.6 )
+endif( COMMAND cmake_policy )
+
+PROJECT (BIOIMAGESUITE3)
+
+SET (BIOIMAGESUITE3_VERSION_MAJOR 3)
+SET (BIOIMAGESUITE3_VERSION_MINOR 0)
+SET (BIOIMAGESUITE3_VERSION_PATCH 1)
+SET (BIOIMAGESUITE3_STRING_VERSION  "${BIOIMAGESUITE_VERSION_MAJOR}${BIOIMAGESUITE_VERSION_MINOR}${BIOIMAGESUITE_VERSION_PATCH}")
+#SET (BIOIMAGESUITE3_JAVASOURCES CACHE STRING "")
+
+
+
+
+
+# Compiler Specific Things
+# -------------------------------------------------------------------------------------
+IF(CMAKE_COMPILER_2005)
+  ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE)
+#  SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /NODEFAULTLIB:msvcrt.lib ")
+ENDIF(CMAKE_COMPILER_2005)
+
+IF (UNIX)
+IF( CMAKE_COMPILER_IS_GNUCXX )
+  set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC" )
+  set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC" )
+ENDIF( CMAKE_COMPILER_IS_GNUCXX )
+ENDIF (UNIX)
+# ------------------------------------------------------------------------------------
+
+
+# Excluded TCL Code 
+
+INCLUDE (${CMAKE_ROOT}/Modules/FindVTK.cmake)
+INCLUDE(${VTK_CMAKE_DIR}/vtkWrapTcl.cmake)
+
+IF (BIOIMAGESUITE3_USE_PYTHON)
+  INCLUDE(${VTK_CMAKE_DIR}/vtkWrapPython.cmake)
+ENDIF (BIOIMAGESUITE3_USE_PYTHON)
+# Excluded TCL Code 
+
+#
+# Assume everything is set up correctly for build.
+#
+# If some requirements are not met, set it to 0.
+# In that case, the build won't be done.
+#
+
+SET (BIOIMAGESUITE3_CAN_BUILD 1)
+
+#
+# Load CMake commands that you probably should not modify.
+#
+INCLUDE (${BIOIMAGESUITE3_SOURCE_DIR}/CMakeOptions.cmake)
+INCLUDE (${BIOIMAGESUITE3_SOURCE_DIR}/BioImageSuiteMacros.cmake)
+#
+# If everything is OK, then go into the sub directories and build.
+#
+
+IF (BIOIMAGESUITE3_CAN_BUILD)
+  #
+  # Here is where you can list the sub-directories holding your local 
+  # classes. Sorting classes by 'package' type like VTK does (Common, 
+  # Rendering, Filtering, Imaging, IO, etc.) is a good thing and prevents 
+  # numerous dependencies problems.
+  #
+
+  INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/include)
+  INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_BINARY_DIR})
+  INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/numerics)
+  INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+
+  SUBDIRS (
+    include
+    numerics
+    pxtklib
+    ${VVLINK_API}
+    Common
+    database
+    Graphics
+    Legacy
+    Imaging
+    Registration
+    Segmentation
+    GUI	   
+    mpjCommon
+    mpjLevelset
+    mpjDiffusion
+    ${BIOIMAGESUITE3_APPLICATIONS}
+    ${STEREOVISION_SOURCE}
+    ${DBFEM_SOURCE} 
+    Connectivity
+#    ShapeModels
+# Excluded TCL Code 
+)
+
+if (BIOIMAGESUITE3_USE_SYSTEM_NIFTI)
+  include_directories( /usr/include/nifti/ )
+endif (BIOIMAGESUITE3_USE_SYSTEM_NIFTI)
+
+if (BIOIMAGESUITE3_USE_SYSTEM_OPENIGTLINK)
+     include_directories( /usr/include/openigtlink/ )
+     include_directories( /usr/include/openigtlink/igtlutil )
+else (BIOIMAGESUITE3_USE_SYSTEM_OPENIGTLINK)
+   subdirs (
+      igtlutil
+   )
+endif (BIOIMAGESUITE3_USE_SYSTEM_OPENIGTLINK)
+
+IF(BIOIMAGESUITE3_MOUSEREG)
+add_subdirectory(DemonsRegistration)
+ENDIF(BIOIMAGESUITE3_MOUSEREG)
+
+add_subdirectory(installtools)
+# Excluded TCL Code 
+add_subdirectory(bioimagesuite)
+
+IF (BIOIMAGESUITE3_USE_JAVA)
+  add_subdirectory(java)
+ENDIF(BIOIMAGESUITE3_USE_JAVA)
+
+
+CONFIGURE_FILE(
+    ${BIOIMAGESUITE3_SOURCE_DIR}/include/vtkbisConfigure.h.in 
+    ${BIOIMAGESUITE3_BINARY_DIR}/bioimagesuite_settings.h
+  )
+
+  # -------------------------------------------------------------------------------------------------
+  # Make Install Stuff
+# -------------------------------------------------------------------------------------------------
+
+set(KIT "root")
+set(KITTCLSRCS)
+SET (KITSRCS 
+  CMakeLists.txt
+  BioImageSuite_License.txt
+  BioImageSuite_ShortLicense.txt
+  CMakeOptions.cmake
+  CPackOptions.cmake
+  BioImageSuiteMacros.cmake
+  CompilingBioImageSuite.html
+  BioImageSuite_Description.txt
+  CTestCustom.cmake.in
+)
+
+install(FILES BioImageSuite_License.txt DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH})
+
+
+bis_simplesourcelist("root" ${FILELIST})
+
+
+
+# Cpack stuff
+IF (BIOIMAGESUITE3_CREATE_INSTALLER)
+  INCLUDE (${BIOIMAGESUITE3_SOURCE_DIR}/CPackOptions.cmake)
+ENDIF (BIOIMAGESUITE3_CREATE_INSTALLER)
+
+
+ENDIF (BIOIMAGESUITE3_CAN_BUILD)
+
+
+
diff --git a/bioimagesuite30_src/CMakeOptions.cmake b/bioimagesuite30_src/CMakeOptions.cmake
new file mode 100644
index 0000000..8c74f50
--- /dev/null
+++ b/bioimagesuite30_src/CMakeOptions.cmake
@@ -0,0 +1,573 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#Force install prefix
+IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+  IF (WIN32)
+    SET (CMAKE_INSTALL_PREFIX "c:/yale" CACHE PATH "Install Path" FORCE)
+  ELSE (WIN32)
+    SET (CMAKE_INSTALL_PREFIX  "/usr/local" CACHE PATH "Install Path" FORCE)
+  ENDIF (WIN32)
+ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+
+SET (BIOIMAGESUITE3_INSTALL_EXTRAPATH  
+  bioimagesuite${BIOIMAGESUITE3_VERSION_MAJOR}${BIOIMAGESUITE3_VERSION_MINOR}
+  CACHE PATH
+  "Extra path for bioimagesuite installation (appended to CMAKE_INSTALL_PREFIX")
+MARK_AS_ADVANCED(BIOIMAGESUITE3_INSTALL_EXTRAPATH)
+
+# Excluded TCL Code 
+
+# Windows Stuff
+IF (WIN32)
+STRING(REGEX REPLACE "/" "\\\\"  BIOIMAGESUITE3_BINARY_DIR_BAT ${BIOIMAGESUITE3_BINARY_DIR})
+STRING(REGEX REPLACE "/" "\\\\"  BIOIMAGESUITE3_SOURCE_DIR_BAT ${BIOIMAGESUITE3_SOURCE_DIR})
+# Excluded TCL Code 
+STRING(REGEX REPLACE "/" "\\\\"  EXECUTABLE_OUTPUT_PATH_BAT ${EXECUTABLE_OUTPUT_PATH})
+STRING(REGEX REPLACE "/" "\\\\"  LIBRARY_OUTPUT_PATH_BAT ${LIBRARY_OUTPUT_PATH})
+STRING(REGEX REPLACE "/" "\\\\"  VTK_DIR_BAT ${VTK_DIR})
+# end of windows stuff
+ENDIF(WIN32)
+
+
+# Excluded TCL Code 
+# ------------------------------------
+#    Common Link Libaries
+# ------------------------------------
+
+IF (WIN32)
+  SET (BUILD TYPE "Release")
+  SET (CMAKE_CXX_WARNING_LEVEL "1")
+ENDIF (WIN32)
+
+SET (BIOIMAGESUITE3_COMMON_LIBS
+  vtkIO
+  vtkHybrid
+  vtkCommon
+  vtkCommonTCL
+  vtkRendering
+  vtkFiltering
+  vtkImaging
+  vtkGraphics
+  vtkGraphicsTCL
+  vtkRendering
+  vtkRenderingTCL
+  vtkWidgets
+  vtkWidgetsTCL
+
+)
+
+
+SET (BIOIMAGESUITE3_COMMON_JAVALIBS
+  vtkImaging
+  vtkImagingJava
+  vtkGraphics
+  vtkGraphicsJava
+  vtkFiltering
+  vtkFilteringJava
+  vtkCommon
+  vtkCommonJava
+)
+
+
+IF (NOT VTK_USE_SYSTEM_ZLIB)
+   SET (BIOIMAGESUITE3_COMMON_LIBS
+      ${BIOIMAGESUITE3_COMMON_LIBS}
+      ${VTK_ZLIB_LIBRARIES}
+   )
+ENDIF (NOT VTK_USE_SYSTEM_ZLIB)
+
+# -----------------------------------------------------------------------------------------------
+
+SET (BIOIMAGESUITE_USING_MINGW 0)
+SET (BIOIMAGESUITE_USING_VS 0)
+SET (LIBRARY_OUTPUT_PATH ${BIOIMAGESUITE3_BINARY_DIR}/lib CACHE PATH "Single output directory for building all libraries.")
+
+
+SET (EXECUTABLE_OUTPUT_PATH ${BIOIMAGESUITE3_BINARY_DIR}/bin CACHE PATH "Single output directory for building all executables.")
+
+
+IF (UNIX)
+  SET (LIBEXTRA  "")
+  IF (${CMAKE_CXX_FLAGS} MATCHES ".+m32.+")
+    SET (LIBEXTRA  "")
+  ELSE(${CMAKE_CXX_FLAGS} MATCHES ".+m32.+")
+    SET (LIBEXTRA ${CMAKE_SYSTEM_PROCESSOR})
+  ENDIF(${CMAKE_CXX_FLAGS} MATCHES ".+m32.+")
+
+ELSE(UNIX)
+  GET_FILENAME_COMPONENT(CL ${CMAKE_CXX_COMPILER} NAME ) 
+  IF (${CL} MATCHES "cl")
+    SET (BIOIMAGESUITE_USING_VS 1)
+  ELSE (${CL} MATCHES "cl")
+    SET (BIOIMAGESUITE_USING_MINGW 1)
+  ENDIF (${CL} MATCHES "cl")
+ENDIF(UNIX)
+
+#MESSAGE("Copying dynamic libraries to ${BIOIMAGESUITE3_COPYLIBPATH} = ${BIOIMAGESUITE3_SOURCE_DIR}/bioimagesuite/lib")
+
+
+SET (BIS_UNIXBUILD 0)
+IF (UNIX)
+   SET (BIS_UNIXBUILD 1)
+ENDIF(UNIX)
+
+IF (BIOIMAGESUITE_USING_MINGW)
+   SET (BIS_UNIXBUILD 1)
+ENDIF (BIOIMAGESUITE_USING_MINGW)
+
+# -----------------------------------------------------------------------------------------------
+IF(UNIX AND NOT APPLE)
+OPTION(BIOIMAGESUITE3_INSTALL_ICONS
+  "Install Icons for GNOME/KDE"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_INSTALL_ICONS)
+ENDIF(UNIX AND NOT APPLE)
+# -----------------------------------------------------------------------------------------------
+
+
+# -----------------------------------------------------------------------------------------------
+OPTION(BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE
+  "Use MySQL Database Module"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_MYSQL_DATABASE_MODULE)
+
+
+
+OPTION(BIOIMAGESUITE3_USE_JAVA
+  "Create JAVA Libraries -- experimental"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_JAVA)
+
+
+OPTION(BIOIMAGESUITE3_MOUSEREG
+  "Build Whole Body Mouse Registration Module"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_MOUSEREG)
+
+OPTION(BIOIMAGESUITE3_USE_QT
+  "Build QT Modules"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_QT)
+
+
+
+
+
+# -----------------------------------------------------------------------------------------------
+#
+# Flags for optional packages 
+#
+OPTION(BIOIMAGESUITE3_INSTALL_SOURCE
+  "Create a source code installation as well"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_INSTALL_SOURCE)
+
+OPTION(BIOIMAGESUITE3_CREATE_INSTALLER
+  "Use CPACK or Inno Setup to generate an installer"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_CREATE_INSTALLER)
+
+OPTION(BIOIMAGESUITE3_PACK_BASE
+  "Include base directories (e.g. vtk,itk) in  CPACK installer to create a complete installer"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_PACK_BASE)
+
+# Excluded TCL Code 
+
+OPTION(BIOIMAGESUITE3_USE_CUDA
+  "Enable CUDA-dependent code in BioImage Suite"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_CUDA)
+
+OPTION(BIOIMAGESUITE3_USE_CUDA_ADVANCED
+  "Enable CUDA Capability 1.2 dependent code in BioImage Suite"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_CUDA)
+
+OPTION(BIOIMAGESUITE3_USE_STEREO
+  "Enable Stereo Vision -dependent code in BioImage Suite"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_STEREO)
+
+OPTION(BIOIMAGESUITE3_USE_DBFEM
+  "Enable Dominique's FEM -dependent code in BioImage Suite"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_DBFEM)
+
+OPTION(BIOIMAGESUITE3_USE_VVLINK
+  "Use New Vector Vision Link (7.8)"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_VVLINK)
+
+OPTION(BIOIMAGESUITE3_USE_ABAQUS
+  "ABAQUS is available"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_ABAQUS)
+
+OPTION(BIOIMAGESUITE3_USE_CPPUNIT
+  "CPPUNIT is available"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_CPPUNIT)
+
+OPTION(BIOIMAGESUITE3_USE_APPS
+  "Enable BINARY Executable Legacy Applications"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_APPS)
+
+OPTION(BIOIMAGESUITE3_USE_SYSTEM_LIBS
+  "Use system libraries for Lapack instead of custom ones"
+  OFF)
+
+OPTION(BIOIMAGESUITE3_USE_SYSTEM_NIFTI
+  "Use system libraries for NIFTI instead of custom ones"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_SYSTEM_NIFTI)
+
+OPTION(BIOIMAGESUITE3_USE_SYSTEM_OPENIGTLINK
+  "Use system libraries for OpenIGTLink instead of custom ones"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_SYSTEM_OPENIGTLINK)
+
+OPTION(BIOIMAGESUITE3_USE_SYSTEM_NEWMAT
+  "Use system libraries for NewMAT instead of custom ones"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_USE_SYSTEM_NEWMAT)
+
+
+OPTION(BIOIMAGESUITE3_DEBIAN
+  "Use configuration for Debian/Ubuntu packaging"
+  OFF)
+MARK_AS_ADVANCED(BIOIMAGESUITE3_DEBIAN)
+
+
+IF (BIOIMAGESUITE3_DEBIAN)
+  MESSAGE("++ Using Debian Configuration rules")
+ENDIF (BIOIMAGESUITE3_DEBIAN)
+# -------------------------------------------------
+# Package naming
+OPTION(BIOIMAGESUITE3_SET_COMPILER_NAME
+  "Set name for the compiler used"
+  "")
+MARK_AS_ADVANCED(BIOIMAGESUITE3_SET_COMPILER_NAME)
+
+
+FIND_FILE(BIOIMAGESUITE3_VALGRIND "valgrind")
+IF (BIOIMAGESUITE3_VALGRIND)
+SET(MEMORY_CHECKCOMMAND ${BIOIMAGESUITE3_VALGRIND} FILEPATH)
+ENDIF (BIOIMAGESUITE3_VALGRIND)
+
+IF(BIOIMAGESUITE3_SET_COMPILER_NAME)
+ FIND_FILE(BIOIMAGESUITE3_COMPILER "g++")
+ELSE(BIOIMAGESUITE3_SET_COMPILER_NAME)
+  SET (BIOIMAGESUITE3_COMPILER ${CMAKE_CXX_COMPILER})
+ENDIF(BIOIMAGESUITE3_SET_COMPILER_NAME)
+
+# ------------ BIOIMAGESUITE3 GDCM MODULE ---------------
+FIND_PACKAGE(GDCM REQUIRED)
+INCLUDE(${GDCM_USE_FILE})
+#INCLUDE_DIRECTORIES(${GDCM_INCLUDE_DIRS}/../../include/gdcm-2.0)
+
+
+# ------------ BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE ---------------
+
+# Fix this for multiple platforms eventually
+IF(BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE)
+ FIND_PATH(MYSQL_INCLUDE_DIR mysql.h)
+IF (WIN32)
+ FIND_FILE(MYSQLLIB "mysqlclient.lib")
+ENDIF(WIN32)
+ENDIF(BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE)
+
+
+IF (BIOIMAGESUITE3_USE_CUDA)
+  IF (${CMAKE_VERSION} MATCHES "2.8.*")
+    MESSAGE("Using New FindCUDA.cmake from CMAKE")
+    INCLUDE (${CMAKE_ROOT}/Modules/FindCUDA.cmake)
+  ELSE (${CMAKE_VERSION} MATCHES "2.8.*")
+    MESSAGE("Using Legacy FindCuda.cmake")
+    INCLUDE ( ${BIOIMAGESUITE3_SOURCE_DIR}/CMake/cuda/FindCuda.cmake)
+  ENDIF (${CMAKE_VERSION} MATCHES "2.8.*")
+
+  IF (WIN32)
+    FIND_PATH(CUDA_LINK_LIBRARIES c:/cuda )
+  ELSE (WIN32)
+    FIND_PATH(CUDA_LINK_LIBRARIES /usr/local/cuda/lib)
+  ENDIF(WIN32)
+  
+  LINK_DIRECTORIES(${CUDA_LINK_LIBRARIES})
+
+  INCLUDE_DIRECTORIES(${CUDA_TOOLKIT_INCLUDE}/../include)
+  INCLUDE_DIRECTORIES(${CUDA_SDK_ROOT_DIR}/shared/inc)
+  INCLUDE_DIRECTORIES(${CUDA_SDK_ROOT_DIR}/C/common/inc)
+#  LINK_DIRECTORIES(${CUDA_SDK_ROOT_DIR}/C/common/lib)
+#  LINK_DIRECTORIES(${CUDA_SDK_ROOT_DIR}/shared/lib)
+
+  SET (BIOIMAGESUITE3_COMMON_LIBS
+    ${BIOIMAGESUITE3_COMMON_LIBS}
+    cudart
+    cufft 
+    cusparse
+    cublas
+    cuda
+  )
+# shrUtils32
+
+ENDIF (BIOIMAGESUITE3_USE_CUDA)
+
+
+#------------- STEREO VISION ----------------
+IF (BIOIMAGESUITE3_USE_STEREO)
+  SET (STEREOVISION_SOURCE StereoVision)
+ELSE (BIOIMAGESUITE3_USE_STEREO)
+  SET (STEREOVISION_SOURCE)
+ENDIF (BIOIMAGESUITE3_USE_STEREO)
+
+
+#------------- FEM ----------------
+IF (BIOIMAGESUITE3_USE_DBFEM)
+  SET (DBFEM_SOURCE dbFEM)
+ELSE (BIOIMAGESUITE3_USE_DBFEM)
+  SET (DBFEM_SOURCE)
+ENDIF (BIOIMAGESUITE3_USE_DBFEM)
+
+
+# ------------ BIOIMAGESUITE3_USE_APPS ---------------
+
+IF(BIOIMAGESUITE3_INSTALL_SOURCE)
+  SET (BIOIMAGESUITE3_INSTALL_SRCPATH  
+    bioimagesuite${BIOIMAGESUITE3_VERSION_MAJOR}${BIOIMAGESUITE3_VERSION_MINOR}_${BIOIMAGESUITE3_VERSION_PATCH}_src
+    CACHE PATH
+    "Extra path for bioimagesuite3 source installation (appended to CMAKE_INSTALL_PREFIX")
+  MARK_AS_ADVANCED(BIOIMAGESUITE_INSTALL_SRCPATH)
+ENDIF(BIOIMAGESUITE3_INSTALL_SOURCE)
+
+# ------------ BIOIMAGESUITE3_USE_APPS ---------------
+
+IF (BIOIMAGESUITE3_USE_APPS)
+  SET (BIOIMAGESUITE3_APPLICATIONS oldapps )
+ELSE (BIOIMAGESUITE3_USE_APPS)
+  SET (BIOIMAGESUITE3_APPLICATIONS )	
+ENDIF (BIOIMAGESUITE3_USE_APPS)
+
+# ------------ Include VTK --------------------
+
+INCLUDE (${CMAKE_ROOT}/Modules/FindVTK.cmake)
+IF (USE_VTK_FILE)
+  INCLUDE (${USE_VTK_FILE})
+ELSE (USE_VTK_FILE)
+  SET (BIOIMAGESUITE3_CAN_BUILD 0)
+ENDIF (USE_VTK_FILE)
+
+# ------------ Include CLAPACK -----------------
+IF(BIOIMAGESUITE3_USE_SYSTEM_LIBS)
+  SET(CLAPACK_LIBRARIES lapack blas f2c)
+  SET (BIOIMAGESUITE3_COMMON_LIBS
+    ${BIOIMAGESUITE3_COMMON_LIBS}
+    ${CLAPACK_LIBRARIES})
+  MESSAGE(INFO
+    " Using System Lapack Library (if installed) ")
+ELSE(BIOIMAGESUITE3_USE_SYSTEM_LIBS)
+  FIND_PACKAGE(CLAPACK)
+  IF(CLAPACK_FOUND)
+    INCLUDE(${CLAPACK_USE_FILE})
+    SET (BIOIMAGESUITE3_COMMON_LIBS
+      ${BIOIMAGESUITE3_COMMON_LIBS}
+      ${CLAPACK_LIBRARIES})
+  ELSE(CLAPACK_FOUND)
+    MESSAGE(FATAL_ERROR
+      "Please specify CLAPACK_DIR ")
+    SET (BIOIMAGESUITE3_CAN_BUILD 0)
+  ENDIF(CLAPACK_FOUND)
+ENDIF(BIOIMAGESUITE3_USE_SYSTEM_LIBS)
+
+
+
+# ------------ Include VVLINK_NEW --------------------
+IF (BIOIMAGESUITE3_USE_VVLINK)
+    SET (VVLINK_API vvlcppapi5)
+ENDIF (BIOIMAGESUITE3_USE_VVLINK)
+
+# ------------ Include ITK  --------------------
+ FIND_PACKAGE(ITK REQUIRED)
+ IF(ITK_FOUND)
+    LINK_DIRECTORIES(${ITK_LIBRARY_DIRS})
+    SET (BIOIMAGESUITE3_COMMON_LIBS
+      ${BIOIMAGESUITE3_COMMON_LIBS}
+      ${ITK_LIBRARIES})
+  ELSE(ITK_FOUND)	
+    MESSAGE(FATAL_ERROR
+      "Please specify ITK_DIR ")
+    SET (BIOIMAGESUITE3_CAN_BUILD 0)
+  ENDIF(ITK_FOUND)
+
+
+# ------------ Standard Stuff from Here on (from vtkMY)  --------------------
+# Build shared libs ?
+# Defaults to the same VTK setting.
+# ---------------------------------------------------------------------------
+IF (USE_VTK_FILE)
+  # Standard CMake option for building libraries shared or static by default.
+  OPTION(BUILD_SHARED_LIBS 
+    "Build with shared libraries." 
+    ${VTK_BUILD_SHARED_LIBS})
+  SET(BIOIMAGESUITE3_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
+ENDIF (USE_VTK_FILE)
+
+
+#
+# -------------------------------------------------------------------------------------------------
+# Default Output Paths
+# -------------------------------------------------------------------------------------------------
+
+SET (CMAKE_VERBOSE_MAKEFILE:BOOL TRUE)
+
+# -------------------------------------------------------------------------------------------------
+# Print some information to a common file
+# -------------------------------------------------------------------------------------------------
+SET (INFOFILE ${BIOIMAGESUITE3_BINARY_DIR}/bioimagesuite_settings.tcl)
+FILE(WRITE  ${INFOFILE} "#BioImage Suite Build Directories\n")
+FILE(APPEND ${INFOFILE} "set cmake(VTK_DIR) \"" ${VTK_DIR} "\"\n")
+FILE(APPEND ${INFOFILE} "set cmake(ITK_DIR) \"" ${ITK_DIR} "\"\n")
+FILE(APPEND ${INFOFILE} "set cmake(CXX) \"" ${CMAKE_CXX_COMPILER} "\"\n")
+FILE(APPEND ${INFOFILE} "set cmake(CXXFLAGS) \"" ${CMAKE_CXX_FLAGS} "\"\n")
+FILE(APPEND ${INFOFILE} "set cmake(OS)  \""  ${CMAKE_SYSTEM_NAME}  "\"\n")
+FILE(APPEND ${INFOFILE} "set cmake(PROC)  \""  ${CMAKE_SYSTEM_PROCESSOR}  "\"\n")
+FILE(APPEND ${INFOFILE} "set cmake(INSTALLPREFIX)  \""  ${CMAKE_INSTALL_PREFIX}  "\"\n")
+FILE(APPEND ${INFOFILE} "set cmake(VERSION)  \"${BIOIMAGESUITE3_VERSION_MAJOR}${BIOIMAGESUITE3_VERSION_MINOR}${BIOIMAGESUITE3_VERSION_PATCH}\"\n")
+
+
+
+
+IF (APPLE)
+  IF (VTK_USE_CARBON)
+    FILE(APPEND ${INFOFILE} "set cmake(OSEXTRA) Carbon")
+  ELSE (VTK_USE_CARBON)
+    FILE(APPEND ${INFOFILE} "set cmake(OSEXTRA) X11")	
+  ENDIF (VTK_USE_CARBON)
+ELSE (APPLE)
+  FILE(APPEND ${INFOFILE} "set cmake(OSEXTRA) \"\"")	
+ENDIF (APPLE)
+	
+FILE(APPEND ${INFOFILE} "\nset cmake(SYSTEM) \"" ${CMAKE_SYSTEM}  "\"\n")
+
+SET (FILELIST ${BIOIMAGESUITE3_BINARY_DIR}/cppfilelist.tcl)
+FILE(WRITE  ${FILELIST} "#CPP File List\n")
+FILE(APPEND ${FILELIST} "#Path\n")
+IF (BIOIMAGESUITE3_DEBIAN)
+   FILE(APPEND ${FILELIST} "${BIOIMAGESUITE3_SOURCE_DIR}/debian/tmp/${CMAKE_INSTALL_PREFIX}/${BIOIMAGESUITE3_INSTALL_SRCPATH}\n")
+ELSE (BIOIMAGESUITE3_DEBIAN)
+   FILE(APPEND ${FILELIST} "${CMAKE_INSTALL_PREFIX}/${BIOIMAGESUITE3_INSTALL_SRCPATH}\n")
+ENDIF(BIOIMAGESUITE3_DEBIAN)
+FILE(APPEND ${FILELIST} "#Files\n")
+
+SET (FILELIST2 ${BIOIMAGESUITE3_BINARY_DIR}/tclfilelist.tcl)
+FILE(WRITE  ${FILELIST2} "#TCL File List\n")
+FILE(APPEND ${FILELIST2} "#Path\n")
+IF (BIOIMAGESUITE3_DEBIAN)
+   FILE(APPEND ${FILELIST2} "${BIOIMAGESUITE3_SOURCE_DIR}/debian/tmp/${CMAKE_INSTALL_PREFIX}\n")
+ELSE (BIOIMAGESUITE3_DEBIAN)
+   FILE(APPEND ${FILELIST2} "${CMAKE_INSTALL_PREFIX}\n")
+ENDIF(BIOIMAGESUITE3_DEBIAN)
+FILE(APPEND ${FILELIST2} "#Files\n")
+
+SET (SCRIPTFILELIST ${BIOIMAGESUITE3_BINARY_DIR}/scriptfiles.txt)
+FILE(WRITE  ${SCRIPTFILELIST} "#SCRIPT File List\n")
+FILE(APPEND ${SCRIPTFILELIST} "#Path\n")
+IF (BIOIMAGESUITE3_DEBIAN)
+   FILE(APPEND ${SCRIPTFILELIST} "${BIOIMAGESUITE3_SOURCE_DIR}/debian/tmp/${CMAKE_INSTALL_PREFIX}/${BIOIMAGESUITE3_INSTALL_EXTRAPATH}\n")
+ELSE (BIOIMAGESUITE3_DEBIAN)
+   FILE(APPEND ${SCRIPTFILELIST} "${CMAKE_INSTALL_PREFIX}/${BIOIMAGESUITE3_INSTALL_EXTRAPATH}\n")
+ENDIF(BIOIMAGESUITE3_DEBIAN)
+FILE(APPEND ${SCRIPTFILELIST} "#VTK_DIR\n")
+FILE(APPEND ${SCRIPTFILELIST} "${VTK_DIR}\n")
+FILE(APPEND ${SCRIPTFILELIST} "#ITK_DIR\n")
+FILE(APPEND ${SCRIPTFILELIST} "${ITK_DIR}\n")
+FILE(APPEND ${SCRIPTFILELIST} "#Files\n")
+
+
+
+IF (BIOIMAGESUITE_USING_VS)
+  STRING(REGEX REPLACE "\\\\" "/" WIN_PATH "${EXECUTABLE_OUTPUT_PATH}")
+ENDIF(BIOIMAGESUITE_USING_VS)
+
+
+
+
+SET (F3 ${BIOIMAGESUITE3_BINARY_DIR}/bioimagesuitepostinstall.cmake)
+FILE(WRITE   ${F3} "#${CMAKE_INSTALL_PREFIX}\n")
+FILE(APPEND  ${F3} "MESSAGE(\"++ Executing BioImage Suite Postinstall Script\")\n\n")
+
+FILE(APPEND ${F3} "execute_process(\n")
+FILE(APPEND ${F3} "COMMAND ${BIOIMAGESUITE3_BINARY_DIR}/bisexec\n")
+FILE(APPEND ${F3} "${BIOIMAGESUITE3_SOURCE_DIR}/installtools/bis_fix.tcl ${BIOIMAGESUITE3_BINARY_DIR}/cppfilelist.tcl ${BIOIMAGESUITE3_BINARY_DIR}/tclfilelist.tcl ${BIOIMAGESUITE3_BINARY_DIR}/scriptfiles.txt on\n")
+FILE(APPEND ${F3} "WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX})\n\n")
+
+
+FILE(APPEND ${F3} "execute_process(\n")
+IF (BIOIMAGESUITE_USING_VS)
+  FILE(APPEND ${F3} "COMMAND ${WIN_PATH}/Release/bis_fixscripts.exe\n")
+ELSE(BIOIMAGESUITE_USING_VS)
+  FILE(APPEND ${F3} "COMMAND ${EXECUTABLE_OUTPUT_PATH}/bis_fixscripts\n")
+ENDIF(BIOIMAGESUITE_USING_VS)
+FILE(APPEND ${F3} "-install ${BIOIMAGESUITE3_BINARY_DIR}/scriptfiles.txt\n")
+FILE(APPEND ${F3} "WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX})\n\n")
+
+
+install (FILES ${BIOIMAGESUITE3_BINARY_DIR}/scriptfiles.txt DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/lib)
+install (FILES ${BIOIMAGESUITE3_BINARY_DIR}/tclfilelist.tcl DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/lib)
+
+
+# Excluded TCL Code 
+
+#IF (APPLE)
+#	FILE(APPEND ${F3} "execute_process(\n")
+#	FILE(APPEND ${F3} "COMMAND ${CMAKE_INSTALL_PREFIX}/${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/bin/FixLibPaths.csh\n")
+#	FILE(APPEND ${F3} " ${CMAKE_INSTALL_PREFIX}/${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/lib)\n")
+#ENDIF (APPLE)
+
+
+IF(UNIX AND NOT APPLE)
+  IF(BIOIMAGESUITE3_INSTALL_ICONS)
+    configure_file( ${BIOIMAGESUITE3_SOURCE_DIR}/Utilities/bis_menu.desktop.in
+      ${BIOIMAGESUITE3_BINARY_DIR}/bis_menu.desktop )
+    install( FILES ${CMAKE_BINARY_DIR}/bis_menu.desktop 
+      DESTINATION "/usr/share/applications/" )
+    configure_file( ${BIOIMAGESUITE3_SOURCE_DIR}/Utilities/bis_console.desktop.in
+      ${BIOIMAGESUITE3_BINARY_DIR}/bis_console.desktop )
+    install( FILES ${CMAKE_BINARY_DIR}/bis_console.desktop
+      DESTINATION "/usr/share/applications/" )
+    install( FILES ${BIOIMAGESUITE3_SOURCE_DIR}/bioimagesuite/images/bioimagesuite.png
+      DESTINATION "/usr/share/pixmaps" )
+  ENDIF(BIOIMAGESUITE3_INSTALL_ICONS)
+ENDIF(UNIX AND NOT APPLE)
+
+
diff --git a/bioimagesuite30_src/CPackOptions.cmake b/bioimagesuite30_src/CPackOptions.cmake
new file mode 100644
index 0000000..b730f0c
--- /dev/null
+++ b/bioimagesuite30_src/CPackOptions.cmake
@@ -0,0 +1,319 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+# ------------------------------------------------------------------------------------------------
+# Get Some Base Directory Names Together
+# ------------------------------------------------------------------------------------------------
+
+SET (BIOPATH ${BIOIMAGESUITE3_INSTALL_EXTRAPATH})
+SET (TMP "${VTK_DIR}/../../..")
+GET_FILENAME_COMPONENT(BIOBASEPATH ${TMP} ABSOLUTE )        
+
+#MESSAGE("BIOBASEPATH = ${BIOBASEPATH}, ${TMP}")
+
+
+SET (CMAKE_MODULE_PATH ${BIOIMAGESUITE3_SOURCE_DIR}/installtools)
+
+# ------------------------------------------------------------------------------------------------
+#
+#   Some more common variables
+#
+# ------------------------------------------------------------------------------------------------
+
+SET (CPACK_PACKAGE_VERSION_MAJOR ${BIOIMAGESUITE3_VERSION_MAJOR})
+SET (CPACK_PACKAGE_VERSION_MINOR ${BIOIMAGESUITE3_VERSION_MINOR})
+SET (CPACK_PACKAGE_VERSION_PATCH ${BIOIMAGESUITE3_VERSION_PATCH})
+SET (CPACK_PACKAGE_VERSION "${BIOIMAGESUITE3_VERSION_MAJOR}${BIOIMAGESUITE3_VERSION_MINOR}${BIOIMAGESUITE3_VERSION_PATCH}")
+SET (CPACK_PACKAGE_VENDOR "Section of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of Medicine. (www.bioimagesuite.org)")
+SET (CPACK_PACKAGE_NAME "bioimagesuite")
+SET (CPACK_PACKAGE_SHORT_FILE_NAME "bioimagesuite${BIOIMAGESUITE3_VERSION_MAJOR}${BIOIMAGESUITE3_VERSION_MINOR}")
+
+SET(TMPNAME "BioImage Suite ${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}")
+SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "BioImage Suite ${TMPNAME}")
+SET(CPACK_PACKAGE_DESCRIPTION_FILE "${BIOIMAGESUITE3_SOURCE_DIR}/BioImageSuite_Description.txt")
+SET(CPACK_RESOURCE_FILE_LICENSE "${BIOIMAGESUITE3_SOURCE_DIR}/BioImageSuite_ShortLicense.txt")
+SET(CPACK_PACKAGE_INSTALL_DIRECTORY "")
+
+# ------------------------------------------------------------------------------------------------
+# UNIX/APPLE STG setup
+
+
+IF(BIS_UNIXBUILD)
+  SET (CPACK_STGZ_HEADER_FILE ${BIOIMAGESUITE3_SOURCE_DIR}/installtools/BIS_CPack.STGZ_Header.sh.in)
+  SET (CPACK_POSTINSTALL "")
+  SET (CPACK_NEWPATH "\\\${newpath}/${BIOIMAGESUITE3_INSTALL_EXTRAPATH}")
+
+  EXECUTE_PROCESS (
+    COMMAND date +%d_%b_%Y
+    OUTPUT_VARIABLE TMPD
+    ERROR_VARIABLE TMPE
+    )
+  STRING(REGEX REPLACE "[\n\t]" "" TMPD "${TMPD}")
+
+
+
+  IF(BIOIMAGESUITE3_SET_COMPILER_NAME)
+    GET_FILENAME_COMPONENT(TMPE ${BIOIMAGESUITE3_COMPILER} NAME )    
+  ELSE(BIOIMAGESUITE3_SET_COMPILER_NAME)
+    GET_FILENAME_COMPONENT(TMPE ${CMAKE_CXX_COMPILER}  NAME )        
+  ENDIF(BIOIMAGESUITE3_SET_COMPILER_NAME)
+
+  IF (${CMAKE_CXX_FLAGS} MATCHES ".+m32.+")
+    SET (TMPF "i386")
+  ELSE(${CMAKE_CXX_FLAGS} MATCHES ".+m32.+")
+    SET (TMPF ${CMAKE_SYSTEM_PROCESSOR})
+  ENDIF(${CMAKE_CXX_FLAGS} MATCHES ".+m32.+")
+  
+  IF (${BIOIMAGESUITE3_EXCLUDE_CODE} MATCHES "ON")
+    SET (TMPG "")
+  ELSE (${BIOIMAGESUITE3_EXCLUDE_CODE} MATCHES "ON")
+    SET (TMPG "-internal")
+  ENDIF (${BIOIMAGESUITE3_EXCLUDE_CODE} MATCHES "ON")
+
+#  MESSAGE ("TMPE=${TMPE}")
+
+
+  SET (CPACK_PACKAGE_VERSION_PATCH
+    "${CPACK_PACKAGE_VERSION_PATCH}_${TMPD}")
+ SET (CPACK_PACKAGE_VERSION "${BIOIMAGESUITE3_VERSION_MAJOR}${BIOIMAGESUITE3_VERSION_MINOR}_${CPACK_PACKAGE_VERSION_PATCH}-${CMAKE_SYSTEM_NAME}-${TMPE}-${TMPF}${TMPG}" CACHE TYPE STRING)
+ SET (CPACK_PACKAGE_VERSION "${BIOIMAGESUITE3_VERSION_MAJOR}${BIOIMAGESUITE3_VERSION_MINOR}_${CPACK_PACKAGE_VERSION_PATCH}-${CMAKE_SYSTEM_NAME}-${TMPE}-${TMPF}${TMPG}")
+
+
+
+  SET (BUILDNAME "${CMAKE_SYSTEM_NAME}-${TMPE}-${TMPF}${TMPG}" CACHE TYPE STRING FORCE)
+
+  MESSAGE("++ Package version = ${CPACK_PACKAGE_VERSION}, BUILDNAME=${BUILDNAME}")
+  
+
+  IF(BIOIMAGESUITE3_PACK_BASE)
+    SET (CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}-complete")
+    install (DIRECTORY ${BIOBASEPATH} DESTINATION "." USE_SOURCE_PERMISSIONS)
+    set (CPACK_POSTINSTALL "${CPACK_POSTINSTALL}\n${CPACK_NEWPATH}/installtools/bis_fixscripts -package ${CPACK_NEWPATH}/lib/scriptfiles.txt ${CPACK_NEWPATH}\n")
+    set (CPACK_POSTINSTALL "${CPACK_POSTINSTALL}\n${CPACK_NEWPATH}/installtools/bis_fixscripts_base \\\${newpath}\n")
+    set (CPACK_POSTINSTALL "${CPACK_POSTINSTALL}\nchmod -R 755 \\\${newpath}/bioimagesuite3_base*")
+  ELSE(BIOIMAGESUITE3_PACK_BASE)
+        set (CPACK_POSTINSTALL "${CPACK_POSTINSTALL}\n${CPACK_NEWPATH}/installtools/bis_fixscripts -install ${CPACK_NEWPATH}/lib/scriptfiles.txt ${CPACK_NEWPATH}\n")
+  ENDIF(BIOIMAGESUITE3_PACK_BASE)
+
+
+
+
+# Excluded TCL Code 
+  
+  
+  SET (CPACK_POSTINSTALL
+    "${CPACK_POSTINSTALL}\n\necho \\\"Change permissions\\\"")
+  IF(BIOIMAGESUITE3_PACK_BASE)
+    set (CPACK_POSTINSTALL "${CPACK_POSTINSTALL}\nchmod -R 755 \\\${newpath}/bioimagesuite3_base*")
+  ENDIF(BIOIMAGESUITE3_PACK_BASE)
+  SET (CPACK_POSTINSTALL "${CPACK_POSTINSTALL}\nchmod -R 755 ${CPACK_NEWPATH}")
+
+
+
+  IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+    IF(BIOIMAGESUITE3_INSTALL_ICONS)
+
+    ELSE(BIOIMAGESUITE3_INSTALL_ICONS)      
+      SET (CPACK_POSTINSTALL
+	"${CPACK_POSTINSTALL}\necho \\\"Execute ${CPACK_NEWPATH}/createmenuentries.sh to create menu entries for GNOME and KDE\\\"")
+    ENDIF(BIOIMAGESUITE3_INSTALL_ICONS)      
+  ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+
+  INCLUDE(InstallRequiredSystemLibraries)
+  
+
+
+  #  MESSAGE("Version = ${CPACK_PACKAGE_VERSION}")
+  SET(CPACK_PACKAGE_FILE_NAME "bioimagesuite-${CPACK_PACKAGE_VERSION}")
+
+  SET(CPACK_GENERATOR "STGZ")
+  INCLUDE(CPack)
+
+ELSE (BIS_UNIXBUILD)
+
+# -------------------------------------------------------------------------------------
+#  Creates an installer for inno setup (complete distribution only)
+# -------------------------------------------------------------------------------------
+
+
+  #  include (InstallRequiredSystemLibraries)
+
+  FIND_PROGRAM(INNO_COMPILER
+    NAMES 
+    ISCC.exe
+    ISCC
+    iscc.exe
+    iscc
+    )
+
+  IF (INNO_COMPILER)
+
+    EXECUTE_PROCESS (
+      COMMAND cmd.exe /cdate /t
+      OUTPUT_VARIABLE TMPD
+      ERROR_VARIABLE TMPE
+      )
+
+    STRING(REGEX REPLACE "/" "_" TMPD "${TMPD}")
+    STRING(REGEX REPLACE " " "-" TMPD "${TMPD}")
+    STRING(REGEX REPLACE "[\n\t]" "" TMPD "${TMPD}")
+    STRING(REGEX REPLACE "-" "" TMPD "${TMPD}")
+    STRING(REGEX REPLACE "^[A-Za-z]+" "" TMPD "${TMPD}")
+    #    MESSAGE("Date = ,${TMPD},")
+    
+    SET (INNOSCRIPT  "${BIOIMAGESUITE3_VERSION_MAJOR}${BIOIMAGESUITE3_VERSION_MINOR}_${BIOIMAGESUITE3_VERSION_PATCH}")
+    SET (BUILDNAME "Windows")
+    IF(CMAKE_GENERATOR MATCHES  "Visual Studio 9")	
+      SET (INNOSCRIPT "${INNOSCRIPT}_${TMPD}-Windows_vs2008")
+      SET (BUILDNAME  "Win32-Visual Studio 2008" CACHE TYPE STRING FORCE)
+    ELSE(CMAKE_GENERATOR MATCHES  "Visual Studio 9")	
+       IF (CMAKE_COMPILER_2005)	
+	  SET (INNOSCRIPT "${INNOSCRIPT}_${TMPD}-Windows_vs2005")
+	  SET (BUILDNAME  "Win32-Visual Studio 2005" CACHE TYPE STRING FORCE)
+      ELSE (CMAKE_COMPILER_2005)	
+            SET (INNOSCRIPT "${INNOSCRIPT}_${TMPD}-Windows_vs2003")
+	    SET (BUILDNAME  "Win32-Visual Studio 2003" CACHE TYPE STRING FORCE)
+      ENDIF (CMAKE_COMPILER_2005)
+    ENDIF(CMAKE_GENERATOR MATCHES  "Visual Studio 9")	
+
+    IF(BIOIMAGESUITE3_PACK_BASE)	
+	SET(INNOSCRIPT "${INNOSCRIPT}_complete")
+    ENDIF(BIOIMAGESUITE3_PACK_BASE)	
+
+    SET (TAILNAME "bioimagesuite-${INNOSCRIPT}")
+
+    SET (CPACK_PACKAGE_VERSION  ${INNOSCRIPT})
+    SET (INNOSCRIPT "${BIOIMAGESUITE3_BINARY_DIR}/bioimagesuite-${INNOSCRIPT}.iss")
+
+
+    MESSAGE("++ Package version = ${INNOSCRIPT} BUILDNAME=${BUILDNAME}")
+
+
+
+    ADD_CUSTOM_TARGET(PACKAGE_WITH_INNOSETUP
+      ${INNO_COMPILER} ${INNOSCRIPT}
+      COMMENT "Creating package ${INNOSCRIPT}"
+      )
+
+    SET (VERSION ${BIOIMAGESUITE3_VERSION_MAJOR}${BIOIMAGESUITE3_VERSION_MINOR}${BIOIMAGESUITE3_VERSION_PATCH})
+    #    GET_FILENAME_COMPONENT(BIOPATH ${CMAKE_INSTALL_PREFIX} NAME )        
+
+    
+    SET (FOUT ${INNOSCRIPT})
+    FILE(WRITE  ${FOUT} "[Setup]\n")
+
+    IF (BIOIMAGESUITE3_PACK_BASE)
+      FILE(APPEND ${FOUT}  "AppVerName=BioImage Suite Complete ${VERSION}\n")
+    ELSE(BIOIMAGESUITE3_PACK_BASE)
+      FILE(APPEND ${FOUT}  "AppVerName=BioImage Suite Update ${VERSION}\n")
+    ENDIF(BIOIMAGESUITE3_PACK_BASE)
+
+    FILE(APPEND ${FOUT}  "AppPublisher=Bioimage Suite Project\n")
+    FILE(APPEND ${FOUT}  "AppPublisherURL=http://www.bioimagesuite.org\n")
+    FILE(APPEND ${FOUT}  "AppSupportURL=http://www.bioimagesuite.org\n")
+    FILE(APPEND ${FOUT}  "AppUpdatesURL=http://www.bioimagesuite.org\n")
+    FILE(APPEND ${FOUT}  "OutputDir=${BIOIMAGESUITE3_BINARY_DIR}\n")
+    FILE(APPEND ${FOUT}  "DefaultDirName=${CMAKE_INSTALL_PREFIX}\n")
+    FILE(APPEND ${FOUT}  "AppName=BioImage Suite ${VERSION}\n")
+    FILE(APPEND ${FOUT}  "DefaultGroupName=BioImage_Suite_${VERSION}\n")
+    FILE(APPEND ${FOUT}  "LicenseFile=${BIOIMAGESUITE3_SOURCE_DIR}\\BioImageSuite_License.txt\n")
+    FILE(APPEND ${FOUT}  "SetupIconFile=${BIOIMAGESUITE3_SOURCE_DIR}\\bioimagesuite\\images\\bioimagesuite.ico\n")
+    FILE(APPEND ${FOUT}  "OutputBaseFilename=${TAILNAME}\n")	
+    FILE(APPEND ${FOUT}  "AllowRootDirectory=no\n")
+    FILE(APPEND ${FOUT}  "AllowUNCPath=no\n")
+    FILE(APPEND ${FOUT}  "SetupLogging=yes\n")
+
+    
+    FILE(APPEND ${FOUT}  "Compression=zip\n")
+    FILE(APPEND ${FOUT}  "SolidCompression=yes\n")
+    FILE(APPEND ${FOUT}  "RestartIfNeededByRun=no\n")
+    FILE(APPEND ${FOUT}  "ChangesAssociations=yes\n")
+    IF (BIOIMAGESUITE3_PACK_BASE)
+       FILE (APPEND ${FOUT} "DirExistsWarning=yes\n")
+    ELSE (BIOIMAGESUITE3_PACK_BASE)
+       FILE (APPEND ${FOUT} "DirExistsWarning=no\n")
+    ENDIF (BIOIMAGESUITE3_PACK_BASE)
+    FILE (APPEND ${FOUT} "WizardImageFile=${BIOIMAGESUITE3_SOURCE_DIR}\\bioimagesuite\\images\\bioimagesuite_setuplogo.bmp\n\n\n")
+
+    FILE(APPEND ${FOUT}  "\n[Languages]\n")
+    FILE(APPEND ${FOUT}  "Name: \"english\"; MessagesFile: \"compiler:Default.isl\"\n\n")
+
+    FILE(APPEND ${FOUT}  "[Files]\n")
+    FILE(APPEND ${FOUT}  "Source: \"${CMAKE_INSTALL_PREFIX}\\${BIOPATH}\\*\"; DestDir: \"{app}\\${BIOPATH}\\\"; Flags: ignoreversion recursesubdirs createallsubdirs;Permissions: everyone-readexec\n")
+
+    IF (BIOIMAGESUITE3_PACK_BASE)
+      FILE(APPEND ${FOUT}  "Source: \"${BIOBASEPATH}\\*\";    DestDir: \"{app}\\bioimagesuite3_base\\\"; Flags: ignoreversion recursesubdirs createallsubdirs; Permissions: everyone-readexec\n")
+    ENDIF (BIOIMAGESUITE3_PACK_BASE)
+    
+    FILE(APPEND ${FOUT}  "\n")
+    FILE(APPEND ${FOUT}  "[Icons]\n")
+    FILE(APPEND ${FOUT}  "Name: \"{group}\\BioImage Suite Menu\"; Filename: \"{app}\\${BIOPATH}\\bioimagesuite.bat\" \n")
+    FILE(APPEND ${FOUT}  "Name: \"{group}\\BioImage Suite Console\"; Filename: \"{app}\\${BIOPATH}\\bisconsole.bat\" \n")
+    FILE(APPEND ${FOUT}  "Name: \"{group}\\Links\\BioImage Suite Web Page\"; Filename: \"http://www.bioimagesuite.org\" \n")
+    FILE(APPEND ${FOUT}  "Name: \"{group}\\Links\\BioImage Suite Forum\"; Filename: \"http://research.yale.edu/bioimagesuite/forum/\" \n")
+
+    IF (BIOIMAGESUITE3_PACK_BASE)
+      FILE(APPEND ${FOUT}  "Name: \"{group}\\Base\\VTK\"; Filename: \"{app}\\bioimagesuite3_base\\vtk52\\bin\\vtk.exe\" \n")
+      FILE(APPEND ${FOUT}  "Name: \"{group}\\Base\\TCLSH\"; Filename: \"{app}\\bioimagesuite3_base\\tcl84\\bin\\tclsh84.exe\" \n")
+      FILE(APPEND ${FOUT}  "Name: \"{group}\\Base\\WISH\"; Filename: \"{app}\\bioimagesuite3_base\\tcl84\\bin\\wish84.exe\" \n")
+      FILE(APPEND ${FOUT}  "Name: \"{group}\\Base\\CMakeSetup\"; Filename: \"{app}\\bioimagesuite3_base\\cmake26\\bin\\CMakeSetup.exe\" \n")
+    ENDIF (BIOIMAGESUITE3_PACK_BASE)				 
+    FILE(APPEND ${FOUT}  "Name: \"{group}\\Admin\\Restore Associations\"; Filename: \"{app}\\${BIOPATH}\\setassociations.bat\" \n")
+
+
+    FILE(APPEND ${FOUT}  "Name: \"{group}\\Uninstall\\{cm:UninstallProgram,BioImage Suite}\"; Filename: \"{uninstallexe}\" \n")
+    FILE(APPEND ${FOUT}  "\n")
+    FILE(APPEND ${FOUT}  "[Run]\n")
+
+    IF (BIOIMAGESUITE3_PACK_BASE)
+      FILE(APPEND ${FOUT}  "Filename: \"{app}\\${BIOPATH}\\installtools\\bis_fixscripts_base.exe\"; Parameters: \"{app}\" \n")
+      FILE(APPEND ${FOUT}  "Filename: \"{app}\\${BIOPATH}\\installtools\\bis_fixscripts.exe\"; Parameters: \"-package {app}\\${BIOPATH}\\lib\\scriptfiles.txt {app}\\${BIOPATH}\"\n")
+      FILE(APPEND ${FOUT}  "Filename: \"{app}\\${BIOPATH}\\setassociations.bat\" \n")
+    ELSE (BIOIMAGESUITE3_PACK_BASE)
+      FILE(APPEND ${FOUT}  "Filename: \"{app}\\${BIOPATH}\\installtools\\bis_fixscripts.exe\"; Parameters: \"-install {app}\\${BIOPATH}\\lib\\scriptfiles.txt {app}\\${BIOPATH}\"\n")
+      FILE(APPEND ${FOUT}  "Filename: \"{app}\\${BIOPATH}\\setassociations.bat\" \n")
+    ENDIF (BIOIMAGESUITE3_PACK_BASE)
+
+
+    
+  ENDIF (INNO_COMPILER)
+
+
+
+  SET(CPACK_PACKAGE_FILE_NAME "bioimagesuite-${CPACK_PACKAGE_VERSION}")
+
+
+  SET(CPACK_GENERATOR "ZIP")
+  INCLUDE(CPack)
+
+  
+ENDIF(BIS_UNIXBUILD)
+
+
+
+
diff --git a/bioimagesuite30_src/CTestCustom.cmake.in b/bioimagesuite30_src/CTestCustom.cmake.in
new file mode 100644
index 0000000..1d825d9
--- /dev/null
+++ b/bioimagesuite30_src/CTestCustom.cmake.in
@@ -0,0 +1,3 @@
+#If you want to increase the limit for log modify following lines
+SET(CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE  65536)
+SET(CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE  65536)
diff --git a/bioimagesuite30_src/Common/CMakeLists.txt b/bioimagesuite30_src/Common/CMakeLists.txt
new file mode 100644
index 0000000..ef7c618
--- /dev/null
+++ b/bioimagesuite30_src/Common/CMakeLists.txt
@@ -0,0 +1,231 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES(${ITK_INCLUDE_DIRS})
+
+IF (BIOIMAGESUITE3_USE_SYSTEM_NIFTI)
+   INCLUDE_DIRECTORIES( /usr/include/nifti/ )
+ELSE (BIOIMAGESUITE3_USE_SYSTEM_NIFTI)
+ENDIF (BIOIMAGESUITE3_USE_SYSTEM_NIFTI)
+
+IF (BIOIMAGESUITE3_USE_SYSTEM_OPENIGTLINK)
+   INCLUDE_DIRECTORIES( /usr/include/openigtlink/igtlutil/ )
+ELSE (BIOIMAGESUITE3_USE_SYSTEM_OPENIGTLINK)
+   INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/igtlutil)
+ENDIF (BIOIMAGESUITE3_USE_SYSTEM_OPENIGTLINK)
+
+
+SET(KIT vtkpxCommon)
+
+SET (KITSRCS
+# ---------------------------
+# NIFTI1 -- Header Stuff
+# ---------------------------
+vtkbisNIFTIExtension.cpp
+vtkbisNIFTIExtensionsList.cpp
+# -------------------------
+# Basic Image To Image Filter
+# -------------------------
+vtkpxSimpleImageToImageFilter.cpp
+# -------------------------
+# Read / Write To File
+# -------------------------
+vtkbisImageHeader.cpp
+vtkpxAnalyzeImageSource.cpp
+#vtkbisVarianSource.cpp
+vtkpxAnalyzeImageSourceOld.cpp
+vtkpxAnalyzeImageWriter.cpp
+vtkpxPickerPrismSource.cpp
+vtkpxSignaLXImageSource.cpp
+vtkpxEpilepsyCSIReader.cpp
+vtkafBVImageReader.cpp
+vtkafBVImageWriter.cpp
+# -------------------------
+# General Utility Code
+# -------------------------
+vtkpxUtil.cpp
+vtkbisTestUtil.cpp
+vtkpxGenericUndoStack.cpp
+vtkpxDataArrayUndoStack.cpp
+# --------------------------
+# Math Based Stuff
+# --------------------------
+vtkpxMath.cpp
+vtkpxOptimizer.cpp
+vtkpxTestOptimizer.cpp
+vtkpxAbstractMatrix.cpp
+vtkpxMatrix.cpp
+#vtknrMatrix.cpp
+vtkpxBSpline.cpp
+# ---------------------------
+# Image Filters
+# --------------------------
+vtkpxImageComponentsToFrames.cpp
+vtkpxStructuredPointsToStructuredPointsFilter.cpp
+vtkpxImageExtract.cpp
+vtkpxAppendComponents.cpp
+vtkpxImageExtractVOI.cpp
+vtkpxImageReplaceSlice.cpp
+vtkpxCrossHairSource.cpp
+vtkbisCylinderSource.cpp
+vtkpxBaseCurve.cpp
+# ----------------------------
+# Transformations
+# ----------------------------
+vtkpxTensorBSplineTransform.cpp
+# ----------------------------
+# Basic Image Filters
+# ----------------------------
+vtkokImageAccumulate.cpp
+vtkbisImageReslice.cpp
+vtkbisImageResample.cpp
+vtkbisImageReOrient.cpp
+# ----------------------------
+# Sphere Coloring Utility
+# ----------------------------
+vtkjoSphereSource.cxx
+vtkjoColoredSphereSource.cpp
+# ----------------------------
+# New Stuff
+# ----------------------------
+vtkjoStatistics.cpp
+vtkjoROCFilter.cpp
+)
+
+IF( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" LESS 5.4 )
+#
+# OpenIGTLink
+#
+SET (KITSRCS
+${KITSRCS}
+vtkpxOpenIGTLinkClient.cpp
+vtkpxOpenIGTLinkServer.cpp
+vtkpxOpenIGTLinkServerObserver.cpp
+vtkpxOpenIGTLinkClientObserver.cpp
+)
+ENDIF( "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}" LESS 5.4 )
+
+IF (NOT BIOIMAGESUITE3_USE_SYSTEM_NIFTI)
+  SET(KITSRCS ${KITSRCS}
+  # ----------------------------
+  # From NIFT1
+  # ----------------------------
+  nifti1_io.c
+  znzlib.c
+  )
+ENDIF (NOT BIOIMAGESUITE3_USE_SYSTEM_NIFTI)
+
+
+SET_SOURCE_FILES_PROPERTIES(
+  vtkpxOpenIGTLinkServerObserver.cpp	
+  vtkpxOpenIGTLinkClientObserver.cpp
+  WRAP_EXCLUDE
+  )
+
+
+SET_SOURCE_FILES_PROPERTIES(	
+vtkpxSimpleImageToImageFilter
+ABSTRACT
+)
+
+SET_SOURCE_FILES_PROPERTIES(	
+znzlib.c
+nifti1_io.c
+#nifticdf.c
+WRAP_EXCLUDE
+)
+
+
+
+IF (BIOIMAGESUITE3_USE_VVLINK)
+   SET (KITSRCS
+       ${KITSRCS}
+       vtkpxVVLinkConnectorNew.cpp
+      )
+   SET (VVLINKLIB vvlcppapi)
+   INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/vvlcppapi5)
+ENDIF (BIOIMAGESUITE3_USE_VVLINK)
+
+
+
+SET_SOURCE_FILES_PROPERTIES(
+vtkpxAbstractMatrix
+vtkpxGenericUndoStack
+ABSTRACT
+)
+
+SET(KITLIBS
+  ${VVLINKLIB}
+  igtlutil
+  numerics
+  vtkIOTCL
+  vtkHybridTCL
+  vtkCommonTCL
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+)
+
+SET(KITJAVALIBS
+  ${VVLINKLIB}
+  igtlutil
+  numerics
+  vtkIOTCL
+  vtkHybridJava
+  vtkCommonJava
+   ${BIOIMAGESUITE3_COMMON_JAVALIBS}
+)
+
+#IF (NOT APPLE)
+SET (KITSRCS ${KITSRCS}
+  vtkbisGDCMImageReader.cpp
+  vtkbisDICOMReader.cpp)
+SET(KITLIBS ${KITLIBS} vtkgdcm )
+SET(KITJAVALIBS ${KITJAVALIBS} vtkgdcm )
+#ENDIF (NOT APPLE)
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+SET (KITEXTRAFILES
+Common/vtkTemplateAliasMacro.h)
+
+SET (KITTCLSRCS )
+bis_complex("Common" ${KIT} ${FILELIST})
+
+
+
+
diff --git a/bioimagesuite30_src/Common/nifti1_io.c b/bioimagesuite30_src/Common/nifti1_io.c
new file mode 100644
index 0000000..531c23d
--- /dev/null
+++ b/bioimagesuite30_src/Common/nifti1_io.c
@@ -0,0 +1,6415 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#define _NIFTI1_IO_C_
+
+#include "nifti1_io.h"   /* typedefs, prototypes, macros, etc. */
+
+/*****===================================================================*****/
+/*****     Sample functions to deal with NIFTI-1 and ANALYZE files       *****/
+/*****...................................................................*****/
+/*****            This code is released to the public domain.            *****/
+/*****...................................................................*****/
+/*****  Author: Robert W Cox, SSCC/DIRP/NIMH/NIH/DHHS/USA/EARTH          *****/
+/*****  Date:   August 2003                                              *****/
+/*****...................................................................*****/
+/*****  Neither the National Institutes of Health (NIH), nor any of its  *****/
+/*****  employees imply any warranty of usefulness of this software for  *****/
+/*****  any purpose, and do not assume any liability for damages,        *****/
+/*****  incidental or otherwise, caused by any use of this document.     *****/
+/*****===================================================================*****/
+
+/** \file nifti1_io.c
+    \brief main collection of nifti1 i/o routines
+           - written by Bob Cox, SSCC NIMH
+           - revised by Mark Jenkinson, FMRIB
+           - revised by Rick Reynolds, SSCC, NIMH
+           - revised by Kate Fissell, University of Pittsburgh
+
+        The library history can be viewed via "nifti_tool -nifti_hist".
+    <br>The library version can be viewed via "nifti_tool -nifti_ver".
+ */
+
+/*! global history and version strings, for printing */
+static char * gni_history[] = 
+{
+  "----------------------------------------------------------------------\n"
+  "history (of nifti library changes):\n"
+  "\n",
+  "0.0  August, 2003 [rwcox]\n"
+  "     (Robert W Cox of the National Institutes of Health, SSCC/DIRP/NIMH)\n"
+  "   - initial version\n"
+  "\n",
+  "0.1  July/August, 2004 [Mark Jenkinson]\n"
+  "     (FMRIB Centre, University of Oxford, UK)\n"
+  "   - Mainly adding low-level IO and changing things to allow gzipped\n"
+  "     files to be read and written\n"
+  "   - Full backwards compatability should have been maintained\n"
+  "\n",
+  "0.2  16 Nov 2004 [rickr]\n"
+  "     (Rick Reynolds of the National Institutes of Health, SSCC/DIRP/NIMH)\n"
+  "   - included Mark's changes in the AFNI distribution (including znzlib/)\n"
+  "     (HAVE_ZLIB is commented out for the standard distribution)\n"
+  "   - modified nifti_validfilename() and nifti_makebasename()\n"
+  "   - added nifti_find_file_extension()\n"
+  "\n",
+  "0.3  3 Dec 2004 [rickr]\n"
+  "   - note: header extensions are not yet checked for\n"
+  "   - added formatted history as global string, for printing\n"
+  "   - added nifti_disp_lib_hist(), to display the nifti library history\n"
+  "   - added nifti_disp_lib_version(), to display the nifti library history\n",
+  "   - re-wrote nifti_findhdrname()\n"
+  "       o used nifti_find_file_extension()\n"
+  "       o changed order of file tests (default is .nii, depends on input)\n"
+  "       o free hdrname on failure\n"
+  "   - made similar changes to nifti_findimgname()\n"
+  "   - check for NULL return from nifti_findhdrname() calls\n",
+  "   - removed most of ERREX() macros\n"
+  "   - modified nifti_image_read()\n"
+  "       o added debug info and error checking (on gni_debug > 0, only)\n"
+  "       o fail if workingname is NULL\n"
+  "       o check for failure to open header file\n"
+  "       o free workingname on failure\n"
+  "       o check for failure of nifti_image_load()\n"
+  "       o check for failure of nifti_convert_nhdr2nim()\n",
+  "   - changed nifti_image_load() to int, and check nifti_read_buffer return\n"
+  "   - changed nifti_read_buffer() to fail on short read, and to count float\n"
+  "     fixes (to print on debug)\n"
+  "   - changed nifti_image_infodump to print to stderr\n"
+  "   - updated function header comments, or moved comments above header\n"
+  "   - removed const keyword\n"
+  "   - added LNI_FERR() macro for error reporting on input files\n"
+  "\n",
+  "0.4  10 Dec 2004 [rickr]  - added header extensions\n"
+  "   - in nifti1_io.h:\n"
+  "       o added num_ext and ext_list to the definition of nifti_image\n"
+  "       o made many functions static (more to follow)\n"
+  "       o added LNI_MAX_NIA_EXT_LEN, for max nifti_type 3 extension length\n",
+  "   - added __DATE__ to version output in nifti_disp_lib_version()\n"
+  "   - added nifti_disp_matrix_orient() to print orientation information\n"
+  "   - added '.nia' as a valid file extension in nifti_find_file_extension()\n"
+  "   - added much more debug output\n"
+  "   - in nifti_image_read(), in the case of an ASCII header, check for\n"
+  "     extensions after the end of the header\n",
+  "   - added nifti_read_extensions() function\n"
+  "   - added nifti_read_next_extension() function\n"
+  "   - added nifti_add_exten_to_list() function\n"
+  "   - added nifti_check_extension() function\n"
+  "   - added nifti_write_extensions() function\n"
+  "   - added nifti_extension_size() function\n"
+  "   - in nifti_set_iname_offest():\n"
+  "       o adjust offset by the extension size and the extender size\n",
+  "       o fixed the 'ceiling modulo 16' computation\n"
+  "   - in nifti_image_write_hdr_img2(): \n"
+  "       o added extension writing\n"
+  "       o check for NULL return from nifti_findimgname()\n"
+  "   - include number of extensions in nifti_image_to_ascii() output\n"
+  "   - in nifti_image_from_ascii():\n"
+  "       o return bytes_read as a parameter, computed from the final spos\n"
+  "       o extract num_ext from ASCII header\n"
+  "\n",
+  "0.5  14 Dec 2004 [rickr]  - added sub-brick reading functions\n"
+  "   - added nifti_brick_list type to nifti1_io.h, along with new prototypes\n"
+  "   - added main nifti_image_read_bricks() function, with description\n"
+  "   - added nifti_image_load_bricks() - library function (requires nim)\n"
+  "   - added valid_nifti_brick_list() - library function\n"
+  "   - added free_NBL() - library function\n",
+  "   - added update_nifti_image_for_brick_list() for dimension update\n"
+  "   - added nifti_load_NBL_bricks(), nifti_alloc_NBL_mem(),\n"
+  "           nifti_copynsort() and force_positive() (static functions)\n"
+  "   - in nifti_image_read(), check for failed load only if read_data is set\n"
+  "   - broke most of nifti_image_load() into nifti_image_load_prep()\n"
+  "\n",
+  "0.6  15 Dec 2004 [rickr]  - added sub-brick writing functionality\n"
+  "   - in nifti1_io.h, removed znzlib directory from include - all nifti\n"
+  "       library files are now under the nifti directory\n"
+  "   - nifti_read_extensions(): print no offset warning for nifti_type 3\n"
+  "   - nifti_write_all_data():\n"
+  "       o pass nifti_brick_list * NBL, for optional writing\n"
+  "       o if NBL, write each sub-brick, sequentially\n",
+  "   - nifti_set_iname_offset(): case 1 must have sizeof() cast to int\n"
+  "   - pass NBL to nifti_image_write_hdr_img2(), and allow NBL or data\n"
+  "   - added nifti_image_write_bricks() wrapper for ...write_hdr_img2()\n"
+  "   - included compression abilities\n"
+  "\n",
+  "0.7  16 Dec 2004 [rickr] - minor changes to extension reading\n"
+  "\n",
+  "0.8  21 Dec 2004 [rickr] - restrict extension reading, and minor changes\n"
+  "   - in nifti_image_read(), compute bytes for extensions (see remaining)\n"
+  "   - in nifti_read_extensions(), pass 'remain' as space for extensions,\n"
+  "        pass it to nifti_read_next_ext(), and update for each one read \n"
+  "   - in nifti_check_extension(), require (size <= remain)\n",
+  "   - in update_nifti_image_brick_list(), update nvox\n"
+  "   - in nifti_image_load_bricks(), make explicit check for nbricks <= 0\n"
+  "   - in int_force_positive(), check for (!list)\n"
+  "   - in swap_nifti_header(), swap sizeof_hdr, and reorder to struct order\n"
+  "   - change get_filesize functions to signed ( < 0 is no file or error )\n",
+  "   - in nifti_validfilename(), lose redundant (len < 0) check\n"
+  "   - make print_hex_vals() static\n"
+  "   - in disp_nifti_1_header, restrict string field widths\n"
+  "\n",
+  "0.9  23 Dec 2004 [rickr] - minor changes\n"
+  "   - broke ASCII header reading out of nifti_image_read(), into new\n"
+  "        functions has_ascii_header() and read_ascii_image()\n",
+  "   - check image_read failure and znzseek failure\n"
+  "   - altered some debug output\n"
+  "   - nifti_write_all_data() now returns an int\n"
+  "\n",
+  "0.10 29 Dec 2004 [rickr]\n"
+  "   - renamed nifti_valid_extension() to nifti_check_extension()\n"
+  "   - added functions nifti_makehdrname() and nifti_makeimgname()\n"
+  "   - added function valid_nifti_extensions()\n"
+  "   - in nifti_write_extensions(), check for validity before writing\n",
+  "   - rewrote nifti_image_write_hdr_img2():\n"
+  "       o set write_data and leave_open flags from write_opts\n"
+  "       o add debug print statements\n"
+  "       o use nifti_write_ascii_image() for the ascii case\n"
+  "       o rewrote the logic of all cases to be easier to follow\n",
+  "   - broke out code as nifti_write_ascii_image() function\n"
+  "   - added debug to top-level write functions, and free the znzFile\n"
+  "   - removed unused internal function nifti_image_open()\n"
+  "\n",
+  "0.11 30 Dec 2004 [rickr] - small mods\n"
+  "   - moved static function prototypes from header to C file\n"
+  "   - free extensions in nifti_image_free()\n"
+  "\n",
+  "1.0  07 Jan 2005 [rickr] - INITIAL RELEASE VERSION\n"
+  "   - added function nifti_set_filenames()\n"
+  "   - added function nifti_read_header()\n"
+  "   - added static function nhdr_looks_good()\n"
+  "   - added static function need_nhdr_swap()\n"
+  "   - exported nifti_add_exten_to_list symbol\n",
+  "   - fixed #bytes written in nifti_write_extensions()\n"
+  "   - only modify offset if it is too small (nifti_set_iname_offset)\n"
+  "   - added nifti_type 3 to nifti_makehdrname and nifti_makeimgname\n"
+  "   - added function nifti_set_filenames()\n"
+  "\n",
+  "1.1  07 Jan 2005 [rickr]\n"
+  "   - in nifti_read_header(), swap if needed\n"
+  "\n",
+  "1.2  07 Feb 2005 [kate fissell c/o rickr] \n"
+  "   - nifti1.h: added doxygen comments for main struct and #define groups\n"
+  "   - nifti1_io.h: added doxygen comments for file and nifti_image struct\n"
+  "   - nifti1_io.h: added doxygen comments for file and some functions\n"
+  "   - nifti1_io.c: changed nifti_copy_nim_info to use memcpy\n"
+  "\n",
+  "1.3  09 Feb 2005 [rickr]\n"
+  "   - nifti1.h: added doxygen comments for extension structs\n"
+  "   - nifti1_io.h: put most #defines in #ifdef _NIFTI1_IO_C_ block\n"
+  "   - added a doxygen-style description to every exported function\n"
+  "   - added doxygen-style comments within some functions\n"
+  "   - re-exported many znzFile functions that I had made static\n"
+  "   - re-added nifti_image_open (sorry, Mark)\n"
+  "   - every exported function now has 'nifti' in the name (19 functions)\n",
+  "   - made sure every alloc() has a failure test\n"
+  "   - added nifti_copy_extensions function, for use in nifti_copy_nim_info\n"
+  "   - nifti_is_gzfile: added initial strlen test\n"
+  "   - nifti_set_filenames: added set_byte_order parameter option\n"
+  "     (it seems appropriate to set the BO when new files are associated)\n"
+  "   - disp_nifti_1_header: prints to stdout (a.o.t. stderr), with fflush\n"
+  "\n",
+  "1.4  23 Feb 2005 [rickr] - sourceforge merge\n"
+  "   - merged into the nifti_io CVS directory structure at sourceforge.net\n"
+  "   - merged in 4 changes by Mark, and re-added his const keywords\n"
+  "   - cast some pointers to (void *) for -pedantic compile option\n"
+  "   - added nifti_free_extensions()\n"
+  "\n",
+  "1.5  02 Mar 2005 [rickr] - started nifti global options\n"
+  "   - gni_debug is now g_opts.debug\n"
+  "   - added validity check parameter to nifti_read_header\n"
+  "   - need_nhdr_swap no longer does test swaps on the stack\n"
+  "\n",
+  "1.6  05 April 2005 [rickr] - validation and collapsed_image_read\n"
+  "   - added nifti_read_collapsed_image(), an interface for reading partial\n"
+  "     datasets, specifying a subset of array indices\n"
+  "   - for read_collapsed_image, added static functions: rci_read_data(),\n"
+  "     rci_alloc_mem(), and make_pivot_list()\n",
+  "   - added nifti_nim_is_valid() to check for consistency (more to do)\n"
+  "   - added nifti_nim_has_valid_dims() to do many dimensions tests\n"
+  "\n",
+  "1.7  08 April 2005 [rickr]\n"
+  "   - added nifti_update_dims_from_array() - to update dimensions\n"
+  "   - modified nifti_makehdrname() and nifti_makeimgname():\n"
+  "       if prefix has a valid extension, use it (else make one up)\n"
+  "   - added nifti_get_intlist - for making an array of ints\n"
+  "   - fixed init of NBL->bsize in nifti_alloc_NBL_mem()  {thanks, Bob}\n"
+  "\n",
+  "1.8  14 April 2005 [rickr]\n"
+  "   - added nifti_set_type_from_names(), for nifti_set_filenames()\n"
+  "     (only updates type if number of files does not match it)\n"
+  "   - added is_valid_nifti_type(), just to be sure\n"
+  "   - updated description of nifti_read_collapsed_image() for *data change\n"
+  "     (if *data is already set, assume memory exists for results)\n"
+  "   - modified rci_alloc_mem() to allocate only if *data is NULL\n"
+  "\n",
+  "1.9  19 April 2005 [rickr]\n"
+  "   - added extension codes NIFTI_ECODE_COMMENT and NIFTI_ECODE_XCEDE\n"
+  "   - added nifti_type codes NIFTI_MAX_ECODE and NIFTI_MAX_FTYPE\n"
+  "   - added nifti_add_extension() {exported}\n"
+  "   - added nifti_fill_extension() as a static function\n"
+  "   - added nifti_is_valid_ecode() {exported}\n",
+  "   - nifti_type values are now NIFTI_FTYPE_* file codes\n"
+  "   - in nifti_read_extensions(), decrement 'remain' by extender size, 4\n"
+  "   - in nifti_set_iname_offset(), case 1, update if offset differs\n"
+  "   - only output '-d writing nifti file' if debug > 1\n"
+  "\n",
+  "1.10 10 May 2005 [rickr]\n"
+  "   - files are read using ZLIB only if they end in '.gz'\n"
+  "\n",
+  "1.11 12 August 2005 [kate fissell]\n"
+  "   - Kate's 0.2 release packaging, for sourceforge\n"
+  "\n",
+  "1.12 17 August 2005 [rickr] - comment (doxygen) updates\n"
+  "   - updated comments for most functions (2 updates from Cinly Ooi)\n"
+  "   - added nifti_type_and_names_match()\n"
+  "\n",
+  "1.12a 24 August 2005 [rickr] - remove all tabs from Clibs/*/*.[ch]\n",
+  "1.12b 25 August 2005 [rickr] - changes by Hans Johnson\n",
+  "1.13  25 August 2005 [rickr]\n",
+  "   - finished changes by Hans for Insight\n"
+  "   - added const in all appropraite parameter locations (30-40)\n"
+  "     (any pointer referencing data that will not change)\n"
+  "   - shortened all string constants below 509 character limit\n"
+  "1.14  28 October 2005 [HJohnson]\n",
+  "   - use nifti_set_filenames() in nifti_convert_nhdr2nim()\n"
+  "1.15  02 November 2005 [rickr]\n",
+  "   - added skip_blank_ext to nifti_global_options\n"
+  "   - added nifti_set_skip_blank_ext(), to set option\n"
+  "   - if skip_blank_ext and no extensions, do not read/write extender\n"
+  "1.16 18 November 2005 [rickr]\n",
+  "   - removed any test or access of dim[i], i>dim[0]\n"
+  "   - do not set pixdim for collapsed dims to 1.0, leave them as they are\n"
+  "   - added magic and dim[i] tests in nifti_hdr_looks_good()\n"
+  "   - added 2 size_t casts\n"
+  "1.17 22 November 2005 [rickr]\n",
+  "   - in hdr->nim, for i > dim[0], pass 0 or 1, else set to 1\n"
+  "1.18 02 March 2006 [rickr]\n",
+  "   - in nifti_alloc_NBL_mem(), fixed nt=0 case from 1.17 change\n"
+  "1.19 23 May 2006 [HJohnson,rickr]\n",
+  "   - nifti_write_ascii_image(): free(hstr)\n"
+  "   - nifti_copy_extensions(): clear num_ext and ext_list\n"
+  "1.20 27 Jun 2006 [rickr]\n",
+  "   - nifti_findhdrname(): fixed assign of efirst to match stated logic\n"
+  "     (problem found by Atle Bjørnerud)\n"
+  "1.21 5 Sep 2006 [rickr] update for nifticlib-0.4 release\n",
+  "   - was reminded to actually add nifti_set_skip_blank_ext()\n"
+  "   - init g_opts.skip_blank_ext to 0\n"
+  "----------------------------------------------------------------------\n"
+};
+static char gni_version[] = "nifti library version 1.21  5 Sep, 2006)";
+
+/*! global nifti options structure */
+static nifti_global_options g_opts = { 3, 3 };
+
+/*---------------------------------------------------------------------------*/
+/* prototypes for internal functions - not part of exported library          */
+
+/* extension routines */
+static int  nifti_read_extensions( nifti_image *nim, znzFile fp, int remain );
+static int  nifti_read_next_extension( nifti1_extension * nex, nifti_image *nim,                                       int remain, znzFile fp );
+static int  nifti_check_extension(nifti_image *nim, int size,int code, int rem);
+static void update_nifti_image_for_brick_list(nifti_image * nim , int nbricks);
+static int  nifti_add_exten_to_list(nifti1_extension *  new_ext,
+                                    nifti1_extension ** list, int new_length);
+static int  nifti_fill_extension(nifti1_extension * ext, const char * data,
+                                 int len, int ecode);
+
+/* NBL routines */
+static int  nifti_load_NBL_bricks(nifti_image * nim , int * slist, int * sindex,                                  nifti_brick_list * NBL, znzFile fp );
+static int  nifti_alloc_NBL_mem(  nifti_image * nim, int nbricks,
+                                  nifti_brick_list * nbl);
+static int  nifti_copynsort(int nbricks, const int *blist, int **slist,
+                            int **sindex);
+
+/* for nifti_read_collapsed_image: */
+static int  rci_read_data(nifti_image *nim, int *pivots, int *prods, int nprods,
+                     const int dims[], char *data, znzFile fp, int base_offset);
+static int  rci_alloc_mem(void ** data, int prods[8], int nprods, int nbyper );
+static int  make_pivot_list(nifti_image * nim, const int dims[], int pivots[],
+                            int prods[], int * nprods );
+
+/* misc */
+static int   need_nhdr_swap    (short dim0, int hdrsize);
+static int   print_hex_vals    (const char * data, int nbytes, FILE * fp);
+static int   unescape_string   (char *str);  /* string utility functions */
+static char *escapize_string   (const char *str);
+
+/* internal I/O routines */
+static znzFile nifti_image_load_prep( nifti_image *nim );
+static int     has_ascii_header(znzFile fp);
+/*---------------------------------------------------------------------------*/
+
+
+/* for calling from some main program */
+
+/*----------------------------------------------------------------------*/
+/*! display the nifti library module history (via stdout)
+*//*--------------------------------------------------------------------*/
+void nifti_disp_lib_hist( void )
+{
+   int c, len = sizeof(gni_history)/sizeof(char *);
+   for( c = 0; c < len; c++ )
+       fputs(gni_history[c], stdout);
+}
+
+/*----------------------------------------------------------------------*/
+/*! display the nifti library version (via stdout)
+*//*--------------------------------------------------------------------*/
+void nifti_disp_lib_version( void )
+{
+   printf("%s, compiled %s\n", gni_version, __DATE__);
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! nifti_image_read_bricks        - read nifti data as array of bricks
+ *
+ *                                   13 Dec 2004 [rickr]
+ * 
+ *  \param  hname    - filename of dataset to read (must be valid)
+ *  \param  nbricks  - number of sub-bricks to read
+ *                     (if blist is valid, nbricks must be > 0)
+ *  \param  blist    - list of sub-bricks to read
+ *                     (can be NULL; if NULL, read complete dataset)
+ *  \param  NBL      - pointer to empty nifti_brick_list struct
+ *                     (must be a valid pointer)
+ *
+ *  \return
+ *     <br> nim      - same as nifti_image_read, but nim->data will be NULL
+ *     <br> NBL      - filled with data
+ *
+ * By default, this function will read the nifti dataset and break the data
+ * into a list of nt*nu*nv*nw sub-bricks, each having size nx*ny*nz elements.
+ * That is to say, instead of reading the entire dataset as a single array,
+ * break it up into sub-bricks, each of size nx*ny*nz elements.
+ *
+ * If 'blist' is valid, it is taken to be a list of sub-bricks, of length
+ * 'nbricks'.  The data will still be separated into sub-bricks of size
+ * nx*ny*nz elements, but now 'nbricks' sub-bricks will be returned, of the
+ * caller's choosing via 'blist'.
+ *
+ * E.g. consider a dataset with 12 sub-bricks (numbered 0..11), and the
+ * following code:
+ *
+ * <pre>
+ * { nifti_brick_list   NB_orig, NB_select;
+ *   nifti_image      * nim_orig, * nim_select;
+ *   int                blist[5] = { 7, 0, 5, 5, 9 };
+ *
+ *   nim_orig   = nifti_image_read_bricks("myfile.nii", 0, NULL,  &NB_orig);
+ *   nim_select = nifti_image_read_bricks("myfile.nii", 5, blist, &NB_select);
+ * }
+ * </pre>
+ *
+ * Here, nim_orig gets the entire dataset, where NB_orig.nbricks = 11.  But
+ * nim_select has NB_select.nbricks = 5.
+ *
+ * Note that the first case is not quite the same as just calling the
+ * nifti_image_read function, as here the data is separated into sub-bricks.
+ *
+ * Note that valid blist elements are in [0..nt*nu*nv*nw-1],
+ * or written [ 0 .. (dim[4]*dim[5]*dim[6]*dim[7] - 1) ].
+ *
+ * Note that, as is the case with all of the reading functions, the
+ * data will be allocated, read in, and properly byte-swapped, if
+ * necessary.
+ *
+ * \sa nifti_image_load_bricks, nifti_free_NBL, valid_nifti_brick_list,
+       nifti_image_read
+*//*----------------------------------------------------------------------*/
+nifti_image *nifti_image_read_bricks(const char * hname, int nbricks,
+                                     const int * blist, nifti_brick_list * NBL)
+{
+   nifti_image * nim;
+
+   if( !hname || !NBL ){
+      fprintf(stderr,"** nifti_image_read_bricks: bad params (%p,%p)\n",
+              hname, (void *)NBL);
+      return NULL;
+   }
+
+   if( blist && nbricks <= 0 ){
+      fprintf(stderr,"** nifti_image_read_bricks: bad nbricks, %d\n", nbricks);
+      return NULL;
+   }
+
+   nim = nifti_image_read(hname, 0);  /* read header, but not data */
+
+   if( !nim ) return NULL;   /* errors were already printed */
+
+   /* if we fail, free image and return */
+   if( nifti_image_load_bricks(nim, nbricks, blist, NBL) <= 0 ){
+      nifti_image_free(nim);
+      return NULL;
+   }
+
+   if( blist ) update_nifti_image_for_brick_list(nim, nbricks);
+
+   return nim;
+}
+
+
+/*----------------------------------------------------------------------
+ * update_nifti_image_for_brick_list  - update nifti_image
+ *
+ * When loading a specific brick list, the distinction between
+ * nt, nu, nv and nw is lost.  So put everything in t, and set
+ * dim[0] = 4.
+ *----------------------------------------------------------------------*/
+static void update_nifti_image_for_brick_list( nifti_image * nim , int nbricks )
+{
+   int ndim;
+
+   if( g_opts.debug > 2 ){
+      fprintf(stderr,"+d updating image dimensions for %d bricks in list\n",
+              nbricks);
+      fprintf(stderr,"   ndim = %d\n",nim->ndim);
+      fprintf(stderr,"   nx,ny,nz,nt,nu,nv,nw: (%d,%d,%d,%d,%d,%d,%d)\n",
+              nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw);
+   }
+
+   nim->nt = nbricks;
+   nim->nu = nim->nv = nim->nw = 1;
+   nim->dim[4] = nbricks;
+   nim->dim[5] = nim->dim[6] = nim->dim[7] = 1;
+
+   /* compute nvox                                                       */
+   /* do not rely on dimensions above dim[0]         16 Nov 2005 [rickr] */
+   for( nim->nvox = 1, ndim = 1; ndim <= nim->dim[0]; ndim++ )
+      nim->nvox *= nim->dim[ndim];
+
+   /* update the dimensions to 4 or lower */
+   for( ndim = 4; (ndim > 1) && (nim->dim[ndim] <= 1); ndim-- )
+       ;
+
+   if( g_opts.debug > 2 ){
+      fprintf(stderr,"+d ndim = %d -> %d\n",nim->ndim, ndim);
+      fprintf(stderr," --> (%d,%d,%d,%d,%d,%d,%d)\n",
+              nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw);
+   }
+
+   nim->dim[0] = nim->ndim = ndim;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! nifti_update_dims_from_array  - update nx, ny, ... from nim->dim[]
+
+    Fix all the dimension information, based on a new nim->dim[].
+
+    Note: we assume that dim[0] will not increase.
+
+    Check for updates to pixdim[], dx,...,  nx,..., nvox, ndim, dim[0].
+*//*--------------------------------------------------------------------*/
+int nifti_update_dims_from_array( nifti_image * nim )
+{
+   int c, ndim;
+
+   if( !nim ){
+      fprintf(stderr,"** update_dims: missing nim\n");
+      return 1;
+   }
+
+   if( g_opts.debug > 2 ){
+      fprintf(stderr,"+d updating image dimensions given nim->dim:");
+      for( c = 0; c < 8; c++ ) fprintf(stderr," %d", nim->dim[c]);
+      fputc('\n',stderr);
+   }
+
+   /* verify dim[0] first */
+   if(nim->dim[0] < 1 || nim->dim[0] > 7){
+      fprintf(stderr,"** invalid dim[0], dim[] = ");
+      for( c = 0; c < 8; c++ ) fprintf(stderr," %d", nim->dim[c]);
+      fputc('\n',stderr);
+      return 1;
+   }
+
+   /* set nx, ny ..., dx, dy, ..., one by one */
+
+   /* less than 1, set to 1, else copy */
+   if(nim->dim[1] < 1) nim->nx = nim->dim[1] = 1;
+   else                nim->nx = nim->dim[1];
+   nim->dx = nim->pixdim[1];
+
+   /* if undefined, or less than 1, set to 1 */
+   if(nim->dim[0] < 2 || (nim->dim[0] >= 2 && nim->dim[2] < 1))
+      nim->ny = nim->dim[2] = 1;
+   else
+      nim->ny = nim->dim[2];
+   /* copy delta values, in any case */
+   nim->dy = nim->pixdim[2];
+
+   if(nim->dim[0] < 3 || (nim->dim[0] >= 3 && nim->dim[3] < 1))
+      nim->nz = nim->dim[3] = 1;
+   else /* just copy vals from arrays */
+      nim->nz = nim->dim[3];
+   nim->dz = nim->pixdim[3];
+
+   if(nim->dim[0] < 4 || (nim->dim[0] >= 4 && nim->dim[4] < 1))
+      nim->nt = nim->dim[4] = 1;
+   else /* just copy vals from arrays */
+      nim->nt = nim->dim[4];
+   nim->dt = nim->pixdim[4];
+
+   if(nim->dim[0] < 5 || (nim->dim[0] >= 5 && nim->dim[5] < 1))
+      nim->nu = nim->dim[5] = 1;
+   else /* just copy vals from arrays */
+      nim->nu = nim->dim[5];
+   nim->du = nim->pixdim[5];
+
+   if(nim->dim[0] < 6 || (nim->dim[0] >= 6 && nim->dim[6] < 1))
+      nim->nv = nim->dim[6] = 1;
+   else /* just copy vals from arrays */
+      nim->nv = nim->dim[6];
+   nim->dv = nim->pixdim[6];
+
+   if(nim->dim[0] < 7 || (nim->dim[0] >= 7 && nim->dim[7] < 1))
+      nim->nw = nim->dim[7] = 1;
+   else /* just copy vals from arrays */
+      nim->nw = nim->dim[7];
+   nim->dw = nim->pixdim[7];
+
+   for( c = 1, nim->nvox = 1; c <= nim->dim[0]; c++ )
+      nim->nvox *= nim->dim[c];
+
+   /* compute ndim, assuming it can be no larger than the old one */
+   for( ndim = nim->dim[0]; (ndim > 1) && (nim->dim[ndim] <= 1); ndim-- )
+       ;
+
+   if( g_opts.debug > 2 ){
+      fprintf(stderr,"+d ndim = %d -> %d\n",nim->ndim, ndim);
+      fprintf(stderr," --> (%d,%d,%d,%d,%d,%d,%d)\n",
+              nim->nx, nim->ny, nim->nz, nim->nt, nim->nu, nim->nv, nim->nw);
+   }
+
+   nim->dim[0] = nim->ndim = ndim;
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! Load the image data from disk into an already-prepared image struct.
+ *
+ * \param    nim      - initialized nifti_image, without data
+ * \param    nbricks  - the length of blist (must be 0 if blist is NULL)
+ * \param    blist    - an array of xyz volume indices to read (can be NULL)
+ * \param    NBL      - pointer to struct where resulting data will be stored
+ *
+ * If blist is NULL, read all sub-bricks.
+ * 
+ * \return the number of loaded bricks (NBL->nbricks),
+ *    0 on failure, < 0 on error
+ *
+ * NOTE: it is likely that another function will copy the data pointers
+ *       out of NBL, in which case the only pointer the calling function
+ *       will want to free is NBL->bricks (not each NBL->bricks[i]).
+*//*--------------------------------------------------------------------*/
+int nifti_image_load_bricks( nifti_image * nim , int nbricks,
+                             const int * blist, nifti_brick_list * NBL )
+{
+   int     * slist = NULL, * sindex = NULL, rv;
+   znzFile   fp;
+
+   /* we can have blist == NULL */
+   if( !nim || !NBL ){
+      fprintf(stderr,"** nifti_image_load_bricks, bad params (%p,%p)\n",
+              (void *)nim, (void *)NBL);
+      return -1;
+   }
+
+   if( blist && nbricks <= 0 ){
+      if( g_opts.debug > 1 )
+         fprintf(stderr,"-d load_bricks: received blist with nbricks = %d,"
+                        "ignoring blist\n", nbricks);
+      blist = NULL; /* pretend nothing was passed */
+   }
+
+   if( blist && ! valid_nifti_brick_list( nim, nbricks, blist, g_opts.debug>0 ) )
+      return -1;
+
+   /* for efficiency, let's read the file in order */
+   if( blist && nifti_copynsort( nbricks, blist, &slist, &sindex ) != 0 )
+      return -1;
+
+   /* open the file and position the FILE pointer */
+   fp = nifti_image_load_prep( nim );
+   if( !fp ){
+      if( g_opts.debug > 0 )
+         fprintf(stderr,"** nifti_image_load_bricks, failed load_prep\n");
+      if( blist ){ free(slist); free(sindex); }
+      return -1;
+   }
+
+   /* this will flag to allocate defaults */
+   if( !blist ) nbricks = 0;
+   if( nifti_alloc_NBL_mem( nim, nbricks, NBL ) != 0 ){
+      if( blist ){ free(slist); free(sindex); }
+      znzclose(fp);
+      return -1;
+   }
+
+   rv = nifti_load_NBL_bricks(nim, slist, sindex, NBL, fp);
+
+   if( rv != 0 ){
+      nifti_free_NBL( NBL );  /* failure! */
+      NBL->nbricks = 0; /* repetative, but clear */
+   }
+
+   if( slist ){ free(slist); free(sindex); }
+
+   znzclose(fp);
+
+   return NBL->nbricks;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! nifti_free_NBL      - free all pointers and clear structure
+ *
+ * note: this does not presume to free the structure pointer
+*//*--------------------------------------------------------------------*/
+void nifti_free_NBL( nifti_brick_list * NBL )
+{
+   int c;
+
+   if( NBL->bricks ){
+      for( c = 0; c < NBL->nbricks; c++ )
+         if( NBL->bricks[c] ) free(NBL->bricks[c]);
+      free(NBL->bricks);
+      NBL->bricks = NULL;
+   }
+
+   NBL->nbricks = NBL->bsize = 0;
+}
+
+
+/*----------------------------------------------------------------------
+ * nifti_load_NBL_bricks      - read the file data into the NBL struct
+ *
+ * return 0 on success, -1 on failure
+ *----------------------------------------------------------------------*/
+static int nifti_load_NBL_bricks( nifti_image * nim , int * slist, int * sindex,
+                                  nifti_brick_list * NBL, znzFile fp )
+{
+   int c, rv;
+   int oposn, fposn;      /* orig and current file positions */
+   int prev, isrc, idest; /* previous and current sub-brick, and new index */
+
+   oposn = znztell(fp);  /* store current file position */
+   fposn = oposn;
+   if( fposn < 0 ){
+      fprintf(stderr,"** load bricks: ztell failed??\n");
+      return -1;
+   }
+
+   /* first, handle the default case, no passed blist */
+   if( !slist ){
+      for( c = 0; c < NBL->nbricks; c++ ) {
+         rv = nifti_read_buffer(fp, NBL->bricks[c], NBL->bsize, nim);
+         if( rv != NBL->bsize ){
+            fprintf(stderr,"** load bricks: cannot read brick %d from '%s'\n",
+                    c, nim->iname ? nim->iname : nim->fname);
+            return -1;
+         }
+      }
+      if( g_opts.debug > 1 )
+         fprintf(stderr,"+d read %d default bricks from file %s\n",
+                 NBL->nbricks, nim->iname ? nim->iname : nim->fname );
+      return 0;
+   }
+
+   if( !sindex ){
+      fprintf(stderr,"** load_NBL_bricks: missing index list\n");
+      return -1;
+   }
+
+   prev = -1;   /* use prev for previous sub-brick */
+   for( c = 0; c < NBL->nbricks; c++ ){
+       isrc = slist[c];   /* this is original brick index (c is new one) */
+       idest = sindex[c]; /* this is the destination index for this data */
+
+       /* if this sub-brick is not the previous, we must read from disk */
+       if( isrc != prev ){
+
+          /* if we are not looking at the correct sub-brick, scan forward */
+          if( fposn != (oposn + isrc*NBL->bsize) ){
+             fposn = oposn + isrc*NBL->bsize;
+             if( znzseek(fp, fposn, SEEK_SET) < 0 ){
+                fprintf(stderr,"** failed to locate brick %d in file '%s'\n",
+                        isrc, nim->iname ? nim->iname : nim->fname);
+                return -1;
+             }
+          }
+
+          /* only 10,000 lines later and we're actually reading something! */
+          rv = nifti_read_buffer(fp, NBL->bricks[idest], NBL->bsize, nim);
+          if( rv != NBL->bsize ){
+             fprintf(stderr,"** failed to read brick %d from file '%s'\n",
+                     isrc, nim->iname ? nim->iname : nim->fname);
+             return -1;
+          }
+          fposn += NBL->bsize;
+       } else {
+          /* we have already read this sub-brick, just copy the previous one */
+          /* note that this works because they are sorted */
+          memcpy(NBL->bricks[idest], NBL->bricks[sindex[c-1]], NBL->bsize);
+       }
+
+       prev = isrc;  /* in any case, note the now previous sub-brick */
+   }
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------
+ * nifti_alloc_NBL_mem      - allocate memory for bricks
+ *
+ * return 0 on success, -1 on failure
+ *----------------------------------------------------------------------*/
+static int nifti_alloc_NBL_mem(nifti_image * nim, int nbricks,
+                               nifti_brick_list * nbl)
+{
+   int c;
+
+   /* if nbricks is not specified, use the default */
+   if( nbricks > 0 ) nbl->nbricks = nbricks;
+   else {  /* I missed this one with the 1.17 change    02 Mar 2006 [rickr] */
+      nbl->nbricks = 1;
+      for( c = 4; c <= nim->ndim; c++ )
+          nbl->nbricks *= nim->dim[c];
+   }
+
+   nbl->bsize   = nim->nx * nim->ny * nim->nz * nim->nbyper;  /* bytes */
+   nbl->bricks  = (void **)malloc(nbl->nbricks * sizeof(void *));
+
+   if( ! nbl->bricks ){
+      fprintf(stderr,"** NANM: failed to alloc %d void ptrs\n",nbricks);
+      return -1;
+   }
+
+   for( c = 0; c < nbl->nbricks; c++ ){
+      nbl->bricks[c] = (void *)malloc(nbl->bsize);
+      if( ! nbl->bricks[c] ){
+         fprintf(stderr,"** NANM: failed to alloc %d bytes for brick %d\n",
+                 nbl->bsize, c);
+         /* so free and clear everything before returning */
+         while( c > 0 ){
+            c--;
+            free(nbl->bricks[c]);
+         }
+         free(nbl->bricks);
+         nbl->bricks = NULL;
+         nbl->nbricks = nbl->bsize = 0;
+         return -1;
+      }
+   }
+
+   if( g_opts.debug > 2 )
+      fprintf(stderr,"+d NANM: alloc'd %d bricks of %d bytes for NBL\n",
+              nbl->nbricks, nbl->bsize);
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------
+ * nifti_copynsort      - copy int list, and sort with indices
+ *
+ * 1. duplicate the incoming list
+ * 2. create an sindex list, and init with 0..nbricks-1
+ * 3. do a slow insertion sort on the small slist, along with sindex list
+ * 4. check results, just to be positive
+ * 
+ * So slist is sorted, and sindex hold original positions.
+ *
+ * return 0 on success, -1 on failure
+ *----------------------------------------------------------------------*/
+static int nifti_copynsort(int nbricks, const int * blist, int ** slist,
+                           int ** sindex)
+{
+   int * stmp, * itmp;   /* for ease of typing/reading */
+   int   c1, c2, spos, tmp;
+
+   *slist  = (int *)malloc(nbricks * sizeof(int));
+   *sindex = (int *)malloc(nbricks * sizeof(int));
+
+   if( !*slist || !*sindex ){
+      fprintf(stderr,"** NCS: failed to alloc %d ints for sorting\n",nbricks);
+      if(*slist)  free(*slist);   /* maybe one succeeded */
+      if(*sindex) free(*sindex);
+      return -1;
+   }
+
+   /* init the lists */
+   memcpy(*slist, blist, nbricks*sizeof(int));
+   for( c1 = 0; c1 < nbricks; c1++ ) (*sindex)[c1] = c1;
+
+   /* now actually sort slist */
+   stmp = *slist;
+   itmp = *sindex;
+   for( c1 = 0; c1 < nbricks-1; c1++ ) {
+      /* find smallest value, init to current */
+      spos = c1;
+      for( c2 = c1+1; c2 < nbricks; c2++ )
+         if( stmp[c2] < stmp[spos] ) spos = c2;
+      if( spos != c1 ) /* swap: fine, don't maintain sub-order, see if I care */
+      {
+         tmp        = stmp[c1];      /* first swap the sorting values */
+         stmp[c1]   = stmp[spos];
+         stmp[spos] = tmp;
+
+         tmp        = itmp[c1];      /* then swap the index values */
+         itmp[c1]   = itmp[spos];
+         itmp[spos] = tmp;
+      }
+   }
+
+   if( g_opts.debug > 2 ){
+      fprintf(stderr,  "+d sorted indexing list:\n");
+      fprintf(stderr,  "  orig   : ");
+      for( c1 = 0; c1 < nbricks; c1++ ) fprintf(stderr,"  %d",blist[c1]);
+      fprintf(stderr,"\n  new    : ");
+      for( c1 = 0; c1 < nbricks; c1++ ) fprintf(stderr,"  %d",stmp[c1]);
+      fprintf(stderr,"\n  indices: ");
+      for( c1 = 0; c1 < nbricks; c1++ ) fprintf(stderr,"  %d",itmp[c1]);
+      fputc('\n', stderr);
+   }
+
+   /* check the sort (why not?  I've got time...) */
+   for( c1 = 0; c1 < nbricks-1; c1++ ){
+       if( (stmp[c1] > stmp[c1+1]) || (blist[itmp[c1]] != stmp[c1]) ){
+          fprintf(stderr,"** sorting screw-up, way to go, rick!\n");
+          free(stmp); free(itmp); *slist = NULL; *sindex = NULL;
+          return -1;
+       }
+   }
+
+   if( g_opts.debug > 2 ) fprintf(stderr,"-d sorting is okay\n");
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! valid_nifti_brick_list      - check sub-brick list for image
+ *
+ * This function verifies that nbricks and blist are appropriate
+ * for use with this nim, based on the dimensions.
+ *
+ * \param nim        nifti_image to check against
+ * \param nbricks    number of brick indices in blist
+ * \param blist      list of brick indices to check in nim
+ * \param disp_error if this flag is set, report errors to user
+ *
+ * \return 1 if valid, 0 if not
+*//*--------------------------------------------------------------------*/
+int valid_nifti_brick_list(nifti_image * nim , int nbricks,
+                           const int * blist, int disp_error)
+{
+   int c, nsubs;
+
+   if( !nim ){
+      if( disp_error || g_opts.debug > 0 )
+         fprintf(stderr,"** valid_nifti_brick_list: missing nifti image\n");
+      return 0;
+   }
+
+   if( nbricks <= 0 || !blist ){
+      if( disp_error || g_opts.debug > 1 )
+         fprintf(stderr,"** valid_nifti_brick_list: no brick list to check\n");
+      return 0;
+   }
+
+   /* nsubs sub-brick is nt*nu*nv*nw */
+   for( c = 4, nsubs = 1; c <= nim->dim[0]; c++ )
+      nsubs *= nim->dim[c];
+
+   if( nsubs <= 0 ){
+      fprintf(stderr,"** VNBL warning: bad dim list (%d,%d,%d,%d)\n",
+                     nim->dim[4], nim->dim[5], nim->dim[6], nim->dim[7]);
+      return 0;
+   }
+
+   for( c = 0; c < nbricks; c++ )
+      if( (blist[c] < 0) || (blist[c] >= nsubs) ){
+         if( disp_error || g_opts.debug > 1 )
+            fprintf(stderr,
+               "-d ** bad sub-brick chooser %d (#%d), valid range is [0,%d]\n",
+               blist[c], c, nsubs-1);
+         return 0;
+      }
+
+   return 1;  /* all is well */
+}
+
+#if 0
+/* set any non-positive values to 1 */
+static int int_force_positive( int * list, int nel )
+{
+   int c;
+   if( !list || nel < 0 ){
+      if( g_opts.debug > 0 )
+         fprintf(stderr,"** int_force_positive: bad params (%p,%d)\n",
+                 (void *)list,nel);
+      return -1;
+   }
+   for( c = 0; c < nel; c++ )
+      if( list[c] <= 0 ) list[c] = 1;
+   return 0;
+}
+#endif
+/* end of new nifti_image_read_bricks() functionality */
+
+/*----------------------------------------------------------------------*/
+/*! display the orientation from the quaternian fields
+ *
+ * \param mesg if non-NULL, display this message first
+ * \param mat  the matrix to convert to "nearest" orientation
+ *
+ * \return -1 if results cannot be determined, 0 if okay
+*//*--------------------------------------------------------------------*/
+int nifti_disp_matrix_orient( const char * mesg, mat44 mat )
+{
+   int i, j, k;
+
+   if ( mesg ) fputs( mesg, stderr );  /* use stdout? */
+
+   nifti_mat44_to_orientation( mat, &i,&j,&k );
+   if ( i <= 0 || j <= 0 || k <= 0 ) return -1;
+
+   /* so we have good codes */
+   fprintf(stderr, "  i orientation = '%s'\n"
+                   "  j orientation = '%s'\n"
+                   "  k orientation = '%s'\n",
+                   nifti_orientation_string(i),
+                   nifti_orientation_string(j),
+                   nifti_orientation_string(k) );
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! duplicate the given string (alloc length+1)
+ *
+ * \return allocated pointer (or NULL on failure)
+*//*--------------------------------------------------------------------*/
+char *nifti_strdup(const char *str)
+{
+  char *dup= (char *)malloc( strlen(str)+1 );
+  if (dup) strcpy(dup,str);
+  return dup;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/*! Return a pointer to a string holding the name of a NIFTI datatype.
+
+    \param dt NIfTI-1 datatype
+
+    \return pointer to static string holding the datatype name
+
+    \warning Do not free() or modify this string!
+             It points to static storage.
+
+    \sa NIFTI1_DATATYPES group in nifti1.h
+*//*-------------------------------------------------------------------------*/
+char *nifti_datatype_string( int dt )
+{
+   switch( dt ){
+     case DT_UNKNOWN:    return "UNKNOWN"    ;
+     case DT_BINARY:     return "BINARY"     ;
+     case DT_INT8:       return "INT8"       ;
+     case DT_UINT8:      return "UINT8"      ;
+     case DT_INT16:      return "INT16"      ;
+     case DT_UINT16:     return "UINT16"     ;
+     case DT_INT32:      return "INT32"      ;
+     case DT_UINT32:     return "UINT32"     ;
+     case DT_INT64:      return "INT64"      ;
+     case DT_UINT64:     return "UINT64"     ;
+     case DT_FLOAT32:    return "FLOAT32"    ;
+     case DT_FLOAT64:    return "FLOAT64"    ;
+     case DT_FLOAT128:   return "FLOAT128"   ;
+     case DT_COMPLEX64:  return "COMPLEX64"  ;
+     case DT_COMPLEX128: return "COMPLEX128" ;
+     case DT_COMPLEX256: return "COMPLEX256" ;
+     case DT_RGB24:      return "RGB24"      ;
+   }
+   return "**ILLEGAL**" ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! Determine if the datatype code dt is an integer type (1=YES, 0=NO).
+
+    \return whether the given NIfTI-1 datatype code is valid
+
+    \sa     NIFTI1_DATATYPES group in nifti1.h
+*//*--------------------------------------------------------------------*/
+int nifti_is_inttype( int dt )
+{
+   switch( dt ){
+     case DT_UNKNOWN:    return 0 ;
+     case DT_BINARY:     return 0 ;
+     case DT_INT8:       return 1 ;
+     case DT_UINT8:      return 1 ;
+     case DT_INT16:      return 1 ;
+     case DT_UINT16:     return 1 ;
+     case DT_INT32:      return 1 ;
+     case DT_UINT32:     return 1 ;
+     case DT_INT64:      return 1 ;
+     case DT_UINT64:     return 1 ;
+     case DT_FLOAT32:    return 0 ;
+     case DT_FLOAT64:    return 0 ;
+     case DT_FLOAT128:   return 0 ;
+     case DT_COMPLEX64:  return 0 ;
+     case DT_COMPLEX128: return 0 ;
+     case DT_COMPLEX256: return 0 ;
+     case DT_RGB24:      return 1 ;
+   }
+   return 0 ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Return a pointer to a string holding the name of a NIFTI units type.
+
+    \param  uu NIfTI-1 unit code
+
+    \return pointer to static string for the given unit type
+
+    \warning Do not free() or modify this string!
+             It points to static storage.
+
+    \sa     NIFTI1_UNITS group in nifti1.h
+*//*-------------------------------------------------------------------------*/
+char *nifti_units_string( int uu )
+{
+   switch( uu ){
+     case NIFTI_UNITS_METER:  return "m" ;
+     case NIFTI_UNITS_MM:     return "mm" ;
+     case NIFTI_UNITS_MICRON: return "um" ;
+     case NIFTI_UNITS_SEC:    return "s" ;
+     case NIFTI_UNITS_MSEC:   return "ms" ;
+     case NIFTI_UNITS_USEC:   return "us" ;
+     case NIFTI_UNITS_HZ:     return "Hz" ;
+     case NIFTI_UNITS_PPM:    return "ppm" ;
+     case NIFTI_UNITS_RADS:   return "rad/s" ;
+   }
+   return "Unknown" ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Return a pointer to a string holding the name of a NIFTI transform type.
+
+    \param  xx NIfTI-1 xform code
+
+    \return pointer to static string describing xform code
+
+    \warning Do not free() or modify this string!
+             It points to static storage.
+
+    \sa     NIFTI1_XFORM_CODES group in nifti1.h
+*//*-------------------------------------------------------------------------*/
+char *nifti_xform_string( int xx )
+{
+   switch( xx ){
+     case NIFTI_XFORM_SCANNER_ANAT:  return "Scanner Anat" ;
+     case NIFTI_XFORM_ALIGNED_ANAT:  return "Aligned Anat" ;
+     case NIFTI_XFORM_TALAIRACH:     return "Talairach" ;
+     case NIFTI_XFORM_MNI_152:       return "MNI_152" ;
+   }
+   return "Unknown" ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Return a pointer to a string holding the name of a NIFTI intent type.
+
+    \param  ii NIfTI-1 intent code
+
+    \return pointer to static string describing code
+
+    \warning Do not free() or modify this string!
+             It points to static storage.
+
+    \sa     NIFTI1_INTENT_CODES group in nifti1.h
+*//*-------------------------------------------------------------------------*/
+char *nifti_intent_string( int ii )
+{
+   switch( ii ){
+     case NIFTI_INTENT_CORREL:     return "Correlation statistic" ;
+     case NIFTI_INTENT_TTEST:      return "T-statistic" ;
+     case NIFTI_INTENT_FTEST:      return "F-statistic" ;
+     case NIFTI_INTENT_ZSCORE:     return "Z-score"     ;
+     case NIFTI_INTENT_CHISQ:      return "Chi-squared distribution" ;
+     case NIFTI_INTENT_BETA:       return "Beta distribution" ;
+     case NIFTI_INTENT_BINOM:      return "Binomial distribution" ;
+     case NIFTI_INTENT_GAMMA:      return "Gamma distribution" ;
+     case NIFTI_INTENT_POISSON:    return "Poisson distribution" ;
+     case NIFTI_INTENT_NORMAL:     return "Normal distribution" ;
+     case NIFTI_INTENT_FTEST_NONC: return "F-statistic noncentral" ;
+     case NIFTI_INTENT_CHISQ_NONC: return "Chi-squared noncentral" ;
+     case NIFTI_INTENT_LOGISTIC:   return "Logistic distribution" ;
+     case NIFTI_INTENT_LAPLACE:    return "Laplace distribution" ;
+     case NIFTI_INTENT_UNIFORM:    return "Uniform distribition" ;
+     case NIFTI_INTENT_TTEST_NONC: return "T-statistic noncentral" ;
+     case NIFTI_INTENT_WEIBULL:    return "Weibull distribution" ;
+     case NIFTI_INTENT_CHI:        return "Chi distribution" ;
+     case NIFTI_INTENT_INVGAUSS:   return "Inverse Gaussian distribution" ;
+     case NIFTI_INTENT_EXTVAL:     return "Extreme Value distribution" ;
+     case NIFTI_INTENT_PVAL:       return "P-value" ;
+
+     case NIFTI_INTENT_LOGPVAL:    return "Log P-value" ;
+     case NIFTI_INTENT_LOG10PVAL:  return "Log10 P-value" ;
+
+     case NIFTI_INTENT_ESTIMATE:   return "Estimate" ;
+     case NIFTI_INTENT_LABEL:      return "Label index" ;
+     case NIFTI_INTENT_NEURONAME:  return "NeuroNames index" ;
+     case NIFTI_INTENT_GENMATRIX:  return "General matrix" ;
+     case NIFTI_INTENT_SYMMATRIX:  return "Symmetric matrix" ;
+     case NIFTI_INTENT_DISPVECT:   return "Displacement vector" ;
+     case NIFTI_INTENT_VECTOR:     return "Vector" ;
+     case NIFTI_INTENT_POINTSET:   return "Pointset" ;
+     case NIFTI_INTENT_TRIANGLE:   return "Triangle" ;
+     case NIFTI_INTENT_QUATERNION: return "Quaternion" ;
+
+     case NIFTI_INTENT_DIMLESS:    return "Dimensionless number" ;
+   }
+   return "Unknown" ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Return a pointer to a string holding the name of a NIFTI slice_code.
+
+    \param  ss NIfTI-1 slice order code
+
+    \return pointer to static string describing code
+
+    \warning Do not free() or modify this string!
+             It points to static storage.
+
+    \sa     NIFTI1_SLICE_ORDER group in nifti1.h
+*//*-------------------------------------------------------------------------*/
+char *nifti_slice_string( int ss )
+{
+   switch( ss ){
+     case NIFTI_SLICE_SEQ_INC:  return "sequential_increasing"    ;
+     case NIFTI_SLICE_SEQ_DEC:  return "sequential_decreasing"    ;
+     case NIFTI_SLICE_ALT_INC:  return "alternating_increasing"   ;
+     case NIFTI_SLICE_ALT_DEC:  return "alternating_decreasing"   ;
+     case NIFTI_SLICE_ALT_INC2: return "alternating_increasing_2" ;
+     case NIFTI_SLICE_ALT_DEC2: return "alternating_decreasing_2" ;
+   }
+   return "Unknown" ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Return a pointer to a string holding the name of a NIFTI orientation.
+
+    \param ii orientation code
+
+    \return pointer to static string holding the orientation information
+
+    \warning Do not free() or modify the return string!
+             It points to static storage.
+
+    \sa  NIFTI_L2R in nifti1_io.h
+*//*-------------------------------------------------------------------------*/
+char *nifti_orientation_string( int ii )
+{
+   switch( ii ){
+     case NIFTI_L2R: return "Left-to-Right" ;
+     case NIFTI_R2L: return "Right-to-Left" ;
+     case NIFTI_P2A: return "Posterior-to-Anterior" ;
+     case NIFTI_A2P: return "Anterior-to-Posterior" ;
+     case NIFTI_I2S: return "Inferior-to-Superior" ;
+     case NIFTI_S2I: return "Superior-to-Inferior" ;
+   }
+   return "Unknown" ;
+}
+
+/*--------------------------------------------------------------------------*/
+/*! Given a datatype code, set number of bytes per voxel and the swapsize.
+
+    \param datatype nifti1 datatype code
+    \param nbyper   pointer to return value: number of bytes per voxel
+    \param swapsize pointer to return value: size of swap blocks
+
+    \return appropriate values at nbyper and swapsize
+
+    The swapsize is set to 0 if this datatype doesn't ever need swapping.
+
+    \sa NIFTI1_DATATYPES in nifti1.h
+*//*------------------------------------------------------------------------*/
+void nifti_datatype_sizes( int datatype , int *nbyper, int *swapsize )
+{
+   int nb=0, ss=0 ;
+   switch( datatype ){
+     case DT_INT8:
+     case DT_UINT8:       nb =  1 ; ss =  0 ; break ;
+
+     case DT_INT16:
+     case DT_UINT16:      nb =  2 ; ss =  2 ; break ;
+
+     case DT_RGB24:       nb =  3 ; ss =  0 ; break ;
+
+     case DT_INT32:
+     case DT_UINT32:
+     case DT_FLOAT32:     nb =  4 ; ss =  4 ; break ;
+
+     case DT_COMPLEX64:   nb =  8 ; ss =  4 ; break ;
+
+     case DT_FLOAT64:
+     case DT_INT64:
+     case DT_UINT64:      nb =  8 ; ss =  8 ; break ;
+
+     case DT_FLOAT128:    nb = 16 ; ss = 16 ; break ;
+
+     case DT_COMPLEX128:  nb = 16 ; ss =  8 ; break ;
+
+     case DT_COMPLEX256:  nb = 32 ; ss = 16 ; break ;
+   }
+
+   ASSIF(nbyper,nb) ; ASSIF(swapsize,ss) ; return ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Given the quaternion parameters (etc.), compute a transformation matrix.
+
+   See comments in nifti1.h for details.
+     - qb,qc,qd = quaternion parameters
+     - qx,qy,qz = offset parameters
+     - dx,dy,dz = grid stepsizes (non-negative inputs are set to 1.0)
+     - qfac     = sign of dz step (< 0 is negative; >= 0 is positive)
+
+   <pre>
+   If qx=qy=qz=0, dx=dy=dz=1, then the output is a rotation matrix.
+   For qfac >= 0, the rotation is proper.
+   For qfac <  0, the rotation is improper.
+   </pre>
+
+   \see "QUATERNION REPRESENTATION OF ROTATION MATRIX" in nifti1.h
+   \see nifti_mat44_to_quatern, nifti_make_orthog_mat44,
+       nifti_mat44_to_orientation
+
+*//*-------------------------------------------------------------------------*/
+mat44 nifti_quatern_to_mat44( float qb, float qc, float qd,
+                              float qx, float qy, float qz,
+                              float dx, float dy, float dz, float qfac )
+{
+   mat44 R ;
+   double a,b=qb,c=qc,d=qd , xd,yd,zd ;
+
+   /* last row is always [ 0 0 0 1 ] */
+
+   R.m[3][0]=R.m[3][1]=R.m[3][2] = 0.0 ; R.m[3][3]= 1.0 ;
+
+   /* compute a parameter from b,c,d */
+
+   a = 1.0l - (b*b + c*c + d*d) ;
+   if( a < 1.e-7l ){                   /* special case */
+     a = 1.0l / sqrt(b*b+c*c+d*d) ;
+     b *= a ; c *= a ; d *= a ;        /* normalize (b,c,d) vector */
+     a = 0.0l ;                        /* a = 0 ==> 180 degree rotation */
+   } else{
+     a = sqrt(a) ;                     /* angle = 2*arccos(a) */
+   }
+
+   /* load rotation matrix, including scaling factors for voxel sizes */
+
+   xd = (dx > 0.0) ? dx : 1.0l ;       /* make sure are positive */
+   yd = (dy > 0.0) ? dy : 1.0l ;
+   zd = (dz > 0.0) ? dz : 1.0l ;
+
+   if( qfac < 0.0 ) zd = -zd ;         /* left handedness? */
+
+   R.m[0][0] =        (a*a+b*b-c*c-d*d) * xd ;
+   R.m[0][1] = 2.0l * (b*c-a*d        ) * yd ;
+   R.m[0][2] = 2.0l * (b*d+a*c        ) * zd ;
+   R.m[1][0] = 2.0l * (b*c+a*d        ) * xd ;
+   R.m[1][1] =        (a*a+c*c-b*b-d*d) * yd ;
+   R.m[1][2] = 2.0l * (c*d-a*b        ) * zd ;
+   R.m[2][0] = 2.0l * (b*d-a*c        ) * xd ;
+   R.m[2][1] = 2.0l * (c*d+a*b        ) * yd ;
+   R.m[2][2] =        (a*a+d*d-c*c-b*b) * zd ;
+
+   /* load offsets */
+
+   R.m[0][3] = qx ; R.m[1][3] = qy ; R.m[2][3] = qz ;
+
+   return R ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Given the 3x4 upper corner of the matrix R, compute the quaternion
+   parameters that fit it.
+
+     - Any NULL pointer on input won't get assigned (e.g., if you don't want
+       dx,dy,dz, just pass NULL in for those pointers).
+     - If the 3 input matrix columns are NOT orthogonal, they will be
+       orthogonalized prior to calculating the parameters, using
+       the polar decomposition to find the orthogonal matrix closest
+       to the column-normalized input matrix.
+     - However, if the 3 input matrix columns are NOT orthogonal, then
+       the matrix produced by nifti_quatern_to_mat44 WILL have orthogonal
+       columns, so it won't be the same as the matrix input here.
+       This "feature" is because the NIFTI 'qform' transform is
+       deliberately not fully general -- it is intended to model a volume
+       with perpendicular axes.
+     - If the 3 input matrix columns are not even linearly independent,
+       you'll just have to take your luck, won't you?
+
+   \see "QUATERNION REPRESENTATION OF ROTATION MATRIX" in nifti1.h
+
+   \see nifti_quatern_to_mat44, nifti_make_orthog_mat44,
+       nifti_mat44_to_orientation
+*//*-------------------------------------------------------------------------*/
+void nifti_mat44_to_quatern( mat44 R ,
+                             float *qb, float *qc, float *qd,
+                             float *qx, float *qy, float *qz,
+                             float *dx, float *dy, float *dz, float *qfac )
+{
+   double r11,r12,r13 , r21,r22,r23 , r31,r32,r33 ;
+   double xd,yd,zd , a,b,c,d ;
+   mat33 P,Q ;
+
+   /* offset outputs are read write out of input matrix  */
+
+   ASSIF(qx,R.m[0][3]) ; ASSIF(qy,R.m[1][3]) ; ASSIF(qz,R.m[2][3]) ;
+
+   /* load 3x3 matrix into local variables */
+
+   r11 = R.m[0][0] ; r12 = R.m[0][1] ; r13 = R.m[0][2] ;
+   r21 = R.m[1][0] ; r22 = R.m[1][1] ; r23 = R.m[1][2] ;
+   r31 = R.m[2][0] ; r32 = R.m[2][1] ; r33 = R.m[2][2] ;
+
+   /* compute lengths of each column; these determine grid spacings  */
+
+   xd = sqrt( r11*r11 + r21*r21 + r31*r31 ) ;
+   yd = sqrt( r12*r12 + r22*r22 + r32*r32 ) ;
+   zd = sqrt( r13*r13 + r23*r23 + r33*r33 ) ;
+
+   /* if a column length is zero, patch the trouble */
+
+   if( xd == 0.0l ){ r11 = 1.0l ; r21 = r31 = 0.0l ; xd = 1.0l ; }
+   if( yd == 0.0l ){ r22 = 1.0l ; r12 = r32 = 0.0l ; yd = 1.0l ; }
+   if( zd == 0.0l ){ r33 = 1.0l ; r13 = r23 = 0.0l ; zd = 1.0l ; }
+
+   /* assign the output lengths */
+
+   ASSIF(dx,xd) ; ASSIF(dy,yd) ; ASSIF(dz,zd) ;
+
+   /* normalize the columns */
+
+   r11 /= xd ; r21 /= xd ; r31 /= xd ;
+   r12 /= yd ; r22 /= yd ; r32 /= yd ;
+   r13 /= zd ; r23 /= zd ; r33 /= zd ;
+
+   /* At this point, the matrix has normal columns, but we have to allow
+      for the fact that the hideous user may not have given us a matrix
+      with orthogonal columns.
+
+      So, now find the orthogonal matrix closest to the current matrix.
+
+      One reason for using the polar decomposition to get this
+      orthogonal matrix, rather than just directly orthogonalizing
+      the columns, is so that inputting the inverse matrix to R
+      will result in the inverse orthogonal matrix at this point.
+      If we just orthogonalized the columns, this wouldn't necessarily hold. */
+
+   Q.m[0][0] = r11 ; Q.m[0][1] = r12 ; Q.m[0][2] = r13 ; /* load Q */
+   Q.m[1][0] = r21 ; Q.m[1][1] = r22 ; Q.m[1][2] = r23 ;
+   Q.m[2][0] = r31 ; Q.m[2][1] = r32 ; Q.m[2][2] = r33 ;
+
+   P = nifti_mat33_polar(Q) ;  /* P is orthog matrix closest to Q */
+
+   r11 = P.m[0][0] ; r12 = P.m[0][1] ; r13 = P.m[0][2] ; /* unload */
+   r21 = P.m[1][0] ; r22 = P.m[1][1] ; r23 = P.m[1][2] ;
+   r31 = P.m[2][0] ; r32 = P.m[2][1] ; r33 = P.m[2][2] ;
+
+   /*                            [ r11 r12 r13 ]               */
+   /* at this point, the matrix  [ r21 r22 r23 ] is orthogonal */
+   /*                            [ r31 r32 r33 ]               */
+
+   /* compute the determinant to determine if it is proper */
+
+   zd = r11*r22*r33-r11*r32*r23-r21*r12*r33
+       +r21*r32*r13+r31*r12*r23-r31*r22*r13 ;  /* should be -1 or 1 */
+
+   if( zd > 0 ){             /* proper */
+     ASSIF(qfac,1.0) ;
+   } else {                  /* improper ==> flip 3rd column */
+     ASSIF(qfac,-1.0) ;
+     r13 = -r13 ; r23 = -r23 ; r33 = -r33 ;
+   }
+
+   /* now, compute quaternion parameters */
+
+   a = r11 + r22 + r33 + 1.0l ;
+
+   if( a > 0.5l ){                /* simplest case */
+     a = 0.5l * sqrt(a) ;
+     b = 0.25l * (r32-r23) / a ;
+     c = 0.25l * (r13-r31) / a ;
+     d = 0.25l * (r21-r12) / a ;
+   } else {                       /* trickier case */
+     xd = 1.0 + r11 - (r22+r33) ;  /* 4*b*b */
+     yd = 1.0 + r22 - (r11+r33) ;  /* 4*c*c */
+     zd = 1.0 + r33 - (r11+r22) ;  /* 4*d*d */
+     if( xd > 1.0 ){
+       b = 0.5l * sqrt(xd) ;
+       c = 0.25l* (r12+r21) / b ;
+       d = 0.25l* (r13+r31) / b ;
+       a = 0.25l* (r32-r23) / b ;
+     } else if( yd > 1.0 ){
+       c = 0.5l * sqrt(yd) ;
+       b = 0.25l* (r12+r21) / c ;
+       d = 0.25l* (r23+r32) / c ;
+       a = 0.25l* (r13-r31) / c ;
+     } else {
+       d = 0.5l * sqrt(zd) ;
+       b = 0.25l* (r13+r31) / d ;
+       c = 0.25l* (r23+r32) / d ;
+       a = 0.25l* (r21-r12) / d ;
+     }
+     if( a < 0.0l ){ b=-b ; c=-c ; d=-d; a=-a; }
+   }
+
+   ASSIF(qb,b) ; ASSIF(qc,c) ; ASSIF(qd,d) ;
+   return ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Compute the inverse of a bordered 4x4 matrix.
+
+     <pre>
+   - Some numerical code fragments were generated by Maple 8.
+   - If a singular matrix is input, the output matrix will be all zero.
+   - You can check for this by examining the [3][3] element, which will
+     be 1.0 for the normal case and 0.0 for the bad case.
+
+     The input matrix should have the form:
+        [ r11 r12 r13 v1 ]
+        [ r21 r22 r23 v2 ]
+        [ r31 r32 r33 v3 ]
+        [  0   0   0   1 ]
+     </pre>
+*//*-------------------------------------------------------------------------*/
+mat44 nifti_mat44_inverse( mat44 R )
+{
+   double r11,r12,r13,r21,r22,r23,r31,r32,r33,v1,v2,v3 , deti ;
+   mat44 Q ;
+                                                       /*  INPUT MATRIX IS:  */
+   r11 = R.m[0][0]; r12 = R.m[0][1]; r13 = R.m[0][2];  /* [ r11 r12 r13 v1 ] */
+   r21 = R.m[1][0]; r22 = R.m[1][1]; r23 = R.m[1][2];  /* [ r21 r22 r23 v2 ] */
+   r31 = R.m[2][0]; r32 = R.m[2][1]; r33 = R.m[2][2];  /* [ r31 r32 r33 v3 ] */
+   v1  = R.m[0][3]; v2  = R.m[1][3]; v3  = R.m[2][3];  /* [  0   0   0   1 ] */
+
+   deti = r11*r22*r33-r11*r32*r23-r21*r12*r33
+         +r21*r32*r13+r31*r12*r23-r31*r22*r13 ;
+
+   if( deti != 0.0l ) deti = 1.0l / deti ;
+
+   Q.m[0][0] = deti*( r22*r33-r32*r23) ;
+   Q.m[0][1] = deti*(-r12*r33+r32*r13) ;
+   Q.m[0][2] = deti*( r12*r23-r22*r13) ;
+   Q.m[0][3] = deti*(-r12*r23*v3+r12*v2*r33+r22*r13*v3
+                     -r22*v1*r33-r32*r13*v2+r32*v1*r23) ;
+
+   Q.m[1][0] = deti*(-r21*r33+r31*r23) ;
+   Q.m[1][1] = deti*( r11*r33-r31*r13) ;
+   Q.m[1][2] = deti*(-r11*r23+r21*r13) ;
+   Q.m[1][3] = deti*( r11*r23*v3-r11*v2*r33-r21*r13*v3
+                     +r21*v1*r33+r31*r13*v2-r31*v1*r23) ;
+
+   Q.m[2][0] = deti*( r21*r32-r31*r22) ;
+   Q.m[2][1] = deti*(-r11*r32+r31*r12) ;
+   Q.m[2][2] = deti*( r11*r22-r21*r12) ;
+   Q.m[2][3] = deti*(-r11*r22*v3+r11*r32*v2+r21*r12*v3
+                     -r21*r32*v1-r31*r12*v2+r31*r22*v1) ;
+
+   Q.m[3][0] = Q.m[3][1] = Q.m[3][2] = 0.0l ;
+   Q.m[3][3] = (deti == 0.0l) ? 0.0l : 1.0l ; /* failure flag if deti == 0 */
+
+   return Q ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Input 9 floats and make an orthgonal mat44 out of them.
+
+   Each row is normalized, then nifti_mat33_polar() is used to orthogonalize
+   them.  If row #3 (r31,r32,r33) is input as zero, then it will be taken to
+   be the cross product of rows #1 and #2.
+
+   This function can be used to create a rotation matrix for transforming
+   an oblique volume to anatomical coordinates.  For this application:
+    - row #1 (r11,r12,r13) is the direction vector along the image i-axis
+    - row #2 (r21,r22,r23) is the direction vector along the image j-axis
+    - row #3 (r31,r32,r33) is the direction vector along the slice direction
+      (if available; otherwise enter it as 0's)
+
+   The first 2 rows can be taken from the DICOM attribute (0020,0037)
+   "Image Orientation (Patient)".
+
+   After forming the rotation matrix, the complete affine transformation from
+   (i,j,k) grid indexes to (x,y,z) spatial coordinates can be computed by
+   multiplying each column by the appropriate grid spacing:
+    - column #1 (R.m[0][0],R.m[1][0],R.m[2][0]) by delta-x
+    - column #2 (R.m[0][1],R.m[1][1],R.m[2][1]) by delta-y
+    - column #3 (R.m[0][2],R.m[1][2],R.m[2][2]) by delta-z
+
+   and by then placing the center (x,y,z) coordinates of voxel (0,0,0) into
+   the column #4 (R.m[0][3],R.m[1][3],R.m[2][3]).
+
+   \sa nifti_quatern_to_mat44, nifti_mat44_to_quatern,
+       nifti_mat44_to_orientation
+*//*-------------------------------------------------------------------------*/
+mat44 nifti_make_orthog_mat44( float r11, float r12, float r13 ,
+                               float r21, float r22, float r23 ,
+                               float r31, float r32, float r33  )
+{
+   mat44 R ;
+   mat33 Q , P ;
+   double val ;
+
+   R.m[3][0] = R.m[3][1] = R.m[3][2] = 0.0l ; R.m[3][3] = 1.0l ;
+
+   Q.m[0][0] = r11 ; Q.m[0][1] = r12 ; Q.m[0][2] = r13 ; /* load Q */
+   Q.m[1][0] = r21 ; Q.m[1][1] = r22 ; Q.m[1][2] = r23 ;
+   Q.m[2][0] = r31 ; Q.m[2][1] = r32 ; Q.m[2][2] = r33 ;
+
+   /* normalize row 1 */
+
+   val = Q.m[0][0]*Q.m[0][0] + Q.m[0][1]*Q.m[0][1] + Q.m[0][2]*Q.m[0][2] ;
+   if( val > 0.0l ){
+     val = 1.0l / sqrt(val) ;
+     Q.m[0][0] *= val ; Q.m[0][1] *= val ; Q.m[0][2] *= val ;
+   } else {
+     Q.m[0][0] = 1.0l ; Q.m[0][1] = 0.0l ; Q.m[0][2] = 0.0l ;
+   }
+
+   /* normalize row 2 */
+
+   val = Q.m[1][0]*Q.m[1][0] + Q.m[1][1]*Q.m[1][1] + Q.m[1][2]*Q.m[1][2] ;
+   if( val > 0.0l ){
+     val = 1.0l / sqrt(val) ;
+     Q.m[1][0] *= val ; Q.m[1][1] *= val ; Q.m[1][2] *= val ;
+   } else {
+     Q.m[1][0] = 0.0l ; Q.m[1][1] = 1.0l ; Q.m[1][2] = 0.0l ;
+   }
+
+   /* normalize row 3 */
+
+   val = Q.m[2][0]*Q.m[2][0] + Q.m[2][1]*Q.m[2][1] + Q.m[2][2]*Q.m[2][2] ;
+   if( val > 0.0l ){
+     val = 1.0l / sqrt(val) ;
+     Q.m[2][0] *= val ; Q.m[2][1] *= val ; Q.m[2][2] *= val ;
+   } else {
+     Q.m[2][0] = Q.m[0][1]*Q.m[1][2] - Q.m[0][2]*Q.m[1][1] ;  /* cross */
+     Q.m[2][1] = Q.m[0][2]*Q.m[1][0] - Q.m[0][0]*Q.m[1][2] ;  /* product */
+     Q.m[2][2] = Q.m[0][0]*Q.m[1][1] - Q.m[0][1]*Q.m[1][0] ;
+   }
+
+   P = nifti_mat33_polar(Q) ;  /* P is orthog matrix closest to Q */
+
+   R.m[0][0] = P.m[0][0] ; R.m[0][1] = P.m[0][1] ; R.m[0][2] = P.m[0][2] ;
+   R.m[1][0] = P.m[1][0] ; R.m[1][1] = P.m[1][1] ; R.m[1][2] = P.m[1][2] ;
+   R.m[2][0] = P.m[2][0] ; R.m[2][1] = P.m[2][1] ; R.m[2][2] = P.m[2][2] ;
+
+   R.m[0][3] = R.m[1][3] = R.m[2][3] = 0.0 ; return R ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! compute the inverse of a 3x3 matrix
+*//*--------------------------------------------------------------------*/
+mat33 nifti_mat33_inverse( mat33 R )   /* inverse of 3x3 matrix */
+{
+   double r11,r12,r13,r21,r22,r23,r31,r32,r33 , deti ;
+   mat33 Q ;
+                                                       /*  INPUT MATRIX:  */
+   r11 = R.m[0][0]; r12 = R.m[0][1]; r13 = R.m[0][2];  /* [ r11 r12 r13 ] */
+   r21 = R.m[1][0]; r22 = R.m[1][1]; r23 = R.m[1][2];  /* [ r21 r22 r23 ] */
+   r31 = R.m[2][0]; r32 = R.m[2][1]; r33 = R.m[2][2];  /* [ r31 r32 r33 ] */
+
+   deti = r11*r22*r33-r11*r32*r23-r21*r12*r33
+         +r21*r32*r13+r31*r12*r23-r31*r22*r13 ;
+
+   if( deti != 0.0l ) deti = 1.0l / deti ;
+
+   Q.m[0][0] = deti*( r22*r33-r32*r23) ;
+   Q.m[0][1] = deti*(-r12*r33+r32*r13) ;
+   Q.m[0][2] = deti*( r12*r23-r22*r13) ;
+
+   Q.m[1][0] = deti*(-r21*r33+r31*r23) ;
+   Q.m[1][1] = deti*( r11*r33-r31*r13) ;
+   Q.m[1][2] = deti*(-r11*r23+r21*r13) ;
+
+   Q.m[2][0] = deti*( r21*r32-r31*r22) ;
+   Q.m[2][1] = deti*(-r11*r32+r31*r12) ;
+   Q.m[2][2] = deti*( r11*r22-r21*r12) ;
+
+   return Q ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! compute the determinant of a 3x3 matrix
+*//*--------------------------------------------------------------------*/
+float nifti_mat33_determ( mat33 R )   /* determinant of 3x3 matrix */
+{
+   double r11,r12,r13,r21,r22,r23,r31,r32,r33 ;
+                                                       /*  INPUT MATRIX:  */
+   r11 = R.m[0][0]; r12 = R.m[0][1]; r13 = R.m[0][2];  /* [ r11 r12 r13 ] */
+   r21 = R.m[1][0]; r22 = R.m[1][1]; r23 = R.m[1][2];  /* [ r21 r22 r23 ] */
+   r31 = R.m[2][0]; r32 = R.m[2][1]; r33 = R.m[2][2];  /* [ r31 r32 r33 ] */
+
+   return r11*r22*r33-r11*r32*r23-r21*r12*r33
+         +r21*r32*r13+r31*r12*r23-r31*r22*r13 ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! compute the max row norm of a 3x3 matrix
+*//*--------------------------------------------------------------------*/
+float nifti_mat33_rownorm( mat33 A )  /* max row norm of 3x3 matrix */
+{
+   float r1,r2,r3 ;
+
+   r1 = fabs(A.m[0][0])+fabs(A.m[0][1])+fabs(A.m[0][2]) ;
+   r2 = fabs(A.m[1][0])+fabs(A.m[1][1])+fabs(A.m[1][2]) ;
+   r3 = fabs(A.m[2][0])+fabs(A.m[2][1])+fabs(A.m[2][2]) ;
+   if( r1 < r2 ) r1 = r2 ;
+   if( r1 < r3 ) r1 = r3 ;
+   return r1 ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! compute the max column norm of a 3x3 matrix
+*//*--------------------------------------------------------------------*/
+float nifti_mat33_colnorm( mat33 A )  /* max column norm of 3x3 matrix */
+{
+   float r1,r2,r3 ;
+
+   r1 = fabs(A.m[0][0])+fabs(A.m[1][0])+fabs(A.m[2][0]) ;
+   r2 = fabs(A.m[0][1])+fabs(A.m[1][1])+fabs(A.m[2][1]) ;
+   r3 = fabs(A.m[0][2])+fabs(A.m[1][2])+fabs(A.m[2][2]) ;
+   if( r1 < r2 ) r1 = r2 ;
+   if( r1 < r3 ) r1 = r3 ;
+   return r1 ;
+}
+
+/*----------------------------------------------------------------------*/
+/*! multiply 2 3x3 matrices
+*//*--------------------------------------------------------------------*/
+mat33 nifti_mat33_mul( mat33 A , mat33 B )  /* multiply 2 3x3 matrices */
+{
+   mat33 C ; int i,j ;
+   for( i=0 ; i < 3 ; i++ )
+    for( j=0 ; j < 3 ; j++ )
+      C.m[i][j] =  A.m[i][0] * B.m[0][j]
+                 + A.m[i][1] * B.m[1][j]
+                 + A.m[i][2] * B.m[2][j] ;
+   return C ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! polar decomposition of a 3x3 matrix
+
+   This finds the closest orthogonal matrix to input A
+   (in both the Frobenius and L2 norms).
+
+   Algorithm is that from NJ Higham, SIAM J Sci Stat Comput, 7:1160-1174.
+*//*-------------------------------------------------------------------------*/
+mat33 nifti_mat33_polar( mat33 A )
+{
+   mat33 X , Y , Z ;
+   float alp,bet,gam,gmi , dif=1.0 ;
+   int k=0 ;
+
+   X = A ;
+
+   /* force matrix to be nonsingular */
+
+   gam = nifti_mat33_determ(X) ;
+   while( gam == 0.0 ){        /* perturb matrix */
+     gam = 0.00001 * ( 0.001 + nifti_mat33_rownorm(X) ) ;
+     X.m[0][0] += gam ; X.m[1][1] += gam ; X.m[2][2] += gam ;
+     gam = nifti_mat33_determ(X) ;
+   }
+
+   while(1){
+     Y = nifti_mat33_inverse(X) ;
+     if( dif > 0.3 ){     /* far from convergence */
+       alp = sqrt( nifti_mat33_rownorm(X) * nifti_mat33_colnorm(X) ) ;
+       bet = sqrt( nifti_mat33_rownorm(Y) * nifti_mat33_colnorm(Y) ) ;
+       gam = sqrt( bet / alp ) ;
+       gmi = 1.0 / gam ;
+     } else {
+       gam = gmi = 1.0 ;  /* close to convergence */
+     }
+     Z.m[0][0] = 0.5 * ( gam*X.m[0][0] + gmi*Y.m[0][0] ) ;
+     Z.m[0][1] = 0.5 * ( gam*X.m[0][1] + gmi*Y.m[1][0] ) ;
+     Z.m[0][2] = 0.5 * ( gam*X.m[0][2] + gmi*Y.m[2][0] ) ;
+     Z.m[1][0] = 0.5 * ( gam*X.m[1][0] + gmi*Y.m[0][1] ) ;
+     Z.m[1][1] = 0.5 * ( gam*X.m[1][1] + gmi*Y.m[1][1] ) ;
+     Z.m[1][2] = 0.5 * ( gam*X.m[1][2] + gmi*Y.m[2][1] ) ;
+     Z.m[2][0] = 0.5 * ( gam*X.m[2][0] + gmi*Y.m[0][2] ) ;
+     Z.m[2][1] = 0.5 * ( gam*X.m[2][1] + gmi*Y.m[1][2] ) ;
+     Z.m[2][2] = 0.5 * ( gam*X.m[2][2] + gmi*Y.m[2][2] ) ;
+
+     dif = fabs(Z.m[0][0]-X.m[0][0])+fabs(Z.m[0][1]-X.m[0][1])
+          +fabs(Z.m[0][2]-X.m[0][2])+fabs(Z.m[1][0]-X.m[1][0])
+          +fabs(Z.m[1][1]-X.m[1][1])+fabs(Z.m[1][2]-X.m[1][2])
+          +fabs(Z.m[2][0]-X.m[2][0])+fabs(Z.m[2][1]-X.m[2][1])
+          +fabs(Z.m[2][2]-X.m[2][2])                          ;
+
+     k = k+1 ;
+     if( k > 100 || dif < 3.e-6 ) break ;  /* convergence or exhaustion */
+     X = Z ;
+   }
+
+   return Z ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! compute the (closest) orientation from a 4x4 ijk->xyz tranformation matrix
+
+   <pre>
+   Input:  4x4 matrix that transforms (i,j,k) indexes to (x,y,z) coordinates,
+           where +x=Right, +y=Anterior, +z=Superior.
+           (Only the upper-left 3x3 corner of R is used herein.)
+   Output: 3 orientation codes that correspond to the closest "standard"
+           anatomical orientation of the (i,j,k) axes.
+   Method: Find which permutation of (x,y,z) has the smallest angle to the
+           (i,j,k) axes directions, which are the columns of the R matrix.
+   Errors: The codes returned will be zero.
+
+   For example, an axial volume might get return values of
+     *icod = NIFTI_R2L   (i axis is mostly Right to Left)
+     *jcod = NIFTI_P2A   (j axis is mostly Posterior to Anterior)
+     *kcod = NIFTI_I2S   (k axis is mostly Inferior to Superior)
+   </pre>
+
+   \see "QUATERNION REPRESENTATION OF ROTATION MATRIX" in nifti1.h
+
+   \see nifti_quatern_to_mat44, nifti_mat44_to_quatern,
+        nifti_make_orthog_mat44
+*//*-------------------------------------------------------------------------*/
+void nifti_mat44_to_orientation( mat44 R , int *icod, int *jcod, int *kcod )
+{
+   float xi,xj,xk , yi,yj,yk , zi,zj,zk , val,detQ,detP ;
+   mat33 P , Q , M ;
+   int i,j,k=0,p,q,r , ibest,jbest,kbest,pbest,qbest,rbest ;
+   float vbest ;
+
+   if( icod == NULL || jcod == NULL || kcod == NULL ) return ; /* bad */
+
+   *icod = *jcod = *kcod = 0 ; /* error returns, if sh*t happens */
+
+   /* load column vectors for each (i,j,k) direction from matrix */
+
+   /*-- i axis --*/ /*-- j axis --*/ /*-- k axis --*/
+
+   xi = R.m[0][0] ; xj = R.m[0][1] ; xk = R.m[0][2] ;
+   yi = R.m[1][0] ; yj = R.m[1][1] ; yk = R.m[1][2] ;
+   zi = R.m[2][0] ; zj = R.m[2][1] ; zk = R.m[2][2] ;
+
+   /* normalize column vectors to get unit vectors along each ijk-axis */
+
+   /* normalize i axis */
+
+   val = sqrt( xi*xi + yi*yi + zi*zi ) ;
+   if( val == 0.0 ) return ;                 /* stupid input */
+   xi /= val ; yi /= val ; zi /= val ;
+
+   /* normalize j axis */
+
+   val = sqrt( xj*xj + yj*yj + zj*zj ) ;
+   if( val == 0.0 ) return ;                 /* stupid input */
+   xj /= val ; yj /= val ; zj /= val ;
+
+   /* orthogonalize j axis to i axis, if needed */
+
+   val = xi*xj + yi*yj + zi*zj ;    /* dot product between i and j */
+   if( fabs(val) > 1.e-4 ){
+     xj -= val*xi ; yj -= val*yi ; zj -= val*zi ;
+     val = sqrt( xj*xj + yj*yj + zj*zj ) ;  /* must renormalize */
+     if( val == 0.0 ) return ;              /* j was parallel to i? */
+     xj /= val ; yj /= val ; zj /= val ;
+   }
+
+   /* normalize k axis; if it is zero, make it the cross product i x j */
+
+   val = sqrt( xk*xk + yk*yk + zk*zk ) ;
+   if( val == 0.0 ){ xk = yi*zj-zi*yj; yk = zi*xj-zj*xi ; zk=xi*yj-yi*xj ; }
+   else            { xk /= val ; yk /= val ; zk /= val ; }
+
+   /* orthogonalize k to i */
+
+   val = xi*xk + yi*yk + zi*zk ;    /* dot product between i and k */
+   if( fabs(val) > 1.e-4 ){
+     xk -= val*xi ; yk -= val*yi ; zk -= val*zi ;
+     val = sqrt( xk*xk + yk*yk + zk*zk ) ;
+     if( val == 0.0 ) return ;      /* bad */
+     xk /= val ; yk /= val ; zk /= val ;
+   }
+
+   /* orthogonalize k to j */
+
+   val = xj*xk + yj*yk + zj*zk ;    /* dot product between j and k */
+   if( fabs(val) > 1.e-4 ){
+     xk -= val*xj ; yk -= val*yj ; zk -= val*zj ;
+     val = sqrt( xk*xk + yk*yk + zk*zk ) ;
+     if( val == 0.0 ) return ;      /* bad */
+     xk /= val ; yk /= val ; zk /= val ;
+   }
+
+   Q.m[0][0] = xi ; Q.m[0][1] = xj ; Q.m[0][2] = xk ;
+   Q.m[1][0] = yi ; Q.m[1][1] = yj ; Q.m[1][2] = yk ;
+   Q.m[2][0] = zi ; Q.m[2][1] = zj ; Q.m[2][2] = zk ;
+
+   /* at this point, Q is the rotation matrix from the (i,j,k) to (x,y,z) axes */
+
+   detQ = nifti_mat33_determ( Q ) ;
+   if( detQ == 0.0 ) return ; /* shouldn't happen unless user is a DUFIS */
+
+   /* Build and test all possible +1/-1 coordinate permutation matrices P;
+      then find the P such that the rotation matrix M=PQ is closest to the
+      identity, in the sense of M having the smallest total rotation angle. */
+
+   /* Despite the formidable looking 6 nested loops, there are
+      only 3*3*3*2*2*2 = 216 passes, which will run very quickly. */
+
+   vbest = -666.0 ; ibest=pbest=qbest=rbest=1 ; jbest=2 ; kbest=3 ;
+   for( i=1 ; i <= 3 ; i++ ){     /* i = column number to use for row #1 */
+    for( j=1 ; j <= 3 ; j++ ){    /* j = column number to use for row #2 */
+     if( i == j ) continue ;
+      for( k=1 ; k <= 3 ; k++ ){  /* k = column number to use for row #3 */
+       if( i == k || j == k ) continue ;
+       P.m[0][0] = P.m[0][1] = P.m[0][2] =
+        P.m[1][0] = P.m[1][1] = P.m[1][2] =
+         P.m[2][0] = P.m[2][1] = P.m[2][2] = 0.0 ;
+       for( p=-1 ; p <= 1 ; p+=2 ){    /* p,q,r are -1 or +1      */
+        for( q=-1 ; q <= 1 ; q+=2 ){   /* and go into rows #1,2,3 */
+         for( r=-1 ; r <= 1 ; r+=2 ){
+           P.m[0][i-1] = p ; P.m[1][j-1] = q ; P.m[2][k-1] = r ;
+           detP = nifti_mat33_determ(P) ;           /* sign of permutation */
+           if( detP * detQ <= 0.0 ) continue ;  /* doesn't match sign of Q */
+           M = nifti_mat33_mul(P,Q) ;
+
+           /* angle of M rotation = 2.0*acos(0.5*sqrt(1.0+trace(M)))       */
+           /* we want largest trace(M) == smallest angle == M nearest to I */
+
+           val = M.m[0][0] + M.m[1][1] + M.m[2][2] ; /* trace */
+           if( val > vbest ){
+             vbest = val ;
+             ibest = i ; jbest = j ; kbest = k ;
+             pbest = p ; qbest = q ; rbest = r ;
+           }
+   }}}}}}
+
+   /* At this point ibest is 1 or 2 or 3; pbest is -1 or +1; etc.
+
+      The matrix P that corresponds is the best permutation approximation
+      to Q-inverse; that is, P (approximately) takes (x,y,z) coordinates
+      to the (i,j,k) axes.
+
+      For example, the first row of P (which contains pbest in column ibest)
+      determines the way the i axis points relative to the anatomical
+      (x,y,z) axes.  If ibest is 2, then the i axis is along the y axis,
+      which is direction P2A (if pbest > 0) or A2P (if pbest < 0).
+
+      So, using ibest and pbest, we can assign the output code for
+      the i axis.  Mutatis mutandis for the j and k axes, of course. */
+
+   switch( ibest*pbest ){
+     case  1: i = NIFTI_L2R ; break ;
+     case -1: i = NIFTI_R2L ; break ;
+     case  2: i = NIFTI_P2A ; break ;
+     case -2: i = NIFTI_A2P ; break ;
+     case  3: i = NIFTI_I2S ; break ;
+     case -3: i = NIFTI_S2I ; break ;
+   }
+
+   switch( jbest*qbest ){
+     case  1: j = NIFTI_L2R ; break ;
+     case -1: j = NIFTI_R2L ; break ;
+     case  2: j = NIFTI_P2A ; break ;
+     case -2: j = NIFTI_A2P ; break ;
+     case  3: j = NIFTI_I2S ; break ;
+     case -3: j = NIFTI_S2I ; break ;
+   }
+
+   switch( kbest*rbest ){
+     case  1: k = NIFTI_L2R ; break ;
+     case -1: k = NIFTI_R2L ; break ;
+     case  2: k = NIFTI_P2A ; break ;
+     case -2: k = NIFTI_A2P ; break ;
+     case  3: k = NIFTI_I2S ; break ;
+     case -3: k = NIFTI_S2I ; break ;
+   }
+
+   *icod = i ; *jcod = j ; *kcod = k ; return ;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Routines to swap byte arrays in various ways:
+    -  2 at a time:  ab               -> ba               [short]
+    -  4 at a time:  abcd             -> dcba             [int, float]
+    -  8 at a time:  abcdDCBA         -> ABCDdcba         [long long, double]
+    - 16 at a time:  abcdefghHGFEDCBA -> ABCDEFGHhgfedcba [long double]
+-----------------------------------------------------------------------------*/
+
+typedef struct { unsigned char a,b ; } twobytes ;
+
+/*----------------------------------------------------------------------*/
+/*! swap each byte pair from the given list of n pairs
+*//*--------------------------------------------------------------------*/
+void nifti_swap_2bytes( int n , void *ar )    /* 2 bytes at a time */
+{
+   register int ii ;
+   register twobytes *tb = (twobytes *)ar ;
+   register unsigned char tt ;
+
+   for( ii=0 ; ii < n ; ii++ ){
+     tt = tb[ii].a ; tb[ii].a = tb[ii].b ; tb[ii].b = tt ;
+   }
+   return ;
+}
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct { unsigned char a,b,c,d ; } fourbytes ;
+
+/*----------------------------------------------------------------------*/
+/*! swap 4 bytes at a time from the given list of n sets of 4 bytes
+*//*--------------------------------------------------------------------*/
+void nifti_swap_4bytes( int n , void *ar )    /* 4 bytes at a time */
+{
+   register int ii ;
+   register fourbytes *tb = (fourbytes *)ar ;
+   register unsigned char tt ;
+
+   for( ii=0 ; ii < n ; ii++ ){
+     tt = tb[ii].a ; tb[ii].a = tb[ii].d ; tb[ii].d = tt ;
+     tt = tb[ii].b ; tb[ii].b = tb[ii].c ; tb[ii].c = tt ;
+   }
+   return ;
+}
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct { unsigned char a,b,c,d , D,C,B,A ; } eightbytes ;
+
+/*----------------------------------------------------------------------*/
+/*! swap 8 bytes at a time from the given list of n sets of 8 bytes
+*//*--------------------------------------------------------------------*/
+void nifti_swap_8bytes( int n , void *ar )    /* 8 bytes at a time */
+{
+   register int ii ;
+   register eightbytes *tb = (eightbytes *)ar ;
+   register unsigned char tt ;
+
+   for( ii=0 ; ii < n ; ii++ ){
+     tt = tb[ii].a ; tb[ii].a = tb[ii].A ; tb[ii].A = tt ;
+     tt = tb[ii].b ; tb[ii].b = tb[ii].B ; tb[ii].B = tt ;
+     tt = tb[ii].c ; tb[ii].c = tb[ii].C ; tb[ii].C = tt ;
+     tt = tb[ii].d ; tb[ii].d = tb[ii].D ; tb[ii].D = tt ;
+   }
+   return ;
+}
+
+/*---------------------------------------------------------------------------*/
+
+typedef struct { unsigned char a,b,c,d,e,f,g,h ,
+                               H,G,F,E,D,C,B,A  ; } sixteenbytes ;
+
+/*----------------------------------------------------------------------*/
+/*! swap 16 bytes at a time from the given list of n sets of 16 bytes
+*//*--------------------------------------------------------------------*/
+void nifti_swap_16bytes( int n , void *ar )    /* 16 bytes at a time */
+{
+   register int ii ;
+   register sixteenbytes *tb = (sixteenbytes *)ar ;
+   register unsigned char tt ;
+
+   for( ii=0 ; ii < n ; ii++ ){
+     tt = tb[ii].a ; tb[ii].a = tb[ii].A ; tb[ii].A = tt ;
+     tt = tb[ii].b ; tb[ii].b = tb[ii].B ; tb[ii].B = tt ;
+     tt = tb[ii].c ; tb[ii].c = tb[ii].C ; tb[ii].C = tt ;
+     tt = tb[ii].d ; tb[ii].d = tb[ii].D ; tb[ii].D = tt ;
+
+     tt = tb[ii].e ; tb[ii].e = tb[ii].E ; tb[ii].E = tt ;
+     tt = tb[ii].f ; tb[ii].f = tb[ii].F ; tb[ii].F = tt ;
+     tt = tb[ii].g ; tb[ii].g = tb[ii].G ; tb[ii].G = tt ;
+     tt = tb[ii].h ; tb[ii].h = tb[ii].H ; tb[ii].H = tt ;
+   }
+   return ;
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/*! based on siz, call the appropriate nifti_swap_Nbytes() function
+*//*--------------------------------------------------------------------*/
+void nifti_swap_Nbytes( int n , int siz , void *ar )  /* subsuming case */
+{
+   switch( siz ){
+     case 2:  nifti_swap_2bytes ( n , ar ) ; break ;
+     case 4:  nifti_swap_4bytes ( n , ar ) ; break ;
+     case 8:  nifti_swap_8bytes ( n , ar ) ; break ;
+     case 16: nifti_swap_16bytes( n , ar ) ; break ;
+   }
+   return ;
+}
+
+
+/*-------------------------------------------------------------------------*/
+/*! Byte swap NIFTI-1 file header in various places and ways.
+
+    If is_nifti is nonzero, will also swap the NIFTI-specific
+    components of the header; otherwise, only the components
+    common to NIFTI and ANALYZE will be swapped.
+*//*---------------------------------------------------------------------- */
+void swap_nifti_header( struct nifti_1_header *h , int is_nifti )
+{
+
+#if 0                /* ANALYZE fields not used by this software */
+   swap_4(h->sizeof_hdr) ;
+   swap_4(h->extents) ;
+   swap_2(h->session_error) ;
+   swap_4(h->compressed) ;
+   swap_4(h->glmax) ; swap_4(h->glmin) ;
+#endif
+
+   /* this stuff is always present, for ANALYZE and NIFTI */
+
+   swap_4(h->sizeof_hdr) ;
+   nifti_swap_2bytes( 8 , h->dim ) ;
+   nifti_swap_4bytes( 8 , h->pixdim ) ;
+
+   swap_2(h->datatype) ;
+   swap_2(h->bitpix) ;
+
+   swap_4(h->vox_offset); swap_4(h->cal_max); swap_4(h->cal_min);
+
+   /* this stuff is NIFTI specific */
+
+   if( is_nifti ){
+     swap_4(h->intent_p1); swap_4(h->intent_p2); swap_4(h->intent_p3);
+     swap_2(h->intent_code);
+
+     swap_2(h->slice_start);    swap_2(h->slice_end);
+     swap_4(h->scl_slope);      swap_4(h->scl_inter);
+     swap_4(h->slice_duration); swap_4(h->toffset);
+
+     swap_2(h->qform_code); swap_2(h->sform_code);
+     swap_4(h->quatern_b); swap_4(h->quatern_c); swap_4(h->quatern_d);
+     swap_4(h->qoffset_x); swap_4(h->qoffset_y); swap_4(h->qoffset_z);
+     nifti_swap_4bytes(4,h->srow_x);
+     nifti_swap_4bytes(4,h->srow_y);
+     nifti_swap_4bytes(4,h->srow_z);
+   }
+   return ;
+}
+
+
+#define USE_STAT
+#ifdef  USE_STAT
+/*---------------------------------------------------------------------------*/
+/* Return the file length (0 if file not found or has no contents).
+   This is a Unix-specific function, since it uses stat().
+-----------------------------------------------------------------------------*/
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/*---------------------------------------------------------------------------*/
+/*! return the size of a file, in bytes
+
+    \return size of file on success, -1 on error or no file
+
+    changed to return int, -1 means no file or error      20 Dec 2004 [rickr]
+*//*-------------------------------------------------------------------------*/
+int nifti_get_filesize( const char *pathname )
+{
+   struct stat buf ; int ii ;
+
+   if( pathname == NULL || *pathname == '\0' ) return -1 ;
+   ii = stat( pathname , &buf ); if( ii != 0 ) return -1 ;
+   return (unsigned int)buf.st_size ;
+}
+
+#else  /*---------- non-Unix version of the above, less efficient -----------*/
+
+int nifti_get_filesize( const char *pathname )
+{
+   znzFile fp ; int len ;
+
+   if( pathname == NULL || *pathname == '\0' ) return -1 ;
+   fp = znzopen(pathname,"rb",0); if( znz_isnull(fp) ) return -1 ;
+   znzseek(fp,0L,SEEK_END) ; len = znztell(fp) ;
+   znzclose(fp) ; return len ;
+}
+
+#endif /* USE_STAT */
+
+
+/*----------------------------------------------------------------------*/
+/*! return the total volume size, in bytes
+
+    This is computed as nvox * nbyper.
+*//*--------------------------------------------------------------------*/
+size_t nifti_get_volsize(const nifti_image *nim)
+{
+   return (size_t)(nim->nbyper) * (size_t)(nim->nvox) ; /* total bytes */
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* Support functions for filenames in read and write
+   - allows for gzipped files
+*/
+
+
+/*----------------------------------------------------------------------*/
+/*! simple check for file existence
+
+    \return 1 on existence, 0 otherwise
+*//*--------------------------------------------------------------------*/
+int nifti_fileexists(const char* fname)
+{
+   znzFile fp;
+   fp = znzopen( fname , "rb" , 1 ) ;
+   if( !znz_isnull(fp) )  { znzclose(fp);  return 1; }
+   return 0; /* fp is NULL */
+}
+
+/*----------------------------------------------------------------------*/
+/*! return whether the filename is valid
+
+    The name is considered valid if the file basename has length greater than
+    zero, AND one of the valid nifti extensions is provided.
+    fname input          | return |
+    ===============================
+    "myimage"            |  0     |
+    "myimage.tif"        |  0     |
+    "myimage.tif.gz"     |  0     |
+    "myimage.nii"        |  1     |
+    ".nii"               |  0     |
+    ".myhiddenimage"     |  0     |
+    ".myhiddenimage.nii" |  1     |
+*//*--------------------------------------------------------------------*/
+int nifti_is_complete_filename(const char* fname)
+{
+   char * ext;
+
+   /* check input file(s) for sanity */
+   if( fname == NULL || *fname == '\0' ){
+      if ( g_opts.debug > 1 )
+         fprintf(stderr,"-- empty filename in nifti_validfilename()\n");
+      return 0;
+   }
+
+   ext = nifti_find_file_extension(fname);
+   if ( ext == NULL ) { /*Invalid extension given */
+      if ( g_opts.debug > 0 )
+         fprintf(stderr,"-- no nifti valid extension for filename '%s'\n", fname);
+       return 0;
+   }
+
+   if ( ext && ext == fname ) {   /* then no filename prefix */
+      if ( g_opts.debug > 0 )
+         fprintf(stderr,"-- no prefix for filename '%s'\n", fname);
+      return 0;
+   }
+   return 1;
+}
+
+/*----------------------------------------------------------------------*/
+/*! return whether the filename is valid
+
+    The name is considered valid if its length is positive, excluding
+    any nifti filename extension.
+    fname input         |  return | result of nifti_makebasename
+    ====================================================================
+    "myimage"           |  1      | "myimage"
+    "myimage.tif"       |  1      | "myimage.tif"
+    "myimage.tif.gz"    |  1      | "myimage.tif"
+    "myimage.nii"       |  1      | "myimage"
+    ".nii"              |  0      | <ERROR - basename has zero length>
+    ".myhiddenimage"    |  1      | ".myhiddenimage"
+    ".myhiddenimage.nii |  1      | ".myhiddenimage"
+*//*--------------------------------------------------------------------*/
+int nifti_validfilename(const char* fname)
+{
+   char * ext;
+
+   /* check input file(s) for sanity */
+   if( fname == NULL || *fname == '\0' ){
+      if ( g_opts.debug > 1 )
+         fprintf(stderr,"-- empty filename in nifti_validfilename()\n");
+      return 0;
+   }
+
+   ext = nifti_find_file_extension(fname);
+
+   if ( ext && ext == fname ) {   /* then no filename prefix */
+      if ( g_opts.debug > 0 )
+         fprintf(stderr,"-- no prefix for filename '%s'\n", fname);
+      return 0;
+   }
+
+   return 1;
+}
+
+/*----------------------------------------------------------------------*/
+/*! check the end of the filename for a valid nifti extension
+
+    Valid extensions are currently .nii, .hdr, .img, .nia,
+    or any of them followed by .gz.  Note that '.' is part of
+    the extension.
+
+    \return a pointer to the extension (within the filename), or NULL
+*//*--------------------------------------------------------------------*/
+char * nifti_find_file_extension( const char * name )
+{
+   char * ext;
+   int    len;
+
+   if ( ! name ) return NULL;
+
+   len = strlen(name);
+   if ( len < 4 ) return NULL;
+
+   ext = (char *)name + len - 4;
+
+   if ( (strcmp(ext, ".hdr") == 0) || (strcmp(ext, ".img") == 0) ||
+        (strcmp(ext, ".nia") == 0) || (strcmp(ext, ".nii") == 0) )
+      return ext;
+
+   //#ifdef HAVE_ZLIB
+   if ( len < 7 ) return NULL;
+
+   ext = (char *)name + len - 7;
+
+   if ( (strcmp(ext, ".hdr.gz") == 0) || (strcmp(ext, ".img.gz") == 0) ||
+        (strcmp(ext, ".nia.gz") == 0) || (strcmp(ext, ".nii.gz") == 0) )
+      return ext;
+   //#endif
+
+   if( g_opts.debug > 1 )
+      fprintf(stderr,"** find_file_ext: failed for name '%s'\n", name);
+
+   return NULL;
+}
+
+/*----------------------------------------------------------------------*/
+/*! return whether the filename ends in ".gz"
+*//*--------------------------------------------------------------------*/
+int nifti_is_gzfile(const char* fname)
+{
+  /* return true if the filename ends with .gz */
+  if (fname == NULL) { return 0; }
+#ifdef HAVE_ZLIB
+  { /* just so len doesn't generate compile warning */
+     int len;
+     len = strlen(fname);
+     if (len < 3) return 0;  /* so we don't search before the name */
+     if (strcmp(fname + strlen(fname) - 3,".gz")==0) { return 1; }
+  }
+#endif
+  return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! duplicate the filename, while clearing any extension
+
+    This allocates memory for basename which should eventually be freed.
+*//*--------------------------------------------------------------------*/
+char * nifti_makebasename(const char* fname)
+{
+   char *basename, *ext;
+
+   basename=nifti_strdup(fname);
+
+   ext = nifti_find_file_extension(basename);
+   if ( ext ) *ext = '\0';  /* clear out extension */
+   
+   return basename;  /* in either case */
+}
+
+/*----------------------------------------------------------------------*/
+/*! set nifti's global debug level, for status reporting
+
+    - 0    : quiet, nothing is printed to the terminal, but errors
+    - 1    : normal execution (the default)
+    - 2, 3 : more details
+*//*--------------------------------------------------------------------*/
+void nifti_set_debug_level( int level )
+{
+    g_opts.debug = level;
+}
+
+/*----------------------------------------------------------------------*/
+/*! set nifti's global skip_blank_ext flag            5 Sep 2006 [rickr]
+
+    explicitly set to 0 or 1
+*//*--------------------------------------------------------------------*/
+void nifti_set_skip_blank_ext( int skip )
+{
+    g_opts.skip_blank_ext = skip ? 1 : 0;
+}
+
+/*----------------------------------------------------------------------*/
+/*! check current directory for existing header file
+
+    \return filename of header on success and NULL if no appropriate file
+            could be found 
+
+    NB: it allocates memory for hdrname which should be freed
+        when no longer required
+*//*-------------------------------------------------------------------*/
+char * nifti_findhdrname(const char* fname)
+{
+   char *basename, *hdrname, *ext;
+   char  elist[2][5] = { ".hdr", ".nii" };
+   int   efirst;
+
+   /**- check input file(s) for sanity */
+   if( !nifti_validfilename(fname) ) return NULL;
+
+   basename = nifti_makebasename(fname);
+   if( !basename ) return NULL;   /* only on string alloc failure */
+
+   /**- return filename if it has a valid extension and exists
+         (except if it is an .img file (and maybe .gz)) */
+   ext = nifti_find_file_extension(fname);
+   if ( ext && nifti_fileexists(fname) ) { 
+     if ( strncmp(ext,".img",4) != 0 ){
+        hdrname = nifti_strdup(fname); 
+        free(basename);
+        return hdrname; 
+     }
+   }
+
+   /* So the requested name is a basename, contains .img, or does not exist. */
+   /* In any case, use basename. */
+
+   /**- if .img, look for .hdr, .hdr.gz, .nii, .nii.gz, in that order */
+   /**- else,    look for .nii, .nii.gz, .hdr, .hdr.gz, in that order */
+
+   /* if we get more extension choices, this could be a loop */
+
+   if ( ext && strncmp(ext,".img",4) == 0 ) efirst = 0;
+   else                                     efirst = 1;
+
+   hdrname = (char *)calloc(sizeof(char),strlen(basename)+8);
+   if( !hdrname ){
+      fprintf(stderr,"** nifti_findhdrname: failed to alloc hdrname\n");
+      free(basename);
+      return NULL;
+   }
+
+   strcpy(hdrname,basename);
+   strcat(hdrname,elist[efirst]);
+   if (nifti_fileexists(hdrname)) { free(basename); return hdrname; }
+#ifdef HAVE_ZLIB
+   strcat(hdrname,".gz"); 
+   if (nifti_fileexists(hdrname)) { free(basename); return hdrname; }
+#endif
+
+   /* okay, try the other possibility */
+
+   efirst = 1 - efirst;
+
+   strcpy(hdrname,basename);
+   strcat(hdrname,elist[efirst]);
+   if (nifti_fileexists(hdrname)) { free(basename); return hdrname; }
+#ifdef HAVE_ZLIB
+   strcat(hdrname,".gz"); 
+   if (nifti_fileexists(hdrname)) { free(basename); return hdrname; }
+#endif
+
+   /**- if nothing has been found, return NULL */
+   free(basename); 
+   free(hdrname); 
+   return NULL;
+}
+
+
+/*------------------------------------------------------------------------*/
+/*! check current directory for existing image file
+
+    \param fname filename to check for
+    \nifti_type  nifti_type for dataset - this determines whether to
+                 first check for ".nii" or ".img" (since both may exist)
+
+    \return filename of data/img file on success and NULL if no appropriate
+            file could be found
+
+    NB: it allocates memory for the image filename, which should be freed
+        when no longer required
+*//*---------------------------------------------------------------------*/
+char * nifti_findimgname(const char* fname , int nifti_type)
+{
+   char *basename, *imgname, ext[2][5] = { ".nii", ".img" };
+   int  first;  /* first extension to use */
+
+   /* check input file(s) for sanity */
+
+   if( !nifti_validfilename(fname) ) return NULL;
+
+   basename =  nifti_makebasename(fname);
+   imgname = (char *)calloc(sizeof(char),strlen(basename)+8);
+   if( !imgname ){
+      fprintf(stderr,"** nifti_findimgname: failed to alloc imgname\n");
+      free(basename);
+      return NULL;
+   }
+
+   /**- test for .nii and .img (don't assume input type from image type) */
+   /**- if nifti_type = 1, check for .nii first, else .img first         */
+
+   /* if we get 3 or more extensions, can make a loop here... */
+
+   if (nifti_type == NIFTI_FTYPE_NIFTI1_1) first = 0;   /* should match .nii */
+   else                                    first = 1;   /* should match .img */
+
+   strcpy(imgname,basename);
+   strcat(imgname,ext[first]);
+   if (nifti_fileexists(imgname)) { free(basename); return imgname; }
+#ifdef HAVE_ZLIB  /* then also check for .gz */
+   strcat(imgname,".gz");
+   if (nifti_fileexists(imgname)) { free(basename); return imgname; }
+#endif
+
+   /* failed to find image file with expected extension, try the other */
+
+   strcpy(imgname,basename);
+   strcat(imgname,ext[1-first]);  /* can do this with only 2 choices */
+   if (nifti_fileexists(imgname)) { free(basename); return imgname; }
+#ifdef HAVE_ZLIB  /* then also check for .gz */
+   strcat(imgname,".gz");
+   if (nifti_fileexists(imgname)) { free(basename); return imgname; }
+#endif
+
+   /**- if nothing has been found, return NULL */
+   free(basename); 
+   free(imgname); 
+   return NULL;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! creates a filename for storing the header, based on nifti_type
+
+   \param   prefix      - this will be copied before the suffix is added
+   \param   nifti_type  - determines the extension, unless one is in prefix
+   \param   check       - check for existence (fail condition)
+   \param   comp        - add .gz for compressed name
+
+   Note that if prefix provides a file suffix, nifti_type is not used.
+  
+   NB: this allocates memory which should be freed
+
+   \sa nifti_set_filenames
+*//*-------------------------------------------------------------------*/
+char * nifti_makehdrname(const char * prefix, int nifti_type, int check,
+                         int comp)
+{
+   char * iname, * ext;
+
+   if( !nifti_validfilename(prefix) ) return NULL;
+
+   /* add space for extension, optional ".gz", and null char */
+   iname = (char *)calloc(sizeof(char),strlen(prefix)+8);
+   if( !iname ){ fprintf(stderr,"** small malloc failure!\n"); return NULL; }
+   strcpy(iname, prefix);
+
+   /* use any valid extension */
+   if( (ext = nifti_find_file_extension(iname)) != NULL ){
+      if( strncmp(ext,".img",4) == 0 )
+         memcpy(ext,".hdr",4);   /* then convert img name to hdr */
+   }
+   /* otherwise, make one up an */
+   else if( nifti_type == NIFTI_FTYPE_NIFTI1_1 ) strcat(iname, ".nii");
+   else if( nifti_type == NIFTI_FTYPE_ASCII )    strcat(iname, ".nia");
+   else                                          strcat(iname, ".hdr");
+
+#ifdef HAVE_ZLIB  /* then also check for .gz */
+   if( comp && (!ext || !strstr(iname,".gz")) ) strcat(iname,".gz");
+#endif
+
+   /* check for existence failure */
+   if( check && nifti_fileexists(iname) ){
+      fprintf(stderr,"** failure: header file '%s' already exists\n",iname);
+      free(iname);
+      return NULL;
+   }
+
+   if(g_opts.debug > 2) fprintf(stderr,"+d made header filename '%s'\n", iname);
+
+   return iname;
+}
+   
+
+/*----------------------------------------------------------------------*/
+/*! creates a filename for storing the image, based on nifti_type
+
+   \param   prefix      - this will be copied before the suffix is added
+   \param   nifti_type  - determines the extension, unless provided by prefix
+   \param   check       - check for existence (fail condition)
+   \param   comp        - add .gz for compressed name
+  
+   Note that if prefix provides a file suffix, nifti_type is not used.
+  
+   NB: it allocates memory which should be freed
+
+   \sa nifti_set_filenames
+*//*-------------------------------------------------------------------*/
+char * nifti_makeimgname(const char * prefix, int nifti_type, int check,
+                         int comp)
+{
+   char * iname, * ext;
+
+   if( !nifti_validfilename(prefix) ) return NULL;
+
+   /* add space for extension, optional ".gz", and null char */
+   iname = (char *)calloc(sizeof(char),strlen(prefix)+8);
+   if( !iname ){ fprintf(stderr,"** small malloc failure!\n"); return NULL; }
+   strcpy(iname, prefix);
+
+   /* use any valid extension */
+   if( (ext = nifti_find_file_extension(iname)) != NULL ){
+      if( strncmp(ext,".hdr",4) == 0 )
+         memcpy(ext,".img",4);   /* then convert hdr name to img */
+   }
+   /* otherwise, make one up */
+   else if( nifti_type == NIFTI_FTYPE_NIFTI1_1 ) strcat(iname, ".nii");
+   else if( nifti_type == NIFTI_FTYPE_ASCII )    strcat(iname, ".nia");
+   else                                          strcat(iname, ".img");
+
+#ifdef HAVE_ZLIB  /* then also check for .gz */
+   if( comp && (!ext || !strstr(iname,".gz")) ) strcat(iname,".gz");
+#endif
+
+   /* check for existence failure */
+   if( check && nifti_fileexists(iname) ){
+      fprintf(stderr,"** failure: image file '%s' already exists\n",iname);
+      free(iname);
+      return NULL;
+   }
+
+   if( g_opts.debug > 2 ) fprintf(stderr,"+d made image filename '%s'\n",iname);
+
+   return iname;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! create and set new filenames, based on prefix and image type
+
+   \param nim            pointer to nifti_image in which to set filenames
+   \param prefix         (required) prefix for output filenames
+   \param check          check for previous existence of filename
+                         (existence is an error condition)
+   \param set_byte_order flag to set nim->byteorder here
+                         (this is probably a logical place to do so)
+
+   \return 0 on successful update
+ 
+   \warning this will free() any existing names and create new ones
+
+   \sa nifti_makeimgname, nifti_makehdrname, nifti_type_and_names_match
+*//*--------------------------------------------------------------------*/
+int nifti_set_filenames( nifti_image * nim, const char * prefix, int check,
+                         int set_byte_order )
+{
+   int comp = nifti_is_gzfile(prefix);
+
+   if( !nim || !prefix ){
+      fprintf(stderr,"** nifti_set_filenames, bad params %p, %p\n",
+              (void *)nim,prefix);
+      return -1;
+   }
+
+   if( g_opts.debug > 1 )
+      fprintf(stderr,"+d modifying output filenames using prefix %s\n", prefix);
+
+   if( nim->fname ) free(nim->fname);
+   if( nim->iname ) free(nim->iname);
+   nim->fname = nifti_makehdrname(prefix, nim->nifti_type, check, comp);
+   nim->iname = nifti_makeimgname(prefix, nim->nifti_type, check, comp);
+   if( !nim->fname || !nim->iname ){
+      LNI_FERR("nifti_set_filename","failed to set prefix for",prefix);
+      return -1;
+   }
+
+   if( set_byte_order ) nim->byteorder = nifti_short_order() ;
+
+   if( nifti_set_type_from_names(nim) < 0 )
+      return -1;
+
+   if( g_opts.debug > 2 )
+      fprintf(stderr,"+d have new filenames %s and %s\n",nim->fname,nim->iname);
+
+   return 0;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! check whether nifti_type matches fname and iname for the nifti_image
+
+    - if type 0 or 2, expect .hdr/.img pair
+    - if type 1, expect .nii (and names must match)
+
+    \param nim       given nifti_image
+    \param show_warn if set, print a warning message for any mis-match
+
+    \return
+        -   1 if the values seem to match
+        -   0 if there is a mis-match
+        -  -1 if there is not sufficient information to create file(s)
+
+    \sa NIFTI_FTYPE_* codes in nifti1_io.h
+    \sa nifti_set_type_from_names, is_valid_nifti_type
+*//*------------------------------------------------------------------------*/
+int nifti_type_and_names_match( nifti_image * nim, int show_warn )
+{
+   char func[] = "nifti_type_and_names_match";
+   char * ext_h, * ext_i;  /* header and image filename extensions */
+   int  errs = 0;          /* error counter */
+
+   /* sanity checks */
+   if( !nim ){
+      if( show_warn ) fprintf(stderr,"** %s: missing nifti_image\n", func);
+      return -1;
+   }
+   if( !nim->fname ){
+      if( show_warn ) fprintf(stderr,"** %s: missing header filename\n", func);
+      errs++;
+   }
+   if( !nim->iname ){
+      if( show_warn ) fprintf(stderr,"** %s: missing image filename\n", func);
+      errs++;
+   }
+   if( !is_valid_nifti_type(nim->nifti_type) ){
+      if( show_warn )
+         fprintf(stderr,"** %s: bad nifti_type %d\n", func, nim->nifti_type);
+      errs++;
+   }
+
+   if( errs ) return -1;   /* then do not proceed */
+
+   /* get pointers to extensions */
+   ext_h = nifti_find_file_extension( nim->fname );
+   ext_i = nifti_find_file_extension( nim->iname );
+
+   /* check for filename extensions */
+   if( !ext_h ){
+      if( show_warn )
+         fprintf(stderr,"-d missing NIFTI extension in header filename, %s\n",
+                 nim->fname);
+      errs++;
+   }
+   if( !ext_i ){
+      if( show_warn )
+         fprintf(stderr,"-d missing NIFTI extension in image filename, %s\n",
+                 nim->iname);
+      errs++;
+   }
+
+   if( errs ) return 0;   /* do not proceed, but this is just a mis-match */
+
+   /* general tests */
+   if( nim->nifti_type == NIFTI_FTYPE_NIFTI1_1 ){  /* .nii */
+      if( strncmp(ext_h,".nii",4) ) {
+         if( show_warn )
+            fprintf(stderr,
+            "-d NIFTI_FTYPE 1, but no .nii extension in header filename, %s\n",
+            nim->fname);
+         errs++;
+      }
+      if( strncmp(ext_i,".nii",4) ) {
+         if( show_warn )
+            fprintf(stderr,
+            "-d NIFTI_FTYPE 1, but no .nii extension in image filename, %s\n",
+            nim->iname);
+         errs++;
+      }
+      if( strcmp(nim->fname, nim->iname) != 0 ){
+         if( show_warn )
+            fprintf(stderr,
+            "-d NIFTI_FTYPE 1, but header and image filenames differ: %s, %s\n",
+            nim->fname, nim->iname);
+         errs++;
+      }
+   }
+   else if( (nim->nifti_type == NIFTI_FTYPE_NIFTI1_2) || /* .hdr/.img */
+            (nim->nifti_type == NIFTI_FTYPE_ANALYZE) )
+   {
+      if( strncmp(ext_h,".hdr",4) != 0 ){
+         if( show_warn )
+            fprintf(stderr,"-d no '.hdr' extension, but NIFTI type is %d, %s\n",
+                    nim->nifti_type, nim->fname);
+         errs++;
+      }
+      if( strncmp(ext_i,".img",4) != 0 ){
+         if( show_warn )
+            fprintf(stderr,"-d no '.img' extension, but NIFTI type is %d, %s\n",
+                    nim->nifti_type, nim->iname);
+         errs++;
+      }
+   }
+   /* ignore any other nifti_type */
+
+   return 1;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! check whether the given type is on the "approved" list
+
+    The code is valid if it is non-negative, and does not exceed
+    NIFTI_MAX_FTYPE.
+
+    \return 1 if nifti_type is valid, 0 otherwise
+    \sa NIFTI_FTYPE_* codes in nifti1_io.h
+*//*------------------------------------------------------------------------*/
+int is_valid_nifti_type( int nifti_type )
+{
+   if( nifti_type >= NIFTI_FTYPE_ANALYZE &&   /* smallest type, 0 */
+       nifti_type <= NIFTI_MAX_FTYPE )
+      return 1;
+   return 0;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! set the nifti_type field based on fname and iname
+
+    Note that nifti_type is changed only when it does not match
+    the filenames.
+
+    \return 0 on success, -1 on error
+
+    \sa is_valid_nifti_type, nifti_type_and_names_match
+*//*------------------------------------------------------------------------*/
+int nifti_set_type_from_names( nifti_image * nim )
+{
+   /* error checking first */
+   if( !nim ){ fprintf(stderr,"** NSTFN: no nifti_image\n");  return -1; }
+
+   if( !nim->fname || !nim->iname ){
+      fprintf(stderr,"** NSTFN: missing filename(s) fname @ %p, iname @ %p\n",
+              nim->fname, nim->iname);
+      return -1;
+   }
+
+   if( ! nifti_validfilename      ( nim->fname ) ||
+       ! nifti_validfilename      ( nim->iname ) ||
+       ! nifti_find_file_extension( nim->fname ) ||
+       ! nifti_find_file_extension( nim->iname )
+     ) {
+      fprintf(stderr,"** NSTFN: invalid filename(s) fname='%s', iname='%s'\n",
+              nim->fname, nim->iname);
+      return -1;
+   }
+
+   if( g_opts.debug > 2 )
+      fprintf(stderr,"-d verify nifti_type from filenames: %d",nim->nifti_type);
+
+   /* not too picky here, do what must be done, and then verify */
+   if( strcmp(nim->fname, nim->iname) == 0 )          /* one file, type 1 */
+      nim->nifti_type = NIFTI_FTYPE_NIFTI1_1;
+   else if( nim->nifti_type == NIFTI_FTYPE_NIFTI1_1 ) /* cannot be type 1 */
+      nim->nifti_type = NIFTI_FTYPE_NIFTI1_2;
+
+   if( g_opts.debug > 2 ) fprintf(stderr," -> %d\n",nim->nifti_type);
+
+   if( g_opts.debug > 1 )  /* warn user about anything strange */
+      nifti_type_and_names_match(nim, 1);
+
+   if( is_valid_nifti_type(nim->nifti_type) ) return 0;  /* success! */
+
+   fprintf(stderr,"** NSTFN: bad nifti_type %d, for '%s' and '%s'\n",
+           nim->nifti_type, nim->fname, nim->iname);
+
+   return -1;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! Determine if this is a NIFTI-formatted file.
+
+   <pre>
+   \return  0 if file looks like ANALYZE 7.5 [checks sizeof_hdr field == 348]
+            1 if file marked as NIFTI (header+data in 1 file)
+            2 if file marked as NIFTI (header+data in 2 files)
+           -1 if it can't tell, file doesn't exist, etc.
+   </pre>
+*//*------------------------------------------------------------------------*/
+int is_nifti_file( const char *hname )
+{
+   struct nifti_1_header nhdr ;
+   znzFile fp ;
+   int ii ;
+   char *tmpname;
+
+   /* bad input name? */
+
+   if( !nifti_validfilename(hname) ) return -1 ;
+
+   /* open file */
+
+   tmpname = nifti_findhdrname(hname);
+   if( tmpname == NULL ){
+      if( g_opts.debug > 0 )
+         fprintf(stderr,"** no header file found for '%s'\n",hname);
+      return -1;
+   }
+   fp = znzopen( tmpname , "rb" , nifti_is_gzfile(tmpname) ) ;
+   free(tmpname);
+   if (znz_isnull(fp))                      return -1 ;  /* bad open? */
+
+   /* read header, close file */
+
+   ii = znzread( &nhdr , 1 , sizeof(nhdr) , fp ) ;
+   znzclose( fp ) ;
+   if( ii < (int) sizeof(nhdr) )               return -1 ;  /* bad read? */
+
+   /* check for NIFTI-ness */
+
+   if( NIFTI_VERSION(nhdr) != 0 ){
+     return ( NIFTI_ONEFILE(nhdr) ) ? 1 : 2 ;
+   }
+
+   /* check for ANALYZE-ness (sizeof_hdr field == 348) */
+
+   ii = nhdr.sizeof_hdr ;
+   if( ii == (int)sizeof(nhdr) ) return 0 ;  /* matches */
+
+   /* try byte-swapping header */
+
+   swap_4(ii) ;
+   if( ii == (int)sizeof(nhdr) ) return 0 ;  /* matches */
+
+   return -1 ;                          /* not good */
+}
+
+static int print_hex_vals( const char * data, int nbytes, FILE * fp )
+{
+   int c;
+
+   if ( !data || nbytes < 1 || !fp ) return -1;
+
+   fputs("0x", fp);
+   for ( c = 0; c < nbytes; c++ )
+      fprintf(fp, " %x", data[c]);
+
+   return 0;
+}
+
+/*----------------------------------------------------------------------*/
+/*! display the contents of the nifti_1_header (send to stdout)
+
+   \param info if non-NULL, print this character string
+   \param hp   pointer to nifti_1_header
+*//*--------------------------------------------------------------------*/
+int disp_nifti_1_header( const char * info, const nifti_1_header * hp )
+{
+   int c;
+
+   fputs( "-------------------------------------------------------\n", stdout );
+   if ( info )  fputs( info, stdout );
+   if ( !hp  ){ fputs(" ** no nifti_1_header to display!\n",stdout); return 1; }
+
+   fprintf(stdout," nifti_1_header :\n"
+           "    sizeof_hdr     = %d\n"
+           "    data_type[10]  = ", hp->sizeof_hdr);
+   print_hex_vals(hp->data_type, 10, stdout);
+   fprintf(stdout, "\n"
+           "    db_name[18]    = ");
+   print_hex_vals(hp->db_name, 18, stdout);
+   fprintf(stdout, "\n"
+           "    extents        = %d\n"
+           "    session_error  = %d\n"
+           "    regular        = 0x%x\n"
+           "    dim_info       = 0x%x\n",
+      hp->extents, hp->session_error, hp->regular, hp->dim_info );
+   fprintf(stdout, "    dim[8]         =");
+   for ( c = 0; c < 8; c++ ) fprintf(stdout," %d", hp->dim[c]);
+   fprintf(stdout, "\n"
+           "    intent_p1      = %f\n"
+           "    intent_p2      = %f\n"
+           "    intent_p3      = %f\n"
+           "    intent_code    = %d\n"
+           "    datatype       = %d\n"
+           "    bitpix         = %d\n"
+           "    slice_start    = %d\n"
+           "    pixdim[8]      =",
+           hp->intent_p1, hp->intent_p2, hp->intent_p3, hp->intent_code,
+           hp->datatype, hp->bitpix, hp->slice_start);
+   /* break pixdim over 2 lines */
+   for ( c = 0; c < 4; c++ ) fprintf(stdout," %f", hp->pixdim[c]);
+   fprintf(stdout, "\n                    ");
+   for ( c = 4; c < 8; c++ ) fprintf(stdout," %f", hp->pixdim[c]);
+   fprintf(stdout, "\n"
+           "    vox_offset     = %f\n"
+           "    scl_slope      = %f\n"
+           "    scl_inter      = %f\n"
+           "    slice_end      = %d\n"
+           "    slice_code     = %d\n"
+           "    xyzt_units     = 0x%x\n"
+           "    cal_max        = %f\n"
+           "    cal_min        = %f\n"
+           "    slice_duration = %f\n"
+           "    toffset        = %f\n"
+           "    glmax          = %d\n"
+           "    glmin          = %d\n",
+           hp->vox_offset, hp->scl_slope, hp->scl_inter, hp->slice_end,
+           hp->slice_code, hp->xyzt_units, hp->cal_max, hp->cal_min,
+           hp->slice_duration, hp->toffset, hp->glmax, hp->glmin);
+   fprintf(stdout,
+           "    descrip        = '%.80s'\n"
+           "    aux_file       = '%.24s'\n"
+           "    qform_code     = %d\n"
+           "    sform_code     = %d\n"
+           "    quatern_b      = %f\n"
+           "    quatern_c      = %f\n"
+           "    quatern_d      = %f\n"
+           "    qoffset_x      = %f\n"
+           "    qoffset_y      = %f\n"
+           "    qoffset_z      = %f\n"
+           "    srow_x[4]      = %f, %f, %f, %f\n"
+           "    srow_y[4]      = %f, %f, %f, %f\n"
+           "    srow_z[4]      = %f, %f, %f, %f\n"
+           "    intent_name    = '%-.16s'\n"
+           "    magic          = '%-.4s'\n",
+           hp->descrip, hp->aux_file, hp->qform_code, hp->sform_code,
+           hp->quatern_b, hp->quatern_c, hp->quatern_d,
+           hp->qoffset_x, hp->qoffset_y, hp->qoffset_z,
+           hp->srow_x[0], hp->srow_x[1], hp->srow_x[2], hp->srow_x[3],
+           hp->srow_y[0], hp->srow_y[1], hp->srow_y[2], hp->srow_y[3],
+           hp->srow_z[0], hp->srow_z[1], hp->srow_z[2], hp->srow_z[3],
+           hp->intent_name, hp->magic);
+   fputs( "-------------------------------------------------------\n", stdout );
+   fflush(stdout);
+
+   return 0;
+}
+
+
+#undef  ERREX
+#define ERREX(msg)                                           \
+ do{ fprintf(stderr,"** ERROR: nifti_convert_nhdr2nim: %s\n", (msg) ) ;  \
+     return NULL ; } while(0)
+
+/*----------------------------------------------------------------------*/
+/*! convert a nifti_1_header into a nift1_image
+  
+   \return an allocated nifti_image, or NULL on failure
+*//*--------------------------------------------------------------------*/
+nifti_image* nifti_convert_nhdr2nim(struct nifti_1_header nhdr,
+                                    const char * fname)
+{
+   int   ii , doswap , ioff ;
+   int   is_nifti , is_onefile ;
+   nifti_image *nim;
+
+   nim = (nifti_image *) calloc( 1 , sizeof(nifti_image) ) ;
+   if( !nim ) ERREX("failed to allocate nifti image");
+
+   /* be explicit with pointers */
+   nim->fname = NULL;
+   nim->iname = NULL;
+   nim->data = NULL;
+
+   /**- check if we must swap bytes */
+  
+   doswap = need_nhdr_swap(nhdr.dim[0], nhdr.sizeof_hdr); /* swap data flag */
+
+   if( doswap < 0 ){
+      if( doswap == -1 ) ERREX("bad dim[0]") ;
+      ERREX("bad sizeof_hdr") ;  /* else */
+   }
+
+   /**- determine if this is a NIFTI-1 compliant header */
+
+   is_nifti = NIFTI_VERSION(nhdr) ;
+   if( doswap ) {
+      if ( g_opts.debug > 3 ) disp_nifti_1_header("-d ni1 pre-swap: ", &nhdr);
+      swap_nifti_header( &nhdr , is_nifti ) ;
+   }
+
+   if ( g_opts.debug > 2 ) disp_nifti_1_header("-d nhdr2nim : ", &nhdr);
+
+   if( nhdr.datatype == DT_BINARY ||
+       nhdr.datatype == DT_UNKNOWN  )    ERREX("bad datatype") ;
+
+   if( nhdr.dim[1] <= 0 )                ERREX("bad dim[1]") ;
+
+   /* fix bad dim[] values in the defined dimension range */
+   for( ii=2 ; ii <= nhdr.dim[0] ; ii++ )
+     if( nhdr.dim[ii] <= 0 ) nhdr.dim[ii] = 1 ;
+
+   /* fix any remaining bad dim[] values, so garbage does not propagate */
+   /* (only values 0 or 1 seem rational, otherwise set to arbirary 1)   */
+   for( ii=nhdr.dim[0]+1 ; ii <= 7 ; ii++ )
+     if( nhdr.dim[ii] != 1 && nhdr.dim[ii] != 0) nhdr.dim[ii] = 1 ;
+
+#if 0  /* rely on dim[0], do not attempt to modify it   16 Nov 2005 [rickr] */
+
+   /**- get number of dimensions (ignoring dim[0] now) */
+   for( ii=7 ; ii >= 2 ; ii-- )            /* loop backwards until we  */
+     if( nhdr.dim[ii] > 1 ) break ;        /* find a dim bigger than 1 */
+   ndim = ii ;
+#endif
+
+   /**- set bad grid spacings to 1.0 */
+
+   for( ii=1 ; ii <= nhdr.dim[0] ; ii++ ){
+     if( nhdr.pixdim[ii] == 0.0         ||
+         !IS_GOOD_FLOAT(nhdr.pixdim[ii])  ) nhdr.pixdim[ii] = 1.0 ;
+   }
+
+  is_onefile = is_nifti && NIFTI_ONEFILE(nhdr) ;
+
+  if( is_nifti ) nim->nifti_type = (is_onefile) ? NIFTI_FTYPE_NIFTI1_1
+                                                : NIFTI_FTYPE_NIFTI1_2 ;
+  else           nim->nifti_type = NIFTI_FTYPE_ANALYZE ;
+  
+  ii = nifti_short_order() ;
+  if( doswap )   nim->byteorder = REVERSE_ORDER(ii) ;
+  else           nim->byteorder = ii ;
+  
+
+  /**- set dimensions of data array */
+  
+  nim->ndim = nim->dim[0] = nhdr.dim[0];
+  nim->nx   = nim->dim[1] = nhdr.dim[1];
+  nim->ny   = nim->dim[2] = nhdr.dim[2];
+  nim->nz   = nim->dim[3] = nhdr.dim[3];
+  nim->nt   = nim->dim[4] = nhdr.dim[4];
+  nim->nu   = nim->dim[5] = nhdr.dim[5];
+  nim->nv   = nim->dim[6] = nhdr.dim[6];
+  nim->nw   = nim->dim[7] = nhdr.dim[7];
+
+  for( ii=1, nim->nvox=1; ii <= nhdr.dim[0]; ii++ )
+     nim->nvox *= nhdr.dim[ii];
+  
+  /**- set the type of data in voxels and how many bytes per voxel */
+  
+  nim->datatype = nhdr.datatype ;
+  
+  nifti_datatype_sizes( nim->datatype , &(nim->nbyper) , &(nim->swapsize) ) ;
+  if( nim->nbyper == 0 ){ free(nim); ERREX("bad datatype"); }
+  
+  /**- set the grid spacings */
+  
+  nim->dx = nim->pixdim[1] = nhdr.pixdim[1] ;
+  nim->dy = nim->pixdim[2] = nhdr.pixdim[2] ;
+  nim->dz = nim->pixdim[3] = nhdr.pixdim[3] ;
+  nim->dt = nim->pixdim[4] = nhdr.pixdim[4] ;
+  nim->du = nim->pixdim[5] = nhdr.pixdim[5] ;
+  nim->dv = nim->pixdim[6] = nhdr.pixdim[6] ;
+  nim->dw = nim->pixdim[7] = nhdr.pixdim[7] ;
+  
+  /**- compute qto_xyz transformation from pixel indexes (i,j,k) to (x,y,z) */
+  
+  if( !is_nifti || nhdr.qform_code <= 0 ){
+    /**- if not nifti or qform_code <= 0, use grid spacing for qto_xyz */
+    
+    nim->qto_xyz.m[0][0] = nim->dx ;  /* grid spacings */
+    nim->qto_xyz.m[1][1] = nim->dy ;  /* along diagonal */
+    nim->qto_xyz.m[2][2] = nim->dz ;
+    
+    /* off diagonal is zero */
+    
+    nim->qto_xyz.m[0][1]=nim->qto_xyz.m[0][2]=nim->qto_xyz.m[0][3] = 0.0;
+    nim->qto_xyz.m[1][0]=nim->qto_xyz.m[1][2]=nim->qto_xyz.m[1][3] = 0.0;
+    nim->qto_xyz.m[2][0]=nim->qto_xyz.m[2][1]=nim->qto_xyz.m[2][3] = 0.0;
+    
+    /* last row is always [ 0 0 0 1 ] */
+    
+    nim->qto_xyz.m[3][0]=nim->qto_xyz.m[3][1]=nim->qto_xyz.m[3][2] = 0.0;
+    nim->qto_xyz.m[3][3]= 1.0 ;
+    
+    nim->qform_code = NIFTI_XFORM_UNKNOWN ;
+    
+    if( g_opts.debug > 1 ) fprintf(stderr,"-d no qform provided\n");
+  } else {
+    /**- else NIFTI: use the quaternion-specified transformation */
+    
+    nim->quatern_b = FIXED_FLOAT( nhdr.quatern_b ) ;
+    nim->quatern_c = FIXED_FLOAT( nhdr.quatern_c ) ;
+    nim->quatern_d = FIXED_FLOAT( nhdr.quatern_d ) ;
+    
+    nim->qoffset_x = FIXED_FLOAT(nhdr.qoffset_x) ;
+    nim->qoffset_y = FIXED_FLOAT(nhdr.qoffset_y) ;
+    nim->qoffset_z = FIXED_FLOAT(nhdr.qoffset_z) ;
+    
+    nim->qfac = (nhdr.pixdim[0] < 0.0) ? -1.0 : 1.0 ;  /* left-handedness? */
+    
+    nim->qto_xyz = nifti_quatern_to_mat44(
+                      nim->quatern_b, nim->quatern_c, nim->quatern_d,
+                      nim->qoffset_x, nim->qoffset_y, nim->qoffset_z,
+                      nim->dx       , nim->dy       , nim->dz       ,
+                      nim->qfac                                      ) ;
+
+    nim->qform_code = nhdr.qform_code ;
+
+    if( g_opts.debug > 1 )
+       nifti_disp_matrix_orient("-d qform orientations:\n", nim->qto_xyz);
+  }
+  
+  /**- load inverse transformation (x,y,z) -> (i,j,k) */
+  
+  nim->qto_ijk = nifti_mat44_inverse( nim->qto_xyz ) ;
+  
+  /**- load sto_xyz affine transformation, if present */
+  
+  if( !is_nifti || nhdr.sform_code <= 0 ){
+    /**- if not nifti or sform_code <= 0, then no sto transformation */
+    
+    nim->sform_code = NIFTI_XFORM_UNKNOWN ;
+
+    if( g_opts.debug > 1 ) fprintf(stderr,"-d no sform provided\n");
+    
+  } else {
+    /**- else set the sto transformation from srow_*[] */
+    
+    nim->sto_xyz.m[0][0] = nhdr.srow_x[0] ;
+    nim->sto_xyz.m[0][1] = nhdr.srow_x[1] ;
+    nim->sto_xyz.m[0][2] = nhdr.srow_x[2] ;
+    nim->sto_xyz.m[0][3] = nhdr.srow_x[3] ;
+    
+    nim->sto_xyz.m[1][0] = nhdr.srow_y[0] ;
+    nim->sto_xyz.m[1][1] = nhdr.srow_y[1] ;
+    nim->sto_xyz.m[1][2] = nhdr.srow_y[2] ;
+    nim->sto_xyz.m[1][3] = nhdr.srow_y[3] ;
+    
+    nim->sto_xyz.m[2][0] = nhdr.srow_z[0] ;
+    nim->sto_xyz.m[2][1] = nhdr.srow_z[1] ;
+    nim->sto_xyz.m[2][2] = nhdr.srow_z[2] ;
+    nim->sto_xyz.m[2][3] = nhdr.srow_z[3] ;
+    
+    /* last row is always [ 0 0 0 1 ] */
+    
+    nim->sto_xyz.m[3][0]=nim->sto_xyz.m[3][1]=nim->sto_xyz.m[3][2] = 0.0;
+    nim->sto_xyz.m[3][3]= 1.0 ;
+    
+    nim->sto_ijk = nifti_mat44_inverse( nim->sto_xyz ) ;
+    
+    nim->sform_code = nhdr.sform_code ;
+
+    if( g_opts.debug > 1 )
+       nifti_disp_matrix_orient("-d sform orientations:\n", nim->sto_xyz);
+  }
+  
+  /**- set miscellaneous NIFTI stuff */
+  
+  if( is_nifti ){
+    nim->scl_slope   = FIXED_FLOAT( nhdr.scl_slope ) ;
+    nim->scl_inter   = FIXED_FLOAT( nhdr.scl_inter ) ;
+    
+    nim->intent_code = nhdr.intent_code ;
+    
+    nim->intent_p1 = FIXED_FLOAT( nhdr.intent_p1 ) ;
+    nim->intent_p2 = FIXED_FLOAT( nhdr.intent_p2 ) ;
+    nim->intent_p3 = FIXED_FLOAT( nhdr.intent_p3 ) ;
+    
+    nim->toffset   = FIXED_FLOAT( nhdr.toffset ) ;
+    
+    memcpy(nim->intent_name,nhdr.intent_name,15); nim->intent_name[15] = '\0';
+    
+    nim->xyz_units  = XYZT_TO_SPACE(nhdr.xyzt_units) ;
+    nim->time_units = XYZT_TO_TIME (nhdr.xyzt_units) ;
+    
+    nim->freq_dim  = DIM_INFO_TO_FREQ_DIM ( nhdr.dim_info ) ;
+    nim->phase_dim = DIM_INFO_TO_PHASE_DIM( nhdr.dim_info ) ;
+    nim->slice_dim = DIM_INFO_TO_SLICE_DIM( nhdr.dim_info ) ;
+    
+    nim->slice_code     = nhdr.slice_code  ;
+    nim->slice_start    = nhdr.slice_start ;
+    nim->slice_end      = nhdr.slice_end   ;
+    nim->slice_duration = FIXED_FLOAT(nhdr.slice_duration) ;
+  }
+  
+  /**- set Miscellaneous ANALYZE stuff */
+  
+  nim->cal_min = FIXED_FLOAT(nhdr.cal_min) ;
+  nim->cal_max = FIXED_FLOAT(nhdr.cal_max) ;
+  
+  memcpy(nim->descrip ,nhdr.descrip ,79) ; nim->descrip [79] = '\0' ;
+  memcpy(nim->aux_file,nhdr.aux_file,23) ; nim->aux_file[23] = '\0' ;
+  
+   /**- set ioff from vox_offset (but at least sizeof(header)) */
+
+   is_onefile = is_nifti && NIFTI_ONEFILE(nhdr) ;
+
+   if( is_onefile ){
+     ioff = (int)nhdr.vox_offset ;
+     if( ioff < (int) sizeof(nhdr) ) ioff = (int) sizeof(nhdr) ;
+   } else {
+     ioff = (int)nhdr.vox_offset ;
+   }
+   nim->iname_offset = ioff ;
+
+
+   /**- deal with file names if set */
+   if (fname!=NULL) {
+       nifti_set_filenames(nim,fname,0,0);
+       if (nim->iname==NULL)  { ERREX("bad filename"); }
+   } else { 
+     nim->fname = NULL;  
+     nim->iname = NULL; 
+   }
+
+   /* clear extension fields */
+   nim->num_ext = 0;
+   nim->ext_list = NULL;
+
+   return nim;
+}
+
+#undef  ERREX
+#define ERREX(msg)                                           \
+ do{ fprintf(stderr,"** ERROR: nifti_image_open(%s): %s\n",  \
+             (hname != NULL) ? hname : "(null)" , (msg) ) ;  \
+     return fptr ; } while(0)
+
+/***************************************************************
+ * nifti_image_open
+ ***************************************************************/
+/*! znzFile nifti_image_open( char *hname, char *opts , nifti_image **nim)
+    \brief Read in NIFTI-1 or ANALYZE-7.5 file (pair) header information into a nifti_image struct.
+
+    - The image data is not read from disk (it may be read later using
+        nifti_image_load(), for example).
+    - The image data will be stored in whatever data format the
+        input data is; no scaling will be applied.
+    - DT_BINARY data is not supported.
+    - nifti_image_free() can be used to delete the returned struct,
+        when you are done with it.
+
+    \param hname filename of dataset .hdr or .nii file
+    \param opts  options string for opening the header file
+    \param nim   pointer to pointer to nifti_image struct
+                 (this routine allocates the nifti_image struct)
+    \return file pointer (gzippable) to the file with the image data,
+                 ready for reading.
+        <br>NULL if something fails badly.
+    \sa nifti_image_load, nifti_image_free
+ */
+znzFile nifti_image_open(const char * hname, char * opts, nifti_image ** nim)
+{
+  znzFile fptr=NULL;
+  /* open the hdr and reading it in, but do not load the data  */
+  *nim = nifti_image_read(hname,0);
+  /* open the image file, ready for reading (compressed works for all reads) */
+  if( ((*nim) == NULL)      || ((*nim)->iname == NULL) ||
+      ((*nim)->nbyper <= 0) || ((*nim)->nvox <= 0)       )
+     ERREX("bad header info") ;
+                                                                                
+  /* open image data file */
+  fptr = znzopen( (*nim)->iname, opts, nifti_is_gzfile((*nim)->iname) );
+  if( znz_isnull(fptr) ) ERREX("Can't open data file") ;
+                                                                                
+  return fptr;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! return an allocated and filled nifti_1_header struct
+
+    Read the binary header from disk, and swap bytes if necessary.
+
+    \return an allocated nifti_1_header struct, or NULL on failure
+
+    \param hname   name of file containing header
+    \param swapped if not NULL, return whether header bytes were swapped
+    \param check   flag to check for invalid nifti_1_header
+
+    \warning ASCII header type is not supported
+
+    \sa nifti_image_read, nifti_image_free, nifti_image_read_bricks
+*//*--------------------------------------------------------------------*/
+nifti_1_header * nifti_read_header(const char * hname, int * swapped, int check)
+{
+   nifti_1_header   nhdr, * hptr;
+   znzFile          fp;
+   int              bytes, lswap;
+   char           * hfile;
+   char             fname[] = { "nifti_read_header" };
+   
+   /* determine file name to use for header */
+   hfile = nifti_findhdrname(hname);
+   if( hfile == NULL ){
+      if( g_opts.debug > 0 )
+         LNI_FERR(fname,"failed to find header file for", hname);
+      return NULL;
+   } else if( g_opts.debug > 1 )
+      fprintf(stderr,"-d %s: found header filename '%s'\n",fname,hfile);
+
+   fp = znzopen( hfile, "rb", nifti_is_gzfile(hfile) );
+   if( znz_isnull(fp) ){
+      if( g_opts.debug > 0 ) LNI_FERR(fname,"failed to open header file",hfile);
+      free(hfile);
+      return NULL;
+   }
+
+   free(hfile);  /* done with filename */
+
+   if( has_ascii_header(fp) == 1 ){
+      znzclose( fp );
+      if( g_opts.debug > 0 )
+         LNI_FERR(fname,"ASCII header type not supported",hname);
+      return NULL;
+   }
+
+   /* read the binary header */ 
+   bytes = znzread( &nhdr, 1, sizeof(nhdr), fp );
+   znzclose( fp );                      /* we are done with the file now */
+
+   if( bytes < (int)sizeof(nhdr) ){
+      if( g_opts.debug > 0 ){
+         LNI_FERR(fname,"bad binary header read for file", hname);
+         fprintf(stderr,"  - read %d of %d bytes\n",bytes, (int)sizeof(nhdr));
+      }
+      return NULL;
+   }
+
+   /* now just decide on byte swapping */
+   lswap = need_nhdr_swap(nhdr.dim[0], nhdr.sizeof_hdr); /* swap data flag */
+   if( check && lswap < 0 ){
+      LNI_FERR(fname,"bad nifti_1_header for file", hname);
+      return NULL;
+   }
+
+   if( lswap ) {
+      if ( g_opts.debug > 3 ) disp_nifti_1_header("-d nhdr pre-swap: ", &nhdr);
+      swap_nifti_header( &nhdr , NIFTI_VERSION(nhdr) ) ;
+   }
+
+   if ( g_opts.debug > 2 ) disp_nifti_1_header("-d nhdr post-swap: ", &nhdr);
+
+   if ( check && ! nifti_hdr_looks_good(&nhdr) ){
+      LNI_FERR(fname,"nifti_1_header looks bad for file", hname);
+      return NULL;
+   }
+
+   /* all looks good, so allocate memory for and return the header */
+   hptr = (nifti_1_header *)malloc(sizeof(nifti_1_header));
+   if( ! hptr ){
+      fprintf(stderr,"** nifti_read_hdr: failed to alloc nifti_1_header\n");
+      return NULL;
+   }
+
+   if( swapped ) *swapped = lswap;  /* only if they care <sniff!> */
+
+   memcpy(hptr, &nhdr, sizeof(nifti_1_header));
+
+   return hptr;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! decide if this nifti_1_header structure looks reasonable
+
+   Check dim[0], dim[1], sizeof_hdr, and datatype.
+   Check magic string for "n+1".
+   Maybe more tests will follow.
+
+   \return 1 if the header seems valid, 0 otherwise
+
+   \sa nifti_nim_is_valid, valid_nifti_extensions
+*//*--------------------------------------------------------------------*/
+int nifti_hdr_looks_good(const nifti_1_header * hdr)
+{
+   int nbyper, swapsize;
+   int c, errs = 0;
+
+   /* check dim[0] and sizeof_hdr */
+   if( need_nhdr_swap(hdr->dim[0], hdr->sizeof_hdr) < 0 ){
+      if( g_opts.debug > 0 )
+         fprintf(stderr,"** bad nhdr fields: dim0, sizeof_hdr = %d, %d\n",
+                 hdr->dim[0], hdr->sizeof_hdr);
+      errs++;
+   }
+
+   /* check the valid dimension sizes (maybe dim[0] is bad) */
+   for( c = 1; c <= hdr->dim[0] && c <= 7; c++ )
+      if( hdr->dim[c] <= 0 ){
+         if( g_opts.debug > 0 )
+            fprintf(stderr,"** bad nhdr field: dim[%d] = %d\n",c,hdr->dim[c]);
+         errs++;
+      }
+
+   /* check the magic string */
+   if( (hdr->magic[0] != 'n')                           ||
+       (hdr->magic[1] != 'i' && hdr->magic[1] != '+')   ||
+       (hdr->magic[2] != '1')                           ||
+       (hdr->magic[3] != '\0') )
+   {
+      if( g_opts.debug > 0 )
+         fprintf(stderr,
+            "** bad nhdr field: magic = '%.4s', should be \"n+1\" or \"ni1\"\n"
+            "   (in hex) magic = 0x%02x%02x%02x%02x\n"
+            "        should be = 0x6e2b3100  or  0x6e693100\n",
+            hdr->magic, hdr->magic[0], hdr->magic[1],
+            hdr->magic[2], hdr->magic[3]);
+      errs++;
+   }
+
+   /* check the datatype */
+   if( hdr->datatype == DT_BINARY || hdr->datatype == DT_UNKNOWN ){
+      if( g_opts.debug > 0 )
+         fprintf(stderr,"** bad nhdr field: datatype = %d\n",hdr->datatype);
+      errs++;
+   }
+
+   nifti_datatype_sizes(hdr->datatype, &nbyper, &swapsize);
+   if( nbyper == 0 ){
+      if( g_opts.debug > 0 )
+         fprintf(stderr,"** bad nhdr field: datatype = %d\n",hdr->datatype);
+      errs++;
+   }
+
+   if( errs ) return 0;  /* problems */
+
+   if( g_opts.debug > 2 ) fprintf(stderr,"-d nifti header looks good\n");
+
+   return 1;   /* looks good */
+}
+
+
+/*----------------------------------------------------------------------
+ * check whether byte swapping is needed
+ * 
+ * dim[0] should be in [0,7], and sizeof_hdr should be accurate
+ *
+ * \returns  > 0 : needs swap
+ *             0 : does not need swap
+ *           < 0 : error condition
+ *----------------------------------------------------------------------*/
+static int need_nhdr_swap( short dim0, int hdrsize )
+{
+   short d0    = dim0;     /* so we won't have to swap them on the stack */
+   int   hsize = hdrsize;
+
+   if( d0 != 0 ){     /* then use it for the check */
+      if( d0 > 0 && d0 <= 7 ) return 0;
+
+      nifti_swap_2bytes(1, &d0);        /* swap? */
+      if( d0 > 0 && d0 <= 7 ) return 1;
+
+      if( g_opts.debug > 1 ){
+         fprintf(stderr,"** bad swapped d0 = %d, unswapped = ", d0);
+         nifti_swap_2bytes(1, &d0);        /* swap? */
+         fprintf(stderr,"%d\n", d0);
+      }
+
+      return -1;        /* bad, naughty d0 */
+   } 
+
+   /* dim[0] == 0 should not happen, but could, so try hdrsize */
+   if( hsize == sizeof(nifti_1_header) ) return 0;
+
+   nifti_swap_4bytes(1, &hsize);     /* swap? */
+   if( hsize == sizeof(nifti_1_header) ) return 1;
+
+   if( g_opts.debug > 1 ){
+      fprintf(stderr,"** bad swapped hsize = %d, unswapped = ", hsize);
+      nifti_swap_4bytes(1, &hsize);        /* swap? */
+      fprintf(stderr,"%d\n", hsize);
+   }
+
+   return -2;     /* bad, naughty hsize */
+}
+
+
+/* use macro LNI_FILE_ERROR instead of ERREX()
+#undef  ERREX
+#define ERREX(msg)                                           \
+ do{ fprintf(stderr,"** ERROR: nifti_image_read(%s): %s\n",  \
+             (hname != NULL) ? hname : "(null)" , (msg) ) ;  \
+     return NULL ; } while(0)
+*/
+
+
+/***************************************************************
+ * nifti_image_read
+ ***************************************************************/
+/*! \brief Read a nifti header and optionally the data, creating a nifti_image.
+
+        - The data buffer will be byteswapped if necessary.
+        - The data buffer will not be scaled.
+        - The data buffer is allocated with calloc().
+
+    \param hname filename of the nifti dataset
+    \param read_data Flag, true=read data blob, false=don't read blob.
+    \return A pointer to the nifti_image data structure.
+
+    \sa nifti_image_free, nifti_free_extensions, nifti_image_read_bricks
+*/
+nifti_image *nifti_image_read( const char *hname , int read_data )
+{
+   struct nifti_1_header  nhdr ;
+   nifti_image           *nim ;
+   znzFile                fp ;
+   int                    rv, ii , filesize, remaining;
+   char                   fname[] = { "nifti_image_read" };
+   char                  *hfile=NULL;
+
+   if( g_opts.debug > 1 ){
+      fprintf(stderr,"-d image_read from '%s', read_data = %d",hname,read_data);
+#ifdef HAVE_ZLIB
+      fprintf(stderr,", HAVE_ZLIB = 1\n");
+#else
+      fprintf(stderr,", HAVE_ZLIB = 0\n");
+#endif
+   }
+
+   /**- determine filename to use for header */
+   hfile = nifti_findhdrname(hname);
+   if( hfile == NULL ){
+      if(g_opts.debug > 0)
+         LNI_FERR(fname,"failed to find header file for", hname);
+      return NULL;  /* check return */
+   } else if( g_opts.debug > 1 )
+      fprintf(stderr,"-d %s: found header filename '%s'\n",fname,hfile);
+
+   if( nifti_is_gzfile(hfile) ) filesize = -1;  /* unknown */
+   else                         filesize = nifti_get_filesize(hfile);
+
+   fp = znzopen(hfile, "rb", nifti_is_gzfile(hfile));
+   if( znz_isnull(fp) ){
+      if( g_opts.debug > 0 ) LNI_FERR(fname,"failed to open header file",hfile);
+      free(hfile);
+      return NULL;
+   }
+
+   rv = has_ascii_header( fp );
+   if( rv < 0 ){
+      if( g_opts.debug > 0 ) LNI_FERR(fname,"short header read",hfile);
+      znzclose( fp );
+      free(hfile);
+      return NULL;
+   }
+   else if ( rv == 1 )  /* process special file type */
+      return nifti_read_ascii_image( fp, hfile, filesize, read_data );
+
+   /* else, just process normally */
+
+   /**- read binary header */
+
+   ii = znzread( &nhdr , 1 , sizeof(nhdr) , fp ) ;       /* read the thing */
+
+   /* keep file open so we can check for exts. after nifti_convert_nhdr2nim() */
+
+   if( ii < sizeof(nhdr) ){
+      if( g_opts.debug > 0 ){
+         LNI_FERR(fname,"bad binary header read for file", hfile);
+         fprintf(stderr,"  - read %d of %d bytes\n",ii, (int)sizeof(nhdr));
+      }
+      znzclose(fp) ;
+      free(hfile);
+      return NULL;
+   }
+
+   /* create output image struct and set it up */
+
+   /**- convert all nhdr fields to nifti_image fields */
+   nim = nifti_convert_nhdr2nim(nhdr,hfile);
+
+   if( nim == NULL ){
+      znzclose( fp ) ;                                   /* close the file */
+      if( g_opts.debug > 0 )
+         LNI_FERR(fname,"cannot create nifti image from header",hfile);
+      free(hfile); /* had to save this for debug message */
+      return NULL;
+   }
+
+   if( g_opts.debug > 3 ){
+      fprintf(stderr,"+d nifti_image_read(), have nifti image:\n");
+      if( g_opts.debug > 2 ) nifti_image_infodump(nim);
+   }
+
+   /**- check for extensions (any errors here means no extensions) */
+   if( NIFTI_ONEFILE(nhdr) ) remaining = nim->iname_offset - sizeof(nhdr);
+   else                      remaining = filesize - sizeof(nhdr);
+
+   (void)nifti_read_extensions(nim, fp, remaining);
+
+   znzclose( fp ) ;                                      /* close the file */
+   free(hfile);
+
+   /**- read the data if desired, then bug out */
+   if( read_data ){
+      if( nifti_image_load( nim ) < 0 ){
+         nifti_image_free(nim);          /* take ball, go home. */
+         return NULL;
+      }
+   }
+   else nim->data = NULL ;
+
+   return nim ;
+}
+
+
+/*----------------------------------------------------------------------
+ * has_ascii_header  - see if the NIFTI header is an ASCII format
+ *
+ * If the file starts with the ASCII string "<nifti_image", then
+ * process the dataset as a type-3 .nia file.
+ *
+ * return:  -1 on error, 1 if true, or 0 if false
+ *
+ * NOTE: this is NOT part of the NIFTI-1 standard
+ *----------------------------------------------------------------------*/
+static int has_ascii_header( znzFile fp )
+{
+   char  buf[16];
+   int   nread;
+
+   if( znz_isnull(fp) ) return 0;
+
+   nread = znzread( buf, 1, 12, fp );
+   buf[12] = '\0';
+
+   if( nread < 12 ) return -1;
+
+   znzrewind(fp);  /* move back to the beginning, and check */
+
+   if( strcmp(buf, "<nifti_image") == 0 ) return 1;
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! nifti_read_ascii_image  - process as a type-3 .nia image file
+
+   return NULL on failure
+  
+   NOTE: this is NOT part of the NIFTI-1 standard
+*//*--------------------------------------------------------------------*/
+nifti_image * nifti_read_ascii_image(znzFile fp, char *fname, int flen,
+                                     int read_data)
+{
+   nifti_image * nim;
+   int           slen, txt_size, remain, rv = 0;
+   char        * sbuf, lfunc[25] = { "nifti_read_ascii_image" };
+
+   if( nifti_is_gzfile(fname) ){
+      LNI_FERR(lfunc, "compressed file with negative offset", fname);
+      free(fname);  znzclose(fp);  return NULL;
+   }
+   slen = flen;  /* slen will be our buffer length */
+
+   if( g_opts.debug > 1 )
+      fprintf(stderr,"-d %s: have ASCII NIFTI file of size %d\n",fname,slen);
+
+   if( slen > 65530 ) slen = 65530 ;
+   sbuf = (char *)calloc(sizeof(char),slen+1) ;
+   if( !sbuf ){
+      fprintf(stderr,"** %s: failed to alloc %d bytes for sbuf",lfunc,65530);
+      free(fname);  znzclose(fp);  return NULL;
+   }
+   znzread( sbuf , 1 , slen , fp ) ;
+   nim = nifti_image_from_ascii( sbuf, &txt_size ) ; free( sbuf ) ;
+   if( nim == NULL ){
+      LNI_FERR(lfunc,"failed nifti_image_from_ascii()",fname);
+      free(fname);  znzclose(fp);  return NULL;
+   }
+   nim->nifti_type = NIFTI_FTYPE_ASCII ;
+
+   /* compute remaining space for extensions */
+   remain = flen - txt_size - (int)nifti_get_volsize(nim);
+   if( remain > 4 ){
+      /* read extensions (reposition file pointer, first) */
+      znzseek(fp, txt_size, SEEK_SET);
+      (void) nifti_read_extensions(nim, fp, remain);
+   }
+
+   free(fname);
+   znzclose( fp ) ;
+
+   nim->iname_offset = -1 ;  /* check from the end of the file */
+
+   if( read_data ) rv = nifti_image_load( nim ) ;
+   else            nim->data = NULL ;
+
+   /* check for nifti_image_load() failure, maybe bail out */
+   if( read_data && rv != 0 ){
+      if( g_opts.debug > 1 )
+         fprintf(stderr,"-d failed image_load, free nifti image struct\n");
+      free(nim);
+      return NULL;
+   }
+
+   return nim ;
+}
+
+
+/*----------------------------------------------------------------------
+ * Read the extensions into the nifti_image struct   08 Dec 2004 [rickr]
+ *
+ * This function is called just after the header struct is read in, and
+ * it is assumed the file pointer has not moved.  The value in remain
+ * is assumed to be accurate, reflecting the bytes of space for potential
+ * extensions.
+ *
+ * return the number of extensions read in, or < 0 on error
+ *----------------------------------------------------------------------*/
+static int nifti_read_extensions( nifti_image *nim, znzFile fp, int remain )
+{
+   nifti1_extender    extdr;      /* defines extension existence  */
+   nifti1_extension   extn;       /* single extension to process  */
+   nifti1_extension * Elist;      /* list of processed extensions */
+   int                posn, count;
+
+   if( !nim || znz_isnull(fp) ) {
+      if( g_opts.debug > 0 )
+         fprintf(stderr,"** nifti_read_extensions: bad inputs (%p,%p)\n",
+                 (void *)nim, (void *)fp);
+      return -1;
+   }
+
+   posn = znztell(fp);
+ 
+   if( (posn != sizeof(nifti_1_header)) &&
+       (nim->nifti_type != NIFTI_FTYPE_ASCII) )
+      fprintf(stderr,"** WARNING: posn not header size (%d, %d)\n",
+              posn, (int)sizeof(nifti_1_header));
+
+   if( g_opts.debug > 2 )
+      fprintf(stderr,"-d nre: posn = %d, offset = %d, type = %d, remain = %d\n",
+              posn, nim->iname_offset, nim->nifti_type, remain);
+
+   if( remain < 16 ){
+      if( g_opts.debug > 2 ){
+         if( g_opts.skip_blank_ext )
+            fprintf(stderr,"-d no extender in '%s' is okay, as "
+                           "skip_blank_ext is set\n",nim->fname);
+         else
+            fprintf(stderr,"-d no space for extensions\n");
+      }
+      return 0;
+   }
+
+   count = znzread( extdr.extension, 1, 4, fp ); /* get extender */
+
+   if( count < 4 ){
+      if( g_opts.debug > 1 )
+         fprintf(stderr,"-d file '%s' is too short for an extender\n",
+                 nim->fname);
+      return 0;
+   }
+
+   if( extdr.extension[0] != 1 ){
+      if( g_opts.debug > 2 )
+         fprintf(stderr,"-d extender[0] (%d) shows no extensions for '%s'\n",
+                 extdr.extension[0], nim->fname);
+      return 0;
+   }
+
+   remain -= 4;
+   if( g_opts.debug > 2 )
+      fprintf(stderr,"-d found valid 4-byte extender, remain = %d\n", remain);
+
+   /* so we expect extensions, but have no idea of how many there may be */
+
+   count = 0;
+   Elist = NULL;
+   while (nifti_read_next_extension(&extn, nim, remain, fp) > 0)
+   {
+      if( nifti_add_exten_to_list(&extn, &Elist, count+1) < 0 ){
+         if( g_opts.debug > 0 )
+            fprintf(stderr,"** failed adding ext %d to list\n", count);
+         return -1;
+      }
+
+      /* we have a new extension */
+      if( g_opts.debug > 1 ){
+         fprintf(stderr,"+d found extension #%d, code = 0x%x, size = %d\n",
+                 count, extn.ecode, extn.esize);
+         if( extn.ecode == NIFTI_ECODE_AFNI && g_opts.debug > 2 ) /* ~XML */
+            fprintf(stderr,"   AFNI extension: %.*s\n",
+                    extn.esize-8,extn.edata);
+         else if( extn.ecode == NIFTI_ECODE_COMMENT && g_opts.debug > 2 )
+            fprintf(stderr,"   COMMENT extension: %.*s\n",        /* TEXT */
+                    extn.esize-8,extn.edata);
+      }
+      remain -= extn.esize;
+      count++;
+   }
+
+   if( g_opts.debug > 2 ) fprintf(stderr,"+d found %d extension(s)\n", count);
+
+   nim->num_ext = count;
+   nim->ext_list = Elist;
+
+   return count;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! nifti_add_extension - add an extension, with a copy of the data
+
+   Add an extension to the nim->ext_list array.
+   Fill this extension with a copy of the data, noting the
+       length and extension code.
+
+   \param nim    - nifti_image to add extension to
+   \param data   - raw extension data
+   \param length - length of raw extension data
+   \param ecode  - extension code
+
+   \sa extension codes NIFTI_ECODE_* in nifti1_io.h
+   \sa nifti_free_extensions, valid_nifti_extensions, nifti_copy_extensions
+
+   \return 0 on success, -1 on error (and free the entire list)
+*//*--------------------------------------------------------------------*/
+int nifti_add_extension(nifti_image *nim, const char * data, int len, int ecode)
+{
+   nifti1_extension ext;
+
+   /* error are printed in functions */
+   if( nifti_fill_extension(&ext, data, len, ecode) )                 return -1;
+   if( nifti_add_exten_to_list(&ext, &nim->ext_list, nim->num_ext+1)) return -1;
+
+   nim->num_ext++;  /* success, so increment */
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/* nifti_add_exten_to_list     - add a new nifti1_extension to the list
+
+   We will append via "malloc, copy and free", because on an error,
+   the old data pointers must all be released (sorry realloc(), only
+   quality dolphins get to become part of St at rk!st brand tunafish).
+
+   return 0 on success, -1 on error (and free the entire list)
+*//*--------------------------------------------------------------------*/
+static int nifti_add_exten_to_list( nifti1_extension *  new_ext,
+                                    nifti1_extension ** list, int new_length )
+{
+   nifti1_extension * tmplist;
+   int                count;
+  
+   tmplist = *list;
+   *list = (nifti1_extension *)malloc(new_length * sizeof(nifti1_extension));
+
+   /* check for failure first */
+   if( ! *list ){
+      fprintf(stderr,"** failed to alloc %d extension structs (%d bytes)\n",
+              new_length, new_length*(int)sizeof(nifti1_extension));
+      if( !tmplist ) return -1;  /* no old list to lose */
+
+      for ( count = 0; count < new_length-1; count++ )
+         if( tmplist[count].edata ) free(tmplist[count].edata);
+      free(tmplist);
+      return -1;
+   }
+
+   /* we have memory, so copy the old and insert the new */
+   memcpy(*list, tmplist, (new_length-1)*sizeof(nifti1_extension));
+
+   /* for some reason, I just don't like struct copy... */
+   (*list)[new_length-1].esize = new_ext->esize;
+   (*list)[new_length-1].ecode = new_ext->ecode;
+   (*list)[new_length-1].edata = new_ext->edata;
+
+   if( g_opts.debug > 2 )
+      fprintf(stderr,"+d allocated and appended extension #%d to list\n",
+              new_length);
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/* nifti_fill_extension  - given data and length, fill an extension struct
+
+   Allocate memory for data, copy data, set the size and code.
+
+   return 0 on success, -1 on error (and free the entire list)
+*//*--------------------------------------------------------------------*/
+static int nifti_fill_extension( nifti1_extension *ext, const char * data,
+                                int len, int ecode)
+{
+   int esize;
+
+   if( !ext || !data || len < 0 ){
+      fprintf(stderr,"** fill_ext: bad params (%p,%p,%d)\n",
+              (void *)ext, data, len);
+      return -1;
+   } else if( ! nifti_is_valid_ecode(ecode) ){
+      fprintf(stderr,"** fill_ext: invalid ecode %d\n", ecode);
+      return -1;
+   }
+
+   /* compute esize, first : len+8, and take ceiling up to a mult of 16 */
+   esize = len+8;
+   if( esize & 0xf ) esize = (esize + 0xf) & ~0xf;
+   ext->esize = esize;
+
+   /* allocate esize-8 (maybe more than len), using calloc for fill */
+   ext->edata = (char *)calloc(esize-8, sizeof(char));
+   if( !ext->edata ){
+      fprintf(stderr,"** NFE: failed to alloc %d bytes for extension\n",len);
+      return -1;
+   }
+
+   memcpy(ext->edata, data, len);  /* copy the data, using len */
+   ext->ecode = ecode;             /* set the ecode */
+
+   if( g_opts.debug > 2 )
+      fprintf(stderr,"+d alloc %d bytes for ext len %d, ecode %d, esize %d\n",
+              esize-8, len, ecode, esize);
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------
+ * nifti_read_next_extension  - read a single extension from the file
+ *
+ * return (>= 0 is okay):
+ *
+ *     success      : esize
+ *     no extension : 0
+ *     error        : -1
+ *----------------------------------------------------------------------*/
+static int nifti_read_next_extension( nifti1_extension * nex, nifti_image *nim,
+                                      int remain, znzFile fp )
+{
+   int swap = nim->byteorder != nifti_short_order();
+   int count, size, code;
+
+   /* first clear nex */
+   nex->esize = nex->ecode = 0;
+   nex->edata = NULL;
+
+   if( remain < 16 ){
+      if( g_opts.debug > 2 )
+         fprintf(stderr,"-d only %d bytes remain, so no extension\n", remain);
+      return 0;
+   }
+
+   /* must start with 4-byte size and code */
+   count = znzread( &size, 4, 1, fp );
+   if( count == 1 ) count += znzread( &code, 4, 1, fp );
+
+   if( count != 2 ){
+      if( g_opts.debug > 2 )
+         fprintf(stderr,"-d current extension read failed\n");
+      znzseek(fp, -4*count, SEEK_CUR); /* back up past any read */
+      return 0;                        /* no extension, no error condition */
+   }
+
+   if( swap ){
+      if( g_opts.debug > 2 )
+         fprintf(stderr,"-d pre-swap exts: code %d, size %d\n", code, size);
+
+      nifti_swap_4bytes(1, &size);
+      nifti_swap_4bytes(1, &code);
+   }
+
+   if( g_opts.debug > 2 )
+      fprintf(stderr,"-d potential extension: code %d, size %d\n", code, size);
+
+   if( !nifti_check_extension(nim, size, code, remain) ){
+      if( znzseek(fp, -8, SEEK_CUR) < 0 ){      /* back up past any read */
+         fprintf(stderr,"** failure to back out of extension read!\n");
+         return -1;
+      }
+      return 0;
+   }
+
+   /* now get the actual data */
+   nex->esize = size;
+   nex->ecode = code;
+
+   size -= 8;  /* subtract space for size and code in extension */
+   nex->edata = (char *)malloc(size * sizeof(char));
+   if( !nex->edata ){
+      fprintf(stderr,"** failed to allocate %d bytes for extension\n",size);
+      return -1;
+   }
+
+   count = znzread(nex->edata, 1, size, fp);
+   if( count < size ){
+      if( g_opts.debug > 0 )
+         fprintf(stderr,"-d read only %d (of %d) bytes for extension\n",
+                 count, size);
+      free(nex->edata);
+      nex->edata = NULL;
+      return -1;
+   }
+
+   /* success! */
+   if( g_opts.debug > 2 )
+      fprintf(stderr,"+d successfully read extension, code %d, size %d\n",
+              nex->ecode, nex->esize);
+
+   return nex->esize;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! for each extension, check code, size and data pointer
+*//*--------------------------------------------------------------------*/
+int valid_nifti_extensions(const nifti_image * nim)
+{
+   nifti1_extension * ext;
+   int                c, errs;
+
+   if( nim->num_ext <= 0 || nim->ext_list == NULL ){
+      if( g_opts.debug > 2 ) fprintf(stderr,"-d empty extension list\n");
+      return 0;
+   }
+
+   /* for each extension, check code, size and data pointer */
+   ext = nim->ext_list;
+   errs = 0;
+   for ( c = 0; c < nim->num_ext; c++ ){
+      if( ! nifti_is_valid_ecode(ext->ecode) ) {
+         if( g_opts.debug > 1 )
+            fprintf(stderr,"-d ext %d, invalid code %d\n", c, ext->ecode);
+         errs++;
+      }
+
+      if( ext->esize <= 0 ){
+         if( g_opts.debug > 1 )
+            fprintf(stderr,"-d ext %d, bad size = %d\n", c, ext->esize);
+         errs++;
+      } else if( ext->esize & 0xf ){
+         if( g_opts.debug > 1 )
+            fprintf(stderr,"-d ext %d, size %d not multiple of 16\n",
+                    c, ext->esize);
+         errs++;
+      }
+
+      if( ext->edata == NULL ){
+         if( g_opts.debug > 1 ) fprintf(stderr,"-d ext %d, missing data\n", c);
+         errs++;
+      }
+
+      ext++;
+   }
+
+   if( errs > 0 ){
+      if( g_opts.debug > 0 )
+         fprintf(stderr,"-d had %d extension errors, none will be written\n",
+                 errs);
+      return 0;
+   }
+
+   /* if we're here, we're good */
+   return 1;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! check whether the extension code is valid
+
+    \return 1 if valid, 0 otherwise
+*//*--------------------------------------------------------------------*/
+int nifti_is_valid_ecode( int ecode )
+{
+   if( ecode < NIFTI_ECODE_IGNORE  ||   /* minimum code number (0) */
+       ecode > NIFTI_MAX_ECODE     ||   /* maximum code number     */
+       ecode & 1 )                      /* cannot be odd           */
+      return 0;
+
+   return 1;
+}
+
+
+/*----------------------------------------------------------------------
+ * check for valid size and code, as well as can be done
+ *----------------------------------------------------------------------*/
+static int nifti_check_extension(nifti_image *nim, int size, int code, int rem)
+{
+   /* check for bad code before bad size */
+   if( ! nifti_is_valid_ecode(code) ) {
+      if( g_opts.debug > 2 )
+         fprintf(stderr,"-d invalid extension code %d\n",code);
+      return 0;
+   }
+
+   if( size < 16 ){
+      if( g_opts.debug > 2 )
+         fprintf(stderr,"-d ext size %d, no extension\n",size);
+      return 0;
+   }
+
+   if( size > rem ){
+      if( g_opts.debug > 2 )
+         fprintf(stderr,"-d ext size %d, space %d, no extension\n", size, rem);
+      return 0;
+   }
+
+   if( size & 0xf ){
+      if( g_opts.debug > 2 )
+         fprintf(stderr,"-d nifti extension size %d not multiple of 16\n",size);
+      return 0;
+   }
+
+   if( nim->nifti_type == NIFTI_FTYPE_ASCII && size > LNI_MAX_NIA_EXT_LEN ){
+      if( g_opts.debug > 2 )
+         fprintf(stderr,"-d NVE, bad nifti_type 3 size %d\n", size);
+      return 0;
+   }
+
+   return 1;
+}
+
+
+/*----------------------------------------------------------------------
+ * nifti_image_load_prep  - prepare to read data
+ *
+ * Check nifti_image fields, open the file and seek to the appropriate
+ * offset for reading.
+ *
+ * return NULL on failure
+ *----------------------------------------------------------------------*/
+static znzFile nifti_image_load_prep( nifti_image *nim )
+{
+   /* set up data space, open data file and seek, then call nifti_read_buffer */
+   size_t ntot , ii , ioff;
+   znzFile fp;
+   char    fname[] = { "nifti_image_load_prep" };
+
+   /**- perform sanity checks */
+   if( nim == NULL      || nim->iname == NULL ||
+       nim->nbyper <= 0 || nim->nvox <= 0       )
+   {
+      if ( g_opts.debug > 0 ){
+         if( !nim ) fprintf(stderr,"** ERROR: N_image_load: no nifti image\n");
+         else fprintf(stderr,"** ERROR: N_image_load: bad params (%p,%d,%d)\n",
+                      nim->iname, nim->nbyper, nim->nvox);
+      }
+      return NULL;
+   }
+
+   ntot = nifti_get_volsize(nim) ; /* total bytes to read */
+
+   /**- open image data file */
+
+   fp = znzopen(nim->iname, "rb", nifti_is_gzfile(nim->iname));
+   if( znz_isnull(fp) ){
+      if( g_opts.debug > 0 ) LNI_FERR(fname,"cannot open data file",nim->iname);
+      return NULL;
+   }
+
+   /**- get image offset: a negative offset means to figure from end of file */
+   if( nim->iname_offset < 0 ){
+     if( nifti_is_gzfile(nim->iname) ){
+        if( g_opts.debug > 0 )
+           LNI_FERR(fname,"negative offset for compressed file",nim->iname);
+        znzclose(fp);
+        return NULL;
+     }
+     ii = nifti_get_filesize( nim->iname ) ;
+     if( ii <= 0 ){
+        if( g_opts.debug > 0 ) LNI_FERR(fname,"empty data file",nim->iname);
+        znzclose(fp);
+        return NULL;
+     }
+     ioff = (ii > ntot) ? ii-ntot : 0 ;
+   } else {                              /* non-negative offset   */
+     ioff = nim->iname_offset ;          /* means use it directly */
+   }
+
+   /**- seek to the appropriate read position */
+   if( znzseek(fp , ioff , SEEK_SET) < 0 ){
+      fprintf(stderr,"** could not seek to offset %d in file '%s'\n",
+              (int)ioff, nim->iname);
+      znzclose(fp);
+      return NULL;
+   }
+
+   /**- and return the File pointer */
+   return fp;
+}
+
+
+/*----------------------------------------------------------------------
+ * nifti_image_load
+ *----------------------------------------------------------------------*/
+/*! \fn int nifti_image_load( nifti_image *nim )
+    \brief Load the image blob into a previously initialized nifti_image.
+
+        - If not yet set, the data buffer is allocated with calloc().
+        - The data buffer will be byteswapped if necessary.
+        - The data buffer will not be scaled.
+
+    This function is used to read the image from disk.  It should be used
+    after a function such as nifti_image_read(), so that the nifti_image
+    structure is already initialized.
+
+    \param  nim pointer to a nifti_image (previously initialized)
+    \return 0 on success, -1 on failure
+    \sa     nifti_image_read, nifti_image_free, nifti_image_unload
+*/
+int nifti_image_load( nifti_image *nim )
+{
+   /* set up data space, open data file and seek, then call nifti_read_buffer */
+   size_t ntot , ii ;
+   znzFile fp ;
+
+   /**- open the file and position the FILE pointer */
+   fp = nifti_image_load_prep( nim );
+
+   if( fp == NULL ){
+      if( g_opts.debug > 0 )
+         fprintf(stderr,"** nifti_image_load, failed load_prep\n");
+      return -1;
+   }
+
+   ntot = nifti_get_volsize(nim);
+
+   /**- if the data pointer is not yet set, get memory space for the image */
+
+   if( nim->data == NULL )
+   {
+     nim->data = (void *)calloc(1,ntot) ;  /* create image memory */
+     if( nim->data == NULL ){
+        if( g_opts.debug > 0 )
+           fprintf(stderr,"** failed to alloc %d bytes for image data\n",
+                   (int)ntot);
+        znzclose(fp);
+        return -1;
+     }
+   }
+
+   /**- now that everything is set up, do the reading */
+   ii = nifti_read_buffer(fp,nim->data,ntot,nim);
+   if( ii < ntot ){
+      znzclose(fp) ;
+      free(nim->data) ;
+      nim->data = NULL ;
+      return -1 ;  /* errors were printed in nifti_read_buffer() */
+   }
+
+   /**- close the file */
+   znzclose( fp ) ;
+
+   return 0 ;
+}
+
+
+/* 30 Nov 2004 [rickr]
+#undef  ERREX
+#define ERREX(msg)                                               \
+ do{ fprintf(stderr,"** ERROR: nifti_read_buffer: %s\n",(msg)) ;  \
+     return 0; } while(0)
+*/
+
+/*----------------------------------------------------------------------*/
+/*! read ntot bytes of data from an open file and byte swaps if necessary
+
+   note that nifti_image is required for information on datatype, bsize
+   (for any needed byte swapping), etc.
+
+   This function does not allocate memory, so dataptr must be valid.
+*//*--------------------------------------------------------------------*/
+size_t nifti_read_buffer(znzFile fp, void* dataptr, size_t ntot, 
+                                nifti_image *nim)
+{
+  size_t ii;
+
+  if( dataptr == NULL ){
+     if( g_opts.debug > 0 )
+        fprintf(stderr,"** ERROR: nifti_read_buffer: NULL dataptr\n");
+     return -1;
+  }
+
+  ii = znzread( dataptr , 1 , ntot , fp ) ;             /* data input */
+  
+  /* if read was short, fail */
+  if( ii < ntot ){ 
+    if( g_opts.debug > 0 )
+       fprintf(stderr,"++ WARNING: nifti_read_buffer(%s):\n"
+               "   data bytes needed = %u\n"
+               "   data bytes input  = %u\n"
+               "   number missing    = %u (set to 0)\n",
+               nim->iname , (unsigned int)ntot ,
+               (unsigned int)ii , (unsigned int)(ntot-ii) ) ;
+    /* memset( (char *)(dataptr)+ii , 0 , ntot-ii ) ;  now failure [rickr] */
+    return -1 ;
+  }
+  
+  /* byte swap array if needed */
+  
+  if( nim->swapsize > 1 && nim->byteorder != nifti_short_order() )
+    nifti_swap_Nbytes( ntot / nim->swapsize , nim->swapsize , dataptr ) ;
+  
+#ifdef isfinite
+{
+  /* check input float arrays for goodness, and fix bad floats */
+  int fix_count = 0 ;
+  
+  switch( nim->datatype ){
+    
+    case NIFTI_TYPE_FLOAT32:
+    case NIFTI_TYPE_COMPLEX64:{
+        register float *far = (float *)dataptr ; register int jj,nj ;
+        nj = ntot / sizeof(float) ;
+        for( jj=0 ; jj < nj ; jj++ )   /* count fixes 30 Nov 2004 [rickr] */
+           if( !IS_GOOD_FLOAT(far[jj]) ){
+              far[jj] = 0 ;
+              fix_count++ ;
+           }
+      }
+      break ;
+    
+    case NIFTI_TYPE_FLOAT64:
+    case NIFTI_TYPE_COMPLEX128:{
+        register double *far = (double *)dataptr ; register int jj,nj ;
+        nj = ntot / sizeof(double) ;
+        for( jj=0 ; jj < nj ; jj++ )   /* count fixes 30 Nov 2004 [rickr] */
+           if( !IS_GOOD_FLOAT(far[jj]) ){
+              far[jj] = 0 ;
+              fix_count++ ;
+           }
+      }
+      break ;
+    
+  }
+
+  if( g_opts.debug > 1 )
+     fprintf(stderr,"+d in image, %d bad floats were set to 0\n", fix_count);
+}
+#endif
+  
+  return ii;
+}
+
+/*--------------------------------------------------------------------------*/
+/*! Unload the data in a nifti_image struct, but keep the metadata.
+*//*------------------------------------------------------------------------*/
+void nifti_image_unload( nifti_image *nim )
+{
+   if( nim != NULL && nim->data != NULL ){
+     free(nim->data) ; nim->data = NULL ;
+   }
+   return ;
+}
+
+/*--------------------------------------------------------------------------*/
+/*! free 'everything' about a nifti_image struct (including the passed struct)
+
+    free (only fields which are not NULL):
+      - fname and iname
+      - data
+      - any ext_list[i].edata
+      - ext_list
+      - nim
+*//*------------------------------------------------------------------------*/
+void nifti_image_free( nifti_image *nim )
+{
+   if( nim == NULL ) return ;
+   if( nim->fname != NULL ) free(nim->fname) ;
+   if( nim->iname != NULL ) free(nim->iname) ;
+   if( nim->data  != NULL ) free(nim->data ) ;
+   (void)nifti_free_extensions( nim ) ;
+   free(nim) ; return ;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! free the nifti extensions
+
+    - If any edata pointer is set in the extension list, free() it.
+    - Free ext_list, if it is set.
+    - Clear num_ext and ext_list from nim.
+
+    \return 0 on success, -1 on error
+
+    \sa nifti_add_extension, nifti_copy_extensions
+*//*------------------------------------------------------------------------*/
+int nifti_free_extensions( nifti_image *nim )
+{
+   int c ;
+   if( nim == NULL ) return -1;
+   if( nim->num_ext > 0 && nim->ext_list ){
+      for( c = 0; c < nim->num_ext; c++ )
+         if ( nim->ext_list[c].edata ) free(nim->ext_list[c].edata);
+      free(nim->ext_list);
+   }
+   /* or if it is inconsistent, warn the user (if we are not in quiet mode) */
+   else if ( (nim->num_ext > 0 || nim->ext_list != NULL) && (g_opts.debug > 0) )
+      fprintf(stderr,"** warning: nifti extension num/ptr mismatch (%d,%p)\n",
+              nim->num_ext, (void *)nim->ext_list);
+
+   if( g_opts.debug > 2 )
+      fprintf(stderr,"+d free'd %d extension(s)\n", nim->num_ext);
+
+   nim->num_ext = 0;
+   nim->ext_list = NULL;
+
+   return 0;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! Print to stdout some info about a nifti_image struct.
+*//*------------------------------------------------------------------------*/
+void nifti_image_infodump( const nifti_image *nim )
+{
+   char *str = nifti_image_to_ascii( nim ) ;
+   /* stdout -> stderr   2 Dec 2004 [rickr] */
+   if( str != NULL ){ fputs(str,stderr) ; free(str) ; }
+   return ;
+}
+
+
+/*--------------------------------------------------------------------------
+ * nifti_write_buffer just check for a null znzFile and call znzwrite
+ *--------------------------------------------------------------------------*/
+/*! \fn size_t nifti_write_buffer(znzFile fp, void *buffer, size_t numbytes)
+    \brief write numbytes of buffer to file, fp
+
+    \param fp           File pointer (from znzopen) to gzippable nifti datafile
+    \param buffer       data buffer to be written
+    \param numbytes     number of bytes in buffer to write
+    \return number of bytes successfully written
+*/
+size_t nifti_write_buffer(znzFile fp, const void *buffer, size_t numbytes)
+{
+   /* Write all the image data at once (no swapping here) */
+   size_t ss;
+   if (znz_isnull(fp)){
+      fprintf(stderr,"** ERROR: nifti_write_buffer: null file pointer\n");
+      return 0;
+   }
+   ss = znzwrite( (void*)buffer , 1 , numbytes , fp ) ;
+   return ss;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! write the nifti_image data to file (from nim->data or from NBL)
+
+   If NBL is not NULL, write the data from that structure.  Otherwise,
+   write it out from nim->data.  No swapping is done here.
+
+   \param  fp  : File pointer
+   \param  nim : nifti_image corresponding to the data
+   \param  NBL : optional source of write data (if NULL use nim->data)
+  
+   \return 0 on success, -1 on failure
+
+   Note: the nifti_image byte_order is set as that of the current CPU.
+         This is because such a conversion was made to the data upon
+         reading, while byte_order was not set (so the programs would
+         know what format the data was on disk).  Effectively, since
+         byte_order should match what is on disk, it should bet set to
+         that of the current CPU whenever new filenames are assigned.
+*//*--------------------------------------------------------------------*/
+int nifti_write_all_data(znzFile fp, nifti_image * nim,
+                         const nifti_brick_list * NBL)
+{
+   size_t ss;
+   int    bnum;
+
+   if( !NBL ){ /* just write one buffer and get out of here */
+      if( nim->data == NULL ){
+         fprintf(stderr,"** NWAD: no image data to write\n");
+         return -1;
+      }
+
+      ss = nifti_write_buffer(fp,nim->data,nim->nbyper * nim->nvox);
+      if (ss < (size_t)(nim->nbyper * nim->nvox)){
+         fprintf(stderr,
+            "** ERROR: NWAD: wrote only %d of %d bytes to file\n",
+            (int)ss, nim->nbyper * nim->nvox);
+         return -1;
+      }
+
+      if( g_opts.debug > 1 )
+         fprintf(stderr,"+d wrote single image of %d bytes\n",(int)ss);
+   } else {
+      if( ! NBL->bricks || NBL->nbricks <= 0 || NBL->bsize <= 0 ){
+         fprintf(stderr,"** NWAD: no brick data to write (%p,%d,%d)\n",
+                 (void *)NBL->bricks, NBL->nbricks, NBL->bsize);
+         return -1;
+      }
+
+      for( bnum = 0; bnum < NBL->nbricks; bnum++ ){
+         ss = nifti_write_buffer(fp, NBL->bricks[bnum], NBL->bsize);
+         if( ss < (size_t)NBL->bsize ){
+            fprintf(stderr,
+               "** NWAD ERROR: wrote %d of %d bytes of brick %d of %d to file",
+               (int)ss, NBL->bsize, bnum+1, NBL->nbricks);
+            return -1;
+         }
+      }
+      if( g_opts.debug > 1 )
+         fprintf(stderr,"+d wrote image of %d brick(s), each of %d bytes\n",
+                 NBL->nbricks, NBL->bsize);
+   }
+
+   /* mark as being in this CPU byte order */
+   nim->byteorder = nifti_short_order() ;
+
+   return 0;
+}
+
+/* return number of extensions written, or -1 on error */
+static int nifti_write_extensions(znzFile fp, nifti_image *nim)
+{
+   nifti1_extension * list;
+   char               extdr[4] = { 0, 0, 0, 0 };
+   int                c, size, ok = 1;
+
+   if( znz_isnull(fp) || !nim || nim->num_ext < 0 ){
+      if( g_opts.debug > 0 )
+         fprintf(stderr,"** nifti_write_extensions, bad params\n");
+      return -1;
+   }
+
+   /* if no extensions and user requests it, skip extender */
+   if( g_opts.skip_blank_ext && (nim->num_ext == 0 || ! nim->ext_list ) ){
+      if( g_opts.debug > 1 )
+         fprintf(stderr,"-d no exts and skip_blank_ext set, "
+                        "so skipping 4-byte extender\n");
+      return 0;
+   }
+
+   /* if invalid extension list, clear num_ext */
+   if( ! valid_nifti_extensions(nim) ) nim->num_ext = 0;
+
+   /* write out extender block */
+   if( nim->num_ext > 0 ) extdr[0] = 1;
+   if( nifti_write_buffer(fp, extdr, 4) != 4 ){
+      fprintf(stderr,"** failed to write extender\n");
+      return -1;
+   }
+
+   list = nim->ext_list;
+   for ( c = 0; c < nim->num_ext; c++ ){
+      size = nifti_write_buffer(fp, &list->esize, sizeof(int));
+      ok = (size == (int)sizeof(int));
+      if( ok ){
+         size = nifti_write_buffer(fp, &list->ecode, sizeof(int));
+         ok = (size == (int)sizeof(int));
+      }
+      if( ok ){
+         size = nifti_write_buffer(fp, list->edata, list->esize - 8);
+         ok = (size == list->esize - 8);
+      }
+
+      if( !ok ){
+         fprintf(stderr,"** failed while writing extension #%d\n",c);
+         return -1;
+      }
+
+      list++;
+   }
+
+   if( g_opts.debug > 1 )
+      fprintf(stderr,"+d wrote out %d extension(s)\n", nim->num_ext);
+
+   return nim->num_ext;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! basic initialization of a nifti_image struct (to a 1x1x1 image)
+*//*--------------------------------------------------------------------*/
+nifti_image* nifti_simple_init_nim(void)
+{
+  nifti_image *nim;
+  struct nifti_1_header nhdr;
+  int nbyper, swapsize;
+  
+   memset(&nhdr,0,sizeof(nhdr)) ;  /* zero out header, to be safe */
+  
+   nhdr.sizeof_hdr = sizeof(nhdr) ;
+   nhdr.regular    = 'r' ;           /* for some stupid reason */
+
+   nhdr.dim[0] = 3 ;
+   nhdr.dim[1] = 1 ; nhdr.dim[2] = 1 ; nhdr.dim[3] = 1 ;
+   nhdr.dim[4] = 0 ;
+
+   nhdr.pixdim[0] = 0.0 ;
+   nhdr.pixdim[1] = 1.0 ; nhdr.pixdim[2] = 1.0 ;
+   nhdr.pixdim[3] = 1.0 ;
+
+   nhdr.datatype = DT_FLOAT32 ;
+   nifti_datatype_sizes( nhdr.datatype , &nbyper, &swapsize );
+   nhdr.bitpix   = 8 * nbyper ;
+
+   nim = nifti_convert_nhdr2nim(nhdr,NULL);
+   nim->fname = NULL;
+   nim->iname = NULL;
+   return nim;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! convert a nifti_image structure to a nifti_1_header struct
+
+    No allocation is done, this should be used via structure copy.
+    As in:
+    <pre>
+    nifti_1_header my_header;
+    my_header = nifti_convert_nim2nhdr(my_nim_pointer);
+    </pre>
+*//*--------------------------------------------------------------------*/
+struct nifti_1_header nifti_convert_nim2nhdr(const nifti_image * nim)
+{
+   struct nifti_1_header nhdr;
+
+   memset(&nhdr,0,sizeof(nhdr)) ;  /* zero out header, to be safe */
+
+
+   /**- load the ANALYZE-7.5 generic parts of the header struct */
+
+   nhdr.sizeof_hdr = sizeof(nhdr) ;
+   nhdr.regular    = 'r' ;             /* for some stupid reason */
+
+   nhdr.dim[0] = nim->ndim ;
+   nhdr.dim[1] = nim->nx ; nhdr.dim[2] = nim->ny ; nhdr.dim[3] = nim->nz ;
+   nhdr.dim[4] = nim->nt ; nhdr.dim[5] = nim->nu ; nhdr.dim[6] = nim->nv ;
+   nhdr.dim[7] = nim->nw ;
+
+   nhdr.pixdim[0] = 0.0 ;
+   nhdr.pixdim[1] = nim->dx ; nhdr.pixdim[2] = nim->dy ;
+   nhdr.pixdim[3] = nim->dz ; nhdr.pixdim[4] = nim->dt ;
+   nhdr.pixdim[5] = nim->du ; nhdr.pixdim[6] = nim->dv ;
+   nhdr.pixdim[7] = nim->dw ;
+
+   nhdr.datatype = nim->datatype ;
+   nhdr.bitpix   = 8 * nim->nbyper ;
+
+   if( nim->cal_max > nim->cal_min ){
+     nhdr.cal_max = nim->cal_max ;
+     nhdr.cal_min = nim->cal_min ;
+   }
+
+   if( nim->scl_slope != 0.0 ){
+     nhdr.scl_slope = nim->scl_slope ;
+     nhdr.scl_inter = nim->scl_inter ;
+   }
+
+   if( nim->descrip[0] != '\0' ){
+     memcpy(nhdr.descrip ,nim->descrip ,79) ; nhdr.descrip[79] = '\0' ;
+   }
+   if( nim->aux_file[0] != '\0' ){
+     memcpy(nhdr.aux_file ,nim->aux_file ,23) ; nhdr.aux_file[23] = '\0' ;
+   }
+
+   /**- Load NIFTI specific stuff into the header */
+
+   if( nim->nifti_type > NIFTI_FTYPE_ANALYZE ){ /* then not ANALYZE */
+
+     if( nim->nifti_type == NIFTI_FTYPE_NIFTI1_1 ) strcpy(nhdr.magic,"n+1") ;
+     else                                          strcpy(nhdr.magic,"ni1") ;
+
+     nhdr.pixdim[1] = fabs(nhdr.pixdim[1]) ; nhdr.pixdim[2] = fabs(nhdr.pixdim[2]) ;
+     nhdr.pixdim[3] = fabs(nhdr.pixdim[3]) ; nhdr.pixdim[4] = fabs(nhdr.pixdim[4]) ;
+     nhdr.pixdim[5] = fabs(nhdr.pixdim[5]) ; nhdr.pixdim[6] = fabs(nhdr.pixdim[6]) ;
+     nhdr.pixdim[7] = fabs(nhdr.pixdim[7]) ;
+
+     nhdr.intent_code = nim->intent_code ;
+     nhdr.intent_p1   = nim->intent_p1 ;
+     nhdr.intent_p2   = nim->intent_p2 ;
+     nhdr.intent_p3   = nim->intent_p3 ;
+     if( nim->intent_name[0] != '\0' ){
+       memcpy(nhdr.intent_name,nim->intent_name,15) ;
+       nhdr.intent_name[15] = '\0' ;
+     }
+
+     nhdr.vox_offset  = (float) nim->iname_offset ;
+     nhdr.xyzt_units  = SPACE_TIME_TO_XYZT( nim->xyz_units, nim->time_units ) ;
+     nhdr.toffset     = nim->toffset ;
+
+     if( nim->qform_code > 0 ){
+       nhdr.qform_code = nim->qform_code ;
+       nhdr.quatern_b  = nim->quatern_b ;
+       nhdr.quatern_c  = nim->quatern_c ;
+       nhdr.quatern_d  = nim->quatern_d ;
+       nhdr.qoffset_x  = nim->qoffset_x ;
+       nhdr.qoffset_y  = nim->qoffset_y ;
+       nhdr.qoffset_z  = nim->qoffset_z ;
+       nhdr.pixdim[0]  = (nim->qfac >= 0.0) ? 1.0 : -1.0 ;
+     }
+
+     if( nim->sform_code > 0 ){
+       nhdr.sform_code = nim->sform_code ;
+       nhdr.srow_x[0]  = nim->sto_xyz.m[0][0] ;
+       nhdr.srow_x[1]  = nim->sto_xyz.m[0][1] ;
+       nhdr.srow_x[2]  = nim->sto_xyz.m[0][2] ;
+       nhdr.srow_x[3]  = nim->sto_xyz.m[0][3] ;
+       nhdr.srow_y[0]  = nim->sto_xyz.m[1][0] ;
+       nhdr.srow_y[1]  = nim->sto_xyz.m[1][1] ;
+       nhdr.srow_y[2]  = nim->sto_xyz.m[1][2] ;
+       nhdr.srow_y[3]  = nim->sto_xyz.m[1][3] ;
+       nhdr.srow_z[0]  = nim->sto_xyz.m[2][0] ;
+       nhdr.srow_z[1]  = nim->sto_xyz.m[2][1] ;
+       nhdr.srow_z[2]  = nim->sto_xyz.m[2][2] ;
+       nhdr.srow_z[3]  = nim->sto_xyz.m[2][3] ;
+     }
+
+     nhdr.dim_info = FPS_INTO_DIM_INFO( nim->freq_dim ,
+                                        nim->phase_dim , nim->slice_dim ) ;
+     nhdr.slice_code     = nim->slice_code ;
+     nhdr.slice_start    = nim->slice_start ;
+     nhdr.slice_end      = nim->slice_end ;
+     nhdr.slice_duration = nim->slice_duration ;
+   }
+
+   return nhdr;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! \fn int nifti_copy_extensions(nifti_image * nim_dest, nifti_image * nim_src)
+    \brief copy the nifti1_extension list from src to dest
+
+    Duplicate the list of nifti1_extensions.  The dest structure must
+    be clear of extensions.
+    \return 0 on success, -1 on failure
+
+    \sa nifti_add_extension, nifti_free_extensions
+*/
+int nifti_copy_extensions(nifti_image * nim_dest, const nifti_image * nim_src)
+{
+   char   * data;
+   size_t   bytes;
+   int      c, size, old_size;
+
+   if( nim_dest->num_ext > 0 || nim_dest->ext_list != NULL ){
+      fprintf(stderr,"** will not copy extensions over existing ones\n");
+      return -1;
+   }
+
+   if( g_opts.debug > 1 )
+      fprintf(stderr,"+d duplicating %d extension(s)\n", nim_src->num_ext);
+
+   if( nim_src->num_ext <= 0 ) return 0;
+
+   bytes = nim_src->num_ext * sizeof(nifti1_extension);  /* I'm lazy */
+   nim_dest->ext_list = (nifti1_extension *)malloc(bytes);
+   if( !nim_dest->ext_list ){
+      fprintf(stderr,"** failed to allocate %d nifti1_extension structs\n",
+              nim_src->num_ext);
+      return -1;
+   }
+
+   /* copy the extension data */
+   nim_dest->num_ext = 0;
+   for( c = 0; c < nim_src->num_ext; c++ ){
+      size = old_size = nim_src->ext_list[c].esize;
+      if( size & 0xf ) size = (size + 0xf) & ~0xf; /* make multiple of 16 */
+      if( g_opts.debug > 2 )
+         fprintf(stderr,"+d dup'ing ext #%d of size %d (from size %d)\n",
+                 c, size, old_size);
+      data = (char *)calloc(size,sizeof(char));  /* calloc, maybe size > old */
+      if( !data ){
+         fprintf(stderr,"** failed to alloc %d bytes for extention\n", size);
+         if( c == 0 ) { free(nim_dest->ext_list); nim_dest->ext_list = NULL; }
+         /* otherwise, keep what we have (a.o.t. deleting them all) */
+         return -1;
+      }
+      /* finally, fill the new structure */
+      nim_dest->ext_list[c].esize = size;
+      nim_dest->ext_list[c].ecode = nim_src->ext_list[c].ecode;
+      nim_dest->ext_list[c].edata = data;
+      memcpy(data, nim_src->ext_list[c].edata, old_size);
+
+      nim_dest->num_ext++;
+   }
+
+   return 0;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! compute the total size of all extensions
+
+    \return the total of all esize fields
+
+    Note that each esize includes 4 bytes for ecode, 4 bytes for esize,
+    and the bytes used for the data.  Each esize also needs to be a
+    multiple of 16, so it may be greater than the sum of its 3 parts.
+*//*--------------------------------------------------------------------*/
+int nifti_extension_size(nifti_image *nim)
+{
+   int c, size = 0;
+
+   if( !nim || nim->num_ext <= 0 ) return 0;
+
+   if( g_opts.debug > 2 ) fprintf(stderr,"-d ext sizes:");
+
+   for ( c = 0; c < nim->num_ext; c++ ){
+      size += nim->ext_list[c].esize;
+      if( g_opts.debug > 2 ) fprintf(stderr,"  %d",nim->ext_list[c].esize);
+   }
+
+   if( g_opts.debug > 2 ) fprintf(stderr," (total = %d)\n",size);
+
+   return size;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! set the nifti_image iname_offset field, based on nifti_type
+
+    - if writing to 2 files, set offset to 0
+    - if writing to a single NIFTI-1 file, set the offset to
+         352 + total extension size, then align to 16-byte boundary
+    - if writing an ASCII header, set offset to -1
+*//*--------------------------------------------------------------------*/
+void nifti_set_iname_offset(nifti_image *nim)
+{
+   int offset;
+
+   switch( nim->nifti_type ){
+
+     default:  /* writing into 2 files */
+       /* we only write files with 0 offset in the 2 file format */
+       nim->iname_offset = 0 ;
+     break ;
+
+     /* NIFTI-1 single binary file - always update */
+     case NIFTI_FTYPE_NIFTI1_1:
+       offset = nifti_extension_size(nim)+sizeof(struct nifti_1_header)+4;
+       /* be sure offset is aligned to a 16 byte boundary */
+       if ( ( offset % 16 ) != 0 )  offset = ((offset + 0xf) & ~0xf);
+       if( nim->iname_offset != offset ){
+          if( g_opts.debug > 1 )
+             fprintf(stderr,"+d changing offset from %d to %d\n",
+                  nim->iname_offset, offset);
+          nim->iname_offset = offset;
+       }
+     break ;
+
+     /* non-standard case: NIFTI-1 ASCII header + binary data (single file) */
+     case NIFTI_FTYPE_ASCII:
+       nim->iname_offset = -1 ;             /* compute offset from filesize */
+     break ;
+   }
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! write the nifti_image dataset to disk, optionally including data
+
+   This is just a front-end for nifti_image_write_hdr_img2.
+
+   \param nim        nifti_image to write to disk
+   \param write_data write options (see nifti_image_write_hdr_img2)
+   \param opts       file open options ("wb" from nifti_image_write)
+
+   \sa nifti_image_write, nifti_image_write_hdr_img2, nifti_image_free,
+       nifti_set_filenames
+*//*--------------------------------------------------------------------*/
+znzFile nifti_image_write_hdr_img( nifti_image *nim , int write_data , 
+                                          const char* opts )
+{
+  return nifti_image_write_hdr_img2(nim,write_data,opts,NULL,NULL);
+}
+
+
+#undef  ERREX
+#define ERREX(msg)                                                \
+ do{ fprintf(stderr,"** ERROR: nifti_image_write_hdr_img: %s\n",(msg)) ;  \
+     return fp ; } while(0)
+
+
+/* ----------------------------------------------------------------------*/
+/*! This writes the header (and optionally the image data) to file
+ *
+ * If the image data file is left open it returns a valid znzFile handle.
+ * It also uses imgfile as the open image file is not null, and modifies
+ * it inside.
+ * 
+ * \param nim        nifti_image to write to disk
+ * \param write_opts flags whether to write data and/or close file (see below)
+ * \param opts       file-open options, probably "wb" from nifti_image_write()
+ * \param imgfile    optional open znzFile struct, for writing image data
+                     (may be NULL)
+ * \param NBL        optional nifti_brick_list, containing the image data
+                     (may be NULL)
+ * 
+ * Values for write_opts mode are based on two binary flags
+ * ( 0/1 for no-write/write data, and 0/2 for close/leave-open files ) :
+ *    -   0 = do not write data and close (do not open data file)
+ *    -   1 = write data        and close
+ *    -   2 = do not write data and leave data file open 
+ *    -   3 = write data        and leave data file open 
+ *
+ * \sa nifti_image_write, nifti_image_write_hdr_img, nifti_image_free,
+ *     nifti_set_filenames
+*//*---------------------------------------------------------------------*/
+znzFile nifti_image_write_hdr_img2(nifti_image *nim, int write_opts, 
+               const char * opts, znzFile imgfile, const nifti_brick_list * NBL)
+{
+   struct nifti_1_header nhdr ;
+   znzFile               fp=NULL;
+   size_t                ss ;
+   int                   write_data, leave_open;
+   char                  func[] = { "nifti_image_write_hdr_img2" };
+
+   write_data = write_opts & 1;  /* just separate the bits now */
+   leave_open = write_opts & 2;
+
+   if( ! nim                              ) ERREX("NULL input") ;
+   if( ! nifti_validfilename(nim->fname)  ) ERREX("bad fname input") ;
+   if( write_data && ! nim->data && ! NBL ) ERREX("no image data") ;
+
+   nifti_set_iname_offset(nim);
+
+   if( g_opts.debug > 1 ){
+      fprintf(stderr,"-d writing nifti file '%s'...\n", nim->fname);
+      if( g_opts.debug > 2 )
+         fprintf(stderr,"-d nifti type %d, offset %d\n",
+                 nim->nifti_type, nim->iname_offset);
+   }
+
+   if( nim->nifti_type == NIFTI_FTYPE_ASCII )   /* non-standard case */
+      return nifti_write_ascii_image(nim,NBL,opts,write_data,leave_open);
+
+   nhdr = nifti_convert_nim2nhdr(nim);    /* create the nifti1_header struct */
+
+   /* if writing to 2 files, make sure iname is set and different from fname */
+   if( nim->nifti_type != NIFTI_FTYPE_NIFTI1_1 ){
+       if( nim->iname && strcmp(nim->iname,nim->fname) == 0 ){
+         free(nim->iname) ; nim->iname = NULL ;
+       }
+       if( nim->iname == NULL ){ /* then make a new one */
+         nim->iname = nifti_makeimgname(nim->fname,nim->nifti_type,0,0);
+         if( nim->iname == NULL ) return NULL;  
+       }
+   }
+
+   /* if we have an imgfile and will write the header there, use it */
+   if( ! znz_isnull(imgfile) && nim->nifti_type == NIFTI_FTYPE_NIFTI1_1 ){
+      if( g_opts.debug > 2 ) fprintf(stderr,"+d using passed file for hdr\n");
+      fp = imgfile;
+   }
+   else {
+      if( g_opts.debug > 2 )
+         fprintf(stderr,"+d opening output file '%s'\n",nim->fname);
+      fp = znzopen( nim->fname , opts , nifti_is_gzfile(nim->fname) ) ;
+      if( znz_isnull(fp) ){
+         LNI_FERR(func,"cannot open output file",nim->fname);
+         return fp;
+      }
+   }
+
+   /* write the header and extensions */
+
+   ss = znzwrite(&nhdr , 1 , sizeof(nhdr) , fp); /* write header */
+   if( ss < sizeof(nhdr) ){
+      LNI_FERR(func,"bad header write to output file",nim->fname);
+      znzclose(fp); return fp;
+   }
+
+   /* partial file exists, and errors have been printed, so ignore return */
+   if( nim->nifti_type != NIFTI_FTYPE_ANALYZE )
+      (void)nifti_write_extensions(fp,nim);
+
+   /* if the header is all we want, we are done */
+   if( ! write_data && ! leave_open ){
+      if( g_opts.debug > 2 ) fprintf(stderr,"-d header is all we want: done\n");
+      znzclose(fp); return(fp);
+   }
+
+   if( nim->nifti_type != NIFTI_FTYPE_NIFTI1_1 ){ /* get a new file pointer */
+      znzclose(fp);         /* first, close header file */
+      if( ! znz_isnull(imgfile) ){
+         if(g_opts.debug > 2) fprintf(stderr,"+d using passed file for img\n");
+         fp = imgfile;
+      }
+      else {
+         if( g_opts.debug > 2 )
+            fprintf(stderr,"+d opening img file '%s'\n", nim->iname);
+         fp = znzopen( nim->iname , opts , nifti_is_gzfile(nim->iname) ) ;
+         if( znz_isnull(fp) ) ERREX("cannot open image file") ;
+      }
+   }
+
+   znzseek(fp, nim->iname_offset, SEEK_SET);  /* in any case, seek to offset */
+
+   if( write_data ) nifti_write_all_data(fp,nim,NBL);
+   if( ! leave_open ) znzclose(fp);
+
+   return fp;
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! write a nifti_image to disk in ASCII format
+*//*--------------------------------------------------------------------*/
+znzFile nifti_write_ascii_image(nifti_image *nim, const nifti_brick_list * NBL,
+                              const char *opts, int write_data, int leave_open)
+{
+   znzFile   fp;
+   char    * hstr;
+                                                                                
+   hstr = nifti_image_to_ascii( nim ) ;  /* get header in ASCII form */
+   if( ! hstr ){ fprintf(stderr,"** failed image_to_ascii()\n"); return NULL; }
+                                                                                
+   fp = znzopen( nim->fname , opts , nifti_is_gzfile(nim->fname) ) ;
+   if( znz_isnull(fp) ){
+      free(hstr);
+      fprintf(stderr,"** failed to open '%s' for ascii write\n",nim->fname);
+      return fp;
+   }
+                                                                                
+   znzputs(hstr,fp);                                               /* header */
+   nifti_write_extensions(fp,nim);                             /* extensions */
+                                                                                
+   if ( write_data   ) { nifti_write_all_data(fp,nim,NBL); }         /* data */
+   if ( ! leave_open ) { znzclose(fp); }
+   free(hstr);
+   return fp;  /* returned but may be closed */
+}
+
+
+/*--------------------------------------------------------------------------*/
+/*! Write a nifti_image to disk.
+
+   Since data is properly byte-swapped upon reading, it is assumed
+   to be in the byte-order of the current CPU at write time.  Thus,
+   nim->byte_order should match that of the current CPU.  Note that
+   the nifti_set_filenames() function takes the flag, set_byte_order.
+
+   The following fields of nim affect how the output appears:
+    - nifti_type = 0 ==> ANALYZE-7.5 format file pair will be written
+    - nifti_type = 1 ==> NIFTI-1 format single file will be written
+                         (data offset will be 352+extensions)
+    - nifti_type = 2 ==> NIFTI_1 format file pair will be written
+    - nifti_type = 3 ==> NIFTI_1 ASCII single file will be written
+    - fname is the name of the output file (header or header+data)
+    - if a file pair is being written, iname is the name of the data file
+    - existing files WILL be overwritten with extreme prejudice
+    - if qform_code > 0, the quatern_*, qoffset_*, and qfac fields determine
+      the qform output, NOT the qto_xyz matrix; if you want to compute these
+      fields from the qto_xyz matrix, you can use the utility function
+      nifti_mat44_to_quatern()
+
+   \sa nifti_image_write_bricks, nifti_image_free, nifti_set_filenames,
+       nifti_image_write_hdr_img
+*//*------------------------------------------------------------------------*/
+void nifti_image_write( nifti_image *nim )
+{
+   znzFile fp = nifti_image_write_hdr_img(nim,1,"wb");
+   if( fp ){
+      if( g_opts.debug > 2 ) fprintf(stderr,"-d niw: done with znzFile\n");
+      free(fp);
+   }
+   if( g_opts.debug > 1 ) fprintf(stderr,"-d nifti_image_write: done\n");
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! similar to nifti_image_write, but data is in NBL struct, not nim->data
+
+   \sa nifti_image_write, nifti_image_free, nifti_set_filenames, nifti_free_NBL
+*//*--------------------------------------------------------------------*/
+void nifti_image_write_bricks( nifti_image *nim, const nifti_brick_list * NBL )
+{
+   znzFile fp = nifti_image_write_hdr_img2(nim,1,"wb",NULL,NBL);
+   if( fp ){
+      if( g_opts.debug > 2 ) fprintf(stderr,"-d niwb: done with znzFile\n");
+      free(fp);
+   }
+   if( g_opts.debug > 1 ) fprintf(stderr,"-d niwb: done writing bricks\n");
+}
+
+
+/*----------------------------------------------------------------------*/
+/*! copy the nifti_image structure, without data
+
+    Duplicate the structure, including fname, iname and extensions.
+    Leave the data pointer as NULL.
+*//*--------------------------------------------------------------------*/
+nifti_image * nifti_copy_nim_info(const nifti_image * src)
+{
+  nifti_image *dest;
+  dest = (nifti_image *)calloc(1,sizeof(nifti_image));
+  if( !dest ){
+     fprintf(stderr,"** NCNI: failed to alloc nifti_image\n");
+     return NULL;
+  }
+  memcpy(dest, src, sizeof(nifti_image));
+  if( src->fname ) dest->fname = nifti_strdup(src->fname);
+  if( src->iname ) dest->iname = nifti_strdup(src->iname);
+  dest->num_ext = 0;
+  dest->ext_list = NULL;
+  /* errors will be printed in NCE(), continue in either case */
+  (void)nifti_copy_extensions(dest, src);
+
+  dest->data = NULL;
+
+  return dest;
+}
+
+
+/*------------------------------------------------------------------------*/
+/* Un-escape a C string in place -- that is, convert XML escape sequences
+   back into their characters.  (This can be done in place since the
+   replacement is always smaller than the input.)  Escapes recognized are:
+     -  <   ->  <
+     -  >   ->  >
+     -  " ->  "
+     -  ' ->  '
+     -  &  ->  &
+   Also replace CR LF pair (Microsoft), or CR alone (Macintosh) with
+   LF (Unix), per the XML standard.
+   Return value is number of replacements made (if you care).
+--------------------------------------------------------------------------*/
+
+#undef  CR
+#undef  LF
+#define CR 0x0D
+#define LF 0x0A
+
+static int unescape_string( char *str )
+{
+   int ii,jj , nn,ll ;
+
+   if( str == NULL ) return 0 ;                /* no string? */
+   ll = strlen(str) ; if( ll == 0 ) return 0 ;
+
+   /* scan for escapes: &something; */
+
+   for( ii=jj=nn=0 ; ii<ll ; ii++,jj++ ){ /* scan at ii; results go in at jj */
+
+     if( str[ii] == '&' ){  /* start of escape? */
+
+             if( ii+3 < ll        &&   /* < */
+                 str[ii+1] == 'l' &&
+                 str[ii+2] == 't' &&
+                 str[ii+3] == ';'   ){ str[jj] = '<' ; ii += 3 ; nn++ ; }
+
+        else if( ii+3 < ll        &&   /* > */
+                 str[ii+1] == 'g' &&
+                 str[ii+2] == 't' &&
+                 str[ii+3] == ';'   ){ str[jj] = '>' ; ii += 3 ; nn++ ; }
+
+        else if( ii+5 < ll        &&   /* " */
+                 str[ii+1] == 'q' &&
+                 str[ii+2] == 'u' &&
+                 str[ii+3] == 'o' &&
+                 str[ii+4] == 't' &&
+                 str[ii+5] == ';'   ){ str[jj] = '"' ; ii += 5 ; nn++ ; }
+
+        else if( ii+5 < ll        &&   /* ' */
+                 str[ii+1] == 'a' &&
+                 str[ii+2] == 'p' &&
+                 str[ii+3] == 'o' &&
+                 str[ii+4] == 's' &&
+                 str[ii+5] == ';'   ){ str[jj] = '\'' ; ii += 5 ; nn++ ; }
+
+        else if( ii+4 < ll        &&  /* & */
+                 str[ii+1] == 'a' &&
+                 str[ii+2] == 'm' &&
+                 str[ii+3] == 'p' &&
+                 str[ii+4] == ';'   ){ str[jj] = '&' ; ii += 4 ; nn++ ; }
+
+        /* although the comments above don't mention it,
+           we also look for XML style numeric escapes
+           of the forms   (decimal) and &#xfd; (hex) */
+
+        else if( ii+3 < ll        &&
+                 str[ii+1] == '#' &&
+                 isdigit(str[ii+2]) ){   /* &#dec; */
+
+           unsigned int val='?' ; int kk=ii+3 ;
+           while( kk < ll && kk != ';' ) kk++ ;
+           sscanf( str+ii+2 , "%u" , &val ) ;
+           str[jj] = (char) val ; ii = kk ; nn++ ;
+        }
+
+        else if( ii+4 < ll        &&
+                 str[ii+1] == '#' &&
+                 str[ii+2] == 'x' &&
+                 isxdigit(str[ii+3]) ){   /* &#hex; */
+
+           unsigned int val='?' ; int kk=ii+4 ;
+           while( kk < ll && kk != ';' ) kk++ ;
+           sscanf( str+ii+3 , "%x" , &val ) ;
+           str[jj] = (char) val ; ii = kk ; nn++ ;
+        }
+
+        /* didn't start a recognized escape, so just copy as normal */
+
+        else if( jj < ii ){ str[jj] = str[ii] ; }
+
+     } else if( str[ii] == CR ) {  /* is a carriage return */
+
+        if( str[ii+1] == LF ){ str[jj] = LF ; ii++ ; nn++ ; }  /* CR LF */
+        else                 { str[jj] = LF ;      ; nn++ ; }  /* CR only */
+
+     } else { /* is a normal character, just copy to output */
+
+             if( jj < ii ){ str[jj] = str[ii] ; }
+     }
+
+     /* at this point, ii=index of last character used up in scan
+                       jj=index of last character written to (jj <= ii) */
+   }
+
+   if( jj < ll ) str[jj] = '\0' ; /* end string properly */
+
+   return nn ;
+}
+
+/*------------------------------------------------------------------------*/
+/* Quotize (and escapize) one string, returning a new string.
+   Approximately speaking, this is the inverse of unescape_string().
+   The result should be free()-ed when you are done with it.
+--------------------------------------------------------------------------*/
+
+static char *escapize_string( const char * str )
+{
+   int ii,jj , lstr,lout ;
+   char *out ;
+
+   if( str == NULL || (lstr=strlen(str)) == 0 ){      /* 0 length */
+     out = nifti_strdup("''") ; return out ;                /* string?? */
+   }
+
+   lout = 4 ;                      /* initialize length of output */
+   for( ii=0 ; ii < lstr ; ii++ ){ /* count characters for output */
+     switch( str[ii] ){
+       case '&':  lout += 5 ; break ;  /* replace '&' with "&" */
+
+       case '<':
+       case '>':  lout += 4 ; break ;  /* replace '<' with "<" */
+
+       case '"' :
+       case '\'': lout += 6 ; break ;  /* replace '"' with """ */
+
+       case CR:
+       case LF:   lout += 6 ; break ;  /* replace CR with "&#x0d;"
+                                                  LF with "&#x0a;" */
+
+       default: lout++ ; break ;      /* copy all other chars */
+     }
+   }
+   out = (char *)calloc(1,lout) ;     /* allocate output string */
+   if( !out ){
+      fprintf(stderr,"** escapize_string: failed to alloc %d bytes\n",lout);
+      return NULL;
+   }
+   out[0] = '\'' ;                    /* opening quote mark */
+   for( ii=0,jj=1 ; ii < lstr ; ii++ ){
+      switch( str[ii] ){
+         default: out[jj++] = str[ii] ; break ;  /* normal characters */
+
+         case '&':  memcpy(out+jj,"&",5)  ; jj+=5 ; break ;
+
+         case '<':  memcpy(out+jj,"<",4)   ; jj+=4 ; break ;
+         case '>':  memcpy(out+jj,">",4)   ; jj+=4 ; break ;
+
+         case '"' : memcpy(out+jj,""",6) ; jj+=6 ; break ;
+
+         case '\'': memcpy(out+jj,"'",6) ; jj+=6 ; break ;
+
+         case CR:   memcpy(out+jj,"&#x0d;",6) ; jj+=6 ; break ;
+         case LF:   memcpy(out+jj,"&#x0a;",6) ; jj+=6 ; break ;
+      }
+   }
+   out[jj++] = '\''  ;  /* closing quote mark */
+   out[jj]   = '\0' ;  /* terminate the string */
+   return out ;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! Dump the information in a NIFTI image header to an XML-ish ASCII string
+   that can later be converted back into a NIFTI header in
+   nifti_image_from_ascii().
+
+   The resulting string can be free()-ed when you are done with it.
+*//*-------------------------------------------------------------------------*/
+char *nifti_image_to_ascii( const nifti_image *nim )
+{
+   char *buf , *ebuf ; int nbuf ;
+
+   if( nim == NULL ) return NULL ;   /* stupid caller */
+
+   buf = (char *)calloc(1,65534); nbuf = 0; /* longer than needed, to be safe */
+   if( !buf ){
+      fprintf(stderr,"** NITA: failed to alloc %d bytes\n",65534);
+      return NULL;
+   }
+
+   sprintf( buf , "<nifti_image\n" ) ;   /* XML-ish opener */
+
+   sprintf( buf+strlen(buf) , "  nifti_type = '%s'\n" ,
+              (nim->nifti_type == NIFTI_FTYPE_NIFTI1_1) ? "NIFTI-1+"
+             :(nim->nifti_type == NIFTI_FTYPE_NIFTI1_2) ? "NIFTI-1"
+             :(nim->nifti_type == NIFTI_FTYPE_ASCII   ) ? "NIFTI-1A"
+             :                         "ANALYZE-7.5" ) ;
+
+   /** Strings that we don't control (filenames, etc.) that might
+       contain "weird" characters (like quotes) are "escaped":
+       - A few special characters are replaced by XML-style escapes, using
+         the function escapize_string().
+       - On input, function unescape_string() reverses this process.
+       - The result is that the NIFTI ASCII-format header is XML-compliant. */
+
+   ebuf = escapize_string(nim->fname) ;
+   sprintf( buf+strlen(buf) , "  header_filename = %s\n",ebuf); free(ebuf);
+
+   ebuf = escapize_string(nim->iname) ;
+   sprintf( buf+strlen(buf) , "  image_filename = %s\n", ebuf); free(ebuf);
+
+   sprintf( buf+strlen(buf) , "  image_offset = '%d'\n" , nim->iname_offset );
+
+                       sprintf( buf+strlen(buf), "  ndim = '%d'\n", nim->ndim);
+                       sprintf( buf+strlen(buf), "  nx = '%d'\n",   nim->nx  );
+   if( nim->ndim > 1 ) sprintf( buf+strlen(buf), "  ny = '%d'\n",   nim->ny  );
+   if( nim->ndim > 2 ) sprintf( buf+strlen(buf), "  nz = '%d'\n",   nim->nz  );
+   if( nim->ndim > 3 ) sprintf( buf+strlen(buf), "  nt = '%d'\n",   nim->nt  );
+   if( nim->ndim > 4 ) sprintf( buf+strlen(buf), "  nu = '%d'\n",   nim->nu  );
+   if( nim->ndim > 5 ) sprintf( buf+strlen(buf), "  nv = '%d'\n",   nim->nv  );
+   if( nim->ndim > 6 ) sprintf( buf+strlen(buf), "  nw = '%d'\n",   nim->nw  );
+                       sprintf( buf+strlen(buf), "  dx = '%g'\n",   nim->dx  );
+   if( nim->ndim > 1 ) sprintf( buf+strlen(buf), "  dy = '%g'\n",   nim->dy  );
+   if( nim->ndim > 2 ) sprintf( buf+strlen(buf), "  dz = '%g'\n",   nim->dz  );
+   if( nim->ndim > 3 ) sprintf( buf+strlen(buf), "  dt = '%g'\n",   nim->dt  );
+   if( nim->ndim > 4 ) sprintf( buf+strlen(buf), "  du = '%g'\n",   nim->du  );
+   if( nim->ndim > 5 ) sprintf( buf+strlen(buf), "  dv = '%g'\n",   nim->dv  );
+   if( nim->ndim > 6 ) sprintf( buf+strlen(buf), "  dw = '%g'\n",   nim->dw  );
+
+   sprintf( buf+strlen(buf) , "  datatype = '%d'\n" , nim->datatype ) ;
+   sprintf( buf+strlen(buf) , "  datatype_name = '%s'\n" ,
+                              nifti_datatype_string(nim->datatype) ) ;
+
+   sprintf( buf+strlen(buf) , "  nvox = '%d'\n" , nim->nvox ) ;
+   sprintf( buf+strlen(buf) , "  nbyper = '%d'\n" , nim->nbyper ) ;
+
+   sprintf( buf+strlen(buf) , "  byteorder = '%s'\n" ,
+            (nim->byteorder==MSB_FIRST) ? "MSB_FIRST" : "LSB_FIRST" ) ;
+
+   if( nim->cal_min < nim->cal_max ){
+     sprintf( buf+strlen(buf) , "  cal_min = '%g'\n", nim->cal_min ) ;
+     sprintf( buf+strlen(buf) , "  cal_max = '%g'\n", nim->cal_max ) ;
+   }
+
+   if( nim->scl_slope != 0.0 ){
+     sprintf( buf+strlen(buf) , "  scl_slope = '%g'\n" , nim->scl_slope ) ;
+     sprintf( buf+strlen(buf) , "  scl_inter = '%g'\n" , nim->scl_inter ) ;
+   }
+
+   if( nim->intent_code > 0 ){
+     sprintf( buf+strlen(buf) , "  intent_code = '%d'\n", nim->intent_code ) ;
+     sprintf( buf+strlen(buf) , "  intent_code_name = '%s'\n" ,
+                                nifti_intent_string(nim->intent_code) ) ;
+     sprintf( buf+strlen(buf) , "  intent_p1 = '%g'\n" , nim->intent_p1 ) ;
+     sprintf( buf+strlen(buf) , "  intent_p2 = '%g'\n" , nim->intent_p2 ) ;
+     sprintf( buf+strlen(buf) , "  intent_p3 = '%g'\n" , nim->intent_p3 ) ;
+
+     if( nim->intent_name[0] != '\0' ){
+       ebuf = escapize_string(nim->intent_name) ;
+       sprintf( buf+strlen(buf) , "  intent_name = %s\n",ebuf) ;
+       free(ebuf) ;
+     }
+   }
+
+   if( nim->toffset != 0.0 )
+     sprintf( buf+strlen(buf) , "  toffset = '%g'\n",nim->toffset ) ;
+
+   if( nim->xyz_units > 0 )
+     sprintf( buf+strlen(buf) ,
+              "  xyz_units = '%d'\n"
+              "  xyz_units_name = '%s'\n" ,
+              nim->xyz_units , nifti_units_string(nim->xyz_units) ) ;
+
+   if( nim->time_units > 0 )
+     sprintf( buf+strlen(buf) ,
+              "  time_units = '%d'\n"
+              "  time_units_name = '%s'\n" ,
+              nim->time_units , nifti_units_string(nim->time_units) ) ;
+
+   if( nim->freq_dim > 0 )
+     sprintf( buf+strlen(buf) , "  freq_dim = '%d'\n",nim->freq_dim ) ;
+   if( nim->phase_dim > 0 )
+     sprintf( buf+strlen(buf) , "  phase_dim = '%d'\n",nim->phase_dim ) ;
+   if( nim->slice_dim > 0 )
+     sprintf( buf+strlen(buf) , "  slice_dim = '%d'\n",nim->slice_dim ) ;
+   if( nim->slice_code > 0 )
+     sprintf( buf+strlen(buf) ,
+              "  slice_code = '%d'\n"
+              "  slice_code_name = '%s'\n" ,
+              nim->slice_code , nifti_slice_string(nim->slice_code) ) ;
+   if( nim->slice_start >= 0 && nim->slice_end > nim->slice_start )
+     sprintf( buf+strlen(buf) ,
+              "  slice_start = '%d'\n"
+              "  slice_end = '%d'\n"  , nim->slice_start , nim->slice_end ) ;
+   if( nim->slice_duration != 0.0 )
+     sprintf( buf+strlen(buf) , "  slice_duration = '%g'\n",
+              nim->slice_duration ) ;
+
+   if( nim->descrip[0] != '\0' ){
+     ebuf = escapize_string(nim->descrip) ;
+     sprintf( buf+strlen(buf) , "  descrip = %s\n",ebuf) ;
+     free(ebuf) ;
+   }
+
+   if( nim->aux_file[0] != '\0' ){
+     ebuf = escapize_string(nim->aux_file) ;
+     sprintf( buf+strlen(buf) , "  aux_file = %s\n",ebuf) ;
+     free(ebuf) ;
+   }
+
+   if( nim->qform_code > 0 ){
+     int i,j,k ;
+
+     sprintf( buf+strlen(buf) ,
+              "  qform_code = '%d'\n"
+              "  qform_code_name = '%s'\n"
+     "  qto_xyz_matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" ,
+         nim->qform_code      , nifti_xform_string(nim->qform_code) ,
+         nim->qto_xyz.m[0][0] , nim->qto_xyz.m[0][1] ,
+         nim->qto_xyz.m[0][2] , nim->qto_xyz.m[0][3] ,
+         nim->qto_xyz.m[1][0] , nim->qto_xyz.m[1][1] ,
+         nim->qto_xyz.m[1][2] , nim->qto_xyz.m[1][3] ,
+         nim->qto_xyz.m[2][0] , nim->qto_xyz.m[2][1] ,
+         nim->qto_xyz.m[2][2] , nim->qto_xyz.m[2][3] ,
+         nim->qto_xyz.m[3][0] , nim->qto_xyz.m[3][1] ,
+         nim->qto_xyz.m[3][2] , nim->qto_xyz.m[3][3]  ) ;
+
+     sprintf( buf+strlen(buf) ,
+     "  qto_ijk_matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" ,
+         nim->qto_ijk.m[0][0] , nim->qto_ijk.m[0][1] ,
+         nim->qto_ijk.m[0][2] , nim->qto_ijk.m[0][3] ,
+         nim->qto_ijk.m[1][0] , nim->qto_ijk.m[1][1] ,
+         nim->qto_ijk.m[1][2] , nim->qto_ijk.m[1][3] ,
+         nim->qto_ijk.m[2][0] , nim->qto_ijk.m[2][1] ,
+         nim->qto_ijk.m[2][2] , nim->qto_ijk.m[2][3] ,
+         nim->qto_ijk.m[3][0] , nim->qto_ijk.m[3][1] ,
+         nim->qto_ijk.m[3][2] , nim->qto_ijk.m[3][3]  ) ;
+
+     sprintf( buf+strlen(buf) ,
+              "  quatern_b = '%g'\n"
+              "  quatern_c = '%g'\n"
+              "  quatern_d = '%g'\n"
+              "  qoffset_x = '%g'\n"
+              "  qoffset_y = '%g'\n"
+              "  qoffset_z = '%g'\n"
+              "  qfac = '%g'\n" ,
+         nim->quatern_b , nim->quatern_c , nim->quatern_d ,
+         nim->qoffset_x , nim->qoffset_y , nim->qoffset_z , nim->qfac ) ;
+
+     nifti_mat44_to_orientation( nim->qto_xyz , &i,&j,&k ) ;
+     if( i > 0 && j > 0 && k > 0 )
+       sprintf( buf+strlen(buf) ,
+                "  qform_i_orientation = '%s'\n"
+                "  qform_j_orientation = '%s'\n"
+                "  qform_k_orientation = '%s'\n" ,
+                nifti_orientation_string(i) ,
+                nifti_orientation_string(j) ,
+                nifti_orientation_string(k)  ) ;
+   }
+
+   if( nim->sform_code > 0 ){
+     int i,j,k ;
+
+     sprintf( buf+strlen(buf) ,
+              "  sform_code = '%d'\n"
+              "  sform_code_name = '%s'\n"
+     "  sto_xyz_matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" ,
+         nim->sform_code      , nifti_xform_string(nim->sform_code) ,
+         nim->sto_xyz.m[0][0] , nim->sto_xyz.m[0][1] ,
+         nim->sto_xyz.m[0][2] , nim->sto_xyz.m[0][3] ,
+         nim->sto_xyz.m[1][0] , nim->sto_xyz.m[1][1] ,
+         nim->sto_xyz.m[1][2] , nim->sto_xyz.m[1][3] ,
+         nim->sto_xyz.m[2][0] , nim->sto_xyz.m[2][1] ,
+         nim->sto_xyz.m[2][2] , nim->sto_xyz.m[2][3] ,
+         nim->sto_xyz.m[3][0] , nim->sto_xyz.m[3][1] ,
+         nim->sto_xyz.m[3][2] , nim->sto_xyz.m[3][3]  ) ;
+
+     sprintf( buf+strlen(buf) ,
+     "  sto_ijk matrix = '%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g'\n" ,
+         nim->sto_ijk.m[0][0] , nim->sto_ijk.m[0][1] ,
+         nim->sto_ijk.m[0][2] , nim->sto_ijk.m[0][3] ,
+         nim->sto_ijk.m[1][0] , nim->sto_ijk.m[1][1] ,
+         nim->sto_ijk.m[1][2] , nim->sto_ijk.m[1][3] ,
+         nim->sto_ijk.m[2][0] , nim->sto_ijk.m[2][1] ,
+         nim->sto_ijk.m[2][2] , nim->sto_ijk.m[2][3] ,
+         nim->sto_ijk.m[3][0] , nim->sto_ijk.m[3][1] ,
+         nim->sto_ijk.m[3][2] , nim->sto_ijk.m[3][3]  ) ;
+
+     nifti_mat44_to_orientation( nim->sto_xyz , &i,&j,&k ) ;
+     if( i > 0 && j > 0 && k > 0 )
+       sprintf( buf+strlen(buf) ,
+                "  sform_i_orientation = '%s'\n"
+                "  sform_j_orientation = '%s'\n"
+                "  sform_k_orientation = '%s'\n" ,
+                nifti_orientation_string(i) ,
+                nifti_orientation_string(j) ,
+                nifti_orientation_string(k)  ) ;
+   }
+
+   sprintf( buf+strlen(buf) , "  num_ext = '%d'\n", nim->num_ext ) ;
+
+   sprintf( buf+strlen(buf) , "/>\n" ) ;   /* XML-ish closer */
+
+   nbuf = strlen(buf) ;
+   buf  = (char *)realloc((void *)buf, nbuf+1); /* cut back to proper length */
+   if( !buf ) fprintf(stderr,"** NITA: failed to realloc %d bytes\n",nbuf+1);
+   return buf ;
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------*/
+/*! get the byte order for this CPU
+
+    - LSB_FIRST means least significant byte, first (little endian)
+    - MSB_FIRST means most significant byte, first (big endian)
+*//*--------------------------------------------------------------------*/
+int nifti_short_order(void)   /* determine this CPU's byte order */
+{
+   union { unsigned char bb[2] ;
+           short         ss    ; } fred ;
+
+   fred.bb[0] = 1 ; fred.bb[1] = 0 ;
+
+   return (fred.ss == 1) ? LSB_FIRST : MSB_FIRST ;
+}
+
+/*---------------------------------------------------------------------------*/
+
+#undef  QQNUM
+#undef  QNUM
+#undef  QSTR
+
+/* macro to check lhs string against "n1"; if it matches,
+   interpret rhs string as a number, and put it into nim->"n2" */
+
+#define QQNUM(n1,n2) if( strcmp(lhs,#n1)==0 ) nim->n2=strtod(rhs,NULL)
+
+/* same, but where "n1" == "n2" */
+
+#define QNUM(nam)    QQNUM(nam,nam)
+
+/* macro to check lhs string against "nam"; if it matches,
+   put rhs string into nim->"nam" string, with max length = "ml" */
+
+#define QSTR(nam,ml) if( strcmp(lhs,#nam) == 0 )                           \
+                       strncpy(nim->nam,rhs,ml), nim->nam[ml]='\0'
+
+/*---------------------------------------------------------------------------*/
+/*! Take an XML-ish ASCII string and create a NIFTI image header to match.
+
+    NULL is returned if enough information isn't present in the input string.
+    - The image data can later be loaded with nifti_image_load().
+    - The struct returned here can be liberated with nifti_image_free().
+    - Not a lot of error checking is done here to make sure that the
+      input values are reasonable!
+*//*-------------------------------------------------------------------------*/
+nifti_image *nifti_image_from_ascii( const char *str, int * bytes_read )
+{
+   char lhs[1024] , rhs[1024] ;
+   int ii , spos, nn , slen ;
+   nifti_image *nim ;              /* will be output */
+
+   if( str == NULL || *str == '\0' ) return NULL ;  /* bad input!? */
+
+   /* scan for opening string */
+
+   spos = 0 ; slen = strlen(str) ;
+   ii = sscanf( str+spos , "%1023s%n" , lhs , &nn ) ; spos += nn ;
+   if( ii == 0 || strcmp(lhs,"<nifti_image") != 0 ) return NULL ;
+
+   /* create empty image struct */
+
+   nim = (nifti_image *) calloc( 1 , sizeof(nifti_image) ) ;
+   if( !nim ){
+      fprintf(stderr,"** NIFA: failed to alloc nifti_image\n");
+      return NULL;
+   }
+
+   nim->nx = nim->ny = nim->nz = nim->nt
+           = nim->nu = nim->nv = nim->nw = 1 ;
+   nim->dx = nim->dy = nim->dz = nim->dt
+           = nim->du = nim->dv = nim->dw = nim->qfac = 1.0 ;
+
+   nim->byteorder = nifti_short_order() ;
+
+   /* starting at str[spos], scan for "equations" of the form
+         lhs = 'rhs'
+      and assign rhs values into the struct component named by lhs */
+
+   while(1){
+
+     while( isspace(str[spos]) ) spos++ ;  /* skip whitespace */
+     if( str[spos] == '\0' ) break ;       /* end of string? */
+
+     /* get lhs string */
+
+     ii = sscanf( str+spos , "%1023s%n" , lhs , &nn ) ; spos += nn ;
+     if( ii == 0 || strcmp(lhs,"/>") == 0 ) break ;  /* end of input? */
+
+     /* skip whitespace and the '=' marker */
+
+     while( isspace(str[spos]) || str[spos] == '=' ) spos++ ;
+     if( str[spos] == '\0' ) break ;       /* end of string? */
+
+     /* if next character is a quote ', copy everything up to next '
+        otherwise, copy everything up to next nonblank              */
+
+     if( str[spos] == '\'' ){
+        ii = spos+1 ;
+        while( str[ii] != '\0' && str[ii] != '\'' ) ii++ ;
+        nn = ii-spos-1 ; if( nn > 1023 ) nn = 1023 ;
+        memcpy(rhs,str+spos+1,nn) ; rhs[nn] = '\0' ;
+        spos = (str[ii] == '\'') ? ii+1 : ii ;
+     } else {
+        ii = sscanf( str+spos , "%1023s%n" , rhs , &nn ) ; spos += nn ;
+        if( ii == 0 ) break ;  /* nothing found? */
+     }
+     unescape_string(rhs) ;  /* remove any XML escape sequences */
+
+     /* Now can do the assignment, based on lhs string.
+        Start with special cases that don't fit the QNUM/QSTR macros. */
+
+     if( strcmp(lhs,"nifti_type") == 0 ){
+            if( strcmp(rhs,"ANALYZE-7.5") == 0 )
+               nim->nifti_type = NIFTI_FTYPE_ANALYZE ;
+       else if( strcmp(rhs,"NIFTI-1+")    == 0 )
+               nim->nifti_type = NIFTI_FTYPE_NIFTI1_1 ;
+       else if( strcmp(rhs,"NIFTI-1")     == 0 )
+               nim->nifti_type = NIFTI_FTYPE_NIFTI1_2 ;
+       else if( strcmp(rhs,"NIFTI-1A")    == 0 )
+               nim->nifti_type = NIFTI_FTYPE_ASCII ;
+     }
+     else if( strcmp(lhs,"header_filename") == 0 ){
+       nim->fname = nifti_strdup(rhs) ;
+     }
+     else if( strcmp(lhs,"image_filename") == 0 ){
+       nim->iname = nifti_strdup(rhs) ;
+     }
+     else if( strcmp(lhs,"sto_xyz_matrix") == 0 ){
+       sscanf( rhs , "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f" ,
+               &(nim->sto_xyz.m[0][0]) , &(nim->sto_xyz.m[0][1]) ,
+               &(nim->sto_xyz.m[0][2]) , &(nim->sto_xyz.m[0][3]) ,
+               &(nim->sto_xyz.m[1][0]) , &(nim->sto_xyz.m[1][1]) ,
+               &(nim->sto_xyz.m[1][2]) , &(nim->sto_xyz.m[1][3]) ,
+               &(nim->sto_xyz.m[2][0]) , &(nim->sto_xyz.m[2][1]) ,
+               &(nim->sto_xyz.m[2][2]) , &(nim->sto_xyz.m[2][3]) ,
+               &(nim->sto_xyz.m[3][0]) , &(nim->sto_xyz.m[3][1]) ,
+               &(nim->sto_xyz.m[3][2]) , &(nim->sto_xyz.m[3][3])  ) ;
+     }
+     else if( strcmp(lhs,"byteorder") == 0 ){
+       if( strcmp(rhs,"MSB_FIRST") == 0 ) nim->byteorder = MSB_FIRST ;
+       if( strcmp(rhs,"LSB_FIRST") == 0 ) nim->byteorder = LSB_FIRST ;
+     }
+     else QQNUM(image_offset,iname_offset) ;
+     else QNUM(datatype) ;
+     else QNUM(ndim) ;
+     else QNUM(nx) ;
+     else QNUM(ny) ;
+     else QNUM(nz) ;
+     else QNUM(nt) ;
+     else QNUM(nu) ;
+     else QNUM(nv) ;
+     else QNUM(nw) ;
+     else QNUM(dx) ;
+     else QNUM(dy) ;
+     else QNUM(dz) ;
+     else QNUM(dt) ;
+     else QNUM(du) ;
+     else QNUM(dv) ;
+     else QNUM(dw) ;
+     else QNUM(cal_min) ;
+     else QNUM(cal_max) ;
+     else QNUM(scl_slope) ;
+     else QNUM(scl_inter) ;
+     else QNUM(intent_code) ;
+     else QNUM(intent_p1) ;
+     else QNUM(intent_p2) ;
+     else QNUM(intent_p3) ;
+     else QSTR(intent_name,15) ;
+     else QNUM(toffset) ;
+     else QNUM(xyz_units) ;
+     else QNUM(time_units) ;
+     else QSTR(descrip,79) ;
+     else QSTR(aux_file,23) ;
+     else QNUM(qform_code) ;
+     else QNUM(quatern_b) ;
+     else QNUM(quatern_c) ;
+     else QNUM(quatern_d) ;
+     else QNUM(qoffset_x) ;
+     else QNUM(qoffset_y) ;
+     else QNUM(qoffset_z) ;
+     else QNUM(qfac) ;
+     else QNUM(sform_code) ;
+     else QNUM(freq_dim) ;
+     else QNUM(phase_dim) ;
+     else QNUM(slice_dim) ;
+     else QNUM(slice_code) ;
+     else QNUM(slice_start) ;
+     else QNUM(slice_end) ;
+     else QNUM(slice_duration) ;
+     else QNUM(num_ext) ;
+
+   } /* end of while loop */
+
+   if( bytes_read ) *bytes_read = spos+1;         /* "process" last '\n' */
+
+   /* do miscellaneous checking and cleanup */
+
+   if( nim->ndim <= 0 ){ nifti_image_free(nim); return NULL; } /* bad! */
+
+   nifti_datatype_sizes( nim->datatype, &(nim->nbyper), &(nim->swapsize) );
+   if( nim->nbyper == 0 ){ nifti_image_free(nim); return NULL; } /* bad! */
+
+   nim->dim[0] = nim->ndim ;
+   nim->dim[1] = nim->nx ; nim->pixdim[1] = nim->dx ;
+   nim->dim[2] = nim->ny ; nim->pixdim[2] = nim->dy ;
+   nim->dim[3] = nim->nz ; nim->pixdim[3] = nim->dz ;
+   nim->dim[4] = nim->nt ; nim->pixdim[4] = nim->dt ;
+   nim->dim[5] = nim->nu ; nim->pixdim[5] = nim->du ;
+   nim->dim[6] = nim->nv ; nim->pixdim[6] = nim->dv ;
+   nim->dim[7] = nim->nw ; nim->pixdim[7] = nim->dw ;
+
+   nim->nvox =  nim->nx * nim->ny * nim->nz
+              * nim->nt * nim->nu * nim->nv * nim->nw ;
+
+   if( nim->qform_code > 0 )
+     nim->qto_xyz = nifti_quatern_to_mat44(
+                      nim->quatern_b, nim->quatern_c, nim->quatern_d,
+                      nim->qoffset_x, nim->qoffset_y, nim->qoffset_z,
+                      nim->dx       , nim->dy       , nim->dz       ,
+                      nim->qfac                                      ) ;
+   else
+     nim->qto_xyz = nifti_quatern_to_mat44(
+                      0.0 , 0.0 , 0.0 , 0.0 , 0.0 , 0.0 ,
+                      nim->dx , nim->dy , nim->dz , 0.0 ) ;
+
+
+   nim->qto_ijk = nifti_mat44_inverse( nim->qto_xyz ) ;
+
+   if( nim->sform_code > 0 )
+     nim->sto_ijk = nifti_mat44_inverse( nim->sto_xyz ) ;
+
+   return nim ;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/*! validate the nifti_image
+
+    \return 1 if the structure seems valid, otherwise 0
+
+    \sa nifti_nim_has_valid_dims, nifti_hdr_looks_good
+*//*-------------------------------------------------------------------------*/
+int nifti_nim_is_valid(nifti_image * nim, int complain)
+{
+   int errs = 0;
+
+   if( !nim ){
+      fprintf(stderr,"** is_valid_nim: nim is NULL\n");
+      return 0;
+   }
+
+   if( g_opts.debug > 2 ) fprintf(stderr,"-d nim_is_valid check...\n");
+
+   /**- check that dim[] matches the individual values ndim, nx, ny, ... */
+   if( ! nifti_nim_has_valid_dims(nim,complain) ){
+      if( !complain ) return 0;
+      errs++;
+   }
+
+   /* might check nbyper, pixdim, q/sforms, swapsize, nifti_type, ... */
+
+   /**- be explicit in return of 0 or 1 */
+   if( errs > 0 ) return 0;
+   else           return 1;
+}
+
+/*---------------------------------------------------------------------------*/
+/*! validate nifti dimensions
+
+    \return 1 if valid, 0 if not
+
+    \sa nifti_nim_is_valid, nifti_hdr_looks_good
+
+    rely on dim[] as the master
+*//*-------------------------------------------------------------------------*/
+int nifti_nim_has_valid_dims(nifti_image * nim, int complain)
+{
+   int c, prod, errs = 0;
+
+   /**- start with dim[0]: failure here is considered terminal */
+   if( nim->dim[0] <= 0 || nim->dim[0] > 7 ){
+      errs++;
+      if( complain )
+         fprintf(stderr,"** NVd: dim[0] (%d) out of range [1,7]\n",nim->dim[0]);
+      return 0;
+   }
+
+   /**- check whether ndim equals dim[0] */
+   if( nim->ndim != nim->dim[0] ){
+      errs++;
+      if( ! complain ) return 0;
+      fprintf(stderr,"** NVd: ndim != dim[0] (%d,%d)\n",nim->ndim,nim->dim[0]);
+   }
+
+   /**- compare each dim[i] to the proper nx, ny, ... */
+   if( ( (nim->dim[0] >= 1) && (nim->dim[1] != nim->nx) ) ||
+       ( (nim->dim[0] >= 2) && (nim->dim[2] != nim->ny) ) ||
+       ( (nim->dim[0] >= 3) && (nim->dim[3] != nim->nz) ) ||
+       ( (nim->dim[0] >= 4) && (nim->dim[4] != nim->nt) ) ||
+       ( (nim->dim[0] >= 5) && (nim->dim[5] != nim->nu) ) ||
+       ( (nim->dim[0] >= 6) && (nim->dim[6] != nim->nv) ) ||
+       ( (nim->dim[0] >= 7) && (nim->dim[7] != nim->nw) )   ){
+      errs++;
+      if( !complain ) return 0;
+      fprintf(stderr,"** NVd mismatch: dims    = %d,%d,%d,%d,%d,%d,%d\n"
+                     "                 nxyz... = %d,%d,%d,%d,%d,%d,%d\n",
+                     nim->dim[1], nim->dim[2], nim->dim[3],
+                     nim->dim[4], nim->dim[5], nim->dim[6], nim->dim[7],
+                     nim->nx, nim->ny, nim->nz,
+                     nim->nt, nim->nu, nim->nv, nim->nw );
+   }
+
+   /**- check the dimensions, and that their product matches nvox */
+   prod = 1;
+   for( c = 1; c <= nim->dim[0]; c++ ){
+      if( nim->dim[c] > 0)
+         prod *= nim->dim[c];
+      else if( nim->dim[c] <= 0 ){
+         if( !complain ) return 0;
+         fprintf(stderr,"** NVd: dim[%d] (=%d) <= 0\n",c, nim->dim[c]);
+         errs++;
+      }
+   }
+   if( prod != nim->nvox ){
+      if( ! complain ) return 0;
+      fprintf(stderr,"** NVd: nvox does not match dimension product (%d, %d)\n",
+              nim->nvox, prod);
+      errs++;
+   }
+
+   /**- if debug, warn about any remaining dim that is neither 0, nor 1 */
+   /*   (values in dims above dim[0] are undefined, as reminded by Cinly
+         Ooi and Alle Meije Wink)                   16 Nov 2005 [rickr] */
+   if( g_opts.debug > 1 )
+      for( c = nim->dim[0]+1; c <= 7; c++ )
+         if( nim->dim[c] != 0 && nim->dim[c] != 1 )
+            fprintf(stderr,"** NVd warning: dim[%d] = %d, but ndim = %d\n",
+                    c, nim->dim[c], nim->dim[0]);
+
+   if( g_opts.debug > 2 )
+      fprintf(stderr,"-d nim_has_valid_dims check, errs = %d\n", errs);
+
+   /**- return invalid or valid */
+   if( errs > 0 ) return 0;
+   else           return 1;
+}
+
+
+/*---------------------------------------------------------------------------*/
+/*! read a nifti image, collapsed across dimensions according to dims[8]  <pre>
+
+    This function may be used to read parts of a nifti dataset, such as
+    the time series for a single voxel, or perhaps a slice.  It is similar
+    to nifti_image_load(), though the passed 'data' parameter is used for
+    returning the image, not nim->data.
+
+    \param nim  given nifti_image struct, corresponding to the data file
+    \param dims given list of dimensions (see below)
+    \param data pointer to data pointer (if *data is NULL, data will be
+                allocated, otherwise not)
+
+    Here, dims is an array of 8 ints, similar to nim->dim[8].  While dims[0]
+    is unused at this point, the other indices specify which dimensions to
+    collapse (and at which index), and which not to collapse.  If dims[i] is
+    set to -1, then that entire dimension will be read in, from index 0 to
+    index (nim->dim[i] - 1).  If dims[i] >= 0, then only that index will be
+    read in (so dims[i] must also be < nim->dim[i]).
+
+    Example: given  nim->dim[8] = { 4, 64, 64, 21, 80, 1, 1, 1 } (4-D dataset)
+
+      if dims[8] = { 0,  5,  4, 17, -1, -1, -1, -1 }
+         -> read time series for voxel i,j,k = 5,4,17
+
+      if dims[8] = { 0, -1, -1, -1, 17, -1, -1, -1 }
+         -> read single volume at time point 17
+
+    Example: given  nim->dim[8] = { 6, 64, 64, 21, 80, 4, 3, 1 } (6-D dataset)
+
+      if dims[8] = { 0, 5, 4, 17, -1, 2, 1, 0 }
+         -> read time series for the voxel i,j,k = 5,4,17, and dim 5,6 = 2,1
+
+      if dims[8] = { 0, 5, 4, -1, -1, 0, 0, 0 }
+         -> read time series for slice at i,j = 5,4, and dim 5,6,7 = 0,0,0
+            (note that dims[7] is not relevant, but must be 0 or -1)
+
+    If *data is NULL, then *data will be set as a pointer to new memory,
+    allocated here for the resulting collapsed image data.
+
+      e.g. { int    dims[8] = { 0,  5,  4, 17, -1, -1, -1, -1 };
+             void * data    = NULL;
+             ret_val = nifti_read_collapsed_image(nim, dims, &data);
+             if( ret_val > 0 ){
+                process_time_series(data);
+                if( data != NULL ) free(data);
+             }
+           }
+
+    NOTE: If *data is not NULL, then it will be assumed that it points to
+          valid memory, sufficient to hold the results.  This is done for
+          speed and possibly repeated calls to this function.
+
+      e.g. { int    dims[8] = { 0,  -1, -1, -1, -1, -1, -1, -1 };
+             void * data    = NULL;
+             for( zslice = 0; zslice < nzslices; zslice++ ){
+                dims[3] = zslice;
+                ret_val = nifti_read_collapsed_image(nim, dims, &data);
+                if( ret_val > 0 ) process_slice(zslice, data);
+             }
+             if( data != NULL ) free(data);
+           }
+
+    \return
+        -  the total number of bytes read, or < 0 on failure
+        -  the read and byte-swapped data, in 'data'            </pre>
+
+    \sa nifti_image_read, nifti_image_free, nifti_image_read_bricks
+        nifti_image_load
+*//*-------------------------------------------------------------------------*/
+int nifti_read_collapsed_image( nifti_image * nim, const int dims [8],
+                                void ** data )
+{
+   znzFile fp;
+   int     pivots[8], prods[8], nprods; /* sizes are bounded by dims[], so 8 */
+   int     c, bytes;
+
+   /** - check pointers for sanity */
+   if( !nim || !dims || !data ){
+      fprintf(stderr,"** nifti_RCI: bad params %p, %p, %p\n",
+              (void *)nim, (void *)dims, (void *)data);
+      return -1;
+   }
+
+   if( g_opts.debug > 2 ){
+      fprintf(stderr,"-d read_collapsed_image:\n        dims =");
+      for(c = 0; c < 8; c++) fprintf(stderr," %3d", dims[c]);
+      fprintf(stderr,"\n   nim->dims =");
+      for(c = 0; c < 8; c++) fprintf(stderr," %3d", nim->dim[c]);
+      fputc('\n', stderr);
+   }
+
+   /** - verify that dim[] makes sense */
+   if( ! nifti_nim_is_valid(nim, g_opts.debug > 0) ){
+      fprintf(stderr,"** invalid nim (file is '%s')\n", nim->fname );
+      return -1;
+   }
+
+   /** - verify that dims[] makes sense for this dataset */
+   for( c = 1; c <= nim->dim[0]; c++ ){
+      if( dims[c] >= nim->dim[c] ){
+         fprintf(stderr,"** nifti_RCI: dims[%d] >= nim->dim[%d] (%d,%d)\n",
+                 c, c, dims[c], nim->dim[c]);
+         return -1;
+      }
+   }
+
+   /** - prepare pivot list - pivots are fixed indices */
+   if( make_pivot_list(nim, dims, pivots, prods, &nprods) < 0 ) return -1;
+
+   bytes = rci_alloc_mem(data, prods, nprods, nim->nbyper);
+   if( bytes < 0 ) return -1;
+
+   /** - open the image file for reading at the appropriate offset */
+   fp = nifti_image_load_prep( nim );
+   if( ! fp ){ free(*data);  *data = NULL;  return -1; }     /* failure */
+
+   /** - call the recursive reading function, passing nim, the pivot info,
+         location to store memory, and file pointer and position */
+   c = rci_read_data(nim, pivots,prods,nprods,dims,
+                     (char *)*data, fp, znztell(fp));
+   znzclose(fp);   /* in any case, close the file */
+   if( c < 0 ){ free(*data);  *data = NULL;  return -1; }    /* failure */
+
+   if( g_opts.debug > 1 )
+      fprintf(stderr,"+d read %d bytes of collapsed image from %s\n",
+              bytes, nim->fname);
+
+   return bytes;
+}
+
+
+/* read the data from the file pointed to by fp
+
+   - this a recursive function, so start with the base case
+   - data is now (char *) for easy incrementing
+
+   return 0 on success, < 0 on failure
+*/
+static int rci_read_data(nifti_image * nim, int * pivots, int * prods,
+         int nprods, const int dims[], char * data, znzFile fp, int base_offset)
+{
+   int c, sublen, offset, read_size;
+
+   /* bad check first - base_offset may not have been checked */
+   if( base_offset < 0 || nprods <= 0 ){
+      fprintf(stderr,"** rci_read_data, bad params, %d,%d\n",
+              nprods, base_offset);
+      return -1;
+   }
+
+   /* base case: actually read the data */
+   if( nprods == 1 ){
+      int nread, bytes;
+
+      /* make sure things look good here */
+      if( *pivots != 0 ){
+         fprintf(stderr,"** rciRD: final pivot == %d!\n", *pivots);
+         return -1;
+      }
+
+      /* so just seek and read (prods[0] * nbyper) bytes from the file */
+      znzseek(fp, base_offset, SEEK_SET);
+      bytes = prods[0] * nim->nbyper;
+      nread = nifti_read_buffer(fp, data, bytes, nim);
+      if( nread != bytes ){
+         fprintf(stderr,"** rciRD: read only %d of %d bytes from '%s'\n",
+                 nread, bytes, nim->fname);
+         return -1;
+      } else if( g_opts.debug > 3 )
+         fprintf(stderr,"+d successful read of %d bytes at offset %d\n",
+                 bytes, base_offset);
+
+      return 0;  /* done with base case - return success */
+   }
+
+   /* not the base case, so do a set of reduced reads */
+
+   /* compute size of sub-brick: all dimensions below pivot */
+   for( c = 1, sublen = 1; c < *pivots; c++ ) sublen *= nim->dim[c];
+
+   /* compute number of values to read, i.e. remaining prods */
+   for( c = 1, read_size = 1; c < nprods; c++ ) read_size *= prods[c];
+   read_size *= nim->nbyper;  /* and multiply by bytes per voxel */
+
+   /* now repeatedly compute offsets, and recursively read */
+   for( c = 0; c < prods[0]; c++ ){
+      /* offset is (c * sub-block size (including pivot dim))   */
+      /*         + (dims[] index into pivot sub-block)          */
+      /* the unneeded multiplication is to make this more clear */
+      offset = c * sublen * nim->dim[*pivots] + sublen * dims[*pivots];
+      offset *= nim->nbyper;
+
+      if( g_opts.debug > 3 )
+         fprintf(stderr,"-d reading %d bytes, foff %d + %d, doff %d\n",
+                 read_size, base_offset, offset, c*read_size);
+
+      /* now read the next level down, adding this offset */
+      if( rci_read_data(nim, pivots+1, prods+1, nprods-1, dims,
+                    data + c * read_size, fp, base_offset + offset) < 0 )
+         return -1;
+   }
+
+   return 0;
+}
+
+
+/* allocate memory for all collapsed image data
+
+   If *data is already set, do not allocate, but still calculate
+   size for debug report.
+
+   return total size on success, and < 0 on failure
+*/
+static int rci_alloc_mem(void ** data, int prods[8], int nprods, int nbyper )
+{
+   int size, index;
+
+   if( nbyper < 0 || nprods < 1 || nprods > 8 ){
+      fprintf(stderr,"** rci_am: bad params, %d, %d\n", nbyper, nprods);
+      return -1;
+   }
+
+   for( index = 0, size = 1; index < nprods; index++ )
+       size *= prods[index];
+
+   size *= nbyper;
+
+   if( ! *data ){   /* then allocate what is needed */
+      if( g_opts.debug > 1 )
+         fprintf(stderr,"+d alloc %d (= %d x %d) bytes for collapsed image\n",
+                 size, size/nbyper, nbyper);
+
+      *data = malloc(size);   /* actually allocate the memory */
+      if( ! *data ){
+         fprintf(stderr,"** rci_am: failed to alloc %d bytes for data\n", size);
+         return -1;
+      }
+   } else if( g_opts.debug > 1 )
+      fprintf(stderr,"-d rci_am: *data already set, need %d (%d x %d) bytes\n",
+              size, size/nbyper, nbyper);
+
+   return size;
+}
+
+
+/* prepare a pivot list for reading
+
+   The pivot points are the indices into dims where the calling function
+   wants to collapse a dimension.  The last pivot should always be zero
+   (note that we have space for that in the lists).
+*/
+static int make_pivot_list(nifti_image * nim, const int dims[], int pivots[],
+                                              int prods[], int * nprods )
+{
+   int len, index;
+
+   len = 0;
+   index = nim->dim[0];
+   while( index > 0 ){
+      prods[len] = 1;
+      while( index > 0 && (nim->dim[index] == 1 || dims[index] == -1) ){
+         prods[len] *= nim->dim[index];
+         index--;
+      }
+      pivots[len] = index;
+      len++;
+      index--;  /* fine, let it drop out at -1 */
+   }
+
+   /* make sure to include 0 as a pivot (instead of just 1, if it is) */
+   if( pivots[len-1] != 0 ){
+      pivots[len] = 0;
+      prods[len] = 1;
+      len++;
+   }
+
+   *nprods = len;
+
+   if( g_opts.debug > 2 ){
+      fprintf(stderr,"+d pivot list created, pivots :");
+      for(index = 0; index < len; index++) fprintf(stderr," %d", pivots[index]);
+      fprintf(stderr,", prods :");
+      for(index = 0; index < len; index++) fprintf(stderr," %d", prods[index]);
+      fputc('\n',stderr);
+   }
+
+   return 0;
+}
+
+
+#undef ISEND
+#define ISEND(c) ( (c)==']' || (c)=='}' || (c)=='\0' )
+
+/*---------------------------------------------------------------------*/
+/*! Get an integer list in the range 0..(nvals-1), from the
+   character string str.  If we call the output pointer fred,
+   then fred[0] = number of integers in the list (> 0), and
+        fred[i] = i-th integer in the list for i=1..fred[0].
+   If on return, fred == NULL or fred[0] == 0, then something is
+   wrong, and the caller must deal with that.
+
+   Syntax of input string:
+     - initial '{' or '[' is skipped, if present
+     - ends when '}' or ']' or end of string is found
+     - contains entries separated by commas
+     - entries have one of these forms:
+       - a single number
+       - a dollar sign '$', which means nvals-1
+       - a sequence of consecutive numbers in the form "a..b" or
+         "a-b", where "a" and "b" are single numbers (or '$')
+       - a sequence of evenly spaced numbers in the form
+         "a..b(c)" or "a-b(c)", where "c" encodes the step
+     - Example:  "[2,7..4,3..9(2)]" decodes to the list
+         2 7 6 5 4 3 5 7 9
+     - entries should be in the range 0..nvals-1
+
+   (borrowed, with permission, from thd_intlist.c)
+*//*-------------------------------------------------------------------*/
+int * nifti_get_intlist( int nvals , const char * str )
+{
+   int *subv = NULL ;
+   int ii , ipos , nout , slen ;
+   int ibot,itop,istep , nused ;
+   char *cpt ;
+
+   /* Meaningless input? */
+   if( nvals < 1 ) return NULL ;
+
+   /* No selection list? */
+   if( str == NULL || str[0] == '\0' ) return NULL ;
+
+   /* skip initial '[' or '{' */
+   subv    = (int *) malloc( sizeof(int) * 2 ) ;
+   subv[0] = nout = 0 ;
+
+   ipos = 0 ;
+   if( str[ipos] == '[' || str[ipos] == '{' ) ipos++ ;
+
+   if( g_opts.debug > 1 )
+      fprintf(stderr,"-d making int_list (vals = %d) from '%s'\n", nvals, str);
+
+   /**- for each sub-selector until end of input... */
+
+   slen = strlen(str) ;
+   while( ipos < slen && !ISEND(str[ipos]) ){
+
+      while( isspace(str[ipos]) ) ipos++ ;   /* skip blanks */
+      if( ISEND(str[ipos]) ) break ;         /* done */
+
+      /**- get starting value */
+
+      if( str[ipos] == '$' ){  /* special case */
+         ibot = nvals-1 ; ipos++ ;
+      } else {                 /* decode an integer */
+         ibot = strtol( str+ipos , &cpt , 10 ) ;
+         if( ibot < 0 ){
+           fprintf(stderr,"** ERROR: list index %d is out of range 0..%d\n",
+                   ibot,nvals-1) ;
+           free(subv) ; return NULL ;
+         }
+         if( ibot >= nvals ){
+           fprintf(stderr,"** ERROR: list index %d is out of range 0..%d\n",
+                   ibot,nvals-1) ;
+           free(subv) ; return NULL ;
+         }
+         nused = (cpt-(str+ipos)) ;
+         if( ibot == 0 && nused == 0 ){
+           fprintf(stderr,"** ERROR: list syntax error '%s'\n",str+ipos) ;
+           free(subv) ; return NULL ;
+         }
+         ipos += nused ;
+      }
+
+      while( isspace(str[ipos]) ) ipos++ ;   /* skip blanks */
+
+      /**- if that's it for this sub-selector, add one value to list */
+
+      if( str[ipos] == ',' || ISEND(str[ipos]) ){
+         nout++ ;
+         subv = (int *) realloc( (char *)subv , sizeof(int) * (nout+1) ) ;
+         subv[0]    = nout ;
+         subv[nout] = ibot ;
+         if( ISEND(str[ipos]) ) break ; /* done */
+         ipos++ ; continue ;            /* re-start loop at next sub-selector */
+      }
+
+      /**- otherwise, must have '..' or '-' as next inputs */
+
+      if( str[ipos] == '-' ){
+         ipos++ ;
+      } else if( str[ipos] == '.' && str[ipos+1] == '.' ){
+         ipos++ ; ipos++ ;
+      } else {
+         fprintf(stderr,"** ERROR: index list syntax is bad: '%s'\n",
+                 str+ipos) ;
+         free(subv) ; return NULL ;
+      }
+
+      /**- get ending value for loop now */
+
+      if( str[ipos] == '$' ){  /* special case */
+         itop = nvals-1 ; ipos++ ;
+      } else {                 /* decode an integer */
+         itop = strtol( str+ipos , &cpt , 10 ) ;
+         if( itop < 0 ){
+           fprintf(stderr,"** ERROR: index %d is out of range 0..%d\n",
+                   itop,nvals-1) ;
+           free(subv) ; return NULL ;
+         }
+         if( itop >= nvals ){
+           fprintf(stderr,"** ERROR: index %d is out of range 0..%d\n",
+                   itop,nvals-1) ;
+           free(subv) ; return NULL ;
+         }
+         nused = (cpt-(str+ipos)) ;
+         if( itop == 0 && nused == 0 ){
+           fprintf(stderr,"** ERROR: index list syntax error '%s'\n",str+ipos) ;
+           free(subv) ; return NULL ;
+         }
+         ipos += nused ;
+      }
+
+      /**- set default loop step */
+
+      istep = (ibot <= itop) ? 1 : -1 ;
+
+      while( isspace(str[ipos]) ) ipos++ ;                  /* skip blanks */
+
+      /**- check if we have a non-default loop step */
+
+      if( str[ipos] == '(' ){  /* decode an integer */
+         ipos++ ;
+         istep = strtol( str+ipos , &cpt , 10 ) ;
+         if( istep == 0 ){
+           fprintf(stderr,"** ERROR: index loop step is 0!\n") ;
+           free(subv) ; return NULL ;
+         }
+         nused = (cpt-(str+ipos)) ;
+         ipos += nused ;
+         if( str[ipos] == ')' ) ipos++ ;
+         if( (ibot-itop)*istep > 0 ){
+           fprintf(stderr,"** WARNING: index list '%d..%d(%d)' means nothing\n",
+                   ibot,itop,istep ) ;
+         }
+      }
+
+      /**- add values to output */
+
+      for( ii=ibot ; (ii-itop)*istep <= 0 ; ii += istep ){
+         nout++ ;
+         subv = (int *) realloc( (char *)subv , sizeof(int) * (nout+1) ) ;
+         subv[0]    = nout ;
+         subv[nout] = ii ;
+      }
+
+      /**- check if we have a comma to skip over */
+
+      while( isspace(str[ipos]) ) ipos++ ;                  /* skip blanks */
+      if( str[ipos] == ',' ) ipos++ ;                       /* skip commas */
+
+   }  /* end of loop through selector string */
+
+   if( g_opts.debug > 1 ) {
+      fprintf(stderr,"+d int_list (vals = %d): ", subv[0]);
+      for( ii = 1; ii <= subv[0]; ii++ ) fprintf(stderr,"%d ", subv[ii]);
+      fputc('\n',stderr);
+   }
+
+   if( subv[0] == 0 ){ free(subv); subv = NULL; }
+   return subv ;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkTemplateAliasMacro.h b/bioimagesuite30_src/Common/vtkTemplateAliasMacro.h
new file mode 100644
index 0000000..1b966e7
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkTemplateAliasMacro.h
@@ -0,0 +1,148 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkTemplateAliasMacro.h,v $
+
+  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 vtkTemplateAliasMacro - Dispatch a scalar processing template.
+// .SECTION Description
+// vtkTemplateAliasMacro is used in a switch statement to
+// automatically generate duplicate code for all enabled scalar types.
+// The code can be written to use VTK_TT to refer to the type, and
+// each case generated will define VTK_TT appropriately.  The
+// difference between this and the standard vtkTemplateMacro is that
+// this version will set VTK_TT to an "alias" for each type.  The
+// alias may be the same type or may be a different type that is the
+// same size/signedness.  This is sufficient when only the numerical
+// value associated with instances of the type is needed, and it
+// avoids unnecessary template instantiations.
+//
+// Example usage:
+//
+//   void* p = dataArray->GetVoidPointer(0);
+//   switch(dataArray->GetDataType())
+//     {
+//     vtkTemplateAliasMacro(vtkMyTemplateFunction(static_cast<VTK_TT*>(p)));
+//     }
+
+#ifndef __vtkTemplateAliasMacro_h
+#define __vtkTemplateAliasMacro_h
+
+#include "vtkTypeTraits.h"
+
+// Allow individual switching of support for each scalar size/signedness.
+// These could be made advanced user options to be configured by CMake.
+#define VTK_USE_INT8 1
+#define VTK_USE_UINT8 1
+#define VTK_USE_INT16 1
+#define VTK_USE_UINT16 1
+#define VTK_USE_INT32 1
+#define VTK_USE_UINT32 1
+#define VTK_USE_INT64 1
+#define VTK_USE_UINT64 1
+#define VTK_USE_FLOAT32 1
+#define VTK_USE_FLOAT64 1
+
+// Force UINT64 off if we cannot implement support for it.
+#if defined(VTK_TYPE_USE___INT64) && !defined(VTK_TYPE_CONVERT_UI64_TO_DOUBLE)
+# undef VTK_USE_UINT64
+# define VTK_USE_UINT64 0
+#endif
+
+//--------------------------------------------------------------------------
+
+// Define helper macros to switch types on and off.
+#define vtkTemplateAliasMacroCase(typeN, call)                                \
+  vtkTemplateAliasMacroCase0(typeN, call, VTK_TYPE_SIZED_##typeN)
+#define vtkTemplateAliasMacroCase0(typeN, call, sized)                        \
+  vtkTemplateAliasMacroCase1(typeN, call, sized)
+#define vtkTemplateAliasMacroCase1(typeN, call, sized)                        \
+  vtkTemplateAliasMacroCase2(typeN, call, VTK_USE_##sized)
+#define vtkTemplateAliasMacroCase2(typeN, call, value)                        \
+  vtkTemplateAliasMacroCase3(typeN, call, value)
+#define vtkTemplateAliasMacroCase3(typeN, call, value)                        \
+  vtkTemplateAliasMacroCase_##value(typeN, call)
+#define vtkTemplateAliasMacroCase_0(typeN, call)                              \
+  case VTK_##typeN:                                                           \
+    {                                                                         \
+    vtkGenericWarningMacro("Support for VTK_" #typeN " not compiled.");       \
+    }; break
+#define vtkTemplateAliasMacroCase_1(typeN, call)                              \
+  case VTK_##typeN:                                                           \
+    {                                                                         \
+    typedef vtkTypeTraits<VTK_TYPE_NAME_##typeN>::SizedType VTK_TT; call;     \
+    }; break
+
+// Add "long long" to the template macro if it is enabled.
+#if defined(VTK_TYPE_USE_LONG_LONG)
+# define vtkTemplateAliasMacroCase_ll(typeN, call)                            \
+             vtkTemplateAliasMacroCase(typeN, call);
+#else
+# define vtkTemplateAliasMacroCase_ll(typeN, call)
+#endif
+
+// Add "__int64" to the template macro if it is enabled.
+#if defined(VTK_TYPE_USE___INT64)
+# define vtkTemplateAliasMacroCase_i64(typeN, call)                           \
+             vtkTemplateAliasMacroCase(typeN, call);
+#else
+# define vtkTemplateAliasMacroCase_i64(typeN, call)
+#endif
+
+// Define a macro to dispatch calls to a template instantiated over
+// the aliased scalar types.
+#define vtkTemplateAliasMacro(call)                                           \
+  vtkTemplateAliasMacroCase(DOUBLE, call);                                    \
+  vtkTemplateAliasMacroCase(FLOAT, call);                                     \
+  vtkTemplateAliasMacroCase_ll(LONG_LONG, call)                               \
+  vtkTemplateAliasMacroCase_ll(UNSIGNED_LONG_LONG, call)                      \
+  vtkTemplateAliasMacroCase_i64(__INT64, call)                                \
+  vtkTemplateAliasMacroCase_i64(UNSIGNED___INT64, call)                       \
+  vtkTemplateAliasMacroCase(ID_TYPE, call);                                   \
+  vtkTemplateAliasMacroCase(LONG, call);                                      \
+  vtkTemplateAliasMacroCase(UNSIGNED_LONG, call);                             \
+  vtkTemplateAliasMacroCase(INT, call);                                       \
+  vtkTemplateAliasMacroCase(UNSIGNED_INT, call);                              \
+  vtkTemplateAliasMacroCase(SHORT, call);                                     \
+  vtkTemplateAliasMacroCase(UNSIGNED_SHORT, call);                            \
+  vtkTemplateAliasMacroCase(CHAR, call);                                      \
+  vtkTemplateAliasMacroCase(SIGNED_CHAR, call);                               \
+  vtkTemplateAliasMacroCase(UNSIGNED_CHAR, call)
+
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkafBVImageReader.cpp b/bioimagesuite30_src/Common/vtkafBVImageReader.cpp
new file mode 100644
index 0000000..4eca95e
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkafBVImageReader.cpp
@@ -0,0 +1,390 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkafBVImageReader.h"
+#include "vtkUnsignedShortArray.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkShortArray.h"
+#include "vtkFloatArray.h"
+#include "vtkObjectFactory.h"
+#include "pxutil.h"
+#include "vtkpxImageComponentsToFrames.h"
+#include "vtkImageToStructuredPoints.h"
+#include "vtkStructuredPoints.h"
+#include "vtkPointData.h"
+//------------------------------------------------------------------------------
+vtkafBVImageReader* vtkafBVImageReader::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkafBVImageReader");
+  if(ret)
+    {
+      return (vtkafBVImageReader*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkafBVImageReader;
+}
+
+// Construct object with NULL file prefix; file pattern "%s.%d"; image range 
+// set to (1,1); data origin (0,0,0); data spacing (1,1,1); no data mask;
+// header size 0; and byte swapping turned off.
+//------------------------------------------------------------------------------
+vtkafBVImageReader::vtkafBVImageReader()
+{
+  this->DataDimensions[0] = this->DataDimensions[1] = this->DataDimensions[2] =1;
+  this->DataOrigin[0] = this->DataOrigin[1] = this->DataOrigin[2] = 0.0;
+  this->DataSpacing[0] = this->DataSpacing[1] = this->DataSpacing[2] = 1.0;
+  this->NumTimeFrames=1;
+  
+  this->HeaderSize = 0;
+  this->FileType=2;
+  
+  this->read_volume_ok=0;
+  
+
+  this->Orientation=0; // Axial
+  this->ForceOutputToShort=0;
+}
+//------------------------------------------------------------------------------
+// Read the header information
+// ---------------------------
+int vtkafBVImageReader::ReadHeaderInfo()
+{
+ void *fdf;
+
+  
+ int bytes =0; 
+ short int *headerinfo= new short int[14];
+ float *headerinfo1= new float[2];
+ 
+ fdf=(FILE *)fopen(this->Filename,"rb"); 
+
+ 
+ bytes+=fread(&version,1,sizeof(short int),(FILE *)fdf);
+ 
+ 
+ cout << "version: " << this->version <<endl;
+ 
+ 
+ char temp[]=" ";
+
+ int counter=0;
+ char *filename = new char[100];
+
+ bytes+=fread(&temp[0],1,sizeof(char),(FILE *)fdf); 
+ filename[counter]=temp[0];
+ 
+ 
+ while( true)
+    {
+      counter++; 
+      bytes+=fread(&temp[0],1,sizeof(char),(FILE *)fdf); 
+      
+      filename[counter]=temp[0];
+   
+     
+      if (counter > 3 && temp[0]== '\0') 
+      	break;
+      
+     
+   }
+ this->FMRfilename = new char [counter];
+ 
+ strncpy(this->FMRfilename, filename,counter);
+ this->FMRfilename[counter]='\0';
+ cout <<this->FMRfilename  <<" " << strlen(this->FMRfilename)+1 <<endl;
+ 
+
+ counter=0;
+ bytes+=fread(&temp[0],1,sizeof(char),(FILE *)fdf); 
+ filename[counter]=temp[0];
+
+   
+   while(true )
+   {
+      counter++; 
+      bytes+=fread(&temp[0],1,sizeof(char),(FILE *)fdf); 
+      filename[counter]=temp[0];
+      if (counter > 3 && temp[0] == '\0') 
+	{ 
+	  break;
+	}
+   }
+
+ this->PRTfilename= new char [counter];
+ 
+ strncpy(this->PRTfilename, filename,counter);
+ this->PRTfilename[counter]='\0';
+
+
+ cout <<this->PRTfilename << "  " << strlen(this->PRTfilename)+1 <<endl;
+
+
+ bytes+=fread(&headerinfo[1],1,sizeof(short int)*9,(FILE *)fdf); 
+ bytes+=fread(&headerinfo1[0],1,sizeof(float)*3,(FILE *)fdf); 
+ bytes+=fread(&headerinfo[10],1,sizeof(short int)*2,(FILE *)fdf); 
+
+ this->NumTimeFrames=headerinfo[1];
+ this->NrOfVolumes=headerinfo[1];
+ this->resolution=headerinfo[2];
+ this->XStart=headerinfo[3];
+ this->XEnd=headerinfo[4];
+ this->YStart=headerinfo[5];
+ this->YEnd=headerinfo[6];
+ this->ZStart=headerinfo[7]; 
+ this->ZEnd=headerinfo[8];
+ this->hemodynamicDelay=headerinfo[9];
+ this->TR=headerinfo1[0];
+ this->deltaParam=headerinfo1[1];
+ this->tauParam=headerinfo1[2];
+ this->segment_sz=headerinfo[10];
+ this->segment_offset=headerinfo[11];
+
+ this->HeaderSize=bytes;
+ 
+ this->DataDimensions[0]= (this->XEnd - this->XStart)/this->resolution;
+ this->DataDimensions[1]= (this->YEnd - this->YStart)/this->resolution;
+ this->DataDimensions[2]= (this->ZEnd - this->ZStart)/this->resolution;
+
+ this->DataSpacing[0]=this->resolution;
+ this->DataSpacing[1]=this->resolution;
+ this->DataSpacing[2]=this->resolution;
+ 
+ for (int ii = 0;ii<12;ii++) {
+   cout << ii << " " << headerinfo[ii] <<endl ;
+ }
+
+ for (int i = 0;i<3;i++) {
+   cout << "float information " <<headerinfo1[i] <<endl ;
+ }
+ 
+ cout <<"total bytes in header file " <<bytes <<endl;
+ fclose((FILE *)fdf);
+
+ this->read_volume_ok=1;
+
+ delete [] filename;
+ delete [] headerinfo;
+ 
+ delete [] headerinfo1;
+ return bytes;
+}
+
+
+//------------------------------------------------------------------------------
+int  vtkafBVImageReader::GetNumTimeFrames()
+{
+  return this->NumTimeFrames;
+}
+//------------------------------------------------------------------------------
+vtkDataArray* vtkafBVImageReader::ReadVolume()
+{ 
+  cout << "Reading VOlume" << endl;
+
+  if (this->read_volume_ok==0)
+    {
+      vtkDebugMacro(<<"Not updating");
+      cout << "NOT UPDATING! "<< endl;
+      return NULL;      
+    }
+  
+  if (!this->Filename)
+    return NULL;
+  
+  char* filename=new char[(strlen(this->Filename))+1];
+  strcpy(filename,this->Filename);
+  
+  int numPts = this->DataDimensions[0] * this->DataDimensions[1] * this->DataDimensions[2];
+  
+  vtkDataArray *scalars = NULL;
+  
+  if (FileType==2)
+    {
+      scalars = vtkDataArray::CreateDataArray(VTK_SHORT);
+      scalars->SetNumberOfComponents(NumTimeFrames);
+      scalars->SetNumberOfTuples(numPts);
+    }
+  
+  
+  gzFile fp = gzsuffixopen(filename,"rb");
+  
+  if ( fp==Z_NULL)
+      {
+	vtkErrorMacro(<< "Cannot Open File " << filename );
+	
+	return NULL;
+      }
+
+  this->UpdateProgress(0.0);
+  //  float oldpog=0.0;
+
+  
+  //if (skip>0)
+    gzseek (fp,this->HeaderSize, 0);
+
+  short test;
+
+  for (int voxel=0;voxel<numPts;voxel++)
+    for (int frame=0;frame<NumTimeFrames;frame++)
+      {
+	gzread(fp,&test,2);
+	scalars->SetComponent(voxel,frame,test);
+      }
+
+  gzclose (fp);
+  delete [] filename;
+  
+  this->UpdateProgress(1.0);
+  this->read_volume_ok=0;
+  return scalars;
+}
+//------------------------------------------------------------------------------
+void vtkafBVImageReader::Execute()
+{
+
+  if (this->Filename == NULL) 
+    {
+      vtkErrorMacro(<< "FilePrefix is NULL");
+      return;
+    }
+  
+  
+  if (this->HeaderSize < 0) 
+    {
+      vtkErrorMacro(<< "HeaderSize " << this->HeaderSize << " must be >= 0");
+      return;
+    }
+  
+  int* dim = this->DataDimensions;
+  
+  if (dim[0] <= 0 || dim[1] <= 0) 
+    {
+      vtkErrorMacro(<< "x, y dimensions " << dim[0] << ", " << dim[1] 
+		    << "must be greater than 0.");    
+      return;
+    } 
+  
+  vtkDataArray* tmpScalars = this->ReadVolume();
+  vtkDataArray* newScalars=tmpScalars;
+  int deletenewscalars=0;
+ 
+
+  if (!tmpScalars)
+    {
+      cout << "RETURNING" << endl;
+      return;
+    }
+
+  if (this->ForceOutputToShort==1)
+    {
+      if (newScalars->GetDataType()==VTK_FLOAT)
+	{
+	  newScalars=vtkDataArray::CreateDataArray(VTK_SHORT);
+	  newScalars->DeepCopy(tmpScalars);
+	  deletenewscalars=1;
+	}
+    }
+
+  vtkStructuredPoints* output=this->GetOutput();
+  if (!output) {
+    cout << "output is null" <<endl;
+    return;
+  }
+  int dimensions[3]; 
+  dimensions[0] = this->DataDimensions[0];
+  dimensions[1] = this->DataDimensions[1];
+  dimensions[2] = this->DataDimensions[2];
+  output->SetDimensions(dimensions);
+  output->SetWholeExtent(0,dimensions[0]-1,0,dimensions[1]-1,0,dimensions[2]-1);
+  output->SetExtent(0,dimensions[0]-1,0,dimensions[1]-1,0,dimensions[2]-1);
+  
+  output->SetSpacing((double*)this->DataSpacing);
+  output->SetOrigin((double*)this->DataOrigin);
+
+  output->SetScalarType(newScalars->GetDataType());
+  output->SetNumberOfScalarComponents(newScalars->GetNumberOfComponents());
+  cout << " num of components " << newScalars->GetNumberOfComponents() <<endl;
+  output->GetPointData()->SetScalars(newScalars);
+  
+  if (deletenewscalars)
+    newScalars->Delete();
+
+  tmpScalars->Delete();
+
+  //  int d[3];
+  cout << "END OF EXECUTE!!!" <<endl;
+}
+//------------------------------------------------------------------------------
+void vtkafBVImageReader::ExecuteInformation()
+{
+ 
+  vtkStructuredPoints *output = this->GetOutput();
+  
+  int dim[3];
+  dim[0]=this->DataDimensions[0];
+  dim[1]=this->DataDimensions[1];
+  dim[2]=this->DataDimensions[2];
+  output->SetWholeExtent(0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1);
+  output->SetExtent(0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1);
+  output->SetNumberOfScalarComponents(NumTimeFrames);
+
+  if (this->FileType!=4)
+    output->SetScalarType(VTK_SHORT);
+  else
+    output->SetScalarType(VTK_FLOAT);
+  
+
+}
+
+//------------------------------------------------------------------------------
+int vtkafBVImageReader::Load(const char *file)
+{
+ 
+  cout <<"LOADING....." << file <<endl;
+
+  
+  this->Filename=new char[strlen(file) +1];
+  strcpy(this->Filename,file);
+  int ok=this->ReadHeaderInfo();
+ 
+  if (ok!=0){
+    
+    this->Update();
+      cout << "DEBUG POINT - after update" << endl;
+  }
+  
+  
+  return ok;
+ 
+  
+}
+//------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Common/vtkafBVImageReader.h b/bioimagesuite30_src/Common/vtkafBVImageReader.h
new file mode 100644
index 0000000..3bdfe25
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkafBVImageReader.h
@@ -0,0 +1,167 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkafBVImageReader
+#define __vtkafBVImageReader
+
+#include <stdio.h>
+#include "vtkStructuredPointsReader.h"
+#include "pxutil.h"
+
+//BTX
+class vtkDataArray;
+//ETX
+
+class vtkafBVImageReader : public vtkStructuredPointsReader
+{
+
+public:
+  vtkTypeMacro(vtkafBVImageReader,vtkStructuredPointsReader);
+  static vtkafBVImageReader* New();
+  
+  // Description:
+  // Convenience Routine for analyze images -- simply use Load("fname.hdr")
+  virtual int  Load(const char* fname);
+
+  // Description:
+  // Reads Header first set using SetFilePrefix
+  virtual int  ReadHeaderInfo();
+
+  // Description:
+  // Get the orientation from analyze header 0=axial 1=coronal 2=saggital (default=2)
+  vtkGetMacro(Orientation,int);
+  vtkSetMacro(Orientation,int);
+
+  // Description:
+  // Get the file type 1=bit 2=short 3=unsigned int 4=float
+  vtkGetMacro(FileType,int);
+  vtkSetClampMacro(FileType,int,1,4);
+
+  // Description:
+  // Force the output scalars to have type short
+  vtkGetMacro(ForceOutputToShort,int);
+  vtkSetMacro(ForceOutputToShort,int);
+  vtkBooleanMacro(ForceOutputToShort,int);
+
+  //the following six functions are parameters for the relative positions with a VMR volume (must be 256^3 data set
+  //for Talaraich VTC data
+
+  // Set/Get relative positions
+  vtkGetMacro(XStart,short int);
+
+  // Get/Set relative positions
+  vtkGetMacro(XEnd,short int);
+
+  // Get/Set relative positions
+  vtkGetMacro(YEnd,short int);
+
+  // Get/Set relative positions
+  vtkGetMacro(ZEnd,short int);
+
+  // Get/Set relative positions
+  vtkGetMacro(YStart,short int);
+
+ // Description:
+  // Get/Set relative positions
+  vtkGetMacro(ZStart,short int);
+
+  // Set/Get VTC-resolution 
+  vtkGetMacro(resolution,short int);
+
+  // Set/Get Hemodynamic Delay, simple shift value
+  vtkGetMacro(hemodynamicDelay,short int);
+
+  // Set/Get TR (ms)
+  vtkGetMacro(TR,float);
+
+  // Set/Get delta Parameter in the Hemodynamic function
+  vtkGetMacro(deltaParam,float);
+
+  // Set/Get tau Parameter in the Hemodynamic function
+  vtkGetMacro(tauParam,float);
+
+  // Set/Get Segment size ,used for time course separation
+  vtkGetMacro(segment_sz,short int);
+
+  // Set/Get Segment offset,used for time course separation
+  vtkGetMacro(segment_offset,short int);
+
+  virtual int  GetNumTimeFrames();
+
+protected:
+  //BTX
+  int read_volume_ok;
+  int FileType;
+ 
+
+  int Orientation;
+  int ForceOutputToShort;
+
+  int DataDimensions[3];
+  int NumTimeFrames;
+ 
+  int HeaderSize;
+
+  float DataSpacing[3];
+  float DataOrigin[3];
+
+  short int version;
+  char *Filename;
+  char *FMRfilename;
+  char *PRTfilename;
+  short int NrOfVolumes;
+  short int resolution;
+   short int XStart;
+  short int XEnd;
+  short int YStart;
+  short int YEnd;
+  short int ZStart; 
+  short int ZEnd;
+
+  short int hemodynamicDelay;
+  float TR;
+  float deltaParam;
+  float tauParam;
+  short int segment_sz;
+  short int segment_offset;
+
+  vtkafBVImageReader();
+  virtual void Execute();
+  virtual void ExecuteInformation();
+
+  virtual vtkDataArray* ReadVolume();
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkafBVImageWriter.cpp b/bioimagesuite30_src/Common/vtkafBVImageWriter.cpp
new file mode 100644
index 0000000..933d9b9
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkafBVImageWriter.cpp
@@ -0,0 +1,236 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkafBVImageWriter.h"
+#include "vtkImageData.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxUtil.h"
+#include "vtkImageImport.h"
+#include "pxutil.h"
+#include <assert.h>
+
+
+//------------------------------------------------------------------------------
+vtkafBVImageWriter* vtkafBVImageWriter::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkafBVImageWriter");
+  if(ret)
+      {
+	return (vtkafBVImageWriter*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkafBVImageWriter;
+}
+//------------------------------------------------------------------------------
+vtkafBVImageWriter::vtkafBVImageWriter()
+{
+  this->NumFrames=1;
+ 
+
+  this->resolution=3;
+  this->XStart=57;
+  this->XEnd=231;
+  this->YStart=52;
+  this->YEnd=172;
+  this->ZStart=59;
+  this->ZEnd=197;
+  this->ByteSwap=0;
+  this->Orientation=0; // Axial
+  this->MultipleComponentsAsFrames=1;
+  
+}
+//----------------------------------------------------------------------------
+char * vtkafBVImageWriter::GetFilename(char *which)
+{
+  if (which == "prt" || which == "PRT")
+    return this->PRTfilename;
+  //if (which == "fmr" || which == "FMR")
+    return this->FMRfilename;
+}
+
+
+//----------------------------------------------------------------------------
+void vtkafBVImageWriter::SetFilenames(const char *fmr,const char* prt)
+{
+  this->FMRfilename = new char[strlen (fmr)+1];
+  assert(this->FMRfilename !=0);
+  
+  this->PRTfilename = new char[strlen (prt)+1];
+  assert(this->PRTfilename !=0);
+  
+
+  //strcpy(this->FMRfilename,fmr);
+
+  strncpy(this->FMRfilename,fmr,strlen(fmr)+1);
+  strncpy(this->PRTfilename,prt,strlen(prt)+1);
+   cout << "SET FILENAME" << this->FMRfilename <<endl;
+  cout << "SET FILENAME" << fmr <<endl;
+ 
+  //strcat(this->FMRfilename,'\0');
+ 
+  //strcat(this->PRTfilename,'\0');
+  
+}
+
+//----------------------------------------------------------------------------
+void vtkafBVImageWriter::WriteData()
+{
+  vtkImageData *input=this->GetInput(0);
+
+ cout << "DEBUG- WRITE DATA" <<endl;
+
+if (input==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image To Save");
+	return;
+      }
+  
+ 
+
+  int dim[3];  
+
+  input->GetDimensions(dim);
+
+ 
+  int maxnumcomp=1;
+ 
+  if (this->NumFrames==1 && this->MultipleComponentsAsFrames==1)
+    {
+      maxnumcomp=input->GetNumberOfScalarComponents();
+ 
+    }
+  
+  //int bits=16;
+
+  
+  // Find Min and Max Values 
+
+  vtkDataArray* int_scalars=input->GetPointData()->GetScalars();
+
+  
+
+  char* fname=this->FileName;
+  
+  int sz=dim[0]*dim[1];
+  long bytes=0;
+
+  void *fdf;
+
+  fdf=(FILE *)fopen(fname,"wb"); 
+  
+
+ short int *headerinfo1= new short int[8];
+ float *headerinfo2= new float[2];
+ short int *headerinfo3= new short int[1];
+ 
+ this->NumFrames=input->GetNumberOfScalarComponents();
+ short int version=(short int)2;
+ //this->NrOfVolumes = this->NumFrames/this->slices;
+ headerinfo1[3-3]=(short int)this->NumFrames; //NrOfVolumes;
+ headerinfo1[4-3]=(short int)this->resolution;
+ headerinfo1[5-3]=(short int)this->XStart;
+ headerinfo1[6-3]=(short int)this->XEnd;
+ headerinfo1[7-3]=(short int)this->YStart;
+ headerinfo1[8-3]=(short int)this->YEnd;
+ headerinfo1[9-3]=(short int)this->ZStart;
+ headerinfo1[10-3]=(short int)this->ZEnd;
+ headerinfo1[11-3]=(short int)this->hemodynamicDelay;
+
+ headerinfo2[0]=(short int)this->TR;
+ headerinfo2[1]=(short int)this->deltaParam;
+ headerinfo2[2]=(short int)this->tauParam;
+ headerinfo3[0]=(short int)this->segment_sz;
+ headerinfo3[1]=(short int)this->segment_offset;
+
+ bytes += fwrite(&version,1,2,(FILE *)fdf);
+ //cout << "size " << sizeof(this->FMRfilename) <<endl;
+ //cout << "size " << sizeof(this->PRTfilename) <<endl;
+ bytes += fwrite(this->FMRfilename,1,strlen(this->FMRfilename)+1,(FILE *)fdf);
+
+ bytes += fwrite(this->PRTfilename,1,strlen(this->PRTfilename)+1,(FILE *)fdf);
+
+ bytes += fwrite(&headerinfo1[0],1,sizeof(short int)*9,(FILE *)fdf);
+ bytes += fwrite(&headerinfo2[0],1,sizeof(float)*3,(FILE *)fdf);
+ bytes += fwrite(&headerinfo3[0],1,sizeof(short int)*2,(FILE *)fdf);
+
+ cout << "BYTES WROTE  HEADER : " << bytes <<endl;
+ 
+ cout << input->GetNumberOfScalarComponents() <<endl;
+ cout << "DIMENSIONS" << dim[0] <<dim[1] <<dim[2] << " " << NumFrames << endl;
+ 
+ int total_voxels=dim[1]*dim[0]*dim[2];
+ //WRITE THE DATA!
+ if (fdf)
+    {
+      
+      for (int voxel=0;voxel<total_voxels;voxel++)
+	{
+	  unsigned short* temp = new unsigned short[sz];
+	  for (int comp=0;comp<this->NumFrames;comp++)
+	    {
+	      temp[0]=(unsigned short)int_scalars->GetComponent(voxel,comp);
+	      bytes+=fwrite(&temp[0],1,2,(FILE *)fdf);
+	      // cout << "within the loop" <<endl;
+	      // int offset=voxel*sz;
+	      //for (int k=0;k<sz;k++)
+	      //temp[k]=(unsigned short)int_scalars->GetComponent(k+offset,comp);
+	      
+	      // bytes += fwrite(&temp[0],1,sz*2,(FILE *)fdf);
+	    } 
+	  delete [] temp;
+	}
+    }
+ 
+ fclose((FILE *)fdf);
+ 
+
+ cout << "DEBUG- end WRITE DATA- bytes wrote: " << bytes <<endl;
+ delete [] fname;
+  //delete hdr;
+
+}
+
+//==============================================================================================
+void vtkafBVImageWriter::Save(const char* fname)
+{ 
+  cout << "WRITING...." <<endl;
+
+  if (fname!=NULL)
+      {
+	 cout << "DEBUG- save" <<endl;
+	this->SetFileName(fname);
+	this->WriteData();
+      }
+}
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkafBVImageWriter.h b/bioimagesuite30_src/Common/vtkafBVImageWriter.h
new file mode 100644
index 0000000..09ecee0
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkafBVImageWriter.h
@@ -0,0 +1,176 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkafBVImageWriter_h
+#define __vtkafBVImageWriter_h
+
+#include "vtkStructuredPointsWriter.h"
+
+class vtkafBVImageWriter : public vtkStructuredPointsWriter
+{
+public:
+  static vtkafBVImageWriter *New();
+  vtkTypeMacro(vtkafBVImageWriter,vtkStructuredPointsWriter);
+
+
+  // Convenience Routine: simply use Save("fname.hdr")
+  void Save(const char* fname);
+
+
+  // Set/Get Number of Time frames in case of 4D Images
+  vtkGetMacro(NumFrames,int);
+  vtkSetMacro(NumFrames,int);
+
+
+  // Save byte-swapped if needed
+  vtkGetMacro(ByteSwap,int);
+  vtkSetClampMacro(ByteSwap,int,0,1);
+  vtkBooleanMacro(ByteSwap, int);
+
+
+  // Save orientation 0=axial 1=coronal 2=saggital (default=2)
+  vtkGetMacro(Orientation,int);
+  vtkSetClampMacro(Orientation,int,0,2);
+
+
+  // SaveMultipleComponents As Frames 
+  vtkGetMacro(MultipleComponentsAsFrames,int);
+  vtkSetClampMacro(MultipleComponentsAsFrames,int,0,1);
+  vtkBooleanMacro(MultipleComponentsAsFrames, int);
+
+
+  //the following six functions are parameters for the relative positions with a VMR volume (must be 256^3 data set
+  //for Talaraich VTC data
+
+  // Set/Get relative positions
+  vtkGetMacro(XStart,short int);
+  vtkSetMacro(XStart,short int);
+
+ // 
+  vtkGetMacro(slices,int);
+  vtkSetMacro(slices,int);
+  //
+  vtkGetMacro(NrOfVolumes,short int);
+  vtkSetMacro(NrOfVolumes,short int);
+
+  // Get/Set relative positions
+  vtkGetMacro(XEnd,short int);
+  vtkSetMacro(XEnd,short int);
+
+
+  // Get/Set relative positions
+  vtkGetMacro(YEnd,short int);
+  vtkSetMacro(YEnd,short int);
+
+  // Get/Set relative positions
+  vtkGetMacro(ZEnd,short int);
+  vtkSetMacro(ZEnd,short int);
+
+
+  // Get/Set relative positions
+  vtkGetMacro(YStart,short int);
+  vtkSetMacro(YStart,short int);
+
+ // Description:
+  // Get/Set relative positions
+  vtkGetMacro(ZStart,short int);
+  vtkSetMacro(ZStart,short int);
+
+
+  // Set/Get VTC-resolution 
+  vtkGetMacro(resolution,short int);
+  vtkSetMacro(resolution,short int);
+
+
+  // Set/Get  FMR and PRT filenames
+  void SetFilenames (const char *, const char *);
+  char * GetFilename (char *);
+
+  
+ // Set/Get Hemodynamic Delay, simple shift value
+  vtkGetMacro(hemodynamicDelay,short int);
+  vtkSetMacro(hemodynamicDelay,short int);
+
+ // Set/Get TR (ms)
+  vtkGetMacro(TR,float);
+  vtkSetMacro(TR,float);
+
+ // Set/Get delta Parameter in the Hemodynamic function
+  vtkGetMacro(deltaParam,float);
+  vtkSetMacro(deltaParam,float);
+
+ // Set/Get tau Parameter in the Hemodynamic function
+  vtkGetMacro(tauParam,float);
+  vtkSetMacro(tauParam,float);
+
+ // Set/Get Segment size ,used for time course separation
+  vtkGetMacro(segment_sz,short int);
+  vtkSetMacro(segment_sz,short int);
+
+// Set/Get Segment offset,used for time course separation
+  vtkGetMacro(segment_offset,short int);
+  vtkSetMacro(segment_offset,short int);
+protected:
+  //BTX
+  vtkafBVImageWriter();
+  ~vtkafBVImageWriter() {};
+  
+  
+  void WriteData();
+ 
+  char *FMRfilename; 
+  char *PRTfilename; 
+  int slices;
+  short int NrOfVolumes;
+  short int resolution;
+  short int XStart;
+  short int XEnd;
+  short int YStart;
+  short int YEnd;
+  short int ZStart; 
+  short int ZEnd;
+  short int hemodynamicDelay;
+  float TR;
+  float deltaParam;
+  float tauParam;
+  short int segment_sz;
+  short int segment_offset;
+
+  int NumFrames;
+  int ByteSwap;
+  int Orientation;
+  int MultipleComponentsAsFrames;
+  //ETX
+};
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Common/vtkbisCylinderSource.cpp b/bioimagesuite30_src/Common/vtkbisCylinderSource.cpp
new file mode 100644
index 0000000..19a4e73
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisCylinderSource.cpp
@@ -0,0 +1,255 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkbisCylinderSource.cxx,v $
+
+  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 "vtkbisCylinderSource.h"
+
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkObjectFactory.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkPolyData.h"
+#include "vtkTransform.h"
+#include "vtkCellArray.h"
+
+#include <math.h>
+
+vtkCxxRevisionMacro(vtkbisCylinderSource, "$Revision: 1.74 $");
+vtkStandardNewMacro(vtkbisCylinderSource);
+
+//----------------------------------------------------------------------------
+// Construct with default resolution 6, height 1.0, radius 0.5, and capping
+// on.
+vtkbisCylinderSource::vtkbisCylinderSource(int res)
+{
+
+  res = (res < 3 ? 3 : res);
+  this->Resolution = res;
+}
+
+//----------------------------------------------------------------------------
+int vtkbisCylinderSource::RequestData(
+  vtkInformation *vtkNotUsed(request),
+  vtkInformationVector **vtkNotUsed(inputVector),
+  vtkInformationVector *outputVector)
+{
+  // get the info objects
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  
+  // get the output
+  vtkPolyData *output = vtkPolyData::SafeDownCast(
+  outInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+  double angle;
+  int numLines, numPolys, numPts;
+  double x[3], xbot;
+  int i;
+  vtkIdType pts[VTK_CELL_SIZE];
+  vtkPoints *newPoints; 
+  vtkCellArray *newLines=0;
+  vtkCellArray *newPolys=0;
+ 
+  // for streaming
+  int piece;
+  int numPieces;
+  int maxPieces;
+  int start, end;
+  
+  piece = output->GetUpdatePiece();
+  if (piece >= this->Resolution && !(piece == 0 && this->Resolution == 0))
+    {
+    return 1;
+    }
+  numPieces = output->GetUpdateNumberOfPieces();
+  maxPieces = this->Resolution;
+  if (numPieces > maxPieces)
+    {
+    numPieces = maxPieces;
+    }
+  if (piece >= maxPieces)
+    {
+    // Super class should do this for us, 
+    // but I put this condition in any way.
+    return 1;
+    }
+  start = maxPieces * piece / numPieces;
+  end = (maxPieces * (piece+1) / numPieces) - 1;
+   
+  vtkDebugMacro("ConeSource Executing");
+  
+  if ( this->Resolution )
+    {
+    angle = 2.0*3.141592654/this->Resolution;
+    }
+  else
+    {
+    angle = 0.0;
+    }
+
+    numPts = this->Resolution * 2; 
+    numPolys = end - start + 3; 
+
+  newPolys = vtkCellArray::New();
+  newPolys->Allocate(newPolys->EstimateSize(numPolys,this->Resolution));
+
+  newPoints = vtkPoints::New();
+  newPoints->SetDataTypeToFloat(); //used later during transformation
+  newPoints->Allocate(numPts);
+
+  xbot = -this->Height / 2.0;
+
+
+ //create Resolution triangles and single cap
+ // create the bottom.
+    if ( this->Capping )
+      {
+      	for (i=0; i < this->Resolution; i++) 
+        {
+        x[0] = xbot;
+        x[1] = this->Radius * cos (i*angle);
+        x[2] = this->Radius * sin (i*angle);
+        // Reverse the order
+        pts[this->Resolution - i - 1] = newPoints->InsertNextPoint(x);
+        }
+      newPolys->InsertNextCell(this->Resolution,pts);
+      
+      // creating top 
+       
+         for (i=0; i < this->Resolution; i++) 
+        {
+        x[0] = this->Height / 2.0;
+        x[1] = this->Radius * cos (i*angle);
+        x[2] = this->Radius * sin (i*angle);
+        // Reverse the order
+        pts[this->Resolution - i - 1] = newPoints->InsertNextPoint(x);
+        }
+      newPolys->InsertNextCell(this->Resolution,pts);
+    }    
+    else{
+        for (i=0; i < this->Resolution; i++) 
+        {
+        	x[0] = this->Height / 2.0;
+        	x[1] = this->Radius * cos (i*angle);
+        	x[2] = this->Radius * sin (i*angle);
+        	// Reverse the order
+        	pts[this->Resolution - i - 1] = newPoints->InsertNextPoint(x);
+       	}
+       	
+        for (i=0; i < this->Resolution; i++) 
+        {	
+        	x[0] = -this->Height / 2.0;
+        	x[1] = this->Radius * cos (i*angle);
+        	x[2] = this->Radius * sin (i*angle);
+        	// Reverse the order
+        	pts[this->Resolution - i - 1] = newPoints->InsertNextPoint(x);
+        }
+      }
+      
+      // Creating the polygons (sides of the cylinder) connecting the top and bottom disks
+      for (i=start; i <= end; i++) 
+        {
+        pts[0] = end + i + 1; 
+        pts[1] = i;
+        pts[2] = i+1;
+        pts[3] = end + i + 2; 
+        
+        if (pts[2] == this->Resolution)
+        {
+	          pts[2] = start;
+	          pts[3] = end + 1; 
+        }          
+
+        newPolys->InsertNextCell(4,pts);
+        }
+
+
+  // A non-default origin and/or direction requires transformation
+  //
+  if ( this->Center[0] != 0.0 || this->Center[1] != 0.0 || 
+       this->Center[2] != 0.0 || this->Direction[0] != 1.0 || 
+       this->Direction[1] != 0.0 || this->Direction[2] != 0.0 )
+    {
+    vtkTransform *t = vtkTransform::New();
+    t->Translate(this->Center[0], this->Center[1], this->Center[2]);
+    double vMag = vtkMath::Norm(this->Direction);
+    if ( this->Direction[0] < 0.0 && 
+         this->Direction[1] == 0.0 && 
+         this->Direction[2] == 0.0 )
+      {
+      // just flip x
+      t->RotateWXYZ(180.0,0,1,0);
+      }
+    else
+      {
+      t->RotateWXYZ(180.0, (this->Direction[0]+vMag)/2.0,
+                    this->Direction[1]/2.0, this->Direction[2]/2.0);
+      }
+    float *ipts=
+      static_cast<vtkFloatArray *>(newPoints->GetData())->GetPointer(0);
+    for (i=0; i<numPts; i++, ipts+=3)
+      {
+      t->TransformPoint(ipts,ipts);
+      }
+    
+    t->Delete();
+    }
+  
+  // Update ourselves
+  //
+  output->SetPoints(newPoints);
+  newPoints->Delete();
+
+  if ( newPolys )
+    {
+    newPolys->Squeeze(); // we may have estimated size; reclaim some space
+    output->SetPolys(newPolys);
+    newPolys->Delete();
+    }
+  else
+    {
+    output->SetLines(newLines);
+    newLines->Delete();
+    }
+
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkbisCylinderSource.h b/bioimagesuite30_src/Common/vtkbisCylinderSource.h
new file mode 100644
index 0000000..0636cb3
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisCylinderSource.h
@@ -0,0 +1,85 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkbisCylinderSource.h,v $
+
+  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 vtkbisCylinderSource - generate polygonal cone 
+// .SECTION Description
+// vtkbisCylinderSource creates a cylinder centered at a specified point and pointing in
+// a specified direction. (By default, the center is the origin and the
+// direction is the x-axis.) Depending upon the resolution of this object,
+// different representations are created. If resolution=0 a line is created;
+// if resolution=1, a single triangle is created; if resolution=2, two
+// crossed triangles are created. For resolution > 2, a 3D cylinder (with
+// resolution number of sides) is created. It also is possible to control
+// whether the bottom of the cylinder is capped with a (resolution-sided)
+// polygon, and to specify the height and eradius of the cylinder.
+
+#ifndef __vtkbisCylinderSource_h
+#define __vtkbisCylinderSource_h
+
+#include "vtkConeSource.h"
+
+class  vtkbisCylinderSource : public vtkConeSource 
+{
+public:
+  vtkTypeRevisionMacro(vtkbisCylinderSource,vtkConeSource);
+
+
+  // Description:
+  // Construct with default resolution 6, height 1.0, radius 0.5, and
+  // capping on. The cone is centered at the origin and points down
+  // the x-axis.
+  static vtkbisCylinderSource *New();
+
+
+protected:
+  vtkbisCylinderSource(int res=6);
+
+  virtual int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
+  
+private:
+  vtkbisCylinderSource(const vtkbisCylinderSource&);  // Not implemented.
+  void operator=(const vtkbisCylinderSource&);  // Not implemented.
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkbisDICOMReader.cpp b/bioimagesuite30_src/Common/vtkbisDICOMReader.cpp
new file mode 100644
index 0000000..230ca14
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisDICOMReader.cpp
@@ -0,0 +1,503 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkbisDICOMReader.h"
+#include "vtkMatrix4x4.h"
+#include "vtkMath.h"
+#include "gdcmImageReader.h"
+#include "gdcmDataElement.h"
+#include "gdcmByteValue.h"
+#include "gdcmSwapper.h"
+#include "gdcmUnpacker12Bits.h"
+#include "gdcmRescaler.h"
+#include "gdcmOrientation.h"
+#include "gdcmImageChangePlanarConfiguration.h"
+#include <vtkObjectFactory.h>
+#include <vtkstd/vector>
+#include <vtkstd/string>
+#include "igtl_types.h"
+#include "sstream"
+
+vtkCxxRevisionMacro(vtkbisDICOMReader, "$Revision: 1.18.2.4 $");
+vtkStandardNewMacro(vtkbisDICOMReader);
+
+inline const char *GetStringValueFromTag_BIS(const gdcm::Tag& t, const gdcm::DataSet& ds)
+{
+  static std::string buffer;
+  buffer = "";  // cleanup previous call
+
+
+  if( ds.FindDataElement( t ) )
+    {
+      const gdcm::DataElement& de = ds.GetDataElement( t );
+      const gdcm::ByteValue *bv = de.GetByteValue();
+
+      if( bv ) // Can be Type 2
+	{
+	  buffer = std::string( bv->GetPointer(), bv->GetLength() );
+	}
+    }
+
+  // Since return is a const char* the very first \0 will be considered
+  return buffer.c_str();
+}
+
+inline double GetValueFromTag_BIS(const gdcm::Tag& t, const gdcm::DataSet& ds)
+{
+  static std::string buffer;
+  buffer = "";  // cleanup previous call
+
+
+  if( ds.FindDataElement( t ) )
+    {
+    const gdcm::DataElement& de = ds.GetDataElement( t );
+    const gdcm::ByteValue *bv = de.GetByteValue();
+    if( bv ) // Can be Type 2
+      {
+      buffer = std::string( bv->GetPointer(), bv->GetLength() );
+      // Will be padded with at least one \0
+      }
+    }
+
+
+  // Since return is a const char* the very first \0 will be considered
+  return atof(buffer.c_str());
+}
+// -------------------------------------------------------------------------------------------------------------------
+inline int GetIntValueFromTag_BIS(const gdcm::Tag& t, const gdcm::DataSet& ds)
+{
+  int val=0;
+
+  if( ds.FindDataElement( t ) )
+    {
+    const gdcm::DataElement& de = ds.GetDataElement( t );
+    const gdcm::ByteValue *bv = de.GetByteValue();
+    if( bv ) // Can be Type 2
+      {
+	if (bv->GetLength()<4)
+	  {
+	    const char* cc=bv->GetPointer();
+	    for (int i=0;i<bv->GetLength();i++)
+	      {
+		val+=int(int(cc[i])*pow(double(256.0),i));
+		//		fprintf(stderr,"i=%d, int(cc[i])=%d val=%d\n",i,int(cc[i]),val);
+	      }
+	  }
+      }
+    }
+
+  return val;
+}
+
+inline double GetDoubleValueFromTag_BIS(const gdcm::Tag& t, const gdcm::DataSet& ds,int offset)
+{
+  int val=0;
+
+  if( ds.FindDataElement( t ) )
+    {
+      const gdcm::DataElement& de = ds.GetDataElement( t );
+      const gdcm::ByteValue *bv = de.GetByteValue();
+      if( bv ) // Can be Type 2
+	{
+	  const char* cc=bv->GetPointer();
+	  double a=(double)cc[offset*4];
+	  return a;
+	}
+    }
+
+  return 0.0;
+}
+
+// -------------------------------------------------------------------------------------------------------------------
+
+vtkbisDICOMReader::vtkbisDICOMReader()
+{
+  this->ReferenceTime=NULL;
+  this->StudyUID=NULL;
+  this->SeriesUID=NULL;
+  this->PName=NULL;
+  this->ReferenceTime=NULL;
+  this->SetReferenceTime("");
+  this->SetStudyUID("None");
+  this->SetSeriesUID("None");
+  this->SetPName("None");
+  this->CreateNIFTIHeader=1;
+  this->ImageHeader=NULL;
+  this->ZPosition=0.0;
+  this->TimeFrame=0.0;
+  this->FlipZ=0;
+  this->IsMosaic=0;
+  this->MosaicWidth=0;
+  this->MosaicHeight=0;
+  this->MosaicDepth=0;
+  this->AddExtensions=1;
+  this->DWIMode=0;
+  this->DWIBValue=0.0;
+  this->DWIDirections[0]=0.0;
+  this->DWIDirections[1]=0.0;
+  this->DWIDirections[2]=0.0;
+}
+
+vtkbisDICOMReader::~vtkbisDICOMReader()
+{
+  delete [] this->ReferenceTime;
+  delete [] this->StudyUID;
+  delete [] this->SeriesUID;
+  delete [] this->PName;
+
+  if (this->ImageHeader)
+    this->ImageHeader->Delete();
+
+}
+
+void bis_Tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters )
+{
+    // Skip delimiters at beginning.
+    std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
+    // Find first "non-delimiter".
+    std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
+
+    while (std::string::npos != pos || std::string::npos != lastPos)
+    {
+        // Found a token, add it to the vector.
+        tokens.push_back(str.substr(lastPos, pos - lastPos));
+        // Skip delimiters.  Note the "not_of"
+        lastPos = str.find_first_not_of(delimiters, pos);
+        // Find next "non-delimiter"
+        pos = str.find_first_of(delimiters, lastPos);
+    }
+}
+
+
+void vtkbisDICOMReader::FillMedicalImageInformation(const gdcm::ImageReader &reader)
+{
+  vtkbisGDCMImageReader::FillMedicalImageInformation(reader);
+
+  const gdcm::File &file = reader.GetFile();
+  const gdcm::DataSet &ds = file.GetDataSet();
+
+
+  const char* s=GetStringValueFromTag_BIS( gdcm::Tag(0x0054,0x1300), ds);
+  if (strlen(s)>0)
+    this->SetReferenceTime(s);
+
+  //  fprintf(stderr,"time=%s\n",s);
+  
+  this->SetStudyUID(GetStringValueFromTag_BIS( gdcm::Tag(0x0020,0x000d), ds));
+  this->SetSeriesUID(GetStringValueFromTag_BIS( gdcm::Tag(0x0020,0x000e), ds));
+  this->SetTimeFrame(GetValueFromTag_BIS( gdcm::Tag(0x0020,0x0012), ds));
+  this->SetPName(GetStringValueFromTag_BIS( gdcm::Tag(0x0008,0x0090), ds));
+
+  
+  //   Mosaic Tag
+  //  0051,1016
+
+  /*(0008,0081) ST [1Gilbert Street, New Haven  //0EE9E0//, Boston, 06520-8043, US]         # 62,1 Institution Address
+(0018,1310) US 64\0\0\64                                          # 8,4 Acquisition Matrix
+(0019,100a) US 19                                                 # 2,1 NumberOfImagesInMosaic
+(0028,0002) US 1                                                  # 2,1 Samples per Pixel
+(0028,0010) US 320                                                # 2,1 Rows
+(0028,0011) US 320                                                # 2,1 Columns
+(0028,0100) US 16                                                 # 2,1 Bits Allocated
+(0028,0101) US 12                                                 # 2,1 Bits Stored
+(0028,0102) US 11                                                 # 2,1 High Bit
+(0028,0103) US 0                                                  # 2,1 Pixel Representation
+(0028,0106) US 0                                                  # 2,1 Smallest Image Pixel Value
+(0028,0107)*/
+    //    fprintf(stderr,"Add = %d\n",GetIntValueFromTag_BIS( gdcm::Tag(0x0019,0x100A), ds));
+
+
+  //  fprintf(stderr,"mname3=%d\n",dp);
+
+  std::string  mname=GetStringValueFromTag_BIS( gdcm::Tag(0x0051,0x1016), ds);
+
+
+
+  std::string::size_type foundmos=mname.find("MOSAIC");
+  this->IsMosaic=0;      this->MosaicWidth=0;      this->MosaicHeight=0; this->MosaicDepth=0;
+
+  if (std::string::npos != foundmos)
+    {
+      std::string  mname2=GetStringValueFromTag_BIS( gdcm::Tag(0x0051,0x100b), ds);
+
+
+      std::vector<std::string> v; bis_Tokenize(mname2,v,"*");
+      if(v.size()==2) 
+	{
+	  this->MosaicWidth=atoi(v[0].c_str());
+	  this->MosaicHeight=atoi(v[1].c_str());
+	  this->IsMosaic=1;
+	}
+
+      int dp=GetIntValueFromTag_BIS( gdcm::Tag(0x0019,0x100a), ds);
+      if (dp>0)
+	this->MosaicDepth=dp;
+      /*fprintf(stderr,"Mname=%s . %d x %d x %d  ismosaic=%d other=%s,\n",mname.c_str(),
+	      this->MosaicWidth,this->MosaicHeight,this->MosaicDepth,
+	      this->IsMosaic,mname2.c_str());*/
+    }
+
+
+  std::string directional=GetStringValueFromTag_BIS(gdcm::Tag(0x0019,0x100D),ds);
+  std::string::size_type founddir=directional.find("DIRECTIONAL");
+  std::string::size_type foundnone=directional.find("NONE");
+
+  this->DWIMode=0;
+  if (std::string::npos != foundnone)
+    {
+      this->DWIMode=1;
+      this->DWIDirections[0]=0.0;
+      this->DWIDirections[1]=0.0;
+      this->DWIDirections[2]=0.0;
+      //      fprintf(stderr,"Baseline  DWI=%s\n",directional.c_str());
+    }
+  else if (std::string::npos != founddir)
+    {
+      this->DWIMode=2;
+      double dir[3];
+      const gdcm::DataElement& dirnorm = ds.GetDataElement( gdcm::Tag(0x0019,0x100e));
+      const gdcm::ByteValue *dirval = dirnorm.GetByteValue();
+      double *v = (double*)dirval->GetPointer();
+      for (int ia=0;ia<=2;ia++)
+	this->DWIDirections[ia]=v[ia];
+
+      std::string bvalstr=GetStringValueFromTag_BIS(gdcm::Tag(0x0019,0x100c),ds);
+      this->DWIBValue=atof(bvalstr.c_str());
+      //      fprintf(stderr,"BValue=%f or %s\n",this->DWIBValue,bvalstr.c_str());
+    }
+  else
+    {
+      //      fprintf(stderr,"Non DWI=%s\n",directional.c_str());
+    }
+  
+
+  
+  // This is the big mes from here on ....
+  double pos[3]; this->GetImagePositionPatient(pos);
+  double orient[6];  this->GetImageOrientationPatient(orient);
+  gdcm::Orientation::OrientationType tp = gdcm::Orientation::GetType(orient);
+  const char *label = gdcm::Orientation::GetLabel( tp );
+
+  //  fprintf(stderr,"Pos=%f,%f,%f\n",pos[0],pos[1],pos[2]);
+  this->X0=pos[0];
+  this->Y0=pos[1];
+  this->Z0=pos[2];
+
+  double x[3],y[3],z[3];
+  // Issues .....
+  // DICOM is rotated 180 degrees with respect to NIFTI (i.e. x=-x, y=-y)
+  // BUT VTK Flips the Y-axis
+  // Hence flip x is all that is needed for axial images!
+  //
+  // For Coronal/Sagittal God help you
+  // Sagittal
+  
+  for (int ia=0;ia<=2;ia++)
+    {
+      x[ia]=orient[ia];
+      y[ia]=orient[ia+3];
+    }
+
+
+  vtkMath::Normalize(x);
+  vtkMath::Normalize(y);
+  vtkMath::Cross(x,y,z);
+
+  // Compliance with VTK Flipping
+  // Flip X, Y is flipped already
+  if (tp==3)
+    {
+      // Saggital
+      for (int ia=0;ia<=2;ia++)
+	{
+	  y[ia]=-y[ia];
+	  x[ia]=-x[ia];
+	}
+      pos[0]=-pos[0];
+      this->ZPosition=pos[0];
+      if(z[0]<0.0)
+	this->ZPosition=-pos[0];
+
+    }
+  else if (tp==2)
+    {
+      // Coronal
+      for (int ia=0;ia<=2;ia++)
+	{
+	  x[ia]=-x[ia];
+	  y[ia]=-y[ia];
+	}
+      pos[1]=-pos[1];
+
+      this->ZPosition=pos[1];
+      if (z[1]<0.0)
+	this->ZPosition=-pos[1];
+    }
+
+  else
+    {
+      // Axial
+      // Axial      
+      for (int ia=0;ia<=2;ia++)
+	x[ia]=-x[ia];
+      this->ZPosition=pos[2];
+      if (z[2]<0.0)
+	this->ZPosition=-pos[2];
+    }
+
+  //  if (this->CreateNIFTIHeader)
+  //    fprintf(stdout,"tp=%d label=%s (%.2f,%.2f,%.2f) x=(%.2f,%.2f,%.2f) y=(%.2f,%.2f,%.2f) z(NFT)=(%.2f,%.2f,%.2f)\n",tp,label,pos[0],pos[1],pos[2],x[0],x[1],x[2],y[0],y[1],y[2],z[0],z[1],z[2]);
+  
+  
+
+  double zfactor=1;
+  if (this->FlipZ)
+    zfactor=-1.0;
+  
+  /*  if (this->CreateNIFTIHeader)
+    {
+      fprintf(stdout,"\n pos=%.2f,%.2f,%.2f, or=%.2f,%.2f,%.2f \n",
+	      pos[0],pos[1],pos[2],
+	      orient[0],orient[1],orient[2]);
+      if (zfactor)
+	for (int ia=0;ia<=2;ia++)
+	  z[ia]=zfactor*z[ia];
+      fprintf(stdout,"x=%.2f,%.2f,%.2f, y=%.2f,%.2f,%.2f z=%.2f,%.2f,%.2f  Zpos=%.4f\n",
+	      x[0],x[1],x[2],
+	      y[0],y[1],y[2],
+	      z[0],z[1],z[2],
+	      this->ZPosition);
+	      }*/
+  
+  
+  if (!this->CreateNIFTIHeader)
+    return;
+
+  if (this->ImageHeader!=NULL)
+    this->ImageHeader->Delete();
+
+  this->ImageHeader=vtkbisImageHeader::New();
+  this->ImageHeader->ResetFields();
+
+  nifti_1_header* header=this->ImageHeader->GetRawHeader();
+  vtkbisNIFTIExtensionsList* extensions=this->ImageHeader->GetExtensions();
+
+  // Set the Dimensions
+  //  for (int ia=0;ia<8;ia++) header->dim[ia]=0;
+  int ext[6];  this->GetDataExtent(ext);
+  for (int ia=0;ia<=2;ia++)
+    header->dim[ia+1]=ext[ia*2+1]-ext[ia*2]+1;
+
+  header->dim[4]=this->GetNumberOfScalarComponents();
+  
+  //
+  int datatype=this->GetDataScalarType();
+  header->datatype=vtkbisImageHeader::GetNIFTIDataType(datatype);
+  header->bitpix=vtkbisImageHeader::GetBitPix(datatype);
+
+  header->slice_start=0;   /*!< First slice index.    */  /* short dim_un0;       */
+
+    /*!< Grid spacings.        */  /* float pixdim[8];     */
+  double sp[3]; this->GetDataSpacing(sp);
+
+  //  if (this->IsMosaic)
+    //    fprintf(stderr,"Data Spacing= %.3f,%.3f,%.3f (%.3f)\n",sp[0],sp[1],sp[2],this->ForceZSpacing);
+
+  if (fabs(this->ForceZSpacing)<0.00001)
+    sp[2]=this->ForceZSpacing;
+
+  /*  for (int ia=1;ia<=3;ia++) 
+      header->pixdim[ia]=1.0;//sp[ia-1];*/
+
+
+  
+  header->scl_slope=this->GetScale();
+  header->scl_inter=this->GetShift();
+
+  //  fprintf(stderr,"DICOM Shift=%.2f\t, scale=%.2f\n",header->scl_inter,header->scl_slope);
+
+  strcpy(header->descrip,"bisImageHeader from DICOM");   /*!< any text you like.    */  /* char descrip[80];    */
+  strcpy(header->aux_file,"none");  /*!< auxiliary filename.   */  /* char aux_file[24];   */
+  
+  header->qform_code=0 ;   /*!< NIFTI_XFORM_* code.   */  /*-- all ANALYZE 7.5 ---*/
+  header->sform_code=1 ;   /*!< NIFTI_XFORM_* code.   */  /*   fields below here  */
+  /*   are replaced       */
+  header->quatern_b=0.0 ;    /*!< Quaternion b param.   */
+  header->quatern_c=0.0 ;    /*!< Quaternion c param.   */
+  header->quatern_d=0.0 ;    /*!< Quaternion d param.   */
+  header->qoffset_x=0.0 ;    /*!< Quaternion x shift.   */
+  header->qoffset_y=0.0 ;    /*!< Quaternion y shift.   */
+  header->qoffset_z=0.0 ;    /*!< Quaternion z shift.   */
+
+  header->srow_x[0]=x[0]*sp[0];
+  header->srow_x[1]=y[0]*sp[1];
+  header->srow_x[2]=z[0]*sp[2];
+
+  header->srow_y[0]=x[1]*sp[0];
+  header->srow_y[1]=y[1]*sp[1];
+  header->srow_y[2]=z[1]*sp[2];
+
+  header->srow_z[0]=x[2]*sp[0];
+  header->srow_z[1]=y[2]*sp[1];
+  header->srow_z[2]=z[2]*sp[2];
+  
+  header->srow_x[3]=zfactor*pos[0];
+  header->srow_y[3]=zfactor*pos[1];
+  header->srow_z[3]=zfactor*pos[2];
+
+  header->intent_name[0]=(char)0;
+  strcpy(header->magic,"ni1\0");
+  this->ImageHeader->MakeStoredHeaderValid();
+
+
+  // Can we do this here
+  if (this->AddExtensions)
+    {
+      std::stringstream s;
+      s << "Original DICOM Header\n";
+      s << "Study UID " << this->StudyUID << "\n";
+      s << "Series UID " << this->SeriesUID << "\n";
+      s << "PNAME " << this->PName << "\n";
+
+      const gdcm::Image &image = reader.GetImage();
+      image.Print(s);
+
+      if (this->IsMosaic)
+	{
+	  s << "Original Image was Siemens Mosaic (fMRI)\n";
+	  s << "Mosaic Image Dimensions " << this->MosaicWidth << "x" << this->MosaicHeight <<"\n";
+	  s << "Mosaic Number of Slices " << this->MosaicDepth << "\n";
+	}
+      s << "End of Original DICOM Header\n";
+      this->ImageHeader->AddComment(s.str().c_str());
+
+    }
+      
+  return;
+  //  fprintf(stdout,"\n\n");
+}
+
diff --git a/bioimagesuite30_src/Common/vtkbisDICOMReader.h b/bioimagesuite30_src/Common/vtkbisDICOMReader.h
new file mode 100644
index 0000000..1d33fb2
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisDICOMReader.h
@@ -0,0 +1,142 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// .NAME vtkDICOMImageReader - Reads DICOM images
+// .SECTION Description
+// .SECTION See Also
+// vtkBMPReader vtkPNMReader vtkTIFFReader
+
+#ifndef __vtkbisDICOMReader_h
+#define __vtkbisDICOMReader_h
+#include "vtkbisImageHeader.h"
+
+
+#include "vtkbisGDCMImageReader.h"
+#include "vtkStdString.h"
+
+class vtkbisDICOMReader : public vtkbisGDCMImageReader
+{
+ public:
+  // Description:
+  // Static method for construction.
+  static vtkbisDICOMReader *New();
+  vtkTypeRevisionMacro(vtkbisDICOMReader,vtkbisGDCMImageReader);
+
+  // Reference Time
+  // Used in PET Studies
+  vtkGetStringMacro(ReferenceTime);
+  vtkSetStringMacro(ReferenceTime);
+
+  // UniqueIDs
+  vtkSetStringMacro(StudyUID);
+  vtkGetStringMacro(StudyUID);
+  vtkSetStringMacro(SeriesUID);
+  vtkGetStringMacro(SeriesUID);
+  vtkSetStringMacro(PName);
+  vtkGetStringMacro(PName);
+
+
+  // ZPosition -- distance along z-axis of position
+  // Used to sort slices to form right-handed 3D Image
+  vtkGetMacro(ZPosition,double);
+  vtkGetMacro(X0,double);
+  vtkGetMacro(Y0,double);
+  vtkGetMacro(Z0,double);
+
+  // This is for fMRI
+  vtkGetMacro(TimeFrame,double);
+  vtkSetMacro(TimeFrame,double);
+
+  // Description:
+  // If On a vtkbisHeader is Created
+  vtkSetClampMacro(CreateNIFTIHeader,int,0,1);
+  vtkGetMacro(CreateNIFTIHeader,int);
+  vtkBooleanMacro(CreateNIFTIHeader,int);
+
+  // Description:
+  // If On Extensions will be added to NIFTI Header to store some DICOM Tags
+  vtkSetClampMacro(AddExtensions,int,0,1);
+  vtkGetMacro(AddExtensions,int);
+  vtkBooleanMacro(AddExtensions,int);
+
+  vtkSetClampMacro(FlipZ,int,0,1);
+  vtkGetMacro(FlipZ,int);
+  vtkBooleanMacro(FlipZ,int);
+
+  // fMRI Stuff
+  vtkGetMacro(IsMosaic,int);
+  vtkGetMacro(MosaicWidth,int);
+  vtkGetMacro(MosaicHeight,int);
+  vtkGetMacro(MosaicDepth,int);
+
+
+  // fMRI Stuff
+  // DWIMode = 0 no, 1 = baseline DTI, 2= weighted DTI
+  vtkGetMacro(DWIMode,int);
+  vtkGetMacro(DWIBValue,double);
+  vtkGetVectorMacro(DWIDirections,double,3);
+
+
+  // Description:
+  // Image Header
+  vtkGetObjectMacro(ImageHeader,vtkbisImageHeader);
+
+protected:
+  
+  vtkbisDICOMReader();
+  virtual ~vtkbisDICOMReader();
+
+  char* ReferenceTime;
+  char* StudyUID;
+  char* SeriesUID;
+  char* PName;
+  int   CreateNIFTIHeader;
+  int   AddExtensions;
+  double ZPosition;
+  double X0;
+  double Y0;
+  double Z0;
+
+  double TimeFrame;
+  int FlipZ;
+  int IsMosaic;
+  int MosaicWidth;
+  int MosaicHeight;
+  int MosaicDepth;
+  int DWIMode;
+  double DWIDirections[3];
+  double DWIBValue;
+  vtkbisImageHeader* ImageHeader;
+
+  // Use this as a place holder to get more data
+  //BTX
+  virtual void FillMedicalImageInformation(const gdcm::ImageReader &reader);
+  //ETX
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkbisGDCMImageReader.cpp b/bioimagesuite30_src/Common/vtkbisGDCMImageReader.cpp
new file mode 100644
index 0000000..65442aa
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisGDCMImageReader.cpp
@@ -0,0 +1,1308 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program: GDCM (Grassroots DICOM). A DICOM library
+  Module:  $URL$
+
+  Copyright (c) 2006-2008 Mathieu Malaterre
+  All rights reserved.
+  See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html 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 "vtkbisGDCMImageReader.h"
+
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPolyData.h"
+#include "vtkCellArray.h"
+#include "vtkPoints.h"
+#include "vtkMedicalImageProperties.h"
+#include "vtkStringArray.h"
+#include "vtkPointData.h"
+#include "vtkLookupTable.h"
+#include "vtkWindowLevelLookupTable.h"
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+#include "vtkLookupTable16.h"
+#include "vtkInformationVector.h"
+#include "vtkInformation.h"
+#include "vtkDemandDrivenPipeline.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/
+#include "vtkMatrix4x4.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkBitArray.h"
+
+#include "gdcmImageReader.h"
+#include "gdcmDataElement.h"
+#include "gdcmByteValue.h"
+#include "gdcmSwapper.h"
+#include "gdcmUnpacker12Bits.h"
+#include "gdcmRescaler.h"
+#include "gdcmOrientation.h"
+#include "gdcmImageChangePlanarConfiguration.h"
+
+#include <sstream>
+
+vtkCxxRevisionMacro(vtkbisGDCMImageReader, "$Revision: 1.1 $")
+vtkStandardNewMacro(vtkbisGDCMImageReader)
+
+inline bool vtkbisGDCMImageReader_IsCharTypeSigned()
+{
+#ifndef VTK_TYPE_CHAR_IS_SIGNED
+  unsigned char uc = 255;
+  return (*reinterpret_cast<char*>(&uc) < 0) ? true : false;
+#else
+  return VTK_TYPE_CHAR_IS_SIGNED;
+#endif
+}
+
+// Output Ports are as follow:
+// #0: The image/volume (root PixelData element)
+// #1: (if present): the Icon Image (0088,0200)
+// #2-xx: (if present): the Overlay (60xx,3000)
+
+#define ICONIMAGEPORTNUMBER 1
+#define OVERLAYPORTNUMBER   2
+
+vtkCxxSetObjectMacro(vtkbisGDCMImageReader,Curve,vtkPolyData)
+
+vtkbisGDCMImageReader::vtkbisGDCMImageReader()
+{
+  // vtkDataArray has an internal vtkLookupTable why not used it ?
+  // vtkMedicalImageProperties is in the parent class
+  //this->FileLowerLeft = 1;
+  this->DirectionCosines = vtkMatrix4x4::New();
+  this->DirectionCosines->SetElement(0,0,1);
+  this->DirectionCosines->SetElement(1,0,0);
+  this->DirectionCosines->SetElement(2,0,0);
+  this->DirectionCosines->SetElement(0,1,0);
+  this->DirectionCosines->SetElement(1,1,1);
+  this->DirectionCosines->SetElement(2,1,0);
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+#else
+  this->MedicalImageProperties = vtkMedicalImageProperties::New();
+#endif
+#if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
+#else
+  this->FileNames = NULL; //vtkStringArray::New();
+#endif
+  this->LoadOverlays = 1;
+  this->LoadIconImage = 1;
+  this->NumberOfOverlays = 0;
+  this->NumberOfIconImages = 0;
+  memset(this->IconImageDataExtent,0,6*sizeof(int));
+  this->ImageFormat = 0; // INVALID
+  this->ApplyInverseVideo = 0;
+  this->ApplyLookupTable = 0;
+  this->ApplyYBRToRGB = 0;
+  this->ApplyPlanarConfiguration = 1;
+  this->ApplyShiftScale = 1;
+  memset(this->ImagePositionPatient,0,3*sizeof(double));
+  memset(this->ImageOrientationPatient,0,6*sizeof(double));
+  this->Curve = 0;
+  this->Shift = 0.;
+  this->Scale = 1.;
+  this->IconDataScalarType = VTK_CHAR;
+  this->IconNumberOfScalarComponents = 1;
+  this->PlanarConfiguration = 0;
+  this->ForceZSpacing=-1.0;
+
+}
+
+vtkbisGDCMImageReader::~vtkbisGDCMImageReader()
+{
+  //delete this->Internals;
+  this->DirectionCosines->Delete();
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+#else
+  this->MedicalImageProperties->Delete();
+#endif
+#if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
+#else
+  if( this->FileNames )
+    {
+    this->FileNames->Delete();
+    }
+#endif
+  if( this->Curve )
+    {
+    this->Curve->Delete();
+    }
+}
+
+#if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
+#else
+void vtkbisGDCMImageReader::SetFileNames(vtkStringArray *filenames)
+{
+  if (filenames == this->FileNames)
+    {
+    return;
+    }
+  if (this->FileNames)
+    {
+    this->FileNames->Delete();
+    this->FileNames = 0;
+    }
+  if (filenames)
+    {
+    this->FileNames = filenames;
+    this->FileNames->Register(this);
+    if (this->FileNames->GetNumberOfValues() > 0)
+      {
+      this->DataExtent[4] = 0;
+      this->DataExtent[5] = this->FileNames->GetNumberOfValues() - 1;
+      }
+    if (this->FilePrefix)
+      {
+      delete [] this->FilePrefix;
+      this->FilePrefix = NULL;
+      }
+    if (this->FileName)
+      {
+      delete [] this->FileName;
+      this->FileName = NULL;
+      }
+    }
+
+  this->Modified();
+}
+#endif
+
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+#else
+void vtkbisGDCMImageReader::ExecuteInformation()
+{
+  //std::cerr << "ExecuteInformation" << std::endl;
+
+  // FIXME: I think it only apply to VTK 4.2...
+  vtkImageData *output = this->GetOutput();
+  output->SetUpdateExtentToWholeExtent(); // pipeline is not reexecuting properly without that...
+
+  int res = RequestInformationCompat();
+  if( !res )
+    {
+    vtkErrorMacro( "ExecuteInformation failed" );
+    return;
+    }
+
+  int numvol = 1;
+  if( this->LoadIconImage )
+    {
+    numvol = 2;
+    }
+  if( this->LoadOverlays )
+    {
+    // If not icon found, we still need to be associated to port #2:
+    numvol = 3;
+    }
+  this->SetNumberOfOutputs(numvol);
+
+  // vtkImageReader2::ExecuteInformation only allocate first output
+  this->vtkImageReader2::ExecuteInformation();
+  // Let's do the other ones ourselves:
+  for (int i=1; i<numvol; i++)
+    {
+    if (!this->Outputs[i])
+      {
+      vtkImageData * img = vtkImageData::New();
+      this->SetNthOutput(i, img);
+      img->Delete();
+      }
+    vtkImageData *output = this->GetOutput(i);
+    switch(i)
+      {
+    case 0:
+      output->SetWholeExtent(this->DataExtent);
+      output->SetSpacing(this->DataSpacing);
+      output->SetOrigin(this->DataOrigin);
+
+      output->SetScalarType(this->DataScalarType);
+      output->SetNumberOfScalarComponents(this->NumberOfScalarComponents);
+      break;
+    case ICONIMAGEPORTNUMBER:
+      output->SetWholeExtent(this->IconImageDataExtent);
+      output->SetScalarType( this->IconDataScalarType );
+      output->SetNumberOfScalarComponents( this->IconNumberOfScalarComponents );
+      break;
+    //case OVERLAYPORTNUMBER:
+    default:
+      output->SetWholeExtent(this->DataExtent[0],this->DataExtent[1],
+        this->DataExtent[2],this->DataExtent[3],
+        0,0
+      );
+      //output->SetSpacing(this->DataSpacing);
+      //output->SetOrigin(this->DataOrigin);
+      output->SetScalarType(VTK_UNSIGNED_CHAR);
+      output->SetNumberOfScalarComponents(1);
+      break;
+      }
+
+    }
+}
+
+void vtkbisGDCMImageReader::ExecuteData(vtkDataObject *output)
+{
+  //std::cerr << "ExecuteData" << std::endl;
+  // In VTK 4.2 AllocateOutputData is reexecuting ExecuteInformation which is bad !
+  //vtkImageData *data = this->AllocateOutputData(output);
+  vtkImageData *res = vtkImageData::SafeDownCast(output);
+  res->SetExtent(res->GetUpdateExtent());
+  res->AllocateScalars();
+
+  if( this->LoadIconImage )
+    {
+    vtkImageData *res = vtkImageData::SafeDownCast(this->Outputs[ICONIMAGEPORTNUMBER]);
+    res->SetUpdateExtentToWholeExtent();
+
+    res->SetExtent(res->GetUpdateExtent());
+    res->AllocateScalars();
+    }
+  if( this->LoadOverlays )
+    {
+    vtkImageData *res = vtkImageData::SafeDownCast(this->Outputs[OVERLAYPORTNUMBER]);
+    res->SetUpdateExtentToWholeExtent();
+
+    res->SetExtent(res->GetUpdateExtent());
+    res->AllocateScalars();
+    }
+  //int * updateExtent = data->GetUpdateExtent();
+  //std::cout << "UpdateExtent:" << updateExtent[4] << " " << updateExtent[5] << std::endl;
+  RequestDataCompat();
+
+}
+
+#endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/
+
+int vtkbisGDCMImageReader::CanReadFile(const char* fname)
+{
+  gdcm::ImageReader reader;
+  reader.SetFileName( fname );
+  if( !reader.Read() )
+    {
+    return 0;
+    }
+  // 3 means: I might be able to read...
+  return 3;
+}
+
+//----------------------------------------------------------------------------
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+int vtkbisGDCMImageReader::ProcessRequest(vtkInformation* request,
+                                 vtkInformationVector** inputVector,
+                                 vtkInformationVector* outputVector)
+{
+  // generate the data
+  if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
+    {
+    return this->RequestData(request, inputVector, outputVector);
+    }
+
+  // execute information
+  if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
+    {
+    return this->RequestInformation(request, inputVector, outputVector);
+    }
+
+  return this->Superclass::ProcessRequest(request, inputVector, outputVector);
+}
+#endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/
+
+
+//----------------------------------------------------------------------------
+inline const char *GetStringValueFromTag(const gdcm::Tag& t, const gdcm::DataSet& ds)
+{
+  static std::string buffer;
+  buffer = "";  // cleanup previous call
+
+  if( ds.FindDataElement( t ) )
+    {
+    const gdcm::DataElement& de = ds.GetDataElement( t );
+    const gdcm::ByteValue *bv = de.GetByteValue();
+    if( bv ) // Can be Type 2
+      {
+      buffer = std::string( bv->GetPointer(), bv->GetLength() );
+      // Will be padded with at least one \0
+      }
+    }
+
+  // Since return is a const char* the very first \0 will be considered
+  return buffer.c_str();
+}
+
+//----------------------------------------------------------------------------
+void vtkbisGDCMImageReader::FillMedicalImageInformation(const gdcm::ImageReader &reader)
+{
+  const gdcm::File &file = reader.GetFile();
+  const gdcm::DataSet &ds = file.GetDataSet();
+
+  // $ grep "vtkSetString\|DICOM" vtkMedicalImageProperties.h 
+  // For ex: DICOM (0010,0010) = DOE,JOHN
+  this->MedicalImageProperties->SetPatientName( GetStringValueFromTag( gdcm::Tag(0x0010,0x0010), ds) );
+  // For ex: DICOM (0010,0020) = 1933197
+  this->MedicalImageProperties->SetPatientID( GetStringValueFromTag( gdcm::Tag(0x0010,0x0020), ds) );
+  // For ex: DICOM (0010,1010) = 031Y
+  this->MedicalImageProperties->SetPatientAge( GetStringValueFromTag( gdcm::Tag(0x0010,0x1010), ds) );
+  // For ex: DICOM (0010,0040) = M
+  this->MedicalImageProperties->SetPatientSex( GetStringValueFromTag( gdcm::Tag(0x0010,0x0040), ds) );
+  // For ex: DICOM (0010,0030) = 19680427
+  this->MedicalImageProperties->SetPatientBirthDate( GetStringValueFromTag( gdcm::Tag(0x0010,0x0030), ds) );
+#if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
+  // For ex: DICOM (0008,0020) = 20030617
+  this->MedicalImageProperties->SetStudyDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0020), ds) );
+#endif
+  // For ex: DICOM (0008,0022) = 20030617
+  this->MedicalImageProperties->SetAcquisitionDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0022), ds) );
+#if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
+  // For ex: DICOM (0008,0030) = 162552.0705 or 230012, or 0012
+  this->MedicalImageProperties->SetStudyTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0030), ds) );
+#endif
+  // For ex: DICOM (0008,0032) = 162552.0705 or 230012, or 0012
+  this->MedicalImageProperties->SetAcquisitionTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0032), ds) );
+  // For ex: DICOM (0008,0023) = 20030617
+  this->MedicalImageProperties->SetImageDate( GetStringValueFromTag( gdcm::Tag(0x0008,0x0023), ds) );
+  // For ex: DICOM (0008,0033) = 162552.0705 or 230012, or 0012
+  this->MedicalImageProperties->SetImageTime( GetStringValueFromTag( gdcm::Tag(0x0008,0x0033), ds) );
+  // For ex: DICOM (0020,0013) = 1
+  this->MedicalImageProperties->SetImageNumber( GetStringValueFromTag( gdcm::Tag(0x0020,0x0013), ds) );
+  // For ex: DICOM (0020,0011) = 902
+  this->MedicalImageProperties->SetSeriesNumber( GetStringValueFromTag( gdcm::Tag(0x0020,0x0011), ds) );
+  // For ex: DICOM (0008,103e) = SCOUT
+  this->MedicalImageProperties->SetSeriesDescription( GetStringValueFromTag( gdcm::Tag(0x0008,0x103e), ds) );
+  // For ex: DICOM (0020,0010) = 37481
+  this->MedicalImageProperties->SetStudyID( GetStringValueFromTag( gdcm::Tag(0x0020,0x0010), ds) );
+  // For ex: DICOM (0008,1030) = BRAIN/C-SP/FACIAL
+  this->MedicalImageProperties->SetStudyDescription( GetStringValueFromTag( gdcm::Tag(0x0008,0x1030), ds) );
+  // For ex: DICOM (0008,0060)= CT
+  this->MedicalImageProperties->SetModality( GetStringValueFromTag( gdcm::Tag(0x0008,0x0060), ds) );
+  // For ex: DICOM (0008,0070) = Siemens
+  this->MedicalImageProperties->SetManufacturer( GetStringValueFromTag( gdcm::Tag(0x0008,0x0070), ds) );
+  // For ex: DICOM (0008,1090) = LightSpeed QX/i
+  this->MedicalImageProperties->SetManufacturerModelName( GetStringValueFromTag( gdcm::Tag(0x0008,0x1090), ds) );
+  // For ex: DICOM (0008,1010) = LSPD_OC8
+  this->MedicalImageProperties->SetStationName( GetStringValueFromTag( gdcm::Tag(0x0008,0x1010), ds) );
+  // For ex: DICOM (0008,0080) = FooCity Medical Center
+  this->MedicalImageProperties->SetInstitutionName( GetStringValueFromTag( gdcm::Tag(0x0008,0x0080), ds) );
+  // For ex: DICOM (0018,1210) = Bone
+  this->MedicalImageProperties->SetConvolutionKernel( GetStringValueFromTag( gdcm::Tag(0x0018,0x1210), ds) );
+  // For ex: DICOM (0018,0050) = 0.273438
+  this->MedicalImageProperties->SetSliceThickness( GetStringValueFromTag( gdcm::Tag(0x0018,0x0050), ds) );
+  // For ex: DICOM (0018,0060) = 120
+  this->MedicalImageProperties->SetKVP( GetStringValueFromTag( gdcm::Tag(0x0018,0x0060), ds) );
+  // For ex: DICOM (0018,1120) = 15
+  this->MedicalImageProperties->SetGantryTilt( GetStringValueFromTag( gdcm::Tag(0x0018,0x1120), ds) );
+  // For ex: DICOM (0018,0081) = 105
+  this->MedicalImageProperties->SetEchoTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x0081), ds) );
+  // For ex: DICOM (0018,0091) = 35
+  this->MedicalImageProperties->SetEchoTrainLength( GetStringValueFromTag( gdcm::Tag(0x0018,0x0091), ds) );
+  // For ex: DICOM (0018,0080) = 2040
+  this->MedicalImageProperties->SetRepetitionTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x0080), ds) );
+  // For ex: DICOM (0018,1150) = 5
+  this->MedicalImageProperties->SetExposureTime( GetStringValueFromTag( gdcm::Tag(0x0018,0x1150), ds) );
+  // For ex: DICOM (0018,1151) = 400
+  this->MedicalImageProperties->SetXRayTubeCurrent( GetStringValueFromTag( gdcm::Tag(0x0018,0x1151), ds) );
+  // For ex: DICOM (0018,1152) = 114
+  this->MedicalImageProperties->SetExposure( GetStringValueFromTag( gdcm::Tag(0x0018,0x1152), ds) );
+
+  // virtual void AddWindowLevelPreset(double w, double l);
+  // (0028,1050) DS [   498\  498]                           #  12, 2 WindowCenter
+  // (0028,1051) DS [  1063\ 1063]                           #  12, 2 WindowWidth
+  gdcm::Tag twindowcenter(0x0028,0x1050);
+  gdcm::Tag twindowwidth(0x0028,0x1051);
+  if( ds.FindDataElement( twindowcenter ) && ds.FindDataElement( twindowwidth) )
+    {
+    const gdcm::DataElement& windowcenter = ds.GetDataElement( twindowcenter );
+    const gdcm::DataElement& windowwidth = ds.GetDataElement( twindowwidth );
+    const gdcm::ByteValue *bvwc = windowcenter.GetByteValue();
+    const gdcm::ByteValue *bvww = windowwidth.GetByteValue();
+    if( bvwc && bvww ) // Can be Type 2
+      {
+      //gdcm::Attributes<0x0028,0x1050> at;
+      gdcm::Element<gdcm::VR::DS,gdcm::VM::VM1_n> elwc;
+      std::stringstream ss1;
+      std::string swc = std::string( bvwc->GetPointer(), bvwc->GetLength() );
+      ss1.str( swc );
+      gdcm::VR vr = gdcm::VR::DS;
+      unsigned int vrsize = vr.GetSizeof();
+      unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swc.c_str(), swc.size());
+      elwc.SetLength( count * vrsize );
+      elwc.Read( ss1 );
+      std::stringstream ss2;
+      std::string sww = std::string( bvww->GetPointer(), bvww->GetLength() );
+      ss2.str( sww );
+      gdcm::Element<gdcm::VR::DS,gdcm::VM::VM1_n> elww;
+      elww.SetLength( count * vrsize );
+      elww.Read( ss2 );
+      //assert( elww.GetLength() == elwc.GetLength() );
+      for(unsigned int i = 0; i < elwc.GetLength(); ++i)
+        {
+        this->MedicalImageProperties->AddWindowLevelPreset( elww.GetValue(i), elwc.GetValue(i) );
+        }
+      }
+    }
+  gdcm::Tag twindowexplanation(0x0028,0x1055);
+  if( ds.FindDataElement( twindowexplanation ) )
+    {
+    const gdcm::DataElement& windowexplanation = ds.GetDataElement( twindowexplanation );
+    const gdcm::ByteValue *bvwe = windowexplanation.GetByteValue();
+    if( bvwe ) // Can be Type 2
+      {
+      int n = this->MedicalImageProperties->GetNumberOfWindowLevelPresets();
+      gdcm::Element<gdcm::VR::LO,gdcm::VM::VM1_n> elwe; // window explanation
+      gdcm::VR vr = gdcm::VR::LO;
+      std::stringstream ss;
+      ss.str( "" );
+      std::string swe = std::string( bvwe->GetPointer(), bvwe->GetLength() );
+      unsigned int count = gdcm::VM::GetNumberOfElementsFromArray(swe.c_str(), swe.size()); (void)count;
+      // I found a case with only one W/L but two comments: WINDOW1\WINDOW2
+      // SIEMENS-IncompletePixelData.dcm
+      //assert( count >= (unsigned int)n );
+      elwe.SetLength( /*count*/ n * vr.GetSizeof() );
+      ss.str( swe );
+      elwe.Read( ss );
+      for(int i = 0; i < n; ++i)
+        {
+        this->MedicalImageProperties->SetNthWindowLevelPresetComment(i, elwe.GetValue(i).c_str() );
+        }
+      }
+    }
+
+#if 0
+  // gdcmData/JDDICOM_Sample4.dcm 
+  // -> (0008,0060) CS [DM  Digital microscopy]                 #  24, 1 Modality
+  gdcm::MediaStorage ms1 = gdcm::MediaStorage::SecondaryCaptureImageStorage;
+  ms1.GuessFromModality( this->MedicalImageProperties->GetModality(), this->FileDimensionality );
+  gdcm::MediaStorage ms2;
+  ms2.SetFromFile( reader.GetFile() );
+  if( ms2 != ms1 && ms2 != gdcm::MediaStorage::SecondaryCaptureImageStorage )
+    {
+    vtkWarningMacro( "SHOULD NOT HAPPEN. Unrecognized Modality: " << this->MedicalImageProperties->GetModality() 
+      << " Will be set instead to the known one: " << ms2.GetModality() )
+    this->MedicalImageProperties->SetModality( ms2.GetModality() );
+    }
+#endif
+ 
+  // Add more info:
+
+}
+
+//----------------------------------------------------------------------------
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+int vtkbisGDCMImageReader::RequestInformation(vtkInformation *request,
+                                      vtkInformationVector **inputVector,
+                                      vtkInformationVector *outputVector)
+{
+  (void)request;(void)inputVector;
+  int res = RequestInformationCompat();
+  if( !res )
+    {
+    vtkErrorMacro( "RequestInformationCompat failed: " << res );
+    return 0;
+    }
+
+  int numvol = 1;
+  if( this->LoadIconImage )
+    {
+    numvol = 2;
+    }
+  if( this->LoadOverlays )
+    {
+    // If no icon found, we still need to be associated to port #2:
+    numvol = 2 + this->NumberOfOverlays;
+    }
+  this->SetNumberOfOutputPorts(numvol);
+  // For each output:
+  for(int i = 0; i < numvol; ++i)
+    {
+    // Allocate !
+    if( !this->GetOutput(i) )
+      {
+      vtkImageData *img = vtkImageData::New();
+      this->GetExecutive()->SetOutputData(i, img );
+      img->Delete();
+      }
+    vtkInformation *outInfo = outputVector->GetInformationObject(i);
+    switch(i)
+      {
+    // root Pixel Data
+    case 0:
+      outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->DataExtent, 6);
+      //outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(), this->DataExtent, 6);
+      outInfo->Set(vtkDataObject::SPACING(), this->DataSpacing, 3);
+      outInfo->Set(vtkDataObject::ORIGIN(), this->DataOrigin, 3);
+      vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->DataScalarType, this->NumberOfScalarComponents);
+      break;
+    // Icon Image
+    case ICONIMAGEPORTNUMBER:
+      outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), this->IconImageDataExtent, 6);
+      vtkDataObject::SetPointDataActiveScalarInfo(outInfo, this->IconDataScalarType, this->IconNumberOfScalarComponents );
+      break;
+    // Overlays:
+    //case OVERLAYPORTNUMBER:
+    default:
+      outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), 
+        this->DataExtent[0], this->DataExtent[1], 
+        this->DataExtent[2], this->DataExtent[3],
+        0,0 );
+      vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 1);
+      break;
+      }
+    }
+
+  //return res;
+  return 1;
+}
+#endif
+
+int vtkbisGDCMImageReader::RequestInformationCompat()
+{
+  // FIXME, need to implement the other modes too:
+  if( this->ApplyLookupTable || this->ApplyYBRToRGB || this->ApplyInverseVideo )
+    {
+    vtkErrorMacro( "ApplyLookupTable/ApplyYBRToRGB/ApplyInverseVideo not compatible" );
+    return 0;
+    }
+  // I do not think this is a good idea anyway to let the user decide
+  // wether or not she wants *not* to apply shift/scale...
+  if( !this->ApplyShiftScale )
+  {
+    vtkErrorMacro("ApplyShiftScale not compatible" );
+    return 0;
+   }
+  // I do not think this one will ever be implemented:
+  if( !this->ApplyPlanarConfiguration )
+    {
+    vtkErrorMacro("ApplyPlanarConfiguration not compatible" );
+    return 0;
+    }
+
+  // Let's read the first file :
+  const char *filename;
+  if( this->FileName )
+    {
+    filename = this->FileName;
+    }
+  else if ( this->FileNames && this->FileNames->GetNumberOfValues() > 0 )
+    {
+    filename = this->FileNames->GetValue( 0 );
+    }
+  else
+    {
+    // hey! I need at least one file to schew on !
+    vtkErrorMacro( "You did not specify any filenames" );
+    return 0;
+    }
+  gdcm::ImageReader reader;
+  reader.SetFileName( filename );
+  if( !reader.Read() )
+    {
+    vtkErrorMacro( "ImageReader failed" );
+    return 0;
+    }
+  const gdcm::Image &image = reader.GetImage();
+  const unsigned int *dims = image.GetDimensions();
+
+  // Set the Extents.
+  assert( image.GetNumberOfDimensions() >= 2 );
+  this->DataExtent[0] = 0;
+  this->DataExtent[1] = dims[0] - 1;
+  this->DataExtent[2] = 0;
+  this->DataExtent[3] = dims[1] - 1;
+  if( image.GetNumberOfDimensions() == 2 )
+    {
+    // This is just so much painfull to deal with DICOM / VTK
+    // they simply assume that number of file is equal to the dimension
+    // of the last axe (see vtkImageReader2::SetFileNames )
+    if ( this->FileNames && this->FileNames->GetNumberOfValues() > 1 )
+      {
+      this->DataExtent[4] = 0;
+      //this->DataExtent[5] = this->FileNames->GetNumberOfValues() - 1;
+      }
+    else
+      {
+      this->DataExtent[4] = 0;
+      this->DataExtent[5] = 0;
+      }
+    }
+  else
+    {
+    assert( image.GetNumberOfDimensions() == 3 );
+    this->FileDimensionality = 3;
+    this->DataExtent[4] = 0;
+    this->DataExtent[5] = dims[2] - 1;
+    }
+  gdcm::MediaStorage ms;
+  ms.SetFromFile( reader.GetFile() );
+  assert( gdcm::MediaStorage::IsImage( ms ) || ms == gdcm::MediaStorage::MRSpectroscopyStorage );
+  // There is no point in adding world info to a SC object since noone but GDCM can use this info...
+  //if( ms != gdcm::MediaStorage::SecondaryCaptureImageStorage )
+
+  const double *spacing = image.GetSpacing();
+  if( spacing )
+    {
+      this->DataSpacing[0] = spacing[0];
+      this->DataSpacing[1] = spacing[1];
+      this->DataSpacing[2] = image.GetSpacing(2);
+    }
+  
+  if (  this->ForceZSpacing>0.0)
+    {
+      this->DataSpacing[2]=this->ForceZSpacing;
+      //      fprintf(stderr,"Zspa[2] = %.4f\n",this->DataSpacing[2]);
+    } 
+  else
+    {
+      //      fprintf(stderr,"Not forcing Zspa[2] = %.4f\n",this->DataSpacing[2]);      
+    }
+
+    const double *origin = image.GetOrigin();
+    if( origin )
+      {
+      this->ImagePositionPatient[0] = image.GetOrigin(0);
+      this->ImagePositionPatient[1] = image.GetOrigin(1);
+      this->ImagePositionPatient[2] = image.GetOrigin(2);
+      }
+
+    const double *dircos = image.GetDirectionCosines();
+    if( dircos )
+      {
+      this->DirectionCosines->SetElement(0,0, dircos[0]);
+      this->DirectionCosines->SetElement(1,0, dircos[1]);
+      this->DirectionCosines->SetElement(2,0, dircos[2]);
+      this->DirectionCosines->SetElement(0,1, dircos[3]);
+      this->DirectionCosines->SetElement(1,1, dircos[4]);
+      this->DirectionCosines->SetElement(2,1, dircos[5]);
+      for(int i=0;i<6;++i)
+        this->ImageOrientationPatient[i] = dircos[i];
+      }
+    // Apply transform:
+    if( dircos && origin )
+      {
+      if( this->FileLowerLeft )
+        {
+        // Since we are not doing the VTK Y-flipping operation, Origin and Image Position (Patient)
+        // are the same:
+        this->DataOrigin[0] = origin[0];
+        this->DataOrigin[1] = origin[1];
+        this->DataOrigin[2] = origin[2];
+        }
+      else
+        {
+        // We are doing the Y-flip:
+        // translate Image Position (Patient) along the Y-vector of the Image Orientation (Patient):
+        // Step 1: Compute norm of translation vector:
+        // Because position is in the center of the pixel, we need to substract 1 to the dimY:
+        assert( dims[1] >=1 );
+        double norm = (dims[1] - 1) * this->DataSpacing[1];
+        // Step 2: translate:
+        this->DataOrigin[0] = origin[0] + norm * dircos[3+0];
+        this->DataOrigin[1] = origin[1] + norm * dircos[3+1];
+        this->DataOrigin[2] = origin[2] + norm * dircos[3+2];
+        }
+      }
+    // Need to set the rest to 0 ???
+
+  const gdcm::PixelFormat &pixeltype = image.GetPixelFormat();
+  this->Shift = image.GetIntercept();
+  this->Scale = image.GetSlope();
+  gdcm::PixelFormat::ScalarType outputpt = pixeltype;
+  // Compute output pixel format when Rescaling:
+  if( this->Shift != 0 || this->Scale != 1. )
+    {
+    gdcm::Rescaler r;
+    r.SetIntercept( this->Shift );
+    r.SetSlope( this->Scale );
+    r.SetPixelFormat( pixeltype );
+    outputpt = r.ComputeInterceptSlopePixelType();
+    assert( pixeltype <= outputpt );
+    }
+  //if( pixeltype != outputpt ) assert( Shift != 0. || Scale != 1 );
+  //std::cerr << "PF:" << pixeltype << " -> " << outputpt << std::endl;
+
+  switch( outputpt )
+    {
+  case gdcm::PixelFormat::INT8:
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+    this->DataScalarType = VTK_SIGNED_CHAR;
+#else
+    if( !vtkbisGDCMImageReader_IsCharTypeSigned() )
+      {
+      vtkErrorMacro( "Output Pixel Type will be incorrect, go get a newer VTK version" );
+      }
+    this->DataScalarType = VTK_CHAR;
+#endif
+    break;
+  case gdcm::PixelFormat::UINT8:
+    this->DataScalarType = VTK_UNSIGNED_CHAR;
+    break;
+  case gdcm::PixelFormat::INT16:
+    this->DataScalarType = VTK_SHORT;
+    break;
+  case gdcm::PixelFormat::UINT16:
+    this->DataScalarType = VTK_UNSIGNED_SHORT;
+    break;
+  // RT / SC have 32bits
+  case gdcm::PixelFormat::INT32:
+    this->DataScalarType = VTK_INT;
+    break;
+  case gdcm::PixelFormat::UINT32:
+    this->DataScalarType = VTK_UNSIGNED_INT;
+    break;
+  case gdcm::PixelFormat::INT12:
+    this->DataScalarType = VTK_SHORT;
+    break;
+  case gdcm::PixelFormat::UINT12:
+    this->DataScalarType = VTK_UNSIGNED_SHORT;
+    break;
+  //case gdcm::PixelFormat::FLOAT16: // TODO
+  case gdcm::PixelFormat::FLOAT32:
+    this->DataScalarType = VTK_FLOAT;
+    break;
+  default:
+    vtkErrorMacro( "Do not support this Pixel Type: " );
+    return 0;
+    }
+  this->NumberOfScalarComponents = pixeltype.GetSamplesPerPixel();
+
+  // Ok let's fill in the 'extra' info:
+  this->FillMedicalImageInformation(reader);
+
+  // Do the IconImage if requested:
+  const gdcm::IconImage& icon = image.GetIconImage();
+  if( this->LoadIconImage && !icon.IsEmpty() )
+    {
+    this->IconImageDataExtent[0] = 0;
+    this->IconImageDataExtent[1] = icon.GetColumns() - 1;
+    this->IconImageDataExtent[2] = 0;
+    this->IconImageDataExtent[3] = icon.GetRows() - 1;
+    // 
+    const gdcm::PixelFormat &iconpixelformat = icon.GetPixelFormat();
+    switch(iconpixelformat)
+      {
+    case gdcm::PixelFormat::INT8:
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+      this->IconDataScalarType = VTK_SIGNED_CHAR;
+#else
+      this->IconDataScalarType = VTK_CHAR;
+#endif
+      break;
+    case gdcm::PixelFormat::UINT8:
+      this->IconDataScalarType = VTK_UNSIGNED_CHAR;
+      break;
+    case gdcm::PixelFormat::INT16:
+      this->IconDataScalarType = VTK_SHORT;
+      break;
+    case gdcm::PixelFormat::UINT16:
+      this->IconDataScalarType = VTK_UNSIGNED_SHORT;
+      break;
+    default:
+      vtkErrorMacro( "Do not support this Icon Pixel Type: " );
+      return 0;
+      }
+    this->IconNumberOfScalarComponents = iconpixelformat.GetSamplesPerPixel();
+    }
+
+  // Overlay!
+  unsigned int numoverlays = image.GetNumberOfOverlays();
+  if( this->LoadOverlays && numoverlays )
+    {
+    // Do overlay specific stuff...
+    // what if overlay do not have the same data extent as image ?
+    for( unsigned int ovidx = 0; ovidx < numoverlays; ++ovidx )
+      {
+      const gdcm::Overlay& ov = image.GetOverlay(ovidx);
+      assert( (unsigned int)ov.GetRows() == image.GetRows() );
+      assert( (unsigned int)ov.GetColumns() == image.GetColumns() );
+      }
+    this->NumberOfOverlays = numoverlays;
+    }
+
+//  return this->Superclass::RequestInformation(
+//    request, inputVector, outputVector);
+
+  return 1;
+}
+
+template <class T>
+inline unsigned long vtkImageDataGetTypeSize(T*, int a = 0,int b = 0)
+{
+  (void)a;(void)b;
+  return sizeof(T);
+}
+
+void InPlaceYFlipImage(vtkImageData* data)
+{
+  unsigned long outsize = data->GetNumberOfScalarComponents();
+  int *dext = data->GetWholeExtent();
+  if( dext[1] == dext[0] && dext[0] == 0 ) return;
+
+  // Multiply by the number of bytes per scalar
+  switch (data->GetScalarType())
+    {
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+    vtkTemplateMacro(
+      outsize *= vtkImageDataGetTypeSize(static_cast<VTK_TT*>(0))
+    );
+#else
+    vtkTemplateMacro3(
+      outsize *= vtkImageDataGetTypeSize, static_cast<VTK_TT*>(0), 0, 0
+    );
+#endif
+    default:
+      //vtkErrorMacro("do not support scalar type: " << data->GetScalarType() );
+      abort();
+    }
+  outsize *= (dext[1] - dext[0] + 1);
+  char * ref = static_cast<char*>(data->GetScalarPointer());
+  char * pointer = static_cast<char*>(data->GetScalarPointer());
+  assert( pointer );
+
+  char *line = new char[outsize];
+
+  for(int j = dext[4]; j <= dext[5]; ++j)
+    {
+    char *start = pointer;
+    assert( start == ref + j * outsize * (dext[3] - dext[2] + 1) );
+    // Swap two-lines at a time
+    // when Rows is odd number (359) then dext[3] == 178 
+    // so we should avoid copying the line right in the center of the image
+    // since memcpy does not like copying on itself...
+    for(int i = dext[2]; i < (dext[3]+1) / 2; ++i)
+      {
+      // image:
+      char * end = start+(dext[3] - i)*outsize;
+      assert( (end - pointer) >= (int)outsize );
+      memcpy(line,end,outsize); // duplicate line
+      memcpy(end,pointer,outsize);
+      memcpy(pointer,line,outsize);
+      pointer += outsize;
+      }
+    // because the for loop iterated only over 1/2 all lines, skip to the next slice:
+    assert( dext[2] == 0 );
+    pointer += (dext[3] + 1 - (dext[3]+1)/2 )*outsize;
+    }
+  // Did we reach the end ?
+  assert( pointer == ref + (dext[5]-dext[4]+1)*(dext[3]-dext[2]+1)*outsize );
+  delete[] line;
+}
+
+//----------------------------------------------------------------------------
+int vtkbisGDCMImageReader::LoadSingleFile(const char *filename, char *pointer, unsigned long &outlen)
+{
+  int *dext = this->GetDataExtent();
+  vtkImageData *data = this->GetOutput(0);
+  //bool filelowerleft = this->FileLowerLeft ? true : false;
+
+  //char * pointer = static_cast<char*>(data->GetScalarPointer());
+
+  gdcm::ImageReader reader;
+  reader.SetFileName( filename );
+  if( !reader.Read() )
+    {
+    vtkErrorMacro( "ImageReader failed: " << filename );
+    return 0;
+    }
+  gdcm::Image &image = reader.GetImage();
+  //VTK does not cope with Planar Configuration, so let's schew the work to please it
+  assert( this->PlanarConfiguration == 0 || this->PlanarConfiguration == 1 );
+  // Store the PlanarConfiguration before inverting it !
+  this->PlanarConfiguration = image.GetPlanarConfiguration();
+  //assert( this->PlanarConfiguration == 0 || this->PlanarConfiguration == 1 );
+  if( image.GetPlanarConfiguration() == 1 )
+    {
+    gdcm::ImageChangePlanarConfiguration icpc;
+    icpc.SetInput( image );
+    icpc.SetPlanarConfiguration( 0 );
+    icpc.Change();
+    image = icpc.GetOutput();
+    }
+
+  const gdcm::PixelFormat &pixeltype = image.GetPixelFormat();
+  assert( image.GetNumberOfDimensions() == 2 || image.GetNumberOfDimensions() == 3 );
+  unsigned long len = image.GetBufferLength();
+  outlen = len;
+  unsigned long overlaylen = 0;
+  image.GetBuffer(pointer);
+  if( pixeltype == gdcm::PixelFormat::UINT12 || pixeltype == gdcm::PixelFormat::INT12 )
+  {
+    assert( Scale == 1.0 && Shift == 0.0 );
+    assert( pixeltype.GetSamplesPerPixel() == 1 );
+    // FIXME: I could avoid this extra copy:
+    char * copy = new char[len];
+    memcpy(copy, pointer, len);
+    gdcm::Unpacker12Bits u12;
+    u12.Unpack(pointer, copy, len);
+    // update len just in case:
+    len = 16 * len / 12;
+    delete[] copy;
+  }
+  // HACK: Make sure that Shift/Scale are the one from the file:
+  this->Shift = image.GetIntercept();
+  this->Scale = image.GetSlope();
+
+  if( Scale != 1.0 || Shift != 0.0 )
+  {
+    assert( pixeltype.GetSamplesPerPixel() == 1 );
+    gdcm::Rescaler r;
+    r.SetIntercept( Shift );
+    r.SetSlope( Scale );
+    r.SetPixelFormat( pixeltype );
+    char * copy = new char[len];
+    memcpy(copy, pointer, len);
+    r.Rescale(pointer,copy,len);
+    delete[] copy;
+    // WARNING: sizeof(Real World Value) != sizeof(Stored Pixel)
+    outlen = data->GetScalarSize() * data->GetNumberOfPoints() / data->GetDimensions()[2];
+    assert( data->GetNumberOfScalarComponents() == 1 );
+  }
+
+  // Do the Icon Image:
+  this->NumberOfIconImages = image.GetIconImage().IsEmpty() ? 0 : 1;
+  if( this->NumberOfIconImages )
+    {
+    char * iconpointer = static_cast<char*>(this->GetOutput(ICONIMAGEPORTNUMBER)->GetScalarPointer());
+    assert( iconpointer );
+    image.GetIconImage().GetBuffer( iconpointer );
+    if ( image.GetIconImage().GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::PALETTE_COLOR )
+      {
+      const gdcm::LookupTable &lut = image.GetIconImage().GetLUT();
+      assert( lut.GetBitSample() == 8 );
+        {
+        vtkLookupTable *vtklut = vtkLookupTable::New();
+        vtklut->SetNumberOfTableValues(256);
+        // SOLVED: GetPointer(0) is skrew up, need to replace it with WritePointer(0,4) ...
+        if( !lut.GetBufferAsRGBA( vtklut->WritePointer(0,4) ) )
+          {
+          vtkWarningMacro( "Could not get values from LUT" );
+          return 0;
+          }
+        vtklut->SetRange(0,255);
+        this->GetOutput(ICONIMAGEPORTNUMBER)->GetPointData()->GetScalars()->SetLookupTable( vtklut );
+        vtklut->Delete();
+        }
+      }
+    }
+
+  // Do the Curve:
+  unsigned int numcurves = image.GetNumberOfCurves();
+  if( numcurves )
+    {
+    const gdcm::Curve& curve = image.GetCurve();
+    //curve.Print( std::cout );
+    vtkPoints * pts = vtkPoints::New();
+    // Number of points is the total number of x+y points, while VTK need the
+    // number of tuples:
+    pts->SetNumberOfPoints( curve.GetNumberOfPoints() / 2 );
+    curve.GetAsPoints( (float*)pts->GetVoidPointer(0) );
+    vtkCellArray *polys = vtkCellArray::New();
+    for(unsigned int i = 0; i < curve.GetNumberOfPoints(); i+=2 )
+      {
+      polys->InsertNextCell(2);
+      polys->InsertCellPoint(i);
+      polys->InsertCellPoint(i+1);
+      }
+    vtkPolyData *cube = vtkPolyData::New();
+    cube->SetPoints(pts);
+    pts->Delete();
+    cube->SetLines(polys);
+    polys->Delete();
+    SetCurve(cube);
+    cube->Delete();
+    }
+
+  // Do the Overlay:
+  unsigned int numoverlays = image.GetNumberOfOverlays();
+  long overlayoutsize = (dext[1] - dext[0] + 1);
+  //this->NumberOfOverlays = numoverlays;
+  //if( numoverlays )
+  if( !this->LoadOverlays ) assert( this->NumberOfOverlays == 0 );
+  for( int ovidx = 0;  ovidx < this->NumberOfOverlays; ++ovidx )
+    {
+    vtkImageData *vtkimage = this->GetOutput(OVERLAYPORTNUMBER + ovidx);
+    // vtkOpenGLImageMapper::RenderData does not support bit array (since OpenGL does not either)
+    // we have to decompress the bit overlay into an unsigned char array to please everybody:
+    const gdcm::Overlay& ov1 = image.GetOverlay(ovidx);
+    vtkUnsignedCharArray *chararray = vtkUnsignedCharArray::New();
+    chararray->SetNumberOfTuples( overlayoutsize * ( dext[3] - dext[2] + 1 ) );
+    overlaylen = overlayoutsize * ( dext[3] - dext[2] + 1 );
+    assert( (unsigned long)ov1.GetRows()*ov1.GetColumns() <= overlaylen );
+    const signed short *origin = ov1.GetOrigin();
+    if( (unsigned long)ov1.GetRows()*ov1.GetColumns() != overlaylen )
+      {
+      vtkWarningMacro( "vtkImageData Overlay have an extent that do not match the one of the image" );
+      }
+    if( origin[0] != 0 || origin[1] != 0 )
+      {
+      vtkWarningMacro( "Overlay with origin are not supported right now" );
+      }
+    vtkimage->GetPointData()->SetScalars( chararray );
+    vtkimage->GetPointData()->GetScalars()->SetName( ov1.GetDescription() );
+    chararray->Delete();
+
+    assert( vtkimage->GetScalarType() == VTK_UNSIGNED_CHAR );
+    unsigned char * overlaypointer = static_cast<unsigned char*>(vtkimage->GetScalarPointer());
+    assert( overlaypointer );
+    //assert( image->GetPointData()->GetScalars() != 0 );
+
+    //memset(overlaypointer,0,overlaylen); // FIXME: can be optimized
+    ov1.GetUnpackBuffer( overlaypointer );
+    }
+
+  //const gdcm::PixelFormat &pixeltype = image.GetPixelFormat();
+  // Do the LUT
+  if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::PALETTE_COLOR )
+    {
+    this->ImageFormat = VTK_LOOKUP_TABLE;
+    const gdcm::LookupTable &lut = image.GetLUT();
+    if( lut.GetBitSample() == 8 )
+      {
+      vtkLookupTable *vtklut = vtkLookupTable::New();
+      vtklut->SetNumberOfTableValues(256);
+      // SOLVED: GetPointer(0) is skrew up, need to replace it with WritePointer(0,4) ...
+      if( !lut.GetBufferAsRGBA( vtklut->WritePointer(0,4) ) )
+        {
+        vtkWarningMacro( "Could not get values from LUT" );
+        return 0;
+        }
+      vtklut->SetRange(0,255);
+      data->GetPointData()->GetScalars()->SetLookupTable( vtklut );
+      vtklut->Delete();
+      }
+    else 
+      {
+#if (VTK_MAJOR_VERSION >= 5)
+      assert( lut.GetBitSample() == 16 );
+      vtkLookupTable16 *vtklut = vtkLookupTable16::New();
+      vtklut->SetNumberOfTableValues(256*256);
+      // SOLVED: GetPointer(0) is skrew up, need to replace it with WritePointer(0,4) ...
+      if( !lut.GetBufferAsRGBA( (unsigned char*)vtklut->WritePointer(0,4) ) )
+        {
+        vtkWarningMacro( "Could not get values from LUT" );
+        return 0;
+        }
+      vtklut->SetRange(0,256*256-1);
+      data->GetPointData()->GetScalars()->SetLookupTable( vtklut );
+      vtklut->Delete();
+#else
+      vtkWarningMacro( "Unhandled" );
+#endif
+      }
+    }
+  else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME1 )
+    {
+    this->ImageFormat = VTK_INVERSE_LUMINANCE;
+    vtkWindowLevelLookupTable *vtklut = vtkWindowLevelLookupTable::New();
+    // Technically we could also use the first of the Window Width / Window Center
+    // oh well, if they are missing let's just compute something:
+    int64_t min = pixeltype.GetMin();
+    int64_t max = pixeltype.GetMax(); 
+    vtklut->SetWindow( max - min );
+    vtklut->SetLevel( 0.5 * (max + min) );
+    //vtklut->SetWindow(1024); // WindowWidth
+    //vtklut->SetLevel(550); // WindowCenter
+    vtklut->InverseVideoOn();
+    data->GetPointData()->GetScalars()->SetLookupTable( vtklut );
+    vtklut->Delete();
+    }
+  else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::YBR_FULL_422 )
+    {
+    if( image.GetPixelFormat().GetSamplesPerPixel() == 3 )
+      {
+      this->ImageFormat = VTK_RGB; // FIXME 
+      }
+    else if( image.GetPixelFormat().GetSamplesPerPixel() == 1 )
+      {
+      abort();
+      vtkWarningMacro( "Image was declared as YBR_FULL_422 but is just grayscale" );
+      this->ImageFormat = VTK_LUMINANCE;
+      }
+    }
+  else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::YBR_FULL )
+    {
+    this->ImageFormat = VTK_YBR;
+    }
+  else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::RGB )
+    {
+    this->ImageFormat = VTK_RGB;
+    }
+  else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::MONOCHROME2 )
+    {
+    this->ImageFormat = VTK_LUMINANCE;
+    }
+  else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::YBR_RCT )
+    {
+    this->ImageFormat = VTK_RGB;
+    }
+  else if ( image.GetPhotometricInterpretation() == gdcm::PhotometricInterpretation::YBR_ICT )
+    {
+    this->ImageFormat = VTK_RGB;
+    }
+  assert( this->ImageFormat );
+
+  long outsize = pixeltype.GetPixelSize()*(dext[1] - dext[0] + 1);
+  if( numoverlays ) assert( (unsigned long)overlayoutsize * ( dext[3] - dext[2] + 1 ) == overlaylen );
+  if( this->FileName) assert( (unsigned long)outsize * (dext[3] - dext[2]+1) * (dext[5]-dext[4]+1) == len );
+
+  return 1; // success
+}
+
+
+//----------------------------------------------------------------------------
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+int vtkbisGDCMImageReader::RequestData(vtkInformation *vtkNotUsed(request),
+                                vtkInformationVector **vtkNotUsed(inputVector),
+                                vtkInformationVector *outputVector)
+{
+  (void)outputVector;
+  //this->UpdateProgress(0.2);
+
+  // Make sure the output dimension is OK, and allocate its scalars
+
+  for(int i = 0; i < this->GetNumberOfOutputPorts(); ++i)
+  {
+  // Copy/paste from vtkImageAlgorithm::AllocateScalars. Cf. "this needs to be fixed -Ken"
+    vtkStreamingDemandDrivenPipeline *sddp = 
+      vtkStreamingDemandDrivenPipeline::SafeDownCast(this->GetExecutive());
+    if (sddp)
+      {
+      int extent[6];
+      sddp->GetOutputInformation(i)->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),extent);
+      this->GetOutput(i)->SetExtent(extent);
+      }
+    this->GetOutput(i)->AllocateScalars();
+  }
+  int res = RequestDataCompat();
+  return res;
+}
+#endif
+
+//----------------------------------------------------------------------------
+int vtkbisGDCMImageReader::RequestDataCompat()
+{
+  vtkImageData *output = this->GetOutput(0);
+  output->GetPointData()->GetScalars()->SetName("GDCMImage");
+
+  char * pointer = static_cast<char*>(output->GetScalarPointer());
+  if( this->FileName )
+    {
+    const char *filename = this->FileName;
+    unsigned long len;
+    int load = this->LoadSingleFile( filename, pointer, len ); (void)len;
+    if( !load )
+      {
+      // FIXME: I need to fill the buffer with 0, shouldn't I ?
+      return 0;
+      }
+    }
+  else if( this->FileNames && this->FileNames->GetNumberOfValues() >= 1 )
+    {
+    // Load each 2D files
+    int *dext = this->GetDataExtent();
+    // HACK: len is moved out of the loop so that when file > 1 start failing we can still know
+    // the len of the buffer...technically all file should have the same len (not checked for now)
+    unsigned long len = 0;
+    for(int j = dext[4]; j <= dext[5]; ++j)
+      {
+      const char *filename = this->FileNames->GetValue( j );
+      int load = this->LoadSingleFile( filename, pointer, len );
+      if( !load )
+        {
+        // hum... we could not read this file within the series, let's just fill
+        // the slice with 0 value, hopefully this should be the right thing to do
+        memset( pointer, 0, len);
+        }
+      assert( len );
+      pointer += len;
+      }
+    }
+  else
+    {
+    return 0;
+    }
+  // Y-flip image
+  if (!this->FileLowerLeft)
+    {
+    InPlaceYFlipImage(this->GetOutput(0));
+    if( this->LoadIconImage )
+      {
+      InPlaceYFlipImage(this->GetOutput(ICONIMAGEPORTNUMBER));
+      }
+    for( int ovidx = 0;  ovidx < this->NumberOfOverlays; ++ovidx )
+      {
+      assert( this->LoadOverlays );
+      InPlaceYFlipImage(this->GetOutput(OVERLAYPORTNUMBER+ovidx));
+      }
+    }
+
+  return 1;
+}
+
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+vtkAlgorithmOutput* vtkbisGDCMImageReader::GetOverlayPort(int index)
+{
+  if( index >= 0 && index < this->NumberOfOverlays)
+    return this->GetOutputPort(index+OVERLAYPORTNUMBER);
+  return NULL;
+}
+vtkAlgorithmOutput* vtkbisGDCMImageReader::GetIconImagePort()
+{
+  const int index = 0;
+  if( index >= 0 && index < this->NumberOfIconImages)
+    return this->GetOutputPort(index+ICONIMAGEPORTNUMBER);
+  return NULL;
+}
+#endif
+
+//----------------------------------------------------------------------------
+vtkImageData* vtkbisGDCMImageReader::GetOverlay(int i)
+{
+  if( i >= 0 && i < this->NumberOfOverlays)
+    return this->GetOutput(i+OVERLAYPORTNUMBER);
+  return NULL;
+}
+//----------------------------------------------------------------------------
+vtkImageData* vtkbisGDCMImageReader::GetIconImage()
+{
+  const int i = 0;
+  if( i >= 0 && i < this->NumberOfIconImages)
+    return this->GetOutput(i+ICONIMAGEPORTNUMBER);
+  return NULL;
+}
+
+//----------------------------------------------------------------------------
+void vtkbisGDCMImageReader::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+}
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkbisGDCMImageReader.h b/bioimagesuite30_src/Common/vtkbisGDCMImageReader.h
new file mode 100644
index 0000000..d60f0b3
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisGDCMImageReader.h
@@ -0,0 +1,306 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program: GDCM (Grassroots DICOM). A DICOM library
+  Module:  $URL$
+
+  Copyright (c) 2006-2008 Mathieu Malaterre
+  All rights reserved.
+  See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html 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 vtkbisGDCMImageReader - read DICOM Image files (Pixel Data)
+// .SECTION Description
+// vtkbisGDCMImageReader is a source object that reads some DICOM files
+// this reader is single threaded.
+// .SECTION Implementation note: when FileLowerLeft is set to on the image is not flipped
+// upside down as VTK would expect, use this option only if you know what you are doing.
+// .SECTION Implementation note: when reading a series of 2D slices, user is
+// expected to provide an ordered list of filenames. No sorting will be applied afterward. 
+// .SECTION Implementation note: Although 99% of the time the Zspacing as read 
+// from a tag in a 2D DICOM file should be correct, there has been reports that this 
+// value can be missing, or incorrect, in which case users are advised to override this 
+// value using the return value from gdcm::IPPSorter::GetZSpacing() and set it via 
+// vtkImageChangeInformation on the reader itself.
+// .SECTION TODO
+// This reader does not handle a series of 3D images, only a single 3D (multi frame) or a 
+// list of 2D files are supported for now.
+// .SECTION BUG
+// Overlay are assumed to have the same extent as image. Right now if overlay origin is not
+// 0,0 the overlay will have an offset...
+// Only the very first overlay is loaded at the VTK level, for now (even if there are more than one in the file)
+// .SECTION DataOrigin
+// When the reader is instanciated with FileLowerLeftOn the DataOrigin and Image Position (Patient) are
+// identical. But when FileLowerLeft is Off, we have to reorder the Y-line of the image, and thus the DataOrigin
+// is then translated to the other side of the image.
+// .SECTION Spacing
+// When reading a 3D volume, the spacing along the Z dimension might be negative
+// .SECTION Warning
+// When using vtkGDCMPolyDataReader in conjonction with vtkbisGDCMImageReader 
+// it is *required* that FileLowerLeft is set to ON as coordinate system
+// would be inconsistant in between the two data structures.
+
+// .SECTION See Also
+// vtkMedicalImageReader2 vtkMedicalImageProperties vtkGDCMPolyDataReader
+
+#ifndef __vtkbisGDCMImageReader_h
+#define __vtkbisGDCMImageReader_h
+
+#include "vtkMedicalImageReader2.h"
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+#else
+class vtkMedicalImageProperties;
+#endif
+#if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
+#else
+class vtkStringArray;
+#endif
+class vtkPolyData;
+
+// vtkSystemIncludes.h defines:
+// #define VTK_LUMINANCE       1
+// #define VTK_LUMINANCE_ALPHA 2
+// #define VTK_RGB             3
+// #define VTK_RGBA            4
+#ifndef VTK_INVERSE_LUMINANCE
+#define VTK_INVERSE_LUMINANCE 5
+#endif
+#ifndef VTK_LOOKUP_TABLE
+#define VTK_LOOKUP_TABLE 6
+#endif
+#ifndef VTK_YBR
+#define VTK_YBR 7
+#endif
+
+//BTX
+namespace gdcm { class ImageReader; }
+//ETX
+class vtkMatrix4x4;
+class VTK_EXPORT vtkbisGDCMImageReader : public vtkMedicalImageReader2
+{
+public:
+  static vtkbisGDCMImageReader *New();
+  vtkTypeRevisionMacro(vtkbisGDCMImageReader,vtkMedicalImageReader2);
+  virtual void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description: is the given file name a DICOM file containing an image ?
+  virtual int CanReadFile(const char* fname);
+
+  // Description:
+  // Valid extensions
+  virtual const char* GetFileExtensions()
+    {
+    // I would like to get rid of ACR/NEMA/IMA so only allow dcm extension for now
+    return ".dcm .DCM";
+    }
+
+  // Description: 
+  // A descriptive name for this format
+  virtual const char* GetDescriptiveName()
+    {
+    return "DICOM";
+    }
+
+  // Description:
+  // Get the Image Position (Patient) as stored in the DICOM file
+  // This is a read-only data member
+  vtkGetObjectMacro(DirectionCosines, vtkMatrix4x4);
+
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+#else
+  // Description:
+  // Get the medical image properties object
+  vtkGetObjectMacro(MedicalImageProperties, vtkMedicalImageProperties);
+#endif
+
+#if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
+#else
+  virtual void SetFileNames(vtkStringArray*);
+  vtkGetObjectMacro(FileNames, vtkStringArray);
+#endif
+
+  // Description:
+  // Specifically request to load the overlay into the gdcm-VTK layer (gdcm always loads them when found).
+  // If no overlay is found in the image, then the vtkImageData for the overlay will be empty.
+  vtkGetMacro(LoadOverlays,int);
+  vtkSetMacro(LoadOverlays,int);
+  vtkBooleanMacro(LoadOverlays,int);
+
+  // Description:
+  // Set/Get whether or not to load the Icon as vtkImageData (if found in the DICOM file)
+  vtkGetMacro(LoadIconImage,int);
+  vtkSetMacro(LoadIconImage,int);
+  vtkBooleanMacro(LoadIconImage,int);
+
+  // Description:
+  // Read only: number of overlays as found in this image (multiple overlays per slice is allowed)
+  vtkGetMacro(NumberOfOverlays,int);
+
+  // Description:
+  // Read only: number of icon image (there should ony be one)
+  vtkGetMacro(NumberOfIconImages,int);
+
+  // Description:
+  // Get Overlay/IconImage
+  // Remember to ALWAYS use those methods in your code, as the internal number for the output port
+  // is not garantee to remain the same, as features are added to the reader
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+//FIXME: Need to get rid of BTX/ETX if only the Python Wrapper of VTK 4.2 would let me
+//BTX
+  vtkAlgorithmOutput* GetOverlayPort(int index);
+  vtkAlgorithmOutput* GetIconImagePort();
+//ETX
+#endif
+  vtkImageData* GetOverlay(int i);
+  vtkImageData* GetIconImage();
+
+  // Description:
+  // Load image with its associated Lookup Table
+  vtkGetMacro(ApplyLookupTable,int);
+  vtkSetMacro(ApplyLookupTable,int);
+  vtkBooleanMacro(ApplyLookupTable,int);
+
+  // Description:
+  // Load image as YBR
+  vtkGetMacro(ApplyYBRToRGB,int)
+  vtkSetMacro(ApplyYBRToRGB,int)
+  vtkBooleanMacro(ApplyYBRToRGB,int);
+
+  // Description:
+  // Return VTK_LUMINANCE, VTK_RGB, VTK_LOOKUP_TABLE or VTK_YBR, VTK_RGB_PLANES
+  vtkGetMacro(ImageFormat,int);
+
+  // Description:
+  // Return the Planar Configuration. This simply means that the internal DICOM image was stored
+  // using a particular planar configuration (most of the time: 0)
+  vtkGetMacro(PlanarConfiguration,int);
+
+  // Description:
+  // Return the 'raw' information stored in the DICOM file:
+  // In case of a series of multiple files, only the first file is considered. The Image Orientation (Patient)
+  // is garantee to remain the same, and image Image Position (Patient) in other slice can be computed
+  // using the ZSpacing (3rd dimension)
+  // (0020,0032) DS [87.774866\-182.908510\168.629671]       #  32, 3 ImagePositionPatient
+  // (0020,0037) DS [0.001479\0.999989\-0.004376\-0.002039\-0.004372\-0.999988] #  58, 6 ImageOrientationPatient
+  vtkGetVector3Macro(ImagePositionPatient,double);
+  vtkGetVector6Macro(ImageOrientationPatient,double);
+
+  // Set/Get the first Curve Data:
+  vtkGetObjectMacro(Curve,vtkPolyData);
+  virtual void SetCurve(vtkPolyData *pd);
+
+  // Modality LUT
+  // DEPRECATED:
+  // Value returned by GetShift/GetScale might be innacurate since Shift/Scale could be
+  // varying along the Series read. Therefore user are advices not to use those function
+  // anymore
+  vtkGetMacro(Shift,double);
+  vtkGetMacro(Scale,double);
+
+  // Z Spacing -- force for 3D Data
+  vtkGetMacro(ForceZSpacing,double);
+  vtkSetMacro(ForceZSpacing,double);
+
+
+protected:
+  vtkbisGDCMImageReader();
+  ~vtkbisGDCMImageReader();
+
+//BTX
+  virtual void FillMedicalImageInformation(const gdcm::ImageReader &reader);
+//ETX
+  int RequestInformationCompat();
+  int RequestDataCompat();
+
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+  int ProcessRequest(vtkInformation* request,
+                                 vtkInformationVector** inputVector,
+                                 vtkInformationVector* outputVector);
+  int RequestInformation(vtkInformation *request,
+                         vtkInformationVector **inputVector,
+                         vtkInformationVector *outputVector);
+  int RequestData(vtkInformation *request,
+                  vtkInformationVector **inputVector,
+                  vtkInformationVector *outputVector);
+#else /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/
+  void ExecuteInformation();
+  void ExecuteData(vtkDataObject *out);
+#endif /*(VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )*/
+
+protected:
+#if (VTK_MAJOR_VERSION >= 5) || ( VTK_MAJOR_VERSION == 4 && VTK_MINOR_VERSION > 5 )
+#else
+  // Description:
+  // Medical Image properties
+  vtkMedicalImageProperties *MedicalImageProperties;
+#endif
+#if ( VTK_MAJOR_VERSION == 5 && VTK_MINOR_VERSION > 0 )
+#else
+  vtkStringArray *FileNames;
+#endif
+
+  vtkMatrix4x4 *DirectionCosines;
+  int LoadOverlays;
+  int NumberOfOverlays;
+  int LoadIconImage;
+  int NumberOfIconImages;
+  int IconImageDataExtent[6];
+  double ImagePositionPatient[3];
+  double ImageOrientationPatient[6];
+  vtkPolyData *Curve;
+
+  int ImageFormat;
+  // the following 3, should remain optional
+  int ApplyInverseVideo;
+  int ApplyLookupTable;
+  int ApplyYBRToRGB;
+  // I think that planar configuration need to always be applied as far as VTK is concerned
+  int ApplyPlanarConfiguration;
+  int ApplyShiftScale;
+
+  int LoadSingleFile(const char *filename, char *pointer, unsigned long &outlen);
+
+  double Shift;
+  double Scale;
+  int IconDataScalarType;
+  int IconNumberOfScalarComponents;
+  int PlanarConfiguration;
+  double ForceZSpacing;
+
+private:
+  vtkbisGDCMImageReader(const vtkbisGDCMImageReader&);  // Not implemented.
+  void operator=(const vtkbisGDCMImageReader&);  // Not implemented.
+};
+#endif
+
+
diff --git a/bioimagesuite30_src/Common/vtkbisImageHeader.cpp b/bioimagesuite30_src/Common/vtkbisImageHeader.cpp
new file mode 100644
index 0000000..e430975
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisImageHeader.cpp
@@ -0,0 +1,2954 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/* =========================================================================*/
+
+#include "vtkbisImageHeader.h"
+#include "vtkbisNIFTIExtensionsList.h"
+#include "vtkbisNIFTIExtension.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkImageShiftScale.h"
+#include "vtkXMLDataElement.h"
+#include "vtkMath.h"
+#include "vtkMatrix4x4.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+#include "vtkTransform.h"
+#include <vtkInformation.h>
+#include "vtkImageReslice.h"
+#include "vtkpxUtil.h"
+#include "pxutil.h"
+
+#include <string>
+
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+vtkbisImageHeader* vtkbisImageHeader::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisImageHeader");
+  if(ret)
+    {
+      return (vtkbisImageHeader*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisImageHeader;
+}
+// ----------------------------------------------------
+vtkbisImageHeader::vtkbisImageHeader()
+{
+  this->Header=new nifti_1_header;
+  this->Extensions=vtkbisNIFTIExtensionsList::New();
+  this->FileName=new char[500];
+  strcpy(this->FileName,"");
+  this->ResetFields();
+  this->Buffer="";
+}
+// ----------------------------------------------------
+vtkbisImageHeader::~vtkbisImageHeader()
+{
+  if (this->Header)
+    delete this->Header;
+
+  if (this->FileName)
+    delete [] this->FileName;
+
+  this->Extensions->Delete();
+}
+// ----------------------------------------------------
+int vtkbisImageHeader::ResetFields()
+{
+  this->Extensions->Cleanup();
+  this->Mode=0;
+  strcpy(FileName,"none.hdr");
+  // Description:
+  // Other Flags
+  this->IsHeaderValid=0;
+  this->HeaderOffset=0;
+  this->SwapBytes=0;
+  this->Orientation=0;
+  this->OriginBuffer[0]=  this->OriginBuffer[1]=  this->OriginBuffer[2]=0.0;
+
+  vtkbisImageHeader::InitializeHeader(this->Header);
+  return 1;
+}
+
+
+int vtkbisImageHeader::CopyHeader(const nifti_1_header* input,nifti_1_header* output)
+{
+  if (input==NULL || output==NULL)
+    return 0;
+  memcpy(output, input, sizeof(nifti_1_header));
+  return 1;
+}
+
+
+int vtkbisImageHeader::InitializeHeader(nifti_1_header* header)
+{
+  if (header==NULL)
+    return 0;
+
+  // NIFTI1 -- Initialize
+  header->sizeof_hdr=348;;          /*!< MUST be 348           */  /* int sizeof_hdr;      */
+  strcpy(header->data_type,"");     /*!< ++UNUSED++            */  /* char data_type[10];  */
+  strcpy(header->db_name,"none");   /*!< ++UNUSED++            */  /* char db_name[18];    */
+  header->extents=0;        /*!< ++UNUSED++            */  /* int extents;         */
+  header->session_error=0; /*!< ++UNUSED++            */  /* short session_error; */
+  header->regular=0;       /*!< ++UNUSED++            */  /* char regular;        */
+  header->dim_info=0;      /*!< MRI slice ordering.   */  /* char hkey_un0;       */
+
+  /*--- was image_dimension substruct ---*/
+  /*!< Data array dimensions.*/  /* short dim[8];        */
+  for (int ia=0;ia<8;ia++) header->dim[ia]=0;
+
+  header->intent_p1=0 ;    /*!< 1st intent parameter. */  /* short unused8;       */
+  /* short unused9;       */
+  header->intent_p2=0 ;    /*!< 2nd intent parameter. */  /* short unused10;      */
+  /* short unused11;      */
+  header->intent_p3=0 ;    /*!< 3rd intent parameter. */  /* short unused12;      */
+  /* short unused13;      */
+  header->intent_code=0 ;  /*!< NIFTI_INTENT_* code.  */  /* short unused14;      */
+  header->datatype=4;      /*!< Defines data type!    */  /* short datatype;      */
+  header->bitpix=16;        /*!< Number bits/voxel.    */  /* short bitpix;        */
+  header->slice_start=0;   /*!< First slice index.    */  /* short dim_un0;       */
+
+    /*!< Grid spacings.        */  /* float pixdim[8];     */
+  for (int ia=0;ia<8;ia++) header->pixdim[ia]=1.0;
+
+  header->vox_offset=0.0;    /*!< Offset into .nii file */  /* float vox_offset;    */
+  header->scl_slope=1.0;    /*!< Data scaling: slope.  */  /* float funused1;      */
+  header->scl_inter=0.0;    /*!< Data scaling: offset. */  /* float funused2;      */
+  header->slice_end=0;     /*!< Last slice index.     */  /* float funused3;      */
+  header->slice_code=0;   /*!< Slice timing order.   */
+  /*!< Units of pixdim[1..4] */
+  header->xyzt_units=NIFTI_UNITS_MM;
+  header->cal_max=255;       /*!< Max display intensity */  /* float cal_max;       */
+  header->cal_min=0;       /*!< Min display intensity */  /* float cal_min;       */
+  header->slice_duration=1.0;/*!< Time for 1 slice.     */  /* float compressed;    */
+  header->toffset=0.0;       /*!< Time axis shift.      */  /* float verified;      */
+  header->glmax=255;         /*!< ++UNUSED++            */  /* int glmax;           */
+  header->glmin=0;         /*!< ++UNUSED++            */  /* int glmin;           */
+  /*--- was data_history substruct ---*/
+  strcpy(header->descrip,"default bisImageHeader");   /*!< any text you like.    */  /* char descrip[80];    */
+  strcpy(header->aux_file,"none");  /*!< auxiliary filename.   */  /* char aux_file[24];   */
+
+  header->qform_code=0 ;   /*!< NIFTI_XFORM_* code.   */  /*-- all ANALYZE 7.5 ---*/
+  header->sform_code=1 ;   /*!< NIFTI_XFORM_* code.   */  /*   fields below here  */
+  /*   are replaced       */
+  header->quatern_b=0.0 ;    /*!< Quaternion b param.   */
+  header->quatern_c=0.0 ;    /*!< Quaternion c param.   */
+  header->quatern_d=0.0 ;    /*!< Quaternion d param.   */
+  header->qoffset_x=0.0 ;    /*!< Quaternion x shift.   */
+  header->qoffset_y=0.0 ;    /*!< Quaternion y shift.   */
+  header->qoffset_z=0.0 ;    /*!< Quaternion z shift.   */
+
+  /*!< 1st row affine transform.   */
+  header->srow_x[0]=-1.0;  header->srow_x[1]= 0.0;  header->srow_x[2]= 0.0;  header->srow_x[3]= 0.0;
+  /*!< 2nd row affine transform.   */
+  header->srow_y[0]= 0.0;  header->srow_y[1]=-1.0;  header->srow_y[2]= 0.0;  header->srow_y[3]= 0.0;
+  /*!< 3rd row affine transform.   */
+  header->srow_z[0]= 0.0;  header->srow_z[1]= 0.0;  header->srow_z[2]= 1.0;  header->srow_z[3]= 0.0;
+
+  header->intent_name[0]=(char)0;
+  strcpy(header->magic,"ni1\0");
+  return 1;
+}
+
+// -------------------------------------------------------------------------------------
+double vtkbisImageHeader::GetIntensityScale()
+{
+  nifti_1_header *hdr=this->Header;
+  return hdr->scl_slope;
+}
+// -------------------------------------------------------------------------------------
+double vtkbisImageHeader::GetIntensityOffset()
+{
+  nifti_1_header *hdr=this->Header;
+  return hdr->scl_inter;
+
+}
+
+// -------------------------------------------------------------------------------------
+void vtkbisImageHeader::GetDimensions(int dim[3])
+{
+  for (int ia=0;ia<=2;ia++)
+    dim[ia]=this->Header->dim[1+ia];
+}
+
+int vtkbisImageHeader::GetNumberOfComponents()
+{
+  return this->Header->dim[4];
+}
+
+void vtkbisImageHeader::GetSpacing(double spa[3])
+{
+  int flag=0;
+  if (this->Header->qform_code==0 && this->Header->sform_code>0) 
+    {
+      //      fprintf(stderr,"\t\t\t\t Incoming q_spacing spacing header=(%.2f,%.2f,%.2f)\n",
+      //	      this->Header->pixdim[1],this->Header->pixdim[2],this->Header->pixdim[3]);
+  
+      for (int ia=0;ia<=2;ia++)
+	spa[ia]=fabs(this->Header->pixdim[ia+1]);
+      
+      mat44 mat;  NIFTI_identity_mat44(&mat);
+      for (int ia=0;ia<=3;ia++)
+	{
+	  mat.m[0][ia]=this->Header->srow_x[ia];
+	  mat.m[1][ia]=this->Header->srow_y[ia];
+	  mat.m[2][ia]=this->Header->srow_z[ia];
+	}
+
+      float quatern_b,quatern_c,quatern_d,qoffset_x,qoffset_y,qoffset_z,pixdim[4];
+      nifti_mat44_to_quatern(mat,
+			     &quatern_b,&quatern_c,&quatern_d,
+			     &qoffset_x,&qoffset_y,&qoffset_z,
+			     &pixdim[1],&pixdim[2],&pixdim[3],
+			     &pixdim[0]);
+      for (int ia=0;ia<=3;ia++)
+	this->Header->pixdim[ia]=pixdim[ia];
+      flag=1;
+    }
+
+  for (int ia=0;ia<=2;ia++)
+    spa[ia]=fabs(this->Header->pixdim[ia+1]);
+
+  /*  if (flag)
+    fprintf(stderr,"\t\t\t\t Post q_spacing spacing header=(%.2f,%.2f,%.2f)\n",
+    spa[0],spa[1],spa[2]);*/
+
+
+
+}
+
+
+int vtkbisImageHeader::GetVTKDataType()
+{
+  if (this->IsHeaderValid==0)
+    return VTK_SHORT;
+
+  return vtkbisImageHeader::GetVTKDataType(this->Header->datatype);
+  //return this->Header->datatype;
+  
+}
+// -------------------------------------------------------------------------------------
+int vtkbisImageHeader::GetNIFTIDataType(int vtkdatatype)
+{
+  switch(vtkdatatype)
+    {
+    case  (VTK_UNSIGNED_CHAR):
+      return DT_UINT8;
+      break;
+
+    case (VTK_CHAR):
+      return DT_INT8;
+      break;
+
+    case (VTK_UNSIGNED_SHORT):
+      return DT_UINT16;
+      break;
+
+    case (VTK_SHORT):
+      return DT_INT16;
+      break;
+
+    case (VTK_UNSIGNED_INT):
+      return DT_UINT32;
+      break;
+
+    case (VTK_INT):
+    return DT_INT32;
+      break;
+
+    case (VTK_FLOAT):
+      return DT_FLOAT;
+      break;
+
+    case (VTK_DOUBLE):
+      return DT_DOUBLE;
+      break;
+    }
+
+  return DT_INT16;
+}
+
+int vtkbisImageHeader::GetBitPix(int vtkdatatype)
+{
+  switch(vtkdatatype)
+    {
+    case  (VTK_UNSIGNED_CHAR):
+    case (VTK_CHAR):
+      return 8;
+      break;
+
+    case (VTK_UNSIGNED_SHORT):
+    case (VTK_SHORT):
+      return 16;
+      break;
+
+    case (VTK_UNSIGNED_INT):
+    case (VTK_INT):
+    case (VTK_FLOAT):
+      return 32;
+      break;
+
+    case (VTK_DOUBLE):
+      return 64;
+      break;
+    }
+
+  return 16;
+}
+
+
+int vtkbisImageHeader::GetVTKDataType(int niftidatatype)
+{
+  //	fprintf(stderr, "in GetVTKDataType %d\n", niftidatatype); 
+  switch(niftidatatype)
+    {
+    case DT_UINT8:
+      return (VTK_UNSIGNED_CHAR);
+      break;
+
+    case DT_INT8:
+      return (VTK_CHAR);
+      break;
+
+    case DT_UINT16:
+      return (VTK_UNSIGNED_SHORT);
+      break;
+
+    case DT_INT16:
+      return (VTK_SHORT);
+      break;
+
+    case DT_UINT32:
+      return (VTK_UNSIGNED_INT);
+      break;
+
+    case DT_INT32:
+      return (VTK_INT);
+      break;
+
+    case DT_FLOAT:
+      return (VTK_FLOAT);
+      break;
+
+    case DT_DOUBLE:
+      return (VTK_DOUBLE);
+      break;
+    }
+
+  return VTK_SHORT;
+}
+// -----------------------------------------------------------------------------------
+int vtkbisImageHeader::GetIndexedDataType()
+{
+  int niftidatatype=this->Header->datatype;
+
+  switch(niftidatatype)
+    {
+    case DT_UINT8:
+      return 0;
+      break;
+
+    case DT_INT8:
+      return 1;
+      break;
+
+    case DT_UINT16:
+      return 2;
+      break;
+
+    case DT_INT16:
+      return 3;
+      break;
+
+    case DT_UINT32:
+      return 4;
+      break;
+
+    case DT_INT32:
+      return 5;
+      break;
+
+    case DT_FLOAT:
+      return 6;
+      break;
+
+    case DT_DOUBLE:
+      return 7;
+      break;
+    }
+
+  return 3;
+}
+// -----------------------------------------------------------------------------------
+void vtkbisImageHeader::SetIndexedDataType(int indexedtype)
+{
+  switch(indexedtype)
+    {
+    case 0:
+      this->Header->datatype=DT_UINT8;
+      this->Header->bitpix=8;
+      break;
+
+    case 1:
+      this->Header->datatype=DT_INT8;
+      this->Header->bitpix=8;
+      break;
+
+    case 2:
+      this->Header->datatype=DT_UINT16;
+      this->Header->bitpix=16;
+      break;
+
+
+    case 4:
+      this->Header->datatype=DT_UINT32;
+      this->Header->bitpix=32;
+      break;
+
+    case 5:
+      this->Header->datatype=DT_INT32;
+      this->Header->bitpix=32;
+      break;
+
+    case 6:
+      this->Header->datatype=DT_FLOAT;
+      this->Header->bitpix=32;
+      break;
+
+    case 7:
+      this->Header->datatype=DT_DOUBLE;
+      this->Header->bitpix=64;
+      break;
+
+    case 3:
+    default:
+      this->Header->datatype=DT_INT16;
+      this->Header->bitpix=16;
+      break;
+    }
+
+}
+// -----------------------------------------------------------------------------------
+int vtkbisImageHeader::CreateHeader(vtkImageData* img,int useorigin)
+{
+  if (img==NULL)
+    return 0;
+
+  this->ResetFields();
+  this->Mode=0;
+  int dim[3]; img->GetDimensions(dim);
+  double spa[3]; img->GetSpacing(spa);
+
+  this->Header->dim[1]=dim[0];   this->Header->dim[2]=dim[1];   this->Header->dim[3]=dim[2];
+  this->Header->dim[4]=img->GetNumberOfScalarComponents();
+  this->Header->dim[0]=(img->GetNumberOfScalarComponents()>1);
+  this->Header->datatype=vtkbisImageHeader::GetNIFTIDataType(img->GetScalarType());
+  this->Header->bitpix=vtkbisImageHeader::GetBitPix(img->GetScalarType());
+
+  this->Header->pixdim[1]=spa[0];      this->Header->srow_x[0]=-spa[0];
+  this->Header->pixdim[2]=spa[1];      this->Header->srow_y[1]=-spa[1];
+  this->Header->pixdim[3]=spa[2];      this->Header->srow_z[2]= spa[2];
+
+
+  double range[2]; img->GetPointData()->GetScalars()->GetRange(range);
+  this->Header->cal_min=range[0];
+  this->Header->glmin=(int)range[0];
+  this->Header->glmax=(int)range[1];
+
+  this->Orientation=0;
+  if (useorigin)
+    this->SetOrigin(img->GetOrigin());
+
+  this->Extensions->Cleanup();
+  this->IsHeaderValid=1;
+  //  this->PrintAll(0);
+  //  this->PrintHeader();
+  return 1;
+}
+
+// -----------------------------------------------------------------------------------
+int vtkbisImageHeader::CopyHeader(vtkbisImageHeader* other)
+{
+  if (other==NULL)
+    return 0;
+  this->Mode=other->GetMode();
+  this->SetFileName(other->GetFileName());
+  vtkbisImageHeader::CopyHeader(other->GetRawHeader(),this->Header);
+  this->IsHeaderValid=other->GetIsHeaderValid();
+  this->HeaderOffset=other->GetHeaderOffset();
+  this->SwapBytes=other->GetSwapBytes();
+  this->Orientation=other->GetOrientation();
+  this->Extensions->Copy(other->GetExtensions());
+  return 1;
+}
+// -----------------------------------------------------------------------------------
+int vtkbisImageHeader::CopyNIFTIHeader(const nifti_1_header* header)
+{
+  if (header==NULL)
+    return 0;
+  this->ResetFields();
+  vtkbisImageHeader::CopyHeader(header,this->Header);
+  this->Mode=1;
+  this->Orientation=0;
+  this->IsHeaderValid=1;
+  this->SetFileName("");
+  return 1;
+}
+
+int vtkbisImageHeader::StoreInNIFTIHeader(nifti_1_header* header)
+{
+  if (header==NULL)
+    return 0;
+
+  vtkbisImageHeader::CopyHeader(this->Header,header);
+  return 1;
+}
+
+// -----------------------------------------------------------------------------------
+int vtkbisImageHeader::AddComment(const char* comment)
+{
+  this->Extensions->AddExtension(comment,4);
+  return 1;
+}
+
+// -----------------------------------------------------------------------------------
+int vtkbisImageHeader::AddComment(const char* comment,int ecode)
+{
+  this->Extensions->AddExtension(comment,ecode);
+  return 1;
+}
+
+// -----------------------------------------------------------------------------------
+void vtkbisImageHeader::SetImageStructureFromHeader(vtkImageData* img)
+{
+  if (this->IsHeaderValid==0 || img==NULL)
+  {
+	  fprintf(stderr, "HeaderValid = %d and img null = %d \n", this->IsHeaderValid, (img==NULL)); 
+    return;
+  }
+
+  img->SetOrigin(0.0,0.0,0.0);
+  //fprintf(stderr, "in bisImageHeader %d %d %d\n", this->Header->dim[1], this->Header->dim[2], this->Header->dim[3]); 
+  //fprintf(stderr, "in bisImageHeader %d %d\n", this->GetVTKDataType(), this->Header->datatype); 
+
+  img->SetDimensions(this->Header->dim[1],this->Header->dim[2],this->Header->dim[3]);
+  img->SetNumberOfScalarComponents(this->Header->dim[4]);
+  img->SetSpacing(fabs(this->Header->pixdim[1]),
+		  fabs(this->Header->pixdim[2]),
+		  fabs(this->Header->pixdim[3]));
+  img->SetScalarType(this->GetVTKDataType());
+}
+
+vtkImageData* vtkbisImageHeader::AllocateImageFromHeaderInfo()
+{
+
+  if (this->IsHeaderValid==0)
+    return NULL;
+
+  vtkImageData* img=vtkImageData::New();
+  img->SetDimensions(this->Header->dim[1],this->Header->dim[2],this->Header->dim[3]);
+  img->SetNumberOfScalarComponents(this->Header->dim[4]);
+  img->SetSpacing(fabs(this->Header->pixdim[1]),
+		  fabs(this->Header->pixdim[2]),
+		  fabs(this->Header->pixdim[3]));
+  img->SetScalarType(this->GetVTKDataType());
+  img->AllocateScalars();
+
+  for (int ia=0;ia<this->Header->dim[4];ia++)
+    img->GetPointData()->GetScalars()->FillComponent(ia,0.0);
+  return img;
+}
+
+// -----------------------------------------------------------------------------------
+// Handling the Origin Flag from some Analyze Format Stuff ...........................
+// -----------------------------------------------------------------------------------
+double vtkbisImageHeader::GetOriginComponent(int a)
+{
+  if (a<0) a=0;
+  if (a>2) a=2;
+  double ori[3]; this->GetOrigin(ori);
+  return ori[a];
+}
+void vtkbisImageHeader::GetOrigin(double origin[3])
+{
+  origin[0]=origin[1]=origin[2]=0.0;
+  if (this->IsHeaderValid==0)
+    return;
+
+  if (this->Header->qform_code>0)
+    {
+      origin[0]=this->Header->qoffset_x;
+      origin[1]=this->Header->qoffset_y;
+      origin[2]=this->Header->qoffset_z;
+      return;
+    }
+
+  if (this->Header->sform_code>0)
+    {
+      origin[0]=this->Header->srow_x[3];
+      origin[1]=this->Header->srow_y[3];
+      origin[2]=this->Header->srow_z[3];
+    }
+
+}
+
+/*void double* vtkbisImageHeader::GetOrigin()
+{
+  this->GetOrigin(this->OriginBuffer);
+  return &this->OriginBuffer[0];
+  }*/
+
+void vtkbisImageHeader::SetOrigin(double x,double y,double z)
+{
+  this->OriginBuffer[0]=x;
+  this->OriginBuffer[1]=y;
+  this->OriginBuffer[2]=z;
+
+  if (this->Header->qform_code>0)
+    {
+      this->Header->qoffset_x=x;
+      this->Header->qoffset_y=y;
+      this->Header->qoffset_z=z;
+      return;
+    }
+
+  this->Header->srow_x[3]=x;
+  this->Header->srow_y[3]=y;
+  this->Header->srow_z[3]=z;
+  if (this->Header->sform_code==0)
+    {
+      this->Header->sform_code=1;
+      this->Header->srow_x[0]=-1.0;  this->Header->srow_x[1]= 0.0;  this->Header->srow_x[2]= 0.0;
+      this->Header->srow_y[0]= 0.0;  this->Header->srow_y[1]=-1.0;  this->Header->srow_y[2]= 0.0;
+      this->Header->srow_z[0]= 0.0;  this->Header->srow_z[1]= 0.0;  this->Header->srow_z[2]= 1.0;
+    }
+}
+
+void vtkbisImageHeader::SetOrigin(double ori[3])
+{
+  this->SetOrigin(ori[0],ori[1],ori[2]);
+}
+
+// -----------------------------------------------------------------------------------
+// Handling the Origin Flag from some Analyze Format Stuff ...........................
+// -----------------------------------------------------------------------------------
+short vtkbisImageHeader::GetVOIValue()
+{
+  return (this->Header->extents);
+}
+
+void vtkbisImageHeader::SetVOIValue(short a)
+{
+  this->Header->extents=a;
+}
+
+
+char* vtkbisImageHeader::GetDBName()
+{
+  return this->Header->db_name;
+}
+
+void vtkbisImageHeader::SetDBName(const char* name)
+{
+  if (name!=NULL)
+    strncpy(this->Header->db_name,name,17);
+}
+// -----------------------------------------------------------------------------------
+int vtkbisImageHeader::FindExtension(const char* orig,const char* lookfor,const char* lookfor2)
+{
+  if (lookfor==NULL)
+    return 0;
+
+
+  int l_orig=strlen(orig);
+  int l_lookfor=strlen(lookfor);
+
+  //fprintf(stderr,"\n\n Looking for %s in %s (%s) \n",lookfor, orig,&orig[l_orig-l_lookfor]);
+
+  if (l_lookfor>l_orig)
+      return 0;
+
+  if (strcmp(&orig[l_orig-l_lookfor],lookfor)==0)
+    {
+      //fprintf(stderr,"Found %s in %s\n",lookfor,orig);
+      return 1;
+    }
+
+  if (lookfor2==NULL)
+    return 0;
+
+  int l_lookfor2=strlen(lookfor2);
+  //fprintf(stderr,"\t\t Take 2 looking for %s in %s (%s)\n",lookfor2, orig,&orig[l_orig-l_lookfor2]);
+
+  if (l_lookfor2>l_orig)
+      return 0;
+
+
+  //  fprintf(stderr,"Looking for %s in %s\n",lookfor2, &orig[l_orig-l_lookfor2]);
+
+
+  if (strcmp(&orig[l_orig-l_lookfor2],lookfor2)==0)
+    {
+      //fprintf(stderr,"Found %s in %s\n",lookfor2,orig);
+      return 1;
+    }
+
+  return 0;
+}
+
+// -----------------------------------------------------------------------------------
+char* vtkbisImageHeader::EatSuffix(const char *orig_filename)
+{
+  int   len = (int)strlen(orig_filename);
+  char* newname = new char[len+10];
+  char* filename= new char[len +10];
+  strcpy(newname,orig_filename);
+  strcpy(filename,orig_filename);
+
+  char* ext = strrchr(filename,'.');
+  char* sla = strrchr(filename,'/');
+
+  if (ext != NULL)
+    {
+      if ((sla == NULL) || (strlen(sla) >= strlen(ext)))
+	{ /* file.ext or ../file.ext */
+	  int lenext = (int)strlen(ext);
+	  strncpy(newname,filename,len-lenext);
+	  newname[len-lenext] = '\0';
+	}
+    }
+
+  delete [] filename;
+  return(newname);
+}
+// -----------------------------------------------------------------------------------
+char* vtkbisImageHeader::CreateFilename(const char* orig_filename,const char* wanted,const char *unwanted)
+{
+  char* tmp,*hdrfile;
+  char* filename=new char[strlen(orig_filename)+1 ];
+  strcpy(filename,orig_filename);
+
+  char* ext = strrchr(filename,'.');
+
+  if (ext)
+    {
+      if ( (strcmp(ext,unwanted) == 0 ) ||  ( strcmp(ext,".") == 0 ) )
+	{
+	  tmp=vtkbisImageHeader::EatSuffix(filename);
+	  hdrfile=new char[strlen(tmp)+strlen(wanted)+5];
+	  sprintf(hdrfile,"%s%s",tmp,wanted);
+	  delete [] tmp;
+	  delete [] filename;
+	  return hdrfile;
+	}
+
+      if (strcmp(ext,wanted) == 0)
+	{
+	  hdrfile=new char[strlen(filename)+5];
+	  strcpy(hdrfile,filename);
+	  delete [] filename;
+	  return hdrfile;
+	}
+
+      hdrfile=new char[strlen(filename)+strlen(wanted)+5];
+      sprintf(hdrfile,"%s%s",filename,wanted);
+      delete [] filename;
+      return hdrfile;
+    }
+  hdrfile=new char[strlen(filename)+strlen(wanted)+5];
+  sprintf(hdrfile,"%s%s",filename,wanted);
+  delete [] filename;
+  return hdrfile;
+}
+// -----------------------------------------------------------------------------------
+char* vtkbisImageHeader::CreateAnalyzeHDRFilename(const char* fname)
+{
+  char* temp=vtkbisImageHeader::CreateFilename(fname,"",".gz");
+  char* temp1=vtkbisImageHeader::CreateFilename(temp,"",".HDR");
+  char* temp2=vtkbisImageHeader::CreateFilename(temp1,".hdr",".img");
+  delete [] temp;
+  delete [] temp1;
+  return temp2;
+}
+
+char* vtkbisImageHeader::CreateAnalyzeIMGFilename(const char* fname)
+{
+  char* temp=vtkbisImageHeader::CreateFilename(fname,"",".gz");
+  char* temp2=vtkbisImageHeader::CreateFilename(temp,"",".HDR");
+  char* temp3=vtkbisImageHeader::CreateFilename(temp2,".img",".hdr");
+
+  delete [] temp;
+  delete [] temp2;
+  return temp3;
+
+}
+
+
+// -----------------------------------------------------------------------------------
+znzFile vtkbisImageHeader::SuffixOpen(const char* path, const char* mode,int complevel)
+{
+  // Default
+
+  if (mode==NULL)
+    return Z_NULL;
+
+  if (mode[0]=='r')
+      {
+	znzFile s=znzopen (path, mode,1);
+	if (!znz_isnull(s))
+	  return s;
+
+	// Take 2 check for .gz suffix if missing
+	char* newpath=new char[strlen(path)+5];
+	sprintf(newpath,"%s.gz",path);
+	s=znzopen(newpath,mode,1);
+	delete [] newpath;
+	return s;
+      }
+
+  // Write or append
+  int foundgz=0;
+
+  if (complevel<0)
+    complevel=0;
+  else if (complevel>9)
+    complevel=9;
+
+  if (complevel==0)
+    {
+      if (vtkbisImageHeader::FindExtension((char* )path,".gz")==1)
+	{
+	  complevel=6;
+	  foundgz=1;
+	}
+    }
+
+  if (complevel==0 || foundgz==1)
+    {
+      //  fprintf(stdout,"Opening %s (mode=%s) comp=%d\n",path,mode,complevel);
+      znzFile fd=znzopen(path,mode,complevel);
+      if (znz_isnull(fd))
+	fprintf(stdout,"Failed to open %s\n",path);
+      return fd;
+    }
+
+  char* newpath=vtkbisImageHeader::CreateFilename((char*)path,".gz",".gz");
+  //  fprintf(stdout,"Opening %s (mode=%s) comp=%d\n",newpath,mode,complevel);
+  znzFile s=znzopen(newpath,mode,complevel);
+  delete [] newpath;
+  if (znz_isnull(s))
+    fprintf(stdout,"Failed to open %s\n",newpath);
+  return s;
+}
+
+
+// -----------------------------------------------------------------------------------
+int vtkbisImageHeader::ReadHeader(char* fname)
+{
+  int ok=this->ReadNIFTIHeader(fname);
+
+  if (ok>0)
+    return 1;
+
+  //  fprintf(stderr,"Reading as Analyze\n");
+
+  return this->ReadAnalyzeHeader(fname);
+}
+// -------------------------------------------------------------------------------------
+int vtkbisImageHeader::WriteHeader(char* fname,int compression)
+{
+
+  if (this->Mode==0)
+    return this->WriteAnalyzeHeader(fname);
+
+
+  return this->WriteNIFTIHeader(fname,compression);
+}
+// ------------------------------------------------------------------------------------
+int vtkbisImageHeader::SetModeToNIFTI_NII()
+{
+  this->Mode=2;
+  double spa[3]; this->GetSpacing(spa);
+  //  fprintf(stdout,"Converting to NIFTI (%.2f,%.2f,%.2f)\n",spa[0],spa[1],spa[2]);
+  strncpy(this->Header->magic,"n+1\0",4);
+  int total=this->Extensions->GetTotalByteSize();
+  this->Header->vox_offset=352+total;
+  //  fprintf(stdout,"Done Converting to NIFTI (%.2f,%.2f,%.2f)\n",spa[0],spa[1],spa[2]);
+  return 1;
+}
+// ------------------------------------------------------------------------------------
+int vtkbisImageHeader::SetModeToNIFTI_HDRIMG()
+{
+  this->Mode=1;
+  this->Header->vox_offset=0;
+  strncpy(this->Header->magic,"ni1\0",4);
+  return 1;
+}
+// ------------------------------------------------------------------------------------
+int vtkbisImageHeader::WriteNIFTIHeader(char* filename,int compression)
+{
+  if (filename==NULL)
+    return 0;
+
+  znzFile fdf=vtkbisImageHeader::SuffixOpen(filename,"wb",compression);
+
+  if (znz_isnull(fdf))
+    {
+      fprintf(stdout,"Cannot write %s\n",filename);
+      return 0;
+    }
+
+  int total=this->WriteNIFTIHeader(fdf);
+  znzclose(fdf);
+  if (total>0)
+      this->SetFileName(filename);
+
+  return total;
+}
+
+// -----------------------------------------------------------------------------------
+int vtkbisImageHeader::WriteAnalyzeHeader(char* filename)
+{
+  //  fprintf(stderr,"Writing Analyze Header ... \n");
+  //  fprintf(stderr,"Valid=%d\n",this->IsHeaderValid);
+
+  if (filename==NULL)   return 0;
+  if (this->IsHeaderValid==0) return 0;
+
+
+  FILE* fp;
+  if((fp=fopen(filename,"wb"))==0)
+    {
+      fprintf(stdout,"vtkbisImageHeader::WriteAnalyzeHeader: unable to create: %s\n",filename);
+      return 0;
+    }
+  //  fprintf(stdout,"Diagnostics OK ... \n");
+
+  struct dsr hdr;
+  memset(&hdr,0,sizeof(struct dsr));
+  hdr.hk.sizeof_hdr = sizeof(struct dsr);
+  hdr.hk.extents = 16384;
+  hdr.hk.regular = 'r';
+
+  if (this->Header->dim[3]>1)
+    hdr.dime.dim[0] = 4;
+  else
+    hdr.dime.dim[0] = 3;
+  hdr.dime.dim[1] = this->Header->dim[1];
+  hdr.dime.dim[2] = this->Header->dim[2];
+  hdr.dime.dim[3] = this->Header->dim[3];
+  hdr.dime.dim[4] = this->Header->dim[4];
+
+  /*  fprintf(stdout,"Dimensions = %d x %d x %d x %d\n",
+	  hdr.dime.dim[1],
+	  hdr.dime.dim[2],
+	  hdr.dime.dim[3],
+	  hdr.dime.dim[4]);*/
+
+  strcpy(hdr.dime.vox_units,"mm");
+  strcpy(hdr.dime.cal_units," ");
+
+  hdr.dime.datatype=this->Header->datatype;
+  hdr.dime.bitpix=this->Header->bitpix;
+  hdr.dime.cal_max = this->Header->cal_max;
+  hdr.dime.cal_min = this->Header->cal_min;
+  hdr.dime.glmax  =  this->Header->glmax;
+  hdr.dime.glmin  =  this->Header->glmin;
+  hdr.dime.pixdim[1] = this->Header->pixdim[1];
+  hdr.dime.pixdim[2] = this->Header->pixdim[2];
+  hdr.dime.pixdim[3] = this->Header->pixdim[3];
+  hdr.dime.pixdim[4] = this->Header->pixdim[4];
+  hdr.dime.vox_offset = 0.0;
+  hdr.hist.orient = this->Orientation;
+
+  hdr.dime.unused1=this->GetVOIValue();
+  //  double ori[3]; this->GetOrigin(ori);
+  hdr.dime.funused1=this->GetIntensityScale();
+  hdr.dime.funused2=this->GetIntensityOffset();
+  hdr.dime.funused3=0.0;
+  strcpy(hdr.hist.exp_date,"");
+  strcpy(hdr.hist.exp_time,"");
+  strcpy(hdr.hist.patient_id,"");
+  strcpy(hdr.hist.descrip,"created by vtkbisImageHeader");
+  strncpy(hdr.hk.db_name,this->GetDBName(),17);
+  fwrite(&hdr,sizeof(struct dsr),1,fp);
+  fclose(fp);
+  this->SetFileName(filename);
+
+  return 348;
+}
+// -----------------------------------------------------------------------------------
+int vtkbisImageHeader::ReadNIFTIHeader(char* filename)
+{
+
+  znzFile fd=vtkbisImageHeader::SuffixOpen(filename,"rb");
+  int mode=0,swap=0;
+  if (!znz_isnull(fd))
+    {
+      znzread(this->Header,sizeof(nifti_1_header),1,fd);
+      znzclose(fd);
+      //this->Header = nifti_read_header(filename,&swap,true);
+      //      fprintf(stdout,"Setting NIFTI Read Filename to %s\n",filename);
+      this->SetFileName(filename);
+    }
+  else
+    {
+      char *hdrfile= vtkbisImageHeader::CreateAnalyzeHDRFilename(filename);
+      fd=vtkbisImageHeader::SuffixOpen(hdrfile,"rb");
+
+      if (!znz_isnull(fd))
+	{
+	  znzread(this->Header,sizeof(nifti_1_header),1,fd);
+	  znzclose(fd);
+	  //	  fprintf(stdout,"Setting NIFTI Read Filename to %s\n",hdrfile);
+	  //	  this->Header = nifti_read_header(hdrfile,&swap,true);
+	}
+      else
+	{
+	  char* hdrfile2=vtkbisImageHeader::CreateFilename(filename,".HDR",".hdr");
+	  fd=vtkbisImageHeader::SuffixOpen(hdrfile2,"rb");
+	  if (!znz_isnull(fd))
+	    {
+	      znzread(this->Header,sizeof(nifti_1_header),1,fd);
+	      znzclose(fd);
+	      //	      this->Header = nifti_read_header(hdrfile2,&swap,true);
+	      //	      fprintf(stdout,"Setting NIFTI Read Filename to %s\n",hdrfile2);
+	      this->SetFileName(hdrfile2);
+	    }
+	  delete [] hdrfile2;
+	}
+      delete [] hdrfile;
+    }
+
+  // Now some testing and optionally byte swapping
+  this->SwapBytes=0;
+  if (strcmp(this->Header->magic,"n+1\0")!=0 &&
+      strcmp(this->Header->magic,"ni1\0")!=0)
+    {
+      //      fprintf(stdout,"Bad Magic String in Header \n");
+      this->ResetFields();
+      return 0;
+    }
+  //  fprintf(stdout,"Read NIFTI Header from %s (magic=%s)\n",this->FileName,this->Header->magic);
+  //  fprintf(stdout,"Size of Header = %d, %d (%d)\n",sizeof(nifti_1_header),sizeof(int),this->Header->sizeof_hdr);
+
+  // Now do swap if needed
+  if (this->Header->sizeof_hdr>65536)
+    {
+      this->SwapBytes=1;
+      swap_nifti_header(this->Header,1);
+    }
+
+  //  fprintf(stdout,"Size of Header = %d, %d (%d)\n",sizeof(nifti_1_header),sizeof(int),this->Header->sizeof_hdr);
+
+  if (strncmp(this->Header->magic,"n+1",3)==0)
+    {
+      this->Mode=2;
+    }
+  else if (strncmp(this->Header->magic,"ni1",3)==0)
+    {
+      this->Mode=1;
+    }
+  else
+    {
+      //      fprintf(stdout,"Bad Magic Code %s\n",this->Header->magic);
+      return 0;
+    }
+
+  if (this->Header->scl_slope==0.0)
+    this->Header->scl_slope=1.0;
+
+
+  //  fprintf(stdout,"Theoretical Spacing %f,%f,%f\n",this->Header->pixdim[1],this->Header->pixdim[2],this->Header->pixdim[3]);
+
+  // If quaternion is bad create it while we are it, it is good to have set
+  // especially the pixdim stuff
+  if (this->Header->qform_code == 0 && this->Header->sform_code==0)
+    {
+      this->Header->srow_x[0]=-fabs(this->Header->pixdim[1]);
+      this->Header->srow_y[1]=-fabs(this->Header->pixdim[2]);
+      this->Header->srow_z[2]= fabs(this->Header->pixdim[3]);
+    }
+
+  // Next up
+  // Compute the Orientation
+  this->Orientation=this->GetOrientationFromNIFTIHeader();
+
+  // Now read extensions
+  // First Compute how many bytes of room are there
+  this->HeaderOffset=(int)this->Header->vox_offset;
+  int numbytesleft=this->HeaderOffset-348;
+  if (this->Mode==1)
+    {
+      this->HeaderOffset=0;
+      // go to the end
+      //      fprintf(stdout,"Reading %s\n",this->FileName);
+      znzFile ffd=vtkbisImageHeader::SuffixOpen(this->FileName,"rb");
+      int n=1,count=0;
+      char line[100];
+      while (n>0)
+	{
+	  n=znzread(line,1,100,ffd);
+	  count+=n;
+	}
+      numbytesleft=count-348;
+      znzclose(ffd);
+    }
+
+  int numberofdimensions=this->Header->dim[0];
+
+  if (this->Header->dim[0]>4)
+    {
+      int fourthdimension=1;
+      for (int ia=4;ia<8;ia++)
+	{
+	  if (this->Header->dim[ia]>0)
+	    fourthdimension=fourthdimension*this->Header->dim[ia];
+	}
+      this->Header->dim[4]=fourthdimension;
+      for (int ia=5;ia<8;ia++)
+	this->Header->dim[ia]=1;
+
+      this->Header->dim[0]=4;
+    }
+
+
+
+
+
+  //  fprintf(stdout,"Reading %s bytesleft=%d\n",this->FileName,numbytesleft);
+  //  fprintf(stdout,"Read NIFTI Header from %s (magic=%s) left=%d\n",this->FileName,this->Header->magic,numbytesleft);
+
+  /// Now read the Extensions
+  znzFile ffd=vtkbisImageHeader::SuffixOpen(this->FileName,"rb");
+  znzseek (ffd, 348, 0);
+  this->Extensions->ReadExtensions(ffd,numbytesleft);
+
+
+  if (this->Header->dim[0]!=numberofdimensions)
+    {
+      char line[200];
+      sprintf(line,"BIS::vtkbisImageHeader::Changed Image Dimension from %d to %d",numberofdimensions,this->Header->dim[0]);
+      this->AddComment(line,0);
+    }
+
+  znzclose(ffd);
+
+  // Set Headet to Valid
+  this->IsHeaderValid=1;
+  //  fprintf(stdout," Extensions Number of Bytes = %d, next=%d\n", this->Extensions->GetTotalByteSize(),this->Extensions->GetNumberOfExtensions());
+
+
+  //  fprintf(stdout,"Setting NIFTI Header Filename to %s\n",filename);
+  //  this->PrintHeader();
+
+  return 1;
+}
+
+// --------------------------------------------------------------------------------
+template<class T>
+void vtkbisImageHeaderSwap(T* dt,int arraysize=1)
+{
+  int sz=sizeof(T);
+  if (sz<2)
+    return;
+
+  char* chardata=(char*)dt;
+  char one_byte=0;
+  int   totalnumbytes=arraysize*sz;
+  for (int i=0;i<totalnumbytes;i+=sz)
+    {
+      char* data=&chardata[i];
+      switch(sz)
+	{
+	case 2:
+	  one_byte = data[0]; data[0] = data[1]; data[1] = one_byte;
+	  break;
+	case 4:
+	  one_byte = data[0]; data[0] = data[3]; data[3] = one_byte;
+	  one_byte = data[1]; data[1] = data[2]; data[2] = one_byte;
+	  break;
+	case 8:
+	  one_byte = data[0]; data[0] = data[7]; data[7] = one_byte;
+	  one_byte = data[1]; data[1] = data[6]; data[6] = one_byte;
+	  one_byte = data[2]; data[2] = data[5]; data[5] = one_byte;
+	  one_byte = data[3]; data[3] = data[4]; data[4] = one_byte;
+	  break;
+	}
+    }
+}
+
+// -----------------------------------------------------------------------
+int vtkbisImageHeader::CreateVarianHeader(vtkXMLDataElement* element)
+{
+  if (element==NULL)
+    return 0;
+  
+  this->ResetFields();
+  
+  // Step 1 .. byte size
+  std::string dtp = element->GetAttribute("storage");
+  if (dtp=="float")
+      this->Header->datatype = DT_FLOAT;
+  else
+    this->Header->datatype = DT_INT16; 
+
+
+
+  this->Header->dim[0]=3;
+  this->Header->dim[1]=atoi(element->GetAttribute("bis_Dimension0"));
+  this->Header->dim[2]=atoi(element->GetAttribute("bis_Dimension1"));
+  this->Header->dim[3]=atoi(element->GetAttribute("bis_Dimension2"));
+
+  /*  this->Header->srow_x[0]=-atof(element->GetAttribute("bis_Orient0"));
+  this->Header->srow_y[0]=-atof(element->GetAttribute("bis_Orient1"));
+  this->Header->srow_z[0]=atof(element->GetAttribute("bis_Orient2"));
+  this->Header->srow_x[1]=-atof(element->GetAttribute("bis_Orient3"));
+  this->Header->srow_y[1]=-atof(element->GetAttribute("bis_Orient4"));
+  this->Header->srow_z[1]=atof(element->GetAttribute("bis_Orient5"));
+  this->Header->srow_x[2]=-atof(element->GetAttribute("bis_Orient6"));
+  this->Header->srow_y[2]=-atof(element->GetAttribute("bis_Orient7"));
+  this->Header->srow_z[2]=atof(element->GetAttribute("bis_Orient8"));*/
+
+  this->Header->srow_x[0]=-atof(element->GetAttribute("bis_Orient0"));
+  this->Header->srow_x[1]=-atof(element->GetAttribute("bis_Orient3"));
+  this->Header->srow_x[2]=-atof(element->GetAttribute("bis_Orient6"));
+
+  this->Header->srow_y[0]=-atof(element->GetAttribute("bis_Orient1"));
+  this->Header->srow_y[1]=-atof(element->GetAttribute("bis_Orient4"));
+  this->Header->srow_y[2]=-atof(element->GetAttribute("bis_Orient7"));
+
+  this->Header->srow_z[0]=atof(element->GetAttribute("bis_Orient2"));
+  this->Header->srow_z[1]=atof(element->GetAttribute("bis_Orient5"));
+  this->Header->srow_z[2]=atof(element->GetAttribute("bis_Orient8"));
+
+
+
+  this->Header->srow_x[3] = this->Header->srow_y[3] = this->Header->srow_z[3] = 0.0;
+
+  this->IsHeaderValid=1;
+  this->Mode=2;
+
+
+  double sp[3];
+  sp[0]=atof(element->GetAttribute("bis_Spacing0"));
+  sp[1]=atof(element->GetAttribute("bis_Spacing1"));
+  sp[2]=atof(element->GetAttribute("bis_Spacing2"));
+
+  // Convert spans and srows into something meaningful
+  this->Header->srow_x[0]*=sp[0];
+  this->Header->srow_x[1]*=sp[1];
+  this->Header->srow_x[2]*=sp[2];
+
+  this->Header->srow_y[0]*=sp[0];
+  this->Header->srow_y[1]*=sp[1];
+  this->Header->srow_y[2]*=sp[2];
+
+  this->Header->srow_z[0]*=sp[0];
+  this->Header->srow_z[1]*=sp[1];
+  this->Header->srow_z[2]*=sp[2];
+  
+  /*  mat44 inmat,rotmat,pmat;
+  for (int ia=0;ia<=3;ia++)
+    {
+      inmat.m[0][ia]=this->Header->srow_x[ia];
+      inmat.m[1][ia]=this->Header->srow_y[ia];
+      inmat.m[2][ia]=this->Header->srow_z[ia];
+      inmat.m[3][ia]=0.0;
+    }
+    inmat.m[3][3]=1.0;*/
+
+  /*  NIFTI_print_mat44("input",inmat);
+  fprintf(stderr,"orient=%.2f ",atof(element->GetAttribute("bis_Orient0")));
+  fprintf(stderr,"%.2f ",atof(element->GetAttribute("bis_Orient3")));
+  fprintf(stderr,"%.2f ",atof(element->GetAttribute("bis_Orient6")));
+
+  fprintf(stderr,"%.2f ",atof(element->GetAttribute("bis_Orient1")));
+  fprintf(stderr,"%.2f ",atof(element->GetAttribute("bis_Orient4")));
+  fprintf(stderr,"%.2f ",atof(element->GetAttribute("bis_Orient7")));
+
+  fprintf(stderr,"%.2f ",atof(element->GetAttribute("bis_Orient2")));
+  fprintf(stderr,"%.2f ",atof(element->GetAttribute("bis_Orient5")));
+  fprintf(stderr,"%.2f\n",atof(element->GetAttribute("bis_Orient8")));*/
+
+
+  /*  vtkbisImageHeader::NIFTI_identity_mat44(&rotmat);
+  rotmat.m[0][0]= 0.0; rotmat.m[0][2]= -1.0;
+  rotmat.m[1][1]= -1.0; 
+  rotmat.m[2][0]= 1.0; rotmat.m[2][2]= 0.0;
+  NIFTI_print_mat44("rot",rotmat);
+
+  mat44 outmat=NIFTI_mat44_mmul(rotmat,inmat);
+  NIFTI_print_mat44("out",outmat);
+  
+  for (int ia=0;ia<=3;ia++)
+    {
+      this->Header->srow_x[ia]=outmat.m[0][ia];
+      this->Header->srow_y[ia]=outmat.m[1][ia];
+      this->Header->srow_z[ia]=outmat.m[2][ia];
+      }*/
+
+
+  this->Header->qform_code=0 ;   /*!< NIFTI_XFORM_* code.   */  /*-- all ANALYZE 7.5 ---*/
+  this->Header->sform_code=1 ;   /*!< NIFTI_XFORM_* code.   */  /*   fields below here  */
+  
+  this->Header->intent_name[0]=(char)0;
+  strcpy(this->Header->magic,"ni1\0");
+  this->MakeStoredHeaderValid();
+
+  //  fprintf(stderr,"Orientation Code =%s\n",this->GetOrientationCode());
+
+
+  return 1;
+}
+// -----------------------------------------------------------------------
+int vtkbisImageHeader::ReadAnalyzeHeader(char* filename)
+{
+  char *hdrfile=vtkbisImageHeader::CreateAnalyzeHDRFilename(filename);
+  znzFile fd=vtkbisImageHeader::SuffixOpen(hdrfile,"rb");
+  if (znz_isnull(fd))
+    {
+      fprintf(stdout,"Failed to open\n",hdrfile);
+      char* hdrfile2=vtkbisImageHeader::CreateFilename(hdrfile,".HDR",".hdr");
+      fd=vtkbisImageHeader::SuffixOpen(hdrfile2,"rb");
+      if (!znz_isnull(fd))
+	this->SetFileName(hdrfile2);
+      delete [] hdrfile2;
+    }
+  else
+    {
+      this->SetFileName(hdrfile);
+    }
+
+  struct dsr hdr;
+  short psize=0;
+  if (znz_isnull(fd))
+    {
+      delete [] hdrfile;
+      this->SetFileName("none.hdr");
+      return 0;
+    }
+
+  znzread(&hdr,sizeof(struct dsr),1,fd);
+
+  std::string s(this->FileName);
+  this->ResetFields();
+  this->SetFileName(s.c_str());
+
+  this->Header->dim[1]  = hdr.dime.dim[1];
+  this->Header->dim[2]  = hdr.dime.dim[2];
+  this->Header->dim[3]  = hdr.dime.dim[3];
+  this->Header->dim[4]  = hdr.dime.dim[4];
+  this->Header->dim[0]  = 3+(hdr.dime.dim[4]>1);
+  this->Header->pixdim[0] =   hdr.dime.pixdim[0];
+  this->Header->pixdim[1] =   hdr.dime.pixdim[1];
+  this->Header->pixdim[2]   = hdr.dime.pixdim[2];
+  this->Header->pixdim[3]   = hdr.dime.pixdim[3];
+  this->Header->glmin = hdr.dime.glmin;
+  this->Header->glmax = hdr.dime.glmax;
+  int orient = hdr.hist.orient;
+  this->Header->bitpix          = hdr.dime.bitpix;
+  this->Header->datatype=hdr.dime.datatype;
+
+
+  strncpy(this->Header->descrip,hdr.hist.descrip,80);
+  strncpy(this->Header->db_name,hdr.hk.db_name,18);
+
+  this->OriginBuffer[0]=0.0;
+  this->OriginBuffer[1]= 0.0;
+  this->OriginBuffer[2]= 0.0;
+
+  //  fprintf(stderr,"hdr.dime.funused1=%f, hdr.dime.funused2=%f\n",hdr.dime.funused1,hdr.dime.funused2);
+
+  if (hdr.dime.funused3==0.0)
+    {
+      this->Header->scl_slope=hdr.dime.funused1;
+      this->Header->scl_inter=hdr.dime.funused2;
+    }
+  else
+    {
+      this->Header->scl_slope=1.0;
+      this->Header->scl_inter=0.0;
+    }
+
+
+
+  short voivalue=hdr.dime.unused1;
+  this->SwapBytes=0;
+
+
+
+  // This can be a common bug sometimes ... short marked as float but 16-bit!
+  if (this->Header->bitpix==16 && this->Header->datatype!=DT_UINT16)
+    this->Header->datatype=DT_INT16;
+
+
+  if (hdr.dime.bitpix<0 || hdr.dime.bitpix>128)
+    {
+      this->SwapBytes=1;
+      vtkbisImageHeaderSwap(&this->Header->dim[0],8);
+      vtkbisImageHeaderSwap(&this->Header->glmin);
+      vtkbisImageHeaderSwap(&this->Header->glmax);
+      vtkbisImageHeaderSwap(&this->Header->pixdim[0],4);
+      vtkbisImageHeaderSwap(&this->Header->bitpix);
+      vtkbisImageHeaderSwap(&this->Header->datatype);
+      vtkbisImageHeaderSwap(&this->OriginBuffer[0],3);
+      vtkbisImageHeaderSwap(&this->Header->scl_slope,4);
+      vtkbisImageHeaderSwap(&this->Header->scl_inter,4);
+      vtkbisImageHeaderSwap(&voivalue);
+    }
+  znzclose(fd);
+
+//  fprintf(stderr,"slope=%f inter=%f swap=%d\n",this->Header->scl_slope,
+//	  this->Header->scl_inter,      this->SwapBytes);
+
+  if (fabs(this->Header->scl_slope)<1e-8)
+    {
+      this->Header->scl_slope=1.0;
+      this->Header->scl_inter=0.0;
+    }
+
+  double spa[3],ori[3]; int dim[3];
+  for (int ia=1;ia<=3;ia++)
+    {
+      dim[ia-1]=this->Header->dim[ia];
+      spa[ia-1]=fabs(this->Header->pixdim[ia]);
+      ori[ia-1]=this->OriginBuffer[ia-1];
+    }
+
+  // Check This Step in future
+  vtkMatrix4x4* mat_mapping=vtkMatrix4x4::New();
+  vtkpxUtil::ReOrientMatrix(ori,spa,dim,0,orient,mat_mapping);
+  mat44 mapping=NIFTI_Copy_Matrix4x4_mat44(mat_mapping);
+  mat_mapping->Delete();
+
+  mat44 scale; vtkbisImageHeader::NIFTI_identity_mat44(&scale);
+  for (int ia=0;ia<=2;ia++)
+    {
+      scale.m[ia][ia]=spa[ia];
+      scale.m[ia][3]=0.0;//this->OriginBuffer[ia];
+    }
+
+  //  vtkbisImageHeader::NIFTI_print_mat44("scale",scale);
+
+  mat44 newmat=vtkbisImageHeader::NIFTI_mat44_mmul(mapping,scale);
+  //  vtkbisImageHeader::NIFTI_print_mat44("newmat",newmat);
+
+  this->ApplyMapping(newmat);
+  this->Orientation=orient;
+  //  this->SetOrientation(orient);
+  this->Header->qform_code=0;
+  this->Header->sform_code=1;
+
+  this->Header->srow_x[3]=this->OriginBuffer[0];
+  this->Header->srow_y[3]=this->OriginBuffer[1];
+  this->Header->srow_z[3]=this->OriginBuffer[2];
+
+  //  this->SetOrigin(this->OriginBuffer);
+  this->SetVOIValue(voivalue);
+  this->SetDBName(hdr.hk.db_name);
+
+  strcpy(this->Header->magic,"ANA\0");
+
+  this->IsHeaderValid=1;
+  this->Mode=0;
+
+
+  //  this->PrintHeader();
+  return 1;
+}
+// --------------------------------------------------------------------------------------------
+void vtkbisImageHeader::SetOrientation(int orient)
+{
+  this->SetOrientationComplex(orient,0);
+}
+
+void vtkbisImageHeader::SetOrientationComplex(int orient,int nomatrixops)
+{
+  if (orient<0) orient=0;
+
+  int oldorient=this->Orientation;
+  this->Orientation=orient;
+
+  if (nomatrixops==1)
+    return;
+
+  if (this->Orientation==3)
+    {
+      this->Header->sform_code=0;
+      this->Header->qform_code=0;
+      return;
+    }
+
+  double ori[3]={0.0,0.0,0.0};
+  int dim[3];
+  dim[0]=this->Header->dim[1];
+  dim[1]=this->Header->dim[2];
+  dim[2]=this->Header->dim[3];
+
+  double spa[3];
+  spa[0]=this->Header->pixdim[1];
+  spa[1]=this->Header->pixdim[2];
+  spa[2]=this->Header->pixdim[3];
+
+  // Check This Step in future
+  vtkMatrix4x4* mat_mapping=vtkMatrix4x4::New();
+  vtkpxUtil::ReOrientMatrix(ori,spa,dim,oldorient,this->Orientation,mat_mapping);
+
+
+  mat44 mapping=NIFTI_Copy_Matrix4x4_mat44(mat_mapping);
+  //  vtkbisImageHeader::NIFTI_print_mat44("reorient mapping",mapping);
+  mat_mapping->Delete();
+  this->ApplyMapping(mapping);
+  if (this->Mode>0)
+    {
+      char line[200];
+      sprintf(line,"BIS::vtkbisImageHeader::SetOrientationComplex Changing Orientation from %d to %d",oldorient,orient);
+      this->AddComment(line,0);
+    }
+
+
+}
+// --------------------------------------------------------------------------------------------
+void vtkbisImageHeader::SetOrientationAsMatrix(mat44 newmat)
+{
+  nifti_1_header* hdr=this->GetRawHeader();
+  int orientation=0;
+  hdr->qform_code=0;
+  hdr->sform_code=1;
+  for (int ia=0;ia<=3;ia++)
+    {
+      hdr->srow_x[ia]=newmat.m[0][ia];
+      hdr->srow_y[ia]=newmat.m[1][ia];
+      hdr->srow_z[ia]=newmat.m[2][ia];
+    }
+
+  this->Orientation=this->GetOrientationFromNIFTIHeader();
+  return;
+
+}
+
+// --------------------------------------------------------------------------------------------
+int vtkbisImageHeader::WriteNIFTIHeader(znzFile fdf)
+{
+
+  if (this->IsHeaderValid==0)
+    return 0;
+
+  //  fprintf(stdout,"Beginning WriteNIFTI Header Diagnostics OK\n");
+  int numbytes=znzwrite(this->Header,sizeof(nifti_1_header),1,fdf);
+
+  //  fprintf(stdout,"Done with Write Header %d\n",numbytes);
+  numbytes+=this->Extensions->WriteExtensions(fdf);
+  //fprintf(stdout,"Numbytes=%d, done with extensions ...\n",numbytes);
+
+  return numbytes;
+}
+// ------------------------------------------------------------------------
+void vtkbisImageHeader::PrintAll(int show_extensions)
+{
+  std::cerr << "Common Parameters:\n";
+  std::cerr  << "Mode (0=Analyze,1 =NIFT1 .hdr/.img, 2=NIFTI .nii) = " << this->Mode << "\n";
+  std::cerr  << "FileName  = " << this->FileName << "\n";
+  std::cerr  << "IsHeaderValid = " << this->IsHeaderValid << "\n";
+  std::cerr  << "SwapBytes = " << this->SwapBytes << "\n";
+  std::cerr  << "Orientation = " << this->Orientation << "\n";
+
+  nifti_1_header *hdr=this->Header;
+  std::cerr  << "NIFTI1 Header (Header)\n --------------------------------------------\n";
+  std::cerr  << "int sizeof_hdr    : " << hdr->sizeof_hdr    << "\t MUST be 348         (ANLZ7.5)int sizeof_hdr\n";
+  std::cerr  << "char data_type[10]: " << hdr->data_type     << "\t ++UNUSED++          (ANLZ7.5)char data_type[10]\n";
+  std::cerr  << "char db_name[18]: " << hdr->db_name       << "\t ++UNUSED++          (ANLZ7.5)char db_name[18]\n";
+  if (show_extensions>1)
+    {
+      std::cerr  << "int extents     : " << hdr->extents       << "\t ++UNUSED++          (ANLZ7.5)int extents\n";
+      std::cerr  << "short session_error : " << hdr->session_error << "\t ++UNUSED++          (ANLZ7.5)short session_error\n";
+      std::cerr  << "char regular    : " << hdr->regular       << "\t ++UNUSED++          (ANLZ7.5)char regular\n";
+      std::cerr  << "char dim_info   : " << hdr->dim_info      << "\t MRI slice ordering. (ANLZ7.5)char hkey_un0\n";
+    }
+  std::cerr  << "short dim[8]    : was image_dimension substruct -- (ANLZ7.5)short dim[8];\n\t";
+  for (int ia=0;ia<8;ia++)
+    std::cerr  << "Dim ("<<ia<<")="<<hdr->dim[ia]<<",";
+  std::cerr << "\n";
+  if (show_extensions>1)
+    {
+      std::cerr  << "float intent_p1 :" << hdr->intent_p1 << "\t 1st intent parameter. (ANLZ7.5)short unused8; short unused9\n";
+      std::cerr  << "float intent_p2 :" << hdr->intent_p2 << "\t 1st intent parameter. (ANLZ7.5)short unused10; short unused11\n";
+      std::cerr  << "float intent_p3 :" << hdr->intent_p3 << "\t 1st intent parameter. (ANLZ7.5)short unused12; short unused13\n";
+      std::cerr  << "short ident_code:" << hdr->intent_code << "\tNIFTI_INTENT_* code.  (Analyze)short unused14;\n";
+    }
+  std::cerr  << "short dataype:   " << hdr->datatype << "\t Defines data type!    (Analyze)short datatype;\n";
+  std::cerr  << "short bitpix :   " << hdr->bitpix   << "\t Number bits/voxel.    (Analyze)short bitpix;\n";
+  if (show_extensions>1)
+    std::cerr  << "short slice_start:" << hdr->slice_start << "\t First slice index.    (Analyze)short dim_un0;\n";
+  std::cerr  << "short pixdim[8] \t    Grid spacings.   (ANLZ7.5)float pixdim[8];\n";
+  for (int ia=0;ia<8;ia++)
+    std::cerr  << "pixdim ("<<ia<<")="<<hdr->pixdim[ia]<<",";
+  std::cerr << "\n";
+  std::cerr  << "float vox_offset: " << hdr->vox_offset << "\t Offset into .nii file (Analyze)float vox_offset;\n";
+  std::cerr  << "float scl_slope : " << hdr->scl_slope  << "\t Data scaling: slope.  (Analyze)float funused1 \n";
+  std::cerr  << "float scl_inter : " << hdr->scl_inter  << "\t Data scaling: offset. (Analyze)float funused2;\n";
+  if (show_extensions>1)
+    {
+      std::cerr  << "float slice_end : " << hdr->slice_end  << "\t Last slice index.     (Analyze)float funused3\n";
+      std::cerr  << "char slice_code : " << hdr->slice_code << "\t Slice timing order.   (Analyze) ...\n";
+      std::cerr  << "char xyzt_units : " << hdr->xyzt_units << "\t Units of pixdim[1..4]";
+      std::cerr  << "float cal_max   : " << hdr->cal_max    << "\t Max display intensity (Analyze)float cal_max;\n";
+      std::cerr  << "float cal_min   : " << hdr->cal_min    << "\t Min display intensity (Analyze)float cal_min;\n";
+      std::cerr  << "float slice_duration"<< hdr->slice_duration << "\t Time for 1 slice.     (Analyze)float compressed;\n";
+      std::cerr  << "float toffset   :   "<<hdr->toffset << "\t Time axis shift.      (Analyze)float verified;\n";
+      std::cerr  << "int glmax       :   "<<hdr->glmax << "\t ++UNUSED++       (ANLZ7.5)int glmax;\n";
+      std::cerr  << "int glmin       :   "<<hdr->glmin << "\t ++UNUSED++       (ANLZ7.5)int glmin;\n";
+      std::cerr  << "char descrip[80]:   "<<hdr->descrip << "\t  any text you like.    (Analyze)char descrip[80];\n";
+      std::cerr  << "char aux_file[24]:  "<<hdr->aux_file<< "\t auxiliary filename.   (Analyze)char aux_file[24];\n";
+    }
+  std::cerr  << "short qform_code :  "<<hdr->qform_code << "\t NIFTI_XFORM_* code.  -- all ANALYZE 7.5 ---\n";
+  std::cerr  << "short sform_code :  "<<hdr->sform_code << "\t NIFTI_XFORM_* code.    fields below here are replaced \n";
+  std::cerr  << "float quatern_b  :  " << hdr->quatern_b << "\t Quaternion b param.  \n";
+  std::cerr  << "float quatern_c  :  " << hdr->quatern_c << "\t Quaternion c param.  \n";
+  std::cerr  << "float quatern_d  :  " << hdr->quatern_d << "\t Quaternion d param.  \n";
+  std::cerr  << "float qoffset_x  :  " << hdr->qoffset_x << "\t Quaternion x shift.  \n";
+  std::cerr  << "float qoffset_y  :  " << hdr->qoffset_y << "\t Quaternion y shift.  \n";
+  std::cerr  << "float qoffset_z  :  " << hdr->qoffset_z << "\t Quaternion z shift.  \n";
+  std::cerr  << "float srow_x[4]  :  \t 1st row affine transform.   \n";
+  std::cerr  << "\t " <<  hdr->srow_x[0] << "\t" <<  hdr->srow_x[1] << "\t" <<  hdr->srow_x[2] << "\t" <<  hdr->srow_x[3] << "\n";
+  std::cerr  << "float srow_y[4]  :  \t 2nd row affine transform.   \n";
+  std::cerr  << "\t " <<  hdr->srow_y[0] << "\t" <<  hdr->srow_y[1] << "\t" <<  hdr->srow_y[2] << "\t" <<  hdr->srow_y[3] << "\n";
+  std::cerr  << "float srow_z[4]  :  \t 3rd row affine transform.   \n";
+  std::cerr  << "\t " <<  hdr->srow_z[0] << "\t" <<  hdr->srow_z[1] << "\t" <<  hdr->srow_z[2] << "\t" <<  hdr->srow_z[3] << "\n";
+  std::cerr  << "char intent_name[16] : " << hdr->intent_name << "\t 'name' or meaning of data. \n";
+  std::cerr  << "char magic[4]        : " << hdr->magic << "\t MUST be ni-1 or n+1\n\n";
+
+
+
+  if (show_extensions)
+    {
+      std::cerr  << "NIFTI1 Extensions (Extensions)\n --------------------------------------------\n";
+      this->Extensions->PrintAll();
+    }
+}
+// -----------------------------------------------------------------------------------------------------------------------------------
+mat44 vtkbisImageHeader::NIFTI_CreateOrientationMatrix( nifti_1_header *hdr)
+{
+  mat44 original;
+  if (hdr->qform_code==0)
+    {
+      for (int ia=0;ia<=3;ia++)
+	{
+	  original.m[0][ia]=hdr->srow_x[ia];
+	  original.m[1][ia]=hdr->srow_y[ia];
+	  original.m[2][ia]=hdr->srow_z[ia];
+	  original.m[3][ia]=float(ia==3);
+	}
+    }
+  else
+    {
+      original=nifti_quatern_to_mat44(hdr->quatern_b,hdr->quatern_c,hdr->quatern_d,
+				      hdr->qoffset_x,hdr->qoffset_y,hdr->qoffset_z,
+				      fabs(hdr->pixdim[1]),fabs(hdr->pixdim[2]),fabs(hdr->pixdim[3]),
+				      hdr->pixdim[0]);
+    }
+
+  return original;
+}
+
+const char* vtkbisImageHeader::NIFTI_GetOrientationString( int ii )
+{
+   switch( ii )
+     {
+     case NIFTI_L2R: return "L-to-R" ;
+     case NIFTI_R2L: return "R-to-L" ;
+     case NIFTI_P2A: return "P-to-A" ;
+     case NIFTI_A2P: return "A-to-P" ;
+     case NIFTI_I2S: return "I-to-S" ;
+     case NIFTI_S2I: return "S-to-I" ;
+     }
+   return "Unknown" ;
+}
+
+const char* vtkbisImageHeader::NIFTI_GetOrientationStringShort( int ii )
+{
+   switch( ii )
+     {
+     case NIFTI_L2R: return "R" ;
+     case NIFTI_R2L: return "L" ;
+     case NIFTI_P2A: return "A" ;
+     case NIFTI_A2P: return "P" ;
+     case NIFTI_I2S: return "S" ;
+     case NIFTI_S2I: return "I" ;
+     }
+   return "U" ;
+}
+
+
+const char* vtkbisImageHeader::GetOrientationCode()
+{
+  this->Buffer="";
+
+  nifti_1_header* hdr=this->GetRawHeader();
+  int orientation=0;
+
+  //   METHOD 1 (the "old" way, used only when qform_code = 0):
+  if (hdr->qform_code == 0 && hdr->sform_code==0)
+    {
+      this->Buffer="";
+      return this->Buffer.c_str();
+    }
+
+  if (this->GetMode()==0)
+    {
+      this->Buffer="";
+      return this->Buffer.c_str();
+    }
+
+
+
+  // Method 2 and 3 Rely on First Creating a 4x4 Matrix
+
+  mat44 original;
+  if (hdr->qform_code==0)
+    {
+      for (int ia=0;ia<=3;ia++)
+	{
+	  original.m[0][ia]=hdr->srow_x[ia];
+	  original.m[1][ia]=hdr->srow_y[ia];
+	  original.m[2][ia]=hdr->srow_z[ia];
+	  original.m[3][ia]=float(ia==3);
+	}
+    }
+  else
+    {
+      original=nifti_quatern_to_mat44(hdr->quatern_b,hdr->quatern_c,hdr->quatern_d,
+				      hdr->qoffset_x,hdr->qoffset_y,hdr->qoffset_z,
+				      fabs(hdr->pixdim[1]),fabs(hdr->pixdim[2]),fabs(hdr->pixdim[3]),
+				      hdr->pixdim[0]);
+    }
+
+  //  vtkbisImageHeader::NIFTI_print_mat44("original",original);
+
+  int icod,jcod,kcod;  nifti_mat44_to_orientation(original,&icod,&jcod,&kcod);
+
+  this->Buffer="(";
+  this->Buffer+=NIFTI_GetOrientationStringShort(icod);
+  this->Buffer+=NIFTI_GetOrientationStringShort(jcod);
+  this->Buffer+=NIFTI_GetOrientationStringShort(kcod);
+  this->Buffer+=")";
+
+  return this->Buffer.c_str();
+}
+
+// -----------------------------------------------------------------------------------
+// mat44 Utilities
+// -----------------------------------------------------------------------------------
+mat44 vtkbisImageHeader::NIFTI_mat44_mmul( mat44 A , mat44 B )  /* multiply 2 4x4 matrices */
+{
+   mat44 C ; int i,j ;
+   for( i=0 ; i < 4 ; i++ )
+    for( j=0 ; j < 4 ; j++ )
+      C.m[i][j] =  A.m[i][0] * B.m[0][j]
+	+ A.m[i][1] * B.m[1][j]
+	+ A.m[i][2] * B.m[2][j]
+	+ A.m[i][3] * B.m[3][j];
+   return C ;
+}
+
+void vtkbisImageHeader::NIFTI_print_mat44(char* s, mat44 A)
+{
+  fprintf(stdout,"\n\n %s = \n",s);
+  for (int ia=0;ia<=3;ia++)
+    {
+      fprintf(stdout,"\t [ ");
+      for (int ib=0;ib<=3;ib++)
+	fprintf(stdout," %+8.3f\t ", A.m[ia][ib]);
+      fprintf(stdout,"]\n");
+    }
+}
+
+void vtkbisImageHeader::NIFTI_identity_mat44(mat44* A)
+{
+  for (int ia=0;ia<=3;ia++)
+    for (int ib=0;ib<=3;ib++)
+      {
+	if (ia==ib)
+	  A->m[ia][ib]=1.0;
+	else
+	  A->m[ia][ib]=0.0;
+      }
+}
+
+
+mat44 vtkbisImageHeader::NIFTI_Copy_Matrix4x4_mat44(vtkMatrix4x4* input)
+{
+  mat44 output;
+  if (input!=NULL)
+    {
+      for (int ia=0;ia<=3;ia++)
+	for (int ib=0;ib<=3;ib++)
+	  output.m[ia][ib]=input->GetElement(ia,ib);
+    }
+  else
+    {
+      vtkbisImageHeader::NIFTI_identity_mat44(&output);
+    }
+  return output;
+
+}
+
+vtkMatrix4x4* vtkbisImageHeader::NIFTI_CopyMat44(mat44 input)
+{
+  vtkMatrix4x4* output=vtkMatrix4x4::New();
+  for (int ia=0;ia<=3;ia++)
+    for (int ib=0;ib<=3;ib++)
+      output->SetElement(ia,ib,input.m[ia][ib]);
+
+  return output;
+
+}
+
+// -----------------------------------------------------------------------------------------------------------------------------------
+void vtkbisImageHeader::PrintHeader(int long_mode)
+{
+  char* l=this->GetHeaderDescription(long_mode);
+  fprintf(stdout,"%s\n",l);
+  delete [] l;
+}
+// -----------------------------------------------------------------------------------------------------------------------------------
+char* vtkbisImageHeader::GetHeaderDescription(int long_mode)
+{
+  std::string output ="";
+  nifti_1_header *hdr=this->Header;
+  char line[20000];
+
+  if (long_mode>=0)
+    output = output +  this->FileName +" ";
+
+  if (long_mode==-1)
+    long_mode=0;
+
+  if (long_mode)
+    output += "\n\tOrientation = ";
+  switch (this->Orientation)
+    {
+    case 0: output += " Axial "; break;
+    case 1: output += " Coronal "; break;
+    case 2: output += " Sagittal "; break;
+    case 3: output += " Polar "; break;
+    }
+
+  mat44 original=vtkbisImageHeader::NIFTI_CreateOrientationMatrix(this->Header);
+  int icod,jcod,kcod;  nifti_mat44_to_orientation(original,&icod,&jcod,&kcod);
+  if (long_mode)
+    {
+      sprintf(line,"(%s,%s,%s)", nifti_orientation_string(icod),
+	      nifti_orientation_string(jcod),
+	      nifti_orientation_string(kcod));
+      output+=line;
+    }
+  else
+    {
+      sprintf(line,"(%s,%s,%s)", vtkbisImageHeader::NIFTI_GetOrientationString(icod),
+	      vtkbisImageHeader::NIFTI_GetOrientationString(jcod),
+	      vtkbisImageHeader::NIFTI_GetOrientationString(kcod));
+      output+=line;
+
+    }
+
+
+  if (long_mode)
+    {
+      output+="\n\tMode = ";
+      switch (this->Mode)
+	{
+	case 0: output+=" Analyze 7.5"; break;
+	case 1: output+=" NIFTI (.hdr/.img)"; break;
+	case 2: output+=" NIFTI (.nii)"; break;
+	}
+      sprintf(line,"(magic=%s) (Valid = %d SwapBytes=%d)\n",hdr->magic,this->IsHeaderValid,this->SwapBytes);
+      output+=line;
+      output+="\t Dimensions =";
+    }
+
+  sprintf(line," %dx%dx%d, %d ",hdr->dim[1],hdr->dim[2],hdr->dim[3],hdr->dim[4]);
+  output+=line;
+  if (long_mode)
+    {
+      sprintf(line,"\n\tVoxel Dimensions = %.3fx%.3fx%.3f, %.2f \n",hdr->pixdim[1],hdr->pixdim[2],hdr->pixdim[3],hdr->pixdim[4]);
+      output+=line;
+      sprintf(line,"\tData Type = %s(%d) (Bits per Pixel=%d) Vox_Offset=%d Num Extensions=%d (Size =%d)\n",nifti_datatype_string(hdr->datatype),hdr->datatype,hdr->bitpix,
+	      (int)hdr->vox_offset,this->Extensions->GetNumberOfExtensions(),this->Extensions->GetTotalByteSize());
+      output+=line;
+
+      sprintf(line,"\tScale= %.3f Shift=%.3f \n",hdr->scl_slope,hdr->scl_inter);
+      output+=line;
+      sprintf(line,"\tOrientation Matrix Stuff (qform_code=%d sform_code=%d)\n",hdr->qform_code,hdr->sform_code);
+      output+=line;
+      if (hdr->qform_code>0)
+	{
+	  sprintf(line,"\tQuatenion (qfac=%f) quat=(%.3f,%.3f,%.3f) offset=(%.3f,%.3f,%.3f)\n",
+		  hdr->pixdim[0],
+		  hdr->quatern_b,hdr->quatern_c,hdr->quatern_d,
+		  hdr->qoffset_x,hdr->qoffset_y,hdr->qoffset_z);
+	  output+=line;
+	}
+
+      if (hdr->sform_code>0)
+	{
+	  sprintf(line,"\tMatrix_x = \t( %+8.3f %+8.3f %+8.3f %+8.3f )\n",
+		  hdr->srow_x[0],hdr->srow_x[1],hdr->srow_x[2],hdr->srow_x[3]);
+	  output+=line;
+	  sprintf(line,"\t       y = \t( %+8.3f %+8.3f %+8.3f %+8.3f )\n",
+		  hdr->srow_y[0],hdr->srow_y[1],hdr->srow_y[2],hdr->srow_y[3]);
+	  output+=line;
+	  sprintf(line,"\t       z = \t( %+8.3f %+8.3f %+8.3f %+8.3f)\n",
+		  hdr->srow_z[0],hdr->srow_z[1],hdr->srow_z[2],hdr->srow_z[3]);
+	  output+=line;
+	}
+
+      if (this->Mode==0)
+	{
+	  double ori[3]; this->GetOrigin(ori);
+	  sprintf(line,"\t (Analyze Origin) = (%.1f,%1.f,%.1f)\n",ori[0],ori[1],ori[2]);
+	  output+=line;
+	}
+    }
+  else
+    {
+      sprintf(line," (%.3fx%.3fx%.3f, %.2f)\n",hdr->pixdim[1],hdr->pixdim[2],hdr->pixdim[3],hdr->pixdim[4]);
+      output+=line;
+      sprintf(line,"\tData Type = %s (Bits=%d) NumExt=%d (Sz =%d)",nifti_datatype_string(hdr->datatype),hdr->bitpix,
+	      this->Extensions->GetNumberOfExtensions(),this->Extensions->GetTotalByteSize());
+      output+=line;
+    }
+
+
+  /*  if (long_mode>0)
+    {
+    sprintf(line,"\t DBName : %s , VOIValue= %d\n",this->GetDBName(),this->GetVOIValue());
+    output+=line;
+      
+    }*/
+
+  if (long_mode>1)
+    {
+      int next=this->Extensions->GetNumberOfExtensions();
+      sprintf(line,"\n\t Extensions = %d , size=%d\n",
+	      next,this->Extensions->GetTotalByteSize());
+      output+=line;
+      for (int i=0;i<next;i++)
+	{
+	  vtkbisNIFTIExtension* extn=this->Extensions->GetRawExtension(i);
+	  sprintf(line,"*********** Extensions %d (code=%d size=%d)\n",
+		  i+1,extn->GetECode(),extn->GetESize());
+	  output+=line;
+	  output+=extn->GetText();
+	  output+="\n";
+	}
+    }
+
+  char* ll=new char[output.length()+1];
+  strcpy(ll,output.c_str());
+  return ll;
+}
+// -----------------------------------------------------------------------------------------------------------------------------------
+int vtkbisImageHeader::ReconcileImage(vtkImageData* img,int useorigin)
+{
+  if (img==NULL || this->IsHeaderValid==0)
+    return 0;
+
+  double spa[3];
+  this->GetSpacing(spa);  img->SetSpacing(spa);
+
+  if (useorigin)
+    {
+      double ori[3]; this->GetOrigin(ori); img->SetOrigin(ori);
+    }
+  return 1;
+}
+
+int vtkbisImageHeader::ReconcileHeader(vtkImageData* img,int useorigin)
+{
+  if (img==NULL)
+    return 0;
+
+  if (this->IsHeaderValid==0)
+    {
+      return this->CreateHeader(img,useorigin);
+    }
+
+  //  fprintf(stderr,"\n ---------------------------------\n OK Reconciling Header .................. \n");
+
+  // These are a lock ...
+  char line[200];
+  int dim[3]; img->GetDimensions(dim);
+  int olddim[3];
+  double spa[3]; img->GetSpacing(spa);
+
+  for (int ia=0;ia<=2;ia++)
+    spa[ia]=fabs(spa[ia]);
+
+  int dim_change=0;
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      olddim[ia]=this->Header->dim[ia+1];
+      if (this->Header->dim[ia+1]!=dim[ia])
+	{
+	  ++dim_change;
+	  this->Header->dim[ia+1]=dim[ia];
+	}
+    }
+
+
+  if (dim_change>0)
+    {
+      //      sprintf(line,"DebugMessage (Ignore) BIS:vtkbisImageHeader:Recon Header:Changed Dimensions  (%d,%d,%d) -> (%d,%d,%d)",
+      //	      olddim[0],olddim[1],olddim[2],dim[0],dim[1],dim[2]);
+      //      this->AddComment(line,0);
+    }
+
+
+  int numc_change=0;
+  if (this->Header->dim[4]!=img->GetNumberOfScalarComponents())
+    {
+      int tmp=this->Header->dim[4];
+      this->Header->dim[4]=img->GetNumberOfScalarComponents();
+
+      //      sprintf(line,"DebugMessage (Ignore) BIS:vtkbisImageHeader:Recon Header:Changed Frames %d to %d",tmp,this->Header->dim[4]);
+      //      this->AddComment(line,0);
+
+      numc_change=1;
+    }
+
+  int maxd=1;
+  for (int ia=1;ia<8;ia++)
+    {
+      if (this->Header->dim[ia]>1)
+	maxd=ia;
+    }
+  this->Header->dim[0]=maxd;
+
+  int datatype_change=0;
+  int dt=vtkbisImageHeader::GetNIFTIDataType(img->GetScalarType());
+  if (this->Header->datatype!=dt)
+    {
+      //  sprintf(line,"DebugMessage (Ignore) BIS:vtkbisImageHeader:Recon Header:Changed Datatype : %d --> %d",
+      //      this->Header->datatype,dt);
+      //      this->AddComment(line,0);
+      this->Header->datatype=dt;
+      this->Header->bitpix=vtkbisImageHeader::GetBitPix(img->GetScalarType());
+      datatype_change=1;
+    }
+
+
+  double oldspa[3]; this->GetSpacing(oldspa);
+  /*  oldspa[0]=this->Header->pixdim[1];
+  oldspa[1]=this->Header->pixdim[2];
+  oldspa[2]=this->Header->pixdim[3];*/
+
+  //    fprintf(stderr,"\n\n\n On to spacing img = (%.2f,%.2f,%.2f) header=(%.2f,%.2f,%.2f) qf=%d, sf=%d\n",
+  //    spa[0],spa[1],spa[2],oldspa[0],oldspa[1],oldspa[2],
+  //    this->Header->qform_code,this->Header->sform_code);
+
+
+  int spacing_change=0;
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (fabs(spa[ia]-oldspa[ia])>0.00001)
+	    ++spacing_change;
+    }
+
+  if (spacing_change!=0)
+    {
+      /*      this->Header->pixdim[1]=spa[0];
+	      this->Header->pixdim[2]=spa[1];
+	      this->Header->pixdim[3]=spa[2];*/
+
+      mat44 mapping; vtkbisImageHeader::NIFTI_identity_mat44(&mapping);
+      for (int ia=0;ia<=2;ia++)
+	mapping.m[ia][ia]=spa[ia]/oldspa[ia];
+
+      /*      for (int ia=0;ia<=3;ia++)
+	{
+	  fprintf(stderr,"mapping = [ ");
+	  for (int ib=0;ib<=3;ib++)
+	    fprintf(stderr,"%.4f ",mapping.m[ia][ib]);
+	  fprintf(stderr,"]\n");
+	  }*/
+
+
+      this->ApplyMapping(mapping);
+      //      this->PrintHeader();
+
+
+      if (useorigin)
+	{
+	  double ori[3]; this->GetOrigin(ori);
+	  double orn[3]; img->GetOrigin(orn);
+	  vtkbisImageHeader::NIFTI_identity_mat44(&mapping);
+	  for (int ia=0;ia<=2;ia++)
+	    mapping.m[ia][3]=orn[ia]-ori[ia];
+	  this->ApplyMapping(mapping);
+	}
+      //      sprintf(line,"DebugMessage (Ignore) BIS:vtkbisImageHeader:Recon Header:Changed Voxel spacing  (%.3f,%.3f,%.3f) -> (%.3f,%.3f,%.3f)",
+      //      oldspa[0],oldspa[1],oldspa[2],spa[0],spa[1],spa[2]);
+      //      this->AddComment(line,0);
+      //fprintf(stderr,"%s\n",line);
+      //      this->PrintHeader();
+    }
+
+  this->IsHeaderValid=1;
+
+  //  fprintf(stderr,"Done Reconciling Header .................. \n");
+  return 1;
+}
+
+// -----------------------------------------------------------------------------------
+int vtkbisImageHeader::ApplyMapping(mat44 mapping,int premultiply)
+{
+  //  First  quaternion stuff
+  int mod_flag=0;
+
+  if (this->Header->sform_code>0)
+    {
+      mat44 original;
+      for (int ia=0;ia<=3;ia++)
+	{
+	  original.m[0][ia]=this->Header->srow_x[ia];
+	  original.m[1][ia]=this->Header->srow_y[ia];
+	  original.m[2][ia]=this->Header->srow_z[ia];
+	  original.m[3][ia]=float(ia==3);
+	}
+      mat44 newmat;
+      if (premultiply>0)
+	newmat=vtkbisImageHeader::NIFTI_mat44_mmul(mapping,original);
+      else
+	newmat=vtkbisImageHeader::NIFTI_mat44_mmul(original,mapping);
+
+      for (int ia=0;ia<=3;ia++)
+	{
+	  this->Header->srow_x[ia]=newmat.m[0][ia];
+	  this->Header->srow_y[ia]=newmat.m[1][ia];
+	  this->Header->srow_z[ia]=newmat.m[2][ia];
+	}
+      mod_flag+=2;
+
+      nifti_mat44_to_quatern(newmat,
+			     &this->Header->quatern_b,&this->Header->quatern_c,&this->Header->quatern_d,
+			     &this->Header->qoffset_x,&this->Header->qoffset_y,&this->Header->qoffset_z,
+			     &this->Header->pixdim[1],&this->Header->pixdim[2],&this->Header->pixdim[3],
+			     &this->Header->pixdim[0]);
+    }
+  else if (this->Header->qform_code>0)
+    {
+      mat44 original;
+      original=nifti_quatern_to_mat44(this->Header->quatern_b,this->Header->quatern_c,this->Header->quatern_d,
+				      this->Header->qoffset_x,this->Header->qoffset_y,this->Header->qoffset_z,
+				      fabs(this->Header->pixdim[1]),fabs(this->Header->pixdim[2]),fabs(this->Header->pixdim[3]),
+				      this->Header->pixdim[0]);
+
+      //      NIFTI_print_mat44("original=",original);
+      //      fprintf(stderr,"Pixdim=%f,%f,%f",this->Header->pixdim[1],this->Header->pixdim[2],this->Header->pixdim[3]);
+
+      mat44 newmat;
+      if (premultiply>0)
+	newmat=vtkbisImageHeader::NIFTI_mat44_mmul(mapping,original);
+      else
+	newmat=vtkbisImageHeader::NIFTI_mat44_mmul(original,mapping);
+
+      for (int ia=0;ia<=3;ia++)
+	{
+	  this->Header->srow_x[ia]=newmat.m[0][ia];
+	  this->Header->srow_y[ia]=newmat.m[1][ia];
+	  this->Header->srow_z[ia]=newmat.m[2][ia];
+	}
+
+      nifti_mat44_to_quatern(newmat,
+			     &this->Header->quatern_b,&this->Header->quatern_c,&this->Header->quatern_d,
+			     &this->Header->qoffset_x,&this->Header->qoffset_y,&this->Header->qoffset_z,
+			     &this->Header->pixdim[1],&this->Header->pixdim[2],&this->Header->pixdim[3],
+			     &this->Header->pixdim[0]);
+      mod_flag+=1;
+    }
+
+  return mod_flag;
+}
+
+int vtkbisImageHeader::ModifyOrientation(mat44 mapping,int DataFlip[3],int do_transpose)
+{
+  int mod_flag=this->ApplyMapping(mapping,0);
+  this->Orientation=this->GetOrientationFromNIFTIHeader();
+
+  if (DataFlip[0]>0 || DataFlip[1] >0 || DataFlip[2]>0 ||
+      do_transpose>0)
+    {
+      char line[300];
+      sprintf(line,"BIS::vtkbisImageHeader :: Fixed Header to BioImage Suite Standard (still valid!) flips = %d,%d,%d transpose=%d orientation=%d (mod_qform=%d),(mod_sform=%d)",
+	      DataFlip[0],
+	      DataFlip[1],
+	      DataFlip[2],
+	      do_transpose,
+	      this->Orientation,
+	      ( (mod_flag==1) || (mod_flag==3)),
+	      (mod_flag>1));
+      this->AddComment(line,0);
+      //      fprintf(stdout,"Comment=%s\n",line);
+      return 1;
+    }
+  return 0;
+}
+
+int vtkbisImageHeader::ApplyShift(double x,double y,double z)
+{
+
+  if (fabs(x)<0.001 && fabs(y)<0.001 && fabs(z)<0.001)
+    return 0;
+
+
+  mat44 shift_matrix;       vtkbisImageHeader::NIFTI_identity_mat44(&shift_matrix);
+  shift_matrix.m[0][3]=x;
+  shift_matrix.m[1][3]=y;
+  shift_matrix.m[1][3]=z;
+
+  this->ApplyMapping(shift_matrix);
+  //  char line[200];
+  //  sprintf(line,"DebugMessage (Ignore) BIS:vtkbisImageHeader:Apply Shift (perhaps image cropping) %.2f %.2f %.2f",x,y,z);
+  //  this->AddComment(line,0);
+  return 1;
+}
+
+// ----------------------------------------------------------------------------------------------
+//
+// ----------------------------------------------------------------------------------------------
+int vtkbisImageHeader::CopyExtensionsOnly(vtkbisImageHeader* other)
+{
+  if (other==NULL)
+    return 0;
+
+  if (other->GetExtensions()==NULL)
+    return 0;
+
+  this->Extensions->Copy(other->GetExtensions());
+  return 1;
+
+}
+// ----------------------------------------------------------------------------------------------
+int vtkbisImageHeader::CopyLocationInformationOnly(vtkbisImageHeader* other)
+{
+  if (other==NULL)
+    return 0;
+
+  nifti_1_header* hdr=this->GetRawHeader();
+  nifti_1_header* otr=other->GetRawHeader();
+
+  hdr->qform_code=otr->qform_code;
+  hdr->sform_code=otr->sform_code;
+  /*   are replaced       */
+  hdr->quatern_b=  otr->quatern_b;
+  hdr->quatern_c=  otr->quatern_c;
+  hdr->quatern_d=  otr->quatern_d;
+  hdr->qoffset_x=  otr->qoffset_x;
+  hdr->qoffset_y=  otr->qoffset_y;
+  hdr->qoffset_z=  otr->qoffset_z;
+
+  for (int ia=0;ia<=3;ia++)
+    {
+      hdr->srow_x[ia]=otr->srow_x[ia];
+      hdr->srow_y[ia]=otr->srow_y[ia];
+      hdr->srow_z[ia]=otr->srow_z[ia];
+    }
+
+  this->Orientation=this->GetOrientationFromNIFTIHeader();
+  return 1;
+}
+// ----------------------------------------------------------------------------------------------
+/*vtkImageData* vtkbisImageHeader::ReOrientDICOMImageAndFillInHeader(vtkbisDICOMReader* dicomr)
+{
+  if (dicomr==NULL)
+    return NULL;
+
+  if (dicomr->GetOutput()==NULL)
+    return NULL;
+
+  vtkImageData* tmp=vtkImageData::New();
+  tmp->ShallowCopy(dicomr->GetOutput());
+
+  if (tmp->GetDimensions()[0]<1)
+    {
+      tmp->Delete();
+      return NULL;
+    }
+
+  // --- On to real work from here on ----------------
+  fprintf(stderr,"Dicomr is OK\n");
+
+  this->CreateHeader(tmp,0);
+  //  this->SetFileName(dicomr->GetFileName());
+
+  strcpy(this->Header->descrip,"from vtkImageDICOMReader");
+  strcpy(this->Header->aux_file,"vtkbisImageHeader");
+
+  // --- Key Thing now is to get the orientation and work from here .....
+
+  double* vec=dicomr->GetImagePositionPatient();
+
+  double v1[3],v2[3],v3[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      v1[ia]=vec[ia];
+      v2[ia]=vec[ia+3];
+    }
+
+  vtkMath::Normalize(v1);
+  vtkMath::Normalize(v2);
+  vtkMath::Cross(v1,v2,v3);
+
+  fprintf(stderr,"v1 = (%.2f,%.2f,%.2f)\n",v1[0],v1[1],v1[2]);
+  fprintf(stderr,"v2 = (%.2f,%.2f,%.2f)\n",v2[0],v2[1],v2[2]);
+  fprintf(stderr,"v3 = (%.2f,%.2f,%.2f)\n\n",v3[0],v3[1],v3[2]);
+
+  return tmp;
+
+}
+*/
+
+int vtkbisImageHeader::MapOrientationToNewStyle(int oldorient)
+{
+  // Called by mistake
+  if (oldorient>=3)
+    return oldorient;
+
+  if (oldorient==1)
+    return 20;
+  else if (oldorient==2)
+    return 30;
+
+  return 10;
+
+}
+
+int vtkbisImageHeader::MapOrientationToOldStyle(int neworient)
+{
+  // No Conversion needed here
+  if (neworient<=3 && neworient>=0)
+    return neworient;
+
+  // Coronal
+  if ( (neworient>=20 && neworient<=27 ) || (neworient>=50 && neworient<=57))
+    return 1;
+
+  // Sagital
+  if ( (neworient>=30 && neworient<=37) || (neworient>=60 && neworient<=67))
+    return 2;
+
+  // Default is Axial
+  return 0;
+}
+// -------------------------------------------------------------------------------
+int vtkbisImageHeader::MakeStoredHeaderValid()
+{
+  this->Mode=2;
+  this->Orientation= this->GetOrientationFromNIFTIHeader();
+  this->SetFileName("");
+  this->SetIsHeaderValid(1);
+
+  return 1;
+}
+// -------------------------------------------------------------------------------
+int vtkbisImageHeader::ReconcileImageIntensityRange(vtkImageData* img)
+{
+  if (img==NULL || this->IsHeaderValid==0)
+    return 0;
+
+  // if scale=1.0 and offset=0.0 then do nothing !
+  if (fabs(this->GetIntensityScale()-1.0)<0.0001 &&
+      fabs(this->GetIntensityOffset())<0.0001 )
+    {
+      //      fprintf(stderr,"vtkbisImageHeader::No changes to intensity needed\n");
+      return 1;
+    }
+
+  if (this->GetIntensityScale()==0.0)
+    return 1;
+
+
+  //
+
+  double scale=this->GetIntensityScale();
+  double shift=this->GetIntensityOffset();
+
+  // vtkImageShiftScale does
+  //  *outSI = static_cast<OT>((static_cast<double>(*inSI) + shift) * scale);
+  // out = (inp + shift2)* scale2
+  // We want
+  // out = inp*scale1 + shift1
+  //
+  // out= inp*scale2 + shift2*scale2
+  // scale2=scale1
+  // shift2=shift1/scale1
+
+  char line[200];
+  sprintf(line,"BIS::vtkbisImageHeader::Changed Image Intensity Scale and Offset from %.6f,%.6f to 1.0,0.0",
+	  scale,shift);
+
+  if  (fabs(scale)>0.00001)
+    shift=shift/scale;
+
+
+  vtkImageShiftScale* sc=vtkImageShiftScale::New();
+  sc->SetInput(img);
+  sc->SetShift(shift);
+  sc->SetScale(scale);
+
+  if (img->GetScalarType()!=VTK_DOUBLE)
+    sc->SetOutputScalarTypeToFloat();
+  else
+    sc->SetOutputScalarTypeToDouble();
+
+  sc->Update();
+
+  img->ShallowCopy(sc->GetOutput());
+  sc->Delete();
+
+  int dt=vtkbisImageHeader::GetNIFTIDataType(img->GetScalarType());
+  if (this->Header->datatype!=dt)
+    {
+      sprintf(line,"%s and changed Header Datatype : %d --> %d\n",
+	      line,this->Header->datatype,dt);
+      this->Header->datatype=dt;
+      this->Header->bitpix=vtkbisImageHeader::GetBitPix(img->GetScalarType());
+    }
+  this->Header->scl_inter=0.0;
+  this->Header->scl_slope=1.0;
+
+  this->AddComment(line,0);
+  //  fprintf(stderr,"line=%s\n",line);
+  return 1;
+
+}
+
+int vtkbisImageHeader::ForceHeaderToBioImageSuiteCoordinatesAndFlipImage(vtkImageData* inout)
+{
+  int flips[3],transpose=1;
+  int ori=this->ForceHeaderToBioImageSuiteCoordinatesAndReturnFlips(flips,transpose);
+
+  // Flip the image
+  if (flips[0]==0 && flips[1]==0 && flips[2]==0 && transpose==0)
+    return ori;
+
+  double scale[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (flips[ia]>0)
+	scale[ia]=-1.0;
+      else
+	scale[ia]=1.0;
+      //      fprintf(stderr,"Scale (%d) = %.2f\n",flips[ia],scale[ia]);
+    }
+
+
+  vtkTransform* tr=vtkTransform::New();
+  tr->Identity();
+  tr->PostMultiply();
+  tr->Scale(scale);
+
+  if (transpose)
+    {
+      double elements[16] = { 0.0, 1.0, 0.0, 0.0, 
+			      1.0, 0.0, 0.0, 0.0, 
+			      0.0, 0.0, 1.0, 0.0,
+			      0.0, 0.0, 0.0, 1.0 };
+      tr->Concatenate(elements);
+    }
+  
+  vtkImageReslice* resl=vtkImageReslice::New();
+  resl->AutoCropOutputOn();
+  resl->SetInput(inout);
+  resl->SetInterpolationMode(0);
+  resl->OptimizationOff();
+  resl->SetResliceTransform(tr);
+  resl->Update();
+  
+  
+
+  tr->Delete();
+  inout->ShallowCopy(resl->GetOutput());
+  inout->SetOrigin(0.0,0.0,0.0);
+
+  if (inout->GetInformation()->Has(vtkDataObject::ORIGIN()))
+    inout->GetInformation()->Set(vtkDataObject::ORIGIN(),0.0,0.0,0.0);
+  
+  if (inout->GetPipelineInformation()->Has(vtkDataObject::ORIGIN()))
+    inout->GetPipelineInformation()->Set(vtkDataObject::ORIGIN(),0.0,0.0,0.0);
+
+  resl->Delete();
+
+
+  return ori;
+}
+
+char vtkbisImageHeader::OrientationToAxisName(int neworient,int axis)
+{
+  if (neworient<10)
+    neworient=vtkbisImageHeader::MapOrientationToNewStyle(neworient);
+  char codes[7];
+  char newc[1]; strcpy(newc,"?");
+
+  if (neworient>=10 && neworient<=17)
+    strcpy(codes,"LPSRAI");
+  else if (neworient>=20 && neworient<=27)
+    strcpy(codes,"LIPRSA");
+  else if (neworient>=30 && neworient<=37)
+    strcpy(codes,"PSRAIL");
+  else if (neworient>=40 && neworient<=47)
+    strcpy(codes,"PLSARI");
+  else if (neworient>=50 && neworient<=57)
+    strcpy(codes,"ILPSRA");
+  else if (neworient>=60 && neworient<=67)
+    strcpy(codes,"SPRIAL");
+  else
+    return newc[0];
+      
+  int subcode=neworient-10*int(neworient/10);
+  int index[3] = { 0,1,2};
+  if (subcode >=4)
+    index[2]=5;
+  if (subcode==2 || subcode==3 || subcode==6 || subcode==7)
+    index[1]=4;
+  if (subcode==1 || subcode==3 || subcode==5 || subcode==7)
+    index[0]=3;
+
+  if (axis<0 || axis>2)
+    axis=0;
+
+  fprintf(stderr,"axis=%d index=%d,%d,%d, subcode=%d, neworient=%d\n",
+	  axis,index[0],index[1],index[2],subcode,neworient);
+
+  return codes[index[axis]];
+}
+// ---------------------------------------------------------------------
+//  If Generating a JPEG this will tell you if you need to flip any axis
+// ---------------------------------------------------------------------
+int vtkbisImageHeader::GetJPEGFlip(int plane) 
+{
+  mat44 original=vtkbisImageHeader::NIFTI_CreateOrientationMatrix(this->Header);
+  int icod,jcod,kcod;  nifti_mat44_to_orientation(original,&icod,&jcod,&kcod);
+
+  if (plane<0 || plane>2)
+    plane=0;
+  
+  int oldstyleorient=vtkbisImageHeader::MapOrientationToOldStyle(this->Orientation);
+
+  int outcode=0;
+  if (oldstyleorient==0)
+    {
+      switch(plane)
+	{
+	case 2:
+	  if (icod==NIFTI_L2R) outcode+=1;
+	  if (jcod==NIFTI_A2P) outcode+=2;
+	  break;
+	case 1: 
+	  if (icod==NIFTI_L2R) outcode+=1;
+	  if (kcod==NIFTI_S2I) outcode+=2;
+	  break;
+	case 0:
+	  if (icod==NIFTI_A2P) outcode+=1;
+	  if (jcod==NIFTI_S2I) outcode+=2;
+	}
+    }
+  return outcode;
+}
+// -----------------------------------------------------------------------------------
+int vtkbisImageHeader::GetOrientationFromNIFTIHeader()
+{
+  // Step 1 : Establish actual rotation matrix
+
+  nifti_1_header* hdr=this->GetRawHeader();
+  int orientation=0;
+
+  //   METHOD 1 (the "old" way, used only when qform_code = 0):
+  if (hdr->qform_code == 0 && hdr->sform_code==0)
+      return 0;
+
+
+  // Method 2 and 3 Rely on First Creating a 4x4 Matrix
+
+  mat44 original;
+  if (hdr->qform_code==0)
+    {
+      for (int ia=0;ia<=3;ia++)
+	{
+	  original.m[0][ia]=hdr->srow_x[ia];
+	  original.m[1][ia]=hdr->srow_y[ia];
+	  original.m[2][ia]=hdr->srow_z[ia];
+	  original.m[3][ia]=float(ia==3);
+	}
+    }
+  else
+    {
+      original=nifti_quatern_to_mat44(hdr->quatern_b,hdr->quatern_c,hdr->quatern_d,
+				      hdr->qoffset_x,hdr->qoffset_y,hdr->qoffset_z,
+				      fabs(hdr->pixdim[1]),fabs(hdr->pixdim[2]),fabs(hdr->pixdim[3]),
+				      hdr->pixdim[0]);
+    }
+
+  //  vtkbisImageHeader::NIFTI_print_mat44("original",original);
+
+  int icod,jcod,kcod;  nifti_mat44_to_orientation(original,&icod,&jcod,&kcod);
+
+  /*  fprintf(stdout,"Orientation icod=%d (%s), jcod=%d (%s), kcod=%d (%s)\n",
+	  icod,nifti_orientation_string(icod),
+	  jcod,nifti_orientation_string(jcod),
+	  kcod,nifti_orientation_string(kcod));*/
+
+
+
+
+  // Step 1 -- establish orientation -- this is the direction where z axis is at
+
+  int needs_transpose=0;
+  mat44 transpose_matrix;       vtkbisImageHeader::NIFTI_identity_mat44(&transpose_matrix);
+
+
+  int done=0;
+  /* Moreover the first three are also assumed to be (as far as the viewers are concerned)
+
+  Axial = LPS i.e. i-axis Right-to-Left, j-axis: Anterior-to-Posterior (Front-to-Back), k-axis: Inferior to Superior (Bottom-to-Top)
+  Coronal = LIP (Right-to-Left, Superior-to-Inferior, Anterior-to-Posterior)
+  Sagital = PSR (Anterior-to-Posterior, Inferior-to-Superior, Left-to-Right)
+  */
+
+  if  (kcod==NIFTI_I2S || kcod==NIFTI_S2I) 
+    {
+      // Axial: Z-axis along k!
+      //      fprintf(stderr,"Axial ...");
+      if  (icod==NIFTI_L2R || icod==NIFTI_R2L)
+	{
+	  //	  fprintf(stderr,"Normal Axial ...");
+	  orientation=10;
+	  if (icod==NIFTI_L2R) orientation+=1;
+	  if (jcod==NIFTI_P2A) orientation+=2;
+	  if (kcod==NIFTI_S2I) orientation+=4;
+	  done=1;
+	}
+      else if (jcod==NIFTI_L2R || jcod==NIFTI_R2L) 
+	{
+	  //	  fprintf(stderr,"Transposed Axial ...");
+	  // Transposed Axial
+	  orientation=40;
+	  if (icod==NIFTI_P2A) orientation+=1;
+	  if (jcod==NIFTI_L2R) orientation+=2;
+	  if (kcod==NIFTI_S2I) orientation+=4;
+	  done=1;
+	}
+    }
+  else if  (kcod==NIFTI_A2P || kcod==NIFTI_P2A) 
+    {
+      //      fprintf(stderr,"Coronal ...");
+      if (icod==NIFTI_L2R || icod==NIFTI_R2L)
+	{
+	  // Coronal
+	  //  fprintf(stderr,"Normal Coronal ...");
+	  orientation=20;
+	  if (icod==NIFTI_L2R) orientation+=1;
+	  if (jcod==NIFTI_I2S) orientation+=2;
+	  if (kcod==NIFTI_P2A) orientation+=4;
+	  done=1;
+	}
+      else if (jcod==NIFTI_L2R || jcod==NIFTI_R2L)
+	{
+	  //	  fprintf(stderr,"Transposed Coronal ...");
+	  orientation=50;
+	  if (icod==NIFTI_I2S) orientation+=1;
+	  if (jcod==NIFTI_L2R) orientation+=2;
+	  if (kcod==NIFTI_P2A) orientation+=4;
+	  done=1;
+	}
+    }
+  else if (kcod==NIFTI_L2R || kcod==NIFTI_R2L)
+    {
+      //      fprintf(stderr,"Sagital ...");
+      if (jcod==NIFTI_I2S || jcod == NIFTI_S2I)
+	{
+	  // Sagittal
+	  //  fprintf(stderr,"Normal Sag ...");
+	  orientation=30;
+	  if (icod==NIFTI_P2A) orientation+=1;
+	  if (jcod==NIFTI_S2I) orientation+=2;
+	  if (kcod==NIFTI_R2L) orientation+=4;
+	  done=1;
+	}
+      else if (icod==NIFTI_I2S || icod == NIFTI_S2I)
+	{
+	  // Transposed Sagittal
+	  //	  fprintf(stderr,"Transp Sag ...");
+	  orientation=60;
+	  if (icod==NIFTI_S2I) orientation+=1;
+	  if (jcod==NIFTI_P2A) orientation+=2;
+	  if (kcod==NIFTI_R2L) orientation+=4;
+	  done=1;
+	}
+    }
+
+  if (done==0)
+    {
+      fprintf(stdout,"Confused Orientation icod=%d (%s), jcod=%d (%s), kcod=%d (%s)\n",
+	      icod,nifti_orientation_string(icod),
+	      jcod,nifti_orientation_string(jcod),
+	      kcod,nifti_orientation_string(kcod));
+      return -1;
+    }
+
+  return orientation;
+}
+// -------------------------------------------------------------------------------------
+int vtkbisImageHeader::ForceHeaderToBioImageSuiteCoordinatesAndReturnFlips(int DataFlip[3],int& Transpose)
+{
+  DataFlip[0]=0;
+  DataFlip[1]=0;
+  DataFlip[2]=0;
+  Transpose=0;
+
+  nifti_1_header* hdr=this->GetRawHeader();
+  int new_orientation=0;
+    
+  //   METHOD 1 (the "old" way, used only when qform_code = 0):
+  if (hdr->qform_code == 0 && hdr->sform_code==0)
+    return new_orientation;
+
+
+  // Method 2 and 3 Rely on First Creating a 4x4 Matrix
+  
+  mat44 original;
+  if (hdr->qform_code==0)
+    {
+      for (int ia=0;ia<=3;ia++)
+	{
+	  original.m[0][ia]=hdr->srow_x[ia];
+	  original.m[1][ia]=hdr->srow_y[ia];
+	  original.m[2][ia]=hdr->srow_z[ia];
+	  original.m[3][ia]=float(ia==3);
+	}
+    }
+  else
+    {
+      original=nifti_quatern_to_mat44(hdr->quatern_b,hdr->quatern_c,hdr->quatern_d,
+				      hdr->qoffset_x,hdr->qoffset_y,hdr->qoffset_z,
+				      fabs(hdr->pixdim[1]),fabs(hdr->pixdim[2]),fabs(hdr->pixdim[3]),
+				      hdr->pixdim[0]);
+    }
+
+
+  double spa[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      double sum=0.0;
+      for (int ib=0;ib<=2;ib++)
+		sum+=pow(original.m[ib][ia],2.0f);
+      spa[ia]=sqrt(sum);
+    }
+
+
+  //  vtkbisImageHeader::NIFTI_print_mat44("original",original);
+  //  fprintf(stderr,"Spacing = %.2f %.2f %.2f\n",spa[0],spa[1],spa[2]);
+	 
+
+
+  int icod,jcod,kcod;  nifti_mat44_to_orientation(original,&icod,&jcod,&kcod);
+  
+  /*  fprintf(stderr,"Orientation icod=%d (%s), jcod=%d (%s), kcod=%d (%s)\n",
+	  icod,nifti_orientation_string(icod),
+	  jcod,nifti_orientation_string(jcod),
+	  kcod,nifti_orientation_string(kcod));*/
+  
+
+
+
+  // Step 1 -- establish orientation -- this is the direction where z axis is at
+
+  int needs_transpose=0;
+  mat44 transpose_matrix;       vtkbisImageHeader::NIFTI_identity_mat44(&transpose_matrix);
+
+  int newdim[3]; this->GetDimensions(newdim);
+  int dim[3];    this->GetDimensions(dim);
+
+  int do_transpose=0;
+  int can_handle=0;
+
+  if  (kcod==NIFTI_I2S || kcod==NIFTI_S2I) 
+    {
+      // Axial: Z-axis along k!
+      //      fprintf(stderr,"Axial ...");
+      if  (icod==NIFTI_L2R || icod==NIFTI_R2L)
+	{
+	  //	  fprintf(stderr,"Normal Axial ...");
+	  new_orientation=10;
+	  if (icod==NIFTI_L2R)	DataFlip[0]=1;
+	  if (jcod==NIFTI_P2A)	DataFlip[1]=1;
+	  if (kcod==NIFTI_S2I)	DataFlip[2]=1;
+	  can_handle=1;
+	}
+      else if (jcod==NIFTI_L2R || jcod==NIFTI_R2L) 
+	{
+	  //	  fprintf(stderr,"Transposed Axial ...");
+	  // Transposed Axial
+	  new_orientation=10;
+	  // This is a transposed axial ....
+	  // Step 1 -- switch x and y
+	  transpose_matrix.m[0][0]=0;      transpose_matrix.m[0][1]=1.0;
+	  transpose_matrix.m[1][0]=1.0;      transpose_matrix.m[1][1]=0;
+	  newdim[1]=dim[0]; newdim[0]=dim[1];
+	  
+	  // Step 2 -- check coordinates as before
+	  if (jcod==NIFTI_L2R)	DataFlip[1]=1;
+	  if (icod==NIFTI_P2A)	DataFlip[0]=1;
+	  if (kcod==NIFTI_S2I)	DataFlip[2]=1;
+	  
+	  do_transpose=1;
+	  can_handle=1;
+	}
+    }
+  else if  (kcod==NIFTI_A2P || kcod==NIFTI_P2A) 
+    {
+      //      fprintf(stderr,"Coronal ...");
+      if (icod==NIFTI_L2R || icod==NIFTI_R2L)
+	{
+	  // Coronal
+	  //	  fprintf(stderr,"Normal Coronal ...");
+	  new_orientation=20;
+	  if (icod==NIFTI_L2R)	DataFlip[0]=1;
+	  if (jcod==NIFTI_I2S)	DataFlip[1]=1;
+	  if (kcod==NIFTI_P2A)	DataFlip[2]=1;
+	  can_handle=1;
+	}
+      else if (jcod==NIFTI_L2R || jcod==NIFTI_R2L)
+	{
+	  //	  fprintf(stderr,"Transposed Coronal ...");
+	  new_orientation=20;
+	  // Step 1 -- switch x and z
+	  transpose_matrix.m[0][0]=0;        transpose_matrix.m[0][1]=1.0;
+	  transpose_matrix.m[1][0]=1.0;      transpose_matrix.m[1][1]=0;
+	  newdim[0]=dim[2]; newdim[2]=dim[0];
+	  // Step 2 -- check coordinates as before
+	  if (jcod==NIFTI_L2R)	DataFlip[1]=1;
+	  if (icod==NIFTI_I2S)	DataFlip[0]=1;
+	  if (kcod==NIFTI_P2A)	DataFlip[2]=1;
+	  do_transpose=1;
+	  can_handle=1;
+	}
+    }
+  else if (kcod==NIFTI_L2R || kcod==NIFTI_R2L)
+    {
+      //      fprintf(stderr,"Sagital ...");
+      if (jcod==NIFTI_I2S || jcod == NIFTI_S2I)
+	{
+	  // Sagittal
+	  //	  fprintf(stderr,"Normal Sag ...");
+	  new_orientation=30;
+	  if (icod==NIFTI_P2A)	DataFlip[0]=1;
+	  if (jcod==NIFTI_S2I)	DataFlip[1]=1;
+	  if (kcod==NIFTI_R2L)	DataFlip[2]=1;
+	  can_handle=1;
+	}
+      else if (icod==NIFTI_I2S || icod == NIFTI_S2I)
+	{
+	  // Transposed Sagittal
+	  //	  fprintf(stderr,"Transp Sag ...");
+	  new_orientation=30;
+	  // Step 1 -- switch y and z
+	  transpose_matrix.m[0][1]=0;        transpose_matrix.m[0][1]=1.0;
+	  transpose_matrix.m[1][0]=1.0;      transpose_matrix.m[1][1]=0.0;
+	  newdim[1]=dim[2]; newdim[2]=dim[1];
+	  
+	  // Step 2 -- check coordinates as before
+	  if (jcod==NIFTI_P2A)	DataFlip[0]=1;
+	  if (icod==NIFTI_S2I)	DataFlip[1]=1;
+	  if (kcod==NIFTI_R2L)	DataFlip[2]=1;
+	  do_transpose=1;
+	  can_handle=1;
+	}
+    }
+
+  if (can_handle==0)
+    {
+      fprintf(stderr,"Can't handle this orientation ... not sure what to do\n");
+      fprintf(stderr,"Orientation icod=%d (%s), jcod=%d (%s), kcod=%d (%s)\n",
+	      icod,nifti_orientation_string(icod),
+	      jcod,nifti_orientation_string(jcod),
+	      kcod,nifti_orientation_string(kcod));
+      return new_orientation;
+    }
+
+  //  fprintf(stderr,"On to computing flips etc, Orientation=%d (flips=%d,%d,%d) do_transpose=%d\n",
+  //	  new_orientation,DataFlip[0],DataFlip[1],DataFlip[2],do_transpose);
+
+  // Now we have the data flips we need to figure out what to do
+  // Original matrix is  xyz= orig * ijk
+  // Need     new matrix xyz= new  * i'j'k'
+  // Which is            ijk= (flip * transpose) i'j'k'
+  //
+  // new = orig * flip * transpose
+  // Key is to find flip and transpose matrices !!!!!
+  
+  mat44 flip;  vtkbisImageHeader::NIFTI_identity_mat44(&flip);
+  //  vtkbisImageHeader::NIFTI_print_mat44("flip matrix 1",flip);
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (DataFlip[ia]==1)
+	{
+	  flip.m[ia][ia]=-1.0;
+	  flip.m[ia][3] = newdim[ia]-1;
+	}
+    }
+  /*  fprintf(stderr,"Data Flip=%d,%d,%d tr=%d\n",
+      DataFlip[0],DataFlip[1],DataFlip[2],do_transpose);*/
+  //  vtkbisImageHeader::NIFTI_print_mat44("flip",flip);
+  //  vtkbisImageHeader::NIFTI_print_mat44("trans",transpose_matrix);
+  mat44 mapping=vtkbisImageHeader::NIFTI_mat44_mmul(flip,transpose_matrix);
+  //  vtkbisImageHeader::NIFTI_print_mat44("mapping",mapping);
+
+  this->ModifyOrientation(mapping,DataFlip,do_transpose);
+
+
+
+  if (do_transpose)
+    Transpose=1;
+
+  
+
+  return this->Orientation;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkbisImageHeader.h b/bioimagesuite30_src/Common/vtkbisImageHeader.h
new file mode 100644
index 0000000..558c894
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisImageHeader.h
@@ -0,0 +1,335 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkbisImageHeader - a class for storing medical image headers (Analyze/NIFTI) 
+// .SECTION Description
+// This class has functionality for reading/writing and storing a medical image header 
+// It it essentially a wrapper around the NIFT1 format with Analyze 7.5 backwards compatibility.
+// It also includes code for reformatting images from coronal and sagittal back to axial
+//
+
+#ifndef __vtkbisImageHeader_h
+#define __vtkbisImageHeader_h
+
+#include "vtkObject.h"
+#include "bis_znzlib.h"
+#include <string>
+
+class vtkImageData;
+class vtkbisNIFTIExtensionsList;
+class vtkMatrix4x4;
+class vtkXMLDataElement;
+
+// These are NIFTY Things
+#include <nifti1.h>
+#include <nifti1_io.h>
+
+
+class vtkbisImageHeader : public vtkObject
+{
+public:
+  static vtkbisImageHeader *New();
+  vtkTypeMacro(vtkbisImageHeader,vtkObject);
+
+  // Description:
+  // Print Self Diagnostic
+  virtual void PrintAll(int show_extensions=1);
+  virtual void PrintHeader(int long_mode=1);
+  virtual  char* GetHeaderDescription(int long_mode=1);
+
+  // Description:
+  // Read Header -- this is generic and will test first NIFTI1 and then Analyze
+  virtual int ReadHeader(char* fname);
+  virtual int WriteHeader(char* fname,int compression=0);
+
+  // Description:
+  // Stuff for Execute Information
+  // Get VTK Data Type from Header
+  virtual int GetVTKDataType();
+  // Simply Ordered from 0 on (from edit menu purposes)
+  virtual int GetIndexedDataType();
+  virtual void SetIndexedDataType(int ind);
+  virtual void GetDimensions(int dim[3]);
+  virtual void GetSpacing(double spa[3]);
+  virtual int  GetNumberOfComponents();
+  
+  
+  // Description:
+  // Save NII Header in already open stream (used for .nii, .nii.gz files)
+  virtual int WriteNIFTIHeader(znzFile fout);
+
+  // Description:
+  // Read/Write Headers
+  int WriteNIFTIHeader(char* filename,int compression);
+  int WriteAnalyzeHeader(char* filename);
+
+  // Description:
+  // Read Headers
+  virtual int ReadNIFTIHeader(char* filename);
+  virtual int ReadAnalyzeHeader(char* filename);
+  virtual int CreateVarianHeader(vtkXMLDataElement* element);
+
+  // Description:
+  // Set All Fields to Default Values
+  virtual int ResetFields();
+
+  // Description:
+  // Initialize (i.e. Reset Fields)
+  virtual void Initialize() { this->ResetFields(); }
+
+  // Description:
+  // GetIsHeaderValid() -- diagnostic to test whether a valid header has been read
+  // Force this to one for editor
+  vtkGetMacro(IsHeaderValid,int);
+  vtkSetMacro(IsHeaderValid,int);
+
+  // Description:
+  // Get Header Offset -- returns the offset from the start of the image (in case of .nii files)
+  vtkGetMacro(HeaderOffset,int);
+  vtkGetMacro(SwapBytes,int);
+  
+
+  // Description:
+  // Static Conversion Functions
+  static int  GetNIFTIDataType(int vtkdatatype);
+  static int  GetBitPix(int vtkdatatype);
+  static int  GetVTKDataType(int niftidatatype);
+  
+  // Description:
+  // Create Header from vtkImageData
+  virtual int CreateHeader(vtkImageData* img,int useorigin=0);
+
+  // Description:
+  // Often the header is copied from another image that 
+  // is in the same space but reampled or truncated in time
+  // ReconcileHeader will fix the header for this purpose
+  // The assumption is that this has the same orientation!!!
+  // Use this with extreme care!
+  virtual int ReconcileHeader(vtkImageData* img,int useorigin=0);
+
+  // Description:
+  // This is the opposite of the above, the image will get reconciled
+  // This will change the spacing and optionally the origin of the image
+  virtual int ReconcileImage(vtkImageData* img,int useorigin=0);
+
+  // Description:
+  // This will scale the image to be in the new range (multiply by scale and add offset)
+  // and change the intensity scale and offset in the header to 1.0 and 0.0 and
+  // add a comment in the header to this effect
+  // Often will be called on load as part of image reconciliation
+  // If needed image will be made float!
+  virtual int ReconcileImageIntensityRange(vtkImageData* img);
+
+  // Description:
+  // Given a header (raw) created from external software
+  // accept as valid and create cached fields
+  virtual int MakeStoredHeaderValid();
+
+
+  // Description:
+  // Newer code for copying parts of header
+  // these are useful when reslicing images and need to preserve part of the 
+  // header from the resliced image and part from the reference
+  virtual int CopyExtensionsOnly(vtkbisImageHeader* other);
+  virtual int CopyLocationInformationOnly(vtkbisImageHeader* other);
+
+
+  // Description:
+  // Copy Other Header
+  virtual int CopyHeader(vtkbisImageHeader* other);
+  virtual int CopyNIFTIHeader(const nifti_1_header* header);
+  virtual int StoreInNIFTIHeader(nifti_1_header* header);
+
+  // Description:
+  // Add Comment -- with and without date stamp
+  virtual int AddComment(const char* comment);
+  virtual int AddComment(const char* comment,int code);
+  
+  // Description:
+  // Mode: 0=Analyze, 1=NIFTI, 2= NIFTI .nii
+  vtkGetMacro(Mode,int);
+  virtual int HasFullNIFTIHeader() { return (this->Mode>0);}
+  virtual int SetModeToAnalyze() { this->Mode=0; return 1;}
+  virtual int SetModeToNIFTI_HDRIMG();
+  virtual int SetModeToNIFTI_NII();
+
+
+  // Description:
+  // Analyze Stuff
+  // 0 = Axial 1= Coronal 2=Sagittal
+  vtkGetMacro(Orientation,int);
+  virtual void SetOrientation(int orient);
+  virtual void SetOrientationComplex(int orient,int nomatrixops);
+  virtual void SetOrientationAsMatrix(mat44 newmat); 
+
+  // Description:
+  // More Complex Stuff 
+  virtual int ApplyShift(double x,double y,double z);
+  virtual int ModifyOrientation(mat44 mapping,int DataFlip[3],int do_transpose);
+  virtual int ForceHeaderToBioImageSuiteCoordinatesAndReturnFlips(int dataflip[3],int& transpose);
+  virtual int ForceHeaderToBioImageSuiteCoordinatesAndFlipImage(vtkImageData* inout);
+
+
+  // Description:
+  // Even more complex Stuff
+  // Given a plane (i.e. 0=XY,1=XZ,2=YZ) and current orientation ,figure out flips for JPEG display 
+  // Output is 0 no flips, 1=flipx,2=flipy,3=flipboth,4=transpose,5=transpose+flipx, ....
+  virtual int GetJPEGFlip(int Plane);
+
+  // Description:
+  // Legacy Analyze Extensions 
+  virtual void    GetOrigin(double origin[3]);
+  virtual double  GetOriginComponent(int a);
+  virtual void    SetOrigin(double origin[3]);
+  virtual void    SetOrigin(double x,double y,double z);
+  virtual short   GetVOIValue();
+  virtual void    SetVOIValue(short a);
+  virtual char*   GetDBName();
+  virtual void    SetDBName(const char* name);
+  virtual const char* GetOrientationCode();
+
+  // Description:
+  // Last Filename
+  vtkSetStringMacro(FileName);
+  vtkGetStringMacro(FileName);
+
+
+  // Description:
+  // Usefull Stuff
+  virtual void SetImageStructureFromHeader(vtkImageData* img);
+  virtual vtkImageData* AllocateImageFromHeaderInfo();
+
+  // BTX
+  // Description:
+  // Raw NIFTI1 Utilities
+  static int CopyHeader(const nifti_1_header* input,nifti_1_header* output);
+  static int InitializeHeader(nifti_1_header* header);
+
+  // Description:
+  // File Name Utilities
+  static znzFile SuffixOpen (const char* path, const char* mode,int complevel=0);
+  static int    FindExtension(const char* orig,const char* lookfor,const char* lookfor2=NULL);
+  static char*  EatSuffix(const char *orig_filename);
+  static char*  CreateFilename(const char* orig_filename,const char* wanted,const char *unwanted);
+  static char*  CreateAnalyzeHDRFilename(const char* fname);
+  static char*  CreateAnalyzeIMGFilename(const char* fname);
+
+  // Description:
+  // Access Raw Geader
+  nifti_1_header* GetRawHeader() { return this->Header;}
+  vtkbisNIFTIExtensionsList* GetExtensions() { return this->Extensions;}
+
+
+  // Description:
+  // Matrix Utilities in Mat44 for NIFTI Header Stuff argh
+  //BTX
+  static mat44 NIFTI_CreateOrientationMatrix( nifti_1_header *hdr);
+  static const char* NIFTI_GetOrientationString( int ii);
+  static const char* NIFTI_GetOrientationStringShort( int ii);
+
+
+  static mat44 NIFTI_mat44_mmul( mat44 A , mat44 B );  /* multiply 2 4x4 matrices */
+  static void NIFTI_print_mat44(char* s, mat44 A);
+  static void NIFTI_identity_mat44(mat44* A);
+  static mat44 NIFTI_Copy_Matrix4x4_mat44(vtkMatrix4x4* input);
+  static vtkMatrix4x4* NIFTI_CopyMat44(mat44 input);
+
+  
+  // Description:
+  // Apply Mapping
+  virtual int ApplyMapping(mat44 mapping,int premultiply=0);
+  //ETX
+
+
+  // Description:
+  // Map Nw Style Orientations to Old Style and back
+  // New Style Axial=10:17, Coronal: 20-27, Sagital 30:37
+  //           Transposed Axial 40:47
+  //           Transposed Coronal 50:57
+  //           Transposed Sagittal 60:67
+  // Old Style Axial =0, coronal =1 , sagittal = 2
+  static int MapOrientationToNewStyle(int oldorient);
+  static int MapOrientationToOldStyle(int neworient);
+  static char OrientationToAxisName(int neworient,int axis);
+
+  // Description:
+  // Intensity Scale and Offset
+  virtual double GetIntensityScale();
+  virtual double GetIntensityOffset();
+
+protected:
+
+  vtkbisImageHeader();
+  virtual ~vtkbisImageHeader();
+  vtkbisImageHeader(const vtkbisImageHeader&) {};
+  void operator=(const vtkbisImageHeader&) {};
+
+  // Description:
+  // Mode (0=Analyze,1 =NIFT1)
+  int Mode;
+
+  // Description:
+  // Filename last used
+  char* FileName;
+
+  // Description:
+  // Header Stuf
+  nifti_1_header* Header;
+  vtkbisNIFTIExtensionsList* Extensions;
+
+  // Description:
+  // Other Flags
+  int IsHeaderValid;
+  int HeaderOffset;
+  int SwapBytes;
+
+
+  // Description:
+  // Orientation:
+  int Orientation;
+
+  // Buffer to Keep the Origin in
+  double OriginBuffer[3];
+
+
+  
+  // Description:
+  // Get Orientation
+  virtual int GetOrientationFromNIFTIHeader();
+
+  // Description:
+  // Buffer String
+  //BTX
+  std::string Buffer;
+  //ETX
+};
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkbisImageReOrient.cpp b/bioimagesuite30_src/Common/vtkbisImageReOrient.cpp
new file mode 100644
index 0000000..58cabf9
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisImageReOrient.cpp
@@ -0,0 +1,323 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkbisImageReOrient.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkbisImageReslice.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include <stdio.h>
+#include "pxutil.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "nifti1_io.h"
+
+
+vtkbisImageReOrient* vtkbisImageReOrient::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisImageReOrient");
+  if(ret)
+    {
+      return (vtkbisImageReOrient*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisImageReOrient;
+}
+
+
+// Construct object to extract all of the input data.
+vtkbisImageReOrient::vtkbisImageReOrient()
+{
+  this->SimpleMode=1;
+  this->InputImageHeader=NULL;
+  this->OutputImageHeader=NULL;
+  this->FullMatrix=NULL;
+  this->OutputOrientation=10;
+}
+
+void vtkbisImageReOrient::SetOutputOrientationToLPS()
+{ 
+  this->SetFullMatrix(NULL);
+  this->SetSimpleMode(1); 
+  this->SetOutputOrientation(10); 
+}
+
+void vtkbisImageReOrient::SetOutputOrientationToRAS()
+{
+  this->SetFullMatrix(NULL);
+  this->SetSimpleMode(1); 
+  this->SetOutputOrientation(13); 
+}
+
+void vtkbisImageReOrient::SetOutputOrientationToLIP()
+{
+  this->SetFullMatrix(NULL);
+  this->SetSimpleMode(1); 
+  this->SetOutputOrientation(20); 
+}
+
+void vtkbisImageReOrient::SetOutputOrientationToRSA()
+{
+  this->SetFullMatrix(NULL);
+  this->SetSimpleMode(1); 
+  this->SetOutputOrientation(27); 
+
+}
+
+void vtkbisImageReOrient::SetOutputOrientationToPSR()
+{
+  this->SetFullMatrix(NULL);
+  this->SetSimpleMode(1); 
+  this->SetOutputOrientation(30); 
+
+}
+
+void vtkbisImageReOrient::SetOutputOrientationToASR()
+{
+  this->SetFullMatrix(NULL);
+  this->SetSimpleMode(1); 
+  this->SetOutputOrientation(31); 
+}
+
+
+// ---------------------------------------------------------------------------
+
+void vtkbisImageReOrient::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkSimpleImageToImageFilter::PrintSelf(os,indent);
+}
+// ---------------------------------------------------------------------------
+int vtkbisImageReOrient::GenerateArraysAndOutputImageHeader()
+{
+
+  // Defaults
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->Axis[ia]=ia; 
+      this->Flip[ia]=0;
+    }
+
+  if (this->InputImageHeader==NULL)
+    return 0;
+
+  
+  nifti_1_header* hdr=this->InputImageHeader->GetRawHeader();
+  mat44 B=vtkbisImageHeader::NIFTI_CreateOrientationMatrix(hdr);
+
+  //  vtkbisImageHeader::NIFTI_print_mat44("Input B",B);
+
+  
+
+  
+  mat44 A;
+  vtkbisImageHeader::NIFTI_identity_mat44(&A);
+  double spa[3]; this->InputImageHeader->GetSpacing(spa);
+  
+  if (this->SimpleMode==0 && this->FullMatrix!=NULL)
+    {
+      A=vtkbisImageHeader::NIFTI_Copy_Matrix4x4_mat44(this->FullMatrix);
+    }
+  else if (this->OutputOrientation==20)
+    {
+      A.m[0][0]=-1.0; A.m[1][1]=0.0; A.m[2][2]=0.0;
+      A.m[1][2]=-1.0; A.m[2][1]=-1.0;
+    }
+  else if (this->OutputOrientation==27)
+    {
+      A.m[0][0]=1.0; A.m[1][1]=0.0; A.m[2][2]=0.0;
+      A.m[1][2]=1.0; A.m[2][1]=1.0;
+    }
+  else if (this->OutputOrientation==30)
+    {
+      A.m[0][0]=0.0; A.m[1][1]=0.0; A.m[2][2]=0.0;
+      A.m[0][2]=1.0; A.m[1][0]=-1.0; A.m[2][1]=1.0;
+    }
+  else if (this->OutputOrientation==31)
+    {
+      A.m[0][0]=0.0; A.m[1][1]=0.0; A.m[2][2]=0.0;
+      A.m[0][2]=1.0; A.m[1][0]=1.0; A.m[2][1]=1.0;
+    }
+  else
+    {
+      // Standard Axial Stuff
+      for (int ia=0;ia<=2;ia++)
+	A.m[ia][ia]=spa[ia];
+      if (this->OutputOrientation==10)
+	{
+	  A.m[0][0]=-A.m[0][0];
+	  A.m[1][1]=-A.m[1][1];
+	}
+    }
+
+  
+
+  //  vtkbisImageHeader::NIFTI_print_mat44("Output A",A);
+
+  // Out Orientation out=A*in;  A=out*in(-1)
+  // To fix this one here ......
+  mat44 invA=nifti_mat44_inverse(A);
+  /*  for (int ia=0;ia<=2;ia++)
+      origmat.m[3][ia]=0;*/
+  // ...........
+
+  // combo=A^{-1}*B;  A= inv(combo*B{-1}) = B*inv(combo)
+  mat44 combo=vtkbisImageHeader::NIFTI_mat44_mmul( invA,B);
+  //  vtkbisImageHeader::NIFTI_print_mat44("Mapping",combo);
+
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->Axis[ia]=0;
+      if (combo.m[ia][0]<0)
+	this->Flip[ia]=1;
+      else
+	this->Flip[ia]=0;
+
+
+      for (int ib=0;ib<=2;ib++)
+	{
+	  if (fabs(combo.m[ia][ib]/spa[ib])>fabs(combo.m[ia][this->Axis[ia]]/spa[this->Axis[ia]]))
+	    {
+	      this->Axis[ia]=ib;
+	      if (combo.m[ia][ib]<0)
+		this->Flip[ia]=1;
+	      else
+		this->Flip[ia]=0;
+	    }
+	}
+    }
+
+  for (int ia=0;ia<=2;ia++)
+    combo.m[ia][3]=0.0;   
+  mat44 icombo=nifti_mat44_inverse(combo);
+  mat44 ap=vtkbisImageHeader::NIFTI_mat44_mmul( B,icombo);
+  //    vtkbisImageHeader::NIFTI_print_mat44("ap",ap);
+
+
+  //  for (int ia=0;ia<=2;ia++)
+  //    fprintf(stdout,"Setting output axis %d from %d (Flip=%d)\n",ia,this->Axis[ia],this->Flip[ia]);
+
+  if (this->OutputImageHeader==NULL)
+    this->OutputImageHeader=vtkbisImageHeader::New();
+  
+  this->OutputImageHeader->CopyHeader(this->InputImageHeader);
+  this->OutputImageHeader->SetOrientationAsMatrix(ap);
+  //  this->OutputImageHeader->PrintHeader(1);
+  return 1;
+}
+
+// ---------------------------------------------------------------------------
+int vtkbisImageReOrient::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+					  vtkInformationVector *outputVector)
+{
+  vtkInformation *inInfo =  inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  int wholeExtent[6]; inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
+  double sp[3];  inInfo->Get(vtkDataObject::SPACING(), sp);
+  double origin[3];  inInfo->Get(vtkDataObject::ORIGIN(),  origin);
+
+
+  //vtkImageData* input=this->GetImageDataInput(0);
+  
+  
+  this->GenerateArraysAndOutputImageHeader();
+
+
+  double outorigin[3],osp[3]; int outext[6];
+  for (int ia=0;ia<=2;ia++)
+    {
+      outorigin[ia]=0.0;
+      osp[ia]=sp[this->Axis[ia]];
+      outext[2*ia]=wholeExtent[this->Axis[ia]*2];
+      outext[2*ia+1]=wholeExtent[this->Axis[ia]*2+1];
+    }
+ 
+  outInfo->Set(vtkDataObject::ORIGIN(), outorigin, 3);
+  outInfo->Set(vtkDataObject::SPACING(), osp, 3);
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),outext,6);
+  return 1;
+}
+// ---------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+void vtkbisImageReOrient::SimpleExecute(vtkImageData* input, vtkImageData* output) 
+{
+  
+
+  int dim[3]; input->GetDimensions(dim);
+  int odim[3]; output->GetDimensions(odim);
+  int nc=input->GetNumberOfScalarComponents();
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  int ia[3];
+
+  int outincr[3];
+  outincr[0]=1;
+  outincr[1]=odim[0];
+  outincr[2]=odim[0]*odim[1];
+
+/*  fprintf(stderr,"OutIncr=%d,%d,%d, odim=%d,%d,%d idim=%d,%d,%d\n",
+	  outincr[0],outincr[1],outincr[2],
+	  odim[0],odim[1],odim[2],
+	  dim[0],dim[1],dim[2]);*/
+	  
+
+  int index=0;
+  for (ia[2]=0;ia[2]<dim[2];ia[2]++)
+    {
+      //      fprintf(stderr,"Doing Slice=%d\n",ia[2]);
+      for (ia[1]=0;ia[1]<dim[1];ia[1]++)
+	for (ia[0]=0;ia[0]<dim[0];ia[0]++)
+	  {
+	    int ib[3];
+	    for (int j=0;j<=2;j++)
+	      {
+		ib[j]=ia[this->Axis[j]];
+		if (this->Flip[j]>0)
+		  ib[j]=(odim[j]-1)-ib[j];
+	      }
+	    int outindex=ib[0]*outincr[0]+ib[1]*outincr[1]+ib[2]*outincr[2];
+	    
+	    for (int c=0;c<nc;c++)
+	      out->SetComponent(outindex,c,inp->GetComponent(index,c));
+	    ++index;
+	  }
+    }
+
+  //  this->OutputImageHeader->ReconcileImage(output,0);
+}
+
+
diff --git a/bioimagesuite30_src/Common/vtkbisImageReOrient.h b/bioimagesuite30_src/Common/vtkbisImageReOrient.h
new file mode 100644
index 0000000..3b94f21
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisImageReOrient.h
@@ -0,0 +1,145 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+  
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkbisImageReOrient.h,v $
+  Language:  C++
+  Date:      $Date: 2003/05/13 15:37:02 $
+  Version:   $Revision: 1.2 $
+  
+  
+  Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+  All rights reserved.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+  
+=========================================================================*/
+// .NAME vtkbisImageReOrient - Reslices an image and creates a new header for the new orientation
+
+
+#ifndef __vtkbisImageReOrient_h
+#define __vtkbisImageReOrient_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkbisImageHeader.h"
+#include "vtkMatrix4x4.h"
+
+class vtkbisImageReOrient : public vtkSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkbisImageReOrient,vtkSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  
+  // Description:
+  // Construct object to extract all of the input data.
+  
+  static vtkbisImageReOrient *New();
+  
+  vtkGetObjectMacro(InputImageHeader,vtkbisImageHeader);
+  vtkSetObjectMacro(InputImageHeader,vtkbisImageHeader);
+  vtkGetObjectMacro(OutputImageHeader,vtkbisImageHeader);
+
+
+  // Description:
+  // Polar Mode used for ultrasound images
+  vtkSetClampMacro(SimpleMode,int,0,1);
+  vtkGetMacro(SimpleMode,int);
+  vtkBooleanMacro(SimpleMode,int);
+
+
+  // Description:
+  // Complex Mode -- if SimpleMode is zero use matrix instead
+  vtkSetObjectMacro(FullMatrix,vtkMatrix4x4);
+  vtkGetObjectMacro(FullMatrix,vtkMatrix4x4);
+
+  // Description:
+  // Standard OutputOrientations
+  virtual void SetOutputOrientationToLPS();
+  virtual void SetOutputOrientationToRAS();
+  virtual void SetOutputOrientationToLIP();
+  virtual void SetOutputOrientationToRSA();
+  virtual void SetOutputOrientationToPSR();
+  virtual void SetOutputOrientationToASR();
+
+
+  
+  
+  // Description:
+  // Get Numerical Code for Orientation
+  vtkGetMacro(OutputOrientation,int);
+
+protected:
+  //BTX
+  vtkbisImageReOrient();
+  ~vtkbisImageReOrient() {};
+  vtkbisImageReOrient(const vtkbisImageReOrient&) {};
+  void operator=(const vtkbisImageReOrient&) {};
+
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+  
+  // Execute Information Replacements
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+  //BTX
+  virtual int GenerateArraysAndOutputImageHeader();
+
+  // Variables
+  vtkbisImageHeader* InputImageHeader;
+  vtkbisImageHeader* OutputImageHeader;
+  vtkMatrix4x4*      FullMatrix;
+
+  // Variables -- old style orientation
+  int OutputOrientation;
+  int SimpleMode;
+  int Axis[3],Flip[3];
+
+  // Description:
+  // OutputOrientation Code
+  vtkSetMacro(OutputOrientation,int);
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkbisImageResample.cpp b/bioimagesuite30_src/Common/vtkbisImageResample.cpp
new file mode 100644
index 0000000..63c9ad8
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisImageResample.cpp
@@ -0,0 +1,54 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkbisImageResample.cxx,v $
+
+  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 "vtkbisImageResample.h"
+#include "vtkObjectFactory.h"
+
+
+vtkCxxRevisionMacro(vtkbisImageResample, "$Revision: 1.43 $");
+vtkStandardNewMacro(vtkbisImageResample);
+
+//----------------------------------------------------------------------------
+// Constructor: Sets default filter to be identity.
+vtkbisImageResample::vtkbisImageResample()
+{
+}
+
diff --git a/bioimagesuite30_src/Common/vtkbisImageResample.h b/bioimagesuite30_src/Common/vtkbisImageResample.h
new file mode 100644
index 0000000..e0d209c
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisImageResample.h
@@ -0,0 +1,67 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkbisImageResample.h,v $
+
+  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 vtkbisImageResample - Resamples an image to be larger or smaller.
+// .SECTION Description
+// This is a legacy code, now it is essentially vtkImageResample
+
+
+#ifndef __vtkbisImageResample_h
+#define __vtkbisImageResample_h
+
+
+#include "vtkImageResample.h"
+
+class  vtkbisImageResample : public vtkImageResample
+{
+public:
+  static vtkbisImageResample *New();
+  vtkTypeRevisionMacro(vtkbisImageResample,vtkImageResample);
+
+protected:
+  vtkbisImageResample();
+private:
+  vtkbisImageResample(const vtkbisImageResample&);  // Not implemented.
+  void operator=(const vtkbisImageResample&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkbisImageReslice.cpp b/bioimagesuite30_src/Common/vtkbisImageReslice.cpp
new file mode 100644
index 0000000..a447847
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisImageReslice.cpp
@@ -0,0 +1,52 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkbisImageReslice.cxx,v $
+
+  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 "vtkbisImageReslice.h"
+#include "vtkObjectFactory.h"
+
+vtkCxxRevisionMacro(vtkbisImageReslice, "$Revision: 1.74 $");
+vtkStandardNewMacro(vtkbisImageReslice);
+
+vtkbisImageReslice::vtkbisImageReslice()
+{
+  this->Optimization=0;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkbisImageReslice.h b/bioimagesuite30_src/Common/vtkbisImageReslice.h
new file mode 100644
index 0000000..7095aae
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisImageReslice.h
@@ -0,0 +1,70 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkbisImageReslice.h,v $
+
+  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 vtkbisImageReslice - Reslices a volume along a new set of axes.
+// .SECTION Description
+// This is a wrapper around vtkImageReslice
+
+
+#ifndef __vtkbisImageReslice_h
+#define __vtkbisImageReslice_h
+
+
+#include "vtkImageReslice.h"
+
+class  vtkbisImageReslice : public vtkImageReslice
+{
+public:
+  static vtkbisImageReslice *New();
+  vtkTypeRevisionMacro(vtkbisImageReslice, vtkThreadedImageAlgorithm);
+
+
+protected:
+  vtkbisImageReslice();
+
+
+private:
+  vtkbisImageReslice(const vtkbisImageReslice&);  // Not implemented.
+  void operator=(const vtkbisImageReslice&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkbisNIFTIExtension.cpp b/bioimagesuite30_src/Common/vtkbisNIFTIExtension.cpp
new file mode 100644
index 0000000..efacc92
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisNIFTIExtension.cpp
@@ -0,0 +1,143 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* =========================================================================*/
+
+#include "vtkObjectFactory.h"
+#include "vtkbisNIFTIExtension.h"
+#include "sstream"
+using namespace std;
+//------------------------------------------------------------------------------
+vtkbisNIFTIExtension* vtkbisNIFTIExtension::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisNIFTIExtension");
+  if(ret)
+    {
+      return (vtkbisNIFTIExtension*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisNIFTIExtension;
+}
+// ----------------------------------------------------
+vtkbisNIFTIExtension::vtkbisNIFTIExtension()
+{
+  this->ESize=0;
+  this->ECode=0;
+  this->Edata="Dummy Extension";
+}
+// ----------------------------------------------------
+vtkbisNIFTIExtension::~vtkbisNIFTIExtension()
+{
+}
+// ----------------------------------------------------
+void vtkbisNIFTIExtension::SetData(const char* extension,int ecode)
+{
+  this->SetXMLData(extension);
+  this->ECode=ecode;
+}
+
+void vtkbisNIFTIExtension::SetXMLData(const char* extension)
+{
+  if (extension==NULL)
+    return;
+
+  std::stringstream s;
+  s << extension;
+
+  //this->Edata=extension;
+  int inplen=strlen(extension);
+  int temp=inplen+8;
+  int newlen=int(temp/16)*16;
+  if (newlen<temp)
+    newlen+=16;
+
+  //  for (int i=inplen;i<this->ESize-8;i++)
+  //    s << ".";
+  this->Edata=s.str();
+  this->ESize=newlen;
+  //  fprintf(stderr,"Added %d (%s)\n",this->ESize,this->Edata.c_str());
+  return;
+}
+
+const char* vtkbisNIFTIExtension::GetText()
+{
+  return this->Edata.c_str();
+}
+
+
+int vtkbisNIFTIExtension::Copy(vtkbisNIFTIExtension* old)
+{
+  if (old==NULL)
+    return 0;
+  
+  const char* txt=old->GetText();
+  if (txt==NULL)
+    return 0;
+
+  this->ESize=old->GetESize();
+  this->ECode=old->GetECode();
+  this->SetXMLData(txt);
+
+  return 1;
+}
+
+
+void vtkbisNIFTIExtension::PrintAll()
+{
+  fprintf(stderr,"Extension: %s  (%d,%d) \n",this->Edata.c_str(),this->ESize,this->ECode);
+}
+
+int vtkbisNIFTIExtension::WriteExtension(znzFile fdf)
+{
+  int total=0;
+  total += znzwrite(&this->ESize,4,1,fdf)*sizeof(this->ESize);
+  total += znzwrite(&this->ECode,4,1,fdf)*sizeof(this->ECode);
+  //  fprintf(stderr,"Total Header = %d %d\n",total,sizeof(this->ESize));
+  int n=this->Edata.length();
+  total += znzwrite(this->Edata.c_str(),1,this->Edata.length(),fdf);
+  //  fprintf(stderr,"Writing edata=%d \"%s\"\n total=%d vs %d",n,this->Edata.c_str(),total,this->ESize);
+
+  char s[1];  s[0]=(char)0;
+
+  while(total<this->ESize)
+    //    {
+      total+=znzwrite(&s,1,1,fdf);
+  //fprintf(stderr,"Adding zeros total=%d vs %d\n",total,this->ESize);
+  //}
+
+  if (total!=this->ESize)
+    fprintf(stderr,"Error not enough bytes %d vs %d\n",total,this->ESize);
+
+  
+  return total;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkbisNIFTIExtension.h b/bioimagesuite30_src/Common/vtkbisNIFTIExtension.h
new file mode 100644
index 0000000..0b2c040
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisNIFTIExtension.h
@@ -0,0 +1,80 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkbisNIFTIExtension - a class for storing NIFTI Extensions -- replaces/converts the c code in nifty_io.c 
+
+#ifndef __vtkbisNIFTIExtension_h
+#define __vtkbisNIFTIExtension_h
+
+#include "vtkObject.h"
+#include "vtkCollection.h"
+#include <vtkstd/string>
+#include "bis_znzlib.h"
+
+class vtkbisNIFTIExtension : public vtkObject
+{
+public:
+  static vtkbisNIFTIExtension *New();
+  vtkTypeMacro(vtkbisNIFTIExtension,vtkObject);
+
+
+  virtual void  PrintAll();
+  virtual void  SetXMLData(const char* extension);
+  virtual void  SetData(const char* extension,int ecode);
+
+  virtual const char* GetText();
+
+  virtual int Copy(vtkbisNIFTIExtension* old);
+  
+
+  vtkGetMacro(ESize,int);
+  vtkGetMacro(ECode,int);
+
+  virtual int WriteExtension(znzFile fdf);
+
+protected:
+
+  vtkbisNIFTIExtension();
+  virtual ~vtkbisNIFTIExtension();
+  vtkbisNIFTIExtension(const vtkbisNIFTIExtension&) {};
+  void operator=(const vtkbisNIFTIExtension&) {};
+
+  int ESize;
+  int ECode;
+  //BTX
+  std::string Edata;
+  //ETX
+
+ 
+  
+};
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkbisNIFTIExtensionsList.cpp b/bioimagesuite30_src/Common/vtkbisNIFTIExtensionsList.cpp
new file mode 100644
index 0000000..0e724f1
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisNIFTIExtensionsList.cpp
@@ -0,0 +1,243 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* =========================================================================*/
+#include "vtkbisNIFTIExtensionsList.h"
+#include "vtkbisNIFTIExtension.h"
+#include "vtkObjectFactory.h"
+
+//------------------------------------------------------------------------------
+vtkbisNIFTIExtensionsList* vtkbisNIFTIExtensionsList::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisNIFTIExtensionsList");
+  if(ret)
+    {
+      return (vtkbisNIFTIExtensionsList*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisNIFTIExtensionsList;
+}
+// ----------------------------------------------------
+vtkbisNIFTIExtensionsList::vtkbisNIFTIExtensionsList()
+{
+  this->ExtensionsCollection=vtkCollection::New();
+  
+}
+// ----------------------------------------------------
+vtkbisNIFTIExtensionsList::~vtkbisNIFTIExtensionsList()
+{
+  this->ExtensionsCollection->Delete();
+}
+
+// ----------------------------------------------------
+int vtkbisNIFTIExtensionsList::ReadExtensions(znzFile fin,int remain)
+{
+  // We start with the magic number !
+  this->Cleanup();
+  if (remain<16)
+    {
+      //      fprintf(stderr,"Not Enough Room for extensions remain=%d (<20)\n",remain);
+      return 0;
+    }
+
+  char extension[4];
+  int count=znzread(&extension[0],1,4,fin);
+  if (count <4)
+    {
+      //      fprintf(stderr,"Failed to read Header\n");
+      return 0;
+    }
+
+  if (extension[0]!=1)
+    {
+      //      fprintf(stderr,"Extension Header is not 1\n");
+      return 0;
+    }
+
+
+  remain-=4;
+  //  fprintf(stderr,"Remaining =%d\n",remain);
+  int maxlength=10000;
+  //  fprintf(stderr,"On to Memory Allocation\n");
+  char* buffer=new char[maxlength];
+  //  fprintf(stderr,"Did Memory Allocation Fail\n");
+
+  while (remain>16)
+    {
+      //      fprintf(stderr,"Here we go %d\n",remain);
+      int esize,ecode;
+      znzread(&esize,4,1,fin);
+      znzread(&ecode,4,1,fin);
+      //      fprintf(stderr,"This Far %d %d\n",esize,ecode);
+      int stringlength=esize-8;
+      if (stringlength>maxlength)
+	{
+	  delete [] buffer;
+	  maxlength=stringlength;
+	  buffer=new char[maxlength];
+	}
+      memset(buffer,0,maxlength);
+      //  fprintf(stderr,"String Length=%d\n",stringlength);
+      znzread(buffer,1,stringlength,fin);
+      remain=remain-(esize);
+      //      fprintf(stderr,"Added Extension (%d,%d) remain=%d \n",esize,ecode,remain);
+      this->AddExtension(buffer,ecode);
+    }
+  //  fprintf(stderr,"Deleting Buffer\n");
+  delete [] buffer;
+  //  fprintf(stderr,"Deleting Buffer Done\n");
+  return this->GetNumberOfExtensions();
+
+}
+
+// --------------------------------------------------------------------------------
+int vtkbisNIFTIExtensionsList::WriteExtensions(znzFile fdf)
+{
+  int next=this->GetNumberOfExtensions();
+  int total=0;
+  if (next==0)
+    {
+      char exten[4]= { 0,0,0,0};
+      total += znzwrite(&exten[0],1,4,fdf);
+      //      total += compressed ? gzwrite(fdf,&exten[0],4): 
+      return total;
+    }
+
+  //  fprintf(stderr,"Writing Extensions\n");
+  char exten[4]= { 1,0,0,0};
+  //  total += compressed ? gzwrite(fdf,&exten[0],4): fwrite(&exten[0],1,4,(FILE *)fdf);
+  total += znzwrite(&exten[0],1,4,fdf);
+  //  fprintf(stderr,"Writing Extensions total=%d\n");  
+
+  for (int i=0;i<next;i++)
+    {
+      vtkbisNIFTIExtension* extn=this->GetRawExtension(i);
+      int esize=extn->GetESize();
+      if (esize>0)
+	total+=extn->WriteExtension(fdf);
+      else
+	fprintf(stderr,"Not writing extension %d\n",i);
+    }
+  return total;
+}
+
+int  vtkbisNIFTIExtensionsList::AddExtension(const char* comment,int ecode)
+{
+  if (comment==NULL)
+    return 0;
+
+  vtkbisNIFTIExtension* exn=vtkbisNIFTIExtension::New();
+  exn->SetData(comment,ecode);
+  this->ExtensionsCollection->AddItem(exn);
+  //  exn->Delete();
+
+  //  fprintf(stderr,"Num Extensions = %d\n\n\n\n",this->GetNumberOfExtensions());
+  return 1;
+}
+
+const char* vtkbisNIFTIExtensionsList::GetExtension(int index)
+{
+  vtkbisNIFTIExtension* ext=this->GetRawExtension(index);
+  if (ext==NULL)
+    return NULL;
+
+  return ext->GetText();
+}
+
+int vtkbisNIFTIExtensionsList::GetNumberOfExtensions()
+{
+  return this->ExtensionsCollection->GetNumberOfItems();
+}
+  
+int vtkbisNIFTIExtensionsList::Copy(vtkbisNIFTIExtensionsList* other)
+{
+  if (other==NULL)
+    return 0;
+
+  this->ExtensionsCollection->RemoveAllItems();
+  int num_ext=other->GetNumberOfExtensions();
+  for (int i=0;i<num_ext;i++)
+    {
+      //      fprintf(stderr,"\n ****************** Copying extension %d/%d \n",i,num_ext);
+      vtkbisNIFTIExtension* orig=other->GetRawExtension(i);
+      vtkbisNIFTIExtension* exn=vtkbisNIFTIExtension::New();
+      exn->Copy(orig);
+      //      orig->PrintAll();
+      //      exn->PrintAll();
+      this->ExtensionsCollection->AddItem(exn);
+      //      exn->Delete();
+    }
+	return num_ext;
+}
+
+// Description:
+// Reset
+int vtkbisNIFTIExtensionsList::Cleanup()
+{
+  this->ExtensionsCollection->RemoveAllItems();
+  return 1;
+}
+
+vtkbisNIFTIExtension* vtkbisNIFTIExtensionsList::GetRawExtension(int i)
+{
+  if (i>=this->GetNumberOfExtensions() || i<0)
+    return NULL;
+
+  return (vtkbisNIFTIExtension*)this->ExtensionsCollection->GetItemAsObject(i);
+
+}
+
+int vtkbisNIFTIExtensionsList::GetTotalByteSize()
+{
+  int next=this->GetNumberOfExtensions(); 
+  int total=0;
+  for (int i=0;i<next;i++)
+    {
+      vtkbisNIFTIExtension* extn=this->GetRawExtension(i);
+      total=total+extn->GetESize();
+    }
+  return total;
+}
+
+
+void vtkbisNIFTIExtensionsList::PrintAll()
+{
+  int next=this->GetNumberOfExtensions(); 
+  //  std::cerr << "Total Number of Bytes = " << this->GetTotalByteSize() << "(" << next <<" extensions)\n";
+
+  for (int i=0;i<next;i++)
+    {
+      vtkbisNIFTIExtension* extn=this->GetRawExtension(i);
+      extn->PrintAll();
+    }
+}
+
diff --git a/bioimagesuite30_src/Common/vtkbisNIFTIExtensionsList.h b/bioimagesuite30_src/Common/vtkbisNIFTIExtensionsList.h
new file mode 100644
index 0000000..94e2716
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisNIFTIExtensionsList.h
@@ -0,0 +1,106 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkbisNIFTIExtensionsList - a class for storing NIFTI Extensions -- replaces/converts the c code in nifty_io.c 
+
+#ifndef __vtkbisNIFTIExtensionsList_h
+#define __vtkbisNIFTIExtensionsList_h
+
+#include "vtkObject.h"
+#include "vtkCollection.h"
+#include "bis_znzlib.h"
+#include <stdio.h>
+
+
+class  vtkbisNIFTIExtension;
+
+class vtkbisNIFTIExtensionsList : public vtkObject
+{
+public:
+  static vtkbisNIFTIExtensionsList *New();
+  vtkTypeMacro(vtkbisNIFTIExtensionsList,vtkObject);
+
+
+  // Description:
+  // Print Self Diagnostic
+  virtual void PrintAll();
+
+  // Description:
+  // Read Header -- this is generic and will test first NIFTI1 and then Analyze
+  virtual int ReadExtensions(znzFile fin,int remain);
+
+  // Description:
+  // Save NII Header in already open stream (used for .nii, .nii.gz files)
+  virtual int WriteExtensions(znzFile fdf);
+
+  // Description:
+  // Add Comment -- 
+  virtual int AddExtension(const char* comment,int ecode);
+
+  // Description:
+  // Get Extension
+  virtual const char* GetExtension(int index);
+
+  // Description:
+  // Get Number of Extensions
+  virtual int GetNumberOfExtensions();
+  
+  // Description:
+  virtual int Copy(vtkbisNIFTIExtensionsList* other);
+
+  // Description:
+  // Reset
+  virtual int Cleanup();
+
+  // Description:
+  // GetRawExtension
+  vtkbisNIFTIExtension* GetRawExtension(int i);
+
+  // Description:
+  // Get Total Byte Size
+  int GetTotalByteSize();
+
+protected:
+
+  vtkbisNIFTIExtensionsList();
+  virtual ~vtkbisNIFTIExtensionsList();
+  vtkbisNIFTIExtensionsList(const vtkbisNIFTIExtensionsList&) {};
+  void operator=(const vtkbisNIFTIExtensionsList&) {};
+  
+  // This stores all extensions;
+  vtkCollection* ExtensionsCollection;
+
+
+  
+};
+#endif
+
+
diff --git a/bioimagesuite30_src/Common/vtkbisTestUtil.cpp b/bioimagesuite30_src/Common/vtkbisTestUtil.cpp
new file mode 100644
index 0000000..5c74c27
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisTestUtil.cpp
@@ -0,0 +1,412 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkMath.h"
+#include "vtkbisTestUtil.h"
+#include "vtkPointData.h"
+#include "vtkCellData.h"
+#include "vtkCellArray.h"
+#include "vtkPointLocator.h"
+
+vtkbisTestUtil* vtkbisTestUtil::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisTestUtil");
+  if(ret)
+      {
+	return (vtkbisTestUtil*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisTestUtil;
+}
+
+vtkbisTestUtil::vtkbisTestUtil() 
+{ 
+  this->ClearStatus();
+}
+
+const char* vtkbisTestUtil::ReturnStatus() 
+{
+  return this->Status.c_str();
+}
+
+void vtkbisTestUtil::ClearStatus()
+{
+  this->Status="";
+}
+
+// ----------------------------------------------------------------------------------------------------
+//
+//  Data Arrays
+//
+// ----------------------------------------------------------------------------------------------------
+
+int vtkbisTestUtil::CompareDataArrays(vtkDataArray* data1,vtkDataArray* data2)
+{
+  return vtkbisTestUtil::CompareDataArrays(data1,data2,0.001);
+
+}
+int vtkbisTestUtil::CompareDataArrays(vtkDataArray* data1,vtkDataArray* data2,double threshold)
+{
+
+  if (data1==NULL && data2==NULL)
+    return 1;
+
+  if (data1==NULL || data2==NULL)
+    return 0;
+
+
+  if (data1->GetDataType()!=data2->GetDataType())
+    {
+      this->Status+="**** DataArray:Warning Differences in data type";
+      //      return 0;
+    }
+
+  if (data1->GetNumberOfTuples()!=data2->GetNumberOfTuples())
+    {
+      this->Status+="**** DataArray:Error Differences in number of tuples";
+      return 0;
+    }
+
+  if (data1->GetNumberOfComponents()!=data2->GetNumberOfComponents())
+    {
+      this->Status+="**** DataArray:Error Difference in number of components";
+      return 0;
+    }
+
+  int nt=data1->GetNumberOfTuples();
+  int nc=data1->GetNumberOfComponents();
+
+  double maxd=0.0;
+  for (int ia=0;ia<nt;ia++)
+    for (int ib=0;ib<nc;ib++)
+      {
+	//	fprintf(stdout,"Point %d Comp %d %f vs %f\n",ia,ib,data1->GetComponent(ia,ib),data2->GetComponent(ia,ib));
+	double v=fabs(data1->GetComponent(ia,ib)-data2->GetComponent(ia,ib));
+	if (v>maxd)
+	  maxd=v;
+      }
+
+  if (nt>0)
+    {
+      sprintf(this->Buffer,"Comparison max=%.5f, thr=%.5f ",maxd,threshold);
+      this->Status+=this->Buffer;
+    }
+
+  if (maxd>threshold)
+    return 0;
+
+  return 1;
+}
+
+// ----------------------------------------------------------------------------------------------------
+
+int vtkbisTestUtil::CorrelateDataArrays(vtkDataArray* data1,vtkDataArray* data2)
+{
+  return vtkbisTestUtil::CorrelateDataArrays(data1,data2,0.001);
+
+}
+int vtkbisTestUtil::CorrelateDataArrays(vtkDataArray* data1,vtkDataArray* data2,double threshold)
+{
+
+  if (data1==NULL && data2==NULL)
+    return 1;
+
+  if (data1==NULL || data2==NULL)
+    return 0;
+
+
+  if (data1->GetDataType()!=data2->GetDataType())
+    {
+      this->Status+="**** CorrDataArray:Warning Differences in data type";
+    }
+
+  if (data1->GetNumberOfTuples()!=data2->GetNumberOfTuples())
+    {
+      this->Status+="**** CorrDataArray:Error Differences in number of tuples";
+      return 0;
+    }
+
+  if (data1->GetNumberOfComponents()!=data2->GetNumberOfComponents())
+    {
+      this->Status+="**** CorrDataArray:Error Differences in number of components";
+      return 0;
+    }
+
+  int nt=data1->GetNumberOfTuples();
+  int nc=data1->GetNumberOfComponents();
+
+  double mean[2],var[2],sum[2],sum2[2],sumprod=0.0;
+  sum[0]=0.0; sum[1]=0.0; sum2[0]=0.0; sum2[1]=0.0;
+  int numscalars=0;
+  for (int i=0;i<nt;i++)
+    for (int j=0;j<nc;j++)
+      {
+	double v0=data1->GetComponent(i,j);
+	sum[0]+=v0;
+	sum2[0]+=v0*v0;
+	
+	double v1=data2->GetComponent(i,j);
+	sum[1]+=v1;
+	sum2[1]+=v1*v1;
+	sumprod+=v0*v1;
+	++numscalars;
+      }
+  
+  for (int j=0;j<=1;j++)
+    {
+      mean[j]=sum[j]/double(numscalars);
+      var[j] =sum2[j]/double(numscalars)-mean[j]*mean[j];
+      if (var[j]<0.00001)
+	var[j]=0.00001;
+    }
+
+  double covar=pow(sumprod/double(numscalars)-mean[0]*mean[1],double(2.0));
+  double covar2=covar/(var[0]*var[1]);
+
+  sprintf(this->Buffer,"cc=%.5f, thr=%.5f",covar2,threshold);
+  this->Status+=this->Buffer;
+
+  if (covar2<threshold)
+    return 0;
+
+  return 1;
+}
+
+// ----------------------------------------------------------------------------------------------------
+// Images
+// ----------------------------------------------------------------------------------------------------
+int vtkbisTestUtil::CompareImages(vtkImageData* img1,vtkImageData* img2) 
+{
+  return vtkbisTestUtil::CompareImages(img1,img2,0.001);
+}
+// ----------------------------------------------------------------------------------------------------
+int vtkbisTestUtil::CorrelateImages(vtkImageData* img1,vtkImageData* img2) 
+{
+  return vtkbisTestUtil::CorrelateImages(img1,img2,0.9);
+}
+// ----------------------------------------------------------------------------------------------------
+int vtkbisTestUtil::CompareImages(vtkImageData* img1,vtkImageData* img2,double threshold)
+{
+
+  if (img1==NULL || img2==NULL)
+    return 0;
+
+  int dim1[3]; img1->GetDimensions(dim1);
+  int dim2[3]; img2->GetDimensions(dim2);
+  double spa1[3]; img1->GetSpacing(spa1);
+  double spa2[3]; img2->GetSpacing(spa2);
+
+  double sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+    {
+      sum+= double(abs(dim1[ia]-dim2[ia]));
+      sum+= fabs(spa1[ia]-spa2[ia]);
+    }
+
+  if (sum>0.01*threshold)
+    {
+      this->Status+="**** Image:Error Differences in dimensions/spacing:";
+      for (int ia=0;ia<=2;ia++)
+	{
+	  sprintf(this->Buffer,"ia=%d dim (%d vs %d) spa=(%f vs %f)\t",ia,dim1[ia],dim2[ia],spa1[ia],spa2[ia]);
+	  this->Status+=this->Buffer;
+	}
+
+      return 0;
+    }
+
+  vtkDataArray* data1=img1->GetPointData()->GetScalars();
+  vtkDataArray* data2=img2->GetPointData()->GetScalars();
+
+  return vtkbisTestUtil::CompareDataArrays(data1,data2,threshold);
+
+}
+
+
+// ----------------------------------------------------------------------------------------------------
+int vtkbisTestUtil::CorrelateImages(vtkImageData* img1,vtkImageData* img2,double threshold)
+{
+
+  if (img1==NULL || img2==NULL)
+    return 0;
+
+
+  int dim1[3]; img1->GetDimensions(dim1);
+  int dim2[3]; img2->GetDimensions(dim2);
+  double spa1[3]; img1->GetSpacing(spa1);
+  double spa2[3]; img2->GetSpacing(spa2);
+
+  double sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+    {
+      sum+= double(abs(dim1[ia]-dim2[ia]));
+      sum+= fabs(spa1[ia]-spa2[ia]);
+    }
+
+  if (sum>0.01*threshold)
+    {
+      this->Status+="**** Image:Error Differences in dimensions/spacing:";
+      for (int ia=0;ia<=2;ia++)
+	{
+	  sprintf(this->Buffer,"ia=%d dim (%d vs %d) spa=(%f vs %f)\t",ia,dim1[ia],dim2[ia],spa1[ia],spa2[ia]);
+	  this->Status+=this->Buffer;
+	}
+    }
+
+  vtkDataArray* data1=img1->GetPointData()->GetScalars();
+  vtkDataArray* data2=img2->GetPointData()->GetScalars();
+
+  return vtkbisTestUtil::CorrelateDataArrays(data1,data2,threshold);
+
+}
+
+
+// ----------------------------------------------------------------------------------------------------
+int vtkbisTestUtil::CompareSurfaces(vtkPolyData* sur1,vtkPolyData* sur2)
+{
+  return vtkbisTestUtil::CompareSurfaces(sur1,sur2,0.001);
+}
+ 
+int vtkbisTestUtil::CompareSurfaces(vtkPolyData* sur1,vtkPolyData* sur2,double threshold)
+{
+
+  if (sur1==NULL || sur2==NULL)
+    return 0;
+
+  this->Status+="Points:";
+  int ok=vtkbisTestUtil::CompareDataArrays(sur1->GetPoints()->GetData(),sur2->GetPoints()->GetData());
+  if (ok==0)    return 0;
+
+  
+  this->Status+="Verts: ";
+  ok=vtkbisTestUtil::CompareDataArrays(sur1->GetVerts()->GetData(),sur2->GetVerts()->GetData());
+  if (ok==0)    return 0;
+  
+  this->Status+="Lines: ";
+  ok=vtkbisTestUtil::CompareDataArrays(sur1->GetLines()->GetData(),sur2->GetLines()->GetData());
+  if (ok==0)    return 0;
+
+  this->Status+="Polys: ";
+  ok=vtkbisTestUtil::CompareDataArrays(sur1->GetPolys()->GetData(),sur2->GetPolys()->GetData());
+  if (ok==0)    return 0;
+
+  this->Status+="Strips: ";
+  ok=vtkbisTestUtil::CompareDataArrays(sur1->GetStrips()->GetData(),sur2->GetStrips()->GetData());
+  if (ok==0)    return 0;
+
+  // CellData and PointData
+  // GetNumberOfArrays!
+  // GetArray!
+  for (int ia=0;ia<=1;ia++)
+    {
+      vtkFieldData* f1=sur1->GetPointData();
+      vtkFieldData* f2=sur2->GetPointData();
+      if (ia==1)
+	{
+	  f1=sur1->GetFieldData();
+	  f2=sur2->GetFieldData();
+	}
+  
+      if (f1==NULL && f2==NULL)
+	{
+	  // OK no issue
+
+	}
+      else if (f1==NULL || f2==NULL)
+	{
+	  return 0;
+	}
+      else
+	{
+	  int n=f1->GetNumberOfArrays();
+	  for (int ib=0;ib<n;ib++)
+	    {
+	      ok=vtkbisTestUtil::CompareDataArrays(f1->GetArray(ib),f2->GetArray(ib));
+	      if (ok==0)
+		return 0;
+	    }
+	}
+    }
+  return ok;
+}
+// ----------------------------------------------------------------------------------------------------
+int vtkbisTestUtil::ComparePoints(vtkPoints* pt1,vtkPoints* pt2)
+{
+  return vtkbisTestUtil::ComparePoints(pt1,pt2,0.001);
+}
+ 
+int vtkbisTestUtil::ComparePoints(vtkPoints* pt1,vtkPoints* pt2,double threshold)
+{
+
+  if (pt1==NULL || pt2==NULL)
+    return 0;
+
+  return vtkbisTestUtil::CompareDataArrays(pt1->GetData(),pt2->GetData(),threshold);
+}
+
+// -----------------------------------------------------------------------------------------------------------
+int vtkbisTestUtil::CompareSurfacesByCorrespondence(vtkPolyData* surface1,vtkPolyData* surface2,double threshold)
+{
+
+
+  vtkPointLocator* locator=vtkPointLocator::New();
+  locator->SetNumberOfPointsPerBucket(1);
+  locator->SetDataSet(surface2);
+  locator->BuildLocator();
+
+  int np=surface1->GetNumberOfPoints();
+  double maxd=0.0;
+  double dthr=threshold*threshold;
+  for (int i=0;i<np;i++)
+    {
+      double x[3]; surface1->GetPoint(i,x);
+      int id=locator->FindClosestPoint(x);
+      double y[3]; surface2->GetPoint(id,y);
+      
+      double d=vtkMath::Distance2BetweenPoints(x, y);
+      if (d>maxd)
+	maxd=d;
+    }
+  locator->Delete();
+  maxd=sqrt(maxd);
+
+  sprintf(this->Buffer,"+++++ SurfaceICP Comparison max=%.5f, thr=%.5f",maxd,threshold);
+  this->Status+=this->Buffer;
+  if (maxd>threshold)
+    return 0;
+  return 1;
+
+}
+
diff --git a/bioimagesuite30_src/Common/vtkbisTestUtil.h b/bioimagesuite30_src/Common/vtkbisTestUtil.h
new file mode 100644
index 0000000..cd5df26
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkbisTestUtil.h
@@ -0,0 +1,87 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkbisTestUtil_h
+#define __vtkbisTestUtil_h
+
+#include "vtkObject.h"
+#include "vtkDataArray.h"
+#include "vtkImageData.h"
+#include "vtkPolyData.h"
+#include <string>
+
+class vtkbisTestUtil : public vtkObject
+{
+public:
+  static vtkbisTestUtil *New();
+  vtkTypeMacro(vtkbisTestUtil,vtkObject);
+  
+  // -------------------------------------------------------
+  // Compare Image and Surfaces
+  // -------------------------------------------------------
+   int CompareDataArrays(vtkDataArray* data1,vtkDataArray* data2);
+   int CompareDataArrays(vtkDataArray* data1,vtkDataArray* data2,double threshold);
+
+   int CorrelateDataArrays(vtkDataArray* data1,vtkDataArray* data2);
+   int CorrelateDataArrays(vtkDataArray* data1,vtkDataArray* data2,double threshold);
+
+
+   int CompareImages(vtkImageData* img1,vtkImageData* img2,double threshold);
+   int CompareImages(vtkImageData* img1,vtkImageData* img2);
+
+   int CorrelateImages(vtkImageData* img1,vtkImageData* img2,double threshold);
+   int CorrelateImages(vtkImageData* img1,vtkImageData* img2);
+
+   int CompareSurfaces(vtkPolyData* img1,vtkPolyData* img2,double threshold);
+   int CompareSurfaces(vtkPolyData* img1,vtkPolyData* img2);
+
+   int ComparePoints(vtkPoints* pt1,vtkPoints* pt2);
+   int ComparePoints(vtkPoints* pt1,vtkPoints* pt2,double threshold);
+
+   int CompareSurfacesByCorrespondence(vtkPolyData* img1,vtkPolyData* img2,double threshold);
+
+   const char* ReturnStatus();
+   void ClearStatus();
+
+
+protected:
+
+  //BTX
+  vtkbisTestUtil();
+
+   std::string Status;
+   char Buffer[200];
+  //ETX
+  
+};
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkjoColoredSphereSource.cpp b/bioimagesuite30_src/Common/vtkjoColoredSphereSource.cpp
new file mode 100644
index 0000000..02afb15
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkjoColoredSphereSource.cpp
@@ -0,0 +1,361 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkjoColoredSphereSource.cpp
+ *
+ *  Created on: Oct 28, 2008
+ *      Author: jonofrey
+ */
+
+#include "vtkjoColoredSphereSource.h"
+
+#include "vtkCellArray.h"
+#include "vtkDoubleArray.h"
+#include "vtkImageData.h"
+#include "vtkImageReslice.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkjoSphereSource.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataToImageStencil.h"
+#include "vtkShortArray.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include <assert.h>
+
+vtkjoColoredSphereSource* vtkjoColoredSphereSource::New()
+{
+    // First try to create the object from the vtkObjectFactory
+    vtkObject* ret = vtkObjectFactory::CreateInstance("vtkjoColoredSphereSource");
+    if (ret)
+    {
+        return (vtkjoColoredSphereSource*) ret;
+    }
+    // If the factory was unable to create the object, then create it here.
+    return new vtkjoColoredSphereSource;
+}
+
+//---------------------------------------------------------------------------
+
+vtkjoColoredSphereSource::vtkjoColoredSphereSource()
+{
+    this->SetNumberOfInputPorts(0);
+
+    this->UseNewWedges=0;
+
+    this->Radius = 32.0;
+    this->SubdivisionLevels = 0;
+
+    this->Center[0] = 32.0;
+    this->Center[1] = 32.0;
+    this->Center[2] = 32.0;
+
+    this->WholeExtent[0] = 0;  this->WholeExtent[1] = 64;
+    this->WholeExtent[2] = 0;  this->WholeExtent[3] = 64;
+    this->WholeExtent[4] = 0;  this->WholeExtent[5] = 64;
+
+    this->UseSingleFrameOff();
+    this->ColorValue = 100;
+}
+
+//---------------------------------------------------------------------------
+
+void vtkjoColoredSphereSource::PrintSelf(ostream& os, vtkIndent indent)
+{
+    this->Superclass::PrintSelf(os, indent);
+
+    os << indent << "Radius: " << this->Radius << "\n";
+    os << indent << "SubdivisionLevels: " << this->SubdivisionLevels << "\n";
+    os << indent << "ColorValue: " << this->ColorValue << "\n";
+    os << indent << "UseSingleFrame: " << this->UseSingleFrame << "\n";
+}
+
+//---------------------------------------------------------------------------
+
+void vtkjoColoredSphereSource::SetRadius(double r)
+{
+    if (r < 0.0) {
+        vtkErrorMacro("SetRadius: Input radius is negative - multiplying by -1");
+        r *= -1.0;
+    }
+
+    if (this->Radius != r)
+    {
+        this->Radius = r;
+
+        // Readjust the Center and WholeExtent
+        int rMax = int(ceil(r));
+
+        this->Center[0] = double(rMax);
+        this->Center[1] = double(rMax);
+        this->Center[2] = double(rMax);
+
+        this->WholeExtent[0] = 0;  this->WholeExtent[1] = 2*rMax;
+        this->WholeExtent[2] = 0;  this->WholeExtent[3] = 2*rMax;
+        this->WholeExtent[4] = 0;  this->WholeExtent[5] = 2*rMax;
+
+        this->Modified();
+    }
+}
+
+//---------------------------------------------------------------------------
+
+int vtkjoColoredSphereSource::RequestInformation(vtkInformation* vtkNotUsed(request),
+        vtkInformationVector** vtkNotUsed(inputVector),
+        vtkInformationVector* outputVector)
+{
+    vtkInformation* outInfo = outputVector->GetInformationObject(0);
+    outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
+            this->WholeExtent, 6);
+
+
+    if (!this->UseSingleFrame)
+    {
+        // Calculate the number of faces of the sphere surface
+        int numFaces = 20*int(pow(float(4), this->SubdivisionLevels));
+        vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_SHORT, numFaces);
+    }
+    else
+        vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_SHORT, 1);
+
+    return 1;
+}
+
+//---------------------------------------------------------------------------
+
+int vtkjoColoredSphereSource::RequestData(vtkInformation* vtkNotUsed(request),
+        vtkInformationVector** vtkNotUsed(inputVector),
+        vtkInformationVector* outputVector)
+{
+    vtkInformation *outInfo = outputVector->GetInformationObject(0);
+    vtkImageData *output = vtkImageData::SafeDownCast(
+            outInfo->Get(vtkDataObject::DATA_OBJECT()));
+    vtkImageData *data = this->AllocateOutputData(output);
+
+    if (data->GetScalarType() != VTK_SHORT)
+    {
+        vtkErrorMacro("Execute: This source only outputs shorts");
+    }
+    vtkShortArray* outData = static_cast<vtkShortArray*>(data->GetPointData()->GetScalars());
+    vtkIdType numPoints = data->GetNumberOfPoints();
+    int numComps = outData->GetNumberOfComponents();
+    // Initialize all components to zero
+    for (int i=0; i<numComps; i++)
+        outData->FillComponent(i, 0.0);
+
+    short* outData_ptr = outData->GetPointer(0);
+
+    // Create an image of all 1's to create the stencil intersection with
+    // the geometry
+    vtkImageData* onesImg=vtkImageData::New();
+    onesImg->CopyStructure(data);
+    onesImg->AllocateScalars();
+    onesImg->GetPointData()->GetScalars()->FillComponent(0,1.0);
+
+    // Create the tessellated sphere
+    vtkjoSphereSource* sphereSrc = vtkjoSphereSource::New();
+    sphereSrc->SetRadius(this->Radius);
+    sphereSrc->SetCenter(this->Center[0], this->Center[1], this->Center[2]);
+    sphereSrc->IcosahedralTessellationOn();
+    sphereSrc->SetSubdivisionLevels(this->SubdivisionLevels);
+    sphereSrc->Update();
+    vtkPolyData* sphere = sphereSrc->GetOutput();
+
+    // Get each face of the surface
+    vtkIdType numFaces = sphere->GetNumberOfCells();
+    vtkCellArray* faces = sphere->GetPolys();
+    faces->InitTraversal();
+
+    // Get the surface points
+    vtkPoints* points = sphere->GetPoints();
+
+    vtkPolyDataToImageStencil* stencil = vtkPolyDataToImageStencil::New();
+    stencil->SetInformationInput(onesImg);
+
+    vtkImageReslice* reslice = vtkImageReslice::New();
+    reslice->SetInput(onesImg);
+
+    vtkIdType nPts;
+    vtkIdType* pts = new vtkIdType[3];
+    double p0[3], p1[3], p2[3];
+    double q0[3], q1[3], q2[3];
+    double opp0[3], opp1[3], opp2[3];
+    for (int i=0; i<numFaces; i++)
+    {
+        faces->GetNextCell(nPts, pts);
+
+        points->GetPoint(pts[0], p0);
+        points->GetPoint(pts[1], p1);
+        points->GetPoint(pts[2], p2);
+	
+	if (this->UseNewWedges){
+	  double centersum=this->Center[0]+this->Center[1]+this->Center[2];
+	  double centroid[3];
+	  for (int x=0; x<3; x++){
+	    //reflect p_i through this->Center
+	    opp0[x]=2*this->Center[x]-p0[x];
+	    opp1[x]=2*this->Center[x]-p1[x];
+	    opp2[x]=2*this->Center[x]-p2[x];
+	    //reflect opp_i through centroid of triangle T=(opp_0, opp_1, opp_2) [equivalent to rotation by 180]
+	    centroid[x]=(opp0[x]+opp1[x]+opp2[x])/3.0;
+	    q0[x]=2*centroid[x]-opp0[x];
+	    q1[x]=2*centroid[x]-opp1[x];
+	    q2[x]=2*centroid[x]-opp2[x];
+	    //	    q0[x]=(2*(2*centersum-this->Center[0])-(2*(p0[x]+p1[x]+p2[x])-p0[x]))/3.0;
+	    //	    q1[x]=(2*(2*centersum-this->Center[1])-(2*(p0[x]+p1[x]+p2[x])-p1[x]))/3.0;
+	    //	    q2[x]=(2*(2*centersum-this->Center[2])-(2*(p0[x]+p1[x]+p2[x])-p2[x]))/3.0;
+	  }
+	  //	  fprintf(stderr, "center: {[%.1f, %.1f, %.1f]}\np: {[%.1f, %.1f, %.1f]; [%.1f, %.1f, %.1f]; [%.1f, %.1f, %.1f]}\nopp: {[%.1f, %.1f, %.1f]; [%.1f, %.1f, %.1f]; [%.1f, %.1f, %.1f]}\ncentroid: {[%.1f, %.1f, %.1f]}\nq: {[%.1f, %.1f, %.1f]; [%.1f, %.1f, %.1f]; [%.1f, %.1f, %.1f]}\n", this->Center[0], this->Center[1], this->Center[2], p0[0], p0[1], p0[2], p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], opp0[0], opp0[1], opp0[2], opp1[0], opp1[1], opp1[2], opp2[0], opp2[1], opp2[2], centroid[0 [...]
+	}
+
+        // Setup the wedge points
+        vtkPoints* wedgePts = vtkPoints::New();
+
+	if (this->UseNewWedges){
+	  wedgePts->Allocate(6, 0);
+	  wedgePts->InsertPoint(0, p0);
+	  wedgePts->InsertPoint(1, p1);
+	  wedgePts->InsertPoint(2, p2);
+	  wedgePts->InsertPoint(3, q0);
+	  wedgePts->InsertPoint(4, q1);
+	  wedgePts->InsertPoint(5, q2);
+	}
+	else {
+	  wedgePts->Allocate(4, 0);
+	  wedgePts->InsertPoint(0, p0);
+	  wedgePts->InsertPoint(1, p1);
+	  wedgePts->InsertPoint(2, p2);
+	  wedgePts->InsertPoint(3, this->Center);
+	}
+
+	// Setup the wedge cells
+        vtkCellArray* wedgePolys = vtkCellArray::New();
+
+	if (this->UseNewWedges){
+	  wedgePolys->Allocate(wedgePolys->EstimateSize(5, 4));
+	  vtkIdType* rects=new vtkIdType[4];
+	  rects[0]=0;
+	  rects[1]=1;
+	  rects[2]=4;
+	  rects[3]=3;
+	  wedgePolys->InsertNextCell(4, rects);
+	  rects[0]=0;
+	  rects[1]=2;
+	  rects[2]=5;
+	  rects[3]=3;
+	  wedgePolys->InsertNextCell(4, rects);
+	  rects[0]=1;
+	  rects[1]=2;
+	  rects[2]=5;
+	  rects[3]=4;
+	  wedgePolys->InsertNextCell(4, rects);
+	  vtkIdType* triangles=new vtkIdType[3];
+	  triangles[0]=0;
+	  triangles[1]=1;
+	  triangles[2]=2;
+	  wedgePolys->InsertNextCell(3, triangles);
+	  triangles[0]=3;
+	  triangles[1]=4;
+	  triangles[2]=5;
+	  wedgePolys->InsertNextCell(3, triangles);
+	  wedgePolys->Squeeze();
+	  delete[] rects;
+	  delete[] triangles;
+	}
+	else {
+	  wedgePolys->Allocate(wedgePolys->EstimateSize(4, 3));
+	  vtkIdType* ids = new vtkIdType[3];
+	  ids[0] = 0;
+	  ids[1] = 1;
+	  ids[2] = 2;
+	  wedgePolys->InsertNextCell(nPts, ids);
+	  ids[0] = 3;
+	  ids[1] = 1;
+	  ids[2] = 0;
+	  wedgePolys->InsertNextCell(nPts, ids);
+	  ids[0] = 3;
+	  ids[1] = 0;
+	  ids[2] = 2;
+	  wedgePolys->InsertNextCell(nPts, ids);
+	  ids[0] = 3;
+	  ids[1] = 2;
+	  ids[2] = 1;
+	  wedgePolys->InsertNextCell(nPts, ids);
+	  delete[] ids;
+	}
+
+        // Create the wedge PolyData out of the points and cells
+        vtkPolyData* wedge = vtkPolyData::New();
+        wedge->SetPoints(wedgePts);
+        wedge->SetPolys(wedgePolys);
+        wedgePts->Delete();
+        wedgePolys->Delete();
+
+        // Create a stencil from the wedge PolyData and then reslice to
+        // get the wedge as image data
+        stencil->SetInput(wedge);
+        stencil->Update();
+
+        reslice->SetStencil(stencil->GetOutput());
+        reslice->SetBackgroundColor(0.0, 0.0, 0.0, 1.0);
+        reslice->Update();
+
+        vtkImageData* wedgeImg = reslice->GetOutput();
+        vtkDoubleArray* wedgeData = (vtkDoubleArray*) wedgeImg->GetPointData()->GetScalars();
+        double* wedgeData_ptr = wedgeData->GetPointer(0);
+
+        // Color the output according the wedge image
+        if (!this->UseSingleFrame)
+        {
+            for (int j=0; j<numPoints; j++)
+            {
+                if (wedgeData_ptr[j] > 0)
+                    outData_ptr[i+j*numComps] = ColorValue;
+            }
+
+        }
+        else
+        {
+            int color = i+1;
+            for (int j=0; j<numPoints; j++)
+            {
+                if (wedgeData_ptr[j] > 0 && !(outData_ptr[j] > 0))
+                    outData_ptr[j] = color;
+            }
+        }
+    }
+
+    stencil->Delete();
+    reslice->Delete();
+    onesImg->Delete();
+    sphereSrc->Delete();
+
+    return 1;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkjoColoredSphereSource.h b/bioimagesuite30_src/Common/vtkjoColoredSphereSource.h
new file mode 100644
index 0000000..b3c2b86
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkjoColoredSphereSource.h
@@ -0,0 +1,113 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkjoColoredSphereSource.h
+ *
+ *  Created on: Oct 28, 2008
+ *      Author: jonofrey
+ */
+// .NAME vtkjoColoredSphereSource - Create an image of a sphere with
+// colored faces.
+// .SECTION Description
+// vtkjoColoredSphereSource produces an image of a sphere with individually
+// integer colored faces.  These colored faces extend to the sphere's center creating
+// colored triangular wedges.  The sphere is tessellated as an icosahedron,
+// with the SubdivisionLevels variable controlling the number of times the
+// faces of the icosahedron are subdivided into smaller triangles.
+
+#ifndef VTKJOCOLOREDSPHERESOURCE_H_
+#define VTKJOCOLOREDSPHERESOURCE_H_
+
+#include "vtkImageAlgorithm.h"
+
+class vtkjoColoredSphereSource : public vtkImageAlgorithm
+{
+public:
+    static vtkjoColoredSphereSource *New();
+    vtkTypeMacro(vtkjoColoredSphereSource, vtkImageAlgorithm);
+
+    void PrintSelf(ostream& os, vtkIndent indent);
+
+    vtkSetMacro(UseNewWedges, int);
+    vtkGetMacro(UseNewWedges, int);
+
+    // Description:
+    // Set the color value within each wedge volume.  Note, this value
+    // will only be used if the UseSingleFrame parameter is turned off.
+    // Default is 100.
+    vtkSetMacro(ColorValue, short);
+    vtkGetMacro(ColorValue, short);
+
+    // Description:
+    // Set radius of the sphere.  Default is 32.0.
+    void SetRadius(double r);
+    vtkGetMacro(Radius, double);
+
+    // Description:
+    // Set the number of subdivisions to perform on the icosahedron when creating
+    // the sphere.  0 subdivions will return the initial icosahedron.
+    vtkSetClampMacro(SubdivisionLevels, int, 0, 1);
+    vtkGetMacro(SubdivisionLevels, int);
+
+    // Description:
+    // Set/Get the center of the sphere.
+    vtkSetVector3Macro(Center, double);
+    vtkGetVector3Macro(Center, double);
+
+    // Description:
+    // If on, create the output using a single vtkImageData component.  This coloring
+    // results in wedges being colored 1,2,3,...,N, where N is the number of wedges
+    // (or faces), in a single image structure.  Note, wegde volumes may not overlap
+    // so the volumes may vary with using this scheme.  Alternatively, if off, create the
+    // output using N components, where N is the number of wedges (or faces).  This
+    // way, each wedge is its own component and wedge volumes are more uniform.  The
+    // wedge color is then the same value for each wedge (see [Get/Set]ColorValue).
+    // Default is Off.
+    vtkSetClampMacro(UseSingleFrame, int, 0, 1);
+    vtkGetMacro(UseSingleFrame, int);
+    vtkBooleanMacro(UseSingleFrame, int);
+
+protected:
+    vtkjoColoredSphereSource();
+    ~vtkjoColoredSphereSource() {};
+
+    int UseNewWedges;
+    short ColorValue;
+    double Radius;
+    int SubdivisionLevels;
+    int WholeExtent[6];
+    double Center[3];
+    int UseSingleFrame;
+
+    virtual int RequestInformation(vtkInformation*, vtkInformationVector**, vtkInformationVector*);
+    virtual int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*);
+
+};
+
+#endif /* VTKJOCOLOREDSPHERE_H_ */
+
diff --git a/bioimagesuite30_src/Common/vtkjoROCFilter.cpp b/bioimagesuite30_src/Common/vtkjoROCFilter.cpp
new file mode 100644
index 0000000..2b9df67
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkjoROCFilter.cpp
@@ -0,0 +1,212 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkjoROCFilter.cpp
+ *
+ *  Created on: Dec 1, 2008
+ *      Author: jonofrey
+ */
+
+#include "vtkjoROCFilter.h"
+
+#include "vtkDataObject.h"
+#include "vtkImageData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkShortArray.h"
+
+vtkjoROCFilter* vtkjoROCFilter::New()
+{
+    // First try to create the object from the vtkObjectFactory
+    vtkObject* ret = vtkObjectFactory::CreateInstance("vtkjoROCFilter");
+    if (ret)
+    {
+        return (vtkjoROCFilter*) ret;
+    }
+    // If the factory was unable to create the object, then create it here.
+    return new vtkjoROCFilter;
+}
+
+//---------------------------------------------------------------------
+
+vtkjoROCFilter::vtkjoROCFilter()
+{
+    this->TP = 0;
+    this->FP = 0;
+    this->TN = 0;
+    this->FN = 0;
+
+    this->TrueResult = NULL;
+}
+
+//---------------------------------------------------------------------
+
+void vtkjoROCFilter::PrintSelf(ostream& os, vtkIndent indent)
+{
+    this->Superclass::PrintSelf(os, indent);
+
+    os << indent << "TP: " << this->TP << "\n";
+    os << indent << "TN: " << this->TN << "\n";
+    os << indent << "FP: " << this->FP << "\n";
+    os << indent << "FN: " << this->FN << "\n";
+}
+
+//---------------------------------------------------------------------
+
+double vtkjoROCFilter::GetTruePositiveRate()
+{
+    return double(this->TP)/double(this->TP + this->FN);
+}
+
+//---------------------------------------------------------------------
+
+double vtkjoROCFilter::GetFalsePositiveRate()
+{
+    return double(this->FP)/double(this->FP + this->TN);
+}
+
+//---------------------------------------------------------------------
+
+double vtkjoROCFilter::GetAccuracy()
+{
+    return double(this->TP + this->TN)/
+        double(this->TP + this->FP + this->TN + this->FN);
+}
+
+//---------------------------------------------------------------------
+
+double vtkjoROCFilter::GetSpecificity()
+{
+    return double(this->TN)/double(this->FP + this->TN);
+}
+
+//---------------------------------------------------------------------
+
+double vtkjoROCFilter::GetPositivePredictiveValue()
+{
+    return double(this->TP)/double(this->TP + this->FP);
+}
+
+//---------------------------------------------------------------------
+
+double vtkjoROCFilter::GetNegativePredictiveValue()
+{
+    return double(this->TN)/double(this->TN + this->FN);
+}
+
+//---------------------------------------------------------------------
+
+double vtkjoROCFilter::GetFalseDiscoveryRate()
+{
+    return double(this->FP)/double(this->FP + this->TP);
+}
+
+//---------------------------------------------------------------------
+
+int vtkjoROCFilter::RequestInformation(vtkInformation* vtkNotUsed(request),
+        vtkInformationVector** vtkNotUsed(inputVector),
+        vtkInformationVector* outputVector)
+{
+    vtkInformation* outInfo = outputVector->GetInformationObject(0);
+    vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_SHORT, 4);
+    return 1;
+}
+
+//---------------------------------------------------------------------
+
+void vtkjoROCFilter::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+    if (this->TrueResult == NULL)
+    {
+        vtkErrorMacro("TrueResult is not set. Filter cannot run.");
+        return;
+    }
+
+    if (output->GetScalarType() != VTK_SHORT)
+    {
+        vtkErrorMacro("Execute: This filter only outputs shorts");
+        return;
+    }
+
+    // Get the predicted data
+    vtkDataArray* inData = input->GetPointData()->GetScalars();
+    // Get the actual, truth data
+    vtkDataArray* trueData = this->TrueResult->GetPointData()->GetScalars();
+
+    vtkShortArray* outData = static_cast<vtkShortArray*>(output->GetPointData()->GetScalars());
+    int numComps = outData->GetNumberOfComponents();
+    for (int i=0; i<numComps; i++)
+        outData->FillComponent(i, 0.0);
+
+    short* outData_ptr = outData->GetPointer(0);
+
+    vtkIdType numPts = input->GetNumberOfPoints();
+    for (int i=0; i<numPts; i++)
+    {
+        double inValue = inData->GetComponent(i, 0);
+        double trueValue = trueData->GetComponent(i, 0);
+
+        if (inValue > 0.0)
+        {
+            // Find the True Positives
+            if (trueValue > 0.0)
+            {
+                this->TP++;
+                outData->SetComponent(i, 0, 1.0);
+            }
+            // Find the False Positives
+            else
+            {
+                this->FP++;
+                outData->SetComponent(i, 1, 1.0);
+            }
+        }
+        else
+        {
+            // Find the False Negatives
+            if (trueValue > 0.0)
+            {
+                this->FN++;
+                outData->SetComponent(i, 2, 1.0);
+            }
+            // Find the True Negative
+            else
+            {
+                this->TN++;
+                outData->SetComponent(i, 3, 1.0);
+            }
+        }
+
+    }
+
+//    PrintSelf(cout, vtkIndent());
+}
+
+
diff --git a/bioimagesuite30_src/Common/vtkjoROCFilter.h b/bioimagesuite30_src/Common/vtkjoROCFilter.h
new file mode 100644
index 0000000..a9b3fb1
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkjoROCFilter.h
@@ -0,0 +1,111 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkjoROCFilter.h
+ *
+ *  Created on: Dec 1, 2008
+ *      Author: jonofrey
+ */
+
+#ifndef VTKJOROCFILTER_H_
+#define VTKJOROCFILTER_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+
+class vtkjoROCFilter : public vtkSimpleImageToImageFilter
+{
+public:
+    static vtkjoROCFilter *New();
+    vtkTypeMacro(vtkjoROCFilter, vtkSimpleImageToImageFilter);
+
+    void PrintSelf(ostream& os, vtkIndent indent);
+
+    // Description:
+    // Set the true result to compare the input against.
+    void SetTrueResult(vtkImageData* truth) { this->TrueResult = truth; };
+    vtkImageData* GetTrueResult() { return this->TrueResult; };
+
+    // Description:
+    // Get the number of True Positives.
+    vtkGetMacro(TP, int);
+    // Description:
+    // Get the number of False Positives.
+    vtkGetMacro(FP, int);
+    // Description:
+    // Get the number of True Negatives.
+    vtkGetMacro(TN, int);
+    // Description:
+    // Get the number of False Negatives.
+    vtkGetMacro(FN, int);
+
+    // Description:
+    // Get the True Positive Rate (Sensitivity) = TP/(TP + FN).
+    double GetTruePositiveRate();
+
+    // Description:
+    // Get the False Positive Rate = FP/(FP + TN).
+    double GetFalsePositiveRate();
+
+    // Description:
+    // Get the Accuracy = (TP + TN)/(P + N).
+    double GetAccuracy();
+
+    // Description:
+    // Get the Specificity = TN/(FP + TN) = 1-FPR.
+    double GetSpecificity();
+
+    // Description:
+    // Get the Positive Predictive Value (Precision) = TP/(TP + FP).
+    double GetPositivePredictiveValue();
+
+    // Description:
+    // Get the Negative Predictive Value = TN/(TN + FN).
+    double GetNegativePredictiveValue();
+
+    // Description:
+    // Get the False Discovery Rate = FP/(FP + TP).
+    double GetFalseDiscoveryRate();
+
+protected:
+    vtkjoROCFilter();
+    ~vtkjoROCFilter() {};
+
+    vtkImageData* TrueResult;
+
+    int TP;
+    int TN;
+    int FP;
+    int FN;
+
+    virtual int RequestInformation(vtkInformation*, vtkInformationVector**, vtkInformationVector*);
+//    virtual void SimpleExecute(vtkInformation*, vtkInformationVector**, vtkInformationVector*);
+    virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+};
+
+#endif /* VTKJOROCFILTER_H_ */
+
diff --git a/bioimagesuite30_src/Common/vtkjoSphereSource.cxx b/bioimagesuite30_src/Common/vtkjoSphereSource.cxx
new file mode 100644
index 0000000..3cb72bf
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkjoSphereSource.cxx
@@ -0,0 +1,566 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkjoSphereSource.cxx,v $
+
+  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 "vtkjoSphereSource.h"
+
+#include "vtkCellArray.h"
+#include "vtkEdgeTable.h"
+#include "vtkFloatArray.h"
+#include "vtkDoubleArray.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPlatonicSolidSource.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+#include <math.h>
+
+vtkCxxRevisionMacro(vtkjoSphereSource, "$Revision: 1.70 $");
+vtkStandardNewMacro(vtkjoSphereSource);
+
+//----------------------------------------------------------------------------
+// Construct sphere with radius=0.5 and default resolution 8 in both Phi
+// and Theta directions. Theta ranges from (0,360) and phi (0,180) degrees.
+vtkjoSphereSource::vtkjoSphereSource(int res)
+{
+  res = res < 4 ? 4 : res;
+  this->Radius = 0.5;
+  this->Center[0] = 0.0;
+  this->Center[1] = 0.0;
+  this->Center[2] = 0.0;
+
+  this->ThetaResolution = res;
+  this->PhiResolution = res;
+  this->StartTheta = 0.0;
+  this->EndTheta = 360.0;
+  this->StartPhi = 0.0;
+  this->EndPhi = 180.0;
+  this->LatLongTessellation = 0;
+  this->IcosahedralTessellation = 0;
+  this->SubdivisionLevels = 3;
+
+  this->SetNumberOfInputPorts(0);
+}
+
+//----------------------------------------------------------------------------
+int vtkjoSphereSource::RequestData(
+  vtkInformation *vtkNotUsed(request),
+  vtkInformationVector **vtkNotUsed(inputVector),
+  vtkInformationVector *outputVector)
+{
+  if (this->IcosahedralTessellation < 1) {
+	  return PerformLatLongTessellation(outputVector);
+  } else {
+	  return PerformIcosahedralTessellation(outputVector);
+  }
+}
+
+//----------------------------------------------------------------------------
+int vtkjoSphereSource::PerformLatLongTessellation(vtkInformationVector *outputVector)
+{
+	  // get the info object
+	  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+	  // get the output
+	  vtkPolyData *output = vtkPolyData::SafeDownCast(
+	    outInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+	  int i, j;
+	  int jStart, jEnd, numOffset;
+	  int numPts, numPolys;
+	  vtkPoints *newPoints;
+	  vtkFloatArray *newNormals;
+	  vtkCellArray *newPolys;
+	  double x[3], n[3], deltaPhi, deltaTheta, phi, theta, radius, norm;
+	  double startTheta, endTheta, startPhi, endPhi;
+	  int base, numPoles=0, thetaResolution, phiResolution;
+	  vtkIdType pts[4];
+	  int piece =
+	    outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
+	  int numPieces =
+	    outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
+
+	  if (numPieces > this->ThetaResolution)
+	    {
+	    numPieces = this->ThetaResolution;
+	    }
+	  if (piece >= numPieces)
+	    {
+	    // Although the super class should take care of this,
+	    // it cannot hurt to check here.
+	    return 1;
+	    }
+
+	  // I want to modify the ivars resoultion start theta and end theta,
+	  // so I will make local copies of them.  THese might be able to be merged
+	  // with the other copies of them, ...
+	  int localThetaResolution = this->ThetaResolution;
+	  double localStartTheta = this->StartTheta;
+	  double localEndTheta = this->EndTheta;
+
+	  while (localEndTheta < localStartTheta)
+	    {
+	    localEndTheta += 360.0;
+	    }
+	  deltaTheta = (localEndTheta - localStartTheta) / localThetaResolution;
+
+	  // Change the ivars based on pieces.
+	  int start, end;
+	  start = piece * localThetaResolution / numPieces;
+	  end = (piece+1) * localThetaResolution / numPieces;
+	  localEndTheta = localStartTheta + (double)(end) * deltaTheta;
+	  localStartTheta = localStartTheta + (double)(start) * deltaTheta;
+	  localThetaResolution = end - start;
+
+	  // Set things up; allocate memory
+	  //
+	  vtkDebugMacro("SphereSource Executing piece index " << piece
+	                << " of " << numPieces << " pieces.");
+
+	  numPts = this->PhiResolution * localThetaResolution + 2;
+	  // creating triangles
+	  numPolys = this->PhiResolution * 2 * localThetaResolution;
+
+	  newPoints = vtkPoints::New();
+	  newPoints->Allocate(numPts);
+	  newNormals = vtkFloatArray::New();
+	  newNormals->SetNumberOfComponents(3);
+	  newNormals->Allocate(3*numPts);
+	  newNormals->SetName("Normals");
+
+	  newPolys = vtkCellArray::New();
+	  newPolys->Allocate(newPolys->EstimateSize(numPolys, 3));
+
+	  // Create sphere
+	  //
+	  // Create north pole if needed
+	  if ( this->StartPhi <= 0.0 )
+	    {
+	    x[0] = this->Center[0];
+	    x[1] = this->Center[1];
+	    x[2] = this->Center[2] + this->Radius;
+	    newPoints->InsertPoint(numPoles,x);
+
+	    x[0] = x[1] = 0.0; x[2] = 1.0;
+	    newNormals->InsertTuple(numPoles,x);
+	    numPoles++;
+	    }
+
+	  // Create south pole if needed
+	  if ( this->EndPhi >= 180.0 )
+	    {
+	    x[0] = this->Center[0];
+	    x[1] = this->Center[1];
+	    x[2] = this->Center[2] - this->Radius;
+	    newPoints->InsertPoint(numPoles,x);
+
+	    x[0] = x[1] = 0.0; x[2] = -1.0;
+	    newNormals->InsertTuple(numPoles,x);
+	    numPoles++;
+	    }
+
+	  // Check data, determine increments, and convert to radians
+	  startTheta = (localStartTheta < localEndTheta ? localStartTheta : localEndTheta);
+	  startTheta *= vtkMath::Pi() / 180.0;
+	  endTheta = (localEndTheta > localStartTheta ? localEndTheta : localStartTheta);
+	  endTheta *= vtkMath::Pi() / 180.0;
+
+	  startPhi = (this->StartPhi < this->EndPhi ? this->StartPhi : this->EndPhi);
+	  startPhi *= vtkMath::Pi() / 180.0;
+	  endPhi = (this->EndPhi > this->StartPhi ? this->EndPhi : this->StartPhi);
+	  endPhi *= vtkMath::Pi() / 180.0;
+
+	  phiResolution = this->PhiResolution - numPoles;
+	  deltaPhi = (endPhi - startPhi) / (this->PhiResolution - 1);
+	  thetaResolution = localThetaResolution;
+	  if (fabs(localStartTheta - localEndTheta) < 360.0)
+	    {
+	    ++localThetaResolution;
+	    }
+	  deltaTheta = (endTheta - startTheta) / thetaResolution;
+
+	  jStart = (this->StartPhi <= 0.0 ? 1 : 0);
+	  jEnd = (this->EndPhi >= 180.0 ? this->PhiResolution - 1
+	        : this->PhiResolution);
+
+	  this->UpdateProgress(0.1);
+
+	  // Create intermediate points
+	  for (i=0; i < localThetaResolution; i++)
+	    {
+	    theta = localStartTheta * vtkMath::Pi() / 180.0 + i*deltaTheta;
+
+	    for (j=jStart; j<jEnd; j++)
+	      {
+	      phi = startPhi + j*deltaPhi;
+	      radius = this->Radius * sin((double)phi);
+	      n[0] = radius * cos((double)theta);
+	      n[1] = radius * sin((double)theta);
+	      n[2] = this->Radius * cos((double)phi);
+	      x[0] = n[0] + this->Center[0];
+	      x[1] = n[1] + this->Center[1];
+	      x[2] = n[2] + this->Center[2];
+	      newPoints->InsertNextPoint(x);
+
+	      if ( (norm = vtkMath::Norm(n)) == 0.0 )
+	        {
+	        norm = 1.0;
+	        }
+	      n[0] /= norm; n[1] /= norm; n[2] /= norm;
+	      newNormals->InsertNextTuple(n);
+	      }
+	    this->UpdateProgress (0.10 + 0.50*i/static_cast<float>(localThetaResolution));
+	    }
+
+	  // Generate mesh connectivity
+	  base = phiResolution * localThetaResolution;
+
+	  if (fabs(localStartTheta - localEndTheta) < 360.0)
+	    {
+	    --localThetaResolution;
+	    }
+
+	  if ( this->StartPhi <= 0.0 )  // around north pole
+	    {
+	    for (i=0; i < localThetaResolution; i++)
+	      {
+	      pts[0] = phiResolution*i + numPoles;
+	      pts[1] = (phiResolution*(i+1) % base) + numPoles;
+	      pts[2] = 0;
+	      newPolys->InsertNextCell(3, pts);
+	      }
+	    }
+
+	  if ( this->EndPhi >= 180.0 ) // around south pole
+	    {
+	    numOffset = phiResolution - 1 + numPoles;
+
+	    for (i=0; i < localThetaResolution; i++)
+	      {
+	      pts[0] = phiResolution*i + numOffset;
+	      pts[2] = ((phiResolution*(i+1)) % base) + numOffset;
+	      pts[1] = numPoles - 1;
+	      newPolys->InsertNextCell(3, pts);
+	      }
+	    }
+	  this->UpdateProgress (0.70);
+
+	  // bands in-between poles
+	  for (i=0; i < localThetaResolution; i++)
+	    {
+	    for (j=0; j < (phiResolution-1); j++)
+	      {
+	      pts[0] = phiResolution*i + j + numPoles;
+	      pts[1] = pts[0] + 1;
+	      pts[2] = ((phiResolution*(i+1)+j) % base) + numPoles + 1;
+	      if ( !this->LatLongTessellation )
+	        {
+	        newPolys->InsertNextCell(3, pts);
+	        pts[1] = pts[2];
+	        pts[2] = pts[1] - 1;
+	        newPolys->InsertNextCell(3, pts);
+	        }
+	      else
+	        {
+	        pts[3] = pts[2] - 1;
+	        newPolys->InsertNextCell(4, pts);
+	        }
+	      }
+	    this->UpdateProgress (0.70 + 0.30*i/static_cast<double>(localThetaResolution));
+	    }
+
+	  // Update ourselves and release memeory
+	  //
+	  newPoints->Squeeze();
+	  output->SetPoints(newPoints);
+	  newPoints->Delete();
+
+	  newNormals->Squeeze();
+	  output->GetPointData()->SetNormals(newNormals);
+	  newNormals->Delete();
+
+	  newPolys->Squeeze();
+	  output->SetPolys(newPolys);
+	  newPolys->Delete();
+
+	return 1;
+}
+
+
+
+//----------------------------------------------------------------------------
+int vtkjoSphereSource::PerformIcosahedralTessellation(vtkInformationVector *outputVector)
+{
+	// get the info object
+	vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+	// get the output
+	vtkPolyData *output = vtkPolyData::SafeDownCast(
+			outInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+	vtkDebugMacro(<<"Creating the initial icosahedron");
+
+	vtkPlatonicSolidSource* icosaSrc = vtkPlatonicSolidSource::New();
+	icosaSrc->SetSolidTypeToIcosahedron();
+	icosaSrc->Update();
+
+	vtkPolyData* original = vtkPolyData::New();
+	original->ShallowCopy(icosaSrc->GetOutput());
+	icosaSrc->Delete();
+
+	vtkPoints* points = original->GetPoints();
+	vtkIdType numPts = points->GetNumberOfPoints();
+	vtkIdType numEdges = 30;	// Known for an icosahedron
+
+	vtkIdType numCells = original->GetNumberOfCells();
+	vtkCellArray* polys = original->GetPolys();
+
+	this->UpdateProgress(0.1);
+
+	for (int level=0; level<this->SubdivisionLevels; level++) {
+		vtkDebugMacro(<<"numPoints="<<numPts<<" numCells="<<numCells<<" numEdges="<<numEdges);
+
+		// The number of points in the new sphere will be numPts + numEdges
+		vtkPoints* newPoints = vtkPoints::New();
+		newPoints->Allocate(numPts + numEdges, 0);
+		newPoints->ShallowCopy(points);
+
+		// Create a table to maintain a list of all edges in the surface
+		vtkEdgeTable* edgeTable = vtkEdgeTable::New();
+        edgeTable->InitEdgeInsertion(numPts, 1);
+
+        vtkIdType nPts;
+		vtkIdType* pts = new vtkIdType[3];
+
+		vtkIdType edgeId;
+		double mid[3];
+		double p1[3], p2[3];
+		vtkIdType nextIdx;
+		double norm;
+
+		// Traverse the cells and record edges while inserting midpoints
+		// into the midpoint array if the edge does not exist in the edge
+		// table
+		polys->InitTraversal();
+		for (int i=0; i<numCells; i++) {
+			polys->GetNextCell(nPts, pts);
+			for (int idx=0; idx<nPts; idx++) {
+				nextIdx = (idx+1)%nPts;
+				vtkIdType id = edgeTable->IsEdge(pts[idx], pts[nextIdx]);
+				if (id == -1) {
+					points->GetPoint(pts[idx], p1);
+					points->GetPoint(pts[nextIdx], p2);
+					mid[0] = (p1[0] + p2[0])/2.0;
+					mid[1] = (p1[1] + p2[1])/2.0;
+					mid[2] = (p1[2] + p2[2])/2.0;
+
+					// Normalize the this midpoint vector to the unit sphere
+					// by dividing by the norm
+					if ((norm = vtkMath::Norm(mid)) == 0) {
+						norm = 1.0;
+					}
+					mid[0] /= norm;
+					mid[1] /= norm;
+					mid[2] /= norm;
+
+					edgeId = newPoints->InsertNextPoint(mid);
+
+					// The edge is not in the table, so insert it!
+					edgeTable->InsertEdge(pts[idx], pts[nextIdx], edgeId);
+				}
+			}
+		}
+
+		// Now, create the new cells using the new points
+
+		// Create a new cell array to store polygon information.
+		// The new surface will subdivide each cell into 4 new cells, with
+		// each cell being defined by 3 points.
+		vtkCellArray* newPolys = vtkCellArray::New();
+		newPolys->Allocate(newPolys->EstimateSize(4*numCells, 3));
+
+		vtkIdType edgeIdA;
+		vtkIdType edgeIdB;
+		vtkIdType edgeIdC;
+		vtkIdType* ids = new vtkIdType[3];
+
+		polys->InitTraversal();
+		for (int i=0; i<numCells; i++) {
+			polys->GetNextCell(nPts, pts);
+			// Assume pts contains 3 ids
+			edgeIdA = edgeTable->IsEdge(pts[0], pts[1]);
+			edgeIdB = edgeTable->IsEdge(pts[1], pts[2]);
+			edgeIdC = edgeTable->IsEdge(pts[2], pts[0]);
+
+			ids[0] = pts[0];
+			ids[1] = edgeIdA;
+			ids[2] = edgeIdC;
+			newPolys->InsertNextCell(nPts, ids);
+			ids[0] = edgeIdA;
+			ids[1] = pts[1];
+			ids[2] = edgeIdB;
+			newPolys->InsertNextCell(nPts, ids);
+			ids[0] = edgeIdC;
+			ids[1] = edgeIdB;
+			ids[2] = pts[2];
+			newPolys->InsertNextCell(nPts, ids);
+			ids[0] = edgeIdA;
+			ids[1] = edgeIdB;
+			ids[2] = edgeIdC;
+			newPolys->InsertNextCell(nPts, ids);
+		}
+
+		// Update the point, cell, and edge counts
+		numPts = points->GetNumberOfPoints();	  // numPts = numPts + numEdges
+		numEdges = 2*numEdges + 3*numCells;		  // numEdges = 2*numEdges + 3*numCells
+		numCells = newPolys->GetNumberOfCells();  // numCells = 4*numCells
+
+		this->UpdateProgress (0.10 + 0.80*level/static_cast<double>(this->SubdivisionLevels));
+
+		// Cleanup at the end of each iteration.
+		edgeTable->Delete();
+
+		delete [] ids;
+
+		points->ShallowCopy(newPoints);
+		newPoints->Delete();
+		polys->DeepCopy(newPolys);
+		newPolys->Delete();
+	}
+
+	vtkDebugMacro(<<"numPoints="<<numPts<<" numCells="<<numCells<<" numEdges="<<numEdges);
+
+	// Add point normals
+	vtkDoubleArray* newNormals = vtkDoubleArray::New();
+	newNormals->SetNumberOfComponents(3);
+	newNormals->Allocate(3*numPts);
+	newNormals->SetName("Normals");
+	double p[3], n[3];
+	double norm;
+
+	for (int i=0; i<numPts; i++) {
+		points->GetPoint(i, p);
+		n[0] = p[0];
+		n[1] = p[1];
+		n[2] = p[2];
+		if ((norm = vtkMath::Norm(n)) == 0.0) {
+			norm = 1.0;
+		}
+		n[0] /= -1.0*norm;
+		n[1] /= -1.0*norm;
+		n[2] /= -1.0*norm;
+		newNormals->InsertNextTuple(n);
+
+		// While we're here, scale to the set radius and translate
+		// to the specified center
+		p[0] = this->Radius*p[0] + this->Center[0];
+		p[1] = this->Radius*p[1] + this->Center[1];
+		p[2] = this->Radius*p[2] + this->Center[2];
+		points->SetPoint(i, p);
+	}
+
+	points->Squeeze();
+	output->SetPoints(points);
+	points->Delete();
+
+	newNormals->Squeeze();
+	output->GetPointData()->SetNormals(newNormals);
+
+	newNormals->Delete();
+
+	polys->Squeeze();
+	output->SetPolys(polys);
+	polys->Delete();
+
+	this->UpdateProgress(1.0);
+
+	return 1;
+}
+
+
+//----------------------------------------------------------------------------
+void vtkjoSphereSource::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+
+  os << indent << "Theta Resolution: " << this->ThetaResolution << "\n";
+  os << indent << "Phi Resolution: " << this->PhiResolution << "\n";
+  os << indent << "Theta Start: " << this->StartTheta << "\n";
+  os << indent << "Phi Start: " << this->StartPhi << "\n";
+  os << indent << "Theta End: " << this->EndTheta << "\n";
+  os << indent << "Phi End: " << this->EndPhi << "\n";
+  os << indent << "Radius: " << this->Radius << "\n";
+  os << indent << "Center: (" << this->Center[0] << ", "
+     << this->Center[1] << ", " << this->Center[2] << ")\n";
+  os << indent
+     << "LatLong Tessellation: " << this->LatLongTessellation << "\n";
+  os << indent
+	 << "Icosahedral Tessellation: " << this->IcosahedralTessellation << "\n";
+  os << indent << "SubdivisionLevels: " << this->SubdivisionLevels << "\n";
+}
+
+//----------------------------------------------------------------------------
+int vtkjoSphereSource::RequestInformation(
+  vtkInformation *vtkNotUsed(request),
+  vtkInformationVector **vtkNotUsed(inputVector),
+  vtkInformationVector *outputVector)
+{
+  // get the info object
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(),
+               -1);
+
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_BOUNDING_BOX(),
+               this->Center[0] - this->Radius,
+               this->Center[0] + this->Radius,
+               this->Center[1] - this->Radius,
+               this->Center[1] + this->Radius,
+               this->Center[2] - this->Radius,
+               this->Center[2] + this->Radius);
+
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkjoSphereSource.h b/bioimagesuite30_src/Common/vtkjoSphereSource.h
new file mode 100644
index 0000000..85ab4c9
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkjoSphereSource.h
@@ -0,0 +1,176 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkjoSphereSource.h,v $
+
+  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 vtkjoSphereSource - create a polygonal sphere centered at the origin
+// .SECTION Description
+// vtkjoSphereSource creates a sphere (represented by polygons) of specified
+// radius centered at the origin. This class extends VTK's vtkSphereSource class
+// by allowing a second style of tessellation of the sphere.  For the first style
+// that uses latitudinal and longitudinal tessellation, the resolution (polygonal
+// discretization) in both the latitude (phi) and longitude (theta) directions can be
+// specified. It also is possible to create partial spheres by specifying
+// maximum phi and theta angles. By default, the surface tessellation of
+// the sphere uses triangles; however you can set LatLongTessellation to
+// produce a tessellation using quadrilaterals.  Alternatively, users may choose
+// to tessellate the sphere starting from an initial icosahedron polygon and
+// subsequently subdividing each of the faces.  The SubdivisionsLevel variable
+// sets the number of recursive subdivisions.
+// .SECTION Caveats
+// Resolution means the number of latitude or longitude lines for a complete
+// sphere. If you create partial spheres the number of latitude/longitude
+// lines may be off by one.
+
+#ifndef __vtkjoSphereSource_h
+#define __vtkjoSphereSource_h
+
+#include "vtkPolyDataAlgorithm.h"
+
+#define VTK_MAX_SPHERE_RESOLUTION 1024
+#define VTK_MAX_SPHERE_SUBDIVISIONS 8
+
+class vtkjoSphereSource : public vtkPolyDataAlgorithm
+{
+public:
+  vtkTypeRevisionMacro(vtkjoSphereSource,vtkPolyDataAlgorithm);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Construct sphere with radius=0.5 and default resolution 8 in both Phi
+  // and Theta directions. Theta ranges from (0,360) and phi (0,180) degrees.
+  static vtkjoSphereSource *New();
+
+  // Description:
+  // Set radius of sphere. Default is .5.
+  vtkSetClampMacro(Radius,double,0.0,VTK_DOUBLE_MAX);
+  vtkGetMacro(Radius,double);
+
+  // Description:
+  // Set the center of the sphere. Default is 0,0,0.
+  vtkSetVector3Macro(Center,double);
+  vtkGetVectorMacro(Center,double,3);
+
+  // Description:
+  // Set the number of points in the longitude direction (ranging from
+  // StartTheta to EndTheta).
+  vtkSetClampMacro(ThetaResolution,int,3,VTK_MAX_SPHERE_RESOLUTION);
+  vtkGetMacro(ThetaResolution,int);
+
+  // Description:
+  // Set the number of points in the latitude direction (ranging
+  // from StartPhi to EndPhi).
+  vtkSetClampMacro(PhiResolution,int,3,VTK_MAX_SPHERE_RESOLUTION);
+  vtkGetMacro(PhiResolution,int);
+
+  // Description:
+  // Set the starting longitude angle. By default StartTheta=0 degrees.
+  vtkSetClampMacro(StartTheta,double,0.0,360.0);
+  vtkGetMacro(StartTheta,double);
+
+  // Description:
+  // Set the ending longitude angle. By default EndTheta=360 degrees.
+  vtkSetClampMacro(EndTheta,double,0.0,360.0);
+  vtkGetMacro(EndTheta,double);
+
+  // Description:
+  // Set the starting latitude angle (0 is at north pole). By default
+  // StartPhi=0 degrees.
+  vtkSetClampMacro(StartPhi,double,0.0,360.0);
+  vtkGetMacro(StartPhi,double);
+
+  // Description:
+  // Set the ending latitude angle. By default EndPhi=180 degrees.
+  vtkSetClampMacro(EndPhi,double,0.0,360.0);
+  vtkGetMacro(EndPhi,double);
+
+  // Description:
+  // Cause the sphere to be tessellated with edges along the latitude
+  // and longitude lines. If off, triangles are generated at non-polar
+  // regions, which results in edges that are not parallel to latitude and
+  // longitude lines. If on, quadrilaterals are generated everywhere
+  // except at the poles. This can be useful for generating a wireframe
+  // sphere with natural latitude and longitude lines.
+  vtkSetMacro(LatLongTessellation,int);
+  vtkGetMacro(LatLongTessellation,int);
+  vtkBooleanMacro(LatLongTessellation,int);
+
+  // Description:
+  // Start with an icosahedron rather than use longitude and latitude
+  // style for constructing the sphere.  The vertices are more uniformly
+  // distributed throughout the sphere surface.
+  vtkSetMacro(IcosahedralTessellation, int);
+  vtkGetMacro(IcosahedralTessellation, int);
+  vtkBooleanMacro(IcosahedralTessellation, int);
+
+  // Description:
+  // Set the number of subdivisions to perform on the icosahedron when creating
+  // the sphere.  0 subdivions will return the initial icosahedron.
+  vtkSetClampMacro(SubdivisionLevels, int, 0, VTK_MAX_SPHERE_SUBDIVISIONS);
+  vtkGetMacro(SubdivisionLevels, int);
+
+protected:
+  vtkjoSphereSource(int res=8);
+  ~vtkjoSphereSource() {}
+
+  int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
+  int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
+
+  double Radius;
+  double Center[3];
+  int ThetaResolution;
+  int PhiResolution;
+  double StartTheta;
+  double EndTheta;
+  double StartPhi;
+  double EndPhi;
+  int LatLongTessellation;
+  int IcosahedralTessellation;
+  int SubdivisionLevels;
+
+  int PerformLatLongTessellation(vtkInformationVector *);
+  int PerformIcosahedralTessellation(vtkInformationVector *);
+
+private:
+  vtkjoSphereSource(const vtkjoSphereSource&);  // Not implemented.
+  void operator=(const vtkjoSphereSource&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkjoStatistics.cpp b/bioimagesuite30_src/Common/vtkjoStatistics.cpp
new file mode 100644
index 0000000..9883162
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkjoStatistics.cpp
@@ -0,0 +1,91 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkjoStatistics.cpp
+ *
+ *  Created on: Nov 19, 2008
+ *      Author: jonofrey
+ */
+
+#include <vtkjoStatistics.h>
+
+#include "vtkDataArray.h"
+#include "vtkImageData.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+
+
+vtkjoStatistics* vtkjoStatistics::New()
+{
+    // First try to create the object from the vtkObjectFactory
+    vtkObject* ret = vtkObjectFactory::CreateInstance("vtkjoStatistics");
+    if(ret)
+      {
+        return (vtkjoStatistics*) ret;
+      }
+    // If the factory was unable to create the object, then create it here.
+    return new vtkjoStatistics;
+}
+
+
+double vtkjoStatistics::JaccardCoefficient(vtkImageData* imageA, vtkImageData* imageB)
+{
+    int dimA[3]; imageA->GetDimensions(dimA);
+    int dimB[3]; imageB->GetDimensions(dimB);
+
+    // TODO: Should we also compare spacing and origin?
+    if ((dimA[0] != dimB[0]) &&
+            (dimA[1] != dimB[1]) &&
+            (dimA[2] != dimB[2]))
+    {
+        fprintf(stderr, "Images are not the same size.");
+        return 0.0;
+    }
+
+    vtkDataArray* dataA = imageA->GetPointData()->GetScalars();
+    vtkDataArray* dataB = imageB->GetPointData()->GetScalars();
+
+    vtkIdType nPts = dataA->GetNumberOfTuples();
+    double valueA = 0.0, valueB = 0.0;
+    int intersectAB = 0, unionAB = 0;
+
+    for (int i=0; i<nPts; i++) {
+        valueA = dataA->GetComponent(i, 0);
+        valueB = dataB->GetComponent(i, 0);
+
+        // Find the intersecting voxels in the image sets
+        if (valueA > 0.0 && valueB > 0.0)
+            intersectAB++;
+        // Find the unions of the image sets voxels
+        if (valueA > 0.0 || valueB > 0.0)
+            unionAB++;
+    }
+
+    return double(intersectAB)/double(unionAB);
+}
+
diff --git a/bioimagesuite30_src/Common/vtkjoStatistics.h b/bioimagesuite30_src/Common/vtkjoStatistics.h
new file mode 100644
index 0000000..f02ffba
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkjoStatistics.h
@@ -0,0 +1,60 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkjoStatistics.h
+ *
+ *  Created on: Nov 19, 2008
+ *      Author: jonofrey
+ */
+
+#ifndef VTKJOSTATISTICS_H_
+#define VTKJOSTATISTICS_H_
+
+#include "vtkObject.h"
+
+class vtkImageData;
+
+class vtkjoStatistics : public vtkObject
+{
+public:
+    static vtkjoStatistics *New();
+    vtkTypeMacro(vtkjoStatistics, vtkObject);
+
+    // Description:
+    // Computes the Jaccard similarity coefficient of two image datasets.
+    // This method converts datasets to binary images, if not already, and then
+    // finds the Jaccard coefficient.  Image must have the same dimensions.
+    static double JaccardCoefficient(vtkImageData* A, vtkImageData* B);
+
+protected:
+    vtkjoStatistics() {};
+    ~vtkjoStatistics() {};
+};
+
+#endif /* VTKJOSTATISTICS_H_ */
+
diff --git a/bioimagesuite30_src/Common/vtkokImageAccumulate.cpp b/bioimagesuite30_src/Common/vtkokImageAccumulate.cpp
new file mode 100644
index 0000000..a4c1600
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkokImageAccumulate.cpp
@@ -0,0 +1,440 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkokImageAccumulate.h"
+
+#include "vtkImageData.h"
+#include "vtkImageStencilData.h"
+#include "vtkObjectFactory.h"
+
+#include <math.h>
+
+vtkCxxRevisionMacro(vtkokImageAccumulate, "$Revision: 1.51 $");
+vtkStandardNewMacro(vtkokImageAccumulate);
+
+//----------------------------------------------------------------------------
+// Constructor sets default values
+vtkokImageAccumulate::vtkokImageAccumulate()
+{
+  int idx;
+  
+  for (idx = 0; idx < 3; ++idx)
+    {
+    this->ComponentSpacing[idx] = 1.0;
+    this->ComponentOrigin[idx] = 0.0;
+    this->ComponentExtent[idx*2] = 0;
+    this->ComponentExtent[idx*2+1] = 0;
+    }
+  this->ComponentExtent[1] = 255;
+  
+  this->ReverseStencil = 0;
+
+  this->Min[0] = this->Min[1] = this->Min[2] = 0.0;
+  this->Max[0] = this->Max[1] = this->Max[2] = 0.0;
+  this->Mean[0] = this->Mean[1] = this->Mean[2] = 0.0;
+  this->StandardDeviation[0] = this->StandardDeviation[1] = this->StandardDeviation[2] = 0.0;  
+  this->VoxelCount = 0;
+
+  for(int i = 0;i<3;i++){
+    this->ThLowCollect[i]  = -10000000;
+    this->ThHighCollect[i] =  10000000;
+  }
+  this->OutlierExceptionMode = 0;
+  this->ThK = 0;
+}
+
+
+//----------------------------------------------------------------------------
+vtkokImageAccumulate::~vtkokImageAccumulate()
+{
+}
+
+//----------------------------------------------------------------------------
+void vtkokImageAccumulate::SetComponentExtent(int extent[6])
+{
+  int idx, modified = 0;
+  
+  for (idx = 0; idx < 6; ++idx)
+    {
+    if (this->ComponentExtent[idx] != extent[idx])
+      {
+      this->ComponentExtent[idx] = extent[idx];
+      this->Modified();
+      }
+    }
+  if (modified)
+    {
+    this->Modified();
+    }
+}
+
+
+//----------------------------------------------------------------------------
+void vtkokImageAccumulate::SetComponentExtent(int minX, int maxX, 
+                                            int minY, int maxY,
+                                            int minZ, int maxZ)
+{
+  int extent[6];
+  
+  extent[0] = minX;  extent[1] = maxX;
+  extent[2] = minY;  extent[3] = maxY;
+  extent[4] = minZ;  extent[5] = maxZ;
+  this->SetComponentExtent(extent);
+}
+
+
+//----------------------------------------------------------------------------
+void vtkokImageAccumulate::GetComponentExtent(int extent[6])
+{
+  int idx;
+  
+  for (idx = 0; idx < 6; ++idx)
+    {
+    extent[idx] = this->ComponentExtent[idx];
+    }
+}
+
+
+//----------------------------------------------------------------------------
+void vtkokImageAccumulate::SetStencil(vtkImageStencilData *stencil)
+{
+  this->vtkProcessObject::SetNthInput(1, stencil); 
+}
+
+
+//----------------------------------------------------------------------------
+vtkImageStencilData *vtkokImageAccumulate::GetStencil()
+{
+  if (this->NumberOfInputs < 2) 
+    { 
+    return NULL;
+    }
+  else
+    {
+    return (vtkImageStencilData *)(this->Inputs[1]); 
+    }
+}
+
+
+//----------------------------------------------------------------------------
+// This templated function executes the filter for any type of data.
+template <class T>
+void vtkokImageAccumulateExecute(vtkokImageAccumulate *self,
+                               vtkImageData *inData, T *inPtr,
+				 double *ThLowCollect,
+				 double *ThHighCollect,
+                               vtkImageData *outData, int *outPtr,
+                               double Min[3], double Max[3],
+                               double Mean[3],
+                               double StandardDeviation[3],
+                               long int *VoxelCount)
+{
+  int idX, idY, idZ, idxC;
+  int iter, pmin0, pmax0, min0, max0, min1, max1, min2, max2;
+  vtkIdType inInc0, inInc1, inInc2;
+  T *tempPtr;
+  int *outPtrC;
+  int numC, outIdx, *outExtent;
+  vtkIdType *outIncs;
+  double *origin, *spacing;
+  unsigned long count = 0;
+  unsigned long target;
+  double sumSqr[3], variance;
+
+  // variables used to compute statistics (filter handles max 3 components)
+  double sum[3];
+  sum[0] = sum[1] = sum[2] = 0.0;
+  Min[0] = Min[1] = Min[2] = VTK_DOUBLE_MAX;
+  Max[0] = Max[1] = Max[2] = VTK_DOUBLE_MIN;
+  sumSqr[0] = sumSqr[1] = sumSqr[2] = 0.0;
+  StandardDeviation[0] = StandardDeviation[1] = StandardDeviation[2] = 0.0;
+  *VoxelCount = 0;
+  
+  vtkImageStencilData *stencil = self->GetStencil();
+
+  // Zero count in every bin
+  outData->GetExtent(min0, max0, min1, max1, min2, max2);
+  memset((void *)outPtr, 0, 
+         (max0-min0+1)*(max1-min1+1)*(max2-min2+1)*sizeof(int));
+    
+  // Get information to march through data 
+  numC = inData->GetNumberOfScalarComponents();
+  inData->GetUpdateExtent(min0, max0, min1, max1, min2, max2);
+  inData->GetIncrements(inInc0, inInc1, inInc2);
+  outExtent = outData->GetExtent();
+  outIncs = outData->GetIncrements();
+  origin = outData->GetOrigin();
+  spacing = outData->GetSpacing();
+
+  target = (unsigned long)((max2 - min2 + 1)*(max1 - min1 +1)/50.0);
+  target++;
+
+
+  // Loop through input pixels
+  for (idZ = min2; idZ <= max2; idZ++)
+    {
+    for (idY = min1; idY <= max1; idY++)
+      {
+      if (!(count%target)) 
+        {
+        self->UpdateProgress(count/(50.0*target));
+        }
+      count++;
+
+      // loop over stencil sub-extents
+      iter = 0;
+      if (self->GetReverseStencil())
+        { // flag that we want the complementary extents
+        iter = -1;
+        }
+
+      pmin0 = min0;
+      pmax0 = max0;
+      while ((stencil != 0 && 
+              stencil->GetNextExtent(pmin0,pmax0,min0,max0,idY,idZ,iter)) ||
+             (stencil == 0 && iter++ == 0))
+        {
+        // set up pointer for sub extent
+        tempPtr = inPtr + (inInc2*(idZ - min2) +
+                           inInc1*(idY - min1) +
+                           numC*(pmin0 - min0));
+
+        // accumulate over the sub extent
+        for (idX = pmin0; idX <= pmax0; idX++)
+          {
+          // find the bin for this pixel.
+          outPtrC = outPtr;
+          for (idxC = 0; idxC < numC; ++idxC)
+            {
+            // Only when te value is betwen thresholds, gather statistics
+	      if(*tempPtr > ThLowCollect[idxC] && *tempPtr < ThHighCollect[idxC]) {
+		sum[idxC]+= *tempPtr;
+		sumSqr[idxC]+= (*tempPtr * *tempPtr);
+		if (*tempPtr > Max[idxC])
+		  {
+		    Max[idxC] = *tempPtr;
+		  }
+		else if (*tempPtr < Min[idxC])
+		  {
+		    Min[idxC] = *tempPtr;
+		  }
+	      }
+            (*VoxelCount)++;
+            // compute the index
+            outIdx = (int) floor((((double)*tempPtr++ - origin[idxC]) 
+                                  / spacing[idxC]));
+            if (outIdx < outExtent[idxC*2] || outIdx > outExtent[idxC*2+1])
+              {
+              // Out of bin range
+              outPtrC = NULL;
+              break;
+              }
+            outPtrC += (outIdx - outExtent[idxC*2]) * outIncs[idxC];
+            }
+          if (outPtrC)
+            {
+            ++(*outPtrC);
+            }
+          }
+        }
+      }
+    }
+  
+  if (*VoxelCount) // avoid the div0
+    {
+    Mean[0] = sum[0] / (double)*VoxelCount;    
+    Mean[1] = sum[1] / (double)*VoxelCount;    
+    Mean[2] = sum[2] / (double)*VoxelCount;    
+
+    variance = sumSqr[0] / (double)(*VoxelCount-1) - ((double) *VoxelCount * Mean[0] * Mean[0] / (double) (*VoxelCount - 1));
+    StandardDeviation[0] = sqrt(variance);
+    variance = sumSqr[1] / (double)(*VoxelCount-1) - ((double) *VoxelCount * Mean[1] * Mean[1] / (double) (*VoxelCount - 1));
+    StandardDeviation[1] = sqrt(variance);
+    variance = sumSqr[2] / (double)(*VoxelCount-1) - ((double) *VoxelCount * Mean[2] * Mean[2] / (double) (*VoxelCount - 1));
+    StandardDeviation[2] = sqrt(variance);
+    }
+  else
+    {
+    Mean[0] = Mean[1] = Mean[2] = 0.0;
+    StandardDeviation[0] = StandardDeviation[1] = StandardDeviation[2] = 0.0;
+    }
+  
+}
+
+        
+
+//----------------------------------------------------------------------------
+// This method is passed a input and output Data, and executes the filter
+// algorithm to fill the output from the input.
+// It just executes a switch statement to call the correct function for
+// the Datas data types.
+void vtkokImageAccumulate::ExecuteData(vtkDataObject *vtkNotUsed(out))
+{
+  void *inPtr;
+  void *outPtr;
+  vtkImageData *inData = this->GetInput();
+  vtkImageData *outData = this->GetOutput();
+  
+  vtkDebugMacro(<<"Executing image accumulate");
+  
+  // We need to allocate our own scalars since we are overriding
+  // the superclasses "Execute()" method.
+  outData->SetExtent(outData->GetWholeExtent());
+  outData->AllocateScalars();
+  
+  inPtr = inData->GetScalarPointerForExtent(inData->GetUpdateExtent());
+  outPtr = outData->GetScalarPointer();
+  
+  // Components turned into x, y and z
+  if (this->GetInput()->GetNumberOfScalarComponents() > 3)
+    {
+    vtkErrorMacro("This filter can handle upto 3 components");
+    return;
+    }
+  
+  // this filter expects that output is type int.
+  if (outData->GetScalarType() != VTK_INT)
+    {
+    vtkErrorMacro(<< "Execute: out ScalarType " << outData->GetScalarType()
+                  << " must be int\n");
+    return;
+    }
+  
+    switch (inData->GetScalarType())
+      {
+     vtkTemplateMacro(vtkokImageAccumulateExecute(this, 
+                       inData, (VTK_TT *)(inPtr), 
+                       this->ThLowCollect,this->ThHighCollect,
+                       outData, (int *)(outPtr),
+                       this->Min, this->Max,
+                       this->Mean,
+                       this->StandardDeviation, &this->VoxelCount));
+
+    default:
+      vtkErrorMacro(<< "Execute: Unknown ScalarType");
+      return;
+    }
+  if(this->OutlierExceptionMode == 1){
+    for(int c=0;c<3;c++){
+      this->ThLowCollect[c]   = this->Mean[c] - this->ThK*this->StandardDeviation[c];
+      this->ThHighCollect[c]  = this->Mean[c] + this->ThK*this->StandardDeviation[c];
+    }
+    switch (inData->GetScalarType())
+      {
+
+ 
+     vtkTemplateMacro(vtkokImageAccumulateExecute(this, 
+                       inData, (VTK_TT *)(inPtr), 
+                       this->ThLowCollect,this->ThHighCollect,
+                       outData, (int *)(outPtr),
+                       this->Min, this->Max,
+                       this->Mean,
+                       this->StandardDeviation, &this->VoxelCount));
+
+    default:
+      vtkErrorMacro(<< "Execute: Unknown ScalarType");
+      return;
+    }
+  }
+
+}
+
+
+//----------------------------------------------------------------------------
+void vtkokImageAccumulate::ExecuteInformation(vtkImageData *input, 
+                                            vtkImageData *output)
+{
+  output->SetWholeExtent(this->ComponentExtent);
+  output->SetOrigin(this->ComponentOrigin);
+  output->SetSpacing(this->ComponentSpacing);
+  output->SetNumberOfScalarComponents(1);
+  output->SetScalarType(VTK_INT);
+
+  // need to set the spacing and origin of the stencil to match the output
+  vtkImageStencilData *stencil = this->GetStencil();
+  if (stencil)
+    {
+    stencil->SetSpacing(input->GetSpacing());
+    stencil->SetOrigin(input->GetOrigin());
+    }
+}
+
+//----------------------------------------------------------------------------
+// Get ALL of the input.
+void vtkokImageAccumulate::ComputeInputUpdateExtent(int inExt[6], 
+                                                  int *vtkNotUsed(outExt))
+{
+  int *wholeExtent;
+
+  wholeExtent = this->GetInput()->GetWholeExtent();
+  memcpy(inExt, wholeExtent, 6*sizeof(int));
+}
+
+
+void vtkokImageAccumulate::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+
+  os << indent << "Mean: ("
+     << this->Mean[0] << ", "
+     << this->Mean[1] << ", "
+     << this->Mean[2] << ")\n";
+  os << indent << "Min: ("
+     << this->Min[0] << ", "
+     << this->Min[1] << ", "
+     << this->Min[2] << ")\n";
+  os << indent << "Max: ("
+     << this->Max[0] << ", "
+     << this->Max[1] << ", "
+     << this->Max[2] << ")\n";
+  os << indent << "StandardDeviation: ("
+     << this->StandardDeviation[0] << ", "
+     << this->StandardDeviation[1] << ", "
+     << this->StandardDeviation[2] << ")\n";
+  os << indent << "VoxelCount: " << this->VoxelCount << "\n";
+  os << indent << "Stencil: " << this->GetStencil() << "\n";
+  os << indent << "ReverseStencil: " << (this->ReverseStencil ?
+                                         "On\n" : "Off\n");
+
+  os << indent << "ComponentOrigin: ( "
+     << this->ComponentOrigin[0] << ", "
+     << this->ComponentOrigin[1] << ", "
+     << this->ComponentOrigin[2] << " )\n";
+
+  os << indent << "ComponentSpacing: ( "
+     << this->ComponentSpacing[0] << ", "
+     << this->ComponentSpacing[1] << ", "
+     << this->ComponentSpacing[2] << " )\n";
+
+  os << indent << "ComponentExtent: ( "
+     << this->ComponentExtent[0] << "," << this->ComponentExtent[1] << " "
+     << this->ComponentExtent[2] << "," << this->ComponentExtent[3] << " "
+     << this->ComponentExtent[4] << "," << this->ComponentExtent[5] << " }\n";
+}
+
+
diff --git a/bioimagesuite30_src/Common/vtkokImageAccumulate.h b/bioimagesuite30_src/Common/vtkokImageAccumulate.h
new file mode 100644
index 0000000..64df3f5
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkokImageAccumulate.h
@@ -0,0 +1,168 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// .NAME vtkokImageAccumulate - Generalized histograms up to 4 dimensions.
+//
+// .SECTION Description
+// vtkokImageAccumulate - This filter divides component space into
+// discrete bins.  It then counts the number of pixels associated
+// with each bin.  The output is this "scatter plot" (histogram values for 1D).
+// The dimensionality of the output depends on how many components the 
+// input pixels have.  Input pixels with one component generate a 1D histogram.
+// This filter can only handle images with 1 to 3 scalar components.
+// The input can be any type, but the output is always int.
+// Some statistics are computed on the pixel values at the same time.
+// The SetStencilFunction, SetClippingExtents and ReverseStencil
+// functions allow the statistics to be computed on an arbitrary
+// portion of the input data.
+// See the documentation for vtkImageStencil for more information.
+//
+// .SECTION See also
+//  vtkokImageAccumulate.tcl,Test_vtkokImageAccumulate.tcl
+//
+// .SECTION Author
+//  Hirohito Okuda <hirohito.okuda at yale.edu>
+//
+
+
+#ifndef __vtkokImageAccumulate_h
+#define __vtkokImageAccumulate_h
+
+
+#include "vtkImageToImageFilter.h"
+
+class vtkImageStencilData;
+
+class  vtkokImageAccumulate : public vtkImageToImageFilter
+{
+public:
+  static vtkokImageAccumulate *New();
+  vtkTypeRevisionMacro(vtkokImageAccumulate,vtkImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Set/Get - The component spacing is the dimension of each bin.
+  // This ends up being the spacing of the output "image".
+  // If the number of input scalar components are less than three,
+  // then some of these spacing values are ignored.
+  // For a 1D histogram with 10 bins spanning the values 1000 to 2000,
+  // this spacing should be set to 100, 0, 0
+  vtkSetVector3Macro(ComponentSpacing, double);
+  vtkGetVector3Macro(ComponentSpacing, double);
+
+  // Description:
+  // Set/Get - The component origin is the location of bin (0, 0, 0).
+  // Note that if the Component extent does not include the value (0,0,0),
+  // then this origin bin will not actually be in the output.
+  // The origin of the output ends up being the same as the componenet origin.
+  // For a 1D histogram with 10 bins spanning the values 1000 to 2000,
+  // this origin should be set to 1000, 0, 0
+  vtkSetVector3Macro(ComponentOrigin, double);
+  vtkGetVector3Macro(ComponentOrigin, double);
+
+  // Description:
+  // Set/Get - The component extent sets the number/extent of the bins.
+  // For a 1D histogram with 10 bins spanning the values 1000 to 2000,
+  // this extent should be set to 0, 9, 0, 0, 0, 0.
+  // The extent specifies inclusive min/max values.  
+  // This implies the the top extent should be set to the number of bins - 1.
+  void SetComponentExtent(int extent[6]);
+  void SetComponentExtent(int minX, int maxX, int minY, int maxY,
+        int minZ, int maxZ);
+  void GetComponentExtent(int extent[6]);
+  int *GetComponentExtent() {return this->ComponentExtent;}
+
+
+  // Description:
+  // Use a stencil to specify which voxels to accumulate.
+  void SetStencil(vtkImageStencilData *stencil);
+  vtkImageStencilData *GetStencil();
+
+  // Description:
+  // Reverse the stencil.
+  vtkSetMacro(ReverseStencil, int);
+  vtkBooleanMacro(ReverseStencil, int);
+  vtkGetMacro(ReverseStencil, int);
+
+  // Description:
+  // Get the statistics information for the data.
+  vtkGetVector3Macro(Min, double);
+  vtkGetVector3Macro(Max, double);
+  vtkGetVector3Macro(Mean, double);
+  vtkGetVector3Macro(StandardDeviation, double);
+  vtkGetMacro(VoxelCount, long int);
+ 
+  vtkGetVector3Macro(ThLowCollect,double);
+  vtkSetVector3Macro(ThLowCollect,double);
+
+  vtkGetVector3Macro(ThHighCollect,double);
+  vtkSetVector3Macro(ThHighCollect,double);
+
+  vtkGetMacro(ThK,double);
+  vtkSetMacro(ThK,double);
+
+  vtkGetMacro(OutlierExceptionMode,int);
+  vtkSetMacro(OutlierExceptionMode,int);
+
+  void SetOutlierExceptionModeToConstantSigma(){this->OutlierExceptionMode = 1;}
+
+protected:
+  vtkokImageAccumulate();
+  ~vtkokImageAccumulate();
+
+  double ComponentSpacing[3];
+  double ComponentOrigin[3];
+  int ComponentExtent[6];
+
+  void ExecuteInformation(vtkImageData *input, vtkImageData *output);
+  void ComputeInputUpdateExtent(int inExt[6], int outExt[6]);
+  void ExecuteInformation(){this->vtkImageToImageFilter::ExecuteInformation();};
+  void ExecuteData(vtkDataObject *out);
+
+  double Min[3];
+  double Max[3];
+  double Mean[3];
+  double StandardDeviation[3];
+  long int VoxelCount;
+
+  double ThLowCollect[3];
+  double ThHighCollect[3];
+  double ThK;
+  int    OutlierExceptionMode;
+
+  int ReverseStencil;
+
+private:
+  vtkokImageAccumulate(const vtkokImageAccumulate&);  // Not implemented.
+  void operator=(const vtkokImageAccumulate&);  // Not implemented.
+};
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxAbstractMatrix.cpp b/bioimagesuite30_src/Common/vtkpxAbstractMatrix.cpp
new file mode 100644
index 0000000..b325aeb
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxAbstractMatrix.cpp
@@ -0,0 +1,104 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAbstractMatrix.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/10/29 19:34:42 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxAbstractMatrix.h"
+
+// -----------------------------------------------------------------------------------
+vtkpxAbstractMatrix::vtkpxAbstractMatrix()
+{
+  this->Size[0]=0;
+  this->Size[1]=0;
+}
+// -----------------------------------------------------------------------------------
+float vtkpxAbstractMatrix::GetElement(int i,int j)
+{
+  i=Irange(i,0,this->Size[0]-1);
+  j=Irange(j,0,this->Size[1]-1);
+  return (this->GetDirectElement(i,j));
+}
+// -----------------------------------------------------------------------------------
+void vtkpxAbstractMatrix::SetElement(int i,int j,float v)
+{
+  i=Irange(i,0,this->Size[0]-1);
+  j=Irange(j,0,this->Size[1]-1);
+  this->SetDirectElement(i,j,v);
+}
+// -----------------------------------------------------------------------------------
+void vtkpxAbstractMatrix::AddToElement(int i,int j,float v)
+{
+  i=Irange(i,0,this->Size[0]-1);
+  j=Irange(j,0,this->Size[1]-1);
+  float v1=this->GetDirectElement(i,j);
+  this->SetDirectElement(i,j,v+v1);
+}
+// -----------------------------------------------------------------------------------
+void vtkpxAbstractMatrix::MakeSymmetricByAddingTransposeOf(vtkpxAbstractMatrix* other)
+{
+  if (other->GetSize()[0]!=this->Size[1] || other->GetSize()[1]!=this->Size[0])
+    {
+      vtkErrorMacro(<<"Bad Matrix to Make Symmetric With\n");
+      return;
+    }
+
+  for (int i=0;i<this->Size[0];i++)
+    for (int j=0;j<this->Size[1];j++)
+      {
+	float v1=this->GetDirectElement(i,j);
+	float v2=other->GetDirectElement(j,i);
+	this->SetDirectElement(i,j,0.5*(v1+v2));
+      }
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxAbstractMatrix.h b/bioimagesuite30_src/Common/vtkpxAbstractMatrix.h
new file mode 100644
index 0000000..00dc52f
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxAbstractMatrix.h
@@ -0,0 +1,155 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAbstractMatrix.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxAbstractMatrix - stores and manipulates a 2D Sparse Matrix (float) using STL map
+// .SECTION Description
+// .SECTION See Also
+//  vtkpxMatrix
+//
+
+class vtkpxMatrix;
+
+#ifndef __vtkpxAbstractMatrix_h
+#define __vtkpxAbstractMatrix_h
+
+#include "vtkObject.h"
+
+class vtkpxAbstractMatrix : public vtkObject
+{
+public:
+  vtkTypeMacro(vtkpxAbstractMatrix,vtkObject);
+  
+  // Description:
+  // Gets the size of the matrix
+  vtkGetVectorMacro(Size,int,2);
+
+  // Description:
+  // Matrix Density
+  virtual float Density() { return 1.0;}
+
+  // Description:
+  // Routine to allocate memory and set equal to zero (alias for allocate ala matlab)
+  virtual void Zeros(int rows,int cols)=0;
+
+  // Description:
+  // Routine to allocate memory 
+  virtual void Allocate(int rows,int columns)=0;
+
+  // Description:
+  // Routines to allocate memory and set equal to one
+  virtual void Ones(int rows,int cols)=0;
+
+  // Description:
+  // Routines to allocate memory for square matrix and initialize accordingly and set to identity
+  virtual void Eye(int rowcol)=0;
+
+  // Description:
+  // Sets current matrix=identity matrix (if it is square)
+  virtual void Identity()=0;
+
+  // Description:
+  // Set all elements = zero
+  virtual void Zero()=0;
+
+
+  // Description:
+  // Set all elements = a
+  virtual void Fill(float a)=0;
+
+  // Description:
+  // Print Matrix to stderr
+  virtual void InternalPrint()=0;
+  virtual void Print(const char* message)=0;
+  
+  //BTX
+  // Description:
+  // Get/Set Element in row=i column=j without range checking UNSAFE
+  inline virtual float  GetDirectElement(const int i,const int j)=0;              
+  inline virtual void   SetDirectElement(const int i,const int j,const float v)=0;
+  //ETX
+
+  // Description:
+  // Get/Set Element in row=i column=j with range checking SAFE
+  virtual float   GetElement(int i,int j);
+  virtual void    SetElement(int i,int j,float v);
+  virtual void    AddToElement(int i,int j,float v);
+
+  // Description:
+  // Multiply All elements in matrix by s
+  virtual void  Scale(float s)=0;
+
+  // Description:
+  // this*b=c
+  virtual void MultiplyThisWith(vtkpxMatrix* b,vtkpxMatrix* c)=0;
+
+  // Description:
+  // RPM Stuff
+  virtual void MapPoints(vtkpxMatrix* Y,vtkpxMatrix* VY)=0;
+  virtual void NormalizeMixtureMatrix(vtkpxMatrix* M_Outliers_Row)=0;
+  virtual void NormalizeRPMMatrix(vtkpxMatrix* M_Outliers_Row,vtkpxMatrix* M_Outliers_Column)=0;
+  virtual void MakeSymmetricByAddingTransposeOf(vtkpxAbstractMatrix* other);
+
+
+protected:
+
+  vtkpxAbstractMatrix();
+  virtual ~vtkpxAbstractMatrix() {};
+
+  int Size[2];
+  int Irange(int a,int minv,int maxv) { if (a<minv) a=minv; else if (a>maxv) a=maxv;  return a; }
+ 
+};
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkpxAnalyzeImageSource.cpp b/bioimagesuite30_src/Common/vtkpxAnalyzeImageSource.cpp
new file mode 100644
index 0000000..7ec7b27
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxAnalyzeImageSource.cpp
@@ -0,0 +1,589 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkpxAnalyzeImageSource.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkbisImageHeader.h"
+#include "vtkImagePermute.h"
+#include "vtkErrorCode.h"
+#include "nifti1.h"
+#include "nifti1_io.h"
+#include "bis_znzlib.h"
+#include "vtkMatrix4x4.h"
+
+#include "vtkInformationVector.h"
+#include "vtkInformation.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+
+//------------------------------------------------------------------------------
+vtkpxAnalyzeImageSource* vtkpxAnalyzeImageSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxAnalyzeImageSource");
+  if(ret)
+    {
+      return (vtkpxAnalyzeImageSource*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxAnalyzeImageSource;
+}
+
+// Construct object with NULL file prefix; file pattern "%s.%d"; image range 
+// set to (1,1); data origin (0,0,0); data spacing (1,1,1); no data mask;
+// header size 0; and byte swapping turned off.
+
+vtkpxAnalyzeImageSource::vtkpxAnalyzeImageSource()
+{
+  this->FilePrefix = NULL;
+  this->DataFlip[0] = this->DataFlip[1] = this->DataFlip[2]=0;
+  this->Transpose=0;
+  this->read_volume_ok=0;
+  this->Orientation=0; // Axial
+  this->IntShift=0.0;
+  this->IntScale=1.0;
+  this->ImageHeader=vtkbisImageHeader::New();
+  this->ForceStandardOrientation=1;
+  this->SetNumberOfInputPorts(0);
+
+}
+
+
+vtkpxAnalyzeImageSource::~vtkpxAnalyzeImageSource()
+{
+  if (this->FilePrefix)
+    delete [] this->FilePrefix;
+
+  if (this->ImageHeader)
+    this->ImageHeader->Delete();
+}
+
+//------------------------------------------------------------------------------
+// Specify the input data or filter.
+
+// Read an analyze header file
+// ---------------------------
+int vtkpxAnalyzeImageSource::ReadHeaderFile()
+{
+  int ok=this->ImageHeader->ReadHeader(this->FilePrefix);
+  if (ok==0)
+    return 0;
+
+  this->Orientation=this->ImageHeader->GetOrientation();
+  this->DataFlip[0] = this->DataFlip[1] = this->DataFlip[2]=0; this->Transpose=0;
+  this->IntShift=0.0;  this->IntScale=1.0;
+  this->read_volume_ok=1;
+  //  this->ImageHeader->PrintHeader();
+  return 1;
+
+}
+//------------------------------------------------------------------------------
+// From VTK vtkByteSwap originally, templated etc.
+//------------------------------------------------------------------------------
+template<class T>
+void vtkpxAnalyzeImageSourceSwapBytes(T* dt,int slicesize,int sz)
+{
+  if (sz<1)
+    return;
+
+  char* chardata=(char*)dt;
+  char one_byte=0;
+  int   totalnumbytes=slicesize*sz;
+  for (int i=0;i<totalnumbytes;i+=sz)
+    {
+      char* data=&chardata[i];
+      switch(sz)
+	{
+	case 2:
+	  one_byte = data[0]; data[0] = data[1]; data[1] = one_byte;
+	  break;
+	case 4:
+	  one_byte = data[0]; data[0] = data[3]; data[3] = one_byte;
+	  one_byte = data[1]; data[1] = data[2]; data[2] = one_byte; 
+	  break;
+	case 8:
+	  one_byte = data[0]; data[0] = data[7]; data[7] = one_byte;
+	  one_byte = data[1]; data[1] = data[6]; data[6] = one_byte;
+	  one_byte = data[2]; data[2] = data[5]; data[5] = one_byte;
+	  one_byte = data[3]; data[3] = data[4]; data[4] = one_byte; 
+	  break;
+	}
+    }
+}
+
+// ----------------------------------------------------------------------------
+template<class T>
+int vtkpxAnalyzeImageSourceReadSlices(vtkpxAnalyzeImageSource *self,
+				      vtkImageData* output,
+				      znzFile fp,
+				      T*)
+{
+
+  vtkDataArray* dat=output->GetPointData()->GetScalars();
+  T* dat_point=(T*)dat->GetVoidPointer(0);
+  
+  unsigned long sz=output->GetPointData()->GetScalars()->GetDataTypeSize();
+
+  int numcomponents=dat->GetNumberOfComponents();
+  int dim[3];output->GetDimensions(dim);
+  int slicesize=dim[0]*dim[1];
+  T* temp = new T[slicesize];
+  double oldpog=0.0;
+
+  int DataFlip[3]; self->GetDataFlip(DataFlip);
+  int Transpose[3]; self->GetDataFlip(Transpose);
+  //  double intScale=self->GetIntScale();
+  //  double intShift=self->GetIntShift();
+  //  fprintf(stderr,"\nUsing Data Flip=%d,%d,%d \n",DataFlip[0],DataFlip[1],DataFlip[2]);
+  //  fprintf(stderr,"Data Size %d\n",dat->GetDataType());
+
+  int sliceNumber=0;
+  int totalslices=numcomponents*dim[2];
+  for (int frame=0;frame<numcomponents;frame++)
+    for (int slice = 0; slice < dim[2]; slice++) 
+      {
+	double pog=float(sliceNumber)/float(totalslices);
+	if ( (pog-oldpog)>0.1)
+	  {
+	    self->UpdateProgress(pog);
+	    oldpog=pog;
+	  }
+	//	fprintf(stderr,"Reading slice %d/%d frame %d/%d\n",slice,dim[2],frame,numcomponents);
+	znzread(&temp[0],sz,slicesize,fp);
+	
+	if (self->GetImageHeader()->GetSwapBytes())
+	  vtkpxAnalyzeImageSourceSwapBytes(temp,slicesize,sz);
+	
+	int index=0;
+	for (int ib=0;ib<dim[1];ib++)
+	  {
+	    int offset=0;
+	    if (DataFlip[2]==0)
+	      offset+=slice*slicesize;
+	    else
+	      offset+=(dim[2]-1-slice)*slicesize;
+	    
+	    if (DataFlip[1]==0)
+	      offset+=ib*dim[0];
+	    else
+	      offset+=(dim[1]-1-ib)*dim[0];
+	    
+	    offset=offset*numcomponents+frame;
+	    
+	    if (DataFlip[0]==1)
+	      offset+=(dim[0]-1)*numcomponents;
+	    
+	    for (int ia=0;ia<dim[0];ia++)
+	      {
+		dat_point[offset]=(T)((double)temp[index]);// *intScale+intShift);
+		if (DataFlip[0]==0)
+		  offset+=numcomponents;
+		else
+		  offset-=numcomponents;
+		++index;
+	      }
+	  }
+	++sliceNumber;
+      }
+  
+  delete [] temp;
+  return 1;
+}
+//------------------------------------------------------------------------------
+int vtkpxAnalyzeImageSource::ReadMetaData(vtkInformation *outInfo)
+{
+  this->SetErrorCode( vtkErrorCode::NoError );
+
+  int ok=1;
+
+  if (this->read_volume_ok==0)
+    ok=this->ReadHeaderFile();
+
+  if (ok==0)
+    {
+      vtkErrorMacro(<<"Bad Header!");
+      this->SetErrorCode( vtkErrorCode::UnrecognizedFileTypeError );
+      return 1;
+    }
+
+
+  int dim[3]; this->ImageHeader->GetDimensions(dim);
+  int nc=this->ImageHeader->GetNumberOfComponents();
+  double spa[3]; this->ImageHeader->GetSpacing(spa);
+  int dt=this->ImageHeader->GetVTKDataType();
+
+
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),
+	       0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
+	       0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+
+  outInfo->Set(vtkDataObject::SPACING(), spa, 3);
+
+
+  double origin[3]={0.0,0.0,0.0};
+
+  outInfo->Set(vtkDataObject::ORIGIN(), origin, 3);
+
+
+  
+
+  vtkDataObject::SetPointDataActiveScalarInfo( outInfo, 
+					       dt,nc);
+  return 1;
+}
+
+//------------------------------------------------------------------------------
+int vtkpxAnalyzeImageSource::Load(const char *ana)
+{
+  this->SetFilePrefix(ana);
+  int ok=this->ReadHeaderFile();
+  if (ok!=0)
+      this->Update();
+
+  int dim[3]; this->GetOutput()->GetDimensions(dim);
+  int total=dim[0]*dim[1]*dim[2];
+  
+  if (total>=1)
+    return 1;
+  return 0;
+}
+//------------------------------------------------------------------------------
+int vtkpxAnalyzeImageSource::RequestData(vtkInformation *,
+					 vtkInformationVector **,
+					 vtkInformationVector *outputVector)
+{
+
+  if (this->FilePrefix == NULL) 
+    {
+      vtkErrorMacro(<< "FilePrefix is NULL");
+      return 1;
+    }
+    
+  if (this->read_volume_ok==0)
+    {
+      vtkDebugMacro(<<"Not updating");
+      return 1;
+    }
+  
+  if (!this->FilePrefix)
+    return 1;
+  
+  char* filename;
+  // Analyze Mode 0 = Binary, 1= Analyze, 2= NIFTY (.hdr,.img), 3=NIFTY(.nii)
+  if (this->ImageHeader->GetMode()==0 || this->ImageHeader->GetMode()==1)
+    {
+      filename=vtkbisImageHeader::CreateAnalyzeIMGFilename(this->FilePrefix);
+    }
+  else
+    {
+      filename=new char[(strlen(this->FilePrefix))+1];
+      strcpy(filename,this->FilePrefix);
+    }
+  
+  //  fprintf(stderr,"Reading data from %s\n",filename);
+
+  znzFile fp = vtkbisImageHeader::SuffixOpen(filename,"rb");
+  
+  if (znz_isnull(fp))
+    {
+      char* filename2=vtkbisImageHeader::CreateFilename(filename,".IMG",".img");
+      fp=vtkbisImageHeader::SuffixOpen(filename2,"rb"); 
+      //      fprintf(stderr,"Reading data from %s\n",filename2);
+      delete [] filename2;
+	
+      if (znz_isnull(fp))
+	{
+	  vtkErrorMacro(<< "Cannot Open File " << filename );
+	  delete [] filename;
+	  this->SetErrorCode( vtkErrorCode::UnrecognizedFileTypeError );
+	  return 1;
+	}
+    }
+
+  this->UpdateProgress(0.0);
+  float oldpog=0.0;
+
+  int offsetposition=0;
+
+
+
+  this->DataFlip[0] = this->DataFlip[1] = this->DataFlip[2]=0; this->Transpose=0;
+  if (this->ImageHeader->GetMode()>0)
+    {
+      if (this->ForceStandardOrientation)
+	{
+	  //	  fprintf(stderr,"Forcing Orientation\n");
+	  this->FlipNIFTIImageAndUpdateMatrixToBioImageSuiteCoordinates();
+	}
+    }
+
+  if (this->ImageHeader->GetMode()==2)
+    {
+      znzseek (fp, this->ImageHeader->GetHeaderOffset(), 0);
+    }
+
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  this->SetErrorCode( vtkErrorCode::NoError );
+  vtkStructuredPoints *output = vtkStructuredPoints::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+  // ImageSource superclass does not do this.
+  output->ReleaseData();
+
+  this->ImageHeader->SetImageStructureFromHeader(output);
+  output->AllocateScalars();
+
+  int d[3]; output->GetDimensions(d);
+
+  switch (output->GetScalarType())
+    {
+      vtkTemplateMacro4(vtkpxAnalyzeImageSourceReadSlices, this, output,
+			fp,static_cast<VTK_TT *>(0));
+    default:
+      vtkGenericWarningMacro("Unknown input ScalarType in Write Data");
+      return 1;
+    }
+
+  // Look at Flips and modify tensor data if needed!
+  // The only changes to the raw data have to do with DataFlip
+
+  /*double spa[3];
+  output->GetSpacing(spa);
+  output->SetSpacing(spa[1],spa[0],spa[2]);
+  fprintf(stderr,"Output spacing =%.2f,%.2f,%.2f\n",spa[0],spa[1],spa[2]);*/
+
+  if (this->Transpose)
+    {
+      
+      vtkImageData* tmp=vtkImageData::New();
+      tmp->ShallowCopy(output);
+
+      vtkImagePermute* perm=vtkImagePermute::New();
+      perm->SetFilteredAxes(1,0,2);
+      perm->SetInput(tmp);
+      perm->Update();
+
+      tmp->Delete();
+      output->ShallowCopy(perm->GetOutput());
+      output->SetOrigin(0.0,0.0,0.0);
+    }
+
+
+
+  /*  output->GetSpacing(spa);
+  output->SetSpacing(spa[1],spa[0],spa[2]);
+  fprintf(stderr,"Output spacing =%.2f,%.2f,%.2f\n",spa[0],spa[1],spa[2]);*/
+
+  return 1;
+
+}
+
+// -----------------------------------------------------------------------------------
+void vtkpxAnalyzeImageSource::FlipNIFTIImageAndUpdateMatrixToBioImageSuiteCoordinates()
+{
+  //  fprintf(stderr,"In Flip NIFTI\n");
+  this->Orientation=this->ImageHeader->ForceHeaderToBioImageSuiteCoordinatesAndReturnFlips(this->DataFlip,this->Transpose);
+  //  this->Orientation=this->ImageHeader->GetOrientation();
+  //  fprintf(stderr,"Done %d,%d,%d tr=%d proent=%d was or=%d\n",this->DataFlip[0],this->DataFlip[1],this->DataFlip[2],this->Transpose,this->ImageHeader->GetOrientation(),ori);
+  return;
+}
+/*
+
+  // Step 1 : Establish actual rotation matrix
+
+  nifti_1_header* hdr=this->ImageHeader->GetRawHeader();
+  this->DataFlip[0] = this->DataFlip[1] = this->DataFlip[2]=0;
+  this->Orientation=0;
+    
+  //   METHOD 1 (the "old" way, used only when qform_code = 0):
+  if (hdr->qform_code == 0 && hdr->sform_code==0)
+      return;
+
+
+  // Method 2 and 3 Rely on First Creating a 4x4 Matrix
+  
+  mat44 original;
+  if (hdr->qform_code==0)
+    {
+      for (int ia=0;ia<=3;ia++)
+	{
+	  original.m[0][ia]=hdr->srow_x[ia];
+	  original.m[1][ia]=hdr->srow_y[ia];
+	  original.m[2][ia]=hdr->srow_z[ia];
+	  original.m[3][ia]=float(ia==3);
+	}
+    }
+  else
+    {
+      original=nifti_quatern_to_mat44(hdr->quatern_b,hdr->quatern_c,hdr->quatern_d,
+				      hdr->qoffset_x,hdr->qoffset_y,hdr->qoffset_z,
+				      fabs(hdr->pixdim[1]),fabs(hdr->pixdim[2]),fabs(hdr->pixdim[3]),
+				      hdr->pixdim[0]);
+    }
+
+  //  vtkbisImageHeader::NIFTI_print_mat44("original",original);
+
+  int icod,jcod,kcod;  nifti_mat44_to_orientation(original,&icod,&jcod,&kcod);
+  
+  //  fprintf(stderr,"Orientation icod=%d (%s), jcod=%d (%s), kcod=%d (%s)\n",	  icod,nifti_orientation_string(icod),	  jcod,nifti_orientation_string(jcod),	  kcod,nifti_orientation_string(kcod));
+  
+
+
+
+  // Step 1 -- establish orientation -- this is the direction where z axis is at
+
+  int needs_transpose=0;
+  mat44 transpose_matrix;       vtkbisImageHeader::NIFTI_identity_mat44(&transpose_matrix);
+
+  int newdim[3]; this->ImageHeader->GetDimensions(newdim);
+  int dim[3];    this->ImageHeader->GetDimensions(dim);
+
+  int do_transpose=0;
+  
+  for (int ia=0;ia<=3;ia++)
+    for (int ib=0;ib<=3;ib++)
+
+  if ( (kcod==NIFTI_I2S || kcod==NIFTI_S2I) && (icod==NIFTI_L2R || icod==NIFTI_R2L) )
+    {
+      // Axial: Z-axis along k!
+      this->Orientation=10;
+      if (icod==NIFTI_L2R)	this->DataFlip[0]=1;
+      if (jcod==NIFTI_P2A)	this->DataFlip[1]=1;
+      if (kcod==NIFTI_S2I)	this->DataFlip[2]=1;
+    }
+  else if ( (jcod==NIFTI_I2S || jcod == NIFTI_S2I) && (icod==NIFTI_L2R || icod==NIFTI_R2L))
+    {
+      // Coronal
+      this->Orientation=20;
+      if (icod==NIFTI_L2R)	this->DataFlip[0]=1;
+      if (jcod==NIFTI_I2S)	this->DataFlip[1]=1;
+      if (kcod==NIFTI_P2A)	this->DataFlip[2]=1;
+    }
+  else if ((jcod==NIFTI_I2S || jcod == NIFTI_S2I) && (kcod==NIFTI_L2R || kcod==NIFTI_R2L))
+    {
+      this->Orientation=30;
+      if (icod==NIFTI_P2A)	this->DataFlip[0]=1;
+      if (jcod==NIFTI_S2I)	this->DataFlip[1]=1;
+      if (kcod==NIFTI_R2L)	this->DataFlip[2]=1;
+    } 
+  // From Here we are in non_standard orientations and need transpose and flip !!!
+  else if ( (kcod==NIFTI_I2S || kcod==NIFTI_S2I) && (jcod==NIFTI_L2R || jcod==NIFTI_R2L) )
+    {
+      this->Orientation=10;
+      // This is a transposed axial ....
+      // Step 1 -- switch x and y
+      transpose_matrix.m[0][0]=0;      transpose_matrix.m[0][1]=1;
+      transpose_matrix.m[1][0]=1;      transpose_matrix.m[1][1]=0;
+      newdim[1]=dim[0]; newdim[0]=dim[1];
+      
+      // Step 2 -- check coordinates as before
+      if (jcod==NIFTI_L2R)	this->DataFlip[0]=1;
+      if (icod==NIFTI_P2A)	this->DataFlip[1]=1;
+      if (kcod==NIFTI_S2I)	this->DataFlip[2]=1;
+
+      do_transpose=1;
+    }
+  else  if ( (jcod==NIFTI_I2S || jcod == NIFTI_S2I) && (kcod==NIFTI_L2R || kcod==NIFTI_R2L))
+    {
+      this->Orientation=20;
+      // This is a transposed coronal ....
+      // Step 1 -- switch x and z
+      transpose_matrix.m[0][0]=0;      transpose_matrix.m[0][2]=1;
+      transpose_matrix.m[2][0]=1;      transpose_matrix.m[2][2]=0;
+      newdim[0]=dim[2]; newdim[2]=dim[0];
+      
+      // Step 2 -- check coordinates as before
+      if (kcod==NIFTI_L2R)	this->DataFlip[0]=1;
+      if (jcod==NIFTI_I2S)	this->DataFlip[1]=1;
+      if (icod==NIFTI_P2A)	this->DataFlip[2]=1;
+
+      do_transpose=1;
+    }
+  else  if ((kcod==NIFTI_I2S || kcod == NIFTI_S2I) && (jcod==NIFTI_L2R || jcod==NIFTI_R2L))
+    {
+      this->Orientation = 30;
+      // This is a transposed sagital ....
+      // Step 1 -- switch y and z
+      transpose_matrix.m[1][1]=0;      transpose_matrix.m[1][2]=1;
+      transpose_matrix.m[2][1]=1;      transpose_matrix.m[2][2]=0;
+      newdim[1]=dim[2]; newdim[2]=dim[1];
+
+      // Step 2 -- check coordinates as before
+      if (icod==NIFTI_P2A)	this->DataFlip[0]=1;
+      if (kcod==NIFTI_S2I)	this->DataFlip[1]=1;
+      if (jcod==NIFTI_R2L)	this->DataFlip[2]=1;
+
+      do_transpose=1;
+    }
+  else
+    {
+      fprintf(stderr,"Can't handle this orientation ... not sure what to do\n");
+      fprintf(stderr,"Orientation icod=%d (%s), jcod=%d (%s), kcod=%d (%s)\n",
+	      icod,nifti_orientation_string(icod),
+	      jcod,nifti_orientation_string(jcod),
+	      kcod,nifti_orientation_string(kcod));
+      return;
+    }
+
+  //  fprintf(stderr,"On to computing flips etc, Orientation=%d (flips=%d,%d,%d) do_transpose=%d\n",
+  //	  this->Orientation,this->DataFlip[0],this->DataFlip[1],this->DataFlip[2],do_transpose);
+
+  // Now we have the data flips we need to figure out what to do
+  // Original matrix is  xyz= orig * ijk
+  // Need     new matrix xyz= new  * i'j'k'
+  // Which is            ijk= (flip * transpose) i'j'k'
+  //
+  // new = orig * flip * transpose
+  // Key is to find flip and transpose matrices !!!!!
+  
+  mat44 flip;  vtkbisImageHeader::NIFTI_identity_mat44(&flip);
+  //  vtkbisImageHeader::NIFTI_print_mat44("flip matrix 1",flip);
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (this->DataFlip[ia]==1)
+	{
+	  flip.m[ia][ia]=-1.0;
+	  flip.m[ia][3] = newdim[ia]-1;
+	}
+    }
+  //  vtkbisImageHeader::NIFTI_print_mat44("flip matrix",flip);
+  mat44 mapping=vtkbisImageHeader::NIFTI_mat44_mmul(flip,transpose_matrix);
+  this->ImageHeader->ModifyOrientation(this->Orientation,mapping,this->DataFlip,do_transpose);
+}
+										     
+*/
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxAnalyzeImageSource.h b/bioimagesuite30_src/Common/vtkpxAnalyzeImageSource.h
new file mode 100644
index 0000000..d3e7be2
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxAnalyzeImageSource.h
@@ -0,0 +1,183 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAnalyzeStructuredPointsReader.h,v $
+  Language:  C++
+  Date:      $Date: 2002/08/09 20:40:16 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxAnalyzeImageSource - reads analyze (or binary) 3d images 
+// .SECTION Description
+// This class reads analyze (.hdr,.img) 3D/4D images from files
+// By manually setting the header information, it can also read binary images stored in a single file
+// The output of this class is vtkStructuredPoints (either uchar,short,float)
+// It can handle byteswapping automatically in the case of analyze image input
+// and can read gzipped compressed files directly (automatically adds .gz suffix if needed)
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// This uses the pxutil library -- for analyze header 
+//
+// .SECTION See Also
+//  vtkpxAnalyzeImageWriter vtkVolume16Reader
+
+
+#ifndef __vtkpxAnalyzeImageSource
+#define __vtkpxAnalyzeImageSource
+
+#include <stdio.h>
+
+#include "vtkStructuredPointsReader.h"
+#include "vtkbisImageHeader.h"
+#include "vtkConfigure.h"
+#include "vtkStructuredPoints.h"
+
+
+
+class vtkDataArray;
+
+class vtkpxAnalyzeImageSource : public vtkStructuredPointsReader
+{
+public:
+  vtkTypeMacro(vtkpxAnalyzeImageSource,vtkStructuredPointsReader);
+  static vtkpxAnalyzeImageSource* New();
+
+  // Description:
+  // Convenience Routine for analyze images -- simply use Load("fname.hdr")
+  virtual int  Load(const char* fname);
+
+  // Description:
+  // Reads Header first set using SetFilePrefix
+  virtual int  ReadHeaderFile();
+
+  // Description:
+  // Get the orientation from analyze header 0=axial 1=coronal 2=saggital (default=0) 3=polar (ultrasound)
+  // see the newer definitions in vtkbisImageHeader
+  vtkGetMacro(Orientation,int);
+  vtkSetMacro(Orientation,int);
+
+  // Description:
+  // Specify the flips for the data.
+  vtkSetVector3Macro(DataFlip,int);
+  vtkGetVectorMacro(DataFlip,int,3);
+
+  // Description:
+  // If Tranpose = 1 permute x and y axis
+  vtkGetMacro(Transpose,int);
+
+  // Description:
+  // Intensity = Shift+Input*scale
+  vtkSetMacro(IntShift,double);
+  vtkGetMacro(IntShift,double);
+  vtkSetMacro(IntScale,double);
+  vtkGetMacro(IntScale,double);
+
+  // Description:
+  // Specify file prefix for the image file(s).
+  vtkSetStringMacro(FilePrefix);
+  vtkGetStringMacro(FilePrefix);
+
+  // Description:
+  // Force Image to BioImage Suite Standard Orientations
+  // default is ON
+  vtkGetMacro(ForceStandardOrientation,int);
+  vtkSetClampMacro(ForceStandardOrientation,int,0,1);
+  vtkBooleanMacro(ForceStandardOrientation,int);
+
+
+  // Description:
+  // Header
+  vtkGetObjectMacro(ImageHeader,vtkbisImageHeader);
+
+  // Description:
+  // Read the meta information from the file.  This needs to be public to it
+  // can be accessed by vtkDataSetReader.
+  virtual int ReadMetaData(vtkInformation *outInfo);
+
+
+
+
+protected:
+  //BTX
+  int read_volume_ok;
+  double IntShift;
+  double IntScale;
+  int    Orientation;
+
+  char *FilePrefix;
+  char* FilePattern;
+  int   DataFlip[3];
+  int ForceStandardOrientation;
+  int   Transpose;
+  vtkbisImageHeader* ImageHeader;
+  //ETX
+
+  // ---------------------------------------------
+  vtkpxAnalyzeImageSource();
+  virtual ~vtkpxAnalyzeImageSource();
+
+  // Description:
+  // Fix Output Flips and Rotations for incoming NIFTI images
+  virtual void FlipNIFTIImageAndUpdateMatrixToBioImageSuiteCoordinates();
+
+
+  // Description:
+  // This used to be "Execute"
+  virtual int RequestData(vtkInformation *, vtkInformationVector **,
+                          vtkInformationVector *);
+
+
+
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxAnalyzeImageSourceOld.cpp b/bioimagesuite30_src/Common/vtkpxAnalyzeImageSourceOld.cpp
new file mode 100644
index 0000000..cb9d25b
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxAnalyzeImageSourceOld.cpp
@@ -0,0 +1,672 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+#include "vtkpxAnalyzeImageSourceOld.h"
+#include "vtkUnsignedShortArray.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkShortArray.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxImageComponentsToFrames.h"
+#include "vtkPointData.h"
+#include "vtkImageShiftScale.h"
+#include "vtkInformation.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+using namespace bioimagesuite_legacy;
+
+//------------------------------------------------------------------------------
+vtkpxAnalyzeImageSourceOld* vtkpxAnalyzeImageSourceOld::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxAnalyzeImageSourceOld");
+  if(ret)
+    {
+      return (vtkpxAnalyzeImageSourceOld*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxAnalyzeImageSourceOld;
+}
+
+// Construct object with NULL file prefix; file pattern "%s.%d"; image range 
+// set to (1,1); data origin (0,0,0); data spacing (1,1,1); no data mask;
+// header size 0; and byte swapping turned off.
+
+vtkpxAnalyzeImageSourceOld::vtkpxAnalyzeImageSourceOld()
+{
+  this->FilePrefix = NULL;
+  this->FilePattern = new char[strlen("%s.%d") + 1];
+    strcpy (this->FilePattern, "%s.%d");
+  this->ImageRange[0] = this->ImageRange[1] = 1;
+  this->DataOrigin[0] = this->DataOrigin[1] = this->DataOrigin[2] = 0.0;
+  this->DataSpacing[0] = this->DataSpacing[1] = this->DataSpacing[2] = 1.0;
+
+  this->HeaderSize = 0;
+  this->SwapBytes = 0;
+  this->FileType=2;
+  this->DataDimensions[0] = this->DataDimensions[1] = 0;
+  this->SetFilePattern ("%s.img");
+  this->read_volume_ok=0;
+  this->AnalyzeMode=1;
+  this->NumTimeFrames=1;
+  this->Orientation=0; // Axial
+  this->ForceOutputToShort=0;
+  this->MultipleFramesAsComponents=1;
+
+  this->SetNumberOfInputPorts(0);
+
+}
+
+
+vtkpxAnalyzeImageSourceOld::~vtkpxAnalyzeImageSourceOld()
+{
+  if (this->FilePrefix)
+    delete [] this->FilePrefix;
+    
+  delete [] this->FilePattern;
+}
+
+//------------------------------------------------------------------------------
+// Specify the input data or filter.
+
+// Read an analyze header file
+// ---------------------------
+int vtkpxAnalyzeImageSourceOld::ReadHeaderFile()
+{
+  anaimagedata *hdr=new anaimagedata;
+
+  int bits=readanahdr(this->FilePrefix,hdr);
+
+  if (bits==0)
+      {
+	delete hdr;
+	return 0;
+      }
+
+  this->read_volume_ok=1;
+  this->SetDataDimensions(hdr->xsize,hdr->ysize);
+  this->SetImageRange(1,hdr->zsize*hdr->tsize);
+  this->SetNumTimeFrames(hdr->tsize);
+
+  if (hdr->xpix>0.01)
+      {
+	this->SetDataSpacing(hdr->xpix,hdr->ypix,hdr->zpix);
+      }
+  else
+      {
+	this->SetDataSpacing(1.0,1.0,1.0);
+      }
+  
+  if (bits<0)
+    {
+      bits=-bits;
+      this->SwapBytes = 1;
+    }
+  else
+      this->SwapBytes = 0;
+
+  this->Orientation=hdr->orient;
+  //  fprintf(stderr,"Reading Image Orientation =%d\n",this->Orientation);
+
+  if (bits==1)
+    this->FileType=0;
+  else if (bits<=8)
+    this->FileType=1;
+  else if (bits==32)
+    this->FileType=4;
+  else if (bits==31)
+    this->FileType=3;
+  else 
+    this->FileType=2;
+
+  delete hdr;
+  this->AnalyzeMode=1;
+  return bits;
+}
+
+
+void vtkpxAnalyzeImageSourceOld::SetHeaderInfo(int width,int height,int depth,int swap,int bytes)
+{
+  this->read_volume_ok=1;
+  this->SetDataDimensions(width,height);
+  this->SetImageRange(1,depth);
+
+  if (swap)
+      this->SwapBytes=1;
+  else
+      this->SwapBytes=0;
+
+  this->FileType=Irange(bytes,1,4);
+  /*  if (this->FileType==3)
+      this->FileType=1;*/
+
+  this->AnalyzeMode=0;
+}
+
+
+void vtkpxAnalyzeImageSourceOld::SetHeaderInfo(int width,int height,int depth,int nframes,int swap,int bytes)
+{
+  if (nframes>0)
+      {
+	this->SetHeaderInfo(width,height,depth*nframes,swap,bytes);
+	this->NumTimeFrames=nframes;
+      }
+  else
+      {
+	this->SetHeaderInfo(width,height,depth,swap,bytes);
+	this->NumTimeFrames=1;
+      }
+}
+
+void vtkpxAnalyzeImageSourceOld::SetVoxelDimensions(float vox1,float vox2,float vox3)
+{
+  this->SetDataSpacing(vox1,vox2,vox3);
+}
+
+int  vtkpxAnalyzeImageSourceOld::GetNumTimeFrames()
+{
+  return this->NumTimeFrames;
+}
+
+void vtkpxAnalyzeImageSourceOld::SetNumTimeFrames(int t)
+{
+  if (t<1)
+      return;
+
+  this->NumTimeFrames=t;
+}
+
+
+int vtkpxAnalyzeImageSourceOld::GetNumSlices()
+{
+  int range[2]; 
+  this->GetImageRange(range);
+
+  int s=range[1]-range[0]+1;
+  if (s==1)
+      return 1;
+  else
+      return s/this->NumTimeFrames;
+
+}
+
+vtkDataArray* vtkpxAnalyzeImageSourceOld::ReadVolume(int first, int last)
+{
+
+  if (this->read_volume_ok==0)
+      {
+	vtkDebugMacro(<<"Not updating");
+	return NULL;      
+      }
+
+  if (!this->FilePrefix)
+    return NULL;
+
+
+  char* filename;
+  if (this->AnalyzeMode==1)
+      {
+	filename=anacreateimagefilename(FilePrefix);
+      }
+  else
+      {
+	filename=new char[(strlen(FilePrefix))+1];
+	strcpy(filename,FilePrefix);
+      }
+
+
+  int numPts = this->DataDimensions[0] * this->DataDimensions[1];
+  int numberSlices = last - first+1;
+
+  vtkDataArray *scalars = NULL;
+  char*  charslice=NULL;
+  short *slice=NULL;
+  float *floatslice=NULL;
+  int   *intslice=NULL;
+
+  if (FileType==1 || FileType==0)
+      {
+	scalars = vtkDataArray::CreateDataArray(VTK_UNSIGNED_CHAR);
+	scalars->SetNumberOfComponents(1);
+	scalars->SetNumberOfTuples(numPts * numberSlices);
+	charslice = (char *)scalars->GetVoidPointer(0);
+      }
+  else if (FileType==2)
+      {
+	scalars = vtkDataArray::CreateDataArray(VTK_SHORT);
+	scalars->SetNumberOfComponents(1);
+	scalars->SetNumberOfTuples(numPts * numberSlices);
+	slice = (short *)scalars->GetVoidPointer(0);
+      }
+  else if (FileType==3)
+    {
+      scalars = vtkDataArray::CreateDataArray(VTK_INT);
+      scalars->SetNumberOfComponents(1);
+      scalars->SetNumberOfTuples(numPts * numberSlices);
+      intslice = (int *)scalars->GetVoidPointer(0);
+    }
+  else
+    {
+      scalars = vtkDataArray::CreateDataArray(VTK_FLOAT);
+      scalars->SetNumberOfComponents(1);
+      scalars->SetNumberOfTuples(numPts * numberSlices);
+      floatslice = (float *)scalars->GetVoidPointer(0);
+    }
+  
+  //  fprintf(stderr,"Number of Tuples (%d)\n",scalars->GetNumberOfTuples());
+
+  gzFile fp = gzsuffixopen(filename,"rb");
+  
+  if ( fp==Z_NULL)
+      {
+	char* filename2=anacreatefilename(filename,".IMG",".img");
+	fp=gzsuffixopen(filename2,"rb"); 
+	//	fprintf(stderr,"Trying %s instead of %s\n",filename2,filename);
+	delete [] filename2;
+	
+	if ( fp==Z_NULL)
+	  {
+	    delete [] filename;
+	    vtkErrorMacro(<< "Cannot Open File " << filename );
+	    return NULL;
+	  }
+      }
+
+  this->UpdateProgress(0.0);
+  float oldpog=0.0;
+
+  int offsetposition=0;
+
+  for (int sliceNumber = first; sliceNumber <= last; sliceNumber++) 
+    {
+      
+      int skip=0;
+      if (sliceNumber==first)
+	{
+	  int sz=this->FileType;
+	  if (FileType==3)
+	    sz=4;
+	  if (first!=1)
+	    skip=this->DataDimensions[0]*this->DataDimensions[1]*(first-1)*sz;
+	  skip+=this->HeaderSize;
+	}
+      
+      
+      float pog=float(sliceNumber-first)/float(last-first+1);
+      //fprintf(stderr,"Progress=%f\n",pog);
+      if ( (pog-oldpog)>0.1)
+	{
+	  this->UpdateProgress(pog);
+	  oldpog=pog;
+	}
+      
+      if (FileType==1 || FileType == 0 )
+	ReadCharBinaryImage (fp, &charslice[offsetposition], this->DataDimensions[0], 
+			     this->DataDimensions[1], 
+			     skip);
+      else if (FileType==2 )
+	ReadBinaryImage (fp, &slice[offsetposition], this->DataDimensions[0], 
+			 this->DataDimensions[1], 
+			 skip,this->SwapBytes);
+      else if (FileType==3)
+	ReadIntBinaryImage (fp, &intslice[offsetposition], this->DataDimensions[0], 
+			    this->DataDimensions[1], 
+			    skip,this->SwapBytes);
+      else
+	this->ReadFloatBinaryImage (fp, &floatslice[offsetposition], this->DataDimensions[0], 
+				    this->DataDimensions[1], 
+				    skip,this->SwapBytes);
+      offsetposition+=numPts;	      
+    }
+    
+
+  gzclose (fp);
+  
+  delete [] filename;
+  
+  this->UpdateProgress(1.0);
+  this->read_volume_ok=0;
+
+  if (Debug)
+    {
+      double rv[2];
+      scalars->GetRange(rv);
+      
+      int dtype=scalars->GetDataType();
+      int bits2;
+      if (dtype==VTK_UNSIGNED_CHAR || dtype==VTK_CHAR)
+	bits2=8;
+      else if (dtype==VTK_SHORT || dtype==VTK_UNSIGNED_SHORT)
+	bits2=16;
+      else if (dtype==VTK_INT)
+	bits2=31;
+      else if (dtype==VTK_FLOAT)
+	bits2=32;
+      
+      char line[180];
+      sprintf(line,"\n%s\n Dimensions %d x %d x %d (%d) (%5.2f %5.2f %5.2f)\n Bits=%d (%d) Swap=%d Range=%f:%f\n",
+	      this->FilePrefix,this->DataDimensions[0],this->DataDimensions[1],this->ImageRange[1]-this->ImageRange[0]+1,numberSlices,
+	      this->DataSpacing[0],this->DataSpacing[1],this->DataSpacing[2],
+	      8*FileType,bits2,this->SwapBytes,rv[0],rv[1]);
+      fprintf(stderr,"out=%s\n",line);
+    }  
+  return scalars;
+}
+//------------------------------------------------------------------------------
+int vtkpxAnalyzeImageSourceOld:: ReadBinaryImage (gzFile fp,  short *pixels, int xsize, 
+					       int ysize, int skip, int swapBytes)
+{
+
+  int numShorts = xsize * ysize;
+  
+  if (skip>0)
+    gzseek (fp, skip, 0);
+  
+  gzread(fp,pixels,numShorts*2);
+
+  if (swapBytes && FileType==2) 
+      {
+	unsigned char *bytes = (unsigned char *) pixels;
+	unsigned char tmp;
+	int i;
+	for (i = 0; i < numShorts; i++, bytes += 2) 
+	    {
+	      tmp = *bytes; 
+	      *bytes = *(bytes + 1); 
+	      *(bytes + 1) = tmp;
+	    }
+      }
+
+
+  return 1;
+}
+//------------------------------------------------------------------------------
+int vtkpxAnalyzeImageSourceOld:: ReadCharBinaryImage (gzFile fp,  char *pixels, int xsize, 
+						   int ysize, int skip)
+{
+
+  int numChars = xsize * ysize;
+  
+  if (skip>0)
+    gzseek (fp, skip, 0);
+  
+  if (FileType==0)
+    {
+      const unsigned char mask[8]={ 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 };
+      int numBits=numChars;
+      int numChars2=(numBits+7)/8;
+      unsigned char *charPtr=new unsigned char[numChars];
+      gzread(fp,&charPtr[0],numChars2);
+      for (int index=0;index<numChars2;index++)
+	{
+	  int i=index/8;
+	  int j=7-(index-i*8);
+	  pixels[index]=(char) (( charPtr[i] & mask[j] )>0);
+	}
+      delete [] charPtr;
+    }
+  else
+    {
+      gzread(fp,pixels,numChars);
+    }
+
+
+  return 1;
+}
+//------------------------------------------------------------------------------
+
+int vtkpxAnalyzeImageSourceOld:: ReadFloatBinaryImage (gzFile fp,  float *pixels, int xsize, 
+					      int ysize, int skip, int swapBytes)
+{
+  int numFloats = xsize * ysize;
+  
+  if (skip)
+      gzseek (fp, skip, 0);
+ 
+  gzread(fp,&pixels[0],numFloats*4);
+
+
+  if (swapBytes) 
+      {
+	unsigned char *bytes = (unsigned char *) pixels;
+	unsigned char tmp;
+	int i;
+	for (i = 0; i < numFloats; i++, bytes += 4) 
+	    {
+	      tmp = *bytes; 
+	      *bytes = *(bytes + 3); 
+	      *(bytes + 3) = tmp;
+
+	      tmp = *(bytes+1);
+	      *(bytes+1)=*(bytes+2);
+	      *(bytes+2)=tmp;
+	    }
+      }
+    
+  return 1;
+}
+
+//------------------------------------------------------------------------------
+int vtkpxAnalyzeImageSourceOld:: ReadIntBinaryImage (gzFile fp,  int *pixels, int xsize, 
+						  int ysize, int skip, int swapBytes)
+{
+  int numInts = xsize * ysize;
+  
+  if (skip)
+      gzseek (fp, skip, 0);
+ 
+  gzread(fp,&pixels[0],numInts*4);
+
+
+  if (swapBytes) 
+      {
+	unsigned char *bytes = (unsigned char *) pixels;
+	unsigned char tmp;
+	int i;
+	for (i = 0; i < numInts; i++, bytes += 4) 
+	    {
+	      tmp = *bytes; 
+	      *bytes = *(bytes + 3); 
+	      *(bytes + 3) = tmp;
+
+	      tmp = *(bytes+1);
+	      *(bytes+1)=*(bytes+2);
+	      *(bytes+2)=tmp;
+	    }
+      }
+    
+  return 1;
+}
+
+//------------------------------------------------------------------------------
+void vtkpxAnalyzeImageSourceOld::Execute()
+{
+
+  if (this->FilePrefix == NULL) 
+      {
+	vtkErrorMacro(<< "FilePrefix is NULL");
+	return;
+      }
+  
+  if (this->HeaderSize < 0) 
+      {
+	vtkErrorMacro(<< "HeaderSize " << this->HeaderSize << " must be >= 0");
+	return;
+      }
+  
+  if (this->DataDimensions[0] <= 0 || this->DataDimensions[1] <= 0) 
+      {
+	vtkErrorMacro(<< "x, y dimensions " << this->DataDimensions[0] << ", " << this->DataDimensions[1] 
+		      << "must be greater than 0.");    
+	return;
+      } 
+  
+  int first = this->ImageRange[0];
+  int last = this->ImageRange[1];
+
+  if (this->FileType==0)
+    first=1;
+
+  vtkDataArray* tmpScalars = this->ReadVolume(first, last);
+  vtkDataArray* newScalars=tmpScalars;
+  int deletenewscalars=0;
+
+
+  //  fprintf(stderr,"Read %d x %d scalars\n",tmpScalars->GetNumberOfTuples(),tmpScalars->GetNumberOfComponents());
+  
+  if (!tmpScalars)
+    return;
+
+  if (this->ForceOutputToShort==1)
+    {
+      if (newScalars->GetDataType()==VTK_FLOAT)
+	{
+	  newScalars=vtkDataArray::CreateDataArray(VTK_SHORT);
+	  newScalars->DeepCopy(tmpScalars);
+	  deletenewscalars=1;
+	}
+    }
+
+  int dimensions[3]; 
+  dimensions[0] = this->DataDimensions[0];
+  dimensions[1] = this->DataDimensions[1];
+  dimensions[2] = this->ImageRange[1] - this->ImageRange[0] + 1;
+
+  vtkImageData* output=this->GetOutput();
+  output->SetSpacing(this->DataSpacing);
+  output->SetOrigin(this->DataOrigin);
+  output->SetScalarType(newScalars->GetDataType());
+  
+  if (this->MultipleFramesAsComponents==1 && this->NumTimeFrames>1)
+    {
+      int dim[3];
+      for (int ia=0;ia<=2;ia++)
+	dim[ia]=dimensions[ia];
+      dim[2]/=this->NumTimeFrames;
+  
+      output->SetNumberOfScalarComponents(this->NumTimeFrames);
+      output->SetDimensions(dim);
+      output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+      output->AllocateScalars();
+      
+      for (int comp=0;comp<NumTimeFrames;comp++)
+	{
+	  int index=comp*dim[0]*dim[1]*dim[2];
+	  for (int k=0;k<dim[2];k++)
+	    for (int j=0;j<dim[1];j++)
+	      for (int i=0;i<dim[0];i++)
+		{
+		  output->SetScalarComponentFromDouble(i,j,k,comp,newScalars->GetComponent(index,0));
+		  ++index;
+		}
+	}
+      
+    }
+  else
+    {
+      output->SetDimensions(dimensions);
+      output->SetWholeExtent(0,dimensions[0]-1,0,dimensions[1]-1,0,dimensions[2]-1);
+      output->SetNumberOfScalarComponents(newScalars->GetNumberOfComponents());
+      output->GetPointData()->SetScalars(newScalars);
+
+    }
+     
+  if (deletenewscalars)
+    newScalars->Delete();
+  tmpScalars->Delete();
+    
+
+
+}
+//------------------------------------------------------------------------------
+void vtkpxAnalyzeImageSourceOld::ExecuteInformation()
+{
+  //  fprintf(stderr,"IN Execute Information\n");
+  vtkImageData *output = this->GetOutput();
+
+  
+  int dim[3];
+  dim[0]=this->DataDimensions[0];
+  dim[1]=this->DataDimensions[1];
+
+  //  output->DebugOn();
+
+  if (this->MultipleFramesAsComponents)
+    {
+      output->SetNumberOfScalarComponents(this->NumTimeFrames);
+      dim[2]=(this->ImageRange[1]-this->ImageRange[0]+1)/this->NumTimeFrames;
+    }
+  else
+    {
+      output->SetNumberOfScalarComponents(1);
+      dim[2]=(this->ImageRange[1]-this->ImageRange[0]+1);
+    }
+
+  output->SetWholeExtent(0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1);
+  output->SetSpacing(this->DataSpacing);
+  output->SetOrigin(this->DataOrigin);
+  output->SetDimensions(dim);
+  
+  if (this->FileType<1)
+    output->SetScalarType(VTK_UNSIGNED_CHAR);
+  else if (this->FileType==2)
+    output->SetScalarType(VTK_SHORT);
+  else
+    output->SetScalarType(VTK_FLOAT);
+
+  //  output->DebugOff();
+  //  fprintf(stderr,"IN Execute Information Done\n");
+}
+
+//------------------------------------------------------------------------------
+int vtkpxAnalyzeImageSourceOld::Load(const char *ana)
+{
+  this->SetFilePrefix(ana);
+  int ok=this->ReadHeaderFile();
+  if (ok!=0)
+      this->Update();
+  return ok;
+}
+//------------------------------------------------------------------------------
+int vtkpxAnalyzeImageSourceOld::FillOutputPortInformation(int port, vtkInformation* info)
+{
+  if(!this->Superclass::FillOutputPortInformation(port, info))
+    {
+    return 0;
+    }
+  info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkImageData");
+  return 1;
+}
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxAnalyzeImageSourceOld.h b/bioimagesuite30_src/Common/vtkpxAnalyzeImageSourceOld.h
new file mode 100644
index 0000000..60f8313
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxAnalyzeImageSourceOld.h
@@ -0,0 +1,191 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkpxAnalyzeImageSourceOld
+#define __vtkpxAnalyzeImageSourceOld
+
+#include <stdio.h>
+#include "vtkImageSource.h"
+#include "pxutil.h"
+#include "vtkConfigure.h"
+#include "vtkImageData.h"
+
+class vtkDataArray;
+
+class vtkpxAnalyzeImageSourceOld : public vtkImageSource
+{
+public:
+  vtkTypeMacro(vtkpxAnalyzeImageSourceOld,vtkImageSource);
+  static vtkpxAnalyzeImageSourceOld* New();
+
+  // Description:
+  // Convenience Routine for analyze images -- simply use Load("fname.hdr")
+  virtual int  Load(const char* fname);
+
+  // Description:
+  // Reads Header first set using SetFilePrefix
+  virtual int  ReadHeaderFile();
+
+  // Description:
+  // Set HeaderInfo manually for binary files
+  virtual void SetHeaderInfo(int width,int height,int depth,int swap,int bytes);
+  virtual void SetHeaderInfo(int width,int height,int depth,int nframes,int swap,int bytes);
+  virtual void SetVoxelDimensions(float vox1,float vox2,float vox3);
+
+  // Description:
+  // Set Number of TimeFrames for binary files (in case of 4D Images)
+  virtual void SetNumTimeFrames(int timeframes);
+
+  // Description:
+  // In case of 4D Images returns number of timeframes
+  virtual int  GetNumTimeFrames();
+
+  // Description:
+  // In case of 4D Images returns number of slices/frame
+  virtual int  GetNumSlices();
+
+  // Description:
+  // Get the orientation from analyze header 0=axial 1=coronal 2=saggital (default=0) 3=polar (ultrasound)
+  vtkGetMacro(Orientation,int);
+  vtkSetMacro(Orientation,int);
+
+  // Description:
+  // Get the file type 1=bit 2=short 3=unsigned int 4=float
+  vtkGetMacro(FileType,int);
+  vtkSetClampMacro(FileType,int,1,4);
+
+
+  // Description:
+  // Force the output scalars to have type short
+  vtkGetMacro(ForceOutputToShort,int);
+  vtkSetMacro(ForceOutputToShort,int);
+  vtkBooleanMacro(ForceOutputToShort,int);
+
+  // Description:
+  // SaveMultiple Frames As Components 
+  vtkGetMacro(MultipleFramesAsComponents,int);
+  vtkSetClampMacro(MultipleFramesAsComponents,int,0,1);
+  vtkBooleanMacro(MultipleFramesAsComponents, int);
+
+  // Description:
+  // Specify the dimensions for the data.
+  vtkSetVector2Macro(DataDimensions,int);
+  vtkGetVectorMacro(DataDimensions,int,2);
+
+  // Description:
+  // Specify the number of bytes to seek over at start of image.
+  vtkSetMacro(HeaderSize,int);
+  vtkGetMacro(HeaderSize,int);
+
+  // Description:
+  // Specify file prefix for the image file(s).
+  vtkSetStringMacro(FilePrefix);
+  vtkGetStringMacro(FilePrefix);
+
+  // Description:
+  // The sprintf format used to build filename from FilePrefix and number.
+  vtkSetStringMacro(FilePattern);
+  vtkGetStringMacro(FilePattern);
+
+  // Description:
+  // Set the range of files to read.
+  vtkSetVector2Macro(ImageRange,int);
+  vtkGetVectorMacro(ImageRange,int,2);
+
+  // Description:
+  // Specify the spacing for the data.
+  vtkSetVector3Macro(DataSpacing,double);
+  vtkGetVectorMacro(DataSpacing,double,3);
+
+  // Description:
+  // Specify the origin for the data.
+  vtkSetVector3Macro(DataOrigin,double);
+  vtkGetVectorMacro(DataOrigin,double,3);
+
+  // Description:
+  // Turn on/off byte swapping.
+  vtkSetMacro(SwapBytes,int);
+  vtkGetMacro(SwapBytes,int);
+  vtkBooleanMacro(SwapBytes,int);
+
+
+  // Pipeline Stuff
+  virtual int FillOutputPortInformation(int port, vtkInformation* info);
+  
+
+protected:
+  //BTX
+  int read_volume_ok;
+  int FileType;
+  int AnalyzeMode;
+  int NumTimeFrames;
+  int Orientation;
+  int ForceOutputToShort;
+  int MultipleFramesAsComponents;
+
+  int  DataDimensions[2];
+  int   SwapBytes,HeaderSize;
+
+
+  char *FilePrefix;
+  char *FilePattern;
+  int ImageRange[2];
+  double DataSpacing[3];
+  double DataOrigin[3];
+
+
+  vtkpxAnalyzeImageSourceOld();
+  virtual ~vtkpxAnalyzeImageSourceOld();
+  //ETX
+
+  virtual void Execute();
+  virtual void ExecuteInformation();
+
+  //BTX
+  virtual vtkDataArray* ReadVolume(int FirstImage, int LastImage);
+  int ReadBinaryImage(gzFile fp,  short *pixels, int xsize, int ysize,  
+		      int skip, int swapBytes);
+
+  int ReadCharBinaryImage(gzFile fp,  char *pixels, int xsize, int ysize,  
+		      int skip);
+
+  int ReadIntBinaryImage(gzFile fp,  int *pixels, int xsize, int ysize,  
+			 int skip, int swapBytes);
+  
+  int ReadFloatBinaryImage(gzFile fp,  float *pixels, int xsize, int ysize,  
+			   int skip, int swapBytes);
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxAnalyzeImageWriter.cpp b/bioimagesuite30_src/Common/vtkpxAnalyzeImageWriter.cpp
new file mode 100644
index 0000000..f64f073
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxAnalyzeImageWriter.cpp
@@ -0,0 +1,354 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+/*=========================================================================*/
+#include "vtkpxAnalyzeImageWriter.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkbisImageHeader.h"
+
+int vtkpxAnalyzeImageWriter::ForceOutputFileFormat=0;
+  //------------------------------------------------------------------------------
+vtkpxAnalyzeImageWriter* vtkpxAnalyzeImageWriter::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxAnalyzeImageWriter");
+  if(ret)
+      {
+	return (vtkpxAnalyzeImageWriter*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxAnalyzeImageWriter;
+}
+//------------------------------------------------------------------------------
+vtkpxAnalyzeImageWriter::vtkpxAnalyzeImageWriter()
+{
+  this->Compression=0;
+  this->ByteSwap=0;
+  this->Orientation=0; // Axial
+  this->SaveStatus=0;
+  this->ImageHeader=NULL;
+
+  // Messy Initialization for DLLS
+  if (vtkpxAnalyzeImageWriter::ForceOutputFileFormat!=1 && vtkpxAnalyzeImageWriter::ForceOutputFileFormat!=2)
+    vtkpxAnalyzeImageWriter::ForceOutputFileFormat=0;
+}
+
+vtkpxAnalyzeImageWriter::~vtkpxAnalyzeImageWriter()
+{
+  if (this->ImageHeader!=NULL)
+    this->ImageHeader->Delete();
+}
+
+void vtkpxAnalyzeImageWriter::SetImageHeader(vtkbisImageHeader* header)
+{
+  if (header==NULL)
+    return;
+
+  if (this->ImageHeader==NULL)
+    this->ImageHeader=vtkbisImageHeader::New();
+
+  this->ImageHeader->CopyHeader(header);
+}
+
+void vtkpxAnalyzeImageWriter::Save(const char* fname)
+{
+  if (fname!=NULL)
+    {
+      this->SetFileName(fname);
+      this->WriteData();
+    }
+}
+
+//----------------------------------------------------------------------------
+// From VTK vtkByteSwap originally, templated etc.
+//------------------------------------------------------------------------------
+template<class T>
+void vtkpxAnalyzeImageWriterSwapBytes(T* dt,int slicesize,int sz)
+{
+  if (sz<1)
+    return;
+
+  char* chardata=(char*)dt;
+  char one_byte=0;
+  int   totalnumbytes=slicesize*sz;
+  for (int i=0;i<totalnumbytes;i+=sz)
+    {
+      char* data=&chardata[i];
+      switch(sz)
+	{
+	case 2:
+	  one_byte = data[0]; data[0] = data[1]; data[1] = one_byte;
+	  break;
+	case 4:
+	  one_byte = data[0]; data[0] = data[3]; data[3] = one_byte;
+	  one_byte = data[1]; data[1] = data[2]; data[2] = one_byte; 
+	  break;
+	case 8:
+	  one_byte = data[0]; data[0] = data[7]; data[7] = one_byte;
+	  one_byte = data[1]; data[1] = data[6]; data[6] = one_byte;
+	  one_byte = data[2]; data[2] = data[5]; data[5] = one_byte;
+	  one_byte = data[3]; data[3] = data[4]; data[4] = one_byte; 
+	  break;
+	}
+    }
+}
+// ----------------------------------------------------------------------------
+
+// Templated Function to write out image
+template<class T>
+int vtkpxAnalyzeImageWriterWritePointer(vtkpxAnalyzeImageWriter* self,vtkImageData* img,
+					znzFile fdf,T *)
+{
+  int dim[3];  img->GetDimensions(dim);
+
+  //  fprintf(stderr,"Dimensions = %d,%d,%d\n",dim[0],dim[1],dim[2]);
+
+  int slicesize=dim[0]*dim[1];
+  T* temp = new T[slicesize];
+  int maxnumcomp=img->GetNumberOfScalarComponents();
+
+
+
+  vtkDataArray* dat=img->GetPointData()->GetScalars();
+  T* dat_point=(T*)dat->GetVoidPointer(0);
+
+  int bytes=0;
+  int sz=sizeof(T);
+  int writesize=sz*slicesize;
+
+  //  fprintf(stderr,"Writing compressed=%d maxnumcomp=%d datatypesize=%d, slicesize=%d, type=%d\n",
+  //	  compressed,maxnumcomp,sz,slicesize,dat->GetDataType());
+  
+  for (int comp=0;comp<maxnumcomp;comp++)
+    for (int slice=0;slice<dim[2];slice++)
+      {
+	int index=0;
+	for (int ib=0;ib<dim[1];ib++)
+	  {
+	    int offset=(slice*slicesize+ib*dim[0])*maxnumcomp+comp;
+	    for (int ia=0;ia<dim[0];ia++)
+	      {
+		temp[index]=dat_point[offset];
+		++index;
+		offset+=maxnumcomp;
+	      }
+	  }
+	if (self->GetByteSwap())
+	  vtkpxAnalyzeImageWriterSwapBytes(temp,slicesize,sz);
+	bytes += znzwrite(temp,1,writesize,fdf);
+	//	fprintf(stderr,"Writing Slice %d (bytes=%d)\n",slice,bytes);
+      }
+  delete [] temp;
+  return bytes;
+}
+//----------------------------------------------------------------------------
+void vtkpxAnalyzeImageWriter::WriteData()
+{
+  this->SaveStatus=0;
+  vtkImageData *input=this->GetInput(0);
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image To Save");
+      return;
+    }
+  
+  // Step 2 --- Create Header if it does not exist
+  if (this->ImageHeader==NULL)
+    this->CreateImageHeader(0);
+
+  //  fprintf(stderr,"\n\n\n  Original Header mode=%d\n\n\n",this->ImageHeader->GetMode());
+  //  this->ImageHeader->PrintHeader(0);
+
+  // Fix Header for Dimensions/Spacing/Numframes/voxel sizes etc.
+  // This is a last resort
+  this->ImageHeader->ReconcileHeader(input,0);
+
+  //  fprintf(stderr,"\n\n\n Reconciled Header mode=%d\n\n\n",this->ImageHeader->GetMode());
+  //  this->ImageHeader->PrintHeader(1);
+
+
+  if (vtkpxAnalyzeImageWriter::ForceOutputFileFormat==1 && this->ImageHeader->GetMode()!=0)
+    {
+      this->ImageHeader->SetModeToAnalyze();
+    }
+  else if (vtkpxAnalyzeImageWriter::ForceOutputFileFormat==2 && this->ImageHeader->GetMode()==0)
+    {
+      if (vtkbisImageHeader::FindExtension(this->FileName,".nii",".nii.gz")==1)
+	this->ImageHeader->SetModeToNIFTI_NII();
+      else
+	this->ImageHeader->SetModeToNIFTI_HDRIMG();
+    }
+  else if (vtkbisImageHeader::FindExtension(this->FileName,".nii",".nii.gz")==1 && 
+	   vtkpxAnalyzeImageWriter::ForceOutputFileFormat!=1 )
+    {
+      this->ImageHeader->SetModeToNIFTI_NII();
+    }
+
+  /*  if (this->ImageHeader->GetMode()==2 && this->Compression==0)
+    {
+      this->Compression=9;
+      }*/
+
+
+
+
+  if (this->ImageHeader->GetMode()==0)
+    this->WriteDataAsAnalyze();
+  else
+    this->WriteDataAsNifty();
+
+  //fprintf(stderr,"\n\n\n Final Header mode=%d\n\n\n",this->ImageHeader->GetMode());
+  //  this->ImageHeader->PrintHeader(2);
+
+}
+//----------------------------------------------------------------------------
+void vtkpxAnalyzeImageWriter::CreateImageHeader(int print)
+{
+  vtkbisImageHeader* newhead=vtkbisImageHeader::New();
+  newhead->CreateHeader(this->GetInput(0),0);
+  newhead->SetOrientation(this->Orientation);
+  this->SetImageHeader(newhead);
+  newhead->Delete();
+  if (print)
+    this->ImageHeader->PrintHeader(0);
+}
+
+//----------------------------------------------------------------------------
+void vtkpxAnalyzeImageWriter::WriteDataAsAnalyze()
+{
+  char* headername=vtkbisImageHeader::CreateAnalyzeHDRFilename(this->FileName);
+
+  
+
+  int ok=this->ImageHeader->WriteAnalyzeHeader(headername);
+
+  if (ok==0)
+    {
+      fprintf(stderr,"Failed to save analyze header in %s\n",headername);
+      delete [] headername;
+      return;
+    }
+
+  char* imgname=vtkbisImageHeader::CreateAnalyzeIMGFilename(headername);
+
+  znzFile fdf=vtkbisImageHeader::SuffixOpen(imgname,"wb",this->Compression);
+
+  switch (this->GetInput(0)->GetScalarType())
+    {
+      vtkTemplateMacro4(vtkpxAnalyzeImageWriterWritePointer, this, this->GetInput(0),
+			fdf,static_cast<VTK_TT *>(0));
+    default:
+      vtkGenericWarningMacro("Unknown input ScalarType in Write Data");
+      return;
+    }
+  
+  znzclose(fdf);
+  
+  delete [] imgname;
+  delete [] headername;
+  this->SaveStatus=1;
+}
+
+void vtkpxAnalyzeImageWriter::WriteDataAsNifty()
+{
+
+  //  this->ImageHeader->PrintHeader(1);
+  if (vtkbisImageHeader::FindExtension(this->FileName,".nii",".nii.gz")==1)
+    this->ImageHeader->SetModeToNIFTI_NII();
+  else
+    this->ImageHeader->SetModeToNIFTI_HDRIMG();
+
+  //  this->ImageHeader->SetModeToNIFTI_HDRIMG();
+  
+  // Check for hdr/img first
+  znzFile fdf;
+  if (this->ImageHeader->GetMode()==1)
+    {
+      char* headername=vtkbisImageHeader::CreateAnalyzeHDRFilename(this->FileName);
+      int ok=this->ImageHeader->WriteNIFTIHeader(headername,0);
+      if (ok==0)
+	{
+	  fprintf(stderr,"Failed to save NIFTI header in %s\n",headername);
+	  delete [] headername;
+	  return;
+	}
+      char* imgname=vtkbisImageHeader::CreateAnalyzeIMGFilename(headername);
+      fdf=vtkbisImageHeader::SuffixOpen(imgname,"wb",this->Compression);
+      delete [] imgname;
+      delete [] headername;
+    }
+  else
+    {
+      fdf=vtkbisImageHeader::SuffixOpen(this->FileName,"wb",this->Compression);
+      int ok=this->ImageHeader->WriteNIFTIHeader(fdf);
+      if (ok==0)
+	{
+	  fprintf(stderr,"Failed to save NIFTI header in %s\n",this->FileName);
+	  return;
+	}
+      this->ImageHeader->SetFileName(this->FileName);
+    }
+
+  //  this->ImageHeader->PrintHeader(1);
+
+  //  fprintf(stderr,"On to saving image %d\n",this->GetInput(0));
+
+
+  switch (this->GetInput(0)->GetScalarType())
+    {
+      vtkTemplateMacro4(vtkpxAnalyzeImageWriterWritePointer, this, this->GetInput(0),
+			fdf,static_cast<VTK_TT *>(0));
+    default:
+      vtkGenericWarningMacro("Unknown input ScalarType in Write Data");
+      return;
+    }
+  
+  znzclose(fdf);
+  this->SaveStatus=1;
+  //  this->ImageHeader->PrintHeader(1);
+}
+
+int vtkpxAnalyzeImageWriter::SetForceOutputFileFormat(int mode)
+{
+  if (mode>=0 && mode <= 2)
+    {
+      vtkpxAnalyzeImageWriter::ForceOutputFileFormat=mode;
+    }
+  return vtkpxAnalyzeImageWriter::ForceOutputFileFormat;
+}
+
+int vtkpxAnalyzeImageWriter::GetForceOutputFileFormat()
+{
+  return vtkpxAnalyzeImageWriter::ForceOutputFileFormat;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxAnalyzeImageWriter.h b/bioimagesuite30_src/Common/vtkpxAnalyzeImageWriter.h
new file mode 100644
index 0000000..8b3705b
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxAnalyzeImageWriter.h
@@ -0,0 +1,139 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAnalyzeImageWriter.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxAnalyzeImageWriter - writes vtkStructuredPoints to file
+// .SECTION Description
+// Can save compressed (gzipped) , byte swapped and multi-frame analyze images
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// This uses the pxutil library
+// .SECTION See Also
+
+
+#ifndef __vtkpxAnalyzeImageWriter_h
+#define __vtkpxAnalyzeImageWriter_h
+
+#include "vtkStructuredPointsWriter.h"
+#include "vtkbisImageHeader.h"
+
+class vtkpxAnalyzeImageWriter : public vtkStructuredPointsWriter
+{
+public:
+  static vtkpxAnalyzeImageWriter *New();
+  vtkTypeMacro(vtkpxAnalyzeImageWriter,vtkStructuredPointsWriter);
+
+  // Description:
+  // Convenience Routine: simply use Save("fname.hdr")
+  virtual void Save(const char* fname);
+
+  // Description:
+  // Set Compression Level 0=Uncompressed, 9=Maximum (adds .gz suffix if compressed)
+  vtkGetMacro(Compression,int);
+  vtkSetClampMacro(Compression,int,0,9);
+
+  // Description:
+  // Save byte-swapped if needed
+  vtkGetMacro(ByteSwap,int);
+  vtkSetClampMacro(ByteSwap,int,0,1);
+  vtkBooleanMacro(ByteSwap, int);
+
+  // Description:
+  // Save orientation 0=axial 1=coronal 2=saggital (default=0), 3=polar (ultrasound)
+  vtkGetMacro(Orientation,int);
+  vtkSetClampMacro(Orientation,int,0,3);
+
+  // Description:
+  // SaveStatus = 1 Success, 0 = failure
+  vtkGetMacro(SaveStatus,int);
+
+  // Description:
+  // Set Proper Header
+  vtkGetObjectMacro(ImageHeader,vtkbisImageHeader);
+  virtual void SetImageHeader(vtkbisImageHeader* header);
+
+
+  // Description:
+  // Set Force Output File Format
+  static int SetForceOutputFileFormat(int mode);
+  static int GetForceOutputFileFormat();
+  
+protected:
+  vtkpxAnalyzeImageWriter();
+  virtual ~vtkpxAnalyzeImageWriter();
+
+  // Description : do the work
+  void WriteData();
+  void WriteDataAsAnalyze();
+  void WriteDataAsNifty();
+
+
+  // Description:
+  // Use this to create a default header if one was not specified
+  void CreateImageHeader(int print);
+
+  //BTX
+  int Compression;
+  int ByteSwap;
+  int Orientation;
+  int SaveStatus;
+  vtkbisImageHeader* ImageHeader;
+  static int ForceOutputFileFormat;
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxAppendComponents.cpp b/bioimagesuite30_src/Common/vtkpxAppendComponents.cpp
new file mode 100644
index 0000000..2046fca
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxAppendComponents.cpp
@@ -0,0 +1,185 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAppendComponents.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:09:25 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkpxAppendComponents.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+//------------------------------------------------------------------------------
+vtkpxAppendComponents* vtkpxAppendComponents::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxAppendComponents");
+  if(ret)
+    {
+    return (vtkpxAppendComponents*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxAppendComponents;
+}
+
+// Construct object with no children.
+vtkpxAppendComponents::vtkpxAppendComponents()
+{
+
+}
+// ----------------------------------------------------------------------------
+vtkpxAppendComponents::~vtkpxAppendComponents()
+{
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxAppendComponents::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+
+  int dim_0[3];
+  this->GetImageDataInput(0)->GetDimensions(dim_0);
+  int numtotal=this->GetImageDataInput(0)->GetNumberOfScalarComponents();
+
+  for (int i=1;i<this->GetNumberOfInputPorts();i++)
+      {
+	if (this->GetImageDataInput(i)==NULL)
+	  {
+	    vtkErrorMacro(<<"No Input Image Data " << i << " !!");
+	    return;
+	  }
+	else
+	  {
+	    int dim_1[3];
+	    this->GetImageDataInput(i)->GetDimensions(dim_1);
+	    int sum=0;
+	    for (int kk=0;kk<=2;kk++)
+	      sum+=abs(dim_1[kk]-dim_0[kk]);
+
+	    if (sum!=0)
+	      {
+		vtkErrorMacro(<<"Multiple Images have different Dimensions !!");
+		return;
+	      }
+
+	    numtotal+=this->GetImageDataInput(i)->GetNumberOfScalarComponents();
+	  }
+      }
+
+  output->SetNumberOfScalarComponents(numtotal);
+}
+
+void vtkpxAppendComponents::SimpleExecute(vtkImageData* ,vtkImageData* output)
+{
+  if (this->GetNumberOfInputPorts()==0 || this->GetImageDataInput(0)==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+
+  int dim_0[3];
+  this->GetImageDataInput(0)->GetDimensions(dim_0);
+  int num_comp=this->GetImageDataInput(0)->GetNumberOfScalarComponents();
+
+  for (int i=1;i<this->GetNumberOfInputPorts();i++)
+      {
+	if (this->GetImageDataInput(i)==NULL)
+	  {
+	    vtkErrorMacro(<<"No Input Image Data " << i << " !!");
+	    return;
+	  }
+	else
+	  {
+	    int dim_1[3];
+	    this->GetImageDataInput(i)->GetDimensions(dim_1);
+	    int sum=0;
+	    for (int kk=0;kk<=2;kk++)
+	      sum+=abs(dim_1[kk]-dim_0[kk]);
+	    if (sum!=0)
+	      {
+		vtkErrorMacro(<<"Multiple Images have different Dimensions !!");
+		return;
+	      }
+    	    num_comp+=this->GetImageDataInput(i)->GetNumberOfScalarComponents();
+	  }
+      }
+
+
+  // Create Output Array
+  // -------------------
+  output->CopyStructure(this->GetImageDataInput(0));
+  output->SetNumberOfScalarComponents(num_comp);
+  output->AllocateScalars();
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  int numscalars=out->GetNumberOfTuples();
+
+  this->UpdateProgress(0.01);
+  float pog=0.00;
+
+  int component=0;
+  for (int i=0;i<this->GetNumberOfInputPorts();i++)
+    {
+      vtkDataArray* inp=this->GetImageDataInput(i)->GetPointData()->GetScalars();
+      for (int c=0;c<inp->GetNumberOfComponents();c++)
+	{
+	  out->CopyComponent(component,inp,c);
+	  ++component;
+	}
+      this->UpdateProgress(float(component)/float(num_comp));
+    }
+    
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxAppendComponents.h b/bioimagesuite30_src/Common/vtkpxAppendComponents.h
new file mode 100644
index 0000000..cdddcb8
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxAppendComponents.h
@@ -0,0 +1,89 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAppendComponents.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:08:12 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxAppendComponents -- combines images to form either mean or median
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// Appends components one after the other
+
+#ifndef __vtkpxAppendComponents_h
+#define __vtkpxAppendComponents_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+
+class vtkpxAppendComponents : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxAppendComponents *New();
+  vtkTypeMacro(vtkpxAppendComponents,vtkpxSimpleImageToImageFilter);
+
+
+protected:
+
+  //BTX
+  vtkpxAppendComponents();
+  virtual ~vtkpxAppendComponents();
+  vtkpxAppendComponents(const vtkpxAppendComponents&) {};
+  void operator=(const vtkpxAppendComponents&) {};
+  //ETX
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual void ExecuteInformation();
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxBSpline.cpp b/bioimagesuite30_src/Common/vtkpxBSpline.cpp
new file mode 100644
index 0000000..12da7b2
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxBSpline.cpp
@@ -0,0 +1,318 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxMath.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+
+#include "vtkMath.h"
+#include "pxutil.h"
+#include "vtkObjectFactory.h"
+#include "vtkDoubleArray.h"
+#include "vtkpxBSpline.h"
+#include "fitpack.h"
+
+// ------------------------------------------------------------------------
+
+vtkpxBSpline* vtkpxBSpline::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxBSpline");
+  if(ret)
+    {
+      return (vtkpxBSpline*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxBSpline;
+}
+// ------------------------------------------------------------------
+vtkpxBSpline::vtkpxBSpline() 
+{
+  Degree=3;
+  NumberOfPoints=0;
+  NumberOfKnots=0;
+  NumberOfControlPoints=0;
+  controlpoints=NULL;
+  knots=NULL;
+  this->Offset=0.0;
+}
+// ------------------------------------------------------------------
+vtkpxBSpline::~vtkpxBSpline() 
+{
+  Cleanup();
+}
+
+void vtkpxBSpline::Cleanup()
+{
+  if (controlpoints!=NULL)
+    delete [] controlpoints;
+  if (knots!=NULL)
+    delete [] knots;
+}
+
+// ------------------------------------------------------------------
+int  vtkpxBSpline::GetControlPointIndex(int i)
+{
+  return Irange(i,0,this->NumberOfControlPoints-1);
+}
+// --------------------------------------------------------------------------
+float vtkpxBSpline::GetControl(int i)
+{
+  if (controlpoints==NULL)
+    return 0.0;
+  return controlpoints[GetControlPointIndex(i)];
+}
+
+void  vtkpxBSpline::SetControl(int i,float v)
+{
+  if (controlpoints==NULL)
+    return;
+  controlpoints[GetControlPointIndex(i)]=v;
+}
+
+void  vtkpxBSpline::ShiftControl(int i,float v)
+{
+  if (controlpoints==NULL)
+    return;
+  controlpoints[GetControlPointIndex(i)]+=v;
+}
+
+float vtkpxBSpline::GetKnot(int i)
+{
+  if (knots==NULL)
+    return 0.0;
+  return knots[Irange(i,0,NumberOfKnots-1)];
+
+}
+
+// ----------------------------------------------------------------------------------
+int   vtkpxBSpline::GetControlPointKnotPosition(int index)
+{
+  int i=this->GetControlPointIndex(index);
+  return i+this->Degree-1;
+}
+
+float vtkpxBSpline::GetControlPointLowerBound(int index)
+{
+  int lb=this->GetControlPointKnotPosition(index);
+  return GetKnot(lb-this->Degree+1);
+}
+
+float vtkpxBSpline::GetControlPointUpperBound(int index)
+{
+  int lb=this->GetControlPointKnotPosition(index);
+  return GetKnot(lb+this->Degree-1);
+}
+
+void  vtkpxBSpline::GetControlPointBounds(int index,float bounds[2])
+{
+  bounds[0]=this->GetControlPointLowerBound(index);
+  bounds[1]=this->GetControlPointUpperBound(index);
+}
+// ----------------------------------------------------------------------------------
+float vtkpxBSpline::GetPosition(float s)
+{
+  if (knots==NULL)
+    return 0.0;
+  
+  integer ier=0;
+  integer M=1;
+  integer K=3;
+  integer N=this->NumberOfKnots;
+  integer NC=this->NumberOfKnots;
+  integer mx=3;
+  real    X[3];
+  integer dimension=1;
+
+  // Calling FITPACK 
+  curev_(&dimension,
+	 knots,&N,
+	 controlpoints,&NC,
+	 &K,&s,&M,X,&mx,&ier);
+
+  return X[0];
+}
+
+// ----------------------------------------------------------------------------------
+// B-Spline Fitting
+// ----------------------------------------------------------------------------------
+
+
+// ----------------------------------------------------------------------------------
+
+int vtkpxBSpline::FitArray(vtkDoubleArray* input,int npoints,float smooth,int component)
+{
+  return this->FitArray(input,NULL,npoints,smooth,component);
+}
+
+
+int vtkpxBSpline::FitArray(vtkDoubleArray* input,vtkDoubleArray* ordinate,int npoints,float smooth,int component)
+  /*PXContour* cnt_in,real smth,real cntrsmth,
+    int deg,int cl,int uniform,int npoints,int iterations)*/
+{
+  static int printed=0;
+  integer  M       =input->GetNumberOfTuples();
+  int useordinate=0;
+  if (ordinate!=NULL)
+    {
+      if (ordinate->GetNumberOfTuples()!=M)
+	{
+	  fprintf(stderr,"Unequal Arrays specified for fitarray\n");
+	  return 0;
+	}
+    }
+
+  //  fprintf(stderr,"M=%d\n",M);
+  component=Irange(component,0,input->GetNumberOfComponents()-1);
+
+  real*    X   =new real[M];
+  real*    Y   =new real[M];
+  real*    W   =new real[M];
+  integer  IOPT=0;
+
+  for (int k=0;k<M;k++)
+    {
+      Y[k]=input->GetComponent(k,component);
+      X[k]=float(k);
+      W[k]=1.0/float(M);
+    }
+
+  integer N;
+  real XB=-this->Offset;
+  real XE=real(M-1)+this->Offset;
+
+  integer NEST=M;
+  real* T=new real[NEST];
+
+  if (npoints>0)
+    {
+      int minv=this->Degree+1;
+      N=npoints+2*this->Degree;
+      int between=N-2*minv+1;
+      IOPT=-1;
+
+      int i;
+      for(i=0;i<minv;i++)
+	T[i]=XB;
+      for(i=N-minv;i<N;i++)
+	T[i]=XE;
+      
+      for (i=minv;i<(N-minv);i++)
+	T[i]= float(i-minv+1)/float(between)*(XE-XB)+XB;
+    }
+    
+  integer K=this->Degree;
+  real S=smooth;
+  real* C=new real[NEST];
+  real FP;
+  integer LWRK=2*(M*(K+1)+NEST*(7+3*K));
+  real* WRK=new real[LWRK];
+  integer* IWRK=new integer[NEST];
+  integer IER=0;
+
+      
+  //  fprintf(stderr,"On to curfit\n");
+  int ret=curfit_(&IOPT,&M,X,Y,W,&XB,&XE,&K,&S,&NEST,&N,T,C,&FP,WRK,&LWRK,IWRK,&IER);
+
+
+  if (IER<=0)
+    {
+      //      fprintf(stderr,"Curfit output OK IER=%d N=%d FP=%.3f\n",(int)IER,(int)N,FP);
+      this->Cleanup();
+      this->NumberOfPoints=N-2*K+2;
+      this->NumberOfKnots=(this->NumberOfPoints-2)+2*this->Degree;   
+      this->NumberOfControlPoints=this->NumberOfPoints;
+      
+      this->knots=new real[this->NumberOfKnots];
+      this->controlpoints=new real[this->NumberOfControlPoints];
+
+      float bounds[2];
+      for (int j=0;j<this->NumberOfKnots;j++)
+	this->knots[j]=T[j];
+
+      for (int j=0;j<this->NumberOfControlPoints;j++)
+	this->controlpoints[j]=C[j];
+
+      for (int ia=0;ia<this->NumberOfControlPoints;ia++)
+	{
+	  int center=this->GetControlPointKnotPosition(ia);
+	  float p=this->GetKnot(center);
+	  this->GetControlPointBounds(ia,bounds);
+	  //	  fprintf(stderr,"controlpoint(%d) = %.2f p=%.2f (%.2f : %.2f)\n",ia,C[ia],p,bounds[0],bounds[1]);
+	}
+
+      ret=1;
+    }
+  else
+    {
+      fprintf(stderr,"Curfit error IER=%d\n",(int)IER);
+      ret=0;
+    }
+      
+  printed=1;
+
+  delete [] T;
+  delete [] C;
+  delete [] WRK;
+  delete [] IWRK;
+  delete [] W;
+  delete [] X;
+  delete [] Y;
+
+  return ret;
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxBSpline.h b/bioimagesuite30_src/Common/vtkpxBSpline.h
new file mode 100644
index 0000000..5166188
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxBSpline.h
@@ -0,0 +1,141 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxMath.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxBSpline - a routine to implement Bsplines of arbitrary dimensions
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// This requires fitpack
+
+#ifndef __vtkpxBSpline_h
+#define __vtkpxBSpline_h
+
+#include "vtkObject.h"
+typedef float real;
+class vtkDoubleArray;
+
+class vtkpxBSpline : public vtkObject
+{
+public:
+  static vtkpxBSpline *New();
+  vtkTypeMacro(vtkpxBSpline,vtkObject);
+  
+
+  // Description: Get Position,Derivative
+  // ------------------------------------
+  virtual float GetPosition(float s);
+
+  // Description: Modify Control Points 
+  // -----------------------------------
+  virtual float GetControl(int i);
+  virtual void  SetControl(int i,float v);
+  virtual void  ShiftControl(int i,float v);
+  virtual float GetKnot(int i);
+
+  
+  // Description: Fit Points
+  // ------------------------
+  virtual int FitArray(vtkDoubleArray* inputdata,int npoints,float smooth,int component);
+  virtual int FitArray(vtkDoubleArray* inputdata,vtkDoubleArray* ordinate,int npoints,float smooth,int component);
+
+  // Description: Access Methods
+  // Degree of Polynomial
+  vtkSetClampMacro(Degree, int,1,3);
+  vtkGetMacro(Degree, int);
+
+  // Description: Access Methods
+  // Degree of Polynomial
+  vtkSetClampMacro(Offset, float,0.0,2.0);
+  vtkGetMacro(Offset, float);
+
+  vtkGetMacro(NumberOfPoints, int);
+  vtkGetMacro(NumberOfControlPoints, int);
+  vtkGetMacro(NumberOfKnots, int);
+
+  int   GetControlPointKnotPosition(int index);
+  float GetControlPointLowerBound(int index);
+  float GetControlPointUpperBound(int index);
+  void  GetControlPointBounds(int index,float bounds[2]);
+
+protected:
+
+  // Description: Constructor/Desctructor etc.
+  vtkpxBSpline();
+  virtual ~vtkpxBSpline();
+
+  vtkpxBSpline(const vtkpxBSpline&) {};
+  void operator=(const vtkpxBSpline&) {};
+
+  // Member variables
+  
+  int Degree;
+  int NumberOfPoints;
+  int NumberOfKnots;
+  int NumberOfControlPoints;
+  real* controlpoints;
+  real* knots;
+  float Offset;
+
+
+  virtual int   GetControlPointIndex(int i);
+  
+  //BTX
+  void Cleanup();
+  //ETX
+  
+  
+};
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkpxBaseCurve.cpp b/bioimagesuite30_src/Common/vtkpxBaseCurve.cpp
new file mode 100644
index 0000000..c1d8cbe
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxBaseCurve.cpp
@@ -0,0 +1,2357 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+ see vtkpxBaseCurve.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "pxcontour.h"
+#include "pxutil.h"
+#include "vtkAppendPolyData.h"
+#include "vtkCellArray.h"
+#include "vtkCleanPolyData.h"
+#include "vtkContourFilter.h"
+#include "vtkDiskSource.h"
+#include "vtkGlyph3D.h"
+#include "vtkImageData.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageGradient.h"
+#include "vtkImageGradientMagnitude.h"
+#include "vtkImageMedian3D.h"
+#include "vtkImageToStructuredPoints.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkOutlineFilter.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataConnectivityFilter.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkPolyDataReader.h"
+#include "vtkSphereSource.h"
+#include "vtkTransform.h"
+#include "vtkTubeFilter.h"
+#include "vtkpxBaseCurve.h"
+#include "vtkpxCrossHairSource.h"
+#include "vtkpxImageExtract.h"
+//------------------------------------------------------------------------------
+vtkpxBaseCurve* vtkpxBaseCurve::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxBaseCurve");
+  if(ret)
+    {
+    return (vtkpxBaseCurve*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxBaseCurve;
+}
+
+// Construct object with no children.
+vtkpxBaseCurve::vtkpxBaseCurve()
+{
+  this->PointScale=1.0;
+  this->ShowControls=0;
+  this->ControlsDisplayMode=0;
+  this->ShowBoundingBox=0;
+  this->ShowCurve=1;
+  this->NumPoints=0;
+  this->ClosedCurve=0;
+
+  for (int i=0;i<=2;i++)
+    {
+      this->Spacing[i]=1.0;
+      this->Origin[i]=0.0;
+    }
+
+  this->Points=vtkPoints::New();
+  this->Points->SetNumberOfPoints(20);
+  this->Points->SetPoint(0,0.0,0.0,0.0);
+}
+
+/* -------------------------------------------------------------------------*/
+ 
+vtkpxBaseCurve::~vtkpxBaseCurve()
+{
+  this->Points->Delete();
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxBaseCurve::Copy(vtkpxBaseCurve* other)
+{
+  this->SetSpacing(other->GetSpacing());
+  this->SetOrigin(other->GetOrigin());
+  
+  int np=other->GetNumPoints();
+  if (np>this->NumPoints)
+    this->Points->SetNumberOfPoints(np+10);
+  
+  this->NumPoints=np;
+  double x[3];
+  for (int i=0;i<np;i++)
+    {
+      other->GetPoints()->GetPoint(i,x);
+      this->Points->SetPoint(i,x);
+    }
+
+  this->Modified();
+  this->Update();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxBaseCurve::GetPoint(int index,double& x,double& y,double &z)
+{
+  index=Irange(index,0,this->NumPoints-1);
+  double xp[3];
+  this->Points->GetPoint(index,xp);
+  x=xp[0];  y=xp[1];  z=xp[2];
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxBaseCurve::SetPoint(int index,double x,double y,double z,
+			      int scaled)
+{
+  index=Irange(index,0,this->NumPoints-1);
+  if (scaled)
+      {
+	x=(x-Origin[0])/Spacing[0];
+	y=(y-Origin[1])/Spacing[1];
+	z=(z-Origin[2])/Spacing[2];
+      }
+  
+  this->Points->SetPoint(index,x,y,z);
+  this->Modified();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxBaseCurve::AddPoint(double x,double y,double z,int scaled)
+{
+  if (scaled)
+    {
+      x=(x-Origin[0])/Spacing[0];
+      y=(y-Origin[1])/Spacing[1];
+      z=(z-Origin[2])/Spacing[2];
+    }
+  
+  int index=this->NumPoints;
+
+  double x1,y1,z1;
+  this->GetPoint(index-1,x1,y1,z1);
+  double d=fabs(x-x1)+fabs(y-y1)+fabs(z-z1);
+  if (d<0.01)
+    return;
+
+  this->NumPoints++;
+  if (this->NumPoints>=this->Points->GetNumberOfPoints()-1)
+    {
+      vtkPoints* tmpPoints=vtkPoints::New();
+      tmpPoints->SetNumberOfPoints(this->NumPoints);
+      for (int i=0;i<this->NumPoints;i++)
+	tmpPoints->SetPoint(i,this->Points->GetPoint(i));
+      
+      this->Points->SetNumberOfPoints(this->NumPoints+20);
+      for (int j=0;j<this->NumPoints;j++)
+	this->Points->SetPoint(j,tmpPoints->GetPoint(j));
+      tmpPoints->Delete();
+    }
+  
+  this->Points->SetPoint(index,x,y,z);
+  this->Modified();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxBaseCurve::DeletePoint(int index)
+{
+  if (index==-1)
+      index=this->NumPoints-1;
+  else
+      index=Irange(index,0,this->NumPoints-1);
+
+  if (index!=this->NumPoints-1)
+      {
+	for (int k=index+1;k<this->NumPoints;k++)
+	    this->Points->SetPoint(k-1,this->Points->GetPoint(k));
+      }
+
+  this->NumPoints-=1;
+  this->Points->SetPoint(this->NumPoints,0.0,0.0,0.0);
+
+  this->Modified();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxBaseCurve::DeleteAllPoints()
+{
+  for (int i=0;i<this->NumPoints;i++)
+      this->Points->SetPoint(this->NumPoints,0.0,0.0,0.0);
+
+  this->NumPoints=0;
+  this->Modified();
+}
+/* -------------------------------------------------------------------------*/
+vtkPoints* vtkpxBaseCurve::GetPoints()
+{
+  return this->Points;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxBaseCurve::Save(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout)
+      {
+	fprintf(fout,"#Landmark Data\n");
+	fprintf(fout,"#Number of Landmarks Mode\n%d %d\n",this->NumPoints,(this->ClosedCurve>0)+1);
+	fprintf(fout,"#Origin\n %6.3f %6.3f %6.3f\n",Origin[0],Origin[1],Origin[2]);
+	fprintf(fout,"#Spacing\n %6.3f %6.3f %6.3f\n",Spacing[0],Spacing[1],Spacing[2]);
+	fprintf(fout,"#Landmarks\n");
+	for (int i=0;i<this->NumPoints;i++)
+	    {
+	      double x[3];
+	      this->Points->GetPoint(i,x);
+	      fprintf(fout,"%6.2f %6.2f %6.2f\n",x[0],x[1],x[2]);
+	    }
+	fclose(fout);
+	vtkDebugMacro(<<"Saved landmarks ("<<this->NumPoints<<")  in "<<fname);
+	return 1;
+      }
+  return 0;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxBaseCurve::Load(const char* fname)
+{
+  char line[400];
+  strncpy(line,fname,400);
+
+  //fprintf(stderr,"Loading %s\n",line);
+  if (gzfindstringinstring(line,".vtk")==1)
+    {
+      //  this->DebugOn();
+      //      fprintf(stderr,"Found .vtk\n");
+      // Read as surface file and adjust points later
+      vtkPolyDataReader* source=vtkPolyDataReader::New();
+      source->SetFileName(fname);
+      source->Update();
+
+      vtkPoints* newPoints=source->GetOutput()->GetPoints();
+
+      /*fprintf(stderr,"Name=%s Points=%d Polys=%d\n",
+	      fname,
+	      source->GetOutput()->GetNumberOfPoints(),
+	      source->GetOutput()->GetNumberOfCells());*/
+
+      if (newPoints!=NULL)
+	{
+	  this->SetFromPoints(newPoints);
+	  vtkDebugMacro(<<"Loaded  landmarks ("<<this->NumPoints<<")  from "<<fname << "via vtkPolyDataReader");
+	  return 1;
+	}
+      else
+	{
+	  return 0;
+	}
+    }
+  
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (fin)
+      {
+
+	gzgets(fin,line,100);
+	if (gzfindstringinstring(line,"#Landmark Data")==0)
+	  {
+	    gzclose(fin);
+	    return 0;
+	  }
+	gzgets(fin,line,100); 	
+	gzgets(fin,line,100);
+	int oldnum=this->NumPoints,new_num,tmp;
+	
+	sscanf(line,"%d %d",&new_num,&tmp);
+	this->DeleteAllPoints();
+	this->NumPoints=new_num;
+	if (this->NumPoints>oldnum)
+	  this->Points->SetNumberOfPoints(this->NumPoints+10);
+	
+	this->SetClosedCurve(tmp>1);
+
+	gzgets(fin,line,100); 	gzgets(fin,line,100);
+	sscanf(line,"%lf %lf %lf",&Origin[0],&Origin[1],&Origin[2]);
+
+	gzgets(fin,line,100); 	gzgets(fin,line,100);
+	sscanf(line,"%lf %lf %lf",&Spacing[0],&Spacing[1],&Spacing[2]);
+
+
+
+	gzgets(fin,line,100);
+	for (int i=0;i<this->NumPoints;i++)
+	    {
+	      gzgets(fin,line,100);
+	      //	      fprintf(stderr,"line=%s\n",line);
+	      double x[3];
+	      sscanf(line,"%lf %lf %lf",&x[0],&x[1],&x[2]);
+	      this->Points->SetPoint(i,x[0],x[1],x[2]);
+	    }
+	gzclose(fin);
+	vtkDebugMacro(<<"Loaded  landmarks ("<<this->NumPoints<<")  from "<<fname);
+	return 1;
+      }
+  return 0;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxBaseCurve::Compact()
+{
+  vtkPoints* tmpPoints=vtkPoints::New();
+  tmpPoints->DeepCopy(this->Points);
+
+  this->Points->SetNumberOfPoints(this->NumPoints);
+  for (int i=0;i<this->NumPoints;i++)
+      {
+	double x[3];
+	tmpPoints->GetPoint(i,x);
+
+	for (int j=0;j<=2;j++)
+	    x[j]=(x[j])*Spacing[j]+Origin[j];
+	this->Points->SetPoint(i,x);
+      }
+  
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->Spacing[ia]=1.0;
+      this->Origin[ia]=0.0;
+    }
+
+  tmpPoints->Delete();
+  return this->Points->GetNumberOfPoints();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxBaseCurve::StoreInContour(PXContour* cntr,int plane)
+{
+  if (cntr==NULL)
+      return -1;
+
+  cntr->DeleteAll();
+
+  for (int i=0;i<this->NumPoints;i++)
+      {
+	double x[3],y[2];
+	this->Points->GetPoint(i,x);
+	
+	switch(plane)
+	    {
+	    case 0: // YZ 
+	      y[0]=x[1];
+	      y[1]=x[2];
+	      break;
+	      
+	    case 1: // XZ
+	      y[0]=x[0];
+	      y[1]=x[2];
+	      break;
+	      
+	    case 2: // XY
+	      y[0]=x[0];
+	      y[1]=x[1];
+	      break;
+	    }
+	cntr->Add(y[0],y[1]);
+      }
+
+  cntr->setclosed(this->ClosedCurve);
+  return cntr->getnumpoints();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxBaseCurve::SetFromContour(PXContour* cntr,int plane,int level)
+{
+  if (cntr==NULL)
+      return 0;
+
+  DeleteAllPoints();
+  
+  this->Points->SetNumberOfPoints(cntr->getnumpoints()+10);
+  this->NumPoints=cntr->getnumpoints();
+
+  this->SetClosedCurve(cntr->isclosed());
+
+  plane=Irange(plane,0,2);
+  //PointScale=0.25;
+
+  if (cntr->getnumpoints()==0)
+      return 0;
+
+  PXContourPoint* temp=cntr->gettoppoint(); 
+
+  for (int i=0; i<cntr->getnumpoints(); i++) 
+      {
+	double y[3];
+	switch(plane)
+	    {
+	    case 0: // YZ 
+	      y[0]=double(level);
+	      y[1]=temp->x;
+	      y[2]=temp->y;
+	      break;
+	      
+	    case 1: // XZ
+	      y[0]=temp->x;
+	      y[1]=double(level);
+	      y[2]=temp->y;
+	      break;
+	      
+	    case 2: // XY
+	      y[0]=temp->x;
+	      y[1]=temp->y;
+	      y[2]=double(level);
+	      break;
+	    }
+	this->Points->SetPoint(i,y);
+	temp=temp->next;
+      }
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxBaseCurve::GetCurrentInternalPlane()
+{
+  if (this->NumPoints<2)
+    return 2;
+
+  double sum[3],sumsq[3],x[3];
+  int ia;
+  for (ia=0;ia<=2;ia++)
+    {
+      sum[ia]=0.0;
+      sumsq[ia]=0.0;
+    }
+
+  for (int i=0;i<this->NumPoints;i++)
+    {
+      this->Points->GetPoint(i,x);
+      for (int ia=0;ia<=2;ia++)
+	{
+	  sum[ia]+=x[ia];
+	  sumsq[ia]+=x[ia]*x[ia];
+	}
+    }
+
+  double np=double(this->NumPoints);
+
+  for (ia=0;ia<=2;ia++)
+    {
+      sum[ia]/=np;
+      sumsq[ia]=sumsq[ia]/np-sum[ia]*sum[ia];
+    }
+
+  if (sumsq[0]<sumsq[1] && sumsq[0]<sumsq[2])
+    return 0;
+
+  if (sumsq[1]<sumsq[2])
+    return 1;
+  
+  return 2;
+
+}
+
+void vtkpxBaseCurve::GetCurrentInternalPlaneAndLevel(int &plane,int &level)
+{
+  if (this->NumPoints<1)
+    {
+      plane =2;
+      level =0;
+    }
+
+  double sum[3],sumsq[3],x[3];
+  int ia;
+  for (ia=0;ia<=2;ia++)
+    {
+      sum[ia]=0.0;
+      sumsq[ia]=0.0;
+    }
+
+  for (int i=0;i<this->NumPoints;i++)
+    {
+      this->Points->GetPoint(i,x);
+      for (int ia=0;ia<=2;ia++)
+	{
+	  sum[ia]+=x[ia];
+	  sumsq[ia]+=x[ia]*x[ia];
+	}
+    }
+
+  if (this->NumPoints>1)
+    {
+      double np=double(this->NumPoints);
+      for (ia=0;ia<=2;ia++)
+	{
+	  sum[ia]/=np;
+	  sumsq[ia]=sumsq[ia]/np-sum[ia]*sum[ia];
+	}
+      
+      if (sumsq[0]<sumsq[1] && sumsq[0]<sumsq[2])
+	{
+	  plane=0;
+	}
+      else if (sumsq[1]<sumsq[2])
+	{
+	  plane=1;
+	} 
+      else 
+	{
+	  plane=2;
+	}
+    } 
+  else
+    {
+      plane=2;
+    }
+
+  level=(int)sum[plane];
+}
+/* -------------------------------------------------------------------------*/
+
+int vtkpxBaseCurve::SetFromPolyData(vtkPolyData* polydata,double startx[3],int plane,int level)
+{
+  if (polydata==NULL)
+      return 0;
+
+  plane=Irange(plane,-1,2);
+  DeleteAllPoints();
+
+  vtkPoints* newPoints=polydata->GetPoints();
+  int np=newPoints->GetNumberOfPoints();
+	
+  int* neigh=new int[np*2];
+  int* used=new int[np];
+
+  for (int ib=0;ib<np*2;ib++)
+      neigh[ib]=-1;
+  for (int ic=0;ic<np;ic++)
+      used[ic]=0;
+ 
+  vtkCellArray* lines=polydata->GetLines();
+  int numlines=lines->GetNumberOfCells();
+  lines->InitTraversal();
+  for (int ia=0;ia<numlines;ia++)
+      {
+	vtkIdType nump;
+	vtkIdType *p;
+	lines->GetNextCell(nump,p);
+	
+	for (int k=0;k<=1;k++)
+	    {
+	      int index=p[k]*2;
+	      if (neigh[index]==-1)
+		  neigh[index]=p[1-k];
+	      else
+		  neigh[index+1]=p[1-k];
+	    }
+      }
+
+  double x[3];
+  int nearest=0;
+  newPoints->GetPoint(0,x);
+  double mindist=Fsqdist(x[0],x[1],x[2],startx[0],startx[1],startx[2]);
+  for (int i=1;i<np;i++)
+      {
+	newPoints->GetPoint(i,x);
+	double dist=Fsqdist(x[0],x[1],x[2],startx[0],startx[1],startx[2]);
+	if (dist<mindist)
+	    {
+	      mindist=dist;
+	      nearest=i;
+	    }
+      }
+  newPoints->GetPoint(nearest,x);
+
+  int done=0,numlinks=0,firstpoint=nearest;
+
+  while (done==0 && numlinks<np-1)
+      {
+	int index=firstpoint*2;
+	used[firstpoint]=1;
+
+	//fprintf(stderr,"Parsing Point=%3d Neighbours %3d,%3d\n",firstpoint,neigh[index],neigh[index+1]);
+	if (neigh[index]==-1 || neigh[index+1]==-1)
+	    {
+	      done=1;
+
+	      // Unless we can merge 
+	      double x1[3],x2[3];
+	      newPoints->GetPoint(firstpoint,x1);
+	      for (int kk=0;kk<np;kk++)
+		  {
+		    if (kk!=firstpoint)
+			{
+			  int index2=kk*2;
+			  if (neigh[index2]==-1 || neigh[index2+1]==-1)
+			      {
+				newPoints->GetPoint(kk,x2);
+				if (Fsqdist(x1[0],x1[1],x1[2],x2[0],x2[1],x2[2])<1.0)
+				    {
+				      /*fprintf(stderr,"\tAdding Link from %5.1f,%5.1f,%5.1f to %5.1f,%5.1f,%5.1f (index=%d,%d)\n",
+					      x1[0],x1[1],x1[2],x2[0],x2[1],x2[2],kk,firstpoint);*/
+				      done=0;
+
+				      if (neigh[index]==-1)
+					  neigh[index]=kk;
+				      else
+					  neigh[index+1]=kk;
+
+				      // Chain Back
+
+				      if (neigh[index2]==-1)
+					  neigh[index2]=firstpoint;
+				      else
+					  neigh[index2+1]=firstpoint;
+				      kk=np;
+				    }
+			      }
+			}
+		  }
+
+	    }
+
+	if (done==0)
+	    {
+	      int keeplooking=1;
+
+	      if (neigh[index]!=-1)
+		  {
+		    if (used[neigh[index]]==0)
+			{
+			  firstpoint=neigh[index];
+			  keeplooking=0;
+			}
+		  }
+
+	      if (keeplooking==1 && neigh[index+1]!=-1)
+		  {
+		    if (used[neigh[index+1]]==0)
+			{
+			  firstpoint=neigh[index+1];
+			  keeplooking=0;
+			}
+		  }
+
+	      if (keeplooking==1)
+		  done=1;
+	      else
+		  numlinks++;
+	    }
+      }
+
+  /*fprintf(stderr,"\tFirstPoint =%d (Neighbours=%d,%d) numlinks=%d (np=%d)\n",firstpoint,neigh[firstpoint*2],
+	  neigh[firstpoint*2+1],numlinks,np);*/
+
+  for (int ie=0;ie<np;ie++)
+      used[ie]=0;
+
+  int numgoodpoints=0,found=0;
+  int nextpoint=firstpoint;
+  while (found==0 && numgoodpoints<np)
+      {
+	int currentpoint=nextpoint;
+	used[currentpoint]=1;
+	int index=currentpoint*2;
+
+	/*fprintf(stderr,"Parsing Point=%3d Neighbours %3d,%3d Used=%d,%d\n",
+		currentpoint,neigh[index],neigh[index+1],used[neigh[index]],
+		used[neigh[index+1]]);*/
+	numgoodpoints++;
+
+	int keeplooking=1;
+	if (neigh[index]!=-1)
+	    {
+	      if (used[neigh[index]]==0)
+		  {
+		    nextpoint=neigh[index];
+		    keeplooking=0;
+		  }
+	    }
+	
+	if (keeplooking==1 && neigh[index+1]!=-1)
+	    {
+	      if (used[neigh[index+1]]==0)
+		  {
+		    nextpoint=neigh[index+1];
+		    keeplooking=0;
+		  }
+	    }
+
+	if (keeplooking==1)
+	    found=1;
+      }
+
+  //fprintf(stderr,"\tNumgoodpoints=%d\n",numgoodpoints);
+
+  // Restablish all links
+  for (int iaa=0;iaa<np;iaa++)
+      used[iaa]=0;
+
+  this->Points->SetNumberOfPoints(numgoodpoints+10);
+  this->NumPoints=numgoodpoints;
+	
+  for (int k=0;k<numgoodpoints;k++)
+      {
+	double x[3],y[3];
+	newPoints->GetPoint(firstpoint,x);
+	used[firstpoint]=1;
+
+	//fprintf(stderr,"Adding %d Point=%3d Neighbours %5d,%5d\n",k,firstpoint,neigh[firstpoint*2],neigh[firstpoint*2+1]);
+	
+	switch(plane)
+	    {
+	    case -1:
+	      {
+		for (int ia=0;ia<=2;ia++)
+		    y[ia]=(x[ia]-Origin[ia])/Spacing[ia];
+	      }
+	      break;
+	      
+	    case 0: // YZ 
+	      y[0]=double(level);
+	      y[1]=(x[0]-Origin[0])/Spacing[0];
+	      y[2]=(x[1]-Origin[1])/Spacing[1];
+	      break;
+	      
+	    case 1: // XZ
+	      y[0]=(x[0]-Origin[0])/Spacing[0];
+	      y[1]=double(level);
+	      y[2]=(x[1]-Origin[1])/Spacing[1];
+	      break;
+	      
+	    case 2: // XY
+	      y[0]=(x[0]-Origin[0])/Spacing[0];
+	      y[1]=(x[1]-Origin[1])/Spacing[1];
+	      y[2]=double(level);
+	      break;
+	    }
+	
+	this->Points->SetPoint(k,y);
+	
+	int index=firstpoint*2;
+	int keeplooking=1;
+
+	if (neigh[index]!=-1)
+	    {
+	      if (used[neigh[index]]==0)
+		  {
+		    firstpoint=neigh[index];
+		    keeplooking=0;
+		  }
+	    }
+
+	if (keeplooking==1 && neigh[index+1]!=1)
+	    {
+	      if (used[neigh[index+1]]==0)
+		  {
+		    firstpoint=neigh[index+1];
+		    keeplooking=0;
+		  }
+	    }
+
+	if (keeplooking==1)
+	    {
+	      this->NumPoints=k+1;
+	      k=np;
+	    }
+      }
+  
+  delete [] used;
+  delete [] neigh;
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxBaseCurve::SetFromPoints(vtkPoints* pts)
+{
+  if (pts==NULL)
+    return -1;
+
+  DeleteAllPoints();
+  this->NumPoints=pts->GetNumberOfPoints();
+  this->Points->SetNumberOfPoints(this->NumPoints+10);
+  for (int i=0;i<pts->GetNumberOfPoints();i++)
+    {
+      double x[3];
+      pts->GetPoint(i,x);
+      this->SetPoint(i,x[0],x[1],x[2],1);
+    }
+  this->Modified();
+  //fprintf(stderr,"Number of Points = %d (in=%d,outb=%d)\n",this->NumPoints,pts->GetNumberOfPoints(),points->GetNumberOfPoints());
+  return this->NumPoints;
+}
+
+int vtkpxBaseCurve::CreateCircle(int plane,int level)
+{
+  if (this->NumPoints<2)
+      return 0;
+
+  double x[3],y[3];
+  this->Points->GetPoint(0,x);
+  this->Points->GetPoint(1,y);
+  double radius=Fdist(x[0],x[1],x[2],y[0],y[1],y[2]);
+
+  int np=int(radius*2.0);
+  
+  double xp[2];
+  switch(plane)
+      {
+      case 0: // YZ 
+	xp[0]=x[1];
+	xp[1]=x[2];
+	break;
+	
+      case 1: // XZ
+	xp[0]=x[0];
+	xp[1]=x[2];
+	break;
+	
+      case 2: // XY
+	xp[0]=x[0];
+	xp[1]=x[1];
+	break;
+      }
+  
+  PXContour* cntr=new PXContour();
+  cntr->setcircle(np,radius,xp[0],xp[1]);
+  cntr->setclosed(1);
+  SetFromContour(cntr,plane,level);
+  delete cntr;
+
+  this->Modified();
+  return this->NumPoints;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxBaseCurve::FindClosestPoint(double x,double y, double z,double threshold,int scaled) 
+{
+  double px[3];
+  px[0]=x;px[1]=y;px[2]=z;
+  return this->FindClosestPoint(px,threshold,scaled);
+}
+int vtkpxBaseCurve::FindClosestPoint(double px[3],double threshold,int scaled)
+{
+  int found=-1;
+  if (this->NumPoints<1)
+      return found;
+
+  if (scaled)
+    {
+      for (int ia=0;ia<=2;ia++)
+	px[ia]=(px[ia]-Origin[ia])/Spacing[ia];
+    }
+ 
+  for (int i=0;i<GetNumPoints();i++)
+      {
+	double lx[3];
+	this->Points->GetPoint(i,lx);
+	/*	fprintf(stderr,"Comparing %d (%.2f,%.2f,%.2f) with (%.2f,%.2f,%.2f) at threshold=%.2f\n",
+	  i,lx[0],lx[1],lx[2],px[0],px[1],px[2],threshold);*/
+	if (Fsamepoint(px[0],px[1],px[2],lx[0],lx[1],lx[2],threshold))
+	  {
+	    found=i;
+	    i=GetNumPoints();
+	  }
+      }
+  return found;
+}
+/* -------------------------------------------------------------------------*/
+float vtkpxBaseCurve::GetLength()
+{
+  int np=this->NumPoints;
+  float dist=0;
+  for (int i=0;i<np;i++)
+    {
+      double x[3],tx[3];
+      this->Points->GetPoint(i,x);
+      int ip=i+1;
+      if (ip<np || this->ClosedCurve==1)
+	{
+	  if (ip==np)
+	    ip=0;
+	  
+	  this->Points->GetPoint(ip,tx);
+	  for (int j=0;j<=2;j++)
+	    {
+	      x[j]=x[j]*Spacing[j]+Origin[j];
+	      tx[j]=tx[j]*Spacing[j]+Origin[j];
+	    }
+	  dist+=sqrt(vtkMath::Distance2BetweenPoints(x,tx));
+	}
+    }
+  return dist;
+}
+/* -------------------------------------------------------------------------*/
+float vtkpxBaseCurve::GetPlaneArea(int plane)
+{
+  /*if (!this->ClosedCurve)
+    return -1.0;*/
+
+
+
+  if (this->NumPoints<3)
+    {
+      //      fprintf(stderr,"Number of Points < 3 \n");
+      return 0.0;
+    }
+
+  float area=0.0;
+  
+
+  //	2 A( P ) = sum_{i=0}^{n-1} (x_i y_{i+1} - y_i x_{i+1}).
+  for (int i=0;i<this->NumPoints;i++)
+      {
+      double xi[3],xip[3];
+
+      this->Points->GetPoint(i,xi);
+      if (i!=this->NumPoints-1)
+	this->Points->GetPoint(i+1,xip);
+      else
+	this->Points->GetPoint(0,xip);
+
+      switch(plane)
+	{
+	case 0:
+	  area+= xi[1]*xip[2]-xi[2]*xip[1];
+	  break;
+	case 1:
+	  area+= xi[0]*xip[2]-xi[2]*xip[0];
+	  break;
+	case 2:
+	  area+= xi[0]*xip[1]-xi[1]*xip[0];
+	  break;
+	}
+    }
+
+  switch(plane)
+    {
+    case 0:
+      return fabs(area*0.5)*Spacing[1]*Spacing[2];
+      break;
+    case 1:
+      return fabs(area*0.5)*Spacing[0]*Spacing[2];
+      break;
+    default:
+      return fabs(area*0.5)*Spacing[1]*Spacing[0];
+      break;
+    }
+}
+/* -------------------------------------------------------------------------*/	
+float vtkpxBaseCurve::GetAreaFromPixels(int num,int image_plane)
+{
+  image_plane=Irange(image_plane,0,2);
+  switch(image_plane)
+    {
+    case 0:
+      return float(num)*Spacing[1]*Spacing[2];
+      break;
+    case 1:
+      return float(num)*Spacing[0]*Spacing[2];
+      break;
+    default:
+      return float(num)*Spacing[1]*Spacing[0];
+      break;
+    }
+}
+
+int vtkpxBaseCurve::ExtractVOIProperties(vtkImageData* image,int plane,
+					 int level,int fr,float& mean,float& sigma)
+{
+  mean=-1.0;
+  sigma=-1.0;
+
+  if (image==NULL || plane==-1)
+      return 0;
+
+  if (this->NumPoints<1)
+      return 0;
+
+  int dim[3];
+  image->GetDimensions(dim);
+  plane=Irange(plane,0,2);
+  
+  if (dim[plane]<0)
+      return 0;
+  level=Irange(level,0,dim[plane]);
+
+  vtkpxImageExtract* extr=vtkpxImageExtract::New();
+  extr->SetInput(image);
+  extr->SetCurrentPlane(plane);
+  extr->SetSliceNo(level);
+  extr->SetFrame(fr);
+  extr->Update();
+
+  vtkImageData* sourceImage=vtkImageData::New();
+  sourceImage->ShallowCopy(extr->GetOutput());
+  extr->Delete();  
+
+  PXContour* cntr=new PXContour();
+  if (this->NumPoints==2)
+      CreateCircle(plane,level);
+	
+  StoreInContour(cntr,plane);
+  cntr->setclosed(1);
+  int numinside=0;
+  int numbiggerthanzero=0;
+  float sum=0,sumsq=0;
+
+  if (cntr->getnumpoints()>1)
+      {
+	PXContourPoint* temp=cntr->gettoppoint(); 
+
+	float minx=temp->x,maxx=temp->x,miny=temp->y,maxy=temp->y;
+	temp=temp->next;
+	for (int i=1; i<cntr->getnumpoints(); i++) 
+	    {
+	      minx=Fmin(minx,temp->x);
+	      maxx=Fmax(maxx,temp->x);
+	      miny=Fmin(miny,temp->y);
+	      maxy=Fmax(maxy,temp->y);
+	      temp=temp->next;
+	    }
+	
+	for (int ia=(int)minx;ia<maxx;ia++)
+	    for (int ib=(int)miny;ib<maxy;ib++)
+		{
+		  if (cntr->IsInside(float(ia),float(ib)))
+		      {
+			numinside++;
+			double pxl=sourceImage->GetScalarComponentAsDouble(ia,ib,0,0);
+			if (pxl>0.0)
+			  ++numbiggerthanzero;
+			sum+=pxl;
+			sumsq+=(pxl*pxl);
+		      }
+		}
+      }
+  else
+      {
+	PXContourPoint* temp=cntr->gettoppoint(); 
+	sum=sourceImage->GetScalarComponentAsDouble((int)temp->x,(int)temp->y,0,0);
+	sumsq=sum*sum;
+	numinside=1;
+      }
+	
+  mean=0.0;
+  sigma=0.0;
+
+  if (numinside==0)
+      return 0;
+
+  mean=sum/float(numinside);
+  sigma=sqrt(sumsq/float(numinside)-mean*mean);
+  
+  sourceImage->Delete();
+  delete cntr;
+  return numbiggerthanzero;
+}
+
+/* -------------------------------------------------------------------------*/
+
+void vtkpxBaseCurve::Sample(int rate)
+{
+  if (this->NumPoints<4)
+      return;
+
+  vtkPoints* tmpPoints=vtkPoints::New();
+  tmpPoints->SetNumberOfPoints(this->NumPoints);
+  for (int i=0;i<this->NumPoints;i++)
+      tmpPoints->SetPoint(i,this->Points->GetPoint(i));
+  
+  int np=this->NumPoints;
+  this->NumPoints=0;
+  for (int j=0;j<np;j+=rate)
+      {
+	this->Points->SetPoint(this->NumPoints,tmpPoints->GetPoint(j));
+	this->NumPoints++;
+      }
+  tmpPoints->Delete();
+  
+  this->Modified();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxBaseCurve::SubSample(int rate)
+{
+  if (this->NumPoints<2)
+      return;
+
+  vtkPoints* tmpPoints=vtkPoints::New();
+  tmpPoints->SetNumberOfPoints(this->NumPoints+1);
+  for (int i=0;i<this->NumPoints;i++)
+      tmpPoints->SetPoint(i,this->Points->GetPoint(i));
+
+  int np=this->NumPoints;
+
+  if (this->ClosedCurve)
+    {
+      tmpPoints->SetPoint(this->NumPoints,this->Points->GetPoint(0));
+      np+=1;
+    }
+  
+  this->Points->SetNumberOfPoints(rate*this->NumPoints+20);
+
+  this->NumPoints=0;
+  for (int j=0;j<np-1;j++)
+      {
+	double x1[3],x2[3];
+	tmpPoints->GetPoint(j,x1);
+	tmpPoints->GetPoint(j+1,x2);
+
+	for (int k=0;k<rate;k++)
+	    {
+	      float ratio2=((float)k)/((float)rate);
+	      float ratio1=1.0-ratio2;
+	      for (int l=0;l<=2;l++)
+		  x1[l]=ratio1*x1[l]+ratio2*x2[l];
+	      this->Points->SetPoint(this->NumPoints,x1);
+	      this->NumPoints++;
+	    }
+      }
+  
+  // Add Last Point if open if closed this is the starting point hence ignore
+  if (!ClosedCurve)
+    {
+      this->Points->SetPoint(this->NumPoints,tmpPoints->GetPoint(np-1));
+      this->NumPoints++;
+    }
+  
+  tmpPoints->Delete();
+  
+  this->Modified();
+
+}
+/* -------------------------------------------------------------------------*/ 
+void vtkpxBaseCurve::Smooth(float relaxation)
+{
+  if (this->NumPoints<5)
+      return;
+
+  relaxation=Frange(relaxation,0.0,0.99);
+  vtkPoints* tmpPoints=vtkPoints::New();
+  tmpPoints->SetNumberOfPoints(this->NumPoints);
+  int np=this->NumPoints;
+
+  for (int pass=0;pass<=1;pass++)
+      {
+	for (int j=0;j<np;j++)
+	    tmpPoints->SetPoint(j,this->Points->GetPoint(j));
+	
+	for (int i=0;i<np;i++)
+	    {
+	      int p0,p1;
+	      if (this->ClosedCurve)
+		  {
+		    p0=Icyclic(i-1,np);
+		    p1=Icyclic(i+1,np);
+		  }
+	      else
+		  {
+		    p0=Irange(i-1,0,np-1);
+		    p1=Irange(i+1,0,np-1);
+		  }
+	      
+	      double x0[3],x1[3],x[3];
+	      tmpPoints->GetPoint(p0,x0);
+	      tmpPoints->GetPoint(i,x);
+	      tmpPoints->GetPoint(p1,x1);
+	      
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    if (pass==0)
+			x[ia]=(1.0-relaxation)*x[ia]+0.5*relaxation*(x0[ia]+x1[ia]);
+		    else
+			x[ia]=(1.0-relaxation)*x[ia]+0.5*relaxation*(x0[ia]+x1[ia]);
+		  }
+	      this->Points->SetPoint(i,x);
+	    }
+	relaxation=-1.0*(relaxation+0.01);
+      }
+  tmpPoints->Delete();
+  
+  this->Modified();
+}
+/* -------------------------------------------------------------------------*/
+float basecurve_getperimeter(vtkPoints* points,int closed,int numpoints)
+{
+  float perimeter=0.0;
+
+  // Determine upper bound for loops
+  int maxp=numpoints-1;
+  if (closed)
+      maxp++;
+
+  // Find Perimeter Length
+  for (int i=0;i<maxp;i++)
+      {
+	double x1[3],x2[3];
+	points->GetPoint(i,x1);
+	points->GetPoint(Icyclic(i+1,numpoints),x2);
+	perimeter+=Fdist(x1[0],x1[1],x1[2],x2[0],x2[1],x2[2]);
+      }
+  return perimeter;
+}
+/* -------------------------------------------------------------------------*/
+int basecurve_intersect(double P1[3],double P2[3],double P3[3],double P4[3],double P[3],int plane,int level)
+{
+  double x1=0,y1=0,x2=0,y2=0,x3=0,y3=0,x4=0,y4=0;
+  switch (plane)
+      {
+      case 0:
+	x1=P1[1]; 	y1=P1[2]; 
+	x2=P2[1]; 	y2=P2[2]; 
+	x3=P3[1]; 	y3=P3[2]; 
+	x4=P4[1]; 	y4=P4[2]; 
+	break;	  
+      case 1:	  
+	x1=P1[0]; 	y1=P1[2]; 
+	x2=P2[0]; 	y2=P2[2]; 
+	x3=P3[0]; 	y3=P3[2]; 
+	x4=P4[0]; 	y4=P4[2]; 
+	break;	  
+      case 2:	  
+	x1=P1[0]; 	y1=P1[1]; 
+	x2=P2[0]; 	y2=P2[1]; 
+	x3=P3[0]; 	y3=P3[1]; 
+	x4=P4[0]; 	y4=P4[1]; 
+	break;
+      }
+  
+  double numA  =(x4-x3)*(y1-y3) - (y4-y3)*(x1-x3);
+  double numB  =(x2-x1)*(y1-y3) - (y2-y1)*(x1-x3);
+  double den   =(y4-y3)*(x2-x1) - (x4-x3)*(y2-y1);
+
+  if (den==0.0)
+      return 0;
+
+  double ua=numA/den;
+  double ub=numB/den;
+
+  if (ua==0.0 && ub==0.0)
+      return 0;
+
+  if (ua>0.0 && ua<1.0 && ub>0.0 && ub<1.0)
+      {
+	double x=x1+ua*(x2-x1);
+	double y=y1+ua*(y2-y1);
+	switch (plane)
+	    {
+	    case 0:
+	      P[0]=level;
+	      P[1]=x;
+	      P[2]=y;
+	      break;
+	    case 1:
+	      P[0]=x;
+	      P[1]=level;
+	      P[2]=y;
+	      break;
+	    case 2:
+	      P[0]=x;
+	      P[1]=y;
+	      P[2]=level;
+	      break;
+	    }
+	return 1;
+      }
+  return 0;
+}
+/* -------------------------------------------------------------------------*/
+int eliminate(vtkPoints* points,int numpoints,int begin,int end,int insert,double P[3])
+{
+  /*  vtkPoints* tmpPoints=vtkPoints::New();
+  tmpPoints->SetNumberOfPoints(numpoints);
+  for (int i=0;i<numpoints;i++)
+      tmpPoints->SetPoint(i,points->GetPoint(i));*/
+
+  begin=Irange(begin,0,numpoints-1);
+  end=Irange(end,0,numpoints-1);
+
+  //  insert=PXFalse;
+
+  if (begin<=end)
+      {
+	int offset=0;
+	if (insert)
+	    {
+	      points->SetPoint(begin,P);
+	      offset=1;
+	    }
+	for (int i=end+1;i<numpoints;i++)
+	    {
+	      int index=i-(end+1)+begin+offset;
+	      points->SetPoint(index,points->GetPoint(i));
+	      //fprintf(stderr,"Setting point %d <--- %d\n",index,i);
+	    }
+	numpoints=numpoints-(end-begin+1)+offset;
+	return numpoints;
+      }
+  else
+      {
+	for (int i=end+1;i<begin;i++)
+	    {
+	      int index=i-(end+1);
+	      points->SetPoint(index,points->GetPoint(i));
+	      //fprintf(stderr,"Setting point %d <--- %d\n",index,i);
+
+	    }
+	numpoints=(begin-(end+1));
+
+	if (insert)
+	    {
+	      int index=begin-(end+1);
+	      points->SetPoint(index,P);
+	      numpoints++;
+	    }
+	return numpoints;
+      }
+}
+/* -------------------------------------------------------------------------*/
+int checkIntersections(vtkPoints* points,int numpoints,int closed,
+		       int seed,double P[3],int longest,
+		       int& begin,int& end,
+		       int plane,int level)
+{
+  int found=-1;
+  if (!closed && seed==numpoints-1)
+      return 0;
+
+  int maxp=numpoints-2;
+  if (closed)
+    maxp++;
+
+  double P1[3],P2[3],P3[3],P4[3];
+  
+  points->GetPoint(seed,P1);
+  points->GetPoint(Icyclic(seed+1,numpoints),P2);
+  int test=seed+1;
+  while (found==-1 && test<=maxp)
+      {
+	/*fprintf(stderr,"\t ---> Testing %d,%d to %d,%d",seed,Icyclic(seed+1,numpoints),test,
+		Icyclic(test+1,numpoints));*/
+	points->GetPoint(test,P3);
+	points->GetPoint(Icyclic(test+1,numpoints),P4);
+	if (basecurve_intersect(P1,P2,P3,P4,P,plane,level))
+	    found=test;
+	else
+	    test++;
+	//	fprintf(stderr,"Found =%d\n",found);
+      }
+  
+  if (found==-1)
+      return 0;
+
+  if (!closed)
+      {
+	begin=seed+1;
+	end=found;
+	return 1;
+      }
+
+  int start[2],finish[2],dist[2];
+
+  start[0] =found+1;
+  finish[0]=  seed;
+  start[1]=seed+1;
+  finish[1]=found;
+
+  for (int kk=0;kk<=1;kk++)
+      dist[kk]=Icyclic(finish[kk]-start[kk],numpoints);
+
+
+  int keep=0;
+  if (dist[0]>dist[1])
+      keep=0;
+  else
+      keep=1;
+
+  if (longest==PXFalse)
+      keep=1-keep;
+  
+  begin=start[1-keep];
+  end=finish[1-keep];
+
+  /*fprintf(stderr,"Found Possible points Set 1 (%d,%d) dist=%d Set 2 (%d,%d) dist=%d selected=%d (%d to %d)\n\n",
+	  start[0],finish[0],dist[0],
+	  start[1],finish[1],dist[1],keep,begin,end);*/
+
+
+  return 1;		      
+}
+/* -------------------------------------------------------------------------*/	
+void vtkpxBaseCurve::RemoveIntersections(int keeplongest,int plane,int level)
+{
+  if (plane==-1)
+    {
+      int pl,lv;
+      this->GetCurrentInternalPlaneAndLevel(pl,lv);
+      plane=pl;
+      level=lv;
+    }
+
+  plane=Irange(plane,0,2);
+
+  int found=1;
+  if (this->NumPoints<3)
+      return;
+
+  int np=this->NumPoints-1;
+  if (this->ClosedCurve)
+      np+=1;
+
+  while (found==1 )
+      {
+	found=0;
+	int seed=0;
+	while (seed<np && found==0)
+	    {
+	      double P[3];
+	      int begin=-1,end=-1;
+	      int ok=checkIntersections(this->Points,this->NumPoints,this->ClosedCurve,seed,P,keeplongest,
+					begin,end,plane,level);
+
+	      /*	      fprintf(stderr,"Checking intersections seed=%d (num_land=%d,max=%d) begin=%d end=%d (found=%d) point=(%5.2f,%5.2f,%5.2f)\n",
+		seed,
+		this->NumPoints,np,begin,end,ok,P[0],P[1],P[2]);*/
+
+	      if (ok==0)
+		  {
+		    seed++;
+		    found=0;
+		  }
+	      else
+		  {
+		    found=1;
+		    //		    fprintf(stderr,"---> Going to eliminate\n");
+		    this->NumPoints=eliminate(this->Points,this->NumPoints,begin,end,PXTrue,P);
+		    np=this->NumPoints-1;
+		    if (this->ClosedCurve)
+			np+=1;    
+		    //		    fprintf(stderr,"---> Eliminated this->NumPoints=%d\n\n",this->NumPoints);
+		  }
+	    }
+      }
+  
+  this->Modified();
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxBaseCurve::Equispace(float sp)
+{
+  if (this->NumPoints<2)
+      return;
+
+  float perimeter=basecurve_getperimeter(this->Points,this->ClosedCurve,this->NumPoints);
+
+// Determine upper bound for loops
+  /* 
+  int maxp=this->NumPoints-1;
+  if (this->ClosedCurve)
+      maxp++;
+
+  // Find Perimeter Length
+  for (int i=0;i<maxp;i++)
+      {
+	float x1[3],x2[3];
+	this->Points->GetPoint(i,x1);
+	this->Points->GetPoint(Icyclic(i+1,this->NumPoints),x2);
+	perimeter+=Fdist(x1[0],x1[1],x1[2],x2[0],x2[1],x2[2]);
+      }*/
+
+  // Determine Appropriate Spacing 
+  float Spacing=sp;
+  if (Spacing<0.0)
+      Spacing=perimeter/float(this->NumPoints);
+
+  // Copy Point to temp array
+  vtkPoints* tmpPoints=vtkPoints::New();
+  tmpPoints->SetNumberOfPoints(this->NumPoints+1);
+  int np=this->NumPoints;
+  for (int j=0;j<this->NumPoints;j++)
+      tmpPoints->SetPoint(j,this->Points->GetPoint(j));
+  if (this->ClosedCurve)
+      {
+	tmpPoints->SetPoint(this->NumPoints,this->Points->GetPoint(0));
+	np++;
+      }
+
+  // Allocate New set of points 
+  int np2=int(perimeter/Spacing);
+  this->Points->SetNumberOfPoints(np2+10);
+
+  // Start New Set of Points at point 0
+  this->Points->SetPoint(0,tmpPoints->GetPoint(0));
+  this->NumPoints=1;
+
+  // Initialize Control Points x0 and x1 
+  int index=0;
+  double x0[3],x1[3];
+  tmpPoints->GetPoint(index,x0);
+  tmpPoints->GetPoint(index+1,x1);  
+  float segment=0.0;
+
+  while(index<np-1)
+      {
+	float part=Fdist(x0[0],x0[1],x0[2],x1[0],x1[1],x1[2]);
+	segment+=part;
+	while (segment>=Spacing)
+	    {
+	      float ratio=1.0-(segment-Spacing)/part;
+	      if (ratio<0.0)
+		ratio=0.0;
+	      if (ratio>1.0)
+		ratio=1.0;
+	      segment=segment-Spacing;
+	      double tx[3];
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    tx[ia]=(1.0-ratio)*x0[ia]+ratio*x1[ia];
+		  }
+	      this->Points->SetPoint(this->NumPoints,tx);
+	      this->NumPoints++;
+	    }
+	index++;
+	tmpPoints->GetPoint(index,x0);
+	tmpPoints->GetPoint(index+1,x1);
+      }
+
+  if (!this->ClosedCurve)
+      {
+	this->Points->SetPoint(this->NumPoints,tmpPoints->GetPoint(np-1));
+	this->NumPoints++;
+      }
+  tmpPoints->Delete();
+  this->Modified();
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxBaseCurve::ExtractImageContour(vtkImageData* image,int plane,int level,int frame,
+					float& threshold,int median,
+					float sigma)
+{
+  int outnp;
+
+  if (image==NULL)
+    return 0;
+
+  if (this->NumPoints==0)
+    return 0;
+
+  int dim[3];
+  image->GetDimensions(dim);
+
+  int pl,lv;
+
+  if (plane == -1)
+    {
+      this->GetCurrentInternalPlaneAndLevel(pl,lv);
+      plane=pl;
+      level=lv;
+    }
+
+  //  fprintf(stderr,"Selected Plane =%d Level=%d\n",plane,level);
+  
+  frame=Irange(frame,0,image->GetNumberOfScalarComponents()-1);
+
+  if (dim[plane]<0)
+      return 0;
+
+  if (this->NumPoints==0)
+      return 0;
+
+  int imagelevel=level;
+  if (imagelevel>=10000 || imagelevel<0)
+      {
+	this->GetCurrentInternalPlaneAndLevel(pl,lv);
+	level=lv;
+      }
+  imagelevel=Irange(imagelevel,0,dim[plane]-1);
+
+  // Pick out image slice 
+  // --------------------
+
+  vtkpxImageExtract* extr=vtkpxImageExtract::New();
+  extr->DebugOn();
+  extr->SetInput(image);
+  extr->SetCurrentPlane(plane);
+  extr->SetSliceNo(imagelevel);
+  extr->SetFrame(frame);
+  extr->DebugOff();
+  extr->Update();
+
+
+  vtkImageData* inp=vtkImageData::New();
+  inp->ShallowCopy(extr->GetOutput());
+  extr->Delete();
+
+  if (median>1)
+    {
+      vtkImageMedian3D* medianFilter=vtkImageMedian3D::New();
+      medianFilter->SetInput(inp);
+      median=Irange(median,0,9)*2+1;
+      medianFilter->SetKernelSize(median,median,1);
+      medianFilter->SetKernelSize(1,1,1);
+      medianFilter->Update();
+      inp->ShallowCopy(medianFilter->GetOutput());
+      medianFilter->Delete();
+    }
+
+  if (sigma>=0.5)
+    {
+      vtkImageGaussianSmooth* smoothFilter=vtkImageGaussianSmooth::New();
+      sigma=Frange(sigma,0.5,5.0);
+      smoothFilter->SetStandardDeviations(1.0,1.0,0.0);
+      smoothFilter->SetRadiusFactors(3.0*sigma,3.0*sigma,1);
+      smoothFilter->SetInput(inp);
+      smoothFilter->Update();
+      inp->ShallowCopy(smoothFilter->GetOutput());
+      smoothFilter->Delete();
+    }
+
+  
+  //  fprintf(stderr,"Plane=%d\n",plane);
+
+  if (threshold<=-100000.0)
+      {
+	threshold=0.0;
+	double x[3];
+	this->Points->GetPoint(0,x);
+	for (int i=-1;i<=1;i++)
+	    for (int j=-1;j<=1;j++)
+		{
+		  int y[3];
+		  switch (plane)
+		      {
+		      case 0:
+			y[0]=int(x[0]);
+			y[1]=int(x[1]+float(i));
+			y[2]=int(x[2]+float(j));
+			break;
+		      case 1:
+			y[1]=int(x[1]);
+			y[0]=int(x[0]+float(i));
+			y[2]=int(x[2]+float(j));
+			break;
+		      case 2:
+			y[2]=int(x[2]);
+			y[1]=int(x[1]+float(i));
+			y[0]=int(x[0]+float(j));
+			break;
+		      }
+		  threshold+=float(image->GetScalarComponentAsDouble(y[0],y[1],y[2],0))/9.0;
+		}
+      }
+
+
+  // Find Start Point 
+  double startx[3];
+  int stindex=0;
+  
+  this->Points->GetPoint(stindex,startx);
+  for (int j=0;j<=2;j++)
+    startx[j]=startx[j]*Spacing[j]+Origin[j];
+  
+  // Extract Contour
+  vtkContourFilter* contourExtractor = vtkContourFilter::New();
+  contourExtractor->SetInput(inp);
+  contourExtractor->SetValue(0,threshold);
+  contourExtractor->ComputeScalarsOff();
+  contourExtractor->ComputeGradientsOff();
+  contourExtractor->ComputeNormalsOff() ;
+  contourExtractor->Update();
+  outnp=contourExtractor->GetOutput()->GetPoints()->GetNumberOfPoints();
+  if (outnp<3)
+    {
+      fprintf(stderr,"Less than 3 points\n");
+      return 0;
+    }
+
+  SetFromPolyData(contourExtractor->GetOutput(),startx,plane,imagelevel);
+  contourExtractor->Delete();
+  
+  // Check whether curve is closed or not
+  // ------------------------------------
+  double x1[3],x2[3];
+  this->Points->GetPoint(0,x1);
+  this->Points->GetPoint(this->NumPoints-1,x2);
+  float dista=Fdist(x1[0],x1[1],x1[2],x2[0],x2[1],x2[2]);  
+  if (dista<3.0)
+    this->ClosedCurve=1;
+  else
+    this->ClosedCurve=0;
+
+  // Update Display
+  // --------------
+  //PointScale=0.5;
+  Equispace(2.5);
+    
+  inp->Delete();
+  return 1;
+}
+
+/* -------------------------------------------------------------------------*/
+float basecurve_getdirection(vtkPoints* points,int numpoints)
+{
+  double x0[3],x1[3],x2[3];
+
+  int np1=Irange(numpoints/3,1,numpoints-1);
+  int np2=Irange(2*np1,np1+1,numpoints-1);
+
+  points->GetPoint(  0,x0);
+  points->GetPoint(np1,x1);
+  points->GetPoint(np2,x2);
+  
+  float v1x=x1[0]-x0[0];
+  float v1y=x1[1]-x0[1];
+
+  float v2x=x2[0]-x0[0];
+  float v2y=x2[1]-x0[1];
+  float zz=(v1x*v2y-v2x*v1y);
+  
+  if (zz<0.0)
+      return 1.0;
+  else
+      return -1.0;
+}
+
+/* -------------------------------------------------------------------------*/
+vtkImageData* vtkpxBaseCurve::UpdateSnake(vtkImageData* image,vtkImageData* energyMap,
+						 int plane,int level,int frame,
+						 float& residual,float edge,float baloon,
+						 float smooth,
+						 float sigma,float step,int maxiter)
+{
+  const int debugmode=0;
+
+  if (image==NULL)
+      return NULL;
+  
+  if (this->NumPoints<1)
+      return 0;
+  
+  int dim[3];
+  image->GetDimensions(dim);
+  plane=Irange(plane,0,2);
+  
+  frame=Irange(frame,0,image->GetNumberOfScalarComponents()-1);
+
+  if (dim[plane]<0)
+      return 0;
+  level=Irange(level,0,dim[plane]);
+
+  sigma=Frange(sigma,0.1,5.0);
+  
+  if (energyMap==NULL)
+    energyMap=vtkpxBaseCurve::CreateEnergyMap(image,plane,level,frame,sigma);
+  
+  float max_move=0.0;
+  float dr=Frange(step,0.1,3.0);
+	  
+  double range[2],scale_int;
+  energyMap->GetPointData()->GetScalars()->GetRange(range);
+  if (range[1]==range[0])
+      range[1]=range[0]+1.0;
+
+  scale_int=fabs(range[1]-range[0])/10.0;
+  /*  if (debugmode)
+      fprintf(stderr,"Intensity Range=%f,%f sc=%f\n",range[0],range[1],scale_int);*/
+  
+
+  float direction=basecurve_getdirection(this->Points,this->NumPoints);
+
+  double sp[3],ori[3];
+  energyMap->GetSpacing(sp);
+  energyMap->GetOrigin(ori);
+  int dim2[3];
+  energyMap->GetDimensions(dim2);
+  
+  float tolerance=residual;
+  maxiter=Irange(maxiter,1,500);
+
+  for(int n=0;n<maxiter;n++)
+      {
+	if (debugmode)
+	    fprintf(stderr,"Starting Iteration %d/%d ",n,maxiter);
+	
+	for(int current=0;current<this->NumPoints;current++)
+	    {
+	      // Get Point Coordinates in pixels
+	      double x[3];
+	      this->Points->GetPoint(current,x);
+	      
+	      // Point coordinates in mm
+	      double xc[3];
+	      for (int ia=0;ia<=2;ia++)
+		  xc[ia]=x[ia]*sp[ia]+ori[ia];
+
+	      // Find neighbouring point coordinates in pixels
+	      int prevpoint1,nextpoint1;//prevpoint2,nextpoint2;
+	      if (this->ClosedCurve)
+		  {
+		    // prevpoint2=Icyclic(current-2,this->NumPoints);
+		    prevpoint1=Icyclic(current-1,this->NumPoints);
+		    nextpoint1=Icyclic(current+1,this->NumPoints);
+		    //nextpoint2=Icyclic(current+2,this->NumPoints);
+		  }
+	      else
+		  {
+		    //prevpoint2=Irange(current-2,0,this->NumPoints-1);
+		    prevpoint1=Irange(current-1,0,this->NumPoints-1);
+		    nextpoint1=Irange(current+1,0,this->NumPoints-1);
+		    //nextpoint2=Irange(current+2,0,this->NumPoints-1);
+		  }
+	      
+	      double xp1[3],xn1[3];//,xn1[3],xn2[3];
+	      //this->Points->GetPoint(prevpoint2,xp2);
+	      this->Points->GetPoint(prevpoint1,xp1);
+	      this->Points->GetPoint(nextpoint1,xn1);
+	      //this->Points->GetPoint(nextpoint2,xn2);
+
+	      // Estimate Normal
+	      float tx=sp[0]*(xn1[0]-xp1[0]);
+	      float ty=sp[1]*(xn1[1]-xp1[1]);
+	      float mag=Frange(sqrt(tx*tx+ty*ty),0.01,100.0);
+	      float nx=-direction*ty/mag;
+	      float ny=direction*tx/mag;
+	      
+	      float inside=1.0;
+
+	      /*float dot=
+		  ((x[0]-0.5*(xp1[0]+xn1[0]))*nx)+
+		      ((x[1]-0.5*(xp1[1]+xn1[1]))*ny);
+	      if (dot<0.0)
+		  inside=-1.0;*/
+	      
+	      // Estimate External Energy Function Change Along Normal
+	      float ext_f=(vtkpxBaseCurve::GetImageValue(energyMap,xc[0]+dr*nx,xc[1]+dr*ny,0,sp,ori,dim2)-
+			   vtkpxBaseCurve::GetImageValue(energyMap,xc[0]-dr*nx,xc[1]-dr*ny,0,sp,ori,dim2))
+		  /(2.0*dr*scale_int);
+	      float ext_2f=(vtkpxBaseCurve::GetImageValue(energyMap,xc[0]+dr*nx,xc[1]+dr*ny,0,sp,ori,dim2)+
+			    vtkpxBaseCurve::GetImageValue(energyMap,xc[0]-dr*nx,xc[1]-dr*ny,0,sp,ori,dim2))/(range[1]-range[0]);
+
+	      // If there is no gradient around just expand
+	      if (ext_2f<0.1)
+		  ext_f=0.05;
+	      
+	      // Estimate Internal Energy Function Along Normal
+	      float ex11 = (2.0*(x[0]+dr*nx)-(xp1[0]+xn1[0]));
+	      float ey11 = (2.0*(x[1]+dr*ny)-(xp1[1]+xn1[1]));
+	      float ex12 = (2.0*(x[0]-dr*nx)-(xp1[0]+xn1[0]));   
+	      float ey12 = (2.0*(x[1]-dr*ny)-(xp1[1]+xn1[1]));
+	      
+	      float int_f = ( sqrt(ex11*ex11+ey11*ey11) -  sqrt( ex12*ex12+ey12*ey12) )/(2.0*dr);
+	      
+	      // Find Total Shift
+	      float shift=(-smooth*int_f + edge* ext_f + baloon*inside);
+	      float dx= 0.2*shift*nx;
+	      float dy= 0.2*shift*ny;
+	      this->Points->SetPoint(current,x[0]+dx,x[1]+dy,x[2]);
+
+	      // Check for convergence
+	      float ds=sqrt(dx*dx+dy*dy);
+	      max_move=Fmax(ds,max_move);
+	    }
+	if (debugmode)
+	    fprintf(stderr,"Max_move =%f tolerance=%f\n",max_move,tolerance);
+	
+	if (max_move<tolerance)
+	    {
+	      n=maxiter+1;
+	    }
+	else if (int(n/20)*20==n)
+	    {
+	      RemoveIntersections(PXTrue,plane,level);
+	    }
+      }
+  
+  residual=max_move;
+  float perimeter=basecurve_getperimeter(this->Points,this->ClosedCurve,this->NumPoints);
+  float Spacing=perimeter/float(this->NumPoints);
+  float newSpacing=Frange(Spacing*0.95,1.5,20.0);
+  /*if (newSpacing<2.0)
+    PointScale=0.5;*/
+  RemoveIntersections(PXTrue,plane,level);
+  Equispace(newSpacing);
+  
+  // Update Display
+  // --------------
+  /*fprintf(stderr,"Perimeter=%f this->NumPoints=%d -> %d Spacing=%f -> %f\n",
+	  perimeter,np,this->NumPoints,Spacing,newSpacing);*/
+
+  return energyMap;
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxBaseCurve::Execute()
+{
+  vtkPolyData* output = this->GetOutput();
+  
+  if ( (this->ShowControls==0 && this->ShowCurve==0 && this->ShowBoundingBox==0) || this->NumPoints<1)
+    {
+      output->Initialize();
+      // Just Create a dummy sphere in this case 
+      vtkSphereSource* sphere=vtkSphereSource::New();
+      sphere->SetRadius(0.01);
+      sphere->SetThetaResolution(3);
+      sphere->SetPhiResolution(3);
+      sphere->Update();
+      output->CopyStructure(sphere->GetOutput());
+      sphere->Delete();
+      return;
+    }
+
+  /*fprintf(stderr,"Drawing Curve  %d (showc=%d showcont=%d)\n",
+    this->NumPoints,this->ShowCurve,this->ShowControls);*/
+
+  float pscalefactor=this->PointScale;
+  pscalefactor*=this->Spacing[2];
+  //  fprintf(stderr,"Point Scale %f --> %f\n",this->PointScale,pscalefactor);
+
+  vtkPolyData* curve=vtkPolyData::New();
+  
+  vtkPoints    *c_points    = vtkPoints::New();
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  
+  c_points->Allocate(this->NumPoints,10);
+  c_lines->Allocate(this->NumPoints-1+this->ClosedCurve,5);
+  
+  int np=this->NumPoints;
+  int index=-1;
+  vtkIdType pt[2];
+  
+  for (int i=0;i<np;i++)
+    {
+      double x[3],tx[3];
+      this->Points->GetPoint(i,x);
+      int add=1;
+
+      if (i>0)
+	{
+	  this->Points->GetPoint(i-1,tx);
+	  if (Fsamepoint(x[0],x[1],x[2],tx[0],tx[1],tx[2],0.05))
+	    add=0;
+	}
+
+      if (add==1)
+	{
+	  ++index;
+	  for (int j=0;j<=2;j++)
+	    x[j]=x[j]*Spacing[j]+Origin[j];
+	  c_points->InsertNextPoint(x);
+      
+	  if (i<np-1 && np>1)
+	    {
+	      pt[0]=index;
+	      pt[1]=index+1;
+	      c_lines->InsertNextCell(2,pt);
+	    }
+	}
+    }
+  
+  if (this->ClosedCurve==1)
+    {
+      pt[0]=index;
+      pt[1]=0;
+      c_lines->InsertNextCell(2,pt);
+    }
+    
+  
+  curve=vtkPolyData::New();
+  curve->SetPoints(c_points);
+  curve->SetLines(c_lines);
+  c_points->Delete();
+  c_lines->Delete();
+
+
+  vtkAppendPolyData* append=vtkAppendPolyData::New();
+
+  if (this->ShowBoundingBox && np>2)
+    {
+      vtkOutlineFilter* outline=vtkOutlineFilter::New();
+      outline->SetInput(curve);
+      outline->Update();
+      append->AddInput(outline->GetOutput());
+      outline->Delete();
+    }
+
+  if (this->ShowCurve && np>1)
+    {
+      vtkTubeFilter* tube=vtkTubeFilter::New();
+      //fprintf(stderr,"Doing Tube\n");
+      //tube->DebugOn();
+      tube->SetInput(curve);
+      tube->SetRadius(0.375*pscalefactor);
+      tube->SetNumberOfSides(4);
+      tube->SetVaryRadiusToVaryRadiusOff();
+      tube->Update();
+      append->AddInput(tube->GetOutput());
+      tube->Delete();
+
+    }
+
+  if (this->ShowControls)
+    {
+      vtkGlyph3D* glyph=vtkGlyph3D::New();
+      if (this->ControlsDisplayMode==0)
+	{
+	  vtkpxCrossHairSource* sphere=vtkpxCrossHairSource::New();
+	  sphere->SetLength(pscalefactor);
+	  sphere->Update();
+	  glyph->SetSource(sphere->GetOutput());
+	  sphere->Delete();
+	}
+      else
+	{
+	  vtkDiskSource* disk=vtkDiskSource::New();
+	  disk->SetInnerRadius(pscalefactor*0.5);
+	  disk->SetOuterRadius(pscalefactor);
+	  disk->SetRadialResolution(2);
+	  disk->SetCircumferentialResolution(8);
+	  disk->Update();
+	  glyph->SetSource(disk->GetOutput());
+	  disk->Delete();
+	}
+      glyph->SetInput(curve);
+      glyph->Update();
+      append->AddInput(glyph->GetOutput());
+      glyph->Delete();
+    }
+  append->Update();
+
+
+  output->CopyStructure(append->GetOutput());
+  append->Delete();
+  curve->Delete();
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxBaseCurve::RescaleSpacing(double sx,double sy,double sz)
+{
+  double sp[3],ori[3];
+  for (int ia=0;ia<=2;ia++)
+    ori[ia]=this->Origin[ia];
+
+  sp[0]=sx;
+  sp[1]=sy;
+  sp[2]=sz;
+  RescaleOriginSpacing(ori,sp);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxBaseCurve::RescaleOriginSpacing(double ori[3],double sp[3])
+{
+  int donothing=1;
+  int i;
+  for (i=0;i<=2;i++)
+    if (this->Spacing[i]!=sp[i] || this->Origin[i]!=ori[i])
+      donothing=0;
+
+  if (donothing)
+    return;
+
+  double oldsp[3],oldori[3];
+  for (i=0;i<=2;i++)
+    {
+      oldsp[i]=this->Spacing[i];
+      oldori[i]=this->Origin[i];
+    }
+
+  this->SetSpacing(sp);
+  this->SetOrigin(ori);
+
+  int np=this->NumPoints;
+  for (i=0;i<np;i++)
+    {
+      double x[3];
+      this->Points->GetPoint(i,x);
+      for (int ia=0;ia<=2;ia++)
+	{
+	  x[ia]=x[ia]*oldsp[ia]+oldori[ia];
+	  x[ia]=(x[ia]-this->Origin[ia])/this->Spacing[ia];
+	}
+      this->Points->SetPoint(i,x);
+    }
+  this->Modified();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxBaseCurve::AddToImage(vtkImageData* image,float value)
+{
+  if (this->NumPoints<2)
+    return 0;
+  
+  if (image==NULL)
+    return 0;
+
+  vtkDataArray* scal=image->GetPointData()->GetScalars();
+  if (scal==NULL)
+    return 0;
+
+  vtkTransform* trans=vtkTransform::New();
+  trans->Identity();
+  trans->PostMultiply();
+  trans->Scale(this->Spacing);
+  trans->Translate(this->Origin);
+
+  for(int i=1;i<=this->NumPoints;i++)
+    {
+      double x1[3],x2[3],p[3],d[3],tx[3],grad[3];
+      int k;
+
+      this->Points->GetPoint(i-1,x1);
+      if (i!=this->NumPoints)
+	this->Points->GetPoint(i,x2);
+      else
+	this->Points->GetPoint(0,x2);
+
+      float maxdist=0.0;
+      int   maxindex=0;
+      
+      for (k=0;k<=2;k++)
+	{
+	  d[k]=x2[k]-x1[k];
+	  if (fabs(d[k])>fabs(maxdist))
+	    {
+	      maxdist=d[k];
+	      maxindex=k;
+	    }
+	}
+
+      // fprintf(stderr,"\nPoint 1 = [%.1f %.1f %.1f ]\t",x1[0],x1[1],x1[2]);
+      // fprintf(stderr,"Point 2 = [%.1f %.1f %.1f ]\t",x2[0],x2[1],x2[2]);
+      // fprintf(stderr,"Dist    = [%.1f %.1f %.1f ]\t%f,ind=%d\t",d[0],d[1],d[2],maxdist,maxindex);
+      
+      for (k=0;k<=2;k++)
+	{
+	  if (d[k]!=0.0)
+	    grad[k]=d[k]/maxdist;
+	  else
+	    grad[k]=0.0;
+	}
+      
+      // fprintf(stderr,"Gradients = [ %.2f %.2f %.2f ] %.2f \n",grad[0],grad[1],grad[2],maxdist);
+      
+      
+      for (float dt=0.0;dt<fabs(maxdist);dt+=0.25)
+	{
+	  if (maxdist==0)
+	    {
+	      for (k=0;k<=2;k++)
+		p[k]=x1[k];
+	    }
+	  else
+	    {
+	      for (k=0;k<=2;k++)
+		p[k]=x1[k]+(dt/fabs(maxdist))*d[k];
+	    }
+	  
+	  // fprintf(stderr,"Adding point %.2f (%.1f %.1f %.1f)\n",dt,p[0],p[1],p[2]);
+	  
+	  trans->TransformPoint(p,tx);
+	  int index=image->FindPoint(tx);
+	  
+	  if (index>0)
+	    scal->SetComponent(index,0,value);
+	}
+    
+      if (this->ClosedCurve==0 && i==this->NumPoints-1)
+	++i;
+    }
+  return 1;
+}
+
+//------------------------------------------------------------------------------
+// Help with Snake Implementation
+//------------------------------------------------------------------------------
+
+double vtkpxBaseCurve::GetDoubleVoxel(vtkImageData* img,int i,int j,int k,int dimensions[3])
+{
+  if (img==NULL)
+      return 0.0;
+
+  i=Irange(i,0,dimensions[0]-1);
+  j=Irange(j,0,dimensions[1]-1);
+  k=Irange(k,0,dimensions[2]-1);
+  int act=0;//img->GetPointData()->GetScalars()->GetActiveComponent();
+  
+  return img->GetScalarComponentAsDouble(i,j,k,act);
+}
+
+
+double vtkpxBaseCurve::GetImageValue(vtkImageData* img,double x,double y,double z,double spacing[3],double origin[3],int dim[3])
+{
+  //  vtkScalars* imageScalars=img->GetPointData()->GetScalars();
+  
+  double p[3];
+  p[0]=x;p[1]=y;p[2]=z;
+  
+  // Find Point ``to the left''
+  int pt[3];
+  for (int id=0;id<=2;id++)
+      pt[id]=int((p[id]-origin[id])/spacing[id]);
+
+  // Calculate Weights
+  double fpt[3][2];
+  for (int i=0;i<=2;i++)
+      {
+	fpt[i][0]=double((pt[i]+1)*spacing[i])+origin[i]-p[i];
+	fpt[i][1]=p[i]-(double(pt[i]*spacing[i])+origin[i]);
+	double s=fpt[i][0]+fpt[i][1];
+	if (s==0.0)
+	    {
+	      for (int k=0;k<=1;k++)
+		  fpt[i][k]=0.5;
+	    }
+	else
+	    {
+	      for (int k=0;k<=1;k++)
+		  fpt[i][k]/=s;
+	    }
+      }    
+  
+  // Find Value
+  double sum=0.0;
+  for (int ia=0;ia<=1;ia++)
+      for (int ib=0;ib<=1;ib++)
+	  for (int ic=0;ic<=1;ic++)
+	      {
+		double v=GetDoubleVoxel(img,pt[0]+ia,pt[1]+ib,pt[2]+ic,dim);
+		double w=fpt[0][ia]*fpt[1][ib]*fpt[2][ic];
+		sum+=v*w;
+	      }
+  return sum;
+ 
+}
+
+double vtkpxBaseCurve::GetImageVoxel(vtkImageData* img,double x,double y,double z,int dim[3])
+{
+  if (img==NULL)
+      return 0.0;
+
+  x=Frange(x,0.0,dim[0]-2);
+  y=Frange(y,0.0,dim[1]-2);
+  z=Frange(z,0.0,dim[2]-2);
+
+  int x1=(int)x,x2=x1+1;
+  int y1=(int)y,y2=y1+1;
+  int z1=(int)z,z2=z1+1;
+
+  int act=0;//img->GetPointData()->GetScalars()->GetActiveComponent();
+
+  return (img->GetScalarComponentAsDouble(x1,y1,z1,act)*(x2-x)*(y2-y)*(z2-z)+
+	  img->GetScalarComponentAsDouble(x1,y2,z1,act)*(x2-x)*(y-y1)*(z2-z)+
+	  img->GetScalarComponentAsDouble(x2,y1,z1,act)*(x-x1)*(y2-y)*(z2-z)+
+	  img->GetScalarComponentAsDouble(x2,y2,z1,act)*(x-x1)*(y-y1)*(z2-z)+
+	  img->GetScalarComponentAsDouble(x1,y1,z2,act)*(x2-x)*(y2-y)*(z-z1)+
+	  img->GetScalarComponentAsDouble(x1,y2,z2,act)*(x2-x)*(y-y1)*(z-z1)+
+	  img->GetScalarComponentAsDouble(x2,y1,z2,act)*(x-x1)*(y2-y)*(z-z1)+
+	  img->GetScalarComponentAsDouble(x2,y2,z2,act)*(x-x1)*(y-y1)*(z-z1));
+  
+}
+
+
+vtkImageData*  vtkpxBaseCurve::CreateEnergyMap(vtkImageData* image,int plane,int level,int fr,float sigma)
+{
+  if (image==NULL)
+    return NULL;
+  vtkpxImageExtract* extr=vtkpxImageExtract::New();
+  extr->SetInput(image);
+  extr->SetCurrentPlane(plane);
+  extr->SetSliceNo(level);
+  extr->SetFrame(fr);
+  extr->Update();
+	
+  vtkImageGaussianSmooth* smoothFilter=vtkImageGaussianSmooth::New();
+  smoothFilter->SetStandardDeviations(sigma,sigma,0.0);
+  smoothFilter->SetRadiusFactors(3.0*sigma,3.0*sigma,1);
+  smoothFilter->SetInput(extr->GetOutput());
+  smoothFilter->Update();
+  
+  vtkImageGradientMagnitude* magn=vtkImageGradientMagnitude::New();
+  magn->SetInput(smoothFilter->GetOutput());
+  magn->SetHandleBoundaries(1);
+  magn->SetDimensionality(2);
+  magn->Update();
+  
+  extr->Delete();
+  smoothFilter->Delete();
+  
+  vtkImageData* energyMap=vtkImageData::New();
+  energyMap->ShallowCopy(magn->GetOutput());
+  magn->Delete();
+  return energyMap;
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxBaseCurve::ExportToPolyData(vtkPolyData* output,float d)
+{
+  if (d>0.1)
+    this->Equispace(d);
+
+  output->Initialize();
+
+  vtkPoints    *c_points    = vtkPoints::New();
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  
+  c_points->Allocate(this->NumPoints,10);
+  c_lines->Allocate(this->NumPoints-1+this->ClosedCurve,5);
+  
+  int np=this->NumPoints;
+  int index=-1;
+  vtkIdType pt[2];
+  
+  for (int i=0;i<np;i++)
+    {
+      double x[3],tx[3];
+      this->Points->GetPoint(i,x);
+      int add=1;
+
+      if (i>0)
+	{
+	  this->Points->GetPoint(i-1,tx);
+	  if (Fsamepoint(x[0],x[1],x[2],tx[0],tx[1],tx[2],0.05))
+	    add=0;
+	}
+
+      if (add==1)
+	{
+	  ++index;
+	  for (int j=0;j<=2;j++)
+	    x[j]=x[j]*Spacing[j]+Origin[j];
+	  c_points->InsertNextPoint(x);
+      
+	  if (i<np-1 && np>1)
+	    {
+	      pt[0]=index;
+	      pt[1]=index+1;
+	      c_lines->InsertNextCell(2,pt);
+	    }
+	}
+    }
+  
+  output->SetPoints(c_points);
+  output->SetLines(c_lines);
+  c_points->Delete();
+  c_lines->Delete();
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxBaseCurve.h b/bioimagesuite30_src/Common/vtkpxBaseCurve.h
new file mode 100644
index 0000000..6717313
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxBaseCurve.h
@@ -0,0 +1,309 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxBaseCurve.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxBaseCurve - stores and manipulates a set of points.
+// .SECTION Description
+// The points can be represented either as landmarks or as an open or closed space curve.
+// The output of this class is vtkPolyData
+// This class essentially captures major aspects of curves as used in Medical Image Analysis.
+// The points are stored in voxel coordinates and are scaled to mm using the Origin and Spacing
+// parameters. If you want to store points as mm simply set spacing to 1.0 1.0 1.0 and Origin to 
+// 0.0 0.0 0.0
+// There are facilities for calculating areas, resampling, smoothing, iso-contour extraction and
+// snakes
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkPoints vtkPolyData vtkPolyDataSource 
+
+
+
+#ifndef __vtkpxBaseCurve_h
+#define __vtkpxBaseCurve_h
+
+class vtkPoints;
+class vtkPolyData;
+
+#include "pxcontour.h"
+#include "vtkpxUtil.h"
+#include "vtkPolyDataSource.h"
+
+class vtkpxBaseCurve : public vtkPolyDataSource 
+{
+public:
+  static vtkpxBaseCurve *New();
+  vtkTypeMacro(vtkpxBaseCurve,vtkPolyDataSource);
+
+public:
+
+  // Description:
+  // Get the Number Of Points -- this is different from the actual number of points stored in the Points ivar
+  vtkGetMacro(NumPoints,int);
+
+  // Description:
+  // For display purposes -- set the radius of the spheres used to display the points
+  // also set the radius (x0.5) of the tubes used to display lines if ShowCurve=1
+  vtkGetMacro(PointScale,double);
+  vtkSetMacro(PointScale,double);
+
+  // Description:
+  // Determines whether the curve is treated as if it were open or closed
+  vtkGetMacro(ClosedCurve,int);
+  vtkSetMacro(ClosedCurve,int);
+
+  // Description:
+  // Show or hide spheres representing individual points
+  vtkGetMacro(ShowControls,int);
+  vtkSetMacro(ShowControls,int);
+
+// Description:
+  // Show or hide spheres representing individual points
+  vtkGetMacro(ControlsDisplayMode,int);
+  vtkSetClampMacro(ControlsDisplayMode,int,0,1);
+  void SetControlsDisplayModeToSphere() { this->SetControlsDisplayMode(0);}
+  void SetControlsDisplayModeToDisc() { this->SetControlsDisplayMode(1);}
+  
+
+  // Description:
+  // Show or hide the lines joining the points
+  vtkGetMacro(ShowCurve,int);
+  vtkSetMacro(ShowCurve,int);
+
+  // Description:
+  // Show or hide the lines joining the points
+  vtkGetMacro(ShowBoundingBox,int);
+  vtkSetMacro(ShowBoundingBox,int);
+
+  // Description:
+  // Scale factors to scale from voxels (used for internal storage) to mm using for the ouput
+  vtkGetVectorMacro(Spacing,double,3);
+  vtkSetVectorMacro(Spacing,double,3);
+
+  // Description:
+  // Shift factor to translate from voxels (used for internal storage) to mm using for the ouput
+  vtkGetVectorMacro(Origin,double,3);
+  vtkSetVectorMacro(Origin,double,3);
+
+  // Description:
+  // Change voxel coordinates to reflect new spacing/origin
+  void RescaleOriginSpacing(double ori[3],double sp[3]);
+  void RescaleSpacing(double sx,double sy,double sz);
+  
+  // I/O
+  // Description:
+  // Store in .land format
+  virtual int          Save(const char* fname);  
+
+  // Description:
+  // Load from .land format
+  virtual int          Load(const char* fname);
+
+  // Description:
+  // Scale internal points to mm and make Points ready for export (adjusting number of points etc).
+  // Use this before GetPoints() is called
+  virtual int          Compact();
+
+  // Description:
+  // Gets internal storage. Use Compact before calling this
+  virtual vtkPoints*   GetPoints();
+
+  // Description:
+  // Copy another curve
+  virtual void         Copy(vtkpxBaseCurve* other);
+
+  // Description:
+  // Get Individual Point Coordinate
+  virtual void         GetPoint(int index,double& x,double& y,double &z);
+
+  // Description:
+  // Set Point index to (x,y,z), if scaled=1 then we assume that (x,y,z) are in mm else
+  // if scaled=0 they are treated as voxels
+  virtual void         SetPoint(int index,double x,double y,double z,int scaled);
+  virtual void         SetPoint(int index,double x,double y,double z) { SetPoint(index,x,y,z,1);}
+
+  // Description:
+  // Add point (x,y,z), if scaled=1 then we assume that (x,y,z) are in mm else
+  // if scaled=0 they are treated as voxels
+  virtual void         AddPoint(double x,double y,double z,int scaled);
+  virtual void         AddPoint(double x,double y,double z) { AddPoint(x,y,z,1);}
+
+  // Description:
+  // Delete point i
+  virtual void         DeletePoint(int i=-1);
+
+
+  // Description:
+  // Delete All points
+  virtual void         DeleteAllPoints();
+
+  //BTX
+
+  // Interface with PXContour and vtkPolyData
+  virtual int          StoreInContour(PXContour* cntr,int plane);
+  virtual int          SetFromContour(PXContour* cntr,int plane=2,int level=0);
+  virtual int          SetFromPolyData(vtkPolyData* polydata,double x[3],int plane=-1,int level=0);
+
+  //ETX
+
+
+  // Description:
+  // Get Plane Based on Points
+  virtual int GetCurrentInternalPlane();
+  virtual void GetCurrentInternalPlaneAndLevel(int& plane,int& level);
+
+
+  // Description:
+  // Using the first point as origin and the second to find the radius
+  // it creates a plance circle with the other coordinate=level and plane
+  // plane=0 XY, 1=XZ, 2=YZ
+  virtual int          CreateCircle(int plane,int level);
+
+  // Description:
+  // Sets points from points
+  virtual int          SetFromPoints(vtkPoints* points);
+
+  // Curve Properties
+  // Description:
+  // Finds closest point with distance < threshold
+  // If scale==1 px is assumed to be in mm otherwise in voxel
+  virtual int          FindClosestPoint(double px[3],double threshold,int scale=1);
+  virtual int          FindClosestPoint(double x,double y, double z,double threshold,int scale=1);
+
+  // Description:
+  // Return area of curve in plane plane (see CreateCircle)
+  virtual float        GetPlaneArea(int plane=2);  
+  virtual float        GetLength();
+
+  //BTX
+  virtual int          ExtractVOIProperties(vtkImageData* image,int plane,int level,int fr,float& mean,float& sigma);
+  virtual float        GetAreaFromPixels(int num,int image_plane);
+  //ETX
+
+  // Curve Operations 
+  // Description:
+  // Resamples curve by factor rate
+  virtual void         Sample(int rate=2);
+
+  // Description:
+  // Subsamples curve by factor rate
+  virtual void         SubSample(int rate=2);
+
+  // Description:
+  // Smooth curve
+  virtual void         Smooth(float relaxation=0.33);
+
+  //BTX
+  virtual void         RemoveIntersections(int keeplongest,int image_plane,int image_level);
+  //ETX
+
+  // Description:
+  // Equispace curve at distance sp
+  virtual void         Equispace(float sp=-1.0);
+
+  //BTX
+  virtual int ExtractImageContour(vtkImageData* image,
+				  int plane,int level,int frame,
+				  float& threshold,int median=0,
+				  float sigma=0.0);
+
+
+  virtual vtkImageData*  UpdateSnake(vtkImageData* image,vtkImageData* energyMap,
+					    int plane,int level,int frame,
+					    float& residual,float edge=1.0,float baloon=0.0,
+					    float smooth=1.0,float sigma=1.0,float step=0.2,int maxiter=10);
+  //ETX
+
+  virtual int AddToImage(vtkImageData* image,float value);
+
+  //BTX
+  // Interpolation Stuff
+  static double GetDoubleVoxel(vtkImageData* img,int i,int j,int k,int dim[3]);
+  static double GetImageVoxel(vtkImageData* img,double x,double y,double z,int dim[3]);
+  static double GetImageValue(vtkImageData* img,double x,double y,double z,double spacing[3],double origin[3],int dim[3]);
+  //ETX
+
+  // Segmentation Stuff
+  // Description:
+  // Create Edge map for slice=level plane=plane, sigma=sigma 
+  static  vtkImageData*  CreateEnergyMap(vtkImageData* image,int plane,int level,int frame,float sigma);
+  
+  // Description:
+  // Export to poly data after equisampling resampling to distance d (d<=0.0 -> no resampling)
+  int ExportToPolyData(vtkPolyData* output,float d);
+
+  
+protected:
+  vtkpxBaseCurve();
+  virtual ~vtkpxBaseCurve();
+
+  vtkpxBaseCurve(const vtkpxBaseCurve&) {};
+  void operator=(const vtkpxBaseCurve&) {};
+
+  vtkPoints             *Points;
+  int                   NumPoints;
+  int                   ShowControls;
+  int                   ControlsDisplayMode;
+  float                 PointScale;
+  double                Spacing[3];
+  double                Origin[3];
+  int                   ClosedCurve;
+  int                   ShowCurve;
+  int                   ShowBoundingBox;
+
+  void Execute();  
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxCrossHairSource.cpp b/bioimagesuite30_src/Common/vtkpxCrossHairSource.cpp
new file mode 100644
index 0000000..13b7a2d
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxCrossHairSource.cpp
@@ -0,0 +1,128 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+ see vtkpxCrossHairSource.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+#include "vtkAppendPolyData.h"
+#include "vtkCubeSource.h"
+#include "vtkSphereSource.h"
+#include "vtkObjectFactory.h"
+#include "vtkPolyData.h"
+#include "vtkpxCrossHairSource.h"
+
+//------------------------------------------------------------------------------
+vtkpxCrossHairSource* vtkpxCrossHairSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxCrossHairSource");
+  if(ret)
+    {
+      return (vtkpxCrossHairSource*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxCrossHairSource;
+}
+
+// Construct object with no children.
+vtkpxCrossHairSource::vtkpxCrossHairSource()
+{
+  this->Position[0]=0;this->Position[1]=0;this->Position[2]=0;
+  this->Thickness=0.5;
+  this->Length=2.0;
+  this->ShowSphere=1;
+}
+/* -------------------------------------------------------------------------*/
+ 
+vtkpxCrossHairSource::~vtkpxCrossHairSource()
+{
+  
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxCrossHairSource::Execute()
+{
+  vtkAppendPolyData* append=vtkAppendPolyData::New();
+  
+  for (int axis=0;axis<=2;axis++)
+    {
+      vtkCubeSource* cube=vtkCubeSource::New();
+      switch (axis)
+	{
+	case 0: // X-axis
+	  cube->SetBounds(this->Position[0]-this->Length,
+			  this->Position[0]+this->Length,
+			  this->Position[1]-this->Thickness,
+			  this->Position[1]+this->Thickness,
+			  this->Position[2]-this->Thickness,
+			  this->Position[2]+this->Thickness);
+	  break;
+	case 1:
+	  cube->SetBounds(this->Position[0]-this->Thickness,
+			  this->Position[0]+this->Thickness,
+			  this->Position[1]-this->Length,
+			  this->Position[1]+this->Length,
+			  this->Position[2]-this->Thickness,
+			  this->Position[2]+this->Thickness);
+	  break;
+	case 2:
+	  cube->SetBounds(this->Position[0]-this->Thickness,
+			  this->Position[0]+this->Thickness,
+			  this->Position[1]-this->Thickness,
+			  this->Position[1]+this->Thickness,
+			  this->Position[2]-this->Length,
+			  this->Position[2]+this->Length);
+	  break;
+	}
+      cube->Update();
+      append->AddInput(cube->GetOutput());
+      cube->Delete();
+    }
+
+  if (this->ShowSphere)
+    {
+      vtkSphereSource* sphere=vtkSphereSource::New();
+      sphere->SetCenter(this->Position);
+      sphere->SetRadius(this->Length);
+      sphere->Update();
+      append->AddInput(sphere->GetOutput());
+      sphere->Delete();
+    }
+
+  append->Update();
+  this->GetOutput()->ShallowCopy(append->GetOutput());
+  append->Delete();
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxCrossHairSource.h b/bioimagesuite30_src/Common/vtkpxCrossHairSource.h
new file mode 100644
index 0000000..fab96d4
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxCrossHairSource.h
@@ -0,0 +1,123 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCrossHairSource.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxCrossHairSource - creates a cross-hair source for clipping 
+// .SECTION Description
+
+
+
+#ifndef __vtkpxCrossHairSource_h
+#define __vtkpxCrossHairSource_h
+
+class vtkPoints;
+class vtkPolyData;
+#include "vtkPolyDataSource.h"
+#include "pxutil.h"
+
+class vtkpxCrossHairSource : public vtkPolyDataSource 
+{
+public:
+  static vtkpxCrossHairSource *New();
+  vtkTypeMacro(vtkpxCrossHairSource,vtkPolyDataSource);
+
+public:
+
+  // Description:
+  // Location and Normal
+  vtkGetVectorMacro(Position,double,3);
+  vtkSetVectorMacro(Position,double,3);
+
+  // Description:
+  // Thickness i.e. distance between lines
+  vtkGetMacro(Thickness,double);
+  vtkSetMacro(Thickness,double);
+
+  // Description:
+  // Length i.e. length of lines 
+  vtkGetMacro(Length,double);
+  vtkSetMacro(Length,double);
+
+  // Description:
+  // Show Sphere
+  vtkSetClampMacro(ShowSphere,int,0,1);
+  vtkGetMacro(ShowSphere,int);
+  vtkBooleanMacro(ShowSphere,int);
+
+ 
+
+protected:
+  vtkpxCrossHairSource();
+  virtual ~vtkpxCrossHairSource();
+
+  vtkpxCrossHairSource(const vtkpxCrossHairSource&) {};
+  void operator=(const vtkpxCrossHairSource&) {};
+
+  // Description:
+  // Enclose attributs in BTX..ETX block to hide them from the TCL parser
+  //BTX
+  double Position[3];
+  double Thickness;
+  double Length;
+  int   ShowSphere;
+  //ETX
+
+  // Description:
+  // Generate Output Surface
+  virtual void Execute();  
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxDataArrayUndoStack.cpp b/bioimagesuite30_src/Common/vtkpxDataArrayUndoStack.cpp
new file mode 100644
index 0000000..19322af
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxDataArrayUndoStack.cpp
@@ -0,0 +1,80 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkpxDataArrayUndoStack.h"
+
+vtkpxDataArrayUndoStack* vtkpxDataArrayUndoStack::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxDataArrayUndoStack");
+  if(ret)
+      {
+	return (vtkpxDataArrayUndoStack*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxDataArrayUndoStack;
+}
+
+// Construct object with no children.
+// ---------------------------------------------------------------------------------------------
+vtkpxDataArrayUndoStack::vtkpxDataArrayUndoStack()
+{
+  this->NumberOfComponents=1;
+  this->DataType=VTK_FLOAT;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxDataArrayUndoStack::Initialize(int numelements,int numcomponents,int datatype)
+{
+  if (numcomponents<1)
+    numcomponents=1;
+  else if (numcomponents>100)
+    numcomponents=100;
+
+  this->NumberOfComponents=numcomponents;
+  this->DataType=datatype;
+  vtkpxGenericUndoStack::Initialize(numelements);
+}
+
+vtkObject* vtkpxDataArrayUndoStack::CreateNewElement()
+{
+  vtkDataArray* arr=vtkDataArray::CreateDataArray(this->DataType);
+  arr->SetNumberOfComponents(this->NumberOfComponents);
+  arr->Allocate(1000,100);
+  return arr;
+}
+// ---------------------------------------------------------------------------------------------
+void vtkpxDataArrayUndoStack::InitializeElement(int index)
+{
+  vtkDataArray* arr=(vtkDataArray*)this->Elements[index];
+  arr->SetNumberOfTuples(0);
+}
+
+// ---------------------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Common/vtkpxDataArrayUndoStack.h b/bioimagesuite30_src/Common/vtkpxDataArrayUndoStack.h
new file mode 100644
index 0000000..63a30aa
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxDataArrayUndoStack.h
@@ -0,0 +1,75 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkpxDataArrayStack_h
+#define __vtkpxDataArrayStack_h
+
+#include "vtkpxGenericUndoStack.h"
+#include "vtkDataArray.h"
+
+
+class vtkpxDataArrayUndoStack : public vtkpxGenericUndoStack {
+  
+public:
+  static vtkpxDataArrayUndoStack *New();
+  vtkTypeMacro(vtkpxDataArrayUndoStack,vtkpxGenericUndoStack);
+
+  // Description:
+  // Initialize
+  virtual void Initialize(int numelements,int numcomponents,int datatype);
+
+  // Description:
+  // Insert Stuff
+  virtual vtkDataArray* GetNextArray()     { return (vtkDataArray*)(this->GetNextObject());}
+  virtual vtkDataArray* GetCurrentArray()  { return (vtkDataArray*)(this->GetCurrentObject());}
+  virtual vtkDataArray* GetNextUndoArray() { return (vtkDataArray*)(this->GetNextUndoObject());}
+  virtual vtkDataArray* GetNextRedoArray() { return (vtkDataArray*)(this->GetNextRedoObject());}
+
+  // Description:
+  // Information
+  vtkGetMacro(NumberOfComponents,int);
+  vtkGetMacro(DataType,int);
+  
+protected:
+  vtkpxDataArrayUndoStack();
+
+  // Description:
+  // Stuff Needed
+  virtual vtkObject* CreateNewElement();
+  virtual void InitializeElement(int index);
+
+  int NumberOfComponents;
+  int DataType;
+
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkpxEpilepsyCSIReader.cpp b/bioimagesuite30_src/Common/vtkpxEpilepsyCSIReader.cpp
new file mode 100644
index 0000000..d31ac02
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxEpilepsyCSIReader.cpp
@@ -0,0 +1,236 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxEpilepsyCSIReader.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/08/09 20:40:19 $
+  Version:   $Revision: 1.3 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxEpilepsyCSIReader.h"
+#include "vtkFloatArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "pxutil.h"
+//------------------------------------------------------------------------------
+vtkpxEpilepsyCSIReader* vtkpxEpilepsyCSIReader::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxEpilepsyCSIReader");
+  if(ret)
+    {
+      return (vtkpxEpilepsyCSIReader*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxEpilepsyCSIReader;
+}
+
+// Construct object with NULL file prefix; file pattern "%s.%d"; image range 
+// set to (1,1); data origin (0,0,0); data spacing (1,1,1); no data mask;
+// header size 0; and byte swapping turned off.
+
+vtkpxEpilepsyCSIReader::vtkpxEpilepsyCSIReader()
+{
+  this->Status=0;
+  this->FlipZOffset=1;
+  this->ScaleFactors=vtkFloatArray::New();
+  this->CategoryNames=new char[300];
+}
+
+
+vtkpxEpilepsyCSIReader::~vtkpxEpilepsyCSIReader()
+{
+  this->ScaleFactors->Delete();
+  delete [] this->CategoryNames;
+}
+//------------------------------------------------------------------------------
+int vtkpxEpilepsyCSIReader::Load(const char* ana)
+{
+  this->SetFileName(ana);
+  this->Update();
+  return this->Status;
+}
+//------------------------------------------------------------------------------
+void vtkpxEpilepsyCSIReader::Execute()
+{
+  this->Status=0;
+
+  if (this->FileName == NULL) 
+    {
+      vtkErrorMacro(<< "FileName is NULL");
+      return;
+    }
+
+
+
+  FILE* fin=fopen(this->FileName,"r");
+  if (!fin)
+    {
+      vtkErrorMacro(<< "Bad FileName " << this->FileName);
+      return;
+    } 
+  
+  char* line=new char[200];
+
+  // Read Header Line
+  fgets(line,200,fin);
+  if (gzfindstringinstring(line, "#AECOM MRS CSI Data File")==0)
+    {
+      vtkErrorMacro(<< "Bad File Header " << line);
+      delete [] line;
+      fclose(fin);
+      return;
+    } 
+
+  // Read Next Line
+  // Read Dimensions
+  fgets(line,200,fin);  fgets(line,200,fin); // fprintf(stderr,"line=%s\n",line);
+  int width=24,height=24,ncomponents=1;
+  sscanf(line,"%d %d %d\n",&width,&height,&ncomponents);
+  // fprintf(stderr,"line=%s\n %d %d %d\n",line,width,height,ncomponents);
+
+  // Read Spacing  
+  fgets(line,200,fin);  fgets(line,200,fin);  // fprintf(stderr,"line=%s\n",line);
+  double spa[3] = { 8.0,8.0,10.0 };
+  sscanf(line,"%lf %lf %lf\n",&spa[0],&spa[1],&spa[2]);
+
+  fgets(line,200,fin);  fgets(line,200,fin);  // fprintf(stderr,"line=%s\n",line);
+  double ori[3] = { 0.0,0.0,0};
+  sscanf(line,"%lf \n",&ori[2]);
+  if (this->FlipZOffset)
+    ori[2]=-1.0*ori[2];
+
+
+  // Read Flip Modes 
+  fgets(line,200,fin);  fgets(line,200,fin);
+  int  flip[3] = { 0,0,0 };
+  sscanf(line,"%d %d %d \n",&flip[0],&flip[1],&flip[2]);
+  fprintf(stderr,"Flips = %d %d %d\n",flip[0],flip[1],flip[2]);
+  
+  
+  // Read Actual Number of Voxels
+  fgets(line,200,fin);  fgets(line,200,fin);
+  int nvoxels=1;
+  sscanf(line,"%d\n",&nvoxels); 
+  fprintf(stderr,"Number Of Voxels = %d\n",nvoxels);
+  fgets(line,200,fin);
+  fprintf(stderr,"line=%s\n",line);
+
+  this->ScaleFactors->SetNumberOfComponents(1);
+  this->ScaleFactors->SetNumberOfTuples(ncomponents);
+  for (int i=0;i<ncomponents;i++)
+    {
+      float sc;  fscanf(fin,"%f ",&sc);
+      this->ScaleFactors->SetComponent(i,0,sc);
+    }
+  fgets(line,200,fin);
+  strcpy(this->CategoryNames,line);
+
+  // Allocate Image and Put Data in place
+  vtkImageData* tmp=vtkImageData::New();
+  tmp->SetNumberOfScalarComponents(ncomponents+1);
+  tmp->SetDimensions(width,height,1); 
+  int dimensions[3]; tmp->GetDimensions(dimensions);
+  tmp->SetWholeExtent(0,dimensions[0]-1,0,dimensions[1]-1,0,dimensions[2]-1);
+  tmp->SetExtent(0,dimensions[0]-1,0,dimensions[1]-1,0,dimensions[2]-1);
+  tmp->SetUpdateExtent(0,dimensions[0]-1,0,dimensions[1]-1,0,dimensions[2]-1);
+  tmp->SetOrigin(ori);
+  tmp->SetSpacing(spa);
+  tmp->SetScalarTypeToFloat();
+  tmp->AllocateScalars();
+  
+  for (int c=0;c<=ncomponents;c++)
+    tmp->GetPointData()->GetScalars()->FillComponent(c,0);
+
+  //  fprintf(stderr,"Height=%d Width=%d\n",height,width);
+
+  for (int voxel=0;voxel<nvoxels;voxel++)
+    {
+      int row,column; fscanf(fin,"%d %d ",&row,&column);
+      //  fprintf(stderr,"voxel=%d row=%d column=%d ",voxel,row,column);
+      row=row-1;
+      column=column-1;
+      //      fprintf(stderr," ---> row=%d column=%d ",row,column);
+
+      if (flip[0]==1)
+	column=(width-1)-column;
+
+      if (flip[1]==1)
+	row=(height-1)-row;
+      
+      if (flip[2]==1)
+	{
+	  int t=row;
+	  row=column;
+	  column=t;
+	}
+
+      //      fprintf(stderr,"--->  row=%d column=%d\n",row,column);
+
+      tmp->SetScalarComponentFromDouble(column,row,0,0,1000.0);
+
+      for (int i=0;i<ncomponents;i++)
+	{
+	  float v;  fscanf(fin,"%f ",&v);
+	  tmp->SetScalarComponentFromDouble(column,row,0,i+1,v*this->ScaleFactors->GetComponent(i,0));
+	}
+    }
+
+
+
+  vtkImageData* output=this->GetOutput();
+  output->ShallowCopy(tmp);
+  tmp->Delete();
+
+  fclose(fin);
+  delete [] line;
+  this->Status=1;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxEpilepsyCSIReader.h b/bioimagesuite30_src/Common/vtkpxEpilepsyCSIReader.h
new file mode 100644
index 0000000..f138971
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxEpilepsyCSIReader.h
@@ -0,0 +1,116 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxEpilepsyCSIReader.h,v $
+  Language:  C++
+  Date:      $Date: 2002/08/09 20:40:16 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxEpilepsyCSIReader - reads analyze (or binary) 3d images 
+// .SECTION Description
+// This class reads analyze (.hdr,.img) 3D/4D images from files
+// By manually setting the header information, it can also read binary images stored in a single file
+// The output of this class is vtkStructuredPoints (either uchar,short,float)
+// It can handle byteswapping automatically in the case of analyze image input
+// and can read gzipped compressed files directly (automatically adds .gz suffix if needed)
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// This uses the pxutil library -- for analyze header 
+//
+// .SECTION See Also
+//  vtkpxAnalyzeImageWriter vtkVolume16Reader
+
+
+#ifndef __vtkpxEpilepsyCSIReader
+#define __vtkpxEpilepsyCSIReader
+
+#include "vtkStructuredPoints.h"
+#include "vtkStructuredPointsReader.h"
+#include "vtkFloatArray.h"
+
+
+class vtkpxEpilepsyCSIReader : public vtkStructuredPointsReader
+{
+public:
+  vtkTypeMacro(vtkpxEpilepsyCSIReader,vtkStructuredPointsReader);
+  static vtkpxEpilepsyCSIReader* New();
+
+  // Description:
+  // Convenience Routine  use Load("fname.dat")
+  virtual int  Load(const char* fname);
+
+  // Description:
+  vtkGetMacro(FlipZOffset,int);
+  vtkSetClampMacro(FlipZOffset,int,0,1);
+  vtkBooleanMacro(FlipZOffset,int);
+
+  // Description:
+  // Extra Information
+  vtkGetObjectMacro(ScaleFactors,vtkFloatArray);
+  vtkGetStringMacro(CategoryNames);
+
+protected:
+  //BTX
+  vtkpxEpilepsyCSIReader();
+  virtual ~vtkpxEpilepsyCSIReader();
+
+  virtual void Execute();
+  
+  int Status;
+  int FlipZOffset;  
+  char* CategoryNames;
+  vtkFloatArray* ScaleFactors;
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxGenericUndoStack.cpp b/bioimagesuite30_src/Common/vtkpxGenericUndoStack.cpp
new file mode 100644
index 0000000..1674999
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxGenericUndoStack.cpp
@@ -0,0 +1,246 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkpxGenericUndoStack.h"
+// ---------------------------------------------------------------------------------------------
+vtkpxGenericUndoStack::vtkpxGenericUndoStack()
+{
+  this->CurrentIndex=-1;
+  this->CurrentUndoIndex=-1;
+  this->CurrentRedoIndex=-1;
+  this->MaxIndex=-1;
+  this->NumberOfElements=0;
+
+  this->CurrentlyUndoing=0;
+  this->CurrentlyRedoing=0;
+
+
+  for (int i=0;i<pxGenericArrayMAXSIZE;i++)
+    Elements[i]=NULL;
+}
+/* -------------------------------------------------------------------------*/
+vtkpxGenericUndoStack::~vtkpxGenericUndoStack()
+{
+  for (int i=0;i<pxGenericArrayMAXSIZE;i++)
+    if (Elements[i]!=NULL)
+      Elements[i]->Delete();
+
+}
+// ---------------------------------------------------------------------------------------------
+void vtkpxGenericUndoStack::Initialize(int numelements)
+{
+  if (numelements<10)
+    numelements=10;
+  else if (numelements>pxGenericArrayMAXSIZE)
+    numelements=pxGenericArrayMAXSIZE;
+
+  for (int i=0;i<pxGenericArrayMAXSIZE;i++)
+    if (Elements[i]!=NULL)
+      {
+	Elements[i]->Delete();
+	Elements[i]=NULL;
+      }
+
+  this->NumberOfElements=numelements;
+
+  for (int i=0;i<this->NumberOfElements;i++)
+    {
+      this->Elements[i]=this->CreateNewElement();
+      this->InitializeElement(i);
+    }
+
+  this->CurrentIndex=-1;
+  this->MaxIndex=-1;
+
+  this->CurrentUndoIndex=-1;
+  this->CurrentRedoIndex=-1;
+  this->CurrentlyUndoing=0;
+  this->CurrentlyRedoing=0;
+
+}
+// ---------------------------------------------------------------------------------------------
+void vtkpxGenericUndoStack::Reset()
+{
+  this->CurrentIndex=-1;
+  this->CurrentUndoIndex=-1;
+  this->CurrentRedoIndex=-1;
+  this->MaxIndex=-1;
+  this->CurrentlyUndoing=0;
+  this->CurrentlyRedoing=0;
+
+
+  for (int i=0;i<this->NumberOfElements;i++)
+    this->Initialize(i);
+}
+
+// ---------------------------------------------------------------------------------------------
+vtkObject* vtkpxGenericUndoStack::GetCurrentObject()
+{
+  if (this->CurrentIndex<0)
+    return this->GetNextObject();
+
+  //fprintf(stderr,"\t\t\t Current Object = %d\n",CurrentIndex);
+  this->CurrentUndoIndex=-1;
+  this->CurrentRedoIndex=-1;
+  this->CurrentlyUndoing=0;
+  this->CurrentlyRedoing=0;
+
+
+  return this->Elements[CurrentIndex];
+}
+
+vtkObject* vtkpxGenericUndoStack::GetNextObject()
+{
+  if (this->CurrentIndex<-1)
+    this->CurrentIndex=-1;
+  else if (this->CurrentIndex==this->NumberOfElements-1)
+    this->ShuffleElements();
+
+  this->CurrentIndex+=1;
+  this->CurrentUndoIndex=-1;
+  this->CurrentRedoIndex=-1;
+  this->CurrentlyUndoing=0;
+  this->CurrentlyRedoing=0;
+  
+  this->MaxIndex=this->CurrentIndex;
+
+  //fprintf(stderr,"\n ************************ Next Object = %d (emptying)\n",CurrentIndex);
+
+  this->InitializeElement(this->CurrentIndex);
+  return this->Elements[this->CurrentIndex];
+}
+
+
+vtkObject* vtkpxGenericUndoStack::GetNextUndoObject()
+{
+  if (this->CurrentlyUndoing==0)
+    {
+      this->CurrentlyRedoing=0;
+      if (this->CurrentIndex>=0)
+	{
+	  this->CurrentUndoIndex=this->CurrentIndex;
+	  //fprintf(stderr,"Returning Undo Object %d\n",this->CurrentUndoIndex);
+	  this->CurrentlyUndoing=1;
+	  return Elements[this->CurrentUndoIndex];
+	}
+      this->CurrentlyUndoing=0;
+      //fprintf(stderr,"Returning NULL Undo Object\n");
+      return NULL;
+    }
+
+  // From Here on Currently Undoing = 1
+  this->CurrentlyRedoing=0;
+  if (this->CurrentUndoIndex>0)
+    {
+      this->CurrentUndoIndex-=1;
+      this->CurrentIndex=this->CurrentUndoIndex;
+      //fprintf(stderr,"Returning Undo Object %d\n",this->CurrentUndoIndex);
+      return Elements[this->CurrentUndoIndex];
+    }
+  
+  //fprintf(stderr,"Returning NULL Undo Object\n");
+  return NULL;
+}
+
+vtkObject* vtkpxGenericUndoStack::GetNextRedoObject()
+{
+  if (this->CurrentlyRedoing==0)
+    {
+      if (this->CurrentlyUndoing==0)
+	{
+	  //fprintf(stderr,"Returning NULL Redo Object Not Undoing\n");
+	  return NULL;
+	}
+      
+      this->CurrentlyUndoing=0;
+      if (this->CurrentIndex>=0)
+	{
+	  this->CurrentRedoIndex=this->CurrentIndex;
+	  //fprintf(stderr,"Returning Redo Object %d\n",this->CurrentUndoIndex);
+	  this->CurrentlyRedoing=1;
+	  return Elements[this->CurrentRedoIndex];
+	}
+      this->CurrentlyRedoing=0;
+      //    //fprintf(stderr,"Returning NULL Redo Object\n");
+      return NULL;
+    }
+
+
+  // From Here on Currently Redoing = 1
+  this->CurrentlyUndoing=0;
+  this->CurrentRedoIndex+=1;
+  if (this->CurrentRedoIndex<= this->MaxIndex)
+    {
+	this->CurrentIndex=this->CurrentRedoIndex;
+	//fprintf(stderr,"Returning Redo Object %d\n",this->CurrentUndoIndex);
+	return Elements[this->CurrentRedoIndex];
+    }
+  
+  //fprintf(stderr,"Returning NULL Redo Object\n");
+  return NULL;
+}
+// ---------------------------------------------------------------------------------------------
+
+void vtkpxGenericUndoStack::ShuffleElements()
+{
+  if (this->CurrentIndex!=this->NumberOfElements-1)
+    return;
+
+  int shift=1;
+  //fprintf(stderr,"Shuffling Elements %d\n",shift);
+
+  for (int ia=shift;ia<this->NumberOfElements;ia++)
+    {
+      vtkObject* tmp=this->Elements[ia-shift];
+      this->Elements[ia-shift]=this->Elements[ia];
+      this->Elements[ia]=tmp;
+    }
+  
+  this->CurrentIndex-=shift;
+  if (this->CurrentUndoIndex>=shift)
+    this->CurrentUndoIndex-=shift;
+  else
+    this->CurrentUndoIndex=-1;
+
+  this->CurrentUndoIndex=-1;
+  
+  if (this->CurrentRedoIndex>=0)
+    this->CurrentRedoIndex-=shift;
+  else
+    this->CurrentRedoIndex=-1;
+
+  this->MaxIndex-=shift;
+  this->CurrentlyUndoing=0;
+  this->CurrentlyRedoing=0;
+
+}
+
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxGenericUndoStack.h b/bioimagesuite30_src/Common/vtkpxGenericUndoStack.h
new file mode 100644
index 0000000..f6a2086
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxGenericUndoStack.h
@@ -0,0 +1,99 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkpxGenericStack_h
+#define __vtkpxGenericStack_h
+
+#include "vtkObject.h"
+
+const int pxGenericArrayMAXSIZE = 100;
+
+class vtkpxGenericUndoStack : public vtkObject {
+  
+public:
+  vtkTypeMacro(vtkpxGenericUndoStack,vtkObject);
+
+  // Description:
+  // Initialize
+  virtual void Initialize(int numelements);
+  virtual void Reset();
+
+  // Description:
+  // Insert Stuff
+  virtual vtkObject* GetNextObject();
+  virtual vtkObject* GetCurrentObject();
+
+  virtual vtkObject* GetNextUndoObject();
+  virtual vtkObject* GetNextRedoObject();
+
+  // Description:
+  // Information
+  vtkGetMacro(NumberOfElements,int);
+
+  
+  // Description:
+  // Diagnostic Stuff
+  vtkGetMacro(CurrentIndex,int);
+  vtkGetMacro(CurrentUndoIndex,int);
+  vtkGetMacro(CurrentRedoIndex,int);
+  vtkGetMacro(MaxIndex,int);
+  vtkGetMacro(CurrentlyUndoing,int);
+  vtkGetMacro(CurrentlyRedoing,int);
+
+protected:
+  vtkpxGenericUndoStack();
+  virtual ~vtkpxGenericUndoStack();
+
+
+
+  // Description:
+  // Data Members
+  int               CurrentIndex;
+  int               CurrentUndoIndex;
+  int               CurrentRedoIndex;
+  int               CurrentlyUndoing;
+  int               CurrentlyRedoing;
+  int               NumberOfElements;
+  int               MaxIndex;
+  vtkObject*        Elements[pxGenericArrayMAXSIZE];
+
+  // Description:
+  // Do Shuffle
+  virtual void ShuffleElements();
+
+  // Description:
+  // Protected Stuff
+  virtual vtkObject* CreateNewElement() = 0;
+  virtual void InitializeElement(int index) = 0;
+  
+};
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkpxImageComponentsToFrames.cpp b/bioimagesuite30_src/Common/vtkpxImageComponentsToFrames.cpp
new file mode 100644
index 0000000..d34f286
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxImageComponentsToFrames.cpp
@@ -0,0 +1,192 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageComponentsToFrames.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/28 16:17:31 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxImageComponentsToFrames.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "math.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+//------------------------------------------------------------------------------
+vtkpxImageComponentsToFrames* vtkpxImageComponentsToFrames::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageComponentsToFrames");
+  if(ret)
+    {
+    return (vtkpxImageComponentsToFrames*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageComponentsToFrames;
+}
+
+// Construct object with no children.
+vtkpxImageComponentsToFrames::vtkpxImageComponentsToFrames()
+{
+  this->Inverse=0;
+  this->SlicesPerFrame=16;
+}
+// ----------------------------------------------------------------------------
+vtkpxImageComponentsToFrames::~vtkpxImageComponentsToFrames()
+{
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageComponentsToFrames::ExecuteInformation()
+{
+  vtkImageData* input=vtkImageData::SafeDownCast(this->GetImageDataInput(0));
+
+  if (input==NULL)
+    {
+	vtkErrorMacro(<<"No Input Specified!!");
+	return;
+      }
+  vtkImageData *output=this->GetOutput();
+  vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+
+  if (this->Inverse==1)
+    {
+      int numfr=dim[2]/this->SlicesPerFrame;
+      if (numfr<1)
+	numfr=1;
+      output->SetNumberOfScalarComponents(numfr);
+      output->SetDimensions(dim[0],dim[1],this->SlicesPerFrame);
+      output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,this->SlicesPerFrame-1);
+      output->SetExtent(0,dim[0]-1,0,dim[1]-1,0,this->SlicesPerFrame-1);
+      output->SetUpdateExtent(0,dim[0]-1,0,dim[1]-1,0,this->SlicesPerFrame-1);
+    }
+  else
+    {
+      output->SetNumberOfScalarComponents(1);
+      output->SetDimensions(dim[0],dim[1],dim[2]*nc);
+      output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]*nc-1);
+      output->SetExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]*nc-1);
+      output->SetUpdateExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]*nc-1);
+    }
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageComponentsToFrames::SimpleExecute(vtkImageData* input, vtkImageData* output) 
+{
+  vtkpxImageComponentsToFrames::ExecuteInformation();
+
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+  int dim[3];  input->GetDimensions(dim);
+
+  if (this->Inverse==0)
+    {
+      int nc=input->GetNumberOfScalarComponents();
+      /*      output->CopyStructure(input);
+      output->SetNumberOfScalarComponents(1);
+      output->SetDimensions(dim[0],dim[1],dim[2]*nc);
+      output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]*nc-1);
+      output->AllocateScalars();*/
+
+
+      vtkDataArray* out=output->GetPointData()->GetScalars();
+
+      for (int comp=0;comp<nc;comp++)
+	{
+	  int offset=comp*dim[0]*dim[1]*dim[2];
+	  int index=0;
+	  for (int k=0;k<dim[2];k++)
+	    for (int j=0;j<dim[1];j++)
+	      for (int i=0;i<dim[0];i++)
+		{
+		  out->SetComponent(offset+index,0,in->GetComponent(index,comp));
+		  ++index;
+		}
+	}
+    }
+  else
+    {
+      int numfr=dim[2]/this->SlicesPerFrame;
+      if (numfr<1)
+	numfr=1;
+      /*      output->CopyStructure(input);
+      output->SetNumberOfScalarComponents(numfr);
+      output->SetDimensions(dim[0],dim[1],this->SlicesPerFrame);
+      output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,this->SlicesPerFrame-1);
+      output->AllocateScalars();*/
+
+      int d[3]; output->GetDimensions(d); fprintf(stderr,"input (%d,%d,%d) %d --> (%d,%d,%d) %d\n",
+						  dim[0],dim[1],dim[2],1,d[0],d[1],d[2],numfr);
+
+      vtkDataArray* out=output->GetPointData()->GetScalars();
+      
+      dim[2]=this->SlicesPerFrame;
+
+      for (int comp=0;comp<numfr;comp++)
+	{
+	  int offset=comp*dim[0]*dim[1]*dim[2];
+	  int index=0;
+	  for (int k=0;k<dim[2];k++)
+	    for (int j=0;j<dim[1];j++)
+	      for (int i=0;i<dim[0];i++)
+		{
+		  out->SetComponent(index,comp,in->GetComponent(index+offset,0));
+		  ++index;
+		}
+	}
+    }
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Common/vtkpxImageComponentsToFrames.h b/bioimagesuite30_src/Common/vtkpxImageComponentsToFrames.h
new file mode 100644
index 0000000..dc64053
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxImageComponentsToFrames.h
@@ -0,0 +1,110 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageComponentsToFrames.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageComponentsToFrames -- compute Field Map from succesive phase images 
+// .SECTION Description
+// This class takes a number of MR phaseimages and a description of the TE times
+// and generates field maps.
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+
+#ifndef __vtkpxImageComponentsToFrames_h
+#define __vtkpxImageComponentsToFrames_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+
+class vtkPolyData;
+class vtkAbstractTransform;
+class vtkTransform;
+
+class vtkpxImageComponentsToFrames : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageComponentsToFrames *New();
+  vtkTypeMacro(vtkpxImageComponentsToFrames,vtkpxSimpleImageToImageFilter);
+
+
+  // Description:
+  // if Inverse = 1 then we go from Frames To Components
+  vtkSetClampMacro(Inverse, int,0,1);
+  vtkGetMacro(Inverse, int);
+  vtkBooleanMacro(Inverse, int);
+
+  // Description:
+  // SlicesPerFrame -- needed to when inverse=1
+  vtkSetMacro(SlicesPerFrame, int);
+  vtkGetMacro(SlicesPerFrame, int);
+
+
+protected:
+
+  vtkpxImageComponentsToFrames();
+  virtual ~vtkpxImageComponentsToFrames();
+  vtkpxImageComponentsToFrames(const vtkpxImageComponentsToFrames&) {};
+  void operator=(const vtkpxImageComponentsToFrames&) {};
+
+  int Inverse;
+  int SlicesPerFrame;
+
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+  void ExecuteInformation();
+
+
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkpxImageExtract.cpp b/bioimagesuite30_src/Common/vtkpxImageExtract.cpp
new file mode 100644
index 0000000..b39287c
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxImageExtract.cpp
@@ -0,0 +1,781 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxImageExtract.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkbisImageReslice.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include <stdio.h>
+#include "pxutil.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+
+
+vtkpxImageExtract* vtkpxImageExtract::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageExtract");
+  if(ret)
+    {
+      return (vtkpxImageExtract*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageExtract;
+}
+
+
+// Construct object to extract all of the input data.
+vtkpxImageExtract::vtkpxImageExtract()
+{
+  this->InternalCurrentPlane=2; 
+  this->SliceNo=0;
+  this->Frame=0;
+  this->PolarMode=0;
+  this->PolarMiddle=-1.0;
+  this->LimitTextureSize=0;
+  this->MaximumTextureSize=256;
+  this->SampleRate[0]=1;
+  this->SampleRate[1]=1;
+  this->ForcePowerOfTwo=0;
+}
+
+// ---------------------------------------------------------------------------
+
+void vtkpxImageExtract::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkSimpleImageToImageFilter::PrintSelf(os,indent);
+
+  os << indent << "  InternalCurrentPlane " << this->InternalCurrentPlane << "\n";
+  os << indent << "  SliceNo " << this->SliceNo << "\n";
+  os << indent << "  Frame " << this->Frame << "\n";
+  os << indent << "  PolarMode " << this->PolarMode << "\n";
+  os << indent << "  PolarMiddle " << this->PolarMiddle << "\n";
+  os << indent << "  LimitTextureSize " << this->LimitTextureSize << "\n";
+  os << indent << "  ForcePowerOfTwo " << this->ForcePowerOfTwo << "\n";
+  os << indent << "  MaximumTextureSize " << this->MaximumTextureSize << "\n";
+  os << indent << "  SampleRate " << this->SampleRate[0] << " " << this->SampleRate[1] << "\n";
+}
+// ---------------------------------------------------------------------------
+
+void vtkpxImageExtract::SetCurrentPlane(int a)
+{
+  this->SetInternalCurrentPlane(a);
+}
+
+int  vtkpxImageExtract::GetCurrentPlane()
+{
+  return this->InternalCurrentPlane;
+}
+
+// ---------------------------------------------------------------------------
+int vtkpxImageExtract::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+					  vtkInformationVector *outputVector)
+{
+  if (this->PolarMode==1)
+    return this->RequestInformationPolar(request,inputVector,outputVector);
+
+  vtkInformation *inInfo =  inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  int wholeExtent[6]; inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
+  double sp[3];  inInfo->Get(vtkDataObject::SPACING(), sp);
+  double origin[3];  inInfo->Get(vtkDataObject::ORIGIN(),  origin);
+
+  vtkImageData* input=this->GetImageDataInput(0);
+  if (input!=NULL)
+    {
+      input->GetExtent(wholeExtent);
+      input->GetSpacing(sp);
+      input->GetOrigin(origin);
+    }
+  int nc=input->GetNumberOfScalarComponents();
+
+
+  /*  if (this->InternalCurrentPlane==1)
+    fprintf(stderr,"\n\nInput Whole Extent=%d:%d,%d:%d,%d:%d, spacing=%f,%f,%f\n",
+	    wholeExtent[0],wholeExtent[1],
+	    wholeExtent[2],wholeExtent[3],
+	    wholeExtent[4],wholeExtent[5],sp[0],sp[1],sp[2]);*/
+  
+  int dim[3];   dim[0]=wholeExtent[1]+1;  dim[1]=wholeExtent[3]+1;  dim[2]=wholeExtent[5]+1;
+
+  // Output is always 2D
+  wholeExtent[5]=0;
+  double osp[3];
+
+  switch (this->InternalCurrentPlane)
+    {
+    case 2:
+      wholeExtent[1] = dim[0]-1;
+      wholeExtent[3] = dim[1]-1;
+      osp[0]=sp[0];osp[1]=sp[1];osp[2]=sp[2];
+      break;
+    case 1:
+      wholeExtent[1] = dim[0]-1;
+      wholeExtent[3] = dim[2]-1;
+      osp[0]=sp[0];osp[1]=sp[2];osp[2]=sp[1];
+      break;
+    case 0:
+      wholeExtent[1] = dim[1]-1;
+      wholeExtent[3] = dim[2]-1;
+      osp[0]=sp[1];osp[1]=sp[2];osp[2]=sp[0];
+      break;
+    }
+
+
+  if (this->ForcePowerOfTwo) 
+    {
+      this->unpaddedoutdim[0]=wholeExtent[1]+1;
+      this->unpaddedoutdim[1]=wholeExtent[3]+1;
+      this->unpaddedoutdim[2]=wholeExtent[5]+1;
+      for (int i=1;i<=3;i+=2)
+	{
+	  int d=wholeExtent[i]+1;
+	  int sz=2;
+	  while (sz<d)
+	    sz*=2;
+	  wholeExtent[i]=sz-1;
+	}
+    }
+  else 
+    {
+      if (this->LimitTextureSize)
+	{
+	  
+	  for (int i=0;i<=1;i++)
+	    {
+	      int index=2*i+1;
+	      int dimension=wholeExtent[index]+1;
+	      this->SampleRate[i]=1;
+	      while ( dimension > this->MaximumTextureSize*this->SampleRate[i])
+		this->SampleRate[i]+=1;
+	      
+	      wholeExtent[index]=int(dimension/this->SampleRate[i])-1;
+	      osp[i]=osp[i]*float(this->SampleRate[i]);
+	    }
+	}
+      this->unpaddedoutdim[0]=wholeExtent[1]+1;
+      this->unpaddedoutdim[1]=wholeExtent[3]+1;
+      this->unpaddedoutdim[2]=wholeExtent[5]+1;
+    }
+
+  
+  if (this->SliceNo<0)
+    {
+      this->SliceNo=0;
+    }
+  else if (this->SliceNo>=dim[this->InternalCurrentPlane])
+    {
+      this->SliceNo=dim[this->InternalCurrentPlane]-1;
+    }
+
+
+  double outorigin[3];
+  switch (this->InternalCurrentPlane)
+    {
+    case 2:
+      outorigin[0]=origin[0];outorigin[1]=origin[1];outorigin[2]=double(this->SliceNo)*sp[2]+origin[2];
+      break;
+    case 1:
+      //      output->SetOrigin(origin[0],origin[2],double(this->SliceNo)*sp[1]+origin[1]);
+      outorigin[0]=origin[0];outorigin[1]=origin[2];outorigin[2]=double(this->SliceNo)*sp[1]+origin[1];
+      break;
+    case 0:
+      //      output->SetOrigin(origin[1],origin[2],double(this->SliceNo)*sp[0]+origin[0]);
+      outorigin[0]=origin[1];outorigin[1]=origin[2];outorigin[2]=double(this->SliceNo)*sp[0]+origin[0];
+      break;
+    }
+ 
+  outInfo->Set(vtkDataObject::ORIGIN(), outorigin, 3);
+  outInfo->Set(vtkDataObject::SPACING(), osp, 3);
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6);
+
+  if (this->ExtractAllFrames && this->PolarMode ==0 )
+    {
+      // Do Nothing
+    }
+  else
+    vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, 1);
+  return 1;
+}
+// ---------------------------------------------------------------------------
+template<class T>
+int vtkpxImageExtract_ExtractSlice(vtkpxImageExtract* self,vtkImageData* input,
+				   vtkImageData* output,
+				   int internalcurrentplane,int sliceno,int frame,
+				   int samplerate[2],int unpaddedoutdim[3],T *)
+{
+
+  int dim[3]; input->GetDimensions(dim);
+  int nframes=input->GetNumberOfScalarComponents();
+  int outdim[3]; output->GetDimensions(outdim);
+
+  vtkDataArray* inp_dat=input->GetPointData()->GetScalars();
+  T* inp=(T*)inp_dat->GetVoidPointer(0);
+
+  vtkDataArray* out_dat=output->GetPointData()->GetScalars();
+  T* out=(T*)out_dat->GetVoidPointer(0);
+
+
+  output->GetPointData()->GetScalars()->FillComponent(0,0.0);
+
+
+  switch(internalcurrentplane)
+    {
+    case 2:
+      {
+	int iincr=nframes*samplerate[0];
+	int offset=dim[0]*dim[1]*sliceno;
+	int in_j=0;
+	for (int j=0;j<unpaddedoutdim[1];++j)
+	  {
+	    int inindex = (dim[0]*in_j+offset)*nframes+frame;
+	    int outindex=j*outdim[0];
+	    for (int i=0;i<unpaddedoutdim[0];++i)
+	      {
+		out[outindex]=inp[inindex];
+		++outindex;
+		inindex+=iincr;
+	      }
+	    in_j+=samplerate[1];
+	  }
+      }
+      break;
+      
+    case 1:
+      {
+	int dim01=dim[0]*dim[1];
+	int offset=sliceno*dim[0];
+	int in_k=0;
+	int iincr=nframes*samplerate[0];
+	for (int k=0;k<unpaddedoutdim[1];++k)
+	  {
+	    int inindex=(in_k*dim01+offset)*nframes+frame;
+	    int outindex=k*outdim[0];
+	    for (int i=0;i<unpaddedoutdim[0];++i)
+	      {
+		out[outindex]=inp[inindex];
+		++outindex;
+		inindex+=iincr;
+	      }
+	    in_k+=samplerate[1];
+	  }
+      }
+      break;
+      
+    case 0:
+      {
+	int dim01=dim[0]*dim[1];
+	int offset=sliceno;
+	int in_k=0;
+	int jincr=nframes*samplerate[0]*dim[0];
+	for (int k=0;k<unpaddedoutdim[1];++k)
+	  {
+	    int outindex=k*outdim[0];
+	    int inindex=(in_k*dim01+offset)*nframes+frame;
+	    for (int j=0;j<unpaddedoutdim[0];++j)
+	      {
+		out[outindex]=inp[inindex];
+		inindex+=jincr;
+		++outindex;
+	      }
+	    in_k+=samplerate[1];
+	  }
+      }
+      break;
+    }
+  return 0;
+}
+
+// ---------------------------------------------------------------------------
+template<class T>
+int vtkpxImageExtract_ExtractSliceAllFrames(vtkpxImageExtract* self,vtkImageData* input,
+					    vtkImageData* output,
+					    int internalcurrentplane,int sliceno,
+					    int samplerate[2],int unpaddedoutdim[3],T *)
+{
+  //  fprintf(stderr,"In Extract Slice All Frames plane=%d, %d x %d\n",internalcurrentplane, samplerate[0],samplerate[1]);
+
+
+
+  int dim[3]; input->GetDimensions(dim);
+  int nframes=input->GetNumberOfScalarComponents();
+  int outdim[3]; output->GetDimensions(outdim);
+  int outframes=output->GetNumberOfScalarComponents();
+
+  //  fprintf(stderr,"In Extract Slice All Frames inframes=%d, outframes=%d , unpad = %d x %d\n",nframes,outframes, unpaddedoutdim[0],unpaddedoutdim[1]);
+  //  fprintf(stderr,"In Extract Slice All Frames dim=(%d,%d,%d), outdim=(%d,%d,%d)\n",dim[0],dim[1],dim[2],outdim[0],outdim[1],outdim[2]);
+
+  vtkDataArray* inp_dat=input->GetPointData()->GetScalars();
+  T* inp=(T*)inp_dat->GetVoidPointer(0);
+
+  vtkDataArray* out_dat=output->GetPointData()->GetScalars();
+  T* out=(T*)out_dat->GetVoidPointer(0);
+
+  for (int ia=0;ia<nframes;ia++)
+    output->GetPointData()->GetScalars()->FillComponent(ia,double(ia));
+
+  switch(internalcurrentplane)
+    {
+    case 2:
+      {
+	int in_j=0;
+	int offset=dim[0]*dim[1]*sliceno;
+
+	for (int j=0;j<unpaddedoutdim[1];j++)
+	  {
+	    int inindex =(in_j*dim[0]+offset)*nframes;
+	    int outindex= j*outdim[0]*nframes;
+	    for (int i=0;i<unpaddedoutdim[0];i++)
+	      {
+		for (int c=0;c<nframes;c++)
+		  {
+		    out[outindex]=inp[inindex];
+		    ++outindex;
+		    ++inindex;
+		  }
+		inindex+=((samplerate[0]-1)*nframes);
+	      }
+	    in_j+=samplerate[1];
+	  }
+      }
+      break;
+      
+    case 1:
+      {
+	int dim01=dim[0]*dim[1];
+	int offset=sliceno*dim[0];
+	int in_k=0;
+	int iincr=nframes*(samplerate[0]-1);
+	for (int k=0;k<unpaddedoutdim[1];++k)
+	  {
+	    int inindex=(in_k*dim01+offset)*nframes;
+	    int outindex=(k*outdim[0])*nframes;
+	    for (int i=0;i<unpaddedoutdim[0];++i)
+	      {
+		for (int c=0;c<nframes;c++)
+		  {
+		    out[outindex]=inp[inindex];
+		    ++outindex;
+		    ++inindex;
+		  }
+		inindex+=iincr;
+	      }
+	    in_k+=samplerate[1];
+	  }
+      }
+      break;
+      
+    case 0:
+      {
+	int dim01=dim[0]*dim[1];
+	int offset=sliceno;
+	int in_k=0;
+	int inincr=(dim[0]-1)*nframes*samplerate[0];
+	for (int k=0;k<unpaddedoutdim[1];++k)
+	  {
+	    int outindex=k*outdim[0]*nframes;
+	    int inindex=(in_k*dim01+offset)*nframes;
+	    for (int j=0;j<unpaddedoutdim[0];++j)
+	      {
+		for (int c=0;c<nframes;c++)
+		  {
+		    out[outindex]=inp[inindex];
+		    ++outindex;
+		    ++inindex;
+		  }
+		inindex+=inincr;
+	      }
+	    in_k+=samplerate[1];
+	  }
+      }
+      break;
+    case -1:
+      {
+	int dim01=dim[0]*dim[1];
+	int offset=sliceno;
+	int in_k=0;
+	int jincr=nframes*(samplerate[0])*dim[0];
+	for (int k=0;k<unpaddedoutdim[1];++k)
+	  {
+	    int outindex=k*outdim[0]*nframes;
+	    int inindex=(in_k*dim01+offset)*nframes;
+	    for (int j=0;j<unpaddedoutdim[0];++j)
+	      {
+		for (int c=0;c<nframes;c++)
+		  {
+		    out[outindex]=inp[inindex];
+		    ++outindex;
+		    ++inindex;
+		  }
+		inindex+=jincr;
+	      }
+	    in_k+=samplerate[1];
+	  }
+      }
+    }
+
+
+  //  fprintf(stderr,"Done with Extract All Frames\n");
+  return 0;
+}
+
+// ---------------------------------------------------------------------------
+void vtkpxImageExtract::SimpleExecute(vtkImageData* input, vtkImageData* output) 
+{
+  if (this->PolarMode)
+    {
+      this->SimpleExecutePolar(input,output);
+      return;
+    }
+
+  vtkDebugMacro(<< "Extracting Slice");
+
+  int dim[3];   input->GetDimensions(dim);
+  int outdim[3];  output->GetDimensions(outdim);
+
+  //  fprintf(stderr,"OutDim= %d %d %d\n",outdim[0],outdim[1],outdim[2]);
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();  
+
+  if (this->InternalCurrentPlane<0)
+      this->InternalCurrentPlane=0;
+  else if (this->InternalCurrentPlane>2)
+      this->InternalCurrentPlane=2;
+
+
+  if (this->SliceNo<0)
+      this->SliceNo=0;
+  else if (this->SliceNo>=dim[this->InternalCurrentPlane])
+    {
+      this->SliceNo=dim[this->InternalCurrentPlane]-1;
+    }
+
+  // Color Mode
+  if (this->ExtractAllFrames)
+    {
+      //      fprintf(stderr,"In Extract All Frames\n");
+      //      fprintf(stderr,"outdim = %d x %d x %d, nc=%d\n",outdim[0],outdim[1],outdim[2],output->GetNumberOfScalarComponents());
+      switch (input->GetScalarType())
+	{
+	  vtkTemplateMacro8(vtkpxImageExtract_ExtractSliceAllFrames, this, input,output,
+			    this->InternalCurrentPlane,
+			    this->SliceNo,
+			    this->SampleRate,
+			    this->unpaddedoutdim,
+			    static_cast<VTK_TT *>(0));
+	  
+	default:
+	  vtkGenericWarningMacro("Unknown input ScalarType in Write Data");
+	  return;
+	}
+
+
+    }
+  else
+    {
+      //      fprintf(stderr,"In Extract Single Frame\n");
+      if (this->Frame<0)
+	this->Frame=0;
+      if ( this->Frame>=input->GetNumberOfScalarComponents())
+	this->Frame=input->GetNumberOfScalarComponents()-1;
+      
+      switch (input->GetScalarType())
+	{
+	  vtkTemplateMacro9(vtkpxImageExtract_ExtractSlice, this, input,output,
+			    this->InternalCurrentPlane,
+			    this->SliceNo,
+			    this->Frame,
+			    this->SampleRate,
+			    this->unpaddedoutdim,
+			    static_cast<VTK_TT *>(0));
+	  
+	default:
+	  vtkGenericWarningMacro("Unknown input ScalarType in Write Data");
+	  return;
+	}
+    }
+
+  
+
+  /*  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+
+
+  switch(this->InternalCurrentPlane)
+    {
+    case 2:
+      {
+	int offset=dim[0]*dim[1]*this->SliceNo;
+	int in_j=0;
+	for (int j=0;j<outdim[1];++j)
+	  {
+	    int in_i=0;
+	    for (int i=0;i<outdim[0];++i)
+	      {
+		out->SetComponent(i+j*outdim[0],0,inp->GetComponent(in_i+dim[0]*in_j+offset,this->Frame));
+		in_i+=this->SampleRate[0];
+	      }
+	    in_j+=this->SampleRate[1];
+	  }
+      }
+      break;
+      
+    case 1:
+      {
+	int dim01=dim[0]*dim[1];
+	int offset=this->SliceNo*dim[0];
+	int in_k=0;
+	for (int k=0;k<outdim[1];++k)
+	  {
+	    int in_i=0;
+	    for (int i=0;i<outdim[0];++i)
+	      {
+		out->SetComponent(i+k*outdim[0],0,
+				  inp->GetComponent(in_k*dim01+offset+in_i,this->Frame));
+		in_i+=this->SampleRate[0];
+	      }
+	    in_k+=this->SampleRate[1];
+	  }
+      }
+      break;
+      
+    case 0:
+      {
+	int dim01=dim[0]*dim[1];
+	int offset=this->SliceNo;
+	int in_k=0;
+	for (int k=0;k<outdim[1];++k)
+	  {
+	    int in_j=0;
+	    for (int j=0;j<outdim[0];++j)
+	      {
+		out->SetComponent(j+k*outdim[0],0,
+				  inp->GetComponent(in_k*dim01+in_j*dim[0]+offset,this->Frame));
+		in_j+=this->SampleRate[0];
+	      }
+	    in_k+=this->SampleRate[1];
+	  }
+      }
+      break;
+      }*/
+      
+}
+
+// ---------------------------------------------------------------------------
+//             Polar Mode Stuff 
+//   Plane 2 is XY of the current angle 
+//   Plane 1 is XY of the current angle + 90 deg
+//   Plane 0 is XZ reconstructed 
+// ---------------------------------------------------------------------------
+int vtkpxImageExtract::RequestInformationPolar(vtkInformation *request,  vtkInformationVector **inputVector, 
+					       vtkInformationVector *outputVector)
+{
+
+  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  int wholeExtent[6]; inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
+  double spa[3];  inInfo->Get(vtkDataObject::SPACING(), spa);
+  double ori[3];  inInfo->Get(vtkDataObject::ORIGIN(),  ori);
+  int dim[3];   dim[0]=wholeExtent[1]+1;  dim[1]=wholeExtent[3]+1;  dim[2]=wholeExtent[5]+1;
+
+  // Uniform Output Spacing
+  double outspa[3]; for (int ia=0;ia<=2;ia++) outspa[ia]=spa[0];
+  //  output->SetSpacing(input->GetSpacing()[0],input->GetSpacing()[0],input->GetSpacing()[0]);
+
+  //output->SetOrigin(input->GetOrigin());
+  
+  wholeExtent[0]=0;    wholeExtent[2]=0;  wholeExtent[4]=0;    wholeExtent[5]=0;
+    
+  switch (this->InternalCurrentPlane)
+    {
+    case 2:
+    case 1:
+      wholeExtent[1] = dim[0]-1;
+      wholeExtent[3] = dim[1]-1;
+      break;
+    case 0:
+      wholeExtent[1] = dim[0]-1;
+      wholeExtent[3] = dim[0]-1;
+      break;
+    }
+  
+  
+  if (this->SliceNo<0)
+    {
+      this->SliceNo=0;
+    }
+  else if (this->SliceNo>=dim[this->InternalCurrentPlane])
+    {
+      this->SliceNo=dim[this->InternalCurrentPlane]-1;
+    }
+  
+  outInfo->Set(vtkDataObject::ORIGIN(), ori, 3);
+  outInfo->Set(vtkDataObject::SPACING(), outspa, 3);
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6);
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, 1);
+  return 1; 
+}
+
+
+float vtkpxImageExtract::Get3DEchoVoxel(vtkImageData* img,int dim[3],int x,int y,int z,int comp,
+					float angularspacing,float middlex)
+{
+  int flag=0;
+  /*  if ( (x==50 && y==50 ) || ( x==(dim[0]-50) && y==(dim[1]-50)))
+      flag=1;*/
+
+
+  if (middlex<0.0) middlex=(dim[0])/2.0;
+  float slice_y=Frange(z,0.0,(float)dim[1]-1);
+
+  float px=float(x)-middlex;
+  float py=float(y)-middlex;
+
+  float radius=sqrt(px*px+py*py);
+  float theta=atan2(py,px)*180.0/M_PI;
+
+
+  if (theta< (000.0-0.5*angularspacing)) theta+=180.0;
+  if (theta>=(180.0-0.5*angularspacing)) theta-=180.0;
+  float slice_z=fabs(theta)/angularspacing;
+  
+  int slice_no=int(slice_z+0.5);
+
+  if (py<0.0 && slice_no!=0)  radius=-radius;
+  if (slice_no==0 && px<0.0)  radius=-radius;
+  slice_no=Irange(slice_no,0,dim[2]-1);
+  float slice_x=radius+middlex;
+
+  /*if (flag)
+    fprintf(stderr,"x=%d, y=%d midx=%.2f --> px,py=(%.2f,%.2f) ,radius=%.2f theta=%.2f\n\t slice_no=%d  --> %d,%d,%d\n",
+    x,y,middlex,px,py,radius,theta,slice_no,int(slice_x+0.5),int(slice_y+0.5),slice_no);*/
+	    
+
+
+  if (slice_x>=0 && slice_x<dim[0]-5)
+    return img->GetScalarComponentAsDouble(int(slice_x+0.5),int(slice_y+0.5),slice_no,comp);
+  else
+    return 0.0;
+}
+
+
+void vtkpxImageExtract::SimpleExecutePolar(vtkImageData* input, vtkImageData* output) 
+{
+  vtkDebugMacro(<< "Extracting Polar Slice");
+
+  int dim[3];   input->GetDimensions(dim);
+  double ori[3];  input->GetOrigin(ori);
+  double sp[3]; input->GetSpacing(sp);
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  int dty=inp->GetDataType();
+
+  output->SetSpacing(input->GetSpacing()[0],input->GetSpacing()[0],input->GetSpacing()[0]);
+  output->SetScalarType(dty);
+  output->SetNumberOfScalarComponents(1);
+  output->SetOrigin(0.0,0.0,0.0);
+
+  if (this->InternalCurrentPlane<0)
+      this->InternalCurrentPlane=0;
+  else if (this->InternalCurrentPlane>2)
+      this->InternalCurrentPlane=2;
+
+
+  if (this->SliceNo<0)
+    {
+      this->SliceNo=0;
+    }
+  else if (this->InternalCurrentPlane==0 && this->SliceNo>=dim[1])
+    {
+      this->SliceNo=dim[1]-1;
+    }
+  else if (this->InternalCurrentPlane>0 && this->SliceNo>=dim[2])
+    {
+      this->SliceNo=dim[2]-1;
+    }
+
+  if (this->Frame<0)
+    this->Frame=0;
+  if ( this->Frame>=input->GetNumberOfScalarComponents())
+    this->Frame=input->GetNumberOfScalarComponents()-1;
+
+  switch(this->InternalCurrentPlane)
+      {
+      case 2:
+      case 1:
+	{
+	  output->SetDimensions(dim[0],dim[1],1);
+	  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,0);
+	  output->AllocateScalars();
+	  vtkDataArray* out=output->GetPointData()->GetScalars();
+	  int offset=dim[0]*dim[1]*this->SliceNo;
+	  //fprintf(stderr,"\t\t\t ***** Image Extract this=%d Plane=%d Slice=%d\n",this,InternalCurrentPlane,SliceNo);
+	  for (int j=0;j<dim[1];j++)
+	    for (int i=0;i<dim[0];i++)
+	      out->SetComponent(i+j*dim[0],0,inp->GetComponent(i+dim[0]*j+offset,this->Frame));
+	}
+	break;
+
+      case 0:
+	{
+	  float middlex=this->PolarMiddle;
+	  if (middlex<0)
+	    middlex=float(dim[0])/2.0;
+	  float angularspacing=180.0/float(dim[2]);
+	  output->SetDimensions(dim[0],dim[0],1);
+	  output->SetWholeExtent(0,dim[0]-1, 0,dim[0]-1, 0,0);
+	  output->AllocateScalars();
+	  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+	  //fprintf(stderr,"\t\t\t **** Image Extract this=%d Plane=%d Slice=%d\n",this,InternalCurrentPlane,SliceNo);
+
+	  int iz=this->SliceNo;
+	  for (int iy=0;iy<dim[0];iy++)
+	    for (int ix=0;ix<dim[0];ix++)
+	      out->SetComponent(ix+iy*dim[0],0,
+				this->Get3DEchoVoxel(input,dim,ix,iy,iz,this->Frame,angularspacing,middlex));
+	}
+	break;
+     }
+
+  vtkErrorMacro("output" << output);
+}
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxImageExtract.h b/bioimagesuite30_src/Common/vtkpxImageExtract.h
new file mode 100644
index 0000000..0b35e80
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxImageExtract.h
@@ -0,0 +1,185 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+  
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageExtract.h,v $
+  Language:  C++
+  Date:      $Date: 2003/05/13 15:37:02 $
+  Version:   $Revision: 1.2 $
+  
+  
+  Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+  All rights reserved.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+  
+=========================================================================*/
+// .NAME vtkpxImageExtract - extracts slices from 3D Images
+// .SECTION Description
+// Extracts single 2D slice from 3D Images determined by slice number, CurrentPlane and flip 
+// CurrentPlane = 0=YZ, 1=XZ, 2=XY
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkExtractVOI
+
+#ifndef __vtkpxImageExtract_h
+#define __vtkpxImageExtract_h
+
+#include "vtkSimpleImageToImageFilter.h"
+
+class vtkpxImageExtract : public vtkSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkpxImageExtract,vtkSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  
+  // Description:
+  // Construct object to extract all of the input data.
+  
+  static vtkpxImageExtract *New();
+  
+  // Description:
+  // CurrentPlane  0=YZ, 1=XZ, 2=XY slice=sliceno
+  void SetCurrentPlane(int);
+  int  GetCurrentPlane();
+  
+  // Description:
+  // Set Slice Number 0--Dim-1
+  vtkSetMacro(SliceNo,int);
+  vtkGetMacro(SliceNo,int);
+  
+  // Description:
+  // Use this to set sliceno,numslices and currentplane
+  // for extracting frames
+  vtkSetMacro(Frame,int);
+  vtkGetMacro(Frame,int);
+  
+  // Description:
+  // Polar Mode used for ultrasound images
+  vtkSetClampMacro(PolarMode,int,0,1);
+  vtkGetMacro(PolarMode,int);
+  vtkBooleanMacro(PolarMode,int);
+
+  // Description:
+  // Use this to set sliceno,numslices and currentplane
+  // for extracting frames
+  vtkSetMacro(PolarMiddle,float);
+  vtkGetMacro(PolarMiddle,float);
+
+  // Description:
+  // Limit Texture Size
+  vtkSetClampMacro(LimitTextureSize,int,0,1);
+  vtkGetMacro(LimitTextureSize,int);
+  vtkBooleanMacro(LimitTextureSize,int);
+
+  // Description:
+  // If On then pass all frames -- useful for color image display
+  vtkSetClampMacro(ExtractAllFrames,int,0,1);
+  vtkGetMacro(ExtractAllFrames,int);
+  vtkBooleanMacro(ExtractAllFrames,int);
+
+  // Description:
+  // Limit Texture Size
+  vtkSetClampMacro(ForcePowerOfTwo,int,0,1);
+  vtkGetMacro(ForcePowerOfTwo,int);
+  vtkBooleanMacro(ForcePowerOfTwo,int);
+
+
+  // Description:
+  // Set Maximum Texture Size
+  vtkSetClampMacro(MaximumTextureSize,int,32,512);
+  vtkGetMacro(MaximumTextureSize,int);
+
+  // Description:
+  // Internal Stuff
+  vtkGetMacro(InternalCurrentPlane,int);
+
+  // Description:
+  vtkGetVectorMacro(SampleRate,int,2);
+
+protected:
+  //BTX
+  vtkpxImageExtract();
+  ~vtkpxImageExtract() {};
+  vtkpxImageExtract(const vtkpxImageExtract&) {};
+  void operator=(const vtkpxImageExtract&) {};
+
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+  virtual void SimpleExecutePolar(vtkImageData* input, vtkImageData* output);
+
+  // Polar Stuff
+  virtual float Get3DEchoVoxel(vtkImageData* img,int dim[3],int x,int y,int z,int comp,
+			       float angularspacing,float middlex);
+
+  
+  // Execute Information Replacements
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+  virtual int RequestInformationPolar(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+				      vtkInformationVector *outputVector);
+
+  //  virtual void  ExecuteInformation();
+  //  virtual void  ExecuteInformationPolar();
+
+  int InternalCurrentPlane;
+  int SliceNo;
+  int Frame;
+  int PolarMode;
+  float PolarMiddle;
+  int LimitTextureSize;
+  int ForcePowerOfTwo;
+  int ExtractAllFrames; // for color images
+  int MaximumTextureSize;
+  int SampleRate[2];
+  int unpaddedoutdim[3];
+  //ETX
+
+  vtkSetClampMacro(InternalCurrentPlane,int,0,2);
+
+
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxImageExtractVOI.cpp b/bioimagesuite30_src/Common/vtkpxImageExtractVOI.cpp
new file mode 100644
index 0000000..56b5dee
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxImageExtractVOI.cpp
@@ -0,0 +1,219 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxImageExtractVOI.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkbisImageReslice.h"
+#include "pxutil.h"
+
+vtkpxImageExtractVOI* vtkpxImageExtractVOI::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageExtractVOI");
+  if(ret)
+    {
+      return (vtkpxImageExtractVOI*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageExtractVOI;
+}
+
+
+// Construct object to extract all of the input data.
+vtkpxImageExtractVOI::vtkpxImageExtractVOI()
+{
+  this->VOI[0] = this->VOI[2] = this->VOI[4] = 0;
+  this->VOI[1] = this->VOI[3] = this->VOI[5] = 1;
+  this->SampleRate[0] = this->SampleRate[1] = this->SampleRate[2] = 1;
+}
+
+// ---------------------------------------------------------------------------
+
+void vtkpxImageExtractVOI::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkpxSimpleImageToImageFilter::PrintSelf(os,indent);
+
+  os << indent << "  VOI " << this->VOI[0] << ":" << this->VOI[1] << " ";
+  os << indent << "  VOI " << this->VOI[2] << ":" << this->VOI[3] << " ";
+  os << indent << "  VOI " << this->VOI[4] << ":" << this->VOI[5] << "\n";
+  os << indent << "  SampleRate "<<this->SampleRate[0]<< ","<<this->SampleRate[1]<<","<<this->SampleRate[2]<<"\n";
+}
+// ---------------------------------------------------------------------------
+void vtkpxImageExtractVOI::SetRegion(double center[3],double gridspacing[3],double scale)
+{
+  if (this->GetImageDataInput(0)==NULL)
+    {
+      vtkErrorMacro(<<"Set Input First before Calling SetRegion\n");
+      fprintf(stderr,"Set Input First before Calling SetRegion\n");
+      return;
+    }
+
+  
+
+  int p1[3],p2[3];
+  double origin[3];   this->GetImageDataInput(0)->GetOrigin(origin);
+  double spacing[3];  this->GetImageDataInput(0)->GetSpacing(spacing);
+  int  dim[3];        this->GetImageDataInput(0)->GetDimensions(dim);
+  int extent[6];
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      double x1=center[ia]-scale*gridspacing[ia];
+      x1=(x1-origin[ia])/spacing[ia];
+      p1[ia]=Irange(int(x1),0,dim[ia]-1);
+
+      double x2=center[ia]+scale*gridspacing[ia];
+      x2=(x2-origin[ia])/spacing[ia];
+      p2[ia]=Irange(int(x2),0,dim[ia]-1);
+      
+      extent[ia*2]=p1[ia];  extent[ia*2+1]=p2[ia];
+    }
+
+  this->SetVOI(extent);
+  this->SetSampleRate(1,1,1);
+
+  /*  fprintf(stderr,"::SetRegion:: Input (%.2f,%.2f,%.2f), sp=(%.2f,%.2f,%.2f) sc=%.2f --> (%d:%d,%d:%d,%d:%d)\n",
+	  center[0],center[1],center[2],gridspacing[1],gridspacing[1],gridspacing[2],scale,
+	  extent[0],extent[1],extent[2],extent[3],extent[4],extent[5]);*/
+}
+
+void vtkpxImageExtractVOI::ExecuteInformation()
+{
+  int i, outDims[3], voi[6];
+  int rate[3];
+  int wholeExtent[6];
+
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  vtkImageData* input=this->GetImageDataInput(0);
+  vtkImageData* output=this->GetOutput();
+  
+  if (this->GetImageDataInput(0) == NULL)
+    {
+      vtkErrorMacro("Missing input");
+      return;
+    }
+  input->GetWholeExtent( wholeExtent );
+  
+  for ( i=0; i < 6; i++ )
+    {
+      voi[i] = this->VOI[i];
+    }
+
+  for ( i=0; i < 3; i++ )
+    {
+      if ( voi[2*i+1] > wholeExtent[2*i+1] )
+	{
+	  voi[2*i+1] = wholeExtent[2*i+1];
+	}
+      else if ( voi[2*i+1] < wholeExtent[2*i] )
+	{
+	  voi[2*i+1] = wholeExtent[2*i];
+	}
+      if ( voi[2*i] < wholeExtent[2*i] )
+	{
+	  voi[2*i] = wholeExtent[2*i];
+	}
+      else if ( voi[2*i] > wholeExtent[2*i+1] )
+	{
+	  voi[2*i] = wholeExtent[2*i+1];
+	}
+      
+      if ( voi[2*i] > voi[2*i+1] )
+	{
+	  voi[2*i] = voi[2*i+1];
+	}
+      
+      if ( (rate[i] = this->SampleRate[i]) < 1 )
+	{
+	  rate[i] = 1;
+	}
+      
+      outDims[i] = (voi[2*i+1] - voi[2*i]) / rate[i] + 1;
+      if ( outDims[i] < 1 )
+	{
+	  outDims[i] = 1;
+	}
+    }
+  
+  // This makes sense for sample rates of 1, 1, 1.
+  wholeExtent[0] = 0;
+  wholeExtent[1] = outDims[0] - 1;
+  wholeExtent[2] = 0;
+  wholeExtent[3] = outDims[1] - 1;
+  wholeExtent[4] = 0;
+  wholeExtent[5] = outDims[2] - 1;
+  
+  output->SetDimensions(outDims);
+  output->SetWholeExtent( wholeExtent );
+
+  double spacing[3]; input->GetSpacing(spacing);
+  double origin[3];  input->GetOrigin(origin);
+
+  output->SetSpacing(spacing[0]*rate[0],spacing[1]*rate[1],spacing[2]*rate[2]);
+  output->SetOrigin(voi[0]*spacing[0]+origin[0],
+		    voi[2]*spacing[1]+origin[1],
+		    voi[4]*spacing[2]+origin[2]);
+
+
+
+
+}
+// ---------------------------------------------------------------------------
+void vtkpxImageExtractVOI::SimpleExecute(vtkImageData* input, vtkImageData* output) 
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<< "Bad Input");
+      return;
+    }
+
+  int dim[3]; output->GetDimensions(dim);
+
+
+  vtkbisImageReslice* resl=vtkbisImageReslice::New();
+  resl->SetInput(input);
+  resl->SetOutputOrigin(output->GetOrigin());
+  resl->SetOutputSpacing(output->GetSpacing());
+  resl->SetInterpolationMode(0);
+  resl->SetOutputExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  resl->OptimizationOff();
+  resl->Update();
+
+  output->ShallowCopy(resl->GetOutput());
+  resl->Delete();
+}
+
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxImageExtractVOI.h b/bioimagesuite30_src/Common/vtkpxImageExtractVOI.h
new file mode 100644
index 0000000..360ef03
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxImageExtractVOI.h
@@ -0,0 +1,121 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+  
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageExtractVOI.h,v $
+  Language:  C++
+  Date:      $Date: 2003/05/13 15:37:02 $
+  Version:   $Revision: 1.2 $
+  
+  
+  Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+  All rights reserved.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+  
+=========================================================================*/
+// .NAME vtkpxImageExtractVOI - extracts slices from 3D Images
+// .SECTION Description
+// ExtractVOIs single 2D slice from 3D Images determined by slice number, CurrentPlane and flip 
+// CurrentPlane = 0=YZ, 1=XZ, 2=XY
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkExtractVOIVOI
+
+#ifndef __vtkpxImageExtractVOI_h
+#define __vtkpxImageExtractVOI_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+
+class vtkpxImageExtractVOI : public vtkpxSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkpxImageExtractVOI,vtkpxSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  
+  // Description:
+  // Construct object to extract all of the input data.
+  static vtkpxImageExtractVOI *New();
+  
+  // Description:
+  // Specify i-j-k (min,max) pairs to extract. The resulting structured points
+  // dataset can be of any topological dimension (i.e., point, line, image, 
+  // or volume). 
+  vtkSetVector6Macro(VOI,int);
+  vtkGetVectorMacro(VOI,int,6);
+
+  // Description:
+  // Set the sampling rate in the i, j, and k directions. If the rate is >
+  // 1, then the resulting VOI will be subsampled representation of the
+  // input.  For example, if the SampleRate=(2,2,2), every other point will
+  // be selected, resulting in a volume 1/8th the original size.
+  vtkSetVector3Macro(SampleRate, int);
+  vtkGetVectorMacro(SampleRate, int, 3);
+
+
+  // Description:
+  // Set VOI for Image Region:
+  virtual void SetRegion(double center[3],double spacing[3],double scale);
+
+protected:
+
+  vtkpxImageExtractVOI();
+  ~vtkpxImageExtractVOI() {};
+  vtkpxImageExtractVOI(const vtkpxImageExtractVOI&) {};
+  void operator=(const vtkpxImageExtractVOI&) {};
+
+  // Description:
+  // Execute Stuff
+  virtual void  ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+
+  //Members
+  int VOI[6];
+  int SampleRate[3];
+
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxImageReplaceSlice.cpp b/bioimagesuite30_src/Common/vtkpxImageReplaceSlice.cpp
new file mode 100644
index 0000000..630f322
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxImageReplaceSlice.cpp
@@ -0,0 +1,198 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxImageReplaceSlice.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include <stdio.h>
+
+vtkpxImageReplaceSlice* vtkpxImageReplaceSlice::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageReplaceSlice");
+  if(ret)
+    {
+      return (vtkpxImageReplaceSlice*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageReplaceSlice;
+}
+
+
+// Construct object to extract all of the input data.
+vtkpxImageReplaceSlice::vtkpxImageReplaceSlice()
+{
+  this->InternalCurrentPlane=2; 
+  this->SliceNo=0;
+  this->Frame=0;
+  this->InsertedSlice=NULL;
+  this->DeepCopyMode=1;
+}
+
+// ---------------------------------------------------------------------------
+
+void vtkpxImageReplaceSlice::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkpxSimpleImageToImageFilter::PrintSelf(os,indent);
+
+  os << indent << "  InternalCurrentPlane " << this->InternalCurrentPlane << "\n";
+  os << indent << "  SliceNo " << this->SliceNo << "\n";
+  os << indent << "  Frame " << this->Frame << "\n";
+  os << indent << "  DeepCopyMode " << this->DeepCopyMode << "\n";
+
+  this->SetInsertedSlice(NULL);
+}
+// ---------------------------------------------------------------------------
+
+void vtkpxImageReplaceSlice::SetCurrentPlane(int a)
+{
+  this->SetInternalCurrentPlane(a);
+}
+
+int  vtkpxImageReplaceSlice::GetCurrentPlane()
+{
+  return this->InternalCurrentPlane;
+}
+
+// ---------------------------------------------------------------------------
+void vtkpxImageReplaceSlice::SimpleExecute(vtkImageData* input, vtkImageData* output) 
+{
+  if (input==NULL || this->InsertedSlice==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxImageReplaceSlice\n");
+      return;
+    }
+
+  // --------------------- Check Dimensions ------------------------------------
+  if (this->InternalCurrentPlane<0)
+      this->InternalCurrentPlane=0;
+  else if (this->InternalCurrentPlane>2)
+      this->InternalCurrentPlane=2;
+
+
+  int dim[3];   input->GetDimensions(dim);
+  int dim2[3];  this->InsertedSlice->GetDimensions(dim2);
+  int targetdim[3];
+
+  
+
+
+  targetdim[2]=  1;
+  switch (this->InternalCurrentPlane)
+    {
+    case 2:
+      targetdim[0] = dim[0];
+      targetdim[1] = dim[1];
+      break;
+    case 1:
+      targetdim[0] = dim[0];
+      targetdim[1] = dim[2];
+      break;
+    case 0:
+      targetdim[0] = dim[1];
+      targetdim[1] = dim[2];
+      break;
+    }
+  
+  int nc=this->InsertedSlice->GetNumberOfScalarComponents();
+
+  if (targetdim[0]!=dim2[0] || targetdim[1]!=dim2[1] || targetdim[2]!=dim2[2])
+    {
+      vtkErrorMacro(<<"Cannot Insert Slice, Bad Dimensions\n");
+      return;
+    }
+
+
+  if (this->SliceNo<0)
+    this->SliceNo=0;
+  else if (this->SliceNo>=dim[this->InternalCurrentPlane])
+    this->SliceNo=dim[this->InternalCurrentPlane]-1;
+
+  if (this->Frame<0)
+    this->Frame=0;
+  if ( this->Frame>=input->GetNumberOfScalarComponents())
+    this->Frame=input->GetNumberOfScalarComponents()-1;
+
+  vtkDebugMacro(<< "Inserting Slice");
+
+  if (this->DeepCopyMode)
+    output->DeepCopy(input);
+  else
+    output->GetPointData()->SetScalars(input->GetPointData()->GetScalars());
+
+  vtkDataArray* slarr=this->InsertedSlice->GetPointData()->GetScalars();
+  int index=0;
+
+  switch(this->InternalCurrentPlane)
+      {
+      case 2:
+	{
+	  int offset=dim[0]*dim[1]*this->SliceNo;
+	  for (int j=0;j<dim[1];j++)
+	    for (int i=0;i<dim[0];i++)
+	      {
+		output->SetScalarComponentFromDouble(i,j,this->SliceNo,this->Frame,
+						     slarr->GetComponent(index,0));
+		++index;
+	      }
+	}
+	break;
+
+      case 1:
+	{
+	  for (int k=0;k<dim[2];k++)
+	    for (int i=0;i<dim[0];i++)
+	      {
+		output->SetScalarComponentFromDouble(i,this->SliceNo,k,this->Frame,
+						     slarr->GetComponent(index,0));
+		++index;
+	      }
+	}
+	break;
+	
+      case 0:
+	{
+	  for (int k=0;k<dim[2];k++)
+	    for (int j=0;j<dim[1];j++)
+	      {
+		output->SetScalarComponentFromDouble(this->SliceNo,j,k,this->Frame,
+						     slarr->GetComponent(index,0));
+		++index;
+	      }
+	}
+	break;
+      }
+  
+  output->GetPointData()->GetScalars()->Modified();
+  double* r=output->GetPointData()->GetScalars()->GetRange(0);
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxImageReplaceSlice.h b/bioimagesuite30_src/Common/vtkpxImageReplaceSlice.h
new file mode 100644
index 0000000..42a2a13
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxImageReplaceSlice.h
@@ -0,0 +1,133 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+  
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageReplaceSlice.h,v $
+  Language:  C++
+  Date:      $Date: 2003/05/13 15:37:02 $
+  Version:   $Revision: 1.2 $
+  
+  
+  Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+  All rights reserved.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+  
+=========================================================================*/
+// .NAME vtkpxImageReplaceSlice - extracts slices from 3D Images
+// .SECTION Description
+// ReplaceSlices single 2D slice from 3D Images determined by slice number, CurrentPlane and flip 
+// CurrentPlane = 0=YZ, 1=XZ, 2=XY
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkReplaceSliceVOI
+
+#ifndef __vtkpxImageReplaceSlice_h
+#define __vtkpxImageReplaceSlice_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkpxImageReplaceSlice : public vtkpxSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkpxImageReplaceSlice,vtkpxSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  
+  // Description:
+  // Construct object to extract all of the input data.
+  
+  static vtkpxImageReplaceSlice *New();
+  
+  // Description:
+  // CurrentPlane  0=YZ, 1=XZ, 2=XY slice=sliceno
+  void SetCurrentPlane(int);
+  int  GetCurrentPlane();
+  
+  // Description:
+  // Set Slice Number 0--Dim-1
+  vtkSetMacro(SliceNo,int);
+  vtkGetMacro(SliceNo,int);
+  
+  // Description:
+  // Use this to set sliceno,numslices and currentplane
+  // for extracting frames
+  vtkSetMacro(Frame,int);
+  vtkGetMacro(Frame,int);
+  
+  // Description:
+  // Slice To Insert
+  vtkSetObjectMacro(InsertedSlice,vtkImageData);
+  vtkGetObjectMacro(InsertedSlice,vtkImageData);
+
+  // Description:
+  vtkSetClampMacro(DeepCopyMode,int,0,1);
+  vtkGetMacro(DeepCopyMode,int);
+  
+
+protected:
+  //BTX
+  vtkpxImageReplaceSlice();
+  ~vtkpxImageReplaceSlice() {};
+  vtkpxImageReplaceSlice(const vtkpxImageReplaceSlice&) {};
+  void operator=(const vtkpxImageReplaceSlice&) {};
+
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+
+  int InternalCurrentPlane;
+  int SliceNo;
+  int Frame;
+  int DeepCopyMode;
+  vtkImageData* InsertedSlice;
+
+  //ETX
+
+  vtkSetClampMacro(InternalCurrentPlane,int,0,2);
+  vtkGetMacro(InternalCurrentPlane,int);
+
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxMath.cpp b/bioimagesuite30_src/Common/vtkpxMath.cpp
new file mode 100644
index 0000000..e0cc66f
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxMath.cpp
@@ -0,0 +1,1126 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+
+#include <nrutil.h>
+#include "vtkpxMath.h"
+#include "vtkMath.h"
+#include "nrutil.h"
+#include "vtkObjectFactory.h"
+#include "vtkFloatArray.h"
+#include "fitpack.h"
+#include "vtkPolyData.h"
+#include "pxgeometrystruct.h"
+#include "vtkPolyDataNormals.h"
+#include "vtkPointData.h"
+#include "pxutil.h"
+#include "pxisinf.h"
+#include <vtkstd/algorithm>
+#include "vnl/vnl_gamma.h"
+#include "vnl/vnl_math.h"
+#include "vnl/vnl_erf.h"
+#include "bio_f2c.h"
+#include "bioimagesuite_settings.h"
+
+
+extern "C" double dbetai_(double *x, double *pin, double *qin);
+extern "C" double dgamma_(double *x);
+
+
+
+//extern "C" { double dbetai_(double *x, double *pin, double *qin); }
+
+// ------------------------------------------------------------------------
+// Define M_PI for Windows !!
+// ------------------------------------------------------------------------
+#ifndef M_PI
+#define M_PI 3.1415926854
+#endif
+
+// ------------------------------------------------------------------------
+
+vtkpxMath* vtkpxMath::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxMath");
+  if(ret)
+    {
+      return (vtkpxMath*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxMath;
+}
+
+//----------------------------------------------------------------------------
+// Euclidean To Polar Conversions
+//----------------------------------------------------------------------------
+void vtkpxMath::EuclideanToPolar(float X,float Y,float& R,float& Theta)
+{
+  R=0.0;
+  Theta=0.0;
+
+  if (X!=0.0 && Y !=0.0)
+    {
+      R=sqrt(X*X+Y*Y);
+      Theta=atan2(Y,X);
+    }
+}
+
+void vtkpxMath::PolarToEuclidean(float R,float Theta,float& X,float& Y)
+{
+  X=R*cos(Theta);
+  Y=R*sin(Theta);
+}
+
+
+// -------------------------------------------------------------------------------
+// Code To Compute Distances around a circle  (units =radians)
+// -------------------------------------------------------------------------------
+
+float vtkpxMath::FindClosestAngleP1(float p1,float p0)
+{
+  if (p0==p1)
+    return p1;
+
+  while (p1-p0 > M_PI)
+    p1-=M_PI*2.0;
+  while (p1-p0 < -M_PI)
+    p1+=M_PI*2.0;
+
+  return p1;
+}
+
+float vtkpxMath::FindMinAngleDistance(float p1,float p0)
+{
+  return vtkpxMath::FindClosestAngleP1(p1,p0)-p0;
+}
+
+
+int vtkpxMath::ComputeAngleDistancePairs(float* ph,float* temp,int step,int np)
+{
+  int numdiff=np-step;
+  if (numdiff<1)
+    return 0;
+
+  for (int i=0;i<numdiff;i++)
+    temp[i]=FindMinAngleDistance(ph[i+step],ph[i]);
+
+  return numdiff;
+}
+
+// ------------------------------------------------------------------------------------
+// Order Statistics Code From Numerical Recipes
+// -------------------------------------------------------------------------------------
+
+
+
+float vtkpxMath::SelectKthLargest(unsigned long k0offset, unsigned long n, float* arr0offset)
+{
+
+  std::nth_element(arr0offset,arr0offset+k0offset,arr0offset+n);
+  return arr0offset[k0offset];
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+}
+
+
+float vtkpxMath::GetMedian(unsigned long n, float* arr)
+{
+  if (n<1)
+    return 0.0;
+
+  if (n==1)
+    return arr[0];
+
+  if (n==2)
+    return 0.5*(arr[0]+arr[1]);
+
+  unsigned long half=n/2;
+
+  // Even Number
+  if (half*2 == n)
+    {
+      float v1=SelectKthLargest(half-1,n,arr);
+      float v2=SelectKthLargest(half,n,arr);
+      return 0.5*(v1+v2);
+    }
+
+  // Odd Number
+  return SelectKthLargest(half,n,arr);
+
+}
+
+
+void vtkpxMath::Meanfit(float* x, float* y, int ndata, float& a, float& b, float& abdev)
+{
+  // Original Code Follows
+  // This fits a straight line using ordinary least squares
+  float sx=0.0,sy=0.0,sxy=0.0,sxx=0.0;
+
+  for (int j=0;j<ndata;j++)
+    {
+      sx += x[j];
+      sy += y[j];
+      sxy += x[j]*y[j];
+      sxx += x[j]*x[j];
+    }
+  //  fprintf(stderr,"sx=%.2f sy=%.2f sxy=%.2f sxx=%.2f\n",sx,sy,sxy,sxx);
+
+  float del=ndata*sxx-sx*sx;
+  a=(sxx*sy-sx*sxy)/del;
+  b=(ndata*sxy-sx*sy)/del;
+
+  //  fprintf(stderr,"del = %.2f a=%.2f b=%.2f\n",del,a,b);
+  abdev=0.0;
+  float temp=0.0;
+  for (int ja=0;ja<ndata;ja++)
+    abdev += (temp=y[ja]-(a+b*x[ja]),temp*temp);
+}
+
+void vtkpxMath::WeightedMeanfit(float *x, float *y, int ndata, float *w, int mwt,
+				float &a,float &b,
+				float &siga, float &sigb, float &chi2, float &q)
+{
+  float wt,t,sxoss,sx=0.0,sy=0.0,st2=0.0,ss,sigdat;
+
+  b=0.0;
+  if (mwt)
+    {
+      ss=0.0;
+      for (int i=0;i<ndata;i++)
+	{
+	  wt=pow(w[i],(float)2.0);
+	  ss += wt;
+	  sx += x[i]*wt;
+	  sy += y[i]*wt;
+	}
+    }
+  else
+    {
+      for (int i=0;i<ndata;i++)
+	{
+	  sx += x[i];
+	  sy += y[i];
+	}
+      ss=ndata;
+    }
+  sxoss=sx/ss;
+  if (mwt)
+    {
+      for (int i=0;i<ndata;i++)
+	{
+	  t=(x[i]-sxoss)*w[i];
+	  st2 += t*t;
+	  b += t*y[i]*w[i];
+	}
+    }
+  else
+    {
+      for (int i=0;i<ndata;i++)
+	{
+	  t=x[i]-sxoss;
+	  st2 += t*t;
+	  b += t*y[i];
+	}
+    }
+  b /= st2;
+  a=(sy-sx*b)/ss;
+  siga=sqrt((1.0+sx*sx/(ss*st2))/ss);
+  sigb=sqrt(1.0/st2);
+  chi2=0.0;
+  if (mwt == 0)
+    {
+      for (int i=0;i<ndata;i++)
+	chi2 += sqrt(y[i]-a-b*x[i]);
+      q=1.0;
+      sigdat=sqrt(chi2/(ndata-2));
+      siga *= sigdat;
+      sigb *= sigdat;
+    }
+  else
+    {
+      for (int i=0;i<ndata;i++)
+	chi2 += sqrt((y[i]-a-b*x[i]))*w[i];
+      q=vnl_gamma_q( double(0.5*(ndata-2)) , chi2*0.5 );
+    }
+}
+
+
+void vtkpxMath::Meanfit_Short(short* x, short* y, int ndata, short& a, short& b, short& abdev)
+{
+  // Original Code Follows
+  // This fits a straight line using ordinary least squares
+  short sx=0,sy=0,sxy=0,sxx=0;
+
+  for (int j=0;j<ndata;j++)
+    {
+      sx += x[j];
+      sy += y[j];
+      sxy += x[j]*y[j];
+      sxx += x[j]*x[j];
+    }
+
+  short del=ndata*sxx-sx*sx;
+  a=(sxx*sy-sx*sxy)/del;
+  b=(ndata*sxy-sx*sy)/del;
+  abdev=0;
+  short temp=0;
+  for (int ja=0;ja<ndata;ja++)
+    abdev += (temp=y[ja]-(a+b*x[ja]),temp*temp);
+}
+
+
+// --------------------------------------------------------------------------------
+// Fiting Code from Numerical Recipes to fit y=ax+b using
+// absolute differences (Medfit)
+// NRrofunc is a utility routine
+// --------------------------------------------------------------------------------
+
+
+
+/*extern int ndatat;
+  extern float *xt,*yt,aa,abdevt;*/
+// originally rofunc in numerical recipes, eliminated 1-offset code and global variables
+
+float vtkpxMath::NRrofunc(float b,float* xt,float* yt,float& aa,float& abdevt,int ndatat,float* arr)
+{
+#ifdef BIS_USE_NR
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+#else
+  return 0.0;
+#endif
+}
+
+
+
+
+void vtkpxMath::Medfit(float* x, float* y, int ndata, float& a, float& b, float& abdev)
+{
+
+  float* temp_arr=new float[ndata];
+  Medfit(x,y,ndata,a,b,abdev,temp_arr);
+  delete [] temp_arr;
+}
+
+
+void vtkpxMath::Medfit(float* x, float* y, int ndata, float& a, float& b, float& abdev,float *temp_arr)
+{
+#ifdef BIS_USE_NR
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+#else
+  vtkpxMath::Meanfit(x,y,ndata,a,b,abdev);
+#endif
+
+}
+
+
+
+// --------------------------------------------------------------------------------
+void vtkpxMath::Heapsort(unsigned long n, float* ra0offset)
+{
+  std::sort(ra0offset,ra0offset+n);
+  //The following code is commented out,
+  //It is left there for Legacy purposes only
+
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+}
+
+
+void vtkpxMath::Heapsort_Short(unsigned long n, short* ra0offset)
+{
+
+  std::sort(ra0offset,ra0offset+n);
+
+
+  //The following code is commented out,
+  //It is left there for Legacy purposes only
+
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+}
+
+// ----------------------------------------------------------------------------------
+float vtkpxMath::Gaussian(float x,float m,float sigma2)
+{
+  float t= (x-m)*(x-m)/(-2.0*sigma2);
+  float A= 1.0/sqrt(2.0*M_PI*sigma2);
+  return A*exp(t);
+}
+
+float vtkpxMath::Rayleigh(float x,float beta2)
+{
+  if (x<0.0)
+    return 0.0;
+
+  return (x/beta2)*exp(-(0.5*x*x)/beta2);
+}
+// ----------------------------------------------------------------------------------
+float vtkpxMath::GaussianRandom()
+{
+  static int mz_previous_normal_flag=0;
+  static double mz_previous_normal=0.0;
+  if (mz_previous_normal_flag)
+    {
+      mz_previous_normal_flag = 0;
+      return mz_previous_normal;
+    }
+  else
+    {
+      double x,y,r2;
+      do
+	{
+	  x=2.0*vtkMath::Random()-1.0;
+	  y=2.0*vtkMath::Random()-1.0;
+	  r2 = x*x+y*y;
+	}
+      while (r2 >=1.0 || r2 == 0.0);
+      double fac = vcl_sqrt(-2.0*vcl_log(r2)/r2);
+      mz_previous_normal = x*fac;
+      mz_previous_normal_flag = 1;
+      return y*fac;
+    }
+}
+
+
+float vtkpxMath::ZscoreToPvalue(float Z)
+{
+  // From itkGaussianDistribution (2 tail)
+  return 2.0*(1.0-0.5 * (vnl_erf(vnl_math::sqrt1_2 * fabs(Z)) + 1.0));
+
+}
+
+float vtkpxMath::PvalueToZscore(float p)
+{
+  /*  if (p<1e-8 || p>0.99 )
+      return -1.0;*/
+
+  //  fprintf(stderr,"Looking for t for p=%.6f\n",p);
+
+  float maxt=0.5,minp=p+1.0;
+  while (minp>p)
+    {
+      maxt*=2.0;
+      minp=ZscoreToPvalue(maxt);
+      //      fprintf(stderr,"maxt=%.4f,minp=%.4f, p=%.4f\n");
+    }
+  //  fprintf(stderr,"Bound 1 = minp=%6.4f maxt=%6.4f\n",minp,maxt);
+
+  float mint=10.0,maxp=p-1.0;
+
+  while (maxp<p)
+    {
+      mint*=0.5;
+      maxp=ZscoreToPvalue(mint);
+    }
+
+  //  fprintf(stderr,"Bound 2 = maxp=%6.4f mint=%6.4f\n",maxp,minp);
+  //  fprintf(stderr,"Looking in t=%6.4f:%6.4f\n",mint,maxt);
+
+  float dt=fabs(maxt-mint)/(maxt+mint);
+  float newt=0.5*(maxt+mint);
+
+  int count=1;
+
+  while (dt>0.001 && count<1000)
+    {
+      newt=0.5*(maxt+mint);
+
+      //      fprintf(stderr,"Looking in %.4f (%.6f):%.4f(%.6f) dt=%.6f\t",	      mint,maxp,maxt,minp,dt);
+      float newp=ZscoreToPvalue(newt);
+      //      fprintf(stderr,"newt=%.4f newp=%.4f\n",newt,newp);
+
+      if (newp>p)
+	{
+	  mint=newt;
+	  maxp=newp;
+	}
+      else
+	{
+	  maxt=newt;
+	  minp=newp;
+	}
+      dt=fabs(maxt-mint)/(maxt+mint);
+      ++count;
+    }
+
+  if (count==1000)
+    newt=-newt;
+
+  return newt;
+}
+
+#ifdef BIS_USE_NR
+
+float vtkpxMath_gammln(float xx)
+{
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+}
+
+#define MAXIT 100
+#define EPS 3.0e-7
+#define FPMIN 1.0e-30
+
+
+float vtkpxMath_betacf(float a, float b, float x)
+{
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+}
+#undef MAXIT
+#undef EPS
+#undef FPMIN
+
+
+float vtkpxMath_betai(float a, float b, float x)
+{
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+}
+// This ends a section of BIS_USE_NR stuff
+#endif
+
+float vtkpxMath::TtestToPvalue(float x,int df)
+{
+#ifdef BIS_USE_NR
+  float fre=float(df);
+  float   xi=fre/(fre+x*x);
+
+  //  fprintf(stderr,"fre=%f pin=%.2f xi=%f\n",fre*0.5,0.5,xi);
+  double value2=vtkpxMath_betai(fre*0.5,0.5,xi);
+
+
+  return value2;
+#else
+  return vtkpxMath::TtestToPvalue_itk(x,df);
+#endif
+}
+
+
+float vtkpxMath::TtestToPvalue_itk(float x,int df)
+{
+  double bx;
+  double pin, qin;
+  double dof;
+
+
+  // Based on Abramowitz and Stegun 26.7.1, which gives the probability
+  // that the absolute value of a random variable with a Student-t
+  // distribution is less than or equal to a specified t.
+  //
+  // P[|x| <= t] = 1 - Ix(v/2, 1/2)
+  //
+  // where Ix is the incomplete beta function and v is the number of
+  // degrees of freedom in the Student-t distribution and x is
+  // v / (v + t^2).
+  //
+  // To calculate the cdf of the Student-t we need to convert
+  // this formula.  For an x >= 0,
+  //
+  // P[|x| <= t] =   \int_{-t}^{t} p(x) dx
+  //             = 2 \int_0^t p(x) dx
+  //
+  // The cdf of the Student-t is
+  //
+  // P[x <= t] = \int_{-\inf}^t p(x) dx
+  //           = 0.5 + \int_0^t p(x) dx           (for x >= 0)
+  //           = 0.5 + 0.5 * P[|x| < t]           (from above)
+  //           = 0.5 + 0.5 * (1 - Ix(v/2. 1/2))
+  //           = 1 - 0.5 * Ix(v/2, 1/2)
+  //
+  dof = static_cast<double>(df);
+  bx = dof / (dof + (x*x));
+  pin = dof / 2.0;
+  qin = 0.5;
+
+  /*  if (x<0.0 || x > 1.0 )
+      return 1.0;*/
+
+  /*  for (int ia=0;ia<=10;ia++)
+    {
+      double numf=10.0;
+      double inpx=double(ia)*0.2;
+      double bbx=numf/(numf+inpx*inpx);
+      double ppin=numf*0.5;
+      double v=dbetai_(&bbx,&ppin,&qin);
+      fprintf(stdout,"x=%.2f \t v=%.2f \t(numf=%.1f)\n",bbx,v,numf);
+      }*/
+
+  //fprintf(stderr,"bx=%f pin=%.2f qin=%f\n",bx,pin,qin);
+
+  double value2=dbetai_(&bx,&pin,&qin);
+  return value2;
+
+  /*  if (x >= 0.0)
+    return 1.0 - 0.5 * dbetai_(&bx, &pin, &qin);
+
+    return 0.5 * dbetai_(&bx, &pin, &qin);*/
+}
+
+float vtkpxMath::PvalueToTvalue(float p,int df)
+{
+  if (p<1e-8 || p>0.99 || df < 1)
+    return -1.0;
+
+  //fprintf(stderr,"Looking for t for p=%.6f\n",p);
+
+  float maxt=0.5,minp=p+1.0;
+  while (minp>p)
+    {
+      maxt*=2.0;
+      minp=TtestToPvalue(maxt,df);
+    }
+  //fprintf(stderr,"Bound 1 = minp=%6.4f maxt=%6.4f\n",minp,maxt);
+
+  float mint=10.0,maxp=p-1.0;
+
+  while (maxp<p)
+    {
+      mint*=0.5;
+      maxp=TtestToPvalue(mint,df);
+    }
+
+  //fprintf(stderr,"Bound 2 = maxp=%6.4f mint=%6.4f\n",maxp,minp);
+  //fprintf(stderr,"Looking in t=%6.4f:%6.4f\n",mint,maxt);
+
+  float dt=fabs(maxt-mint)/(maxt+mint);
+  float newt=0.5*(maxt+mint);
+
+  int count=1;
+
+  while (dt>0.001 && count<1000)
+    {
+      newt=0.5*(maxt+mint);
+
+      //fprintf(stderr,"Looking in %.4f (%.6f):%.4f(%.6f) dt=%.6f\t",	      mint,maxp,maxt,minp,dt);
+      float newp=TtestToPvalue(newt,df);
+      //fprintf(stderr,"newt=%.4f newp=%.4f\n",newt,newp);
+
+      if (newp>p)
+	{
+	  mint=newt;
+	  maxp=newp;
+	}
+      else
+	{
+	  maxt=newt;
+	  minp=newp;
+	}
+      dt=fabs(maxt-mint)/(maxt+mint);
+      ++count;
+    }
+
+  if (count==1000)
+    newt=-newt;
+
+  return newt;
+}
+
+// -----------------------------------------------------------------------------------------
+//               Geometric Stuff ...
+// ------------------------------------------------------------------------------------------
+int vtkpxMath::CalculateCurvatures(vtkPolyData* polydata,int scale,PXIntegerList* neighbours)
+{
+  static int debugmode=0;
+  int mode=0;
+  int numpoints=polydata->GetNumberOfPoints();
+
+
+  // Do Normals Scalars Stuff
+  // ------------------------
+  vtkFloatArray* curvature=vtkFloatArray::New();
+  curvature->SetNumberOfComponents(2);
+  curvature->SetNumberOfTuples(numpoints);
+
+  vtkFloatArray* normals=vtkFloatArray::New();
+  if (polydata->GetPointData()->GetNormals()!=NULL)
+    {
+      normals->DeepCopy(polydata->GetPointData()->GetNormals());
+    }
+  else
+    {
+      vtkPolyDataNormals* normalsFilter=vtkPolyDataNormals::New();
+      normalsFilter->SetInput(polydata);
+      normalsFilter->SetSplitting(0);
+      normalsFilter->Update();
+      normals->DeepCopy(normalsFilter->GetOutput()->GetPointData()->GetNormals());
+      normalsFilter->Delete();
+    }
+
+  vtkPoints* points=polydata->GetPoints();
+
+  if (debugmode)
+    fprintf(stderr,"Num Points= %d , curvature(%d,%d) normals(%d,%d)\n",
+	    numpoints,
+	    curvature->GetNumberOfTuples(),curvature->GetNumberOfComponents(),
+	    normals->GetNumberOfTuples(),normals->GetNumberOfComponents());
+
+  scale=Irange(scale,1,10);
+  if (mode==1 && debugmode)
+    fprintf(stderr,"Curvature mode=%d, scale=%d\n",mode,scale);
+
+  Vertex_3d neighbour_point[500],xformed_neighbour_point[500];
+  int neighbour_index[500];
+
+  Node_3d N, T1, T2, T;
+  double c[4], length;
+  double x, y, z;
+
+  double fx, fy, fxx, fxy, fyy;
+  //  Node_3d k1, k2;
+  double K1, K2;
+  int nrot;
+
+  double** A     = dmatrix(0, 500-1, 0, 5);
+  double** At    = dmatrix(0, 5, 0, 500-1);
+  double** B     = dmatrix(0, 5, 0, 5);
+  double** B_1   = dmatrix(0, 5, 0, 5);
+  int*     indx  = ivector(0, 5);
+  double** C     = dmatrix(0, 5, 0, 0);
+  double** C2    = dmatrix(0, 5, 0, 0);
+  double*  coeff = dvector(0, 5);
+  double** data  = dmatrix(0, 500-1, 0, 0);
+
+  double** g     = dmatrix(0, 1, 0, 1);
+  double** g_1   = dmatrix(0, 1, 0, 1);
+  double** b     = dmatrix(0, 1, 0, 1);
+  double** beta  = dmatrix(0, 1, 0, 1);
+
+
+  double ** a1_repl = new double*[2];
+  a1_repl[0] = new double[2];
+  a1_repl[1] = new double[2];
+
+  double ** v1_repl = new double*[2];
+  v1_repl[0] = new double[2];
+  v1_repl[1] = new double[2];
+
+  double* d1_repl=new double[2];
+
+
+  for(int i=0; i<numpoints; i++)
+    {
+      if (debugmode)
+	{
+	  if (100*int(i/100)==i)
+	    fprintf(stderr,"%d/%d ",i,numpoints);
+	}
+      for(int j=0; j<500; j++)
+	{
+	  neighbour_point[j].x   = 0.0;  neighbour_point[j].y   = 0.0;
+	  neighbour_point[j].z   = 0.0;
+	  neighbour_point[j].K   = 0.0;  neighbour_point[j].H   = 0.0;
+	  neighbour_point[j].k1  = 0.0;  neighbour_point[j].k2  = 0.0;
+	  neighbour_point[j].k1x = 0.0;  neighbour_point[j].k1y = 0.0;
+	  neighbour_point[j].k1z = 0.0;
+	  neighbour_point[j].k2x = 0.0;  neighbour_point[j].k2y = 0.0;
+	  neighbour_point[j].k2z = 0.0;  neighbour_point[j].nx  = 0.0;
+	  neighbour_point[j].ny  = 0.0;  neighbour_point[j].nz  = 0.0;
+	}
+
+      /* find the neighbouring points within the defined radius */
+      neighbour_index[0] = i;
+      int k = 1;
+
+      /* run through the layers of neighbours */
+      int num1 = 0, num2 = k;
+      for(int s=1; s<=scale; s++)
+	{
+	  for(int j=num1; j<num2; j++)
+	    {
+	      neighbours[neighbour_index[j]].Rewind();
+	      for(int m=0; m<neighbours[neighbour_index[j]].getnumnodes(); m++)
+		{
+		  int index=neighbours[neighbour_index[j]].getcurrent();
+		  int flag = 0;
+		  for (int n=0;n<k;n++)
+		    {
+		      if (index==neighbour_index[n])
+			flag=1;
+		    }
+		  if (flag==0)
+		    {
+		      neighbour_index[k]=index;
+		      k++;
+		    }
+		  neighbours[neighbour_index[j]].Next();
+		}
+	    }
+	  num1 = num2;
+	  num2 = k;
+	}
+      int num_neighbours = k;
+      if (debugmode)
+	{
+	  if (100*int(i/100)==i)
+	    fprintf(stderr,"num_neighbours[%d] = %d\t", i, num_neighbours);
+	}
+
+      /*for(j=0; j<num_neighbours; j++)
+	neighbour_point[j] = point[neighbour_index[j]];*/
+
+      double point_x[3],normal_x[3];
+
+      for (int j=0;j<num_neighbours;j++)
+	{
+
+	  points->GetPoint(neighbour_index[j],point_x);
+	  normals->GetTuple(neighbour_index[j],normal_x);
+
+	  neighbour_point[j].x =point_x[0];
+	  neighbour_point[j].y =point_x[1];
+	  neighbour_point[j].z =point_x[2];
+	  neighbour_point[j].nx=normal_x[0];
+	  neighbour_point[j].ny=normal_x[1];
+	  neighbour_point[j].nz=normal_x[2];
+	}
+
+      if(num_neighbours<5)
+	{
+	  if (debugmode)
+	    {
+	      fprintf(stderr,"point no.%d: very few neighbours: %d\n", i, num_neighbours);
+	      fprintf(stderr,"add three interpolated points\n");
+	    }
+	  /* there are at least four neighbours (including myself) */
+	  /* add three neighbours from the interpolation between   */
+	  /* me and the three existing neighbours. 		*/
+	  /* (need at least five neighbours 			*/
+	  for(int j=0; j<3; j++){
+	    neighbour_point[j+num_neighbours].x
+	      = (neighbour_point[0].x + neighbour_point[j].x) / 2.0;
+	    neighbour_point[j+num_neighbours].y
+	      = (neighbour_point[0].y + neighbour_point[j].y) / 2.0;
+	    neighbour_point[j+num_neighbours].z
+	      = (neighbour_point[0].z + neighbour_point[j].z) / 2.0;
+	  }
+	}
+      if(num_neighbours>499 && debugmode)
+	{
+	  fprintf(stderr,"point no.%d: too many neighbours: %d\n", i, num_neighbours);
+	  fprintf(stderr,"do you really need that many neighbours??\n");
+	}
+
+
+      /* the normal vector at point[i] */
+      points->GetPoint(i,point_x);
+      normals->GetTuple(i,normal_x);
+      N.x = normal_x[0];
+      N.y = normal_x[1];
+      N.z = normal_x[2];
+
+      /* the coeffs of the tangent plane at point[i] */
+      c[0] = N.x;
+      c[1] = N.y;
+      c[2] = N.z;
+      c[3] = c[0] * point_x[0] + c[1] * point_x[1] + c[2] * point_x[2];
+
+      /* pick a random point T on the tangent plane */
+      if(c[0]==1.0 || c[0]==-1.0)
+	{
+	  T.x = 0.0; T.y = 1.0;  T.z = 0.0;
+	}
+      else if(c[1]==1.0 || c[1]==-1.0)
+	{
+	  T.x = 0.0;  T.y = 0.0;  T.z = 1.0;
+	}
+      else if(c[2]==1.0 || c[2]==-1.0)
+	{
+	  T.x = 1.0;  T.y = 0.0;  T.z = 0.0;
+	}
+      else if(c[0]!=0.0)
+	{
+	  T.x = c[3] / c[0];  T.y = 0.0;  T.z = 0.0;
+	}
+      else if(c[1]!=0.0)
+	{
+	  T.x = 0.0;  T.y = c[3] / c[2];T.z = 0.0;
+	}
+      else if(c[2]!=0.0)
+	{
+	  T.x = 0.0; T.y = 0.0; T.z = c[3] / c[2];
+	}
+
+      /* the vector between point[i] and T is the first(x) tangent vector */
+      T1.x = point_x[0] - T.x;
+      T1.y = point_x[1] - T.y;
+      T1.z = point_x[2] - T.z;
+      length = T1.x * T1.x + T1.y * T1.y + T1.z * T1.z;
+      length = sqrt(length);
+      T1.x /= length;
+      T1.y /= length;
+      T1.z /= length;
+
+      /* the cross product N x T1 is the second(y) tangent vector */
+      T2.x = N.y * T1.z - T1.y * N.z;
+      T2.y = N.z * T1.x - T1.z * N.x;
+      T2.z = N.x * T1.y - T1.x * N.y;
+      /*
+	fprintf(stderr,"N:  (%4.2f, %4.2f, %4.2f)\n", N.x, N.y, N.z);
+	fprintf(stderr,"Ti: (%4.2f, %4.2f, %4.2f)\n", T1.x, T1.y, T1.z);
+	fprintf(stderr,"T2: (%4.2f, %4.2f, %4.2f)\n", T2.x, T2.y, T2.z);
+      */
+      /* transform the neighbour points, such that   */
+      /* the current point (I) becomes the origin,  */
+      /* the normal direction N becomes the z-axis, */
+      /* and the tangent directions T1/T2 becomes   */
+      /* the x/y-axes.	 			  */
+      for(int m=0; m<num_neighbours; m++)
+	{
+	  x = neighbour_point[m].x - point_x[0];
+	  y = neighbour_point[m].y - point_x[1];
+	  z = neighbour_point[m].z - point_x[2];
+	  xformed_neighbour_point[m].x = x * T1.x + y * T1.y + z * T1.z;
+	  xformed_neighbour_point[m].y = x * T2.x + y * T2.y + z * T2.z;
+	  xformed_neighbour_point[m].z = x * N.x  + y * N.y  + z * N.z;
+	}
+
+
+      /* fit the local quadric surface */
+      /* using least square method     */
+      for(int m=0; m<num_neighbours; m++)
+	data[m][0] = xformed_neighbour_point[m].z;
+
+      for(int m=0; m<num_neighbours; m++){
+	A[m][0] = xformed_neighbour_point[m].x
+	  * xformed_neighbour_point[m].x;
+	A[m][1] = xformed_neighbour_point[m].y
+	  * xformed_neighbour_point[m].y;
+	A[m][2] = xformed_neighbour_point[m].x
+	  * xformed_neighbour_point[m].y;
+	A[m][3] = xformed_neighbour_point[m].x;
+	A[m][4] = xformed_neighbour_point[m].y;
+	A[m][5] = 1.0;
+      }
+
+      double det=0;
+      int sing=0;
+
+      matrix_transpose(A, At, num_neighbours, 6);
+      matrix_product(B, At, 6, num_neighbours, A, num_neighbours, 6);
+      if (mode==0)
+	{
+	  matrix_inverse(B, B_1, 6);
+	}
+      else
+	{
+	  ludcmp0(B,6,indx,&det,sing);
+	  //fprintf(stderr,"Det =%f, sing=%d ",det,sing);
+	}
+
+      matrix_product(C, At, 6, num_neighbours, data, num_neighbours, 1);
+
+      if (mode==0)
+	{
+	  matrix_product(C2, B_1, 6, 6, C, 6, 1);
+	  for (int ii=0;ii<6;ii++)
+	    coeff[ii]=C2[ii][0];
+	}
+      else
+	{
+	  for (int ii=0;ii<6;ii++)
+	    coeff[ii]=C[ii][0];
+	  lubksb0(B,6,indx,coeff);
+	}
+      /*
+	// compute the residual of the fit
+	double residual = 0.0;
+	for(m=0; m<num_neighbours; m++)
+	residual += fabs(data[m]
+	- coeff[0] * A[m][0]
+	- coeff[1] * A[m][1]
+	- coeff[2] * A[m][2]
+	- coeff[3] * A[m][3]
+	- coeff[4] * A[m][4]
+	- coeff[5] * A[m][5]);
+      */
+      /* compute the curvatures */
+      fx  = coeff[3];
+      fy  = coeff[4];
+      fxx = coeff[0] * 2.0;
+      fxy = coeff[2];
+      fyy = coeff[1] * 2.0;
+
+      g[0][0] = 1.0 + fx*fx;
+      g[0][1] = fx * fy;
+      g[1][0] = fx * fy;
+      g[1][1] = 1.0 + fy*fy;
+
+
+
+      matrix_inverse(g, g_1, 2);
+
+      b[0][0] = fxx / ((1.0+fx*fx+fy*fy) * (1.0+fx*fx+fy*fy));
+      b[0][1] = fxy / ((1.0+fx*fx+fy*fy) * (1.0+fx*fx+fy*fy));
+      b[1][0] = fxy / ((1.0+fx*fx+fy*fy) * (1.0+fx*fx+fy*fy));
+      b[1][1] = fyy / ((1.0+fx*fx+fy*fy) * (1.0+fx*fx+fy*fy));
+
+      matrix_product(beta, g_1, 2, 2, b, 2, 2);
+
+      //point[i].K = beta[0][0] * beta[1][1] - beta[0][1] * beta[1][0];
+      //point[i].H = (beta[0][0] + beta[1][1]) / 2.0;
+
+
+      for(int m=1; m<3; m++)
+	for(int n=1; n<3; n++)
+	  a1_repl[m-1][n-1] = beta[m-1][n-1];
+
+
+      vtkMath::JacobiN(a1_repl,2,d1_repl,v1_repl);
+
+      //      get_eigenvalues_vectors(a1, 2, d1, v1, &nrot);
+      //      sort_eigenvalues_vectors(d1, v1, 2);
+
+      K1 = d1_repl[0];
+      K2 = d1_repl[1];
+
+      if (debugmode)
+	{
+	  if (100*int(i/100)==i)
+	    fprintf(stderr," k1=%6.3f, k2=%6.3f\n",K1,K2);
+	}
+
+      /* the prinipal curvatures and directions in local space */
+
+      curvature->SetComponent(i,0,K1);
+      curvature->SetComponent(i,1,K2);
+
+      /* the normal vector in global space */
+      normals->SetComponent(i,0, N.x);
+      normals->SetComponent(i,1, N.y);
+      normals->SetComponent(i,2, N.z);
+    }
+
+  free_dmatrix(A,     0,500-1,0,5);
+  free_dmatrix(At,    0,5,0,500-1);
+  free_dmatrix(B,     0,5,0,5);
+  free_dmatrix(B_1,   0,5,0,5);
+  free_ivector(indx  ,0,5);
+  free_dmatrix(C,     0,5,0,5);
+  free_dmatrix(C2,    0,5,0,5);
+  free_dvector(coeff, 0,5);
+  free_dmatrix(data,  0,500-1,0,0);
+  free_dmatrix(g,     0, 1, 0, 1);
+  free_dmatrix(g_1,   0, 1, 0, 1);
+  free_dmatrix(b,     0, 1, 0, 1);
+  free_dmatrix(beta,  0, 1, 0, 1);
+  //  free_dmatrix(a1,    1, 2, 1, 2);
+  //  free_dvector(d1,    1, 2);
+  //  free_dmatrix(v1,    1, 2, 1, 2);
+
+
+
+  delete [] a1_repl[1];
+  delete [] a1_repl[0];
+  delete [] a1_repl;
+
+
+  delete [] v1_repl[1];
+  delete [] v1_repl[0];
+  delete [] v1_repl;
+
+  delete [] d1_repl;
+
+
+
+
+  polydata->GetPointData()->SetNormals(normals);
+  polydata->GetPointData()->SetScalars(curvature);
+
+  curvature->Delete();
+  normals->Delete();
+  return 1;
+
+
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxMath.h b/bioimagesuite30_src/Common/vtkpxMath.h
new file mode 100644
index 0000000..56f46d7
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxMath.h
@@ -0,0 +1,146 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//  This file depends heavily on NR code in vtkpxNonLinearFit.cpp
+//
+//---------------------------------------------------------------------------------------------------------
+
+#ifndef __vtkpxMath_h
+#define __vtkpxMath_h
+
+#include "vtkObject.h"
+
+
+
+//BTX
+class vtkFloatArray;
+class vtkPolyData;
+#include "pxgeometrystruct.h"
+//ETX
+
+class vtkpxMath : public vtkObject
+{
+public:
+  static vtkpxMath *New();
+  vtkTypeMacro(vtkpxMath,vtkObject);
+  
+  // ---------------------------------------------------------------------
+  // This Code is Primarily Derived From Numerical Recipes
+  // ---------------------------------------------------------------------
+
+  // Description:
+  // Conversion Routines 
+  static void EuclideanToPolar(float X,float Y,float& R,float& Theta);
+  static void PolarToEuclidean(float R,float Theta,float& X,float& Y);
+
+  // Description:
+  // Evaluate Gaussian Sigma
+  static float Gaussian(float x,float m,float sigma2);
+  static float Rayleigh(float x,float beta2);
+  
+  // Description:
+  // Normal Random Generator
+  static float GaussianRandom();
+
+
+  // Description:
+  // Ttest to Pvalue
+  static float TtestToPvalue(float t,int df);
+  static float TtestToPvalue_itk(float t,int df);
+  static float PvalueToTvalue(float p,int df);
+  static float ZscoreToPvalue(float z);
+  static float PvalueToZscore(float z);
+  
+  // Description:
+  // Some Static Utility Functions to compute distances around a circle (radians)
+  static float FindClosestAngleP1(float p1,float p2);
+  static float FindMinAngleDistance(float p1,float p2);
+
+  // Description:
+  // Compute Differences between ph and distance step and store in temp 
+  // (input np points output np-step differences)
+  static int   ComputeAngleDistancePairs(float* ph,float* temp,int step,int np);
+
+
+
+  // Description:
+  // Lower Level Numerical Recipes Helper Routines -- do not call directly 
+  static float NRSelect(unsigned long k, unsigned long n, float* arr);
+  static float NRrofunc(float b,float* xt,float* yt,float& aa,float& abdevt,int ndatat,float* arr);
+  
+  // Description:
+  // Functions To Compute Order Statistics 
+  static float SelectKthLargest(unsigned long k0offset, unsigned long n, float* arr0offset);
+  static float GetMedian(unsigned long n, float* arr);
+
+
+  // Description:
+  // Fit Line y=ax+b to x,y pairs with temp storage space (output a,b and fit error abdev)
+  // Medfit uses absolute deviation, meanfit uses least squares fitting 
+
+
+  static void  Medfit(float* x, float* y, int ndata, float& a, float& b, float& abdev);
+  static void  Meanfit(float* x, float* y, int ndata, float& a, float& b, float& abdev);
+  static void WeightedMeanfit(float *x, float *y, int ndata, float *sig, int mwt, float &a,
+			      float &b, float &siga, float &sigb, float &chi2, float &q);
+
+
+  // Description:
+  // Use this version of medfit to pre-allocate temporary storage (for many succesive invocations)
+  static void  Medfit(float* x, float* y, int ndata, float& a, float& b, float& abdev,float* temp);
+
+
+  // Description:
+  // Sorting Code to either sort an array (Heapsort) or to index an array (IndexArray)
+  static void Heapsort(unsigned long n, float* ra0offset);
+
+
+  // Description:
+  // Short Code
+  static void Meanfit_Short(short* x, short* y, int ndata, short& a, short& b, short& abdev);
+  static void Heapsort_Short(unsigned long n, short* ra0offset);
+
+
+
+  // Description:
+  //BTX
+  static int CalculateCurvatures(vtkPolyData* polydata,int scale,PXIntegerList* neighbours);
+
+  //ETX
+
+  
+
+
+
+protected:
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkpxMatrix.cpp b/bioimagesuite30_src/Common/vtkpxMatrix.cpp
new file mode 100644
index 0000000..4a87986
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxMatrix.cpp
@@ -0,0 +1,3029 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+#include "vtkpxMatrix.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxUtil.h"
+#include "bio_f2c.h"
+#include "clapack.h"
+#include "pxutil.h"
+#include "vtkpxMath.h"
+#include "vnl/vnl_vector.h"
+#include "vnl/vnl_vector_fixed.h"
+#include "vnl/vnl_matrix.h"
+#include "vnl/vnl_matrix_fixed.h"
+#include "vnl/vnl_matlab_filewrite.h"
+#include <vnl/vnl_matlab_read.h>
+#include <vnl/vnl_matlab_write.h>
+#include <vnl/vnl_matlab_print.h>
+#include <vcl_cstring.h>
+#include <vcl_fstream.h>
+#include "bis_znzlib.h"
+#include <pxutil.h>
+// -----------------------------------------------------------------------------------
+
+vtkpxMatrix* vtkpxMatrix::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxMatrix");
+  if(ret)
+      {
+	return (vtkpxMatrix*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxMatrix;
+}
+
+// -----------------------------------------------------------------------------------
+vtkpxMatrix::vtkpxMatrix()
+{
+  this->Size[0]=0;
+  this->Size[1]=0;
+  this->TrueSize=0;
+  this->TotalSize=0;
+  this->Matrix=NULL;
+}
+// -----------------------------------------------------------------------------------
+vtkpxMatrix::~vtkpxMatrix()
+{
+  if (this->Matrix!=NULL)
+    delete [] this->Matrix;
+}
+// -----------------------------------------------------------------------------------
+// Some in-line stuff
+
+void vtkpxMatrix::Zeros(int rows,int cols)
+{
+  Allocate(rows,cols);
+  Fill(0.0);
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Ones(int rows,int cols)
+{
+  Allocate(rows,cols); Fill(1.0);
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Eye(int rowcol)
+{
+  Allocate(rowcol,rowcol) ; Identity();
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Allocate(int rows,int columns)
+{
+  if (rows==0 || columns==0)
+    return;
+
+  if (this->Matrix!=NULL)
+    {
+      if (rows*columns<=this->TrueSize)
+	{
+	  this->Size[0]=rows;
+	  this->Size[1]=columns;
+	  this->TotalSize=this->Size[0]*this->Size[1];
+	  return;
+	}
+
+      delete [] this->Matrix;
+    }
+
+  this->Size[0]=Irange(rows,1,100000000);
+  this->Size[1]=Irange(columns,1,100000000);
+  this->TotalSize=this->Size[0]*this->Size[1];
+  this->TrueSize=this->TotalSize;
+  this->Matrix=new float[this->TrueSize];
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Squeeze()
+{
+  if (this->Matrix==NULL)
+    return;
+
+  if (this->TotalSize==this->TrueSize)
+    return;
+
+  this->TrueSize=this->Size[0]*this->Size[1];
+  float* tmp=this->Matrix;
+
+  this->Matrix=new float[this->TrueSize];
+  for (int i=0;i<this->TrueSize;i++)
+    this->Matrix[i]=tmp[i];
+
+  delete [] tmp;
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Identity()
+{
+  if (this->Matrix==NULL || (this->Size[0]!=this->Size[1]))
+    return;
+
+  this->Zero();
+  for (int i=0;i<this->Size[0];i++)
+    this->SetDirectElement(i,i,1.0);
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Zero()
+{
+  Fill(0);
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Fill(float v)
+{
+  if (this->Matrix==NULL)
+    return;
+
+  for (int i=0;i<this->TotalSize;i++)
+    this->Matrix[i]=v;
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Transpose()
+{
+  if (this->Matrix==NULL)  return;
+
+  // Only need to do transposing if matrix is not a row or col vector,
+  if (this->Size[0]==1 || this->Size[1]==1)
+    {
+      int t=this->Size[0];
+      this->Size[0]=this->Size[1];
+      this->Size[1]=t;
+      return;
+    }
+
+  // Square Matrix
+  if (this->Size[1]==this->Size[0])
+    {
+      for (int i=0;i<this->Size[0];i++)
+	for (int j=i+1;j<this->Size[1];j++)
+	  {
+	    float a=this->GetDirectElement(i,j);
+	    this->SetDirectElement(i,j,this->GetDirectElement(j,i));
+	    this->SetDirectElement(j,i,a);
+	  }
+      return;
+    }
+
+  // Copy Matrix out first
+  vtkpxMatrix* temp=vtkpxMatrix::New();
+  temp->Copy(this);
+
+  int r=Size[0];
+  int c=Size[1];
+  this->Allocate(c,r);
+
+  for (int i=0;i<this->Size[0];i++)
+    for (int j=0;j<this->Size[1];j++)
+      this->SetDirectElement(i,j,temp->GetDirectElement(j,i));
+
+  temp->Delete();
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Print(const char* message)
+{
+  fprintf(stdout,"\n %s =\n",message);
+  this->InternalPrint();
+  fprintf(stdout,"\n");
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::InternalPrint()
+{
+  if (this->Matrix==NULL)  return;
+
+  for(int i = 0; i < this->Size[0]; i++)
+    {
+      fprintf(stdout,"[ ");
+      for(int j = 0; j < this->Size[1]; j++)
+	fprintf(stdout,"%7.3f ", this->GetDirectElement(i,j));
+      fprintf(stdout,"]\n");
+    }
+
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::PrintRange(const char* message,int r1,int r2,int c1,int c2)
+{
+  fprintf(stdout,"\n %s (%d:%d,%d:%d) =\n",message,r1,r2,c1,c2);
+  this->PrintRange(r1,r2,c1,c2);
+  fprintf(stdout,"\n");
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::PrintRange(int r1,int r2,int c1,int c2)
+{
+  if (this->Matrix==NULL)  return;
+
+
+  if (r1==-1)
+    r1=0;
+  else
+    r1=Irange(r1,0,this->Size[0]-1);
+
+  if (r2==-1)
+    r2=this->Size[0]-1;
+  else
+    r2=Irange(r2,r1,this->Size[0]-1);
+
+  if (c1==-1)
+    c1=0;
+  else
+    c1=Irange(c1,0,this->Size[1]-1);
+
+  if (c2==-1)
+    c2=this->Size[1]-1;
+  else
+    c2=Irange(c2,c1,this->Size[1]-1);
+
+
+
+  for(int i = r1; i <= r2; i++)
+    {
+      fprintf(stdout,"[ ");
+      for(int j = c1; j <= c2; j++)
+	fprintf(stdout,"%7.3f ", this->GetDirectElement(i,j));
+      fprintf(stdout,"]\n");
+    }
+
+}
+// -----------------------------------------------------------------------------------
+int vtkpxMatrix::Load(const char* fname)
+{
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  int ok=Load(fin);
+  gzclose(fin);
+  return ok;
+}
+
+
+void vtkpxMatrix::ReplaceWithSpace(char* line,const char* t)
+{
+  if (line==NULL)
+    return;
+
+  if (strlen(line)<1)
+    return;
+
+  //fprintf(stderr,"Starting line=***%s***\n",line);
+  
+  int done=0;
+  std::string newpath=line;
+
+
+
+  if (newpath.length()> strlen(t)+1) 
+    {
+      while ( done==0 && newpath.length() > (strlen(t)+1 ))
+	{
+	  int f=newpath.rfind(t);
+	  if (f==std::string::npos)
+	    {
+	      done=1;
+	    }
+	  else if (f+strlen(t) >= newpath.length())
+	    {
+	      done =1;
+	    }
+	  else
+	    {
+	      newpath.replace(f,strlen(t)," ");
+	    }
+	}
+      strcpy(line,newpath.c_str());
+    }
+}
+
+
+int vtkpxMatrix::Load(gzFile fin)
+{
+  char line[100];
+
+  gzgets(fin,line,100);   gzgets(fin,line,100);   gzgets(fin,line,100);
+
+  if (gzfindstringinstring(line,"type: matrix")==0)
+    {
+      gzclose(fin);
+      return 0;
+    }
+
+  int np1,np2;
+  gzgets(fin,line,100);  sscanf(line,"# rows: %d",&np1);
+  gzgets(fin,line,100);  sscanf(line,"# columns: %d",&np2);
+
+  if (np1<0 || np1>1000000 || np2<0 || np2>1000000)
+    {
+      gzclose(fin);
+      return 0;
+    }
+  this->Allocate(np1,np2);
+  char* newline=new char[np2*15];
+  float a=0.0;
+
+  for (int i=0;i<np1;i++)
+    {
+      gzgets(fin,newline,np2*15);
+      vtkpxMatrix::ReplaceWithSpace(newline,"  ");
+      vtkpxMatrix::ReplaceWithSpace(newline,"\t");
+      vtkpxMatrix::ReplaceWithSpace(newline,",");
+      char* parseline=strtok(newline," ");
+      for (int j=0;j<np2;j++)
+	{
+	  sscanf(parseline,"%f",&a);
+	  parseline=strtok(NULL," ");
+	  this->SetDirectElement(i,j,a);
+	}
+    }
+
+  delete [] newline;
+
+
+  return 1;
+
+}
+// -----------------------------------------------------------------------------------
+int vtkpxMatrix::Save(const char* fname)
+{
+  char* matname=eatsuffix(fname);
+  char* matname2=anaeatpath(matname);
+  return this->Save(fname,matname2);
+  delete []  matname;
+
+}
+// -----------------------------------------------------------------------------------
+int vtkpxMatrix::Save(const char* fname,const char* varname,int compression)
+{
+  if (compression==0)
+    {
+      FILE* fout=fopen(fname,"w");
+      if (fout==NULL)
+	return 0;
+      int ok=Save(fout,varname);
+      fclose(fout);
+      return ok;
+    }
+
+  gzFile fout=gzsuffixopen(fname,"wb",compression);
+  if (!fout)
+    return 0;
+  int ok=Save(fout,varname);
+  gzclose(fout);
+  return ok;
+}
+// -----------------------------------------------------------------------------------
+int vtkpxMatrix::Save(gzFile fout,const char* varname)
+{
+  gzprintf(fout,"#vtkpxMatrix File\n");
+  gzprintf(fout,"# name: %s\n# type: matrix\n",varname);
+  gzprintf(fout,"# rows: %d\n# columns: %d\n",this->Size[0],this->Size[1]);
+
+  for(int i = 0; i < this->Size[0]; i++)
+    {
+      for(int j = 0; j < this->Size[1]; j++)
+	gzprintf(fout,"%f ", this->GetDirectElement(i,j));
+      gzprintf(fout,"\n");
+    }
+  return 1;
+}
+// -----------------------------------------------------------------------------------
+int vtkpxMatrix::Save(FILE*  fout,const char* varname)
+{
+  fprintf(fout,"#vtkpxMatrix File\n");
+  fprintf(fout,"# name: %s\n# type: matrix\n",varname);
+  fprintf(fout,"# rows: %d\n# columns: %d\n",this->Size[0],this->Size[1]);
+
+  for(int i = 0; i < this->Size[0]; i++)
+    {
+      for(int j = 0; j < this->Size[1]; j++)
+	fprintf(fout,"%f ", this->GetDirectElement(i,j));
+      fprintf(fout,"\n");
+    }
+  return 1;
+}
+
+int vtkpxMatrix::ExportAFNI(char*  fname,const char* formatstring)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout==NULL)
+    return 0;
+
+  for(int i = 0; i < this->Size[0]; i++)
+    {
+      for(int j = 0; j < this->Size[1]; j++)
+	fprintf(fout,formatstring, this->GetDirectElement(i,j));
+      fprintf(fout,"\n");
+    }
+  fclose(fout);
+  return 1;
+}
+
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Print(const char* message,const char* format)
+{
+  if (this->Matrix==NULL || message==NULL || format==NULL)  return;
+
+  fprintf(stdout,"\n %s =\n",message);
+
+  for(int i = 0; i < this->Size[0]; i++)
+    {
+      fprintf(stdout,"[ ");
+      for(int j = 0; j < this->Size[1]; j++)
+	fprintf(stdout,format, this->GetDirectElement(i,j));
+      fprintf(stdout,"]\n");
+    }
+  fprintf(stdout,"\n");
+
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Copy(vtkpxMatrix* oldmat)
+{
+  int oldsize[2];
+  oldmat->GetSize(oldsize);
+  this->Allocate(oldsize[0],oldsize[1]);
+
+  float* o_pointer=oldmat->GetMatrixPointer();
+
+  for (int i=0;i<this->TotalSize;i++)
+    Matrix[i]=o_pointer[i];
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Copy(vtkpxMatrix* oldmat,int x1,int x2,int y1,int y2)
+{
+  int oldsize[2];
+  oldmat->GetSize(oldsize);
+
+  if (x1==-1)     x1=0;
+  if (x2==-1)     x2=oldsize[0]-1;
+  if (y1==-1)     y1=0;
+  if (y2==-1)     y2=oldsize[1]-1;
+
+  x1=Irange(x1,0,oldsize[0]-1);
+  x2=Irange(x2,0,oldsize[0]-1);
+  y1=Irange(y1,0,oldsize[1]-1);
+  y2=Irange(y2,0,oldsize[1]-1);
+
+  this->Allocate(x2-x1+1,y2-y1+1);
+
+  int sz[2]; this->GetSize(sz);
+
+  /*  fprintf(stdout,"Copying Matrix -- New matrix Size = %d x %d vs old %d x %d\n",
+      sz[0],sz[1],oldsize[0],oldsize[1]);*/
+
+  for (int i=0;i<this->Size[0];i++)
+    for (int j=0;j<this->Size[1];j++)
+      this->SetDirectElement(i,j,oldmat->GetDirectElement(i+x1,j+y1));
+
+}
+
+int vtkpxMatrix::CopyInto(vtkpxMatrix* oldmat,int x1,int x2,int y1,int y2,int newx,int newy)
+{
+ int oldsize[2];
+  oldmat->GetSize(oldsize);
+
+  if (x1==-1)     x1=0;
+  if (x2==-1)     x2=oldsize[0]-1;
+  if (y1==-1)     y1=0;
+  if (y2==-1)     y2=oldsize[1]-1;
+
+  x1=Irange(x1,0,oldsize[0]-1);
+  x2=Irange(x2,0,oldsize[0]-1);
+  y1=Irange(y1,0,oldsize[1]-1);
+  y2=Irange(y2,0,oldsize[1]-1);
+
+
+  int sz[2]; this->GetSize(sz);
+  if ( (x2-x1+newx) > sz[0] || (y2-y1+newy) > sz[1])
+    {
+      fprintf(stderr,"Error CopyIntoMatrix ... x1:x2=%d:%d newx=%d y1:y2=%d:%d newy=%d sz=%d,%d oldsz=%d,%d\n",
+	      x1,x2,newx,y1,y2,newy,sz[0],sz[1],oldsize[0],oldsize[1]);
+      return 0;
+    }
+  else
+      fprintf(stderr,"OK CopyIntoMatrix ... x1:x2=%d:%d newx=%d y1:y2=%d:%d newy=%d sz=%d,%d, oldsz=%d,%d\n",
+	      x1,x2,newx,y1,y2,newy,sz[0],sz[1],oldsize[0],oldsize[1]);
+
+  //  this->Allocate(x2-x1+1,y2-y1+1);
+
+  /*  fprintf(stdout,"Copying Matrix -- New matrix Size = %d x %d vs old %d x %d\n",
+      sz[0],sz[1],oldsize[0],oldsize[1]);*/
+
+  for (int i=x1;i<=x2;i++)
+    for (int j=y1;j<=y2;j++)
+      this->SetDirectElement(newx+i-x1,
+			     newy+j-y1,
+			     oldmat->GetDirectElement(i,j));
+      //    this->SetDirectElement(i,j,oldmat->GetDirectElement(i+x1,j+y1));
+  return 1;
+
+}
+
+
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::SetMatrix(double** mat,int x,int y)
+{
+  Copy(mat,x,y) ;
+}
+
+void vtkpxMatrix::Copy(double** mat,int x,int y)
+{
+  Copy(mat,0,x-1,0,y-1);
+}
+
+void vtkpxMatrix::Copy(double** mat,int x1,int x2,int y1,int y2)
+{
+  this->Allocate(x2-x1+1,y2-y1+1);
+  for (int i=0;i<this->Size[0];i++)
+    for (int j=0;j<this->Size[1];j++)
+      this->SetDirectElement(i,j,mat[i+x1][j+y1]);
+}
+// -----------------------------------------------------------------------------------
+int  vtkpxMatrix::GetRow(int row,int maxval,float* values)
+{
+  if (Matrix==NULL)
+    return 0;
+  row=Irange(row,0,this->Size[0]-1);
+
+  int minn=Imin(this->Size[1],maxval);
+  for (int i=0;i<minn;i++)
+    values[i]=this->GetDirectElement(row,i);
+  return minn;
+}
+
+int  vtkpxMatrix::GetColumn(int column,int maxval,float* values)
+{
+  if (Matrix==NULL)
+    return 0;
+  column=Irange(column,0,this->Size[1]-1);
+
+  int minn=Imin(this->Size[0],maxval);
+  for (int i=0;i<minn;i++)
+    values[i]=this->GetDirectElement(i,column);
+  return minn;
+}
+// -----------------------------------------------------------------------------------
+int  vtkpxMatrix::SetRow(int row,int maxval,float* values)
+{
+  if (Matrix==NULL)
+    return 0;
+  row=Irange(row,0,this->Size[0]-1);
+
+  int minn=Imin(this->Size[1],maxval);
+  for (int i=0;i<minn;i++)
+    this->SetDirectElement(row,i,values[i]);
+  return minn;
+}
+
+int  vtkpxMatrix::SetColumn(int column,int maxval,float* values)
+{
+  if (Matrix==NULL)
+    return 0;
+  column=Irange(column,0,this->Size[1]-1);
+
+  int minn=Imin(this->Size[0],maxval);
+  for (int i=0;i<minn;i++)
+    this->SetDirectElement(i,column,values[i]);
+  return minn;
+}
+// -----------------------------------------------------------------------------------
+int  vtkpxMatrix::GetRow(int row,int maxval,double* values)
+{
+  if (Matrix==NULL)
+    return 0;
+  row=Irange(row,0,this->Size[0]-1);
+
+  int minn=Imin(this->Size[1],maxval);
+  for (int i=0;i<minn;i++)
+    values[i]=this->GetDirectElement(row,i);
+  return minn;
+}
+
+int  vtkpxMatrix::GetColumn(int column,int maxval,double* values)
+{
+  if (Matrix==NULL)
+    return 0;
+  column=Irange(column,0,this->Size[1]-1);
+
+  int minn=Imin(this->Size[0],maxval);
+  for (int i=0;i<minn;i++)
+    values[i]=this->GetDirectElement(i,column);
+  return minn;
+}
+// -----------------------------------------------------------------------------------
+int  vtkpxMatrix::SetRow(int row,int maxval,double* values)
+{
+  if (Matrix==NULL)
+    return 0;
+  row=Irange(row,0,this->Size[0]-1);
+
+  int minn=Imin(this->Size[1],maxval);
+  for (int i=0;i<minn;i++)
+    this->SetDirectElement(row,i,values[i]);
+  return minn;
+}
+
+int  vtkpxMatrix::SetColumn(int column,int maxval,double* values)
+{
+  if (Matrix==NULL)
+    return 0;
+  column=Irange(column,0,this->Size[1]-1);
+
+  int minn=Imin(this->Size[0],maxval);
+  for (int i=0;i<minn;i++)
+    this->SetDirectElement(i,column,values[i]);
+  return minn;
+}
+// -----------------------------------------------------------------------------------
+double**  vtkpxMatrix::GetNewMatrixPointer()
+{
+  if (Matrix==NULL)
+    return NULL;
+
+  double** a=vtkpxMatrix::NewMatrix(this->Size[0],this->Size[1]);
+  for (int i=0;i<this->Size[0];i++)
+    for (int j=0;j<this->Size[1];j++)
+      a[i][j]=this->GetDirectElement(i,j);
+  return a;
+}
+//  =====================================================================
+//  Real Matrix Operations !!
+//  =====================================================================
+void vtkpxMatrix::Scale(float scale)
+{
+  if (Matrix==NULL)
+    return;
+
+
+  for (int i=0;i<this->TotalSize;i++)
+    Matrix[i]*=scale;
+}
+
+void vtkpxMatrix::ScaleAdd(float multi,float offset)
+{
+  if (Matrix==NULL)
+    return;
+
+
+  for (int i=0;i<this->TotalSize;i++)
+    Matrix[i]=Matrix[i]*multi+offset;
+}
+
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Add(vtkpxMatrix* a,vtkpxMatrix* b,vtkpxMatrix* c)
+{
+  int s1[2],s2[2];
+  a->GetSize(s1);
+  b->GetSize(s2);
+
+  if (s1[1]!=s2[1] || s1[0]!=s2[0])
+    {
+      fprintf(stderr,"Cannot add matrices bad size a=%dx%d, b=%dx%d!\n",s1[0],s1[1],s2[0],s2[1]);
+      return;
+    }
+
+  c->Allocate(s1[0],s1[1]);
+
+  float* A=a->GetMatrixPointer();
+  float* B=b->GetMatrixPointer();
+  float* C=c->GetMatrixPointer();
+
+  int sz=c->GetTotalSize();
+
+  for(int i=0;i<sz;i++)
+    {
+      *C=*A+*B;
+      ++C;
+      ++B;
+      ++A;
+    }
+  //    c_pointer[i]=a_pointer[i]+b_pointer[i];
+
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Add(float wa,vtkpxMatrix* a,float wb,vtkpxMatrix* b,vtkpxMatrix* c)
+{
+
+  int s1[2],s2[2];
+  a->GetSize(s1);
+  b->GetSize(s2);
+
+  if (s1[1]!=s2[1] || s1[0]!=s2[0])
+    {
+      fprintf(stderr,"Cannot add matrices bad size %f*a=%dx%d, %f*b=%dx%d!\n",wa,s1[0],s1[1],wb,s2[0],s2[1]);
+      return;
+    }
+
+  c->Allocate(s1[0],s1[1]);
+
+  float* A=a->GetMatrixPointer();
+  float* B=b->GetMatrixPointer();
+  float* C=c->GetMatrixPointer();
+
+  int sz=c->GetTotalSize();
+
+  for(int i=0;i<sz;i++)
+    {
+      *C = wa*(*A) + wb*(*B);
+      ++C;
+      ++A;
+      ++B;
+    }
+
+  //    c_pointer[i]=wa*a_pointer[i]+wb*b_pointer[i];
+
+}
+
+int vtkpxMatrix::IsEqual(vtkpxMatrix* a, vtkpxMatrix* b,double tolerance)
+{
+
+  int ret;
+  int s1[2],s2[2];
+
+  ret = 0;
+  a->GetSize(s1);
+  b->GetSize(s2);
+
+  if (s1[1]!=s2[1] || s1[0]!=s2[0])
+    {
+      fprintf(stderr,"Size of matrices are different a=%dx%d, b=%dx%d!\n",s1[0],s1[1],s2[0],s2[1]);
+      ret = 1;
+      return ret;
+    }
+
+  float* A=a->GetMatrixPointer();
+  float* B=b->GetMatrixPointer();
+
+  int sz=a->GetTotalSize();
+
+  for(int i=0;i<sz;i++)
+    {
+      if(((*A) - (*B) > tolerance ) || ((*A) - (*B) < -tolerance ))
+	{
+	  ret = 1;
+	  return ret;
+	}
+      ++A;
+      ++B;
+    }
+
+  return ret;
+}
+
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::Multiply(vtkpxMatrix* a,vtkpxMatrix* b,vtkpxMatrix* c)
+{
+  int s1[2],s2[2],s3[2];
+  a->GetSize(s1);
+  b->GetSize(s2);
+
+  if (s1[1]!=s2[0])
+    {
+      fprintf(stderr,"Cannot multiply matrices bad size! a=%dx%d, b=%dx%d\n",s1[0],s1[1],s2[0],s2[1]);
+      return;
+    }
+
+  c->Allocate(s1[0],s2[1]);
+  c->GetSize(s3);
+
+  float* a_pointer=a->GetMatrixPointer();
+  float* b_pointer=b->GetMatrixPointer();
+  float* c_pointer=c->GetMatrixPointer();
+
+  float* C=&c_pointer[0];
+
+  for(int col = 0; col < s3[1]; col++)
+    {
+      for(int row = 0; row < s3[0]; row++)
+	{
+	  float* B=&b_pointer[col*s2[0]];
+	  float* A=&a_pointer[row];
+	  *C=0;
+	  for(int i = 0; i < s1[1]; i++)
+	    {
+	      (*C)+=(*A)*(*B);
+	      ++B;
+	      A+=s1[0];
+	    }
+	  ++C;
+	}
+    }
+}
+// -----------------------------------------------------------------------------------
+void vtkpxMatrix::MultiplyTripleProduct(vtkpxMatrix* a,vtkpxMatrix* b,vtkpxMatrix* c)
+{
+  int s1[2],s2[2],s3[2];
+  a->GetSize(s1);
+  b->GetSize(s2);
+
+  if (s1[0]!=s2[0] || s2[0]!=s2[1])
+    {
+      fprintf(stderr,"Cannot triple-multiply matrices bad sizes a=%dx%d, b=%dx%d!\n",s1[0],s1[1],s2[0],s2[1]);
+      return;
+    }
+
+  int n=s2[0];
+
+  c->Allocate(s1[1],s1[1]);
+  c->GetSize(s3);
+
+
+  float* a_pointer=a->GetMatrixPointer();
+  float* b_pointer=b->GetMatrixPointer();
+  float* c_pointer=c->GetMatrixPointer();
+
+  float* C =&c_pointer[0];
+
+  for(int j = 0; j < s3[1]; j++)
+    {
+      for(int i = 0; i < s3[0]; i++)
+	{
+	  (*C)=0;
+	  /*for(int k = 0; k < n ; k++)
+	    for (int l=0; l <  n ; l++ )
+	    (*C) = (*C) + a_pointer[i*s1[0]+k]*b_pointer[l*s2[0]+k]*a_pointer[j*s1[0]+l];*/
+	  float *AT=&a_pointer[i*s1[0]];
+	  for(int k = 0; k < n ; k++)
+	    {
+	      float* B =&b_pointer[k];
+	      float* A =&a_pointer[j*s1[0]];
+	      for (int l=0; l <  n ; l++ )
+		{
+		  (*C) = (*C) + (*AT)*(*B)*(*A);//a_pointer[j*s1[0]+l];
+		  B+=s2[0];
+		  ++A;
+		}
+	      ++AT;
+	    }
+
+	  ++C;
+	}
+    }
+}
+
+// -----------------------------------------------------------------------------------
+void  vtkpxMatrix::Multiply3(vtkpxMatrix* a,vtkpxMatrix* b,vtkpxMatrix* c,vtkpxMatrix* result)
+{
+  int s1[2],s2[2],s3[2],s4[2];
+  a->GetSize(s1);
+  b->GetSize(s2);
+  c->GetSize(s3);
+
+  if (s1[1]!=s2[0] || s2[1]!=s3[0])
+    {
+      fprintf(stderr,"Cannot multiply3 matrices bad sizes a=%dx%d, b=%dx%d c=%dx%d!\n",s1[0],s1[1],s2[0],s2[1],s3[0],s3[1]);
+      return;
+    }
+
+  result->Allocate(s1[0],s3[1]);
+  result->GetSize(s4);
+
+  float* a_pointer=a->GetMatrixPointer();
+  float* b_pointer=b->GetMatrixPointer();
+  float* c_pointer=c->GetMatrixPointer();
+
+  float* R=result->GetMatrixPointer();
+
+  for(int j = 0; j < s4[1]; j++)
+    for(int i = 0; i < s4[0]; i++)
+      {
+	*R=0.0;
+	float* A=&a_pointer[i];
+	for(int k = 0; k < s1[1] ; k++)
+	  {
+	    float *B=&b_pointer[k];
+	    float *C=&c_pointer[j*s3[0]];
+	    for (int l=0; l <  s2[1] ; l++ )
+	      {
+		(*R)+=(*A)*(*B)*(*C);//c_pointer[j*s3[0]+l];
+		B+=s2[0];
+		++C;
+	      }
+	    A+=s1[0];
+	  }
+	R++;
+      }
+}
+// -----------------------------------------------------------------------------------
+float vtkpxMatrix::Max()
+{
+  if (Matrix==NULL)
+    return 0.0;
+  float max=this->Matrix[0];
+  for (int i=0;i<this->TotalSize;i++)
+    {
+      float v=Matrix[i];
+      if (max<v)
+	max=v;
+    }
+  return max;
+}
+// -----------------------------------------------------------------------------------
+float vtkpxMatrix::MaxColumn(int col)
+{
+  if (Matrix==NULL)
+    return 0.0;
+
+  if (col<0 || col>=Size[1])
+    return 0.0;
+
+  float max=GetDirectElement(0,col);
+  for (int i=1;i<this->Size[0];i++)
+    {
+      float v=this->GetDirectElement(i,col);
+      if (max<v)
+	max=v;
+    }
+  return max;
+}
+// -----------------------------------------------------------------------------------
+float vtkpxMatrix::MaxRow(int row)
+{
+  if (Matrix==NULL)
+    return 0.0;
+
+  if (row<0 || row>=Size[0])
+    return 0.0;
+
+  float max=GetDirectElement(row,0);
+  for (int i=1;i<this->Size[1];i++)
+    {
+      float v=this->GetDirectElement(row,i);
+      if (max<v)
+	max=v;
+    }
+  return max;
+}
+
+// -----------------------------------------------------------------------------------
+float vtkpxMatrix::Sum()
+{
+  if (Matrix==NULL)
+    return 0.0;
+
+  float sum=0.0;
+  for (int i=0;i<this->TotalSize;i++)
+    sum+=this->Matrix[i];
+  return sum;
+}
+// -----------------------------------------------------------------------------------
+float vtkpxMatrix::Median()
+{
+  if (Matrix==NULL)
+    return 0.0;
+
+  return vtkpxMath::GetMedian(this->TotalSize,this->Matrix);
+}
+// -----------------------------------------------------------------------------------
+float vtkpxMatrix::SumSquares()
+{
+  if (Matrix==NULL)
+    return 0.0;
+
+  float sum=0.0;
+  for (int i=0;i<this->TotalSize;i++)
+    sum+=pow(this->Matrix[i],float(2.0));
+  return sum;
+}
+// -----------------------------------------------------------------------------------
+float vtkpxMatrix::SumMagnitude()
+{
+  if (Matrix==NULL)
+    return 0.0;
+
+  float sum=0.0;
+  for (int i=0;i<this->TotalSize;i++)
+    sum+=fabs(this->Matrix[i]);
+  return sum;
+}
+// -----------------------------------------------------------------------------------
+vtkpxMatrix* vtkpxMatrix::RowSums()
+{
+  if (Matrix==NULL)
+    return NULL;
+
+  vtkpxMatrix* temp=vtkpxMatrix::New();
+  temp->Allocate(this->Size[0],1);
+
+  for (int i=0;i<this->Size[0];i++)
+    {
+      float sum=0.0;
+      for (int j=0;j<this->Size[1];j++)
+	sum+=this->GetDirectElement(i,j);
+      temp->SetDirectElement(i,0,sum);
+    }
+  return temp;
+}
+// -----------------------------------------------------------------------------------
+vtkpxMatrix* vtkpxMatrix::ColumnSums()
+{
+  if (Matrix==NULL)
+    return NULL;
+
+  vtkpxMatrix* temp=vtkpxMatrix::New();
+  temp->Allocate(1,this->Size[1]);
+
+  for (int j=0;j<this->Size[1];j++)
+    {
+      float sum=0.0;
+      for (int i=0;i<this->Size[0];i++)
+	sum+=this->GetDirectElement(i,j);
+      temp->SetDirectElement(0,j,sum);
+    }
+  return temp;
+}
+
+// -----------------------------------------------------------------------------------
+//   Uses Lapack Stuff from here
+// -----------------------------------------------------------------------------------
+int vtkpxMatrix::Invert()
+{
+  if (Matrix==NULL)
+    return 0;
+
+  if (this->Size[0]!=this->Size[1])
+    {
+      vtkErrorMacro(<<"Cannot Invert non-square matrix");
+      return 0;
+    }
+
+  if (this->Size[0]==1)
+    {
+      // This is stupid, 1x1 matrix but you never know !!
+      float a=this->GetDirectElement(0,0);
+      if (a!=0.0)
+	this->SetDirectElement(0,0,1.0/a);
+      return 1;
+    }
+
+  /*  =====================================================================
+   *  SUBROUTINE DGETRF( M, N, A, LDA, IPIV, INFO )
+   *
+   *  DGETRF computes an LU factorization of a general M-by-N matrix A
+   *  using partial pivoting with row interchanges.
+   *
+   *  The factorization has the form
+   *     A = P * L * U
+   *  where P is a permutation matrix, L is lower triangular with unit
+   *  diagonal elements (lower trapezoidal if m > n), and U is upper
+   *  triangular (upper trapezoidal if m < n).
+   *
+   *  M       (input) INTEGER
+   *          The number of rows of the matrix A.  M >= 0.
+   *
+   *  N       (input) INTEGER
+   *          The number of columns of the matrix A.  N >= 0.
+   *
+   *  A       (input/output) FLOAT PRECISION array, dimension (LDA,N)
+   *          On entry, the M-by-N matrix to be factored.
+   *          On exit, the factors L and U from the factorization
+   *          A = P*L*U; the unit diagonal elements of L are not stored.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,M).
+   *
+   *  IPIV    (output) INTEGER array, dimension (min(M,N))
+   *          The pivot indices; for 1 <= i <= min(M,N), row i of the
+   *          matrix was interchanged with row IPIV(i).
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value
+   *          > 0:  if INFO = i, U(i,i) is exactly zero. The factorization
+   *                has been completed, but the factor U is exactly
+   *                singular, and division by zero will occur if it is used
+   *                to solve a system of equations.
+   *
+   *  ===================================================================== */
+
+  integer M=this->Size[0];
+  integer N=this->Size[1];
+
+  // Copy Matrix (transposed) into Array A
+  real* A=new real[M*N];
+
+  float* mat=&Matrix[0];
+  int i,j;
+  for (j=0;j<N;j++)
+    for (i=0;i<M;i++)
+      {
+	A[j*M+i]=*mat;//this->GetDirectElement(i,j);
+	++mat;
+      }
+
+  integer LDA=M;
+
+  integer K=this->Size[0];
+  if (K > this->Size[1])
+    K=this->Size[1];
+
+  integer* IPIV=new integer[K];
+
+  integer INFO =1;
+
+  // Do LU Factorization First
+  sgetrf_(&M, &N, &A[0], &LDA, &IPIV[0], &INFO);
+
+  if (INFO!=0)
+    {
+      vtkErrorMacro(<<"Error INFO="<<INFO);
+      return 0;
+    }
+
+  /*  =====================================================================
+   *  SUBROUTINE DGETRI( N, A, LDA, IPIV, WORK, LWORK, INFO )
+   *
+   *  DGETRI computes the inverse of a matrix using the LU factorization
+   *  computed by DGETRF.
+   *
+   *  This method inverts U and then computes inv(A) by solving the system
+   *  inv(A)*L = inv(U) for inv(A).
+   *
+   *  N       (input) INTEGER
+   *          The order of the matrix A.  N >= 0.
+   *
+   *  A       (input/output) FLOAT PRECISION array, dimension (LDA,N)
+   *          On entry, the factors L and U from the factorization
+   *          A = P*L*U as computed by DGETRF.
+   *          On exit, if INFO = 0, the inverse of the original matrix A.
+   *
+   *  LDA     (input) INTEGER
+   *          The leading dimension of the array A.  LDA >= max(1,N).
+   *
+   *  IPIV    (input) INTEGER array, dimension (N)
+   *          The pivot indices from DGETRF; for 1<=i<=N, row i of the
+   *          matrix was interchanged with row IPIV(i).
+   *
+   *  WORK    (workspace/output) FLOAT PRECISION array, dimension (LWORK)
+   *          On exit, if INFO=0, then WORK(1) returns the optimal LWORK.
+   *
+   *  LWORK   (input) INTEGER
+   *          The dimension of the array WORK.  LWORK >= max(1,N).
+   *          For optimal performance LWORK >= N*NB, where NB is
+   *          the optimal blocksize returned by ILAENV.
+   *
+   *          If LWORK = -1, then a workspace query is assumed; the routine
+   *          only calculates the optimal size of the WORK array, returns
+   *          this value as the first entry of the WORK array, and no error
+   *          message related to LWORK is issued by XERBLA.
+   *
+   *  INFO    (output) INTEGER
+   *          = 0:  successful exit
+   *          < 0:  if INFO = -i, the i-th argument had an illegal value
+   *          > 0:  if INFO = i, U(i,i) is exactly zero; the matrix is
+   *                singular and its inverse could not be computed.
+   *
+   *  ===================================================================== */
+
+  integer LWORK=10*N;
+  real* WORK=new real[LWORK];
+
+  sgetri_( &N , &A[0] , &LDA, &IPIV[0], &WORK[0], &LWORK, &INFO);
+
+  vtkDebugMacro(<<"Work [0]="<<WORK[0]);
+
+  if (INFO!=0)
+    {
+      vtkErrorMacro(<<"Error INFO="<<(int)INFO);
+      return 0;
+    }
+
+  mat=&Matrix[0];
+  for (j=0;j<N;j++)
+    for (i=0;i<N;i++)
+      {
+	*mat=A[j*M+i];
+	++mat;
+      }
+
+
+  delete [] WORK;
+  delete [] IPIV;
+  delete [] A;
+
+  return 1;
+
+}
+// -----------------------------------------------------------------------------------
+int vtkpxMatrix::QRDecomposition(vtkpxMatrix* Q,vtkpxMatrix* R)
+{
+  if (Matrix==NULL)
+    return 0;
+
+  /*  =====================================================================
+      int sgeqrf_(integer *m, integer *n, real *a, integer *
+                  lda, real *tau, real *work, integer *lwork, integer *info)
+
+		  -- LAPACK routine (version 2.0) --
+       Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+       Courant Institute, Argonne National Lab, and Rice University
+       September 30, 1994
+
+
+    Purpose
+    =======
+
+    DGEQRF computes a QR factorization of a real M-by-N matrix A:
+    A = Q * R.
+
+    Arguments
+    =========
+
+    M       (input) INTEGER
+            The number of rows of the matrix A.  M >= 0.
+
+    N       (input) INTEGER
+            The number of columns of the matrix A.  N >= 0.
+
+    A       (input/output) FLOAT PRECISION array, dimension (LDA,N)
+            On entry, the M-by-N matrix A.
+            On exit, the elements on and above the diagonal of the array
+
+            contain the min(M,N)-by-N upper trapezoidal matrix R (R is
+            upper triangular if m >= n); the elements below the diagonal,
+
+            with the array TAU, represent the orthogonal matrix Q as a
+            product of min(m,n) elementary reflectors (see Further
+            Details).
+
+    LDA     (input) INTEGER
+            The leading dimension of the array A.  LDA >= max(1,M).
+
+    TAU     (output) FLOAT PRECISION array, dimension (min(M,N))
+            The scalar factors of the elementary reflectors (see Further
+
+            Details).
+
+    WORK    (workspace/output) FLOAT PRECISION array, dimension (LWORK)
+
+            On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
+
+    LWORK   (input) INTEGER
+            The dimension of the array WORK.  LWORK >= max(1,N).
+            For optimum performance LWORK >= N*NB, where NB is
+            the optimal blocksize.
+
+    INFO    (output) INTEGER
+            = 0:  successful exit
+            < 0:  if INFO = -i, the i-th argument had an illegal value
+
+    Further Details
+    ===============
+
+    The matrix Q is represented as a product of elementary reflectors
+
+       Q = H(1) H(2) . . . H(k), where k = min(m,n).
+
+    Each H(i) has the form
+
+       H(i) = I - tau * v * v'
+
+    where tau is a real scalar, and v is a real vector with
+    v(1:i-1) = 0 and v(i) = 1; v(i+1:m) is stored on exit in A(i+1:m,i),
+
+    and tau in TAU(i).
+
+    ===================================================================== */
+
+  int i,j;
+
+  integer M=this->Size[0];
+  integer N=this->Size[1];
+
+
+  // Copy Matrix (transposed) into Array A
+
+  integer MK=Imax(M,N);
+  integer K=Imin(M,N);
+  integer MK2=MK*MK;
+
+  integer LDA=MK;
+
+  real* A=new real[MK2];
+  // To get the full QR ( as opposed to the economy QR A needs to be made square and padded with zeros!!!)
+
+  for (i=0;i<MK2;i++)
+    A[i]=0.0;
+
+  for (i=0;i<N;i++)
+    for (j=0;j<M;j++)
+      A[i*MK+j]=this->GetDirectElement(j,i);
+
+
+  real* TAU=new real[MK];
+
+  integer LWORK=MK*10;
+  real* WORK=new real[LWORK];
+
+  integer INFO=0;
+
+  sgeqrf_(&MK, &MK, &A[0], &LDA, &TAU[0], &WORK[0], &LWORK, &INFO);
+  vtkDebugMacro(<<"Work [0]="<<WORK[0]);
+
+  if (INFO!=0)
+    {
+      vtkErrorMacro(<<"Error INFO="<<(int)INFO);
+      return 0;
+    }
+
+  // Copy R Matrix Out First
+  R->Zeros(MK,N);
+
+  for (i=0;i<K;i++)
+    for (j=i;j<N;j++)
+      R->SetDirectElement(i,j,A[j*MK+i]);
+
+  // Next Get Q and then we are out of here
+  /*  =====================================================================
+      int SORGQR_(integer *m, integer *n, integer *k, real *
+                 a, integer *lda, real *tau, real *work, integer *lwork,
+                 integer *info)
+
+
+      -- LAPACK routine (version 2.0) --
+      Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+      Courant Institute, Argonne National Lab, and Rice University
+      September 30, 1994
+
+
+    Purpose
+    =======
+
+    DORGQR generates an M-by-N real matrix Q with orthonormal columns,
+    which is defined as the first N columns of a product of K elementary
+
+    reflectors of order M
+
+          Q  =  H(1) H(2) . . . H(k)
+
+    as returned by DGEQRF.
+
+    Arguments
+    =========
+
+    M       (input) INTEGER
+            The number of rows of the matrix Q. M >= 0.
+
+    N       (input) INTEGER
+            The number of columns of the matrix Q. M >= N >= 0.
+
+    K       (input) INTEGER
+            The number of elementary reflectors whose product defines the
+
+            matrix Q. N >= K >= 0.
+
+    A       (input/output) FLOAT PRECISION array, dimension (LDA,N)
+            On entry, the i-th column must contain the vector which
+            defines the elementary reflector H(i), for i = 1,2,...,k, as
+
+            returned by DGEQRF in the first k columns of its array
+            argument A.
+            On exit, the M-by-N matrix Q.
+
+    LDA     (input) INTEGER
+            The first dimension of the array A. LDA >= max(1,M).
+
+    TAU     (input) FLOAT PRECISION array, dimension (K)
+            TAU(i) must contain the scalar factor of the elementary
+            reflector H(i), as returned by DGEQRF.
+
+    WORK    (workspace/output) FLOAT PRECISION array, dimension (LWORK)
+
+            On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
+
+    LWORK   (input) INTEGER
+            The dimension of the array WORK. LWORK >= max(1,N).
+            For optimum performance LWORK >= N*NB, where NB is the
+            optimal blocksize.
+
+    INFO    (output) INTEGER
+            = 0:  successful exit
+            < 0:  if INFO = -i, the i-th argument has an illegal value
+
+   *  ===================================================================== */
+
+  sorgqr_( &MK, &MK, &MK, A, &LDA, TAU, WORK, &LWORK, &INFO );
+
+  if (INFO!=0)
+    {
+      vtkErrorMacro(<<"Error INFO="<<INFO);
+      return 0;
+    }
+
+  // Copy Q Matrix
+  Q->Zeros(MK,MK);
+
+  for (i=0;i<MK;i++)
+    for (j=0;j<MK;j++)
+      Q->SetDirectElement(i,j,A[j*MK+i]);
+
+  delete [] WORK;
+  delete [] TAU;
+  delete [] A;
+
+  return 1;
+}
+
+// -----------------------------------------------------------------------------------
+int vtkpxMatrix::Q1Q2RDecomposition(vtkpxMatrix* Q1,vtkpxMatrix* Q2,vtkpxMatrix* R)
+{
+  if (Matrix==NULL)
+    return 0;
+
+  int i,j;
+
+  integer M=this->Size[0];
+  integer N=this->Size[1];
+
+  if (N>M)
+    {
+      fprintf(stderr,"More columns than rows, no Q1Q2R possible\n");
+      return 0;
+    }
+
+
+  // Copy Matrix (transposed) into Array A
+  integer MK=Imax(M,N);
+  integer K=Imin(M,N);
+  integer MK2=MK*MK;
+  integer LDA=MK;
+
+  real* A=new real[MK2];
+  // To get the full QR ( as opposed to the economy QR A needs to be made square and padded with zeros!!!)
+
+  for (i=0;i<MK2;i++)
+    A[i]=0.0;
+
+  for (i=0;i<N;i++)
+    for (j=0;j<M;j++)
+      A[i*MK+j]=this->GetDirectElement(j,i);
+
+
+  real* TAU=new real[MK];
+
+  integer LWORK=MK*10;
+  real* WORK=new real[LWORK];
+
+  integer INFO=0;
+
+  sgeqrf_(&MK, &MK, &A[0], &LDA, &TAU[0], &WORK[0], &LWORK, &INFO);
+  vtkDebugMacro(<<"Work [0]="<<WORK[0]);
+
+  if (INFO!=0)
+    {
+      vtkErrorMacro(<<"Error INFO="<<(int)INFO);
+      return 0;
+    }
+
+  // Copy R Matrix Out First
+  R->Zeros(K,N);
+
+  for (i=0;i<K;i++)
+    for (j=i;j<N;j++)
+      R->SetDirectElement(i,j,A[j*MK+i]);
+
+  // Next Get Q and then we are out of here
+  sorgqr_( &MK, &MK, &MK, A, &LDA, TAU, WORK, &LWORK, &INFO );
+
+  if (INFO!=0)
+    {
+      vtkErrorMacro(<<"Error INFO="<<INFO);
+      return 0;
+    }
+
+  // Copy Q Matrix
+  Q1->Zeros(M,N);
+
+  for (i=0;i<M;i++)
+    for (j=0;j<N;j++)
+      Q1->SetDirectElement(i,j,A[j*MK+i]);
+
+  Q2->Zeros(M,M-N);
+  for (i=0;i<M;i++)
+    for (j=N;j<M;j++)
+      Q2->SetDirectElement(i,j-N,A[j*MK+i]);
+
+  delete [] WORK;
+  delete [] TAU;
+  delete [] A;
+
+  return 1;
+}
+// -----------------------------------------------------------------------------------
+int vtkpxMatrix::SolveWeightedLeastSquares(vtkpxMatrix* W,vtkpxMatrix* B,vtkpxMatrix* X)
+{
+  if (this->Matrix==NULL || W==NULL || B==NULL || X==NULL)
+    {
+      vtkErrorMacro(<<"Invalid Inputs");
+      return 0;
+    }
+
+  int w_size[2],b_size[2],x_size[2];
+
+  W->GetSize(w_size);
+  B->GetSize(b_size);
+  X->GetSize(x_size);
+
+  if (w_size[0] != w_size[1] || w_size[1] != this->Size[0])
+    {
+      vtkErrorMacro(<<"Bad Size for Matrix W");
+      return 0;
+    }
+
+  if (w_size[1] != b_size[0])
+    {
+      vtkErrorMacro(<<"Bad Size for Vector B");
+      return 0;
+    }
+
+  if (x_size[0] != this->Size[1])
+    {
+      vtkErrorMacro(<<"Bad Size for Vector X");
+      return 0;
+    }
+
+  vtkpxMatrix* WA=vtkpxMatrix::New();
+  vtkpxMatrix::Multiply(W,this,WA);
+
+  vtkpxMatrix* WB=vtkpxMatrix::New();
+  vtkpxMatrix::Multiply(W,B,WB);
+
+  int ok=WA->SolveLeastSquares(WB,X);
+
+  WA->Delete();
+  WB->Delete();
+
+  return ok;
+}
+// -----------------------------------------------------------------------------------
+int vtkpxMatrix::SolveLeastSquares(vtkpxMatrix* Borig,vtkpxMatrix* X)
+{
+
+  if (this->Matrix==NULL ||  Borig==NULL || X==NULL)
+    {
+      vtkErrorMacro(<<"Invalid Inputs");
+      return 0;
+    }
+
+
+  /*
+      SUBROUTINE SGELS( TRANS, M, N, NRHS, A, LDA, B, LDB, WORK, LWORK,
+     $                  INFO )
+*
+*  -- LAPACK driver routine (version 3.0) --
+*     Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+*     Courant Institute, Argonne National Lab, and Rice University
+*     June 30, 1999
+
+*  Purpose
+*  =======
+*
+*  SGELS solves overdetermined or underdetermined real linear systems
+*  involving an M-by-N matrix A, or its transpose, using a QR or LQ
+*  factorization of A.  It is assumed that A has full rank.
+*
+*  The following options are provided:
+*
+*  1. If TRANS = 'N' and m >= n:  find the least squares solution of
+*     an overdetermined system, i.e., solve the least squares problem
+*                  minimize || B - A*X ||.
+*
+*  2. If TRANS = 'N' and m < n:  find the minimum norm solution of
+*     an underdetermined system A * X = B.
+*
+*  3. If TRANS = 'T' and m >= n:  find the minimum norm solution of
+*     an undetermined system A**T * X = B.
+*
+*  4. If TRANS = 'T' and m < n:  find the least squares solution of
+*     an overdetermined system, i.e., solve the least squares problem
+*                  minimize || B - A**T * X ||.
+*
+*  Several right hand side vectors b and solution vectors x can be
+*  handled in a single call; they are stored as the columns of the
+*  M-by-NRHS right hand side matrix B and the N-by-NRHS solution
+*  matrix X.
+*
+*  Arguments
+*  =========
+*
+*  TRANS   (input) CHARACTER
+*          = 'N': the linear system involves A;
+*          = 'T': the linear system involves A**T.
+*
+*  M       (input) INTEGER
+*          The number of rows of the matrix A.  M >= 0.
+*
+*  N       (input) INTEGER
+*          The number of columns of the matrix A.  N >= 0.
+*
+*  NRHS    (input) INTEGER
+*          The number of right hand sides, i.e., the number of
+*          columns of the matrices B and X. NRHS >=0.
+*
+*  A       (input/output) REAL array, dimension (LDA,N)
+*          On entry, the M-by-N matrix A.
+*          On exit,
+*            if M >= N, A is overwritten by details of its QR
+*                       factorization as returned by SGEQRF;
+*            if M <  N, A is overwritten by details of its LQ
+*                       factorization as returned by SGELQF.
+*
+*  LDA     (input) INTEGER
+*          The leading dimension of the array A.  LDA >= max(1,M).
+*
+*  B       (input/output) REAL array, dimension (LDB,NRHS)
+*          On entry, the matrix B of right hand side vectors, stored
+*          columnwise; B is M-by-NRHS if TRANS = 'N', or N-by-NRHS
+*          if TRANS = 'T'.
+*          On exit, B is overwritten by the solution vectors, stored
+*          columnwise:
+*          if TRANS = 'N' and m >= n, rows 1 to n of B contain the least
+*          squares solution vectors; the residual sum of squares for the
+*          solution in each column is given by the sum of squares of
+*          elements N+1 to M in that column;
+*          if TRANS = 'N' and m < n, rows 1 to N of B contain the
+*          minimum norm solution vectors;
+*          if TRANS = 'T' and m >= n, rows 1 to M of B contain the
+*          minimum norm solution vectors;
+*          if TRANS = 'T' and m < n, rows 1 to M of B contain the
+*          least squares solution vectors; the residual sum of squares
+*          for the solution in each column is given by the sum of
+*          squares of elements M+1 to N in that column.
+*
+*  LDB     (input) INTEGER
+*          The leading dimension of the array B. LDB >= MAX(1,M,N).
+*
+*  WORK    (workspace/output) REAL array, dimension (LWORK)
+*          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
+*
+*  LWORK   (input) INTEGER
+*          The dimension of the array WORK.
+*          LWORK >= max( 1, MN + max( MN, NRHS ) ).
+*          For optimal performance,
+*          LWORK >= max( 1, MN + max( MN, NRHS )*NB ).
+*          where MN = min(M,N) and NB is the optimum block size.
+*
+*          If LWORK = -1, then a workspace query is assumed; the routine
+*          only calculates the optimal size of the WORK array, returns
+*          this value as the first entry of the WORK array, and no error
+*          message related to LWORK is issued by XERBLA.
+*
+*  INFO    (output) INTEGER
+*          = 0:  successful exit
+*          < 0:  if INFO = -i, the i-th argument had an illegal value
+*
+*  =====================================================================
+*/
+
+
+  // First Matrix A = M*N
+  // --------------------
+  integer M=this->Size[0];
+  integer N=this->Size[1];
+
+  // Copy Matrix (transposed) into Array A
+  real* A=new real[M*N];
+  float* mat=&Matrix[0];
+  int i,j;
+  for (j=0;j<N;j++)
+    for (i=0;i<M;i++)
+      {
+	A[j*M+i]=*mat;//this->GetDirectElement(i,j);
+	++mat;
+      }
+
+  integer LDA=M;
+
+  // Then Matrix B = M*NRHS
+  // ----------------------
+  int b_size[2];
+  Borig->GetSize(b_size);
+  integer NRHS=b_size[1];
+
+  // Copy Matrix (transposed) into Array A
+  real* B=new real[M*NRHS];
+  float* matB=Borig->GetMatrixPointer();
+  for (j=0;j<NRHS;j++)
+    for (i=0;i<M;i++)
+      {
+	B[j*M+i]=*matB;//this->GetDirectElement(i,j);
+	++matB;
+      }
+
+  integer LDB=M;
+
+
+  // Then Other Stuff
+
+  integer MX=M;
+  if (NRHS>M)
+    MX=NRHS;
+
+  integer LWORK=N+3*MX;
+  real* WORK=new real[3*M];
+
+  integer INFO=-1;
+
+  char line[2];
+  strcpy(line,"N");
+  sgels_(&line[0],&M,&N,&NRHS,A,&LDA,B,&LDB,
+	 WORK,&LWORK,&INFO);
+
+  if (INFO==0)
+    {
+      int xsize[2];
+      X->GetSize(xsize);
+
+      for (i=0;i<xsize[0];i++)
+	for (j=0;j<xsize[1];j++)
+	  X->SetElement(i,j,B[j*M+i]);
+    }
+  else
+    {
+      vtkErrorMacro(<<"Error in Solving Least Squares Problem!");
+      INFO=1;
+    }
+
+  delete [] A;
+  delete [] B;
+  delete [] WORK;
+
+  return (1-INFO);
+}
+// -----------------------------------------------------------------------------------
+int vtkpxMatrix::SolveLinearSystem(vtkpxMatrix* B,vtkpxMatrix* X)
+{
+  return this->InternalSolveLinearSystem(B,X,0);
+}
+
+int vtkpxMatrix::SolveSymmetricLinearSystem(vtkpxMatrix* B,vtkpxMatrix* X)
+{
+  return this->InternalSolveLinearSystem(B,X,1);
+}
+
+int vtkpxMatrix::SolveUpperSymmetricLinearSystem(vtkpxMatrix* B,vtkpxMatrix* X)
+{
+  return this->InternalSolveLinearSystem(B,X,1);
+}
+
+int vtkpxMatrix::SolveLowerSymmetricLinearSystem(vtkpxMatrix* B,vtkpxMatrix* X)
+{
+  return this->InternalSolveLinearSystem(B,X,-1);
+}
+
+int vtkpxMatrix::InternalSolveLinearSystem(vtkpxMatrix* Borig,vtkpxMatrix* X,int symmetric)
+{
+  if (this->Matrix==NULL ||  Borig==NULL || X==NULL)
+    {
+      vtkErrorMacro(<<"Invalid Inputs");
+      return 0;
+    }
+
+  integer M=this->Size[0];
+  integer N=this->Size[1];
+
+  // Copy Matrix (transposed) into Array A
+  real* A=new real[M*N];
+  float* mat=&Matrix[0];
+  int i,j;
+  for (j=0;j<N;j++)
+    for (i=0;i<M;i++)
+      {
+	A[j*M+i]=*mat;//this->GetDirectElement(i,j);
+	++mat;
+      }
+  integer LDA=M;
+
+  int b_size[2];
+  Borig->GetSize(b_size);
+  integer NRHS=b_size[1];
+
+  // Copy Matrix (transposed) into Array A
+  real* B=new real[M*NRHS];
+  float* matB=Borig->GetMatrixPointer();
+  for (j=0;j<NRHS;j++)
+    for (i=0;i<M;i++)
+      {
+	B[j*M+i]=*matB;//this->GetDirectElement(i,j);
+	++matB;
+      }
+  integer LDB=M;
+  integer INFO=0;
+
+  if (symmetric==0)
+    {
+      /*      SUBROUTINE SGESV( N, NRHS, A, LDA, IPIV, B, LDB, INFO )
+       *
+       *  -- LAPACK driver routine (version 3.0) --
+       *     Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+       *     Courant Institute, Argonne National Lab, and Rice University
+       *     March 31, 1993
+       *
+       *
+       *  Purpose
+       *  =======
+       *
+       *  SGESV computes the solution to a real system of linear equations
+       *     A * X = B,
+       *  where A is an N-by-N matrix and X and B are N-by-NRHS matrices.
+       *
+       *  The LU decomposition with partial pivoting and row interchanges is
+       *  used to factor A as
+       *     A = P * L * U,
+       *  where P is a permutation matrix, L is unit lower triangular, and U is
+       *  upper triangular.  The factored form of A is then used to solve the
+       *  system of equations A * X = B.
+       *
+       *  Arguments
+       *  =========
+       *
+       *  N       (input) INTEGER
+       *          The number of linear equations, i.e., the order of the
+       *          matrix A.  N >= 0.
+       *
+       *  NRHS    (input) INTEGER
+       *          The number of right hand sides, i.e., the number of columns
+       *          of the matrix B.  NRHS >= 0.
+       *
+       *  A       (input/output) REAL array, dimension (LDA,N)
+       *          On entry, the N-by-N coefficient matrix A.
+       *          On exit, the factors L and U from the factorization
+       *          A = P*L*U; the unit diagonal elements of L are not stored.
+       *
+       *  LDA     (input) INTEGER
+       *          The leading dimension of the array A.  LDA >= max(1,N).
+       *
+       *  IPIV    (output) INTEGER array, dimension (N)
+       *          The pivot indices that define the permutation matrix P;
+       *          row i of the matrix was interchanged with row IPIV(i).
+       *
+       *  B       (input/output) REAL array, dimension (LDB,NRHS)
+       *          On entry, the N-by-NRHS matrix of right hand side matrix B.
+       *          On exit, if INFO = 0, the N-by-NRHS solution matrix X.
+       *
+       *  LDB     (input) INTEGER
+       *          The leading dimension of the array B.  LDB >= max(1,N).
+       *
+       *  INFO    (output) INTEGER
+       *          = 0:  successful exit
+       *          < 0:  if INFO = -i, the i-th argument had an illegal value
+       *          > 0:  if INFO = i, U(i,i) is exactly zero.  The factorization
+       *                has been completed, but the factor U is exactly
+       *                singular, so the solution could not be computed.
+       *
+       *  =====================================================================*/
+      integer* IPIV=new integer[N];
+      for (int i=0;i<N;i++)
+	IPIV[i]=i+1;
+
+      sgesv_(&N,&NRHS,A,&LDA,IPIV,B,&LDB,&INFO);
+
+      delete [] IPIV;
+    } else {
+
+      /* SUBROUTINE SPOSV( UPLO, N, NRHS, A, LDA, B, LDB, INFO )
+       *
+       *  -- LAPACK driver routine (version 3.0) --
+       *     Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+       *     Courant Institute, Argonne National Lab, and Rice University
+       *     March 31, 1993
+       *
+       *
+       *  Purpose
+       *  =======
+       *
+       *  SPOSV computes the solution to a real system of linear equations
+       *     A * X = B,
+       *  where A is an N-by-N symmetric positive definite matrix and X and B
+       *  are N-by-NRHS matrices.
+       *
+       *  The Cholesky decomposition is used to factor A as
+       *     A = U**T* U,  if UPLO = 'U', or
+       *     A = L * L**T,  if UPLO = 'L',
+       *  where U is an upper triangular matrix and L is a lower triangular
+       *  matrix.  The factored form of A is then used to solve the system of
+       *  equations A * X = B.
+       *
+       *  Arguments
+       *  =========
+       *
+       *  UPLO    (input) CHARACTER*1
+       *          = 'U':  Upper triangle of A is stored;
+       *          = 'L':  Lower triangle of A is stored.
+       *
+       *  N       (input) INTEGER
+       *          The number of linear equations, i.e., the order of the
+       *          matrix A.  N >= 0.
+       *
+       *  NRHS    (input) INTEGER
+       *          The number of right hand sides, i.e., the number of columns
+       *          of the matrix B.  NRHS >= 0.
+       *
+       *  A       (input/output) REAL array, dimension (LDA,N)
+       *          On entry, the symmetric matrix A.  If UPLO = 'U', the leading
+       *          N-by-N upper triangular part of A contains the upper
+       *          triangular part of the matrix A, and the strictly lower
+       *          triangular part of A is not referenced.  If UPLO = 'L', the
+       *          leading N-by-N lower triangular part of A contains the lower
+       *          triangular part of the matrix A, and the strictly upper
+       *          triangular part of A is not referenced.
+       *
+       *          On exit, if INFO = 0, the factor U or L from the Cholesky
+       *          factorization A = U**T*U or A = L*L**T.
+       *
+       *  LDA     (input) INTEGER
+       *          The leading dimension of the array A.  LDA >= max(1,N).
+       *
+       *  B       (input/output) REAL array, dimension (LDB,NRHS)
+       *          On entry, the N-by-NRHS right hand side matrix B.
+       *          On exit, if INFO = 0, the N-by-NRHS solution matrix X.
+       *
+       *  LDB     (input) INTEGER
+       *          The leading dimension of the array B.  LDB >= max(1,N).
+       *
+       *  INFO    (output) INTEGER
+       *          = 0:  successful exit
+       *          < 0:  if INFO = -i, the i-th argument had an illegal value
+       *          > 0:  if INFO = i, the leading minor of order i of A is not
+       *                positive definite, so the factorization could not be
+       *                completed, and the solution has not been computed.
+       *
+       *  =====================================================================*/
+
+      char line[2];
+      if (symmetric==1)
+	strcpy(line,"U");
+      else
+	strcpy(line,"L");
+      sposv_(&line[0],&N,&NRHS,A,&LDA,B,&LDB,&INFO);
+    }
+
+
+    if (INFO==0)
+    {
+      int xsize[2];
+      X->GetSize(xsize);
+
+      for (i=0;i<xsize[0];i++)
+	for (j=0;j<xsize[1];j++)
+	  X->SetElement(i,j,B[j*M+i]);
+    }
+  else
+    {
+      vtkErrorMacro(<<"Error in Solving Linear System Problem (symmetric="<<symmetric<<")!");
+      INFO=1;
+    }
+
+  delete [] A;
+  delete [] B;
+
+  return (1-INFO);
+
+
+}
+//------------------------------------------------------------------------
+int vtkpxMatrix::SOR(vtkpxMatrix* B,vtkpxMatrix* X,float thr,float omega)
+{
+  if (X==NULL || B==NULL)
+    return 0;
+
+  int b_size[2];   B->GetSize(b_size);
+
+  if (this->Size[0] != this->Size[1])
+    {
+      vtkErrorMacro(<<"Bad Size for Solving Linear System (Not Square)");
+      return 0;
+    }
+
+  if (this->Size[1] != b_size[0])
+    {
+      vtkErrorMacro(<<"Bad Size for Vector B");
+      return 0;
+    }
+
+  int x_size[2]; X->GetSize(x_size);
+  if (x_size[0] !=b_size[0] || x_size[1] !=b_size[1])
+    X->Zeros(b_size[0],b_size[1]);
+
+  const int MAXITER=100;
+  int maxiter=MAXITER*this->Size[0];
+  int totaliter=0;
+
+  int ok=1;
+  for (int i=0;i<this->Size[0];i++)
+    {
+      float v=this->GetDirectElement(i,i);
+      if (fabs(v)<0.0001)
+	{
+	  ok=0;
+	  i=this->Size[0];
+	}
+    }
+
+  if (ok==0)
+    {
+      vtkErrorMacro(<<"Zero diagonal element ... bad SOR\n");
+      return 0;
+    }
+
+
+
+  float *newx=new float[this->Size[0]];
+  float *oldx=new float[this->Size[0]];
+
+  float* bpoint=B->GetMatrixPointer();
+
+  for (int master_column=0;master_column<b_size[1];master_column++)
+    {
+      int row,col,iter=0;
+
+      for (int ia=0;ia<this->Size[0];ia++)
+	{
+	  oldx[ia]=X->GetDirectElement(ia,master_column);
+	  newx[ia]=oldx[ia];
+	}
+
+
+
+      float res=thr+1.0;
+
+      while ( res>thr && iter < maxiter)
+	{
+	  iter++;
+	  for (row=0;row<this->Size[0];row++)
+	    {
+	      float r=0.0;
+
+	      //     form gaus-seidel best estimate;
+	      //     for elements before leading diagonal;
+	      for (col=0;col<row;col++)
+		r+=this->Matrix[col*Size[0]+row]*newx[col];
+
+	      //  for elements after leading diagonal;
+
+	      for (col=row+1;col<this->Size[0];col++)
+		r+=this->Matrix[col*Size[0]+row]*oldx[col];
+
+	      // form sor (gaus seidel omega=1);
+
+	      newx[row]=omega*((bpoint[row+master_column*b_size[0]]-r)/this->Matrix[row*Size[0]+row]);
+	      newx[row]=newx[row]+(1-omega)*oldx[row];
+	    }
+
+	  //     calculate ||x(k+1)-x(k)||(inf) moddif and ||x(k)||(inf)=modx;
+	  //     also do oldx=x to prepare for next iteration;
+
+	  float moddif=0.0,modx=0.0;
+
+	  for (row=0;row<this->Size[0];row ++)
+	    {
+	      if (fabs(oldx[row]-newx[row]) > moddif)
+		moddif=fabs(oldx[row]-newx[row]);
+	      if (fabs(newx[row]) > modx)
+		modx=fabs(newx[row]);
+	      oldx[row]=newx[row];
+	    }
+	  res=moddif/modx;
+	  fprintf(stderr,"Iteration %d/%d col=%d/%d thr=%.4f < %.4f\n",
+		  iter,maxiter,master_column,b_size[1],res,thr);
+	}
+
+      totaliter+=iter;
+
+      for (int ib=0;ib<this->Size[0];ib++)
+	X->SetDirectElement(ib,master_column,oldx[ib]);
+    }
+  delete [] newx;
+  delete [] oldx;
+  return totaliter;
+}
+
+//------------------------------------------------------------------------
+// Static Code which can be accessed directly
+//------------------------------------------------------------------------
+double** vtkpxMatrix::NewMatrix(int x, int y)
+{
+  double** m = new double*[x];
+  for(int i = 0; i < x; i++)
+    {
+      m[i] = new double[y];
+    }
+  return m;
+}
+
+void vtkpxMatrix::DeleteMatrix(double** m, int x, int vtkNotUsed(y))
+{
+  for(int i = 0; i < x; i++)
+    {
+    delete [] m[i]; // OK, we don't actually need y
+    }
+  delete [] m;
+}
+
+void vtkpxMatrix::FillMatrixWithZeros(double** m, int x, int y)
+{
+  int i,j;
+  for(i = 0; i < x; i++)
+    {
+    for(j = 0; j < y; j++)
+      {
+      m[i][j] = 0.0;
+      }
+    }
+}
+
+void vtkpxMatrix::MatrixMultiply(double** a, double** b, double** c,
+					     int ar, int ac, int br, int bc)
+{
+  if(ac != br)
+    {
+    return;	// ac must equal br otherwise we can't proceed
+    }
+
+  // c must have size ar*bc (we assume this)
+  const int cr = ar;
+  const int cc = bc;
+  int row,col,i;
+  for(row = 0; row < cr; row++)
+    {
+    for(col = 0; col < cc; col++)
+      {
+      c[row][col] = 0.0;
+      for(i = 0; i < ac; i++)
+        {
+        c[row][col] += a[row][i]*b[i][col];
+        }
+      }
+    }
+}
+
+void vtkpxMatrix::PrintMatrix(double **m, int x, int y)
+{
+  int i,j;
+  for(i = 0; i < x; i++)
+    {
+    for(j = 0; j < y; j++)
+      {
+      cerr << m[i][j] << ((j != y-1) ? " " : "\n");
+      }
+    }
+}
+void vtkpxMatrix::InPlaceTransposeMatrix(double** m,int x, int y)
+{
+  for (int i=0;i<x;i++)
+    for (int j=0;j<y;j++)
+      {
+	double a=m[i][j];
+	m[i][j]=m[j][i];
+	m[j][i]=a;
+      }
+}
+
+double** vtkpxMatrix::TransposeMatrix(double** src,int x ,int y)
+{
+  double** dest=vtkpxMatrix::NewMatrix(x,y);
+  for (int i=0;i<x;i++)
+    for (int j=0;j<y;j++)
+      dest[i][j]=src[j][i];
+  return dest;
+}
+
+void vtkpxMatrix::CopyMatrix(double** dest,double** src,int x ,int y)
+{
+  for (int i=0;i<x;i++)
+    for (int j=0;j<y;j++)
+      dest[i][j]=src[i][j];
+}
+
+double** vtkpxMatrix::CopyMatrix(double** src,int x ,int y)
+{
+  double** dest=vtkpxMatrix::NewMatrix(x,y);
+  for (int i=0;i<x;i++)
+    for (int j=0;j<y;j++)
+      dest[i][j]=src[i][j];
+  return dest;
+}
+
+double** vtkpxMatrix::SubMatrix(double** src,int x1,int x2,int y1,int y2)
+{
+  int x=x2-x1+1;
+  int y=y2-y1+1;
+  double** dest=vtkpxMatrix::NewMatrix(x,y);
+  for (int i=0;i<x;i++)
+    for (int j=0;j<y;j++)
+      dest[i][j]=src[i+x1][j+y1];
+  return dest;
+}
+
+//------------------------------------------------------------------------
+// RPM Code
+//------------------------------------------------------------------------
+void vtkpxMatrix::MapPoints(vtkpxMatrix* Y,vtkpxMatrix* VY)
+{
+  int size[2];
+  this->GetSize(size);
+
+  if (Y->GetSize()[0] != size[1] || Y->GetSize()[1]!=4)
+    {
+      vtkErrorMacro(<<"Bad Matrices to Map Points");
+      return;
+    }
+
+  if (VY->GetSize()[0]!=size[0] || VY->GetSize()[1]!=4)
+    VY->Zeros(size[0],4);
+
+  if (this->Debug)
+    fprintf(stderr,"Mapping Points %dx%d ...",size[0],size[1]);
+
+  for (int row=0;row<size[0];row++)
+    {
+      float sum=0.0;
+      for (int column=0;column<size[1];column++)
+	sum+=this->GetDirectElement(row,column);
+
+      if (sum<0.0001)
+	sum=0.0001;
+
+      for (int comp=0;comp<3;comp++)
+	{
+	  float value=0.0;
+	  for (int column=0;column<size[1];column++)
+	    value+=this->GetDirectElement(row,column)*Y->GetDirectElement(column,comp);
+	  VY->SetDirectElement(row,comp,value/sum);
+	}
+      VY->SetDirectElement(row,3,1.0);
+    }
+  if (this->Debug)
+    fprintf(stderr,"done\n");
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - -
+void vtkpxMatrix::NormalizeMixtureMatrix(vtkpxMatrix* M_Outliers_Row)
+{
+  int size[2];
+  this->GetSize(size);
+  if (this->Debug)
+    fprintf(stderr,"Normalizing Distance Matrix %dx%d ...",size[0],size[1]);
+  int row,column;
+
+  // Normalize Accross Outlier Row
+  for (column=0;column<size[1];column++)
+    {
+      float sum=0.0;
+      for (row=0;row<size[0];row++)
+	sum+=this->GetDirectElement(row,column);
+      sum+=M_Outliers_Row->GetElement(0,column);
+
+      if (sum<0.0001)
+	sum=0.0001;
+
+      for (row=0;row<size[0];row++)
+	this->SetDirectElement(row,column,this->GetDirectElement(row,column)/sum);
+    }
+  if (this->Debug)
+    fprintf(stderr,"done\n");
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - -
+void vtkpxMatrix::NormalizeRPMMatrix(vtkpxMatrix* M_Outliers_Row,vtkpxMatrix* M_Outliers_Column)
+{
+  int size[2];
+  this->GetSize(size);
+
+  //float norm_threshold = 0.05;
+  int   norm_maxit     = 10;
+
+  int row,column;
+  float sumx,sumy;
+
+  int norm_it = 0;
+  while (norm_it < norm_maxit)
+    {
+      // --- Row normalization --------------------------------------------
+      for (row=0;row<size[0];row++)
+	{
+	  sumx=0.0;
+	  for (column=0;column<size[1];column++)
+	    sumx+=this->GetDirectElement(row,column);
+	  sumx+=M_Outliers_Column->GetElement(row,0);
+
+	  if (sumx<0.0001)
+	    sumx=0.0001;
+
+	  for (column=0;column<size[1];column++)
+	    this->SetDirectElement(row,column,this->GetDirectElement(row,column)/sumx);
+	  M_Outliers_Column->SetElement(row,0,M_Outliers_Column->GetElement(row,0)/sumx);
+	}
+
+      /*sx = sum(m')' + m_outlier_col;
+	m  = m ./ (sx * ones(0,ymax));
+	m_outlier_col = m_outlier_col ./sx;*/
+
+      // --- Column normalization -----------------------------------------
+      for (column=0;column<size[1];column++)
+	{
+	  sumy=0.0;
+	  for (row=0;row<size[0];row++)
+	    sumy+=this->GetDirectElement(row,column);
+	  sumy+=M_Outliers_Row->GetElement(0,column);
+
+	  if (sumy<0.0001)
+	    sumy+=0.0001;
+
+	  for (row=0;row<size[0];row++)
+	    this->SetDirectElement(row,column,this->GetDirectElement(row,column)/sumy);
+	  M_Outliers_Row->SetElement(0,column,M_Outliers_Row->GetElement(0,column)/sumy);
+	}
+
+      /*sy = sum(m) + m_outlier_row;
+	m  = m ./ (ones(xmax,0)*sy);
+	m_outlier_row = m_outlier_row ./sy;*/
+
+      // time to quit?
+      norm_it = norm_it + 1;
+    }
+
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - -
+int vtkpxMatrix::Eigenvalues(vtkpxMatrix* D)
+{
+  return this->Diagonalize(D,NULL);
+}
+int vtkpxMatrix::Diagonalize(vtkpxMatrix* D,vtkpxMatrix* U)
+{
+  if (Matrix==NULL || D==NULL)
+    return 0;
+
+  if (this->Size[0]!=this->Size[1])
+    {
+      vtkErrorMacro(<<"Cannot Invert non-square matrix");
+      return 0;
+    }
+
+  /*
+    SUBROUTINE SSYEV( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, INFO )
+    *
+    *  -- LAPACK driver routine (version 3.0) --
+    *     Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
+    *     Courant Institute, Argonne National Lab, and Rice University
+    *     June 30, 1999
+    *
+    *     .. Scalar Arguments ..
+    CHARACTER          JOBZ, UPLO
+    INTEGER            INFO, LDA, LWORK, N
+    *     ..
+    *     .. Array Arguments ..
+    REAL               A( LDA, * ), W( * ), WORK( * )
+    *     ..
+    *
+    *  Purpose
+    *  =======
+    *
+    *  SSYEV computes all eigenvalues and, optionally, eigenvectors of a
+    *  real symmetric matrix A.
+    *
+    *  Arguments
+    *  =========
+    *
+    *  JOBZ    (input) CHARACTER*1
+    *          = 'N':  Compute eigenvalues only;
+    *          = 'V':  Compute eigenvalues and eigenvectors.
+    *
+    *  UPLO    (input) CHARACTER*1
+    *          = 'U':  Upper triangle of A is stored;
+    *          = 'L':  Lower triangle of A is stored.
+    *
+    *  N       (input) INTEGER
+    *          The order of the matrix A.  N >= 0.
+    *
+    *  A       (input/output) REAL array, dimension (LDA, N)
+    *          On entry, the symmetric matrix A.  If UPLO = 'U', the
+    *          leading N-by-N upper triangular part of A contains the
+    *          upper triangular part of the matrix A.  If UPLO = 'L',
+    *          the leading N-by-N lower triangular part of A contains
+    *          the lower triangular part of the matrix A.
+    *          On exit, if JOBZ = 'V', then if INFO = 0, A contains the
+    *          orthonormal eigenvectors of the matrix A.
+    *          If JOBZ = 'N', then on exit the lower triangle (if UPLO='L')
+    *          or the upper triangle (if UPLO='U') of A, including the
+    *          diagonal, is destroyed.
+    *
+    *  LDA     (input) INTEGER
+    *          The leading dimension of the array A.  LDA >= max(1,N).
+    *
+    *  W       (output) REAL array, dimension (N)
+    *          If INFO = 0, the eigenvalues in ascending order.
+    *
+    *  WORK    (workspace/output) REAL array, dimension (LWORK)
+    *          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
+    *
+    *  LWORK   (input) INTEGER
+    *          The length of the array WORK.  LWORK >= max(1,3*N-1).
+    *          For optimal efficiency, LWORK >= (NB+2)*N,
+    *          where NB is the blocksize for SSYTRD returned by ILAENV.
+    *
+    *          If LWORK = -1, then a workspace query is assumed; the routine
+    *          only calculates the optimal size of the WORK array, returns
+    *          this value as the first entry of the WORK array, and no error
+    *          message related to LWORK is issued by XERBLA.
+    *
+    *  INFO    (output) INTEGER
+    *          = 0:  successful exit
+    *          < 0:  if INFO = -i, the i-th argument had an illegal value
+    *          > 0:  if INFO = i, the algorithm failed to converge; i
+    *                off-diagonal elements of an intermediate tridiagonal
+    *                form did not converge to zero.
+    */
+
+
+  integer N=this->Size[0];
+
+  // Copy Matrix (transposed) into Array A
+  real* A=new real[N*N];
+
+  float* mat=&Matrix[0];
+  int i,j;
+  for (j=0;j<N;j++)
+    for (i=0;i<N;i++)
+      {
+	A[j*N+i]=*mat;//this->GetDirectElement(i,j);
+	++mat;
+      }
+
+  integer LDA=N;
+  float *W=new real[N];
+
+  integer LWORK=5*N;
+  float *WORK=new float[LWORK];
+
+  integer INFO =0;
+
+  char md[2],mv[2];
+  if (U!=NULL)
+    strcpy(md,"V");
+  else
+    strcpy(md,"N");
+  strcpy(mv,"U");
+
+  // Call Eigenvalue routine
+  ssyev_(&md[0],&mv[0],&N,&A[0],&LDA,&W[0],&WORK[0],&LWORK, &INFO);
+
+  if (INFO!=0)
+    {
+      vtkErrorMacro(<<"Error INFO="<<INFO);
+      return 0;
+    }
+
+  D->Zeros(N,1);
+  for (i=0;i<N;i++)
+    D->SetDirectElement((N-1)-i,0,W[i]);
+
+  if (U!=NULL)
+    {
+      U->Zeros(N,N);
+
+      for (j=0;j<N;j++)
+	for (i=0;i<N;i++)
+	  U->SetDirectElement(i,(N-1)-j,A[j*N+i]);
+    }
+
+  delete [] WORK;
+  delete [] W;
+  delete [] A;
+
+  return 1;
+
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - -
+int vtkpxMatrix::BuildSmoothness(int ndim,int width,int height,int depth,float weight)
+{
+  int sz=width*height*depth;
+  this->Eye(sz*ndim);
+
+   int dim12=height*depth;
+   for (int k=0;k<depth;k++)
+     {
+       int kp=Icyclic(k+1,depth);
+       int km=Icyclic(k-1,depth);
+
+       for (int j=0;j<height;j++)
+	 {
+	   int jp=Icyclic(j+1,height);
+	   int jm=Icyclic(j-1,height);
+	   for (int i=0;i<width;i++)
+	     {
+	       int ip=Icyclic(i+1,width);
+	       int im=Icyclic(i-1,width);
+
+	       int ind1=i+j*width+k*dim12,l=0,ind2=0;
+
+	       if (width>1)
+		 {
+		   ind2=ip+j*width+k*dim12;
+		   for (l=0;l<ndim;l++)
+		     this->SetElement(ind1*ndim+l,ind2*ndim+l,0.5);
+
+		   ind2=im+j*width+k*dim12;
+		   for (l=0;l<ndim;l++)
+		     this->SetElement(ind1*ndim+l,ind2*ndim+l,0.5);
+		 }
+
+	       if (height>1)
+		 {
+		   ind2=i+jp*width+k*dim12;
+		   for (l=0;l<ndim;l++)
+		     this->SetElement(ind1*ndim+l,ind2*ndim+l,0.5);
+
+		   ind2=i+jm*width+k*dim12;
+		   for (l=0;l<ndim;l++)
+		     this->SetElement(ind1*ndim+l,ind2*ndim+l,0.5);
+		 }
+
+	       if (depth>1)
+		 {
+		   ind2=i+j*width+kp*dim12;
+		   for (l=0;l<ndim;l++)
+		     this->SetElement(ind1*ndim+l,ind2*ndim+l,0.5);
+
+		   ind2=i+j*width+km*dim12;
+		   for (l=0;l<ndim;l++)
+		     this->SetElement(ind1*ndim+l,ind2*ndim+l,0.5);
+		 }
+	     }
+	 }
+     }
+   return 1;
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - -
+int vtkpxMatrix::DoPCA(vtkpxMatrix* D,vtkpxMatrix* U,vtkpxMatrix* M)
+{
+  if (Matrix==NULL || D==NULL || U==NULL || M==NULL)
+    return 0;
+
+  if (this->Size[1]<2 || this->Size[0]<2)
+    {
+      vtkErrorMacro(<<"Cannot Do PCA matrix is too small");
+      return 0;
+    }
+
+  // First Compute Mean Vector and subtract it from the picture
+  M->Zeros(this->Size[0],1);
+  float scalefactor=1.0/float(this->Size[1]);
+  for (int ia=0;ia<this->Size[0];ia++)
+    {
+      float sum=0.0;
+      for (int ib=0;ib<this->Size[1];ib++)
+	sum+=this->GetDirectElement(ia,ib);
+      sum*=scalefactor;
+      M->SetDirectElement(ia,0,sum);
+      sum=-1.0*sum;
+      for (int ic=0;ic<this->Size[1];ic++)
+	this->AddToElement(ia,ic,sum);
+    }
+
+  // Next Compute S=(1/n) D*D^t  where D=this and temp=D^t
+  vtkpxMatrix* temp=vtkpxMatrix::New();
+  vtkpxMatrix* S=vtkpxMatrix::New();
+  temp->Copy(this);
+  temp->Transpose();
+
+  if (this->Size[1] < this->Size[2])
+    vtkpxMatrix::Multiply(temp,this,S);
+  else
+    vtkpxMatrix::Multiply(this,temp,S);
+  S->Scale(scalefactor);
+
+
+  // Next Diagonalize S to get eigenvalues D and "eigenvectors" in temp
+  if (this->Size[1] < this->Size[2])
+    {
+      S->Diagonalize(D,temp);
+      // Next Generate real eigenvectors  U = D*temp
+      vtkpxMatrix::Multiply(this,temp,U);
+    }
+  else
+    {
+      S->Diagonalize(D,U);
+    }
+
+  // Now normalize eigenvectors to have size 1 and scale eigenvalues appropriately
+  for (int j=0;j<U->Size[1];j++)
+    {
+      float sum=0.0;
+      for (int i=0;i<U->Size[0];i++)
+	{
+	  float v=U->GetDirectElement(i,j);
+	  sum+=v*v;
+	}
+      float magn=sqrt(sum);
+
+      if (magn>1e-4)
+	{
+	  for (int ib=0;ib<U->Size[0];ib++)
+	    {
+	      float v=U->GetDirectElement(ib,j);
+	      U->SetDirectElement(ib,j,v/magn);
+	    }
+	}
+      else
+	{
+	  D->SetElement(j,0,0.0);
+	  for (int ib=0;ib<U->Size[0];ib++)
+	    U->SetDirectElement(ib,j,0.0);
+
+	}
+    }
+
+  S->Delete();
+  temp->Delete();
+  return 1;
+
+}
+
+// ----------------------------------------------------------------------------------------------------
+int vtkpxMatrix::ExportToMatlab(const char* fname,const char* matrixname)
+{
+  vnl_matrix<float> M(this->Size[0],this->Size[1]);
+  for (unsigned i=0; i<M.rows(); ++i)
+    for (unsigned j=0; j<M.cols(); ++j)
+      M(i,j) = this->GetDirectElement(i,j);
+
+  //  vcl_cout << M << vcl_endl;
+  //  vnl_matlab_print(vcl_cout, M, "M") << vcl_endl;
+
+  vcl_ofstream f(fname);
+  if (vnl_matlab_write(f, (float const * const *)M.data_array(), M.rows(), M.cols(), matrixname))
+    {
+      f.close();
+      return 1;
+    }
+  return 0;
+}
+// ---------------------------------------------------------------------------------------
+int vtkpxMatrix::ImportFromMatlab(const char* fname,const char* matrixname)
+{
+  return this->ImportFromMatlab2(fname,matrixname,0);
+}
+// ---------------------------------------------------------------------------------------
+int vtkpxMatrix::ImportFromMatlab2(const char* fname,const char* matrixname,int debug)
+{
+  debug=(debug>0);
+  vcl_ifstream f(fname);
+
+  try
+    {
+      vnl_matlab_readhdr  pReader2(f);
+      if (pReader2.is_complex())
+	{
+	  f.close();
+	  	  if (debug)
+	    std::cout << " header is complex, matlab v6 \n";
+	  return this->ImportFromMatlabV6(fname,matrixname,debug);
+	}
+      f.close();
+
+    }
+  catch (std::bad_alloc)
+    {
+      std::cout << "Exception caught onto matlab v6\n";
+      return this->ImportFromMatlabV6(fname,matrixname,debug);
+    }
+
+  int count=0;
+  vnl_matlab_readhdr  pReader(f);
+  while (count < 20 )
+    {
+      if (debug)
+	{
+	  std::cout << "\n Reading " << fname << "\n";
+	  std::cout << "p.Name = " << pReader.name() << "Size=" << pReader.rows() << "x" <<  pReader.cols() << "\n";
+	}
+
+      if (vcl_strcmp(pReader.name(), matrixname)==0 || strlen(matrixname) == 0)
+	{
+	  if (debug)
+	    std::cout << "Found matrix " << matrixname << "\n";
+	  vnl_matrix<double> M(pReader.rows(), pReader.cols());
+	  pReader.read_data(M.data_array());
+
+	  this->Zeros(pReader.rows(), pReader.cols());
+	  for (unsigned i=0; i<M.rows(); ++i)
+	    for (unsigned j=0; j<M.cols(); ++j)
+	      this->SetDirectElement(i,j,M(i,j));
+	  f.close();
+	  return 1;
+	}
+
+      ++count;
+    }
+  f.close();
+  std::cerr << " matrix " << matrixname << "not found \n";
+  return 0;
+}
+// ------------------------------------------------------------------------------------------------------
+int vtkpxMatrix::ImportFromMatlabV6(const char* fname,const char* matrixname,int debug)
+{
+  //  debug=1;
+  znzFile fp = znzopen(fname,"rb",1);
+  char buffer[2000];
+  char name[2000];
+
+  znzread(buffer,1,116,fp);
+  if (debug)
+    std::cout << "Description = " << buffer << "\n";
+
+  znzread(buffer,1,8,fp);
+  int ok=1;
+  for (int ia=0;ia<=7;ia++)
+    {
+      int v=int(buffer[ia]);
+      if (!(v==0 || v==32))
+	{
+	  std::cerr << "We have a problem with ia=" << ia << "\n";
+	  ok=0;
+	  ia=9;
+	}
+    }
+
+  if (ok==0)
+    {
+      znzclose(fp);
+      return 0;
+    }
+  znzread(buffer,1,4,fp);
+  if (debug)
+    std::cout << "All Offset bytes are either zero or space OK!\n";
+
+
+  int done=0;
+  int totalread=128;
+  int count=0;
+
+  while (done==0)
+    {
+      vxl_int_32 dtype[2];
+      int n=znzread(dtype,sizeof(vxl_int_32),2,fp);
+      totalread+=8;
+      if (debug)
+	std::cout << "n = " << n << " totalread= " << totalread << "\n\n-----------------------------------------------------\n";
+      if (n<1)
+	{
+	  done=1;
+	}
+      else
+	{
+	  int swap=0;
+	  ++count;
+	  if (dtype[0]<0 || dtype[0]>1024)
+	    {
+	      dtype[0]=pxanaswapint(dtype[0]);
+	      dtype[1]=pxanaswapint(dtype[1]);
+	      swap=1;
+	    }
+	  if (debug)
+	    std::cout << "\n\n\n dtype = " << dtype[0] << " , numbytes = " << dtype[1] << "\n";
+	  if (dtype[0]!=14)
+	    {
+	      if (debug)
+		{
+		  std::cout << "Not a matrix skipping ahead " << dtype[1] << " bytes\n";
+		  std::cout << "Seaking ahead  " << dtype[1] << " bytes\n";
+		}
+	      int toread=dtype[1];
+
+
+	      // Add padding
+	      int tmp=8*int(toread/8);
+	      if (tmp<toread)
+		{
+		  toread=8+tmp;
+		  //		  std::cout  << "Adding padding from " << dtype[1] << " to " << toread << "\n";
+		}
+
+	      while (toread>0)
+		{
+		  int n=toread;
+		  if (toread>256) n=256;
+		  totalread+=znzread(buffer,1,n,fp);
+		  toread-=n;
+		}
+	      if (debug)
+		std::cout << "Total read = " << totalread << "\n";
+	    }
+	  else
+	    {
+	      if (debug)
+		std::cout << "Beginning to read matrix: \n";
+	      int bytes_read=znzread(buffer,1,16,fp);
+	      int cl=(int)buffer[8];
+	      if (debug)
+		fprintf(stderr,"in cl=%d\n",cl);
+	      //	      if (swap)
+	      //		cl=pxanaswapint(cl);
+
+	      vxl_int_32 flags[6],length[1];
+	      bytes_read+=sizeof(vxl_int_32)*znzread(flags,sizeof(vxl_int_32),5,fp);
+	      if (swap)
+		{
+		  length[0]=pxanaswapint(length[0]);
+		  for (int ic=0;ic<5;ic++)
+		    flags[ic]=pxanaswapint(flags[ic]);
+		}
+
+	      if (debug)
+		{
+		  fprintf(stderr,"Flags[0]=%d, flags[1]=%d\n",flags[0],flags[1]);
+		  fprintf(stderr,"Flags[4]=%d, flags[5]=%d\n",flags[4],flags[5]);
+		}
+
+	      // Check for use of small element format
+	      //
+	      int test=int(flags[4] / 65536 );
+	      if (debug)
+		std::cout << "***************** Is Small Element " << test << "\n";
+	      if (test==0)
+		{
+		  bytes_read+=sizeof(vxl_int_32)*znzread(length,sizeof(vxl_int_32),1,fp);
+		  //		  if (swap)
+		  //		    length[0]=pxanaswapint(length[0]);
+		  flags[5]=length[0];
+		  if (swap)
+		    flags[5]=pxanaswapint(flags[5]);
+		  bytes_read+=znzread(name,1,flags[5],fp);
+		  name[flags[5]]=(char)0;
+		  int rem=8-(flags[5]-int(flags[5]/8)*8);
+		  if (debug)
+		    std::cout << "Remainder " << rem << "\n";
+		  bytes_read+=znzread(buffer,1,rem,fp);
+		}
+	      else
+		{
+		  int nb=(flags[4] && 65535);
+		  if (debug)
+		    std::cout << "Small Element nb=" << nb << " test= " << int(test/65536) << "\n";
+		  bytes_read+=znzread(name,1,4,fp);
+		  name[nb]=(char)0;
+		  flags[5]=0;
+		}
+
+	      vxl_int_32 nfl[2];
+	      bytes_read+=sizeof(vxl_int_32)*znzread(nfl,sizeof(vxl_int_32),2,fp);
+	      if (swap)
+		{
+		  nfl[0]=pxanaswapint(nfl[0]);
+		  nfl[1]=pxanaswapint(nfl[1]);
+		}
+	      if (debug)
+		std::cout << "Final Flags = " << nfl[0] << "," << nfl[1] << "\n";
+
+
+	      int numrows=flags[2];
+	      int numcols=flags[3];
+	      if (debug)
+		{
+		  std::cout << "Dimensions = " << numrows << "x" << numcols << " cl = " << cl << "length = " << flags[5] << "\n";
+		  std::cout << "Name = " << name << "(bytes read= " << bytes_read << ")\n";
+		}
+	      int toread=dtype[1]-bytes_read;
+	      if (debug)
+		std::cout << "To read (1) = " << toread << "\n";
+	      int canread=0;
+
+	      if (vcl_strcmp(name, matrixname)==0 || strlen(matrixname) == 0)
+		{
+		  if ( (cl==7 || cl==6))
+		    {
+		      int numbytesneeded=4*numrows*numcols;
+		      if (cl==6)
+			numbytesneeded*=2;
+
+		      if (debug)
+			fprintf(stderr,"Need (%d) < (%d) to read matrix \n",numbytesneeded , toread);
+
+
+		      if (numbytesneeded<=toread)
+			{
+			  double* rd=NULL;
+			  float*  rf=NULL;
+
+			  if (cl==6)
+			    rd=new double[numrows];
+			  else
+			    rf=new float[numrows];
+
+
+			  if (debug)
+			    fprintf(stderr,"Beginning to read matrix (%d) < (%d) \n",numbytesneeded , toread);
+			  this->Zeros(numrows,numcols);
+			  for (int ib=0;ib<numcols;ib++)
+			    {
+			      if (cl==6)
+				{
+				  bytes_read+=sizeof(double)*znzread(rd,sizeof(double),numrows,fp);
+				  for (int ia=0;ia<numrows;ia++)
+				    if (swap)
+				      this->SetDirectElement(ia,ib,pxanaswapdouble(rd[ia]));
+				    else
+				      this->SetDirectElement(ia,ib,rd[ia]);
+				}
+			      else
+				{
+				  bytes_read+=sizeof(float)*znzread(rf,sizeof(float),numrows,fp);
+				  for (int ia=0;ia<numrows;ia++)
+				    if (swap)
+				      this->SetDirectElement(ia,ib,pxanaswapfloat(rf[ia]));
+				    else
+				      this->SetDirectElement(ia,ib,rf[ia]);
+				}
+			    }
+			  znzclose(fp);
+			  if (rd!=NULL) delete [] rd;
+			  if (rf!=NULL) delete [] rf;
+			  //			  this->Print(name);
+			  return 1;
+			  toread=dtype[1]-bytes_read;
+			  if (debug)
+			    std::cout << "To read part2 = " << toread << "(" << numbytesneeded << ")\n";
+			}
+		      else
+			{
+			  std::cerr << "\t\t\t can't read data not enough bytes\n";
+			}
+		    }
+		  std::cout << "Final To read (2) = " << toread << "\n";
+		}
+	      else
+		{
+		  if (debug)
+		    std::cout << "Not the matrix we are looking for\n";
+		}
+
+	      while (toread>0)
+		{
+		  int n=toread;
+		  if (toread>256) n=256;
+		  bytes_read+=znzread(buffer,1,n,fp);
+		  toread-=n;
+		}
+
+	      totalread+=bytes_read;
+	    }
+	}
+    }
+
+  znzclose(fp);
+
+  return 0;
+
+
+}
+// ------------------------------------------------------------------------
+void vtkpxMatrix::NormalizeColumns(int begin,int end)
+{
+  int size[2];  this->GetSize(size);
+  if (begin<0 || begin>=size[1])
+    begin=0;
+  if (end<0 || end >=size[1])
+    end=size[1]-1;
+  if (begin>end)
+    {
+      int tmp=end;
+      end=begin;
+      begin=end;
+    }
+
+  for (int col=begin;col<=end;col++)
+    {
+      double sum=0.0;
+      for (int row=0;row<size[0];row++)
+	sum+=pow(this->GetDirectElement(row,col),(float)2.0);
+      sum=sqrt(sum);
+      if (sum>0.0000001)
+	{
+	  for (int row=0;row<size[0];row++)
+	    this->SetDirectElement(row,col,this->GetDirectElement(row,col)/sum);
+	}
+    }
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxMatrix.h b/bioimagesuite30_src/Common/vtkpxMatrix.h
new file mode 100644
index 0000000..9ec2d28
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxMatrix.h
@@ -0,0 +1,337 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxMatrix.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxMatrix - stores and manipulates a 2D Matrix (float)
+// .SECTION Description
+// This class is an interface for manipulation of 2D Matrices. It is an interface to routines from
+// <a href="www.netlib.org/clapack">CLAPACK</a>
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// Requires <a href="www.netlib.org/clapack">CLAPACK</a> and <a href="www.netlib.org/f2c">f2c</a>
+// <br> Internal storage is 1-d array in column major order (i.e. Fortran convention)
+// .SECTION See Also
+//  vtkMath
+//
+#ifndef __vtkpxMatrix_h
+#define __vtkpxMatrix_h
+
+#include "vtkpxAbstractMatrix.h"
+#include "pxutil.h"
+
+class vtkpxMatrix : public vtkpxAbstractMatrix
+{
+public:
+  static vtkpxMatrix *New();
+  vtkTypeMacro(vtkpxMatrix,vtkpxAbstractMatrix);
+  
+
+  // Description:
+  // Get The Full Storage Size of the Matrix
+  vtkGetMacro(TrueSize,int);
+
+  // Description:
+  // Get The Total Size i.e. rows*columns
+  vtkGetMacro(TotalSize,int);
+
+  // Description:
+  // Squeeze Memory Usage to Minimum
+  virtual void Squeeze();
+
+  // Description:
+  // Routine to allocate memory 
+  virtual void Allocate(int rows,int columns);
+
+  // Description:
+  // Routine to allocate memory and set equal to zero (alias for allocate ala matlab)
+  virtual void Zeros(int rows,int cols);
+
+  // Description:
+  // Routines to allocate memory and set equal to one
+  virtual void Ones(int rows,int cols);
+
+  // Description:
+  // Routines to allocate memory for square matrix and initialize accordingly and set to identity
+  virtual void Eye(int rowcol);
+
+  // Description:
+  // Sets current matrix=identity matrix (if it is square)
+  virtual void Identity();
+
+  // Description:
+  // Set all elements = zero
+  virtual void Zero();
+
+  // Description:
+  // Set all elements = a
+  virtual void Fill(float a);
+
+  // Description:
+  // Print Matrix to stderr
+  virtual void InternalPrint();
+  virtual void Print(const char* message);
+
+  virtual void PrintRange(int row1,int row2,int col1,int col2);
+  virtual void PrintRange(const char* message,int row1,int row2,int col1,int col2);
+  virtual void Print(const char* message,const char* format);
+
+
+  // Description:
+  // Load/Save Matrix
+  virtual int Load(const char* fname);
+  virtual int Load(gzFile fin);
+
+  virtual int Save(const char* fname);
+  virtual int Save(const char* fname,const char* vname,int compression=0);
+  virtual int Save(gzFile fout,const char* varname);
+  virtual int Save(FILE*  fout,const char* varname);
+  virtual int ExportAFNI(char* fname,const char* formatstring);
+
+  // Description:
+  // Matlab Read/Write
+  virtual int ImportFromMatlab(const char* fname,const char* matrixname);
+  virtual int ImportFromMatlab2(const char* fname,const char* matrixname,int debug);
+  virtual int ExportToMatlab(const char* fname,const char* matrixname);
+
+  // Description:
+  // Copy oldmat
+  virtual void  Copy(vtkpxMatrix* oldmat);
+
+  // Description:
+  // Copy Part of  oldmat(x1:x2,y1:y2)
+  virtual void  Copy(vtkpxMatrix* oldmat,int x1,int x2,int y1,int y2);
+  virtual int   CopyInto(vtkpxMatrix* oldmat,int x1,int x2,int y1,int y2,int newx,int newy);
+
+  
+  // Description:
+  // Set Matrix from double** array (as used by vtkMath)
+  virtual void SetMatrix(double** mat,int x,int y);
+  virtual void  Copy(double** mat,int x,int y);
+  virtual void  Copy(double** mat,int x1,int x2,int y1,int y2);
+
+  //BTX
+  // Description:
+  // Get/Set Element in row=i column=j without range checking UNSAFE
+  inline virtual float  GetDirectElement(const int i,const int j)               { return Matrix[j*Size[0]+i] ;}
+  inline virtual void   SetDirectElement(const int i,const int j,const float v) { Matrix[j*Size[0]+i]=v;}
+  //ETX
+
+
+  // Description:
+  // Get Row
+  int  GetRow(int row,int maxval,float* values);  
+  int  GetRow(int row,int maxval,double* values);
+
+  int  GetColumn(int column,int maxval,float* values);
+  int  GetColumn(int column,int maxval,double* values);
+
+  int  SetRow(int row,int maxval,float* values);
+  int  SetRow(int row,int maxval,double* values);
+  int  SetColumn(int column,int maxval,float* values);
+  int  SetColumn(int column,int maxval,double* values);
+
+  // Description:
+  // Export matrix to new double** pointer for use in vtkMath
+  double**  GetNewMatrixPointer();
+
+  // Description:
+  // Multiply All elements in matrix by s
+  virtual void  Scale(float s);
+  virtual void  ScaleAdd(float multi,float offset);
+
+  // Description:
+  // Transpose Matrix
+  virtual void  Transpose();
+
+  // Description:
+  // Static methods: a+b=results, a*b=results 
+  static  void  Add(vtkpxMatrix* a,vtkpxMatrix* b,vtkpxMatrix* result);
+  static  void  Add(float wa,vtkpxMatrix* a,float wb,vtkpxMatrix* b,vtkpxMatrix* result);
+  static  void  Multiply(vtkpxMatrix* a,vtkpxMatrix* b,vtkpxMatrix* result);
+  static  int   IsEqual(vtkpxMatrix* a,vtkpxMatrix* b, double tolerance);
+  virtual void  MultiplyThisWith(vtkpxMatrix* b,vtkpxMatrix* result) { vtkpxMatrix::Multiply(this,b,result);}
+  
+
+  // Description:
+  // Static methods: a*b*c=results
+  static  void  Multiply3(vtkpxMatrix* a,vtkpxMatrix* b,vtkpxMatrix* c,vtkpxMatrix* result);
+
+  // Description:
+  // Static Method result=a'*b*a
+  static  void  MultiplyTripleProduct(vtkpxMatrix* a,vtkpxMatrix* b,vtkpxMatrix* result);
+
+  // Description:
+  // Normalize columns of matrix to make them magnitude 1
+  virtual void NormalizeColumns(int begin=-1,int end=-1);
+
+  // Description:
+  // Find Maximum values in matrix or column=col or row=row
+  virtual float Max();
+  virtual float MaxColumn(int col);
+  virtual float MaxRow(int row);
+
+  // Description:
+  // Sum Matrix
+  virtual float Sum();
+  virtual float Median();
+
+  // Description:
+  virtual float SumSquares();
+  virtual float SumMagnitude();
+
+  // Description:
+  // Output is vtkpxMatrix* containing sums of rows or columns
+  virtual vtkpxMatrix* RowSums();
+  virtual vtkpxMatrix* ColumnSums();
+
+
+  // Description:
+  // Diagonalization into Eigenvalues D and Eigenvectors U (D,U must be non-null);
+  virtual int Diagonalize(vtkpxMatrix* D,vtkpxMatrix* U);
+  virtual int Eigenvalues(vtkpxMatrix* D);
+  
+  // Description:
+  // Diagonalization into Eigenvalues D and Eigenvectors U (D,U must be non-null), M is the average vector
+  virtual int DoPCA(vtkpxMatrix* D,vtkpxMatrix* U,vtkpxMatrix* M);
+
+  // Description:
+  // Using lapack routines perform QR Decomposition (Q,R must be NON-NULL)
+  virtual int   QRDecomposition(vtkpxMatrix* Q,vtkpxMatrix* R);
+  virtual int   Q1Q2RDecomposition(vtkpxMatrix* Q1,vtkpxMatrix* Q2,vtkpxMatrix* R);
+
+  // Description:
+  // Invert matrix if it is square
+  virtual int   Invert();
+  
+  // Description:
+  // Solution of Least Squares and Weighted Least Squares Problems
+  // of the form Min |b-Ax|2 this=A
+  // and of the form | W(b-Ax)|2 this=A
+  virtual int SolveLeastSquares(vtkpxMatrix* B,vtkpxMatrix* X);
+  virtual int SolveWeightedLeastSquares(vtkpxMatrix* W,vtkpxMatrix* B,vtkpxMatrix* X);
+
+  // Description:
+  // Solution of Linear System of Equations of the form
+  // Ax=b where this=A
+  virtual int SolveLinearSystem(vtkpxMatrix* B,vtkpxMatrix* X);
+  virtual int SolveSymmetricLinearSystem(vtkpxMatrix* B,vtkpxMatrix* X);
+  virtual int SolveUpperSymmetricLinearSystem(vtkpxMatrix* B,vtkpxMatrix* X);
+  virtual int SolveLowerSymmetricLinearSystem(vtkpxMatrix* B,vtkpxMatrix* X);
+
+  // Description:
+  // Succesive Over-relaxation code set omeaga=1.0 for Gaus-Seidel and thr<0.01
+  virtual int SOR(vtkpxMatrix* B,vtkpxMatrix* X,float thr,float omega);
+
+  // Description:
+  // Create Smoothness Matrix
+  virtual int BuildSmoothness(int ndim,int width,int height,int depth,float weight);
+
+  //BTX
+  virtual float* GetMatrixPointer() { return Matrix;}
+
+  // -----------------------------------------------------
+  // Description:
+  // RPM Related Stuff;
+  virtual void MapPoints(vtkpxMatrix* Y,vtkpxMatrix* VY);
+  virtual void NormalizeMixtureMatrix(vtkpxMatrix* M_Outliers_Row);
+  virtual void NormalizeRPMMatrix(vtkpxMatrix* M_Outliers_Row,vtkpxMatrix* M_Outliers_Column);
+
+
+  // -----------------------------------------------------
+  // Static Functions :: Can be called from other C++ Code
+  // -----------------------------------------------------
+
+  static double** NewMatrix(int x, int y) ;
+  static void     DeleteMatrix(double** m, int x, int vtkNotUsed(y));
+  static void     FillMatrixWithZeros(double** m, int x, int y);
+  static void     MatrixMultiply(double** a, double** b, double** c,int ar, int ac, int br, int bc) ;
+  static void     PrintMatrix(double **m, int x, int y);
+
+  static void     InPlaceTransposeMatrix(double** m,int x, int y);
+  static double** TransposeMatrix(double** m,int x, int y);
+
+  static void     CopyMatrix(double** dest,double** src,int x ,int y);
+  static double** CopyMatrix(double** src,int x ,int y);
+
+  static double** SubMatrix(double** src,int x1,int x2,int y1,int y2);
+  //ETX 
+
+protected:
+
+  //BTX
+  vtkpxMatrix();
+  virtual ~vtkpxMatrix();
+
+  vtkpxMatrix(const vtkpxMatrix&) {};
+  void operator=(const vtkpxMatrix&) {};
+
+  int TrueSize;
+  int TotalSize;
+  float* Matrix;
+
+  int InternalSolveLinearSystem(vtkpxMatrix* B,vtkpxMatrix* X,int symmetric);
+
+
+  //ETX
+
+  // Description
+  // Unfinished for now -- but mostly works
+  virtual int ImportFromMatlabV6(const char* fname,const char* matrixname,int debug=0);
+
+  // Description
+  // For cleaning up tab or , delimited files
+  void ReplaceWithSpace(char* line,const char* t);
+};
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkpxOpenIGTLinkClient.cpp b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkClient.cpp
new file mode 100644
index 0000000..31fb579
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkClient.cpp
@@ -0,0 +1,421 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+// OpenIGTLink specific includes
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkpxOpenIGTLinkClient.h"
+#include "vtkMath.h"
+#include "vtkPointData.h"
+#include "igtl_header.h"
+#include "igtl_transform.h"
+#include "igtl_image.h"
+#include "igtl_util.h"
+#include <string.h>
+
+vtkpxOpenIGTLinkClient* vtkpxOpenIGTLinkClient::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxOpenIGTLinkClient");
+  if(ret)
+    {
+      return (vtkpxOpenIGTLinkClient*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxOpenIGTLinkClient;
+}
+
+// Construct object to extract all of the input data.
+vtkpxOpenIGTLinkClient::vtkpxOpenIGTLinkClient()
+{
+  this->Connector=vtkClientSocket::New();
+  this->ToolName=NULL;
+  this->SetToolName("BioImageSuite");
+  this->IsConnected=0;
+  this->InternalPoints=vtkPoints::New();
+  this->InternalPoints->SetNumberOfPoints(2);
+  vtkSocketController* dummy=vtkSocketController::New();
+  dummy->Initialize();
+  dummy->Delete();
+  this->Observer=vtkpxOpenIGTLinkClientObserver::New();
+}
+
+vtkpxOpenIGTLinkClient::~vtkpxOpenIGTLinkClient()
+{
+  if (this->ToolName!=NULL)
+    delete [] this->ToolName;
+
+  this->CloseConnection();
+  //  fprintf(stderr,"Deleting Connector\n");
+  if (this->Connector)
+    this->Connector->Delete();
+
+  // fprintf(stderr,"Deleting Internal Points\n");
+  this->InternalPoints->Delete();
+
+  if (this->Observer!=NULL)
+    this->Observer->Delete();
+}
+// ---------------------------------------------------------------------------
+
+void vtkpxOpenIGTLinkClient::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkObject::PrintSelf(os,indent);
+
+  os << indent << "  IsConnected " << this->IsConnected << "\n";
+  os << indent << "  ToolName " << this->ToolName << "\n";
+  os << indent << "  Connector " << this->Connector << "\n";
+}
+// ---------------------------------------------------------------------------
+int   vtkpxOpenIGTLinkClient::InitializeConnection(char* server,int port)
+{
+  if (this->IsConnected)
+    this->CloseConnection();
+
+  int r=this->Connector->ConnectToServer(server,port);
+  if (r!=0)
+    {
+      this->IsConnected=0;
+      //vtkErrorMacro("Cannot connect to the server." << server << ":" << port << std::endl);
+      return 0;
+    }
+  //  fprintf(stderr,"r=%d\n",r);
+
+
+  this->Observer->AttachSocketAndClient(this->Connector,this);
+  this->IsConnected=1;
+  return 1;
+}
+
+// ---------------------------------------------------------------------------
+int vtkpxOpenIGTLinkClient::HandleErrorFromSocket()
+{
+  // This is to keep the vtkErrorMacro from being called ....
+  //  vtkDebugMacro(<<"++ Failed to send data .., ignoring \n");
+  fprintf(stderr,"++ Failed to send data .., disconnecting \n");
+  this->CloseConnection();
+  return 0;
+}
+// ---------------------------------------------------------------------------
+int   vtkpxOpenIGTLinkClient::CloseConnection()
+{
+  if (this->IsConnected && this->Connector!=NULL)
+    {
+      //      vtkDebugMacro(<<"Closing Socket\n");
+      fprintf(stderr,"Closing Socket\n");
+      this->Connector->CloseSocket();
+      this->IsConnected=0;
+      //      fprintf(stderr,"Closing Socket Done\n");
+      return 1;
+    }
+  this->IsConnected=0;
+  return 0;
+}
+// ---------------------------------------------------------------------------
+int vtkpxOpenIGTLinkClient::SendToolLocation(vtkPoints* pts,vtkImageData* img,int slicermode)
+{
+  if (img==NULL || pts==0)
+    {
+      vtkErrorMacro(<<"Bad Inputs to Send Tool Location\n");
+      return 0;
+    }
+
+
+  double spa[3]; img->GetSpacing(spa);
+  double ori[3]; img->GetOrigin(ori);
+  int    dim[3]; img->GetDimensions(dim);
+
+  int np=pts->GetNumberOfPoints();
+
+  if (  this->InternalPoints->GetNumberOfPoints()!=np)
+    this->InternalPoints->SetNumberOfPoints(np);
+
+  double mx[3];
+  for (int ia=0;ia<=2;ia++)
+    mx[ia]=double(dim[ia]-1)*0.5;
+
+  for (int i=0;i<np;i++)
+    {
+      double cx[3]; pts->GetPoint(i,cx);
+      for (int ia=0;ia<=2;ia++)
+	{
+	  if (slicermode>0)
+	    {
+	      // flip LPS->RAS
+	      //	      fprintf(stderr,"\n\n\nBeginning ia=%d,cx[%d]=%.2f\n",ia,ia,cx[ia]);
+	      // cx[ia]=cx[ia]-ori[ia];
+	      //	      fprintf(stderr,"Origin shift cx[%d]=%.2f\n",ia,cx[ia]);
+	      cx[ia]=cx[ia]/spa[ia];
+	      //	      fprintf(stderr," / spa cx[%d]=%.2f\n",ia,cx[ia]);
+	      if (ia<2)
+		cx[ia]=double(dim[ia]-1)-cx[ia];
+		    
+	      if (slicermode==2)
+		cx[ia]=cx[ia]-mx[ia];
+	  
+	      cx[ia]=cx[ia]*spa[ia];
+	      //	      fprintf(stderr," *spa cx[%d]=%.2f\n",ia,cx[ia]);
+	      //cx[ia]=cx[ia]+ori[ia];
+	      //	      fprintf(stderr," +ori cx[%d]=%.2f\n",ia,cx[ia]);
+	    }
+	}
+      //      fprintf(stderr,"**** Setting Point %d (%.2f %.2f %.2f)\n",i,cx[0],cx[1],cx[2]);
+      this->InternalPoints->SetPoint(i,cx);
+    }
+
+  return this->SendToolLocation(this->InternalPoints);
+}
+// ---------------------------------------------------------------------------
+int vtkpxOpenIGTLinkClient::SendToolLocation(vtkPoints* pts)
+{
+  vtkDebugMacro(<<"In Send Tool Location " << this->IsConnected << "\n");
+
+  if (this->IsConnected==0 || this->Connector==NULL)
+    return 0;
+
+  if (pts==NULL)
+    return 0;
+
+  if (pts->GetNumberOfPoints()<1)
+    return 0;
+
+	
+
+
+  igtl_float32 transform[12];    
+  if (pts->GetNumberOfPoints()<2)
+    {
+      double x[3]; pts->GetPoint(0,x);
+      transform[0] = 1.0;   transform[3] = 0;     transform[6] = 0;   transform[9] =  x[0];
+      transform[1] = 0;     transform[4] = 1.0;   transform[7] = 0;   transform[10] = x[1];  
+      transform[2] = 0;     transform[5] = 0;     transform[8] = 1.0; transform[11] = x[2];
+      vtkDebugMacro(<<"Sending x= " << x[0] << "," << x[1] << "," << x[2] << "\n");
+    }
+  else
+    {
+      // ----------------------- Rotation ------------------
+      // Create rotation matrix
+      // Goal is to map
+      // [ 0 0 1 ]'   to direction p1-p2
+      //
+      //
+      double m[3],p[3];
+      
+      double base[3]; pts->GetPoint(0,base);
+      double top[3];  pts->GetPoint(1,top);
+      //	  fprintf(stderr,"base=%.2f,%.2f,%.2f\n",base[0],base[1],base[2]);
+      //  fprintf(stderr,"top=%.2f,%.2f,%.2f\n",top[0],top[1],top[2]);
+
+      
+      double n[3];
+      for (int i=0;i<=2;i++)
+	{
+	  // m is along z-axis
+	  m[i]=base[i]-top[i];
+	  // n[i] is a random vector not parallel to m -- essentially rotation about
+	  // y-axis is a free parameter!
+	  n[i]=m[i]+0.2*double(i);
+	}
+      
+
+      // n is fake y-axis
+      // m is real z-axis
+      //
+      // nxm = p (x-axis)
+      // mxp = n
+
+      //      n[0]=0.0; n[1]=1.0; n[2]=0.0;
+      double dist=vtkMath::Normalize(n);      vtkMath::Normalize(m);
+      vtkMath::Cross(n,m,p);      vtkMath::Normalize(p); 
+      // --> p is perpendicular to both n and m
+      vtkMath::Cross(m,p,n);      vtkMath::Normalize(n); 
+      // --> m is perpendicular to both p and n
+      // Now p n and m are a right handed orthogonal set
+      
+      /*      p[0]=1.0;  p[1]=0.0;      p[2]=0.0;
+      n[0]=0.0;  n[1]=1.0;      n[2]=0.0;
+      m[0]=0.0;  m[1]=0.0;      m[2]=1.0;*/
+     
+	
+
+
+      transform[0] = p[0];     transform[3] = n[0];     transform[6] = m[0];   transform[9] =  base[0];
+      transform[1] = p[1];     transform[4] = n[1];     transform[7] = m[1];   transform[10] = base[1];  
+      transform[2] = p[2];     transform[5] = n[2];     transform[8] = m[2];   transform[11] = base[2];
+
+      //      fprintf(stderr," [ %.2f %.2f %.2f %.2f ]\n",transform[0],transform[3],transform[6],transform[9]);
+      //      fprintf(stderr," [ %.2f %.2f %.2f %.2f ]\n",transform[1],transform[4],transform[7],transform[10]);
+      //      fprintf(stderr," [ %.2f %.2f %.2f %.2f ]\n",transform[2],transform[5],transform[8],transform[11]);
+    }
+
+ 
+
+  igtl_transform_convert_byte_order(transform);  /* convert endian if necessary */
+ 
+  /********** general header **********/  
+  igtl_header header;
+  igtl_uint64 crc = crc64(0, 0, 0LL);          /* initial crc */
+  header.version   = IGTL_HEADER_VERSION;
+  header.timestamp = 0;
+  header.body_size = IGTL_TRANSFORM_SIZE;
+  header.crc       = crc64((unsigned char*)transform, IGTL_TRANSFORM_SIZE, crc);
+  
+  strncpy(header.name, "TRANSFORM", 12);       /* Device Type: should be "TRANSFORM" */
+  strncpy(header.device_name, this->ToolName, 20);    /* Device name */
+  
+  igtl_header_convert_byte_order(&header);   /* convert endian if necessary */
+
+  //  Then send package (in case of BSD socket)
+  this->Connector->Send((void*) &header, IGTL_HEADER_SIZE);
+  this->Connector->Send((void*) transform, IGTL_TRANSFORM_SIZE);
+  return 1;
+}
+// ---------------------------------------------------------------------------
+int vtkpxOpenIGTLinkClient::SendImage(vtkImageData* img)
+{
+  if (this->IsConnected==0  || this->Connector==NULL)
+    return 0;
+
+  if (img==NULL)
+    return 0;
+
+  enum {    COORDINATE_LPS,    COORDINATE_RAS  };
+  enum {    ENDIAN_BIG,    ENDIAN_LITTLE  };
+  enum {    DTYPE_SCALAR = 1,    DTYPE_VECTOR = 2  };
+
+  // This matches VTK -- see vtkType.h !
+  //#define VTK_CHAR            2
+  //#define VTK_UNSIGNED_CHAR   3
+  //#define VTK_SHORT           4
+  //#define VTK_UNSIGNED_SHORT  5
+  //#define VTK_INT             6
+  //#define VTK_UNSIGNED_INT    7
+
+  enum {    TYPE_INT8   = 2,    TYPE_UINT8  = 3,    TYPE_INT16  = 4,    TYPE_UINT16 = 5,    TYPE_INT32  = 6,    TYPE_UINT32 = 7  };
+
+  int dimensions[3]; img->GetDimensions(dimensions);
+  int imagesize=dimensions[0]*dimensions[1]*dimensions[2];
+
+  int s = IGTL_IMAGE_HEADER_SIZE + imagesize;
+  unsigned char* m_ImageHeader = new unsigned char [s];
+  unsigned char* m_Body   = &m_ImageHeader[IGTL_IMAGE_HEADER_SIZE];
+  int m_PackSize = s;
+
+  igtl_image_header* image_header = (igtl_image_header*)m_ImageHeader;
+  image_header->version     = IGTL_IMAGE_HEADER_VERSION;
+  image_header->data_type   = DTYPE_SCALAR;
+
+  // We are focing everything to UINT8 ... see scaling below! (VVLink is almost always UINT8)
+  image_header->scalar_type = TYPE_UINT8;
+  image_header->endian      = ENDIAN_BIG;
+  image_header->coord       = COORDINATE_RAS;
+  image_header->size[0]     = dimensions[0];
+  image_header->size[1]     = dimensions[1];
+  image_header->size[2]     = dimensions[2];
+  image_header->subvol_offset[0] = 0;
+  image_header->subvol_offset[1] = 0;
+  image_header->subvol_offset[2] = 0;
+  image_header->subvol_size[0] = dimensions[0];
+  image_header->subvol_size[1] = dimensions[1];
+  image_header->subvol_size[2] = dimensions[2];
+
+  float origin[3], norm_i[3], norm_j[3], norm_k[3], spacing[3];
+
+  
+
+  for (int i = 0; i < 3; i ++) 
+    {
+      norm_i[i] = -1.0*float (i==0);
+      norm_j[i] = -1.0*float (i==1);
+      norm_k[i] = 1.0*float (i==2);
+      spacing[i] = float(img->GetSpacing()[i]);
+      origin[i] = 0.0;//(float(dimensions[i]-1)*0.5*spacing[i]);
+      //      if (i==0 || i==2)
+      //	origin[i]=-origin[i];
+    }
+
+
+  // First Header
+  igtl_image_set_matrix(spacing, origin,
+                        norm_i, norm_j, norm_k,
+                        image_header);
+
+  /*  fprintf(stderr,"****************\nSpacing = %.3f %.3f %.3f\n",spacing[0],spacing[1],spacing[2]);
+      fprintf(stderr,"Origin  = %.3f %.3f %.3f\n",origin[0],origin[1],origin[2]);
+      fprintf(stderr,"Norm_i  = %.3f %.3f %.3f\n",norm_i[0],norm_i[1],norm_i[2]);
+      fprintf(stderr,"Norm_j  = %.3f %.3f %.3f\n",norm_j[0],norm_j[1],norm_j[2]);
+      fprintf(stderr,"Norm_k  = %.3f %.3f %.3f\n",norm_k[0],norm_k[1],norm_k[2]);*/
+
+  igtl_image_convert_byte_order(image_header);
+
+  
+  // Next Data
+
+  vtkDataArray* dat=img->GetPointData()->GetScalars();
+  int nt=dat->GetNumberOfTuples();
+  double r[2]; dat->GetRange(r);
+  double scale=255.0/(r[1]-r[0]);
+  if (scale>=1.0)
+    scale=1.0;
+  double shift=r[0];
+
+  for (int i=0;i<nt;i++)
+    m_Body[i]=(unsigned char)(scale*dat->GetComponent(i,0)+shift);
+  
+
+  // 
+
+  //  Sending
+  //  First the IMAGE_HEADER
+  //
+  igtl_header header;
+  igtl_uint64 crc = crc64(0, 0, 0LL);          /* initial crc */
+  header.version   = IGTL_HEADER_VERSION;
+  header.timestamp = 0;
+  header.body_size = IGTL_IMAGE_HEADER_SIZE+imagesize;
+
+  header.crc       = crc64(m_ImageHeader, IGTL_IMAGE_HEADER_SIZE+imagesize, crc);
+  strncpy(header.name, "IMAGE", 12);       /* Device Type: should be "TRANSFORM" */
+  strncpy(header.device_name, "VVLinkImage", 20);    /* Device name */
+  igtl_header_convert_byte_order(&header);   /* convert endian if necessary */
+
+  //  Then send IGTL Header (in case of BSD socket)
+  this->Connector->Send((void*) &header, IGTL_HEADER_SIZE);
+
+  // This sends image header + image
+  this->Connector->Send((void*) m_ImageHeader, IGTL_IMAGE_HEADER_SIZE+imagesize);
+
+  delete [] m_ImageHeader;
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxOpenIGTLinkClient.h b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkClient.h
new file mode 100644
index 0000000..9c45779
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkClient.h
@@ -0,0 +1,100 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+#ifndef __vtkpxOpenIGTLinkClient_h
+#define __vtkpxOpenIGTLinkClient_h
+
+#include "vtkObject.h"
+#include "vtkPoints.h"
+#include "vtkImageData.h"
+#include "vtkClientSocket.h"
+#include "vtkSocketController.h"
+#include "vtkpxOpenIGTLinkClientObserver.h"
+
+class vtkpxOpenIGTLinkClient : public vtkObject
+{
+public:
+  static vtkpxOpenIGTLinkClient *New();
+  vtkTypeMacro(vtkpxOpenIGTLinkClient,vtkObject);
+
+  // Description:
+  // Print Self
+  void PrintSelf(ostream& os, vtkIndent indent);  
+
+  // Description:
+  // Initialize and Close Connection
+  virtual int   InitializeConnection(char* server,int port);
+  virtual int   CloseConnection();
+
+
+  // Description:
+  // Callback for Handling Error from Sending Data
+  virtual int HandleErrorFromSocket();
+
+  // Description:
+  // Set Name of this "device"
+  vtkSetStringMacro(ToolName);
+  vtkGetStringMacro(ToolName);
+  vtkGetMacro(IsConnected,int);
+
+  // Description:
+  // Send Tool Location
+  virtual int SendToolLocation(vtkPoints* pts);
+  virtual int SendToolLocation(vtkPoints* pts,vtkImageData* img,int slicermode);
+
+  // Description:
+  // Send Image
+  virtual int SendImage(vtkImageData* img);
+  
+  // Description:
+  // 
+
+
+protected:
+
+  vtkpxOpenIGTLinkClient();
+  ~vtkpxOpenIGTLinkClient();
+  vtkpxOpenIGTLinkClient(const vtkpxOpenIGTLinkClient&) {};
+  void operator=(const vtkpxOpenIGTLinkClient&) {};
+
+  // Use BTX..ETX to avoid parsing for tcl
+  //BTX
+  vtkClientSocket* Connector;
+  vtkPoints* InternalPoints;
+  char* ToolName;
+  int  IsConnected;
+  vtkpxOpenIGTLinkClientObserver* Observer;
+  //ETX
+
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkpxOpenIGTLinkClientObserver.cpp b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkClientObserver.cpp
new file mode 100644
index 0000000..06dc3cd
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkClientObserver.cpp
@@ -0,0 +1,66 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxOpenIGTLinkClientObserver.h"
+#include "vtkpxOpenIGTLinkClient.h"
+
+vtkpxOpenIGTLinkClientObserver* vtkpxOpenIGTLinkClientObserver::New()
+{ 
+  return new vtkpxOpenIGTLinkClientObserver; 
+}
+
+vtkpxOpenIGTLinkClientObserver::vtkpxOpenIGTLinkClientObserver()
+{
+  this->Socket=NULL;
+  this->Client=NULL;
+}
+
+void vtkpxOpenIGTLinkClientObserver::AttachSocketAndClient(vtkSocket* in_socket,vtkpxOpenIGTLinkClient* in_client)
+{
+  this->Socket=in_socket;
+  this->Client=in_client;
+  this->Socket->AddObserver(vtkCommand::ErrorEvent,this);
+}
+
+void vtkpxOpenIGTLinkClientObserver::Execute(vtkObject *caller,unsigned long event, void* vtkNotUsed(v))
+{
+  if (this->Client==NULL || this->Socket==NULL)
+    return;
+
+  // For no simply handle error
+  if (caller)
+    {
+      if (event == vtkCommand::ErrorEvent)
+	this->Client->HandleErrorFromSocket();
+    }
+}
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxOpenIGTLinkClientObserver.h b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkClientObserver.h
new file mode 100644
index 0000000..0a604bb
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkClientObserver.h
@@ -0,0 +1,68 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkpxOpenIGTLinkClientObserver -- trap error from vtkpxOpenIGTLinkClient
+
+#ifndef __vtkpxOpenIGTLinkClientObserver_h
+#define __vtkpxOpenIGTLinkClientObserver_h
+
+#include "vtkObjectFactory.h"
+#include "vtkCommand.h"
+#include "vtkObject.h"
+#include "vtkSocket.h"
+
+class vtkpxOpenIGTLinkClient;
+
+
+class vtkpxOpenIGTLinkClientObserver : public vtkCommand
+{
+public:
+
+  static vtkpxOpenIGTLinkClientObserver *New();
+  vtkTypeMacro(vtkpxOpenIGTLinkClientObserver,vtkCommand);
+  virtual void Execute(vtkObject *caller,unsigned long event, void* vtkNotUsed(v));
+  virtual void AttachSocketAndClient(vtkSocket* socket,vtkpxOpenIGTLinkClient* client);
+
+protected:
+
+  vtkpxOpenIGTLinkClientObserver();
+
+  vtkpxOpenIGTLinkClientObserver(const vtkpxOpenIGTLinkClientObserver&) {};
+  void operator=(const vtkpxOpenIGTLinkClientObserver&) {};
+
+  vtkSocket*            Socket;
+  vtkpxOpenIGTLinkClient* Client;
+};
+
+
+ 
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkpxOpenIGTLinkServer.cpp b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkServer.cpp
new file mode 100644
index 0000000..016f8d3
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkServer.cpp
@@ -0,0 +1,646 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+// OpenIGTLink specific includes
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkpxOpenIGTLinkServer.h"
+#include "vtkSocketController.h"
+#include "vtkMath.h"
+#include "vtkPointData.h"
+#include "vtkCriticalSection.h"
+#include "vtkMutexLock.h"
+#include "vtkCommand.h"
+#include "igtl_header.h"
+#include "igtl_transform.h"
+#include "igtl_image.h"
+#include "igtl_util.h"
+#include "igtl_types.h"
+#include <string.h>
+
+
+vtkpxOpenIGTLinkServer* vtkpxOpenIGTLinkServer::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxOpenIGTLinkServer");
+  if(ret)
+    {
+      return (vtkpxOpenIGTLinkServer*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxOpenIGTLinkServer;
+}
+
+// Construct object to extract all of the input data.
+vtkpxOpenIGTLinkServer::vtkpxOpenIGTLinkServer()
+{
+  this->Connector=NULL;
+  this->Observer=NULL;
+  this->ClientSocket=NULL;
+
+  this->IsServerActive=0;
+  this->IsServerConnected=0;
+  this->ThreadActive=0;
+  this->Port=18946;
+
+  this->LastReceivedImage=NULL;
+  this->TempImage=NULL;
+
+
+  this->ImageSemaphore = vtkCriticalSection::New();
+  this->LastReceivedImageTime.Modified();
+
+  this->LastReceivedImageTransform=vtkTransform::New();
+  this->LastReceivedImageTransform->Identity();
+  this->TempImageTransform=vtkTransform::New();
+  this->TempImageTransform->Identity();
+
+
+  this->LastReceivedTransform=vtkTransform::New();
+  this->LastReceivedTransform->Identity();
+  this->TempTransform=vtkTransform::New();
+  this->TempTransform->Identity();
+
+
+  this->TransformSemaphore = vtkCriticalSection::New();
+  this->LastReceivedTransformTime.Modified();
+
+  this->ServerThreader=vtkMultiThreader::New();
+  this->ActivelyReceiving=0;
+  this->ThreadReceivingData=0;
+  this->ThreadReceivingDataId=-1;
+
+  // Get Windows networking initialized!
+  vtkSocketController* dummy=vtkSocketController::New();
+  dummy->Initialize();
+  dummy->Delete();
+
+}
+
+// ----------------------------------------------------------------------
+
+vtkpxOpenIGTLinkServer::~vtkpxOpenIGTLinkServer()
+{
+  if (this->Connector!=NULL)
+    this->Connector->Delete();
+
+  if (this->Observer!=NULL)
+    this->Observer->Delete();
+
+  this->ServerThreader->Delete();
+
+  if (this->LastReceivedImage!=NULL)
+    this->LastReceivedImage->Delete();
+  if (this->TempImage!=NULL)
+    this->TempImage->Delete();
+  this->ImageSemaphore->Delete();
+
+  this->LastReceivedImageTransform->Delete();
+  this->TempImageTransform->Delete();
+
+
+  this->LastReceivedTransform->Delete();
+  this->TempTransform->Delete();
+
+
+  this->TransformSemaphore->Delete();
+
+}
+// ---------------------------------------------------------------------------
+vtkImageData* vtkpxOpenIGTLinkServer::GetLastReceivedImage()
+{
+  vtkImageData* retval=NULL;
+
+  this->ImageSemaphore->Lock();
+  // ++++++++++++++++++++
+  if (this->TempImage!=NULL)
+    {
+      if (this->LastReceivedImage==NULL)
+	this->LastReceivedImage=vtkImageData::New();
+      this->LastReceivedImage->ShallowCopy(this->TempImage);
+      retval=this->LastReceivedImage;
+    }
+  // ++++++++++++++++++++
+  this->ImageSemaphore->Unlock();
+  return retval;
+}
+
+
+vtkTransform* vtkpxOpenIGTLinkServer::GetLastReceivedImageTransform()
+{
+  this->ImageSemaphore->Lock();
+  // ++++++++++++++++++++
+  this->LastReceivedImageTransform->Identity();
+  this->LastReceivedImageTransform->Concatenate(this->TempImageTransform);
+  // ++++++++++++++++++++
+  this->ImageSemaphore->Unlock();
+
+  return this->LastReceivedImageTransform;
+}
+
+ 
+vtkTransform* vtkpxOpenIGTLinkServer::GetLastReceivedTransform()
+{
+  this->TransformSemaphore->Lock();
+  // ++++++++++++++++++++
+  this->LastReceivedTransform->Identity();
+  this->LastReceivedTransform->Concatenate(this->TempTransform);
+  // ++++++++++++++++++++
+  this->TransformSemaphore->Unlock();
+
+  return this->LastReceivedTransform;
+}
+
+void vtkpxOpenIGTLinkServer::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkObject::PrintSelf(os,indent);
+
+  os << indent << "  IsServerActive " << this->IsServerActive << std::endl;
+  os << indent << "  IsServerConnected " << this->IsServerConnected << std::endl;
+  os << indent << "  Port " << this->Port << std::endl;
+
+  os << indent << "  LastReceivedImageTime " << this->LastReceivedImageTime << std::endl;
+  os << indent << "  LastReceivedImage " << this->LastReceivedImage << std::endl;
+  os << indent << "  TempImage " << this->TempImage << std::endl;
+  os << indent << "  ImageSemaphore " << this->ImageSemaphore << std::endl;
+
+  os << indent << "  LastReceivedTransformTime " << this->LastReceivedTransformTime << std::endl;
+  os << indent << "  LastReceivedTransform " << this->LastReceivedTransform << std::endl;
+  os << indent << "  TempTransform " << this->TempTransform << std::endl;
+  os << indent << "  TransformSemaphore " << this->TransformSemaphore << std::endl;
+
+  os << indent << "  Connector " << this->Connector << std::endl;
+  os << indent << "  Observer " << this->Observer << std::endl;
+  os << indent << "  ClientSocket " << this->ClientSocket << std::endl;
+}
+
+// -------------------------------------------------------------------------
+unsigned long int vtkpxOpenIGTLinkServer::GetLastReceivedImageTime() 
+{
+  this->ImageSemaphore->Lock();
+  // ++++++++++++++++++++
+  unsigned long a=this->LastReceivedImageTime.GetMTime();
+  // ++++++++++++++++++++
+  this->ImageSemaphore->Unlock();
+  return a;
+}
+
+unsigned long int vtkpxOpenIGTLinkServer::GetLastReceivedTransformTime() 
+{
+  this->TransformSemaphore->Lock();
+  // ++++++++++++++++++++
+  unsigned long a=this->LastReceivedTransformTime.GetMTime();
+  // ++++++++++++++++++++
+  this->TransformSemaphore->Unlock();
+  return a;
+}
+
+// ---------------------------------------------------------------------------
+
+void vtkpxOpenIGTLinkServer::SetLastReceivedTimeAndType(int tp)
+{
+  if (tp==0)
+    {
+      this->TransformSemaphore->Lock();
+      // ++++++++++++++++++++
+      this->LastReceivedTransformTime.Modified();
+      // ++++++++++++++++++++
+      this->TransformSemaphore->Unlock();
+    }
+  else
+    {
+      this->ImageSemaphore->Lock();
+      // ++++++++++++++++++++
+      this->LastReceivedImageTime.Modified();
+      // ++++++++++++++++++++
+      this->ImageSemaphore->Unlock();
+    }
+  this->InvokeEvent(vtkCommand::UserEvent,NULL);
+}
+
+// this function runs in an alternate thread to asyncronously grab frames
+// ---------------------------------------------------------------------------
+static void vtkpxOpenIGTLinkServerWaitForConnectionThread(vtkMultiThreader::ThreadInfo *data)
+{
+  vtkpxOpenIGTLinkServer *self = (vtkpxOpenIGTLinkServer *)(data->UserData);
+  self->WaitForConnection();
+}
+// ---------------------------------------------------------------------------
+int vtkpxOpenIGTLinkServer::HandleErrorFromSocket()
+{
+  // This is to keep the vtkErrorMacro from being called ....
+  vtkDebugMacro(<<"++ No data to read .., ignoring \n");
+  //  fprintf(stderr,"No More Data\n");
+  return 0;
+}
+// ---------------------------------------------------------------------------
+int vtkpxOpenIGTLinkServer::WaitForConnection()
+{
+  if (this->Connector==NULL)
+    return 0;
+
+  this->ThreadActive=1;
+  vtkDebugMacro(<<"++ OpenIGTLinkServer waiting for connection\n");
+
+  this->IsServerActive=1;
+  this->IsServerConnected=0;
+
+
+  vtkClientSocket* in_socket=this->Connector->WaitForConnection(0);
+  if (in_socket==NULL)
+    {
+      int r=this->Connector->CreateServer(this->Port);
+      if (r!=0)
+	{
+	  std::cerr << "Failed to create  server on " << this->Port  << std::endl;
+	  return 0;
+	}
+      in_socket=this->Connector->WaitForConnection(0);
+    }
+  
+  int isdone=0;
+
+  if (in_socket!=NULL)
+    {
+      //      this->InvokeEvent(vtkCommand::NextDataEvent ,NULL);
+      vtkDebugMacro(<<"++ Connection Received all set ... now waiting for data\n");
+      this->IsServerConnected=1;
+
+      this->Observer->AttachSocketAndServer(in_socket,this);
+      this->ClientSocket=in_socket;
+    }
+  this->ThreadActive=0;
+  return 1;
+}
+//----------------------------------------------------------------------------
+int   vtkpxOpenIGTLinkServer::InitializeConnection(int port)
+{
+  if (ThreadActive==1)
+    {
+      std::cerr << "Server Thread still active can not initialize connection " << std::endl;
+      return 0;
+    }
+  
+  if (this->IsServerConnected==1)
+    this->CloseConnection();
+  
+  int oldport=this->Port;
+  if (port!=-1)
+    this->Port=port;
+  
+  if (this->Port!=oldport  || this->Connector==NULL)
+    {
+      if (this->Connector==NULL)
+	this->Connector=vtkServerSocket::New();
+      else
+	this->Connector->CloseSocket();
+
+      //      fprintf(stderr,"Proceeding to Create Server\n");
+      int r=this->Connector->CreateServer(this->Port);
+      
+      if (r!=0)
+	{
+	  std::cerr << "Failed to create  server on " << port  << std::endl;
+	  return 0;
+	}
+    }
+
+  if (this->Observer==NULL)
+    this->Observer=vtkpxOpenIGTLinkServerObserver::New();  
+  return this->RestartConnection();
+}
+// ---------------------------------------------------------------------------
+int   vtkpxOpenIGTLinkServer::RestartConnection()
+{
+  if (this->Connector==NULL || this->Observer==NULL)
+    return 0;
+
+  std::cerr << "Simply Restarting Connection" << this->Port  << std::endl;
+  this->ServerThreader->SpawnThread((vtkThreadFunctionType)		\
+				    &vtkpxOpenIGTLinkServerWaitForConnectionThread,this);
+  return 1;
+}
+// ---------------------------------------------------------------------------
+int   vtkpxOpenIGTLinkServer::CloseConnection()
+{
+  //  fprintf(stderr,"Begin Close Connection\n");
+  if (this->IsServerConnected==0)
+    {
+      std::cerr << "No Connection ... cannot close connection " << std::endl;
+      return 1;
+    }
+
+  if (ThreadActive==1)
+    {
+      std::cerr << "Server Thread still active can not close connection " << std::endl;
+      // Need a hack here that connects and closes ...
+      return 0;
+    }
+
+  if (this->Connector==NULL)
+    {
+      std::cerr << "Connector is NULL cannot disconnect " << std::endl;
+      return 1;
+    }
+
+  if (this->ThreadReceivingData>0)
+    {
+      std::cerr << "Waiting to terminate thread prior to disconnection " << std::endl;
+      this->ServerThreader->TerminateThread(this->ThreadReceivingDataId);
+    }
+
+
+  this->ClientSocket=NULL;
+
+  this->IsServerActive=0;
+  this->ThreadReceivingData=0;
+  this->IsServerConnected=0;
+  //  fprintf(stderr,"End Close Connection\n");
+  return 1;
+}
+// -------------------------------------------------------------------------
+static void vtkpxOpenIGTLinkServerKeepReceivingData(vtkMultiThreader::ThreadInfo *data)
+{
+  vtkpxOpenIGTLinkServer *self = (vtkpxOpenIGTLinkServer *)(data->UserData);
+  self->ThreadReceiveAllData();
+}
+
+
+int vtkpxOpenIGTLinkServer::BeginReceivingDataInThread()
+{
+  if (this->ThreadReceivingData==1)
+    return 0;
+
+  if (this->IsServerConnected==0)
+    return 0;
+  
+  this->ThreadReceivingDataId=this->ServerThreader->SpawnThread((vtkThreadFunctionType) \
+								&vtkpxOpenIGTLinkServerKeepReceivingData,this);
+  return this->ThreadReceivingDataId;
+}
+
+int vtkpxOpenIGTLinkServer::ThreadReceiveAllData()
+{
+  if (this->ClientSocket==NULL)
+    return 0;
+
+  if (this->ThreadReceivingData==1)
+    return 0;
+
+  this->ThreadReceivingData=1;
+  //  fprintf(stderr,"Receiving All Data\n");
+
+  int ok=1,count=0;
+  while (ok>0)
+    {
+      ok=this->ReceiveData(this->ClientSocket);     
+      ++count;
+      //      fprintf(stderr,"\t\t Received Packet %d %d\n",ok,count);
+    }
+
+  this->ThreadReceivingData=0;
+  this->CloseConnection();
+
+  //  fprintf(stderr,"Done Thread Receiving Data .. client disconnected\n");
+  return count;
+}
+// -------------------------------------------------------------------------
+int vtkpxOpenIGTLinkServer::ReceiveData(vtkClientSocket* in_socket)
+{
+  if (this->ActivelyReceiving==1)
+    return 1;
+
+  if (this->IsServerActive==0)
+    return -1;
+
+  if (this->IsServerConnected==0)
+    return -1;
+
+  int len=1;
+  int n=0;
+
+
+  this->ActivelyReceiving=1;
+
+  vtkDebugMacro(<<"++ In Receiving Data\n");
+  len=in_socket->Receive((void*)buffer,58);
+  if (len!=58)
+    {
+      this->ActivelyReceiving=0;
+      return 0;
+    }
+
+  igtl_header* header=  (igtl_header*)buffer;
+  igtl_header_convert_byte_order(header);   /* convert endian if necessary */
+
+  vtkDebugMacro(<<"Received packed name= " << header->name << " device_name= " << header->device_name << "\n");
+  //  std::cerr<<"Received packed name= " << header->name << " device_name= " << header->device_name << "\n";
+
+
+
+  int st=0;
+
+  if (strncmp(header->name,"TRANSFORM",9)==0)
+    {
+      st=this->ReceiveTransform(in_socket);
+    }
+  else if (strncmp(header->name,"IMAGE",5)==0)
+    {
+      st=this->ReceiveImage(in_socket);
+    }
+  else
+    {
+      st=0;
+    }
+
+  this->ActivelyReceiving=0;
+  return st;
+}
+// -------------------------------------------------------------------------
+
+int vtkpxOpenIGTLinkServer::ReceiveTransform(vtkClientSocket* in_socket)
+{
+  int len=in_socket->Receive((void*)buffer,48);
+  if (len!=48)
+    return 0;
+
+  vtkDebugMacro(<<"Received Transform size=" << len <<"\n");
+
+  igtl_float32* tr=(igtl_float32*)buffer;
+  igtl_transform_convert_byte_order(tr);   /* convert endian if necessary */
+
+  /*  for (int i=0;i<=11;i++)
+    fprintf(stderr,"Tr[%d]=%.2f ",i,tr[i]);
+    fprintf(stderr,"\n");*/
+
+  /*  double p[3];
+  p[0]=tr[9];   p[1]=tr[10];   p[2]=tr[11];
+  fprintf(stderr,"Point (%.2f %.2f %.2f)\n",p[0],p[1],p[2]);*/
+
+  double elements[16];
+  for (int j=0;j<=2;j++)
+    for (int i=0;i<=3;i++)
+      elements[j*4+i]=tr[i*3+j];
+  elements[12]=0;  elements[13]=0;  elements[14]=0;  elements[15]=1;
+
+  int index=0;
+  /*  for (int j=0;j<=3;j++)
+    {
+      fprintf(stderr,"[ ");
+      for (int i=0;i<=3;i++)
+	{
+	  fprintf(stderr,"%f ",elements[index]);
+	  ++index;
+	}
+      fprintf(stderr,"]\n");
+      }*/
+
+  this->TransformSemaphore->Lock();
+  // ++++++++++++++++++++
+  this->TempTransform->Identity();
+  this->TempTransform->Concatenate(elements);
+  // ++++++++++++++++++++
+  this->TransformSemaphore->Unlock();
+
+
+  this->SetLastReceivedTimeAndType(0);
+
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxOpenIGTLinkServer::ReceiveImage(vtkClientSocket* in_socket)
+{
+  int len=in_socket->Receive((void*)buffer,72);
+  if (len!=72)
+    return 0;
+
+
+  igtl_image_header* image_header=(igtl_image_header*)buffer;
+  
+  igtl_image_convert_byte_order(image_header);
+  igtl_uint64 imgsize=igtl_image_get_data_size(image_header);
+
+
+
+  // Begin Critical Section
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  this->ImageSemaphore->Lock();
+
+  int sum=0;
+  float spacing[3],origin[3],norm_i[3],norm_j[3],norm_k[3];
+  igtl_image_get_matrix(spacing,origin,norm_i,norm_j,norm_k,image_header);
+
+  if (this->TempImage!=NULL)
+    {
+      int dim[3]; this->TempImage->GetDimensions(dim);
+      for (int ia=0;ia<=2;ia++)
+	sum+=abs(image_header->size[ia]-dim[ia]);
+      if (sum!=0)
+	{
+	  fprintf(stderr,"Sum is not zero allocating memory %d,%d,%d vs %d,%d,%d\n",
+		  image_header->size[0],
+		  image_header->size[1],
+		  image_header->size[2],
+		  dim[0],dim[1],dim[2]);
+	  this->TempImage->Delete();
+	  this->TempImage=vtkImageData::New();
+	}
+    } 
+  else 
+    {
+      sum=-1;
+      fprintf(stderr,"Pointer is zero allocating memory\n");
+      this->TempImage=vtkImageData::New();
+    }
+
+  image_header->version     = IGTL_IMAGE_HEADER_VERSION;
+
+  //  this->LastReceivedImage->SetScalarType(image_header->data_type);
+  if (sum!=0)
+    {
+      this->TempImage->SetScalarType(VTK_UNSIGNED_CHAR);
+      this->TempImage->SetDimensions(image_header->size[0],image_header->size[1],image_header->size[2]);
+    }
+
+
+  // Store the normals in a transformation
+  double elements[16];
+  elements[0]=norm_i[0]; elements[4]=norm_j[0]; elements[8]=norm_k[0];
+  elements[1]=norm_i[1]; elements[5]=norm_j[1];	elements[9]=norm_k[1];
+  elements[2]=norm_i[2]; elements[6]=norm_j[2];	elements[10]=norm_k[2];
+  elements[3]=0.0;       elements[7]=0.0;      	elements[11]=0.0;      
+
+  elements[12]=0.0; elements[13]=0.0; elements[14]=0.0; elements[15]=1.0;
+  this->TempImageTransform->Identity();
+  this->TempImageTransform->Concatenate(elements);
+  // -----------------------------------------------
+  // On to image
+  // -----------------------------------------------
+
+  for (int ia=0;ia<=2;ia++)
+    spacing[ia]=fabs(spacing[ia]);
+
+  if (sum!=0) 
+    {
+      this->TempImage->SetSpacing(spacing[0],spacing[1],spacing[2]);
+      this->TempImage->SetOrigin(origin[0],origin[1],origin[2]);
+      this->TempImage->AllocateScalars();
+    }
+  
+  int dim[3]; this->TempImage->GetDimensions(dim);
+
+  /*  fprintf(stderr,"Dim = %d x %d x %d  spa = %.2f x %.2f x %.2f size=%d\n",
+	  dim[0],dim[1],dim[2],
+	  spacing[0],spacing[1],spacing[2],imgsize);*/
+
+  unsigned char* dpointer=new unsigned char[imgsize];
+  int totalsize=in_socket->Receive((void*)dpointer,imgsize);
+
+  vtkDataArray* arr=this->TempImage->GetPointData()->GetScalars();
+  //  std::cerr <<"Received Image size= " << imgsize << "actual size=" << totalsize << "\n";
+  unsigned char* ptr= (unsigned char*)arr->GetVoidPointer(0);
+  memcpy(ptr,dpointer,imgsize);
+  delete [] dpointer;
+
+  //vtkDebugMacro(<<"Received Image size= " << imgsize << "actual size=" << totalsize << "\n");
+  
+
+  // End Critical Section
+  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+  this->ImageSemaphore->Unlock();
+
+  this->SetLastReceivedTimeAndType(1);
+  return 1;
+}
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxOpenIGTLinkServer.h b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkServer.h
new file mode 100644
index 0000000..a72f782
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkServer.h
@@ -0,0 +1,173 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+#ifndef __vtkpxOpenIGTLinkServer_h
+#define __vtkpxOpenIGTLinkServer_h
+
+#include "vtkObject.h"
+#include "vtkPoints.h"
+#include "vtkImageData.h"
+#include "vtkServerSocket.h"
+#include "vtkClientSocket.h"
+#include "vtkMultiThreader.h"
+#include "vtkTransform.h"
+#include "vtkImageData.h"
+#include "vtkpxOpenIGTLinkServerObserver.h"
+#include "vtkTimeStamp.h"
+
+class vtkCriticalSection;
+
+class vtkpxOpenIGTLinkServer : public vtkObject
+{
+public:
+  static vtkpxOpenIGTLinkServer *New();
+  vtkTypeMacro(vtkpxOpenIGTLinkServer,vtkObject);
+
+  // Description:
+  // Print Self
+  void PrintSelf(ostream& os, vtkIndent indent);  
+
+  // Description:
+  // Initialize and Close Connection
+  virtual int   InitializeConnection() { return this->InitializeConnection(-1);}
+  virtual int   InitializeConnection(int port);
+  virtual int   RestartConnection();
+  virtual int   CloseConnection();
+
+
+  // Description:
+  // Receive All Data
+  virtual int BeginReceivingDataInThread();
+
+  // Function to Receive Data in Thread
+  virtual int ThreadReceiveAllData();
+
+
+  // Description
+  // Get The Actual Sockets if needed
+  vtkGetObjectMacro(Connector,vtkServerSocket);
+
+
+
+  // Description:
+  // Get Info About Server
+  vtkGetMacro(IsServerActive,int);
+  vtkGetMacro(IsServerConnected,int);
+  vtkGetMacro(ThreadActive,int);
+  vtkGetMacro(Port,int);
+  vtkGetMacro(ThreadReceivingData,int);
+
+
+  // Description:
+  // Callback for Handling Error from Receive Data
+  virtual int HandleErrorFromSocket();
+
+
+  // Description:
+  // Wait for Connection -- DO NOT USE this directly
+  virtual int WaitForConnection();
+
+  // Description:
+  // Time when last data was received
+  virtual unsigned long GetLastReceivedTransformTime();
+  virtual unsigned long GetLastReceivedImageTime();
+
+  // Description:
+  // Get Last Good Stuff
+  virtual vtkImageData* GetLastReceivedImage();
+  virtual vtkTransform* GetLastReceivedImageTransform();
+  virtual vtkTransform* GetLastReceivedTransform();
+
+
+protected:
+
+  vtkpxOpenIGTLinkServer();
+  ~vtkpxOpenIGTLinkServer();
+  vtkpxOpenIGTLinkServer(const vtkpxOpenIGTLinkServer&) {};
+  void operator=(const vtkpxOpenIGTLinkServer&) {};
+
+  // Use BTX..ETX to avoid parsing for tcl
+  //BTX
+  vtkServerSocket* Connector;
+  vtkClientSocket* ClientSocket;
+  vtkMultiThreader *ServerThreader;
+  vtkpxOpenIGTLinkServerObserver* Observer;
+
+  
+  // Key Variables
+  int  IsServerActive;
+  int  IsServerConnected;
+  int  Port;
+
+  char buffer[2000];
+  int  ThreadActive;
+
+
+  vtkTransform* LastReceivedTransform;
+  vtkTransform* TempTransform;
+
+  vtkImageData* LastReceivedImage;
+  vtkImageData* TempImage;
+  vtkTransform* LastReceivedImageTransform;
+  vtkTransform* TempImageTransform;
+
+
+  vtkTimeStamp  LastReceivedImageTime;   // Time Last Data was received
+  vtkTimeStamp  LastReceivedTransformTime;   // Time Last Data was received
+  int           ActivelyReceiving;
+  int           ThreadReceivingData;
+  int           ThreadReceivingDataId;
+  vtkCriticalSection *ImageSemaphore;
+  vtkCriticalSection *TransformSemaphore;
+
+  //ETX
+  // Description:
+  // Internal "Object Factory" Methods
+  virtual int ReceiveTransform(vtkClientSocket* ReceiveConnector);
+  virtual int ReceiveImage(vtkClientSocket* ReceiveConnector);
+  
+
+  // Description:
+  // Receive Stuff
+  virtual int ReceiveData(vtkClientSocket* ReceiveConnector);
+
+
+  // Description:
+  // Update Last Received Time and trigger USER Event
+  virtual void SetLastReceivedTimeAndType(int tp);
+
+
+
+
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkpxOpenIGTLinkServerObserver.cpp b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkServerObserver.cpp
new file mode 100644
index 0000000..b381db6
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkServerObserver.cpp
@@ -0,0 +1,66 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxOpenIGTLinkServerObserver.h"
+#include "vtkpxOpenIGTLinkServer.h"
+
+vtkpxOpenIGTLinkServerObserver* vtkpxOpenIGTLinkServerObserver::New()
+{ 
+  return new vtkpxOpenIGTLinkServerObserver; 
+}
+
+vtkpxOpenIGTLinkServerObserver::vtkpxOpenIGTLinkServerObserver()
+{
+  this->Socket=NULL;
+  this->Server=NULL;
+}
+
+void vtkpxOpenIGTLinkServerObserver::AttachSocketAndServer(vtkSocket* in_socket,vtkpxOpenIGTLinkServer* in_server)
+{
+  this->Socket=in_socket;
+  this->Server=in_server;
+  this->Socket->AddObserver(vtkCommand::ErrorEvent,this);
+}
+
+void vtkpxOpenIGTLinkServerObserver::Execute(vtkObject *caller,unsigned long event, void* vtkNotUsed(v))
+{
+  if (this->Server==NULL || this->Socket==NULL)
+    return;
+
+  // For no simply handle error
+  if (caller)
+    {
+      if (event == vtkCommand::ErrorEvent)
+	this->Server->HandleErrorFromSocket();
+    }
+}
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxOpenIGTLinkServerObserver.h b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkServerObserver.h
new file mode 100644
index 0000000..807c207
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxOpenIGTLinkServerObserver.h
@@ -0,0 +1,68 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkpxOpenIGTLinkServerObserver -- trap error from vtkpxOpenIGTLinkServer
+
+#ifndef __vtkpxOpenIGTLinkServerObserver_h
+#define __vtkpxOpenIGTLinkServerObserver_h
+
+#include "vtkObjectFactory.h"
+#include "vtkCommand.h"
+#include "vtkObject.h"
+#include "vtkSocket.h"
+
+class vtkpxOpenIGTLinkServer;
+
+
+class vtkpxOpenIGTLinkServerObserver : public vtkCommand
+{
+public:
+
+  static vtkpxOpenIGTLinkServerObserver *New();
+  vtkTypeMacro(vtkpxOpenIGTLinkServerObserver,vtkCommand);
+  virtual void Execute(vtkObject *caller,unsigned long event, void* vtkNotUsed(v));
+  virtual void AttachSocketAndServer(vtkSocket* socket,vtkpxOpenIGTLinkServer* server);
+
+protected:
+
+  vtkpxOpenIGTLinkServerObserver();
+
+  vtkpxOpenIGTLinkServerObserver(const vtkpxOpenIGTLinkServerObserver&) {};
+  void operator=(const vtkpxOpenIGTLinkServerObserver&) {};
+
+  vtkSocket*            Socket;
+  vtkpxOpenIGTLinkServer* Server;
+};
+
+
+ 
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkpxOptimizer.cpp b/bioimagesuite30_src/Common/vtkpxOptimizer.cpp
new file mode 100644
index 0000000..f9474d5
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxOptimizer.cpp
@@ -0,0 +1,957 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//  This File contains the following Numerical Recipes derived code that
+//   These are replaced if  BIS_USE_NR is not defined by ITK Code
+//   Good for testing for now, later eliminate all NR Code Completely
+// ---------------------------------------------------------------------------------------------------------
+
+// vtk includes
+
+#include "pxutil.h"
+#include "vtkpxOptimizer.h"
+#include "vtkObjectFactory.h"
+#include "vcl_algorithm.h"
+#include <vnl/vnl_math.h>
+#include "bioimagesuite_settings.h"
+#include "vtkTimerLog.h"
+
+#define TOL 2.0e-4
+
+
+char vtkpxOptimizer::OutputStatus[400];
+
+vtkpxOptimizer* vtkpxOptimizer::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxOptimizer");
+  if(ret)
+    {
+      return (vtkpxOptimizer*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxOptimizer;
+}
+
+
+vtkpxOptimizer::vtkpxOptimizer()
+{
+  this->MasterObject=NULL;
+  this->FeedbackMethod=NULL;
+  this->InternalEvaluateFunction=NULL;
+  this->InternalBeginIteration=NULL;
+  this->InternalEvaluateGradient=NULL;
+  this->TempArray=NULL;
+  this->pcom=NULL;
+  this->xicom=NULL;
+  this->xtemp=NULL;
+  this->ResetStatistics();
+}
+
+vtkpxOptimizer::~vtkpxOptimizer()
+{
+  this->SetTempArray(NULL);
+  this->SetMasterObject(NULL);
+  this->CleanUpLineTempCommons();
+}
+
+//----------------------------------------------------------------------------
+//  Hook Functions
+//----------------------------------------------------------------------------
+void vtkpxOptimizer::SetFeedbackMethod(void (*f)(vtkObject*,const char*,double ))
+{
+  this->FeedbackMethod=f;
+}
+
+void vtkpxOptimizer::SetEvaluateFunctionMethod(double (*f)(vtkObject*,vtkDoubleArray* ))
+{
+  this->InternalEvaluateFunction=f;
+}
+
+void vtkpxOptimizer::SetBeginIterationMethod(double (*f)(vtkObject*,vtkDoubleArray* ))
+{
+  this->InternalBeginIteration=f;
+}
+
+
+void vtkpxOptimizer::SetEvaluateGradientMethod(double (*f)(vtkObject*,vtkDoubleArray*,vtkDoubleArray* ))
+{
+  this->InternalEvaluateGradient=f;
+}
+
+
+void vtkpxOptimizer::ResetStatistics()
+{
+  this->NumberOfFunctionEvaluations=0;
+  this->NumberOfGradientEvaluations=0;
+  this->MinFunctionValue=1e+30;
+}
+// ------------------------------------------------------------------------------
+// Support Functions
+// ------------------------------------------------------------------------------
+
+void vtkpxOptimizer::AddScaledVectors(vtkDoubleArray* a1,double s1,vtkDoubleArray* a2,double s2,vtkDoubleArray* sum)
+{
+  int np=sum->GetNumberOfTuples();
+  for (int i=0;i<np;i++)
+    sum->SetComponent(i,0,
+		      s1*a1->GetComponent(i,0)+
+		      s2*a2->GetComponent(i,0));
+}
+
+void vtkpxOptimizer::AddToVector(vtkDoubleArray* position,vtkDoubleArray* grad,double factor)
+{
+  int np=position->GetNumberOfTuples();
+  for (int i=0;i<np;i++)
+    position->SetComponent(i,0,position->GetComponent(i,0)+factor*grad->GetComponent(i,0));
+
+}
+
+void vtkpxOptimizer::ScaleVector(vtkDoubleArray* position,double scale)
+{
+  int np=position->GetNumberOfTuples();
+  for (int i=0;i<np;i++)
+    position->SetComponent(i,0,position->GetComponent(i,0)*scale);
+}
+
+int vtkpxOptimizer::UseParameter(vtkShortArray* flag,int p)
+{
+  if (flag==NULL)
+    return 1;
+
+  return (flag->GetComponent(p,0)>0);
+}
+
+void vtkpxOptimizer::GenerateOutput(const char* prefix1,const char* prefix2,
+				    vtkDoubleArray* position,double measure,int iter,vtkShortArray* flags)
+{
+  sprintf(this->OutputStatus,"%s:%s %2d : ",prefix1,prefix2,iter);
+  if (position->GetNumberOfTuples()<=25)
+    {
+      sprintf(this->OutputStatus,"%s (",this->OutputStatus);
+      for (int ii=0; ii<position->GetNumberOfTuples(); ii++) 
+	{
+	  if (this->UseParameter(flags,ii))
+	    {
+	      double a=position->GetComponent(ii,0);
+	      if (position->GetNumberOfComponents()==2)
+		a=a/position->GetComponent(ii,1);
+	      sprintf(this->OutputStatus,"%s %-.5f ",this->OutputStatus,a);
+	    }
+	}
+      sprintf(this->OutputStatus,"%s )",this->OutputStatus);
+    }
+  if (this->FeedbackMethod!=NULL)
+    this->FeedbackMethod(this->MasterObject,this->OutputStatus,measure);
+
+}
+
+
+void vtkpxOptimizer::GenerateStatistics(const char* method,vtkDoubleArray* position)
+{
+  double v=this->EvaluateFunction(this->MasterObject,position);
+  sprintf(this->OutputStatus,"%s Stats: Nfuncr=%d, Ngrad=%d Minv=%.4f ReturnedV=%.4f",
+	  method,
+	  this->NumberOfFunctionEvaluations-1,
+	  this->NumberOfGradientEvaluations,
+	  this->MinFunctionValue,
+	  v);
+  if (this->FeedbackMethod!=NULL)
+    this->FeedbackMethod(this->MasterObject,this->OutputStatus,v);
+}
+
+//----------------------------------------------------------------------------
+double vtkpxOptimizer::ComputeOldGradientDescent(vtkDoubleArray* position,double step,double tolerance,int maxsteps)
+{
+  if (this->MasterObject==NULL || this->InternalEvaluateFunction==NULL || this->InternalEvaluateGradient==NULL)
+    {
+      vtkErrorMacro(<<"Hook Functions Not Properly Defined\n");
+    }
+
+  vtkDoubleArray* grad=NULL;
+  if (this->TempArray==NULL)
+      grad=vtkDoubleArray::New();
+  else
+      grad=this->TempArray;
+
+
+  double old_similarity=this->EvaluateFunction(this->MasterObject,position);
+  this->EvaluateGradient(this->MasterObject,position,grad);
+  double dstep=-1.0*step;
+  this->GenerateOutput("oGD", "Beginning",position,old_similarity,0);
+
+  int upd=1;
+  double best=old_similarity;
+  int flag=1;
+  
+  int count=0,maxcount=maxsteps;
+  while (flag==1 && count<maxcount)
+    {  
+      ++count;
+      AddToVector(position,grad,dstep);
+      double similarity = this->EvaluateFunction(this->MasterObject,position);
+      if (similarity<best)
+	{
+	  best=similarity;
+	  this->GenerateOutput("oGD", "Iter",position,best,upd);
+	  ++upd;
+	}
+      
+      else
+	flag=0;
+    }
+  
+  // Last step was no improvement, so back track
+  if (flag==0)
+    AddToVector(position,grad,-dstep);
+  
+  this->GenerateOutput("oGD", "Done",position,best,upd);
+  this->GenerateStatistics("oGD",position);
+
+  if (this->TempArray==NULL)
+      grad->Delete();
+  return best;
+}
+//----------------------------------------------------------------------------
+double vtkpxOptimizer::ComputeGradientDescent(vtkDoubleArray* position,int iterations,double tolerance)
+{
+  if (this->MasterObject==NULL || this->InternalEvaluateFunction==NULL || this->InternalEvaluateGradient==NULL)
+    {
+      vtkErrorMacro(<<"Hook Functions Not Properly Defined\n");
+    }
+
+  vtkDoubleArray* grad=NULL;
+  if (this->TempArray==NULL)
+      grad=vtkDoubleArray::New();
+  else
+      grad=this->TempArray;
+
+  this->AllocateLineTempCommons(position);
+  this->BeginIteration(this->MasterObject,position);  
+  double old_similarity=this->EvaluateFunction(this->MasterObject,position);
+  this->EvaluateGradient(this->MasterObject,position,grad);
+  this->GenerateOutput("GD", "Beginning",position,old_similarity,0);
+
+  double best=old_similarity;
+  int flag=1;
+  int iter=1;
+  
+  while (flag==1 && iter<iterations)
+    {  
+      this->BeginIteration(this->MasterObject,position);
+      best=this->LineMinimization(position,grad,iter,tolerance,"GD");
+      if (fabs(best-old_similarity)<tolerance)
+	{
+	  flag=0;
+	}
+      else
+	{
+	  old_similarity=this->EvaluateFunction(this->MasterObject,position);
+	  this->EvaluateGradient(this->MasterObject,position,grad);
+	  ++iter;
+	}
+    }
+
+  this->GenerateOutput("GD", "Done",position,best,iter);
+  this->GenerateStatistics("GD",position);
+  this->CleanUpLineTempCommons();
+
+  if (this->TempArray==NULL)
+      grad->Delete();
+  return best;
+}
+//----------------------------------------------------------------------------
+double vtkpxOptimizer::ComputeSlowClimb(vtkDoubleArray* position,double step,int iterations,vtkShortArray* flags)
+{
+  if (this->MasterObject==NULL || this->InternalEvaluateFunction==NULL)
+    {
+      vtkErrorMacro(<<"Hook Functions Not Properly Defined\n");
+    }
+
+  this->BeginIteration(this->MasterObject,position);  
+  double old_similarity=this->EvaluateFunction(this->MasterObject,position),similarity=old_similarity;
+  int   nump=position->GetNumberOfTuples();
+
+  char line[20];   sprintf(line,"SC %.5f",step);
+  this->GenerateOutput(line, "Beginning",position,old_similarity,0);
+
+  for (int iter=1;iter<iterations;iter++)
+    {
+      int j = 0,k = 0;
+      double best_similarity=old_similarity;
+      this->BeginIteration(this->MasterObject,position);
+
+      for (int i = 0; i < nump; i++)
+	{
+	  if (this->UseParameter(flags,i))
+	    {
+	      double orig=position->GetComponent(i,0);
+	      position->SetComponent(i,0, orig + step);
+	      similarity=this->EvaluateFunction(this->MasterObject,position);
+	      if (similarity < best_similarity)
+		{
+		  best_similarity = similarity;
+		  j =  i;
+		  k =  1;
+		}
+	      
+	      position->SetComponent(i,0, orig - step);
+	      similarity=this->EvaluateFunction(this->MasterObject,position);
+	      
+	      if (similarity < best_similarity)
+		{
+		  best_similarity = similarity;
+		  j =  i;
+		  k = -1; 
+		}
+	      position->SetComponent(i,0, orig);
+	    }
+	}
+
+      if (best_similarity < old_similarity)
+	{
+	  double oldv=position->GetComponent(j,0);
+	  double newv=oldv+k*step;
+	  position->SetComponent(j,0,newv);
+	  old_similarity=best_similarity;
+	  this->GenerateOutput(line, "It",position,old_similarity,iter);
+	}
+      else
+	iter=iterations+1; // Break Out
+    }
+  this->GenerateStatistics(line,position);
+  return old_similarity;
+}
+
+
+double vtkpxOptimizer::ComputeSlowClimbPlus(vtkDoubleArray* position,int iterations,vtkShortArray* flags)
+{
+  if (this->MasterObject==NULL || this->InternalEvaluateFunction==NULL)
+    {
+      vtkErrorMacro(<<"Hook Functions Not Properly Defined\n");
+    }
+
+  this->BeginIteration(this->MasterObject,position);  
+  double old_similarity=this->EvaluateFunction(this->MasterObject,position),similarity=old_similarity;
+  int   nump=position->GetNumberOfTuples();
+
+  char line[20];   sprintf(line,"SC ");
+  this->GenerateOutput(line, "Beginning",position,old_similarity,0);
+
+  for (int iter=1;iter<iterations;iter++)
+    {
+      int j = 0,k = 0;
+      double best_similarity=old_similarity;
+      this->BeginIteration(this->MasterObject,position);
+
+      for (int i = 0; i < nump; i++)
+	{
+	  if (this->UseParameter(flags,i))
+	    {
+	      double orig=position->GetComponent(i,0);
+	      double step=position->GetComponent(i,1);
+	      double newp=orig+step;
+	      if (newp>position->GetComponent(i,3))
+		newp=position->GetComponent(i,3);
+
+	      position->SetComponent(i,0, newp);
+	      similarity=this->EvaluateFunction(this->MasterObject,position);
+	      if (similarity < best_similarity)
+		{
+		  best_similarity = similarity;
+		  j =  i;
+		  k =  1;
+		}
+
+	      newp=orig-step;
+	      if (newp<position->GetComponent(i,2))
+		newp=position->GetComponent(i,2);
+
+	      position->SetComponent(i,0, newp);
+	      similarity=this->EvaluateFunction(this->MasterObject,position);
+	      
+	      if (similarity < best_similarity)
+		{
+		  best_similarity = similarity;
+		  j =  i;
+		  k = -1; 
+		}
+	      position->SetComponent(i,0, orig);
+	    }
+	}
+
+      if (best_similarity < old_similarity)
+	{
+	  double oldv=position->GetComponent(j,0);
+	  double step=position->GetComponent(j,1);
+	  double newv=oldv+k*step;
+	  if (newv<position->GetComponent(j,2))
+	    newv=position->GetComponent(j,2);
+	  else if (newv>position->GetComponent(j,3))
+	    newv=position->GetComponent(j,3);
+	  position->SetComponent(j,0,newv);
+	  old_similarity=best_similarity;
+	  this->GenerateOutput(line, "It",position,old_similarity,iter);
+	}
+      else
+	iter=iterations+1; // Break Out
+    }
+  this->GenerateStatistics(line,position);
+  return old_similarity;
+}
+
+
+
+// ---------------------------------------------------------------------------
+double vtkpxOptimizer::ComputeConjugateGradient(vtkDoubleArray* position, int num_iterations,double tolerance)
+{
+  /*  int j,its=0;
+  double gg,gam,fp,dgg;
+  double fret;*/
+
+  vtkTimerLog* timer=vtkTimerLog::New();
+  timer->StartTimer();
+
+  this->AllocateLineTempCommons(position);
+  int n=position->GetNumberOfTuples();
+  vtkDoubleArray* grad=vtkDoubleArray::New();  grad->SetNumberOfTuples(n);
+
+
+  char line[60];
+  sprintf(line,"Begin Optimization (it=%d), tolerance=%f",num_iterations,tolerance);
+  this->GenerateOutput("GC",line,position,0,0);
+
+  this->BeginIteration(this->MasterObject,position);  
+  double funcval=this->EvaluateFunction(this->MasterObject,position);
+  double norm=this->EvaluateGradient(this->MasterObject,position,grad);
+
+
+
+
+
+  int done=0;
+
+  if (norm<tolerance)
+    {
+      this->GenerateOutput("CG", "Done",position,funcval,0);  
+      this->GenerateStatistics("CG",position);
+      grad->Delete();this->CleanUpLineTempCommons();
+      return funcval;
+    }
+
+  vtkDoubleArray* g=vtkDoubleArray::New();  g->SetNumberOfTuples(n);
+  vtkDoubleArray* h=vtkDoubleArray::New();  h->SetNumberOfTuples(n);
+
+  g->DeepCopy(grad); this->ScaleVector(g,-1.0); 
+  h->DeepCopy(g);  grad->DeepCopy(h);
+
+  int iter=1;
+  while (iter<=num_iterations && done == 0 )
+    {
+      this->BeginIteration(this->MasterObject,position);
+      double newval=this->LineMinimization(position,grad,iter,tolerance,"CG");
+      done=1;
+      if (fabs(funcval-newval)>tolerance)
+	{
+	  funcval=this->EvaluateFunction(this->MasterObject,position);
+	  this->EvaluateGradient(this->MasterObject,position,grad);
+	  double dgg=0.0,gg=0.0;
+	  for (int j=0;j<n;j++) 
+	    {
+	      gg += g->GetComponent(j,0)*g->GetComponent(j,0);
+	      dgg += (grad->GetComponent(j,0)+g->GetComponent(j,0))*grad->GetComponent(j,0);
+	    }
+	  
+	  if (gg > 0.000001) 
+	    {
+	      double gam=dgg/gg;
+	      g->DeepCopy(grad); this->ScaleVector(g,-1.0);
+	      this->ScaleVector(h,gam); this->AddToVector(h,g,1.0);
+	      grad->DeepCopy(h);
+	      done=0;
+	    }
+	}
+      ++iter;
+    }
+  
+  timer->StopTimer();
+  double elapsed=timer->GetElapsedTime();
+  timer->Delete();
+
+  sprintf(line,"Done (%10.4f s) \t\t",elapsed);
+
+  this->GenerateOutput("CG", line,position,funcval,iter);  
+  this->GenerateStatistics("CG",position);
+  g->Delete();h->Delete();grad->Delete();this->CleanUpLineTempCommons();
+  return funcval;
+}
+
+#define SQR(a)  ((sqrarg=(a)) = 0.0 ? 0.0 : sqrarg*sqrarg)
+// ---------------------------------------------------------------------------
+double vtkpxOptimizer::ComputePowell(vtkDoubleArray* position,vtkDoubleArray* temp, int iterations,double tolerance)
+{
+#ifdef BIS_USE_NR
+  static double sqrarg;
+  int n=position->GetNumberOfTuples();
+  if (temp->GetNumberOfComponents()<n || temp->GetNumberOfTuples()<n)
+    {
+      temp->SetNumberOfComponents(n);
+      temp->SetNumberOfTuples(n);
+      for (int i=0;i<n;i++)
+	temp->FillComponent(i,0.0);
+      for (int j=0;j<n;j++)
+	temp->SetComponent(j,j,1.0);
+    }
+  vtkDoubleArray* pt=vtkDoubleArray::New(); pt->SetNumberOfTuples(n);
+  vtkDoubleArray* ptt=vtkDoubleArray::New(); ptt->SetNumberOfTuples(n);
+  vtkDoubleArray* xit=vtkDoubleArray::New(); xit->SetNumberOfTuples(n);
+  this->AllocateLineTempCommons(position);
+
+  //This code derives from Numerical Recipes in C
+  //It computes a powell optimization
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+  pt->Delete();
+  ptt->Delete();
+  xit->Delete();
+  this->CleanUpLineTempCommons();
+  fret=this->EvaluateFunction(this->MasterObject,position);
+  this->GenerateOutput("PW", "Done",position,fret,iter);
+  this->GenerateStatistics("PW",position);
+  return fret;
+#else
+  // No Numerical Recipes So reroute to Gradient Descent for now
+  fprintf(stderr,"Powell unavailable using Slow Climb Descent\n");
+  return vtkpxOptimizer::ComputeSlowClimb(position,0.1,iterations);
+#endif
+}
+#undef SQR  
+
+//----------------------------------------------------------------------------
+// Numerical Recipes code for optimization
+// ---------------------------------------------------------------------------
+
+void ShiftValues(double* a, double* b, double* c, double d)
+{
+  *a = *b;
+  *b = *c;
+  *c = d;
+}
+
+
+#define GOLD 1.618034
+#define GLIMIT 100.0
+#define TINY 1.0e-20
+// Bracketing Routine 
+
+void vtkpxOptimizer::BracketMinimum(double *ax, 
+			    double *bx, 
+			    double *cx, 
+			    double *fa, 
+			    double *fb, 
+			    double *fc)
+{
+#ifdef BIS_USE_NR
+  //This code derives from Numerical Recipes in C
+  // It is practically unmodified
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+#else
+  // Replacement code from ITK 3.4 (vnl_brent)
+  double ulim,u,r,q,fu;
+
+  *fa=this->LineFunction(*ax);
+  *fb=this->LineFunction(*bx);
+  if (*fb > *fa) {
+    vcl_swap(*ax, *bx);
+    vcl_swap(*fa, *fb);
+  }
+  *cx=(*bx)+GOLD*(*bx-*ax);
+  *fc=this->LineFunction(*cx);
+  while (*fb > *fc) {
+    r=(*bx-*ax)*(*fb-*fc);
+    q=(*bx-*cx)*(*fb-*fa);
+    double dq = q-r;
+    if (vcl_abs(dq) < TINY)
+      dq = vnl_math_sgn(dq) * TINY;
+
+    u=(*bx)-((*bx-*cx)*q-(*bx-*ax)*r)/(2.0*dq);
+    ulim=(*bx)+GLIMIT*(*cx-*bx);
+    if ((*bx-u)*(u-*cx) > 0.0) {
+      fu=this->LineFunction(u);
+      if (fu < *fc) {
+        *ax=(*bx);
+        *bx=u;
+        *fa=(*fb);
+        *fb=fu;
+        return;
+      } else if (fu > *fb) {
+        *cx=u;
+        *fc=fu;
+        return;
+      }
+      u=(*cx)+GOLD*(*cx-*bx);
+      fu=this->LineFunction(u);
+    } else if ((*cx-u)*(u-ulim) > 0.0) {
+      fu=this->LineFunction(u);
+      if (fu < *fc) {
+        //ShiftValues(bx,cx,&u,*cx+GOLD*(*cx-*bx)); awf dumped -- c is useless
+        ShiftValues(bx,cx,&u,u+GOLD*(u-*cx));
+        ShiftValues(fb,fc,&fu,this->LineFunction(u));
+      }
+    } else if ((u-ulim)*(ulim-*cx) >= 0.0) {
+      u=ulim;
+      fu=this->LineFunction(u);
+    } else {
+      u=(*cx)+GOLD*(*cx-*bx);
+      fu=this->LineFunction(u);
+    }
+    ShiftValues(ax,bx,cx,u);
+    ShiftValues(fa,fb,fc,fu);
+  }
+#endif
+  
+}
+#undef GOLD
+#undef GLIMIT
+#undef TINY
+
+// ---------------------------------------------------------------------------
+#define ITMAX 100
+#define CGOLD 0.3819660
+#define ZEPS 1.0e-10
+
+
+double vtkpxOptimizer::MinimizeGivenBounds(double ax, double bx, double cx,  double tol,  double *xmin)
+{
+#ifdef BIS_USE_NR
+  //This code derives from Numerical Recipes in C
+  // It is practically unmodified
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+#else
+  // Replacement code from ITK 3.4 (vnl_brent)
+
+  //
+  // This code has been removed after it was pointed out
+  // to ITK developers that it was a copy of code from
+  // Numerical Recipies. January 23 2007
+  //
+  // The distribution license of numerical recipies is not
+  // compatible with the BSD-License used by ITK.
+  // 
+  // -----------------------------------------------------------
+  //
+  // The following implementation was based on the description
+  // of the Brent's method presented in the Wikipedia:
+  //
+  //    http://en.wikipedia.org/wiki/Brent%27s_method
+  //
+  double a = ax;
+  double b = cx;
+
+  bool mflag;
+
+  if( ax > cx )
+    {
+    a = cx;
+    b = ax;
+    }
+
+  double x = bx;
+
+  double fa = this->LineFunction(a);
+  double fb = this->LineFunction(b);
+  double fx = this->LineFunction(x);
+
+  if( fa * fb >= 0.0 )
+    {
+      //    fprintf(stderr,"vnl_brent f(%f) has same sign as f(%f) \n",a,b);
+    *xmin = x;
+    return fx;
+    }
+
+  if( vcl_fabs(fa) < vcl_fabs(fb) )
+    {
+    const double t= a;
+    a = b;
+    b = t;
+    const double ft = fa;
+    fa = fb;
+    fb = ft;
+    }
+
+  double c = a;
+  double d = a;   // it is not clear how to initialize d
+  double fc = fa;
+
+  double s;
+
+  for( unsigned int iteration = 1; iteration <= ITMAX; iteration++)
+    {
+
+    if( vcl_fabs(fb) <= ZEPS || vcl_fabs( a - b ) <= ZEPS )
+      {
+      *xmin=b;
+      return fb;
+      }
+
+    const double fac = fa - fc;
+    const double fbc = fb - fc;
+    const double fab = fa - fb;
+
+    if( vcl_fabs( fac ) < ZEPS || vcl_fabs(fbc) < ZEPS )
+      {
+      // Apply secant rule
+      s = b - fb * (b - a) / ( fb - fa );
+      }
+    else
+      {
+      // Inverse quadratic interpolation
+      const double afbfc = ( a * fb * fc ) / ( fab * fac );
+      const double bfafc = ( b * fa * fc ) / ( fab * fbc );
+      const double cfafb = ( c * fa * fb ) / ( fac * fbc );
+      s = afbfc - bfafc + cfafb;
+      }
+
+    if( !( s > ( 3 * a + b ) / 4.0 && s < b ) ||
+         (  mflag && ( vcl_fabs( s - b ) >= vcl_fabs( b - c ) / 2.0 ) ) ||
+         ( !mflag && ( vcl_fabs( s - b ) >= vcl_fabs( c - d ) / 2.0 ) )    )
+      {
+      s = ( a + b ) / 2;
+      mflag = true;
+      }
+    else
+      {
+      mflag = false;
+      }
+       
+    double fs = this->LineFunction(s);
+
+    d = c;
+    c = b;
+
+    if( fa * fs < 0.0 )
+      {
+      b = s;
+      fb = fs;
+      }
+    else
+      {
+      a = s;
+      fa = fs;
+      }
+
+    if( vcl_fabs( fa ) < vcl_fabs( fb ) )
+      {
+      const double temp = a;
+      a = b;
+      b = temp;
+      }
+    
+    }
+
+  *xmin = b;
+  return fb;
+#endif
+}
+#undef ITMAX
+#undef CGOLD
+#undef ZEPS
+
+// ---------------------------------------------------------------------------
+// Line Minimization 
+// ---------------------------------------------------------------------------
+void vtkpxOptimizer::AllocateLineTempCommons(vtkDoubleArray* position)
+{
+  if (this->pcom==NULL)
+    this->pcom=vtkDoubleArray::New();
+
+  if (this->xicom==NULL)
+    this->xicom=vtkDoubleArray::New();
+
+  if (this->xtemp==NULL)
+    this->xtemp=vtkDoubleArray::New();
+
+  this->pcom->SetNumberOfTuples(position->GetNumberOfTuples());
+  this->xicom->SetNumberOfTuples(position->GetNumberOfTuples());
+  this->xtemp->SetNumberOfTuples(position->GetNumberOfTuples());
+  
+}
+
+void vtkpxOptimizer::CleanUpLineTempCommons()
+{
+  if (this->pcom!=NULL)
+    this->pcom->Delete();
+  if (this->xicom!=NULL)
+    this->xicom->Delete();
+  if (this->xtemp!=NULL)
+    this->xtemp->Delete();
+  this->pcom=NULL;
+  this->xicom=NULL;
+  this->xtemp=NULL;
+}
+
+
+double vtkpxOptimizer::LineMinimization(vtkDoubleArray* p, vtkDoubleArray* xi,int iterno,double tolerance,
+				       const char* method)
+{
+  static int firsttime=0;
+  /*
+    ncom=n;
+    pcom=vector(1,n);
+    xicom=vector(1,n);
+    nrfunc=func;
+    for (j=1;j<=n;j++) {
+    pcom[j]=p[j];
+    xicom[j]=xi[j];
+    }*/
+
+  pcom->DeepCopy(p);
+  xicom->DeepCopy(xi);
+
+  /*
+	BracketMinimum(&ax,&xx,&bx,&fa,&fx,&fb,f1dim);
+	*fret=MinimizeGivenBounds(ax,xx,bx,f1dim,TOL,&xmin);
+	for (j=1;j<=n;j++) {
+		xi[j] *= xmin;
+		p[j] += xi[j];
+	}
+	free_vector(xicom,1,n);
+	free_vector(pcom,1,n);
+  */
+  // This is a Critical Change here 
+  double xx=1.0,xmin,fx,fb,fa,bx,ax=0.0;
+
+  /*  if (firsttime)
+      fprintf(stdout,"Searching ax=%.2f bx=%.2f\n",ax,bx);*/
+    
+  this->BracketMinimum(&ax,&xx,&bx,&fa,&fx,&fb);
+
+  /*  if (firsttime)
+      fprintf(stdout,"Bracketing ax=%.2f bx=%.2f cx=%.2f\n",ax,bx,xx);*/
+
+    
+
+  double fret=this->MinimizeGivenBounds(ax,xx,bx,tolerance,&xmin);
+
+  /*  if (firsttime)
+      fprintf(stdout,"MinimizeGivenBounds ax=%.2f bx=%.2f cx=%.2f xmin=%.2f \n",ax,xx,bx,xmin);*/
+
+
+  this->ScaleVector(xi,xmin);
+  this->AddToVector(p,xi,1.0);
+
+  if (iterno>=0)
+    this->GenerateOutput(method, "Lmin",p,fret,iterno);
+
+  firsttime=0;
+  return fret;
+}
+
+
+double vtkpxOptimizer::LineFunction(double x)
+{
+  xtemp->DeepCopy(pcom);
+  this->AddToVector(xtemp,xicom,x);
+  return this->EvaluateFunction(this->MasterObject,xtemp);
+}
+
+// ---------------------------------------------------------------------------
+double vtkpxOptimizer::Compute1DMinimization(vtkDoubleArray* position,double min_v,double max_v,double tolerance)
+{
+  if (position->GetNumberOfTuples()>1)
+    {
+      //      fprintf(stdout,"1D Minimization Only!!!!\n");
+      return -1.0;
+    }
+
+  if (this->MasterObject==NULL || this->InternalEvaluateFunction==NULL)
+    {
+      vtkErrorMacro(<<"Hook Functions Not Properly Defined\n");
+      return -1.0;
+    }
+  
+  double old_similarity=this->EvaluateFunction(this->MasterObject,position);
+
+  this->GenerateOutput("1D", "Beginning",position,old_similarity,0);
+  this->AllocateLineTempCommons(position);
+  this->pcom->DeepCopy(position);
+  if (tolerance<0.0001)
+    tolerance=0.0001;
+  this->xicom->SetComponent(0,0,fabs(max_v-min_v)*0.01);
+
+  double bx,xmin,fx,fb,fa,xx=max_v,ax=min_v;
+  this->BracketMinimum(&ax,&xx,&bx,&fa,&fx,&fb);
+  //  fprintf(stdout,"Bracketing ax=%.2f (%f) xx=%.2f (%f) bx=%.2f (%f)\n",ax,fa,xx,fx,bx,fb);
+
+  double fret=this->MinimizeGivenBounds(ax,xx,bx,tolerance,&xmin);
+  //  fprintf(stdout,"MinimizeGivenBounds ax=%.2f bx=%.2f cx=%.2f xmin=%.2f \n",ax,xx,bx,xmin);
+
+  this->ScaleVector(xicom,xmin);
+  this->AddToVector(position,xicom,1.0);
+
+  this->GenerateOutput("1D"," ",position,fret,1);
+  this->GenerateStatistics("1D",position);
+  this->CleanUpLineTempCommons();
+  return fret;
+}
+ 
+
+
+
+int vtkpxOptimizer::UsesNumericalRecipes()
+{
+#ifdef BIS_USE_NR
+  return 1;
+#endif
+
+  return 0;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxOptimizer.h b/bioimagesuite30_src/Common/vtkpxOptimizer.h
new file mode 100644
index 0000000..b4fbac4
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxOptimizer.h
@@ -0,0 +1,185 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//  This file is OK but it depends heavily on Numerical Recipes code in vtkpxOptimizer.cpp
+//  
+//
+//---------------------------------------------------------------------------------------------------------
+
+#ifndef __VTKPXOPTIMIZER_H
+#define __VTKPXOPTIMIZER_H
+
+#include "vtkProcessObject.h"
+#include "vtkDoubleArray.h"
+#include "vtkShortArray.h"
+
+class vtkpxOptimizer : public vtkProcessObject {
+
+public:
+
+  vtkTypeMacro(vtkpxOptimizer,vtkProcessObject);
+
+  // Description:
+  // This one also 
+  static vtkpxOptimizer* New();
+
+  // Description:
+  // Set Master Object
+  vtkSetObjectMacro(MasterObject,vtkObject);
+  vtkGetObjectMacro(MasterObject,vtkObject);
+
+
+  // Description:
+  // Temporary Storage Array 
+  vtkSetObjectMacro(TempArray,vtkDoubleArray);
+  vtkGetObjectMacro(TempArray,vtkDoubleArray);
+
+
+  // Description:
+  // Set Command Hooks for function,gradient,feedback
+  //BTX
+  void SetFeedbackMethod(void (*f)(vtkObject*,const char*,double ));
+  void SetEvaluateFunctionMethod(double (*f)(vtkObject*,vtkDoubleArray* ));
+  void SetBeginIterationMethod(double (*f)(vtkObject*,vtkDoubleArray* ));
+  void SetEvaluateGradientMethod(double (*f)(vtkObject*,vtkDoubleArray*,vtkDoubleArray* ));
+  //ETX
+
+  // Description:
+  // Compute Gradient Descent using func,funcd and self
+  virtual double ComputeSlowClimb(vtkDoubleArray* position,double step,int iterations,vtkShortArray* flags=NULL);
+  virtual double ComputeSlowClimbPlus(vtkDoubleArray* position,int iterations,vtkShortArray* flags=NULL);
+  virtual double ComputeOldGradientDescent(vtkDoubleArray* position,double step,double tolerance,int maxsteps=50);
+  virtual double ComputeGradientDescent(vtkDoubleArray* position,int iterations,double tolerance);
+  virtual double ComputePowell(vtkDoubleArray* position,vtkDoubleArray* temp, int iterations=200,double tolerance=0.001);
+  virtual double ComputeConjugateGradient(vtkDoubleArray* position, int iterations=200,double tolerance=0.001);
+
+  virtual double Compute1DMinimization(vtkDoubleArray* position,double min,double max,double tolerance=0.001);
+
+
+  // Description:
+  // Check for whether we are using Numerical Recipes Code
+  static int UsesNumericalRecipes();
+
+protected:
+
+  // Description:
+  // Make all these protected 
+  // Constructor
+  vtkpxOptimizer();
+  virtual ~vtkpxOptimizer();
+  vtkpxOptimizer(const vtkpxOptimizer&) {};
+  void operator=(const vtkpxOptimizer&) {};
+
+
+  void AddToVector(vtkDoubleArray* position,vtkDoubleArray* grad,double factor);
+  void ScaleVector(vtkDoubleArray* position,double scale);
+  void AddScaledVectors(vtkDoubleArray* a1,double s1,vtkDoubleArray* a2,double s2,vtkDoubleArray* sum);
+  int  UseParameter(vtkShortArray* flag,int p);
+
+  // Callback Functions 
+  vtkObject* MasterObject;
+  vtkDoubleArray* TempArray;
+  //BTX
+  void (*FeedbackMethod)(vtkObject *,const char* ,double);
+  double (*InternalBeginIteration)(vtkObject *, vtkDoubleArray*);
+  double (*InternalEvaluateFunction)(vtkObject *, vtkDoubleArray*);
+  double (*InternalEvaluateGradient)(vtkObject *, vtkDoubleArray*,vtkDoubleArray*);
+
+  static char OutputStatus[400];
+  //ETX
+
+
+  // Description:
+  // Line Minimization
+  //BTX
+  void    BracketMinimum(double *ax, double *bx, double *cx,  double *fa, double *fb, double *fc);
+  double  MinimizeGivenBounds(double ax, double bx, double cx,  double tol,   double *xmin);
+  //ETX
+
+  // Description:
+  // Generate Output
+  void GenerateOutput(const char* prefix1,const char* prefix2,
+		      vtkDoubleArray* position,double measure,int iter,vtkShortArray* flags=NULL);
+
+  // Description:
+  // Statistics of Optimization:
+  void GenerateStatistics(const char* method,vtkDoubleArray* finalposition);
+  void ResetStatistics();
+
+  // Description:
+  // Parameters for doing statistics
+  int   NumberOfFunctionEvaluations;
+  int   NumberOfGradientEvaluations;
+  double MinFunctionValue;
+
+  // Description:
+  // Line Search Algorithms -- Modified to use vtkDoubleArray on Input Side
+
+  //BTX
+  // Global Data Structures
+  vtkDoubleArray* pcom,*xicom,*xtemp;
+  virtual void  AllocateLineTempCommons(vtkDoubleArray* position);
+  virtual void  CleanUpLineTempCommons();
+  virtual double LineMinimization(vtkDoubleArray* position, vtkDoubleArray* gradient,int iterno=-1,
+				 double tolerance=2.0e-4,const char* method=" ");
+  virtual double LineFunction(double x);
+  //ETX
+
+
+  double EvaluateFunction(vtkObject* f,vtkDoubleArray* p ) {
+    ++NumberOfFunctionEvaluations;
+    double v=this->InternalEvaluateFunction(f,p);
+    if (v<this->MinFunctionValue)
+      this->MinFunctionValue=v;
+    return v;
+  }
+
+  double BeginIteration(vtkObject* f,vtkDoubleArray* p ) {
+    if (this->InternalBeginIteration==NULL)
+      return -1.0;
+    return this->InternalBeginIteration(f,p);
+    
+  }
+
+
+  double EvaluateGradient(vtkObject* f,vtkDoubleArray* p,vtkDoubleArray* g ) {
+    ++NumberOfGradientEvaluations;
+    return this->InternalEvaluateGradient(f,p,g);
+  }
+
+  
+};
+
+
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxPickerPrismSource.cpp b/bioimagesuite30_src/Common/vtkpxPickerPrismSource.cpp
new file mode 100644
index 0000000..df3bf45
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxPickerPrismSource.cpp
@@ -0,0 +1,501 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxPickerPrismSource.h"
+#include "vtkObjectFactory.h"
+#include "pxutil.h"
+
+//-------------------------------------------------------------------------------------
+// Prism Data Structure from Larry Staib
+//-------------------------------------------------------------------------------------
+
+/*@(#)iibdef.txt	1.8 8/1/90*/
+/* L. Staib */
+class picker_iib
+{	/* Beginning of PRISM IIB Structure */
+
+
+public:
+  /***************************/
+  /**  Manufacturer's data  **/
+  /***************************/
+#define PRISM1  1           /* IIB Type Code for P1 Prism System */
+unsigned char   itc;        /* IIB Type Code */
+
+#define IIBVER  2           /* IIB Version Number */
+unsigned char   ivc;        /* IIB Version Code */
+
+char            mmd[10];    /* Machine Model; 8. char */
+
+char            msn[6];     /* Machine (Gantry) Serial number; 4. char */
+
+unsigned short  rbl;        /* Released Software Baseline Level */
+unsigned short  rtl;        /* Released Software TSKGEN Level */
+unsigned short  rpl;        /* Released Software Partial Level */
+
+	/*File Data Types*/
+#define IIBPRJ  01          /* Projection (raw) data */
+#define IIBCPR  02          /* Compressed data */
+#define IIBIMG  04          /* Image data */
+#define IIBFIL  010         /* File data */
+#define IIBLBI  020         /* XImage bitmap data */
+unsigned short  typ;        /* Type of data in this file */
+
+	/********************/
+	/**  Patient Data  **/
+	/********************/
+char            pn[22];     /* Patient Name; 20. char */
+
+char            pi[22];     /* Patient Identification; 20. char */
+
+unsigned char   pbm;        /* Patient birth month (1=Jan - 12=Dec) */
+unsigned char   pbd;        /* Patient birth day of month (1 - 31) */
+unsigned short  pby;        /* Patient birth year (e.g.: 1987) */
+
+char            sex[2];     /* Patient Sex; 1 character (M, F, O) */
+
+	/*********************/
+	/**  Hospital Data  **/
+	/*********************/
+
+char            rdn[22];    /* Radiologist's Name; 20. char */
+
+char            rpn[22];    /* Referring Physician's Name; 20. char */
+
+char            oi[4];      /* Operator Identification; 3 char (initials) */
+
+char            hn[22];     /* Hospital Name; 20. char */
+char            hi[22];     /* Hospital Identification; 20. char */
+
+	/***********************/
+	/**  Acquisition Data **/
+	/***********************/
+char            obs0[10];   /* unused space due to obsoleted fields */
+unsigned short  aqu;        /* Acquisition Number (for this patient) */
+unsigned short  obs1;       /* unused space due to obsoleted fields */
+
+unsigned char   atm;        /* Acquisition start month (1=Jan - 12=Dec) */
+unsigned char   atd;        /* Acquisition start day of month (1 - 31) */
+unsigned short  aty;        /* Acquisition start year (e.g.: 1987) */
+char            ati[10];    /* Acquisition start time (HH:MM:SS) */
+
+unsigned char   ctm;        /* Acquisition completion month (1=Jan - 12=Dec) */
+unsigned char   ctd;        /* Acquisition completion day of month (1 - 31) */
+unsigned short  cty;        /* Acquisition completion year (e.g.: 1987) */
+char            cti[10];    /* Acquisition completion time (HH:MM:SS) */
+
+	/*Acquisition types*/
+#define IIBINJ  04          /* injector synchronized scan */
+#define IIBEKG  010         /* ekg-gated scan */
+#define IIBRES  020         /* respiratory-gated scan */
+#define IIBDUA  0400        /* dual isotope scan */
+#define IIBSTP  01000       /* step-and-shoot */
+#define IIBCON  02000       /* continuous */
+#define IIBFLD  04000       /* Flood */
+#define IIBPLN  010000      /* Planar */
+#define IIBDYN  020000      /* Dynamic */
+#define IIBWBA  040000      /* Whole Body */
+unsigned short  at;         /* Acquisition type */
+
+short           ttp;        /* Absolute table traverse position in 0.1 mm */
+short           tth;        /* Absolute table height in 0.1 mm */
+
+	/*Data Modes*/
+#define IIBBYT  1           /* Byte-mode data */
+#define IIBWOR  2           /* Word-mode data */
+short           dmd;        /* Data mode flag */
+	/*Gantry Rotation Direction*/
+#define IIBCW   01          /* Clockwise Rotation */
+#define IIBCCW  02          /* Counter Clockwise Rotation */
+unsigned short  rod;        /* Rotation direction */
+
+unsigned short  ns;         /* Number of scans */
+
+short           sa;         /* Acquisition start angle in 0.1 degrees */
+short           ar;         /* Acquisition angle range in 0.1 degrees */
+short           npi;        /* Number of projections in this acquisition */
+
+unsigned short  tv;         /* Maximum time per step in 0.01 seconds */
+
+unsigned short  cps[4];     /* Kcounts per step per window (all heads) */
+
+	/*Rotation Orbit Types*/
+#define IIBCIR  01          /* circular */
+#define IIBELL  02          /* non-circular */
+#define IIBOOT  04          /* other */
+unsigned short  orb;        /* Rotation orbit type */
+
+unsigned short  orm[4];     /* Orbital radial map in 0.1 mm units */
+
+#define IIBPC1  1           /* Version 1 Prism camera 9.4x15.75 */
+#define IIBCAMTECHRECT 2    /* 14.5x20 camera with cropped corners */
+#define IIBCAMTECHHEX 3     /* Hex head */
+#define IIBCAMGENESYS 4     /* 15x20 camera with cropped corners */
+#define IIBCAMDYNAMO 5      /* 10 inch circular */
+unsigned short  cam;        /* Camera type */
+
+	/*Active Head and Window Bit Masks*/
+	/*Bit Number:    |15|14|13|12|11|10|9|8|7|6|5|4|3|2|1|0|*/
+	/*Head Number:   |  | 3| 2| 1|  | 3|2|1| |3|2|1| |3|2|1|*/
+	/*Window Number: | 4| 4| 4| 4| 3| 3|3|3|2|2|2|2|1|1|1|1|*/
+#define IIBHE1  010421      /* Head 1 active (0x1111) */
+#define IIBHE2  021042      /* Head 2 active (0x2222) */
+#define IIBHE3  042104      /* Head 3 active (0x4444) */
+unsigned short  hac;        /* Heads active */
+
+	/*Window Type Flags*/
+#define IIBWTK  01          /* keV window */
+#define IIBWCH  02          /* channel window */
+unsigned short  wtf;        /* Window type flag */
+
+	/*window center accessed from C as wce[3][4] or wce[head][window]*/
+unsigned short  wce[12];    /* window center */
+
+	/*window width in % accessed from C as wwi[3][4] or wwi[head][window]*/
+unsigned char   wwi[12];    /* window width in % */
+short           hvs[3];     /* High Voltage Settings */
+
+char            apx[12];    /* Acquisition pixel size x axis in mm (floating pt.) */
+char            apy[12];    /* Acquisition pixel size y axis in mm (floating pt.) */
+
+int             amx;        /* Acquisition x axis pixels */
+int             amy;        /* Acquisition y axis pixels */
+
+char            rnu[12];    /* radiopharmaceutical; 10 char */
+unsigned short  rnv;        /* radiopharmaceutical volume in 0.1 cc */
+unsigned short  rna;        /* radiopharmaceutical activity in 0.1 mCi units */
+unsigned char   rnm;        /* radiopharmaceutical injection month (1=Jan - 12=Dec) */
+unsigned char   rnd;        /* radiopharmaceutical injection day of month (1 - 31) */
+unsigned short  rny;        /* radiopharmaceutical injection year (e.g.: 1987) */
+char            rni[6];     /* radiopharmaceutical injection time (HH:MM) */
+
+	/*Isotope Half-Life*/
+#define IIBTMI  00          /* units of 0.01 minutes */
+#define IIBTHR  01          /* units of 0.01 hours */
+#define IIBTDA  02          /* units of 0.01 days */
+#define IIBTYR  03          /* units of 0.01 years */
+#define IIBTUK  04          /* units unknown */
+unsigned short  rhu;        /* isotope half-life time units */
+unsigned short  rhl;        /* isotope half-life in units shown above */
+
+	/*Isotope*/
+#define IIBITC  01          /* Tc-99m */
+#define IIBICO  02          /* Co-57 */
+#define IIBITL  04          /* Tl-201 */
+#define IIBIGA  010         /* Ga-97 */
+#define IIBIXE  020         /* Xe-133 */
+#define IIBI23  040         /* I-123 */
+#define IIBI31  0100        /* I-131 */
+#define IIBIN1  0200        /* In-111 */
+#define IIBUKI  0100000     /* unknown isotope or combination */
+unsigned short  iso;        /* isotope */
+
+	/*Collimator Descriptions*/
+#define IIBHF   1           /* 140keV HR fan */
+#define IIBHP   2           /* 140keV HR parallel */
+#define IIBPG   3           /* 140keV parallel gap */
+#define IIBFG   4           /* 140keV fan gap */
+#define IIBUF   5           /* 140keV UHR fan */
+#define IIBUP   6           /* 140keV UHR parallel */
+#define IIBMEF  7           /* 300keV fan */
+#define IIBMEP  8           /* 300keV parallel */
+#define IIBHEP  9           /* 400keV parallel */
+unsigned short  col;        /* collimator description */
+short           fbf[3];     /* fan beam focal distance in 0.1 mm units (per head) */
+short           fbx[3];     /* fan beam x-axis focus in 0.1 pixel units (256 mtx) */
+
+	/*patient direction in gantry values: H=headfirst, F=feetfirst*/
+char            pdg[2];     /* patient direction in gantry; 1 char */
+
+	/*patient orientation in gantry values:*/
+	/*S=supine, P=prone, L=leftdown, R=rightdown*/
+char            pog[2];     /* patient orientation in gantry; 1 char (S,P,L,R) */
+
+	/*Interval Information*/
+short           inn;        /* Interval Number */
+short           noi;        /* Number of Intervals */
+
+	/*View Termination Information:	Type (parameter)*/
+#define VTTIME  01          /* Time (0.01 seconds) */
+#define VTTRIG  02          /* Trigger (number of triggers) */
+#define VTTCOU  04          /* Counts (Kcounts per projection) */
+#define VTTDEN  010         /* Density (counts per pixel) */
+#define VTTCLO  020         /* Close on byte overflow */
+#define VTTWRA  040         /* Wraparound on byte overflow */
+unsigned short  vtt;        /* View Termination Type */
+int             vtp;        /* View Termination Parameter */
+
+	/*Beat Rejection Information*/
+#define NOBRT   00          /* No Beat Rejection (no parameters) */
+	/*Beat Rejection Types:	Type (parameters)*/
+#define BRT3P   01          /* 3 Bin Percentage (% and 0) */
+#define BRT3I   02          /* 3 Bin Interval (begin and end in msec) */
+#define BRT1P   03          /* 1 Bin Percentage (% and 0) */
+	/*Beat Rejection Masks*/
+#define BRTTYP  0377        /* Type Mask */
+#define BRTNOR  0400        /* Normal Bin */
+#define BRTSHO  01000       /* Short Bin */
+#define BRTLON  02000       /* Long Bin */
+unsigned short  brt;        /* Beat Rejection Type */
+short           brp[2];     /* Beat Rejection Parameters */
+	/*Acquisition Orientation*/
+unsigned short  ori;        /* Acquisition Orientation */
+
+	/*Gantry Type*/
+#define IIBGANPRISM 0       /* Prism gantry */
+#define IIBGANUNK 1         /* unknown gantry */
+#define IIBGANGEMINI 2      /* Gemini gantry */
+#define IIBGANOMEGA 3       /* Omega gantry */
+#define IIBGANDYNAMO 4      /* DynaMo gantry */
+#define IIBGENESYS 5        /* Genesys gantry */
+unsigned short  gan;        /* Gantry Type */
+
+	/*Corrections*/
+char            fn1[8];     /* 6 character flood name */
+char            fn2[8];     /* 6 character flood name, head 2 */
+char            fn3[8];     /* 6 character flood name, head 3 */
+
+#define IIBCORENERGY 01     /* Energy correction enabled */
+#define IIBCORFLOOD 02      /* Flood correction enabled */
+#define IIBCORLIN 04        /* Linearity correction enabled */
+#define IIBCORIRC 010       /* Image registration correction enabled */
+unsigned char   cor[4];     /* Acquisition corrections, 1 per head */
+
+	/*Second Isotope/Radiopharmaceutical*/
+char            rnu2[12];   /* radiopharmaceutical; 10 char */
+unsigned short  rnv2;       /* radiopharmaceutical volume in 0.1 cc */
+unsigned short  rna2;       /* radiopharmaceutical activity in 0.1 mCi units */
+unsigned char   rnm2;       /* radiopharmaceutical injection month (1=Jan - 12=Dec) */
+unsigned char   rnd2;       /* radiopharmaceutical injection day of month (1 - 31) */
+unsigned short  rny2;       /* radiopharmaceutical injection year (e.g.: 1987) */
+char            rni2[6];    /* radiopharmaceutical injection time (HH:MM) */
+unsigned short  rhu2;       /* isotope half-life time units */
+unsigned short  rhl2;       /* isotope half-life in units specified above */
+unsigned short  iso2;       /* isotope */
+
+	/*180 Recon Frame Range*/
+unsigned short  lvf;        /* Lowest valid frame */
+unsigned short  hvf;        /* Highest valid frame */
+
+char            zap[12];    /* z-axis pixel size in mm (floating pt.) */
+
+char			fill0[38];	/* UNUSED */
+
+	/*****************************************/
+	/**  Display/Reconstruction Information **/
+	/*****************************************/
+char            dxt[6];     /* display x-axis tag (bottom edge); 5 char */
+char            dyt[6];     /* display y-axis tag (left edge); 5 char */
+
+short           otw;        /* oblique twist (y/y) in degrees */
+short           oti;        /* oblique tilt (x/z) in degrees */
+
+	/*Processing Flags*/
+#define IIBSAG  01          /* sagittal */
+#define IIBCOR  02          /* coronal */
+#define IIBOBL  04          /* oblique */
+#define IIBOBS  010         /* oblique sagittal */
+#define IIBOBC  020         /* oblique coronal */
+#define IIBOBT  040         /* oblique transverse */
+#define IIBSAX  0100        /* short axis cardiac */
+#define IIBHLA  0200        /* horiz long axis cardiac */
+#define IIBVLA  0400        /* vert long axis cardiac */
+unsigned short  pf;         /* Processing Flag */
+
+#define IIBSCA  01          /* Scatter corrected */
+#define IIBADF  02          /* Adaptive filtered */
+unsigned short  ppf;        /* Post Processing Flags */
+
+char            rid[12];    /* Reconstruction ID; 10 char */
+
+unsigned char   rcm;        /* reconstruction month (1=Jan - 12=Dec) */
+unsigned char   rcd;        /* reconstruction day of month (1 - 31) */
+unsigned short  rcy;        /* reconstruction year (e.g.: 1987) */
+char            rci[10];    /* reconstruction time (HH:MM:SS) */
+
+char            cfs[16];    /* Convolution filter file spec; 15. char */
+
+	/*Pixel scaling, maximum, minimum pixel values*/
+short           upv;        /* Upper pixel value */
+short           lpv;        /* lower pixel value */
+
+	/*Transverse Slice Positioning*/
+unsigned short  slr;        /* Projection used as reference */
+short           slo;        /* Slice offset in pixels from first projection pixel */
+unsigned short  slt;        /* Reconstructed slice thickness in pixels */
+unsigned short  sls;        /* Distance between slices in mm */
+unsigned short  sln;        /* Number of slices */
+
+	/*Zoom recon parameters*/
+short           zx;         /* Zoom X ctr in mm; ctr of scan to ctr of zoom */
+short           zy;         /* Zoom Y ctr in mm; ctr of scan to ctr of zoom */
+unsigned short  zd;         /* Zoom recon diameter in mm */
+char            rpx[12];    /* Reconstructed pixel size x axis in mm (floating pt.) */
+char            rpy[12];    /* Reconstructed pixel size y axis in mm (floating pt.) */
+
+unsigned short  vsp;        /* Reconstructed view spacing in 0.25 degree units */
+
+int             rmx;        /* Reconstructed x axis pixels */
+int             rmy;        /* Reconstructed y axis pixels */
+
+#define ALCRC0  2           /* no-BP, ECT recon */
+#define ALCRC1  3           /* 180, no-BP, ECT recon */
+#define ALCRC2  4           /* standard BP, ECT recon */
+#define ALCRC3  5           /* 180, BP, ECT recon */
+#define ALCRC4  6           /* 360, BP, linear weighted, ECT recon */
+unsigned short  alc;        /* Reconstruction algorithm code */
+char            scl[12];    /* Reconstruction scale factor (floating pt.) */
+unsigned short  rsa;        /* Reconstruction start angle for 180+ */
+
+#define IIBAC0H 1           /* Automatic Head Chang AttCor Algorithm */
+#define IIBAC0T 2           /* Automatic Torso Chang AttCor Algorithm */
+#define IIBAC0M 3           /* Manual Chang AttCor Algorithm */
+unsigned short  atc;        /* Attenuation algorithm code */
+char            acv[12];    /* Attenuation coefficient (floating pt.) */
+char            acs[12];    /* AttCor Scale Factor (floating pt.) */
+
+	/*******************/
+	/** MISCELLANEOUS **/
+	/*******************/
+char            cl1[32];    /* Comment Line; 30 char */
+char            obs2[16];   /* unused space due to obsoleted field */
+char            mom[16];    /* parent file; 15 char */
+char            aid[12];    /* Acquisition ID; 10 char */
+char            vie[12];    /* Anatomical view; 10 char */
+char            org[12];    /* Organ description; 10 char */
+unsigned short  cvt;        /* 1=file converted from foreign format */
+unsigned int    ebo;        /* offset to first IIB extension block */
+unsigned int    imo;        /* offset to first image data */
+
+char			fill1[1268];	/* UNUSED */
+
+	/**************************/
+	/** END OF THE PRISM IIB **/
+	/**************************/
+};			/* End of PRISM IIB Structure */
+
+//------------------------------------------------------------------------------
+vtkpxPickerPrismSource* vtkpxPickerPrismSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxPickerPrismSource");
+  if(ret)
+    {
+      return (vtkpxPickerPrismSource*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxPickerPrismSource;
+}
+
+//------------------------------------------------------------------------------
+
+vtkpxPickerPrismSource::vtkpxPickerPrismSource()
+{
+  this->HeaderSize=2048;
+  this->SetFilePattern ("%s");
+
+}
+
+int vtkpxPickerPrismSource::ReadHeaderFile()
+{
+
+  picker_iib* hdr=new picker_iib;
+
+  gzFile fd=gzsuffixopen(this->FilePrefix,"rb");
+  if ((long)fd==0)
+    {
+      return 0;
+    }
+
+  gzread(fd,hdr,2048);
+  gzclose(fd);
+  this->read_volume_ok=1;
+
+  // Voxel Dimensions
+  float voxel_width=atof(hdr->rpx);
+  float voxel_height=atof(hdr->rpy);
+  float voxel_depth=atof(hdr->zap);
+
+  int dimx=hdr->rmx;
+  int dimy=hdr->rmy;
+  unsigned short dimz=hdr->sln;
+  int orient=hdr->pf;
+
+
+  unsigned short sls=hdr->sls;
+
+
+
+  if (dimx<0 || dimx>2048)
+    {
+      this->SwapBytes=1;
+      dimx=pxanaswapint(dimx);
+      dimy=pxanaswapint(dimy);
+      dimz=pxanaswapshort(dimz);
+      orient=pxanaswapint(orient);
+      sls=pxanaswapshort(sls);
+    }
+
+  
+
+
+  this->SetDataDimensions(dimx,dimy);
+  this->SetImageRange(1,dimz);
+  this->SetDataSpacing(voxel_width,voxel_height,voxel_depth);
+  this->SetNumTimeFrames(1);
+
+  switch(orient)
+    {
+    case 1: // Saggital
+      this->Orientation=2;
+      break;
+      
+    case 2: // Coronal
+      this->Orientation=1;
+      break;
+
+    default: // Axial
+      this->Orientation=0;
+    }
+
+
+  if (hdr->dmd==1)
+    this->FileType=1;
+  else
+    this->FileType=2;
+
+  this->HeaderSize=2048;
+
+  delete hdr;
+  return 8*this->FileType;
+}
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxPickerPrismSource.h b/bioimagesuite30_src/Common/vtkpxPickerPrismSource.h
new file mode 100644
index 0000000..5f18ba5
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxPickerPrismSource.h
@@ -0,0 +1,91 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxPickerPrismSource.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxPickerPrismSource - reads .mnc images from disk
+// .SECTION Description
+// This routines reads .psm (Picker Prism Image Files)
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkpxAnalyzeImageSourceOld
+
+#ifndef _vtkpxPickerPrismSource
+#define _vtkpxPickerPrismSource
+
+#include "vtkpxAnalyzeImageSourceOld.h"
+
+
+
+
+class vtkpxPickerPrismSource : public vtkpxAnalyzeImageSourceOld
+{
+public:
+  vtkTypeMacro(vtkpxPickerPrismSource,vtkpxAnalyzeImageSourceOld);
+  static vtkpxPickerPrismSource* New();
+
+  // Description:
+  // Overrides ReadHeaderFile from vtkpxAnalyzeImageSourceOld to read .picker header file
+  virtual int ReadHeaderFile();
+
+
+protected:
+  vtkpxPickerPrismSource();
+
+};
+
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxSignaLXImageSource.cpp b/bioimagesuite30_src/Common/vtkpxSignaLXImageSource.cpp
new file mode 100644
index 0000000..db4a063
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxSignaLXImageSource.cpp
@@ -0,0 +1,364 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSignaLXImageSource.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxSignaLXImageSource.h"
+#include "vtkUnsignedShortArray.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkShortArray.h"
+#include "vtkFloatArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "pxutil.h"
+
+//------------------------------------------------------------------------------
+vtkpxSignaLXImageSource* vtkpxSignaLXImageSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxSignaLXImageSource");
+  if(ret)
+    {
+      return (vtkpxSignaLXImageSource*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxSignaLXImageSource;
+}
+
+// Construct object with NULL file prefix; file pattern "%s.%d"; image range 
+// set to (1,1); data origin (0,0,0); data spacing (1,1,1); no data mask;
+// header size 0; and byte swapping turned off.
+
+vtkpxSignaLXImageSource::vtkpxSignaLXImageSource()
+{
+  this->SetFilePattern ("%s%d");
+}
+
+//------------------------------------------------------------------------------
+// Read signa header file
+// ---------------------------
+int vtkpxSignaLXImageSource::ReadHeaderFile()
+{
+
+  anaimagedata *hdr=new anaimagedata;
+
+  char filename[1024];
+  if (this->FilePattern)
+    {
+      sprintf (filename, this->FilePattern, this->FilePrefix, ImageRange[0]);
+    }
+  else
+    {
+      sprintf (filename, this->FilePattern, ImageRange[0]);
+    }
+
+  int bits=readlxhdr(filename,hdr);
+
+  if (bits==0)
+      {
+	delete hdr;
+	return 0;
+      }
+
+  this->read_volume_ok=1;
+  this->SetDataDimensions(hdr->xsize,hdr->ysize);
+  this->SetNumTimeFrames(hdr->tsize);
+
+  if (hdr->xpix>0.01)
+    {
+      this->SetDataSpacing(hdr->xpix,hdr->ypix,hdr->zpix);
+    }
+  else
+    {
+      this->SetDataSpacing(1.0,1.0,1.0);
+    }
+  
+  if (bits<0)
+    this->SwapBytes = 1;
+  else
+    this->SwapBytes = 0;
+  
+  this->Orientation=hdr->orient;
+  this->FileType=2;
+  
+  delete hdr;
+
+  
+  vtkDebugMacro(<<"Read Header " << this->FilePrefix << " Dime="<<this->DataDimensions[0]<<"*"<<this->DataDimensions[0]<<" Orient= "<<this->Orientation<< " Swap= " << this->SwapBytes);
+  
+  return bits;
+}
+
+vtkDataArray* vtkpxSignaLXImageSource::ReadVolume(int first, int last)
+{
+  
+  this->MultipleFramesAsComponents=0;
+  if (this->read_volume_ok==0)
+      {
+	vtkDebugMacro(<<"Not updating");
+	return NULL;      
+      }
+
+  if (!this->FilePrefix)
+    return NULL;
+
+  
+  int numPts = this->DataDimensions[0] * this->DataDimensions[1];
+  int numberSlices = last - first+1;
+
+  vtkShortArray* scalars = vtkShortArray::New();
+  scalars->SetNumberOfComponents(1);
+  scalars->SetNumberOfTuples(numPts * numberSlices);
+  short *slice = ((vtkShortArray *)scalars)->WritePointer(0, numPts*numberSlices);
+
+  this->UpdateProgress(0.0);
+  float oldpog=0.0;
+
+  int offsetposition=0;
+  int skip=0;
+  for (int sliceNumber = first; sliceNumber <= last; sliceNumber++) 
+    {
+      char filename[1024];
+      if (this->FilePattern)
+	{
+	  sprintf (filename, this->FilePattern, this->FilePrefix, sliceNumber);
+	}
+      else
+	{
+	  sprintf (filename, this->FilePattern, sliceNumber);
+	}
+      
+      if (sliceNumber == first)
+	{ 
+	  // Figure Skip stuff once and for all 
+	  gzFile fp2 = gzsuffixopen(filename,"rb");
+	  if (fp2==0)
+	    {
+	      vtkErrorMacro(<<"Can't find file: " << filename);
+	      scalars->Delete();
+	      return NULL;
+	    }
+	  char t;
+	  int flag=0,total=0;
+	  while (flag==0)
+	    {
+	      if (gzread(fp2,&t,1)!=0)
+		++total;
+	      else
+		flag=1;
+	    }
+	  gzclose(fp2);
+	  skip=total-numPts*2;
+	  vtkDebugMacro(<< "File Size = " << total << " Skip = " << skip << " (numPts="<<numPts<<")");
+	}
+      
+      gzFile fp = gzsuffixopen(filename,"rb");
+      if (fp==0)
+	{
+	  vtkErrorMacro(<<"Can't find file: " << filename);
+	  scalars->Delete();
+	  return NULL;
+	}
+      
+      vtkDebugMacro ( << "Reading " << filename );
+      
+      float pog=float(sliceNumber-first)/float(last-first+1);
+      if ( (pog-oldpog)>0.1)
+	{
+	  this->UpdateProgress(pog);
+	  oldpog=pog;
+	}
+      
+      ReadBinaryImage (fp, &slice[offsetposition], 
+		       this->DataDimensions[0], 
+		       this->DataDimensions[1], 
+		       skip,this->SwapBytes);
+      offsetposition+=numPts;	      
+      gzclose (fp);
+    }
+  
+  
+  this->UpdateProgress(1.0);
+  this->read_volume_ok=0;
+
+  /*  if (Debug)
+      {*/
+      double rv[2];
+      scalars->GetRange(rv);
+      int bits2=16;
+               
+      char line[180];
+      sprintf(line,"\n%s\n Dimensions %d x %d x %d (%d) (%5.2f %5.2f %5.2f)\n Bits=%d (%d) Swap=%d Range=%f:%f\n",
+	      this->FilePrefix,this->DataDimensions[0],this->DataDimensions[1],this->ImageRange[1]-this->ImageRange[0]+1,numberSlices,
+	      this->DataSpacing[0],this->DataSpacing[1],this->DataSpacing[2],
+	      8*FileType,bits2,this->SwapBytes,rv[0],rv[1]);
+      vtkDebugMacro(<<line);
+      //}
+  return scalars;
+}
+//------------------------------------------------------------------------------
+int vtkpxSignaLXImageSource::Load(const char *ana)
+{
+  return this->Load(ana,1,1);
+}
+
+int vtkpxSignaLXImageSource::Load(const char *ana,int begin,int end)
+{
+  this->SetFilePrefix(ana);
+  this->SetImageRange(begin,end);
+  int ok=this->ReadHeaderFile();
+  if (ok!=0)
+      this->Update();
+  return ok;
+}
+//------------------------------------------------------------------------------
+void vtkpxSignaLXImageSource::Execute()
+{
+
+  if (this->FilePrefix == NULL) 
+      {
+	vtkErrorMacro(<< "FilePrefix is NULL");
+	return;
+      }
+  
+  if (this->HeaderSize < 0) 
+      {
+	vtkErrorMacro(<< "HeaderSize " << this->HeaderSize << " must be >= 0");
+	return;
+      }
+  
+  if (this->DataDimensions[0] <= 0 || this->DataDimensions[1] <= 0) 
+      {
+	vtkErrorMacro(<< "x, y dimensions " << this->DataDimensions[0] << ", " << this->DataDimensions[1] 
+		      << "must be greater than 0.");    
+	return;
+      } 
+  
+  int first = this->ImageRange[0];
+  int last = this->ImageRange[1];
+
+  if (this->FileType==0)
+    first=1;
+
+  vtkDataArray* tmpScalars = this->ReadVolume(first, last);
+  vtkDataArray* newScalars=tmpScalars;
+  int deletenewscalars=0;
+
+
+  //  fprintf(stderr,"Read %d x %d scalars\n",tmpScalars->GetNumberOfTuples(),tmpScalars->GetNumberOfComponents());
+  
+  if (!tmpScalars)
+    return;
+
+  if (this->ForceOutputToShort==1)
+    {
+      if (newScalars->GetDataType()==VTK_FLOAT)
+	{
+	  newScalars=vtkDataArray::CreateDataArray(VTK_SHORT);
+	  newScalars->DeepCopy(tmpScalars);
+	  deletenewscalars=1;
+	}
+    }
+
+  int dimensions[3]; 
+  dimensions[0] = this->DataDimensions[0];
+  dimensions[1] = this->DataDimensions[1];
+  dimensions[2] = this->ImageRange[1] - this->ImageRange[0] + 1;
+
+  vtkImageData* output=this->GetOutput();
+  output->SetSpacing(this->DataSpacing);
+  output->SetOrigin(this->DataOrigin);
+  output->SetScalarType(newScalars->GetDataType());
+  
+  if (this->MultipleFramesAsComponents==1 && this->NumTimeFrames>1)
+    {
+      int dim[3];
+      for (int ia=0;ia<=2;ia++)
+	dim[ia]=dimensions[ia];
+      dim[2]/=this->NumTimeFrames;
+  
+      output->SetNumberOfScalarComponents(this->NumTimeFrames);
+      output->SetDimensions(dim);
+      output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+      output->AllocateScalars();
+      
+      for (int comp=0;comp<NumTimeFrames;comp++)
+	{
+	  int index=comp*dim[0]*dim[1]*dim[2];
+	  for (int k=0;k<dim[2];k++)
+	    for (int j=0;j<dim[1];j++)
+	      for (int i=0;i<dim[0];i++)
+		{
+		  output->SetScalarComponentFromDouble(i,j,k,comp,newScalars->GetComponent(index,0));
+		  ++index;
+		}
+	}
+      
+    }
+  else
+    {
+      output->SetDimensions(dimensions);
+      output->SetWholeExtent(0,dimensions[0]-1,0,dimensions[1]-1,0,dimensions[2]-1);
+      output->SetNumberOfScalarComponents(newScalars->GetNumberOfComponents());
+      output->GetPointData()->SetScalars(newScalars);
+
+    }
+     
+  if (deletenewscalars)
+    newScalars->Delete();
+  tmpScalars->Delete();
+    
+
+
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxSignaLXImageSource.h b/bioimagesuite30_src/Common/vtkpxSignaLXImageSource.h
new file mode 100644
index 0000000..c447a02
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxSignaLXImageSource.h
@@ -0,0 +1,101 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSignaLXImageSource.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxSignaLXImageSource - reads analyze (or binary) 3d images 
+// .SECTION Description
+// .SECTION See Also
+//  vtkpxAnalyzeImageWriter vtkpxAnalyzeImageSourceOld
+
+
+#ifndef __vtkpxSignaLXImageSource
+#define __vtkpxSignaLXImageSource
+
+#include <stdio.h>
+#include "vtkpxAnalyzeImageSourceOld.h"
+#include "pxutil.h"
+
+
+class vtkpxSignaLXImageSource : public vtkpxAnalyzeImageSourceOld
+{
+public:
+  vtkTypeMacro(vtkpxSignaLXImageSource,vtkpxAnalyzeImageSourceOld);
+  static vtkpxSignaLXImageSource* New();
+
+  // Description:
+  // Convenience Routine for analyze images -- simply use Load("e3305s1i",1,16)
+  virtual int  Load(const char* fname,int begin,int end);
+    
+  // Description:
+  // Reads Header first set using SetFilePrefix
+  virtual int  ReadHeaderFile();
+
+
+protected:
+
+  vtkpxSignaLXImageSource();
+  virtual vtkDataArray *ReadVolume(int FirstImage, int LastImage);
+
+
+  // Description:
+  // Convenience Routine for analyze images 
+  virtual int  Load(const char* fname);
+  virtual void Execute();
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxSimpleImageToImageFilter.cpp b/bioimagesuite30_src/Common/vtkpxSimpleImageToImageFilter.cpp
new file mode 100644
index 0000000..17cd9a8
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxSimpleImageToImageFilter.cpp
@@ -0,0 +1,163 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// Renamed vtkpxSimpleImageToImageFilter
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkInformation.h"
+
+vtkCxxRevisionMacro(vtkpxSimpleImageToImageFilter, "$Revision: 1.11 $");
+
+//----------------------------------------------------------------------------
+vtkpxSimpleImageToImageFilter::vtkpxSimpleImageToImageFilter()
+{
+  this->NumberOfRequiredInputs = 1;
+  this->SetNumberOfInputPorts(1);
+}
+
+//----------------------------------------------------------------------------
+vtkpxSimpleImageToImageFilter::~vtkpxSimpleImageToImageFilter()
+{
+}
+
+//----------------------------------------------------------------------------
+void vtkpxSimpleImageToImageFilter::SetInput(vtkImageData *input)
+{
+  this->vtkProcessObject::SetNthInput(0, input);
+}
+
+//----------------------------------------------------------------------------
+vtkImageData *vtkpxSimpleImageToImageFilter::GetInput()
+{
+  if (this->NumberOfInputs < 1)
+    {
+    return NULL;
+    }
+  
+  return (vtkImageData *)(this->Inputs[0]);
+}
+
+void vtkpxSimpleImageToImageFilter::ExecuteInformation()
+{
+  vtkImageData *input = this->GetInput();
+  vtkImageData *output = this->GetOutput();
+
+  // Make sure the Input has been set.
+  if ( input == NULL)
+    {
+    vtkErrorMacro(<< "ExecuteInformation: Input is not set.");
+    return;
+    }
+
+  // Start with some defaults.
+  output->CopyTypeSpecificInformation( input );
+}
+
+
+void vtkpxSimpleImageToImageFilter::ComputeInputUpdateExtent( int inExt[6], 
+                                                            int vtkNotUsed(outExt)[6] )
+{
+  vtkImageData *input = this->GetInput();
+  // Make sure the Input has been set.
+  if ( input == NULL)
+    {
+    vtkErrorMacro(<< "ComputeInputUpdateExtent: Input is not set.");
+    return;
+    }
+  int* wholeExtent = input->GetWholeExtent();
+  memcpy(inExt,wholeExtent,sizeof(int)*6);
+}
+
+void vtkpxSimpleImageToImageFilter::ExecuteData(vtkDataObject *vtkNotUsed(out))
+{
+
+  vtkDebugMacro("Executing.");
+  vtkImageData* output = this->GetOutput();
+  vtkImageData* input = this->GetInput();
+
+  if (!input)
+    {
+    vtkErrorMacro("No input is specified!");
+    return;
+    }
+
+  // Too many filters have floating point exceptions to execute
+  // with empty input/ no request.
+  if (this->UpdateExtentIsEmpty(output))
+    {
+    return;
+    }
+
+  // Set the extent of the output and allocate memory.
+  output->SetExtent(output->GetWholeExtent());
+  output->AllocateScalars();
+
+  this->SimpleExecute(input, output);
+}
+
+//----------------------------------------------------------------------------
+void vtkpxSimpleImageToImageFilter::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+}
+
+int vtkpxSimpleImageToImageFilter::FillInputPortInformation(int port,vtkInformation* info)
+{
+  if(!this->Superclass::FillInputPortInformation(port, info))
+    {
+      return 0;
+    }
+  info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkImageData");
+  return 1;
+}
+
+
+// ----------------------------------------------------------------------------
+void vtkpxSimpleImageToImageFilter::AddInput(vtkImageData *input)
+{
+  this->vtkProcessObject::AddInput(input);
+}
+
+//----------------------------------------------------------------------------
+void vtkpxSimpleImageToImageFilter::SetInput(int idx, vtkImageData *input)
+{
+  this->vtkProcessObject::SetNthInput(idx, input);
+}
+
+//----------------------------------------------------------------------------
+vtkImageData *vtkpxSimpleImageToImageFilter::GetInput(int idx)
+{
+  if (this->NumberOfInputs <= idx)
+    {
+      return NULL;
+    }
+  
+  return (vtkImageData*)(this->Inputs[idx]);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Common/vtkpxSimpleImageToImageFilter.h b/bioimagesuite30_src/Common/vtkpxSimpleImageToImageFilter.h
new file mode 100644
index 0000000..2a17b50
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxSimpleImageToImageFilter.h
@@ -0,0 +1,118 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// .NAME vtkpxSimpleImageToImageFilter - Generic image filter with one input.
+// .SECTION Description
+// vtkpxSimpleImageToImageFilter is a filter which aims to avoid much
+// of the complexity associated with vtkImageToImageFilter (i.e.
+// support for pieces, multi-threaded operation). If you need to write
+// a simple image-image filter which operates on the whole input, use
+// this as the superclass. The subclass has to provide only an execute
+// method which takes input and output as arguments. Memory allocation
+// is handled in vtkpxSimpleImageToImageFilter. Also, you are guaranteed to
+// have a valid input in the Execute(input, output) method. By default, 
+// this filter
+// requests it's input's whole extent and copies the input's information
+// (spacing, whole extent etc...) to the output. If the output's setup
+// is different (for example, if it performs some sort of sub-sampling),
+// ExecuteInformation has to be overwritten. As an example of how this
+// can be done, you can look at vtkImageShrink3D::ExecuteInformation.
+// For a complete example which uses templates to support generic data
+// types, see  vtkpxSimpleFilterExample.
+
+// .SECTION See also
+// vtkImageToImageFilter vtkpxSimpleImageFilterExample
+
+#ifndef __vtkpxSimpleImageToImageFilter_h
+#define __vtkpxSimpleImageToImageFilter_h
+
+#include "vtkImageSource.h"
+
+class  vtkpxSimpleImageToImageFilter : public vtkImageSource
+{
+public:
+  vtkTypeRevisionMacro(vtkpxSimpleImageToImageFilter,vtkImageSource);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Set the Input of a filter. 
+  virtual void SetInput(vtkImageData *input);
+  vtkImageData *GetInput();
+
+  // Multiple Input Stuff
+  // --------------------
+  // Description:
+  // Set an Input of this filter. 
+  virtual void SetInput(int num, vtkImageData *input);
+
+  // Description:
+  // Adds an input to the first null position in the input list.
+  // Expands the list memory if necessary
+  virtual void AddInput(vtkImageData *input);
+  
+  // Description:
+  // Get one input to this filter.
+  vtkImageData *GetInput(int num);
+
+  
+  // Description:
+  // More Compatibility Hacks
+  vtkImageData* GetImageDataInput(int n) { return this->GetInput(n);}
+  int GetNumberOfInputPorts() { return this->GetNumberOfInputs();}
+
+
+protected:
+  vtkpxSimpleImageToImageFilter();
+  ~vtkpxSimpleImageToImageFilter();
+
+  // These are called by the superclass.
+  // You might have to override ExecuteInformation
+  virtual void ExecuteInformation();
+  virtual void ComputeInputUpdateExtent(int inExt[6], int outExt[6]);
+
+  // You don't have to touch this unless you have a good reason.
+  virtual void ExecuteData(vtkDataObject *output);
+  // In the simplest case, this is the only method you need to define.
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output) = 0;
+
+  // This is needed for VTK5
+  virtual int FillInputPortInformation(int, vtkInformation*);
+
+private:
+  vtkpxSimpleImageToImageFilter(const vtkpxSimpleImageToImageFilter&);  // Not implemented.
+  void operator=(const vtkpxSimpleImageToImageFilter&);  // Not implemented.
+};
+
+#endif
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxStructuredPointsToStructuredPointsFilter.cpp b/bioimagesuite30_src/Common/vtkpxStructuredPointsToStructuredPointsFilter.cpp
new file mode 100644
index 0000000..0bfe549
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxStructuredPointsToStructuredPointsFilter.cpp
@@ -0,0 +1,103 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxStructuredPointsToStructuredPointsFilter.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageToStructuredPoints.h"
+
+vtkpxStructuredPointsToStructuredPointsFilter* vtkpxStructuredPointsToStructuredPointsFilter::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxStructuredPointsToStructuredPointsFilter");
+  if(ret)
+    {
+    return (vtkpxStructuredPointsToStructuredPointsFilter*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxStructuredPointsToStructuredPointsFilter;
+}
+
+
+//----------------------------------------------------------------------------
+// Specify the input data or filter.
+void vtkpxStructuredPointsToStructuredPointsFilter::SetInput(vtkImageData *input0)
+{
+  vtkImageToStructuredPoints* filt=vtkImageToStructuredPoints::New();
+  filt->SetInput(input0);
+  filt->Update();
+  this->SetInput(filt->GetOutput());
+  filt->Delete();
+}
+
+void vtkpxStructuredPointsToStructuredPointsFilter::SetInput(vtkStructuredPoints *input)
+{
+  this->vtkProcessObject::SetNthInput(0, input);
+}
+
+//----------------------------------------------------------------------------
+// Specify the input data or filter.
+vtkStructuredPoints *vtkpxStructuredPointsToStructuredPointsFilter::GetInput()
+{
+  if (this->NumberOfInputs < 1)
+    {
+      return NULL;
+    }
+  
+  return (vtkStructuredPoints *)(this->Inputs[0]);
+}
+
+
+//----------------------------------------------------------------------------
+// Copy WholeExtent, Spacing and Origin.
+void vtkpxStructuredPointsToStructuredPointsFilter::ExecuteInformation()
+{
+  vtkStructuredPoints *input = this->GetInput();
+  vtkStructuredPoints *output = this->GetOutput();
+  
+  if (output == NULL || input == NULL)
+    {
+      return;
+    }
+  
+  output->SetWholeExtent(input->GetWholeExtent());
+  output->SetSpacing(input->GetSpacing());
+  output->SetOrigin(input->GetOrigin());
+}
+
+
+//----------------------------------------------------------------------------
+void vtkpxStructuredPointsToStructuredPointsFilter::ComputeInputUpdateExtents( 
+                                                        vtkDataObject *output)
+{
+  this->vtkStructuredPointsSource::ComputeInputUpdateExtents(output);
+  this->GetInput()->RequestExactExtentOn();
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxStructuredPointsToStructuredPointsFilter.h b/bioimagesuite30_src/Common/vtkpxStructuredPointsToStructuredPointsFilter.h
new file mode 100644
index 0000000..9f7d5ca
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxStructuredPointsToStructuredPointsFilter.h
@@ -0,0 +1,87 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkpxStructuredPointsToStructuredPointsFilter - abstract filter class
+// .SECTION Description
+// vtkpxStructuredPointsToStructuredPointsFilter is an abstract filter class 
+// whose subclasses take on input structured points and generate
+// structured points on output.
+
+// .SECTION See Also
+// vtkExtractVOI vtkImageDifference vtkSweptSurface
+// vtkTransformStructuredPoints
+
+#ifndef __vtkpxStructuredPointsToStructuredPointsFilter_h
+#define __vtkpxStructuredPointsToStructuredPointsFilter_h
+
+#include "vtkStructuredPointsToStructuredPointsFilter.h"
+#include "vtkStructuredPoints.h"
+
+
+
+class vtkpxStructuredPointsToStructuredPointsFilter : public vtkStructuredPointsToStructuredPointsFilter
+{
+public:
+  vtkTypeMacro(vtkpxStructuredPointsToStructuredPointsFilter,vtkStructuredPointsToStructuredPointsFilter);
+
+
+  // Description:
+  // Construct object to extract all of the input data.
+  static vtkpxStructuredPointsToStructuredPointsFilter *New();
+
+  // Description:
+  // Set / get the input data or filter.
+  void SetInput(vtkStructuredPoints *input);
+  void SetInput(vtkImageData *input);
+  vtkStructuredPoints *GetInput();
+
+  
+protected:
+  vtkpxStructuredPointsToStructuredPointsFilter() {this->NumberOfRequiredInputs = 1;};
+  ~vtkpxStructuredPointsToStructuredPointsFilter() {};
+
+
+  // Since input[0] and output are of same type, we can create this
+  // method that defaults to just copying information.
+  void ExecuteInformation();
+  void ComputeInputUpdateExtents(vtkDataObject *output);
+
+
+private:
+  vtkpxStructuredPointsToStructuredPointsFilter(const vtkpxStructuredPointsToStructuredPointsFilter&);  
+  void operator=(const vtkpxStructuredPointsToStructuredPointsFilter&);  
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxTensorBSplineTransform.cpp b/bioimagesuite30_src/Common/vtkpxTensorBSplineTransform.cpp
new file mode 100644
index 0000000..cca7e3f
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxTensorBSplineTransform.cpp
@@ -0,0 +1,1472 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkpxTensorBSplineTransform.h"
+#include "vtkMath.h"
+#include "vtkImageData.h"
+#include "vtkDoubleArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkCollection.h"
+#include "pxisinf.h"
+
+//----------------------------------------------------------------------------
+vtkpxTensorBSplineTransform* vtkpxTensorBSplineTransform::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxTensorBSplineTransform");
+  if(ret)
+    {
+      return (vtkpxTensorBSplineTransform*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxTensorBSplineTransform;
+}
+
+//------------------------------------------------------------------------
+vtkpxTensorBSplineTransform::vtkpxTensorBSplineTransform()
+{
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->Dimensions[ia]=0;
+      this->Origin[ia]=0.0;
+      this->Spacing[ia]=1.0;
+      this->OffsetDimensions[ia]=1;
+    }
+
+  this->WholeImageCache=NULL;
+  this->DetailImageCache=NULL;
+  this->Displacements=NULL;
+  this->CachedPointsInfo=NULL;
+  this->CachedPoints=NULL;
+  this->ActiveControlPointList=NULL;
+  this->ControlPointStatus=NULL;
+  this->NumberOfActiveComponents=3;
+  this->CacheMode=0;
+}
+//------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::Copy(vtkpxTensorBSplineTransform* other)
+{
+  if (other==NULL)
+    {
+      vtkErrorMacro(<<"Copy Transform given NULL argument");
+      return;
+    }
+  other->GetDimensions(this->Dimensions);
+  other->GetOffsetDimensions(this->OffsetDimensions);
+  other->GetSpacing(this->Spacing);
+  other->GetOrigin(this->Origin);
+  this->NumberOfActiveComponents=other->GetNumberOfActiveComponents();
+  this->CacheMode=other->GetCacheMode();
+  this->NumberOfControlPoints=other->GetNumberOfControlPoints();
+
+  if (other->GetDisplacements()!=NULL)
+    {
+      if (this->Displacements==NULL)
+	this->Displacements=vtkDoubleArray::New();
+      this->Displacements->DeepCopy(other->GetDisplacements());
+    }
+  else
+    {
+      if (this->Displacements!=NULL)
+	this->Displacements->Delete();
+      this->Displacements=NULL;
+    }
+
+  if (other->GetControlPointStatus()!=NULL)
+    {
+      if (this->ActiveControlPointList==NULL)
+	this->ActiveControlPointList=vtkIntArray::New();
+      if (this->ControlPointStatus==NULL)
+	this->ControlPointStatus=vtkCharArray::New();
+
+      this->ControlPointStatus->DeepCopy(other->GetControlPointStatus());
+      this->ActiveControlPointList->DeepCopy(other->GetActiveControlPointList());
+      
+    }
+  else
+    {
+      if (this->ActiveControlPointList!=NULL)
+	this->ActiveControlPointList->Delete();
+      if (this->ControlPointStatus==NULL)
+	this->ControlPointStatus->Delete();
+      
+      this->ActiveControlPointList=NULL;
+      this->ControlPointStatus=NULL;
+    }
+  
+  if (other->GetWholeImageCache()!=NULL)
+    {
+      if (this->WholeImageCache==NULL)
+	this->WholeImageCache=vtkImageData::New();
+      this->WholeImageCache->DeepCopy(other->GetWholeImageCache());
+    }
+  else
+    {
+      if (this->WholeImageCache!=NULL)
+	this->WholeImageCache->Delete();
+      this->WholeImageCache=NULL;
+    }
+
+
+  if (other->GetDetailImageCache()!=NULL)
+    {
+      if (this->DetailImageCache==NULL)
+	this->DetailImageCache=vtkImageData::New();
+      this->DetailImageCache->DeepCopy(other->GetDetailImageCache());
+    }
+  else
+    {
+      if (this->DetailImageCache!=NULL)
+	this->DetailImageCache->Delete();
+      this->DetailImageCache=NULL;
+    }
+
+  if (other->GetCachedPointsInfo()!=NULL)
+    {
+      if (this->CachedPointsInfo==NULL)
+	this->CachedPointsInfo=vtkFloatArray::New();
+      this->CachedPointsInfo->DeepCopy(other->GetCachedPointsInfo());
+    }
+  else
+    {
+      if (this->CachedPointsInfo!=NULL)
+	this->CachedPointsInfo->Delete();
+      this->CachedPointsInfo=NULL;
+    }
+
+  if (other->GetCachedPoints()!=NULL)
+    {
+      if (this->CachedPoints==NULL)
+	this->CachedPoints=vtkPolyData::New();
+      this->CachedPoints->DeepCopy(other->GetCachedPoints());
+    }
+  else
+    {
+      if (this->CachedPoints!=NULL)
+	this->CachedPoints->Delete();
+      this->CachedPoints=NULL;
+    }
+}
+//------------------------------------------------------------------------
+vtkpxTensorBSplineTransform::~vtkpxTensorBSplineTransform()
+{
+  if (this->WholeImageCache!=NULL)
+    this->WholeImageCache->Delete();
+
+  if (this->DetailImageCache!=NULL)
+    this->DetailImageCache->Delete();
+
+  if (this->Displacements!=NULL)
+    this->Displacements->Delete();
+
+  if (this->CachedPointsInfo!=NULL)
+    this->CachedPointsInfo->Delete();
+
+  if (this->CachedPoints!=NULL)
+    this->CachedPoints->Delete();
+
+  if (this->ActiveControlPointList!=NULL)
+    this->ActiveControlPointList->Delete();
+
+  if (this->ControlPointStatus!=NULL)
+    this->ControlPointStatus=NULL;
+}
+
+//------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkWarpTransform::PrintSelf(os,indent);
+  
+}
+
+//----------------------------------------------------------------------------
+vtkAbstractTransform *vtkpxTensorBSplineTransform::MakeTransform()
+{
+  return vtkpxTensorBSplineTransform::New(); 
+}
+
+//----------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::InternalDeepCopy(vtkAbstractTransform *transform)
+{
+  vtkpxTensorBSplineTransform *t = (vtkpxTensorBSplineTransform *)transform;
+
+  this->SetInverseTolerance(t->InverseTolerance);
+  this->SetInverseIterations(t->InverseIterations);
+  //  this->SetLandmarks(t->Landmarks);
+
+  if (this->InverseFlag != t->InverseFlag)
+    {
+      this->InverseFlag = t->InverseFlag;
+      this->Modified();
+    }
+}
+//------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::InternalUpdate()
+{
+  return;
+}
+//------------------------------------------------------------------------
+template<class T>
+static inline void vtkpxTensorBSplineForwardTransformPoint(vtkpxTensorBSplineTransform *self,const T point[3], T output[3])
+{
+  double s[3];
+  int  lat[3];
+
+  double pp[3]; 
+  for (int ia=0;ia<=2;ia++)
+    {
+      pp[ia]=point[ia];
+      output[ia]=point[ia];
+    }
+  
+  self->GetCoordinatesInGrid(pp,lat,s);
+
+  int GridDimensions[3]; self->GetDimensions(GridDimensions);
+  int GridSliceDimensions=GridDimensions[0]*GridDimensions[1];
+  double ori[3]; self->GetOrigin(ori);
+  double spa[3]; self->GetSpacing(spa);
+  
+
+  for (int k = 0; k < 4; k++)
+    {
+      int K = Irange(k + lat[2] - 1,0,GridDimensions[2]-1);
+      for (int j = 0; j < 4; j++)
+	{
+	  int J = Irange(j + lat[1] - 1,0,GridDimensions[1]-1);
+	  for (int i = 0; i < 4; i++)
+	    {
+	      int I = Irange(i + lat[0] - 1,0,GridDimensions[0]-1);
+	      int   cpoint=I+J*GridDimensions[0]+K*GridSliceDimensions;
+	      double wgt= vtkpxTensorBSplineTransform::B(i, s[0]) * vtkpxTensorBSplineTransform::B(j, s[1]) * vtkpxTensorBSplineTransform::B(k, s[2]);
+	      double d[3]; self->GetControlPointDisplacement(cpoint,d);
+	      for (int ia=0;ia<=2;ia++)
+		output[ia]+=wgt*d[ia];
+	    }
+	}
+    }
+
+}
+//------------------------------------------------------------------------
+template<class T>
+static inline void vtkpxTensorBSplineTransformDerivative(vtkpxTensorBSplineTransform *self,const T point[3], T output[3],T derivative[3][3])
+{
+  
+  double s[3];
+  int  lat[3];
+  
+  double pp[3]; 
+  for (int ia=0;ia<=2;ia++)
+    {
+      pp[ia]=point[ia];
+      output[ia]=0.0;
+      for (int ib=0;ib<=2;ib++)
+	derivative[ia][ib]=0.0;
+    }
+  
+  self->GetCoordinatesInGrid(pp,lat,s);
+
+  int GridDimensions[3]; self->GetDimensions(GridDimensions);
+  int GridSliceDimensions=GridDimensions[0]*GridDimensions[1];
+  
+ 
+  for (int k = 0; k < 4; k++)
+    {
+      int K = Irange(k + lat[2] - 1,0,GridDimensions[2]-1);
+      for (int j = 0; j < 4; j++)
+	{
+	  int J = Irange(j + lat[1] - 1,0,GridDimensions[1]-1);
+	  for (int i = 0; i < 4; i++)
+	    {
+	      int I = Irange(i + lat[0] - 1,0,GridDimensions[0]-1);
+	      int   cpoint=I+J*GridDimensions[0]+K*GridSliceDimensions;
+	      double wgt= vtkpxTensorBSplineTransform::B(i, s[0]) * vtkpxTensorBSplineTransform::B(j, s[1]) * vtkpxTensorBSplineTransform::B(k, s[2]);
+	      double w[3];
+	      w[0]=vtkpxTensorBSplineTransform::dB(i, s[0]) * vtkpxTensorBSplineTransform::B(j, s[1]) * vtkpxTensorBSplineTransform::B(k, s[2]);
+	      w[1]=vtkpxTensorBSplineTransform::B(i, s[0]) * vtkpxTensorBSplineTransform::dB(j, s[1]) * vtkpxTensorBSplineTransform::B(k, s[2]);
+	      w[2]=vtkpxTensorBSplineTransform::B(i, s[0]) * vtkpxTensorBSplineTransform::B(j, s[1]) * vtkpxTensorBSplineTransform::dB(k, s[2]);
+
+	      double d[3];
+	      self->GetControlPointDisplacement(cpoint,d);
+	      for (int ia=0;ia<=2;ia++)
+		{
+		  output[ia]+=wgt*d[ia];
+		  for (int ib=0;ib<=2;ib++)
+		    derivative[ia][ib]=w[ib]*d[ia];
+		}
+	    }
+	}
+    }
+}
+//------------------------------------------------------------------------
+
+void vtkpxTensorBSplineTransform::ForwardTransformPoint(const double point[3],double output[3])
+{
+  if (this->InverseFlag)
+    {
+      vtkWarpTransform::InverseTransformPoint(point,output);
+      return;
+    }
+
+  vtkpxTensorBSplineForwardTransformPoint(this,point,output);
+
+}
+
+void vtkpxTensorBSplineTransform::ForwardTransformPoint(const float point[3],float output[3])
+{
+  if (this->InverseFlag)
+    {
+      vtkWarpTransform::InverseTransformPoint(point,output);
+      return;
+    }
+
+  vtkpxTensorBSplineForwardTransformPoint(this,point,output);
+
+}
+
+//------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::ForwardTransformDerivative(const double point[3],
+							     double output[3],
+							     double derivative[3][3])
+{
+  vtkpxTensorBSplineTransformDerivative(this,point,output,derivative);
+}
+
+void vtkpxTensorBSplineTransform::ForwardTransformDerivative(const float point[3],
+							     float output[3],
+							     float derivative[3][3])
+{
+  vtkpxTensorBSplineTransformDerivative(this,point,output,derivative);
+}
+
+
+//----------------------------------------------------------------------------
+double vtkpxTensorBSplineTransform::B(int i, double t)
+{
+  switch (i) 
+    {
+    case 0:
+      return (1-t)*(1-t)*(1-t)/6.0;
+      break;
+      
+    case 1:
+      return (3*t*t*t - 6*t*t + 4)/6.0;
+    case 2:
+      return (-3*t*t*t + 3*t*t + 3*t + 1)/6.0;
+      
+    case 3:
+      return (t*t*t)/6.0;
+    }
+  return 0;
+}
+//----------------------------------------------------------------------------
+double vtkpxTensorBSplineTransform::dB(int i, double t)
+{
+  switch (i) 
+    {
+    case 0:
+      return -(1-t)*(1-t)/2.0;
+    case 1:
+      return (9*t*t - 12*t)/6.0;
+    case 2:
+      return (-9*t*t + 6*t + 3)/6.0;
+    case 3:
+      return (t*t)/2.0;
+    }
+  return 0;
+}
+//----------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::Load(const char* fname)
+{  
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  int ok=Load(fin);
+  gzclose(fin);
+
+  return ok;
+}
+
+int vtkpxTensorBSplineTransform::Load(gzFile fin,int skipheader,const char* header)
+{
+  char pxtk_buffer[255];
+  
+  if (skipheader==0)
+    gzgets(fin,pxtk_buffer,100);
+  else
+    strncpy(pxtk_buffer,header,255);
+  
+  int interpmode=0;
+  if (gzfindstringinstring(pxtk_buffer,"#vtkpxBaseGridTransform File")==0)
+    {
+      if (gzfindstringinstring(pxtk_buffer,"#vtkpxBaseGridTransform2 File")==0)
+	return 0;
+      else
+	interpmode=1;
+    }
+  
+  gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+  sscanf(pxtk_buffer,"%lf %lf %lf",&this->Origin[0],&this->Origin[1],&this->Origin[2]);
+  gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+  sscanf(pxtk_buffer,"%lf %lf %lf",&this->Spacing[0],&this->Spacing[1],&this->Spacing[2]);
+  gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+  sscanf(pxtk_buffer,"%d %d %d",&this->Dimensions[0],&this->Dimensions[1],&this->Dimensions[2]);
+  
+  if (interpmode)
+    {
+      // Skip over interpolation stuff
+      gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+    }
+
+  if (this->Displacements==NULL)
+    this->Displacements=vtkDoubleArray::New();
+  this->Displacements->SetNumberOfComponents(3);
+  this->Displacements->SetNumberOfTuples(this->Dimensions[0]*this->Dimensions[1]*this->Dimensions[2]);
+
+  this->OffsetDimensions[0]=1;
+  this->OffsetDimensions[1]=this->Dimensions[0];
+  this->OffsetDimensions[2]=this->Dimensions[0]*this->Dimensions[1];
+
+  this->NumberOfControlPoints=this->OffsetDimensions[2]*this->Dimensions[2];
+  gzgets(fin,pxtk_buffer,100);  
+
+  for (int ia=0;ia<=2;ia++)
+    this->Displacements->FillComponent(ia,0.0);
+
+  int np=this->Displacements->GetNumberOfTuples();
+  int tmp=0;
+  double dx[3];
+  for (int i=0;i<np;i++)
+    {
+      gzgets(fin,pxtk_buffer,100);
+      sscanf(pxtk_buffer,"%d %lf %lf %lf",&tmp,&dx[0],&dx[1],&dx[2]);
+      this->Displacements->SetTuple(i,dx);
+    }
+
+  this->InitializeStatusAndCaches();
+
+  return 1;
+}
+//----------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::Save(const char* fname)
+{
+  return this->Save(fname,0);
+}
+
+int vtkpxTensorBSplineTransform::Save(const char* fname,int compression)
+{
+  if (compression==0)
+    {
+      FILE* fout=fopen(fname,"w");
+      if (!fout)
+	return 0;
+      
+      int ok=Save(fout);
+      fclose(fout);
+      return ok;
+    } 
+
+  gzFile fout=gzsuffixopen(fname,"wb",compression);
+  if (!fout)
+    return 0;
+  int ok=Save(fout);
+  gzclose(fout);
+  return ok;
+  
+}
+
+int vtkpxTensorBSplineTransform::Save(FILE* fout)
+{
+  if (this->Displacements==NULL)
+    return 0;
+  int np=this->Displacements->GetNumberOfTuples();
+
+
+  fprintf(fout,"#vtkpxBaseGridTransform2 File\n");
+  fprintf(fout,"#Origin\n %.4f %.4f %.4f\n",this->Origin[0],this->Origin[1],this->Origin[2]);
+  fprintf(fout,"#Spacing\n %.4f %.4f %.4f\n",this->Spacing[0],this->Spacing[1],this->Spacing[2]);
+  fprintf(fout,"#Dimensions\n %d %d %d\n",this->Dimensions[0],this->Dimensions[1],this->Dimensions[2]);
+  fprintf(fout,"#Interpolation Mode\n%d\n",4);
+  fprintf(fout,"#Displacements\n");
+
+  for (int i = 0; i < np;i++)
+    fprintf(fout,"%d %.4f %.4f %.4f\n",i,
+	     this->Displacements->GetComponent(i,0),
+	     this->Displacements->GetComponent(i,1),
+	     this->Displacements->GetComponent(i,2));
+
+  return 1;
+}
+//----------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::Save(gzFile fout)
+{
+  if (this->Displacements==NULL)
+    return 0;
+
+  int np=this->Displacements->GetNumberOfTuples();
+  gzprintf(fout,"#vtkpxBaseGridTransform2 File\n");
+  gzprintf(fout,"#Origin\n %.4f %.4f %.4f\n",this->Origin[0],this->Origin[1],this->Origin[2]);
+  gzprintf(fout,"#Spacing\n %.4f %.4f %.4f\n",this->Spacing[0],this->Spacing[1],this->Spacing[2]);
+  gzprintf(fout,"#Dimensions\n %d %d %d\n",this->Dimensions[0],this->Dimensions[1],this->Dimensions[2]);
+  gzprintf(fout,"#Interpolation Mode\n%d\n",3);
+  gzprintf(fout,"#Displacements\n");
+  
+  for (int i = 0; i < np;i++)
+    gzprintf(fout,"%d %.4f %.4f %.4f\n",i,
+	     this->Displacements->GetComponent(i,0),
+	     this->Displacements->GetComponent(i,1),
+	     this->Displacements->GetComponent(i,2));
+  
+  return 1;
+}
+//----------------------------------------------------------------------------
+// Index Manipulation
+//----------------------------------------------------------------------------
+int  vtkpxTensorBSplineTransform::GetControlPointIndex(int i,int j,int k)
+{
+  i=Irange(i,0,this->Dimensions[0]-1);
+  j=Irange(j,0,this->Dimensions[1]-1);
+  k=Irange(k,0,this->Dimensions[2]-1);
+
+  return i+j*this->Dimensions[0]+k*this->OffsetDimensions[2];
+}
+
+void vtkpxTensorBSplineTransform::GetControlPointIndices(int index,int ind[3])
+{
+  index=Irange(index,0,this->NumberOfControlPoints-1);
+  ind[2]=index/this->OffsetDimensions[2];
+  int t=index%this->OffsetDimensions[2];
+  ind[1]=t/this->Dimensions[0];
+  ind[0]=t%this->Dimensions[0];
+}
+//----------------------------------------------------------------------------
+// Get/Set Displacement of control point index 
+//----------------------------------------------------------------------------
+double vtkpxTensorBSplineTransform::GetControlPointDisplacement(int index,int comp)
+{
+  comp=Irange(comp,0,2);
+  return this->Displacements->GetComponent(index,comp);
+}
+//-------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::GetControlPointDisplacement(int index,double val[3])
+{
+  for (int i=0;i<=2;i++)
+    val[i]=this->Displacements->GetComponent(index,i);
+}
+
+void vtkpxTensorBSplineTransform::SetControlPointDisplacement(int index,int comp,double val)
+{
+  comp=Irange(comp,0,2);
+  this->Displacements->SetComponent(index,comp,val);
+}
+
+void vtkpxTensorBSplineTransform::SetControlPointDisplacement(int index,double val[3])
+{
+  for (int i=0;i<=2;i++)
+    this->Displacements->SetComponent(index,i,val[i]);
+}
+
+//----------------------------------------------------------------------------
+// Move Control Point index
+//----------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::ShiftControlPoint(int index,int comp,double val)
+{
+  comp=Irange(comp,0,2);
+  double p=this->Displacements->GetComponent(index,comp);
+  this->Displacements->SetComponent(index,comp,p+val);
+}
+//-------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::ShiftControlPoint(int index,double val[3])
+{
+  double* ptr=this->Displacements->GetTuple(index);
+  for (int i=0;i<=2;i++)
+    this->Displacements->SetComponent(index,i,ptr[i]+val[i]);
+}
+//-------------------------------------------------------------------------
+//  Active Control Point Indexing
+//-------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::IsControlPointActive(int cp)
+{
+  return (this->ControlPointStatus->GetComponent(cp,0)>0);
+}
+//-------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::GetNumberOfActiveControlPoints()
+{
+  return this->ActiveControlPointList->GetNumberOfTuples();
+}
+
+int vtkpxTensorBSplineTransform::GetActualControlPointIndexFromActiveIndex(int i)
+{
+  return (int)this->ActiveControlPointList->GetComponent(i,0);
+}
+
+//-------------------------------------------------------------------------
+// Shift Active Control Point
+//-------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::ShiftActiveControlPoint(int index,int comp,double val)
+{
+  int true_index=(int)this->ActiveControlPointList->GetComponent(index,0);
+  this->ShiftControlPoint(true_index,comp,val);
+}
+
+void vtkpxTensorBSplineTransform::ShiftActiveControlPoint(int index,double val[3])
+{
+  int true_index=(int)this->ActiveControlPointList->GetComponent(index,0);
+  this->ShiftControlPoint(true_index,val);
+}
+
+//-------------------------------------------------------------------------
+// Get the Location of control point index
+//-------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::GetControlPointLocation(int index,double p[3])
+{
+  int ind[3];  this->GetControlPointIndices(index,ind);
+  for (int ia=0;ia<=2;ia++)
+    p[ia]=this->Origin[ia]+this->Spacing[ia]*double(ind[ia]);
+}
+//----------------------------------------------------------------------------
+double vtkpxTensorBSplineTransform::GetControlPointLocation(int index,int comp)
+{
+  double p[3];
+  this->GetControlPointLocation(index,p);
+  comp=Irange(comp,0,2);
+  return p[comp];
+}
+
+//--------------------------------------------------------------------------------------------
+// Get the Location of Active control point index by mapping through active control point list
+//-------------------------------------------------------------------------------------------
+void   vtkpxTensorBSplineTransform::GetActiveControlPointLocation(int index, double p[3])
+{
+  int true_index=(int)this->ActiveControlPointList->GetComponent(index,0);
+  this->GetControlPointLocation(true_index,p);
+}
+
+double vtkpxTensorBSplineTransform::GetActiveControlPointLocation(int index, int comp)
+{
+  int true_index=(int)this->ActiveControlPointList->GetComponent(index,0);
+  return this->GetControlPointLocation(true_index,comp);
+}
+//----------------------------------------------------------------------------
+// Get Internal Coordinates both lattice and arclengths
+//----------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::GetCoordinatesInGrid(double p[3],int lat[3],double s[3])
+{
+  for (int ia=0;ia<=2;ia++)
+    {
+      double x=(p[ia]-this->Origin[ia])/this->Spacing[ia]; 
+      lat[ia]=int(floor(x+0.0001));
+      s[ia]=x-lat[ia];
+    }
+}
+//----------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::InitializeStatusAndCaches()
+{
+  if (this->Displacements==NULL)
+    {
+      vtkErrorMacro(<<"Bad Displacements Cannot Initialize Status and Cache Arrays");
+      return 0;
+    }
+
+  if (this->WholeImageCache!=NULL)
+    this->WholeImageCache->Delete();
+  this->WholeImageCache=NULL;
+
+  if (this->DetailImageCache!=NULL)
+    this->DetailImageCache->Delete();
+  this->DetailImageCache=NULL;
+
+  if (this->CachedPointsInfo!=NULL)
+    this->CachedPointsInfo->Delete();
+  this->CachedPointsInfo=NULL;
+
+  if (this->CachedPoints!=NULL)
+    this->CachedPoints->Delete();
+  this->CachedPoints=NULL;
+
+  if (this->ActiveControlPointList==NULL)
+    this->ActiveControlPointList=vtkIntArray::New();
+
+  if (this->ControlPointStatus==NULL)
+    this->ControlPointStatus=vtkCharArray::New();
+
+  int nt=this->Displacements->GetNumberOfTuples();
+
+  this->ActiveControlPointList->SetNumberOfComponents(1);
+  this->ActiveControlPointList->SetNumberOfTuples(nt);
+
+  this->ControlPointStatus->SetNumberOfComponents(4);
+  this->ControlPointStatus->SetNumberOfTuples(nt);
+
+  this->ControlPointStatus->FillComponent(0,1);
+  for (int i=0;i<nt;i++)
+    this->ActiveControlPointList->SetComponent(i,0,i);
+
+  int index=0;
+  for (int k=0;k<Dimensions[2];k++)
+    {
+      int zstatus=0;
+      if (k==0)
+	zstatus=-2;
+      else if (k==1)
+	zstatus=-1;
+      else if (k==Dimensions[2]-2)
+	zstatus=1;
+      else if (k==Dimensions[2]-1)
+	zstatus=2;
+      
+      for (int j=0;j<Dimensions[1];j++)
+	{
+	  int ystatus=0;
+	  if (j==0)
+	    ystatus=-2;
+	  else if (j==1)
+	    ystatus=-1;
+	  else if (j==Dimensions[1]-2)
+	    ystatus=1;
+	  else if (j==Dimensions[1]-1)
+	    ystatus=2;
+	  
+	  for (int i=0;i<Dimensions[2];i++)
+	    {
+	      
+	      int xstatus=0;
+	      if (i==0)
+		xstatus=-2;
+	      else if (i==1)
+		xstatus=-1;
+	      else if (i==Dimensions[0]-2)
+		xstatus=1;
+	      else if (i==Dimensions[0]-1)
+		xstatus=2;
+	      
+	      this->ControlPointStatus->SetComponent(index,1,xstatus);
+	      this->ControlPointStatus->SetComponent(index,2,ystatus);
+	      this->ControlPointStatus->SetComponent(index,3,zstatus);
+	      ++index;
+	    }
+	}
+    }
+  return 1;
+}
+//----------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::Initialize(vtkImageData* img,double spacing,double offset)
+{
+  return vtkpxTensorBSplineTransform::Initialize(img,spacing,spacing,spacing,offset);
+}
+//----------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::Initialize(vtkImageData* img,double spacingx,double spacingy,double spacingz,double offset,
+					    int adjustspacing)
+{
+  if (img==NULL)
+    return 0;
+ 
+
+  double bounds[6];   img->GetBounds(bounds); 
+  double sp[3];
+
+  sp[0]=spacingx;
+  sp[1]=spacingy;
+  sp[2]=spacingz;
+  double imgsp[3]; img->GetSpacing(imgsp);
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (sp[ia]<imgsp[ia])
+	sp[ia]=imgsp[ia];
+    }
+
+  if (offset<0.0)
+    offset=0.0;
+  else if (offset>0.5)
+    offset=0.5;
+
+
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      int up=ia*2+1;
+      int lp=ia*2;
+      double len=bounds[up]-bounds[lp];
+      bounds[lp]-=offset*len;
+      bounds[up]+=offset*len;
+      double newlen=bounds[up]-bounds[lp];
+      
+      this->Dimensions[ia] = int(newlen/sp[ia]+1.5);
+      if (this->Dimensions[ia]<4) this->Dimensions[ia]=4;
+      this->Spacing[ia] =  double(newlen) / double(this->Dimensions[ia]-1);
+      if (adjustspacing==1)
+	{
+	  if (this->Spacing[ia]<imgsp[ia])
+	    {
+	      this->Spacing[ia]=imgsp[ia];
+	    }
+	  else
+	    {
+	      int n=int(imgsp[ia]/this->Spacing[ia]+0.5);
+	      this->Spacing[ia]=double(n)*imgsp[ia];
+	    }
+	}
+
+      this->Origin[ia]=bounds[lp];
+    }
+
+  if (this->Displacements==NULL)
+    this->Displacements=vtkDoubleArray::New();
+
+  this->Displacements->SetNumberOfComponents(3);
+  this->Displacements->SetNumberOfTuples(this->Dimensions[0]*this->Dimensions[1]*this->Dimensions[2]);
+
+  this->OffsetDimensions[0]=1;
+  this->OffsetDimensions[1]=this->Dimensions[0];
+  this->OffsetDimensions[2]=this->Dimensions[0]*this->Dimensions[1];
+  this->NumberOfControlPoints=this->OffsetDimensions[2]*this->Dimensions[2];
+  
+  for (int i=0;i<=2;i++)
+    this->Displacements->FillComponent(i,0.0);
+
+  this->InitializeStatusAndCaches();
+
+  return this->NumberOfControlPoints;
+}
+//-------------------------------------------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::CachedInitialize(vtkImageData* img,double spacingx,double spacingy,double spacingz,double offset)
+{
+  int ok=this->Initialize(img,spacingx,spacingy,spacingz,offset,1);
+
+  if (ok==0)
+    return 0;
+  else {
+  // Build Image Cache ....
+    return 0;
+  }
+
+  
+
+
+}
+//-------------------------------------------------------------------------------------------------------------
+//
+//   Optimizer Related Stuff, get current parameters and set current parameters using active control point list
+//
+//-------------------------------------------------------------------------------------------------------------
+void  vtkpxTensorBSplineTransform::SetCurrentParameters(vtkDoubleArray* param)
+{
+  int numt=this->ActiveControlPointList->GetNumberOfTuples();
+  int numit=this->NumberOfActiveComponents*numt;
+  int num=param->GetNumberOfTuples();
+
+  if (num!=numit)
+    {
+      vtkErrorMacro(<<"Bad Data for Optimization");
+      return;
+    }
+
+    int index=0;
+    for (int i=0;i<numt;i++)
+      {
+	int cp=(int)this->ActiveControlPointList->GetComponent(i,0);
+	double p[3] = { 0.0,0.0,0.0};
+	for (int j=0;j<this->NumberOfActiveComponents;j++)
+	  {
+	    p[j]=param->GetComponent(index,0);
+	    ++index;
+	  }
+	this->Displacements->SetTuple(cp,p);
+      }
+}
+
+// -----------------------------------------------------------------------------------------
+void  vtkpxTensorBSplineTransform::GetCurrentParameters(vtkDoubleArray* param)
+{
+  int numt=this->ActiveControlPointList->GetNumberOfTuples();
+  int numit=this->NumberOfActiveComponents*numt;
+
+  if (param->GetNumberOfComponents()!=1 || param->GetNumberOfTuples()!=numit)
+    {
+      param->SetNumberOfComponents(1);
+      param->SetNumberOfTuples(numit);
+    }
+
+  int index=0;
+  for (int i=0;i<numt;i++)
+    {
+      int cp=(int)this->ActiveControlPointList->GetComponent(i,0);
+      double* p=this->Displacements->GetTuple(cp);
+      this->GetControlPointDisplacement(i,p);
+      for (int j=0;j<=2;j++)
+	{
+	  param->SetComponent(index,0,p[j]);
+	  ++index;
+	}
+    }
+}
+// -----------------------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::CreateActiveControlPointListFromControlPointStatusArray()
+{
+  if (this->ControlPointStatus==NULL || this->ActiveControlPointList==NULL)
+    {
+      vtkErrorMacro(<<"Copy Create Active Control Point List  NULL ControlPointStatus");
+      return 0;
+    }
+
+  
+  int nt=0;
+  int numcp=this->ControlPointStatus->GetNumberOfTuples();
+  for (int i=0;i<numcp;i++)
+    {
+      if (ControlPointStatus->GetComponent(i,0)>0)
+	++nt;
+    }
+
+  this->ActiveControlPointList->SetNumberOfComponents(1);
+  this->ActiveControlPointList->SetNumberOfTuples(nt);
+
+  int index=0;
+  for (int i=0;i<numcp;i++)
+    {
+      if (ControlPointStatus->GetComponent(i,0)>0)
+	{
+	  this->ActiveControlPointList->SetComponent(index,0,i);
+	  ++index;
+	}
+    }
+
+  return nt;
+}
+// -----------------------------------------------------------------------------------------
+//
+//        Points Cache Stuff
+//
+// -----------------------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::CreatePointCache(vtkPolyData* pts)
+{
+  if (pts==NULL)
+    {
+      vtkErrorMacro(<<"Copy Create Active Control Point List  NULL ControlPointStatus");
+      return 0;
+    }
+
+  if (this->CachedPointsInfo!=NULL)
+    this->CachedPointsInfo->Delete();
+  if (this->CachedPoints!=NULL)
+    this->CachedPoints->Delete();
+
+  this->CachedPoints=vtkPolyData::New();
+  this->CachedPoints->DeepCopy(pts);
+
+  int nump=this->CachedPoints->GetNumberOfPoints();
+
+  this->CachedPointsInfo=vtkFloatArray::New();
+
+  // numcomp = 64 controlpoints + 64 weights =128
+  this->CachedPointsInfo->SetNumberOfComponents(128);
+  this->CachedPointsInfo->SetNumberOfTuples(nump);
+
+
+  double s[3];
+  int  lat[3];
+
+
+  for (int point=0;point<nump;point++)
+    {
+      double pp[3]; this->CachedPoints->GetPoint(point,pp);
+      this->GetCoordinatesInGrid(pp,lat,s);
+      int index=0;
+      for (int k = 0; k < 4; k++)
+	{
+	  int K = Irange(k + lat[2] - 1,0,Dimensions[2]-1);
+	  for (int j = 0; j < 4; j++)
+	    {
+	      int J = Irange(j + lat[1] - 1,0,Dimensions[1]-1);
+	      for (int i = 0; i < 4; i++)
+		{
+		  int I = Irange(i + lat[0] - 1,0,Dimensions[0]-1);
+		  int   cpoint=I+J*Dimensions[0]+K*OffsetDimensions[2];
+		  double wgt= vtkpxTensorBSplineTransform::B(i, s[0]) * vtkpxTensorBSplineTransform::B(j, s[1]) * vtkpxTensorBSplineTransform::B(k, s[2]);
+		  this->CachedPointsInfo->SetComponent(point,index*2,cpoint);
+		  this->CachedPointsInfo->SetComponent(point,index*2+1,wgt);
+		  ++index;
+		}
+	    }
+	}
+    }
+	return 1;
+}
+
+int vtkpxTensorBSplineTransform::CachedPointTransform(int index,double output[3])
+{
+  if (this->CachedPoints==NULL)
+    {
+      vtkErrorMacro(<<"Cannot Transform Cached Point no Points Cache");
+      return 0;
+    }
+
+  //  int ind=Irange(index,0,this->CachedPointsInfo->GetNumberOfTuples()-1);
+
+  this->CachedPoints->GetPoint(index,output);
+
+  for (int ia=0;ia<64;ia++)
+    {
+      int offset=ia*2;
+      int cpoint=(int)this->CachedPointsInfo->GetComponent(index,offset);
+      double wgt=this->CachedPointsInfo->GetComponent(index,offset+1);
+      double d[3]; this->GetControlPointDisplacement(cpoint,d);
+      
+      for (int ia=0;ia<=2;ia++)
+	output[ia]+=wgt*d[ia];
+    }
+  return 1;
+}
+// -----------------------------------------------------------------------------------------
+//
+//        Bending Energy Stuff
+//
+// -----------------------------------------------------------------------------------------
+double vtkpxTensorBSplineTransform::ComputeTotalBendingEnergy()
+{
+  double sum=0.0;
+  int nc=this->NumberOfControlPoints;
+  if (nc==0)
+    return 0.0;
+  
+  for (int i=0;i<nc;i++)
+    sum+=this->ComputeBendingEnergyAtControlPoint(i);
+  return sum;
+}
+// ---------------------------------------------------------------------------------------
+double vtkpxTensorBSplineTransform::ComputeBendingEnergyAroundControlPoint(int cpoint)
+{
+  double sum=this->ComputeBendingEnergyAtControlPoint(cpoint);
+
+  for (int direction=0;direction<=2;direction++)
+    {
+      int status=(int)this->ControlPointStatus->GetComponent(cpoint,direction+1);
+      int cmin=-1,cmax=1;
+      if (status<0)
+	cmin=0;
+      if (status>0)
+	cmax=0;
+
+      for (int c=cmin;c<=cmax;c++)
+	if (c!=0)
+	  sum+=this->ComputeBendingEnergyAtControlPoint(cpoint+c*this->OffsetDimensions[direction]);
+    }
+  return sum;
+}
+// ---------------------------------------------------------------------------------------
+double vtkpxTensorBSplineTransform::ComputeBendingEnergyAtControlPoint(int cpoint)
+{
+  double scale=0.01*(1.0/(double(this->NumberOfControlPoints)));
+  
+
+  int status[3];
+  for (int ia=0;ia<=2;ia++)
+    status[ia]=(int)this->ControlPointStatus->GetComponent(cpoint,ia+1);
+
+  double* thisdisp=this->Displacements->GetTuple(cpoint);
+  double sum=0.0;
+
+  for (int row=0;row<=2;row++)
+    {
+      // First Ordinary Second derivatives i.e. d2u/dx2 ...  x=row
+      int neigh[2]= { cpoint,cpoint };
+      if (status[row]!=-2)
+	neigh[0]-=this->OffsetDimensions[row];
+      if (status[row]!=2)
+	neigh[1]+=this->OffsetDimensions[row];
+
+      double* pdisp=this->Displacements->GetTuple(neigh[0]);
+      double* mdisp=this->Displacements->GetTuple(neigh[1]);
+      
+      for (int comp=0;comp<=2;comp++)
+	sum+=pow(pdisp[comp]-2.0*thisdisp[comp]+mdisp[comp],2.0);
+
+      // Now Mixed Derivatives i.e. d2u/dxdy x=row,y=col
+      
+      for (int col=row+1;col<=2;col++)
+	{
+	  int corner[2][2];
+	  corner[0][0]=neigh[0];
+	  corner[1][0]=neigh[0];
+	  corner[0][1]=neigh[1];
+	  corner[1][1]=neigh[1];
+	  
+	  if (status[col]!=-2)
+	    {
+	      for (int ib=0;ib<=1;ib++)
+		corner[ib][0]-=this->OffsetDimensions[col];
+	    }
+
+	  if (status[col]!=2)
+	    {
+	      for (int ib=0;ib<=1;ib++)
+		corner[ib][1]+=this->OffsetDimensions[col];
+	    }
+	    
+	  double* pdisp1=this->Displacements->GetTuple(corner[0][0]);
+	  double* pdisp2=this->Displacements->GetTuple(corner[1][1]);
+	  double* mdisp1=this->Displacements->GetTuple(corner[0][1]);
+	  double* mdisp2=this->Displacements->GetTuple(corner[1][0]);
+	  
+	  for (int comp=0;comp<=2;comp++)
+	    sum+=2.0*pow(0.25*(pdisp1[comp]+pdisp2[comp]-mdisp1[comp]-mdisp2[comp]),2.0);
+	}
+    }
+  return (sum)*scale;
+}
+// ---------------------------------------------------------------------------------------
+//
+//        Point Approximation Utilities
+//
+// ---------------------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::GenerateTestPoints(vtkPoints* points,double incr)
+{
+  if (points==NULL)
+    return 0;
+
+  int nc=this->GetNumberOfControlPoints();
+  incr=Frange(incr,0.2,3.0);
+
+  double max=nc/(incr*incr*incr)+10;
+  points->Allocate((int)max,20);
+  double p[3];
+
+
+  for (double k=0;k<this->Dimensions[2];k+=incr)
+    {
+      p[2]=this->Origin[2]+this->Spacing[2]*(k);
+      for (double j=0;j<this->Dimensions[1];j+=incr)
+	{
+	  p[1]=this->Origin[1]+this->Spacing[1]*(j);
+	  for (double i=0;i<this->Dimensions[0];i+=incr)
+	    {
+	      p[0]=this->Origin[0]+this->Spacing[0]*(i);
+	      points->InsertNextPoint(p);
+	    }
+	}
+    }
+
+  return (points->GetNumberOfPoints());
+}
+//-------------------------------------------------------------------------
+double vtkpxTensorBSplineTransform::TestApproximation(vtkAbstractTransform* tr,vtkPoints* points)
+{
+  double error=0.0;
+  int caching=0;
+
+  if (points==NULL && this->CachedPoints!=NULL)
+    {
+      points=this->CachedPoints->GetPoints();
+      caching=1;
+    }
+
+  if (points==NULL)
+    return -1.0;
+
+  int nc=points->GetNumberOfPoints();
+  if (nc<1)
+    return -1.0;
+
+  tr->Update();
+  this->Update();
+
+  double x[3],t1[3],t2[3];
+  for (int i=0;i<nc;i++)
+    {
+      points->GetPoint(i,x);
+      tr->InternalTransformPoint(x,t1);
+      if (!caching)
+	this->InternalTransformPoint(x,t2);
+      else
+	this->CachedPointTransform(i,t2);
+      error+=sqrt(vtkMath::Distance2BetweenPoints(t1,t2));
+    }
+
+  return error/double(nc);
+}
+//-------------------------------------------------------------------------
+double vtkpxTensorBSplineTransform::TestApproximation(vtkPoints* points,vtkPoints* points2)
+{
+  double error=0.0;
+  int caching=0;
+
+  if (points==NULL && this->CachedPoints!=NULL)
+    {
+      points=this->CachedPoints->GetPoints();
+      caching=1;
+    }
+
+  if (points==NULL)
+    return -1.0;
+
+  int nc=points->GetNumberOfPoints();
+  if (nc<1)
+    return -1.0;
+
+  this->Update();
+
+  double x[3],tx[3],x2[3];
+  for (int i=0;i<nc;i++)
+    {
+      points->GetPoint(i,x);
+      points2->GetPoint(i,tx);
+      if (!caching)
+	this->InternalTransformPoint(x,x2);
+      else
+	this->CachedPointTransform(i,x2);
+      error+=sqrt(vtkMath::Distance2BetweenPoints(x2,tx));
+    }
+  return error/double(nc);
+}
+//-------------------------------------------------------------------------
+double vtkpxTensorBSplineTransform::TestWeightedApproximation(vtkPoints* points,vtkPoints* points2,vtkpxMatrix* lsqweights,
+							      double& sum2error)
+{
+  double error=0.0;
+  sum2error=0.0;
+  int caching=0;
+
+  if (points==NULL && this->CachedPoints!=NULL)
+    {
+      points=this->CachedPoints->GetPoints();
+      caching=1;
+    }
+
+  if (points==NULL)
+    return -1.0;
+
+  int nc=points->GetNumberOfPoints();
+  
+  int useweights=0;
+  if (lsqweights!=NULL)
+    {
+      if (lsqweights->GetSize()[0]>=points->GetNumberOfPoints())
+	useweights=1;
+    }
+
+
+  if (nc<1)
+    {
+      fprintf(stderr,"*** nc<1");
+      return -1.0;
+    }
+
+  this->Update();
+  double x[3],x2[3],tx[3];
+  for (int i=0;i<nc;i++)
+    {
+      points2->GetPoint(i,tx);
+      if (!caching)
+	{
+	  points->GetPoint(i,x);
+	  this->InternalTransformPoint(x,x2);
+	}
+      else
+	{
+	  this->CachedPointTransform(i,x2);
+	}
+
+      double d=vtkMath::Distance2BetweenPoints(x2,tx);
+      if (isinf(d))
+	{
+	  fprintf(stderr,"-- i=%d %.2f %.2f %.2f,  %.2f %.2f %.2f\n",i,
+		  x[0],x[1],x[2],
+		  x2[0],x2[1],x2[2]);
+	  d=0.0;
+	}
+      double w=1.0;
+      if (useweights)
+	{
+	  w=lsqweights->GetDirectElement(i,0);
+	  if (isinf(w))
+	    {
+	      w=1.0;
+	      fprintf(stderr,"Weight=inf i=%d\n",i);
+	    }
+	}
+      error+=w*sqrt(d);
+      sum2error+=w*d;
+    }
+  sum2error/=double(nc);
+  return error/double(nc);
+}
+//-------------------------------------------------------------------------
+double vtkpxTensorBSplineTransform::ComputeWeightedDistance(vtkpxTensorBSplineTransform* other,
+							    int cpindex,vtkDoubleArray* weights0)
+{
+  if (other==NULL)
+    {
+      vtkErrorMacro(<<"Really Bad Prior\n");
+      return 0;
+    }
+
+  int np=other->GetNumberOfControlPoints();
+  if (np!=this->GetNumberOfControlPoints())
+    {
+      vtkErrorMacro(<<"Bad Prior\n");
+      return 0;
+    }
+  
+  vtkDoubleArray* weights=weights0;
+
+  double weight=1.0;
+  if (weights0!=NULL)
+    {
+      if (weights->GetNumberOfTuples()!=np)
+	weights=NULL;
+    }
+  int mincpindex=0;
+  int maxcpindex=np-1;
+  
+  if (cpindex>=0)
+    {
+      mincpindex=Irange(cpindex,0,maxcpindex);
+      maxcpindex=mincpindex;
+    }
+  
+  double v=0;
+  double scale=1.0/double(np);
+  for (int cp=mincpindex;cp<=maxcpindex;cp++)
+    {
+      double d1[3],d2[3];
+      other->GetControlPointDisplacement(cp,d1);
+      this->GetControlPointDisplacement(cp,d2);
+      double d=(vtkMath::Distance2BetweenPoints(d1,d2));
+      if (weights!=NULL)
+	weight=weights->GetComponent(cp,0);
+      v+=d*weight;
+    }
+  return v*scale;
+}
+// ---------------------------------------------------------------------------------------
+// Key Procedures for approximation of points via optimization
+// ---------------------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::ShiftControlPoints(vtkDoubleArray* grad,double step)
+{
+  int nc=this->GetNumberOfControlPoints();
+  for (int j=0;j<=2;j++)
+    for (int i = 0; i < nc; i++)
+      this->ShiftControlPoint(i,j,step*grad->GetComponent(i,j));
+}
+// ---------------------------------------------------------------------------------------
+void vtkpxTensorBSplineTransform::ScaleGradients(vtkDoubleArray* grad,double scale)
+{
+  int nt=grad->GetNumberOfTuples();
+  int nc=grad->GetNumberOfComponents();
+  for (int t=0;t<nt;t++)
+    for (int c=0;c<nc;c++)
+      grad->SetComponent(t,c,grad->GetComponent(t,c) * scale);
+
+}
+// ---------------------------------------------------------------------------------------
+int vtkpxTensorBSplineTransform::FormCollectionStructure(vtkPoints* SourcePoints,vtkCollection* ControlsCollection,double PointWeightThreshold)
+{
+  if (ControlsCollection==NULL)
+    return 0;
+  ControlsCollection->RemoveAllItems();
+
+  double thr=Frange(PointWeightThreshold,0.0,0.2);
+
+  int np=SourcePoints->GetNumberOfPoints();
+  int nc=this->GetNumberOfControlPoints();
+
+  vtkDoubleArray** arrlist=new vtkDoubleArray*[nc];
+
+  for (int cp=0;cp<nc;cp++)
+    {
+      vtkDoubleArray* fl=vtkDoubleArray::New();
+      fl->SetNumberOfComponents(2);
+      fl->Allocate(10,10);
+      ControlsCollection->AddItem(fl);
+      arrlist[cp]=fl;
+    }
+
+  int GridSliceDimensions=this->Dimensions[0]*this->Dimensions[1];
+
+  for (int node=0;node<np;node++)
+    {
+      double p1[3],s[3];
+      int  lat[3];
+      SourcePoints->GetPoint(node,p1);
+      this->GetCoordinatesInGrid(p1,lat,s);
+
+      for (int k = 0; k < 4; k++)
+	{
+	  int K = Irange(k + lat[2] - 1,0,this->Dimensions[2]-1);
+	  for (int j = 0; j < 4; j++)
+	    {
+	      int J = Irange(j + lat[1] - 1,0,this->Dimensions[1]-1);
+	      for (int i = 0; i < 4; i++)
+		{
+		  int I = Irange(i + lat[0] - 1,0,this->Dimensions[0]-1);
+		  int   cpoint=I+J*this->Dimensions[0]+K*GridSliceDimensions;
+		  double wgt= vtkpxTensorBSplineTransform::B(i, s[0]) * 
+		    vtkpxTensorBSplineTransform::B(j, s[1]) * 
+		    vtkpxTensorBSplineTransform::B(k, s[2]);
+		  if (wgt>=thr)
+		    {
+		      vtkDoubleArray* fl=arrlist[cpoint];
+		      int numt=fl->GetNumberOfTuples();
+		      int found=0,l=0;
+		      
+		      while (l<numt && found==0)
+			{
+			  int cand=(int)fl->GetComponent(l,0);
+			  if (cand==node)
+			    {
+			      fl->SetComponent(l,1,fl->GetComponent(l,1)+wgt);
+			      found=1;
+			    }
+			  l++;
+			}
+		      
+		      if (found==0)
+			fl->InsertNextTuple2(double(node),wgt);
+		    }
+		}
+	    }
+	}
+    }
+
+  delete [] arrlist;
+
+
+  int sum=0;
+  ControlsCollection->InitTraversal();
+  for (int p=0;p<nc;p++)
+    {
+      vtkDoubleArray* fl=(vtkDoubleArray*)ControlsCollection->GetNextItemAsObject();
+      sum+=fl->GetNumberOfTuples();
+    }
+  int m=int(sum/nc);
+  return m;
+
+}
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxTensorBSplineTransform.h b/bioimagesuite30_src/Common/vtkpxTensorBSplineTransform.h
new file mode 100644
index 0000000..6104f04
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxTensorBSplineTransform.h
@@ -0,0 +1,290 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxTensorBSplineTransform.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+ ========================================================================*/
+
+#ifndef __vtkpxTensorBSplineTransform_h
+#define __vtkpxTensorBSplineTransform_h
+
+#include "vtkWarpTransform.h"
+#include "pxutil.h"
+#include "vtkDoubleArray.h"
+#include "vtkFloatArray.h"
+#include "vtkCharArray.h"
+#include "vtkIntArray.h"
+#include "vtkPolyData.h"
+#include "vtkpxMatrix.h"
+
+class vtkTransform;
+class vtkPolyData;
+class vtkImageData;
+class vtkPoints;
+class vtkCollection;
+
+class vtkpxTensorBSplineTransform : public vtkWarpTransform
+{
+public:
+  vtkTypeMacro(vtkpxTensorBSplineTransform,vtkWarpTransform);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  static vtkpxTensorBSplineTransform *New();
+
+  // Description:
+  // Make another transform of the same type.
+  vtkAbstractTransform *MakeTransform();
+
+  // Description:
+  // Copy Transformation
+  virtual void Copy(vtkpxTensorBSplineTransform* other);
+
+  // Description:
+  // Initialize from Image
+  virtual int Initialize(vtkImageData* img,double spacing,double offset);
+  virtual int Initialize(vtkImageData* img,double spacingx,double spacingy,double spacingz,double offset,int adjustspacing=0);
+
+  virtual int CachedInitialize(vtkImageData* img,double spacingx,double spacingy,double spacingz,double offset);
+
+  
+
+  // Description:
+  // Load/Save Transformation
+  virtual int Load(const char* fname);
+  virtual int Save(const char* fname);
+  virtual int Save(const char* fname,int compression);
+
+  virtual int Load(gzFile fin,int skipheader=0,const char* header=NULL);
+  virtual int Save(FILE* fout);
+  virtual int Save(gzFile fout);
+
+  // Description:
+  // Return Result of B-sline basis functions 
+  static double B (int, double);
+  static double dB (int, double);
+
+  // Description:
+  // Access to Internal Structures for Information
+  vtkGetVector3Macro(Dimensions,int);
+  vtkGetVector3Macro(Spacing,double);
+  vtkGetVector3Macro(Origin,double);
+  vtkGetVector3Macro(OffsetDimensions,int);
+  vtkGetMacro(NumberOfActiveComponents,int);
+  vtkGetMacro(NumberOfControlPoints,int);
+
+  // Description:
+  // Cache Mode
+  // 0 = None
+  // 1 = Points
+  // 2 = Image
+  // 3 = Both
+  vtkGetMacro(CacheMode,int);
+  vtkSetClampMacro(CacheMode,int,0,3);
+  
+  // Description:
+  // Get Displacements and Cache Stuff
+  vtkGetObjectMacro(Displacements,vtkDoubleArray);
+  vtkGetObjectMacro(ActiveControlPointList,vtkIntArray);
+  vtkGetObjectMacro(ControlPointStatus,vtkCharArray);
+  vtkGetObjectMacro(WholeImageCache,vtkImageData);
+  vtkGetObjectMacro(DetailImageCache,vtkImageData);
+  vtkGetObjectMacro(CachedPoints,vtkPolyData);
+  vtkGetObjectMacro(CachedPointsInfo,vtkFloatArray);
+  
+  // Description:
+  // Grid Indexing Stuff
+  virtual int GetControlPointIndex(int i,int j,int k);
+
+  // Description:
+  // Get control point location stuff
+  virtual void  GetControlPointLocation(int index, double p[3]);
+  virtual double GetControlPointLocation(int index, int comp);
+
+  // Description:
+  // Get Control Point Location  (by looking up ActiveControlPointList to map index)
+  virtual void   GetActiveControlPointLocation(int index, double p[3]);
+  virtual double GetActiveControlPointLocation(int index, int comp);
+
+
+  // Description:
+  // Modify individual displacements
+  virtual double GetControlPointDisplacement(int index,int comp);
+  virtual void  GetControlPointDisplacement(int index,double val[3]);
+  virtual void  SetControlPointDisplacement(int index,int comp,double val);
+  virtual void  SetControlPointDisplacement(int index,double val[3]);
+
+  // Description:
+  // Shift Control Point
+  virtual void  ShiftControlPoint(int index,int comp,double val);
+  virtual void  ShiftControlPoint(int index,double val[3]);
+
+  // Description:
+  // Shift Active Control Point index (by looking up ActiveControlPointList)
+  virtual void  ShiftActiveControlPoint(int index,int comp,double val);
+  virtual void  ShiftActiveControlPoint(int index,double val[3]);
+
+
+  // Description:
+  // Get Offset Coordinates
+  virtual void GetCoordinatesInGrid(double p[3],int lat[3],double s[3]);
+
+  //BTX
+  // Description:
+  // Pointer to Control Point
+  virtual void   GetControlPointIndices(int index,int ind[3]);
+  //ETX
+
+  // Description:
+  // Hook to Optimization Routines -- only active control points used
+  virtual void  SetCurrentParameters(vtkDoubleArray* par);
+  virtual void  GetCurrentParameters(vtkDoubleArray* par);
+
+  // Description:
+  // Create/Use Point Cache
+  virtual int CreatePointCache(vtkPolyData* pts);
+  virtual int FormCollectionStructure(vtkPoints* SourcePoints,vtkCollection* ControlsCollection,double PointWeightThreshold);
+  virtual int CachedPointTransform(int index,double output[3]);
+
+
+  // Description:
+  // Bending Energy Stuff
+  virtual double ComputeTotalBendingEnergy();
+  virtual double ComputeBendingEnergyAroundControlPoint(int cpoint);
+  virtual double ComputeBendingEnergyAtControlPoint(int cpoint);
+
+  // Description:
+  // Active Control Point Stuff
+  virtual int GetNumberOfActiveControlPoints();
+  virtual int GetActualControlPointIndexFromActiveIndex(int i);
+  virtual int IsControlPointActive(int cp);
+
+  // Description:
+  // Functions to facilitate point approximation issues
+  virtual int GenerateTestPoints(vtkPoints* points,double incr);
+
+  // Description:
+  // Test Approximation: Specify points1=NULL to use cached points
+  virtual double TestApproximation(vtkAbstractTransform* tr,vtkPoints* points);
+  virtual double TestApproximation(vtkPoints* points,vtkPoints* points2);
+  virtual double TestWeightedApproximation(vtkPoints* points,vtkPoints* points2,vtkpxMatrix* lsqweights,double& sum2error);
+
+
+  // Description:
+  // Compute Distance to other transformation
+  virtual double ComputeWeightedDistance(vtkpxTensorBSplineTransform* other,int cp,vtkDoubleArray* weights=NULL);
+
+
+  // Description:
+  // More Optimization Stuff
+  virtual void  ShiftControlPoints(vtkDoubleArray* grad,double step);
+  static  void  ScaleGradients(vtkDoubleArray* grad,double scale);
+
+
+protected:
+  vtkpxTensorBSplineTransform();
+  virtual ~vtkpxTensorBSplineTransform();
+
+  vtkpxTensorBSplineTransform(const vtkpxTensorBSplineTransform&) {};
+  void operator=(const vtkpxTensorBSplineTransform&) {};
+
+
+  // Description:
+  // Members an array of N components to specify control point positions and values
+  vtkDoubleArray* Displacements;
+  double          Origin[3];
+  double          Spacing[3];
+  int             Dimensions[3];
+  int             OffsetDimensions[3];
+  int             NumberOfControlPoints;
+  vtkImageData*   WholeImageCache;
+  vtkImageData*   DetailImageCache;
+  vtkFloatArray*  CachedPointsInfo;
+  vtkPolyData*    CachedPoints;
+  vtkIntArray* ActiveControlPointList;
+  vtkCharArray* ControlPointStatus;
+  int             NumberOfActiveComponents;
+  int             CacheMode;
+
+  // Description:
+  // Prepare the transformation for application.
+  virtual void InternalUpdate();
+
+  // Description:
+  // This method does no type checking, use DeepCopy instead.
+  virtual void InternalDeepCopy(vtkAbstractTransform *transform);
+
+  // Description:
+  // Forward Transform Point -- OK
+  virtual void ForwardTransformPoint(const float in[3], float out[3]);
+  virtual void ForwardTransformPoint(const double in[3], double out[3]);
+
+  // Description:
+  // Forward Transform Derivative (Not done yet) -- OK
+  virtual void ForwardTransformDerivative(const float in[3], float out[3],
+				  float derivative[3][3]);
+  virtual void ForwardTransformDerivative(const double in[3], double out[3],
+					  double derivative[3][3]);
+
+  // Description:
+  // Initialize Caches and Control Point Status issues
+  virtual int InitializeStatusAndCaches();
+
+  // Description:
+  // Recompute ActiveControlPoint List from ControlPoint Status stuff
+  virtual int CreateActiveControlPointListFromControlPointStatusArray();
+
+};
+
+#endif
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxTestOptimizer.cpp b/bioimagesuite30_src/Common/vtkpxTestOptimizer.cpp
new file mode 100644
index 0000000..fb99ce5
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxTestOptimizer.cpp
@@ -0,0 +1,217 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+
+// vtk includes
+#include "vtkObjectFactory.h"
+#include "vtkpxTestOptimizer.h"
+#include "vtkMath.h"
+#include "vtkpxOptimizer.h"
+
+vtkpxTestOptimizer* vtkpxTestOptimizer::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxTestOptimizer");
+  if(ret)
+    {
+      return (vtkpxTestOptimizer*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxTestOptimizer;
+}
+
+
+vtkpxTestOptimizer::vtkpxTestOptimizer()
+{
+  this->OptimizationMethod=0;
+  this->parameters=vtkDoubleArray::New();
+  this->parameters->SetNumberOfComponents(1);
+  this->parameters->SetNumberOfTuples(2);
+  this->parameters->SetComponent(0,0,5);
+  this->parameters->SetComponent(1,0,5);
+  this->FunctionEvaluation=0;
+  this->DerivEvaluation=0;
+  this->Dimension=2;
+}
+
+vtkpxTestOptimizer::~vtkpxTestOptimizer()
+{
+  this->parameters->Delete();
+}
+
+//-------------------------------------------------------------------------
+void vtkpxTestOptimizer::SetOutputStatus(const char* line,double v)
+{
+  fprintf(stdout,"**Opt=%s (%.5f)\n",line,v);
+}
+
+//-------------------------------------------------------------------------
+double vtkpxTestOptimizer::CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output)
+{
+  return ((vtkpxTestOptimizer*)self)->OptimizerGradient(position,output);
+}
+
+double vtkpxTestOptimizer::CalculateFunction(vtkObject* self,vtkDoubleArray* position)
+{
+  return ((vtkpxTestOptimizer*)self)->OptimizerValue(position);
+}
+
+void vtkpxTestOptimizer::OptimizerFeedback(vtkObject* self,const char* line,double val)
+{
+  ((vtkpxTestOptimizer*)self)->SetOutputStatus(line,val);
+}
+//-------------------------------------------------------------------------
+void vtkpxTestOptimizer::SetCurrentParameters(vtkDoubleArray* par)
+{
+  this->parameters->DeepCopy(par);
+}
+ 
+void vtkpxTestOptimizer::GetCurrentParameters(vtkDoubleArray* par)
+{
+  par->DeepCopy(this->parameters);
+}
+
+double vtkpxTestOptimizer::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+{
+  if (grad->GetNumberOfTuples()!=params->GetNumberOfTuples())
+    grad->SetNumberOfTuples(params->GetNumberOfTuples());
+
+  if (this->Dimension==2)
+    {
+      double x=params->GetComponent(0,0);
+      double y=params->GetComponent(1,0);
+      
+      double dx=2*(x-9);
+      double dy=2*y;
+      double s=dx*dx+dy*dy;
+      
+      s=sqrt(s);
+      grad->SetComponent(0,0,dx/s);
+      grad->SetComponent(1,0,dy/s);
+      ++this->DerivEvaluation;
+      fprintf(stdout,"\t x=%.2f y=%.2f --> dx=%.2f dy=%.2f --> v=[%.2f %.2f]\n",x,y,dx,dy,dx/s,dy/s);
+      return (s);
+    }
+  else
+    {
+      double x=params->GetComponent(0,0);
+      double dx=2*(x-9);
+      grad->SetComponent(0,0,dx);
+      ++this->DerivEvaluation;
+      fprintf(stdout,"\t x=%.2f  --> dx=%.2f  --> v=[%.2f]\n",x,dx,dx);
+      return fabs(dx);
+    }
+
+}
+ 
+double vtkpxTestOptimizer::OptimizerValue(vtkDoubleArray* params)
+{
+  double x=params->GetComponent(0,0);
+  double v=0.0,y=0.0;
+  if (this->Dimension==2)
+    y=params->GetComponent(1,0);
+  v=(x-9)*(x-9)+y*y;
+  ++this->FunctionEvaluation;
+
+  //  fprintf(stdout,"\t x=%.2f y=%.2f --> v=%.2f\n",x,y,v);
+  return v;
+
+}
+
+int vtkpxTestOptimizer::Run()
+{
+  vtkpxOptimizer* optimizer=vtkpxOptimizer::New();
+  this->parameters->SetNumberOfTuples(this->Dimension);
+  vtkDoubleArray* position=vtkDoubleArray::New();
+  vtkDoubleArray* temp=vtkDoubleArray::New();
+  this->GetCurrentParameters(position);
+  optimizer->SetMasterObject(this);
+
+  optimizer->SetEvaluateFunctionMethod(&vtkpxTestOptimizer::CalculateFunction);
+  optimizer->SetEvaluateGradientMethod(&vtkpxTestOptimizer::CalculateGradient);
+  optimizer->SetFeedbackMethod(&vtkpxTestOptimizer::OptimizerFeedback);
+
+  fprintf(stdout,"Starting meth=%d\n",this->OptimizationMethod);
+  this->FunctionEvaluation=0;
+  this->DerivEvaluation=0;
+
+  switch (this->OptimizationMethod)
+    {
+    case -1:
+    case 0:
+      optimizer->ComputeOldGradientDescent(position,0.5,0.0001);
+      break;
+    case 2:
+      optimizer->ComputeGradientDescent(position,50,0.0001);
+      break;
+    case 1:
+      optimizer->DebugOn();
+      optimizer->ComputeSlowClimb(position,0.25,50);
+      optimizer->DebugOff();
+      break;
+    case 4:
+      optimizer->ComputeConjugateGradient(position,50,0.001);
+      break;
+
+    case 5:
+      if (this->Dimension==1)
+	optimizer->Compute1DMinimization(position,-25,25,0.01);
+      break;
+    }
+
+
+  float error=0.0;
+  if (this->Dimension==2)
+    {
+      fprintf(stdout,"\n\n Final Output = (%.2f %.2f) func=%.5f eval= f=%d d=%d\n",
+	      position->GetComponent(0,0),
+	      position->GetComponent(1,0),
+	      this->OptimizerValue(position),
+	      this->FunctionEvaluation,
+	      this->DerivEvaluation);
+      error+=pow(position->GetComponent(0,0)-9.0,2.0)+pow(position->GetComponent(1,0),2.0);
+    }
+  else
+    {
+      fprintf(stdout,"\n\n Final Output = (%.2f) func=%.5f eval= f=%d d=%d\n",
+	      position->GetComponent(0,0),
+	      this->OptimizerValue(position),
+	      this->FunctionEvaluation,
+	      this->DerivEvaluation);
+      error+=pow(position->GetComponent(0,0)-9.0,2.0);
+    }
+  optimizer->Delete();
+  position->Delete();
+  temp->Delete();
+  if (error<0.001)
+    return 1;
+  return 0;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxTestOptimizer.h b/bioimagesuite30_src/Common/vtkpxTestOptimizer.h
new file mode 100644
index 0000000..f1cfc89
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxTestOptimizer.h
@@ -0,0 +1,115 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+
+
+#ifndef __VTKPXREGISTRATION_H
+#define __VTKPXREGISTRATION_H
+
+#include "vtkProcessObject.h"
+#include "vtkDoubleArray.h"
+
+class vtkpxTestOptimizer : public vtkProcessObject {
+
+public:
+
+  vtkTypeMacro(vtkpxTestOptimizer,vtkProcessObject);
+
+  // Description:
+  // This one also 
+  static vtkpxTestOptimizer* New();
+  
+  // Description:
+  // These are needed for the Optimizer 
+  static void  OptimizerFeedback(vtkObject* self,const char* line,double val);
+  static double CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output);
+  static double CalculateFunction(vtkObject* self,vtkDoubleArray* position);
+
+  // Description:
+  // Optimization Method
+  vtkSetMacro(OptimizationMethod,int);
+  vtkGetMacro(OptimizationMethod,int);
+
+  // Description:
+  // Optimization Method
+  vtkSetMacro(Dimension,int);
+  vtkGetMacro(Dimension,int);
+
+
+  // Description:
+  // Shorthand for different optimization methods 
+  virtual void SetOptimizationMethodToOldStyle() { this->SetOptimizationMethod(-1); }
+  virtual void SetOptimizationMethodToDefault() { this->SetOptimizationMethod(0); }
+  virtual void SetOptimizationMethodToSlowClimb() { this->SetOptimizationMethod(1); }
+  virtual void SetOptimizationMethodToGradientDescent() { this->SetOptimizationMethod(2); }
+  virtual void SetOptimizationMethodToConjugateGradient() { this->SetOptimizationMethod(4); }
+
+  // Description:
+  // Run Test
+  virtual int Run();
+
+protected:
+
+  // Description:
+  // Make all these protected 
+  // Constructor
+  vtkpxTestOptimizer();
+  virtual ~vtkpxTestOptimizer();
+  vtkpxTestOptimizer(const vtkpxTestOptimizer&) {};
+  void operator=(const vtkpxTestOptimizer&) {};
+
+
+  // Description:
+  // Various Control Parameters
+  int   OptimizationMethod;
+
+  vtkDoubleArray* parameters;
+  int   FunctionEvaluation;
+  int   DerivEvaluation;
+  int   Dimension;
+
+  // Description:
+  // Needed for Optimizer -- set,get,optimizer,optimizervalue
+  virtual void SetCurrentParameters(vtkDoubleArray* par);
+  virtual void GetCurrentParameters(vtkDoubleArray* par);
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+  virtual void  SetOutputStatus(const char* line,double v);
+};
+
+
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Common/vtkpxUtil.cpp b/bioimagesuite30_src/Common/vtkpxUtil.cpp
new file mode 100644
index 0000000..439c0f1
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxUtil.cpp
@@ -0,0 +1,1057 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxUtil.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkAbstractTransform.h"
+#include "vtkDataArray.h"
+#include "vtkFloatArray.h"
+#include "vtkIdentityTransform.h"
+#include "vtkImageData.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkbisImageResample.h"
+#include "vtkbisImageHeader.h"
+#include "vtkbisImageReslice.h"
+#include "vtkMath.h"
+#include "vtkMatrix4x4.h"
+#include "vtkObjectFactory.h"
+#include "vtkStructuredPoints.h"
+#include "vtkTransform.h"
+#include "vtkpxAnalyzeImageWriter.h"
+#include "vtkpxImageExtract.h"
+#include "vtkpxUtil.h"
+#include "vtkpxImageExtractVOI.h"
+#include "vtkImageAccumulate.h"
+#include "vtkImageResample.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkPointData.h"
+
+
+// ---------------------------
+
+vtkpxUtil* vtkpxUtil::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxUtil");
+  if(ret)
+      {
+	return (vtkpxUtil*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxUtil;
+}
+
+
+/*=========================================================================
+
+
+         C R E A T E  / C O P Y    I M A G E S
+
+=========================================================================*/
+
+int vtkpxUtil::CreateImage(vtkImageData* img,vtkImageData* Image)
+{
+  if (Image==NULL)
+    return 0;
+
+  int dim[3];  Image->GetDimensions(dim);
+  double sp[3];  Image->GetSpacing(sp);
+  double ori[3];  Image->GetOrigin(ori);
+  int c=Image->GetNumberOfScalarComponents();
+  int t=Image->GetScalarType();
+
+  return vtkpxUtil::CreateImage(img,dim[0],dim[1],dim[2],c,t,
+				sp[0],sp[1],sp[2],ori[0],ori[1],ori[2]);
+  
+}
+
+int vtkpxUtil::CreateFloatImage(vtkImageData* img,
+						 int width,int height,int depth,int numcomp,
+						 float sp1,float sp2,float sp3,
+						 float or1,float or2,float or3)
+{
+  return vtkpxUtil::CreateImage(img,width,height,depth,numcomp,VTK_FLOAT,
+				sp1,sp2,sp3,or1,or2,or3);
+}
+
+int vtkpxUtil::CreateShortImage(vtkImageData* img,
+						 int width,int height,int depth,int numcomp,
+						 float sp1,float sp2,float sp3,
+						 float or1,float or2,float or3)
+{
+  return vtkpxUtil::CreateImage(img,width,height,depth,numcomp,VTK_SHORT,
+				sp1,sp2,sp3,or1,or2,or3);
+
+}
+
+
+int vtkpxUtil::CreateImage(vtkImageData* img,
+			   int width,int height,int depth,int numcomp,
+			   int scalar_type,
+			   float sp1,float sp2,float sp3,
+					    float or1,float or2,float or3)
+{
+  if (img==NULL)
+    return 0;
+
+  img->SetSpacing(sp1,sp2,sp3);
+  img->SetOrigin(or1,or2,or3);
+  img->SetScalarType(scalar_type);
+  img->SetNumberOfScalarComponents(numcomp);
+  img->SetDimensions(width,height,depth);
+  img->SetWholeExtent(0,width-1,0,height-1,0,depth-1);
+  img->SetExtent(0,width-1,0,height-1,0,depth-1);
+  img->AllocateScalars();
+  return 1;
+}
+
+/*=========================================================================
+
+
+         B A S I C   I M A G E    U T I L I T I E S
+
+
+=========================================================================*/
+
+int vtkpxUtil::SaveAnalyze(const char* filename,vtkImageData* saveThisImage,int compression)
+{
+  if (saveThisImage==NULL)
+      return 0;
+
+  vtkpxAnalyzeImageWriter* ana=vtkpxAnalyzeImageWriter::New();
+
+  ana->SetInput(saveThisImage);
+  ana->SetCompression(compression);
+  ana->Save(filename);
+  ana->Delete();
+
+  return 1;
+}
+//------------------------------------------------------------------------------
+int vtkpxUtil::ReorderImage(vtkImageData* destination,vtkImageData* source)
+{
+
+  // Frames And Slices are output correct i.e. the correct output number of frames and slices
+
+  if (source==NULL || destination==NULL)
+      return 0;
+
+  int dim[3];
+  source->GetDimensions(dim);
+
+  int slices=source->GetNumberOfScalarComponents();
+  int frames=dim[2];
+
+
+  destination->CopyStructure(source);
+  destination->SetScalarType(source->GetScalarType());
+  destination->SetNumberOfScalarComponents(frames);
+  destination->SetDimensions(dim[0],dim[1],slices);
+  destination->AllocateScalars();
+
+  int numpixels=dim[0]*dim[1];
+  vtkDataArray* destScalars=destination->GetPointData()->GetScalars();
+  vtkDataArray* sourceScalars=source->GetPointData()->GetScalars();
+  
+  /*  fprintf(stdout,"Num Scalars output=%d, input=%d\n",
+	  destScalars->GetNumberOfTuples(),
+	  sourceScalars->GetNumberOfTuples());*/
+
+  for (int outputslice=0;outputslice<slices;outputslice++)
+    {
+      int  index_out=outputslice*numpixels;
+      for (int outputframe=0;outputframe<frames;outputframe++)
+	{
+	  int inputslice=outputframe;
+	  int inputframe=outputslice;
+	  int  index_in =inputslice*numpixels;
+	  //  fprintf(stderr,"Mapping input slice=%d, frame=%d (index_in=%d) to output slice=%d,frame=%d (index_out=%d)\n",inputslice,inputframe,index_in,outputslice,outputframe,index_out);
+	  for (int k=0;k<numpixels;k++)
+	    destScalars->SetComponent(index_out+k,outputframe,sourceScalars->GetComponent(index_in+k,inputframe));
+      }
+    }
+  return 1;
+}
+
+// -------------------------------------------------------------------------------------
+//   Multi-scale pyramid creation
+// -------------------------------------------------------------------------------------
+int vtkpxUtil::ResampleAndSmoothImage(vtkImageData* destination,
+				      vtkImageData* source,
+				      float gaussian,
+				      float resolution)
+{
+  return vtkpxUtil::ResampleAndSmoothImage(destination,source,gaussian,resolution,0.0);
+}
+
+
+int vtkpxUtil::ResampleAndSmoothImage(vtkImageData* destination,
+				      vtkImageData* source,
+				      float gaussian,
+				      float resolution,
+				      float padvalue)
+{
+
+  if (source==NULL || destination==NULL)
+      return 0;
+
+  if (source->GetPointData()==NULL)
+    return 0;
+
+  double sp[3];  source->GetSpacing(sp);
+  double ori[3]; source->GetOrigin(ori);
+  int dim[3];   source->GetDimensions(dim);
+
+
+  int ext[6];
+  for (int i=0;i<3;i++)
+    {
+      ext[i*2]=0;
+      ext[i*2+1] = int(0.5+(dim[i]*sp[i])/resolution)-1;
+    }
+
+  // Step 1 Smooth 
+  double gp[3];
+  for (int ia=0;ia<=2;ia++)
+    gp[ia]=(gaussian/sp[ia]);
+
+  vtkbisImageReslice* res=vtkbisImageReslice::New();
+  res->OptimizationOff();
+  if (gaussian > 0.1 )
+    {
+      vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+      smooth->SetInput(source);
+      smooth->SetStandardDeviations(gp);
+      res->SetInput(smooth->GetOutput());
+      smooth->Delete();
+    }
+  else
+    res->SetInput(source);
+  
+  res->SetOutputOrigin(source->GetOrigin());
+  res->SetOutputSpacing(resolution,resolution,resolution);
+  res->SetInterpolationMode(1);
+  res->SetOutputExtent(ext);
+  res->SetBackgroundLevel(padvalue);
+  res->Update();
+
+  destination->ShallowCopy(res->GetOutput());
+  res->Delete();
+
+  return 1;
+}
+
+
+// -------------------------------------------------------------------------------------
+//   Compute Image Difference
+// -------------------------------------------------------------------------------------
+
+float vtkpxUtil::ComputeAbsoluteImageDifference(vtkImageData* image1,
+						vtkImageData* image2,
+						int ignoreon,float ignore)
+{
+  int dim1[3]; image1->GetDimensions(dim1);
+  int dim2[3]; image1->GetDimensions(dim2);
+
+  int diff=0;
+  for (int ia=0;ia<=2;ia++)
+    diff+=abs(dim1[ia]-dim2[ia]);
+
+  if (diff!=0)
+    return -1.0;
+
+  int totalpixels=dim1[0]*dim1[1]*dim1[2];
+  float sum=0.0;
+  int used=0;
+  for (int px=0;px<totalpixels;px++)
+    {
+      float p1=image1->GetPointData()->GetScalars()->GetComponent(px,0);
+      float p2=image2->GetPointData()->GetScalars()->GetComponent(px,0);
+
+      if (ignoreon==0 || ( p1!=ignore && p2!=ignore)) 
+	{
+	  sum+=fabs(p1-p2);
+	  ++used;
+	}
+    }
+
+  if (used>0)
+    sum/=float(used);
+  return sum;
+}
+
+
+/*=========================================================================
+
+
+         C O D E   T O    R E O R I E N T    I M A G E S
+
+
+=========================================================================*/
+
+
+//------------------------------------------------------------------------------
+//  ReOrient Image Stuff 
+//------------------------------------------------------------------------------
+
+int vtkpxUtil::ReOrientMatrix(vtkImageData* source,int inputorient,int outputorient,vtkMatrix4x4* tmat,int centered)
+{
+
+  if (tmat==NULL || source==NULL)
+    return 0;
+  
+  int   dim[3];
+  double sp[3];
+  double ori[3];
+  source->GetDimensions(dim);
+  source->GetSpacing(sp);
+  source->GetOrigin(ori);
+
+  return vtkpxUtil::ReOrientMatrix(ori,sp,dim,inputorient,outputorient,tmat,centered);
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+int vtkpxUtil::ReOrientMatrix(double ori[3],double sp[3],int dim[3],
+			      int inputorient,int outputorient,vtkMatrix4x4* tmat,
+			      int centered)
+{
+  if (tmat==NULL)
+    return 0;
+  
+  // Xenios -- to do stuff
+  // This should be generalized for all vectors etc.
+  // In fact the easiest way would be to simply generate matrices for each orientation
+  // and then multiply them
+  inputorient=vtkbisImageHeader::MapOrientationToOldStyle(inputorient);
+  outputorient=vtkbisImageHeader::MapOrientationToOldStyle(outputorient);
+
+
+
+  /*  fprintf(stderr,"Inputs ori=%f,%f,%f sp=%f,%f,%f dim=%d,%d,%d orient=%d,%d\n",
+	  ori[0],ori[1],ori[2],
+	  sp[0],sp[1],sp[2],
+	  dim[0],dim[1],dim[2],inputorient,outputorient);*/
+
+  vtkMatrix4x4* mat=vtkMatrix4x4::New();
+  mat->Identity();
+  
+  if (inputorient==outputorient)
+    return 1;
+
+  if (inputorient==1 && outputorient==0)
+    {
+      // Coronal->Axial  
+      mat->SetElement(1, 1, 0); mat->SetElement( 1, 2, -1);
+      mat->SetElement(2, 1, 1); mat->SetElement( 2, 2,  0);
+    }
+   
+  if (inputorient==0 && outputorient==1)
+    {
+      // Axial->Coronal  
+      mat->SetElement(1, 1,  0); mat->SetElement(1, 2, 1);
+      mat->SetElement(2, 1, -1); mat->SetElement(2, 2, 0);
+    }
+	
+  if (inputorient==1 && outputorient==2)
+    {
+      // Coronal->Sagittal  
+      mat->SetElement(0, 0, 0) ;  mat->SetElement(1, 0, 0 );  mat->SetElement(2, 0, 1);
+      mat->SetElement(1, 1, -1);
+      mat->SetElement(0, 2, -1 ); mat->SetElement(1, 2, 0 ); mat->SetElement(2, 2, 0);
+    }
+  
+  if (inputorient==2 && outputorient==1)
+    {
+      // Sagittal->Coronal  
+      mat->SetElement(0, 0, 0) ;  mat->SetElement(0, 1, 0 );  mat->SetElement(0, 2, 1);
+      mat->SetElement(1, 1, -1);
+      mat->SetElement(2, 0, -1 ); mat->SetElement(2, 1, 0 ); mat->SetElement(2, 2, 0);
+    }
+
+  
+  if (inputorient==0 && outputorient==2)
+    {
+      // Axial->Sagittal  
+      mat->SetElement(0, 0,  0) ;  mat->SetElement(1, 0, 1) ;  mat->SetElement(2, 0, 0);
+      mat->SetElement(0, 1,  0) ;  mat->SetElement(1, 1, 0) ;  mat->SetElement(2, 1, 1);
+      mat->SetElement(0, 2, -1) ;  mat->SetElement(1, 2, 0) ;  mat->SetElement(2, 2, 0);
+    }
+
+  if (inputorient==2 && outputorient==0)
+    {
+      // Sagittal->Axial  
+      mat->SetElement(0, 0,  0) ;  mat->SetElement(0, 1, 1) ;  mat->SetElement(0, 2, 0);
+      mat->SetElement(1, 0,  0) ;  mat->SetElement(1, 1, 0) ;  mat->SetElement(1, 2, 1);
+      mat->SetElement(2, 0, -1) ;  mat->SetElement(2, 1, 0) ;  mat->SetElement(2, 2, 0);
+    }
+
+
+  //  mat->Print(cerr);
+
+  if (centered==0)
+    {
+      double sp_out[3]; int dim_out[3];
+      vtkpxUtil::ReOrientDimensions(sp,dim,inputorient,outputorient,sp_out,dim_out);
+      float shift_y[3],shift_x[3];
+      for (int i=0;i<=2;i++)
+	{
+	  shift_y[i]= 0.5*sp[i]*float(dim[i]-1);
+	  shift_x[i]=-0.5*sp_out[i]*float(dim_out[i]-1);
+	}
+      
+      vtkTransform* tr=vtkTransform::New();
+      tr->Identity();
+      tr->PostMultiply();
+      tr->Translate(shift_x);
+      tr->Concatenate(mat);
+      tr->Translate(shift_y);
+      tr->GetMatrix(tmat);
+      tr->Delete();
+    }
+  else
+    tmat->DeepCopy(mat);
+
+  mat->Delete();
+  
+
+  return 1;
+}  
+//------------------------------------------------------------------------------
+int vtkpxUtil::ReOrientDimensions(double sp_in[3],int dim_in[3],int inputorient,int outputorient,
+				  double sp_out[3],int dim_out[3])
+{
+
+  inputorient=vtkbisImageHeader::MapOrientationToOldStyle(inputorient);
+  outputorient=vtkbisImageHeader::MapOrientationToOldStyle(outputorient);
+
+  if (inputorient==outputorient)
+    {
+      for (int ia=0;ia<=2;ia++)
+	{
+	  dim_out[ia]=dim_in[ia];
+	  sp_out[ia]=sp_in[ia];
+	}
+    }
+
+  if (inputorient==1 && outputorient==0)
+    {
+      // Coronal->Axial  
+      dim_out[0]=dim_in[0]; dim_out[1]=dim_in[2]; dim_out[2]=dim_in[1];
+      sp_out[0]=sp_in[0];   sp_out[1]=sp_in[2];   sp_out[2]=sp_in[1];
+    }
+   
+  if (inputorient==0 && outputorient==1)
+    {
+      // Axial->Coronal  
+      dim_out[0]=dim_in[0]; dim_out[1]=dim_in[2]; dim_out[2]=dim_in[1];
+      sp_out[0]=sp_in[0];   sp_out[1]=sp_in[2];   sp_out[2]=sp_in[1];
+    }
+	
+  if (inputorient==1 && outputorient==2)
+    {
+      // Coronal->Sagittal  
+      dim_out[0]=dim_in[2]; dim_out[1]=dim_in[1]; dim_out[2]=dim_in[0];
+      sp_out[0]=sp_in[2];   sp_out[1]=sp_in[1];   sp_out[2]=sp_in[0];
+    }
+  
+  if (inputorient==2 && outputorient==1)
+    {
+      // Sagittal->Coronal  
+      dim_out[0]=dim_in[2]; dim_out[1]=dim_in[1]; dim_out[2]=dim_in[0];
+      sp_out[0]=sp_in[2];   sp_out[1]=sp_in[1];   sp_out[2]=sp_in[0];
+    }
+
+  
+  if (inputorient==0 && outputorient==2)
+    {
+      // Axial->Sagittal  
+      dim_out[0]=dim_in[1]; dim_out[1]=dim_in[2]; dim_out[2]=dim_in[0];
+      sp_out[0]=sp_in[1];   sp_out[1]=sp_in[2];   sp_out[2]=sp_in[0];
+    }
+
+  if (inputorient==2 && outputorient==0)
+    {
+      // Sagittal->Axial  
+      dim_out[0]=dim_in[2]; dim_out[1]=dim_in[0]; dim_out[2]=dim_in[1];
+      sp_out[0]=sp_in[2];   sp_out[1]=sp_in[0];   sp_out[2]=sp_in[1];
+    }
+
+  return 1;
+}
+
+
+int vtkpxUtil::ReOrientImage(vtkImageData* destination,vtkImageData* source,int inputorient,int outputorient)
+{
+  if (source==NULL || destination==NULL)
+      return 0;
+
+  // This is unncecessary, i.e. taken care of in the individual functions
+  inputorient=vtkbisImageHeader::MapOrientationToOldStyle(inputorient);
+  outputorient=vtkbisImageHeader::MapOrientationToOldStyle(outputorient);
+
+  if (inputorient==outputorient)
+    {
+      destination->ShallowCopy(source);
+      return 1;
+    }
+  
+ 
+  vtkMatrix4x4* tmat=vtkMatrix4x4::New();
+  int ok2=vtkpxUtil::ReOrientMatrix(source,inputorient,outputorient,tmat);
+  if (ok2==0)
+    return ok2;
+
+  vtkTransform* trans=vtkTransform::New();
+  trans->SetMatrix(tmat);
+		
+  double sp[3],spout[3];
+  int dim[3],dimout[3];
+
+  source->GetSpacing(sp);
+  source->GetDimensions(dim);
+  vtkpxUtil::ReOrientDimensions(sp,dim,inputorient,outputorient,spout,dimout);
+
+  vtkbisImageReslice* reslice=vtkbisImageReslice::New();
+
+  reslice->SetInput(source);
+  reslice->OptimizationOff();
+  reslice->SetOutputOrigin(0.0,0.0,0.0);
+  reslice->SetOutputExtent(0,dimout[0]-1,0,dimout[1]-1,0,dimout[2]-1);
+  reslice->SetOutputSpacing(spout[0],spout[1],spout[2]);
+  reslice->SetInterpolationMode(0);
+  reslice->SetResliceTransform(trans);
+  reslice->SetBackgroundLevel(0);
+  reslice->Update();
+
+  destination->ShallowCopy(reslice->GetOutput());
+  reslice->Delete();
+  trans->Delete();
+  tmat->Delete();
+  return 1;
+}
+
+// --------------------------------------------------------------------------------
+// Reslice image source to have same dimensions as image ref
+// Store output in destination using transform, interp and background
+// --------------------------------------------------------------------------------
+int vtkpxUtil::ResliceImage(vtkImageData* destination,
+			    vtkImageData* source,
+			    vtkImageData* ref,
+			    vtkAbstractTransform* transform,
+			    int interp,float background)
+{
+  if (destination==NULL || source==NULL || ref==NULL || transform==NULL)
+    return 0;
+
+  if (interp==1)
+    {
+      double range[2]; 
+      source->GetPointData()->GetScalars()->GetRange(range);
+      if (range[1]-range[0]<16.0)
+	{
+	  interp=3;
+	  fprintf(stderr,"Switching to Cubic .... low range of input\n");
+	}
+    }
+
+  vtkbisImageReslice* resl=vtkbisImageReslice::New();
+  resl->SetInput(source);
+  resl->SetInformationInput(ref);
+  resl->SetResliceTransform(transform);
+  resl->SetInterpolationMode(interp);
+  resl->SetBackgroundLevel(background);
+  resl->OptimizationOff();
+  resl->Update();
+
+  destination->ShallowCopy(resl->GetOutput());
+  resl->Delete();
+  return 1;
+}
+
+// --------------------------------------------------------------------------------
+// Equi Reslice force two images to have same dimensions using linear interpolation
+// --------------------------------------------------------------------------------
+
+
+int vtkpxUtil::EquiReslice(vtkImageData* output,
+			   vtkImageData* input,
+			   vtkImageData* reference)
+{
+  if (input==NULL || output == NULL || reference==NULL)
+    return 0;
+
+  vtkIdentityTransform* tr=vtkIdentityTransform::New();
+
+  int ok=vtkpxUtil::ResliceImage(output,input,reference,tr,1,0.0);
+  tr->Delete();
+  return ok;
+
+
+}
+
+
+// ------------------------------------------------------------------------------
+int vtkpxUtil::ExtractFrames(vtkImageData* destination,vtkImageData* source,int begin,int end,int inc)
+{
+  // Frames And Slices are output correct i.e. the correct output number of frames and slices
+
+  if (source==NULL || destination==NULL)
+      return 0;
+
+  int dim[3];
+  source->GetDimensions(dim);
+  int frames=source->GetNumberOfScalarComponents();
+
+  
+
+  begin=Irange(begin,0,frames-1);
+  end=Irange(end,begin,frames-1);
+  inc=Irange(inc,1,frames);
+
+  if (begin==0 && end==(frames-1) && inc==1)
+    {
+      destination->ShallowCopy(source);
+      return 1;
+    }
+
+  int totalframes=0;
+  for (int test=begin;test<=end;test+=inc)
+    ++totalframes;
+
+  destination->SetScalarType(source->GetScalarType());
+  destination->SetNumberOfScalarComponents(totalframes);
+  destination->SetDimensions(dim);
+  destination->SetWholeExtent(source->GetWholeExtent());
+  destination->SetExtent(source->GetExtent());
+  destination->SetSpacing(source->GetSpacing());
+  destination->SetOrigin(source->GetOrigin());
+  destination->AllocateScalars();
+
+
+  vtkDataArray* destScalars=destination->GetPointData()->GetScalars();
+  vtkDataArray* sourceScalars=source->GetPointData()->GetScalars();
+  
+  int inframe=begin;
+  for (int fr=0;fr<totalframes;fr++)
+    {
+      destScalars->CopyComponent(fr,sourceScalars,inframe);
+      inframe+=inc;
+    }
+  return 1;
+
+}
+
+// ------------------------------------------------------------------------------
+int vtkpxUtil::ComputeImageNormalizationFactors(vtkImageData* ref,
+						vtkImageData* scaled,
+						vtkFloatArray* params,
+						float threshold)
+  
+{
+ 
+  int nump=ref->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nump2=scaled->GetPointData()->GetScalars()->GetNumberOfTuples();
+
+  if (nump!=nump2)
+    return 0;
+
+  params->SetNumberOfComponents(1);
+  params->SetNumberOfTuples(2);
+
+
+  float sx=0.0,sy=0.0,sxy=0.0,sxx=0.0;
+  int ndata=0;
+  
+  vtkDataArray* pix1=ref->GetPointData()->GetScalars();
+  vtkDataArray* pix2=scaled->GetPointData()->GetScalars();
+
+
+  for (int j=0;j<nump;j++) 
+    {
+      float x=pix1->GetComponent(j,0);
+      float y=pix2->GetComponent(j,0);
+      
+      if (x>=threshold)
+	{
+	  sx += x;
+	  sy += y;
+	  sxy += x*y;
+	  sxx += x*x;
+	  ++ndata;
+	}
+    }
+
+  if (ndata==0)
+    return 0;
+
+  //  fprintf(stderr,"sx=%f , sy=%f sxy=%f sxx=%f ndata=%d\n",sx/float(ndata),sy/float(ndata),sxy,sxx,ndata);
+  
+  float del=float(ndata)*sxx-sx*sx;
+  float a=(sxx*sy-sx*sxy)/del;
+  float b=(float(ndata)*sxy-sx*sy)/del;
+
+  params->SetComponent(0,0,a);
+  params->SetComponent(1,0,b);
+  return 1;
+}
+						
+
+// ---------------------------------------------------------------
+float vtkpxUtil::Fmin(float a,float b)
+{
+  if (a<b)
+      return a;
+  else
+      return b;
+}
+
+float vtkpxUtil::Fmax(float a,float b)
+{
+  if (a>b)
+      return a;
+  else
+      return b;
+}
+
+int vtkpxUtil::Imin(int a,int b)
+{
+  if (a<b)
+      return a;
+  else
+      return b;
+}
+
+int vtkpxUtil::Imax(int a,int b)
+{
+  if (a>b)
+      return a;
+  else
+      return b;
+}
+// -------------------------------------------------------------
+float vtkpxUtil::Frange(float a,float minv,float maxv)
+{
+  if (a<minv) a=minv;
+  if (a>maxv) a=maxv;
+  return a;
+}
+// -------------------------------------------------------------
+int  vtkpxUtil::Irange(int   a,int   minv,int   maxv)
+{
+  if (a<minv) a=minv;
+  if (a>maxv) a=maxv;
+  return a;
+}
+// -------------------------------------------------------------
+
+int vtkpxUtil::AutoCropImage(vtkImageData* img,int offset)
+{
+
+  if (img==NULL)
+    {
+      fprintf(stderr,"Bad Image in AutoCrop\n");
+      return 0;
+    }
+
+  if (offset<2)
+    offset=2;
+
+  int dim[3]; img->GetDimensions(dim);
+  int bounds[3][2];
+  for (int ia=0;ia<=2;ia++)
+    {
+      bounds[ia][0]=dim[ia]-1;
+      bounds[ia][1]=0;
+    }
+
+  fprintf(stderr,"Starting Bounds x: %d:%d y: %d:%d z: %d:%d\n",
+	  bounds[0][0],bounds[0][1],bounds[1][0],bounds[1][1],bounds[2][0],bounds[2][1]);
+  
+  for (int k=0;k<dim[2];k+=2)
+    for (int j=0;j<dim[1];j+=2)
+      for (int i=0;i<dim[0];i+=2)
+	{
+	  double v=img->GetScalarComponentAsDouble(i,j,k,0);
+	  if (v>0)
+	    {
+	      bounds[0][0]=Imin(bounds[0][0],i);
+	      bounds[0][1]=Imax(bounds[0][1],i);
+	      bounds[1][0]=Imin(bounds[1][0],j);
+	      bounds[1][1]=Imax(bounds[1][1],j);
+	      bounds[2][0]=Imin(bounds[2][0],k);
+	      bounds[2][1]=Imax(bounds[2][1],k);
+	    }
+	}
+  
+  fprintf(stderr,"Bounds x: %d:%d y: %d:%d z: %d:%d\n",
+      bounds[0][0],bounds[0][1],bounds[1][0],bounds[1][1],bounds[2][0],bounds[2][1]);
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      bounds[ia][0]=Imax(0,bounds[ia][0]-offset);
+      bounds[ia][1]=Imin(dim[ia]-1,bounds[ia][1]+offset);
+    }
+
+
+  fprintf(stderr,"Offset (%d) Bounds x: %d:%d y: %d:%d z: %d:%d\n",offset,
+	  bounds[0][0],bounds[0][1],bounds[1][0],bounds[1][1],bounds[2][0],bounds[2][1]);
+
+  //  fprintf(stderr,"Old Dimensions =%d %d %d\n",img->GetDimensions()[0],img->GetDimensions()[1],img->GetDimensions()[2]);
+
+  vtkpxImageExtractVOI* voi=  vtkpxImageExtractVOI::New();
+  //  voi->DebugOn();
+  voi->SetVOI(bounds[0][0],bounds[0][1],bounds[1][0],bounds[1][1],bounds[2][0],bounds[2][1]);
+  //  voi->DebugOff();
+  voi->SetInput(img);
+  voi->Update();
+
+  img->ShallowCopy(voi->GetOutput());
+  //  fprintf(stderr,"New Dimensions =%d %d %d\n",img->GetDimensions()[0],img->GetDimensions()[1],img->GetDimensions()[2]);
+  voi->Delete();
+  return 1;
+}
+
+
+// ----------------------------------------------------------------------------------------------------
+void vtkpxUtil::ImageRobustRange(vtkImageData* image,float perlow,float perhigh,vtkFloatArray* params,
+				 float dim_target)
+{
+  if (params==NULL)
+    return;
+
+  float tlow,thigh;
+  ImageRobustRange(image,perlow,perhigh,tlow,thigh,dim_target);
+  params->SetNumberOfTuples(2);
+  params->SetComponent(0,0,tlow);
+  params->SetComponent(1,0,thigh);
+}
+
+void vtkpxUtil::ImageRobustRange(vtkImageData* image,float perlow,float perhigh,float& tlow,float& thigh,
+				 float dim_target)
+{
+  dim_target=Frange(dim_target,16.0,256.0);
+
+  if (image==NULL)
+    {
+      tlow=0.0;
+      thigh=1.0;
+      return;
+    }
+
+  if (perlow<0.0 || perlow>0.99)
+    perlow=0.0;
+  
+  if (perhigh<perlow)
+    perhigh=perlow+0.01;
+  if (perhigh>1.0)
+    perhigh=1.0;
+
+  double in_range[2];
+  image->GetPointData()->GetScalars()->GetRange(in_range);
+  if ((in_range[1]-in_range[0])<20.0)
+    {
+      tlow=in_range[0];
+      thigh=in_range[1];
+      double diff=in_range[1]-in_range[0];
+
+      if (diff>0.0)
+	{
+	  tlow=in_range[0]+perlow*diff;
+	  thigh=in_range[0]+perhigh*diff;
+	}
+      return;
+    }
+  
+
+  double sp[3]; image->GetSpacing(sp);
+  int dim[3];image->GetDimensions(dim);
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (dim[ia]>32)
+	sp[ia]*=double(dim[ia])/dim_target;
+    }
+
+  vtkImageResample* resl=vtkImageResample::New();
+  //  resl->DebugOn();
+
+  if (image->GetNumberOfScalarComponents()>1)
+    {
+      vtkImageExtractComponents* ext=vtkImageExtractComponents::New();
+      ext->SetInput(image);
+      ext->SetComponents(0);
+      ext->Update();
+      resl->SetInput(ext->GetOutput());
+      ext->Delete();
+    }
+  else
+    {
+      resl->SetInput(image);
+    }
+
+  resl->InterpolateOff();
+  resl->SetAxisOutputSpacing(0,sp[0]);
+  resl->SetAxisOutputSpacing(1,sp[1]);
+  resl->SetAxisOutputSpacing(2,sp[2]);
+  resl->Update();
+  
+  vtkDataArray* tmp=resl->GetOutput()->GetPointData()->GetScalars();
+  double range[2];
+  tmp->GetRange(range);
+  int bins=512;
+
+  if (range[1]-range[0] < bins)
+    bins=int(range[1]-range[0])+1;
+
+  float spacing = (range[1]-range[0])/float(bins-1);
+
+
+  vtkImageAccumulate* accumulate=vtkImageAccumulate::New();
+
+  accumulate->SetInput(resl->GetOutput());
+  accumulate->SetComponentExtent(0,bins-1,0,0,0,0);
+  accumulate->SetComponentOrigin(range[0],0,0);
+  accumulate->SetComponentSpacing(spacing,1,1);
+  accumulate->Update();
+
+  vtkDataArray* data=accumulate->GetOutput()->GetPointData()->GetScalars();
+  vtkFloatArray* cum=vtkFloatArray::New();
+  cum->SetNumberOfTuples(bins);
+
+  cum->SetComponent(0,0,data->GetComponent(0,0));
+  for (int ia=1;ia<bins;ia++)
+    cum->SetComponent(ia,0,data->GetComponent(ia,0)+cum->GetComponent(ia-1,0));
+
+  float total=cum->GetComponent(bins-1,0);
+
+  int foundperlow=0,foundperhigh=0;
+
+  for (int ib=1;ib<bins;ib++)
+    {
+      float v=cum->GetComponent(ib,0);
+      if (foundperlow==0)
+	{
+	  if (v/total > perlow)
+	    {
+	      foundperlow=1;
+	      tlow=range[0]+ib*spacing;
+	    }
+	}
+
+      if (foundperhigh==0)
+	{
+	  if (v/total > perhigh)
+	    {
+	      foundperhigh=1;
+	      thigh=range[0]+ib*spacing;
+	      ib=bins;
+	    }
+	}
+    }
+
+  //    fprintf(stderr,"low=%.2f (%f) high=%.2f (%f)\n", perlow,tlow,perhigh,thigh);
+
+  accumulate->Delete();
+  resl->Delete();
+
+  //   fprintf(stderr,"Done\n");
+}
+
+double vtkpxUtil::ComputeImageProductSum(vtkImageData* img1,vtkImageData* img2)
+{
+  if (img1==NULL || img2==NULL)
+    return 0.0;
+
+  vtkDataArray* dat1=img1->GetPointData()->GetScalars();
+  vtkDataArray* dat2=img2->GetPointData()->GetScalars();
+  if (dat1->GetNumberOfTuples()!=dat2->GetNumberOfTuples())
+    return 0.0;
+
+  int nt=dat1->GetNumberOfTuples();
+
+  double sum=0.0;
+  
+  for (int ia=0;ia<nt;ia++)
+    sum+=dat1->GetComponent(ia,0)*dat2->GetComponent(ia,0);
+
+  return sum;
+
+}
+
+double vtkpxUtil::ComputeImageSum(vtkImageData* img1,double threshold)
+{
+  if (img1==NULL)
+    return 0.0;
+
+  double range[2]; img1->GetPointData()->GetScalars()->GetRange(range);
+  if (threshold<0.0)
+    threshold=0.0;
+  else if (threshold>1.0)
+    threshold=1.0;
+
+  double thr=range[0]+threshold*range[1];
+  vtkDataArray* dat1=img1->GetPointData()->GetScalars();
+  int nt=dat1->GetNumberOfTuples();
+
+  double sum=0.0;
+  for (int ia=0;ia<nt;ia++)
+    {
+      double v=dat1->GetComponent(ia,0);
+      if (v>thr)
+	sum+=v;
+    }
+  return sum;
+}
+
diff --git a/bioimagesuite30_src/Common/vtkpxUtil.h b/bioimagesuite30_src/Common/vtkpxUtil.h
new file mode 100644
index 0000000..badf264
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxUtil.h
@@ -0,0 +1,232 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxUtil - a collection of static utility functions
+// .SECTION Description
+// This class contains a collection of <EM>static</EM> utility functions for use elsewhere ala vtkMath
+// These deal with images and transformations.
+// <br> <br> <EM>Copyright (c) 1995-2002 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// This requires pxutil 
+
+#ifndef __vtkpxUtil_h
+#define __vtkpxUtil_h
+
+#include "vtkObject.h"
+#include "vtkRenderer.h"
+#include "vtkFloatArray.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "pxutil.h"
+
+class vtkImageData;
+class vtkLookupTable;
+class vtkImageData;
+class vtkPolyData;
+class vtkPoints;
+class vtkContourFilter;
+class vtkAbstractTransform;
+class vtkDataArray;
+class vtkpxMatrix;
+
+
+
+
+
+class vtkpxUtil : public vtkObject
+{
+public:
+  static vtkpxUtil *New();
+  vtkTypeMacro(vtkpxUtil,vtkObject);
+  
+
+  // -------------------------------------------------------------------
+  // Create And Copy Image Routines -- these are HUGELY important
+  // -------------------------------------------------------------------
+
+  // Description:
+  // Create Image To have identical dimenions as Input
+  static int CreateImage(vtkImageData* img,vtkImageData* SameSizeAsThisOne);
+
+  // Description:
+  // Create Float/Short or Generic Type Image with specified dimensions
+  static int CreateFloatImage(vtkImageData* img,
+			      int width,int height,int depth,int numcomp,
+			      float sp1,float sp2,float sp3,
+			      float or1,float or2,float or3);
+  
+    
+  static  int CreateShortImage(vtkImageData* img,int width,int height,int depth,int numcomp,
+			       float sp1,float sp2,float sp3,
+			       float or1,float or2,float or3);
+  
+  static int CreateImage(vtkImageData* img,
+			 int width,int height,int depth,int numcomp,
+			 int scalar_type,
+			 float sp1,float sp2,float sp3,
+			 float or1,float or2,float or3);
+
+  // -------------------------------------------------------------------
+  // Basic Image Operations 
+  // -------------------------------------------------------------------
+
+  // Description:
+  // Reorder 4D Image into frame-major order mode from slice-major order mode
+  static int   ReorderImage(vtkImageData* destination,vtkImageData* source);
+
+  // Description:
+  // Extract Frames
+  static int   ExtractFrames(vtkImageData* destination,vtkImageData* source,int begin,int end,int inc);
+
+  // Description:
+  // Resample image to spacing resol*resol*resol after smoothing with Gaussian sigma (all in mm)
+  static int ResampleAndSmoothImage(vtkImageData* destination,
+				    vtkImageData* source,
+				    float gaussian,
+				    float resolution,
+				    float padvalue);
+
+  static int ResampleAndSmoothImage(vtkImageData* destination,
+				    vtkImageData* source,
+				    float gaussian,
+				    float resolution);
+
+  // Description:
+  // Average absolute difference of pixel intensity values of all voxels
+  // If ignoreon=1, then any pixel with value=ignore is not used
+  static float ComputeAbsoluteImageDifference(vtkImageData* image1,
+					      vtkImageData* image2,
+					      int ignoreon=0,
+					      float ignore=-1.0);
+  
+
+  
+  static int ComputeImageNormalizationFactors(vtkImageData* ref,
+					      vtkImageData* scaled,
+					      vtkFloatArray* params,
+					      float threshold=0.0);
+						
+  // Description:
+  // Using vtkpxAnalyzeImageWriter, saves ImageData to analyze file
+  static int   SaveAnalyze(const char* fname,vtkImageData* points,int compression=0);
+
+  // ------------------------------------------------------------------
+  //  Reslice image input to have same dimensions as image reference 
+  // and store in output
+  //
+  // Use transformation = transform
+  //     interpolation mode = interp (0,1,3)
+  //     background    value = background
+  // ------------------------------------------------------------------
+
+  static int EquiReslice(vtkImageData* output,
+			 vtkImageData* input,
+			 vtkImageData* reference);
+  
+
+  static int ResliceImage(vtkImageData* output,
+			  vtkImageData* input,
+			  vtkImageData* reference,
+			  vtkAbstractTransform* transform,
+			  int interp,float background);
+
+  static int AutoCropImage(vtkImageData* img,int offset=5);
+
+  // ------------------------------------------------------------------
+  // Re-orient Image Routines 
+  // ------------------------------------------------------------------
+  
+  
+  // Description:
+  // Procedures to Re-Orient an Image from Coronal/Axial/Saggital to C/A/S
+  static int ReOrientMatrix(vtkImageData* source,int inputorient,int outputorient,vtkMatrix4x4* tmat,int centered=0);
+  static int ReOrientImage(vtkImageData* destination,vtkImageData* source,int inputorient,int outputorient);
+
+  //BTX
+  // Lower Level Helper Routines
+  static int ReOrientMatrix(double ori[3],double sp[3],int dim[3],int inputorient,int outputorient,vtkMatrix4x4* tmat,int centered=0);
+  static int ReOrientDimensions(double sp_in[3],int dim_in[3],int inputorient,int outputorient,double sp_out[3],int dim_out[3]);
+  //ETX
+  
+
+
+  // -------------------------------------------------
+  // Utility Code
+  // -------------------------------------------------
+
+  static float Fmin(float a,float b);
+  static float Fmax(float a,float b);
+  static float Frange(float a,float minv,float maxv);
+
+  static int Imin(int a,int b);
+  static int Imax(int a,int b);
+  static int Irange(int a,int minv,int maxv);
+
+  // -------------------------------------------------------
+  // Image Robust Range -- moved here from vtkpxNonLinearFit
+  // -------------------------------------------------------
+  static void ImageRobustRange(vtkImageData* image,float perlow,float perhigh,float& tlow,float& thigh,float dim=32.0);
+  static void ImageRobustRange(vtkImageData* image,float perlow,float perhigh,vtkFloatArray* params,float dim=32.0);
+
+
+  // -------------------------------------------------------
+  // Compute Sum of Image Product
+  // -------------------------------------------------------
+  static double ComputeImageProductSum(vtkImageData* img1,vtkImageData* img2);
+  static double ComputeImageSum(vtkImageData* img1,double threshold=0.05);
+ 
+};
+#endif
+
diff --git a/bioimagesuite30_src/Common/vtkpxVVLinkConnectorNew.cpp b/bioimagesuite30_src/Common/vtkpxVVLinkConnectorNew.cpp
new file mode 100644
index 0000000..4027b34
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxVVLinkConnectorNew.cpp
@@ -0,0 +1,1446 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// VVLink specific includes
+#include <VVLConnection.h>
+#include <VVLQGetPatientName.h>
+#include <VVLQGetPoints.h>
+#include <VVLQGetTrajectories.h>
+#include <VVLQGetSliceSets.h>
+#include <VVLQSetView.h>
+#include <VVLNTrackingData.h>
+#include <common/VVLCoordinateSystem.h>
+#include <common/VVLTrajectory.h>
+
+#include "vtkImageData.h"
+#include "vtkMatrixToLinearTransform.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkRenderWindow.h"
+#include "vtkTransformPolyDataFilter.h"
+#include "vtkpxVVLinkConnectorNew.h"
+#include <vtkCharArray.h>
+#include <vtkConeSource.h>
+#include <vtkbisCylinderSource.h>
+#include <vtkSphereSource.h>
+#include <vtkpxCrossHairSource.h>
+#include <vtkCamera.h>
+#include <vtkDoubleArray.h>
+#include <vtkbisImageReslice.h>
+#include <vtkMath.h>
+#include <vtkTransform.h>
+#include <vtkUnsignedCharArray.h>
+#include <vtkWindowToImageFilter.h>
+#include <vtkLookupTable.h>
+#include <vtkCellArray.h>
+
+// std includes
+#include <list>
+#include <sstream>
+#include <string>
+
+
+// small helper class
+//BTX
+template<typename T>
+class vtkObjectContainer
+{
+public:
+	vtkObjectContainer( T * pointer )
+   :_pointer(pointer)
+	{}
+	~vtkObjectContainer(){ _pointer->Delete(); }
+
+	T * operator->(){ return _pointer; }
+	operator T* () { return _pointer; }
+
+private:
+	T * _pointer;
+
+	// not implemented, forbidden
+	vtkObjectContainer(const vtkObjectContainer &);
+	const vtkObjectContainer &operator=(const vtkObjectContainer &);
+};
+//ETX
+
+// -------------------------------------------------------------------
+//       Initialize Static Members to NULL
+//
+// All instances of VVLinkConnectorNew share a single connection to
+// VectorVisionCranial using the static
+//
+// vtkpxVVLinkConnectorNew::VVLinkServer  proxy object
+//
+// The channel number for each connection is incremented automatically
+// -------------------------------------------------------------------
+vvlink::VVLConnection*         vtkpxVVLinkConnectorNew::VVLinkServer         = NULL;
+char *                         vtkpxVVLinkConnectorNew::VVLinkPatientName    = NULL;
+vvlink::VVLQGetSliceSets *     vtkpxVVLinkConnectorNew::VVLSliceSets         = NULL;
+char*                          vtkpxVVLinkConnectorNew::VVLinkImageListNames = NULL;
+int                            vtkpxVVLinkConnectorNew::VVLinkNumberOfImages = 0;
+vvlink::VVLNTrackingData *     vtkpxVVLinkConnectorNew::VVLNTrackingData     = NULL;
+std::list<std::string>         vtkpxVVLinkConnectorNew::VVLToolsAndOrder     = std::list<std::string>();
+
+vtkpxVVLinkConnectorNew* vtkpxVVLinkConnectorNew::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxVVLinkConnectorNew");
+  if(ret)
+  {
+    return (vtkpxVVLinkConnectorNew*)ret;
+  }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxVVLinkConnectorNew;
+}
+
+
+// Construct object to extract all of the input data.
+vtkpxVVLinkConnectorNew::vtkpxVVLinkConnectorNew()
+{
+  // The following lines determine the instruments that will be considered in GetVVLinkPointer
+  // and determine its priority
+  if ( !this->VVLToolsAndOrder.size() )
+  {
+
+    // TODO: sort
+    this->VVLToolsAndOrder.push_back("Softouch");
+    this->VVLToolsAndOrder.push_back("Pointer");
+    this->VVLToolsAndOrder.push_back("InstrumentXL");
+    this->VVLToolsAndOrder.push_back("InstrumentL");
+    this->VVLToolsAndOrder.push_back("InstrumentML");
+    this->VVLToolsAndOrder.push_back("InstrumentM");
+    this->VVLToolsAndOrder.push_back("InstrumentS");
+    this->VVLToolsAndOrder.push_back("BiopsyInstrument");
+    this->VVLToolsAndOrder.push_back("BiopsyGuidingTubeInstrument");
+    this->VVLToolsAndOrder.push_back("Microscope");
+    this->VVLToolsAndOrder.push_back("Ultrasound");
+  }
+
+  this->VVLinkChannel=-1;
+  this->VVLinkVersion=7.5;
+  this->VVLCoordinateSystem = vvlink::VVLCoordinateSystem::New( vvlink::VVLCoordinateSystem::PATIENT );
+}
+
+vtkpxVVLinkConnectorNew::~vtkpxVVLinkConnectorNew()
+{
+  this->VVLCoordinateSystem->Delete();
+}
+// ---------------------------------------------------------------------------
+
+void vtkpxVVLinkConnectorNew::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkObject::PrintSelf(os,indent);
+
+  os << indent << "  VVLinkChannel " << this->VVLinkChannel << "\n";
+  os << indent << "  VVLinkServer " << this->VVLinkServer << "\n";
+  os << indent << "  VVLinkPatientName " << this->VVLinkPatientName << "\n";
+  os << indent << "  VVLinkImageListNames " << this->VVLinkImageListNames << "\n";
+  os << indent << "  VVLinkNumberOfImages " << this->VVLinkNumberOfImages << "\n";
+}
+
+// -------------------------------------------------------------------------------
+//           Vector Vision Related Code
+// -------------------------------------------------------------------------------
+int vtkpxVVLinkConnectorNew::InitializeVVLConnection(char* server,char* password,int channel)
+{
+
+  if (vtkpxVVLinkConnectorNew::VVLinkServer!=NULL)
+  {
+    //      cerr << "Alrady Connected \n";
+    this->VVLinkChannel=channel;
+    return 2;
+  }
+
+  //  cerr << "Creating VVLink Server \n";
+  vtkpxVVLinkConnectorNew::VVLinkServer= vvlink::VVLConnection::New();
+  //  cout << "Connecting to \"" << server <<  "\" ... ";
+
+  try {
+    int i;
+    std::string sClientName;
+    std::stringstream ss;
+    ss << "Client Nr. " << channel;
+    sClientName = ss.str();
+
+
+    vtkpxVVLinkConnectorNew::VVLinkServer->ConnectTo( server, sClientName, password );
+    this->VVLinkChannel=channel;
+    //cout << "!!!done channel = " << this->VVLinkChannel << " !!!" << endl << endl;
+
+    // getting the patient data
+    vvlink::VVLQGetPatientName *cmdPatient = vvlink::VVLQGetPatientName::New();
+    cmdPatient->Execute( vtkpxVVLinkConnectorNew::VVLinkServer );
+    const std::string &pat_name = cmdPatient->GetName();
+    const std::string &pat_id   = cmdPatient->GetID();
+
+    if (vtkpxVVLinkConnectorNew::VVLinkPatientName!=NULL)
+      delete [] vtkpxVVLinkConnectorNew::VVLinkPatientName;
+
+    vtkpxVVLinkConnectorNew::VVLinkPatientName=new char[pat_name.length()+pat_id.length()+10];
+    sprintf(vtkpxVVLinkConnectorNew::VVLinkPatientName,"%s.%s",pat_name.c_str(),pat_id.c_str());
+
+
+    // getting all slice sets
+    if ( vtkpxVVLinkConnectorNew::VVLSliceSets != NULL )
+      vtkpxVVLinkConnectorNew::VVLSliceSets->Delete();
+
+    vtkpxVVLinkConnectorNew::VVLSliceSets = vvlink::VVLQGetSliceSets::New();
+    vtkpxVVLinkConnectorNew::VVLSliceSets->SetCoordinateSystem( this->VVLCoordinateSystem );
+    vtkpxVVLinkConnectorNew::VVLSliceSets->Execute( vtkpxVVLinkConnectorNew::VVLinkServer );
+
+
+    int ok=this->UpdateImageList();
+
+    // prepare tracking
+    if ( vtkpxVVLinkConnectorNew::VVLNTrackingData )
+      vtkpxVVLinkConnectorNew::VVLNTrackingData->Delete();
+
+    vtkpxVVLinkConnectorNew::VVLNTrackingData = vvlink::VVLNTrackingData::New();
+    vtkpxVVLinkConnectorNew::VVLNTrackingData->SetCoordinateSystem( this->VVLCoordinateSystem );
+    vtkpxVVLinkConnectorNew::VVLNTrackingData->RegisterOnServer( vtkpxVVLinkConnectorNew::VVLinkServer );
+
+    return 1;
+  }
+  catch ( vvlink::VVLEx &a )
+  {
+
+    if ( vtkpxVVLinkConnectorNew::VVLinkServer )
+      vtkpxVVLinkConnectorNew::VVLinkServer->Delete();
+    vtkpxVVLinkConnectorNew::VVLinkServer = NULL;
+
+    if ( vtkpxVVLinkConnectorNew::VVLNTrackingData )
+      vtkpxVVLinkConnectorNew::VVLNTrackingData->Delete();
+    vtkpxVVLinkConnectorNew::VVLNTrackingData = NULL;
+
+    if ( vtkpxVVLinkConnectorNew::VVLSliceSets )
+      vtkpxVVLinkConnectorNew::VVLSliceSets->Delete();
+    vtkpxVVLinkConnectorNew::VVLSliceSets = NULL;
+
+    //      cerr << "Connection Failed\n";
+    vtkErrorMacro(<<"Connection Failed: " << a.What().c_str() << "\n");
+    return 0;
+  }
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+int vtkpxVVLinkConnectorNew::CloseVVLConnection()
+{
+
+  if (vtkpxVVLinkConnectorNew::VVLinkServer!=NULL)
+	{
+	  if ( vtkpxVVLinkConnectorNew::VVLNTrackingData )
+    {
+      vtkpxVVLinkConnectorNew::VVLNTrackingData->UnregisterFromServer();
+      vtkpxVVLinkConnectorNew::VVLNTrackingData->Delete();
+    }
+	  vtkpxVVLinkConnectorNew::VVLNTrackingData = NULL;
+
+	  if ( vtkpxVVLinkConnectorNew::VVLSliceSets != NULL )
+	    vtkpxVVLinkConnectorNew::VVLSliceSets->Delete();
+	  vtkpxVVLinkConnectorNew::VVLSliceSets = NULL;
+
+	  vtkpxVVLinkConnectorNew::VVLinkServer->Disconnect();
+	  vtkpxVVLinkConnectorNew::VVLinkServer->Delete();
+	  vtkpxVVLinkConnectorNew::VVLinkServer=NULL;
+
+	  if (vtkpxVVLinkConnectorNew::VVLinkImageListNames!=NULL)
+	    delete [] vtkpxVVLinkConnectorNew::VVLinkImageListNames;
+
+	  vtkpxVVLinkConnectorNew::VVLinkImageListNames=NULL;
+	  vtkpxVVLinkConnectorNew::VVLinkNumberOfImages=0;
+
+	  return 1;
+	}
+
+  return 0;
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+int vtkpxVVLinkConnectorNew::UpdateImageList()
+{
+  int length=0;
+
+  if ( vtkpxVVLinkConnectorNew::VVLSliceSets == NULL )
+    return 0;
+
+  for(int i=0; i<vtkpxVVLinkConnectorNew::VVLSliceSets->GetNumberOfSliceSets(); i++ )
+    length += vtkpxVVLinkConnectorNew::VVLSliceSets->GetSliceSet(i)->GetName().length() + 10;
+
+  if (vtkpxVVLinkConnectorNew::VVLinkImageListNames!=NULL)
+    delete [] vtkpxVVLinkConnectorNew::VVLinkImageListNames;
+  vtkpxVVLinkConnectorNew::VVLinkImageListNames=new char[length];
+
+  strcpy(vtkpxVVLinkConnectorNew::VVLinkImageListNames,"");
+
+  vtkpxVVLinkConnectorNew::VVLinkNumberOfImages = vtkpxVVLinkConnectorNew::VVLSliceSets->GetNumberOfSliceSets();
+
+  for(int i=0; i<vtkpxVVLinkConnectorNew::VVLSliceSets->GetNumberOfSliceSets(); i++ )
+    sprintf( vtkpxVVLinkConnectorNew::VVLinkImageListNames, "%s%s,",
+	     vtkpxVVLinkConnectorNew::VVLinkImageListNames, vtkpxVVLinkConnectorNew::VVLSliceSets->GetSliceSet(i)->GetName().c_str());
+
+  return vtkpxVVLinkConnectorNew::VVLSliceSets->GetNumberOfSliceSets();
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+int vtkpxVVLinkConnectorNew::SendViewerToVVLChannel(vtkRenderWindow* renwin)
+{
+  if (vtkpxVVLinkConnectorNew::VVLinkServer==NULL)
+    return 0;
+
+  renwin->Render();
+
+  vtkObjectContainer<vtkWindowToImageFilter> renSrc( vtkWindowToImageFilter::New() );
+  renSrc->SetInput(renwin);
+  renSrc->Update();
+
+	try
+	{
+    std::stringstream channel;
+    channel << "Channel " << VVLinkChannel;
+
+		vtkObjectContainer<vvlink::VVLQSetView> cmd( vvlink::VVLQSetView::New() );
+		cmd->SetChannel( channel.str() );
+		cmd->SetImage( renSrc->GetOutput() );
+		cmd->Execute( vtkpxVVLinkConnectorNew::VVLinkServer );
+	}
+	catch( vvlink::VVLEx &e )
+	{
+		vtkErrorMacro( << e.What().c_str() << "\n" );
+		return 0;
+	}
+
+  return 1;
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+int   vtkpxVVLinkConnectorNew::GetNumberOfVVLinkImages()
+{
+  return vtkpxVVLinkConnectorNew::VVLinkNumberOfImages;
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+char* vtkpxVVLinkConnectorNew::GetVVLinkImageNameList()
+{
+  return vtkpxVVLinkConnectorNew::VVLinkImageListNames;
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+char* vtkpxVVLinkConnectorNew::GetVVLinkPatientName()
+{
+  return vtkpxVVLinkConnectorNew::VVLinkPatientName;
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+int vtkpxVVLinkConnectorNew::GetVVLinkImage(char* imagename,vtkImageData* img,vtkMatrix4x4* matrix,vtkLookupTable* lut)
+{
+  if (vtkpxVVLinkConnectorNew::VVLinkServer==NULL)
+	{
+		vtkErrorMacro(<<"No Connection");
+		return 0;
+	}
+
+	if ( vtkpxVVLinkConnectorNew::VVLSliceSets == NULL )
+	{
+		vtkErrorMacro(<<"connection but no slice set object created yet");
+		return 0;
+	}
+
+  if (img==NULL || matrix==NULL || lut==NULL)
+	{
+		vtkErrorMacro(<<"Pointers must be initilialized prior to GetVVLInkImage");
+		return 0;
+	}
+
+  try
+	{
+		const vvlink::VVLSliceSet *sliceSet = vtkpxVVLinkConnectorNew::VVLSliceSets->GetSliceSet( imagename );
+
+		matrix->DeepCopy( sliceSet->GetOrthogonalTransformation() );
+		img->ShallowCopy( sliceSet->GetOrthogonalVolume() );
+		lut->DeepCopy( sliceSet->GetLookupTable() );
+		return 1;
+	}
+  catch ( vvlink::VVLEx &e )
+	{
+		vtkErrorMacro(<< "Image Download Failed: " << e.What().c_str() );
+		return 0;
+	}
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+int vtkpxVVLinkConnectorNew::GetVVLabeledPoints(vtkPoints* points)
+{
+  if (vtkpxVVLinkConnectorNew::VVLinkServer==NULL)
+	{
+		vtkErrorMacro(<<"No Connection");
+		return 0;
+	}
+
+  if (points==NULL)
+	{
+		vtkErrorMacro(<<"Pointers must be initilialized prior to GetVVLInkImage");
+		return 0;
+	}
+
+  try
+	{
+  	vtkObjectContainer<vvlink::VVLQGetPoints>cmd( vvlink::VVLQGetPoints::New() );
+		cmd->SetCoordinateSystem( this->VVLCoordinateSystem );
+		cmd->SetPointGroup( vvlink::VVLQGetPoints::GROUP_LABELED_POINTS );
+		cmd->Execute( vtkpxVVLinkConnectorNew::VVLinkServer );
+
+		for( int i=0; i<cmd->GetNumberOfPoints(); i++ )
+		{
+			points->InsertNextPoint( cmd->GetPoint(i)->GetPoint() );
+		}
+	}
+  catch ( vvlink::VVLEx &a )
+	{
+		vtkErrorMacro(<<"Point Download Failed: " << a.What().c_str());
+    return 0;
+	}
+
+  return 1;
+}
+//-------
+int vtkpxVVLinkConnectorNew::GetVVNamesOfTrajectories(int numberOfTrajectories)
+{
+	if (vtkpxVVLinkConnectorNew::VVLinkServer==NULL)
+		{
+			vtkErrorMacro(<<"No Connection");
+			return 0;
+		}
+
+	  try
+		{
+			vtkObjectContainer<vvlink::VVLQGetTrajectories>cmd( vvlink::VVLQGetTrajectories::New() );
+
+			cmd->SetCoordinateSystem( this->VVLCoordinateSystem );
+			cmd->SetTrajectoryGroup( vvlink::VVLQGetTrajectories::GROUP_INTRAOP_TRAJECTORY);
+			cmd->Execute( vtkpxVVLinkConnectorNew::VVLinkServer );
+
+			fprintf(stderr, "num traj intraop is %d\n", (int)cmd->GetNumberOfTrajectories()); 
+			int temp = (int)cmd->GetNumberOfTrajectories(); 
+						
+			//for(int i=0;i<numberOfTrajectories; i++)
+			for(int i=0;i<temp; i++)
+			{
+				const char * c = cmd->GetTrajectory(i)->GetName().c_str();
+				fprintf(stderr, "++++++++++++ traj num %d name is %s\n", i, c);
+				
+				const std::wstring s2 = cmd->GetTrajectory(i)->GetNameWide();
+				char *str = new char[255];
+				
+				std::wcout << s2 << std::endl;
+
+				sprintf(str,"%ls",s2.data());
+				fprintf(stderr, "wide name is %s and size is %d\n", str, sizeof(s2)); 
+				std::cout << "test size is " << s2.length() << std::endl ; 
+				
+				 /*for(size_t i = 0, iMax = wcslen(wtext); i < iMax; ++i)
+				   {
+				      std::cout << " " << static_cast<unsigned int>(static_cast<unsigned short>(wtext[i])) ;
+				   }
+				   */
+
+				 std::cout << std::endl << std::endl ;
+			}
+			//int test = cmd->GetNumberOfTrajectories();
+
+			// fprintf(stderr, "+++++++++++++ number of trajectories is %d +++++++++++++++++++ ", test);
+			return 1;
+		}
+	  catch ( vvlink::VVLEx &a )
+		{
+			vtkErrorMacro(<<"Point Download Failed: " << a.What().c_str());
+	    	return 0;
+		}
+
+	  return -1;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+int vtkpxVVLinkConnectorNew::GetVVNumberOfTrajectories()
+{
+	if (vtkpxVVLinkConnectorNew::VVLinkServer==NULL)
+		{
+			vtkErrorMacro(<<"No Connection");
+			return 0;
+		}
+
+	  try
+		{
+	  		//vtkObjectContainer<vvlink::VVLQGetPoints>cmd( vvlink::VVLQGetPoints::New() );
+
+			vtkObjectContainer<vvlink::VVLQGetTrajectories>cmd( vvlink::VVLQGetTrajectories::New() );
+
+			cmd->SetCoordinateSystem( this->VVLCoordinateSystem );
+			//cmd->SetPointGroup( vvlink::VVLQGetPoints::GROUP_LABELED_POINTS );
+			cmd->SetTrajectoryGroup( vvlink::VVLQGetTrajectories::GROUP_TRAJECTORY);
+			cmd->Execute( vtkpxVVLinkConnectorNew::VVLinkServer );
+			int test = cmd->GetNumberOfTrajectories();
+
+			// fprintf(stderr, "+++++++++++++ number of trajectories is %d +++++++++++++++++++ ", test);
+			return test;
+		}
+	  catch ( vvlink::VVLEx &a )
+		{
+			vtkErrorMacro(<<"Point Download Failed: " << a.What().c_str());
+	    return 0;
+		}
+
+	  return -1;
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+int vtkpxVVLinkConnectorNew::GetVVTrajectoryPoints(vtkPoints* points, vtkTransform* xform)
+{
+  if (vtkpxVVLinkConnectorNew::VVLinkServer==NULL)
+	{
+		vtkErrorMacro(<<"No Connection");
+		return 0;
+	}
+
+  if (points==NULL)
+	{
+		vtkErrorMacro(<<"Pointers must be initilialized prior to GetVVLInkImage");
+		return 0;
+	}
+
+  try
+	{
+  		//vtkObjectContainer<vvlink::VVLQGetPoints>cmd( vvlink::VVLQGetPoints::New() );
+
+		vtkObjectContainer<vvlink::VVLQGetTrajectories>cmd( vvlink::VVLQGetTrajectories::New() );
+
+		cmd->SetCoordinateSystem( this->VVLCoordinateSystem );
+		//cmd->SetPointGroup( vvlink::VVLQGetPoints::GROUP_LABELED_POINTS );
+		cmd->SetTrajectoryGroup( vvlink::VVLQGetTrajectories::GROUP_TRAJECTORY);
+		cmd->Execute( vtkpxVVLinkConnectorNew::VVLinkServer );
+
+		//vtkObjectContainer<vvlink::VVLTrajectory>traj( vvlink::VVLTrajectory::New() );
+
+		//traj = cmd->GetTrajectory(0);
+		/*vtkFloatingPointType startpoint[3];
+		cmd->GetTrajectory(0)->GetStartPoint(startpoint);
+
+		vtkFloatingPointType endpoint[3];
+		cmd->GetTrajectory(0)->GetEndPoint(endpoint);*/
+
+		vtkPoints* oldPoints= vtkPoints::New();
+		oldPoints->InsertNextPoint( cmd->GetTrajectory(4)->GetStartPoint() );
+		oldPoints->InsertNextPoint( cmd->GetTrajectory(4)->GetEndPoint() );
+		
+		fprintf(stderr, "get trajectory - number 1 ----- %d \n", (int)cmd->GetNumberOfTrajectories()); 
+
+
+		  //int np=oldPoints->GetNumberOfPoints();
+		  //newPoints->SetNumberOfPoints(np);
+		int np = 2;
+		points->SetNumberOfPoints(np);
+
+		  //  fprintf(stderr,"Obtained np=%d points\n",np);
+
+		  for (int i=0;i<np;i++)
+		    {
+		      double x[3],tx[3];
+		      oldPoints->GetPoint(i,x);
+		      xform->GetLinearInverse()->TransformPoint(x,tx);
+		      points->SetPoint(i,tx);
+		    }
+
+		  //return 1;
+
+
+		//std::cout << traj->GetName();
+
+		//traj->GetStartPoint( point );
+
+		//for( int i=0; i<cmd->GetNumberOfPoints(); i++ )
+		//{
+			//points->InsertNextPoint( cmd->GetPoint(i)->GetPoint() );
+		//}
+	}
+  catch ( vvlink::VVLEx &a )
+	{
+		vtkErrorMacro(<<"Point Download Failed: " << a.What().c_str());
+    return 0;
+	}
+
+  return 1;
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+int vtkpxVVLinkConnectorNew::GetVVLinkImage(char* imagename,vtkImageData* img,vtkTransform* xform,
+                                            vtkLookupTable* lut,int orientation,int sample)
+{
+
+  vtkImageData* img2=vtkImageData::New();
+
+  vtkMatrix4x4* matrix=vtkMatrix4x4::New();
+  int ok=this->GetVVLinkImage(imagename,img2,matrix,lut);
+  if (ok==0)
+	{
+		img2->Delete();
+		return 0;
+	}
+
+  if (sample<1)
+    sample=1;
+  else if (sample>8)
+    sample=8;
+
+  int dim[3];    img2->GetDimensions(dim);
+  double spa[3]; img2->GetSpacing(spa);
+
+  //  fprintf(stderr,"Dimensions =%d %d %d\n",dim[0],dim[1],dim[2]);
+
+  vtkbisImageReslice* resl=vtkbisImageReslice::New();
+
+  int outdim[3];
+  double outspa[3];
+  for (int ia=0;ia<=2;ia++)
+	{
+		outdim[ia]=dim[ia];
+		outspa[ia]=spa[ia];
+		if (outdim[ia]>256)
+		{
+			outdim[ia]=outdim[ia]/sample;
+			outspa[ia]=outspa[ia]*double(sample);
+		}
+	}
+
+  resl->SetOutputExtent(0,outdim[0]-1,
+												0,outdim[1]-1,
+												0,outdim[2]-1);
+  resl->SetOutputOrigin(img2->GetOrigin());
+  resl->SetOutputSpacing(outspa);
+  resl->SetInterpolationModeToNearestNeighbor();
+  resl->SetInput(img2);
+
+
+  vtkMatrix4x4* mat=vtkMatrix4x4::New();
+  mat->Identity();
+  if ( orientation !=0 )
+	{
+		// Coronal or Saggital
+		mat->SetElement(1,1,-1.0);
+		mat->SetElement(1,3,double(dim[1]-1)*spa[1]);
+	}
+  else
+	{
+		// Axial
+		mat->SetElement(2,2,-1.0);
+		mat->SetElement(2,3,double(dim[2]-1)*spa[2]);
+	}
+
+  if (orientation!=2)
+	{
+		// Coronal or Axial Flip Left/Right
+		mat->SetElement(0,0,-1.0);
+		mat->SetElement(0,3,double(dim[0]-1)*spa[0]);
+	}
+
+  vtkMatrix4x4* final=vtkMatrix4x4::New();
+  vtkMatrix4x4::Multiply4x4(matrix,mat,final);
+
+  xform->Identity();
+  xform->Concatenate(final);
+  final->Delete();
+
+  vtkMatrixToLinearTransform* tr=vtkMatrixToLinearTransform::New();
+  tr->SetInput(mat);
+  tr->Update();
+
+  resl->SetResliceTransform(tr);
+  resl->Update();
+
+  img->ShallowCopy(resl->GetOutput());
+  resl->Delete();
+  img2->Delete();
+  tr->Delete();
+
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------
+
+int  vtkpxVVLinkConnectorNew::GetVVLabeledPoints(vtkPoints* newPoints,vtkTransform* xform)
+{
+  if (vtkpxVVLinkConnectorNew::VVLinkServer==NULL)
+	{
+	  vtkErrorMacro(<<"No Connection");
+	  return 0;;
+	}
+
+  if (newPoints==NULL || xform==NULL)
+	{
+	  vtkErrorMacro(<<"Pointers must be initilialized prior to GetVVLabeledPoints");
+	  return 0;
+	}
+
+  vtkPoints* oldPoints= vtkPoints::New();
+  if ( !GetVVLabeledPoints( oldPoints ) )
+    {
+      vtkErrorMacro(<< "Point Download Failed");
+      oldPoints->Delete();
+      return 0;
+    }
+
+  int np=oldPoints->GetNumberOfPoints();
+  newPoints->SetNumberOfPoints(np);
+
+  //  fprintf(stderr,"Obtained np=%d points\n",np);
+
+  for (int i=0;i<np;i++)
+    {
+      double x[3],tx[3];
+      oldPoints->GetPoint(i,x);
+      xform->GetLinearInverse()->TransformPoint(x,tx);
+      newPoints->SetPoint(i,tx);
+    }
+
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------
+int  vtkpxVVLinkConnectorNew::GetVVLinkPointer(vtkPoints* newPoints,vtkTransform* xform)
+{
+  return this->GetVVLinkPointer(newPoints,xform,20.0);
+}
+
+int  vtkpxVVLinkConnectorNew::GetVVLinkPointer(vtkPoints* newPoints,vtkTransform* xform,double length)
+{
+  if (vtkpxVVLinkConnectorNew::VVLinkServer==NULL)
+    {
+      vtkErrorMacro(<<"No Connection");
+      return 0;
+    }
+
+  if (newPoints==NULL || xform==NULL)
+    {
+      vtkErrorMacro(<<"Pointers must be initilialized prior to GetVVLInkPointer");
+      return 0;
+    }
+
+  int index=0;
+
+  if (newPoints->GetNumberOfPoints()!=2)
+    {
+      //      fprintf(stderr,"Setting Points to 2 \n");
+      newPoints->SetNumberOfPoints(2);
+    }
+
+  try
+    {
+      vtkObjectContainer<vvlink::VVLTrackingData> data( vvlink::VVLTrackingData::New() );
+      vtkpxVVLinkConnectorNew::VVLNTrackingData->GetTrackingData( data );
+
+      for( std::list<std::string>::const_iterator itToolNames = this->VVLToolsAndOrder.begin();
+	   itToolNames != this->VVLToolsAndOrder.end();
+         itToolNames++ )
+	{
+	  try
+	    {
+	      const vvlink::VVLInstrument *instr = data->GetInstrument(*itToolNames);
+	      if ( instr->IsValid() )
+		{
+		  double tip[3]; instr->GetTip(tip);
+		  double dir[3]; instr->GetDirection(dir);
+		  newPoints->SetPoint(0, instr->GetTip() );
+		  newPoints->SetPoint(1, instr->GetDirection() );
+		  ++index;
+		  break;
+		}
+	    }
+	  catch( vvlink::VVLNoSuchObjectErrEx & ){} // this tool is not available, just skip
+	}
+    }
+  catch( vvlink::VVLEx &e ) // a real error occured
+    {
+      vtkErrorMacro( << "Error getting tools: " << e.What().c_str() << "\n" );
+      return 0;
+    }
+
+
+  if (index==0)
+    {
+      return 0;
+    }
+
+  double tip[3]; newPoints->GetPoint(0,tip);
+  double dir[3]; newPoints->GetPoint(1,dir);
+  double base[3];
+  for(int i=0;i<3;i++)
+    base[i]=tip[i]-length*dir[i];
+
+  /*  fprintf(stderr,"Get::Getting Points tip=(%.2f,%.2f,%.2f) base=(%.2f,%.2f,%.2f)\n",
+	  tip[0],tip[1],tip[2],
+	  base[0],base[1],base[2]);*/
+
+
+  xform->GetLinearInverse()->TransformPoint(tip,tip);
+  newPoints->SetPoint(0,tip);
+
+  xform->GetLinearInverse()->TransformPoint(base,base);
+  newPoints->SetPoint(1,base);
+
+  /*  fprintf(stderr,"Get::Getting Points Mapped\n\t tip=(%.2f,%.2f,%.2f) \n\t base=(%.2f,%.2f,%.2f)\n",
+	  tip[0],tip[1],tip[2],
+	  base[0],base[1],base[2]);*/
+
+  return 1;
+
+}
+// ---------------------------------------------------------------------------------------------
+//   Get As Poly Data
+// ---------------------------------------------------------------------------------------------
+int  vtkpxVVLinkConnectorNew::GetVVLabeledPointsAsPolyData(vtkPolyData* newdata,vtkTransform* xform)
+{
+  if (vtkpxVVLinkConnectorNew::VVLinkServer==NULL)
+    {
+      vtkErrorMacro(<<"No Connection");
+      return 0;;
+    }
+
+  if (newdata==NULL || xform==NULL)
+    {
+      vtkErrorMacro(<<"Pointers must be initilialized prior to GetVVLabeledPointsAsPolyData");
+      return 0;
+    }
+
+  vtkObjectContainer<vtkPoints> points( vtkPoints::New() );
+  if ( !this->GetVVLabeledPoints( points, xform ) )
+    {
+      vtkErrorMacro(<< "Point Download Failed");
+      return 0;
+    }
+
+  // setting points
+  newdata->SetPoints( points );
+
+  // create corresponding cell array
+  vtkCellArray* verts = vtkCellArray::New();
+  newdata->SetVerts( verts );
+  verts->Delete();
+  for( vtkIdType i=0; i<points->GetNumberOfPoints(); i++ )
+    newdata->GetVerts()->InsertNextCell( 1, &i );
+
+  return 1;
+}
+
+// ---------------------------------------------------------------------------------------------
+int  vtkpxVVLinkConnectorNew::GetVVLinkTrackedToolsAsPolyData(vtkPolyData* newdata,vtkTransform* xform)
+{
+  if (vtkpxVVLinkConnectorNew::VVLinkServer==NULL)
+  {
+    vtkErrorMacro(<<"No Connection");
+    return 0;
+  }
+
+  if (newdata==NULL || xform==NULL)
+  {
+    vtkErrorMacro(<<"Pointers must be initilialized prior to GetVVLInkImage");
+    return 0;
+  }
+
+  vtkObjectContainer<vtkPolyData> polydata( vtkPolyData::New() );
+  // setting points array
+  vtkObjectContainer<vtkPoints> points( vtkPoints::New() );
+  polydata->SetPoints( points );
+
+  // create cell array
+  vtkObjectContainer<vtkCellArray> verts( vtkCellArray::New() );
+  newdata->SetVerts( verts );
+
+  try
+  {
+    vtkObjectContainer<vvlink::VVLTrackingData> data( vvlink::VVLTrackingData::New() );
+    vtkpxVVLinkConnectorNew::VVLNTrackingData->GetTrackingData( data );
+
+    for( int i=0; i<data->GetNumberOfInstruments(); i++ )
+    {
+      const vvlink::VVLInstrument *instr = data->GetInstrument( i );
+      if ( instr->IsValid() )
+	{
+	  vtkIdType pid = points->InsertNextPoint( instr->GetTip() );
+	  verts->InsertNextCell( 1, &pid );
+	}
+    }
+  }
+  catch( vvlink::VVLEx &e ) // a real error occured
+  {
+    vtkErrorMacro( << "Error getting tools: " << e.What().c_str() << "\n" );
+    return 0;
+  }
+
+  vtkTransformPolyDataFilter* polyDataFilter=vtkTransformPolyDataFilter::New();
+  polyDataFilter->SetInput(polydata);
+  polyDataFilter->SetTransform(xform->GetLinearInverse());
+  polyDataFilter->Update();
+
+  newdata->ShallowCopy(polyDataFilter->GetOutput());
+  polyDataFilter->Delete();
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------
+int vtkpxVVLinkConnectorNew::SaveVVLinkLabeledPoints(char* filename,vtkTransform* xform)
+{
+  if (vtkpxVVLinkConnectorNew::VVLinkServer==NULL)
+  {
+    vtkErrorMacro(<<"No Connection");
+    return 0;
+  }
+
+
+  FILE* fout=fopen(filename,"w");
+  if (!fout)
+    return 0;
+
+  try
+  {
+    vtkObjectContainer<vvlink::VVLQGetPatientName> cmdPatient( vvlink::VVLQGetPatientName::New() );
+    cmdPatient->Execute( vtkpxVVLinkConnectorNew::VVLinkServer );
+
+    fprintf(fout, "#VVLinkLabeled Points for Patient %s, ID: %s\n",
+            cmdPatient->GetName().c_str(), cmdPatient->GetID().c_str());
+  }
+  catch( vvlink::VVLCommandExecutionErrEx& ){} // possibly no patient loaded => do nothing
+  catch( vvlink::VVLEx &e )
+  {
+    vtkErrorMacro( << e.What().c_str() << "\n" );
+    fclose(fout);
+    return 0;
+  }
+
+  try
+  {
+    vtkObjectContainer<vvlink::VVLQGetPoints> cmd( vvlink::VVLQGetPoints::New() );
+    cmd->SetCoordinateSystem( this->VVLCoordinateSystem );
+    cmd->SetPointGroup( vvlink::VVLQGetPoints::GROUP_LABELED_POINTS );
+    cmd->Execute( vtkpxVVLinkConnectorNew::VVLinkServer );
+
+    fprintf(fout,"#Total Number Of Labeled Points = %d\n", cmd->GetNumberOfPoints());
+    fprintf(fout,"#Point No \t Location \t\t Color \t\t Label\n");
+    fprintf(fout,"#---------------------------------------------------------------\n");
+
+    for( int i=0; i<cmd->GetNumberOfPoints(); i++ )
+    {
+      double x[3];
+      xform->GetLinearInverse()->TransformPoint( cmd->GetPoint(i)->GetPoint(), x );
+
+      double fcolor[4];
+      cmd->GetPoint(i)->GetColor(fcolor);
+
+      fprintf(fout, "Point %d\t (%.3f,%.3f,%.3f) \t (%.2f,%.2f,%.2f,%.2f) \t %s\n",
+              i+1,
+              x[0],x[1],x[2],
+              fcolor[0],fcolor[1],fcolor[2],fcolor[3],
+              cmd->GetPoint(i)->GetName().c_str() );
+    }
+  }
+  catch ( vvlink::VVLEx &a )
+  {
+    vtkErrorMacro(<<"Point Download Failed: " << a.What().c_str() << "\n");
+    fclose(fout);
+    return 0;
+  }
+
+  fclose(fout);
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------
+int vtkpxVVLinkConnectorNew::SaveVVLinkTrackedTools(char* filename,vtkTransform* xform,char *comment)
+{
+  if (vtkpxVVLinkConnectorNew::VVLinkServer==NULL)
+  {
+    vtkErrorMacro(<<"No Connection");
+    return 0;
+  }
+
+  if (xform==NULL)
+  {
+    vtkErrorMacro(<<"Pointers must be initilialized prior to SaveVVLinkTrackedTools");
+    return 0;
+  }
+
+
+  FILE* fout=fopen(filename,"w");
+  if (!fout)  {  return 0;   }
+
+  try
+  {
+    vtkObjectContainer<vvlink::VVLQGetPatientName> cmdPatient( vvlink::VVLQGetPatientName::New() );
+    cmdPatient->Execute( vtkpxVVLinkConnectorNew::VVLinkServer );
+
+    fprintf(fout, "#VVLinkTrackedTools for Patient %s, ID: %s\n",
+            cmdPatient->GetName().c_str(), cmdPatient->GetID().c_str());
+  }
+  catch( vvlink::VVLCommandExecutionErrEx& ){} // possibly no patient loaded => do nothing
+  catch( vvlink::VVLEx &e )
+  {
+    vtkErrorMacro( << e.What().c_str() << "\n" );
+    fclose(fout);
+    return 0;
+  }
+
+
+  try
+  {
+    vtkObjectContainer<vvlink::VVLTrackingData> data( vvlink::VVLTrackingData::New() );
+    vtkpxVVLinkConnectorNew::VVLNTrackingData->GetTrackingData( data );
+
+    if (comment!=NULL)
+      fprintf(fout,"#%s\n",comment);
+    fprintf(fout,"#Total Number Of Tracked Tools = %d\n", data->GetNumberOfInstruments());
+
+    for( int i=0; i<data->GetNumberOfInstruments(); i++ )
+    {
+      const vvlink::VVLInstrument *instr = data->GetInstrument(i);
+
+      if ( instr->IsValid() )
+	    {
+	      fprintf(fout,"# -------------------------------------------------\n");
+	      fprintf(fout,"Instrument: %s\n", instr->GetName().c_str());
+	      fprintf(fout,"Tip = (%.3f,%.3f,%.3f)\t", instr->GetTip()[0], instr->GetTip()[1], instr->GetTip()[2]);
+	      fprintf(fout,"Direction: (%.3f,%.3f,%.3f)\n", instr->GetDirection()[0], instr->GetDirection()[1], instr->GetDirection()[2]);
+
+	      double totrackertrafo[16];
+	      vtkMatrix4x4::DeepCopy( totrackertrafo, instr->GetTransformation() );
+	      fprintf(fout,"To-tracker transformation matrix:\n");
+	      fprintf(fout,"\t [ %.3f \t %.3f \t %.3f \t %.3f ]\n", totrackertrafo[ 0] ,totrackertrafo[ 1] ,totrackertrafo[ 2] ,totrackertrafo[ 3] );
+	      fprintf(fout,"\t [ %.3f \t %.3f \t %.3f \t %.3f ]\n", totrackertrafo[ 4] ,totrackertrafo[ 5] ,totrackertrafo[ 6] ,totrackertrafo[ 7] );
+	      fprintf(fout,"\t [ %.3f \t %.3f \t %.3f \t %.3f ]\n", totrackertrafo[ 8] ,totrackertrafo[ 9] ,totrackertrafo[10] ,totrackertrafo[11] );
+	      fprintf(fout,"\t [ %.3f \t %.3f \t %.3f \t %.3f ]\n", totrackertrafo[12] ,totrackertrafo[13] ,totrackertrafo[14] ,totrackertrafo[15] );
+	      fprintf(fout,"\n");
+	    }
+    }
+  }
+  catch( vvlink::VVLEx &e )
+  {
+    vtkErrorMacro( << e.What().c_str() << "\n" );
+    fclose(fout);
+    return 0;
+  }
+
+  fclose(fout);
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------
+int  vtkpxVVLinkConnectorNew::GetAndDrawVVLinkPointer(vtkPoints* newPoints,vtkTransform* xform,
+                                                      double length,double radius,double extension,
+                                                      vtkConeSource* source, vtkSphereSource* tipsphere, vtkpxCrossHairSource* tipsphere2)
+{
+  int i;
+
+  int ok=this->GetVVLinkPointer(newPoints,xform,length);
+  if (ok==0)
+    {
+      return 0;
+      /*
+	newPoints->SetNumberOfPoints(2);
+	newPoints->SetPoint(1,119.54, 55.803, 160.745);
+	newPoints->SetPoint(0,119.54, 22.1486, 170.829);*/
+    }
+
+  double base[3],tip[3];
+
+  if (newPoints->GetNumberOfPoints()<2 || source==NULL)
+    {
+      vtkErrorMacro(<<"Failed to Get Pointer Coordinates");
+      return 0;
+    }
+
+  newPoints->GetPoint(0,tip);
+  newPoints->GetPoint(1,base);
+
+  /*  fprintf(stderr,"GetAndDraw::Getting Points tip=(%.2f,%.2f,%.2f) base=(%.2f,%.2f,%.2f)\n",
+	  tip[0],tip[1],tip[2],
+	  base[0],base[1],base[2]);*/
+
+  double n[3],center[3];
+  for (i=0;i<=2;i++)
+    n[i]=tip[i]-base[i];
+  vtkMath::Normalize(n);
+
+  // Make Tip Longer by extension
+  for (int ia=0;ia<=2;ia++)
+    {
+      tip[ia]=tip[ia]+extension*n[ia];
+      base[ia]=base[ia]+extension*n[ia];
+    }
+
+
+  for (i=0;i<=2;i++)
+    center[i]=tip[i]-0.5*length*n[i];
+
+  source->SetHeight(length);
+  source->SetRadius(radius);
+  source->SetCenter(center);
+  source->SetDirection(n);
+  source->CappingOn();
+  source->Update();
+
+  tipsphere->SetCenter(tip);
+  tipsphere->SetRadius(5.0); 
+
+//  vtkCamera *myCamera = vtkCamera::New(); 
+ // myCamera->Get
+
+
+  tipsphere2->SetPosition(tip);
+//  tipsphere2->SetLength(3.0); 
+  tipsphere2->SetThickness(0.3);
+  tipsphere2->SetShowSphere(0); 
+
+
+  newPoints->SetPoint(0,tip);
+  newPoints->SetPoint(1,base);
+
+  return 1;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+int vtkpxVVLinkConnectorNew::ReOrientMatrix(vtkImageData* source,int inputorient,int outputorient,vtkMatrix4x4* tmat,double sp_out[3], int dim_out[3])
+{
+  if (tmat==NULL)
+    return 0;
+
+  if (inputorient<0 || inputorient>2)
+    inputorient=0;
+  if (outputorient<0 || outputorient>2)
+    outputorient=0;
+
+  int   dim[3];  source->GetDimensions(dim);
+  double sp[3];  source->GetSpacing(sp);
+  double ori[3]; source->GetOrigin(ori);
+
+  vtkMatrix4x4* mat=vtkMatrix4x4::New();
+  mat->Identity();
+
+
+
+  if (inputorient==1 && outputorient==0)
+  {
+    // Coronal->Axial
+    mat->SetElement(1, 1, 0); mat->SetElement( 1, 2, -1);
+    mat->SetElement(2, 1, 1); mat->SetElement( 2, 2,  0);
+  }
+
+  if (inputorient==0 && outputorient==1)
+  {
+    // Axial->Coronal
+    mat->SetElement(1, 1,  0); mat->SetElement(1, 2, 1);
+    mat->SetElement(2, 1, -1); mat->SetElement(2, 2, 0);
+  }
+
+  if (inputorient==1 && outputorient==2)
+  {
+    // Coronal->Sagittal
+    mat->SetElement(0, 0, 0) ;  mat->SetElement(1, 0, 0 );  mat->SetElement(2, 0, 1);
+    mat->SetElement(1, 1, -1);
+    mat->SetElement(0, 2, -1 ); mat->SetElement(1, 2, 0 ); mat->SetElement(2, 2, 0);
+  }
+
+  if (inputorient==2 && outputorient==1)
+  {
+    // Sagittal->Coronal
+    mat->SetElement(0, 0, 0) ;  mat->SetElement(0, 1, 0 );  mat->SetElement(0, 2, 1);
+    mat->SetElement(1, 1, -1);
+    mat->SetElement(2, 0, -1 ); mat->SetElement(2, 1, 0 ); mat->SetElement(2, 2, 0);
+  }
+
+
+  if (inputorient==0 && outputorient==2)
+  {
+    // Axial->Sagittal
+    mat->SetElement(0, 0,  0) ;  mat->SetElement(1, 0, 1) ;  mat->SetElement(2, 0, 0);
+    mat->SetElement(0, 1,  0) ;  mat->SetElement(1, 1, 0) ;  mat->SetElement(2, 1, 1);
+    mat->SetElement(0, 2, -1) ;  mat->SetElement(1, 2, 0) ;  mat->SetElement(2, 2, 0);
+  }
+
+  if (inputorient==2 && outputorient==0)
+  {
+    // Sagittal->Axial
+    mat->SetElement(0, 0,  0) ;  mat->SetElement(0, 1, 1) ;  mat->SetElement(0, 2, 0);
+    mat->SetElement(1, 0,  0) ;  mat->SetElement(1, 1, 0) ;  mat->SetElement(1, 2, 1);
+    mat->SetElement(2, 0, -1) ;  mat->SetElement(2, 1, 0) ;  mat->SetElement(2, 2, 0);
+  }
+
+
+  vtkpxVVLinkConnectorNew::ReOrientDimensions(sp,dim,inputorient,outputorient,sp_out,dim_out);
+  float shift_y[3],shift_x[3];
+  for (int i=0;i<=2;i++)
+  {
+    shift_y[i]= 0.5*sp[i]*float(dim[i]-1);
+    shift_x[i]=-0.5*sp_out[i]*float(dim_out[i]-1);
+  }
+
+  vtkTransform* tr=vtkTransform::New();
+  tr->Identity();
+  tr->PostMultiply();
+  tr->Translate(shift_x);
+  tr->Concatenate(mat);
+  tr->Translate(shift_y);
+  tmat->DeepCopy(tr->GetMatrix());
+  tr->Delete();
+
+  return 1;
+}
+//------------------------------------------------------------------------------
+int vtkpxVVLinkConnectorNew::ReOrientDimensions(double sp_in[3],int dim_in[3],int inputorient,int outputorient,
+                                                double sp_out[3],int dim_out[3])
+{
+
+  if (inputorient<0 || inputorient>2)
+    inputorient=0;
+  if (outputorient<0 || outputorient>2)
+    outputorient=0;
+
+
+  if (inputorient==outputorient)
+  {
+    for (int ia=0;ia<=2;ia++)
+    {
+      dim_out[ia]=dim_in[ia];
+      sp_out[ia]=sp_in[ia];
+    }
+  }
+
+  if (inputorient==1 && outputorient==0)
+  {
+    // Coronal->Axial
+    dim_out[0]=dim_in[0]; dim_out[1]=dim_in[2]; dim_out[2]=dim_in[1];
+    sp_out[0]=sp_in[0];   sp_out[1]=sp_in[2];   sp_out[2]=sp_in[1];
+  }
+
+  if (inputorient==0 && outputorient==1)
+  {
+    // Axial->Coronal
+    dim_out[0]=dim_in[0]; dim_out[1]=dim_in[2]; dim_out[2]=dim_in[1];
+    sp_out[0]=sp_in[0];   sp_out[1]=sp_in[2];   sp_out[2]=sp_in[1];
+  }
+
+  if (inputorient==1 && outputorient==2)
+  {
+    // Coronal->Sagittal
+    dim_out[0]=dim_in[2]; dim_out[1]=dim_in[1]; dim_out[2]=dim_in[0];
+    sp_out[0]=sp_in[2];   sp_out[1]=sp_in[1];   sp_out[2]=sp_in[0];
+  }
+
+  if (inputorient==2 && outputorient==1)
+  {
+    // Sagittal->Coronal
+    dim_out[0]=dim_in[2]; dim_out[1]=dim_in[1]; dim_out[2]=dim_in[0];
+    sp_out[0]=sp_in[2];   sp_out[1]=sp_in[1];   sp_out[2]=sp_in[0];
+  }
+
+
+  if (inputorient==0 && outputorient==2)
+  {
+    // Axial->Sagittal
+    dim_out[0]=dim_in[1]; dim_out[1]=dim_in[2]; dim_out[2]=dim_in[0];
+    sp_out[0]=sp_in[1];   sp_out[1]=sp_in[2];   sp_out[2]=sp_in[0];
+  }
+
+  if (inputorient==2 && outputorient==0)
+  {
+    // Sagittal->Axial
+    dim_out[0]=dim_in[2]; dim_out[1]=dim_in[0]; dim_out[2]=dim_in[1];
+    sp_out[0]=sp_in[2];   sp_out[1]=sp_in[0];   sp_out[2]=sp_in[1];
+  }
+
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------
+void LinPrint2(vtkMatrix4x4* matrix,char* name)
+{
+  fprintf(stdout,"\n Printing %s\n",name);
+  for(int i=0;i<=3;i++)
+  {
+    for (int j=0;j<=3;j++)
+      fprintf(stdout,"%7.3f ",matrix->GetElement(i,j));
+    fprintf(stdout,"\n");
+  }
+  return;
+}
+
+
+int vtkpxVVLinkConnectorNew::GetVVLinkImage(char* imagename,vtkImageData* img,vtkTransform* xform,
+                                            vtkLookupTable* lut,int orientation,
+                                            int flipleftright,int flipanteriorposterior,int flipsuperiorinferior,
+                                            int outputorientation,int sample)
+{
+
+  vtkImageData* img2=vtkImageData::New();
+
+  vtkMatrix4x4* matrix=vtkMatrix4x4::New();
+  int ok=this->GetVVLinkImage(imagename,img2,matrix,lut);
+
+  if (ok==0)
+  {
+    img2->Delete();
+    return 0;
+  }
+
+  if (sample<1)
+    sample=1;
+  else if (sample>8)
+    sample=8;
+
+  if (orientation == -1 )
+  {
+    double m1=fabs(matrix->GetElement(1,1));
+    double m2=fabs(matrix->GetElement(1,2));
+    if (m1>m2)
+      orientation=0;
+    else
+      orientation=1;
+    fprintf(stderr,"Auto Orientation Set to %d (%.2f,%.2f)\n",orientation,m1,m2);
+    flipleftright=1;
+    if (orientation==0)
+    {
+      flipanteriorposterior=0;
+      flipsuperiorinferior=1;
+    }
+    else
+    {
+      flipanteriorposterior=1;
+      flipsuperiorinferior=0;
+    }
+  }
+
+
+  if (orientation<0 || orientation>2)
+    orientation=0;
+
+  if (outputorientation< 0 || outputorientation>2)
+    outputorientation=orientation;
+
+  fprintf(stderr,"Parameters = orientations %d -> %d , flips =%d,%d,%d, sample=%d\n",
+          orientation,outputorientation,flipleftright,flipanteriorposterior,flipsuperiorinferior,sample);
+
+  double sp_out[3];int dim_out[3];
+  vtkMatrix4x4* reorient=vtkMatrix4x4::New();
+  vtkpxVVLinkConnectorNew::ReOrientMatrix(img2,orientation,outputorientation,reorient,sp_out,dim_out);
+
+
+  int dim[3];    img2->GetDimensions(dim);
+  double spa[3]; img2->GetSpacing(spa);
+  double ori[3]; img2->GetOrigin(ori);
+
+  fprintf(stderr,"Input Dimensions =%d %d %d, Spacing=%.2f,%.2f,%.2f Origin=%.2f,%.2f,%.2f\n",
+					dim[0],dim[1],dim[2],spa[0],spa[1],spa[2],ori[0],ori[1],ori[2]);
+
+  int doflips[3] = { 0 , 0,0 };
+
+  switch (orientation)
+	{
+	case 0: // Axial
+	  if (flipleftright)
+	    doflips[0]=1;
+	  if (flipanteriorposterior)
+	    doflips[1]=1;
+	  if (flipsuperiorinferior)
+	    doflips[2]=1;
+	  break;
+	case 1: // Coronal
+	  if (flipleftright)
+	    doflips[0]=1;
+	  if (flipanteriorposterior)
+	    doflips[2]=1;
+	  if (flipsuperiorinferior)
+	    doflips[1]=1;
+	  break;
+	case 2: // Sagittal
+	  if (flipleftright)
+	    doflips[2]=1;
+	  if (flipanteriorposterior)
+	    doflips[0]=1;
+	  if (flipsuperiorinferior)
+	    doflips[1]=1;
+	  break;
+	}
+
+  vtkMatrix4x4* flipmat=vtkMatrix4x4::New();
+  flipmat->Identity();
+
+  for (int ia=0;ia<=2;ia++)
+	{
+	  if (doflips[ia]==1)
+    {
+      flipmat->SetElement(ia,ia,-1.0);
+      flipmat->SetElement(ia,3,double(dim[ia]-1)*spa[ia]);
+    }
+	}
+  //  LinPrint2(flipmat,"FlipMat");
+  //  LinPrint2(reorient,"Reorient");
+
+
+  vtkMatrix4x4* mat=vtkMatrix4x4::New();
+  vtkMatrix4x4* final=vtkMatrix4x4::New();
+  vtkMatrix4x4::Multiply4x4(flipmat,reorient,mat);
+
+  //  LinPrint2(mat,"Mat");
+
+  // First The world to image connection
+  vtkMatrix4x4::Multiply4x4(matrix,mat,final);
+
+  //  LinPrint2(final,"Final");
+
+  xform->Identity();
+  xform->Concatenate(final);
+  final->Delete();
+
+  vtkMatrixToLinearTransform* tr=vtkMatrixToLinearTransform::New();
+  tr->SetInput(mat);
+  tr->Update();
+
+  vtkbisImageReslice* resl=vtkbisImageReslice::New();
+  resl->OptimizationOff();
+  resl->SetOutputExtent(0,(dim_out[0])/sample-1,
+                        0,(dim_out[1])/sample-1,
+                        0,(dim_out[2]-1));
+  resl->SetOutputOrigin(img2->GetOrigin());
+  resl->SetOutputSpacing(double(sample)*sp_out[0],double(sample)*sp_out[1],sp_out[2]);
+  resl->SetInterpolationModeToNearestNeighbor();
+  resl->SetInput(img2);
+  resl->SetResliceTransform(tr);
+  resl->Update();
+
+  img->ShallowCopy(resl->GetOutput());
+  resl->Delete();
+  img2->Delete();
+  tr->Delete();
+
+
+  mat->Delete();
+  reorient->Delete();
+  matrix->Delete();
+  flipmat->Delete();
+
+  return 1;
+
+}
+// ---------------------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Common/vtkpxVVLinkConnectorNew.h b/bioimagesuite30_src/Common/vtkpxVVLinkConnectorNew.h
new file mode 100644
index 0000000..6ba6a36
--- /dev/null
+++ b/bioimagesuite30_src/Common/vtkpxVVLinkConnectorNew.h
@@ -0,0 +1,216 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   vtkpxCommon library file
+  Module:    $RCSfile: vtkpxVVLinkConnectorNew.h,v $
+  Language:  C++
+  Date:      $Date: 2007/01/08 $
+  Version:   $Revision: #1 $
+
+
+Copyright (c) 1995-2005 Xenios Papademetris
+xenophon.papademetris at .yale.edu
+All rights reserved.
+
+=========================================================================*/
+// .NAME vtkpxVVLinkConnectorNew - a collection of static utility functions
+// .SECTION Description
+// This class encapsulates the vvlink::VProxy Class and
+// provides functionality for the integration of VectorVisionLink with BioImage Suite
+
+#ifndef __vtkpxVVLinkConnectorNew_h
+#define __vtkpxVVLinkConnectorNew_h
+
+#include "vtkObject.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+#include "vtkTransform.h"
+#include "vtkImageData.h"
+
+
+#include <list>
+#include <string>
+
+class vtkMatrix4x4;
+class vtkPolyData;
+class vtkRenderWindow;
+class vtkConeSource;
+class vtkbisCylinderSource;
+class vtkSphereSource;
+class vtkpxCrossHairSource;
+
+//BTX
+namespace vvlink
+{
+  class VVLConnection;
+  class VVLCoordinateSystem;
+  class VVLQGetSliceSets;
+  class VVLNTrackingData;
+}
+//ETX
+
+class vtkpxVVLinkConnectorNew : public vtkObject
+{
+public:
+  static vtkpxVVLinkConnectorNew *New();
+  vtkTypeMacro(vtkpxVVLinkConnectorNew,vtkObject);
+
+  // Description:
+  // Print Self
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Initialize and Close Connection
+  virtual int   InitializeVVLConnection(char* server,char* password,int channel);
+  virtual int   CloseVVLConnection();
+  virtual int   UpdateImageList();
+
+
+  // Description:
+  // Get Channel that this object wil send images to (using SendViewerToVVLChannel Below)
+  vtkGetMacro(VVLinkChannel,int);
+
+  // Description:
+  // Number of Images on VV Station
+  virtual int   GetNumberOfVVLinkImages();
+
+  // Description:
+  // Comma separated string of all VV Image Names
+  virtual char* GetVVLinkImageNameList();
+  virtual char* GetVVLinkPatientName();
+
+  // Description:
+  // Get Image, Matrix and Lookup Table
+  virtual int   GetVVLinkImage(char* imagename,vtkImageData* img,vtkMatrix4x4* matrix,vtkLookupTable* lut);
+
+  // Description:
+  // Get and Sample/Flip Image Appropriately as well as Transformation and LookupTable
+  // orientation: 0=Axial, 1=Coronal, 2=Sagittal
+  // Axial    (FlipX and FlipZ)
+  // Coronal  (FlipX and FlipY)
+  // Sagittal (FlipY only)
+  //
+  // Sample --> Reduce In-plane resolution   i.e. Sample=2 takes 512x512 and outputs 256x256
+  virtual int   GetVVLinkImage(char* imagename,vtkImageData* img,vtkTransform* xform,vtkLookupTable* lut,int orientation,
+			       int flipleftright,
+			       int flipanteriorposterior,
+			       int flipsuperiorinferior,
+			       int outputorientation,int sample=2);
+  virtual int   GetVVLinkImage(char* imagename,vtkImageData* img,vtkTransform* xform,vtkLookupTable* lut,int orientation,
+			       int sample=2);
+
+  // Description:
+  // Send RGB Image obtained from a vtkRenderWindow to VVLink
+  virtual int   SendViewerToVVLChannel(vtkRenderWindow* renwin);
+
+  // Description:
+  // Labeled Points
+  // Get Labeled Point position and other information (in case of Poly Data)
+  // and map using xform (obtained using VVLinkGetImage i.e. Image->World)
+  virtual int   GetVVLabeledPoints(vtkPoints* points);
+  virtual int   GetVVLabeledPoints(vtkPoints* points,vtkTransform* xform);
+  virtual int   GetVVLabeledPointsAsPolyData(vtkPolyData* surface,vtkTransform* xform);
+
+  //virtual int   GetVVTrajectoryPoints(vtkPoints* points);
+
+  // Description:
+  // Save all information in a text file (filename), points are mapped to image space using xform
+  virtual int   SaveVVLinkLabeledPoints(char* filename,vtkTransform* xform);
+
+
+  // Description:
+  // Get Pointer Position and Orientation
+  // Point 1 = Tool Tip
+  // Point 2 = Tool Base ( Base=Tip-length*Direction direction=pointer orientation)
+  virtual int   GetVVLinkPointer(vtkPoints* newPoints,vtkTransform* xform);
+  virtual int   GetVVLinkPointer(vtkPoints* newPoints,vtkTransform* xform,double length);
+
+  // Description:
+  // Get Pointer and Draw Cone to represent in in scene (in image space coordinates as specified using xform)
+  // length= Cone length
+  // radius= Cone base radius
+  // source= vtkConeSource object to modify
+  virtual int   GetAndDrawVVLinkPointer(vtkPoints* newPoints,vtkTransform* xform,
+					double length,double radius,double extension,
+					vtkConeSource* source, vtkSphereSource* tipsphere, vtkpxCrossHairSource* tipsphere2);
+
+  // Description:
+  // Get All Tracked Tools
+  // Get Labeled Point position and other information and either story in PolyData on in filename
+  virtual int   GetVVLinkTrackedToolsAsPolyData(vtkPolyData* tools,vtkTransform* xform);
+  virtual int   SaveVVLinkTrackedTools(char* filename,vtkTransform* transform,char* comment);
+
+  // Description:
+  // Trajectory Points (start point, end point)
+  // Get Trajectory Points position and other information
+  virtual int GetVVTrajectoryPoints(vtkPoints* points, vtkTransform* xform);
+  virtual int GetVVNumberOfTrajectories();
+  virtual int GetVVNamesOfTrajectories(int numberOfTrajectories); 
+
+protected:
+
+  vtkpxVVLinkConnectorNew();
+  ~vtkpxVVLinkConnectorNew();
+  vtkpxVVLinkConnectorNew(const vtkpxVVLinkConnectorNew&) {};
+  void operator=(const vtkpxVVLinkConnectorNew&) {};
+
+  // Use BTX..ETX to avoid parsing for tcl
+
+  //BTX
+  static vvlink::VVLConnection*        VVLinkServer;
+  int                                  VVLinkChannel;
+  float                                VVLinkVersion;
+
+	vvlink::VVLCoordinateSystem *        VVLCoordinateSystem;
+
+  static char*                         VVLinkPatientName;
+
+	static vvlink::VVLQGetSliceSets *    VVLSliceSets;
+  static char*                         VVLinkImageListNames;
+  static int                           VVLinkNumberOfImages;
+
+	static vvlink::VVLNTrackingData *    VVLNTrackingData;
+
+  static std::list<std::string>        VVLToolsAndOrder;
+  //ETX
+
+  // Image Reorientation Stuff
+  // ------------------------
+  // Description:
+  // Procedures to Re-Orient an Image from Coronal/Axial/Saggital to C/A/S
+  // BTX
+  static int ReOrientMatrix(vtkImageData* source,int inputorient,int outputorient,vtkMatrix4x4* tmat,double sp_out[3],int dim_out[3]);
+  static int ReOrientDimensions(double sp_in[3],int dim_in[3],int inputorient,int outputorient,double sp_out[3],int dim_out[3]);
+  //ETX
+
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Common/znzlib.c b/bioimagesuite30_src/Common/znzlib.c
new file mode 100644
index 0000000..0858e69
--- /dev/null
+++ b/bioimagesuite30_src/Common/znzlib.c
@@ -0,0 +1,309 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/** \file znzlib.c
+    \brief Low level i/o interface to compressed and noncompressed files.
+        Written by Mark Jenkinson, FMRIB
+
+This library provides an interface to both compressed (gzip/zlib) and
+uncompressed (normal) file IO.  The functions are written to have the
+same interface as the standard file IO functions.
+
+To use this library instead of normal file IO, the following changes
+are required:
+ - replace all instances of FILE* with znzFile
+ - change the name of all function calls, replacing the initial character
+   f with the znz  (e.g. fseek becomes znzseek)
+   one exception is rewind() -> znzrewind()
+ - add a third parameter to all calls to znzopen (previously fopen)
+   that specifies whether to use compression (1) or not (0)
+ - use znz_isnull rather than any (pointer == NULL) comparisons in the code
+   for znzfile types (normally done after a return from znzopen)
+ 
+NB: seeks for writable files with compression are quite restricted
+
+ */
+
+/* BioImage Suite Hack*/
+#include "bis_znzlib.h"
+
+/*
+znzlib.c  (zipped or non-zipped library)
+
+*****            This code is released to the public domain.            *****
+
+*****  Author: Mark Jenkinson, FMRIB Centre, University of Oxford       *****
+*****  Date:   September 2004                                           *****
+
+*****  Neither the FMRIB Centre, the University of Oxford, nor any of   *****
+*****  its employees imply any warranty of usefulness of this software  *****
+*****  for any purpose, and do not assume any liability for damages,    *****
+*****  incidental or otherwise, caused by any use of this document.     *****
+
+*/
+
+
+/* Note extra argument (use_compression) where 
+   use_compression==0 is no compression
+   use_compression!=0 uses zlib (gzip) compression
+*/
+
+/* Hack Xenios Papademetris for BioImage Suite (where ZLIB Exists) */
+#define HAVE_ZLIB 1
+/* End of forced definition */
+
+znzFile znzopen(const char *path, const char *mode, int use_compression)
+{
+  znzFile file;
+  file = (znzFile) calloc(1,sizeof(struct znzptr));
+  if( file == NULL ){
+     fprintf(stderr,"** ERROR: znzopen failed to alloc znzptr\n");
+     return NULL;
+  }
+
+  file->nzfptr = NULL;
+
+#ifdef HAVE_ZLIB
+  file->zfptr = NULL;
+
+  if (use_compression) {
+    file->withz = 1;
+    if((file->zfptr = gzopen(path,mode)) == NULL) {
+        free(file);
+        file = NULL;
+    }
+  } else {
+#endif
+
+    file->withz = 0;
+    if((file->nzfptr = fopen(path,mode)) == NULL) {
+      free(file);
+      file = NULL;
+    }
+
+#ifdef HAVE_ZLIB
+  }
+#endif
+
+  return file;
+}
+
+
+znzFile znzdopen(int fd, const char *mode, int use_compression)
+{
+  znzFile file;
+  file = (znzFile) calloc(1,sizeof(struct znzptr));
+  if( file == NULL ){
+     fprintf(stderr,"** ERROR: znzdopen failed to alloc znzptr\n");
+     return NULL;
+  }
+#ifdef HAVE_ZLIB
+  if (use_compression) {
+    file->withz = 1;
+    file->zfptr = gzdopen(fd,mode);
+    file->nzfptr = NULL;
+  } else {
+#endif
+    file->withz = 0;
+#ifdef HAVE_FDOPEN
+    file->nzfptr = fdopen(fd,mode);
+#endif
+#ifdef HAVE_ZLIB
+    file->zfptr = NULL;
+  };
+#endif
+  return file;
+}
+
+
+int Xznzclose(znzFile * file)
+{
+  int retval = 0;
+  if (*file!=NULL) {
+#ifdef HAVE_ZLIB
+    if ((*file)->zfptr!=NULL)  { retval = gzclose((*file)->zfptr); }
+#endif
+    if ((*file)->nzfptr!=NULL) { retval = fclose((*file)->nzfptr); }
+                                                                                
+    free(*file);
+    *file = NULL;
+  }
+  return retval;
+}
+
+
+size_t znzread(void* buf, size_t size, size_t nmemb, znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_ZLIB
+  if (file->zfptr!=NULL) 
+    return (size_t) (gzread(file->zfptr,buf,((int) size)*((int) nmemb)) / size);
+#endif
+  return fread(buf,size,nmemb,file->nzfptr);
+}
+
+size_t znzwrite(const void* buf, size_t size, size_t nmemb, znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_ZLIB
+  if (file->zfptr!=NULL)
+      {
+      /*  NOTE:  We must typecast const away from the buffer because
+          gzwrite does not have complete const specification */
+    return (size_t) ( gzwrite(file->zfptr,(void *)buf,size*nmemb) / size );
+      }
+#endif
+  return fwrite(buf,size,nmemb,file->nzfptr);
+}
+
+long znzseek(znzFile file, long offset, int whence)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_ZLIB
+  if (file->zfptr!=NULL) return (long) gzseek(file->zfptr,offset,whence);
+#endif
+  return fseek(file->nzfptr,offset,whence);
+}
+
+int znzrewind(znzFile stream)
+{
+  if (stream==NULL) { return 0; }
+#ifdef HAVE_ZLIB
+  /* On some systems, gzrewind() fails for uncompressed files.
+     Use gzseek(), instead.               10, May 2005 [rickr]
+
+     if (stream->zfptr!=NULL) return gzrewind(stream->zfptr);
+  */
+
+  if (stream->zfptr!=NULL) return (int)gzseek(stream->zfptr, 0L, SEEK_SET);
+#endif
+  rewind(stream->nzfptr);
+  return 0;
+}
+
+long znztell(znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_ZLIB
+  if (file->zfptr!=NULL) return (long) gztell(file->zfptr);
+#endif
+  return ftell(file->nzfptr);
+}
+
+int znzputs(const char * str, znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_ZLIB
+  if (file->zfptr!=NULL) return gzputs(file->zfptr,str);
+#endif
+  return fputs(str,file->nzfptr);
+}
+
+
+char * znzgets(char* str, int size, znzFile file)
+{
+  if (file==NULL) { return NULL; }
+#ifdef HAVE_ZLIB
+  if (file->zfptr!=NULL) return gzgets(file->zfptr,str,size);
+#endif
+  return fgets(str,size,file->nzfptr);
+}
+
+
+int znzflush(znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_ZLIB
+  if (file->zfptr!=NULL) return gzflush(file->zfptr,Z_SYNC_FLUSH);
+#endif
+  return fflush(file->nzfptr);
+}
+
+
+int znzeof(znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_ZLIB
+  if (file->zfptr!=NULL) return gzeof(file->zfptr);
+#endif
+  return feof(file->nzfptr);
+}
+
+
+int znzputc(int c, znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_ZLIB
+  if (file->zfptr!=NULL) return gzputc(file->zfptr,c);
+#endif
+  return fputc(c,file->nzfptr);
+}
+
+
+int znzgetc(znzFile file)
+{
+  if (file==NULL) { return 0; }
+#ifdef HAVE_ZLIB
+  if (file->zfptr!=NULL) return gzgetc(file->zfptr);
+#endif
+  return fgetc(file->nzfptr);
+}
+
+#if !defined (WIN32)
+int znzprintf(znzFile stream, const char *format, ...)
+{
+  int retval=0;
+  char *tmpstr;
+  va_list va;
+  if (stream==NULL) { return 0; }
+  va_start(va, format);
+#ifdef HAVE_ZLIB
+  if (stream->zfptr!=NULL) {
+    int size;  /* local to HAVE_ZLIB block */
+    size = strlen(format) + 1000000;  /* overkill I hope */
+    tmpstr = (char *)calloc(1, size);
+    if( tmpstr == NULL ){
+       fprintf(stderr,"** ERROR: znzprintf failed to alloc %d bytes\n", size);
+       return retval;
+    }
+    vsprintf(tmpstr,format,va);
+    retval=gzprintf(stream->zfptr,"%s",tmpstr);
+    free(tmpstr);
+  } else 
+#endif
+  {
+   retval=vfprintf(stream->nzfptr,format,va);
+  }
+  va_end(va);
+  return retval;
+}
+
+#endif
+
+
+#undef HAVE_ZLIB 
+
diff --git a/bioimagesuite30_src/CompilingBioImageSuite.html b/bioimagesuite30_src/CompilingBioImageSuite.html
new file mode 100644
index 0000000..710dd06
--- /dev/null
+++ b/bioimagesuite30_src/CompilingBioImageSuite.html
@@ -0,0 +1,212 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+  <title>BioImage Suite Source Code Information</title>
+
+
+</head>
+
+
+<body>
+
+<h1><a name="Installation_Overview"></a>1.
+Overview</h1>
+
+As stated in the <a
+href="http://www.bioimagesuite.org/download/Install_beta.html">3.0beta installation
+page</a>, installing BioImage Suite consists of twp parts.
+<span style="font-weight: bold;"></span>
+<ol>
+
+  <li>Installation of a pre-compiled binary bioimagesuite3_base
+  distribution. This includes: </li>
+
+<ul>
+<LI> The CLapack (v3) numerical library (original
+source=clapack.tgz.gz)</LI>
+<LI> CMake Cross-Platform Build System 2.6.1 (cmake-2.6.1.tar.gz)</LI>
+<LI> GDCM Dicom Library 2.0.10 (gdcm-2.0.10.zip)</LI>
+<LI> The Insight Toolkit v 3.10 (InsightToolkit-3.10.0.zip)</LI>
+<LI> VTK 5.2  (vtk_5.2_src_patched.zip)</LI>
+<LI> MYSQL client libraries (mysql-5.0.51a.tar.gz)</LI>
+<LI> Tcl/Tk 8.4.19 (tcl8.4.19-src.tar.gz/tk8.4.19-src.tar.gz) with the following extensions:
+<UL>
+<LI> Incr Tcl/Incr Tk 3.3 (itcl3.3.tar.gz/itk3.3.tar.gz) and IWidgets
+(iwidgets4.0.1.tar.gz)</LI>
+<LI> Tcllib 1.10 (tcllib-1.10.tar.gz)</LI>
+<LI> Sqlite 3_6_2 (sqlite-3_6_2-tea.tar.gz) </LI>
+<LI> Tile 0.8.2 (tile-0.8.2.tar.gz) </LI>
+<LI> TkCon 2.4 (tkcon-2.4.tar.gz)</LI>
+</UL>
+The original source files for these can be found at <a
+href="http://bioimagesuite.org/download/3.0/prereq/">this location</a>. Use
+the same username/password as for downloading BioImage Suite itself.
+
+All of the Open Source software listed above compiled without
+changes on all platforms.<br> <br>
+
+</UL>
+
+  <li>Installation of the BioImage Suite software package itself.</li>
+
+</ol>
+
+
+BioImage Suite consists of a mixture of C++ libraries and .tcl code.
+ The development process is described in the lecture notes
+from a
+seminar taught by Xenios Papademetris (<a href="http://bioimagesuite.org/vtkbook5/index.html">Introduction
+to Programming
+for Medical Image Analysis with VTK</a>)<br>
+
+<br>
+
+The BioImage Source code is released under the <a href="BioImageSuite_License.txt">GNU General Public License
+(v2).</a>
+<br>
+
+<hr style="width: 100%; height: 2px;">
+<h1><a name="Compiling"></a>2. Compiling
+BioImage Suite</h1>
+
+<h4> Notes </h4>
+
+<p>
+Note that the binary bioimagesuite3_base distribution that comes with
+BioImage Suite is needed for compiling this. While the contents of these are open source,
+it is easier to use the precompiled versions to avoid unnecessary
+troubles. </p>
+
+<p><b> BioImage Suite is an application not a toolkit.
+While we provide the
+source code under the terms of the GPL, support for compiling this is
+limited to this document!</b> A certain familiarity with the UNIX
+operating system and cmake is assumed. 
+
+These instructions are for Linux/Mac OS X and on MS-Windows when using the
+MSYS development environment. If using Visual Studio 2008 see comments in 
+
+<span style="color: red;">red</span> below. Essentially you need to open a
+dos box (cmd.exe) and in steps 2-3 below edit the file setpaths.bat and
+invoke it. </p>
+
+
+<h4><a name="Steps"></a>Steps</h4>
+
+<ol>
+
+  <p></p>
+
+  <li> Place the BioImage Suite source code into a directory we
+will refer to as ${MYSRC}.</li>
+
+  <li>Edit the setpaths.csh or setpaths.sh file to reflect their
+new location. i.e. in setpaths.csh change the line
+    <pre>setenv BASE ${HOME}/src/bioimagesuite<br></pre>
+
+    <p>to something like
+${MYSRC}/bioimagesuite_src/bioimagesuite ... use <b>absolute
+paths</b>. </p>
+
+<span style="color: red;"><p>On MS-Windows if using Visual Studio edit the file setpaths.bat instead.</p></span>
+
+  </li>
+
+  <li> Source the appropriate setpaths file (much like when
+running the software) to set all environment variables i.e.
+    <pre>source ${MYSRC}/bioimagesuite/setpaths.csh </pre>
+
+(or setpaths.sh if using
+one of the sh/ksh/bash shells. or modify setpaths.bat on MS-Windows). <br>
+
+<span style="color: red;"><p>On MS-Windows, if using Visual Studio, execute the file setpaths.bat
+instead.</p></span>
+
+    <br>
+
+  </li>
+
+  <li> <B>Optionally:</B> On Unix-like setups, set the following environment variables</li>
+<UL>
+<LI> CC - this is the C compiler you want to use (if it is not the
+default). For example on Centos 5.x we use CC=gcc34.</LI>
+
+<LI> CXX - this is the C++ compiler you want to use (if it is not the
+default). For example on Centos 5.x we use CC=g++34.</LI>
+
+<LI> CFLAGS - this sets the defaults C options. Often set to either "-fPIC"
+or "-fPIC -m32" (-m32 forces 32 bit compilation on 64-bit machines).
+
+<LI> CXXFLAGS - set identical to CFLAGS.
+</ul>
+
+  <li>Configure the build</li>
+
+  <pre>cd ${MYSRC}/build<br>ccmake ..<br></pre>
+
+On MS-Windows type
+<span style="color: red;"> <pre>cmakesetup ..</pre> instead of ccmake.</span>
+
+  <p>You may also need to specify the positions of vtk, itk etc.
+If you are using the precompiled distributions, this is all taken care
+of for you. If not you will need to specify</p>
+
+
+
+  <li>Compile</li>
+
+    <p>Simply type make </p>
+
+<p><span style="color: red;">On MS-Windows at this point use Visual Studio to build the project BIOIMAGESUITE3.sln.</span></p>
+
+  <li> To run from the source tree build version </li>
+
+    <pre>bis.tcl<br></pre>
+
+    <p>To verify that this is the source build click on the
+"Which"
+button on the bottom the main bis.tcl application. If it says something
+like ${MYSRC}/bioimagesuite then all is good. </p>
+
+  </ul>
+
+</ol>
+
+<hr>
+<h1>Additional Notes</h1>
+
+BioImage Suite is an integrated image analysis software suite developed at
+Yale University. We acknowledge support from the <a
+href="http://www.nibib.nih.gov">National Institutes of Health
+(NIH)/National Institute of Biomedical Imaging and Bioengineering
+(NIBIB)</a> under grant R01 EB006494.  If you are using BioImage Suite for
+a paper please add something like this in the acknowledgment section.
+<pre>Image analysis performed using the BioImage Suite software suite. This
+is supported in part by the NIH-NIBIB under grant R01 EB006494,
+Papademetris, X. (PI).<br></pre>
+
+It will help us keep the project funded. For the reference section use
+something like 
+
+<pre>
+BioImage Suite: An integrated medical image analysis suite.
+ X. Papademetris, M. Jackowski, A. Joshi, D. Scheinost,
+I. Murphy, H Okuda, R.T. Constable and L.H Staib. 
+
+Section of Bioimaging Sciences, Dept. of Diagnostic Radiology, 
+Yale School of Medicine. 
+www.bioimagesuite.org
+</pre>
+
+<hr>
+<br>
+
+<br>
+
+<center>
+<b> For more information see the BioImage Suite web-page <a href="http://www.bioimagesuite.org">
+www.bioimagesuite.org</a></b>
+</center>
+
+</body>
+</html>
diff --git a/bioimagesuite30_src/Connectivity/CMakeLists.txt b/bioimagesuite30_src/Connectivity/CMakeLists.txt
new file mode 100644
index 0000000..1d94967
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/CMakeLists.txt
@@ -0,0 +1,107 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+# test
+SET(KITBASE Connectivity)
+SET(KIT vtkbis${KITBASE})
+
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/${KITBASE})
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Graphics)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Imaging)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Segmentation)
+INCLUDE_DIRECTORIES(${ITK_INCLUDE_DIRS})
+
+
+SET (KITSRCS
+vtkbisImageTimeSeriesNormalize.cpp
+vtkbisImageTemporalSmoothing.cpp
+vtkbisMedianTemporalSmoothing.cpp
+vtkbisRemoveTemporalDrift.cpp
+vtkbisRemoveGlobalTemporalDrift.cpp
+vtkbisRemoveSliceMean.cpp
+vtkbisRemoveVolumeMean.cpp
+vtkbisTimeSeriesMean.cpp
+vtkbisTimeSeriesStat.cpp
+vtkbisTimeSeriesCorrelation.cpp
+vtkbisROIMean.cpp
+vtkbisROIMean_rt.cpp
+vtkbisROICorrelation.cpp
+vtkbisConnectivityUtility.cpp
+vtkbisCsfWmMotionCorrection.cpp
+vtkbisTaskBasedSeedCorrelation.cpp
+vtkbisDisplayROIMean.cpp
+vtkbisIntrinsicConnMap.cpp
+vtkbisIpsilateralConnMap.cpp
+vtkbisDijkstraGraphGeodesicPath.cpp
+vtkbisfmriToolBox.cpp
+vtkbisfmriToolBoxOptimize.cpp
+)
+
+# ----------------------------------------------
+# CUDA Conditional Compilation
+# -----------------------------------------------
+
+
+SET(KITLIBS
+  vtkpxSegmentation
+  vtkpxSegmentationTCL
+  vtkpxCommon
+  vtkpxCommonTCL
+  numerics
+  vtkCommonTCL
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+)
+
+SET(KITJAVALIBS
+  vtkpxCommon
+  vtkpxCommonJava
+  vtkFilteringJava
+  vtkImagingJava
+  numerics
+  ${BIOIMAGESUITE3_COMMON_JAVALIBS}
+)
+
+
+
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+SET (KITTCLSRCS )
+bis_complex("Connectivity" ${KIT} ${FILELIST})
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisConnectivityUtility.cpp b/bioimagesuite30_src/Connectivity/vtkbisConnectivityUtility.cpp
new file mode 100644
index 0000000..d6ea737
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisConnectivityUtility.cpp
@@ -0,0 +1,759 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisConnectivityUtility.cpp
+ *
+ *  Created on: Feb 19, 2009
+ *      Author: Isabella Murphy
+ *      collection of static utility methods
+ *      trunk3
+ */
+#include <vtkbisConnectivityUtility.h>
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkbisImageTimeSeriesNormalize.h"
+#include <fstream>
+#include <cstdlib>
+#include <vector>
+#include <algorithm>
+#include <math.h>
+#include <float.h>
+#include "vtkbisMedianTemporalSmoothing.h"
+#include "vtkpxImageRobustHistogram.h"
+#include "pxisinf.h"
+
+using namespace std;
+
+
+// ---------------------------
+
+vtkbisConnectivityUtility* vtkbisConnectivityUtility::New()
+{
+	// First try to create the object from the vtkObjectFactory
+	vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisConnectivityUtility");
+	if(ret)
+    {
+		return (vtkbisConnectivityUtility*)ret;
+    }
+	// If the factory was unable to create the object, then create it here.
+	return new vtkbisConnectivityUtility;
+}
+
+double vtkbisConnectivityUtility::ComputeRatio(vtkImageData* input, vtkImageData * mask, double threshold)
+{
+	int dim[3];input->GetDimensions(dim);
+	int dimMask[3];
+	int tsum = 0;
+	if (mask!=NULL)
+	{
+		mask->GetDimensions(dimMask);
+		for (int ia=0;ia<=2;ia++)
+				tsum += abs(dim[ia]-dimMask[ia]);
+		if (tsum>0)
+		{
+			fprintf(stderr,"Bad Mask Input to vtkbisIpsilateralConnMap SimpleExecute\n");
+			return -1;
+		}
+	}
+
+	vtkDataArray* temp=input->GetPointData()->GetScalars();
+	int nt=temp->GetNumberOfTuples();//number of voxels
+	int nc=temp->GetNumberOfComponents();//number of frames (time series)
+
+	vtkDataArray* msk = NULL;
+	if (mask!=NULL)
+		msk=mask->GetPointData()->GetScalars();
+
+	double position[3],spacing[3];
+	int lcounter=0;int rcounter=0;
+	input->GetSpacing(spacing);
+	//sort voxel to left or right brain vector
+	for(int t= 0; t < nt; t++)
+	{
+
+		int DoGlm=1;
+		if (mask!=NULL)
+		{
+			if(msk->GetComponent(t,0) < 1)
+					DoGlm=0;
+		}
+		if(DoGlm)
+		{
+			input->GetPoint(t,position);
+			if( position[0]/spacing[0] > (dim[0]-1)/2 )
+			{
+				//std::cout<<"position:"<<position[0]<<"spacing:"<<spacing[0]<<endl;
+				//left brain
+				if(temp->GetComponent(t,0) > threshold)
+					++lcounter;
+				//std::cout<<"t:"<<t<<"lv:"<<temp->GetComponent(t,0)<<"lcounter:"<<lcounter<<endl;
+			}
+			else
+			{
+				//right brain
+				//std::cout<<"position:"<<position[0]<<"spacing:"<<spacing[0]<<endl;
+				if(temp->GetComponent(t,0) > threshold)
+					++rcounter;
+				//std::cout<<"t:"<<t<<"rv:"<<temp->GetComponent(t,0)<<"rcounter:"<<rcounter<<endl;
+			}
+		}
+	}
+	if (lcounter+rcounter > 0.000001)
+	{
+		std::cout<<"lcounter:"<<lcounter<<"rcounter"<<rcounter<<"ratio:"<<(double)(lcounter-rcounter)/(lcounter+rcounter)*100<<endl;
+		return (double)(lcounter-rcounter)/(lcounter+rcounter)*100;
+	}
+	else
+	{
+		fprintf(stderr,"No voxel within threshold\n");
+		return -1;
+	}
+}
+
+void vtkbisConnectivityUtility::ImagetoText(vtkImageData* input, const char* filename)
+{
+	vtkDataArray*  inp=input->GetPointData()->GetScalars();
+	int nt = inp->GetNumberOfTuples();
+	int nc = inp->GetNumberOfComponents();
+
+	if(nt > 400 || nc > 500)
+	{
+		fprintf(stderr, "Too much data to export.");
+		return;
+	}
+	std::ofstream myfile(filename);//output file stream
+	if(!myfile.is_open())
+	{
+		cout<< "Unable to open file"<<filename<<"/n";
+		return;
+	}
+	//loop through the output image file
+	int counter=0;
+	for (int ia = 0; ia<nc; ia++)
+	{
+		for (int ib=0;ib<nt;ib++)
+		{
+			myfile<<inp->GetComponent(counter,0)<< "\t";
+	    	++counter;
+	    }
+	    myfile<<"\n";
+	}
+	myfile.close();
+}
+void vtkbisConnectivityUtility::TexttoImage(const char* filename,vtkImageData* out)
+{
+	std::ifstream infile(filename, ios::in);
+
+	if(!infile.is_open())
+	{
+		cerr<< "Unable to open file"<<filename<<"\n";
+		return;
+	}
+
+	std::vector<float> data;
+	float value=0.0;
+
+	while (!infile.eof())
+	{
+		infile>>value;
+		if(!infile.eof())
+			data.push_back(value);
+	}
+	infile.close();
+	int size = data.size();
+
+	if( (size)%2 > 0 )
+	{
+		cerr<<"not a matrix, error.\n";
+		return;
+	}
+	int dim = (int)sqrt((float)size);
+	out->SetOrigin(0,0,0);
+	out->SetSpacing(1,1,1);
+	out->SetDimensions(dim,dim,1);
+	out->SetScalarTypeToFloat();
+	out->AllocateScalars();
+	vtkDataArray* output = out->GetPointData()->GetScalars();
+	output->FillComponent(0,0.0);
+
+	for (int i=0;i<size;i++)
+	{
+		output->SetComponent(i,0,data[i]);
+	}
+
+}
+
+int vtkbisConnectivityUtility::ExtractImageBlocks(vtkImageData* input, vtkImageData* result, vtkIntArray* frames)
+{
+
+  if (input==NULL || result==NULL  || frames==NULL)
+    {
+      fprintf(stderr,"Bad Inputs to Extract Image Blocks\n");
+      return 0;
+    }
+
+  vtkDataArray* temp = input->GetPointData()->GetScalars();
+  int nframes=temp->GetNumberOfComponents();
+
+  vtkIntArray* markers=vtkIntArray::New();
+  markers->SetNumberOfComponents(2);
+
+  //  fprintf(stderr,"\n\n");
+
+  //output
+  int arraysize = frames->GetNumberOfTuples();
+  int totalframe = 0;
+  for (int i=0; i<arraysize;i++)
+  {
+      int startframe= (int) frames->GetComponent(i,0);
+      int endframe  = (int) frames->GetComponent(i,1);
+      if (startframe<=endframe && endframe>=0)
+      {
+    	  totalframe+=(endframe-startframe)+1;
+    	  double p[2];
+    	  p[0]=startframe;
+    	  p[1]=endframe;
+    	  markers->InsertNextTuple2(p[0],p[1]);
+      }
+  }
+
+  result->CopyStructure(input);
+  result->SetScalarType(input->GetScalarType());
+  result->SetNumberOfScalarComponents(totalframe);
+  result->AllocateScalars();
+
+  //  fprintf(stderr,"Data Type inp=%s, out=%s\n",input->GetScalarTypeAsString(), result->GetScalarTypeAsString());
+
+  vtkDataArray* out=result->GetPointData()->GetScalars();
+  for(int ia=0;ia<totalframe;ia++)
+    out->FillComponent(ia,0);
+
+  //annealing blocks together
+  int comp=0;
+  arraysize=markers->GetNumberOfTuples();
+
+  //  fprintf(stderr,"\n\n");
+
+  for (int j=0;j<arraysize;j++)
+  {
+      int bframe=(int)markers->GetComponent(j,0);
+      int eframe=(int)markers->GetComponent(j,1);
+      if (bframe>=0 && bframe<nframes && eframe>=0 && eframe<nframes)
+      {
+    	  fprintf(stdout,"Using Block %d:%d \n", bframe+1,eframe+1,nframes);
+    	  for(int k=bframe;k<=eframe;k++)
+	    {
+	      out->CopyComponent(comp,temp,k);
+	      ++comp;
+	    }
+      }
+      else
+	{
+    	  fprintf(stderr,"Block %d:%d is not valid, number of frames=%d\n",
+		  bframe+1,eframe+1,nframes);
+	}
+  }
+
+  markers->Delete();
+  return totalframe;
+}
+
+// ---------------------------------------------------------------------------------------------------------
+int vtkbisConnectivityUtility::DiscardImageBlocks(vtkImageData* input, vtkImageData* result, vtkIntArray* frames)
+{
+
+  if (input==NULL || result==NULL  || frames==NULL)
+    {
+      fprintf(stderr,"Bad Inputs to Discard Image Blocks\n");
+      return 0;
+    }
+
+  vtkDataArray* temp = input->GetPointData()->GetScalars();
+  int nframes=temp->GetNumberOfComponents();
+
+  vtkIntArray* markers=vtkIntArray::New();
+  markers->SetNumberOfComponents(2);
+
+  //  fprintf(stderr,"\n\n");
+
+  //output
+  int arraysize = frames->GetNumberOfTuples();
+  int totalframe = 0, startframe=0,endframe=0;
+  for (int i=0; i<=arraysize;i++)
+  {
+      if (i<arraysize)
+    	  endframe   = (int) frames->GetComponent(i,0);
+      else
+    	  endframe=nframes;
+
+      endframe=endframe-1;
+
+       //     fprintf(stderr,"i=%d startframe=%d, endframe=%d\n",i,startframe,endframe);
+
+      if (startframe<=endframe && endframe>=0)
+      {
+    	  totalframe+=(endframe-startframe)+1;
+    	  double p[2];
+    	  p[0]=startframe;
+    	  p[1]=endframe;
+    	  markers->InsertNextTuple2(p[0],p[1]);
+    	//  	  fprintf(stderr,"Creating Pair %.0f:%.0f \t\t totalframe=%d\n",p[0],p[1],totalframe);
+      }
+
+      if (i<arraysize)
+    	  startframe = (int) frames->GetComponent(i,1)+1;
+
+      //      fprintf(stderr,"done i=%d startframe=%d, endframe=%d\n",i,startframe,endframe);
+  }
+
+  result->CopyStructure(input);
+  result->SetScalarType(input->GetScalarType());
+  result->SetNumberOfScalarComponents(totalframe);
+  result->AllocateScalars();
+
+  //  fprintf(stderr,"Data Type inp=%s, out=%s\n",input->GetScalarTypeAsString(), result->GetScalarTypeAsString());
+
+  vtkDataArray* out=result->GetPointData()->GetScalars();
+  for(int ia=0;ia<totalframe;ia++)
+    out->FillComponent(ia,0);
+
+  //annealing blocks together
+  int comp=0;
+  arraysize=markers->GetNumberOfTuples();
+
+  //  fprintf(stderr,"\n\n");
+
+  for (int j=0;j<arraysize;j++)
+  {
+      int bframe=(int)markers->GetComponent(j,0);
+      int eframe=(int)markers->GetComponent(j,1);
+      if (bframe>=0 && bframe<nframes && eframe>=0 && eframe<nframes)
+      {
+    	  fprintf(stdout,"Using Block %d:%d \n", bframe+1,eframe+1,nframes);
+    	  for(int k=bframe;k<=eframe;k++)
+    	  {
+    		  out->CopyComponent(comp,temp,k);
+    		  ++comp;
+    	  }
+      }
+      else
+      {
+    	  fprintf(stderr,"Block %d:%d is not valid, number of frames=%d\n",
+    			  bframe+1,eframe+1,nframes);
+      }
+  }
+
+  markers->Delete();
+  return totalframe;
+}
+/*!---------------------------------------------------------------------------------------------------------------------------
+*  Histogram fitting from Michele
+*@param[in]zmap: input 3D image data type has to be z number (after calculating correlation, do fisher r-to-z transform to obtain this z number)
+*@param[out]output:output image
+*/
+// ---------------------------------------------------------------------------------------------------------
+
+void vtkbisConnectivityUtility::Ztransform(vtkImageData* zmap, vtkImageData* output)
+{
+
+	vtkDataArray* inp2=zmap->GetPointData()->GetScalars();
+	int nt2=inp2->GetNumberOfTuples();//number of voxels
+	int nc2=inp2->GetNumberOfComponents();
+
+	output->SetDimensions(zmap->GetDimensions());
+	output->SetSpacing(zmap->GetSpacing());
+	output->SetOrigin(zmap->GetOrigin());
+	output->SetNumberOfScalarComponents(zmap->GetNumberOfScalarComponents());
+	output->SetScalarTypeToDouble();
+	output->AllocateScalars();//allocation space on memery
+	for (int ia=0;ia<nc2;ia++)
+		output->GetPointData()->GetScalars()->FillComponent(ia,0.0);
+	vtkDataArray* out=output->GetPointData()->GetScalars();
+
+
+	vtkbisMedianTemporalSmoothing* smooth=vtkbisMedianTemporalSmoothing::New();
+	vector<float> mean;
+	vector<float> sigma;
+
+
+
+	for(int i = 0; i < nc2;i++)
+	{
+		vtkpxImageRobustHistogram* histo = vtkpxImageRobustHistogram::New();
+		histo->SetInput(zmap);
+		histo->SetPlainHistogram();
+		histo->SetFrame(i);
+		histo->SetNumberOfBins(1024);
+		histo->Update();
+		/*if(i==0)
+			histo->SaveGnuplot("test0.txt");
+		else if(i==1)
+			histo->SaveGnuplot("test1.txt");
+		else if(i==2)
+			histo->SaveGnuplot("test2.txt");
+		else if(i==3)
+			histo->SaveGnuplot("test3.txt");*/
+
+		smooth->SetRadius(3);
+		smooth->SetInput(histo->GetOutput());
+		smooth->Update();
+		histo->Delete();
+
+		vtkDataArray* inp=smooth->GetOutput()->GetPointData()->GetScalars();
+		int nt=inp->GetNumberOfTuples();//number of voxels
+		//for(int his=0;his<nt;his++)
+			//std::cout<<inp->GetComponent(his,0)<<"|";
+		double range[2];
+		inp->GetRange(range);
+		int max = (int)(range[1]);
+		float half = float(max)*0.5;
+		int maxbucket =0;
+		int leftbucket = 0;
+		int j=0;int k=0;
+		for(int l=0; l<nt;l++)
+		{
+			if(inp->GetComponent(l,0) == max)
+			{
+				maxbucket = l;
+				//std::cout<<"# in maxbucket:"<<inp->GetComponent(l,0)<<endl;
+			}
+
+		}
+		for(j=0;j<maxbucket;j++)
+		{
+			if(inp->GetComponent(j,0) <= half)
+			{
+				leftbucket = j;
+			}
+		}
+		int rightbucket = maxbucket+1;
+		for (k = maxbucket+1;k<nt;k++)
+		{
+			if(inp->GetComponent(k,0) >= half)
+				rightbucket = k;
+		}
+		//compute sigma
+		double  sp[3]; smooth->GetOutput()->GetSpacing(sp);
+		double ori[3]; smooth->GetOutput()->GetOrigin(ori);
+		double x10=double(leftbucket)*sp[0]+ori[0];
+		double x11=double(leftbucket+1.0)*sp[0]+ori[0];
+		double x20=double(rightbucket)*sp[0]+ori[0];
+		double x21=double(rightbucket+1.0)*sp[0]+ori[0];
+		double x1 = (x11-x10)*0.5+x10;
+		double x2 = (x21-x20)*0.5+x20;
+		float diff = fabs(float(x2-x1));
+		float dsigma = diff/(2.0*sqrt(2.0*log(2.0)));
+		if (dsigma<0.00001)
+				dsigma=1.0;
+		if (isnan(dsigma) || isinf(dsigma))
+				dsigma=1.0;
+		sigma.push_back(dsigma);
+		//std::cout<<"difference:"<<diff<<"denominator:"<<2*sqrt(2*log(2))<<"sigma1:"<<sigma<<endl;
+		//compute mean
+		float sum = 0;
+		int counter = 0;
+
+		for(int m =0; m<nt2;m++)
+		{
+			if(inp2->GetComponent(m,0) > x1 && inp2->GetComponent(m,0) < x2)
+			{
+				sum+=inp2->GetComponent(m,0);
+				//std::cout<<";"<<inp2->GetComponent(l,0);
+				++counter;
+			}
+		}
+		if(counter < 1)
+			counter = 1;
+		float dmean = sum/counter;
+		if (isnan(dmean) || isinf(dmean))
+				dmean=0.0;
+		mean.push_back(dmean);
+		//do z-mean/sigma on every value in zmap
+
+
+		std::cout<<"max:"<<max<<"maxbucket:"<<maxbucket<<"leftbucket:"<<leftbucket<<"rightbucket:"<<rightbucket<<"x1:"<<x1<<"x2:"<<x2<<"sigma:"<<dsigma<<"mean:"<<dmean<<endl;
+
+	}
+
+
+
+	for(int m=0;m<nt2;m++)
+	{
+		for(int n=0;n<nc2;n++)
+			out->SetComponent(m,n,(inp2->GetComponent(m,n)-mean[n])/sigma[n]);
+	}
+
+	smooth->Delete();
+
+}
+/*!---------------------------------------------------------------------------------------------------------------------------
+*  Text file to matrix. This is written to read fmri motion file.
+*@param[in]filename: input text file with a 2D matrix with 6 columns
+*@param[out]output:output vtkpxMatrix object
+*/
+// ---------------------------------------------------------------------------------------------------------
+int vtkbisConnectivityUtility::TexttoMarix6Cols(const char* filename, vtkpxMatrix* outmatrix)
+{
+	const int cols=6;
+
+	std::ifstream infile(filename, ios::in);
+
+	if(!infile.is_open())
+	{
+		cerr<< "Unable to open file"<<filename<<"\n";
+		return 0;
+	}
+
+	std::vector<float> data;
+	float value=0.0;
+
+	while (!infile.eof())
+	{
+		infile>>value;
+		if(!infile.eof())
+			data.push_back(value);
+	}
+	infile.close();
+	int size = data.size();
+
+	if( (size)%cols > 0 )
+	{
+		cerr<<"not a matrix, error.\n";
+		return 0;
+	}
+	int rows=0;
+	rows = size/6;
+
+	outmatrix->Zeros(rows,cols);
+	int i=0;
+	for(int r=0;r<rows;r++)
+	{
+		for(int c=0;c<cols;c++)
+		{
+			outmatrix->SetDirectElement(r,c,data[i]);
+			++i;
+		}
+	}
+	//outmatrix->Print();
+	return rows;
+
+
+}
+void vtkbisConnectivityUtility::ROCCurve(vtkImageData* mask, vtkImageData* groundtruth, vtkImageData* segmentedimage, int steps, vtkDoubleArray* output, const char* Filename)
+{
+	if (groundtruth == NULL)
+	{
+		cout<<"bad input to ROC Curve, no ground truth image."<<endl;
+		return;
+	}
+	if (segmentedimage == NULL)
+	{
+		cout<<"bad input to ROC Curve, no segmented image."<<endl;
+	    return;
+	}
+	int dim1[3]; groundtruth->GetDimensions(dim1);
+	int dim2[3]; segmentedimage->GetDimensions(dim2);
+	int sum=0;
+	for (int ia=0;ia<=2;ia++)
+		sum+=abs(dim1[ia]-dim2[ia]);
+	if (sum>0)
+	{
+		fprintf(stderr,"Error: ground truth and segmented image do not have the same dimension. \n");
+		return;
+	}
+	if (mask!=NULL)
+	{
+		int dim3[3]; mask->GetDimensions(dim3);
+	    int sum=0;
+	    for (int ia=0;ia<=2;ia++)
+	    	sum+=abs(dim3[ia]-dim2[ia]);
+	    if (sum>0)
+		{
+	    	fprintf(stderr,"Bad Mask Input to ROC Curve \n");
+		    return;
+		}
+	}
+
+	vtkDataArray* msk=NULL;
+	if (mask!=NULL)
+	msk=mask->GetPointData()->GetScalars();
+	vtkDataArray* grd=groundtruth->GetPointData()->GetScalars();
+	vtkDataArray* seg=segmentedimage->GetPointData()->GetScalars();
+	int nt=seg->GetNumberOfTuples();//number of voxels
+	output->SetNumberOfComponents(3);
+	output->SetNumberOfTuples(steps+1);
+
+
+	double range[2];
+	seg->GetRange(range);
+	double min=range[0];
+	double max=range[1];
+	double addvalue=(max-min)/steps;
+	std::cout<<"region min:"<<range[0]<<"region max:"<<range[1]<<endl;
+
+	int step=0;
+	for(double t=min;t<=max;t=t+addvalue)
+	{
+		int TP=0;
+		int FP=0;
+		int TN=0;
+		int FN=0;
+		for(int i=0;i<nt;i++)
+		{
+			int doAlg=1;
+			if (msk!=NULL)
+			{
+				if (msk->GetComponent(i,0)<1)
+					doAlg=0;
+			}
+			if (doAlg)
+			{
+				if(seg->GetComponent(i,0)>=t)
+				{
+					if(grd->GetComponent(i,0)>0)
+					{
+						++TP;
+					}else{
+						++FP;
+					}
+				}else{
+					if(grd->GetComponent(i,0)>0)
+					{
+						++FN;
+					}else{
+						++TN;
+					}
+				}
+			}
+		}
+		double sensitivity = (double)TP/(TP+FN);
+		if (TP<0.00001 || (TP+FN)<1)
+			sensitivity=0.0;
+
+		double oneminusspecificity = (double)FP/(TN+FP);
+		if (FP<0.00001 || (TN+FP)<1)
+			oneminusspecificity=0.0;
+		output->SetComponent(step,0,t);
+		output->SetComponent(step,1,sensitivity);
+		output->SetComponent(step,2,oneminusspecificity);
+		cout<<"TP:"<<TP<<"TN"<<TN<<"FP:"<<FP<<"FN:"<<FN<<"Sen:"<<sensitivity<<"1-Spc:"<<oneminusspecificity<<"\n";
+		++step;
+
+	}
+	/*for(int i=0;i<steps;i++)
+		{
+		cout<<output->GetComponent(i,0)<<"\t"<<output->GetComponent(i,1)<<"\t"<<output->GetComponent(i,2)<<"\n";
+
+		}*/
+	std::ofstream myfile(Filename);
+
+	if(!myfile.is_open())
+	{
+	     cout<< "Unable to open file"<<Filename<<"/n";
+	     return;
+	}
+	myfile<<"Step \t TP \t FP \n ";
+	for(int i=0;i<steps;i++)
+	{
+
+		myfile<<output->GetComponent(i,0)<<"\t"<<output->GetComponent(i,1)<<"\t"<<output->GetComponent(i,2)<<"\n";
+	}
+
+	myfile.close();
+}
+/*!---------------------------------------------------------------------------------------------------------------------------
+*  Take matrix from validateblockdefinition with task and blocks information, return a 1 D array of blocks of one task
+*@param[in]matrix: the matrix with task information. For example, if frame 2 is doing task 3, on (2,3) will be 1
+*@param[in]column: which column (task) we want to extract block information now
+*@param[in]numrows: total number of rows of the matrix(frames)
+*@param[out]output:output a 1D array with list of blocks, its beginning and ending frame.
+*For example: 025688 means block one from frame 0 to frame 2;block 2 from frame 5 to frame 6;block 3 from frame 8 to frame 8.
+*/
+// ---------------------------------------------------------------------------------------------------------
+int vtkbisConnectivityUtility::SplitBlocks(vtkpxMatrix* matrix , int column, int numrows, vtkIntArray* output)
+{
+	int pre=0;int numblocks=0;
+	for (int r=0;r<numrows;r++)
+	{
+
+		if ( matrix->GetDirectElement(r,column) != pre)
+		{
+			if(pre==0)
+			{
+				pre=1;
+				output->InsertNextTuple1(r);
+				++numblocks;
+			}else{
+				pre=0;
+				output->InsertNextTuple1(r-1);
+
+			}
+		}
+	}
+	if (output->GetNumberOfTuples()%2 != 0)
+	{
+		output->InsertNextTuple1(numrows-1);
+	}
+	std::cout<<"Beginning and ending frame of each block:"<<endl;
+	for(int j=0;j<output->GetNumberOfTuples();j++)
+	{
+		std::cout<<output->GetTuple1(j)<<endl;
+	}
+
+	return numblocks;
+}
+/*
+ * function h=vasicekExact(v,m)
+>
+> len=length(v);
+>
+> orderStats=sort(v);
+>
+>
+>
+> % Note that the intervals overlap for this estimator.
+>
+> intvals=orderStats(m+1:len)-orderStats(1:len-m);
+>
+> hvec=log(intvals);
+>
+> h=sum(hvec);
+>
+> %h=h/(len-m)+log((len+1)/m);     % Simpler version. See Learned-Miller
+> et al.
+>
+> h=h/(len-m)+log(len+1)-psi(m);   % With partial bias correction? See
+> Beirlant et al
+ */
+void vtkbisConnectivityUtility::VasicekExact(double* v,int len,int m)
+{
+	std::sort(v,v+len);
+
+
+}
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisConnectivityUtility.h b/bioimagesuite30_src/Connectivity/vtkbisConnectivityUtility.h
new file mode 100644
index 0000000..09b6c97
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisConnectivityUtility.h
@@ -0,0 +1,77 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisConnectivityUtility.h
+ *
+ *  Created on: Feb 19, 2009
+ *      Author: Isabella Murphy
+ *      trunk3
+ */
+
+#ifndef VTKBISCONNECTIVITYUTILITY_H_
+#define VTKBISCONNECTIVITYUTILITY_H_
+
+#include "vtkObject.h"
+#include "vtkImageData.h"
+#include "vtkIntArray.h"
+#include "vtkpxMatrix.h"
+#include "vtkpxImageRobustHistogram.h"
+#include "vtkFloatArray.h"
+#include "vtkDoubleArray.h"
+
+
+class vtkbisConnectivityUtility : public vtkObject{
+public:
+  vtkTypeMacro(vtkbisConnectivityUtility,vtkObject);
+  static vtkbisConnectivityUtility *New();
+
+  //static functions
+  static double ComputeRatio(vtkImageData* input, vtkImageData* mask, double threshold);
+  static void ImagetoText(vtkImageData* input, const char *filename);
+  static void TexttoImage(const char* filename,vtkImageData* out);
+  static int TexttoMarix6Cols(const char* filename, vtkpxMatrix* outmatrix);
+  static int SplitBlocks(vtkpxMatrix* matrix , int column, int numrows, vtkIntArray* output);
+  static void VasicekExact(double* v,int len,int m);
+
+  // Descripition:
+  // Input is input
+  // Output is result
+  // Frames is a two-component array where each tuple is a block with limits in component0:component1 (inclusive)
+  static int ExtractImageBlocks(vtkImageData* input, vtkImageData* result, vtkIntArray* frames);
+
+  // Eliminate frames from image
+  static int DiscardImageBlocks(vtkImageData* input, vtkImageData* result, vtkIntArray* frames);
+
+  // Other stuff
+  static void Ztransform(vtkImageData* zmap, vtkImageData* output);
+  static void ROCCurve(vtkImageData* mask, vtkImageData* groundtruth, vtkImageData* segmentedimage, int steps, vtkDoubleArray* output,const char* Filename);
+
+};
+
+#endif /* VTKBISCONNECTIVITYUTILITY_H_ */
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisCsfWmMotionCorrection.cpp b/bioimagesuite30_src/Connectivity/vtkbisCsfWmMotionCorrection.cpp
new file mode 100644
index 0000000..ac5c31c
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisCsfWmMotionCorrection.cpp
@@ -0,0 +1,351 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisCsfWmMotionCorrection.cpp
+ *
+ *  Created on: May 29, 2009
+ *      Author: Isabella Murphy, Xilin Shen
+ *      calculate the mean of csh and white matter, construct a matrix [ csf_mean white matter_mean motion1 motion2 motion3 motion4 motion5 motion6 ]
+ *      Define mask 0=background, 1=csf, 2=white matter, 3=grey matter
+ */
+
+#include <vtkbisCsfWmMotionCorrection.h>
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vnl/vnl_matrix.h"
+#include "vnl/algo/vnl_matrix_inverse.h"
+
+
+
+using namespace std;
+
+// This creates the "New" Function
+vtkStandardNewMacro(vtkbisCsfWmMotionCorrection);
+
+vtkbisCsfWmMotionCorrection::vtkbisCsfWmMotionCorrection()
+{
+  this->ImageMask=NULL;
+  this->MotionMatrix=vtkpxMatrix::New();
+  this->LSQ=vtkpxMatrix::New();
+
+}
+vtkbisCsfWmMotionCorrection::~vtkbisCsfWmMotionCorrection()
+{
+  this->SetImageMask(NULL);
+  this->MotionMatrix->Delete();
+  this->LSQ->Delete();
+
+}
+void vtkbisCsfWmMotionCorrection::SetFileName(const char* filename)
+{
+  this->FileName=filename;
+}
+
+const char* vtkbisCsfWmMotionCorrection::GetFileName()
+{
+  return this->FileName.c_str();
+}
+//----------------------------------------------------------------------------------------------------------------------
+//RequestInformation
+//I. make sure output image data type is float
+// ---------------------------------------------------------------------------------------------------------------------------
+int vtkbisCsfWmMotionCorrection::RequestInformation (vtkInformation * request,
+						vtkInformationVector ** inputVector,
+						vtkInformationVector * outputVector)
+{
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);//set output datatype to float
+
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+/*
+  Problem =  A x = B  where X is unknown
+
+ First premultiply by A':  A'A x = A'B
+ Solution x = (A'A)^{-1}.A'.B
+
+  LSQ = (A'A)^{-1}.A'
+*/
+// ---------------------------------------------------------------------------------------------------------------------------
+
+void vtkbisCsfWmMotionCorrection::ComputeLSQMatrix(vtkpxMatrix* A, vtkpxMatrix* LSQ)
+{
+  int sz[2]; A->GetSize(sz);
+  vnl_matrix<double> M(sz[0],sz[1]);
+  for (unsigned i=0; i<M.rows(); ++i)
+    for (unsigned j=0; j<M.cols(); ++j)
+      M(i,j)=A->GetDirectElement(i,j);
+
+
+  vnl_matrix<double> Mt=M.transpose();
+  vnl_matrix<double> MtM=Mt*M;
+  vnl_matrix<double> IN=vnl_matrix_inverse<double>(MtM);
+  vnl_matrix<double> F=IN*Mt;
+
+  LSQ->Zeros(F.rows(), F.cols());
+  for (unsigned i=0; i<F.rows(); ++i)
+    for (unsigned j=0; j<F.cols(); ++j)
+      LSQ->SetDirectElement(i,j,F(i,j));
+}
+/*
+ * EliminateError: subtract error from original data
+ *@param[in]inp: original input data
+ *@param[in]index: which voxel we are working at
+ *@param[in]numframes: how many frames
+ *@param[in]LSQ: LSQ matrix calculated earlier
+ *@param[in]A:8 column big matrix with csf mean, wm mean and 6 columns of motion information
+ *@param[out]out: write to output image directly
+ */
+void vtkbisCsfWmMotionCorrection::EliminateError(vtkDataArray* inp,vtkDataArray* out,int index,
+						    int numframes,
+						    vtkpxMatrix* LSQ,
+						    vtkpxMatrix* A)
+{
+/*	//Store original value of each frame of voxel "index" into B matrix
+	for (int i=0;i<numframes;i++)
+	  this->B->SetDirectElement(i,0,inp->GetComponent(index,i));
+
+	//X = LSQ*B
+	vtkpxMatrix::Multiply(LSQ,this->B,this->X);
+
+	//AX = A*X
+	vtkpxMatrix::Multiply(A,this->X,this->AX);
+
+	//for every frame, subtract AX
+	for (int ia=0;ia<numframes;ia++)
+	{
+		out->SetComponent(index,ia,this->B->GetDirectElement(ia,0)-this->AX->GetDirectElement(ia,0));
+			//std::cout<<"NV:"<<out->GetComponent(index,ia)<<"="<<B->GetDirectElement(ia,0)<<"-"<<AX->GetDirectElement(ia,0)<<"|";
+	}
+*/
+
+  vnl_matrix<double> mB(numframes,1);
+  for(int i=0;i<numframes;i++)
+    mB(i,0)=inp->GetComponent(index,i);
+
+
+  int sz[2]; LSQ->GetSize(sz);
+  vnl_matrix<double> mLSQ(sz[0],sz[1]);
+  for (unsigned i=0; i<mLSQ.rows(); ++i)
+    for (unsigned j=0; j<mLSQ.cols(); ++j)
+      mLSQ(i,j)=LSQ->GetDirectElement(i,j);
+
+  int szA[2]; A->GetSize(szA);
+  vnl_matrix<double> mA(szA[0],szA[1]);
+  for (unsigned i=0; i<mA.rows(); ++i)
+    for (unsigned j=0; j<mA.cols(); ++j)
+      mA(i,j)=A->GetDirectElement(i,j);
+
+  vnl_matrix<double> mX=mLSQ*mB;
+  vnl_matrix<double> mAX=mA*mX;
+  //std::cout<<"I am in eliminateError"<<endl;
+  //for (unsigned i=0; i<mAX.rows(); ++i)
+  //for (unsigned j=0; j<mAX.cols(); ++j)
+  //this->AX->SetDirectElement(i,j,mAX(i,j));
+  for (int ia=0;ia<numframes;ia++)
+    {
+      out->SetComponent(index,ia,mB(ia,0)-mAX(ia,0));
+      //std::cout<<"NV:"<<out->GetComponent(index,ia)<<"="<<B->GetDirectElement(ia,0)<<"-"<<AX->GetDirectElement(ia,0)<<"|";
+    }
+
+}
+/*
+ * MotionErrorCorr: correct motion error
+ *@param[in]numoftuples: number of tuples in the image
+ *@param[in]numofframes: number of frames in the image
+ *@param[in]inp: input vtkDataArray
+ *@param[in]msk: mask vtkDataArray
+ *@param[out]out: write to output image directly
+ */
+void vtkbisCsfWmMotionCorrection::MotionErrorCorr(int numoftuples,int numofframes,vtkDataArray* inp,vtkDataArray* out,vtkDataArray* msk)
+{
+  int nt=numoftuples;
+  int nc=numofframes;
+  vtkpxMatrix* A = vtkpxMatrix::New();
+  A->ImportFromMatlab(this->FileName.c_str(),"Q_ser");
+
+  this->ComputeLSQMatrix(A,this->LSQ);
+
+  int maxcount=int(nt/10);
+  int count=0;
+  double pog=0.0;
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      int dooperation=1;
+      if (msk!=NULL)
+	{
+	  if (msk->GetComponent(voxel,0) <1)
+	    dooperation=0;
+	}
+
+      if (dooperation)
+	{
+	  this->EliminateError(inp,out,voxel,nc,LSQ,A);
+	}
+
+      ++count;
+      if (count==maxcount)
+	{
+	  pog=double(voxel)/double(nt);
+	  this->UpdateProgress(pog);
+	  count=0;
+	  //fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,double(numdone)/double(nt));
+	}
+    }
+  A->Delete();
+}
+/*
+ * CSFWMErrorCorr: correct CSF, WM error
+ *@param[in]numoftuples: number of tuples in the image
+ *@param[in]numofframes: number of frames in the image
+ *@param[in]inp: input vtkDataArray
+ *@param[in]msk: mask vtkDataArray
+ *@param[out]out: write to output image directly
+ */
+void vtkbisCsfWmMotionCorrection::CSFWMErrorCorr(int numoftuples,int numofframes,vtkDataArray* inp,vtkDataArray* out,vtkDataArray* msk)
+{
+  int nt=numoftuples;
+  int nc=numofframes;
+
+  double* csfMean = new double[nc];
+  double* wmMean = new double[nc];
+  for(int ia=0;ia<nc;ia++)
+    {
+      csfMean[ia]=0.0;
+      wmMean[ia]=0.0;
+    }
+
+  double csfsum,wmsum;int csfcount,wmcount;
+  for (int i=0;i<nc;i++)
+    {
+      csfsum=0.0;wmsum=0.0;
+      csfcount=0;wmcount = 0;
+      for (int j=0;j<nt;j++)
+	{
+	  if(msk->GetComponent(j,0) == 1)
+	    {
+	      csfsum+=inp->GetComponent(j,i);
+	      ++csfcount;
+	    }
+	  if(msk->GetComponent(j,0) == 2)
+	    {
+	      wmsum+=inp->GetComponent(j,i);
+	      ++wmcount;
+	    }
+	}
+      csfMean[i]=(double)(csfsum/csfcount);
+      wmMean[i]=(double)(wmsum/wmcount);
+    }
+
+  //take out the error from csf and wm
+  vtkpxMatrix* csfwmA = vtkpxMatrix::New();
+  csfwmA->Zeros(nc,2);
+  for(int r=0;r<nc;r++)
+    {
+      int c=0;
+      csfwmA->SetDirectElement(r,c,csfMean[r]);
+      ++c;
+      csfwmA->SetDirectElement(r,c,wmMean[r]);
+    }
+
+  this->ComputeLSQMatrix(csfwmA, this->LSQ);
+  //std::string fname = "/mnt/cluster1/isabella/Desktop/james.mat";
+  //std::string matrixname = "James";
+  //csfwmALSQ->ExportToMatlab(fname.c_str(),matrixname.c_str());
+  //csfwmALSQ->Print();
+
+
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      int dooperation=1;
+      if (msk!=NULL)
+	{
+	  if (msk->GetComponent(voxel,0) <1)
+	    dooperation=0;
+	}
+
+      if (dooperation)
+	{
+	  this->EliminateError(inp,out,voxel,nc,this->LSQ,csfwmA);
+	}
+    }
+
+  delete [] csfMean;
+  delete [] wmMean;
+  csfwmA->Delete();
+
+}
+void vtkbisCsfWmMotionCorrection::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+
+  fprintf(stderr,"Beginning vtkbisCsfWmMotionCorrection\n");
+
+  if (this->ImageMask!=NULL)
+    {
+      int dim[3]; this->ImageMask->GetDimensions(dim);
+      int dim2[3]; input->GetDimensions(dim2);
+      int sum=0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=abs(dim[ia]-dim2[ia]);
+      if (sum>0)
+	{
+	  fprintf(stderr,"Bad Mask Input to vtkbisCsfWmMotionCorrection SimpleExecute\n");
+	  return;
+	}
+    }
+
+  vtkDataArray*   inp=input->GetPointData()->GetScalars();
+  int nt=inp->GetNumberOfTuples();
+  int nc=inp->GetNumberOfComponents();
+
+  vtkDataArray* msk=NULL;
+  if (this->ImageMask!=NULL)
+    msk=this->ImageMask->GetPointData()->GetScalars();
+
+  vtkDataArray*   out=output->GetPointData()->GetScalars();
+  for (int ia=0;ia<nc;ia++)
+    out->FillComponent(ia,0.0);
+
+  if(this->doMotion==1 && this->doCsfWm ==1)
+    {
+      this->CSFWMErrorCorr(nt,nc,inp,out,msk);
+      this->MotionErrorCorr(nt,nc,out,out,msk);
+    }
+  else if (this->doMotion==1)
+    {
+      this->MotionErrorCorr(nt,nc,inp,out,msk);
+    }
+  else if (this->doCsfWm == 1)
+    {
+      this->CSFWMErrorCorr(nt,nc,inp,out,msk);
+    }
+}
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisCsfWmMotionCorrection.h b/bioimagesuite30_src/Connectivity/vtkbisCsfWmMotionCorrection.h
new file mode 100644
index 0000000..014c9df
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisCsfWmMotionCorrection.h
@@ -0,0 +1,104 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisCsfWmMotionCorrection.h
+ *
+ *  Created on: May 29, 2009
+ *      Author: Isabella Murphy, Xilin Shen
+ *      calculate the mean of csf and white matter, construct a matrix [ csf_mean white matter_mean motion1 motion2 motion3 motion4 motion5 motion6 ]
+ */
+
+#ifndef VTKBISCSFWMMOTIONCORRECTION_H_
+#define VTKBISCSFWMMOTIONCORRECTION_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkpxMatrix.h"
+#include <string>
+
+using namespace std;
+
+class vtkbisCsfWmMotionCorrection : public vtkSimpleImageToImageFilter
+{
+public:
+	vtkTypeMacro(vtkbisCsfWmMotionCorrection,vtkSimpleImageToImageFilter);
+	static vtkbisCsfWmMotionCorrection *New();
+
+	// Mask Image
+	vtkSetObjectMacro(ImageMask,vtkImageData);
+	vtkGetObjectMacro(ImageMask,vtkImageData);
+
+	// Motion Matrix
+	vtkSetObjectMacro(MotionMatrix,vtkpxMatrix);
+	vtkGetObjectMacro(MotionMatrix,vtkpxMatrix);
+
+	// LSQ
+	vtkSetObjectMacro(LSQ,vtkpxMatrix);
+	vtkGetObjectMacro(LSQ,vtkpxMatrix);
+
+	//Filename
+	void SetFileName(const char* filename);
+	const char* GetFileName();
+
+	//doMotion
+	vtkSetClampMacro(doMotion,int,0,1);
+	vtkGetMacro(doMotion,int);
+
+	//doCsfWm
+	vtkSetClampMacro(doCsfWm,int,0,1);
+	vtkGetMacro(doCsfWm,int);
+
+protected:
+	vtkbisCsfWmMotionCorrection();
+	virtual ~vtkbisCsfWmMotionCorrection();
+	virtual int RequestInformation (vtkInformation * request,
+							vtkInformationVector ** inputVector,
+							vtkInformationVector * outputVector);
+	virtual void MotionErrorCorr(int numoftuples,int numofframes,vtkDataArray* inp,vtkDataArray* out,vtkDataArray* msk);
+	virtual void CSFWMErrorCorr(int numoftuples,int numofframes,vtkDataArray* inp,vtkDataArray* out,vtkDataArray* msk);
+	virtual void EliminateError(vtkDataArray* inp,vtkDataArray* out,int index,int numframes,vtkpxMatrix* LSQ,vtkpxMatrix* A);
+	virtual void ComputeLSQMatrix(vtkpxMatrix* A, vtkpxMatrix* LSQ);
+
+	// Execute Function -- main function
+	virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+private:
+	vtkbisCsfWmMotionCorrection(const vtkbisCsfWmMotionCorrection& src) {};
+	vtkbisCsfWmMotionCorrection& operator=(const vtkbisCsfWmMotionCorrection& rhs) {};
+	vtkImageData* ImageMask;
+	vtkpxMatrix* MotionMatrix;
+	vtkpxMatrix* LSQ;
+	//BTX
+	std::string FileName;
+	//ETX
+	int doMotion;
+	int doCsfWm;
+
+};
+
+#endif /* VTKBISCSFWMMOTIONCORRECTION_H_ */
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisDijkstraGraphGeodesicPath.cpp b/bioimagesuite30_src/Connectivity/vtkbisDijkstraGraphGeodesicPath.cpp
new file mode 100644
index 0000000..95247a1
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisDijkstraGraphGeodesicPath.cpp
@@ -0,0 +1,615 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisDijkstraGraphGeodesicPath.cpp
+ *
+ *  Created on: Apr 29, 2010
+ *      Author: Isabella Murphy, Xilin Shen
+ *      We modified the vtkDijkstraGraphGeodesicPath in vtk5.2, 2 modifications:
+ *      1. the edge weight is always 1
+ *      2. The condition that there is no path between the given vertices is considered
+ */
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:  $RCSfile: vtkDijkstraGraphGeodesicPath.cxx,v $
+  Language:  C++
+  Date:    $Date: 2008-07-21 19:34:55 $
+  Version:   $Revision: 1.6.2.1 $
+
+  Made by Rasmus Paulsen
+  email:  rrp(at)imm.dtu.dk
+  web:    www.imm.dtu.dk/~rrp/VTK
+
+  This class is not mature enough to enter the official VTK release.
+=========================================================================*/
+#include "vtkbisDijkstraGraphGeodesicPath.h"
+
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkFloatArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkExecutive.h"
+#include "vtkMath.h"
+#include "vtkIdList.h"
+#include "vtkIntArray.h"
+#include "vtkPolyData.h"
+#include "vtkPoints.h"
+#include "vtkPointData.h"
+#include "vtkCellArray.h"
+vtkbisDijkstraGraphGeodesicPath* vtkbisDijkstraGraphGeodesicPath::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisDijkstraGraphGeodesicPath");
+  if(ret)
+    {
+      return (vtkbisDijkstraGraphGeodesicPath*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisDijkstraGraphGeodesicPath;
+}
+//----------------------------------------------------------------------------
+vtkbisDijkstraGraphGeodesicPath::vtkbisDijkstraGraphGeodesicPath()
+{
+  this->IdList = vtkIdList::New();
+  this->d    = vtkFloatArray::New();
+  this->pre  = vtkIntArray::New();
+  this->f    = vtkIntArray::New();
+  this->s    = vtkIntArray::New();
+  this->Heap = vtkIntArray::New();
+  this->p    = vtkIntArray::New();
+  this->HeapSize  = 0;
+  this->StartVertex = 0;
+  this->EndVertex   = 0;
+  this->StopWhenEndReached = 0;
+  this->UseScalarWeights = 0;
+  this->Adjacency = NULL;
+  this->NumberOfVertices = 0;
+  this->AdjacencyGraphSize = 0;
+}
+
+//----------------------------------------------------------------------------
+vtkbisDijkstraGraphGeodesicPath::~vtkbisDijkstraGraphGeodesicPath()
+{
+  if (this->IdList)
+    {
+    this->IdList->Delete();
+    }
+  if (this->d)
+    {
+    this->d->Delete();
+    }
+  if (this->pre)
+    {
+    this->pre->Delete();
+    }
+  if (this->f)
+    {
+    this->f->Delete();
+    }
+  if (this->s)
+    {
+    this->s->Delete();
+    }
+  if (this->Heap)
+    {
+    this->Heap->Delete();
+    }
+  if (this->p)
+    {
+    this->p->Delete();
+    }
+
+  this->DeleteAdjacency();
+}
+
+//----------------------------------------------------------------------------
+int vtkbisDijkstraGraphGeodesicPath::RequestData(
+  vtkInformation *           vtkNotUsed( request ),
+  vtkInformationVector **    inputVector,
+  vtkInformationVector *     outputVector)
+{
+  vtkInformation * inInfo = inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo =   outputVector->GetInformationObject(0);
+
+  vtkPolyData *input = vtkPolyData::SafeDownCast(
+    inInfo->Get(vtkDataObject::DATA_OBJECT()));
+  if (!input)
+    {
+    return 0;
+    }
+
+  vtkPolyData *output = vtkPolyData::SafeDownCast(
+    outInfo->Get(vtkDataObject::DATA_OBJECT()));
+  if (!output)
+    {
+    return 0;
+    }
+
+  if ( this->AdjacencyBuildTime.GetMTime() < input->GetMTime() )
+    {
+    this->Initialize();
+    }
+  else
+    {
+    this->Reset();
+    }
+
+  if (this->NumberOfVertices == 0)
+    {
+    return 0;
+    }
+
+  int trace =this->ShortestPath(this->StartVertex, this->EndVertex);
+  //std::cout<<"we are here!!!!!!!!!"<<"trace:"<<trace<<endl;
+  //if(trace==1)
+  //{
+	  //std::cout<<"we are in trace!!!!!!!!"<<endl;
+	  this->TraceShortestPath(input, output, this->StartVertex, this->EndVertex);
+  //}
+
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+void vtkbisDijkstraGraphGeodesicPath::Initialize()
+{
+  vtkPolyData *input = vtkPolyData::SafeDownCast(
+      this->GetExecutive()->GetInputData(0, 0));
+//cout<<"A\n";
+  this->BuildAdjacency( input );
+  //cout<<"B\n";
+  this->NumberOfVertices = input->GetNumberOfPoints();
+
+  this->d->SetNumberOfComponents(1);
+  this->d->SetNumberOfTuples(this->NumberOfVertices);
+  this->pre->SetNumberOfComponents(1);
+  this->pre->SetNumberOfTuples(this->NumberOfVertices);
+  this->f->SetNumberOfComponents(1);
+  this->f->SetNumberOfTuples(this->NumberOfVertices);
+  this->s->SetNumberOfComponents(1);
+  this->s->SetNumberOfTuples(this->NumberOfVertices);
+  this->p->SetNumberOfComponents(1);
+  this->p->SetNumberOfTuples(this->NumberOfVertices);
+
+  // The heap has elements from 1 to n
+  this->Heap->SetNumberOfComponents(1);
+  this->Heap->SetNumberOfTuples(this->NumberOfVertices+1);
+}
+
+//----------------------------------------------------------------------------
+void vtkbisDijkstraGraphGeodesicPath::Reset()
+{
+  this->IdList->Reset();
+  this->HeapSize = 0;
+}
+
+//----------------------------------------------------------------------------
+void vtkbisDijkstraGraphGeodesicPath::DeleteAdjacency()
+{
+  const int npoints = this->AdjacencyGraphSize;
+
+  if (this->Adjacency)
+    {
+    for (int i = 0; i < npoints; i++)
+      {
+      this->Adjacency[i]->Delete();
+      }
+    delete [] this->Adjacency;
+    }
+  this->Adjacency = NULL;
+}
+
+//----------------------------------------------------------------------------
+// The edge cost function should be implemented as a callback function to
+// allow more advanced weighting
+double vtkbisDijkstraGraphGeodesicPath::CalculateEdgeCost(
+     vtkPolyData *pd, vtkIdType u, vtkIdType v)
+{
+  double p1[3];
+  pd->GetPoint(u,p1);
+  double p2[3];
+  pd->GetPoint(v,p2);
+
+  double w = sqrt(vtkMath::Distance2BetweenPoints(p1, p2));
+
+  if (this->UseScalarWeights)
+    {
+    // Note this edge cost is not symmetric!
+    vtkFloatArray *scalars =
+      static_cast<vtkFloatArray*>(pd->GetPointData()->GetScalars());
+    //    float s1 = scalars->GetValue(u);
+    double s2 = static_cast<double>(scalars->GetValue(v));
+
+    double wt = s2*s2;
+    if (wt != 0.0)
+      {
+      w  /= wt;
+      }
+    }
+  return w;
+}
+
+
+//----------------------------------------------------------------------------
+// This is probably a horribly inefficient way to do it.
+void vtkbisDijkstraGraphGeodesicPath::BuildAdjacency(vtkPolyData *pd)
+{
+	int i;
+
+	int npoints = pd->GetNumberOfPoints();
+	int ncells = pd->GetNumberOfCells();
+//cout<<"npoints:"<<npoints<<"\t";
+	this->DeleteAdjacency();
+	//cout<<"b\t";
+	this->Adjacency = new vtkIdList*[npoints];
+	//cout<<"c\t";
+	// Remember size, so it can be deleted again
+	this->AdjacencyGraphSize = npoints;
+	//cout<<"d\t";
+	for (i = 0; i < npoints; i++)
+    {
+		this->Adjacency[i] = vtkIdList::New();
+    }
+
+	for (i = 0; i < ncells; i++)
+    {//cout<<"f\t";
+		// Possible types
+		//    VTK_VERTEX, VTK_POLY_VERTEX, VTK_LINE,
+		//    VTK_POLY_LINE,VTK_TRIANGLE, VTK_QUAD,
+		//    VTK_POLYGON, or VTK_TRIANGLE_STRIP.
+
+		vtkIdType ctype = pd->GetCellType(i);
+
+		// Until now only handle polys and triangles
+		// TODO: All types
+		if (ctype == VTK_POLYGON || ctype == VTK_TRIANGLE || ctype == VTK_LINE)
+		{//cout<<"g\n";
+			vtkIdType *pts;
+			vtkIdType npts;
+			pd->GetCellPoints (i, npts, pts);
+
+			vtkIdType u = pts[0];
+			vtkIdType v = pts[npts-1];
+
+			this->Adjacency[u]->InsertUniqueId(v);
+			this->Adjacency[v]->InsertUniqueId(u);
+			for (int j = 0; j < npts-1; j++)
+			{
+				vtkIdType u1 = pts[j];
+				vtkIdType v1 = pts[j+1];
+				this->Adjacency[u1]->InsertUniqueId(v1);
+				this->Adjacency[v1]->InsertUniqueId(u1);
+			}
+		}
+    }
+	this->AdjacencyBuildTime.Modified();
+}
+
+//----------------------------------------------------------------------------
+void vtkbisDijkstraGraphGeodesicPath::TraceShortestPath(
+               vtkPolyData *inPd, vtkPolyData *outPd,
+               vtkIdType startv, vtkIdType endv)
+{
+	//std::cout<<"startv:"<<startv<<"endv:"<<endv<<" \n";
+	vtkPoints   *points = vtkPoints::New();
+	vtkCellArray *lines = vtkCellArray::New();
+
+	// n is far to many. Adjusted later
+	lines->InsertNextCell(this->NumberOfVertices);
+
+	// trace backward
+	int npoints = 0;
+	int v = endv;
+	double pt[3];
+	vtkIdType id;
+	while (v != startv && v != (-1))
+	{//std::cout<<"v="<<v<<"startv="<<startv<<" \n";
+		IdList->InsertNextId(v);
+
+		inPd->GetPoint(v,pt);
+
+		id = points->InsertNextPoint(pt);
+
+		lines->InsertCellPoint(id);
+
+		npoints++;
+
+		v = this->pre->GetValue(v);
+		//std::cout<<"after update v = "<<v<<"\n";
+
+    }
+	//std::cout<<"out of traceshortestpath while loop \n";
+	this->IdList->InsertNextId(v);
+	inPd->GetPoint(v,pt);
+	id = points->InsertNextPoint(pt);
+	lines->InsertCellPoint(id);
+	npoints++;
+
+	lines->UpdateCellCount(npoints);
+	outPd->SetPoints(points);
+	points->Delete();
+	outPd->SetLines(lines);
+	lines->Delete();
+
+}
+
+
+//----------------------------------------------------------------------------
+void vtkbisDijkstraGraphGeodesicPath::InitSingleSource(int startv)
+{
+  for (int v = 0; v < this->NumberOfVertices; v++)
+    {
+    // d will be updated with first visit of vertex
+    this->d->SetValue(v, -1);
+    this->pre->SetValue(v, -1);
+    this->s->SetValue(v, 0);
+    this->f->SetValue(v, 0);
+    }
+
+  this->d->SetValue(startv, 0);
+}
+
+
+//----------------------------------------------------------------------------
+void vtkbisDijkstraGraphGeodesicPath::Relax(int u, int v, double w)
+{
+  if (this->d->GetValue(v) > this->d->GetValue(u) + w)
+    {
+    this->d->SetValue(v, this->d->GetValue(u) + w);
+    this->pre->SetValue(v, u);
+
+    this->HeapDecreaseKey(v);
+    }
+}
+
+//----------------------------------------------------------------------------
+int vtkbisDijkstraGraphGeodesicPath::ShortestPath(int startv, int endv)
+{
+	//std::cout<<"We are in shortestpath"<<"startv:"<<startv<<"endv:"<<endv<<endl;
+	vtkPolyData *input = vtkPolyData::SafeDownCast(
+			this->GetExecutive()->GetInputData(0, 0));
+
+	int i, u, v;
+	this->InitSingleSource(startv);
+	this->HeapInsert(startv);
+	this->f->SetValue(startv, 1);
+	int stop = 0;
+
+	//u=this->HeapExtractMin();
+	//for(; u>=0 ; )
+
+	while ((u = this->HeapExtractMin()) >= 0 && !stop)
+	{
+			//if(stop==0)
+			//{
+				//std::cout<<"e"<<endl;
+				// u is now in s since the shortest path to u is determined
+				this->s->SetValue(u, 1);
+				//std::cout<<"f"<<endl;
+				// remove u from the front set
+				this->f->SetValue(u, 0);
+				//std::cout<<"g"<<"u:"<<u<<endl;
+				if (u == endv && this->StopWhenEndReached)
+				{
+					//std::cout<<"h"<<endl;
+					stop = 1;
+				}
+
+				// Update all vertices v adjacent to u
+				for (i = 0; i < this->Adjacency[u]->GetNumberOfIds(); i++)
+				{
+					//std::cout<<"adj:"<<this->Adjacency[u]->GetNumberOfIds()<<"i now:"<<i<<endl;
+					v = this->Adjacency[u]->GetId(i);
+					//std::cout<<"what is v now?"<<v<<endl;
+					//std::cout<<"j"<<endl;
+					// s is the set of vertices with determined shortest path...do not use them again
+					if (!this->s->GetValue(v))
+					{
+						//std::cout<<"k"<<endl;
+						// Only relax edges where the end is not in s and edge is in the front set
+						//double w = this->CalculateEdgeCost(input, u, v);
+						double w = 1;
+						//std::cout<<"l"<<endl;
+						if (this->f->GetValue(v))
+						{
+							//std::cout<<"m"<<endl;
+							this->Relax(u, v, w);
+							//std::cout<<"n"<<endl;
+						}
+						// add edge v to front set
+						else
+						{
+							this->f->SetValue(v, 1);
+							this->d->SetValue(v, this->d->GetValue(u) + w);
+
+							// Set Predecessor of v to be u
+							this->pre->SetValue(v, u);
+
+							this->HeapInsert(v);
+						}
+					}
+				}
+				//u = this->HeapExtractMin();
+				//if( u==-1)
+				//{
+				//return -1;
+				//}
+			//}
+	}
+	return 1;
+}
+
+
+//----------------------------------------------------------------------------
+void vtkbisDijkstraGraphGeodesicPath::Heapify(int i)
+{
+	// left node
+	int l = i * 2;
+
+	// right node
+	int r = i * 2 + 1;
+
+	int smallest = -1;
+
+	// The value of element v is d(v)
+	// the heap stores the vertex numbers
+	if (   l <= this->HeapSize && (this->d->GetValue(this->Heap->GetValue(l)) < this->d->GetValue(this->Heap->GetValue(i))))
+    {
+		smallest = l;
+    }
+	else
+    {
+		smallest = i;
+    }
+
+	if ( r <= this->HeapSize && (this->d->GetValue(this->Heap->GetValue(r)) < this->d->GetValue(this->Heap->GetValue(smallest))))
+    {
+		smallest = r;
+    }
+
+	if (smallest != i)
+    {
+		int t = this->Heap->GetValue(i);
+
+		this->Heap->SetValue(i, this->Heap->GetValue(smallest));
+
+		// where is Heap(i)
+		this->p->SetValue(this->Heap->GetValue(i), i);
+
+		// Heap and p are kind of inverses
+		this->Heap->SetValue(smallest, t);
+		this->p->SetValue(t, smallest);
+
+		this->Heapify(smallest);
+    }
+}
+
+//----------------------------------------------------------------------------
+// Insert vertex v. Weight is given in d(v)
+// H has indices 1..n
+void vtkbisDijkstraGraphGeodesicPath::HeapInsert(int v)
+{
+  if (this->HeapSize >= this->Heap->GetNumberOfTuples()-1)
+    return;
+
+  this->HeapSize++;
+  int i = this->HeapSize;
+
+  while (i > 1 &&
+         (this->d->GetValue(this->Heap->GetValue(i/2))
+                   > this->d->GetValue(v)))
+    {
+    this->Heap->SetValue(i, this->Heap->GetValue(i/2));
+    this->p->SetValue(this->Heap->GetValue(i), i);
+    i /= 2;
+    }
+  // Heap and p are kind of inverses
+  this->Heap->SetValue(i, v);
+  this->p->SetValue(v, i);
+}
+
+//----------------------------------------------------------------------------
+int vtkbisDijkstraGraphGeodesicPath::HeapExtractMin()
+{
+	//std::cout<<"in HeapExtractMin"<<endl;
+  if (this->HeapSize == 0)
+  {
+	  //std::cout<<"in HeapSize==0 "<<endl;
+	  return -1;
+
+  }
+
+  //std::cout<<"in HeapSize!=0"<<endl;
+  int minv = this->Heap->GetValue(1);
+  //std::cout<<"minv="<<minv<<"\n";
+  this->p->SetValue(minv, -1);
+
+  this->Heap->SetValue(1, this->Heap->GetValue(this->HeapSize));
+  //std::cout<<"set heap 1 to:"<<this->Heap->GetValue(this->HeapSize)<<endl;
+  this->p->SetValue(this->Heap->GetValue(1), 1);
+  //std::cout<<"set p"<<this->Heap->GetValue(1)<<"to 1\n";
+  this->HeapSize--;
+  //std::cout<<"updated heap size:"<<this->HeapSize<<endl;
+  this->Heapify(1);
+  //std::cout<<"returned minv:"<<minv<<endl;
+  return minv;
+}
+
+//----------------------------------------------------------------------------
+void vtkbisDijkstraGraphGeodesicPath::HeapDecreaseKey(int v)
+{
+  // where in Heap is vertex v
+  int i = this->p->GetValue(v);
+  if (i < 1 || i > this->HeapSize)
+    return;
+
+  while (i > 1 &&
+      this->d->GetValue(this->Heap->GetValue(i/2)) > this->d->GetValue(v))
+    {
+    this->Heap->SetValue(i, this->Heap->GetValue(i/2));
+    this->p->SetValue(this->Heap->GetValue(i), i);
+    i /= 2;
+    }
+
+  // Heap and p are kind of inverses
+  this->Heap->SetValue(i, v);
+  this->p->SetValue(v, i);
+}
+
+//----------------------------------------------------------------------------
+void vtkbisDijkstraGraphGeodesicPath::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+
+  os << indent << "StopWhenEndReached: ";
+  if (this->StopWhenEndReached)
+    {
+    os << "On\n";
+    }
+  else
+    {
+    os << "Off\n";
+    }
+  os << indent << "Verts in input mesh: " << this->NumberOfVertices << endl;
+
+  // Add all members later
+  // this->d
+  // this->pre
+  // this->Adjacency
+  // this->IdList
+  // this->p
+  // this->UseScalarWeights
+  // this->AdjacencyGraphSize
+  // this->HeapSize
+  // this->s
+  // this->Heap
+  // this->f
+}
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisDijkstraGraphGeodesicPath.h b/bioimagesuite30_src/Connectivity/vtkbisDijkstraGraphGeodesicPath.h
new file mode 100644
index 0000000..4e35dba
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisDijkstraGraphGeodesicPath.h
@@ -0,0 +1,212 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisDijkstraGraphGeodesicPath.h
+ *
+ *  Created on: Apr 29, 2010
+ *      Author: Isabella Murphy, Xilin Shen
+ *      We modified the vtkDijkstraGraphGeodesicPath in vtk5.2, 2 modifications:
+ *      1. the edge weight is always 1
+ *      2. The condition that there is no path between the given vertices is considered
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkbisDijkstraGraphGeodesicPath.h,v $
+
+  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 vtkbisDijkstraGraphGeodesicPath - Dijkstra algorithm to compute the graph geodesic.
+// .SECTION Description
+// Takes as input a polygonal mesh and performs a single source shortest
+// path calculation. Dijkstra's algorithm is used. The implementation is
+// similar to the one described in Introduction to Algorithms (Second Edition)
+// by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and
+// Cliff Stein, published by MIT Press and McGraw-Hill. Some minor
+// enhancement are added though. All vertices are not pushed on the heap
+// at start, instead a front set is maintained. The heap is implemented as
+// a binary heap. The output of the filter is a set of lines describing
+// the shortest path from StartVertex to EndVertex.
+//
+// .SECTION Caveats
+// The input polydata must have only triangle cells.
+//
+// .SECTION Thanks
+// The class was contributed by Rasmus Paulsen.
+// www.imm.dtu.dk/~rrp/VTK . Also thanks to Alexandre Gouaillard and Shoaib
+// Ghias for bug fixes and enhancements.
+
+#ifndef __vtkbisDijkstraGraphGeodesicPath_H_
+#define __vtkbisDijkstraGraphGeodesicPath_H_
+
+#include "vtkGraphGeodesicPath.h"
+
+class vtkDoubleArray;
+class vtkIntArray;
+class vtkIdList;
+class vtkFloatArray;
+
+class vtkbisDijkstraGraphGeodesicPath : public vtkGraphGeodesicPath {
+
+public:
+
+  // Description:
+  // Instantiate the class
+  static vtkbisDijkstraGraphGeodesicPath *New();
+  vtkTypeMacro(vtkbisDijkstraGraphGeodesicPath,vtkGraphGeodesicPath);
+  // Description:
+  // Standard methids for printing and determining type information.
+  //vtkTypeRevisionMacro(vtkbisDijkstraGraphGeodesicPath,vtkGraphGeodesicPath);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // The vertex ids (of the input polydata) on the shortest path
+  vtkGetObjectMacro(IdList, vtkIdList);
+
+  // Description:
+  // Get the summed weight for all vertices
+  vtkGetObjectMacro(d, vtkFloatArray);
+
+  // Description:
+  // Stop when the end vertex is reached
+  // or calculate shortest path to all vertices
+  vtkSetMacro(StopWhenEndReached, int);
+  vtkGetMacro(StopWhenEndReached, int);
+  vtkBooleanMacro(StopWhenEndReached, int);
+
+  // Description:
+  // Use scalar values in the edge weight (experimental)
+  vtkSetMacro(UseScalarWeights, int);
+  vtkGetMacro(UseScalarWeights, int);
+  vtkBooleanMacro(UseScalarWeights, int);
+
+  // Description:
+  // TODO: Get the total geodesic length.
+  virtual double GetGeodesicLength() { return 0.0; }
+
+protected:
+  vtkbisDijkstraGraphGeodesicPath();
+  ~vtkbisDijkstraGraphGeodesicPath();
+
+  virtual int RequestData(vtkInformation *, vtkInformationVector **,
+                          vtkInformationVector *);
+
+  // Build a graph description of the mesh
+  void BuildAdjacency(vtkPolyData *pd);
+
+  void DeleteAdjacency();
+
+  vtkTimeStamp AdjacencyBuildTime;
+
+  // The cost going from vertex u to v
+  // TODO: should be implemented as a user supplied
+  // callback function
+  double CalculateEdgeCost(vtkPolyData *pd, vtkIdType u, vtkIdType v);
+
+  void Initialize();
+
+  void Reset();
+
+  // structure the heap
+  void Heapify(int i);
+
+  // insert vertex v in heap. Weight is in d(v)
+  void HeapInsert(int v);
+
+  // extract vertex with min d(v)
+  int HeapExtractMin();
+
+  // Update heap when key d(v) has been decreased
+  void HeapDecreaseKey(int v);
+
+  void InitSingleSource(int startv);
+
+  // Calculate shortest path from vertex startv to vertex endv
+  int ShortestPath(int startv, int endv);
+
+  // Relax edge u,v with weight w
+  void Relax(int u, int v, double w);
+
+  // Backtrace the shortest path
+  void TraceShortestPath(vtkPolyData *inPd, vtkPolyData *outPd,
+               vtkIdType startv, vtkIdType endv);
+
+  // the number of vertices
+  int NumberOfVertices;
+
+  // d(v) current summed weight for path to vertex v
+  vtkFloatArray *d;
+
+  // pre(v) predecessor of v
+  vtkIntArray *pre;
+
+  // f is the set of vertices wich has not a shortest path yet but has a path
+  // ie. the front set (f(v) == 1 means that vertex v is in f)
+  vtkIntArray *f;
+
+  // s is the set of vertices with already determined shortest path
+  // s(v) == 1 means that vertex v is in s
+  vtkIntArray *s;
+
+  // the priority que (a binary heap) with vertex indices
+  vtkIntArray *Heap;
+
+  // The real number of elements in H != H.size()
+  int HeapSize;
+
+  // p(v) the position of v in H (p and H are kind of inverses)
+  vtkIntArray *p;
+
+  // The vertex ids on the shortest path
+  vtkIdList *IdList;
+
+  // Adjacency representation
+  vtkIdList **Adjacency;
+
+  int StopWhenEndReached;
+
+  int UseScalarWeights;
+
+  // Used to remember the size of the graph. If the filter is re-used.
+  int AdjacencyGraphSize;
+
+private:
+  vtkbisDijkstraGraphGeodesicPath(const vtkbisDijkstraGraphGeodesicPath&);  // Not implemented.
+  void operator=(const vtkbisDijkstraGraphGeodesicPath&);  // Not implemented.
+
+};
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisDisplayROIMean.cpp b/bioimagesuite30_src/Connectivity/vtkbisDisplayROIMean.cpp
new file mode 100644
index 0000000..303dfc1
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisDisplayROIMean.cpp
@@ -0,0 +1,151 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisDisplayROIMean.cpp
+ *
+ *  Created on: Sep 1, 2009
+ *      Author: Isabella Murphy
+ */
+
+#include <vtkbisDisplayROIMean.h>
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkObjectFactory.h"
+#include "vtkObject.h"
+#include "vtkPointData.h"
+#include "vtkbisImageTimeSeriesNormalize.h"
+#include "vtkFloatArray.h"
+
+using namespace std;
+
+vtkbisDisplayROIMean::vtkbisDisplayROIMean() 
+{
+  this->ImageROI=NULL;
+  this->AverageROI=NULL;
+  
+}
+
+vtkbisDisplayROIMean::~vtkbisDisplayROIMean() 
+{
+  this->SetImageROI(NULL);
+  this->SetAverageROI(NULL);
+}
+
+vtkbisDisplayROIMean* vtkbisDisplayROIMean::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisDisplayROIMean");
+  if(ret)
+    {
+      return (vtkbisDisplayROIMean*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisDisplayROIMean;
+}
+/*-------------------------------------------------------------------------------------
+ * force the output data type to float, need to change extend information to let
+ * the pipeline know the difference
+ * @Set: output data type = float
+ */
+int vtkbisDisplayROIMean::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+					  vtkInformationVector *outputVector)
+{
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisDisplayROIMean::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+  fprintf(stderr,"Beginning vtkbisDisplayROIMean\n");
+
+  if (this->AverageROI==NULL || this->ImageROI==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkbisDisplayROIMean\n");
+      return;
+    }
+
+
+  if (this->AverageROI->GetNumberOfScalarComponents()!=input->GetNumberOfScalarComponents())
+    {
+      fprintf(stderr,"Bad ROI mean Image in vtkbisDisplayROIMean SimpleExecute\n");
+      return;
+    }
+
+  int dim[3],dim2[3];
+  this->ImageROI->GetDimensions(dim);
+  input->GetDimensions(dim2);
+  int sum=0;
+  for (int ia=0;ia<=2;ia++)
+    sum+=abs(dim[ia]-dim2[ia]);
+  if (sum>0)
+    {
+      fprintf(stderr,"Bad ROI Input to vtkbisROIMean SimpleExecute, wrong dimensions ROI=%d,%d,%d input=%d,%d,%d.\n",
+	      dim[0],dim[1],dim[2],
+	      dim2[0],dim2[1],dim2[2]);
+      return;
+    }
+
+  double r[2]; this->ImageROI->GetPointData()->GetScalars()->GetRange(r);
+  int ntr=this->AverageROI->GetPointData()->GetScalars()->GetNumberOfTuples();
+
+  int numr=int(r[1]);
+  if (ntr!=numr)
+    {
+      fprintf(stderr,"Average ROI Map does not agree with ROI Image ntr=%d numr=%d\n",ntr,numr);
+      return;
+    }
+
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  int nt=inp->GetNumberOfTuples();//number of voxels
+  int nc=inp->GetNumberOfComponents();//number of frames
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  for (int ia=0;ia<nc;ia++)
+    out->FillComponent(ia,0.0);
+
+  vtkDataArray* roi=roi=this->ImageROI->GetPointData()->GetScalars();
+  vtkDataArray* roimean=this->AverageROI->GetPointData()->GetScalars();
+
+
+
+  for(int i=0;i<nt;i++)
+    {
+      int roiregion = (int)roi->GetComponent(i,0);
+      if(roiregion>0)
+	{
+	  for(int j=0;j<nc;j++)
+	      out->SetComponent(i,j,roimean->GetComponent(roiregion-1,j));
+	}
+    }
+}
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisDisplayROIMean.h b/bioimagesuite30_src/Connectivity/vtkbisDisplayROIMean.h
new file mode 100644
index 0000000..3a32ab6
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisDisplayROIMean.h
@@ -0,0 +1,73 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisDisplayROIMean.h
+ *
+ *  Created on: Sep 1, 2009
+ *      Author: Isabella Murphy
+ */
+
+#ifndef VTKBISDISPLAYROIMEAN_H_
+#define VTKBISDISPLAYROIMEAN_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkbisDisplayROIMean : public vtkSimpleImageToImageFilter
+{
+public:
+	vtkTypeMacro(vtkbisDisplayROIMean,vtkSimpleImageToImageFilter);
+	static vtkbisDisplayROIMean *New();
+
+	// ROI Mean
+	vtkSetObjectMacro(AverageROI,vtkImageData);
+	vtkGetObjectMacro(AverageROI,vtkImageData);
+
+	// ROI Image
+	vtkSetObjectMacro(ImageROI,vtkImageData);
+	vtkGetObjectMacro(ImageROI,vtkImageData);
+
+	virtual int RequestInformation (vtkInformation * request,
+				vtkInformationVector ** inputVector,
+				vtkInformationVector * outputVector) ;
+
+	virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+
+protected:
+	vtkbisDisplayROIMean();
+	virtual ~vtkbisDisplayROIMean();
+private:
+	vtkbisDisplayROIMean(const vtkbisDisplayROIMean& src){};
+	vtkbisDisplayROIMean& operator=(const vtkbisDisplayROIMean& rhs){};
+	vtkImageData* AverageROI;
+	vtkImageData* ImageROI;
+};
+
+#endif /* VTKBISDISPLAYROIMEAN_H_ */
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisImageTemporalSmoothing.cpp b/bioimagesuite30_src/Connectivity/vtkbisImageTemporalSmoothing.cpp
new file mode 100644
index 0000000..56ca08c
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisImageTemporalSmoothing.cpp
@@ -0,0 +1,226 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*!
+ *
+ * vtkbisImageTemporalSmoothing.cpp
+ *
+ *  Created on: Aug 20, 2008
+ *      Author: Isabella Murphy,Xilin Shen
+ *
+ * Gaussian smoothing method
+ * User can choose the value of sigma. The length of the kernel will be 1+2*radius.
+ * Radius = 2sigma+0.5
+ */
+
+#include "vtkbisImageTemporalSmoothing.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "pxisinf.h"
+
+// This creates the "New" Function
+vtkStandardNewMacro(vtkbisImageTemporalSmoothing);
+
+// Construct object to extract all of the input data.
+vtkbisImageTemporalSmoothing::vtkbisImageTemporalSmoothing()
+{
+  this->Sigma=1.0;
+  this->ImageMask=NULL;
+}
+vtkbisImageTemporalSmoothing::~vtkbisImageTemporalSmoothing()
+{
+  this->SetImageMask(NULL);
+}
+
+/*-------------------------------------------------------------------------------------
+ * force the output data type to double, need to change extend information to let
+ * the pipeline know the difference
+ * @Set: output data type = double
+ */
+int vtkbisImageTemporalSmoothing::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+					  vtkInformationVector *outputVector)
+{
+	vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+	vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+	return 1;
+}
+
+vtkFloatArray* vtkbisImageTemporalSmoothing::CreateKernel(double sigma)
+{
+
+  int radius=int(2.0*sigma+0.5);
+  int length=1+2*radius;
+  int midpoint=radius;
+
+  /*
+    To create a pointer ordinarily
+    vtkFloatArray* kernel=new vtkFloatArray();
+
+    BUT
+
+    constructor is protected! so you can't do this.
+
+    Instead use the New method which is a static member of the class
+
+  */
+  vtkFloatArray* kernel=vtkFloatArray::New();
+  kernel->SetNumberOfComponents(1);
+  kernel->SetNumberOfTuples(length);
+
+  double sum=0.0;
+  double g=0.0;
+
+  for (int i=0;i<length;i++)
+    {
+      double x=double(i-midpoint);
+      if(sigma<0.00001)
+      {
+    	  g=1;
+      }else{
+    	  g=exp(-x*x/(2.0*sigma*sigma));
+      }
+      sum+=g;
+      kernel->SetComponent(i,0,g);
+    }
+  if (sum<0.00001)
+	  sum=1.0;
+  if (isnan(sum) || isinf(sum))
+	  sum=1.0;
+
+  // Normalize
+  for (int i=0;i<length;i++)
+    {
+      double g=kernel->GetComponent(i,0);
+      if (isnan(g) || isinf(g))
+      		  g=0.0;
+      double gnorm=g/sum;
+      kernel->SetComponent(i,0,gnorm);
+            //fprintf(stderr,"Kernel Value %d = %.4f\n",i,kernel->GetComponent(i,0));
+    }
+  return kernel;
+}
+
+// ---------------------------------------------------------------------------
+void vtkbisImageTemporalSmoothing::SmoothVoxel(vtkDataArray* inpdata,vtkDataArray* outdata,vtkFloatArray* kernel,int index,int numframes,int radius)
+{
+	double sum;int imgindex;int kernelindex;double imagevalue;double kerneldata;
+
+  for (int f=0;f<numframes;f++)
+    {
+      sum=0.0;
+      for (int t=-radius;t<=radius;t++)
+	  {
+    	  imgindex=f+t;
+    	  if (imgindex<0)
+    		  imgindex=0;
+    	  else if (imgindex>=numframes)
+    		  imgindex=numframes-1;
+
+    	  kernelindex=t+radius;
+
+    	  imagevalue=inpdata->GetComponent(index,imgindex);
+    	  kerneldata=kernel->GetComponent(kernelindex,0);
+    	  sum+=imagevalue*kerneldata;
+	  }
+		  outdata->SetComponent(index,f,sum);
+    }
+}
+// ---------------------------------------------------------------------------
+void vtkbisImageTemporalSmoothing::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+	fprintf(stderr,"Beginning ImageTemporalSmoothing use sigma=%.2f\n",
+			  this->Sigma);
+
+  if (this->ImageMask!=NULL)
+  {
+	  int dim[3]; this->ImageMask->GetDimensions(dim);
+      int dim2[3]; input->GetDimensions(dim2);
+      int sum=0;
+      for (int ia=0;ia<=2;ia++)
+      	sum+=abs(dim[ia]-dim2[ia]);
+      if (sum>0)
+      {
+      	fprintf(stderr,"Bad Mask Input to vtkbisImageTemporalSmoothing SimpleExecute\n");
+      	return;
+      }
+  }
+
+  vtkDataArray*   inp=input->GetPointData()->GetScalars();
+  int nt=inp->GetNumberOfTuples();
+  int nc=input->GetNumberOfScalarComponents();
+
+  vtkDataArray*   out=output->GetPointData()->GetScalars();
+  // Cleanup first -- fill output with zeros
+  for (int c=0;c<nc;c++)
+    out->FillComponent(c,0.0);
+
+  vtkFloatArray* kernel=this->CreateKernel(this->Sigma);
+  int radius=int(2.0*this->Sigma+0.5);
+  /*  for (int i=0;i<kernel->GetNumberOfTuples();i++)
+      fprintf(stdout,"kernel %d = %f\n",i,kernel->GetComponent(i,0));*/
+
+  vtkDataArray* msk=NULL;
+  if (this->ImageMask!=NULL)
+    msk=this->ImageMask->GetPointData()->GetScalars();
+
+  int maxcount=int(nt/10);
+  int count=0;
+  double pog=0.0;
+
+  this->UpdateProgress(0.01);
+  int index=0;
+  for (int voxel=0;voxel<nt;voxel++)
+  {
+	  int doglm=1;
+	  if (msk!=NULL)
+	  {
+		  if (msk->GetComponent(voxel,0)<1)
+			  doglm=0;
+	  }
+	  if (doglm)
+	  {
+		  this->SmoothVoxel(inp,out,kernel,voxel,nc,radius);
+	  }
+	  ++count;
+	  if (count==maxcount)
+	  {
+		  pog=double(voxel)/double(nt);
+	      this->UpdateProgress(pog);
+	      count=0;
+	      //fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,double(numdone)/double(nt));
+	  }
+  }
+  this->UpdateProgress(1.0);
+  kernel->Delete();
+}
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisImageTemporalSmoothing.h b/bioimagesuite30_src/Connectivity/vtkbisImageTemporalSmoothing.h
new file mode 100644
index 0000000..5cb9aed
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisImageTemporalSmoothing.h
@@ -0,0 +1,88 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*
+ * vtkbisImageTemporalSmoothing.h
+ *
+ *  Created on: Aug 20, 2008
+ *      Author: Isabella Murphy; Xilin Chen
+ *
+ * Gaussian smoothing method
+ * User can choose the value of sigma. The length of the kernel will be 1+2*radius.
+ * Radius = 2sigma+0.5
+ */
+
+#ifndef __vtkbisImageTemporalSmoothing_h
+#define __vtkbisImageTemporalSmoothing_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+
+class vtkbisImageTemporalSmoothing : public vtkSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkbisImageTemporalSmoothing,vtkSimpleImageToImageFilter);
+  static vtkbisImageTemporalSmoothing *New();
+
+  // Mask Image
+  vtkSetObjectMacro(ImageMask,vtkImageData);
+  vtkGetObjectMacro(ImageMask,vtkImageData);
+
+  // Sigma
+  vtkSetClampMacro(Sigma,double,0.05,10.0);
+  vtkGetMacro(Sigma,double);
+
+protected:
+
+  vtkbisImageTemporalSmoothing();
+  virtual ~vtkbisImageTemporalSmoothing();
+
+  virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+  					  vtkInformationVector *outputVector);
+
+  // Execute Function -- main function
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+
+  // Utility Function to create the kernel
+  virtual vtkFloatArray* CreateKernel(double sigma);
+  virtual void SmoothVoxel(vtkDataArray* inpdata,vtkDataArray* outdata,vtkFloatArray* kernel,int index,int numframes,int radius);
+
+private:
+	vtkbisImageTemporalSmoothing(const vtkbisImageTemporalSmoothing& src) {};
+	vtkbisImageTemporalSmoothing& operator=(const vtkbisImageTemporalSmoothing& rhs) {};
+	double Sigma;
+	vtkImageData* ImageMask;
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisImageTimeSeriesNormalize.cpp b/bioimagesuite30_src/Connectivity/vtkbisImageTimeSeriesNormalize.cpp
new file mode 100644
index 0000000..fdca349
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisImageTimeSeriesNormalize.cpp
@@ -0,0 +1,194 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkbisImageTimeSeriesNormalize.h"
+
+#include "vtkImageData.h"
+#include "vtkImageProgressIterator.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkObjectFactory.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "pxisinf.h"
+
+
+vtkCxxRevisionMacro(vtkbisImageTimeSeriesNormalize, "$Revision: 1.54 $");
+vtkStandardNewMacro(vtkbisImageTimeSeriesNormalize);
+
+//----------------------------------------------------------------------------
+vtkbisImageTimeSeriesNormalize::vtkbisImageTimeSeriesNormalize()
+{
+  //  this->NormalizeMean=1;
+  //  this->NormalizeSigma=1;
+}
+
+//----------------------------------------------------------------------------
+vtkbisImageTimeSeriesNormalize::~vtkbisImageTimeSeriesNormalize()
+{
+}
+
+//----------------------------------------------------------------------------
+void vtkbisImageTimeSeriesNormalize::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+  //  os << indent << "NormalizeMean: " << this->NormalizeMean << "\n";
+  //  os << indent << "NormalizeSigma: " << this->NormalizeSigma << "\n";
+
+}
+
+//----------------------------------------------------------------------------
+int vtkbisImageTimeSeriesNormalize::RequestInformation(vtkInformation*,
+                                           vtkInformationVector**,
+                                           vtkInformationVector* outputVector)
+{
+  vtkInformation* outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+// This function template implements the filter for any type of data.
+// The last two arguments help the vtkTemplateMacro calls below
+// instantiate the proper input and output types.
+template <class IT, class OT>
+void vtkbisImageTimeSeriesNormalizeExecute(vtkbisImageTimeSeriesNormalize* self,
+                               vtkImageData* inData,
+                               vtkImageData* outData,
+                               int outExt[6], int id,
+                               IT*, OT*)
+{
+  // Create iterators for the input and output extents assigned to
+  // this thread.
+  vtkImageIterator<IT> inIt(inData, outExt);
+  vtkImageProgressIterator<OT> outIt(outData, outExt, self, id);
+
+  // Get the shift and scale parameters values.
+  //  int domean=self->GetNormalizeMean();
+  //  int dosigma=self->GetNormalizeSigma();
+
+  // Clamp pixel values within the range of the output type.
+
+  int maxC = inData->GetNumberOfScalarComponents();
+
+  double scalefactor=1.0;
+  scalefactor=1.0/double(maxC);
+
+  // Loop through output pixels.
+  while (!outIt.IsAtEnd())
+    {
+      IT* inSI = inIt.BeginSpan();
+      OT* outSI = outIt.BeginSpan();
+      OT* outSIEnd = outIt.EndSpan();
+
+      while (outSI != outSIEnd)
+	{
+	  IT* inSItemp=inSI;
+	  double sum=0.0,sum2=0.0;
+	  for (int idxC = 0; idxC < maxC; idxC++)
+	    {
+	      // Pixel operation
+	      double v=(static_cast<double>(*inSItemp));
+	      sum+=v;
+	      sum2+=v*v;
+	      ++inSItemp;
+	    }
+	  double mean=sum*scalefactor;
+	  double sigma=sqrt(sum2*scalefactor-mean*mean);
+
+	  if (sigma<0.00001)
+	    sigma=1.0;
+
+	  if (isnan(sigma) || isinf(sigma))
+	    sigma=1.0;
+	  if (isnan(mean) || isinf(mean))
+	    mean=0.0;
+
+
+	  for (int idxC = 0; idxC < maxC; idxC++)
+	    {
+	      // Pixel operation
+	      double v=(static_cast<double>(*inSI));
+	      //cout<<"oriV:"<<v;
+	      v= (v-mean)/sigma;
+	      *outSI = static_cast<OT>(v);
+	      //cout<<"newV:"<<v<<"mean:"<<mean<<"sigma:"<<sigma<<" | ";
+	      ++outSI;
+	      ++inSI;
+	    }
+	}
+      inIt.NextSpan();
+      outIt.NextSpan();
+    }
+}
+
+//----------------------------------------------------------------------------
+template <class T>
+void vtkbisImageTimeSeriesNormalizeExecute1(vtkbisImageTimeSeriesNormalize* self,
+                                vtkImageData* inData,
+                                vtkImageData* outData,
+                                int outExt[6], int id, T*)
+{
+  switch (outData->GetScalarType())
+    {
+    vtkTemplateMacro(
+      vtkbisImageTimeSeriesNormalizeExecute(self, inData,
+                                outData, outExt, id,
+                                static_cast<T*>(0),
+                                static_cast<VTK_TT*>(0)));
+    default:
+      vtkErrorWithObjectMacro(
+        self, "ThreadedRequestData: Unknown output ScalarType");
+      return;
+    }
+}
+
+//----------------------------------------------------------------------------
+// This method is passed a input and output data, and executes the filter
+// algorithm to fill the output from the input.
+// It just executes a switch statement to call the correct function for
+// the datas data types.
+void vtkbisImageTimeSeriesNormalize::ThreadedRequestData(vtkInformation*,
+                                             vtkInformationVector**,
+                                             vtkInformationVector*,
+                                             vtkImageData*** inData,
+                                             vtkImageData** outData,
+                                             int outExt[6],
+                                             int threadId)
+{
+  vtkImageData* input = inData[0][0];
+  vtkImageData* output = outData[0];
+  switch(input->GetScalarType())
+    {
+    vtkTemplateMacro(
+      vtkbisImageTimeSeriesNormalizeExecute1(this, input, output, outExt, threadId,
+                                 static_cast<VTK_TT*>(0)));
+    default:
+      vtkErrorMacro("ThreadedRequestData: Unknown input ScalarType");
+      return;
+    }
+}
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisImageTimeSeriesNormalize.h b/bioimagesuite30_src/Connectivity/vtkbisImageTimeSeriesNormalize.h
new file mode 100644
index 0000000..606b88a
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisImageTimeSeriesNormalize.h
@@ -0,0 +1,84 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// .NAME vtkbisImageTimeSeriesNormalize - takes a time series and normalizes it to have zero mean and unit standard deviation
+
+#ifndef __vtkbisImageTimeSeriesNormalize_h
+#define __vtkbisImageTimeSeriesNormalize_h
+
+
+#include "vtkThreadedImageAlgorithm.h"
+
+class vtkbisImageTimeSeriesNormalize : public vtkThreadedImageAlgorithm
+{
+public:
+  static vtkbisImageTimeSeriesNormalize *New();
+  vtkTypeRevisionMacro(vtkbisImageTimeSeriesNormalize,vtkThreadedImageAlgorithm);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  //NumOfFrames
+  //vtkGetMacro(NumOfFrames,int);
+  //vtkSetMacro(NumOfFrames,int);
+
+  // Description:
+  // Normalize Mean and Sigma
+  /*  vtkSetClampMacro(NormalizeMean,int,0,1);
+  vtkGetMacro(NormalizeMean,int);
+  vtkBooleanMacro(NormalizeMean,int)
+
+  vtkSetClampMacro(NormalizeSigma,int,0,1);
+  vtkGetMacro(NormalizeSigma,int);
+  vtkBooleanMacro(NormalizeSigma,int)*/
+
+
+protected:
+  vtkbisImageTimeSeriesNormalize();
+  ~vtkbisImageTimeSeriesNormalize();
+
+  //  int NormalizeMean;
+  //  int NormalizeSigma;
+
+
+  virtual int RequestInformation(vtkInformation*,
+                                 vtkInformationVector**,
+                                 vtkInformationVector*);
+
+  virtual void ThreadedRequestData(vtkInformation*,
+                                   vtkInformationVector**,
+                                   vtkInformationVector*,
+                                   vtkImageData*** inData,
+                                   vtkImageData** outData,
+                                   int outExt[6],
+                                   int threadId);
+private:
+  vtkbisImageTimeSeriesNormalize(const vtkbisImageTimeSeriesNormalize&);  // Not implemented.
+  void operator=(const vtkbisImageTimeSeriesNormalize&);  // Not implemented.
+  //int NumOfFrames;
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisIntrinsicConnMap.cpp b/bioimagesuite30_src/Connectivity/vtkbisIntrinsicConnMap.cpp
new file mode 100644
index 0000000..69ce42b
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisIntrinsicConnMap.cpp
@@ -0,0 +1,1524 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisIntrinsicConnMap.cpp
+ *
+ *  Created on: Nov 3, 2008
+ *      Author: Isabella Murphy; Xilin Shen
+ * @Input: 4D vtkImageData object of the whole image and a threshold
+ * @output: 3D vtkImageData object with sum of absolute or power value of correlation among
+ * each voxel of the image which are above the threshold.
+ * User can chose to look at only the positive correlation , only the negative correlation or both.
+ * For example, correlation of voxel 0 to each voxel is stored in output vtkImagedata voxel 0 component 0.
+ * In the output image, xyz=input dimension, component=1.
+ */
+
+#include "vtkbisIntrinsicConnMap.h"
+#include "vtkbisImageTimeSeriesNormalize.h"
+#include "vtkbisTimeSeriesCorrelation.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkObjectFactory.h"
+#include "vtkObject.h"
+#include "vtkPointData.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include <math.h>
+#include <time.h>
+#include "pxisinf.h"
+#include <fstream>
+#include <cstdlib>
+
+using namespace std;
+
+vtkbisIntrinsicConnMap::vtkbisIntrinsicConnMap()
+{
+  this->Threshold= 0.0;
+  this->ImageMask = NULL;
+  this->Range = 3;
+  this->Abs = 1;
+  this->Optimized = 1;
+  this->Type = 1;
+  this->OutData2=NULL;
+ // this->OutputRaw=0;
+  this->Mean=0.0;
+  this->Std=0.0;
+  this->DegreeMean=0.0;
+  this->DegreeStd=0.0;
+  this->FileName="";
+
+}
+
+vtkbisIntrinsicConnMap::~vtkbisIntrinsicConnMap()
+{
+  this->SetImageMask(NULL);
+  if (this->OutData2!=NULL)
+    this->OutData2->Delete();
+
+}
+void vtkbisIntrinsicConnMap::SetFileName(const char* filename)
+{
+  this->FileName=filename;
+}
+
+const char* vtkbisIntrinsicConnMap::GetFileName()
+{
+  return this->FileName.c_str();
+}
+
+vtkbisIntrinsicConnMap* vtkbisIntrinsicConnMap::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisIntrinsicConnMap");
+  if(ret)
+    {
+      return (vtkbisIntrinsicConnMap*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisIntrinsicConnMap;
+}
+//----------------------------------------------------------------------------------------------------------------------
+//RequestInformation
+//I. Our vtkImageData input has number of components = number of frames but output vtkImageData object has number of
+//components = 1.
+// ---------------------------------------------------------------------------------------------------------------------------
+int vtkbisIntrinsicConnMap::RequestInformation (vtkInformation * request,
+						vtkInformationVector ** inputVector,
+						vtkInformationVector * outputVector)
+{
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1);//set number of components to 1
+
+  return 1;
+}
+//--------------------------------------------------------------------------
+//templated function, optimized the original code
+//--------------------------------------------------------------------------
+template <class IT,class OT>
+static void vtkbisIntrinsicConnMapDoConnectivity(vtkbisIntrinsicConnMap *self,
+						 vtkImageData *inData,
+						 vtkImageData *outData,
+						 vtkImageData *OutData2,
+						 vtkImageData *maskData,
+						 IT*, OT*)
+{
+  //IT *img1 = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+  OT *msk  = NULL;
+  //if (maskData!=NULL)
+  //  msk=(OT*) maskData->GetPointData()->GetScalars()->GetVoidPointer(0);
+
+  float *count=(float*)OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+  int nt=inData->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc=inData->GetPointData()->GetScalars()->GetNumberOfComponents();
+  // Normalize input
+
+  /*  for (int i=0;i< nt;i++)
+	  {
+		int DoGlm=1;
+		if (msk!=NULL)
+		{
+			if (*msk < 1 )
+			  DoGlm=0;
+			++msk;
+		}
+		if(DoGlm)
+		{
+			double psum=0.0;
+			IT* temp=img1;
+			for (int m = 0; m < nc; m++)
+			  {
+				//GetComponent(voxel,m) Return the data component at the ith tuple and mth component
+				psum += (*temp)*(*temp);
+				++temp;
+			  }
+			double norm = sqrt(psum);
+			if(norm != 0)
+			{
+				for (int m = 0; m < nc; m++)
+				{
+					double v= double(*img1)/norm;
+					*img1= (IT)v;
+					++img1;
+				}
+			}else{
+			for (int m = 0; m < nc; m++)
+			{
+				 *img1=0;
+				 ++img1;
+			}
+			}
+      }
+      else
+      {
+		  for (int m = 0; m < nc; m++)
+		  {
+			  *img1=0;
+			  ++img1;
+		  }
+      }
+    }*/
+  //Calculation intrinsic connectivity
+  //1.move all the pointer to the front of the array
+  msk  = NULL;
+  if (maskData!=NULL)
+  {
+	  msk=(OT*) maskData->GetPointData()->GetScalars()->GetVoidPointer(0);
+  }
+
+
+
+  IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+  IT *outerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+  int Type = self->GetType();
+  float Threshold = self->GetThreshold();
+  switch(Type)
+    {
+    case 1:
+      positiveAbs(static_cast<OT *>(0),maskData,msk,self,nt,nc,static_cast<IT *>(0),inData,outerloop,Threshold,out,count);
+      break;
+    case 2:
+      positivePow(static_cast<OT *>(0),maskData,msk,self,nt,nc,static_cast<IT *>(0),inData,outerloop,Threshold,out,count);
+      break;
+    case 3:
+      negativeAbs(static_cast<OT *>(0),maskData,msk,self,nt,nc,static_cast<IT *>(0),inData,outerloop,Threshold,out,count);
+      break;
+    case 4:
+      negativePow(static_cast<OT *>(0),maskData,msk,self,nt,nc,static_cast<IT *>(0),inData,outerloop,Threshold,out,count);
+      break;
+    case 5:
+      bothAbs(static_cast<OT *>(0),maskData,msk,self,nt,nc,static_cast<IT *>(0),inData,outerloop,Threshold,out,count);
+      break;
+    case 6:
+      bothPow(static_cast<OT *>(0),maskData,msk,self,nt,nc,static_cast<IT *>(0),inData,outerloop,Threshold,out,count);
+      break;
+    }//end of Type switch
+}//end of template function
+//---------------------------------------------------------------------------
+//templated function, called when not using mask
+//---------------------------------------------------------------------------
+template <class IT>
+static void vtkbisIntrinsicConnMapDoConnectivity2(vtkbisIntrinsicConnMap *self,
+						 vtkImageData *inData,
+						 vtkImageData *outData,
+						 vtkImageData *OutData2,
+						 IT*)
+{
+  //IT *img1 = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+  float *count=(float*)OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+  int nt=inData->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc=inData->GetPointData()->GetScalars()->GetNumberOfComponents();
+  // Normalize input
+/*  for (int i=0;i< nt;i++)
+    {
+      double psum=0.0;
+      IT* temp=img1;
+      for (int m = 0; m < nc; m++)
+	{
+	  //GetComponent(voxel,m) Return the data component at the ith tuple and mth component
+	  psum += (*temp)*(*temp);
+	  ++temp;
+	}
+      double norm = sqrt(psum);
+      for (int m = 0; m < nc; m++)
+	{
+	  double v= double(*img1)/norm;
+	  *img1= (IT)v;
+	  ++img1;
+	}
+    }
+    */
+  IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+  IT *outerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+  int Type = self->GetType();
+  float Threshold = self->GetThreshold();
+  switch(Type)
+    {
+    case 1:
+      positiveAbsNoMask(self, nt, nc,static_cast<IT *>(0),inData,outerloop,Threshold,out,count);
+      break;
+    case 2:
+      positivePowNoMask(self, nt, nc,static_cast<IT *>(0),inData,outerloop,Threshold,out,count);
+      break;
+    case 3:
+      negativeAbsNoMask(self, nt, nc,static_cast<IT *>(0),inData,outerloop,Threshold,out,count);
+      break;
+    case 4:
+      negativePowNoMask(self, nt, nc,static_cast<IT *>(0),inData,outerloop,Threshold,out,count);
+      break;
+    case 5:
+      bothAbsNoMask(self, nt, nc,static_cast<IT *>(0),inData,outerloop,Threshold,out,count);
+      break;
+    case 6:
+      bothPowNoMask(self, nt, nc,static_cast<IT *>(0),inData,outerloop,Threshold,out,count);
+      break;
+    }
+}
+template <class IT>
+static void positiveAbsNoMask(vtkbisIntrinsicConnMap *self,int& nt,int& nc,IT*,vtkImageData *inData,IT *outerloop,float Threshold,IT *out,float *count)
+{
+	cout<<"no Mask, Whole, Positive, Abs"<<endl;
+	int maxcount=int(nt/10);
+	int outcount=0;
+	float pog=0.0;
+  for (int l = 0; l<nt;l++)
+    {
+      float goodSum = 0.0;
+      int counter = 0;
+      //for each voxel n
+      IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+      for (int n = 0; n<nt; n++)
+	{
+	  IT *thisvoxel = outerloop;
+	  float sum = 0;
+	  // For each component m
+	  for (int m = 0; m < nc; m++)
+	    {
+	      sum += (*thisvoxel)*(*innerloop);
+	      ++thisvoxel;
+	      ++innerloop;
+	    }
+	  sum/=nc;
+	  if (sum >= Threshold)
+	    {
+	      goodSum += sum;
+	      ++counter;
+	    }
+	}//end of the other voxel
+      *out=(IT)goodSum;
+      *count=counter;
+      ++out;
+      ++count;
+      outerloop=outerloop+nc;
+      ++outcount;
+      if (outcount==maxcount)
+      {
+    	  pog=float(l)/float(nt);
+          self->UpdateProgress(pog);
+          outcount=0;
+          fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(l)/float(nt));
+      }
+      //self->UpdateProgress(float(l+1)/float(nt)); //fprintf(stderr,"Progress = %f\n",self->GetProgress());
+    }//end of outer loop
+}
+
+template <class IT,class OT>
+static void positiveAbs(OT*,vtkImageData *maskData,OT *msk,vtkbisIntrinsicConnMap *self,int& nt,int& nc,IT*,vtkImageData *inData,IT *outerloop,float Threshold,IT *out,float *count)
+{
+	cout<<"Whole, Positive, Abs"<<endl;
+	int maxcount=int(nt/10);
+	int outcount=0;
+	float pog=0.0;
+	for (int l = 0; l<nt;l++)
+    {
+		float goodSum = 0.0;
+		int counter = 0;
+		int DoGlm=1;
+		if (msk != NULL)
+		{
+			if (*msk < 1 )
+				DoGlm=0;
+			++msk;
+		}
+		if(DoGlm)
+		{
+			//for each voxel n
+			IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+			OT *msk2  = NULL;
+			if (maskData!=NULL)
+			{
+			   msk2=(OT*) maskData->GetPointData()->GetScalars()->GetVoidPointer(0);
+			}
+			for (int n = 0; n<nt; n++)
+			{
+				IT *thisvoxel = outerloop;
+				float sum = 0;
+				int DoGlm2=1;
+				if(msk2 != NULL)
+				{
+					if (*msk2 < 1 )
+						DoGlm2=0;
+				    ++msk2;
+				}
+				if(DoGlm2)
+				{
+					// For each component m
+					for (int m = 0; m < nc; m++)
+					{
+						sum += (*thisvoxel)*(*innerloop);
+						++thisvoxel;
+						++innerloop;
+					}
+					sum/=nc;
+					if (sum >= Threshold)
+					{
+						goodSum += sum;
+						++counter;
+					}
+				}else{
+					innerloop=innerloop+nc;
+				}//end of DoGlm2
+	    }//end of the other voxel
+	}//end of DoGlm
+      *out=(IT)goodSum;
+      *count=counter;
+      ++out;
+      ++count;
+      outerloop=outerloop+nc;
+      ++outcount;
+      if (outcount==maxcount)
+      {
+          pog=float(l)/float(nt);
+          self->UpdateProgress(pog);
+          outcount=0;
+          fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(l)/float(nt));
+      }
+      //self->UpdateProgress(float(l+1)/float(nt)); //fprintf(stderr,"Progress = %f\n",self->GetProgress());
+    }//end of outer loop
+}
+
+template <class IT>
+static void positivePowNoMask(vtkbisIntrinsicConnMap *self,int& nt,int& nc,IT*,vtkImageData *inData,IT *outerloop,float Threshold,IT *out,float *count)
+{
+	cout<<"no Mask, Whole, Positive, Sqr"<<endl;
+	int maxcount=int(nt/10);
+	int outcount=0;
+	float pog=0.0;
+  for (int l = 0; l<nt;l++)
+    {
+      float goodSum = 0.0;
+      int counter = 0;
+      // For each voxel n
+      IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+      for (int n = 0; n<nt; n++)
+	{
+	  IT *thisvoxel = outerloop;
+	  float sum = 0;
+	  // For each component m
+	  for (int m = 0; m < nc; m++)
+	    {
+	      sum += (*thisvoxel)*(*innerloop);
+	      ++thisvoxel;
+	      ++innerloop;
+	    }
+	  sum/=nc;
+	  if(sum >= Threshold)
+	    {
+	      goodSum += sum*sum;
+	      ++counter;
+	    }
+	}//end of the other voxel
+      *out=(IT)goodSum;
+      *count=counter;
+      ++out;
+      ++count;
+      outerloop=outerloop+nc;
+      ++outcount;
+      if (outcount==maxcount)
+      {
+          pog=float(l)/float(nt);
+          self->UpdateProgress(pog);
+          outcount=0;
+          fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(l)/float(nt));
+      }
+      //self->UpdateProgress(float(l+1)/float(nt)); //fprintf(stderr,"Progress = %f\n",self->GetProgress());
+    }//end of outer loop
+
+}
+
+template <class IT,class OT>
+static void positivePow(OT*,vtkImageData *maskData,OT *msk,vtkbisIntrinsicConnMap *self,int& nt,int& nc,IT*,vtkImageData *inData,IT *outerloop,float Threshold,IT *out,float *count)
+{
+	cout<<"Whole, Positive, Sqr"<<endl;
+	int maxcount=int(nt/10);
+	int outcount=0;
+	float pog=0.0;
+  for (int l = 0; l<nt;l++)
+    {
+      float goodSum = 0.0;
+      int counter = 0;
+      int DoGlm=1;
+      if (msk != NULL)
+	{
+	  if (*msk < 1 )
+	    DoGlm=0;
+	  ++msk;
+	}
+      if(DoGlm)
+	{
+	  // For each voxel n
+	  IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	  OT *msk2  = NULL;
+	  if (maskData!=NULL)
+	  {
+	     msk2=(OT*) maskData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	  }
+	  for (int n = 0; n<nt; n++)
+	  {
+	      IT *thisvoxel = outerloop;
+	      float sum = 0;
+	      int DoGlm2=1;
+	      if(msk2 != NULL)
+	      {
+	    	  if (*msk2 < 1 )
+	    		  DoGlm2=0;
+	    	  ++msk2;
+	      }
+	      if(DoGlm2)
+	      {
+	    	  // For each component m
+	    	  for (int m = 0; m < nc; m++)
+	    	  {
+	    		  sum += (*thisvoxel)*(*innerloop);
+	    		  ++thisvoxel;
+	    		  ++innerloop;
+	    	  }
+	    	  sum/=nc;
+	    	  if(sum >= Threshold)
+	    	  {
+	    		  goodSum += sum*sum;
+	    		  ++counter;
+	    	  }
+	      }else{
+	    	  innerloop=innerloop+nc;
+	      }//end of DoGlm2
+	    }//end of the other voxel
+	}//end of DoGlm
+      *out=(IT)goodSum;
+      *count=counter;
+      ++out;
+      ++count;
+      outerloop=outerloop+nc;
+      ++outcount;
+      if (outcount==maxcount)
+      {
+          pog=float(l)/float(nt);
+          self->UpdateProgress(pog);
+          outcount=0;
+          fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(l)/float(nt));
+      }
+      //self->UpdateProgress(float(l+1)/float(nt)); //fprintf(stderr,"Progress = %f\n",self->GetProgress());
+    }//end of outer loop
+}
+
+template <class IT>
+static void negativeAbsNoMask(vtkbisIntrinsicConnMap *self,int& nt,int& nc,IT*,vtkImageData *inData,IT *outerloop,float Threshold,IT *out,float *count)
+{
+	cout<<"no Mask, Whole,Negative, Abs"<<endl;
+	int maxcount=int(nt/10);
+	int outcount=0;
+	float pog=0.0;
+  for (int l = 0; l<nt;l++)
+    {
+      float goodSum = 0.0;
+      int counter = 0;
+      // For each voxel n
+      IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+      for (int n = 0; n<nt; n++)
+	{
+	  IT *thisvoxel = outerloop;
+	  float sum = 0;
+	  // For each component m
+	  for (int m = 0; m < nc; m++)
+	    {
+	      sum += (*thisvoxel)*(*innerloop);
+	      ++thisvoxel;
+	      ++innerloop;
+	    }
+	  sum/=nc;
+	  if(sum <= -Threshold)
+	    {
+	      sum = sum * -1;
+	      goodSum += sum;
+	      ++counter;
+	    }
+	}//end of the other voxel
+      *out=(IT)goodSum;
+      *count=counter;
+      ++out;
+      ++count;
+      outerloop=outerloop+nc;
+      ++outcount;
+      if (outcount==maxcount)
+      {
+          pog=float(l)/float(nt);
+          self->UpdateProgress(pog);
+          outcount=0;
+          fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(l)/float(nt));
+      }
+      //self->UpdateProgress(float(l+1)/float(nt)); //fprintf(stderr,"Progress = %f\n",self->GetProgress());
+    }//end of outer loop
+}
+
+template <class IT,class OT>
+static void negativeAbs(OT*,vtkImageData *maskData,OT *msk,vtkbisIntrinsicConnMap *self,int& nt,int& nc,IT*,vtkImageData *inData,IT *outerloop,float Threshold,IT *out,float *count)
+{
+	cout<<"Whole,Negative, Abs"<<endl;
+	int maxcount=int(nt/10);
+	int outcount=0;
+	float pog=0.0;
+  for (int l = 0; l<nt;l++)
+    {
+      float goodSum = 0.0;
+      int counter = 0;
+      int DoGlm=1;
+      if (msk != NULL)
+	{
+	  if (*msk < 1 )
+	    DoGlm=0;
+	  ++msk;
+	}
+      if(DoGlm)
+	{
+	  // For each voxel n
+	  IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	  OT *msk2  = NULL;
+	  if (maskData!=NULL)
+	  {
+		  msk2=(OT*) maskData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	  }
+	  for (int n = 0; n<nt; n++)
+	  {
+	      IT *thisvoxel = outerloop;
+	      float sum = 0;
+	      int DoGlm2=1;
+	      if(msk2 != NULL)
+	      {
+	    	  if (*msk2 < 1 )
+	    		  DoGlm2=0;
+	          ++msk2;
+	      }
+	      if(DoGlm2)
+	      {
+	    	  // For each component m
+	    	  for (int m = 0; m < nc; m++)
+	    	  {
+	    		  sum += (*thisvoxel)*(*innerloop);
+	    		  ++thisvoxel;
+	    		  ++innerloop;
+	    	  }
+	    	  sum/=nc;
+	    	  if(sum <= -Threshold)
+	    	  {
+	    		  sum = sum * -1;
+	    		  goodSum += sum;
+	    		  ++counter;
+	    	  }
+	      }else{
+	    	  innerloop=innerloop+nc;
+	      }//end of DoGlm2
+	    }//end of the other voxel
+	}//end of DoGlm
+      *out=(IT)goodSum;
+      *count=counter;
+      ++out;
+      ++count;
+      outerloop=outerloop+nc;
+      ++outcount;
+      if (outcount==maxcount)
+      {
+          pog=float(l)/float(nt);
+          self->UpdateProgress(pog);
+          outcount=0;
+          fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(l)/float(nt));
+      }
+      //self->UpdateProgress(float(l+1)/float(nt)); //fprintf(stderr,"Progress = %f\n",self->GetProgress());
+    }//end of outer loop
+}
+
+template <class IT>
+static void negativePowNoMask(vtkbisIntrinsicConnMap *self,int& nt,int& nc,IT*,vtkImageData *inData,IT *outerloop,float Threshold,IT *out,float *count)
+{
+	cout<<"no Mask, Whole, Negative, Sqr"<<endl;
+	int maxcount=int(nt/10);
+	int outcount=0;
+	float pog=0.0;
+  for (int l = 0; l<nt;l++)
+    {
+      float goodSum = 0.0;
+      int counter = 0;
+      // For each voxel n
+      IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+      for (int n = 0; n<nt; n++)
+	{
+	  IT *thisvoxel = outerloop;
+	  float sum = 0;
+	  // For each component m
+	  for (int m = 0; m < nc; m++)
+	    {
+	      sum += (*thisvoxel)*(*innerloop);
+	      ++thisvoxel;
+	      ++innerloop;
+	    }
+	  sum/=nc;
+	  if (sum <= -Threshold)
+	    {
+	      goodSum += sum*sum;
+	      ++counter;
+	    }
+	}//end of the other voxel
+      *out=(IT)goodSum;
+      *count=counter;
+      ++out;
+      ++count;
+      outerloop=outerloop+nc;
+      ++outcount;
+      if (outcount==maxcount)
+      {
+          pog=float(l)/float(nt);
+          self->UpdateProgress(pog);
+          outcount=0;
+          fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(l)/float(nt));
+      }
+      //self->UpdateProgress(float(l+1)/float(nt)); //fprintf(stderr,"Progress = %f\n",self->GetProgress());
+    }//end of outer loop
+}
+
+template <class IT,class OT>
+static void negativePow(OT*,vtkImageData *maskData,OT *msk,vtkbisIntrinsicConnMap *self,int& nt,int& nc,IT*,vtkImageData *inData,IT *outerloop,float Threshold,IT *out,float *count)
+{
+	cout<<"Whole, Negative, Sqr"<<endl;
+	int maxcount=int(nt/10);
+	int outcount=0;
+	float pog=0.0;
+  for (int l = 0; l<nt;l++)
+    {
+      float goodSum = 0.0;
+      int counter = 0;
+      int DoGlm=1;
+      if (msk != NULL)
+	{
+	  if (*msk < 1 )
+	    DoGlm=0;
+	  ++msk;
+	}
+      if(DoGlm)
+	{
+	  // For each voxel n
+	  IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	  OT *msk2  = NULL;
+	  if (maskData!=NULL)
+	  {
+		  msk2=(OT*) maskData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	  }
+	  for (int n = 0; n<nt; n++)
+	  {
+	      IT *thisvoxel = outerloop;
+	      float sum = 0;
+	      int DoGlm2=1;
+	      if(msk2 != NULL)
+	      {
+	    	  if (*msk2 < 1 )
+	    		  DoGlm2=0;
+	          ++msk2;
+	      }
+	      if(DoGlm2)
+	      {
+	    	  // For each component m
+	    	  for (int m = 0; m < nc; m++)
+	    	  {
+	    		  sum += (*thisvoxel)*(*innerloop);
+	    		  ++thisvoxel;
+	    		  ++innerloop;
+	    	  }
+	    	  sum/=nc;
+	    	  if (sum <= -Threshold)
+	    	  {
+	    		  goodSum += sum*sum;
+	    		  ++counter;
+	    	  }
+	      }else{
+	    	  innerloop=innerloop+nc;
+	      }//end of DoGlm2
+	    }//end of the other voxel
+	}//end of DoGlm
+      *out=(IT)goodSum;
+      *count=counter;
+      ++out;
+      ++count;
+      outerloop=outerloop+nc;
+      ++outcount;
+      if (outcount==maxcount)
+      {
+          pog=float(l)/float(nt);
+          self->UpdateProgress(pog);
+          outcount=0;
+          fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(l)/float(nt));
+      }
+      //self->UpdateProgress(float(l+1)/float(nt)); //fprintf(stderr,"Progress = %f\n",self->GetProgress());
+    }//end of outer loop
+}
+
+template <class IT>
+static void bothAbsNoMask(vtkbisIntrinsicConnMap *self,int& nt,int& nc,IT*,vtkImageData *inData,IT *outerloop,float Threshold,IT *out,float *count)
+{
+	cout<<"no Mask, Whole,Both, Abs"<<endl;
+	int maxcount=int(nt/10);
+	int outcount=0;
+	float pog=0.0;
+  for (int l = 0; l<nt;l++)
+    {
+      float goodSum = 0.0;
+      int counter = 0;
+      // For each voxel n
+      IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+      for (int n = 0; n<nt; n++)
+	{
+	  IT *thisvoxel = outerloop;
+	  float sum = 0;
+	  // For each component m
+	  for (int m = 0; m < nc; m++)
+	    {
+	      sum += (*thisvoxel)*(*innerloop);
+	      ++thisvoxel;
+	      ++innerloop;
+	    }
+	  sum/=nc;
+	  if (sum <= -Threshold || sum >= Threshold)
+	    {
+	      if(sum <0)
+		sum = sum * -1;
+	      goodSum += sum;
+	      ++counter;
+	    }
+	}//end of the other voxel
+      *out=(IT)goodSum;
+      *count=counter;
+      ++out;
+      ++count;
+      outerloop=outerloop+nc;
+      ++outcount;
+      if (outcount==maxcount)
+      {
+          pog=float(l)/float(nt);
+          self->UpdateProgress(pog);
+          outcount=0;
+          fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(l)/float(nt));
+      }
+      //self->UpdateProgress(float(l+1)/float(nt)); //fprintf(stderr,"Progress = %f\n",self->GetProgress());
+    }//end of outer loop
+}
+
+template <class IT,class OT>
+static void bothAbs(OT*,vtkImageData *maskData,OT *msk,vtkbisIntrinsicConnMap *self,int& nt,int& nc,IT*,vtkImageData *inData,IT *outerloop,float Threshold,IT *out,float *count)
+{
+	cout<<"Whole,Both, Abs"<<endl;
+	int maxcount=int(nt/10);
+	int outcount=0;
+	float pog=0.0;
+  for (int l = 0; l<nt;l++)
+    {
+      float goodSum = 0.0;
+      int counter = 0;
+      int DoGlm=1;
+      if (msk != NULL)
+	{
+	  if (*msk < 1 )
+	    DoGlm=0;
+	  ++msk;
+	}
+      if(DoGlm)
+	{
+	  // For each voxel n
+	  IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	  OT *msk2  = NULL;
+	  if (maskData!=NULL)
+	  {
+	     msk2=(OT*) maskData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	  }
+	  for (int n = 0; n<nt; n++)
+	    {
+	      IT *thisvoxel = outerloop;
+	      float sum = 0;
+	      int DoGlm2=1;
+	      if(msk2 != NULL)
+	      {
+	    	  if (*msk2 < 1 )
+	    		  DoGlm2=0;
+	          ++msk2;
+	      }
+	      if(DoGlm2)
+	      {
+	    	  // For each component m
+	    	  for (int m = 0; m < nc; m++)
+	    	  {
+	    		  sum += (*thisvoxel)*(*innerloop);
+	    		  ++thisvoxel;
+	    		  ++innerloop;
+	    	  }
+	    	  sum/=nc;
+	    	  if (sum <= -Threshold || sum >= Threshold)
+	    	  {
+	    		  if(sum <0)
+	    			  sum = sum * -1;
+	    		  goodSum += sum;
+	    		  ++counter;
+	    	  }
+	      }else{
+	    	  innerloop=innerloop+nc;
+	      }//end of DoGlm2
+	    }//end of the other voxel
+	}//end of DoGlm
+      *out=(IT)goodSum;
+      *count=counter;
+      ++out;
+      ++count;
+      outerloop=outerloop+nc;
+      ++outcount;
+      if (outcount==maxcount)
+      {
+          pog=float(l)/float(nt);
+          self->UpdateProgress(pog);
+          outcount=0;
+          fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(l)/float(nt));
+      }
+      //self->UpdateProgress(float(l+1)/float(nt)); //fprintf(stderr,"Progress = %f\n",self->GetProgress());
+    }//end of outer loop
+}
+
+template <class IT>
+static void bothPowNoMask(vtkbisIntrinsicConnMap *self,int& nt,int& nc,IT*,vtkImageData *inData,IT *outerloop,float Threshold,IT *out,float *count)
+{
+	cout<<"no Mask, Whole, Both, Sqr"<<endl;
+	int maxcount=int(nt/10);
+	int outcount=0;
+	float pog=0.0;
+	for (int l = 0; l<nt;l++)
+    {
+      float goodSum = 0.0;
+      int counter=0;
+      // For each voxel n
+      IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+      for (int n = 0; n<nt; n++)
+      {
+	  IT *thisvoxel = outerloop;
+	  float sum = 0;
+	  // For each component m
+	  for (int m = 0; m < nc; m++)
+	    {
+	      sum += (*thisvoxel)*(*innerloop);
+	      ++thisvoxel;
+	      ++innerloop;
+	    }
+	  sum/=nc;
+	  if(sum <= -Threshold || sum >= Threshold)
+	    {
+	      goodSum += sum*sum;
+	      ++counter;
+	    }
+	}//end of the other voxel
+      *out=(IT)goodSum;
+      *count=counter;
+      ++out;
+      ++count;
+      outerloop=outerloop+nc;
+      ++outcount;
+      if (outcount==maxcount)
+      {
+    	  pog=float(l)/float(nt);
+          self->UpdateProgress(pog);
+          outcount=0;
+          fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(l)/float(nt));
+      }
+      //self->UpdateProgress(float(l+1)/float(nt)); //fprintf(stderr,"Progress = %f\n",self->GetProgress());
+    }//end of outer loop
+}
+
+template <class IT,class OT>
+static void bothPow(OT*,vtkImageData *maskData,OT *msk,vtkbisIntrinsicConnMap *self,int& nt,int& nc,IT*,vtkImageData *inData,IT *outerloop,float Threshold,IT *out,float *count)
+{
+	cout<<"Whole, Both, Sqr"<<endl;
+	int maxcount=int(nt/10);
+	int outcount=0;
+	float pog=0.0;
+	for (int l = 0; l<nt;l++)
+    {
+      float goodSum = 0.0;
+      int counter=0;
+      int DoGlm=1;
+      if (msk != NULL)
+      {
+    	  if (*msk < 1 )
+    		  DoGlm=0;
+    	  ++msk;
+      }
+      if(DoGlm)
+      {
+    	  // For each voxel n
+    	  IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+    	  OT *msk2  = NULL;
+    	  if (maskData!=NULL)
+    	  {
+    	  	  msk2=(OT*) maskData->GetPointData()->GetScalars()->GetVoidPointer(0);
+    	  }
+    	  for (int n = 0; n<nt; n++)
+    	  {
+    		  IT *thisvoxel = outerloop;
+    	      float sum = 0;
+    	      int DoGlm2=1;
+    	      if(msk2 != NULL)
+    	      {
+    	    	  if (*msk2 < 1 )
+    	    		  DoGlm2=0;
+    	    	  ++msk2;
+    	      }
+    	      if(DoGlm2)
+    	      {
+    	    	  // For each component m
+    	    	  for (int m = 0; m < nc; m++)
+    	    	  {
+    	    		  sum += (*thisvoxel)*(*innerloop);
+			  // cout<<(*thisvoxel)<<"*"<<(*innerloop)<<"\n";
+    	    		  ++thisvoxel;
+    	    		  ++innerloop;
+    	    	  }
+    	    	  sum/=nc;
+		  // cout<<"sum/nc="<<sum<<"\n";
+    	    	  if(sum <= -Threshold || sum >= Threshold)
+    	    	  {
+    	    		  goodSum += sum*sum;
+			  //cout<<sum<<"*"<<sum<<"="<<sum*sum<<"\n";
+    	    		  ++counter;
+			  //cout<<"counter:"<<counter<<"\n";
+    	    	  }
+    	      }else{
+    	    	  innerloop=innerloop+nc;
+    	      }//end of DoGlm2
+    	  }//end of the other voxel
+	}//end of DoGlm
+      *out=(IT)goodSum;
+      *count=counter;
+      //cout<<"out:"<<*out<<"count:"<<*count<<"\n";
+      ++out;
+      ++count;
+      outerloop=outerloop+nc;
+      ++outcount;
+      if (outcount==maxcount)
+      {
+    	  pog=float(l)/float(nt);
+    	  self->UpdateProgress(pog);
+      	  outcount=0;
+      	  fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(l)/float(nt));
+      }
+      //self->UpdateProgress(float(l+1)/float(nt)); //fprintf(stderr,"Progress = %f\n",self->GetProgress());
+    }//end of outer loop
+}
+
+template <class IT>
+static void vtkbisIntrinsicConnMapDoConnectivity1(vtkbisIntrinsicConnMap *self,
+						  vtkImageData *inData,
+						  vtkImageData *outData,
+						  vtkImageData *OutData2,
+						  vtkImageData *maskData,
+						  IT* )
+{
+  switch (maskData->GetScalarType())
+    {
+      vtkTemplateMacro7(vtkbisIntrinsicConnMapDoConnectivity, self, inData,outData,OutData2,maskData,
+			static_cast<IT *>(0),
+			static_cast<VTK_TT *>(0));
+    default:
+      vtkGenericWarningMacro("Execute: Unknown input ScalarType");
+      return;
+    }
+}
+// --------------------------------------------------------------------
+// Old Way
+// ---------------------------------------------------------------------
+void vtkbisIntrinsicConnMap::OldExecute(vtkImageData* input ,vtkImageData* output)
+{
+  fprintf(stderr,"vtkbisIntrinsicConnMap");
+
+  int dim[3];
+  int dimMask[3];
+  int ia;
+  int tsum = 0;
+/*
+  vtkImageCast* cast=vtkImageCast::New();
+  cast->SetInput(input);
+  cast->SetOutputScalarTypeTofloat();
+  cast->Update();
+
+  vtkImageData* inp=vtkImageData::New();
+  inp->ShallowCopy(cast->GetOutput());
+  cast->Delete();
+ */
+  vtkbisImageTimeSeriesNormalize* norm1=vtkbisImageTimeSeriesNormalize::New();
+  norm1->SetInput(input);
+  norm1->Update();
+
+  vtkImageData* inp=vtkImageData::New();
+  inp->ShallowCopy(norm1->GetOutput());
+  norm1->Delete();
+
+  vtkDataArray* temp=inp->GetPointData()->GetScalars();
+  int nt=temp->GetNumberOfTuples();//number of voxels
+  int nc=temp->GetNumberOfComponents();//number of frames (time series)
+
+  inp->GetDimensions(dim);
+  if (this->ImageMask!=NULL)
+    {
+      this->ImageMask->GetDimensions(dimMask);
+      for (ia=0;ia<=2;ia++)
+	tsum += abs(dim[ia]-dimMask[ia]);
+      if (tsum>0)
+	{
+	  fprintf(stderr,"Bad Mask Input to vtkbisIntrinsicConnMap SimpleExecute\n");
+	  return;
+	}
+    }
+
+  vtkDataArray*   mask = NULL;
+  if (this->ImageMask!=NULL)
+    mask=this->ImageMask->GetPointData()->GetScalars();
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  out->FillComponent(0,0.0);
+
+  OutData2=vtkImageData::New();
+  OutData2->SetOrigin(output->GetOrigin());
+  OutData2->SetSpacing(output->GetSpacing());
+  OutData2->SetDimensions(output->GetDimensions());
+  OutData2->SetScalarTypeToFloat();
+  OutData2->AllocateScalars();//allocation space on memery
+
+  vtkDataArray* out2=OutData2->GetPointData()->GetScalars();
+  out2->FillComponent(0,0);
+
+  float sum = 0;
+  float psum = 0;
+  float norm = 0;
+  float goodSum = 0;
+  int i,l,n,m,u,v,index;
+  this->UpdateProgress(0.01);
+  //normalize time series voxel by voxel
+/*  for (i=0;i< nt;i++)
+    {
+      psum = 0;
+      int DoGlm=1;
+      if (mask!=NULL)
+	{
+	  if (mask->GetComponent(i,0)<1)
+	    {
+	      DoGlm=0;
+	    }
+	}
+      if(DoGlm)
+	{
+	  for (m = 0; m < nc; m++)
+	    {
+	      psum += pow(temp->GetComponent(i,m),2);//GetComponent(voxel,m) Return the data component at the ith tuple and mth component
+	    }
+	  norm = sqrt(psum);
+
+	  for (m = 0; m < nc; m++)
+	    {
+	      temp->SetComponent(i,m,temp->GetComponent(i,m)/norm);
+	      //std::cout<<"t:"<<i<<"m:"<<m<<"n:"<<temp->GetComponent(i,m)<<endl;
+	    }
+	}else{
+	for (m = 0; m < nc; m++)
+	  temp->SetComponent(i,m,0);
+      }
+    }
+*/
+  //Calculation intrinsic connectivity
+  for (l = 0; l<nt;l++)
+    {
+      goodSum = 0;
+      int DoGlm=1;
+      int counter = 0;
+      if (mask != NULL)
+	{
+	  if (mask->GetComponent(l,0)<1)
+	    {
+	      DoGlm=0;
+	    }
+	}
+      if(DoGlm)
+	{
+	  for (n = 0; n<nt; n++)
+	    {
+	      sum = 0;
+	      for (m = 0; m < nc; m++)
+		{
+		  //fprintf(stderr,"Getting %d,%d and %d,%d\n",l,m,n,m);
+		  sum += temp->GetComponent(l,m)*temp->GetComponent(n,m);
+		}
+	      sum/=nc;
+	      switch(this->Range)
+		{
+		case 1:
+		  //process for >0 sum only
+		  if(sum > this->Threshold)
+		    {
+		      if(this->Abs == 1)
+			{
+			  goodSum += sum;
+			  ++counter;
+			}else{
+			goodSum += pow(sum,2);
+			++counter;
+		      }
+		    }
+		  break;
+		case 2:
+		  //process for <0 sum only
+		  if(sum < this->Threshold * -1)
+		    {
+		      if(this->Abs == 1)
+			{
+			  sum = sum * -1;
+			  goodSum += sum;
+			  ++counter;
+			}else{
+			goodSum += pow(sum,2);
+			++counter;
+		      }
+		    }
+		  break;
+		case 3:
+		  //process all sum
+		  if(sum > this->Threshold || sum < this->Threshold * -1)
+		    {
+		      if(this->Abs == 1)
+			{
+			  if(sum <0)
+			    {
+			      sum = sum * -1;
+			    }
+			  goodSum += sum;
+			  ++counter;
+			}else{
+			goodSum += pow(sum,2);
+			++counter;
+		      }
+		    }
+		}//end of switch
+	    }//end of the other voxel
+	}//end of DoGlm
+      out->SetComponent(l,0,goodSum/nt);
+      out2->SetComponent(l,0,counter/nt);
+      //std::cout<<l<<"voxel done"<<endl;
+      this->UpdateProgress(float(l+1)/float(nt));
+    }
+  this->UpdateProgress(1.0);
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisIntrinsicConnMap::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+  //fprintf(stderr," beginning vtkbisIntrinsicConnMap\n");
+
+  if (this->Optimized==0)
+    {
+      fprintf(stderr,"Running Non Optimized Code\n");
+      this->OldExecute(input,output);
+      return;
+    }
+
+  /*  vtkImageCast* cast=vtkImageCast::New();
+    cast->SetInput(input);
+    cast->SetOutputScalarTypeToFloat();
+    cast->Update();*/
+
+  vtkbisImageTimeSeriesNormalize* norm1=vtkbisImageTimeSeriesNormalize::New();
+  norm1->SetInput(input);
+  norm1->Update();
+
+  vtkImageData* inp=vtkImageData::New();
+  inp->ShallowCopy(norm1->GetOutput());
+  norm1->Delete();
+
+  /*vtkDataArray* inpinp=inp->GetPointData()->GetScalars();
+  int inpnt=inpinp->GetNumberOfTuples();//number of voxels
+  int inpnc=inpinp->GetNumberOfComponents();//number of frames
+  for(int i=0;i<inpnt;i++)
+  {
+	  for(int j=0;j<inpnc;j++)
+	  {
+		  cout<<inpinp->GetComponent(i,j)<<"\t";
+	  }
+	  cout<<"\n";
+  }*/
+
+  if (this->OutData2!=NULL)
+    this->OutData2->Delete();
+
+  OutData2=vtkImageData::New();
+  OutData2->SetDimensions(output->GetDimensions());
+  OutData2->SetSpacing(output->GetSpacing());
+  OutData2->SetOrigin(output->GetOrigin());
+  OutData2->SetNumberOfScalarComponents(output->GetNumberOfScalarComponents());
+  OutData2->SetScalarTypeToFloat();
+  OutData2->AllocateScalars();//allocation space on memery
+  OutData2->GetPointData()->GetScalars()->FillComponent(0,0.0);
+
+  int dim[3];
+  int dimMask[3];
+  int ia;
+  int tsum = 0;
+  inp->GetDimensions(dim);
+  if (this->ImageMask!=NULL)
+    {
+      this->ImageMask->GetDimensions(dimMask);
+      for (ia=0;ia<=2;ia++)
+	tsum += abs(dim[ia]-dimMask[ia]);
+      if (tsum>0)
+	{
+    	  fprintf(stderr,"Bad Mask Input to vtkbisIntrinsicConnMap SimpleExecute\n");
+    	  return;
+	}
+    }
+
+  if (this->Range == 1 ) {
+    if (this->Abs == 1 ) {
+      //PositiveAbs
+      this->Type = 1;
+    }else{
+      //PositivePow
+      this->Type= 2 ;
+    }
+  }else if ( this->Range == 2 ) {
+    if ( this->Abs == 1 ) {
+      //NegativeAbs
+      this->Type = 3;
+    }else{
+      //NegativePow
+      this->Type = 4;
+    }
+  }else{
+    if ( this->Abs == 1 ){
+      //BothAbs
+      this->Type = 5;
+    } else {
+      //BothPow
+      this->Type = 6;
+    }
+  }
+  //fprintf(stderr,"running vtkbisIntrinsicConnMap use type=%d threshold=%.2f range=%d abs=%d optimize=%d\n",
+	//  this->Type,this->Threshold,this->Range,this->Abs,this->Optimized);
+
+  this->UpdateProgress(0.01);
+  time_t start,end;
+  time(&start);
+
+  if(this->ImageMask!=NULL)
+    {
+      switch (inp->GetScalarType())
+	{
+	  vtkTemplateMacro6(vtkbisIntrinsicConnMapDoConnectivity1,this,
+			    inp, output, OutData2,
+			    this->ImageMask,static_cast<VTK_TT *>(0));
+	default:
+	  vtkErrorMacro(<< "Execute: Unknown ScalarType");
+	  return;
+	}
+    }else{
+    switch (inp->GetScalarType())
+      {
+	vtkTemplateMacro5(vtkbisIntrinsicConnMapDoConnectivity2,this,
+			  inp,output,OutData2,static_cast<VTK_TT *>(0));
+      default:
+	vtkErrorMacro(<< "Execute: Unknown ScalarType");
+	return;
+      }
+  }
+//normalize the output spatial wise
+  vtkDataArray* msk=NULL;
+  if (this->ImageMask!=NULL)
+    msk=this->ImageMask->GetPointData()->GetScalars();
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  	int nt = out->GetNumberOfTuples();
+
+  int counter=0;
+  double sum=0.0,sum2=0.0;
+  for(int i=0;i<nt;i++)
+  {
+
+  	int doAlg=1;
+  	if (msk!=NULL)
+  	{
+  		if (msk->GetComponent(i,0)<1)
+  			doAlg=0;
+  	}
+  	if (doAlg)
+  	{
+  		++counter;
+  		double v=out->GetComponent(i,0);
+  		sum+=v;
+  		sum2+=v*v;
+  	}
+  }
+  double scalefactor=1.0/(double)counter;
+  double mean=sum*scalefactor;
+  double sigma=sqrt(sum2*scalefactor-mean*mean);
+  if (sigma<0.00001)
+	  sigma=1.0;
+  if (isnan(sigma) || isinf(sigma))
+	  sigma=1.0;
+  if (isnan(mean) || isinf(mean))
+	  mean=0.0;
+  //double sumx=0.0;
+  for(int i=0;i<nt;i++)
+  {
+	  int doAlg=1;
+	  if (msk!=NULL)
+	  {
+		  if (msk->GetComponent(i,0)<1)
+			  doAlg=0;
+	  }
+	  if (doAlg)
+	  {
+		  //double x = (out->GetComponent(i,0)-mean)/sigma;
+
+		  //std::cout<<"frame2:"<<j<<"x"<<x<<endl;
+		  out->SetComponent(i,0,(out->GetComponent(i,0)-mean)/sigma);
+		  //std::cout<<out->GetComponent(i,0)<<"@"<<x<<"%";
+		  //sumx+=x*x;
+	  }
+
+  }
+  this->Mean=mean;
+  this->Std=sigma;
+  		//std::cout<<"sumx"<<sumx<<endl;
+  		//std::cout<<"number of tuples in the mask:"<<counter<<endl;
+  if (this->Threshold != 0)
+  	{
+  		//normalize the count output spatial wise
+
+
+  		vtkDataArray* out2=this->OutData2->GetPointData()->GetScalars();
+  		int nt = out2->GetNumberOfTuples();
+
+
+  		int counter=0;
+  		sum=0.0,sum2=0.0;
+  		for(int i=0;i<nt;i++)
+  		{
+  		  	int doAlg=1;
+  		  	if (msk!=NULL)
+  		  	{
+  		  		if (msk->GetComponent(i,0)<1)
+  		  			doAlg=0;
+  		  	}
+  		  	if (doAlg)
+  		  	{
+  		  		++counter;
+  		  		double v=(double)out2->GetComponent(i,0);
+  		  		//std::cout<<v<<"|";
+  		  		sum+=v;
+  		  		sum2+=v*v;
+  		  	}
+  		  }
+  		  double scalefactor=1.0/(double)counter;
+  		  double mean=sum*scalefactor;
+  		  double sigma=sqrt(sum2*scalefactor-mean*mean);
+  		  if (sigma<0.00001)
+  			  sigma=1.0;
+  		  if (isnan(sigma) || isinf(sigma))
+  			  sigma=1.0;
+  		  if (isnan(mean) || isinf(mean))
+  			  mean=0.0;
+  		  //double sumx=0.0;
+  		  for(int i=0;i<nt;i++)
+  		  {
+  			  int doAlg=1;
+  			  if (msk!=NULL)
+  			  {
+  				  if (msk->GetComponent(i,0)<1)
+  					  doAlg=0;
+  			  }
+  			  if (doAlg)
+  			  {
+  				  //double x = (out2->GetComponent(i,0)-mean)/sigma;
+  				  //std::cout<<"frame2:"<<j<<"x"<<x<<endl;
+  				  out2->SetComponent(i,0,(out2->GetComponent(i,0)-mean)/sigma);
+  				  //sumx+=x*x;
+  			  }
+
+  		  }
+  		  this->DegreeMean=mean;
+  		  this->DegreeStd=sigma;
+  		  		//std::cout<<"sumx"<<sumx<<endl;
+  		  		//std::cout<<"number of tuples :"<<counter<<endl;
+  	}
+
+
+
+/*
+  if (this->FileName=="")
+    return;
+
+  std::ofstream myfile(this->FileName.c_str());
+  if(!myfile.is_open())
+    {
+      cout<< "Unable to open text file" << this->FileName << "\n";
+      return;
+    }
+  myfile<<"Mean: \t "<<this->Mean<<"\t"<<"Standard Deviation: \t "<<this->Std<<"Number of Voxels: \t "<<counter<<"\n";
+  if (this->Threshold != 0)
+    {
+      myfile<<"Degree Mean: \t "<<this->DegreeMean<<"\t"<<"Degree Standard Deviation: \t "<<this->DegreeStd<<"\n";
+    }
+
+  myfile.close();
+
+*/
+/*  vtkDataArray* dat=output->GetPointData()->GetScalars();
+  vtkDataArray* cnt=OutData2->GetPointData()->GetScalars();
+  int nt=dat->GetNumberOfTuples();
+
+  for (int i=0;i<nt;i++)
+  {
+      float c=cnt->GetComponent(i,0);
+      if (isnan(c) || isinf(c) || c<1.0)
+      {
+    	  cnt->SetComponent(i,0,0.0);
+    	  dat->SetComponent(i,0,0.0);
+      }
+      else
+      {
+    	  if (this->OutputRaw)
+    		  dat->SetComponent(i,0,dat->GetComponent(i,0)/c);
+    	  else
+    		  dat->SetComponent(i,0,vtkbisTimeSeriesCorrelation::RhoToZConversion(dat->GetComponent(i,0)/c));
+      }
+  }
+
+*/
+  time(&end);
+  std::cout<<endl<<"elapsed time "<<difftime(end, start)<<" seconds"<<endl;
+  this->UpdateProgress(1.0);
+
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisIntrinsicConnMap.h b/bioimagesuite30_src/Connectivity/vtkbisIntrinsicConnMap.h
new file mode 100644
index 0000000..2c2a3b2
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisIntrinsicConnMap.h
@@ -0,0 +1,142 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisIntrinsicConnMap.h
+ *
+ *  Created on: Nov 3, 2008
+ *      Author: Isabella Murphy, Xilin Shen
+ *      given a set of time courses compute intrinsic connectivity mapping
+ *      @Input: a 4D vtkImageData object (Brain image) with time courses
+ *      @Output: a 3D vtkImageData object with intrinsic connectivity mapping
+ */
+
+#ifndef VTKBISINTRINSICCONNMAP_H_
+#define VTKBISINTRINSICCONNMAP_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include <string>
+#include <iostream>
+
+class vtkInformation;
+class vtkInformationVector;
+
+class vtkbisIntrinsicConnMap : public vtkSimpleImageToImageFilter{
+
+public:
+  static vtkbisIntrinsicConnMap *New();
+  vtkTypeMacro(vtkbisIntrinsicConnMap,vtkSimpleImageToImageFilter);
+
+  // Threshold
+  vtkSetClampMacro(Threshold,float,0.0,1.0);
+  vtkGetMacro(Threshold,float);
+
+  // Mask Image
+  vtkSetObjectMacro(ImageMask,vtkImageData);
+  vtkGetObjectMacro(ImageMask,vtkImageData);
+
+  //Second Output Image
+  vtkSetObjectMacro(OutData2,vtkImageData);
+  vtkGetObjectMacro(OutData2,vtkImageData);
+
+  //Range
+  vtkSetClampMacro(Range,int,1,3);
+  vtkGetMacro(Range,int);
+
+  //Abs
+  vtkSetClampMacro(Abs,int,1,2);
+  vtkGetMacro(Abs,int);
+
+  //OutputRaw
+  //vtkSetClampMacro(OutputRaw,int,0,1);
+  //vtkGetMacro(OutputRaw,int);
+
+  //lookN
+  vtkSetClampMacro(Optimized,int,0,1);
+  vtkGetMacro(Optimized,int);
+
+  //Type
+  vtkSetClampMacro(Type,int,1,9);
+  vtkGetMacro(Type,int);
+
+  // File name
+  virtual void SetFileName(const char* filename);
+  virtual const char* GetFileName();
+
+  //Mean
+  vtkSetMacro(Mean,double);
+  vtkGetMacro(Mean,double);
+
+  //Std
+  vtkSetMacro(Std,double);
+  vtkGetMacro(Std,double);
+
+  //Mean of degree
+  vtkSetMacro(DegreeMean,double);
+  vtkGetMacro(DegreeMean,double);
+
+  //Std of degree
+  vtkSetMacro(DegreeStd,double);
+  vtkGetMacro(DegreeStd,double);
+
+
+protected:
+  vtkbisIntrinsicConnMap();
+  virtual ~vtkbisIntrinsicConnMap();
+  virtual int RequestInformation (vtkInformation * request,
+				  vtkInformationVector ** inputVector,
+				  vtkInformationVector * outputVector) ;
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual void OldExecute(vtkImageData* input,vtkImageData* output);
+
+private:
+  vtkbisIntrinsicConnMap(const vtkbisIntrinsicConnMap& src){};
+  vtkbisIntrinsicConnMap& operator=(const vtkbisIntrinsicConnMap& rhs){};
+  float Threshold;
+  vtkImageData* ImageMask;
+  vtkImageData* OutData2;
+  int Range;
+  int Abs;
+  //int LookN;
+  int Optimized;
+  int Type;
+  //int OutputRaw;
+  //BTX
+  std::string FileName;
+  //ETX
+  double Mean;
+  double Std;
+  double DegreeMean;
+  double DegreeStd;
+
+};
+
+#endif /* VTKBISINTRINSICCONNMAP_H_ */
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisIpsilateralConnMap.cpp b/bioimagesuite30_src/Connectivity/vtkbisIpsilateralConnMap.cpp
new file mode 100644
index 0000000..e746816
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisIpsilateralConnMap.cpp
@@ -0,0 +1,2780 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisIpsilateralConnMap.cpp
+ *
+ *  Created on: Nov 13, 2008
+ *      Author: Isabella Murphy, Xilin Shen
+ * @Input: 4D vtkImageData object of the whole brain
+ * @output: 3D vtkImageData object with sum of absolute or power value of correlation among
+ * each voxel of the same side of the brain.
+ * User can chose to look at only the positive correlation , only the negative correlation or both.
+ * For example, correlation of voxel 0 to each voxel is stored in output vtkImagedata voxel 0 component 0.
+ * In the output image, xyz=input dimension, component=1.
+ * @mask: if want to use mask to distinguish left and right brain, 0 is background, 1 is right brain, 2 is left brain
+ */
+
+#include <vtkbisIpsilateralConnMap.h>
+#include "vtkbisImageTimeSeriesNormalize.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkObjectFactory.h"
+#include "vtkObject.h"
+#include "vtkPointData.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include <math.h>
+#include <vector>
+#include <time.h>
+#include "vtkbisTimeSeriesCorrelation.h"
+#include "pxisinf.h"
+#include <fstream>
+#include <cstdlib>
+
+using namespace std;
+
+vtkbisIpsilateralConnMap::vtkbisIpsilateralConnMap() {
+	this->Threshold= 0.0;
+	this->ImageMask = NULL;
+	this->Range = 3;
+	this->Abs = 1;
+	this->Optimize = 1;
+	this->Type = 1;
+	this->OutData2=NULL;
+//	this->OutputRaw=0;
+	this->DoContralateral=0;
+	this->LMean=0.0;
+	this->LStd=0.0;
+	this->RMean=0.0;
+	this->RStd=0.0;
+	this->LDegreeMean=0.0;
+	this->LDegreeStd=0.0;
+	this->RDegreeMean=0.0;
+	this->RDegreeStd=0.0;
+	this->FileName="";
+}
+
+vtkbisIpsilateralConnMap::~vtkbisIpsilateralConnMap() {
+	this->SetImageMask(NULL);
+	if (this->OutData2!=NULL)
+	  this->OutData2->Delete();
+
+}
+
+
+vtkbisIpsilateralConnMap* vtkbisIpsilateralConnMap::New()
+{
+	// First try to create the object from the vtkObjectFactory
+	vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisIpsilateralConnMap");
+	if(ret)
+    {
+		return (vtkbisIpsilateralConnMap*)ret;
+    }
+	// If the factory was unable to create the object, then create it here.
+	return new vtkbisIpsilateralConnMap;
+}
+void vtkbisIpsilateralConnMap::SetFileName(const char* filename)
+{
+  this->FileName=filename;
+}
+
+const char* vtkbisIpsilateralConnMap::GetFileName()
+{
+  return this->FileName.c_str();
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+//RequestInformation
+//I. Our vtkImageData input has number of components = number of frames but output vtkImageData object has number of
+//components = 1.
+// ---------------------------------------------------------------------------------------------------------------------------
+int vtkbisIpsilateralConnMap::RequestInformation (vtkInformation * request,
+			vtkInformationVector ** inputVector,
+			vtkInformationVector * outputVector)
+{
+	vtkInformation *outInfo = outputVector->GetInformationObject(0);
+	vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1);//set number of components to 1
+
+	return 1;
+}
+
+float vtkbisIpsilateralConnMap::CalculateGoodSum (float sum,int& count)
+{
+	float fsum = 0;
+	switch(this->Range)
+	{
+	case 1://process for >0 sum only
+		if(sum >= this->Threshold)
+		{
+			fsum = pow(sum,2);
+			if(this->Abs == 1)
+			{
+				fsum = sum;
+			}
+			++count;
+		}
+	    break;
+	case 2://process for <0 sum only
+		if(sum <= this->Threshold * -1)
+		{
+			fsum= pow(sum,2);
+			if(this->Abs == 1)
+			{
+				sum = sum * -1;
+				fsum = sum;
+			}
+			++count;
+		}
+		break;
+	case 3://process all sum
+		if(sum >= this->Threshold || sum <= this->Threshold * -1)
+		{
+			fsum = pow(sum,2);
+			if(this->Abs == 1)
+			{
+				if(sum <0)
+				{
+					sum = sum * -1;
+					fsum = sum;
+				}
+			}
+			++count;
+		}
+		break;
+	default:
+		std::cout<<"Something wrong with the range selection"<<endl;
+	}//end of switch
+	return fsum;
+}
+//templated function, optimized the original code
+template <class IT,class OT>
+static void vtkbisIpsilateralConnMapDoConnectivity(vtkbisIpsilateralConnMap *self,
+						 vtkImageData *inData,
+						 vtkImageData *outData,
+						 vtkImageData *OutData2,
+						 vtkImageData *maskData,
+						 IT*, OT*)
+{
+  IT *img1 = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+  OT *msk  = NULL;
+  if (maskData!=NULL)
+    msk=(OT*)maskData->GetPointData()->GetScalars()->GetVoidPointer(0);
+  int nt=inData->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc=inData->GetPointData()->GetScalars()->GetNumberOfComponents();
+  // ------------------------------------------------------------------------------
+  // Normalization Code
+  // ------------------------------------------------------------------------------
+
+/*  for (int i=0;i< nt;i++)
+  {
+	  int DoGlm=1;
+      if (msk!=NULL)
+      {
+    	  if (*msk < 1 )
+    		  DoGlm=0;
+    	  ++msk;
+      }
+      if(DoGlm)
+      {
+    	  float psum=0.0;
+	      IT* temp=img1;
+	      for (int m = 0; m < nc; m++)
+	      {
+	        //GetComponent(voxel,m) Return the data component at the ith tuple and mth component
+	        psum += (*temp)*(*temp);
+	        ++temp;
+	      }
+	      float norm = sqrt(psum);
+
+	      if (norm != 0)
+	      {
+	    	  for (int m = 0; m < nc; m++)
+	    	  {
+	    		  float v= float(*img1)/norm;
+	    		  *img1= (IT)v;
+	    		  //cout<<"psum:"<<psum<<"norm"<<norm<<"img:"<<*img1;
+	    		  ++img1;
+	    	  }
+		  }else{
+			  for (int m=0;m<nc;m++)
+			  {
+				  *img1=0;
+				  ++img1;
+			  }
+	      }
+	  }
+      else
+	  {
+	    for (int m = 0; m < nc; m++)
+	      {
+	        *img1=0;
+	        ++img1;
+	       }
+	   }
+    }*/
+
+	double position[3],spacing[3];
+	int dim[3];
+	vector<int> lbrain,rbrain;
+	inData->GetSpacing(spacing);
+	inData->GetDimensions(dim);
+	msk  = NULL;
+
+	//int usemaskforleftright=0;
+
+	if (maskData!=NULL)
+	  {
+	    msk=(OT*) maskData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	    double r[2];
+	    maskData->GetPointData()->GetScalars()->GetRange(r);
+	    if (r[0]==0.0 && r[1]!=200.0)
+	    {
+	    	cout<<"Invalid mask. User needs to provide a mask with 0 = background, 100 = right brain, 200 = left brain";
+	    	return;
+	    }
+	      //usemaskforleftright=1;
+	  }
+
+	//-------------------------------------------------------
+	//sort voxel to left or right brain vector
+	//------------------------------------------
+	for(int t= 0; t < nt; t++)
+	  {
+	    int DoGlm=1;
+	    if (msk!=NULL)
+	    {
+	    	if (*msk < 1 )
+	    	{
+	    		DoGlm=0;
+	    		++msk;
+	    	}
+
+	    }
+	    if(DoGlm)
+	    {
+	    	/*if (usemaskforleftright==0)
+	    	{
+	    		inData->GetPoint(t,position);
+	    		if( position[0]/spacing[0] > (dim[0]-1)/2 )
+	    		{
+	    			lbrain.push_back(t);
+	    			//std::cout<<"lb:"<<t;
+	    		}else{
+	    			rbrain.push_back(t);
+		      //std::cout<<"rb"<<t;
+	    		}
+	    		++msk;
+
+	    	}*/
+	    	//else
+	    	//{
+	    		if (*msk == 100){
+	    			rbrain.push_back(t);
+	    			//std::cout<<"rb:"<<t;
+	    		}
+
+	    		else{
+	    			lbrain.push_back(t);
+	    			//std::cout<<"lb"<<t;
+	    		}
+	    		++msk;
+
+
+	    	//}
+	    }
+	 }
+	self->SetLSize(lbrain.size());
+	self->SetRSize(rbrain.size());
+	//cout<<"lb:"<<lbrain.size()<<"rb:"<<rbrain.size()<<endl;
+
+
+
+	//clean up the output images
+	outData->GetPointData()->GetScalars()->FillComponent(0,0.0);
+	OutData2->GetPointData()->GetScalars()->FillComponent(0,0.0);
+
+	int Type = self->GetType();
+	float Threshold = self->GetThreshold();
+	if(self->GetDoContralateral() == 0)
+	{
+		switch(Type)
+		{
+			case 1:
+				positiveAbs(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 2:
+				positivePow(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 3:
+				negativeAbs(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 4:
+				negativePow(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 5:
+				bothAbs(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 6:
+				bothPow(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+		}
+	}else{
+		switch(Type)
+		{
+			case 1:
+				ConpositiveAbs(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 2:
+				ConpositivePow(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 3:
+				ConnegativeAbs(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 4:
+				ConnegativePow(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 5:
+				ConbothAbs(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 6:
+				ConbothPow(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+		}
+	}
+	//normalize left brain output
+	vtkDataArray* out=outData->GetPointData()->GetScalars();
+	double sum=0.0,sum2=0.0;
+	for(int i=0;i<lbrain.size();i++)
+	{
+		double v=out->GetComponent(lbrain[i],0);
+		//std::cout<<"frame:"<<j<<"v:"<<v;
+		sum+=v;
+		sum2+=v*v;
+	}
+	double scalefactor=1.0/(double)lbrain.size();
+	double mean=sum*scalefactor;
+	double sigma=sqrt(sum2*scalefactor-mean*mean);
+	//std::cout<<"m:"<<mean<<"s"<<sigma;
+	if (sigma<0.00001)
+		sigma=1.0;
+	if (isnan(sigma) || isinf(sigma))
+		sigma=1.0;
+	if (isnan(mean) || isinf(mean))
+		mean=0.0;
+	//double	sumx = 0;
+	for(int i=0;i<lbrain.size();i++)
+	{
+		out->SetComponent(lbrain[i],0,(out->GetComponent(lbrain[i],0)-mean)/sigma);
+	}
+	self->SetLMean(mean);
+	self->SetLStd(sigma);
+
+
+	//normalize right brain output
+	sum=0.0;sum2=0.0;
+	for(int i=0;i<rbrain.size();i++)
+	{
+		double v=out->GetComponent(rbrain[i],0);
+		//std::cout<<"frame:"<<j<<"v:"<<v;
+		sum+=v;
+		sum2+=v*v;
+	}
+	scalefactor=1.0/(double)rbrain.size();
+	mean=sum*scalefactor;
+	sigma=sqrt(sum2*scalefactor-mean*mean);
+	//std::cout<<"m:"<<mean<<"s"<<sigma;
+	if (sigma<0.00001)
+		sigma=1.0;
+	if (isnan(sigma) || isinf(sigma))
+		sigma=1.0;
+	if (isnan(mean) || isinf(mean))
+		mean=0.0;
+	//double sumx = 0;
+
+	for(int i=0;i<rbrain.size();i++)
+	{
+		//double x = (out->GetComponent(rbrain[i],0)-mean)/sigma;
+		//std::cout<<"frame2:"<<j<<"x"<<x<<endl;
+		out->SetComponent(rbrain[i],0,(out->GetComponent(rbrain[i],0)-mean)/sigma);
+		//sumx+=x*x;
+	}
+	//std::cout<<"rbrain size:"<<rbrain.size()<<endl;
+	//std::cout<<"sumx"<<sumx<<endl;
+	self->SetRMean(mean);
+	self->SetRStd(sigma);
+
+
+	if (Threshold != 0)
+	{
+		//normalize left brain degree output
+		vtkDataArray* out2=OutData2->GetPointData()->GetScalars();
+
+		double sum=0.0,sum2=0.0;
+		for(int i=0;i<lbrain.size();i++)
+		{
+			double v2=out2->GetComponent(lbrain[i],0);
+			//std::cout<<"frame:"<<j<<"v:"<<v;
+			sum+=v2;
+			sum2+=v2*v2;
+		}
+		double scalefactor=1.0/(double)lbrain.size();
+		double mean=sum*scalefactor;
+		double sigma=sqrt(sum2*scalefactor-mean*mean);
+		//std::cout<<"m:"<<mean<<"s"<<sigma;
+		if (sigma<0.00001)
+			sigma=1.0;
+		if (isnan(sigma) || isinf(sigma))
+			sigma=1.0;
+		if (isnan(mean) || isinf(mean))
+			mean=0.0;
+		//double	sumx = 0;
+		for(int i=0;i<lbrain.size();i++)
+		{
+			//double x = (out2->GetComponent(lbrain[i],0)-mean)/sigma;
+			out2->SetComponent(lbrain[i],0,(out2->GetComponent(lbrain[i],0)-mean)/sigma);
+			//sumx+=x*x;
+		}
+		//std::cout<<"lbrain size:"<<lbrain.size()<<endl;
+		//std::cout<<"sumx"<<sumx<<endl;
+		self->SetLDegreeMean(mean);
+		self->SetLDegreeStd(sigma);
+
+		//normalize right brain degree output
+		sum=0.0;sum2=0.0;
+		for(int i=0;i<rbrain.size();i++)
+		{
+			double v2=out2->GetComponent(rbrain[i],0);
+			//std::cout<<"frame:"<<j<<"v:"<<v;
+			sum+=v2;
+			sum2+=v2*v2;
+		}
+		scalefactor=1.0/(double)rbrain.size();
+		mean=sum*scalefactor;
+		sigma=sqrt(sum2*scalefactor-mean*mean);
+		//std::cout<<"m:"<<mean<<"s"<<sigma;
+		if (sigma<0.00001)
+			sigma=1.0;
+		if (isnan(sigma) || isinf(sigma))
+			sigma=1.0;
+		if (isnan(mean) || isinf(mean))
+			mean=0.0;
+		//double sumx = 0;
+
+		for(int i=0;i<rbrain.size();i++)
+		{
+			//double x = (out2->GetComponent(rbrain[i],0)-mean)/sigma;
+			//std::cout<<"frame2:"<<j<<"x"<<x<<endl;
+			out2->SetComponent(rbrain[i],0,(out2->GetComponent(rbrain[i],0)-mean)/sigma);
+			//sumx+=x*x;
+		}
+		//std::cout<<"rbrain size:"<<rbrain.size()<<endl;
+		//std::cout<<"sumx"<<sumx<<endl;
+		self->SetRDegreeMean(mean);
+		self->SetRDegreeStd(sigma);
+
+	}
+
+
+
+	//-----------------------------------------------------
+	//left brain intrinsic connectivity calculation
+	//-----------------------------------------------------
+
+/*	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *lptr = &lbrain[0];int *oldptr;
+
+	//move pointer point to the first voxel of left brain on the output array
+	out = out + (*lptr);
+	count = count + (*lptr);
+
+	for(int lb=0;lb<lbrain.size();lb++)//lptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &lbrain[0];
+
+		for(int lbf=0;lbf<lbrain.size();lbf++)//lptrf counting
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+
+			//inner loop pointer move to the beginning of the next voxel's time series
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			//self->OverThreshold(sum,counter);
+			goodSum +=self->CalculateGoodSum(sum,counter);
+			++lptrf;
+		}
+		//write results to output arrays
+		*out=(IT)goodSum/lbrain.size();
+		*count=(float)counter/lbrain.size();
+
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+
+		self->UpdateProgress(float(lb+1)/float(nt));
+		//sstd::cout<<"lv: "<<lbrain[lb];
+	}//end of left brain
+
+	//-----------------------------------------------------
+	//right brain intrinsic connectivity calculation
+	//-----------------------------------------------------
+	out =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *rptr = &rbrain[0];
+	out = out + (*rptr);
+	count = count + (*rptr);
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &rbrain[0];
+		for(int rbf=0;rbf<rbrain.size();rbf++)//lptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			//self->OverThreshold(sum,counter);
+			goodSum +=self->CalculateGoodSum(sum,counter);
+			++rptrf;
+			}
+			*out=(IT)goodSum/rbrain.size();
+			*count=(float)counter/rbrain.size();
+			oldptr = rptr;
+			++rptr;
+			out = out + ((*rptr)-(*oldptr));
+			count= count + ((*rptr)-(*oldptr));
+			//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+			self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+			//std::cout<<"rv: "<<rbrain[rb];
+		}//end of right brain
+		*/
+}//end of template function
+//--------------------------------------------------------------------------------
+//templated function invoked when mask is not used
+//-----------------------------------------------------------------------------
+template <class IT>
+static void vtkbisIpsilateralConnMapDoConnectivity2(vtkbisIpsilateralConnMap *self,
+						  vtkImageData *inData,
+						  vtkImageData *outData,
+						  vtkImageData *OutData2,
+						  IT* )
+{
+	IT *img1 = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int nt=inData->GetPointData()->GetScalars()->GetNumberOfTuples();
+	int nc=inData->GetPointData()->GetScalars()->GetNumberOfComponents();
+	// Normalize the time course
+/*	for (int i=0;i< nt;i++)
+	{
+		float psum=0.0;
+		IT* temp=img1;
+		for (int m = 0; m < nc; m++)
+		{
+			//GetComponent(voxel,m) Return the data component at the ith tuple and mth component
+		    psum += (*temp)*(*temp);
+		    ++temp;
+		}
+		float norm = sqrt(psum);
+		if (norm != 0 )
+		{
+			for (int m = 0; m < nc; m++)
+			{
+				float v= float(*img1)/norm;
+				*img1= (IT)v;
+				++img1;
+			}
+		}else{
+			for (int m = 0; m < nc; m++)
+			{
+				*img1= 0;
+				++img1;
+			}
+		}
+	}*/
+	//sort voxel to left or right brain vector
+	double position[3],spacing[3];
+	int dim[3];
+	vector<int> lbrain,rbrain;
+	inData->GetSpacing(spacing);
+	inData->GetDimensions(dim);
+	for(int t= 0; t < nt; t++)
+	{
+		inData->GetPoint(t,position);
+		if( position[0]/spacing[0] > (dim[0]-1)/2 )
+		{
+			lbrain.push_back(t);
+			//std::cout<<"lb:"<<t;
+		}else{
+			rbrain.push_back(t);
+			//std::cout<<"rb"<<t;
+		}
+	}
+	self->SetLSize(lbrain.size());
+	self->SetRSize(rbrain.size());
+	//clean up the output images
+	outData->GetPointData()->GetScalars()->FillComponent(0,0.0);
+	OutData2->GetPointData()->GetScalars()->FillComponent(0,0.0);
+
+	int Type = self->GetType();
+	float Threshold = self->GetThreshold();
+	if(self->GetDoContralateral() == 0)
+	{
+		switch(Type)
+		{
+			case 1:
+				positiveAbs(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 2:
+				positivePow(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 3:
+				negativeAbs(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 4:
+				negativePow(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 5:
+				bothAbs(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 6:
+				bothPow(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+		}
+	}else{
+		switch(Type)
+		{
+			case 1:
+				ConpositiveAbs(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 2:
+				ConpositivePow(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 3:
+				ConnegativeAbs(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 4:
+				ConnegativePow(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 5:
+				ConbothAbs(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+			case 6:
+				ConbothPow(self,inData,outData,OutData2,static_cast<IT *>(0),lbrain,rbrain,nc,nt,Threshold);
+				break;
+		}
+	}
+	//normalize left brain output
+		vtkDataArray* out=outData->GetPointData()->GetScalars();
+		double sum=0.0,sum2=0.0;
+		for(int i=0;i<lbrain.size();i++)
+		{
+			double v=out->GetComponent(lbrain[i],0);
+			//std::cout<<"frame:"<<j<<"v:"<<v;
+			sum+=v;
+			sum2+=v*v;
+		}
+		double scalefactor=1.0/(double)lbrain.size();
+		double mean=sum*scalefactor;
+		double sigma=sqrt(sum2*scalefactor-mean*mean);
+		//std::cout<<"m:"<<mean<<"s"<<sigma;
+		if (sigma<0.00001)
+			sigma=1.0;
+		if (isnan(sigma) || isinf(sigma))
+			sigma=1.0;
+		if (isnan(mean) || isinf(mean))
+			mean=0.0;
+		//double	sumx = 0;
+		for(int i=0;i<lbrain.size();i++)
+		{
+			out->SetComponent(lbrain[i],0,(out->GetComponent(lbrain[i],0)-mean)/sigma);
+		}
+		self->SetLMean(mean);
+		self->SetLStd(sigma);
+
+		//normalize right brain output
+		sum=0.0;sum2=0.0;
+		for(int i=0;i<rbrain.size();i++)
+		{
+			double v=out->GetComponent(rbrain[i],0);
+			//std::cout<<"frame:"<<j<<"v:"<<v;
+			sum+=v;
+			sum2+=v*v;
+		}
+		scalefactor=1.0/(double)rbrain.size();
+		mean=sum*scalefactor;
+		sigma=sqrt(sum2*scalefactor-mean*mean);
+		//std::cout<<"m:"<<mean<<"s"<<sigma;
+		if (sigma<0.00001)
+			sigma=1.0;
+		if (isnan(sigma) || isinf(sigma))
+			sigma=1.0;
+		if (isnan(mean) || isinf(mean))
+			mean=0.0;
+		//double sumx = 0;
+
+		for(int i=0;i<rbrain.size();i++)
+		{
+			//double x = (out->GetComponent(rbrain[i],0)-mean)/sigma;
+			//std::cout<<"frame2:"<<j<<"x"<<x<<endl;
+			out->SetComponent(rbrain[i],0,(out->GetComponent(rbrain[i],0)-mean)/sigma);
+			//sumx+=x*x;
+		}
+		self->SetRMean(mean);
+		self->SetRStd(sigma);
+		//std::cout<<"rbrain size:"<<rbrain.size()<<endl;
+		//std::cout<<"sumx"<<sumx<<endl;
+
+
+		if (Threshold != 0)
+		{
+			//normalize left brain degree output
+			vtkDataArray* out2=OutData2->GetPointData()->GetScalars();
+
+			double sum=0.0,sum2=0.0;
+			for(int i=0;i<lbrain.size();i++)
+			{
+				double v2=out2->GetComponent(lbrain[i],0);
+				//std::cout<<"frame:"<<j<<"v:"<<v;
+				sum+=v2;
+				sum2+=v2*v2;
+			}
+			double scalefactor=1.0/(double)lbrain.size();
+			double mean=sum*scalefactor;
+			double sigma=sqrt(sum2*scalefactor-mean*mean);
+			//std::cout<<"m:"<<mean<<"s"<<sigma;
+			if (sigma<0.00001)
+				sigma=1.0;
+			if (isnan(sigma) || isinf(sigma))
+				sigma=1.0;
+			if (isnan(mean) || isinf(mean))
+				mean=0.0;
+			//double	sumx = 0;
+			for(int i=0;i<lbrain.size();i++)
+			{
+				//double x = (out2->GetComponent(lbrain[i],0)-mean)/sigma;
+				out2->SetComponent(lbrain[i],0,(out2->GetComponent(lbrain[i],0)-mean)/sigma);
+				//sumx+=x*x;
+			}
+			//std::cout<<"lbrain size:"<<lbrain.size()<<endl;
+			//std::cout<<"sumx"<<sumx<<endl;
+			self->SetLDegreeMean(mean);
+			self->SetLDegreeStd(sigma);
+
+			//normalize right brain degree output
+			sum=0.0;sum2=0.0;
+			for(int i=0;i<rbrain.size();i++)
+			{
+				double v2=out2->GetComponent(rbrain[i],0);
+				//std::cout<<"frame:"<<j<<"v:"<<v;
+				sum+=v2;
+				sum2+=v2*v2;
+			}
+			scalefactor=1.0/(double)rbrain.size();
+			mean=sum*scalefactor;
+			sigma=sqrt(sum2*scalefactor-mean*mean);
+			//std::cout<<"m:"<<mean<<"s"<<sigma;
+			if (sigma<0.00001)
+				sigma=1.0;
+			if (isnan(sigma) || isinf(sigma))
+				sigma=1.0;
+			if (isnan(mean) || isinf(mean))
+				mean=0.0;
+			//double sumx = 0;
+
+			for(int i=0;i<rbrain.size();i++)
+			{
+				//double x = (out2->GetComponent(rbrain[i],0)-mean)/sigma;
+				//std::cout<<"frame2:"<<j<<"x"<<x<<endl;
+				out2->SetComponent(rbrain[i],0,(out2->GetComponent(rbrain[i],0)-mean)/sigma);
+				//sumx+=x*x;
+			}
+			//std::cout<<"rbrain size:"<<rbrain.size()<<endl;
+			//std::cout<<"sumx"<<sumx<<endl;
+			self->SetRDegreeMean(mean);
+			self->SetRDegreeStd(sigma);
+
+		}
+
+
+}
+template <class IT>
+static void positiveAbs(vtkbisIpsilateralConnMap *self,vtkImageData *inData,vtkImageData *outData,vtkImageData *OutData2,IT*,vector<int>& lbrain,vector<int>& rbrain,int nc,int nt,const float Threshold)
+{
+	cout<<"Ipsilateral, Positive, Abs"<<endl;
+	int maxcount=int(lbrain.size()/10);
+	int outcount=0;
+	float pog=0.0;
+	//left brain intrinsic connectivity calculation
+	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+
+	int *lptr = &lbrain[0];
+	int *oldptr;
+	//move pointer point to the first voxel of left brain on the output array
+
+	out = out + (*lptr);
+	count = count + (*lptr);
+	//cout<<"size:"<<lbrain.size()<<endl;
+
+	for(int lb=0;lb<lbrain.size();lb++)
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &lbrain[0];
+
+		for(int lbf=0;lbf<lbrain.size();lbf++)
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+			//inner loop pointer move to the beginning of the next voxel's time series
+
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if (sum >= Threshold)
+			{
+				goodSum += sum;
+				++counter;
+			}
+			++lptrf;
+		}
+		//write results to output arrays
+		*out=(IT)goodSum;
+		*count=(float)counter;
+		//cout<<*lptr<<"GS:"<<goodSum<<"S:"<<*out<<"N:"<<*count<<endl;
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+		++outcount;
+		/*if (outcount==maxcount)
+		{
+			pog=float(lb+1)/float(nt);
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(lb+1)/float(nt));
+		}*/
+		//self->UpdateProgress(float(lb+1)/float(nt));
+		//std::cout<<"Newlv: "<<lbrain[lb];
+	}//end of left brain
+	//right brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count2=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+
+	int *rptr = &rbrain[0];
+	out2 = out2 + (*rptr);
+	count2 = count2 + (*rptr);
+	maxcount=int(rbrain.size()/10);
+	outcount=0;
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &rbrain[0];
+
+		for(int rbf=0;rbf<rbrain.size();rbf++)//lptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if (sum >= Threshold)
+			{
+				goodSum += sum;
+				++counter;
+			}
+			++rptrf;
+		}
+		*out2=(IT)goodSum;
+		*count2=(float)counter;
+		//cout<<*rptr<<"RGS:"<<goodSum<<"S:"<<*out<<"N:"<<*count<<endl;
+		oldptr = rptr;
+		++rptr;
+		out2 = out2 + ((*rptr)-(*oldptr));
+		count2= count2 + ((*rptr)-(*oldptr));
+		++outcount;
+		if (outcount==maxcount)
+		{
+			pog=(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size()));
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size())));
+		}
+		//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+		//self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+		//std::cout<<"Newrv: "<<rbrain[rb];
+	}//end of right brain
+}
+template <class IT>
+static void ConpositiveAbs(vtkbisIpsilateralConnMap *self,vtkImageData *inData,vtkImageData *outData,vtkImageData *OutData2,IT*,vector<int>& lbrain,vector<int>& rbrain,int nc,int nt,const float Threshold)
+{
+	cout<<"Contralateral, Positive, Abs"<<endl;
+	int maxcount=int(lbrain.size()/10);
+	int outcount=0;
+	float pog=0.0;
+	//left to right brain intrinsic connectivity calculation
+	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+
+	int *lptr = &lbrain[0];
+	int *oldptr;
+	//move pointer point to the first voxel of left brain on the output array
+
+	out = out + (*lptr);
+	count = count + (*lptr);
+	//cout<<"left brain size:"<<lbrain.size()<<endl;
+
+	for(int lb=0;lb<lbrain.size();lb++)
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &rbrain[0];
+
+		for(int lbf=0;lbf<rbrain.size();lbf++)
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+			//inner loop pointer move to the beginning of the next voxel's time series
+
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if (sum >= Threshold)
+			{
+				//cout<<"sum:"<<sum<<endl;
+				goodSum += sum;
+				++counter;
+			}
+			++lptrf;
+		}
+		//write results to output arrays
+		*out=(IT)goodSum;
+		*count=(float)counter;
+		//cout<<*lptr<<"GS:"<<goodSum<<"S:"<<*out<<"N:"<<*count<<endl;
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+		/*++outcount;
+		if (outcount==maxcount)
+		{
+			pog=float(lb+1)/float(nt);
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(lb+1)/float(nt));
+		}*/
+		//self->UpdateProgress(float(lb+1)/float(nt));
+		//std::cout<<"Newlv: "<<lbrain[lb];
+	}//end of left brain
+	//right to left brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count2=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+
+	int *rptr = &rbrain[0];
+	out2 = out2 + (*rptr);
+	count2 = count2 + (*rptr);
+	maxcount=int(rbrain.size()/10);
+    outcount=0;
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &lbrain[0];
+
+		for(int rbf=0;rbf<lbrain.size();rbf++)//rptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if (sum >= Threshold)
+			{
+				goodSum += sum;
+				++counter;
+			}
+			++rptrf;
+		}
+		*out2=(IT)goodSum;
+		*count2=(float)counter;
+		//cout<<*rptr<<"RGS:"<<goodSum<<"S:"<<*out<<"N:"<<*count<<endl;
+		oldptr = rptr;
+		++rptr;
+		out2 = out2 + ((*rptr)-(*oldptr));
+		count2= count2 + ((*rptr)-(*oldptr));
+		++outcount;
+		if (outcount==maxcount)
+		{
+			pog=(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size()));
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size())));
+		}
+		//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+		//self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+		//std::cout<<"Newrv: "<<rbrain[rb];
+	}//end of right brain
+}
+template <class IT>
+static void positivePow(vtkbisIpsilateralConnMap *self,vtkImageData *inData,vtkImageData *outData,vtkImageData *OutData2,IT*,vector<int>& lbrain,vector<int>& rbrain,int nc,int nt,const float Threshold)
+{
+	cout<<"Ipsilateral, Positive, Sqr"<<endl;
+	int maxcount=int(lbrain.size()/10);
+	int outcount=0;
+	float pog=0.0;
+	//left brain intrinsic connectivity calculation
+	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *lptr = &lbrain[0];
+	int *oldptr;
+	//move pointer point to the first voxel of left brain on the output array
+	out = out + (*lptr);
+	count = count + (*lptr);
+	for(int lb=0;lb<lbrain.size();lb++)//lptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &lbrain[0];
+		for(int lbf=0;lbf<lbrain.size();lbf++)//lptrf counting
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+			//inner loop pointer move to the beginning of the next voxel's time series
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if(sum >= Threshold)
+			{
+				goodSum += sum*sum;
+				++counter;
+			}
+			++lptrf;
+		}
+		//write results to output arrays
+		*out=(IT)goodSum;
+		*count=(float)counter;
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+		++outcount;
+		/*if (outcount==maxcount)
+		{
+			pog=float(lb+1)/float(nt);
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(lb+1)/float(nt));
+		}*/
+		//self->UpdateProgress(float(lb+1)/float(nt));
+		//std::cout<<"Newlv: "<<lbrain[lb];
+	}//end of left brain
+	//right brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count2=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *rptr = &rbrain[0];
+	out2 = out2 + (*rptr);
+	count2 = count2 + (*rptr);
+	maxcount=int(rbrain.size()/10);
+	outcount=0;
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &rbrain[0];
+		for(int rbf=0;rbf<rbrain.size();rbf++)//lptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if(sum >= Threshold)
+			{
+				goodSum += sum*sum;
+				++counter;
+			}
+			++rptrf;
+		}
+		*out2=(IT)goodSum;
+		*count2=(float)counter;
+		oldptr = rptr;
+		++rptr;
+		out2 = out2+ ((*rptr)-(*oldptr));
+		count2= count2 + ((*rptr)-(*oldptr));
+		//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+		++outcount;
+		if (outcount==maxcount)
+		{
+			pog=(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size()));
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size())));
+		}
+		//self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+		//std::cout<<"Newrv: "<<rbrain[rb];
+	}//end of right brain
+}
+template <class IT>
+static void ConpositivePow(vtkbisIpsilateralConnMap *self,vtkImageData *inData,vtkImageData *outData,vtkImageData *OutData2,IT*,vector<int>& lbrain,vector<int>& rbrain,int nc,int nt,const float Threshold)
+{
+	cout<<"Contralateral, Positive, Sqr"<<endl;
+	int maxcount=int(lbrain.size()/10);
+	int outcount=0;
+	float pog=0.0;
+	//left to right brain intrinsic connectivity calculation
+	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *lptr = &lbrain[0];
+	int *oldptr;
+	//move pointer point to the first voxel of left brain on the output array
+	out = out + (*lptr);
+	count = count + (*lptr);
+	for(int lb=0;lb<lbrain.size();lb++)//lptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &rbrain[0];
+		for(int lbf=0;lbf<rbrain.size();lbf++)//lptrf counting
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+			//inner loop pointer move to the beginning of the next voxel's time series
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if(sum >= Threshold)
+			{
+				goodSum += sum*sum;
+				++counter;
+			}
+			++lptrf;
+		}
+		//write results to output arrays
+		*out=(IT)goodSum;
+		*count=(float)counter;
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+		/*++outcount;
+		if (outcount==maxcount)
+		{
+			pog=float(lb+1)/float(nt);
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(lb+1)/float(nt));
+		}*/
+		//self->UpdateProgress(float(lb+1)/float(nt));
+		//std::cout<<"Newlv: "<<lbrain[lb];
+	}//end of left brain
+	//right to left brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count2=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *rptr = &rbrain[0];
+	out2 = out2 + (*rptr);
+	count2 = count2 + (*rptr);
+	maxcount=int(rbrain.size()/10);
+	outcount=0;
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &lbrain[0];
+		for(int rbf=0;rbf<lbrain.size();rbf++)//lptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if(sum >= Threshold)
+			{
+				goodSum += sum*sum;
+				++counter;
+			}
+			++rptrf;
+		}
+		*out2=(IT)goodSum;
+		*count2=(float)counter;
+		oldptr = rptr;
+		++rptr;
+		out2 = out2+ ((*rptr)-(*oldptr));
+		count2= count2 + ((*rptr)-(*oldptr));
+		//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+		++outcount;
+		if (outcount==maxcount)
+		{
+			pog=(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size()));
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size())));
+		}
+		//self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+		//std::cout<<"Newrv: "<<rbrain[rb];
+	}//end of right brain
+}
+template <class IT>
+static void negativeAbs(vtkbisIpsilateralConnMap *self,vtkImageData *inData,vtkImageData *outData,vtkImageData *OutData2,IT*,vector<int>& lbrain,vector<int>& rbrain,int nc,int nt,const float Threshold)
+{
+	cout<<"Ipsilateral, Negative, Abs"<<endl;
+	int maxcount=int(lbrain.size()/10);
+	int outcount=0;
+	float pog=0.0;
+	//left brain intrinsic connectivity calculation
+	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *lptr = &lbrain[0];
+	int *oldptr;
+	//move pointer point to the first voxel of left brain on the output array
+	out = out + (*lptr);
+	count = count + (*lptr);
+	for(int lb=0;lb<lbrain.size();lb++)//lptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &lbrain[0];
+		for(int lbf=0;lbf<lbrain.size();lbf++)//lptrf counting
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+			//inner loop pointer move to the beginning of the next voxel's time series
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if(sum <= -Threshold)
+			{
+				sum = fabs(sum);
+				goodSum += sum;
+				++counter;
+			}
+			++lptrf;
+		}
+		//write results to output arrays
+		*out=(IT)goodSum;
+		*count=(float)counter;
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+		++outcount;
+		/*if (outcount==maxcount)
+		{
+			pog=float(lb+1)/float(nt);
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(lb+1)/float(nt));
+		}*/
+		//self->UpdateProgress(float(lb+1)/float(nt));
+		//std::cout<<"Newlv: "<<lbrain[lb];
+	}//end of left brain
+	//right brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count2=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *rptr = &rbrain[0];
+	out2 = out2 + (*rptr);
+	count2 = count2 + (*rptr);
+	maxcount=int(rbrain.size()/10);
+	outcount=0;
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &rbrain[0];
+		for(int rbf=0;rbf<rbrain.size();rbf++)//lptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if(sum <= -Threshold)
+			{
+				sum = sum * -1;
+				goodSum += sum;
+				++counter;
+			}
+			++rptrf;
+		}
+		*out2=(IT)goodSum;
+		*count2=(float)counter;
+		oldptr = rptr;
+		++rptr;
+		out2 = out2 + ((*rptr)-(*oldptr));
+		count2= count2 + ((*rptr)-(*oldptr));
+		//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+		++outcount;
+		if (outcount==maxcount)
+		{
+			pog=(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size()));
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size())));
+		}
+		//self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+		//std::cout<<"Newrv: "<<rbrain[rb];
+	}//end of right brain
+}
+template <class IT>
+static void ConnegativeAbs(vtkbisIpsilateralConnMap *self,vtkImageData *inData,vtkImageData *outData,vtkImageData *OutData2,IT*,vector<int>& lbrain,vector<int>& rbrain,int nc,int nt,const float Threshold)
+{
+	cout<<"Contralateral, Negative, Abs"<<endl;
+	int maxcount=int(lbrain.size()/10);
+	int outcount=0;
+	float pog=0.0;
+	//left to right brain intrinsic connectivity calculation
+	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *lptr = &lbrain[0];
+	int *oldptr;
+	//move pointer point to the first voxel of left brain on the output array
+	out = out + (*lptr);
+	count = count + (*lptr);
+	for(int lb=0;lb<lbrain.size();lb++)//lptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &rbrain[0];
+		for(int lbf=0;lbf<rbrain.size();lbf++)//lptrf counting
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+			//inner loop pointer move to the beginning of the next voxel's time series
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if(sum <= -Threshold)
+			{
+				sum = sum * -1;
+				goodSum += sum;
+				++counter;
+			}
+			++lptrf;
+		}
+		//write results to output arrays
+		*out=(IT)goodSum;
+		*count=(float)counter;
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+		/*++outcount;
+		if (outcount==maxcount)
+		{
+			pog=float(lb+1)/float(nt);
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(lb+1)/float(nt));
+		}*/
+		//self->UpdateProgress(float(lb+1)/float(nt));
+		//std::cout<<"Newlv: "<<lbrain[lb];
+	}//end of left brain
+	//right to left brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count2=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *rptr = &rbrain[0];
+	out2 = out2 + (*rptr);
+	count2 = count2 + (*rptr);
+	maxcount=int(rbrain.size()/10);
+	outcount=0;
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &lbrain[0];
+		for(int rbf=0;rbf<lbrain.size();rbf++)//lptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if(sum <= -Threshold)
+			{
+				sum = sum * -1;
+				goodSum += sum;
+				++counter;
+			}
+			++rptrf;
+		}
+		*out2=(IT)goodSum;
+		*count2=(float)counter;
+		oldptr = rptr;
+		++rptr;
+		out2 = out2 + ((*rptr)-(*oldptr));
+		count2= count2 + ((*rptr)-(*oldptr));
+		//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+		++outcount;
+		if (outcount==maxcount)
+		{
+			pog=(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size()));
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size())));
+		}
+		//self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+		//std::cout<<"Newrv: "<<rbrain[rb];
+	}//end of right brain
+}
+template <class IT>
+static void negativePow(vtkbisIpsilateralConnMap *self,vtkImageData *inData,vtkImageData *outData,vtkImageData *OutData2,IT*,vector<int>& lbrain,vector<int>& rbrain,int nc,int nt,const float Threshold)
+{
+	cout<<"Ipsilateral, Negative, Pow"<<endl;
+	int maxcount=int(lbrain.size()/10);
+	int outcount=0;
+	float pog=0.0;
+	//left brain intrinsic connectivity calculation
+	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *lptr = &lbrain[0];
+	int *oldptr;
+	//move pointer point to the first voxel of left brain on the output array
+	out = out + (*lptr);
+	count = count + (*lptr);
+	for(int lb=0;lb<lbrain.size();lb++)//lptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &lbrain[0];
+		for(int lbf=0;lbf<lbrain.size();lbf++)//lptrf counting
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+			//inner loop pointer move to the beginning of the next voxel's time series
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if (sum <= -Threshold)
+			{
+				goodSum += sum*sum;
+				++counter;
+			}
+			++lptrf;
+		}
+		//write results to output arrays
+		*out=(IT)goodSum;
+		*count=(float)counter;
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+		++outcount;
+		/*if (outcount==maxcount)
+		{
+			pog=float(lb+1)/float(nt);
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(lb+1)/float(nt));
+		}*/
+		//self->UpdateProgress(float(lb+1)/float(nt));
+		//std::cout<<"Newlv: "<<lbrain[lb];
+	}//end of left brain
+	//right brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count2=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *rptr = &rbrain[0];
+	out2 = out2 + (*rptr);
+	count2 = count2 + (*rptr);
+	maxcount=int(rbrain.size()/10);
+	outcount=0;
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &rbrain[0];
+		for(int rbf=0;rbf<rbrain.size();rbf++)//lptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if (sum <= -Threshold)
+			{
+				goodSum += sum*sum;
+				++counter;
+			}
+			++rptrf;
+		}
+		*out2=(IT)goodSum;
+		*count2=(float)counter;
+		oldptr = rptr;
+		++rptr;
+		out2 = out2 + ((*rptr)-(*oldptr));
+		count2= count2 + ((*rptr)-(*oldptr));
+		//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+		++outcount;
+		if (outcount==maxcount)
+		{
+			pog=(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size()));
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size())));
+		}
+		//self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+		//std::cout<<"Newrv: "<<rbrain[rb];
+	}//end of right brain
+}
+template <class IT>
+static void ConnegativePow(vtkbisIpsilateralConnMap *self,vtkImageData *inData,vtkImageData *outData,vtkImageData *OutData2,IT*,vector<int>& lbrain,vector<int>& rbrain,int nc,int nt,const float Threshold)
+{
+	cout<<"Contralateral, Negative, Sqr"<<endl;
+	int maxcount=int(lbrain.size()/10);
+	int outcount=0;
+	float pog=0.0;
+	//left to right brain intrinsic connectivity calculation
+	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *lptr = &lbrain[0];
+	int *oldptr;
+	//move pointer point to the first voxel of left brain on the output array
+	out = out + (*lptr);
+	count = count + (*lptr);
+	for(int lb=0;lb<lbrain.size();lb++)//lptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &rbrain[0];
+		for(int lbf=0;lbf<rbrain.size();lbf++)//lptrf counting
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+			//inner loop pointer move to the beginning of the next voxel's time series
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if (sum <= -Threshold)
+			{
+				goodSum += sum*sum;
+				++counter;
+			}
+			++lptrf;
+		}
+		//write results to output arrays
+		*out=(IT)goodSum;
+		*count=(float)counter;
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+		/*++outcount;
+		if (outcount==maxcount)
+		{
+			pog=float(lb+1)/float(nt);
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(lb+1)/float(nt));
+		}*/
+		//self->UpdateProgress(float(lb+1)/float(nt));
+		//std::cout<<"Newlv: "<<lbrain[lb];
+	}//end of left brain
+	//right to left brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count2=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *rptr = &rbrain[0];
+	out2 = out2 + (*rptr);
+	count2 = count2 + (*rptr);
+	maxcount=int(rbrain.size()/10);
+	outcount=0;
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &lbrain[0];
+		for(int rbf=0;rbf<lbrain.size();rbf++)//lptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if (sum <= -Threshold)
+			{
+				goodSum += sum*sum;
+				++counter;
+			}
+			++rptrf;
+		}
+		*out2=(IT)goodSum;
+		*count2=(float)counter;
+		oldptr = rptr;
+		++rptr;
+		out2 = out2 + ((*rptr)-(*oldptr));
+		count2= count2 + ((*rptr)-(*oldptr));
+		//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+		++outcount;
+		if (outcount==maxcount)
+		{
+			pog=(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size()));
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size())));
+		}
+		//self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+		//std::cout<<"Newrv: "<<rbrain[rb];
+	}//end of right brain
+}
+template <class IT>
+static void bothAbs(vtkbisIpsilateralConnMap *self,vtkImageData *inData,vtkImageData *outData,vtkImageData *OutData2,IT*,vector<int>& lbrain,vector<int>& rbrain,int nc,int nt,const float Threshold)
+{
+	cout<<"Ipsilateral, Both, Abs"<<endl;
+	int maxcount=int(lbrain.size()/10);
+	int outcount=0;
+	float pog=0.0;
+	//left brain intrinsic connectivity calculation
+	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *lptr = &lbrain[0];
+	int *oldptr;
+	//move pointer point to the first voxel of left brain on the output array
+	out = out + (*lptr);
+	count = count + (*lptr);
+	for(int lb=0;lb<lbrain.size();lb++)//lptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &lbrain[0];
+		for(int lbf=0;lbf<lbrain.size();lbf++)//lptrf counting
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+			//inner loop pointer move to the beginning of the next voxel's time series
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if (sum <= -Threshold || sum >= Threshold)
+			{
+				if(sum <0)
+					sum = sum * -1;
+				goodSum += sum;
+				++counter;
+			}
+			++lptrf;
+		}
+		//write results to output arrays
+		*out=(IT)goodSum;
+		*count=(float)counter;
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+		++outcount;
+		/*if (outcount==maxcount)
+		{
+			pog=float(lb+1)/float(nt);
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(lb+1)/float(nt));
+		}*/
+		//self->UpdateProgress(float(lb+1)/float(nt));
+		//std::cout<<"Newlv: "<<lbrain[lb];
+	}//end of left brain
+	//right brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count2=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *rptr = &rbrain[0];
+	out2 = out2+ (*rptr);
+	count2 = count2 + (*rptr);
+	maxcount=int(rbrain.size()/10);
+	outcount=0;
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &rbrain[0];
+		for(int rbf=0;rbf<rbrain.size();rbf++)//lptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if (sum <= -Threshold || sum >= Threshold)
+			{
+				if(sum <0)
+					sum = sum * -1;
+				goodSum += sum;
+				++counter;
+			}
+			++rptrf;
+		}
+		*out2=(IT)goodSum;
+		*count2=(float)counter;
+		oldptr = rptr;
+		++rptr;
+		out2 = out2 + ((*rptr)-(*oldptr));
+		count2= count2 + ((*rptr)-(*oldptr));
+		//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+		++outcount;
+		if (outcount==maxcount)
+		{
+			pog=(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size()));
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size())));
+		}
+		//self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+		//std::cout<<"Newrv: "<<rbrain[rb];
+	}//end of right brain
+}
+template <class IT>
+static void ConbothAbs(vtkbisIpsilateralConnMap *self,vtkImageData *inData,vtkImageData *outData,vtkImageData *OutData2,IT*,vector<int>& lbrain,vector<int>& rbrain,int nc,int nt,const float Threshold)
+{
+	cout<<"Contralateral, Both, Abs"<<endl;
+	int maxcount=int(lbrain.size()/10);
+	int outcount=0;
+	float pog=0.0;
+	//left to right brain intrinsic connectivity calculation
+	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *lptr = &lbrain[0];
+	int *oldptr;
+	//move pointer point to the first voxel of left brain on the output array
+	out = out + (*lptr);
+	count = count + (*lptr);
+	for(int lb=0;lb<lbrain.size();lb++)//lptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &rbrain[0];
+		for(int lbf=0;lbf<rbrain.size();lbf++)//lptrf counting
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+			//inner loop pointer move to the beginning of the next voxel's time series
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if (sum <= -Threshold || sum >= Threshold)
+			{
+				if(sum <0)
+					sum = sum * -1;
+				goodSum += sum;
+				++counter;
+			}
+			++lptrf;
+		}
+		//write results to output arrays
+		*out=(IT)goodSum;
+		*count=(float)counter;
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+		/*++outcount;
+		if (outcount==maxcount)
+		{
+			pog=float(lb+1)/float(nt);
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(lb+1)/float(nt));
+		}*/
+		//self->UpdateProgress(float(lb+1)/float(nt));
+		//std::cout<<"Newlv: "<<lbrain[lb];
+	}//end of left brain
+	//right to left brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count2=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *rptr = &rbrain[0];
+	out2 = out2+ (*rptr);
+	count2 = count2 + (*rptr);
+	maxcount=int(rbrain.size()/10);
+	outcount=0;
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &lbrain[0];
+		for(int rbf=0;rbf<lbrain.size();rbf++)//lptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if (sum <= -Threshold || sum >= Threshold)
+			{
+				if(sum <0)
+					sum = sum * -1;
+				goodSum += sum;
+				++counter;
+			}
+			++rptrf;
+		}
+		*out2=(IT)goodSum;
+		*count2=(float)counter;
+		oldptr = rptr;
+		++rptr;
+		out2 = out2 + ((*rptr)-(*oldptr));
+		count2= count2 + ((*rptr)-(*oldptr));
+		//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+		++outcount;
+		if (outcount==maxcount)
+		{
+			pog=(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size()));
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size())));
+		}
+		//self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+		//std::cout<<"Newrv: "<<rbrain[rb];
+	}//end of right brain
+}
+template <class IT>
+static void bothPow(vtkbisIpsilateralConnMap *self,vtkImageData *inData,vtkImageData *outData,vtkImageData *OutData2,IT*,vector<int>& lbrain,vector<int>& rbrain,int nc,int nt,const float Threshold)
+{
+	cout<<"Ipsilateral, Both, Sqr"<<endl;
+	int maxcount=int(lbrain.size()/10);
+	int outcount=0;
+	float pog=0.0;
+	//left brain intrinsic connectivity calculation
+	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *lptr = &lbrain[0];
+	int *oldptr;
+	//move pointer point to the first voxel of left brain on the output array
+	out = out + (*lptr);
+	count = count + (*lptr);
+	for(int lb=0;lb<lbrain.size();lb++)//lptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &lbrain[0];
+		for(int lbf=0;lbf<lbrain.size();lbf++)//lptrf counting
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+			//inner loop pointer move to the beginning of the next voxel's time series
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if(sum <= -Threshold || sum >= Threshold)
+			{
+				goodSum += sum*sum;
+				//cout<<sum<<"*"<<sum;
+				++counter;
+			}
+			++lptrf;
+			//cout<<"+";
+		}
+		//cout<<"lS:"<<goodSum<<"/"<<lbrain.size()<<"=";
+		//write results to output arrays
+		*out=(IT)goodSum;
+		//cout<<*out<<endl;
+		*count=(float)counter;
+		//cout<<"counter:"<<counter<<"N:"<<*count<<endl;
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+		//++outcount;
+		//if (outcount==maxcount)
+		//{
+			//pog=(float(lb+1)/float(lbrain.size()))/2;
+			//self->UpdateProgress(pog);
+			//outcount=0;
+			//fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(lb+1)/float(lbrain.size()))/2);
+		//}
+		//self->UpdateProgress(float(lb+1)/float(nt));
+		//std::cout<<"Newlv: "<<lbrain[lb];
+	}//end of left brain
+	//right brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count2=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *rptr = &rbrain[0];
+	out2 = out2 + (*rptr);
+	count2 = count2 + (*rptr);
+	maxcount=int(rbrain.size()/10);
+	outcount=0;
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &rbrain[0];
+		for(int rbf=0;rbf<rbrain.size();rbf++)//lptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if(sum <= -Threshold || sum >= Threshold)
+			{
+				goodSum += sum*sum;
+				//cout<<sum<<"*"<<sum;
+				++counter;
+			}
+			++rptrf;
+			//cout<<"+";
+		}
+		//cout<<"=rS"<<goodSum<<"/"<<rbrain.size()<<"=";
+		*out2=(IT)goodSum;
+		//cout<<*out<<endl;
+		*count2=(float)counter;
+		//cout<<"counter:"<<counter<<"N:"<<*count<<endl;
+		oldptr = rptr;
+		++rptr;
+		out2= out2 + ((*rptr)-(*oldptr));
+		count2= count2 + ((*rptr)-(*oldptr));
+		//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+		++outcount;
+		if (outcount==maxcount)
+		{
+			pog=(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size()));
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size())));
+		}
+		//self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+		//std::cout<<"Newrv: "<<rbrain[rb];
+	}//end of right brain
+}
+template <class IT>
+static void ConbothPow(vtkbisIpsilateralConnMap *self,vtkImageData *inData,vtkImageData *outData,vtkImageData *OutData2,IT*,vector<int>& lbrain,vector<int>& rbrain,int nc,int nt,const float Threshold)
+{
+	cout<<"Contralateral, Both, Sqr"<<endl;
+	int maxcount=int(lbrain.size()/10);
+	int outcount=0;
+	float pog=0.0;
+	//left to right brain intrinsic connectivity calculation
+	//make the pointers point to the beginning of the output array
+	IT *out = (IT*)  outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *lptr = &lbrain[0];
+	int *oldptr;
+	//move pointer point to the first voxel of left brain on the output array
+	out = out + (*lptr);
+	count = count + (*lptr);
+	for(int lb=0;lb<lbrain.size();lb++)//lptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		//move current voxel pointer point to the beginning of a voxel on left brain
+		IT *outerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*lptr)*nc;
+		//inner loop pointer point to the beginning of the input array
+		IT *innerloop = (IT*)inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *lptrf = &rbrain[0];
+		for(int lbf=0;lbf<rbrain.size();lbf++)//lptrf counting
+		{
+			//thisvoxel pointer move back to the beginning of current voxel
+			IT *thisvoxel = outerloop;
+			//inner loop pointer move to the beginning of the next voxel's time series
+			IT *friendvoxel = innerloop+(*lptrf)*nc;
+			float sum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*lptr<<"*"<<*lptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if(sum <= -Threshold || sum >= Threshold)
+			{
+				goodSum += sum*sum;
+				//cout<<sum<<"*"<<sum;
+				++counter;
+			}
+			++lptrf;
+			//cout<<"+";
+		}
+		//cout<<"lS:"<<goodSum<<"/"<<lbrain.size()<<"=";
+		//write results to output arrays
+		*out=(IT)goodSum;
+		//cout<<*out<<endl;
+		*count=(float)counter;
+		//cout<<"counter:"<<counter<<"N:"<<*count<<endl;
+		//increment outerloop(current voxel) pointer
+		oldptr = lptr;
+		++lptr;
+		//output pointer move to the next voxel on the left brain
+		out = out + ((*lptr)-(*oldptr));
+		count= count + ((*lptr)-(*oldptr));
+		++outcount;
+		/*if (outcount==maxcount)
+		{
+		    pog=float(lb+1)/float(nt);
+		    self->UpdateProgress(pog);
+		    outcount=0;
+		    fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(lb+1)/float(nt));
+		}*/
+		//self->UpdateProgress(float(lb+1)/float(nt));
+		//std::cout<<"Newlv: "<<lbrain[lb];
+	}//end of left brain
+	//right to left brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	float* count2=(float*) OutData2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	int *rptr = &rbrain[0];
+	out2 = out2 + (*rptr);
+	count2 = count2 + (*rptr);
+	maxcount=int(rbrain.size()/10);
+	outcount=0;
+
+	//xilin added this
+//	float sum_volume = 0;
+//	float sum2_volume = 0;
+	//end of xilin's addition
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+		float goodSum = 0.0;
+		int counter = 0;
+		IT *outerloop = (IT*) inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		outerloop=outerloop+(*rptr)*nc;
+		IT *innerloop = (IT*)  inData->GetPointData()->GetScalars()->GetVoidPointer(0);
+		int *rptrf = &lbrain[0];
+		for(int rbf=0;rbf<lbrain.size();rbf++)//lptrf counting
+		{
+			IT *thisvoxel = outerloop;
+			IT *friendvoxel = innerloop+(*rptrf)*nc;
+			float sum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				sum += (*thisvoxel)*(*friendvoxel);
+				//std::cout<<*rptr<<"*"<<*rptrf<<"="<<*thisvoxel<<"*"<<*friendvoxel<<"="<<sum<<endl;
+				++thisvoxel;
+				++friendvoxel;
+			}
+			sum/=nc;
+			if(sum <= -Threshold || sum >= Threshold)
+			{
+				goodSum += sum*sum;
+				//cout<<sum<<"*"<<sum;
+				++counter;
+			}
+			++rptrf;
+			//cout<<"+";
+		}
+		//cout<<"=rS"<<goodSum<<"/"<<rbrain.size()<<"=";
+
+		//xilin added these lines
+//		sum_volume += goodSum;
+//		sum2_volume +=  goodSum*goodSum;
+		//end of xilin's addtion
+
+		*out2=(IT)goodSum;
+		//cout<<*out<<endl;
+		*count2=(float)counter;
+		//cout<<"counter:"<<counter<<"N:"<<*count<<endl;
+		oldptr = rptr;
+		++rptr;
+		out2= out2 + ((*rptr)-(*oldptr));
+		count2= count2 + ((*rptr)-(*oldptr));
+		//std::cout<<(*rptr)<<"-"<<(*oldptr)<<endl;
+		++outcount;
+		if (outcount==maxcount)
+		{
+			pog=(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size()));
+			self->UpdateProgress(pog);
+			outcount=0;
+			fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,(float(rb+1)/float(rbrain.size()))+(lbrain.size()/(lbrain.size()+rbrain.size())));
+		}
+		//self->UpdateProgress((float(rb+1)+lbrain.size())/float(nt));
+		//std::cout<<"Newrv: "<<rbrain[rb];
+	}//end of right brain
+
+
+	// xilin added these lines
+	//right to left brain intrinsic connectivity calculation
+	//make the pointers go back to the beginning of the output array
+/*	int *rptr = &rbrain[0];
+	IT* out2 =(IT*) outData->GetPointData()->GetScalars()->GetVoidPointer(0);
+	out2 = out2 + (*rptr);
+
+	float sum_avg = sum_volume/lbrain.size();
+	float sum_sig = sum2_volume/lbrain.size()- sum_avg*sum_avg;
+
+	for(int rb=0;rb<rbrain.size();rb++)//rptr counting
+	{
+	  *out2 = (IT)(*out2-sum_avg)/sum_sig;
+	}
+
+*/
+}
+
+
+template <class IT>
+static void vtkbisIpsilateralConnMapDoConnectivity1(vtkbisIpsilateralConnMap *self,
+						  vtkImageData *inData,
+						  vtkImageData *outData,
+						  vtkImageData *OutData2,
+						  vtkImageData *maskData,
+						  IT* )
+{
+	switch (maskData->GetScalarType())
+	{
+		vtkTemplateMacro7(vtkbisIpsilateralConnMapDoConnectivity,self
+				,inData,outData,OutData2
+				,maskData,static_cast<IT *>(0),static_cast<VTK_TT *>(0));
+		default:
+			vtkGenericWarningMacro("Execute: Unknown input ScalarType");
+        return;
+    }
+}
+//-------------------------------------------------------------------------------
+//Old not optimized simpleExecute code
+//-------------------------------------------------------------------------------
+void vtkbisIpsilateralConnMap::OldExecute(vtkImageData* original_input ,vtkImageData* output)
+{
+	fprintf(stderr,"beginning vtkbisIpsilateralConnMap Old method");
+
+/*	vtkImageCast* cast=vtkImageCast::New();
+	cast->SetInput(original_input);
+	cast->SetOutputScalarTypeToFloat();
+	cast->Update();
+
+	vtkImageData* inp=vtkImageData::New();
+	inp->ShallowCopy(cast->GetOutput());
+	cast->Delete();
+*/
+	vtkbisImageTimeSeriesNormalize* norm1=vtkbisImageTimeSeriesNormalize::New();
+	norm1->SetInput(original_input);
+	norm1->Update();
+
+	vtkImageData* inp=vtkImageData::New();
+	inp->ShallowCopy(norm1->GetOutput());
+	norm1->Delete();
+
+	int dim[3];
+	int dimMask[3];
+	int ia;
+	int tsum = 0;
+	inp->GetDimensions(dim);
+	if (this->ImageMask!=NULL)
+	{
+		this->ImageMask->GetDimensions(dimMask);
+		for (ia=0;ia<=2;ia++)
+			tsum += abs(dim[ia]-dimMask[ia]);
+		if (tsum>0)
+		{
+			fprintf(stderr,"Bad Mask Input to vtkbisIpsilateralConnMap SimpleExecute\n");
+			return;
+		}
+	}
+
+	vtkDataArray* temp=inp->GetPointData()->GetScalars();
+	int nt=temp->GetNumberOfTuples();//number of voxels
+	int nc=temp->GetNumberOfComponents();//number of frames (time series)
+
+	vtkDataArray* mask = NULL;
+	if (this->ImageMask!=NULL)
+		mask=this->ImageMask->GetPointData()->GetScalars();
+
+	vtkDataArray* out=output->GetPointData()->GetScalars();
+	out->FillComponent(0,0.0);
+
+	this->OutData2=vtkImageData::New();
+	this->OutData2->SetOrigin(output->GetOrigin());
+	this->OutData2->SetSpacing(output->GetSpacing());
+	this->OutData2->SetDimensions(output->GetDimensions());
+	this->OutData2->SetScalarTypeToFloat();
+	this->OutData2->AllocateScalars();//allocation space on memery
+	vtkDataArray* out2 = this->OutData2->GetPointData()->GetScalars();
+	out2->FillComponent(0,0.0);
+
+	//normalize time series voxel by voxel
+/*	for (int i=0;i< nt;i++)
+	{
+		float psum = 0;
+		int DoGlm=1;
+		if (mask!=NULL)
+		{
+			if (mask->GetComponent(i,0)<1)
+				DoGlm=0;
+		}
+		if(DoGlm)
+		{
+			for (int m = 0; m < nc; m++)
+			{
+				psum += temp->GetComponent(i,m)*temp->GetComponent(i,m);//GetComponent(voxel,m) Return the data component at the ith tuple and mth component
+			}
+			float norm = sqrt(psum);
+			if (norm != 0)
+			{
+				for (int m2 = 0; m2 < nc; m2++)
+				{
+					float ns = temp->GetComponent(i,m2) / norm;
+					//cout<<temp->GetComponent(i,m2)<<"/"<<norm<<"="<<ns<<";";
+					temp->SetComponent(i,m2,ns);
+					//cout<<temp->GetComponent(i,m2)<<";";
+				}
+			}
+		 }
+	  }
+*/
+	double position[3],spacing[3];
+	vector<int> lbrain,rbrain;
+	original_input->GetSpacing(spacing);
+	//sort voxel to left or right brain vector
+	for(int t= 0; t < nt; t++)
+	{
+		int DoGlm=1;
+		if (mask!=NULL)
+		{
+			if(mask->GetComponent(t,0) < 1)
+				DoGlm=0;
+		}
+		if(DoGlm)
+		{
+			original_input->GetPoint(t,position);
+			if( position[0]/spacing[0] > (dim[0]-1)/2 )
+			{
+				lbrain.push_back(t);
+				//std::cout<<"lb:"<<t;
+		    }
+		    else
+		    {
+			    rbrain.push_back(t);
+			    //std::cout<<"rb"<<t;
+		    }
+	    }
+    }
+	//cout<<"oldwaywithmask lbrain:"<<lbrain.size()<<"rbrain:"<<rbrain.size()<<endl;
+	this->UpdateProgress(0.01);
+	//-----------------------------------------------------
+	//left brain intrinsic connectivity calculation
+	//-----------------------------------------------------
+	//cout<<"size"<<lbrain.size()<<endl;
+	for(int lb=0;lb<lbrain.size();lb++)
+	{
+		float lgoodSum = 0.0;
+		int counter = 0;
+		for(int lbf=0;lbf<lbrain.size();lbf++)
+		{
+			float lsum = 0;
+			for(int lm=0;lm<nc;lm++)
+			{
+				lsum += temp->GetComponent(lbrain[lb],lm)*temp->GetComponent(lbrain[lbf],lm);
+				//cout<<lbrain[lb]<<"*"<<lbrain[lbf]<<"="<<temp->GetComponent(lbrain[lb],lm)<<"*"<<temp->GetComponent(lbrain[lbf],lm)<<"="<<lsum<<endl;
+			}
+			//lsum/nc if use Xenios normalize code
+			lsum/=nc;
+
+			lgoodSum +=this->CalculateGoodSum(lsum,counter);
+			//cout<<lbrain[lb]<<"to"<<lbrain[lbf]<<"="<<lsum<<","<<counter<<";";
+		}
+		out2->SetComponent(lbrain[lb],0,(float)counter/lbrain.size());
+		//cout<<lbrain[lb]<<"N:"<<out2->GetComponent(lbrain[lb],0)<<";";
+		out->SetComponent(lbrain[lb],0,lgoodSum/lbrain.size());
+		//cout<<"S:"<<out->GetComponent(lbrain[lb],0)<<endl;
+		//std::cout<<"lv: "<<lbrain[lb];
+	}
+	//---------------------------------------------------------
+	//right brain intrinsic connectivity calculation
+	//---------------------------------------------------------
+	for(int rb=0;rb<rbrain.size();rb++)
+	{
+		int counter = 0;
+		float rgoodSum = 0;
+		for(int rbf=0;rbf<rbrain.size();rbf++)
+		{
+			float rsum = 0;
+			for(int rm=0;rm<nc;rm++)
+			{
+				rsum += temp->GetComponent(rbrain[rb],rm)*temp->GetComponent(rbrain[rbf],rm);
+			}
+			//rsum/nc if use Xenios normalize code
+			rsum/=nc;
+
+			rgoodSum +=this->CalculateGoodSum(rsum,counter);
+		}
+		out2->SetComponent(rbrain[rb],0,(float)counter/rbrain.size());
+		out->SetComponent(rbrain[rb],0,rgoodSum/rbrain.size());
+		//std::cout<<" rv:"<<rbrain[rb];
+	}
+	this->UpdateProgress(1.0);
+}//end of old execute
+
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisIpsilateralConnMap::SimpleExecute(vtkImageData* original_input ,vtkImageData* output)
+{
+	//fprintf(stderr," beginning vtkbisIpsilateralConnMap");
+	if (this->Optimize == 0)
+	  {
+	    fprintf(stderr,"Running Non Optimized Code\n");
+	    this->OldExecute(original_input,output);
+	    return;
+	  }
+
+
+	int dim[3];
+	int dimMask[3];
+	int ia;
+	int tsum = 0;
+
+
+	vtkbisImageTimeSeriesNormalize* norm1=vtkbisImageTimeSeriesNormalize::New();
+	norm1->SetInput(original_input);
+	norm1->Update();
+
+	vtkImageData* inp=vtkImageData::New();
+	inp->ShallowCopy(norm1->GetOutput());
+	norm1->Delete();
+
+
+	inp->GetDimensions(dim);
+	if (this->ImageMask!=NULL)
+	{
+		this->ImageMask->GetDimensions(dimMask);
+		for (ia=0;ia<=2;ia++)
+			tsum += abs(dim[ia]-dimMask[ia]);
+		if (tsum>0)
+		{
+			fprintf(stderr,"Bad Mask Input to vtkbisIpsilateralConnMap SimpleExecute\n");
+			return;
+		}
+	}
+
+	if (this->OutData2!=NULL)
+	  this->OutData2->Delete();
+
+	this->OutData2=vtkImageData::New();
+	this->OutData2->SetOrigin(output->GetOrigin());
+	this->OutData2->SetSpacing(output->GetSpacing());
+	this->OutData2->SetDimensions(output->GetDimensions());
+	this->OutData2->SetScalarTypeToFloat();
+	this->OutData2->AllocateScalars();//allocation space on memery
+
+
+	if (this->Range == 1 ) {
+		  if (this->Abs == 1 ) {
+			  //PositiveAbs
+			  this->Type = 1;
+		  }else{
+			  //PositivePow
+			  this->Type= 2 ;
+		  }
+	  }else if ( this->Range == 2 ) {
+		  if ( this->Abs == 1 ) {
+			  //NegativeAbs
+			  this->Type = 3;
+	  	  }else{
+	  		  //NegativePow
+	  		  this->Type = 4;
+	  	  }
+	  }else{
+		  if ( this->Abs == 1 ){
+			  //BothAbs
+			  this->Type = 5;
+		  } else {
+			  //BothPow
+			  this->Type = 6;
+		  }
+	  }
+
+	//fprintf(stderr," doContralater=%d use type=%d threshold=%.2f range=%d abs=%d optimize=%d\n",
+	 // 		  this->DoContralateral,this->Type,this->Threshold,this->Range,this->Abs,this->Optimize);
+
+	this->UpdateProgress(0.01);
+	time_t start,end;
+	time(&start);
+
+	if(this->ImageMask!=NULL)
+	{
+		switch (inp->GetScalarType())
+		{
+		vtkTemplateMacro6(vtkbisIpsilateralConnMapDoConnectivity1,this,
+				inp,output, this->OutData2,
+				this->ImageMask,static_cast<VTK_TT *>(0));
+		default:
+			vtkErrorMacro(<< "Execute: Unknown ScalarType");
+		return;
+		}
+	}else{
+		switch (inp->GetScalarType())
+		{
+		vtkTemplateMacro5(vtkbisIpsilateralConnMapDoConnectivity2,this,
+						inp, output, this->OutData2,
+						static_cast<VTK_TT *>(0));
+		default:
+			vtkErrorMacro(<< "Execute: Unknown ScalarType");
+		return;
+		}
+	}
+
+/*	if (this->FileName=="")
+	  return;
+
+	std::ofstream myfile(this->FileName.c_str());
+	if(!myfile.is_open())
+	  {
+	    cout<< "Unable to open file" << this->FileName.c_str();
+	    return;
+	  }
+	myfile<<"Left Brain Mean: \t "<<this->LMean<<"\t"<<"Left Brain Standard Deviation: \t "<<this->LStd<<"Left Brain Number of Voxels: \t "<<this->LSize<<"\n";
+	myfile<<"Right Brain Mean: \t "<<this->RMean<<"\t"<<"Right Brain Standard Deviation: \t "<<this->RStd<<"Right Brain Number of Voxels: \t "<<this->RSize<<"\n";
+	if (Threshold != 0)
+	  {
+	    myfile<<"Left Brain Degree Mean: \t "<<this->LDegreeMean<<"\t"<<"Left Brain Degree Standard Deviation: \t "<<this->LDegreeStd<<"\n";
+	    myfile<<"Right Brain Degree Mean: \t "<<this->RDegreeMean<<"\t"<<"Right Brain Degree Standard Deviation: \t "<<this->RDegreeStd<<"\n";
+	  }
+	myfile.close();
+	*/
+	//normalize brain frame by frame
+
+	/*	vtkDataArray* dat=output->GetPointData()->GetScalars();
+		int nt = dat->GetNumberOfTuples();
+		if (!this->OutputRaw)
+		{
+		std::cout<<"I am here to output Z"<<endl;
+		for (int i=0;i<nt;i++)
+		{
+		dat->SetComponent(i,0,vtkbisTimeSeriesCorrelation::RhoToZConversion(dat->GetComponent(i,0)));
+		}
+		}
+	*/
+	time(&end);
+
+	std::cout<<endl<<"elapsed time "<<difftime(end, start)<<" seconds"<<endl;
+	this->UpdateProgress(1.0);
+}
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisIpsilateralConnMap.h b/bioimagesuite30_src/Connectivity/vtkbisIpsilateralConnMap.h
new file mode 100644
index 0000000..6dc995a
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisIpsilateralConnMap.h
@@ -0,0 +1,161 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisIpsilateralConnMap.h
+ *
+ *  Created on: Nov 13, 2008
+ *      Author: Isabella Murphy, Xilin Shen
+ *      given a brain time series image, calculate intrinsic connectivity within each half
+ *      (left and right) of the brain
+ *      @Input: a 4D vtkImageData object (Brain image) with time courses.
+ *      @Output: a 3D vtkImageData object with intrinsic ipsilateral connectivity contrast.
+ */
+#ifndef VTKBISIPSILATERALINTRINSICCONNCONTRAST_H_
+#define VTKBISIPSILATERALINTRINSICCONNCONTRAST_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include <string>
+#include <iostream>
+
+class vtkInformation;
+class vtkInformationVector;
+
+class vtkbisIpsilateralConnMap : public vtkSimpleImageToImageFilter{
+public:
+	static vtkbisIpsilateralConnMap *New();
+	vtkTypeMacro(vtkbisIpsilateralConnMap,vtkSimpleImageToImageFilter);
+
+	// Threshold
+	vtkSetClampMacro(Threshold,float,0.0,1.0);
+	vtkGetMacro(Threshold,float);
+
+	// Mask Image
+	vtkSetObjectMacro(ImageMask,vtkImageData);
+	vtkGetObjectMacro(ImageMask,vtkImageData);
+
+	//Range
+	vtkSetClampMacro(Range,int,1,3);
+	vtkGetMacro(Range,int);
+
+	//Abs
+	vtkSetClampMacro(Abs,int,1,2);
+	vtkGetMacro(Abs,int);
+
+	//counter
+	vtkSetObjectMacro(OutData2,vtkImageData);
+	vtkGetObjectMacro(OutData2,vtkImageData);
+
+	//OutpuRaw
+//	vtkSetClampMacro(OutputRaw,int,0,1);
+//	vtkGetMacro(OutputRaw,int);
+
+	//Type
+	vtkSetClampMacro(Type,int,1,9);
+	vtkGetMacro(Type,int);
+
+	//DoContralateral
+	vtkSetClampMacro(DoContralateral,int,0,1);
+	vtkGetMacro(DoContralateral,int);
+
+	virtual float CalculateGoodSum (float sum,int& counter);
+	//virtual void OverThreshold (double sum,int& counter);
+
+	// File name
+	virtual void SetFileName(const char* filename);
+	virtual const char* GetFileName();
+
+	vtkSetMacro(LMean,double);
+	vtkGetMacro(LMean,double);
+	vtkSetMacro(LStd,double);
+	vtkGetMacro(LStd,double);
+	vtkSetMacro(RMean,double);
+	vtkGetMacro(RMean,double);
+	vtkSetMacro(RStd,double);
+	vtkGetMacro(RStd,double);
+	vtkSetMacro(LDegreeMean,double);
+	vtkGetMacro(LDegreeMean,double);
+	vtkSetMacro(LDegreeStd,double);
+	vtkGetMacro(LDegreeStd,double);
+	vtkSetMacro(RDegreeMean,double);
+	vtkGetMacro(RDegreeMean,double);
+	vtkSetMacro(RDegreeStd,double);
+	vtkGetMacro(RDegreeStd,double);
+	vtkSetMacro(LSize,int);
+	vtkGetMacro(LSize,int);
+	vtkSetMacro(RSize,int);
+	vtkGetMacro(RSize,int);
+protected:
+	vtkbisIpsilateralConnMap();
+	virtual ~vtkbisIpsilateralConnMap();
+	virtual int RequestInformation (vtkInformation * request,
+				vtkInformationVector ** inputVector,
+				vtkInformationVector * outputVector) ;
+	virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+	virtual void OldExecute(vtkImageData* input ,vtkImageData* output);
+
+private:
+	vtkbisIpsilateralConnMap(const vtkbisIpsilateralConnMap& src){};
+	vtkbisIpsilateralConnMap& operator=(const vtkbisIpsilateralConnMap& rhs){};
+	float Threshold;
+	vtkImageData* ImageMask;
+	int Range;
+	int Abs;
+	vtkImageData* OutData2;
+	//int LookN;
+	int Optimize;
+	int Type;
+	//int OutputRaw;
+	int DoContralateral;
+	//BTX
+	std::string FileName;
+	//ETX
+	double LMean;
+	double LStd;
+	double RMean;
+	double RStd;
+	double LDegreeMean;
+	double LDegreeStd;
+	double RDegreeMean;
+	double RDegreeStd;
+	int LSize;
+	int RSize;
+
+};
+
+#endif /* VTKBISIPSILATERALINTRINSICCONNCONTRAST_H_ */
+
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisMedianTemporalSmoothing.cpp b/bioimagesuite30_src/Connectivity/vtkbisMedianTemporalSmoothing.cpp
new file mode 100644
index 0000000..45d1187
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisMedianTemporalSmoothing.cpp
@@ -0,0 +1,207 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+/*
+ * vtkbisMedianTemporalSmoothing.cpp
+ *
+ *  Created on: Aug 20, 2008
+ *      Author: Isabella Murphy,Xilin Shen
+ *      @Input:4D image
+ *      @Output:Smoothed image using median. Kernel size = 2*radius+1.
+ */
+#include "vtkbisMedianTemporalSmoothing.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkpxMath.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkbisConnectivityUtility.h"
+#include "vtkIntArray.h"
+
+
+// This creates the "New" Function
+vtkStandardNewMacro(vtkbisMedianTemporalSmoothing);
+
+vtkbisMedianTemporalSmoothing::vtkbisMedianTemporalSmoothing()
+{
+  this->Radius=1;
+  this->ImageMask=NULL;
+  //this->Result=NULL;
+}
+
+vtkbisMedianTemporalSmoothing::~vtkbisMedianTemporalSmoothing()
+{
+  this->SetImageMask(NULL);
+  //if (this->Result!=NULL)
+  //       this->SetResult(NULL);
+}
+/*-------------------------------------------------------------------------------------
+ * force the output data type to double, need to change extend information to let
+ * the pipeline know the difference
+ * @Set: output data type = double
+ */
+int vtkbisMedianTemporalSmoothing::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+					  vtkInformationVector *outputVector)
+{
+	vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+	vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+	return 1;
+}
+// ---------------------------------------------------------------------------
+void vtkbisMedianTemporalSmoothing::SmoothVoxel(vtkDataArray* inpdata,vtkDataArray* outdata,int voxel,
+					       int numframes,int radius)
+{
+
+  int length=2*radius+1;double imagevalue;int temparrindex;double median;
+
+  //create a temporary array to hold the frames that is going
+  //to pass into GetMeidan method to calculate median
+  // 30 is a large number > max number needed
+  float temparr[30];
+
+  for (int f=0;f<numframes;f++)
+    {
+      for (int t=-radius;t<=radius;t++)
+	{
+    	  int frame=f+t;
+    	  if (frame<0)
+    		  frame=0;
+    	  else if (frame>=numframes)
+    		  frame=numframes-1;
+
+    	  imagevalue=inpdata->GetComponent(voxel,frame);
+    	  temparrindex=t+radius;
+    	  temparr[temparrindex]=imagevalue;
+	}
+      median=vtkpxMath::GetMedian(length, temparr);
+      outdata->SetComponent(voxel,f,median);
+    }
+}
+
+// ---------------------------------------------------------------------------
+void vtkbisMedianTemporalSmoothing::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+	fprintf(stderr,"Beginning vtkbisMedianTemporalSmoothing use radius=%d\n",
+				  this->Radius);
+
+	if (this->ImageMask!=NULL)
+	{
+		int dim[3]; this->ImageMask->GetDimensions(dim);
+	    int dim2[3]; input->GetDimensions(dim2);
+	    int sum=0;
+	    for (int ia=0;ia<=2;ia++)
+	     sum+=abs(dim[ia]-dim2[ia]);
+	    if (sum>0)
+	    {
+	     fprintf(stderr,"Bad Mask Input to vtkbisMedianTemporalSmoothing SimpleExecute\n");
+	     return;
+	    }
+	}
+    vtkDataArray*   inp=input->GetPointData()->GetScalars();
+    int nt=inp->GetNumberOfTuples();
+    int nc=input->GetNumberOfScalarComponents();
+
+    vtkDataArray*   out=output->GetPointData()->GetScalars();
+    // Cleanup first -- fill output with zeros
+    for (int c=0;c<nc;c++)
+      out->FillComponent(c,0.0);
+
+
+  int length=2*this->Radius+1;
+
+  vtkDataArray* msk=NULL;
+    if (this->ImageMask!=NULL)
+      msk=this->ImageMask->GetPointData()->GetScalars();
+
+
+  //fprintf(stderr,"The ratio is: %.2f",vtkbisConnectivityUtility::ComputeRatio(input, this->ImageMask, this->Threshold) );
+//Test some functions has nothing to do with this class
+  //vtkbisConnectivityUtility::ImagetoText( input, "test.txt");
+
+  //vtkbisConnectivityUtility::TexttoImage("test.txt",result);
+ /*   if (this->Result!=NULL)
+        this->Result->Delete();
+    Result = vtkImageData::New();
+
+    vtkIntArray* frames = vtkIntArray::New();
+    frames->SetNumberOfTuples(3);
+    frames->SetNumberOfComponents(2);
+    for (int ia=0;ia<2;ia++)
+    {
+    	frames->FillComponent(ia,0);
+    }
+
+    frames->SetComponent(0,0,1);
+    frames->SetComponent(0,1,2);
+    frames->SetComponent(1,0,4);
+    frames->SetComponent(1,1,5);
+    frames->SetComponent(2,0,7);
+    frames->SetComponent(2,1,8);
+    vtkbisConnectivityUtility::ExtractImageBlocks(input,Result,frames);
+    frames->Delete();
+*/
+  int maxcount=int(nt/10);
+  int count=0;
+  double pog=0.0;
+
+  this->UpdateProgress(0.01);
+
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+	  int doglm=1;
+	  if (msk!=NULL)
+	  {
+	  	if (msk->GetComponent(voxel,0)<1)
+	  			  doglm=0;
+	  }
+	  if (doglm)
+	  {
+		  this->SmoothVoxel(inp,out,voxel,nc,this->Radius);
+	  }
+	  ++count;
+	  if (count==maxcount)
+	  {
+		  pog=double(voxel)/double(nt);
+	  	  this->UpdateProgress(pog);
+	  	  count=0;
+	  	  //fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,double(numdone)/double(nt));
+	  }
+    }
+  this->UpdateProgress(1.0);
+}
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisMedianTemporalSmoothing.h b/bioimagesuite30_src/Connectivity/vtkbisMedianTemporalSmoothing.h
new file mode 100644
index 0000000..23994ae
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisMedianTemporalSmoothing.h
@@ -0,0 +1,100 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisMedianTemporalSmoothing.h
+ *
+ *  Created on: Aug 20, 2008
+ *      Author: Isabella Murphy; Xilin Chen
+ */
+
+#ifndef VTKBISMEDIANTEMPORALSMOOTHING_H_
+#define VTKBISMEDIANTEMPORALSMOOTHING_H_
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+
+class vtkbisMedianTemporalSmoothing: public vtkpxSimpleImageToImageFilter {
+
+public:
+	vtkTypeMacro(vtkbisMedianTemporalSmoothing,vtkpxSimpleImageToImageFilter);
+	// Description:
+	// Construct object to extract all of the input data.
+	static vtkbisMedianTemporalSmoothing *New();
+
+	// Mask Image
+	vtkSetObjectMacro(ImageMask,vtkImageData);
+	vtkGetObjectMacro(ImageMask,vtkImageData);
+
+	//Test functions has nothing to do with this class
+  //result Image
+	//vtkSetObjectMacro(Result,vtkImageData);
+	//vtkGetObjectMacro(Result,vtkImageData);
+/*
+	//Threshold
+	vtkSetClampMacro(Threshold,double,0,1);
+	vtkGetMacro(Threshold,double);
+	*/
+	//Radius
+	vtkSetClampMacro(Radius,int,1,9);
+	vtkGetMacro(Radius,int);
+
+
+protected:
+	vtkbisMedianTemporalSmoothing();
+	virtual ~vtkbisMedianTemporalSmoothing();
+
+	virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+						  vtkInformationVector *outputVector);
+	// Execute Function -- main function
+	virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+	virtual void SmoothVoxel(vtkDataArray* inpdata,vtkDataArray* outdata,int index,int numframes,int radius);
+
+
+private:
+	vtkbisMedianTemporalSmoothing(const vtkbisMedianTemporalSmoothing& src){};
+	vtkbisMedianTemporalSmoothing& operator=(const vtkbisMedianTemporalSmoothing& rhs){};
+	int Radius;
+	vtkImageData* ImageMask;
+	//double Threshold;
+	//vtkImageData* Result;
+
+
+};
+
+#endif /* VTKBISMEDIANTEMPORALSMOOTHING_H_ */
+
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisROICorrelation.cpp b/bioimagesuite30_src/Connectivity/vtkbisROICorrelation.cpp
new file mode 100644
index 0000000..b1f3bf9
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisROICorrelation.cpp
@@ -0,0 +1,212 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisROICorrelation.cpp
+ *
+ *  Created on: Sep 30, 2008
+ *      Author: Isabella Murphy; Xilin Lin
+ * @Input: 4D vtkImageData object of the whole image and a 4D vtkImageData object of the ROI average time course
+ * @output: 4D vtkImageData object with correlation among each voxel of the image to each ROI region.
+ * For example, correlation of voxel 0 to each ROI (say 0-10) is stored in output vtkImagedata voxel 0 component 0-10;
+ * correlation of voxel 1 to each ROI (say 0-10) is stored in output vtkImageData voxel 1 component 0-10 and so on.
+ * In the output image, xyz=input dimension, component=number of ROI regions
+ */
+
+#include "vtkbisROICorrelation.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkObjectFactory.h"
+#include "vtkObject.h"
+#include "vtkPointData.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkbisTimeSeriesCorrelation.h"
+#include "vtkbisImageTimeSeriesNormalize.h"
+#include <math.h>
+
+using namespace std;
+
+vtkbisROICorrelation::vtkbisROICorrelation() {
+  this->AverageROI= NULL;
+  this->ImageMask=NULL;
+  this->OutputRaw=0;
+}
+
+vtkbisROICorrelation::~vtkbisROICorrelation() {
+  this->SetAverageROI(NULL);
+  this->SetImageMask(NULL);
+
+}
+
+vtkbisROICorrelation* vtkbisROICorrelation::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisROICorrelation");
+  if(ret)
+    {
+      return (vtkbisROICorrelation*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisROICorrelation;
+}
+//----------------------------------------------------------------------------------------------------------------------
+//RequestInformation
+//I. Our vtkImageData input has number of components = number of frames but output vtkImageData object has number of
+//components = roint.
+//II. Input and Output has different number of voxels, has to let the pipeline know it (change extend)
+//need to call RequstInformation to set those differences.
+// ---------------------------------------------------------------------------------------------------------------------------
+int vtkbisROICorrelation::RequestInformation (vtkInformation * request,
+			vtkInformationVector ** inputVector,
+			vtkInformationVector * outputVector)
+{
+  //vtkInformation *inInfo =  inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  //int wholeExtent[6];
+  //inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
+  //int dim[3];dim[0]= wholeExtent[1]+1;dim[1]= wholeExtent[3]+1;dim[2]= wholeExtent[5]+1;
+  //wholeExtent[3] = dim[0]*dim[1]*dim[2]-1;
+  vtkDataArray* roi=NULL;
+  if (this->AverageROI!=NULL)
+    roi=this->AverageROI->GetPointData()->GetScalars();
+  else
+    cout<<"bad input for vtkbisROICorrelation: no average ROI image"<<endl;
+  int roint = roi->GetNumberOfTuples();//number of regions
+  //wholeExtent[1]=roint-1;
+
+  /*fprintf(stderr,"\n\nInput Whole Extent=%d:%d,%d:%d,%d:%d",
+    wholeExtent[0],wholeExtent[1],
+    wholeExtent[2],wholeExtent[3],
+    wholeExtent[4],wholeExtent[5]);*/
+
+  //outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6);//change extend
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, roint);//set number of components to roint
+
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisROICorrelation::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+  fprintf(stderr,"Beginning vtkbisROICorrelation\n");
+
+  if (this->ImageMask!=NULL)
+    {
+      int dim[3]; this->ImageMask->GetDimensions(dim);
+      int dim2[3]; input->GetDimensions(dim2);
+      int sum=0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=abs(dim[ia]-dim2[ia]);
+      if (sum>0)
+	{
+	  fprintf(stderr,"Bad Mask Input to vtkbisROICorrelation SimpleExecute\n");
+	  return;
+	}
+    }
+
+  if (this->AverageROI->GetNumberOfScalarComponents()!=input->GetNumberOfScalarComponents())
+    {
+      fprintf(stderr,"Bad ROI Image in vtkbisROICorrelation SimpleExecute\n");
+      return;
+    }
+
+
+
+  vtkbisImageTimeSeriesNormalize* norm1=vtkbisImageTimeSeriesNormalize::New();
+  norm1->SetInput(input);
+  norm1->Update();
+
+  vtkImageData* temp=vtkImageData::New();
+  temp->ShallowCopy(norm1->GetOutput());
+  norm1->Delete();
+
+  vtkDataArray*   inp=temp->GetPointData()->GetScalars();
+
+  vtkbisImageTimeSeriesNormalize* norm2=vtkbisImageTimeSeriesNormalize::New();
+  norm2->SetInput(this->AverageROI);
+  norm2->Update();
+
+  vtkImageData* temp2=vtkImageData::New();
+  temp2->ShallowCopy(norm2->GetOutput());
+  norm2->Delete();
+  vtkDataArray*   roi=(vtkFloatArray*)temp2->GetPointData()->GetScalars();
+
+  int nt=inp->GetNumberOfTuples();//number of voxels
+  int nc=inp->GetNumberOfComponents();//number of frames (time series)
+  float factor=1.0/float(nc);
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  int ncout=out->GetNumberOfComponents();
+  for (int ia=0;ia<ncout;ia++)
+    out->FillComponent(ia,0.0);
+
+
+  int roint = roi->GetNumberOfTuples();//number of regions
+  int roinc = roi->GetNumberOfComponents();//number of frames (time series)
+
+
+  vtkDataArray* msk=NULL;
+  if (this->ImageMask!=NULL)
+    msk=this->ImageMask->GetPointData()->GetScalars();
+
+  this->UpdateProgress(0.01);
+  //Calculate correlation
+
+  // For each voxel
+  for (int voxel = 0; voxel<nt;voxel++)
+  {
+    int docompute=1;
+    if (msk!=NULL)
+      {
+	if (msk->GetComponent(voxel,0)<1)
+	  docompute=0;
+      }
+
+    if (docompute)
+      {
+	for (int roiindex = 0; roiindex<roint; roiindex++)
+    	  {
+	    //	      double rho=vtkbisTimeSeriesCorrelation::ComputeCorrelationCoefficient(inp,voxel,roi,roiindex);
+	    float rho=vtkbisTimeSeriesCorrelation::ComputePreNormalizedCorrelationCoefficient(inp,voxel,roi,roiindex,factor,nc);
+	    if (this->OutputRaw)
+	      out->SetComponent(voxel,roiindex,rho);
+	    else
+	      out->SetComponent(voxel,roiindex,vtkbisTimeSeriesCorrelation::RhoToZConversion(rho));
+	    //std::cout<<out->GetComponent(voxel,roiindex)<<";";
+    	  }
+	//    	  std::cout<<endl;
+      }
+  }
+
+  temp->Delete();
+  temp2->Delete();
+
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisROICorrelation.h b/bioimagesuite30_src/Connectivity/vtkbisROICorrelation.h
new file mode 100644
index 0000000..46450ed
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisROICorrelation.h
@@ -0,0 +1,94 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisROICorrelation.h
+ *
+ *  Created on: Sep 30, 2008
+ *      Author: Isabella Murphy, Xilin Lin
+ *      @Input: a 4D vtkImageData object (Brain image) with average time courses and a 4D ROI average time courses image
+ *      @Output: a 4D vtkImageData object with correlation of the two input images
+ */
+
+#ifndef VTKBISROICORRELATION_H_
+#define VTKBISROICORRELATION_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkInformation;
+class vtkInformationVector;
+
+class vtkbisROICorrelation : public vtkSimpleImageToImageFilter{
+public:
+	static vtkbisROICorrelation *New();
+	vtkTypeMacro(vtkbisROICorrelation,vtkSimpleImageToImageFilter);
+
+	// ROI Image
+	vtkSetObjectMacro(AverageROI,vtkImageData);
+	vtkGetObjectMacro(AverageROI,vtkImageData);
+
+	// Mask Image
+	vtkSetObjectMacro(ImageMask,vtkImageData);
+	vtkGetObjectMacro(ImageMask,vtkImageData);
+
+  // Raw Correlation vs Z-value
+  vtkSetClampMacro(OutputRaw,int,0,1);
+  vtkGetMacro(OutputRaw,int);
+
+
+protected:
+	vtkbisROICorrelation();
+	virtual ~vtkbisROICorrelation();
+	virtual int RequestInformation (vtkInformation * request,
+			vtkInformationVector ** inputVector,
+			vtkInformationVector * outputVector) ;
+
+	virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+	vtkImageData* AverageROI;
+	vtkImageData* ImageMask;
+  int OutputRaw;
+
+private:
+	vtkbisROICorrelation(const vtkbisROICorrelation& src){};
+	vtkbisROICorrelation& operator=(const vtkbisROICorrelation& rhs){};
+};
+
+#endif /* VTKBISROICORRELATION_H_ */
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisROIMean.cpp b/bioimagesuite30_src/Connectivity/vtkbisROIMean.cpp
new file mode 100644
index 0000000..e602012
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisROIMean.cpp
@@ -0,0 +1,362 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisROIMean.cpp
+ *
+ *  Created on: Sep 26, 2008
+ *      Author: Isabella Murphy; Xilin Shen
+ * @Input: 4D image and an ROI(Region of Interest) 3D image,
+ * @output: average time courses in each ROI region.Dimension: number of regions*1*1*N
+ * Assume user name each region using integer
+ * In output vtkImageData object, voxel 0 = region 0, voxel 10 = region 10 and so on.
+ * dimension is number of regions*1*1*N
+ */
+
+#include <vtkbisROIMean.h>
+#include "vtkObjectFactory.h"
+#include "vtkObject.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkPoints.h"
+#include <fstream>
+#include <cstdlib>
+
+using namespace std;
+
+vtkbisROIMean* vtkbisROIMean::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisROIMean");
+  if(ret)
+    {
+      return (vtkbisROIMean*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisROIMean;
+}
+
+vtkbisROIMean::vtkbisROIMean() {
+  this->ImageROI=NULL;
+  this->NumberOfRegions=0;
+  this->Centroids=NULL;
+  this->DoText = 0;
+  this->ImageMask=NULL;
+  this->AddRegion = 0;
+}
+
+vtkbisROIMean::~vtkbisROIMean() {
+  this->SetImageROI(NULL);
+  if (this->Centroids!=NULL)
+    this->Centroids->Delete();
+  this->SetImageMask(NULL);
+}
+void vtkbisROIMean::SetFileName(const char* filename)
+{
+  this->FileName=filename;
+}
+
+const char* vtkbisROIMean::GetFileName()
+{
+  return this->FileName.c_str();
+}
+void vtkbisROIMean::SetFileName2(const char* filename2)
+{
+  this->FileName2=filename2;
+}
+
+const char* vtkbisROIMean::GetFileName2()
+{
+  return this->FileName2.c_str();
+}
+
+/*-------------------------------------------------------------------------------------
+ * Input/Output number of voxels are different, need to change extend information to let
+ * the pipeline know the difference
+ * @Set: output dimension = number of regions*1*1*N
+ * !!!Output will loose the ROI region information
+ */
+int vtkbisROIMean::RequestInformation(vtkInformation *request,
+				      vtkInformationVector **inputVector,
+				      vtkInformationVector *outputVector)
+{
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  int wholeExtent[6];
+  for(int i = 0;i<6;i++)
+    wholeExtent[i]=0;
+
+  vtkDataArray* roi=NULL;
+  if (this->ImageROI!=NULL)
+    roi=this->ImageROI->GetPointData()->GetScalars();
+
+  double range[2];
+  roi->GetRange(range);
+  std::cout<<"ROI region min="<<range[0]<<" max="<<range[1]<<endl;
+
+  this->NumberOfRegions = int(range[1]);
+  if ( this->AddRegion >0 ) {
+	  this->NumberOfRegions +=(int)this->AddRegion ;
+  }
+
+  wholeExtent[1]= this->NumberOfRegions-1;
+  /*fprintf(stderr,"\n\nOutput Whole Extent=%d:%d,%d:%d,%d:%d",
+	  wholeExtent[0],wholeExtent[1],
+	  wholeExtent[2],wholeExtent[3],
+	  wholeExtent[4],wholeExtent[5]);
+*/
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisROIMean::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+
+  fprintf(stderr,"Beginning vtkbisROIMean\n");
+  int dim[3];
+  int dim2[3];
+  int dim3[3];
+
+
+ input->GetDimensions(dim);
+ fprintf(stderr," Input dim=%d x %d x %d , nframes=%d\n",
+	 dim[0],dim[1],dim[2],input->GetNumberOfScalarComponents());
+
+ output->GetDimensions(dim);
+ fprintf(stderr," Output dim=%d x %d x %d , nframes=%d\n",
+	 dim[0],dim[1],dim[2],output->GetNumberOfScalarComponents());
+
+
+  if (this->ImageMask!=NULL)
+    {
+      int dim3[3]; this->ImageMask->GetDimensions(dim3);
+      int dim2[3]; input->GetDimensions(dim2);
+      int sum=0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=abs(dim3[ia]-dim2[ia]);
+      if (sum>0)
+	{
+	  fprintf(stderr,"Bad Mask Input to vtkbisROIMean SimpleExecute\n");
+	  return;
+	}
+    }
+
+  if (this->ImageROI!=NULL)
+    {
+      this->ImageROI->GetDimensions(dim);
+      input->GetDimensions(dim2);
+      int sum=0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=abs(dim[ia]-dim2[ia]);
+      if (sum>0)
+	{
+    	  fprintf(stderr,"Bad ROI Input to vtkbisROIMean SimpleExecute\n");
+    	  return;
+       }
+     }
+   else
+   {
+     cout<<"bad input to vtkbisROIMean, no ROI image."<<endl;
+     return;
+   }
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  int nt=inp->GetNumberOfTuples();//number of voxels
+  int nc=inp->GetNumberOfComponents();//number of frames
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  for (int ia=0;ia<nc;ia++)
+    out->FillComponent(ia,0.0);
+
+  vtkDataArray* roi=NULL;
+  if (this->ImageROI!=NULL)
+    roi=this->ImageROI->GetPointData()->GetScalars();
+
+  vtkDataArray* msk=NULL;
+  if (this->ImageMask!=NULL)
+    msk=this->ImageMask->GetPointData()->GetScalars();
+
+  this->UpdateProgress(0.01);
+
+  if (this->Centroids==NULL)
+    {
+      this->Centroids=vtkPoints::New();
+    }
+  //double range[2];
+  //roi->GetRange(range);
+  //std::cout<<"region min:"<<range[0]<<"region max:"<<range[1]<<endl;
+  //this->NumberOfRegions = int(range[1]);
+  //if ( this->AddRegion >0 )
+  //{
+	  //this->NumberOfRegions +=(int)this->AddRegion ;
+  //}
+  this->Centroids->SetNumberOfPoints(this->NumberOfRegions+1);// As many points as ROIs
+  //fprintf(stderr,"In Simple Execute, Number Of Regions = %d\n",this->NumberOfRegions);
+
+  double* x=new double[this->NumberOfRegions+1];
+  double* y=new double[this->NumberOfRegions+1];
+  double* z=new double[this->NumberOfRegions+1];
+  double* num=new double[this->NumberOfRegions+1];
+  double position[3];
+  //initialize to 0
+
+  double range[2];  roi->GetRange(range);
+  int minroi=int(range[0])+1;
+
+  for (int i=0;i<=this->NumberOfRegions;i++)
+  {
+      x[i]=0.0; y[i]=0.0; z[i]=0.0; num[i]=0.0;
+  }
+
+  //do something voxel by voxel
+  for (int i=0;i< nt;i++)
+  {
+      int doinclude=1;
+      if (msk!=NULL)
+      {
+    	  if (msk->GetComponent(i,0)<1)
+    		  doinclude=0;
+      }
+      if (doinclude)
+      {
+    	  //guarantee that the first frame of the output will not be all 0
+    	  int regionLabel = (int)roi->GetComponent(i,0)-minroi;
+    	  //int regionLabel = (int)roi->GetComponent(i,0);
+    	  input->GetPoint(i,position);//get x,y,z location of the voxel
+
+    	  if (regionLabel >=0 )
+    	  {
+    		  for(int j=0;j<nc;j++)
+    			  out->SetComponent(regionLabel,j,out->GetComponent(regionLabel,j)+inp->GetComponent(i,j));
+    		  x[regionLabel]+=position[0];
+    		  y[regionLabel]+=position[1];
+    		  z[regionLabel]+=position[2];
+    		  num[regionLabel]+=1.0;
+    	  }
+
+      }
+   }
+
+
+
+
+  int maxcount=int(nt/10);
+  int count=0;
+  double pog=0.0;
+  //calculate mean time series of each ROI region
+  for (int region=0;region<=this->NumberOfRegions;region++)
+  {
+	  //std::cout<<"region:"<<region;
+
+    if (num[region]>0.00001)
+	{
+    	 //std::cout<<" Num:"<<num[region]<<endl;
+
+    	x[region]=x[region]/num[region];
+    	y[region]=y[region]/num[region];
+    	z[region]=z[region]/num[region];
+
+    	for (int j=0;j<nc;j++)
+    	{
+    		//std::cout<<"data:"<<out->GetComponent(region,j)<<"num:"<<num[region]<<endl;
+    		out->SetComponent(region,j,out->GetComponent(region,j)/num[region]);
+	 	}
+
+    	this->Centroids->SetPoint(region,x[region],y[region],z[region]);
+	}
+    else
+    {
+
+    	this->Centroids->SetPoint(region,-10000,-10000,-10000);
+    }
+
+  }
+
+
+  if(this->DoText == 1 )
+  {
+
+    /*  if(this->NumberOfRegions > 400 || nc > 500 )
+      {
+    	  fprintf(stderr, "number of voxels or number of frames > 400. Too much data to export.");
+    	  return;
+      }
+*/
+      std::ofstream myfile(this->FileName.c_str());
+
+      if(!myfile.is_open())
+      {
+    	  cout<< "Unable to open file"<<this->FileName.c_str()<<"\n";
+    	  return;
+      }
+      myfile<<"ROI \t ";
+      for (int ia=0;ia<this->NumberOfRegions;ia++)
+    	  myfile<<"ROI "<< ia <<"\t";
+      myfile<<"\n";
+      for(int i = 0; i < nc;i++)
+      {
+    	  myfile<<i<<"\t";
+    	  for (int j = 0; j<this->NumberOfRegions;j++)
+    	  {
+    		  myfile<<out->GetComponent(j,i)<< "\t";
+    	  }
+    	  myfile<<"\n";
+      }
+      myfile.close();
+
+      //*******************************************
+      //file output for Alark Viewer
+      //*******************************************
+      std::ofstream alarkfile(this->FileName2.c_str());
+
+      if(!alarkfile.is_open())
+      {
+    	  cout<< "Unable to open file "<<this->FileName2.c_str()<<"\n";
+          return;
+      }
+      alarkfile<<"#Connectivity file\n#Points\n"<<this->NumberOfRegions<<"\n# index x y z label\n";
+      for(int i=0;i<this->NumberOfRegions;i++)
+      {
+    	  alarkfile<<i<<"\t"<<x[i]<<"\t"<<y[i]<<"\t"<<z[i]<<"\t"<<i+1<<"\n";
+      }
+      alarkfile.close();
+
+  }//end of DoText==1
+
+  delete [] x; delete [] y; delete []z  ; delete [] num ;
+
+  this->UpdateProgress(1.0);
+
+}
+
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisROIMean.h b/bioimagesuite30_src/Connectivity/vtkbisROIMean.h
new file mode 100644
index 0000000..ba95961
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisROIMean.h
@@ -0,0 +1,113 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*!
+ * vtkbisROIMean.h
+ *
+ *  Created on: Sep 26, 2008
+ *      Author: Isabella Murphy; Xilin Lin
+ *      calculate the mean time series of each ROI region
+ */
+
+#ifndef VTKBISROIMEAN_H_
+#define VTKBISROIMEAN_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include <string>
+#include <iostream>
+
+class vtkInformation;
+class vtkPoints;
+class vtkInformationVector;
+
+
+class vtkbisROIMean : public vtkSimpleImageToImageFilter {
+
+public:
+
+  static vtkbisROIMean *New();
+  vtkTypeMacro(vtkbisROIMean,vtkSimpleImageToImageFilter);
+
+  // ROI Image
+  vtkSetObjectMacro(ImageROI,vtkImageData);
+  vtkGetObjectMacro(ImageROI,vtkImageData);
+
+  // ROI Centroids
+  vtkGetObjectMacro(Centroids,vtkPoints);
+
+  // File name
+  virtual void SetFileName(const char* filename);
+  virtual const char* GetFileName();
+  // File name
+  virtual void SetFileName2(const char* filename2);
+  virtual const char* GetFileName2();
+
+  //DoText
+  vtkSetClampMacro(DoText,int,0,1);
+  vtkGetMacro(DoText,int);
+
+  //AddRegion
+  vtkSetClampMacro(AddRegion,double,0,100);
+  vtkGetMacro(AddRegion,double);
+
+  //NumberOfRegions
+  vtkGetMacro(NumberOfRegions,int);
+
+
+  // Mask Image
+  vtkSetObjectMacro(ImageMask,vtkImageData);
+  vtkGetObjectMacro(ImageMask,vtkImageData);
+
+protected:
+  vtkbisROIMean();
+  virtual ~vtkbisROIMean();
+  virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+				 vtkInformationVector *outputVector);
+
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+  vtkImageData* ImageROI;
+  int NumberOfRegions;
+  vtkPoints*    Centroids;
+  //BTX
+  std::string FileName;
+  std::string FileName2;
+  //ETX
+
+  int DoText;
+  double AddRegion;
+  vtkImageData* ImageMask;
+
+
+private:
+  vtkbisROIMean(const vtkbisROIMean& src){};
+  vtkbisROIMean& operator=(const vtkbisROIMean& rhs){};
+};
+
+#endif /* VTKBISROIMEAN_H_ */
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisROIMean_rt.cpp b/bioimagesuite30_src/Connectivity/vtkbisROIMean_rt.cpp
new file mode 100644
index 0000000..df6f8b9
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisROIMean_rt.cpp
@@ -0,0 +1,327 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisROIMean_rt.cpp
+ *
+ *  Created on: Sep 26, 2008
+ *      Author: Isabella Murphy; Xilin Shen
+ * @Input: 4D image and an ROI(Region of Interest) 3D image,
+ * @output: average time courses in each ROI region.Dimension: number of regions*1*1*N
+ * Assume user name each region using integer
+ * In output vtkImageData object, voxel 0 = region 0, voxel 10 = region 10 and so on.
+ * dimension is number of regions*1*1*N
+ */
+
+#include <vtkbisROIMean_rt.h>
+#include "vtkObjectFactory.h"
+#include "vtkObject.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkPoints.h"
+#include <vector>
+#include <fstream>
+#include <cstdlib>
+
+using namespace std;
+
+vtkbisROIMean_rt* vtkbisROIMean_rt::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisROIMean_rt");
+  if(ret)
+    {
+      return (vtkbisROIMean_rt*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisROIMean_rt;
+}
+
+vtkbisROIMean_rt::vtkbisROIMean_rt() {
+  this->ImageROI=NULL;
+  this->NumberOfRegions=0;
+  this->Centroids=NULL;
+  this->DoText = 0;
+  this->ImageMask=NULL;
+  this->AddRegion = 0;
+  this->MinThreshold = -1;
+}
+
+vtkbisROIMean_rt::~vtkbisROIMean_rt() {
+  this->SetImageROI(NULL);
+  if (this->Centroids!=NULL)
+    this->Centroids->Delete();
+  this->SetImageMask(NULL);
+}
+void vtkbisROIMean_rt::SetFileName(const char* filename)
+{
+  this->FileName=filename;
+}
+
+const char* vtkbisROIMean_rt::GetFileName()
+{
+  return this->FileName.c_str();
+}
+/*-------------------------------------------------------------------------------------
+ * Input/Output number of voxels are different, need to change extend information to let
+ * the pipeline know the difference
+ * @Set: output dimension = number of regions*1*1*N
+ * !!!Output will loose the ROI region information
+ */
+int vtkbisROIMean_rt::RequestInformation(vtkInformation *request,
+				      vtkInformationVector **inputVector,
+				      vtkInformationVector *outputVector)
+{
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  int wholeExtent[6];
+  for(int i = 0;i<6;i++)
+    wholeExtent[i]=0;
+
+  vtkDataArray* roi=NULL;
+  if (this->ImageROI!=NULL)
+    roi=this->ImageROI->GetPointData()->GetScalars();
+
+  double range[2];
+  roi->GetRange(range);
+  std::cout<<"region min:"<<range[0]<<"region max:"<<range[1]<<endl;
+
+  this->NumberOfRegions = int(range[1]);
+  if ( this->AddRegion == 1 ) {
+	  this->NumberOfRegions +=1;
+  }
+
+  wholeExtent[1]= this->NumberOfRegions-1;
+  fprintf(stderr,"\n\nOutput Whole Extent=%d:%d,%d:%d,%d:%d",
+	  wholeExtent[0],wholeExtent[1],
+	  wholeExtent[2],wholeExtent[3],
+	  wholeExtent[4],wholeExtent[5]);
+
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisROIMean_rt::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+
+  fprintf(stderr,"Beginning vtkbisROIMean_rt");
+  int dim[3];
+  int dim2[3];
+  int dim3[3];
+
+
+ input->GetDimensions(dim);
+ fprintf(stderr,"dim=%d x %d x %d , nframes=%d\n",
+	 dim[0],dim[1],dim[2],input->GetNumberOfScalarComponents());
+
+ output->GetDimensions(dim);
+ fprintf(stderr,"dim=%d x %d x %d , nframes=%d\n",
+	 dim[0],dim[1],dim[2],output->GetNumberOfScalarComponents());
+
+
+  if (this->ImageROI==NULL)
+    {
+      fprintf(stderr,"Bad ROI Specified\n");
+      exit(0);
+    }
+
+  if (this->ImageMask!=NULL)
+    {
+      int dim3[3]; this->ImageMask->GetDimensions(dim3);
+      int dim2[3]; input->GetDimensions(dim2);
+      int sum=0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=abs(dim3[ia]-dim2[ia]);
+      if (sum>0)
+	{
+	  fprintf(stderr,"Bad Mask Input to vtkbisROIMean_rt SimpleExecute\n");
+	  return;
+	}
+    }
+
+  if (this->ImageROI!=NULL)
+    {
+      this->ImageROI->GetDimensions(dim);
+      input->GetDimensions(dim2);
+      int sum=0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=abs(dim[ia]-dim2[ia]);
+      if (sum>0)
+	{
+    	  fprintf(stderr,"Bad ROI Input to vtkbisROIMean_rt SimpleExecute\n");
+    	  return;
+       }
+     }
+   else
+   {
+     cout<<"bad input to vtkbisROIMean_rt, no ROI image."<<endl;
+     return;
+   }
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  int nt=inp->GetNumberOfTuples();//number of voxels
+  int nc=inp->GetNumberOfComponents();//number of frames
+
+  //fprintf(stderr,"nt=%d , nc=%d\n\n",nt,nc);
+
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  for (int ia=0;ia<nc;ia++)
+    out->FillComponent(ia,0.0);
+
+  vtkDataArray* roi=NULL;
+  if (this->ImageROI!=NULL)
+    roi=this->ImageROI->GetPointData()->GetScalars();
+
+  vtkDataArray* msk=NULL;
+  if (this->ImageMask!=NULL)
+    msk=this->ImageMask->GetPointData()->GetScalars();
+
+  this->UpdateProgress(0.01);
+
+  if (this->Centroids==NULL)
+    {
+      this->Centroids=vtkPoints::New();
+    }
+  this->Centroids->SetNumberOfPoints(this->NumberOfRegions+1);// As many points as ROIs
+  fprintf(stderr,"Number Of Regions = %d\n",this->NumberOfRegions);
+
+  double* x=new double[this->NumberOfRegions+1];
+  double* y=new double[this->NumberOfRegions+1];
+  double* z=new double[this->NumberOfRegions+1];
+  double* num=new double[this->NumberOfRegions+1];
+  double position[3];
+  //initialize to 0
+
+  double range[2];  roi->GetRange(range);
+  int minroi=int(range[0])+1;
+
+  for (int i=0;i<=this->NumberOfRegions;i++)
+    {
+      x[i]=0.0; y[i]=0.0; z[i]=0.0; num[i]=0.0;
+    }
+
+  //do something voxel by voxel
+  for (int i=0;i< nt;i++)
+    {
+      int doinclude=1;
+      if (msk!=NULL)
+	{
+    	  if (msk->GetComponent(i,0)<1)
+	    doinclude=0;
+	}
+      if (doinclude)
+	{
+    	  int regionLabel = (int)roi->GetComponent(i,0)-minroi;
+    	  //int regionLabel = (int)roi->GetComponent(i,0)-1;
+    	  input->GetPoint(i,position);//get x,y,z location of the voxel
+
+    	  if (regionLabel >=0 )
+	    {
+	      if (inp->GetComponent(i,0)>this->MinThreshold)
+		{
+		  for(int j=0;j<nc;j++)
+		    out->SetComponent(regionLabel,j,out->GetComponent(regionLabel,j)+inp->GetComponent(i,j));
+		  x[regionLabel]+=position[0];
+		  y[regionLabel]+=position[1];
+		  z[regionLabel]+=position[2];
+		num[regionLabel]+=1.0;
+		}
+	      else
+		{
+		  roi->SetComponent(i,0,0);
+		}
+	    }
+	}
+    }
+
+  int maxcount=int(nt/10);
+  int count=0;
+  double pog=0.0;
+  //calculate mean time series of each ROI region
+  for (int region=0;region<=this->NumberOfRegions;region++)
+    {
+      if (num[region]>0.00001)
+	{
+	  x[region]=x[region]/num[region];
+	  y[region]=y[region]/num[region];
+	  z[region]=z[region]/num[region];
+
+	  for (int j=0;j<nc;j++)
+	    {
+	      //std::cout<<"data:"<<out->GetComponent(region,j)<<"num:"<<num[region]<<endl;
+	      out->SetComponent(region,j,out->GetComponent(region,j)/num[region]);
+	    }
+
+	  this->Centroids->SetPoint(region,x[region],y[region],z[region]);
+	}
+      else
+	this->Centroids->SetPoint(region,-1.0,-1.0,-1.0);
+    }
+
+
+  if(this->DoText == 1 )
+    {
+      if(this->NumberOfRegions > 400 || nc > 500 )
+	{
+    	  fprintf(stderr, "number of voxels or number of frames > 400. Too much data to export.");
+    	  return;
+	}
+
+      std::ofstream myfile(this->FileName.c_str());
+      if(!myfile.is_open())
+	{
+    	  cout<< "Unable to open file"<<this->FileName.c_str()<<"/n";
+    	  return;
+	}
+      myfile<<"ROI \t ";
+      for (int ia=0;ia<this->NumberOfRegions;ia++)
+	myfile<<"ROI "<< ia <<"\t";
+      myfile<<"\n";
+      for(int i = 0; i < nc;i++)
+	{
+    	  myfile<<i<<"\t";
+    	  for (int j = 0; j<this->NumberOfRegions;j++)
+	    {
+	      myfile<<out->GetComponent(j,i)<< "\t";
+	    }
+    	  myfile<<"\n";
+	}
+      myfile.close();
+    }
+
+  delete [] x; delete [] y; delete []z  ; delete [] num ;
+  this->UpdateProgress(1.0);
+}
+
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisROIMean_rt.h b/bioimagesuite30_src/Connectivity/vtkbisROIMean_rt.h
new file mode 100644
index 0000000..8b1aa7f
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisROIMean_rt.h
@@ -0,0 +1,114 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*!
+ * vtkbisROIMean_rt.h
+ *
+ *  Created on: Sep 26, 2008
+ *      Author: Isabella Murphy; Xilin Lin
+ *      calculate the mean time series of each ROI region
+ */
+
+#ifndef VTKBISROIMEAN_H_
+#define VTKBISROIMEAN_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include <string>
+#include <iostream>
+
+class vtkInformation;
+class vtkPoints;
+class vtkInformationVector;
+
+
+class vtkbisROIMean_rt : public vtkSimpleImageToImageFilter {
+
+public:
+
+  static vtkbisROIMean_rt *New();
+  vtkTypeMacro(vtkbisROIMean_rt,vtkSimpleImageToImageFilter);
+
+  // ROI Image
+  vtkSetObjectMacro(ImageROI,vtkImageData);
+  vtkGetObjectMacro(ImageROI,vtkImageData);
+
+  // ROI Centroids
+  vtkGetObjectMacro(Centroids,vtkPoints);
+
+  // File name
+  virtual void SetFileName(const char* filename);
+  virtual const char* GetFileName();
+
+  //DoText
+  vtkSetClampMacro(DoText,int,0,1);
+  vtkGetMacro(DoText,int);
+
+  //MinThreshold
+  vtkSetClampMacro(MinThreshold,int,-1,10000);
+  vtkGetMacro(MinThreshold,int);
+
+  //AddRegion
+  vtkSetClampMacro(AddRegion,int,0,1);
+  vtkGetMacro(AddRegion,int);
+
+  //NumberOfRegions
+  vtkGetMacro(NumberOfRegions,int);
+
+
+  // Mask Image
+  vtkSetObjectMacro(ImageMask,vtkImageData);
+  vtkGetObjectMacro(ImageMask,vtkImageData);
+
+protected:
+  vtkbisROIMean_rt();
+  virtual ~vtkbisROIMean_rt();
+  virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+				 vtkInformationVector *outputVector);
+
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+  vtkImageData* ImageROI;
+  int NumberOfRegions;
+  vtkPoints*    Centroids;
+  int MinThreshold;
+  //BTX
+  std::string FileName;
+  //ETX
+
+  int DoText;
+  int AddRegion;
+  vtkImageData* ImageMask;
+
+
+private:
+  vtkbisROIMean_rt(const vtkbisROIMean_rt& src){};
+  vtkbisROIMean_rt& operator=(const vtkbisROIMean_rt& rhs){};
+};
+
+#endif /* VTKBISROIMEAN_H_ */
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisRemoveGlobalTemporalDrift.cpp b/bioimagesuite30_src/Connectivity/vtkbisRemoveGlobalTemporalDrift.cpp
new file mode 100644
index 0000000..cb1266e
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisRemoveGlobalTemporalDrift.cpp
@@ -0,0 +1,218 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*!
+ * vtkbisRemoveGlobalTemporalDrift.cpp
+ *
+ *  Created on: Aug 28, 2008
+ *      Author: Isabella Murphy, Xilin Shen
+ *
+ * Use Legendre Polynomial or power to the order to create a LSQ matrix
+ * to model the potential drift of fMRI data
+ */
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkbisRemoveGlobalTemporalDrift.h"
+#include "vtkbisTimeSeriesNormalize.h"
+#include "vtkFloatArray.h"
+
+vtkbisRemoveGlobalTemporalDrift* vtkbisRemoveGlobalTemporalDrift::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisRemoveGlobalTemporalDrift");
+  if(ret)
+    {
+      return (vtkbisRemoveGlobalTemporalDrift*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisRemoveGlobalTemporalDrift;
+}
+
+// -------------------------------------------------------------------------------------------------
+vtkbisRemoveGlobalTemporalDrift::vtkbisRemoveGlobalTemporalDrift()
+{
+  this->OutputNormalized=1;
+  this->NormalizedThreshold=1;
+  this->Threshold=0.05;
+}
+
+void vtkbisRemoveGlobalTemporalDrift::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+
+  fprintf(stderr,"Beginning RemoveGlobalTemporalDrift use legendre=%d order=%d\n",
+		  this->UseLegendrePolynomials,this->Order);
+
+
+  vtkDataArray* msk=NULL;
+  if (this->ImageMask!=NULL)
+    {
+      int dim[3]; this->ImageMask->GetDimensions(dim);
+      int dim2[3]; input->GetDimensions(dim2);
+      int sum=0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=abs(dim[ia]-dim2[ia]);
+      if (sum>0)
+	{
+    	  fprintf(stderr,"Bad Mask Input to vtkbisRemoveGlobalTemporalDrift SimpleExecute\n");
+    	  return;
+	}
+      msk=this->ImageMask->GetPointData()->GetScalars();
+    }
+
+
+  double thr=this->Threshold;
+  if (this->NormalizedThreshold>0)
+    {
+      double range[2]; input->GetPointData()->GetScalars()->GetRange(range);
+      thr=this->Threshold*(range[1]-range[0])+range[0];
+    }
+
+
+  vtkImageData* normalized=vtkImageData::New();
+  normalized->CopyStructure(output);
+  normalized->SetNumberOfScalarComponents(output->GetNumberOfScalarComponents());
+  normalized->AllocateScalars();
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkFloatArray* stats=vtkFloatArray::New();
+  stats->SetNumberOfComponents(2);
+  stats->SetNumberOfTuples(inp->GetNumberOfTuples());
+  int numframes=inp->GetNumberOfComponents();
+  int nt=inp->GetNumberOfTuples();
+  double scalefactor=1.0/double(numframes);
+
+  vtkDataArray* norminp=normalized->GetPointData()->GetScalars();
+
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      double sum=0.0,sum2=0.0;
+      for (int i=0;i<numframes;i++)
+	{
+	  double v=inp->GetComponent(voxel,i);
+	  sum+=v;
+	  sum2+=v*v;
+	}
+      double mean=sum*scalefactor;
+      double sigma=sqrt(sum2*scalefactor-mean*mean);
+      stats->SetComponent(voxel,0,mean);
+      stats->SetComponent(voxel,1,sigma);
+      if (sigma<0.00001)
+	sigma=0.00001;
+      for (int i=0;i<numframes;i++)
+	norminp->SetComponent(voxel,i,(inp->GetComponent(voxel,i)-mean)*sigma);
+    }
+  
+  double numgood=0.0;
+
+
+  double* sumarray=new double[numframes];
+  for (int i=0;i<numframes;i++)
+    sumarray[i]=0.0;
+
+  double range[2];
+  inp->GetRange(range);
+
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      int usevoxel=1;
+      if (msk!=NULL)
+	{
+    	  if (msk->GetComponent(voxel,0)<1)
+	    usevoxel=0;
+	}
+      else 
+	{
+	  double v=inp->GetComponent(voxel,0);
+	  if (v<thr)
+	    usevoxel=0;
+	}
+      
+      if (usevoxel)
+	{
+	  numgood+=1.0;
+	  for (int i=0;i<numframes;i++)
+	    sumarray[i]+=norminp->GetComponent(voxel,i);
+	}
+    }
+  if (numgood==0.0)
+    numgood=1.0;
+
+  for (int i=0;i<numframes;i++)
+    sumarray[i]/=numgood;
+
+  fprintf(stderr,"So far, numgood=%f\n",numgood);
+  
+  this->UpdateProgress(0.1);
+
+
+  vtkpxMatrix* LSQ=this->ComputeLSQMatrix(this->Order,numframes);
+  vtkpxMatrix* temp2=vtkpxMatrix::New();
+  temp2->Zeros(this->Order+1,1);
+
+  vtkpxMatrix* temp1=vtkpxMatrix::New();
+  temp1->Zeros(numframes,1);
+  for (int i=0;i<numframes;i++)
+    temp1->SetDirectElement(i,0,sumarray[i]);
+
+  vtkpxMatrix::Multiply(LSQ,temp1,temp2);  
+  this->UpdateProgress(0.2);
+
+  fprintf(stderr,"Global Polynomial Fit: ");
+  for (int p=0;p<=this->Order;p++)
+    fprintf(stderr,"p[%d]=%.6f ",p,temp2->GetDirectElement(p,0));
+  fprintf(stderr,"\n");
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      for (int ia=0;ia<numframes;ia++)
+	{
+	  double t=this->ComputeTime(ia,numframes);
+	  double v=norminp->GetComponent(voxel,ia);
+	  for (int p=1;p<=this->Order;p++)
+	    v=v-temp2->GetDirectElement(p,0)*Polynomial(t,p);
+	  if (this->OutputNormalized==0)
+	    v=v*stats->GetComponent(voxel,1)+stats->GetComponent(voxel,0);
+	  out->SetComponent(voxel,ia,v);
+	}
+    }
+  
+  
+  this->UpdateProgress(0.99);
+  delete [] sumarray;
+  LSQ->Delete();
+  temp1->Delete();
+  temp2->Delete();
+  stats->Delete();
+  normalized->Delete();
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisRemoveGlobalTemporalDrift.h b/bioimagesuite30_src/Connectivity/vtkbisRemoveGlobalTemporalDrift.h
new file mode 100644
index 0000000..db0cef6
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisRemoveGlobalTemporalDrift.h
@@ -0,0 +1,79 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*!
+ * vtkbisRemoveGlobalTemporalDrift.cpp
+ *
+ *  Created on: Aug 28, 2008
+ *      Author: Isabella Murphy, Xilin Chen
+ *
+ * Use Legendre Polynomial or power function to create a LSQ matrix
+ * to model the potential drift of fMRI data
+ */
+
+#ifndef __vtkbisRemoveGlobalTemporalDrift_h
+#define __vtkbisRemoveGlobalTemporalDrift_h
+
+#include "vtkbisRemoveTemporalDrift.h"
+#include "vtkImageData.h"
+#include "vtkpxMatrix.h"
+
+
+class vtkbisRemoveGlobalTemporalDrift : public vtkbisRemoveTemporalDrift
+{
+public:
+  static vtkbisRemoveGlobalTemporalDrift *New();
+  vtkTypeMacro(vtkbisRemoveGlobalTemporalDrift,vtkbisRemoveTemporalDrift);
+
+  // Output Normalized time series (mean 100), default is off
+  vtkSetClampMacro(OutputNormalized,int,0,1);
+  vtkGetMacro(OutputNormalized,int);
+
+  // Parameters
+  // Defaults is 5% of maximum mean intensity
+  vtkSetMacro(Threshold,double);
+  vtkGetMacro(Threshold,double);
+
+  vtkSetClampMacro(NormalizedThreshold, int,0,1);
+  vtkGetMacro(NormalizedThreshold, int);
+  vtkBooleanMacro(NormalizedThreshold, int);
+
+
+protected:
+
+  vtkbisRemoveGlobalTemporalDrift();
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+  int OutputNormalized;
+  double Threshold;
+  int NormalizedThreshold;
+    
+};
+#endif
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisRemoveSliceMean.cpp b/bioimagesuite30_src/Connectivity/vtkbisRemoveSliceMean.cpp
new file mode 100644
index 0000000..aa6c0b3
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisRemoveSliceMean.cpp
@@ -0,0 +1,256 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisRemoveSliceMean.cpp
+ *
+ *  Created on: Aug 28, 2008
+ *      Author: Isabella Murphy, Xilin Shen
+ *
+ * Subtract slice mean of each frame for each voxel
+ */
+
+#include "vtkbisRemoveSliceMean.h"
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include <math.h>// for the sqrt function
+#include "pxisinf.h"
+
+vtkbisRemoveSliceMean* vtkbisRemoveSliceMean::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisRemoveSliceMean");
+  if(ret)
+    {
+      return (vtkbisRemoveSliceMean*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisRemoveSliceMean;
+}
+
+vtkbisRemoveSliceMean::vtkbisRemoveSliceMean()
+{
+	this->ImageMask = NULL;
+}
+
+vtkbisRemoveSliceMean::~vtkbisRemoveSliceMean()
+{
+  this->SetImageMask(NULL);
+}
+/*-------------------------------------------------------------------------------------
+ * force the output data type to double, need to change extend information to let
+ * the pipeline know the difference
+ * @Set: output data type = double
+ */
+int vtkbisRemoveSliceMean::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+					  vtkInformationVector *outputVector)
+{
+	vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+	vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+	return 1;
+}
+/*!-----------------------------------------------------------------------------------------------------------
+* Calculate mean of one slice for each frame
+* @param[in]inpdata: input image
+* @param[in]mask: mask image
+* @param[in]numvoxels: number of voxels in one slice (one depth in the 3D image)
+* @param[in]slice: which slice we are going to work on , an offset value for calculating voxel position
+* @param[in]numtimepoints: number for time points (number of frames)
+* @param[out]outarr: output array. It will store the mornalized mean of the slice for each time points
+*/
+void vtkbisRemoveSliceMean::CalculateSliceMean(vtkDataArray* inpdata,vtkDataArray* mask,
+		double* outarr, int numvoxels, int slice, int numtimepoints)
+{
+
+	int voxel = 0;
+	double tempsum=0;
+	double meanInnerproduct = 0;
+	int f,i;
+	double normV = 0;
+	int usedvoxels = 0;
+
+
+  for (f=0;f<numtimepoints; f++)
+    {
+	  for (i=0; i<numvoxels; i++)
+	  {
+		  voxel = slice+i;
+		  int doGlm = 1;
+		  if (mask != NULL)
+		  	 {
+		  		  if (mask->GetComponent(voxel,0)<1)
+		  		  {
+		  			doGlm=0;
+		  		  }
+		  		//std::cout<<"voxel:"<<voxel<<"do gui:"<<doGlm;
+		  	 }
+		  if(doGlm)
+		  {
+			  tempsum += inpdata->GetComponent(voxel,f);
+			  ++usedvoxels;
+			  //std::cout<<"voxel:"<<voxel<<"get here 1!"<<endl;
+		  }
+	  }
+	  outarr[f] = tempsum/usedvoxels;//mean
+
+	  if (isnan(outarr[f]) || isinf(outarr[f]))
+	  {
+		  //std::cout<<"Aslice:"<<slice;
+		  outarr[f]=0.0;
+	  }
+
+	  //std::cout<<"f"<<f<<"tempsum:"<<tempsum<<"usedvoxel:"<<usedvoxels;
+	  tempsum = 0;
+	  usedvoxels = 0;
+      meanInnerproduct += pow(outarr[f],2);
+    }
+  normV = sqrt(meanInnerproduct);
+
+  if (normV<0.00001){
+	  normV=1.0;
+  }
+
+
+  if (isnan(normV) || isinf(normV)){
+	  normV=1.0;
+  }
+
+
+  //normalize the mean for each time point
+
+  for (f=0;f<numtimepoints;f++)
+  {
+	  //std::cout<<"slice:"<<slice<<"f:"<<f<<"="<<outarr[f]<<"norm:"<<normV;
+	  outarr[f]/=normV;
+  }
+
+}
+/*!--------------------------------------------------------------------
+ * This method subtract slice mean of each frame for a voxel
+ * x-(innerproduct of x and mean)*mean
+ * @param[in]inp: input vtkDataArray pointer
+ * @param[in]outarr: array pointer, outarr hold the normalized slice mean of each frame calculated by this->CalculateSliceMean method
+ * @param[in]int voxel:the voxel we will work on
+ * @param[in]numc: number of frames a voxel has
+ * @param[out]out: ouput vtkDataArray pointer
+ */
+void vtkbisRemoveSliceMean::RemoveMean(vtkDataArray* inp, vtkDataArray* out,double* outarr, int voxel, int numc)
+{
+	double innerproduct = 0;
+	int m,f;
+
+	for (m=0; m<numc; m++)
+		innerproduct += inp->GetComponent(voxel, m)*outarr[m];
+
+	for (f=0; f<numc; f++){
+		out->SetComponent(voxel,f,inp->GetComponent(voxel, f)-innerproduct*outarr[f]);
+		//std::cout<<"voxel:"<<voxel<<"f:"<<f<<"="<<out->GetComponent(voxel,f)<<endl;
+	}
+}
+// ---------------------------------------------------------------------------
+void vtkbisRemoveSliceMean::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+	fprintf(stderr,"Beginning vtkbisRemoveSliceMean \n");
+	int dim[3];
+	int dimMask[3];
+	int numc = 0;//number of components
+	int voxel= 0;
+    int slice = 0;
+    int numvoxel= 0; //number of voxels in one slice
+    int sum=0;
+    int i,j,k,f,ia;
+
+    input->GetDimensions(dim);
+
+    if (this->ImageMask!=NULL)
+    {
+    	this->ImageMask->GetDimensions(dimMask);
+    	for (ia=0;ia<=2;ia++)
+    		sum += abs(dim[ia]-dimMask[ia]);
+    	if (sum>0)
+    	{
+    		fprintf(stderr,"Bad Mask Input to vtkbisRemoveSliceMean SimpleExecute\n");
+            return;
+        }
+    }
+
+    vtkDataArray*   inp=input->GetPointData()->GetScalars();
+    vtkDataArray*   out=output->GetPointData()->GetScalars();
+    vtkDataArray*   mask = NULL;
+    if (this->ImageMask!=NULL)
+    	mask=this->ImageMask->GetPointData()->GetScalars();
+
+    numc=input->GetNumberOfScalarComponents();
+    double* outarr=new double[numc];//create an array to hold the mean on all time points t
+    numvoxel=dim[0]*dim[1];//number of voxel per slice
+
+    // Cleanup first -- fill output with zeros
+    for (f=0;f<numc;f++)
+    	out->FillComponent(f,0.0);
+
+    this->UpdateProgress(0.01);// for the use interface to show progress
+
+    for (k=0;k<dim[2];k++)
+      {
+	//calculate time course mean for each slice on each time point
+	slice=numvoxel*k;
+
+	this->CalculateSliceMean(inp,mask,outarr,numvoxel,slice, numc);
+	//std::cout<<"get here 2!"<<endl;
+
+	for (j=0;j<dim[1];j++)
+	  {
+	    for (i=0;i<dim[0];i++)
+	      {
+		int doGlm=1;
+		if (mask!=NULL)
+		  {
+		    if (mask->GetComponent(voxel,0)<1)
+		      {
+			doGlm=0;
+		      }
+		  }
+		if(doGlm)
+		  {
+		    this->RemoveMean(inp,out,outarr,voxel,numc);
+		    //std::cout<<"get here 3!"<<endl;
+		  }
+		++voxel;
+	      }
+	  }
+	this->UpdateProgress(float(k+1)/float(dim[2]));
+      }
+
+    this->UpdateProgress(1.0);
+    delete [] outarr;
+}
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisRemoveSliceMean.h b/bioimagesuite30_src/Connectivity/vtkbisRemoveSliceMean.h
new file mode 100644
index 0000000..d679be2
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisRemoveSliceMean.h
@@ -0,0 +1,76 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisRemoveSliceMean.h
+ *
+ *  Created on: Aug 28, 2008
+ *      Author: Isabella Murphy, Xilin Chen
+ *
+ * Subtract slice mean of each frame for each voxel
+ */
+
+#ifndef VTKBISREMOVESLICEMEAN_H_
+#define VTKBISREMOVESLICEMEAN_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkbisRemoveSliceMean : public vtkSimpleImageToImageFilter{
+public:
+	static vtkbisRemoveSliceMean *New();
+	vtkTypeMacro(vtkbisRemoveSliceMean,vtkSimpleImageToImageFilter);
+
+	// Mask Image
+	vtkSetObjectMacro(ImageMask,vtkImageData);
+	vtkGetObjectMacro(ImageMask,vtkImageData);
+
+
+protected:
+	vtkbisRemoveSliceMean();
+	virtual ~vtkbisRemoveSliceMean();
+
+	virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+						  vtkInformationVector *outputVector);
+	virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+	virtual void RemoveMean(vtkDataArray* inp,vtkDataArray* out,double* outarr,int voxel,int numc);
+	virtual void CalculateSliceMean(vtkDataArray* inpdata,vtkDataArray* mask,
+			double* outarr,int numvoxels,int slice,int numtimepoints);
+
+private:
+	vtkbisRemoveSliceMean(const vtkbisRemoveSliceMean& src){};
+	vtkbisRemoveSliceMean& operator=(const vtkbisRemoveSliceMean& rhs){};
+
+	vtkImageData* ImageMask;
+
+};
+
+#endif /* VTKBISREMOVESLICEMEAN_H_ */
+
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisRemoveTemporalDrift.cpp b/bioimagesuite30_src/Connectivity/vtkbisRemoveTemporalDrift.cpp
new file mode 100644
index 0000000..39fa766
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisRemoveTemporalDrift.cpp
@@ -0,0 +1,309 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*!
+ * vtkbisRemoveTemporalDrift.cpp
+ *
+ *  Created on: Aug 28, 2008
+ *      Author: Isabella Murphy, Xilin Shen
+ *
+ * Use Legendre Polynomial or power to the order to create a LSQ matrix
+ * to model the potential drift of fMRI data
+ */
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkbisRemoveTemporalDrift.h"
+#include "vtkpxAnalyzeImageWriter.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+
+vtkbisRemoveTemporalDrift* vtkbisRemoveTemporalDrift::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisRemoveTemporalDrift");
+  if(ret)
+    {
+      return (vtkbisRemoveTemporalDrift*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisRemoveTemporalDrift;
+}
+
+vtkbisRemoveTemporalDrift::vtkbisRemoveTemporalDrift()
+{
+  this->DebugIndex=-1;
+  this->ImageMask=NULL;
+  this->Order=3;
+  this->UseLegendrePolynomials=1;
+}
+
+vtkbisRemoveTemporalDrift::~vtkbisRemoveTemporalDrift()
+{
+  this->SetImageMask(NULL);
+}
+
+/*-------------------------------------------------------------------------------------
+ * force the output data type to float, need to change extend information to let
+ * the pipeline know the difference
+ * @Set: output data type = float
+ */
+int vtkbisRemoveTemporalDrift::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+					  vtkInformationVector *outputVector)
+{
+	vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+	vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+	return 1;
+}
+/*!---------------------------------------------------------------------------------------------------------------------------
+*Use Legendre polynomial functions or power function to create a matrix.
+*Call this method with outer loop = number of orders, inner loop = number of frame of the input image
+*@param[in]t:the time point (frame) we are working at
+*@param[in]order:order of polynomial (0=constant,1=linear etc.)
+*@/return a double value
+*/
+double vtkbisRemoveTemporalDrift::Polynomial(double t, int order)
+{
+    if (order<0)
+      order=0;
+    else if (order>6)
+      order=6;
+
+    if (this->UseLegendrePolynomials)
+      {
+	switch(order)
+	  {
+	  case 0: // P_0(x)=1;
+	    return 1.0;
+	    break;
+	  case 1: // P_1(x)=x;
+	    return t;
+	    break;
+	  case 2: // P_2(x)=0.5*(3x^2-1)
+	    return 1.5*t*t-0.5;
+	    break;
+	  case 3: // P_3(x) =0.5*(5x^3-3x)
+	    return 2.5*t*t*t-1.5*t;
+	    break;
+	  case 4: // P_4(x) = 1/8*(35x^4-30x^2+3)
+	    return 0.125*35*t*t*t*t-0.125*30*t*t+0.375;
+	    break;
+	  case 5: // P_5(x) = 1/8*(63*x^5-70*x^3+15x)
+	    return 0.125*63*t*t*t*t*t-0.125*70*t*t*t+0.125*15*t;
+	    break;
+	  case 6: // P_6(x) = 1/16*(231x^6-315x^4+105x^2-5)
+	    return (231*t*t*t*t*t*t-315*t*t*t*t+105*t*t-5)/16;
+	    break;
+	  }
+      }
+
+
+	return pow(t,order);
+
+ }
+/*! ---------------------------------------------------------------------------------------------------------------------------
+* a function that return a “central” representation for time frame: col-(numframes-1)/2.
+* has to change range to -1 to 1, there for divid the result with
+* (numframes-1)/2
+*@param[in]col: the column(frame) we are working on
+*@param[in]numframe: total number of frames
+*@/return centralized representation for time frame (range from -1 to 1)
+*/
+double vtkbisRemoveTemporalDrift::ComputeTime(int col,int numframes)
+{
+	if ((numframes-1)<0.00001)
+		return ((double)col)-((double)numframes-1)*0.5;
+	else
+		return (((double)col)-((double)numframes-1)*0.5)/(((double)numframes-1)*0.5);
+}
+/*!---------------------------------------------------------------------------------------------------------------------------
+*  Problem : A x = B  where X is unknown
+*  First pre-multiply by A':  A'A x = A'B
+*  Solution x = (A'A)^{-1}.A'.B
+*  LSQ = (A'A)^{-1}.A'
+*@param[in]order: order of LSQ
+*@param[in]numframes: number of frames of the input image
+*@/return LSQ matrix
+*/
+vtkpxMatrix* vtkbisRemoveTemporalDrift::ComputeLSQMatrix(int order,int numframes)
+{
+	double v;
+  vtkpxMatrix* At=vtkpxMatrix::New();
+  At->Zeros(order+1,numframes);
+
+  for (int row=0;row<=order;row++)
+    {
+      for (int col=0;col<numframes;col++)
+		  {
+			  double t=this->ComputeTime(col,numframes);
+			  v=Polynomial(t,row);
+			  At->SetElement(row,col,v);
+		  }
+    }
+  //At->Print();
+
+  vtkpxMatrix* A=vtkpxMatrix::New();
+  A->Copy(At);
+  A->Transpose();
+
+  vtkpxMatrix* AtA=vtkpxMatrix::New();
+  vtkpxMatrix::Multiply(At,A,AtA);
+  AtA->Invert();
+
+  vtkpxMatrix* LSQ=vtkpxMatrix::New();
+  vtkpxMatrix::Multiply(AtA,At,LSQ);
+
+  AtA->Delete();
+  At->Delete();
+  A->Delete();
+  return LSQ;
+
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+/*void vtkbisRemoveTemporalDrift::StoreVoxelIndexIntoColumn(vtkDataArray* dat,int index,vtkpxMatrix* colvect,int nc)
+{
+  for (int i=0;i<nc;i++)
+    colvect->SetDirectElement(i,0,dat->GetComponent(index,i));
+}*/
+//----------------------------------------------------------------------------------------------------------------------------
+void vtkbisRemoveTemporalDrift::EliminatePolynomial(vtkDataArray* inp,vtkDataArray* out,int index,int order,
+						    int numframes,
+						    vtkpxMatrix* LSQ,
+						    vtkpxMatrix* temp1,vtkpxMatrix* temp2)
+{
+	double t,v,test;int p;
+  //Store value of each frame of voxel x into temp1 vector
+  for (int i=0;i<numframes;i++)
+	  temp1->SetDirectElement(i,0,inp->GetComponent(index,i));
+
+  //temp2 = LSQ*temp1
+  vtkpxMatrix::Multiply(LSQ,temp1,temp2);
+  //  temp2->Print("Params");
+
+  //for every frame, subtract LSQ*temp1*polynomial(a very small number)
+  for (int ia=0;ia<numframes;ia++)
+    {
+      t=this->ComputeTime(ia,numframes);
+      v=inp->GetComponent(index,ia);
+      //std::cout<<"OV:"<<v<<endl;
+      test = 0;
+      for (p=0;p<=order;p++)
+      {
+    	  //std::cout<<"t2:"<<temp2->GetDirectElement(p,0)<<"p:"<<Polynomial(t,p)<<endl;
+    	  test+=temp2->GetDirectElement(p,0)*Polynomial(t,p);
+    	  //std::cout<<"test:"<<test<<endl;
+      }
+      v =v-test;
+    	  out->SetComponent(index,ia,v);
+    	  //std::cout<<"NV:"<<v<<endl;
+    }
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisRemoveTemporalDrift::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+
+  fprintf(stderr,"Beginning RemoveTemporalDrift use legendre=%d order=%d\n",
+		  this->UseLegendrePolynomials,this->Order);
+
+
+  if (this->ImageMask!=NULL)
+    {
+      int dim[3]; this->ImageMask->GetDimensions(dim);
+      int dim2[3]; input->GetDimensions(dim2);
+      int sum=0;
+      for (int ia=0;ia<=2;ia++)
+    	  sum+=abs(dim[ia]-dim2[ia]);
+      if (sum>0)
+      {
+    	  fprintf(stderr,"Bad Mask Input to vtkbisRemoveTemporalDrift SimpleExecute\n");
+    	  return;
+      }
+    }
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  int nt=inp->GetNumberOfTuples();
+  int nc=inp->GetNumberOfComponents();
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  for (int ia=0;ia<nc;ia++)
+    out->FillComponent(ia,0.0);
+
+  vtkDataArray* msk=NULL;
+  if (this->ImageMask!=NULL)
+    msk=this->ImageMask->GetPointData()->GetScalars();
+
+  int maxcount=int(nt/10);
+  int count=0;
+  double pog=0.0;
+
+  vtkpxMatrix* LSQ=this->ComputeLSQMatrix(this->Order,nc);
+  //LSQ->Print();
+  vtkpxMatrix* temp1=vtkpxMatrix::New();
+  temp1->Zeros(nc,1);
+
+  vtkpxMatrix* temp2=vtkpxMatrix::New();
+  temp2->Zeros(this->Order+1,1);
+
+
+  for (int voxel=0;voxel<nt;voxel++)
+  {
+	  int doglm=1;
+      if (msk!=NULL)
+      {
+    	  if (msk->GetComponent(voxel,0)<1)
+    		  doglm=0;
+      }
+
+      if (doglm)
+      {
+    	  //std::cout<<"[";
+    	  this->EliminatePolynomial(inp,out,voxel,this->Order,nc,LSQ,temp1,temp2);
+    	  //std::cout<<"]"<<endl;
+      }
+
+      ++count;
+      if (count==maxcount)
+      {
+    	  pog=double(voxel)/double(nt);
+    	  this->UpdateProgress(pog);
+    	  count=0;
+    	  //fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,double(numdone)/double(nt));
+      }
+  }
+
+  LSQ->Delete();
+  temp1->Delete();
+  temp2->Delete();
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisRemoveTemporalDrift.h b/bioimagesuite30_src/Connectivity/vtkbisRemoveTemporalDrift.h
new file mode 100644
index 0000000..d21dd24
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisRemoveTemporalDrift.h
@@ -0,0 +1,104 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*!
+ * vtkbisRemoveTemporalDrift.cpp
+ *
+ *  Created on: Aug 28, 2008
+ *      Author: Isabella Murphy, Xilin Chen
+ *
+ * Use Legendre Polynomial or power function to create a LSQ matrix
+ * to model the potential drift of fMRI data
+ */
+
+#ifndef __vtkbisRemoveTemporalDrift_h
+#define __vtkbisRemoveTemporalDrift_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkpxMatrix.h"
+
+
+class vtkbisRemoveTemporalDrift : public vtkSimpleImageToImageFilter
+{
+public:
+  static vtkbisRemoveTemporalDrift *New();
+  vtkTypeMacro(vtkbisRemoveTemporalDrift,vtkSimpleImageToImageFilter);
+
+  // Mask Image
+  vtkSetObjectMacro(ImageMask,vtkImageData);
+  vtkGetObjectMacro(ImageMask,vtkImageData);
+
+
+  // Number of Tasks (last N columns of regressor matrix, first few columns are drift)
+  vtkSetMacro(DebugIndex,int);
+  vtkGetMacro(DebugIndex,int);
+
+  // Description:
+  // Order of Polynomial
+  vtkSetClampMacro(Order,int,0,6);
+  vtkGetMacro(Order,int);
+
+  // Description:
+  // UseLegendrePolynomials
+  vtkSetClampMacro(UseLegendrePolynomials,int,0,1);
+  vtkGetMacro(UseLegendrePolynomials,int);
+
+
+protected:
+
+  vtkbisRemoveTemporalDrift();
+  virtual ~vtkbisRemoveTemporalDrift();
+
+  virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+  					  vtkInformationVector *outputVector);
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual vtkpxMatrix* ComputeLSQMatrix(int order,int numframes);
+  virtual void   EliminatePolynomial(vtkDataArray* inp,vtkDataArray* out,int index,int order,
+				     int numframes,
+				     vtkpxMatrix* LSQ,
+				     vtkpxMatrix* temp1,vtkpxMatrix* temp2);
+
+  //Polynomial(t,order) where t =time and order=order of polynomial (0=constant,1=linear etc.)
+  virtual double Polynomial(double t, int order);
+
+  //return a “central” representation for time frame
+  virtual double ComputeTime(int frame,int numframes);
+
+  int   Order;
+  vtkImageData* ImageMask;
+  int  DebugIndex;
+  int UseLegendrePolynomials;
+
+private:
+	vtkbisRemoveTemporalDrift(const vtkbisRemoveTemporalDrift& src){};
+	vtkbisRemoveTemporalDrift& operator=(const vtkbisRemoveTemporalDrift& rhs){};
+};
+#endif
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisRemoveVolumeMean.cpp b/bioimagesuite30_src/Connectivity/vtkbisRemoveVolumeMean.cpp
new file mode 100644
index 0000000..de6c4b6
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisRemoveVolumeMean.cpp
@@ -0,0 +1,234 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisRemoveVolumeMean.cpp
+ *
+ *  Created on: Aug 28, 2008
+ *      Author: Isabella Murphy, Xilin Shen
+ *
+ * Subtract slice mean of each frame for each voxel
+ */
+
+#include "vtkbisRemoveVolumeMean.h"
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include <math.h>// for the sqrt function
+#include "pxisinf.h"
+
+vtkbisRemoveVolumeMean* vtkbisRemoveVolumeMean::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisRemoveVolumeMean");
+  if(ret)
+    {
+      return (vtkbisRemoveVolumeMean*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisRemoveVolumeMean;
+}
+
+vtkbisRemoveVolumeMean::vtkbisRemoveVolumeMean()
+{
+	this->ImageMask = NULL;
+}
+
+vtkbisRemoveVolumeMean::~vtkbisRemoveVolumeMean()
+{
+  this->SetImageMask(NULL);
+}
+/*-------------------------------------------------------------------------------------
+ * force the output data type to double, need to change extend information to let
+ * the pipeline know the difference
+ * @Set: output data type = double
+ */
+int vtkbisRemoveVolumeMean::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+					  vtkInformationVector *outputVector)
+{
+	vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+	vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+	return 1;
+}
+/*!-----------------------------------------------------------------------------------------------------------
+* Calculate mean of brain for each frame
+* @param[in]inpdata: input image
+* @param[in]mask: mask image
+* @param[in]numvoxels: number of voxels in brain
+* @param[in]numtimepoints: number for time points (number of frames)
+* @param[out]outarr: output array. It will store the mornalized mean of the brain for each time points
+*/
+void vtkbisRemoveVolumeMean::CalculateVolumeMean(vtkDataArray* inpdata,vtkDataArray* mask,
+						 double* outarr, int numvoxels, int numtimepoints)
+{
+  int voxel = 0;
+  double tempsum=0;
+  double meanInnerproduct = 0;
+  int f,i;
+  double normV = 0;
+  int usedvoxels = 0;
+
+
+  for (f=0;f<numtimepoints; f++)
+  {
+      for (i=0; i<numvoxels; i++)
+      {
+    	  //voxel = slice+i;
+    	  int doGlm = 1;
+    	  if (mask != NULL)
+    	  {
+    		  //if (mask->GetComponent(voxel,0)<1)
+    		  if (mask->GetComponent(i,0)<1)
+    		  {
+    			  doGlm=0;
+    		  }
+	      //std::cout<<"voxel:"<<voxel<<"do gui:"<<this->DoGlm<<endl;
+    	  }
+    	  if(doGlm)
+    	  {
+    		  tempsum += inpdata->GetComponent(i,f);
+    		  ++usedvoxels;
+	      //std::cout<<"voxel:"<<voxel<<"get here 1!"<<endl;
+    	  }
+      }
+      outarr[f] = tempsum/usedvoxels;//mean of time f
+      tempsum = 0;
+      usedvoxels = 0;
+      meanInnerproduct += pow(outarr[f],2);
+  }
+  normV = sqrt(meanInnerproduct);
+  if (normV<0.00001)
+  	  normV=1.0;
+  if (isnan(normV) || isinf(normV))
+  	  normV=1.0;
+
+  //normalize the mean for each time point
+  for (f=0;f<numtimepoints;f++)
+  {
+    if (isnan(outarr[f]) || isinf(outarr[f]))
+      outarr[f]=0.0;
+    outarr[f]=outarr[f]/normV;
+    std::cout<<"f:"<<f<<"="<<outarr[f]<<endl;
+  }
+
+}
+/*!--------------------------------------------------------------------
+ * This method subtract slice mean of each frame for a voxel
+ * x-(innerproduct of x and mean)*mean
+ * @param[in]inp: input vtkDataArray pointer
+ * @param[in]outarr: array pointer, outarr hold the normalized slice mean of each frame calculated by this->CalculateVolumeMean method
+ * @param[in]int voxel:the voxel we will work on
+ * @param[in]numc: number of frames a voxel has
+ * @param[out]out: ouput vtkDataArray pointer
+ */
+void vtkbisRemoveVolumeMean::RemoveMean(vtkDataArray* inp, vtkDataArray* out,double* outarr, int voxel, int numc)
+{
+  double innerproduct = 0;
+  int m,f;
+
+  for (m=0; m<numc; m++)
+    innerproduct += inp->GetComponent(voxel, m)*outarr[m];
+
+  for (f=0; f<numc; f++){
+    out->SetComponent(voxel,f,inp->GetComponent(voxel, f)-innerproduct*outarr[f]);
+    //std::cout<<"voxel:"<<voxel<<"f:"<<f<<"="<<out->GetComponent(voxel,f)<<endl;
+  }
+}
+// ---------------------------------------------------------------------------
+void vtkbisRemoveVolumeMean::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+  //fprintf(stderr,"Beginning vtkbisRemoveVolumeMean \n");
+  int dim[3];
+  int dimMask[3];
+  int numc = 0;//number of components
+  int voxel= 0;
+  int slice = 0;
+  int numvoxel= 0; //number of voxels in one slice
+  int sum=0;
+  int i,j,k,f,ia;
+
+  input->GetDimensions(dim);
+
+  if (this->ImageMask!=NULL)
+    {
+      this->ImageMask->GetDimensions(dimMask);
+      for (ia=0;ia<=2;ia++)
+	sum += abs(dim[ia]-dimMask[ia]);
+      if (sum>0)
+    	{
+	  fprintf(stderr,"Bad Mask Input to vtkbisRemoveVolumnMean SimpleExecute\n");
+	  return;
+        }
+    }
+
+    vtkDataArray*   inp=input->GetPointData()->GetScalars();
+    vtkDataArray*   out=output->GetPointData()->GetScalars();
+    vtkDataArray*   mask = NULL;
+    if (this->ImageMask!=NULL)
+    	mask=this->ImageMask->GetPointData()->GetScalars();
+
+    numc=input->GetNumberOfScalarComponents();
+    double* outarr=new double[numc];//create an array to hold the mean on all time points t
+    numvoxel=dim[0]*dim[1]*dim[2];//number of voxel per volume
+
+    // Cleanup first -- fill output with zeros
+    for (f=0;f<numc;f++)
+      out->FillComponent(f,0.0);
+
+    this->UpdateProgress(0.01);// for the use interface to show progress
+
+    this->CalculateVolumeMean(inp,mask,outarr,numvoxel, numc);
+
+    for (k=0;k<dim[2];k++)
+    {
+    	for (j=0;j<dim[1];j++)
+    	{
+    		for (i=0;i<dim[0];i++)
+    		{
+    			int dooperation=1;
+    			if (mask!=NULL)
+    			{
+    				if (mask->GetComponent(voxel,0)<1)
+    					dooperation=0;
+    			}
+    			if(dooperation)
+    			{
+    				this->RemoveMean(inp,out,outarr,voxel,numc);
+    			}
+    			++voxel;
+    		}
+    	}
+    	this->UpdateProgress(float(k+1)/float(dim[2]));
+    }
+    delete [] outarr;
+    this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisRemoveVolumeMean.h b/bioimagesuite30_src/Connectivity/vtkbisRemoveVolumeMean.h
new file mode 100644
index 0000000..9b099bb
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisRemoveVolumeMean.h
@@ -0,0 +1,76 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisRemoveVolumeMean.h
+ *
+ *  Created on: Aug 28, 2008
+ *      Author: Isabella Murphy, Xilin Chen
+ *
+ * Subtract slice mean of each frame for each voxel
+ */
+
+#ifndef VTKBISREMOVESLICEMEAN_H_
+#define VTKBISREMOVESLICEMEAN_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkbisRemoveVolumeMean : public vtkSimpleImageToImageFilter{
+public:
+	static vtkbisRemoveVolumeMean *New();
+	vtkTypeMacro(vtkbisRemoveVolumeMean,vtkSimpleImageToImageFilter);
+
+	// Mask Image
+	vtkSetObjectMacro(ImageMask,vtkImageData);
+	vtkGetObjectMacro(ImageMask,vtkImageData);
+
+
+protected:
+	vtkbisRemoveVolumeMean();
+	virtual ~vtkbisRemoveVolumeMean();
+
+	virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+						  vtkInformationVector *outputVector);
+	virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+	virtual void RemoveMean(vtkDataArray* inp,vtkDataArray* out,double* outarr,int voxel,int numc);
+	virtual void CalculateVolumeMean(vtkDataArray* inpdata,vtkDataArray* mask,
+			double* outarr,int numvoxels,int numtimepoints);
+
+private:
+	vtkbisRemoveVolumeMean(const vtkbisRemoveVolumeMean& src){};
+	vtkbisRemoveVolumeMean& operator=(const vtkbisRemoveVolumeMean& rhs){};
+
+	vtkImageData* ImageMask;
+
+};
+
+#endif /* VTKBISREMOVESLICEMEAN_H_ */
+
+
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisTaskBasedSeedCorrelation.cpp b/bioimagesuite30_src/Connectivity/vtkbisTaskBasedSeedCorrelation.cpp
new file mode 100644
index 0000000..30afc6b
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisTaskBasedSeedCorrelation.cpp
@@ -0,0 +1,471 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisTaskBasedSeedCorrelation.cpp
+ *
+ *  Created on: Jul 23, 2009
+ *      Author: Isabella Murphy,Xilin Shen
+ */
+
+#include <vtkbisTaskBasedSeedCorrelation.h>
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkbisConnectivityUtility.h"
+#include "vtkbisTimeSeriesCorrelation.h"
+#include "vtkbisImageTimeSeriesNormalize.h"
+#include "vtkImageCast.h"
+#include <math.h>
+#include "pxisinf.h"
+
+using namespace std;
+
+vtkbisTaskBasedSeedCorrelation* vtkbisTaskBasedSeedCorrelation::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisTaskBasedSeedCorrelation");
+  if(ret)
+    {
+      return (vtkbisTaskBasedSeedCorrelation*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisTaskBasedSeedCorrelation;
+}
+
+
+vtkbisTaskBasedSeedCorrelation::vtkbisTaskBasedSeedCorrelation() {
+	this->ImageROI=NULL;
+	this->NumberOfRegions=0;
+	this->ImageMask=NULL;
+	this->Matrix=NULL;
+	this->Task=0;
+	this->AddRegion=0;
+	this->DoText = 0;
+
+}
+
+vtkbisTaskBasedSeedCorrelation::~vtkbisTaskBasedSeedCorrelation() {
+	this->SetImageROI(NULL);
+	this->SetImageMask(NULL);
+	this->SetMatrix(NULL);
+}
+void vtkbisTaskBasedSeedCorrelation::SetFileName(const char* filename)
+{
+  this->FileName=filename;
+}
+
+const char* vtkbisTaskBasedSeedCorrelation::GetFileName()
+{
+  return this->FileName.c_str();
+}
+
+//----------------------------------------------------------------------------------------------------------------------
+//RequestInformation
+//I. Our vtkImageData input has number of components = number of frames but output vtkImageData object has number of
+//components = roint.
+//II. Input and Output has different number of voxels, has to let the pipeline know it (change extend)
+//need to call RequstInformation to set those differences.
+// ---------------------------------------------------------------------------------------------------------------------------
+int vtkbisTaskBasedSeedCorrelation::RequestInformation (vtkInformation * request,
+			vtkInformationVector ** inputVector,
+			vtkInformationVector * outputVector)
+{
+	vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+	vtkDataArray* roi=NULL;
+	if (this->ImageROI!=NULL)
+	{
+		roi=this->ImageROI->GetPointData()->GetScalars();
+	}else{
+		std::cout<<"bad input for vtkbisROICorrelation: no average ROI image"<<endl;
+		return 0;
+	}
+
+	double range[2];  roi->GetRange(range);
+	int roint = int(range[1]);//number of regions
+
+	if(this->AddRegion >0)
+	{
+		roint+=(int)this->AddRegion;
+		this->NumberOfRegions=roint;
+	}
+
+	vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, roint);//set number of components to roint
+
+	return 1;
+}
+/*
+ * @Input[inp]: 4D functional image
+ * @Input[roimean]: 4D ROI average time course, regions*1*1*N
+ * @Input[msk]: mask
+ * @Input[nt]: number of tuples
+ * @Input[startframe]: first frame of this block
+ * @Input[endframe]: last frame of this block
+ * @output[out]: sum of correlation(z value) of all the blocks
+ * For example, correlation of voxel 0 to each ROI (say 0-10) is stored in output vtkImagedata voxel 0 component 0-10;
+ * correlation of voxel 1 to each ROI (say 0-10) is stored in output vtkImageData voxel 1 component 0-10 and so on.
+ * In the output image, xyz=input dimension, component=number of ROI regions
+ */
+void vtkbisTaskBasedSeedCorrelation::CalculateSeedCorrelation(vtkFloatArray* inp,vtkFloatArray* roimean,vtkDataArray* msk,int nt,int startframe,int endframe,vtkDataArray* out)
+{
+	double scalefactor=1.0/(double)(endframe-startframe+1);
+
+	//normalize input
+	for(int i=0;i<nt;i++)
+	{
+		int doAlg=1;
+		if (msk!=NULL)
+		{
+			if (msk->GetComponent(i,0)<1)
+				doAlg=0;
+		}
+		if (doAlg)
+		{
+			double sum=0.0,sum2=0.0;
+			for(int j=startframe;j<=endframe;j++)
+			{
+				double v=inp->GetComponent(i,j);
+				//std::cout<<"frame:"<<j<<"v:"<<v;
+				sum+=v;
+				sum2+=v*v;
+			}
+			double mean=sum*scalefactor;
+			double sigma=sqrt(sum2*scalefactor-mean*mean);
+			//std::cout<<"m:"<<mean<<"s"<<sigma;
+			if (sigma<0.00001)
+				sigma=1.0;
+			if (isnan(sigma) || isinf(sigma))
+				sigma=1.0;
+			if (isnan(mean) || isinf(mean))
+				mean=0.0;
+		   //double	sumx = 0;
+			for(int j=startframe;j<=endframe;j++)
+			{
+				//double x = (inp->GetComponent(i,j)-mean)/sigma;
+				//std::cout<<"frame2:"<<j<<"x"<<x<<endl;
+				inp->SetComponent(i,j,(inp->GetComponent(i,j)-mean)/sigma);
+				//sumx+=x*x;
+			}
+			//std::cout<<"v:"<<i<<"sumx"<<sumx<<endl;
+		}
+	}
+
+	//std::cout<<"FISNISH ONE BLOCK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"<<endl;
+
+	//for(int f=startframe;f<=endframe;f++)
+		//std::cout<<"f:"<<f<<"x:"<<inp->GetComponent(15093,f)<<"......";
+
+
+	for (int voxel = 0; voxel<nt;voxel++)
+	{
+		int doAlg=1;
+	    if (msk!=NULL)
+	    {
+	    	if (msk->GetComponent(voxel,0)<1)
+	    		doAlg=0;
+	    }
+	    if (doAlg)
+	    {
+	    	for (int roiindex = 0; roiindex<this->NumberOfRegions; roiindex++)
+	    	{
+	    		float sumx =0;
+	    		float sumy =0;
+	    		double sum=0.0;double gValue = 0;
+	    		for (int i=startframe;i<=endframe;i++)
+	    		{
+
+	    			float x=inp->GetComponent(voxel,i);
+	    			/*if(voxel==15093)
+	    			{
+	    				   //std::cout<<"fagain:"<<i<<"xagain:"<<x<<"........";
+	    			}*/
+	    		    float y=roimean->GetComponent(roiindex,i);
+	    		    //std::cout<<"("<<roiindex<<","<<i<<")"<<y<<endl;
+	    		    float xx = x*x;
+	    		    float yy = y*y;
+	    		    //std::cout<<"x:"<<x<<"y:"<<y<<"|";
+	    		    sum+=x*y;
+	    		    sumx+= xx;
+	    		    sumy+= yy;
+
+	    		}
+	    		//one block's rho/# of frames in that block
+	    		double rho=sum*scalefactor;
+	    		//std::cout<<"start:"<<startframe<<"endframe"<<endframe<<endl;
+	    		//std::cout<<"("<<voxel<<","<<roiindex<<")"<<"sumx"<<sumx<<"sumy"<<sumy<<"sum:"<<sum<<"r:"<<rho<<endl;
+	    		//store sum of z's of each block to out
+	    		if (fabs(rho-1.0)>0.00001)
+	    		{
+	    			/*if((1+rho)/(1-rho)<=0)
+	    			{
+	    				std::cout<<rho<<log((1+rho)/(1-rho));
+	    			}*/
+
+	    			gValue = 0.5*log((1+rho)/(1-rho));
+	    				    		//std::cout<<gValue;
+	    		}
+
+	    		//std::cout<<out->GetComponent(voxel,roiindex);
+
+	    		out->SetComponent(voxel,roiindex,out->GetComponent(voxel,roiindex)+gValue);
+	    		//std::cout<<out->GetComponent(voxel,roiindex);
+	    	  }
+	      }
+	   }
+}
+/*
+ * @Input[inp]: 4D functional image
+ * @Input[roi]: ROI(Region of Interest) 3D image
+ * @Input[msk]: mask
+ * @Input[nt]: number of tuples
+ * @Input[startframe]:first frame of this block
+ * @Input[endframe]:last frame of this block
+ * @output[roimean]: average time courses in each ROI region.Dimension: number of regions*1*1*N
+ * Assume user name each region using integer
+ * In output vtkImageData object, voxel 0 = region 0, voxel 10 = region 10 and so on.
+ * dimension is number of regions*1*1*N
+ */
+void vtkbisTaskBasedSeedCorrelation::CalculateROIMean(vtkFloatArray* inp,vtkFloatArray* roi,vtkDataArray* msk,vtkFloatArray* roimean,int nt,int nc,int startframe,int endframe)
+{
+	//std::cout<<"number of regions in roimean:"<<this->NumberOfRegions<<endl;
+	int* num=new int[this->NumberOfRegions ];
+	for(int ia=0;ia<this->NumberOfRegions;ia++)
+		num[ia]=0;
+	double scalefactor=1.0/(double)(endframe-startframe+1);
+
+	for (int i=0;i<nt;i++)
+	{
+		int doAlg=1;
+	    if (msk!=NULL)
+	    {
+	    	if (msk->GetComponent(i,0)<1)
+	    		doAlg=0;
+	    }
+	    if (doAlg)
+	    {
+	    	int regionLabel = (int)roi->GetComponent(i,0)-1;
+
+	    	if (regionLabel >=0 )
+	    	{
+
+	    		for(int j=startframe;j<=endframe;j++)
+	    		{
+	    			//std::cout<<"region:"<<regionLabel<<"frame:"<<j<<"data1:"<<roimean->GetComponent(regionLabel,j)<<"data2:"<<inp->GetComponent(i,j)<<"sum:"<<roimean->GetComponent(regionLabel,j)+inp->GetComponent(i,j);
+	    			roimean->SetComponent(regionLabel,j,roimean->GetComponent(regionLabel,j)+inp->GetComponent(i,j));
+	    			//std::cout<<"output:"<<roimean->GetComponent(regionLabel,j)<<endl;
+	    		}
+	    		num[regionLabel]+=1;
+	    	}
+	     }
+	}
+
+	for (int region=0;region<this->NumberOfRegions;region++)
+	{
+		if (num[region] >= 1)
+		{
+			double sum=0.0,sum2=0.0;
+			for (int j=startframe;j<=endframe;j++)
+			{
+				//std::cout<<"region:"<<region<<"frame:"<<j<<"data:"<<roimean->GetComponent(region,j)<<"num:"<<num[region];
+				double v=roimean->GetComponent(region,j)/num[region];
+				roimean->SetComponent(region,j,v);
+				sum+=v;
+				sum2+=v*v;
+				//std::cout<<"("<<region<<","<<j<<")= "<<roimean->GetComponent(region,j)<<endl;
+			}
+			double mean=sum*scalefactor;
+			double sigma=sqrt(sum2*scalefactor-mean*mean);
+			if (sigma<0.00001)
+				sigma=1.0;
+			if (isnan(sigma) || isinf(sigma))
+				sigma=1.0;
+			if (isnan(mean) || isinf(mean))
+				mean=0.0;
+			for (int j=startframe;j<=endframe;j++)
+			{
+				//std::cout<<"region:"<<region<<"frame:"<<j<<"data:"<<roimean->GetComponent(region,j)<<"num:"<<num[region];
+				roimean->SetComponent(region,j,(roimean->GetComponent(region,j)-mean)/sigma);
+				//std::cout<<"("<<region<<","<<j<<")= "<<roimean->GetComponent(region,j)<<endl;
+			}
+
+		}
+	}
+	if(this->DoText == 1 )
+	  {
+	      if(this->NumberOfRegions > 400 || nc > 500 )
+	      {
+	    	  fprintf(stderr, "Number of frames > 500. Too much data to export.");
+	    	  return;
+	      }
+
+	      std::ofstream myfile(this->FileName.c_str());
+	      if(!myfile.is_open())
+	      {
+	    	  cout<< "Unable to open file"<<this->FileName.c_str()<<"\n";
+	    	  return;
+	      }
+	      myfile<<"Frame \t ";
+	      for (int ia=0;ia<this->NumberOfRegions;ia++)
+	    	  myfile<<"ROI "<< ia+1 <<"\t";
+	      myfile<<"\n";
+	      for(int i = 0; i < nc;i++)
+	      {
+	    	  myfile<<i<<"\t";
+	    	  for (int j = 0; j<this->NumberOfRegions;j++)
+	    	  {
+	    		  myfile<<roimean->GetComponent(j,i)<< "\t";
+	    	  }
+	    	  myfile<<"\n";
+	      }
+	      myfile.close();
+	  }
+
+	delete [] num;
+}
+void vtkbisTaskBasedSeedCorrelation::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+	fprintf(stderr,"Beginning vtkbisTaskBasedSeedCorrelation\n");
+	int dim2[3]; input->GetDimensions(dim2);
+	if (this->ImageROI==NULL)
+		{
+		   fprintf(stderr,"bad input to vtkbisTaskBasedSeedCorrelation, no ROI image.\n");
+		   exit(0);
+		} else {
+			int dim[3]; this->ImageROI->GetDimensions(dim);
+			int sum=0;
+			for (int ia=0;ia<=2;ia++)
+				sum+=abs(dim[ia]-dim2[ia]);
+			if (sum>0)
+			{
+				fprintf(stderr,"Bad ROI Input to vtkbisTaskBasedSeedCorrelation SimpleExecute\n");
+				return;
+			 }
+		}
+
+		if (this->ImageMask!=NULL)
+		{
+			int dim3[3]; this->ImageMask->GetDimensions(dim3);
+		    int sum=0;
+		    for (int ia=0;ia<=2;ia++)
+		    	sum+=abs(dim3[ia]-dim2[ia]);
+		    if (sum>0)
+		    {
+		    	fprintf(stderr,"Bad Mask Input to vtkbisTaskBasedSeedCorrelation SimpleExecute\n");
+			    return;
+			}
+		}
+
+		vtkImageCast* cast=vtkImageCast::New();
+		cast->SetInput(input);
+		cast->SetOutputScalarTypeToFloat();
+		cast->Update();
+
+		vtkImageData* temp=vtkImageData::New();
+		temp->ShallowCopy(cast->GetOutput());
+		cast->Delete();
+
+		vtkFloatArray* inp=(vtkFloatArray*)temp->GetPointData()->GetScalars();
+		int nt=inp->GetNumberOfTuples();//number of voxels
+		int nc=inp->GetNumberOfComponents();//number of frames
+
+		vtkFloatArray* roi=NULL;
+		if (this->ImageROI!=NULL)
+			roi=(vtkFloatArray*)this->ImageROI->GetPointData()->GetScalars();
+		double range[2];  roi->GetRange(range);
+		//int minroi=int(range[0])+1;
+		this->NumberOfRegions = int(range[1]);//number of regions
+
+		if(this->AddRegion > 0)
+		{
+			this->NumberOfRegions+=(int)this->AddRegion;
+		}
+		std::cout<<"final number of regions:"<<this->NumberOfRegions<<" number of regions added:"<<this->AddRegion<<endl;
+		vtkDataArray* out=output->GetPointData()->GetScalars();
+		for (int ia=0;ia<this->NumberOfRegions;ia++)
+			out->FillComponent(ia,0.0);
+
+
+		vtkDataArray* msk=NULL;
+		if (this->ImageMask!=NULL)
+			msk=this->ImageMask->GetPointData()->GetScalars();
+
+		vtkImageData* AverageROI =vtkImageData::New();
+		AverageROI->SetExtent(0,this->NumberOfRegions-1,0,0,0,0);
+		AverageROI->SetNumberOfScalarComponents(nc);
+		AverageROI->SetScalarTypeToFloat();
+		AverageROI->AllocateScalars();
+		vtkFloatArray* roimean=(vtkFloatArray*)AverageROI->GetPointData()->GetScalars();
+		for(int ia=0;ia<nc;ia++)
+			roimean->FillComponent(ia,0.0);
+
+		int numrows[2];  this->Matrix->GetSize(numrows);
+		vtkIntArray* blockarray = vtkIntArray::New();
+		int numblocks=vtkbisConnectivityUtility::SplitBlocks(this->Matrix,this->Task,numrows[0],blockarray);
+		//std::cout<<"(This information is for Isabella only)number of blocks of task "<<this->Task<<" is "<<numblocks<<endl;
+
+		//1.calculate roi mean for each block, normalize on site(within a block), save in the big roimean array
+		int block=0;int sframe=0;
+		for (int i=0; i<numblocks;i++)
+		{
+			int startframe=(int)blockarray->GetComponent(block,0);
+			int endframe=(int)blockarray->GetComponent(block+1,0);
+			block+=2;
+			this->CalculateROIMean(inp,roi,msk,roimean,nt,nc,startframe,endframe);
+
+		}
+
+
+		//2.calculate correlation
+		block=0;
+		for (int i=0; i<numblocks;i++)
+		{
+			int startframe=(int)blockarray->GetComponent(block,0);
+			int endframe=(int)blockarray->GetComponent(block+1,0);
+			block+=2;
+			this->CalculateSeedCorrelation(inp,roimean,msk,nt,startframe,endframe,out);
+		}
+
+		//3.average all the z values from all the blocks
+		for (int voxel = 0; voxel<nt;voxel++)
+		{
+			for (int region=0;region<this->NumberOfRegions;region++)
+			{
+				if(out->GetComponent(voxel,region) != 0)
+				{
+					out->SetComponent(voxel,region,out->GetComponent(voxel,region)/numblocks);
+					//std::cout<<"voxel"<<voxel<<":"<<out->GetComponent(voxel,region);
+				}
+
+			}
+		}
+		AverageROI->Delete();
+		blockarray->Delete();
+		temp->Delete();
+
+}
+
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisTaskBasedSeedCorrelation.h b/bioimagesuite30_src/Connectivity/vtkbisTaskBasedSeedCorrelation.h
new file mode 100644
index 0000000..4cf8071
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisTaskBasedSeedCorrelation.h
@@ -0,0 +1,108 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisTaskBasedSeedCorrelation.h
+ *
+ *  Created on: Jul 23, 2009
+ *      Author: Isabella Murphy
+ */
+
+#ifndef VTKBISTASKBASEDSEEDCORRELATION_H_
+#define VTKBISTASKBASEDSEEDCORRELATION_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkpxMatrix.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkFloatArray.h"
+
+class vtkbisTaskBasedSeedCorrelation : public vtkSimpleImageToImageFilter {
+public:
+	static vtkbisTaskBasedSeedCorrelation *New();
+	vtkTypeMacro(vtkbisTaskBasedSeedCorrelation,vtkSimpleImageToImageFilter);
+
+	// ROI Image
+	vtkSetObjectMacro(ImageROI,vtkImageData);
+	vtkGetObjectMacro(ImageROI,vtkImageData);
+
+	//NumberOfRegions
+	vtkGetMacro(NumberOfRegions,int);
+
+	// Mask Image
+	vtkSetObjectMacro(ImageMask,vtkImageData);
+	vtkGetObjectMacro(ImageMask,vtkImageData);
+
+	//Matrix
+	vtkSetObjectMacro(Matrix,vtkpxMatrix);
+	vtkGetObjectMacro(Matrix,vtkpxMatrix);
+
+	//Task
+	vtkGetMacro(Task,int);
+	vtkSetClampMacro(Task,int,0,1);
+
+	//AddRange
+	vtkGetMacro(AddRegion,double);
+	vtkSetClampMacro(AddRegion,double,0,100);
+
+	//DoText
+	vtkSetClampMacro(DoText,int,0,1);
+	vtkGetMacro(DoText,int);
+
+	// File name
+	virtual void SetFileName(const char* filename);
+	virtual const char* GetFileName();
+
+
+
+protected:
+	vtkbisTaskBasedSeedCorrelation();
+	virtual ~vtkbisTaskBasedSeedCorrelation();
+	virtual void CalculateROIMean(vtkFloatArray* inp,vtkFloatArray* roi,vtkDataArray* msk,vtkFloatArray* roimean,int nt,int nc,int startframe,int endframe);
+	virtual void CalculateSeedCorrelation(vtkFloatArray* inp,vtkFloatArray*roimean,vtkDataArray* msk,int nt,int startframe,int endframe,vtkDataArray* out);
+	int RequestInformation (vtkInformation * request,
+				vtkInformationVector ** inputVector,
+				vtkInformationVector * outputVector);
+	virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+private:
+	vtkImageData* ImageROI;
+	vtkImageData* ImageMask;
+	vtkpxMatrix* Matrix;
+	int NumberOfRegions;
+	int Task;
+	double AddRegion;
+	int DoText;
+	//BTX
+	std::string FileName;
+	//ETX
+	vtkbisTaskBasedSeedCorrelation(const vtkbisTaskBasedSeedCorrelation& src){};
+	vtkbisTaskBasedSeedCorrelation& operator=(const vtkbisTaskBasedSeedCorrelation& rhs){};
+};
+
+#endif /* VTKBISTASKBASEDSEEDCORRELATION_H_ */
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesCorrelation.cpp b/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesCorrelation.cpp
new file mode 100644
index 0000000..cc0f38a
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesCorrelation.cpp
@@ -0,0 +1,356 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisTimeSeriesCorrelation.cpp
+ *
+ *  Created on: Sep 29, 2008
+ *      Author: Isabella Murphy; Xilin Lin
+ *      Also called matrix correlation, ROI Mean X ROI Mean
+ * @Input: 4D vtkImageData object ,which is the output of vtkbisroimean. Dimension:number of regions*1*1*N
+ * @output: 2D vtkImageData object with correlation among each ROI Mean.Dimension:number of regions *Number of regions*1*1
+ * size = number of time series*number of time series*1*1
+ * For example, correlation of average time course 0 to  (say 0-10) is stored in output
+ * vtkImagedata voxel 0-10 component 0;correlation of average time course 1 to all other
+ * average time course (say 0-10) is stored in output vtkImageData voxel 11-20 component
+ * 0 and so on.
+ * voxel 1 is stored at (1,0,0) ; voxel 2 is stored at (2,0,0)
+ */
+
+#include "vtkbisTimeSeriesCorrelation.h"
+#include "vtkImageData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkObjectFactory.h"
+#include "vtkObject.h"
+#include "vtkPointData.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkbisImageTimeSeriesNormalize.h"
+#include <math.h>
+#include <fstream>
+#include <cstdlib>
+using namespace std;
+
+vtkbisTimeSeriesCorrelation::vtkbisTimeSeriesCorrelation()
+{
+  this->DoText = 0;
+  this->OutputRaw = 0;
+}
+// This creates the "New" Function
+vtkbisTimeSeriesCorrelation* vtkbisTimeSeriesCorrelation::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisTimeSeriesCorrelation");
+  if(ret)
+    {
+      return (vtkbisTimeSeriesCorrelation*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisTimeSeriesCorrelation;
+}
+void vtkbisTimeSeriesCorrelation::SetFileName(const char* filename)
+{
+  this->FileName=filename;
+
+}
+const char* vtkbisTimeSeriesCorrelation::GetFileName()
+{
+  return this->FileName.c_str();
+}
+void vtkbisTimeSeriesCorrelation::SetFileName2(const char* filename2)
+{
+  this->FileName2=filename2;
+}
+
+const char* vtkbisTimeSeriesCorrelation::GetFileName2()
+{
+  return this->FileName2.c_str();
+}
+/*----------------------------------------------------------------------------------------------------------------------
+*RequestInformation
+*I.vtkImageData input has many number of components(number of frames) but output
+*vtkImageData object has number of components = 1,
+*II.the input/output number of voxels is different, need to change extend
+*extend[0],extend[1] for x;extend[2], extend[3] for y; extend[4], extend[5] for z
+*if dimension is 16*4*1 then extend is (0,15,0,3,0,0)
+*need to call RequstInformation to set those difference.
+*/// ---------------------------------------------------------------------------------------------------------------------------
+int vtkbisTimeSeriesCorrelation::RequestInformation (vtkInformation * request,
+						     vtkInformationVector ** inputVector,
+						     vtkInformationVector * outputVector)
+{
+  vtkInformation *inInfo =  inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  int wholeExtent[6];
+  inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
+
+
+  int nvoxels= (wholeExtent[1]+1)*(wholeExtent[3]+1)*(wholeExtent[5]+1);
+
+  //wholeExtent = { 0, width-1, 0 , height -1, 0, depth-1 }
+  //int half=ceil(double(nvoxels*nvoxels)/2.0)+1;
+
+  wholeExtent[0]=0; 	wholeExtent[1]=nvoxels-1;
+  wholeExtent[2]=0; 	wholeExtent[3]=nvoxels-1;
+  wholeExtent[4]=0; 	wholeExtent[5]=0;
+
+  /*wholeExtent[0]=0; 	wholeExtent[1]=half-1;
+    wholeExtent[2]=0; 	wholeExtent[3]=0;
+    wholeExtent[4]=0; 	wholeExtent[5]=0;*/
+
+ /* fprintf(stderr,"\n\nOutput Whole Extent=%d:%d,%d:%d,%d:%d",
+    wholeExtent[0],wholeExtent[1],
+    wholeExtent[2],wholeExtent[3],
+    wholeExtent[4],wholeExtent[5]);
+*/
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6);//change extend
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1);//change number of components
+
+  return 1;
+}
+
+//---------------------------------------------------------------------------------
+// Compute Correlation Coefficient
+//---------------------------------------------------------------------------------
+double vtkbisTimeSeriesCorrelation::RhoToZConversion(double rho)
+{
+
+  double gValue = 0;
+  if (fabs(rho-1.0)>0.00001)
+    gValue = 0.5*log((1+rho)/(1-rho));
+  return gValue;
+}
+//---------------------------------------------------------------------------------
+double vtkbisTimeSeriesCorrelation::ComputeCorrelationCoefficient(vtkDataArray* a1,int index1,vtkDataArray* a2,int index2)
+{
+  if (a1==NULL || a2==NULL)
+    return 0.0;
+  if (a1->GetNumberOfComponents()!=a2->GetNumberOfComponents())
+    return 0.0;
+
+  int nc=a1->GetNumberOfComponents();
+  if (nc<1)
+    return 0.0;
+
+
+  double sumxy=0.0;
+  double sumx=0.0;
+  double sumx2=0.0;
+  double sumy=0.0;
+  double sumy2=0.0;
+
+
+  double factor=1.0/double(nc);
+  for (int i=0;i<nc;i++)
+    {
+      double x=a1->GetComponent(index1,i);
+      double y=a2->GetComponent(index2,i);
+
+      sumx+=x;
+      sumy+=y;
+      sumx2+=x*x;
+      sumy2+=y*y;
+      sumxy+=x*y;
+    }
+
+  double exy=sumxy*factor;
+  double ex2=sumx2*factor;
+  double ex=sumx*factor;
+  double ey2=sumy2*factor;
+  double ey=sumy*factor;
+
+  double numerator=exy-ex*ey;
+  double denom    = sqrt(ex2-ex*ex)*sqrt(ey2-ey*ey);
+
+  if (denom>0.0)
+    return numerator/denom;
+
+  return 0.0;
+}
+
+double vtkbisTimeSeriesCorrelation::ComputePreNormalizedCorrelationCoefficient(vtkDataArray* a1,int index1,vtkDataArray* a2,int index2,double factor,int nc)
+{
+  double sum=0.0;
+
+  if ( (a1->IsA("vtkFloatArray") && a2->IsA("vtkFloatArray")) )
+    {
+      float* x1=((vtkFloatArray*)a1)->GetPointer(index1*nc);
+      float* y1=((vtkFloatArray*)a2)->GetPointer(index2*nc);
+      for (int i=0;i<nc;i++)
+	{
+    	  sum+=(*x1)*(*y1);
+    	  ++x1;
+    	  ++y1;
+	}
+    }
+  else
+    {
+      for (int i=0;i<nc;i++)
+	{
+    	  double x=a1->GetComponent(index1,i);
+    	  double y=a2->GetComponent(index2,i);
+    	  sum+=x*y;
+	}
+    }
+
+  return sum*factor;
+
+}
+
+//---------------------------------------------------------------------------------
+//main function
+//---------------------------------------------------------------------------------
+void vtkbisTimeSeriesCorrelation::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  fprintf(stderr,"Beginning vtkbisTimeSeriesCorrelation.\n");
+  int dim[3];
+
+  input->GetDimensions(dim);
+  /*fprintf(stderr,"dim=%d x %d x %d , nframes=%d\n",
+	  dim[0],dim[1],dim[2],input->GetNumberOfScalarComponents());
+
+  output->GetDimensions(dim);
+  fprintf(stderr,"dim=%d x %d x %d , nframes=%d\n",
+	  dim[0],dim[1],dim[2],output->GetNumberOfScalarComponents());*/
+
+  vtkbisImageTimeSeriesNormalize* norm1=vtkbisImageTimeSeriesNormalize::New();
+  norm1->SetInput(input);
+  norm1->Update();
+
+  vtkImageData* temp=vtkImageData::New();
+  temp->ShallowCopy(norm1->GetOutput());
+  norm1->Delete();
+
+
+  vtkDataArray*   inp=temp->GetPointData()->GetScalars();
+  vtkDataArray*   out=output->GetPointData()->GetScalars();
+
+  int nt = inp->GetNumberOfTuples();//get number of regions
+  int nc = inp->GetNumberOfComponents();//get number of frames(time series points)
+  //cout<<"nt:"<<nt<<"nc"<<nc<<"\n";
+  double factor=1.0/double(nc);
+
+  int ncout=out->GetNumberOfComponents();
+  int ntout=out->GetNumberOfTuples();
+  //cout<<"ntout:"<<ntout<<"\n";
+  for (int ia=0;ia<ncout;ia++)
+    out->FillComponent(ia,0.0);
+
+
+  this->UpdateProgress(0.01);
+
+  int index=0;
+  for (int ia=0;ia<nt;ia++)
+  {
+    for (int ib = 0;ib<nt;ib++)
+	{
+	  double rho=vtkbisTimeSeriesCorrelation::ComputePreNormalizedCorrelationCoefficient(inp,ia,inp,ib,factor,nc);
+	  //	  double rho2=vtkbisTimeSeriesCorrelation::ComputeCorrelationCoefficient(inp,ia,inp,ib);
+
+	  //	  fprintf(stderr,"%d \t %d \t %f \t %f\n",ia,ib,rho,rho2);
+	  if (this->OutputRaw)
+	  {
+		  out->SetComponent(index,0,rho);
+	  }else{
+		  out->SetComponent(index,0,vtkbisTimeSeriesCorrelation::RhoToZConversion(rho));
+	  }
+	  ++index;
+	}
+      this->UpdateProgress(float(ia+1)/float(nt));
+    }
+  //cout<<"index:"<<index<<"\n";
+
+  temp->Delete();
+
+
+  if(this->DoText == 1 )
+  {
+      if(nc > 400 )
+      {
+    	  fprintf(stderr, "number of frames > 400. Too much data to export.");
+    	  return;
+      }
+      std::ofstream myfile(this->FileName.c_str());//output file stream
+      if(!myfile.is_open())
+      {
+    	  cout<< "Unable to open file"<<this->FileName.c_str()<<"\n";
+    	  return;
+      }
+      //loop through the output image file
+      int counter=0;
+      for (int ia = 0; ia<nt; ia++)
+      {
+    	  for (int ib=0;ib<nt;ib++)
+    	  {
+    		  myfile<<out->GetComponent(counter,0)<< "\t";
+
+    		  ++counter;
+    	  }
+    	  myfile<<"\n";
+      }
+      myfile.close();
+
+      //*******************************************
+      //file output for Alark Viewer
+      //*******************************************
+      std::ofstream alarkfile(this->FileName2.c_str());
+
+      if(!alarkfile.is_open())
+      {
+    	  cout<< "Unable to open file "<<this->FileName2.c_str()<<"\n";
+          return;
+      }
+
+      alarkfile<<"#Connections and strengths\n"<<((1+nt-1)*(nt-1))/2<<"\n";
+      vtkFloatArray* alarkoutput=vtkFloatArray::New();
+      alarkoutput->SetNumberOfComponents(nt);
+      alarkoutput->SetNumberOfTuples(nt);
+      for(int ia=0;ia<nt;ia++)
+    	  alarkoutput->FillComponent(ia,0.0);
+      int index=0;
+      for(int i=0;i<nt;i++)
+      {
+    	  for(int j=0;j<nt;j++)
+    	  {
+    		  alarkoutput->SetComponent(i,j,out->GetComponent(index,0));
+    		  ++index;
+    	  }
+      }
+      for(int i=0;i<nt;i++)
+      {
+          for(int j=i+1;j<nt;j++)
+          {
+        	  alarkfile<<i<<"\t"<<j<<"\t"<<alarkoutput->GetComponent(i,j)<<"\n";
+          }
+      }
+      alarkfile.close();
+      alarkoutput->Delete();
+  }
+  //  temp->Delete();
+  this->UpdateProgress(1.0);
+}
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesCorrelation.h b/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesCorrelation.h
new file mode 100644
index 0000000..4c00e76
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesCorrelation.h
@@ -0,0 +1,104 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+/*!
+ * vtkbisTimeSeriesCorrelation.h
+ *
+ *  Created on: Sep 29, 2008
+ *      Author: Isabella Murphy; Xilin Lin
+ *      given a set of average time courses compute a correlation matrix among them
+ *      also called matrix correlation
+ */
+
+#ifndef _VTKBISTIMESERIESCORRELATION_H
+#define _VTKBISTIMESERIESCORRELATION_H
+
+#include "vtkSimpleImageToImageFilter.h"
+#include <string>
+#include <iostream>
+#include "vtkFloatArray.h"
+
+class vtkImageData;
+class vtkInformation;
+class vtkInformationVector;
+
+class vtkbisTimeSeriesCorrelation: public vtkSimpleImageToImageFilter {
+public:
+  static vtkbisTimeSeriesCorrelation *New();
+  vtkTypeMacro(vtkbisTimeSeriesCorrelation,vtkSimpleImageToImageFilter);
+
+  //filename
+  virtual void SetFileName(const char* filename);
+  virtual const char* GetFileName();
+  // File name2
+  virtual void SetFileName2(const char* filename2);
+  virtual const char* GetFileName2();
+
+  //DoText
+  vtkSetClampMacro(DoText,int,0,1);
+  vtkGetMacro(DoText,int);
+  //OutputRaw
+  vtkSetClampMacro(OutputRaw,int,0,1);
+  vtkGetMacro(OutputRaw,int);
+
+  // Compute Correlation Coefficient
+  //
+
+  static double ComputeCorrelationCoefficient(vtkDataArray* a1,int index1,vtkDataArray* a2,int index2);
+  static double RhoToZConversion(double rho);
+
+  // This function does no checking!
+  static double ComputePreNormalizedCorrelationCoefficient(vtkDataArray* a1,int index1,vtkDataArray* a2,int index2,double factor,int nc);
+
+
+protected:
+  vtkbisTimeSeriesCorrelation();
+  virtual ~vtkbisTimeSeriesCorrelation(){};
+
+  virtual int RequestInformation (vtkInformation * request,
+				  vtkInformationVector ** inputVector,
+				  vtkInformationVector * outputVector);
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+
+
+private:
+  vtkbisTimeSeriesCorrelation(const vtkbisTimeSeriesCorrelation& src){};
+  vtkbisTimeSeriesCorrelation& operator=(const vtkbisTimeSeriesCorrelation& rhs){};
+  int DoText;
+  int OutputRaw;
+
+  //BTX
+  std::string FileName;
+  std::string FileName2;
+  //ETX
+
+};
+
+#endif /* VTKBISTIMESERIESCORRELATION_H_ */
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesMean.cpp b/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesMean.cpp
new file mode 100644
index 0000000..b6cf586
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesMean.cpp
@@ -0,0 +1,94 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkbisTimeSeriesMean.h"
+
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+
+vtkbisTimeSeriesMean* vtkbisTimeSeriesMean::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisTimeSeriesMean");
+  if(ret)
+    {
+      return (vtkbisTimeSeriesMean*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisTimeSeriesMean;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------
+int vtkbisTimeSeriesMean::RequestInformation (vtkInformation * vtkNotUsed( request ),
+					      vtkInformationVector ** vtkNotUsed( inputVector ),
+					      vtkInformationVector * outputVector)
+{
+
+  vtkDataObject::SetPointDataActiveScalarInfo(
+    outputVector->GetInformationObject(0), -1, 1);
+    vtkInformation* outInfo = outputVector->GetInformationObject(0);
+
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT , -1);
+  return 1;
+}
+
+
+void vtkbisTimeSeriesMean::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+  if (input==NULL || output==NULL)
+    {
+      fprintf(stderr,"Bad Image Input to vtkbisTimeSeriesMean SimpleExecute\n");
+      return;
+    }
+
+  vtkDataArray* marr = output->GetPointData()->GetScalars();
+  vtkDataArray* inp = input->GetPointData()->GetScalars();
+
+
+  int nt=inp->GetNumberOfTuples();
+  int nc=inp->GetNumberOfComponents();
+
+  for (int i=0;i<nt;i++)
+    {
+      double sum=0.0;
+      for (int j=0;j<nc;j++)
+	sum+=inp->GetComponent(i,j);
+      sum/=double(nc);
+      marr->SetComponent(i,0,sum);
+    }
+}
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesMean.h b/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesMean.h
new file mode 100644
index 0000000..a502f2d
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesMean.h
@@ -0,0 +1,69 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkbisTimeSeriesMean_h
+#define __vtkbisTimeSeriesMean_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkInformation;
+class vtkInformationVector;
+
+
+class vtkbisTimeSeriesMean : public vtkSimpleImageToImageFilter
+{
+public:
+  static vtkbisTimeSeriesMean *New();
+  vtkTypeMacro(vtkbisTimeSeriesMean,vtkSimpleImageToImageFilter);
+
+
+
+protected:
+
+
+  vtkbisTimeSeriesMean(){};
+  virtual ~vtkbisTimeSeriesMean(){};
+
+  // Description:
+  // Static Routines
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+
+  // This to specify  output pipeline info
+  virtual int RequestInformation (vtkInformation *, vtkInformationVector**,
+                                  vtkInformationVector *);
+
+
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesStat.cpp b/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesStat.cpp
new file mode 100644
index 0000000..d7d26f3
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesStat.cpp
@@ -0,0 +1,129 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkbisTimeSeriesStat.h"
+
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+
+vtkbisTimeSeriesStat* vtkbisTimeSeriesStat::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisTimeSeriesStat");
+  if(ret)
+    {
+      return (vtkbisTimeSeriesStat*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisTimeSeriesStat;
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+vtkbisTimeSeriesStat::vtkbisTimeSeriesStat() 
+{
+  this->Mode=0;
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+int vtkbisTimeSeriesStat::RequestInformation (vtkInformation * vtkNotUsed( request ),
+					      vtkInformationVector ** vtkNotUsed( inputVector ),
+					      vtkInformationVector * outputVector)
+{
+
+  vtkDataObject::SetPointDataActiveScalarInfo(
+    outputVector->GetInformationObject(0), -1, 1);
+    vtkInformation* outInfo = outputVector->GetInformationObject(0);
+
+    if (this->Mode<2)
+      vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT , -1);
+  return 1;
+}
+
+
+void vtkbisTimeSeriesStat::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+  if (input==NULL || output==NULL)
+    {
+      fprintf(stderr,"Bad Image Input to vtkbisTimeSeriesStat SimpleExecute\n");
+      return;
+    }
+
+  vtkDataArray* marr = output->GetPointData()->GetScalars();
+  vtkDataArray* inp = input->GetPointData()->GetScalars();
+
+
+  int nt=inp->GetNumberOfTuples();
+  int nc=inp->GetNumberOfComponents();
+
+  /*
+  virtual void SetModeToMean() { this->SetMode(0); }
+  virtual void SetModeToSum() { this->SetMode(1); }
+  virtual void SetModeToMin() { this->SetMode(2); }
+  virtual void SetModeToMax() { this->SetMode(3); }
+
+  */
+  for (int i=0;i<nt;i++)
+    {
+      double sum=0.0;
+      double sum2=0.0;
+      double vmin=inp->GetComponent(i,0);
+      double vmax=vmin;
+      for (int j=0;j<nc;j++)
+	{
+	  double v=inp->GetComponent(i,j);
+	  sum+=v;
+	  sum2+=v*v;
+	  if (vmax<v)
+	    vmax=v;
+	  else if (vmin>v)
+	    vmin=v;
+	}
+      
+      double mean=sum/double(nc);
+      double magn=sqrt(sum2);
+      
+      if (this->Mode==0)
+	marr->SetComponent(i,0,mean);
+      else if (this->Mode == 1 )
+	marr->SetComponent(i,0,sum);
+      else if (this->Mode == 2 )
+	marr->SetComponent(i,0,vmin);
+      else if (this->Mode == 3 )
+	marr->SetComponent(i,0,vmax);
+      else if (this->Mode == 4 )
+	marr->SetComponent(i,0,magn);
+    }
+}
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesStat.h b/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesStat.h
new file mode 100644
index 0000000..00c8708
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisTimeSeriesStat.h
@@ -0,0 +1,78 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkbisTimeSeriesStat_h
+#define __vtkbisTimeSeriesStat_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkInformation;
+class vtkInformationVector;
+
+
+class vtkbisTimeSeriesStat : public vtkSimpleImageToImageFilter
+{
+public:
+  static vtkbisTimeSeriesStat *New();
+  vtkTypeMacro(vtkbisTimeSeriesStat,vtkSimpleImageToImageFilter);
+
+
+  // Description:
+  vtkGetMacro(Mode,int);
+  vtkSetClampMacro(Mode,int,0,4);
+  virtual void SetModeToMean() { this->SetMode(0); }
+  virtual void SetModeToSum() { this->SetMode(1); }
+  virtual void SetModeToMin() { this->SetMode(2); }
+  virtual void SetModeToMax() { this->SetMode(3); }
+  virtual void SetModeToVectorMagnitude() { this->SetMode(4); }
+
+protected:
+
+
+  vtkbisTimeSeriesStat();
+  virtual ~vtkbisTimeSeriesStat(){};
+
+  // Description:
+  // Static Routines
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+
+  // This to specify  output pipeline info
+  virtual int RequestInformation (vtkInformation *, vtkInformationVector**,
+                                  vtkInformationVector *);
+
+
+  int Mode;
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisfmriToolBox.cpp b/bioimagesuite30_src/Connectivity/vtkbisfmriToolBox.cpp
new file mode 100644
index 0000000..489cba4
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisfmriToolBox.cpp
@@ -0,0 +1,1072 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisfmriToolBox.cpp
+ *
+ *  Created on: May 21, 2010
+ *      Author: Isabella Murphy,Xilin Shen
+ *      This class compute complex network measures
+ *      1. Adjacency matrix (brain network)
+ *      2. Degrees
+ *      3. Reachability matrix
+ *      4. Shortest path length matrix
+ *      5. Number of triangles
+ *      6. Characteristic path length
+ *      7. individual characteristic path length
+ *      8. Global efficiency
+ *      9. individual global efficiency
+ *      10. Clustering coefficient
+ *      11. Transicity
+ *      12. Local efficiency
+ *      13. individual local efficiency
+ *      14. Closeness Centrality
+ *      15. Betweeness centrality
+ *      @[in]:input,vtkImageData,seedToseed correlation result from vtkbisTimeSeriesCorrelation
+ *      @[in]:this->functionalImage,vtkImageData
+ *      @[in]:this->roiMap,vtkImageData
+ *      @[in]:this->threshold, to threshold seedToseed correlation result to generate adjacency matrix for the rest of calculation
+ *      @[out]:output,_shortestpathlength.nii.gz
+ *      @[out]:this->OutData2,_networkMeasure.nii.gz
+ *      @[out]:_adjMatrixForAlarkViewer.txt.Text file for Alark Viewer to display adjacency matrix.
+ *      @[out]:_networkMeasures.txt. Text file for Alark Viewer to display complex network measures.
+ *      @[out]:_roiCorrelationForAlarkViewer.txt. Text file for Alark Viewer to display seedToseed correlation result from vtkbisTimeSereisCorrelation.
+ */
+#include "vtkbisImageTimeSeriesNormalize.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include <vtkbisfmriToolBox.h>
+#include "vtkObjectFactory.h"
+#include "vtkCellArray.h"
+#include "vtkPointData.h"
+#include <vector>
+#include "vtkbisROIMean.h"
+#include "vtkPoints.h"
+#include "vtkIdList.h"
+#include "vtkbisDijkstraGraphGeodesicPath.h"
+#include "vtkpxMatrix.h"
+#include "vtkPolyDataWriter.h"
+#include <time.h>
+#include "pxisinf.h"
+#include <fstream>
+#include <cstdlib>
+
+using namespace std;
+
+vtkbisfmriToolBox* vtkbisfmriToolBox::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisfmriToolBox");
+  if(ret)
+    {
+      return (vtkbisfmriToolBox*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisfmriToolBox;
+}
+
+vtkbisfmriToolBox::vtkbisfmriToolBox()
+{
+  this->FunctionalImage=NULL;
+  this->roiMap=NULL;
+  this->OutData2=NULL;
+  this->Threshold=0.0;
+}
+
+//----------------------------------------------------------------------------
+vtkbisfmriToolBox::~vtkbisfmriToolBox()
+{
+  this->SetFunctionalImage(NULL);
+  this->SetroiMap(NULL);
+  if (this->OutData2!=NULL)
+    this->OutData2->Delete();
+}
+
+void vtkbisfmriToolBox::SetFilename(const char* filename)
+{
+  this->Filename=filename;
+}
+
+const char* vtkbisfmriToolBox::GetFilename()
+{
+  return this->Filename.c_str();
+}
+void vtkbisfmriToolBox::SetFilename2(const char* filename2)
+{
+  this->Filename2=filename2;
+}
+
+const char* vtkbisfmriToolBox::GetFilename2()
+{
+  return this->Filename2.c_str();
+}
+void vtkbisfmriToolBox::SetFilename3(const char* filename3)
+{
+  this->Filename3=filename3;
+}
+
+const char* vtkbisfmriToolBox::GetFilename3()
+{
+  return this->Filename3.c_str();
+}
+//----------------------------------------------------------------------------
+int vtkbisfmriToolBox::RequestInformation(vtkInformation*,
+                                           vtkInformationVector**,
+                                           vtkInformationVector* outputVector)
+{
+  vtkInformation* outInfo = outputVector->GetInformationObject(0);
+
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+  return 1;
+}
+/*
+ * ComputeBrainNetwork
+ * @[in]:roiCorrelation. Output of vtkbisTimeSeriesCorrelation, an ROI*ROI*1*1 image.
+ * For example, correlation of average time course 0 to  (say 0-10) is stored in output
+ * vtkImagedata voxel 0-10 component 0;correlation of average time course 1 to all other
+ * average time course (say 0-10) is stored in output vtkImageData voxel 11-20 component
+ * 0 and so on.
+ * @[in]:threshold. If value of (ROI1,ROI2)>threshold, (ROI1,ROI2)is stored in the network
+ * @[in]:binary. If 0 then output weighted network; if 1 then output binary netowrk
+ * @[out]:2Darray. A matrix describe the connection between ROIs
+ */
+vtkFloatArray* vtkbisfmriToolBox::ComputeBrainNetwork(vtkImageData* roiCorrelation, float threshold, int binary)
+{
+	//get number of regions
+	vtkDataArray* inp=roiCorrelation->GetPointData()->GetScalars();
+	int nt = (int)sqrt(double(inp->GetNumberOfTuples()));
+
+	//prepare output
+	vtkFloatArray* output=vtkFloatArray::New();
+	output->SetNumberOfComponents(nt);
+	output->SetNumberOfTuples(nt);
+	for(int ia=0;ia<nt;ia++)
+		output->FillComponent(ia,0.0);
+
+	//scan through the roiCorrelation result, fill up the brain network base on the threshold
+	int counter=0;
+	for (int ia=0;ia<nt;ia++)
+    {
+		for (int ib=0;ib<nt;ib++)
+		{
+			double value = inp->GetComponent(counter,0);
+			if(value > threshold && ia!=ib)
+			{
+				if(binary > 0)
+				{
+					output->SetComponent(ia,ib,1.0);
+				}
+				else
+				{
+					output->SetComponent(ia,ib,value);
+				}
+			}
+			++counter;
+		}
+    }
+
+	return output;
+}
+/*
+ * In an undirected graph, the degree is the number of connections for individual nodes.
+ * @[in]:brainNetwork. the output of ComputeBrainNetwork
+ * @[out]:output. Output a vtkIntArray and a text file
+ */
+vtkIntArray* vtkbisfmriToolBox::ComputeDegreesUnd(vtkFloatArray* brainNetwork)
+{
+	int nt = brainNetwork->GetNumberOfComponents();
+	vtkIntArray* output= vtkIntArray::New();
+	output->SetNumberOfComponents(1);
+	output->SetNumberOfTuples(nt);
+	output->FillComponent(0,0.0);
+
+	for (int i=0;i<nt;i++)
+    {
+		int sum = 0;
+		for (int j=0;j<nt;j++)
+		{
+			if(brainNetwork->GetComponent(i,j)==1)
+				++sum;
+		}
+		output->SetComponent(i,0,(double)sum);
+    }
+	return output;
+}
+
+float vtkbisfmriToolBox::ComputeNumberOfTriangles(vtkFloatArray* brainNetwork,int tuple)
+{
+	int nt=brainNetwork->GetNumberOfTuples();
+	float counter=0;
+	for(int j=0;j<nt;j++)
+	{
+		for(int h=0;h<nt;h++)
+		{
+			if((brainNetwork->GetComponent(tuple,j)==1) && (brainNetwork->GetComponent(tuple,h)==1) && (brainNetwork->GetComponent(j,h)==1))
+			{
+				++counter;
+			}
+		}
+	}
+	counter/=2;
+	return counter;
+}
+
+/*
+ * Translate from matlab code betweeness_bin.m
+ */
+vtkpxMatrix* vtkbisfmriToolBox::ComputeBetweenessCentrality(vtkFloatArray* brainNetwork)
+{
+	time_t start,end;
+	time(&start);
+	int nt=brainNetwork->GetNumberOfTuples();
+
+
+	vtkpxMatrix* BC=vtkpxMatrix::New();
+	vtkpxMatrix* G=vtkpxMatrix::New();
+	vtkpxMatrix* Gt=vtkpxMatrix::New();
+	vtkpxMatrix* NPd=vtkpxMatrix::New();
+	vtkpxMatrix* tempNPd=vtkpxMatrix::New();
+	vtkpxMatrix* NSPd=vtkpxMatrix::New();
+	vtkpxMatrix* NSP=vtkpxMatrix::New();
+	vtkpxMatrix* tempNSP=vtkpxMatrix::New();
+	vtkpxMatrix* L=vtkpxMatrix::New();
+	vtkpxMatrix* DP=vtkpxMatrix::New();
+	vtkpxMatrix* tempDP=vtkpxMatrix::New();
+	vtkpxMatrix* DPd1=vtkpxMatrix::New();
+	vtkpxMatrix* tempDPd1=vtkpxMatrix::New();
+	vtkpxMatrix* temptempDPd1=vtkpxMatrix::New();
+	G->Zeros(nt,nt);
+	for(int row = 0;row<nt;row++)
+	{
+		for(int col=0;col<nt;col++)
+		{
+			G->SetElement(row,col,brainNetwork->GetComponent(row,col));
+		}
+	}
+
+	NPd->Copy(G);
+	NSPd->Copy(NPd);
+	NSP->Copy(NSPd);
+	L->Copy(NSPd);
+
+	//NSP(I)=1;L(I)1;
+	for(int i=0;i<nt;i++)
+	{
+		NSP->SetElement(i,i,1);
+		L->SetElement(i,i,1);
+	}
+
+	int d=1;//path length
+	int NSPdhasOne=1;
+	while(NSPdhasOne==1 )
+	{
+		NSPdhasOne=0;
+		++d;
+
+		//NPd=NPd*G
+		vtkpxMatrix::Multiply(NPd,G,tempNPd);
+		NPd->Copy(tempNPd);
+
+		//NSPd=NPd.*(L==0)
+		for(int row = 0;row<nt;row++)
+		{
+			for(int col=0;col<nt;col++)
+			{
+				if(L->GetElement(row,col)==0)
+				{
+					NSPd->SetElement(row,col,NPd->GetElement(row,col));
+				}else{
+					NSPd->SetElement(row,col,0);
+				}
+			}
+		}
+
+		//NSP=NSP+NSPd
+		vtkpxMatrix::Add(NSP,NSPd,tempNSP);
+		NSP->Copy(tempNSP);
+
+		//L=L+d.*(NSPd~=0)
+		for(int row = 0;row<nt;row++)
+		{
+			for(int col=0;col<nt;col++)
+			{
+				if(NSPd->GetElement(row,col)!=0)
+				{
+					L->SetElement(row,col,d);
+					NSPdhasOne=1;
+					//can not jump out the double for loop until all the L is updated
+
+				}
+			}
+		}
+	}//end of while loop
+
+	//L(~L)=-1; L(I)=0; NSP(~NSP)=1
+	for(int row = 0;row<nt;row++)
+	{
+		for(int col=0;col<nt;col++)
+		{
+			if(L->GetElement(row,col)==0)
+			{
+				L->SetElement(row,col,-1);
+			}
+			if(NSP->GetElement(row,col)==0)
+			{
+				NSP->SetElement(row,col,1);
+			}
+		}
+	}
+	for(int i=0;i<nt;i++)
+	{
+		L->SetElement(i,i,0);
+	}
+
+
+	//Gt=G.'
+	Gt->Copy(G);
+	Gt->Transpose();
+
+
+	/*for(d=diam:-1:2)
+	 *DPd1=((L==d).*(1+DP)/NSP)*Gt).*((L==d-1).*NSP)
+	 *DP=DP+DPd1
+	 */
+	DP->Zeros(nt,nt);
+	DPd1->Zeros(nt,nt);
+	tempDPd1->Zeros(nt,nt);
+	int diam=d-1;
+	for(int t=diam;t>=2;t--)
+	{
+		for(int row = 0;row<nt;row++)
+		{
+			for(int col=0;col<nt;col++)
+			{
+				float value=0;
+				if(L->GetElement(row,col)==t)
+				{
+					tempDPd1->SetElement(row,col,((DP->GetElement(row,col)+1)/NSP->GetElement(row,col)));
+				}
+			}
+		}
+		vtkpxMatrix::Multiply(tempDPd1,Gt,temptempDPd1);
+		DPd1->Fill(0);
+		for(int row = 0;row<nt;row++)
+		{
+			for(int col=0;col<nt;col++)
+			{
+				//std::cout<<"L:"<<L->GetElement(row,col);
+				if(L->GetElement(row,col)==(t-1))
+				{
+					DPd1->SetElement(row,col,temptempDPd1->GetElement(row,col)*NSP->GetElement(row,col));
+				}
+			}
+		}
+		vtkpxMatrix::Add(DP,DPd1,tempDP);
+		DP->Copy(tempDP);
+	}
+
+	//BC=sum(DP,1)
+	BC=DP->ColumnSums();
+
+	G->Delete();
+	Gt->Delete();
+	NPd->Delete();
+	tempNPd->Delete();
+	NSPd->Delete();
+	NSP->Delete();
+	tempNSP->Delete();
+	L->Delete();
+	DP->Delete();
+	tempDP->Delete();
+	DPd1->Delete();
+	tempDPd1->Delete();
+	temptempDPd1->Delete();
+
+	time(&end);
+	std::cout<<endl<<"\nElapsed time for calculating Betweeness Centrality in fmritoolboc.cpp "<<difftime(end, start)<<" seconds"<<endl;
+	return BC;
+}
+
+/*
+ * translate from matalb code efficiency.m
+ */
+vtkFloatArray* vtkbisfmriToolBox::ComputeLocalEfficiency(vtkFloatArray* brainNetwork, vtkIntArray* degrees)
+{
+	int nt=brainNetwork->GetNumberOfTuples();
+
+		vtkFloatArray* localE = vtkFloatArray::New();
+		localE->SetNumberOfComponents(1);
+		localE->SetNumberOfTuples(nt);
+		localE->FillComponent(0,0.0);
+		vtkpxMatrix* g=vtkpxMatrix::New();
+		vtkpxMatrix* D=vtkpxMatrix::New();
+		vtkpxMatrix* tempD=vtkpxMatrix::New();
+		vtkpxMatrix* nPATH=vtkpxMatrix::New();
+		vtkpxMatrix* tempPATH=vtkpxMatrix::New();
+		vtkpxMatrix* L=vtkpxMatrix::New();
+
+		for(int c=0;c<nt;c++)
+	    {
+			int ki=(int)degrees->GetComponent(c,0);
+			if(ki>=2)
+			{
+				//1.extract small matrix g
+				vector<int> v(ki,0);
+				int index=0;
+				for(int t=0;t<nt;t++)
+				{
+					if(brainNetwork->GetComponent(t,c)>0)
+					{
+						v[index]=t;
+						++index;
+					}
+				}
+
+				g->Zeros(ki,ki);
+				for(int row = 0;row<ki;row++)
+				{
+					for(int col=0;col<ki;col++)
+					{
+						g->SetElement(row,col,brainNetwork->GetComponent(v[row],v[col]));
+					}
+				}
+
+
+				//2.make identical matrix D
+				D->Eye(ki);
+
+				//3.initialize number of steps
+				int n=1;
+
+				//4.nPATH=g
+				nPATH->Copy(g);
+
+				//5.L=(nPATH~=0)
+				int LhasOne=0;
+
+				L->Zeros(ki,ki);
+				for(int row=0;row<ki;row++)
+				{
+					for(int col=0;col<ki;col++)
+					{
+						if(nPATH->GetElement(row,col)>0)
+						{
+							L->SetElement(row,col,1);
+							LhasOne=1;
+						}
+					}
+				}
+				while(LhasOne>0)
+				{
+					//6.D=D+n.*L
+					vtkpxMatrix::Add(D,L,tempD);
+					D->Copy(tempD);
+
+					//7. increment number of steps
+					++n;
+
+					//8.nPATH=nPATH*g
+					vtkpxMatrix::Multiply(nPATH,g,tempPATH);
+					nPATH->Copy(tempPATH);
+
+					//9.L=(nAPTH~=0) and D==0
+					LhasOne=0;
+					L->Fill(0.0);
+					for(int row=0;row<ki;row++)
+					{
+						for(int col=0;col<ki;col++)
+						{
+							if((nPATH->GetElement(row,col)!=0) && (D->GetElement(row,col)==0))
+							{
+								L->SetElement(row,col,n);
+								LhasOne=1;
+							}
+						}
+					}
+				}//end of while loop
+
+				//10.D=1/D
+				for(int row=0;row<ki;row++)
+				{
+					for(int col=0;col<ki;col++)
+					{
+						double d=D->GetElement(row,col);
+
+						if(d>0)
+						{
+							D->SetElement(row,col,(double)1/d);
+						}else{
+							D->SetElement(row,col,0);
+						}
+					}
+				}
+
+				//11.remove 1 from diagonal line
+				for(int d =0;d<ki;d++)
+				{
+					D->SetElement(d,d,0);
+				}
+
+				//12.sum D
+				float sum=D->Sum();
+
+				//13.e=sum/ki(ki-1)
+				int bot=ki*(ki-1);
+				localE->SetComponent(c,0,(double)sum/bot);
+			}
+	    }
+
+		g->Delete();
+		D->Delete();
+		tempD->Delete();
+		nPATH->Delete();
+		tempPATH->Delete();
+		L->Delete();
+		return localE;
+}
+
+/*
+ * Output format:
+ * component
+ * 0 index
+ * 1 x
+ * 2 y
+ * 3 z
+ * 4 label
+ * 5 individual char path length
+ * 6 individual global efficient
+ * 7 closeness centrality
+ * 8 # of triangles
+ * 9 degrees
+ * (below only store one value on tuple 0)
+ * 10 char path length
+ * 11 global efficiency
+ * 12 clustering coefficient
+ * 13 transicity
+ */
+vtkFloatArray* vtkbisfmriToolBox::ComputeNetworkMeasures(vtkFloatArray* brainNetwork,vtkImageData* brain, vtkImageData* ROI, vtkIntArray* degrees,vtkDataArray* out)
+{
+  time_t start,end;
+  time(&start);
+
+  int nt = brainNetwork->GetNumberOfTuples();
+  //std::cout<<"nt:!!!!!!!!!!!"<<nt<<endl;
+
+  int numItem=14;
+
+  vtkFloatArray* output=vtkFloatArray::New();
+  output->SetNumberOfComponents(numItem);
+  output->SetNumberOfTuples(nt);
+  for(int ia=0;ia<numItem;ia++)
+    output->FillComponent(ia,0.0);
+
+  //compute xyz coordinates of each ROI center
+  vtkbisROIMean* calCentroids = vtkbisROIMean::New();
+  calCentroids->SetInput(brain);
+  calCentroids->SetImageROI(ROI);
+  calCentroids->SetDoText(0);
+  calCentroids->Update();
+
+  //vtkbisROIMean output has 1 extra point at end with xyz=-1,-1,-1
+  vtkPoints* centroids = vtkPoints::New();
+  centroids->Allocate(100,10);
+  //centroids->ShallowCopy(calCentroids->GetCentroids());
+  //calCentroids->Delete();
+
+  vtkIdType pt[2];
+  vtkPolyData* surface =vtkPolyData::New();
+  vtkCellArray* s_lines=vtkCellArray::New();
+  s_lines->Allocate(100,10);
+
+  //Now, create the real connections
+  for(int i=0;i<nt;i++)//for each point(ROI)
+    {
+      double x[3];
+      //centroids->GetPoint(i,x);
+      calCentroids->GetCentroids()->GetPoint(i,x);
+      output->SetComponent(i,0,i);
+      output->SetComponent(i,1,x[0]);
+      output->SetComponent(i,2,x[1]);
+      output->SetComponent(i,3,x[2]);
+      output->SetComponent(i,4,i+1);
+
+      centroids->InsertNextPoint(x);
+      for(int j=i+1;j<nt;j++)
+	{
+	  if(brainNetwork->GetComponent(i,j)>0)
+	    {
+	      pt[0]=i;
+	      pt[1]=j;
+	      s_lines->InsertNextCell(2,pt);
+	    }
+	}
+    }
+
+  surface->SetPoints(centroids);
+  centroids->Delete();
+  surface->SetLines(s_lines);
+  s_lines->Delete();
+/*
+  vtkPolyDataWriter* w=vtkPolyDataWriter::New();
+  w->SetInput(surface);
+  w->SetFileName("test.vtk");
+  w->Write();
+  w->Delete();
+*/
+  vtkIntArray* pathlength = vtkIntArray::New();
+  pathlength->SetNumberOfComponents(nt);
+  pathlength->SetNumberOfTuples(nt);
+
+  vtkIntArray* reachable =  vtkIntArray::New();
+  reachable->SetNumberOfComponents(nt);
+  reachable->SetNumberOfTuples(nt);
+
+  for(int ia=0;ia<nt;ia++)
+    {
+      pathlength->FillComponent(ia,0.0);
+      reachable->FillComponent(ia,0.0);
+    }
+
+  for(int ib=0;ib<nt;ib++)
+    reachable->SetComponent(ib,ib,1.0);
+
+
+  //find shortest path using vtkDijkstraGraphGeodesicPath
+  //std::map<int, vector<int> > pathmatrix;
+  vtkbisDijkstraGraphGeodesicPath* shpath = vtkbisDijkstraGraphGeodesicPath::New();
+
+
+  //int idcounter=1;
+  for (int k=0;k<nt;k++)
+    {
+      for(int l=k+1;l<nt;l++)
+	{
+	  shpath->SetInput(surface);
+	  shpath->SetStartVertex(k);
+	  shpath->SetEndVertex(l);
+	  shpath->Update();
+
+	  vtkIdList* list = shpath->GetIdList();
+
+	  //if there is a path between k and l, store it.
+	  if(list->GetId(1)!= -1)
+	    {
+	      int numid = list->GetNumberOfIds();
+	      pathlength->SetComponent(k,l,double(numid-1.0));
+	      reachable->SetComponent(k,l,1.0);
+	      reachable->SetComponent(l,k,1.0);
+	      //std::cout<<"["<<l<<","<<k<<"] \t";
+	      //myfile<<"["<<l<<","<<k<<"] \t";
+	      //vector<int> path(numid,0);
+	      //for (int m=0;m<numid;m++)
+	      //{
+	      //path[m]=list->GetId(m);
+	      //std::cout<<list->GetId(m)<<"\t";
+	      //myfile<<list->GetId(m)<<"\t";
+	      //}
+	      //pathmatrix[idcounter]=path;
+	      //idTable->SetComponent(k,l,idcounter);
+	      //idcounter++;
+
+	      //std::cout<<"\n";
+	      //myfile<<"\n";
+	    }
+	}
+    }
+
+  /*1.output reachability matrix
+   *2.output shortest path length matrix
+   *3.calculate characteristic path length (cpl)
+   *4.calculate global efficiency(ge)
+   *5.calculate closeness centrality
+   */
+  /*	//std::cout<<"Reachability Matrix:\n";
+	//myfile<<"Reachability Matrix:\n";
+	for(int r=0;r<nt;r++)
+	{
+	for(int c=0;c<nt;c++)
+	{
+	std::cout<<reachable->GetComponent(r,c)<<"\t";
+	myfile<<reachable->GetComponent(r,c)<<"\t";
+	}
+	//std::cout<<"\n";
+	//myfile<<"\n";
+	}
+  */
+  double cpl =0;
+  double ge=0.0;
+  //  vector<double> centrality(0,nt);
+
+  //std::cout<<"Path Length Matrix:\n";
+  //myfile<<"Path Length Matrix:\n";
+  int colument=0;
+  int offset=0;
+  for(int n=0;n<nt;n++)
+    {
+      double sumdi=0.0;
+      //initialize rownt=1. Because a node is always connect to itself, but our brain network set plength to itself to 0. By setting rownt=1 to start with, we add 1 back.
+      int rownt=1;
+      double thiscpl=0.0;
+      double thisge=0.0;
+      for(int p=0;p<nt;p++)
+	{
+	  int plength;
+	  if(n<p)
+	    {
+	      plength=(int)pathlength->GetComponent(n,p);
+	    }else{
+	    plength=(int)pathlength->GetComponent(p,n);
+	  }
+	  if(plength>0)
+	    {
+	      thisge+=(double)1/plength;
+	      ++rownt;
+	      sumdi+=plength;
+	      out->InsertTuple1(offset,plength);
+
+	    }
+	  ++offset;
+	  //std::cout<<plength<<"\t";
+	  //myfile<<plength<<"\t";
+
+
+	}
+      output->SetComponent(n,7,(double)(rownt-1)/sumdi);
+      //centrality[n]=(double)(rownt-1)/sumdi;
+
+      //if rownt >1 means this node connect to another node other then itself, then count this node for CPL and GE
+      if(rownt>1)
+	{
+	  thisge/=(rownt-1);
+	  output->SetComponent(n,6,thisge);
+	  ge+=thisge;
+	  thiscpl=(double)sumdi/(rownt-1);
+	  output->SetComponent(n,5,thiscpl);
+	  cpl+=thiscpl;
+	  ++colument;
+	}
+      //std::cout<<"\n";
+      //myfile<<"\n";
+    }
+
+  cpl/=colument;
+  ge/=colument;
+  std::cout<<"Characteristic Path Length: "<<cpl<<" \nGlobal Efficiency: "<<ge;
+  //myfile<<"Characteristic Path Length: "<<cpl<<" \nGlobal Efficiency: "<<ge<<" \nCloseness Centrality: ";
+  output->SetComponent(0,10,cpl);
+  output->SetComponent(0,11,ge);
+  /*	for(int ib=0;ib<nt;ib++)
+    {
+    std::cout<<centrality[ib]<<"\t";
+    myfile<<centrality[ib]<<"\t";
+
+    }
+  */
+  //calculate number of triangles
+  vector<float> triangle(nt,0.0);
+  //std::cout<<"\nNumber of Triangles: ";
+  //myfile<<"\nNumber of Triangles: ";
+  for(int i=0;i<nt;i++)
+    {
+      triangle[i]=vtkbisfmriToolBox::ComputeNumberOfTriangles(brainNetwork,i);
+      //std::cout<<triangle[i]<<"\t";
+      //myfile<<triangle[i]<<"\t";
+      output->SetComponent(i,8,ComputeNumberOfTriangles(brainNetwork,i));
+    }
+
+  //compute clustering coefficient
+  float ci=0.0;int counter=0;
+  float ttop=0.0;float tbot=0.0;
+  for(int i=0;i<nt;i++)
+    {
+      int ki=(int)degrees->GetComponent(i,0);
+      output->SetComponent(i,9,ki);
+      if(ki>=2)
+	{
+	  ttop+=2*triangle[i];
+	  tbot+=ki*(ki-1);
+	  ci+=(float)((2*triangle[i])/(ki*(ki-1)));
+	  ++counter;
+	}
+    }
+  float cc=(float)ci/counter;
+  float trans=(float)ttop/tbot;
+
+  std::cout<<"\nClustering Coefficient: "<<cc;
+  std::cout<<"\nTransitivity: "<<trans;
+
+  output->SetComponent(0,12,cc);
+  output->SetComponent(0,13,trans);
+
+  //myfile<<"\nClustering Coefficient: "<<cc<<"\nTransitivity: "<<trans;
+
+  time(&end);
+  std::cout<<endl<<"\nelapsed time for calculating Network Measures in vtkbisfmritoolbox is "<<difftime(end, start)<<" seconds"<<endl;
+
+  surface->Delete();
+  pathlength->Delete();
+
+  //idTable->Delete();
+
+  //shpath->Delete();
+  //fprintf(stderr,"OK about to return output size %d x %d\n",output->GetNumberOfTuples(),output->GetNumberOfComponents());
+  return output;
+  //myfile.close();
+
+}
+
+/*
+ * otherData Input format:
+ * component
+ * 0 index
+ * 1 x
+ * 2 y
+ * 3 z
+ * 4 label
+ * 5 individual char path length
+ * 6 individual global efficient
+ * 7 closeness centrality
+ * 8 # of triangles
+ * 9 degrees
+ * (below only store one value on tuple 0)
+ * 10 char path lenth
+ * 11 global efficiency
+ * 12 clustering coefficient
+ * 13 transicity
+ */
+void vtkbisfmriToolBox::GenerateOutputForAlarkViewer(vtkFloatArray* localE, vtkpxMatrix * BC, vtkFloatArray* otherData,const char* Filename2, vtkDataArray* out2)
+{
+  int nt=otherData->GetNumberOfTuples();
+  int nc=10;
+  int out2nc=12;
+
+  std::ofstream alarkfile(Filename2);
+
+  if(!alarkfile.is_open())
+    {
+      cout<< "Unable to open file"<<Filename2<<"\n";
+      return;
+    }
+  else
+    {
+      std::cout << "Opening " << Filename2 << "\n";
+    }
+
+  alarkfile<<"#Connectivity file\n#Points\n"<<nt<<"\n#index x y z label ind.CharPathLength ind.GlobalEffi. ClosenessCentrality #ofTriangles Degrees LocalEffi BetweenessCentrality\n";
+
+  int index=0;
+  for (int i=0;i<nt;i++)
+    {
+      //      fprintf(stderr,"Row %d/%d\n",i,nt);
+      for(int j=0;j<nc;j++)
+	{
+	  alarkfile<<otherData->GetComponent(i,j)<<"\t";
+	  out2->SetComponent(index,0,otherData->GetComponent(i,j));
+	  ++index;
+	}
+      alarkfile<<localE->GetComponent(i,0)<<"\t"<<BC->GetDirectElement(i,0)<<"\n";
+      out2->SetComponent(index,0,localE->GetComponent(i,0));
+      ++index;
+      out2->SetComponent(index,0,BC->GetDirectElement(i,0));
+      ++index;
+    }
+  alarkfile<<"#Other information\n#CharPathLength "<<otherData->GetComponent(0,10)<<"\n#Global Effi "<<otherData->GetComponent(0,11)<<"\n#Clustering Coef "<<otherData->GetComponent(0,12)<<"\n#Transicity "<<otherData->GetComponent(0,13);
+
+  alarkfile.close();
+  //  fprintf(stderr,"This Far\n");
+}
+
+void vtkbisfmriToolBox::GenerateAdjMatrixOutputForAlarkViewer(vtkFloatArray* brainNetwork, vtkFloatArray* otherData, const char* Filename)
+{
+	std::ofstream alarkfile(Filename);
+
+		if(!alarkfile.is_open())
+		{
+			cout<< "Unable to open file"<<Filename<<"\n";
+			return;
+		}
+		else
+		{
+			std::cout << "Opening " << Filename << "\n";
+		}
+
+		int nt=brainNetwork->GetNumberOfTuples();
+		int nc=5;
+
+		alarkfile<<"#Connectivity file\n#Points\n"<<nt<<"\n#index x y z label\n";
+
+		for (int i=0;i<nt;i++)
+		{
+			for(int j=0;j<nc;j++)
+			{
+				alarkfile<<otherData->GetComponent(i,j)<<"\t";
+			}
+			alarkfile<<"\n";
+		}
+
+		alarkfile<<"\n#Connections and strengths\n"<<((1+nt-1)*(nt-1))/2<<"\n";
+		for(int i=0;i<nt;i++)
+		{
+			for(int j=i+1;j<nt;j++)
+			{
+				alarkfile<<i<<"\t"<<j<<"\t"<<brainNetwork->GetComponent(i,j)<<"\n";
+			}
+		}
+
+		alarkfile.close();
+}
+void vtkbisfmriToolBox::GenerateROICorrelationOutputForAlarkViewer(vtkImageData* roiCorrelation, vtkFloatArray* otherData, const char* Filename3)
+{
+	std::ofstream alarkfile(Filename3);
+
+	if(!alarkfile.is_open())
+	{
+		cout<< "Unable to open file"<<Filename3<<"\n";
+		return;
+	}else
+	{
+		std::cout << "Opening " << Filename3 << "\n";
+	}
+
+	//get number of regions
+	vtkDataArray* inp=roiCorrelation->GetPointData()->GetScalars();
+	int nt = (int)sqrt(double(inp->GetNumberOfTuples()));
+	int nc=5;
+
+	alarkfile<<"#Connectivity file\n#Points\n"<<nt<<"\n#index x y z label\n";
+
+	for (int i=0;i<nt;i++)
+	{
+		for(int j=0;j<nc;j++)
+		{
+			alarkfile<<otherData->GetComponent(i,j)<<"\t";
+		}
+		alarkfile<<"\n";
+	}
+
+	alarkfile<<"\n#Connections and strengths\n"<<((1+nt-1)*(nt-1))/2<<"\n";
+
+	//prepare temp structure to whole roi correlation data
+	vtkFloatArray* temp=vtkFloatArray::New();
+	temp->SetNumberOfComponents(nt);
+	temp->SetNumberOfTuples(nt);
+	for(int ia=0;ia<nt;ia++)
+		temp->FillComponent(ia,0.0);
+
+	int index=0;
+	for(int it=0;it<nt;it++)
+	{
+		for(int jt=0;jt<nt;jt++)
+		{
+			temp->SetComponent(it,jt,inp->GetComponent(index,0));
+			++index;
+		}
+	}
+	for(int i=0;i<nt;i++)
+	{
+		for(int j=i+1;j<nt;j++)
+		{
+			alarkfile<<i<<"\t"<<j<<"\t"<<temp->GetComponent(i,j)<<"\n";
+
+		}
+	}
+	alarkfile.close();
+}
+/*
+ * @[in]:input:ROI Correlation from vtkbisTimeSeriesCorrelation
+ * @[in]:this->FunctionalImage
+ * @[in]:this->ROI Map
+ * @[out]:output:(pair-wise) shortest path length
+ * @[out]:OutData2:network measures
+ */
+void vtkbisfmriToolBox::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+	fprintf(stderr,"Beginning vtkbisfmriToolBox\n");
+	if(input == NULL)
+	{
+		cerr<<"No ROI Correlation Image input. Computation terminated.\n";
+		return;
+	}else if(this->FunctionalImage ==NULL)
+	{
+		cerr<<"No Functional Image input. Computation terminated.\n";
+		return;
+	}else if(this->roiMap == NULL)
+	{
+		cerr<<"No ROI Map input. Computation terminated.\n";
+		return;
+	}
+
+	int dim[3];int dim2[3];
+	this->FunctionalImage->GetDimensions(dim);
+	this->roiMap->GetDimensions(dim2);
+	int sum=0;int sum1=0;
+	for(int ia=0;ia<=2;ia++)
+	{
+		sum+=abs(dim2[ia]-dim[ia]);
+	}
+	if(sum>0)
+	{
+		cerr<<"ROI Map and Functional image does not have the same dimensions. Computation terminated.'n";
+		return;
+	}
+	int numItem=12;
+
+	vtkFloatArray* brainNetwork=vtkbisfmriToolBox::ComputeBrainNetwork(input, this->Threshold, 1);
+
+	int nc=brainNetwork->GetNumberOfComponents();
+	vtkDataArray* out=output->GetPointData()->GetScalars();
+	out->FillComponent(0,0.0);
+
+	vtkIntArray* degrees=vtkbisfmriToolBox::ComputeDegreesUnd(brainNetwork);
+	vtkpxMatrix* BC=vtkbisfmriToolBox::ComputeBetweenessCentrality(brainNetwork);
+	vtkFloatArray* localE=vtkbisfmriToolBox::ComputeLocalEfficiency(brainNetwork,degrees);
+	vtkFloatArray* otherData=vtkbisfmriToolBox::ComputeNetworkMeasures(brainNetwork,this->FunctionalImage,this->roiMap,degrees,out);
+
+	//	fprintf(stderr,"This far\n");
+
+	vtkbisfmriToolBox::GenerateAdjMatrixOutputForAlarkViewer(brainNetwork, otherData, this->GetFilename());
+
+	//output network measures as an nii.gz file
+	int dim3[3];dim3[0]=nc;dim3[1]=numItem;dim3[2]=1;
+	//	int ext[6] = { 0, nc-1, 0, numItem-1, 0, 1 };
+	this->OutData2=vtkImageData::New();
+	this->OutData2->SetSpacing(output->GetSpacing());
+	this->OutData2->SetOrigin(output->GetOrigin());
+	this->OutData2->SetScalarTypeToFloat();
+	this->OutData2->SetNumberOfScalarComponents(1);
+	this->OutData2->SetDimensions(dim3);
+	//	this->OutData2->SetWholeExtent(ext);
+	this->OutData2->AllocateScalars();//allocation space on memory
+
+	vtkDataArray* out2=this->OutData2->GetPointData()->GetScalars();
+	out2->FillComponent(0,0.0);
+
+	vtkbisfmriToolBox::GenerateOutputForAlarkViewer(localE, BC, otherData,this->GetFilename2(), out2);
+	vtkbisfmriToolBox::GenerateROICorrelationOutputForAlarkViewer(input, otherData, this->GetFilename3());
+}
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisfmriToolBox.h b/bioimagesuite30_src/Connectivity/vtkbisfmriToolBox.h
new file mode 100644
index 0000000..3222682
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisfmriToolBox.h
@@ -0,0 +1,139 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisfmriToolBox.cpp
+ *
+ *  Created on: May 21, 2010
+ *      Author: Isabella Murphy,Xilin Shen
+ *      This class compute complex network measures
+ *      1. Adjacency matrix (brain network)
+ *      2. Degrees
+ *      3. Reachability matrix
+ *      4. Shortest path length matrix
+ *      5. Number of triangles
+ *      6. Characteristic path length
+ *      7. Global efficiency
+ *      8. Clustering coefficient
+ *      9. Transicity
+ *      10. Local efficiency
+ *      11. Closeness Centrality
+ *      12. Betweeness centrality
+ *      @[in]:image1 Functional Image.
+ *      @[in]:image2 ROI Correlation Image
+ *      @[in]:image3 ROI Map Image
+ *      @[out]:image1 shortest path length. # of tuples=# of components=# of nodes
+ *      @[out]:image2 network measurements. # of tuples=# of nodes, # of components=12
+ *
+ */
+
+#ifndef VTKBISFMRITOOLBOX_H_
+#define VTKBISFMRITOOLBOX_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkIntArray.h"
+#include "vtkpxMatrix.h"
+#include "vtkFloatArray.h"
+#include <string>
+#include <iostream>
+
+class vtkInformation;
+class vtkInformationVector;
+
+class vtkbisfmriToolBox : public vtkSimpleImageToImageFilter {
+public:
+	static vtkbisfmriToolBox *New();
+	vtkTypeMacro(vtkbisfmriToolBox,vtkSimpleImageToImageFilter);
+
+	//FunctionalImage Image
+	vtkSetObjectMacro(FunctionalImage,vtkImageData);
+	vtkGetObjectMacro(FunctionalImage,vtkImageData);
+
+	//roiMap Image
+	vtkSetObjectMacro(roiMap,vtkImageData);
+	vtkGetObjectMacro(roiMap,vtkImageData);
+
+	//OutData2 Image
+	vtkSetObjectMacro(OutData2,vtkImageData);
+	vtkGetObjectMacro(OutData2,vtkImageData);
+
+	//Threshold
+	vtkSetMacro(Threshold,float);
+	vtkGetMacro(Threshold,float);
+
+	// File name
+	virtual void SetFilename(const char* filename);
+	virtual const char* GetFilename();
+	// File name
+	virtual void SetFilename2(const char* filename2);
+	virtual const char* GetFilename2();
+	// File name
+	virtual void SetFilename3(const char* filename3);
+	virtual const char* GetFilename3();
+
+	/*
+	 * ComputeBinaryNetwork
+	 * @[in]:FunctionalImage. Output of vtkbisTimeSeriesCorrelation, an ROI*ROI*1*1 image
+	 * @[in]:threshold. If value of (ROI1,ROI2)>threshold, (ROI1,ROI2)of network=1
+	 * @[out]:matrix. An binary matrix describe the connectiveness between ROIs
+	 */
+	static vtkFloatArray* ComputeBrainNetwork(vtkImageData* roiCorrelation, float threshold, int binary);
+	static vtkIntArray* ComputeDegreesUnd(vtkFloatArray* brainNetwork);
+	static float ComputeNumberOfTriangles(vtkFloatArray* brainNetwork,int tuple);
+	static vtkpxMatrix* ComputeBetweenessCentrality(vtkFloatArray* brainNetwork);
+	static vtkFloatArray* ComputeLocalEfficiency(vtkFloatArray* brainNetwork, vtkIntArray* degrees);
+	static vtkFloatArray* ComputeNetworkMeasures(vtkFloatArray* brainNetwork,vtkImageData* brain, vtkImageData* ROI, vtkIntArray* degrees, vtkDataArray* out);
+	static void GenerateOutputForAlarkViewer(vtkFloatArray* localE, vtkpxMatrix * BC, vtkFloatArray* otherData,const char* Filename2, vtkDataArray* out2);
+	static void GenerateAdjMatrixOutputForAlarkViewer(vtkFloatArray* brainNetwork, vtkFloatArray* otherData, const char* Filename);
+	static void GenerateROICorrelationOutputForAlarkViewer(vtkImageData* roiCorrelation, vtkFloatArray* otherData, const char* Filename3);
+
+protected:
+
+  vtkbisfmriToolBox();
+  virtual ~vtkbisfmriToolBox();
+  virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+    					  vtkInformationVector *outputVector);
+  // Execute Function -- main function
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+
+private:
+	vtkbisfmriToolBox(const vtkbisfmriToolBox& src) {};
+	vtkbisfmriToolBox& operator=(const vtkbisfmriToolBox& rhs) {};
+	vtkImageData* FunctionalImage;
+	vtkImageData* roiMap;
+	vtkImageData* OutData2;
+	float Threshold;
+	//BTX
+	std::string Filename;
+	std::string Filename2;
+	std::string Filename3;
+	//ETX
+};
+
+#endif /* VTKBISFMRITOOLBOX_H_ */
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisfmriToolBoxOptimize.cpp b/bioimagesuite30_src/Connectivity/vtkbisfmriToolBoxOptimize.cpp
new file mode 100644
index 0000000..3b5307c
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisfmriToolBoxOptimize.cpp
@@ -0,0 +1,1280 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisfmriToolBox.cpp
+ *
+ *  Created on: May 21, 2010
+ *      Author: Isabella Murphy,Xilin Shen
+ *      This class compute complex network measures
+ *      1. Adjacency matrix (brain network)
+ *      2. Degrees
+ *      3. Reachability matrix
+ *      4. Shortest path length matrix
+ *      5. Number of triangles
+ *      6. Characteristic path length
+ *      7. individual characteristic path length
+ *      8. Global efficiency
+ *      9. individual global efficiency
+ *      10. Clustering coefficient
+ *      11. Transicity
+ *      12. Local efficiency
+ *      13. individual local efficiency
+ *      14. Closeness Centrality
+ *      15. Betweeness centrality
+ *      @[in]:input,vtkImageData,seedToseed correlation result from vtkbisTimeSeriesCorrelation
+ *      @[in]:this->functionalImage,vtkImageData
+ *      @[in]:this->roiMap,vtkImageData
+ *      @[in]:this->threshold, to threshold seedToseed correlation result to generate adjacency matrix for the rest of calculation
+ *      @[out]:output,_shortestpathlength.nii.gz
+ *      @[out]:this->OutData2,_networkMeasure.nii.gz
+ *      @[out]:_adjMatrixForAlarkViewer.txt.Text file for Alark Viewer to display adjacency matrix.
+ *      @[out]:_networkMeasures.txt. Text file for Alark Viewer to display complex network measures.
+ *      @[out]:_roiCorrelationForAlarkViewer.txt. Text file for Alark Viewer to display seedToseed correlation result from vtkbisTimeSereisCorrelation.
+ */
+#include "vtkbisImageTimeSeriesNormalize.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include <vtkbisfmriToolBoxOptimize.h>
+#include "vtkObjectFactory.h"
+#include "vtkCellArray.h"
+#include "vtkPointData.h"
+#include <vector>
+#include "vtkbisROIMean.h"
+#include "vtkPoints.h"
+#include "vtkIdList.h"
+#include "vtkbisDijkstraGraphGeodesicPath.h"
+#include "vtkpxMatrix.h"
+#include "vtkPolyDataWriter.h"
+#include <time.h>
+#include "pxisinf.h"
+#include <fstream>
+#include <cstdlib>
+#include "vnl/vnl_sparse_matrix.h"
+
+
+using namespace std;
+
+
+vtkbisfmriToolBoxOptimize* vtkbisfmriToolBoxOptimize::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisfmriToolBoxOptimize");
+  if(ret)
+    {
+      return (vtkbisfmriToolBoxOptimize*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisfmriToolBoxOptimize;
+}
+
+vtkbisfmriToolBoxOptimize::vtkbisfmriToolBoxOptimize()
+{
+  this->FunctionalImage=NULL;
+  this->roiMap=NULL;
+  this->OutData2=NULL;
+  this->Threshold=0.0;
+}
+
+//----------------------------------------------------------------------------
+vtkbisfmriToolBoxOptimize::~vtkbisfmriToolBoxOptimize()
+{
+  this->SetFunctionalImage(NULL);
+  this->SetroiMap(NULL);
+  if (this->OutData2!=NULL)
+    this->OutData2->Delete();
+}
+
+void vtkbisfmriToolBoxOptimize::SetFilename(const char* filename)
+{
+  this->Filename=filename;
+}
+
+const char* vtkbisfmriToolBoxOptimize::GetFilename()
+{
+  return this->Filename.c_str();
+}
+void vtkbisfmriToolBoxOptimize::SetFilename2(const char* filename2)
+{
+  this->Filename2=filename2;
+}
+
+const char* vtkbisfmriToolBoxOptimize::GetFilename2()
+{
+  return this->Filename2.c_str();
+}
+void vtkbisfmriToolBoxOptimize::SetFilename3(const char* filename3)
+{
+  this->Filename3=filename3;
+}
+
+const char* vtkbisfmriToolBoxOptimize::GetFilename3()
+{
+  return this->Filename3.c_str();
+}
+//----------------------------------------------------------------------------
+int vtkbisfmriToolBoxOptimize::RequestInformation(vtkInformation*,
+                                           vtkInformationVector**,
+                                           vtkInformationVector* outputVector)
+{
+  vtkInformation* outInfo = outputVector->GetInformationObject(0);
+
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+  return 1;
+}
+/*
+ * ComputeBrainNetwork
+ * @[in]:roiCorrelation. Output of vtkbisTimeSeriesCorrelation, an ROI*ROI*1*1 image.
+ * For example, correlation of average time course 0 to  (say 0-10) is stored in output
+ * vtkImagedata voxel 0-10 component 0;correlation of average time course 1 to all other
+ * average time course (say 0-10) is stored in output vtkImageData voxel 11-20 component
+ * 0 and so on.
+ * @[in]:threshold. If value of (ROI1,ROI2)>threshold, (ROI1,ROI2)is stored in the network
+ * @[in]:binary. If 0 then output weighted network; if 1 then output binary netowrk
+ * @[out]:2Darray. A matrix describe the connection between ROIs
+ */
+vtkFloatArray* vtkbisfmriToolBoxOptimize::ComputeBrainNetwork(vtkImageData* roiCorrelation, float threshold, int binary)
+{
+	//get number of regions
+	vtkDataArray* inp=roiCorrelation->GetPointData()->GetScalars();
+	int nt = (int)sqrt(double(inp->GetNumberOfTuples()));
+
+	//prepare output
+	vtkFloatArray* output=vtkFloatArray::New();
+	output->SetNumberOfComponents(nt);
+	output->SetNumberOfTuples(nt);
+	for(int ia=0;ia<nt;ia++)
+		output->FillComponent(ia,0.0);
+
+	//scan through the roiCorrelation result, fill up the brain network base on the threshold
+	int counter=0;
+	for (int ia=0;ia<nt;ia++)
+    {
+		for (int ib=0;ib<nt;ib++)
+		{
+			double value = inp->GetComponent(counter,0);
+			if(value > threshold && ia!=ib)
+			{
+				if(binary > 0)
+				{
+					output->SetComponent(ia,ib,1.0);
+				}
+				else
+				{
+					output->SetComponent(ia,ib,value);
+				}
+			}
+			++counter;
+		}
+    }
+
+	return output;
+}
+/*
+ * In an undirected graph, the degree is the number of connections for individual nodes.
+ * @[in]:brainNetwork. the output of ComputeBrainNetwork
+ * @[out]:output. Output a vtkIntArray and a text file
+ */
+vtkIntArray* vtkbisfmriToolBoxOptimize::ComputeDegreesUnd(vtkFloatArray* brainNetwork)
+{
+	int nt = brainNetwork->GetNumberOfComponents();
+	vtkIntArray* output= vtkIntArray::New();
+	output->SetNumberOfComponents(1);
+	output->SetNumberOfTuples(nt);
+	output->FillComponent(0,0.0);
+
+	for (int i=0;i<nt;i++)
+    {
+		int sum = 0;
+		for (int j=0;j<nt;j++)
+		{
+			if(brainNetwork->GetComponent(i,j)==1)
+				++sum;
+		}
+		output->SetComponent(i,0,(double)sum);
+    }
+	return output;
+}
+
+float vtkbisfmriToolBoxOptimize::ComputeNumberOfTriangles(vtkFloatArray* brainNetwork,int tuple)
+{
+	int nt=brainNetwork->GetNumberOfTuples();
+	float counter=0;
+	for(int j=0;j<nt;j++)
+	{
+		for(int h=0;h<nt;h++)
+		{
+			if((brainNetwork->GetComponent(tuple,j)==1) && (brainNetwork->GetComponent(tuple,h)==1) && (brainNetwork->GetComponent(j,h)==1))
+			{
+				++counter;
+			}
+		}
+	}
+	counter/=2;
+	return counter;
+}
+/*
+void vtkbisfmriToolBoxOptimize::transpose(vnl_sparse_matrix<float> & A, vnl_sparse_matrix<float> & A_transpose)
+{
+    //vnl_sparse_matrix<double> A(30,30);
+	//vnl_sparse_matrix<double> A_transpose(30,30);
+	int N = A.rows();
+
+	// For each row I
+	for (int i = 0; i < N; i++)
+	{
+		vcl_vector< vnl_sparse_matrix_pair<float> > rowVector = A.get_row(i);
+		int numRowElems = rowVector.size();
+
+		for (int elem=0; elem<numRowElems; elem++)
+		{
+			vnl_sparse_matrix_pair<float> elemPair = rowVector[elem];
+			int j = elemPair.first;
+			float value = elemPair.second;
+
+			A_transpose(j,i) = value;
+		}
+	}
+}
+*/
+/*
+ * Translate from matlab code betweeness_bin.m
+ */
+vtkpxMatrix* vtkbisfmriToolBoxOptimize::ComputeBetweenessCentrality(vtkFloatArray* brainNetwork)
+{
+	time_t start,end;
+	time(&start);
+	unsigned int nt=brainNetwork->GetNumberOfTuples();
+	std::cout<<"Start computing BC remaked."<<endl;
+
+	vtkpxMatrix* BC=vtkpxMatrix::New();
+	//vtkpxMatrix* G=vtkpxMatrix::New();
+	//vtkpxMatrix* Gt=vtkpxMatrix::New();
+	//vtkpxMatrix* NPd=vtkpxMatrix::New();
+	//vtkpxMatrix* tempNPd=vtkpxMatrix::New();
+	//vtkpxMatrix* NSPd=vtkpxMatrix::New();
+	//vtkpxMatrix* NSP=vtkpxMatrix::New();
+	//vtkpxMatrix* tempNSP=vtkpxMatrix::New();
+	//vtkpxMatrix* L=vtkpxMatrix::New();
+	vtkpxMatrix* DP=vtkpxMatrix::New();
+	//vtkpxMatrix* tempDP=vtkpxMatrix::New();
+	//vtkpxMatrix* DPd1=vtkpxMatrix::New();
+	//vtkpxMatrix* tempDPd1=vtkpxMatrix::New();
+	//vtkpxMatrix* temptempDPd1=vtkpxMatrix::New();
+
+
+	//G->Zeros(nt,nt);
+	vnl_sparse_matrix<float> vnlG(nt,nt);
+	for(int row = 0;row<nt;row++)
+	{
+		for(int col=0;col<nt;col++)
+		{
+			//G->SetElement(row,col,brainNetwork->GetComponent(row,col));
+			float val = brainNetwork->GetComponent(row,col);
+			if(val!=0)
+			{
+				vnlG(row,col)=val;
+
+			}
+		}
+	}
+
+	//NPd->Copy(G);
+	vnl_sparse_matrix<float> vnlNPd(vnlG);
+
+	std::cout<<"NPd->Copy(G) done "<<endl;
+
+
+	//NSPd->Copy(NPd);
+	vnl_sparse_matrix<float> vnlNSPd(vnlNPd);
+	std::cout<<"NSPd->Copy(NPd) done "<<endl;
+
+
+	//NSP->Copy(NSPd);
+	vnl_sparse_matrix<float> vnlNSP(vnlNSPd);
+	std::cout<<"NSP->Copy(NSPd) done "<<endl;
+
+	//L->Copy(NSPd);
+	vnl_sparse_matrix<float> vnlL(vnlNSPd);
+	std::cout<<"L->Copy(NSPd) done "<<endl;
+
+	//NSP(I)=1;L(I)1;
+	for(int i=0;i<nt;i++)
+	{
+		//NSP->SetElement(d,d,1);
+		vnlNSP(i,i)=1;
+		//L->SetElement(d,d,1);
+		vnlL(i,i)=1;
+	}
+
+	int NSPdhasOne=1;
+	int d=1;//path length
+
+	while(NSPdhasOne==1 )
+	{
+		NSPdhasOne=0;
+		++d;
+		std::cout<<"in while loop "<<d-1<<" time\n";
+
+		//NPd=NPd*G
+		//vtkpxMatrix::Multiply(NPd,G,tempNPd);
+		//NPd->Copy(tempNPd);
+		vnl_sparse_matrix<float> vnltempNPd(nt,nt);
+        vnlNPd.mult(vnlG, vnltempNPd);
+        vnlNPd=vnltempNPd;
+
+
+		//NSPd=NPd.*(L==0)
+		for(int row = 0;row<nt;row++)
+		{
+			for(int col=0;col<nt;col++)
+			{
+				//if(L->GetElement(row,col)==0)
+				if(vnlL(row,col) == 0)
+				{
+					//NSPd->SetElement(row,col,NPd->GetElement(row,col));
+					vnlNSPd(row,col)=vnlNPd(row,col);
+
+				}else{
+					//NSPd->SetElement(row,col,0);
+					vnlNSPd(row,col)=0;
+				}
+			}
+		}
+
+		//NSP=NSP+NSPd
+		//vtkpxMatrix::Add(NSP,NSPd,tempNSP);
+		//NSP->Copy(tempNSP);
+		vnl_sparse_matrix<float> vnltempNSP(nt,nt);
+		vnlNSP.add(vnlNSPd,vnltempNSP);
+		vnlNSP=(vnltempNSP);
+
+		//L=L+d.*(NSPd~=0)
+		for(int row = 0;row<nt;row++)
+		{
+			for(int col=0;col<nt;col++)
+			{
+				//if(NSPd->GetElement(row,col)!=0)
+				if(vnlNSPd(row,col)!=0)
+				{
+					//L->SetElement(row,col,d);
+					vnlL(row,col)=d;
+					NSPdhasOne=1;
+					//can not jump out of the double for look until all the rows and column of L has been updated
+				}
+			}
+		}
+	}//end of while loop
+
+	//L(~L)=-1; L(I)=0; NSP(~NSP)=1
+	for(int row = 0;row<nt;row++)
+	{
+		for(int col=0;col<nt;col++)
+		{
+			//if(L->GetElement(row,col)==0)
+			if(vnlL(row,col)==0)
+			{
+				//L->SetElement(row,col,-1);
+				vnlL(row,col)=-1;
+			}
+			//if(NSP->GetElement(row,col)==0)
+			if(vnlNSP(row,col)==0)
+			{
+				//NSP->SetElement(row,col,1);
+				vnlNSP(row,col)=1;
+			}
+		}
+	}
+	for(int i=0;i<nt;i++)
+	{
+		//L->SetElement(l,l,0);
+		vnlL(i,i)=0;
+	}
+
+
+	//Gt=G.'
+	//Gt->Copy(G);
+	//Gt->Transpose();
+	/**
+	 * This block of code is to do transpose
+	 */
+	vnl_sparse_matrix<float> vnlGt(nt,nt);
+	int N = vnlG.rows();
+
+	// For each row I
+	for (int i = 0; i < N; i++)
+	{
+		vcl_vector< vnl_sparse_matrix_pair<float> > rowVector = vnlG.get_row(i);
+		int numRowElems = rowVector.size();
+
+		for (int elem=0; elem<numRowElems; elem++)
+		{
+			vnl_sparse_matrix_pair<float> elemPair = rowVector[elem];
+			int j = elemPair.first;
+			float value = elemPair.second;
+
+			vnlGt(j,i) = value;
+		}
+	}
+
+
+	/*for(d=diam:-1:2)
+	 *DPd1=((L==d).*(1+DP)/NSP)*Gt).*((L==d-1).*NSP)
+	 *DP=DP+DPd1
+	 */
+	//DP->Zeros(nt,nt);
+	vnl_sparse_matrix<float> vnlDP(nt,nt);
+	//DPd1->Zeros(nt,nt);
+	vnl_sparse_matrix<float> vnlDPd1(nt,nt);
+	//tempDPd1->Zeros(nt,nt);
+	vnl_sparse_matrix<float> vnltempDPd1(nt,nt);
+	int diam=d-1;
+	int counter2=0;
+	for(int t=diam;t>=2;t--)
+	{
+		std::cout<<"In t loop "<<++counter2;
+		for(int row = 0;row<nt;row++)
+		{
+			for(int col=0;col<nt;col++)
+			{
+				//if(L->GetElement(row,col)==t)
+				if(vnlL(row,col)==t)
+				{
+					//tempDPd1->SetElement(row,col,((DP->GetElement(row,col)+1)/NSP->GetElement(row,col)));
+					vnltempDPd1(row,col)=(vnlDP(row,col)+1)/vnlNSP(row,col);
+				}
+			}
+		}
+		//vtkpxMatrix::Multiply(tempDPd1,Gt,temptempDPd1);
+		vnl_sparse_matrix<float> vnltemptempDPd1(nt,nt);
+		vnltempDPd1.mult(vnlGt,vnltemptempDPd1);
+
+		//DPd1->Fill(0);
+		for(int row = 0;row<nt;row++)
+		{
+			for(int col=0;col<nt;col++)
+			{
+				//std::cout<<"L:"<<vnlL(row,col);
+				//if(L->GetElement(row,col)==(t-1))
+				if(vnlL(row,col)==t-1)
+				{
+					//DPd1->SetElement(row,col,temptempDPd1->GetElement(row,col)*NSP->GetElement(row,col));
+					vnlDPd1(row,col)=vnltemptempDPd1(row,col)*vnlNSP(row,col);
+				}
+			}
+		}
+		//vtkpxMatrix::Add(DP,DPd1,tempDP);
+		//DP->Copy(tempDP);
+		vnl_sparse_matrix<float> vnltempDP(nt,nt);
+		vnlDP.add(vnlDPd1,vnltempDP);
+		vnlDP=vnltempDP;
+
+	}
+
+	//BC=sum(DP,1)
+	//copy vnlDP to vtkpxMatrix DP and then do column sum using vtkpxMatrix's ColumnSums method
+	DP->Zeros(nt,nt);
+	int numRows = vnlDP.rows();
+
+	// For each row I
+	for (int i = 0; i < numRows; i++)
+	{
+		vcl_vector< vnl_sparse_matrix_pair<float> > rowVector = vnlDP.get_row(i);
+		int numRowElems = rowVector.size();
+
+		for (int elem=0; elem<numRowElems; elem++)
+		{
+			vnl_sparse_matrix_pair<float> elemPair = rowVector[elem];
+			int j = elemPair.first;
+			float value = elemPair.second;
+
+			DP->SetElement(i,j,value);
+			}
+		}
+	BC=DP->ColumnSums();
+
+
+	time(&end);
+	  std::cout<<endl<<"\nelapsed time for calculating Betweeness Centrality in fmritoolboxoptimized "<<difftime(end, start)<<" seconds"<<endl;
+
+	//G->Delete();
+	//Gt->Delete();
+	//NPd->Delete();
+	//tempNPd->Delete();
+	//NSPd->Delete();
+	//NSP->Delete();
+	//tempNSP->Delete();
+	//L->Delete();
+	DP->Delete();
+	//tempDP->Delete();
+	//DPd1->Delete();
+	//tempDPd1->Delete();
+	//temptempDPd1->Delete();
+	return BC;
+}
+
+/*
+ * translate from matalb code efficiency.m
+ */
+vtkFloatArray* vtkbisfmriToolBoxOptimize::ComputeLocalEfficiency(vtkFloatArray* brainNetwork, vtkIntArray* degrees)
+{
+	time_t start,end;
+	time(&start);
+	std::cout<<"Start computing Local Efficiency."<<endl;
+
+	int nt=brainNetwork->GetNumberOfTuples();
+
+		vtkFloatArray* localE = vtkFloatArray::New();
+		localE->SetNumberOfComponents(1);
+		localE->SetNumberOfTuples(nt);
+		localE->FillComponent(0,0.0);
+		//vtkpxMatrix* g=vtkpxMatrix::New();
+		vnl_sparse_matrix<float> vnlg;
+		//vtkpxMatrix* D=vtkpxMatrix::New();
+		vnl_sparse_matrix<float> vnlD;
+		//vtkpxMatrix* tempD=vtkpxMatrix::New();
+		vnl_sparse_matrix<float> vnltempD;
+		//vtkpxMatrix* nPATH=vtkpxMatrix::New();
+		vnl_sparse_matrix<float> vnlnPATH;
+		//vtkpxMatrix* tempPATH=vtkpxMatrix::New();
+		vnl_sparse_matrix<float> vnltempPATH;
+		//vtkpxMatrix* L=vtkpxMatrix::New();
+		vnl_sparse_matrix<float> vnlL;
+
+/*
+		int maxDegree=0;
+		for (int i=0;i<nt;i++)
+	    {
+			if(degrees->GetComponent(i,0)>maxDegree)
+			{
+				maxDegree=degrees->GetComponent(i,0);
+			}
+	    }
+
+		g->Zeros(maxDegree,maxDegree);
+		L->Zeros(maxDegree,maxDegree);
+		*/
+		for(int c=0;c<nt;c++)
+	    {
+			int ki=(int)degrees->GetComponent(c,0);
+			if(ki>=2)
+			{
+				//1.extract small matrix g
+				vector<int> v(ki,0);
+				int index=0;
+				for(int t=0;t<nt;t++)
+				{
+					if(brainNetwork->GetComponent(t,c)>0)
+					{
+						v[index]=t;
+						++index;
+					}
+				}
+
+				//g->Zeros(ki,ki);
+				//g->Fill(0.0);
+				//vnl_sparse_matrix<float> vnlg(ki,ki);
+				vnlg.set_size(ki,ki);
+				for(int row = 0;row<ki;row++)
+				{
+					for(int col=0;col<ki;col++)
+					{
+						//g->SetElement(row,col,brainNetwork->GetComponent(v[row],v[col]));
+						float val = brainNetwork->GetComponent(v[row],v[col]);
+						if(val!=0)
+						{
+							vnlg(row,col)=val;
+						}
+					}
+				}
+
+				//2.make identical matrix D
+				//D->Eye(ki);
+				//vnl_sparse_matrix<float> vnlD(ki,ki);
+				vnlD.set_size(ki,ki);
+				for(int row = 0;row<ki;row++)
+				{
+					for(int col=0;col<ki;col++)
+					{
+						if(row==col)
+						{
+							vnlD(row,col)=1;
+						}
+					}
+				}
+			/*	for(int row = 0;row<ki;row++)
+				{
+					for(int col=0;col<ki;col++)
+					{
+						std::cout<<vnlD(row,col);
+					}
+				}
+				*/
+
+				//3.initialize number of steps
+				int n=1;
+
+				//4.nPATH=g
+				//nPATH->Copy(g);
+				//vnl_sparse_matrix<float> vnlnPATH(ki,ki);
+				vnlnPATH.resize(ki,ki);
+				vnlnPATH=(vnlg);
+
+				//5.L=(nPATH~=0)
+				int LhasOne=0;
+
+				//L->Zeros(ki,ki);
+				//L->Fill(0.0);
+				//vnl_sparse_matrix<float> vnlL(ki,ki);
+				vnlL.set_size(ki,ki);
+				for(int row=0;row<ki;row++)
+				{
+					for(int col=0;col<ki;col++)
+					{
+						//if(nPATH->GetElement(row,col)>0)
+						if(vnlnPATH(row,col)>0)
+						{
+							//L->SetElement(row,col,1);
+							vnlL(row,col)=1;
+							LhasOne=1;
+						}
+					}
+				}
+				while(LhasOne>0)
+				{
+					//6.D=D+n.*L
+					//vtkpxMatrix::Add(D,L,tempD);
+					//D->Copy(tempD);
+					vnltempD.set_size(ki,ki);
+					vnlD.add(vnlL,vnltempD);
+					vnlD=(vnltempD);
+
+					//7. increment number of steps
+					++n;
+
+					//8.nPATH=nPATH*g
+					//vtkpxMatrix::Multiply(nPATH,g,tempPATH);
+					//nPATH->Copy(tempPATH);
+					vnltempPATH.set_size(ki,ki);
+					vnlnPATH.mult(vnlg,vnltempPATH);
+					vnlnPATH=(vnltempPATH);
+
+					//9.L=(nAPTH~=0) and D==0
+					LhasOne=0;
+					//L->Fill(0.0);
+					vnlL.set_size(ki,ki);
+					for(int row=0;row<ki;row++)
+					{
+						for(int col=0;col<ki;col++)
+						{
+							//if((nPATH->GetElement(row,col)!=0) && (D->GetElement(row,col)==0))
+							if(vnlnPATH(row,col)!=0 && vnlD(row,col)==0)
+							{
+								//L->SetElement(row,col,n);
+								vnlL(row,col)=n;
+								LhasOne=1;
+							}
+						}
+					}
+				}//end of while loop
+
+				//10.D=1/D
+				for(int row=0;row<ki;row++)
+				{
+					for(int col=0;col<ki;col++)
+					{
+						//double d=D->GetElement(row,col);
+						double d=vnlD(row,col);
+
+						if(d>0)
+						{
+							//D->SetElement(row,col,(double)1/d);
+							vnlD(row,col)=1/d;
+						}else{
+							//D->SetElement(row,col,0);
+							vnlD(row,col)=0;
+						}
+					}
+				}
+
+				//11.remove 1 from diagnal line
+				for(int d =0;d<ki;d++)
+				{
+					//D->SetElement(d,d,0);
+					vnlD(d,d)=0;
+				}
+
+				//12.sum D
+				//float sum=D->Sum();
+				float sum=0;
+				for(int row=0;row<ki;row++)
+				{
+					for(int col=0;col<ki;col++)
+					{
+						sum+=vnlD(row,col);
+					}
+				}
+
+				//13.e=sum/ki(ki-1)
+				int bot=ki*(ki-1);
+				localE->SetComponent(c,0,(double)sum/bot);
+			}
+	    }
+		time(&end);
+			  std::cout<<endl<<"\nelapsed time for calculating Local Efficiency in fmritoolboxoptimized "<<difftime(end, start)<<" seconds"<<endl;
+		//g->Delete();
+		//D->Delete();
+		//tempD->Delete();
+		//nPATH->Delete();
+		//tempPATH->Delete();
+		//L->Delete();
+		return localE;
+}
+
+/*
+ * Output format:
+ * component
+ * 0 index
+ * 1 x
+ * 2 y
+ * 3 z
+ * 4 label
+ * 5 individual char path length
+ * 6 individual global efficient
+ * 7 closeness centrality
+ * 8 # of triangles
+ * 9 degrees
+ * (below only store one value on tuple 0)
+ * 10 char path length
+ * 11 global efficiency
+ * 12 clustering coefficient
+ * 13 transicity
+ */
+vtkFloatArray* vtkbisfmriToolBoxOptimize::ComputeNetworkMeasures(vtkFloatArray* brainNetwork,vtkImageData* brain, vtkImageData* ROI, vtkIntArray* degrees,vtkDataArray* out)
+{
+  time_t start,end;
+  time(&start);
+  std::cout<<"Start computing Network Measures."<<endl;
+
+  int nt = brainNetwork->GetNumberOfTuples();
+  //std::cout<<"nt:!!!!!!!!!!!"<<nt<<endl;
+
+  int numItem=14;
+
+  vtkFloatArray* output=vtkFloatArray::New();
+  output->SetNumberOfComponents(numItem);
+  output->SetNumberOfTuples(nt);
+  for(int ia=0;ia<numItem;ia++)
+    output->FillComponent(ia,0.0);
+
+  //compute xyz coordinates of each ROI center
+  vtkbisROIMean* calCentroids = vtkbisROIMean::New();
+  calCentroids->SetInput(brain);
+  calCentroids->SetImageROI(ROI);
+  calCentroids->SetDoText(0);
+  calCentroids->Update();
+
+  //vtkbisROIMean output has 1 extra point at end with xyz=-1,-1,-1
+  vtkPoints* centroids = vtkPoints::New();
+  centroids->Allocate(100,10);
+  //centroids->ShallowCopy(calCentroids->GetCentroids());
+  //calCentroids->Delete();
+
+  vtkIdType pt[2];
+  vtkPolyData* surface =vtkPolyData::New();
+  vtkCellArray* s_lines=vtkCellArray::New();
+  s_lines->Allocate(100,10);
+
+  //Now, create the real connections
+  for(int i=0;i<nt;i++)//for each point(ROI)
+    {
+      double x[3];
+      //centroids->GetPoint(i,x);
+      calCentroids->GetCentroids()->GetPoint(i,x);
+      output->SetComponent(i,0,i);
+      output->SetComponent(i,1,x[0]);
+      output->SetComponent(i,2,x[1]);
+      output->SetComponent(i,3,x[2]);
+      output->SetComponent(i,4,i+1);
+
+      centroids->InsertNextPoint(x);
+      for(int j=i+1;j<nt;j++)
+	{
+	  if(brainNetwork->GetComponent(i,j)>0)
+	    {
+	      pt[0]=i;
+	      pt[1]=j;
+	      s_lines->InsertNextCell(2,pt);
+	    }
+	}
+    }
+
+  surface->SetPoints(centroids);
+  centroids->Delete();
+  surface->SetLines(s_lines);
+  s_lines->Delete();
+/*
+  vtkPolyDataWriter* w=vtkPolyDataWriter::New();
+  w->SetInput(surface);
+  w->SetFileName("test.vtk");
+  w->Write();
+  w->Delete();
+*/
+  vtkIntArray* pathlength = vtkIntArray::New();
+  pathlength->SetNumberOfComponents(nt);
+  pathlength->SetNumberOfTuples(nt);
+
+  vtkIntArray* reachable =  vtkIntArray::New();
+  reachable->SetNumberOfComponents(nt);
+  reachable->SetNumberOfTuples(nt);
+
+  for(int ia=0;ia<nt;ia++)
+    {
+      pathlength->FillComponent(ia,0.0);
+      reachable->FillComponent(ia,0.0);
+    }
+
+  for(int ib=0;ib<nt;ib++)
+    reachable->SetComponent(ib,ib,1.0);
+
+
+  //find shortest path using vtkDijkstraGraphGeodesicPath
+  //std::map<int, vector<int> > pathmatrix;
+  vtkbisDijkstraGraphGeodesicPath* shpath = vtkbisDijkstraGraphGeodesicPath::New();
+
+
+  //int idcounter=1;
+  for (int k=0;k<nt;k++)
+    {
+      for(int l=k+1;l<nt;l++)
+	{
+	  shpath->SetInput(surface);
+	  shpath->SetStartVertex(k);
+	  shpath->SetEndVertex(l);
+	  shpath->Update();
+
+	  vtkIdList* list = shpath->GetIdList();
+
+	  //if there is a path between k and l, store it.
+	  if(list->GetId(1)!= -1)
+	    {
+	      int numid = list->GetNumberOfIds();
+	      pathlength->SetComponent(k,l,double(numid-1.0));
+	      reachable->SetComponent(k,l,1.0);
+	      reachable->SetComponent(l,k,1.0);
+	      //std::cout<<"["<<l<<","<<k<<"] \t";
+	      //myfile<<"["<<l<<","<<k<<"] \t";
+	      //vector<int> path(numid,0);
+	      //for (int m=0;m<numid;m++)
+	      //{
+	      //path[m]=list->GetId(m);
+	      //std::cout<<list->GetId(m)<<"\t";
+	      //myfile<<list->GetId(m)<<"\t";
+	      //}
+	      //pathmatrix[idcounter]=path;
+	      //idTable->SetComponent(k,l,idcounter);
+	      //idcounter++;
+
+	      //std::cout<<"\n";
+	      //myfile<<"\n";
+	    }
+	}
+    }
+
+  /*1.output reachability matrix
+   *2.output shortest path length matrix
+   *3.calculate characteristic path length (cpl)
+   *4.calculate global efficiency(ge)
+   *5.calculate closeness centrality
+   */
+  /*	//std::cout<<"Reachability Matrix:\n";
+	//myfile<<"Reachability Matrix:\n";
+	for(int r=0;r<nt;r++)
+	{
+	for(int c=0;c<nt;c++)
+	{
+	std::cout<<reachable->GetComponent(r,c)<<"\t";
+	myfile<<reachable->GetComponent(r,c)<<"\t";
+	}
+	//std::cout<<"\n";
+	//myfile<<"\n";
+	}
+  */
+  double cpl =0;
+  double ge=0.0;
+  //  vector<double> centrality(0,nt);
+
+  //std::cout<<"Path Length Matrix:\n";
+  //myfile<<"Path Length Matrix:\n";
+  int colument=0;
+  int offset=0;
+  for(int n=0;n<nt;n++)
+    {
+      double sumdi=0.0;
+      //initialize rownt=1. Because a node is always connect to itself, but our brain network set plength to itself to 0. By setting rownt=1 to start with, we add 1 back.
+      int rownt=1;
+      double thiscpl=0.0;
+      double thisge=0.0;
+      for(int p=0;p<nt;p++)
+	{
+	  int plength;
+	  if(n<p)
+	    {
+	      plength=(int)pathlength->GetComponent(n,p);
+	    }else{
+	    plength=(int)pathlength->GetComponent(p,n);
+	  }
+	  if(plength>0)
+	    {
+	      thisge+=(double)1/plength;
+	      ++rownt;
+	      sumdi+=plength;
+	      out->InsertTuple1(offset,plength);
+
+	    }
+	  ++offset;
+	  //std::cout<<plength<<"\t";
+	  //myfile<<plength<<"\t";
+
+
+	}
+      output->SetComponent(n,7,(double)(rownt-1)/sumdi);
+      //centrality[n]=(double)(rownt-1)/sumdi;
+
+      //if rownt >1 means this node connect to another node other then itself, then count this node for CPL and GE
+      if(rownt>1)
+	{
+	  thisge/=(rownt-1);
+	  output->SetComponent(n,6,thisge);
+	  ge+=thisge;
+	  thiscpl=(double)sumdi/(rownt-1);
+	  output->SetComponent(n,5,thiscpl);
+	  cpl+=thiscpl;
+	  ++colument;
+	}
+      //std::cout<<"\n";
+      //myfile<<"\n";
+    }
+
+  cpl/=colument;
+  ge/=colument;
+  std::cout<<"Characteristic Path Length: "<<cpl<<" \nGlobal Efficiency: "<<ge;
+  //myfile<<"Characteristic Path Length: "<<cpl<<" \nGlobal Efficiency: "<<ge<<" \nCloseness Centrality: ";
+  output->SetComponent(0,10,cpl);
+  output->SetComponent(0,11,ge);
+  /*	for(int ib=0;ib<nt;ib++)
+    {
+    std::cout<<centrality[ib]<<"\t";
+    myfile<<centrality[ib]<<"\t";
+
+    }
+  */
+  //calculate number of triangles
+  vector<float> triangle(nt,0.0);
+  //std::cout<<"\nNumber of Triangles: ";
+  //myfile<<"\nNumber of Triangles: ";
+  for(int i=0;i<nt;i++)
+    {
+      triangle[i]=vtkbisfmriToolBoxOptimize::ComputeNumberOfTriangles(brainNetwork,i);
+      //std::cout<<triangle[i]<<"\t";
+      //myfile<<triangle[i]<<"\t";
+      output->SetComponent(i,8,ComputeNumberOfTriangles(brainNetwork,i));
+    }
+
+  //compute clustering coefficient
+  float ci=0.0;int counter=0;
+  float ttop=0.0;float tbot=0.0;
+  for(int i=0;i<nt;i++)
+    {
+      int ki=(int)degrees->GetComponent(i,0);
+      output->SetComponent(i,9,ki);
+      if(ki>=2)
+	{
+	  ttop+=2*triangle[i];
+	  tbot+=ki*(ki-1);
+	  ci+=(float)((2*triangle[i])/(ki*(ki-1)));
+	  ++counter;
+	}
+    }
+  float cc=(float)ci/counter;
+  float trans=(float)ttop/tbot;
+
+  std::cout<<"\nClustering Coefficient: "<<cc;
+  std::cout<<"\nTransitivity: "<<trans;
+
+  output->SetComponent(0,12,cc);
+  output->SetComponent(0,13,trans);
+
+  //myfile<<"\nClustering Coefficient: "<<cc<<"\nTransitivity: "<<trans;
+
+  time(&end);
+  std::cout<<endl<<"\nelapsed time for calculating Network Measurements in fmritoolboxoptimized "<<difftime(end, start)<<" seconds"<<endl;
+
+  surface->Delete();
+  pathlength->Delete();
+
+  //idTable->Delete();
+
+  //shpath->Delete();
+  //fprintf(stderr,"OK about to return output size %d x %d\n",output->GetNumberOfTuples(),output->GetNumberOfComponents());
+  return output;
+  //myfile.close();
+
+}
+
+/*
+ * otherData Input format:
+ * component
+ * 0 index
+ * 1 x
+ * 2 y
+ * 3 z
+ * 4 label
+ * 5 individual char path length
+ * 6 individual global efficient
+ * 7 closeness centrality
+ * 8 # of triangles
+ * 9 degrees
+ * (below only store one value on tuple 0)
+ * 10 char path lenth
+ * 11 global efficiency
+ * 12 clustering coefficient
+ * 13 transicity
+ */
+void vtkbisfmriToolBoxOptimize::GenerateOutputForAlarkViewer(vtkFloatArray* localE, vtkpxMatrix * BC, vtkFloatArray* otherData,const char* Filename2, vtkDataArray* out2)
+{
+  int nt=otherData->GetNumberOfTuples();
+  int nc=10;
+  int out2nc=12;
+
+  std::ofstream alarkfile(Filename2);
+
+  if(!alarkfile.is_open())
+    {
+      cout<< "Unable to open file"<<Filename2<<"\n";
+      return;
+    }
+  else
+    {
+      std::cout << "Opening " << Filename2 << "\n";
+    }
+
+  alarkfile<<"#Connectivity file\n#Points\n"<<nt<<"\n#index x y z label ind.CharPathLength ind.GlobalEffi. ClosenessCentrality #ofTriangles Degrees LocalEffi BetweenessCentrality\n";
+
+  int index=0;
+  for (int i=0;i<nt;i++)
+    {
+      //      fprintf(stderr,"Row %d/%d\n",i,nt);
+      for(int j=0;j<nc;j++)
+	{
+	  alarkfile<<otherData->GetComponent(i,j)<<"\t";
+	  out2->SetComponent(index,0,otherData->GetComponent(i,j));
+	  ++index;
+	}
+      alarkfile<<localE->GetComponent(i,0)<<"\t"<<BC->GetDirectElement(i,0)<<"\n";
+      out2->SetComponent(index,0,localE->GetComponent(i,0));
+      ++index;
+      out2->SetComponent(index,0,BC->GetDirectElement(i,0));
+      ++index;
+    }
+  alarkfile<<"#Other information\n#CharPathLength "<<otherData->GetComponent(0,10)<<"\n#Global Effi "<<otherData->GetComponent(0,11)<<"\n#Clustering Coef "<<otherData->GetComponent(0,12)<<"\n#Transicity "<<otherData->GetComponent(0,13);
+
+  alarkfile.close();
+  //  fprintf(stderr,"This Far\n");
+}
+
+void vtkbisfmriToolBoxOptimize::GenerateAdjMatrixOutputForAlarkViewer(vtkFloatArray* brainNetwork, vtkFloatArray* otherData, const char* Filename)
+{
+	std::ofstream alarkfile(Filename);
+
+		if(!alarkfile.is_open())
+		{
+			cout<< "Unable to open file"<<Filename<<"\n";
+			return;
+		}
+		else
+		{
+			std::cout << "Opening " << Filename << "\n";
+		}
+
+		int nt=brainNetwork->GetNumberOfTuples();
+		int nc=5;
+
+		alarkfile<<"#Connectivity file\n#Points\n"<<nt<<"\n#index x y z label\n";
+
+		for (int i=0;i<nt;i++)
+		{
+			for(int j=0;j<nc;j++)
+			{
+				alarkfile<<otherData->GetComponent(i,j)<<"\t";
+			}
+			alarkfile<<"\n";
+		}
+
+		alarkfile<<"\n#Connections and strengths\n"<<((1+nt-1)*(nt-1))/2<<"\n";
+		for(int i=0;i<nt;i++)
+		{
+			for(int j=i+1;j<nt;j++)
+			{
+				alarkfile<<i<<"\t"<<j<<"\t"<<brainNetwork->GetComponent(i,j)<<"\n";
+			}
+		}
+
+		alarkfile.close();
+}
+void vtkbisfmriToolBoxOptimize::GenerateROICorrelationOutputForAlarkViewer(vtkImageData* roiCorrelation, vtkFloatArray* otherData, const char* Filename3)
+{
+	std::ofstream alarkfile(Filename3);
+
+	if(!alarkfile.is_open())
+	{
+		cout<< "Unable to open file"<<Filename3<<"\n";
+		return;
+	}else
+	{
+		std::cout << "Opening " << Filename3 << "\n";
+	}
+
+	//get number of regions
+	vtkDataArray* inp=roiCorrelation->GetPointData()->GetScalars();
+	int nt = (int)sqrt(double(inp->GetNumberOfTuples()));
+	int nc=5;
+
+	alarkfile<<"#Connectivity file\n#Points\n"<<nt<<"\n#index x y z label\n";
+
+	for (int i=0;i<nt;i++)
+	{
+		for(int j=0;j<nc;j++)
+		{
+			alarkfile<<otherData->GetComponent(i,j)<<"\t";
+		}
+		alarkfile<<"\n";
+	}
+
+	alarkfile<<"\n#Connections and strengths\n"<<((1+nt-1)*(nt-1))/2<<"\n";
+
+	//prepare temp structure to whole roi correlation data
+	vtkFloatArray* temp=vtkFloatArray::New();
+	temp->SetNumberOfComponents(nt);
+	temp->SetNumberOfTuples(nt);
+	for(int ia=0;ia<nt;ia++)
+		temp->FillComponent(ia,0.0);
+
+	int index=0;
+	for(int it=0;it<nt;it++)
+	{
+		for(int jt=0;jt<nt;jt++)
+		{
+			temp->SetComponent(it,jt,inp->GetComponent(index,0));
+			++index;
+		}
+	}
+	for(int i=0;i<nt;i++)
+	{
+		for(int j=i+1;j<nt;j++)
+		{
+			alarkfile<<i<<"\t"<<j<<"\t"<<temp->GetComponent(i,j)<<"\n";
+
+		}
+	}
+	alarkfile.close();
+}
+/*
+ * @[in]:input:ROI Correlation from vtkbisTimeSeriesCorrelation
+ * @[in]:this->FunctionalImage
+ * @[in]:this->ROI Map
+ * @[out]:output:(pair-wise) shortest path length
+ * @[out]:OutData2:network measures
+ */
+void vtkbisfmriToolBoxOptimize::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+	fprintf(stderr,"Beginning vtkbisfmriToolBoxOptimize\n");
+	if(input == NULL)
+	{
+		cerr<<"No ROI Correlation Image input. Computation terminated.\n";
+		return;
+	}else if(this->FunctionalImage ==NULL)
+	{
+		cerr<<"No Functional Image input. Computation terminated.\n";
+		return;
+	}else if(this->roiMap == NULL)
+	{
+		cerr<<"No ROI Map input. Computation terminated.\n";
+		return;
+	}
+
+	int dim[3];int dim2[3];
+	this->FunctionalImage->GetDimensions(dim);
+	this->roiMap->GetDimensions(dim2);
+	int sum=0;int sum1=0;
+	for(int ia=0;ia<=2;ia++)
+	{
+		sum+=abs(dim2[ia]-dim[ia]);
+	}
+	if(sum>0)
+	{
+		cerr<<"ROI Map and Functional image does not have the same dimensions. Computation terminated.'n";
+		return;
+	}
+	int numItem=12;
+std::cout<<"going to compute brain network."<<endl;
+	vtkFloatArray* brainNetwork=vtkbisfmriToolBoxOptimize::ComputeBrainNetwork(input, this->Threshold, 1);
+std::cout<<"Done computing brain network."<<endl;
+	int nc=brainNetwork->GetNumberOfComponents();
+	vtkDataArray* out=output->GetPointData()->GetScalars();
+	out->FillComponent(0,0.0);
+std::cout<<"going to compute degrees."<<endl;
+	vtkIntArray* degrees=vtkbisfmriToolBoxOptimize::ComputeDegreesUnd(brainNetwork);
+	std::cout<<"Done computing degrees."<<endl;
+	vtkpxMatrix* BC=vtkbisfmriToolBoxOptimize::ComputeBetweenessCentrality(brainNetwork);
+	vtkFloatArray* localE=vtkbisfmriToolBoxOptimize::ComputeLocalEfficiency(brainNetwork,degrees);
+	vtkFloatArray* otherData=vtkbisfmriToolBoxOptimize::ComputeNetworkMeasures(brainNetwork,this->FunctionalImage,this->roiMap,degrees,out);
+
+	//	fprintf(stderr,"This far\n");
+
+	vtkbisfmriToolBoxOptimize::GenerateAdjMatrixOutputForAlarkViewer(brainNetwork, otherData, this->GetFilename());
+
+	//output network measures as an nii.gz file
+	int dim3[3];dim3[0]=nc;dim3[1]=numItem;dim3[2]=1;
+	//	int ext[6] = { 0, nc-1, 0, numItem-1, 0, 1 };
+	this->OutData2=vtkImageData::New();
+	this->OutData2->SetSpacing(output->GetSpacing());
+	this->OutData2->SetOrigin(output->GetOrigin());
+	this->OutData2->SetScalarTypeToFloat();
+	this->OutData2->SetNumberOfScalarComponents(1);
+	this->OutData2->SetDimensions(dim3);
+	//	this->OutData2->SetWholeExtent(ext);
+	this->OutData2->AllocateScalars();//allocation space on memory
+
+	vtkDataArray* out2=this->OutData2->GetPointData()->GetScalars();
+	out2->FillComponent(0,0.0);
+
+	vtkbisfmriToolBoxOptimize::GenerateOutputForAlarkViewer(localE, BC, otherData,this->GetFilename2(), out2);
+	vtkbisfmriToolBoxOptimize::GenerateROICorrelationOutputForAlarkViewer(input, otherData, this->GetFilename3());
+}
+
diff --git a/bioimagesuite30_src/Connectivity/vtkbisfmriToolBoxOptimize.h b/bioimagesuite30_src/Connectivity/vtkbisfmriToolBoxOptimize.h
new file mode 100644
index 0000000..a6ae066
--- /dev/null
+++ b/bioimagesuite30_src/Connectivity/vtkbisfmriToolBoxOptimize.h
@@ -0,0 +1,143 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisfmriToolBox.cpp
+ *
+ *  Created on: May 21, 2010
+ *      Author: Isabella Murphy,Xilin Shen
+ *      This class compute complex network measures
+ *      1. Adjacency matrix (brain network)
+ *      2. Degrees
+ *      3. Reachability matrix
+ *      4. Shortest path length matrix
+ *      5. Number of triangles
+ *      6. Characteristic path length
+ *      7. Global efficiency
+ *      8. Clustering coefficient
+ *      9. Transicity
+ *      10. Local efficiency
+ *      11. Closeness Centrality
+ *      12. Betweeness centrality
+ *      @[in]:image1 Functional Image.
+ *      @[in]:image2 ROI Correlation Image
+ *      @[in]:image3 ROI Map Image
+ *      @[out]:image1 shortest path length. # of tuples=# of components=# of nodes
+ *      @[out]:image2 network measurements. # of tuples=# of nodes, # of components=12
+ *
+ */
+
+#ifndef VTKBISFMRITOOLBOX_H_
+#define VTKBISFMRITOOLBOX_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkIntArray.h"
+#include "vtkpxMatrix.h"
+#include "vtkFloatArray.h"
+#include <string>
+#include <iostream>
+
+
+
+class vtkInformation;
+class vtkInformationVector;
+
+class vtkbisfmriToolBoxOptimize : public vtkSimpleImageToImageFilter {
+public:
+	static vtkbisfmriToolBoxOptimize *New();
+	vtkTypeMacro(vtkbisfmriToolBoxOptimize,vtkSimpleImageToImageFilter);
+
+	//FunctionalImage Image
+	vtkSetObjectMacro(FunctionalImage,vtkImageData);
+	vtkGetObjectMacro(FunctionalImage,vtkImageData);
+
+	//roiMap Image
+	vtkSetObjectMacro(roiMap,vtkImageData);
+	vtkGetObjectMacro(roiMap,vtkImageData);
+
+	//OutData2 Image
+	vtkSetObjectMacro(OutData2,vtkImageData);
+	vtkGetObjectMacro(OutData2,vtkImageData);
+
+	//Threshold
+	vtkSetMacro(Threshold,float);
+	vtkGetMacro(Threshold,float);
+
+	// File name
+	virtual void SetFilename(const char* filename);
+	virtual const char* GetFilename();
+	// File name
+	virtual void SetFilename2(const char* filename2);
+	virtual const char* GetFilename2();
+	// File name
+	virtual void SetFilename3(const char* filename3);
+	virtual const char* GetFilename3();
+
+	/*
+	 * ComputeBinaryNetwork
+	 * @[in]:FunctionalImage. Output of vtkbisTimeSeriesCorrelation, an ROI*ROI*1*1 image
+	 * @[in]:threshold. If value of (ROI1,ROI2)>threshold, (ROI1,ROI2)of network=1
+	 * @[out]:matrix. An binary matrix describe the connectiveness between ROIs
+	 */
+	static vtkFloatArray* ComputeBrainNetwork(vtkImageData* roiCorrelation, float threshold, int binary);
+	static vtkIntArray* ComputeDegreesUnd(vtkFloatArray* brainNetwork);
+	static float ComputeNumberOfTriangles(vtkFloatArray* brainNetwork,int tuple);
+	static vtkpxMatrix* ComputeBetweenessCentrality(vtkFloatArray* brainNetwork);
+
+	static vtkFloatArray* ComputeLocalEfficiency(vtkFloatArray* brainNetwork, vtkIntArray* degrees);
+	static vtkFloatArray* ComputeNetworkMeasures(vtkFloatArray* brainNetwork,vtkImageData* brain, vtkImageData* ROI, vtkIntArray* degrees, vtkDataArray* out);
+	static void GenerateOutputForAlarkViewer(vtkFloatArray* localE, vtkpxMatrix * BC, vtkFloatArray* otherData,const char* Filename2, vtkDataArray* out2);
+	static void GenerateAdjMatrixOutputForAlarkViewer(vtkFloatArray* brainNetwork, vtkFloatArray* otherData, const char* Filename);
+	static void GenerateROICorrelationOutputForAlarkViewer(vtkImageData* roiCorrelation, vtkFloatArray* otherData, const char* Filename3);
+
+protected:
+
+  vtkbisfmriToolBoxOptimize();
+  virtual ~vtkbisfmriToolBoxOptimize();
+  virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+    					  vtkInformationVector *outputVector);
+  //virtual void transpose(vnl_sparse_matrix<float>  & A, vnl_sparse_matrix<float> & A_transpose) ;
+  // Execute Function -- main function
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+
+private:
+	vtkbisfmriToolBoxOptimize(const vtkbisfmriToolBoxOptimize& src) {};
+	vtkbisfmriToolBoxOptimize& operator=(const vtkbisfmriToolBoxOptimize& rhs) {};
+	vtkImageData* FunctionalImage;
+	vtkImageData* roiMap;
+	vtkImageData* OutData2;
+	float Threshold;
+	//BTX
+	std::string Filename;
+	std::string Filename2;
+	std::string Filename3;
+	//ETX
+};
+
+#endif /* vtkbisfmriToolBoxOptimize_H_ */
+
diff --git a/bioimagesuite30_src/DemonsRegistration/CMakeLists.txt b/bioimagesuite30_src/DemonsRegistration/CMakeLists.txt
new file mode 100644
index 0000000..0d6154c
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/CMakeLists.txt
@@ -0,0 +1,175 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+SET(KITBASE DemonsRegistration)
+SET(KIT vtkpx${KITBASE})
+
+SET(KIT vtkjws${KITBASE})
+
+INCLUDE_DIRECTORIES(${ITK_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/${KITBASE})
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/numerics)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/Segmentation)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/Registration)
+
+
+# -------------------- Add Files Here --------------------
+SET (SYMMETRIC 1)
+
+IF(${SYMMETRIC})
+  SET (KITSRCS
+    vtkjwsSymmetricDemonsRegistration.cpp
+    OtherFunctions.cxx
+    #DeformableRegistration.cxx 
+    #itkjwsDemonsRegistrationFilter.txx  
+    #itkjwsDemonsRegistrationFunction.txx
+    itkjwsPDEDeformableRegistrationFilter.txx
+    itkjwsDenseFiniteDifferenceImageFilter.txx
+    itkjwsSymmetricForcesDemonsRegistrationFilter.txx
+    itkjwsSymmetricForcesDemonsRegistrationFunction.txx
+    )
+  
+ELSE (${SYMMETRIC})
+  SET (KITSRCS
+    vtkjwsDemonsRegistration.cpp
+    OtherFunctions.cxx
+    DeformableRegistration.cxx 
+    itkjwsDemonsRegistrationFilter.txx  
+    itkjwsDemonsRegistrationFunction.txx
+    itkjwsPDEDeformableRegistrationFilter.txx
+    itkjwsDenseFiniteDifferenceImageFilter.txx
+    itkjwsSymmetricForcesDemonsRegistrationFilter.txx
+    itkjwsSymmetricForcesDemonsRegistrationFunction.txx
+    )
+ENDIF (${SYMMETRIC})
+
+
+SET_SOURCE_FILES_PROPERTIES(
+OtherFunctions.cxx
+DeformableRegistration.cxx 
+itkjwsDemonsRegistrationFilter.txx  
+itkjwsDemonsRegistrationFunction.txx
+itkjwsPDEDeformableRegistrationFilter.txx
+itkjwsDenseFiniteDifferenceImageFilter.txx
+itkjwsSymmetricForcesDemonsRegistrationFilter.txx
+itkjwsSymmetricForcesDemonsRegistrationFunction.txx
+WRAP_EXCLUDE
+)
+
+
+
+SET(KITLIBS
+  vtkpxCommon
+  vtkpxCommonTCL
+  numerics
+  vtkpxRegistration
+  vtkpxRegistrationTCL
+  vtkpxSegmentation
+  vtkpxSegmentationTCL
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+)
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+SET (KITEXTRAFILES
+DemonsRegistration/wook.h
+DemonsRegistration/jwsNewMain.cxx
+DemonsRegistration/jwsSymmetricNewMain.cxx
+DemonsRegistration/jwsReadWriteImages.cpp
+DemonsRegistration/jwsReadWriteImages.h
+DemonsRegistration/jwsReadWriteImagesTest.cpp
+DemonsRegistration/jwsForRewritingPreprocess.cpp
+DemonsRegistration/DeformableRegistration.cxx 
+DemonsRegistration/itkjwsDemonsRegistrationFilter.txx  
+DemonsRegistration/itkjwsDemonsRegistrationFunction.txx
+DemonsRegistration/itkjwsPDEDeformableRegistrationFilter.txx
+DemonsRegistration/itkjwsDenseFiniteDifferenceImageFilter.txx
+DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFilter.txx
+DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFunction.txx
+DemonsRegistration/itkBinaryMorphologicalClosingImageFilter.txx
+DemonsRegistration/itkjwsDemonsRegistrationFilter.h  
+DemonsRegistration/itkjwsDemonsRegistrationFunction.h
+DemonsRegistration/itkjwsPDEDeformableRegistrationFilter.h
+DemonsRegistration/itkjwsDenseFiniteDifferenceImageFilter.h
+DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFilter.h
+DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFunction.h
+DemonsRegistration/itkBinaryMorphologicalClosingImageFilter.h
+DemonsRegistration/itkjwsMultiResolutionPDEDeformableRegistration.h    
+DemonsRegistration/itkjwsPDEDeformableRegistrationFilter.txx
+DemonsRegistration/itkjwsMultiResolutionPDEDeformableRegistration.txx  
+DemonsRegistration/itkjwsPDEDeformableRegistrationFunction.h
+DemonsRegistration/itkjwsPDEDeformableRegistrationFilter.h
+DemonsRegistration/firstExtendedDemon.h
+DemonsRegistration/secondExtendedDemon.h
+DemonsRegistration/thirdDemon.h
+DemonsRegistration/firstExtendedSymmetricDemon.h
+DemonsRegistration/secondExtendedSymmetricDemon.h
+DemonsRegistration/thirdSymmetricDemon.h
+)
+
+SET (KITTCLSRCS )
+bis_complex("DemonsRegistration" ${KIT} ${FILELIST})
+
+ADD_EXECUTABLE(SerialEDemon_intensity 
+	jwsNewMain.cxx
+	jwsReadWriteImages.cpp
+	jwsReadWriteImagesTest.cpp
+	jwsForRewritingPreprocess.cpp
+	OtherFunctions.cxx
+	DeformableRegistration.cxx 
+	itkjwsDemonsRegistrationFilter.txx  
+	itkjwsDemonsRegistrationFunction.txx
+	itkjwsPDEDeformableRegistrationFilter.txx
+	itkjwsDenseFiniteDifferenceImageFilter.txx
+) 
+TARGET_LINK_LIBRARIES(SerialEDemon_intensity ITKNumerics ITKIO ITKStatistics)
+
+
+ADD_EXECUTABLE(SerialSymmetricEDemon_intensity 
+	jwsSymmetricNewMain.cxx
+	jwsReadWriteImages.cpp
+	jwsReadWriteImagesTest.cpp
+	jwsForRewritingPreprocess.cpp
+	OtherFunctions.cxx
+#	DeformableRegistration.cxx 
+#	itkjwsDemonsRegistrationFilter.txx  
+#	itkjwsDemonsRegistrationFunction.txx
+	itkjwsPDEDeformableRegistrationFilter.txx
+	itkjwsDenseFiniteDifferenceImageFilter.txx
+	itkjwsSymmetricForcesDemonsRegistrationFilter.txx
+	itkjwsSymmetricForcesDemonsRegistrationFunction.txx
+) 
+TARGET_LINK_LIBRARIES(SerialSymmetricEDemon_intensity ITKNumerics ITKIO ITKStatistics)
+
+
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/DeformableRegistration.cxx b/bioimagesuite30_src/DemonsRegistration/DeformableRegistration.cxx
new file mode 100644
index 0000000..b02b8cc
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/DeformableRegistration.cxx
@@ -0,0 +1,613 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "wook.h"
+#include "tnt/tnt_array3d.h"
+#include <math.h>
+
+using namespace jws_demons;
+
+int stop_by_wook = 0;
+
+//#define GET_NUMBER_OF_THREADS
+#define GET_INFORMATION_ON_ITERATION
+
+//#define SET_SMALL_NUMBER_THREADS
+//#define FORCED_UPDATE
+extern void testDMapImageToFile(TNT::Array3D<float> &DMap, int sizeX, int sizeY, int sizeZ,  FixedImageType::ConstPointer fxImage);
+extern void testDfieldImageToFile(TNT::Array3D<VectorPixelType> &DField, int sizeX, int sizeY, int sizeZ,  DeformationFieldType::Pointer DImage);
+
+namespace SECOND_EDEMON{
+template <typename TRegistration>
+class RegistrationInterfaceCommand : public itk::Command
+{
+
+public:
+  typedef  RegistrationInterfaceCommand   Self;
+  typedef  itk::Command                   Superclass;
+  typedef  itk::SmartPointer<Self>        Pointer;
+  itkNewMacro( Self );
+protected:
+  RegistrationInterfaceCommand() {};
+
+public:
+  typedef   TRegistration                              RegistrationType;
+  typedef   RegistrationType *                         RegistrationPointer;
+
+  typedef itk::Vector< float, Dimension >    VectorPixelType;
+  typedef itk::Image< float, Dimension > InternalImageType;
+  typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+  typedef itk::jwsDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+  
+  void Execute(itk::Object * object, const itk::EventObject & event)
+  {
+
+    if( !(itk::IterationEvent().CheckEvent( &event )) )
+      {
+      return;
+      }
+     
+
+    RegistrationPointer registration =
+                            dynamic_cast<RegistrationPointer>( object );
+    // for MultiResolutionPDEDeformableRegistration
+
+
+    RegistrationFilterType * filter = dynamic_cast< RegistrationFilterType * >(
+                       registration->GetRegistrationFilter() );
+       // for Demon Registration algorithm
+    
+
+    std::cout << "level:"<<registration->GetCurrentLevel() <<std::endl;
+                 
+    if ( registration->GetCurrentLevel() == 1 )
+      {
+        std::cout << "*****   level 111111" <<std::endl;
+        std::cout<<"In Multilevel : "  <<  filter->GetElapsedIterations()<< std::endl;
+      }
+     
+  }
+
+
+  void Execute(const itk::Object * , const itk::EventObject & )
+    { return; }
+};
+
+
+
+
+//  The following section of code implements a Command observer
+//  that will monitor the evolution of the registration process.
+//
+  class CommandIterationUpdate : public itk::Command
+  {
+  public:
+    typedef  CommandIterationUpdate   Self;
+    typedef  itk::Command             Superclass;
+    typedef  itk::SmartPointer<CommandIterationUpdate>  Pointer;
+
+    double lPreviousValue;
+    double lCurrentValue ;
+    double lDiff;
+    double lDiff_Diff;
+    double lPrevDiff;
+    int     nContinueCount, nIncreased;
+    FILE *fp;
+
+
+    itkNewMacro( CommandIterationUpdate );
+  protected:
+    CommandIterationUpdate() {};
+
+    typedef itk::Image< float, Dimension > InternalImageType;
+    typedef itk::Vector< float, Dimension >    VectorPixelType;
+    typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+    typedef itk::jwsDemonsRegistrationFilter<
+                                  InternalImageType,
+                                  InternalImageType,
+                                  DeformationFieldType> RegistrationFilterType;
+	
+    typedef itk::ImageRegionIterator< DeformationFieldType > FieldIterator;
+    typedef itk::ImageRegionConstIterator< InternalImageType > DMapIterator;
+	
+    VectorPixelType displacement;
+    DeformationFieldType::IndexType index;
+
+  public:
+
+    void InitFile(void)
+    {
+         fp = fopen("Diff_data.txt","w");
+         nIncreased = 0;
+    }
+
+    void CloseFile(void)
+    {
+        fclose(fp);
+    } 
+        
+  
+    void Execute(itk::Object *caller, const itk::EventObject & event)
+      {
+       // Execute( (const itk::Object *)caller, event);
+#if 1
+           RegistrationFilterType * filter =
+            dynamic_cast< RegistrationFilterType * >( caller );
+
+            unsigned int unElapsedIter;  // by wook
+	   DeformationFieldType::Pointer Dfield;
+	   FixedImageType::ConstPointer fxImage;   // Ohhh  -> ConstPointer for const pointer
+	   
+          if( !(itk::IterationEvent().CheckEvent( &event )) )
+            {
+            return;
+            }
+            
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#if 1       
+	 Dfield = filter->GetDeformationField();
+	 
+	 fxImage =filter->GetFixedImage();
+//	 fxImage =filter->GetMovingImage();
+	 
+	 int dx, dy, dz;
+	 dx = Dfield->GetRequestedRegion().GetSize()[0];
+	 dy = Dfield->GetRequestedRegion().GetSize()[1];
+	 dz = Dfield->GetRequestedRegion().GetSize()[2];
+	 cout << "DeformableRegistration.cxx dx =" <<dx<<" dy="<<dy<<" dz="<<dz<<endl;
+	 
+	 int orgSizeX = dx >> 1;
+	 
+         TNT::Array3D<float> fixedSkinDMap( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<float> fixedBoneDMap( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldSkin( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldBone( orgSizeX, dy, dz, (float)0);
+	 
+	 TNT::Array3D<VectorPixelType> vFieldCombined( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldAdjusted( dx, dy, dz, (float)0);
+	 
+         FieldIterator fi( Dfield,  Dfield->GetRequestedRegion().GetSize() );
+	 DMapIterator DMapIt( fxImage,   fxImage->GetRequestedRegion().GetSize());
+
+  	fi.GoToBegin();   //std::cout <<"test!!!"<<endl;
+	DMapIt.GoToBegin();
+
+	int i,j,k;
+
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < dx; i++){
+			
+		if(i<orgSizeX) {		
+			
+			fixedSkinDMap[i][j][k] =  DMapIt.Get();
+			vFieldSkin[i][j][k] =  fi.Get();
+		
+		}
+		else {
+			fixedBoneDMap[i - orgSizeX][j][k] =  DMapIt.Get();
+			vFieldBone[i - orgSizeX][j][k] =  fi.Get();
+		}
+	    
+             ++fi;  
+	     ++DMapIt;
+
+         }
+         }
+         }		
+
+	
+//	if(dx == 328) {
+//		testDMapImageToFile(fixedSkinDMap, orgSizeX, dy, dz, fxImage);
+//		testDfieldImageToFile(vFieldSkin, orgSizeX, dy, dz, Dfield);
+//        }
+	
+	float abs_skinDMap, abs_boneDMap, abs_sum;
+	abs_skinDMap = 0.0; 	abs_boneDMap = 0.0;	abs_sum = 0.0;
+	
+	float skin_ratio=0.0, bone_ratio=0.0;
+	
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < orgSizeX; i++){
+			
+			if((fixedSkinDMap[i][j][k]<0) && (fixedBoneDMap[i][j][k] <=0)) {  // bone	
+				
+				    vFieldCombined[i][j][k][0] = vFieldBone[i][j][k][0];
+                                    vFieldCombined[i][j][k][1] = vFieldBone[i][j][k][1];
+                                    vFieldCombined[i][j][k][2] = vFieldBone[i][j][k][2];
+				
+			}
+			else if((fixedSkinDMap[i][j][k]>=0) && (fixedBoneDMap[i][j][k] >0)) {  // skin
+				
+				    vFieldCombined[i][j][k][0] = vFieldSkin[i][j][k][0];
+                                    vFieldCombined[i][j][k][1] = vFieldSkin[i][j][k][1];
+                                    vFieldCombined[i][j][k][2] = vFieldSkin[i][j][k][2];				
+				
+			}
+			else if((fixedSkinDMap[i][j][k]<0) && (fixedBoneDMap[i][j][k] >0)){
+				
+				    abs_skinDMap 	= 	fabs(fixedSkinDMap[i][j][k]);
+				    abs_boneDMap 	=	fabs(fixedBoneDMap[i][j][k]);
+				    abs_sum = abs_skinDMap + abs_boneDMap;
+					
+				    skin_ratio = abs_boneDMap / abs_sum;
+				    bone_ratio = abs_skinDMap / abs_sum;
+					
+//cout<<"abs_skin="<<abs_skinDMap <<" abs_bone="<<abs_boneDMap<<" abs_sum="<<abs_sum<<endl;
+				    vFieldCombined[i][j][k][0] = (bone_ratio * vFieldBone[i][j][k][0]) + (skin_ratio * vFieldSkin[i][j][k][0]);
+                                    vFieldCombined[i][j][k][1] =  (bone_ratio * vFieldBone[i][j][k][1]) + (skin_ratio * vFieldSkin[i][j][k][1]);
+                                    vFieldCombined[i][j][k][2] =  (bone_ratio * vFieldBone[i][j][k][2]) + (skin_ratio * vFieldSkin[i][j][k][2]);			
+			}
+			else {  // exceptional cases
+				cout<<"exceptional case at ("<<i<<", "<<j<<", "<<k<<")"<<endl;
+				    vFieldCombined[i][j][k][0] = 0.0;
+                                    vFieldCombined[i][j][k][1] = 0.0;
+                                    vFieldCombined[i][j][k][2] = 0.0;				
+			}
+	}
+	}
+        }
+	
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < orgSizeX; i++){
+	
+		vFieldAdjusted[i][j][k][0] = vFieldCombined[i][j][k][0];
+		vFieldAdjusted[i+orgSizeX][j][k][0] = vFieldCombined[i][j][k][0];
+			
+		vFieldAdjusted[i][j][k][1] = vFieldCombined[i][j][k][1];
+		vFieldAdjusted[i+orgSizeX][j][k][1] = vFieldCombined[i][j][k][1];
+		
+		vFieldAdjusted[i][j][k][2] = vFieldCombined[i][j][k][2];	
+		vFieldAdjusted[i+orgSizeX][j][k][2] = vFieldCombined[i][j][k][2];
+
+         }
+         }
+         }
+	
+
+	fi.GoToBegin(); 
+	
+  	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < dx; i++) {       
+//		displacement = fi.Get();
+//             	std::cout <<"("<<displacement[0]<<","<<displacement[1]<<","<<displacement[2]<<")   : ";
+    		
+		#if 1
+		displacement[0] = vFieldAdjusted[i][j][k][0];
+    		displacement[1] = vFieldAdjusted[i][j][k][1];
+		displacement[2] = vFieldAdjusted[i][j][k][2];
+		#endif
+//		std::cout <<"("<<displacement[0]<<","<<displacement[1]<<","<<displacement[2]<<")"<<std::endl;
+    		fi.Set( displacement );
+    		++fi;
+    	}
+	}
+	}
+
+	 filter->setMyDField(Dfield);
+#endif
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+          unElapsedIter = filter->GetElapsedIterations();
+          lPreviousValue = lCurrentValue;
+          lCurrentValue = filter->GetMetric();
+
+          lPrevDiff = lDiff;
+          lDiff = fabs(lPreviousValue - lCurrentValue);
+          lDiff_Diff = fabs(lPrevDiff - lDiff) *100;
+                   
+          fprintf(fp,"%d %f\n",unElapsedIter,lCurrentValue);
+          
+          
+          if(lDiff < 0.0001) nContinueCount++;    // when input data is signed float (minus value for inside)
+          //if(lDiff < 0.1) nContinueCount++;  // when input data is unsigned short
+          else  nContinueCount = 0;
+
+          #ifdef GET_INFORMATION_ON_ITERATION
+          if(lPreviousValue > lCurrentValue){
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= -"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<<std::endl;
+            nIncreased = 0;                                                                                                              
+          } 
+          else{
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= +"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<< std::endl;
+            nIncreased++;                                                                                                                         
+          } 
+                                                                                                                                                                                                                                
+          if(nContinueCount > 10){
+                nContinueCount = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continuous negligible variations     "<<std::endl;                                
+          }
+
+          if(nIncreased > 20){
+                nIncreased = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continumes metric increasement      "<<std::endl;                              
+          }
+          
+                        
+          #endif
+                                                        
+          #if 0  
+          
+          std::cout << unElapsedIter << " " << filter->GetMetric() << std::endl;
+
+          if(unElapsedIter ==20){ std::cout << "********************************  count!!"<<std::endl;
+              filter->StopRegistration();
+          }
+          #endif
+#endif
+      }
+
+    void Execute(const itk::Object * object, const itk::EventObject & event)
+      {
+	}
+  };
+
+
+#if  1
+void ExtendedDemonRegistrationMain(FixedImageType::Pointer fixedImage, MovingImageType::Pointer movingImage, string &registeredImageName)
+{
+  std::cout <<" start registration!! " <<std::endl;   
+  std::cout <<"1: accept parameter  " <<std::endl;
+		
+#if 0
+  typedef itk::HistogramMatchingImageFilter<                      
+                                    InternalImageType,
+                                    InternalImageType >   MatchingFilterType;
+  MatchingFilterType::Pointer matcher = MatchingFilterType::New();
+
+  std::cout <<"2: set HistogramMatchingImageFilter  " <<std::endl;
+  matcher->SetInput( movingImage );       
+  matcher->SetReferenceImage( fixedImage );
+  matcher->SetNumberOfHistogramLevels( 1024 );
+  matcher->SetNumberOfMatchPoints( 7 );
+  matcher->ThresholdAtMeanIntensityOn();
+
+   #ifdef SET_SMALL_NUMBER_THREADS
+     matcher->SetNumberOfThreads(1);
+   #endif
+
+   #ifdef FORCED_UPDATE
+     matcher->Update();
+   #endif
+
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for HistogramMatchingImageFilter: "<<matcher->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+#endif
+  std::cout <<"6: generate DeformationFieldType format  " <<std::endl;
+
+  typedef itk::jwsDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+
+  std::cout <<"7: set  DemonsRegistrationFilter " <<std::endl;
+  RegistrationFilterType::Pointer filter = RegistrationFilterType::New();
+
+  filter->SetNumberOfIterations( 50 );
+  filter->SetStandardDeviations( 1.0 );
+
+
+     #ifdef SET_SMALL_NUMBER_THREADS
+       filter->SetNumberOfThreads(1);
+     #endif
+
+  
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for DemonsRegistrationFilter: "<<filter->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+  /////////////////////////////////////////////////////////////////////////////
+  std::cout <<"8: set  CommandIterationUpdate " <<std::endl;
+  CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
+  observer->InitFile();
+
+  std::cout <<"9: filter->AddObserver " <<std::endl;
+  filter->AddObserver( itk::IterationEvent(), observer );
+
+     
+  /////////////////////////////////////////////////////////////////////////////
+
+  typedef itk::jwsMultiResolutionPDEDeformableRegistration<
+                                InternalImageType,
+                                InternalImageType,
+                                DeformationFieldType >   MultiResRegistrationFilterType;
+
+  std::cout <<"10: set MultiResolutionPDEDeformableRegistration " <<std::endl;
+  MultiResRegistrationFilterType::Pointer multires = MultiResRegistrationFilterType::New();
+  multires->SetRegistrationFilter( filter );
+  
+  int numberOfLevels = 3;
+//  unsigned int nIterations[3] = { 10,10,3 };     // for test
+unsigned int nIterations[3] = { 500,500,100 };     // for test
+ 
+  multires->SetNumberOfLevels( numberOfLevels ); 
+  multires->SetFixedImage( fixedImage );
+  //multires->SetMovingImage( matcher->GetOutput() );   // turn off the histogram matching for distance mapping demon
+                                                                               // by wook 02/28/08
+  multires->SetMovingImage( movingImage );
+
+  #ifdef SET_SMALL_NUMBER_THREADS
+    multires->SetNumberOfThreads(1);
+  #endif
+ 
+  multires->SetNumberOfIterations( nIterations );  
+
+
+   /******************  by wook    ***************************/
+   std::cout <<"11: set multires->AddObserver " <<std::endl;
+   typedef RegistrationInterfaceCommand<MultiResRegistrationFilterType> CommandType;
+   CommandType::Pointer command = CommandType::New();
+   multires->AddObserver( itk::IterationEvent(), command );
+//   multires->Update();
+   /*****************************************************************/
+
+
+ #ifdef FORCED_UPDATE
+   multires->Update();
+ #endif
+
+
+#ifdef GET_NUMBER_OF_THREADS
+
+  std::cout <<" Number of Threads for MultiResolutionPDEDeformableRegistration: "<<multires->GetNumberOfThreads() << std::endl;
+
+#endif
+                
+
+  std::cout <<"12: WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  typedef itk::LinearInterpolateImageFunction<
+                                   MovingImageType,
+                                   double          >  InterpolatorType;
+  WarperType::Pointer warper = WarperType::New();
+  InterpolatorType::Pointer interpolator = InterpolatorType::New();
+//  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
+
+  std::cout <<"13: initialize WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  warper->SetInput( movingImage );
+  warper->SetInterpolator( interpolator );
+
+
+  warper->SetOutputSpacing( fixedImage->GetSpacing() );
+  warper->SetOutputOrigin( fixedImage->GetOrigin() );
+  warper->SetDeformationField( multires->GetOutput() );
+
+  // by wook to set the large value as outside pixel value
+  warper->SetEdgePaddingValue(65535L);
+
+ #ifdef SET_SMALL_NUMBER_THREADS
+   warper->SetNumberOfThreads(1);
+ #endif
+
+   //#ifdef FORCED_UPDATE
+     warper->Update();
+     std::cout<< "warper spacing:" <<warper->GetOutput()->GetSpacing()    <<"warper origin:"<<warper->GetOutput()->GetOrigin() <<std::endl;
+     std::cout<< "warper size:" <<warper->GetOutput()->GetRequestedRegion().GetSize()    <<std::endl; 
+   //#endif
+
+      
+  
+ #ifdef GET_NUMBER_OF_THREADS
+
+   std::cout <<" Number of Threads for WarpImageFilter: "<<warper->GetNumberOfThreads() << std::endl;
+                                 
+ #endif
+                                                                                                                                              
+  // Write warped image out to file
+  //typedef unsigned short  OutputPixelType;
+  typedef float  OutputPixelType;
+  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
+  typedef itk::CastImageFilter< 
+                        MovingImageType,
+                        OutputImageType > CastFilterType;
+  typedef itk::ImageFileWriter< OutputImageType >  WriterType;
+
+  std::cout <<"14: set writer->Update();" <<std::endl;
+  WriterType::Pointer      writer =  WriterType::New();
+  CastFilterType::Pointer  caster =  CastFilterType::New();
+
+  string boneRegisteredImageFileName = registeredImageName + "Bone";
+  string skinRegisteredImageFileName = registeredImageName + "Skin";
+		
+  string boneRegisteredFileNamewithExtension =boneRegisteredImageFileName + ".vtk";
+  writer->SetFileName( boneRegisteredFileNamewithExtension );
+  
+  caster->SetInput( warper->GetOutput() );
+  writer->SetInput( caster->GetOutput() );
+
+  #ifdef SET_SMALL_NUMBER_THREADS
+    writer->SetNumberOfThreads(1);
+  #endif
+
+  
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for ImageFileWriter: "<<writer->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+  
+  
+  std::cout <<"15: writer->Update();" <<std::endl;
+  writer->Update();
+
+  std::cout <<"16: observer->CloseFile()" <<std::endl;
+  observer->CloseFile();  // by wook
+
+
+    std::cout <<"17: set fieldWriter->Update()" <<std::endl;
+    FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
+
+    string deformationFieldFileNamewithExtension = registeredImageName + "_DField.vtk";
+    fieldWriter->SetFileName( deformationFieldFileNamewithExtension );
+    fieldWriter->SetInput( multires->GetOutput() );
+
+
+    #ifdef SET_SMALL_NUMBER_THREADS
+      fieldWriter->SetNumberOfThreads(1);
+    #endif
+
+      // #ifdef FORCED_UPDATE
+      //   fieldWrite->Update();
+      // #endif
+    
+    #ifdef GET_NUMBER_OF_THREADS
+
+      std::cout <<" Number of Threads for ImageFileWriter: "<<fieldWriter->GetNumberOfThreads() << std::endl;
+                                    
+    #endif
+    
+
+    
+    std::cout <<"18: fieldWriter->Update()" <<std::endl;
+
+    try
+      {
+      fieldWriter->Update();
+      }
+    catch ( itk::ExceptionObject e )
+      {
+      e.Print( std::cerr );
+      }
+  
+//  return 0;
+}
+}   //   namespace SECOND_EDEMON
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/OtherFunctions.cxx b/bioimagesuite30_src/DemonsRegistration/OtherFunctions.cxx
new file mode 100644
index 0000000..81945d3
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/OtherFunctions.cxx
@@ -0,0 +1,358 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include <string.h>
+#include "wook.h"
+#include "tnt/tnt_array3d.h"
+
+namespace jws_demons {
+
+void testImageToFile2(OutputImageType::Pointer outImage)
+{
+	string fileName = "testImage2.vtk";
+	
+	WriterType::Pointer writer = WriterType::New();
+	writer->SetFileName( fileName );
+	writer->SetInput( outImage );
+	writer->Update();
+}
+
+void testFloatImageToFile(InternalImageType::Pointer outImage, string fileName)
+{
+	cout << "Combined image saved : "<<fileName ;
+	//string fileName = "testFloatImage.vtk";
+	
+	typedef itk::ImageFileWriter< InternalImageType >   FloatWriterType;
+	FloatWriterType::Pointer writer = FloatWriterType::New();
+	writer->SetFileName( fileName );
+	writer->SetInput( outImage );
+	writer->Update();
+	cout <<" :File Save Done !!"<<endl;
+}
+
+
+void DistanceMapGeneration(string dmapName, OutputImageType::Pointer image, FixedImageType::Pointer outDMapImage, InputImageType::RegionType inputRegion)
+{
+	
+  // testImageToFile2(image);
+  /////// generate Signed Distance Map  ////////////////
+  cout<<"	Generate Signed Distance Map ..."<<endl;	
+  DMapFilterType::Pointer DMapfilter = DMapFilterType::New();
+  
+  //string inputFileName = argv;
+  //cout<<" input string name ="<< inputFileName<<endl;
+  //string DMapFileName = inputFileName + "_DMap.vtk";
+ 
+  
+  DMapfilter->SetInput( image );
+  DMapfilter->Update();
+
+     ///////////////////// save the mrphologyBImage   /////////////////////////////////////
+ InternalIteratorType  inputIt( DMapfilter->GetOutput(), inputRegion );
+ InternalIteratorType  outputIt( outDMapImage, inputRegion );
+ 
+ inputIt.GoToBegin();
+ outputIt.GoToBegin();
+ 
+ while( (!inputIt.IsAtEnd())&&(!outputIt.IsAtEnd()) )
+    {                       
+	outputIt.Set(inputIt.Get());
+                                             
+	++inputIt;
+	++outputIt;
+    
+    }   
+   /////////////////////////////////////////////////////////////////////////////////////
+
+ if (dmapName.length()>0)
+   {
+     string DMapFileName = dmapName + "_DMap.vtk";	 
+     FloatWriterType::Pointer floatWriter = FloatWriterType::New();
+     floatWriter->SetFileName( DMapFileName );
+     floatWriter->SetInput( DMapfilter->GetOutput() );
+     floatWriter->Update();
+   }
+}
+
+
+void testGrayImageToFile(GrayImageType::Pointer outImage, string InputFileName)
+{
+	string fileName = InputFileName + ".vtk";
+	
+	GrayWriterType::Pointer writer = GrayWriterType::New();
+	writer->SetFileName( fileName );
+	writer->SetInput( outImage );
+	writer->Update();
+}
+
+void myWarperGray(GrayImageType::Pointer inputImg,  GrayImageType::Pointer deformedImg, DeformationFieldType::Pointer DField, string fileName )
+{
+
+  GrayWarperType::Pointer filter = GrayWarperType::New();
+
+  typedef itk::LinearInterpolateImageFunction< 
+                       GrayImageType, double >  InterpolatorType;
+
+  InterpolatorType::Pointer interpolator = InterpolatorType::New();
+
+  filter->SetInterpolator( interpolator );
+  filter->SetOutputSpacing( DField->GetSpacing() );
+  filter->SetOutputOrigin(  DField->GetOrigin() );
+
+  filter->SetDeformationField( DField );
+  filter->SetInput( inputImg );
+  filter->Update();
+  
+  IteratorGrayType fi( filter->GetOutput() , inputImg->GetRequestedRegion().GetSize() );
+  //InternalIteratorType fi( inputImg , inputImg->GetRequestedRegion().GetSize() );
+  IteratorGrayType outIt( deformedImg, deformedImg->GetRequestedRegion().GetSize() );
+  fi.GoToBegin();
+  outIt.GoToBegin();
+	
+  //cout << "myWarper() : 1" <<endl;
+  
+  GrayPixelType t=0;
+   while( (!fi.IsAtEnd())&&(!outIt.IsAtEnd()) ){
+		t = fi.Get();     //cout << "2 " <<endl;
+    		outIt.Set(  t );  // cout << "3 " <<endl;
+    		++fi;
+		++outIt;
+    	}
+
+   int sizeX, sizeY, sizeZ;
+   sizeX = deformedImg->GetRequestedRegion().GetSize()[0];
+   sizeY = deformedImg->GetRequestedRegion().GetSize()[1];
+   sizeZ = deformedImg->GetRequestedRegion().GetSize()[2];
+   
+   cout<<"Deformed sizeX="<<sizeX<<" sizeY="<<sizeY <<" sizeZ="<<sizeZ<<endl;
+   
+   //testGrayImageToFile(filter->GetOutput(), fileName);
+
+}
+
+void myWarper(InternalImageType::Pointer inputImg,  InternalImageType::Pointer deformedImg, DeformationFieldType::Pointer DField )
+{
+
+  //cout << "myWarper()" <<endl;
+	
+  //DeformationFieldType::ConstPointer deformationField = fieldReader->GetOutput();
+  typedef itk::WarpImageFilter< InternalImageType, 
+                               InternalImageType, 
+                                DeformationFieldType  >  FilterType;
+
+  FilterType::Pointer filter = FilterType::New();
+	
+     
+     ////////////////////////////////// First Extended Demon with only Bone Distance Map   ///////////////////////////////////////////////
+
+  typedef itk::LinearInterpolateImageFunction< 
+                       InternalImageType, double >  InterpolatorType;
+
+  InterpolatorType::Pointer interpolator = InterpolatorType::New();
+
+  filter->SetInterpolator( interpolator );
+  filter->SetOutputSpacing( DField->GetSpacing() );
+  filter->SetOutputOrigin(  DField->GetOrigin() );
+
+  filter->SetDeformationField( DField );
+  filter->SetInput( inputImg );
+  filter->Update();
+  
+  InternalIteratorType fi( filter->GetOutput() , inputImg->GetRequestedRegion().GetSize() );
+  //InternalIteratorType fi( inputImg , inputImg->GetRequestedRegion().GetSize() );
+  InternalIteratorType outIt( deformedImg, deformedImg->GetRequestedRegion().GetSize() );
+  fi.GoToBegin();
+  outIt.GoToBegin();
+	
+  //cout << "myWarper() : 1" <<endl;
+  
+  float t=0;
+   while( (!fi.IsAtEnd())&&(!outIt.IsAtEnd()) ){
+		t = fi.Get();     //cout << "2 " <<endl;
+    		outIt.Set(  t );  // cout << "3 " <<endl;
+    		++fi;
+		++outIt;
+    	}
+
+   int sizeX, sizeY, sizeZ;
+   sizeX = deformedImg->GetRequestedRegion().GetSize()[0];
+   sizeY = deformedImg->GetRequestedRegion().GetSize()[1];
+   sizeZ = deformedImg->GetRequestedRegion().GetSize()[2];
+   
+   cout<<"Deformed sizeX="<<sizeX<<" sizeY="<<sizeY <<" sizeZ="<<sizeZ<<endl;
+    string boneOnlyRegistrationResult = "FirstRegResultHalf";
+   //testDeformedImageToFile(deformedImg);
+   //testDfieldToFile(DField);
+}
+
+void myWarperUShort(InputImageType::Pointer inputImg,  InputImageType::Pointer deformedImg, DeformationFieldType::Pointer DField )
+{
+
+  //cout << "myWarper()" <<endl;
+	
+  //DeformationFieldType::ConstPointer deformationField = fieldReader->GetOutput();
+	
+  //testImageToFile(inputImg);	
+  typedef itk::WarpImageFilter< InputImageType, 
+                               InputImageType, 
+                                DeformationFieldType  >  FilterType;
+
+  FilterType::Pointer filter = FilterType::New();
+
+  typedef itk::LinearInterpolateImageFunction< 
+                       InputImageType, double >  InterpolatorType;
+
+  InterpolatorType::Pointer interpolator = InterpolatorType::New();
+
+  filter->SetInterpolator( interpolator );
+  filter->SetOutputSpacing( DField->GetSpacing() );
+  filter->SetOutputOrigin(  DField->GetOrigin() );
+
+  filter->SetDeformationField( DField );
+  filter->SetInput( inputImg );
+  filter->Update();
+  
+  IteratorType fi( filter->GetOutput() , inputImg->GetRequestedRegion().GetSize() );
+  IteratorType outIt( deformedImg, deformedImg->GetRequestedRegion().GetSize() );
+  fi.GoToBegin();
+  outIt.GoToBegin();
+	
+  //cout << "myWarper() : 1" <<endl;
+  
+  unsigned short t=0;
+   while( (!fi.IsAtEnd())&&(!outIt.IsAtEnd()) ){
+		t = fi.Get();     //cout << "2 " <<endl;
+    		outIt.Set(  t );  // cout << "3 " <<endl;
+    		++fi;
+		++outIt;
+    	}
+
+   int sizeX, sizeY, sizeZ;
+   sizeX = deformedImg->GetRequestedRegion().GetSize()[0];
+   sizeY = deformedImg->GetRequestedRegion().GetSize()[1];
+   sizeZ = deformedImg->GetRequestedRegion().GetSize()[2];
+   
+   cout<<"Deformed sizeX="<<sizeX<<" sizeY="<<sizeY <<" sizeZ="<<sizeZ<<endl;
+   
+   //testImageToFile(deformedImg);
+   //testDeformedImageToFile(deformedImg);
+   //testDfieldToFile(DField);
+}
+
+void mergeImages(InternalImageType::Pointer Image1, InternalImageType::Pointer Image2, InternalImageType::Pointer CombinedImage, string fileName)
+{
+	InternalImageType::RegionType::SizeType  inputImage1size;
+	InternalImageType::RegionType::SizeType  inputImage2size;
+	inputImage1size =  Image1->GetRequestedRegion().GetSize();
+	inputImage2size =  Image2->GetRequestedRegion().GetSize();
+	
+	int sizeX, sizeY, sizeZ;
+	sizeX =inputImage1size[0];     sizeY = inputImage1size[1];    sizeZ = inputImage1size[2];
+	cout<<"sizeX="<< sizeX<<" sizeY="<<sizeY<<" sizeZ="<<sizeZ<<endl;	
+	
+	int newSizeX = sizeX * 2;
+	
+	InternalImageType::RegionType::SizeType  combinedImageSize;
+	combinedImageSize[0] = newSizeX;
+	combinedImageSize[1] = sizeY;
+	combinedImageSize[2] = sizeZ;
+	cout<<"NewImage sizeX="<< combinedImageSize[0]<<" sizeY="<<combinedImageSize[1]<<" sizeZ="<<combinedImageSize[2]<<endl;	
+	// I decided to connect the two images in x-direction only because of visualization reason.
+	// by wook 08/02/27
+	TNT::Array3D<float> Voxel1(sizeX, sizeY, sizeZ, (float)0);
+	TNT::Array3D<float> Voxel2(sizeX, sizeY, sizeZ, (float)0);
+	TNT::Array3D<float> newVoxel(newSizeX, sizeY, sizeZ, (float)0);
+	
+	InternalIteratorType  It1( Image1, inputImage1size );
+	InternalIteratorType  It2( Image2, inputImage2size );
+
+	
+	int i,j,k;
+
+	for(k=0; k < sizeZ; k++){
+	for(j=0; j < sizeY; j++){
+        for(i=0; i < sizeX; i++){
+			
+             Voxel1[i][j][k] =  It1.Get();
+	     Voxel2[i][j][k] =  It2.Get();
+             ++It1;  
+	     ++It2;
+
+         }
+         }
+         }	
+	
+	for(k=0; k < sizeZ; k++){
+	for(j=0; j < sizeY; j++){
+        for(i=0; i <newSizeX; i++){
+
+		if(i<sizeX)      newVoxel[i][j][k] = Voxel1[i][j][k];
+		else                newVoxel[i][j][k] = Voxel2[ i - sizeX ][j][k];
+
+         }
+         }
+         }	
+	
+	InternalImageType::RegionType region; 
+	InternalImageType::RegionType::IndexType indexStart;
+	indexStart[0]=0;   indexStart[1]=0;  indexStart[2]=0;
+	region.SetSize( combinedImageSize );
+	region.SetIndex( indexStart ); 		
+	
+	CombinedImage->SetRegions( region );
+	CombinedImage->SetOrigin(  Image1->GetOrigin() );
+	CombinedImage->SetSpacing(  Image1->GetSpacing() );
+	CombinedImage->Allocate();
+	
+	InternalIteratorType  OutIt( CombinedImage, combinedImageSize );
+	
+#if 1
+	for(k=0; k < sizeZ; k++){
+	for(j=0; j < sizeY; j++){
+        for(i=0; i <newSizeX; i++){
+
+			OutIt.Set(  newVoxel[i][j][k] );
+			++OutIt;
+         }
+         }
+         }	
+	
+	//testFloatImageToFile(CombinedImage, fileName);
+#endif	
+}
+
+void DfieldToFile(DeformationFieldType::Pointer DImage, string fileName)
+{
+	FieldWriterType::Pointer fieldwriter = FieldWriterType::New();
+
+	string outFile = fileName +"_DField.vtk";
+	fieldwriter->SetFileName( outFile );
+	fieldwriter->SetInput(  DImage  );
+	fieldwriter->Update();
+}
+}
+
diff --git a/bioimagesuite30_src/DemonsRegistration/OtherFunctions.h b/bioimagesuite30_src/DemonsRegistration/OtherFunctions.h
new file mode 100644
index 0000000..edb0c23
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/OtherFunctions.h
@@ -0,0 +1,46 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef __WOOKOTHER_H__
+#define  __WOOKOTHER_H__
+
+
+#include "wook.h"
+
+namespace jws_demons {
+
+
+ void DistanceMapGeneration(string dmapName, OutputImageType::Pointer image, FixedImageType::Pointer outDMapImage, InputImageType::RegionType inputRegion);
+ void myWarper(InternalImageType::Pointer inputImg,  InternalImageType::Pointer deformedImg, DeformationFieldType::Pointer DField );
+ void myWarperUShort(InputImageType::Pointer inputImg,  InputImageType::Pointer deformedImg, DeformationFieldType::Pointer DField );
+ void myWarperGray(GrayImageType::Pointer inputImg,  GrayImageType::Pointer deformedImg, DeformationFieldType::Pointer DField, string fileName );
+ void mergeImages(InternalImageType::Pointer Image1, InternalImageType::Pointer Image2, InternalImageType::Pointer CombinedImage, string fileName);
+ void DfieldToFile(DeformationFieldType::Pointer DImage, string fileName);
+}
+
+#endif
+
diff --git a/bioimagesuite30_src/DemonsRegistration/firstExtendedDemon.h b/bioimagesuite30_src/DemonsRegistration/firstExtendedDemon.h
new file mode 100644
index 0000000..ffb40ce
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/firstExtendedDemon.h
@@ -0,0 +1,391 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+//#define GET_NUMBER_OF_THREADS
+//#define GET_INFORMATION_ON_ITERATION
+
+//#define SET_SMALL_NUMBER_THREADS
+//#define FORCED_UPDATE
+
+
+namespace FIRST_EDEMON{
+
+
+template <typename TRegistration>
+class RegistrationInterfaceCommand : public itk::Command
+{
+
+public:
+  typedef  RegistrationInterfaceCommand   Self;
+  typedef  itk::Command                   Superclass;
+  typedef  itk::SmartPointer<Self>        Pointer;
+  itkNewMacro( Self );
+protected:
+  RegistrationInterfaceCommand() {};
+
+public:
+  typedef   TRegistration                              RegistrationType;
+  typedef   RegistrationType *                         RegistrationPointer;
+
+  typedef itk::Vector< float, Dimension >    VectorPixelType;
+  typedef itk::Image< float, Dimension > InternalImageType;
+  typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+  typedef itk::jwsDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+  
+  void Execute(itk::Object * object, const itk::EventObject & event)
+  {
+
+    if( !(itk::IterationEvent().CheckEvent( &event )) )
+      {
+      return;
+      }
+     
+
+    RegistrationPointer registration =
+                            dynamic_cast<RegistrationPointer>( object );
+    // for MultiResolutionPDEDeformableRegistration
+
+
+    RegistrationFilterType * filter = dynamic_cast< RegistrationFilterType * >(
+                       registration->GetRegistrationFilter() );
+       // for Demon Registration algorithm
+    
+
+    std::cout << "level:"<<registration->GetCurrentLevel() <<std::endl;
+                 
+    if ( registration->GetCurrentLevel() == 1 )
+      {
+        std::cout << "*****   level 111111" <<std::endl;
+        std::cout<<"In Multilevel : "  <<  filter->GetElapsedIterations()<< std::endl;
+      }
+     
+  }
+
+
+  void Execute(const itk::Object * , const itk::EventObject & )
+    { return; }
+};
+
+
+
+
+//  The following section of code implements a Command observer
+//  that will monitor the evolution of the registration process.
+//
+  class CommandIterationUpdate : public itk::Command
+  {
+  public:
+    typedef  CommandIterationUpdate   Self;
+    typedef  itk::Command             Superclass;
+    typedef  itk::SmartPointer<CommandIterationUpdate>  Pointer;
+
+    double lPreviousValue;
+    double lCurrentValue ;
+    double lDiff;
+    double lDiff_Diff;
+    double lPrevDiff;
+    int     nContinueCount, nIncreased;
+    FILE *fp;
+
+
+    itkNewMacro( CommandIterationUpdate );
+  protected:
+    CommandIterationUpdate() {};
+
+    typedef itk::Image< float, Dimension > InternalImageType;
+    typedef itk::Vector< float, Dimension >    VectorPixelType;
+    typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+    typedef itk::jwsDemonsRegistrationFilter<
+                                  InternalImageType,
+                                  InternalImageType,
+                                  DeformationFieldType> RegistrationFilterType;
+
+    typedef itk::ImageRegionIterator< DeformationFieldType > FieldIterator;
+    typedef itk::ImageRegionConstIterator< InternalImageType > DMapIterator;
+	
+    VectorPixelType displacement;
+    DeformationFieldType::IndexType index;
+
+  public:
+
+    void InitFile(void)
+    {
+         //fp = fopen("Diff_data.txt","w");
+         nIncreased = 0;
+    }
+
+    void CloseFile(void)
+    {
+        //fclose(fp);
+    } 
+        
+  
+    void Execute(itk::Object *caller, const itk::EventObject & event)
+      {
+       // Execute( (const itk::Object *)caller, event);
+#if 1
+           RegistrationFilterType * filter =
+            dynamic_cast< RegistrationFilterType * >( caller );
+
+            unsigned int unElapsedIter;  // by wook
+	   DeformationFieldType::Pointer Dfield;
+	   FixedImageType::ConstPointer fxImage;   // Ohhh  -> ConstPointer for const pointer
+	   
+          if( !(itk::IterationEvent().CheckEvent( &event )) )
+            {
+            return;
+            }
+            
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		  cout << "firstExtendedDemon.cxx " <<endl;
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+          unElapsedIter = filter->GetElapsedIterations();
+          lPreviousValue = lCurrentValue;
+          lCurrentValue = filter->GetMetric();
+
+          lPrevDiff = lDiff;
+          lDiff = fabs(lPreviousValue - lCurrentValue);
+          lDiff_Diff = fabs(lPrevDiff - lDiff) *100;
+                   
+          //fprintf(fp,"%d %f\n",unElapsedIter,lCurrentValue);
+          
+          
+          if(lDiff < 0.0001) nContinueCount++;    // when input data is signed float (minus value for inside)
+          //if(lDiff < 0.1) nContinueCount++;  // when input data is unsigned short
+          else  nContinueCount = 0;
+
+          #ifdef GET_INFORMATION_ON_ITERATION
+          if(lPreviousValue > lCurrentValue){
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= -"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<<std::endl;
+            nIncreased = 0;                                                                                                              
+          } 
+          else{
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= +"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<< std::endl;
+            nIncreased++;                                                                                                                         
+          } 
+                                                                                                                                                                                                                                
+          if(nContinueCount > 10){
+                nContinueCount = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continuous negligible variations     "<<std::endl;                                
+          }
+
+          if(nIncreased > 20){
+                nIncreased = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continumes metric increasement      "<<std::endl;                              
+          }
+          
+                        
+          #endif
+                                                        
+          #if 0  
+          
+          std::cout << unElapsedIter << " " << filter->GetMetric() << std::endl;
+
+          if(unElapsedIter ==20){ std::cout << "********************************  count!!"<<std::endl;
+              filter->StopRegistration();
+          }
+          #endif
+#endif
+      }
+
+    void Execute(const itk::Object * object, const itk::EventObject & event)
+      {
+	}
+  };
+
+
+#if  1
+void firstExtendedDemonRegistration(FixedImageType::Pointer fixedImage, MovingImageType::Pointer movingImage, DeformationFieldType::Pointer resultingDField, string registeredImageName)
+{
+  std::cout <<" start first extended demon registration " <<std::endl;   
+
+  typedef itk::jwsDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+
+  std::cout <<"7: set  DemonsRegistrationFilter " <<std::endl;
+  RegistrationFilterType::Pointer filter = RegistrationFilterType::New();
+
+  filter->SetNumberOfIterations( 50 );
+  filter->SetStandardDeviations( 1.0 );
+
+
+     #ifdef SET_SMALL_NUMBER_THREADS
+       filter->SetNumberOfThreads(1);
+     #endif
+
+  
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for DemonsRegistrationFilter: "<<filter->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+  /////////////////////////////////////////////////////////////////////////////
+  std::cout <<"8: set  CommandIterationUpdate " <<std::endl;
+  CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
+  observer->InitFile();
+
+  std::cout <<"9: filter->AddObserver " <<std::endl;
+  filter->AddObserver( itk::IterationEvent(), observer );
+
+     
+  /////////////////////////////////////////////////////////////////////////////
+
+  typedef itk::jwsMultiResolutionPDEDeformableRegistration<
+                                InternalImageType,
+                                InternalImageType,
+                                DeformationFieldType >   MultiResRegistrationFilterType;
+
+  std::cout <<"10: set MultiResolutionPDEDeformableRegistration " <<std::endl;
+  MultiResRegistrationFilterType::Pointer multires = MultiResRegistrationFilterType::New();
+  multires->SetRegistrationFilter( filter );
+  
+  int numberOfLevels = 3;
+// unsigned int nIterations[3] = { 2,2,1 };     // for test
+// unsigned int nIterations[3] = { 400,400,50 };     // for test
+  unsigned int nIterations[3] = { 200,200,30 };
+  multires->SetNumberOfLevels( numberOfLevels ); 
+  multires->SetFixedImage( fixedImage );
+  //multires->SetMovingImage( matcher->GetOutput() );   // turn off the histogram matching for distance mapping demon
+                                                                               // by wook 02/28/08
+  multires->SetMovingImage( movingImage );
+
+  #ifdef SET_SMALL_NUMBER_THREADS
+    multires->SetNumberOfThreads(1);
+  #endif
+ 
+  multires->SetNumberOfIterations( nIterations );  
+
+
+   /******************  by wook    ***************************/
+   std::cout <<"11: set multires->AddObserver " <<std::endl;
+   typedef RegistrationInterfaceCommand<MultiResRegistrationFilterType> CommandType;
+   CommandType::Pointer command = CommandType::New();
+   multires->AddObserver( itk::IterationEvent(), command );
+//   multires->Update();
+   /*****************************************************************/
+
+
+ #ifdef FORCED_UPDATE
+   multires->Update();
+ #endif
+
+
+#ifdef GET_NUMBER_OF_THREADS
+
+  std::cout <<" Number of Threads for MultiResolutionPDEDeformableRegistration: "<<multires->GetNumberOfThreads() << std::endl;
+
+#endif
+                
+
+  std::cout <<"12: WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  typedef itk::LinearInterpolateImageFunction<
+                                   MovingImageType,
+                                   double          >  InterpolatorType;
+  WarperType::Pointer warper = WarperType::New();
+  InterpolatorType::Pointer interpolator = InterpolatorType::New();
+//  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
+
+  std::cout <<"13: initialize WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  warper->SetInput( movingImage );
+  warper->SetInterpolator( interpolator );
+
+
+  warper->SetOutputSpacing( fixedImage->GetSpacing() );
+  warper->SetOutputOrigin( fixedImage->GetOrigin() );
+  warper->SetDeformationField( multires->GetOutput() );
+
+  // by wook to set the large value as outside pixel value
+  warper->SetEdgePaddingValue(65535L);
+
+ #ifdef SET_SMALL_NUMBER_THREADS
+   warper->SetNumberOfThreads(1);
+ #endif
+
+     warper->Update();
+     std::cout<< "warper spacing:" <<warper->GetOutput()->GetSpacing()    <<"warper origin:"<<warper->GetOutput()->GetOrigin() <<std::endl;
+     std::cout<< "warper size:" <<warper->GetOutput()->GetRequestedRegion().GetSize()    <<std::endl; 
+   
+                                                                                                                                              
+if(registeredImageName.length()>0){
+	typedef float  OutputPixelType;
+	typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
+	typedef itk::CastImageFilter< 
+			MovingImageType,
+                        OutputImageType > CastFilterType;
+	typedef itk::ImageFileWriter< OutputImageType >  WriterType;
+
+ 
+	WriterType::Pointer      writer =  WriterType::New();
+	CastFilterType::Pointer  caster =  CastFilterType::New();
+  
+	string registeredFileNamewithExtension = registeredImageName + ".vtk";
+	writer->SetFileName( registeredFileNamewithExtension );
+  
+	caster->SetInput( warper->GetOutput() );
+	writer->SetInput( caster->GetOutput() );
+
+	writer->Update();
+	observer->CloseFile();  // by wook
+
+
+	FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
+
+	string deformationFieldFileNamewithExtension = registeredImageName + "_DField.vtk";
+	fieldWriter->SetFileName( deformationFieldFileNamewithExtension );
+	fieldWriter->SetInput( multires->GetOutput() );
+	fieldWriter->Update();
+
+}
+//  return multires->GetOutput();
+	DfieldIteratorType fi( multires->GetOutput(), fixedImage->GetRequestedRegion().GetSize() );
+	DfieldIteratorType resultDFit( resultingDField, resultingDField->GetRequestedRegion().GetSize() );
+	fi.GoToBegin();
+	resultDFit.GoToBegin();
+	
+	while( (!fi.IsAtEnd())&&(!resultDFit.IsAtEnd()) ){
+		
+    		resultDFit.Set(  fi.Get() );
+    		++fi;
+		++resultDFit;
+    	}
+
+}
+}   // namespace FIRST_EDEMON
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/firstExtendedSymmetricDemon.h b/bioimagesuite30_src/DemonsRegistration/firstExtendedSymmetricDemon.h
new file mode 100644
index 0000000..0989636
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/firstExtendedSymmetricDemon.h
@@ -0,0 +1,393 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+//#define GET_NUMBER_OF_THREADS
+#define GET_INFORMATION_ON_ITERATION
+
+//#define SET_SMALL_NUMBER_THREADS
+//#define FORCED_UPDATE
+
+
+namespace FIRST_SEDEMON{
+
+
+template <typename TRegistration>
+class RegistrationInterfaceCommand : public itk::Command
+{
+
+public:
+  typedef  RegistrationInterfaceCommand   Self;
+  typedef  itk::Command                   Superclass;
+  typedef  itk::SmartPointer<Self>        Pointer;
+  itkNewMacro( Self );
+protected:
+  RegistrationInterfaceCommand() {};
+
+public:
+  typedef   TRegistration                              RegistrationType;
+  typedef   RegistrationType *                         RegistrationPointer;
+
+  typedef itk::Vector< float, Dimension >    VectorPixelType;
+  typedef itk::Image< float, Dimension > InternalImageType;
+  typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+  typedef itk::jwsSymmetricForcesDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+  
+  void Execute(itk::Object * object, const itk::EventObject & event)
+  {
+
+    if( !(itk::IterationEvent().CheckEvent( &event )) )
+      {
+      return;
+      }
+     
+
+    RegistrationPointer registration =
+                            dynamic_cast<RegistrationPointer>( object );
+    // for MultiResolutionPDEDeformableRegistration
+
+
+    RegistrationFilterType * filter = dynamic_cast< RegistrationFilterType * >(
+                       registration->GetRegistrationFilter() );
+       // for Demon Registration algorithm
+    
+
+    std::cout << "level:"<<registration->GetCurrentLevel() <<std::endl;
+                 
+    if ( registration->GetCurrentLevel() == 1 )
+      {
+        std::cout << "*****   level 111111" <<std::endl;
+        std::cout<<"In Multilevel : "  <<  filter->GetElapsedIterations()<< std::endl;
+      }
+     
+  }
+
+
+  void Execute(const itk::Object * , const itk::EventObject & )
+    { return; }
+};
+
+
+
+
+//  The following section of code implements a Command observer
+//  that will monitor the evolution of the registration process.
+//
+  class CommandIterationUpdate : public itk::Command
+  {
+  public:
+    typedef  CommandIterationUpdate   Self;
+    typedef  itk::Command             Superclass;
+    typedef  itk::SmartPointer<CommandIterationUpdate>  Pointer;
+
+    double lPreviousValue;
+    double lCurrentValue ;
+    double lDiff;
+    double lDiff_Diff;
+    double lPrevDiff;
+    int     nContinueCount, nIncreased;
+    FILE *fp;
+
+
+    itkNewMacro( CommandIterationUpdate );
+  protected:
+    CommandIterationUpdate() {};
+
+    typedef itk::Image< float, Dimension > InternalImageType;
+    typedef itk::Vector< float, Dimension >    VectorPixelType;
+    typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+    typedef itk::jwsSymmetricForcesDemonsRegistrationFilter<
+                                  InternalImageType,
+                                  InternalImageType,
+                                  DeformationFieldType> RegistrationFilterType;
+
+    typedef itk::ImageRegionIterator< DeformationFieldType > FieldIterator;
+    typedef itk::ImageRegionConstIterator< InternalImageType > DMapIterator;
+	
+    VectorPixelType displacement;
+    DeformationFieldType::IndexType index;
+
+  public:
+
+    void InitFile(void)
+    {
+         //fp = fopen("Diff_data.txt","w");
+         nIncreased = 0;
+    }
+
+    void CloseFile(void)
+    {
+        //fclose(fp);
+    } 
+        
+  
+    void Execute(itk::Object *caller, const itk::EventObject & event)
+      {
+       // Execute( (const itk::Object *)caller, event);
+#if 1
+           RegistrationFilterType * filter =
+            dynamic_cast< RegistrationFilterType * >( caller );
+
+            unsigned int unElapsedIter;  // by wook
+	   DeformationFieldType::Pointer Dfield;
+	   FixedImageType::ConstPointer fxImage;   // Ohhh  -> ConstPointer for const pointer
+	   
+          if( !(itk::IterationEvent().CheckEvent( &event )) )
+            {
+            return;
+            }
+            
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		  cout << "firstExtendedSymmetricDemon.cxx " <<endl;
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+          unElapsedIter = filter->GetElapsedIterations();
+          lPreviousValue = lCurrentValue;
+          lCurrentValue = filter->GetMetric();
+
+          lPrevDiff = lDiff;
+          lDiff = fabs(lPreviousValue - lCurrentValue);
+          lDiff_Diff = fabs(lPrevDiff - lDiff) *100;
+                   
+          //fprintf(fp,"%d %f\n",unElapsedIter,lCurrentValue);
+          
+          
+          if(lDiff < 0.0001) nContinueCount++;    // when input data is signed float (minus value for inside)
+          //if(lDiff < 0.1) nContinueCount++;  // when input data is unsigned short
+          else  nContinueCount = 0;
+
+          #ifdef GET_INFORMATION_ON_ITERATION
+          if(lPreviousValue > lCurrentValue){
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= -"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<<std::endl;
+            nIncreased = 0;                                                                                                              
+          } 
+          else{
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= +"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<< std::endl;
+            nIncreased++;                                                                                                                         
+          } 
+                                                                                                                                                                                                                                
+          if(nContinueCount > 10){
+                nContinueCount = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continuous negligible variations     "<<std::endl;                                
+          }
+
+          if(nIncreased > 20){
+                nIncreased = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continumes metric increasement      "<<std::endl;                              
+          }
+          
+                        
+          #endif
+                                                        
+          #if 0  
+          
+          std::cout << unElapsedIter << " " << filter->GetMetric() << std::endl;
+
+          if(unElapsedIter ==20){ std::cout << "********************************  count!!"<<std::endl;
+              filter->StopRegistration();
+          }
+          #endif
+#endif
+      }
+
+    void Execute(const itk::Object * object, const itk::EventObject & event)
+      {
+	}
+  };
+
+
+#if  1
+void firstExtendedDemonRegistration(FixedImageType::Pointer fixedImage, MovingImageType::Pointer movingImage, DeformationFieldType::Pointer resultingDField, string registeredImageName)
+{
+  std::cout <<" start first extended demon registration " <<std::endl;   
+
+  typedef itk::jwsSymmetricForcesDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+
+  std::cout <<"7: set  DemonsRegistrationFilter " <<std::endl;
+  RegistrationFilterType::Pointer filter = RegistrationFilterType::New();
+
+  filter->SetNumberOfIterations( 50 );
+//  filter->SetStandardDeviations( 1.0 );   // good
+  filter->SetStandardDeviations( 2.0 );   // test
+
+     #ifdef SET_SMALL_NUMBER_THREADS
+       filter->SetNumberOfThreads(1);
+     #endif
+
+  
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for DemonsRegistrationFilter: "<<filter->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+  /////////////////////////////////////////////////////////////////////////////
+  std::cout <<"8: set  CommandIterationUpdate " <<std::endl;
+  CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
+  observer->InitFile();
+
+  std::cout <<"9: filter->AddObserver " <<std::endl;
+  filter->AddObserver( itk::IterationEvent(), observer );
+
+     
+  /////////////////////////////////////////////////////////////////////////////
+
+  typedef itk::jwsMultiResolutionPDEDeformableRegistration<
+                                InternalImageType,
+                                InternalImageType,
+                                DeformationFieldType >   MultiResRegistrationFilterType;
+
+  std::cout <<"10: set MultiResolutionPDEDeformableRegistration " <<std::endl;
+  MultiResRegistrationFilterType::Pointer multires = MultiResRegistrationFilterType::New();
+  multires->SetRegistrationFilter( filter );
+  
+  int numberOfLevels = 3;
+// unsigned int nIterations[3] = { 2,2,1 };     // for test
+ //unsigned int nIterations[3] = { 400,400,300 };     // for test
+//  unsigned int nIterations[3] = { 200,200,30 };
+ unsigned int nIterations[3] = { 300,300, 100 };     // good
+  
+  multires->SetNumberOfLevels( numberOfLevels ); 
+  multires->SetFixedImage( fixedImage );
+  //multires->SetMovingImage( matcher->GetOutput() );   // turn off the histogram matching for distance mapping demon
+                                                                               // by wook 02/28/08
+  multires->SetMovingImage( movingImage );
+
+  #ifdef SET_SMALL_NUMBER_THREADS
+    multires->SetNumberOfThreads(1);
+  #endif
+ 
+  multires->SetNumberOfIterations( nIterations );  
+
+
+   /******************  by wook    ***************************/
+   std::cout <<"11: set multires->AddObserver " <<std::endl;
+   typedef RegistrationInterfaceCommand<MultiResRegistrationFilterType> CommandType;
+   CommandType::Pointer command = CommandType::New();
+   multires->AddObserver( itk::IterationEvent(), command );
+//   multires->Update();
+   /*****************************************************************/
+
+
+ #ifdef FORCED_UPDATE
+   multires->Update();
+ #endif
+
+
+#ifdef GET_NUMBER_OF_THREADS
+
+  std::cout <<" Number of Threads for MultiResolutionPDEDeformableRegistration: "<<multires->GetNumberOfThreads() << std::endl;
+
+#endif
+                
+
+  std::cout <<"12: WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  typedef itk::LinearInterpolateImageFunction<
+                                   MovingImageType,
+                                   double          >  InterpolatorType;
+  WarperType::Pointer warper = WarperType::New();
+  InterpolatorType::Pointer interpolator = InterpolatorType::New();
+//  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
+
+  std::cout <<"13: initialize WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  warper->SetInput( movingImage );
+  warper->SetInterpolator( interpolator );
+
+
+  warper->SetOutputSpacing( fixedImage->GetSpacing() );
+  warper->SetOutputOrigin( fixedImage->GetOrigin() );
+  warper->SetDeformationField( multires->GetOutput() );
+
+  // by wook to set the large value as outside pixel value
+  warper->SetEdgePaddingValue(65535L);
+
+ #ifdef SET_SMALL_NUMBER_THREADS
+   warper->SetNumberOfThreads(1);
+ #endif
+
+     warper->Update();
+     std::cout<< "warper spacing:" <<warper->GetOutput()->GetSpacing()    <<"warper origin:"<<warper->GetOutput()->GetOrigin() <<std::endl;
+     std::cout<< "warper size:" <<warper->GetOutput()->GetRequestedRegion().GetSize()    <<std::endl; 
+   
+                                                                                                                                              
+if(registeredImageName.length()>0){
+	typedef float  OutputPixelType;
+	typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
+	typedef itk::CastImageFilter< 
+			MovingImageType,
+                        OutputImageType > CastFilterType;
+	typedef itk::ImageFileWriter< OutputImageType >  WriterType;
+
+ 
+	WriterType::Pointer      writer =  WriterType::New();
+	CastFilterType::Pointer  caster =  CastFilterType::New();
+  
+	string registeredFileNamewithExtension = registeredImageName + ".vtk";
+	writer->SetFileName( registeredFileNamewithExtension );
+  
+	caster->SetInput( warper->GetOutput() );
+	writer->SetInput( caster->GetOutput() );
+
+	writer->Update();
+	observer->CloseFile();  // by wook
+
+
+	FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
+
+	string deformationFieldFileNamewithExtension = registeredImageName + "_DField.vtk";
+	fieldWriter->SetFileName( deformationFieldFileNamewithExtension );
+	fieldWriter->SetInput( multires->GetOutput() );
+	fieldWriter->Update();
+
+}
+//  return multires->GetOutput();
+	DfieldIteratorType fi( multires->GetOutput(), fixedImage->GetRequestedRegion().GetSize() );
+	DfieldIteratorType resultDFit( resultingDField, resultingDField->GetRequestedRegion().GetSize() );
+	fi.GoToBegin();
+	resultDFit.GoToBegin();
+	
+	while( (!fi.IsAtEnd())&&(!resultDFit.IsAtEnd()) ){
+		
+    		resultDFit.Set(  fi.Get() );
+    		++fi;
+		++resultDFit;
+    	}
+
+}
+}   // namespace FIRST_EDEMON
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkBinaryMorphologicalClosingImageFilter.h b/bioimagesuite30_src/DemonsRegistration/itkBinaryMorphologicalClosingImageFilter.h
new file mode 100644
index 0000000..ff2eb12
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkBinaryMorphologicalClosingImageFilter.h
@@ -0,0 +1,159 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkBinaryMorphologicalClosingImageFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2007/06/07 09:05:07 $
+  Version:   $Revision: 1.1 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+
+#ifndef __itkBinaryMorphologicalClosingImageFilter_h
+#define __itkBinaryMorphologicalClosingImageFilter_h
+
+#include "itkImageToImageFilter.h"
+
+namespace itk {
+
+/**
+ * \class BinaryMorphologicalClosingImageFilter
+ * \brief binary morphological closing of an image.
+ *
+ * This filter removes small (i.e., smaller than the structuring 
+ * element) holes and tube like structures in the interior or at the
+ * boundaries of the image. The morphological closing of an image
+ * "f" is defined as:
+ * Closing(f) = Erosion(Dilation(f)).
+ *
+ * The structuring element is assumed to be composed of binary
+ * values (zero or one). Only elements of the structuring element
+ * having values > 0 are candidates for affecting the center pixel.
+ * 
+ *
+ * \author Ga�tan Lehmann. Biologie du D�veloppement et de la Reproduction, INRA of Jouy-en-Josas, France.
+ *
+ * \sa MorphologyImageFilter, GrayscaleDilateImageFilter, GrayscaleErodeImageFilter
+ * \ingroup ImageEnhancement  MathematicalMorphologyImageFilters
+ */
+
+template<class TInputImage, class TOutputImage, class TKernel>
+class ITK_EXPORT BinaryMorphologicalClosingImageFilter : 
+    public ImageToImageFilter<TInputImage, TOutputImage>
+{
+public:
+  /** Standard class typedefs. */
+  typedef BinaryMorphologicalClosingImageFilter         Self;
+  typedef ImageToImageFilter<TInputImage, TOutputImage> Superclass;
+  typedef SmartPointer<Self>                            Pointer;
+  typedef SmartPointer<const Self>                      ConstPointer;
+  
+  /** Standard New method. */
+  itkNewMacro(Self);  
+
+  /** Runtime information support. */
+  itkTypeMacro(BinaryMorphologicalClosingImageFilter, 
+               ImageToImageFilter);
+
+  typedef TInputImage                              InputImageType;
+  typedef TOutputImage                             OutputImageType;
+  typedef typename InputImageType::Pointer         InputImagePointer;
+  typedef typename OutputImageType::RegionType     OutputImageRegionType;
+
+  /** Declaration of pixel type. */
+  typedef typename TInputImage::PixelType InputPixelType;
+  typedef typename TInputImage::PixelType OutputPixelType;
+
+  /** Kernel typedef. */
+  typedef TKernel KernelType;
+
+  /** Set kernel (structuring element). */
+  itkSetMacro(Kernel, KernelType);
+
+  /** Get the kernel (structuring element). */
+  itkGetConstReferenceMacro(Kernel, KernelType);
+
+  /** Set the value in the image to consider as "foreground". Defaults to
+   * maximum value of InputPixelType. */
+  itkSetMacro(ForegroundValue, InputPixelType);
+ 
+  /** Get the value in the image considered as "foreground". Defaults to
+   * maximum value of InputPixelType. */
+  itkGetMacro(ForegroundValue, InputPixelType);
+ 
+  
+  /** A safe border is added to input image to avoid borders effects
+   * and remove it once the closing is done */
+  itkSetMacro(SafeBorder, bool);
+  itkGetConstReferenceMacro(SafeBorder, bool);
+  itkBooleanMacro(SafeBorder);
+   
+protected:
+  BinaryMorphologicalClosingImageFilter();
+  ~BinaryMorphologicalClosingImageFilter() {};
+  void PrintSelf(std::ostream& os, Indent indent) const;
+
+  /** BinaryMorphologicalClosingImageFilter need to make sure they request enough of an
+   * input image to account for the structuring element size.  The input
+   * requested region is expanded by the radius of the structuring element.
+   * If the request extends past the LargestPossibleRegion for the input,
+   * the request is cropped by the LargestPossibleRegion. */
+  void GenerateInputRequestedRegion();
+
+  /** Single-threaded version of GenerateData.  This filter delegates
+   * to GrayscaleDilateImageFilter GrayscaleErodeImageFilter. */
+  void  GenerateData ();
+
+private:
+  BinaryMorphologicalClosingImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+  /** kernel or structuring element to use. */
+  KernelType m_Kernel;
+   
+  InputPixelType m_ForegroundValue;
+  
+  bool m_SafeBorder;
+}; // end of class
+
+} // end namespace itk
+  
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkBinaryMorphologicalClosingImageFilter.txx"
+#endif
+
+#endif
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkBinaryMorphologicalClosingImageFilter.txx b/bioimagesuite30_src/DemonsRegistration/itkBinaryMorphologicalClosingImageFilter.txx
new file mode 100644
index 0000000..bb92b0a
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkBinaryMorphologicalClosingImageFilter.txx
@@ -0,0 +1,247 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkBinaryMorphologicalClosingImageFilter.txx,v $
+  Language:  C++
+  Date:      $Date: 2007/06/07 09:05:07 $
+  Version:   $Revision: 1.1 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+
+#ifndef __itkBinaryMorphologicalClosingImageFilter_txx
+#define __itkBinaryMorphologicalClosingImageFilter_txx
+
+#include "itkBinaryMorphologicalClosingImageFilter.h"
+#include "itkBinaryErodeImageFilter.h"
+#include "itkBinaryDilateImageFilter.h"
+#include "itkProgressAccumulator.h"
+#include "itkCropImageFilter.h"
+#include "itkConstantPadImageFilter.h"
+#include "itkConstNeighborhoodIterator.h"
+#include "itkNeighborhoodIterator.h"
+#include "itkProgressReporter.h"
+
+namespace itk {
+
+template<class TInputImage, class TOutputImage, class TKernel>
+BinaryMorphologicalClosingImageFilter<TInputImage, TOutputImage, TKernel>
+::BinaryMorphologicalClosingImageFilter()
+  : m_Kernel()
+{
+  m_ForegroundValue = NumericTraits<InputPixelType>::max();
+  m_SafeBorder = true;
+}
+
+template <class TInputImage, class TOutputImage, class TKernel>
+void 
+BinaryMorphologicalClosingImageFilter<TInputImage, TOutputImage, TKernel>
+::GenerateInputRequestedRegion()
+{
+  // call the superclass' implementation of this method
+  Superclass::GenerateInputRequestedRegion();
+  
+  // get pointers to the input and output
+  typename Superclass::InputImagePointer  inputPtr = 
+    const_cast< TInputImage * >( this->GetInput() );
+  
+  if ( !inputPtr )
+    {
+    return;
+    }
+
+  // get a copy of the input requested region (should equal the output
+  // requested region)
+  typename TInputImage::RegionType inputRequestedRegion;
+  inputRequestedRegion = inputPtr->GetRequestedRegion();
+
+  // pad the input requested region by the operator radius
+  inputRequestedRegion.PadByRadius( m_Kernel.GetRadius() );
+
+  // crop the input requested region at the input's largest possible region
+  if ( inputRequestedRegion.Crop(inputPtr->GetLargestPossibleRegion()) )
+    {
+    inputPtr->SetRequestedRegion( inputRequestedRegion );
+    return;
+    }
+  else
+    {
+    // Couldn't crop the region (requested region is outside the largest
+    // possible region).  Throw an exception.
+
+    // store what we tried to request (prior to trying to crop)
+    inputPtr->SetRequestedRegion( inputRequestedRegion );
+    
+    // build an exception
+    InvalidRequestedRegionError e(__FILE__, __LINE__);
+    OStringStream msg;
+    msg << static_cast<const char *>(this->GetNameOfClass())
+        << "::GenerateInputRequestedRegion()";
+    e.SetLocation(msg.str().c_str());
+    e.SetDescription("Requested region is (at least partially) outside the largest possible region.");
+    e.SetDataObject(inputPtr);
+    throw e;
+    }
+}
+
+template<class TInputImage, class TOutputImage, class TKernel>
+void
+BinaryMorphologicalClosingImageFilter<TInputImage, TOutputImage, TKernel>
+::GenerateData()
+{
+  // Allocate the outputs
+  this->AllocateOutputs();
+  
+  // let choose a background value. Background value should not be given by user
+  // because closing is extensive so no background pixels will be added
+  // it is just needed for internal erosion filter and constant padder
+  InputPixelType backgroundValue = NumericTraits<InputPixelType>::Zero;
+  if ( m_ForegroundValue == backgroundValue )
+    {
+    // current background value is already used for foreground value
+    // choose another one
+    backgroundValue = NumericTraits<InputPixelType>::max();
+    }
+
+  typename BinaryDilateImageFilter<TInputImage, TInputImage, TKernel>::Pointer
+    dilate = BinaryDilateImageFilter<TInputImage, TInputImage, TKernel>::New();
+
+  typename BinaryErodeImageFilter<TInputImage, TOutputImage, TKernel>::Pointer
+    erode = BinaryErodeImageFilter<TInputImage, TOutputImage, TKernel>::New();
+
+  // create the pipeline without input and output image
+  dilate->ReleaseDataFlagOn();
+  dilate->SetKernel( this->GetKernel() );
+  dilate->SetDilateValue( m_ForegroundValue );
+
+  erode->SetKernel( this->GetKernel() );
+  erode->ReleaseDataFlagOn();
+  erode->SetErodeValue( m_ForegroundValue );
+  erode->SetBackgroundValue( backgroundValue );
+  erode->SetInput( dilate->GetOutput() );
+
+  // now we have 2 cases:
+  // + SafeBorder is true so we need to create a bigger image use it as input
+  //   and crop the image to the normal output image size
+  // + SafeBorder is false; we just have to connect filters
+  if ( m_SafeBorder )
+    {
+    typedef typename itk::ConstantPadImageFilter<InputImageType, InputImageType> PadType;
+    typename PadType::Pointer pad = PadType::New();
+    pad->SetPadLowerBound( m_Kernel.GetRadius().m_Size );
+    pad->SetPadUpperBound( m_Kernel.GetRadius().m_Size );
+    pad->SetConstant( backgroundValue );
+    pad->SetInput( this->GetInput() );
+
+    dilate->SetInput( pad->GetOutput() );
+    
+    typedef typename itk::CropImageFilter<TOutputImage, TOutputImage> CropType;
+    typename CropType::Pointer crop = CropType::New();
+    crop->SetInput( erode->GetOutput() );
+    crop->SetUpperBoundaryCropSize( m_Kernel.GetRadius() );
+    crop->SetLowerBoundaryCropSize( m_Kernel.GetRadius() );
+    
+    ProgressAccumulator::Pointer progress = ProgressAccumulator::New();
+    progress->SetMiniPipelineFilter(this);
+    progress->RegisterInternalFilter(pad, .1f);
+    progress->RegisterInternalFilter(erode, .35f);
+    progress->RegisterInternalFilter(dilate, .35f);
+    progress->RegisterInternalFilter(crop, .1f);
+    
+    crop->GraftOutput( this->GetOutput() );
+    crop->Update();
+  
+    this->GraftOutput( crop->GetOutput() );
+    }
+  else
+    {
+    ProgressAccumulator::Pointer progress = ProgressAccumulator::New();
+    progress->SetMiniPipelineFilter(this);
+    progress->RegisterInternalFilter(erode, .45f);
+    progress->RegisterInternalFilter(dilate, .45f);
+    
+    dilate->SetInput( this->GetInput() );
+    erode->GraftOutput( this->GetOutput() );
+  
+    erode->Update();
+  
+    this->GraftOutput( erode->GetOutput() );
+    }
+
+  // finally copy background which should have been eroded
+  //
+  // iterator on input image
+  ImageRegionConstIterator<InputImageType> inIt 
+            = ImageRegionConstIterator<InputImageType>( this->GetInput(),
+                    this->GetOutput()->GetRequestedRegion() );
+  // iterator on output image
+  ImageRegionIterator<OutputImageType> outIt
+            = ImageRegionIterator<OutputImageType>( this->GetOutput(),
+                    this->GetOutput()->GetRequestedRegion() );
+  outIt.GoToBegin(); 
+  inIt.GoToBegin(); 
+
+  ProgressReporter progress2(this, 0, this->GetOutput()->GetRequestedRegion().GetNumberOfPixels(), 20, 0.9, 0.1);
+  while( !outIt.IsAtEnd() )
+    {
+    if( outIt.Get() != m_ForegroundValue )
+      {
+      outIt.Set( static_cast<OutputPixelType>( inIt.Get() ) );
+      }
+    ++outIt;
+    ++inIt;
+    progress2.CompletedPixel();
+    }
+  
+  // the end !
+}
+
+template<class TInputImage, class TOutputImage, class TKernel>
+void
+BinaryMorphologicalClosingImageFilter<TInputImage, TOutputImage, TKernel>
+::PrintSelf(std::ostream &os, Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+
+  os << indent << "Kernel: " << m_Kernel << std::endl;
+  os << indent << "ForegroundValue: " << static_cast<typename NumericTraits<InputPixelType>::PrintType>(m_ForegroundValue) << std::endl;
+  os << indent << "SafeBorder: " << m_SafeBorder << std::endl;
+}
+
+}// end namespace itk
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsDemonsRegistrationFilter.h b/bioimagesuite30_src/DemonsRegistration/itkjwsDemonsRegistrationFilter.h
new file mode 100644
index 0000000..dfba2eb
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsDemonsRegistrationFilter.h
@@ -0,0 +1,183 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsDemonsRegistrationFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2004/06/17 15:25:58 $
+  Version:   $Revision: 1.14 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkjwsDemonsRegistrationFilter_h_
+#define _itkjwsDemonsRegistrationFilter_h_
+
+#include "itkjwsPDEDeformableRegistrationFilter.h"
+#include "itkjwsDemonsRegistrationFunction.h"
+
+namespace itk {
+
+/** \class jwsDemonsRegistrationFilter
+ * \brief Deformably register two images using the demons algorithm.
+ *
+ * jwsDemonsRegistrationFilter implements the demons deformable algorithm that 
+ * register two images by computing the deformation field which will map a 
+ * moving image onto a fixed image.
+ *
+ * A deformation field is represented as a image whose pixel type is some
+ * vector type with at least N elements, where N is the dimension of
+ * the fixed image. The vector type must support element access via operator
+ * []. It is assumed that the vector elements behave like floating point
+ * scalars.
+ *
+ * This class is templated over the fixed image type, moving image type
+ * and the deformation field type.
+ *
+ * The input fixed and moving images are set via methods SetFixedImage
+ * and SetMovingImage respectively. An initial deformation field maybe set via
+ * SetInitialDeformationField or SetInput. If no initial field is set,
+ * a zero field is used as the initial condition.
+ *
+ * The algorithm has one parameters: the number of iteration to be performed.
+ *
+ * The output deformation field can be obtained via methods GetOutput
+ * or GetDeformationField.
+ *
+ * This class make use of the finite difference solver hierarchy. Update
+ * for each iteration is computed in jwsDemonsRegistrationFunction.
+ *
+ * \warning This filter assumes that the fixed image type, moving image type
+ * and deformation field type all have the same number of dimensions.
+ * 
+ * \sa jwsDemonsRegistrationFunction 
+ * \ingroup DeformableImageRegistration MultiThreaded
+ */
+template<class TFixedImage, class TMovingImage, class TDeformationField>
+class ITK_EXPORT jwsDemonsRegistrationFilter : 
+    public jwsPDEDeformableRegistrationFilter< TFixedImage, TMovingImage,
+                                            TDeformationField>
+{
+public:
+  /** Standard class typedefs. */
+  typedef jwsDemonsRegistrationFilter    Self;
+  typedef jwsPDEDeformableRegistrationFilter<
+    TFixedImage, TMovingImage,TDeformationField>    Superclass;
+  typedef SmartPointer<Self> Pointer;
+  typedef SmartPointer<const Self> ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro( jwsDemonsRegistrationFilter, 
+                jwsPDEDeformableRegistrationFilter );
+
+  /** Inherit types from superclass. */
+  typedef typename Superclass::TimeStepType  TimeStepType;
+
+  /** FixedImage image type. */
+  typedef typename Superclass::FixedImageType   FixedImageType;
+  typedef typename Superclass::FixedImagePointer  FixedImagePointer;
+
+  /** MovingImage image type. */
+  typedef typename Superclass::MovingImageType    MovingImageType;
+  typedef typename Superclass::MovingImagePointer  MovingImagePointer;
+  
+  /** Deformation field type. */
+  typedef typename Superclass::DeformationFieldType 
+  DeformationFieldType;
+  typedef typename Superclass::DeformationFieldPointer  
+  DeformationFieldPointer;
+
+  /** FiniteDifferenceFunction type. */
+  typedef typename Superclass::FiniteDifferenceFunctionType
+  FiniteDifferenceFunctionType;
+
+  /** jwsDemonsRegistrationFilterFunction type. */
+  typedef jwsDemonsRegistrationFunction<FixedImageType,MovingImageType,
+                                     DeformationFieldType>  jwsDemonsRegistrationFunctionType;
+  
+  /** Get the metric value. The metric value is the mean square difference 
+   * in intensity between the fixed image and transforming moving image 
+   * computed over the the overlapping region between the two images. 
+   * This is value is only available for the previous iteration and 
+   * NOT the current iteration. */
+  virtual double GetMetric() const;
+
+  /** Switch between using the fixed image and moving image gradient
+   * for computing the deformation field updates. */
+  itkSetMacro( UseMovingImageGradient, bool );
+  itkGetMacro( UseMovingImageGradient, bool );
+  itkBooleanMacro( UseMovingImageGradient );
+
+  /** Set/Get the threshold below which the absolute difference of
+   * intensity yields a match. When the intensities match between a
+   * moving and fixed image pixel, the update vector (for that
+   * iteration) will be the zero vector. Default is 0.001. */
+  virtual void SetIntensityDifferenceThreshold(double);
+  virtual double GetIntensityDifferenceThreshold() const;
+
+
+  /**  Added by wook  */
+  virtual void setMyDField( DeformationFieldPointer ptr );  
+
+protected:
+  jwsDemonsRegistrationFilter();
+  ~jwsDemonsRegistrationFilter() {}
+  void PrintSelf(std::ostream& os, Indent indent) const;
+
+  /** Initialize the state of filter and equation before each iteration. */
+  virtual void InitializeIteration();
+
+  /** Apply update. */
+  virtual void ApplyUpdate(TimeStepType dt);
+
+private:
+  jwsDemonsRegistrationFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+  bool  m_UseMovingImageGradient;
+
+};
+
+
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkjwsDemonsRegistrationFilter.txx"
+#endif
+
+#endif
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsDemonsRegistrationFilter.txx b/bioimagesuite30_src/DemonsRegistration/itkjwsDemonsRegistrationFilter.txx
new file mode 100644
index 0000000..d81fe79
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsDemonsRegistrationFilter.txx
@@ -0,0 +1,248 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsDemonsRegistrationFilter.txx,v $
+  Language:  C++
+  Date:      $Date: 2004/09/29 23:59:04 $
+  Version:   $Revision: 1.13 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkjwsDemonsRegistrationFilter_txx
+#define _itkjwsDemonsRegistrationFilter_txx
+#include "itkjwsDemonsRegistrationFilter.h"
+
+namespace itk {
+
+/*
+ * Default constructor
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+jwsDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::jwsDemonsRegistrationFilter()
+{
+ 
+  typename jwsDemonsRegistrationFunctionType::Pointer drfp;
+  drfp = jwsDemonsRegistrationFunctionType::New();
+
+  this->SetDifferenceFunction( static_cast<FiniteDifferenceFunctionType *>(
+                                 drfp.GetPointer() ) );
+
+  m_UseMovingImageGradient = false;
+
+}
+
+
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::PrintSelf(std::ostream& os, Indent indent) const
+{ 
+  Superclass::PrintSelf( os, indent );
+  os << indent << "UseMovingImageGradient: ";
+  os << m_UseMovingImageGradient << std::endl;
+  os << indent << "Intensity difference threshold: " <<
+    this->GetIntensityDifferenceThreshold() << std::endl;
+}
+/////////////////////////////////////////////////////////////////////////////////
+/*
+ * Added by wook 08/02/26
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::setMyDField( DeformationFieldPointer ptr )
+{
+   // set the gradient selection flag
+  jwsDemonsRegistrationFunctionType *drfp = 
+    dynamic_cast<jwsDemonsRegistrationFunctionType *>
+      (this->GetDifferenceFunction().GetPointer());
+ 
+  if( !drfp )
+   {
+   itkExceptionMacro( << 
+     "Could not cast difference function to jwsDemonsRegistrationFunction" );
+   }
+   
+  drfp->SetDeformationField( ptr );
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+/*
+ * Set the function state values before each iteration
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::InitializeIteration()
+{
+ 
+  // call the superclass  implementation
+  Superclass::InitializeIteration();
+
+  // set the gradient selection flag
+  jwsDemonsRegistrationFunctionType *drfp = 
+    dynamic_cast<jwsDemonsRegistrationFunctionType *>
+      (this->GetDifferenceFunction().GetPointer());
+ 
+  if( !drfp )
+   {
+   itkExceptionMacro( << 
+     "Could not cast difference function to jwsDemonsRegistrationFunction" );
+   }
+   
+  drfp->SetUseMovingImageGradient( m_UseMovingImageGradient );
+
+
+  /*
+   * Smooth the deformation field
+   */
+  if ( this->GetSmoothDeformationField() )
+    {
+    this->SmoothDeformationField();
+    }
+
+}
+
+
+/*
+ * Get the metric value from the difference function
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+double
+jwsDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::GetMetric() const
+{
+ 
+  jwsDemonsRegistrationFunctionType *drfp = 
+    dynamic_cast<jwsDemonsRegistrationFunctionType *>
+      (this->GetDifferenceFunction().GetPointer());
+ 
+  if( !drfp )
+   {
+   itkExceptionMacro( << 
+     "Could not cast difference function to jwsDemonsRegistrationFunction" );
+   }
+   
+  return drfp->GetMetric();
+
+}
+
+
+/*
+ * 
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+double
+jwsDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::GetIntensityDifferenceThreshold() const
+{
+ 
+  jwsDemonsRegistrationFunctionType *drfp = 
+    dynamic_cast<jwsDemonsRegistrationFunctionType *>
+      (this->GetDifferenceFunction().GetPointer());
+ 
+  if( !drfp )
+   {
+   itkExceptionMacro( << 
+     "Could not cast difference function to jwsDemonsRegistrationFunction" );
+   }
+   
+  return drfp->GetIntensityDifferenceThreshold();
+
+}
+
+/*
+ * 
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::SetIntensityDifferenceThreshold(double threshold) 
+{
+ 
+  jwsDemonsRegistrationFunctionType *drfp = 
+    dynamic_cast<jwsDemonsRegistrationFunctionType *>
+      (this->GetDifferenceFunction().GetPointer());
+ 
+  if( !drfp )
+   {
+   itkExceptionMacro( << 
+     "Could not cast difference function to jwsDemonsRegistrationFunction" );
+   }
+   
+  drfp->SetIntensityDifferenceThreshold(threshold);
+
+}
+
+/*
+ * Get the metric value from the difference function
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::ApplyUpdate(TimeStepType dt)
+{
+  // If we smooth the update buffer before applying it, then the are
+  // approximating a viscuous problem as opposed to an elastic problem
+  if ( this->GetSmoothUpdateField() )
+    {
+    this->SmoothUpdateField();
+    }
+  
+  this->Superclass::ApplyUpdate(dt);
+
+  jwsDemonsRegistrationFunctionType *drfp = 
+    dynamic_cast<jwsDemonsRegistrationFunctionType *>
+      (this->GetDifferenceFunction().GetPointer());
+ 
+  if( !drfp )
+   {
+   itkExceptionMacro( << 
+     "Could not cast difference function to jwsDemonsRegistrationFunction" );
+   }
+
+  this->SetRMSChange( drfp->GetRMSChange() );
+   
+}
+
+
+
+} // end namespace itk
+
+#endif
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsDemonsRegistrationFunction.h b/bioimagesuite30_src/DemonsRegistration/itkjwsDemonsRegistrationFunction.h
new file mode 100644
index 0000000..fa9d6a0
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsDemonsRegistrationFunction.h
@@ -0,0 +1,301 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsjwsDemonsRegistrationFunction.h,v $
+  Language:  C++
+  Date:      $Date: 2004/06/17 15:25:58 $
+  Version:   $Revision: 1.27 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkjwsDemonsRegistrationFunction_h_
+#define _itkjwsDemonsRegistrationFunction_h_
+
+#include "itkjwsPDEDeformableRegistrationFunction.h"
+#include "itkPoint.h"
+#include "itkCovariantVector.h"
+#include "itkInterpolateImageFunction.h"
+#include "itkLinearInterpolateImageFunction.h"
+#include "itkCentralDifferenceImageFunction.h"
+
+namespace itk {
+
+/**
+* \class jwsDemonsRegistrationFunction
+*
+* This class encapsulate the PDE which drives the demons registration
+* algorithm. It is used by DemonsRegistrationFilter to compute the
+* output deformation field which will map a moving image onto a
+* a fixed image.
+*
+* Non-integer moving image values are obtained by using
+* interpolation. The default interpolator is of type
+* LinearInterpolateImageFunction. The user may set other
+* interpolators via method SetMovingImageInterpolator. Note that the input
+* interpolator must derive from baseclass InterpolateImageFunction.
+*
+* This class is templated over the fixed image type, moving image type,
+* and the deformation field type.
+*
+* \warning This filter assumes that the fixed image type, moving image type
+* and deformation field type all have the same number of dimensions.
+*
+* \sa DemonsRegistrationFilter
+* \ingroup FiniteDifferenceFunctions
+*/
+template<class TFixedImage, class TMovingImage, class TDeformationField>
+class  jwsDemonsRegistrationFunction :
+    public jwsPDEDeformableRegistrationFunction< TFixedImage,
+                                              TMovingImage, 
+TDeformationField>
+{
+public:
+  /** Standard class typedefs. */
+  typedef jwsDemonsRegistrationFunction    Self;
+  typedef jwsPDEDeformableRegistrationFunction< TFixedImage,
+                                             TMovingImage, TDeformationField >    Superclass;
+  typedef SmartPointer<Self> Pointer;
+  typedef SmartPointer<const Self> ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro( jwsDemonsRegistrationFunction,
+                jwsPDEDeformableRegistrationFunction );
+
+  /** MovingImage image type. */
+  typedef typename Superclass::MovingImageType     MovingImageType;
+  typedef typename Superclass::MovingImagePointer  MovingImagePointer;
+
+  /** FixedImage image type. */
+  typedef typename Superclass::FixedImageType     FixedImageType;
+  typedef typename Superclass::FixedImagePointer  FixedImagePointer;
+  typedef typename FixedImageType::IndexType      IndexType;
+  typedef typename FixedImageType::SizeType       SizeType;
+  typedef typename FixedImageType::SpacingType    SpacingType;
+
+  /** Deformation field type. */
+  typedef typename Superclass::DeformationFieldType    DeformationFieldType;
+  typedef typename Superclass::DeformationFieldTypePointer
+  DeformationFieldTypePointer;
+
+  /** Inherit some enums from the superclass. */
+  itkStaticConstMacro(ImageDimension, unsigned 
+int,Superclass::ImageDimension);
+
+  /** Inherit some enums from the superclass. */
+  typedef typename Superclass::PixelType     PixelType;
+  typedef typename Superclass::RadiusType    RadiusType;
+  typedef typename Superclass::NeighborhoodType    NeighborhoodType;
+  typedef typename Superclass::FloatOffsetType  FloatOffsetType;
+  typedef typename Superclass::TimeStepType TimeStepType;
+
+  /** Interpolator type. */
+  typedef double CoordRepType;
+  typedef InterpolateImageFunction<MovingImageType,CoordRepType> 
+InterpolatorType;
+  typedef typename InterpolatorType::Pointer         InterpolatorPointer;
+  typedef typename InterpolatorType::PointType       PointType;
+  typedef LinearInterpolateImageFunction<MovingImageType,CoordRepType>
+  DefaultInterpolatorType;
+
+  /** Covariant vector type. */
+  typedef CovariantVector<double,itkGetStaticConstMacro(ImageDimension)> 
+CovariantVectorType;
+
+  /** Fixed image gradient calculator type. */
+  typedef CentralDifferenceImageFunction<FixedImageType> 
+GradientCalculatorType;
+  typedef typename GradientCalculatorType::Pointer   
+GradientCalculatorPointer;
+
+ /** Moving image gradient calculator type. */
+  typedef CentralDifferenceImageFunction<MovingImageType,CoordRepType>
+      MovingImageGradientCalculatorType;
+  typedef typename MovingImageGradientCalculatorType::Pointer
+      MovingImageGradientCalculatorPointer;
+
+  /** Set the moving image interpolator. */
+  void SetMovingImageInterpolator( InterpolatorType * ptr )
+  { m_MovingImageInterpolator = ptr; }
+
+  /** Get the moving image interpolator. */
+  InterpolatorType * GetMovingImageInterpolator(void)
+  { return m_MovingImageInterpolator; }
+
+  /** This class uses a constant timestep of 1. */
+  virtual TimeStepType ComputeGlobalTimeStep(void * itkNotUsed(GlobalData)) 
+const
+  { return m_TimeStep; }
+
+  /** Return a pointer to a global data structure that is passed to
+   * this object from the solver at each calculation.  */
+  virtual void *GetGlobalDataPointer() const
+  {
+    GlobalDataStruct *global = new GlobalDataStruct();
+    global->m_SumOfSquaredDifference  = 0.0;
+    global->m_NumberOfPixelsProcessed = 0L;
+    global->m_SumOfSquaredChange      = 0;
+    return global;
+  }
+
+  /** Release memory for global data structure. */
+  virtual void ReleaseGlobalDataPointer( void *GlobalData ) const;
+
+  /** Set the object's state before each iteration. */
+  virtual void InitializeIteration();
+
+  /** This method is called by a finite difference solver image filter at
+   * each pixel that does not lie on a data set boundary */
+  virtual PixelType  ComputeUpdate(const NeighborhoodType &neighborhood,
+                                   void *globalData,
+                                   const FloatOffsetType &offset = 
+FloatOffsetType(0.0));
+
+  /** Get the metric value. The metric value is the mean square difference 
+   * in intensity between the fixed image and transforming moving image 
+   * computed over the the overlapping region between the two images. */
+  virtual double GetMetric() const
+    { return m_Metric; }
+
+  /** Get the rms change in deformation field. */
+  virtual double GetRMSChange() const
+    { return m_RMSChange; }
+
+
+
+
+
+///////////////////// Added by Xenios  02/15/08  ///////////////////////
+/** Set the relative weight of the second distance map to the first */
+  virtual void SetSecondDistanceMapWeight( float w )
+    { m_SecondDistanceMapWeight = w; }
+  virtual float GetSecondDistanceMapWeight( float w )
+    { return m_SecondDistanceMapWeight; }
+/////////////////////////////////////////////////////////////////////////
+
+
+
+  /** Select if the fixed image or moving image gradient is used for
+   * the computating the demon forces. The fixed image gradient is used
+   * by default. */
+    virtual void SetUseMovingImageGradient( bool flag )
+    { m_UseMovingImageGradient = flag; }
+  virtual bool GetUseMovingImageGradient() const
+    { return m_UseMovingImageGradient; }
+
+  /** Set/Get the threshold below which the absolute difference of
+   * intensity yields a match. When the intensities match between a
+   * moving and fixed image pixel, the update vector (for that
+   * iteration) will be the zero vector. Default is 0.001. */
+  virtual void SetIntensityDifferenceThreshold(double);
+  virtual double GetIntensityDifferenceThreshold() const;
+  
+protected:
+  jwsDemonsRegistrationFunction();
+  ~jwsDemonsRegistrationFunction() {}
+  void PrintSelf(std::ostream& os, Indent indent) const;
+
+  /** FixedImage image neighborhood iterator type. */
+  typedef ConstNeighborhoodIterator<FixedImageType> 
+FixedImageNeighborhoodIteratorType;
+
+  /** A global data type for this class of equation. Used to store
+   * information for computing the metric. */
+  struct GlobalDataStruct
+  {
+    double          m_SumOfSquaredDifference;
+    unsigned long   m_NumberOfPixelsProcessed;
+    double          m_SumOfSquaredChange;
+  };
+
+private:
+  jwsDemonsRegistrationFunction(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+  /** Cache fixed image information. */
+  SpacingType                     m_FixedImageSpacing;
+  PointType                       m_FixedImageOrigin;
+  double                          m_Normalizer;
+
+  /** Function to compute derivatives of the fixed image. */
+  GradientCalculatorPointer       m_FixedImageGradientCalculator;
+
+  /** Function to compute derivatives of the moving image. */
+  MovingImageGradientCalculatorPointer       m_MovingImageGradientCalculator;
+  bool                                       m_UseMovingImageGradient;
+
+  /** Function to interpolate the moving image. */
+  InterpolatorPointer             m_MovingImageInterpolator;
+
+  /** The global timestep. */
+  TimeStepType                    m_TimeStep;
+
+  /** Threshold below which the denominator term is considered zero. */
+  double                          m_DenominatorThreshold;
+
+  /** Threshold below which two intensity value are assumed to match. */
+  double                          m_IntensityDifferenceThreshold;
+
+/** This is the relative weight of the second distance map. */
+  float							m_SecondDistanceMapWeight;
+
+
+  /** The metric value is the mean square difference in intensity between
+   * the fixed image and transforming moving image computed over the 
+   * the overlapping region between the two images. */
+  mutable double                  m_Metric;
+  mutable double                  m_SumOfSquaredDifference;
+  mutable unsigned long           m_NumberOfPixelsProcessed;
+  mutable double                  m_RMSChange;
+  mutable double                  m_SumOfSquaredChange;
+
+  /** Mutex lock to protect modification to metric. */
+  mutable SimpleFastMutexLock     m_MetricCalculationLock;
+
+};
+
+
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkjwsDemonsRegistrationFunction.txx"
+#endif
+
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsDemonsRegistrationFunction.txx b/bioimagesuite30_src/DemonsRegistration/itkjwsDemonsRegistrationFunction.txx
new file mode 100644
index 0000000..312a7c0
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsDemonsRegistrationFunction.txx
@@ -0,0 +1,343 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsDemonsRegistrationFunction.txx,v $
+  Language:  C++
+  Date:      $Date: 2004/12/21 22:47:26 $
+  Version:   $Revision: 1.30 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkjwsDemonsRegistrationFunction_txx_
+#define _itkjwsDemonsRegistrationFunction_txx_
+
+#include "itkjwsDemonsRegistrationFunction.h"
+#include "itkExceptionObject.h"
+#include "vnl/vnl_math.h"
+#include <stdio.h>
+
+namespace itk {
+
+/*
+ * Default constructor
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+jwsDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::jwsDemonsRegistrationFunction()
+{
+
+  RadiusType r;
+  unsigned int j;
+  for( j = 0; j < ImageDimension; j++ )
+    {
+    r[j] = 0;
+    }
+  this->SetRadius(r);
+
+  m_TimeStep = 1.0;
+  m_DenominatorThreshold = 1e-9;
+  m_IntensityDifferenceThreshold = 0.001;
+  this->SetMovingImage(NULL);
+  this->SetFixedImage(NULL);
+  m_FixedImageSpacing.Fill( 1.0 );
+  m_FixedImageOrigin.Fill( 0.0 );
+  m_Normalizer = 1.0;
+  m_FixedImageGradientCalculator = GradientCalculatorType::New();
+
+
+  typename DefaultInterpolatorType::Pointer interp =
+    DefaultInterpolatorType::New();
+
+  m_MovingImageInterpolator = static_cast<InterpolatorType*>(
+    interp.GetPointer() );
+
+  m_Metric = NumericTraits<double>::max();
+  m_SumOfSquaredDifference = 0.0;
+  m_NumberOfPixelsProcessed = 0L;
+  m_RMSChange = NumericTraits<double>::max();
+  m_SumOfSquaredChange = 0.0;
+
+  m_MovingImageGradientCalculator = MovingImageGradientCalculatorType::New();
+  m_UseMovingImageGradient = false;
+
+}
+
+
+/*
+ * Standard "PrintSelf" method.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::PrintSelf(std::ostream& os, Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+
+  os << indent << "MovingImageIterpolator: ";
+  os << m_MovingImageInterpolator.GetPointer() << std::endl;
+  os << indent << "FixedImageGradientCalculator: ";
+  os << m_FixedImageGradientCalculator.GetPointer() << std::endl;
+  os << indent << "DenominatorThreshold: ";
+  os << m_DenominatorThreshold << std::endl;
+  os << indent << "IntensityDifferenceThreshold: ";
+  os << m_IntensityDifferenceThreshold << std::endl;
+
+  os << indent << "UseMovingImageGradient: ";
+  os << m_UseMovingImageGradient << std::endl;
+
+  os << indent << "Metric: ";
+  os << m_Metric << std::endl;
+  os << indent << "SumOfSquaredDifference: ";
+  os << m_SumOfSquaredDifference << std::endl;
+  os << indent << "NumberOfPixelsProcessed: ";
+  os << m_NumberOfPixelsProcessed << std::endl;
+  os << indent << "RMSChange: ";
+  os << m_RMSChange << std::endl;
+  os << indent << "SumOfSquaredChange: ";
+  os << m_SumOfSquaredChange << std::endl;
+
+}
+
+
+/**
+ *
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::SetIntensityDifferenceThreshold(double threshold)
+{
+  m_IntensityDifferenceThreshold = threshold;
+}
+
+/**
+ *
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+double
+jwsDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::GetIntensityDifferenceThreshold() const
+{
+  return m_IntensityDifferenceThreshold;
+}
+
+
+/*
+ * Set the function state values before each iteration
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::InitializeIteration()
+{
+  if( !this->GetMovingImage() || !this->GetFixedImage() || !m_MovingImageInterpolator )
+    {
+    itkExceptionMacro( << "MovingImage, FixedImage and/or Interpolator not set" );
+    }
+
+  // cache fixed image information
+  m_FixedImageSpacing    = this->GetFixedImage()->GetSpacing();
+  m_FixedImageOrigin     = this->GetFixedImage()->GetOrigin();
+
+  // compute the normalizer
+  m_Normalizer      = 0.0;
+  for( unsigned int k = 0; k < ImageDimension; k++ )
+    {
+    m_Normalizer += m_FixedImageSpacing[k] * m_FixedImageSpacing[k];
+    }
+  m_Normalizer /= static_cast<double>( ImageDimension );
+
+
+  // setup gradient calculator
+  m_FixedImageGradientCalculator->SetInputImage( this->GetFixedImage() );
+  m_MovingImageGradientCalculator->SetInputImage( this->GetMovingImage() );
+
+  // setup moving image interpolator
+  m_MovingImageInterpolator->SetInputImage( this->GetMovingImage() );
+
+  // initialize metric computation variables
+  m_SumOfSquaredDifference  = 0.0;
+  m_NumberOfPixelsProcessed = 0L;
+  m_SumOfSquaredChange      = 0.0;
+
+}
+
+
+/*
+ * Compute update at a specify neighbourhood
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+typename jwsDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::PixelType
+jwsDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::ComputeUpdate(const NeighborhoodType &it, void * gd,
+                const FloatOffsetType& itkNotUsed(offset))
+{
+
+ //fprintf(stderr,"In jwsDemonsReg Method Update\n");
+
+  PixelType update;
+  unsigned int j;
+
+  IndexType index = it.GetIndex();
+
+  // Get fixed image related information
+  double fixedValue;
+  CovariantVectorType gradient;
+  double gradientSquaredMagnitude = 0;
+
+  // Note: no need to check the index is within
+  // fixed image buffer. This is done by the external filter.
+  fixedValue = (double) this->GetFixedImage()->GetPixel( index );
+
+  // Get moving image related information
+  double movingValue;
+  PointType mappedPoint;
+
+  for( j = 0; j < ImageDimension; j++ )
+    {
+    mappedPoint[j] = double( index[j] ) * m_FixedImageSpacing[j] + 
+      m_FixedImageOrigin[j];
+    mappedPoint[j] += it.GetCenterPixel()[j];
+    }
+  if( m_MovingImageInterpolator->IsInsideBuffer( mappedPoint ) )
+    {
+    movingValue = m_MovingImageInterpolator->Evaluate( mappedPoint );
+    }
+  else
+    {
+    for( j = 0; j < ImageDimension; j++ )
+      {
+      update[j] = 0.0;
+      }
+    return update;
+    }
+
+  // Compute the gradient of either fixed or moving image
+  if( !m_UseMovingImageGradient )
+    {
+    gradient = m_FixedImageGradientCalculator->EvaluateAtIndex( index );
+    }
+  else
+    {
+    gradient = m_MovingImageGradientCalculator->Evaluate( mappedPoint );
+    }
+
+  for( j = 0; j < ImageDimension; j++ )
+    {
+    gradientSquaredMagnitude += vnl_math_sqr( gradient[j] );
+    } 
+
+
+  /**
+   * Compute Update.
+   * In the original equation the denominator is defined as (g-f)^2 + grad_mag^2.
+   * However there is a mismatch in units between the two terms. 
+   * The units for the second term is intensity^2/mm^2 while the
+   * units for the first term is intensity^2. This mismatch is particularly
+   * problematic when the fixed image does not have unit spacing.
+   * In this implemenation, we normalize the first term by a factor K,
+   * such that denominator = (g-f)^2/K + grad_mag^2
+   * where K = mean square spacing to compensate for the mismatch in units.
+   */
+  double speedValue = fixedValue - movingValue;
+  
+  // update the metric
+  GlobalDataStruct *globalData = (GlobalDataStruct *)gd;
+  if ( globalData )
+    {
+    globalData->m_SumOfSquaredDifference += vnl_math_sqr( speedValue );
+    globalData->m_NumberOfPixelsProcessed += 1;
+    }
+
+  double denominator = vnl_math_sqr( speedValue ) / m_Normalizer + 
+    gradientSquaredMagnitude;
+
+  if ( vnl_math_abs(speedValue) < m_IntensityDifferenceThreshold || 
+       denominator < m_DenominatorThreshold )
+    {
+    for( j = 0; j < ImageDimension; j++ )
+      {
+      update[j] = 0.0;
+      }
+    return update;
+    }
+
+  for( j = 0; j < ImageDimension; j++ )
+    {
+    update[j] = speedValue * gradient[j] / denominator;
+    if ( globalData )
+      {
+      globalData->m_SumOfSquaredChange += vnl_math_sqr( update[j] );
+      }
+    }
+
+  return update;
+
+}
+
+/*
+ * Update the metric and release the per-thread-global data.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::ReleaseGlobalDataPointer( void *gd ) const
+{
+  GlobalDataStruct * globalData = (GlobalDataStruct *) gd;
+
+  m_MetricCalculationLock.Lock();
+  m_SumOfSquaredDifference  += globalData->m_SumOfSquaredDifference;
+  m_NumberOfPixelsProcessed += globalData->m_NumberOfPixelsProcessed;
+  m_SumOfSquaredChange += globalData->m_SumOfSquaredChange;
+  if ( m_NumberOfPixelsProcessed )
+    {
+    m_Metric = m_SumOfSquaredDifference / 
+               static_cast<double>( m_NumberOfPixelsProcessed ); 
+    m_RMSChange = vcl_sqrt( m_SumOfSquaredChange / 
+               static_cast<double>( m_NumberOfPixelsProcessed ) ); 
+    }
+  m_MetricCalculationLock.Unlock();
+
+  delete globalData;
+}
+
+
+
+} // end namespace itk
+
+#endif
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsDenseFiniteDifferenceImageFilter.h b/bioimagesuite30_src/DemonsRegistration/itkjwsDenseFiniteDifferenceImageFilter.h
new file mode 100644
index 0000000..9f13017
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsDenseFiniteDifferenceImageFilter.h
@@ -0,0 +1,234 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsDenseFiniteDifferenceImageFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2007/02/08 16:56:10 $
+  Version:   $Revision: 1.23 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkjwsDenseFiniteDifferenceImageFilter_h_
+#define __itkjwsDenseFiniteDifferenceImageFilter_h_
+
+#include "itkFiniteDifferenceImageFilter.h"
+#include "itkMultiThreader.h"
+
+namespace itk {
+
+/**
+ * \class jwsDenseFiniteDifferenceImageFilter
+ *
+ * This filter implements a layer of the finite difference solver hierarchy that
+ * performs ``dense'' iteration, ie. iteration over all pixels in the input and
+ * output at each change calculation and update step. Dense iteration is in
+ * contrast to a ``sparse'' iteration over a subset of the pixels.  See
+ * documentation for FiniteDifferenceImageFilter for an overview of the
+ * iterative finite difference algorithm:
+ *
+ * \par
+ * \f$u_{\mathbf{i}}^{n+1}=u^n_{\mathbf{i}}+\Delta u^n_{\mathbf{i}}\Delta t\f$ 
+ *
+ * \par
+ * The generic code for performing iterations and updates at each time
+ * step is inherited from the parent class.  This class defines an update
+ * buffer for \f$ \Delta \f$ and the methods CalculateChange() and
+ * ApplyUpdate(). These methods are designed to automatically thread their
+ * execution.  \f$ \Delta \f$ is defined as an image of identical size and type 
+ * as the output image.
+ *
+ * \par
+ * As we descend through each layer in the hierarchy, we know more and more
+ * about the specific application of our filter.  At this level, we
+ * have committed to iteration over each pixel in an image. We take advantage
+ * of that knowledge to multithread the iteration and update methods. 
+ *  
+ * \par Inputs and Outputs
+ * This is an image to image filter.  The specific types of the images are not
+ * fixed at this level in the hierarchy.
+ *
+ * \par How to use this class
+ * This filter is only one layer in a branch the finite difference solver
+ * hierarchy.  It does not define the function used in the CalculateChange() and
+ * it does not define the stopping criteria (Halt method).  To use this class,
+ * subclass it to a specific instance that supplies a function and Halt()
+ * method.
+ * 
+ * \ingroup ImageFilters
+ * \sa FiniteDifferenceImageFilter */
+template <class TInputImage, class TOutputImage>
+class ITK_EXPORT jwsDenseFiniteDifferenceImageFilter  
+  : public FiniteDifferenceImageFilter<TInputImage, TOutputImage>
+{
+public:
+  /** Standard class typedefs */
+  typedef jwsDenseFiniteDifferenceImageFilter Self;
+  typedef FiniteDifferenceImageFilter<TInputImage, TOutputImage> Superclass;
+  typedef SmartPointer<Self>  Pointer;
+  typedef SmartPointer<const Self>  ConstPointer;
+  
+  /** Run-time type information (and related methods) */
+  itkTypeMacro(jwsDenseFiniteDifferenceImageFilter, ImageToImageFilter );
+  
+  /** Convenient typedefs */
+  typedef typename Superclass::InputImageType  InputImageType;
+  typedef typename Superclass::OutputImageType OutputImageType;
+  typedef typename Superclass::FiniteDifferenceFunctionType
+   FiniteDifferenceFunctionType;
+  
+  /** Dimensionality of input and output data is assumed to be the same.
+   * It is inherited from the superclass. */
+  itkStaticConstMacro(ImageDimension, unsigned int,Superclass::ImageDimension);
+
+  /** The pixel type of the output image will be used in computations.
+   * Inherited from the superclass. */
+  typedef typename Superclass::PixelType PixelType;
+
+  /** The value type of a time step.  Inherited from the superclass. */
+  typedef typename Superclass::TimeStepType TimeStepType;
+
+  /** The container type for the update buffer. */
+  typedef OutputImageType UpdateBufferType;
+
+#ifdef ITK_USE_CONCEPT_CHECKING
+  /** Begin concept checking */
+  itkConceptMacro(OutputTimesDoubleCheck,
+    (Concept::MultiplyOperator<PixelType, double>));
+  itkConceptMacro(OutputAdditiveOperatorsCheck,
+    (Concept::AdditiveOperators<PixelType>));
+  itkConceptMacro(InputConvertibleToOutputCheck,
+    (Concept::Convertible<typename TInputImage::PixelType, PixelType>));
+  /** End concept checking */
+#endif
+
+protected:
+  jwsDenseFiniteDifferenceImageFilter()
+    { m_UpdateBuffer = UpdateBufferType::New(); }
+  ~jwsDenseFiniteDifferenceImageFilter() {}
+  void PrintSelf(std::ostream& os, Indent indent) const;
+
+  /** A simple method to copy the data from the input to the output.  ( Supports
+   * "read-only" image adaptors in the case where the input image type converts
+   * to a different output image type. )  */
+  virtual void CopyInputToOutput();
+
+  /** This method applies changes from the m_UpdateBuffer to the output using
+   * the ThreadedApplyUpdate() method and a multithreading mechanism.  "dt" is
+   * the time step to use for the update of each pixel. */
+  virtual void ApplyUpdate(TimeStepType dt);
+
+  /** Method to allow subclasses to get direct access to the update
+   * buffer */
+  virtual UpdateBufferType* GetUpdateBuffer()
+    { return m_UpdateBuffer; }
+
+  /** This method populates an update buffer with changes for each pixel in the
+   * output using the ThreadedCalculateChange() method and a multithreading
+   * mechanism. Returns value is a time step to be used for the update. */
+  virtual TimeStepType CalculateChange();
+
+  /** This method allocates storage in m_UpdateBuffer.  It is called from
+   * Superclass::GenerateData(). */
+  virtual void AllocateUpdateBuffer();
+ 
+  /** The type of region used for multithreading */
+  typedef typename UpdateBufferType::RegionType ThreadRegionType;
+
+  /**  Does the actual work of updating the output from the UpdateContainer over
+   *  an output region supplied by the multithreading mechanism.
+   *  \sa ApplyUpdate
+   *  \sa ApplyUpdateThreaderCallback */ 
+  virtual
+  void ThreadedApplyUpdate(TimeStepType dt,
+                           const ThreadRegionType &regionToProcess,
+                           int threadId);
+
+  /** Does the actual work of calculating change over a region supplied by
+   * the multithreading mechanism.
+   * \sa CalculateChange
+   * \sa CalculateChangeThreaderCallback */
+  virtual
+  TimeStepType ThreadedCalculateChange(const ThreadRegionType &regionToProcess,
+                                       int threadId);
+
+private:
+  jwsDenseFiniteDifferenceImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+  /** Structure for passing information into static callback methods.  Used in
+   * the subclasses' threading mechanisms. */
+  struct DenseFDThreadStruct
+  {
+    jwsDenseFiniteDifferenceImageFilter *Filter;
+    TimeStepType TimeStep;
+    TimeStepType *TimeStepList;
+    bool *ValidTimeStepList;
+  };
+    
+  /** This callback method uses ImageSource::SplitRequestedRegion to acquire an
+   * output region that it passes to ThreadedApplyUpdate for processing. */
+  static ITK_THREAD_RETURN_TYPE ApplyUpdateThreaderCallback( void *arg );
+  
+  /** This callback method uses SplitUpdateContainer to acquire a region
+   * which it then passes to ThreadedCalculateChange for processing. */
+  static ITK_THREAD_RETURN_TYPE CalculateChangeThreaderCallback( void *arg );
+ 
+  /** The buffer that holds the updates for an iteration of the algorithm. */
+  typename UpdateBufferType::Pointer m_UpdateBuffer;
+};
+  
+
+}// end namespace itk
+
+// Define instantiation macro for this template.
+#define ITK_TEMPLATE_jwsDenseFiniteDifferenceImageFilter(_, EXPORT, x, y) namespace itk { \
+  _(2(class EXPORT jwsDenseFiniteDifferenceImageFilter< ITK_TEMPLATE_2 x >)) \
+  namespace Templates { typedef jwsDenseFiniteDifferenceImageFilter< ITK_TEMPLATE_2 x > \
+                                            jwsDenseFiniteDifferenceImageFilter##y; } \
+  }
+
+#if ITK_TEMPLATE_EXPLICIT
+# include "Templates/itkjwsDenseFiniteDifferenceImageFilter+-.h"
+#endif
+
+#if ITK_TEMPLATE_TXX
+# include "itkjwsDenseFiniteDifferenceImageFilter.txx"
+#endif
+
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsDenseFiniteDifferenceImageFilter.txx b/bioimagesuite30_src/DemonsRegistration/itkjwsDenseFiniteDifferenceImageFilter.txx
new file mode 100644
index 0000000..f2803cd
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsDenseFiniteDifferenceImageFilter.txx
@@ -0,0 +1,342 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsDenseFiniteDifferenceImageFilter.txx,v $
+  Language:  C++
+  Date:      $Date: 2006/10/27 14:52:31 $
+  Version:   $Revision: 1.29 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkjwsDenseFiniteDifferenceImageFilter_txx_
+#define __itkjwsDenseFiniteDifferenceImageFilter_txx_
+#include "itkjwsDenseFiniteDifferenceImageFilter.h"
+
+#include <list>
+#include "itkImageRegionConstIterator.h"
+#include "itkImageRegionIterator.h"
+#include "itkNumericTraits.h"
+#include "itkNeighborhoodAlgorithm.h"
+#include <stdio.h>
+
+namespace itk {
+
+template <class TInputImage, class TOutputImage>
+void
+jwsDenseFiniteDifferenceImageFilter<TInputImage, TOutputImage>
+::CopyInputToOutput()
+{
+  typename TInputImage::ConstPointer  input  = this->GetInput();
+  typename TOutputImage::Pointer      output = this->GetOutput();
+
+  if ( !input || !output )
+    {
+    itkExceptionMacro(<< "Either input and/or output is NULL.");
+    }
+
+  // Check if we are doing in-place filtering
+  if ( this->GetInPlace() && (typeid(TInputImage) == typeid(TOutputImage)) )
+    {
+    typename TInputImage::Pointer tempPtr = 
+      dynamic_cast<TInputImage *>( output.GetPointer() );
+    if ( tempPtr && tempPtr->GetPixelContainer() == input->GetPixelContainer() )
+      {
+      // the input and output container are the same - no need to copy
+      return;
+      }
+    }
+  
+  ImageRegionConstIterator<TInputImage>  in(input, output->GetRequestedRegion());
+  ImageRegionIterator<TOutputImage> out(output, output->GetRequestedRegion());
+
+  while( ! out.IsAtEnd() )
+    {
+    out.Value() =  static_cast<PixelType>(in.Get());  // Supports input image adaptors only
+    ++in;
+    ++out;
+    }
+}
+
+template <class TInputImage, class TOutputImage>
+void
+jwsDenseFiniteDifferenceImageFilter<TInputImage, TOutputImage>
+::AllocateUpdateBuffer()
+{
+  // The update buffer looks just like the output.
+  typename TOutputImage::Pointer output = this->GetOutput();
+
+  m_UpdateBuffer->SetSpacing(output->GetSpacing());
+  m_UpdateBuffer->SetOrigin(output->GetOrigin());
+  m_UpdateBuffer->SetLargestPossibleRegion(output->GetLargestPossibleRegion());
+  m_UpdateBuffer->SetRequestedRegion(output->GetRequestedRegion());
+  m_UpdateBuffer->SetBufferedRegion(output->GetBufferedRegion());
+  m_UpdateBuffer->Allocate();
+}
+
+template<class TInputImage, class TOutputImage>
+void
+jwsDenseFiniteDifferenceImageFilter<TInputImage, TOutputImage>
+::ApplyUpdate(TimeStepType dt)
+{
+  // Set up for multithreaded processing.
+  DenseFDThreadStruct str;
+  str.Filter = this;
+  str.TimeStep = dt;
+  this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads());
+  this->GetMultiThreader()->SetSingleMethod(this->ApplyUpdateThreaderCallback,
+                                            &str);
+  // Multithread the execution
+  this->GetMultiThreader()->SingleMethodExecute();
+}
+
+template<class TInputImage, class TOutputImage>
+ITK_THREAD_RETURN_TYPE
+jwsDenseFiniteDifferenceImageFilter<TInputImage, TOutputImage>
+::ApplyUpdateThreaderCallback( void * arg )
+{
+  DenseFDThreadStruct * str;
+  int total, threadId, threadCount;
+
+  threadId = ((MultiThreader::ThreadInfoStruct *)(arg))->ThreadID;
+  threadCount = ((MultiThreader::ThreadInfoStruct *)(arg))->NumberOfThreads;
+
+  str = (DenseFDThreadStruct *)(((MultiThreader::ThreadInfoStruct *)(arg))->UserData);
+
+  // Execute the actual method with appropriate output region
+  // first find out how many pieces extent can be split into.
+  // Using the SplitRequestedRegion method from itk::ImageSource.
+  ThreadRegionType splitRegion;
+  total = str->Filter->SplitRequestedRegion(threadId, threadCount,
+                                            splitRegion);
+  
+  if (threadId < total)
+    {
+    str->Filter->ThreadedApplyUpdate(str->TimeStep, splitRegion, threadId);
+    }
+
+  return ITK_THREAD_RETURN_VALUE;
+}
+
+template <class TInputImage, class TOutputImage>
+typename
+jwsDenseFiniteDifferenceImageFilter<TInputImage, TOutputImage>::TimeStepType
+jwsDenseFiniteDifferenceImageFilter<TInputImage, TOutputImage>
+::CalculateChange()
+{
+  int threadCount;
+  TimeStepType dt;
+
+  // Set up for multithreaded processing.
+  DenseFDThreadStruct str;
+  str.Filter = this;
+  str.TimeStep = NumericTraits<TimeStepType>::Zero;  // Not used during the
+  // calculate change step.
+  this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads());
+  this->GetMultiThreader()->SetSingleMethod(this->CalculateChangeThreaderCallback,
+                                            &str);
+
+  // Initialize the list of time step values that will be generated by the
+  // various threads.  There is one distinct slot for each possible thread,
+  // so this data structure is thread-safe.
+  threadCount = this->GetMultiThreader()->GetNumberOfThreads();  
+  str.TimeStepList = new TimeStepType[threadCount];                 
+  str.ValidTimeStepList = new bool[threadCount];
+  for (int i =0; i < threadCount; ++i)
+    {      str.ValidTimeStepList[i] = false;    } 
+
+  // Multithread the execution
+  this->GetMultiThreader()->SingleMethodExecute();
+
+  // Resolve the single value time step to return
+  dt = this->ResolveTimeStep(str.TimeStepList, str.ValidTimeStepList, threadCount);
+  delete [] str.TimeStepList;
+  delete [] str.ValidTimeStepList;
+
+  return  dt;
+}
+
+template <class TInputImage, class TOutputImage>
+ITK_THREAD_RETURN_TYPE
+jwsDenseFiniteDifferenceImageFilter<TInputImage, TOutputImage>
+::CalculateChangeThreaderCallback( void * arg )
+{
+  DenseFDThreadStruct * str;
+  int total, threadId, threadCount;
+
+  threadId = ((MultiThreader::ThreadInfoStruct *)(arg))->ThreadID;
+  threadCount = ((MultiThreader::ThreadInfoStruct *)(arg))->NumberOfThreads;
+
+  str = (DenseFDThreadStruct *)(((MultiThreader::ThreadInfoStruct *)(arg))->UserData);
+
+  // Execute the actual method with appropriate output region
+  // first find out how many pieces extent can be split into.
+  // Using the SplitRequestedRegion method from itk::ImageSource.
+  ThreadRegionType splitRegion;
+
+  total = str->Filter->SplitRequestedRegion(threadId, threadCount,
+                                            splitRegion);
+
+  if (threadId < total)
+    { 
+    str->TimeStepList[threadId]
+      = str->Filter->ThreadedCalculateChange(splitRegion, threadId);
+    str->ValidTimeStepList[threadId] = true;
+    }
+
+  return ITK_THREAD_RETURN_VALUE;  
+}
+
+template <class TInputImage, class TOutputImage>
+void
+jwsDenseFiniteDifferenceImageFilter<TInputImage, TOutputImage>
+::ThreadedApplyUpdate(TimeStepType dt, const ThreadRegionType &regionToProcess,
+                      int)
+{
+  ImageRegionIterator<UpdateBufferType> u(m_UpdateBuffer,    regionToProcess);
+  ImageRegionIterator<OutputImageType>  o(this->GetOutput(), regionToProcess);
+
+  u = u.Begin();
+  o = o.Begin();
+
+  while ( !u.IsAtEnd() )
+    {
+    o.Value() += static_cast<PixelType>(u.Value() * dt);  // no adaptor support here
+    ++o;
+    ++u;
+    }
+}
+
+template <class TInputImage, class TOutputImage>
+typename
+jwsDenseFiniteDifferenceImageFilter<TInputImage, TOutputImage>::TimeStepType
+jwsDenseFiniteDifferenceImageFilter<TInputImage, TOutputImage>
+::ThreadedCalculateChange(const ThreadRegionType &regionToProcess, int)
+{
+
+ //fprintf(stderr,"## jwsDenseFiniteDifference ###");
+
+  typedef typename OutputImageType::RegionType RegionType;
+  typedef typename OutputImageType::SizeType   SizeType;
+  typedef typename OutputImageType::SizeValueType   SizeValueType;
+  typedef typename OutputImageType::IndexType  IndexType;
+  typedef typename OutputImageType::IndexValueType  IndexValueType;
+  typedef typename FiniteDifferenceFunctionType::NeighborhoodType
+    NeighborhoodIteratorType;
+  typedef ImageRegionIterator<UpdateBufferType> UpdateIteratorType;
+
+  typename OutputImageType::Pointer output = this->GetOutput();
+  TimeStepType timeStep;
+  void *globalData;
+
+  // Get the FiniteDifferenceFunction to use in calculations.
+  const typename FiniteDifferenceFunctionType::Pointer df
+    = this->GetDifferenceFunction();
+  const SizeType  radius = df->GetRadius();
+  
+  // Break the input into a series of regions.  The first region is free
+  // of boundary conditions, the rest with boundary conditions.  We operate
+  // on the output region because input has been copied to output.
+  typedef NeighborhoodAlgorithm::ImageBoundaryFacesCalculator<OutputImageType>
+    FaceCalculatorType;
+  typedef typename FaceCalculatorType::FaceListType FaceListType;
+
+  FaceCalculatorType faceCalculator;
+    
+  FaceListType faceList = faceCalculator(output, regionToProcess, radius);
+  typename FaceListType::iterator fIt = faceList.begin();
+
+  // Ask the function object for a pointer to a data structure it
+  // will use to manage any global values it needs.  We'll pass this
+  // back to the function object at each calculation and then
+  // again so that the function object can use it to determine a
+  // time step for this iteration.
+  globalData = df->GetGlobalDataPointer();
+
+  // Process the non-boundary region.
+  NeighborhoodIteratorType nD(radius, output, *fIt);
+  UpdateIteratorType       nU(m_UpdateBuffer,  *fIt);
+  nD.GoToBegin();
+  while( !nD.IsAtEnd() )
+    {       //fprintf(stderr," nnnnnnU::df->ComputeUpdate() at jwsDenseFiniteDifference~.txx\n");
+    nU.Value() = df->ComputeUpdate(nD, globalData);
+    ++nD;
+    ++nU;
+    }
+
+  // Process each of the boundary faces.
+
+  NeighborhoodIteratorType bD;
+  UpdateIteratorType   bU;
+  for (++fIt; fIt != faceList.end(); ++fIt)
+    {
+    bD = NeighborhoodIteratorType(radius, output, *fIt);
+    bU = UpdateIteratorType  (m_UpdateBuffer, *fIt);
+     
+    bD.GoToBegin();
+    bU.GoToBegin();
+    while ( !bD.IsAtEnd() )
+      {     fprintf(stderr," bbbbbbU::df->ComputeUpdate() at jwsDenseFiniteDifference~.txx\n");
+      bU.Value() = df->ComputeUpdate(bD, globalData);
+      ++bD;
+      ++bU;
+      }
+    }
+
+  // Ask the finite difference function to compute the time step for
+  // this iteration.  We give it the global data pointer to use, then
+  // ask it to free the global data memory.
+  timeStep = df->ComputeGlobalTimeStep(globalData);
+  df->ReleaseGlobalDataPointer(globalData);
+
+  return timeStep;
+}
+
+template <class TInputImage, class TOutputImage>
+void
+jwsDenseFiniteDifferenceImageFilter<TInputImage, TOutputImage>
+::PrintSelf(std::ostream& os, Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+
+  
+}
+
+}// end namespace itk
+
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsMultiResolutionPDEDeformableRegistration.h b/bioimagesuite30_src/DemonsRegistration/itkjwsMultiResolutionPDEDeformableRegistration.h
new file mode 100644
index 0000000..1eb6631
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsMultiResolutionPDEDeformableRegistration.h
@@ -0,0 +1,293 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsMultiResolutionPDEDeformableRegistration.h,v $
+  Language:  C++
+  Date:      $Date: 2007/07/31 23:12:20 $
+  Version:   $Revision: 1.29 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkjwsMultiResolutionPDEDeformableRegistration_h
+#define __itkjwsMultiResolutionPDEDeformableRegistration_h
+
+#include "itkImage.h"
+#include "itkImageToImageFilter.h"
+#include "itkjwsPDEDeformableRegistrationFilter.h"
+#include "itkjwsDemonsRegistrationFilter.h"
+#include "itkMultiResolutionPyramidImageFilter.h"
+#include "itkVectorResampleImageFilter.h"
+
+#include <vector>
+
+namespace itk
+{
+/**
+ * \class jwsMultiResolutionPDEDeformableRegistration
+ * \brief Framework for perfoming multi-resolution PDE deformable registration.
+ *
+ * jwsMultiResolutionPDEDeformableRegistration provides a generic framework
+ * to peform multi-resolution deformable registration.
+ *
+ * At each resolution level a PDEDeformableRegistrationFilter is used
+ * to register two images by computing the deformation field which will 
+ * map a moving image onto a fixed image.
+ *
+ * A deformation field is represented as an image whose pixel type is some
+ * vector type with at least N elements, where N is the dimension of
+ * the fixed image. The vector type must support element access via operator
+ * []. It is assumed that the vector elements behave like floating point
+ * scalars.
+ *
+ * The internal PDEDeformationRegistrationFilter can be set using
+ * SetRegistrationFilter. By default a DemonsRegistrationFilter is used.
+ *
+ * The input fixed and moving images are set via methods SetFixedImage
+ * and SetMovingImage respectively. An initial deformation field maybe set via
+ * SetInitialDeformationField or SetInput. If no initial field is set
+ * a zero field is used as the initial condition.
+ *
+ * MultiResolutionPyramidImageFilters are used to downsample the fixed
+ * and moving images. A VectorExpandImageFilter is used to upsample
+ * the deformation as we move from a coarse to fine solution.
+ *
+ * This class is templated over the fixed image type, the moving image type,
+ * and the Deformation Field type.
+ *
+ * \warning This class assumes that the fixed, moving and deformation
+ * field image types all have the same number of dimensions.
+ *
+ * \sa PDEDeformableRegistrationFilter
+ * \sa DemonsRegistrationFilter
+ * \sa MultiResolutionPyramidImageFilter
+ * \sa VectorExpandImageFilter
+ *
+ * The current implementation of this class does not support streaming.
+ *
+ * \ingroup DeformableImageRegistration
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+class ITK_EXPORT jwsMultiResolutionPDEDeformableRegistration :
+    public ImageToImageFilter <TDeformationField, TDeformationField>
+{
+public:
+  /** Standard class typedefs */
+  typedef jwsMultiResolutionPDEDeformableRegistration Self;
+  typedef ImageToImageFilter<TDeformationField, TDeformationField>
+  Superclass;
+  typedef SmartPointer<Self>  Pointer;
+  typedef SmartPointer<const Self>  ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro( jwsMultiResolutionPDEDeformableRegistration, 
+                ImageToImageFilter );
+
+  /** Fixed image type. */
+  typedef TFixedImage FixedImageType;
+  typedef typename FixedImageType::Pointer FixedImagePointer;
+  typedef typename FixedImageType::ConstPointer FixedImageConstPointer;
+
+  /** Moving image type. */
+  typedef TMovingImage MovingImageType;
+  typedef typename MovingImageType::Pointer MovingImagePointer;
+  typedef typename MovingImageType::ConstPointer MovingImageConstPointer;
+
+  /** Deformation field image type. */
+  typedef TDeformationField DeformationFieldType;
+  typedef typename DeformationFieldType::Pointer DeformationFieldPointer;
+
+  /** ImageDimension. */
+  itkStaticConstMacro(ImageDimension, unsigned int,
+                      FixedImageType::ImageDimension);
+
+  /** Internal float image type. */
+  typedef Image<float,itkGetStaticConstMacro(ImageDimension)> FloatImageType;
+
+  /** The internal registration type. */
+  typedef jwsPDEDeformableRegistrationFilter<
+    FloatImageType, FloatImageType, DeformationFieldType > RegistrationType;
+  typedef typename RegistrationType::Pointer RegistrationPointer;
+
+  /** The default registration type. */
+  typedef jwsDemonsRegistrationFilter<
+    FloatImageType, FloatImageType, DeformationFieldType > DefaultRegistrationType;
+
+  /** The fixed multi-resolution image pyramid type. */
+  typedef MultiResolutionPyramidImageFilter<
+    FixedImageType, FloatImageType > FixedImagePyramidType;
+  typedef typename FixedImagePyramidType::Pointer FixedImagePyramidPointer;
+
+  /** The moving multi-resolution image pyramid type. */
+  typedef MultiResolutionPyramidImageFilter<
+    MovingImageType, FloatImageType > MovingImagePyramidType;
+  typedef typename MovingImagePyramidType::Pointer MovingImagePyramidPointer;
+   
+  /** The deformation field expander type. */
+  typedef VectorResampleImageFilter<
+    DeformationFieldType, DeformationFieldType > FieldExpanderType;
+  typedef typename FieldExpanderType::Pointer  FieldExpanderPointer;
+
+  /** Set the fixed image. */
+  virtual void SetFixedImage( const FixedImageType * ptr );
+
+  /** Get the fixed image. */
+  const FixedImageType * GetFixedImage(void) const;
+
+  /** Set the moving image. */
+  virtual void SetMovingImage( const MovingImageType * ptr );
+
+  /** Get the moving image. */
+  const MovingImageType * GetMovingImage(void) const;
+
+  /** Set initial deformation field. */
+  virtual void SetInitialDeformationField( DeformationFieldType * ptr )
+  {
+    this->m_InitialDeformationField=ptr;
+    // itkExceptionMacro( << "This feature not implemented yet"  );
+  }
+
+  /** Get output deformation field. */
+  const DeformationFieldType * GetDeformationField(void)
+  { return this->GetOutput(); }
+
+  /** Get the number of valid inputs.  For
+   * jwsMultiResolutionPDEDeformableRegistration, this checks whether the
+   * fixed and moving images have been set. While
+   * jwsMultiResolutionPDEDeformableRegistration can take a third input
+   * as an initial deformation field, this input is not a required input.
+   */
+  virtual std::vector<SmartPointer<DataObject> >::size_type GetNumberOfValidRequiredInputs() const;
+
+  /** Set the internal registrator. */
+  itkSetObjectMacro( RegistrationFilter, RegistrationType );
+
+  /** Get the internal registrator. */
+  itkGetObjectMacro( RegistrationFilter, RegistrationType );
+  
+  /** Set the fixed image pyramid. */
+  itkSetObjectMacro( FixedImagePyramid, FixedImagePyramidType );
+
+  /** Get the fixed image pyramid. */
+  itkGetObjectMacro( FixedImagePyramid, FixedImagePyramidType );
+
+  /** Set the moving image pyramid. */
+  itkSetObjectMacro( MovingImagePyramid, MovingImagePyramidType );
+
+  /** Get the moving image pyramid. */
+  itkGetObjectMacro( MovingImagePyramid, MovingImagePyramidType );
+
+  /** Set number of multi-resolution levels. */
+  virtual void SetNumberOfLevels( unsigned int num );
+
+  /** Get number of multi-resolution levels. */
+  itkGetConstReferenceMacro( NumberOfLevels, unsigned int );
+
+  /** Get the current resolution level being processed. */
+  itkGetConstReferenceMacro( CurrentLevel, unsigned int );
+
+  /** Set number of iterations per multi-resolution levels. */
+  itkSetVectorMacro( NumberOfIterations, unsigned int, m_NumberOfLevels );
+
+  /** Get number of iterations per multi-resolution levels. */
+  virtual const unsigned int * GetNumberOfIterations() const
+  { return &(m_NumberOfIterations[0]); }
+
+  /** Stop the registration after the current iteration. */
+  virtual void StopRegistration();
+
+protected:
+  jwsMultiResolutionPDEDeformableRegistration();
+  ~jwsMultiResolutionPDEDeformableRegistration() {}
+  void PrintSelf(std::ostream& os, Indent indent) const;
+
+  /** Generate output data by performing the registration
+   * at each resolution level. */
+  virtual void GenerateData();
+
+  /** The current implementation of this class does not support
+   * streaming. As such it requires the largest possible region
+   * for the moving, fixed and input deformation field. */
+  virtual void GenerateInputRequestedRegion();
+
+  /** By default, the output deformation field has the same
+   * spacing, origin and LargestPossibleRegion as the input/initial
+   * deformation field.
+   *
+   * If the initial deformation field is not set, the output
+   * information is copied from the fixed image. */
+  virtual void GenerateOutputInformation();
+
+  /** The current implementation of this class does not supprot
+   * streaming. As such it produces the output for the largest
+   * possible region. */
+  virtual void EnlargeOutputRequestedRegion( DataObject *ptr );
+
+  /** This method returns true to indicate that the registration should
+   * terminate at the current resolution level. */
+  virtual bool Halt();
+
+private:
+  jwsMultiResolutionPDEDeformableRegistration(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+  RegistrationPointer        m_RegistrationFilter;
+  FixedImagePyramidPointer   m_FixedImagePyramid;
+  MovingImagePyramidPointer  m_MovingImagePyramid;
+  FieldExpanderPointer       m_FieldExpander;
+  DeformationFieldPointer    m_InitialDeformationField;
+
+  unsigned int               m_NumberOfLevels;
+  unsigned int               m_CurrentLevel;
+  std::vector<unsigned int>  m_NumberOfIterations;
+
+  /** Flag to indicate user stop registration request. */
+  bool                      m_StopRegistrationFlag;
+
+};
+
+
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkjwsMultiResolutionPDEDeformableRegistration.txx"
+#endif
+
+
+#endif
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsMultiResolutionPDEDeformableRegistration.txx b/bioimagesuite30_src/DemonsRegistration/itkjwsMultiResolutionPDEDeformableRegistration.txx
new file mode 100644
index 0000000..5fbb2ff
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsMultiResolutionPDEDeformableRegistration.txx
@@ -0,0 +1,533 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsMultiResolutionPDEDeformableRegistration.txx,v $
+  Language:  C++
+  Date:      $Date: 2007/07/31 23:12:20 $
+  Version:   $Revision: 1.28 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkjwsMultiResolutionPDEDeformableRegistration_txx
+#define _itkjwsMultiResolutionPDEDeformableRegistration_txx
+#include "itkjwsMultiResolutionPDEDeformableRegistration.h"
+
+#include "itkRecursiveMultiResolutionPyramidImageFilter.h"
+#include "itkImageRegionIterator.h"
+#include "vnl/vnl_math.h"
+#include <stdio.h>
+
+namespace itk {
+
+/*
+ * Default constructor
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::jwsMultiResolutionPDEDeformableRegistration()
+{
+  fprintf(stderr," My MultiResolutionPDE Defor..\n");
+
+  this->SetNumberOfRequiredInputs(2);
+
+  typename DefaultRegistrationType::Pointer registrator =
+    DefaultRegistrationType::New();
+  m_RegistrationFilter = static_cast<RegistrationType*>(
+    registrator.GetPointer() );
+
+  m_MovingImagePyramid  = MovingImagePyramidType::New();
+  m_FixedImagePyramid     = FixedImagePyramidType::New();
+  m_FieldExpander     = FieldExpanderType::New();
+  m_InitialDeformationField = NULL;
+
+  m_NumberOfLevels = 3;
+  m_NumberOfIterations.resize( m_NumberOfLevels );
+  m_FixedImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
+  m_MovingImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
+
+  unsigned int ilevel;
+  for( ilevel = 0; ilevel < m_NumberOfLevels; ilevel++ )
+    {
+    m_NumberOfIterations[ilevel] = 10;
+    }
+  m_CurrentLevel = 0;
+
+  m_StopRegistrationFlag = false;
+
+}
+
+
+/*
+ * Set the moving image image.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::SetMovingImage(
+const MovingImageType * ptr )
+{
+  this->ProcessObject::SetNthInput( 2, const_cast< MovingImageType * >( ptr ) );
+}
+
+
+/*
+ * Get the moving image image.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+const typename jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::MovingImageType *
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::GetMovingImage(void) const
+{
+  return dynamic_cast< const MovingImageType * >
+    ( this->ProcessObject::GetInput( 2 ) );
+}
+
+
+/*
+ * Set the fixed image.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::SetFixedImage(
+const FixedImageType * ptr )
+{
+  this->ProcessObject::SetNthInput( 1, const_cast< FixedImageType * >( ptr ) );
+}
+
+
+/*
+ * Get the fixed image.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+const typename jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::FixedImageType *
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::GetFixedImage(void) const
+{
+  return dynamic_cast< const FixedImageType * >
+    ( this->ProcessObject::GetInput( 1 ) );
+}
+
+/*
+ * 
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+std::vector<SmartPointer<DataObject> >::size_type
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::GetNumberOfValidRequiredInputs() const
+{
+  typename std::vector<SmartPointer<DataObject> >::size_type num = 0;
+
+  if (this->GetFixedImage())
+    {
+    num++;
+    }
+
+  if (this->GetMovingImage())
+    {
+    num++;
+    }
+  
+  return num;
+}
+
+
+/*
+ * Set the number of multi-resolution levels
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::SetNumberOfLevels(
+unsigned int num )
+{
+  if( m_NumberOfLevels != num )
+    {
+    this->Modified();
+    m_NumberOfLevels = num;
+    m_NumberOfIterations.resize( m_NumberOfLevels );
+    }
+
+  if( m_MovingImagePyramid && m_MovingImagePyramid->GetNumberOfLevels() != num )
+    {
+    m_MovingImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
+    }
+  if( m_FixedImagePyramid && m_FixedImagePyramid->GetNumberOfLevels() != num )
+    {
+    m_FixedImagePyramid->SetNumberOfLevels( m_NumberOfLevels );
+    }  
+    
+}
+
+
+/*
+ * Standard PrintSelf method.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::PrintSelf(std::ostream& os, Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+  os << indent << "NumberOfLevels: " << m_NumberOfLevels << std::endl;
+  os << indent << "CurrentLevel: " << m_CurrentLevel << std::endl;
+
+  os << indent << "NumberOfIterations: [";
+  unsigned int ilevel;
+  for( ilevel = 0; ilevel < m_NumberOfLevels - 1; ilevel++ )
+    {
+    os << m_NumberOfIterations[ilevel] << ", ";
+    }
+  os << m_NumberOfIterations[ilevel] << "]" << std::endl;
+  
+  os << indent << "RegistrationFilter: ";
+  os << m_RegistrationFilter.GetPointer() << std::endl;
+  os << indent << "MovingImagePyramid: ";
+  os << m_MovingImagePyramid.GetPointer() << std::endl;
+  os << indent << "FixedImagePyramid: ";
+  os << m_FixedImagePyramid.GetPointer() << std::endl;
+
+  os << indent << "StopRegistrationFlag: ";
+  os << m_StopRegistrationFlag << std::endl;
+
+}
+
+/*
+ * Perform a the deformable registration using a multiresolution scheme
+ * using an internal mini-pipeline
+ *
+ *  ref_pyramid ->  registrator  ->  field_expander --|| tempField
+ * test_pyramid ->           |                              |
+ *                           |                              |
+ *                           --------------------------------    
+ *
+ * A tempField image is used to break the cycle between the
+ * registrator and field_expander.
+ *
+ */                              
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::GenerateData()
+{
+  //DeformationFieldPointer NullDeformationFieldPointer = DeformationFieldType::New();
+  
+  // Check for NULL images and pointers
+  MovingImageConstPointer movingImage = this->GetMovingImage();
+  FixedImageConstPointer  fixedImage = this->GetFixedImage();
+
+  if( !movingImage || !fixedImage )
+    {
+    itkExceptionMacro( << "Fixed and/or moving image not set" );
+    }
+
+  if( !m_MovingImagePyramid || !m_FixedImagePyramid )
+    {
+    itkExceptionMacro( << "Fixed and/or moving pyramid not set" );
+    }
+
+  if( !m_RegistrationFilter )
+    {
+    itkExceptionMacro( << "Registration filter not set" );
+    }
+  
+  // Create the image pyramids.
+  m_MovingImagePyramid->SetInput( movingImage );
+  m_MovingImagePyramid->UpdateLargestPossibleRegion();
+
+  m_FixedImagePyramid->SetInput( fixedImage );
+  m_FixedImagePyramid->UpdateLargestPossibleRegion();
+ 
+  // Initializations
+  m_CurrentLevel = 0;
+  m_StopRegistrationFlag = false;
+
+  unsigned int movingLevel = vnl_math_min( (int) m_CurrentLevel, 
+    (int) m_MovingImagePyramid->GetNumberOfLevels() );
+
+  unsigned int fixedLevel = vnl_math_min( (int) m_CurrentLevel, 
+    (int) m_FixedImagePyramid->GetNumberOfLevels() );
+
+  DeformationFieldPointer tempField = this->m_InitialDeformationField;
+  bool lastShrinkFactorsAllOnes = false;
+
+  while ( !this->Halt() )
+    {
+   
+    if( tempField.IsNull() )
+      {
+      m_RegistrationFilter->SetInitialDeformationField( NULL );
+      }
+    else
+      {
+      // Resample the field to be the same size as the fixed image
+      // at the current level
+      m_FieldExpander->SetInput( tempField );
+      
+      typename FloatImageType::Pointer fi = 
+        m_FixedImagePyramid->GetOutput( fixedLevel );
+      m_FieldExpander->SetSize( 
+        fi->GetLargestPossibleRegion().GetSize() );
+      m_FieldExpander->SetOutputStartIndex(
+        fi->GetLargestPossibleRegion().GetIndex() );
+      m_FieldExpander->SetOutputOrigin( fi->GetOrigin() );
+      m_FieldExpander->SetOutputSpacing( fi->GetSpacing());
+
+      m_FieldExpander->UpdateLargestPossibleRegion();
+      m_FieldExpander->SetInput( NULL );
+      tempField = m_FieldExpander->GetOutput();
+      tempField->DisconnectPipeline();
+
+      m_RegistrationFilter->SetInitialDeformationField( tempField );
+
+      }
+
+    // setup registration filter and pyramids 
+    m_RegistrationFilter->SetMovingImage( m_MovingImagePyramid->GetOutput(movingLevel) );
+    m_RegistrationFilter->SetFixedImage( m_FixedImagePyramid->GetOutput(fixedLevel) );
+
+    m_RegistrationFilter->SetNumberOfIterations(
+      m_NumberOfIterations[m_CurrentLevel] );
+
+    // cache shrink factors for computing the next expand factors.
+    lastShrinkFactorsAllOnes = true;
+    for( unsigned int idim = 0; idim < ImageDimension; idim++ )
+      {
+      if ( m_FixedImagePyramid->GetSchedule()[fixedLevel][idim] > 1 )
+        {
+        lastShrinkFactorsAllOnes = false;
+        break;
+        }
+      }
+
+    // compute new deformation field
+    m_RegistrationFilter->UpdateLargestPossibleRegion();
+    tempField = m_RegistrationFilter->GetOutput();
+    tempField->DisconnectPipeline();
+
+    // Increment level counter.  
+    m_CurrentLevel++;
+    movingLevel = vnl_math_min( (int) m_CurrentLevel, 
+      (int) m_MovingImagePyramid->GetNumberOfLevels() );
+    fixedLevel = vnl_math_min( (int) m_CurrentLevel, 
+      (int) m_FixedImagePyramid->GetNumberOfLevels() );
+
+    // Invoke an iteration event.
+    this->InvokeEvent( IterationEvent() );
+
+    // We can release data from pyramid which are no longer required.
+    if ( movingLevel > 0 )
+      {
+      m_MovingImagePyramid->GetOutput( movingLevel - 1 )->ReleaseData();
+      }
+    if( fixedLevel > 0 )
+      {
+      m_FixedImagePyramid->GetOutput( fixedLevel - 1 )->ReleaseData();
+      }
+
+    } // while not Halt()
+
+    if( !lastShrinkFactorsAllOnes )
+      {
+      // Some of the last shrink factors are not one
+      // graft the output of the expander filter to
+      // to output of this filter
+
+      // resample the field to the same size as the fixed image
+      m_FieldExpander->SetInput( tempField );
+      m_FieldExpander->SetSize( 
+        fixedImage->GetLargestPossibleRegion().GetSize() );
+      m_FieldExpander->SetOutputStartIndex(
+        fixedImage->GetLargestPossibleRegion().GetIndex() );
+      m_FieldExpander->SetOutputOrigin( fixedImage->GetOrigin() );
+      m_FieldExpander->SetOutputSpacing( fixedImage->GetSpacing());
+
+      m_FieldExpander->UpdateLargestPossibleRegion();
+      this->GraftOutput( m_FieldExpander->GetOutput() );
+      }
+    else
+      {
+      // all the last shrink factors are all ones
+      // graft the output of registration filter to
+      // to output of this filter
+      this->GraftOutput( tempField );
+      }
+
+    // Release memory
+    m_FieldExpander->SetInput( NULL );
+    m_FieldExpander->GetOutput()->ReleaseData();
+    m_RegistrationFilter->SetInput( NULL );
+    m_RegistrationFilter->GetOutput()->ReleaseData();
+
+}
+
+
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::StopRegistration()
+{
+  m_RegistrationFilter->StopRegistration();
+  m_StopRegistrationFlag = true;
+}
+
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+bool
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::Halt()
+{
+  // Halt the registration after the user-specified number of levels
+  if (m_NumberOfLevels != 0)
+  {
+  this->UpdateProgress( static_cast<float>( m_CurrentLevel ) /
+                        static_cast<float>( m_NumberOfLevels ) );
+  }
+
+  if ( m_CurrentLevel >= m_NumberOfLevels )
+    {
+    return true;
+    }
+  if ( m_StopRegistrationFlag )
+    {
+    return true;
+    }
+  else
+    { 
+    return false; 
+    }
+
+}
+
+
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::GenerateOutputInformation()
+{
+
+ typename DataObject::Pointer output;
+
+ if( this->GetInput(0) )
+  {
+  // Initial deformation field is set.
+  // Copy information from initial field.
+  this->Superclass::GenerateOutputInformation();
+
+  }
+ else if( this->GetFixedImage() )
+  {
+  // Initial deforamtion field is not set. 
+  // Copy information from the fixed image.
+  for (unsigned int idx = 0; idx < 
+    this->GetNumberOfOutputs(); ++idx )
+    {
+    output = this->GetOutput(idx);
+    if (output)
+      {
+      output->CopyInformation(this->GetFixedImage());
+      }  
+    }
+
+  }
+
+}
+
+
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::GenerateInputRequestedRegion()
+{
+
+  // call the superclass's implementation
+  Superclass::GenerateInputRequestedRegion();
+
+  // request the largest possible region for the moving image
+  MovingImagePointer movingPtr = 
+    const_cast< MovingImageType * >( this->GetMovingImage() );
+  if( movingPtr )
+    {
+    movingPtr->SetRequestedRegionToLargestPossibleRegion();
+    }
+  
+  // just propagate up the output requested region for
+  // the fixed image and initial deformation field.
+  DeformationFieldPointer inputPtr = 
+      const_cast< DeformationFieldType * >( this->GetInput() );
+  DeformationFieldPointer outputPtr = this->GetOutput();
+  FixedImagePointer fixedPtr = 
+        const_cast< FixedImageType *>( this->GetFixedImage() );
+
+  if( inputPtr )
+    {
+    inputPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
+    }
+
+  if( fixedPtr )
+    {
+    fixedPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
+    }
+
+}
+
+
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsMultiResolutionPDEDeformableRegistration<TFixedImage,TMovingImage,TDeformationField>
+::EnlargeOutputRequestedRegion(
+DataObject * ptr )
+{
+  // call the superclass's implementation
+  Superclass::EnlargeOutputRequestedRegion( ptr );
+
+  // set the output requested region to largest possible.
+  DeformationFieldType * outputPtr;
+  outputPtr = dynamic_cast<DeformationFieldType*>( ptr );
+
+  if( outputPtr )
+    {
+    outputPtr->SetRequestedRegionToLargestPossibleRegion();
+    }
+
+}
+
+
+} // end namespace itk
+
+#endif
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsPDEDeformableRegistrationFilter.h b/bioimagesuite30_src/DemonsRegistration/itkjwsPDEDeformableRegistrationFilter.h
new file mode 100644
index 0000000..c70f706
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsPDEDeformableRegistrationFilter.h
@@ -0,0 +1,326 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsPDEDeformableRegistrationFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2004/09/29 14:20:40 $
+  Version:   $Revision: 1.23 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkjwsPDEDeformableRegistrationFilter_h_
+#define _itkjwsPDEDeformableRegistrationFilter_h_
+
+#include "itkjwsDenseFiniteDifferenceImageFilter.h"
+#include "itkjwsPDEDeformableRegistrationFunction.h"
+
+namespace itk {
+
+/**
+ * \class jwsPDEDeformableRegistrationFilter
+ * \brief Deformably register two images using a PDE algorithm.
+ *
+ * PDEDeformableRegistrationFilter is a base case for filter implementing
+ * a PDE deformable algorithm that register two images by computing the 
+ * deformation field which will map a moving image onto a fixed image.
+ *
+ * A deformation field is represented as a image whose pixel type is some
+ * vector type with at least N elements, where N is the dimension of
+ * the fixed image. The vector type must support element access via operator
+ * []. It is assumed that the vector elements behave like floating point
+ * scalars.
+ *
+ * This class is templated over the fixed image type, moving image type
+ * and the deformation Field type.
+ *
+ * The input fixed and moving images are set via methods SetFixedImage
+ * and SetMovingImage respectively. An initial deformation field maybe set via
+ * SetInitialDeformationField or SetInput. If no initial field is set,
+ * a zero field is used as the initial condition.
+ *
+ * The output deformation field can be obtained via methods GetOutput
+ * or GetDeformationField.
+ *
+ * The PDE algorithm is run for a user defined number of iterations.
+ * Typically the PDE algorithm requires period Gaussin smoothing of the
+ * deformation field to enforce an elastic-like condition. The amount
+ * of smoothing is governed by a set of user defined standard deviations
+ * (one for each dimension).
+ *
+ * In terms of memory, this filter keeps two internal buffers: one for storing
+ * the intermediate updates to the field and one for double-buffering when
+ * smoothing the deformation field. Both buffers are the same type and size as the
+ * output deformation field.
+ *
+ * This class make use of the finite difference solver hierarchy. Update
+ * for each iteration is computed using a PDEDeformableRegistrationFunction.
+ *
+ * \warning This filter assumes that the fixed image type, moving image type
+ * and deformation field type all have the same number of dimensions.
+ * 
+ * \sa PDEDeformableRegistrationFunction.
+ * \ingroup DeformableImageRegistration
+ */
+template<class TFixedImage, class TMovingImage, class TDeformationField>
+class ITK_EXPORT jwsPDEDeformableRegistrationFilter : 
+    public jwsDenseFiniteDifferenceImageFilter<TDeformationField,TDeformationField>
+{
+public:
+  /** Standard class typedefs. */
+  typedef jwsPDEDeformableRegistrationFilter    Self;
+  typedef jwsDenseFiniteDifferenceImageFilter<
+    TDeformationField,TDeformationField>    Superclass;
+  typedef SmartPointer<Self> Pointer;
+  typedef SmartPointer<const Self> ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods) */
+  itkTypeMacro( jwsPDEDeformableRegistrationFilter, 
+                jwsDenseFiniteDifferenceImageFilter );
+
+  /** FixedImage image type. */
+  typedef TFixedImage   FixedImageType;
+  typedef typename FixedImageType::Pointer  FixedImagePointer;
+  typedef typename FixedImageType::ConstPointer  FixedImageConstPointer;
+
+  /** MovingImage image type. */
+  typedef TMovingImage    MovingImageType;
+  typedef typename MovingImageType::Pointer  MovingImagePointer;
+  typedef typename MovingImageType::ConstPointer  MovingImageConstPointer;
+  
+  /** Deformation field type. */
+  typedef TDeformationField    DeformationFieldType;
+  typedef typename DeformationFieldType::Pointer  DeformationFieldPointer;
+
+  /** Types inherithed from the superclass */
+  typedef typename Superclass::OutputImageType    OutputImageType;
+
+  /** FiniteDifferenceFunction type. */
+  typedef typename Superclass::FiniteDifferenceFunctionType
+  FiniteDifferenceFunctionType;
+
+  /** jwsPDEDeformableRegistrationFilterFunction type. */
+  typedef jwsPDEDeformableRegistrationFunction<FixedImageType,MovingImageType,
+                                            DeformationFieldType>  jwsPDEDeformableRegistrationFunctionType;
+
+  /** Inherit some enums and typedefs from the superclass. */
+  itkStaticConstMacro(ImageDimension, unsigned int,
+                      Superclass::ImageDimension);
+
+  /** Set the fixed image. */
+  void SetFixedImage( const FixedImageType * ptr );
+
+  /** Get the fixed image. */
+  const FixedImageType * GetFixedImage(void) const;
+
+  /** Set the moving image. */
+  void SetMovingImage( const MovingImageType * ptr );
+
+  /** Get the moving image. */
+  const MovingImageType * GetMovingImage(void) const;
+
+  /** Set initial deformation field. */
+  void SetInitialDeformationField( DeformationFieldType * ptr )
+  { this->SetInput( ptr ); }
+
+  /** Get output deformation field. */
+  DeformationFieldType * GetDeformationField()
+  { return this->GetOutput(); }
+
+  /** Get the number of valid inputs.  For jwsPDEDeformableRegistration,
+   * this checks whether the fixed and moving images have been
+   * set. While jwsPDEDeformableRegistration can take a third input as an
+   * initial deformation field, this input is not a required input.
+   */
+  virtual std::vector<SmartPointer<DataObject> >::size_type GetNumberOfValidRequiredInputs() const;
+
+  /** Set/Get whether the deformation field is smoothed 
+   * (regularized). Smoothing the deformation yields a solution
+   * elastic in nature. If SmoothDeformationField is on, then the
+   * deformation field is smoothed with a Gaussian whose standard
+   * deviations are specified with SetStandardDeviations() */
+  itkSetMacro( SmoothDeformationField, bool );
+  itkGetMacro( SmoothDeformationField, bool );
+  itkBooleanMacro( SmoothDeformationField );
+  
+  /** Set the Gaussian smoothing standard deviations for the
+   * deformation field. The values are set with respect to pixel
+   * coordinates. */
+  itkSetVectorMacro( StandardDeviations, double, ImageDimension );
+  virtual void SetStandardDeviations( double value );
+
+  /** Get the Gaussian smoothing standard deviations use for smoothing
+   * the deformation field. */
+  const double * GetStandardDeviations(void) 
+    { return (double *) m_StandardDeviations; }
+
+  /** Set/Get whether the update field is smoothed 
+   * (regularized). Smoothing the update field yields a solution
+   * viscous in nature. If SmoothUpdateField is on, then the
+   * update field is smoothed with a Gaussian whose standard
+   * deviations are specified with SetUpdateFieldStandardDeviations() */
+  itkSetMacro( SmoothUpdateField, bool );
+  itkGetMacro( SmoothUpdateField, bool );
+  itkBooleanMacro( SmoothUpdateField );
+  
+  /** Set the Gaussian smoothing standard deviations for the update
+   * field. The values are set with respect to pixel coordinates. */
+  itkSetVectorMacro( UpdateFieldStandardDeviations, double, ImageDimension );
+  virtual void SetUpdateFieldStandardDeviations( double value );
+
+  /** Get the Gaussian smoothing standard deviations used for
+   * smoothing the update field. */
+  const double * GetUpdateFieldStandardDeviations(void) 
+    { return (double *) m_UpdateFieldStandardDeviations; }
+  
+  
+
+  /** Stop the registration after the current iteration. */
+  virtual void StopRegistration()
+    { m_StopRegistrationFlag = true; }
+
+  /** Set/Get the desired maximum error of the Guassian kernel approximate. 
+   * \sa GaussianOperator. */
+  itkSetMacro( MaximumError, double );
+  itkGetMacro( MaximumError, double );
+
+  /** Set/Get the desired limits of the Gaussian kernel width.
+   * \sa GaussianOperator. */
+  itkSetMacro( MaximumKernelWidth, unsigned int );
+  itkGetMacro( MaximumKernelWidth, unsigned int );
+  
+
+protected:
+  jwsPDEDeformableRegistrationFilter();
+  ~jwsPDEDeformableRegistrationFilter() {}
+  void PrintSelf(std::ostream& os, Indent indent) const;
+
+  /** Supplies the halting criteria for this class of filters.  The
+   * algorithm will stop after a user-specified number of iterations. */
+  virtual bool Halt()
+    {
+
+    if ( m_StopRegistrationFlag )
+      {
+      return true;
+      }
+
+    return this->Superclass::Halt();
+    }
+
+  /** A simple method to copy the data from the input to the output.
+   * If the input does not exist, a zero field is written to the output. */
+  virtual void CopyInputToOutput();
+
+  /** Initialize the state of filter and equation before each iteration.
+   * Progress feeback is implemented as part of this method. */
+  virtual void InitializeIteration();
+
+  /** Utility to smooth the deformation field (represented in the Output)
+   * using a Guassian operator. The amount of smoothing can be specified
+   * by setting the StandardDeviations. */
+  virtual void SmoothDeformationField();
+
+  /** Utility to smooth the UpdateBuffer using a Gaussian operator.
+   * The amount of smoothing can be specified by setting the
+   * UpdateFieldStandardDeviations. */
+  virtual void SmoothUpdateField();
+  
+  /** This method is called after the solution has been generated. In this case,
+   * the filter release the memory of the internal buffers. */
+  virtual void PostProcessOutput();
+
+  /** This method is called before iterating the solution. */
+  virtual void Initialize();
+
+  /** By default the output deformation field has the same Spacing, Origin
+   * and LargestPossibleRegion as the input/initial deformation field.  If
+   * the initial deformation field is not set, the output information is
+   * copied from the fixed image. */
+  virtual void GenerateOutputInformation();
+
+  /** It is difficult to compute in advance the input moving image region
+   * required to compute the requested output region. Thus the safest
+   * thing to do is to request for the whole moving image.
+   *
+   * For the fixed image and deformation field, the input requested region
+   * set to be the same as that of the output requested region. */
+  virtual void GenerateInputRequestedRegion();
+
+private:
+  jwsPDEDeformableRegistrationFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+  /** Standard deviation for Gaussian smoothing */
+  double                   m_StandardDeviations[ImageDimension];
+  double                   m_UpdateFieldStandardDeviations[ImageDimension];
+
+  /** Modes to control smoothing of the update and deformation fields */
+  bool m_SmoothDeformationField;
+  bool m_SmoothUpdateField;
+  
+  
+  /** Temporary deformation field use for smoothing the
+   * the deformation field. */
+  DeformationFieldPointer   m_TempField;
+
+private:
+  /** Maximum error for Gaussian operator approximation. */
+  double                    m_MaximumError;
+
+  /** Limits of Guassian kernel width. */
+  unsigned int              m_MaximumKernelWidth;
+
+  /** Flag to indicate user stop registration request. */
+  bool                      m_StopRegistrationFlag;
+
+};
+
+
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkjwsPDEDeformableRegistrationFilter.txx"
+#endif
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsPDEDeformableRegistrationFilter.txx b/bioimagesuite30_src/DemonsRegistration/itkjwsPDEDeformableRegistrationFilter.txx
new file mode 100644
index 0000000..75ba4aa
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsPDEDeformableRegistrationFilter.txx
@@ -0,0 +1,574 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsPDEDeformableRegistrationFilter.txx,v $
+  Language:  C++
+  Date:      $Date: 2004/12/21 22:47:28 $
+  Version:   $Revision: 1.30 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkjwsPDEDeformableRegistrationFilter_txx_
+#define _itkjwsPDEDeformableRegistrationFilter_txx_
+
+#include "itkjwsPDEDeformableRegistrationFilter.h"
+
+#include "itkExceptionObject.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageLinearIteratorWithIndex.h"
+#include "itkDataObject.h"
+
+#include "itkGaussianOperator.h"
+#include "itkVectorNeighborhoodOperatorImageFilter.h"
+
+#include "vnl/vnl_math.h"
+
+namespace itk {
+
+/*
+ * Default constructor
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::jwsPDEDeformableRegistrationFilter()
+{
+ 
+  this->SetNumberOfRequiredInputs(2);
+
+  this->SetNumberOfIterations(10);
+ 
+  unsigned int j;
+  for( j = 0; j < ImageDimension; j++ )
+    {
+    m_StandardDeviations[j] = 1.0;
+    m_UpdateFieldStandardDeviations[j] = 1.0;
+    }
+
+  m_TempField = DeformationFieldType::New();
+  m_MaximumError = 0.1;
+  m_MaximumKernelWidth = 30;
+  m_StopRegistrationFlag = false;
+
+  m_SmoothDeformationField = true;
+  m_SmoothUpdateField = false;
+}
+
+
+/*
+ * Set the fixed image.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::SetFixedImage(
+  const FixedImageType * ptr )
+{
+  this->ProcessObject::SetNthInput( 1, const_cast< FixedImageType * >( ptr ) );
+}
+
+
+/*
+ * Get the fixed image.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+const typename jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::FixedImageType *
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::GetFixedImage() const
+{
+  return dynamic_cast< const FixedImageType * >
+    ( this->ProcessObject::GetInput( 1 ) );
+}
+
+
+/*
+ * Set the moving image.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::SetMovingImage(
+  const MovingImageType * ptr )
+{
+  this->ProcessObject::SetNthInput( 2, const_cast< MovingImageType * >( ptr ) );
+}
+
+
+/*
+ * Get the moving image.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+const typename jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::MovingImageType *
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::GetMovingImage() const
+{
+  return dynamic_cast< const MovingImageType * >
+    ( this->ProcessObject::GetInput( 2 ) );
+}
+
+
+/*
+ * 
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+std::vector<SmartPointer<DataObject> >::size_type
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::GetNumberOfValidRequiredInputs() const
+{
+  typename std::vector<SmartPointer<DataObject> >::size_type num = 0;
+
+  if (this->GetFixedImage())
+    {
+    num++;
+    }
+
+  if (this->GetMovingImage())
+    {
+    num++;
+    }
+  
+  return num;
+}
+
+
+/*
+ * Set the standard deviations.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::SetStandardDeviations(
+  double value )
+{
+
+  unsigned int j;
+  for( j = 0; j < ImageDimension; j++ )
+    {
+    if( value != m_StandardDeviations[j] )
+      {
+      break;
+      }
+    }
+  if( j < ImageDimension )
+    {
+    this->Modified();
+    for( j = 0; j < ImageDimension; j++ )
+      {
+      m_StandardDeviations[j] = value;
+      }
+    }
+
+}
+
+/*
+ * Set the standard deviations.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::SetUpdateFieldStandardDeviations(
+  double value )
+{
+
+  unsigned int j;
+  for( j = 0; j < ImageDimension; j++ )
+    {
+    if( value != m_UpdateFieldStandardDeviations[j] )
+      {
+      break;
+      }
+    }
+  if( j < ImageDimension )
+    {
+    this->Modified();
+    for( j = 0; j < ImageDimension; j++ )
+      {
+      m_UpdateFieldStandardDeviations[j] = value;
+      }
+    }
+
+}
+
+
+/*
+ * Standard PrintSelf method.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::PrintSelf(std::ostream& os, Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+  os << indent << "Smooth deformation field: "
+     << (m_SmoothDeformationField ? "on" : "off") << std::endl;
+  os << indent << "Standard deviations: [";
+  unsigned int j;
+  for( j = 0; j < ImageDimension - 1; j++ )
+    {
+    os << m_StandardDeviations[j] << ", ";
+    }
+  os << m_StandardDeviations[j] << "]" << std::endl;
+  os << indent << "Smooth update field: "
+     << (m_SmoothUpdateField ? "on" : "off") << std::endl;
+  os << indent << "Update field standard deviations: [";
+  for( j = 0; j < ImageDimension - 1; j++ )
+    {
+    os << m_UpdateFieldStandardDeviations[j] << ", ";
+    }
+  os << m_UpdateFieldStandardDeviations[j] << "]" << std::endl;
+  os << indent << "StopRegistrationFlag: ";
+  os << m_StopRegistrationFlag << std::endl;
+  os << indent << "MaximumError: ";
+  os << m_MaximumError << std::endl;
+  os << indent << "MaximumKernelWidth: ";
+  os << m_MaximumKernelWidth << std::endl; 
+
+}
+
+
+/*
+ * Set the function state values before each iteration
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::InitializeIteration()
+{
+
+  MovingImageConstPointer movingPtr = this->GetMovingImage();
+  FixedImageConstPointer fixedPtr = this->GetFixedImage();
+
+  if( !movingPtr || !fixedPtr )
+    {
+    itkExceptionMacro( << "Fixed and/or moving image not set" );
+    }
+
+  // update variables in the equation object
+  jwsPDEDeformableRegistrationFunctionType *f = 
+    dynamic_cast<jwsPDEDeformableRegistrationFunctionType *>
+    (this->GetDifferenceFunction().GetPointer());
+
+  if ( !f )
+    {
+    itkExceptionMacro(<<"FiniteDifferenceFunction not of type jwsPDEDeformableRegistrationFilterFunction");
+    }
+
+  f->SetFixedImage( fixedPtr );
+  f->SetMovingImage( movingPtr );
+
+  this->Superclass::InitializeIteration();           
+
+}
+
+
+/*
+ * Override the default implemenation for the case when the 
+ * initial deformation is not set.
+ * If the initial deformation is not set, the output is
+ * fill with zero vectors.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::CopyInputToOutput()
+{
+
+  typename Superclass::InputImageType::ConstPointer  inputPtr  = this->GetInput();
+  
+  if( inputPtr )
+    {
+    this->Superclass::CopyInputToOutput();
+    }
+  else
+    {
+    typename Superclass::PixelType zeros;
+    for( unsigned int j = 0; j < ImageDimension; j++ )
+      {
+      zeros[j] = 0;
+      }
+
+    typename OutputImageType::Pointer output = this->GetOutput();
+  
+    ImageRegionIterator<OutputImageType> out(output, output->GetRequestedRegion());
+
+    while( ! out.IsAtEnd() )
+      {
+      out.Value() =  zeros;
+      ++out;
+      }
+    }
+}
+
+
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::GenerateOutputInformation()
+{
+
+  typename DataObject::Pointer output;
+
+  if( this->GetInput(0) )
+    {
+    // Initial deformation field is set.
+    // Copy information from initial field.
+    this->Superclass::GenerateOutputInformation();
+
+    }
+  else if( this->GetFixedImage() )
+    {
+    // Initial deforamtion field is not set. 
+    // Copy information from the fixed image.
+    for (unsigned int idx = 0; idx < 
+           this->GetNumberOfOutputs(); ++idx )
+      {
+      output = this->GetOutput(idx);
+      if (output)
+        {
+        output->CopyInformation(this->GetFixedImage());
+        }  
+      }
+
+    }
+
+}
+
+
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::GenerateInputRequestedRegion()
+{
+
+  // call the superclass's implementation
+  Superclass::GenerateInputRequestedRegion();
+
+  // request the largest possible region for the moving image
+  MovingImagePointer movingPtr = 
+    const_cast< MovingImageType * >( this->GetMovingImage() );
+  if( movingPtr )
+    {
+    movingPtr->SetRequestedRegionToLargestPossibleRegion();
+    }
+  
+  // just propagate up the output requested region for
+  // the fixed image and initial deformation field.
+  DeformationFieldPointer inputPtr = 
+    const_cast< DeformationFieldType * >( this->GetInput() );
+  DeformationFieldPointer outputPtr = this->GetOutput();
+  FixedImagePointer fixedPtr = 
+    const_cast< FixedImageType *>( this->GetFixedImage() );
+
+  if( inputPtr )
+    {
+    inputPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
+    }
+
+  if( fixedPtr )
+    {
+    fixedPtr->SetRequestedRegion( outputPtr->GetRequestedRegion() );
+    }
+
+}
+
+
+/*
+ * Release memory of internal buffers
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::PostProcessOutput()
+{
+  this->Superclass::PostProcessOutput();
+  m_TempField->Initialize();
+}
+
+
+/*
+ * Initialize flags
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::Initialize()
+{
+  this->Superclass::Initialize();
+  m_StopRegistrationFlag = false;
+}
+
+
+/*
+ * Smooth deformation using a separable Gaussian kernel
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::SmoothDeformationField()
+{
+
+  DeformationFieldPointer field = this->GetOutput();
+
+  // copy field to TempField
+  m_TempField->SetSpacing( field->GetSpacing() );
+  m_TempField->SetOrigin( field->GetOrigin() );
+  m_TempField->SetLargestPossibleRegion( 
+    field->GetLargestPossibleRegion() );
+  m_TempField->SetRequestedRegion(
+    field->GetRequestedRegion() );
+  m_TempField->SetBufferedRegion( field->GetBufferedRegion() );
+  m_TempField->Allocate();
+  
+  typedef typename DeformationFieldType::PixelType VectorType;
+  typedef typename VectorType::ValueType           ScalarType;
+  typedef GaussianOperator<ScalarType,ImageDimension> OperatorType;
+  typedef VectorNeighborhoodOperatorImageFilter<
+    DeformationFieldType,
+    DeformationFieldType> SmootherType;
+
+  OperatorType * oper = new OperatorType;
+  typename SmootherType::Pointer smoother = SmootherType::New();
+
+  typedef typename DeformationFieldType::PixelContainerPointer 
+    PixelContainerPointer;
+  PixelContainerPointer swapPtr;
+
+  // graft the output field onto the mini-pipeline
+  smoother->GraftOutput( m_TempField );
+
+  for( unsigned int j = 0; j < ImageDimension; j++ )
+    {
+    // smooth along this dimension
+    oper->SetDirection( j );
+    double variance = vnl_math_sqr( m_StandardDeviations[j] );
+    oper->SetVariance( variance );
+    oper->SetMaximumError( m_MaximumError );
+    oper->SetMaximumKernelWidth( m_MaximumKernelWidth );
+    oper->CreateDirectional();
+
+    // todo: make sure we only smooth within the buffered region
+    smoother->SetOperator( *oper );
+    smoother->SetInput( field );
+    smoother->Update();
+
+    if ( j < ImageDimension - 1 )
+      {
+      // swap the containers
+      swapPtr = smoother->GetOutput()->GetPixelContainer();
+      smoother->GraftOutput( field );
+      field->SetPixelContainer( swapPtr );
+      smoother->Modified();
+      }
+
+    }
+
+  // graft the output back to this filter
+  m_TempField->SetPixelContainer( field->GetPixelContainer() );
+  this->GraftOutput( smoother->GetOutput() );
+
+  delete oper;
+
+}
+
+/*
+ * Smooth deformation using a separable Gaussian kernel
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsPDEDeformableRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::SmoothUpdateField()
+{
+  // The update buffer will be overwritten with new data.
+  DeformationFieldPointer field = this->GetUpdateBuffer();
+
+  typedef typename DeformationFieldType::PixelType VectorType;
+  typedef typename VectorType::ValueType           ScalarType;
+  typedef GaussianOperator<ScalarType,ImageDimension> OperatorType;
+  typedef VectorNeighborhoodOperatorImageFilter<
+    DeformationFieldType,
+    DeformationFieldType> SmootherType;
+  
+  OperatorType opers[ImageDimension];
+  typename SmootherType::Pointer smoothers[ImageDimension];
+
+  for( unsigned int j = 0; j < ImageDimension; j++ )
+    {
+    // smooth along this dimension
+    opers[j].SetDirection( j );
+    double variance = vnl_math_sqr( this->GetUpdateFieldStandardDeviations()[j] );
+    //double variance = vnl_math_sqr( 1.0 );
+    opers[j].SetVariance( variance );
+    opers[j].SetMaximumError( this->GetMaximumError() );
+    opers[j].SetMaximumKernelWidth( this->GetMaximumKernelWidth() );
+    opers[j].CreateDirectional();
+
+    smoothers[j] = SmootherType::New();
+    smoothers[j]->SetOperator( opers[j] );
+    smoothers[j]->ReleaseDataFlagOn();
+
+    if (j > 0)
+      {
+      smoothers[j]->SetInput( smoothers[j-1]->GetOutput() );
+      }
+    }
+  smoothers[0]->SetInput( field );
+  smoothers[ImageDimension-1]->GetOutput()
+    ->SetRequestedRegion( field->GetBufferedRegion() );
+
+  smoothers[ImageDimension-1]->Update();
+  
+  // field to contain the final smoothed data, do the equivalent of a graft
+  field->SetPixelContainer( smoothers[ImageDimension-1]->GetOutput()
+                            ->GetPixelContainer() );
+  field->SetRequestedRegion( smoothers[ImageDimension-1]->GetOutput()
+                             ->GetRequestedRegion() );
+  field->SetBufferedRegion( smoothers[ImageDimension-1]->GetOutput()
+                            ->GetBufferedRegion() );
+  field->SetLargestPossibleRegion( smoothers[ImageDimension-1]->GetOutput()
+                                   ->GetLargestPossibleRegion() );
+  field->CopyInformation( smoothers[ImageDimension-1]->GetOutput() );
+}
+
+
+} // end namespace itk
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsPDEDeformableRegistrationFunction.h b/bioimagesuite30_src/DemonsRegistration/itkjwsPDEDeformableRegistrationFunction.h
new file mode 100644
index 0000000..bc30bc1
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsPDEDeformableRegistrationFunction.h
@@ -0,0 +1,171 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsPDEDeformableRegistrationFunction.h,v $
+  Language:  C++
+  Date:      $Date: 2005/03/12 01:46:56 $
+  Version:   $Revision: 1.17 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkjwsPDEDeformableRegistrationFunction_h_
+#define _itkjwsPDEDeformableRegistrationFunction_h_
+
+#include "itkFiniteDifferenceFunction.h"
+
+namespace itk {
+
+/** \class jwsPDEDeformableRegistrationFunction
+ *
+ * This is an abstract base class for all PDE functions which drives a
+ * deformable registration algorithm. It is used by 
+ * PDEDeformationRegistrationFilter subclasses to compute the
+ * output deformation field which will map a moving image onto
+ * a fixed image.
+ *
+ * This class is templated over the fixed image type, moving image type
+ * and the deformation field type.
+ *
+ * \sa jwsPDEDeformableRegistrationFilter
+ * \ingroup FiniteDifferenceFunctions
+ */
+template<class TFixedImage, class TMovingImage, class TDeformationField>
+class ITK_EXPORT jwsPDEDeformableRegistrationFunction : 
+  public FiniteDifferenceFunction<TDeformationField>
+{
+public:
+  /** Standard class typedefs. */
+  typedef jwsPDEDeformableRegistrationFunction    Self;
+  typedef FiniteDifferenceFunction<TDeformationField>    Superclass;
+  typedef SmartPointer<Self> Pointer;
+  typedef SmartPointer<const Self> ConstPointer;
+
+  /** Run-time type information (and related methods) */
+  itkTypeMacro( jwsPDEDeformableRegistrationFunction, 
+    FiniteDifferenceFunction );
+
+  /** MovingImage image type. */
+  typedef TMovingImage   MovingImageType;
+  typedef typename MovingImageType::ConstPointer  MovingImagePointer;
+
+  /** FixedImage image type. */
+  typedef TFixedImage    FixedImageType;
+  typedef typename FixedImageType::ConstPointer  FixedImagePointer;
+  
+  /** Deformation field type. */
+  typedef TDeformationField    DeformationFieldType;
+  typedef typename DeformationFieldType::Pointer   
+    DeformationFieldTypePointer;
+
+  /** Set the moving image.  */
+  void SetMovingImage( const MovingImageType * ptr )
+    { m_MovingImage = ptr; }
+
+  /** Get the moving image. */
+  const MovingImageType * GetMovingImage(void) const
+    { return m_MovingImage; }
+
+  /** Set the fixed image. */
+  void SetFixedImage( const FixedImageType * ptr )
+    { m_FixedImage = ptr; }
+
+  /** Get the fixed image. */
+  const FixedImageType * GetFixedImage(void) const
+    { return m_FixedImage; }
+
+  /** Set the fixed image. */
+  void SetDeformationField(  DeformationFieldTypePointer ptr )
+    { m_DeformationField = ptr; }
+
+  /** Get the fixed image. */
+  DeformationFieldTypePointer GetDeformationField(void)
+    { return m_DeformationField; }
+
+
+  void SetEnergy( double e) { m_Energy=e;}
+  double GetEnergy( ) const { return m_Energy;}
+  void SetGradientStep( double e) { m_GradientStep = e;}
+  double GetGradientStep( ) const { return m_GradientStep ;}
+  void SetNormalizeGradient( bool e) { m_NormalizeGradient=e;}
+  bool GetNormalizeGradient( ) const { return m_NormalizeGradient;}
+
+protected:
+  jwsPDEDeformableRegistrationFunction()
+    {
+      m_MovingImage = NULL;
+      m_FixedImage = NULL;
+      m_DeformationField = NULL;
+      m_Energy = 0.0;
+      m_NormalizeGradient = true;
+      m_GradientStep = 1.0;
+    }
+
+  ~jwsPDEDeformableRegistrationFunction() {}
+
+  void PrintSelf(std::ostream& os, Indent indent) const
+  {
+    Superclass::PrintSelf(os, indent);
+    os << indent << "MovingImage: ";
+    os << m_MovingImage.GetPointer() << std::endl;
+    os << indent << "FixedImage: ";
+    os << m_FixedImage.GetPointer() << std::endl;
+
+  };
+
+  /** The moving image. */
+  MovingImagePointer                m_MovingImage;
+  
+  /** The fixed image. */
+  FixedImagePointer                   m_FixedImage;
+
+  /** The deformation field. */
+  DeformationFieldTypePointer                   m_DeformationField;
+
+  mutable double                  m_Energy;
+  bool                            m_NormalizeGradient;
+  mutable double                          m_GradientStep;
+private:
+  jwsPDEDeformableRegistrationFunction(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+};
+
+
+} // end namespace itk
+
+
+#endif
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFilter.h b/bioimagesuite30_src/DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFilter.h
new file mode 100644
index 0000000..5ad99a6
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFilter.h
@@ -0,0 +1,184 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsSymmetricForcesDemonsRegistrationFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2004/11/04 20:40:37 $
+  Version:   $Revision: 1.6 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkjwsSymmetricForcesDemonsRegistrationFilter_h_
+#define _itkjwsSymmetricForcesDemonsRegistrationFilter_h_
+
+#include "itkjwsPDEDeformableRegistrationFilter.h"
+#include "itkjwsSymmetricForcesDemonsRegistrationFunction.h"
+
+namespace itk {
+
+/** \class jwsSymmetricForcesDemonsRegistrationFilter
+ * \brief Deformably register two images using the demons algorithm.
+ *
+ * This class was contributed by Corinne Mattmann, ETH Zurich, Switzerland.
+ * based on a variation of the DemonsRegistrationFilter. The basic modification
+ * is to use equation (5) from Thirion's paper along with the modification for
+ * avoiding large deformations when gradients have small values.
+ *
+ * jwsSymmetricForcesDemonsRegistrationFilter implements the demons deformable algorithm that 
+ * register two images by computing the deformation field which will map a 
+ * moving image onto a fixed image.
+ *
+ * A deformation field is represented as a image whose pixel type is some
+ * vector type with at least N elements, where N is the dimension of
+ * the fixed image. The vector type must support element access via operator
+ * []. It is assumed that the vector elements behave like floating point
+ * scalars.
+ *
+ * This class is templated over the fixed image type, moving image type
+ * and the deformation field type.
+ *
+ * The input fixed and moving images are set via methods SetFixedImage
+ * and SetMovingImage respectively. An initial deformation field maybe set via
+ * SetInitialDeformationField or SetInput. If no initial field is set,
+ * a zero field is used as the initial condition.
+ *
+ * The algorithm has one parameters: the number of iteration to be performed.
+ *
+ * The output deformation field can be obtained via methods GetOutput
+ * or GetDeformationField.
+ *
+ * This class make use of the finite difference solver hierarchy. Update
+ * for each iteration is computed in DemonsRegistrationFunction.
+ *
+ * \warning This filter assumes that the fixed image type, moving image type
+ * and deformation field type all have the same number of dimensions.
+ * 
+ * \sa jwsSymmetricForcesDemonsRegistrationFunction 
+ * \sa DemonsRegistrationFilter
+ * \sa DemonsRegistrationFunction
+ * \ingroup DeformableImageRegistration MultiThreaded
+ */
+template<class TFixedImage, class TMovingImage, class TDeformationField>
+class ITK_EXPORT jwsSymmetricForcesDemonsRegistrationFilter : 
+    public jwsPDEDeformableRegistrationFilter< TFixedImage, TMovingImage,
+                                            TDeformationField>
+{
+public:
+  /** Standard class typedefs. */
+  typedef jwsSymmetricForcesDemonsRegistrationFilter    Self;
+  typedef jwsPDEDeformableRegistrationFilter<
+    TFixedImage, TMovingImage,TDeformationField>    Superclass;
+  typedef SmartPointer<Self> Pointer;
+  typedef SmartPointer<const Self> ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro( jwsSymmetricForcesDemonsRegistrationFilter, 
+                jwsPDEDeformableRegistrationFilter );
+
+  /** FixedImage image type. */
+  typedef typename Superclass::FixedImageType   FixedImageType;
+  typedef typename Superclass::FixedImagePointer  FixedImagePointer;
+
+  /** MovingImage image type. */
+  typedef typename Superclass::MovingImageType    MovingImageType;
+  typedef typename Superclass::MovingImagePointer  MovingImagePointer;
+  
+  /** Deformation field type. */
+  typedef typename Superclass::DeformationFieldType 
+  DeformationFieldType;
+  typedef typename Superclass::DeformationFieldPointer  
+  DeformationFieldPointer;
+
+  /** FiniteDifferenceFunction type. */
+  typedef typename Superclass::FiniteDifferenceFunctionType
+  FiniteDifferenceFunctionType;
+
+  /** Take timestep type from the FiniteDifferenceFunction. */
+  typedef typename FiniteDifferenceFunctionType::TimeStepType  TimeStepType;
+
+
+  /** DemonsRegistrationFilterFunction type. */
+  typedef jwsSymmetricForcesDemonsRegistrationFunction<FixedImageType,MovingImageType,
+                                     DeformationFieldType>  jwsSymmetricForcesDemonsRegistrationFunctionType;
+
+  /** Get the metric value. The metric value is the mean square difference 
+   * in intensity between the fixed image and transforming moving image 
+   * computed over the the overlapping region between the two images. 
+   * This value is calculated for the current iteration */
+  virtual double GetMetric() const;
+  virtual const double &GetRMSChange() const;
+
+  /** Set/Get the threshold below which the absolute difference of
+   * intensity yields a match. When the intensities match between a
+   * moving and fixed image pixel, the update vector (for that
+   * iteration) will be the zero vector. Default is 0.001. */
+  virtual void SetIntensityDifferenceThreshold(double);
+  virtual double GetIntensityDifferenceThreshold() const;
+
+  /**  Added by wook  */
+  virtual void setMyDField( DeformationFieldPointer ptr ); 
+
+protected:
+  jwsSymmetricForcesDemonsRegistrationFilter();
+  ~jwsSymmetricForcesDemonsRegistrationFilter() {}
+  void PrintSelf(std::ostream& os, Indent indent) const;
+
+  /** Initialize the state of filter and equation before each iteration. */
+  virtual void InitializeIteration();
+
+  /** Apply update. */
+  virtual void ApplyUpdate(TimeStepType dt);
+
+private:
+  jwsSymmetricForcesDemonsRegistrationFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+};
+
+
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkjwsSymmetricForcesDemonsRegistrationFilter.txx"
+#endif
+
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFilter.txx b/bioimagesuite30_src/DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFilter.txx
new file mode 100644
index 0000000..a5732de
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFilter.txx
@@ -0,0 +1,270 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsSymmetricForcesDemonsRegistrationFilter.txx,v $
+  Language:  C++
+  Date:      $Date: 2004/11/04 20:40:37 $
+  Version:   $Revision: 1.6 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkjwsSymmetricForcesDemonsRegistrationFilter_txx
+#define _itkjwsSymmetricForcesDemonsRegistrationFilter_txx
+#include "itkjwsSymmetricForcesDemonsRegistrationFilter.h"
+
+namespace itk {
+
+/*
+ * Default constructor
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+jwsSymmetricForcesDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::jwsSymmetricForcesDemonsRegistrationFilter()
+{
+ 
+  typename jwsSymmetricForcesDemonsRegistrationFunctionType::Pointer drfp;
+  drfp = jwsSymmetricForcesDemonsRegistrationFunctionType::New();
+
+  this->SetDifferenceFunction( static_cast<FiniteDifferenceFunctionType *>(
+                                 drfp.GetPointer() ) );
+
+}
+
+
+/*
+ * Set the function state values before each iteration
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsSymmetricForcesDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::InitializeIteration()
+{
+
+
+  // update variables in the equation object
+  jwsSymmetricForcesDemonsRegistrationFunctionType *f = 
+    dynamic_cast<jwsSymmetricForcesDemonsRegistrationFunctionType *>
+    (this->GetDifferenceFunction().GetPointer());
+
+  if ( !f )
+    {
+    itkExceptionMacro(<<"FiniteDifferenceFunction not of type jwsSymmetricForcesDemonsRegistrationFunctionType");
+    }
+
+  f->SetDeformationField( this->GetDeformationField() );
+
+
+ 
+  // call the superclass  implementation
+  Superclass::InitializeIteration();
+
+  /*
+   * Smooth the deformation field
+   */
+  if ( this->GetSmoothDeformationField() )
+    {
+    this->SmoothDeformationField();
+    }
+
+}
+
+
+/*
+ * Get the metric value from the difference function
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+double
+jwsSymmetricForcesDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::GetMetric() const
+{
+ 
+  jwsSymmetricForcesDemonsRegistrationFunctionType *drfp = 
+    dynamic_cast<jwsSymmetricForcesDemonsRegistrationFunctionType *>
+      (this->GetDifferenceFunction().GetPointer());
+ 
+  if( !drfp )
+   {
+   itkExceptionMacro( << 
+     "Could not cast difference function to jwsSymmetricForcesDemonsRegistrationFunction" );
+   }
+   
+  return drfp->GetMetric();
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////
+/*
+ * Added by wook 05/16/08
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsSymmetricForcesDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::setMyDField( DeformationFieldPointer ptr )
+{
+   // set the gradient selection flag
+  jwsSymmetricForcesDemonsRegistrationFunctionType *drfp = 
+    dynamic_cast<jwsSymmetricForcesDemonsRegistrationFunctionType *>
+      (this->GetDifferenceFunction().GetPointer());
+ 
+  if( !drfp )
+   {
+   itkExceptionMacro( << 
+     "Could not cast difference function to jwsDemonsRegistrationFunction" );
+   }
+   
+  drfp->SetDeformationField( ptr );
+
+}
+
+/*
+ * 
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+double
+jwsSymmetricForcesDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::GetIntensityDifferenceThreshold() const
+{
+ 
+  jwsSymmetricForcesDemonsRegistrationFunctionType *drfp = 
+    dynamic_cast<jwsSymmetricForcesDemonsRegistrationFunctionType *>
+      (this->GetDifferenceFunction().GetPointer());
+ 
+  if( !drfp )
+   {
+   itkExceptionMacro( << 
+     "Could not cast difference function to DemonsRegistrationFunction" );
+   }
+   
+  return drfp->GetIntensityDifferenceThreshold();
+
+}
+
+/*
+ * 
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsSymmetricForcesDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::SetIntensityDifferenceThreshold(double threshold) 
+{
+ 
+  jwsSymmetricForcesDemonsRegistrationFunctionType *drfp = 
+    dynamic_cast<jwsSymmetricForcesDemonsRegistrationFunctionType *>
+      (this->GetDifferenceFunction().GetPointer());
+ 
+  if( !drfp )
+   {
+   itkExceptionMacro( << 
+     "Could not cast difference function to SymmetricDemonsRegistrationFunction" );
+   }
+   
+  drfp->SetIntensityDifferenceThreshold(threshold);
+
+}
+
+/*
+ * Get the metric value from the difference function
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+const double &
+jwsSymmetricForcesDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::GetRMSChange() const
+{
+ 
+  jwsSymmetricForcesDemonsRegistrationFunctionType *drfp = 
+    dynamic_cast<jwsSymmetricForcesDemonsRegistrationFunctionType *>
+      (this->GetDifferenceFunction().GetPointer());
+ 
+  if( !drfp )
+   {
+   itkExceptionMacro( << 
+     "Could not cast difference function to jwsSymmetricForcesDemonsRegistrationFunction" );
+   }
+   
+  return drfp->GetRMSChange();
+
+}
+
+
+/*
+ * Get the metric value from the difference function
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsSymmetricForcesDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::ApplyUpdate(TimeStepType dt)
+{
+  // If we smooth the update buffer before applying it, then the are
+  // approximating a viscuous problem as opposed to an elastic problem
+  if ( this->GetSmoothUpdateField() )
+    {
+    this->SmoothUpdateField();
+    }
+  
+  this->Superclass::ApplyUpdate(dt);
+
+  jwsSymmetricForcesDemonsRegistrationFunctionType *drfp = 
+    dynamic_cast<jwsSymmetricForcesDemonsRegistrationFunctionType *>
+      (this->GetDifferenceFunction().GetPointer());
+ 
+  if( !drfp )
+   {
+   itkExceptionMacro( << 
+     "Could not cast difference function to DemonsRegistrationFunction" );
+   }
+
+  this->SetRMSChange( drfp->GetRMSChange() );
+   
+}
+
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsSymmetricForcesDemonsRegistrationFilter<TFixedImage,TMovingImage,TDeformationField>
+::PrintSelf(std::ostream& os, Indent indent) const
+{ 
+  Superclass::PrintSelf( os, indent );
+  os << indent << "Intensity difference threshold: " <<
+    this->GetIntensityDifferenceThreshold() << std::endl;
+}
+
+
+} // end namespace itk
+
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFunction.h b/bioimagesuite30_src/DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFunction.h
new file mode 100644
index 0000000..b88ff05
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFunction.h
@@ -0,0 +1,265 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkitkjwsSymmetricForcesDemonsRegistrationFunction.h,v $
+  Language:  C++
+  Date:      $Date: 2004/11/04 20:40:37 $
+  Version:   $Revision: 1.5 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkjwsSymmetricForcesDemonsRegistrationFunction_h_
+#define _itkjwsSymmetricForcesDemonsRegistrationFunction_h_
+
+#include "itkjwsPDEDeformableRegistrationFunction.h"
+#include "itkPoint.h"
+#include "itkCovariantVector.h"
+#include "itkInterpolateImageFunction.h"
+#include "itkLinearInterpolateImageFunction.h"
+#include "itkCentralDifferenceImageFunction.h"
+
+namespace itk {
+
+/**
+ * \class itkjwsSymmetricForcesDemonsRegistrationFunction
+ *
+ * This class encapsulate the PDE which drives the demons registration 
+ * algorithm (formula (5) in J.-P. Thirions's paper "Fast Non-Rigid Matching of
+ * 3D MEdical Images", May 1995). It is used by SymmetricForcesDemonsRegistrationFilter
+ * to compute the output deformation field which will map a moving image onto a
+ * a fixed image.
+ *
+ * This class was contributed by Corinne Mattmann, ETH Zurich, Switzerland.
+ * based on a variation of the DemonsRegistrationFunction. The basic modification
+ * is to use equation (5) from Thirion's paper along with the modification for
+ * avoiding large deformations when gradients have small values.
+ *
+ * Non-integer moving image values are obtained by using
+ * interpolation. The default interpolator is of type
+ * LinearInterpolateImageFunction. The user may set other
+ * interpolators via method SetMovingImageInterpolator. Note that the input
+ * interpolator must derive from baseclass InterpolateImageFunction.
+ *
+ * This class is templated over the fixed image type, moving image type,
+ * and the deformation field type.
+ *
+ * \warning This filter assumes that the fixed image type, moving image type
+ * and deformation field type all have the same number of dimensions.
+ *
+ * \sa SymmetricForcesDemonsRegistrationFilter
+ * \sa DemonsRegistrationFilter
+ * \sa DemonsRegistrationFunction
+ * \ingroup FiniteDifferenceFunctions
+ */
+template<class TFixedImage, class TMovingImage, class TDeformationField>
+class ITK_EXPORT jwsSymmetricForcesDemonsRegistrationFunction : 
+    public jwsPDEDeformableRegistrationFunction< TFixedImage,
+                                              TMovingImage, TDeformationField>
+{
+public:
+  /** Standard class typedefs. */
+  typedef jwsSymmetricForcesDemonsRegistrationFunction    Self;
+  typedef jwsPDEDeformableRegistrationFunction< TFixedImage,
+                                             TMovingImage, TDeformationField >    Superclass;
+  typedef SmartPointer<Self> Pointer;
+  typedef SmartPointer<const Self> ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro( jwsSymmetricForcesDemonsRegistrationFunction, 
+                jwsPDEDeformableRegistrationFunction );
+
+  /** MovingImage image type. */
+  typedef typename Superclass::MovingImageType     MovingImageType;
+  typedef typename Superclass::MovingImagePointer  MovingImagePointer;
+
+  /** FixedImage image type. */
+  typedef typename Superclass::FixedImageType     FixedImageType;
+  typedef typename Superclass::FixedImagePointer  FixedImagePointer;
+  typedef typename FixedImageType::IndexType      IndexType;
+  typedef typename FixedImageType::SizeType       SizeType;
+  typedef typename FixedImageType::SpacingType    SpacingType;
+  
+  /** Deformation field type. */
+  typedef typename Superclass::DeformationFieldType    DeformationFieldType;
+  typedef typename Superclass::DeformationFieldTypePointer   
+  DeformationFieldTypePointer;
+
+  /** Inherit some enums from the superclass. */
+  itkStaticConstMacro(ImageDimension, unsigned int,Superclass::ImageDimension);
+
+  /** Inherit some enums from the superclass. */
+  typedef typename Superclass::PixelType     PixelType;
+  typedef typename Superclass::RadiusType    RadiusType;
+  typedef typename Superclass::NeighborhoodType    NeighborhoodType;
+  typedef typename Superclass::FloatOffsetType  FloatOffsetType;
+  typedef typename Superclass::TimeStepType TimeStepType;
+
+  /** Interpolator type. */
+  typedef double CoordRepType;
+  typedef InterpolateImageFunction<MovingImageType,CoordRepType> InterpolatorType;
+  typedef typename InterpolatorType::Pointer         InterpolatorPointer;
+  typedef typename InterpolatorType::PointType       PointType;
+  typedef LinearInterpolateImageFunction<MovingImageType,CoordRepType>
+  DefaultInterpolatorType;
+
+  /** Covariant vector type. */
+  typedef CovariantVector<double,itkGetStaticConstMacro(ImageDimension)> CovariantVectorType;
+
+  /** Gradient calculator type. */
+  typedef CentralDifferenceImageFunction<FixedImageType> GradientCalculatorType;
+  typedef typename GradientCalculatorType::Pointer   GradientCalculatorPointer;
+
+  /** Set the moving image interpolator. */
+  void SetMovingImageInterpolator( InterpolatorType * ptr )
+  { m_MovingImageInterpolator = ptr; }
+
+  /** Get the moving image interpolator. */
+  InterpolatorType * GetMovingImageInterpolator(void)
+  { return m_MovingImageInterpolator; }
+
+  /** This class uses a constant timestep of 1. */
+  virtual TimeStepType ComputeGlobalTimeStep(void * itkNotUsed(GlobalData)) const
+  { return m_TimeStep; }
+
+  /** Return a pointer to a global data structure that is passed to
+   * this object from the solver at each calculation.  */
+  virtual void *GetGlobalDataPointer() const
+  {
+    GlobalDataStruct *global = new GlobalDataStruct();
+    global->m_SumOfSquaredDifference  = 0.0;
+    global->m_NumberOfPixelsProcessed = 0L;
+    global->m_SumOfSquaredChange      = 0;
+    return global;
+  }
+
+  /** Release memory for global data structure. */
+  virtual void ReleaseGlobalDataPointer( void *GlobalData ) const;
+
+  /** Set the object's state before each iteration. */
+  virtual void InitializeIteration();
+
+  /** This method is called by a finite difference solver image filter at
+   * each pixel that does not lie on a data set boundary */
+  virtual PixelType  ComputeUpdate(const NeighborhoodType &neighborhood,
+                                   void *globalData,
+                                   const FloatOffsetType &offset = FloatOffsetType(0.0));
+
+   /** Get the metric value. The metric value is the mean square difference 
+   * in intensity between the fixed image and transforming moving image 
+   * computed over the the overlapping region between the two images. */
+  virtual double GetMetric() const
+    { return m_Metric; }
+
+  /** Get the rms change in deformation field. */
+  virtual const double &GetRMSChange() const
+    { return m_RMSChange; }
+
+  /** Set/Get the threshold below which the absolute difference of
+   * intensity yields a match. When the intensities match between a
+   * moving and fixed image pixel, the update vector (for that
+   * iteration) will be the zero vector. Default is 0.001. */
+  virtual void SetIntensityDifferenceThreshold(double);
+  virtual double GetIntensityDifferenceThreshold() const;
+
+protected:
+  jwsSymmetricForcesDemonsRegistrationFunction();
+  ~jwsSymmetricForcesDemonsRegistrationFunction() {}
+  void PrintSelf(std::ostream& os, Indent indent) const;
+
+  /** FixedImage image neighborhood iterator type. */
+  typedef ConstNeighborhoodIterator<FixedImageType> FixedImageNeighborhoodIteratorType;
+
+  /** A global data type for this class of equation. Used to store
+   * iterators for the fixed image. */
+  struct GlobalDataStruct
+  {
+    double          m_SumOfSquaredDifference;
+    unsigned long   m_NumberOfPixelsProcessed;
+    double          m_SumOfSquaredChange;
+  };
+
+private:
+  jwsSymmetricForcesDemonsRegistrationFunction(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+  /** Cache fixed image information. */
+  SpacingType                     m_FixedImageSpacing;
+  PointType                       m_FixedImageOrigin;
+  double                          m_Normalizer;
+
+  /** Function to compute derivatives of the fixed image. */
+  GradientCalculatorPointer       m_FixedImageGradientCalculator;
+
+  /** Function to interpolate the moving image. */
+  InterpolatorPointer             m_MovingImageInterpolator;
+
+  /** The global timestep. */
+  TimeStepType                    m_TimeStep;
+
+  /** Threshold below which the denominator term is considered zero. */
+  double                          m_DenominatorThreshold;
+
+  /** Threshold below which two intensity value are assumed to match. */
+  double                          m_IntensityDifferenceThreshold;
+
+  /** The metric value is the mean square difference in intensity between
+   * the fixed image and transforming moving image computed over the 
+   * the overlapping region between the two images. */
+  mutable double                  m_Metric;
+  mutable double                  m_SumOfSquaredDifference;
+  mutable unsigned long           m_NumberOfPixelsProcessed;
+  mutable double                  m_RMSChange;
+  mutable double                  m_SumOfSquaredChange;
+
+  /** Mutex lock to protect modification to metric. */
+  mutable SimpleFastMutexLock     m_MetricCalculationLock;
+
+};
+
+
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkjwsSymmetricForcesDemonsRegistrationFunction.txx"
+#endif
+
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFunction.txx b/bioimagesuite30_src/DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFunction.txx
new file mode 100644
index 0000000..e1f70ed
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/itkjwsSymmetricForcesDemonsRegistrationFunction.txx
@@ -0,0 +1,386 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkjwsSymmetricForcesDemonsRegistrationFunction.txx,v $
+  Language:  C++
+  Date:      $Date: 2004/12/21 22:47:29 $
+  Version:   $Revision: 1.4 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkjwsSymmetricForcesDemonsRegistrationFunction_txx_
+#define _itkjwsSymmetricForcesDemonsRegistrationFunction_txx_
+
+#include "itkjwsSymmetricForcesDemonsRegistrationFunction.h"
+#include "itkExceptionObject.h"
+#include "vnl/vnl_math.h"
+
+namespace itk {
+
+/*
+ * Default constructor
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+jwsSymmetricForcesDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::jwsSymmetricForcesDemonsRegistrationFunction()
+{
+
+  RadiusType r;
+  unsigned int j;
+  for( j = 0; j < ImageDimension; j++ )
+    {
+    r[j] = 0;
+    }
+  this->SetRadius(r);
+
+  m_TimeStep = 1.0;
+  m_DenominatorThreshold = 1e-9;
+  m_IntensityDifferenceThreshold = 0.001;
+  this->SetMovingImage(NULL);
+  this->SetFixedImage(NULL);
+  m_FixedImageSpacing.Fill( 1.0 );
+  m_FixedImageOrigin.Fill( 0.0 );
+  m_Normalizer = 0.0;
+  m_FixedImageGradientCalculator = GradientCalculatorType::New();
+
+
+  typename DefaultInterpolatorType::Pointer interp =
+    DefaultInterpolatorType::New();
+
+  m_MovingImageInterpolator = static_cast<InterpolatorType*>(
+    interp.GetPointer() );
+
+  m_Metric = NumericTraits<double>::max();
+  m_SumOfSquaredDifference = 0.0;
+  m_NumberOfPixelsProcessed = 0L;
+  m_RMSChange = NumericTraits<double>::max();
+  m_SumOfSquaredChange = 0.0;
+
+}
+
+
+/*
+ * Standard "PrintSelf" method.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsSymmetricForcesDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::PrintSelf(std::ostream& os, Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+
+  os << indent << "MovingImageIterpolator: ";
+  os << m_MovingImageInterpolator.GetPointer() << std::endl;
+  os << indent << "FixedImageGradientCalculator: ";
+  os << m_FixedImageGradientCalculator.GetPointer() << std::endl;
+  os << indent << "DenominatorThreshold: ";
+  os << m_DenominatorThreshold << std::endl;
+  os << indent << "IntensityDifferenceThreshold: ";
+  os << m_IntensityDifferenceThreshold << std::endl;
+
+  os << indent << "Metric: ";
+  os << m_Metric << std::endl;
+  os << indent << "SumOfSquaredDifference: ";
+  os << m_SumOfSquaredDifference << std::endl;
+  os << indent << "NumberOfPixelsProcessed: ";
+  os << m_NumberOfPixelsProcessed << std::endl;
+  os << indent << "RMSChange: ";
+  os << m_RMSChange << std::endl;
+  os << indent << "SumOfSquaredChange: ";
+  os << m_SumOfSquaredChange << std::endl;
+
+}
+
+/**
+ *
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsSymmetricForcesDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::SetIntensityDifferenceThreshold(double threshold)
+{
+  m_IntensityDifferenceThreshold = threshold;
+}
+
+/**
+ *
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+double
+jwsSymmetricForcesDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::GetIntensityDifferenceThreshold() const
+{
+  return m_IntensityDifferenceThreshold;
+}
+
+/*
+ * Set the function state values before each iteration
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsSymmetricForcesDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::InitializeIteration()
+{
+  if( !this->GetMovingImage() || !this->GetFixedImage() || !m_MovingImageInterpolator )
+    {
+    itkExceptionMacro( << "MovingImage, FixedImage and/or Interpolator not set" );
+    }
+
+  // cache fixed image information
+  m_FixedImageSpacing    = this->GetFixedImage()->GetSpacing();
+  m_FixedImageOrigin     = this->GetFixedImage()->GetOrigin();
+
+  // compute the normalizer
+  m_Normalizer      = 0.0;
+  for( unsigned int k = 0; k < ImageDimension; k++ )
+    {
+    m_Normalizer += m_FixedImageSpacing[k] * m_FixedImageSpacing[k];
+    }
+  m_Normalizer /= static_cast<double>( ImageDimension );
+
+
+  // setup gradient calculator
+  m_FixedImageGradientCalculator->SetInputImage( this->GetFixedImage() );
+
+  // setup moving image interpolator
+  m_MovingImageInterpolator->SetInputImage( this->GetMovingImage() );
+
+  // initialize metric computation variables
+  m_SumOfSquaredDifference  = 0.0;
+  m_NumberOfPixelsProcessed = 0L;
+  m_SumOfSquaredChange      = 0.0;
+
+}
+
+
+/*
+ * Compute update at a non boundary neighbourhood
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+typename jwsSymmetricForcesDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::PixelType
+jwsSymmetricForcesDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::ComputeUpdate(const NeighborhoodType &it, void * gd,
+                const FloatOffsetType& itkNotUsed(offset))
+{
+
+  GlobalDataStruct *globalData = (GlobalDataStruct *)gd;
+  PixelType update;
+  IndexType FirstIndex = this->GetFixedImage()->GetLargestPossibleRegion().GetIndex();
+  IndexType LastIndex = this->GetFixedImage()->GetLargestPossibleRegion().GetIndex() + 
+                        this->GetFixedImage()->GetLargestPossibleRegion().GetSize();
+
+  IndexType index = it.GetIndex();
+
+
+
+  // Get fixed image related information
+  double fixedValue;
+  CovariantVectorType fixedGradient;
+
+  // Note: no need to check the index is within
+  // fixed image buffer. This is done by the external filter.
+  fixedValue = (double) this->GetFixedImage()->GetPixel( index );
+  fixedGradient = m_FixedImageGradientCalculator->EvaluateAtIndex( index );
+
+
+
+  // Get moving image related information
+  IndexType tmpIndex = index;
+  PointType mappedNeighPoint;
+  PointType mappedCenterPoint;
+  CovariantVectorType movingGradient;
+  double movingValue;
+
+  for( unsigned int dim = 0; dim < ImageDimension; dim++ ){
+
+    // bounds checking
+    if( index[dim] < (FirstIndex[dim] + 1) || index[dim] > (LastIndex[dim] - 2 )){
+      movingGradient[dim] = 0.0;
+    }
+
+    else{
+      tmpIndex[dim] += 1;
+      for( unsigned int j = 0; j < ImageDimension; j++ ){
+        mappedNeighPoint[j] = double( tmpIndex[j] ) * m_FixedImageSpacing[j] + m_FixedImageOrigin[j];
+        mappedNeighPoint[j] += this->GetDeformationField()->GetPixel(tmpIndex)[j];
+      }
+      if( m_MovingImageInterpolator->IsInsideBuffer( mappedNeighPoint ) ){
+        movingGradient[dim] = m_MovingImageInterpolator->Evaluate( mappedNeighPoint );
+      }
+      else{
+        movingGradient[dim] = 0.0;
+      }
+
+      tmpIndex[dim] -= 2;
+      for( unsigned int j = 0; j < ImageDimension; j++ ){
+        mappedNeighPoint[j] = double( tmpIndex[j] ) * m_FixedImageSpacing[j] + m_FixedImageOrigin[j];
+        mappedNeighPoint[j] += this->GetDeformationField()->GetPixel(tmpIndex)[j];
+      }
+      if( m_MovingImageInterpolator->IsInsideBuffer( mappedNeighPoint ) ){
+        movingGradient[dim] -= m_MovingImageInterpolator->Evaluate( mappedNeighPoint );
+      }
+
+      movingGradient[dim] *= 0.5 / m_FixedImageSpacing[dim];
+      tmpIndex[dim] += 1;
+    }
+
+    mappedCenterPoint[dim] = double( index[dim] ) * m_FixedImageSpacing[dim] + m_FixedImageOrigin[dim];
+    mappedCenterPoint[dim] += it.GetCenterPixel()[dim];
+  }
+
+  if( m_MovingImageInterpolator->IsInsideBuffer( mappedCenterPoint ) ){
+    movingValue = m_MovingImageInterpolator->Evaluate( mappedCenterPoint );
+  }
+  else{
+    movingValue = 0.0;
+  }
+
+
+  /**
+   * Compute Update.
+   * In the original equation the denominator is defined as
+   *
+   *         (g-f)^2 + (moving_grad+fixed_grad)_mag^2
+   *
+   * However there is a mismatch in units between the two terms. 
+   * The units for the second term is intensity^2/mm^2 while the
+   * units for the first term is intensity^2. This mismatch is particularly
+   * problematic when the fixed image does not have unit spacing.
+   * In this implemenation, we normalize the first term by a factor K,
+   * such that denominator = (g-f)^2/K + grad_mag^2
+   * where K = mean square spacing to compensate for the mismatch in units.
+   */
+
+  double fixedPlusMovingGradientSquaredMagnitude = 0;
+  for( unsigned int dim = 0; dim < ImageDimension; dim++ ){
+    fixedPlusMovingGradientSquaredMagnitude += vnl_math_sqr( fixedGradient[dim] + movingGradient[dim] );
+  }
+
+  double speedValue = fixedValue - movingValue;
+  double denominator = vnl_math_sqr( speedValue ) / m_Normalizer + fixedPlusMovingGradientSquaredMagnitude;
+
+  if ( vnl_math_abs(speedValue) < m_IntensityDifferenceThreshold || denominator < m_DenominatorThreshold )
+    {
+    for( unsigned int j = 0; j < ImageDimension; j++ )
+      {
+      update[j] = 0.0;
+      }
+    }
+
+  else
+    {
+    for( unsigned int j = 0; j < ImageDimension; j++ )
+      {
+      update[j] = 2 * speedValue * (fixedGradient[j] + movingGradient[j]) / denominator;
+      }
+    }
+
+  // update the squared change value
+  PointType newMappedCenterPoint;
+  double newMovingValue;
+  bool IsOutsideRegion = 0;
+  for( unsigned int j = 0; j < ImageDimension; j++ )
+    {
+    if ( globalData )
+      {
+      globalData->m_SumOfSquaredChange += vnl_math_sqr( update[j] );
+
+      newMappedCenterPoint[j] = mappedCenterPoint[j] + update[j];
+      if ( index[j] < (FirstIndex[j] + 2) || index[j] > (LastIndex[j] - 3) )
+        {
+        IsOutsideRegion = 1;
+        }
+      }
+    }
+
+  // update the metric with the latest deformable field
+  if ( globalData )
+    {
+    // do not consider voxel on the border (2 voxels) as there are often artefacts
+    // which falsify the metric
+    if( !IsOutsideRegion )
+      {
+      if( m_MovingImageInterpolator->IsInsideBuffer( newMappedCenterPoint ) )
+        {
+        newMovingValue = m_MovingImageInterpolator->Evaluate( newMappedCenterPoint );
+        }
+      else
+        {
+        newMovingValue = 0;
+        }
+        globalData->m_SumOfSquaredDifference += vnl_math_sqr( fixedValue - newMovingValue );
+        globalData->m_NumberOfPixelsProcessed += 1;
+      }
+    }
+
+  return update;
+
+}
+
+
+/*
+ * Update the metric and release the per-thread-global data.
+ */
+template <class TFixedImage, class TMovingImage, class TDeformationField>
+void
+jwsSymmetricForcesDemonsRegistrationFunction<TFixedImage,TMovingImage,TDeformationField>
+::ReleaseGlobalDataPointer( void *gd ) const
+{
+  GlobalDataStruct * globalData = (GlobalDataStruct *) gd;
+
+  m_MetricCalculationLock.Lock();
+  m_SumOfSquaredDifference  += globalData->m_SumOfSquaredDifference;
+  m_NumberOfPixelsProcessed += globalData->m_NumberOfPixelsProcessed;
+  m_SumOfSquaredChange += globalData->m_SumOfSquaredChange;
+  if ( m_NumberOfPixelsProcessed )
+    {
+    m_Metric = m_SumOfSquaredDifference / 
+               static_cast<double>( m_NumberOfPixelsProcessed ); 
+    m_RMSChange = vcl_sqrt( m_SumOfSquaredChange / 
+               static_cast<double>( m_NumberOfPixelsProcessed ) ); 
+    }
+  m_MetricCalculationLock.Unlock();
+
+  delete globalData;
+}
+
+} // end namespace itk
+
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/jwsForRewritingPreprocess.cpp b/bioimagesuite30_src/DemonsRegistration/jwsForRewritingPreprocess.cpp
new file mode 100644
index 0000000..1ea4147
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/jwsForRewritingPreprocess.cpp
@@ -0,0 +1,145 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include <string.h>
+#include "wook.h"
+#include "jwsReadWriteImages.h"
+
+namespace jws_demons {
+
+void imagePreProcessing::imageCleaning(OutputImageType::Pointer cleanFixedBone,  OutputImageType::Pointer cleanFixedSkin, OutputImageType::Pointer cleanMovingBone, OutputImageType::Pointer cleanMovingSkin)
+{     
+	const InputPixelType lowerThSkin = (unsigned short) 1;
+	const InputPixelType upperThSkin =(unsigned short) 2 ;    
+	std::cout<<"lowerThSkin= "<< lowerThSkin  <<"  upperThSkin= "<< upperThSkin <<std::endl;
+     
+	const InputPixelType lowerThBone = (unsigned short) 2;
+	const InputPixelType upperThBone =(unsigned short) 3 ;    
+	std::cout<<"lowerThBone= "<< lowerThBone  <<"  upperThBone= "<< upperThBone <<std::endl;
+     
+	cout<<"### FixedImage for Skin Processing Begin ###"<<endl;
+	imagePreparation(newFixedImage, FixedSkinName, region, FixedWriter, cleanFixedSkin,upperThSkin, lowerThSkin);
+     
+	cout<<"### FixedImage for Bone Processing Begin ###"<<endl;
+	imagePreparation(newFixedImage, FixedBoneName, region, FixedWriter, cleanFixedBone, upperThBone, lowerThBone);
+	
+	cout<<"### MovingImage for Skin Processing Begin ###"<<endl;
+	imagePreparation(newMovingImage, MovingSkinName, region, MovingWriter, cleanMovingSkin,upperThSkin, lowerThSkin);
+     
+	cout<<"### MovingImage for Bone Processing Begin ###"<<endl;
+	imagePreparation(newMovingImage, MovingBoneName, region, MovingWriter, cleanMovingBone, upperThBone, lowerThBone);	
+	
+}
+
+
+//////////////////// for test  ///////////////////////////////////////////////////////////////
+void testImageToFile1(OutputImageType::Pointer outImage)
+{
+	string fileName = "testImage1.vtk";
+	
+	WriterType::Pointer writer = WriterType::New();
+	writer->SetFileName( fileName );
+	writer->SetInput( outImage );
+	writer->Update();
+}
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+void imagePreProcessing::imagePreparation(InputImageType::Pointer inputImage, string &inputFileName, InputImageType::RegionType inputRegion, WriterType::Pointer writer,  OutputImageType::Pointer cleanOutImage, const InputPixelType upperTh, const InputPixelType lowerTh)
+{
+
+  string simpleThresholdImageFileName = inputFileName + "_ThresholdImage.vtk";
+  string morphologyBinaryFileName = inputFileName + "_morphologyBinaryImage.vtk";
+
+  ClosingFilterType::Pointer binaryClosing = ClosingFilterType::New();  
+
+  cout<<"	morphologyBinaryFiltering ..."<<endl;
+  morphologyBinaryFiltering(inputImage, writer, inputRegion, upperTh, lowerTh, simpleThresholdImageFileName, binaryClosing);
+  
+  writer->SetFileName( morphologyBinaryFileName );
+  writer->SetInput( binaryClosing->GetOutput() );
+  writer->Update();
+
+   //cleanOutImage = binaryClosing->GetOutput();
+     ///////////////////// save the mrphologyBImage   /////////////////////////////////////
+ IteratorType  inputIt( binaryClosing->GetOutput(), inputRegion );
+ IteratorType  outputIt( cleanOutImage, inputRegion );
+ 
+ inputIt.GoToBegin();
+ outputIt.GoToBegin();
+ 
+    while( (!inputIt.IsAtEnd())&&(!outputIt.IsAtEnd()) )
+    {                       
+	outputIt.Set(inputIt.Get());
+                                             
+	++inputIt;
+	++outputIt;
+    
+    }   
+  // testImageToFile1(cleanOutImage);
+}
+
+void imagePreProcessing::morphologyBinaryFiltering(InputImageType::Pointer inputImage, WriterType::Pointer writer, InputImageType::RegionType inputRegion, const InputPixelType upperTh, const InputPixelType lowerTh, string simpleThresholdImageName, ClosingFilterType::Pointer binaryClosing )
+{
+ 
+  ThresholdFilterType::Pointer thresholder = ThresholdFilterType::New();
+
+
+  StructuringElementType  structuringElement;
+  structuringElement.SetRadius( 1 );  // 3x3 structuring element
+  //structuringElement.SetRadius( 3 );  // 9x9 structuring element
+  //structuringElement.SetRadius( 5 );  // 9x9 structuring element
+  structuringElement.CreateStructuringElement();
+
+  // added by wook 
+  binaryClosing->SetKernel( structuringElement );
+  
+//  thresholder->SetInput( reader->GetOutput() );
+  thresholder->SetInput( inputImage );
+
+  InputPixelType background =   0;
+  InputPixelType foreground =  3056;  //255;
+
+  thresholder->SetOutsideValue( background );
+  thresholder->SetInsideValue(  foreground );
+
+  thresholder->SetLowerThreshold( lowerTh );
+  thresholder->SetUpperThreshold( upperTh );
+  thresholder->Update(); // modified by wook 04/24/08
+  ///////////////////////   write simpleThresholdImageFile    ///////////////////////////
+  //writer->SetFileName( simpleThresholdImageName );
+  //writer->SetInput( thresholder->GetOutput() );
+  //writer->Update();
+  //////////////////////////////////////////////////////////////////////////////////////////////////
+  
+  binaryClosing->SetInput( thresholder->GetOutput() );
+  binaryClosing->SetForegroundValue( foreground );   // Is it correct? by wook
+  //binaryClosing->Update();
+  //outImage = binaryClosing->GetOutput() ;  //
+}
+};
+
diff --git a/bioimagesuite30_src/DemonsRegistration/jwsNewMain.cxx b/bioimagesuite30_src/DemonsRegistration/jwsNewMain.cxx
new file mode 100644
index 0000000..bade54c
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/jwsNewMain.cxx
@@ -0,0 +1,270 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include <string.h>
+#include "wook.h"
+#include "OtherFunctions.h"
+
+
+
+using namespace jws_demons;
+
+#include "firstExtendedDemon.h"
+#include "secondExtendedDemon.h"
+#include "thirdDemon.h"
+#include "jwsReadWriteImages.h"
+
+
+
+
+// OtherFunctions.cxx
+/*
+// New Functions (three of them)
+// And key parameters
+DField*  RunRegistration1(Image* FixedBinary,Image* FixedGray,Image* MovingBinary, Image* MovingGray,int parameter1, float parameter2, int parameter 3)
+DField*  RunRegistration2(Image* FixedBinary,Image* FixedGray,Image* MovingBinary, Image* MovingGray)
+DField*  RunRegistration3(Image* FixedBinary,Image* FixedGray,Image* MovingBinary, Image* MovingGray)
+
+
+// Rewrite main Function ...
+NewMainFunction
+
+
+   1. Load Images
+   2. RunRegistration1 --- output should only be displacement field
+   3. Save Something   --- optionally warp and save
+   4. RunRegistration2
+   5. SaveSomething
+   6. RunRegistration3
+   7. Save
+   8. Done
+}
+
+See Examples in Levelset Directory
+
+vtkpx -- is a VTK Class wrapper around ITK
+
+
+Test how to convert vector images to VTK
+
+vtkImageData* img;   Allocatee
+for all pixels
+img->SetPixel(itkimg->GetPixel());
+
+
+Look at Levelset/vtkjwsDemonsRegistration for a boilerplate VTK Class
+
+*/
+
+
+
+int main( int argc, char * argv[] )
+{
+  if( argc < 6 )
+    {
+      std::cerr<< std::endl ;
+      std::cerr << "Usage (all input files should .vtk format): " << std::endl ;
+      std::cerr << argv[0]<<" FixedImageFile(No extension)  MovingImageFile(No extension) RegisteredImageFile(No extension) FixedGray(No extension) MovingGray(No extension) RegisteredGray(No extension)  ";   // 1 ,2, 3
+      std::cerr << std::endl<< std::endl;  
+      return EXIT_FAILURE;
+    }
+
+
+  imagePreProcessing PreClass;
+  
+  PreClass.loadImages( argv );
+  PreClass.makeSameSizeAllInputImages();       cout<<"0.5" <<endl;
+  
+  OutputImageType::Pointer cleanFixedBoneImage = OutputImageType::New();
+  OutputImageType::Pointer cleanFixedSkinImage = OutputImageType::New();
+  OutputImageType::Pointer cleanMovingBoneImage = OutputImageType::New();
+  OutputImageType::Pointer cleanMovingSkinImage = OutputImageType::New();
+  
+	
+  	cleanFixedBoneImage->SetRegions( PreClass.region );  							  
+	cleanFixedBoneImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	cleanFixedBoneImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	cleanFixedBoneImage->Allocate();    
+	
+  	cleanFixedSkinImage->SetRegions( PreClass.region );  							  
+	cleanFixedSkinImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	cleanFixedSkinImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	cleanFixedSkinImage->Allocate();  
+	
+	cleanMovingBoneImage->SetRegions( PreClass.region );  							  
+	cleanMovingBoneImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	cleanMovingBoneImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	cleanMovingBoneImage->Allocate();  
+	
+  	cleanMovingSkinImage->SetRegions( PreClass.region );  							  
+	cleanMovingSkinImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	cleanMovingSkinImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	cleanMovingSkinImage->Allocate();  	
+  
+  PreClass.imageCleaning(cleanFixedBoneImage, cleanFixedSkinImage, cleanMovingBoneImage, cleanMovingSkinImage);             
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		GrayImageType::Pointer newFixedGrayImage = GrayImageType::New();
+		GrayImageType::Pointer newMovingGrayImage = GrayImageType::New();
+		
+		newFixedGrayImage->SetRegions( PreClass.region );
+		newFixedGrayImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+		newFixedGrayImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+		newFixedGrayImage->Allocate();
+		
+		newMovingGrayImage->SetRegions( PreClass.region );
+		newMovingGrayImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+		newMovingGrayImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+		newMovingGrayImage->Allocate();	
+		
+   PreClass.GetNewSizedGrayImages(newFixedGrayImage, newMovingGrayImage);
+		
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
+  
+  FixedImageType::Pointer fixedBoneDMapImage = FixedImageType::New();
+  FixedImageType::Pointer fixedSkinDMapImage = FixedImageType::New();
+  MovingImageType::Pointer movingBoneDMapImage = MovingImageType::New();
+  
+  	fixedBoneDMapImage->SetRegions( PreClass.region );  							  
+	fixedBoneDMapImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	fixedBoneDMapImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	fixedBoneDMapImage->Allocate(); 
+	
+  	fixedSkinDMapImage->SetRegions( PreClass.region );  							  
+	fixedSkinDMapImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	fixedSkinDMapImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	fixedSkinDMapImage->Allocate(); 
+	
+	movingBoneDMapImage->SetRegions( PreClass.region );  							  
+	movingBoneDMapImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	movingBoneDMapImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	movingBoneDMapImage->Allocate(); 
+  // Fixed Bone
+  DistanceMapGeneration( "cleanFixedBone", cleanFixedBoneImage, fixedBoneDMapImage, PreClass.region);
+ 
+    // Fixed Skin
+  DistanceMapGeneration( "cleanFixedSkin", cleanFixedSkinImage, fixedSkinDMapImage, PreClass.region);
+  
+  // Moving Bone
+  DistanceMapGeneration( "cleanMovingBone", cleanMovingBoneImage, movingBoneDMapImage, PreClass.region);
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
+
+     DeformationFieldType::Pointer DFieldBone = DeformationFieldType::New();     
+     DFieldBone->SetRegions( PreClass.region  );
+     DFieldBone->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin()  );
+     DFieldBone->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+     DFieldBone->Allocate();
+     
+     InternalImageType::Pointer deformedBoneImg = InternalImageType::New();
+     deformedBoneImg->SetRegions( PreClass.region );
+     deformedBoneImg->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin());
+     deformedBoneImg->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+     deformedBoneImg->Allocate();
+     
+     InputImageType::Pointer UshortDeformedSkinImg = InputImageType::New();
+     UshortDeformedSkinImg ->SetRegions(PreClass.region );
+     UshortDeformedSkinImg ->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+     UshortDeformedSkinImg ->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+     UshortDeformedSkinImg ->Allocate();		
+     
+     GrayImageType::Pointer firstDeformedGrayImg = GrayImageType::New();
+     firstDeformedGrayImg->SetRegions( PreClass.region);
+     firstDeformedGrayImg->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+     firstDeformedGrayImg->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+     firstDeformedGrayImg->Allocate();		
+     
+     ////////////////////////////////// First Extended Demon with only Bone Distance Map   ///////////////////////////////////////////////
+     string boneOnlyRegistrationResult = "FirstRegResultHalf";
+     FIRST_EDEMON::firstExtendedDemonRegistration(fixedBoneDMapImage, movingBoneDMapImage, DFieldBone, boneOnlyRegistrationResult);	
+	 
+     myWarper(movingBoneDMapImage,  deformedBoneImg, DFieldBone );
+     myWarperGray(newMovingGrayImage,  firstDeformedGrayImg, DFieldBone, "firstDeformedGray" ); 
+	 
+     // 1. Deform Skin(actually whole moving image) by bone-DField
+     // 2. Generate distance map of the deformed skin
+     myWarperUShort(cleanMovingSkinImage, UshortDeformedSkinImg , DFieldBone );	
+    
+     MovingImageType::Pointer movingSkinDMapImage = MovingImageType::New();
+	
+	movingSkinDMapImage->SetRegions( PreClass.region );  							  
+	movingSkinDMapImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	movingSkinDMapImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	movingSkinDMapImage->Allocate(); 	 
+	 // Moving Skine
+    DistanceMapGeneration( "firstDeformedMovingSkin", UshortDeformedSkinImg, movingSkinDMapImage, PreClass.region);
+     
+	       
+     ///////////////////////////////// Combine Two images for one-time registration   ///////////////////////////////////////////////////////
+     InternalImageType::Pointer combinedDMapFixedImage = InternalImageType::New();
+     mergeImages(fixedSkinDMapImage, fixedBoneDMapImage, combinedDMapFixedImage,"combineDMFixedImage.vtk");
+     
+     InternalImageType::Pointer combinedDMapFirstDeformedImage = InternalImageType::New();
+     mergeImages(movingSkinDMapImage, deformedBoneImg, combinedDMapFirstDeformedImage , "combinedFirstDeformedImage.vtk");
+   
+/*	 
+     // just for test
+     string combinedDMapMovingFileName = "combinedDMMovingImage.vtk";
+     InternalImageType::Pointer combinedDMapMovingImage = InternalImageType::New();
+     mergeImages(movingSkinDMapImage, movingBoneDMapImage, combinedDMapMovingImage, combinedDMapMovingFileName);		
+*/      	 
+     /////////////////////////////////////////////////////////  Extended Demons Registration  //////////////////////////////////////////////////
+     //		string registeredImageName(argv[3]);
+     
+     DeformationFieldType::Pointer DField2 = DeformationFieldType::New();
+     DField2->SetRegions( PreClass.region );
+     DField2->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+     DField2->SetSpacing(PreClass.FixedReader->GetOutput()->GetSpacing() );
+     DField2->Allocate();
+     
+     SECOND_EDEMON::ExtendedDemonRegistrationMain(combinedDMapFixedImage, combinedDMapFirstDeformedImage, DField2, "SecondRegResult");	
+     DfieldToFile(DField2, "SecondRegResultHalf");
+     
+	 
+     GrayImageType::Pointer secondDeformedGrayImg = GrayImageType::New();
+     secondDeformedGrayImg->SetRegions( PreClass.region );
+     secondDeformedGrayImg->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+     secondDeformedGrayImg->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+     secondDeformedGrayImg->Allocate();		
+     
+     myWarperGray(firstDeformedGrayImg, secondDeformedGrayImg, DField2, "secondDeformedGray" );
+#if 1
+
+     DeformationFieldType::Pointer DField3 = DeformationFieldType::New();
+     DField3->SetRegions( PreClass.region );
+     DField3->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+     DField3->SetSpacing(PreClass.FixedReader->GetOutput()->GetSpacing() );
+     DField3->Allocate();
+
+     THIRD_EDEMON::DemonRegistrationMain(newFixedGrayImage, secondDeformedGrayImg, DField3, "thirdDeformedGray");	
+     
+#endif	 
+     return EXIT_SUCCESS;
+ 
+}
+
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/jwsReadWriteImages.cpp b/bioimagesuite30_src/DemonsRegistration/jwsReadWriteImages.cpp
new file mode 100644
index 0000000..3b47c09
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/jwsReadWriteImages.cpp
@@ -0,0 +1,284 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include <string.h>
+#include "wook.h"
+#include "jwsReadWriteImages.h"
+using namespace jws_demons;
+
+namespace jws_demons {
+
+imagePreProcessing::imagePreProcessing()
+{
+	FixedReader = ReaderType::New();
+	FixedWriter = WriterType::New();
+        MovingReader = ReaderType::New();
+	MovingWriter = WriterType::New();
+	
+	newFixedImage = OutputImageType::New();
+	newMovingImage = OutputImageType::New();
+	outImage = OutputImageType::New();	
+	
+	newFixedGrayImage = GrayImageType::New();
+        newMovingGrayImage = GrayImageType::New();	
+	
+}
+
+void imagePreProcessing::makeSameSizeAllInputImages(void)
+{
+	ImageSize = decideImageSize( FixedReader, MovingReader);
+	std::cout<<"[ForRewriting Class:: makeSameSizeAllInputImages()]  Internal image sizeX="<< ImageSize[0]<<" sizeY="<<ImageSize[1]<<" sizeZ="<<ImageSize[2]<<std::endl;
+	
+	prepareSameSizedNewImages();
+	makeSameSize(FixedReader, newFixedImage, ImageSize);
+        makeSameSize(MovingReader, newMovingImage, ImageSize);
+	makeSameSizeGray(GrayFixedReader, newFixedGrayImage, ImageSize);
+	makeSameSizeGray(GrayMovingReader, newMovingGrayImage, ImageSize);
+	
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	//   for test
+
+	testGrayImageToFile(newFixedGrayImage, inputFixedGrayName);
+	testGrayImageToFile(newMovingGrayImage, inputMovingGrayName);
+}
+
+void imagePreProcessing::prepareSameSizedNewImages(void)
+{
+	 indexStart[0]=0;   indexStart[1]=0;  indexStart[2]=0;
+	 region.SetSize( ImageSize );
+	 region.SetIndex( indexStart ); 	
+	
+	 newFixedImage->SetRegions( region );
+	 newFixedImage->SetOrigin( FixedReader->GetOutput()->GetOrigin() );
+	 newFixedImage->SetSpacing( FixedReader->GetOutput()->GetSpacing() );
+	 newFixedImage->Allocate();
+     
+	 newMovingImage->SetRegions( region );
+	 newMovingImage->SetOrigin( FixedReader->GetOutput()->GetOrigin() );
+	 newMovingImage->SetSpacing( FixedReader->GetOutput()->GetSpacing() );
+	 newMovingImage->Allocate();
+     
+	 outImage->SetRegions( region );
+	 outImage->SetOrigin( FixedReader->GetOutput()->GetOrigin() );
+	 outImage->SetSpacing( FixedReader->GetOutput()->GetSpacing() );
+	 outImage->Allocate();	 	
+	 
+	 newFixedGrayImage->SetRegions( region );
+	 newFixedGrayImage->SetOrigin( FixedReader->GetOutput()->GetOrigin() );
+	 newFixedGrayImage->SetSpacing( FixedReader->GetOutput()->GetSpacing() );
+	 newFixedGrayImage->Allocate();
+     
+	 newMovingGrayImage->SetRegions( region );
+	 newMovingGrayImage->SetOrigin( FixedReader->GetOutput()->GetOrigin() );
+	 newMovingGrayImage->SetSpacing( FixedReader->GetOutput()->GetSpacing() );
+	 newMovingGrayImage->Allocate();		 
+}
+
+
+void imagePreProcessing::loadImages(char * argv[])
+{
+	  inputFixedName = argv[1];
+	  inputMovingName = argv[2]; 
+	  FixedSkinName = inputFixedName + "SKIN";
+	  FixedBoneName = inputFixedName + "BONE";
+	  MovingSkinName = inputMovingName + "SKIN";
+	  MovingBoneName = inputMovingName + "BONE";
+
+	  inputFixedGrayName = argv[4];
+	  inputMovingGrayName = argv[5];
+	  RegisteredGrayName = argv[6];
+
+     // Read Input Files
+     // Binary classification image 0,1,2 -- unsigned short 
+	  string inputFixedFileName = inputFixedName + ".vtk";
+	  FixedReader->SetFileName( inputFixedFileName );  FixedReader->Update();
+     
+	  string inputMovingFileName = inputMovingName + ".vtk";    
+	  MovingReader->SetFileName( inputMovingFileName );   MovingReader->Update();  
+	 
+	 GrayFixedReader = GrayReaderType::New();
+	 GrayMovingReader = GrayReaderType::New();
+     
+     // Read Gray Level Files
+     // Gray Level Images -- short
+	 string inputFixedGrayFileName = inputFixedGrayName + ".vtk";
+	 GrayFixedReader->SetFileName( inputFixedGrayFileName );  GrayFixedReader->Update();		
+	 string inputMovingGrayFileName = inputMovingGrayName + ".vtk";
+	 GrayMovingReader->SetFileName( inputMovingGrayFileName );  GrayMovingReader->Update();
+     // End of Read 
+	 	 	 
+}
+
+// Because of the 3 Layered-multiresolution implementation of registration, Image size should be adjusted to the multiple of 4.
+InputImageType::RegionType::SizeType imagePreProcessing::decideImageSize(ReaderType::Pointer reader1, ReaderType::Pointer reader2)
+{
+		InputImageType::RegionType::SizeType  Image1size;
+		Image1size =  reader1->GetOutput()->GetRequestedRegion().GetSize();
+		
+		InputImageType::RegionType::SizeType  Image2size;
+		Image2size =  reader2->GetOutput()->GetRequestedRegion().GetSize();
+		
+		int sizeX1, sizeY1, sizeZ1;
+		int sizeX2, sizeY2, sizeZ2;
+		sizeX1 =Image1size[0];     sizeY1 = Image1size[1];    sizeZ1 = Image1size[2];
+		sizeX2 =Image2size[0];     sizeY2 = Image2size[1];    sizeZ2 = Image2size[2];
+		cout<<"Input Fixed image sizeX="<< sizeX1<<" sizeY="<<sizeY1<<" sizeZ="<<sizeZ1<<endl;
+		cout<<"Input Moving image sizeX="<< sizeX2<<" sizeY="<<sizeY2 <<" sizeZ="<<sizeZ2<<endl;
+		
+		int tempX, tempY, tempZ;
+		
+		InputImageType::RegionType::SizeType InternalImageSize;
+		if(sizeX1 >= sizeX2) tempX = sizeX1;
+		else tempX = sizeX2;
+		
+		if(sizeY1 >= sizeY2) tempY = sizeY1;
+		else tempY = sizeY2;
+		
+		if(sizeZ1 >= sizeZ2) tempZ = sizeZ1;
+		else tempZ = sizeZ2;
+		
+		int adjustX, adjustY, adjustZ;
+		
+		//adjustX =  ((tempX+2)>>2)<<2;	adjustY=  ((tempY+2)>>2)<<2;	adjustZ =  ((tempZ+2)>>2)<<2;
+		adjustX =  ((tempX+3)>>2)<<2;	adjustY=  ((tempY+3)>>2)<<2;	adjustZ =  ((tempZ+3)>>2)<<2;
+		cout<<"Adjusted image sizeX="<<adjustX<<" sizeY="<<adjustY <<" sizeZ="<<adjustZ<<endl;
+		
+		InternalImageSize[0] = adjustX;
+		InternalImageSize[1] = adjustY;
+		InternalImageSize[2] = adjustZ;
+		
+		return InternalImageSize;
+}
+
+void imagePreProcessing::makeSameSize(ReaderType::Pointer reader, OutputImageType::Pointer outImage, OutputImageType::RegionType::SizeType imageSize)
+{
+	InputImageType::RegionType::SizeType  inputImagesize;
+	inputImagesize =  reader->GetOutput()->GetRequestedRegion().GetSize();	
+	//cout<<"input image sizeX="<< inputImagesize[0]<<" sizeY="<<inputImagesize[1]<<" sizeZ="<<inputImagesize[2]<<endl;
+					  
+	IteratorType  inputIt( reader->GetOutput(), inputImagesize );
+	OutImageIteratorType  outIt( outImage, outImage->GetBufferedRegion() );
+	
+	int i,j,k;
+        int newSizeX, newSizeY, newSizeZ;
+	newSizeX = imageSize[0];	newSizeY = imageSize[1];	newSizeZ = imageSize[2];
+	
+	int oldSizeX, oldSizeY, oldSizeZ;
+	oldSizeX = inputImagesize[0];	oldSizeY = inputImagesize[1];	oldSizeZ = inputImagesize[2];
+	
+	for(k=0; k < newSizeZ; k++){
+	for(j=0; j < newSizeY; j++){
+        for(i=0; i < newSizeX; i++){
+
+		if((i<oldSizeX) && (j<oldSizeY) && (k<oldSizeZ)){
+			 outIt.Set(inputIt.Get());   
+			  ++inputIt;
+		 }
+		else {
+			outIt.Set((unsigned short)0);
+		}
+            
+	     ++outIt;
+
+        }
+        }
+        }	
+	
+//  for test
+	//testImageToFile(outImage);
+}
+
+void imagePreProcessing::GetNewSizedGrayImages(GrayImageType::Pointer outFixedGrayImage, GrayImageType::Pointer outMovingGrayImage)
+{
+	IteratorGrayType fi( newFixedGrayImage , ImageSize );
+	IteratorGrayType outIt( outFixedGrayImage, ImageSize );
+  
+	fi.GoToBegin();
+	outIt.GoToBegin();
+  
+	GrayPixelType t=0;
+	while( (!fi.IsAtEnd())&&(!outIt.IsAtEnd()) ){
+		t = fi.Get();     //cout << "2 " <<endl;
+    		outIt.Set(  t );  // cout << "3 " <<endl;
+    		++fi;
+		++outIt;
+    	}
+	
+	IteratorGrayType fi2( newMovingGrayImage , ImageSize );
+	IteratorGrayType outIt2( outMovingGrayImage, ImageSize );
+  
+	fi2.GoToBegin();
+	outIt2.GoToBegin();
+  
+	while( (!fi2.IsAtEnd())&&(!outIt2.IsAtEnd()) ){
+		t = fi2.Get();     //cout << "2 " <<endl;
+    		outIt2.Set(  t );  // cout << "3 " <<endl;
+    		++fi2;
+		++outIt2;
+    	}	
+}
+
+void imagePreProcessing::makeSameSizeGray(GrayReaderType::Pointer reader, GrayImageType::Pointer outImage, OutputImageType::RegionType::SizeType imageSize)
+{
+	GrayImageType::RegionType::SizeType  inputImagesize;
+	inputImagesize =  reader->GetOutput()->GetRequestedRegion().GetSize();	
+	cout<<"Gray image sizeX="<< inputImagesize[0]<<" sizeY="<<inputImagesize[1]<<" sizeZ="<<inputImagesize[2]<<endl;
+					  
+	IteratorGrayType  inputIt( reader->GetOutput(), inputImagesize );
+	OutImageIteratorGrayType  outIt( outImage, outImage->GetBufferedRegion() );
+	
+	int i,j,k;
+        int newSizeX, newSizeY, newSizeZ;
+	newSizeX = imageSize[0];	newSizeY = imageSize[1];	newSizeZ = imageSize[2];
+	
+	int oldSizeX, oldSizeY, oldSizeZ;
+	oldSizeX = inputImagesize[0];	oldSizeY = inputImagesize[1];	oldSizeZ = inputImagesize[2];
+	
+	for(k=0; k < newSizeZ; k++){
+	for(j=0; j < newSizeY; j++){
+        for(i=0; i < newSizeX; i++){
+
+		if((i<oldSizeX) && (j<oldSizeY) && (k<oldSizeZ)){
+			 outIt.Set(inputIt.Get());   
+			  ++inputIt;
+		 }
+		else {
+			outIt.Set((GrayPixelType)0);
+		}
+            
+	     ++outIt;
+
+        }
+        }
+        }	
+	
+//  for test
+	//testImageToFile(outImage);
+}
+	
+};
+
diff --git a/bioimagesuite30_src/DemonsRegistration/jwsReadWriteImages.h b/bioimagesuite30_src/DemonsRegistration/jwsReadWriteImages.h
new file mode 100644
index 0000000..adf8858
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/jwsReadWriteImages.h
@@ -0,0 +1,88 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include <string.h>
+#include "wook.h"
+
+#ifndef __jwsReadWriteImages__
+#define __jwsReadWriteImages__
+
+
+
+namespace jws_demons {
+
+  class imagePreProcessing {
+    
+  public:
+    ReaderType::Pointer FixedReader;
+    WriterType::Pointer FixedWriter;
+    ReaderType::Pointer MovingReader;
+    WriterType::Pointer MovingWriter;
+    InputImageType::RegionType::SizeType  ImageSize;
+    
+    OutputImageType::Pointer newFixedImage;
+    OutputImageType::Pointer newMovingImage;
+    
+    OutputImageType::Pointer outImage;	 
+    OutputImageType::RegionType region; 
+    InputImageType::RegionType::IndexType indexStart;
+    
+    GrayReaderType::Pointer GrayFixedReader;
+    GrayReaderType::Pointer GrayMovingReader;
+    
+    GrayImageType::Pointer newFixedGrayImage;
+    GrayImageType::Pointer newMovingGrayImage;
+    
+    string inputFixedName, inputMovingName;
+    string inputFixedGrayName, inputMovingGrayName, RegisteredGrayName;
+    string FixedSkinName, FixedBoneName, MovingSkinName, MovingBoneName;
+    
+    DMapFilterType::Pointer FixedSkinDMapfilter;
+    DMapFilterType::Pointer FixedBoneDMapfilter;		 
+    
+  public:
+    imagePreProcessing();
+    void loadImages(char * argv[]);
+    InputImageType::RegionType::SizeType decideImageSize(ReaderType::Pointer reader1, ReaderType::Pointer reader2);
+    void makeSameSizeAllInputImages(void);
+    void prepareSameSizedNewImages(void);
+    void makeSameSize(ReaderType::Pointer reader, OutputImageType::Pointer outImage, OutputImageType::RegionType::SizeType imageSize);
+    void makeSameSizeGray(GrayReaderType::Pointer reader, GrayImageType::Pointer outImage, OutputImageType::RegionType::SizeType imageSize);
+    // for image processing
+    void imageCleaning(OutputImageType::Pointer cleanFixedBone,  OutputImageType::Pointer cleanFixedSkin, OutputImageType::Pointer cleanMovingBone, OutputImageType::Pointer cleanMovingSkin);
+    void imagePreparation(InputImageType::Pointer inputImage, string &inputFileName, InputImageType::RegionType inputRegion, WriterType::Pointer writer,  OutputImageType::Pointer cleanOutImage, const InputPixelType upperTh, const InputPixelType lowerTh);
+    void morphologyBinaryFiltering(InputImageType::Pointer inputImage, WriterType::Pointer writer, InputImageType::RegionType inputRegion, const InputPixelType upperTh, const InputPixelType lowerTh, string simpleThresholdImageName, ClosingFilterType::Pointer binaryClosing );
+    void GetNewSizedGrayImages(GrayImageType::Pointer outFixedGrayImage, GrayImageType::Pointer outMovingGrayImage);
+    
+    
+    // for test
+    void testGrayImageToFile(GrayImageType::Pointer outImage, string InputFileName);
+    
+  };
+};
+#endif
+
diff --git a/bioimagesuite30_src/DemonsRegistration/jwsReadWriteImagesTest.cpp b/bioimagesuite30_src/DemonsRegistration/jwsReadWriteImagesTest.cpp
new file mode 100644
index 0000000..6106a66
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/jwsReadWriteImagesTest.cpp
@@ -0,0 +1,46 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include <string.h>
+#include "wook.h"
+
+#include "jwsReadWriteImages.h"
+
+namespace jws_demons {
+
+void imagePreProcessing::testGrayImageToFile(GrayImageType::Pointer outImage, string InputFileName)
+{
+  string fileName = InputFileName + "_resized.vtk";
+  
+  GrayWriterType::Pointer writer = GrayWriterType::New();
+  writer->SetFileName( fileName );
+  writer->SetInput( outImage );
+  writer->Update();
+}
+
+};
+
diff --git a/bioimagesuite30_src/DemonsRegistration/jwsSymmetricNewMain.cxx b/bioimagesuite30_src/DemonsRegistration/jwsSymmetricNewMain.cxx
new file mode 100644
index 0000000..37705b6
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/jwsSymmetricNewMain.cxx
@@ -0,0 +1,270 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include <string.h>
+#include "wook.h"
+#include "OtherFunctions.h"
+
+
+
+using namespace jws_demons;
+
+#include "firstExtendedSymmetricDemon.h"
+#include "secondExtendedSymmetricDemon.h"
+#include "thirdSymmetricDemon.h"
+#include "jwsReadWriteImages.h"
+
+
+
+
+// OtherFunctions.cxx
+/*
+// New Functions (three of them)
+// And key parameters
+DField*  RunRegistration1(Image* FixedBinary,Image* FixedGray,Image* MovingBinary, Image* MovingGray,int parameter1, float parameter2, int parameter 3)
+DField*  RunRegistration2(Image* FixedBinary,Image* FixedGray,Image* MovingBinary, Image* MovingGray)
+DField*  RunRegistration3(Image* FixedBinary,Image* FixedGray,Image* MovingBinary, Image* MovingGray)
+
+
+// Rewrite main Function ...
+NewMainFunction
+
+
+   1. Load Images
+   2. RunRegistration1 --- output should only be displacement field
+   3. Save Something   --- optionally warp and save
+   4. RunRegistration2
+   5. SaveSomething
+   6. RunRegistration3
+   7. Save
+   8. Done
+}
+
+See Examples in Levelset Directory
+
+vtkpx -- is a VTK Class wrapper around ITK
+
+
+Test how to convert vector images to VTK
+
+vtkImageData* img;   Allocatee
+for all pixels
+img->SetPixel(itkimg->GetPixel());
+
+
+Look at Levelset/vtkjwsDemonsRegistration for a boilerplate VTK Class
+
+*/
+
+
+
+int main( int argc, char * argv[] )
+{
+  if( argc < 6 )
+    {
+      std::cerr<< std::endl ;
+      std::cerr << "Usage (all input files should .vtk format): " << std::endl ;
+      std::cerr << argv[0]<<" FixedImageFile(No extension)  MovingImageFile(No extension) RegisteredImageFile(No extension) FixedGray(No extension) MovingGray(No extension) RegisteredGray(No extension)  ";   // 1 ,2, 3
+      std::cerr << std::endl<< std::endl;  
+      return EXIT_FAILURE;
+    }
+
+
+  imagePreProcessing PreClass;
+  
+  PreClass.loadImages( argv );
+  PreClass.makeSameSizeAllInputImages();       cout<<"0.5" <<endl;
+  
+  OutputImageType::Pointer cleanFixedBoneImage = OutputImageType::New();
+  OutputImageType::Pointer cleanFixedSkinImage = OutputImageType::New();
+  OutputImageType::Pointer cleanMovingBoneImage = OutputImageType::New();
+  OutputImageType::Pointer cleanMovingSkinImage = OutputImageType::New();
+  
+	
+  	cleanFixedBoneImage->SetRegions( PreClass.region );  							  
+	cleanFixedBoneImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	cleanFixedBoneImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	cleanFixedBoneImage->Allocate();    
+	
+  	cleanFixedSkinImage->SetRegions( PreClass.region );  							  
+	cleanFixedSkinImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	cleanFixedSkinImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	cleanFixedSkinImage->Allocate();  
+	
+	cleanMovingBoneImage->SetRegions( PreClass.region );  							  
+	cleanMovingBoneImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	cleanMovingBoneImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	cleanMovingBoneImage->Allocate();  
+	
+  	cleanMovingSkinImage->SetRegions( PreClass.region );  							  
+	cleanMovingSkinImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	cleanMovingSkinImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	cleanMovingSkinImage->Allocate();  	
+  
+  PreClass.imageCleaning(cleanFixedBoneImage, cleanFixedSkinImage, cleanMovingBoneImage, cleanMovingSkinImage);             
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+		GrayImageType::Pointer newFixedGrayImage = GrayImageType::New();
+		GrayImageType::Pointer newMovingGrayImage = GrayImageType::New();
+		
+		newFixedGrayImage->SetRegions( PreClass.region );
+		newFixedGrayImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+		newFixedGrayImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+		newFixedGrayImage->Allocate();
+		
+		newMovingGrayImage->SetRegions( PreClass.region );
+		newMovingGrayImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+		newMovingGrayImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+		newMovingGrayImage->Allocate();	
+		
+   PreClass.GetNewSizedGrayImages(newFixedGrayImage, newMovingGrayImage);
+		
+ ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
+  
+  FixedImageType::Pointer fixedBoneDMapImage = FixedImageType::New();
+  FixedImageType::Pointer fixedSkinDMapImage = FixedImageType::New();
+  MovingImageType::Pointer movingBoneDMapImage = MovingImageType::New();
+  
+  	fixedBoneDMapImage->SetRegions( PreClass.region );  							  
+	fixedBoneDMapImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	fixedBoneDMapImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	fixedBoneDMapImage->Allocate(); 
+	
+  	fixedSkinDMapImage->SetRegions( PreClass.region );  							  
+	fixedSkinDMapImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	fixedSkinDMapImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	fixedSkinDMapImage->Allocate(); 
+	
+	movingBoneDMapImage->SetRegions( PreClass.region );  							  
+	movingBoneDMapImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	movingBoneDMapImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	movingBoneDMapImage->Allocate(); 
+  // Fixed Bone
+  DistanceMapGeneration( "cleanFixedBone", cleanFixedBoneImage, fixedBoneDMapImage, PreClass.region);
+ 
+    // Fixed Skin
+  DistanceMapGeneration( "cleanFixedSkin", cleanFixedSkinImage, fixedSkinDMapImage, PreClass.region);
+  
+  // Moving Bone
+  DistanceMapGeneration( "cleanMovingBone", cleanMovingBoneImage, movingBoneDMapImage, PreClass.region);
+
+ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
+
+     DeformationFieldType::Pointer DFieldBone = DeformationFieldType::New();     
+     DFieldBone->SetRegions( PreClass.region  );
+     DFieldBone->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin()  );
+     DFieldBone->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+     DFieldBone->Allocate();
+     
+     InternalImageType::Pointer deformedBoneImg = InternalImageType::New();
+     deformedBoneImg->SetRegions( PreClass.region );
+     deformedBoneImg->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin());
+     deformedBoneImg->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+     deformedBoneImg->Allocate();
+     
+     InputImageType::Pointer UshortDeformedSkinImg = InputImageType::New();
+     UshortDeformedSkinImg ->SetRegions(PreClass.region );
+     UshortDeformedSkinImg ->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+     UshortDeformedSkinImg ->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+     UshortDeformedSkinImg ->Allocate();		
+     
+     GrayImageType::Pointer firstDeformedGrayImg = GrayImageType::New();
+     firstDeformedGrayImg->SetRegions( PreClass.region);
+     firstDeformedGrayImg->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+     firstDeformedGrayImg->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+     firstDeformedGrayImg->Allocate();		
+     
+     ////////////////////////////////// First Extended Demon with only Bone Distance Map   ///////////////////////////////////////////////
+     string boneOnlyRegistrationResult = "FirstRegResultHalf";
+     FIRST_SEDEMON::firstExtendedDemonRegistration(fixedBoneDMapImage, movingBoneDMapImage, DFieldBone, boneOnlyRegistrationResult);	
+	 
+     myWarper(movingBoneDMapImage,  deformedBoneImg, DFieldBone );
+     myWarperGray(newMovingGrayImage,  firstDeformedGrayImg, DFieldBone, "firstDeformedGray" ); 
+	 
+     // 1. Deform Skin(actually whole moving image) by bone-DField
+     // 2. Generate distance map of the deformed skin
+     myWarperUShort(cleanMovingSkinImage, UshortDeformedSkinImg , DFieldBone );	
+    
+     MovingImageType::Pointer movingSkinDMapImage = MovingImageType::New();
+	
+	movingSkinDMapImage->SetRegions( PreClass.region );  							  
+	movingSkinDMapImage->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );     
+	movingSkinDMapImage->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );  
+	movingSkinDMapImage->Allocate(); 	 
+	 // Moving Skine
+    DistanceMapGeneration( "firstDeformedMovingSkin", UshortDeformedSkinImg, movingSkinDMapImage, PreClass.region);
+     
+	       
+     ///////////////////////////////// Combine Two images for one-time registration   ///////////////////////////////////////////////////////
+     InternalImageType::Pointer combinedDMapFixedImage = InternalImageType::New();
+     mergeImages(fixedSkinDMapImage, fixedBoneDMapImage, combinedDMapFixedImage,"combineDMFixedImage.vtk");
+     
+     InternalImageType::Pointer combinedDMapFirstDeformedImage = InternalImageType::New();
+     mergeImages(movingSkinDMapImage, deformedBoneImg, combinedDMapFirstDeformedImage , "combinedFirstDeformedImage.vtk");
+   
+/*	 
+     // just for test
+     string combinedDMapMovingFileName = "combinedDMMovingImage.vtk";
+     InternalImageType::Pointer combinedDMapMovingImage = InternalImageType::New();
+     mergeImages(movingSkinDMapImage, movingBoneDMapImage, combinedDMapMovingImage, combinedDMapMovingFileName);		
+*/      	 
+     /////////////////////////////////////////////////////////  Extended Demons Registration  //////////////////////////////////////////////////
+     //		string registeredImageName(argv[3]);
+     
+     DeformationFieldType::Pointer DField2 = DeformationFieldType::New();
+     DField2->SetRegions( PreClass.region );
+     DField2->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+     DField2->SetSpacing(PreClass.FixedReader->GetOutput()->GetSpacing() );
+     DField2->Allocate();
+     
+          SECOND_SEDEMON::ExtendedDemonRegistrationMain(combinedDMapFixedImage, combinedDMapFirstDeformedImage, DField2, "SecondRegResult");	
+	    DfieldToFile(DField2, "SecondRegResultHalf");
+     
+	 
+     GrayImageType::Pointer secondDeformedGrayImg = GrayImageType::New();
+     secondDeformedGrayImg->SetRegions( PreClass.region );
+     secondDeformedGrayImg->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+     secondDeformedGrayImg->SetSpacing( PreClass.FixedReader->GetOutput()->GetSpacing() );
+     secondDeformedGrayImg->Allocate();		
+     
+     myWarperGray(firstDeformedGrayImg, secondDeformedGrayImg, DField2, "secondDeformedGray" );
+#if 1
+
+     DeformationFieldType::Pointer DField3 = DeformationFieldType::New();
+     DField3->SetRegions( PreClass.region );
+     DField3->SetOrigin( PreClass.FixedReader->GetOutput()->GetOrigin() );
+     DField3->SetSpacing(PreClass.FixedReader->GetOutput()->GetSpacing() );
+     DField3->Allocate();
+
+          THIRD_SEDEMON::DemonRegistrationMain(newFixedGrayImage, secondDeformedGrayImg, DField3, "thirdDeformedGray");	
+     
+#endif	 
+     return EXIT_SUCCESS;
+ 
+}
+
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/secondExtendedDemon.h b/bioimagesuite30_src/DemonsRegistration/secondExtendedDemon.h
new file mode 100644
index 0000000..96cf4a7
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/secondExtendedDemon.h
@@ -0,0 +1,742 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//#include "wook.h"
+#include "tnt/tnt_array3d.h"
+#include <math.h>
+
+
+
+//#define GET_NUMBER_OF_THREADS
+#define GET_INFORMATION_ON_ITERATION
+
+//#define SET_SMALL_NUMBER_THREADS
+//#define FORCED_UPDATE
+extern void testDMapImageToFile(TNT::Array3D<float> &DMap, int sizeX, int sizeY, int sizeZ,  FixedImageType::ConstPointer fxImage);
+extern void testDfieldImageToFile(TNT::Array3D<VectorPixelType> &DField, int sizeX, int sizeY, int sizeZ,  DeformationFieldType::Pointer DImage);
+
+extern void gaussianFilteringForVectorImage(TNT::Array3D<VectorPixelType>& vFieldCombined, int sizeX, int sizeY, int sizeZ, float variance);
+
+namespace SECOND_EDEMON{
+template <typename TRegistration>
+class RegistrationInterfaceCommand : public itk::Command
+{
+
+public:
+  typedef  RegistrationInterfaceCommand   Self;
+  typedef  itk::Command                   Superclass;
+  typedef  itk::SmartPointer<Self>        Pointer;
+  itkNewMacro( Self );
+protected:
+  RegistrationInterfaceCommand() {};
+
+public:
+  typedef   TRegistration                              RegistrationType;
+  typedef   RegistrationType *                         RegistrationPointer;
+
+  typedef itk::Vector< float, Dimension >    VectorPixelType;
+  typedef itk::Image< float, Dimension > InternalImageType;
+  typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+  typedef itk::jwsDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+  
+  void Execute(itk::Object * object, const itk::EventObject & event)
+  {
+
+    if( !(itk::IterationEvent().CheckEvent( &event )) )
+      {
+      return;
+      }
+     
+
+    RegistrationPointer registration =
+                            dynamic_cast<RegistrationPointer>( object );
+    // for MultiResolutionPDEDeformableRegistration
+
+
+    RegistrationFilterType * filter = dynamic_cast< RegistrationFilterType * >(
+                       registration->GetRegistrationFilter() );
+       // for Demon Registration algorithm
+    
+
+    std::cout << "level:"<<registration->GetCurrentLevel() <<std::endl;
+                 
+    if ( registration->GetCurrentLevel() == 1 )
+      {
+        std::cout << "*****   level 111111" <<std::endl;
+        std::cout<<"In Multilevel : "  <<  filter->GetElapsedIterations()<< std::endl;
+      }
+     
+  }
+
+
+  void Execute(const itk::Object * , const itk::EventObject & )
+    { return; }
+};
+
+
+
+
+//  The following section of code implements a Command observer
+//  that will monitor the evolution of the registration process.
+//
+  class CommandIterationUpdate : public itk::Command
+  {
+  public:
+    typedef  CommandIterationUpdate   Self;
+    typedef  itk::Command             Superclass;
+    typedef  itk::SmartPointer<CommandIterationUpdate>  Pointer;
+
+    double lPreviousValue;
+    double lCurrentValue ;
+    double lDiff;
+    double lDiff_Diff;
+    double lPrevDiff;
+    int     nContinueCount, nIncreased;
+    FILE *fp;
+
+
+    itkNewMacro( CommandIterationUpdate );
+  protected:
+    CommandIterationUpdate() {};
+
+    typedef itk::Image< float, Dimension > InternalImageType;
+    typedef itk::Vector< float, Dimension >    VectorPixelType;
+    typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+    typedef itk::jwsDemonsRegistrationFilter<
+                                  InternalImageType,
+                                  InternalImageType,
+                                  DeformationFieldType> RegistrationFilterType;
+	
+    typedef itk::ImageRegionIterator< DeformationFieldType > FieldIterator;
+    typedef itk::ImageRegionConstIterator< InternalImageType > DMapIterator;
+	
+    VectorPixelType displacement;
+    DeformationFieldType::IndexType index;
+
+  public:
+
+    void InitFile(void)
+    {
+         //fp = fopen("Diff_data.txt","w");
+         nIncreased = 0;
+    }
+
+    void CloseFile(void)
+    {
+        //fclose(fp);
+    } 
+        
+  
+    void Execute(itk::Object *caller, const itk::EventObject & event)
+      {
+       // Execute( (const itk::Object *)caller, event);
+#if 1
+           RegistrationFilterType * filter =
+            dynamic_cast< RegistrationFilterType * >( caller );
+
+            unsigned int unElapsedIter;  // by wook
+	   DeformationFieldType::Pointer Dfield;
+	   FixedImageType::ConstPointer fxImage;   // Ohhh  -> ConstPointer for const pointer
+	   
+          if( !(itk::IterationEvent().CheckEvent( &event )) )
+            {
+            return;
+            }
+            
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#if 0                        // with my smoothing
+		  
+	 Dfield = filter->GetDeformationField();
+	 
+	 fxImage =filter->GetFixedImage();
+//	 fxImage =filter->GetMovingImage();
+	 
+	 int dx, dy, dz;
+	 dx = Dfield->GetRequestedRegion().GetSize()[0];
+	 dy = Dfield->GetRequestedRegion().GetSize()[1];
+	 dz = Dfield->GetRequestedRegion().GetSize()[2];
+	 cout << "DeformableRegistration.cxx dx =" <<dx<<" dy="<<dy<<" dz="<<dz<<endl;
+	 
+	 int orgSizeX = dx >> 1;
+	 
+         TNT::Array3D<float> fixedSkinDMap( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<float> fixedBoneDMap( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldSkin( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldBone( orgSizeX, dy, dz, (float)0);
+	 
+	 TNT::Array3D<VectorPixelType> vFieldCombined( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldAdjusted( dx, dy, dz, (float)0);
+	 
+         FieldIterator fi( Dfield,  Dfield->GetRequestedRegion().GetSize() );
+	 DMapIterator DMapIt( fxImage,   fxImage->GetRequestedRegion().GetSize());
+
+  	fi.GoToBegin();   //std::cout <<"test!!!"<<endl;
+	DMapIt.GoToBegin();
+
+	int i,j,k;
+
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < dx; i++){
+			
+		if(i<orgSizeX) {		
+			
+			fixedSkinDMap[i][j][k] =  DMapIt.Get();
+			vFieldSkin[i][j][k] =  fi.Get();
+		
+		}
+		else {
+			fixedBoneDMap[i - orgSizeX][j][k] =  DMapIt.Get();
+			vFieldBone[i - orgSizeX][j][k] =  fi.Get();
+		}
+	    
+             ++fi;  
+	     ++DMapIt;
+
+         }
+         }
+         }		
+
+	
+//	if(dx == 328) {
+//		testDMapImageToFile(fixedSkinDMap, orgSizeX, dy, dz, fxImage);
+//		testDfieldImageToFile(vFieldSkin, orgSizeX, dy, dz, Dfield);
+//        }
+	
+	float abs_skinDMap, abs_boneDMap, abs_sum;
+	abs_skinDMap = 0.0; 	abs_boneDMap = 0.0;	abs_sum = 0.0;
+	
+	float skin_ratio=0.0, bone_ratio=0.0;
+	float bone_no_change_value;
+	
+	bone_no_change_value = 0.0;
+	//bone_no_change_value = 1.0;
+	
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < orgSizeX; i++){
+			
+			if(fixedBoneDMap[i][j][k] <= bone_no_change_value) {  // bone	
+				
+				    vFieldCombined[i][j][k][0] = 0.0;
+                                    vFieldCombined[i][j][k][1] = 0.0;
+                                    vFieldCombined[i][j][k][2] = 0.0;
+				
+			}
+			else  {  // skin
+				
+				    vFieldCombined[i][j][k][0] = vFieldSkin[i][j][k][0];
+                                    vFieldCombined[i][j][k][1] = vFieldSkin[i][j][k][1];
+                                    vFieldCombined[i][j][k][2] = vFieldSkin[i][j][k][2];								
+			}
+	}
+	}
+        }
+	
+	// smoothing
+	float variance = 1.0;
+	gaussianFilteringForVectorImage( vFieldCombined, orgSizeX, dy, dz, variance);
+	
+	// make the vector of the bone(which was smoothed) zero vector
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < orgSizeX; i++){
+			
+			if(fixedBoneDMap[i][j][k] <= bone_no_change_value) {  // bone	
+				
+				    vFieldCombined[i][j][k][0] = 0.0;
+                                    vFieldCombined[i][j][k][1] = 0.0;
+                                    vFieldCombined[i][j][k][2] = 0.0;				
+			}
+	}
+	}
+        }	
+
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < orgSizeX; i++){
+	
+		vFieldAdjusted[i][j][k][0] = vFieldCombined[i][j][k][0];
+		vFieldAdjusted[i+orgSizeX][j][k][0] = vFieldCombined[i][j][k][0];
+			
+		vFieldAdjusted[i][j][k][1] = vFieldCombined[i][j][k][1];
+		vFieldAdjusted[i+orgSizeX][j][k][1] = vFieldCombined[i][j][k][1];
+		
+		vFieldAdjusted[i][j][k][2] = vFieldCombined[i][j][k][2];	
+		vFieldAdjusted[i+orgSizeX][j][k][2] = vFieldCombined[i][j][k][2];
+
+         }
+         }
+         }
+	
+
+	fi.GoToBegin(); 
+	
+  	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < dx; i++) {       
+//		displacement = fi.Get();
+//             	std::cout <<"("<<displacement[0]<<","<<displacement[1]<<","<<displacement[2]<<")   : ";
+    		
+		#if 1
+		displacement[0] = vFieldAdjusted[i][j][k][0];
+    		displacement[1] = vFieldAdjusted[i][j][k][1];
+		displacement[2] = vFieldAdjusted[i][j][k][2];
+		#endif
+//		std::cout <<"("<<displacement[0]<<","<<displacement[1]<<","<<displacement[2]<<")"<<std::endl;
+    		fi.Set( displacement );
+    		++fi;
+    	}
+	}
+	}
+	
+	 filter->setMyDField(Dfield);
+#endif
+	 
+#if 1          // without my smoothing  because there is another smoothing within the Demon
+	 Dfield = filter->GetDeformationField();
+	 
+	 fxImage =filter->GetFixedImage();
+//	 fxImage =filter->GetMovingImage();
+	 
+	 int dx, dy, dz;
+	 dx = Dfield->GetRequestedRegion().GetSize()[0];
+	 dy = Dfield->GetRequestedRegion().GetSize()[1];
+	 dz = Dfield->GetRequestedRegion().GetSize()[2];
+	 cout << "dx =" <<dx<<" dy="<<dy<<" dz="<<dz<<endl;
+	 
+	 int orgSizeX = dx >> 1;
+	 
+         TNT::Array3D<float> fixedSkinDMap( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<float> fixedBoneDMap( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldSkin( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldBone( orgSizeX, dy, dz, (float)0);
+	 
+	 TNT::Array3D<VectorPixelType> vFieldCombined( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldAdjusted( dx, dy, dz, (float)0);
+	 
+         FieldIterator fi( Dfield,  Dfield->GetRequestedRegion().GetSize() );
+	 DMapIterator DMapIt( fxImage,   fxImage->GetRequestedRegion().GetSize());
+
+  	fi.GoToBegin();   //std::cout <<"test!!!"<<endl;
+	DMapIt.GoToBegin();
+
+	int i,j,k;
+
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < dx; i++){
+			
+		if(i<orgSizeX) {		
+			
+			fixedSkinDMap[i][j][k] =  DMapIt.Get();
+			vFieldSkin[i][j][k] =  fi.Get();
+		
+		}
+		else {
+			fixedBoneDMap[i - orgSizeX][j][k] =  DMapIt.Get();
+			vFieldBone[i - orgSizeX][j][k] =  fi.Get();
+		}
+	    
+             ++fi;  
+	     ++DMapIt;
+
+         }
+         }
+         }		
+
+	
+//	if(dx == 328) {
+//		testDMapImageToFile(fixedSkinDMap, orgSizeX, dy, dz, fxImage);
+//		testDfieldImageToFile(vFieldSkin, orgSizeX, dy, dz, Dfield);
+//        }
+	
+	float abs_skinDMap, abs_boneDMap, abs_sum;
+	abs_skinDMap = 0.0; 	abs_boneDMap = 0.0;	abs_sum = 0.0;
+	
+	float skin_ratio=0.0, bone_ratio=0.0;
+	
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < orgSizeX; i++){
+			
+			if((fixedSkinDMap[i][j][k]<0) && (fixedBoneDMap[i][j][k] <=0)) {  // bone	
+				
+				    vFieldCombined[i][j][k][0] = vFieldBone[i][j][k][0];
+                                    vFieldCombined[i][j][k][1] = vFieldBone[i][j][k][1];
+                                    vFieldCombined[i][j][k][2] = vFieldBone[i][j][k][2];
+				
+			}
+			else if((fixedSkinDMap[i][j][k]>=0) && (fixedBoneDMap[i][j][k] >0)) {  // skin
+				
+				    vFieldCombined[i][j][k][0] = vFieldSkin[i][j][k][0];
+                                    vFieldCombined[i][j][k][1] = vFieldSkin[i][j][k][1];
+                                    vFieldCombined[i][j][k][2] = vFieldSkin[i][j][k][2];				
+				
+			}
+			else if((fixedSkinDMap[i][j][k]<0) && (fixedBoneDMap[i][j][k] >0)){
+				
+				    abs_skinDMap 	= 	fabs(fixedSkinDMap[i][j][k]);
+				    abs_boneDMap 	=	fabs(fixedBoneDMap[i][j][k]);
+				    abs_sum = abs_skinDMap + abs_boneDMap;
+					
+				    skin_ratio = abs_boneDMap / abs_sum;
+				    bone_ratio = abs_skinDMap / abs_sum;
+					
+//cout<<"abs_skin="<<abs_skinDMap <<" abs_bone="<<abs_boneDMap<<" abs_sum="<<abs_sum<<endl;
+				    vFieldCombined[i][j][k][0] = (bone_ratio * vFieldBone[i][j][k][0]) + (skin_ratio * vFieldSkin[i][j][k][0]);
+                                    vFieldCombined[i][j][k][1] =  (bone_ratio * vFieldBone[i][j][k][1]) + (skin_ratio * vFieldSkin[i][j][k][1]);
+                                    vFieldCombined[i][j][k][2] =  (bone_ratio * vFieldBone[i][j][k][2]) + (skin_ratio * vFieldSkin[i][j][k][2]);			
+			}
+			else {  // exceptional cases
+				cout<<"exceptional case at ("<<i<<", "<<j<<", "<<k<<") fixedSkinDMap="<<fixedSkinDMap[i][j][k]<<" fixedBoneDMap="<< fixedBoneDMap[i][j][k]<<endl;
+				    vFieldCombined[i][j][k][0] = 0.0;
+                                    vFieldCombined[i][j][k][1] = 0.0;
+                                    vFieldCombined[i][j][k][2] = 0.0;				
+			}
+	}
+	}
+        }
+	
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < orgSizeX; i++){
+	
+		vFieldAdjusted[i][j][k][0] = vFieldCombined[i][j][k][0];
+		vFieldAdjusted[i+orgSizeX][j][k][0] = vFieldCombined[i][j][k][0];
+			
+		vFieldAdjusted[i][j][k][1] = vFieldCombined[i][j][k][1];
+		vFieldAdjusted[i+orgSizeX][j][k][1] = vFieldCombined[i][j][k][1];
+		
+		vFieldAdjusted[i][j][k][2] = vFieldCombined[i][j][k][2];	
+		vFieldAdjusted[i+orgSizeX][j][k][2] = vFieldCombined[i][j][k][2];
+
+         }
+         }
+         }
+	
+
+	fi.GoToBegin(); 
+	
+  	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < dx; i++) {       
+//		displacement = fi.Get();
+//             	std::cout <<"("<<displacement[0]<<","<<displacement[1]<<","<<displacement[2]<<")   : ";
+    		
+		#if 1
+		displacement[0] = vFieldAdjusted[i][j][k][0];
+    		displacement[1] = vFieldAdjusted[i][j][k][1];
+		displacement[2] = vFieldAdjusted[i][j][k][2];
+		#endif
+//		std::cout <<"("<<displacement[0]<<","<<displacement[1]<<","<<displacement[2]<<")"<<std::endl;
+    		fi.Set( displacement );
+    		++fi;
+    	}
+	}
+	}
+
+	 filter->setMyDField(Dfield);
+#endif
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+          unElapsedIter = filter->GetElapsedIterations();
+          lPreviousValue = lCurrentValue;
+          lCurrentValue = filter->GetMetric();
+
+          lPrevDiff = lDiff;
+          lDiff = fabs(lPreviousValue - lCurrentValue);
+          lDiff_Diff = fabs(lPrevDiff - lDiff) *100;
+                   
+          //fprintf(fp,"%d %f\n",unElapsedIter,lCurrentValue);
+          
+          
+          if(lDiff < 0.0001) nContinueCount++;    // when input data is signed float (minus value for inside)
+          //if(lDiff < 0.1) nContinueCount++;  // when input data is unsigned short
+          else  nContinueCount = 0;
+
+          #ifdef GET_INFORMATION_ON_ITERATION
+          if(lPreviousValue > lCurrentValue){
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= -"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<<std::endl;
+            nIncreased = 0;                                                                                                              
+          } 
+          else{
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= +"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<< std::endl;
+            nIncreased++;                                                                                                                         
+          } 
+                                                                                                                                                                                                                                
+          if(nContinueCount > 10){
+                nContinueCount = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continuous negligible variations     "<<std::endl;                                
+          }
+
+          if(nIncreased > 20){
+                nIncreased = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continumes metric increasement      "<<std::endl;                              
+          }
+          
+                        
+          #endif
+                                                        
+          #if 0  
+          
+          std::cout << unElapsedIter << " " << filter->GetMetric() << std::endl;
+
+          if(unElapsedIter ==20){ std::cout << "********************************  count!!"<<std::endl;
+              filter->StopRegistration();
+          }
+          #endif
+#endif
+      }
+
+    void Execute(const itk::Object * object, const itk::EventObject & event)
+      {
+	}
+  };
+
+
+#if  1
+void ExtendedDemonRegistrationMain(FixedImageType::Pointer fixedImage, MovingImageType::Pointer movingImage, DeformationFieldType::Pointer resultingHalfDField, string registeredImageName)
+{
+  std::cout <<" start second registration!! " <<std::endl;   
+  std::cout <<"1: accept parameter  " <<std::endl;
+		
+#if 0
+  typedef itk::HistogramMatchingImageFilter<                      
+                                    InternalImageType,
+                                    InternalImageType >   MatchingFilterType;
+  MatchingFilterType::Pointer matcher = MatchingFilterType::New();
+
+  std::cout <<"2: set HistogramMatchingImageFilter  " <<std::endl;
+  matcher->SetInput( movingImage );       
+  matcher->SetReferenceImage( fixedImage );
+  matcher->SetNumberOfHistogramLevels( 1024 );
+  matcher->SetNumberOfMatchPoints( 7 );
+  matcher->ThresholdAtMeanIntensityOn();
+
+   #ifdef SET_SMALL_NUMBER_THREADS
+     matcher->SetNumberOfThreads(1);
+   #endif
+
+   #ifdef FORCED_UPDATE
+     matcher->Update();
+   #endif
+
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for HistogramMatchingImageFilter: "<<matcher->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+#endif
+  std::cout <<"6: generate DeformationFieldType format  " <<std::endl;
+
+  typedef itk::jwsDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+
+  std::cout <<"7: set  DemonsRegistrationFilter " <<std::endl;
+  RegistrationFilterType::Pointer filter = RegistrationFilterType::New();
+
+  filter->SetNumberOfIterations( 50 );
+  filter->SetStandardDeviations( 1.0 );
+  //filter->SetStandardDeviations( 0.0 );
+
+
+     #ifdef SET_SMALL_NUMBER_THREADS
+       filter->SetNumberOfThreads(1);
+     #endif
+
+  
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for DemonsRegistrationFilter: "<<filter->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+  /////////////////////////////////////////////////////////////////////////////
+  std::cout <<"8: set  CommandIterationUpdate " <<std::endl;
+  CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
+  observer->InitFile();
+
+  std::cout <<"9: filter->AddObserver " <<std::endl;
+  filter->AddObserver( itk::IterationEvent(), observer );
+
+     
+  /////////////////////////////////////////////////////////////////////////////
+
+  typedef itk::jwsMultiResolutionPDEDeformableRegistration<
+                                InternalImageType,
+                                InternalImageType,
+                                DeformationFieldType >   MultiResRegistrationFilterType;
+
+  std::cout <<"10: set MultiResolutionPDEDeformableRegistration " <<std::endl;
+  MultiResRegistrationFilterType::Pointer multires = MultiResRegistrationFilterType::New();
+  multires->SetRegistrationFilter( filter );
+  
+  int numberOfLevels = 3;
+  //unsigned int nIterations[3] = { 2,2,1 };     // for test
+//  unsigned int nIterations[3] = { 10,10, 4 };     // for test
+unsigned int nIterations[3] = { 200,200, 30 };     // for test
+ 
+  multires->SetNumberOfLevels( numberOfLevels ); 
+  multires->SetFixedImage( fixedImage );
+  //multires->SetMovingImage( matcher->GetOutput() );   // turn off the histogram matching for distance mapping demon
+                                                                               // by wook 02/28/08
+  multires->SetMovingImage( movingImage );
+
+  #ifdef SET_SMALL_NUMBER_THREADS
+    multires->SetNumberOfThreads(1);
+  #endif
+ 
+  multires->SetNumberOfIterations( nIterations );  
+
+
+   /******************  by wook    ***************************/
+   std::cout <<"11: set multires->AddObserver " <<std::endl;
+   typedef RegistrationInterfaceCommand<MultiResRegistrationFilterType> CommandType;
+   CommandType::Pointer command = CommandType::New();
+   multires->AddObserver( itk::IterationEvent(), command );
+//   multires->Update();
+   /*****************************************************************/
+
+
+ #ifdef FORCED_UPDATE
+   multires->Update();
+ #endif
+
+
+#ifdef GET_NUMBER_OF_THREADS
+
+  std::cout <<" Number of Threads for MultiResolutionPDEDeformableRegistration: "<<multires->GetNumberOfThreads() << std::endl;
+
+#endif
+                
+
+  std::cout <<"12: WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  typedef itk::LinearInterpolateImageFunction<
+                                   MovingImageType,
+                                   double          >  InterpolatorType;
+  WarperType::Pointer warper = WarperType::New();
+  InterpolatorType::Pointer interpolator = InterpolatorType::New();
+//  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
+
+  std::cout <<"13: initialize WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  warper->SetInput( movingImage );
+  warper->SetInterpolator( interpolator );
+
+
+  warper->SetOutputSpacing( fixedImage->GetSpacing() );
+  warper->SetOutputOrigin( fixedImage->GetOrigin() );
+  warper->SetDeformationField( multires->GetOutput() );
+
+  // by wook to set the large value as outside pixel value
+  warper->SetEdgePaddingValue(65535L);
+     warper->Update();
+
+ if(registeredImageName.length()>0){
+	 typedef float  OutputPixelType;
+	 typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
+	 typedef itk::CastImageFilter< 
+			 MovingImageType,
+			 OutputImageType > CastFilterType;
+  
+	  typedef itk::ImageFileWriter< OutputImageType >  WriterType;
+
+  
+	  WriterType::Pointer      writer =  WriterType::New();
+	  CastFilterType::Pointer  caster =  CastFilterType::New();
+
+	  string boneRegisteredImageFileName = registeredImageName + "Both";
+	  string skinRegisteredImageFileName = registeredImageName + "Skin";
+		
+	  string boneRegisteredFileNamewithExtension =boneRegisteredImageFileName + ".vtk";
+	  writer->SetFileName( boneRegisteredFileNamewithExtension );
+  
+	  caster->SetInput( warper->GetOutput() );
+	  writer->SetInput( caster->GetOutput() );
+	  writer->Update();
+  
+
+	  FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
+
+	  string deformationFieldFileNamewithExtension = registeredImageName + "_DField.vtk";
+	  fieldWriter->SetFileName( deformationFieldFileNamewithExtension );
+	  fieldWriter->SetInput( multires->GetOutput() );
+	  fieldWriter->Update();
+
+   }
+  std::cout <<"16: observer->CloseFile()" <<std::endl;
+  observer->CloseFile();  // by wook
+
+
+
+	////////////////////// store half DField  /////////////////////////////////////////
+  	 int dx, dy, dz;
+	 dx = multires->GetOutput()->GetRequestedRegion().GetSize()[0];
+	 dy = multires->GetOutput()->GetRequestedRegion().GetSize()[1];
+	 dz = multires->GetOutput()->GetRequestedRegion().GetSize()[2];
+	 
+	 int halfSizeX = dx >>1; cout<<" halfSizeX= "<<halfSizeX<<endl;
+	//TNT::Array3D<VectorPixelType> vField( dx, dy, dz, (float)0);
+	DfieldIteratorType fieldIt( multires->GetOutput(), multires->GetOutput()->GetRequestedRegion().GetSize() );
+	DfieldIteratorType fieldOut( resultingHalfDField, resultingHalfDField->GetRequestedRegion().GetSize() );
+	
+	cout<< "size of From SecondDField = "<<multires->GetOutput()->GetRequestedRegion().GetSize()<<endl;
+	cout<<"size of To SecondDField=" <<resultingHalfDField->GetRequestedRegion().GetSize()<<endl;
+	
+	fieldIt.GoToBegin();
+	fieldOut.GoToBegin();
+	
+	int i,j,k;
+
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < dx; i++){
+			
+		if(i<halfSizeX) {		
+	
+			fieldOut.Set(  fieldIt.Get() );
+			++fieldOut;
+		}
+	        ++fieldIt;
+
+         }
+         }
+         }
+	
+//  return 0;
+}
+}   //   namespace SECOND_EDEMON
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/secondExtendedSymmetricDemon.h b/bioimagesuite30_src/DemonsRegistration/secondExtendedSymmetricDemon.h
new file mode 100644
index 0000000..cb8756a
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/secondExtendedSymmetricDemon.h
@@ -0,0 +1,743 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//#include "wook.h"
+#include "tnt/tnt_array3d.h"
+#include <math.h>
+
+
+
+//#define GET_NUMBER_OF_THREADS
+#define GET_INFORMATION_ON_ITERATION
+
+//#define SET_SMALL_NUMBER_THREADS
+//#define FORCED_UPDATE
+extern void testDMapImageToFile(TNT::Array3D<float> &DMap, int sizeX, int sizeY, int sizeZ,  FixedImageType::ConstPointer fxImage);
+extern void testDfieldImageToFile(TNT::Array3D<VectorPixelType> &DField, int sizeX, int sizeY, int sizeZ,  DeformationFieldType::Pointer DImage);
+
+extern void gaussianFilteringForVectorImage(TNT::Array3D<VectorPixelType>& vFieldCombined, int sizeX, int sizeY, int sizeZ, float variance);
+
+namespace SECOND_SEDEMON{
+template <typename TRegistration>
+class RegistrationInterfaceCommand : public itk::Command
+{
+
+public:
+  typedef  RegistrationInterfaceCommand   Self;
+  typedef  itk::Command                   Superclass;
+  typedef  itk::SmartPointer<Self>        Pointer;
+  itkNewMacro( Self );
+protected:
+  RegistrationInterfaceCommand() {};
+
+public:
+  typedef   TRegistration                              RegistrationType;
+  typedef   RegistrationType *                         RegistrationPointer;
+
+  typedef itk::Vector< float, Dimension >    VectorPixelType;
+  typedef itk::Image< float, Dimension > InternalImageType;
+  typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+  typedef itk::jwsDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+  
+  void Execute(itk::Object * object, const itk::EventObject & event)
+  {
+
+    if( !(itk::IterationEvent().CheckEvent( &event )) )
+      {
+      return;
+      }
+     
+
+    RegistrationPointer registration =
+                            dynamic_cast<RegistrationPointer>( object );
+    // for MultiResolutionPDEDeformableRegistration
+
+
+    RegistrationFilterType * filter = dynamic_cast< RegistrationFilterType * >(
+                       registration->GetRegistrationFilter() );
+       // for Demon Registration algorithm
+    
+
+    std::cout << "level:"<<registration->GetCurrentLevel() <<std::endl;
+                 
+    if ( registration->GetCurrentLevel() == 1 )
+      {
+        std::cout << "*****   level 111111" <<std::endl;
+        std::cout<<"In Multilevel : "  <<  filter->GetElapsedIterations()<< std::endl;
+      }
+     
+  }
+
+
+  void Execute(const itk::Object * , const itk::EventObject & )
+    { return; }
+};
+
+
+
+
+//  The following section of code implements a Command observer
+//  that will monitor the evolution of the registration process.
+//
+  class CommandIterationUpdate : public itk::Command
+  {
+  public:
+    typedef  CommandIterationUpdate   Self;
+    typedef  itk::Command             Superclass;
+    typedef  itk::SmartPointer<CommandIterationUpdate>  Pointer;
+
+    double lPreviousValue;
+    double lCurrentValue ;
+    double lDiff;
+    double lDiff_Diff;
+    double lPrevDiff;
+    int     nContinueCount, nIncreased;
+    FILE *fp;
+
+
+    itkNewMacro( CommandIterationUpdate );
+  protected:
+    CommandIterationUpdate() {};
+
+    typedef itk::Image< float, Dimension > InternalImageType;
+    typedef itk::Vector< float, Dimension >    VectorPixelType;
+    typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+    typedef itk::jwsDemonsRegistrationFilter<
+                                  InternalImageType,
+                                  InternalImageType,
+                                  DeformationFieldType> RegistrationFilterType;
+	
+    typedef itk::ImageRegionIterator< DeformationFieldType > FieldIterator;
+    typedef itk::ImageRegionConstIterator< InternalImageType > DMapIterator;
+	
+    VectorPixelType displacement;
+    DeformationFieldType::IndexType index;
+
+  public:
+
+    void InitFile(void)
+    {
+         //fp = fopen("Diff_data.txt","w");
+         nIncreased = 0;
+    }
+
+    void CloseFile(void)
+    {
+        //fclose(fp);
+    } 
+        
+  
+    void Execute(itk::Object *caller, const itk::EventObject & event)
+      {
+       // Execute( (const itk::Object *)caller, event);
+#if 1
+           RegistrationFilterType * filter =
+            dynamic_cast< RegistrationFilterType * >( caller );
+
+            unsigned int unElapsedIter;  // by wook
+	   DeformationFieldType::Pointer Dfield;
+	   FixedImageType::ConstPointer fxImage;   // Ohhh  -> ConstPointer for const pointer
+	   
+          if( !(itk::IterationEvent().CheckEvent( &event )) )
+            {
+            return;
+            }
+            
+	//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#if 0                        // with my smoothing
+		  
+	 Dfield = filter->GetDeformationField();
+	 
+	 fxImage =filter->GetFixedImage();
+//	 fxImage =filter->GetMovingImage();
+	 
+	 int dx, dy, dz;
+	 dx = Dfield->GetRequestedRegion().GetSize()[0];
+	 dy = Dfield->GetRequestedRegion().GetSize()[1];
+	 dz = Dfield->GetRequestedRegion().GetSize()[2];
+	 cout << "DeformableRegistration.cxx dx =" <<dx<<" dy="<<dy<<" dz="<<dz<<endl;
+	 
+	 int orgSizeX = dx >> 1;
+	 
+         TNT::Array3D<float> fixedSkinDMap( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<float> fixedBoneDMap( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldSkin( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldBone( orgSizeX, dy, dz, (float)0);
+	 
+	 TNT::Array3D<VectorPixelType> vFieldCombined( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldAdjusted( dx, dy, dz, (float)0);
+	 
+         FieldIterator fi( Dfield,  Dfield->GetRequestedRegion().GetSize() );
+	 DMapIterator DMapIt( fxImage,   fxImage->GetRequestedRegion().GetSize());
+
+  	fi.GoToBegin();   //std::cout <<"test!!!"<<endl;
+	DMapIt.GoToBegin();
+
+	int i,j,k;
+
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < dx; i++){
+			
+		if(i<orgSizeX) {		
+			
+			fixedSkinDMap[i][j][k] =  DMapIt.Get();
+			vFieldSkin[i][j][k] =  fi.Get();
+		
+		}
+		else {
+			fixedBoneDMap[i - orgSizeX][j][k] =  DMapIt.Get();
+			vFieldBone[i - orgSizeX][j][k] =  fi.Get();
+		}
+	    
+             ++fi;  
+	     ++DMapIt;
+
+         }
+         }
+         }		
+
+	
+//	if(dx == 328) {
+//		testDMapImageToFile(fixedSkinDMap, orgSizeX, dy, dz, fxImage);
+//		testDfieldImageToFile(vFieldSkin, orgSizeX, dy, dz, Dfield);
+//        }
+	
+	float abs_skinDMap, abs_boneDMap, abs_sum;
+	abs_skinDMap = 0.0; 	abs_boneDMap = 0.0;	abs_sum = 0.0;
+	
+	float skin_ratio=0.0, bone_ratio=0.0;
+	float bone_no_change_value;
+	
+	bone_no_change_value = 0.0;
+	//bone_no_change_value = 1.0;
+	
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < orgSizeX; i++){
+			
+			if(fixedBoneDMap[i][j][k] <= bone_no_change_value) {  // bone	
+				
+				    vFieldCombined[i][j][k][0] = 0.0;
+                                    vFieldCombined[i][j][k][1] = 0.0;
+                                    vFieldCombined[i][j][k][2] = 0.0;
+				
+			}
+			else  {  // skin
+				
+				    vFieldCombined[i][j][k][0] = vFieldSkin[i][j][k][0];
+                                    vFieldCombined[i][j][k][1] = vFieldSkin[i][j][k][1];
+                                    vFieldCombined[i][j][k][2] = vFieldSkin[i][j][k][2];								
+			}
+	}
+	}
+        }
+	
+	// smoothing
+	float variance = 1.0;
+	gaussianFilteringForVectorImage( vFieldCombined, orgSizeX, dy, dz, variance);
+	
+	// make the vector of the bone(which was smoothed) zero vector
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < orgSizeX; i++){
+			
+			if(fixedBoneDMap[i][j][k] <= bone_no_change_value) {  // bone	
+				
+				    vFieldCombined[i][j][k][0] = 0.0;
+                                    vFieldCombined[i][j][k][1] = 0.0;
+                                    vFieldCombined[i][j][k][2] = 0.0;				
+			}
+	}
+	}
+        }	
+
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < orgSizeX; i++){
+	
+		vFieldAdjusted[i][j][k][0] = vFieldCombined[i][j][k][0];
+		vFieldAdjusted[i+orgSizeX][j][k][0] = vFieldCombined[i][j][k][0];
+			
+		vFieldAdjusted[i][j][k][1] = vFieldCombined[i][j][k][1];
+		vFieldAdjusted[i+orgSizeX][j][k][1] = vFieldCombined[i][j][k][1];
+		
+		vFieldAdjusted[i][j][k][2] = vFieldCombined[i][j][k][2];	
+		vFieldAdjusted[i+orgSizeX][j][k][2] = vFieldCombined[i][j][k][2];
+
+         }
+         }
+         }
+	
+
+	fi.GoToBegin(); 
+	
+  	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < dx; i++) {       
+//		displacement = fi.Get();
+//             	std::cout <<"("<<displacement[0]<<","<<displacement[1]<<","<<displacement[2]<<")   : ";
+    		
+		#if 1
+		displacement[0] = vFieldAdjusted[i][j][k][0];
+    		displacement[1] = vFieldAdjusted[i][j][k][1];
+		displacement[2] = vFieldAdjusted[i][j][k][2];
+		#endif
+//		std::cout <<"("<<displacement[0]<<","<<displacement[1]<<","<<displacement[2]<<")"<<std::endl;
+    		fi.Set( displacement );
+    		++fi;
+    	}
+	}
+	}
+	
+	 filter->setMyDField(Dfield);
+#endif
+	 
+#if 1          // without my smoothing  because there is another smoothing within the Demon
+	 Dfield = filter->GetDeformationField();
+	 
+	 fxImage =filter->GetFixedImage();
+//	 fxImage =filter->GetMovingImage();
+	 
+	 int dx, dy, dz;
+	 dx = Dfield->GetRequestedRegion().GetSize()[0];
+	 dy = Dfield->GetRequestedRegion().GetSize()[1];
+	 dz = Dfield->GetRequestedRegion().GetSize()[2];
+	 cout << "dx =" <<dx<<" dy="<<dy<<" dz="<<dz<<endl;
+	 
+	 int orgSizeX = dx >> 1;
+	 
+         TNT::Array3D<float> fixedSkinDMap( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<float> fixedBoneDMap( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldSkin( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldBone( orgSizeX, dy, dz, (float)0);
+	 
+	 TNT::Array3D<VectorPixelType> vFieldCombined( orgSizeX, dy, dz, (float)0);
+	 TNT::Array3D<VectorPixelType> vFieldAdjusted( dx, dy, dz, (float)0);
+	 
+         FieldIterator fi( Dfield,  Dfield->GetRequestedRegion().GetSize() );
+	 DMapIterator DMapIt( fxImage,   fxImage->GetRequestedRegion().GetSize());
+
+  	fi.GoToBegin();   //std::cout <<"test!!!"<<endl;
+	DMapIt.GoToBegin();
+
+	int i,j,k;
+
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < dx; i++){
+			
+		if(i<orgSizeX) {		
+			
+			fixedSkinDMap[i][j][k] =  DMapIt.Get();
+			vFieldSkin[i][j][k] =  fi.Get();
+		
+		}
+		else {
+			fixedBoneDMap[i - orgSizeX][j][k] =  DMapIt.Get();
+			vFieldBone[i - orgSizeX][j][k] =  fi.Get();
+		}
+	    
+             ++fi;  
+	     ++DMapIt;
+
+         }
+         }
+         }		
+
+	
+//	if(dx == 328) {
+//		testDMapImageToFile(fixedSkinDMap, orgSizeX, dy, dz, fxImage);
+//		testDfieldImageToFile(vFieldSkin, orgSizeX, dy, dz, Dfield);
+//        }
+	
+	float abs_skinDMap, abs_boneDMap, abs_sum;
+	abs_skinDMap = 0.0; 	abs_boneDMap = 0.0;	abs_sum = 0.0;
+	
+	float skin_ratio=0.0, bone_ratio=0.0;
+	
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < orgSizeX; i++){
+			
+			if((fixedSkinDMap[i][j][k]<0) && (fixedBoneDMap[i][j][k] <=0)) {  // bone	
+				
+				    vFieldCombined[i][j][k][0] = vFieldBone[i][j][k][0];
+                                    vFieldCombined[i][j][k][1] = vFieldBone[i][j][k][1];
+                                    vFieldCombined[i][j][k][2] = vFieldBone[i][j][k][2];
+				
+			}
+			else if((fixedSkinDMap[i][j][k]>=0) && (fixedBoneDMap[i][j][k] >0)) {  // skin
+				
+				    vFieldCombined[i][j][k][0] = vFieldSkin[i][j][k][0];
+                                    vFieldCombined[i][j][k][1] = vFieldSkin[i][j][k][1];
+                                    vFieldCombined[i][j][k][2] = vFieldSkin[i][j][k][2];				
+				
+			}
+			else if((fixedSkinDMap[i][j][k]<0) && (fixedBoneDMap[i][j][k] >0)){
+				
+				    abs_skinDMap 	= 	fabs(fixedSkinDMap[i][j][k]);
+				    abs_boneDMap 	=	fabs(fixedBoneDMap[i][j][k]);
+				    abs_sum = abs_skinDMap + abs_boneDMap;
+					
+				    skin_ratio = abs_boneDMap / abs_sum;
+				    bone_ratio = abs_skinDMap / abs_sum;
+					
+//cout<<"abs_skin="<<abs_skinDMap <<" abs_bone="<<abs_boneDMap<<" abs_sum="<<abs_sum<<endl;
+				    vFieldCombined[i][j][k][0] = (bone_ratio * vFieldBone[i][j][k][0]) + (skin_ratio * vFieldSkin[i][j][k][0]);
+                                    vFieldCombined[i][j][k][1] =  (bone_ratio * vFieldBone[i][j][k][1]) + (skin_ratio * vFieldSkin[i][j][k][1]);
+                                    vFieldCombined[i][j][k][2] =  (bone_ratio * vFieldBone[i][j][k][2]) + (skin_ratio * vFieldSkin[i][j][k][2]);			
+			}
+			else {  // exceptional cases
+				cout<<"exceptional case at ("<<i<<", "<<j<<", "<<k<<") fixedSkinDMap="<<fixedSkinDMap[i][j][k]<<" fixedBoneDMap="<< fixedBoneDMap[i][j][k]<<endl;
+				    vFieldCombined[i][j][k][0] = 0.0;
+                                    vFieldCombined[i][j][k][1] = 0.0;
+                                    vFieldCombined[i][j][k][2] = 0.0;				
+			}
+	}
+	}
+        }
+	
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < orgSizeX; i++){
+	
+		vFieldAdjusted[i][j][k][0] = vFieldCombined[i][j][k][0];
+		vFieldAdjusted[i+orgSizeX][j][k][0] = vFieldCombined[i][j][k][0];
+			
+		vFieldAdjusted[i][j][k][1] = vFieldCombined[i][j][k][1];
+		vFieldAdjusted[i+orgSizeX][j][k][1] = vFieldCombined[i][j][k][1];
+		
+		vFieldAdjusted[i][j][k][2] = vFieldCombined[i][j][k][2];	
+		vFieldAdjusted[i+orgSizeX][j][k][2] = vFieldCombined[i][j][k][2];
+
+         }
+         }
+         }
+	
+
+	fi.GoToBegin(); 
+	
+  	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < dx; i++) {       
+//		displacement = fi.Get();
+//             	std::cout <<"("<<displacement[0]<<","<<displacement[1]<<","<<displacement[2]<<")   : ";
+    		
+		#if 1
+		displacement[0] = vFieldAdjusted[i][j][k][0];
+    		displacement[1] = vFieldAdjusted[i][j][k][1];
+		displacement[2] = vFieldAdjusted[i][j][k][2];
+		#endif
+//		std::cout <<"("<<displacement[0]<<","<<displacement[1]<<","<<displacement[2]<<")"<<std::endl;
+    		fi.Set( displacement );
+    		++fi;
+    	}
+	}
+	}
+
+	 filter->setMyDField(Dfield);
+#endif
+	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+          unElapsedIter = filter->GetElapsedIterations();
+          lPreviousValue = lCurrentValue;
+          lCurrentValue = filter->GetMetric();
+
+          lPrevDiff = lDiff;
+          lDiff = fabs(lPreviousValue - lCurrentValue);
+          lDiff_Diff = fabs(lPrevDiff - lDiff) *100;
+                   
+          //fprintf(fp,"%d %f\n",unElapsedIter,lCurrentValue);
+          
+          
+          if(lDiff < 0.0001) nContinueCount++;    // when input data is signed float (minus value for inside)
+          //if(lDiff < 0.1) nContinueCount++;  // when input data is unsigned short
+          else  nContinueCount = 0;
+
+          #ifdef GET_INFORMATION_ON_ITERATION
+          if(lPreviousValue > lCurrentValue){
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= -"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<<std::endl;
+            nIncreased = 0;                                                                                                              
+          } 
+          else{
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= +"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<< std::endl;
+            nIncreased++;                                                                                                                         
+          } 
+                                                                                                                                                                                                                                
+          if(nContinueCount > 10){
+                nContinueCount = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continuous negligible variations     "<<std::endl;                                
+          }
+
+          if(nIncreased > 20){
+                nIncreased = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continumes metric increasement      "<<std::endl;                              
+          }
+          
+                        
+          #endif
+                                                        
+          #if 0  
+          
+          std::cout << unElapsedIter << " " << filter->GetMetric() << std::endl;
+
+          if(unElapsedIter ==20){ std::cout << "********************************  count!!"<<std::endl;
+              filter->StopRegistration();
+          }
+          #endif
+#endif
+      }
+
+    void Execute(const itk::Object * object, const itk::EventObject & event)
+      {
+	}
+  };
+
+
+#if  1
+void ExtendedDemonRegistrationMain(FixedImageType::Pointer fixedImage, MovingImageType::Pointer movingImage, DeformationFieldType::Pointer resultingHalfDField, string registeredImageName)
+{
+  std::cout <<" start second registration!! " <<std::endl;   
+  std::cout <<"1: accept parameter  " <<std::endl;
+		
+#if 0
+  typedef itk::HistogramMatchingImageFilter<                      
+                                    InternalImageType,
+                                    InternalImageType >   MatchingFilterType;
+  MatchingFilterType::Pointer matcher = MatchingFilterType::New();
+
+  std::cout <<"2: set HistogramMatchingImageFilter  " <<std::endl;
+  matcher->SetInput( movingImage );       
+  matcher->SetReferenceImage( fixedImage );
+  matcher->SetNumberOfHistogramLevels( 1024 );
+  matcher->SetNumberOfMatchPoints( 7 );
+  matcher->ThresholdAtMeanIntensityOn();
+
+   #ifdef SET_SMALL_NUMBER_THREADS
+     matcher->SetNumberOfThreads(1);
+   #endif
+
+   #ifdef FORCED_UPDATE
+     matcher->Update();
+   #endif
+
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for HistogramMatchingImageFilter: "<<matcher->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+#endif
+  std::cout <<"6: generate DeformationFieldType format  " <<std::endl;
+
+  typedef itk::jwsDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+
+  std::cout <<"7: set  DemonsRegistrationFilter " <<std::endl;
+  RegistrationFilterType::Pointer filter = RegistrationFilterType::New();
+
+  filter->SetNumberOfIterations( 50 );
+  //filter->SetStandardDeviations( 1.0 );   // good
+  filter->SetStandardDeviations( 2.0 );    // for test
+
+
+     #ifdef SET_SMALL_NUMBER_THREADS
+       filter->SetNumberOfThreads(1);
+     #endif
+
+  
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for DemonsRegistrationFilter: "<<filter->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+  /////////////////////////////////////////////////////////////////////////////
+  std::cout <<"8: set  CommandIterationUpdate " <<std::endl;
+  CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
+  observer->InitFile();
+
+  std::cout <<"9: filter->AddObserver " <<std::endl;
+  filter->AddObserver( itk::IterationEvent(), observer );
+
+     
+  /////////////////////////////////////////////////////////////////////////////
+
+  typedef itk::jwsMultiResolutionPDEDeformableRegistration<
+                                InternalImageType,
+                                InternalImageType,
+                                DeformationFieldType >   MultiResRegistrationFilterType;
+
+  std::cout <<"10: set MultiResolutionPDEDeformableRegistration " <<std::endl;
+  MultiResRegistrationFilterType::Pointer multires = MultiResRegistrationFilterType::New();
+  multires->SetRegistrationFilter( filter );
+  
+  int numberOfLevels = 3;
+  //unsigned int nIterations[3] = { 2,2,1 };     // for test
+//  unsigned int nIterations[3] = { 10,10, 4 };     // for test
+//unsigned int nIterations[3] = { 400,400, 300 };     // for test
+unsigned int nIterations[3] = { 300,300, 100 };     // good
+ 
+  multires->SetNumberOfLevels( numberOfLevels ); 
+  multires->SetFixedImage( fixedImage );
+  //multires->SetMovingImage( matcher->GetOutput() );   // turn off the histogram matching for distance mapping demon
+                                                                               // by wook 02/28/08
+  multires->SetMovingImage( movingImage );
+
+  #ifdef SET_SMALL_NUMBER_THREADS
+    multires->SetNumberOfThreads(1);
+  #endif
+ 
+  multires->SetNumberOfIterations( nIterations );  
+
+
+   /******************  by wook    ***************************/
+   std::cout <<"11: set multires->AddObserver " <<std::endl;
+   typedef RegistrationInterfaceCommand<MultiResRegistrationFilterType> CommandType;
+   CommandType::Pointer command = CommandType::New();
+   multires->AddObserver( itk::IterationEvent(), command );
+//   multires->Update();
+   /*****************************************************************/
+
+
+ #ifdef FORCED_UPDATE
+   multires->Update();
+ #endif
+
+
+#ifdef GET_NUMBER_OF_THREADS
+
+  std::cout <<" Number of Threads for MultiResolutionPDEDeformableRegistration: "<<multires->GetNumberOfThreads() << std::endl;
+
+#endif
+                
+
+  std::cout <<"12: WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  typedef itk::LinearInterpolateImageFunction<
+                                   MovingImageType,
+                                   double          >  InterpolatorType;
+  WarperType::Pointer warper = WarperType::New();
+  InterpolatorType::Pointer interpolator = InterpolatorType::New();
+//  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
+
+  std::cout <<"13: initialize WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  warper->SetInput( movingImage );
+  warper->SetInterpolator( interpolator );
+
+
+  warper->SetOutputSpacing( fixedImage->GetSpacing() );
+  warper->SetOutputOrigin( fixedImage->GetOrigin() );
+  warper->SetDeformationField( multires->GetOutput() );
+
+  // by wook to set the large value as outside pixel value
+  warper->SetEdgePaddingValue(65535L);
+     warper->Update();
+
+ if(registeredImageName.length()>0){
+	 typedef float  OutputPixelType;
+	 typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
+	 typedef itk::CastImageFilter< 
+			 MovingImageType,
+			 OutputImageType > CastFilterType;
+  
+	  typedef itk::ImageFileWriter< OutputImageType >  WriterType;
+
+  
+	  WriterType::Pointer      writer =  WriterType::New();
+	  CastFilterType::Pointer  caster =  CastFilterType::New();
+
+	  string boneRegisteredImageFileName = registeredImageName + "Both";
+	  string skinRegisteredImageFileName = registeredImageName + "Skin";
+		
+	  string boneRegisteredFileNamewithExtension =boneRegisteredImageFileName + ".vtk";
+	  writer->SetFileName( boneRegisteredFileNamewithExtension );
+  
+	  caster->SetInput( warper->GetOutput() );
+	  writer->SetInput( caster->GetOutput() );
+	  writer->Update();
+  
+
+	  FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
+
+	  string deformationFieldFileNamewithExtension = registeredImageName + "_DField.vtk";
+	  fieldWriter->SetFileName( deformationFieldFileNamewithExtension );
+	  fieldWriter->SetInput( multires->GetOutput() );
+	  fieldWriter->Update();
+
+   }
+  std::cout <<"16: observer->CloseFile()" <<std::endl;
+  observer->CloseFile();  // by wook
+
+
+
+	////////////////////// store half DField  /////////////////////////////////////////
+  	 int dx, dy, dz;
+	 dx = multires->GetOutput()->GetRequestedRegion().GetSize()[0];
+	 dy = multires->GetOutput()->GetRequestedRegion().GetSize()[1];
+	 dz = multires->GetOutput()->GetRequestedRegion().GetSize()[2];
+	 
+	 int halfSizeX = dx >>1; cout<<" halfSizeX= "<<halfSizeX<<endl;
+	//TNT::Array3D<VectorPixelType> vField( dx, dy, dz, (float)0);
+	DfieldIteratorType fieldIt( multires->GetOutput(), multires->GetOutput()->GetRequestedRegion().GetSize() );
+	DfieldIteratorType fieldOut( resultingHalfDField, resultingHalfDField->GetRequestedRegion().GetSize() );
+	
+	cout<< "size of From SecondDField = "<<multires->GetOutput()->GetRequestedRegion().GetSize()<<endl;
+	cout<<"size of To SecondDField=" <<resultingHalfDField->GetRequestedRegion().GetSize()<<endl;
+	
+	fieldIt.GoToBegin();
+	fieldOut.GoToBegin();
+	
+	int i,j,k;
+
+	for(k=0; k < dz; k++){
+	for(j=0; j < dy; j++){
+        for(i=0; i < dx; i++){
+			
+		if(i<halfSizeX) {		
+	
+			fieldOut.Set(  fieldIt.Get() );
+			++fieldOut;
+		}
+	        ++fieldIt;
+
+         }
+         }
+         }
+	
+//  return 0;
+}
+}   //   namespace SECOND_EDEMON
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/thirdDemon.h b/bioimagesuite30_src/DemonsRegistration/thirdDemon.h
new file mode 100644
index 0000000..7d24fda
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/thirdDemon.h
@@ -0,0 +1,437 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//#include "wook.h"
+#include "tnt/tnt_array3d.h"
+#include <math.h>
+
+//#define GET_NUMBER_OF_THREADS
+#define GET_INFORMATION_ON_ITERATION
+
+//#define SET_SMALL_NUMBER_THREADS
+//#define FORCED_UPDATE
+extern void testDMapImageToFile(TNT::Array3D<float> &DMap, int sizeX, int sizeY, int sizeZ,  FixedImageType::ConstPointer fxImage);
+extern void testDfieldImageToFile(TNT::Array3D<VectorPixelType> &DField, int sizeX, int sizeY, int sizeZ,  DeformationFieldType::Pointer DImage);
+
+extern void gaussianFilteringForVectorImage(TNT::Array3D<VectorPixelType>& vFieldCombined, int sizeX, int sizeY, int sizeZ, float variance);
+
+namespace THIRD_EDEMON{
+template <typename TRegistration>
+class RegistrationInterfaceCommand : public itk::Command
+{
+
+public:
+  typedef  RegistrationInterfaceCommand   Self;
+  typedef  itk::Command                   Superclass;
+  typedef  itk::SmartPointer<Self>        Pointer;
+  itkNewMacro( Self );
+protected:
+  RegistrationInterfaceCommand() {};
+
+public:
+  typedef   TRegistration                              RegistrationType;
+  typedef   RegistrationType *                         RegistrationPointer;
+
+  typedef itk::Vector< float, Dimension >    VectorPixelType;
+  typedef itk::Image< GrayPixelType, Dimension > GrayImageType;
+  typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+  typedef itk::jwsDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+  
+  void Execute(itk::Object * object, const itk::EventObject & event)
+  {
+
+    if( !(itk::IterationEvent().CheckEvent( &event )) )
+      {
+      return;
+      }
+     
+
+    RegistrationPointer registration =
+                            dynamic_cast<RegistrationPointer>( object );
+    // for MultiResolutionPDEDeformableRegistration
+
+
+    RegistrationFilterType * filter = dynamic_cast< RegistrationFilterType * >(
+                       registration->GetRegistrationFilter() );
+       // for Demon Registration algorithm
+    
+
+    std::cout << "level:"<<registration->GetCurrentLevel() <<std::endl;
+                 
+    if ( registration->GetCurrentLevel() == 1 )
+      {
+        std::cout << "*****   level 111111" <<std::endl;
+        std::cout<<"In Multilevel : "  <<  filter->GetElapsedIterations()<< std::endl;
+      }
+     
+  }
+
+
+  void Execute(const itk::Object * , const itk::EventObject & )
+    { return; }
+};
+
+
+
+
+//  The following section of code implements a Command observer
+//  that will monitor the evolution of the registration process.
+//
+  class CommandIterationUpdate : public itk::Command
+  {
+  public:
+    typedef  CommandIterationUpdate   Self;
+    typedef  itk::Command             Superclass;
+    typedef  itk::SmartPointer<CommandIterationUpdate>  Pointer;
+
+    double lPreviousValue;
+    double lCurrentValue ;
+    double lDiff;
+    double lDiff_Diff;
+    double lPrevDiff;
+    int     nContinueCount, nIncreased;
+    FILE *fp;
+
+
+    itkNewMacro( CommandIterationUpdate );
+  protected:
+    CommandIterationUpdate() {};
+
+    typedef itk::Image< GrayPixelType, Dimension > GrayImageType;
+    typedef itk::Vector< float, Dimension >    VectorPixelType;
+    typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+    typedef itk::jwsDemonsRegistrationFilter<
+                                  InternalImageType,
+                                  InternalImageType,
+                                  DeformationFieldType> RegistrationFilterType;
+	
+    typedef itk::ImageRegionIterator< DeformationFieldType > FieldIterator;
+    //typedef itk::ImageRegionConstIterator< GrayImageType > DMapIterator;
+	
+    VectorPixelType displacement;
+    DeformationFieldType::IndexType index;
+
+  public:
+
+    void InitFile(void)
+    {
+         //fp = fopen("Diff_data.txt","w");
+         nIncreased = 0;
+    }
+
+    void CloseFile(void)
+    {
+        //fclose(fp);
+    } 
+        
+  
+    void Execute(itk::Object *caller, const itk::EventObject & event)
+      {
+       // Execute( (const itk::Object *)caller, event);
+#if 1
+           RegistrationFilterType * filter =
+            dynamic_cast< RegistrationFilterType * >( caller );
+
+            unsigned int unElapsedIter;  // by wook
+	   DeformationFieldType::Pointer Dfield;
+	   FixedImageType::ConstPointer fxImage;   // Ohhh  -> ConstPointer for const pointer
+	   
+          if( !(itk::IterationEvent().CheckEvent( &event )) )
+            {
+            return;
+            }
+            
+
+          unElapsedIter = filter->GetElapsedIterations();
+          lPreviousValue = lCurrentValue;
+          lCurrentValue = filter->GetMetric();
+
+          lPrevDiff = lDiff;
+          lDiff = fabs(lPreviousValue - lCurrentValue);
+          lDiff_Diff = fabs(lPrevDiff - lDiff) *100;
+                   
+          //fprintf(fp,"%d %f\n",unElapsedIter,lCurrentValue);
+          
+          
+          if(lDiff < 0.0001) nContinueCount++;    // when input data is signed float (minus value for inside)
+          //if(lDiff < 0.1) nContinueCount++;  // when input data is unsigned short
+          else  nContinueCount = 0;
+
+          #ifdef GET_INFORMATION_ON_ITERATION
+          if(lPreviousValue > lCurrentValue){
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= -"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<<std::endl;
+            nIncreased = 0;                                                                                                              
+          } 
+          else{
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= +"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<< std::endl;
+            nIncreased++;                                                                                                                         
+          } 
+                                                                                                                                                                                                                                
+          if(nContinueCount > 10){
+                nContinueCount = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continuous negligible variations     "<<std::endl;                                
+          }
+
+          if(nIncreased > 20){
+                nIncreased = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continumes metric increasement      "<<std::endl;                              
+          }
+          
+                        
+          #endif
+                                                        
+
+#endif
+      }
+
+    void Execute(const itk::Object * object, const itk::EventObject & event)
+      {
+	}
+  };
+
+
+#if  1
+void DemonRegistrationMain(GrayImageType::Pointer fixedImage, GrayImageType::Pointer movingImage, DeformationFieldType::Pointer resultingDField, string registeredImageName)
+{
+  std::cout <<" start Third registration!! " <<std::endl;   
+  std::cout <<"1: accept parameter  " <<std::endl;
+  
+  typedef itk::CastImageFilter<GrayImageType,  
+                                InternalImageType > FixedImageCasterType; 
+  typedef itk::CastImageFilter< GrayImageType,  
+                                InternalImageType > MovingImageCasterType;
+  
+  FixedImageCasterType::Pointer fixedImageCaster   = FixedImageCasterType::New(); 
+  MovingImageCasterType::Pointer movingImageCaster = MovingImageCasterType::New();
+   
+  fixedImageCaster->SetInput( fixedImage ); 
+  movingImageCaster->SetInput( movingImage ); 
+  
+#if 1
+  typedef itk::HistogramMatchingImageFilter<                      
+                                    InternalImageType,
+                                    InternalImageType >   MatchingFilterType;
+  MatchingFilterType::Pointer matcher = MatchingFilterType::New();
+
+  std::cout <<"2: set HistogramMatchingImageFilter  " <<std::endl;
+  matcher->SetInput( movingImageCaster->GetOutput()  );       
+  matcher->SetReferenceImage( fixedImageCaster->GetOutput() );
+  matcher->SetNumberOfHistogramLevels( 1024 );
+  matcher->SetNumberOfMatchPoints( 7 );
+  matcher->ThresholdAtMeanIntensityOn();
+
+   #ifdef SET_SMALL_NUMBER_THREADS
+     matcher->SetNumberOfThreads(1);
+   #endif
+
+   #ifdef FORCED_UPDATE
+     matcher->Update();
+   #endif
+
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for HistogramMatchingImageFilter: "<<matcher->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+#endif
+  std::cout <<"6: generate DeformationFieldType format  " <<std::endl;
+
+  typedef itk::jwsDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+
+  std::cout <<"7: set  DemonsRegistrationFilter " <<std::endl;
+  RegistrationFilterType::Pointer filter = RegistrationFilterType::New();
+
+  filter->SetNumberOfIterations( 50 );
+  filter->SetStandardDeviations( 1.0 );
+  //filter->SetStandardDeviations( 0.0 );
+
+
+     #ifdef SET_SMALL_NUMBER_THREADS
+       filter->SetNumberOfThreads(1);
+     #endif
+
+  
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for DemonsRegistrationFilter: "<<filter->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+  /////////////////////////////////////////////////////////////////////////////
+  std::cout <<"8: set  CommandIterationUpdate " <<std::endl;
+  CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
+  observer->InitFile();
+
+  std::cout <<"9: filter->AddObserver " <<std::endl;
+  filter->AddObserver( itk::IterationEvent(), observer );
+
+     
+  /////////////////////////////////////////////////////////////////////////////
+
+  typedef itk::jwsMultiResolutionPDEDeformableRegistration<
+                                InternalImageType,
+                                InternalImageType,
+                                DeformationFieldType >   GrayMultiResRegistrationFilterType;
+
+  std::cout <<"10: set MultiResolutionPDEDeformableRegistration " <<std::endl;
+  GrayMultiResRegistrationFilterType::Pointer Gmultires = GrayMultiResRegistrationFilterType::New();
+  Gmultires->SetRegistrationFilter( filter );
+  
+  int numberOfLevels = 3;
+//  unsigned int nIterations[3] = { 10,10,3 };     // for test
+unsigned int nIterations[3] = { 200,200, 30 };     // for test
+ 
+  Gmultires->SetNumberOfLevels( numberOfLevels ); 
+  Gmultires->SetFixedImage( fixedImageCaster->GetOutput() );
+  Gmultires->SetMovingImage( matcher->GetOutput() );   // turn off the histogram matching for distance mapping demon
+                                                                               // by wook 02/28/08
+  //Gmultires->SetMovingImage( movingImage );
+
+  #ifdef SET_SMALL_NUMBER_THREADS
+    Gmultires->SetNumberOfThreads(1);
+  #endif
+ 
+  Gmultires->SetNumberOfIterations( nIterations );  
+
+
+   /******************  by wook    ***************************/
+   std::cout <<"11: set multires->AddObserver " <<std::endl;
+   typedef RegistrationInterfaceCommand<GrayMultiResRegistrationFilterType> CommandType;
+   CommandType::Pointer command = CommandType::New();
+   Gmultires->AddObserver( itk::IterationEvent(), command );
+//   multires->Update();
+   /*****************************************************************/
+
+
+ #ifdef FORCED_UPDATE
+   Gmultires->Update();
+ #endif
+
+
+#ifdef GET_NUMBER_OF_THREADS
+
+  std::cout <<" Number of Threads for MultiResolutionPDEDeformableRegistration: "<<multires->GetNumberOfThreads() << std::endl;
+
+#endif
+                
+
+  std::cout <<"12: WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  typedef itk::LinearInterpolateImageFunction<
+                                   GrayImageType,
+                                   double          >  InterpolatorType;
+  GrayWarperType::Pointer warper = GrayWarperType::New();
+  InterpolatorType::Pointer interpolator = InterpolatorType::New();
+//  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
+
+  std::cout <<"13: initialize WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  warper->SetInput( movingImage );
+  warper->SetInterpolator( interpolator );
+
+
+  warper->SetOutputSpacing( fixedImage->GetSpacing() );
+  warper->SetOutputOrigin( fixedImage->GetOrigin() );
+  warper->SetDeformationField( Gmultires->GetOutput() );
+
+  // by wook to set the large value as outside pixel value
+  warper->SetEdgePaddingValue(65535L);
+
+ #ifdef SET_SMALL_NUMBER_THREADS
+   warper->SetNumberOfThreads(1);
+ #endif
+
+   //#ifdef FORCED_UPDATE
+     warper->Update();
+     std::cout<< "warper spacing:" <<warper->GetOutput()->GetSpacing()    <<"warper origin:"<<warper->GetOutput()->GetOrigin() <<std::endl;
+     std::cout<< "warper size:" <<warper->GetOutput()->GetRequestedRegion().GetSize()    <<std::endl; 
+   //#endif
+
+
+               
+   if(registeredImageName.length()>0){
+	   typedef itk::ImageFileWriter< GrayImageType >  WriterType;
+	   WriterType::Pointer      writer =  WriterType::New();
+  		
+	   string registeredFileNamewithExtension =registeredImageName + ".vtk";
+	   writer->SetFileName( registeredFileNamewithExtension );
+	   writer->SetInput( warper->GetOutput()  );
+
+           #ifdef SET_SMALL_NUMBER_THREADS
+	   writer->SetNumberOfThreads(1);
+           #endif
+ 	  
+	   writer->Update();
+	   
+	   FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
+
+	   string deformationFieldFileNamewithExtension = registeredImageName + "_DField.vtk";
+	   fieldWriter->SetFileName( deformationFieldFileNamewithExtension );
+	   fieldWriter->SetInput( Gmultires->GetOutput() );
+	   fieldWriter->Update();
+        }
+   
+   observer->CloseFile();  // by wook
+
+	////////////////////// store half DField  /////////////////////////////////////////
+  	 int ddx, ddy, ddz;
+	 ddx = Gmultires->GetOutput()->GetRequestedRegion().GetSize()[0];
+	 ddy = Gmultires->GetOutput()->GetRequestedRegion().GetSize()[1];
+	 ddz = Gmultires->GetOutput()->GetRequestedRegion().GetSize()[2];
+	 
+
+	//TNT::Array3D<VectorPixelType> vField( dx, dy, dz, (float)0);
+	DfieldIteratorType fieldIt( Gmultires->GetOutput(), Gmultires->GetOutput()->GetRequestedRegion().GetSize() );
+	DfieldIteratorType fieldOut( resultingDField, resultingDField->GetRequestedRegion().GetSize() );
+	
+	fieldIt.GoToBegin();
+	fieldOut.GoToBegin();
+	
+	int i,j,k;
+
+	for(k=0; k < ddz; k++){
+	  for(j=0; j < ddy; j++){
+	    for(i=0; i < ddx; i++){
+	      fieldOut.Set(  fieldIt.Get() );
+	      ++fieldOut;	
+	      ++fieldIt;
+	      
+	    }
+	  }
+         }
+}
+}   //   namespace THIRD_EDEMON
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/thirdSymmetricDemon.h b/bioimagesuite30_src/DemonsRegistration/thirdSymmetricDemon.h
new file mode 100644
index 0000000..3ee3e55
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/thirdSymmetricDemon.h
@@ -0,0 +1,438 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//#include "wook.h"
+#include "tnt/tnt_array3d.h"
+#include <math.h>
+
+//#define GET_NUMBER_OF_THREADS
+#define GET_INFORMATION_ON_ITERATION
+
+//#define SET_SMALL_NUMBER_THREADS
+//#define FORCED_UPDATE
+extern void testDMapImageToFile(TNT::Array3D<float> &DMap, int sizeX, int sizeY, int sizeZ,  FixedImageType::ConstPointer fxImage);
+extern void testDfieldImageToFile(TNT::Array3D<VectorPixelType> &DField, int sizeX, int sizeY, int sizeZ,  DeformationFieldType::Pointer DImage);
+
+extern void gaussianFilteringForVectorImage(TNT::Array3D<VectorPixelType>& vFieldCombined, int sizeX, int sizeY, int sizeZ, float variance);
+
+namespace THIRD_SEDEMON{
+template <typename TRegistration>
+class RegistrationInterfaceCommand : public itk::Command
+{
+
+public:
+  typedef  RegistrationInterfaceCommand   Self;
+  typedef  itk::Command                   Superclass;
+  typedef  itk::SmartPointer<Self>        Pointer;
+  itkNewMacro( Self );
+protected:
+  RegistrationInterfaceCommand() {};
+
+public:
+  typedef   TRegistration                              RegistrationType;
+  typedef   RegistrationType *                         RegistrationPointer;
+
+  typedef itk::Vector< float, Dimension >    VectorPixelType;
+  typedef itk::Image< GrayPixelType, Dimension > GrayImageType;
+  typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+  typedef itk::jwsDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+  
+  void Execute(itk::Object * object, const itk::EventObject & event)
+  {
+
+    if( !(itk::IterationEvent().CheckEvent( &event )) )
+      {
+      return;
+      }
+     
+
+    RegistrationPointer registration =
+                            dynamic_cast<RegistrationPointer>( object );
+    // for MultiResolutionPDEDeformableRegistration
+
+
+    RegistrationFilterType * filter = dynamic_cast< RegistrationFilterType * >(
+                       registration->GetRegistrationFilter() );
+       // for Demon Registration algorithm
+    
+
+    std::cout << "level:"<<registration->GetCurrentLevel() <<std::endl;
+                 
+    if ( registration->GetCurrentLevel() == 1 )
+      {
+        std::cout << "*****   level 111111" <<std::endl;
+        std::cout<<"In Multilevel : "  <<  filter->GetElapsedIterations()<< std::endl;
+      }
+     
+  }
+
+
+  void Execute(const itk::Object * , const itk::EventObject & )
+    { return; }
+};
+
+
+
+
+//  The following section of code implements a Command observer
+//  that will monitor the evolution of the registration process.
+//
+  class CommandIterationUpdate : public itk::Command
+  {
+  public:
+    typedef  CommandIterationUpdate   Self;
+    typedef  itk::Command             Superclass;
+    typedef  itk::SmartPointer<CommandIterationUpdate>  Pointer;
+
+    double lPreviousValue;
+    double lCurrentValue ;
+    double lDiff;
+    double lDiff_Diff;
+    double lPrevDiff;
+    int     nContinueCount, nIncreased;
+    FILE *fp;
+
+
+    itkNewMacro( CommandIterationUpdate );
+  protected:
+    CommandIterationUpdate() {};
+
+    typedef itk::Image< GrayPixelType, Dimension > GrayImageType;
+    typedef itk::Vector< float, Dimension >    VectorPixelType;
+    typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+    typedef itk::jwsDemonsRegistrationFilter<
+                                  InternalImageType,
+                                  InternalImageType,
+                                  DeformationFieldType> RegistrationFilterType;
+	
+    typedef itk::ImageRegionIterator< DeformationFieldType > FieldIterator;
+    //typedef itk::ImageRegionConstIterator< GrayImageType > DMapIterator;
+	
+    VectorPixelType displacement;
+    DeformationFieldType::IndexType index;
+
+  public:
+
+    void InitFile(void)
+    {
+         //fp = fopen("Diff_data.txt","w");
+         nIncreased = 0;
+    }
+
+    void CloseFile(void)
+    {
+        //fclose(fp);
+    } 
+        
+  
+    void Execute(itk::Object *caller, const itk::EventObject & event)
+      {
+       // Execute( (const itk::Object *)caller, event);
+#if 1
+           RegistrationFilterType * filter =
+            dynamic_cast< RegistrationFilterType * >( caller );
+
+            unsigned int unElapsedIter;  // by wook
+	   DeformationFieldType::Pointer Dfield;
+	   FixedImageType::ConstPointer fxImage;   // Ohhh  -> ConstPointer for const pointer
+	   
+          if( !(itk::IterationEvent().CheckEvent( &event )) )
+            {
+            return;
+            }
+            
+
+          unElapsedIter = filter->GetElapsedIterations();
+          lPreviousValue = lCurrentValue;
+          lCurrentValue = filter->GetMetric();
+
+          lPrevDiff = lDiff;
+          lDiff = fabs(lPreviousValue - lCurrentValue);
+          lDiff_Diff = fabs(lPrevDiff - lDiff) *100;
+                   
+          //fprintf(fp,"%d %f\n",unElapsedIter,lCurrentValue);
+          
+          
+          if(lDiff < 0.0001) nContinueCount++;    // when input data is signed float (minus value for inside)
+          //if(lDiff < 0.1) nContinueCount++;  // when input data is unsigned short
+          else  nContinueCount = 0;
+
+          #ifdef GET_INFORMATION_ON_ITERATION
+          if(lPreviousValue > lCurrentValue){
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= -"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<<std::endl;
+            nIncreased = 0;                                                                                                              
+          } 
+          else{
+            std::cout <<unElapsedIter<<" : prv="<<lPreviousValue<<" curr="<<lCurrentValue<< " diff= +"<<lDiff<<" nCnt="<<nContinueCount<<" nIn="<<nIncreased<< std::endl;
+            nIncreased++;                                                                                                                         
+          } 
+                                                                                                                                                                                                                                
+          if(nContinueCount > 10){
+                nContinueCount = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continuous negligible variations     "<<std::endl;                                
+          }
+
+          if(nIncreased > 20){
+                nIncreased = 0;
+                filter->StopRegistration();
+                std::cout << "**************** registration Stop by continumes metric increasement      "<<std::endl;                              
+          }
+          
+                        
+          #endif
+                                                        
+
+#endif
+      }
+
+    void Execute(const itk::Object * object, const itk::EventObject & event)
+      {
+	}
+  };
+
+
+#if  1
+void DemonRegistrationMain(GrayImageType::Pointer fixedImage, GrayImageType::Pointer movingImage, DeformationFieldType::Pointer resultingDField, string registeredImageName)
+{
+  std::cout <<" start Third registration!! " <<std::endl;   
+  std::cout <<"1: accept parameter  " <<std::endl;
+  
+  typedef itk::CastImageFilter<GrayImageType,  
+                                InternalImageType > FixedImageCasterType; 
+  typedef itk::CastImageFilter< GrayImageType,  
+                                InternalImageType > MovingImageCasterType;
+  
+  FixedImageCasterType::Pointer fixedImageCaster   = FixedImageCasterType::New(); 
+  MovingImageCasterType::Pointer movingImageCaster = MovingImageCasterType::New();
+   
+  fixedImageCaster->SetInput( fixedImage ); 
+  movingImageCaster->SetInput( movingImage ); 
+  
+#if 1
+  typedef itk::HistogramMatchingImageFilter<                      
+                                    InternalImageType,
+                                    InternalImageType >   MatchingFilterType;
+  MatchingFilterType::Pointer matcher = MatchingFilterType::New();
+
+  std::cout <<"2: set HistogramMatchingImageFilter  " <<std::endl;
+  matcher->SetInput( movingImageCaster->GetOutput()  );       
+  matcher->SetReferenceImage( fixedImageCaster->GetOutput() );
+  matcher->SetNumberOfHistogramLevels( 1024 );
+  matcher->SetNumberOfMatchPoints( 7 );
+  matcher->ThresholdAtMeanIntensityOn();
+
+   #ifdef SET_SMALL_NUMBER_THREADS
+     matcher->SetNumberOfThreads(1);
+   #endif
+
+   #ifdef FORCED_UPDATE
+     matcher->Update();
+   #endif
+
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for HistogramMatchingImageFilter: "<<matcher->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+#endif
+  std::cout <<"6: generate DeformationFieldType format  " <<std::endl;
+
+  typedef itk::jwsDemonsRegistrationFilter<
+                            InternalImageType,
+                            InternalImageType,
+                            DeformationFieldType> RegistrationFilterType;
+
+  std::cout <<"7: set  DemonsRegistrationFilter " <<std::endl;
+  RegistrationFilterType::Pointer filter = RegistrationFilterType::New();
+
+  filter->SetNumberOfIterations( 50 );
+  filter->SetStandardDeviations( 1.0 );   // good
+  //filter->SetStandardDeviations( 0.0 );
+
+
+     #ifdef SET_SMALL_NUMBER_THREADS
+       filter->SetNumberOfThreads(1);
+     #endif
+
+  
+  #ifdef GET_NUMBER_OF_THREADS
+
+    std::cout <<" Number of Threads for DemonsRegistrationFilter: "<<filter->GetNumberOfThreads() << std::endl;
+                                  
+  #endif
+  /////////////////////////////////////////////////////////////////////////////
+  std::cout <<"8: set  CommandIterationUpdate " <<std::endl;
+  CommandIterationUpdate::Pointer observer = CommandIterationUpdate::New();
+  observer->InitFile();
+
+  std::cout <<"9: filter->AddObserver " <<std::endl;
+  filter->AddObserver( itk::IterationEvent(), observer );
+
+     
+  /////////////////////////////////////////////////////////////////////////////
+
+  typedef itk::jwsMultiResolutionPDEDeformableRegistration<
+                                InternalImageType,
+                                InternalImageType,
+                                DeformationFieldType >   GrayMultiResRegistrationFilterType;
+
+  std::cout <<"10: set MultiResolutionPDEDeformableRegistration " <<std::endl;
+  GrayMultiResRegistrationFilterType::Pointer Gmultires = GrayMultiResRegistrationFilterType::New();
+  Gmultires->SetRegistrationFilter( filter );
+  
+  int numberOfLevels = 3;
+//  unsigned int nIterations[3] = { 10,10,3 };     // for test
+//unsigned int nIterations[3] = { 400,400, 400 };     // for test
+unsigned int nIterations[3] = { 400,400, 200 };     // good
+ 
+  Gmultires->SetNumberOfLevels( numberOfLevels ); 
+  Gmultires->SetFixedImage( fixedImageCaster->GetOutput() );
+  Gmultires->SetMovingImage( matcher->GetOutput() );   // turn off the histogram matching for distance mapping demon
+                                                                               // by wook 02/28/08
+  //Gmultires->SetMovingImage( movingImage );
+
+  #ifdef SET_SMALL_NUMBER_THREADS
+    Gmultires->SetNumberOfThreads(1);
+  #endif
+ 
+  Gmultires->SetNumberOfIterations( nIterations );  
+
+
+   /******************  by wook    ***************************/
+   std::cout <<"11: set multires->AddObserver " <<std::endl;
+   typedef RegistrationInterfaceCommand<GrayMultiResRegistrationFilterType> CommandType;
+   CommandType::Pointer command = CommandType::New();
+   Gmultires->AddObserver( itk::IterationEvent(), command );
+//   multires->Update();
+   /*****************************************************************/
+
+
+ #ifdef FORCED_UPDATE
+   Gmultires->Update();
+ #endif
+
+
+#ifdef GET_NUMBER_OF_THREADS
+
+  std::cout <<" Number of Threads for MultiResolutionPDEDeformableRegistration: "<<multires->GetNumberOfThreads() << std::endl;
+
+#endif
+                
+
+  std::cout <<"12: WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  typedef itk::LinearInterpolateImageFunction<
+                                   GrayImageType,
+                                   double          >  InterpolatorType;
+  GrayWarperType::Pointer warper = GrayWarperType::New();
+  InterpolatorType::Pointer interpolator = InterpolatorType::New();
+//  FixedImageType::Pointer fixedImage = fixedImageReader->GetOutput();
+
+  std::cout <<"13: initialize WarpImageFilter  &  LinearInterpolateImageFunction" <<std::endl;
+
+  warper->SetInput( movingImage );
+  warper->SetInterpolator( interpolator );
+
+
+  warper->SetOutputSpacing( fixedImage->GetSpacing() );
+  warper->SetOutputOrigin( fixedImage->GetOrigin() );
+  warper->SetDeformationField( Gmultires->GetOutput() );
+
+  // by wook to set the large value as outside pixel value
+  warper->SetEdgePaddingValue(65535L);
+
+ #ifdef SET_SMALL_NUMBER_THREADS
+   warper->SetNumberOfThreads(1);
+ #endif
+
+   //#ifdef FORCED_UPDATE
+     warper->Update();
+     std::cout<< "warper spacing:" <<warper->GetOutput()->GetSpacing()    <<"warper origin:"<<warper->GetOutput()->GetOrigin() <<std::endl;
+     std::cout<< "warper size:" <<warper->GetOutput()->GetRequestedRegion().GetSize()    <<std::endl; 
+   //#endif
+
+
+               
+   if(registeredImageName.length()>0){
+	   typedef itk::ImageFileWriter< GrayImageType >  WriterType;
+	   WriterType::Pointer      writer =  WriterType::New();
+  		
+	   string registeredFileNamewithExtension =registeredImageName + ".vtk";
+	   writer->SetFileName( registeredFileNamewithExtension );
+	   writer->SetInput( warper->GetOutput()  );
+
+           #ifdef SET_SMALL_NUMBER_THREADS
+	   writer->SetNumberOfThreads(1);
+           #endif
+ 	  
+	   writer->Update();
+	   
+	   FieldWriterType::Pointer fieldWriter = FieldWriterType::New();
+
+	   string deformationFieldFileNamewithExtension = registeredImageName + "_DField.vtk";
+	   fieldWriter->SetFileName( deformationFieldFileNamewithExtension );
+	   fieldWriter->SetInput( Gmultires->GetOutput() );
+	   fieldWriter->Update();
+        }
+   
+   observer->CloseFile();  // by wook
+
+	////////////////////// store half DField  /////////////////////////////////////////
+  	 int ddx, ddy, ddz;
+	 ddx = Gmultires->GetOutput()->GetRequestedRegion().GetSize()[0];
+	 ddy = Gmultires->GetOutput()->GetRequestedRegion().GetSize()[1];
+	 ddz = Gmultires->GetOutput()->GetRequestedRegion().GetSize()[2];
+	 
+
+	//TNT::Array3D<VectorPixelType> vField( dx, dy, dz, (float)0);
+	DfieldIteratorType fieldIt( Gmultires->GetOutput(), Gmultires->GetOutput()->GetRequestedRegion().GetSize() );
+	DfieldIteratorType fieldOut( resultingDField, resultingDField->GetRequestedRegion().GetSize() );
+	
+	fieldIt.GoToBegin();
+	fieldOut.GoToBegin();
+	
+	int i,j,k;
+
+	for(k=0; k < ddz; k++){
+	  for(j=0; j < ddy; j++){
+	    for(i=0; i < ddx; i++){
+	      fieldOut.Set(  fieldIt.Get() );
+	      ++fieldOut;	
+	      ++fieldIt;
+	      
+	    }
+	  }
+         }
+}
+}   //   namespace THIRD_EDEMON
+#endif
+
+
diff --git a/bioimagesuite30_src/DemonsRegistration/vtkjwsSymmetricDemonsRegistration.cpp b/bioimagesuite30_src/DemonsRegistration/vtkjwsSymmetricDemonsRegistration.cpp
new file mode 100644
index 0000000..b298714
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/vtkjwsSymmetricDemonsRegistration.cpp
@@ -0,0 +1,482 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkjwsDemonsRegistration.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papd at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkImageImport.h"
+#include "vtkImageExport.h"
+#include "vtkjwsSymmetricDemonsRegistration.h"
+#include "vtkImageCast.h"
+#include "itkImage.h"
+#include "vtkIntArray.h"
+#include "vtkImageReslice.h"
+#include "vtkImageAppend.h"
+#include "itkVTKImageExport.h"
+#include "itkVTKImageImport.h"
+#include "vtkITKUtility.h"
+#include "vtkjwsSignedDanielssonDistanceMapImageFilter.h"
+#include <string.h>
+#include "wook.h"
+#include "OtherFunctions.h"
+using namespace jws_demons;
+#include "firstExtendedSymmetricDemon.h"
+#include "secondExtendedSymmetricDemon.h"
+#include "thirdSymmetricDemon.h"
+
+//---------------------------------------------------------------------------
+// First a Helper Class
+// -----------------------------------------------------------------------------
+vtkjwsSymmetricDemonsRegistration* vtkjwsSymmetricDemonsRegistration::New()
+{
+  return new vtkjwsSymmetricDemonsRegistration;
+}
+
+
+
+vtkjwsSymmetricDemonsRegistration::vtkjwsSymmetricDemonsRegistration()
+{
+  //ldsa
+  this->ReferenceDistanceMap=NULL;
+  this->TargetDistanceMap=NULL;
+  this->GridTransform=NULL;
+}
+// ----------------------------------------------------------------------------
+vtkjwsSymmetricDemonsRegistration::~vtkjwsSymmetricDemonsRegistration()
+{
+  this->SetReferenceDistanceMap(NULL);
+  this->SetTargetDistanceMap(NULL);
+  if (this->GridTransform!=NULL)
+    this->GridTransform->Delete();
+}
+// ----------------------------------------------------------------------------
+
+//  half_mode = 1 if using Second Demons where images 2 x size of the displacement field
+//  half_mode = 0 if image size = displacement field size
+
+vtkImageData* vtkjwsSymmetricDemonsRegistration_ConvertTransformation(vtkImageData* ReferenceDistanceMap,int half_mode,
+							     DeformationFieldType::Pointer DField)
+{
+  int dim[3]; ReferenceDistanceMap->GetDimensions(dim);
+  if (half_mode)
+    dim[0]=dim[0]/2;
+
+  vtkImageData* dispfield=vtkImageData::New();
+  dispfield->SetOrigin( ReferenceDistanceMap->GetOrigin()  );
+  dispfield->SetSpacing( ReferenceDistanceMap->GetSpacing()  );
+  dispfield->SetDimensions(dim);
+  dispfield->SetNumberOfScalarComponents(3);
+  dispfield->SetScalarTypeToDouble();
+  dispfield->AllocateScalars();
+
+  DeformationFieldType::IndexType pixelIndex;
+
+
+  for (int k=0;k<dim[2];k++)
+    {
+      pixelIndex[2]=k;
+      for (int j=0;j<dim[1];j++)
+	{
+	  pixelIndex[1]=j;
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      pixelIndex[0]=i;
+	      VectorPixelType v= DField->GetPixel(pixelIndex);
+	      dispfield->SetScalarComponentFromDouble(i,j,k,0,v[0]);
+	      dispfield->SetScalarComponentFromDouble(i,j,k,1,v[1]);
+	      dispfield->SetScalarComponentFromDouble(i,j,k,2,v[2]);
+	    }
+	}
+    }
+
+  return dispfield;
+}
+
+
+// ----------------------------------------------------------------------------
+int vtkjwsSymmetricDemonsRegistration::RunExtendedDemons(int Mode)
+{
+  if (Mode!=2)
+    Mode=1;
+
+
+  if (this->ReferenceDistanceMap==NULL || this->TargetDistanceMap==NULL)
+    {
+      vtkErrorMacro(<<"NULL Inputs to vtkjwsSymmetricDemonsRegistration");
+      return 0;
+    }
+
+  
+  // Resize Images to have equal and appropriate size
+  int newdimensions[3]; 
+  this->ReferenceDistanceMap->GetDimensions(newdimensions);
+
+  // Step 1 is take vtkImageData and convert to ITK
+  vtkImageCast* cast_ref=vtkImageCast::New();
+  cast_ref->SetInput(this->ReferenceDistanceMap);
+  cast_ref->SetOutputScalarTypeToFloat();
+
+  vtkImageCast* cast_targ=vtkImageCast::New();
+  cast_targ->SetInput(this->TargetDistanceMap);
+  cast_targ->SetOutputScalarTypeToFloat();
+  
+
+  // Create the appropriate input class (itk Image is OutputImageType which is 
+  // unsigned short -- see wook.h 
+  typedef itk::VTKImageImport<FixedImageType> ImportType;
+  
+  // Reference
+  vtkImageExport *vtkInputExporterRef = vtkImageExport::New();
+  vtkInputExporterRef->SetInput(cast_ref->GetOutput());
+  ImportType::Pointer itkInputImporterRef =  ImportType::New();
+  ConnectPipelines(vtkInputExporterRef, itkInputImporterRef);
+  itkInputImporterRef->Update();
+
+  vtkImageExport *vtkInputExporterTarg = vtkImageExport::New();
+  vtkInputExporterTarg->SetInput(cast_targ->GetOutput());
+  ImportType::Pointer itkInputImporterTarg =  ImportType::New();
+  ConnectPipelines(vtkInputExporterTarg, itkInputImporterTarg);
+  itkInputImporterTarg->Update();
+  
+  // Step 2 is run ITK Algorithm
+
+  // 2.a  Create Same Types etc.
+  OutputImageType::RegionType region; 
+  InputImageType::RegionType::IndexType indexStart;  
+  InputImageType::RegionType::SizeType  ImageSize;
+  ImageSize[0]=newdimensions[0];
+  ImageSize[1]=newdimensions[1];
+  ImageSize[2]=newdimensions[2];
+  
+  if (Mode==2) ImageSize[0]=newdimensions[0] / 2;
+  
+  indexStart[0]=0;   indexStart[1]=0;  indexStart[2]=0;
+  region.SetSize( ImageSize );
+  region.SetIndex(indexStart ); 	
+  cout<< "size of DField="<< region.GetSize()<<endl;
+   
+  // 2c Run Registration
+
+  DeformationFieldType::Pointer DField = DeformationFieldType::New();     
+  DField->SetRegions( region  );
+  DField->SetOrigin(  itkInputImporterRef->GetOutput()->GetOrigin()  );
+  DField->SetSpacing( itkInputImporterRef->GetOutput()->GetSpacing() );
+  DField->Allocate();
+
+
+  if (this->GridTransform!=NULL)
+    this->GridTransform->Delete();
+  this->GridTransform=vtkpxGridTransform::New();
+  this->GridTransform->SetInterpolationModeToLinear();
+  
+  vtkImageData* dispfield=NULL;
+
+  if (Mode==1)
+    {
+      string RegistrationResult = "FirstRegResultHalf";
+      FIRST_SEDEMON::firstExtendedDemonRegistration(itkInputImporterRef->GetOutput(), 
+						   itkInputImporterTarg->GetOutput(),
+						   DField, RegistrationResult);	
+      dispfield=vtkjwsSymmetricDemonsRegistration_ConvertTransformation(ReferenceDistanceMap,
+							       0,DField);
+    } 
+  else if (Mode==2)
+    {
+      string RegistrationResult = "SecondRegResultDouble";
+      SECOND_SEDEMON::ExtendedDemonRegistrationMain(itkInputImporterRef->GetOutput(), 
+						   itkInputImporterTarg->GetOutput(),
+						   DField, RegistrationResult);	
+      dispfield=vtkjwsSymmetricDemonsRegistration_ConvertTransformation(ReferenceDistanceMap,
+							       1,DField);
+
+    }
+  
+  // Step 3:
+  // Push it out to VTK
+  this->GridTransform->SetDisplacementGrid(dispfield);
+  dispfield->Delete();
+
+  cast_ref->Delete();
+  cast_targ->Delete();
+  vtkInputExporterRef->Delete();
+  vtkInputExporterTarg->Delete();
+
+  return 1;
+}
+
+// ---------------------------------------------------------------------------------------------
+
+int vtkjwsSymmetricDemonsRegistration::RunNormalDemons()
+{
+
+
+  if (this->ReferenceDistanceMap==NULL || this->TargetDistanceMap==NULL)
+    {
+      vtkErrorMacro(<<"NULL Inputs to vtkjwsSymmetricDemonsRegistration");
+      return 0;
+    }
+
+  
+  // Resize Images to have equal and appropriate size
+  int newdimensions[3]; 
+  this->ReferenceDistanceMap->GetDimensions(newdimensions);
+
+  // Step 1 is take vtkImageData and convert to ITK
+  vtkImageCast* cast_ref=vtkImageCast::New();
+  cast_ref->SetInput(this->ReferenceDistanceMap);
+  cast_ref->SetOutputScalarTypeToShort();
+
+  vtkImageCast* cast_targ=vtkImageCast::New();
+  cast_targ->SetInput(this->TargetDistanceMap);
+  cast_targ->SetOutputScalarTypeToShort();
+  
+
+  // Create the appropriate input class (itk Image is OutputImageType which is 
+  // unsigned short -- see wook.h 
+  typedef itk::VTKImageImport<GrayImageType> ImportType;
+  
+  // Reference
+  vtkImageExport *vtkInputExporterRef = vtkImageExport::New();
+  vtkInputExporterRef->SetInput(cast_ref->GetOutput());
+  ImportType::Pointer itkInputImporterRef =  ImportType::New();
+  ConnectPipelines(vtkInputExporterRef, itkInputImporterRef);
+  itkInputImporterRef->Update();
+
+  vtkImageExport *vtkInputExporterTarg = vtkImageExport::New();
+  vtkInputExporterTarg->SetInput(cast_targ->GetOutput());
+  ImportType::Pointer itkInputImporterTarg =  ImportType::New();
+  ConnectPipelines(vtkInputExporterTarg, itkInputImporterTarg);
+  itkInputImporterTarg->Update();
+  
+  // Step 2 is run ITK Algorithm
+
+  OutputImageType::RegionType region; 
+  InputImageType::RegionType::IndexType indexStart;  
+  InputImageType::RegionType::SizeType  ImageSize;
+  ImageSize[0]=newdimensions[0];
+  ImageSize[1]=newdimensions[1];
+  ImageSize[2]=newdimensions[2];
+  indexStart[0]=0;   indexStart[1]=0;  indexStart[2]=0;
+  region.SetSize( ImageSize );
+  region.SetIndex(indexStart ); 	
+
+  DeformationFieldType::Pointer DField = DeformationFieldType::New();     
+  DField->SetRegions( region  );
+  DField->SetOrigin(  itkInputImporterRef->GetOutput()->GetOrigin()  );
+  DField->SetSpacing( itkInputImporterRef->GetOutput()->GetSpacing() );
+  DField->Allocate();
+
+
+  if (this->GridTransform!=NULL)
+    this->GridTransform->Delete();
+  this->GridTransform=vtkpxGridTransform::New();
+  this->GridTransform->SetInterpolationModeToLinear();
+  
+
+  // Fixed Third Demons to Return displacement field
+
+  THIRD_SEDEMON::DemonRegistrationMain(itkInputImporterRef->GetOutput(), 
+				      itkInputImporterTarg->GetOutput(),
+				      DField, "");     
+  vtkImageData* dispfield=
+    vtkjwsSymmetricDemonsRegistration_ConvertTransformation(ReferenceDistanceMap,0,DField);
+  
+  // Step 3:
+  // Push it out to VTK
+  this->GridTransform->SetDisplacementGrid(dispfield);
+  dispfield->Delete();
+
+  cast_ref->Delete();
+  cast_targ->Delete();
+  vtkInputExporterRef->Delete();
+  vtkInputExporterTarg->Delete();
+
+  return 1;
+}
+
+// --------------------------------------------------------------------------------------------------------------------------------------
+vtkIntArray* vtkjwsSymmetricDemonsRegistration::DecideImageSize(vtkImageData* ref,vtkImageData* targ)
+{
+  int d[3];
+  int ok=DecideImageSize(ref,targ,d);
+  if (ok==0)
+    return NULL;
+
+  vtkIntArray* arr=vtkIntArray::New();
+  arr->SetNumberOfComponents(3);
+  arr->SetNumberOfTuples(1);
+  arr->SetComponent(0,0,d[0]);
+  arr->SetComponent(0,1,d[1]);
+  arr->SetComponent(0,2,d[2]);
+  
+  return arr;
+}
+
+// --------------------------------------------------------------------------------------------------------------------------------------
+
+int vtkjwsSymmetricDemonsRegistration::DecideImageSize(vtkImageData* ref,vtkImageData* targ,int outdim[3])
+{
+  if (ref==NULL || targ==NULL)
+    return 0;
+
+  int Image1size[3]; ref->GetDimensions(Image1size);
+  int Image2size[3]; targ->GetDimensions(Image2size);
+  
+  int sizeX1, sizeY1, sizeZ1;
+  int sizeX2, sizeY2, sizeZ2;
+  sizeX1 =Image1size[0];     sizeY1 = Image1size[1];    sizeZ1 = Image1size[2];
+  sizeX2 =Image2size[0];     sizeY2 = Image2size[1];    sizeZ2 = Image2size[2];
+  cout<<"Input Fixed image sizeX="<< sizeX1<<" sizeY="<<sizeY1<<" sizeZ="<<sizeZ1<<endl;
+  cout<<"Input Moving image sizeX="<< sizeX2<<" sizeY="<<sizeY2 <<" sizeZ="<<sizeZ2<<endl;
+  
+  int tempX, tempY, tempZ;
+  
+  InputImageType::RegionType::SizeType InternalImageSize;
+  if(sizeX1 >= sizeX2) tempX = sizeX1;
+  else tempX = sizeX2;
+  
+  if(sizeY1 >= sizeY2) tempY = sizeY1;
+  else tempY = sizeY2;
+  
+  if(sizeZ1 >= sizeZ2) tempZ = sizeZ1;
+  else tempZ = sizeZ2;
+  
+  int adjustX, adjustY, adjustZ;
+  
+  //adjustX =  ((tempX+2)>>2)<<2;	adjustY=  ((tempY+2)>>2)<<2;	adjustZ =  ((tempZ+2)>>2)<<2;
+  adjustX =  ((tempX+3)>>2)<<2;	adjustY=  ((tempY+3)>>2)<<2;	adjustZ =  ((tempZ+3)>>2)<<2;
+  cout<<"Adjusted image sizeX="<<adjustX<<" sizeY="<<adjustY <<" sizeZ="<<adjustZ<<endl;
+
+  
+  outdim[0] = adjustX;
+  outdim[1] = adjustY;
+  outdim[2] = adjustZ;
+  
+  return 1;
+}
+
+vtkImageData* vtkjwsSymmetricDemonsRegistration::PadImage(vtkImageData* inp,int x,int y, int z )
+{
+  int d[3];
+  d[0]=x;
+  d[1]=y;
+  d[2]=z;
+  return PadImage(inp,d);
+}
+
+vtkImageData* vtkjwsSymmetricDemonsRegistration::PadImage(vtkImageData* inp,int outdim[3])
+{
+
+  vtkImageReslice* pad=vtkImageReslice::New();
+  pad->SetInput(inp);
+  pad->SetOutputSpacing(inp->GetSpacing());
+  pad->SetOutputOrigin(inp->GetOrigin());
+  pad->SetInterpolationMode(0);
+  pad->SetOutputExtent(0,outdim[0]-1,0,outdim[1]-1,0,outdim[2]-1);
+  pad->Update();
+
+
+  vtkImageData* out=vtkImageData::New();
+  out->ShallowCopy(pad->GetOutput());
+  pad->Delete();
+
+  return out;
+}
+
+
+
+vtkImageData*  vtkjwsSymmetricDemonsRegistration::ComputeDistanceMap(vtkImageData* input,double lower_threshold,double upper_threshold)
+{
+  if (input==NULL)
+    {
+      fprintf(stderr,"Bad Input to ComputeDistanceMap\n");
+      return NULL;
+    }
+
+
+  // This is in the Levelset directory
+  vtkjwsSignedDanielssonDistanceMapImageFilter* filt=vtkjwsSignedDanielssonDistanceMapImageFilter::New();
+  filt->SetLowerThreshold(lower_threshold);
+  filt->SetUpperThreshold(upper_threshold);
+  filt->SetInValue(3056);
+  filt->SetOutValue(0);
+  filt->SetRadius(1);
+  filt->SetInput(input);
+  filt->Update();
+
+  vtkImageData* dmap=vtkImageData::New();
+  dmap->ShallowCopy(filt->GetOutput());
+  filt->Delete();
+  return dmap;
+}
+
+
+vtkImageData*  vtkjwsSymmetricDemonsRegistration::MergeDistanceMaps(vtkImageData* dmap1,vtkImageData* dmap2)
+{
+  if (dmap1==NULL || dmap2 == NULL)
+    {
+      fprintf(stderr,"Bad Input to Merge Distance Maps\n");
+      return NULL;
+    }
+
+
+  vtkImageAppend* filt=vtkImageAppend::New();
+  filt->AddInput(dmap1);
+  filt->AddInput(dmap2);
+  filt->SetAppendAxis(0);
+  filt->Update();
+
+  vtkImageData* dmap=vtkImageData::New();
+  dmap->ShallowCopy(filt->GetOutput());
+  filt->Delete();
+  return dmap;
+}
+
diff --git a/bioimagesuite30_src/DemonsRegistration/vtkjwsSymmetricDemonsRegistration.h b/bioimagesuite30_src/DemonsRegistration/vtkjwsSymmetricDemonsRegistration.h
new file mode 100644
index 0000000..c1169b4
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/vtkjwsSymmetricDemonsRegistration.h
@@ -0,0 +1,134 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkjwsDemonsRegistration.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkjwsDemonsRegistration -- corrects for B0 inhomogeneity in 1-H CSI Data for fat quantification
+
+#ifndef __vtkjwsSymmetricDemonsRegistration_h
+#define __vtkjwsSymmetricDemonsRegistration_h
+
+
+#include "vtkProcessObject.h"
+#include "vtkImageData.h"
+#include "vtkpxGridTransform.h"
+#include "vtkIntArray.h"
+
+class vtkjwsSymmetricDemonsRegistration : public vtkProcessObject
+{
+public:
+  static vtkjwsSymmetricDemonsRegistration *New();
+  vtkTypeMacro(vtkjwsSymmetricDemonsRegistration,vtkProcessObject);
+
+  // Description:
+  // Reference Image
+  vtkSetObjectMacro(ReferenceDistanceMap,vtkImageData);
+  vtkGetObjectMacro(ReferenceDistanceMap,vtkImageData);
+
+  // Description:
+  // Target Image
+  vtkSetObjectMacro(TargetDistanceMap,vtkImageData);
+  vtkGetObjectMacro(TargetDistanceMap,vtkImageData);
+
+
+  // Description:
+  // Transformation
+  vtkGetObjectMacro(GridTransform,vtkpxGridTransform);
+
+
+  // Description:
+  // Run Filter
+  // Mode = 1 => First  Demons
+  // Mode = 2 => Second Demons
+  virtual int RunExtendedDemons(int Mode);
+
+  // Mode =3 (Implied) --> GrayLevel Images
+  virtual int RunNormalDemons();
+
+
+  // Description:
+  // Processing Steps
+  static int            DecideImageSize(vtkImageData* ref,vtkImageData* targ,int outdim[3]);
+  static vtkIntArray* DecideImageSize(vtkImageData* ref,vtkImageData* targ);
+  static vtkImageData*  PadImage(vtkImageData* inp,int outdim[3]);
+  static vtkImageData*  PadImage(vtkImageData* inp,int x,int y,int z);
+
+  static vtkImageData*  ComputeDistanceMap(vtkImageData* input,double lower_threshold,double upper_threshold);
+  static vtkImageData*  MergeDistanceMaps(vtkImageData* dmap1,vtkImageData* dmap2);
+
+
+protected:
+
+  vtkjwsSymmetricDemonsRegistration();
+  virtual ~vtkjwsSymmetricDemonsRegistration();
+  vtkjwsSymmetricDemonsRegistration(const vtkjwsSymmetricDemonsRegistration&) {};
+  void operator=(const vtkjwsSymmetricDemonsRegistration&) {};
+
+  // Class Members
+  // -------------
+  vtkImageData*       ReferenceDistanceMap;
+  vtkImageData*       TargetDistanceMap;
+  vtkpxGridTransform* GridTransform;
+
+
+
+  // Description:
+  // Make Images Same size and multiples of 4
+
+
+
+
+  
+};
+#endif
+
diff --git a/bioimagesuite30_src/DemonsRegistration/wook.h b/bioimagesuite30_src/DemonsRegistration/wook.h
new file mode 100644
index 0000000..4b48db5
--- /dev/null
+++ b/bioimagesuite30_src/DemonsRegistration/wook.h
@@ -0,0 +1,148 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef __WOOK_H__
+#define  __WOOK_H__
+
+#include "itkImage.h"
+#include "itkImageFileReader.h"
+#include "itkImageFileWriter.h"
+
+///////////////////////////////   for mythreshold.cxx     ////////////////////////////////////////
+#include "itkBinaryMorphologicalClosingImageFilter.h"
+#include "itkBinaryBallStructuringElement.h" 
+#include "itkBinaryThresholdImageFilter.h"
+#include "itkSignedDanielssonDistanceMapImageFilter.h"
+#include "itkRescaleIntensityImageFilter.h"
+
+/////////////////////////   for DeformableRegistration.cxx /////////////////////////////////////////    
+#include "itkImageRegionIterator.h"
+#include "itkjwsDemonsRegistrationFilter.h"
+#include "itkjwsSymmetricForcesDemonsRegistrationFilter.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkjwsMultiResolutionPDEDeformableRegistration.h"
+#include "itkHistogramMatchingImageFilter.h"
+#include "itkCastImageFilter.h"
+#include "itkWarpImageFilter.h"
+#include "itkLinearInterpolateImageFunction.h"
+#include "itkExceptionObject.h"
+#include "itkCastImageFilter.h"
+
+#include <math.h>
+#include <stdio.h>
+
+///////////////////////////  for Vector3DImage.cxx  //////////////////////////////////
+#include "itkCompose3DVectorImageFilter.h" 
+#include "itkCompose2DVectorImageFilter.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkImageRegionIteratorWithIndex.h"
+#include "itkDiscreteGaussianImageFilter.h"
+/////////////////////////////////////////////////////////////////////////////////////////////////////
+  using namespace std;
+
+namespace jws_demons {
+
+  typedef  unsigned short  InputPixelType;
+  typedef  unsigned short  OutputPixelType;
+  typedef  float		   FloatPixelType;
+  
+  typedef  short  GrayPixelType;
+  
+  const unsigned int Dimension = 3;
+  
+  typedef itk::Image< InputPixelType,  Dimension >   InputImageType;
+  typedef itk::Image< OutputPixelType, Dimension >   OutputImageType;
+  typedef itk::Image< FloatPixelType, Dimension > FloatImageType;
+  typedef itk::Image< GrayPixelType,  Dimension >   GrayImageType;
+  
+
+  typedef itk::ImageFileReader< InputImageType  >  ReaderType;
+  typedef itk::ImageFileWriter< OutputImageType >  WriterType;
+  typedef itk::ImageFileReader< FloatImageType  >  FloatReaderType;
+  typedef itk::ImageFileWriter< FloatImageType >   FloatWriterType;
+  
+  typedef itk::ImageFileReader< GrayImageType  >  GrayReaderType;
+  typedef itk::ImageFileWriter< GrayImageType >   GrayWriterType;
+  
+  typedef itk::ImageRegionIteratorWithIndex<  InputImageType >  IteratorType;
+  typedef itk::ImageRegionIteratorWithIndex< OutputImageType >  OutImageIteratorType;
+  
+  typedef itk::ImageRegionIteratorWithIndex<  GrayImageType >  IteratorGrayType;
+  typedef itk::ImageRegionIteratorWithIndex< GrayImageType >  OutImageIteratorGrayType;  
+  
+  typedef itk::BinaryThresholdImageFilter< InputImageType, InputImageType >  ThresholdFilterType;
+   
+  typedef itk::BinaryBallStructuringElement< 
+                      InputPixelType,
+                      Dimension  >             StructuringElementType;
+
+  typedef itk::BinaryMorphologicalClosingImageFilter<
+    InputImageType, 
+                            OutputImageType, 
+                            StructuringElementType >  ClosingFilterType; 
+
+  typedef itk::SignedDanielssonDistanceMapImageFilter<
+                                         InputImageType, 
+                                         FloatImageType >  DMapFilterType; 
+
+/////////////////////////   for DeformableRegistration.cxx ///////////////////////////////////////// 
+
+  typedef float RegPixelType;
+
+  typedef itk::Image< RegPixelType, Dimension >  FixedImageType;
+  typedef itk::Image< RegPixelType, Dimension >  MovingImageType;
+  typedef itk::Image< RegPixelType, Dimension >  InternalImageType;
+  
+  typedef itk::Vector< RegPixelType, Dimension >    VectorPixelType;
+  typedef itk::Image<  VectorPixelType, Dimension > DeformationFieldType;
+  
+  typedef itk::ImageFileReader< DeformationFieldType  >  DFieldReaderType;
+  
+  typedef itk::ImageFileWriter< DeformationFieldType > FieldWriterType;
+
+  typedef itk::ImageRegionIteratorWithIndex< InternalImageType >  InternalIteratorType;
+  typedef itk::ImageRegionIteratorWithIndex< DeformationFieldType >  DfieldIteratorType;
+  
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+  typedef itk::WarpImageFilter<                                               
+                          MovingImageType, 
+                          MovingImageType,
+                          DeformationFieldType  >     WarperType;
+  
+    typedef itk::WarpImageFilter< GrayImageType, 
+                               GrayImageType, 
+                                DeformationFieldType  >  GrayWarperType;
+  
+    typedef itk::DiscreteGaussianImageFilter<
+                 InternalImageType, InternalImageType >  DiscreteGaussianFilterType;
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+	
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/GUI/CMakeLists.txt b/bioimagesuite30_src/GUI/CMakeLists.txt
new file mode 100644
index 0000000..2c4293e
--- /dev/null
+++ b/bioimagesuite30_src/GUI/CMakeLists.txt
@@ -0,0 +1,178 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+SET(KITBASE GUI)
+SET(KIT vtkpx${KITBASE})
+
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/${KITBASE})
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/pxtklib)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Graphics)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Legacy)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Registration)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Imaging)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Nmrlib)
+
+
+
+
+SET (KITSRCS
+# ------------------------------------------------------------
+# Base GUI Stuff.cpp
+# ------------------------
+vtkpxGUIComponent.cpp
+vtkbisGUINIFTIHeaderEditor.cpp
+# -----------------------
+# Gui Stuff -- 1 Renderers
+# -----------------------
+vtkpxGUIBaseRenderer.cpp
+vtkpxGUIRenderer.cpp
+vtkpxGUI4DRenderer.cpp
+# ------------------------
+# Gui Stuff 2 -- viewers
+# ------------------------
+vtkpxGUIBaseImageViewer.cpp
+vtkpxGUIBaseCurveEditor.cpp
+vtkpxGUI2DImageViewer.cpp
+vtkpxGUIMosaicViewer.cpp
+vtkpxGUIObjectmapMosaicViewer.cpp
+vtkpxGUIMultipleMosaicViewer.cpp
+vtkpxGUICurveImageEditor.cpp
+vtkpxGUIContourStackEditor.cpp
+vtkpxGUIOrthogonalViewer.cpp
+vtkpxGUIObjectmapOrthogonalViewer.cpp
+vtkpxGUIOrthogonal4DViewer.cpp
+vtkpxGUI2DSplineObjectmapViewer.cpp
+vtkpxGUISplineEditor.cpp
+# ----------------------------
+# Objectmap Editor Attachments
+# ----------------------------
+vtkpxGUIAbstractMultisliceEditor.cpp
+vtkpxGUIObjectmapMosaicEditor.cpp
+vtkpxGUIObjectmapOrthogonalEditor.cpp
+vtkpxGUI2DImageEditor.cpp
+# ---------------------------------
+# GYU Stuff 3 - auxiliary controls
+# ---------------------------------
+vtkpxGUIAnalyzeHeaderEditor.cpp
+vtkpxGUIColormapEditor.cpp
+vtkpxGUIBaseCurveControl.cpp
+vtkpxGUIPolyDataControl.cpp
+vtkpxGUIObjectmapSplineControl.cpp
+vtkpxGUISplineControl.cpp
+vtkpxGUISplineStackControl.cpp
+vtkpxGUIObjectmapSplineStackControl.cpp
+vtkpxGUI4DSplineStackControl.cpp
+vtkpxGUITriangulatedStackControl.cpp
+vtkpxGUI4DTriangulatedStackControl.cpp
+vtkpxGUIFemPostControl.cpp
+#vtkpxGUITransformControl.cpp
+vtkpxGUIVolumeControl.cpp
+vtkpxGUIObliqueImageSliceControl.cpp
+#
+pxvtkgadgets.cpp
+pxvtktkdialog.cpp
+pxtkanaheadercontrol.cpp
+vtkpxGUICallback.cpp
+vtkpxTalairachTransform.cpp
+vtkpxTalairachTransformHelper.cpp
+#
+)
+
+#IF (BIOIMAGESUITE3_EXPERIMENTAL)
+#SET (KITSRCS
+#    ${KITSRCS}
+#    vtkbisFMRITools.cpp
+#}
+
+SET (KITTCLSRCS 
+  vtkpxtkGUIlib.cpp
+  )
+
+SET (KIIPYTHONSRCS
+#  vtkpxPythonGUIlib.cpp
+)
+
+SET_SOURCE_FILES_PROPERTIES(
+ vtkpxGUIBaseImageViewer.cpp
+ vtkpxGUIBaseCurveEditor.cpp
+ vtkpxGUIBaseRenderer.cpp
+ vtkpxGUIAbstractMultisliceEditor.cpp
+ABSTRACT
+)
+
+SET_SOURCE_FILES_PROPERTIES(
+ pxtkanaheadercontrol.cpp
+ pxvtkgadgets.cpp
+ pxvtktkdialog.cpp
+ vtkpxGUICallback.cpp
+ vtkpxTalairachTransformHelper.cpp
+ WRAP_EXCLUDE
+)
+
+SET(KITLIBS
+  numerics
+  vtkpxRegistration
+  vtkpxRegistrationTCL
+  vtkpxLegacy
+  vtkpxLegacyTCL
+  vtkpxGraphics
+  vtkpxGraphicsTCL
+  vtkpxImaging
+  vtkpxCommon
+  vtkpxCommonTCL
+  vtkCommonTCL
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+  pxtklib
+)
+
+	
+
+
+IF (CYGWIN)
+SET (KITLIBS
+    ${KITLIBS}
+    -ltk84
+    )
+ENDIF(CYGWIN)
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+bis_complex("GUI" ${KIT} ${FILELIST})
+
+
+
+
diff --git a/bioimagesuite30_src/GUI/pxtkanaheadercontrol.cpp b/bioimagesuite30_src/GUI/pxtkanaheadercontrol.cpp
new file mode 100644
index 0000000..778aad5
--- /dev/null
+++ b/bioimagesuite30_src/GUI/pxtkanaheadercontrol.cpp
@@ -0,0 +1,393 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+ see pxtkanaheader.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+#include "pxtkanaheadercontrol.h"
+#include "pxtkcomplexwidgets.h"
+
+PXTkAnaHeaderControl::PXTkAnaHeaderControl(PXTkEventObj* evpar,PXTkGadget* par):PXTkDialog(evpar,par,
+											     "Ana-Header Control",PXFalse)
+{
+  header=new anaimagedata;
+  header_filename=new char[40];
+  strcpy(header_filename,"new_header.hdr");
+}
+
+PXTkAnaHeaderControl::~PXTkAnaHeaderControl()
+{
+  delete header;
+  delete [] header_filename;
+}
+ 
+int  PXTkAnaHeaderControl::initDisplay()
+{
+  int i=0;
+
+  PXTkDialog::initDisplay();
+  PXTkFrame* mainFrame=(PXTkFrame*)(main_window);
+
+  PXTkFrame* menubar=new PXTkFrame(this,mainFrame);
+  mainFrame->addChildren("-side top -expand false -fill x -pady 5",menubar);
+
+  PXTkFrame* otherFrame=new PXTkFrame(this,mainFrame);
+  mainFrame->addChildren("-side top -expand true -fill both -pady 5",otherFrame);
+  mainFrame->setPackMode(PXFalse);
+
+  PXTkMenuButton* but1=new PXTkMenuButton(this,menubar,"Header",-1,PXTrue);
+  menubar->configure("-relief","ridge");
+  menubar->addChildren("-side left -expand false ",but1);
+
+  PXTkMenu *menu1=new PXTkMenu(this,but1,PXFalse);
+  menu1->addButton("New",100);
+  menu1->addSeparator();
+  menu1->addButton("Load",101);
+  menu1->addButton("Save",102);
+  menu1->addButton("Save As",103);
+  menu1->addSeparator();
+  menu1->addButton("Close",3);
+
+  // Dimensions xsize,ysize,zsize,tsize
+  // Pixel Dims xpix,ypix,zpix,orient,MinValue,MaxValue,bits
+
+  PXTkLabelFrame* dimensionframe=new PXTkLabelFrame(this,otherFrame,"Image Dimensions (voxels)");
+  PXTkLabelFrame* voxelframe=new PXTkLabelFrame(this,otherFrame,"Voxel Dimensions (mm)");
+  PXTkLabelFrame* intensityframe=new PXTkLabelFrame(this,otherFrame,"Intensity Range");
+  PXTkLabelFrame* miscframe=new PXTkLabelFrame(this,otherFrame,"Image Type");
+
+  otherFrame->addChildren("-side top -fill both -expand t",dimensionframe,voxelframe,intensityframe,miscframe);
+
+
+  // First Dimension Frame 
+  for (i=0;i<=3;i++)
+    {
+      label[i]=new PXTkLabel(this,dimensionframe,"X-Size");
+      label[i]->configure("-width",5);
+      entry[i]=new PXTkEntry(this,dimensionframe);
+      entry[i]->configure("-width",5);
+      entry[i]->configure("-relief","sunken");
+      switch(i) 
+	{
+	case 0:
+	  label[i]->setText("xsize");
+	  break;
+	case 1:
+	  label[i]->setText("ysize");
+	  break;
+	case 2:
+	  label[i]->setText("zsize");
+	  break;
+	case 3:
+	  label[i]->setText("tsize");
+	  break;
+	}
+      dimensionframe->addChildren("-side left -padx 2 -fill x -expand t",label[i],entry[i]);
+    }
+
+  // Then Voxel Frame 
+  for (i=4;i<=6;i++)
+    {
+      label[i]=new PXTkLabel(this,voxelframe,"X-Size");
+      label[i]->configure("-width",5);
+      entry[i]=new PXTkEntry(this,voxelframe);
+      entry[i]->configure("-width",5);
+      entry[i]->configure("-relief","sunken");
+      switch(i) 
+	{
+	case 4:
+	  label[i]->setText("x-size");
+	  break;
+	case 5:
+	  label[i]->setText("y-size");
+	  break;
+	case 6:
+	  label[i]->setText("z-size");
+	  break;
+	}
+      voxelframe->addChildren("-side left -padx 2 -fill x -expand t",label[i],entry[i]);
+    }
+
+
+  // Then Intensity Frame 
+  for (i=7;i<=8;i++)
+    {
+      label[i]=new PXTkLabel(this,intensityframe,"X-Size");
+      label[i]->configure("-width",5);
+      entry[i]=new PXTkEntry(this,intensityframe);
+      entry[i]->configure("-width",5);
+      entry[i]->configure("-relief","sunken");
+      switch(i) 
+	{
+	case 7:
+	  label[i]->setText("Min:");
+	  break;
+	case 8:
+	  label[i]->setText("Max:");
+	  break;
+	}
+      intensityframe->addChildren("-side left -padx 2 -fill x -expand t",label[i],entry[i]);
+    }
+
+  PXTkLabel* lab0=new PXTkLabel(this,miscframe,"Orientation:");
+  orientation=new PXTkOptionMenu(this,miscframe,"Axial (0)",-1);
+  orientation->addOption("Coronal (1)",-1);
+  orientation->addOption("Sagittal (2)",-1);
+  orientation->addOption("Polar (3)",-1);
+  
+  PXTkLabel* lab1=new PXTkLabel(this,miscframe,"Data Type:");
+  data_type=new PXTkOptionMenu(this,miscframe,"1-Byte (8)",-1);
+  data_type->addOption("Short (2)",-1);
+  data_type->addOption("Float (4)",-1);
+  data_type->setIndex(1);
+
+  byte_swapped=new PXTkCheckButton(this,miscframe,"Byte Swapped",-1);
+  miscframe->addChildren("-side left -fill x -expand t",lab0,orientation,lab1,data_type);
+  miscframe->addChildren("-side left -fill x -expand t",byte_swapped);
+
+ 
+  is_display_ok=PXTrue;
+  resetHeader();
+  displayHeader();
+  return TCL_OK;
+
+}
+
+int  PXTkAnaHeaderControl::handleEvent(int event)
+{
+  if (event<10)
+      return PXTkDialog::handleEvent(event);
+
+  switch(event)
+      {
+      case 100:
+	resetHeader();
+	displayHeader();
+	break;
+
+      case 101:
+	{
+	  char* line=getOpenFilename("Header File name","Header Files","*.hdr*");
+	  
+	  if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		    readHeader(line);
+	      }
+	}
+	break;
+	
+      case 102:
+	saveHeader(header_filename);
+	break;
+	
+      case 103:
+	{
+	  char* line=getSaveFilename("Header File Name",header_filename,"Header Files","*.hdr");
+	  if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		    saveHeader(line);
+	      }
+	}
+	break;
+      }
+
+  return TCL_OK;
+}
+
+int PXTkAnaHeaderControl::readHeader(const char* name)
+{
+  header_bits=readanahdr(name,header);
+  if (header_bits==0)
+      {
+	setHeaderFromDialog();
+      }
+  else
+      {
+	delete [] header_filename;
+	header_filename=new char[strlen(name)+1];
+	strcpy(header_filename,name);
+	displayHeader();
+      }
+  return TCL_OK;
+}
+
+int PXTkAnaHeaderControl::saveHeader(const char* name)
+{
+  strcpy(pxtk_buffer,name);
+  setHeaderFromDialog();
+  
+  int ok=writeanahdr(pxtk_buffer,header,header_bits);
+
+  if (ok)
+      {
+	if (strcmp(header_filename,pxtk_buffer)!=0)
+	  {
+	    delete [] header_filename;
+	    header_filename=new char[strlen(pxtk_buffer)+1];
+	    strcpy(header_filename,pxtk_buffer);
+	  }
+      }
+  return displayHeader();
+
+}
+
+int PXTkAnaHeaderControl::setHeaderFromDialog()
+{
+  header->xsize=Irange(atoi(entry[0]->getText()),1,1024);
+  header->ysize=Irange(atoi(entry[1]->getText()),1,1024);
+  header->zsize=Irange(atoi(entry[2]->getText()),1,1024);
+  header->tsize=Irange(atoi(entry[3]->getText()),1,1024);
+
+  header->xpix=Frange(atof(entry[4]->getText()),(float)0.01,(float)100.0);
+  header->ypix=Frange(atof(entry[5]->getText()),(float)0.01,(float)100.0);
+  header->zpix=Frange(atof(entry[6]->getText()),(float)0.01,(float)100.0);
+
+  header->minpix=Irange(atoi(entry[7]->getText()),-65535,65535);
+  header->maxpix=Irange(atoi(entry[8]->getText()),-65535,65535);
+  
+  header->orient=Irange(orientation->getIndex(),0,5);
+
+  switch (data_type->getIndex())
+    {
+    case 0:
+      header_bits=8;
+      break;
+    case 1:
+      header_bits=16;
+      break;
+    case 2:
+      header_bits=32;
+      break;
+    }
+  
+  if (byte_swapped->getState())
+    header_bits=-header_bits;
+
+  return TCL_OK;
+}
+int PXTkAnaHeaderControl::resetHeader()
+{
+  header->zsize=128;
+  header->xsize=128;
+  header->ysize=128;
+  header->tsize=1;
+  header->zasp=1.0; header->yasp=1.0;header->xasp=1.0;
+  header->zpix=1.0; header->ypix=1.0;header->xpix=1.0;
+  header->minpix=0;header->maxpix=65536;
+  header->trueminpix=0; header->truemaxpix=65536;
+  header->orient=0;
+  header_bits=16;
+  return TCL_OK;
+}
+
+
+int PXTkAnaHeaderControl::displayHeader()
+{
+  for (int i=0;i<=11;i++)
+      {
+	switch(i)
+	    {
+	    case 0:
+	      sprintf(pxtk_buffer,"%d",header->xsize);
+	      break;
+	    case 1:
+	      sprintf(pxtk_buffer,"%d",header->ysize);
+	      break;
+	    case 2:
+	      sprintf(pxtk_buffer,"%d",header->zsize);
+	      break;
+	    case 3:
+	      sprintf(pxtk_buffer,"%d",header->tsize);
+	      break;
+	    case 4:
+	      sprintf(pxtk_buffer,"%5.2f",header->xpix);
+	      break;
+	    case 5:
+	      sprintf(pxtk_buffer,"%5.2f",header->ypix);
+	      break;
+	    case 6:
+	      sprintf(pxtk_buffer,"%5.2f",header->zpix);
+	      break;
+	    case 7:
+	      sprintf(pxtk_buffer,"%d",header->minpix);
+	      break;
+	    case 8:
+	      sprintf(pxtk_buffer,"%d",header->maxpix);
+	      break;
+	    case 9:
+	      {
+		int or_nt=header->orient;
+		if (or_nt<0 || or_nt>2)
+		  or_nt=3;
+		orientation->setIndex(or_nt);
+	      }
+	      break;
+	    case 10:
+	      {
+		int h=abs(header_bits);
+		switch (h)
+		  {
+		  case 8:
+		    data_type->setIndex(0);
+		    break;
+		  case 16:
+		    data_type->setIndex(1);
+		    break;
+		  case 32:
+		    data_type->setIndex(2);
+		    break;
+		  }
+	      }
+	      break;
+	    case 11:
+	      if (header_bits>0)
+		byte_swapped->setState(PXFalse);
+	      else
+		byte_swapped->setState(PXTrue);
+	      break;
+	    }
+	if (i<9)
+	  entry[i]->setText(pxtk_buffer);
+      }
+
+  strcpy(pxtk_buffer,header_filename);
+  sprintf(pxtk_buffer2,"%s",PXTkApp::getFilenameTail(pxtk_buffer));
+  setTitle(pxtk_buffer2);
+  return TCL_OK;
+}
+
diff --git a/bioimagesuite30_src/GUI/pxtkanaheadercontrol.h b/bioimagesuite30_src/GUI/pxtkanaheadercontrol.h
new file mode 100644
index 0000000..f3ac718
--- /dev/null
+++ b/bioimagesuite30_src/GUI/pxtkanaheadercontrol.h
@@ -0,0 +1,114 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// PXTkanaheader.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkAnaHeaderControl
+
+
+_Description : Definition of Classes to draw iso-surfaces 
+ 
+               PXTkAnaHeaderControl()
+
+_Call : 
+
+  
+_References : The Visualization Toolkit: An Object-Oriented
+              Approach to Graphics. 2nd Edition. Prentice-Hall
+	      Schroeder, Martin and Lorensen
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 17th August 2000
+                                
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXTK_AnaHeaderControl
+#define _PXTK_AnaHeaderControl
+#include "pxutil.h"
+#include "pxtkapp.h"
+#include "pxtkdialog.h"
+#include "pxtkgadgets.h"
+#include "pxtkcomplexwidgets.h"
+#include "pxtkseldialog.h"
+#include "pxtkmenu.h"
+
+// ****************************************
+// ******* PXTkAnaHeaderControl Class ********
+// ****************************************
+
+class  PXTkAnaHeaderControl : public PXTkDialog
+{
+protected:
+  anaimagedata *header;
+  int           header_bits;
+  char*         header_filename;
+ 
+  PXTkLabel* label[9];
+  PXTkEntry* entry[9];
+
+  PXTkOptionMenu* orientation;
+  PXTkOptionMenu* data_type;
+  PXTkCheckButton* byte_swapped;
+
+public:
+  
+  PXTkAnaHeaderControl(PXTkEventObj* evpar,PXTkGadget* par);
+
+  virtual ~PXTkAnaHeaderControl();
+
+  virtual int  initDisplay();
+  virtual int  handleEvent(int);
+
+  virtual int  readHeader(const char* name);
+  virtual int  saveHeader(const char* name);
+  virtual int  resetHeader();
+  virtual int  setHeaderFromDialog();
+  virtual int  displayHeader();
+};
+
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/pxvtkgadgets.cpp b/bioimagesuite30_src/GUI/pxvtkgadgets.cpp
new file mode 100644
index 0000000..ed1c760
--- /dev/null
+++ b/bioimagesuite30_src/GUI/pxvtkgadgets.cpp
@@ -0,0 +1,313 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+
+   see pxvtkgadgets.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxvtkgadgets.h"
+#include "pxtkeventobj.h"
+#include "pxtkdialog.h"
+#include "vtkTclUtil.h"
+#include "vtkRenderWindow.h"
+
+/* -------------------------------------------------------------------------*/
+/*                   PXVTkTkGadget                                          */
+/* -------------------------------------------------------------------------*/
+
+PXVTkTkGadget::PXVTkTkGadget(PXTkEventObj* evpar,PXTkGadget* gadg_par,int moption):PXTkGadget(evpar,gadg_par)
+{
+  call_no=moption;
+}
+
+int PXVTkTkGadget::setWidthHeight(int w,int h)
+{
+  int a=TCL_OK;
+  if (w>0)
+      a=configure("-width",w);
+  if (h>0 && a==TCL_OK)
+      a=configure("-height",w);
+  return a;
+}
+ 
+int PXVTkTkGadget::setPadding(int bd,int padx,int pady)
+{
+  int a=TCL_OK;
+  if (bd>=0)
+      a=configure("-borderwidth",bd);
+  if (padx>=0 && a==TCL_OK)
+      a=configure("-padx",padx);
+  if (pady>=0 && a==TCL_OK)
+      a=configure("-pady",pady);
+  return a;
+}
+
+int PXVTkTkGadget::bindMouseEvents()
+{
+  if (!has_event_parent)
+      return 0;
+
+  strcpy(pxtk_buffer2," %x %y");
+  for (int mouse=1;mouse<=3;mouse++)
+      {
+	sprintf(pxtk_buffer,"bind %s <ButtonPress-%d> { pxtkcallback %d %d %d 0 %s %d }",
+		getWidgetName(),mouse,
+		event_parent->getHandlerNo(),call_no,mouse,pxtk_buffer2,object_id);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	
+	sprintf(pxtk_buffer,"bind %s <B%d-Motion> { pxtkcallback %d %d %d 1 %s %d }",
+		getWidgetName(),mouse,
+		event_parent->getHandlerNo(),call_no,mouse,pxtk_buffer2,object_id);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	
+	sprintf(pxtk_buffer,"bind %s <ButtonRelease-%d> { pxtkcallback %d %d %d 2 %s %d }",
+		getWidgetName(),mouse,
+		event_parent->getHandlerNo(),call_no,mouse,pxtk_buffer2,object_id);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+
+	sprintf(pxtk_buffer,"bind %s <Shift-ButtonPress-%d> { pxtkcallback %d %d %d 0 %s %d }",
+		getWidgetName(),mouse,
+		event_parent->getHandlerNo(),call_no,mouse+3,pxtk_buffer2,object_id);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	
+	sprintf(pxtk_buffer,"bind %s <Shift-B%d-Motion> { pxtkcallback %d %d %d 1 %s %d }",
+		getWidgetName(),mouse,
+		event_parent->getHandlerNo(),call_no,mouse+3,pxtk_buffer2,object_id);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	
+	sprintf(pxtk_buffer,"bind %s <Shift-ButtonRelease-%d> { pxtkcallback %d %d %d 2 %s %d }",
+		getWidgetName(),mouse,
+		event_parent->getHandlerNo(),call_no,mouse+3,pxtk_buffer2,object_id);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+
+	sprintf(pxtk_buffer,"bind %s <Control-ButtonPress-%d> { pxtkcallback %d %d %d 0 %s %d }",
+		getWidgetName(),mouse,
+		event_parent->getHandlerNo(),call_no,mouse+6,pxtk_buffer2,object_id);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	
+	sprintf(pxtk_buffer,"bind %s <Control-B%d-Motion> { pxtkcallback %d %d %d 1 %s %d }",
+		getWidgetName(),mouse,
+		event_parent->getHandlerNo(),call_no,mouse+6,pxtk_buffer2,object_id);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	
+	sprintf(pxtk_buffer,"bind %s <Control-ButtonRelease-%d> { pxtkcallback %d %d %d 2 %s %d }",
+		getWidgetName(),mouse,
+		event_parent->getHandlerNo(),call_no,mouse+6,pxtk_buffer2,object_id);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+
+      }
+
+  /*sprintf(pxtk_buffer,"bind %s <Map> { pxtkcallback %d %d %d }",
+	  getWidgetName(),
+	  event_parent->getHandlerNo(),call_no+1,object_id);
+  PXTkApp::executeTclCommand(pxtk_buffer);*/
+  
+  /*sprintf(pxtk_buffer,"bind %s <Configure> { pxtkcallback %d %d %d }",
+	  getWidgetName(),
+	  event_parent->getHandlerNo(),call_no+1,object_id);
+  PXTkApp::executeTclCommand(pxtk_buffer);*/
+  
+  sprintf(pxtk_buffer,"bind %s <Expose> { pxtkcallback %d %d %d }",
+	  getWidgetName(),
+	  event_parent->getHandlerNo(),call_no+1,object_id);
+  PXTkApp::executeTclCommand(pxtk_buffer);
+
+  return 1;
+}
+
+/* -------------------------------------------------------------------------*/
+/*       Definition of PXVTkTkRenderWidget Class                            */
+/* -------------------------------------------------------------------------*/
+PXVTkTkRenderWidget::PXVTkTkRenderWidget(PXTkEventObj* evpar,PXTkGadget* gadg_par,
+					 int moption):PXVTkTkGadget(evpar,gadg_par,moption)
+{
+  initDisplay();
+}
+  
+int PXVTkTkRenderWidget::initDisplay()
+{
+  sprintf(pxtk_buffer,"vtkTkRenderWidget %s -width 300 -height 300",widget_name);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+
+  if (a!=TCL_OK)
+      return TCL_ERROR;
+  
+  // GetRenderWindow
+  sprintf(pxtk_buffer," %s GetRenderWindow",widget_name);
+  PXTkApp::executeTclCommand(pxtk_buffer);
+  
+  strcpy(pxtk_buffer,PXTkApp::getTclStringResult());
+
+  // Get Pointers to C++ classes
+  int error=0;
+  vtkRenderWindow *renWin = (vtkRenderWindow *)(vtkTclGetPointerFromObject(pxtk_buffer,"vtkRenderWindow",
+									   PXTkApp::tcl_interpreter,error));  
+  if (error==1)
+    {
+      is_display_ok=PXFalse;
+      renderWindow=NULL;
+      renderer=NULL;
+      return TCL_ERROR;
+    }
+  is_display_ok=PXTrue;
+  renderWindow=renWin;
+  renderer=vtkRenderer::New();
+  renderWindow->AddRenderer(renderer);
+  return TCL_OK;
+}
+
+vtkRenderWindow* PXVTkTkRenderWidget::getRenderWindow()
+{
+  return renderWindow;
+}
+
+vtkRenderer* PXVTkTkRenderWidget::getRenderer()
+{
+  return renderer;
+}
+
+
+void PXVTkTkRenderWidget::Render()
+{
+  if (is_display_ok)
+      renderWindow->Render();
+}
+
+void PXVTkTkRenderWidget::RenderDelay(int t)
+{
+  Tcl_CreateTimerHandler(t,PXVTkTkRenderWidget::handleRenderEvent,this);
+}
+
+void PXVTkTkRenderWidget::handleRenderEvent(void *arg1)
+{
+  ((PXVTkTkRenderWidget*)arg1)->Render();
+}
+
+
+/* -------------------------------------------------------------------------*/
+/*           Definition of PXVTkTkImageViewerWidget                         */
+/* -------------------------------------------------------------------------*/
+/*PXVTkTkImageWindowWidget::PXVTkTkImageWindowWidget(PXTkEventObj* evpar,PXTkGadget* gadg_par,
+						   int moption):PXVTkTkGadget(evpar,gadg_par,moption)
+{
+  initDisplay();
+}
+  
+int PXVTkTkImageWindowWidget::initDisplay()
+{
+  sprintf(pxtk_buffer,"vtkImageWindow pxvtkren%d",object_id);
+  PXTkApp::executeTclCommand(pxtk_buffer);
+
+  sprintf(pxtk_buffer,"vtkTkImageWindowWidget %s -width 150 -height 150 -iw pxvtkren%d",widget_name,object_id);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  
+  if (a!=TCL_OK)
+      return TCL_ERROR;
+  
+  int error=0;
+  sprintf(pxtk_buffer,"pxvtkren%d",object_id);
+  // Get Pointers to C++ classes
+  vtkImageWindow *ren = (vtkImageWindow *)(vtkTclGetPointerFromObject(pxtk_buffer,"vtkImageWindow",
+								      PXTkApp::tcl_interpreter,error));  
+  if (error==1)
+      {
+	is_display_ok=PXFalse;
+	imageWindow=NULL;
+#ifndef _WIN32
+	fprintf(stderr,"Bad Image Viewer %s\n",widget_name);
+#endif
+	return TCL_ERROR;
+      }
+  is_display_ok=PXTrue;
+  imageWindow=ren;
+  return TCL_OK;
+}
+
+vtkImageWindow* PXVTkTkImageWindowWidget::getImageWindow()
+{
+  return imageWindow;
+}
+*/
+
+/* -------------------------------------------------------------------------*/
+/*           Definition of PXVTkTkImageViewerWidget                         */
+/* -------------------------------------------------------------------------*/
+
+/*PXVTkTkImageViewerWidget::PXVTkTkImageViewerWidget(PXTkEventObj* evpar,PXTkGadget* gadg_par,
+						   int moption):PXVTkTkGadget(evpar,gadg_par,moption)
+{
+  initDisplay();
+}
+  
+int PXVTkTkImageViewerWidget::initDisplay()
+{
+  sprintf(pxtk_buffer,"vtkImageViewer pxvtkren%d",object_id);
+  PXTkApp::executeTclCommand(pxtk_buffer);
+
+  sprintf(pxtk_buffer,"vtkTkImageViewerWidget %s -width 150 -height 150 -iv pxvtkren%d",widget_name,object_id);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  
+  if (a!=TCL_OK)
+      return TCL_ERROR;
+  
+  int error=0;
+  sprintf(pxtk_buffer,"pxvtkren%d",object_id);
+  // Get Pointers to C++ classes
+  vtkImageViewer *ren = (vtkImageViewer *)(vtkTclGetPointerFromObject(pxtk_buffer,"vtkImageViewer",
+								      PXTkApp::tcl_interpreter,error));  
+  if (error==1)
+      {
+	is_display_ok=PXFalse;
+	imageViewer=NULL;
+#ifndef _WIN32
+	fprintf(stderr,"Bad Image Viewer %s\n",widget_name);
+#endif
+	return TCL_ERROR;
+      }
+  is_display_ok=PXTrue;
+  imageViewer=ren;
+  return TCL_OK;
+}
+
+vtkImageViewer* PXVTkTkImageViewerWidget::getImageViewer()
+{
+  return imageViewer;
+}
+
+*/
+
diff --git a/bioimagesuite30_src/GUI/pxvtkgadgets.h b/bioimagesuite30_src/GUI/pxvtkgadgets.h
new file mode 100644
index 0000000..cc073a9
--- /dev/null
+++ b/bioimagesuite30_src/GUI/pxvtkgadgets.h
@@ -0,0 +1,154 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxvtkgadgets.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkGadgets
+
+_Description : Definition of wrapper classes for the three vtkTkClasses
+
+   PXVTkTkGadget            --- abstract base class
+   PXVTkTkRenderWidget      --- wrapper around vtkTkRenderWidget
+   PXVTkTkImageWindowWidget --- wrapper around vtkTkImageWindowWidget
+   PXVTkTkImageViewerWidget --- wrapper around vtkTikImageViewerWidget
+
+
+_Call :   
+
+ PXVTkTkRenderWidget(PXTkEventObj* par,PXTkGadget* par,int moption=-1,PXBool dodisplay=PXTrue);
+ PXVTkTkImageWindowWidget(PXTkEventObj* par,PXTkGadget* par,int moption=-1,PXBool dodisplay=PXTrue);
+ PXVTkTkImageViewerWidget(PXTkEventObj* par,PXTkGadget* par,int moption=-1,PXBool dodisplay=PXTrue);
+
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+              The Visualization Toolki User's Guide, Kitware Inc (www.kitware.com)
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 6th July 2000
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtkgadgets.h"
+#include "pxtkdialog.h"
+#include "vtkRenderer.h"
+#include "vtkRenderWindow.h"
+#include "vtkImageViewer.h"
+
+/*class vtkImageWindow;
+class vtkImageWindowWidget;
+
+
+class vtkImageViewer;
+class vtkImageViewerWidget;*/
+
+#ifndef _PXVTkGadget
+#define  _PXVTkGadget
+
+/* ----  Definition of PXVTkTkGadget Class  ---- */
+
+class  PXVTkTkGadget : public PXTkGadget
+{
+protected:
+  int call_no;
+
+public:
+  PXVTkTkGadget(PXTkEventObj* evpar,PXTkGadget* gadg_par,int moption=-1);
+  
+  virtual int setWidthHeight(int w=-1,int h=-1);
+  virtual int setPadding(int bd=-1,int padx=-1,int pady=-1);
+  virtual int bindMouseEvents();
+};
+
+/* ----  Definition of PXVTkTkRenderWidget Class  ---- */
+class PXVTkTkRenderWidget : public PXVTkTkGadget
+{
+protected:
+  vtkRenderWindow* renderWindow;
+  vtkRenderer*     renderer;
+  
+public:
+  PXVTkTkRenderWidget(PXTkEventObj* evpar,PXTkGadget* gadg_par,int moption=-1);
+  
+  virtual int initDisplay();
+
+  virtual vtkRenderWindow* getRenderWindow();
+  virtual vtkRenderer*     getRenderer();
+
+  virtual void             Render();
+  virtual void             RenderDelay(int t=3);
+
+private:
+  static void handleRenderEvent(void *arg1);
+};
+
+/* ----  Definition of PXVTkTkImageWindowWidget Class  ---- */
+
+/*class PXVTkTkImageWindowWidget : public PXVTkTkGadget
+{
+protected:
+  vtkImageWindow* imageWindow;
+
+public:
+  PXVTkTkImageWindowWidget(PXTkEventObj* evpar,PXTkGadget* gadg_par,int moption=-1);
+  
+  virtual int initDisplay();
+  virtual vtkImageWindow *       getImageWindow();
+};*/
+
+/* ----  Definition of PXVTkTkImageViewerWidget Class  ---- */
+
+/*class PXVTkTkImageViewerWidget : public PXVTkTkGadget
+{
+protected:
+  vtkImageViewer* imageViewer;
+
+public:
+  PXVTkTkImageViewerWidget(PXTkEventObj* evpar,PXTkGadget* gadg_par,int moption=-1);
+  
+  virtual int initDisplay();
+  virtual vtkImageViewer*        getImageViewer();
+};*/
+
+#endif
+
diff --git a/bioimagesuite30_src/GUI/pxvtktkdialog.cpp b/bioimagesuite30_src/GUI/pxvtktkdialog.cpp
new file mode 100644
index 0000000..c202de9
--- /dev/null
+++ b/bioimagesuite30_src/GUI/pxvtktkdialog.cpp
@@ -0,0 +1,71 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "pxvtktkdialog.h"
+#include "vtkpxGUIComponent.h"
+#include "pxtkgadget.h"
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+
+   see PXVTkTkDialog.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+/* -------------------------------------------------------------------------*/
+/*                   PXVTkTkDialog                                          */
+/* -------------------------------------------------------------------------*/
+
+/* -------------------------------------------------------------------------*/
+PXVTkTkDialog::PXVTkTkDialog(vtkpxGUIComponent* comp,PXTkGadget* par,const char* title,PXBool insideparent):PXTkDialog(par,title,insideparent)
+{
+  vtkpxParent=comp;
+}
+
+
+int PXVTkTkDialog::handleEvent(int event)
+{
+  //fprintf(stderr,"In PXVTkTkDialog Event=%d\n",event);
+  return vtkpxParent->HandleEvent(event);
+}
+
+int PXVTkTkDialog::handleDirectEvent(int event)
+{
+  return PXTkDialog::handleEvent(event);
+}
+
+int PXVTkTkDialog::handleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* obj)
+{
+  return vtkpxParent->HandleMouseButtonEvent(nbutton,state,x,y,obj);
+}
+
diff --git a/bioimagesuite30_src/GUI/pxvtktkdialog.h b/bioimagesuite30_src/GUI/pxvtktkdialog.h
new file mode 100644
index 0000000..9108c45
--- /dev/null
+++ b/bioimagesuite30_src/GUI/pxvtktkdialog.h
@@ -0,0 +1,90 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// PXVTkTkDialog.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+
+_Module_Name : PXVTkTkDialog.h
+
+
+_Description : This is a specialized event handler to bridge the pxtk and vtkpxcontrib libraries
+
+_Call : 
+  PXVTkTkDialog();
+  
+_References : 
+
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 5th January 2000
+                                
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXVTkTkDialog
+#define _PXVTkTkDialog
+
+#include "pxtkdialog.h"
+class vtkpxGUIComponent;
+
+// ****************************************
+// ******* PXVTkTkDialog Class ************
+// ****************************************
+
+class PXVTkTkDialog : public PXTkDialog {
+  
+friend class vtkpxGUIComponent;
+
+protected:
+  vtkpxGUIComponent* vtkpxParent;
+
+public:
+  
+  PXVTkTkDialog(vtkpxGUIComponent* comp,PXTkGadget* par,const char* title,PXBool insideparent=PXFalse);
+  virtual int handleEvent(int eventno);
+  virtual int handleDirectEvent(int eventno);
+  virtual int handleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* obj=NULL);
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkbisGUINIFTIHeaderEditor.cpp b/bioimagesuite30_src/GUI/vtkbisGUINIFTIHeaderEditor.cpp
new file mode 100644
index 0000000..4f59e29
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkbisGUINIFTIHeaderEditor.cpp
@@ -0,0 +1,955 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkbisNIFTIHeaderEditor.cpp,v $
+  Language:  C++
+  Date:      $Date: 2005/07/31 20:39:21 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkbisGUINIFTIHeaderEditor.h"
+#include "vtkbisImageHeader.h"
+#include "vtkObjectFactory.h"
+#include "pxtkapp.h"
+#include "vtkImageData.h"
+#include "nrtk_iwidget_tabnotebook.h"
+#include "vtkbisNIFTIExtensionsList.h"
+#include "vtkbisNIFTIExtension.h"
+
+vtkbisGUINIFTIHeaderEditor* vtkbisGUINIFTIHeaderEditor::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisGUINIFTIHeaderEditor");
+  if(ret)
+    {
+      return (vtkbisGUINIFTIHeaderEditor*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisGUINIFTIHeaderEditor;
+}
+
+// Construct object with no children.
+vtkbisGUINIFTIHeaderEditor::vtkbisGUINIFTIHeaderEditor()
+{
+  this->Header=vtkbisImageHeader::New();
+  this->OriginalHeader=vtkbisImageHeader::New();
+  this->ChangingHeaderMode=0;
+  this->ChangingDetailMode=0;
+
+}
+
+vtkbisGUINIFTIHeaderEditor::~vtkbisGUINIFTIHeaderEditor()
+{
+  this->Header->Delete();
+  this->OriginalHeader->Delete();
+}
+
+// -----------------------------------------------------------------------------
+char*  vtkbisGUINIFTIHeaderEditor::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+    return this->GetWidgetName();
+  
+  vtkpxGUIComponent::Initialize(name,inside);
+  this->CreateGUI();
+  this->ResetHeader();
+  this->DisplayHeader();
+  return GetWidgetName();
+}
+
+// -----------------------------------------------------------------------------
+int  vtkbisGUINIFTIHeaderEditor::HandleEvent(int event)
+{
+  if (event<=10)
+      return this->EventManager->handleDirectEvent(event);
+
+  switch(event)
+      {
+      case 100:
+	ResetHeader();
+	DisplayHeader();
+	break;
+
+      case 101:
+	{
+	  char* line=this->EventManager->getOpenFilename("Header File name","Header Files","{*.hdr*,*.nii*}");
+	  
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		this->ReadHeader(line);
+	    }
+	}
+	break;
+	
+      case 102:
+	if (this->Header->GetMode()!=2 )
+	  {
+	    char* line=this->EventManager->getSaveFilename("Header File Name",this->Header->GetFileName(),"Header Files","*.hdr");
+	    if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		  {
+		    this->SaveHeader(line);
+		  }
+	      }
+	  }
+	else
+	  {
+	    this->EventManager->messageBox("Cannot save NIFTI .nii header independent of the image!","For your information ...");
+	  }
+	break;
+
+
+      case 103:
+	this->Header->CopyHeader(this->OriginalHeader);
+	this->DisplayHeader();
+	break;
+
+      case 104:
+	this->SetHeaderFromDialog();
+	if (this->EventParent!=NULL && this->CallbackNo>0)
+	  this->EventParent->HandleEvent(CallbackNo);
+	
+	if (this->CallbackName!=NULL)
+	  PXTkApp::executeTclCommand(this->CallbackName);
+	this->DisplayHeader();
+	break;
+
+	
+      case 110:
+      case 111:
+      case 112:
+	this->SetHeaderMode(event-110);
+	break;
+
+      case 120:
+	this->SetDetailMode(-1,1);
+	break;
+      }
+	  
+  
+  return TCL_OK;
+}
+// -----------------------------------------------------------------------------
+int vtkbisGUINIFTIHeaderEditor::ReadHeader(char* name)
+{
+  vtkbisImageHeader* header=vtkbisImageHeader::New();
+  int ok=header->ReadHeader(name);
+
+  if (ok)
+    {
+      this->SetHeader(header);
+    }
+  else
+    {
+      this->EventManager->messageBox("Failed to Load Header!","Error Message ...");
+    }
+
+  header->Delete();
+  return TCL_OK;
+}
+
+int vtkbisGUINIFTIHeaderEditor::SaveHeader(char* name)
+{
+  strcpy(pxtk_buffer,name);
+  this->SetHeaderFromDialog();
+  
+  //  fprintf(stderr,"Mode = %d , Filename = %s\n",this->Header->GetMode(),pxtk_buffer);
+
+  int ok=this->Header->WriteHeader(pxtk_buffer);
+  if (!ok)
+    {
+      this->EventManager->messageBox("Unfortunately, failed to save header!","Error Message ...");
+    }
+  else
+    {
+      this->DisplayHeader();
+    }
+
+
+  return TCL_OK;
+}
+
+
+int vtkbisGUINIFTIHeaderEditor::ResetHeader()
+{
+  this->Header->ResetFields();
+  this->Header->SetModeToNIFTI_HDRIMG();
+  this->Header->SetIsHeaderValid(1);
+  this->DisplayHeader();
+  return TCL_OK;
+}
+
+int vtkbisGUINIFTIHeaderEditor::SetHeader(vtkbisImageHeader* hdr)
+{
+  if (hdr==NULL)
+    return 0;
+
+  this->OriginalHeader->CopyHeader(hdr);
+  this->Header->CopyHeader(hdr);
+  this->DisplayHeader();
+  return 1;
+}
+// -------------------------------------------------------------------------------------------
+//
+//  The heart of the functionality is below .....
+//
+// -------------------------------------------------------------------------------------------
+int vtkbisGUINIFTIHeaderEditor::CreateGUI()
+{
+  PXTkFrame* mainFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+  mainFrame->configure("-bg","black");
+
+  PXTkFrame* menubar=new PXTkFrame(this->EventManager,mainFrame);
+  mainFrame->addChildren("-side top -expand false -fill x",menubar);
+
+  PXTkLabel* lab=new PXTkLabel(this->EventManager,menubar,"");
+  lab->configure("-image","$::pxtclvtkpxcontrib::smalllogo ");
+  menubar->addChildren("-side right -expand false  -padx 5 -pady 5",lab);
+
+  PXTkMenuButton* but1=new PXTkMenuButton(this->EventManager,menubar,"File",-1,PXTrue);
+  PXTkMenuButton* but2=new PXTkMenuButton(this->EventManager,menubar,"Edit",-1,PXTrue);
+  PXTkMenuButton* but3=new PXTkMenuButton(this->EventManager,menubar,"View",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but1,but2,but3);
+  
+  PXTkMenu *menu1=new PXTkMenu(this->EventManager,but1,PXFalse);
+  menu1->addButton("New Header",100);
+  menu1->addSeparator();
+  menu1->addButton("Load",101);
+  menu1->addButton("Save As",102);
+  menu1->addSeparator();
+  menu1->addButton("Close",3);
+  
+  editMenu=new PXTkMenu(this->EventManager,but2,PXFalse);
+  editMenu->addRadioButton("Analyze 7,5",0,0,PXTrue,110);
+  editMenu->addRadioButton("NIFTI-1 (.hdr)",0,1,PXFalse,111);
+  editMenu->addRadioButton("NIFTI-1 (.nii)",0,2,PXFalse,112);
+
+  detailMenu=new PXTkMenu(this->EventManager,but3,PXFalse);
+  detailMenu->addRadioButton("Short Header",0,0,PXFalse,120);
+  detailMenu->addRadioButton("Long Header",0,1,PXTrue,120);
+  detailMenu->addRadioButton("Complete Header",0,2,PXFalse,120);
+  detailMenu->addRadioButton("Extensions Only",0,3,PXFalse,120);
+  
+  int width=600;
+  int height=300;
+
+  this->notebook = new NRTkIWTabNotebook(this->EventManager, mainFrame, "n",width,height);
+  PXTkFrame* dim_frame=this->notebook->addPage("Dimensions");
+  PXTkFrame* or_frame=this->notebook->addPage("Orientation");
+  PXTkFrame* mis_frame=this->notebook->addPage("Misc");
+  PXTkFrame* det_frame=this->notebook->addPage("Detail_View");
+
+  PXTkFrame* bot_frame=new PXTkFrame(this->EventManager,mainFrame);
+  mainFrame->addChildren("-side bottom -expand true -fill x",bot_frame);
+  mainFrame->addChildren("-side top -expand true -fill both",this->notebook->getMainWindow());
+
+  PXTkButton* b0=new PXTkButton(this->EventManager,bot_frame,"Apply Changes to Viewer",104); 
+  PXTkButton* b1=new PXTkButton(this->EventManager,bot_frame,"Revert to Original",103); 
+  bot_frame->addChildren("-side left -expand true -fill x -padx 5",b0,b1);
+  
+
+
+  // Step 1 Dimensions Frame
+  // -----------------------
+  PXTkLabelFrame* dimensionframe=new PXTkLabelFrame(this->EventManager,dim_frame,"Image Dimensions (voxels)");
+  PXTkLabelFrame* voxelframe=new PXTkLabelFrame(this->EventManager,dim_frame,"Voxel Dimensions (mm or s)");
+  PXTkLabelFrame* miscframe=new PXTkLabelFrame(this->EventManager,dim_frame,"Image Type");
+
+  dim_frame->addChildren("-side top -fill both -expand t",dimensionframe,voxelframe,miscframe);
+  
+  for (int i=0;i<=3;i++)
+    {
+      dim_label[i]=new PXTkLabel(this->EventManager,dimensionframe,"X-Size");
+      dim_label[i]->configure("-width",5);
+      dim_entry[i]=new PXTkEntry(this->EventManager,dimensionframe);
+      dim_entry[i]->configure("-width",8);
+      dim_entry[i]->configure("-relief","sunken");
+      switch(i) 
+	{
+	case 0:
+	  dim_label[i]->setText("x:");
+	  break;
+	case 1:
+	  dim_label[i]->setText("y:");
+	  break;
+	case 2:
+	  dim_label[i]->setText("z:");
+	  break;
+	case 3:
+	  dim_label[i]->setText("t:");
+	  break;
+	}
+      dimensionframe->addChildren("-side left -padx 2 -fill x -expand t",dim_label[i],dim_entry[i]);
+    }
+  
+  // Then Voxel Frame 
+  for (int i=4;i<=7;i++)
+    {
+      dim_label[i]=new PXTkLabel(this->EventManager,voxelframe,"X-Size");
+      dim_label[i]->configure("-width",5);
+      dim_entry[i]=new PXTkEntry(this->EventManager,voxelframe);
+      dim_entry[i]->configure("-width",5);
+      dim_entry[i]->configure("-relief","sunken");
+      switch(i) 
+	{
+	case 4:
+	  dim_label[i]->setText("x:");
+	  break;
+	case 5:
+	  dim_label[i]->setText("y:");
+	  break;
+	case 6:
+	  dim_label[i]->setText("z:");
+	  break;
+	case 7:
+	  dim_label[i]->setText("t:");
+	  break;
+	}
+      voxelframe->addChildren("-side left -padx 2 -fill x -expand t",dim_label[i],dim_entry[i]);
+    }
+
+
+  PXTkLabel* lab1=new PXTkLabel(this->EventManager,miscframe,"Data Type:");
+  datatypeMenu=new PXTkOptionMenu(this->EventManager,miscframe,"Unsigned Char",-1);
+  datatypeMenu->addOption("Char",-1);
+  datatypeMenu->addOption("Unsigned Short",-1);
+  datatypeMenu->addOption("Short",-1);
+  datatypeMenu->addOption("Usigned Int",-1);
+  datatypeMenu->addOption("Int",-1);
+  datatypeMenu->addOption("Float",-1);
+  datatypeMenu->addOption("Double",-1);
+  datatypeMenu->setIndex(3);
+
+  dim_label[8]=new PXTkLabel(this->EventManager,miscframe,"Bits/pixel:");
+  dim_label[8]->configure("-width",5);
+  dim_entry[8]=new PXTkEntry(this->EventManager,miscframe);
+  dim_entry[8]->configure("-width",5);
+  dim_entry[8]->configure("-relief","sunken");
+  dim_entry[8]->enable(PXFalse);
+  miscframe->addChildren("-side left -fill x -expand t",lab1,datatypeMenu,dim_label[8],dim_entry[8]);
+
+  // Step 2 Misc_frame
+  //PXTkFrame* mis_frame=this->notebook->addPage("Misc");
+  PXTkLabelFrame* mis_frame1=new PXTkLabelFrame(this->EventManager,mis_frame,"Scaling");
+  //  PXTkLabelFrame* mis_frame2=new PXTkLabelFrame(this->EventManager,mis_frame,"Offsets/Units (mm or s)");
+  PXTkLabelFrame* mis_frame3=new PXTkLabelFrame(this->EventManager,mis_frame,"Text Labels");
+  //  PXTkLabelFrame* mis_frame4=new PXTkLabelFrame(this->EventManager,mis_frame,"Intents");
+  mis_frame->addChildren("-side top -pady 2 -fill x -expand t",mis_frame1,mis_frame3);//,mis_frame2,mis_frame4);
+
+  PXTkFrame* m_frame1=new PXTkFrame(this->EventManager,mis_frame1);
+  PXTkFrame* m_frame2=new PXTkFrame(this->EventManager,mis_frame1);
+  mis_frame1->addChildren("-side top -pady 2 -fill x -expand t",m_frame1,m_frame2);
+  
+  misc_sclabel[0]=new PXTkLabel(this->EventManager,m_frame1,"Int_scale (scl_slope)");
+  misc_sclabel[1]=new PXTkLabel(this->EventManager,m_frame1,"Int_shift (scl_offset)");
+  for (int i=0;i<=1;i++)
+    {
+      misc_scentry[i]=new PXTkEntry(this->EventManager,m_frame1);
+      misc_scentry[i]->configure("-relief","sunken");
+    }
+  m_frame1->addChildren("-side left -padx 2 -fill x -expand true",
+			misc_sclabel[0],misc_scentry[0],
+			misc_sclabel[1],misc_scentry[1]);
+  
+
+  for (int i=2;i<=5;i++)
+    {
+      misc_sclabel[i]=new PXTkLabel(this->EventManager,m_frame2,"T");
+      misc_scentry[i]=new PXTkEntry(this->EventManager,m_frame2);
+      misc_scentry[i]->configure("-relief","sunken");
+      misc_scentry[i]->configure("-width",4);
+      
+      switch(i) 
+	{
+	case 2:
+	  misc_sclabel[i]->setText("cal_min:");
+	  break;
+	case 3:
+	  misc_sclabel[i]->setText("cal_max");
+	  break;
+	case 4:
+	  misc_sclabel[i]->setText("gl_min:");
+	  break;
+	case 5:
+	  misc_sclabel[i]->setText("gl_max");
+	  break;
+	}
+      m_frame2->addChildren("-side left -padx 0 -fill x -expand t",misc_sclabel[i],misc_scentry[i]);
+    }
+  
+
+  for (int i=0;i<=2;i++)
+    {
+      misc_txlabel[i]=new PXTkLabel(this->EventManager,mis_frame3,"T");
+      misc_txentry[i]=new PXTkEntry(this->EventManager,mis_frame3);
+      misc_txentry[i]->configure("-relief","sunken");
+      switch(i) 
+	{
+	case 0:
+	  misc_txlabel[i]->setText("DB_Name:");
+	  misc_txentry[i]->configure("-width",14);
+	  break;
+	case 1:
+	  misc_txlabel[i]->setText("Extent (VOI Value):");
+	  misc_txentry[i]->configure("-width",3);
+	  break;
+	case 2:
+	  misc_txlabel[i]->setText("Intent_Name:");
+	  misc_txentry[i]->configure("-width",10);
+	  break;
+	  
+	}
+      mis_frame3->addChildren("-side left -padx 0 -fill x -expand t",misc_txlabel[i],misc_txentry[i]);
+    }
+  
+  // Step 2.5 -- Orientation Frame
+  // -----------------------------
+  //  PXTkFrame* or_frame=this->notebook->addPage("Orientation");
+  PXTkFrame* or_frame1=new PXTkFrame(this->EventManager,or_frame);
+  PXTkLabelFrame* or_frame2=new PXTkLabelFrame(this->EventManager,or_frame,"Quaternion (qform_code)");
+  PXTkLabelFrame* or_frame3=new PXTkLabelFrame(this->EventManager,or_frame,"Affine Transform (sform_code)");
+  or_frame->addChildren("-side top -pady 0 -fill x -expand t",or_frame1,or_frame2,or_frame3);  
+
+  PXTkLabel* orlabel=new PXTkLabel(this->EventManager,or_frame1,"Orientation:");
+  this->orientationMenu=new PXTkOptionMenu(this->EventManager,or_frame1,"Axial",-1);
+  this->orientationMenu->addOption("Coronal",-1);
+  this->orientationMenu->addOption("Sagittal",-1);
+  this->orientationMenu->addOption("Polar/Other",-1);
+
+  orientationDescription=new PXTkLabel(this->EventManager,or_frame1," ");
+  orientationDescription->configure("-width",10);
+  or_frame1->addChildren("-side left -padx 2 -fill x -expand t",orlabel,this->orientationMenu,
+			 this->orientationDescription);
+
+  PXTkFrame* q_frame1=new PXTkFrame(this->EventManager,or_frame2);   
+  PXTkFrame* q_frame2=new PXTkFrame(this->EventManager,or_frame2);   
+  or_frame2->addChildren("-side top -pady 2 -fill both -expand true",q_frame1,q_frame2);
+
+  PXTkLabel* q_label=new PXTkLabel(this->EventManager,q_frame1,"Qform_code : ");
+  this->qformMenu=new PXTkOptionMenu(this->EventManager,q_frame1,"Unknown/Not used",-1);
+  this->qformMenu->addOption("Scanner Anatomical");
+  this->qformMenu->addOption("Aligned Anatomical");
+  this->qformMenu->addOption("Talairach");
+  this->qformMenu->addOption("MNI 152");
+  this->qformDescription=new PXTkLabel(this->EventManager,q_frame2," ");
+  this->qformDescription->configure("-width",20);
+
+  q_frame1->addChildren("-side left -padx 2 -fill x -expand t",q_label, this->qformMenu);
+  q_frame2->addChildren("-side left -padx 2 -fill x -expand t",this->qformDescription);
+
+  PXTkFrame* s_frame1=new PXTkFrame(this->EventManager,or_frame3);   
+  PXTkFrame* s_frame2=new PXTkFrame(this->EventManager,or_frame3);   
+  or_frame3->addChildren("-side top -pady 2 -fill x -expand f",s_frame1);
+  or_frame3->addChildren("-side top -pady 2 -fill both -expand true",s_frame2);
+  
+  PXTkLabel* s_label=new PXTkLabel(this->EventManager,s_frame1,"Sform_code : ");
+  this->sformMenu=new PXTkOptionMenu(this->EventManager,s_frame1,"Unknown/Not used",-1);
+  this->sformMenu->addOption("Scanner Anatomical");
+  this->sformMenu->addOption("Aligned Anatomical");
+  this->sformMenu->addOption("Talairach");
+  this->sformMenu->addOption("MNI 152");
+  s_frame1->addChildren("-side left -padx 2 -fill x -expand t",s_label, this->sformMenu);
+  
+   
+  PXTkLabel* s_label2=new PXTkLabel(this->EventManager,s_frame2,"Matrix : ");
+  this->sformMatrix=new PXTkText(this->EventManager,s_frame2);
+  this->sformMatrix->configure("-width",60);
+  this->sformMatrix->configure("-height",3);
+  this->sformMatrix->configure("-wrap","none");
+  this->sformMatrix->configure("-relief","ridge");
+  this->sformMatrix->setEditableState(PXFalse);
+  s_frame2->addChildren("-side left -expand fals",s_label2);
+  s_frame2->addChildren("-side left -expand true -fill both",this->sformMatrix);
+
+
+  // Step 3 Extensions Frame
+  // ------------------------
+  //PXTkFrame* det_frame=this->notebook->addPage("Detail");
+  det_frame->configure("-bg","red");
+  PXTkScrollbar* xbar=new PXTkScrollbar(this->EventManager,det_frame,PXFalse);
+  det_frame->addChildren("-side bottom -expand false -fill x",xbar);
+
+  PXTkFrame* top_frame=new PXTkFrame(this->EventManager,det_frame);
+  det_frame->addChildren("-side top -expand true -fill both",top_frame);
+
+  PXTkScrollbar* ybar=new PXTkScrollbar(this->EventManager,top_frame,PXTrue);
+  
+  this->textBox=new PXTkText(this->EventManager,top_frame);
+  ybar->attachGadget(this->textBox);
+  xbar->attachGadget(this->textBox);
+
+  this->textBox->configure("-width",80);
+  this->textBox->configure("-height",15);
+  this->textBox->configure("-wrap","none");
+  this->textBox->configure("-relief","ridge");
+  this->textBox->setEditableState(PXFalse);
+  top_frame->addChildren("-side right -expand false -fill y",ybar);
+  top_frame->addChildren("-side left -expand true -fill both",this->textBox);
+
+  // Done
+  this->notebook->viewPage("Dimensions");
+  this->Initialized=1;
+  return 1;
+}
+
+// -------------------------------------------------------------------------------------------
+int vtkbisGUINIFTIHeaderEditor::SetDetailMode(int dt,int switchto)
+{
+  if (this->Initialized==0)
+    return 0;
+
+  if (this->ChangingDetailMode==1)
+    {
+      //      fprintf(stderr,"Already changing detail_mode\n");
+      return 0;
+    }
+
+  this->ChangingDetailMode=1;
+
+  if (dt<0 || dt > 3 )
+    dt=this->detailMenu->getMenuWidgetVariable(0);
+
+  this->textBox->setEditableState(PXTrue);
+  this->textBox->clearText();
+
+  nifti_1_header *hdr=this->Header->GetRawHeader();
+  char line[1000];
+  int long_mode=dt;
+  
+  if (dt != 3 )
+    {
+      this->textBox->addText("File Name = ");
+      this->textBox->addText(this->Header->GetFileName());
+
+
+      this->textBox->addText("\n\nOrientation =");
+
+      int oldstyle=vtkbisImageHeader::MapOrientationToOldStyle(this->Header->GetOrientation());
+
+
+      switch (oldstyle)
+	{
+	case 0: this->textBox->addText(" Axial "); break;
+	case 1: this->textBox->addText(" Coronal "); break;
+	case 2: this->textBox->addText(" Sagittal "); break;
+	case 3: this->textBox->addText(" Polar "); break;
+	}
+      
+      mat44 original=vtkbisImageHeader::NIFTI_CreateOrientationMatrix(hdr);
+      int icod,jcod,kcod;  nifti_mat44_to_orientation(original,&icod,&jcod,&kcod);
+      if (long_mode)
+	{
+	  sprintf(line,"(%s,%s,%s)", nifti_orientation_string(icod),
+		  nifti_orientation_string(jcod),
+		  nifti_orientation_string(kcod));
+	  this->textBox->addText(line);
+	}
+      else
+	{
+	  sprintf(line,"(%s,%s,%s)", vtkbisImageHeader::NIFTI_GetOrientationString(icod),
+		  vtkbisImageHeader::NIFTI_GetOrientationString(jcod),
+		  vtkbisImageHeader::NIFTI_GetOrientationString(kcod));
+	  this->textBox->addText(line);
+	  
+	}
+      
+      
+      if (long_mode)
+	{
+	  this->textBox->addText("\n\nMode = ");
+	  switch (this->Header->GetMode())
+	    {
+	    case 0: this->textBox->addText(" Analyze 7.5"); break;
+	    case 1: this->textBox->addText(" NIFTI (.hdr/.img)"); break;
+	    case 2: this->textBox->addText(" NIFTI (.nii)"); break;
+	    }
+	  sprintf(line,"(magic=%s) (Valid = %d SwapBytes=%d)\n",hdr->magic,this->GetHeader()->GetIsHeaderValid(),this->Header->GetSwapBytes());
+	  this->textBox->addText(line);
+	  this->textBox->addText("\nDimensions =");
+	}
+      
+      sprintf(line," %dx%dx%d, %d ",hdr->dim[1],hdr->dim[2],hdr->dim[3],hdr->dim[4]);
+      this->textBox->addText(line);
+      if (long_mode)
+	{
+	  sprintf(line,"\n\nVoxel Dimensions = %.3fx%.3fx%.3f, %.2f \n",hdr->pixdim[1],hdr->pixdim[2],hdr->pixdim[3],hdr->pixdim[4]);
+	  this->textBox->addText(line);
+	  sprintf(line,"\nData Type = %s(%d) (Bits per Pixel=%d) Vox_Offset=%d Num Extensions=%d (Size =%d)\n",nifti_datatype_string(hdr->datatype),hdr->datatype,hdr->bitpix,
+		  (int)hdr->vox_offset,this->Header->GetExtensions()->GetNumberOfExtensions(),this->Header->GetExtensions()->GetTotalByteSize());
+	  this->textBox->addText(line);
+	  
+	  sprintf(line,"\nScale= %.3f Shift=%.3f \n",hdr->scl_slope,hdr->scl_inter);
+	  this->textBox->addText(line);
+	  sprintf(line,"\nOrientation Matrix Stuff (qform_code=%d sform_code=%d)\n",hdr->qform_code,hdr->sform_code);
+	  this->textBox->addText(line);
+	  if (hdr->qform_code>0)
+	    {
+	      sprintf(line,"\nQuatenion (qfac=%f) quat=(%.3f,%.3f,%.3f) offset=(%.3f,%.3f,%.3f)\n",
+		      hdr->pixdim[0],
+		      hdr->quatern_b,hdr->quatern_c,hdr->quatern_d,
+		      hdr->qoffset_x,hdr->qoffset_y,hdr->qoffset_z);
+	      this->textBox->addText(line);
+	    }
+	  
+	  if (hdr->sform_code>0)
+	    {
+	      sprintf(line,"\nMatrix_x = \t( %+8.3f %+8.3f %+8.3f %+8.3f )\n",
+		      hdr->srow_x[0],hdr->srow_x[1],hdr->srow_x[2],hdr->srow_x[3]);
+	      this->textBox->addText(line);
+	      sprintf(line,"\t       y = \t( %+8.3f %+8.3f %+8.3f %+8.3f )\n",
+		      hdr->srow_y[0],hdr->srow_y[1],hdr->srow_y[2],hdr->srow_y[3]);
+	      this->textBox->addText(line);
+	      sprintf(line,"\t       z = \t( %+8.3f %+8.3f %+8.3f %+8.3f)\n",
+		      hdr->srow_z[0],hdr->srow_z[1],hdr->srow_z[2],hdr->srow_z[3]);
+	      this->textBox->addText(line);
+	    }
+	  
+	  if (this->Header->GetMode()==0)
+	    {
+	      double ori[3]; this->Header->GetOrigin(ori);
+	      sprintf(line,"\n(Analyze Origin) = (%.1f,%1.f,%.1f)\n",ori[0],ori[1],ori[2]);
+	      this->textBox->addText(line);
+	    }
+	}
+      else
+	{
+	  sprintf(line," (%.3fx%.3fx%.3f, %.2f)\n",hdr->pixdim[1],hdr->pixdim[2],hdr->pixdim[3],hdr->pixdim[4]);
+	  this->textBox->addText(line);
+	  sprintf(line,"\nData Type = %s (Bits=%d) NumExt=%d (Sz =%d)",nifti_datatype_string(hdr->datatype),hdr->bitpix,
+		  this->Header->GetExtensions()->GetNumberOfExtensions(),this->Header->GetExtensions()->GetTotalByteSize());
+	  this->textBox->addText(line);
+	}
+      
+      
+      if (long_mode>0)
+	{
+	  sprintf(line,"\nDBName : %s , VOIValue= %d\n",this->Header->GetDBName(),this->Header->GetVOIValue());
+	  this->textBox->addText(line);
+	  
+	}
+    }
+
+  if (long_mode>1)
+    {
+      int next=this->Header->GetExtensions()->GetNumberOfExtensions(); 
+      sprintf(line,"\n\n\t Extensions = %d , size=%d\n",
+	      next,this->Header->GetExtensions()->GetTotalByteSize());
+      this->textBox->addText(line);
+      for (int i=0;i<next;i++)
+	{
+	  vtkbisNIFTIExtension* extn=this->Header->GetExtensions()->GetRawExtension(i);
+	  sprintf(line,"*********** Extensions %d (code=%d size=%d)\n",
+		  i+1,extn->GetECode(),extn->GetESize());
+	  this->textBox->addText(line);
+	  this->textBox->addText(extn->GetText());
+	  this->textBox->addText("\n");
+	}
+    }
+  
+
+  if (switchto)
+    this->notebook->viewPage("Detail_View");
+  PXTkApp::executeTclCommand("update idletasks");
+  this->ChangingDetailMode=0;
+  this->textBox->setEditableState(PXFalse);
+  return 1;
+  //  fprintf(stderr,"Done changing detail_mode\n");
+}
+
+int vtkbisGUINIFTIHeaderEditor::SetHeaderMode(int md)
+{
+  if (this->ChangingHeaderMode==1)
+    return 0;
+
+  this->ChangingHeaderMode=1;
+
+  if (md<0) md=0;
+  if (md>2) md=2;
+
+  int mode=this->Header->GetMode();
+  if (mode==md)
+    return 1;
+
+  int ok=0;
+
+  if (md!=mode)
+    {
+      if (md==0 && mode==1)
+	ok=this->EventManager->questionBox("Changing the header mode from NIFTI to Analyze may result in loss of information. Are you sure?");
+      else if (md==1 && mode==0)
+	{
+	  this->EventManager->messageBox("Changing Header from .hdr (analyze) to .hdr (NIFTI)");
+	  ok=1;
+	}
+      else if (md==2)
+	this->EventManager->messageBox("Cannot change a header from .hdr to .nii");
+      else if (mode==2)
+	this->EventManager->messageBox("Cannot change a header from .nii to .hdr");
+    }
+
+  if (ok!=0)
+    mode=md;
+
+  if (this->Initialized)
+    this->editMenu->setMenuWidgetVariable(0,mode);
+
+  if (ok==0)
+    return 0;
+
+  //  fprintf(stderr,"Setting Mode to %d\n",mode);
+
+  if (mode==0)
+    this->Header->SetModeToAnalyze();
+  else if (mode==1)
+    this->Header->SetModeToNIFTI_HDRIMG();
+  else if (mode==2)
+    fprintf(stderr,"Error, we should never get here!\n");
+
+  this->ChangingHeaderMode=0;  
+  return 1;
+}
+// -------------------------------------------------------------------------------------------
+int vtkbisGUINIFTIHeaderEditor::DisplayHeader()
+{
+  if (this->Initialized==0)
+    return 0;
+
+  int md=this->Header->GetMode();
+  if (md<0) md=0;
+  if (md>2) md=2;
+
+
+  strcpy(pxtk_buffer,this->Header->GetFileName());
+  switch (md)
+    {
+    case 0:
+      sprintf(pxtk_buffer2,"Header Editor: %s (ANA) ",PXTkApp::getFilenameTail(pxtk_buffer));
+      break;
+    case 1:
+      sprintf(pxtk_buffer2,"Header Editor: %s (NIFTI .hdr) ",PXTkApp::getFilenameTail(pxtk_buffer));
+      break;
+    case 2:
+      sprintf(pxtk_buffer2,"Header Editor: %s (NIFTI .nii) ",PXTkApp::getFilenameTail(pxtk_buffer));
+      break;
+    }
+
+  this->EventManager->setTitle(pxtk_buffer2);
+
+  
+  // ----------------------------------------------------------------------
+  // First Dimensions Part
+  // ----------------------------------------------------------------------
+
+  for (int i=0;i<9;i++)
+    {
+      switch(i)
+	{
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	  sprintf(pxtk_buffer,"%d",this->Header->GetRawHeader()->dim[i+1]);
+	  break;
+	  break;
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	  sprintf(pxtk_buffer,"%7.5f",this->Header->GetRawHeader()->pixdim[i-3]);
+	  break;
+	case 8:
+	  sprintf(pxtk_buffer,"%d",this->Header->GetRawHeader()->bitpix);
+	  break;
+	}
+      dim_entry[i]->setText(pxtk_buffer);
+    }
+  int ind=this->Header->GetIndexedDataType();
+  //  fprintf(stderr,"Index=%d\n",ind);
+  datatypeMenu->setIndex(ind,PXFalse);
+
+  // ----------------------------------------------------------------------------
+  // Misc
+  // ----------------------------------------------------------------------------
+  sprintf(pxtk_buffer,"%f",this->Header->GetRawHeader()->scl_slope);
+  misc_scentry[0]->setText(pxtk_buffer);
+
+  sprintf(pxtk_buffer,"%f",this->Header->GetRawHeader()->scl_inter);
+  misc_scentry[1]->setText(pxtk_buffer);
+  
+  sprintf(pxtk_buffer,"%f",this->Header->GetRawHeader()->cal_min);
+  misc_scentry[2]->setText(pxtk_buffer);
+  
+  sprintf(pxtk_buffer,"%f",this->Header->GetRawHeader()->cal_max);
+  misc_scentry[3]->setText(pxtk_buffer);
+  
+  sprintf(pxtk_buffer,"%d",this->Header->GetRawHeader()->glmin);
+  misc_scentry[4]->setText(pxtk_buffer);
+  
+  sprintf(pxtk_buffer,"%d",this->Header->GetRawHeader()->glmax);
+  misc_scentry[5]->setText(pxtk_buffer);
+
+  misc_txentry[0]->setText(this->Header->GetRawHeader()->db_name);
+  sprintf(pxtk_buffer,"%d",this->Header->GetRawHeader()->extents);
+  misc_txentry[1]->setText(pxtk_buffer);
+  misc_txentry[2]->setText(this->Header->GetRawHeader()->intent_name);
+  // ----------------------------------------------------------------------------
+  // Orientation
+  // ----------------------------------------------------------------------------
+  int oldstyle=vtkbisImageHeader::MapOrientationToOldStyle(this->Header->GetOrientation());
+  this->orientationMenu->setIndex(oldstyle,PXFalse);
+  mat44 original=vtkbisImageHeader::NIFTI_CreateOrientationMatrix(this->Header->GetRawHeader());
+  int icod,jcod,kcod;  nifti_mat44_to_orientation(original,&icod,&jcod,&kcod);
+  sprintf(pxtk_buffer,"(%s,%s,%s)", vtkbisImageHeader::NIFTI_GetOrientationString(icod),
+	  vtkbisImageHeader::NIFTI_GetOrientationString(jcod),
+	  vtkbisImageHeader::NIFTI_GetOrientationString(kcod));
+  this->orientationDescription->setText(pxtk_buffer);
+
+
+  nifti_1_header *hdr=this->Header->GetRawHeader();
+  int qf=hdr->qform_code; if (qf<0 || qf>4) qf=0;
+  this->qformMenu->setIndex(qf,PXFalse);
+  int sf=hdr->sform_code; if (sf<0 || sf>4) sf=0;
+  this->sformMenu->setIndex(sf,PXFalse);
+
+  
+  sprintf(pxtk_buffer,"Quatenion (qfac=%f) quat=(%.3f,%.3f,%.3f) offset=(%.3f,%.3f,%.3f)\n",
+		      hdr->pixdim[0],
+		      hdr->quatern_b,hdr->quatern_c,hdr->quatern_d,
+		      hdr->qoffset_x,hdr->qoffset_y,hdr->qoffset_z);
+  this->qformDescription->setText(pxtk_buffer);
+
+  this->sformMatrix->clearText();
+  this->sformMatrix->setEditableState(PXTrue);
+  sprintf(pxtk_buffer,"x= \t( %+8.3f %+8.3f %+8.3f %+8.3f )\n",
+	  hdr->srow_x[0],hdr->srow_x[1],hdr->srow_x[2],hdr->srow_x[3]);
+  this->sformMatrix->addText(pxtk_buffer);
+  sprintf(pxtk_buffer,"y = \t( %+8.3f %+8.3f %+8.3f %+8.3f )\n",
+	  hdr->srow_y[0],hdr->srow_y[1],hdr->srow_y[2],hdr->srow_y[3]);
+  this->sformMatrix->addText(pxtk_buffer);
+  sprintf(pxtk_buffer,"z = \t( %+8.3f %+8.3f %+8.3f %+8.3f)",
+	  hdr->srow_z[0],hdr->srow_z[1],hdr->srow_z[2],hdr->srow_z[3]);
+  this->sformMatrix->addText(pxtk_buffer);
+  this->sformMatrix->setEditableState(PXFalse);
+
+    
+  // Detail View
+  // ----------------------------------------------------------------------------
+  this->SetDetailMode(-1,0);
+  // Last thing, fix the menu
+  this->editMenu->setMenuWidgetVariable(0,md);
+  return TCL_OK;
+}
+// -----------------------------------------------------------------------------
+int vtkbisGUINIFTIHeaderEditor::SetHeaderFromDialog()
+{
+  
+  if (this->Initialized==0)
+    return 0;
+
+  //  fprintf(stderr,"Setting Header from Dialog \n");
+
+  nifti_1_header *hdr=this->Header->GetRawHeader();
+  for (int i=1;i<=4;i++)
+    hdr->dim[i]=Irange(atoi(dim_entry[i-1]->getText()),1,2048);
+  this->Header->SetIndexedDataType(datatypeMenu->getIndex());
+
+  // ----------------------------------------------------------------------------
+  // Misc
+  // ----------------------------------------------------------------------------
+  hdr->scl_slope=atof(misc_scentry[0]->getText());
+  hdr->scl_inter=atof(misc_scentry[1]->getText());
+  hdr->cal_min=  atof(misc_scentry[2]->getText());
+  hdr->cal_max=  atof(misc_scentry[3]->getText());
+  hdr->glmin=  atoi(misc_scentry[4]->getText());
+  hdr->glmax=  atoi(misc_scentry[5]->getText());
+
+  strncpy(hdr->db_name,misc_txentry[0]->getText(),17);
+  hdr->extents=atoi(misc_txentry[1]->getText());
+  strncpy(hdr->intent_name,misc_txentry[2]->getText(),15);
+
+  // ----------------------------------------------------------------------------
+  // Orientation
+  // ----------------------------------------------------------------------------
+  this->Header->SetOrientation(this->orientationMenu->getIndex());
+  
+  int qf=this->qformMenu->getIndex();
+  if (hdr->qform_code>0 && qf>0)
+    hdr->qform_code=qf;
+
+  int sf=this->sformMenu->getIndex();
+  if (hdr->sform_code>0 && sf>0)
+    hdr->sform_code=sf;
+
+  double oldpixdim[3],newpixdim[3];
+  for (int i=1;i<=3;i++)
+    {
+      oldpixdim[i-1]=Frange(fabs(hdr->pixdim[i]),0.00001,1000.0);
+      newpixdim[i-1]=Frange(fabs(atof(dim_entry[i+3]->getText())),0.00001,1000.0);
+    }
+  hdr->pixdim[4]=atof(dim_entry[7]->getText());
+  mat44 mapping; vtkbisImageHeader::NIFTI_identity_mat44(&mapping);
+  for (int ia=0;ia<=2;ia++)
+    mapping.m[ia][ia]=Frange(newpixdim[ia]/oldpixdim[ia],0.001,1000.0);
+
+  /*  if (hdr->qform_code==0)
+    {
+      for (int i=0;i<=2;i++)
+	hdr->pixdim[i+1]=mapping.m[i][i]*oldpixdim[i];
+	}*/
+  
+  //  vtkbisImageHeader::NIFTI_print_mat44("mapping",mapping);
+  this->Header->ApplyMapping(mapping);
+
+  //  fprintf(stderr,"Setting Header from Dialog Done\n");
+  return TCL_OK;
+}
+// -----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/GUI/vtkbisGUINIFTIHeaderEditor.h b/bioimagesuite30_src/GUI/vtkbisGUINIFTIHeaderEditor.h
new file mode 100644
index 0000000..d915f53
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkbisGUINIFTIHeaderEditor.h
@@ -0,0 +1,150 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIAnalyzeHeaderEditor.h,v $
+  Language:  C++
+  Date:      $Date: 2002/06/07 20:34:50 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkbisGUINIFTIHeaderEditor - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkbisGUINIFTIHeaderEditor_h
+#define __vtkbisGUINIFTIHeaderEditor_h
+
+#include "vtkpxGUIComponent.h"
+
+#include "pxtkapp.h"
+#include "pxtkdialog.h"
+#include "pxtkgadgets.h"
+#include "pxtkcomplexwidgets.h"
+#include "pxtkmenu.h"
+#include "pxtkradiobutton.h"
+#include "vtkbisImageHeader.h"
+
+//BTX
+class NRTkIWTabNotebook;
+//ETX
+
+class vtkbisGUINIFTIHeaderEditor : public vtkpxGUIComponent
+{
+public:
+  static vtkbisGUINIFTIHeaderEditor *New();
+  vtkTypeMacro(vtkbisGUINIFTIHeaderEditor,vtkpxGUIComponent);
+  
+  virtual char* Initialize(const char* name,int inside);
+  virtual int   HandleEvent(int );
+  
+  virtual int   ReadHeader(char* name);
+  virtual int   SaveHeader(char* name);
+  virtual int   ResetHeader();
+
+
+  virtual int SetHeader(vtkbisImageHeader *header);
+  vtkGetObjectMacro(Header,vtkbisImageHeader);
+
+protected:
+
+  vtkbisGUINIFTIHeaderEditor();
+  virtual  ~vtkbisGUINIFTIHeaderEditor();
+
+  vtkbisImageHeader* Header;
+  vtkbisImageHeader* OriginalHeader;
+
+  // Parameter Stuff etc.
+  PXTkLabel* dim_label[9];
+  PXTkEntry* dim_entry[9];
+
+  PXTkLabel* misc_sclabel[6];
+  PXTkEntry* misc_scentry[6];
+
+  PXTkLabel* misc_txlabel[6];
+  PXTkEntry* misc_txentry[6];
+
+  PXTkOptionMenu* orientationMenu;
+  PXTkLabel*      orientationDescription;
+
+  PXTkOptionMenu* qformMenu;
+  PXTkLabel* qformDescription;
+
+  PXTkOptionMenu* sformMenu;
+  PXTkText*       sformMatrix;
+  
+
+  PXTkMenu*  editMenu;
+  PXTkMenu*  detailMenu;
+  PXTkOptionMenu* datatypeMenu;
+  PXTkText*  textBox;
+  //BTX
+  NRTkIWTabNotebook* notebook;
+  //ETX
+
+
+  // Description:
+  // 
+  virtual int   SetHeaderFromDialog();
+  virtual int   DisplayHeader();
+  virtual int   CreateGUI();
+
+
+  // Description:
+  // Modify Header Mode
+  int ChangingHeaderMode;
+  virtual int   SetHeaderMode(int md);
+
+  // Description:
+  // Show Header Detail
+  int ChangingDetailMode;
+
+
+  virtual int SetDetailMode(int dt,int switchto=1);
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUI2DImageEditor.cpp b/bioimagesuite30_src/GUI/vtkpxGUI2DImageEditor.cpp
new file mode 100644
index 0000000..ed2fdea
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUI2DImageEditor.cpp
@@ -0,0 +1,130 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUI2DImageEditor.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:14 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxGUI2DImageEditor.h"
+#include "vtkpxGUI2DImageViewer.h"
+#include "vtkObjectFactory.h"
+
+
+vtkpxGUI2DImageEditor* vtkpxGUI2DImageEditor::New()
+{
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUI2DImageEditor");
+  if(ret)
+      {
+	return (vtkpxGUI2DImageEditor*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUI2DImageEditor;
+}
+
+// Construct object with no children.
+vtkpxGUI2DImageEditor::vtkpxGUI2DImageEditor()
+{
+  this->Viewer=NULL;
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI2DImageEditor::UpdateFromViewer(int mode)
+{
+  //  fprintf(stderr,"Updating from Viewer (%d) mode=%d\n",this->Viewer,mode);
+
+  if (this->Viewer==NULL)
+    return;
+  if (mode==0)
+    this->SetImagesAndLookupTable(this->Viewer->Get2DImageRegion(),
+				  this->Viewer->Get2DImageMaskRegion(),NULL,
+				  this->Viewer->GetCurrentImageIsColor());
+  else
+    this->SetImagesAndLookupTable(this->Viewer->Get2DImageRegion(),
+				  this->Viewer->Get2DImageMaskRegion(),
+				  this->Viewer->GetMaskLookupTable(),
+				  this->Viewer->GetCurrentImageIsColor());
+
+}
+
+void vtkpxGUI2DImageEditor::UpdateViewerDisplay()
+{
+  if (this->Viewer==NULL)
+    return;
+ 
+    this->Viewer->UpdateDisplay();
+
+}
+
+void vtkpxGUI2DImageEditor::UpdateViewerObjectmapColormap()
+{
+   if (this->Viewer==NULL)
+    return;
+ 
+   vtkLookupTable* lkp=this->Viewer->GetMaskLookupTable();
+   lkp->DeepCopy(this->ObjectmapLookupTable);
+}
+ 
+void vtkpxGUI2DImageEditor::UpdateViewerObjectmap()
+{
+   if (this->Viewer==NULL)
+    return;
+ 
+   this->Viewer->Get2DImageMaskRegion()->ShallowCopy(this->Objectmap);
+   this->Viewer->Get2DImageSlice()->UpdateTexture();
+   this->Viewer->UpdateDisplay();
+}
+
+void vtkpxGUI2DImageEditor::SetObjectmapViewer(vtkpxGUI2DImageViewer* viewer)
+{
+  this->Viewer=viewer;
+}
+
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUI2DImageEditor.h b/bioimagesuite30_src/GUI/vtkpxGUI2DImageEditor.h
new file mode 100644
index 0000000..97f6966
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUI2DImageEditor.h
@@ -0,0 +1,99 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUI3DObjectmapEditor.h,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:33 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUI3DObjectmapEditor 
+// .SECTION Description
+
+#ifndef __vtkpxGUI2DImageEditor_h
+#define __vtkpxGUI2DImageEditor_h
+
+#include "vtkpxGUIAbstractMultisliceEditor.h"
+
+class vtkpxGUI2DImageViewer;
+
+class  vtkpxGUI2DImageEditor : public vtkpxGUIAbstractMultisliceEditor {
+  
+public:
+
+  static vtkpxGUI2DImageEditor *New();
+  vtkTypeMacro(vtkpxGUI2DImageEditor,vtkpxGUIAbstractMultisliceEditor);
+  
+  // Description:
+  // Set Viewer
+  virtual void SetObjectmapViewer(vtkpxGUI2DImageViewer* viewer);
+  
+  // Previously Virtual
+  virtual void UpdateFromViewer(int docmap=0);
+
+protected:
+
+  vtkpxGUI2DImageEditor();
+  
+
+  // Description: 
+  // Talking to the Viewer
+  virtual void UpdateViewerDisplay();
+  virtual void UpdateViewerObjectmapColormap();
+  virtual void UpdateViewerObjectmap();
+
+  // Description:
+  // A Pointer to the Viewer 
+  vtkpxGUI2DImageViewer* Viewer;
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUI2DImageViewer.cpp b/bioimagesuite30_src/GUI/vtkpxGUI2DImageViewer.cpp
new file mode 100644
index 0000000..a66d9e0
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUI2DImageViewer.cpp
@@ -0,0 +1,1088 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxGUIColormapEditor.h"
+#include "pxutil.h"
+#include "vtkActor.h"
+#include "vtkImageQuantizeRGBToIndex.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxGUI2DImageViewer.h"
+#include "vtkpxColorMapUtil.h"
+#include "vtkImageThreshold.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkpxUtil.h"
+#include "vtkbisImageReslice.h"
+// -------------------------------------------------------------------------
+vtkpxGUI2DImageViewer* vtkpxGUI2DImageViewer::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUI2DImageViewer");
+  if(ret)
+    {
+      return (vtkpxGUI2DImageViewer*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUI2DImageViewer;
+}
+// -------------------------------------------------------------------------
+// Construct object with no children.
+vtkpxGUI2DImageViewer::vtkpxGUI2DImageViewer()
+{
+  this->offset=0;
+  this->ColormapEditor=NULL;
+  this->timeframeControlFrame=NULL;
+  this->frameScale=NULL;
+
+  this->MouseToEditor=0;
+  this->ShiftMouseToEditor=1;
+  this->Editor=NULL;
+
+  initialized=PXFalse;
+  this->statusLabel=NULL;
+  this->donotRender=0;
+  this->inexpose=0;
+  this->inexposecount=0;
+  this->LastEvent=-1;
+  this->ownsLookupTable=1;
+
+  this->maskImage=NULL;
+  this->maskImageRegion=NULL;
+  this->maskImageSlice=NULL;
+  this->maskTransparency=NULL;
+  this->currentImageRegion=NULL;
+
+  this->LastExtractedSlice=-1;
+  this->LastExtractedOrientation=0;
+  this->LastExtractedFrame=0;
+
+  maskLookupTable=vtkLookupTable::New();
+  vtkpxSurfaceUtil::DefaultObjectMapLookupTable(maskLookupTable,-1,1);
+
+  firsttime=1;
+  olddimensions[0] =  -1;
+  olddimensions[1] =  -1;
+  olddimensions[1] =  -1;
+
+}
+// -------------------------------------------------------------------------
+vtkpxGUI2DImageViewer::~vtkpxGUI2DImageViewer()
+{
+  if (this->maskImage)
+    this->maskImage->Delete();
+  if (this->maskImageRegion)
+    this->maskImageRegion->Delete();
+}
+/* -------------------------------------------------------------------------*/
+char* vtkpxGUI2DImageViewer::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+    return GetWidgetName();
+  
+  vtkpxGUIComponent::Initialize(name,inside);
+
+  PXTkFrame* manager=(PXTkFrame*)(this->EventManager->getMainWindow());
+  PXTkFrame* viewerFrame=new PXTkFrame(this->EventManager,manager);
+  manager->setPackMode(PXTrue);
+
+  manager->addChildren("-side top  -expand true -fill both",viewerFrame);
+  InitControls(viewerFrame,this->CreateHighlights);
+  InitViewer(viewerFrame);
+  return GetWidgetName();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI2DImageViewer::Update()
+{
+  UpdateViewer();
+  UpdateDisplay();
+}
+// -------------------------------------------------------------------------
+void vtkpxGUI2DImageViewer::SetOffset(int of)
+{
+  if (this->Initialized==0)
+      this->offset=of;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUI2DImageViewer::InitializeViewer()
+{
+  if ((!hasImage && this->Initialized))
+      return 0;
+  
+  if (mainLookupTable==NULL)
+    {
+      mainLookupTable=vtkLookupTable::New();
+      this->ownsLookupTable=1;
+      vtkpxColorMapUtil::SetStepColorMap(mainLookupTable,0,255,0,255,256,PXFalse);
+
+    }
+  
+  CreateViewerAndSlice();
+  
+  if (this->ColormapEditor==NULL && this->ownsLookupTable==1)
+    {
+      ColormapEditor=vtkpxGUIColormapEditor::New();
+      ColormapEditor->SetSimpleMode(0);
+      ColormapEditor->SetCallback(this,200);
+      ColormapEditor->Initialize(this->GetWidgetName(),0);
+      ColormapEditor->SetRange(0,255);
+      this->ColormapEditor->SetColormap(mainLookupTable);
+    }
+  
+  return 1;
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUI2DImageViewer::ResetViewer()
+{
+
+  if (!(hasImage && this->Initialized))
+      return 0;
+
+
+
+  // ------------------------------------------------------
+  //           C h e c k    f o r    L o o k u p T a b l e
+  // ------------------------------------------------------
+  int numc=currentImage->GetNumberOfScalarComponents();
+  if (this->ownsLookupTable)
+    {
+      if (numc==3 && this->NumberOfFrames==1)
+	{
+	  vtkpxColorMapUtil::QuantizeColorImage(currentImage,currentImage,mainLookupTable);
+	  this->ColormapEditor->Update();
+	  this->ColormapEditor->SetLock(1);
+	}
+      else
+	{
+	  this->ColormapEditor->SetLock(0);
+	  this->ColormapEditor->SetRange(currentImage);
+	  this->SetPresetLookupTable(this->PresetLookupTableMode);
+	  this->ColormapEditor->Update();
+	}
+    }
+     
+  if (this->Editor!=NULL)
+    this->Editor->SetLookupTable(mainLookupTable);
+  
+  // ------------------------------------------------------
+  //   Bounds/ Highlights 
+  // ------------------------------------------------------
+  double bounds[6];  GetBounds(bounds);
+  int   range[3];   currentImage->GetDimensions(range); 
+  double sp[3];      currentImage->GetSpacing(sp);
+  double ori[3];     currentImage->GetOrigin(ori);
+
+  
+  if (frameScale!=NULL && this->CurrentImageIsColor==0)
+    {
+      this->ShowFrameControls((this->NumberOfFrames>1));
+    }
+  
+  // ------------------------------------------------------
+  //  C h e c k   for   S a m e   D i m e n s i o ns
+  // ------------------------------------------------------
+  int dim[3];     
+  currentImage->GetDimensions(dim);
+  int numslices=dim[2];
+  int samesizeasbefore=0;
+
+  if (firsttime==0)
+    {
+      int flag=0;
+      for (int i=0;i<=2;i++)
+	{
+	  if (dim[i]!=olddimensions[i])
+	    flag++;
+	}
+      if (frameScale!=NULL)
+	{
+	  if (this->NumberOfFrames!=(int(frameScale->getmax())))
+	    flag++;
+	}
+      samesizeasbefore=(flag==0);
+    }
+  
+  for (int i=0;i<=2;i++)
+    olddimensions[i]=dim[i];
+
+  if (samesizeasbefore==0)
+    {
+      firsttime=0;
+      sliceNumber->setResolution(1);
+      sliceNumber->setRange(float(offset),float(numslices-1+offset));
+      sliceNumber->setValue(offset);
+  
+      frameScale->setRange(1,this->NumberOfFrames);
+      frameScale->setResolution(1);
+      frameScale->setValue(1);
+  
+      if (this->Orientation==3)
+	{
+	  renderer->SetClipMode(PXFalse);
+	}
+      else
+	{
+	  renderer->SetClipMode(PXTrue);
+	}
+      //      imageSlice->SetInput(currentImage);
+      renderer->SetBounds(bounds);
+      renderer->SetClipThickness(currentImage->GetSpacing()[2]);
+      //      renderer->SetOrientation(this->Orientation);
+      renderer->SetPlaneMode(2);
+      renderer->SetCurrentImageOrientation(currentImage,this->Orientation);
+      this->CreateMaskImage(currentImage);
+    }
+  else
+    {
+      //      imageSlice->SetInput(currentImage);
+      renderer->SetCurrentImageOrientation(currentImage,this->Orientation);
+    }
+
+  
+
+
+  if (this->Editor!=NULL)
+    this->Editor->SetImage(currentImage,2,0);
+
+  ChangeSliceAndFrame(-1,-1);
+  this->ResetAll();
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUI2DImageViewer::HandleEvent(int event)
+{
+  if (event<10)
+      return this->EventManager->handleDirectEvent(event);
+  
+  if (event==200)
+      UpdateDisplay();
+  
+  if (event==201 || event==202)
+      {
+       if (hasImage)
+	 {
+	   if (event==202)
+	     renderer->Zoom(renderer->GetCameraScale()*1.2,PXFalse);
+	   else
+	     renderer->Zoom(renderer->GetCameraScale()*0.833,PXFalse);
+	   
+	   UpdateDisplay();
+	 }
+      }
+  
+   if (event==203)
+     {
+       if (hasImage)
+	 {
+	   int dim[3];     
+	   currentImage->GetDimensions(dim);
+	   int plane=2;
+	   int numslices=dim[plane];
+	   if (this->Orientation==3)
+	     {
+	       if (plane==0)
+		 numslices=dim[1];
+	       else
+		 numslices=dim[2];
+	     }
+	   
+	   sliceNumber->setRange(offset,numslices-1+offset);
+	   if (sliceNumber->getValue()>=numslices+offset)
+	     sliceNumber->setValue(0+offset);
+	   
+	   UpdateViewer();
+	   UpdateDisplay();
+	 }
+     }
+
+
+   if (event==205)
+     {
+       if (hasImage)
+	 {
+	   PXBool interp=interpolateMode->getState();
+	   if (initialized)
+	     imageSlice->SetInterpolation((int)interp);
+	 }
+       UpdateDisplay();
+     }
+   
+   if (event==206)
+     {
+       ChangeSliceAndFrame(-1,-1);
+     }
+
+   if (event==207)
+     {
+       if (hasImage)
+	 {
+	   UpdateViewer();
+	   UpdateDisplay();
+	 }
+     }
+   
+   if (event==208)
+     ResetAll();
+  
+   if (event==210)
+     {
+       this->SetObjectmapTransparency(this->maskTransparency->getValue());
+     }
+
+   if (event==221)
+     this->SaveAsTiff(render_widget->getRenderWindow());
+   
+   /*if (event==221)
+     this->ExportAsVRML(render_widget->getRenderWindow());*/
+   
+   
+   if (event==209)
+     {
+       if (this->ColormapEditor!=NULL)
+	 this->ColormapEditor->Show();
+     }
+   
+   if (event==214 || event==215 || event==216 || event==217 || event==218 || event==219)
+     {
+       if (event<219)
+	 this->SetPresetLookupTable(event-215);
+       else
+	 this->SetPresetLookupTable(event-213);
+     }
+   
+   
+  if (event==300)
+    {
+      int* x=render_widget->getRenderWindow()->GetSize();
+      int mouse=PXTkApp::getIntArgument(0);
+      int state=PXTkApp::getIntArgument(1);
+      int x1=PXTkApp::getIntArgument(2);
+      int x2=x[1]-PXTkApp::getIntArgument(3);
+      HandleMouseButtonEvent(mouse,state,x1,x2,this->EventManager);
+    }
+  
+  if (event==301)
+    {
+      if (this->LastEvent!=301)
+	{
+	  this->RenderDelay(500);
+	}
+    }
+  
+  this->LastEvent=event;
+  
+  return TCL_OK;
+  
+}
+
+void vtkpxGUI2DImageViewer::SetPresetLookupTable(int mode)
+{
+  if (!hasImage || this->ownsLookupTable==0)
+    return;
+  
+  this->SetPresetLookupTableMode(mode);
+  if (this->ColormapEditor!=NULL)
+    this->ColormapEditor->SetFmriMode(this->PresetLookupTableMode);
+}
+     
+// -------------------------------------------------------------------------
+int vtkpxGUI2DImageViewer::UpdateViewer()
+{
+  if (!hasImage)
+    return TCL_ERROR;
+
+  int plane=2;
+  int dim[3];     currentImage->GetDimensions(dim);
+  int frame=this->CurrentFrame;
+
+  double sp[3];  currentImage->GetSpacing(sp);
+  double ori[3]; currentImage->GetOrigin(ori);
+  
+  this->EventManager->setWaitCursor(PXTrue);
+
+  if (this->Orientation==3)
+    {
+      dim[0]=dim[1];
+      dim[1]=dim[2];
+    }
+
+  int slice=GetSliceNumber();
+
+  int doreset=0;
+  int doclip=0;
+  if (this->Orientation!=3)
+    {
+      renderer->SetClipMode(PXTrue);
+      doclip=1;
+    }
+  else
+    renderer->SetClipMode(PXFalse);
+
+  if (renderer->GetPlaneMode()!=plane)
+    {
+      doreset=1;
+      renderer->SetPlaneMode(plane);
+      renderer->SetFlipMode(0);
+    }
+  
+  renderer->SetClipBounds(slice,slice,slice,sp,ori);
+  renderer->SetViewerCoordinates(slice,slice,slice);
+      
+  if (slice<dim[plane])
+    {
+      this->UpdateObjectmapChanges();
+
+      vtkpxImageExtract* extract=vtkpxImageExtract::New();
+      extract->SetInput(currentImage);
+      extract->SetCurrentPlane(plane);
+      extract->SetSliceNo(slice);
+      extract->SetFrame(frame);
+      if (this->Orientation==3)
+	extract->SetPolarMode(1);
+      else
+	extract->SetPolarMode(0);
+      extract->Update();
+      if (this->currentImageRegion==NULL)
+	this->currentImageRegion=vtkImageData::New();
+      this->currentImageRegion->ShallowCopy(extract->GetOutput());
+
+      imageSlice->SetInput(currentImageRegion);
+      imageSlice->SetVisibility(1);
+      imageSlice->Update();
+
+      extract->SetInput(maskImage);
+      extract->SetCurrentPlane(plane);
+      extract->SetSliceNo(slice);
+      extract->SetFrame(frame);
+      if (this->Orientation==3)
+	extract->SetPolarMode(1);
+      else
+	extract->SetPolarMode(0);
+      extract->Update();
+
+      if (this->maskImageRegion==NULL)
+	this->maskImageRegion=vtkImageData::New();
+      this->maskImageRegion->ShallowCopy(extract->GetOutput());
+      maskImageSlice->SetInput(this->maskImageRegion);
+      maskImageSlice->SetVisibility(1);
+      maskImageSlice->Update();
+
+
+      this->UpdateUndoImages();
+      this->LastExtractedSlice=extract->GetSliceNo();
+      this->LastExtractedOrientation=extract->GetCurrentPlane();
+      this->LastExtractedFrame=extract->GetFrame();
+      extract->Delete();
+
+    }
+  else
+    {
+      imageSlice->SetVisibility(0);
+      imageSlice->Update();
+
+      maskImageSlice->SetVisibility(0);
+      maskImageSlice->Update();
+    }
+
+  this->UpdateObjectmapSlice();
+
+      
+  if (this->Orientation==3)
+    renderer->MoveAbove();
+
+  if (doreset)
+    {
+      renderer->SetClipThickness(currentImage->GetSpacing()[plane]);
+      renderer->Reset();
+    }
+  
+  if (doclip)
+    renderer->Clip();
+  
+  this->EventManager->setWaitCursor(PXFalse);
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUI2DImageViewer::ChangeSliceAndFrame(int sl,int fr)
+{
+  if (!hasImage)
+    return;
+  
+  if (sl!=-1)
+      sliceNumber->setValue(sl+offset);
+  
+  if (fr!=-1 && !this->CurrentImageIsColor)
+      frameScale->setValue(fr+1);
+
+  int callframecallback=0;
+  if (!this->CurrentImageIsColor)
+    {
+      int a=(int) frameScale->getValue()-1;
+      if (a!=this->CurrentFrame)
+	{
+	  this->CurrentFrame=a;
+	  callframecallback=1;
+	}
+    }
+    
+  if (this->Editor!=NULL)
+    {
+      int bl=(int)sliceNumber->getValue()-offset;
+      int plane=2;
+      this->Editor->SetPlaneLevel(plane,bl);
+      this->Editor->SetFrame(CurrentFrame);
+    }
+  
+  UpdateViewer();
+
+  if (callframecallback==1)
+    this->ExecuteFrameChangeCallback();
+
+  if (this->donotRender==0)
+    this->UpdateDisplay();
+   
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUI2DImageViewer::GetSliceNumber()
+{
+  if (!hasImage)
+    return -1;
+
+  return (int) sliceNumber->getValue();
+}
+// -------------------------------------------------------------------------
+void vtkpxGUI2DImageViewer::SetCurrentFrame(int t)
+{
+  if (!this->CurrentImageIsColor)
+    {
+      if (t<0)
+	t=this->NumberOfFrames-1;
+      if (t>this->NumberOfFrames-1)
+	t=0;
+      this->ChangeSliceAndFrame(-1,t);
+    }
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUI2DImageViewer::CreateViewerAndSlice()
+{
+  if (hasImage== PXFalse || this->Initialized==0)
+    return;
+  
+  if (initialized)
+    return;
+  
+  int plane=2;
+  //  int frame=0;
+
+  vtkRenderer* ren=vtkRenderer::New();
+  ren->SetBackground(0.0,0.1,0.25);
+  render_widget->getRenderWindow()->AddRenderer(ren);
+    
+  renderer=vtkpxGUIRenderer::New();
+  renderer->SetPlaneMode(plane);
+  renderer->SetOrientation(this->Orientation);
+  renderer->SetFlipMode(0);
+  renderer->SetNoGUI(PXTrue);
+  
+  renderer->Initialize(this->EventManager->getMainWindow()->getWidgetName(),ren,0);
+  renderer->SetAutoZoom(1.0);
+  renderer->SetCallback(this,201);
+
+  imageSlice=vtkpx2DImageSlice::New();
+  imageSlice->SetAutoUpdate(0);
+  imageSlice->SetInput(currentImage);
+  imageSlice->SetLookupTable(mainLookupTable);
+ 
+  maskImageSlice=vtkpx2DImageSlice::New();
+  maskImageSlice->SetAutoUpdate(0);
+  maskImageSlice->SetInput(currentImage);
+  maskImageSlice->SetLookupTable(maskLookupTable);
+  maskImageSlice->SetOpacity(this->maskTransparency->getValue()*0.01);
+ 
+#ifndef _WIN32
+  renderer->SetClipMode(PXTrue);
+#endif
+
+#ifndef _WIN32
+  renderer->SetClipMode(PXTrue);
+  renderer->SetClipThickness(currentImage->GetSpacing()[2]);
+#endif
+
+  renderer->GetRenderer()->AddActor(imageSlice);
+  renderer->GetRenderer()->AddActor(maskImageSlice);
+  
+  
+  if (this->Editor)
+    this->Editor->SetRenderer(ren);
+
+  double bounds[6];  GetBounds(bounds);
+  renderer->SetBounds(bounds);
+
+  
+
+  //  if (index>0)
+  //  renderer->SetCameraScale(renderer->GetCameraScale());
+  //else
+  renderer->Reset();
+
+  initialized=PXTrue;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUI2DImageViewer::ResetAll()
+{
+  if (!hasImage)
+      return 0;
+
+  if (initialized)
+    renderer->Reset();
+
+  UpdateDisplay();
+
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUI2DImageViewer::HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev)
+{
+  //  int found=-1;
+  if (ev==NULL || hasImage==PXFalse)
+    return 0;
+  
+  if (!renderer->InViewport(x,y))
+    return 0;
+  
+  if (this->Editor!=NULL)
+    {
+      if (nbutton==3  && this->Editor->IsOpen()==0 && this->IsA("vtkpxGUI2DImageViewer")==0)
+	{
+	  if (state==2)
+	    this->Editor->Show();
+	  return 1;
+	}
+    }
+
+  int sendtoeditor=0;
+  //  if ( this->MouseToEditor && (  nbutton == 4 || nbutton==7 || ( this->ShiftMouseToEditor==0 && nbutton==1)))
+  if ( this->MouseToEditor==1 || ( nbutton == 4 || nbutton==7 || ( this->ShiftMouseToEditor==0 && nbutton==1)))
+    {
+      if (this->Editor!=NULL)
+	sendtoeditor=1;
+    }
+  
+  //  fprintf(stderr,"nbutton=%d sendtoeditor=%d mousetoeditor=%d shiftmouse=%d\n",nbutton,sendtoeditor,
+  //  this->MouseToEditor,this->ShiftMouseToEditor);
+
+  if (nbutton  == 1 || nbutton == 4 || nbutton == 7 )
+    {
+      double px1,py1;
+      
+      renderer->Get2DClickedPoint(px1,py1,x,y);
+
+      int plane=2;
+      int slice=GetSliceNumber();
+      double sp[3],ori[3];
+      currentImage->GetSpacing(sp);
+      currentImage->GetOrigin(ori);
+      float slice_sc=slice*sp[plane]+ori[plane];
+      
+      if (nbutton==7)
+	state=3+state;
+
+      if (nbutton==4)
+	{
+	  if (this->IsA("vtkpxGUI2DImageViewer")==1)
+	    {
+	      state=6+state;
+	    }
+	}
+
+
+      switch(plane)
+	{
+	case 0:
+	  if (sendtoeditor)
+	    this->Editor->HandleClickedPoint(slice_sc,px1,py1,1,state);
+	  this->LastClickedPointScaled[0]=slice_sc;
+	  this->LastClickedPointScaled[1]=px1;
+	  this->LastClickedPointScaled[2]=py1;
+	  break;
+	case 1:
+	  if (sendtoeditor)
+	    this->Editor->HandleClickedPoint(px1,slice_sc,py1,1,state);
+	  this->LastClickedPointScaled[0]=px1;
+	  this->LastClickedPointScaled[1]=slice_sc;
+	  this->LastClickedPointScaled[2]=py1;
+	  break;
+	case 2:
+	  if (sendtoeditor)
+	    this->Editor->HandleClickedPoint(px1,py1,slice_sc,1,state);
+	  this->LastClickedPointScaled[0]=px1;
+	  this->LastClickedPointScaled[1]=py1;
+	  this->LastClickedPointScaled[2]=slice_sc;
+	  break;
+	}
+      
+      double lv[3];
+      for (int ia=0;ia<=2;ia++)
+	lv[ia]=(this->LastClickedPointScaled[ia]-ori[ia])/sp[ia];
+      this->SetLastClickedPoint(lv);
+
+      int   dim[3];   
+      currentImage->GetDimensions(dim);
+      lv[0]=Frange(lv[0],0,dim[0]-1);
+      lv[1]=Frange(lv[1],0,dim[1]-1);
+      lv[2]=Frange(lv[2],0,dim[2]-1);
+
+      /*      //      if (!sendtoeditor)
+      //{
+	  fprintf(stderr,"Setting %d %d to 400.0\n",int(lv[0]),int(lv[1]));
+	  this->maskImageSlice->GetCurrentImage()->SetScalarComponentFromDouble((int)lv[0],(int)lv[1],0,0,1.0);
+	  this->maskImageSlice->UpdateTexture();
+	  //}
+      
+      //      if (this->statusLabel!=NULL)
+      //{
+      
+	  double vl=currentImage->GetScalarComponentAsDouble((int)lv[0],
+							    (int)lv[1],
+							    (int)lv[2],
+							    this->CurrentFrame);
+	  sprintf(pxtk_buffer,"* %.2f (%.0f,%.0f,%.0f)",vl,
+		  lv[0],lv[1],lv[2]);
+	  
+	  
+	  statusLabel->setText(pxtk_buffer);
+	  //}*/
+      
+      UpdateDisplay();
+      return 1;
+    }
+
+  if ( nbutton!=1 && nbutton!=4 && nbutton!=7)
+    {
+      return renderer->HandleMouseButtonEvent(nbutton,state,x,y,ev);
+    }
+
+  return 0;
+  
+}
+// -------------------------------------------------------------------------
+void vtkpxGUI2DImageViewer::InitControls(PXTkFrame* parwidget,int dohighlight)
+{
+  controlFrame=new PXTkFrame(this->EventManager,parwidget);
+  parwidget->setPackMode(PXTrue);
+  parwidget->addChildren("-side bottom -expand false -fill x",controlFrame);
+
+  PXTkFrame* tframe=new PXTkFrame(this->EventManager,controlFrame);
+  PXTkFrame* bframe=new PXTkFrame(this->EventManager,controlFrame);
+  controlFrame->addChildren("-side top -expand false -fill x",bframe);
+  controlFrame->addChildren("-side bottom    -expand true  -fill both -pady 2",tframe);
+  
+  interpolateMode=new PXTkCheckButton(this->EventManager,bframe,"Interp",205);
+  interpolateMode->setState(PXTrue);
+
+  PXTkButton* b1=new PXTkButton(this->EventManager,bframe,"Reset",208);
+  bframe->addChildren("-side right -expand t -fill x",interpolateMode,b1);
+      
+  if (this->ownsLookupTable)
+    {
+      PXTkButton* b1c=new PXTkButton(this->EventManager,bframe,"ColorMap",209);
+      bframe->addChildren("-side right -expand t -fill x",interpolateMode,b1c);
+    }
+  
+  //#ifdef _WIN32
+  PXTkDualArrowLabel* zoom=new PXTkDualArrowLabel(this->EventManager,bframe,"Zoom",201,202,0);
+  bframe->addChildren("-side right -expand t -fill x",zoom);
+  //#endif
+  
+  this->timeframeControlFrame=new PXTkFrame(this->EventManager,tframe);
+  tframe->addChildren("-side left -expand true -fill x -padx 2 ",timeframeControlFrame);
+  
+  sliceNumber=new PXTkArrowScale(this->EventManager,timeframeControlFrame,"Slice:",206,PXTrue);
+  sliceNumber->setLengthWidth(120,15);
+  
+  maskTransparency=new PXTkArrowScale(this->EventManager,timeframeControlFrame,"Mask:",210,PXTrue);
+  maskTransparency->setRange(0.0,100.0);
+  maskTransparency->setResolution(1.0);
+  maskTransparency->setValue(50.0);
+  maskTransparency->setLengthWidth(80,15);
+
+
+  frameScale=new PXTkArrowScale(this->EventManager,this->timeframeControlFrame,"Frame:",206,PXTrue);
+  frameScale->setRange(1,1);
+  frameScale->setIncrement(1);
+  frameScale->setResolution(1);
+  frameScale->setValue(1);
+  frameScale->setLengthWidth(10,10);
+  timeframeControlFrame->addChildren("-side left -expand f -fill x",sliceNumber->getMainWindow(),
+				     frameScale->getMainWindow(),
+				     maskTransparency->getMainWindow());
+  
+  statusLabel=new PXTkLabel(this->EventManager,bframe,"PI:");
+  statusLabel->configure("-bg","black");
+  statusLabel->configure("-fg","white");
+  statusLabel->configure("-width","24");
+  
+  PXTkButton* b2=new PXTkButton(this->EventManager,bframe,"Snapshot",221);
+  bframe->addChildren("-side left -expand false -fill x",statusLabel,b2);
+  if (this->CurrentImageIsColor)
+    this->ShowFrameControls(0);
+  
+  sliceNumber->setRange(float(offset),float(10.0+offset));
+  sliceNumber->setValue(float(offset));
+  sliceNumber->setIncrement(1.0);
+  sliceNumber->setResolution(1.0);
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUI2DImageViewer::InitViewer(PXTkFrame* parFrame)
+{
+  render_widget=new PXVTkTkRenderWidget(this->EventManager,parFrame,300);
+  render_widget->setWidthHeight(400,400);
+  parFrame->setPackMode(PXTrue);
+  parFrame->addChildren("-side left -expand true -fill both",render_widget);
+  render_widget->bindMouseEvents();
+}
+// -------------------------------------------------------------------------
+void vtkpxGUI2DImageViewer::GetBounds(double bounds[6])
+{
+  if (!hasImage)
+      return;
+
+  int   range[3]; currentImage->GetDimensions(range);
+  double sp[3];    currentImage->GetSpacing(sp);
+  double ori[3];   currentImage->GetOrigin(ori);
+
+  for (int k=0;k<=2;k++)
+      {
+	bounds[2*k]  =      ori[k]-0.5*sp[k];
+	bounds[2*k+1]=float(range[k]-0.5)*sp[k]+ori[k];
+      }
+}
+// -------------------------------------------------------------------------
+char* vtkpxGUI2DImageViewer::GetRenderWidgetName()
+{
+  if (this->render_widget==NULL)
+    return NULL;
+  else
+    return this->render_widget->getWidgetName();
+}
+// -------------------------------------------------------------------------
+vtkRenderer* vtkpxGUI2DImageViewer::GetRenderer()
+{
+  if (initialized)
+    return renderer->GetRenderer();
+  else
+    return NULL;
+}
+
+vtkpxGUIRenderer* vtkpxGUI2DImageViewer::GetGUIRenderer()
+{
+  if (initialized)
+    return renderer;
+  else
+    return NULL;
+}
+
+char* vtkpxGUI2DImageViewer::GetControlFrameName()
+{
+  if (this->Initialized==0)
+    return NULL;
+  
+  return this->controlFrame->getWidgetName();
+}
+
+
+
+PXTkFrame* vtkpxGUI2DImageViewer::GetControlFrame()
+{
+  if (this->Initialized==0)
+    return NULL;
+  
+  return this->controlFrame;
+}
+
+PXTkFrame* vtkpxGUI2DImageViewer::GetTimeSliceFrame()
+{
+  if (this->Initialized==0)
+    return NULL;
+  
+  return this->timeframeControlFrame;
+}
+
+
+// -------------------------------------------------------------------------
+void vtkpxGUI2DImageViewer::ShowFrameControls(int show)
+{
+  if (!this->Initialized || frameScale==NULL)
+    {
+      return;
+    }
+  
+  if (show==0)
+    {
+      frameScale->setLengthWidth(10,10);
+      timeframeControlFrame->unmapChild(frameScale->getMainWindow());
+      timeframeControlFrame->configure("-width",0);
+    }
+  else
+    {
+      frameScale->setLengthWidth(50,10);
+      sliceNumber->setLengthWidth(70,10);
+      timeframeControlFrame->addChildren("-side left -expand t -fill x",frameScale->getMainWindow());
+    }
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI2DImageViewer::UpdateDisplay()
+{
+  if (this->Initialized && this->donotRender==0)
+    {
+      if (inexpose==1 || this->EnableRendering==0)
+	{
+	  ++inexposecount;
+	  return TCL_OK;
+	}
+
+      inexpose=1;
+      PXTkApp::executeTclCommand("update display");
+      render_widget->getRenderWindow()->Render();  
+      this->LastEvent=-1;
+      inexposecount=0;
+      inexpose=0;
+      return TCL_OK;
+    }
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------	    
+
+ 
+void vtkpxGUI2DImageViewer::CreateMaskImage(vtkImageData* cur_img)
+{
+  if (this->maskImage==NULL)
+    {
+      this->maskImage=vtkImageData::New();
+    }
+
+  double range[2]; currentImage->GetPointData()->GetScalars()->GetRange(range);
+
+  vtkImageThreshold* thr=vtkImageThreshold::New();
+  thr->SetInput(cur_img);
+  thr->ThresholdByLower(0.5*(range[0]+range[1]));
+  thr->ReplaceInOn();
+  thr->ReplaceOutOn();
+  thr->SetInValue(0.0);
+  thr->SetOutValue(0.0);
+  thr->SetOutputScalarTypeToUnsignedChar();
+  thr->Update();
+
+  maskImage->ShallowCopy(thr->GetOutput());
+  thr->Delete();
+
+  this->LastExtractedSlice=-1;
+  this->UpdateViewer();
+}
+
+// ------------------------------------------------------------------------
+int vtkpxGUI2DImageViewer::ClearMaskImage() 
+{
+  if ((!hasImage && this->Initialized))
+    return 0;
+  this->CreateMaskImage(currentImage);
+  return 1;
+}
+
+void vtkpxGUI2DImageViewer::SetMaskImage(vtkImageData* newmaskimage,int orientation) 
+{
+  if (newmaskimage==NULL)
+    return;
+  
+  if (this->maskImage==NULL)
+    this->maskImage=vtkImageData::New();
+
+  vtkbisImageReslice* resl=vtkbisImageReslice::New();
+  resl->OptimizationOff();
+  resl->SetInput(newmaskimage);
+  resl->SetInformationInput(this->maskImage);
+  resl->SetInterpolationMode(0);
+  resl->SetBackgroundLevel(0);
+  resl->Update();
+
+  this->maskImage->ShallowCopy(resl->GetOutput());
+  resl->Delete();
+  this->LastExtractedSlice=-1;
+  this->UpdateViewer();
+}
+
+vtkImageData*  vtkpxGUI2DImageViewer::GetMaskImage()
+{
+  this->UpdateObjectmapChanges();
+  return this->maskImage;
+}
+
+float vtkpxGUI2DImageViewer::GetObjectmapTransparency()
+{
+  if (  this->maskImageSlice==NULL)
+    return 0.0;
+
+  return 100.0*this->maskImageSlice->GetOpacity();
+}
+
+void vtkpxGUI2DImageViewer::SetObjectmapTransparency(float v)
+{
+  if (  this->maskImageSlice!=NULL)
+    {
+      this->maskImageSlice->SetOpacity(float(v)*0.01);
+      this->UpdateDisplay();
+    }
+}
+
+vtkLookupTable*  vtkpxGUI2DImageViewer::GetMaskLookupTable()
+{
+  return maskLookupTable;
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUI2DImageViewer.h b/bioimagesuite30_src/GUI/vtkpxGUI2DImageViewer.h
new file mode 100644
index 0000000..3fd68fa
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUI2DImageViewer.h
@@ -0,0 +1,219 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUI2DImageViewer.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUI2DImageViewer 
+// .SECTION Description
+
+#ifndef __vtkpxGUI2DImageViewer_h
+#define __vtkpxGUI2DImageViewer_h
+
+
+#include "pxtkcomplexwidgets.h"
+#include "pxtkdialog.h"
+#include "pxvtkgadgets.h"
+
+#include "vtkpxGUIBaseImageViewer.h"
+#include "vtkpxGUIRenderer.h"
+#include "vtkpx2DImageSlice.h"
+#include "vtkpxUtil.h"
+#include "vtkpxGUIBaseCurveEditor.h"
+
+
+
+class  vtkpxGUI2DImageViewer : public vtkpxGUIBaseImageViewer
+{
+public:
+  static vtkpxGUI2DImageViewer *New();
+  vtkTypeMacro(vtkpxGUI2DImageViewer,vtkpxGUIBaseImageViewer);
+  
+  // Initialize Display  
+  virtual char*  Initialize(const char* name,int inside);
+  virtual void   Update();
+
+
+  // Auto Lookup Table
+  virtual void SetPresetLookupTable(int mode=0);
+  
+  virtual void SetOffset(int off);
+  virtual void ShowFrameControls(int show=1);
+
+  virtual int  InitializeViewer();
+  virtual int  ResetViewer();
+
+  virtual int  UpdateViewer();
+  virtual int  UpdateDisplay();
+  virtual int  ResetAll();
+
+  virtual int  GetSliceNumber();
+  virtual void SetCurrentFrame(int t);
+  //virtual void SetCurrentSlice(int sl);
+
+  virtual char* GetRenderWidgetName();
+
+  virtual int  HandleEvent(int eventno);
+  virtual int  HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev);
+
+  virtual void SetEditor(vtkpxGUIBaseCurveEditor* cont) { Editor=cont;}
+
+  vtkSetMacro(MouseToEditor,int);
+  vtkGetMacro(MouseToEditor,int);
+  vtkSetMacro(ShiftMouseToEditor,int);
+  vtkGetMacro(ShiftMouseToEditor,int);
+
+  virtual vtkRenderer* GetRenderer();
+  virtual vtkpxGUIRenderer* GetGUIRenderer();
+
+  virtual char* GetControlFrameName();
+
+
+  //BTX
+  virtual PXTkFrame* GetControlFrame();
+  virtual PXTkFrame* GetTimeSliceFrame();
+  //ETX
+
+  virtual void SetMaskImage(vtkImageData* maskimage,int orientation);
+  virtual vtkImageData* GetMaskImage();
+  virtual int  ClearMaskImage();
+  // V in 0:100
+  virtual void  SetObjectmapTransparency(float v);
+  virtual float GetObjectmapTransparency();
+
+  virtual vtkLookupTable*  GetMaskLookupTable();
+
+  // Description:
+  // Rapid Access
+  virtual vtkImageData* Get2DImageRegion() { return this->currentImageRegion; }
+  virtual vtkImageData* Get2DImageMaskRegion()   { return this->maskImageRegion; }
+  virtual vtkpx2DImageSlice* Get2DImageSlice()   { return this->maskImageSlice; }
+
+  // Description:
+  // Does this have an objectmap
+  virtual int HasObjectmap() { return 1;}
+
+protected:
+
+  vtkpxGUIRenderer*         renderer;
+  PXVTkTkRenderWidget*      render_widget;
+  vtkpx2DImageSlice*        imageSlice;
+  PXBool                    initialized;
+
+  vtkpxGUIBaseCurveEditor*  Editor;
+  int                       MouseToEditor;
+  int                       ShiftMouseToEditor;
+  int                       CreateHighlights;
+
+  PXTkFrame*                controlFrame;
+  PXTkFrame*                timeframeControlFrame;
+
+  PXTkLabel*                statusLabel;
+
+  int                       offset;
+  int                       donotRender;
+
+  PXTkCheckButton*          interpolateMode;
+  PXTkArrowScale            *sliceNumber;
+  PXTkArrowScale            *frameScale;
+  vtkpxGUIColormapEditor*   ColormapEditor;
+
+
+  vtkpxGUI2DImageViewer();
+  virtual ~vtkpxGUI2DImageViewer();
+   
+  virtual void ChangeSliceAndFrame(int sl,int fr=-1);
+
+  virtual void CreateViewerAndSlice();
+
+  virtual void InitControls(PXTkFrame* parent,int hm=1);
+  virtual void InitViewer(PXTkFrame* parent);
+
+  virtual void GetBounds(double bounds[6]);
+
+  // Flags to check for Rendering
+  //BTX
+  int inexpose,inexposecount;
+  //ETX
+
+  vtkImageData*       maskImage;
+  vtkImageData*       maskImageRegion;
+  vtkImageData*       currentImageRegion;
+
+  vtkpx2DImageSlice*  maskImageSlice;
+  PXTkArrowScale*     maskTransparency;
+  vtkLookupTable*     maskLookupTable;
+
+  virtual void CreateMaskImage(vtkImageData* currentImage);
+  // BTX
+  virtual int  UpdateUndoImages() { return 1; }
+  virtual int  UpdateObjectmapChanges() { return 1; }
+  // ETX
+  int               LastExtractedSlice;
+  int               LastExtractedOrientation;
+  int               LastExtractedFrame;
+
+  //BTX
+  int firsttime;
+  int olddimensions[3];
+  //ETX
+
+  virtual int UpdateIntensityLabelInfo() { return 0;}
+  virtual int UpdateObjectmapSlice() { return 1;}
+
+  
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUI2DSplineObjectmapViewer.cpp b/bioimagesuite30_src/GUI/vtkpxGUI2DSplineObjectmapViewer.cpp
new file mode 100644
index 0000000..3953425
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUI2DSplineObjectmapViewer.cpp
@@ -0,0 +1,599 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUI2DSplineObjectmapViewer.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:14 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxGUI2DSplineObjectmapViewer.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxImageReplaceSlice.h"
+#include "vtkpxGUI2DImageEditor.h"
+#include "nrtk_iwidget_tabnotebook.h"
+
+vtkpxGUI2DSplineObjectmapViewer* vtkpxGUI2DSplineObjectmapViewer::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUI2DSplineObjectmapViewer");
+  if(ret)
+      {
+	return (vtkpxGUI2DSplineObjectmapViewer*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUI2DSplineObjectmapViewer;
+}
+
+// Construct object with no children.
+vtkpxGUI2DSplineObjectmapViewer::vtkpxGUI2DSplineObjectmapViewer()
+{
+  this->CreateHighlights=0;
+  this->SplineControl=NULL;
+  this->NumberOfSplines=50;
+  this->ColorMode=0;
+  this->ForceNoAutoUpdate=0;
+  this->sliceChangeCallbackName=NULL;
+  this->EnableSliceChangeCallback=1;
+  this->SplineControl=NULL;
+  this->ObjectmapControl=NULL;
+  this->DefaultScaleMode=4;
+
+}
+/* -------------------------------------------------------------------------*/
+vtkpxGUI2DSplineObjectmapViewer::~vtkpxGUI2DSplineObjectmapViewer()
+{
+  if (this->SplineControl)
+    this->SplineControl->Delete();
+
+  if (this->ObjectmapControl)
+    this->ObjectmapControl->Delete();
+
+  if (this->sliceChangeCallbackName!=NULL)
+    delete [] this->sliceChangeCallbackName;
+
+
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI2DSplineObjectmapViewer::SetNumberOfSplines(int a)
+{
+  if (this->Initialized==1)
+      return;
+  
+  this->NumberOfSplines=Irange(a,1,SP_MAX_COLLECTIONS);
+  return;
+}
+
+/* -------------------------------------------------------------------------*/
+char* vtkpxGUI2DSplineObjectmapViewer::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+  
+  vtkpxGUIComponent::Initialize(name,inside);
+
+  PXTkFrame* manager=(PXTkFrame*)(this->EventManager->getMainWindow());
+
+  PXTkFrame* tframe=new PXTkFrame(this->EventManager,manager);
+  PXTkFrame* bframe=new PXTkFrame(this->EventManager,manager);
+
+
+  manager->setPackMode(PXTrue);
+  manager->addChildren("-side bottom -expand false -fill x",bframe);
+  manager->addChildren("-side top    -expand true  -fill both -pady 2",tframe);
+
+  PXTkFrame* v_frame=new PXTkFrame(this->EventManager,tframe);
+  NRTkIWTabNotebook* tab=new NRTkIWTabNotebook(this->EventManager,tframe,"n",300,500);
+  tframe->addChildren("-side right -expand false -fill y",tab->getMainWindow());
+  tframe->addChildren("-side left -expand true -fill both",v_frame);
+
+
+  PXTkFrame* fillFrame=tab->addPage("Objectmap");
+  fillFrame->configure("-height",200);
+  fillFrame->configure("-bg","blue");
+  this->CreateObjectmapControl(fillFrame);
+
+  InitControls(bframe,this->CreateHighlights);
+  this->ShowFrameControls(0);
+  InitViewer(v_frame);
+
+  this->SplineControl=vtkpxGUISplineControl::New();
+  this->SplineControl->SetShowGhostControls(0);
+  this->SplineControl->SetNumberOfSplines(this->NumberOfSplines);
+  this->SplineControl->SetSlaveMode(1);
+  this->SplineControl->SetDefaultScaleMode(this->DefaultScaleMode);
+  this->SetEditor(this->SplineControl);
+  this->SetMouseToEditor(1);
+  if (this->EventParent!=NULL && this->CallbackNo>0)
+    this->SplineControl->SetCallback(this,800);
+
+  
+  PXTkFrame* spFrame=tab->addPage("Spline");
+  this->SplineControl->Initialize(spFrame->getWidgetName(),1);
+
+  tab->viewPage("Objectmap");
+  
+  if (!inside)
+    {
+      PXTkFrame* bottomButtonFrame=this->GetTimeSliceFrame();
+      PXTkButton* closeB;
+      if (this->EventParent!=NULL || this->CallbackName!=NULL)
+	closeB=new PXTkButton(this->EventManager,bottomButtonFrame,"Close",3);
+      else
+	closeB=new PXTkButton(this->EventManager,bottomButtonFrame,"Exit",1);
+      bottomButtonFrame->addChildren("-side right -expand false -fill x -padx 10",closeB);
+    }
+
+  this->ShowFrameControls(0);
+
+  return GetWidgetName();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI2DSplineObjectmapViewer::HandleEvent(int event)
+{
+  switch(event)
+    {
+    case 800:
+      if (this->EventParent!=NULL && this->CallbackNo>0)
+	this->EventParent->HandleEvent(CallbackNo+1);
+      else
+	if (this->CallbackName!=NULL)
+	  PXTkApp::executeTclCommand(this->CallbackName);
+      break;
+      
+    case 806:
+      this->FillObjectmap(this->ObjectmapControl->GetCurrentColor(),1);
+      break;
+      
+    case 810:
+      this->FillObjectmap(this->ObjectmapControl->GetCurrentColor(),0);
+      break;
+      
+      
+    case 802:
+      {
+	int sl=vtkpxGUI2DImageViewer::GetSliceNumber();
+	this->LastExtractedSlice=-1;
+	this->SetSlice(sl);
+      }
+      break;
+      
+    default:
+      vtkpxGUI2DImageViewer::HandleEvent(event);
+    }
+    
+  
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI2DSplineObjectmapViewer::SetSlice(int sl)
+{
+  if (!hasImage)
+    return;
+
+  int dim[3];
+  currentImage->GetDimensions(dim);
+  
+  if (sl<0)
+    sl=dim[2]/2;
+  else
+    sl=Irange(sl,0,dim[2]-1);
+ 
+  int a=this->ForceNoAutoUpdate;
+  this->ForceNoAutoUpdate=1;
+  this->ChangeSliceAndFrame(sl,-1);
+  this->ForceNoAutoUpdate=a;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI2DSplineObjectmapViewer::ChangeSliceAndFrame(int sl,int fr)
+{
+
+  vtkpxGUI2DImageViewer::ChangeSliceAndFrame(sl,fr);
+  PXTkApp::executeTclCommand("update idletasks");
+
+  int nc=currentImage->GetNumberOfScalarComponents();
+  if (nc==1)
+    sprintf(pxtk_buffer,"Spline/ObjectmapEditor Slice=%d",
+	    this->GetBeginSlice());
+  else
+    sprintf(pxtk_buffer,"Spline/ObjectmapEditor Slice=%d Frame=%d",
+	    this->GetBeginSlice(),this->GetCurrentFrame()+1);
+  this->EventManager->setTitle(pxtk_buffer);
+  
+  // Something here about objectmapcontrol ADD
+  this->ObjectmapControl->UpdateFromViewer(0);
+  // -----------------------------------------
+
+
+  this->ExecuteSliceChangeCallback();
+}
+/* -------------------------------------------------------------------------*/
+// Description:
+// Enable/Disable Spline
+void vtkpxGUI2DSplineObjectmapViewer::EnableSpline(int i)
+{
+  if (this->SplineControl==NULL)
+    return;
+  this->SplineControl->EnableSpline(i);
+}
+
+void vtkpxGUI2DSplineObjectmapViewer::DisableSpline(int i)
+{
+ if (this->SplineControl==NULL)
+   return;
+ this->SplineControl->DisableSpline(i);
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI2DSplineObjectmapViewer::GetBeginSlice()
+{
+  return vtkpxGUI2DImageViewer::GetSliceNumber();
+}
+
+int vtkpxGUI2DSplineObjectmapViewer::ResetViewer()
+{
+  if (this->Orientation==3)
+    this->Orientation=1;
+  int status=vtkpxGUI2DImageViewer::ResetViewer();
+  this->ObjectmapControl->UpdateFromViewer(1);
+  return status;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI2DSplineObjectmapViewer::CreateSnake()
+{
+  if (this->SplineControl!=NULL)
+    this->SplineControl->DoSnake(1);
+}
+
+void vtkpxGUI2DSplineObjectmapViewer::UpdateSnake()
+{
+  if (this->SplineControl!=NULL)
+    this->SplineControl->DoSnake(2);
+
+}
+
+void vtkpxGUI2DSplineObjectmapViewer::SetSliceChangeCallback(const char* name)
+{
+  if (name==NULL)
+    return;
+
+  if (this->sliceChangeCallbackName!=NULL)
+    delete [] this->sliceChangeCallbackName;
+
+  this->sliceChangeCallbackName=new char[strlen(name)+1];
+  strcpy(this->sliceChangeCallbackName,name);
+}
+
+void  vtkpxGUI2DSplineObjectmapViewer::ExecuteSliceChangeCallback()
+{
+  if (this->EnableSliceChangeCallback==0)
+    return;
+  
+  if (this->sliceChangeCallbackName!=NULL)
+    {
+      PXTkApp::executeTclCommand(this->sliceChangeCallbackName);
+    }
+  else if (this->EventParent!=NULL && this->CallbackNo>0)
+    {
+      this->EventParent->HandleEvent(CallbackNo);
+    }
+  else
+    {
+      if (this->CallbackName!=NULL)
+	PXTkApp::executeTclCommand(this->CallbackName);
+    }
+}
+// -------------------------------------------------------------------------
+int vtkpxGUI2DSplineObjectmapViewer::HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev)
+{
+  int found=-1;
+  if (ev==NULL || hasImage==PXFalse)
+    return 0;
+  
+  if (!renderer->InViewport(x,y))
+    return 0;
+  
+  /*  if (this->Editor!=NULL)
+    {
+      if (nbutton==3  && this->Editor->IsOpen()==0 && this->IsA("vtkpxGUI2DSplineObjectmapViewer")==0)
+	{
+	  if (state==2)
+	    this->Editor->Show();
+	  return 1;
+	}
+	}*/
+
+  int sendtosplinecontrol=0;
+  int draw_mode=this->ObjectmapControl->GetPaintMode();
+
+  if (draw_mode==0)
+    {
+      if ( ( this->MouseToEditor || ( nbutton == 4 || nbutton==7 )) || ( this->ShiftMouseToEditor==0 && nbutton==1) )
+	sendtosplinecontrol=1;
+    }
+
+
+  if (nbutton  == 1 || nbutton == 4 || nbutton == 7 )
+    {
+      double px1,py1;
+      
+      renderer->Get2DClickedPoint(px1,py1,x,y);
+
+      int plane=2;
+      int slice=GetSliceNumber();
+      double sp[3],ori[3];
+      currentImage->GetSpacing(sp);
+      currentImage->GetOrigin(ori);
+      float slice_sc=slice*sp[plane]+ori[plane];
+      
+      if (nbutton==7)
+	state=3+state;
+
+      if (nbutton==4)
+	{
+	  if (this->IsA("vtkpxGUI2DSplineObjectmapViewer")==1)
+	    {
+	      state=6+state;
+	    }
+	}
+
+
+      switch(plane)
+	{
+	case 0:
+	  if (sendtosplinecontrol)
+	    this->Editor->HandleClickedPoint(slice_sc,px1,py1,1,state);
+	  this->LastClickedPointScaled[0]=slice_sc;
+	  this->LastClickedPointScaled[1]=px1;
+	  this->LastClickedPointScaled[2]=py1;
+	  break;
+	case 1:
+	  if (sendtosplinecontrol)
+	    this->Editor->HandleClickedPoint(px1,slice_sc,py1,1,state);
+	  this->LastClickedPointScaled[0]=px1;
+	  this->LastClickedPointScaled[1]=slice_sc;
+	  this->LastClickedPointScaled[2]=py1;
+	  break;
+	case 2:
+	  if (sendtosplinecontrol)
+	    this->Editor->HandleClickedPoint(px1,py1,slice_sc,1,state);
+	  this->LastClickedPointScaled[0]=px1;
+	  this->LastClickedPointScaled[1]=py1;
+	  this->LastClickedPointScaled[2]=slice_sc;
+	  break;
+	}
+      
+      double lv[3];
+      for (int ia=0;ia<=2;ia++)
+	lv[ia]=(this->LastClickedPointScaled[ia]-ori[ia])/sp[ia];
+      this->SetLastClickedPoint(lv);
+
+      int   dim[3];   
+      currentImage->GetDimensions(dim);
+      lv[0]=Frange(lv[0],0,dim[0]-1);
+      lv[1]=Frange(lv[1],0,dim[1]-1);
+      lv[2]=Frange(lv[2],0,dim[2]-1);
+
+      if (!sendtosplinecontrol && draw_mode>0)
+	{
+	  int point[3];
+	  for (int ia=0;ia<=2;ia++)
+	    point[ia]=int(lv[ia]);
+
+	  this->ObjectmapControl->SetPaint2DAxis(2);
+	  this->ObjectmapControl->HandleClickedPoint(point[0],point[1],point[2],nbutton,state);
+	  this->maskImageSlice->SetInput(this->maskImageRegion);
+	}
+
+      double vl=currentImage->GetScalarComponentAsDouble((int)lv[0],
+							 (int)lv[1],
+							 (int)lv[2],
+							 this->CurrentFrame);
+      int obj=(int)this->maskImageRegion->GetScalarComponentAsDouble((int)lv[0],
+								    (int)lv[1],0,0);
+
+      
+      sprintf(pxtk_buffer,"%.2f/%d (%.0f,%.0f,%.0f)",vl,obj,
+	      lv[0],lv[1],lv[2]);
+      
+      
+      statusLabel->setText(pxtk_buffer);
+          
+      UpdateDisplay();
+      return 1;
+    }
+
+  if ( nbutton!=1 && nbutton!=4 && nbutton!=7)
+    {
+      return renderer->HandleMouseButtonEvent(nbutton,state,x,y,ev);
+    }
+
+  return 0;
+  
+}
+// -------------------------------------------------------------------------
+int vtkpxGUI2DSplineObjectmapViewer::CreateObjectmapControl(PXTkFrame* fillframe)
+{
+  
+  this->ObjectmapControl=vtkpxGUI2DImageEditor::New();
+  this->ObjectmapControl->SetSimpleMode(0);
+  this->ObjectmapControl->SetObjectmapViewer(this);
+  this->ObjectmapControl->Initialize(fillframe->getWidgetName(),1);
+  this->ObjectmapControl->RenamePaintOffLabel("Spline");
+  this->ObjectmapControl->UpdateColorButtons();
+
+  PXTkFrame* extra=this->ObjectmapControl->GetExtraFrame();
+
+  PXTkButton* b1=new PXTkButton(this->EventManager,extra,"Fill In",806);  
+  PXTkButton* b2=new PXTkButton(this->EventManager,extra,"Fill Out",810);  
+  //  PXTkButton* b3=new PXTkButton(this->EventManager,extra,"Undo All",808);
+  //PXTkButton* b4=new PXTkButton(this->EventManager,extra,"Revert",802);
+  extra->addChildren("-side left -padx 1 -expand true -fill x",b1,b2);
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUI2DSplineObjectmapViewer::FillObjectmap(int new_color,int inside)
+{
+  vtkpxSplineSource* spl=this->SplineControl->GetSpline(-1);
+
+
+  int usethr=this->ObjectmapControl->GetPaintUseThresholdMode();
+
+
+  if (inside<1)
+    inside=0;
+  else
+    inside=1;
+
+
+  vtkDataArray* elements=this->ObjectmapControl->GetNextArray();
+ 
+  /*  if (inside==1 && usethr==0)
+    {
+      if (usethr==0)
+	spl->AddToObjectMap(this->maskImageRegion,0,float(n),0);
+    }
+  else
+  {*/
+     
+  vtkImageData* tmp=vtkImageData::New(); 
+  tmp->CopyStructure(maskImageRegion); 
+  tmp->SetNumberOfScalarComponents(maskImageRegion->GetNumberOfScalarComponents());
+  tmp->AllocateScalars(); 
+  tmp->GetPointData()->GetScalars()->FillComponent(0,0.0);
+  spl->AddToObjectMap(tmp,0,1.0,0);
+  
+  vtkImageData* sourceImage=currentImageRegion;
+  if (this->ObjectmapControl->GetPaintUseMaskMode())
+    sourceImage=maskImageRegion;
+  
+  double range[2];   sourceImage->GetPointData()->GetScalars()->GetRange(range);
+  float a[2];this->ObjectmapControl->GetThresholds(a);
+
+      
+  /*  vtkDataArray* src=sourceImage->GetPointData()->GetScalars();
+  vtkDataArray* mask=this->maskImageRegion->GetPointData()->GetScalars();
+  vtkDataArray* obj=tmp->GetPointData()->GetScalars();*/
+
+  int dim[3]; this->maskImageRegion->GetDimensions(dim);
+
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  int flag=int(tmp->GetScalarComponentAsDouble(i,j,k,0));
+	  double v=sourceImage->GetScalarComponentAsDouble(i,j,k,0);
+	  
+	  if (usethr==0)
+	    {
+	      if ( (inside==1 && flag==1) || (inside==0 && flag==0) )
+		{
+		  //  mask->SetComponent(i,0,float(n));
+		  this->ObjectmapControl->ChangeObjectmapValue(elements,i,j,k,new_color);
+		}
+	    }
+	  else 
+	    {
+	      if (v>=a[0] && v<=a[1])
+		{
+		  if (inside==0 && flag==0)
+		    this->ObjectmapControl->ChangeObjectmapValue(elements,i,j,k,new_color);
+		  else if (inside==1 && flag==1)
+		    this->ObjectmapControl->ChangeObjectmapValue(elements,i,j,k,new_color);
+		}
+	    }
+	}
+
+  tmp->Delete();
+  maskImageSlice->SetInput(this->maskImageRegion);
+  maskImageSlice->UpdateTexture();
+  this->UpdateDisplay();
+
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUI2DSplineObjectmapViewer::UpdateObjectmapSlice()
+{
+  if (this->ObjectmapControl!=NULL)
+    this->ObjectmapControl->UpdateFromViewer(0);
+  return 1;
+}
+
+int vtkpxGUI2DSplineObjectmapViewer::UpdateObjectmapChanges()
+{
+  // Never Extracted Nothing to do
+  if (this->LastExtractedSlice == -1 )
+    return 0;
+
+  /*  int dim[3];
+  this->maskImageRegion->GetDimensions(dim);
+  int nc=  this->maskImageRegion->GetNumberOfScalarComponents();
+  int nc2=  this->maskImage->GetNumberOfScalarComponents();*/
+  //  fprintf(stderr,"Dimensions =%d,%d,%d f=%d vs %d\n",dim[0],dim[1],dim[2],nc,nc2);
+
+  vtkpxImageReplaceSlice* repl=vtkpxImageReplaceSlice::New();
+  repl->SetInput(maskImage);
+  repl->SetInsertedSlice(maskImageRegion);
+  repl->SetCurrentPlane(this->LastExtractedOrientation);
+  repl->SetSliceNo(this->LastExtractedSlice);
+  repl->SetFrame(this->LastExtractedFrame);
+  repl->SetDeepCopyMode(0);
+  repl->Update();
+  maskImage->ShallowCopy(repl->GetOutput());
+  repl->Delete();
+  return 1;
+}
+
+void vtkpxGUI2DSplineObjectmapViewer::SetMaskImage(vtkImageData* maskimage,int orientation)
+{
+  vtkpxGUI2DImageViewer::SetMaskImage(maskimage,orientation);
+  this->ObjectmapControl->UpdateFromViewer(0);
+  this->ExecuteSliceChangeCallback();
+}
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUI2DSplineObjectmapViewer.h b/bioimagesuite30_src/GUI/vtkpxGUI2DSplineObjectmapViewer.h
new file mode 100644
index 0000000..f41ef44
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUI2DSplineObjectmapViewer.h
@@ -0,0 +1,174 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIObjectmapEditor.h,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:33 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUI2DSplineObjectmapViewer 
+// .SECTION Description
+
+#ifndef __vtkpxGUI2DSplineObjectmapViewer_h
+#define __vtkpxGUI2DSplineObjectmapViewer_h
+
+#include "vtkpxGUI2DImageViewer.h"
+#include "vtkpxGUISplineControl.h"
+#include "vtkpxGUIBaseCurveControl.h"
+#include "pxtkradiobutton.h"
+class vtkpxGUI2DImageEditor;
+
+
+class  vtkpxGUI2DSplineObjectmapViewer : public vtkpxGUI2DImageViewer {
+  
+public:
+
+  static vtkpxGUI2DSplineObjectmapViewer *New();
+  vtkTypeMacro(vtkpxGUI2DSplineObjectmapViewer,vtkpxGUI2DImageViewer);
+  
+  // Description:
+  // Initialize Display  
+  virtual char*  Initialize(const char* name,int inside);
+
+  // Description:
+  // Handle Events
+  virtual int  HandleEvent(int eventno);
+
+  // Description:
+  // Set/Get Number Of Splines 
+  virtual void SetNumberOfSplines(int a);
+  vtkGetMacro(NumberOfSplines,int);
+
+  // Description:
+  // Get Spline Control Editor 
+  vtkGetObjectMacro(SplineControl,vtkpxGUISplineControl);
+  vtkGetObjectMacro(ObjectmapControl,vtkpxGUI2DImageEditor);
+
+  // Description:
+  // Set Slice 
+  virtual void SetSlice(int sl=-1);
+
+  // Description:
+  // Set Slice and Frame
+  virtual void ChangeSliceAndFrame(int sl=-1,int fr=-1);
+
+  // Description:
+  // Enable/Disable Spline
+  void EnableSpline(int i);
+  void DisableSpline(int i);
+
+  // Description:
+  // Get Current Slice
+  virtual int GetBeginSlice();
+
+  // Description:
+  // Automation Interface
+  virtual void CreateSnake();
+  virtual void UpdateSnake();
+
+
+  // Description:
+  // Keep Auto Update Off
+  vtkSetMacro(ForceNoAutoUpdate,int);
+  vtkGetMacro(ForceNoAutoUpdate,int);
+
+  // Description;
+  // Slice Changed Callback 
+  virtual void   SetSliceChangeCallback(const char* CallbackName);
+  vtkGetMacro(EnableSliceChangeCallback,int);
+  vtkSetClampMacro(EnableSliceChangeCallback,int,0,1);
+  virtual void  ExecuteSliceChangeCallback();
+
+  
+  // Description:
+  // Handle Mouse Button Event
+  virtual int HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev);
+
+  // Description:
+  // Default Scale Mode
+  vtkSetClampMacro(DefaultScaleMode,int,0,8);
+  vtkGetMacro(DefaultScaleMode,int);
+
+
+  // Description:
+  // Set Mask Image
+  virtual void SetMaskImage(vtkImageData* maskimage,int orientation);
+  
+
+protected:
+
+  vtkpxGUI2DSplineObjectmapViewer();
+  virtual ~vtkpxGUI2DSplineObjectmapViewer();
+
+  vtkpxGUISplineControl* SplineControl;
+  vtkpxGUI2DImageEditor* ObjectmapControl;
+
+  virtual int  ResetViewer();
+
+  int NumberOfSplines;
+  int ForceNoAutoUpdate;
+
+  char*                   sliceChangeCallbackName; 
+  int                     EnableSliceChangeCallback;
+
+
+  // Objectmap Stuff
+  virtual int CreateObjectmapControl(PXTkFrame* fillframe);
+  virtual int FillObjectmap(int n,int inside=1);
+  virtual int UpdateObjectmapChanges();
+  virtual int UpdateObjectmapSlice();
+
+  int           DefaultScaleMode;
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUI4DRenderer.cpp b/bioimagesuite30_src/GUI/vtkpxGUI4DRenderer.cpp
new file mode 100644
index 0000000..90b65a4
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUI4DRenderer.cpp
@@ -0,0 +1,262 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUI4DRenderer.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxGUI4DRenderer.h"
+#include "vtkObjectFactory.h"
+#include <vtkRenderer.h>
+#include <vtkRenderWindow.h>
+#include <vtkRendererCollection.h>
+#include <vtkLight.h>
+#include <vtkLightCollection.h>
+#include "pxutil.h"
+
+vtkpxGUI4DRenderer* vtkpxGUI4DRenderer::New()
+{
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUI4DRenderer");
+  if(ret)
+      {
+	return (vtkpxGUI4DRenderer*)ret;
+      }
+  return new vtkpxGUI4DRenderer;
+}
+
+// Construct object with no children.
+vtkpxGUI4DRenderer::vtkpxGUI4DRenderer()
+{
+  this->RendererCollection=NULL;
+  this->LightCollection=NULL;
+  this->CurrentFrame=0;
+  this->NumberOfFrames=0;
+  this->ActualNumberOfFrames=0;
+}
+
+
+vtkpxGUI4DRenderer::~vtkpxGUI4DRenderer()
+{
+  // To be done later 
+}
+
+// -------------------------------------------------------------------
+
+char* vtkpxGUI4DRenderer::Initialize(const char* widgetname,vtkRenderer* ren,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+
+  vtkpxGUIRenderer::Initialize(widgetname,ren,inside);
+  
+  this->NumberOfFrames=1;
+  this->ActualNumberOfFrames=1;
+  this->CurrentFrame=0;
+
+  this->RendererCollection=vtkRendererCollection::New();
+  this->RendererCollection->AddItem(this->renderer);
+
+  this->LightCollection=vtkLightCollection::New();
+  this->LightCollection->AddItem(main_light);
+
+
+  return GetWidgetName();
+}
+/* -------------------------------------------------------------------------*/
+vtkRenderer* vtkpxGUI4DRenderer::GetRendererForFrame(int frame)
+{
+ if (this->RendererCollection==NULL)
+    return NULL;
+ 
+ frame=Irange(frame,0,this->NumberOfFrames-1);
+ return (vtkRenderer*)this->RendererCollection->GetItemAsObject(frame);
+}
+/* -------------------------------------------------------------------------*/
+vtkRendererCollection* vtkpxGUI4DRenderer::GetRendererCollection()
+{
+  return this->RendererCollection;
+}
+
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DRenderer::SetCurrentFrame(int frame)
+{
+  if (this->NumberOfFrames==0)
+    return 0;
+
+  frame=Irange(frame,0,this->NumberOfFrames-1);
+  if (frame==this->CurrentFrame)
+    return frame;
+
+  return this->SwitchFrame(frame,this->CurrentFrame,0);
+
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DRenderer::FastSetCurrentFrame(int frame)
+{
+  if (this->NumberOfFrames==0)
+    return 0;
+
+  frame=Irange(frame,0,this->NumberOfFrames-1);
+  if (frame==this->CurrentFrame)
+    return frame;
+
+  return this->SwitchFrame(frame,this->CurrentFrame,1);
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DRenderer::GetCurrentFrame()
+{
+  return this->CurrentFrame;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DRenderer:: SetNumberOfFrames(int numframes)
+{
+  if (this->NumberOfFrames==0)
+    return 0;
+
+  if (numframes==this->NumberOfFrames)
+    return numframes;
+
+  numframes=Irange(numframes,1,999);
+
+  if (numframes<=this->ActualNumberOfFrames)
+    {
+      if (this->CurrentFrame>=this->NumberOfFrames)
+	this->SwitchFrame(0,this->CurrentFrame);
+    }
+  else
+    {
+      int diff=numframes-this->ActualNumberOfFrames;
+      for (int i=0;i<diff;i++)
+	this->AddFrame();
+    }
+
+  this->NumberOfFrames=numframes;
+  return this->NumberOfFrames;
+      
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DRenderer:: GetNumberOfFrames()
+{
+  return this->NumberOfFrames;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DRenderer::PrepareForCineMode()
+{
+  int f=this->CurrentFrame;
+  int ip=f;
+  
+  for (int i=0;i<this->NumberOfFrames;i++)
+    {
+      if (i!=f)
+	ip=this->SwitchFrame(i,ip);
+    }
+  ip=this->SwitchFrame(f,ip);
+  return 1;
+  
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DRenderer::SwitchFrame(int newframe,int oldframe,int fast)
+{
+  //  fprintf(stderr,"Switchframe from %d to %d fast=%d\n",oldframe,newframe,fast);
+
+  vtkRenderer* newRenderer=(vtkRenderer*)this->RendererCollection->GetItemAsObject(newframe);
+  vtkRenderer* oldRenderer=(vtkRenderer*)this->RendererCollection->GetItemAsObject(oldframe);
+  this->CopyCamera(newRenderer->GetActiveCamera(),oldRenderer->GetActiveCamera());
+  vtkLight* newLight=(vtkLight*)this->LightCollection->GetItemAsObject(newframe);
+
+  //float vp[4],cl[3];
+  if  (fast==0)
+    {
+      vtkLight* oldLight=(vtkLight*)this->LightCollection->GetItemAsObject(oldframe);
+      newRenderer->SetViewport(oldRenderer->GetViewport());
+      newRenderer->SetBackground(oldRenderer->GetBackground());
+      newLight->DeepCopy(oldLight);
+    }
+  
+  vtkRenderWindow* renWin=oldRenderer->GetRenderWindow();
+  
+  if (renWin!=NULL)
+    {
+      vtkRendererCollection* renWinCol=oldRenderer->GetRenderWindow()->GetRenderers();
+      renWinCol->RemoveItem(oldRenderer);
+      renWin->AddRenderer(newRenderer);
+      this->renderer=newRenderer;
+      this->UpdateClippingPlanes();
+    }
+
+  this->main_light=newLight;
+
+  this->CurrentFrame=newframe;
+  return newframe;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DRenderer::AddFrame()
+{
+  if (this->RendererCollection==NULL || this->LightCollection==NULL)
+    return 0;
+
+  vtkRenderer* ren=vtkRenderer::New();
+  this->RendererCollection->AddItem(ren);
+ 
+  vtkLight* light=vtkLight::New();
+  this->LightCollection->AddItem(light);
+
+  ++this->ActualNumberOfFrames;
+  //  fprintf(stderr,"GUIRenderer:: Adding Frame Now have %d \n",this->ActualNumberOfFrames);
+
+
+  return 1; 
+}
+/* -------------------------------------------------------------------------*/
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUI4DRenderer.h b/bioimagesuite30_src/GUI/vtkpxGUI4DRenderer.h
new file mode 100644
index 0000000..fab611c
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUI4DRenderer.h
@@ -0,0 +1,121 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUI4DRenderer.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUI4DRenderer - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkpxGUI4DRenderer_h
+#define __vtkpxGUI4DRenderer_h
+
+#include "vtkpxGUIRenderer.h"
+#include "vtkRendererCollection.h"
+class vtkLightCollection;
+class vtkCamera;
+
+class  vtkpxGUI4DRenderer : public vtkpxGUIRenderer
+{
+public:
+  static vtkpxGUI4DRenderer *New();
+  vtkTypeMacro(vtkpxGUI4DRenderer,vtkpxGUIRenderer);
+  
+  // Description:
+  // Initialize Using a single renderer
+  virtual char* Initialize(const char* widgetname,vtkRenderer* firstRenderer, int inside);
+  virtual vtkRenderer* GetRendererForFrame(int frame);
+  virtual vtkRendererCollection* GetRendererCollection();
+
+  // Description:
+  // Set/Get Current Frame
+  virtual int SetCurrentFrame(int frame);
+  virtual int GetCurrentFrame();
+
+  // Description:
+  // Set/Get Number Of Frames
+  virtual int SetNumberOfFrames(int numframes);
+  virtual int GetNumberOfFrames();
+  
+  // Description:
+  // Cine Mode
+  virtual int PrepareForCineMode();
+  virtual int FastSetCurrentFrame(int frame);
+
+
+  
+protected:
+
+  vtkpxGUI4DRenderer();
+  virtual ~vtkpxGUI4DRenderer();
+  
+  vtkRendererCollection*    RendererCollection;
+  vtkLightCollection*         LightCollection;
+
+  int CurrentFrame;
+  int NumberOfFrames;
+  int ActualNumberOfFrames;
+
+  int SwitchFrame(int newframe,int oldframe,int fast=0);
+
+
+  // Description:
+  // Make Protected and Lock
+  void SetLabel(const char* text,float x,float y,float c1,float c2,float c3) {}
+
+ // Description:
+  // Create New Time Frame
+  virtual int AddFrame();
+ 
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUI4DSplineStackControl.cpp b/bioimagesuite30_src/GUI/vtkpxGUI4DSplineStackControl.cpp
new file mode 100644
index 0000000..f9ceaa2
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUI4DSplineStackControl.cpp
@@ -0,0 +1,1963 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+// 	$Id: vtkpxGUI4DSplineStackControl.cpp,v 1.2 2003/09/12 12:59:32 xenios Exp xenios $	
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkpxGUI4DSplineStackControl.h"
+#include "vtkpxUtil.h"
+#include "vtkActor.h"
+#include "vtkAssembly.h"
+#include "vtkRenderer.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxImageExtract.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkImageData.h"
+#include "vtkpxGUI4DRenderer.h"
+#include "vtkCollection.h"
+#include "vtkActorCollection.h"
+#include "vtkPolyDataWriter.h"
+#include "vtkpxTriangulatedStackSource.h"
+#include "pxchamferdistancemap.h"
+#include "pxfpbspline.h"
+#include "pxcontour.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkpxGUIBaseImageViewer.h"
+/* -------------------------------------------------------------------------*/
+vtkpxGUI4DSplineStackControl* vtkpxGUI4DSplineStackControl::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUI4DSplineStackControl");
+  if(ret)
+      {
+	return (vtkpxGUI4DSplineStackControl*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUI4DSplineStackControl;
+}
+
+// ----------------------------------------------------------------------------
+vtkpxGUI4DSplineStackControl::vtkpxGUI4DSplineStackControl()
+{
+  for (int j=0;j<SSP_MAX_RENDERERS;j++)
+    this->MultiRenderer[j]=NULL;
+  
+  this->CurrentFrame=0;
+  this->NumberOfFrames=0;
+  this->ActualNumberOfFrames=0;
+  this->splineStackCollection=NULL;
+  this->splineStackActorCollection=NULL;
+  this->do_autosave=PXTrue;
+  this->do_backup=PXTrue;
+  this->BaseViewer=NULL;
+  
+  this->dimensions[0]=-1;
+  this->AbortProcessing=-1;
+  this->optionDialog=NULL;
+}
+// ----------------------------------------------------------------------------
+vtkpxGUI4DSplineStackControl::~vtkpxGUI4DSplineStackControl()
+{
+  this->SetBaseViewer(NULL);
+
+  if (this->splineStackCollection!=NULL)
+    this->splineStackCollection->Delete();
+
+  if (this->splineStackActorCollection==NULL)
+    this->splineStackActorCollection->Delete();
+
+  // Set to NULL to avoid deleting by parent
+  for (int i=0;i<this->NumberOfSplineStacks;i++)
+    {
+      this->splineStackSet[i]=NULL;
+      for (int j=0;j<SSP_MAX_RENDERERS;j++)
+	this->splineStackActor[j][i]=NULL;
+    }
+    
+}
+// ----------------------------------------------------------------------------
+void vtkpxGUI4DSplineStackControl::InitializeSplineStacks()
+{
+  this->splineStackCollection=vtkCollection::New();
+  this->splineStackActorCollection=vtkActorCollection::New();
+
+  current_splinestack=0;
+  clipboardSplineStack=vtkpxSplineStackSource::New();
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxGUI4DSplineStackControl::ResetSplineStacks()
+{
+
+  int d[3]; double sp[3],ori[3];
+  for (int ib=0;ib<=2;ib++)
+    {
+      d[ib]=this->dimensions[ib];
+      sp[ib]=this->spacing[ib];
+      ori[ib]=this->origin[ib];
+    }
+  
+  int oldnumframes=this->NumberOfFrames;
+
+  this->NumberOfFrames=this->image->GetNumberOfScalarComponents();
+  this->image->GetSpacing(this->spacing);
+  this->image->GetOrigin(this->origin);
+  this->image->GetDimensions(this->dimensions);
+
+  //  fprintf(stderr,"Reset Spline Stacks this->Dim=%d,%d,%d\n",this->dimensions[0],this->dimensions[1],this->dimensions[2]);
+
+  this->CreateFrames(this->NumberOfFrames);
+  for (int i=1;i<this->NumberOfFrames;i++)
+    this->UpdateFrame(i);
+  this->UpdateFrame(0);
+
+
+  float sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+    sum+=
+      fabs(float(d[ia]-this->dimensions[ia]))+
+      fabs(sp[ia]-this->spacing[ia])+
+      fabs(ori[ia]-this->origin[ia]);
+
+  vtkpxSplineStackSource *stc=(vtkpxSplineStackSource*)this->splineStackCollection->GetItemAsObject(0);
+
+  if ( (stc->GetPolarMode()==0 && this->orientation==3) || (stc->GetPolarMode()==1 && this->orientation!=3))
+       sum=1.0;
+
+  if (sum>0.01)
+    {
+      float dz=spacing[2];
+      float factor=1.0;
+      if (this->orientation==3)
+	dz=180.0/float(this->dimensions[2]);
+
+	    
+      if (oldnumframes>0)
+	{
+	  int index=0;
+	  
+	  for (int f=0;f<oldnumframes;f++)
+	    for (int i=0;i<this->NumberOfSplineStacks;i++)
+	      {
+		vtkpxSplineStackSource *st=(vtkpxSplineStackSource*)this->splineStackCollection->GetItemAsObject(index);
+		++index;
+		st->SetEllipticalCylinder(8,
+					  this->dimensions[2],
+					  factor*spacing[0]*dimensions[0]/8.0*(1.0+i),
+					  factor*spacing[1]*dimensions[1]/8.0*(1.0+i),
+					  origin[0]+spacing[0]*dimensions[0]/2.0,
+					  origin[1]+spacing[1]*dimensions[1]/2.0,
+					  dz,
+					  this->origin[2]);
+		st->SetDrawMode(0);
+
+		if (this->orientation==3)
+		  {
+		    st->SetPolarMode(1);
+		    st->SetPolarMiddle(spacing[0]*dimensions[0]*0.5+origin[0]);
+		  }
+		else
+		  {
+		    st->SetPolarMode(0);
+		    if (dimensions[2]>12)
+		      {
+			st->SetTrimBottom(dimensions[2]/2-5);
+			st->SetTrimTop(dimensions[2]/2+5);
+		      }
+		    else
+		      {
+			st->SetTrimTop(dimensions[2]-1);
+			st->SetTrimBottom(0);
+		      }
+		  }
+		
+		st->SetResolutionU(2.0*spacing[1]);
+		st->SetResolutionV(spacing[2]);
+	      }
+	}
+  
+      // Get Current Spline Stack then set trims
+      trimScale[0]->setRange(0,this->dimensions[2]-1);
+      trimScale[1]->setRange(0,this->dimensions[2]-1);
+      trimScale[0]->setValue(this->currentSplineStack->GetTrimBottom());
+      trimScale[1]->setValue(this->currentSplineStack->GetTrimTop());
+      this->UpdateSplineEditor();
+    }
+
+}
+
+// ----------------------------------------------------------------------------
+void vtkpxGUI4DSplineStackControl::CreateFrames(int numframes)
+{
+
+  if (numframes<this->ActualNumberOfFrames)
+    return;
+
+  if (numframes>this->MultiRenderer[0]->GetNumberOfFrames())
+    numframes=this->MultiRenderer[0]->GetNumberOfFrames();
+  if (numframes<1)
+    numframes=1;
+
+  float dz=spacing[2];
+  float factor=1.0;
+  float cx = origin[0]+spacing[0]*dimensions[0]/2.0;
+  float cy = origin[1]+spacing[1]*dimensions[1]/2.0;
+  if (this->orientation==3)
+    {
+      dz=180.0/float(this->dimensions[2]);
+      cy=cx;
+    }
+
+  for (int fr=this->ActualNumberOfFrames;fr<numframes;fr++)
+    {
+      for (int i=0;i<this->NumberOfSplineStacks;i++)
+	{
+	  double c[3]; vtkpxSurfaceUtil::GetColor(i,c);
+	  splineStackSet[i]=vtkpxSplineStackSource::New();
+	  splineStackSet[i]->SetEllipticalCylinder(8,
+						   this->dimensions[2],
+						   factor*spacing[0]*dimensions[0]/8.0*(1.0+i),
+						   factor*spacing[1]*dimensions[1]/8.0*(1.0+i),
+						   cx,cy,
+						   dz,
+						   this->origin[2]);
+	  if (this->orientation==3)
+	    {
+	      splineStackSet[i]->SetPolarMode(1);
+	      splineStackSet[i]->SetPolarMiddle(spacing[0]*dimensions[0]*0.5+origin[0]);
+	    }
+	  else
+	    {
+	      splineStackSet[i]->SetPolarMode(0);
+	      if (dimensions[2]>12)
+		{
+		  splineStackSet[i]->SetTrimBottom(dimensions[2]/2-5);
+		  splineStackSet[i]->SetTrimTop(dimensions[2]/2+5);
+		}
+	      else
+		{
+		  splineStackSet[i]->SetTrimTop(dimensions[2]-1);
+		  splineStackSet[i]->SetTrimBottom(0);
+		}
+	    }
+		
+	  this->splineStackCollection->AddItem(splineStackSet[i]);
+	  
+	  for (int r=0;r<SSP_MAX_RENDERERS;r++)
+	    {
+	      splineStackActor[r][i]=vtkActor::New();
+	      splineStackActor[r][i]->GetProperty()->SetColor(c);
+	      this->splineStackActorCollection->AddItem(splineStackActor[r][i]);
+	      
+	      if (this->MultiRenderer[r]!=NULL)
+		{
+		  vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+		  map->SetInput(splineStackSet[i]->GetOutput());
+		  
+		  splineStackActor[r][i]->SetMapper(map);
+		  if (display_mode[i]!=0)
+		    splineStackActor[r][i]->SetVisibility(1);
+		  else
+		    splineStackActor[r][i]->SetVisibility(0);
+		  
+		  if (wireframemode[r]==1)
+		    {
+		      splineStackActor[r][i]->GetProperty()->SetRepresentationToWireframe();
+		      splineStackActor[r][i]->GetProperty()->SetLineWidth(2.0);
+		      splineStackActor[r][i]->GetProperty()->SetAmbient(1.0);
+		      splineStackActor[r][i]->GetProperty()->SetDiffuse(0.0);
+		      splineStackActor[r][i]->GetProperty()->SetSpecular(0.0);
+		    }
+		  map->Delete();
+		  this->MultiRenderer[r]->GetRendererForFrame(fr)->AddActor(splineStackActor[r][i]);
+		}
+	    }
+	}
+      if (fr==0)
+	{
+	  current_splinestack=0;
+	  currentSplineStack=splineStackSet[current_splinestack];
+	}
+    }
+
+  this->ActualNumberOfFrames=numframes;
+
+  
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DSplineStackControl::UpdateFrame(int frame)
+{
+
+  if (frame>=this->ActualNumberOfFrames)
+    return;
+  
+  // Image Slice Ortho Slice First 
+  int index=frame*this->NumberOfSplineStacks;
+  int index2=index*SSP_MAX_RENDERERS;
+
+  //  fprintf(stderr,"Index=%d index2=%d\n",index,index2);
+  for (int i=0;i<this->NumberOfSplineStacks;i++)
+    {
+      splineStackSet[i]=(vtkpxSplineStackSource*)this->splineStackCollection->GetItemAsObject(index);
+      ++index;
+      for (int r=0;r<SSP_MAX_RENDERERS;r++)
+	{
+	  splineStackActor[r][i]=(vtkActor*)this->splineStackActorCollection->GetItemAsObject(index2);
+	  ++index2;
+	}
+    }
+
+  //fprintf(stderr,"Final Index=%d index2=%d\n",index,index2);
+
+  for (int r=0;r<SSP_MAX_RENDERERS;r++)
+    {
+      if (this->MultiRenderer[r]!=NULL)
+	this->Renderer[r]=this->MultiRenderer[r]->GetRendererForFrame(frame);
+    }
+
+  //  fprintf(stderr,"Done Updating %d\n",frame);
+
+}
+// -------------------------------------------------------------------------
+void vtkpxGUI4DSplineStackControl::ChangeFrame(int newframe)
+{
+
+  newframe=Irange(newframe,0,this->NumberOfFrames-1);
+  if (newframe==this->CurrentFrame)
+    return;
+
+  this->SplineEditor->SetEnableAutoUpdateModeCallback(0);
+  // Check for Auto Update and execute it before frame changes 
+  if (this->SplineEditor->IsAutoUpdateModeEnabled()==1)
+    {
+      this->UpdateFromSplineEditor();
+    }
+
+
+  int trim_bot[SSP_MAX_COLLECTIONS];
+  int trim_top[SSP_MAX_COLLECTIONS];
+  int draw_mode[SSP_MAX_COLLECTIONS];
+  int ia=0;
+  for (ia=0;ia<this->NumberOfSplineStacks;ia++)
+    {
+      trim_bot[ia]=splineStackSet[ia]->GetTrimBottom();
+      trim_top[ia]=splineStackSet[ia]->GetTrimTop();
+      draw_mode[ia]=splineStackSet[ia]->GetDrawMode();
+    }
+
+  this->UpdateFrame(newframe); 
+
+  for (ia=0;ia<this->NumberOfSplineStacks;ia++)
+    {
+      splineStackSet[ia]->SetTrimBottom(trim_bot[ia]);
+      splineStackSet[ia]->SetTrimTop(trim_top[ia]);
+      splineStackSet[ia]->SetDrawMode(draw_mode[ia]);
+      if (display_mode[ia]==1 && splineStackSet[ia]->GetWholeSurface()==1)
+	splineStackSet[ia]->SetWholeSurface(0);
+      if (display_mode[ia]==2 && splineStackSet[ia]->GetWholeSurface()==0)
+	splineStackSet[ia]->SetWholeSurface(1);
+    }
+
+  this->currentSplineStack=splineStackSet[current_splinestack];
+  this->CurrentFrame=newframe;
+  this->UpdateSplineEditor();
+
+  this->SplineEditor->SetEnableAutoUpdateModeCallback(1);
+  this->Update();
+}
+// -------------------------------------------------------------------------
+
+char* vtkpxGUI4DSplineStackControl::Initialize(const char* name,int inside)
+{
+  return this->Initialize(name,name,name,inside);
+}
+
+char* vtkpxGUI4DSplineStackControl::Initialize(const char* name,const char* name2,const char* name3,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+
+  vtkpxGUISplineStackControl::Initialize(name,inside);
+
+  //  fprintf(stderr,"name=%s,name2=%s,name3=%s\n",name,name2,name3);
+
+  PXTkLabelFrame* mFrame=NULL;
+  if (strcmp(name,name2)==0)
+    {
+      mFrame=new PXTkLabelFrame(this->EventManager,this->controlFrame,"Multi Frame");
+      this->controlFrame->addChildren("-side top -expand false -fill x -padx 1 -pady 2",mFrame);
+    }
+  else
+    {
+      PXTkFrame* m=new PXTkFrame(NULL,name2);
+      mFrame=new PXTkLabelFrame(this->EventManager,m,"Multi Frame");
+      m->addChildren("-side top -expand false -fill x -padx 1 -pady 2",mFrame);
+    }
+  mFrame->setPackMode(PXTrue);
+
+
+  PXTkFrame* segmentFrame=NULL;
+  if (strcmp(name,name3)==0)
+    {
+      segmentFrame=new PXTkFrame(this->EventManager,this->controlFrame);
+      this->controlFrame->addChildren("-side top -expand false -fill x -padx 1 -pady 2",segmentFrame);
+    }
+  else
+    {
+      PXTkFrame* m=new PXTkFrame(NULL,name3);
+      segmentFrame=new PXTkFrame(this->EventManager,m);
+      m->addChildren("-side top -expand false -fill x -padx 1 -pady 2",segmentFrame);
+    }
+  segmentFrame->setPackMode(PXTrue);
+
+
+  PXTkFrame* f1=new PXTkFrame(this->EventManager,mFrame);
+  PXTkFrame* f2=new PXTkFrame(this->EventManager,mFrame);
+  PXTkFrame* f3=new PXTkFrame(this->EventManager,mFrame);
+  PXTkFrame* f4=new PXTkFrame(this->EventManager,mFrame);
+  mFrame->addChildren("-side top -expand false -fill x -pady 2 ",f1,f2,f3,f4);
+
+ 
+  PXTkLabel* labs=new PXTkLabel(this->EventManager,f1,"Current Stack:");
+  currentCollection2=new PXTkOptionMenu(this->EventManager,f1,"Stack 1",800);
+  for (int ip=1;ip<this->NumberOfSplineStacks;ip++)
+    {
+      sprintf(pxtk_buffer4,"Stack %d",ip+1);
+      currentCollection2->addOption(pxtk_buffer4);
+    }
+  currentCollection2->setIndex(current_splinestack);
+  f1->addChildren("-side left -expand t -fill x -pady 1",labs,currentCollection2);
+    
+  PXTkButton* b0a=new PXTkButton(this->EventManager,f2,"Load All",801);
+  PXTkButton* b0b=new PXTkButton(this->EventManager,f2,"Save All",802);
+  f2->addChildren("-side top -expand t -fill x -pady 1 -padx 2",b0a,b0b);
+
+  autosavebutton=new PXTkCheckButton(this->EventManager,f3,"Autosave",803);
+  autosavebutton->setState(do_autosave);
+  backupbutton=new PXTkCheckButton(this->EventManager,f3,"Backup",803);
+  backupbutton->setState(do_backup);
+  f3->addChildren("-side top -expand t -fill x -pady 1",autosavebutton,backupbutton);
+
+  f4->setPackMode(PXTrue);
+
+  PXTkButton* but1=new PXTkButton(this->EventManager,f4,"Shift And Scale",810);
+  PXTkButton* but3=new PXTkButton(this->EventManager,f4,"Volume",812);
+  PXTkButton* but4=new PXTkButton(this->EventManager,f4,"Cylinders",813);
+  PXTkButton* but6=new PXTkButton(this->EventManager,f4,"Export",815);
+  PXTkButton* but7=new PXTkButton(this->EventManager,f4,"Extract From (Binary) Image",816);
+  f4->addChildren("-side top -expand t -fill x -pady 1",but1,but3,but4);
+  f4->addChildren("-side top -expand t -fill x -pady 1",but6,but7);
+
+  this->CreateSegmentationControl(segmentFrame);
+
+  if (this->optionDialog==NULL)
+    this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,10);
+
+
+  return GetWidgetName();
+}
+
+/* -------------------------------------------------------------------------*/ 
+void vtkpxGUI4DSplineStackControl::SetRenderer(vtkRenderer* ren,int index)
+{
+  vtkErrorMacro(<<"Cannot Use this Function in vtkpxGUI4DSplineStackControl");
+}
+
+void vtkpxGUI4DSplineStackControl::SetRenderer(vtkpxGUI4DRenderer* ren,int index)
+{
+  this->SetRenderer(ren,index,0);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DSplineStackControl::SetRenderer(vtkRenderer *ren,int index,int wireframe)
+{
+  vtkErrorMacro(<<"Cannot Use this Function in vtkpxGUI4DSplineStackControl");
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DSplineStackControl::SetRenderer(vtkpxGUI4DRenderer *ren,int index,int wireframe)
+{
+  index=Irange(index,0,SSP_MAX_RENDERERS-1);
+
+  if (this->MultiRenderer[index]!=NULL)
+    return;
+
+  this->MultiRenderer[index]=ren;
+  this->wireframemode[index]=wireframe;
+  this->Renderer[index]=this->MultiRenderer[index]->GetRendererForFrame(this->CurrentFrame);
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DSplineStackControl::Update()
+{
+  vtkpxGUISplineStackControl::Update();
+  UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DSplineStackControl::UpdateDisplay()
+{
+  vtkpxGUISplineStackControl::UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+
+int  vtkpxGUI4DSplineStackControl::HandleEvent(int event)
+{
+  if (!this->Initialized)
+      return TCL_OK;
+
+  //  fprintf(stderr,"Event=%d\n",event);
+
+  if (event<10)
+      return this->EventManager->handleDirectEvent(event);
+
+  if (event<800)
+    return vtkpxGUISplineStackControl::HandleEvent(event);
+
+  int updateeditor=0;
+
+  //  fprintf(stderr,"Switching to Event=%d Part I\n",event);
+
+  if (this->NumberOfFrames==0)
+    return TCL_OK;
+
+
+  //  fprintf(stderr,"Switching to Event=%d\n",event);
+
+  switch (event)
+    {
+    case 800:
+      SetCurrentCollection(currentCollection2->getIndex());
+      break;
+
+    case 801:
+      if (this->NumberOfFrames>0)
+	{
+	  char* line=this->EventManager->getOpenFilename("Load series","Series","*.01.sur");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		updateeditor=(this->MultiLoad(line)>0);
+	    }
+	}
+      break;
+
+    case 802:
+      if (this->NumberOfFrames>0)
+	{
+	  sprintf(pxtk_buffer,"%s.01.sur",surface_filename[current_splinestack]);
+	  char* line=this->EventManager->getSaveFilename("Save series",pxtk_buffer,"Series","*.01.sur");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		{
+		  char *newline=new char[strlen(line)+1 ];
+		  strcpy(newline,line);
+		  //		  fprintf(stderr,"Multi Save %s\n",newline);
+		  this->MultiSave(newline);
+		  delete [] newline;
+		}
+	    }
+	}
+      break;
+
+    case 803:
+      do_autosave=autosavebutton->getState();
+      do_backup=backupbutton->getState();
+      break;
+
+    case 810:
+      this->DoShiftScale(0,850);
+      break;
+    
+    case 811:
+      this->DoResample(0,852);
+      break;
+    
+    case 812:
+      //      fprintf(stderr,"Doing nothing for 812\n");
+      this->DoVolume(0,854);
+      break;
+    
+    case 813:
+      //      fprintf(stderr,"Option=813\n");
+      this->DoCylinders(0,856);
+      break;
+    
+    case 814:
+      this->DoSmoothApex(0,858);
+      break;
+    
+    case 815:
+      this->DoExport(0,860);
+      break;
+
+    case 816:
+      this->DoImport(0,864);
+      break;
+
+    case 850:
+      this->DoShiftScale(1);
+      updateeditor=1;
+      break;
+    
+    case 852:
+      this->DoResample(1);
+      updateeditor=1;
+      break;
+    
+    case 854:
+      this->DoVolume(1);
+      updateeditor=1;
+      break;
+    
+    case 856:
+      this->DoCylinders(1);
+      updateeditor=1;
+      break;
+    
+    case 858:
+      this->DoSmoothApex(1);
+      updateeditor=1;
+      break;
+    
+    case 860:
+      this->DoExport(1);
+      updateeditor=1;
+      break;
+    
+    case 862:
+      this->DoExport(2);
+      updateeditor=1;
+      break;
+
+    case 864:
+      this->DoImport(1,864);
+      updateeditor=1;
+      break;
+
+    case 900:
+      this->AutoSegmentMode=1;
+      this->AutoSegment();
+      break;
+
+    case 901:
+      this->AutoSegmentMode=0;
+      this->AutoSegment();
+      break;
+
+    case 902:
+      this->InterpolateSpatially();
+      break;
+      
+    case 903:
+    case 904:
+    case 905:
+    case 906:
+      this->AutoTemporalVolumeSegment(event-903);
+      break;
+      
+    case 908:
+      this->InterpolateTemporally(0);
+      break;
+
+    case 909:
+      this->InterpolateTemporally(1);
+      break;
+      
+
+    case 910:
+      this->AbortProcessing=1;
+      break;
+    }
+  
+  //  fprintf(stderr,"Done %d\n",event);
+
+
+  if (updateeditor==1 && this->BlockEditorCallback==0)
+    this->UpdateSplineEditor();
+
+
+  this->UpdateDisplay();
+
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DSplineStackControl::SetImage(vtkImageData* img,int orient,int level,int frame)
+{
+  this->BlockEditorCallback=1;
+
+  this->orientation=vtkpxGUIBaseImageViewer::MapOrientationToOldStyle(orient);
+
+  if (img!=NULL)  
+    this->SetImage(img);
+  this->SetCurrentFrame(frame);
+  this->BlockEditorCallback=0;
+
+}
+
+
+void vtkpxGUI4DSplineStackControl::SetCurrentCollection(int num)
+{
+  if (!this->Initialized)
+    return;
+  vtkpxGUISplineStackControl::SetCurrentCollection(num);
+  currentCollection2->setIndex(current_splinestack);
+  currentCollection->setIndex(current_splinestack);
+}
+
+void vtkpxGUI4DSplineStackControl::SetImage(vtkImageData* img)
+{
+  if (img==NULL)
+    return;
+
+  if (this->image!=NULL)
+    this->image->Delete();
+  this->image=vtkImageData::New();
+  this->image->ShallowCopy(img);      
+  
+  if (this->SplineEditor!=NULL)
+    {
+      this->SplineEditor->SetImage(this->image,this->orientation);
+      this->SplineEditor->ShowFrameControls(0);
+      this->SplineEditor->SetSlice(-1);
+    }
+
+  this->ResetSplineStacks();
+
+
+  if (this->NumberOfFrames<2)
+    {
+      toggle_past->configure("-state","disabled");
+      toggle_future->configure("-state","disabled");
+    } 
+  else 
+    {
+      toggle_past->configure("-state","normal");
+      toggle_future->configure("-state","normal");
+    }
+
+  if (this->image->GetDimensions()[2]<2)
+    {
+      toggle_up->configure("-state","disabled");
+      toggle_down->configure("-state","disabled");
+    } 
+  else 
+    {
+      toggle_up->configure("-state","normal");
+      toggle_down->configure("-state","normal");
+    }
+
+  for (int ia=0;ia<=1;ia++)
+    {
+      frameScale[ia]->setRange(1,this->NumberOfFrames);
+      frameScale[ia]->setValue(1+ia*(this->NumberOfFrames-1));
+      sliceScale[ia]->setRange(0,this->image->GetDimensions()[2]-1);
+      sliceScale[ia]->setValue(ia*(this->image->GetDimensions()[2]-1));
+    }
+
+
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DSplineStackControl::MultiLoad(const char* fname)
+{
+  strcpy(pxtk_buffer2,fname);
+
+  char* noext1=nothisextension(fname,".sur");
+  char* noext2=nothisextension(noext1,".01");
+  int sum=0;
+
+  for (int frame=0;frame<this->NumberOfFrames;frame++)
+    {
+      sprintf(pxtk_buffer3,"%s.%02d.sur",noext2,frame+1);
+      vtkpxSplineStackSource *stack=this->GetSplineStack(frame,current_splinestack);
+      int ok=stack->Load(pxtk_buffer3);
+
+      stack->AdjustNumberOfSplines(this->dimensions[2]);
+      sum+=(1-ok);
+      sprintf(pxtk_buffer,"Loading from %s (status=%d)\n",pxtk_buffer3,ok);
+      PXTkApp::printToConsole(pxtk_buffer);
+
+      if (ok>0 && frame==0)
+	{
+	  sprintf(pxtk_buffer3,"%s",noext2);
+	  this->SetItemFilename(current_splinestack,pxtk_buffer3);
+	  sprintf(pxtk_buffer4,"%s.%d",PXTkApp::getFilenameTail(noext2),current_splinestack+1);
+	  currentCollection2->changeLabel(current_splinestack,pxtk_buffer4);
+	}
+
+    }
+
+  if (sum<this->NumberOfFrames)
+    {
+      delete [] surface_filename[current_splinestack];
+      surface_filename[current_splinestack]=new char[strlen(noext2)+1];
+      strcpy(surface_filename[current_splinestack],noext2);
+    }
+
+  if (sum>0)
+    PXTkApp::popupConsole();
+      
+  delete [] noext2;
+  delete [] noext1;
+  this->UpdateAfterExternalEditing();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DSplineStackControl::UpdateAfterExternalEditing()
+{
+  //  fprintf(stderr,"In 4D SSC:: UpdateAfterExternalEditing");
+  this->UpdateFrame(this->CurrentFrame);
+  this->UpdateControlsFromCurrentSplineStack();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DSplineStackControl::MultiSave(const char* fname)
+{
+  //  fprintf(stderr,"fname=%s\n",fname);
+  char* noext1=nothisextension(fname,".sur");
+  //  fprintf(stderr,"noext1=%s\n",noext1);
+  char* noext2=nothisextension(noext1,".01");
+  //  fprintf(stderr,"noext2=%s\n",noext2);
+  int sum=0;
+
+  if (this->do_backup==PXTrue)
+    this->DoBackup(current_splinestack,noext2);
+
+  for (int frame=0;frame<this->NumberOfFrames;frame++)
+    {
+      sprintf(pxtk_buffer3,"%s.%02d.sur",noext2,frame+1);
+      vtkpxSplineStackSource *stack=this->GetSplineStack(frame,current_splinestack);
+      int ok=stack->Save(pxtk_buffer3);
+      sum+=(1-ok);
+      sprintf(pxtk_buffer,"Saving to %s (status=%d)\n",pxtk_buffer3,ok);
+      PXTkApp::printToConsole(pxtk_buffer);
+      //fprintf(stderr,"%s\n",pxtk_buffer);
+
+      if (ok>0 && frame==0)
+	{
+	  sprintf(pxtk_buffer3,"%s",noext2);
+	  this->SetItemFilename(current_splinestack,pxtk_buffer3);
+	  sprintf(pxtk_buffer4,"%s.%d",PXTkApp::getFilenameTail(noext2),current_splinestack+1);
+	  currentCollection2->changeLabel(current_splinestack,pxtk_buffer4);
+	}
+    }
+  
+
+
+  if (sum>0)
+    PXTkApp::popupConsole();
+
+  if (sum<this->NumberOfFrames)
+    {
+      delete [] surface_filename[current_splinestack];
+      surface_filename[current_splinestack]=new char[strlen(noext2)+1];
+      strcpy(surface_filename[current_splinestack],noext2);
+    }
+
+      
+  //  fprintf(stderr,"Here on to cleanup\n");
+
+  delete [] noext2;
+  delete [] noext1;
+
+  //  fprintf(stderr,"Here on to screen update\n");
+
+  this->UpdateAfterExternalEditing();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DSplineStackControl::DoBackup(int stackindex,const char* rootname)
+{
+  stackindex=Irange(stackindex,0,this->NumberOfSplineStacks-1);
+  //  fprintf(stderr,"Beginning Do Backup %d %s\n",stackindex,rootname);
+  
+  for (int ia=0;ia<this->NumberOfFrames;ia++)
+    {
+      sprintf(pxtk_buffer,"%s.%02d.sur",rootname,ia+1);
+      PXTkApp::fileOperation("exists",pxtk_buffer,NULL);
+      int ok=PXTkApp::getTclIntResult();
+      //      fprintf(stderr,"pxtk_buffer=%s, %d\n",pxtk_buffer,ok);
+
+      if (ok==1)
+	{
+	  sprintf(pxtk_buffer,"%s.%02d.sur",rootname,ia+1);
+	  sprintf(pxtk_buffer2,"%s_back.%02d.sur",rootname,ia+1);
+	  sprintf(pxtk_buffer3,"File %s exists copying to %s\n",pxtk_buffer,pxtk_buffer2);
+	  PXTkApp::printToConsole(pxtk_buffer3);
+	  PXTkApp::copyFile(pxtk_buffer,pxtk_buffer2);
+	}
+    }
+  return 1;
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DSplineStackControl::DoAutosave(int frame)
+{
+  frame=Irange(frame,0,this->NumberOfFrames-1);
+  for (int i=0;i<this->NumberOfSplineStacks;i++)
+    {
+      vtkpxSplineStackSource *stack=this->GetSplineStack(frame,i);
+      sprintf(pxtk_buffer,"%s_auto.%02d.sur",surface_filename[i],frame+1);
+      stack->Save(pxtk_buffer);
+    }
+  return 1;
+}
+
+
+/* -------------------------------------------------------------------------*/
+vtkpxSplineStackSource* vtkpxGUI4DSplineStackControl::GetSplineStack(int frame,int index)
+{
+  if (this->splineStackCollection==NULL)
+    return NULL;
+
+  frame=Irange(frame,0,this->NumberOfFrames-1);
+  index=Irange(index,0,this->NumberOfSplineStacks);
+
+  int ind=frame*this->NumberOfSplineStacks+index;
+  return (vtkpxSplineStackSource*)this->splineStackCollection->GetItemAsObject(ind);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DSplineStackControl::UpdateSplineEditor()
+{
+  if (this->SplineEditor==NULL)
+    return;
+  if (this->SplineEditor->GetCurrentFrame()!=this->CurrentFrame)
+    this->SplineEditor->SetCurrentFrame(this->CurrentFrame);
+
+  int fr[2];
+  fr[0]=this->CurrentFrame-1;
+  if (fr[0]<0)
+    fr[0]=this->NumberOfFrames-1;
+  fr[1]=this->CurrentFrame+1;
+  if (fr[1]>=this->NumberOfFrames)
+    fr[1]=0;
+
+  int sl=this->SplineEditor->GetBeginSlice();
+  int num=this->GetNumberOfSplineStacks();
+
+  for (int j=0;j<2;j++)  
+    for (int i=0;i<num;i++)
+      {
+	vtkpxSplineStackSource *stack=this->GetSplineStack(fr[j],i);
+	vtkpxSplineSource* spl=this->SplineEditor->GetSplineControl()->GetGhostSpline(j,i);
+	if (spl!=NULL)
+	  {
+	    stack->SetSplineFromSplineStack(spl,sl);
+	    spl->Modified();
+	  }
+      }
+        
+  vtkpxGUISplineStackControl::UpdateSplineEditor();
+ 
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DSplineStackControl::SetCurrentFrame(int t)
+{
+  if (t<0) 
+    t=this->NumberOfFrames-1;
+  if (t>this->NumberOfFrames-1)
+    t=0;
+
+
+  if (!this->Initialized)
+    return;
+
+  //  fprintf(stderr,"Changing Frame to %d\n",t);
+  
+
+  this->ChangeFrame(t);
+  this->UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DSplineStackControl::GetCurrentFrame()
+{
+  return this->CurrentFrame;
+}
+
+int vtkpxGUI4DSplineStackControl::GetNumberOfFrames()
+{
+  return this->NumberOfFrames;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DSplineStackControl::UpdateFromSplineEditor()
+{
+  vtkpxGUISplineStackControl::UpdateFromSplineEditor();
+  if (this->do_autosave==PXTrue)
+    this->DoAutosave(this->CurrentFrame);
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DSplineStackControl::DoShiftScale(int mode,int moption)
+{
+  if (mode==0)
+    {
+      if (this->optionDialog!=NULL)
+	{
+	  if (this->optionDialog->isOpen())
+	    return;
+	  delete this->optionDialog;
+	}
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,6);
+      this->optionDialog->initDisplay();
+
+      this->optionDialog->setTitleDescription("Shift+Scale Surface",
+					      "Enter Multipliers to Shift and Scale the Surfaces");
+      this->optionDialog->setfoption(0,"Shift-X","%.1f",0.0);
+      this->optionDialog->setfoption(2,"Shift-Y","%.1f",0.0);
+      this->optionDialog->setfoption(4,"Shift-Z","%.1f",0.0);
+      this->optionDialog->setfoption(1,"Scale-X","%.1f",this->spacing[0]);
+      this->optionDialog->setfoption(3,"Scale-Y","%.1f",this->spacing[1]);
+      this->optionDialog->setfoption(5,"Scale-Z","%.1f",this->spacing[2]/this->currentSplineStack->GetZSpacing());
+      this->optionDialog->setMenuOption(moption);
+      this->optionDialog->popupDialog();
+    }
+
+  if (mode==1)
+    {
+      double sh[3],sc[3];
+      for (int ia=0;ia<=2;ia++)
+	{
+	  sh[ia]=Frange(this->optionDialog->getfoption(ia*2)  ,-100.0,100.0);
+	  sc[ia]=Frange(this->optionDialog->getfoption(ia*2+1),   0.1, 10.0);
+	}
+     
+      /*fprintf(stderr,"Shifts %.1f %.1f %.1f\t scales=%.1f %.1f %.1f\n",
+	sh[0],sh[1],sh[2],sc[0],sc[1],sc[2]);*/
+      for (int frame=0;frame<this->NumberOfFrames;frame++)
+	{
+	  vtkpxSplineStackSource *stack=this->GetSplineStack(frame,current_splinestack);
+	  stack->ScaleShiftXY(sh[0],sh[1],sc[0],sc[1]);
+	  stack->ScaleShiftZ(sh[2],sc[2]);
+	  //fprintf(stderr,"Processed frame=%d/%d\n",frame+1,this->NumberOfFrames);
+	}
+      
+      this->UpdateAfterExternalEditing();
+    }
+      
+      
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DSplineStackControl::DoResample(int mode,int moption)
+{
+  if (mode==0)
+    {
+      if (this->optionDialog!=NULL)
+	{
+	  if (this->optionDialog->isOpen())
+	    return;
+	  delete this->optionDialog;
+	}
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,2);
+      this->optionDialog->initDisplay();
+      
+      this->optionDialog->setTitleDescription("Resample Surfaces",
+					      "Enter npoints=-1 for auto-spacing");
+      this->optionDialog->setioption(0,"Points","%d",-1);
+      this->optionDialog->setfoption(1,"Smoothness","%.1f",2.0);
+      this->optionDialog->setMenuOption(moption);
+      this->optionDialog->popupDialog();
+      return;
+    }
+
+  if (mode==1)
+    {
+      int np=Irange(this->optionDialog->getioption(0),3,50);
+      if (np==3)
+	np=-1;
+      float ds=Frange(this->optionDialog->getfoption(1),1.0,20.0);
+      
+      for (int frame=0;frame<this->NumberOfFrames;frame++)
+	{
+	  //fprintf(stderr,"Processing frame=%d\n",frame);
+	  vtkpxSplineStackSource *stack=this->GetSplineStack(frame,current_splinestack);
+	  stack->ChangeSpacing(ds,np,0.01);
+	}
+      
+      this->UpdateAfterExternalEditing();
+    }
+
+      
+
+}
+
+void vtkpxGUI4DSplineStackControl::DoVolume(int mode,int moption)
+{
+
+  //  fprintf(stderr,"in Volume mode=%d moption=%d\n",mode,moption);
+
+  if (mode==0)
+    {
+      //      fprintf(stderr,"in Volume mode=%d moption=%d\n",mode,moption);
+
+      if (this->optionDialog!=NULL)
+	{
+	  //	  fprintf(stderr,"Should I delete optionDialog\n");
+	  if (this->optionDialog->isOpen())
+	    return;
+	  //	  fprintf(stderr,"Deleting optionDialog\n");
+	  delete this->optionDialog;
+	}
+      //      fprintf(stderr,"Creating optionDialog\n");
+
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,2);
+      this->optionDialog->initDisplay();
+
+      this->optionDialog->setTitleDescription("Volume Computation",
+					      "compute volume in mm3");
+      this->optionDialog->setioption(0,"Begin Frame","%d",1);
+      this->optionDialog->setioption(1,"End   Frame","%d",this->NumberOfFrames);
+      this->optionDialog->setMenuOption(moption);
+      this->optionDialog->popupDialog();
+    }
+
+  if (mode==1)
+    {
+      int bframe=Irange(this->optionDialog->getioption(0),1,this->NumberOfFrames);
+      int eframe=Irange(this->optionDialog->getioption(1),1,this->NumberOfFrames);
+      bframe-=1;
+      eframe-=1;
+      if (eframe<bframe)
+	eframe+=this->NumberOfFrames;
+      PXTkApp::popupConsole();
+      PXTkApp::printToConsole("\n Computing Volumes For Surfaces\n------------------------\n");
+      int minf=bframe,maxf=bframe;
+      float minv=0.0,maxv=0.0;
+      for (int frame=bframe;frame<=eframe;frame++)
+	{
+	  int fr=frame;
+	  if (frame>=this->NumberOfFrames)
+	    fr-=this->NumberOfFrames;
+	  vtkpxSplineStackSource *stack=this->GetSplineStack(fr,current_splinestack);
+	  float a=stack->GetVolume();
+
+	  if (frame==bframe)
+	    {
+	      minv=a;
+	      maxv=a;
+	    }
+	  else if (a<minv)
+	    {
+	      minv=a;
+	      minf=fr;
+	    }
+	  else if (a>maxv)
+	    {
+	      maxv=a;
+	      maxf=fr;
+	    }
+
+	  sprintf(pxtk_buffer,"Surface %d frame %2d volume=%.2f\n",current_splinestack+1,fr+1,a);
+	  PXTkApp::printToConsole(pxtk_buffer);
+	}
+      
+      sprintf(pxtk_buffer,"\nLargest  Volume at frame %d = %.2f\n",maxf+1,maxv);
+      PXTkApp::printToConsole(pxtk_buffer);
+      sprintf(pxtk_buffer,"Smallest Volume at frame %d = %.2f\n\n",minf+1,minv);
+      PXTkApp::printToConsole(pxtk_buffer);
+
+    }
+
+
+}
+
+void vtkpxGUI4DSplineStackControl::DoCylinders(int mode,int moption)
+{
+
+  if (mode==0)
+    {
+      if (this->optionDialog!=NULL)
+	{
+	  if (this->optionDialog->isOpen())
+	    return;
+	  delete this->optionDialog;
+	}
+
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,7);
+      this->optionDialog->initDisplay();
+
+      this->optionDialog->setTitleDescription("Set Cylinders",
+					      "Enter Cylinder Parameters");
+      this->optionDialog->setfoption(0,"Center X","%.2f",this->origin[0]+this->dimensions[0]*this->spacing[0]*0.5);
+      this->optionDialog->setfoption(2,"Center Y","%.2f",this->origin[1]+this->dimensions[1]*this->spacing[1]*0.5);
+      this->optionDialog->setfoption(1,"Radius X","%.2f",this->dimensions[0]*this->spacing[0]*0.2);
+      this->optionDialog->setfoption(3,"Radius Y","%.2f",this->dimensions[1]*this->spacing[1]*0.2);
+      this->optionDialog->setioption(4,"Bot Slice","%d",0);
+      this->optionDialog->setioption(5,"Top Slice","%d",this->dimensions[2]-1);
+      this->optionDialog->setioption(6,"Num points","%d",8);
+      this->optionDialog->setMenuOption(moption);
+      this->optionDialog->popupDialog();
+      return;
+    }
+
+
+  if (mode==1)
+    {
+      float c[2],r[2];
+      for (int ia=0;ia<=1;ia++)
+	{
+	  c[ia]=Frange(this->optionDialog->getfoption(ia*2),
+		       this->origin[ia],this->origin[ia]+this->dimensions[ia]*this->spacing[ia]);
+	  r[ia]=Frange(this->optionDialog->getfoption(ia*2+1),
+		       this->spacing[ia],0.5*+this->dimensions[ia]*this->spacing[ia]);
+	}
+      
+      
+      int numsl=this->dimensions[2];
+      float bottomz=this->origin[2];
+      float zsp=this->spacing[2];
+      int nump=Irange(this->optionDialog->getioption(6),4,24);
+      int minz=Irange(this->optionDialog->getioption(4),0,this->dimensions[2]-2);
+      int maxz=Irange(this->optionDialog->getioption(5),minz,this->dimensions[2]-2);
+      
+      for (int frame=0;frame<this->NumberOfFrames;frame++)
+	{
+	  vtkpxSplineStackSource *stack=this->GetSplineStack(frame,current_splinestack);
+	  stack->SetEllipticalCylinder(nump,numsl,r[0],r[1],c[0],c[1],zsp,bottomz);
+	  //	  fprintf(stderr,"Do Cylinders :: Setting Elliptical Cylinder f=%d\n",frame);
+	  stack->SetTrimBottom(minz);
+	  stack->SetTrimTop(maxz);
+	}
+    
+      this->UpdateAfterExternalEditing();
+      
+      char line[100];
+      strcpy(line,"CStack.sur");
+      this->SetItemFilename(current_splinestack,line);
+      sprintf(line,"CStack.%d",current_splinestack+1);
+      currentCollection2->changeLabel(current_splinestack,line);
+      
+
+    }
+
+}
+void vtkpxGUI4DSplineStackControl::DoSmoothApex(int mode,int moption)
+{
+  if (mode==0)
+    {
+      if (this->optionDialog!=NULL)
+	{
+	  if (this->optionDialog->isOpen())
+	    return;
+	  delete this->optionDialog;
+	}
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,3);
+      this->optionDialog->initDisplay();
+      this->optionDialog->setTitleDescription("Smooth Apex",
+					      "Smooth Apex");
+      this->optionDialog->setioption(0,"Begin Frame","%d",1);
+      this->optionDialog->setioption(1,"End   Frame","%d",this->NumberOfFrames);
+      this->optionDialog->setfoption(2,"Smooth Sigma","%.1f",1.0);
+      this->optionDialog->setMenuOption(moption);
+      this->optionDialog->popupDialog();
+    }
+
+
+}
+
+
+// --------------------------------------------------------------------------
+
+
+void vtkpxGUI4DSplineStackControl::DoExport(int mode,int moption)
+{
+  if (mode==0)
+    {
+      if (this->optionDialog->isOpen())
+	return;
+
+      delete this->optionDialog;
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,7);
+      this->optionDialog->initDisplay();
+      this->optionDialog->showDebugButton();
+      this->optionDialog->setDebugButton("Update Z-Range",moption+2);
+      this->optionDialog->setTitleDescription("Export Surfaces",
+					      "Format 1=.tstack 2=.vtk");
+
+      
+      if (this->orientation<3)
+	{
+	  this->optionDialog->setfoption(0,"Spacing XY","%.1f",this->spacing[0]);
+	  this->optionDialog->setfoption(1,"Spacing  Z","%.1f",this->spacing[0]);
+	}
+      else
+	{
+	  this->optionDialog->setfoption(0,"Spacing XY","%.1f",this->spacing[0]*3.0);
+	  this->optionDialog->setfoption(1,"Spacing  Z","%.1f",this->spacing[0]*3.0);
+	}
+
+      this->optionDialog->setioption(4,"Start Frame","%d",1);
+      this->optionDialog->setioption(5,"End   Frame","%d",this->NumberOfFrames);
+      this->optionDialog->setioption(6,"Format","%d",1);
+      this->optionDialog->setMenuOption(moption);
+    } 
+
+  if (mode==0 || mode == 2)
+    {
+      float z[2];
+      int bf=0,ef=this->NumberOfFrames-1;
+      
+      if (mode==2)
+	{
+	  bf=Irange(this->optionDialog->getioption(4)-1,0,this->NumberOfFrames-1);
+	  ef=Irange(this->optionDialog->getioption(5)-1,0,this->NumberOfFrames-1);
+	}
+      
+      vtkpxSplineStackSource::ComputeZRange(this->splineStackCollection,
+					    this->NumberOfFrames,
+					    this->NumberOfSplineStacks,
+					    bf,ef,
+					    current_splinestack,z);
+      
+      //      fprintf(stderr,"Z-range = %.1f %.1f\n",z[0],z[1]);
+
+      this->optionDialog->setfoption(2,"Bot Slice","%.1f",z[0]);
+      this->optionDialog->setfoption(3,"Top Slice","%.1f",z[1]);
+    }
+
+  if (mode==0)
+    this->optionDialog->popupDialog();
+
+  if (mode!=1)
+    return;
+
+  float uspacing=Frange(this->optionDialog->getfoption(0),0.2*this->spacing[0],this->spacing[0]*10);
+  float vspacing=Frange(this->optionDialog->getfoption(1),0.2*this->spacing[2],this->spacing[2]*10);
+  float z[2];
+  
+  if (this->orientation<3)
+    {
+      float botslice=Frange(this->optionDialog->getfoption(2),0,this->dimensions[2]-1.0);
+      float topslice=Frange(this->optionDialog->getfoption(3),botslice+1,this->dimensions[2]-1.0);
+      z[0]=botslice*spacing[2];
+      z[1]=topslice*spacing[2];
+    }
+  else
+    {
+      z[0]=Frange(this->optionDialog->getfoption(2),0,this->dimensions[1]-1.0);
+      z[1]=Frange(this->optionDialog->getfoption(3),z[0]+1.0,this->dimensions[1]-1.0);
+    }
+  
+   
+  int format=Irange(this->optionDialog->getioption(6),1,2);
+  int bf=Irange(this->optionDialog->getioption(4)-1,0,this->NumberOfFrames-1);
+  int ef=Irange(this->optionDialog->getioption(5)-1,0,this->NumberOfFrames-1);
+  
+  
+  char extension[10];
+  char* line=NULL;
+  if (format==1)
+    {
+      sprintf(pxtk_buffer,"%s.01.tstack",surface_filename[current_splinestack]);
+      line=this->EventManager->getSaveFilename("Save series as tstacks",pxtk_buffer,"Series","*.01.tstack");
+      strcpy(extension,".tstack");
+    }
+  else
+    {
+      sprintf(pxtk_buffer,"%s.01.vtk",surface_filename[current_splinestack]);
+      line=this->EventManager->getSaveFilename("Save exported series as vtk surfaces",pxtk_buffer,"Series","*.01.vtk");
+      strcpy(extension,".vtk");
+    }
+  
+  if (line==NULL)
+    return;
+  
+  
+  char* noext1=nothisextension(line,extension);
+  char* noext2=nothisextension(noext1,".01");
+  vtkpxTriangulatedStackSource* tstack=vtkpxTriangulatedStackSource::New();
+  vtkPolyDataWriter* poly=vtkPolyDataWriter::New();
+  
+  PXTkApp::popupConsole();
+  for (int frame=bf;frame<=ef;frame++)
+    {
+      sprintf(pxtk_buffer3,"%s.%02d%s",noext2,frame+1,extension);
+      vtkpxSplineStackSource *stack=this->GetSplineStack(frame,current_splinestack);
+      tstack->SetFromSplineStackSource2(stack,uspacing,vspacing,z[0],z[1]);
+      
+      if (format==1)
+	{
+	  int ok=tstack->Save(pxtk_buffer3);
+	  sprintf(pxtk_buffer,"Saving to %s (status=%d)\n",pxtk_buffer3,ok);
+	}
+      else
+	{
+	  tstack->Update();
+	  poly->SetInput(tstack->GetOutput());
+	  poly->SetFileName(pxtk_buffer3);
+	  poly->Update();
+	  sprintf(pxtk_buffer,"Saving to %s\n",pxtk_buffer3);
+	}
+      PXTkApp::printToConsole(pxtk_buffer);
+    }
+  poly->Delete();
+  tstack->Delete();
+}
+
+
+// ---------------------------------------------------------------------------
+void vtkpxGUI4DSplineStackControl::ComputeVOIProperties(int frame)
+{
+  vtkpxGUISplineStackControl::ComputeVOIProperties(this->CurrentFrame);
+}
+// ---------------------------------------------------------------------------
+//
+//   Segmentation Stuff
+//
+// ---------------------------------------------------------------------------
+// Create GUI
+// ---------------------------------------------------------------------------
+void vtkpxGUI4DSplineStackControl::CreateSegmentationControl(PXTkFrame* segmentFrame)
+{
+  PXTkLabelFrame* temporal=new PXTkLabelFrame(this->EventManager,segmentFrame,"Temporal");
+  PXTkLabelFrame* spatial=new PXTkLabelFrame(this->EventManager,segmentFrame,"Spatial");
+  segmentFrame->addChildren("-side top -expand f -fill x",spatial,temporal);
+
+  PXTkFrame* spatial_t=new PXTkFrame(this->EventManager,spatial);
+  toggle_up    =new PXTkCheckButton(this->EventManager,spatial_t,"Up",-1);
+  toggle_down  =new PXTkCheckButton(this->EventManager,spatial_t,"Down",-1);
+  PXTkButton* but1=new PXTkButton(this->EventManager,spatial_t,"Auto",900);
+  PXTkButton* but2=new PXTkButton(this->EventManager,spatial_t,"Batch",901);
+
+  toggle_up->setState(PXTrue);
+  toggle_down->setState(PXTrue);
+  spatial_t->addChildren("-side left -expand f -fill x ",toggle_up,toggle_down,but1,but2);
+
+
+  sliceScale[0]=new PXTkArrowScale(this->EventManager,spatial,"Bottom",-1,PXTrue);
+  sliceScale[1]=new PXTkArrowScale(this->EventManager,spatial,"Top",-1,PXTrue);
+  for (int ia=0;ia<2;ia++)
+    {
+      sliceScale[ia]->setRange(0,15);
+      sliceScale[ia]->setValue(float(ia*14+1));
+      sliceScale[ia]->setLengthWidth(120,10);
+      sliceScale[ia]->setIncrement(1.0);
+      sliceScale[ia]->setResolution(1.0);
+    }
+  PXTkFrame* spatial_b=new PXTkFrame(this->EventManager,spatial);
+  PXTkButton* but3=new PXTkButton(this->EventManager,spatial_b,"Interpolate",902);
+  spatial_b->addChildren("-side right -expand f -padx 20 -pady 1",but3);
+  spatial->addChildren("-side top -expand f -fill x",
+		       spatial_t,sliceScale[0]->getMainWindow(),sliceScale[1]->getMainWindow(),spatial_b);
+  
+  
+
+  PXTkFrame* temporal_t=new PXTkFrame(this->EventManager,temporal);
+  PXTkFrame* temporal_t2=new PXTkFrame(this->EventManager,temporal);
+  PXTkFrame* temporal_t3=new PXTkFrame(this->EventManager,temporal);
+
+  toggle_past  =new PXTkCheckButton(this->EventManager,temporal_t,"Past",-1);
+  toggle_future=new PXTkCheckButton(this->EventManager,temporal_t,"Future",-1);
+  toggle_past->setState(PXTrue);
+  toggle_future->setState(PXTrue);
+
+  PXTkButton* tbut1=new PXTkButton(this->EventManager,temporal_t2,"Auto Current",903);
+  PXTkButton* tbut2=new PXTkButton(this->EventManager,temporal_t2,"Auto All",904);
+  
+  PXTkButton* tbut3=new PXTkButton(this->EventManager,temporal_t3,"Batch Current",905);
+  PXTkButton* tbut4=new PXTkButton(this->EventManager,temporal_t3,"Batch All",906);
+
+  temporal_t->addChildren("-side left -expand f -fill x ",toggle_past,toggle_future);
+  temporal_t2->addChildren("-side left -expand f -padx 2 ",tbut1,tbut2);
+  temporal_t3->addChildren("-side left -expand f -padx 2 ",tbut3,tbut4);
+
+  frameScale[0]=new PXTkArrowScale(this->EventManager,temporal,"ED",-1,PXTrue);
+  frameScale[1]=new PXTkArrowScale(this->EventManager,temporal,"ES",-1,PXTrue);
+  for (int iaa=0;iaa<2;iaa++)
+    {
+      frameScale[iaa]->setRange(1,10);
+      frameScale[iaa]->setValue(float(iaa*9+1));
+      frameScale[iaa]->setLengthWidth(120,10);
+      frameScale[iaa]->setIncrement(1.0);
+      frameScale[iaa]->setResolution(1.0);
+    }
+
+  PXTkFrame* temporal_b=new PXTkFrame(this->EventManager,temporal);
+  PXTkButton* tbut13=new PXTkButton(this->EventManager,temporal_b,"Interpolate Current",908);
+  PXTkButton* tbut14=new PXTkButton(this->EventManager,temporal_b,"Interpolate All",909);
+  temporal_b->addChildren("-side right -expand f -padx 1 -pady 1",tbut13,tbut14);
+
+  temporal->addChildren("-side top -expand f -fill x",
+			temporal_t,temporal_t2,temporal_t3);
+
+  temporal->addChildren("-side top -expand f -fill x",
+			frameScale[0]->getMainWindow(),frameScale[1]->getMainWindow(),temporal_b);
+
+  wait_dialog=new PXTkWaitDialog(this->EventManager,"Processing ...",910,PXTrue,200,200);
+  wait_dialog->initDisplay();
+  
+}
+
+/* **************************************************************************      */ 
+int vtkpxGUI4DSplineStackControl::InterpolateSpatially()
+{
+  this->BlockEditorCallback=1;
+  this->AbortProcessing=0;
+
+  int bottom=Irange((int)sliceScale[0]->getValue(),
+		    splineStackSet[current_splinestack]->GetTrimBottom(),
+		    splineStackSet[current_splinestack]->GetTrimTop()-1);
+  
+  int top=Irange((int)sliceScale[1]->getValue(),
+		 splineStackSet[current_splinestack]->GetTrimBottom()+1,
+		 splineStackSet[current_splinestack]->GetTrimTop());
+  
+
+  wait_dialog->showStopPrompt(PXTrue);
+  this->wait_dialog->setTitle("Interpolating Spatially");
+  this->wait_dialog->setText("initializing ...");
+  this->wait_dialog->popupDialog();
+
+  PXContour* cnt1=splineStackSet[current_splinestack]->GetSpline(bottom)->exporttocontour(0.8);
+  PXContour* cnt2=splineStackSet[current_splinestack]->GetSpline(top)->exporttocontour(0.8);
+
+  PXChamferDistanceMap* map1=new PXChamferDistanceMap(cnt1);
+  PXChamferDistanceMap* map2=new PXChamferDistanceMap(cnt2);
+
+  
+  int start=bottom+1;
+  int end=top-1;
+
+
+  for (int sl=start;sl<=end;sl++)
+      {
+	sprintf(pxtk_buffer,"Interpolating Frame %d Slice %d",this->CurrentFrame+1,sl);
+	this->wait_dialog->setText(pxtk_buffer);
+	PXTkApp::executeTclCommand("after 10");
+	if (this->AbortProcessing==1)
+	  {
+	    sl=end+1;
+	  }
+	else
+	  {
+	    float z=splineStackSet[current_splinestack]->GetSpline(sl)->getzlevel();
+    
+	    int w1=int(100.0*float(top-sl)/float(top-bottom)+0.5);
+	    int w2=int(100.0*float(sl-bottom)/float(top-bottom)+0.5);
+	    
+	    PXChamferDistanceMap* map=new PXChamferDistanceMap(map1,map2,w1,w2);
+	    PXContour* cntr=map->extractContour();
+	    
+	    int np=int(0.5+float(w1*splineStackSet[current_splinestack]->GetSpline(bottom)->getnumpoints()+
+				 w2*splineStackSet[current_splinestack]->GetSpline(top)->getnumpoints())
+		       /float(w1+w2));
+	    splineStackSet[current_splinestack]->GetSpline(sl)->fittocontour(cntr,2.0,0.0,np,1);
+	    splineStackSet[current_splinestack]->GetSpline(sl)->setzlevel(z);
+	    delete cntr;
+	    delete map;      
+	    splineStackSet[current_splinestack]->SetSpline((PXFPBSpline*)NULL,sl);
+	    splineStackSet[current_splinestack]->Modified();
+	    this->UpdateSplineEditor();
+	    this->UpdateDisplay();
+	  }
+      }
+
+  this->wait_dialog->popdownDialog();
+    
+  delete map1;  delete map2;
+  delete cnt1;  delete cnt2;
+
+  this->BlockEditorCallback=0;
+  this->UpdateSplineEditor();
+  return 1;
+}
+
+/* **************************************************************************      */ 
+int vtkpxGUI4DSplineStackControl::InterpolateTemporally(int allslices)
+{
+  this->BlockEditorCallback=1;
+  this->AbortProcessing=0;
+
+  int bottom=Irange((int)sliceScale[0]->getValue(),
+		    splineStackSet[current_splinestack]->GetTrimBottom(),
+		    splineStackSet[current_splinestack]->GetTrimTop()-1);
+  
+  int top=Irange((int)sliceScale[1]->getValue(),
+		 splineStackSet[current_splinestack]->GetTrimBottom()+1,
+		 splineStackSet[current_splinestack]->GetTrimTop());
+  
+  if (allslices==0)
+    {
+      int sl=this->SplineEditor->GetBeginSlice();
+      bottom=sl;
+      top=sl;
+    }
+
+
+  wait_dialog->showStopPrompt(PXTrue);
+  this->wait_dialog->setTitle("Interpolating Temporally");
+  this->wait_dialog->setText("initializing ...");
+  this->wait_dialog->popupDialog();
+
+
+  int beginframe=Irange((int)frameScale[0]->getValue(),1,this->NumberOfFrames)-1;
+  int endframe=Irange((int)frameScale[1]->getValue(),1,this->NumberOfFrames)-1;
+  int oldcurrentframe=this->GetCurrentFrame();
+  
+  if (this->BaseViewer!=NULL)
+    {
+      this->BaseViewer->SetCurrentFrame(beginframe);
+      this->BaseViewer->SetCurrentFrame(endframe);
+    }
+
+  int lastframe=endframe;
+  if (endframe<beginframe)
+    lastframe+=this->NumberOfFrames;
+
+  
+  for (int sl=bottom;sl<=top;sl++)
+    {
+      PXFPBSpline *spl1=this->GetSplineStack(beginframe,current_splinestack)->GetSpline(sl);
+      PXContour* cnt1=spl1->exporttocontour(0.8);
+      PXFPBSpline* spl2=this->GetSplineStack(endframe,current_splinestack)->GetSpline(sl);
+      PXContour* cnt2=spl2->exporttocontour(0.8);
+      float z=0.5*(spl1->getzlevel()+spl2->getzlevel());
+
+      PXChamferDistanceMap* map1=new PXChamferDistanceMap(cnt1);
+      PXChamferDistanceMap* map2=new PXChamferDistanceMap(cnt2);
+
+      for (int frame=beginframe;frame<=lastframe;frame++)
+	{
+	  int actualframe=frame;
+	  if (actualframe>=this->NumberOfFrames)
+	    actualframe-=this->NumberOfFrames;
+
+	  if (frame!=beginframe && frame!=lastframe)
+	    {
+	      if (this->BaseViewer)
+		this->BaseViewer->SetCurrentFrame(actualframe);
+
+	      sprintf(pxtk_buffer,"Interpolating Slice %d Frame %d",sl,actualframe+1);
+	      this->wait_dialog->setText(pxtk_buffer);
+	      PXTkApp::executeTclCommand("after 10");
+	      if (this->AbortProcessing==1)
+		{
+		  frame=lastframe;
+		  sl=top+1;
+		}
+	      else
+		{
+		  int w1=int(100.0*float(lastframe-frame)/float(lastframe-beginframe)+0.5);
+		  int w2=int(100.0*float(frame-beginframe)/float(lastframe-beginframe)+0.5);
+		  
+		  PXChamferDistanceMap* map=new PXChamferDistanceMap(map1,map2,w1,w2);
+		  PXContour* cntr=map->extractContour();
+		  
+		  int np=int(0.5+float(w1*spl1->getnumpoints()+
+				       w2*spl2->getnumpoints())
+			     /float(w1+w2));
+		  
+		  PXFPBSpline* spl=this->GetSplineStack(actualframe,current_splinestack)->GetSpline(sl);
+		  
+		  spl->fittocontour(cntr,2.0,0.0,np,1);
+		  spl->setzlevel(z);
+		  this->GetSplineStack(actualframe,current_splinestack)->SetSpline((PXFPBSpline*)NULL,sl);
+		  this->GetSplineStack(actualframe,current_splinestack)->Modified();
+		  delete map;      
+		  delete cntr;
+		  this->UpdateSplineEditor();
+		  this->UpdateDisplay();
+		}
+	    }
+	}
+      delete map1;
+      delete map2;
+      delete cnt1;
+      delete cnt2;
+    }
+
+
+  this->wait_dialog->popdownDialog();
+	
+  if (this->BaseViewer)
+    this->BaseViewer->SetCurrentFrame(oldcurrentframe);
+  
+
+  this->BlockEditorCallback=0;
+
+  return 1;
+
+}
+
+/*********************************************************************/
+void vtkpxGUI4DSplineStackControl::AutoSegment()
+{
+  if (this->AbortProcessing!=-1)
+    {
+      //      fprintf(stderr,"Already Processing at Work\n");
+      return;
+    }
+
+  this->SplineEditor->CopyCallback();  
+  wait_dialog->showStopPrompt(PXTrue);
+  this->wait_dialog->setTitle("Auto Segmentation");
+  this->wait_dialog->setText("initializing ...");
+  this->wait_dialog->popupDialog();
+  this->AbortProcessing=0;
+
+  Tcl_CreateTimerHandler(10,vtkpxGUI4DSplineStackControl::AutoSegmentStaticWork,this);
+}
+/*                *****************************************      */ 
+void vtkpxGUI4DSplineStackControl::AutoSegmentStaticWork(void* cl)
+{
+  int done=((vtkpxGUI4DSplineStackControl*)cl)->AutoSegmentWork();
+  if (done==0)
+    Tcl_CreateTimerHandler(10,vtkpxGUI4DSplineStackControl::AutoSegmentStaticWork,cl);
+}
+/*                *****************************************      */ 
+int vtkpxGUI4DSplineStackControl::AutoSegmentWork()
+{
+  static int startingFromScratch=1;
+  static int lastslice=-1;
+  static int firstslice;
+  static int lastincrement=1;
+
+  if (this->AbortProcessing==1)
+    {
+      this->wait_dialog->popdownDialog();
+      startingFromScratch=1;
+      this->AbortProcessing=-1;
+      return 1;
+    }
+    
+  if (startingFromScratch==1)
+    {
+      int curSlice=this->SplineEditor->GetBeginSlice();
+      firstslice=curSlice;
+      this->wait_dialog->setText("Segmenting slice : ",curSlice);
+      this->SplineEditor->CreateSnake();
+      this->SplineEditor->UpdateSnake();
+      if (this->AutoSegmentMode)
+	this->SplineEditor->CopyCallback();
+      this->UpdateFromSplineEditor();
+      if (toggle_up->getState())
+	lastincrement=1;
+      else
+	lastincrement=-1;
+      lastslice=firstslice+lastincrement;
+      startingFromScratch=0;
+      return 0;
+    }
+
+  if (lastincrement==1)
+    {
+      if (lastslice<=splineStackSet[current_splinestack]->GetTrimTop() )
+	{
+	  this->SplineEditor->SetSlice(lastslice);
+	  this->wait_dialog->setText("Segmenting slice : ",lastslice);
+	  if (this->AutoSegmentMode)
+	    this->SplineEditor->PasteCallback(); 
+	  this->SplineEditor->CreateSnake();
+	  this->SplineEditor->UpdateSnake();
+	  if (this->AutoSegmentMode)
+	    this->SplineEditor->CopyCallback();  
+	  this->UpdateFromSplineEditor();
+	  lastslice++;
+	  return 0;
+	}
+      else
+	{
+	  if (this->AutoSegmentMode)
+	    {
+	      this->SplineEditor->SetSlice(firstslice);
+	      this->SplineEditor->CopyCallback();  
+	    }
+	  lastslice=firstslice-1;
+	  lastincrement=-1;
+	  return 0;
+	}
+    }
+  
+  if (lastincrement==-1 && 
+      toggle_down->getState()==PXTrue &&
+      lastslice>=splineStackSet[current_splinestack]->GetTrimBottom())
+    {
+      this->SplineEditor->SetSlice(lastslice);
+      this->wait_dialog->setText("Segmenting slice : ",this->SplineEditor->GetBeginSlice());
+      if (this->AutoSegmentMode)
+	this->SplineEditor->PasteCallback();
+      this->SplineEditor->CreateSnake();
+      this->SplineEditor->UpdateSnake();
+      if (this->AutoSegmentMode)
+	this->SplineEditor->CopyCallback(); 
+      this->UpdateFromSplineEditor();
+      lastslice=lastslice-1;
+      return 0;
+    }
+
+  this->wait_dialog->popdownDialog();
+  this->splineStackSet[current_splinestack]->Modified();
+  this->SplineEditor->SetSlice(firstslice);
+  this->UpdateSplineEditor();
+  startingFromScratch=1;
+  lastincrement=1;
+  this->UpdateDisplay();
+  this->AbortProcessing=-1;
+  PXTkApp::executeTclCommand("update idletasks");
+  return 1;
+
+}
+/*********************************************************************/
+void vtkpxGUI4DSplineStackControl::AutoTemporalVolumeSegment(int mode)
+{
+
+  // 0 == Auto Current Slice
+  // 1 == Auto All Slices
+  // 2 == Batch Current Slice
+  // 3 == Batch All Slices
+
+
+  int bottom=splineStackSet[current_splinestack]->GetTrimBottom();
+  int top=splineStackSet[current_splinestack]->GetTrimTop();
+  int middle=this->SplineEditor->GetBeginSlice();
+
+  if (mode==0 || mode == 2)
+    {
+      bottom=middle;
+      top=middle;
+    }
+  else
+    {
+      if (toggle_up->getState()==PXFalse)
+	top=middle;
+      if (toggle_down->getState()==PXFalse)
+	bottom=middle;
+    }
+    int beginframe=this->CurrentFrame;
+    int currentframe=this->CurrentFrame;
+    int endframe=this->NumberOfFrames+beginframe-1;
+    int frameincrement=1;
+
+    if (toggle_past->getState()==PXFalse)
+      {
+	endframe=this->NumberOfFrames-1;
+	if (toggle_future->getState()==PXFalse)
+	  endframe=beginframe;
+      }
+    else if (toggle_future->getState()==PXFalse)
+      {
+	beginframe=0;
+	endframe=currentframe;
+	frameincrement=-1;
+      }
+
+    if (mode==0 || mode == 1)
+      this->AutoSegmentMode=1;
+    else
+      this->AutoSegmentMode=0;
+
+
+  this->AbortProcessing=0;
+
+  wait_dialog->showStopPrompt(PXTrue);
+  this->wait_dialog->setDebugMode(PXFalse);
+  this->wait_dialog->setTitle("Temporal Segmentation");
+  this->wait_dialog->setText("initializing ...");
+  this->wait_dialog->popupDialog();
+
+
+  /*  fprintf(stderr,"Currentframe =%d frameincrement=%d beginframe=%d endframe=%d\n",
+      currentframe,frameincrement,beginframe,endframe);*/
+
+  for (int slice=bottom;slice<=top;slice++)
+    {
+      sprintf(pxtk_buffer,"Segmenting Slice %d Frame %d",slice,currentframe+1);
+      this->wait_dialog->setText(pxtk_buffer);
+      if (this->BaseViewer)
+	this->BaseViewer->SetCurrentFrame(currentframe);
+      this->SetCurrentFrame(currentframe);
+      this->SplineEditor->CreateSnake();
+      this->SplineEditor->UpdateSnake();
+      if (this->AutoSegmentMode)
+	this->SplineEditor->CopyCallback();
+      this->UpdateFromSplineEditor();
+    	
+      int done=0;
+      int frame=currentframe;
+      while (done ==0 )
+	{
+	  if (frame!=currentframe)
+	    {
+	      int actualframe=frame;
+	      if (actualframe>=this->NumberOfFrames)
+		actualframe-=this->NumberOfFrames;
+	      
+	      sprintf(pxtk_buffer,"Segmenting Slice %d Frame %d",slice,actualframe+1);
+	      this->wait_dialog->setText(pxtk_buffer);
+	      if (this->BaseViewer)
+		this->BaseViewer->SetCurrentFrame(actualframe);
+	      this->SetCurrentFrame(actualframe);
+	      PXTkApp::executeTclCommand("after 10");
+	      if (this->AbortProcessing==1)
+		{
+		  frame=endframe+1;
+		  slice=top+1;
+		}
+	      else
+		{
+		  if (this->AutoSegmentMode)
+		  this->SplineEditor->PasteCallback();
+		  this->SplineEditor->CreateSnake();
+		  this->SplineEditor->UpdateSnake();
+		  if (this->AutoSegmentMode)
+		    this->SplineEditor->CopyCallback();
+		  this->UpdateFromSplineEditor();
+		}
+	    }
+
+	  frame+=frameincrement;
+	  if (frameincrement>0)
+	    {
+	      if (frame>endframe)
+		done=1;
+	    }
+	  else
+	    {
+	      if (frame<beginframe)
+		done=1;
+	    }
+	}
+    }
+
+
+  if (this->BaseViewer)
+    this->BaseViewer->SetCurrentFrame(currentframe);
+  this->SetCurrentFrame(currentframe);
+
+
+  wait_dialog->popdownDialog();
+  wait_dialog->setDebugMode(PXFalse);
+}
+
+/*********************************************************************/
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUI4DSplineStackControl.h b/bioimagesuite30_src/GUI/vtkpxGUI4DSplineStackControl.h
new file mode 100644
index 0000000..6a5c18e
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUI4DSplineStackControl.h
@@ -0,0 +1,244 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUI4DSplineStackControl.h,v $
+  Language:  C++
+  Date:      $Date: 2002/04/09 15:46:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUI4DSplineStackControl - Base Image Viewer
+// .SECTION Description
+
+#ifndef __vtkpxGUI4DSplineStackControl_h
+#define __vtkpxGUI4DSplineStackControl_h
+
+#include "vtkpxGUISplineStackControl.h"
+#include "pxtkseldialog.h"
+#include "pxtkwaitdialog.h"
+
+class vtkImageData;
+class vtkpxGUI4DRenderer;
+class vtkCollection;
+class vtkActorCollection;
+
+class vtkpxGUI4DSplineStackControl : public vtkpxGUISplineStackControl 
+{
+public:
+
+  static vtkpxGUI4DSplineStackControl *New();
+  vtkTypeMacro(vtkpxGUI4DSplineStackControl,vtkpxGUISplineStackControl);
+  
+  // Description:
+  // Initialize Display and add Renderer 
+  virtual char*  Initialize(const char* name,int inside);
+  virtual char*  Initialize(const char* name,const char* name2,const char* name3,int inside);
+
+  // Description:
+  // Set Renderer
+  virtual void   SetRenderer(vtkpxGUI4DRenderer *rendererer,int num);
+  virtual void   SetRenderer(vtkpxGUI4DRenderer *rendererer,int num,int wireframe);
+
+  // Description:
+  // Set/Get Base Viewer
+  vtkSetObjectMacro(BaseViewer,vtkpxGUIBaseImageViewer);
+  vtkGetObjectMacro(BaseViewer,vtkpxGUIBaseImageViewer);
+
+  // Description:
+  // Update Display
+  virtual void   Update();
+  virtual void   UpdateDisplay();
+
+
+  // Description:
+  // Set Image Level,Plane And Frame 
+  virtual void SetImage(vtkImageData* image,int orientation,int level=0,int frame=0);
+  virtual void SetImage(vtkImageData* image);
+
+  // Description:
+  // Event Manager 
+  virtual int    HandleEvent(int);
+
+  // Description:
+  // Communication with SplineEditor
+  // Add Frame Checking
+  virtual void UpdateSplineEditor();
+  virtual void UpdateFromSplineEditor();
+
+
+  // Description:
+  // Get Spline Stack from Collection
+  virtual vtkpxSplineStackSource* GetSplineStack(int frame,int index);
+
+  // Description:
+  // If outside process modified splines (using GetSplineStack) this functions needs to
+  // be called to re-synchronize the GUI etc
+  virtual void UpdateAfterExternalEditing();
+
+  // Description:
+  // Enable Change Of Frame from this control -- bad idea 
+  //virtual void EnableFrameScale(int enable);
+
+  // Description:
+  // Frame Stuff
+  virtual void SetCurrentFrame(int fr);
+  virtual int  GetCurrentFrame();
+  virtual int  GetNumberOfFrames();
+
+  // Description:
+  // Load / Save
+  virtual int  MultiLoad(const char* fname);
+  virtual int  MultiSave(const char* fname);
+
+protected:
+
+  vtkpxGUI4DSplineStackControl();
+  virtual ~vtkpxGUI4DSplineStackControl();
+
+  // Description:
+  // Disable these two functions insist on multirenderer 
+  virtual void   SetRenderer(vtkRenderer *rendererer,int num);
+  virtual void   SetRenderer(vtkRenderer *rendererer,int num,int wireframe);
+
+
+  // Description:
+  // Collection Stuff
+  vtkCollection*       splineStackCollection;
+  vtkActorCollection*  splineStackActorCollection;
+  vtkpxGUI4DRenderer*  MultiRenderer[SSP_MAX_RENDERERS];
+  vtkpxGUIBaseImageViewer*  BaseViewer;
+  int                  wireframemode[SSP_MAX_RENDERERS];
+
+  // Description:
+  // Frame Scale Widget
+  //PXTkArrowScale*      frameScale;
+  PXTkOptionMenu       *currentCollection2;
+  PXTkCheckButton*     autosavebutton;
+  PXTkCheckButton*     backupbutton;
+  PXBool               do_autosave;
+  PXBool               do_backup;
+  
+  // Description:
+  // Widgets for various GUIS
+  // 1. Multi-resample
+  // 2. Multi-shift+scale
+
+
+
+  // Description:
+  // Frame Stuff
+  int   NumberOfFrames;
+  int   ActualNumberOfFrames;
+
+
+  // Description:
+  // Initialize SplineStacks
+  virtual void InitializeSplineStacks();
+  virtual void ResetSplineStacks();
+
+  // Description:
+  // Frame Update Stuff 
+  virtual void CreateFrames(int numframes);
+  virtual void UpdateFrame(int frame);
+  virtual void ChangeFrame(int newframe);
+  virtual void SetCurrentCollection(int num);
+
+
+  // Description:
+  // Implement Autosave
+  virtual int DoAutosave(int frame);
+  virtual int DoBackup(int stackindex,const char* rootname);
+
+
+  // Description:
+  // Handle Callbacks for GUI Stuff
+  virtual void DoShiftScale(int mode,int moption=-1);
+  virtual void DoResample(int mode,int moption=-1);
+  virtual void DoVolume(int mode,int moption=-1);
+  virtual void DoCylinders(int mode,int moption=-1);
+  virtual void DoSmoothApex(int mode,int moption=-1);
+  virtual void DoExport(int mode,int moption=-1);
+
+  // Description:
+  // Handle VOI Props
+  virtual void ComputeVOIProperties(int frame);
+
+  //BTX
+  // -------------------------------------------------------------------------
+  // Segmentation Stuff
+  // -------------------------------------------------------------------------
+  PXTkSelDialog*  optionDialog;
+  PXTkWaitDialog           *wait_dialog;
+  PXTkCheckButton          *toggle_up,*toggle_down,*toggle_past,*toggle_future;
+  PXTkArrowScale           *frameScale[2],*sliceScale[2];
+  int                      AbortProcessing,AutoSegmentMode;
+
+  virtual void CreateSegmentationControl(PXTkFrame* segmentFrame);
+
+  virtual void AutoSegment();
+  virtual int AutoSegmentWork();
+  static  void AutoSegmentStaticWork(void*  clientdata);
+  
+  virtual void AutoTemporalVolumeSegment(int mode);
+
+
+
+  virtual int  InterpolateTemporally(int allslices);
+  virtual int  InterpolateSpatially();
+
+  //ETX
+
+
+};
+
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUI4DTriangulatedStackControl.cpp b/bioimagesuite30_src/GUI/vtkpxGUI4DTriangulatedStackControl.cpp
new file mode 100644
index 0000000..d5d6591
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUI4DTriangulatedStackControl.cpp
@@ -0,0 +1,738 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// 	$Id: vtkpxGUI4DTriangulatedStackControl.cpp,v 1.1 2002/06/07 19:40:45 papad Exp papad $	
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkpxGUI4DTriangulatedStackControl.h"
+#include "vtkpxUtil.h"
+#include "vtkActor.h"
+#include "vtkAssembly.h"
+#include "vtkRenderer.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxImageExtract.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkImageData.h"
+#include "vtkpxGUI4DRenderer.h"
+#include "vtkCollection.h"
+#include "vtkActorCollection.h"
+#include "vtkpxShapeTracking.h"
+#include "vtkProperty.h"
+#include "pxcontourstack.h"
+/* -------------------------------------------------------------------------*/
+vtkpxGUI4DTriangulatedStackControl* vtkpxGUI4DTriangulatedStackControl::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUI4DTriangulatedStackControl");
+  if(ret)
+      {
+	return (vtkpxGUI4DTriangulatedStackControl*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUI4DTriangulatedStackControl;
+}
+
+// ----------------------------------------------------------------------------
+vtkpxGUI4DTriangulatedStackControl::vtkpxGUI4DTriangulatedStackControl()
+{
+  for (int j=0;j<TSP_MAX_RENDERERS;j++)
+    this->MultiRenderer[j]=NULL;
+  
+  this->CurrentFrame=0;
+  this->NumberOfFrames=0;
+  this->ActualNumberOfFrames=0;
+  this->triangulatedStackCollection=NULL;
+  this->triangulatedStackActorCollection=NULL;
+  
+  for (int ia=0;ia<TSP_MAX_COLLECTIONS;ia++)
+    {
+      surface_filename[ia]=new char[20];
+      sprintf(surface_filename[ia],"unnamed_%d",ia+1);
+    }
+}
+// ----------------------------------------------------------------------------
+vtkpxGUI4DTriangulatedStackControl::~vtkpxGUI4DTriangulatedStackControl()
+{
+  
+  if (this->triangulatedStackCollection!=NULL)
+    this->triangulatedStackCollection->Delete();
+
+  if (this->triangulatedStackActorCollection==NULL)
+    this->triangulatedStackActorCollection->Delete();
+
+  // Set to NULL to avoid deleting by parent
+  for (int i=0;i<this->NumberOfTriangulatedStacks;i++)
+    {
+      this->triangulatedStackSet[i]=NULL;
+      for (int j=0;j<TSP_MAX_RENDERERS;j++)
+	this->triangulatedStackActor[j][i]=NULL;
+    }
+    
+  for (int ia=0;ia<TSP_MAX_COLLECTIONS;ia++)
+    delete [] surface_filename[ia];
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxGUI4DTriangulatedStackControl::InitializeTriangulatedStacks()
+{
+  this->triangulatedStackCollection=vtkCollection::New();
+  this->triangulatedStackActorCollection=vtkActorCollection::New();
+
+  current_triangulatedstack=0;
+  clipboardTriangulatedStack=vtkpxTriangulatedStackSource::New();
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxGUI4DTriangulatedStackControl::ResetTriangulatedStacks()
+{
+  //  fprintf(stderr,"In Reset Triangulated Stacks");
+
+  int d[3]; float sp[3],ori[3];
+  for (int ib=0;ib<=2;ib++)
+    {
+      d[ib]=this->dimensions[ib];
+      sp[ib]=this->spacing[ib];
+      ori[ib]=this->origin[ib];
+    }
+  
+  int oldnumframes=this->NumberOfFrames;
+
+  this->NumberOfFrames=this->image->GetNumberOfScalarComponents();
+  this->image->GetSpacing(this->spacing);
+  this->image->GetOrigin(this->origin);
+  this->image->GetDimensions(this->dimensions);
+
+  this->CreateFrames(this->NumberOfFrames);
+  for (int i=1;i<this->NumberOfFrames;i++)
+    this->UpdateFrame(i);
+  this->UpdateFrame(0);
+
+
+  float sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+    sum+=
+      fabs(float(d[ia]-this->dimensions[ia]))+
+      fabs(sp[ia]-this->spacing[ia])+
+      fabs(ori[ia]-this->origin[ia]);
+  
+  if (sum>0.01)
+    {
+      if (oldnumframes>0)
+	{
+	  int index=0;
+	  
+	  for (int f=0;f<oldnumframes;f++)
+	    for (int i=0;i<this->NumberOfTriangulatedStacks;i++)
+	      {
+		vtkpxTriangulatedStackSource *st=(vtkpxTriangulatedStackSource*)this->triangulatedStackCollection->GetItemAsObject(index);
+		++index;
+		PXContourStack* cstack=new PXContourStack(this->dimensions[2]);
+		cstack->setellipticalcylinder(8,
+					      spacing[0]*float(dimensions[0])/8.0*(1.0+i),
+					      spacing[1]*float(dimensions[1])/8.0*(1.0+i),
+					      origin[0]+spacing[0]*dimensions[0]/2.0,
+					      origin[1]+spacing[1]*dimensions[1]/2.0);
+		st->SetFromContourStack(cstack);
+		delete cstack;//fprintf(stderr,"Setting Elliptical Cylinder f=%d,i=%d\n",f,i);
+	      }
+	}
+    }
+}
+
+// ----------------------------------------------------------------------------
+void vtkpxGUI4DTriangulatedStackControl::CreateFrames(int numframes)
+{
+
+  if (numframes<this->ActualNumberOfFrames)
+    return;
+
+  if (numframes>this->MultiRenderer[0]->GetNumberOfFrames())
+    numframes=this->MultiRenderer[0]->GetNumberOfFrames();
+  if (numframes<1)
+    numframes=1;
+
+
+  for (int fr=this->ActualNumberOfFrames;fr<numframes;fr++)
+    {
+      for (int i=0;i<this->NumberOfTriangulatedStacks;i++)
+	{
+	  triangulatedStackSet[i]=vtkpxTriangulatedStackSource::New();
+	  triangulatedStackSet[i]->SetColorMode(color_mode[i]);
+	  
+	  //	  fprintf(stderr,"Create Frames:: Setting Elliptical Cylinder f=%d,i=%d\n",fr,i);
+	  PXContourStack* cstack=new PXContourStack(this->dimensions[2]);
+	  cstack->setellipticalcylinder(8,
+					spacing[0]*float(dimensions[0])/8.0*(1.0+i),
+					spacing[1]*float(dimensions[1])/8.0*(1.0+i),
+					origin[0]+spacing[0]*dimensions[0]/2.0,
+					origin[1]+spacing[1]*dimensions[1]/2.0);
+	  triangulatedStackSet[i]->SetFromContourStack(cstack);
+	  delete cstack;//fprintf(stderr,"Setting Elliptical Cylinder f=%d,i=%d\n",f,i);
+	  this->triangulatedStackCollection->AddItem(triangulatedStackSet[i]);
+	  
+	  for (int r=0;r<TSP_MAX_RENDERERS;r++)
+	    {
+	      triangulatedStackActor[r][i]=vtkActor::New();
+	      this->triangulatedStackActorCollection->AddItem(triangulatedStackActor[r][i]);
+	      
+	      if (this->MultiRenderer[r]!=NULL)
+		{
+		  vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+		  map->SetInput(triangulatedStackSet[i]->GetOutput());
+		  
+		  triangulatedStackActor[r][i]->SetMapper(map);
+		  if (display_mode[i]!=0)
+		    triangulatedStackActor[r][i]->SetVisibility(1);
+		  else
+		    triangulatedStackActor[r][i]->SetVisibility(0);
+		  
+		  if (wireframemode[r]==1)
+		    {
+		      triangulatedStackActor[r][i]->GetProperty()->SetRepresentationToWireframe();
+		      triangulatedStackActor[r][i]->GetProperty()->SetLineWidth(2.0);
+		      triangulatedStackActor[r][i]->GetProperty()->SetAmbient(1.0);
+		      triangulatedStackActor[r][i]->GetProperty()->SetDiffuse(0.0);
+		      triangulatedStackActor[r][i]->GetProperty()->SetSpecular(0.0);
+		    }
+		  map->Delete();
+		  this->MultiRenderer[r]->GetRendererForFrame(fr)->AddActor(triangulatedStackActor[r][i]);
+		}
+	    }
+	}
+      if (fr==0)
+	{
+	  current_triangulatedstack=0;
+	  currentTriangulatedStack=triangulatedStackSet[current_triangulatedstack];
+	}
+    }
+
+  this->ActualNumberOfFrames=numframes;
+
+  
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DTriangulatedStackControl::UpdateFrame(int frame)
+{
+  //  fprintf(stderr,"Updating Frame %d\n",frame);
+
+  if (frame>=this->ActualNumberOfFrames)
+    return;
+  
+  // Image Slice Ortho Slice First 
+  int index=frame*this->NumberOfTriangulatedStacks;
+  int index2=index*TSP_MAX_RENDERERS;
+
+  //  fprintf(stderr,"Index=%d index2=%d\n",index,index2);
+  for (int i=0;i<this->NumberOfTriangulatedStacks;i++)
+    {
+      triangulatedStackSet[i]=(vtkpxTriangulatedStackSource*)this->triangulatedStackCollection->GetItemAsObject(index);
+      ++index;
+      for (int r=0;r<TSP_MAX_RENDERERS;r++)
+	{
+	  triangulatedStackActor[r][i]=(vtkActor*)this->triangulatedStackActorCollection->GetItemAsObject(index2);
+	  ++index2;
+	}
+    }
+
+  //fprintf(stderr,"Final Index=%d index2=%d\n",index,index2);
+
+  for (int r=0;r<TSP_MAX_RENDERERS;r++)
+    {
+      if (this->MultiRenderer[r]!=NULL)
+	this->Renderer[r]=this->MultiRenderer[r]->GetRendererForFrame(frame);
+    }
+
+  //  fprintf(stderr,"Done Updating %d\n",frame);
+
+}
+// -------------------------------------------------------------------------
+void vtkpxGUI4DTriangulatedStackControl::ChangeFrame(int newframe)
+{
+  newframe=Irange(newframe,0,this->NumberOfFrames-1);
+  if (newframe==this->CurrentFrame)
+    return;
+
+  this->UpdateFrame(newframe); 
+  this->currentTriangulatedStack=triangulatedStackSet[current_triangulatedstack];
+  this->CurrentFrame=newframe;
+  this->Update();
+}
+// -------------------------------------------------------------------------
+
+char* vtkpxGUI4DTriangulatedStackControl::Initialize(const char* name,int inside)
+{
+  return this->Initialize(name,name,inside);
+}
+
+char* vtkpxGUI4DTriangulatedStackControl::Initialize(const char* name,const char* name2,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+
+  vtkpxGUITriangulatedStackControl::Initialize(name,inside);
+
+  PXTkLabelFrame* mFrame=NULL;
+  if (strcmp(name,name2)==0)
+    {
+      mFrame=new PXTkLabelFrame(this->EventManager,this->controlFrame,"Multi Frame");
+      this->controlFrame->addChildren("-side top -expand false -fill x -padx 1 -pady 5",mFrame);
+    }
+  else
+    {
+      PXTkFrame* m=new PXTkFrame(NULL,name2);
+      mFrame=new PXTkLabelFrame(this->EventManager,m,"Multi Frame");
+      m->addChildren("-side top -expand false -fill x -padx 1 -pady 5",mFrame);
+    }
+  mFrame->setPackMode(PXTrue);
+
+   PXTkFrame* f2=new PXTkFrame(this->EventManager,mFrame);
+  PXTkFrame* f4=new PXTkFrame(this->EventManager,mFrame);
+  mFrame->addChildren("-side top -expand false -fill x -pady 0 ",f2,f4);
+
+     
+  PXTkButton* b0a=new PXTkButton(this->EventManager,f2,"Load All",801);
+  PXTkButton* b0b=new PXTkButton(this->EventManager,f2,"Save All",802);
+  f2->addChildren("-side left -expand f -fill x -pady 1 -padx 2",b0a,b0b);
+
+  f4->setPackMode(PXTrue);
+
+  PXTkButton* but1=new PXTkButton(this->EventManager,f4,"Curvatures",810);
+  PXTkButton* but2=new PXTkButton(this->EventManager,f4,"Shape Tracking",812);
+  f4->addChildren("-side left -expand f -fill x -pady 0",but1,but2);
+  return GetWidgetName();
+}
+
+/* -------------------------------------------------------------------------*/ 
+void vtkpxGUI4DTriangulatedStackControl::SetRenderer(vtkRenderer* ren,int index)
+{
+  vtkErrorMacro(<<"Cannot Use this Function in vtkpxGUI4DTriangulatedStackControl");
+}
+
+void vtkpxGUI4DTriangulatedStackControl::SetRenderer(vtkpxGUI4DRenderer* ren,int index)
+{
+  this->SetRenderer(ren,index,0);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DTriangulatedStackControl::SetRenderer(vtkRenderer *ren,int index,int wireframe)
+{
+  vtkErrorMacro(<<"Cannot Use this Function in vtkpxGUI4DTriangulatedStackControl");
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DTriangulatedStackControl::SetRenderer(vtkpxGUI4DRenderer *ren,int index,int wireframe)
+{
+  index=Irange(index,0,TSP_MAX_RENDERERS-1);
+
+  if (this->MultiRenderer[index]!=NULL)
+    return;
+
+  this->MultiRenderer[index]=ren;
+  this->wireframemode[index]=wireframe;
+  this->Renderer[index]=this->MultiRenderer[index]->GetRendererForFrame(this->CurrentFrame);
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DTriangulatedStackControl::Update()
+{
+  if (this->triangulatedStackActor[0]==NULL)
+      return;
+
+  
+  for (int frame=0;frame<this->NumberOfFrames;frame++)
+    {
+      int index=frame*this->NumberOfTriangulatedStacks;
+      int index2=index*TSP_MAX_RENDERERS;
+      //  fprintf(stderr,"Index=%d index2=%d\n",index,index2);
+      for (int i=0;i<this->NumberOfTriangulatedStacks;i++)
+	{
+	  vtkpxTriangulatedStackSource *stack2=this->GetTriangulatedStack(frame,i);
+	  if (stack2->GetColorMode()!=color_mode[i])
+	    stack2->SetColorMode(color_mode[i]);
+
+	  for (int r=0;r<TSP_MAX_RENDERERS;r++)
+	    {
+	      vtkActor* act=(vtkActor*)this->triangulatedStackActorCollection->GetItemAsObject(index2);
+	      ++index2;
+	      
+	      if (display_mode[i]==0)
+		{
+		  act->SetVisibility(0);
+		}
+	      else
+		{
+		  vtkProperty* prop=act->GetProperty();
+		  switch (display_mode[i])
+		    {
+		    case 3:
+		      prop->SetRepresentationToSurface();
+		      prop->SetDiffuse(1.0);
+		      prop->SetAmbient(0.0);
+		      prop->SetSpecular(0.0);
+		      break;
+		    case 2:
+		      prop->SetRepresentationToWireframe();
+		      prop->SetDiffuse(0.0);
+		      prop->SetAmbient(1.0);
+		      prop->SetSpecular(0.0);
+		      break;
+		    case 1:
+		      prop->SetRepresentationToPoints();
+		      prop->SetDiffuse(0.0);
+		      prop->SetAmbient(1.0);
+		      prop->SetSpecular(0.0);
+		      prop->SetPointSize(3.0);		
+		      break;
+		    }
+		  act->SetVisibility(1);
+		}
+	    }
+	}
+    }
+  // Curve Stuff 
+  UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DTriangulatedStackControl::UpdateDisplay()
+{
+  vtkpxGUITriangulatedStackControl::UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+
+int  vtkpxGUI4DTriangulatedStackControl::HandleEvent(int event)
+{
+  if (!this->Initialized)
+      return TCL_OK;
+
+  if (event<10)
+      return this->EventManager->handleDirectEvent(event);
+
+  if (event<800)
+    return vtkpxGUITriangulatedStackControl::HandleEvent(event);
+
+
+
+  switch (event)
+    {
+    case 801:
+      if (this->NumberOfFrames>0)
+	{
+	  char* line=this->EventManager->getOpenFilename("Load series","Series","*.01.tstack");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		this->MultiLoad(line);
+	    }
+	}
+      break;
+    case 802:
+      if (this->NumberOfFrames>0)
+	{
+	  sprintf(pxtk_buffer,"%s.01.tstack",surface_filename[current_triangulatedstack]);
+	  char* line=this->EventManager->getSaveFilename("Save series",pxtk_buffer,"Series","*.01.tstack");
+	  if (line!=NULL)
+	    {
+	      this->MultiSave(line);
+	    }
+	}
+      break;
+
+    case 810:
+      this->DoCurvatures(0,850);
+      break;
+
+    case 850:
+      this->DoCurvatures(1);
+      break;
+
+    case 812:
+      this->DoShapeTracking(0,860);
+      break;
+
+    case 860:
+      this->DoShapeTracking(1);
+      break;
+
+    }
+  
+  
+  this->UpdateDisplay();
+
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DTriangulatedStackControl::SetImage(vtkImageData* img,int orient,int level,int frame)
+{
+  if (img!=NULL)  this->SetImage(img);
+  this->orientation=Irange(orient,0,3);
+  this->SetCurrentFrame(frame);
+  
+}
+
+void vtkpxGUI4DTriangulatedStackControl::SetImage(vtkImageData* img)
+{
+  if (img==NULL)
+    return;
+
+  if (this->image!=NULL)
+    this->image->Delete();
+  this->image=vtkImageData::New();
+  this->image->ShallowCopy(img);      
+  
+  this->ResetTriangulatedStacks();
+
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DTriangulatedStackControl::MultiLoad(const char* fname)
+{
+  strcpy(pxtk_buffer2,fname);
+
+  char* noext1=nothisextension(fname,".tstack");
+  char* noext2=nothisextension(noext1,".01");
+  int sum=0;
+
+  for (int frame=0;frame<this->NumberOfFrames;frame++)
+    {
+      sprintf(pxtk_buffer3,"%s.%02d.tstack",noext2,frame+1);
+      vtkpxTriangulatedStackSource *stack=this->GetTriangulatedStack(frame,current_triangulatedstack);
+      int ok=stack->Load(pxtk_buffer3);
+      stack->Modified();
+      sum+=(1-ok);
+      sprintf(pxtk_buffer,"Loading from %s (status=%d,current=%d)\n",pxtk_buffer3,ok,current_triangulatedstack);
+      PXTkApp::printToConsole(pxtk_buffer);
+    }
+
+  if (sum<this->NumberOfFrames)
+    {
+      delete [] surface_filename[current_triangulatedstack];
+      surface_filename[current_triangulatedstack]=new char[strlen(noext2)+1];
+      strcpy(surface_filename[current_triangulatedstack],noext2);
+    }
+
+  if (sum>0)
+    PXTkApp::popupConsole();
+      
+  delete [] noext2;
+  delete [] noext1;
+  this->UpdateAfterExternalEditing();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DTriangulatedStackControl::UpdateAfterExternalEditing()
+{
+  this->UpdateFrame(this->CurrentFrame);
+
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DTriangulatedStackControl::MultiSave(const char* fname)
+{
+  char* noext1=nothisextension(fname,".tstack");
+  char* noext2=nothisextension(noext1,".01");
+  int sum=0;
+
+
+
+  for (int frame=0;frame<this->NumberOfFrames;frame++)
+    {
+      sprintf(pxtk_buffer3,"%s.%02d.tstack",noext2,frame+1);
+      vtkpxTriangulatedStackSource *stack=this->GetTriangulatedStack(frame,current_triangulatedstack);
+      int ok=stack->Save(pxtk_buffer3);
+      sum+=(1-ok);
+      sprintf(pxtk_buffer,"Saving to %s (status=%d)\n",pxtk_buffer3,ok);
+      PXTkApp::printToConsole(pxtk_buffer);
+    }
+
+  if (sum>0)
+    PXTkApp::popupConsole();
+
+  if (sum<this->NumberOfFrames)
+    {
+      delete [] surface_filename[current_triangulatedstack];
+      surface_filename[current_triangulatedstack]=new char[strlen(noext2)+1];
+      strcpy(surface_filename[current_triangulatedstack],noext2);
+    }
+
+      
+  delete [] noext2;
+  delete [] noext1;
+
+  this->UpdateAfterExternalEditing();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+vtkpxTriangulatedStackSource* vtkpxGUI4DTriangulatedStackControl::GetTriangulatedStack(int frame,int index)
+{
+  if (this->triangulatedStackCollection==NULL)
+    return NULL;
+
+  frame=Irange(frame,0,this->NumberOfFrames-1);
+  index=Irange(index,0,this->NumberOfTriangulatedStacks);
+
+  int ind=frame*this->NumberOfTriangulatedStacks+index;
+  return (vtkpxTriangulatedStackSource*)this->triangulatedStackCollection->GetItemAsObject(ind);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DTriangulatedStackControl::SetCurrentFrame(int t)
+{
+  if (t<0) 
+    t=this->NumberOfFrames-1;
+  if (t>this->NumberOfFrames-1)
+    t=0;
+
+  if (!this->Initialized)
+    return;
+
+  this->ChangeFrame(t);
+  this->UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUI4DTriangulatedStackControl::GetCurrentFrame()
+{
+  return this->CurrentFrame;
+}
+
+int vtkpxGUI4DTriangulatedStackControl::GetNumberOfFrames()
+{
+  return this->NumberOfFrames;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DTriangulatedStackControl::DoCurvatures(int mode,int moption)
+{
+  if (mode==0)
+    {
+      if (this->optionDialog->isOpen())
+	return;
+
+      delete this->optionDialog;
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,2);
+      this->optionDialog->initDisplay();
+
+      this->optionDialog->setTitleDescription("Computing Curvatures",
+					      "Enter Parameters for Curvature Computation");
+      this->optionDialog->setioption(0,"Scale","%d",4);
+      this->optionDialog->setioption(1,"Smooth Iterations","%d",50);
+      this->optionDialog->setMenuOption(moption);
+      this->optionDialog->popupDialog();
+    }
+
+  if (mode==1)
+    {
+      int scale=Irange(this->optionDialog->getioption(0)  ,2,6);
+      int iterations=Irange(this->optionDialog->getioption(1),0,100);
+
+      PXTkApp::popupConsole();
+      for (int frame=0;frame<this->NumberOfFrames;frame++)
+	{
+	  vtkpxTriangulatedStackSource *stack=this->GetTriangulatedStack(frame,current_triangulatedstack);
+	  if (iterations>0)
+	    stack->NonShrinkSmooth(0.33,0.34,iterations);
+	  stack->ComputeCurvatures(scale);
+	  stack->Update();
+	  sprintf(pxtk_buffer3,"Compute Curvatures for frame %d (%d,%d)\n",frame+1,scale,iterations);
+	  PXTkApp::printToConsole(pxtk_buffer3);
+	}
+      
+      this->UpdateAfterExternalEditing();
+    }
+      
+      
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUI4DTriangulatedStackControl::DoShapeTracking(int mode,int moption)
+{
+  if (mode==0)
+    {
+      if (this->optionDialog->isOpen())
+	return;
+
+      delete this->optionDialog;
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,4);
+      this->optionDialog->initDisplay();
+
+      this->optionDialog->setTitleDescription("Shape-based Tracking",
+					      "Enter  Parameters for Shape Tracking");
+      this->optionDialog->setioption(0,"Start Frame","%d",1);
+      this->optionDialog->setioption(1,"Stop  Frame","%d",9);
+      this->optionDialog->setioption(2,"Search Window","%d",3);
+      this->optionDialog->setioption(3,"Surface Subdivision","%d",2);
+      
+      this->optionDialog->setMenuOption(moption);
+      this->optionDialog->popupDialog();
+    }
+
+  if (mode==1)
+    {
+
+      sprintf(pxtk_buffer,"%s_01_02_init_sm1.match",surface_filename[current_triangulatedstack]);
+      char* fname=this->EventManager->getSaveFilename("Save tracking results",pxtk_buffer,"Shape tracking results","*_01_02_init_sm1.match");
+      if (fname==NULL)
+	return;
+
+      char* first=strstr(fname,"_01_02_init_sm1.match");
+      if (first!=NULL)
+	strncpy(pxtk_buffer4,fname,(first-fname));
+      else
+	strcpy(pxtk_buffer4,fname);
+
+      int bframe=Irange(this->optionDialog->getioption(0)  ,0,this->NumberOfFrames-1);
+      int eframe=Irange(this->optionDialog->getioption(1)  ,0,this->NumberOfFrames-1);
+      int searchwindow=Irange(this->optionDialog->getioption(2),1,10);
+      int subdivision=Irange(this->optionDialog->getioption(3),0,3);
+
+      PXTkApp::popupConsole();
+
+      if (eframe<bframe)
+	eframe+=this->NumberOfFrames;
+
+      for (int frame=bframe;frame<eframe;frame++)
+	{
+	  vtkpxTriangulatedStackSource *stack=this->GetTriangulatedStack(frame,current_triangulatedstack);
+	  int nextf=frame+1;
+	  if (nextf>this->NumberOfFrames)
+	    nextf-=this->NumberOfFrames;
+	  vtkpxTriangulatedStackSource *stack2=this->GetTriangulatedStack(nextf,current_triangulatedstack);
+
+	  sprintf(pxtk_buffer2,"%s_%02d_%02d_init_sm1.match",pxtk_buffer4,frame,frame+1);
+	  int ok=vtkpxShapeTracking::OldStyleShapeTracking(stack,stack2,pxtk_buffer2,
+							   searchwindow,subdivision);
+	  sprintf(pxtk_buffer3,"Saved results for frame %d in %s (%d)\n",frame+1,pxtk_buffer2,ok);
+	  PXTkApp::printToConsole(pxtk_buffer3);
+	}
+    }
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUI4DTriangulatedStackControl.h b/bioimagesuite30_src/GUI/vtkpxGUI4DTriangulatedStackControl.h
new file mode 100644
index 0000000..54b5a55
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUI4DTriangulatedStackControl.h
@@ -0,0 +1,175 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUI4DTriangulatedStackControl.h,v $
+  Language:  C++
+  Date:      $Date: 2002/04/09 15:46:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUI4DTriangulatedStackControl - Base Image Viewer
+// .SECTION Description
+
+#ifndef __vtkpxGUI4DTriangulatedStackControl_h
+#define __vtkpxGUI4DTriangulatedStackControl_h
+
+#include "vtkpxGUITriangulatedStackControl.h"
+
+
+class vtkImageData;
+class vtkpxGUI4DRenderer;
+class vtkCollection;
+class vtkActorCollection;
+
+class vtkpxGUI4DTriangulatedStackControl : public vtkpxGUITriangulatedStackControl 
+{
+public:
+
+  static vtkpxGUI4DTriangulatedStackControl *New();
+  vtkTypeMacro(vtkpxGUI4DTriangulatedStackControl,vtkpxGUITriangulatedStackControl);
+  
+  // Description:
+  // Initialize Display and add Renderer 
+  virtual char*  Initialize(const char* name,int inside);
+  virtual char*  Initialize(const char* name,const char* name2,int inside);
+
+  // Description:
+  // Set Renderer
+  virtual void   SetRenderer(vtkpxGUI4DRenderer *rendererer,int num);
+  virtual void   SetRenderer(vtkpxGUI4DRenderer *rendererer,int num,int wireframe);
+
+  // Description:
+  // Update Display
+  virtual void   Update();
+  virtual void   UpdateDisplay();
+
+
+  // Description:
+  // Set Image Level,Plane And Frame 
+  virtual void SetImage(vtkImageData* image,int orientation,int level=0,int frame=0);
+  virtual void SetImage(vtkImageData* image);
+
+  // Description:
+  // Event Manager 
+  virtual int    HandleEvent(int);
+
+  // Description:
+  // Get Triangulated Stack from Collection
+  virtual vtkpxTriangulatedStackSource* GetTriangulatedStack(int frame,int index);
+
+  // Description:
+  // If outside process modified triangulateds (using GetTriangulatedStack) this functions needs to
+  // be called to re-synchronize the GUI etc
+  virtual void UpdateAfterExternalEditing();
+
+  // Description:
+  // Enable Change Of Frame from this control -- bad idea 
+  //virtual void EnableFrameScale(int enable);
+
+  // Description:
+  // Frame Stuff
+  virtual void SetCurrentFrame(int fr);
+  virtual int  GetCurrentFrame();
+  virtual int  GetNumberOfFrames();
+
+  // Description:
+  // Load / Save
+  virtual int  MultiLoad(const char* fname);
+  virtual int  MultiSave(const char* fname);
+
+protected:
+
+  vtkpxGUI4DTriangulatedStackControl();
+  virtual ~vtkpxGUI4DTriangulatedStackControl();
+
+  // Description:
+  // Disable these two functions insist on multirenderer 
+  virtual void   SetRenderer(vtkRenderer *rendererer,int num);
+  virtual void   SetRenderer(vtkRenderer *rendererer,int num,int wireframe);
+
+
+  // Description:
+  // Collection Stuff
+  vtkCollection*       triangulatedStackCollection;
+  vtkActorCollection*  triangulatedStackActorCollection;
+  vtkpxGUI4DRenderer*  MultiRenderer[TSP_MAX_RENDERERS];
+  int                  wireframemode[TSP_MAX_RENDERERS];
+  char*                surface_filename[TSP_MAX_COLLECTIONS];
+
+
+  // Description:
+  // Frame Stuff
+  int   CurrentFrame;
+  int   NumberOfFrames;
+  int   ActualNumberOfFrames;
+
+
+  // Description:
+  // Initialize TriangulatedStacks
+  virtual void InitializeTriangulatedStacks();
+  virtual void ResetTriangulatedStacks();
+
+  // Description:
+  // Frame Update Stuff 
+  virtual void CreateFrames(int numframes);
+  virtual void UpdateFrame(int frame);
+  virtual void ChangeFrame(int newframe);
+
+  // Description:
+  // Handle Callbacks for GUI Stuff
+  virtual void DoCurvatures(int mode,int moption=-1);
+  virtual void DoShapeTracking(int mode,int moption=-1);
+
+};
+
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIAbstractMultisliceEditor.cpp b/bioimagesuite30_src/GUI/vtkpxGUIAbstractMultisliceEditor.cpp
new file mode 100644
index 0000000..a5bc5ee
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIAbstractMultisliceEditor.cpp
@@ -0,0 +1,1321 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIAbstractMultisliceEditor.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:14 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxGUIAbstractMultisliceEditor.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkpxImageExtractVOI.h"
+#include "vtkImageThreshold.h"
+#include "vtkImageSeedConnectivity.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkMath.h"
+#include "vtkbisObjectmapRegularization.h"
+#include "vtkpxDataArrayUndoStack.h"
+
+using namespace bioimagesuite_legacy;
+
+// Construct object with no children.
+vtkpxGUIAbstractMultisliceEditor::vtkpxGUIAbstractMultisliceEditor()
+{
+  for (int ia=0;ia< pxAME_NUM_COLOR_BUTTONS;ia++)
+    this->colorButton[ia]=NULL;
+  for (int ia=0;ia<pxAME_NUM_DIALOG_COLOR_BUTTONS;ia++)
+    this->dialogColorButton[ia]=NULL;
+
+
+  this->DefaultScaleMode=4;
+
+  objectmapcolormapname=new char[20];
+  strcpy(objectmapcolormapname,"object.cmap");
+  this->current_fill_color=1;
+  this->draw_mode=0;
+  this->old_draw_mode=0;
+  this->draw_mode3D=0;
+  this->MainImage=NULL;
+  this->Objectmap=NULL;
+  this->ObjectmapLookupTable=NULL;
+  this->SimpleMode=0;
+  this->Paint2DAxis=2;
+  this->SingleSliceMode=0;
+  this->paintMode=NULL;
+  this->paintMode3D=NULL;
+  this->smoothMode=NULL;
+  this->smoothConvergenceMode=NULL;
+  this->fillMode=NULL;
+  this->fillThresholds[0]=NULL;
+  this->fillThresholds[1]=NULL;
+  this->colorSelection=NULL;
+  this->connectFillMode=NULL;
+  this->voiNameEntry=NULL;
+  
+  this->UndoStack=vtkpxDataArrayUndoStack::New();
+  this->UndoStack->Initialize(40,5,VTK_INT);
+
+  this->ResetVOINames();
+}
+/* -------------------------------------------------------------------------*/
+vtkpxGUIAbstractMultisliceEditor::~vtkpxGUIAbstractMultisliceEditor()
+{
+  delete []  objectmapcolormapname;
+  if (this->MainImage)
+    this->MainImage->Delete();
+  if (this->Objectmap)
+    this->Objectmap->Delete();
+  if (this->ObjectmapLookupTable)
+    this->ObjectmapLookupTable->Delete();
+
+  this->UndoStack->Delete();
+
+
+}
+
+int vtkpxGUIAbstractMultisliceEditor::SetImagesAndLookupTable(vtkImageData* mainImage,vtkImageData* objectmap,vtkLookupTable* lkup,
+							      int iscolor)
+{
+  //  fprintf(stderr,"Setting Image and Objectmap %d %d\n",mainImage,objectmap);
+
+  if (mainImage==NULL || objectmap == NULL)
+    return 0;
+
+  if (mainImage->GetNumberOfPoints()!=objectmap->GetNumberOfPoints())
+    return 0;
+
+  if (this->MainImage==NULL)
+    this->MainImage=vtkImageData::New();
+  this->MainImage->ShallowCopy(mainImage);
+
+  this->CurrentImageIsColor=0;
+  if (iscolor>0)
+    {
+      if (this->MainImage->GetNumberOfScalarComponents()==3 && this->MainImage->GetScalarType()==VTK_UNSIGNED_CHAR)
+	this->CurrentImageIsColor=1;
+    }
+
+
+  if (this->fillThresholds[0]!=NULL)
+    {
+      //      fprintf(stderr,"Reseting thresholds\n");
+      if (!this->CurrentImageIsColor)
+	{
+	  double range[2]; this->MainImage->GetPointData()->GetScalars()->GetRange(range);
+	  sprintf(pxtk_buffer,"%.2f",0.8*range[1]+0.2*range[0]);
+	  this->fillThresholds[0]->setText(pxtk_buffer);
+	  sprintf(pxtk_buffer,"%.2f",range[1]);
+	  this->fillThresholds[1]->setText(pxtk_buffer);
+	} 
+      else 
+	{
+	  this->fillThresholds[0]->setText("204");
+	  this->fillThresholds[1]->setText("255");
+	}
+    }
+
+  if (this->colorSelection!=NULL)
+    {
+      if (this->CurrentImageIsColor)
+	this->colorSelection->enable(PXTrue);
+      else
+	this->colorSelection->enable(PXFalse);
+    }
+
+  if (this->Objectmap==NULL)
+    this->Objectmap=vtkImageData::New();
+  this->Objectmap->ShallowCopy(objectmap);
+
+
+
+  this->UndoStack->Reset();
+
+
+  if (this->ObjectmapLookupTable==NULL)
+    this->ObjectmapLookupTable=vtkLookupTable::New();
+  
+  if (lkup!=NULL)
+    {
+      this->ObjectmapLookupTable->DeepCopy(lkup);
+    }
+  else
+    {
+      this->CreateDefaultLookupTable();
+    }
+
+
+  this->UpdateColorButtons();
+
+  return 1;
+
+}
+/* -------------------------------------------------------------------------*/
+double vtkpxGUIAbstractMultisliceEditor::SetObjectmapWithUndo(vtkImageData* objectmap)
+{
+  if (objectmap == NULL || this->Objectmap==NULL)
+    return -1.0;
+
+  if (this->Objectmap->GetNumberOfPoints()!=objectmap->GetNumberOfPoints())
+    return -1.0;
+
+  vtkDataArray* olddata=this->Objectmap->GetPointData()->GetScalars();
+  vtkDataArray* newdata=objectmap->GetPointData()->GetScalars();
+  int nt=newdata->GetNumberOfTuples();
+
+  vtkDataArray* elements=this->UndoStack->GetNextArray();
+  
+  int dim[3]; this->Objectmap->GetDimensions(dim);
+
+  int index=0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  int old_color=(int)olddata->GetComponent(index,0);
+	  int new_color=(int)newdata->GetComponent(index,0);
+	  if (new_color!=old_color)
+	    this->ChangeObjectmapValue(elements,i,j,k,new_color);
+	  ++index;
+	}
+
+  double p=100.0*double(elements->GetNumberOfTuples())/double(nt);
+
+  /*  fprintf(stderr,"Changed %d/%d elements (%.2f %%)\n",
+      elements->GetNumberOfTuples(),nt,p);*/
+
+	  
+
+  this->UpdateViewerObjectmap();
+  this->UpdateViewerDisplay();
+  return p;
+
+}
+/* -------------------------------------------------------------------------*/
+
+char* vtkpxGUIAbstractMultisliceEditor::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+  
+  vtkpxGUIComponent::Initialize(name,inside);
+  this->EventManager->setTitle("Objectmap Editor");
+
+  PXTkFrame* manager=(PXTkFrame*)(this->EventManager->getMainWindow());
+
+  PXTkLabelFrame* fillFrame=new PXTkLabelFrame(this->EventManager,manager,"Paint Control");
+  PXTkFrame* bottomButtonFrame=new PXTkFrame(this->EventManager,manager);
+
+  manager->setPackMode(PXTrue);
+  manager->addChildren("-side bottom -expand false -fill x",bottomButtonFrame);
+  manager->addChildren("-side top    -expand true  -fill both",fillFrame);
+
+  this->CreateFillControl(fillFrame);
+
+  if (!inside)
+    {
+      PXTkButton* closeB=new PXTkButton(this->EventManager,bottomButtonFrame,"Close",3);
+      bottomButtonFrame->addChildren("-side right -expand false -fill x -padx 10",closeB);
+    }
+
+  return GetWidgetName();
+
+}
+int vtkpxGUIAbstractMultisliceEditor::CreateDefaultLookupTable(int voimode)
+{
+  if (this->ObjectmapLookupTable==NULL)
+    this->ObjectmapLookupTable=vtkLookupTable::New();
+  if (voimode==0)
+    vtkpxSurfaceUtil::DefaultObjectMapLookupTable(ObjectmapLookupTable,-1,1);
+  else
+    vtkpxSurfaceUtil::VOIObjectMapLookupTable(ObjectmapLookupTable,-1);
+  this->UpdateObjectmapColormap();
+
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIAbstractMultisliceEditor::HandleEvent(int event)
+{
+
+  if (event<10)
+    return this->EventManager->handleDirectEvent(event);
+
+
+  if (event>=821 && event<821+vtkpxSurfaceUtil::DefaultObjectMapLookupTableNumberOfColors())
+    {
+      current_fill_color=event-821;
+
+
+      if (current_fill_color==0)
+	{
+	  voiNameEntry->configure("-bg","black");
+	  voiNameEntry->configure("-fg","white");
+	}
+      else
+	{
+	  char* line=dialogColorButton[current_fill_color]->cget("-bg");	  
+	  strcpy(pxtk_buffer,line);
+	  editcolorframe->configure("-bg",pxtk_buffer);
+	  voiNameEntry->configure("-fg","black");
+	  voiNameEntry->configure("-bg","white");
+	}
+      voiNameEntry->setText(voiNames[current_fill_color].c_str());
+    }
+  else
+    {
+      switch(event)
+	{
+	case 800:
+	  this->draw_mode=paintMode->getIndex();
+	  if (this->draw_mode==10)
+	    {
+	      this->draw_mode3D=1;
+	      if (fillMode!=NULL)
+		fillMode->setState(PXTrue);
+	      if (connectFillMode!=NULL)
+		connectFillMode->setState(PXTrue);
+	      if (this->paintMode3D!=NULL)
+		paintMode3D->setState(PXTrue);
+	    }
+
+	  if (this->draw_mode==10)
+	    this->EventManager->messageBox("You have enabled a large brush ... go slowly!","Painting  Warning");
+	  break;
+
+	case 801:
+	  if (this->paintMode3D!=NULL)
+	    {
+	      if (this->draw_mode==10)
+		{
+		  paintMode3D->setState(PXTrue);
+		}
+	      else
+		{
+		  if (paintMode3D->getState())
+		    this->draw_mode3D=1;
+		  else
+		    this->draw_mode3D=0;
+		}
+	    }
+	  break;
+	  
+
+	case 802:
+	  this->colorButtonDialog->popupDialog();
+	  break;
+
+	  
+	case 803:
+	  this->LoadObjectmapColormap();
+	  break;
+	  
+	case 804:
+	  this->SaveObjectmapColormap();
+	  break;
+	  
+	case 805:
+	  this->CreateDefaultLookupTable();
+	  break;
+
+	case 806:
+	  this->EditColorButton(current_fill_color);
+	  break;
+
+	case 807:
+	  this->UndoLastObjectmapChange();
+	  break;
+
+	case 808:
+	  this->RedoLastObjectmapChange();
+	  break;
+
+	case 809:
+	  this->SmoothObjectmap();
+	  break;
+
+	case 810:
+	  // Update name
+	  //	  fprintf(stderr,"Updating VOI Name\n");
+		{
+	  char *line=voiNameEntry->getText();
+	  if (strlen(line)>0 && current_fill_color>0)
+	    voiNames[current_fill_color]=line;
+	  else
+	    voiNameEntry->setText(voiNames[current_fill_color].c_str());
+		}
+	  break;
+	  
+	default:
+	  vtkpxGUIComponent::HandleEvent(event);
+	}
+    }
+  
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIAbstractMultisliceEditor::GetPaintConnectMode()
+{
+  if (this->connectFillMode!=NULL)
+    {
+      if (connectFillMode->getState())
+	return 1;
+    }
+  return 0;
+
+}
+
+int vtkpxGUIAbstractMultisliceEditor::GetPaintUseThresholdMode()
+{
+  if (this->fillMode!=NULL)
+    {
+      if (fillMode->getState())
+	return 1;
+    }
+  return 0;
+
+}
+
+int vtkpxGUIAbstractMultisliceEditor::GetPaintUseMaskMode()
+{
+  if (baseImageMode!=NULL)
+    {
+      if (baseImageMode->getState()==PXTrue)
+	return 1;
+    }
+  return 0;
+}
+ 
+void vtkpxGUIAbstractMultisliceEditor::GetThresholds(float val[2])
+{
+  val[0]=0.0;
+  val[1]=0.0;
+  if (fillThresholds[0]==NULL || fillThresholds[1]==NULL)
+    return;
+
+  val[0]=atof(fillThresholds[0]->getText());
+  val[1]=atof(fillThresholds[1]->getText());
+
+  return;
+}
+
+int vtkpxGUIAbstractMultisliceEditor::GetCurrentColor()
+{
+  return current_fill_color;
+}
+
+int vtkpxGUIAbstractMultisliceEditor::GetPaintMode()
+{
+  return this->draw_mode;
+}
+
+int vtkpxGUIAbstractMultisliceEditor::GetPaint3DMode()
+{
+  return this->draw_mode3D;
+}
+
+
+void vtkpxGUIAbstractMultisliceEditor::ChangeObjectmapValue(vtkDataArray* elements,int i,int j,int k,int new_color)
+{
+  double old_color=this->Objectmap->GetScalarComponentAsDouble(i,j,k,0);
+  this->Objectmap->SetScalarComponentFromDouble(i,j,k,0,double(new_color));
+  double v[5];
+  v[0]=double(i);
+  v[1]=double(j);
+  v[2]=double(k);
+  v[3]=old_color;
+  v[4]=double(new_color);
+
+  if (elements!=NULL)
+    elements->InsertNextTuple(v);
+}
+
+void vtkpxGUIAbstractMultisliceEditor::UndoLastObjectmapChange()
+{
+  vtkDataArray* elements=this->UndoStack->GetNextUndoArray();
+  if (elements==NULL)
+    return;
+
+  //  vtkpxDataArrayUndoStack::ConsolidateArray(elements,3);
+
+  int nt=elements->GetNumberOfTuples();
+  for (int ia=nt-1;ia>=0;ia=ia-1)
+    {
+      int i=int(elements->GetComponent(ia,0));
+      int j=int(elements->GetComponent(ia,1));
+      int k=int(elements->GetComponent(ia,2));
+      double old_color=elements->GetComponent(ia,3);
+      double new_color=elements->GetComponent(ia,4);
+      this->Objectmap->SetScalarComponentFromDouble(i,j,k,0,old_color);
+    }
+
+  this->UpdateViewerObjectmap();
+  this->UpdateViewerDisplay();
+  this->UpdateUndoIndicesDisplay();
+}
+// --------------------------------------------------------------------------------------
+void vtkpxGUIAbstractMultisliceEditor::RedoLastObjectmapChange()
+{
+  vtkDataArray* elements=this->UndoStack->GetNextRedoArray();
+  if (elements==NULL)
+    return;
+
+  int nt=elements->GetNumberOfTuples();
+  for (int ia=0;ia<nt;ia++)
+    {
+      double* v=elements->GetTuple(ia);
+      int i=int(v[0]);
+      int j=int(v[1]);
+      int k=int(v[2]);
+      double old_color=v[3];
+      double new_color=v[4];
+      this->Objectmap->SetScalarComponentFromDouble(i,j,k,0,new_color);
+    }
+
+  this->UpdateViewerObjectmap();
+  this->UpdateViewerDisplay();
+  this->UpdateUndoIndicesDisplay();
+}
+// --------------------------------------------------------------------------------------
+void vtkpxGUIAbstractMultisliceEditor::UpdateUndoIndicesDisplay()
+{
+  if (this->Initialized==0)
+    return;
+
+  if (!this->Debug)
+    return;
+  
+  sprintf(pxtk_buffer,"C=%d U=%d (%d) R=%d (%d,m=%d)",
+	  this->UndoStack->GetCurrentIndex(),
+	  this->UndoStack->GetCurrentUndoIndex(),	  this->UndoStack->GetCurrentlyUndoing(),
+	  this->UndoStack->GetCurrentRedoIndex(),this->UndoStack->GetCurrentlyRedoing(),
+	  this->UndoStack->GetMaxIndex());
+  fprintf(stderr,"Status=%s\n",pxtk_buffer);
+}
+// -------------------------------------------------------------------------------------
+vtkDataArray* vtkpxGUIAbstractMultisliceEditor::GetNextArray()
+{
+  if (this->UndoStack==NULL)
+    return NULL;
+  return this->UndoStack->GetNextArray();
+}
+
+int vtkpxGUIAbstractMultisliceEditor::HandleClickedPoint(int x,int y,int z,int nbutton,int state)
+{
+  if (!this->EventManager->isOpen() && !this->EventManager->isInside())
+    return 0;
+
+  if ( nbutton==4  && state!=2)
+    return 0;
+
+  if (nbutton==4) 
+    {
+      if (draw_mode>0)
+	{
+	  this->old_draw_mode=this->draw_mode;
+	  this->draw_mode=0;
+	  this->paintMode->setIndex(draw_mode);
+	  return 0;
+	}
+      else
+	{
+	  this->draw_mode=this->old_draw_mode;
+	  this->old_draw_mode=0;
+	  this->paintMode->setIndex(draw_mode);
+	}
+      return 0;
+    }
+
+  if (nbutton!=1)
+    return 0;
+  
+  if (state==2 || this->draw_mode==0)
+    return 0;
+  
+
+  // Paint Mode
+  int   dim[3];   
+  int   lv[3];
+  this->MainImage->GetDimensions(dim);
+  lv[0]=Irange(x,0,dim[0]-1);
+  lv[1]=Irange(y,0,dim[1]-1);
+  lv[2]=Irange(z,0,dim[2]-1);
+  
+  //  fprintf(stderr,"Dimensions = %d %d %d, point=%d,%d,%d\n",dim[0],dim[1],dim[2],x,y,z);
+
+  int offset[3][3];
+  //fprintf(stderr,"\n");
+  int dm=draw_mode;
+  switch (dm)
+    {
+    case 7: dm=8; break;
+    case 8: dm=10; break;
+    case 9: dm=12; break;
+    case 10: dm=50; draw_mode3D=1; break;
+    }
+      
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      offset[ia][0]=Irange(lv[ia]-dm+1,0,dim[ia]-1);
+      offset[ia][1]=Irange(lv[ia]+dm-1,0,dim[ia]-1);
+    }
+  
+  if (draw_mode3D==0)
+    {
+      offset[this->Paint2DAxis][0]=lv[this->Paint2DAxis];
+      offset[this->Paint2DAxis][1]=lv[this->Paint2DAxis];
+    }
+
+  int seed[3];
+  for (int ia=0;ia<=2;ia++)
+    seed[ia]=lv[ia]-offset[ia][0];
+
+
+  //  fprintf(stderr,"draw_mode=%d, dm=%d, d3d=draw_mode3D\n",draw_mode,dm,draw_mode3D);
+      
+  PXBool thrmode=fillMode->getState();
+  PXBool cmode=connectFillMode->getState();
+  float a[2];
+  a[0]=atof(fillThresholds[0]->getText());
+  a[1]=atof(fillThresholds[1]->getText());
+
+  int selectcolor=0;
+
+  if (this->CurrentImageIsColor)
+    selectcolor=Irange(this->colorSelection->getIndex(),0,2);
+  
+
+  vtkImageData* sourceImage=this->MainImage;
+  int domask=0;
+
+  if (baseImageMode->getState()==PXTrue)
+    domask=1;
+
+  vtkDataArray* elements;
+  if (state==0)
+    elements=this->UndoStack->GetNextArray();
+  else
+    elements=this->UndoStack->GetCurrentArray();
+
+  if (elements==NULL)
+    {
+      fprintf(stderr,"Bad Undo Array ....\n");
+    }
+  
+  this->UpdateUndoIndicesDisplay();
+
+  if ( (cmode==PXTrue && thrmode==PXTrue) || draw_mode==10)
+    {
+      double vl=sourceImage->GetScalarComponentAsDouble(lv[0],lv[1],lv[2],selectcolor);
+      if (vl>=a[0] && vl<=a[1])
+	{
+	  vtkImageThreshold* thr=vtkImageThreshold::New();
+	  int dvoi[3];
+	  
+	  vtkpxImageExtractVOI* voi=vtkpxImageExtractVOI::New();
+	  voi->SetInput(sourceImage);
+	  voi->SetVOI(offset[0][0],offset[0][1],offset[1][0],offset[1][1],offset[2][0],offset[2][1]);
+	  voi->Update();
+	  voi->GetOutput()->GetDimensions(dvoi);
+	  
+	  if (this->CurrentImageIsColor)
+	    {
+	      vtkImageExtractComponents* extr=vtkImageExtractComponents::New();
+	      extr->SetInput(voi->GetOutput());
+	      //	      fprintf(stderr,"Using Color=%d\n",selectcolor);
+	      extr->SetComponents(selectcolor);
+	      extr->Update();
+	      thr->SetInput(extr->GetOutput());
+	      extr->Delete();
+	    }
+	  else
+	    {
+	      thr->SetInput(voi->GetOutput());
+	    }
+	  voi->Delete();
+	  
+	  thr->ThresholdBetween(a[0],a[1]);
+	  thr->SetInValue(1);
+	  thr->SetOutValue(0);
+	  thr->ReplaceInOn();
+	  thr->ReplaceOutOn();
+	  thr->SetOutputScalarTypeToUnsignedChar();
+	  
+	  vtkImageSeedConnectivity* connectivity=vtkImageSeedConnectivity::New();
+	  connectivity->SetInput(thr->GetOutput());
+	  connectivity->SetInputConnectValue(1);
+	  connectivity->AddSeed(seed[0],seed[1],seed[2]);
+	  connectivity->SetOutputConnectedValue(1);
+	  connectivity->SetOutputUnconnectedValue(0);
+	  connectivity->SetDimensionality(3);
+	  connectivity->Update();
+	  
+	  vtkImageData* tmp=connectivity->GetOutput();
+	  
+	  for (int i=0;i<dvoi[0];i++)
+	    for (int j=0;j<dvoi[1];j++)
+	      for (int k=0;k<dvoi[2];k++)
+		{
+		  double vl=tmp->GetScalarComponentAsDouble(i,j,k,0);
+		  if (vl>0)
+		    {
+		      int m=0;
+		      if (domask)
+			m=(this->Objectmap->GetScalarComponentAsDouble(i+offset[0][0],j+offset[1][0],k+offset[2][0],0)>0);
+		      if (m==0)
+			this->ChangeObjectmapValue(elements,i+offset[0][0],j+offset[1][0],k+offset[2][0],current_fill_color);
+		    }
+		}
+	  connectivity->Delete();
+	  thr->Delete();
+	}
+      /*      else 
+	{
+	  fprintf(stdout,"No Dice\n");
+	  }*/
+    }
+  else
+    {
+      for (int i=offset[0][0];i<=offset[0][1];i++)
+	for (int j=offset[1][0];j<=offset[1][1];j++)
+	  for (int k=offset[2][0];k<=offset[2][1];k++)
+	    {
+	      if (thrmode==PXFalse)
+		{
+		  int m=0;
+		  if (domask)
+		    m=(this->Objectmap->GetScalarComponentAsDouble(i,j,k,0)>0);
+		  if (m==0)
+		    this->ChangeObjectmapValue(elements,i,j,k,current_fill_color);
+		}
+	      else
+		{
+		  double vl=sourceImage->GetScalarComponentAsDouble(i,j,k,selectcolor);
+		  if (vl>=a[0] && vl<=a[1])
+		    {
+		      int m=0;
+		      if (domask)
+			m=(this->Objectmap->GetScalarComponentAsDouble(i,j,k,0)>0);
+		      if (m==0)
+			this->ChangeObjectmapValue(elements,i,j,k,current_fill_color);
+		    }
+		}
+	    }
+    }
+  
+  this->UpdateViewerObjectmap();
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIAbstractMultisliceEditor::DisablePainting()
+{
+  if (this->draw_mode==0)
+    return 0;
+  this->draw_mode=0;
+  paintMode->setIndex(0,PXFalse);
+  return 1;
+}
+
+int vtkpxGUIAbstractMultisliceEditor::EnablePainting()
+{
+  if (this->draw_mode!=0)
+    return 0;
+  this->draw_mode=1;
+  paintMode->setIndex(1,PXFalse);
+  return 1;
+}
+
+PXTkFrame* vtkpxGUIAbstractMultisliceEditor::GetExtraFrame() 
+{ 
+  return this->extraFrame; 
+}
+
+char* vtkpxGUIAbstractMultisliceEditor::GetExtraFrameName()
+{
+  if (this->extraFrame==NULL)
+    return NULL;
+
+  return this->extraFrame->getWidgetName();
+}
+
+int vtkpxGUIAbstractMultisliceEditor::CreateFillControl(PXTkFrame* fillframe)
+{
+
+  PXTkFrame* voiNameFrame=new PXTkFrame(this->EventManager,fillframe);
+  PXTkFrame* colorframe1=new PXTkFrame(this->EventManager,fillframe);
+  PXTkFrame* colorframe2=new PXTkFrame(this->EventManager,fillframe);
+  editcolorframe=new PXTkFrame(this->EventManager,fillframe);
+  PXTkFrame* fillmodeframe=new PXTkFrame(this->EventManager,fillframe);
+  PXTkFrame* fillmodeframe2=new PXTkFrame(this->EventManager,fillframe);
+  PXTkFrame* buttonframe=new PXTkFrame(this->EventManager,fillframe);
+  PXTkFrame* paintframe=new PXTkFrame(this->EventManager,fillframe);
+  this->extraFrame=new PXTkFrame(this->EventManager,fillframe);
+  
+  PXTkLabelFrame* buttonframe2=new PXTkLabelFrame(this->EventManager,fillframe,"Colormap");
+  PXTkLabelFrame* buttonframe3=new PXTkLabelFrame(this->EventManager,fillframe,"Objectmap Smoothing");
+
+
+  PXTkButton* b11=new PXTkButton(this->EventManager,buttonframe2,"Load",803);
+  PXTkButton* b21=new PXTkButton(this->EventManager,buttonframe2,"Save",804);
+  PXTkButton* b31=new PXTkButton(this->EventManager,buttonframe2,"Restore",805);
+  buttonframe2->addChildren("-side left -padx 1 -expand true -fill x",b11,b21,b31);
+
+
+  fillframe->addChildren("-side bottom -expand false -fill x -pady 1",buttonframe2,buttonframe3);
+  fillframe->addChildren("-side top -expand false -fill x -pady 1",voiNameFrame,colorframe1,colorframe2,editcolorframe);
+  fillframe->addChildren("-side top -expand false -fill x -pady 1",paintframe,fillmodeframe,fillmodeframe2);
+  fillframe->addChildren("-side top -expand false -fill x -pady 1",buttonframe,extraFrame);
+
+  if (this->SimpleMode==0)
+    {
+      PXTkButton* popupbut=new PXTkButton(this->EventManager,editcolorframe,"More Colors",802);
+      editcolorframe->addChildren("-side right -padx 0 -expand false -fill x",popupbut);
+    }
+  PXTkButton* b5=new PXTkButton(this->EventManager,editcolorframe,"Edit Color",806);
+  editcolorframe->addChildren("-side left -padx 10",b5);
+
+  voiNameEntry=new PXTkEntry(this->EventManager,voiNameFrame);
+  voiNameEntry->configure("-fg","black");
+  voiNameEntry->configure("-bg","white");
+  voiNameEntry->setText(voiNames[current_fill_color].c_str());
+  PXTkButton* voiNameUpdate=new PXTkButton(this->EventManager,voiNameFrame,"Upd",810);
+  voiNameFrame->addChildren("-side right -padx 2 -expand false",voiNameUpdate);
+  voiNameFrame->addChildren("-side left -padx 0 -expand true -fill x",voiNameEntry);
+
+
+  for (int k=0;k<pxAME_NUM_COLOR_BUTTONS;k++)
+    {
+      sprintf(pxtk_buffer,"%d",k);
+      if (k==0)
+	colorButton[k]=new PXTkRadioButton(this->EventManager,colorframe1,pxtk_buffer,821+k);
+      else if (k<=4)
+	colorButton[k]=new PXTkRadioButton(this->EventManager,colorframe1,pxtk_buffer,821+k,colorButton[0]);
+      else
+	colorButton[k]=new PXTkRadioButton(this->EventManager,colorframe2,pxtk_buffer,821+k,colorButton[0]);
+    
+      colorButton[k]->configure("-width",4);
+
+      if (k<=4)
+	colorframe1->addChildren("-side left -padx 0 -expand true -fill x",colorButton[k]);
+      else
+	colorframe2->addChildren("-side left -padx 0 -expand true -fill x",colorButton[k]);
+    }
+
+  this->colorButtonDialog=new PXTkDialog(this->EventManager,colorframe2,"Select Colors",PXFalse);
+  this->colorButtonDialog->initDisplay();
+
+  PXTkFrame* cframe=(PXTkFrame*)this->colorButtonDialog->getMainWindow();
+
+  PXTkButton* closebut=new PXTkButton(colorButtonDialog,cframe,"Close",3);
+  cframe->addChildren("-side bottom -padx 0 -expand true -fill x",closebut);
+
+  int maxc=vtkpxSurfaceUtil::DefaultObjectMapLookupTableNumberOfColors();
+  if (maxc>pxAME_NUM_DIALOG_COLOR_BUTTONS)
+    maxc=pxAME_NUM_DIALOG_COLOR_BUTTONS;
+
+  for (int i=0;i<maxc;i+=2)
+    {
+      PXTkFrame* afr=new PXTkFrame(this->EventManager,cframe);
+      cframe->addChildren("-side top -padx 0 -expand true -fill x",afr);
+      sprintf(pxtk_buffer,"%d",i);
+      this->dialogColorButton[i]=new PXTkRadioButton(this->EventManager,afr,pxtk_buffer,821+i,colorButton[0]);
+      afr->addChildren("-side left -padx 0 -expand true -fill x",this->dialogColorButton[i]);
+      if ((i+1)<maxc)
+	{
+	  sprintf(pxtk_buffer,"%d",i+1);
+	  this->dialogColorButton[i+1]=new PXTkRadioButton(this->EventManager,afr,pxtk_buffer,821+i+1,colorButton[0]);
+	  afr->addChildren("-side left -padx 0 -expand true -fill x",this->dialogColorButton[i+1]);
+	}
+    }
+
+  colorButtonDialog->popdownDialog();
+
+
+
+  PXTkLabel*  md=new PXTkLabel(this->EventManager,paintframe,"Mode (Shift-Mouse 1 to Toggle On/Off):");
+  md->configure("-bg","black");
+  md->configure("-fg","white");
+  md->configure("-padx","0");
+
+  paintMode=new PXTkOptionMenu(this->EventManager,paintframe,"Off",800);
+  paintMode->addOption("Brush-1");
+  paintMode->addOption("Brush-2");
+  paintMode->addOption("Brush-3");
+  paintMode->addOption("Brush-4");
+  paintMode->addOption("Brush-5");
+  paintMode->addOption("Brush-6");
+  paintMode->addOption("Brush-8");
+  paintMode->addOption("Brush-10");
+  paintMode->addOption("Brush-12");
+  paintMode->addOption("Brush-50");
+  paintMode->setIndex(this->draw_mode);
+
+  paintframe->addChildren("-side left -padx 2",md,paintMode);
+
+
+  PXTkLabel*  md2=new PXTkLabel(this->EventManager,buttonframe3,"Factor:");
+  md->configure("-padx","0");
+
+  this->smoothMode=new PXTkOptionMenu(this->EventManager,buttonframe3,"1.0",-1);
+  this->smoothMode->addOption("2.0");
+  this->smoothMode->addOption("4.0");
+  this->smoothMode->addOption("8.0");
+  this->smoothMode->addOption("16.0");
+  this->smoothMode->addOption("32");
+  this->smoothMode->addOption("64.0");
+  this->smoothMode->setIndex(3);
+
+  PXTkLabel*  md3=new PXTkLabel(this->EventManager,buttonframe3,"Conv:");
+  md3->configure("-padx","0");
+
+  this->smoothConvergenceMode=new PXTkOptionMenu(this->EventManager,buttonframe3,"0.025",-1);
+  this->smoothConvergenceMode->addOption("0.05");
+  this->smoothConvergenceMode->addOption("0.1");
+  this->smoothConvergenceMode->addOption("0.2");
+  this->smoothConvergenceMode->addOption("0.4");
+  this->smoothConvergenceMode->addOption("0.8");
+  this->smoothConvergenceMode->setIndex(3);
+
+  PXTkButton* smoothbut=new PXTkButton(this->EventManager,buttonframe3,"Smooth",809);
+
+  paintframe->addChildren("-side right -padx 2",smoothbut);
+  paintframe->addChildren("-side left -padx 1 -expand true -fill x",md2,this->smoothMode,md3,this->smoothConvergenceMode);
+
+  if (this->SingleSliceMode!=1)
+    {
+      paintMode3D=new PXTkCheckButton(this->EventManager,fillmodeframe2,"3D",801);
+      editcolorframe->addChildren("-side left -padx 2",paintMode3D);
+    }
+
+
+  fillMode=new PXTkCheckButton(this->EventManager,fillmodeframe2,"Use Thrshld",-1);
+  connectFillMode=new PXTkCheckButton(this->EventManager,fillmodeframe2,"Connect",-1);
+  baseImageMode=new PXTkCheckButton(this->EventManager,fillmodeframe2,"No Overwrite",-1);
+  fillmodeframe2->addChildren("-side left -padx 0 -expand false -fill x",baseImageMode,fillMode,connectFillMode);
+
+  for (int ia=0;ia<=1;ia++)
+    {
+      fillThresholds[ia]=new PXTkEntry(this->EventManager,fillmodeframe);
+      fillThresholds[ia]->configure("-width",6);
+      sprintf(pxtk_buffer,"%f",300.0*float(ia));
+      fillThresholds[ia]->setText(pxtk_buffer);
+    }
+
+  this->colorSelection=new PXTkOptionMenu(this->EventManager,fillmodeframe,"R",-1);
+  this->colorSelection->addOption("G");
+  this->colorSelection->addOption("B");
+  fillmodeframe->addChildren("-side right -padx 1 -expand f ",this->colorSelection);
+  this->colorSelection->enable(PXFalse);
+
+  fillmodeframe->addChildren("-side left -padx 1 -expand t -fill x",fillThresholds[0],fillThresholds[1]);
+
+  PXTkButton* b01=new PXTkButton(this->EventManager,buttonframe,"Undo",807);
+  PXTkButton* b02=new PXTkButton(this->EventManager,buttonframe,"Redo",808);
+  buttonframe->addChildren("-side left -padx 1 -expand true -fill x",b01,b02);
+
+
+  UpdateColorButtons();
+
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIAbstractMultisliceEditor::UpdateObjectmapColormap()
+{
+  int num=ObjectmapLookupTable->GetNumberOfColors();
+  UpdateColorButtons();
+  this->ObjectmapLookupTable->Modified();
+  this->UpdateViewerObjectmapColormap();
+  this->Objectmap->Modified();
+  this->UpdateViewerObjectmap();
+  this->UpdateViewerDisplay();
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIAbstractMultisliceEditor::LoadObjectmapColormap()
+{
+  char* line=this->EventManager->getOpenFilename("Objectmap Colormap File name","Colormap Files","*.cmap*");
+  
+  if (line==NULL)
+    return 0;
+  if (strlen(line)==0)
+    return 0;
+  strcpy(pxtk_buffer2,line);
+
+  gzFile fin=gzsuffixopen(pxtk_buffer2,"rb");
+  if (!fin)
+    return 0;
+  
+  gzgets(fin,pxtk_buffer,100);
+  if (gzfindstringinstring(pxtk_buffer,"#IPAGRGBAColormap")==0)
+    {
+      gzclose(fin);
+      return 0;
+    }
+  
+  gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+  int numc;  sscanf(pxtk_buffer,"%d",&numc);
+
+  int maxc=vtkpxSurfaceUtil::DefaultObjectMapLookupTableNumberOfColors();
+  if (numc>maxc)
+    numc=maxc;
+
+
+  double dat[2];
+  gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+  sscanf(pxtk_buffer,"%lf %lf",&dat[0],&dat[1]);
+
+  if (numc>ObjectmapLookupTable->GetNumberOfColors())
+    {
+      ObjectmapLookupTable->SetNumberOfTableValues(numc);
+      ObjectmapLookupTable->SetTableRange(dat);
+    }
+
+  //  double d[2];     ObjectmapLookupTable->GetTableRange(d);
+  //  fprintf(stderr,"New Range = %f:%f\n",d[0],d[1]);
+  
+
+  gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+  for (int i=0;i<numc;i++)
+    {
+      double val[4];
+      int tmp;
+      gzgets(fin,pxtk_buffer,100);
+      sscanf(pxtk_buffer,"%d %lf %lf %lf %lf",&tmp,&val[0],&val[1],&val[2],&val[3]);
+      ObjectmapLookupTable->SetTableValue(tmp,val);
+    }
+  gzclose(fin);
+    
+  delete [] objectmapcolormapname;
+  objectmapcolormapname=new char[strlen(pxtk_buffer2)+1];
+  strcpy(objectmapcolormapname,pxtk_buffer2);
+
+
+  this->UpdateObjectmapColormap();
+  return 1;
+
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIAbstractMultisliceEditor::SaveObjectmapColormap()
+{
+  char* line=this->EventManager->getSaveFilename("Save Objectmap Colormap",objectmapcolormapname,"Colormaps","*.cmap");
+  if (line==NULL)
+    return 0;
+  if (strlen(line)==0)
+    return 0;
+  
+  strcpy(pxtk_buffer2,line);
+
+  FILE* fout=fopen(pxtk_buffer2,"w");
+  if (!fout)
+    return 0;
+
+  fprintf(fout,"#IPAGRGBAColormap\n");
+  fprintf(fout,"#Number of Colors\n%d\n",ObjectmapLookupTable->GetNumberOfColors());
+
+  double dat[2];
+  ObjectmapLookupTable->GetTableRange(dat);
+  fprintf(fout,"#Range\n %6.3f %6.3f \n",dat[0],dat[1]);
+
+  fprintf(fout,"#Colors\n#Index  R     G     B  Alpha\n");
+  for (int i=0;i<ObjectmapLookupTable->GetNumberOfColors();i++)
+      {
+	double val[4];
+	ObjectmapLookupTable->GetTableValue(i,val);
+	fprintf(fout,"%4d %5.3f %5.3f %5.3f %5.3f\n",i,val[0],val[1],val[2],val[3]);
+      }
+  fclose(fout);
+
+  if (strcmp(objectmapcolormapname,pxtk_buffer2)!=0)
+      {
+	delete [] objectmapcolormapname;
+	objectmapcolormapname=new char[strlen(pxtk_buffer2)+1];
+	strcpy(objectmapcolormapname,pxtk_buffer2);
+      }
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIAbstractMultisliceEditor::UpdateColorButtons()
+{
+  if (ObjectmapLookupTable==NULL)
+    return 0;
+  int num=ObjectmapLookupTable->GetNumberOfColors();
+
+  
+  int maxc=vtkpxSurfaceUtil::DefaultObjectMapLookupTableNumberOfColors();
+  if (maxc>pxAME_NUM_DIALOG_COLOR_BUTTONS)
+    maxc=pxAME_NUM_DIALOG_COLOR_BUTTONS;
+
+
+  if (num>maxc)
+    num=maxc;
+
+
+
+  for (int k=0;k<num;k++)
+    {
+      double cd[4]; ObjectmapLookupTable->GetTableValue(k,cd);
+      int c[3];
+      strcpy(pxtk_buffer,"#");
+      
+      for (int i=0;i<=2;i++)
+	{
+	  c[i]=int(cd[i]*255.0);
+	  for (int byte=0;byte<=1;byte++)
+	    {
+	      int val=0;
+	      if (byte==0)
+		val=c[i]/16;
+	      else
+		val=c[i]-16*int(c[i]/16);
+	      
+	      switch (val)
+		{
+		case 10:    strcat(pxtk_buffer,"A");  break;
+		case 11:    strcat(pxtk_buffer,"B");  break;
+		case 12:    strcat(pxtk_buffer,"C");  break;
+		case 13:    strcat(pxtk_buffer,"D");  break;
+		case 14:    strcat(pxtk_buffer,"E");  break;
+		case 15:    strcat(pxtk_buffer,"F");  break;
+		default:    sprintf(pxtk_buffer,"%s%1d",pxtk_buffer,val); break;
+		  
+		}
+	    }
+	}
+      //      fprintf(stderr,"k=%d, value=%.2f,%.2f,%.2f,%.2f --> %s\n",k,cd[0],cd[1],cd[2],cd[3],pxtk_buffer);
+
+      if (k<pxAME_NUM_COLOR_BUTTONS)
+	{
+	  if (colorButton[k]!=NULL)
+	    {
+	      if (k<num)
+		{
+		  
+		  colorButton[k]->configure("-bg",pxtk_buffer);
+		  colorButton[k]->enable(PXTrue);
+		}
+	      else
+		{
+		  colorButton[k]->configure("-bg","black");
+		  colorButton[k]->enable(PXFalse);
+		}
+	    }
+	}
+
+      //      fprintf(stderr,"On to Dialog Color Button k=%d\n");
+
+      if (k<maxc)
+	{
+	  if (dialogColorButton[k]!=NULL)
+	    {
+	      //	      fprintf(stderr,"Doing Dialog Button %d\n",k);
+	      if (k<num)
+		{
+		  //		  fprintf(stderr,"Configuring Dialog Button %d\n",k);
+		  dialogColorButton[k]->configure("-bg",pxtk_buffer);
+		  dialogColorButton[k]->enable(PXTrue);
+		}
+	      else
+		{
+		  dialogColorButton[k]->configure("-bg","black");
+		  dialogColorButton[k]->enable(PXFalse);
+		}
+	    }
+	}
+      //fprintf(stderr,"\t\tDone k=%d\n",k);
+    }
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIAbstractMultisliceEditor::EditColorButton(int n)
+{
+  if (n<0 || n>=vtkpxSurfaceUtil::DefaultObjectMapLookupTableNumberOfColors())
+    return 0;
+  if (dialogColorButton[n]==NULL)
+    return 0;
+
+  double c[3],cd[4];
+  ObjectmapLookupTable->GetTableValue(n,cd);
+  sprintf(pxtk_buffer2,"Color %d",n);
+  int a=this->EventManager->d_colorBox(pxtk_buffer2,cd[0],cd[1],cd[2]);
+  if (a==1)
+    {
+      ObjectmapLookupTable->SetTableValue(n,cd);
+      this->UpdateObjectmapColormap();
+      char* line=dialogColorButton[n]->cget("-bg");
+      strcpy(pxtk_buffer,line);
+      editcolorframe->configure("-bg",pxtk_buffer);
+    }
+
+  return a;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIAbstractMultisliceEditor::RenamePaintOffLabel(const char* newname)
+{
+  if (this->paintMode==NULL)
+    return;
+
+  this->paintMode->changeLabel(0,newname);
+
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUIAbstractMultisliceEditor::SmoothObjectmap()
+{
+
+  if (this->Objectmap==NULL)
+    return 0;
+
+  double lambda=2.0;
+  if (this->smoothMode!=NULL)
+    {
+      double v=(double)this->smoothMode->getIndex();
+      lambda=pow(2.0,v);
+    }
+
+  double epsilon=0.2;
+  if (this->smoothConvergenceMode!=NULL)
+    {
+      double v=(double)this->smoothConvergenceMode->getIndex();
+      epsilon=0.025*pow(2.0,v);
+    }
+
+  vtkbisObjectmapRegularization* segm=vtkbisObjectmapRegularization::New();
+  segm->SetInput(this->Objectmap);
+  segm->SetSmoothness(lambda);
+  segm->SetConvergencePercentage(epsilon);
+  segm->Update();
+
+
+  double p=this->SetObjectmapWithUndo(segm->GetOutput());
+
+  char pxtk_buffer4[200];
+  if (p>0.0)
+    sprintf(pxtk_buffer4,"Objectmap smoothed %.2f %% of all voxels changed",p);
+  else
+    sprintf(pxtk_buffer4,"Objectmap smoothing failed.",p);
+  
+  this->EventManager->messageBox(pxtk_buffer4,"Objectmap Smoothing");
+  
+  segm->Delete();
+  return 1;
+}
+// ------------------------------------------------------------------------------
+int vtkpxGUIAbstractMultisliceEditor::SetVOISelectMode(double minthr,double maxthr,int force3dbrush)
+{
+  if (fillThresholds[0]==NULL || fillThresholds[1]==NULL)
+    return 0;
+
+  sprintf(pxtk_buffer,"%.2f",minthr);  fillThresholds[0]->setText(pxtk_buffer);
+  sprintf(pxtk_buffer,"%.2f",maxthr);  fillThresholds[1]->setText(pxtk_buffer);
+
+  if (force3dbrush==0)
+    return 1;
+
+  if (fillMode!=NULL)
+    fillMode->setState(PXTrue);
+  if (connectFillMode!=NULL)
+    connectFillMode->setState(PXTrue);
+  if (this->paintMode3D!=NULL)
+    paintMode3D->setState(PXTrue);
+
+  this->draw_mode=10;
+  this->draw_mode3D=1;
+  this->paintMode->setIndex(10);
+  return 1;
+}
+// ------------------------------------------------------------------------------
+int vtkpxGUIAbstractMultisliceEditor::SetVOIName(int index,char* name)
+{
+if (index<0)
+    index=0;
+ if (index>=pxAME_NUM_DIALOG_COLOR_BUTTONS)
+   index=pxAME_NUM_DIALOG_COLOR_BUTTONS-1;
+ 
+  if (strlen(name)>0)
+    {
+      voiNames[index]=name;
+
+      if (voiNameEntry!=NULL && current_fill_color==index)
+	voiNameEntry->setText(voiNames[index].c_str());
+      return 1;
+    }
+  
+  return 0;
+}
+
+const char* vtkpxGUIAbstractMultisliceEditor::GetVOIName(int index)
+{
+  if (index<0)
+    index=0;
+  if (index>=pxAME_NUM_DIALOG_COLOR_BUTTONS)
+    index=pxAME_NUM_DIALOG_COLOR_BUTTONS-1;
+  
+  return voiNames[index].c_str();
+}
+
+int vtkpxGUIAbstractMultisliceEditor::GetNumberOfVOIS()
+{
+  return pxAME_NUM_DIALOG_COLOR_BUTTONS;
+}
+
+void vtkpxGUIAbstractMultisliceEditor::ResetVOINames()
+{
+  voiNames[0]="Background";
+  for (int ia=1;ia<pxAME_NUM_DIALOG_COLOR_BUTTONS;ia++)
+    {
+      sprintf(pxtk_buffer,"VOI %d",ia);
+      voiNames[ia]=pxtk_buffer;
+    }
+
+  if (voiNameEntry!=NULL)
+    voiNameEntry->setText(voiNames[current_fill_color].c_str());
+
+
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIAbstractMultisliceEditor.h b/bioimagesuite30_src/GUI/vtkpxGUIAbstractMultisliceEditor.h
new file mode 100644
index 0000000..5f3c454
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIAbstractMultisliceEditor.h
@@ -0,0 +1,238 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUI3DObjectmapEditor.h,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:33 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUI3DObjectmapEditor 
+// .SECTION Description
+
+#ifndef __vtkpxGUIAbstractMultisliceEditor_h
+#define __vtkpxGUIAbstractMultisliceEditor_h
+
+
+#include "vtkpxGUIComponent.h"
+#include "vtkpxGUIObjectmapMosaicViewer.h"
+#include "pxtkradiobutton.h"
+#include <string>
+
+class vtkpxDataArrayUndoStack;
+
+
+const int pxAME_NUM_COLOR_BUTTONS=9;
+const int pxAME_NUM_DIALOG_COLOR_BUTTONS=60;
+
+
+class  vtkpxGUIAbstractMultisliceEditor : public vtkpxGUIComponent {
+  
+public:
+
+  vtkTypeMacro(vtkpxGUIAbstractMultisliceEditor,vtkpxGUIComponent);
+  
+  // Description:
+  // Initialize Display  
+  virtual char*  Initialize(const char* name,int inside);
+
+  // Description:
+  // Handle Events
+  virtual int  HandleEvent(int eventno);
+
+  // Description:
+  // Handle Clicked Point
+  virtual int HandleClickedPoint(int x,int y,int z,int nbutton,int state);
+
+  // Description:
+  // Default Scale Mode
+  vtkSetClampMacro(DefaultScaleMode,int,0,8);
+  vtkGetMacro(DefaultScaleMode,int);
+
+  // Description:
+  // Set Images 
+  virtual int SetImagesAndLookupTable(vtkImageData* mainImage,vtkImageData* objectmap,vtkLookupTable* lkp,int iscolor);
+
+  // Description:
+  // Set objectmap and create undo 
+  virtual double SetObjectmapWithUndo(vtkImageData* objectmap);
+
+  // Description:
+  // Create Default Lookup Table
+  virtual int CreateDefaultLookupTable(int voimode=0);
+
+  // Description:
+  // Update From Viewer
+  virtual void UpdateFromViewer(int docmap=0) = 0;
+
+  // Description:
+  // Simple Mode
+  vtkSetClampMacro(SimpleMode,int,0,1);
+
+  // Description:
+  // Set 2D Axis
+  vtkSetClampMacro(Paint2DAxis,int,0,2);
+
+  // Description:
+  virtual int GetPaintConnectMode();
+  virtual int GetPaintUseThresholdMode();
+  virtual int GetPaintUseMaskMode();
+  virtual void GetThresholds(float val[2]);
+  virtual int GetCurrentColor();
+  virtual int GetPaintMode();
+  virtual int GetPaint3DMode();
+
+  // Description:
+  // Get Extra Frame
+  virtual PXTkFrame* GetExtraFrame();
+  virtual char* GetExtraFrameName();
+  virtual int      UpdateColorButtons();
+  virtual void     RenamePaintOffLabel(const char* newname);
+
+
+  // Description:
+  // Set VOI Select Mode
+  virtual int SetVOISelectMode(double minthr,double maxthr,int force3dbrush=1);
+
+  // Description:
+  // Some Undo Stuff
+  virtual void ChangeObjectmapValue(vtkDataArray* element,int i,int j,int k,int new_color);
+  virtual vtkDataArray*  GetNextArray();
+
+
+  // Description:
+  // Disable Painting
+  virtual int DisablePainting();
+  virtual int EnablePainting();
+
+
+  // Description:
+  // VOI Names
+  virtual int SetVOIName(int index,char* name);
+  virtual const char* GetVOIName(int index);
+  virtual int GetNumberOfVOIS();
+  virtual void ResetVOINames();
+  
+protected:
+
+  vtkpxGUIAbstractMultisliceEditor();
+  virtual ~vtkpxGUIAbstractMultisliceEditor();
+  
+  // Description:
+  // Issues to do with painting and controls
+  char*            objectmapcolormapname;
+  int              current_fill_color;
+  virtual int      CreateFillControl(PXTkFrame* fillframe);
+  virtual int      UpdateObjectmapColormap();
+  virtual int      LoadObjectmapColormap();
+  virtual int      SaveObjectmapColormap();
+  virtual int      EditColorButton(int n);
+
+  // Description:
+  // Viewer Communications
+  virtual void UpdateViewerDisplay() = 0;
+  virtual void UpdateViewerObjectmapColormap() = 0;
+  virtual void UpdateViewerObjectmap() = 0;
+
+
+  // Description:
+  // Undo/Redo Operation
+  virtual void UndoLastObjectmapChange();
+  virtual void RedoLastObjectmapChange();
+  virtual void UpdateUndoIndicesDisplay();
+
+
+  // Description:
+  // Smooth Objectmap
+  virtual int SmoothObjectmap();
+
+
+  // Description:
+  // Data Members
+  PXTkRadioButton*  colorButton[pxAME_NUM_COLOR_BUTTONS];
+  PXTkRadioButton*  dialogColorButton[pxAME_NUM_DIALOG_COLOR_BUTTONS];
+  //BTX
+  std::string       voiNames[pxAME_NUM_DIALOG_COLOR_BUTTONS];
+  //ETX
+  PXTkDialog*       colorButtonDialog;
+  PXTkFrame*        editcolorframe;
+  PXTkFrame*        extraFrame;
+  PXTkEntry*        fillThresholds[2];
+  PXTkEntry*        voiNameEntry;
+  PXTkOptionMenu* colorSelection;
+  PXTkCheckButton*  fillMode;
+  PXTkCheckButton*  paintMode3D;
+  PXTkCheckButton*  connectFillMode;
+  PXTkCheckButton*  baseImageMode;
+  PXTkOptionMenu*   paintMode;
+  PXTkOptionMenu*   smoothMode;
+  PXTkOptionMenu*   smoothConvergenceMode;
+  int               draw_mode;
+  int               old_draw_mode;
+  int               draw_mode3D;
+  int               DefaultScaleMode;
+  int               SimpleMode;
+  int               SingleSliceMode;
+  int               Paint2DAxis;
+  int               CurrentImageIsColor;
+  vtkImageData*     MainImage;
+  vtkImageData*     Objectmap;
+  vtkLookupTable*   ObjectmapLookupTable;
+
+  //  PXTkEntry*        undoIndices[3];
+
+  vtkpxDataArrayUndoStack* UndoStack;
+
+
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIAnalyzeHeaderEditor.cpp b/bioimagesuite30_src/GUI/vtkpxGUIAnalyzeHeaderEditor.cpp
new file mode 100644
index 0000000..1bae9c7
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIAnalyzeHeaderEditor.cpp
@@ -0,0 +1,536 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIAnalyzeHeaderEditor.cpp,v $
+  Language:  C++
+  Date:      $Date: 2005/07/31 20:39:21 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxGUIAnalyzeHeaderEditor.h"
+#include "vtkObjectFactory.h"
+#include "pxtkapp.h"
+#include "pxutil.h"
+#include "vtkImageData.h"
+
+vtkpxGUIAnalyzeHeaderEditor* vtkpxGUIAnalyzeHeaderEditor::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIAnalyzeHeaderEditor");
+  if(ret)
+      {
+	return (vtkpxGUIAnalyzeHeaderEditor*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIAnalyzeHeaderEditor;
+}
+
+// Construct object with no children.
+vtkpxGUIAnalyzeHeaderEditor::vtkpxGUIAnalyzeHeaderEditor()
+{
+  header=new anaimagedata;
+  header_filename=new char[40];
+  strcpy(header_filename,"new_header.hdr");
+  this->Mode=0;
+}
+
+vtkpxGUIAnalyzeHeaderEditor::~vtkpxGUIAnalyzeHeaderEditor()
+{
+  delete header;
+  delete [] header_filename;
+}
+
+char*  vtkpxGUIAnalyzeHeaderEditor::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+    return GetWidgetName();
+  
+  int i;
+
+  vtkpxGUIComponent::Initialize(name,inside);
+  PXTkFrame* mainFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+  mainFrame->configure("-bg","black");
+
+
+  PXTkFrame* otherFrame=new PXTkFrame(this->EventManager,mainFrame);
+  mainFrame->addChildren("-side top -expand true -fill both -pady 5",otherFrame);
+
+  /*  if (this->Mode==0)
+    {
+      PXTkFrame* buttonFrame=new PXTkFrame(this->EventManager,mainFrame);
+      PXTkButton* b0=new PXTkButton(this->EventManager,buttonFrame,"Update",104); 
+      buttonFrame->addChildren("-side left -expand f -padx 10",b0);
+      mainFrame->addChildren("-side top -expand true -fill both -pady 5",buttonFrame);
+      }*/
+
+
+  // Dimensions xsize,ysize,zsize,tsize
+  // Pixel Dims xpix,ypix,zpix,orient,MinValue,MaxValue,bits
+
+  PXTkLabelFrame* dimensionframe=new PXTkLabelFrame(this->EventManager,otherFrame,"Image Dimensions (voxels)");
+  PXTkLabelFrame* voxelframe=new PXTkLabelFrame(this->EventManager,otherFrame,"Voxel Dimensions (mm)");
+  PXTkLabelFrame* intensityframe=new PXTkLabelFrame(this->EventManager,otherFrame,"Intensity Range");
+  PXTkLabelFrame* miscframe=new PXTkLabelFrame(this->EventManager,otherFrame,"Image Type");
+
+  otherFrame->addChildren("-side top -fill both -expand t",dimensionframe,voxelframe,intensityframe,miscframe);
+
+  PXTkFrame* barFrame=new PXTkFrame(this->EventManager,otherFrame);
+  otherFrame->addChildren("-side bottom -fill x -expand t -pady 2",barFrame);
+      
+  PXTkButton* m_1=new PXTkButton(this->EventManager,barFrame,"New",100); 
+  PXTkButton* m_2=new PXTkButton(this->EventManager,barFrame,"Load",101); 
+  PXTkButton* m_3=new PXTkButton(this->EventManager,barFrame,"Save",102); 
+  PXTkButton* m_4=new PXTkButton(this->EventManager,barFrame,"Save As",103); 
+  barFrame->addChildren("-side left -expand t -fill x -padx 2",m_1,m_2,m_3,m_4);
+  if (!this->EventManager->isInside())
+    {
+      PXTkButton* b0a=new PXTkButton(this->EventManager,barFrame,"Close",3); 
+      barFrame->addChildren("-side right -expand t -fill x -padx 10",b0a);
+    }
+
+    
+
+  // First Dimension Frame 
+  for (i=0;i<=3;i++)
+    {
+      label[i]=new PXTkLabel(this->EventManager,dimensionframe,"X-Size");
+      label[i]->configure("-width",5);
+      entry[i]=new PXTkEntry(this->EventManager,dimensionframe);
+      entry[i]->configure("-width",8);
+      entry[i]->configure("-relief","sunken");
+      switch(i) 
+	{
+	case 0:
+	  label[i]->setText("xsize");
+	  break;
+	case 1:
+	  label[i]->setText("ysize");
+	  break;
+	case 2:
+	  label[i]->setText("zsize");
+	  break;
+	case 3:
+	  label[i]->setText("tsize");
+	  break;
+	}
+      dimensionframe->addChildren("-side left -padx 2 -fill x -expand t",label[i],entry[i]);
+    }
+
+  // Then Voxel Frame 
+  for (i=4;i<=6;i++)
+    {
+      label[i]=new PXTkLabel(this->EventManager,voxelframe,"X-Size");
+      label[i]->configure("-width",5);
+      entry[i]=new PXTkEntry(this->EventManager,voxelframe);
+      entry[i]->configure("-width",5);
+      entry[i]->configure("-relief","sunken");
+      switch(i) 
+	{
+	case 4:
+	  label[i]->setText("x-size");
+	  break;
+	case 5:
+	  label[i]->setText("y-size");
+	  break;
+	case 6:
+	  label[i]->setText("z-size");
+	  break;
+	}
+      voxelframe->addChildren("-side left -padx 2 -fill x -expand t",label[i],entry[i]);
+    }
+
+
+  // Then Intensity Frame 
+  for (i=7;i<=8;i++)
+    {
+      label[i]=new PXTkLabel(this->EventManager,intensityframe,"X-Size");
+      label[i]->configure("-width",5);
+      entry[i]=new PXTkEntry(this->EventManager,intensityframe);
+      entry[i]->configure("-width",5);
+      entry[i]->configure("-relief","sunken");
+      switch(i) 
+	{
+	case 7:
+	  label[i]->setText("Min:");
+	  break;
+	case 8:
+	  label[i]->setText("Max:");
+	  break;
+	}
+      intensityframe->addChildren("-side left -padx 2 -fill x -expand t",label[i],entry[i]);
+    }
+
+  PXTkLabel* lab0=new PXTkLabel(this->EventManager,miscframe,"Orientation:");
+  orientation=new PXTkOptionMenu(this->EventManager,miscframe,"Axial (0)",-1);
+  orientation->addOption("Coronal (1)",-1);
+  orientation->addOption("Sagittal (2)",-1);
+  orientation->addOption("Other (3)",-1);
+  
+  PXTkLabel* lab1=new PXTkLabel(this->EventManager,miscframe,"Data Type:");
+  data_type=new PXTkOptionMenu(this->EventManager,miscframe,"1-Byte (8)",-1);
+  data_type->addOption("Short (2)",-1);
+  data_type->addOption("Int   (3)",-1);
+  data_type->addOption("Float (4)",-1);
+  data_type->setIndex(1);
+
+  byte_swapped=new PXTkCheckButton(this->EventManager,miscframe,"Byte Swapped",-1);
+  miscframe->addChildren("-side left -fill x -expand t",lab0,orientation,lab1,data_type);
+  miscframe->addChildren("-side left -fill x -expand t",byte_swapped);
+
+ 
+  this->Initialized=1;
+  this->ResetHeader();
+  this->DisplayHeader();
+  return GetWidgetName();
+}
+ 
+
+int  vtkpxGUIAnalyzeHeaderEditor::HandleEvent(int event)
+{
+  if (event<=10)
+      return this->EventManager->handleDirectEvent(event);
+
+  switch(event)
+      {
+      case 100:
+	ResetHeader();
+	DisplayHeader();
+	break;
+
+      case 101:
+	{
+	  char* line=this->EventManager->getOpenFilename("Header File name","Header Files","*.hdr*");
+	  
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		ReadHeader(line);
+	    }
+	}
+	break;
+	
+      case 102:
+	SaveHeader(header_filename);
+	break;
+	
+      case 103:
+	{
+	  char* line=this->EventManager->getSaveFilename("Header File Name",header_filename,"Header Files","*.hdr");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		this->SaveHeader(line);
+	    }
+	}
+	break;
+
+      case 104:
+	if (this->EventParent!=NULL && this->CallbackNo>0)
+	  this->EventParent->HandleEvent(CallbackNo);
+	
+	if (this->CallbackName!=NULL)
+	  PXTkApp::executeTclCommand(this->CallbackName);
+	break;
+      }
+  
+  return TCL_OK;
+}
+
+int vtkpxGUIAnalyzeHeaderEditor::ReadHeader(const char* name)
+{
+  header_bits=readanahdr(name,header);
+  if (header_bits==0)
+    {
+      SetHeaderFromDialog();
+    }
+  else
+    {
+      delete [] header_filename;
+      header_filename=new char[strlen(name)+1];
+      strcpy(header_filename,name);
+      DisplayHeader();
+    }
+  return TCL_OK;
+}
+
+int vtkpxGUIAnalyzeHeaderEditor::SaveHeader(const char* name)
+{
+  strcpy(pxtk_buffer,name);
+  SetHeaderFromDialog();
+  
+  int ok=writeanahdr(pxtk_buffer,header,header_bits);
+  
+  if (ok)
+    {
+      if (strcmp(header_filename,pxtk_buffer)!=0)
+	{
+	  delete [] header_filename;
+	  header_filename=new char[strlen(pxtk_buffer)+1];
+	  strcpy(header_filename,pxtk_buffer);
+	}
+    }
+  return DisplayHeader();
+
+}
+
+int vtkpxGUIAnalyzeHeaderEditor::SetHeaderFromDialog()
+{
+  header->xsize=Irange(atoi(entry[0]->getText()),1,1024);
+  header->ysize=Irange(atoi(entry[1]->getText()),1,1024);
+  header->zsize=Irange(atoi(entry[2]->getText()),1,1024);
+  header->tsize=Irange(atoi(entry[3]->getText()),1,1024);
+
+  header->xpix=Frange(atof(entry[4]->getText()),(float)0.01,(float)100.0);
+  header->ypix=Frange(atof(entry[5]->getText()),(float)0.01,(float)100.0);
+  header->zpix=Frange(atof(entry[6]->getText()),(float)0.01,(float)100.0);
+
+  header->minpix=Irange(atoi(entry[7]->getText()),-65535,65535);
+  header->maxpix=Irange(atoi(entry[8]->getText()),-65535,65535);
+  
+  header->orient=Irange(orientation->getIndex(),0,5);
+
+  switch (data_type->getIndex())
+    {
+    case 0:
+      header_bits=8;
+      break;
+    case 1:
+      header_bits=16;
+      break;
+    case 2:
+      header_bits=31;
+      break;
+    case 3:
+      header_bits=32;
+      break;
+    }
+  
+  if (byte_swapped->getState())
+    header_bits=-header_bits;
+  
+  return TCL_OK;
+}
+
+int vtkpxGUIAnalyzeHeaderEditor::ResetHeader()
+{
+  header->zsize=128;
+  header->xsize=128;
+  header->ysize=128;
+  header->tsize=1;
+  header->zasp=1.0; header->yasp=1.0;header->xasp=1.0;
+  header->zpix=1.0; header->ypix=1.0;header->xpix=1.0;
+  header->minpix=0;header->maxpix=65536;
+  header->trueminpix=0; header->truemaxpix=65536;
+  header->orient=0;
+  header_bits=16;
+  return TCL_OK;
+}
+
+
+int vtkpxGUIAnalyzeHeaderEditor::DisplayHeader()
+{
+  for (int i=0;i<=11;i++)
+    {
+      switch(i)
+	{
+	case 0:
+	  sprintf(pxtk_buffer,"%d",header->xsize);
+	  break;
+	case 1:
+	  sprintf(pxtk_buffer,"%d",header->ysize);
+	  break;
+	case 2:
+	  sprintf(pxtk_buffer,"%d",header->zsize);
+	  break;
+	case 3:
+	  sprintf(pxtk_buffer,"%d",header->tsize);
+	  break;
+	case 4:
+	  sprintf(pxtk_buffer,"%7.5f",header->xpix);
+	  break;
+	case 5:
+	  sprintf(pxtk_buffer,"%7.5f",header->ypix);
+	  break;
+	case 6:
+	  sprintf(pxtk_buffer,"%7.5f",header->zpix);
+	  break;
+	case 7:
+	  sprintf(pxtk_buffer,"%d",header->minpix);
+	  break;
+	case 8:
+	  sprintf(pxtk_buffer,"%d",header->maxpix);
+	  break;
+	case 9:
+	  {
+	    int orn=header->orient;
+	    if (orn<0 || orn>2)
+	      orn=3;
+	    orientation->setIndex(orn);
+	  }
+	  break;
+	case 10:
+	  {
+	    int h=abs(header_bits);
+	    switch (h)
+	      {
+	      case 8:
+		data_type->setIndex(0);
+		break;
+	      case 16:
+		data_type->setIndex(1);
+		break;
+	      case 31:
+		data_type->setIndex(2);
+		break;
+	      case 32:
+		data_type->setIndex(3);
+		break;
+	      }
+	  }
+	  break;
+	case 11:
+	  if (header_bits>0)
+	    byte_swapped->setState(PXFalse);
+	  else
+	    byte_swapped->setState(PXTrue);
+	  break;
+	}
+      if (i<9)
+	entry[i]->setText(pxtk_buffer);
+    }
+  
+  strcpy(pxtk_buffer,header_filename);
+  sprintf(pxtk_buffer2,"Analyze Header Editor: %s",PXTkApp::getFilenameTail(pxtk_buffer));
+  this->EventManager->setTitle(pxtk_buffer2);
+  return TCL_OK;
+}
+
+int vtkpxGUIAnalyzeHeaderEditor::SetHeader(vtkImageData* image,int orient)
+{
+  return SetHeader(image,orient,-1);
+}
+
+
+int vtkpxGUIAnalyzeHeaderEditor::SetHeader(vtkImageData* image,int orient,int frames)
+{
+  if (image==NULL)
+    return TCL_ERROR;
+
+  int Dim[3];
+  image->GetDimensions(Dim);
+
+  header->xsize=Dim[0];
+  header->ysize=Dim[1];
+
+  if (frames != -1 ) {
+    header->tsize=frames;
+    header->zsize=Dim[2]/header->tsize;
+  } else {
+    header->zsize=Dim[2];
+    header->tsize=image->GetNumberOfScalarComponents();
+  }
+
+  double Sp[3];
+  image->GetSpacing(Sp);
+
+  header->xpix=Sp[0];
+  header->ypix=Sp[1];
+  header->zpix=Sp[2];
+
+  double range[2];
+  header->orient=Irange(orient,0,5);
+
+  if (image->GetPointData()->GetScalars()!=NULL)
+    {
+      image->GetPointData()->GetScalars()->GetRange(range);
+      header->minpix=(int)range[0];
+      header->maxpix=(int)range[1];
+
+      double r[2];
+      image->GetPointData()->GetScalars()->GetDataTypeRange(r);
+      float diff=r[1]-r[0];
+      if (diff<256)
+	header_bits=8;
+      else if (diff<65536)
+	header_bits=16;
+      else if (image->GetPointData()->GetScalars()->GetDataType()==VTK_FLOAT)
+	header_bits=32;
+      else
+	header_bits=31;
+    }
+  DisplayHeader();
+  return TCL_OK;
+}
+
+int vtkpxGUIAnalyzeHeaderEditor::SetImageName(const char* headername)
+{
+  if (headername==NULL)
+    return TCL_ERROR;
+
+  delete [] header_filename;
+  header_filename=new char[strlen(headername)+1];
+  strcpy(header_filename,headername);
+  strcpy(pxtk_buffer,header_filename);
+  sprintf(pxtk_buffer2,"Analyze Header Editor: %s",PXTkApp::getFilenameTail(pxtk_buffer));
+  this->EventManager->setTitle(pxtk_buffer2);
+  return TCL_OK;
+}
+
+int vtkpxGUIAnalyzeHeaderEditor::GetOrientation()
+{
+  header->orient=Irange(orientation->getIndex(),0,5);
+  return header->orient;
+}
+
+int vtkpxGUIAnalyzeHeaderEditor::SetImageSpacingToImage(vtkImageData* img)
+{
+  img->SetSpacing(header->xpix,header->ypix,header->zpix);
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIAnalyzeHeaderEditor.h b/bioimagesuite30_src/GUI/vtkpxGUIAnalyzeHeaderEditor.h
new file mode 100644
index 0000000..7398455
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIAnalyzeHeaderEditor.h
@@ -0,0 +1,121 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIAnalyzeHeaderEditor.h,v $
+  Language:  C++
+  Date:      $Date: 2002/06/07 20:34:50 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIAnalyzeHeaderEditor - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkpxGUIAnalyzeHeaderEditor_h
+#define __vtkpxGUIAnalyzeHeaderEditor_h
+
+#include "vtkpxGUIComponent.h"
+
+#include "pxutil.h"
+#include "pxtkapp.h"
+#include "pxtkdialog.h"
+#include "pxtkgadgets.h"
+#include "pxtkcomplexwidgets.h"
+#include "pxtkmenu.h"
+
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkpxGUIAnalyzeHeaderEditor : public vtkpxGUIComponent
+{
+public:
+  static vtkpxGUIAnalyzeHeaderEditor *New();
+  vtkTypeMacro(vtkpxGUIAnalyzeHeaderEditor,vtkpxGUIComponent);
+  
+  virtual char* Initialize(const char* name,int inside);
+  virtual int   HandleEvent(int );
+
+  virtual int   ReadHeader(const char* name);
+  virtual int   SaveHeader(const char* name);
+  virtual int   ResetHeader();
+  virtual int   SetHeaderFromDialog();
+  virtual int   DisplayHeader();
+
+  // Description: 
+  // UseLabels
+  vtkSetClampMacro(Mode, int,0,2);
+  vtkGetMacro(Mode, int);
+
+  virtual int SetHeader(vtkImageData* image,int orient,int frames);
+  virtual int SetHeader(vtkImageData* image,int orient);
+  virtual int SetImageName(const char* headername);
+
+  virtual int  GetOrientation();
+  virtual int  SetImageSpacingToImage(vtkImageData* img);
+
+protected:
+
+  vtkpxGUIAnalyzeHeaderEditor();
+  virtual  ~vtkpxGUIAnalyzeHeaderEditor();
+
+  int Mode;
+
+  anaimagedata *header;
+  int           header_bits;
+  char*         header_filename;
+ 
+  PXTkLabel* label[9];
+  PXTkEntry* entry[9];
+
+  PXTkOptionMenu* orientation;
+  PXTkOptionMenu* data_type;
+  PXTkCheckButton* byte_swapped;
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIBaseCurveControl.cpp b/bioimagesuite30_src/GUI/vtkpxGUIBaseCurveControl.cpp
new file mode 100644
index 0000000..d3591ad
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIBaseCurveControl.cpp
@@ -0,0 +1,2835 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkpxGUIBaseCurveControl.h"
+#include "pxutil.h"
+#include "vtkActor.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkPolyDataWriter.h"
+#include "vtkAssembly.h"
+#include "vtkRenderer.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxImageExtract.h"
+#include "vtkSphereSource.h"
+#include "vtkTransformPolyDataFilter.h"
+#include "vtkIdentityTransform.h"
+#include "vtkMath.h"
+#include "vtkPoints.h"
+#include "vtkTransform.h"
+#include "vtkImageShiftScale.h"
+#include "vtkpxUtil.h"
+#include "vtkpxColorMapUtil.h"
+#include "vtkpxAnalyzeImageWriter.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkLookupTable.h"
+#include "vtkImageData.h"
+#include "vtkProperty.h"
+#include "vtkPolyData.h"
+
+// 	$Id: vtkpxGUIBaseCurveControl.cpp,v 1.1 2002/02/20 18:06:52 Xenios Exp Xenios $	
+
+
+/* -------------------------------------------------------------------------*/
+char vtkpxGUIBaseCurveControl::lamstring[400];
+vtkpxBaseCurve* vtkpxGUIBaseCurveControl::clipboardCollection=NULL;
+/* -------------------------------------------------------------------------*/
+
+vtkpxGUIBaseCurveControl* vtkpxGUIBaseCurveControl::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIBaseCurveControl");
+  if(ret)
+      {
+	return (vtkpxGUIBaseCurveControl*)ret;
+      }
+  return new vtkpxGUIBaseCurveControl;
+}
+
+// Construct object with no children.
+vtkpxGUIBaseCurveControl::vtkpxGUIBaseCurveControl()
+{
+  num_collections=9;
+  if (clipboardCollection==NULL)
+    clipboardCollection=vtkpxBaseCurve::New();
+
+  this->transform=vtkIdentityTransform::New();
+  owns_transform=PXTrue;
+
+  for (int i=0;i<num_collections;i++)
+      {
+	allCollections[i]=vtkpxBaseCurve::New();
+	showCollection[i]=PXTrue;
+	allCollections[i]->SetPointScale(1.0);
+	allCollections[i]->SetShowControls(1);
+	allCollections[i]->SetShowCurve(0);
+	allCollections[i]->SetClosedCurve(0);
+	
+	for (int j=0;j<BCC_MAX_RENDERERS;j++)
+	  {
+	    if (i==0)
+	      {
+		renderer[j]=NULL;
+		highlightActor[j]=NULL;
+	      }
+	    landmarkActor[j][i]=NULL;
+	  }
+	
+	landmarkFilter[i]=vtkTransformPolyDataFilter::New();
+	landmarkFilter[i]->SetInput(allCollections[i]->GetOutput());
+	landmarkFilter[i]->SetTransform(this->transform);
+      }
+
+  highlightData=NULL;
+  highlightFilter=NULL;
+  highlightIndex=-1;
+  current_collection=0;
+  landmarkCollection=allCollections[current_collection];
+  strcpy(clipboard," ");
+
+  backupColormap=NULL;
+  currentColormap=NULL;
+  edit_window=NULL;
+  label_window=NULL;
+  extractGUI=NULL;
+  thresholdGUI=NULL;
+  snakeGUI=NULL;
+  edit_item=-1;
+
+  enable_complex=PXTrue;
+  enable_labels=PXTrue;
+  enable_curve=PXTrue;
+  enable_list=PXTrue;
+  image=NULL;
+  image_plane=2;
+  image_frame=0;
+  image_level=-1;
+
+
+}
+
+vtkpxGUIBaseCurveControl::~vtkpxGUIBaseCurveControl()
+{
+  for (int i=0;i<num_collections;i++)
+    {
+      for (int j=0;j<BCC_MAX_RENDERERS;j++)
+	{
+	  if (landmarkActor[j][i]!=NULL)
+	    landmarkActor[i][j]->Delete();
+	  if (i==0)
+	    {
+	      if (highlightActor[j]!=NULL)
+		{
+		  highlightActor[j]->Delete();
+		  landmarkFilter[j]->Delete();
+		}
+	    }
+	}
+      allCollections[i]->Delete();
+    }
+
+  if (highlightData!=NULL)
+    {
+      highlightData->Delete();
+      highlightFilter->Delete();
+    }
+     
+  if (this->transform!=NULL)
+    {
+      if (owns_transform)
+	this->transform->Delete();
+    }
+
+  /*if (clipboardCollection!=NULL)
+    clipboardCollection->Delete();*/
+
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::GetNumberOfCollections()
+{
+  return this->num_collections;
+}
+
+char* vtkpxGUIBaseCurveControl::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+
+
+  vtkpxGUIComponent::Initialize(name,inside);
+  //  PXTkDialog::initDisplay();
+
+  PXTkFrame* landmarkFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+
+  landmarkFrame->bindCallback("<Delete>",204);
+
+  // Menu Stuff
+  // ----------
+  PXTkFrame* menubar=new PXTkFrame(this->EventManager,landmarkFrame);
+  landmarkFrame->addChildren("-side top -expand false -fill x",menubar);
+
+  PXTkMenuButton* but1=new PXTkMenuButton(this->EventManager,menubar,"File",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but1);
+  
+  PXTkMenu *menu1=new PXTkMenu(this->EventManager,but1,PXFalse);
+  menu1->addButton("New",100);
+  menu1->addSeparator();
+  menu1->addButton("Load",101);
+  menu1->addButton("Save",102);
+  menu1->addSeparator();
+  menu1->addButton("Export to Surface File",104);
+  if (enable_list)
+    {
+      menu1->addSeparator();
+      if (enable_complex)
+	{
+	  //	  menu1->addButton("Save as Transformation",307);
+	  menu1->addButton("Save as Object Map",310);
+	  menu1->addSeparator();
+	}
+      menu1->addButton("Clear All Sets",105);
+    }
+  else
+    menu1->addSeparator();
+  if (this->EventParent)
+      menu1->addButton("Close",3);
+  else
+      menu1->addButton("Exit",1);
+  
+  PXTkMenuButton* but2=new PXTkMenuButton(this->EventManager,menubar,"Edit",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but2);
+
+  
+  PXTkMenu *menu2=new PXTkMenu(this->EventManager,but2,PXFalse);
+  if (enable_list)
+      {
+	menu2->addButton("Edit Point",210);
+	menu2->addSeparator();
+	menu2->addButton("Cut Point",201);
+	menu2->addButton("Copy Point",202);
+	menu2->addButton("Paste Point at End",203);
+     }
+  menu2->addButton("Delete Last Point",204);
+  menu2->addButton("Delete All Points",100);
+
+  PXTkMenuButton* but24=new PXTkMenuButton(this->EventManager,menubar,"Color",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but24);
+  PXTkMenu *menu24=new PXTkMenu(this->EventManager,but24,PXFalse);
+  menu24->addButton("Landmark Color",400);
+  menu24->addButton("Highlight Color",401);
+
+
+ 
+  if (enable_labels)
+    {
+      PXTkMenuButton* but3=new PXTkMenuButton(this->EventManager,menubar,"Setup",-1,PXTrue);
+      menubar->addChildren("-side left -expand false ",but3);
+
+      PXTkMenu *menu3=new PXTkMenu(this->EventManager,but3,PXFalse);
+      menu3->addButton("Edit Setup File",303);
+      menu3->addSeparator();
+      menu3->addButton("Load Setup File",300);
+      menu3->addButton("Save Setup File",301);
+      menu3->addSeparator();
+      menu3->addButton("Talairach Mode",302);
+      //      menu3->addButton("Brainstrip Mode",304);
+      //      menu3->addButton("Transform Mode",305);
+      //      menu3->addButton("Articulated Mouse Mode",306);
+    }
+  
+  PXTkMenuButton* but6=new PXTkMenuButton(this->EventManager,menubar,"Point Set",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but6);
+  
+  PXTkMenu *menu6=new PXTkMenu(this->EventManager,but6,PXFalse);
+  menu6->addButton("Copy  Point Set",590);
+  menu6->addButton("Paste Point Set",591);
+  if (enable_curve)
+    {
+      menu6->addButton("Paste Curve (2D)",592);
+      menu6->addSeparator();
+      menu6->addButton("Create Circle",596);
+    }
+
+  PXTkMenuButton* but62=new PXTkMenuButton(this->EventManager,menubar,"Curve",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but62);
+
+  PXTkMenu *menu62=new PXTkMenu(this->EventManager,but62,PXFalse);
+  menu62->addButton("Area",605);
+  menu62->addButton("Length",604);
+  menu62->addButton("Image Stats (ROI)",606);
+  menu62->addSeparator();
+  menu62->addButton("Remove Loops",597);
+  menu62->addButton("Smooth",602);
+  menu62->addSeparator();
+  menu62->addButton("Equispace",603);
+  menu62->addButton("Equispace 2.0",598);
+  menu62->addButton("Sample x2",600);
+  menu62->addButton("Sample x8",599);
+  menu62->addButton("Subsample x2",601);
+  
+ 
+  if (enable_curve)
+    {
+      PXTkMenuButton* but7=new PXTkMenuButton(this->EventManager,menubar,"Operation",-1,PXTrue);
+      menubar->addChildren("-side left -expand false ",but7);
+      
+      PXTkMenu *menu7=new PXTkMenu(this->EventManager,but7,PXFalse);
+      //      menu7->addButton("Threshold",612);
+      menu7->addButton("Angle",615);
+      //      menu7->addSeparator();
+      menu7->addButton("Extract",609);
+      //      menu7->addButton("Snake",610);
+    }
+
+  // Other Stuff 
+  // --------------
+  // Collection Properties 
+
+  PXTkLabelFrame* checkFrame=new PXTkLabelFrame(this->EventManager,landmarkFrame,"PointSet Properties");
+  landmarkFrame->addChildren("-side top -expand true -fill both -padx 2 -pady 2",checkFrame);
+  checkFrame->setPackMode(PXFalse);
+
+  curveMode=new PXTkOptionMenu(this->EventManager,checkFrame,"Landmarks",110);
+  curveMode->addOption("Open   Curve");
+  curveMode->addOption("Closed Curve");
+  curveMode->addOption("Bounding Box");
+  checkFrame->gridRowColumnChild(curveMode,0,0);
+  if (allCollections[0]->GetShowCurve()==1)
+    curveMode->setIndex(1);
+  else
+    curveMode->setIndex(0);//landmarkCollection->GetCurveMode());
+
+  scaleMode=new PXTkOptionMenu(this->EventManager,checkFrame,"Size=0.25",111);
+  for (float s=0.50;s<=4.50;s+=0.25)
+      {
+	sprintf(pxtk_buffer,"Size=%3.2f",s);
+	scaleMode->addOption(pxtk_buffer);
+      }
+  int sc=int(landmarkCollection->GetPointScale()/0.25)-1;
+  scaleMode->setIndex(sc);
+  checkFrame->gridRowColumnChild(scaleMode,0,1);
+
+  displayCollection=new PXTkCheckButton(this->EventManager,checkFrame,"Show",501);
+  displayCollection->setState(showCollection[0]);
+  checkFrame->gridRowColumnChild(displayCollection,0,2);
+
+  message=new PXTkLabel(this->EventManager,checkFrame,"Num");
+  checkFrame->gridRowColumnChild(message,1,0,1,3);
+  message->configure("-relief","ridge");
+
+  
+  if (enable_labels)
+    {
+      currentLabel=new PXTkLabel(this->EventManager,checkFrame,"No Label");
+      checkFrame->gridRowColumnChild(currentLabel,2,0,1,2);
+      currentLabel->configure("-relief","ridge");
+      currentLabel->configure("-pady",2);
+      currentLabel->configure("-padx",2);
+      currentLabel->configure("-width",40);
+    }
+
+  // List Box and Scalebar
+  if (enable_list)
+      {
+	PXTkFrame* listFrame=new PXTkFrame(this->EventManager,checkFrame);
+	checkFrame->gridRowColumnChild(listFrame,3,0,3,2);
+	
+	PXTkScrollbar* ybar=new PXTkScrollbar(this->EventManager,listFrame,PXTrue);
+	listBox=new PXTkListBox(this->EventManager,listFrame,208);
+	ybar->attachGadget(listBox);
+	
+	listBox->configure("-width",30);
+	listBox->configure("-height",10);
+	listBox->configure("-wrap","none");
+	
+	listFrame->addChildren("-side left -expand true -fill both",listBox);
+	listFrame->addChildren("-side left -expand false -fill y",ybar);
+      }
+
+  // Control Properties
+  PXTkLabelFrame* vFrame=new PXTkLabelFrame(this->EventManager,landmarkFrame,"General Properties");
+  landmarkFrame->addChildren("-side bottom -expand false -fill x -padx 5 -pady 5",vFrame);
+  vFrame->setPackMode(PXFalse);
+  
+  
+  mouseMode=new PXTkOptionMenu(this->EventManager,vFrame,"Disabled  ",502);
+  mouseMode->addOption("Pick Mode");
+  //  mouseMode->addOption("Smooth Mode");
+  mouseMode->addOption("Auto Mode");
+  mouseMode->addOption("Add  Mode");
+  mouseMode->addOption("Continuous Add  Mode");
+  mouseMode->setIndex(3);
+  vFrame->gridRowColumnChild(mouseMode,1,0);
+
+  currentCollection=new PXTkOptionMenu(this->EventManager,vFrame,"Point Set 1",500);
+  for (int i=1;i<num_collections;i++)
+      {
+	sprintf(lamstring,"Point Set %d",i+1);
+	currentCollection->addOption(lamstring);
+      }
+  vFrame->gridRowColumnChild(currentCollection,1,1);
+
+
+  PXTkLabel* lab=new PXTkLabel(this->EventManager,vFrame,"");
+  lab->configure("-image","$::pxtclvtkpxcontrib::smalllogo ");
+  vFrame->gridRowColumnChild(lab,1,2);
+
+  /*displayMode=new PXTkOptionMenu(this->EventManager,vFrame,"Show None",501);
+  displayMode->addOption("Show Current");
+  displayMode->addOption("Show All");
+  displayMode->setIndex(1);
+  vFrame->gridRowColumnChild(displayMode,1,2);*/
+
+
+  
+  if (enable_labels)
+    CreateLabelWindow();
+
+  UpdateStatus();
+  
+
+  return GetWidgetName();
+}
+
+/* -------------------------------------------------------------------------*/ 
+void vtkpxGUIBaseCurveControl::SetRenderer(vtkRenderer* ren,int num)
+{
+  num=Irange(num,0,BCC_MAX_RENDERERS-1);
+  if (renderer[num]!=NULL || ren==NULL)
+    return;
+
+  renderer[num]=ren;
+
+  
+  if (highlightData==NULL)
+    {
+      highlightData=vtkSphereSource::New();
+      highlightIndex=-1;
+      highlightData->SetRadius(1.5*landmarkCollection->GetPointScale());
+      highlightData->SetThetaResolution(5);
+      highlightData->SetPhiResolution(5);
+
+      highlightData->SetCenter(0.0,0.0,0.0);
+
+      highlightFilter=vtkTransformPolyDataFilter::New();
+      highlightFilter->SetInput(highlightData->GetOutput());
+      highlightFilter->SetTransform(this->transform);
+      //highlightData->DebugOn();
+    }
+
+
+  highlightData->Update();
+  vtkPolyDataMapper* map2=vtkPolyDataMapper::New();
+  map2->SetInput(highlightFilter->GetOutput());
+
+  highlightActor[num]=vtkActor::New();
+  highlightActor[num]->SetMapper(map2);
+  highlightActor[num]->GetProperty()->SetRepresentationToWireframe();
+  highlightActor[num]->GetProperty()->SetLineWidth(2.0);
+  highlightActor[num]->GetProperty()->SetAmbient(1.0);
+  highlightActor[num]->GetProperty()->SetDiffuse(0.0);
+  highlightActor[num]->GetProperty()->SetSpecular(0.0);
+  highlightActor[num]->SetVisibility(0);
+  renderer[num]->AddActor(highlightActor[num]);
+
+  map2->Delete();
+
+  for (int i=0;i<num_collections;i++)
+      {
+	vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+	map->SetInput(landmarkFilter[i]->GetOutput());
+	landmarkActor[num][i]=vtkActor::New();
+	landmarkActor[num][i]->SetMapper(map);
+	landmarkActor[num][i]->GetProperty()->SetLineWidth(2.0);
+	/*landmarkActor[num][i]->GetProperty()->SetAmbient(1.0);
+	landmarkActor[num][i]->GetProperty()->SetDiffuse(0.0);
+	landmarkActor[num][i]->GetProperty()->SetSpecular(0.0);*/
+	allCollections[i]->Update();
+	renderer[num]->AddActor(landmarkActor[num][i]);
+	map->Delete();
+
+	if (num==0)
+	  {
+	    double c[3]; vtkpxSurfaceUtil::GetColor(i,c);
+	    landmarkActor[num][i]->GetProperty()->SetColor(c);
+	  }
+	else
+	  {
+	    if (landmarkActor[0][i]!=NULL)
+	      {
+		landmarkActor[num][i]->GetProperty()->SetColor(landmarkActor[0][i]->GetProperty()->GetColor());
+	      }
+	  }
+      }
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::Update()
+{
+  highlightData->Update();
+  SetHighlightDisplay(1);
+
+  for (int j=0;j<BCC_MAX_RENDERERS;j++)
+    {
+      if (renderer[j]!=NULL)
+	{
+	  for (int i=0;i<num_collections;i++)
+	    {
+	      allCollections[i]->Update();
+	      if (showCollection[i]==PXTrue)
+		landmarkActor[j][i]->SetVisibility(1);
+	      else
+		landmarkActor[j][i]->SetVisibility(0);
+	    }
+	}
+    }
+  // Curve Stuff 
+  UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::UpdateDisplay()
+{
+  if (!this->Initialized)
+      return;
+
+  if (showCollection[current_collection]==PXTrue)
+    {
+      highlightData->Update();
+      landmarkCollection->Update();
+    }
+  
+  if (this->EventParent!=NULL && this->CallbackNo>0)
+    this->EventParent->HandleEvent(CallbackNo);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::UpdateStatus()
+{
+  if (!this->Initialized)
+    return;
+  
+  if (enable_list)
+    {
+      int a=this->highlightIndex;
+      //int a=listBox->getCurrentItem();//this->highlightIndex;
+      listBox->selectItem(a);
+
+      if (mouseMode->getIndex()>=3)
+	a+=1;
+
+      if (enable_labels)
+	{
+	  if (a>=0)
+	    {
+	      // Display Next Item
+	      char line2[20];
+	      if (mouseMode->getIndex()>=3)
+		strcpy(line2,"Click Now for :");
+	      else
+		strcpy(line2,"Name:");
+
+	      int num=labelListBox->getNumItems();
+	      if (a<num)
+		{
+		  char* line=labelListBox->getItem(a);
+		  if (strlen(line)>=2)
+		    {
+		      strcpy(pxtk_buffer,&line[1]);
+		      pxtk_buffer[strlen(pxtk_buffer)-1]=(char)0;
+		      sprintf(pxtk_buffer2,"%s %s ",line2,pxtk_buffer);
+		      currentLabel->setText(pxtk_buffer2);
+		    }
+		  else
+		    currentLabel->setText(line);
+		}
+	      else
+		{
+		  sprintf(pxtk_buffer2,"%s Point %d",line2,a+1);
+		  currentLabel->setText(pxtk_buffer2);
+		}
+	    }
+	  else
+	    currentLabel->setText("No Point Selected");
+	}
+    }
+
+  sprintf(pxtk_buffer,"Name=%s Num Landmarks=%d",
+	  currentCollection->getLabel(current_collection),landmarkCollection->GetNumPoints());
+  message->setText(pxtk_buffer);
+}
+/* -------------------------------------------------------------------------*/
+int  vtkpxGUIBaseCurveControl::HandleEvent(int event)
+{
+  if (!this->Initialized)
+      return TCL_OK;
+
+  if (event<10)
+      return this->EventManager->handleDirectEvent(event);
+
+  switch(event)
+      {
+      case 100:
+	if (landmarkCollection->GetNumPoints()>0)
+	    {
+	      int ok=this->EventManager->questionBox("This will delete your old landmarks. Are you sure?");
+	      if (ok)
+		  {
+		    landmarkCollection->DeleteAllPoints(); SetHighlight(-1);
+
+		    if (enable_list)
+			listBox->clearList();
+		    UpdateDisplay();
+		    sprintf(pxtk_buffer2,"Point Set %d",current_collection+1);
+		    currentCollection->changeLabel(current_collection,pxtk_buffer2);
+		    UpdateStatus();
+		    if (mouseMode->getIndex()!=0)
+		      mouseMode->setIndex(3);
+		  }
+	    }
+	break;
+
+      case 101:
+	{
+	  int ok=1;
+	  if (landmarkCollection->GetNumPoints()>0)
+	      ok=this->EventManager->questionBox("Loading will delete your old landmarks. Are you sure?");
+	  if (ok)
+	      {
+		char* line=this->EventManager->getOpenFilename("Load landmarks","Landmarks","*.land");
+		if (line!=NULL)
+		    {
+		      if (strlen(line)>0)
+			  LoadLandmarks(line);
+		    }
+	      }
+	}
+	break;
+	
+      case 102:
+	{
+	  char* line=this->EventManager->getSaveFilename("Save Landmarks","points.land","Landmarks","*.land");
+	  if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		    {
+		      strcpy(pxtk_buffer2,line);
+		      if(landmarkCollection->Save(line))
+			  {
+			    sprintf(pxtk_buffer2,"%s.%d",PXTkApp::getFilenameTail(pxtk_buffer2),current_collection+1);
+			    currentCollection->changeLabel(current_collection,pxtk_buffer2);
+			    UpdateStatus();
+			  }
+		      else
+			  {
+			    sprintf(pxtk_buffer,"Failed to save landmarks %d in %s",current_collection+1,line);
+			    this->EventManager->messageBox(pxtk_buffer,"Save Failure");
+			  }
+		    }
+	      }
+	}
+	break;
+
+      case 103:
+	{
+	  int ok=1;
+	  if (landmarkCollection->GetNumPoints()>0)
+	    ok=this->EventManager->questionBox("Importing seeds will delete your old landmarks. Are you sure?");
+	  if (ok)
+	    {
+	      char* line=this->EventManager->getOpenFilename("Import Seed File","Seed Files","*.dat");
+	      if (line!=NULL)
+		{
+		  if (strlen(line)>0)
+		    LoadSeedFile(line);
+		}
+	    }
+	}
+	break;
+	
+  
+      case 104:
+	{
+	  char* line=this->EventManager->getSaveFilename("Save as Surface File","surface.vtk","Surface Files","*.vtk");
+	  if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		  {
+		    strcpy(pxtk_buffer2,line);
+		    vtkPolyDataWriter* writer=vtkPolyDataWriter::New();
+		    writer->SetFileName(pxtk_buffer2);
+		    vtkPolyData* newp=vtkPolyData::New();
+		    landmarkCollection->ExportToPolyData(newp,-1.0);
+		    writer->SetInput(newp);
+		    writer->SetFileTypeToASCII();
+		    writer->Update();
+		    writer->Delete();
+		    newp->Delete();
+		  }
+	      }
+	}
+	break;
+  
+
+      case 105:
+	{
+	  int ok=1;
+	  ok=this->EventManager->questionBox("Loading will delete ALL your old landmarks in all sets. Are you sure?");
+	  if (ok)
+	      {
+		for (int i=0;i<num_collections;i++)
+		    {
+		      allCollections[i]->DeleteAllPoints(); SetHighlight(-1);
+		      sprintf(pxtk_buffer2,"Point Set %d",i+1);
+		      currentCollection->changeLabel(i,pxtk_buffer2);
+		    }
+		
+		if (enable_list)
+		    listBox->clearList();
+		UpdateDisplay();
+		UpdateStatus();
+		if (mouseMode->getIndex()!=0)
+		  mouseMode->setIndex(3);
+	      }
+	}
+	break;
+
+      case 110:
+	{
+	  int c=curveMode->getIndex();
+	  if (c!=2)
+	    {
+	      landmarkCollection->SetClosedCurve(0);
+	    }
+	  else
+	    {
+	      landmarkCollection->SetClosedCurve(1);
+	      if (mouseMode->getIndex()>=3)
+		mouseMode->setIndex(1);
+	    }
+
+	  if (c==2 || c==1)
+	    landmarkCollection->SetShowCurve(1);
+	  else
+	    landmarkCollection->SetShowCurve(0);
+
+	  if (c==3)
+	    landmarkCollection->SetShowBoundingBox(1);
+	  else
+	    landmarkCollection->SetShowBoundingBox(0);
+
+	  landmarkCollection->SetShowControls(1);
+	  landmarkCollection->Update();
+	}
+	break;
+	
+      case 111:
+	landmarkCollection->SetPointScale(0.25+0.25*float(scaleMode->getIndex()));
+	highlightData->SetRadius(1.5*landmarkCollection->GetPointScale());
+	break;
+	
+      case 201:
+      case 202:
+      case 203:
+      case 204:
+	ClipboardCommand(event-200);
+	UpdateDisplay();
+	break;
+
+
+      case 208: // ListBox Callback
+	if (mouseMode->getIndex()>=3)
+	  mouseMode->setIndex(1);
+	SetHighlight(listBox->getCurrentItem());
+	UpdateStatus();
+	break;
+
+      case 209:
+	HandleEditWindowCallback();
+	break;
+
+      case 210: 
+	if (edit_window==NULL)
+	    CreateEditWindow(209);
+	UpdateEditWindow();
+	break;
+
+      case 300:
+	{
+	  char* line=this->EventManager->getOpenFilename("Load Setup File","Setup File","*.set");
+	  if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		    LoadSetupFile(line);
+	      }
+	}
+	break;
+
+      case 301:
+	{
+	  char* line=this->EventManager->getSaveFilename("Save Setup File","setup.set","Setup Files","*.set");
+	  if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		    SaveSetupFile(line);
+	      }
+	}
+	break;
+
+
+      case 302:
+	SetTalarachSetup();
+	break;
+	
+      case 303: // popupLabel Callback
+	label_window->popupDialog();
+	break;
+
+      case 320: // labelListBox Callback
+      case 321: // update Callback
+      case 322: // add Callback
+      case 323: // insert Callback
+      case 324: // deleteLabel Callback
+      case 325: // deleteAll Callback
+	HandleLabelWindowCallback(event-320);
+	break;
+
+      case 304:
+	SetBrainstripSetup();
+	break;
+
+      case 305:
+	SetTransformSetup();
+	break;
+
+      case 306:
+	SetArticulatedMouseSetup();
+	break;
+
+      case 307:
+	{
+	  char* line=this->EventManager->getSaveFilename("Save as Transformation","reslice.matr","Matrix Files","*.matr");
+	  if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		    {
+		      strcpy(pxtk_buffer2,line);
+		      SaveTransform(line);
+		    }
+	      }
+	}
+	break;
+
+      case 310:
+	if (image!=NULL)
+	  {
+	    char* line=this->EventManager->getSaveFilename("Save as Object Map","objectmap.hdr","Analyze Files","*.hdr");
+	    if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		  {
+		    strcpy(pxtk_buffer,line);
+
+		    vtkImageShiftScale* shiftscale=vtkImageShiftScale::New();
+		    shiftscale->SetOutputScalarTypeToUnsignedChar();
+		    shiftscale->SetInput(image);
+		    shiftscale->SetScale(0.0);
+		    shiftscale->Update();
+		    
+		    vtkImageData* outim=vtkImageData::New();
+		    outim->DeepCopy(shiftscale->GetOutput());
+		    shiftscale->Delete();
+		    
+		    for (int i=0;i<num_collections;i++)
+		      allCollections[i]->AddToImage(outim,float(i+1));
+		    
+		    vtkpxAnalyzeImageWriter* wr=vtkpxAnalyzeImageWriter::New();
+		    wr->SetInput(outim);
+		    wr->Save(pxtk_buffer);
+		    wr->Delete();
+		    outim->Delete();
+		  }
+	      }
+	  }
+	break;
+
+      case 400:
+	{
+	  double c[3];
+	  if (renderer[0]!=NULL)
+	    {
+	      landmarkActor[0][current_collection]->GetProperty()->GetColor(c);
+	      //landmarkCollection->GetColor(c);
+	      int a=this->EventManager->d_colorBox("Landmark Color",c[0],c[1],c[2]);
+
+	      if (a==1)
+		{
+		  for (int j=0;j<BCC_MAX_RENDERERS;j++)
+		    {
+		      if (landmarkActor[j][current_collection]!=NULL)
+			landmarkActor[j][current_collection]->GetProperty()->SetColor(c);
+		    }
+		}
+	    }
+	  else
+	    fprintf(stderr,"Renderer[0]=NULL\n");
+	  break;
+	}
+
+      case 401:
+	{
+	  double c[3]; 	  
+	  if (renderer[0]!=NULL)
+	    {
+	      highlightActor[0]->GetProperty()->GetColor(c);
+	      int a=this->EventManager->d_colorBox("Highlight Color",c[0],c[1],c[2]); 	    
+	      if (a==1)
+		{
+		  for (int j=0;j<BCC_MAX_RENDERERS;j++)
+		    {
+		      if (highlightActor[j]!=NULL)
+			highlightActor[j]->GetProperty()->SetColor(c);
+		    }
+		}
+	    }
+	  else
+	    fprintf(stderr,"Renderer[0]=NULL\n");
+	  break;
+	}
+
+      case 500:
+	SetCurrentCollection(currentCollection->getIndex());
+	if (mouseMode->getIndex()!=0)
+	    {
+	      if (landmarkCollection->GetNumPoints()==0)
+		  mouseMode->setIndex(3);
+	      else  if (mouseMode->getIndex()>=3)
+		  mouseMode->setIndex(1);
+	    }
+	break;
+	      
+
+      case 501:
+	showCollection[current_collection]=displayCollection->getState();
+	Update();
+	break;
+
+      case 502:
+	if (mouseMode->getIndex()>=3)
+	    {
+	      int index=this->highlightIndex;// this->highlightIndex;
+	      int numitems=landmarkCollection->GetNumPoints();
+	      if (numitems>0 && index<0)
+		  {
+		    SetHighlight(0);
+		    UpdateStatus();
+		  }
+	    }
+	break;
+	
+      case 590:
+	clipboardCollection->Copy(landmarkCollection);
+	break;
+	
+      case 591:
+	if (clipboardCollection->GetNumPoints()>0)
+	    SetCollection(clipboardCollection,-1);
+	break;
+
+      case 592:
+	{
+	  PXContour* cntr=new PXContour();
+	  clipboardCollection->StoreInContour(cntr,image_plane);
+	  SetCollection(cntr,-1,image_plane,image_level);
+	  delete cntr;
+	}
+	break;
+
+      case 595:
+	landmarkCollection->Equispace(1.0);
+	//landmarkCollection->SetPointScale(0.5);
+	UpdateListFromCurrentCollection();
+	break;
+
+      case 596:
+	landmarkCollection->CreateCircle(image_plane,image_level);
+	UpdateListFromCurrentCollection();
+	break;
+
+      case 597:
+	landmarkCollection->RemoveIntersections(PXTrue,image_plane,image_level);
+	UpdateListFromCurrentCollection();
+	break;
+
+      case 598:
+	landmarkCollection->Equispace(2.0);
+	//landmarkCollection->SetPointScale(0.5);
+	UpdateListFromCurrentCollection();
+	break;
+
+      case 599:
+	landmarkCollection->Sample(8);
+	UpdateListFromCurrentCollection();
+	break;
+
+      case 600:
+	landmarkCollection->Sample(2);
+	UpdateListFromCurrentCollection();
+	break;
+
+      case 601:
+	landmarkCollection->SubSample(2);
+	UpdateListFromCurrentCollection();
+	break;
+
+      case 602:
+	landmarkCollection->Smooth(0.33);
+	UpdateListFromCurrentCollection();
+	break;
+
+      case 603:
+	landmarkCollection->Equispace(-1.0);
+	UpdateListFromCurrentCollection();
+	break;
+
+      case 604:
+	{
+	  float len=landmarkCollection->GetLength();
+	  sprintf(pxtk_buffer,"Curve %d Length=%8.1f mm\n",current_collection+1,len);
+	  PXTkApp::printToConsole(pxtk_buffer);
+	  this->EventManager->messageBox(pxtk_buffer,"Curve Length ...");
+	  break;
+	}
+
+      case 605:
+	{
+	  int plane=landmarkCollection->GetCurrentInternalPlane();//Irange(image_plane,0,2);
+	  if (image_plane==-1)
+	      plane=2;
+
+	  float area=landmarkCollection->GetPlaneArea(plane);
+	  sprintf(pxtk_buffer,"Curve %d Area=%8.1f (plane=%d)\n",current_collection+1,area,plane);
+	  PXTkApp::printToConsole(pxtk_buffer);
+	  this->EventManager->messageBox(pxtk_buffer,"Curve Area ...");
+	  break;
+	}
+
+      case 606:
+	{
+	  float mean,sigma;
+	  int plane,level;
+	  landmarkCollection->GetCurrentInternalPlaneAndLevel(plane,level);//Irange(image_plane,0,2);
+
+	  int num=landmarkCollection->ExtractVOIProperties(image,plane,level,image_frame,mean,sigma);
+	  float area=landmarkCollection->GetAreaFromPixels(num,plane);
+	  if(thresholdGUI!=NULL)
+	      {
+		if (thresholdGUI->isOpen())
+		    {
+		      float val=mean+2.0*sigma;
+		      sprintf(pxtk_buffer2,"%6.1f",val);
+		      entryThreshold->setText(pxtk_buffer2);
+		    }
+	      }
+
+	  if (num>=0)
+	      {
+		sprintf(pxtk_buffer,"Curve %d Mean Intensity=%8.1f Stdev=%8.1f (pixels>0=%d voxels, area=%5.2f mm2)\n(plane=%d,level=%d)",current_collection+1,mean,sigma,num,area,plane,level);
+		PXTkApp::printToConsole(pxtk_buffer);
+		this->EventManager->messageBox(pxtk_buffer,"Image Stats ...");
+	      }
+	  else
+	      {
+		sprintf(pxtk_buffer,"Curve %d Mean Intensity=%8.1f Stdev=%8.1f (Using Circle Mode)\n",
+			current_collection+1,mean,sigma);
+		PXTkApp::printToConsole(pxtk_buffer);
+		this->EventManager->messageBox(pxtk_buffer,"Image Stats ...");
+		UpdateListFromCurrentCollection();
+	      }
+	  
+	}
+	break;
+
+      
+      case 607:
+	DoExtract(1);
+	break;
+
+      case 608:
+	DoExtract(2);
+	break;
+
+      case 609:
+	DoExtract(0);
+	break;
+
+      case 610:
+	DoSnake(0);
+	break;
+
+      case 611:
+	DoSnake(1);
+	break;
+
+      case 612:
+	DoThreshold(0);
+	break;
+
+      case 613:
+	DoThreshold(1);
+	break;
+
+      case 614:
+	DoThreshold(2);
+	break;
+
+      case 615: // Angle
+	{
+	  double x1[3],x2[3];
+	  int np=landmarkCollection->GetNumPoints();
+	  if (np<2)
+	    {
+	      this->EventManager->messageBox("Need 2 points to calculate angle","Error!");
+	    }
+	  else
+	    {
+	      landmarkCollection->GetPoints()->GetPoint(np-2,x1);
+	      landmarkCollection->GetPoints()->GetPoint(np-1,x2);
+	      double sp[3]; landmarkCollection->GetSpacing(sp);
+
+	      for (int ia=0;ia<=2;ia++)
+		{
+		  x2[ia]=(x2[ia]-x1[ia])*sp[ia];
+		  x1[ia]=fabs(x2[ia]);
+		}
+
+	      int minindex=0;
+	      if (x1[1]<x1[0] && x1[1]<x1[2])
+		minindex=1;
+	      else if (x1[2]<x1[0] && x1[2]<x1[1])
+		minindex=2;
+	      
+	      int a1=Icyclic(minindex+1,3);
+	      int a2=Icyclic(minindex+2,3);
+	      float angle=atan2(x2[a2],x2[a1])*180/M_PI;
+	      
+	      switch (minindex)
+		{
+		case 0:
+		  sprintf(pxtk_buffer," X-Rotation %5.1f",angle);
+		  break;
+		case 1:
+		  sprintf(pxtk_buffer," Y-Rotation %5.1f",angle);
+		  break;
+		case 2:
+		  sprintf(pxtk_buffer," Z-Rotation %5.1f",angle);
+		  break;
+		}
+	      this->EventManager->messageBox(pxtk_buffer,"Rotation Result (use -1*answer)");
+	    }
+	}
+	break;
+      }
+  
+
+  if (event>=595 && event<=614)
+    {
+      if (mouseMode->getIndex()>=3)
+	  mouseMode->setIndex(1);
+    }
+
+  this->UpdateDisplay();
+  /*  if (this->EventParent!=NULL && this->CallbackNo>0)
+      this->EventParent->HandleEvent(CallbackNo);*/
+
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+void  vtkpxGUIBaseCurveControl::SetSpacingOrigin(double sp[3],double ori[3])
+{
+  for (int i=0;i<num_collections;i++)
+    {
+      allCollections[i]->RescaleOriginSpacing(ori,sp);
+      //allCollections[i]->SetOrigin(ori);
+      allCollections[i]->Update();
+    }
+
+  clipboardCollection->RescaleOriginSpacing(ori,sp);
+  //clipboardCollection->SetSpacing(sp);
+  //clipboardCollection->SetOrigin(ori);
+
+  UpdateListFromCurrentCollection();
+
+}
+
+/* -------------------------------------------------------------------------*/
+vtkpxBaseCurve* vtkpxGUIBaseCurveControl::GetCollection(int index)
+{
+  if (index==-1)
+      index=current_collection;
+
+  return allCollections[Irange(index,0,num_collections-1)];
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::GetCurrentIndex()
+{
+  return current_collection;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::SetCollection(vtkpxBaseCurve* land,int index)
+{
+  if (index==-1)
+    index=current_collection;
+  
+  index=Irange(index,0,num_collections-1);
+  //  fprintf(stderr,"Setting Collection %d\n",index);
+
+  allCollections[index]->Copy(land);
+  allCollections[index]->Modified();
+
+  if (index==current_collection)
+      {
+	UpdateListFromCurrentCollection();
+	if (landmarkCollection->GetNumPoints()==0)
+	  mouseMode->setIndex(3);
+	else  if (mouseMode->getIndex()>=3)
+	  mouseMode->setIndex(1);
+      }
+  
+  /*if (allCollections[index]->GetCurveActor()!=NULL)
+    {
+    allCollections[index]->DrawLandmarks(0);*/
+  allCollections[index]->Update();
+  //}
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::SetCollection(PXContour* cntr,int index,int plane,int level)
+{
+  if (cntr==NULL)
+      return;
+  
+  if (index==-1)
+      index=current_collection;
+
+  if (plane==-1)
+    plane=2;
+  plane=Irange(plane,0,2);
+
+  index=Irange(index,0,num_collections-1);
+  //fprintf(stderr,"Changing point set %d (np=%d) --> ",index,allCollections[index]->GetNumPoints());
+  allCollections[index]->SetFromContour(cntr,plane,level);
+
+  //  fprintf(stderr,"to %d (np=%d)\n",cntr->GetNumPoints(),allCollections[index]->GetNumPoints());
+  
+  if (index==current_collection)
+      {
+	UpdateListFromCurrentCollection();
+	if (landmarkCollection->GetNumPoints()==0)
+	    mouseMode->setIndex(3);
+	else  if (mouseMode->getIndex()>=3)
+	    mouseMode->setIndex(1);
+      }
+
+  /*if (allCollections[index]->GetCurveActor()!=NULL)
+      {
+	if (allCollections[index]->GetVisibility()==1)
+	    {
+	      allCollections[index]->DrawLandmarks(0);
+	      allCollections[index]->DrawCurve();
+	    }
+	    }*/
+  allCollections[index]->Update();
+ 
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::DisableCurve()
+{
+  if (!this->Initialized)
+    enable_curve=PXFalse;
+}
+
+void vtkpxGUIBaseCurveControl::DisableComplex()
+{
+  if (!this->Initialized)
+    enable_complex=PXFalse;
+}
+
+void vtkpxGUIBaseCurveControl::DisableLabels()
+{
+  if (!this->Initialized)
+    {
+      enable_labels=PXFalse;
+      for (int i=0;i<num_collections;i++)
+	{
+	  allCollections[i]->SetShowControls(1);
+	  allCollections[i]->SetShowCurve(1);
+	}
+    }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::DisableList()
+{
+  if (!this->Initialized)
+      {
+	enable_list=PXFalse;
+	enable_labels=PXFalse;
+	for (int i=0;i<num_collections;i++)
+	  {
+	    allCollections[i]->SetShowControls(1);
+	    allCollections[i]->SetShowCurve(1);
+	  }
+      }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::SetImage(vtkImageData* img,int plane,int level,int fr)
+{
+  if (img==NULL)
+    return;
+
+  if (image!=img)
+      {
+	image=img;
+	image->GetPointData()->GetScalars()->GetRange(image_range);
+	if (extractGUI!=NULL)
+	    {
+	      if (extractGUI->isOpen())
+		extractGUI->popdownDialog();
+	    }
+	SetSpacingOrigin(image->GetSpacing(),image->GetOrigin());
+      }
+  SetPlaneLevel(plane,level);
+  SetFrame(fr);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::SetPlaneLevel(int plane,int level)
+{
+  //  fprintf(stderr,"Setting Plane and Level=%d,%d\n",plane,level);
+  image_plane=plane;
+  image_level=level;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::SetFrame(int fr)
+{
+  image_frame=fr;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::SetLookupTable(vtkLookupTable* lookuptable)
+{
+  currentColormap=lookuptable;
+  if (backupColormap==NULL)
+    backupColormap=vtkLookupTable::New();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::ClipboardCommand(int mode)
+{
+  // modes = { 1=Cut , 2=Copy , 3= Paste , 4=Delete }3
+
+  //int  current=this->highlightIndex;
+  int current=this->highlightIndex;
+  
+  if (current==-1 && (mode==1 || mode==2 || mode==4))
+      return;
+
+  if ((mode==1 || mode==2) && enable_list)
+      strcpy(clipboard,listBox->getItem(current));
+
+  if ((mode==1 || mode==4))
+      {
+	int oldc=current;
+	landmarkCollection->DeletePoint(current); 
+	if (enable_list)
+	    listBox->clearItem(current);
+	      
+	if (oldc>0)
+	  SetHighlight(oldc-1);
+	else
+	  SetHighlight(0);
+      }
+
+  if ((mode==3 && strlen(clipboard)>10) && enable_list)
+      {
+	float x,y,z;
+	ExtractCoordinates(clipboard,x,y,z);
+	AddListLandmark(x,y,z,-1,0);
+	SetHighlight(landmarkCollection->GetNumPoints()-1);
+      }
+  UpdateStatus();
+}
+/* -------------------------------------------------------------------------*/      
+void vtkpxGUIBaseCurveControl::AddListLandmark(float x,float y,float z,
+					       int index,int scaled,int listonly)
+{
+  //fprintf(stderr,"\n +++ Adding List Landmark (%f,%f,%f) index=%d scaled=%d listonly=%d\n",x,y,z,index,scaled,listonly);
+  double sp[3]; landmarkCollection->GetSpacing(sp);
+  double ori[3]; landmarkCollection->GetOrigin(ori);
+
+  if (index==-1)
+    {
+      if (!listonly)
+	{
+	  landmarkCollection->AddPoint(x,y,z,scaled);
+	  landmarkCollection->Modified();
+	  landmarkCollection->Update();
+	}
+      if (enable_list)
+	{
+	  
+	  if (scaled==0)
+	    sprintf(pxtk_buffer,"%6.2f,%6.2f,%6.2f",x,y,z); 
+	  else
+	    sprintf(pxtk_buffer,"%6.2f,%6.2f,%6.2f",(x-ori[0])/sp[0],(y-ori[1])/sp[1],(z-ori[2])/sp[2]); 
+	  listBox->addItem(pxtk_buffer);
+	  PXTkApp::executeTclCommand("update idletasks");
+	}
+    }
+  else
+    {
+      if (!listonly)
+	{
+	  landmarkCollection->SetPoint(index,x,y,z,scaled);    
+	  landmarkCollection->Modified();
+	  landmarkCollection->Update();
+	}
+      
+      if (enable_list)
+	{
+	  if (scaled==0)
+	    sprintf(pxtk_buffer,"%6.2f,%6.2f,%6.2f",x,y,z); 
+	  else
+	    sprintf(pxtk_buffer,"%6.2f,%6.2f,%6.2f",(x-ori[0])/sp[0],(y-ori[1])/sp[1],(z-ori[2])/sp[2]); 
+	  listBox->clearItem(index);
+	  listBox->addItem(pxtk_buffer,index);
+	  PXTkApp::executeTclCommand("update idletasks");
+	}
+    }
+  
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::HandleClickedPoint(float x,float y,float z,int scaled,int state)
+{
+  if (!this->EventManager->isOpen() && !this->EventManager->isInside())
+    return 0;
+
+  //  fprintf(stderr,"x=%.1f,y=%.1f z=%.1f scaled=%d state=%d\n",x,y,z,scaled,state);
+
+  int mode=mouseMode->getIndex();
+  
+  if (mode==0 || state>=3)
+      return 0;
+  
+  int index=this->highlightIndex;//listBox->getCurrentItem();
+  int numitems=landmarkCollection->GetNumPoints();//listBox->getNumItems();
+  
+  /*fprintf(stderr,"Mousemode=%d , index=%d, numitems=%d coord=(%f,%f,%f) state=%d\n",
+    mode,index,numitems,x,y,z,state);*/
+
+  switch (mode)
+    {
+    case 4:  // Continuous Add Mode 
+      switch(state)
+	{
+	case 0:
+	  break;
+	case 1:
+	  AddListLandmark(x,y,z,-1,scaled,0);
+	  /*index=landmarkCollection->GetNumPoints()-1;
+	  if (enable_list)
+	  SetHighlight(index);*/
+	  break;
+	case 2:
+	  SetHighlight(index);
+	  if (enable_list)
+	    {
+	      sprintf(pxtk_buffer,"%s see end",listBox->getWidgetName());
+	      PXTkApp::executeTclCommand(pxtk_buffer);
+	    }
+	  UpdateStatus();
+	  break;
+	}
+      return 1;
+      break;
+      
+
+    case 3:  // Add Mode 
+      switch(state)
+	{
+	case 0:
+	  AddListLandmark(x,y,z,-1,scaled,0);
+	  index=landmarkCollection->GetNumPoints()-1;
+	  //if (enable_list)
+	  SetHighlight(index);
+	  //fprintf(stderr,"Current Highlight Index=%d\n",this->highlightIndex);
+	  break;
+	case 1:
+	  AddListLandmark(x,y,z,index,scaled,0);
+	  //	  if (enable_list)
+	  SetHighlight(index);
+	  break;
+	case 2:
+	  AddListLandmark(x,y,z,index,scaled,0);
+	  SetHighlight(index);
+	  if (enable_list)
+	    {
+
+	      sprintf(pxtk_buffer,"%s see end",listBox->getWidgetName());
+	      PXTkApp::executeTclCommand(pxtk_buffer);
+	    }
+	  UpdateStatus();
+	  break;
+	}
+      return 1;
+      break;
+      
+    case 1: // Pick Mode 
+      if (numitems<1)
+	return 0;
+      switch (state)
+	{
+	case 0:
+	  {
+	    double lx[3];
+	    lx[0]=x;lx[1]=y;lx[2]=z;
+	    int found=landmarkCollection->FindClosestPoint(lx,landmarkCollection->GetPointScale()*1.2,scaled);
+	    if (found>-1)
+	      {
+		if (enable_list)
+		  listBox->selectItem(found);
+		SetHighlight(found);
+	      }
+	    else 
+	      {
+		if (enable_list)		    
+		  listBox->selectItem(-1);
+		SetHighlight(-1);
+	      }
+	    break;
+	  }
+	case 1:
+	  if (index>=0)
+	    {
+	      AddListLandmark(x,y,z,index,scaled,0);
+	      SetHighlight(index);
+	    }
+	    break;
+	case 2:
+	  if (index>=0)
+	    {
+	      AddListLandmark(x,y,z,index,scaled,0);
+	      if (enable_list)
+		SetHighlight(index);
+	      UpdateStatus();
+	    }
+	  break;
+	}
+      return 1;
+      break;
+      
+    case 2: // Edit Mode 
+      if (index<0)
+	return 0;
+      switch(state)
+	{
+	case 0:
+	  AddListLandmark(x,y,z,index,scaled,0);
+	  listBox->selectItem(index);
+	  break;
+	case 1:
+	  AddListLandmark(x,y,z,index,scaled,0);
+	  SetHighlight(index);
+	  break;
+	case 2:
+	  AddListLandmark(x,y,z,index,scaled,0);
+	  if (index<numitems-1)
+	    {
+	      index++;
+	    }
+	  else if (enable_labels)
+	    {
+	      if (index<labelListBox->getNumItems())
+		mouseMode->setIndex(3);
+	    }
+	  SetHighlight(index);
+	  UpdateStatus();
+	  break;
+	}
+      return 1;
+    }
+  return 0;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::LoadLandmarks(const char* fname)
+{
+  strcpy(pxtk_buffer2,fname);
+  int ok=landmarkCollection->Load(fname);
+  if (!ok)
+      {
+	sprintf(pxtk_buffer,"Failed to load landmarks %d from %s",current_collection+1,fname);
+	this->EventManager->messageBox(pxtk_buffer,"Load Failure");
+      }
+  else
+    {
+      sprintf(pxtk_buffer2,"%s.%d",PXTkApp::getFilenameTail(pxtk_buffer2),current_collection+1);
+      currentCollection->changeLabel(current_collection,pxtk_buffer2);
+      
+      if (image!=NULL)
+	landmarkCollection->RescaleOriginSpacing(image->GetOrigin(),image->GetSpacing());
+
+      UpdateListFromCurrentCollection();
+      landmarkCollection->Update();
+    }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::SaveSeedFile(const char* fname)
+{
+  strcpy(pxtk_buffer2,fname);
+  FILE* fout=fopen(fname,"w");
+  if (fout)
+    {
+      for (int i=0;i<landmarkCollection->GetNumPoints();i++)
+	    {
+	      double x[3];
+	      landmarkCollection->GetPoints()->GetPoint(i,x);
+	      fprintf(fout,"%6.1f %6.1f %6.1f 1.5 1.5 1.5\n",x[0],x[1],x[2]);
+	    }
+      fclose(fout);
+    }
+  else
+    {
+      sprintf(pxtk_buffer,"Failed to export landmarks %d to seed file %s",current_collection+1,fname);
+      this->EventManager->messageBox(pxtk_buffer,"Export Failure");
+    }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::LoadSeedFile(const char* fname)
+{
+  strcpy(pxtk_buffer2,fname);
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (fin)
+    {
+      landmarkCollection->DeleteAllPoints(); SetHighlight(-1);
+
+      float x,y,z,tx,ty,tz;
+      while (gzgets(fin,pxtk_buffer2,100))
+	{
+	  sscanf(pxtk_buffer2,"%f %f %f %f %f %f",&x,&y,&z,&tx,&ty,&tz);
+	  landmarkCollection->AddPoint(x,y,z,0);
+	}
+      gzclose(fin);
+      UpdateListFromCurrentCollection();
+      landmarkCollection->Update();
+    }
+  else
+    {
+      sprintf(pxtk_buffer,"Failed to import landmarks %d from seed file %s",current_collection+1,fname);
+      this->EventManager->messageBox(pxtk_buffer,"Import Failure");
+    }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::ExtractCoordinates(const char* line,float& x,float& y,float& z)
+{
+  sscanf(line,"{%f,%f,%f}",&x,&y,&z);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::SetCurrentCollection(int num)
+{
+  num=Irange(num,0,num_collections-1);
+  if (num==current_collection)
+      return;
+  current_collection=num;
+
+  landmarkCollection=allCollections[current_collection];  
+  displayCollection->setState(showCollection[current_collection]);
+  Update();
+
+  int sc=int(landmarkCollection->GetPointScale()/0.25)-1;
+  scaleMode->setIndex(sc);
+
+  int c=landmarkCollection->GetShowCurve();
+  int m=landmarkCollection->GetClosedCurve();
+  int b=landmarkCollection->GetShowBoundingBox();
+
+  if (b==1)
+    {
+      curveMode->setIndex(3);
+    }
+  else
+    {
+      if (c==0)
+	{
+	  curveMode->setIndex(0);
+	}
+      else
+	{
+	  if (m==1)
+	    curveMode->setIndex(2);
+	  else
+	    curveMode->setIndex(1);
+	}
+    }
+
+  UpdateListFromCurrentCollection();
+  if (landmarkCollection->GetNumPoints()>0)
+    SetHighlight(0);
+  else
+    SetHighlight(-1);
+  UpdateStatus();
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::UpdateListFromCurrentCollection()
+{
+  //  curveMode->setIndex(landmarkCollection->GetCurveMode());
+  int c=landmarkCollection->GetShowCurve();
+  int m=landmarkCollection->GetClosedCurve();
+  int b=landmarkCollection->GetShowBoundingBox();
+
+  if (b==1)
+    {
+      curveMode->setIndex(3);
+    }
+  else
+    {
+      if (c==0)
+	{
+	  curveMode->setIndex(0);
+	}
+      else
+	{
+	  if (m==1)
+	curveMode->setIndex(2);
+	  else
+	    curveMode->setIndex(1);
+	}
+    }
+
+  int sc=int(landmarkCollection->GetPointScale()/0.25)-1;
+  scaleMode->setIndex(sc);
+
+  if (enable_list)
+      {
+	listBox->clearList();
+
+	if (landmarkCollection->GetNumPoints()>0)
+	    {
+	      for (int i=0;i<landmarkCollection->GetNumPoints();i++)
+		  {
+		    double x[3];
+		    landmarkCollection->GetPoint(i,x[0],x[1],x[2]);
+		    AddListLandmark(x[0],x[1],x[2],i,0,1);
+		  }
+	      SetHighlight(0);
+	    }
+      }
+  UpdateStatus();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::CreateEditWindow(int editcallback)
+{
+  if (edit_window!=NULL || enable_list==PXFalse)
+      return;
+
+  PXTkFrame* landmarkFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+  
+  edit_window=new PXTkDialog(this->EventManager,landmarkFrame,"Edit Point",PXFalse);
+  edit_window->initDisplay();
+  PXTkFrame* editFrame=(PXTkFrame*)edit_window->getMainWindow();
+  editFrame->setPackMode(PXFalse);
+  
+  PXTkLabel* lab2=new PXTkLabel(this->EventManager,editFrame,"Coord (x,y,z)");
+  editFrame->gridRowColumnChild(lab2,1,0);
+  
+  for (int kk=0;kk<=2;kk++)
+      {
+	coord[kk]=new PXTkEntry(this->EventManager,editFrame);
+	coord[kk]->configure("-width",8);
+	editFrame->gridRowColumnChild(coord[kk],0,kk+1);
+      }
+
+  PXTkButton* upd=new PXTkButton(this->EventManager,editFrame,"Update",editcallback);
+  editFrame->gridRowColumnChild(upd,1,0,1,2);
+
+  PXTkButton* b1=new PXTkButton(edit_window,editFrame,"Close",3);
+  editFrame->gridRowColumnChild(b1,1,2);
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::UpdateEditWindow()
+{
+  if (enable_list==PXFalse)
+      return TCL_OK;
+
+  edit_item=listBox->getCurrentItem();
+  if (edit_item<0)
+      return TCL_OK;
+
+  char* line=listBox->getItem(edit_item);
+  float x[3];
+  ExtractCoordinates(line,x[0],x[1],x[2]);
+  
+  for (int kk=0;kk<=2;kk++)
+      {
+	sprintf(pxtk_buffer,"%6.2f",x[kk]);
+	coord[kk]->setText(pxtk_buffer);
+      }
+
+  edit_window->popupDialog();
+  edit_window->setModality(PXTrue);
+
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::HandleEditWindowCallback()
+{
+  if (edit_item<0 || enable_list==PXFalse)
+      return TCL_OK;
+
+  float x[3];
+  for (int i=0;i<=2;i++)
+      {
+	char*a =coord[i]->getText();
+	x[i]=atof(a);
+      }
+
+  edit_window->setModality(PXFalse);
+  AddListLandmark(x[0],x[1],x[2],edit_item,0,0);
+  SetHighlight(edit_item);
+  edit_window->setModality(PXTrue);
+
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::LoadSetupFile(const char* fname)
+{
+  strcpy(lamstring,fname);
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (fin)
+      {
+	gzgets(fin,pxtk_buffer,100);
+	if (gzfindstringinstring(pxtk_buffer,"#Landmark Setup File")==0)
+	    {
+	      gzclose(fin);
+	      return 0;
+	    }
+	gzgets(fin,pxtk_buffer,100); 	
+	gzgets(fin,pxtk_buffer,100);
+	int num;
+	sscanf(pxtk_buffer,"%d",&num);
+	gzgets(fin,pxtk_buffer,100); 	
+
+	labelListBox->clearList();
+	
+	for (int i=0;i<num;i++)
+	    {
+	      gzgets(fin,pxtk_buffer,100);
+	      pxtk_buffer[strlen(pxtk_buffer)-1]=(char)0; // eat end of-line
+	      labelListBox->addItem(pxtk_buffer,-1);
+	    }
+	gzclose(fin);
+
+	int num2=(landmarkCollection->GetNumPoints());
+	if (num2<num)
+	    {
+	      for (int i=num2;i<num;i++)
+		  AddListLandmark(0.0,0.0,0.0,-1,0,0);
+	    }
+	SetHighlight(0);
+
+	if (mouseMode->getIndex()>=3)
+	    mouseMode->setIndex(2);
+	
+	sprintf(lamstring,"Loaded  setupfile (%d)  from %s \n",num,lamstring);
+	PXTkApp::printToConsole(lamstring);
+
+	UpdateStatus();
+	return 1;
+      }
+  sprintf(pxtk_buffer,"Failed to load setup file from %s",fname);
+  this->EventManager->messageBox(pxtk_buffer,"Load Failure");
+
+  return 0;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::SaveSetupFile(const char* fname)
+{
+  strcpy(lamstring,fname);
+  FILE* fout=fopen(fname,"w");
+  if (fout)
+      {
+	fprintf(fout,"#Landmark Setup File\n");
+	fprintf(fout,"#Number of Landmarks\n%d\n",labelListBox->getNumItems());
+	fprintf(fout,"#Landmark Names\n");
+	
+	for (int i=0;i<labelListBox->getNumItems();i++)
+	    {
+	      char* line=labelListBox->getItem(i);
+	      if (strlen(line)>=2)
+		  {
+		    strcpy(pxtk_buffer,&line[1]);
+		    pxtk_buffer[strlen(pxtk_buffer)-1]=(char)32;
+		    fprintf(fout,"%s\n",pxtk_buffer);
+		  }
+	      else
+		  fprintf(fout,"%s\n",labelListBox->getItem(i));
+	    }
+	fclose(fout);
+	sprintf(lamstring,"Saved Setup File (%d)  in %s \n",labelListBox->getNumItems(),lamstring);
+	PXTkApp::printToConsole(lamstring);
+	return 1;
+      }
+
+  sprintf(pxtk_buffer,"Failed to save setup file in %s",fname);
+  this->EventManager->messageBox(pxtk_buffer,"Save Failure");
+  return 0;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::SetTalarachSetup()
+{
+  int ok=1;
+  if (landmarkCollection->GetNumPoints()>0)
+    ok=this->EventManager->questionBox("Setup will delete ALL your old landmarks in all sets. Are you sure?");
+  if (!ok)
+    return 0;
+
+  landmarkCollection->DeleteAllPoints(); 
+  labelListBox->clearList();
+  labelListBox->addItem("AC     ",-1);
+  labelListBox->addItem("PC     ",-1);
+  labelListBox->addItem("Bottom Z",-1);
+  labelListBox->addItem("Top    Z",-1);
+  labelListBox->addItem("Bound 1",-1);
+  labelListBox->addItem("Bound 2",-1);
+  labelListBox->addItem("Bound 3",-1);
+  labelListBox->addItem("Bound 4",-1);
+  labelListBox->addItem("Bound 5",-1);
+  labelListBox->addItem("Bound 6",-1);
+  labelListBox->addItem("Bound 7",-1);
+  labelListBox->addItem("Bound 8",-1);
+  labelListBox->addItem("Bound 9",-1);
+
+  SetHighlight(-1);
+  mouseMode->setIndex(3);
+  curveMode->setIndex(3,PXTrue);
+  UpdateListFromCurrentCollection();
+  landmarkCollection->Update(); 
+  UpdateStatus();
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::SetBrainstripSetup()
+{
+  labelListBox->clearList();
+  labelListBox->addItem("Left 1",-1);
+  labelListBox->addItem("Left 2",-1);
+  labelListBox->addItem("Left 3",-1);
+  labelListBox->addItem("Right 1",-1);
+  labelListBox->addItem("Right 2",-1);
+  labelListBox->addItem("Right 3",-1);
+  labelListBox->addItem("Stem   ",-1);
+
+  int num=(landmarkCollection->GetNumPoints());
+  if (num<7)
+    {
+      for (int i=num;i<7;i++)
+	AddListLandmark(0.0,0.0,0.0,-1,0,0);
+    }
+  
+  SetHighlight(0);
+  mouseMode->setIndex(2);
+  UpdateStatus();
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::SetArticulatedMouseSetup(int hasfeet,int hashindlimbs,int hasforelimbs,
+						       int hashead,int taildivisions,int spinedivisions)
+{
+  int ok=0;
+  if (landmarkCollection->GetNumPoints()>0)
+    ok=this->EventManager->questionBox("Would you like to delete your current points?");
+
+  //  fprintf(stderr,"In Setting Articulated Mouse Setup\n");
+  
+  if (ok==1)
+    landmarkCollection->DeleteAllPoints(); 
+  SetHighlight(-1);
+  labelListBox->clearList();
+  labelListBox->addItem("Body Center",-1);
+  labelListBox->addItem("Body X-Axis",-1);
+  labelListBox->addItem("Body Y-Axis",-1);
+
+  if (hashindlimbs>0)
+    {
+      labelListBox->addItem("Left Hip Center",-1);
+      labelListBox->addItem("Left Hip X-Axis",-1);
+      labelListBox->addItem("Left Hip Y-Axis",-1);
+      labelListBox->addItem("Left Knee Center",-1);
+      labelListBox->addItem("Left Knee X-Axis",-1);
+      labelListBox->addItem("Left Knee Y-Axis",-1);
+      if (hasfeet)
+	{
+	  labelListBox->addItem("Left Ankle Center",-1);
+	  labelListBox->addItem("Left Ankle X-Axis",-1);
+	  labelListBox->addItem("Left Ankle Y-Axis",-1);
+	}
+      labelListBox->addItem("Right Hip Center",-1);
+      labelListBox->addItem("Right Hip X-Axis",-1);
+      labelListBox->addItem("Right Hip Y-Axis",-1);
+      labelListBox->addItem("Right Knee Center",-1);
+      labelListBox->addItem("Right Knee X-Axis",-1);
+      labelListBox->addItem("Right Knee Y-Axis",-1);
+      if (hasfeet)
+	{
+	  labelListBox->addItem("Right Ankle Center",-1);
+	  labelListBox->addItem("Right Ankle X-Axis",-1);
+	  labelListBox->addItem("Right Ankle Y-Axis",-1);
+	}
+    }
+
+  if (hasforelimbs>0)
+    {
+      labelListBox->addItem("Left Shoulder Center",-1);
+      labelListBox->addItem("Left Shoulder X-Axis",-1);
+      labelListBox->addItem("Left Shoulder Y-Axis",-1);
+      labelListBox->addItem("Left Elbow Center",-1);
+      labelListBox->addItem("Left Elbow X-Axis",-1);
+      labelListBox->addItem("Left Elbow Y-Axis",-1);
+      if (hasfeet)
+	{
+	  labelListBox->addItem("Left Wrist Center",-1);
+	  labelListBox->addItem("Left Wrist X-Axis",-1);
+	  labelListBox->addItem("Left Wrist Y-Axis",-1);
+	}
+      labelListBox->addItem("Right Shoulder Center",-1);
+      labelListBox->addItem("Right Shoulder X-Axis",-1);
+      labelListBox->addItem("Right Shoulder Y-Axis",-1);
+      labelListBox->addItem("Right Elbow Center",-1);
+      labelListBox->addItem("Right Elbow X-Axis",-1);
+      labelListBox->addItem("Right Elbow Y-Axis",-1);
+      if (hasfeet)
+	{
+	  labelListBox->addItem("Right Wrist Center",-1);
+	  labelListBox->addItem("Right Wrist X-Axis",-1);
+	  labelListBox->addItem("Right Wrist Y-Axis",-1);
+	}
+    }
+
+  char line[200],line2[100];
+  if (taildivisions>0)
+    {
+      for (int i=0;i<taildivisions;i++)
+	{
+	  sprintf(line2,"Tail-%d ",i+1);
+	  sprintf(line,"%s Center",line2); 	  labelListBox->addItem(line,-1);
+	  sprintf(line,"%s X-Axis",line2); 	  labelListBox->addItem(line,-1);
+	  sprintf(line,"%s Y-Axis",line2); 	  labelListBox->addItem(line,-1);
+	}
+    }
+
+  if (spinedivisions>0)
+    {
+      for (int i=0;i<spinedivisions;i++)
+	{
+	  sprintf(line2,"Spine-%d ",i+1);
+	  sprintf(line,"%s Center",line2); 	  labelListBox->addItem(line,-1);
+	  sprintf(line,"%s X-Axis",line2); 	  labelListBox->addItem(line,-1);
+	  sprintf(line,"%s Y-Axis",line2); 	  labelListBox->addItem(line,-1);
+	}
+    }
+
+  if (hashead>0)
+    {
+      labelListBox->addItem("Neck Center",-1);
+      labelListBox->addItem("Neck X-Axis",-1);
+      labelListBox->addItem("Neck Y-Axis",-1);
+    }
+
+  mouseMode->setIndex(3);  
+  curveMode->setIndex(1,PXTrue);
+  UpdateListFromCurrentCollection();
+  landmarkCollection->Update(); 
+  UpdateStatus();
+
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::SetTransformSetup()
+{
+  labelListBox->clearList();
+  labelListBox->addItem("Origin",-1);
+  labelListBox->addItem("X-Axis",-1);
+  labelListBox->addItem("Y-Axis",-1);
+  labelListBox->addItem("Z-Axis",-1);
+  int num=(landmarkCollection->GetNumPoints());
+  if (num<4)
+    {
+      for (int i=num;i<4;i++)
+	AddListLandmark(0.0,0.0,0.0,-1,0,0);
+    }
+  
+  SetHighlight(0);
+  mouseMode->setIndex(2);
+  UpdateStatus();
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::SaveTransform(const char* fname)
+{
+  strcpy(pxtk_buffer,fname);
+
+
+  if (landmarkCollection->GetNumPoints()<2)
+    {
+      this->EventManager->messageBox("Not Enough Points (<2) to Generate Tranformation","No Transformation Generated!");
+      return;
+    }
+
+  if (this->image==NULL)
+    {
+      this->EventManager->messageBox("Not Image to Generate Tranformation","No Transformation Generated!");
+      return;
+    }
+  double origin[3],sp[3],ori[3];
+  int dim[3];
+
+  image->GetSpacing(sp);
+  image->GetOrigin(ori);
+  image->GetDimensions(dim);
+
+  for (int ic=0;ic<=2;ic++)
+    origin[ic]=0.5*(float(dim[ic])*sp[ic]+ori[ic]);
+  
+
+  vtkTransform* tr=vtkTransform::New();
+  tr->Identity();
+  tr->PostMultiply();
+
+
+
+  vtkpxBaseCurve* tmp=vtkpxBaseCurve::New();
+  tmp->Copy(landmarkCollection);
+  tmp->Compact();
+
+
+  double x0[3],x1[3],x2[3],x3[3],midpoint[3];
+  int kk;
+  for (kk=0;kk<=2;kk++)
+    midpoint[kk]=0.0;
+ 
+  vtkPoints* tmppoints=tmp->GetPoints();
+
+  //  fprintf(stderr,"Origin = %.1f %.1f %.1f \n",origin[0],origin[1],origin[2]);
+  
+  if (landmarkCollection->GetNumPoints()>2)
+    {
+      tmppoints->GetPoint(0,x0);
+      tmppoints->GetPoint(1,x1);
+      tmppoints->GetPoint(2,x2);
+
+
+      for (int ia=0;ia<=2;ia++)
+	{
+	  midpoint[ia]=(x0[ia]+x1[ia]+x2[ia])/3.0;
+	  x1[ia]=x1[ia]-x0[ia];
+	  x2[ia]=x2[ia]-x0[ia];
+	}
+      
+      vtkMath::Normalize(x2);
+      vtkMath::Normalize(x1);
+      vtkMath::Cross(x1,x2,x3);
+    }
+  else
+    {
+      tmppoints->GetPoint(0,x0);
+      tmppoints->GetPoint(1,x2);
+
+
+
+      int bestdim=0;
+      float mindist=fabs(x0[0]-x2[0]);
+      for (int ia=1;ia<=2;ia++)
+	{
+	  float dist=fabs(x0[ia]-x2[ia]);
+	  if (dist<mindist)
+	    bestdim=ia;
+	}
+      
+      for (int dim=0;dim<=2;dim++)
+	{
+	  if (dim!=bestdim)
+	    x1[dim]=0.0;
+	  else
+	    x1[dim]=1.0;
+	}
+      
+      {
+	for (int ia=0;ia<=2;ia++)
+	  {
+	    midpoint[ia]=(x0[ia]+x2[ia])/2.0;
+	    x2[ia]=x2[ia]-x0[ia];
+	  }
+      }
+      vtkMath::Normalize(x2);
+
+      vtkMath::Cross(x1,x2,x3);
+
+      /*fprintf(stderr,"Bestdim=%d\n",bestdim);
+	fprintf(stderr,"x1 = %.1f %.1f %.1f \n",x1[0],x1[1],x1[2]);
+	fprintf(stderr,"x2 = %.1f %.1f %.1f \n",x2[0],x2[1],x2[2]);
+	fprintf(stderr,"x3 = %.1f %.1f %.1f \n",x3[0],x3[1],x3[2]);*/
+
+    }
+
+
+
+  tr->Translate(-origin[0],-origin[1],-origin[2]);
+
+  double matr[16];
+  for (kk=0;kk<15;kk++)
+    matr[kk]=0.0;
+
+  // Set the 3x3 Section with the vectors x2,x3,x1 ::: Done 
+  for (int i=0;i<=2;i++)
+    {
+      matr[0*4+i]=x1[i];
+      matr[1*4+i]=x2[i];
+      matr[2*4+i]=x3[i];
+    }
+  matr[15]=1.0;
+  tr->Concatenate(matr);
+
+
+  //tr->Translate(origin[0],origin[1],origin[2]);
+  tr->Translate(midpoint[0],midpoint[1],midpoint[2]);
+
+  FILE* fout=fopen(pxtk_buffer,"w");
+  if (fout)
+    {
+      for(int i=0;i<=3;i++)
+	{
+	  for (int j=0;j<=3;j++)
+	    fprintf(fout,"%7.3f ",tr->GetMatrix()->GetElement(i,j));
+	  fprintf(fout,"\n");
+	}
+      fclose(fout);
+    }
+  tmp->Delete();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::CreateLabelWindow()
+{
+  if (!enable_labels)
+    return;
+
+  PXTkFrame* landmarkFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+  
+  label_window=new PXTkDialog(this->EventManager,landmarkFrame,"Label Editor",PXFalse);
+  label_window->initDisplay();
+  PXTkFrame* labelFrame=(PXTkFrame*)label_window->getMainWindow();
+  
+  PXTkFrame* listFrame=new PXTkFrame(this->EventManager,labelFrame);
+  labelFrame->addChildren("-side top -expand true -fill both",listFrame);  
+  PXTkFrame* buttonFrame=new PXTkFrame(this->EventManager,labelFrame);
+  labelFrame->addChildren("-side top -expand false -fill x",buttonFrame);  
+  buttonFrame->setPackMode(PXFalse);
+
+  PXTkScrollbar* ybar=new PXTkScrollbar(this->EventManager,listFrame,PXTrue);
+  labelListBox=new PXTkListBox(this->EventManager,listFrame,320);
+  ybar->attachGadget(labelListBox);
+  
+  labelListBox->configure("-width",25);
+  labelListBox->configure("-height",10);
+  labelListBox->configure("-wrap","none");
+  labelListBox->configure("-relief","ridge");
+  
+  listFrame->addChildren("-side left -expand true -fill both",labelListBox);
+  listFrame->addChildren("-side left -expand false -fill y",ybar);
+
+  PXTkButton *b1=new PXTkButton(this->EventManager,buttonFrame,"Add",322);
+  PXTkButton *b2=new PXTkButton(this->EventManager,buttonFrame,"Insert",323);
+  PXTkButton *b3=new PXTkButton(this->EventManager,buttonFrame,"Delete",324);
+  PXTkButton *b4=new PXTkButton(this->EventManager,buttonFrame,"Delete All",325);
+  buttonFrame->gridRowColumnChild(b1,1,0);
+  buttonFrame->gridRowColumnChild(b2,1,1);
+  buttonFrame->gridRowColumnChild(b3,1,2);
+  buttonFrame->gridRowColumnChild(b4,1,3);
+
+  label_entry=new PXTkEntry(this->EventManager,buttonFrame);
+  buttonFrame->gridRowColumnChild(label_entry,0,0,1,3);
+  PXTkButton *b0=new PXTkButton(this->EventManager,buttonFrame,"Update",321);
+  buttonFrame->gridRowColumnChild(b0,0,3);
+
+  PXTkButton* b5=new PXTkButton(label_window,buttonFrame,"Close",3);
+  buttonFrame->gridRowColumnChild(b5,2,1,1,2);
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::HandleLabelWindowCallback(int option)
+{
+  if (!enable_labels)
+      return TCL_OK;
+
+  static int oldindex=-1;
+  char* entrytext=label_entry->getText();
+  
+  switch (option)
+      {
+      case 0: // List Callback
+	{
+	  int index=labelListBox->getCurrentItem();
+	  oldindex=index;
+	  if (index>=0)
+	    SetHighlight(index);
+	  char* line=labelListBox->getItem(index);
+	  if (strlen(line)>=2)
+	      {
+		strcpy(pxtk_buffer,&line[1]);
+		pxtk_buffer[strlen(pxtk_buffer)-1]=(char)0;
+		label_entry->setText(pxtk_buffer);
+	      }
+	  else
+	      label_entry->setText(line);
+	}
+	break;
+	
+      case 1: // Update
+	if (oldindex>=0)
+	    {
+	      labelListBox->clearItem(oldindex);
+	      labelListBox->addItem(entrytext,oldindex);
+	      labelListBox->selectItem(oldindex);
+	    }
+	break;
+	
+      case 2: // Add
+	labelListBox->addItem(entrytext,-1);
+	break;
+	
+      case 3: // Insert
+	if (oldindex>=0)
+	    {
+	      labelListBox->addItem(entrytext,oldindex);
+	      labelListBox->selectItem(oldindex);
+	    }
+	break;
+	
+      case 4: // Delete
+	if (oldindex>=0)
+	    {
+	      labelListBox->clearItem(oldindex);
+	      label_entry->setText("");
+	      oldindex=-1;
+	    }
+	break;
+	
+      case 5:
+	if (labelListBox->getNumItems()>0)
+	    {
+	      int ok=this->EventManager->questionBox("This will delete all your labels. Are you sure?");
+	      if (ok)
+		  {
+		    labelListBox->clearList();
+		    label_entry->setText("");
+		    oldindex=-1;
+		  }
+	    }
+	break;
+      }
+  UpdateStatus();
+  return TCL_OK;
+}
+
+
+int vtkpxGUIBaseCurveControl::DoExtract(int apply)
+{
+  if (image==NULL)
+      return 0;
+
+  if (apply==0)
+      {
+	if (extractGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+	      extractGUI=new PXTkDialog(this->EventManager,polyFrame,"Extract Controls",PXFalse);
+	      extractGUI->initDisplay();
+	      
+	      PXTkFrame* frame=(PXTkFrame*)extractGUI->getMainWindow();
+	      extractType=new PXTkOptionMenu(extractGUI,frame,"Auto Threshold",-1);
+	      extractType->addOption("Manual Threshold");
+	      extractType->setIndex(0);
+
+	      thresholdScale=new PXTkArrowScale(extractGUI,frame,"Threshold",-1,PXTrue);
+	      thresholdScale->setRange(0.0,255.0);
+	      thresholdScale->setValue(128.0);
+	      thresholdScale->setIncrement(1);
+	      thresholdScale->setResolution(1);
+	      thresholdScale->setLengthWidth(120,8);
+
+	      medianScale=new PXTkArrowScale(extractGUI,frame,"Median Radius",-1,PXTrue);
+	      medianScale->setRange(0.0,4.0);
+	      medianScale->setValue(0.0);
+	      medianScale->setIncrement(1.0);
+	      medianScale->setResolution(1.0);
+	      medianScale->setLengthWidth(120,8);
+
+	      sigmaScale=new PXTkArrowScale(extractGUI,frame,"Sigma",-1,PXTrue);
+	      sigmaScale->setRange(0.0,5.0);
+	      sigmaScale->setValue(0.0);
+	      sigmaScale->setIncrement(0.5);
+	      sigmaScale->setResolution(0.1);
+	      sigmaScale->setDecimalPoints(1);
+	      sigmaScale->setLengthWidth(120,8);
+
+	      PXTkFrame* fr2=new PXTkFrame(extractGUI,frame);
+	      PXTkButton* b1=new PXTkButton(this->EventManager,fr2,"Extract",607);
+	      //PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Method2",608);
+	      PXTkButton* b3=new PXTkButton(extractGUI,fr2,"Close",3);
+	      frame->addChildren("-side top -expand true -fill x",extractType,thresholdScale->getMainWindow(),
+				 medianScale->getMainWindow(),sigmaScale->getMainWindow(),fr2);
+	      fr2->addChildren("-side left -expand true -fill x",b1/*,b2*/,b3);
+	    }
+	
+	thresholdScale->setRange(image_range[0],image_range[1]);
+	thresholdScale->setValue(Frange(thresholdScale->getValue(),image_range[0],image_range[1]));
+	extractGUI->popupDialog();
+	return 0;
+      }
+
+  if (extractGUI==NULL)
+      {
+	DoExtract(0);
+	extractGUI->popdownDialog();
+      }
+
+
+  int ok=0;
+
+  if (extractType->getIndex()==0)
+      {
+	float threshold=-200000.0;
+
+	ok=landmarkCollection->ExtractImageContour(image,image_plane,image_level,image_frame,
+						   threshold,
+						   (int)medianScale->getValue(),sigmaScale->getValue());
+	if (ok)
+	    thresholdScale->setValue(threshold);
+      }
+  else
+      {
+	float threshold=thresholdScale->getValue();
+	ok=landmarkCollection->ExtractImageContour(image,image_plane,image_level,image_frame,threshold,
+						   (int)medianScale->getValue(),sigmaScale->getValue());
+      }
+
+  if (ok)
+      {
+	if (mouseMode->getIndex()>=3)
+	    mouseMode->setIndex(1);
+	sprintf(pxtk_buffer2,"Extr%1d_%d.%d",image_plane,image_level,current_collection+1);
+	currentCollection->changeLabel(current_collection,pxtk_buffer2);
+	UpdateListFromCurrentCollection();
+      }
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::DoSnake(int apply)
+{
+  if (image==NULL)
+      return 0;
+
+  if (apply==0)
+      {
+	if (snakeGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+	      snakeGUI=new PXTkDialog(this->EventManager,polyFrame,"Snake Controls",PXFalse);
+	      snakeGUI->initDisplay();
+	      PXTkFrame* frame=(PXTkFrame*)snakeGUI->getMainWindow();
+
+	      snakeEdgeWeight=new PXTkArrowScale(snakeGUI,frame,"Edge Weight",-1,PXTrue);
+	      snakeEdgeWeight->setRange(0.0,1.0);
+	      snakeEdgeWeight->setIncrement(0.05);
+	      snakeEdgeWeight->setResolution(0.01);
+	      snakeEdgeWeight->setDecimalPoints(2);
+	      snakeEdgeWeight->setLengthWidth(120,8);
+	      snakeEdgeWeight->setValue(0.5);
+
+	      snakeSmoothWeight=new PXTkArrowScale(snakeGUI,frame,"Smoothness Weight",-1,PXTrue);
+	      snakeSmoothWeight->setRange(0.0,1.0);
+	      snakeSmoothWeight->setIncrement(0.05);
+	      snakeSmoothWeight->setResolution(0.01);
+	      snakeSmoothWeight->setDecimalPoints(2);
+	      snakeSmoothWeight->setLengthWidth(120,8);
+	      snakeSmoothWeight->setValue(0.3);
+
+	      snakeBaloon=new PXTkArrowScale(snakeGUI,frame,"Baloon Weight",-1,PXTrue);
+	      snakeBaloon->setValue(0.0);
+	      snakeBaloon->setResolution(0.01);
+	      snakeBaloon->setDecimalPoints(3);
+	      snakeBaloon->setRange(-0.5,0.5);
+	      snakeBaloon->setIncrement(0.05);
+	      snakeBaloon->setLengthWidth(120,8);
+
+	      snakeSigma=new PXTkArrowScale(snakeGUI,frame,"Sigma",-1,PXTrue);
+	      snakeSigma->setRange(0.0,4.0);
+	      snakeSigma->setIncrement(0.5);
+	      snakeSigma->setResolution(0.1);
+	      snakeSigma->setDecimalPoints(1);
+	      snakeSigma->setLengthWidth(120,8);
+	      snakeSigma->setValue(1.0);
+
+	      snakeIterations=new PXTkArrowScale(snakeGUI,frame,"Iterations",-1,PXTrue);
+	      snakeIterations->setRange(1,300);
+	      snakeIterations->setIncrement(10);
+	      snakeIterations->setResolution(1);
+	      snakeIterations->setDecimalPoints(0);
+	      snakeIterations->setLengthWidth(120,8);
+	      snakeIterations->setValue(50);
+
+	      snakeTolerance=new PXTkArrowScale(snakeGUI,frame,"Tolerance",-1,PXTrue);
+	      snakeTolerance->setResolution(0.001);
+	      snakeTolerance->setDecimalPoints(3);
+	      snakeTolerance->setRange(0.0,0.5);
+	      snakeTolerance->setIncrement(0.025);
+	      snakeTolerance->setLengthWidth(120,8);
+	      snakeTolerance->setValue(0.05);
+
+	      snakeStep=new PXTkArrowScale(snakeGUI,frame,"Step",-1,PXTrue);
+	      snakeStep->setRange(0.0,3.0);
+	      snakeStep->setIncrement(0.5);
+	      snakeStep->setResolution(0.1);
+	      snakeStep->setDecimalPoints(2);
+	      snakeStep->setLengthWidth(120,8);
+	      snakeStep->setValue(1.0);
+
+
+	      PXTkFrame* fr2=new PXTkFrame(snakeGUI,frame);
+	      PXTkButton* b1=new PXTkButton(this->EventManager,fr2,"Snake",611);
+	      PXTkButton* b3=new PXTkButton(snakeGUI,fr2,"Close",3);
+	      frame->addChildren("-side top -expand true -fill x",
+				 snakeEdgeWeight->getMainWindow(),
+				 snakeBaloon->getMainWindow(),
+				 snakeSmoothWeight->getMainWindow(),
+				 snakeSigma->getMainWindow(),
+				 snakeIterations->getMainWindow());
+	      frame->addChildren("-side bottom -expand true -fill x",
+				 fr2,
+				 snakeTolerance->getMainWindow(),
+				 snakeStep->getMainWindow());
+	      fr2->addChildren("-side left -expand true -fill x",b1,b3);
+	    }
+	
+	/*snakeEdgeWeight->setRange(image_range[0],image_range[1]);
+	  snakeEdgeWeight->setValue(Frange(snakeEdgeWeight->getValue(),image_range[0],image_range[1]));*/
+	snakeGUI->popupDialog();
+	return 0;
+      }
+
+
+  if (snakeGUI==NULL)
+      {
+	DoSnake(0);
+	snakeGUI->popdownDialog();
+      }
+
+  if (apply==1)
+      {
+	float res=snakeTolerance->getValue();
+	float w_img=snakeEdgeWeight->getValue();
+	float w_bal=snakeBaloon->getValue();
+	float w_smo=snakeSmoothWeight->getValue();
+	float sigma=snakeSigma->getValue();
+	float stp=snakeStep->getValue();
+	int   iter=(int)snakeIterations->getValue();
+
+	int plane,level;
+	landmarkCollection->GetCurrentInternalPlaneAndLevel(plane,level);//Irange(image_plane,0,2);
+
+
+	vtkImageData* en_out=landmarkCollection->UpdateSnake(image,NULL,
+								    plane,level,image_frame,
+								    res,w_img,w_bal,w_smo,
+								    sigma,stp,iter);
+	en_out->Delete();
+	
+	if (mouseMode->getIndex()>=3)
+	    mouseMode->setIndex(1);
+	UpdateListFromCurrentCollection();
+      }
+
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl_thresholdStats(vtkImageData* img,int plane,int level,int frame,float threshold,int& numin,int& total)
+{
+  vtkpxImageExtract* extr=vtkpxImageExtract::New();
+  extr->SetInput(img);
+  extr->SetCurrentPlane(plane);
+  extr->SetSliceNo(level);
+  extr->SetFrame(frame);
+  extr->Update();
+
+  vtkImageData* image=extr->GetOutput();
+  
+  numin=0,total=0;
+
+  vtkDataArray* scal=image->GetPointData()->GetScalars();
+
+  /*fprintf(stderr,"Image Dimensions %d x %d x%d (%d x %d) plane=%d level=%d\n",dim[0],dim[1],dim[2],
+	  image->getWidth(),image->getHeight(),plane,level);*/
+
+
+  for (int ia=0;ia<scal->GetNumberOfTuples();ia++)
+      {
+	total++;
+	float px=scal->GetComponent(ia,0);
+	if (px>threshold)
+	    numin++;
+      }
+  
+  /*fprintf(stderr,"Pixels with Intensity >%f = %d (total=%d) percentage=%5.2f \n",
+	  threshold,numin,total,100.0*float(numin)/float(total));*/
+
+  extr->Delete();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseCurveControl::DoThreshold(int apply)
+{
+  if (image==NULL)
+    return 0;
+
+  if (apply==0)
+      {
+	if (thresholdGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+	      thresholdGUI=new PXTkDialog(this->EventManager,polyFrame,"Threshold Controls",PXFalse);
+	      thresholdGUI->initDisplay();
+	      PXTkFrame* frame=(PXTkFrame*)thresholdGUI->getMainWindow();
+	      frame->setPackMode(PXFalse);
+	      
+	      PXTkLabel* label=new PXTkLabel(thresholdGUI,frame,"Threshold:");
+	      entryThreshold=new PXTkEntry(thresholdGUI,frame);
+	      entryThreshold->setText("128.0");
+	      
+	      frame->gridRowColumnChild(label,0,0);
+	      frame->gridRowColumnChild(entryThreshold,0,1,1,2);
+
+	      PXTkButton* b1=new PXTkButton(this->EventManager,frame,"Threshold",613);
+	      PXTkButton* b2=new PXTkButton(this->EventManager,frame,"Undo",614);
+	      PXTkButton* b3=new PXTkButton(thresholdGUI,frame,"Close",3);
+	      frame->gridRowColumnChild(b1,1,0);
+	      frame->gridRowColumnChild(b2,1,1);
+	      frame->gridRowColumnChild(b3,1,2);
+	    }
+	
+	float mean,sigma;
+	int plane=Irange(image_plane,0,2);
+	if (image_plane==-1)
+	    plane=2;
+	
+	landmarkCollection->ExtractVOIProperties(image,image_plane,image_level,image_frame,mean,sigma);
+	float val=mean+2.0*sigma;
+	sprintf(pxtk_buffer2,"%6.1f",val);
+	entryThreshold->setText(pxtk_buffer2);
+	thresholdGUI->popupDialog();
+	return 0;
+      }
+
+
+  if (thresholdGUI==NULL)
+      {
+	DoThreshold(0);
+	thresholdGUI->popdownDialog();
+      }
+
+  if (apply==1)
+      {
+	float threshold=atof(entryThreshold->getText());
+	int numin,total;
+	
+	vtkpxGUIBaseCurveControl_thresholdStats(image,image_plane,image_level,image_frame,
+						threshold,numin,total);
+	if (total==0)
+	    total=-1;
+	
+	if (currentColormap!=NULL && backupColormap!=NULL)
+	    {
+	      vtkpxColorMapUtil::CopyLookupTable(currentColormap,backupColormap);
+	      
+	      double range[2];
+	      currentColormap->GetTableRange(range);
+	      int numc=currentColormap->GetNumberOfColors();
+	      
+	      for (int i=0;i<numc;i++)
+		  {
+		    double dat[4];
+		    currentColormap->GetTableValue(i,dat);
+		    float val=(float(i)/float(numc))*(range[1]-range[0])+range[0];
+		    if (val<threshold)
+			dat[3]=0.0;
+		    currentColormap->SetTableValue(i,dat);
+		  }
+
+	      sprintf(pxtk_buffer,"Slice =%d Threshold =%6.2f Pixels = %d/%d %5.2f",
+		      image_level,threshold,numin,total,float(numin)/float(total)*100.0);
+	      PXTkApp::printToConsole(pxtk_buffer);
+	      this->EventManager->messageBox(pxtk_buffer,"Threhold Stats ...");
+	      UpdateListFromCurrentCollection();
+  	    }
+	
+      }
+  
+  if (apply==2)
+      if (currentColormap!=NULL && backupColormap!=NULL)
+	vtkpxColorMapUtil::CopyLookupTable(backupColormap,currentColormap);
+  
+  return 1;
+}
+
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::SetHighlightDisplay(int disp)
+{
+  int flag=1;
+  if (disp==0 || highlightIndex==-1 || displayCollection->getState()==PXFalse)
+    flag=0;
+
+
+  for (int j=0;j<BCC_MAX_RENDERERS;j++)
+    {
+      if (renderer[j]!=NULL)
+	{
+	  if (highlightActor[j]->GetVisibility() != flag )
+	    highlightActor[j]->SetVisibility(flag);
+	}
+    }
+}	  
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseCurveControl::SetHighlight(int numh)
+{
+
+  if (highlightData==NULL || landmarkCollection==NULL)
+    {
+      this->highlightIndex=-1;
+      SetHighlightDisplay(0);
+      return;
+    }
+
+  int np=landmarkCollection->GetNumPoints();
+  
+  if (numh<0 || np<1)
+    {
+      highlightData->SetRadius(0.01);
+      highlightData->Update();
+      SetHighlightDisplay(0);
+      this->highlightIndex=-1;
+      return;
+    }
+
+  numh=Irange(numh,0,np-1);
+
+  double sp[3]; landmarkCollection->GetSpacing(sp);
+  double ori[3]; landmarkCollection->GetOrigin(ori);
+
+  numh=Irange(numh,0,np-1);
+  this->highlightIndex=numh;
+
+  double x[3];
+  landmarkCollection->GetPoints()->GetPoint(numh,x);
+  for (int ia=0;ia<=2;ia++)
+    x[ia]=x[ia]*sp[ia]+ori[ia];
+
+  highlightData->SetCenter(x);
+  highlightData->SetRadius(1.5*landmarkCollection->GetPointScale());
+  highlightData->Update();
+  SetHighlightDisplay(1);
+}
+
+void vtkpxGUIBaseCurveControl::SetTransform(vtkAbstractTransform* newtransform)
+{
+  if (newtransform==NULL)
+    return;
+
+  if (this->transform!=NULL)
+    {
+      if (owns_transform)
+	this->transform->Delete();
+    }
+
+  this->transform=newtransform;
+  owns_transform=PXFalse;
+
+    for (int i=0;i<num_collections;i++)
+    {
+      if (landmarkFilter[i]!=NULL)
+	{
+	  landmarkFilter[i]->SetTransform(this->transform);
+	  landmarkFilter[i]->Update();
+	}
+    }
+
+  if (highlightFilter!=NULL)
+    {
+      highlightFilter->SetTransform(this->transform);
+      highlightFilter->Update();
+    }
+}
+
+void vtkpxGUIBaseCurveControl::SetClipboardCollection(vtkpxBaseCurve* data,int scaled)
+{
+  if (data==NULL)
+    return;
+
+  if (scaled==0)
+    {
+      clipboardCollection->Copy(data);
+      return;
+    }
+
+  clipboardCollection->DeleteAllPoints();
+  for (int i=0;i<data->GetNumPoints();i++)
+    {
+      double x[3];
+      data->GetPoints()->GetPoint(i,x);
+      clipboardCollection->AddPoint(x[0],x[1],x[2],1);
+    }
+}
+
+void vtkpxGUIBaseCurveControl::SetClipboardCollection(vtkPoints* data)
+{
+  if (data==NULL)
+    return;
+
+  clipboardCollection->SetFromPoints(data);
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIBaseCurveControl.h b/bioimagesuite30_src/GUI/vtkpxGUIBaseCurveControl.h
new file mode 100644
index 0000000..45aae44
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIBaseCurveControl.h
@@ -0,0 +1,218 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkpxGUIBaseCurveControl
+// .SECTION Description
+
+#ifndef __vtkpxGUIBaseCurveControl_h
+#define __vtkpxGUIBaseCurveControl_h
+
+#include "vtkpxBaseCurve.h"
+#include "vtkpxGUIBaseCurveEditor.h"
+#include "pxtkapp.h"
+#include "pxtkeventobj.h"
+#include "pxtkgadgets.h"
+#include "pxtkcomplexwidgets.h"
+#include "pxtkdialog.h"
+#include "pxtkmenu.h"
+#include "pxcontour.h"
+
+
+const int BCC_MAX_COLLECTIONS = 40; 
+const int BCC_MAX_RENDERERS   = 16; 
+class vtkActor;
+class vtkPolyData;
+class vtkSphereSource;
+class vtkTransformPolyDataFilter;
+
+class vtkpxGUIBaseCurveControl : public vtkpxGUIBaseCurveEditor 
+{
+public:
+
+  static vtkpxGUIBaseCurveControl *New();
+  vtkTypeMacro(vtkpxGUIBaseCurveControl,vtkpxGUIBaseCurveEditor);
+  
+  // Initialize Display  
+  virtual char*  Initialize(const char* name,int inside);
+
+  virtual void SetRenderer(vtkRenderer *rendererer,int num);
+
+  virtual void Update();
+  virtual void UpdateDisplay();
+  virtual int  HandleEvent(int);
+  
+  virtual void UpdateStatus();
+  virtual int  HandleClickedPoint(float x,float y,float z,int scaled=1,int state=0);
+  virtual void SetSpacingOrigin(double sp[3],double ori[3]);
+
+
+  virtual int  GetNumberOfCollections(); 
+  virtual vtkpxBaseCurve* GetCollection(int index=-1);
+  virtual vtkObject* GetItem(int index) { return GetCollection(index);}
+  virtual int  GetCurrentIndex();
+
+  virtual void SetCollection(vtkpxBaseCurve* land,int index=-1);
+  virtual void SetCollection(PXContour* cntr,int index=-1,int plane=2,int level=0);
+  virtual void SetClipboardCollection(vtkpxBaseCurve* data,int scaled=1);
+  virtual void SetClipboardCollection(vtkPoints* data);
+
+  virtual void DisableLabels();
+  virtual void DisableList();
+  virtual void DisableCurve();
+  virtual void DisableComplex();
+
+  virtual void SetImage(vtkImageData* image,int plane=0,int level=-1,int frame=0);
+  virtual void SetPlaneLevel(int plane,int level);
+  virtual void SetFrame(int frame);
+  virtual void SetLookupTable(vtkLookupTable* lookuptable);
+  virtual void SetTransform(vtkAbstractTransform* transform);
+  virtual vtkAbstractTransform* GetTransform() { return this->transform;}
+
+  virtual int  DoExtract(int apply);
+  virtual int  DoSnake(int apply);
+  virtual int  DoThreshold(int apply);
+
+  virtual void SetHighlight(int num=-1);
+
+  virtual int  SetTalarachSetup();
+  virtual int  SetTransformSetup();
+  virtual int  SetArticulatedMouseSetup(int hasfeet=1,int hashindlimbs=1,int hasforelimbs=0,int hashead=0,
+					int taildivisions=0,int splinedivisions=0);
+  virtual void SaveTransform(const char* fname);
+  virtual int  SetBrainstripSetup();
+
+  // Description:
+  // Outside Interface
+  virtual void SetCurrentCollection(int num);
+  virtual void LoadLandmarks(const char* fname);
+
+protected:
+
+  vtkpxGUIBaseCurveControl();
+  virtual ~vtkpxGUIBaseCurveControl();
+
+  vtkpxBaseCurve *landmarkCollection;
+  vtkpxBaseCurve *allCollections[BCC_MAX_COLLECTIONS];
+  PXBool         showCollection[BCC_MAX_COLLECTIONS];
+  static vtkpxBaseCurve *clipboardCollection;
+
+  vtkRenderer*       renderer[BCC_MAX_RENDERERS];
+  vtkActor*          landmarkActor[BCC_MAX_RENDERERS][BCC_MAX_COLLECTIONS];
+  vtkActor*          highlightActor[BCC_MAX_RENDERERS];
+  vtkSphereSource*   highlightData;
+  vtkTransformPolyDataFilter* highlightFilter;
+  vtkTransformPolyDataFilter* landmarkFilter[BCC_MAX_COLLECTIONS];
+  int                highlightIndex;
+
+  PXTkDialog*     edit_window;
+  PXTkDialog*     label_window;
+  PXTkDialog*     extractGUI;
+  PXTkDialog*     snakeGUI;
+  PXTkDialog*     thresholdGUI;
+  PXTkOptionMenu* extractType;
+
+  PXTkArrowScale* thresholdScale;
+  PXTkArrowScale* medianScale;
+  PXTkArrowScale* sigmaScale;
+  PXTkArrowScale* snakeEdgeWeight;
+  PXTkArrowScale* snakeSmoothWeight;
+  PXTkArrowScale* snakeTolerance;
+  PXTkArrowScale* snakeStep;
+  PXTkArrowScale* snakeSigma;
+  PXTkArrowScale* snakeIterations;
+  PXTkArrowScale* snakeBaloon;
+  PXTkEntry*      entryThreshold;
+
+  PXBool          has_landmark_collection;
+  PXBool          enable_labels;
+  PXBool          enable_list;
+  PXBool          enable_curve;
+  PXBool          enable_complex;
+  int             current_collection;
+  int             num_collections;
+  PXBool          click_mode;
+  PXBool          owns_transform;
+
+  PXTkListBox*     listBox;
+  PXTkListBox*     labelListBox;
+  PXTkLabel*       message;
+  PXTkLabel*       currentLabel;
+  PXTkEntry        *coord[3];
+  PXTkEntry        *label_entry;
+  PXTkOptionMenu*  curveMode;
+  PXTkOptionMenu*  mouseMode;
+  PXTkOptionMenu   *currentCollection;
+  //PXTkOptionMenu   *displayMode;
+  PXTkCheckButton    *displayCollection;
+  PXTkOptionMenu   *scaleMode;
+  //*clickMode,*addMode,*autoMode
+  int             callback_no;
+  int             edit_item;
+
+  char            clipboard[100];
+  static char     lamstring[400];
+
+  vtkLookupTable*      backupColormap;
+  vtkLookupTable       *currentColormap;
+  vtkImageData*         image;
+  vtkAbstractTransform* transform;
+
+  int             image_plane;
+  int             image_level;
+  int             image_frame;
+  double          image_range[2];
+
+  virtual void ClipboardCommand(int mode);
+  virtual void AddListLandmark(float x,float y,float z,int index=-1,int scaled=0,int listonly=0);
+  virtual void ExtractCoordinates(const char* line,float& x,float& y,float& z);
+
+  virtual void SaveSeedFile(const char* fname);
+  virtual void LoadSeedFile(const char* fname);
+
+  virtual void UpdateListFromCurrentCollection();
+
+  virtual void CreateEditWindow(int callbackno);
+  virtual int  UpdateEditWindow();
+  virtual int  HandleEditWindowCallback();
+
+  virtual int  LoadSetupFile(const char* fname);
+  virtual int  SaveSetupFile(const char* fname);
+  virtual void CreateLabelWindow();
+  virtual int  HandleLabelWindowCallback(int option);
+  
+  virtual void SetHighlightDisplay(int disp=1);
+};
+
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIBaseCurveEditor.cpp b/bioimagesuite30_src/GUI/vtkpxGUIBaseCurveEditor.cpp
new file mode 100644
index 0000000..121e23d
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIBaseCurveEditor.cpp
@@ -0,0 +1,47 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkpxGUIBaseCurveEditor - Base Image Viewer
+// .SECTION Description
+
+#include "vtkpxGUIBaseCurveEditor.h"
+/*#include "vtkRenderer.h"
+#include "vtkLookupTable.h"
+#include "vtkImageData.h"*/
+
+
+// Construct object with no children.
+
+void vtkpxGUIBaseCurveEditor::SetRenderer(vtkRenderer *ren) {
+  this->SetRenderer(ren,0);
+}
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIBaseCurveEditor.h b/bioimagesuite30_src/GUI/vtkpxGUIBaseCurveEditor.h
new file mode 100644
index 0000000..5db6a51
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIBaseCurveEditor.h
@@ -0,0 +1,122 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIBaseCurveEditor.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIBaseCurveEditor - Base class for curve/point editors
+// .SECTION Description
+// This is an abstract base class for curve/point editors
+// Facilities for handling clicked points, maintaining a list of objects, setting
+// Image,LookupTable and CurrentTransform
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkpxGUIBaseCurveControl
+
+
+#ifndef __vtkpxGUIBaseCurveEditor_h
+#define __vtkpxGUIBaseCurveEditor_h
+
+#include "vtkpxGUIComponent.h"
+
+class vtkRenderer;
+class vtkLookupTable;
+class vtkImageData;
+class vtkAbstractTransform;
+
+class vtkpxGUIBaseCurveEditor : public vtkpxGUIComponent 
+{
+public:
+
+  vtkTypeMacro(vtkpxGUIBaseCurveEditor,vtkpxGUIComponent);
+
+  // Description:
+  // Set Renderer for Display purposes 
+  virtual void SetRenderer(vtkRenderer *ren);
+  virtual void SetRenderer(vtkRenderer *rendererer,int num)=0;
+
+  // Description:
+  // Generic Event Handlers
+  virtual void Update()=0;
+  virtual void UpdateDisplay()=0;
+  virtual int  HandleEvent(int)=0;
+  virtual int  HandleClickedPoint(float x,float y,float z,int scaled=1,int state=0)=0;
+
+  // Description:
+  // Access Internal Storage i-vtkObjets
+  virtual int         GetCurrentIndex()=0;
+  virtual vtkObject*  GetItem(int i)=0;
+  virtual void SetItemColor(int index,double color[3]) {};
+  virtual void SetItemFilename(int index,const char* s) {};
+
+  // Description:
+  // Image Related Stuff 
+  virtual void SetSpacingOrigin(double sp[3],double ori[3])=0;
+  virtual void SetPlaneLevel(int plane,int level)=0;
+  virtual void SetFrame(int frame)=0;
+  virtual void SetImage(vtkImageData* image,int plane=0,int level=-1,int frame=0)=0;
+
+  // Description:
+  // Lookup Table
+  virtual void SetLookupTable(vtkLookupTable* lookuptable)=0;
+
+  // Description:
+  // Current Transform 
+  virtual void SetTransform(vtkAbstractTransform* transform)=0;
+  virtual vtkAbstractTransform* GetTransform()=0;
+
+
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIBaseImageViewer.cpp b/bioimagesuite30_src/GUI/vtkpxGUIBaseImageViewer.cpp
new file mode 100644
index 0000000..de3dd14
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIBaseImageViewer.cpp
@@ -0,0 +1,1015 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxGUIBaseImageViewer.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxUtil.h"
+#include "vtkImageData.h"
+#include <vtkVRMLExporter.h>
+#include <vtkTIFFWriter.h> 
+#include <vtkPNGWriter.h> 
+#include <vtkJPEGWriter.h> 
+#include "vtkWindowToImageFilter.h"
+#include "vtkpxTalairachTransform.h"
+#include "vtkpxBaseCurve.h"
+#include "vtkLookupTable.h"
+#include "vtkpxColorMapUtil.h"
+#include "vtkpxImageComponentsToFrames.h"
+#include "vtkImageConstantPad.h"
+#include "vtkPolyData.h"
+#include "vtkRenderer.h"
+#include "vtkScalarBarActor.h"
+#include "pxtkapp.h"
+#include <vtkstd/string>
+#include "vtkRendererCollection.h"
+#include "vtkRenderer.h"
+#include "vtkbisImageHeader.h"
+#include "vtkstd/string"
+#include "sstream"
+
+// Construct object with no children.
+vtkpxGUIBaseImageViewer::vtkpxGUIBaseImageViewer()
+{
+  this->hasImage=PXFalse;
+  this->currentImage=NULL;
+  this->valueImage=NULL;
+
+  this->LastClickedPoint[0]=0.0;
+  this->LastClickedPoint[1]=0.0;
+  this->LastClickedPoint[2]=0.0;
+
+  this->LastClickedPointScaled[0]=0.0;
+  this->LastClickedPointScaled[1]=0.0;
+  this->LastClickedPointScaled[2]=0.0;
+
+  this->Orientation=0;
+  this->NumberOfFrames=1;
+  this->ColorMode=1;
+  this->CurrentImageIsColor=0;
+
+  this->CurrentFrame=0;
+
+  this->talairachTransform=vtkpxTalairachTransform::New();
+  this->mainLookupTable=vtkLookupTable::New();
+  vtkpxColorMapUtil::SetStepColorMap(mainLookupTable,0,255,0,255,256,PXFalse);
+
+  this->PresetLookupTableMode=-1;
+
+  this->frameChangeCallbackName=NULL;
+  this->EnableFrameChangeCallback=1;
+  this->KeyRenderer=vtkRenderer::New();
+  this->ScalarBar=vtkScalarBarActor::New();
+  this->ScalarBar->VisibilityOff();
+  this->KeyRenderer->AddActor2D(this->ScalarBar);
+
+
+  this->ShowKeyRenderer=0;
+  this->MagnificationFactor=1;
+
+  this->coordinatesChangeCallbackName=NULL;
+  this->EnableCoordinatesChangeCallback=1;
+
+  this->EnableRendering=1;
+  this->ColormapEditor=NULL;
+  this->ownsLookupTable=1;
+  this->createTalairachButtons=PXFalse;
+
+  this->IntensityScale=1.0;
+  this->IntensityOffset=0.0;
+
+}
+
+vtkpxGUIBaseImageViewer::~vtkpxGUIBaseImageViewer()
+{
+  if (this->currentImage)
+      currentImage->Delete();
+
+  if (this->talairachTransform)
+    this->talairachTransform->Delete();
+
+  if (mainLookupTable!=NULL &&  this->ownsLookupTable>0)
+    mainLookupTable->Delete();
+  
+  if (this->frameChangeCallbackName!=NULL)
+    delete [] this->frameChangeCallbackName;
+
+  if (this->coordinatesChangeCallbackName!=NULL)
+    delete [] this->coordinatesChangeCallbackName;
+
+
+  if (this->ColormapEditor!=NULL)
+    this->ColormapEditor->Delete();
+
+  if (this->KeyRenderer!=NULL)
+    this->KeyRenderer->Delete();
+
+  if (this->valueImage!=NULL)
+    this->valueImage->Delete();
+}
+/* -------------------------------------------------------------------------*/
+char* vtkpxGUIBaseImageViewer::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+
+  vtkpxGUIComponent::Initialize(name,inside);
+
+  return GetWidgetName();
+
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUIBaseImageViewer::SetColorMode(int cm)
+{
+  if (this->Initialized==0)
+    {
+      if (cm>0)
+	this->ColorMode=1;
+      else
+	this->ColorMode=0;
+    }
+}
+
+int vtkpxGUIBaseImageViewer::GetCurrentFrame()
+{
+  return this->CurrentFrame;
+}
+
+void vtkpxGUIBaseImageViewer::SetCurrentFrame(int t)
+{
+  if (!this->CurrentImageIsColor)
+    this->CurrentFrame=t;
+}
+
+void vtkpxGUIBaseImageViewer::SetFrameChangeCallback(const char* name)
+{
+  if (name==NULL)
+    return;
+
+  if (this->frameChangeCallbackName!=NULL)
+    delete [] this->frameChangeCallbackName;
+
+  this->frameChangeCallbackName=new char[strlen(name)+1];
+  strcpy(this->frameChangeCallbackName,name);
+}
+
+void  vtkpxGUIBaseImageViewer::ExecuteFrameChangeCallback()
+{
+  if (this->EnableFrameChangeCallback==0 || this->frameChangeCallbackName==NULL)
+    return;
+
+  PXTkApp::executeTclCommand(this->frameChangeCallbackName);
+
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIBaseImageViewer::SetCoordinatesChangeCallback(const char* name)
+{
+  if (name==NULL)
+    return;
+
+  if (this->coordinatesChangeCallbackName!=NULL)
+    delete [] this->coordinatesChangeCallbackName;
+
+  this->coordinatesChangeCallbackName=new char[strlen(name)+1];
+  strcpy(this->coordinatesChangeCallbackName,name);
+  //  fprintf(stderr,"New Coordinate change = %s\n",this->coordinatesChangeCallbackName);
+}
+
+void  vtkpxGUIBaseImageViewer::ExecuteCoordinatesChangeCallback()
+{
+  if (this->EnableCoordinatesChangeCallback==0 || this->coordinatesChangeCallbackName==NULL)
+    return;
+
+  PXTkApp::executeTclCommand(this->coordinatesChangeCallbackName);
+
+}
+
+void vtkpxGUIBaseImageViewer::ToggleKeyRenderer()
+{
+  this->SetShowKeyRenderer(this->ShowKeyRenderer<1);
+  this->UpdateKeyRenderer();
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUIBaseImageViewer::SetImage(vtkImageData* image,int orient,vtkLookupTable* cmap,double offset,double scale)
+{
+  if (image==NULL)
+    return 0;
+  
+  this->Orientation=orient;
+
+  if (this->currentImage==NULL)
+    currentImage=vtkImageData::New();  
+  
+  int dim[3]; image->GetDimensions(dim);
+
+  this->CurrentImageIsColor=0;
+  if (this->ColorMode==0 || orient==3)
+    {
+      this->NumberOfFrames=image->GetNumberOfScalarComponents();
+    }
+  else  
+    {
+      int nc=image->GetNumberOfScalarComponents();
+      if (nc==3 && image->GetScalarType()==VTK_UNSIGNED_CHAR)
+	{
+	  this->NumberOfFrames=1;
+	  this->CurrentImageIsColor=1;
+	}
+      else
+	this->NumberOfFrames=image->GetNumberOfScalarComponents();		  
+    }
+    
+  //  fprintf(stderr,"Orientation=%d, colormode=%d iscolor=%d\n",this->Orientation,this->ColorMode,this->CurrentImageIsColor);
+  
+  currentImage->ShallowCopy(image);
+  this->IntensityScale=scale;
+  this->IntensityOffset=offset;
+
+  if (this->valueImage!=NULL)
+    this->valueImage->Delete();
+  this->valueImage=NULL;
+  
+  if (this->CurrentFrame>=this->NumberOfFrames)
+    this->CurrentFrame=0;
+  
+  if (hasImage==PXFalse)
+    {
+      hasImage=PXTrue;
+      InitializeViewer();
+    }
+
+  ResetViewer();
+
+  if (cmap==NULL)
+    this->ResetColormap();
+  else
+    this->SetLookupTable(cmap);
+
+
+  this->ResetEditor();
+  this->UpdateIntensityLabelInfo();
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+vtkImageData* vtkpxGUIBaseImageViewer::GetImage()
+{
+  return currentImage;
+}
+
+vtkImageData* vtkpxGUIBaseImageViewer::GetValueImage()
+{
+  return this->valueImage;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIBaseImageViewer::DoImagesHaveSameDimensions(vtkImageData* img1,vtkImageData* img2,int checknumframes)
+{
+  if (img1==NULL || img2==NULL)
+    return 0;
+
+  int ndim[3]; img1->GetDimensions(ndim);
+  int odim[3]; img2->GetDimensions(odim);
+  int nnc=img1->GetNumberOfScalarComponents();
+  int onc=img2->GetNumberOfScalarComponents();
+
+  int sum=0;
+  for (int i=0;i<=2;i++)
+    sum+=abs(ndim[i]-odim[i]);
+  if (checknumframes)
+    sum+=abs(nnc-onc);
+
+  if (sum>0)
+    return 0;
+
+  double nsp[3]; img1->GetSpacing(nsp);
+  double osp[3]; img2->GetSpacing(osp);
+
+
+  double fsum=0;
+  for (int i=0;i<=2;i++)
+    fsum+=fabs(nsp[i]-osp[i]);
+
+  if (fsum>0.001)
+    return 0;
+  
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIBaseImageViewer::SetValueImage(vtkImageData* val)
+{
+  if (this->valueImage!=NULL)
+    this->valueImage->Delete();
+  this->valueImage=NULL;
+
+  if (val==NULL || this->currentImage==NULL)
+    return 0;
+
+  if (this->DoImagesHaveSameDimensions(val,this->currentImage,1)==0)
+    return 0;
+
+  this->valueImage=vtkImageData::New();
+  this->valueImage->ShallowCopy(val);
+  this->UpdateIntensityLabelInfo();
+  return 1;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIBaseImageViewer::SaveAsTiff(vtkRenderWindow* renwin)
+{
+  this->SaveAsTiff(renwin,NULL);
+}
+
+void vtkpxGUIBaseImageViewer::SaveAsTiff(vtkRenderWindow* renwin,const char *fname)
+{
+  if (this->Initialized==0)
+    return;
+
+  if (fname==NULL)
+    {
+      int* size=renwin->GetSize();
+      sprintf(pxtk_buffer,"Save Window %dx%d",size[0],size[1]);
+      fname=this->EventManager->getSaveFilenameComplex(pxtk_buffer,"screen.png",
+						       "{\"PNG Files\" {\"*.png\"}} {\"JPEG Files\" {\"*.jpg\"}} {\"TIFF File\" {\".tif\"}}");
+    }
+  if (strlen(fname)<1)
+    return;
+
+  char line[400];
+  strncpy(line,fname,400);
+  renwin->Render();
+  PXTkApp::executeTclCommand("update idletasks");
+
+  vtkWindowToImageFilter* renSrc=vtkWindowToImageFilter::New();
+  renSrc->SetInput(renwin);
+  renSrc->SetMagnification(this->MagnificationFactor);
+  renSrc->Update();
+
+  vtkImageWriter* writer=NULL;
+
+  if (strcmp(PXTkApp::getFilenameExtension(line),".jpg")==0 ||
+      (strcmp(PXTkApp::getFilenameExtension(line),".jpeg")==0) )
+    {
+      writer=vtkJPEGWriter::New();
+    }
+  else if (strcmp(PXTkApp::getFilenameExtension(line),".png")==0 )
+    {
+      writer=vtkPNGWriter::New();
+    }
+  else
+    {
+      writer=vtkTIFFWriter::New();
+    }
+
+  
+  writer->SetInput(renSrc->GetOutput());
+
+  writer->SetFileName(line);
+  writer->Write();
+  writer->Delete();
+  renSrc->Delete();
+
+  return;
+
+}
+/* -------------------------------------------------------------------------*/
+//  Save All as Tiff
+/* -------------------------------------------------------------------------*/
+
+void vtkpxGUIBaseImageViewer::SaveAllAsTiff(vtkRenderWindow* renwin)
+{
+  this->SaveAllAsTiff(renwin,NULL);
+}
+void vtkpxGUIBaseImageViewer::SaveAllAsTiff(vtkRenderWindow* renwin,const char *fname)
+{
+  if (this->Initialized==0)
+    return;
+
+  int* size=renwin->GetSize();
+  sprintf(pxtk_buffer,"Save Window (All Frames) %dx%d",size[0],size[1]);
+  
+  if (fname==NULL)
+    fname=this->EventManager->getSaveFilenameComplex(pxtk_buffer,"screen.jpg",
+						     "{\"JPEG Files\" {\"*.jp*g\"}} {\"TIFF File\" {\"*.tif*\"}}");
+  if (strlen(fname)<1)
+    return;
+
+  strncpy(pxtk_buffer,fname,400);
+  PXTkApp::executeTclCommand("update idletasks");
+  
+  strncpy(pxtk_buffer2,PXTkApp::getFilenameRoot(pxtk_buffer),400);
+
+  int jpeg_mode=0;
+
+  char extension[5];
+  strncpy(extension,PXTkApp::getFilenameExtension(pxtk_buffer),5);
+  if (strlen(extension)<2)
+    strcpy(extension,".jpg");
+  
+  int oldframe=this->GetCurrentFrame();
+
+  vtkWindowToImageFilter* renSrc=vtkWindowToImageFilter::New();
+  renSrc->SetInput(renwin);
+
+  
+  vtkImageWriter* writer=NULL;
+  if (strcmp(extension,".jpg")==0 ||
+      (strcmp(extension,".jpeg")==0) )
+    {
+      writer=vtkJPEGWriter::New();
+      jpeg_mode=1;
+    }
+  else
+    writer=vtkTIFFWriter::New();
+
+  
+  for (int frame=0;frame<this->NumberOfFrames;frame++)
+    {
+      sprintf(pxtk_buffer3,"%s.%03d%s",pxtk_buffer2,frame+1,extension);
+      sprintf(pxtk_buffer4,"Saving Output in %s\n",pxtk_buffer3);
+      PXTkApp::printToConsole(pxtk_buffer4);
+      this->SetCurrentFrame(frame);
+
+      renwin->Render();
+      PXTkApp::executeTclCommand("update idletasks");
+
+
+      renSrc->Modified();
+      renSrc->SetMagnification(this->MagnificationFactor);
+      renSrc->Update();
+      int dim[3];
+      renSrc->GetOutput()->GetDimensions(dim);
+
+      writer->SetInput(renSrc->GetOutput());
+      writer->SetFileName(pxtk_buffer3);
+      writer->Write();
+    }
+
+  writer->Delete();
+  renSrc->Delete();
+  this->SetCurrentFrame(oldframe);
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseImageViewer::ExportAsVRML(vtkRenderWindow* renwin)
+{
+  if (this->Initialized==0)
+    return;
+
+  char *line=this->EventManager->getSaveFilenameComplex("Export Window to VRML","screen.wrl","{\"VRML Files\" {\".wrl\"}} ");
+  if (line==NULL)
+    return;
+  if (strlen(line)<1)
+    return;
+    
+  renwin->Render();
+  vtkVRMLExporter* exp=vtkVRMLExporter::New();
+  exp->SetRenderWindow(renwin);
+  exp->SetFileName(line);
+  exp->Update();
+  exp->Delete();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseImageViewer::SetTalairachPoints(vtkPoints* pt)
+{
+  if (pt==NULL)
+    return;
+
+  if (this->talairachTransform==NULL)
+    this->talairachTransform=vtkpxTalairachTransform::New();
+
+  this->talairachTransform->SetLandmarks(pt);
+  this->talairachTransform->Update();
+  this->UpdateTalairachGrid(1);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseImageViewer::LinkLookupTable(vtkLookupTable* lkp)
+{
+  if (lkp==NULL)
+    return;
+
+  if (hasImage)
+    return;
+  
+  if (mainLookupTable!=NULL &&  this->ownsLookupTable>0)
+    mainLookupTable->Delete();
+
+  mainLookupTable=lkp;
+  this->ownsLookupTable=0;
+  //  fprintf(stderr,"Lookup Tables Linked\n");
+}
+
+void vtkpxGUIBaseImageViewer::SetLookupTable(vtkLookupTable* lkp)
+{
+  if (!this->Initialized || !hasImage || lkp==NULL)
+      return;
+
+  if (this->ownsLookupTable==0 || this->mainLookupTable==NULL)
+    this->mainLookupTable=vtkLookupTable::New();
+  this->ownsLookupTable=1;
+
+  this->mainLookupTable->DeepCopy(lkp);
+
+  if (this->ColormapEditor!=NULL)
+    {
+      this->ColormapEditor->SetColormap(this->mainLookupTable);
+      this->ColormapEditor->Update();
+    }
+
+
+
+}
+
+/* -------------------------------------------------------------------------*/ 
+
+int vtkpxGUIBaseImageViewer::ResetColormap()
+{
+  if (this->ownsLookupTable==0 || this->ColormapEditor==NULL)
+    {
+      return 0;
+    }
+ 
+  this->ColormapEditor->SetLock(0);
+  this->ColormapEditor->SetColormap(this->mainLookupTable);
+  this->ColormapEditor->SetRange(currentImage);
+  this->SetPresetLookupTable(this->PresetLookupTableMode);
+  this->ColormapEditor->Update();
+
+      
+  return 1;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIBaseImageViewer::SetFmriMergeLookupTable()
+{
+  if (!this->Initialized || !hasImage)
+      return;
+
+  vtkpxColorMapUtil::SetFmriMergeColormap(this->mainLookupTable,0);
+}
+
+void vtkpxGUIBaseImageViewer::SetFmriMergeLookupTable(int mode)
+{
+  if (!this->Initialized || !hasImage)
+      return;
+
+  vtkpxColorMapUtil::SetFmriMergeColormap(this->mainLookupTable,mode);
+}
+
+void vtkpxGUIBaseImageViewer::SetPresetLookupTable(int mode)
+{
+  if (!hasImage)
+    return;
+
+  //  fprintf(stderr,"Going to Preset Lookup Table\n");
+
+  this->SetPresetLookupTableMode(mode);
+  if (this->ColormapEditor!=NULL)
+    this->ColormapEditor->SetFmriMode(this->PresetLookupTableMode);
+
+  //  fprintf(stderr,"Done with Preset Lookup Table\n");
+
+  return;
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIBaseImageViewer::LoadTalairachLandmarks(const char* fname)
+{
+  int dodialog=1;
+  if (fname!=NULL)
+    {
+      if (strlen(fname)>0)
+	{
+	  strcpy(pxtk_buffer,fname);
+	  dodialog=0;
+	}
+    }
+
+  if (dodialog>0)
+    {
+      char* line=this->EventManager->getOpenFilename("Load Talairach Landmarks","Landmarks","*.land");
+      if (line==NULL)
+	return;
+      if (strlen(line)<1)
+	return;
+      strcpy(pxtk_buffer,line);
+    }
+
+  vtkpxBaseCurve* land=vtkpxBaseCurve::New();
+  int ok=land->Load(pxtk_buffer);
+
+  if (ok==0)
+    {
+      land->Delete();
+      vtkErrorMacro(<<"Failed to Load Landmarks (Talairach) from "<<pxtk_buffer);
+      return;
+    }
+
+  land->Compact();
+  this->SetTalairachPoints(land->GetPoints());
+  land->Delete();
+  return;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseImageViewer::LoadTalairachTransform(const char* fname)
+{
+  int dodialog=1;
+
+  if (fname!=NULL)
+    {
+      if (strlen(fname)>0)
+	{
+	  strcpy(pxtk_buffer,fname);
+	  dodialog=0;
+	}
+    }
+
+  if (dodialog==1)
+    {
+      char* line=this->EventManager->getOpenFilename("Load Talairach Transform","T-Transform","*.tal");
+      if (line==NULL)
+	return 0;
+      if (strlen(line)<1)
+	return 0;
+      strcpy(pxtk_buffer,line);
+    }
+
+  if (this->talairachTransform==NULL)
+    this->talairachTransform=vtkpxTalairachTransform::New();
+  int ok=this->talairachTransform->Load(pxtk_buffer);
+  if (ok==0)
+    {
+      vtkErrorMacro(<<"Failed to Load Talairach Transform from "<<pxtk_buffer);
+      return 0;
+    }
+  
+  this->UpdateTalairachGrid(1);
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIBaseImageViewer::SaveTalairachTransform(const char* fname)
+{
+
+  if (this->talairachTransform==NULL)
+    {
+      vtkErrorMacro(<<"No Talairach Transform to Save!");
+      return 0;
+    }
+
+  int dodialog=1;
+  if (fname!=NULL)
+    {
+      if (strlen(fname)>1)
+	{
+	  strcpy(pxtk_buffer,fname);
+	  dodialog=0;
+	}
+    }
+
+  if (dodialog>0)
+    {
+      char* line=this->EventManager->getSaveFilename("Save Talairach Transform","transform.tal","T-Transform","*.tal");
+      if (line==NULL)
+	return 0;
+      if (strlen(line)<1)
+	return 0;
+      strcpy(pxtk_buffer,line);
+    }
+
+
+  int ok=this->talairachTransform->Save(pxtk_buffer);
+  if (ok==0)
+    {
+      vtkErrorMacro(<<"Failed to Save Talairach Transform from "<<pxtk_buffer);
+      return 0;
+    }
+
+  return 1;
+}
+
+void vtkpxGUIBaseImageViewer::ShowFrameControls(int show)
+{
+  vtkDebugMacro(<<"Function has not been defined\n");
+}
+
+void vtkpxGUIBaseImageViewer::UpdateTalairachGrid(int )
+{
+  return;
+}
+
+void vtkpxGUIBaseImageViewer::RenderDelay(int t)
+{
+  Tcl_CreateTimerHandler(t,vtkpxGUIBaseImageViewer::handleRenderEvent,this);
+}
+
+void vtkpxGUIBaseImageViewer::handleRenderEvent(void *arg1)
+{
+  //fprintf(stderr,"On to delayed expose\n");
+  ((vtkpxGUIBaseImageViewer*)arg1)->UpdateDisplay();
+}
+
+// ----------------------------------------------------------------------------------------------------------------------
+
+const  char* vtkpxGUIBaseImageViewer::GetFormatedNumber(double vl,int dp)
+{
+  std::stringstream s;
+  
+  if (vl<10.0)
+    s.precision(dp);
+  s << vl;
+  this->Buffer=s.str();
+  return this->Buffer.c_str();
+}
+
+// ----------------------------------------------------------------------------------------------------------------------
+
+int vtkpxGUIBaseImageViewer::DisplayNeuroCoordinates(double pos[3],int coord[3],PXTkLabel* talairachlabel,PXTkLabel* mnilabel,vtkImageData* img)
+{
+  vtkImageData* usethisimage=img;
+  int usingvalueimage=1;
+  if (img==NULL)
+    {
+      if (this->valueImage!=NULL)
+	{
+	  usethisimage=this->valueImage;
+	}
+      else
+	{
+	  usethisimage=this->currentImage;
+	  usingvalueimage=0;
+	}
+    }
+
+  if (this->talairachTransform==NULL || usethisimage==NULL)
+    return 0;
+
+  int ok=0;
+
+  int oldstyleorient=vtkpxGUIBaseImageViewer::MapOrientationToOldStyle(this->Orientation);
+
+  if (oldstyleorient==1 || oldstyleorient==2)
+    {
+      double p1[3];
+      for (int ia=0;ia<=2;ia++) p1[ia]=pos[ia];
+      ok=this->talairachTransform->ReorientCoordinates(usethisimage,oldstyleorient,p1,pos);
+    }
+
+  std::string objlabel=this->GetObjectmapValueAsText(coord[0],coord[1],coord[2]);
+  
+  if (oldstyleorient==0 || ok == 1)
+    {
+      double p[3];
+      this->talairachTransform->TransformPoint(pos,p);
+
+      
+      double vl[3];
+      if (!this->CurrentImageIsColor)
+	{
+	  vl[0]=usethisimage->GetScalarComponentAsDouble(coord[0],coord[1],coord[2],this->CurrentFrame);
+	  if (usingvalueimage==0)
+	    vl[0]=vl[0]*this->IntensityScale+IntensityOffset;
+	}
+      else 
+	{
+	  for (int ia=0;ia<=2;ia++)
+	    vl[ia]=this->currentImage->GetScalarComponentAsDouble(coord[0],coord[1],coord[2],ia);
+	}
+     
+      double mni[3];
+      int domni=this->talairachTransform->GetMNICoordinates(pos,mni);
+      
+      char name[100];
+      char name2[100];
+      strcpy(name,"Custom TC");
+      strcpy(name2,"");
+      
+      int md=this->talairachTransform->GetColinMode();
+      int dostandard=this->talairachTransform->GetStandardMode();
+      int sz=this->talairachTransform->GetColinYSize();
+      
+      if (md==1 || md==-1)
+	{
+	  if (sz==216)
+	    strcpy(name,"C");
+	  else
+	    strcpy(name,"YC");
+	  
+	  if (md==1)
+	    strcpy(name2,"_AP TC=");
+	  else
+	    strcpy(name2,"_PA TC=");
+	  if (talairachlabel!=NULL)
+	    talairachlabel->configure("-fg","red");
+	}
+      
+      if (dostandard==1)
+	{
+	  mnilabel->setText("");
+	  talairachlabel->configure("-fg","white");
+	  if (!this->CurrentImageIsColor)
+	    sprintf(pxtk_buffer,"(%d %d %d) %s %s",coord[0],coord[1],coord[2],this->GetFormatedNumber(vl[0],3),objlabel.c_str());
+	  else
+	    sprintf(pxtk_buffer,"(%d %d %d) (%.0f,%.0f,%.0f) %s",coord[0],coord[1],coord[2],
+		    vl[0],vl[1],vl[2],objlabel.c_str());
+	  talairachlabel->setText(pxtk_buffer);
+	}
+      else if (domni==1)
+	{
+	  sprintf(pxtk_buffer,"MNI=(%.0f,%.0f,%.0f)",mni[0],mni[1],mni[2]);
+	  mnilabel->setText(pxtk_buffer);
+	  if (!this->CurrentImageIsColor)
+	    sprintf(pxtk_buffer,"%s%s(%.0f %.0f %.0f) %s %s",name,name2,p[0],p[1],p[2],this->GetFormatedNumber(vl[0],3),objlabel.c_str());
+	  else
+	    sprintf(pxtk_buffer,"%s%s(%.0f %.0f %.0f) (%.0f,%.0f,%.0f) %s",name,name2,p[0],p[1],p[2],
+		    vl[0],vl[1],vl[2],objlabel.c_str());
+	  talairachlabel->setText(pxtk_buffer);
+	  talairachlabel->configure("-fg","green");
+	}
+      else
+	{	
+	  sprintf(pxtk_buffer,"%s%s(%.0f %.0f %.0f)",name,name2,p[0],p[1],p[2]);
+	  talairachlabel->setText(pxtk_buffer);
+	  talairachlabel->configure("-fg","yellow");
+	  if (!this->CurrentImageIsColor)
+	    sprintf(pxtk_buffer,"Int=%s %s",this->GetFormatedNumber(vl[0],3),objlabel.c_str());
+	  else
+	    sprintf(pxtk_buffer,"Int=(%.0f,%.0f,%.0f) %s",vl[0],vl[1],vl[2],objlabel.c_str());
+	  mnilabel->setText(pxtk_buffer);
+	}
+      return 2;
+    }
+
+  mnilabel->setText("Not Axial");
+
+  if (!this->CurrentImageIsColor)
+    {
+      double vl=usethisimage->GetScalarComponentAsDouble(coord[0],coord[1],coord[2],this->CurrentFrame);
+      if (usingvalueimage==0)
+	vl=vl*this->IntensityScale+IntensityOffset;
+      sprintf(pxtk_buffer,"(%d %d %d) %s %s",coord[0],coord[1],coord[2],this->GetFormatedNumber(vl,3),objlabel.c_str());
+    } 
+  else 
+    {
+      double vl[3];
+      for (int ia=0;ia<=2;ia++)
+	vl[ia]=this->currentImage->GetScalarComponentAsDouble(coord[0],coord[1],coord[2],ia);
+      sprintf(pxtk_buffer,"(%d %.d %d) (%.0f,%.0f,%.0f) %s",coord[0],coord[1],coord[2],vl[0],vl[1],vl[2],objlabel.c_str());
+    }
+
+  talairachlabel->setText(pxtk_buffer);
+  talairachlabel->configure("-fg","white");
+  return 1;
+}
+
+void vtkpxGUIBaseImageViewer::DisableTalairachButtons()
+{
+  if (this->Initialized==1)
+    return;
+
+  this->createTalairachButtons=PXFalse;
+}
+
+void vtkpxGUIBaseImageViewer::EnableTalairachButtons()
+{
+  if (this->Initialized==1)
+    return;
+
+  this->createTalairachButtons=PXTrue;
+}
+
+double vtkpxGUIBaseImageViewer::GetMNISliceNo(int index,int plane,int& axis)
+{
+  axis=-1;
+  if (plane<0)
+    plane=0;
+  else if (plane>2)
+    plane=2;
+
+  if (this->talairachTransform==NULL || this->currentImage==NULL)
+      return -1000;
+
+  int oldstyleorient=vtkpxGUIBaseImageViewer::MapOrientationToOldStyle(this->Orientation);
+
+  double sp[3];    currentImage->GetSpacing(sp);
+  double ori[3];   currentImage->GetOrigin(ori);
+  int    dim[3];   currentImage->GetDimensions(dim);
+  double pos[3];
+  int level[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (ia==2)
+	level[ia]=index;
+      else
+	level[ia]=int(0.5*double(dim[ia])*sp[ia]+ori[ia]);
+      level[ia]=Irange(level[ia],0,dim[ia]-1);
+      pos[ia]=double(level[ia])*sp[ia]+ori[ia];
+    }
+  
+  if (oldstyleorient==1 || oldstyleorient==2)
+    {
+      double p1[3];
+      for (int ia=0;ia<=2;ia++) p1[ia]=pos[ia];
+      int ok=this->talairachTransform->ReorientCoordinates(this->currentImage,oldstyleorient,p1,pos);
+      if (ok==0)
+	return -1000;
+    }
+  
+
+  double mni[3];
+  int domni=this->talairachTransform->GetMNICoordinates(pos,mni);
+  if (domni==0)
+    return -1000;
+
+  if (oldstyleorient==0)
+    {
+      axis=plane;
+    }
+  else if (oldstyleorient==1)
+    {
+      switch (plane) {
+	case 0:	  axis=0;	  break;
+	case 1:	  axis=2;	  break;
+	case 2:	  axis=1;	  break;
+      }
+    }
+  else if (oldstyleorient==2)
+    {
+      switch (plane) {
+	case 0:	  axis=1;	  break;
+	case 1:	  axis=2;	  break;
+	case 2:	  axis=0;	  break;
+      }
+    }
+  
+  return mni[axis];
+}
+
+std::string vtkpxGUIBaseImageViewer::GetObjectmapValueAsText(int ,int,int ) 
+{
+  std::string s=" ";
+  return s;
+}
+
+
+void vtkpxGUIBaseImageViewer::SetBackgroundColor(vtkRenderWindow* renwin)
+{
+  vtkRendererCollection* col=renwin->GetRenderers();
+  int numren=col->GetNumberOfItems();
+
+  vtkRenderer* ren=col->GetFirstRenderer();
+
+  double c[3];   ren->GetBackground(c);
+  int a=this->EventManager->d_colorBox("Background Color",c[0],c[1],c[2]);
+
+  if (a==0)
+    return;
+
+  for (int i=0;i<numren;i++)
+    {
+      vtkRenderer* r=(vtkRenderer*)col->GetItemAsObject(i);
+      r->SetBackground(c);
+    }
+  renwin->Render();
+}
+
+int vtkpxGUIBaseImageViewer::MapOrientationToNewStyle(int oldorient)
+{
+  return vtkbisImageHeader::MapOrientationToNewStyle(oldorient);
+}
+
+int vtkpxGUIBaseImageViewer::MapOrientationToOldStyle(int neworient)
+{
+  return vtkbisImageHeader::MapOrientationToOldStyle(neworient);
+}
+
+const char* vtkpxGUIBaseImageViewer::OrientationToAxisName(int neworient,int axis)
+{
+  this->Buffer=vtkbisImageHeader::OrientationToAxisName(neworient,axis);
+  return this->Buffer.c_str();
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIBaseImageViewer.h b/bioimagesuite30_src/GUI/vtkpxGUIBaseImageViewer.h
new file mode 100644
index 0000000..8d127a9
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIBaseImageViewer.h
@@ -0,0 +1,302 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIBaseImageViewer - Base Image Viewer
+// .SECTION Description
+
+#ifndef __vtkpxGUIBaseImageViewer_h
+#define __vtkpxGUIBaseImageViewer_h
+
+class vtkImageData;
+class vtkPoints;
+class vtkImageData;
+
+#include "vtkpxGUIComponent.h"
+#include "vtkRenderWindow.h"
+#include "vtkWindow.h"
+#include "vtkPoints.h"
+#include "vtkTransform.h"
+#include "vtkpxGUIColormapEditor.h"
+#include <vtkstd/string>
+
+class vtkpxTalairachTransform;
+class vtkLookupTable;
+class vtkRenderer;
+class vtkScalarBarActor;
+
+class vtkpxGUIBaseImageViewer : public vtkpxGUIComponent
+{
+public:
+  
+  vtkTypeMacro(vtkpxGUIBaseImageViewer,vtkpxGUIComponent);
+  
+  // Initialize Display  
+  virtual char*  Initialize(const char* name,int inside);
+  
+  // Display Stuff 
+  virtual int  InitializeViewer() { return 1;}
+  virtual int  ResetViewer()      { return 1;}
+  virtual int  UpdateDisplay()    { return 0;}
+  virtual int  CustomPick(float selectionX, float selectionY, float selectionZ,
+			  float &x1,float& x2,float &x3) { return 0; }
+
+  // Description:
+  // Set Input Image
+  virtual int  SetImage(vtkImageData* im) {   return this->SetImage(im,0,NULL); }
+  virtual int  SetImage(vtkImageData* im,int orientation) { return this->SetImage(im,orientation,NULL,0.0,1.0); }
+  virtual int  SetImage(vtkImageData* im,int orientation,vtkLookupTable* lkp) { return this->SetImage(im,orientation,lkp,0.0,1.0); }
+  virtual int  SetImage(vtkImageData* im,int orientation,double offset,double scale) { return this->SetImage(im,orientation,NULL,offset,scale); }
+  virtual int  SetImage(vtkImageData* im,int orientation,vtkLookupTable* lkp,double offset,double scale);
+  virtual vtkImageData* GetImage();
+
+  // Description:
+  // Set Value Image (for overlays)
+  virtual int SetValueImage(vtkImageData* val);
+  virtual vtkImageData* GetValueImage();
+
+  // Description:
+  // CLicked Points
+  vtkGetVectorMacro(LastClickedPoint,double,3);
+  vtkSetVectorMacro(LastClickedPoint,double,3);
+
+  vtkGetVectorMacro(LastClickedPointScaled,double,3);
+  vtkSetVectorMacro(LastClickedPointScaled,double,3);
+
+  // Description:
+  // Information for Images
+  vtkGetMacro(Orientation,int);
+  vtkGetMacro(NumberOfFrames,int);
+
+  vtkSetClampMacro(PresetLookupTableMode,int,-1,7);
+  vtkGetMacro(PresetLookupTableMode,int);
+
+  // Export Facilities
+  virtual void SaveAsTiff(vtkRenderWindow* renwin);
+  virtual void SaveAsTiff(vtkRenderWindow* renwin,const char* fname);
+
+  virtual void SaveAllAsTiff(vtkRenderWindow* renwin);
+  virtual void SaveAllAsTiff(vtkRenderWindow* renwin,const char* fname);
+
+
+  // Scale factor -- render higher resolution images
+  vtkSetClampMacro(MagnificationFactor,int,1,8);
+  vtkGetMacro(MagnificationFactor,int);
+
+  virtual void ExportAsVRML(vtkRenderWindow* renwin);
+  virtual void SetBackgroundColor(vtkRenderWindow* renwin);
+
+
+
+  virtual void LoadTalairachLandmarks(const char* fname=NULL);
+  virtual vtkpxTalairachTransform* GetTalairachTransform()
+  { return talairachTransform; }
+  virtual void SetTalairachPoints(vtkPoints* pt);
+
+
+  virtual int LoadTalairachTransform(const char* fname=NULL);
+  virtual int SaveTalairachTransform(const char* fname=NULL);
+
+  virtual vtkLookupTable* GetLookupTable() { return this->mainLookupTable;}
+  virtual void SetLookupTable(vtkLookupTable* lkp);
+  virtual void LinkLookupTable(vtkLookupTable* lkp);
+  virtual void SetFmriMergeLookupTable();
+  virtual void SetFmriMergeLookupTable(int mode);
+  virtual void SetPresetLookupTable(int mode=0);
+
+  // Description:
+  // If this is 0 then off, 1=auto
+  // if auto then 3-frame images unsigned char are treated as color
+  // everything else as multiframe
+  virtual void SetColorMode(int md=1);
+
+  // Description:
+  // If 1 viewer is treating current image as color
+  vtkGetMacro(CurrentImageIsColor,int);
+
+  // Procedures for handling multiple frames
+  virtual int  GetCurrentFrame();
+  virtual void SetCurrentFrame(int t);
+  virtual void ShowFrameControls(int show=1);
+
+  // Description:
+  // Callback On Change Of Frame 
+  virtual void   SetFrameChangeCallback(const char* CallbackName);
+  vtkGetMacro(EnableFrameChangeCallback,int);
+  vtkSetClampMacro(EnableFrameChangeCallback,int,0,1);
+
+  // Description:
+  // Callback On Change Of Coordinates 
+  virtual void   SetCoordinatesChangeCallback(const char* CallbackName);
+  vtkGetMacro(EnableCoordinatesChangeCallback,int);
+  vtkSetClampMacro(EnableCoordinatesChangeCallback,int,0,1);
+  virtual const char*   GetCoordinateChangeCallback() { return this->coordinatesChangeCallbackName; }
+  virtual const char*   GetFrameChangeCallback() { return this->frameChangeCallbackName; }
+
+
+  vtkGetMacro(EnableRendering,int);
+  vtkSetMacro(EnableRendering,int);
+
+  // Description:
+  // Get RenderWidget Name
+  virtual char* GetRenderWidgetName() =0 ;
+  
+
+  // Description:
+  // GetKeyRenderer
+  vtkGetObjectMacro(KeyRenderer,vtkRenderer);
+  vtkGetMacro(ShowKeyRenderer,int);
+  vtkSetMacro(ShowKeyRenderer,int);
+  virtual void ToggleKeyRenderer();
+  virtual void UpdateKeyRenderer() { };
+  vtkGetObjectMacro(ScalarBar,vtkScalarBarActor);
+
+
+  // Description:
+  // Enable or Disable Talairach Buttons
+  virtual void DisableTalairachButtons();
+  virtual void EnableTalairachButtons();
+
+  // Description:
+  // Has Objectmap
+  virtual int HasObjectmap() { return 0;}
+
+
+  // Description:
+  // Painting Enabled
+  virtual int PaintingEnabled() { return 0;}
+
+
+  // Description:
+  // Map Nw Style Orientations to Old Style and back
+  // New Style Axial=10:17, Coronal: 20-27, Sagital 30:37
+  // Old Style Axial =0, coronal =1 , sagittal = 2
+  static int MapOrientationToNewStyle(int oldorient);
+  static int MapOrientationToOldStyle(int neworient);
+
+  // This generates the axis-names
+  const char* OrientationToAxisName(int neworient,int axis);
+
+protected:
+
+  vtkImageData*           currentImage;
+  vtkImageData*           valueImage;
+  vtkLookupTable*         mainLookupTable;
+  vtkRenderer*            KeyRenderer;
+  vtkScalarBarActor*      ScalarBar;
+  vtkpxGUIColormapEditor* ColormapEditor;
+  int                     ownsLookupTable;
+  int                     ShowKeyRenderer;
+  char*                   frameChangeCallbackName; 
+  int                     EnableFrameChangeCallback;
+
+  char*                   coordinatesChangeCallbackName; 
+  int                     EnableCoordinatesChangeCallback;
+
+
+  PXBool                  hasImage;
+  int                     Orientation;
+  double                  IntensityScale;
+  double                  IntensityOffset;
+  int                     PresetLookupTableMode;
+  int                     CurrentFrame;
+  int                     ColorMode;
+  int                     CurrentImageIsColor;
+  int                     NumberOfFrames;
+  int                     EnableRendering;
+  int                     MagnificationFactor;
+
+  PXBool                    createTalairachButtons;
+
+  vtkpxGUIBaseImageViewer();
+  virtual ~vtkpxGUIBaseImageViewer();
+
+  double                   LastClickedPoint[3];
+  double                   LastClickedPointScaled[3];
+  vtkpxTalairachTransform* talairachTransform;
+
+
+  virtual void     ExecuteFrameChangeCallback();
+  virtual void     ExecuteCoordinatesChangeCallback();
+
+
+
+  // Description:
+  // Talairach Grid
+  virtual void UpdateTalairachGrid(int force);
+  virtual void  RenderDelay(int t=3);
+
+  // Description:
+  // Coordinate Updates
+  virtual int  UpdateIntensityLabelInfo() =0;
+  virtual int  DisplayNeuroCoordinates(double pos[3],int coord[3],PXTkLabel* talairachlabel,PXTkLabel* mnilabel,vtkImageData* img=NULL);
+  const  char* GetFormatedNumber(double vl,int dp);
+  virtual double GetMNISliceNo(int index,int plane,int& axis);
+
+  // Description:
+  // Utility Functions
+  virtual int DoImagesHaveSameDimensions(vtkImageData* img,vtkImageData* img2,int checknumframes=0);
+
+  // Description:
+  // Colormap Stuff
+  virtual int ResetColormap();
+  virtual int ResetEditor() { return 0;}
+
+  // Objectmap Value
+  //BTX
+  virtual std::string GetObjectmapValueAsText(int a=0,int b=0,int c=0);
+  //ETX
+
+private:
+  static void handleRenderEvent(void *arg1);
+
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIBaseRenderer.cpp b/bioimagesuite30_src/GUI/vtkpxGUIBaseRenderer.cpp
new file mode 100644
index 0000000..b4f391d
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIBaseRenderer.cpp
@@ -0,0 +1,43 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxGUIBaseRenderer.h"
+
+vtkpxGUIBaseRenderer::vtkpxGUIBaseRenderer() 
+{
+
+}
+vtkpxGUIBaseRenderer::~vtkpxGUIBaseRenderer() 
+{
+
+}
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIBaseRenderer.h b/bioimagesuite30_src/GUI/vtkpxGUIBaseRenderer.h
new file mode 100644
index 0000000..0992777
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIBaseRenderer.h
@@ -0,0 +1,70 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkpxGUIBaseRenderer - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkpxGUIBaseRenderer_h
+#define __vtkpxGUIBaseRenderer_h
+
+#include "vtkpxGUIComponent.h"
+#include "vtkRenderer.h"
+
+class  vtkpxGUIBaseRenderer : public vtkpxGUIComponent
+{
+public:
+  vtkTypeMacro(vtkpxGUIBaseRenderer,vtkpxGUIComponent);
+  
+  virtual char* Initialize(const char* widgetname,int inside)=0;
+
+  // ---------------------------------------------------- 
+  virtual vtkRenderer* GetRenderer()=0;
+
+  virtual int    Get2DClickedPoint(double& px,double& py,int mousex,int mousey,int orient=-1) = 0;
+  virtual int    GetFlipMode() =0 ;
+
+  virtual void   SetUpdateRate(double interactiverate=15.0,double staticrate=0.1)=0;
+
+  virtual void   GetBounds(double bd[6])=0;
+  virtual void   SetBounds(double bd[6])=0;
+
+  virtual void   SetClipBounds(double x,double y,double z)=0;
+  virtual void   SetClipBounds(int x,int y,int z,double sp[3],double ori[3])=0;
+  virtual void   Render()=0;
+  virtual void   RenderDelay(int a=-1)=0;
+
+protected:
+  vtkpxGUIBaseRenderer();
+  virtual ~vtkpxGUIBaseRenderer();
+  //  PXVTkViewer* Viewer;
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUICallback.cpp b/bioimagesuite30_src/GUI/vtkpxGUICallback.cpp
new file mode 100644
index 0000000..5b1838d
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUICallback.cpp
@@ -0,0 +1,76 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxGUICallback.h"
+#include "vtkObject.h"
+
+vtkpxGUICallback* vtkpxGUICallback::New()
+{ 
+  return new vtkpxGUICallback; 
+}
+
+vtkpxGUICallback::vtkpxGUICallback()
+{
+  this->component=NULL;
+  this->filter=NULL;
+
+}
+
+void vtkpxGUICallback::AttachFilter(vtkObject* in_filter,vtkpxGUIComponent* in_component,const char* in_label)
+{
+  this->filter=in_filter;
+  this->component=in_component;
+  strncpy(this->label,in_label,50);
+}
+
+void vtkpxGUICallback::Execute(vtkObject *caller,unsigned long event, void* vtkNotUsed(v))
+{
+  if (this->filter==NULL || this->component==NULL)
+    return;
+
+  if (caller)
+    {
+      if (event == vtkCommand::ProgressEvent)
+	{
+	  if (this->filter->IsA("vtkProcessObject")==1)
+	    {
+	      this->component->ExecuteProgressMethod(this->label,((vtkProcessObject*)this->filter)->GetProgress());
+	    }
+	  else
+	    this->component->ExecuteProgressMethod(this->label,0.5);
+	}
+      else if (event == vtkCommand::StartEvent)
+	this->component->ExecuteProgressMethod(this->label,0.0);
+      else if (event == vtkCommand::EndEvent)
+	this->component->ExecuteProgressMethod(this->label,1.0);
+    }
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUICallback.h b/bioimagesuite30_src/GUI/vtkpxGUICallback.h
new file mode 100644
index 0000000..de0dd04
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUICallback.h
@@ -0,0 +1,91 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUICallback.h,v $
+  Language:  C++
+  Date:      $Date: 2002/07/18 15:04:57 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUICallback - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkpxGUICallback_h
+#define __vtkpxGUICallback_h
+
+#include "vtkObjectFactory.h"
+#include "vtkCommand.h"
+#include "vtkObject.h"
+#include "vtkpxGUIComponent.h"
+
+class vtkpxGUICallback : public vtkCommand
+{
+public:
+
+  static vtkpxGUICallback *New();
+  vtkTypeMacro(vtkpxGUICallback,vtkCommand);
+  virtual void Execute(vtkObject *caller,unsigned long event, void* vtkNotUsed(v));
+  virtual void AttachFilter(vtkObject* filter,vtkpxGUIComponent* component,const char* label);
+
+protected:
+
+  vtkpxGUICallback();
+
+  vtkpxGUICallback(const vtkpxGUICallback&) {};
+  void operator=(const vtkpxGUICallback&) {};
+
+  vtkpxGUIComponent*   component;
+  vtkObject*           filter;
+  char                 label[50];
+
+};
+
+
+ 
+#endif
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIColormapEditor.cpp b/bioimagesuite30_src/GUI/vtkpxGUIColormapEditor.cpp
new file mode 100644
index 0000000..af6dead
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIColormapEditor.cpp
@@ -0,0 +1,1904 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkpxUtil.h"
+#include "vtkpxGUIColormapEditor.h"
+#include "vtkLineSource.h"
+#include "vtkProbeFilter.h"
+#include "vtkDataSetCollection.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkCubeSource.h"
+#include "vtkActor.h"
+#include "vtkDataArray.h"
+#include "vtkpxColorMapUtil.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkpxUtil.h"
+#include "vtkPolyData.h"
+#include "vtkCommand.h"
+#include "vtkCamera.h"
+#include "vtkPlane.h"
+#include "vtkCellArray.h"
+#include "vtkMath.h"
+#include "vtkCoordinate.h"
+
+//#include "vtkContourWidget.h"
+//#include "vtkGenericRenderWindowInteractor.h"
+#include "vtkPolyData.h"
+
+
+#include "vtkCommand.h"
+#include "vtkRegressionTestImage.h"
+#include "vtkDebugLeaks.h"
+//#include "vtkTestUtilities.h"
+#include "vtkCamera.h"
+#include "vtkPlane.h"
+#include "vtkCellArray.h"
+#include "vtkMath.h"
+#include "vtkCoordinate.h"
+
+using namespace bioimagesuite_legacy;
+// ---------------------------------------------------------------------------------------------------------
+
+
+vtkpxGUIColormapEditor* vtkpxGUIColormapEditor::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIColormapEditor");
+  if(ret)
+    {
+      return (vtkpxGUIColormapEditor*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIColormapEditor;
+}
+
+// Construct object with no children.
+vtkpxGUIColormapEditor::vtkpxGUIColormapEditor()
+{
+  colormap=vtkLookupTable::New();
+  internal_colormap=vtkLookupTable::New();
+  owns_colormap=1;
+
+  colormap_filename=new char[20];
+  sprintf(colormap_filename,"new_colormap.cmap");
+  colormap_type=NULL;
+    
+  //  scalar_bar=NULL;
+  plot_actor=NULL;
+  render_widget=NULL;
+
+  editor_dialog=NULL;
+  simple_parent=NULL;
+  min_value=0;
+  num_decimal_points=0;
+  max_value=255;
+  num_colors=256;
+
+ /* this->redSpline = NULL;
+  this->greenSpline=NULL;
+  this->blueSpline =NULL;
+  this->alphaSpline = NULL; */
+  //  this->WidgetInteractor=NULL;
+
+  this->contourRep_red = NULL;
+  //  this->contourWidget_red = NULL;
+  this->contourRep_green = NULL;
+  //  this->contourWidget_green = NULL;
+
+  this->contourRep_blue = NULL;
+  //  this->contourWidget_blue = NULL;
+
+  this->contourRep_alpha = NULL;
+  //  this->contourWidget_alpha = NULL;
+
+  this->contourRep_rgb = NULL;
+  //  this->contourWidget_rgb = NULL;
+
+  /*  this->pd_r = NULL;
+  this->lines_r = NULL; 
+  this->points_r = NULL;
+  this->lineIndices_r = NULL; 
+
+  this->pd_g = NULL;
+  this->lines_g = NULL; 
+  this->points_g = NULL;
+  this->lineIndices_g = NULL; 
+
+  this->pd_b = NULL;
+  this->lines_b = NULL; 
+  this->points_b = NULL;
+  this->lineIndices_b = NULL; 
+
+  this->pd_a = NULL;
+  this->lines_a = NULL; 
+  this->points_a = NULL;
+  this->lineIndices_a = NULL; 
+
+  this->pd_rgb = NULL;
+  this->lines_rgb = NULL; 
+  this->points_rgb = NULL;
+  this->lineIndices_rgb = NULL; */
+
+  this->lockunlock=NULL;
+  volume_mode=0;
+  fmri_mode=0;
+  simple_mode=1;
+  locked=0;
+  strcpy(data_type,"Not Defined");
+  this->contourOffset[0]=0;
+  this->contourOffset[1]=0;
+  this->contourOffset[2]=0;
+
+  this->contourScale[0]=1;
+  this->contourScale[1]=255;
+  this->contourScale[2]=0;
+  //this->activeShiftPoint-1;
+  this->activeShiftPoint=1;
+  this->activeColorContour=4;
+}
+
+vtkpxGUIColormapEditor::~vtkpxGUIColormapEditor()
+{
+  if (owns_colormap)
+      colormap->Delete();
+
+  internal_colormap->Delete();
+  delete [] colormap_filename;
+}
+// --------------------------------------------------------------------------------------------------------- 
+char*  vtkpxGUIColormapEditor::Initialize(const char* name,int inside)
+{
+
+  if (this->Initialized==1)
+    return GetWidgetName();
+  
+  vtkpxGUIComponent::Initialize(name,inside);
+  PXTkFrame* mainFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+
+
+  if (!inside)
+      {
+	if (!simple_mode)
+	  {
+	    PXTkFrame* menubar=new PXTkFrame(this->EventManager,mainFrame);
+	    mainFrame->addChildren("-side top -expand false -fill x -pady 5",menubar);
+	    CreateMenu(menubar);
+	  }
+	
+	PXTkFrame* otherFrame=new PXTkFrame(this->EventManager,mainFrame);
+	otherFrame->configure("-bg","black");
+	mainFrame->addChildren("-side bottom -expand true -fill both -pady 5 -padx 5",otherFrame);
+	CreateRenderer(otherFrame);
+	if (simple_mode)
+	  CreateSimpleControls(otherFrame);
+	else
+	  CreateComplexControls(otherFrame);
+      }
+  else
+      {
+	simple_mode=1;
+	CreateSimpleControls(mainFrame);
+      }
+
+
+  
+  ResetSimpleColormap();
+  DisplayColormap();
+  sprintf(pxtk_buffer,"wm resizable %s 0 0",this->GetWidgetName());
+  PXTkApp::executeTclCommand(pxtk_buffer);
+
+  return GetWidgetName();
+
+}
+// ---------------------------------------------------------------------------------------------------------
+vtkLookupTable* vtkpxGUIColormapEditor::GetColormap()
+{
+  return colormap;
+}
+// ---------------------------------------------------------------------------------------------------------
+void  vtkpxGUIColormapEditor::AutoSetNumDecimalPoints()
+{
+  float maxdiff=50.0;
+  float newdiff=max_value-min_value;
+
+  if (newdiff>50.0)
+    {
+      num_decimal_points=0;
+      return;
+    }
+
+  if (newdiff<0.00001)
+    {
+      num_decimal_points=6;
+      return;
+    }
+
+  num_decimal_points=1;
+  while (newdiff < maxdiff && num_decimal_points<7)
+    {
+      ++num_decimal_points;
+      newdiff*=10.0;
+    }
+  
+
+}
+// ---------------------------------------------------------------------------------------------------------
+void  vtkpxGUIColormapEditor::SetColormap(vtkLookupTable* cmap)
+{
+  if (cmap==NULL)
+    {
+      fprintf(stderr,"\n\n\n Bad Setting of Colormap in vtkpxGUIColormapEditor\n\n\n\n\n");
+      return;
+    }
+
+  if (owns_colormap)
+    {
+      colormap->Delete();
+      owns_colormap=0;
+    }
+  
+  colormap=cmap;
+  internal_colormap->DeepCopy(colormap);
+
+  double range[2];
+  colormap->GetTableRange(range);
+  min_value=range[0];
+  max_value=range[1];
+  this->AutoSetNumDecimalPoints();
+  
+  ResetColormap(1);
+
+  /*  if (scalar_bar!=NULL)
+      scalar_bar->SetLookupTable(colormap);*/
+
+  if (render_widget!=NULL)
+      {
+	UpdateGraphFromColormap();
+	render_widget->RenderDelay();
+      }
+
+  if (this->EventParent!=NULL && this->CallbackNo>0)
+    this->EventParent->HandleEvent(CallbackNo);
+  
+  if (this->CallbackName!=NULL)
+    PXTkApp::executeTclCommand(this->CallbackName);
+
+
+
+}
+// ---------------------------------------------------------------------------------------------------------
+void  vtkpxGUIColormapEditor::SetVolumeMode(int vol)
+{
+  volume_mode=(vol>0);
+}
+
+void  vtkpxGUIColormapEditor::SetFmriMode(int fmri)
+{
+  // range set changed from 7 to 9 to incorporate extra preset colormaps 
+  fmri_mode=Irange(fmri,-1,8);
+
+  
+  int vol=0;
+  if (volume_mode)
+    vol=1;
+  
+  int outmode=0;
+
+
+  
+  if (fmri_mode>0 && fmri_mode<8)
+    {		
+      vtkpxColorMapUtil::SetFmriMergeColormap(colormap,fmri_mode-1,vol);
+      internal_colormap->DeepCopy(colormap);
+      outmode=4;
+    }
+  else if (vol==0)
+    {
+      if (fmri_mode==0)
+	{
+	  if (min_value<-1.0 && max_value>1.0 && !volume_mode )
+	    {
+	      vtkpxColorMapUtil::SetConstantHueColorMap(colormap,0.5,0.02,0.58,
+							Fmax( fabs(auto_min),fabs(auto_max)),
+							min_value,max_value,256);
+	      outmode=2;
+	    }
+	  else
+	    {
+	      vtkpxColorMapUtil::SetStepColorMap(colormap,auto_min,auto_max,min_value,max_value,256,vol);
+	      outmode=0;
+	    }
+	  internal_colormap->DeepCopy(colormap);
+	}
+      else if(fmri_mode==8)
+	{				
+	  vtkpxSurfaceUtil::DefaultObjectMapLookupTable(colormap,num_colors,1);
+	  internal_colormap->DeepCopy(colormap);
+	  outmode = 0; 
+	}
+      else
+	{
+	  vtkpxColorMapUtil::SetStepColorMap(colormap,min_value,max_value,min_value,max_value,256,vol);
+	  outmode=0;
+	  internal_colormap->DeepCopy(colormap);
+	}
+    }
+  else
+    {
+      if (fmri_mode==0)
+	{
+	  if (auto_min==min_value && auto_max==max_value)
+	    {
+	      double r=0.4*(max_value-min_value);
+	      double r2=r/8.0;
+	      vtkpxColorMapUtil::SetStepColorMap(colormap,min_value+r2,max_value-r,min_value+r2,max_value-r,256,vol);
+	      vtkpxColorMapUtil::SetStepColorMap(internal_colormap,min_value+r2,max_value-r,min_value,max_value,256,vol);
+	      outmode=0;
+	    }
+	  else
+	    {
+	      vtkpxColorMapUtil::SetStepColorMap(colormap,auto_min,auto_max,auto_min,auto_max,256,vol);
+	      vtkpxColorMapUtil::SetStepColorMap(internal_colormap,auto_min,auto_max,min_value,max_value,256,vol);
+	      outmode=0;
+	    }
+	}
+      else if(fmri_mode==8)
+	{					
+	  vtkpxSurfaceUtil::DefaultObjectMapLookupTable(colormap,num_colors,1);
+	  internal_colormap->DeepCopy(colormap);
+	  outmode = 0; 
+	  
+	}
+      else
+	{
+	  vtkpxColorMapUtil::SetStepColorMap(colormap,min_value,max_value,min_value,max_value,256,vol);
+	  outmode=0;
+	  internal_colormap->DeepCopy(colormap);
+	}
+    }
+  
+  
+  if (this->Initialized)
+    {
+      colormap_type->setIndex(outmode);
+      this->ResetSimpleColormap(1);
+      DisplayColormap();
+    }
+  
+  
+  if (this->EventParent!=NULL && this->CallbackNo>0)
+    this->EventParent->HandleEvent(CallbackNo);
+  
+  if (this->CallbackName!=NULL)
+    PXTkApp::executeTclCommand(this->CallbackName);
+}
+
+void  vtkpxGUIColormapEditor::SetSimpleMode(int simple)
+{
+  if (this->Initialized)
+      return;
+  simple_mode=(simple>0);
+}
+// ---------------------------------------------------------------------------------------------------------
+
+void  vtkpxGUIColormapEditor::SetRange(int min,int max)
+{
+  min_value=Frange(float(min),-32767.0,32766.0);
+  max_value=Frange(float(max),min_value,32767.0);
+  auto_min=min_value;
+  auto_max=max_value;
+  this->AutoSetNumDecimalPoints();
+  
+
+  if (this->Initialized)
+    {
+      ResetSimpleColormap();
+      SetSimpleColormapFromDialog();
+    }
+}
+// ---------------------------------------------------------------------------------------------------------
+void  vtkpxGUIColormapEditor::SetRange(vtkImageData* image)
+{
+  if (image==NULL)
+    {
+      vtkErrorMacro(<<"Bad Image\n");
+      this->SetRange(0,255);
+      return;
+    }
+  
+  
+  double range[2];  vtkDataArray* arr=image->GetPointData()->GetScalars();
+  arr->GetRange(range);
+  
+  min_value=range[0];
+  max_value=range[1];
+
+  int m=arr->GetNumberOfComponents();
+  //  if (m>4)    m=4;
+
+  for (int k=1;k<m;k++)
+    {
+      arr->GetRange(range,k);
+      min_value=Fmin(min_value,range[0]);
+      max_value=Fmax(max_value,range[1]);
+    }
+
+  if (fabs(max_value-min_value)<1.0e-6)
+    max_value=min_value+1.0e-6;
+
+
+  this->AutoSetNumDecimalPoints();
+  //  fprintf(stderr,"Done Scanning Components %f:%f, %d\n",range[0],range[1],num_decimal_points);
+
+
+  switch (image->GetScalarType()) 
+    {
+    case 0:
+      strcpy(data_type,"VTK_VOID");
+      break;
+    case 1:
+      strcpy(data_type,"VTK_BIT");
+      break;
+    case 2:
+      strcpy(data_type,"VTK_CHAR");
+      break;
+    case 3:
+      strcpy(data_type,"VTK_UNSIGNED_CHAR");
+      break;
+    case 4:
+      strcpy(data_type,"VTK_SHORT");
+      break;
+    case 5:
+      strcpy(data_type,"VTK_UNSIGNED_SHORT");
+      break;
+    case 6:
+      strcpy(data_type,"VTK_INT");
+      break;
+    case 7:
+      strcpy(data_type,"VTK_UNSIGNED_INT");
+      break;
+    case 8:
+      strcpy(data_type,"VTK_LONG");
+      break;
+    case 9:
+      strcpy(data_type,"VTK_UNSIGNED_LONG");
+      break;
+    case 10:
+      strcpy(data_type,"VTK_FLOAT");
+      break;
+    case 11:
+      strcpy(data_type,"VTK_DOUBLE");
+      break;
+    default:
+      strcpy(data_type,"Not Defined");
+      break;
+    }
+
+  if (this->Initialized)
+      {
+	if (min_value<0)
+	  colormap_type->setIndex(2,PXTrue);
+	else
+	  colormap_type->setIndex(0,PXTrue);
+      }
+  
+  auto_min=min_value;
+  auto_max=max_value;
+
+  //  fprintf(stderr,"Going to Robust Range\n");
+  vtkpxUtil::ImageRobustRange(image,0.01,0.99,auto_min,auto_max);
+
+
+  
+
+
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::SetPickedColorMapControl(int value)
+{
+  if(value < 0)
+    value = 0;
+  if(value > 4)
+    value = 4; 
+
+  this->activeColorContour=value;
+  
+  for (int ib=0;ib<=4;ib++)
+    {
+      if (ib==value)
+	{
+	  this->contourRep[ib]->SetPointScale(6.0);
+	  this->contourRep[ib]->SetShowControls(1);
+	  
+	}
+      else
+	{
+	  this->contourRep[ib]->SetPointScale(2.0);
+	  this->contourRep[ib]->SetShowControls(0);
+	}
+      this->contourRep[ib]->Update();
+    }
+
+  return 1; 
+}
+
+
+// ---------------------------------------------------------------------------------------------------------
+void  vtkpxGUIColormapEditor::SetNumberOfColors(int numc)
+{
+  num_colors=Irange(numc,2,2048);
+  if (this->Initialized)
+    {
+      ResetSimpleColormap();
+      SetSimpleColormapFromDialog();
+    }
+}
+
+void  vtkpxGUIColormapEditor::SetLock(int lock)
+{
+  locked=(lock>0);
+  /*if (locked)
+    {
+      if (editor_dialog!=NULL)
+	editor_dialog->popdownDialog();
+    }*/
+
+  strcpy(pxtk_buffer,colormap_filename);
+  if (locked)
+    sprintf(pxtk_buffer2,"Colormap Editor (Locked) %s",PXTkApp::getFilenameTail(pxtk_buffer));
+  else
+    sprintf(pxtk_buffer2,"Colormap Editor (Un Locked) %s",PXTkApp::getFilenameTail(pxtk_buffer));
+
+
+  if (this->lockunlock!=NULL)
+    {
+      if (locked)
+	{
+	  this->lockunlock->configure("-text","UnLock");
+	  this->lockunlock->configure("-bg","red");
+	  for (int i=0;i<=4;i++)
+	    scale[i]->disable();
+	  colormap_type->disable();
+	}
+      else
+	{
+	  this->lockunlock->configure("-text","Lock");
+	  this->lockunlock->configure("-bg","gray");
+	  for (int i=0;i<=4;i++)
+	    scale[i]->enable();
+	  colormap_type->enable();
+	}
+    }
+
+  this->EventManager->setTitle(pxtk_buffer2);
+	
+}
+
+void vtkpxGUIColormapEditor::Update()
+{
+  double range[2];
+  colormap->GetTableRange(range);
+  DisplayColormap();
+}
+
+// ---------------------------------------------------------------------------------------------------------
+int  vtkpxGUIColormapEditor::HandleEvent(int event)
+{
+  if (event<10)
+    return this->EventManager->handleDirectEvent(event);
+  
+  
+  switch(event)
+      {
+      case 100:
+	ResetSimpleColormap();
+	DisplayColormap();
+	break;
+
+      case 101:
+	{
+	  char* line=this->EventManager->getOpenFilename("Colormap File name","Colormap Files","*.cmap*");
+	  
+	  if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		  ReadColormap(line);
+	      }
+	}
+	break;
+	
+      case 102:
+	SaveColormap(colormap_filename);
+	break;
+	
+      case 103:
+	{
+	  char* line=this->EventManager->getSaveFilename("Colormap File Name",colormap_filename,"Colormap Files","*.cmap");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		SaveColormap(line);
+	    }
+	}
+	break;
+
+      case 104:
+	if (locked==0)
+	  SetColormapFromDialog();
+	break;
+	
+      case 105: // 
+      case 106: //
+      case 107: //
+      case 108: //
+      case 109:
+      case 110:
+      case 111:
+      case 112:
+      case 113:
+      case 114:
+	this->locked=0;
+	SetFmriMode(event-106);
+	break;
+	
+
+      case 118:
+	if (editor_dialog!=NULL && locked==0)
+	    editor_dialog->popupDialog();
+	break;
+
+      case 120:
+      case 121:
+      case 122:
+      case 123:
+      case 124:
+      case 125:
+      case 126:
+      case 127:
+	if (locked==0)
+	  {
+	    num_colors=(int)pow(float(2.0),float(event-116.0));
+	    //	    fprintf(stderr,"New Number Of Colors=%d\n",num_colors);
+	    ResetSimpleColormap();
+	    ResetComplexColormap();
+	  }
+	break;
+
+
+      case 130:
+	{
+	  int* x=render_widget->getRenderWindow()->GetSize();
+	  int mouse=PXTkApp::getIntArgument(0);
+	  int state=PXTkApp::getIntArgument(1);
+	  int x1=PXTkApp::getIntArgument(2);
+	  int x2=x[1]-PXTkApp::getIntArgument(3);
+	  int ok=this->HandleMouseButtonEvent(mouse,state,x1,x2,this->EventManager);
+	}
+	break;
+
+	
+
+      case 150:
+	{
+	  char line[175];
+	  sprintf(line,"Intensity Range %5.0f:%5.0f\n Data type=%s, num_colors=%d (or %d)",min_value,max_value,data_type,
+		  colormap->GetNumberOfTableValues(),num_colors);
+	  this->EventManager->messageBox(line);
+	}
+	break;
+	
+	  case 151: case 152: case 153: case 154: case 155:
+	    SetPickedColorMapControl(event-151);
+		break;
+
+	  case 160:
+		  this->SetLock((locked==0));
+		  break;
+
+      case 200:
+	if (locked==0)
+	  {
+	    ResetSimpleColormap();
+	    SetSimpleColormapFromDialog();
+	    ResetComplexColormap();
+	  }
+	break;
+
+      case 201: // change options
+	if (locked==0)
+	  {
+	    if (colormap_type->getIndex()==0)
+	      {
+		if (scale[0]->getValue()>scale[1]->getValue())
+		  scale[0]->setValue(scale[1]->getValue());
+	      }
+	    SetSimpleColormapFromDialog();
+	    ResetComplexColormap();
+	  }
+	break;
+	
+      case 202:
+	if (locked==0)
+	  {
+	    if (colormap_type->getIndex()==0 || colormap_type->getIndex()==3)
+	      {
+		if (scale[0]->getValue()>scale[1]->getValue())
+		  scale[1]->setValue(scale[0]->getValue());
+	      }
+	    SetSimpleColormapFromDialog();
+	    ResetComplexColormap();
+	  }
+	break;
+	
+      case 203:
+	  case 204:
+      case 205:
+	if (locked==0)
+	  {
+	    SetSimpleColormapFromDialog();
+	    ResetComplexColormap();
+	  }
+	break;
+	
+      case 131:
+
+	if (render_widget!=NULL)
+	  {
+	    this->SetPickedColorMapControl(this->activeColorContour);
+	    render_widget->Render();
+	  }
+	break;
+	
+      case 300:
+      case 301:
+      case 302:
+      case 303:
+      case 304:
+      case 305:
+      case 306:
+      case 307:
+	if (locked==0)
+	  SetComplexColormapFromDialog(event-300);
+	break;
+	
+      case 310:
+	if (locked==0)
+	  ResetComplexColormap();
+	break;
+	
+	
+      case 401:
+	{
+	  char* line=this->EventManager->getOpenFilename("Import Analyze Colormap","Analyze Colormap","*.lkup");
+	  
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		ImportColormap(line);
+	    }
+	}
+	break;
+		
+      case 402:
+	{
+	  char* line=this->EventManager->getSaveFilename("Export Analyze Colormap","colormap.lkup","Analyze Colormap Files","*.lkup");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		ExportColormap(line);
+	    }
+	}
+	break;
+	
+
+      }
+
+  if (event==101 || event==401 || event==105 || event==106  || event == 107 || event == 108 ||
+      event==200 || event==201 || event==202 || event==203 || event==204 || event==205 ||
+      event>=300 || (event>120 && event<128))
+      {
+	if (this->EventParent!=NULL && this->CallbackNo>0)
+	  this->EventParent->HandleEvent(CallbackNo);
+	
+	if (this->CallbackName!=NULL)
+	  PXTkApp::executeTclCommand(this->CallbackName);
+      }
+
+
+  return TCL_OK;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::CreateMenu(PXTkFrame* menubar)
+{
+  PXTkMenuButton* but1=new PXTkMenuButton(this->EventManager,menubar,"Colormap",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but1);
+  
+  PXTkMenu *menu1=new PXTkMenu(this->EventManager,but1,PXFalse);
+  menu1->addButton("New",100);
+  menu1->addSeparator();
+  menu1->addButton("Load",101);
+  menu1->addButton("Save",102);
+  menu1->addButton("Save As",103);
+  menu1->addSeparator();
+  menu1->addButton("Import Analyze",401);
+  menu1->addButton("Export Analyze",402);
+  menu1->addSeparator();
+  menu1->addButton("Close",3);
+
+  PXTkMenuButton* but4=new PXTkMenuButton(this->EventManager,menubar,"Presets",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but4);
+  
+  PXTkMenu *menu4=new PXTkMenu(this->EventManager,but4,PXFalse);
+  menu4->addButton("Reset",105);
+  menu4->addButton("Normalized",106);
+  menu4->addButton("Objectmap",114);
+  menu4->addSeparator();
+  menu4->addButton("Fmri 1",107);
+  menu4->addButton("Fmri 2",108);
+  menu4->addButton("Fmri 3",109);
+  menu4->addButton("Fmri 4",112);
+  menu4->addButton("Fmri 5",113);
+  menu4->addButton("Spect 1",110);
+  menu4->addButton("Spect 2",111);
+
+
+
+  PXTkMenuButton* but3=new PXTkMenuButton(this->EventManager,menubar,"Levels",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but3);
+  
+  PXTkMenu *menu3=new PXTkMenu(this->EventManager,but3,PXFalse);
+  menu3->addButton("Update",104);
+  menu3->addButton("Info",150);
+  menu3->addSeparator();
+  menu3->addRadioButton("16",1,16,PXFalse,120);
+  menu3->addRadioButton("32",1,32,PXFalse,121);
+  menu3->addRadioButton("64",1,64,PXFalse,122);
+  menu3->addRadioButton("128",1,128,PXFalse,123);
+  menu3->addRadioButton("256",1,256,PXTrue,124);
+  menu3->addRadioButton("512",1,512,PXFalse,125);
+  menu3->addRadioButton("1024",1,1024,PXFalse,126);
+  menu3->addRadioButton("2048",1,2048,PXFalse,127);
+
+  if (!simple_mode)
+      {
+  PXTkMenuButton* but5=new PXTkMenuButton(this->EventManager,menubar,"RGBA",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but5);
+  
+  PXTkMenu *menu5=new PXTkMenu(this->EventManager,but5,PXFalse);
+  menu5->addButton("Red",151);
+  menu5->addButton("Green",152);
+  menu5->addButton("Blue",153);
+  menu5->addButton("Alpha",154);
+  menu5->addButton("RGB",155);
+  menu5->addSeparator();
+  menu5->addButton("Slider Controls",118);
+  }
+  
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::CreateSimpleControls(PXTkFrame* parframe)
+{
+  this->simple_parent=new PXTkFrame(this->EventManager,parframe);
+  parframe->addChildren("-side top -fill x -expand false",simple_parent);
+  
+  PXTkFrame* bframe=new PXTkFrame(this->EventManager,this->simple_parent);
+  this->simple_parent->addChildren("-side top -fill x -expand true",bframe);
+
+  colormap_type=new PXTkOptionMenu(this->EventManager,bframe,"Step",200);
+  colormap_type->addOption("Gamma");
+  colormap_type->addOption("Constant-Hue");
+  colormap_type->addOption("Overlay");
+  colormap_type->addOption("Complex Overlay");
+  colormap_type->addOption("Temperature");
+  colormap_type->addOption("Rainbow");
+  //  colormap_type->addOption("Reverse Rainbow");
+  colormap_type->setIndex(0);
+
+  PXTkLabel* lab=new PXTkLabel(this->EventManager,bframe,"");
+  lab->configure("-image","$::pxtclvtkpxcontrib::smalllogo ");
+  this->lockunlock=new PXTkButton(this->EventManager,bframe,"Lock",160);
+  bframe->addChildren("-side right  -expand false -padx 1",lab,lockunlock);
+  bframe->addChildren("-side left  -expand true -fill x",colormap_type);
+
+  PXBool inside_parent=PXTrue;
+
+  for (int i=0;i<=4;i++)
+      {
+	scale[i]=new PXTkArrowScale(this->EventManager,this->simple_parent,"Min:",201+i,inside_parent);
+	scale[i]->setRange(min_value,max_value);
+	scale[i]->setValue(0.5*(max_value+min_value));
+	scale[i]->setDecimalPoints(1);
+	scale[i]->setIncrement(1.0);
+	scale[i]->setLengthWidth(180,10);
+	this->simple_parent->addChildren("-side top -fill x -expand false",scale[i]->getMainWindow());
+	packed[i]=1;
+
+      }
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::CreateEditorControls(PXTkFrame* edit)
+{
+  PXTkFrame* fr=new PXTkFrame(this->EventManager,edit);
+  edit->addChildren("-side top -expand true -fill both",fr);
+
+  fr->setPackMode(PXFalse);
+  
+  editor_type=new PXTkOptionMenu(this->EventManager,fr,"RGB",310);
+  editor_type->addOption("Red");
+  editor_type->addOption("Green");
+  editor_type->addOption("Blue");
+  editor_type->addOption("Opacity");
+ 
+  fr->gridRowColumnChild(editor_type,0,0,1,2);
+  
+  int maxno=5;
+
+  for (int i=0;i<=maxno;i++)
+      {
+	float vl=float(i)/float(maxno);
+	if (i!=0 && i!=maxno)
+    {
+      int index=int(vl*float(num_colors)+0.5);
+      levelscale[i]=new PXTkArrowScale(this->EventManager,fr,"Level",300+i,PXFalse);
+      levelscale[i]->setRange(0.0,num_colors-1);
+      levelscale[i]->setDecimalPoints(1);
+      levelscale[i]->setResolution(1);
+      levelscale[i]->setValue(index);
+      
+      levelscale[i]->setIncrement(1);
+      levelscale[i]->setLengthWidth(150,10);
+      fr->gridRowColumnChild(levelscale[i]->getMainWindow(),i+1,0);
+    }
+
+	valuescale[i]=new PXTkArrowScale(this->EventManager,fr,"Value",300+i,PXFalse);
+	valuescale[i]->setRange(0.0,1.0);
+	valuescale[i]->setDecimalPoints(3);
+	valuescale[i]->setResolution(0.001);
+	valuescale[i]->setValue(vl);
+	valuescale[i]->setIncrement(0.01);
+	valuescale[i]->setLengthWidth(150,10);
+	fr->gridRowColumnChild(valuescale[i]->getMainWindow(),i+1,1);
+      }
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::CreateRenderer(PXTkFrame* frame)
+{
+#if defined(VTK_USE_CARBON)
+  return 0;
+#endif
+
+  render_widget=new PXVTkTkRenderWidget(this->EventManager,frame,130);
+  render_widget->setWidthHeight(400,400);
+  render_widget->bindMouseEvents();
+  frame->addChildren("-side top -expand false",render_widget);
+
+  //vtkScalarBarActor *scalar_bar=vtkScalarBarActor::New();
+  scalar_bar = vtkScalarBarActor::New(); 
+  scalar_bar->SetLookupTable(colormap);
+  scalar_bar->SetOrientationToHorizontal();
+  scalar_bar->GetPositionCoordinate()->SetValue(0.0,0.0);
+  scalar_bar->SetWidth(1.0);
+
+  if (simple_mode)
+    scalar_bar->SetHeight(0.35);
+  else
+    scalar_bar->SetHeight(0.15);
+
+  scalar_bar->SetLabelFormat("%5.0f");
+  scalar_bar->SetNumberOfLabels(10);
+
+
+  render_widget->getRenderer()->AddActor2D(scalar_bar);
+
+  render_widget->getRenderer()->SetBackground(0.4,0.4,0.4);
+  //render_widget->getRenderer()->SetBackground(0.1,0.1,0.1);
+
+  // Create and Bind Interactor
+  // --------------------------
+
+  this->contourRep_red = vtkpxBaseCurve::New();
+  this->contourRep_green = vtkpxBaseCurve::New();
+  this->contourRep_blue = vtkpxBaseCurve::New();
+  this->contourRep_alpha = vtkpxBaseCurve::New();
+  this->contourRep_rgb = vtkpxBaseCurve::New();
+  this->contourRep_box = vtkpxBaseCurve::New();
+
+  this->contourRep[0]=this->contourRep_red;
+  this->contourRep[1]=this->contourRep_green;
+  this->contourRep[2]=this->contourRep_blue;
+  this->contourRep[3]=this->contourRep_alpha;
+  this->contourRep[4]=this->contourRep_rgb;
+  this->contourRep[5]=this->contourRep_box;
+
+
+  vtkPoints* pts=vtkPoints::New();
+  pts->SetNumberOfPoints(6);
+  for (int ia=0;ia<pts->GetNumberOfPoints();ia++)
+    pts->SetPoint(ia,0,0,0);
+  
+
+  for (int ib=0;ib<=5;ib++)
+    {
+      //      fprintf(stderr,"Creating Contour %d",ib);
+      this->contourRep[ib]->SetPointScale(6.0);
+      this->contourRep[ib]->SetClosedCurve(0);
+      this->contourRep[ib]->SetShowControls((ib==4));
+      this->contourRep[ib]->SetShowCurve(1);
+
+      if (ib!=5)
+	{
+	  this->contourRep[ib]->SetFromPoints(pts);
+	}
+      else
+	{
+	  this->contourRep[5]->AddPoint(0,0,1,0);
+	  this->contourRep[5]->AddPoint(255,0,1,0);
+	  this->contourRep[5]->AddPoint(255,255,1,0);
+	  this->contourRep[5]->AddPoint(255,0,1,0);
+	  this->contourRep[ib]->SetClosedCurve(1);
+	  this->contourRep[ib]->SetShowBoundingBox(1);
+	}
+      //      fprintf(stderr,"Done creating curve %d nump=%d\n",ib,this->contourRep[ib]->GetNumPoints());
+  
+      vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+      map->SetInput(this->contourRep[ib]->GetOutput());
+
+      vtkActor* act=vtkActor::New();
+      act->SetMapper(map);
+      
+      switch (ib)
+	{
+	case 0:  act->GetProperty()->SetColor(1,0,0); break;
+	case 1:  act->GetProperty()->SetColor(0,1,0); break;
+	case 2:  act->GetProperty()->SetColor(0,0,1); break;
+	case 3:  act->GetProperty()->SetColor(1,1,0); break;
+	case 4:  act->GetProperty()->SetColor(1,1,1); break;	
+	case 5:  act->GetProperty()->SetColor(0.2,0.2,0.2); break;
+	}
+      /*      act->GetProperty()->SetRepresentationToWireframe();
+      act->GetProperty()->SetLineWidth(2.0);
+      act->GetProperty()->SetAmbient(1.0);
+      act->GetProperty()->SetDiffuse(0.0);
+      act->GetProperty()->SetSpecular(0.0);*/
+
+
+      render_widget->getRenderer()->AddActor(act);
+      act->SetVisibility(1);
+      act->Delete();
+      map->Delete();
+    }
+  pts->Delete();
+  
+  //  render_widget->getRenderer()->GetCamera()->ParallelProjectionOn();
+
+  
+
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::CreateComplexControls(PXTkFrame* frame)
+{
+  CreateSimpleControls(frame);
+
+  editor_dialog=new PXTkDialog(this->EventManager,frame,"Slider Controls",PXFalse);
+  editor_dialog->initDisplay();
+  
+  PXTkFrame* editorframe=(PXTkFrame*)editor_dialog->getMainWindow();
+  CreateEditorControls(editorframe);
+
+  PXTkButton* editorclose=new PXTkButton(editor_dialog,editorframe,"Close",3);
+  editorframe->addChildren("-side bottom -expand false -fill x",editorclose);
+
+  return 0;
+}
+
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::ReadColormap(const char* name)
+{
+  int ok=vtkpxColorMapUtil::LoadColormap(colormap,name);
+  if (ok==0)
+    return 0;
+
+  /*double dat[2];  colormap->GetTableRange(dat);
+  min_value=dat[0];
+  max_value=dat[1];*/
+
+  fmri_mode=0;
+  delete [] colormap_filename;
+  colormap_filename=new char[strlen(name)+1];
+  strcpy(colormap_filename,name);
+
+  internal_colormap->DeepCopy(colormap);
+
+  DisplayColormap();
+  locked=0;
+  return TCL_OK;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::SaveColormap(const char* name)
+{
+  int ok=vtkpxColorMapUtil::SaveColormap(colormap,name);
+  if (ok==0)
+    return 0;
+
+  if (strcmp(colormap_filename,name)!=0)
+    {
+      delete [] colormap_filename;
+      colormap_filename=new char[strlen(name)+1];
+      strcpy(colormap_filename,name);
+    }
+  return DisplayColormap();
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::ImportColormap(const char* name)
+{
+  int ok=vtkpxColorMapUtil::LoadAnalyzeColormap(colormap,name,volume_mode);
+  if (ok==0)
+    return 0;
+  
+  fmri_mode=0;
+  locked=0;
+  internal_colormap->DeepCopy(colormap);
+  //  vtkpxColorMapUtil::CopyLookupTable(colormap,internal_colormap);
+  DisplayColormap();
+  return TCL_OK;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::ExportColormap(const char* name)
+{
+  if (colormap==NULL)
+    return 0;
+  
+  if (colormap->GetNumberOfColors()!=256)
+    {
+	this->EventManager->messageBox(pxtk_buffer,"Cannot export colormap as it does not have 256 colors\n");
+	return 0;
+      }
+
+  int ok=vtkpxColorMapUtil::SaveAnalyzeColormap(colormap,name);
+  return DisplayColormap();
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::DisplayColormap()
+{
+  if (!this->EventManager->isInside())
+    {
+      strcpy(pxtk_buffer,colormap_filename);
+      if (locked)
+	sprintf(pxtk_buffer2,"Colormap Editor (Locked) %s",PXTkApp::getFilenameTail(pxtk_buffer));
+      else
+	sprintf(pxtk_buffer2,"Colormap Editor (Un Locked) %s",PXTkApp::getFilenameTail(pxtk_buffer));
+      this->EventManager->setTitle(pxtk_buffer2);
+      if (render_widget!=NULL)
+	{
+	  ResetColormap(1);
+	  if (render_widget!=NULL)
+	    render_widget->RenderDelay();
+	}
+    }
+  return TCL_OK;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::UpdateGraphFromColormap()
+{
+  if (render_widget==NULL || colormap==NULL)
+      return 0;
+
+  int dimensions[3];
+
+  int numc=colormap->GetNumberOfTableValues();
+  if (numc<2)
+    return 0;
+
+  double rgba[4]; 
+  
+  int ncp=this->contourRep_red->GetNumPoints();
+  int sc=(numc/(ncp-1));
+
+  double z=this->contourOffset[2];
+
+  //  fprintf(stderr,"Updating Graph From Colormap ncp=%d numc=%d sc=%d\n",ncp,numc,sc);
+
+  double xmin,xmax,ymin,ymax;
+
+  // Update Location Of Control Points
+  for (int i = 0; i< ncp; i++)
+    {
+
+      // Index is index into colormap of current control point
+      int index=i*sc;
+      if (index>=numc)
+	index=numc-1;
+
+      // X-Coordinate on display
+      double x=double(this->contourScale[0]*index+this->contourOffset[0]);
+
+      colormap->GetTableValue(index, rgba); 
+
+      // Y-Coordinate(s) on display are values for five bars R,G,B,A, RGB
+      double y[5];
+      for (int ib=0;ib<=3;ib++)
+	y[ib]=double(this->contourScale[1])*rgba[ib]+double(this->contourOffset[1]);
+      y[4]=0.0;
+      for (int ib=0;ib<=2;ib++)
+	y[4]+=rgba[ib];
+      y[4]=double(this->contourScale[1])*(y[4]/3.0)+double(this->contourOffset[1]);
+
+      this->contourRep_red->SetPoint(i,x,y[0],z,0);
+      this->contourRep_green->SetPoint(i,x,y[1],z,0);
+      this->contourRep_blue->SetPoint(i,x,y[2],z,0);
+      this->contourRep_alpha->SetPoint(i,x,y[3],z,0);
+      this->contourRep_rgb->SetPoint(i,x,y[4],z,0);
+
+      if (i==0)
+	{
+	  xmin=x;
+	  xmax=x;
+	  ymin=y[0]; ymax=y[0];
+	}
+
+      if (x<xmin) xmin=x;
+      if (x>xmax) xmax=x;
+      for (int ia=0;ia<=4;ia++)
+	{
+	  if (ymin>y[ia]) ymin=y[ia];
+	  if (ymax<y[ia]) ymax=y[ia];
+	}
+
+    }
+  
+  for (int ib=0;ib<=4;ib++)
+    this->contourRep[ib]->Update();
+  
+  this->render_widget->getRenderer()->ResetCamera(xmin,xmax,ymin-50,ymax,0,5);
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::ResetColormap(int controlsonly)
+{
+  if (controlsonly)
+    num_colors=colormap->GetNumberOfColors();
+      
+
+  ResetSimpleColormap(controlsonly);
+  ResetComplexColormap(controlsonly);
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::ResetComplexColormap(int controlsonly)
+{
+  if (!this->Initialized)
+      return 0;
+
+  // Graph is directly paired to complex colormap sliders 
+
+  if (num_colors>0)
+    this->contourScale[0]=256/double(num_colors);
+
+  this->UpdateGraphFromColormap();
+
+
+  if (editor_dialog==NULL)
+      return 0;
+
+  //  fprintf(stderr,"Doing COmplex ...");
+  
+  int maxno=5;
+
+  int mode=Irange(editor_type->getIndex(),1,4);
+  
+  for (int i=0;i<=maxno;i++)
+    {
+      double c[4];
+      int index=int(double(i)/double(maxno)*double(num_colors)+0.5);
+      colormap->GetTableValue(index,c);
+      if (i!=0 && i!=maxno)
+	{
+	  levelscale[i]->setRange(0,num_colors-1);
+	  levelscale[i]->setValue(index);
+	}
+      valuescale[i]->setValue(c[mode-1]);
+    }
+
+  //  fprintf(stderr,"Doing COmplex ... Done");
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::ResetSimpleColormap(int controlsonly)
+{
+  if (!this->Initialized)
+    return 0;
+  
+  int option=colormap_type->getIndex();
+  int maxshow=4;
+  
+  //  fprintf(stderr,"Values = %f:%f numdp=%d\n",min_value,max_value,num_decimal_points);
+  
+  
+  switch(option)
+    {
+    case 0:
+      {
+	for (int i=0;i<=1;i++)
+	  {
+	    scale[i]->setRange(min_value,max_value);
+	    scale[i]->setDecimalPoints(num_decimal_points);
+	    if (max_value-min_value>32)
+	      scale[i]->setIncrement(1.0);
+	    else		 
+	      scale[i]->setIncrement(double(max_value-min_value)/32.0);
+	    scale[i]->enable();
+	  }
+      }
+      scale[0]->setLabel("Min Intensity");
+      scale[0]->setValue(min_value);
+      scale[1]->setLabel("Max Intensity");
+      scale[1]->setValue(max_value);
+      maxshow=2;
+      
+      if (!controlsonly)
+	{
+	  vtkpxColorMapUtil::SetStepColorMap(colormap,min_value,max_value,min_value,max_value,num_colors,volume_mode);
+	  internal_colormap->DeepCopy(colormap);
+	  //	    vtkpxColorMapUtil::CopyLookupTable(colormap,internal_colormap);
+	}
+      break;
+    case 1:
+      scale[0]->setLabel("Gamma");
+      scale[0]->setRange(0.0,5.0);
+      scale[0]->setValue(1.0);
+      scale[0]->setDecimalPoints(1);
+      scale[0]->setIncrement(0.2);
+      scale[0]->enable();
+      maxshow=1;
+      if (!controlsonly)
+	{
+	  vtkpxColorMapUtil::SetGammaColorMap(colormap,1.0,min_value,max_value,num_colors,volume_mode);
+	  internal_colormap->DeepCopy(colormap);
+	  //	    vtkpxColorMapUtil::CopyLookupTable(colormap,internal_colormap);
+	}
+      break;
+      
+    case 2:
+      {
+	for (int i=0;i<=2;i++)
+	  {
+	    scale[i]->setRange(0.0,1.0);
+	    scale[i]->setIncrement(0.01);
+	    scale[i]->setDecimalPoints(3);
+	    scale[i]->enable();
+	  }
+      }
+      scale[0]->setLabel("Intensity");
+      scale[0]->setValue(0.5);
+      scale[1]->setLabel("Positive Hue");
+      scale[1]->setValue(0.02);
+      scale[2]->setLabel("Negative Hue");
+      scale[2]->setValue(0.58);
+      scale[3]->setLabel("Cutoff");
+      scale[3]->setRange(0.0,Fmax(fabs(min_value),fabs(max_value)));
+      scale[3]->enable();
+      scale[3]->setDecimalPoints(num_decimal_points);
+      scale[3]->setIncrement(1.0);
+      scale[3]->setValue(Fmax(fabs(min_value),fabs(max_value)));
+      maxshow=4;
+      if (!controlsonly)
+	vtkpxColorMapUtil::SetConstantHueColorMap(colormap,0.5,0.02,0.58,scale[3]->getValue(),
+						  min_value,max_value,num_colors,volume_mode);
+      internal_colormap->DeepCopy(colormap);
+      break;
+      
+    case 3:
+    case 4:
+      {
+	int nc=colormap->GetNumberOfColors();
+	float maxv=55.0;
+	if (nc==256)
+	  maxv=191.0;
+	
+	for (int i=0;i<=1;i++)
+	  {
+	    scale[i]->setRange(0,maxv);
+	    scale[i]->setDecimalPoints(num_decimal_points);
+	    scale[i]->setIncrement(1.0);
+	    scale[i]->enable();
+	  }
+	
+	scale[0]->setLabel("Min Intensity");
+	scale[0]->setValue(min_value);
+	scale[1]->setLabel("Max Intensity");
+	scale[1]->setValue(max_value);
+	
+	for (int i=2;i<=4;i++)
+	  {
+	    scale[i]->setRange(0.0,1.0);
+	    scale[i]->setIncrement(0.01);
+	    scale[i]->setDecimalPoints(3);
+	    scale[i]->enable();
+	  }
+	
+	scale[2]->setLabel("Intensity");
+	scale[2]->setValue(1.0);
+	scale[3]->setLabel("Positive Hue");
+	scale[3]->setValue(0.0);
+	scale[4]->setLabel("Negative Hue");
+	scale[4]->setValue(0.58);
+	
+	if (option==3)
+	  maxshow=5;
+	else
+	  maxshow=2;
+	
+	vtkpxColorMapUtil::CreateOverlayColorMap(colormap,
+						 colormap->GetNumberOfColors(),
+						 0,maxv,0,maxv,
+						 1.0,0.0,0.58,volume_mode,(option==3));
+	internal_colormap->DeepCopy(colormap);
+      }
+      break;
+      
+    case 5:
+    case 6:
+    case 7:
+      {
+	//	fprintf(stderr,"Option=%d\n",option);
+	for (int i=0;i<=1;i++)
+	  {
+	    scale[i]->setRange(min_value,max_value);
+	    scale[i]->setDecimalPoints(num_decimal_points);
+	    if (max_value-min_value>32)
+	      scale[i]->setIncrement(1.0);
+	    else		 
+	      scale[i]->setIncrement(double(max_value-min_value)/32.0);
+	    scale[i]->enable();
+	  }
+      
+	scale[0]->setLabel("Min Intensity");
+	scale[0]->setValue(min_value);
+	scale[1]->setLabel("Max Intensity");
+	scale[1]->setValue(max_value);
+	maxshow=2;
+	
+	if (!controlsonly)
+	  {	
+	    if (option==6)
+	      vtkpxColorMapUtil::SetRainbowColorMap(colormap,min_value,max_value,min_value,max_value,num_colors,volume_mode);
+	    else if (option==7)
+	      vtkpxColorMapUtil::SetReverseRainbowColorMap(colormap,min_value,max_value,min_value,max_value,num_colors,volume_mode);
+	    else
+		{
+	      vtkpxColorMapUtil::SetBlackBodyColorMap(colormap,min_value,max_value,min_value,max_value,num_colors,volume_mode);
+		}
+
+	  internal_colormap->DeepCopy(colormap);		
+
+
+	  }
+      }
+      break;
+      
+    }
+  
+  for (int j=0;j<=4;j++)
+    {
+      if (j<maxshow)
+	{
+	  if (packed[j]==0)
+	    {
+	      scale[j]->enable();
+	      this->simple_parent->addChildren("-side top -fill x -expand false",scale[j]->getMainWindow());
+	      packed[j]=1;
+	    }
+	}
+      else
+	{
+	  scale[j]->setLabel("Not Unused");
+	  scale[j]->disable();
+	  if (packed[j]==1)
+	    this->simple_parent->unmapChild(scale[j]->getMainWindow());
+	  packed[j]=0;
+	}
+    }
+  
+  //  fprintf(stderr,"Done Values = %f:%f numdp=%d\n",min_value,max_value,num_decimal_points);
+  return TCL_OK;
+}
+// ---------------------------------------------------------------------------------------------------------
+int  vtkpxGUIColormapEditor::SetColormapFromDialog()
+{
+  if (simple_mode)
+    return SetSimpleColormapFromDialog();
+  else
+    return SetComplexColormapFromDialog(0);
+
+}
+// ---------------------------------------------------------------------------------------------------------
+int  vtkpxGUIColormapEditor::SetComplexColormapFromDialog(int active)
+{
+  if (editor_dialog==NULL)
+      return 0;
+
+  if (active<0)
+    {
+      return ResetComplexColormap();
+    }
+  
+  int maxno=5;
+
+  if (active<=maxno-2 && active >=1) 
+    {
+      if (levelscale[active]->getValue()>levelscale[active+1]->getValue())
+	levelscale[active]->setValue(levelscale[active+1]->getValue());
+    }
+  if (active>=2 && active <= maxno-1)
+    {
+      if (levelscale[active]->getValue()<levelscale[active-1]->getValue())
+	levelscale[active]->setValue(levelscale[active-1]->getValue());
+    }
+  
+  int mode=editor_type->getIndex();
+  
+  if (num_colors!=colormap->GetNumberOfColors())
+    {
+      colormap->SetNumberOfTableValues(num_colors);
+      mode=0;
+      }
+  
+  for (int act=0;act<maxno;act++)
+    {
+      int index1=0;
+      if (act>0)
+	index1=int(levelscale[act]->getValue());
+      
+      int index2=num_colors-1;
+      if (act<maxno-1)
+	index2=int(levelscale[act+1]->getValue());
+
+      if (fmri_mode>0)
+	{
+	  int maxc=55;
+	  if (fmri_mode==2)
+	    maxc=239;
+	  if (index2>maxc)
+	    {
+	      index2=maxc;
+	      if (index1>maxc-1)
+		index1=maxc-1;
+	    }
+	}
+
+      int range=Irange(index2-index1,1,num_colors);
+      double dval=valuescale[act+1]->getValue()-valuescale[act]->getValue();
+      double bval=valuescale[act]->getValue();
+      
+      for (int i=index1;i<=index2;i++)
+	{
+	  double frac=(double(i)-double(index1))/double(range);
+	  double val=Frange(frac*dval+bval,0.0,1.0);
+	  
+	  double c[4];
+	  colormap->GetTableValue(i,c);
+
+	  /*if (i==10 || i==20 || i == 30)
+	    fprintf(stderr,"Mode=%d In Color %d %4.2f %4.2f %4.2f %4.2f\n",mode,i,c[0],c[1],c[2],c[3]);*/
+	  
+	  switch(mode)
+	    {
+	    case 0:
+	      colormap->SetTableValue(i,val,val,val,c[3]);
+	      break;
+	    case 1:
+	      colormap->SetTableValue(i,val,c[1],c[2],c[3]);
+	      break;
+	    case 2:
+	      colormap->SetTableValue(i,c[0],val,c[2],c[3]);
+	      break;		  
+	    case 3:
+	      colormap->SetTableValue(i,c[0],c[1],val,c[3]);
+	      break;
+	    case 4:
+	      colormap->SetTableValue(i,c[0],c[1],c[2],val);
+	      break;
+	    }
+	  colormap->GetTableValue(i,c);
+
+	  /*if (i==10 || i==20 || i == 30)
+	    fpintf(stderr,"Out Color  %d %4.2f %4.2f %4.2f %4.2f\n",i,c[0],c[1],c[2],c[3]);*/
+	}
+    }
+  internal_colormap->DeepCopy(colormap);
+  //  vtkpxColorMapUtil::CopyLookupTable(colormap,internal_colormap);
+  UpdateGraphFromColormap();
+  render_widget->RenderDelay();
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::SetSimpleColormapFromDialog()
+{
+  int option=colormap_type->getIndex();
+  if (colormap==NULL)
+    {
+      return 0;
+    }
+
+  
+
+  switch(option)
+  {
+  case 0 : // Step Color Map
+	  vtkpxColorMapUtil::SetStepColorMap(colormap,scale[0]->getValue(),scale[1]->getValue(),scale[0]->getValue(),scale[1]->getValue(),
+		  num_colors,volume_mode);
+	  vtkpxColorMapUtil::SetStepColorMap(internal_colormap,scale[0]->getValue(),scale[1]->getValue(),min_value,max_value,num_colors,volume_mode);
+	  break;
+  case 1: // Gamma Color Map
+	  vtkpxColorMapUtil::SetGammaColorMap(colormap,scale[0]->getValue(),min_value,max_value,num_colors,volume_mode);
+	  if (internal_colormap!=NULL && colormap!=NULL )
+		  internal_colormap->DeepCopy(colormap);
+
+	  break;
+  case 2: // Hue ColorMap
+	  vtkpxColorMapUtil::SetConstantHueColorMap(colormap,
+		  scale[0]->getValue(),scale[1]->getValue(),scale[2]->getValue(),
+		  scale[3]->getValue(),
+		  min_value,max_value,num_colors,volume_mode);
+	  internal_colormap->DeepCopy(colormap);
+
+	  break;
+  case 3:
+  case 4:
+	  {
+		  int nc=colormap->GetNumberOfColors();
+		  float maxv=55.0;
+		  if (nc==256)
+			  maxv=191.0;
+
+		  vtkpxColorMapUtil::CreateOverlayColorMap(colormap,colormap->GetNumberOfColors(),
+			  scale[0]->getValue(),scale[1]->getValue(),0,maxv,
+			  scale[2]->getValue(),scale[3]->getValue(),scale[4]->getValue(),
+			  volume_mode,(option==3));
+		  internal_colormap->DeepCopy(colormap);
+	  }
+	  break;
+
+  case 6:
+	  vtkpxColorMapUtil::SetRainbowColorMap(colormap,scale[0]->getValue(),scale[1]->getValue(),scale[0]->getValue(),scale[1]->getValue(),
+		  num_colors,volume_mode);
+	  vtkpxColorMapUtil::SetRainbowColorMap(internal_colormap,scale[0]->getValue(),scale[1]->getValue(),min_value,max_value,num_colors,volume_mode);
+	  break;
+
+  case 7:
+	  vtkpxColorMapUtil::SetReverseRainbowColorMap(colormap,scale[0]->getValue(),scale[1]->getValue(),scale[0]->getValue(),scale[1]->getValue(),
+		  num_colors,volume_mode);
+	  vtkpxColorMapUtil::SetReverseRainbowColorMap(internal_colormap,scale[0]->getValue(),scale[1]->getValue(),min_value,max_value,num_colors,volume_mode);
+	  break;
+
+  case 5:
+	  vtkpxColorMapUtil::SetBlackBodyColorMap(colormap,scale[0]->getValue(),scale[1]->getValue(),scale[0]->getValue(),scale[1]->getValue(),
+		  num_colors,volume_mode);
+	  vtkpxColorMapUtil::SetBlackBodyColorMap(internal_colormap,scale[0]->getValue(),scale[1]->getValue(),min_value,max_value,num_colors,volume_mode);
+	  break;
+
+  }
+  
+
+  if (!this->EventManager->isInside())
+      {
+	if (render_widget!=NULL)
+	  render_widget->RenderDelay();
+      }
+
+
+  return TCL_OK;
+}
+
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIColormapEditor::HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev)
+{
+  //  fprintf(stderr,"Handling mouse Button event (nbutton=%d, state=%d x=%d, y=%d\n",nbutton,state,x,y);
+
+  if (nbutton==3 && state==2)
+    {
+      int a=this->activeColorContour+1;
+      if (a>4)
+	a=0;
+      this->SetPickedColorMapControl(a);
+      this->render_widget->RenderDelay();
+    }
+
+
+  if (nbutton!=1 || state>2)
+    return 0;
+
+  // Find which one is active
+  int active=0,done=0;
+  while (active<=4 && done==0)
+    {
+      done=this->contourRep[active]->GetShowControls();
+      if (done==0)
+	++active;
+    }
+
+  if (done==0)
+    return 0;
+
+  // Convert pixels to 3D because these are now 3D Objects
+  vtkCoordinate* coord=vtkCoordinate::New();
+  coord->SetCoordinateSystemToDisplay();
+  coord->SetValue(x,y,0.0);
+  double* out=coord->GetComputedWorldValue(render_widget->getRenderer());
+  
+  double px[3];
+  px[0]=out[0];
+  px[1]=out[1];
+  px[2]=0.0;
+  
+  // Find Closest Point (or -1 if none found 2.0=tolerance)
+  if (state==0)
+    {
+      this->activeShiftPoint=this->contourRep[active]->FindClosestPoint(px,4.0,1);
+      return 1;
+    }
+
+  // Otherwise either drag or reset
+  if (this->activeShiftPoint==-1)
+    return 0;
+
+  this->SetLock(1);
+  int np=this->contourRep[active]->GetNumPoints();
+  int numc=colormap->GetNumberOfTableValues();
+  int sc=(numc/(np-1));
+  
+  // Moving --> Editing Curve
+  if (state==1)
+    {
+      // Change Colormap at this point
+      // ------------------------------------------------------------
+      int pt=this->activeShiftPoint;
+      
+      // Force X-Coordinate Bounds
+      if (pt==0)
+	{
+	  px[0]=this->contourOffset[0];
+	}
+      else if (pt==np-1)
+	{
+	  px[0]=double(this->contourScale[0]*(np-1)*sc+this->contourOffset[0]);
+	}
+      else
+	{
+	  double x0,x1,x2;
+	  this->contourRep[active]->GetPoint(pt-1,x0,x1,x2);
+	  if (px[0]<x0)
+	    px[0]=x0+this->contourScale[0];
+	  this->contourRep[active]->GetPoint(pt+1,x0,x1,x2);
+	  if (px[0]>x0)
+	    px[0]=x0-this->contourScale[0];
+	}
+
+      // Force Y
+      if (px[1]<this->contourOffset[1])
+	px[1]=this->contourOffset[1];
+      if (px[1]>this->contourScale[1])
+	px[1]=this->contourScale[1];
+      
+      this->contourRep[active]->SetPoint(pt,px[0],px[1],px[2],1);
+      if (active==4)
+	{
+	  for (int ia=0;ia<=2;ia++)
+	    this->contourRep[ia]->SetPoint(pt,px[0],px[1],px[2],1);
+	}
+
+
+      this->contourRep[active]->Update();
+      this->render_widget->RenderDelay();
+      // End of Moving
+      return 1;
+    }
+
+  int pt=this->activeShiftPoint;
+  this->activeShiftPoint=-1;
+  
+  int min_p=pt-1; if (min_p<0) min_p=0;
+  int max_p=pt+1; if (max_p==np) max_p=np-1;
+  int gap=max_p-min_p+1;
+
+  double vx[3],vy[3]; // Control Points from 0:gap-1 (0:1, 0:2)
+
+  /*  fprintf(stderr,"\n\n\n Setting Colormap around point %d (%d:%d) gap=%d\n",
+      pt,min_p,max_p,gap);*/
+  
+  for (int ia=0;ia<gap;ia++)
+    {
+      double x0,x1,x2;
+      int ind=min_p+ia;
+      this->contourRep[active]->GetPoint(ind,x0,x1,x2);
+      vx[ia]=(x0-this->contourOffset[0])/this->contourScale[0];
+      vy[ia]=(x1-this->contourOffset[1])/this->contourScale[1];
+      //      fprintf(stderr,"Indexing ia=%d pt=%d (vx=%.2f vy=%.2f)\n",ia,ind,vx[ia],vy[ia]);
+    }
+
+  
+  // Now Change Colormap
+  for (int ia=0;ia<gap-1;ia++)
+    {
+      int xc[2];      double yc[2];
+      xc[0]=int(vx[ia]);    yc[0]=vy[ia];
+      xc[1]=int(vx[ia+1]);  yc[1]=vy[ia+1];
+      
+      if (xc[0]<0)	xc[0]=0;
+      if (xc[0]>=numc)	xc[0]=numc-1;
+      if (xc[1]<0)	xc[1]=0;
+      if (xc[1]>=numc)	xc[1]=numc-1;
+      
+      //      fprintf(stderr,"Interpolating ia=%d (x=%d:%d y=%.2f:%.2f)\n",ia,xc[0],xc[1],yc[0],yc[1]);
+
+      if (xc[1]!=xc[0])
+	{
+	  for (int cl=xc[0];cl<xc[1];cl++)
+	    {
+	      double rgba[4];
+	      colormap->GetTableValue(cl, rgba); 
+	      double w1=double(xc[1]-cl)/double(xc[1]-xc[0]);
+	      double w2=1.0-w1;
+	      double val=w1*yc[0]+w2*yc[1];	      
+
+	      switch(active)
+		{
+		case 0: rgba[0]=val; break;
+		case 1: rgba[1]=val; break;
+		case 2: rgba[2]=val; break;
+		case 3: rgba[3]=val; break;
+		case 4:
+		  rgba[0]=val;
+		  rgba[1]=val;
+		  rgba[2]=val;
+		  break;
+		}
+	      colormap->SetTableValue(cl,rgba);
+	    }
+	}
+    }
+
+  if (this->EventParent!=NULL && this->CallbackNo>0)
+    this->EventParent->HandleEvent(CallbackNo);
+  
+  if (this->CallbackName!=NULL)
+    PXTkApp::executeTclCommand(this->CallbackName);
+  
+  scalar_bar->SetLookupTable(colormap);
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIColormapEditor.h b/bioimagesuite30_src/GUI/vtkpxGUIColormapEditor.h
new file mode 100644
index 0000000..3d121f0
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIColormapEditor.h
@@ -0,0 +1,196 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxvtkColormap.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+
+_Module_Name : vtkpxGUIColormapEditor
+
+
+_Description : Definition of Classes to draw iso-surfaces 
+ 
+               vtkpxGUIColormapEditor()
+
+_Call : 
+
+  
+_References : The Visualization Toolkit: An Object-Oriented
+              Approach to Graphics. 2nd Edition. Prentice-Hall
+	      Schroeder, Martin and Lorensen
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 17th August 2000
+                                
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _vtkpxGUIColormapEditor
+#define _vtkpxGUIColormapEditor
+
+
+#include "pxutil.h"
+#include "pxtkgadgets.h"
+#include "pxtkcomplexwidgets.h"
+#include "pxtkseldialog.h"
+#include "pxtkmenu.h"
+#include "vtkLookupTable.h"
+#include "pxvtkgadgets.h"
+#include "vtkXYPlotActor.h"
+#include "vtkpxGUIComponent.h"
+#include "vtkProperty.h"
+#include "vtkPlaneSource.h"
+#include "vtkPolyDataMapper.h" 
+#include "vtkScalarBarActor.h"
+#include "vtkpxBaseCurve.h"
+
+
+// ****************************************
+// ******* vtkpxGUIColormapEditor Class ********
+// ****************************************
+
+class  vtkpxGUIColormapEditor : public vtkpxGUIComponent
+{
+public:
+
+  static vtkpxGUIColormapEditor *New();
+  vtkTypeMacro(vtkpxGUIColormapEditor,vtkpxGUIComponent);
+  
+  virtual char* Initialize(const char* name,int inside);
+  virtual int   HandleEvent(int );
+  virtual int   HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev);
+
+  virtual vtkLookupTable* GetColormap();
+  virtual void  SetColormap(vtkLookupTable* cmap);
+  virtual void  SetSimpleMode(int simple=0);
+  virtual void  SetVolumeMode(int vol=0);
+  virtual void  SetFmriMode(int fmri=1);
+
+  virtual void  SetRange(int min,int max);
+  virtual void  SetRange(vtkImageData* image);
+  virtual void  SetNumberOfColors(int numc=256);
+  virtual void  SetLock(int lock=1);
+  virtual void  Update();
+
+protected:
+
+  //BTX
+  vtkLookupTable *colormap;
+  vtkLookupTable *internal_colormap;
+  char*           colormap_filename;
+  int             owns_colormap,simple_mode,volume_mode,locked;
+  int             num_colors,fmri_mode,num_decimal_points;
+  float           min_value,max_value;
+  float           auto_min,auto_max;
+  char            data_type[25];
+  int             packed[5];
+  
+  PXVTkTkRenderWidget          *render_widget;
+  PXTkFrame                    *simple_parent;
+  PXTkButton                   *lockunlock;
+  PXTkArrowScale               *scale[5],*levelscale[8],*valuescale[8];
+  PXTkOptionMenu               *colormap_type,*editor_type;
+  PXTkDialog                   *editor_dialog;
+  //  vtkScalarBarActor*           scalar_bar;
+  vtkXYPlotActor*              plot_actor;
+  //ETX
+
+  
+  vtkpxGUIColormapEditor();
+  virtual ~vtkpxGUIColormapEditor();
+  vtkpxGUIColormapEditor(const vtkpxGUIColormapEditor&) {};
+  void operator=(const vtkpxGUIColormapEditor&) {};
+
+  virtual int CreateMenu(PXTkFrame* menubar);
+  virtual int CreateSimpleControls(PXTkFrame* frame);
+  virtual int CreateEditorControls(PXTkFrame* edit);
+  virtual int CreateRenderer(PXTkFrame* frame);
+  virtual int CreateComplexControls(PXTkFrame* frame);
+
+  virtual int  ReadColormap(const char* name);
+  virtual int  SaveColormap(const char* name);
+
+  virtual int  ImportColormap(const char* name);
+  virtual int  ExportColormap(const char* name);
+
+  virtual int  DisplayColormap();
+  virtual int  UpdateGraphFromColormap();
+
+  virtual int  ResetColormap(int controlsonly=0);
+  virtual int  ResetComplexColormap(int controlsonly=0);
+  virtual int  ResetSimpleColormap(int controlsonly=0);
+
+  virtual int  SetColormapFromDialog();
+  virtual int  SetComplexColormapFromDialog(int active=-1);
+  virtual int  SetSimpleColormapFromDialog();
+  virtual int  SetPickedColorMapControl(int picked_value); 
+
+  virtual void AutoSetNumDecimalPoints();
+
+  // Description:
+  // Interactor Stuff
+  //BTX
+  //  vtkGenericRenderWindowInteractor* WidgetInteractor;
+  vtkScalarBarActor *scalar_bar;
+  vtkpxBaseCurve *contourRep_red;
+  vtkpxBaseCurve *contourRep_green;
+  vtkpxBaseCurve *contourRep_blue;
+  vtkpxBaseCurve *contourRep_alpha;
+  vtkpxBaseCurve *contourRep_rgb;
+  vtkpxBaseCurve *contourRep_box;
+
+  // Pointer to all of these
+  vtkpxBaseCurve *contourRep[6];
+  double          contourOffset[3];
+  double          contourScale[3];
+  int             activeShiftPoint;
+  int             activeColorContour;
+  //ETX
+
+
+};
+
+
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIComponent.cpp b/bioimagesuite30_src/GUI/vtkpxGUIComponent.cpp
new file mode 100644
index 0000000..7fb10f4
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIComponent.cpp
@@ -0,0 +1,377 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIComponent.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/07/18 15:04:07 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxGUIComponent.h"
+#include "vtkObjectFactory.h"
+#include "vtkTclUtil.h"
+#include "pxtkapp.h"
+//#include "pxtkanaheadercontrol.h"
+#include "vtkpxGUICallback.h"
+#include <string>
+
+
+char   vtkpxGUIComponent::pxtk_buffer[4000];
+char   vtkpxGUIComponent::pxtk_buffer2[4000];
+char   vtkpxGUIComponent::pxtk_buffer3[4000];
+char   vtkpxGUIComponent::pxtk_buffer4[4000];
+
+
+
+// -----------------------------------------------------------------------
+vtkpxGUIComponent* vtkpxGUIComponent::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIComponent");
+  if(ret)
+      {
+	return (vtkpxGUIComponent*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIComponent;
+}
+// -----------------------------------------------------------------------
+// Construct object with no children.
+vtkpxGUIComponent::vtkpxGUIComponent()
+{
+  this->EventManager=NULL;
+  this->BaseWindow=NULL;
+  this->Initialized=0;
+  this->EventParent=NULL;
+  this->CallbackNo=-1;
+  this->CallbackName=NULL;
+  this->ProgressCommand=NULL;
+  this->LastEvent=-1;
+  this->Buffer="";
+}
+// -----------------------------------------------------------------------
+vtkpxGUIComponent::~vtkpxGUIComponent()
+{
+  if (this->EventManager!=NULL)
+      delete this->EventManager;
+  if (this->BaseWindow!=NULL)
+      delete this->BaseWindow;
+  if (this->CallbackName!=NULL)
+    delete [] this->CallbackName;
+
+  if (this->ProgressCommand!=NULL)
+    delete [] this->ProgressCommand;
+
+}
+// -----------------------------------------------------------------------
+char* vtkpxGUIComponent::Initialize(const char* name,int inside)
+{
+  if (this->BaseWindow==NULL)
+      {
+	this->BaseWindow=new PXTkFrame(NULL,name);
+
+	PXBool createinside=PXFalse;
+	if (inside)
+	    createinside=PXTrue;
+
+	this->EventManager=new PXVTkTkDialog(this,this->BaseWindow,
+					     "vtkpxGUIComponent",createinside);
+	this->EventManager->initDisplay();
+	this->Initialized=1;
+      }
+
+  return GetWidgetName();
+}
+// -----------------------------------------------------------------------
+ char* vtkpxGUIComponent::GetWidgetName()
+{
+  if (this->Initialized==1)
+    return this->EventManager->getMainWindow()->getWidgetName();
+
+  char* line=new char[2];
+  strcpy(line,".");
+  return line;
+}
+// -----------------------------------------------------------------------
+
+int vtkpxGUIComponent::BindMouseEvents(const char* widgetname,int callno1,int callno2)
+{
+  sprintf(pxtk_buffer,"pxtkcallback %d %d",this->EventManager->getHandlerNo(),callno1);
+  sprintf(pxtk_buffer2,"pxtkcallback %d %d",this->EventManager->getHandlerNo(),callno2);
+  return BindMouseEvents(widgetname,pxtk_buffer,pxtk_buffer2);
+}
+// -----------------------------------------------------------------------
+int vtkpxGUIComponent::BindMouseEvents(const char* widgetname,const char* commandname1,const char* commandname2)
+{
+  strcpy(pxtk_buffer2," %x %y");
+  for (int mouse=1;mouse<=3;mouse++)
+      {
+	sprintf(pxtk_buffer,"bind %s <ButtonPress-%d> { %s %d 0 %s %s }",
+		widgetname,mouse,commandname1,mouse,pxtk_buffer2,widgetname);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	
+	sprintf(pxtk_buffer,"bind %s <B%d-Motion> { %s %d 1 %s %s }",
+		widgetname,mouse,commandname1,mouse,pxtk_buffer2,widgetname);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	
+	sprintf(pxtk_buffer,"bind %s <ButtonRelease-%d> { %s %d 2 %s %s }",
+		widgetname,mouse,commandname1,mouse,pxtk_buffer2,widgetname);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+
+	sprintf(pxtk_buffer,"bind %s <Shift-ButtonPress-%d> { %s %d 0 %s %s }",
+		widgetname,mouse,commandname1,mouse+3,pxtk_buffer2,widgetname);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	
+	sprintf(pxtk_buffer,"bind %s <Shift-B%d-Motion> { %s %d 1 %s %s }",
+		widgetname,mouse,commandname1,mouse+3,pxtk_buffer2,widgetname);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	
+	sprintf(pxtk_buffer,"bind %s <Shift-ButtonRelease-%d> { %s %d 2 %s %s }",
+		widgetname,mouse,commandname1,mouse+3,pxtk_buffer2,widgetname);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+
+	sprintf(pxtk_buffer,"bind %s <Control-ButtonPress-%d> { %s %d 0 %s %s }",
+		widgetname,mouse,commandname1,mouse+6,pxtk_buffer2,widgetname);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	
+	sprintf(pxtk_buffer,"bind %s <Control-B%d-Motion> { %s %d 1 %s %s }",
+		widgetname,mouse,commandname1,mouse+6,pxtk_buffer2,widgetname);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	
+	sprintf(pxtk_buffer,"bind %s <Control-ButtonRelease-%d> { %s %d 2 %s %s }",
+		widgetname,mouse,commandname1,mouse+6,pxtk_buffer2,widgetname);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+      }
+  
+  if (strlen(commandname2)>1)
+    {
+      sprintf(pxtk_buffer,"bind %s <Expose> { %s %s }",
+	      widgetname,commandname2,widgetname);
+      PXTkApp::executeTclCommand(pxtk_buffer);
+    }
+
+  return TCL_OK;
+}
+// -----------------------------------------------------------------------
+void vtkpxGUIComponent::SetCallback(vtkpxGUIComponent* comp,int call_no)
+{
+  this->EventParent=comp;
+  this->CallbackNo=call_no;
+}
+// -----------------------------------------------------------------------
+void vtkpxGUIComponent::WatchOn(int dodot)
+{
+  int flag=0;
+  if (dodot)
+    {
+      PXTkApp::executeTclCommand(". config -cursor watch");
+      flag=1;
+    };
+
+  if (this->Initialized)
+    {
+      sprintf(pxtk_buffer,"%s config -cursor watch",this->GetWidgetName());
+      PXTkApp::executeTclCommand(pxtk_buffer);
+      flag=1;
+    }
+
+  if (flag==1)
+    PXTkApp::executeTclCommand("update idletasks");
+}
+// -----------------------------------------------------------------------
+void vtkpxGUIComponent::WatchOff(int dodot)
+{
+  int flag=0;
+  if (dodot)
+    {
+      PXTkApp::executeTclCommand(". config -cursor \"\"");
+      flag=1;
+    };
+
+  if (this->Initialized)
+    {
+      sprintf(pxtk_buffer,"%s config -cursor \"\"",this->GetWidgetName());
+      PXTkApp::executeTclCommand(pxtk_buffer);
+      flag=1;
+    }
+
+  if (flag==1)
+    PXTkApp::executeTclCommand("update idletasks");
+}
+// -----------------------------------------------------------------------
+void vtkpxGUIComponent::Show(int show)
+{
+  if (this->Initialized)
+    {
+      if (show)
+	this->EventManager->popupDialog();
+      else
+	this->EventManager->popdownDialog();
+    }
+}
+
+int vtkpxGUIComponent::IsOpen()
+{
+  if (this->Initialized)
+    {
+      if (this->EventManager->isOpen())
+	return 1;
+    }
+  return 0;
+}
+// -----------------------------------------------------------------------
+void vtkpxGUIComponent::SetCallback(const char* name)
+{
+  if (name==NULL)
+    return;
+
+  if (this->CallbackName!=NULL)
+    delete [] this->CallbackName;
+
+  this->CallbackName=new char[strlen(name)+1];
+  strcpy(this->CallbackName,name);
+}
+// -----------------------------------------------------------------------
+vtkpxGUICallback* vtkpxGUIComponent::AddMethodsToFilter(vtkObject* filter,const char* label)
+{
+  if (filter==NULL || label==NULL)
+    return NULL;
+
+  vtkpxGUICallback* clb=vtkpxGUICallback::New();
+  clb->AttachFilter((vtkProcessObject*)filter,this,label);
+  filter->AddObserver(vtkCommand::StartEvent,clb);
+  filter->AddObserver(vtkCommand::ProgressEvent,clb);
+  filter->AddObserver(vtkCommand::EndEvent,clb);
+
+  return clb;
+
+  
+}
+// -----------------------------------------------------------------------
+void vtkpxGUIComponent::SetProgressCommand(const char* name)
+{
+  if (name==NULL)
+    return;
+
+  if (this->ProgressCommand!=NULL)
+    delete [] this->ProgressCommand;
+
+  this->ProgressCommand=new char[strlen(name)+1];
+  strcpy(this->ProgressCommand,name);
+}
+// -----------------------------------------------------------------------
+void vtkpxGUIComponent::ExecuteProgressMethod(const char* label,float progress)
+{
+  if (this->ProgressCommand==NULL)
+    return;
+
+  if (progress<1.0)
+    sprintf(pxtk_buffer,"%s \"%s\" %f",this->ProgressCommand,label,progress);
+  else
+    sprintf(pxtk_buffer,"%s Done 0.0",this->ProgressCommand);
+
+  PXTkApp::executeTclCommand(pxtk_buffer);
+}
+// -----------------------------------------------------------------------
+char* vtkpxGUIComponent::CreateAnaHeaderControl(const char* name)
+{
+  PXTkFrame* frame=new PXTkFrame(NULL,name);
+  PXTkAnaHeaderControl* ana=new PXTkAnaHeaderControl(NULL,frame);
+  ana->initDisplay();
+  ana->popupDialog();
+  return ana->getMainWindow()->getWidgetName();
+}
+
+
+#ifdef BIOIMAGESUITE3_USE_PYTHON
+#include <vtkPythonUtil.h>
+#include "vtkTclUtil.h"
+
+int vtkpxGUIComponent::vtkpxPythonTkInitialize(int interpaddr)
+{
+/*
+ 4321: - Add a new method of interpreter objects, interpaddr().  This returns
+ 4322: the address of the Tcl interpreter object, as an integer.  Not very
+ 4323: useful for the Python programmer, but this can be called by another C
+ 4324: extension that needs to make calls into the Tcl/Tk C API and needs to
+ 4325: get the address of the Tcl interpreter object.  A simple cast of the
+ 4326: return value to (Tcl_Interp *) will do the trick.
+static PyObject *
+Tkapp_InterpAddr(PyObject *self, PyObject *args)
+{
+
+        if (!PyArg_ParseTuple(args, ":interpaddr"))
+                return NULL;
+
+        return PyInt_FromLong((long)Tkapp_Interp(self));
+}
+
+*/
+  Tcl_Interp* interp = (Tcl_Interp*)interpaddr;
+
+  std::cout << "interp->result: " << interp->result << std::endl;
+  std::cout << "hex of interp: " << interp << std::endl;
+
+  std::cout << "lets run something: expr 4+7 " << interp->result << std::endl;
+  Tcl_Eval(interp, "expr 4+7");
+
+  std::cout << "interp->result: " << interp->result << std::endl;
+
+  int b=PXTkApp::initialize(interp);
+  fprintf(stderr,"b=%d\n",b);
+  PXTkApp::createConsole();
+  return b;
+}
+#else
+int vtkpxGUIComponent::vtkpxPythonTkInitialize(int value)
+{
+  return 0;
+}
+#endif
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIComponent.h b/bioimagesuite30_src/GUI/vtkpxGUIComponent.h
new file mode 100644
index 0000000..2601ce7
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIComponent.h
@@ -0,0 +1,143 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIComponent.h,v $
+  Language:  C++
+  Date:      $Date: 2002/07/18 15:04:57 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIComponent - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkpxGUIComponent_h
+#define __vtkpxGUIComponent_h
+
+#include "bioimagesuite_settings.h"
+
+
+#include "vtkObject.h"
+#include "pxvtktkdialog.h"
+#include "pxtkframe.h"
+#include "pxtkanaheadercontrol.h"
+#include "vtkProcessObject.h"
+
+#include <string>
+class vtkpxGUICallback;
+
+
+class vtkpxGUIComponent : public vtkObject
+{
+public:
+  static vtkpxGUIComponent *New();
+  vtkTypeMacro(vtkpxGUIComponent,vtkObject);
+  
+  virtual char*  Initialize(const char* name,int inside);
+  virtual char*  Initialize(const char* name) { return Initialize(name,1);}
+  virtual char*  GetWidgetName();
+
+  virtual int    HandleEvent(int ) {return TCL_OK;}
+  virtual int    HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* obj) {return 0;}
+  virtual int    HandleMouseButtonEvent(int nbutton,int state,int x,int y) 
+  { return this->HandleMouseButtonEvent(nbutton,state,x,y,this->EventManager);}
+
+  virtual int    BindMouseEvents(const char* widgetname,const char* commandname1,const char* commandname2);
+  virtual int    BindMouseEvents(const char* widgetname,int callno1,int callno2);
+
+  virtual void   SetCallback(vtkpxGUIComponent* comp,int callno);
+  virtual void   SetCallback(const char* CallbackName);
+
+  virtual void WatchOn(int dodot=1);
+  virtual void WatchOff(int dodot=1);
+
+  //BTX
+  virtual PXVTkTkDialog* GetEventManager() { return EventManager;}
+  //ETX
+  virtual int  IsOpen();
+  virtual void Show(int show=1);
+  virtual void Hide() { Show(0);}
+
+  //BTX
+  virtual vtkpxGUICallback* AddMethodsToFilter(vtkObject* filter,const char* label);
+  //ETX
+  virtual void SetProgressCommand(const char* CallbackName);
+  virtual void ExecuteProgressMethod(const char* label,float progress);
+
+  // Description:
+  // Returns the name of tk widget contains analyze header edit control
+  static char* CreateAnaHeaderControl(const char* name);
+
+  // THis is a hack for PythonTkInter -- use with care!
+  static int vtkpxPythonTkInitialize(int value);
+
+
+protected:
+
+  PXTkFrame*         BaseWindow;
+  PXVTkTkDialog*     EventManager;
+  int                Initialized;
+  vtkpxGUIComponent* EventParent;	  
+  int                CallbackNo;
+  int                LastEvent;
+  char*              CallbackName;
+  char*              ProgressCommand;
+  
+
+  vtkpxGUIComponent();
+  virtual ~vtkpxGUIComponent();
+  vtkpxGUIComponent(const vtkpxGUIComponent&) {};
+  void operator=(const vtkpxGUIComponent&) {};
+
+  //BTX
+  static char pxtk_buffer[4000], pxtk_buffer2[4000], pxtk_buffer3[4000], pxtk_buffer4[4000];
+  std::string Buffer;
+  //ETX
+  
+};
+#endif
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIContourStackEditor.cpp b/bioimagesuite30_src/GUI/vtkpxGUIContourStackEditor.cpp
new file mode 100644
index 0000000..8f2e8f5
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIContourStackEditor.cpp
@@ -0,0 +1,1027 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIContourStackEditor.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "pxutil.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataWriter.h"
+#include "pxcontourstack.h"
+#include "pxfpbsplinestack.h"
+#include "pxchamferdistancemap.h"
+#include "vtkpxGUIContourStackEditor.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkpxSplineStackSource.h"
+
+vtkpxGUIContourStackEditor* vtkpxGUIContourStackEditor::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIContourStackEditor");
+  if(ret)
+      {
+	return (vtkpxGUIContourStackEditor*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIContourStackEditor;
+}
+
+// Construct object with no children.
+vtkpxGUIContourStackEditor::vtkpxGUIContourStackEditor()
+{
+  num_contour_stacks=4;
+  for (int i=0;i<CSE_MAX_STACKS;i++)
+      surfaceStack[i]=NULL;
+
+  multisliceGUI=NULL;
+  exportAsSurfaceGUI=NULL;
+  allow_multi_save=PXFalse;
+  owns_surfaces=PXTrue;
+  auto_save_mode=PXTrue;
+  this->CreateHighlights=0;
+}
+
+vtkpxGUIContourStackEditor::~vtkpxGUIContourStackEditor()
+{
+  for (int i=0;i<CSE_MAX_STACKS;i++)
+    if (surfaceStack[i]!=NULL)
+      delete surfaceStack[i];
+}
+/* -------------------------------------------------------------------------*/
+char* vtkpxGUIContourStackEditor::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+  
+  fprintf(stderr,"Initializing 2D Viewer");
+  vtkpxGUI2DImageViewer::Initialize(name,inside);
+
+  return GetWidgetName();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIContourStackEditor::SetCurveControl(vtkpxGUIBaseCurveControl* cont)
+{
+  CurveEditor=cont;
+  // Fot compatibility with vtkpxGUI2DImageViewer
+  Editor=cont;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIContourStackEditor::ResetViewer()
+{
+  if (!(hasImage && this->Initialized))
+      return 0;
+
+  int dim[3];    
+   currentImage->GetDimensions(dim);
+  int numslices=dim[2];
+  double sp[3],ori[3];
+  currentImage->GetSpacing(sp);
+  currentImage->GetOrigin(ori);
+  
+  for (int i=0;i<num_contour_stacks;i++)
+    {
+      if (owns_surfaces)
+	{
+	  if (surfaceStack[i]!=NULL)
+	    delete surfaceStack[i];
+	  surfaceStack[i]=new PXContourStack(numslices);
+	}
+      for (int k=0;k<surfaceStack[i]->getnumcontours();k++)
+	surfaceStack[i]->setzlevel(k,float(k)*sp[2]+ori[2]);
+      if (i==0)
+	surfaceStack[i]->SaveNuages("init.cnt");
+    }
+
+
+
+  last_slice=0;
+  if (multisliceGUI!=NULL)
+      {
+	int newdim[3];     
+	currentImage->GetDimensions(newdim);
+	beginMultislice->setRange(offset,newdim[2]-1+offset);
+	beginMultislice->setValue(offset);
+	endMultislice->setRange(offset,newdim[2]-1+offset);
+	endMultislice->setValue(newdim[2]-1+offset);
+      }
+
+  return vtkpxGUI2DImageViewer::ResetViewer();
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIContourStackEditor::HandleEvent(int event)
+{
+  switch(event)
+      {
+      case 500:
+	{
+	  int ok=1;
+	  int currentstack=CurveEditor->GetCurrentIndex();
+	  if (surfaceStack[currentstack]->getnumpoints()>0)
+	      ok=this->EventManager->questionBox("Loading will delete the current landmark set. Are you sure?");
+	  if (ok)
+	      {
+		char* line=this->EventManager->getOpenFilename("Load Current Stack","Stack Files","*.cnt*");
+		if (line!=NULL)
+		    {
+		      if (strlen(line)>0)
+			  {
+			    strcpy(pxtk_buffer,line);
+			    PXContourStack* temp=new PXContourStack(2);
+
+			    if (temp->LoadNuages(pxtk_buffer))
+				{
+				  for (int k=0;k<surfaceStack[currentstack]->getnumcontours();k++)
+				      {
+					if (k<temp->getnumcontours())
+					    surfaceStack[currentstack]->getcontour(k)->copypoints(temp->getcontour(k));
+					else
+					    surfaceStack[currentstack]->getcontour(k)->DeleteAll();
+				      }
+				  
+				  int currentslice=(int)sliceNumber->getValue();
+				  CurveEditor->SetCollection(surfaceStack[currentstack]->getcontour(currentslice),
+							     currentstack,2,currentslice);
+				  last_slice=currentslice;
+				  CurveEditor->UpdateStatus();
+				}
+			    else
+				{
+				  sprintf(pxtk_buffer,"Failed to load stack %d from %s",currentstack+1,pxtk_buffer);
+				  this->EventManager->messageBox(pxtk_buffer,"Load Failure");
+				}
+			    delete temp;
+			  }
+		    }
+	      }
+	}
+	break;
+	
+      case 502:
+	{
+	  int ok=1;
+	      
+	  int np=0;
+	  for (int i=0;i<num_contour_stacks;i++)
+	    np+=surfaceStack[i]->getnumpoints();
+	  
+	  if (np>0)
+	    ok=this->EventManager->questionBox("Loading will delete your old stacks. Are you sure?");
+	  
+	  if (ok)
+		{
+		  char* line=this->EventManager->getOpenFilename("Load All Stacks","Stack Files","*.01.cnt*");
+		  if (line!=NULL)
+		      {
+			if (strlen(line)>0)
+			    {
+			      strcpy(pxtk_buffer2,line);
+			      char* line2=anaeatsuffix(pxtk_buffer2);
+			      int currentslice=(int)sliceNumber->getValue();
+			      
+			      PXContourStack* temp=new PXContourStack(2);
+
+			      for (int i=0;i<num_contour_stacks;i++)
+				  {
+				    
+				    sprintf(pxtk_buffer,"%s.%02d.cnt",line2,i+1);
+				    if (temp->LoadNuages(pxtk_buffer))
+					{
+					  for (int k=0;k<surfaceStack[i]->getnumcontours();k++)
+					    {
+					      if (k<temp->getnumcontours())
+						surfaceStack[i]->getcontour(k)->copypoints(temp->getcontour(k));
+					      else
+						surfaceStack[i]->getcontour(k)->DeleteAll();
+					    }
+					  
+					  CurveEditor->SetCollection(surfaceStack[i]->getcontour(currentslice),
+								     i,2,currentslice);
+					}
+				    else
+				      {
+					sprintf(pxtk_buffer,"Failed to load stack %d from %s",i+1,pxtk_buffer);
+					this->EventManager->messageBox(pxtk_buffer,"Load Failure");
+				      }
+				  }
+			      delete temp;
+			      last_slice=currentslice;
+			      CurveEditor->UpdateStatus();
+			    }
+		      }
+		}
+	}
+	break;
+	
+      case 501:
+	{
+	  char* line=this->EventManager->getSaveFilename("Save Current Stack","points.cnt","Stack Files","*.cnt*");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		{
+		  strcpy(pxtk_buffer2,line);
+		  int currentstack=CurveEditor->GetCurrentIndex();
+		  UpdateFromEditor(PXTrue);
+		  if (!surfaceStack[currentstack]->SaveNuages(pxtk_buffer2))
+		    {
+		      sprintf(pxtk_buffer,"Failed to save stack %d from %s",currentstack+1,line);
+		      this->EventManager->messageBox(pxtk_buffer,"Save Failure");
+		    }
+		}
+	    }
+	}
+	break;
+	
+      case 503:
+	{
+	  char* line=this->EventManager->getSaveFilename("Save All Stacks","points.01.cnt","Stack Files","*.01.cnt*");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		{
+		  strcpy(pxtk_buffer2,line);
+		  char* line2=anaeatsuffix(pxtk_buffer2);
+		  UpdateFromEditor();
+		  for (int i=0;i<num_contour_stacks;i++)
+		    {
+		      sprintf(pxtk_buffer,"%s.%02d.cnt",line2,i+1);
+		      if (!surfaceStack[i]->SaveNuages(pxtk_buffer))
+			{
+			  sprintf(pxtk_buffer,"Failed to save stack %d from %s",i+1,pxtk_buffer);
+			  this->EventManager->messageBox(pxtk_buffer,"Save Failure");
+			}
+		    }
+		}
+	    }
+	}
+	break;
+	
+      case 504:
+	{
+	  int currentstack=CurveEditor->GetCurrentIndex();
+	  UpdateFromEditor(PXTrue);
+	  int np=surfaceStack[currentstack]->getnumpoints();
+	  sprintf(pxtk_buffer,"Stack %d has %d points",currentstack+1,np);
+	  this->EventManager->messageBox(pxtk_buffer,"Stack Info");
+	}
+	break;
+	
+      case 505:
+	{
+	  PXTkApp::printToConsole("\n\n Area Info\n");
+	  double sp[3];
+	  currentImage->GetSpacing(sp);
+	  int j=CurveEditor->GetCurrentIndex();
+	  float total=0.0;
+	  for (int i=0;i<surfaceStack[j]->getnumcontours();i++)
+	      {
+		float area=0.0;
+		int np=surfaceStack[j]->getcontour(i)->getnumpoints();
+		if (np>2)
+		  {
+		    PXContour* cntr=surfaceStack[j]->getcontour(i);
+		    int wasclosed=cntr->isclosed();
+		    cntr->setclosed(1);
+		    area=cntr->getarea()*sp[0]*sp[1];
+		    cntr->setclosed(wasclosed);
+		    if (area>0.0)
+		      {
+			total+=area*sp[2];
+			sprintf(pxtk_buffer,"slice =%d Area=%6.1f\n",i+offset,area);
+			PXTkApp::printToConsole(pxtk_buffer);
+		      }
+		  }
+	      }
+	  sprintf(pxtk_buffer,"-------------------------------\nTotal Volume  = %6.1f\n",total);
+	  PXTkApp::printToConsole(pxtk_buffer);
+	  PXTkApp::popupConsole();
+	}
+	break;
+
+      case 506:
+      case 507:
+	{
+	  char* line;
+	  if (event==506)
+	    line=this->EventManager->getSaveFilename("Export Current Stack as surface","sur.vtk","vtk files","*.vtk");
+	  else 
+	    line=this->EventManager->getSaveFilename("Export Current Stack as tstack","sur.tstack","tstack files","*.tstack");
+
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		{
+		  strcpy(pxtk_buffer2,line);
+		  int currentstack=CurveEditor->GetCurrentIndex();
+		  UpdateFromEditor(PXTrue);
+		  PXTriangulatedStack* tstack=new PXTriangulatedStack();
+		  PXContourStack* tmp=new PXContourStack();
+		  int numc=tmp->cleancopypoints(surfaceStack[currentstack]);
+		  if (numc>1)
+		    {
+		      tmp->ensureAnticlockwise();
+		      tstack->setfromcontourstack(tmp,0);
+		      double sp[3];currentImage->GetSpacing(sp);
+		      tstack->scalepoints(sp[0],sp[1]);
+		      
+		      if (event==506)
+			{
+			  vtkPolyData* temppoly=vtkPolyData::New();
+			  vtkpxSurfaceUtil::drawtstack(temppoly,tstack);
+			  vtkPolyDataWriter* writer=vtkPolyDataWriter::New();
+			  writer->SetFileName(pxtk_buffer2);
+			  writer->SetInput(temppoly);
+			  this->WatchOn();
+			  writer->Update();
+			  this->WatchOff();
+			  
+			  writer->Delete();
+			  temppoly->Delete();
+			}
+		      else
+			{
+			  int ok=tstack->Save(pxtk_buffer2);
+			  if (!ok)
+			    {
+			      sprintf(pxtk_buffer2,"Failed to save surface in %s",pxtk_buffer2);
+			      this->EventManager->messageBox(pxtk_buffer2,"Export Failure");
+			    }
+			}
+		      delete tstack;
+		    }
+		  else
+		    {
+		      sprintf(pxtk_buffer3,"Failed to save surface in %s",pxtk_buffer2);
+		      this->EventManager->messageBox(pxtk_buffer3,"Insufficient Points");
+		    }
+		  delete tmp;
+		}
+	    }
+	}
+	break;
+
+
+      case 509:
+	this->GetSurfaceFittingParameters();
+	break;
+
+      case 508:
+	{
+	  char* line=this->EventManager->getSaveFilename("Export Current Stack as bspline surface","surface.sur","surface files","*.sur");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		{
+		  strcpy(pxtk_buffer2,line);
+		  int ok=FitAndSaveBSplineSurface(pxtk_buffer2);
+		  if (!ok)
+		    {
+		      sprintf(pxtk_buffer3,"Failed to save surface in %s",pxtk_buffer2);
+		      this->EventManager->messageBox(pxtk_buffer3,"Fitting Failed");
+		    }
+		}
+	    }
+	}
+	this->exportAsSurfaceGUI->popdownDialog();
+
+	break;
+
+      case 519:
+	CreateThresholdStats();
+	break;
+
+      case 520:
+	Operate(0);
+	if (multisliceGUI!=NULL)
+	  multisliceSelect->setIndex(0);
+	break;
+
+      case 521:
+	Operate(0);
+	if (multisliceGUI!=NULL)
+	  multisliceSelect->setIndex(1);
+	break;
+
+      case 522:
+	Operate(0);
+	if (multisliceGUI!=NULL)
+	  multisliceSelect->setIndex(2);
+	break;
+
+      case 523:
+	Operate(0);
+	if (multisliceGUI!=NULL)
+	  multisliceSelect->setIndex(3);
+	break;
+
+      case 530:
+	if (multisliceGUI!=NULL)
+	  Operate(1);
+	break;
+
+      default:
+	vtkpxGUI2DImageViewer::HandleEvent(event);
+      }
+
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIContourStackEditor::ChangeSliceAndFrame(int sl,int fr)
+{
+  if (!hasImage)
+      return;
+
+  if (sl!=-1)
+    sliceNumber->setValue(sl);
+  
+  int currentslice=(int)sliceNumber->getValue()-offset;
+
+  if (this->Editor!=NULL)
+    {
+      if (last_slice!=currentslice)
+	{
+	  for (int i=0;i<num_contour_stacks;i++)
+	    {
+	      if (last_slice!=-1)
+		(CurveEditor->GetCollection(i))->StoreInContour(surfaceStack[i]->getcontour(last_slice),2);
+	      CurveEditor->SetCollection(surfaceStack[i]->getcontour(currentslice),
+					 i,2,currentslice);
+	    }
+	  last_slice=currentslice;
+	  CurveEditor->UpdateStatus();
+	}
+      
+      int bl=(int)sliceNumber->getValue()-offset;
+      int plane=2;
+      this->Editor->SetImage(currentImage,plane,bl);
+    }
+  UpdateViewer();
+  this->UpdateDisplay();
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIContourStackEditor::InitMenus(const char* parentname)
+{
+  PXTkFrame* menuBar=new PXTkFrame(NULL,parentname);
+  PXTkMenuButton* mbut1=new PXTkMenuButton(this->EventManager,menuBar,"Stack",-1,PXTrue);
+  menuBar->addChildren("-side left -expand false ",mbut1);
+  PXTkMenu *stmenu=new PXTkMenu(this->EventManager,mbut1,PXFalse);
+  
+
+  stmenu->addButton("Load Stack",500);
+  stmenu->addButton("Save Stack",501);
+  stmenu->addSeparator();
+  stmenu->addButton("Export .vtk",506);
+  stmenu->addButton("Export .tstack",507);
+  stmenu->addButton("Export .sur",509);
+  stmenu->addSeparator();
+  stmenu->addButton("Area Info",505);
+
+  if (allow_multi_save)
+      {
+	stmenu->addSeparator();
+	stmenu->addButton("Load All Stacks",502);
+	stmenu->addButton("Save All Stacks",503);
+	stmenu->addSeparator();
+      }
+  //stmenu->addCascade("Info",infoMenu);
+
+  PXTkMenuButton* mbut2=new PXTkMenuButton(this->EventManager,menuBar,"Multi-Slice",-1,PXTrue);
+  menuBar->addChildren("-side left -expand false ",mbut2);
+  PXTkMenu *stmenu2=new PXTkMenu(this->EventManager,mbut2,PXFalse);
+
+  stmenu2->addButton("Interpolate",520);
+  stmenu2->addButton("Extract Iso",521);
+  stmenu2->addButton("Auto-Snake",522);
+  stmenu2->addButton("Batch-Snake",523);
+  
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIContourStackEditor::Operate(int apply)
+{
+  if (!hasImage)
+      return;
+  
+  if (apply==0)
+    {
+      if (multisliceGUI==NULL)
+	{
+	  PXTkFrame* polyFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+	  multisliceGUI=new PXTkDialog(this->EventManager,polyFrame,"Multislice Controls",PXFalse);
+	  multisliceGUI->initDisplay();
+	  PXTkFrame* frame=(PXTkFrame*)multisliceGUI->getMainWindow();
+	  
+	  multisliceSelect=new PXTkOptionMenu(multisliceGUI,frame,"Interpolate",-1);
+	  multisliceSelect->addOption("Extract Iso");
+	  multisliceSelect->addOption("Auto-Snake");
+	  multisliceSelect->addOption("Batch-Snake");
+	  multisliceSelect->setIndex(0);
+	  
+	  beginMultislice=new PXTkArrowScale(multisliceGUI,frame,"Begin Slice",-1,PXTrue);
+	  beginMultislice->setRange(offset,99+offset);
+	  beginMultislice->setIncrement(1);
+	  beginMultislice->setResolution(1);
+	  beginMultislice->setLengthWidth(120,8);
+	  beginMultislice->setValue(0);
+	  
+	  endMultislice=new PXTkArrowScale(multisliceGUI,frame,"End Slice",-1,PXTrue);
+	  endMultislice->setRange(0+offset,99+offset);
+	  endMultislice->setIncrement(1);
+	  endMultislice->setResolution(1);
+	  endMultislice->setLengthWidth(120,8);
+	  endMultislice->setValue(99);
+	  
+	  PXTkFrame* fr2=new PXTkFrame(multisliceGUI,frame);
+	  PXTkButton* b1=new PXTkButton(this->EventManager,fr2,"Apply",530);
+	  PXTkButton* b3=new PXTkButton(multisliceGUI,fr2,"Close",3);
+	  frame->addChildren("-side top -expand true -fill x",
+			     multisliceSelect,
+			     beginMultislice->getMainWindow(),
+			     endMultislice->getMainWindow(),
+			     fr2);
+	  fr2->addChildren("-side left -expand true -fill x",b1,b3);
+	}
+      
+      int dim[3];     
+      currentImage->GetDimensions(dim);
+      beginMultislice->setRange(0+offset,dim[2]-1+offset);
+      endMultislice->setRange(0+offset,dim[2]-1+offset);
+      multisliceGUI->popupDialog();
+      return;
+    }
+  
+  
+  if (multisliceGUI==NULL)
+    {
+      this->Operate(0);
+      multisliceGUI->popdownDialog();
+    }
+  
+  if (apply==1)
+    {
+      int begin=(int)beginMultislice->getValue()-offset;
+      int end=  (int)endMultislice->getValue()-offset;
+      int mode=multisliceSelect->getIndex();
+      switch (mode)
+	{
+	case 0:
+	  Interpolate(begin,end);
+	  break;
+	case 1:
+	  Extract(begin,end);
+	  break;
+	case 2:
+	  Snake(begin,end,0);
+	  break;
+	case 3:
+	  Snake(begin,end,1);
+	  break;
+	}
+    }
+  return;
+  
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIContourStackEditor::Interpolate(int begin,int end)
+{
+  if (begin==end)
+    return 0;
+  
+  if (begin>end)
+    {
+      int temp=end;
+      end=begin;
+      begin=temp;
+    }
+  
+  if (end-begin<2)
+    return 0;
+  
+  
+  int currentslice=(int)sliceNumber->getValue();  
+  UpdateFromEditor(PXTrue);
+
+  int currentstack=CurveEditor->GetCurrentIndex();
+  PXContour* cntr1=new PXContour();
+  PXContour* cntr2=new PXContour();
+  
+  cntr1->copypoints(surfaceStack[currentstack]->getcontour(begin));
+  cntr2->copypoints(surfaceStack[currentstack]->getcontour(end));
+
+  if (cntr1->getnumpoints()<3 || cntr2->getnumpoints()<3)
+      {
+	this->EventManager->messageBox("Seed contours do not have enough points");
+	delete cntr1;
+	delete cntr2;
+	return 0;
+      }
+
+  cntr1->Equispace(1.0);
+  cntr2->Equispace(1.0);
+  
+  PXChamferDistanceMap* map1=new PXChamferDistanceMap(cntr1,1);
+  PXChamferDistanceMap* map2=new PXChamferDistanceMap(cntr2,1);
+  
+  for (int slice=begin+1;slice<=end-1;slice++)
+    {
+      int fraction1=end-slice;
+      int fraction2=slice-begin;
+      PXChamferDistanceMap* map=new PXChamferDistanceMap(map1,map2,fraction1,fraction2);
+      PXContour* cntr=map->extractContour();
+      (surfaceStack[currentstack]->getcontour(slice))->copypoints(cntr);
+      this->ChangeSliceAndFrame(slice);
+      this->UpdateDisplay();
+      delete map;
+      delete cntr;
+    }
+  delete map1;
+  delete map2;
+  delete cntr1;
+  delete cntr2;
+
+  UpdateFromEditor(PXTrue);
+  this->ChangeSliceAndFrame(currentslice);
+  return 0;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIContourStackEditor::Snake(int begin,int end,int mode)
+{
+  int currentslice=(int)sliceNumber->getValue();  
+  int temp;
+  if (begin>end)
+      {
+	temp=end;
+	end=begin;
+	begin=temp;
+      }
+
+  if (mode==0)
+      {
+	if (currentslice<begin || currentslice>end)
+	    {
+	      this->EventManager->messageBox("Current Slice not in Range Specified!");
+	      return 0;
+	    }
+	
+	if (begin<currentslice)
+	    {
+	      for (int slice=currentslice-1;slice>=begin;slice-=1)
+		  {
+		    UpdateFromEditor(PXTrue);
+		    this->CopySlice(slice+1,slice);
+		    this->ChangeSliceAndFrame(slice);
+		    CurveEditor->DoSnake(1);
+		    this->UpdateDisplay();
+		  }
+	    }
+	
+	if (end>currentslice)
+	    {
+	      for (int slice=currentslice+1;slice<=end;slice++)
+		  {
+		    UpdateFromEditor(PXTrue);
+		    this->CopySlice(slice-1,slice);
+		    this->ChangeSliceAndFrame(slice);
+		    CurveEditor->DoSnake(1);
+		    this->UpdateDisplay();
+		  }
+	    }
+      }
+  else
+      {
+	for (int slice=begin;slice<=end;slice++)
+	    {
+	      this->ChangeSliceAndFrame(slice);
+	      CurveEditor->DoSnake(1);
+	      this->UpdateDisplay();
+	    }
+      }
+  UpdateFromEditor(PXTrue);
+  this->ChangeSliceAndFrame(currentslice);
+  return 1;
+}
+/* -------------------------------------------------------------------------*/ 
+int vtkpxGUIContourStackEditor::Extract(int begin,int end)
+{
+  int currentslice=(int)sliceNumber->getValue();  
+  int temp;
+  if (begin>end)
+      {
+	temp=end;
+	end=begin;
+	begin=temp;
+      }
+
+
+  if (currentslice<begin || currentslice>end)
+      {
+	this->EventManager->messageBox("Current Slice not in Range Specified!");
+	return 0;
+      }
+
+  int currentstack=CurveEditor->GetCurrentIndex();
+  int np=(CurveEditor->GetCollection(currentstack))->GetNumPoints();
+  if (np<1)
+      {
+	this->EventManager->messageBox("No seed point specified on current slice");
+	return 0;
+      }
+	
+  if (begin<currentslice)
+      {
+	for (int slice=currentslice-1;slice>=begin;slice-=1)
+	    {
+	      UpdateFromEditor(PXTrue);
+	      this->CopySlice(slice+1,slice);
+	      this->ChangeSliceAndFrame(slice);
+	      CurveEditor->DoExtract(1);
+	      this->UpdateDisplay();
+	    }
+      }
+  
+  if (end>currentslice)
+      {
+	for (int slice=currentslice+1;slice<=end;slice++)
+	    {
+	      UpdateFromEditor(PXTrue);
+	      this->CopySlice(slice-1,slice);
+	      this->ChangeSliceAndFrame(slice);
+	      CurveEditor->DoExtract(1);
+	      this->UpdateDisplay();
+	    }
+      }
+
+  UpdateFromEditor(PXTrue);
+  this->ChangeSliceAndFrame(currentslice);
+  return 1;
+}
+/* -------------------------------------------------------------------------*/ 
+int vtkpxGUIContourStackEditor::CopySlice(int source,int target)
+{
+  int currentstack=CurveEditor->GetCurrentIndex();
+  PXContour* dest=surfaceStack[currentstack]->getcontour(target);
+  PXContour* src=surfaceStack[currentstack]->getcontour(source);
+  if (dest!=src)
+      dest->copypoints(src);
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIContourStackEditor::UpdateFromEditor(PXBool currentonly)
+{
+  int currentslice=(int)sliceNumber->getValue();
+
+  if (currentonly)
+      {
+	int currentstack=CurveEditor->GetCurrentIndex();
+	(CurveEditor->GetCollection(currentstack))->StoreInContour(surfaceStack[currentstack]->getcontour(currentslice),2);
+      }
+  else
+      {
+	for (int i=0;i<num_contour_stacks;i++)
+	  (CurveEditor->GetCollection(i))->StoreInContour(surfaceStack[i]->getcontour(currentslice),2);
+      }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIContourStackEditor::CreateThresholdStats()
+{
+  int currentstack=CurveEditor->GetCurrentIndex();
+  UpdateFromEditor(PXTrue);
+
+  PXTkApp::printToConsole("\n\n-------------------------------\n");
+  sprintf(pxtk_buffer,"Area Info Based on Point Set %d\n",currentstack);
+  PXTkApp::printToConsole(pxtk_buffer);
+  PXTkApp::printToConsole("-------------------------------\n");
+
+  
+  vtkpxBaseCurve* templand=vtkpxBaseCurve::New();
+
+  for (int j=0;j<surfaceStack[currentstack]->getnumcontours();j++)
+      {
+	int np=surfaceStack[currentstack]->getcontour(j)->getnumpoints();
+	if (np>2)
+	    {
+	      PXContour* cntr=surfaceStack[currentstack]->getcontour(j);
+	      int wasclosed=cntr->isclosed();
+	      cntr->setclosed(1);
+	      templand->SetFromContour(cntr,2,j);
+	      cntr->setclosed(wasclosed);
+
+	      float mean,sigma;
+	      templand->ExtractVOIProperties(currentImage,2,j,this->CurrentFrame,mean,sigma);
+	      //	      float threshold=mean+2.0*sigma;
+
+	      /*PXVTkImage::thresholdStats(currentImage,2,j,
+		threshold,numin,total);*/
+	      
+	      /*sprintf(pxtk_buffer,"Slice =%d Threshold =%5.1f (mean=%5.1f sigma=%5.1f) Pixels = %d/%d %5.2f\n",
+		      j,threshold,mean,sigma,numin,total,float(numin)/float(total)*100.0);
+	      PXTkApp::printToConsole(pxtk_buffer);*/
+	    }
+      }
+  PXTkApp::popupConsole();
+  templand->Delete();
+  return;
+}
+
+void vtkpxGUIContourStackEditor::ExportToPolyData(vtkPolyData* poly,int stack)
+{
+  if (poly==NULL || this->Initialized==0)
+    return;
+
+  if (stack==-1)
+    stack=CurveEditor->GetCurrentIndex();
+  else
+    stack=Irange(stack,0,num_contour_stacks-1);
+  PXTriangulatedStack* tstack=new PXTriangulatedStack();
+  tstack->setfromcontourstack(surfaceStack[stack],0);
+  vtkpxSurfaceUtil::drawtstack(poly,tstack);
+  delete tstack;
+}
+
+int vtkpxGUIContourStackEditor::CreateObjectMap(vtkImageData* img,int begin,int end)
+{
+  if (img==NULL || currentImage==NULL)
+    return 0;
+
+  if (begin==-1)
+    begin=0;
+  
+  if (end==-1)
+    end=num_contour_stacks-1;
+
+  img->DeepCopy(currentImage);
+
+  int dim[3];
+  img->GetDimensions(dim);
+
+  vtkDataArray* scal=img->GetPointData()->GetScalars();
+  scal->FillComponent(0,0.0);
+
+  int totalp=0;
+
+  for (int st=begin;st<=end;st++)
+    {
+      for (int k=0;k<surfaceStack[st]->getnumcontours();k++)
+      {
+	int np=surfaceStack[st]->getcontour(k)->getnumpoints();
+	if (np>2)
+	    {
+	      int base_offset=k*dim[0]*dim[1];
+	      PXContour* cntr=surfaceStack[st]->getcontour(k);
+	      int wasclosed=cntr->isclosed();
+	      cntr->setclosed(1);
+	      for (int ia=0;ia<dim[0];ia++)
+		for (int ib=0;ib<dim[1];ib++)
+		  {
+		    if (cntr->IsInside(float(ia),float(ib)))
+		      {
+			int index=base_offset+ib*dim[0]+ia;
+			scal->SetComponent(index,0,(1+st)*10);
+			totalp++;
+		      }
+		  }
+	      cntr->setclosed(wasclosed);
+	    }
+      }
+
+      //fprintf(stderr,"st=%d totalp=%d\n",st,totalp);
+
+    }
+  
+
+
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIContourStackEditor::GetSurfaceFittingParameters()
+{
+  if (!hasImage)
+    return;
+
+  if (exportAsSurfaceGUI==NULL)
+    {
+      PXTkFrame* polyFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+      exportAsSurfaceGUI=new PXTkDialog(this->EventManager,polyFrame,"Export As B-spline Surface Controls",PXFalse);
+      exportAsSurfaceGUI->initDisplay();
+      PXTkFrame* frame=(PXTkFrame*)exportAsSurfaceGUI->getMainWindow();
+      
+      surfaceSmoothness=new PXTkOptionMenu(exportAsSurfaceGUI,frame,"Very Low Smoothness",-1);
+      surfaceSmoothness->addOption("Low Smoothness");
+      surfaceSmoothness->addOption("Medium Smoothness");
+      surfaceSmoothness->addOption("Medium High Smoothness");
+      surfaceSmoothness->addOption("High Smoothness");
+      surfaceSmoothness->addOption("Extremely High Smoothness");
+      surfaceSmoothness->setIndex(0);
+      
+      PXTkFrame* fr2=new PXTkFrame(exportAsSurfaceGUI,frame);
+      PXTkButton* b1=new PXTkButton(this->EventManager,fr2,"Apply",508);
+      PXTkButton* b3=new PXTkButton(exportAsSurfaceGUI,fr2,"Close",3);
+      frame->addChildren("-side top -expand true -fill x",
+			 surfaceSmoothness,
+			 fr2);
+      fr2->addChildren("-side left -expand true -fill x",b1,b3);
+      fprintf(stderr,"Here\n");
+    }
+  
+  exportAsSurfaceGUI->popupDialog();
+  return;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIContourStackEditor::FitAndSaveBSplineSurface(const char* filename)
+{
+  float smoothness=2.0;
+  switch (surfaceSmoothness->getIndex())
+    {
+    case 1:
+      smoothness=5.0;
+      break;
+    case 2:
+      smoothness=10.0;
+      break;
+    case 3:
+      smoothness=15.0;
+      break;
+    case 4:
+      smoothness=20.0;
+      break;
+    case 5:
+      smoothness=50.0;
+      break;
+    }
+
+  
+
+  int currentstack=CurveEditor->GetCurrentIndex();
+  UpdateFromEditor(PXTrue);
+
+  double sp[3];currentImage->GetSpacing(sp);
+  float sx=sp[0];
+  float sy=sp[1];
+
+  vtkpxSplineStackSource* sur=vtkpxSplineStackSource::New();
+  int ok=sur->FitToContourStack(surfaceStack[currentstack],smoothness,smoothness/20.0,-1,1);
+
+  if (ok)
+    {
+      for (int i=sur->GetTrimBottom(); i<=sur->GetTrimTop();i++)
+	sur->GetSplineStack()->getspline(i)->scaleshift2D(0,0,sx,sy);
+      
+      int ok2=sur->Save(filename);
+      
+      sur->Delete();
+      return ok2;
+    }
+
+  return ok;
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIContourStackEditor.h b/bioimagesuite30_src/GUI/vtkpxGUIContourStackEditor.h
new file mode 100644
index 0000000..64fd426
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIContourStackEditor.h
@@ -0,0 +1,135 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIContourStackEditor.h,v $
+  Language:  C++
+  Date:      $Date: 2002/07/16 18:54:26 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIContourStackEditor 
+// .SECTION Description
+
+#ifndef __vtkpxGUIContourStackEditor_h
+#define __vtkpxGUIContourStackEditor_h
+
+#include "vtkpxGUI2DImageViewer.h"
+#include "vtkpxGUIBaseCurveControl.h"
+const int CSE_MAX_STACKS=5;
+//BTX
+class PXContourStack;
+//ETX
+
+
+class  vtkpxGUIContourStackEditor : public vtkpxGUI2DImageViewer {
+  
+public:
+
+  static vtkpxGUIContourStackEditor *New();
+  vtkTypeMacro(vtkpxGUIContourStackEditor,vtkpxGUI2DImageViewer);
+  
+  // Initialize Display  
+  virtual char*  Initialize(const char* name,int inside);
+  //  virtual void   Update();
+  
+  virtual int  ResetViewer();
+  virtual int  HandleEvent(int eventno);
+
+  void Operate(int mode);
+  void GetSurfaceFittingParameters();
+  int  FitAndSaveBSplineSurface(const char* filename);
+
+  int  Interpolate(int begin,int end);
+  int  Snake(int begin,int end,int mode);
+  int  Extract(int begin,int end);
+  int  CopySlice(int source,int target);
+  void UpdateFromEditor(PXBool currentonly=PXFalse);
+
+
+  virtual void SetCurveControl(vtkpxGUIBaseCurveControl* cont);
+  virtual void InitMenus(const char* parentname);
+  virtual void ExportToPolyData(vtkPolyData* poly,int stack);
+
+  virtual int CreateObjectMap(vtkImageData* img,int begin,int end);
+
+
+protected:
+
+  vtkpxGUIContourStackEditor();
+  virtual ~vtkpxGUIContourStackEditor();
+
+  vtkpxGUIBaseCurveControl* CurveEditor;
+
+  PXContourStack* surfaceStack[CSE_MAX_STACKS];
+  //BTX
+  PXBool owns_surfaces,allow_multi_save,auto_save_mode;
+  int num_contour_stacks,last_slice;
+  PXTkDialog* multisliceGUI;
+  PXTkDialog* exportAsSurfaceGUI;
+
+  PXTkMenu*       optionMenu;
+  PXTkOptionMenu* multisliceSelect;
+  PXTkArrowScale  *beginMultislice,*endMultislice;
+  PXTkOptionMenu*  surfaceSmoothness;
+  //ETX
+
+  virtual void ChangeSliceAndFrame(int sl=-1,int fr=-1);
+  virtual void CreateThresholdStats();
+
+
+  // Description:
+  // Export as B-Spline
+  
+
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUICurveImageEditor.cpp b/bioimagesuite30_src/GUI/vtkpxGUICurveImageEditor.cpp
new file mode 100644
index 0000000..b589c69
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUICurveImageEditor.cpp
@@ -0,0 +1,380 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+#include "vtkpxAnalyzeImageSource.h"
+#include "vtkpxGUICurveImageEditor.h"
+#include "vtkpxGUIMosaicViewer.h"
+#include "pxutil.h"
+#include "vtkActor.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkAssembly.h"
+#include "vtkRenderer.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxImageExtract.h"
+#include "vtkSphereSource.h"
+#include "vtkTransformPolyDataFilter.h"
+#include "vtkIdentityTransform.h"
+#include "vtkMath.h"
+#include "vtkPoints.h"
+#include "vtkTransform.h"
+
+// 	$Id: vtkpxGUICurveImageEditor.cpp,v 1.2 2004/03/01 18:20:58 xenios Exp xenios $	
+
+
+vtkpxGUICurveImageEditor* vtkpxGUICurveImageEditor::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUICurveImageEditor");
+  if(ret)
+      {
+	return (vtkpxGUICurveImageEditor*)ret;
+      }
+  return new vtkpxGUICurveImageEditor;
+}
+
+// Construct object with no children.
+vtkpxGUICurveImageEditor::vtkpxGUICurveImageEditor()
+{
+  this->ImageViewer=NULL;
+  enable_curve=PXTrue;
+  enable_labels=PXFalse;
+  enable_list=PXFalse;
+}
+
+vtkpxGUICurveImageEditor::~vtkpxGUICurveImageEditor()
+{
+  if (this->ImageViewer!=NULL)
+    this->ImageViewer->Delete();
+  if (this->image!=NULL)
+    this->image->Delete();
+}
+/* -------------------------------------------------------------------------*/
+char* vtkpxGUICurveImageEditor::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+    return GetWidgetName();
+
+
+  vtkpxGUIComponent::Initialize(name,inside);
+
+  PXTkFrame* baseFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+
+  baseFrame->bindCallback("<Delete>",204);
+
+  // Menu Stuff
+  // ----------
+  PXTkFrame* menubar=new PXTkFrame(this->EventManager,baseFrame);
+  baseFrame->addChildren("-side top -expand false -fill x",menubar);
+
+
+  PXTkMenuButton* but0=new PXTkMenuButton(this->EventManager,menubar,"Image",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but0);
+
+  PXTkMenu *menu0=new PXTkMenu(this->EventManager,but0,PXFalse);
+  menu0->addButton("Load",700);
+  menu0->addSeparator();
+  if (this->EventParent)
+    menu0->addButton("Close",3);
+  else
+    menu0->addButton("Exit",1);
+
+
+  PXTkMenuButton* but1=new PXTkMenuButton(this->EventManager,menubar,"Curve",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but1);
+  
+  PXTkMenu *menu1=new PXTkMenu(this->EventManager,but1,PXFalse);
+  menu1->addButton("New",100);
+  menu1->addSeparator();
+  menu1->addButton("Load",101);
+  menu1->addButton("Save",102);
+
+  
+  PXTkMenuButton* but2=new PXTkMenuButton(this->EventManager,menubar,"Edit",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but2);
+  PXTkMenu *menu2=new PXTkMenu(this->EventManager,but2,PXFalse);
+  menu2->addButton("Delete Last Point",204);
+  menu2->addButton("Delete All Points",100);
+
+  PXTkMenuButton* but24=new PXTkMenuButton(this->EventManager,menubar,"Color",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but24);
+  PXTkMenu *menu24=new PXTkMenu(this->EventManager,but24,PXFalse);
+  menu24->addButton("Landmark Color",400);
+  menu24->addButton("Highlight Color",401);
+
+  PXTkMenuButton* but6=new PXTkMenuButton(this->EventManager,menubar,"Curve",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but6);
+  
+  PXTkMenu *menu6=new PXTkMenu(this->EventManager,but6,PXFalse);
+  menu6->addButton("Copy  Point Set",590);
+  menu6->addButton("Paste Point Set",591);
+  menu6->addButton("Paste Curve (2D)",592);
+  menu6->addSeparator();
+  menu6->addButton("Create Circle",596);
+  menu6->addButton("Remove Loops",597);
+  menu6->addButton("Smooth",602);
+  
+  PXTkMenuButton* but62=new PXTkMenuButton(this->EventManager,menubar,"Resample",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but62);
+  PXTkMenu *menu62=new PXTkMenu(this->EventManager,but62,PXFalse);
+  menu62->addButton("Equispace",604);
+  menu62->addButton("Equispace 1.0",595);
+  menu62->addButton("Equispace 2.0",598);
+  menu62->addButton("Sample x2",600);
+  menu62->addButton("Sample x8",599);
+  menu62->addButton("Subsample x2",601);
+  
+    
+  PXTkMenuButton* but7=new PXTkMenuButton(this->EventManager,menubar,"Operation",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but7);
+  
+  PXTkMenu *menu7=new PXTkMenu(this->EventManager,but7,PXFalse);
+  menu7->addButton("Area",605);
+  menu7->addButton("Image Stats",606);
+  menu7->addButton("Threshold",612);
+  menu7->addSeparator();
+  menu7->addButton("Extract",609);
+  menu7->addButton("Snake",610);
+
+
+
+  // Other Stuff 
+  // --------------
+  // Collection Properties 
+
+  PXTkFrame* viewerFrame=new PXTkFrame(this->EventManager,baseFrame);
+  baseFrame->addChildren("-side left -expand true -fill both -padx 2 -pady 2",viewerFrame);
+
+  PXTkFrame* checkFrame=new PXTkFrame(this->EventManager,baseFrame);
+  baseFrame->addChildren("-side left -expand f -fill x -padx 2 -pady 2",checkFrame);
+
+  this->ImageViewer=vtkpxGUIMosaicViewer::New();
+  this->ImageViewer->SetSingleSliceMode();
+  this->ImageViewer->SetOffset(1);
+  this->ImageViewer->SetEditor(this);
+  this->ImageViewer->SetMouseToEditor(1);
+  this->ImageViewer->Initialize(viewerFrame->getWidgetName(),1);
+  
+  currentCollection=new PXTkOptionMenu(this->EventManager,checkFrame,"Point Set 1",500);
+  for (int i=1;i<num_collections;i++)
+    {
+      sprintf(lamstring,"Point Set %d",i+1);
+      currentCollection->addOption(lamstring);
+    }
+  checkFrame->addChildren("-side top -expand f -fill x  -pady 1",currentCollection);
+
+  curveMode=new PXTkOptionMenu(this->EventManager,checkFrame,"Points",110);
+  curveMode->addOption("Open   Curve");
+  curveMode->addOption("Closed Curve");
+  curveMode->setIndex(1);
+
+  scaleMode=new PXTkOptionMenu(this->EventManager,checkFrame,"Size=0.25",111);
+  for (float s=0.50;s<=2.50;s+=0.25)
+      {
+	sprintf(pxtk_buffer,"Size=%3.2f",s);
+	scaleMode->addOption(pxtk_buffer);
+      }
+  int sc=int(landmarkCollection->GetPointScale()/0.25)-1;
+  scaleMode->setIndex(sc);
+
+  displayCollection=new PXTkCheckButton(this->EventManager,checkFrame,"Show",501);
+  displayCollection->setState(showCollection[0]);
+  
+  message=new PXTkLabel(this->EventManager,checkFrame,"Num");
+  message->configure("-relief","ridge");
+
+  checkFrame->addChildren("-side top -expand f -fill x  -pady 1",curveMode,scaleMode,displayCollection,message);
+
+  mouseMode=new PXTkOptionMenu(this->EventManager,checkFrame,"Disabled  ",502);
+  mouseMode->addOption("Pick Mode");
+  mouseMode->addOption("Auto Mode");
+  mouseMode->addOption("Add  Mode");
+  mouseMode->addOption("Cont-Add Mode");
+  mouseMode->setIndex(0);
+  checkFrame->addChildren("-side top -expand f -fill x  -pady 1",mouseMode);
+
+  PXTkButton* updateButton=new PXTkButton(this->EventManager,checkFrame,"Update",701);
+  checkFrame->addChildren("-side top -expand f -fill x -padx 2 -pady 2",updateButton);
+
+  UpdateStatus();
+
+  fprintf(stderr,"This->Initalized=%d\n",this->Initialized);
+  return GetWidgetName();
+}
+
+/* -------------------------------------------------------------------------*/ 
+void vtkpxGUICurveImageEditor::SetRenderer(vtkRenderer* ren,int num)
+{
+  if (this->ImageViewer==NULL)
+    return;
+
+  num=0;
+  if (renderer[num]!=NULL || ren==NULL)
+    return;
+
+  ren=this->ImageViewer->GetRenderer();
+  vtkpxGUIBaseCurveControl::SetRenderer(ren,0);
+}
+/* -------------------------------------------------------------------------*/
+int  vtkpxGUICurveImageEditor::HandleEvent(int event)
+{
+  if (!this->Initialized)
+      return TCL_OK;
+
+  if (event<10)
+      return this->EventManager->handleDirectEvent(event);
+
+  if (event<700)
+    return vtkpxGUIBaseCurveControl::HandleEvent(event);
+
+  if (event==700)
+    {
+      char* line=this->EventManager->getOpenFilename("Image File Name","Analyze Images","*.hdr*");
+      if (line!=NULL)
+	{
+	  if (strlen(line)>0)
+	    {
+	      strcpy(pxtk_buffer,line);
+	      vtkpxAnalyzeImageSource* ana=vtkpxAnalyzeImageSource::New();
+	      int ok=ana->Load(pxtk_buffer);
+	      if (ok!=0)
+		this->SetImage(ana->GetOutput(),ana->GetOrientation());
+	      ana->Delete();
+	    }
+	}
+    }
+  
+  if (event==701)
+    {
+      if (this->EventParent!=NULL && this->CallbackNo>0)
+	this->EventParent->HandleEvent(CallbackNo);
+    }
+  
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+void  vtkpxGUICurveImageEditor::SetSpacingOrigin(double sp[3],double ori[3])
+  {
+  if (this->image==NULL)
+    return;
+
+  this->image->GetSpacing(sp);
+  this->image->GetOrigin(ori);
+  vtkpxGUIBaseCurveControl::SetSpacingOrigin(sp,ori);
+}
+
+/* -------------------------------------------------------------------------*/
+
+
+/*      for (int i=0;i<num_collections;i++)
+	{
+	  allCollections[i]->SetShowControls(1);
+	  allCollections[i]->SetShowCurve(1);
+	}
+*/
+
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUICurveImageEditor::SetImage(vtkImageData* img,int plane,int level)
+{
+  if (img != this->ImageViewer->GetImage())
+    {
+      this->ImageViewer->SetImage(img,plane);
+      this->ImageViewer->UpdateAllViewers();
+    }
+
+  if (this->renderer[0]==NULL)
+    this->SetRenderer(this->ImageViewer->GetRenderer(),0);
+
+  vtkpxGUIBaseCurveControl::SetImage(this->ImageViewer->GetImage(),2,level);
+
+  //fprintf(stderr,"Image Set image=%d, render=%d\n",(int)this->image,(int)this->renderer[0]);
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUICurveImageEditor::SetPlaneLevel(int plane,int level)
+{
+  image_plane=2; // Force XY Plane for editing 
+  image_level=level;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUICurveImageEditor::SetLookupTable(vtkLookupTable* lookuptable)
+{
+  currentColormap=lookuptable;
+  if (this->ImageViewer!=NULL)
+    this->ImageViewer->SetLookupTable(lookuptable);
+  if (backupColormap==NULL)
+    backupColormap=vtkLookupTable::New();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUICurveImageEditor::UpdateStatus()
+{
+  if (!this->Initialized)
+    return;
+  
+  sprintf(pxtk_buffer,"NP=%d",
+	  landmarkCollection->GetNumPoints());
+  message->setText(pxtk_buffer);
+}
+/* -------------------------------------------------------------------------*/
+vtkpxGUIMosaicViewer* vtkpxGUICurveImageEditor::GetImageViewer()
+{
+  if (this->ImageViewer==NULL)
+    {
+      fprintf(stderr,"Likely Error Here\n");
+      return NULL;
+    }
+  else
+    return this->ImageViewer;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUICurveImageEditor::UpdateAllViewers()
+{
+  if (!this->Initialized)
+    return 0;
+
+  if (showCollection[current_collection]==PXTrue)
+    {
+      highlightData->Update();
+      landmarkCollection->Update();
+    }
+  
+
+    this->ImageViewer->UpdateDisplay();
+    return 1;
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUICurveImageEditor.h b/bioimagesuite30_src/GUI/vtkpxGUICurveImageEditor.h
new file mode 100644
index 0000000..ae4049c
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUICurveImageEditor.h
@@ -0,0 +1,97 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUICurveImageEditor.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 17:58:45 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUICurveImageEditor - Base Image Viewer
+// .SECTION Description
+
+#ifndef __vtkpxGUICurveImageEditor_h
+#define __vtkpxGUICurveImageEditor_h
+
+#include "vtkpxGUIBaseCurveControl.h"
+class vtkpxGUIMosaicViewer;
+
+class vtkpxGUICurveImageEditor : public vtkpxGUIBaseCurveControl 
+{
+public:
+
+  static vtkpxGUICurveImageEditor *New();
+  vtkTypeMacro(vtkpxGUICurveImageEditor,vtkpxGUIBaseCurveEditor);
+  
+  // Initialize Display  
+  virtual char*  Initialize(const char* name,int inside);
+  virtual void   SetRenderer(vtkRenderer *rendererer,int num);
+  virtual void   SetSpacingOrigin(double sp[3],double ori[3]);
+  virtual void   SetImage(vtkImageData* image,int plane=0,int level=0);
+  virtual void   SetPlaneLevel(int plane,int level);
+  virtual void   SetLookupTable(vtkLookupTable* lookuptable);
+  virtual int    HandleEvent(int);
+  virtual void   UpdateStatus();
+  virtual int    UpdateAllViewers();
+  vtkpxGUIMosaicViewer* GetImageViewer();
+  
+protected:
+
+  vtkpxGUICurveImageEditor();
+  virtual ~vtkpxGUICurveImageEditor();
+
+  vtkpxGUIMosaicViewer* ImageViewer;
+
+};
+
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIFemPostControl.cpp b/bioimagesuite30_src/GUI/vtkpxGUIFemPostControl.cpp
new file mode 100644
index 0000000..45bee38
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIFemPostControl.cpp
@@ -0,0 +1,980 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// 	$Id: vtkpxGUIFemPostControl.cpp,v 1.1 2003/05/28 16:42:54 papad Exp papad $	
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkpxGUIFemPostControl.h"
+#include "vtkpxUtil.h"
+#include "vtkActor.h"
+#include "vtkAssembly.h"
+#include "vtkRenderer.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxFemSolid.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkImageData.h"
+#include "vtkpxGUI4DRenderer.h"
+#include "vtkCollection.h"
+#include "vtkActorCollection.h"
+#include "vtkTransformPolyDataFilter.h"
+#include "vtkTransform.h"
+#include "vtkRenderWindow.h"
+#include "vtkpxBaseCurve.h"
+#include "vtkProperty.h"
+#include "vtkPoints.h"
+#include "pxabaqussolid.h"
+
+/* -------------------------------------------------------------------------*/
+vtkpxGUIFemPostControl* vtkpxGUIFemPostControl::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIFemPostControl");
+  if(ret)
+    {
+      return (vtkpxGUIFemPostControl*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIFemPostControl;
+}
+
+// ----------------------------------------------------------------------------
+vtkpxGUIFemPostControl::vtkpxGUIFemPostControl()
+{
+  for (int j=0;j<TSP_MAX_RENDERERS;j++)
+    {
+      this->MultiRenderer[j]=NULL;
+      this->Renderer[j]=NULL;
+      this->wireframemode[j]=0;
+      this->solidActor[j]=NULL;
+    }
+  
+  this->CurrentFrame=0;
+  this->NumberOfFrames=0;
+  this->ActualNumberOfFrames=0;
+  this->scalingTransformation=vtkTransform::New();
+  this->scalingTransformation->Identity();
+  this->transformFilterCollection=NULL;
+  this->solidCollection=NULL;
+  this->solidActorCollection=NULL;
+  this->currentSolid=NULL;
+
+  this->currentImageNumberOfFrames=0;
+  this->currentOrientation=0;
+  this->displayMode=1;
+  
+  study_filename=new char[20];
+  sprintf(study_filename,"unnamed.sld");
+
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->ReferencePoint[ia]=0.0;
+      this->ScaleFactor[ia]=1.0;
+    }
+}
+// ----------------------------------------------------------------------------
+vtkpxGUIFemPostControl::~vtkpxGUIFemPostControl()
+{
+  
+  if (this->solidCollection!=NULL)
+    this->solidCollection->Delete();
+
+  if (this->transformFilterCollection!=NULL)
+    this->transformFilterCollection->Delete();
+
+  if (this->solidActorCollection==NULL)
+    this->solidActorCollection->Delete();
+
+  // Set to NULL to avoid deleting by parent
+  this->currentSolid=NULL;
+  for (int j=0;j<TSP_MAX_RENDERERS;j++)
+    this->solidActor[j]=NULL;
+    
+  delete [] study_filename;
+  this->scalingTransformation->Delete();
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxGUIFemPostControl::InitializeSolids()
+{
+  this->solidCollection=vtkCollection::New();
+  this->solidActorCollection=vtkActorCollection::New();
+  this->transformFilterCollection=vtkCollection::New();
+}
+// ----------------------------------------------------------------------------
+void vtkpxGUIFemPostControl::ResetSolids()
+{
+  this->NumberOfFrames=this->currentImageNumberOfFrames;
+  this->CreateFrames(this->NumberOfFrames);
+  for (int i=1;i<this->NumberOfFrames;i++)
+    this->UpdateFrame(i);
+  this->UpdateFrame(0);
+}
+
+// ----------------------------------------------------------------------------
+void vtkpxGUIFemPostControl::CreateFrames(int numframes)
+{
+  if (numframes<this->ActualNumberOfFrames)
+    return;
+
+  if (numframes>this->MultiRenderer[0]->GetNumberOfFrames())
+    numframes=this->MultiRenderer[0]->GetNumberOfFrames();
+  if (numframes<1)
+    numframes=1;
+  
+  for (int fr=this->ActualNumberOfFrames;fr<numframes;fr++)
+    {
+      //      fprintf(stderr,"FEM Control :: Creating Frame =%d\n",fr);
+      vtkpxFemSolid* solid=vtkpxFemSolid::New();
+      solid->SetWarpMode(1);
+      this->solidCollection->AddItem(solid);
+      if (fr==0)
+	this->currentSolid=solid;
+
+      vtkTransformPolyDataFilter* trf=vtkTransformPolyDataFilter::New();
+      this->transformFilterCollection->AddItem(trf);
+      trf->SetInput(solid->GetOutput());
+      trf->SetTransform(this->scalingTransformation);
+      trf->Update();
+
+      for (int r=0;r<TSP_MAX_RENDERERS;r++)
+	{
+	  vtkActor* tempActor=vtkActor::New();
+	  this->solidActorCollection->AddItem(tempActor);
+	  
+	  if (this->MultiRenderer[r]!=NULL)
+	    {
+	      vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+	      map->SetInput(trf->GetOutput());
+		  
+	      tempActor->SetMapper(map);
+	      if (displayMode)
+		tempActor->SetVisibility(1);
+	      else
+		tempActor->SetVisibility(0);
+	      
+	      if (wireframemode[r]==1)
+		{
+		  tempActor->GetProperty()->SetRepresentationToWireframe();
+		  tempActor->GetProperty()->SetLineWidth(2.0);
+		  tempActor->GetProperty()->SetAmbient(1.0);
+		  tempActor->GetProperty()->SetDiffuse(0.0);
+		  tempActor->GetProperty()->SetSpecular(0.0);
+		}
+	      map->Delete();
+	      this->MultiRenderer[r]->GetRendererForFrame(fr)->AddActor(tempActor);
+	      if (fr==0)
+		this->solidActor[r]=tempActor;
+	    }
+	}
+    }
+
+  this->ActualNumberOfFrames=numframes;
+  
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIFemPostControl::UpdateFrame(int frame)
+{
+  if (frame>=this->ActualNumberOfFrames)
+    return;
+  
+  // Image Slice Ortho Slice First 
+  int index=frame;
+  int index2=index*TSP_MAX_RENDERERS;
+
+  this->currentSolid=(vtkpxFemSolid*)this->solidCollection->GetItemAsObject(index);
+  for (int r=0;r<TSP_MAX_RENDERERS;r++)
+    {
+      solidActor[r]=(vtkActor*)this->solidActorCollection->GetItemAsObject(index2);
+      ++index2;
+    }
+    
+  for (int rr=0;rr<TSP_MAX_RENDERERS;rr++)
+    {
+      if (this->MultiRenderer[rr]!=NULL)
+	this->Renderer[rr]=this->MultiRenderer[rr]->GetRendererForFrame(frame);
+    }
+
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIFemPostControl::ChangeFrame(int newframe)
+{
+  newframe=Irange(newframe,0,this->NumberOfFrames-1);
+  if (newframe==this->CurrentFrame)
+    return;
+  this->CurrentFrame=newframe;
+}
+// -------------------------------------------------------------------------
+
+char* vtkpxGUIFemPostControl::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+    return GetWidgetName();
+
+  this->InitializeSolids();
+
+  vtkpxGUIComponent::Initialize(name,inside);
+  PXTkFrame* mFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+
+  showHide=new PXTkCheckButton(this->EventManager,mFrame,"Show",401);
+  showHide->setState(PXTrue);
+  statusLine1=new PXTkLabel(this->EventManager,mFrame,"No Surface");
+  statusLine2=new PXTkLabel(this->EventManager,mFrame,"0 pts, 0 elements");
+  mFrame->addChildren("-side top -expand false -fill x -pady 0 ",showHide,statusLine1,statusLine2);
+
+  for (int i=0;i<=2;i++)
+    {
+      PXTkFrame* f=new PXTkFrame(this->EventManager,mFrame);
+      mFrame->addChildren("-side top -expand false -fill x -pady 0 ",f);
+      PXTkLabel* l=NULL;
+      PXTkOptionMenu* menu=NULL;
+      switch (i)
+	{
+	case 0:
+	  l=new PXTkLabel(this->EventManager,f,"Mode:");
+	  modeMenu=new PXTkOptionMenu(this->EventManager,f,"None",400);
+	  modeMenu->addOption("PiesBW");
+	  modeMenu->addOption("Pies");
+	  modeMenu->addOption("Strains");
+	  modeMenu->addOption("HSV-Strain");
+	  menu=modeMenu;
+	  break;
+	case 1:
+	  l=new PXTkLabel(this->EventManager,f,"Plot:");
+	  plotMenu=new PXTkOptionMenu(this->EventManager,f,"S1",400);
+	  plotMenu->addOption("S2");
+	  plotMenu->addOption("S3");
+	  plotMenu->addOption("S4");
+	  plotMenu->addOption("S5");
+	  plotMenu->addOption("S6");
+	  menu=plotMenu;
+	  break;
+	case 2:
+	  l=new PXTkLabel(this->EventManager,f,"Resolution:");
+	  resolutionMenu=new PXTkOptionMenu(this->EventManager,f,"Elements",400);
+	  resolutionMenu->addOption("Pies");
+	  menu=resolutionMenu;
+	  break;
+	}
+      f->addChildren("-side left -expand f -fill x",l,menu);
+    }
+
+
+  // ---------- scale stuff -------------
+  PXTkLabelFrame* scFrame=new PXTkLabelFrame(this->EventManager,mFrame,"Scale");
+  mFrame->addChildren("-side top -expand false -fill x",scFrame);
+  for (int ia=0;ia<=2;ia++)
+    {
+      PXTkFrame* f=new PXTkFrame(this->EventManager,scFrame);
+      scFrame->addChildren("-side top -expand false -fill x -pady 0 ",f);
+      PXTkLabel* l=NULL;
+      switch (ia)
+	{
+	case 0:
+	  l=new PXTkLabel(this->EventManager,f,"scale x:");
+	  break;
+	case 1:
+	  l=new PXTkLabel(this->EventManager,f,"scale y:");
+	  break;
+	case 2:
+	  l=new PXTkLabel(this->EventManager,f,"scale z:");
+	  break;
+	}
+      scaleFactorEntry[ia]=new PXTkEntry(this->EventManager,f);
+      scaleFactorEntry[ia]->setText("1.0");
+      f->addChildren("-side left -expand f -fill x",l,scaleFactorEntry[ia]);
+    }
+  PXTkButton* scalebut=new PXTkButton(this->EventManager,scFrame,"Scale Solids",807);
+  scFrame->addChildren("-side top -expand f -fill x -pady 1 ",scalebut);
+
+  // ---------- reslice stuff -------------
+  PXTkLabelFrame* f3=new PXTkLabelFrame(this->EventManager,mFrame,"Reslicing Parameters");
+  mFrame->addChildren("-side top -expand false -fill x",f3);  
+
+  for (int k=0;k<=2;k++)
+    {
+      PXTkFrame* f=new PXTkFrame(this->EventManager,f3);
+      f3->addChildren("-side top -expand false -fill x -pady 0 ",f);
+      PXTkLabel* l=NULL;
+      PXTkOptionMenu* menu=NULL;
+      switch (k)
+	{
+	case 0:
+	  l=new PXTkLabel(this->EventManager,f,"Slices:");
+	  numslicesMenu=new PXTkOptionMenu(this->EventManager,f,"2",-1);
+	  numslicesMenu->addOption("3");
+	  numslicesMenu->addOption("4");
+	  numslicesMenu->addOption("5");
+	  numslicesMenu->addOption("6");
+	  numslicesMenu->addOption("7");
+	  numslicesMenu->addOption("8");
+	  numslicesMenu->addOption("9");
+	  numslicesMenu->addOption("10");
+	  numslicesMenu->setIndex(1);
+	  menu=numslicesMenu;
+	  break;
+	case 1:
+	  l=new PXTkLabel(this->EventManager,f,"Sectors:");
+	  numsectorsMenu=new PXTkOptionMenu(this->EventManager,f,"8",-1);
+	  numsectorsMenu->addOption("12");
+	  numsectorsMenu->addOption("16");
+	  numsectorsMenu->addOption("4");
+	  menu=numsectorsMenu;
+	  break;
+	case 2:
+	  l=new PXTkLabel(this->EventManager,f,"Transmural:");
+	  numtransmuralMenu=new PXTkOptionMenu(this->EventManager,f,"1",-1);
+	  numtransmuralMenu->addOption("2");
+	  numtransmuralMenu->addOption("3");
+	  numtransmuralMenu->addOption("4");
+	  numtransmuralMenu->setIndex(0);
+	  menu=numtransmuralMenu;
+	  break;
+	}
+      f->addChildren("-side left -expand f -fill x",l,menu);
+    }
+
+  anticlockwise=new PXTkCheckButton(this->EventManager,f3,"Anticlockwise",-1);
+  anticlockwise->setState(PXTrue);
+
+  PXTkFrame* f3c=new PXTkFrame(this->EventManager,f3);
+  PXTkFrame* f4c=new PXTkFrame(this->EventManager,f3);
+  f3->addChildren("-side top -expand f -fill x -pady 1 ",anticlockwise,f3c,f4c);
+
+  PXTkButton* resl=new PXTkButton(this->EventManager,f3c,"Reslice",803);
+  PXTkButton* b3a=new PXTkButton(this->EventManager,f3c,"Save Pies",804);
+  f3c->addChildren("-side left -expand f -fill x -pady 1 -padx 2",resl,b3a);
+
+  PXTkButton* b4b=new PXTkButton(this->EventManager,f4c,"Load Indices",805);
+  PXTkButton* b4a=new PXTkButton(this->EventManager,f4c,"Save Indices",806);
+  f4c->addChildren("-side left -expand f -fill x -pady 1 -padx 2",b4b,b4a);
+
+  // --------- bottom layer ---------------------
+  PXTkLabelFrame* gFrame=new PXTkLabelFrame(this->EventManager,mFrame,"Load/Save");
+  mFrame->addChildren("-side top -expand false -fill x",gFrame);
+
+  PXTkFrame* f2=new PXTkFrame(this->EventManager,gFrame);
+  gFrame->addChildren("-side top -expand false -fill x",f2);
+  PXTkButton* b0a=new PXTkButton(this->EventManager,f2,"Load Study",801);
+  PXTkButton* b0b=new PXTkButton(this->EventManager,f2,"Load Ref",802);
+  f2->addChildren("-side left -expand f -fill x -pady 1 -padx 2",b0a,b0b);
+
+
+  if (!inside)
+    {
+      PXTkButton* closeB;
+      if (this->EventParent)
+	closeB=new PXTkButton(this->EventManager,mFrame,"Close",3);
+      else
+	closeB=new PXTkButton(this->EventManager,mFrame,"Exit",1);
+      mFrame->addChildren("-side bottom -expand false -fill x -padx 2",closeB);
+    }
+
+  return GetWidgetName();
+}
+
+/* -------------------------------------------------------------------------*/ 
+void vtkpxGUIFemPostControl::SetRenderer(vtkpxGUI4DRenderer* ren,int index)
+{
+  this->SetRenderer(ren,index,0);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIFemPostControl::SetRenderer(vtkpxGUI4DRenderer *ren,int index,int wireframe)
+{
+  index=Irange(index,0,TSP_MAX_RENDERERS-1);
+
+  if (this->MultiRenderer[index]!=NULL)
+    return;
+
+  this->MultiRenderer[index]=ren;
+  this->wireframemode[index]=wireframe;
+  this->Renderer[index]=this->MultiRenderer[index]->GetRendererForFrame(this->CurrentFrame);
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIFemPostControl::SetImage(vtkImageData* img,int orient)
+{
+  if (img!=NULL)  
+    {
+      this->currentImageNumberOfFrames=img->GetNumberOfScalarComponents();
+      this->currentOrientation=orient;
+      this->ResetSolids();
+      this->SetCurrentFrame(0);
+    }
+  
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIFemPostControl::SetCurrentFrame(int t)
+{
+  if (t<0) 
+    t=this->NumberOfFrames-1;
+  if (t>this->NumberOfFrames-1)
+    t=0;
+
+  if (!this->Initialized)
+    return;
+
+  this->ChangeFrame(t);
+  this->UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIFemPostControl::GetCurrentFrame()
+{
+  return this->CurrentFrame;
+}
+
+int vtkpxGUIFemPostControl::GetNumberOfFrames()
+{
+  return this->NumberOfFrames;
+}
+/* -------------------------------------------------------------------------*/
+//
+//    Handle Callbacks 
+//
+/* -------------------------------------------------------------------------*/
+int  vtkpxGUIFemPostControl::HandleEvent(int event)
+{
+  if (!this->Initialized)
+      return TCL_OK;
+
+  if (event<10)
+      return this->EventManager->handleDirectEvent(event);
+
+  
+  switch (event)
+    {
+    case 400: //Render Mode
+      this->Update();
+      break;
+      
+    case 401: // Show/Hide
+      if (this->showHide->getState())
+	this->displayMode=1;
+      else
+	this->displayMode=0;
+      this->UpdateDisplay();
+      break;
+      
+    case 801: // Load Study
+      if (this->NumberOfFrames>0)
+	{
+	  char* line=this->EventManager->getOpenFilename("Load Study","Finite Element Study","*.stat");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		this->LoadStudy(line);
+	    }
+	}
+      break;
+
+    case 802: // Load Reference Point
+      if (this->NumberOfFrames>0)
+	{
+	  char* line=this->EventManager->getOpenFilenameComplex("Load Reference Point",
+								"{\"Reference/Landmark Files\" {\".ref\" \".land\" } } { \"Reference Point\" {\"*.ref\"}} {\"Landmarks\" {\"*.land\"}}");
+	  //	  char* line=this->EventManager->getOpenFilename("Load Reference Point","Reference Point","*.ref");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		this->LoadReferencePoint(line);
+	    }
+	}
+      break;
+      
+      
+    case 803:
+      this->ReslicePies();
+      break;
+
+    case 804:
+      if (this->NumberOfFrames>0)
+	{
+	  sprintf(pxtk_buffer,"%s.pie",study_filename);
+	  char* line=this->EventManager->getSaveFilename("Save pies",pxtk_buffer,"Pies","*.pie");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		{
+		  strcpy(pxtk_buffer,line);
+		  this->SavePies(pxtk_buffer);
+		}
+	    }
+	}
+      break;
+
+    case 805: // Load Reference Point
+      if (this->NumberOfFrames>0)
+	{
+	  char* line=this->EventManager->getOpenFilename("Load Pie Indices","Indices","*.pieindex");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		this->LoadIndices(line);
+	    }
+	}
+      break;
+
+    case 806: // Load Reference Point
+      if (this->NumberOfFrames>0)
+	{
+	  sprintf(pxtk_buffer,"%s.pieindex",study_filename);
+	  char* line=this->EventManager->getSaveFilename("Save Pie Indices",pxtk_buffer,"Indices","*.pieindex");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		this->SaveIndices(line);
+	    }
+	}
+      break;
+
+
+    case 807:
+      for (int ia=0;ia<=2;ia++)
+	this->ScaleFactor[ia]=Frange(atof(scaleFactorEntry[ia]->getText()),0.2,10.0);
+      this->UpdateScaling(this->ScaleFactor[0],
+			  this->ScaleFactor[1],
+			  this->ScaleFactor[2]);
+      break;
+    }
+   
+  
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIFemPostControl::UpdateScaling(float x,float y,float z)
+{
+  if (this->NumberOfFrames<1)
+    return;
+
+  this->scalingTransformation->Identity();
+  this->scalingTransformation->Scale(x,y,z);
+
+  for (int i=0;i<this->NumberOfFrames;i++)
+    {
+      vtkTransformPolyDataFilter* trf=(vtkTransformPolyDataFilter*)this->transformFilterCollection->GetItemAsObject(i);
+      trf->Modified();
+    }
+  this->UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIFemPostControl::Update()
+{
+  if (this->NumberOfFrames<1)
+    return;
+
+  int mode=this->modeMenu->getIndex();
+  int plot=this->plotMenu->getIndex();
+  int res= this->resolutionMenu->getIndex();
+
+  int strain=plot+6*res;
+
+  
+  int cmode=0;
+
+  switch (mode)
+    {
+    case 0: // None
+    case 1: // Pies BW
+    case 2: // Pies
+    case 3: // Strain 
+      cmode=mode;
+      break;
+
+    case 4: // Strain HSV
+      cmode=5;
+      break;
+    }
+
+
+
+  for (int i=0;i<this->NumberOfFrames;i++)
+    {
+      vtkpxFemSolid* solid=(vtkpxFemSolid*)this->solidCollection->GetItemAsObject(i);
+      solid->SetColorMode(cmode);
+      solid->SetStrainMode(strain);
+      solid->SetWarpMode(1);
+      solid->Update();
+      //fprintf(stderr,"Updated solid %d\n",i);
+    }
+    
+  this->UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIFemPostControl::UpdateDisplay()
+{
+  for (int i=0;i<this->NumberOfFrames;i++)
+    {
+      int index2=i*TSP_MAX_RENDERERS;
+      for (int r=0;r<TSP_MAX_RENDERERS;r++)
+	{
+	  vtkActor* tmp=(vtkActor*)this->solidActorCollection->GetItemAsObject(index2);
+	  if (displayMode)
+	    tmp->SetVisibility(1);
+	  else
+	    tmp->SetVisibility(0);
+	}
+    }
+
+  if (this->Renderer[0]!=NULL)
+    this->Renderer[0]->GetRenderWindow()->Render();
+
+}
+/* -------------------------------------------------------------------------*/
+//
+//       This is work all the work is done ....
+// 
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIFemPostControl::LoadStudy(const char* filename)
+{
+  static int debugmode=1;
+  gzFile fin=gzsuffixopen(filename,"r");
+  if (fin==NULL)
+    {
+      return 0;
+    }
+  
+  char line[400];
+  gzgets(fin,line,200);
+  int mode=0;
+  
+  if (gzfindstringinstring(line, "#XPResults File Set"))
+      mode=1;
+  else if (gzfindstringinstring(line, "#AbaqusResults File Set"))
+    mode=2;
+  else if (gzfindstringinstring(line, "#Abaqus Results File Set"))
+    mode=3;
+
+
+  if (mode==0)
+    {
+      gzclose(fin);
+      fprintf(stderr,"Not a .stat file\n");
+      return 0;
+    }
+  
+  int numframes,numel,numnodes;
+  gzgets(fin,line,200); sscanf(line,"%d",&numframes);
+  gzgets(fin,line,200); sscanf(line,"%d",&numnodes);
+  gzgets(fin,line,200); sscanf(line,"%d",&numel);
+  
+  char solidname[100];  
+  gzgets(fin,line,200);     gzgets(fin,line,200);  
+  sscanf(line,"%s\n",&solidname[0]);
+  char jobname[100]; 
+  gzgets(fin,line,200);     gzgets(fin,line,200);  
+  sscanf(line,"%s\n",&jobname[0]);
+
+  float scale[3];
+  
+  if (mode==3)
+    {
+      gzgets(fin,line,200);     gzgets(fin,line,200);  
+      sscanf(line,"%f %f %f",&scale[0],&scale[1],&scale[2]);
+    } 
+  else
+    {
+      scale[0]=1.0;
+      scale[1]=1,0;
+      scale[2]=1.0;
+    }
+
+  fprintf(stderr,"Reading set file %s \n",filename);
+  fprintf(stderr,"Job stem =`%s' solid name=`%s' frames=%d nodes=%d elements=%d\n",
+	  jobname,solidname,numframes,numnodes,numel);
+  
+  gzclose(fin);
+
+  char* path=anaextractpath(filename);
+  sprintf(line,"%s%s",path,solidname);
+
+
+  /*if (numframes>this->NumberOfFrames)
+    numframes=this->NumberOfFrames;*/
+
+  this->CreateFrames(numframes);
+
+  vtkpxFemSolid* basesolid=(vtkpxFemSolid*)this->solidCollection->GetItemAsObject(0);
+
+  int ok=basesolid->Load(line);
+
+  if (ok==0)
+    {
+      fprintf(stderr,"Failed to Load solid from %s \n",line);
+      delete [] path;
+      return 0;
+    }
+
+  if (basesolid->GetNumberOfElements()!= numel ||
+      basesolid->GetNumberOfNodes() != numnodes)
+    {
+      fprintf(stderr,"Not correct numnodes or numelements\n");
+      delete [] path;
+      return 0;
+    }
+
+
+  fprintf(stderr,".. Strain data from %s%s : (or=%d) mode=%d,",path,jobname,
+	  basesolid->GetInternalSolid()->getorientationmode(),mode);
+
+  
+  for (int ii=0;ii<numframes;ii++)
+    {
+      vtkpxFemSolid* newsolid=(vtkpxFemSolid*)this->solidCollection->GetItemAsObject(ii);
+      if (ii>0)
+	newsolid->Copy(basesolid);
+      
+      newsolid->CreateFemData();
+      if (mode==1)
+	{
+	  sprintf(line,"%s%s_%02d",path,jobname,ii+1);
+	  if (debugmode)
+	    fprintf(stderr,"Reading old %s\n",line);
+	  else
+	    fprintf(stderr,"(%d) ",ii+1);
+	  newsolid->GetInternalFemData()->LoadOld(line,1);
+	}
+      else if (mode>1)
+	{
+	  sprintf(line,"%s%s.%02d.dat",path,jobname,ii+1);
+	  if (debugmode)
+	    fprintf(stderr,"Reading new data: %s\n",line);
+	  else
+	    fprintf(stderr,"%d ",ii+1);
+	  newsolid->GetInternalFemData()->Load(line,0,1);
+	} 
+    }
+  
+  if (debugmode)
+    fprintf(stderr,"Done Reading\n");
+  
+  sprintf(line,"%s%s.ref",path,jobname);
+  this->LoadReferencePoint(line);
+  delete [] path;
+
+  sprintf(line,"Nodes=%d Elements=%d",
+	  basesolid->GetNumberOfNodes(),
+	  basesolid->GetNumberOfElements());
+  statusLine1->setText(solidname);
+  statusLine2->setText(line);
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->ScaleFactor[ia]=scale[ia];
+      sprintf(line,"%.2f",this->ScaleFactor[ia]);
+      scaleFactorEntry[ia]->setText(line);
+    }
+      
+  this->UpdateScaling(this->ScaleFactor[0],
+		      this->ScaleFactor[1],
+		      this->ScaleFactor[2]);
+
+
+  if (basesolid->GetInternalSolid()->hasfemdata())
+    {
+      int orient=basesolid->GetInternalSolid()->getorientationmode();
+		    
+      if (orient==2 || orient==4)
+	{
+	  plotMenu->changeLabel(0,"XX");
+	  plotMenu->changeLabel(1,"RR");
+	  plotMenu->changeLabel(2,"FF");
+	  plotMenu->changeLabel(3,"XR");
+	  plotMenu->changeLabel(4,"XF");
+	  plotMenu->changeLabel(5,"RF");
+	}
+      else if (orient==5)
+	{
+	  plotMenu->changeLabel(0,"P1");
+	  plotMenu->changeLabel(1,"P2");
+	  plotMenu->changeLabel(2,"P3");
+	  plotMenu->changeLabel(3,"N/A");
+	  plotMenu->changeLabel(4,"N/A");
+	  plotMenu->changeLabel(5,"N/A");
+	}
+      else
+	{
+	  plotMenu->changeLabel(0,"RR");
+	  plotMenu->changeLabel(1,"CC");
+	  plotMenu->changeLabel(2,"LL");
+	  plotMenu->changeLabel(3,"RC");
+	  plotMenu->changeLabel(4,"RL");
+	  plotMenu->changeLabel(5,"CL");
+	}
+    }
+
+  if (numframes<this->NumberOfFrames)
+    {
+      for (int fr=numframes;fr<this->NumberOfFrames;fr++)
+	{
+	  vtkpxFemSolid* newsolid=(vtkpxFemSolid*)this->solidCollection->GetItemAsObject(fr);
+	  newsolid->Copy(basesolid);
+	  newsolid->CreateFemData();
+	}
+    }
+
+  this->Update();
+  return numframes;
+
+
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIFemPostControl::LoadReferencePoint(const char* fname)
+{
+  static int debugmode=1;
+  
+  if (debugmode)
+    fprintf(stderr,"Opening %s ... ",fname);
+  else
+    fprintf(stderr,"\n");
+  
+  int ok=0;
+
+  gzFile fin=gzsuffixopen(fname,"r");
+  if (fin)
+    {
+      char line[100];
+      gzgets(fin,line,100);
+      float rx,ry,rz;
+      if (gzfindstringinstring(line,"#Landmark Data")!=0)
+	{
+	  // Treat as Landmark File
+	  gzclose(fin);
+	  vtkpxBaseCurve* curve=vtkpxBaseCurve::New();
+	  ok=curve->Load(fname);
+	  if (ok)
+	    {
+	      if (curve->GetNumPoints() > 0 ) 
+		{
+		  rx=curve->GetPoints()->GetPoint(0)[0];
+		  ry=curve->GetPoints()->GetPoint(0)[1];
+		  rz=curve->GetPoints()->GetPoint(0)[2];
+		}
+	    }
+	  curve->Delete();
+	}
+      else
+	{
+	  sscanf(line,"%f %f %f",&rx,&ry,&rz);
+	  ok=1;
+	  gzclose(fin);
+	}
+
+      if (ok)
+	{
+	  fprintf(stderr,"Junction Point (%5.2f %5.2f %5.2f)\n",rx,ry,rz);
+	  
+	  this->ReferencePoint[0]=rx;
+	  this->ReferencePoint[1]=ry;
+	  this->ReferencePoint[2]=rz;
+	}
+
+      return ok;
+    }
+
+  return 0;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIFemPostControl::LoadIndices(const char* fname)
+{
+  vtkpxFemSolid* basesolid=(vtkpxFemSolid*)this->solidCollection->GetItemAsObject(0);
+  if (basesolid->GetNumberOfElements() < 1)
+      return 0;
+
+  int ok=basesolid->GetInternalFemData()->loadPieDivision(fname);
+  if (ok)
+    {
+      for (int i=1;i<this->NumberOfFrames;i++)
+	{
+	  vtkpxFemSolid* newsld=(vtkpxFemSolid*)this->solidCollection->GetItemAsObject(i);
+	  newsld->GetInternalFemData()->copypieindex(basesolid->GetInternalFemData());
+	}
+    }
+  return ok;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIFemPostControl::SaveIndices(const char* fname)
+{
+  vtkpxFemSolid* basesolid=(vtkpxFemSolid*)this->solidCollection->GetItemAsObject(0);
+  return  basesolid->GetInternalFemData()->savePieDivision(fname);
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIFemPostControl::ReslicePies()
+{
+  int numslices=atoi(numslicesMenu->getValue());
+  int numsectors=atoi(numsectorsMenu->getValue());
+  int numtransmural=atoi(numtransmuralMenu->getValue());
+  int anti=0;
+  if (anticlockwise->getState())
+    anti=1;
+
+  fprintf(stderr,"Reslicing Pies Ref= %.2f,%.2f,%.2f\n",
+	  this->ReferencePoint[0],
+	  this->ReferencePoint[1],
+	  this->ReferencePoint[2]);
+
+  int ok=vtkpxFemSolid::ReslicePies(this->solidCollection,this->NumberOfFrames,
+				    numslices,numsectors,numtransmural,anti,
+				    this->ReferencePoint);
+
+  if (ok)
+    this->Update();
+  return ok;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIFemPostControl::SavePies(const char* fname)
+{
+  int numslices=atoi(numslicesMenu->getValue());
+  int numsectors=atoi(numsectorsMenu->getValue());
+  int numtransmural=atoi(numtransmuralMenu->getValue());
+  int anti=0;
+  if (anticlockwise->getState())
+    anti=1;
+
+  fprintf(stderr,"Saving Pies Ref= %.2f,%.2f,%.2f\n",
+	  this->ReferencePoint[0],
+	  this->ReferencePoint[1],
+	  this->ReferencePoint[2]);
+
+  return vtkpxFemSolid::SavePies(fname,this->solidCollection,this->NumberOfFrames,
+				 numslices,numsectors,numtransmural,anti,
+				 this->ReferencePoint);
+ 
+}
+
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIFemPostControl.h b/bioimagesuite30_src/GUI/vtkpxGUIFemPostControl.h
new file mode 100644
index 0000000..0ea9e38
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIFemPostControl.h
@@ -0,0 +1,188 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIFemPostControl.h,v $
+  Language:  C++
+  Date:      $Date: 2003/05/28 16:43:01 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIFemPostControl - Base Image Viewer
+// .SECTION Description
+
+#ifndef __vtkpxGUIFemPostControl_h
+#define __vtkpxGUIFemPostControl_h
+
+#include "vtkpxGUITriangulatedStackControl.h"
+#include "vtkpxFemSolid.h"
+
+class vtkImageData;
+class vtkpxGUI4DRenderer;
+class vtkCollection;
+class vtkActorCollection;
+class vtkTransform;
+
+class vtkpxGUIFemPostControl : public vtkpxGUIComponent 
+{
+public:
+
+  static vtkpxGUIFemPostControl *New();
+  vtkTypeMacro(vtkpxGUIFemPostControl,vtkpxGUITriangulatedStackControl);
+  
+  // Description:
+  // Initialize Display and add Renderer 
+  virtual char*  Initialize(const char* name,int inside);
+
+  // Description:
+  // Set Renderer
+  virtual void   SetRenderer(vtkpxGUI4DRenderer *rendererer,int num);
+  virtual void   SetRenderer(vtkpxGUI4DRenderer *rendererer,int num,int wireframe);
+
+  // Description:
+  // Update Display
+  virtual void   Update();
+  virtual void   UpdateDisplay();
+  virtual void   UpdateScaling(float x,float y,float z);
+
+  // Description:
+  // Event Manager 
+  virtual int    HandleEvent(int);
+
+  // Description:
+  // Enable Change Of Frame from this control -- bad idea 
+  //virtual void EnableFrameScale(int enable);
+
+  // Description:
+  // Frame Stuff
+  virtual void SetCurrentFrame(int fr);
+  virtual int  GetCurrentFrame();
+  virtual int  GetNumberOfFrames();
+
+  // Description:
+  // Load / Save
+  virtual int  LoadStudy(const char* fname);
+  virtual int  LoadReferencePoint(const char* fname);
+  virtual int  LoadIndices(const char* fname);
+  virtual int  SaveIndices(const char* fname);
+  virtual int  SavePies(const char* fname);
+  virtual int  ReslicePies();
+
+
+  // Description:
+  // Location and Normal
+  vtkGetVectorMacro(ReferencePoint,float,3);
+  vtkSetVectorMacro(ReferencePoint,float,3);
+
+  // Description:
+  // SetImage
+  virtual void SetImage(vtkImageData* image,int orientation);
+
+protected:
+
+  vtkpxGUIFemPostControl();
+  virtual ~vtkpxGUIFemPostControl();
+
+  // Description:
+  // Pointers to Current Frame Stuff
+  vtkpxFemSolid     *currentSolid;
+  vtkActor*         solidActor[TSP_MAX_RENDERERS];
+  vtkRenderer*      Renderer[TSP_MAX_RENDERERS];
+
+  // Description:
+  // Collection Stuff
+  vtkCollection*       solidCollection;
+  vtkCollection*       transformFilterCollection;
+  vtkActorCollection*  solidActorCollection;
+  vtkTransform*        scalingTransformation;
+
+  vtkpxGUI4DRenderer*  MultiRenderer[TSP_MAX_RENDERERS];
+  int                  wireframemode[TSP_MAX_RENDERERS];
+  char*                study_filename;
+  float                ReferencePoint[3];
+  float                ScaleFactor[3];
+
+  // Description:
+  // Frame Stuff
+  int   CurrentFrame;
+  int   NumberOfFrames;
+  int   ActualNumberOfFrames;
+
+  // Description:
+  // Initialize SolidStacks
+  virtual void InitializeSolids();
+  virtual void ResetSolids();
+
+  // Description:
+  // Frame Update Stuff 
+  virtual void CreateFrames(int numframes);
+  virtual void UpdateFrame(int frame);
+  virtual void ChangeFrame(int newframe);
+
+  // Description:
+  // Widgets
+  //BTX
+  PXTkOptionMenu  *modeMenu,*plotMenu,*resolutionMenu;
+  PXTkLabel       *statusLine1,*statusLine2;
+  PXTkOptionMenu  *numslicesMenu,*numsectorsMenu,*numtransmuralMenu;
+  PXTkCheckButton *showHide,*anticlockwise,*autoscale;
+  PXTkEntry*      scaleFactorEntry[3];
+  int             displayMode;
+  int             currentImageNumberOfFrames;
+  int             currentOrientation;
+  //ETX
+
+  
+
+};
+
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIMosaicViewer.cpp b/bioimagesuite30_src/GUI/vtkpxGUIMosaicViewer.cpp
new file mode 100644
index 0000000..1e9df9f
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIMosaicViewer.cpp
@@ -0,0 +1,1800 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIMosaicViewer.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/02/03 15:28:38 $
+  Version:   $Revision: 1.3 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxGUIColormapEditor.h"
+#include "pxutil.h"
+#include "vtkActor.h"
+#include "vtkImageQuantizeRGBToIndex.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxGUIMosaicViewer.h"
+#include "vtkpxTalairachTransform.h"
+// -------------------------------------------------------------------------
+vtkpxGUIMosaicViewer* vtkpxGUIMosaicViewer::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIMosaicViewer");
+  if(ret)
+      {
+	return (vtkpxGUIMosaicViewer*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIMosaicViewer;
+}
+// -------------------------------------------------------------------------
+// Construct object with no children.
+vtkpxGUIMosaicViewer::vtkpxGUIMosaicViewer()
+{
+
+  this->single_slice_mode=PXFalse;
+  this->xy_slice_only=PXFalse;
+  this->offset=0;
+  this->NumberOfViewers=1;
+  this->NumberOfRows=1;
+  this->NumberOfColumns=1;
+  this->MaximumNumberOfViewers=48;
+  this->show_controlframe=1;
+
+  this->highlightGUI=NULL;
+
+  this->timeframeControlFrame=NULL;
+  this->frameScale=NULL;
+  this->CreateHighlights=0;
+  this->extraFrame=NULL;
+  this->reverseOrder=NULL;
+  this->transposeOrder=NULL;
+  this->currentPlane=NULL;
+  this->MouseToEditor=0;
+  this->ShiftMouseToEditor=0;
+  this->Editor=NULL;
+
+  for (int i=0;i<MVP_MAX_VIEWERS;i++)
+      initialized[i]=PXFalse;
+  this->statusLabel=NULL;
+  this->donotRender=0;
+
+  this->inexpose=0;
+  this->inexposecount=0;
+  this->LastEvent=-1;
+  this->showLabels=NULL;
+
+  this->firsttime=1;
+  this->olddimensions[0]=-1;
+  this->olddimensions[1]=-1;
+  this->olddimensions[2]=-1;
+
+
+}
+// -------------------------------------------------------------------------
+vtkpxGUIMosaicViewer::~vtkpxGUIMosaicViewer()
+{
+
+
+}
+/* -------------------------------------------------------------------------*/
+char* vtkpxGUIMosaicViewer::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+  
+  vtkpxGUIComponent::Initialize(name,inside);
+
+  PXTkFrame* manager=(PXTkFrame*)(this->EventManager->getMainWindow());
+  PXTkFrame* viewerFrame=new PXTkFrame(this->EventManager,manager);
+  manager->setPackMode(PXTrue);
+
+  if (single_slice_mode)
+    manager->addChildren("-side top  -expand true -fill both",viewerFrame);
+  else
+    manager->addChildren("-side left -expand true -fill both",viewerFrame);
+
+  InitControls(viewerFrame,this->CreateHighlights);
+  InitViewer(viewerFrame);
+
+  return GetWidgetName();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIMosaicViewer::Update()
+{
+  UpdateAllViewers();
+  UpdateDisplay();
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::SetOffset(int of)
+{
+  if (this->Initialized==0)
+      this->offset=of;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::SetXYSliceOnly()
+{
+  if (this->Initialized==0)
+    {
+      xy_slice_only=PXTrue;
+      this->DisableTalairachButtons();
+    }
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::SetSingleSliceMode()
+{
+  if (this->Initialized==0)
+    {
+      single_slice_mode=PXTrue;
+      CreateHighlights=0;
+      this->DisableTalairachButtons();
+      this->MaximumNumberOfViewers=1;
+    }
+}
+
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIMosaicViewer::InitializeViewer()
+{
+  if ((!hasImage && this->Initialized))
+      return 0;
+  
+  for (int i=0;i<NumberOfViewers;i++)
+    CreateViewerAndSlice(i);
+  
+  if (this->ColormapEditor==NULL && this->ownsLookupTable==1)
+    {
+      ColormapEditor=vtkpxGUIColormapEditor::New();
+      ColormapEditor->SetSimpleMode(0);
+      ColormapEditor->SetCallback(this,200);
+      ColormapEditor->Initialize(this->GetWidgetName(),0);
+      ColormapEditor->SetRange(0,255);
+      this->ColormapEditor->SetColormap(mainLookupTable);
+    }
+  
+  return 1;
+  //  fprintf(stderr,"Viewer Initialized\n");
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUIMosaicViewer::ResetEditor()
+{
+  if (this->Editor!=NULL)
+    this->Editor->SetLookupTable(mainLookupTable);
+
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIMosaicViewer::ResetViewer()
+{
+  //  fprintf(stderr,"Reseting Viewer\n");
+
+  if (!(hasImage && this->Initialized))
+      return 0;
+
+  // ------------------------------------------------------
+  //           C h e c k    f o r    L o o k u p T a b l e
+  // ------------------------------------------------------
+  int numc=currentImage->GetNumberOfScalarComponents();
+     
+
+  
+  // ------------------------------------------------------
+  //   Bounds/ Highlights 
+  // ------------------------------------------------------
+  double bounds[6];  GetBounds(bounds);
+  int   range[3];   currentImage->GetDimensions(range); 
+  double sp[3];      currentImage->GetSpacing(sp);
+  double ori[3];     currentImage->GetOrigin(ori);
+
+  //  fprintf(stderr,"Image Dimensions = %d %d %d\n",range[0],range[1],range[2]);
+
+  if (this->talairachTransform==NULL)
+    this->talairachTransform=vtkpxTalairachTransform::New();
+      
+  this->talairachTransform->SetColinMode(1,this->currentImage);
+  this->talairachTransform->Modified();
+  this->UpdateAllViewers();
+  this->UpdateStatusLabels();
+
+
+  if (highlightGUI!=NULL)
+      {
+	for (int ka=0;ka<=2;ka++)
+	  {
+	    highlightscale[ka*2]->setRange(offset,range[ka]-2.0+float(offset));
+	    highlightscale[ka*2+1]->setRange(offset+1.0,range[ka]-1.0+float(offset));
+	    highlightscale[ka*2]->setValue(0.0+float(offset));
+	    highlightscale[ka*2+1]->setValue(offset+range[ka]-1.0);
+	  }
+	UpdateHighlights();
+      }
+
+  if (frameScale!=NULL)
+    {
+      if (CurrentImageIsColor==0)
+	this->ShowFrameControls((this->NumberOfFrames>1));
+      else
+	this->ShowFrameControls(0);
+    } 
+
+  
+  
+  // ------------------------------------------------------
+  //  C h e c k   for   S a m e   D i m e n s i o ns
+  // ------------------------------------------------------
+  int dim[3];     
+  currentImage->GetDimensions(dim);
+  int numslices=dim[2];
+  int samesizeasbefore=0;
+
+  if (firsttime==0)
+    {
+      int flag=0;
+      for (int i=0;i<=2;i++)
+	{
+	  if (dim[i]!=olddimensions[i])
+	    flag++;
+	}
+      if (frameScale!=NULL)
+	{
+	  if (this->NumberOfFrames!=(int(frameScale->getmax())))
+	    flag++;
+	}
+      samesizeasbefore=(flag==0);
+    }
+  
+  for (int i=0;i<=2;i++)
+    olddimensions[i]=dim[i];
+
+  //  fprintf(stderr,"This Far (1)\n");
+
+  // THIS IS A HACK for now .........
+  if (this->IsA("vtkpxGUIObjectmapMosaicViewer"))
+    samesizeasbefore=0;
+  
+  if (samesizeasbefore==0)
+    {
+      //      fprintf(stderr,"Into samesizeas before = 0 ");
+
+      if (!single_slice_mode && !xy_slice_only)
+	currentPlane->setIndex(2);
+      firsttime=0;
+      beginSlice->setResolution(1);
+      beginSlice->setRange(float(offset),float(numslices-1+offset));
+      beginSlice->setValue(offset+dim[2]/2);
+
+  
+      if (!single_slice_mode)
+	{
+	  if (this->NumberOfViewers>0)
+	    incrementSlice->setRange(1,numslices/this->NumberOfViewers);
+	  else
+	    incrementSlice->setRange(1,numslices);
+	  incrementSlice->setResolution(1);
+	  incrementSlice->setValue(1);
+	}
+
+      frameScale->setRange(1,this->NumberOfFrames);
+      frameScale->setResolution(1);
+      frameScale->setValue(1);
+
+      if (this->NumberOfViewers>0)
+	{
+	  SetViewports();
+	  //	  fprintf(stderr,"This Far samesizeasbefore=%d SetViewp numvie=%d\n",samesizeasbefore,this->NumberOfViewers);
+	  
+	  for (int kk=0;kk<this->NumberOfViewers;kk++)
+	    {
+	      imageSlice[kk]->SetCurrentPlane(2);
+	      imageSlice[kk]->SetFrame(0);
+	      imageSlice[kk]->SetLevel(-1);
+	      if (this->Orientation==3)
+		{
+		  imageSlice[kk]->SetPolarMode(1);
+		  renderer[kk]->SetClipMode(PXFalse);
+		}
+	      else
+		{
+		  imageSlice[kk]->SetPolarMode(0);
+		  renderer[kk]->SetClipMode(PXFalse);
+		}
+	      imageSlice[kk]->SetColorMode(this->CurrentImageIsColor);
+	      imageSlice[kk]->SetInput(currentImage);
+	      
+	      renderer[kk]->SetBounds(bounds);
+	      renderer[kk]->SetClipThickness(currentImage->GetSpacing()[2]);
+	      renderer[kk]->SetPlaneMode(2);
+	      renderer[kk]->SetCurrentImageOrientation(currentImage,this->Orientation,1);
+	      renderer[kk]->Reset();
+
+	    }
+	}
+    }
+  else
+    {
+      //      fprintf(stderr,"Same stuff\n");
+      for (int kk=0;kk<this->NumberOfViewers;kk++)
+	{
+	  imageSlice[kk]->SetColorMode(this->CurrentImageIsColor);
+	  imageSlice[kk]->SetInput(currentImage);
+	  renderer[kk]->SetCurrentImageOrientation(currentImage,this->Orientation,0);
+	  renderer[kk]->SetClipThickness(currentImage->GetSpacing()[2]);
+	  renderer[kk]->SetBounds(bounds);
+	}
+    }
+
+
+  if (currentPlane!=NULL)
+    {
+      int oldstyleorient=vtkpxGUIBaseImageViewer::MapOrientationToOldStyle(this->Orientation);
+      //      fprintf(stderr,"This far %d,%d\n",this->Orientation,currentPlane);
+      switch (oldstyleorient)
+	{
+	case 0: // Axial
+	  currentPlane->changeLabel(0,"Sagittal-YZ");
+	  currentPlane->changeLabel(1,"Coronal-XZ");
+	  currentPlane->changeLabel(2,"Axial-XY");
+	  break;
+	case 1:
+	  currentPlane->changeLabel(0,"Sagittal-YZ");
+	  currentPlane->changeLabel(1,"Axial-XZ");
+	  currentPlane->changeLabel(2,"Coronal-XY");
+	  break;
+	case 2:
+	  currentPlane->changeLabel(0,"Coronal-YZ");
+	  currentPlane->changeLabel(1,"Axial-XZ");
+	  currentPlane->changeLabel(2,"Sagittal-XY");
+	  break;
+	case 3: // Polar
+	  currentPlane->changeLabel(0,"Short-Axis");
+	  currentPlane->changeLabel(1,"Radial");
+	  currentPlane->changeLabel(2,"Radial");
+	  break;
+	}
+    }
+
+  if (this->Editor!=NULL)
+    {
+      int plane=2;
+      if (currentPlane!=NULL)
+	plane=currentPlane->getIndex();
+      this->Editor->SetImage(currentImage,plane,0);
+    }
+
+
+
+  if (samesizeasbefore==0)
+    ChangeSliceIncrement(-1,-1,-1);
+
+  this->UpdateStatusLabels();
+
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIMosaicViewer::HandleEvent(int event)
+{
+  if (event<10)
+      return this->EventManager->handleDirectEvent(event);
+  
+  if (!hasImage && event!=301)
+    return TCL_OK;
+
+  if (event==200)
+      UpdateDisplay();
+  
+  if (event==201 || event==202)
+    {
+      if (hasImage)
+	{
+	  if (event==202)
+	    renderer[0]->Zoom(renderer[0]->GetCameraScale()*1.2,PXFalse);
+	  else
+	    renderer[0]->Zoom(renderer[0]->GetCameraScale()*0.833,PXFalse);
+	  
+	  for (int kk=1;kk<MVP_MAX_VIEWERS;kk++)
+	    {
+	      if (initialized[kk]==PXTrue)
+		{
+		  renderer[kk]->Zoom(renderer[0]->GetCameraScale(),PXFalse);
+		}
+	    }
+	}
+      UpdateDisplay();
+    }
+  
+   if (event==203)
+     {
+       if (hasImage)
+	 {
+	   int dim[3];     
+	   currentImage->GetDimensions(dim);
+	   int plane=2;
+	   if (!single_slice_mode && !xy_slice_only )
+	     plane=currentPlane->getIndex();
+	   int numslices=dim[plane];
+	   if (this->Orientation==3)
+	     {
+	       if (plane==0)
+		 numslices=dim[1];
+	       else
+		 numslices=dim[2];
+	     }
+	   
+	   beginSlice->setRange(offset,numslices-1+offset);
+	   if (beginSlice->getValue()>=numslices+offset)
+	     beginSlice->setValue(0+offset);
+	   
+	   if (!single_slice_mode)
+	     {
+	       incrementSlice->setRange(1,numslices/this->NumberOfViewers);
+	       if (incrementSlice->getValue()>=numslices/this->NumberOfViewers)
+		 {
+		   if (numslices/this->NumberOfViewers>0)
+		     incrementSlice->setValue(numslices/this->NumberOfViewers);
+		   else
+		       incrementSlice->setValue(1);			
+		 }
+	     }
+	   UpdateAllViewers();
+	   UpdateDisplay();
+	 }
+       }
+
+
+   if (event==205)
+     {
+       if (hasImage)
+	 {
+	   PXBool interp=interpolateMode->getState();
+	   for (int k=0;k<MVP_MAX_VIEWERS;k++)
+	     {
+	       if (initialized[k])
+		 imageSlice[k]->SetInterpolation((int)interp);
+	     }
+	 }
+       UpdateDisplay();
+     }
+   
+   if (event==206)
+     {
+       ChangeSliceIncrement(-1,-1,-1);
+     }
+
+   if (event==207)
+     {
+       if (hasImage)
+	 {
+	   UpdateAllViewers();
+	   UpdateDisplay();
+	 }
+     }
+   
+   if (event==208)
+     ResetAll();
+  
+   if (event==221)
+     this->SaveAsTiff(render_widget->getRenderWindow());
+   
+   if (event==222)
+     this->SetBackgroundColor(render_widget->getRenderWindow());
+
+   /*if (event==221)
+     this->ExportAsVRML(render_widget->getRenderWindow());*/
+   
+   
+   if (event==209)
+     {
+       if (this->ColormapEditor!=NULL && this->hasImage)
+	 this->ColormapEditor->Show();
+     }
+   
+   if (event==214 || event==215 || event==216 || event==217 || event==218 || event==219)
+     {
+       if (event<219)
+	 this->SetPresetLookupTable(event-215);
+       else
+	 this->SetPresetLookupTable(event-213);
+     }
+   
+   if (event==210)
+     {
+       if (highlightGUI!=NULL)
+	 highlightGUI->popupDialog();
+     }
+   
+   if (event==211)
+     {
+       if (highlightGUI!=NULL)
+	 {
+	   this->UpdateHighlights();
+	   UpdateDisplay();
+	 }
+     }
+   
+   if (event==212)
+     {
+       int dm=0;
+       
+       if (highlightGUI!=NULL)
+	 {
+	   if (showhighlight->getState())
+	     {
+	       dm=1;
+	       this->UpdateHighlights();
+	     }
+	   
+	   for (int kk=0;kk<MVP_MAX_VIEWERS;kk++)
+	     if (initialized[kk]==PXTrue)
+	       imageSlice[kk]->SetDisplayHighlight(dm);
+	   UpdateDisplay();
+	 }
+     }
+   
+   if (event==213)
+     {
+	if (hasImage && highlightGUI!=NULL)
+	  {
+	    int dim[3];     
+	    currentImage->GetDimensions(dim);
+	    for (int k=0;k<=2;k++)
+	      {
+		highlightscale[k*2]->setValue(0.0+float(offset));
+		highlightscale[k*2+1]->setValue(dim[k]);
+	      }
+	    this->UpdateHighlights();
+	    UpdateDisplay();
+	  }
+     }
+
+  if (event==300)
+      {
+	int* x=render_widget->getRenderWindow()->GetSize();
+	int mouse=PXTkApp::getIntArgument(0);
+	int state=PXTkApp::getIntArgument(1);
+	int x1=PXTkApp::getIntArgument(2);
+	int x2=x[1]-PXTkApp::getIntArgument(3);
+	HandleMouseButtonEvent(mouse,state,x1,x2,this->EventManager);
+      }
+  
+  if (event==301)
+    {
+      if (this->LastEvent!=301)
+	{
+	  //  fprintf(stderr,"Setting delayed expose\n");
+	  this->RenderDelay(500);
+	}
+      //      fprintf(stderr,"*%d*",this->LastEvent);
+      //UpdateDisplay();
+    }
+  
+  
+  /*  if (event==305)
+    {
+      UpdateDisplay();
+      }*/
+  
+  if (event==401)
+    {
+      int numr=(int)viewerPresetsRow->getValue();
+      int numc=(int)viewerPresetsCol->getValue();
+      //      fprintf(stderr,"event=%d, values=%d,%d\n",event,numr,numc);
+      this->SetConfiguration(numr,numc);
+    }
+
+  if ( (event==402 || event==403) && hasImage)
+    {
+      if (this->talairachTransform==NULL)
+	this->talairachTransform=vtkpxTalairachTransform::New();
+      
+      int   range[3];   currentImage->GetDimensions(range); 
+      //      fprintf(stderr,"Tal %d Image Dimensions = %d %d %d\n",event,range[0],range[1],range[2]);
+
+      if (event==402)
+	this->talairachTransform->SetColinMode(1,this->currentImage);
+      else
+	this->talairachTransform->SetColinMode(-1,this->currentImage);
+      this->talairachTransform->Modified();
+      this->UpdateAllViewers();
+      this->UpdateStatusLabels();
+      
+    }
+
+
+  this->LastEvent=event;
+  
+  return TCL_OK;
+  
+}
+
+int  vtkpxGUIMosaicViewer::UpdateAllViewers()
+{
+  if (!hasImage)
+    return TCL_ERROR;
+  
+  return UpdateViewers(0,this->NumberOfViewers-1);
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIMosaicViewer::UpdateViewers(int firstv,int lastv)
+{
+  if (!hasImage)
+      return TCL_ERROR;
+
+  firstv=Irange(firstv,0,this->NumberOfViewers-1);
+  lastv=Irange(lastv,0,this->NumberOfViewers-1);
+
+  // Read UI variables 
+  int plane=2;
+  if (!single_slice_mode && !xy_slice_only )
+      plane=currentPlane->getIndex();
+  int dim[3];     currentImage->GetDimensions(dim);
+  int frame=this->CurrentFrame;
+
+  double sp[3];  currentImage->GetSpacing(sp);
+  double ori[3]; currentImage->GetOrigin(ori);
+
+  this->EventManager->setWaitCursor(PXTrue);
+
+  if (this->Orientation==3)
+    {
+      dim[0]=dim[1];
+      dim[1]=dim[2];
+    }
+
+  for (int k=firstv;k<=lastv;k++)
+    {
+      int doreset=0;
+      int doclip=1;
+      if (this->Orientation!=3)
+	{
+	  renderer[k]->SetClipMode(PXTrue);
+	  doclip=1;
+	}
+      else
+	renderer[k]->SetClipMode(PXFalse);
+
+      renderer[k]->SetCameraScale(renderer[0]->GetCameraScale());
+
+      if (renderer[k]->GetPlaneMode()!=plane)
+	{
+	  doreset=1;
+	  renderer[k]->SetPlaneMode(plane);
+	  imageSlice[k]->SetCurrentPlane(plane);
+	  renderer[k]->SetFlipMode(0);
+	}
+      
+      int slice=GetViewerSlice(k);
+      renderer[k]->SetClipBounds(slice,slice,slice,sp,ori);
+      renderer[k]->SetViewerCoordinates(slice,slice,slice);
+      
+      if (slice<dim[plane] && slice>=0)
+	{
+	  imageSlice[k]->SetColorMode(this->CurrentImageIsColor);
+	  imageSlice[k]->SetFrame(frame);
+	  imageSlice[k]->SetLevel(slice);
+	  imageSlice[k]->SetCurrentPlane(plane);
+	  imageSlice[k]->SetDisplayMode(2);
+	  imageSlice[k]->Update();
+	  renderer[k]->SetViewerCoordinates(slice,slice,slice);
+	  char line[250];
+
+  
+	  if (!single_slice_mode && !xy_slice_only ) 
+	    {
+	      int axis;
+	      double mni=this->GetMNISliceNo(slice,plane,axis);
+	      if (axis==-1)
+		{
+		  sprintf(line,"Slice=%d/%d (%s)",
+			  slice,dim[plane]-1,
+			  currentPlane->getLabel(imageSlice[k]->GetCurrentPlane()));
+		}
+	      else
+		{
+		  switch (axis) {
+		  case 0: sprintf(line,"MNI X=%.0f Slice=%d/%d",mni,slice,dim[plane]-1); break;
+		  case 1: sprintf(line,"MNI Y=%.0f Slice=%d/%d",mni,slice,dim[plane]-1); break;
+		  case 2: sprintf(line,"MNI Z=%.0f Slice=%d/%d",mni,slice,dim[plane]-1); break;
+		  }
+		}
+	      renderer[k]->SetLabel(line,0.05,0.05,0.73,0.73,0.0);
+	    }
+	}
+      else
+	{
+	  renderer[k]->SetLabel("None",0.05,0.05,
+				0.8,0.8,0.0);
+	  imageSlice[k]->SetDisplayMode(1);
+	  imageSlice[k]->Update();
+	}
+      
+      if (this->showLabels!=NULL)
+	{
+	  if (this->showLabels->getState()==PXTrue)
+	    renderer[k]->ShowLabel();
+	  else
+	    renderer[k]->HideLabel();
+	}
+
+      if (this->Orientation==3)
+	renderer[k]->MoveAbove();
+
+      if (doreset)
+	{
+	  renderer[k]->SetClipThickness(currentImage->GetSpacing()[plane]);
+	  renderer[k]->Reset();
+      	}
+      
+      if (doclip)
+	renderer[k]->Clip();
+
+    }
+  
+  this->EventManager->setWaitCursor(PXFalse);
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::SetNumberOfViewers(int numv)
+{
+  if (numv<1 || numv>this->MaximumNumberOfViewers)
+    return;
+
+  int* sz=render_widget->getRenderWindow()->GetSize();
+  double ratio=(float(sz[0])/float(sz[1]));
+  double sq=double(numv);
+  
+  //float nc=sqrt(float(numv)*ratio);
+  int num_cols=int(sqrt(ratio*sq));
+  if (num_cols==0)
+    num_cols++;
+  int num_rows=int(numv/num_cols);
+  if (num_rows==0)
+    num_rows++;
+  
+  while (num_rows*num_cols<numv)
+    {
+      if ( (num_rows*(num_cols+1) < (num_rows+1)*num_cols))
+	num_cols++;
+      else
+	num_rows++;
+    }
+  this->SetConfiguration(num_rows,num_cols);
+
+}
+
+void vtkpxGUIMosaicViewer::SetConfiguration(int numr,int numc)
+{
+
+  if (!hasImage)
+      return;
+  
+  //  fprintf(stderr,"In Set Configuration\n");
+
+
+  while (numc*numr > this->MaximumNumberOfViewers && numc>0 )
+    numc=numc-1;
+      
+
+  while (numc*numr > this->MaximumNumberOfViewers && numr>0 )
+    numr=numr-1;
+
+
+
+  int old_num=this->NumberOfViewers;
+  this->NumberOfViewers=numr*numc;
+
+  //  fprintf(stderr,"old_num=%d, new=%d\n",old_num,this->NumberOfViewers);
+
+  int createdviewers=0;
+
+  if (this->NumberOfViewers>old_num)
+    {
+      for (int kk=old_num;kk<this->NumberOfViewers;kk++)
+	{
+	  if (initialized[kk])
+	    {
+	      render_widget->getRenderWindow()->AddRenderer(renderer[kk]->GetRenderer());
+	    }
+	  else
+	    {
+	      CreateViewerAndSlice(kk);
+	      ++createdviewers;
+	    }
+	}
+    }
+  else 
+    {
+      for (int kk=this->NumberOfViewers;kk<old_num;kk++)
+	render_widget->getRenderWindow()->RemoveRenderer(renderer[kk]->GetRenderer());
+    }
+  
+  this->NumberOfRows=numr;
+  this->NumberOfColumns=numc;
+
+  viewerPresetsRow->setValue((float)this->NumberOfRows,PXFalse);
+  viewerPresetsCol->setValue((float)this->NumberOfColumns,PXFalse);
+  
+  SetViewports();
+  if (highlightGUI!=NULL)
+    {
+      if (showhighlight->getState())
+	UpdateHighlights();
+    }
+  
+
+  UpdateViewers(old_num,this->NumberOfViewers-1);
+  for (int i=0;i<this->NumberOfViewers;i++)
+    {
+      renderer[i]->Reset();
+      renderer[i]->Zoom(renderer[0]->GetCameraScale(),PXTrue);
+    }
+
+  UpdateDisplay();
+  if ( createdviewers)
+    {
+      if (this->EventParent!=NULL && this->CallbackNo>0)
+	{
+	  this->EventParent->HandleEvent(CallbackNo);
+	}
+      else
+	{
+	  if (this->CallbackName!=NULL)
+	    PXTkApp::executeTclCommand(this->CallbackName);
+	}
+    }
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::ChangeSliceIncrement(int sl,int incr,int fr)
+{
+  if (!hasImage)
+    return;
+
+  if (sl!=-1)
+    {
+      beginSlice->setValue(sl+offset);
+    }
+  
+  if (incr!=-1 && !single_slice_mode)
+    {
+      incrementSlice->setValue(incr);
+    }
+  
+  if (fr!=-1 && !this->CurrentImageIsColor)
+    {
+      frameScale->setValue(fr+1);
+    }
+
+  int callframecallback=0;
+  if (!this->CurrentImageIsColor)
+    {
+      int a=(int) frameScale->getValue()-1;
+      if (a!=this->CurrentFrame)
+	{
+	  this->CurrentFrame=a;
+	  callframecallback=1;
+	}
+    }
+    
+  if (this->Editor!=NULL)
+    {
+      int bl=(int)beginSlice->getValue()-offset;
+      int plane=2;
+      if (!single_slice_mode && !xy_slice_only)
+	plane=currentPlane->getIndex();
+
+      if (this->NumberOfViewers==1)
+	this->Editor->SetPlaneLevel(plane,bl);
+      else
+	this->Editor->SetPlaneLevel(plane,bl+10000);
+
+      this->Editor->SetFrame(CurrentFrame);
+    }
+  
+  //fprintf(stderr,"Updating Display\n");
+  UpdateAllViewers();
+  //  fprintf(stderr,"Updating Display Done\n");
+  //  UpdateDisplay();
+
+  if (callframecallback==1)
+    this->ExecuteFrameChangeCallback();
+
+  if (this->donotRender==0)
+    this->UpdateDisplay();
+
+  if (this->EventParent!=NULL && this->CallbackNo>0)
+    {
+      this->EventParent->HandleEvent(CallbackNo);
+    }
+  else
+    {
+      if (this->CallbackName!=NULL)
+	PXTkApp::executeTclCommand(this->CallbackName);
+    }
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUIMosaicViewer::GetBeginSlice()
+{
+  if (!hasImage)
+    return -1;
+
+  return (int) beginSlice->getValue();
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIMosaicViewer::GetIncrement()
+{
+  if (!hasImage || single_slice_mode)
+    return 1;
+
+  int inc=(int) incrementSlice->getValue();
+
+  if (this->reverseOrder!=NULL)
+    {
+      if (reverseOrder->getState())
+	{
+	  return -inc;
+	}
+    }
+  
+  return inc;
+}
+// -------------------------------------------------------------------------
+
+void vtkpxGUIMosaicViewer::SetCurrentFrame(int t)
+{
+
+  if (!this->CurrentImageIsColor)
+    {
+      if (t<0)
+	t=this->NumberOfFrames-1;
+      if (t>this->NumberOfFrames-1)
+	t=0;
+      this->ChangeSliceIncrement(-1,-1,t);
+    }
+
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::SetViewports()
+{
+  double dx=1.0/float(this->NumberOfColumns);
+  double dy=1.0/float(this->NumberOfRows);
+
+
+  int dotranspose=0;
+  if (this->transposeOrder!=NULL)
+    {
+      if (this->transposeOrder->getState())
+	dotranspose=1;
+    }
+  
+  // fprintf(stderr,"\n Viewer %d x %d dx=%.2f dy=%.2f\n",NumberOfRows,NumberOfColumns,dx,dy);
+  
+  for (int j=0;j<this->NumberOfRows;j++)
+    for (int i=0;i<this->NumberOfColumns;i++)
+      {
+	float v[4];
+	int index=i+j*this->NumberOfColumns;
+
+	if (initialized[index])
+	  {
+	    if (dotranspose==0)
+	      {
+		v[0]=i*dx;
+		v[1]=((this->NumberOfRows-1)-j)*dy;
+		v[2]=v[0]+dx;
+		v[3]=v[1]+dy;
+	      }
+	    else
+	      {
+		v[0]=j*dy;
+		v[2]=v[0]+dy;
+		v[1]=((this->NumberOfColumns-1)-i)*dx;
+		v[3]=v[1]+dx;
+	      }
+	    renderer[index]->SetViewport(v[0],v[1],v[2],v[3]);
+	    //	    fprintf(stderr,"indx=%d i=%d j=%d v=%.2f:%.2f %.2f:%.2f\n",index,i,j,v[0],v[1],v[2],v[3]);
+	  }
+      }
+
+  for (int k=this->NumberOfViewers;k<MVP_MAX_VIEWERS;k++)
+    {
+      if (initialized[k]==PXTrue)
+	renderer[k]->SetViewport(0.9999,0.9999,1.0,1.0);
+    }
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::CreateViewerAndSlice(int index)
+{
+  if (hasImage== PXFalse || this->Initialized==0)
+      return;
+
+  index=Irange(index,0,this->MaximumNumberOfViewers-1);
+  if (initialized[index])
+      return;
+  
+  //  fprintf(stderr,"MOS Creating Viewer And Slice %d\n",index);
+
+  int plane=2;
+  if (!single_slice_mode && !xy_slice_only)
+      plane=currentPlane->getIndex();
+
+  int frame=0;
+
+  vtkRenderer* ren=vtkRenderer::New();
+  //ren->TwoSidedLightingOff();
+  render_widget->getRenderWindow()->AddRenderer(ren);
+    
+  renderer[index]=vtkpxGUIRenderer::New();
+  renderer[index]->SetPlaneMode(plane);
+  renderer[index]->SetFlipMode(0);
+
+  if (index>0 || this->single_slice_mode==PXFalse)
+    renderer[index]->SetNoGUI(PXTrue);
+
+  if (index>0)
+    ren->SetBackground(renderer[0]->GetRenderer()->GetBackground());
+  
+  renderer[index]->Initialize(this->EventManager->getMainWindow()->getWidgetName(),ren,0);
+  renderer[index]->SetAutoZoom(1.0);
+  renderer[index]->SetCallback(this,201);
+
+
+
+  imageSlice[index]=vtkpxImageSlice::New();
+  imageSlice[index]->SetAutoUpdate(0);
+  imageSlice[index]->SetColorMode(this->CurrentImageIsColor);
+  imageSlice[index]->SetInput(currentImage);
+  imageSlice[index]->SetLookupTable(mainLookupTable);
+
+  if (this->Orientation==3)
+    {
+      imageSlice[index]->SetPolarMode(1);
+    }
+  else
+    {
+      imageSlice[index]->SetPolarMode(0);
+    }
+
+#ifndef _WIN32
+  renderer[index]->SetClipMode(PXTrue);
+#endif
+  imageSlice[index]->SetCurrentPlane(2);
+  imageSlice[index]->SetDisplayMode(1);
+
+  if (highlightGUI!=NULL)
+    {
+      if (showhighlight->getState())
+	imageSlice[index]->SetDisplayHighlight(1);
+    }
+#ifndef _WIN32
+  renderer[index]->SetClipMode(PXTrue);
+  renderer[index]->SetClipThickness(currentImage->GetSpacing()[2]);
+#endif
+  renderer[index]->GetRenderer()->AddActor(imageSlice[index]);
+
+
+  
+  if (this->Editor)
+    this->Editor->SetRenderer(ren,index);
+
+
+  double bounds[6];
+  GetBounds(bounds);
+  renderer[index]->SetBounds(bounds);
+  renderer[index]->SetCurrentImageOrientation(currentImage,this->Orientation,1);
+  renderer[index]->Reset();
+
+  if (index>0)
+    renderer[index]->SetCameraScale(renderer[0]->GetCameraScale());
+
+  initialized[index]=PXTrue;
+}
+// -------------------------------------------------------------------------
+int  vtkpxGUIMosaicViewer::GetViewerSlice(int v)
+{
+  v=Irange(v,0,this->NumberOfViewers-1);
+  
+  if (!this->Initialized)
+    {
+      return 0;
+    }
+  
+  int firstslice=(int)beginSlice->getValue()-offset;
+  int incr=1;
+
+  if (firstslice<0)
+      firstslice=0;
+  
+
+  int increment=this->GetIncrement();
+  int final=firstslice+v*increment;
+  //  fprintf(stderr,"v=%d firstslice=%d incr=%d final=%d\n",v,firstslice,incr,final);
+  return final;
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUIMosaicViewer::ResetAll()
+{
+  if (!hasImage)
+      return 0;
+
+  this->EventManager->setWaitCursor(PXTrue);
+
+  for (int k=0;k<MVP_MAX_VIEWERS;k++)
+    {
+      if (initialized[k])
+	{
+	  renderer[k]->Reset();
+	}
+    }
+  UpdateDisplay();
+  this->EventManager->setWaitCursor(PXFalse);
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIMosaicViewer::HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev)
+{
+  int found=-1;
+  if (ev==NULL || hasImage==PXFalse)
+    return 0;
+  
+  for (int i=0;i<this->NumberOfViewers;i++)
+    {
+      if (renderer[i]->InViewport(x,y))
+	{
+	  found=i;
+	  i=this->NumberOfViewers;
+	}
+    }
+  
+  if (found==-1)
+    return 0;
+  
+  if (this->Editor!=NULL)
+    {
+      if (nbutton==3  && this->Editor->IsOpen()==0 && this->IsA("vtkpxGUISplineEditor")==0)
+	{
+	  if (state==2)
+	    this->Editor->Show();
+	  return 1;
+	}
+    }
+
+  int sendtoeditor=0;
+  if ( this->MouseToEditor && (  nbutton == 4 || nbutton==7 || ( this->ShiftMouseToEditor==0 && nbutton==1)))
+    {
+      if (this->Editor!=NULL)
+	sendtoeditor=1;
+    }
+
+  if (nbutton  == 1 || nbutton == 4 || nbutton == 7 )
+    {
+      double px1,py1;
+      
+      renderer[found]->Get2DClickedPoint(px1,py1,x,y);
+	
+      int plane=2;
+      if (!single_slice_mode && !xy_slice_only)
+	plane=currentPlane->getIndex();
+      
+      int slice=GetViewerSlice(found);
+      double sp[3],ori[3];
+      currentImage->GetSpacing(sp);
+      currentImage->GetOrigin(ori);
+      double slice_sc=double(slice)*sp[plane]+ori[plane];
+      //      fprintf(stderr,"slice_sc=%f (o=%f,s=%f)slice=%d\n\n",slice_sc,ori[plane],sp[plane],slice);
+      
+      if (nbutton==7)
+	state=3+state;
+
+      if (nbutton==4)
+	{
+	  if (this->ShiftMouseToEditor==0 && this->IsA("vtkpxGUISplineEditor")==1)
+	    state=6+state;
+	}
+
+
+      switch(plane)
+	{
+	case 0:
+	  if (sendtoeditor)
+	    this->Editor->HandleClickedPoint(slice_sc,px1,py1,1,state);
+	  this->LastClickedPointScaled[0]=slice_sc;
+	  this->LastClickedPointScaled[1]=px1;
+	  this->LastClickedPointScaled[2]=py1;
+	  break;
+	case 1:
+	  if (sendtoeditor)
+	    this->Editor->HandleClickedPoint(px1,slice_sc,py1,1,state);
+	  this->LastClickedPointScaled[0]=px1;
+	  this->LastClickedPointScaled[1]=slice_sc;
+	  this->LastClickedPointScaled[2]=py1;
+	  break;
+	case 2:
+	  if (sendtoeditor)
+	    this->Editor->HandleClickedPoint(px1,py1,slice_sc,1,state);
+	  this->LastClickedPointScaled[0]=px1;
+	  this->LastClickedPointScaled[1]=py1;
+	  this->LastClickedPointScaled[2]=slice_sc;
+	  break;
+	}
+      
+      double lv[3];
+      for (int ia=0;ia<=2;ia++)
+	lv[ia]=(this->LastClickedPointScaled[ia]-ori[ia])/sp[ia];
+      this->SetLastClickedPoint(lv);
+      
+      
+      int   dim[3];   
+      currentImage->GetDimensions(dim);
+      lv[0]=Frange(lv[0],0,dim[0]-1);
+      lv[1]=Frange(lv[1],0,dim[1]-1);
+      lv[2]=Frange(lv[2],0,dim[2]-1);
+      
+      this->UpdateStatusLabels();
+
+      UpdateDisplay();
+      this->ExecuteCoordinatesChangeCallback();
+      return 1;
+    }
+
+  if ( nbutton!=1 && nbutton!=4 && nbutton!=7)
+    {
+      return renderer[found]->HandleMouseButtonEvent(nbutton,state,x,y,ev);
+    }
+
+  return 0;
+  
+}
+// -------------------------------------------------------------------------
+void  vtkpxGUIMosaicViewer::SetShowControls(int show)
+{
+  show=(show>0);
+  if (show==this->show_controlframe)
+    return;
+
+  this->show_controlframe=show;
+
+  PXTkFrame* fr=(PXTkFrame*)controlFrame->getGadgetParent();
+  if (this->controlFrame!=NULL && fr!=NULL)
+    {
+      if (this->show_controlframe==1)
+	{
+	  if (!single_slice_mode)
+	    fr->addChildren("-side right -expand false",controlFrame);
+	  else
+	    fr->addChildren("-side bottom -expand false -fill x",controlFrame);
+	}
+      else
+	fr->unmapChild(controlFrame);
+    }
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::InitControls(PXTkFrame* parwidget,int dohighlight)
+{
+  controlFrame=new PXTkFrame(this->EventManager,parwidget);
+  parwidget->setPackMode(PXTrue);
+
+  
+  if (!single_slice_mode)
+    {
+      parwidget->addChildren("-side right -expand false",controlFrame);
+
+      PXTkFrame* iframe=new PXTkFrame(this->EventManager,controlFrame);
+      interpolateMode=new PXTkCheckButton(this->EventManager,iframe,"Interpolation",205);
+      interpolateMode->setState(PXTrue);
+
+      showLabels=new PXTkCheckButton(this->EventManager,iframe,"Labels",207);
+      showLabels->setState(PXTrue);
+
+      if (!this->createTalairachButtons)
+	{
+	  if (this->showLabels!=NULL)
+	    controlFrame->addChildren("-side top -expand false -fill x",showLabels);
+	  controlFrame->addChildren("-side top -expand false -fill x",interpolateMode);
+	}
+      else
+	{
+	  if (this->showLabels!=NULL)
+	    controlFrame->addChildren("-side left -expand false -fill x",showLabels);
+	  controlFrame->addChildren("-side left -expand false -fill x",interpolateMode);
+	}
+
+      controlFrame->addChildren("-side top -expand false",iframe);
+
+      PXTkDualArrowLabel* zoom=new PXTkDualArrowLabel(this->EventManager,controlFrame,"Zoom",201,202,0);
+
+
+      if (!xy_slice_only)
+	{
+	  currentPlane=new PXTkOptionMenu(this->EventManager,controlFrame,"YZ",203);
+	  currentPlane->addOption("XZ");
+	  currentPlane->addOption("XY");
+	  currentPlane->setIndex(2);
+	  controlFrame->addChildren("-side top -expand false -fill x",currentPlane);
+	}
+
+      statusLabel=new PXTkLabel(this->EventManager,controlFrame,"PI:");
+      statusLabel->configure("-bg","black");
+      statusLabel->configure("-fg","white");
+      statusLabel->configure("-width","25");
+      controlFrame->addChildren("-side top -expand false -fill x -padx 2",statusLabel);
+
+      if (this->createTalairachButtons)
+	{
+	  PXTkFrame* tframe2=new PXTkFrame(this->EventManager,controlFrame);
+	  controlFrame->addChildren("-side top -expand true -fill x",tframe2);
+	  
+	  PXTkButton*   talairachButton[2];
+	  talairachButton[0]=new PXTkButton(this->EventManager,tframe2,"Tal",402);
+	  talairachButton[0]->configure("-pady","0");
+	  talairachButton[0]->configure("-padx","1");
+	  talairachButton[0]->configure("-fg","red");
+	  talairachButton[1]=new PXTkButton(this->EventManager,tframe2,"Tal NEU",403);
+	  
+	  talairachButton[1]->configure("-pady","0");
+	  talairachButton[1]->configure("-padx","1");
+	  
+	  
+	  mniLabel=new PXTkLabel(this->EventManager,tframe2,"");
+	  mniLabel->configure("-bg","black");
+	  mniLabel->configure("-fg","white");
+	  mniLabel->configure("-width","25");
+	  mniLabel->configure("-padx","0");
+	  //	  tframe2->addChildren("-side right -expand false",talairachButton[1],talairachButton[0]);
+	  tframe2->addChildren("-side left -expand true -fill x -padx 2",mniLabel);
+	}
+
+      viewerPresetsRow=new PXTkArrowScale(this->EventManager,controlFrame,"Rows:",401);
+      viewerPresetsRow->setRange(1,8);
+      viewerPresetsRow->setIncrement(1);
+      viewerPresetsRow->setResolution(1);
+      viewerPresetsRow->setValue(1);
+      viewerPresetsRow->setLengthWidth(90,10);
+
+      viewerPresetsCol=new PXTkArrowScale(this->EventManager,controlFrame,"Cols:",401);
+      viewerPresetsCol->setRange(1,12);
+      viewerPresetsCol->setIncrement(1);
+      viewerPresetsCol->setResolution(1);
+      viewerPresetsCol->setValue(1);
+      viewerPresetsCol->setLengthWidth(90,10);
+
+
+      controlFrame->addChildren("-side top -expand true -fill x",viewerPresetsRow->getMainWindow(),viewerPresetsCol->getMainWindow());
+
+      this->extraFrame=new PXTkFrame(this->EventManager,controlFrame);
+
+
+      beginSlice=new PXTkArrowScale(this->EventManager,controlFrame,"First Slice",206,PXTrue);
+      beginSlice->setLengthWidth(90,10);
+      controlFrame->addChildren("-side top -expand t -fill x",this->extraFrame,beginSlice->getMainWindow());
+
+      incrementSlice=new PXTkArrowScale(this->EventManager,controlFrame,"Increment",206,PXTrue);
+      incrementSlice->setRange(1,20);
+      incrementSlice->setIncrement(1);
+      incrementSlice->setResolution(1);
+      incrementSlice->setValue(1);
+      incrementSlice->setLengthWidth(90,10);
+      PXTkFrame* ordFrame=new PXTkFrame(this->EventManager,controlFrame);
+
+      controlFrame->addChildren("-side top -expand t -fill x",incrementSlice->getMainWindow(),ordFrame);
+
+      reverseOrder=new PXTkCheckButton(this->EventManager,ordFrame,"Reverse Inc",206);
+      transposeOrder=new PXTkCheckButton(this->EventManager,ordFrame,"Transpose",401);
+      ordFrame->addChildren("-side left -expand t -fill x",reverseOrder,transposeOrder);
+
+      this->timeframeControlFrame=new PXTkFrame(this->EventManager,controlFrame);
+      controlFrame->addChildren("-side top -expand t -fill x",timeframeControlFrame);
+      
+      frameScale=new PXTkArrowScale(this->EventManager,this->timeframeControlFrame,"Frame No:",206,PXTrue);
+      frameScale->setRange(1,1);
+      frameScale->setIncrement(1);
+      frameScale->setResolution(1);
+      frameScale->setValue(1);
+      frameScale->setLengthWidth(10,10);
+      timeframeControlFrame->addChildren("-side top -expand t -fill x",frameScale->getMainWindow());
+      
+      if (this->ownsLookupTable)
+	{
+	  PXTkFrame* colFrame=new PXTkFrame(this->EventManager,controlFrame);
+	  PXTkButton* b1c0=new PXTkButton(this->EventManager,colFrame,"St",214);
+	  b1c0->configure("-padx",0);
+	  PXTkButton* b1c=new PXTkButton(this->EventManager,colFrame,"Nr",215);
+	  b1c->configure("-padx",0);
+	  PXTkButton* b1d=new PXTkButton(this->EventManager,colFrame,"F1",216);
+	  b1d->configure("-padx",0);
+	  PXTkButton* b1e=new PXTkButton(this->EventManager,colFrame,"F2",217);
+	  b1e->configure("-padx",0);
+	  PXTkButton* b1f1=new PXTkButton(this->EventManager,colFrame,"F4",219);
+	  b1f1->configure("-padx",0);
+	  PXTkButton* b1g=new PXTkButton(this->EventManager,colFrame,"Cmap",209);
+	  b1g->configure("-padx",0);
+	  colFrame->addChildren("-side left -expand true -fill x",b1c0,b1c);
+	  colFrame->addChildren("-side left -expand true -fill x",b1d,b1e);
+	  colFrame->addChildren("-side right -expand true -fill both",b1g,b1f1);
+	  controlFrame->addChildren("-side top -expand true -fill x",colFrame);
+	}
+      
+      PXTkFrame* botFrame=new PXTkFrame(this->EventManager,controlFrame);
+      PXTkButton* b1=new PXTkButton(this->EventManager,botFrame,"Reset",208);
+      PXTkButton* b2=new PXTkButton(this->EventManager,botFrame,"Snap",221);
+
+
+
+      botFrame->addChildren("-side left -expand true -fill x ",b1,b2);
+      controlFrame->addChildren("-side top -expand true -fill x",zoom,botFrame);
+    }
+  else
+    {
+      parwidget->addChildren("-side bottom -expand false -fill x",controlFrame);
+      interpolateMode=new PXTkCheckButton(this->EventManager,controlFrame,"Interp",205);
+      interpolateMode->setState(PXTrue);
+
+      PXTkButton* b1=new PXTkButton(this->EventManager,controlFrame,"Reset",208);
+      controlFrame->addChildren("-side right -expand t -fill x",interpolateMode,b1);
+      
+      if (this->ownsLookupTable)
+	{
+	  PXTkButton* b1c=new PXTkButton(this->EventManager,controlFrame,"ColorMap",209);
+	  controlFrame->addChildren("-side right -expand t -fill x",interpolateMode,b1c);
+	}
+
+      //#ifdef _WIN32
+      PXTkDualArrowLabel* zoom=new PXTkDualArrowLabel(this->EventManager,controlFrame,"Zoom",201,202,0);
+      controlFrame->addChildren("-side right -expand t -fill x",zoom);
+      //#endif
+
+      this->timeframeControlFrame=new PXTkFrame(this->EventManager,controlFrame);
+      controlFrame->addChildren("-side left -expand f -fill x -padx 2 ",timeframeControlFrame);
+
+      this->extraFrame=new PXTkFrame(this->EventManager,controlFrame);
+
+      beginSlice=new PXTkArrowScale(this->EventManager,timeframeControlFrame,"Slice:",206,PXTrue);
+      beginSlice->setLengthWidth(120,15);
+     
+      frameScale=new PXTkArrowScale(this->EventManager,this->timeframeControlFrame,"Frame:",206,PXTrue);
+      frameScale->setRange(1,1);
+      frameScale->setIncrement(1);
+      frameScale->setResolution(1);
+      frameScale->setValue(1);
+      frameScale->setLengthWidth(10,10);
+      timeframeControlFrame->addChildren("-side left -expand f -fill x",
+					 this->extraFrame,
+					 beginSlice->getMainWindow(),
+					 frameScale->getMainWindow());
+
+      statusLabel=new PXTkLabel(this->EventManager,controlFrame,"PI:");
+      statusLabel->configure("-bg","black");
+      statusLabel->configure("-fg","white");
+      statusLabel->configure("-width","24");
+
+      PXTkButton* b2=new PXTkButton(this->EventManager,controlFrame,"Snapshot",221);
+
+      controlFrame->addChildren("-side left -expand false -fill x -padx 0",statusLabel,b2);
+    }
+
+  if (this->CurrentImageIsColor)
+    this->ShowFrameControls(0);
+
+  beginSlice->setRange(float(offset),float(10.0+offset));
+  beginSlice->setValue(float(offset));
+  beginSlice->setIncrement(1.0);
+  beginSlice->setResolution(1.0);
+
+  if (dohighlight && !single_slice_mode)
+      {
+	PXTkButton* b1d=new PXTkButton(this->EventManager,controlFrame,"Highlight",210);
+	controlFrame->addChildren("-side bottom -expand f -fill x",b1d);
+	
+	highlightGUI=new PXTkDialog(this->EventManager,controlFrame,"Highlight Control",PXFalse);
+	highlightGUI->initDisplay();
+	
+	PXTkFrame* highlightFrame=(PXTkFrame*)highlightGUI->getMainWindow();
+	highlightFrame->setPackMode(PXFalse);
+	
+	for (int kk=0;kk<=2;kk++)
+	    for (int jj=0;jj<=1;jj++)
+		{
+		  int index=kk*2+jj;
+		  
+		  switch (index)
+		      {
+		      case 0:
+			strcpy(pxtk_buffer4,"X-Min");	  break;
+		      case 1:
+			strcpy(pxtk_buffer4,"X-Max");	  break;
+		      case 2:
+			strcpy(pxtk_buffer4,"Y-Min");	  break;
+		      case 3:
+			strcpy(pxtk_buffer4,"Y-Max");	  break;
+		      case 4:
+			strcpy(pxtk_buffer4,"Z-Min");	  break;
+		      case 5:
+			strcpy(pxtk_buffer4,"Z-Max");	  break;
+		      }
+		  
+		  highlightscale[index]=new PXTkArrowScale(this->EventManager,highlightFrame,pxtk_buffer4,211,PXTrue);
+		  highlightscale[index]->setRange(offset,offset+10);
+		  highlightscale[index]->setValue(offset);
+		  highlightscale[index]->setIncrement(1.0);
+		  highlightscale[index]->setResolution(1.0);
+		  highlightscale[index]->setLengthWidth(90,10);
+		  highlightFrame->gridRowColumnChild(highlightscale[index]->getMainWindow(),kk+1,jj);
+		}
+	
+	showhighlight=new PXTkCheckButton(this->EventManager,highlightFrame,"Show",212);
+	highlightFrame->gridRowColumnChild(showhighlight,0,0,1,1);
+	
+	PXTkButton* b51=new PXTkButton(highlightGUI,highlightFrame,"Reset",213); 
+	highlightFrame->gridRowColumnChild(b51,0,1,1,1);
+	
+	PXTkButton* b5=new PXTkButton(highlightGUI,highlightFrame,"Close",3); 
+	highlightFrame->gridRowColumnChild(b5,4,0,1,2);
+      }
+
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::InitViewer(PXTkFrame* parFrame)
+{
+  render_widget=new PXVTkTkRenderWidget(this->EventManager,parFrame,300);
+  render_widget->setWidthHeight(400,400);
+  parFrame->setPackMode(PXTrue);
+  parFrame->addChildren("-side left -expand true -fill both",render_widget);
+  render_widget->bindMouseEvents();
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::GetBounds(double bounds[6])
+{
+  if (!hasImage)
+      return;
+
+  int   range[3]; currentImage->GetDimensions(range);
+  double sp[3];    currentImage->GetSpacing(sp);
+  double ori[3];   currentImage->GetOrigin(ori);
+
+  for (int k=0;k<=2;k++)
+      {
+	bounds[2*k]  =      ori[k]-0.5*sp[k];
+	bounds[2*k+1]=float(range[k]-0.5)*sp[k]+ori[k];
+      }
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::UpdateHighlights()
+{
+  if (highlightGUI==NULL)
+      return;
+
+  int hlevels[6];
+
+  for (int k=0;k<=2;k++)
+      {
+	HighlightLevels[k*2]=int(highlightscale[k*2]->getValue());
+	HighlightLevels[k*2+1]=int(highlightscale[k*2+1]->getValue());
+	if ( HighlightLevels[k*2+1] <=	HighlightLevels[k*2])
+	  {
+	    highlightscale[k*2+1]->setValue(HighlightLevels[k*2]+1);
+	    HighlightLevels[k*2+1]=int(highlightscale[k*2+1]->getValue());
+	  }
+	hlevels[k*2]=int(highlightscale[k*2]->getValue()-float(offset));
+	hlevels[k*2+1]=int(highlightscale[k*2+1]->getValue()-float(offset));
+      }
+ 
+  if (showhighlight->getState() && hasImage)
+      {
+	for (int kk=0;kk<MVP_MAX_VIEWERS;kk++)
+	    if (initialized[kk]==PXTrue)
+		imageSlice[kk]->SetHighlightBounds(hlevels[0],
+						   hlevels[1],
+						   hlevels[2],
+						   hlevels[3],
+						   hlevels[4],
+						   hlevels[5]);
+      }
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::SetHighlightLevels(int p1,int p2,int p3,int p4,int p5,int p6)
+{
+  if (p1>=0)   HighlightLevels[0]=p1;
+  if (p2>=0)   HighlightLevels[1]=p2;
+  if (p3>=0)   HighlightLevels[2]=p3;
+  if (p4>=0)   HighlightLevels[3]=p4;
+  if (p5>=0)   HighlightLevels[4]=p5;
+  if (p6>=0)   HighlightLevels[5]=p6;
+
+  // Force Callback 
+  if (highlightGUI!=NULL)
+    {
+      for (int i=0;i<=5;i++)
+	highlightscale[i]->setValue(HighlightLevels[i]);
+      showhighlight->setState(PXTrue);
+      UpdateHighlights();
+      UpdateDisplay();
+    }
+  
+}
+
+char* vtkpxGUIMosaicViewer::GetRenderWidgetName()
+{
+  if (this->render_widget==NULL)
+    return NULL;
+  else
+    return this->render_widget->getWidgetName();
+}
+// -------------------------------------------------------------------------
+
+
+vtkRenderer* vtkpxGUIMosaicViewer::GetRenderer(int i)
+{
+  i=Irange(i,0,MVP_MAX_VIEWERS-1);
+  if (initialized[i])
+      return renderer[i]->GetRenderer();
+  else
+      return NULL;
+}
+
+vtkpxGUIRenderer* vtkpxGUIMosaicViewer::GetGUIRenderer(int i)
+{
+  i=Irange(i,0,MVP_MAX_VIEWERS-1);
+  if (initialized[i])
+    return renderer[i];
+  else
+    return NULL;
+}
+
+char* vtkpxGUIMosaicViewer::GetControlFrameName()
+{
+  if (this->Initialized==0)
+    return NULL;
+  
+  return this->controlFrame->getWidgetName();
+}
+
+
+
+PXTkFrame* vtkpxGUIMosaicViewer::GetControlFrame()
+{
+  if (this->Initialized==0)
+    return NULL;
+  
+  return this->controlFrame;
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUIMosaicViewer::ShowFrameControls(int show)
+{
+  if (!this->Initialized || frameScale==NULL)
+    {
+      return;
+    }
+  
+  if (show==0)
+    {
+      frameScale->setLengthWidth(10,10);
+      timeframeControlFrame->unmapChild(frameScale->getMainWindow());
+      timeframeControlFrame->configure("-width",0);
+    }
+  else
+    {
+      frameScale->setLengthWidth(50,10);
+      beginSlice->setLengthWidth(70,10);
+      timeframeControlFrame->addChildren("-side left -expand t -fill x",frameScale->getMainWindow());
+    }
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIMosaicViewer::UpdateDisplay()
+{
+  if (this->Initialized && this->donotRender==0)
+    {
+      if (inexpose==1 || this->EnableRendering==0)
+	{
+	  ++inexposecount;
+	  return TCL_OK;
+	}
+
+      inexpose=1;
+      PXTkApp::executeTclCommand("update display");
+      render_widget->getRenderWindow()->Render();  
+      this->LastEvent=-1;
+      inexposecount=0;
+      inexpose=0;
+      return TCL_OK;
+    }
+  return TCL_OK;
+}
+
+
+
+// -------------------------------------------------------------------------	    
+int vtkpxGUIMosaicViewer::UpdateStatusLabels()
+{
+  double pos[3]; this->GetLastClickedPointScaled(pos);
+  double sp[3];    currentImage->GetSpacing(sp);
+  double ori[3];   currentImage->GetOrigin(ori);
+  int    dim[3];   currentImage->GetDimensions(dim);
+
+  int level[3];
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      level[ia]=int((pos[ia]-ori[ia])/sp[ia]+0.5);
+      if (level[ia]<0)
+	level[ia]=0;
+      else if (level[ia]>=dim[ia])
+	level[ia]=dim[ia]-1;
+
+      pos[ia]=double(level[ia])*sp[ia]+ori[ia];
+      
+    }
+
+  if (this->createTalairachButtons && this->talairachTransform!=NULL)
+    {
+      this->DisplayNeuroCoordinates(pos,level,statusLabel,mniLabel);
+    }
+  else
+    {
+      double vl=0.0;
+      if (this->valueImage!=NULL)
+	vl=valueImage->GetScalarComponentAsDouble(level[0],level[1],level[2],this->CurrentFrame);
+      else
+	vl=currentImage->GetScalarComponentAsDouble(level[0],level[1],level[2],this->CurrentFrame);
+
+      std::string objlabel=this->GetObjectmapValueAsText(level[0],level[1],level[2]);
+      sprintf(pxtk_buffer,"(%d %d %d) %s %s",level[0],level[1],level[2],
+	      this->GetFormatedNumber(vl,3),
+	      objlabel.c_str());
+      statusLabel->setText(pxtk_buffer);
+      if (this->createTalairachButtons)
+	mniLabel->setText("");
+
+    }
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIMosaicViewer.h b/bioimagesuite30_src/GUI/vtkpxGUIMosaicViewer.h
new file mode 100644
index 0000000..dbacb46
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIMosaicViewer.h
@@ -0,0 +1,220 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIMosaicViewer.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIMosaicViewer 
+// .SECTION Description
+
+#ifndef __vtkpxGUIMosaicViewer_h
+#define __vtkpxGUIMosaicViewer_h
+
+
+#include "pxtkcomplexwidgets.h"
+#include "pxtkdialog.h"
+#include "pxvtkgadgets.h"
+
+#include "vtkpxGUIBaseImageViewer.h"
+#include "vtkpxGUIRenderer.h"
+#include "vtkpxImageSlice.h"
+#include "vtkpxUtil.h"
+#include "vtkpxGUIBaseCurveEditor.h"
+
+
+
+const int MVP_MAX_VIEWERS=100;
+
+class  vtkpxGUIMosaicViewer : public vtkpxGUIBaseImageViewer
+{
+public:
+  static vtkpxGUIMosaicViewer *New();
+  vtkTypeMacro(vtkpxGUIMosaicViewer,vtkpxGUIBaseImageViewer);
+  
+  // Initialize Display  
+  virtual char*  Initialize(const char* name,int inside);
+  virtual void   Update();
+
+
+  virtual void SetOffset(int off);
+  virtual void SetXYSliceOnly();
+  virtual void SetSingleSliceMode();
+  virtual void ShowFrameControls(int show=1);
+
+  virtual int  InitializeViewer();
+  virtual int  ResetViewer();
+
+  virtual int  UpdateAllViewers();
+  virtual int  UpdateViewers(int firstv,int lastv);
+  virtual int  UpdateDisplay();
+  virtual int  ResetAll();
+
+  virtual int GetBeginSlice();
+  virtual int GetIncrement();
+
+  virtual void SetCurrentFrame(int t);
+
+  virtual char* GetRenderWidgetName();
+
+  virtual int  HandleEvent(int eventno);
+  virtual int  HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev);
+
+  vtkGetVectorMacro(HighlightLevels,int,6);
+  virtual void SetHighlightLevels(int p1,int p2,int p3,int p4,int p5,int p6);
+
+  virtual void SetEditor(vtkpxGUIBaseCurveEditor* cont) { Editor=cont;}
+  vtkSetMacro(MouseToEditor,int);
+  vtkGetMacro(MouseToEditor,int);
+  vtkSetMacro(ShiftMouseToEditor,int);
+  vtkGetMacro(ShiftMouseToEditor,int);
+  vtkGetMacro(NumberOfViewers,int);
+  
+  virtual vtkRenderer* GetRenderer(int i);
+  virtual vtkRenderer* GetRenderer() { return GetRenderer(0);}
+
+  virtual vtkpxGUIRenderer* GetGUIRenderer(int i);
+  virtual vtkpxGUIRenderer* GetGUIRenderer() { return GetGUIRenderer(0);}
+
+  virtual char* GetControlFrameName();
+
+  //BTX
+  virtual PXTkFrame* GetControlFrame();
+  //ETX
+
+  virtual void SetConfiguration(int row,int col);
+  virtual void  SetShowControls(int show=1);
+
+protected:
+
+  vtkpxGUIRenderer*         renderer[MVP_MAX_VIEWERS];
+  PXVTkTkRenderWidget*      render_widget;
+  vtkpxImageSlice*          imageSlice[MVP_MAX_VIEWERS];
+  PXBool                    initialized[MVP_MAX_VIEWERS];
+
+  vtkpxGUIBaseCurveEditor*  Editor;
+  int                       MouseToEditor;
+  int                       ShiftMouseToEditor;
+  int                       CreateHighlights;
+
+  PXTkFrame*                controlFrame;
+  PXTkFrame*                extraFrame;
+  PXTkFrame*                timeframeControlFrame;
+
+  PXTkLabel*                statusLabel;
+  PXTkLabel*                mniLabel;
+
+
+
+  int                       NumberOfViewers;
+  int                       NumberOfRows;
+  int                       NumberOfColumns;
+  int                       MaximumNumberOfViewers;
+
+  int                       offset;
+  int                       donotRender;
+
+
+  PXTkCheckButton*          interpolateMode;
+  PXTkCheckButton*          showLabels;
+  PXTkCheckButton*          reverseOrder;
+  PXTkCheckButton*          transposeOrder;
+  PXTkArrowScale            *viewerPresetsRow;
+  PXTkArrowScale            *viewerPresetsCol;
+  PXTkArrowScale            *beginSlice;
+  PXTkArrowScale            *incrementSlice;
+  PXTkArrowScale            *frameScale;
+
+  PXTkDialog*               highlightGUI;
+  PXTkArrowScale*           highlightscale[6];
+  PXTkCheckButton*          showhighlight;
+  int                       HighlightLevels[6];
+
+  PXTkOptionMenu*           currentPlane;
+
+
+
+  PXBool                    single_slice_mode;
+  PXBool                    xy_slice_only;
+
+  vtkpxGUIMosaicViewer();
+  virtual ~vtkpxGUIMosaicViewer();
+   
+
+  virtual void SetNumberOfViewers(int numv);
+  virtual void ChangeSliceIncrement(int sl=-1,int incr=-1,int fr=-1);
+
+  virtual void SetViewports();
+  virtual void CreateViewerAndSlice(int index);
+  virtual int  GetViewerSlice(int v);
+
+  virtual void InitControls(PXTkFrame* parent,int hm=1);
+  virtual void InitViewer(PXTkFrame* parent);
+
+  virtual void GetBounds(double bounds[6]);
+  virtual void UpdateHighlights();
+
+  virtual int UpdateIntensityLabelInfo() { return this->UpdateStatusLabels(); }
+  virtual int UpdateStatusLabels();
+
+  virtual int ResetEditor();
+
+  // Flags to check for Rendering
+  //BTX
+  int inexpose,inexposecount,firsttime,olddimensions[3];
+  int                        show_controlframe;
+  //ETX
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIMultipleMosaicViewer.cpp b/bioimagesuite30_src/GUI/vtkpxGUIMultipleMosaicViewer.cpp
new file mode 100644
index 0000000..3c25057
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIMultipleMosaicViewer.cpp
@@ -0,0 +1,451 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIMultipleMosaicViewer.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/02/03 15:28:38 $
+  Version:   $Revision: 1.3 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "pxutil.h"
+#include "vtkActor.h"
+#include "vtkImageQuantizeRGBToIndex.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxGUIMultipleMosaicViewer.h"
+#include "vtkpxTalairachTransform.h"
+// -------------------------------------------------------------------------
+vtkpxGUIMultipleMosaicViewer* vtkpxGUIMultipleMosaicViewer::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIMultipleMosaicViewer");
+  if(ret)
+      {
+	return (vtkpxGUIMultipleMosaicViewer*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIMultipleMosaicViewer;
+}
+// -------------------------------------------------------------------------
+// Construct object with no children.
+vtkpxGUIMultipleMosaicViewer::vtkpxGUIMultipleMosaicViewer()
+{
+  for (int i=0;i<=3;i++)
+    AuxImages[i]=NULL;
+}
+// -------------------------------------------------------------------------
+vtkpxGUIMultipleMosaicViewer::~vtkpxGUIMultipleMosaicViewer()
+{
+  for (int i=0;i<=3;i++)
+    {
+      if (AuxImages[i]!=NULL)
+	AuxImages[i]->Delete();
+    }
+
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIMultipleMosaicViewer::ResetViewer()
+{
+  //  fprintf(stderr,"Reseting Viewer check for changes to auxiliary images\n");
+  if (!(hasImage && this->Initialized))
+      return 0;
+
+  int dim[3],auxdim[3];
+
+  this->currentImage->GetDimensions(dim);
+
+  int flag=0;
+  for (int i=0;i<=3;i++)
+    {
+      if (this->AuxImages[i]!=NULL)
+	{
+	  this->AuxImages[i]->GetDimensions(auxdim);
+	  for (int i=0;i<=2;i++)
+	    if (dim[i]!=auxdim[i])
+	      flag++;
+	}
+    }
+
+  if (flag>0)
+    {
+      for (int i=0;i<=3;i++)
+	{
+	  if (this->AuxImages[i]!=NULL)
+	    this->AuxImages[i]->Delete();
+	  this->AuxImages[i]=NULL;
+	}
+    }
+  
+  if (this->GetNumberOfImages()<=1)
+    {
+      viewerPresetsRow->enable(PXTrue);
+      vtkpxGUIMosaicViewer::ResetViewer();
+    }
+  else
+    {
+      viewerPresetsRow->enable(PXTrue);
+      viewerPresetsRow->setValue((float)this->GetNumberOfImages(),PXFalse);
+      viewerPresetsRow->enable(PXFalse);
+      this->SetConfiguration(this->GetNumberOfImages(),this->NumberOfColumns);
+    }
+  return TCL_OK;
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUIMultipleMosaicViewer::UpdateViewers(int firstv,int lastv)
+{
+  if (!hasImage)
+      return TCL_ERROR;
+
+  firstv=Irange(firstv,0,this->NumberOfViewers-1);
+  lastv=Irange(lastv,0,this->NumberOfViewers-1);
+
+  // Read UI variables 
+  int plane=2;
+  if (!single_slice_mode && !xy_slice_only )
+      plane=currentPlane->getIndex();
+  int dim[3];     currentImage->GetDimensions(dim);
+  int frame=this->CurrentFrame;
+
+  double sp[3];  currentImage->GetSpacing(sp);
+  double ori[3]; currentImage->GetOrigin(ori);
+
+  this->EventManager->setWaitCursor(PXTrue);
+
+  if (this->Orientation==3)
+    {
+      dim[0]=dim[1];
+      dim[1]=dim[2];
+    }
+
+  //  fprintf(stderr,"\n************************************************\n Updating Viewers %d:%d\n",firstv,lastv);
+
+  for (int k=firstv;k<=lastv;k++)
+    {
+      //      fprintf(stderr,"********* Updating Viewer %d\n",k);
+      int doreset=0;
+      int doclip=1;
+      if (this->Orientation!=3)
+	{
+	  renderer[k]->SetClipMode(PXTrue);
+	  doclip=1;
+	}
+      else
+	renderer[k]->SetClipMode(PXFalse);
+
+      renderer[k]->SetCameraScale(renderer[0]->GetCameraScale());
+
+      if (renderer[k]->GetPlaneMode()!=plane)
+	{
+	  doreset=1;
+	  renderer[k]->SetPlaneMode(plane);
+	  imageSlice[k]->SetCurrentPlane(plane);
+	  renderer[k]->SetFlipMode(0);
+	}
+      
+      int slice=this->GetViewerSlice(k);
+      int row=this->GetRow(k);
+      vtkImageData* img=this->GetIndexedImage(row);
+
+      //      fprintf(stderr,"\t\t\t Slice=%d row=%d \n",slice,row);
+
+      renderer[k]->SetClipBounds(slice,slice,slice,sp,ori);
+      renderer[k]->SetViewerCoordinates(slice,slice,slice);
+      
+      if (slice<dim[plane] && slice>=0)
+	{
+	  imageSlice[k]->SetInput(img);
+	  imageSlice[k]->SetFrame(frame);
+	  imageSlice[k]->SetLevel(slice);
+	  imageSlice[k]->SetCurrentPlane(plane);
+	  imageSlice[k]->SetDisplayMode(2);
+	  imageSlice[k]->Update();
+	  renderer[k]->SetViewerCoordinates(slice,slice,slice);
+	  char line[250];
+
+  
+	  if (!single_slice_mode && !xy_slice_only ) 
+	    {
+	      int axis;
+	      double mni=this->GetMNISliceNo(slice,plane,axis);
+	      if (axis==-1)
+		{
+		  sprintf(line,"Slice=%d/%d (%s)",
+			  slice,dim[plane]-1,
+			  currentPlane->getLabel(imageSlice[k]->GetCurrentPlane()));
+		}
+	      else
+		{
+		  switch (axis) {
+		  case 0: sprintf(line,"MNI X=%.0f Slice=%d/%d",mni,slice,dim[plane]-1); break;
+		  case 1: sprintf(line,"MNI Y=%.0f Slice=%d/%d",mni,slice,dim[plane]-1); break;
+		  case 2: sprintf(line,"MNI Z=%.0f Slice=%d/%d",mni,slice,dim[plane]-1); break;
+		  }
+		}
+	      renderer[k]->SetLabel(line,0.05,0.05,0.73,0.73,0.0);
+	    }
+	}
+      else
+	{
+	  renderer[k]->SetLabel("None",0.05,0.05,
+				0.8,0.8,0.0);
+	  imageSlice[k]->SetDisplayMode(1);
+	  imageSlice[k]->Update();
+	}
+      
+      if (this->showLabels!=NULL)
+	{
+	  if (this->showLabels->getState()==PXTrue)
+	    renderer[k]->ShowLabel();
+	  else
+	    renderer[k]->HideLabel();
+	}
+
+      if (this->Orientation==3)
+	renderer[k]->MoveAbove();
+
+      if (doreset)
+	{
+	  renderer[k]->SetClipThickness(currentImage->GetSpacing()[plane]);
+	  renderer[k]->Reset();
+      	}
+      
+      if (doclip)
+	renderer[k]->Clip();
+
+    }  
+  this->EventManager->setWaitCursor(PXFalse);
+  return TCL_OK;
+}
+
+int vtkpxGUIMultipleMosaicViewer::GetNumberOfImages()
+{
+  if (!hasImage)
+    return 0;
+
+  int numimg=1;
+  for (int i=0;i<=3;i++)
+    {
+      if (this->AuxImages[i]!=NULL)
+	numimg++;
+    }
+
+  //  fprintf(stderr,"\t\t Number of Images=%d\n",numimg);
+
+  return numimg;
+
+}
+
+vtkImageData* vtkpxGUIMultipleMosaicViewer::GetIndexedImage(int index)
+{
+  if (!hasImage)
+      return NULL;
+
+  if (this->GetNumberOfImages()==1)
+    {
+      //      fprintf(stderr,"Only One image in memory returning current\n");
+      return this->currentImage;
+    }
+
+  if (index>4)
+    {
+      //      fprintf(stderr,"Bad Indexed Image=%d\n",index);
+      return NULL;
+    }
+
+  if (index<=0)
+    {
+      //      fprintf(stderr,"Indexed image %d = current\n",index);
+      return this->currentImage;
+    }
+
+
+  int count=0;
+  int target=index;
+  int newcount=0;
+
+  //  fprintf(stderr,"Looking for indexed=%d\n",target);
+
+  while (count<=3)
+    {
+      if (this->AuxImages[count]!=NULL)
+	{
+	  ++newcount;
+	  //	  fprintf(stderr,"\t\t AuxImage[%d] not NULL newcound=%d (target=%d)\n",
+	  //  count,newcount,target);
+	  if (newcount==target)
+	    {
+	      //	      fprintf(stderr,"Indexed image %d = aux[%d]\n",index,count);
+	      return this->AuxImages[count];
+	    }
+	} 
+
+      ++count;
+    }
+
+  //  fprintf(stderr,"Bad Indexed Image=%d\n",index);
+  return NULL;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIMultipleMosaicViewer::ClearAuxImages()
+{
+  for (int i=0;i<=3;i++)
+    {
+      if (this->AuxImages[i]!=NULL)
+	this->AuxImages[i]->Delete();
+      this->AuxImages[i]=NULL;
+    }
+  viewerPresetsRow->enable(PXTrue);
+  vtkpxGUIMosaicViewer::ResetViewer();
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIMultipleMosaicViewer::SetConfiguration(int numr,int numc)
+{
+  if (!hasImage)
+      return;
+  int numimg=this->GetNumberOfImages();
+
+  if (numimg==1)
+    vtkpxGUIMosaicViewer::SetConfiguration(numr,numc);
+  else
+    vtkpxGUIMosaicViewer::SetConfiguration(numimg,numc);
+
+  ChangeSliceIncrement(-1,-1,-1);
+  this->UpdateStatusLabels();
+
+}
+// -------------------------------------------------------------------------
+int  vtkpxGUIMultipleMosaicViewer::GetViewerSlice(int v)
+{
+  if (!this->Initialized)
+    return 0;
+
+
+  if (this->GetNumberOfImages()<=1)
+    return vtkpxGUIMosaicViewer::GetViewerSlice(v);
+
+  v=Irange(v,0,this->NumberOfViewers-1);
+  int row=this->GetRow(v);
+  int col=v-row*this->NumberOfColumns;
+    
+  int firstslice=(int)beginSlice->getValue()-offset;
+  if (firstslice<0)
+      firstslice=0;
+  
+  int increment=this->GetIncrement();
+  int final=firstslice+col*increment;
+
+  //  fprintf(stderr,"Viewer =%d slice=%d (row=%d,col+%d)\n",v,final,row,col);
+
+  return final;
+	  
+}
+// -------------------------------------------------------------------------	    
+int vtkpxGUIMultipleMosaicViewer::GetRow(int v)
+{
+  v=Irange(v,0,this->NumberOfViewers-1);
+  if (!this->Initialized)
+    return 0;
+  
+  int row=v/this->NumberOfColumns;
+  //  fprintf(stderr,"Viewer =%d row=%d (num_cols=%d)\n",v,row,this->NumberOfColumns);
+  return row;
+}
+// -------------------------------------------------------------------------	    
+
+void vtkpxGUIMultipleMosaicViewer::SetAuxImage(vtkImageData* img,int index)
+{
+  if (this->currentImage==NULL)
+    return;
+
+  if (index<0)
+    index=0;
+  else if (index>3)
+    index=3;
+
+  if (img==NULL)
+    {
+      if (this->AuxImages[index]!=NULL)
+	this->AuxImages[index]->Delete();
+      this->AuxImages[index]=NULL;
+      return;
+    }
+
+  int dim[3],auxdim[3],flag=0;
+  this->currentImage->GetDimensions(dim);
+  img->GetDimensions(auxdim);
+  for (int i=0;i<=2;i++)
+    if (dim[i]!=auxdim[i])
+      flag++;
+
+  if (flag>0)
+    return;
+
+  
+  if (this->AuxImages[index]==NULL)
+    this->AuxImages[index]=vtkImageData::New();
+
+  this->AuxImages[index]->ShallowCopy(img);
+  //  fprintf(stderr,"Setting Aux Image=%d\n",index);
+
+  if (this->GetNumberOfImages()<=1)
+    {
+      viewerPresetsRow->enable(PXTrue);
+      this->SetConfiguration(this->NumberOfRows,this->NumberOfColumns);
+    }
+  else
+    {
+      viewerPresetsRow->enable(PXTrue);
+      viewerPresetsRow->setValue((float)this->GetNumberOfImages(),PXFalse);
+      viewerPresetsRow->enable(PXFalse);
+      this->SetConfiguration(this->GetNumberOfImages(),this->NumberOfColumns);
+    }
+
+}
+
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIMultipleMosaicViewer.h b/bioimagesuite30_src/GUI/vtkpxGUIMultipleMosaicViewer.h
new file mode 100644
index 0000000..dde5a69
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIMultipleMosaicViewer.h
@@ -0,0 +1,100 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIMultipleMosaicViewer.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIMultipleMosaicViewer 
+// .SECTION Description
+
+#ifndef __vtkpxGUIMultipleMosaicViewer_h
+#define __vtkpxGUIMultipleMosaicViewer_h
+
+
+#include "vtkpxGUIMosaicViewer.h"
+
+class  vtkpxGUIMultipleMosaicViewer : public vtkpxGUIMosaicViewer
+{
+public:
+  static vtkpxGUIMultipleMosaicViewer *New();
+  vtkTypeMacro(vtkpxGUIMultipleMosaicViewer,vtkpxGUIMosaicViewer);
+  
+  // Initialize Display  
+  virtual int  ResetViewer();
+  virtual int  UpdateViewers(int firstv,int lastv);
+
+  // Description:
+  // Set/Get Auxiliary Image Input
+  virtual void SetAuxImage(vtkImageData* img,int index);
+  virtual vtkImageData* GetAuxImage(int index) { return AuxImages[index];}
+
+  // Description:
+  // Bypass NULL in count, currentImage = 0 and non-NULL auxiliary follow
+  virtual int GetNumberOfImages();
+  virtual vtkImageData* GetIndexedImage(int index);
+
+  virtual void SetConfiguration(int numr,int numc);
+  virtual void ClearAuxImages();
+protected:
+
+  vtkpxGUIMultipleMosaicViewer();
+  virtual ~vtkpxGUIMultipleMosaicViewer();
+   
+  virtual int  GetViewerSlice(int v);
+  virtual int  GetRow(int v);
+
+  vtkImageData* AuxImages[4];
+
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObjectmapMosaicEditor.cpp b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapMosaicEditor.cpp
new file mode 100644
index 0000000..c1bf90b
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapMosaicEditor.cpp
@@ -0,0 +1,125 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIObjectmapMosaicEditor.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:14 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxGUIObjectmapMosaicEditor.h"
+#include "vtkpxGUIObjectmapMosaicViewer.h"
+#include "vtkObjectFactory.h"
+
+
+vtkpxGUIObjectmapMosaicEditor* vtkpxGUIObjectmapMosaicEditor::New()
+{
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIObjectmapMosaicEditor");
+  if(ret)
+      {
+	return (vtkpxGUIObjectmapMosaicEditor*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIObjectmapMosaicEditor;
+}
+
+// Construct object with no children.
+vtkpxGUIObjectmapMosaicEditor::vtkpxGUIObjectmapMosaicEditor()
+{
+  this->Viewer=NULL;
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapMosaicEditor::UpdateFromViewer(int mode)
+{
+  if (this->Viewer==NULL)
+    return;
+  if (mode==0)
+    this->SetImagesAndLookupTable(this->Viewer->GetImage(),
+				  this->Viewer->GetObjectMapImage(),NULL,
+				  this->Viewer->GetCurrentImageIsColor());
+  else
+    this->SetImagesAndLookupTable(this->Viewer->GetImage(),
+				  this->Viewer->GetObjectMapImage(),
+				  this->Viewer->GetObjectMapLookupTable(),
+				  this->Viewer->GetCurrentImageIsColor());
+
+}
+
+void vtkpxGUIObjectmapMosaicEditor::UpdateViewerDisplay()
+{
+  if (this->Viewer==NULL)
+    return;
+ 
+  this->Viewer->UpdateDisplay();
+
+}
+
+void vtkpxGUIObjectmapMosaicEditor::UpdateViewerObjectmapColormap()
+{
+   if (this->Viewer==NULL)
+    return;
+ 
+   this->Viewer->SetObjectLookupTable(this->ObjectmapLookupTable,0);
+}
+ 
+void vtkpxGUIObjectmapMosaicEditor::UpdateViewerObjectmap()
+{
+   if (this->Viewer==NULL)
+    return;
+ 
+   this->Viewer->QuickUpdateObjectmap();
+}
+
+void vtkpxGUIObjectmapMosaicEditor::SetObjectmapViewer(vtkpxGUIObjectmapMosaicViewer* viewer)
+{
+  this->Viewer=viewer;
+}
+
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObjectmapMosaicEditor.h b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapMosaicEditor.h
new file mode 100644
index 0000000..7f29cea
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapMosaicEditor.h
@@ -0,0 +1,99 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUI3DObjectmapEditor.h,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:33 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUI3DObjectmapEditor 
+// .SECTION Description
+
+#ifndef __vtkpxGUIObjectmapMosaicEditor_h
+#define __vtkpxGUIObjectmapMosaicEditor_h
+
+#include "vtkpxGUIAbstractMultisliceEditor.h"
+
+class vtkpxGUIObjectmapMosaicViewer;
+
+class  vtkpxGUIObjectmapMosaicEditor : public vtkpxGUIAbstractMultisliceEditor {
+  
+public:
+
+  static vtkpxGUIObjectmapMosaicEditor *New();
+  vtkTypeMacro(vtkpxGUIObjectmapMosaicEditor,vtkpxGUIAbstractMultisliceEditor);
+  
+  // Description:
+  // Set Viewer
+  virtual void SetObjectmapViewer(vtkpxGUIObjectmapMosaicViewer* viewer);
+  
+  // Previously Virtual
+  virtual void UpdateFromViewer(int docmap=0);
+
+protected:
+
+  vtkpxGUIObjectmapMosaicEditor();
+  
+
+  // Description: 
+  // Talking to the Viewer
+  virtual void UpdateViewerDisplay();
+  virtual void UpdateViewerObjectmapColormap();
+  virtual void UpdateViewerObjectmap();
+
+  // Description:
+  // A Pointer to the Viewer 
+  vtkpxGUIObjectmapMosaicViewer* Viewer;
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObjectmapMosaicViewer.cpp b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapMosaicViewer.cpp
new file mode 100644
index 0000000..f662672
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapMosaicViewer.cpp
@@ -0,0 +1,402 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "pxutil.h"
+#include "vtkActor.h"
+#include "vtkImageQuantizeRGBToIndex.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkImageThreshold.h"
+#include "vtkpxColorMapUtil.h"
+#include "vtkpxGUIObjectmapMosaicEditor.h"
+#include "vtkpxGUIObjectmapMosaicViewer.h"
+
+// -------------------------------------------------------------------------
+vtkpxGUIObjectmapMosaicViewer* vtkpxGUIObjectmapMosaicViewer::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIObjectmapMosaicViewer");
+  if(ret)
+      {
+	return (vtkpxGUIObjectmapMosaicViewer*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIObjectmapMosaicViewer;
+}
+// -------------------------------------------------------------------------
+// Construct object with no children.
+vtkpxGUIObjectmapMosaicViewer::vtkpxGUIObjectmapMosaicViewer()
+{
+  maskTransparency=NULL;
+  maskImage=NULL;
+  maskLookupTable=vtkLookupTable::New();
+
+  for (int i=0;i<MVP_MAX_VIEWERS;i++)
+    this->maskImageSlice[i]=NULL;
+
+  this->create_internal_editor=0;
+  this->InternalEditor=NULL;
+  this->ColorMode=0;
+}
+
+// -------------------------------------------------------------------------
+vtkpxGUIObjectmapMosaicViewer::~vtkpxGUIObjectmapMosaicViewer()
+{
+  if (maskImage!=NULL)
+    maskImage->Delete();
+  
+  if (maskLookupTable!=NULL)
+    maskLookupTable->Delete();
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapMosaicViewer::SetCreateInternalEditorOn()
+{
+  if (this->Initialized==0)
+    create_internal_editor=1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIObjectmapMosaicViewer::ResetViewer()
+{
+  if (!(hasImage && this->Initialized))
+      return 0;
+
+
+  this->AutoCreateMaskAndLookupTable();
+  vtkpxGUIMosaicViewer::ResetViewer();
+
+  for (int kk=0;kk<this->NumberOfViewers;kk++)
+    {
+      if (maskImageSlice[kk]!=NULL)
+	{
+	  maskImageSlice[kk]->SetInput(maskImage);
+	  maskImageSlice[kk]->SetFrame(0);
+	  maskImageSlice[kk]->SetLookupTable(this->maskLookupTable);
+	  maskImageSlice[kk]->Update();
+	}
+    }
+
+  if (this->InternalEditor!=NULL)
+    this->InternalEditor->UpdateFromViewer();
+
+  this->UpdateDisplay();
+
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIObjectmapMosaicViewer::HandleEvent(int event)
+{
+  if (event<799)
+      return vtkpxGUIMosaicViewer::HandleEvent(event);
+  
+  if (event==800)
+    {
+      this->SetObjectmapTransparency(this->maskTransparency->getValue());
+      this->LastEvent=event;
+    }
+
+  if (event==801)
+    {
+      if (this->InternalEditor!=NULL)
+	this->InternalEditor->Show();
+    }
+  
+  return TCL_OK;
+  
+}
+
+
+// -------------------------------------------------------------------------
+int vtkpxGUIObjectmapMosaicViewer::UpdateViewers(int firstv,int lastv)
+{
+  int ok=vtkpxGUIMosaicViewer::UpdateViewers(firstv,lastv);
+
+  this->EventManager->setWaitCursor(PXTrue);
+
+  firstv=Irange(firstv,0,this->NumberOfViewers-1);
+  lastv=Irange(lastv,0,this->NumberOfViewers-1);
+
+  for (int k=firstv;k<=lastv;k++)
+    {
+      int lv=imageSlice[k]->GetLevel();
+      int pl=imageSlice[k]->GetCurrentPlane();
+      if (maskImageSlice[k]!=NULL)
+	{
+	  maskImageSlice[k]->SetFrame(0);
+	  maskImageSlice[k]->SetLevel(lv);
+	  maskImageSlice[k]->SetCurrentPlane(pl);
+	  maskImageSlice[k]->SetDisplayMode(2);
+	  maskImageSlice[k]->Update();
+	}
+    }
+  
+  this->EventManager->setWaitCursor(PXFalse);
+  this->UpdateDisplay();
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIObjectmapMosaicViewer::CreateViewerAndSlice(int index)
+{
+  if (hasImage== PXFalse || this->Initialized==0)
+      return;
+
+  index=Irange(index,0,MVP_MAX_VIEWERS-1);
+  if (initialized[index])
+      return;
+
+  vtkpxGUIMosaicViewer::CreateViewerAndSlice(index);
+
+
+  maskImageSlice[index]=vtkpxImageSlice::New();
+  maskImageSlice[index]->SetAutoUpdate(0);
+  maskImageSlice[index]->SetInput(maskImage);
+  maskImageSlice[index]->SetFrame(0);
+  maskImageSlice[index]->SetLookupTable(maskLookupTable);
+  maskImageSlice[index]->SetOpacity(0.5);
+  maskImageSlice[index]->SetInterpolation(0);
+  renderer[index]->GetRenderer()->AddActor(maskImageSlice[index]);
+  
+  return;
+
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIObjectmapMosaicViewer::InitControls(PXTkFrame* parwidget,int dohighlight)
+{
+  vtkpxGUIMosaicViewer::InitControls(parwidget,dohighlight);
+  if (this->extraFrame==NULL)
+    return;
+
+  maskTransparency=new PXTkArrowScale(this->EventManager,extraFrame,"Mask:",800,PXTrue);
+  maskTransparency->setRange(0.0,100.0);
+  maskTransparency->setResolution(1.0);
+  maskTransparency->setValue(50.0);
+  maskTransparency->setLengthWidth(80,15);
+
+  extraFrame->addChildren("-side left -expand true -fill x",maskTransparency->getMainWindow());
+
+  if (create_internal_editor==0)
+    return;
+
+  PXTkButton* ut5=new PXTkButton(this->EventManager,controlFrame,"Show Paint Controls",801); 
+  ut5->configure("-fg","red");
+  controlFrame->addChildren("-side bottom -expand true -fill x -padx 5",ut5);
+  
+
+  this->InternalEditor=vtkpxGUIObjectmapMosaicEditor::New();
+  this->InternalEditor->Initialize(this->GetWidgetName(),0);
+  this->InternalEditor->SetObjectmapViewer(this);
+  //  this->InternalEditor->CreateDefaultLookupTable();
+}
+
+// -------------------------------------------------------------------------
+float vtkpxGUIObjectmapMosaicViewer::GetObjectmapTransparency()
+{
+  if (  this->maskImageSlice[0]==NULL)
+    return 0.0;
+  
+  return 100.0*this->maskImageSlice[0]->GetOpacity();
+}
+
+void vtkpxGUIObjectmapMosaicViewer::SetObjectmapTransparency(float v)
+{
+  if (this->maskImageSlice[0]!=NULL)
+    {
+      v*=0.01;
+      for (int ia=0;ia<this->NumberOfViewers;ia++)
+	{
+	  if (this->maskImageSlice[ia]!=NULL)
+	    maskImageSlice[ia]->SetOpacity(v);
+	}
+      this->UpdateDisplay();
+      this->maskTransparency->setValue(v*100.0,PXFalse);
+    }
+}
+
+void vtkpxGUIObjectmapMosaicViewer::UpdateObjectmap()
+{
+  if (this->maskImageSlice[0]==NULL)
+    return;
+  
+  for (int kk=0;kk<this->NumberOfViewers;kk++)
+    maskImageSlice[kk]->SetInput(maskImage);
+
+  if (this->InternalEditor!=NULL)
+    this->InternalEditor->UpdateFromViewer();
+
+
+  this->UpdateDisplay();
+}
+
+
+int vtkpxGUIObjectmapMosaicViewer::SetObjectMapImage(vtkImageData* img)
+{
+  if ((!hasImage && this->Initialized))
+    return 0;
+  
+  int ndim[3]; img->GetDimensions(ndim);
+  int odim[3]; this->currentImage->GetDimensions(odim);
+  int nc=img->GetNumberOfScalarComponents();
+  int onc=this->currentImage->GetNumberOfScalarComponents();
+  int sum=0;
+  for (int i=0;i<=2;i++)
+    sum+=abs(ndim[i]-odim[i]);
+
+  if (sum!=0 || nc>onc)
+    {
+      vtkErrorMacro(<<"Bad Mask Image Dimensions\n");
+      return 0;
+    }
+  
+  this->maskImage->ShallowCopy(img);
+  double r[2]; img->GetPointData()->GetScalars()->GetRange(r);
+
+  vtkpxSurfaceUtil::DefaultObjectMapLookupTable(maskLookupTable,int(r[1]+2),1);
+  UpdateObjectmap();
+  return 1;
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUIObjectmapMosaicViewer::AutoCreateMaskAndLookupTable()
+{
+  this->ClearMaskImage();
+  if (this->maskLookupTable==NULL)
+    maskLookupTable=vtkLookupTable::New();
+
+  vtkpxSurfaceUtil::DefaultObjectMapLookupTable(maskLookupTable,28,1);
+
+  return 1;
+}
+
+int vtkpxGUIObjectmapMosaicViewer::SetObjectLookupTable(vtkLookupTable* lkp)
+{
+  return this->SetObjectLookupTable(lkp,1);
+}
+
+int vtkpxGUIObjectmapMosaicViewer::SetObjectLookupTable(vtkLookupTable* lkp,int updateeditor)
+{
+  if (lkp==NULL)
+    return 0;
+
+  if (this->maskLookupTable==NULL)
+    maskLookupTable=vtkLookupTable::New();
+
+  vtkpxColorMapUtil::CopyLookupTable(lkp,this->maskLookupTable);
+
+  if (this->InternalEditor!=NULL && updateeditor==1)
+    this->InternalEditor->UpdateFromViewer(1);
+  
+  this->UpdateDisplay();
+  return 1;
+}
+
+void vtkpxGUIObjectmapMosaicViewer::ClearMaskImage()
+{
+  if (this->maskImage==NULL)
+    this->maskImage=vtkImageData::New();
+
+  vtkImageThreshold* thr=vtkImageThreshold::New();
+  thr->SetInput(currentImage);
+  thr->ThresholdByLower(1);
+  thr->ReplaceInOn();
+  thr->ReplaceOutOn();
+  thr->SetInValue(0.0);
+  thr->SetOutValue(0.0);
+  thr->SetOutputScalarTypeToUnsignedChar();
+  thr->Update();
+
+  this->maskImage->ShallowCopy(thr->GetOutput());
+  thr->Delete();
+
+
+}
+
+void vtkpxGUIObjectmapMosaicViewer::QuickUpdateObjectmap()
+{
+  for (int i=0;i<this->MaximumNumberOfViewers;i++)
+    {
+      if (this->maskImageSlice[i]!=NULL)
+	{
+	  this->maskImageSlice[i]->Update();
+	  this->maskImageSlice[i]->UpdateTexture();
+	  this->maskImageSlice[i]->Modified();
+	}
+    }
+}
+
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxGUIObjectmapMosaicViewer::HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev)
+{
+  int status=vtkpxGUIMosaicViewer::HandleMouseButtonEvent(nbutton,state,x,y,ev);
+  if (status==0)
+    return status;
+
+  if (this->InternalEditor==NULL)
+    return status;
+  
+  double lv[3];
+  this->GetLastClickedPoint(lv);
+  
+  int x1=int(lv[0]+0.5);
+  int y1=int(lv[1]+0.5);
+  int z1=int(lv[2]+0.5);
+
+  int plane=currentPlane->getIndex();
+  this->InternalEditor->SetPaint2DAxis(plane);
+
+  //  fprintf(stderr,"Sending to Int Editor %d,%d,%d from %f,%f,%f\n",x1,y1,z1,lv[0],lv[1],lv[2]);
+  this->InternalEditor->HandleClickedPoint(x1,y1,z1,nbutton,state);
+  return status;
+}
+
+std::string vtkpxGUIObjectmapMosaicViewer::GetObjectmapValueAsText(int a,int b,int c)
+{
+  std::string s="n";
+  if (this->maskImage!=NULL)
+    {
+      int dim[3]; this->maskImage->GetDimensions(dim);
+      if (a>=0 && a<dim[0] &&
+	  b>=0 && b<dim[1] &&
+	  c>=0 && c<dim[2])
+	{
+	  int vl=(int)this->maskImage->GetScalarComponentAsDouble(a,b,c,0);
+	  s=this->GetFormatedNumber(vl,3);
+	}
+    }
+  return s;
+}
+
+int vtkpxGUIObjectmapMosaicViewer::PaintingEnabled()
+{
+  if (this->InternalEditor==NULL)
+    return 0;
+  return (this->InternalEditor->GetPaintMode()>0);
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObjectmapMosaicViewer.h b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapMosaicViewer.h
new file mode 100644
index 0000000..01a0feb
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapMosaicViewer.h
@@ -0,0 +1,155 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIObjectmapMosaicViewer.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIObjectmapMosaicViewer 
+// .SECTION Description
+
+#ifndef __vtkpxGUIObjectmapMosaicViewer_h
+#define __vtkpxGUIObjectmapMosaicViewer_h
+
+
+#include "pxtkcomplexwidgets.h"
+#include "pxtkdialog.h"
+#include "pxvtkgadgets.h"
+
+#include "vtkpxGUIMosaicViewer.h"
+#include "vtkpxGUIRenderer.h"
+#include "vtkpxImageSlice.h"
+#include "vtkpxUtil.h"
+
+class vtkpxGUIObjectmapMosaicEditor;
+
+
+class  vtkpxGUIObjectmapMosaicViewer : public vtkpxGUIMosaicViewer
+{
+public:
+  static vtkpxGUIObjectmapMosaicViewer *New();
+  vtkTypeMacro(vtkpxGUIObjectmapMosaicViewer,vtkpxGUIMosaicViewer);
+  
+
+  virtual int  ResetViewer();
+  virtual int  UpdateViewers(int firstv,int lastv);
+  virtual int  HandleEvent(int eventno);
+
+  // Description:
+  // Set Objectmap Transparency 
+  virtual float GetObjectmapTransparency();
+  virtual void  SetObjectmapTransparency(float v);
+  virtual void  UpdateObjectmap();
+  virtual void  QuickUpdateObjectmap();
+
+  // Description:
+  // Set Objectmap  Image
+  virtual int SetObjectMapImage(vtkImageData* img);
+  virtual int SetObjectLookupTable(vtkLookupTable* lkp);
+  virtual int SetObjectLookupTable(vtkLookupTable* lkp,int updateeditor);
+  virtual vtkImageData* GetObjectMapImage() { return this->maskImage;}
+  virtual vtkLookupTable* GetObjectMapLookupTable() { return this->maskLookupTable;}
+
+
+  // Description:
+  // Clean Objectmap
+  virtual void ClearMaskImage();
+
+  // Description:
+  virtual void SetCreateInternalEditorOn();
+  vtkGetObjectMacro(InternalEditor,vtkpxGUIObjectmapMosaicEditor);
+
+  // Description::
+  virtual int  HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev);
+
+  // Description:
+  // Does this have an objectmap
+  virtual int HasObjectmap() { return 1;}
+  virtual int PaintingEnabled();
+
+protected:
+
+  vtkpxGUIObjectmapMosaicViewer();
+  virtual ~vtkpxGUIObjectmapMosaicViewer();
+
+  // Create Viewer
+  virtual void CreateViewerAndSlice(int index);
+
+  // Create Controls
+  virtual void InitControls(PXTkFrame* parent,int hm=1);
+
+  // Description:
+  // If we have no Editor
+  virtual int AutoCreateMaskAndLookupTable();
+
+
+  vtkImageData*              maskImage;
+  vtkLookupTable*            maskLookupTable;
+  vtkLookupTable*            maskVolumeLookupTable;
+  vtkpxImageSlice*           maskImageSlice[MVP_MAX_VIEWERS];
+  PXTkArrowScale             *maskTransparency;
+
+  // Description:
+  // Editor;
+  int                            create_internal_editor;
+  vtkpxGUIObjectmapMosaicEditor* InternalEditor;
+
+  // Description:
+  // Objectmap Value
+  //BTX
+  virtual std::string GetObjectmapValueAsText(int a=0,int b=0,int c=0);
+  //ETX
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObjectmapOrthogonalEditor.cpp b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapOrthogonalEditor.cpp
new file mode 100644
index 0000000..7425baa
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapOrthogonalEditor.cpp
@@ -0,0 +1,126 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIObjectmapOrthogonalEditor.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:14 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxGUIObjectmapOrthogonalEditor.h"
+#include "vtkpxGUIObjectmapOrthogonalViewer.h"
+#include "vtkObjectFactory.h"
+
+
+vtkpxGUIObjectmapOrthogonalEditor* vtkpxGUIObjectmapOrthogonalEditor::New()
+{
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIObjectmapOrthogonalEditor");
+  if(ret)
+      {
+	return (vtkpxGUIObjectmapOrthogonalEditor*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIObjectmapOrthogonalEditor;
+}
+
+// Construct object with no children.
+vtkpxGUIObjectmapOrthogonalEditor::vtkpxGUIObjectmapOrthogonalEditor()
+{
+  this->Viewer=NULL;
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapOrthogonalEditor::UpdateFromViewer(int mode)
+{
+
+  //  fprintf(stderr,"In Update From Viewer %d\n",mode);
+
+  if (this->Viewer==NULL)
+    return;
+  if (mode==0)
+    this->SetImagesAndLookupTable(this->Viewer->GetImage(),
+				  this->Viewer->GetObjectMapImage(),NULL,
+				  this->Viewer->GetCurrentImageIsColor());
+  else
+    this->SetImagesAndLookupTable(this->Viewer->GetImage(),
+				  this->Viewer->GetObjectMapImage(),
+				  this->Viewer->GetObjectLookupTable(),
+				  this->Viewer->GetCurrentImageIsColor());
+}
+
+void vtkpxGUIObjectmapOrthogonalEditor::UpdateViewerObjectmapColormap()
+{
+   if (this->Viewer==NULL)
+    return;
+ 
+   this->Viewer->SetObjectLookupTable(this->ObjectmapLookupTable,0);
+}
+ 
+void vtkpxGUIObjectmapOrthogonalEditor::UpdateViewerObjectmap()
+{
+   if (this->Viewer==NULL)
+    return;
+ 
+   this->Viewer->QuickUpdateObjectmap();
+}
+
+void vtkpxGUIObjectmapOrthogonalEditor::SetObjectmapViewer(vtkpxGUIObjectmapOrthogonalViewer* viewer)
+{
+  this->Viewer=viewer;
+}
+
+
+void vtkpxGUIObjectmapOrthogonalEditor::UpdateViewerDisplay()
+{
+  if (this->Viewer==NULL)
+    return;
+ 
+  this->Viewer->UpdateDisplay();
+
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObjectmapOrthogonalEditor.h b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapOrthogonalEditor.h
new file mode 100644
index 0000000..595452d
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapOrthogonalEditor.h
@@ -0,0 +1,100 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUI3DObjectmapEditor.h,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:33 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUI3DObjectmapEditor 
+// .SECTION Description
+
+#ifndef __vtkpxGUIObjectmapOrthogonalEditor_h
+#define __vtkpxGUIObjectmapOrthogonalEditor_h
+
+#include "vtkpxGUIAbstractMultisliceEditor.h"
+
+class vtkpxGUIObjectmapOrthogonalViewer;
+
+class  vtkpxGUIObjectmapOrthogonalEditor : public vtkpxGUIAbstractMultisliceEditor {
+  
+public:
+
+  static vtkpxGUIObjectmapOrthogonalEditor *New();
+  vtkTypeMacro(vtkpxGUIObjectmapOrthogonalEditor,vtkpxGUIAbstractMultisliceEditor);
+  
+  // Description:
+  // Get/Set Viewer
+  vtkGetObjectMacro(Viewer, vtkpxGUIObjectmapOrthogonalViewer);
+  virtual void SetObjectmapViewer(vtkpxGUIObjectmapOrthogonalViewer* viewer);
+  
+  // Previously Virtual
+  virtual void UpdateFromViewer(int docmap=0);
+
+protected:
+
+  vtkpxGUIObjectmapOrthogonalEditor();
+  
+
+  // Description: 
+  // Talking to the Viewer
+  virtual void UpdateViewerDisplay();
+  virtual void UpdateViewerObjectmapColormap();
+  virtual void UpdateViewerObjectmap();
+
+  // Description:
+  // A Pointer to the Viewer 
+  vtkpxGUIObjectmapOrthogonalViewer* Viewer;
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObjectmapOrthogonalViewer.cpp b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapOrthogonalViewer.cpp
new file mode 100644
index 0000000..15f6609
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapOrthogonalViewer.cpp
@@ -0,0 +1,829 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIObjectmapOrthogonalViewer.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/04/27 18:52:50 $
+  Version:   $Revision: 1.3 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "pxtkframe.h"
+#include "vtkActor.h"
+#include "vtkCellPicker.h"
+#include "vtkCubeSource.h"
+#include "vtkDataSetMapper.h"
+#include "vtkLineSource.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkOutlineFilter.h"
+#include "vtkPoints.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkProbeFilter.h"
+#include "vtkRenderer.h"
+#include "vtkRendererCollection.h"
+
+#include "vtkSphereSource.h"
+#include "vtkPolyData.h"
+#include "vtkpxColorMapUtil.h"
+#include "vtkpxGUIObjectmapOrthogonalViewer.h"
+#include "vtkpxGUIRenderer.h"
+#include "vtkpxGUIVolumeControl.h"
+#include "vtkpxGUIObliqueImageSliceControl.h"
+#include "vtkpxImageExtract.h"
+#include "vtkpxImageSlice.h"
+#include "vtkpxObliqueImageSlice.h"
+#include "vtkpxOrthoImageSlice.h"
+#include "vtkpxTalairachTransform.h"
+#include "vtkpxVolume.h"
+
+#include "vtkImageSeedConnectivity.h"
+#include "vtkImageDataGeometryFilter.h"
+#include "vtkThresholdPoints.h"
+#include "vtkImageThreshold.h"
+#include "vtkpxImageExtractVOI.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkImageThreshold.h"
+
+#include "vtkpxGUIObjectmapOrthogonalEditor.h"
+#include "vtkpxGUI2DSplineObjectmapViewer.h"
+#include "vtkpxGUI2DImageEditor.h"
+#include "vtkstd/string"
+
+/*#include "vtkImageMapToRGBA.h"
+  #include "vtkCollection.h"
+  #include "vtkImageQuantizeRGBToIndex.h"
+  #include "vtkImageBlend.h"*/
+
+// -------------------------------------------------------------------------
+vtkpxGUIObjectmapOrthogonalViewer* vtkpxGUIObjectmapOrthogonalViewer::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIObjectmapOrthogonalViewer");
+  if(ret)
+      {
+	return (vtkpxGUIObjectmapOrthogonalViewer*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIObjectmapOrthogonalViewer;
+}
+
+// Construct object with no children.
+vtkpxGUIObjectmapOrthogonalViewer::vtkpxGUIObjectmapOrthogonalViewer()
+{
+  for (int i=0;i<=2;i++)
+    maskImageSlice[i]=NULL;
+  maskOrthoSlice=NULL;
+  maskTransparency=NULL;
+  SplineObjectmapEditor=NULL;
+  maskImage=NULL;
+  maskLookupTable=NULL;
+  maskVolumeLookupTable=NULL;
+  //  this->ColorMode=0;
+
+  this->create_internal_editor=0;
+  this->InternalEditor=NULL;
+}
+
+vtkpxGUIObjectmapOrthogonalViewer::~vtkpxGUIObjectmapOrthogonalViewer()
+{
+  for (int i=0;i<=2;i++)
+    if (maskImageSlice[i]!=NULL)
+      maskImageSlice[i]->Delete();
+
+  if (maskOrthoSlice!=NULL)
+    maskOrthoSlice->Delete();
+
+  if (maskImage!=NULL)
+    this->maskImage->Delete();
+
+  if (maskLookupTable!=NULL)
+    this->maskLookupTable->Delete();
+
+  if (maskVolumeLookupTable!=NULL)
+    this->maskVolumeLookupTable->Delete();
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapOrthogonalViewer::SetCreateInternalEditorOn()
+{
+  if (this->SplineObjectmapEditor!=NULL)
+    return;
+
+  if (this->Initialized==0)
+    create_internal_editor=1;
+}
+/* -------------------------------------------------------------------------*/
+
+int vtkpxGUIObjectmapOrthogonalViewer::HandleEvent(int event)
+{
+  if (event>0 && event<10)
+      return this->EventManager->handleDirectEvent(event);
+
+  if (event<400)
+    return vtkpxGUIOrthogonalViewer::HandleEvent(event);
+
+  if (!hasImage)
+    return TCL_OK;
+
+
+  if (event==400)
+    {
+      if (  this->maskImageSlice[0]!=NULL)
+	{
+	  this->SetObjectmapTransparency(this->maskTransparency->getValue());
+	}
+    }
+
+  if (event==401)
+    {
+      if (this->InternalEditor!=NULL)
+	this->InternalEditor->Show();
+    }
+
+  return TCL_OK;
+     
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIObjectmapOrthogonalViewer::InitControls(int a)
+{
+  vtkpxGUIOrthogonalViewer::InitControls(a);
+  // Put extra item in extraFrame
+
+  maskTransparency=new PXTkArrowScale(this->EventManager,extraFrame,"Mask:",400,PXTrue);
+  maskTransparency->setRange(0.0,100.0);
+  maskTransparency->setResolution(1.0);
+  maskTransparency->setValue(50.0);
+  maskTransparency->setLengthWidth(80,15);
+
+
+  extraFrame->addChildren("-side left -expand true -fill x",maskTransparency->getMainWindow());
+
+  if (create_internal_editor==0)
+    return;
+
+  PXTkButton* ut5=new PXTkButton(this->EventManager,controlFrame,"Show Paint Controls",401); 
+  ut5->configure("-fg","red");
+  controlFrame->addChildren("-side bottom -expand true -fill x -padx 5",ut5);
+  
+  this->InternalEditor=vtkpxGUIObjectmapOrthogonalEditor::New();
+  this->InternalEditor->Initialize(this->GetWidgetName(),0);
+  //  this->InternalEditor->Initialize(this->GetWidgetName(),0);
+  this->InternalEditor->SetObjectmapViewer(this);
+
+}
+
+void vtkpxGUIObjectmapOrthogonalViewer::UpdateMaskVolumeLookupTableAndImage()
+{
+  if (this->Volume==NULL)
+    return;
+
+  double opacity=0.5;
+
+  //  fprintf(stderr,"opacity\n");
+  if (  this->maskImageSlice[0]!=NULL)
+    opacity=this->maskTransparency->getValue()*0.01;
+
+  //fprintf(stderr,"This far\n");
+
+  if (maskVolumeLookupTable==NULL)
+    fprintf(stderr,"It is null\n");
+
+
+  if (maskVolumeLookupTable->GetNumberOfColors()!=maskLookupTable->GetNumberOfColors())
+    {
+    //fprintf(stderr,"Setting num values\n");
+      maskVolumeLookupTable->SetNumberOfTableValues(maskLookupTable->GetNumberOfColors());
+    }
+
+  //fprintf(stderr,"Setting range\n");
+
+  maskVolumeLookupTable->SetTableRange(maskLookupTable->GetTableRange());
+
+  //fprintf(stderr,"vol\n");
+
+  for (int i=0;i<maskVolumeLookupTable->GetNumberOfColors();i++)
+    {
+      double v[4]; maskLookupTable->GetTableValue(i,v);
+      if (i>0)
+	v[3]=opacity;
+      else
+	v[3]=0.0;
+      maskVolumeLookupTable->SetTableValue(i,v);
+    }
+
+  //fprintf(stderr,"Fixed MaskVolume Table\n");
+
+  this->Volume->SetSecondLookupTable(this->maskVolumeLookupTable);
+
+  //fprintf(stderr,"Done Setting Lookup Table\n");
+  this->Volume->SetSecondInput(this->maskImage);
+
+  //fprintf(stderr,"Done Setting Inputs\n");
+}
+
+
+// -------------------------------------------------------------------------
+int vtkpxGUIObjectmapOrthogonalViewer::AutoCreateMaskAndLookupTable()
+{
+  if (this->maskImage==NULL)
+    {
+      this->maskImage=vtkImageData::New();
+    }
+  else
+    {
+      int ok=this->DoImagesHaveSameDimensions(this->maskImage,this->currentImage,0);
+      if (ok==1)
+	return 1;
+    }
+
+
+  vtkImageThreshold* thr=vtkImageThreshold::New();
+  thr->SetInput(currentImage);
+  thr->ThresholdByLower(1);
+  thr->ReplaceInOn();
+  thr->ReplaceOutOn();
+  thr->SetInValue(0.0);
+  thr->SetOutValue(0.0);
+  thr->SetOutputScalarTypeToUnsignedChar();
+  thr->Update();
+  
+  this->maskImage->ShallowCopy(thr->GetOutput());
+  thr->Delete();
+
+  /*  this->maskImage->CopyStructure(currentImage);
+  this->maskImage->SetScalarTypeToUnsignedChar();
+  this->maskImage->AllocateScalars();
+  this->maskImage->GetPointData()->GetScalars()->FillComponent(0,0.0);*/
+
+  if (this->maskLookupTable==NULL)
+    maskLookupTable=vtkLookupTable::New();
+
+  vtkpxSurfaceUtil::DefaultObjectMapLookupTable(maskLookupTable,28,1);
+
+  if (this->maskVolumeLookupTable==NULL)
+    maskVolumeLookupTable=vtkLookupTable::New();
+
+  this->UpdateMaskVolumeLookupTableAndImage();
+
+  if (this->InternalEditor!=NULL)
+    this->InternalEditor->ResetVOINames();
+
+
+  return 1;
+}
+
+int vtkpxGUIObjectmapOrthogonalViewer::SetObjectLookupTable(vtkLookupTable* lkp)
+{
+  return this->SetObjectLookupTable(lkp,1);
+}
+
+int vtkpxGUIObjectmapOrthogonalViewer::SetObjectLookupTable(vtkLookupTable* lkp,int updateeditor)
+{
+
+  if (lkp==NULL)
+    return 0;
+  if (this->maskLookupTable==NULL)
+    maskLookupTable=vtkLookupTable::New();
+
+  vtkpxColorMapUtil::CopyLookupTable(lkp,this->maskLookupTable);
+
+  this->UpdateMaskVolumeLookupTableAndImage();
+  this->UpdateDisplay();
+
+  if (this->InternalEditor!=NULL && updateeditor==1)
+    {
+      //fprintf(stderr,"Updating Editor Objectmap Colormap");
+      this->InternalEditor->UpdateFromViewer(1);
+    }
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (maskImageSlice[ia]!=NULL) 
+	{
+	  maskImageSlice[ia]->UpdateTexture();
+	  maskImageSlice[ia]->Modified();
+	}
+    }
+
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIObjectmapOrthogonalViewer::InitializeViewer()
+{
+  if ((!hasImage && this->Initialized))
+      return 0;
+
+  if (this->SplineObjectmapEditor!=NULL)
+    this->SplineObjectmapEditor->SetImage(this->currentImage);
+    
+
+  int ok=vtkpxGUIOrthogonalViewer::InitializeViewer();
+  if (ok==0)
+    return 0;
+
+  this->maskImage=vtkImageData::New();
+  if (this->SplineObjectmapEditor!=NULL)
+    {
+      maskImage->ShallowCopy(SplineObjectmapEditor->GetMaskImage());
+      if (this->maskLookupTable==NULL)
+	maskLookupTable=vtkLookupTable::New();
+      
+      vtkpxSurfaceUtil::DefaultObjectMapLookupTable(maskLookupTable,28,1);
+      
+      if (this->maskVolumeLookupTable==NULL)
+	maskVolumeLookupTable=vtkLookupTable::New();
+      
+      this->UpdateMaskVolumeLookupTableAndImage();
+    } 
+  else
+    this->AutoCreateMaskAndLookupTable();
+  
+  for (int k=0;k<=2;k++)
+    {
+      maskImageSlice[k]=vtkpxImageSlice::New();
+      maskImageSlice[k]->SetAutoUpdate(0);
+      maskImageSlice[k]->SetInput(maskImage);
+      maskImageSlice[k]->SetFrame(0);
+      maskImageSlice[k]->SetCurrentPlane(k);
+      maskImageSlice[k]->PickableOff();
+      maskImageSlice[k]->SetOpacity(0.5);
+      maskImageSlice[k]->SetInterpolation(0);
+
+      renderer[k]->GetRenderer()->AddActor(maskImageSlice[k]);
+    }
+
+  maskOrthoSlice=vtkpxOrthoImageSlice::New();
+  maskOrthoSlice->SetAutoUpdate(0);
+  maskOrthoSlice->SetInput(maskImage);
+  maskOrthoSlice->SetFrame(0);
+  maskOrthoSlice->PickableOff();
+  maskOrthoSlice->SetOpacity(0.5);
+  maskOrthoSlice->SetInterpolation(0);
+
+  renderer[3]->GetRenderer()->AddActor(maskOrthoSlice);
+  maskOrthoSlice->SetVisibility(this->OrthoSliceVisibility);
+
+
+  if (this->Volume!=NULL)
+    {
+      this->UpdateMaskVolumeLookupTableAndImage();
+    }
+
+  return 1;
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUIObjectmapOrthogonalViewer::ChangeSliceLevels(int lv[3],int infoonly)
+{
+  if (this->Initialized==0 || !hasImage || imageSlice[0]==NULL)
+    return;
+
+  double sp[3];    currentImage->GetSpacing(sp);
+  double ori[3];   currentImage->GetOrigin(ori);
+
+  if (infoonly==0)
+    {
+      for (int ia=0;ia<=2;ia++)
+	{
+	  imageSlice[ia]->SetLevel(lv[ia]);
+	  maskImageSlice[ia]->SetLevel(lv[ia]);
+	}
+      orthoSlice->SetLevels(lv[0],lv[1],lv[2]);
+      maskOrthoSlice->SetLevels(lv[0],lv[1],lv[2]);
+    }
+
+  double lvv[3],lvs[3];
+  for (int ic=0;ic<=2;ic++)
+    {
+      lvv[ic]=float(lv[ic]);
+      lvs[ic]=lvv[ic]*sp[ic]+ori[ic];
+    }
+  this->SetLastClickedPoint(lvv);
+  this->SetLastClickedPointScaled(lvs);
+
+  if (infoonly==0)
+    {
+      MoveAxis(1);
+    }
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIObjectmapOrthogonalViewer::ChangeFrame(int newframe)
+{
+  if (newframe==this->CurrentFrame)
+    return;
+   
+  this->CurrentFrame=Irange(newframe,0,this->NumberOfFrames-1);
+  for (int ia=0;ia<=2;ia++)
+    {
+      imageSlice[ia]->SetFrame(this->CurrentFrame);
+      maskImageSlice[ia]->SetFrame(this->CurrentFrame);
+    }
+  orthoSlice->SetFrame(this->CurrentFrame);
+  maskOrthoSlice->SetFrame(this->CurrentFrame);
+
+  obliqueSlice->SetFrame(this->CurrentFrame);
+
+  if (this->Volume!=NULL)
+    this->Volume->SetFrame(this->CurrentFrame);
+
+  this->UpdateIntensityLabelInfo();
+  this->ExecuteFrameChangeCallback();
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIObjectmapOrthogonalViewer::SetOrthoSliceVisibility(int orthovis)
+{
+  vtkpxGUIOrthogonalViewer::SetOrthoSliceVisibility(orthovis);
+  if (this->maskOrthoSlice!=NULL)
+    this->maskOrthoSlice->SetVisibility(orthoSlice->GetVisibility());
+}
+
+void vtkpxGUIObjectmapOrthogonalViewer::SetVolumeVisibility(int volvis)
+{
+  vtkpxGUIOrthogonalViewer::SetVolumeVisibility(volvis);
+}
+
+void vtkpxGUIObjectmapOrthogonalViewer::SetObliqueSliceVisibility(int orthovis)
+{
+  vtkpxGUIOrthogonalViewer::SetObliqueSliceVisibility(orthovis);
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUIObjectmapOrthogonalViewer::ResetViewerUpdatePolar()
+{
+  vtkpxGUIOrthogonalViewer::ResetViewerUpdatePolar();
+  for (int sc=0;sc<=2;sc++)
+    {
+      maskImageSlice[sc]->SetLevel(imageSlice[sc]->GetLevel());
+      maskImageSlice[sc]->Update();
+      maskImageSlice[sc]->SetAutoUpdate(1);
+    }
+
+  int levels[3];
+  orthoSlice->GetLevels(levels);
+  maskOrthoSlice->SetAutoUpdate(0);
+  maskOrthoSlice->SetLevels(levels[0],levels[1],levels[2]);
+  maskOrthoSlice->Update();
+  maskOrthoSlice->SetAutoUpdate(1);
+
+  return 1;
+}
+// ------------------------------------------------------------------------- 
+int vtkpxGUIObjectmapOrthogonalViewer::ResetViewerUpdateCartesian() 
+{
+  vtkpxGUIOrthogonalViewer::ResetViewerUpdateCartesian();
+  int   range[3]; 
+  currentImage->GetDimensions(range);
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      maskImageSlice[ia]->SetAutoUpdate(0);
+      maskImageSlice[ia]->SetCurrentPlane(ia);
+    }
+  
+  maskOrthoSlice->SetAutoUpdate(0);
+  maskOrthoSlice->SetLevels(range[0]/2,range[1]/2,range[2]/2);
+  maskOrthoSlice->Update();
+  maskOrthoSlice->SetAutoUpdate(1);
+
+  for (int kk=0;kk<=2;kk++)
+    {
+      maskImageSlice[kk]->SetLevel(range[kk]/2);
+      maskImageSlice[kk]->Update();
+      maskImageSlice[kk]->SetAutoUpdate(1);
+    }
+  
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIObjectmapOrthogonalViewer::ResetViewer()
+{
+  //  fprintf(stderr,"In Reset Viewer %d oldorient=%d firsttimereset=%d\n",this,oldorientation,firsttimereset);
+
+  if (!(hasImage && this->Initialized))
+      return 0;
+
+  if (this->SplineObjectmapEditor==NULL)
+    this->AutoCreateMaskAndLookupTable();
+  else
+    this->SplineObjectmapEditor->SetImage(this->currentImage);
+
+  if (this->InternalEditor!=NULL)
+    this->InternalEditor->UpdateFromViewer();
+
+
+  vtkpxGUIOrthogonalViewer::ResetViewer();
+
+  if (!hasImage)
+    {
+      oldorientation=-1;
+      firsttimereset=-1;
+    }
+
+  if (this->SplineObjectmapEditor!=NULL)
+    maskImage->ShallowCopy(SplineObjectmapEditor->GetMaskImage());
+      
+
+  for (int i=0;i<=2;i++)
+    {
+      maskImageSlice[i]->SetInput(maskImage);
+      maskImageSlice[i]->SetFrame(this->CurrentFrame);
+      if (this->SplineObjectmapEditor!=NULL)
+	maskImageSlice[i]->SetLookupTable(this->SplineObjectmapEditor->GetMaskLookupTable());
+      else
+	maskImageSlice[i]->SetLookupTable(this->maskLookupTable);
+
+      if (this->Orientation==3)
+	maskImageSlice[i]->SetPolarMode(1);
+      else
+	maskImageSlice[i]->SetPolarMode(0);
+
+      maskImageSlice[i]->Update();
+    }
+
+  maskOrthoSlice->SetInput(maskImage);
+  maskOrthoSlice->SetFrame(this->CurrentFrame);
+
+
+  if (this->SplineObjectmapEditor!=NULL)
+    maskOrthoSlice->SetLookupTable(this->SplineObjectmapEditor->GetMaskLookupTable());
+  else
+    maskOrthoSlice->SetLookupTable(this->maskLookupTable);
+
+
+  if (this->Volume!=NULL)
+    {
+      this->UpdateMaskVolumeLookupTableAndImage();
+    }
+
+
+  if (this->Orientation==3)
+    {
+      maskOrthoSlice->SetPolarMode(1);
+      }
+  else
+    {
+      maskOrthoSlice->SetPolarMode(0);
+    }
+
+
+  this->UpdateDisplay();
+  return 1;
+}
+
+void vtkpxGUIObjectmapOrthogonalViewer::SetSplineObjectmapEditor(vtkpxGUI2DSplineObjectmapViewer* editor)
+{
+  if ((!hasImage && this->Initialized) || editor==NULL)
+    return;
+
+  if (this->create_internal_editor==1)
+    return;
+  this->SplineObjectmapEditor=editor;
+
+}
+vtkpxGUI2DSplineObjectmapViewer* vtkpxGUIObjectmapOrthogonalViewer::GetSplineObjectmapEditor()
+{
+  return SplineObjectmapEditor;
+}
+
+
+ 
+
+float vtkpxGUIObjectmapOrthogonalViewer::GetObjectmapTransparency()
+{
+  if (  this->maskImageSlice[0]==NULL)
+    return 0.0;
+
+  return 100.0*this->maskImageSlice[0]->GetOpacity();
+}
+
+void vtkpxGUIObjectmapOrthogonalViewer::SetObjectmapTransparency(float v)
+{
+  if (  this->maskImageSlice[0]!=NULL)
+    {
+       v*=0.01;
+       for (int ia=0;ia<=2;ia++)
+	 maskImageSlice[ia]->SetOpacity(v);
+       maskOrthoSlice->SetOpacity(v);
+       this->UpdateMaskVolumeLookupTableAndImage();
+       this->UpdateDisplay();
+       this->maskTransparency->setValue(v*100.0,PXFalse);
+    }
+
+}
+
+void vtkpxGUIObjectmapOrthogonalViewer::UpdateObjectmap()
+{
+  if (this->maskImageSlice[0]==NULL)
+    return;
+  
+  if (this->SplineObjectmapEditor!=NULL)
+    maskImage->ShallowCopy(SplineObjectmapEditor->GetMaskImage());
+
+  //  fprintf(stderr,"In Updating Objectmap\n");
+
+  for (int ia=0;ia<=2;ia++)
+      maskImageSlice[ia]->SetInput(maskImage);
+      
+  maskOrthoSlice->SetInput(maskImage);
+
+  if (this->InternalEditor!=NULL)
+    this->InternalEditor->UpdateFromViewer();
+
+  this->QuickUpdateObjectmap();
+  this->UpdateIntensityLabelInfo();
+  this->UpdateDisplay();
+}
+
+
+void vtkpxGUIObjectmapOrthogonalViewer::QuickUpdateObjectmap()
+{
+ if (this->maskImageSlice[0]==NULL)
+    return;
+  
+   for (int ia=0;ia<=2;ia++)
+    {
+      maskImageSlice[ia]->Update();
+      maskImageSlice[ia]->UpdateTexture();
+    }
+      
+  maskOrthoSlice->Update();
+  maskOrthoSlice->UpdateTexture();
+ 
+}
+
+
+int vtkpxGUIObjectmapOrthogonalViewer::SetObjectMapImage(vtkImageData* img)
+{
+  //  fprintf(stderr,"In Set Objectmap Image\n");
+
+  if ((!hasImage && this->Initialized))
+    return 0;
+  
+
+
+  if (this->SplineObjectmapEditor!=NULL)
+    {
+      this->SplineObjectmapEditor->SetMaskImage(img,this->Orientation);
+      return 0;
+    }
+
+  //  fprintf(stderr,"Setting Objectmap\n");
+
+  int ndim[3]; img->GetDimensions(ndim);
+  int odim[3]; this->currentImage->GetDimensions(odim);
+  int nc=img->GetNumberOfScalarComponents();
+  int onc=this->currentImage->GetNumberOfScalarComponents();
+  int sum=0;
+  for (int i=0;i<=2;i++)
+    sum+=abs(ndim[i]-odim[i]);
+
+  if (sum!=0 || nc>onc)
+    {
+      vtkErrorMacro(<<"Bad Mask Image Dimensions\n");
+      return 0;
+    }
+  
+  //  fprintf(stderr,"Updating Objectmap part II");
+
+  this->maskImage->ShallowCopy(img);
+  double r[2]; img->GetPointData()->GetScalars()->GetRange(r);
+
+  vtkpxSurfaceUtil::DefaultObjectMapLookupTable(maskLookupTable,int(r[1]+2),1);
+  UpdateObjectmap();
+  return 1;
+}
+
+
+
+int vtkpxGUIObjectmapOrthogonalViewer::HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev)
+{
+  int status=vtkpxGUIOrthogonalViewer::HandleMouseButtonEvent(nbutton,state,x,y,ev);
+  if (status==0)
+    return status;
+
+  if (nbutton!=1 && nbutton!=4 && nbutton!=7)
+    return status;
+
+
+  if (this->InternalEditor==NULL)
+    return status;
+
+  double lv[3];
+  this->GetLastClickedPoint(lv);
+  int x1=int(lv[0]);
+  int y1=int(lv[1]);
+  int z1=int(lv[2]);
+  this->InternalEditor->SetPaint2DAxis(this->LastClickedSlice);
+  this->InternalEditor->HandleClickedPoint(x1,y1,z1,nbutton,state);
+  return status;
+}
+
+std::string vtkpxGUIObjectmapOrthogonalViewer::GetObjectmapValueAsText(int a,int b,int c)
+{
+  std::string s=" ";
+  if (this->maskImage!=NULL)
+    {
+      int dim[3]; this->maskImage->GetDimensions(dim);
+      if (a>=0 && a<dim[0] &&
+	  b>=0 && b<dim[1] &&
+	  c>=0 && c<dim[2])
+	{
+	  double vl=this->maskImage->GetScalarComponentAsDouble(a,b,c,0);
+	  s=this->GetFormatedNumber(vl,3);
+	}
+    }
+  return s;
+}
+
+int vtkpxGUIObjectmapOrthogonalViewer::PaintingEnabled()
+{
+  if (this->InternalEditor==NULL)
+    return 0;
+  return (this->InternalEditor->GetPaintMode()>0);
+}
+
+
+void vtkpxGUIObjectmapOrthogonalViewer::SetPresetLookupTable(int mode)
+{
+  //  fprintf(stderr,"In Setting preset lookup table\n");
+
+  if (!hasImage)
+    return;
+
+  vtkpxGUIOrthogonalViewer::SetPresetLookupTable(mode);
+
+  if (mode<1 || mode>6)
+    return;
+
+  if (this->InternalEditor==NULL)
+    return;
+
+  int minv=56,maxv=63;
+
+  if (mode==2 || mode==3)
+    {
+      minv=192;
+      maxv=255;
+    }
+  else if ( mode==5 || mode == 6)
+    {
+      minv=238;
+      maxv=255;
+    }
+  
+  //  fprintf(stderr,"Setting Thresholds %f:%f\n",double(minv),double(maxv));
+
+  double r[2]; this->maskImage->GetPointData()->GetScalars()->GetRange(r);
+  vtkpxSurfaceUtil::VOIObjectMapLookupTable(maskLookupTable,-1);
+  UpdateObjectmap();
+  this->InternalEditor->CreateDefaultLookupTable(1);
+  maskTransparency->setValue(100.0,PXTrue);
+  this->InternalEditor->SetVOISelectMode(double(minv),double(maxv),0);
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObjectmapOrthogonalViewer.h b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapOrthogonalViewer.h
new file mode 100644
index 0000000..adb3577
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapOrthogonalViewer.h
@@ -0,0 +1,182 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIObjectmapOrthogonalViewer.h,v $
+  Language:  C++
+  Date:      $Date: 2004/04/27 18:53:07 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+// .NAME vtkpxGUIObjectmapOrthogonalViewer 
+// .SECTION Description
+
+#ifndef __vtkpxGUIObjectmapOrthogonalViewer_h
+#define __vtkpxGUIObjectmapOrthogonalViewer_h
+
+#include "vtkpxGUIOrthogonalViewer.h"
+#include "vtkLookupTable.h"
+//#include "vtkCollection.h"
+
+class vtkpxGUIObjectmapOrthogonalEditor;
+class vtkpxGUI2DSplineObjectmapViewer;
+
+class  vtkpxGUIObjectmapOrthogonalViewer : public vtkpxGUIOrthogonalViewer 
+{
+public:
+  
+  static vtkpxGUIObjectmapOrthogonalViewer *New();
+  vtkTypeMacro(vtkpxGUIObjectmapOrthogonalViewer,vtkpxGUIOrthogonalViewer);
+
+  // Jury is out but chance are some of these only
+  virtual int   InitializeViewer();
+  virtual int   ResetViewer();
+  virtual int   HandleEvent(int eventno);
+  virtual void  ChangeFrame(int t);
+  virtual void  SetOrthoSliceVisibility(int orthovis);
+  virtual void SetVolumeVisibility(int volvis);
+  virtual void SetObliqueSliceVisibility(int volvis);
+
+
+  // Description:
+  // Objectmap Editor
+  virtual void SetSplineObjectmapEditor(vtkpxGUI2DSplineObjectmapViewer* editor);
+  virtual vtkpxGUI2DSplineObjectmapViewer* GetSplineObjectmapEditor();
+
+  // Description:
+  // Set Objectmap Transparency 
+  virtual float GetObjectmapTransparency();
+  virtual void  SetObjectmapTransparency(float v);
+  virtual void  UpdateObjectmap();
+  virtual void  QuickUpdateObjectmap();
+
+
+  // Description:
+  // Set Objectmap  Image
+  virtual int SetObjectMapImage(vtkImageData* img);
+  virtual int SetObjectLookupTable(vtkLookupTable* lkp);
+  virtual int SetObjectLookupTable(vtkLookupTable* lkp,int updateeditor);
+  virtual vtkImageData* GetObjectMapImage() { return this->maskImage;}
+  virtual vtkLookupTable* GetObjectLookupTable() { return this->maskLookupTable;}
+
+  // Description:
+  // Get Combined Image and Lookup Table of Current View
+  //  vtkCollection* GetCombinedImageAndLookupTable();
+
+
+  // Description:
+  virtual void SetCreateInternalEditorOn();
+  vtkGetObjectMacro(InternalEditor,vtkpxGUIObjectmapOrthogonalEditor);
+
+  // Description::
+  virtual int  HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev);
+
+
+  // Description:
+  // Does this have an objectmap
+  virtual int HasObjectmap() { return 1;}
+  virtual int PaintingEnabled();
+
+  // Description:
+  // This is useful for VOI painting
+  virtual void  SetPresetLookupTable(int mode);
+
+protected:
+
+  vtkpxGUIObjectmapOrthogonalViewer();
+  virtual ~vtkpxGUIObjectmapOrthogonalViewer();
+
+  vtkImageData*              maskImage;
+  vtkLookupTable*            maskLookupTable;
+  vtkLookupTable*            maskVolumeLookupTable;
+
+  vtkpxImageSlice*           maskImageSlice[3];
+  vtkpxOrthoImageSlice       *maskOrthoSlice;
+  PXTkArrowScale             *maskTransparency;
+  vtkpxGUI2DSplineObjectmapViewer    *SplineObjectmapEditor;
+
+  // Description:
+  // Initialization Stuff 
+  virtual void InitControls(int hm=1);
+
+  // Description:
+  // Change Coordinates Frame Stuff 
+  virtual void ChangeSliceLevels(int lv[3],int infoonly=0);
+
+
+  // Description:
+  // Polar and Cartesian Stuff
+  virtual int ResetViewerUpdatePolar();
+  virtual int ResetViewerUpdateCartesian();
+  
+  // Description:
+  // If we have no Editor
+  virtual int AutoCreateMaskAndLookupTable();
+
+  // Description:
+  // Fix Volume Lookup Table
+  virtual void UpdateMaskVolumeLookupTableAndImage();
+
+
+  // Description:
+  // Editor;
+  int                                create_internal_editor;
+  vtkpxGUIObjectmapOrthogonalEditor* InternalEditor;
+
+  // Get Objectmap Value
+  //BTX
+  virtual std::string GetObjectmapValueAsText(int a=0,int b=0,int c=0);
+  //ETX
+
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObjectmapSplineControl.cpp b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapSplineControl.cpp
new file mode 100644
index 0000000..8a28f72
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapSplineControl.cpp
@@ -0,0 +1,1116 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// 	$Id: vtkpxGUIObjectmapSplineControl.cpp,v 1.2 2003/09/11 13:34:39 xenios Exp xenios $	
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkpxGUIObjectmapSplineControl.h"
+#include "vtkpxUtil.h"
+#include "vtkActor.h"
+#include "vtkAssembly.h"
+#include "vtkRenderer.h"
+#include "vtkRenderWindow.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxImageExtract.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkImageData.h"
+#include "vtkProperty.h"
+#include "vtkPoints.h"
+#include "pxfpbsplinestack.h"
+/* -------------------------------------------------------------------------*/
+vtkpxGUIObjectmapSplineControl* vtkpxGUIObjectmapSplineControl::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIObjectmapSplineControl");
+  if(ret)
+      {
+	return (vtkpxGUIObjectmapSplineControl*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIObjectmapSplineControl;
+}
+
+// ----------------------------------------------------------------------------
+vtkpxGUIObjectmapSplineControl::vtkpxGUIObjectmapSplineControl()
+{
+  this->NumberOfSplines=50;
+  this->ObjectmapEditor=NULL;
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->origin[ia]=0.0;
+      this->spacing[ia]=1.0;
+      this->dimensions[ia]=100;
+    }
+  
+  for (int i=0;i<this->NumberOfSplines;i++)
+    {
+      splineSet[i]=NULL;
+      splineActor[i]=NULL;
+      if (i==0)
+	display_mode[i]=PXTrue;
+      else
+	display_mode[i]=PXFalse;
+      scale_mode[i]=4;
+      spline_enabled[i]=1;
+      this->changed[i]=0;
+    }
+
+  editCurve=NULL;
+  manualEditCurve=NULL;
+
+  editActor=NULL;
+  manualEditActor=NULL;
+  this->Renderer=NULL;
+  current_spline=0;
+  currentSpline=NULL;
+  snakeGUI=NULL;
+  image=NULL;
+  image_level=0;
+  image_frame=0;
+  slice_offset=-0.02;
+
+  autoUpdate=NULL;
+  AutoUpdateMode=1;
+  
+  this->SlaveMode=0;
+  this->DistanceThreshold=1.0;
+  this->ControlPointScaleFactor=1.0;
+  this->manual_add_mode=0;
+  this->manual_zcoord=0.0;
+  this->DefaultSmoothing=1.0;
+
+  char* line=PXTkApp::getTclVariable("pxtcl_pref_array(SplineSmoothing)");
+  if (line!=NULL)
+      this->DefaultSmoothing=Frange(atof(line),0.0001,10.0);
+
+}
+// ----------------------------------------------------------------------------
+
+vtkpxGUIObjectmapSplineControl::~vtkpxGUIObjectmapSplineControl()
+{
+  
+  if (editCurve!=NULL)
+    editCurve->Delete();
+  if (editActor!=NULL)
+    editActor->Delete();
+
+  if (manualEditCurve!=NULL)
+    manualEditCurve->Delete();
+  if (manualEditActor!=NULL)
+    manualEditActor->Delete();
+
+
+  for (int i=0;i<this->NumberOfSplines;i++)
+    {
+      if (splineSet[i]!=NULL)
+	splineSet[i]->Delete();
+      if (splineActor[i]!=NULL)
+	splineActor[i]->Delete();
+    }
+    
+  if (this->image!=NULL)
+    this->image->Delete();
+
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxGUIObjectmapSplineControl::SetObjectmapEditor(vtkpxGUIObjectmapEditor* ed)
+{
+  if (this->Initialized==0 && ed!=NULL)
+    this->ObjectmapEditor=ed;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::SetNumberOfSplines(int a)
+{
+  if (this->Initialized==1)
+    {
+      return;
+    }
+  
+  this->NumberOfSplines=Irange(a,1,SP_MAX_COLLECTIONS);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::InitializeSplines()
+{
+  for (int i=0;i<this->NumberOfSplines;i++)
+    {
+      splineSet[i]=vtkpxSplineSource::New();
+      splineSet[i]->SetResolution(0.01);
+      splineSet[i]->SetEllipse(8,
+			       spacing[0]*dimensions[0]/8.0*(1.0+i),
+			       spacing[1]*dimensions[1]/8.0*(1.0+i),
+			       origin[0]+spacing[0]*dimensions[0]/2.0,
+			       origin[1]+spacing[1]*dimensions[1]/2.0,
+			       0.0,2);
+    }
+  editCurve=vtkpxBaseCurve::New();
+  editCurve->SetShowCurve(0);
+  editCurve->SetShowControls(1);
+  editCurve->SetControlsDisplayModeToDisc();
+  editCurve->SetPointScale(1.0);
+  editCurve->SetOrigin(this->origin);
+  editCurve->SetSpacing(this->spacing);
+  
+
+  manualEditCurve=vtkpxBaseCurve::New();
+  manualEditCurve->SetShowControls(1);
+  manualEditCurve->SetShowCurve(1);
+  manualEditCurve->SetControlsDisplayModeToDisc();
+  manualEditCurve->SetPointScale(1.0);
+  manualEditCurve->SetOrigin(this->origin);
+  manualEditCurve->SetSpacing(this->spacing);
+  
+
+  splineSet[0]->ExportToBaseCurve(editCurve);
+  splineSet[0]->ExportToBaseCurve(manualEditCurve);
+  current_spline=0;
+  currentSpline=splineSet[current_spline];
+
+
+
+}
+/* -------------------------------------------------------------------------*/
+char* vtkpxGUIObjectmapSplineControl::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+
+  InitializeSplines();
+
+  vtkpxGUIComponent::Initialize(name,inside);
+  PXTkFrame* mFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+  PXTkLabelFrame* landmarkFrame=new PXTkLabelFrame(this->EventManager,mFrame,"Spline Control");
+  mFrame->addChildren("-side top -expand t -fill both -padx 4 -pady 4 ",landmarkFrame);
+
+  // Control Properties
+  // ---------------------
+  mouseMode=new PXTkCheckButton(this->EventManager,landmarkFrame,"Edit Mode",-1);
+  mouseMode->setState(PXTrue);
+  editMode=new PXTkCheckButton(this->EventManager,landmarkFrame,"Manual Mode",510);
+  editMode->setState(PXFalse);
+  showControls=new PXTkCheckButton(this->EventManager,landmarkFrame,"Controls",502);
+  showControls->setState(PXTrue);
+  PXTkButton* b0=new PXTkButton(this->EventManager,landmarkFrame,"(Sag -)",504);
+  b0->configure("-padx",2);
+  landmarkFrame->addChildren("-side top -expand false -fill x",mouseMode,editMode,showControls,b0);
+
+  message=new PXTkLabel(this->EventManager,landmarkFrame,"Num");
+  message->configure("-relief","ridge");
+  displayMode=new PXTkCheckButton(this->EventManager,landmarkFrame,"Display",501);
+  displayMode->setState(display_mode[current_spline]);
+
+  PXTkFrame* fr1=new PXTkFrame(this->EventManager,landmarkFrame);
+  landmarkFrame->addChildren("-side top -expand false -fill x",message,displayMode,fr1);
+
+  PXTkLabel* lab0=new PXTkLabel(this->EventManager,fr1,"Size:");
+  scaleMode=new PXTkOptionMenu(this->EventManager,fr1,"0.25",503);
+  for (float s=0.50;s<=4.5;s+=0.25)
+      {
+	sprintf(pxtk_buffer,"%3.2f",s);
+	scaleMode->addOption(pxtk_buffer);
+      }
+  scaleMode->setIndex(scale_mode[current_spline]);
+  fr1->addChildren("-side left -expand true -fill x",lab0,scaleMode);
+
+  // Collection Operations 
+  // ---------------------
+  PXTkFrame* oFrame=new PXTkFrame(this->EventManager,landmarkFrame);
+  landmarkFrame->addChildren("-side top -expand false -fill x -padx 1 -pady 1",oFrame);
+
+  PXTkFrame* topfr=new PXTkFrame(this->EventManager,oFrame);
+  PXTkFrame* midfr=new PXTkFrame(this->EventManager,oFrame);
+
+  PXTkFrame* midfr2=new PXTkFrame(this->EventManager,oFrame);
+  PXTkFrame* midfr3=new PXTkFrame(this->EventManager,oFrame);
+  PXTkFrame* botfr=new PXTkFrame(this->EventManager,oFrame);  
+  PXTkFrame* botfr2=new PXTkFrame(this->EventManager,oFrame);  
+  oFrame->addChildren("-side top -pady 1 -expand f -fill x",topfr,midfr,midfr3,midfr2);
+  oFrame->addChildren("-side top -pady 1 -expand f -fill x",botfr,botfr2);
+ 
+
+  PXTkButton* but3=new PXTkButton(this->EventManager,topfr,"x0.8",600);
+  PXTkButton* but4=new PXTkButton(this->EventManager,topfr,"x1.0",601);
+  PXTkButton* but4a=new PXTkButton(this->EventManager,topfr,"x1.25",602);
+  topfr->addChildren("-side left ",but3,but4,but4a);
+  
+  SmoothingEntry=new PXTkEntry(this->EventManager,midfr);
+  SmoothingEntry->configure("-width",6);
+  SmoothingEntry->configure("-bg","red");
+  char line[10]; sprintf(line,"%f",this->DefaultSmoothing); SmoothingEntry->setText(line);
+  PXTkButton* but4c=new PXTkButton(this->EventManager,midfr,"sm",604);
+  midfr->addChildren("-side left -expand true -fill x ",SmoothingEntry,but4c);
+  
+  
+  PXTkButton* but6=new PXTkButton(this->EventManager,midfr2,"Color",450);
+  PXTkButton* but7=new PXTkButton(this->EventManager,midfr2,"C-Color",451);
+  but6->configure("-padx",0);   but7->configure("-padx",0);
+  midfr2->addChildren("-side left -padx 0 -expand t -fill x",but6,but7);
+
+  PXTkButton* but5=new PXTkButton(this->EventManager,midfr3,"Ellipse",452);
+  PXTkButton* bbut5=new PXTkButton(this->EventManager,midfr3,"Area",453);
+  but5->configure("-padx",0);  bbut5->configure("-padx",0);
+  midfr3->addChildren("-side left -padx 0 -expand t -fill x",but5,bbut5);
+
+  PXTkButton* but9=new PXTkButton(this->EventManager,botfr,"Snake",610);
+  PXTkButton* but10=new PXTkButton(this->EventManager,botfr,"Upd Snake",612);
+  but9->configure("-padx",0);
+  but10->configure("-padx",0);
+  botfr->addChildren("-side left -padx 0 -expand t -fill x",but9,but10);
+
+  bottomButtonFrame=new PXTkFrame(this->EventManager,landmarkFrame);  
+  landmarkFrame->addChildren("-side bottom -expand false -fill x -padx 00",bottomButtonFrame);
+
+
+  if ( (this->EventParent!=NULL && this->CallbackNo>0) || ( this->CallbackName!=NULL ))
+    {
+      autoUpdate=new PXTkCheckButton(this->EventManager,bottomButtonFrame,"Auto Upd",615);
+      if (this->AutoUpdateMode)
+	autoUpdate->setState(PXTrue);
+      PXTkButton* updB=new PXTkButton(this->EventManager,bottomButtonFrame,"Update",614);
+      bottomButtonFrame->addChildren("-side left -padx 10 -expand t -fill x",updB,autoUpdate);
+    }
+  
+  if (inside==0)
+    {
+      PXTkButton* closeB;
+      if (this->EventParent)
+	closeB=new PXTkButton(this->EventManager,bottomButtonFrame,"Close",3);
+      else
+	closeB=new PXTkButton(this->EventManager,bottomButtonFrame,"Exit",1);
+      bottomButtonFrame->addChildren("-side right -expand false -fill x -padx 10",closeB);
+    }
+
+  // Other Stuff 
+  UpdateStatus();
+  return GetWidgetName();
+}
+
+/* -------------------------------------------------------------------------*/ 
+void vtkpxGUIObjectmapSplineControl::SetRenderer(vtkRenderer *ren,int num)
+{
+  this->SetRenderer(ren);
+}
+
+void vtkpxGUIObjectmapSplineControl::SetRenderer(vtkRenderer* ren)
+{
+  for (int i=0;i<this->NumberOfSplines;i++)
+    {
+      double c[3]; vtkpxSurfaceUtil::GetColor(i,c);
+      if (splineActor[i]==NULL)
+	{
+	  vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+	  map->SetInput(splineSet[i]->GetOutput());
+	  
+	  splineActor[i]=vtkActor::New();
+	  splineActor[i]->SetMapper(map);
+	  
+	  if (display_mode[i])
+	    splineActor[i]->SetVisibility(1);
+	  else
+	    splineActor[i]->SetVisibility(0);
+	  splineActor[i]->GetProperty()->SetColor(c);
+	  map->Delete();
+	}
+      ren->AddActor(splineActor[i]);      
+    }
+  
+  if (editActor==NULL)
+    {
+      vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+      map->SetInput(editCurve->GetOutput());
+
+      editActor=vtkActor::New();
+      editActor->SetMapper(map);
+      map->Delete();
+    }
+
+  if (manualEditActor==NULL)
+    {
+      vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+      map->SetInput(manualEditCurve->GetOutput());
+
+      manualEditActor=vtkActor::New();
+      manualEditActor->SetMapper(map);
+      manualEditActor->SetVisibility(0);
+      map->Delete();
+    }
+
+  ren->AddActor(editActor);
+  ren->AddActor(manualEditActor);
+  this->Renderer=ren;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::Update()
+{
+  if (this->splineActor[0]==NULL)
+      return;
+
+  for (int i=0;i<this->NumberOfSplines;i++)
+      {
+	if (display_mode[i] && spline_enabled[i]==1)
+	  splineActor[i]->SetVisibility(1);
+	else
+	  splineActor[i]->SetVisibility(0);
+
+	double c[3];
+	for (int ib=0;ib<=2;ib++)
+	  c[ib]=0.1;
+	double w=splineActor[i]->GetProperty()->GetLineWidth();
+	w*=0.5;
+      }
+
+  editActor->SetVisibility(splineActor[current_spline]->GetVisibility());
+
+  // Curve Stuff 
+  UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::UpdateDisplay()
+{
+  if (this->Renderer!=NULL)
+    this->Renderer->GetRenderWindow()->Render();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::UpdateStatus()
+{
+  if (!this->Initialized)
+      return;
+
+  if (spline_enabled[current_spline]==1)
+    sprintf(pxtk_buffer4,"Points=%d",
+	    currentSpline->GetNumPoints());
+  else
+    sprintf(pxtk_buffer4,"Disabled!");
+  message->setText(pxtk_buffer4);
+}
+/* -------------------------------------------------------------------------*/
+int  vtkpxGUIObjectmapSplineControl::HandleEvent(int event)
+{
+  if (!this->Initialized)
+    return TCL_OK;
+  
+  if (event<10)
+    return this->EventManager->handleDirectEvent(event);
+
+  if (event==500)
+    {
+      //      SetCurrentCollection(0);//currentCollection->getIndex());
+      if (mouseMode->getState())
+	{
+	  if (currentSpline->GetNumPoints()==0)
+	    mouseMode->setState(PXFalse);
+	}
+    }
+  else if (event==614)
+    {
+      if (this->EventParent!=NULL && this->CallbackNo>0)
+	this->EventParent->HandleEvent(CallbackNo);
+      else
+	if (this->CallbackName!=NULL)
+	  PXTkApp::executeTclCommand(this->CallbackName);
+    }
+  else if (event==615)
+    {
+      if (autoUpdate->getState())
+	this->AutoUpdateMode=1;
+      else
+	this->AutoUpdateMode=0;
+    }
+  else if (spline_enabled[current_spline]==1)
+    {
+      switch(event)
+	{
+	case 450:
+	  if (splineActor[current_spline]!=NULL)
+	    {
+	      double c[3];
+	      splineActor[current_spline]->GetProperty()->GetColor(c);
+	      int a=this->EventManager->d_colorBox("Spline Color",c[0],c[1],c[2]);
+	      if (a==1)
+		splineActor[current_spline]->GetProperty()->SetColor(c);
+	    }
+	  break;
+	  
+	case 451:
+	  if (editActor!=NULL)
+	    {
+	      double c[3];
+	      editActor->GetProperty()->GetColor(c);
+	      int a=this->EventManager->d_colorBox("Controls Color",c[0],c[1],c[2]);
+	      if (a==1)
+		editActor->GetProperty()->SetColor(c);
+	    }
+	  break;
+	  
+	case 452: // Ellipse
+	  currentSpline->SetEllipse(8,
+				    spacing[0]*float(dimensions[0])/8.0*(1.0+current_spline),
+				    spacing[1]*float(dimensions[0])/8.0*(1.0+current_spline),
+				    origin[0]+spacing[0]*dimensions[0]/2.0,
+				    origin[1]+spacing[1]*dimensions[1]/2.0,
+				    slice_offset+float(image_level)*this->spacing[2]+this->origin[2]);
+	  UpdateControlsFromCurrentSpline();
+	  break;
+	  
+	case 453:
+	  sprintf(pxtk_buffer,"Curve %d Area=%8.1f mm^2\n",current_spline+1,currentSpline->GetArea());
+	  PXTkApp::printToConsole(pxtk_buffer);
+	  this->EventManager->messageBox(pxtk_buffer,"Curve Area ...");
+	  break;
+	  
+	case 454:
+	  if (image!=NULL)
+	    {
+	      float area[2],mean[2],std[2],threshold[2];
+	      int np[2];
+	      for (int ii=0;ii<2;ii++)
+		{
+		  threshold[ii]=atof(thresholdEntry[ii]->getText());
+		  sprintf(pxtk_buffer,"%5.2f",threshold[ii]);
+		  thresholdEntry[ii]->setText(pxtk_buffer);
+		}
+	      
+	      int nt=currentSpline->GetDualVOIProperties(image,image_level,image_frame,
+							 area,mean,std,np,threshold);
+	      
+	      if (area[0]<0.0001)
+		area[0]=0.0001;
+	      
+	      sprintf(pxtk_buffer,"Curve %d Total Enclosed Area=%8.1f mm^2 npix=%d\n",
+		      current_spline+1,currentSpline->GetArea(),nt);
+	      PXTkApp::printToConsole(pxtk_buffer);
+	      for (int i=0;i<=1;i++)
+		{
+		  sprintf(pxtk_buffer,"\t ROI %d area >%.1f \t= %6.1f (mm^2) mean=%5.1f std=%5.1f npix=%6d\n",
+			  i+1,threshold[i],area[i],mean[i],std[i],np[i]);
+		  PXTkApp::printToConsole(pxtk_buffer);
+		}
+	      sprintf(pxtk_buffer, "\t Ratio 2/1  \t= %5.2f %% \n\n",
+		      area[1]/area[0]*100.0);
+	      PXTkApp::printToConsole(pxtk_buffer);
+	      PXTkApp::popupConsole();
+	    }
+	  break;
+	  
+	case 501:
+	  display_mode[current_spline]=displayMode->getState();
+	  Update();
+	  break;
+
+	case 502:
+	  if (editActor!=NULL)
+	    {
+	      if (showControls->getState())
+		editActor->SetVisibility(1);
+	      else
+	      editActor->SetVisibility(0);
+	  }
+	  break;
+	  
+	case 503:
+	  scale_mode[current_spline]=scaleMode->getIndex();
+	  editCurve->SetPointScale(0.25+0.25*float(scale_mode[current_spline])*this->ControlPointScaleFactor);
+	  /*fprintf(stderr,"Dist Threshold=%f controlpointscalefactor=%f pointscale=%f\n",
+		  this->DistanceThreshold,this->ControlPointScaleFactor,
+		  editCurve->GetPointScale());*/
+	  break;
+	  
+	case 504:
+	  slice_offset=-slice_offset;
+	  this->SetLevel(image_level);
+	  break;
+	  
+	case 505:
+	  {
+	    for  (int i=0;i<this->NumberOfSplines;i++)
+	      display_mode[i]=PXFalse;
+	    displayMode->setState(PXFalse);
+	  }
+	  Update();
+	  break;
+	  
+	case 506:
+	{
+	  for  (int i=0;i<this->NumberOfSplines;i++)
+	    display_mode[i]=PXTrue;
+	  displayMode->setState(PXTrue);
+	}
+	Update();
+	break;
+	
+	  
+	case 510:
+	  if (editMode->getState()==PXFalse)
+	    {
+	      if (this->manual_add_mode==1)
+		this->FitSplineToCurrentControls();
+	    }
+	  else
+	    {
+	      this->manual_add_mode=1;
+	      splineSet[current_spline]->ExportToBaseCurve(this->manualEditCurve);
+	      this->manualEditCurve->SetPointScale(editCurve->GetPointScale()*0.5);
+	      this->manualEditCurve->DeleteAllPoints();
+	      this->manualEditActor->SetVisibility(1);
+	    }
+	  break;
+
+	case 600: // x0.8
+	  {
+	    float s=this->currentSpline->GetSpline()->getlength(0.0,1.0,0.05)/100.0;
+	    currentSpline->ChangeSpacing(this->DefaultSmoothing*s,(80*currentSpline->GetNumPoints())/100);
+	    UpdateControlsFromCurrentSpline();
+	  }
+	  break;
+	  
+	case 601: // x1.0
+	  {
+	    float s=this->currentSpline->GetSpline()->getlength(0.0,1.0,0.05)/100.0;
+	    currentSpline->ChangeSpacing(this->DefaultSmoothing*s,currentSpline->GetNumPoints());
+	    UpdateControlsFromCurrentSpline();
+	  }
+	  break;
+	  
+	case 602: // x1.25
+	  {
+	    float s=this->currentSpline->GetSpline()->getlength(0.0,1.0,0.05)/100.0;
+	    currentSpline->ChangeSpacing(this->DefaultSmoothing*s,(125*currentSpline->GetNumPoints())/100);
+	    UpdateControlsFromCurrentSpline();
+	  }
+	  break;
+	  
+	  
+	case 604: // sD
+	  {
+	    float s=this->currentSpline->GetSpline()->getlength(0.0,1.0,0.05)/100.0;
+	    float t=Frange(atof(SmoothingEntry->getText()),0.0001,10.0);
+	    char line[10]; sprintf(line,"%f",t); SmoothingEntry->setText(line);
+	    currentSpline->ChangeSpacing(t*s,-1);
+	    UpdateControlsFromCurrentSpline();
+	  }
+	break;
+	
+	  
+	case 610:
+	  DoSnake(0);
+	  break;
+	  
+	case 611:
+	  DoSnake(1);
+	  break;
+	  
+	case 612:
+	  DoSnake(2);
+	  break;
+	  
+	case 613:
+	  DoSnake(3);
+	  break;
+	  
+	}
+    }
+
+
+  UpdateDisplay();
+
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::SetItemColor(int index,double color[3])
+{
+  if (splineActor[index]!=NULL)
+    splineActor[index]->GetProperty()->SetColor(color);
+
+}
+
+void vtkpxGUIObjectmapSplineControl::SetItemFilename(int index,const char* s)
+{
+  if (this->Initialized==0)
+    return;
+
+  //  fprintf(stderr,"index=%d s=%s\n",index,s);
+
+  if (index==-1)
+    {
+      sprintf(pxtk_buffer2,"%s.%d",PXTkApp::getFilenameTail(s),current_spline+1);
+      currentCollection->changeLabel(current_spline,pxtk_buffer2);
+      return;
+    }
+
+  sprintf(pxtk_buffer2,"%s.%d",PXTkApp::getFilenameTail(s),index+1);
+  currentCollection->changeLabel(index,pxtk_buffer2);
+
+}
+
+/* -------------------------------------------------------------------------*/
+vtkpxSplineSource* vtkpxGUIObjectmapSplineControl::GetSpline(int index)
+{
+  if (index==-1)
+      index=current_spline;
+
+  return splineSet[Irange(index,0,this->NumberOfSplines-1)];
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIObjectmapSplineControl::GetCurrentIndex()
+{
+  return current_spline;
+}
+
+int  vtkpxGUIObjectmapSplineControl::GetCurrentSliceNumber()
+{
+  return image_level;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::SetSpline(vtkpxSplineSource* land,int index)
+{
+  if (index==-1)
+    index=current_spline;
+
+  index=Irange(index,0,this->NumberOfSplines-1);
+
+  splineSet[index]->Copy(land);
+  float zlev=image_level*this->spacing[2]+this->origin[2];
+  splineSet[index]->SetZlevel(zlev+slice_offset);
+  this->manual_zcoord=zlev+slice_offset;
+  this->changed[index]=1;  
+
+
+  if (index==current_spline)
+    UpdateControlsFromCurrentSpline();
+  
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::SetChangedStatus(int index,int val)
+{
+  index=Irange(index,0,this->NumberOfSplines-1);
+  this->changed[index]=(val>0);
+  //  fprintf(stderr,"Changed[%d]=%d\n",index+1,this->changed[index]);
+}
+
+int  vtkpxGUIObjectmapSplineControl::GetChangedStatus(int index)
+{
+  index=Irange(index,0,this->NumberOfSplines-1);
+  return this->changed[index];
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::SetImage(vtkImageData* img,int plane,int level,int frame)
+{
+  if (img!=NULL)
+    {
+      if (this->image!=NULL)
+	this->image->Delete();
+      this->image=vtkImageData::New();
+      this->image->ShallowCopy(img);
+      
+      int d[3]; double sp[3],ori[3];
+      image->GetSpacing(sp);
+      image->GetOrigin(ori);
+      image->GetDimensions(d);
+ 
+      double sum=0.0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=fabs(float(d[ia]-this->dimensions[ia]))+fabs(sp[ia]-this->spacing[ia])+fabs(ori[ia]-this->origin[ia]);
+
+      if (sum>0.01)
+	{
+	  this->SetSpacingOrigin(sp,ori);
+	  this->SetLevel(level);
+	  image->GetDimensions(d);
+	  image->GetDimensions(this->dimensions);
+	  	  
+	  for (int i=0;i<this->NumberOfSplines;i++)
+	    {
+	      splineSet[i]->SetEllipse(6,
+				       spacing[0]*dimensions[0]/8.0*(1.0+i),
+				       spacing[1]*dimensions[1]/8.0*(1.0+i),
+				       origin[0]+spacing[0]*dimensions[0]/2.0,
+				       origin[1]+spacing[1]*dimensions[1]/2.0,
+				       0.0,2);
+	      splineSet[i]->SetResolution(sp[0]);
+	    }
+
+	  this->DistanceThreshold=(spacing[0]*dimensions[0])/50.0;
+	  this->ControlPointScaleFactor=this->DistanceThreshold*0.5;
+	  editCurve->SetPointScale(0.25+0.25*float(scale_mode[current_spline])*this->ControlPointScaleFactor);
+	  /*fprintf(stderr,"Dist Threshold=%f controlpointscalefactor=%f pointscale=%f\n",
+		  this->DistanceThreshold,this->ControlPointScaleFactor,
+		  editCurve->GetPointScale());*/
+	}
+      else
+	{
+	  if (level!=image_level)
+	    this->SetLevel(level);
+	  image_frame=frame;
+	}
+    }
+}
+
+void vtkpxGUIObjectmapSplineControl::SetPlaneLevel(int plane,int level)
+{
+  this->SetLevel(level);
+}
+
+
+void vtkpxGUIObjectmapSplineControl::SetSpacingOrigin(double sp[3],double ori[3])
+{
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->origin[ia]=ori[ia];
+      this->spacing[ia]=sp[ia];
+    }
+
+
+  for (int i=0;i<this->NumberOfSplines;i++)
+    {
+      splineSet[i]->SetImageOrigin(this->origin);
+      splineSet[i]->SetImageSpacing(this->spacing);
+    }
+
+}
+
+void vtkpxGUIObjectmapSplineControl::SetLevel(int level)
+{
+  image_level=level;
+  double zlev=level*this->spacing[2]+this->origin[2];
+  this->manual_zcoord=zlev+slice_offset;
+  for (int i=0;i<this->NumberOfSplines;i++)
+    {
+      splineSet[i]->SetZlevel(zlev+slice_offset);
+    }
+  UpdateControlsFromCurrentSpline();
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIObjectmapSplineControl::HandleClickedPoint(float x,float y,float z,int scaled,int state)
+{
+  static int found_point=-1;
+  if (!mouseMode->getState())
+    return 0;
+
+
+  if (spline_enabled[current_spline]==0)
+    return 0;
+
+  fprintf(stderr,"add_mode=%d \n",this->manual_add_mode);
+
+
+  if (this->manual_add_mode==1)
+    {
+      switch (state)
+	{
+	case 0:
+	  this->manualEditCurve->AddPoint(x,y,manual_zcoord,scaled);
+	  fprintf(stderr,"Adding Point %.2f %.2f\n",x,y);
+	  break;
+	case 1:
+	  this->manualEditCurve->SetPoint(this->manualEditCurve->GetNumPoints()-1,x,y,manual_zcoord,scaled);
+	  break;
+	case 2:
+	  break;
+	}
+      return 1;
+    }
+
+
+  if (editActor==NULL)
+    return 0;
+
+  if (editActor->GetVisibility()==0)
+    return 0;
+
+
+  int numitems=currentSpline->GetNumPoints();//listBox->getNumItems();
+  if (numitems<1)
+    return 0;
+
+  double lx[3];
+  switch (state)
+    {
+    case 0:
+    case 6:
+      {
+	lx[0]=x;lx[1]=y;lx[2]=z;
+	found_point=editCurve->FindClosestPoint(lx,this->DistanceThreshold,1);
+	if (found_point>=0)
+	  return 1;
+      }
+      break;
+
+    case 1:
+      if (found_point>=0)
+	{
+	  double x1,y1,z1;
+	  editCurve->GetPoint(found_point,x1,y1,z1);
+	  editCurve->SetPoint(found_point,x,y,z1,scaled);
+	  currentSpline->SetFromBaseCurve(editCurve);
+	  this->SetChangedStatus(current_spline,1);
+	  return 1;
+	  return 1;
+	}
+      break;
+
+    case 7:
+      if (found_point>=0)
+	{
+	  double x1,y1,z1;
+	  editCurve->GetPoint(found_point,x1,y1,z1);
+	  float dx=x-x1;
+	  float dy=y-y1;
+	  int np=editCurve->GetNumPoints();
+	  for (int ia=0;ia<np;ia++)
+	    {
+	      editCurve->GetPoint(ia,x1,y1,z1);
+	      editCurve->SetPoint(ia,x1+dx,y1+dy,z1,scaled);
+	    }
+	  currentSpline->SetFromBaseCurve(editCurve);
+	  this->SetChangedStatus(current_spline,1);
+	  return 1;
+	}
+      break;
+
+    case 2:
+    case 8:
+      if (found_point>=0)
+	{
+	  found_point=-1;
+	  UpdateStatus();
+	  return 1;
+	}
+      break;
+
+    case 5:
+      {
+	int ok=currentSpline->InsertKnot(x,y);
+	if (ok==1)
+	  {
+	    UpdateControlsFromCurrentSpline();
+	  }
+      }
+      break;
+    }
+  return 0;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::UpdateControlsFromCurrentSpline()
+{
+  if (spline_enabled[current_spline]==0)
+    {
+      UpdateStatus();
+      return;
+    }
+  this->editCurve->SetShowCurve(0);
+  splineSet[current_spline]->ExportToBaseCurve(editCurve);
+  displayMode->setState(display_mode[current_spline]);
+  scaleMode->setIndex(scale_mode[current_spline]);
+  UpdateStatus();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIObjectmapSplineControl::DoSnake(int apply)
+{
+  if (image==NULL)
+      return 0;
+  
+  if (apply==0)
+    {
+      if (snakeGUI==NULL)
+	{
+	  PXTkFrame* polyFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+	  snakeGUI=new PXTkDialog(this->EventManager,polyFrame,"Snake Controls",PXFalse);
+	  snakeGUI->initDisplay();
+	  PXTkFrame* frame=(PXTkFrame*)snakeGUI->getMainWindow();
+	  
+	  snakeEdgeWeight=new PXTkArrowScale(snakeGUI,frame,"Edge Weight",-1,PXTrue);
+	  snakeEdgeWeight->setRange(0.0,10.0);
+	  snakeEdgeWeight->setIncrement(0.5);
+	  snakeEdgeWeight->setResolution(0.1);
+	  snakeEdgeWeight->setDecimalPoints(1);
+	  snakeEdgeWeight->setLengthWidth(120,8);
+	  
+	  snakeSmoothWeight=new PXTkArrowScale(snakeGUI,frame,"Smoothness Weight",-1,PXTrue);
+	  snakeSmoothWeight->setRange(0.0,10.0);
+	  snakeSmoothWeight->setIncrement(0.5);
+	  snakeSmoothWeight->setResolution(0.1);
+	  snakeSmoothWeight->setDecimalPoints(1);
+	  snakeSmoothWeight->setLengthWidth(120,8);
+	  
+	  snakeSigma=new PXTkArrowScale(snakeGUI,frame,"Sigma",-1,PXTrue);
+	  snakeSigma->setRange(0.0,4.0);
+	  snakeSigma->setIncrement(0.5);
+	  snakeSigma->setResolution(0.1);
+	  snakeSigma->setDecimalPoints(1);
+	  snakeSigma->setLengthWidth(120,8);
+	  
+	  snakeIterations=new PXTkArrowScale(snakeGUI,frame,"Iterations",-1,PXTrue);
+	  snakeIterations->setRange(1,20);
+	  snakeIterations->setIncrement(3);
+	  snakeIterations->setResolution(1);
+	  snakeIterations->setDecimalPoints(0);
+	  snakeIterations->setLengthWidth(120,8);
+	  
+
+	  snakeStep=new PXTkArrowScale(snakeGUI,frame,"Step",-1,PXTrue);
+	  snakeStep->setRange(0.0,1.0);
+	  snakeStep->setIncrement(0.05);
+	  snakeStep->setResolution(0.01);
+	  snakeStep->setDecimalPoints(2);
+	  snakeStep->setLengthWidth(120,8);
+
+	  PXTkFrame* fr2=new PXTkFrame(snakeGUI,frame);
+	  PXTkButton* b1=new PXTkButton(this->EventManager,fr2,"Create",611);
+	  PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Update",612);
+	  PXTkButton* b3=new PXTkButton(this->EventManager,fr2,"Reset",613);
+	  PXTkButton* b4=new PXTkButton(snakeGUI,fr2,"Close",3);
+	  
+	  b1->configure("-padx",1);
+	  b2->configure("-padx",1);
+	  b3->configure("-padx",1);
+	  b4->configure("-padx",1);
+	  
+	  frame->addChildren("-side top -expand true -fill x",
+			     snakeEdgeWeight->getMainWindow(),
+			     snakeSmoothWeight->getMainWindow(),
+			     snakeIterations->getMainWindow());
+	  frame->addChildren("-side bottom -expand true -fill x",
+			     fr2,
+			     snakeSigma->getMainWindow(),
+			     snakeStep->getMainWindow());
+	  fr2->addChildren("-side left -expand true -fill x",b1,b2,b3,b4);
+	}
+      
+      /*snakeEdgeWeight->setRange(image_range[0],image_range[1]);
+	snakeEdgeWeight->setValue(Frange(snakeEdgeWeight->getValue(),image_range[0],image_range[1]));*/
+      snakeGUI->popupDialog();
+      DoSnake(3);
+    }
+  
+
+  if (snakeGUI==NULL)
+    {
+      DoSnake(0);
+      snakeGUI->popdownDialog();
+    }
+  
+  
+  if (apply==3)
+    {
+      snakeEdgeWeight->setValue(3.0);
+      snakeSmoothWeight->setValue(3.0);
+      snakeSigma->setValue(1.0);
+      snakeIterations->setValue(5);
+      snakeStep->setValue(0.05);
+    }
+
+  if (apply==1)
+    {
+      float w_img=snakeEdgeWeight->getValue()*10.0;
+      float w_smo=snakeSmoothWeight->getValue()*0.1;
+      float sigma=snakeSigma->getValue();
+      float stp=snakeStep->getValue();
+      int   iter=(int)snakeIterations->getValue();
+      
+      currentSpline->CreateSnake(image,image_level,image_frame,
+				 w_img,w_smo,stp,sigma,iter);
+      this->changed[current_spline]=1;
+    }
+
+  if (apply==1 || apply==2)
+    {
+      if (mouseMode->getState()==PXFalse)
+	mouseMode->setState(PXTrue);
+      float w_img=snakeEdgeWeight->getValue()*10.0;
+      float w_smo=snakeSmoothWeight->getValue()*0.1;
+
+      currentSpline->UpdateSnake(w_img,w_smo);      
+      this->changed[current_spline]=1;
+      UpdateControlsFromCurrentSpline();
+    }
+
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::EnableSpline(int i)
+{
+  i=Irange(i,0,this->NumberOfSplines-1);
+  spline_enabled[i]=1;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::DisableSpline(int i)
+{
+  i=Irange(i,0,this->NumberOfSplines-1);
+  spline_enabled[i]=1; // Fix this some time
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineControl::FitSplineToCurrentControls()
+{
+  int nump=manualEditCurve->GetNumPoints();
+  int ok=0;
+
+  if (nump<4)
+    ok=this->EventManager->questionBox("Not enough points to fit spline! Do you want to add more points? (No will revert to current spline)");
+  else
+    ok=this->EventManager->questionBox("Do you want to fit spline to current set of controls? This will delete your old spline. Are you sure?");
+
+  if (ok==0)
+    {
+      this->manual_add_mode=0;
+      this->manualEditActor->SetVisibility(0);
+      return;
+    }
+
+  if (nump<4)
+    {
+      editMode->setState(PXTrue);
+      return;
+    }
+
+  manualEditCurve->Compact();
+  float z=this->currentSpline->GetZlevel();
+  this->currentSpline->FitPoints(manualEditCurve->GetPoints(),0.1,-1,1,100);
+  this->currentSpline->ChangeSpacing(1.0,currentSpline->GetNumPoints());
+  this->currentSpline->SetZlevel(z);
+  this->currentSpline->Modified();
+
+  this->manualEditActor->SetVisibility(0);
+  this->manual_add_mode=0;
+  UpdateControlsFromCurrentSpline();
+}
+/* -------------------------------------------------------------------------*/
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObjectmapSplineControl.h b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapSplineControl.h
new file mode 100644
index 0000000..65c8ce0
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapSplineControl.h
@@ -0,0 +1,300 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIObjectmapSplineControl.h,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:29 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIObjectmapSplineControl - Base Image Viewer
+// .SECTION Description
+
+#ifndef __vtkpxGUIObjectmapSplineControl_h
+#define __vtkpxGUIObjectmapSplineControl_h
+
+#include "vtkpxSplineSource.h"
+#include "vtkpxBaseCurve.h"
+#include "vtkpxGUIBaseCurveEditor.h"
+#include "vtkActor.h"
+#include "pxtkapp.h"
+#include "pxtkeventobj.h"
+#include "pxtkgadgets.h"
+#include "pxtkcomplexwidgets.h"
+#include "pxtkdialog.h"
+#include "pxtkmenu.h"
+#include "pxcontour.h"
+#include "vtkpxGUISplineControl.h"
+
+class vtkpxGUIObjectmapEditor;
+
+//const int SP_MAX_COLLECTIONS = 2; 
+
+class vtkpxGUIObjectmapSplineControl : public vtkpxGUIBaseCurveEditor 
+{
+public:
+
+  static vtkpxGUIObjectmapSplineControl *New();
+  vtkTypeMacro(vtkpxGUIObjectmapSplineControl,vtkpxGUIBaseCurveEditor);
+  
+
+  // Description:
+  // Set/Get Number Of Splines 
+  virtual void SetNumberOfSplines(int a);
+  vtkGetMacro(NumberOfSplines,int);
+
+  // Description:
+  // Initialize Display and add Renderer 
+  virtual char*  Initialize(const char* name,int inside);
+  virtual void   SetRenderer(vtkRenderer *rendererer,int num);
+  virtual void   SetRenderer(vtkRenderer *rendererer);
+
+  // Description:
+  // Update Display
+  virtual void   Update();
+  virtual void   UpdateDisplay();
+
+  // Description:
+  // Event Manager 
+  virtual int    HandleEvent(int);
+  
+  // Description:
+  // Update status label with info on current spline 
+  virtual void    UpdateStatus();
+
+  // Description:
+  // Handle mouse point 
+  virtual int     HandleClickedPoint(float x,float y,float z,int scaled=1,int state=0);
+
+  // Description:
+  // Get and Set Current Spline 
+  virtual vtkpxSplineSource* GetSpline(int index=-1);
+  virtual vtkObject* GetItem(int index) { return GetSpline(index);}
+  virtual int  GetCurrentIndex();
+  virtual void SetSpline(vtkpxSplineSource* land,int index=-1);
+  virtual int  GetCurrentSliceNumber();
+  virtual void SetItemColor(int index,double color[3]);
+  virtual void SetItemFilename(int index,const char* s);
+
+  // Description:
+  // Set Current Image , including slice and orientation
+  // Discards plane and assumes plane =2 
+  virtual void SetImage(vtkImageData* image,int plane=2,int level=0,int frame=0);
+  virtual void SetPlaneLevel(int plane,int level);
+  virtual void SetSpacingOrigin(double sp[3],double ori[3]);
+  virtual void SetLevel(int level);
+  
+  // Description:
+  // Snake Operations 
+  virtual int  DoSnake(int apply);
+
+
+  // Description:
+  // Callback Handlers for Clipboard Operations
+  virtual void UpdateControlsFromCurrentSpline();
+  virtual void FitSplineToCurrentControls();
+
+  //BTX
+  PXTkFrame* getBottomButtonFrame() { return bottomButtonFrame;}
+  //ETX
+
+
+  // Description:
+  // Enable/Disable Spline
+  virtual void EnableSpline(int i);
+  virtual void DisableSpline(int i);
+
+  // Description:
+  // Get Auto Update Mode
+  vtkGetMacro(AutoUpdateMode,int);
+
+  // Description:
+  // Clean Changed Status
+  virtual void SetChangedStatus(int index,int val);
+  virtual int  GetChangedStatus(int index);
+
+  // Description:
+  // Slave Mode i.e. not main program
+  vtkSetClampMacro(SlaveMode,int,0,1);
+  vtkGetMacro(SlaveMode,int);
+  vtkBooleanMacro(SlaveMode,int);
+  
+  // Description:
+  // Default Smoothing 
+  vtkSetClampMacro(DefaultSmoothing,double,0.0001,10.0);
+  vtkGetMacro(DefaultSmoothing,double);
+
+  // Description:
+  // ObjectMap Editor 
+  virtual void SetObjectmapEditor(vtkpxGUIObjectmapEditor* ed);
+ 
+
+protected:
+
+  vtkpxGUIObjectmapSplineControl();
+  virtual ~vtkpxGUIObjectmapSplineControl();
+
+  // Description:
+  // Splines for editing backup and pointer to current 
+  vtkpxSplineSource *currentSpline;
+  vtkpxSplineSource *splineSet[SP_MAX_COLLECTIONS];
+  vtkRenderer* Renderer;
+
+  // Description:
+  // Parent Object
+  vtkpxGUIObjectmapEditor* ObjectmapEditor;
+
+  // Description:
+  // Curve to display control points 
+  vtkpxBaseCurve    *editCurve;
+  vtkpxBaseCurve    *manualEditCurve;
+  
+
+
+  // Description:
+  // vtkActors which capture curves/control points 
+  vtkActor*         splineActor[SP_MAX_COLLECTIONS];
+  vtkActor*         editActor;
+  vtkActor*         manualEditActor;
+
+  // Description:
+  // Gadgets/Widgets for Snakes
+  PXTkDialog*       snakeGUI;
+  PXTkArrowScale* snakeEdgeWeight;
+  PXTkArrowScale* snakeSmoothWeight;
+  PXTkArrowScale* snakeStep;
+  PXTkArrowScale* snakeSigma;
+  PXTkArrowScale* snakeIterations;
+
+
+  // Description:
+  // Gadgets/Widgets for Snakes
+  PXTkDialog*       resampleGUI;
+  PXTkArrowScale*   resampleNumberOfPoints;
+  PXTkArrowScale*   resampleSmoothing;
+  PXTkArrowScale*   resampleDs;
+  PXTkArrowScale*   resamplePreSmooth;
+  PXTkArrowScale*   resamplePreSmoothIterations;
+
+
+  // Description:
+  // Index of Current Spline and Number of Splines 
+  int             current_spline;
+  int             NumberOfSplines;
+
+  // Description:
+  // Visibility and Size (in units 0f 0.25 pixels) of all splines 
+  PXBool          display_mode[SP_MAX_COLLECTIONS];
+  int             scale_mode[SP_MAX_COLLECTIONS];
+  int             spline_enabled[SP_MAX_COLLECTIONS];
+  int             manual_add_mode;
+  int             SlaveMode;
+  float           manual_zcoord;
+
+  // Description:
+  // Status Label
+  PXTkLabel*       message;
+
+  // Description:
+  // Options to select whether to show/hide controls mouse mode etc
+  PXTkCheckButton*  showControls;
+  PXTkCheckButton*  mouseMode;
+  PXTkCheckButton*  editMode;
+  PXTkCheckButton*  autoUpdate;
+  PXTkOptionMenu   *currentCollection;
+
+  // Description:
+  // Show/Hide Current Spline, size of current spline 
+  PXTkCheckButton  *displayMode;
+  PXTkOptionMenu   *scaleMode;
+  PXTkFrame        *bottomButtonFrame;
+  PXTkEntry        *thresholdEntry[2];
+  PXTkEntry        *SmoothingEntry;
+
+
+  // Description:
+  // Current Image and Energy map as well as image properties
+  vtkImageData    *image;
+  int             image_level;
+  int             image_frame;
+  double          image_range[2];
+  double          spacing[3];
+  double          origin[3];
+  double          DefaultSmoothing;
+  int             dimensions[3];
+  double           slice_offset;
+  int             AutoUpdateMode;
+  float           DistanceThreshold;
+  float           ControlPointScaleFactor;
+  int             changed[SP_MAX_COLLECTIONS];
+
+  // Description:
+  // Callback Handlers for Changing Spline, Updating GUI and Loading Spline
+  virtual void SetCurrentCollection(int ) { return; }
+
+
+  // Description:
+  // Initialize Splines
+  virtual void InitializeSplines();
+
+
+  // Description:
+  // Following Needed to satisfy undefined calls
+  virtual void SetFrame(int) { } 
+  virtual void SetLookupTable (vtkLookupTable *) { }
+  virtual void SetTransform(vtkAbstractTransform *) { } 
+  virtual vtkAbstractTransform* GetTransform () { return NULL;}
+
+};
+
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObjectmapSplineStackControl.cpp b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapSplineStackControl.cpp
new file mode 100644
index 0000000..8e3d2e7
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapSplineStackControl.cpp
@@ -0,0 +1,1035 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// 	$Id: vtkpxGUIObjectmapSplineStackControl.cpp,v 1.2 2003/09/12 12:59:32 xenios Exp xenios $	
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkpxGUIObjectmapSplineStackControl.h"
+#include "vtkpxUtil.h"
+#include "vtkActor.h"
+#include "vtkAssembly.h"
+#include "vtkRenderer.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxImageExtract.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkImageData.h"
+#include "vtkPolyDataWriter.h"
+#include "vtkpxTriangulatedStackSource.h"
+#include "pxchamferdistancemap.h"
+#include "pxfpbspline.h"
+#include "pxcontour.h"
+#include "vtkpxGUIBaseImageViewer.h"
+#include "vtkpxSurfaceUtil.h"
+/* -------------------------------------------------------------------------*/
+vtkpxGUIObjectmapSplineStackControl* vtkpxGUIObjectmapSplineStackControl::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIObjectmapSplineStackControl");
+  if(ret)
+      {
+	return (vtkpxGUIObjectmapSplineStackControl*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIObjectmapSplineStackControl;
+}
+
+// ----------------------------------------------------------------------------
+vtkpxGUIObjectmapSplineStackControl::vtkpxGUIObjectmapSplineStackControl()
+{
+  this->do_autosave=PXTrue;
+  this->do_backup=PXTrue;
+  this->dimensions[0]=-1;
+  this->SplineEditor=NULL;
+  this->sliceScale=NULL;
+  //  this->frameScale=NULL;
+  this->BaseViewer=NULL;
+
+  surface_setfilename=new char[30];
+  strcpy(surface_setfilename,"unnamed_set.multisur");
+
+}
+// ----------------------------------------------------------------------------
+vtkpxGUIObjectmapSplineStackControl::~vtkpxGUIObjectmapSplineStackControl()
+{
+  this->SetBaseViewer(NULL);
+  delete [] surface_setfilename;
+}
+// ----------------------------------------------------------------------------
+void vtkpxGUIObjectmapSplineStackControl::InitializeSplineStacks()
+{
+  vtkpxGUISplineStackControl::InitializeSplineStacks();
+}
+// ----------------------------------------------------------------------------
+void vtkpxGUIObjectmapSplineStackControl::ResetSplineStacks()
+{
+  int d[3]; double sp[3],ori[3];
+  for (int ib=0;ib<=2;ib++)
+    {
+      d[ib]=this->dimensions[ib];
+      sp[ib]=this->spacing[ib];
+      ori[ib]=this->origin[ib];
+    }
+  
+  this->image->GetSpacing(this->spacing);
+  this->image->GetOrigin(this->origin);
+  this->image->GetDimensions(this->dimensions);
+
+  
+  float sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+    sum+=
+      fabs(float(d[ia]-this->dimensions[ia]))+
+      fabs(sp[ia]-this->spacing[ia])+
+      fabs(ori[ia]-this->origin[ia]);
+
+  vtkpxSplineStackSource *st=splineStackSet[0];
+
+  if ( (st->GetPolarMode()==0 && this->orientation==3) || (st->GetPolarMode()==1 && this->orientation!=3))
+       sum=1.0;
+
+  if (sum>0.01)
+    {
+      float dz=spacing[2];
+      float factor=1.0;
+      if (this->orientation==3)
+	dz=180.0/float(this->dimensions[2]);
+
+      for (int i=0;i<this->NumberOfSplineStacks;i++)
+	{
+	  vtkpxSplineStackSource *st=splineStackSet[i];
+	  surface_modified[i]=0;
+	  //	  fprintf(stderr,"Creating Surface dz=%.2f\n",dz);
+
+
+	  st->SetEllipticalCylinder(8,
+				    this->dimensions[2],
+				    factor*spacing[0]*dimensions[0]/(2.0*this->NumberOfSplineStacks)*(1.0+i),
+				    factor*spacing[1]*dimensions[1]/(2.0*this->NumberOfSplineStacks)*(1.0+i),
+				    origin[0]+spacing[0]*dimensions[0]/2.0,
+				    origin[1]+spacing[1]*dimensions[1]/2.0,
+				    dz,
+				    this->origin[2]);
+	  st->SetDrawMode(0);
+	  
+	  if (this->orientation==3)
+	    {
+	      st->SetPolarMode(1);
+	      st->SetPolarMiddle(spacing[0]*dimensions[0]*0.5+origin[0]);
+	    }
+	  else
+	    {
+	      st->SetPolarMode(0);
+	      if (dimensions[2]>12)
+		{
+		  st->SetTrimBottom(dimensions[2]/2-5);
+		  st->SetTrimTop(dimensions[2]/2+5);
+		}
+	      else
+		{
+		  st->SetTrimTop(dimensions[2]-1);
+		  st->SetTrimBottom(0);
+		}
+	    }
+	  
+	  st->SetResolutionU(2.0*spacing[1]);
+	  st->SetResolutionV(spacing[2]);
+	}
+    }
+  
+  // Get Current Spline Stack then set trims
+  trimScale[0]->setRange(0,this->dimensions[2]-1);
+  trimScale[1]->setRange(0,this->dimensions[2]-1);
+  trimScale[0]->setValue(this->currentSplineStack->GetTrimBottom());
+  trimScale[1]->setValue(this->currentSplineStack->GetTrimTop());
+  this->UpdateSplineEditor();
+}
+
+// -------------------------------------------------------------------------
+
+char* vtkpxGUIObjectmapSplineStackControl::Initialize(const char* name,int inside)
+{
+  return this->Initialize(name,name,name,inside);
+}
+
+char* vtkpxGUIObjectmapSplineStackControl::Initialize(const char* name,const char* name2,const char* name3,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+
+  vtkpxGUISplineStackControl::Initialize(name,inside);
+
+  PXTkLabelFrame* mFrame=NULL;
+  if (strcmp(name,name2)==0)
+    {
+      mFrame=new PXTkLabelFrame(this->EventManager,this->controlFrame,"Surface");
+      this->controlFrame->addChildren("-side top -expand false -fill x -padx 1 -pady 2",mFrame);
+    }
+  else
+    {
+      PXTkFrame* m=new PXTkFrame(NULL,name2);
+      mFrame=new PXTkLabelFrame(this->EventManager,m,"Additional Operations");
+      m->addChildren("-side top -expand false -fill x -padx 1 -pady 2",mFrame);
+    }
+
+  masterFrame=NULL;
+  if (strcmp(name,name3)==0)
+    {
+      masterFrame=new PXTkFrame(this->EventManager,this->controlFrame);
+      this->controlFrame->addChildren("-side top -expand false -fill x -padx 1 -pady 2",masterFrame);
+    }
+  else
+    {
+      PXTkFrame* m=new PXTkFrame(NULL,name3);
+      masterFrame=new PXTkFrame(this->EventManager,m);
+      m->addChildren("-side top -expand true -fill both -padx 1 -pady 2",masterFrame);
+    }
+
+  mFrame->setPackMode(PXTrue);
+  masterFrame->setPackMode(PXTrue);
+
+
+  PXTkFrame* f1=new PXTkFrame(this->EventManager,mFrame);
+  PXTkFrame* f2=new PXTkFrame(this->EventManager,mFrame);
+  PXTkFrame* f3=new PXTkFrame(this->EventManager,mFrame);
+  PXTkFrame* f4=new PXTkFrame(this->EventManager,mFrame);
+  mFrame->addChildren("-side top -expand false -fill x -pady 2 ",f1,f2,f3,f4);
+
+  this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,10);
+ 
+  PXTkLabel* labs=new PXTkLabel(this->EventManager,f1,"Current Stack:");
+  currentCollection2=new PXTkOptionMenu(this->EventManager,f1,"Stack 1",800);
+  for (int ip=1;ip<this->NumberOfSplineStacks;ip++)
+    {
+      sprintf(pxtk_buffer4,"Stack %d",ip+1);
+      currentCollection2->addOption(pxtk_buffer4);
+    }
+  currentCollection2->setIndex(current_splinestack);
+  f1->addChildren("-side left -expand t -fill x -pady 1",labs,currentCollection2);
+    
+
+  PXTkButton* but1a=new PXTkButton(this->EventManager,f3,"Load Set",702);
+  PXTkButton* but2a=new PXTkButton(this->EventManager,f3,"Save Set",703);
+  f3->addChildren("-side top -expand t -fill x -pady 1",but1a,but2a);
+
+
+  autosavebutton=new PXTkCheckButton(this->EventManager,f3,"Autosave",803);
+  autosavebutton->setState(do_autosave);
+  backupbutton=new PXTkCheckButton(this->EventManager,f3,"Backup",803);
+  backupbutton->setState(do_backup);
+  f3->addChildren("-side top -expand t -fill x -pady 1",autosavebutton,backupbutton);
+
+  f4->setPackMode(PXTrue);
+
+  PXTkButton* but1=new PXTkButton(this->EventManager,f4,"Shift And Scale",810);
+  PXTkButton* but4=new PXTkButton(this->EventManager,f4,"Cylinders",813);
+  PXTkButton* but5=new PXTkButton(this->EventManager,f4,"Export",815);
+  PXTkButton* but7=new PXTkButton(this->EventManager,f4,"Extract From (Binary) Image",816);
+  f4->addChildren("-side top -expand t -fill x -pady 1",but1,but4,but5,but7);
+
+
+  // Master Frame Stuff (i.e. frame and scale)
+
+  sliceScale=new PXTkArrowScale(this->EventManager,masterFrame,"Slice",804,PXFalse);
+  //  frameScale=new PXTkArrowScale(this->EventManager,masterFrame,"Fr",805,PXFalse);
+  PXTkButton* but9=new PXTkButton(this->EventManager,masterFrame,"Objectmap/Spline Editor",806);
+  //  frameScale->setRange(1,1);
+
+  sliceScale->setValue(float(0.0));
+  sliceScale->setLengthWidth(200,10);
+  sliceScale->setIncrement(1.0);
+  sliceScale->setResolution(1.0);
+
+  /*  frameScale->setValue(float(0.0));
+  frameScale->setLengthWidth(200,10);
+  frameScale->setIncrement(1.0);
+  frameScale->setResolution(1.0);*/
+
+  masterFrame->addChildren("-side right -expand false -padx 5",but9);
+  masterFrame->addChildren("-side left -expand false -fill x",sliceScale->getMainWindow());
+  //,frameScale->getMainWindow());
+
+
+  return GetWidgetName();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineStackControl::SetItemColor(int index,double color[3])
+{
+  for (int j=0;j<SSP_MAX_RENDERERS;j++)
+    {
+      if (splineStackActor[j][index]!=NULL)
+	splineStackActor[j][index]->GetProperty()->SetColor(color);
+
+      this->SplineEditor->GetSplineControl()->SetItemColor(index,color);
+    }
+
+}
+
+// -----------------------------------------------------------------------------------------------
+void vtkpxGUIObjectmapSplineStackControl::SetItemFilename(int i,const char* s)
+{
+  //  fprintf(stderr,"Here SetFileName GUIObjectmapSPlineControl\n");
+
+  delete surface_filename[i];
+  surface_filename[i]=new char[strlen(s)+1];
+  strcpy(surface_filename[i],s);
+
+  if (this->Initialized==1)
+    {
+      strcpy(pxtk_buffer4,s);
+      sprintf(pxtk_buffer4,"%s.%d",PXTkApp::getFilenameTail(pxtk_buffer4),i+1);
+      currentCollection->changeLabel(i,pxtk_buffer4);
+    }
+  //  fprintf(stderr,"On to SPline Control\n");
+  //  fprintf(stderr,"Setting Filename of %d = %s\n",i,s);
+  this->SplineEditor->GetSplineControl()->SetItemFilename(i,s);
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineStackControl::Update()
+{
+  vtkpxGUISplineStackControl::Update();
+  UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineStackControl::UpdateDisplay()
+{
+  vtkpxGUISplineStackControl::UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+int  vtkpxGUIObjectmapSplineStackControl::HandleEvent(int event)
+{
+  if (!this->Initialized)
+      return TCL_OK;
+
+  if (event<10)
+      return this->EventManager->handleDirectEvent(event);
+
+  int updateeditor=0;  
+
+  if (event<800 && event!=700 && event!=701)
+    {
+      updateeditor=this->HandleEventSecond(event);
+    }
+
+
+
+
+  switch (event)
+    {
+    case 700:
+      if (this->SplineEditor->GetSplineControl()->GetAutoUpdateMode()==1)
+	this->UpdateFromSplineEditor();
+      this->UpdateSplineEditor();
+      this->UpdateMasterFrame();
+      break;
+
+    case 701:
+      //      fprintf(stderr,"\n Explicit Update from Editor\n");
+      this->UpdateFromSplineEditor();
+      this->UpdateMasterFrame();
+      break;
+
+    case 702:
+      {
+	int ok=this->EventManager->questionBox("Loading will delete ALL your surfaces. Are you sure?");
+	if (ok)
+	  {
+	    char* line=this->EventManager->getOpenFilename("Load splinestack set","SplineStack Sets","*.multisur");
+	    if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		  {
+		    char newline[400]; strcpy(newline,line);  LoadSet(newline);
+		  }
+		updateeditor=1;
+	      }
+	  }
+      }
+      break;
+      
+    case 703:
+      {
+	sprintf(pxtk_buffer,"%s",surface_setfilename);
+	//	fprintf(stderr,"Old filename = %s\n",surface_setfilename);
+	char* line=this->EventManager->getSaveFilename("Save Spline Stack Set",pxtk_buffer,"SplineStack Sets","*.multisur");
+	if (line!=NULL)
+	  {
+	    if (strlen(line)>0)
+	      {
+		strcpy(pxtk_buffer,line);
+		char* noext1=nothisextension(pxtk_buffer,".multisur");
+		char newname[400];
+		sprintf(newname,"%s.multisur",noext1);
+		//		delete [] noext1;
+		this->SaveSet(newname);
+	      }
+	  }
+      }
+      break;
+  
+    case 800:
+      SetCurrentCollection(currentCollection2->getIndex());
+      break;
+
+
+    case 804: // Update from slice/frame scales
+      this->UpdateFromMasterFrame(0);
+      break;
+
+    case 805: // Update from slice/frame scales
+      this->UpdateFromMasterFrame(1);
+      break;
+      
+    case 806: // Popup spline editor;
+      if (this->SplineEditor!=NULL)
+	this->SplineEditor->Show();
+      break;
+      
+
+    case 803:
+      do_autosave=autosavebutton->getState();
+      do_backup=backupbutton->getState();
+      break;
+
+    case 810:
+      this->DoShiftScale(0,850);
+      break;
+    case 811:
+      this->DoResample(0,852);
+      break;
+
+    case 813:
+      this->DoCylinders(0,856);
+      break;
+
+    case 815:
+      this->DoExport(0,860);
+      break;
+
+    case 816:
+      this->DoImport(0,864);
+      break;
+
+
+    case 860:
+      this->DoExport(1);
+      updateeditor=1;
+      break;
+
+    case 850:
+      this->DoShiftScale(1);
+      updateeditor=1;
+      break;
+    case 852:
+      this->DoResample(1);
+      updateeditor=1;
+      break;
+
+    case 856:
+      this->DoCylinders(1);
+      updateeditor=1;
+      break;
+
+    case 864:
+      this->DoImport(1,864);
+      updateeditor=1;
+      break;
+
+    }
+  
+  if (updateeditor==1 && this->BlockEditorCallback==0)
+    this->UpdateSplineEditor();
+
+
+  this->UpdateDisplay();
+
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineStackControl::SetImage(vtkImageData* img,int orient,int level,int frame)
+{
+  this->BlockEditorCallback=1;
+
+  this->orientation=vtkpxGUIBaseImageViewer::MapOrientationToOldStyle(orient);
+  if (img!=NULL)  
+    this->SetImage(img);
+  this->BlockEditorCallback=0;
+}
+
+
+void vtkpxGUIObjectmapSplineStackControl::SetCurrentCollection(int num)
+{
+  if (!this->Initialized)
+    return;
+  vtkpxGUISplineStackControl::SetCurrentCollection(num);
+  currentCollection2->setIndex(current_splinestack);
+  currentCollection->setIndex(current_splinestack);
+}
+
+void vtkpxGUIObjectmapSplineStackControl::SetImage(vtkImageData* img)
+{
+  if (img==NULL)
+    return;
+
+  if (this->image!=NULL)
+    this->image->Delete();
+  this->image=vtkImageData::New();
+  this->image->ShallowCopy(img);      
+  
+  if (this->SplineEditor!=NULL)
+    {
+      this->SplineEditor->SetImage(this->image,this->orientation);
+      this->SplineEditor->ShowFrameControls(0);
+      this->SplineEditor->SetSlice(-1);
+    }
+
+  /*  int nc=this->image->GetNumberOfScalarComponents();
+  if (nc==1)
+    {
+      frameScale->getMainWindow()->enable(PXFalse);
+    }
+  else
+    {
+      frameScale->getMainWindow()->enable(PXTrue);
+      frameScale->setRange(1,nc);
+      frameScale->setValue(1);
+      masterFrame->addChildren("-side left -expand false -fill x",frameScale->getMainWindow());
+      }*/
+
+  int numsl=this->image->GetDimensions()[2];
+  sliceScale->setRange(0,numsl-1);
+  sliceScale->setValue(this->SplineEditor->GetSliceNumber());
+
+  this->ResetSplineStacks();
+
+
+  /*  for (int ia=0;ia<=1;ia++)
+    {
+      sliceScale[ia]->setRange(0,this->image->GetDimensions()[2]-1);
+      sliceScale[ia]->setValue(ia*(this->image->GetDimensions()[2]-1));
+      }*/
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIObjectmapSplineStackControl::DoBackup(int stackindex,const char* rootname)
+{
+  stackindex=Irange(stackindex,0,this->NumberOfSplineStacks-1);
+  sprintf(pxtk_buffer,"%s.sur",rootname);
+  PXTkApp::fileOperation("exists",pxtk_buffer,NULL);
+  int ok=PXTkApp::getTclIntResult();
+  if (ok==1)
+    {
+      sprintf(pxtk_buffer,"%s.sur",rootname);
+      sprintf(pxtk_buffer2,"%s_back.sur",rootname);
+      sprintf(pxtk_buffer3,"File %s exists copying to %s\n",pxtk_buffer,pxtk_buffer2);
+      PXTkApp::printToConsole(pxtk_buffer3);
+      PXTkApp::copyFile(pxtk_buffer,pxtk_buffer2);
+    }
+
+  return 1;
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIObjectmapSplineStackControl::DoAutosave()
+{
+  for (int i=0;i<this->NumberOfSplineStacks;i++)
+    {
+      if ( surface_modified[i] == 1 ) 
+	{
+	  vtkpxSplineStackSource *stack=this->GetSplineStack(i);
+	  sprintf(pxtk_buffer,"%s_auto.sur",surface_filename[i]);
+	  stack->Save(pxtk_buffer);
+	  surface_modified[i]=0;
+	}
+    }
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineStackControl::UpdateFromMasterFrame(int mode)
+{
+  if (this->SplineEditor->GetSplineControl()->GetAutoUpdateMode()==1)
+    {
+      int  sl=this->SplineEditor->GetBeginSlice();
+      this->UpdateFromSplineEditor(sl);
+    }
+
+  this->SplineEditor->SetEnableSliceChangeCallback(0);
+  this->SplineEditor->SetSlice((int)this->sliceScale->getValue());
+  this->SplineEditor->SetEnableSliceChangeCallback(1);
+  this->UpdateSplineEditor();
+
+
+  if (this->BaseViewer!=NULL)
+    {
+      double lp[3]; this->BaseViewer->GetLastClickedPoint(lp);
+      lp[2]=sliceScale->getValue();
+      this->BaseViewer->SetCoordinates(int(lp[0]),int(lp[1]),int(lp[2]));
+    }
+
+}
+
+void vtkpxGUIObjectmapSplineStackControl::UpdateMasterFrame()
+{
+  sliceScale->setValue(this->SplineEditor->GetSliceNumber());
+
+  if (this->BaseViewer!=NULL)
+    {
+      double lp[3]; this->BaseViewer->GetLastClickedPoint(lp);
+      lp[2]=sliceScale->getValue();
+      this->BaseViewer->SetCoordinates(int(lp[0]),int(lp[1]),int(lp[2]));
+
+    }
+}
+
+void vtkpxGUIObjectmapSplineStackControl::UpdateSplineEditor(int sl)
+{
+  if (this->SplineEditor==NULL)
+    return;
+
+  if (sl==-1)
+    sl=this->SplineEditor->GetBeginSlice();
+  int num=this->GetNumberOfSplineStacks();
+
+
+  //  fprintf(stderr,"\tSTACK:: Sending Update To Spline Editor for current slice=%d BLOCK=%d\n",sl,this->BlockEditorCallback);
+
+  for (int i=0;i<num;i++)
+    {
+      vtkpxSplineStackSource* stack=this->GetSplineStack(i);
+      if (sl>=stack->GetTrimBottom() && sl<=stack->GetTrimTop())
+	{
+	  vtkpxSplineSource* spl=this->SplineEditor->GetSplineControl()->GetSpline(i);
+	  stack->SetSplineFromSplineStack(spl,sl);
+	  this->SplineEditor->EnableSpline(i);
+	  this->SplineEditor->GetSplineControl()->SetChangedStatus(i,0);
+	}
+      else
+	{
+	  this->SplineEditor->DisableSpline(i);
+	}
+    }
+  this->SplineEditor->GetSplineControl()->UpdateControlsFromCurrentSpline();
+  this->SplineEditor->GetSplineControl()->Update();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineStackControl::UpdateFromSplineEditor(int sl)
+{
+  if (sl==-1)
+    sl=(int)sliceScale->getValue();
+  int num=this->GetNumberOfSplineStacks();
+
+  //  fprintf(stderr,"\tSTACK:: Receiving Update From Spline Editor for previous slice=%d BLOCK=%d\n",sl,this->BlockEditorCallback);
+  for (int i=0;i<num;i++)
+    {
+      if (this->SplineEditor->GetSplineControl()->GetChangedStatus(i)==1)
+	{
+	  vtkpxSplineStackSource* stack=this->GetSplineStack(i);
+	  if (sl>=stack->GetTrimBottom() && sl<=stack->GetTrimTop())
+	    {
+	      vtkpxSplineSource*spl=this->SplineEditor->GetSplineControl()->GetSpline(i);
+	      stack->SetSpline(spl,sl);
+	      surface_modified[i]=1;
+
+	      if (i==this->SplineEditor->GetSplineControl()->GetCurrentIndex())
+		this->SplineEditor->GetSplineControl()->CopySpline();
+	    }
+	}
+    }
+  this->UpdateDisplay();
+  if (this->BaseViewer!=NULL)
+    this->BaseViewer->UpdateObjectmap();
+
+  if (this->do_autosave==PXTrue)
+    this->DoAutosave();
+
+  //  this->UpdateMasterFrame();
+
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineStackControl::DoShiftScale(int mode,int moption)
+{
+  if (mode==0)
+    {
+      if (this->optionDialog->isOpen())
+	return;
+
+      delete this->optionDialog;
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,6);
+      this->optionDialog->initDisplay();
+
+      this->optionDialog->setTitleDescription("Shift+Scale Surface",
+					      "Enter Multipliers to Shift and Scale the Surfaces");
+      this->optionDialog->setfoption(0,"Shift-X","%.1f",0.0);
+      this->optionDialog->setfoption(2,"Shift-Y","%.1f",0.0);
+      this->optionDialog->setfoption(4,"Shift-Z","%.1f",0.0);
+      this->optionDialog->setfoption(1,"Scale-X","%.2f",1.0);
+      this->optionDialog->setfoption(3,"Scale-Y","%.2f",1.0);
+      this->optionDialog->setfoption(5,"Scale-Z","%.2f",this->spacing[2]/this->currentSplineStack->GetZSpacing());
+      this->optionDialog->setMenuOption(moption);
+      this->optionDialog->popupDialog();
+    }
+
+  if (mode==1)
+    {
+      double sh[3],sc[3];
+      for (int ia=0;ia<=2;ia++)
+	{
+	  sh[ia]=Frange(this->optionDialog->getfoption(ia*2)  ,-100.0,100.0);
+	  sc[ia]=Frange(this->optionDialog->getfoption(ia*2+1),   0.1, 10.0);
+	}
+     
+      vtkpxSplineStackSource *stack=this->GetSplineStack(current_splinestack);
+      stack->ScaleShiftXY(sh[0],sh[1],sc[0],sc[1]);
+      stack->ScaleShiftZ(sh[2],sc[2]);
+      
+      this->UpdateAfterExternalEditing();
+    }
+      
+      
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineStackControl::DoResample(int mode,int moption)
+{
+  if (mode==0)
+    {
+      if (this->optionDialog->isOpen())
+	return;
+
+      delete this->optionDialog;
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,2);
+      this->optionDialog->initDisplay();
+      
+      this->optionDialog->setTitleDescription("Resample Surfaces",
+					      "Enter npoints=-1 for auto-spacing");
+      this->optionDialog->setioption(0,"Points","%d",-1);
+      this->optionDialog->setfoption(1,"Smoothness","%.1f",2.0);
+      this->optionDialog->setMenuOption(moption);
+      this->optionDialog->popupDialog();
+      return;
+    }
+
+  if (mode==1)
+    {
+      int np=Irange(this->optionDialog->getioption(0),3,50);
+      if (np==3)
+	np=-1;
+      float ds=Frange(this->optionDialog->getfoption(1),1.0,20.0);
+      
+      vtkpxSplineStackSource *stack=this->GetSplineStack(current_splinestack);
+      stack->ChangeSpacing(ds,np,0.01);
+     
+      this->UpdateAfterExternalEditing();
+    }
+
+      
+
+}
+
+
+void vtkpxGUIObjectmapSplineStackControl::DoCylinders(int mode,int moption)
+{
+  if (mode==0)
+    {
+      if (this->optionDialog->isOpen())
+	return;
+
+      delete this->optionDialog;
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,7);
+      this->optionDialog->initDisplay();
+
+      this->optionDialog->setTitleDescription("Set Cylinders",
+					      "Enter Cylinder Parameters");
+      this->optionDialog->setfoption(0,"Center X","%.2f",this->origin[0]+this->dimensions[0]*this->spacing[0]*0.5);
+      this->optionDialog->setfoption(2,"Center Y","%.2f",this->origin[1]+this->dimensions[1]*this->spacing[1]*0.5);
+      this->optionDialog->setfoption(1,"Radius X","%.2f",this->dimensions[0]*this->spacing[0]*0.2);
+      this->optionDialog->setfoption(3,"Radius Y","%.2f",this->dimensions[1]*this->spacing[1]*0.2);
+      this->optionDialog->setioption(4,"Bot Slice","%d",0);
+      this->optionDialog->setioption(5,"Top Slice","%d",this->dimensions[2]-1);
+      this->optionDialog->setioption(6,"Num points","%d",8);
+      this->optionDialog->setMenuOption(moption);
+      this->optionDialog->popupDialog();
+      return;
+    }
+
+
+  if (mode==1)
+    {
+      float c[2],r[2];
+      for (int ia=0;ia<=1;ia++)
+	{
+	  c[ia]=Frange(this->optionDialog->getfoption(ia*2),
+		       this->origin[ia],this->origin[ia]+this->dimensions[ia]*this->spacing[ia]);
+	  r[ia]=Frange(this->optionDialog->getfoption(ia*2+1),
+		       this->spacing[ia],0.5*+this->dimensions[ia]*this->spacing[ia]);
+	}
+      
+      
+      int numsl=this->dimensions[2];
+      float bottomz=this->origin[2];
+      float zsp=this->spacing[2];
+      int nump=Irange(this->optionDialog->getioption(6),4,24);
+      int minz=Irange(this->optionDialog->getioption(4),0,this->dimensions[2]-2);
+      int maxz=Irange(this->optionDialog->getioption(5),minz,this->dimensions[2]-2);
+      
+      vtkpxSplineStackSource *stack=this->GetSplineStack(current_splinestack);
+      stack->SetEllipticalCylinder(nump,numsl,r[0],r[1],c[0],c[1],zsp,bottomz);
+      stack->SetTrimBottom(minz);
+      stack->SetTrimTop(maxz);
+      this->UpdateAfterExternalEditing();
+    }
+
+}
+// ---------------------------------------------------------------------------
+void vtkpxGUIObjectmapSplineStackControl::ComputeVOIProperties(int frame)
+{
+  vtkpxGUISplineStackControl::ComputeVOIProperties(frame);
+}
+
+void vtkpxGUIObjectmapSplineStackControl::SetSplineEditor(vtkpxGUI2DSplineObjectmapViewer* splineControl)
+{
+  this->SplineEditor=splineControl;
+  if (this->SplineEditor!=NULL)
+    {
+      this->SplineEditor->SetNumberOfSplines(this->NumberOfSplineStacks);
+      this->SplineEditor->SetCallback(this,700);
+    }
+}
+// ---------------------------------------------------------------------------
+
+int vtkpxGUIObjectmapSplineStackControl::LoadSet(const char* fname)
+{
+  int status=0;
+  gzFile fin;
+
+  fin=gzsuffixopen(fname,"r");
+  char line[300];
+  if (fin!=NULL)
+    {
+      gzgets(fin,line,100);
+      if (gzfindstringinstring(line, "#BFPSplineStack Set File")==1)
+	status=1;
+    }
+  
+  if (status==0)
+    {
+      if (fin!=NULL)
+	gzclose(fin);
+      sprintf(pxtk_buffer2,"Failed to load SplineStack Set from %s",fname);
+      this->EventManager->messageBox(pxtk_buffer2,"Load Set Failure");
+      return 0;
+    }
+     
+  gzgets(fin,line,100); int nt; sscanf(line,"%d",&nt);
+
+  int ntorig=nt;
+  if (nt>this->NumberOfSplineStacks)
+    nt=this->NumberOfSplineStacks;
+
+  int old_col=current_splinestack;
+  
+  for (int i=0;i<nt;i++)
+    {
+      gzgets(fin,line,100); 
+      //      fprintf(stderr,"line=%s\n",line);
+      gzgets(fin,pxtk_buffer2,200); 
+      sscanf(pxtk_buffer2,"%s\n",&line[0]); // filename
+      this->SetCurrentCollection(i);
+      this->LoadSplineStack(line);
+
+      gzgets(fin,line,100); 
+      double c[3];  sscanf(line,"%lf %lf %lf",&c[0],&c[1],&c[2]);
+      this->SetItemColor(i,c);
+    }
+  gzclose(fin);
+
+  delete [] surface_setfilename;
+  surface_setfilename=new char[strlen(fname+1)];
+  strcpy(surface_setfilename,fname);
+  
+  sprintf(pxtk_buffer2,"Loaded %d surfaces from\n %s\n (total surfaces in file=%d)\n",nt,fname,ntorig);
+  this->EventManager->messageBox(pxtk_buffer2,"Load Set Information");
+  this->SetCurrentCollection(old_col);
+  UpdateControlsFromCurrentSplineStack();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIObjectmapSplineStackControl::SaveSet(const char* fname)
+{
+  int status=0;
+  FILE* fout=fopen(fname,"w");
+  if (fout==NULL)
+    {
+      sprintf(pxtk_buffer2,"Failed to Save SplineStack Set in %s",fname);
+      this->EventManager->messageBox(pxtk_buffer2,"Save Set Failure");
+      return 0;
+    }
+
+  char line[300];
+  int nt=this->NumberOfSplineStacks;
+  int old_col=current_splinestack;
+
+  for (int i=0;i<nt;i++)
+    {
+      sprintf(line,"unnamed_%d",i+1);
+      int n=9+(i>=9);
+      if (strncmp(surface_filename[i],line,n)==0)
+	sprintf(line,"%s_%d.sur",fname,i+1);
+      else
+	strcpy(line,surface_filename[i]);
+      
+      this->SetCurrentCollection(i);
+      this->SaveSplineStack(line);
+    }
+  
+  fprintf(fout,"#BFPSplineStack Set File\n%d\n",this->NumberOfSplineStacks);
+  for (int i=0;i<nt;i++)
+    {
+      fprintf(fout,"# ----------------- Spline Stack %d ---------------------\n",i+1);
+      fprintf(fout,"%s\n",surface_filename[i]);
+      double c[3]; vtkpxSurfaceUtil::GetColor(i,c);
+	if (splineStackActor[0][current_splinestack]!=NULL)
+	  {
+	    if ( splineStackActor[0][i]!=NULL)
+	      splineStackActor[0][i]->GetProperty()->GetColor(c);
+	  }
+	fprintf(fout,"%.3f %.3f %.3f\n",c[0],c[1],c[2]);
+    }
+  fclose(fout);
+
+
+  delete [] surface_setfilename;
+  surface_setfilename=new char[strlen(fname+1)];
+  strcpy(surface_setfilename,fname);
+
+  sprintf(pxtk_buffer2,"Saved %d surfaces to\n %s \n",nt,fname);
+  this->EventManager->messageBox(pxtk_buffer2,"Save Set Information");
+  this->SetCurrentCollection(old_col);
+  UpdateControlsFromCurrentSplineStack();
+  return 1;
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIObjectmapSplineStackControl::DoExport(int mode,int moption)
+{
+  if (mode==0)
+    {
+      if (this->optionDialog->isOpen())
+	return;
+
+      delete this->optionDialog;
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,4);
+      this->optionDialog->initDisplay();
+      this->optionDialog->setTitleDescription("Export Surfaces",
+					      "Format 1=.tstack 2=.vtk");
+      
+      if (this->orientation!=3)
+	{
+	  this->optionDialog->setfoption(0,"Spacing XY","%.1f",this->spacing[0]);
+	  this->optionDialog->setfoption(1,"Spacing  Z","%.1f",this->spacing[0]);
+	}
+      else
+	{
+	  this->optionDialog->setfoption(0,"Spacing XY","%.1f",this->spacing[0]*3.0);
+	  this->optionDialog->setfoption(1,"Spacing  Z","%.1f",this->spacing[0]*3.0);
+	}
+
+      this->optionDialog->setioption(2,"Format","%d",2);
+      this->optionDialog->setioption(3,"Smoothing Iterations","%d",20);
+      this->optionDialog->setMenuOption(moption);
+    } 
+
+  if (mode==0)
+    this->optionDialog->popupDialog();
+
+  if (mode!=1)
+    return;
+
+  float uspacing=Frange(this->optionDialog->getfoption(0),0.2*this->spacing[0],this->spacing[0]*10);
+  float vspacing=Frange(this->optionDialog->getfoption(1),0.2*this->spacing[2],this->spacing[2]*10);
+  int format=Irange(this->optionDialog->getioption(2),1,2);
+  int iterations=Irange(this->optionDialog->getioption(2),0,100);
+    
+  char extension[10];
+  char* line=NULL;
+  if (format==1)
+    {
+      sprintf(pxtk_buffer,"%s.tstack",surface_filename[current_splinestack]);
+      line=this->EventManager->getSaveFilename("Save as tstack",pxtk_buffer,"Tstack Surface",".tstack");
+      strcpy(extension,".tstack");
+    }
+  else
+    {
+      sprintf(pxtk_buffer,"%s.vtk",surface_filename[current_splinestack]);
+      line=this->EventManager->getSaveFilename("Save  as vtk surfaces",pxtk_buffer,"VTK Surface","*.vtk");
+      strcpy(extension,".vtk");
+    }
+  
+  if (line==NULL)
+    return;
+  
+  char* noext2=nothisextension(line,extension);
+
+  vtkpxTriangulatedStackSource* tstack=vtkpxTriangulatedStackSource::New();
+  vtkPolyDataWriter* poly=vtkPolyDataWriter::New();
+  
+  PXTkApp::popupConsole();
+  sprintf(pxtk_buffer3,"%s%s",noext2,extension);
+  vtkpxSplineStackSource *stack=this->currentSplineStack;
+  tstack->SetFromSplineStackSource2(stack,uspacing,vspacing,-10000.0,10000.0);
+  tstack->NonShrinkSmooth(0.33,-0.34,iterations);
+  
+  if (format==1)
+    {
+      int ok=tstack->Save(pxtk_buffer3);
+      sprintf(pxtk_buffer,"Saving to %s (status=%d)\n",pxtk_buffer3,ok);
+    }
+  else
+    {
+      tstack->Update();
+      poly->SetInput(tstack->GetOutput());
+      poly->SetFileName(pxtk_buffer3);
+      poly->Update();
+      sprintf(pxtk_buffer,"Saving to %s\n",pxtk_buffer3);
+    }
+  PXTkApp::printToConsole(pxtk_buffer);
+  poly->Delete();
+  tstack->Delete();
+}
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObjectmapSplineStackControl.h b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapSplineStackControl.h
new file mode 100644
index 0000000..3df4959
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObjectmapSplineStackControl.h
@@ -0,0 +1,192 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIObjectmapSplineStackControl.h,v $
+  Language:  C++
+  Date:      $Date: 2002/04/09 15:46:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIObjectmapSplineStackControl - Base Image Viewer
+// .SECTION Description
+
+#ifndef __vtkpxGUIObjectmapSplineStackControl_h
+#define __vtkpxGUIObjectmapSplineStackControl_h
+
+#include "vtkpxGUISplineStackControl.h"
+#include "pxtkseldialog.h"
+#include "pxtkwaitdialog.h"
+#include "vtkpxGUI2DSplineObjectmapViewer.h"
+#include "vtkpxGUIObjectmapOrthogonalViewer.h"
+class vtkImageData;
+
+
+class vtkpxGUIObjectmapSplineStackControl : public vtkpxGUISplineStackControl 
+{
+public:
+
+  static vtkpxGUIObjectmapSplineStackControl *New();
+  vtkTypeMacro(vtkpxGUIObjectmapSplineStackControl,vtkpxGUISplineStackControl);
+  
+  // Description:
+  // Initialize Display and add Renderer 
+  virtual char*  Initialize(const char* name,int inside);
+  virtual char*  Initialize(const char* name,const char* name2,const char* name3,int inside);
+
+
+  // Description:
+  // Update Display
+  virtual void   Update();
+  virtual void   UpdateDisplay();
+
+
+  // Description:
+  // Set Image Level,Plane And Frame 
+  virtual void SetImage(vtkImageData* image,int orientation,int level=0,int frame=0);
+  virtual void SetImage(vtkImageData* image);
+
+  // Description:
+  // Event Manager 
+  virtual int    HandleEvent(int);
+
+  // Description:
+  // Communication with SplineEditor
+  // Add Frame Checking
+  virtual void UpdateSplineEditor(int slice=-1);
+  virtual void UpdateFromSplineEditor(int slice=-1);
+
+  // Description:
+  // Communitcation with Masterframe (slice/frame)
+  virtual void UpdateMasterFrame();
+  virtual void UpdateFromMasterFrame(int mode);
+  
+  // Description:
+  // Set Spline Control to facilitate proper updating
+  virtual void SetSplineEditor(vtkpxGUI2DSplineObjectmapViewer* splineeditor);
+  virtual void SetItemColor(int index,double color[3]);
+  virtual void SetItemFilename(int index,const char* s);
+
+  // Description:
+  // Set Current Spline Stack
+  virtual void SetCurrentCollection(int num);
+
+  // Description:
+  // Base Viewer for communication
+  vtkSetObjectMacro(BaseViewer,vtkpxGUIObjectmapOrthogonalViewer);
+  vtkGetObjectMacro(BaseViewer,vtkpxGUIObjectmapOrthogonalViewer);
+
+protected:
+
+  vtkpxGUIObjectmapSplineStackControl();
+  virtual ~vtkpxGUIObjectmapSplineStackControl();
+
+  // Description:
+  // Collection Stuff
+  vtkpxGUIObjectmapOrthogonalViewer*  BaseViewer;
+  int                  wireframemode[SSP_MAX_RENDERERS];
+
+  // Description:
+  // Frame Scale Widget
+  PXTkOptionMenu       *currentCollection2;
+  PXTkCheckButton*     autosavebutton;
+  PXTkCheckButton*     backupbutton;
+  PXBool               do_autosave;
+  PXBool               do_backup;
+  
+  // Description:
+  // Widgets for various GUIS
+  // 1. Multi-resample
+  // 2. Multi-shift+scale
+  PXTkSelDialog*  optionDialog;
+
+  // Description:
+  // Initialize SplineStacks
+  virtual void InitializeSplineStacks();
+  virtual void ResetSplineStacks();
+
+  // Description:
+  // Implement Autosave
+  virtual int DoAutosave();
+  virtual int DoBackup(int stackindex,const char* rootname);
+
+
+  // Description:
+  // Handle Callbacks for GUI Stuff
+  virtual void DoShiftScale(int mode,int moption=-1);
+  virtual void DoResample(int mode,int moption=-1);
+  virtual void DoExport(int mode,int moption=-1);
+  virtual void DoCylinders(int mode,int moption=-1);
+
+
+  // Description:
+  // Handle VOI Props
+  virtual void ComputeVOIProperties(int frame);
+
+  // Description:
+  // Load/Save Surface Sets
+  virtual int LoadSet(const char* fname);
+  virtual int SaveSet(const char* fname);
+
+
+  // Description:
+  vtkpxGUI2DSplineObjectmapViewer* SplineEditor;
+  PXTkArrowScale            *sliceScale;
+  //  PXTkArrowScale            *frameScale;
+  PXTkFrame*                 masterFrame;
+
+  char*       surface_setfilename;
+
+
+};
+
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObliqueImageSliceControl.cpp b/bioimagesuite30_src/GUI/vtkpxGUIObliqueImageSliceControl.cpp
new file mode 100644
index 0000000..b2338db
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObliqueImageSliceControl.cpp
@@ -0,0 +1,624 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIObliqueImageSliceControl.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/05/08 16:04:58 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxGUIObliqueImageSliceControl.h"
+#include "vtkObjectFactory.h"
+#include "vtkCamera.h"
+#include "vtkPlaneSource.h"
+#include "vtkpxAnalyzeImageWriter.h"
+#include "vtkpxTransformationUtil.h"
+
+
+vtkpxGUIObliqueImageSliceControl* vtkpxGUIObliqueImageSliceControl::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIObliqueImageSliceControl");
+  if(ret)
+      {
+	return (vtkpxGUIObliqueImageSliceControl*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIObliqueImageSliceControl;
+}
+
+// Construct object with no children.
+vtkpxGUIObliqueImageSliceControl::vtkpxGUIObliqueImageSliceControl()
+{
+  has_obliqueslice=PXFalse;
+  this->ObliqueImageSlice=NULL;
+  this->Viewer=NULL;
+  this->internal_viewer=NULL;
+  this->show_obliqueslice=NULL;
+  this->Visibility=PXFalse;
+  this->NormalVisibility=PXFalse;
+  this->Initialized=0;
+  this->FollowCamera=PXFalse;
+}
+// ------------------------------------------------------------------------------------
+void vtkpxGUIObliqueImageSliceControl::SetObliqueImageSliceRenderer(vtkpxObliqueImageSlice* vol,vtkpxGUIBaseRenderer* view)
+{
+  if (vol!=NULL)
+    {
+      this->ObliqueImageSlice=vol;
+      this->Viewer=view;
+      has_obliqueslice=PXTrue;
+      this->SetResolution(resliceMode->getIndex());
+      //      fprintf(stderr,"Setting Oblique Image Slice Renderer\n");
+      this->Update(1);
+    }
+}
+// ------------------------------------------------------------------------------------
+void  vtkpxGUIObliqueImageSliceControl::UpdateObliqueImageSliceRenderer(vtkpxObliqueImageSlice* vol,vtkpxGUIBaseRenderer* ren)
+{
+  if (vol==NULL || ren==NULL)
+    return;
+
+  if (has_obliqueslice==PXFalse)
+    {
+      //      fprintf(stderr,"Calling Set Oblique Image Slice Renderer\n");
+      this->SetObliqueImageSliceRenderer(vol,ren);
+      return;
+    }
+
+  float d1[6]; this->ObliqueImageSlice->GetImageRange(d1);
+  float d2[6]; vol->GetImageRange(d2);
+
+  float d=0;
+  for (int ia=1;ia<=5;ia+=2)
+    d+=fabs(d1[ia]-d2[ia]);
+
+  if (d>0)
+    distanceScale->setRange(-d,d);
+
+  this->ObliqueImageSlice=vol;
+  this->Viewer=ren;
+  this->SetResolution(resliceMode->getIndex());
+  //this->Update(0);
+}
+// ------------------------------------------------------------------------------------
+void vtkpxGUIObliqueImageSliceControl::SetRenderer(vtkpxGUIBaseRenderer* viewer1)
+{
+  this->Viewer=viewer1;
+}
+// ------------------------------------------------------------------------------------
+char*  vtkpxGUIObliqueImageSliceControl::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+    return GetWidgetName();
+  
+  vtkpxGUIComponent::Initialize(name,inside);
+
+  PXTkFrame* parentFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+  viewerFrame=new PXTkFrame(this->EventManager,parentFrame);
+  volFrame=new PXTkFrame(this->EventManager,parentFrame);
+
+  parentFrame->setPackMode(PXTrue);
+  parentFrame->addChildren("-side top -expand false -fill both",volFrame,viewerFrame);
+  
+  show_obliqueslice=new PXTkCheckButton(this->EventManager,volFrame,"Show",104);
+  show_obliqueslice->setState(this->Visibility);
+
+  show_normal=new PXTkCheckButton(this->EventManager,volFrame,"Normal",104);
+  show_normal->setState(this->NormalVisibility);
+
+  follow_camera=new PXTkCheckButton(this->EventManager,volFrame,"Follow Cam",105);
+  follow_camera->setState(PXFalse);
+  volFrame->addChildren("-side left -expand f -fill x",show_obliqueslice,show_normal,follow_camera);
+
+  PXTkLabel* l1=new PXTkLabel(this->EventManager,volFrame,"Res:"); 
+  resliceMode=new PXTkOptionMenu(this->EventManager,volFrame,"64x64",103);
+  resliceMode->addOption("128x128");
+  resliceMode->addOption("256x256");
+  resliceMode->addOption("512x512");
+  resliceMode->setIndex(2);
+  
+  volFrame->addChildren("-side left -expand f -fill x",l1,resliceMode);
+
+
+
+  PXTkFrame* vFrame=new PXTkFrame(this->EventManager,parentFrame);
+  PXTkFrame* vFrame2=new PXTkFrame(this->EventManager,parentFrame);
+  parentFrame->addChildren("-side top -expand false -fill x",vFrame,vFrame2);
+
+  distanceScale=new PXTkArrowScale(this->EventManager,vFrame2,"Distance",107,PXTrue);
+  distanceScale->setRange(-400,400);
+  distanceScale->setResolution(0.1);
+  distanceScale->setIncrement(0.5);
+  distanceScale->setDecimalPoints(1);
+  distanceScale->setLengthWidth(160,10);
+  vFrame2->addChildren("-side left -expand t -fill x",distanceScale->getMainWindow());
+	
+  opacityScale=new PXTkScale(this->EventManager,vFrame2,"Opacity",106);
+  opacityScale->setResolution(0.05);
+  opacityScale->setRange(0.5,1);
+  opacityScale->setDigits(3);
+  opacityScale->setLengthWidth(80,10);
+  vFrame2->addChildren("-side right -expand f -fill x",opacityScale);
+	
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (ia==0)
+	strcpy(pxtk_buffer4,"x-");
+      else if (ia==1)
+	strcpy(pxtk_buffer4,"y-");
+      else
+	strcpy(pxtk_buffer4,"z-");
+      
+      sprintf(pxtk_buffer4,"%s-norm",pxtk_buffer4);
+      clipScale[ia]=new PXTkScale(this->EventManager,vFrame,pxtk_buffer4,107);
+      clipScale[ia]->setRange(-1.0,1.0);
+      clipScale[ia]->setDigits(3);
+      clipScale[ia]->setResolution(0.01);
+      clipScale[ia]->setLengthWidth(80,10);
+      vFrame->addChildren("-side left -expand t -fill x",clipScale[ia]);
+    }
+
+  
+  PXTkFrame* bFrame=new PXTkFrame(this->EventManager,parentFrame);
+  PXTkFrame* bFrame2=new PXTkFrame(this->EventManager,parentFrame);
+  parentFrame->addChildren("-side bottom -expand false -fill x",bFrame2,bFrame);
+
+  if (!this->EventManager->isInside())
+    {
+      PXTkButton* b5=new PXTkButton(this->EventManager,bFrame2,"Close",3); 
+      bFrame2->addChildren("-side right -expand f -fill x -padx 5",b5);
+    }
+
+  PXTkLabel* lab=new PXTkLabel(this->EventManager,bFrame,"");
+  lab->configure("-image","$::pxtclvtkpxcontrib::smalllogo ");
+  bFrame->addChildren("-side right -expand f",lab);
+
+  PXTkButton* b4=new PXTkButton(this->EventManager,bFrame,"Reset",139); 
+  PXTkButton* b5=new PXTkButton(this->EventManager,bFrame,"Look to Camera",138); 
+  PXTkButton* b6=new PXTkButton(this->EventManager,bFrame,"Edge Camera",137); 
+  bFrame->addChildren("-side left -expand t -fill x -padx 2",b4,b5,b6);
+
+
+  PXTkButton* b7=new PXTkButton(this->EventManager,bFrame2,"Load Plane",141); 
+  PXTkButton* b8=new PXTkButton(this->EventManager,bFrame2,"Save Plane",142); 
+  PXTkButton* b9=new PXTkButton(this->EventManager,bFrame2,"Save Image",143); 
+  PXTkButton* b10=new PXTkButton(this->EventManager,bFrame2,"Save Xform",144); 
+  bFrame2->addChildren("-side left -expand t -fill x -padx 5",b7,b8,b9,b10);
+  
+  this->Initialized=1;
+
+  return GetWidgetName();
+}
+ // ------------------------------------------------------------------------------------
+void vtkpxGUIObliqueImageSliceControl::Update(int full)
+{
+  if (!this->Initialized || !has_obliqueslice)
+      return;
+
+  //  fprintf(stderr,"\n\n ********** Updating Oblique full=%d\n",full);
+
+  if (this->Visibility)	
+    this->ObliqueImageSlice->SetVisibility(1);
+  else
+    this->ObliqueImageSlice->SetVisibility(0);
+
+  if (this->NormalVisibility)
+    this->ObliqueImageSlice->SetShowNormalArrow(1);
+  else
+    this->ObliqueImageSlice->SetShowNormalArrow(0);
+
+
+  if (full==0)
+    {
+      this->ObliqueImageSlice->SetOpacity(opacityScale->getValue());
+      this->UpdateObliqueSlicePositionAndOrientation();
+      Viewer->Render();
+    }
+  else if (full ==1)
+    {
+      float range[6]; 
+      this->ObliqueImageSlice->GetImageRange(range);
+      float d=sqrt(pow(range[0]-range[1],float(2.0))+
+		   pow(range[2]-range[3],float(2.0))+
+		   pow(range[4]-range[5],float(2.0)));
+      
+      //      fprintf(stderr,"Full =%d calling Update Scales from setting distance scale\n",full);
+      distanceScale->setRange(-d,d);
+      UpdateScales();
+    }
+
+}
+// ------------------------------------------------------------------------------------
+void vtkpxGUIObliqueImageSliceControl::UpdateDisplay()
+{
+  if (!this->Initialized || !has_obliqueslice)
+      return;
+
+  if (!this->Visibility)
+      return;
+  
+  this->UpdateObliqueSlicePositionAndOrientation();
+}
+// ------------------------------------------------------------------------------------
+int vtkpxGUIObliqueImageSliceControl::UpdateObliqueSlicePositionAndOrientation()
+{
+  if (!this->Initialized || !has_obliqueslice)
+      return 0;
+
+  //  fprintf(stderr,"\nUpdating Slice Position and Orientation");
+  float norm[3],sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+    {
+      norm[ia]=(clipScale[ia]->getValue());
+      sum+=norm[ia]*norm[ia];
+    }
+  sum=sqrt(sum);
+  for (int ia=0;ia<=2;ia++)
+    norm[ia]/=sum;
+
+  float dist=distanceScale->getValue();
+
+
+  //  fprintf(stderr,"Setting Norm %.2f %.2f %.2f\n",norm[0],norm[1],norm[2]);
+  this->ObliqueImageSlice->UpdateImagePlane(dist,norm[0],norm[1],norm[2]);
+
+  //  fprintf(stderr,"Calling Update Scales from UpdateObliqueSlice \t");
+  this->UpdateScales();
+
+
+  return 1;
+}
+// ------------------------------------------------------------------------------------
+void vtkpxGUIObliqueImageSliceControl::SetVisibility(int vis)
+{
+  vis=(vis>0);
+  if (vis)
+    this->Visibility=PXTrue;
+  else
+    this->Visibility=PXFalse;
+
+  if (this->show_obliqueslice!=NULL)
+    show_obliqueslice->setState(this->Visibility);
+  
+  if (this->ObliqueImageSlice!=NULL)
+    {
+      if (this->Visibility)
+	this->ObliqueImageSlice->SetVisibility(1);
+      else
+	this->ObliqueImageSlice->SetVisibility(0);
+    }
+}
+// ------------------------------------------------------------------------------------
+int  vtkpxGUIObliqueImageSliceControl::HandleEvent(int event)
+{
+  if (event<=10)
+      return this->EventManager->handleDirectEvent(event);
+
+  if (!has_obliqueslice)    // Nothing to do 
+      return TCL_OK;
+
+  switch (event)
+      {
+      case 102:
+	UpdateDisplay();
+	break;
+	
+      case 103:
+	this->SetResolution(resliceMode->getIndex());
+	Viewer->Render();
+	break;
+
+
+      case 104:
+	this->Visibility=show_obliqueslice->getState();
+	this->NormalVisibility=show_normal->getState();
+
+	if (this->Visibility)
+	  this->ObliqueImageSlice->SetVisibility(1);
+	else
+	  this->ObliqueImageSlice->SetVisibility(0);
+
+	if (this->NormalVisibility)
+	  this->ObliqueImageSlice->SetShowNormalArrow(1);
+	else
+	  this->ObliqueImageSlice->SetShowNormalArrow(0);
+	break;
+	
+
+      case 105:
+	this->FollowCamera=follow_camera->getState();
+	if (this->FollowCamera)
+	  {
+	    this->UpdateFromCamera();
+	    Viewer->Render();
+	  }
+	break;
+	
+
+      case 106:
+	if (has_obliqueslice)
+	  {
+	    float v=(opacityScale->getValue());
+	    this->ObliqueImageSlice->SetOpacity(v);
+	    Viewer->Render();
+	  }
+	break;
+
+      case 107:
+	UpdateObliqueSlicePositionAndOrientation();
+	break;
+
+      case 139:
+	if (has_obliqueslice)
+	  {
+	    this->ObliqueImageSlice->Reset();
+	    //	    fprintf(stderr,"Event =139 calling Update Scales\n");
+	    this->UpdateScales();
+	    Viewer->Render();
+	  }
+	break;
+
+      case 138:
+	this->UpdateFromCamera(1,0);
+	break;
+
+      case 137:
+	this->UpdateFromCamera(1,1);
+	break;
+
+      case 140:
+	this->UpdateFromCamera(0,0);
+	break;
+
+      case 141:
+	this->Load();
+	break;
+
+      case 142:
+	this->Save();
+	break;
+
+      case 143:
+	this->SaveCurrentImage();
+	break;
+
+      case 144:
+	this->SaveCurrentTransform();
+	break;
+	
+      }
+
+  Viewer->Render();
+  return TCL_OK;
+}
+// ------------------------------------------------------------------------------------
+vtkpxGUIBaseRenderer* vtkpxGUIObliqueImageSliceControl::GetViewer()
+{
+  return this->Viewer;
+}
+
+// ------------------------------------------------------------------------------------
+void vtkpxGUIObliqueImageSliceControl::UpdateFromCamera(int force,int mode)
+{
+  if (this->Viewer==NULL || ( this->FollowCamera==PXFalse && force==0) || has_obliqueslice==PXFalse)
+    return;
+
+  vtkCamera* cam=this->Viewer->GetRenderer()->GetActiveCamera();
+  this->ObliqueImageSlice->UpdateImagePlane(cam,mode);
+  //  fprintf(stderr,"Calling UpdateScales from Update from Camera\n");
+  this->UpdateScales();
+}
+
+
+void vtkpxGUIObliqueImageSliceControl::UpdateScales()
+{
+  if (this->Initialized==0 ||  has_obliqueslice==PXFalse)
+    return;
+
+  //  fprintf(stderr,"Updating Scales\n");
+  vtkPlaneSource* plane=this->ObliqueImageSlice->GetImagePlane();
+  if (plane==NULL)
+    return;
+
+  float  d=this->ObliqueImageSlice->GetDistance();
+  double n[3]; this->ObliqueImageSlice->GetNormal(n);
+  //  fprintf(stderr,"\t\t Getting Norm from plane %.2f %.2f %.2f\n",n[0],n[1],n[2]);
+
+  for (int i=0;i<=2;i++)
+    clipScale[i]->setValue(n[i]);
+  distanceScale->setValue(d);
+
+}
+
+void vtkpxGUIObliqueImageSliceControl::SetResolution(int mode)
+{
+  int r=64;
+  switch (mode)
+    {
+    case 1:
+      r=128;
+      break;
+    case 2:
+      r=256;
+      break;
+    case 3:
+      r=512;
+      break;
+    }
+  
+
+  this->ObliqueImageSlice->SetResolution(r);
+}
+
+int vtkpxGUIObliqueImageSliceControl::Load()
+{
+  if (this->Initialized==0 ||  has_obliqueslice==PXFalse)
+    return 0;
+
+  char* line=this->EventManager->getOpenFilename("Load Oblique Slice Position","Oblique Slice","*.obl");
+  if (line!=NULL)
+    {
+      if (strlen(line)>0)
+	{
+	  gzFile fin=gzsuffixopen(line,"rb");
+	  if (fin)
+	    {
+	      gzgets(fin,pxtk_buffer,100);
+	      if (gzfindstringinstring(pxtk_buffer,"#Oblique Slice Position")==0)
+		{
+		  gzclose(fin);
+		  return 0;
+		}
+
+
+	      float  d,n[3]; 
+	      gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100);
+	      sscanf(pxtk_buffer,"%f %f %f",&n[0],&n[1],&n[2]);
+	      gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100);
+	      sscanf(pxtk_buffer,"%f",&d);
+	      gzclose(fin);	      
+	      
+	      this->ObliqueImageSlice->UpdateImagePlane(d,n[0],n[1],n[2]);
+	      //	      fprintf(stderr,"Loaded calling Update Scales\n");
+	      this->UpdateScales();
+
+	      return 1;
+	    }
+	}
+
+    }
+  return 0;
+}
+// ----------------------------------------------------------------------------------------
+int vtkpxGUIObliqueImageSliceControl::Save()
+{
+  if (this->Initialized==0 ||  has_obliqueslice==PXFalse)
+    return 0;
+
+  vtkPlaneSource* plane=this->ObliqueImageSlice->GetImagePlane();
+  if (plane==NULL)
+    return 0;
+
+  char* line=this->EventManager->getSaveFilename("Save Oblique Slice Position","position.obl","Oblique Slice","*.obl");
+  if (line!=NULL)
+    {
+      if (strlen(line)>0)
+	{
+	  FILE* fout=fopen(line,"w");
+	  if (fout)
+	    {
+	      fprintf(fout,"#Oblique Slice Position\n");
+	      
+	      float  d=this->ObliqueImageSlice->GetDistance();
+	      double n[3]; this->ObliqueImageSlice->GetNormal(n);
+	      double c[3]; this->ObliqueImageSlice->GetCenter(c);
+	      fprintf(fout,"#Normal\n %.4f %.4f %.4f\n#Distance\n%.3f\n",
+		      n[0],n[1],n[2],d);
+	      fprintf(fout,"#Center\n %.4f %.4f %.4f\n",c[0],c[1],c[2]);
+	      fclose(fout);
+	      return 1;
+	    }
+	}
+    }
+  return 0;
+}
+// ----------------------------------------------------------------------------------------
+int vtkpxGUIObliqueImageSliceControl::SaveCurrentImage()
+{
+ if (this->Initialized==0 ||  has_obliqueslice==PXFalse)
+    return 0;
+
+  vtkPlaneSource* plane=this->ObliqueImageSlice->GetImagePlane();
+  if (plane==NULL)
+    return 0;
+  
+  vtkImageData* image=this->ObliqueImageSlice->GetObliqueImage();
+  if (image==NULL)
+    return 0;
+
+  char* line=this->EventManager->getSaveFilename("Save Oblique Image","oblique.hdr","Analyze Image Files","*.hdr");
+  if (line!=NULL)
+    {
+      if (strlen(line)>0)
+	{
+	  vtkpxAnalyzeImageWriter* ana=vtkpxAnalyzeImageWriter::New();
+	  ana->SetInput(image);
+	  ana->Save(line);
+	  ana->Delete();
+	  return 1;
+	}
+    }
+
+  return 0;
+}
+
+int vtkpxGUIObliqueImageSliceControl::SaveCurrentTransform()
+{
+ if (this->Initialized==0 ||  has_obliqueslice==PXFalse)
+    return 0;
+
+  vtkTransform* xform=this->ObliqueImageSlice->GetObliqueTransform();
+  if (xform==NULL)
+    return 0;
+
+  char* line=this->EventManager->getSaveFilename("Save Oblique Transformation","oblique.matr","Matrix Files","*.matr");
+  if (line!=NULL)
+    {
+      if (strlen(line)>0)
+	{
+	  vtkpxTransformationUtil::SaveMatrixTransform(xform,line);
+	  return 1;
+	}
+    }
+
+  return 0;
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIObliqueImageSliceControl.h b/bioimagesuite30_src/GUI/vtkpxGUIObliqueImageSliceControl.h
new file mode 100644
index 0000000..612fa7e
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIObliqueImageSliceControl.h
@@ -0,0 +1,135 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIObliqueImageSliceControl.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIObliqueImageSliceControl - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkpxGUIObliqueImageSliceControl_h
+#define __vtkpxGUIObliqueImageSliceControl_h
+
+#include "vtkpxGUIComponent.h"
+#include "vtkpxObliqueImageSlice.h"
+#include "vtkpxGUIBaseRenderer.h"
+
+#include "pxtkframe.h"
+#include "pxtkscale.h"
+#include "pxtkoptionmenu.h"
+#include "pxtkcheckbutton.h"
+#include "pxtkcomplexwidgets.h"
+
+class vtkpxGUIObliqueImageSliceControl : public vtkpxGUIComponent
+{
+public:
+  static vtkpxGUIObliqueImageSliceControl *New();
+  vtkTypeMacro(vtkpxGUIObliqueImageSliceControl,vtkpxGUIComponent);
+  
+  virtual char* Initialize(const char* name,int inside);
+  virtual int   HandleEvent(int );
+
+  virtual void         SetObliqueImageSliceRenderer(vtkpxObliqueImageSlice* vol,vtkpxGUIBaseRenderer* viewer1);
+  virtual void         SetRenderer(vtkpxGUIBaseRenderer* viewer1);
+
+  virtual void         UpdateObliqueImageSliceRenderer(vtkpxObliqueImageSlice* vol,vtkpxGUIBaseRenderer* ren);
+
+  virtual void Update(int full=1);
+  virtual void UpdateDisplay();
+  virtual int  UpdateObliqueSlicePositionAndOrientation();
+  virtual vtkpxGUIBaseRenderer* GetViewer();
+  virtual void SetVisibility(int vis);
+
+  virtual void UpdateFromCamera(int force=0,int mode=0);
+  virtual void UpdateScales();
+
+  // Description:
+  // Save/Load Plane position
+  virtual int Save();
+  virtual int Load();
+
+  // Description:
+  // Save Grabbed Image
+  virtual int SaveCurrentImage();
+  virtual int SaveCurrentTransform();
+
+protected:
+
+  vtkpxGUIObliqueImageSliceControl();
+
+  vtkpxObliqueImageSlice    *ObliqueImageSlice;
+  vtkpxGUIBaseRenderer      *Viewer;
+  vtkpxGUIBaseRenderer      *internal_viewer;
+  PXBool                    has_obliqueslice;
+  PXBool                    Visibility;
+  PXBool                    NormalVisibility;
+  PXBool                    FollowCamera;
+
+  PXTkScale              *clipScale[3];
+  PXTkScale         *opacityScale;
+  PXTkArrowScale         *distanceScale;
+
+  PXTkOptionMenu         *resliceMode;
+
+  PXTkCheckButton        *show_obliqueslice;
+  PXTkCheckButton        *show_normal;
+  PXTkCheckButton        *follow_camera;
+
+  PXTkFrame              *viewerFrame;
+  PXTkFrame              *volFrame;
+
+
+  virtual void SetResolution(int mode);
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIOrthogonal4DViewer.cpp b/bioimagesuite30_src/GUI/vtkpxGUIOrthogonal4DViewer.cpp
new file mode 100644
index 0000000..fc47ff0
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIOrthogonal4DViewer.cpp
@@ -0,0 +1,1063 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIOrthogonal4DViewer.cpp,v $
+  Language:  C++
+  Date:      $Date: 2003/05/28 16:43:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxGUIColormapEditor.h"
+#include "pxtkframe.h"
+#include "vtkActor.h"
+#include "vtkActorCollection.h"
+#include "vtkObjectFactory.h"
+#include "vtkOutlineFilter.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkPropCollection.h"
+#include "vtkpxVolume.h"
+#include "vtkpxGUIVolumeControl.h"
+#include "vtkpxGUIObliqueImageSliceControl.h"
+#include "vtkVolumeCollection.h"
+#include "vtkRenderer.h"
+#include "vtkpxGUI4DRenderer.h"
+#include "vtkpxGUIOrthogonal4DViewer.h"
+#include "vtkpxImageExtract.h"
+#include "vtkpxImageSlice.h"
+#include "vtkpxOrthoImageSlice.h"
+#include "vtkpxObliqueImageSlice.h"
+#include "pxtktoplevel.h"
+
+vtkpxGUIOrthogonal4DViewer* vtkpxGUIOrthogonal4DViewer::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIOrthogonal4DViewer");
+  if(ret)
+      {
+	return (vtkpxGUIOrthogonal4DViewer*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIOrthogonal4DViewer;
+}
+
+// Construct object with no children.
+vtkpxGUIOrthogonal4DViewer::vtkpxGUIOrthogonal4DViewer()
+{
+  for (int i=0;i<=3;i++)
+    this->MultiRenderer[i]=NULL;
+  this->ImageSliceCollection=NULL;
+  this->AxisActorCollection=NULL;
+  this->OutlineActorCollection=NULL;
+  this->ActualNumberOfFrames=0;
+  this->EnableFrameChangeOnCallback=0;
+  this->createTalairachButtons=PXFalse;
+  this->ImageVolumeCollection=NULL;
+
+  this->MovieControl=NULL;
+  this->MovieFrameDelay=10.0;
+  this->MovieFrameStep=1;
+  this->MovieLoopMode=1;
+  this->CurrentlyPlayingMovie=0;
+  this->MoviePlayMode=0;
+  this->MovieControlInside=1;
+  //  this->SingleFrameMode=0;
+  this->ColorMode=0;
+  this->showMB=NULL;
+}
+// -------------------------------------------------------------------------
+// This needs work 
+vtkpxGUIOrthogonal4DViewer::~vtkpxGUIOrthogonal4DViewer()
+{
+  if (this->ImageSliceCollection)
+    this->ImageSliceCollection->Delete();
+
+  if (this->AxisActorCollection)
+    this->AxisActorCollection->Delete();
+
+  if (this->OutlineActorCollection)
+    this->OutlineActorCollection->Delete();
+
+  if (this->ImageVolumeCollection)
+    this->ImageVolumeCollection->Delete();
+  
+  for (int i=0;i<=3;i++)
+    if (this->MultiRenderer[i]!=NULL)
+      this->MultiRenderer[i]->Delete();
+
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIOrthogonal4DViewer::InitViewer()
+{
+  render_widget=new PXVTkTkRenderWidget(this->EventManager,viewerFrame,200);
+  render_widget->setWidthHeight(400,400);
+  render_widget->bindMouseEvents();
+  viewerFrame->addChildren("-side left -expand true -fill both",render_widget);
+  
+  // Background renderer 
+
+  vtkRenderer* ren=vtkRenderer::New();
+  render_widget->getRenderWindow()->AddRenderer(ren);
+
+  for (int ia=1;ia>=0;ia=ia-1)
+    {
+      for (int ib=1;ib>=0;ib-=1)
+	{
+	  int index=ia*2+ib;
+	  vtkRenderer* ren=vtkRenderer::New();
+	  render_widget->getRenderWindow()->AddRenderer(ren);
+	  this->MultiRenderer[index]=vtkpxGUI4DRenderer::New();
+	  this->renderer[index]=this->MultiRenderer[index];
+	  this->MultiRenderer[index]->SetAutoZoom(1.0);
+	  this->MultiRenderer[index]->SetFlipMode(0);
+	  if (index!=3)
+	    {
+	      this->MultiRenderer[index]->SetNoGUI(PXTrue);
+	      this->MultiRenderer[index]->SetPlaneMode(Irange(index,0,2));
+	      this->MultiRenderer[index]->SetClipMode(PXTrue);
+	      this->MultiRenderer[index]->SetClipThickness(2.0);
+	      this->MultiRenderer[index]->SetEnableActorTransform(0);
+	    }
+	  else
+	    {
+	      this->MultiRenderer[index]->SetClipMode(PXFalse);
+	      this->MultiRenderer[index]->SetClipThickness(0.25);
+	      this->MultiRenderer[index]->SetVerticalDecoration(PXFalse);
+	      this->MultiRenderer[index]->SetEnableActorTransform(1);
+	    }
+	  this->MultiRenderer[index]->Initialize(viewerFrame->getWidgetName(),ren,0);
+	  this->MultiRenderer[index]->SetViewport((ia)*0.5,(1-ib)*0.5,(1+ia)*0.5,(2-ib)*0.5);
+	  this->MultiRenderer[index]->Reset();
+	}
+    }
+  this->UpdateDisplay();
+  //render_widget->getRenderWindow()->Render();
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonal4DViewer::InitializeViewer()
+{
+  if ((!hasImage && this->Initialized))
+      return 0;
+
+  this->ColormapEditor=vtkpxGUIColormapEditor::New();
+  this->ColormapEditor->SetSimpleMode(0);
+  this->ColormapEditor->SetCallback(this,201);
+  this->ColormapEditor->Initialize(this->GetWidgetName(),0);
+  
+  this->ImageSliceCollection=vtkPropCollection::New();
+  this->AxisActorCollection=vtkActorCollection::New();
+  this->OutlineActorCollection=vtkActorCollection::New();
+  this->ImageVolumeCollection=vtkVolumeCollection::New();
+
+  for (int i=0;i<=3;i++)
+    {
+      outlineFilter[i]=vtkOutlineFilter::New();
+      outlineFilter[i]->SetInput(currentImage);
+    } 
+
+  this->SetDisplay3DMode(display3d_mode);
+  this->SetDisplay3DAxisOutlineMode(display3d_axisoutlinemode);
+
+  return 1;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonal4DViewer::CreateFrames(int numframes)
+{
+  if (numframes<this->ActualNumberOfFrames)
+    return;
+
+  if (numframes>999)
+    numframes=999;
+  if (numframes<1)
+    numframes=1;
+
+  int i=0;
+
+  for (i=0;i<=3;i++)
+    this->MultiRenderer[i]->SetNumberOfFrames(numframes);
+  
+  
+  for (int fr=this->ActualNumberOfFrames;fr<numframes;fr++)
+    {
+      //fprintf(stderr,"--------------------------------------\n");
+      for (i=0;i<=3;i++)
+	this->MultiRenderer[i]->SetCurrentFrame(fr);
+
+      /*fprintf(stderr,"Creating Frame=%d renderer[fr][0]=%d\n",fr,
+	(int)this->MultiRenderer[0]->GetRenderer());*/
+      
+      for (int k=0;k<=2;k++)
+	{
+	  imageSlice[k]=vtkpxImageSlice::New();
+	  imageSlice[k]->SetAutoUpdate(0);
+	  imageSlice[k]->SetInput(currentImage);
+	  imageSlice[k]->SetFrame(fr);
+	  imageSlice[k]->SetCurrentPlane(k);
+	  imageSlice[k]->PickableOff();
+	  this->MultiRenderer[k]->GetRenderer()->AddActor(imageSlice[k]);
+	  this->ImageSliceCollection->AddItem(imageSlice[k]);
+	}
+      
+      orthoSlice=vtkpxOrthoImageSlice::New();
+      orthoSlice->SetInput(currentImage);
+      orthoSlice->SetFrame(fr);
+      orthoSlice->PickableOff();
+      orthoSlice->SetPolarMode(0);
+      this->MultiRenderer[3]->GetRenderer()->AddActor(orthoSlice);
+      orthoSlice->SetVisibility(this->OrthoSliceVisibility);
+      this->ImageSliceCollection->AddItem(orthoSlice);
+
+      obliqueSlice=vtkpxObliqueImageSlice::New();
+      obliqueSlice->SetAutoUpdate(0);
+      obliqueSlice->SetInput(currentImage);
+      obliqueSlice->SetFrame(fr);
+      obliqueSlice->PickableOff();
+      obliqueSlice->SetVisibility(0);
+      this->MultiRenderer[3]->GetRenderer()->AddActor(obliqueSlice);
+      this->ImageSliceCollection->AddItem(obliqueSlice);
+      
+      // Volume Stuff
+      this->Volume=vtkpxVolume::New();
+      this->Volume->SetInput(currentImage,this->Orientation);
+      this->Volume->SetFrame(fr);
+      this->Volume->SetVisibility(0);
+      this->Volume->Update();
+      this->MultiRenderer[3]->GetRenderer()->AddVolume(this->Volume);
+      this->ImageVolumeCollection->AddItem(this->Volume);
+      
+      // Outline Stuff
+      for (i=0;i<=3;i++)
+	{
+	  vtkPolyDataMapper *mapOutline = vtkPolyDataMapper::New();
+	  mapOutline->SetInput(outlineFilter[i]->GetOutput());
+	  
+	  outline[i] = vtkActor::New();
+	  outline[i]->SetMapper(mapOutline);
+	  outline[i]->GetProperty()->SetColor(0.0,1.0,0.0);
+	  outline[i]->GetProperty()->SetAmbient(1.0);
+	  outline[i]->GetProperty()->SetDiffuse(0.0);
+	  outline[i]->GetProperty()->SetSpecular(0.0);
+	  outline[i]->GetProperty()->SetRepresentationToWireframe();
+	  outline[i]->PickableOff();
+	  this->MultiRenderer[i]->GetRenderer()->AddActor(outline[i]);
+	  mapOutline->Delete();
+	  this->OutlineActorCollection->AddItem(outline[i]);
+	}
+	  
+      // Axis Stuff
+      // Create Axis 
+      for (int rend=0;rend<=2;rend++)
+	for (int axis=0;axis<=1;axis++)
+	  {
+	    int index=rend*2+axis;
+	    axisActor[index]=vtkActor::New();
+	    axisActor[index]->PickableOff();
+	    this->MultiRenderer[rend]->GetRenderer()->AddActor(axisActor[index]);
+	    this->AxisActorCollection->AddItem(axisActor[index]);
+	  }
+      for (i=6;i<=9;i++)
+	{
+	  axisActor[i]=vtkActor::New();
+	  axisActor[i]->PickableOff();
+	  this->MultiRenderer[3]->GetRenderer()->AddActor(axisActor[i]);
+	  axisActor[i]->SetVisibility(0);
+	  this->AxisActorCollection->AddItem(axisActor[i]);
+	}
+    }
+  this->ActualNumberOfFrames=numframes;
+  
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonal4DViewer::HandleEvent(int event)
+{
+
+  // Block Volume Control pop-up
+  if (event==330 && this->CurrentlyPlayingMovie==1)
+    return TCL_OK;
+
+
+  if (event<400)
+    return vtkpxGUIOrthogonalViewer::HandleEvent(event);
+
+  if (!hasImage)
+    return TCL_OK;
+
+
+  switch (event)
+    {
+    case 400:
+      this->ShowMovieControl(1);
+      break;
+    case 401:
+      this->ShowMovieControl(0);
+      break;
+    case 402:
+      // Do Something about frame change
+      {
+	int cf=int(movieFrameScale->getValue()-1);
+	this->FastChangeFrame(cf);
+	this->UpdateDisplay();
+      }
+      break;
+
+    case 403:
+      this->MovieFrameDelay=1000.0*float(1.0/movieRateScale->getValue());
+      break;
+
+    case 404:
+      this->MovieLoopMode=(int)loopMenu->getIndex();
+      break;
+      
+    case 405:
+      this->MoviePlayMode=(int)playMenu->getIndex();
+      if (this->CurrentlyPlayingMovie==0)
+	{
+	  if (this->MoviePlayMode==0)
+	    this->prepareB->enable(PXFalse);
+	  else
+	    this->prepareB->enable(PXTrue);
+	}
+      break;
+
+    case 410:
+      this->MoviePrepare();
+      break;
+    case 411:
+      this->MoviePlay();
+      break;
+    case 412:
+      this->MovieStop();
+      break;
+    case 413:
+      this->FastChangeFrame(0);
+      break;
+
+    }
+
+  this->LastEvent=event;
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonal4DViewer::ChangeFrame(int newframe)
+{
+  newframe=Irange(newframe,0,this->NumberOfFrames-1);
+  if (newframe==this->CurrentFrame)
+    return;
+
+  int levels[3],levels2[3];
+  orthoSlice->GetLevels(levels);
+  UpdateFrame(newframe,0); 
+  orthoSlice->GetLevels(levels2);
+  int d=0;
+  for (int i=0;i<=2;i++)
+    d+=abs(levels[i]-levels2[i]);
+  
+  this->CurrentFrame=newframe;
+  //  fprintf(stderr,"in 4D Viewer:: Current Frame = %d\n",this->CurrentFrame);
+
+  SetDisplay3DMode(display3d_mode);
+  SetDisplay3DAxisOutlineMode(display3d_axisoutlinemode);
+
+  if (this->MovieControl!=NULL)
+    movieFrameScale->setValue(this->CurrentFrame+1);
+  this->ExecuteFrameChangeCallback();
+
+
+  if (d>0)
+    this->SetCoordinates(levels[0],levels[1],levels[2]);
+  else
+    MoveAxis(1);
+
+}
+// -------------------------------------------------------------------------
+// Movie Stuff 
+// -------------------------------------------------------------------------
+char* vtkpxGUIOrthogonal4DViewer::InitializeMovieControl(const char* name,int inside)
+{
+  if (this->Initialized==0)
+    return NULL;
+
+  if (this->MovieControl!=NULL)
+    return this->MovieControl->getWidgetName();
+
+  if (inside==1)
+    {
+      this->MovieControl=new PXTkFrame(NULL,name);
+      this->MovieControlInside=1;
+    }
+  else
+    {
+      this->MovieControl=new PXTkToplevel(this->EventManager,this->EventManager->getMainWindow(),"Movie Controls");
+      this->MovieControlInside=0;
+    }
+    
+  PXTkFrame* mainFrame=new PXTkFrame(this->EventManager,this->MovieControl);
+  this->MovieControl->addChildren("-side top -expand t -fill both",mainFrame);
+
+
+  
+  movieFrameScale=new PXTkArrowScale(this->EventManager,mainFrame,"Frame",402,PXTrue);
+  movieFrameScale->setRange(1,10);
+  movieFrameScale->setValue(float(1));
+  movieFrameScale->setLengthWidth(120,10);
+  movieFrameScale->setIncrement(1.0);
+  movieFrameScale->setResolution(1.0);
+	
+  movieRateScale=new PXTkArrowScale(this->EventManager,mainFrame,"Rate",403,PXTrue);
+  movieRateScale->setRange(1,64);
+  movieRateScale->setValue(1.0/(this->MovieFrameDelay*0.01));
+  movieRateScale->setLengthWidth(120,10);
+  movieRateScale->setIncrement(1.0);
+  movieRateScale->setResolution(1.0);
+
+  PXTkFrame* m1=new PXTkFrame(this->EventManager,this->MovieControl);
+  PXTkFrame* m2=new PXTkFrame(this->EventManager,this->MovieControl);
+
+  mainFrame->addChildren("-side top -expand f -fill x",
+			 movieFrameScale->getMainWindow(),movieRateScale->getMainWindow(),m1,m2);
+
+  PXTkLabel*  md0=new PXTkLabel(this->EventManager,m1,"Play Mode:");
+  playMenu=new PXTkOptionMenu(this->EventManager,m1,"Complete",405);
+  playMenu->addOption("Fast");
+  playMenu->setIndex(this->MoviePlayMode);
+
+  PXTkLabel*  md=new PXTkLabel(this->EventManager,m1,"Loop Mode:");
+  loopMenu=new PXTkOptionMenu(this->EventManager,m1,"Once",404);
+  loopMenu->addOption("Loop");
+  loopMenu->addOption("Swing");
+  loopMenu->setIndex(this->MovieLoopMode);
+
+  m1->addChildren("-side left -expand f -fill x",md0,playMenu,md,loopMenu);
+
+  this->prepareB=new PXTkButton(this->EventManager,m2,"Prepare",410);
+  this->playB=new PXTkButton(this->EventManager,m2,"Play",411);
+  this->pauseB=new PXTkButton(this->EventManager,m2,"Pause",412);
+  this->rewindB=new PXTkButton(this->EventManager,m2,"Rewind",413);
+  m2->addChildren("-side left -expand f -fill x",this->prepareB,this->playB,this->pauseB,this->rewindB);
+  this->pauseB->enable(PXFalse);
+
+  this->closeB=new PXTkButton(this->EventManager,m2,"Close",401);
+
+  if (inside==0)
+    {
+      m2->addChildren("-side right -expand f -fill x -padx 4",this->closeB);
+      ((PXTkToplevel*)this->MovieControl)->hide();
+      showMB=new PXTkButton(this->EventManager,coordScaleFrame,"Movie Control",400);
+      coordScaleFrame->addChildren("-side bottom -expand f -fill x -padx 0 ",showMB);
+    }
+ 
+  return this->MovieControl->getWidgetName();
+
+}
+// -------------------------------------------------------------------------  
+int   vtkpxGUIOrthogonal4DViewer::MoviePrepare()
+{
+  if (this->NumberOfFrames<2 || this->MovieControl==NULL)
+    return 0;
+  int fr=this->CurrentFrame;
+  
+  for (int i=0;i<this->NumberOfFrames;i++)
+    {
+      if (i!=fr)
+	this->SetCurrentFrame(i);
+    }
+  this->SetCurrentFrame(fr);
+  return 1;
+}
+
+int   vtkpxGUIOrthogonal4DViewer::MoviePlay()
+{
+  if (this->NumberOfFrames<2 || this->MovieControl==NULL)
+    return 0;
+  if (this->VolumeControl!=NULL)
+    this->VolumeControl->Show(0);
+  if (this->ObliqueControl!=NULL)
+    this->ObliqueControl->Show(0);
+
+  this->MovieFrameDelay=1000.0*float(1.0/movieRateScale->getValue());
+
+  for (int i=0;i<=2;i++)
+    this->MultiRenderer[i]->MoveAbove(-1);
+
+  this->MovieFrameStep=1;
+  Tcl_CreateTimerHandler((int)this->MovieFrameDelay,vtkpxGUIOrthogonal4DViewer::HandleNextFrameEvent,this);
+  this->CurrentlyPlayingMovie=1;
+
+  this->pauseB->enable(PXTrue);
+  this->rewindB->enable(PXFalse);
+  this->playB->enable(PXFalse);
+  this->prepareB->enable(PXFalse);
+  this->closeB->enable(PXFalse);
+  this->playMenu->enable(PXFalse);
+  this->movieFrameScale->enable(PXFalse);
+  return 1;
+}
+
+int   vtkpxGUIOrthogonal4DViewer::MovieStop()
+{
+  if (this->NumberOfFrames<2)
+    return 0;
+  this->CurrentlyPlayingMovie=0;
+  return 1;
+}
+
+
+void vtkpxGUIOrthogonal4DViewer::FastChangeFrame(int newfr)
+{
+  if (this->NumberOfFrames<2 || this->MovieControl==NULL)
+    return;
+
+  int newframe=newfr;
+
+  if (newframe==-1 && this->NumberOfFrames==1)
+    return;
+  
+  if (newframe==-1)
+    {
+      int fr=int(movieFrameScale->getValue()-1);
+      newframe=fr+this->MovieFrameStep;
+      //fprintf(stderr,"Newframe=%d fr=%d\n",newframe,fr);
+
+      switch (this->MovieLoopMode)
+	{
+	case 0: // Once
+	  if (newframe==this->NumberOfFrames)
+	    {
+	      this->CurrentlyPlayingMovie=0;
+	      newframe=this->NumberOfFrames-1;
+	    }
+	  break;
+	case 1: // Loop
+	  if (newframe==this->NumberOfFrames)
+	    newframe=0;
+	  break;
+	case 2:
+	  if (newframe==this->NumberOfFrames)
+	    {
+	      newframe=this->NumberOfFrames-2;
+	      this->MovieFrameStep=-1;
+	    }
+	  else if ( newframe==-1)
+	    {
+	      newframe=1;
+	      this->MovieFrameStep=1;
+	    }
+	  break;
+	}
+    }
+  
+
+  if (this->CurrentlyPlayingMovie==1)
+    {
+      if (this->MoviePlayMode==1)
+	{
+	  this->UpdateFrame(newframe,-1); 
+	  this->coordScale[3]->setValue(newframe+1,PXFalse);
+	  if (newfr==-1)
+	    movieFrameScale->setValue(newframe+1,PXFalse);
+	  this->CurrentFrame=newframe;
+	  this->UpdateDisplay();
+	}
+      else
+	{
+	  this->SetCurrentFrame(newframe);
+	}
+      Tcl_CreateTimerHandler((int)this->MovieFrameDelay,vtkpxGUIOrthogonal4DViewer::HandleNextFrameEvent,this);
+    }
+  else
+    {
+      this->SetCurrentFrame(newframe);
+      this->pauseB->enable(PXFalse);
+      this->rewindB->enable(PXTrue);
+      this->playB->enable(PXTrue);
+      if (this->MoviePlayMode==1)
+	this->prepareB->enable(PXTrue);
+      this->closeB->enable(PXTrue);
+      this->playMenu->enable(PXTrue);
+      this->movieFrameScale->enable(PXTrue);
+    }
+}
+
+void vtkpxGUIOrthogonal4DViewer::HandleNextFrameEvent(void *arg1)
+{
+  ((vtkpxGUIOrthogonal4DViewer*)arg1)->FastChangeFrame(-1);
+}
+
+int vtkpxGUIOrthogonal4DViewer::ShowMovieControl(int show)
+{
+  if ( (this->NumberOfFrames<2 && show==1) ||  this->MovieControlInside==1)
+    return 0;
+
+  if (!show)
+    ((PXTkToplevel*)this->MovieControl)->hide();
+  else
+    ((PXTkToplevel*)this->MovieControl)->show();
+
+  return 1;
+}
+
+void vtkpxGUIOrthogonal4DViewer::ShowFrameControls(int show)
+{
+  return;
+}
+  
+
+vtkpxGUI4DRenderer* vtkpxGUIOrthogonal4DViewer::GetMultiRenderer(int i)
+{
+  return this->MultiRenderer[Irange(i,0,3)];
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonal4DViewer::ResetViewerUpdatePolar()
+{
+  int   range[3]; 
+  currentImage->GetDimensions(range);
+
+  coordScale[0]->setLabel("Z-Coord");
+  coordScale[1]->setLabel("Angle 1");
+  coordScale[2]->setLabel("Angle 2");
+  
+  int levels[3];
+
+  for (int sc=0;sc<=2;sc++)
+    {
+      int sp=1;
+      if (sc>0)
+	sp=2;
+      levels[sc]=range[sp]/2;
+      if (sc==1)
+	levels[1]=0;
+      coordScale[sc]->setRange(offset,range[sp]-1+offset);  
+      coordScale[sc]->setValue(levels[sc]+offset);
+      coordScale[sc]->setResolution(1.0);
+      /*imageSlice[sc]->SetAutoUpdate(0);
+	imageSlice[sc]->SetCurrentPlane(sc);
+	imageSlice[sc]->SetLevel(levels[sc]);
+	imageSlice[sc]->Update();
+	imageSlice[sc]->SetAutoUpdate(1);
+	renderer[sc]->SetClipMode(PXTrue);
+	renderer[sc]->SetOrientation(3);
+	renderer[sc]->SetPlaneMode(sc);*/
+    }
+
+  orthoSlice->SetAutoUpdate(0);
+  orthoSlice->SetLevels(levels[0],levels[1],levels[2]);
+  orthoSlice->Update();
+  orthoSlice->SetAutoUpdate(1);
+
+  coordScale[3]->setRange(1,this->NumberOfFrames);
+  coordScale[3]->setValue(this->CurrentFrame+offset);
+  coordScale[3]->setResolution(1.0);
+
+
+  if (range[2]==1)
+    {
+      if (display_mode!=5)
+	{
+	  display_mode=5;
+	  AdjustViewports(display_mode);
+	}
+    }
+  else  
+    {
+      display_mode=(int)displayMode->getIndex();
+      AdjustViewports(display_mode);
+    }
+  this->MoveAxisPolar(1);
+  return 1;
+}
+// ------------------------------------------------------------------------- 
+int vtkpxGUIOrthogonal4DViewer::ResetViewerUpdateCartesian() 
+{
+  int   range[3]; 
+  currentImage->GetDimensions(range);
+
+  coordScale[0]->setLabel("X-Coord:");
+  coordScale[1]->setLabel("Y-Coord:");
+  coordScale[2]->setLabel("Z-Coord:");
+  
+  /*  for (int kk=0;kk<=2;kk++)
+      {
+      imageSlice[kk]->SetAutoUpdate(0);
+      imageSlice[kk]->SetCurrentPlane(kk);
+      renderer[kk]->SetPlaneMode(kk);
+      renderer[kk]->SetOrientation(this->Orientation);
+      renderer[kk]->SetClipMode(PXFalse);
+      }*/
+  
+  int levels[3];
+  orthoSlice->GetLevels(levels);
+  
+  double   sp[3],ori[3];
+  currentImage->GetSpacing(sp);
+  currentImage->GetOrigin(ori);
+  
+  double lvv[3],lvs[3];
+  for (int ic=0;ic<=2;ic++)
+    {
+      lvv[ic]=double(levels[ic]);
+      lvs[ic]=lvv[ic]*sp[ic]+ori[ic];
+    }
+  this->SetLastClickedPoint(lvv);
+  this->SetLastClickedPointScaled(lvs);
+  
+  coordScale[3]->setRange(1,this->NumberOfFrames);
+  coordScale[3]->setValue(this->CurrentFrame+offset);
+  coordScale[3]->setResolution(1.0);
+  
+  if (range[2]==1)
+    {
+      if (display_mode!=5)
+	{
+	  display_mode=5;
+	  AdjustViewports(display_mode);
+	}
+    }
+  else  
+    {
+      display_mode=(int)displayMode->getIndex();
+      AdjustViewports(display_mode);
+    }
+  this->MoveAxisCartesian(1);
+  
+  for (int sc=0;sc<=2;sc++)
+    {
+      coordScale[sc]->setRange(offset,range[sc]-1+offset);  
+      coordScale[sc]->setValue(levels[sc]+offset);
+      coordScale[sc]->setResolution(1.0);
+    }
+  return 1;
+}
+// -------------------------------------------------------------------------
+
+int vtkpxGUIOrthogonal4DViewer::ResetViewer()
+{
+  if (!(hasImage && this->Initialized))
+      return 0;
+
+  if (this->Orientation==3)
+    this->ModifyPolarImageSpacing();
+
+  this->CreateFrames(this->NumberOfFrames);
+
+  for (int i=1;i<this->NumberOfFrames;i++)
+    this->UpdateFrame(i,1);
+  UpdateFrame(0,1);
+
+  for (int j=0;j<=3;j++)
+    outlineFilter[j]->SetInput(currentImage);
+
+  int   range[3]; 
+  currentImage->GetDimensions(range);
+
+  this->ColormapEditor->SetLock(0);
+  this->ColormapEditor->SetRange(currentImage);
+  this->SetPresetLookupTable(this->PresetLookupTableMode);
+  this->ColormapEditor->Update();
+
+
+  int doupdate=1;
+  if (firsttimereset>0)
+    doupdate=0;
+
+  if (firsttimereset==0)
+    {
+      int flag=0;
+      for (int i=0;i<=2;i++)
+	if (range[i]!=(int(coordScale[i]->getmax())+1-offset))
+	  flag++;
+      if (this->NumberOfFrames!=(int(coordScale[3]->getmax())))
+	flag++;
+      
+      doupdate=(flag>0);
+    }
+
+  if (oldorientation!=this->Orientation)
+    {
+      doupdate=1;
+      oldorientation=this->Orientation;
+      this->ResetCoordinateScalesAndLabels();
+    }
+
+  if (range[2]==1 && display_mode!=5)
+    {
+      doupdate=1;
+    }
+
+  
+  if (doupdate)
+    {
+      if (this->Orientation!=3)
+	this->ResetViewerUpdateCartesian();
+      else
+	this->ResetViewerUpdatePolar();
+    }
+
+  
+  if (this->MovieControl!=NULL)
+    {
+      movieFrameScale->setRange(1,this->NumberOfFrames);
+      movieFrameScale->setValue(this->CurrentFrame+1);
+      movieFrameScale->setResolution(1.0);
+    }
+  
+  vtkpxGUIOrthogonalViewer::ShowFrameControls(1);
+
+  if (this->NumberOfFrames==1)
+    {
+      coordScale[3]->enable(PXFalse);
+      if (showMB!=NULL)
+	showMB->enable(PXFalse);
+      this->ShowMovieControl(0); 
+    }
+  else
+    {
+      coordScale[3]->enable(PXTrue);
+      if (showMB!=NULL)
+	showMB->enable(PXTrue);
+    }
+
+  if (this->obliqueSlice!=NULL && this->Orientation!=3)
+    {
+      //      fprintf(stderr,"Setting Camera Callback\n");
+      this->MultiRenderer[3]->SetCameraCallback(this->ObliqueControl,140);
+    }
+
+
+  firsttimereset=0;
+  return 1;
+}
+// -------------------------------------------------------------------------
+// Update Frame Stuff
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonal4DViewer::UpdateFrameCartesian(int frame,int full)
+{
+  if (full==1)
+    {
+      int   range[3]; 
+      currentImage->GetDimensions(range);
+      
+      orthoSlice->SetAutoUpdate(0);
+      orthoSlice->SetLevels(range[0]/2,range[1]/2,range[2]/2);
+      orthoSlice->Update();
+      orthoSlice->SetAutoUpdate(1);
+
+      for (int kk=0;kk<=2;kk++)
+	{
+	  imageSlice[kk]->SetAutoUpdate(0);
+	  imageSlice[kk]->SetLevel(range[kk]/2);
+	  imageSlice[kk]->Update();
+	  imageSlice[kk]->SetAutoUpdate(1);
+	}
+    }
+
+  this->Volume=(vtkpxVolume*)this->ImageVolumeCollection->GetItemAsObject(frame);
+
+
+  if (full==1)
+    {
+      this->Volume->SetInput(currentImage,this->Orientation);
+      this->Volume->SetFrame(frame);
+      this->VolumeControl->Update(1);
+      this->obliqueSlice->SetInput(currentImage);
+      this->obliqueSlice->SetFrame(frame);
+      this->ObliqueControl->Update(1);
+    }
+
+
+
+  if (full>=0)
+    {
+      this->Volume->SetFromLookupTable(this->VolumeControl->GetColorMapEditor()->GetColormap());
+      this->VolumeControl->UpdateVolumeRenderer(this->Volume,renderer[3]);
+      //      fprintf(stderr,"Updating Image Slice Renderer\n");
+      this->ObliqueControl->UpdateObliqueImageSliceRenderer(this->obliqueSlice,renderer[3]);
+      if (full==0)
+	this->ObliqueControl->Update(0);
+    }
+
+
+  if (full==1)
+    this->Volume->Update();
+
+
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonal4DViewer::UpdateFramePolar(int frame,int full)
+{
+  if (full)
+    {
+      int   range[3]; 
+      currentImage->GetDimensions(range);
+      
+      int v[3];
+      v[0]=range[1]/2;
+      v[1]=0;
+      v[2]=range[2]/2;
+
+      orthoSlice->SetAutoUpdate(0);      
+      orthoSlice->SetLevels(v[0],v[1],v[2]);
+      orthoSlice->Update();
+      orthoSlice->SetAutoUpdate(1);
+
+      for (int kk=0;kk<=2;kk++)
+	{
+	  imageSlice[kk]->SetAutoUpdate(0);
+	  imageSlice[kk]->SetLevel(v[kk]);
+	  imageSlice[kk]->Update();
+	  imageSlice[kk]->SetAutoUpdate(1);
+	}
+      
+    }
+  this->Volume=(vtkpxVolume*)this->ImageVolumeCollection->GetItemAsObject(frame);
+
+
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonal4DViewer::UpdateFrame(int frame,int full)
+{
+  if (frame>=this->ActualNumberOfFrames)
+    return;
+  
+  // First Collect Stuff from Collections 
+  if (full>=0)
+    {
+      for (int r=0;r<=3;r++)
+	this->MultiRenderer[r]->SetCurrentFrame(frame);
+    }
+  else
+    {
+      for (int r=0;r<=3;r++)
+	this->MultiRenderer[r]->FastSetCurrentFrame(frame);
+    }
+  
+  // Image Slice Ortho Slice First 
+  int index=frame*5;
+  
+  for (int i=0;i<=2;i++)
+    {
+      imageSlice[i]=(vtkpxImageSlice*)this->ImageSliceCollection->GetItemAsObject(index+i);
+      if (full==1)
+	{
+	  imageSlice[i]->SetAutoUpdate(0);
+	  imageSlice[i]->SetInput(currentImage);
+	  imageSlice[i]->SetFrame(frame);
+	  imageSlice[i]->SetLookupTable(mainLookupTable);
+	  if (this->Orientation==3)
+	    imageSlice[i]->SetPolarMode(1);
+	  else
+	    imageSlice[i]->SetPolarMode(0);
+	  imageSlice[i]->SetAutoUpdate(1);
+	  imageSlice[i]->Update();
+	  //	  this->MultiRenderer[i]->SetOrientation(this->Orientation);
+	  this->MultiRenderer[i]->SetCurrentImageOrientation(currentImage,this->Orientation);
+	  this->MultiRenderer[i]->SetClipThickness(currentImage->GetSpacing()[2]);
+	}
+    }
+
+  orthoSlice=(vtkpxOrthoImageSlice*)this->ImageSliceCollection->GetItemAsObject(index+3);
+  obliqueSlice=(vtkpxObliqueImageSlice*)this->ImageSliceCollection->GetItemAsObject(index+4);
+  if (full==1)
+    {
+      orthoSlice->SetAutoUpdate(0);
+      orthoSlice->SetInput(currentImage);
+      orthoSlice->SetFrame(frame);
+      orthoSlice->SetLookupTable(mainLookupTable);
+      if (this->Orientation==3)
+	orthoSlice->SetPolarMode(1);
+      else
+	orthoSlice->SetPolarMode(0);
+      orthoSlice->SetAutoUpdate(1);
+
+      obliqueSlice->SetAutoUpdate(0);
+      obliqueSlice->SetInput(currentImage);
+      obliqueSlice->SetFrame(frame);
+      obliqueSlice->SetLookupTable(mainLookupTable);
+      if (this->Orientation==3)
+	obliqueSlice->SetDisplayMode(0);
+      else
+	obliqueSlice->SetDisplayMode(3);
+      obliqueSlice->SetAutoUpdate(1);
+
+      //      this->MultiRenderer[3]->SetOrientation(this->Orientation);
+      this->MultiRenderer[3]->SetPlaneMode(2);
+      this->MultiRenderer[3]->GetRenderer()->SetBackground(0.2,0.2,0.3);
+      this->MultiRenderer[3]->SetCurrentImageOrientation(currentImage,this->Orientation);
+    }
+  
+  index=frame*4;
+  for (int out=0;out<=3;out++)
+    {
+      int vis=0;
+      if (outline[out]!=NULL)
+	vis=outline[out]->GetVisibility();
+
+      outline[out]=(vtkActor*)this->OutlineActorCollection->GetItemAsObject(index+out);
+      outline[out]->SetVisibility(vis);
+    }
+  
+  index=frame*10;
+  for (int ax=0;ax<=9;ax++)
+    {
+      int vis=0;
+      if (axisActor[ax]!=NULL)
+	vis=axisActor[ax]->GetVisibility();
+      axisActor[ax]=(vtkActor*)this->AxisActorCollection->GetItemAsObject(index+ax);
+      axisActor[ax]->SetVisibility(vis);
+    }
+
+
+
+  if (this->Orientation==3)
+    this->UpdateFramePolar(frame,full);
+  else
+    this->UpdateFrameCartesian(frame,full);
+  
+  return;
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIOrthogonal4DViewer.h b/bioimagesuite30_src/GUI/vtkpxGUIOrthogonal4DViewer.h
new file mode 100644
index 0000000..a046cf4
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIOrthogonal4DViewer.h
@@ -0,0 +1,173 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIOrthogonal4DViewer.h,v $
+  Language:  C++
+  Date:      $Date: 2004/03/18 18:31:23 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+// .NAME vtkpxGUIOrthogonal4DViewer 
+// .SECTION Description
+
+#ifndef __vtkpxGUIOrthogonal4DViewer_h
+#define __vtkpxGUIOrthogonal4DViewer_h
+
+#include "vtkpxGUIOrthogonalViewer.h"
+#include "pxvtkgadgets.h"
+#include "pxtkscale.h"
+#include "pxtkframe.h"
+#include "pxtkoptionmenu.h"
+#include "pxtklabel.h"
+#include "pxutil.h"
+
+class vtkActor;
+class vtkPropCollection;
+class vtkVolumeCollection;
+class vtkActorCollection;
+class vtkpxGUI4DRenderer;
+class vtkpxImageSlice;
+class vtkpxOrthoImageSlice;
+class vtkOutlineFilter;
+class vtkStructuredGrid;
+class vtkpxVolume;
+
+class  vtkpxGUIOrthogonal4DViewer : public vtkpxGUIOrthogonalViewer
+{
+public:
+  
+  static vtkpxGUIOrthogonal4DViewer *New();
+  vtkTypeMacro(vtkpxGUIOrthogonal4DViewer,vtkpxGUIOrthogonalViewer);
+
+  // Description:
+  // Functions Overriden from vtkpxGUIOrthogonalViewer
+  virtual int   InitializeViewer();
+  virtual int   ResetViewer();
+  virtual int   HandleEvent(int event);
+
+  // Description:
+  // Movie Stuff 
+  virtual char* InitializeMovieControl(const char* name,int inside);
+  virtual char* InitializeMovieControl(const char* name) { return InitializeMovieControl(name,1); }
+
+  virtual int   ShowMovieControl(int show);
+  virtual int   MoviePrepare();
+  virtual int   MoviePlay();
+  virtual int   MovieStop();
+  
+  virtual void  ShowFrameControls(int show=1);
+
+  virtual vtkpxGUI4DRenderer*  GetMultiRenderer(int r);
+protected:
+
+  vtkpxGUIOrthogonal4DViewer();
+  virtual ~vtkpxGUIOrthogonal4DViewer();
+
+  vtkpxGUI4DRenderer*       MultiRenderer[4];
+  vtkPropCollection*        ImageSliceCollection; // 5 Actors per frame 0-2 image slice[0-2] 3=orthoslice 4=obliqueslice
+  vtkActorCollection*       AxisActorCollection;  // 10 Actors per frame 
+  vtkActorCollection*       OutlineActorCollection;  // 4 Actors per frame 
+  vtkVolumeCollection*      ImageVolumeCollection;
+  int                       ActualNumberOfFrames;
+
+  // Movie Related Stuff
+  PXTkFrame*                MovieControl;
+  PXTkArrowScale            *movieFrameScale;
+  PXTkArrowScale            *movieRateScale;
+  PXTkOptionMenu*           loopMenu;
+  PXTkOptionMenu*           playMenu;
+  //BTX
+  PXTkButton                *playB,*prepareB,*pauseB,*rewindB,*closeB,*showMB;
+  //ETX
+  float                     MovieFrameDelay;
+  int                       MovieLoopMode;
+  int                       MovieFrameStep;
+  int                       MoviePlayMode;
+  int                       CurrentlyPlayingMovie;
+  int                       MovieControlInside;
+
+
+  virtual void InitViewer();
+
+  // Description:
+  // Change Frame -- copy outlines, actors axis/actors etc etc etc 
+  virtual void ChangeFrame(int newframe);
+
+  // Description:
+  // Update Frame for new Input Image
+  virtual void UpdateFrame(int frame,int full);
+  virtual void UpdateFrameCartesian(int frame,int full);
+  virtual void UpdateFramePolar(int frame,int full);
+
+  // Description:
+  // Reset Viewer Stuff
+  virtual int ResetViewerUpdatePolar();
+  virtual int ResetViewerUpdateCartesian();
+
+
+
+  // Description:
+  // Add Frame
+  virtual void CreateFrames(int numframes);
+
+  // Description:
+  // Fast Change Frame 
+  virtual void FastChangeFrame(int newframe=-1);
+
+  // Description:
+  // Handle Next Frame Event (timer)
+  static void HandleNextFrameEvent(void *arg1);
+
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIOrthogonalViewer.cpp b/bioimagesuite30_src/GUI/vtkpxGUIOrthogonalViewer.cpp
new file mode 100644
index 0000000..2b62202
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIOrthogonalViewer.cpp
@@ -0,0 +1,3260 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+#include "vtkLineWidget.h"
+#include "vtkpxGUIColormapEditor.h"
+
+#include "pxtkframe.h"
+#include "vtkCamera.h"
+#include "vtkActor.h"
+#include "vtkCellPicker.h"
+#include "vtkCubeSource.h"
+#include "vtkDataSetMapper.h"
+#include "vtkImageDataGeometryFilter.h"
+#include "vtkImageSeedConnectivity.h"
+#include "vtkImageThreshold.h"
+#include "vtkLineSource.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkOutlineFilter.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkProbeFilter.h"
+#include "vtkRenderer.h"
+#include "vtkRendererCollection.h"
+#include "vtkSphereSource.h"
+#include "vtkConeSource.h"
+#include "vtkCubeSource.h"
+#include "vtkCylinderSource.h"
+#include "vtkThresholdPoints.h"
+#include "vtkpxGUIObliqueImageSliceControl.h"
+#include "vtkpxGUIOrthogonalViewer.h"
+#include "vtkpxGUIRenderer.h"
+#include "vtkpxGUIVolumeControl.h"
+#include "vtkpxImageExtract.h"
+#include "vtkpxImageExtractVOI.h"
+#include "vtkpxImageSlice.h"
+#include "vtkpxObliqueImageSlice.h"
+#include "vtkpxOrthoImageSlice.h"
+#include "vtkpxTalairachTransform.h"
+#include "vtkpxVolume.h"
+#include "vtkGenericRenderWindowInteractor.h"
+#include "vtkCommand.h"
+#include "vtkConeSource.h"
+#include "vtkInteractorStyle.h"
+#include "vtkTransformPolyDataFilter.h"
+#include "vtkTransform.h"
+// -------------------------------------------------------------------------
+// A Quick Helper Class
+// -------------------------------------------------------------------------
+
+
+// This does the actual work: updates the probe.
+// Callback for the interaction
+class vtkmyPWCallback : public vtkCommand
+{
+public:
+
+  static vtkmyPWCallback *New()   { return new vtkmyPWCallback; }
+  virtual void Execute(vtkObject *caller, unsigned long, void*)
+  {
+    this->Viewer->SetEventResponseFromWidget(1);
+  }
+
+  vtkpxGUIOrthogonalViewer *Viewer;
+};
+
+
+// -------------------------------------------------------------------------
+vtkpxGUIOrthogonalViewer* vtkpxGUIOrthogonalViewer::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIOrthogonalViewer");
+  if(ret)
+      {
+	return (vtkpxGUIOrthogonalViewer*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIOrthogonalViewer;
+}
+
+// Construct object with no children.
+vtkpxGUIOrthogonalViewer::vtkpxGUIOrthogonalViewer()
+{
+  this->showPointer=NULL;
+  this->viewerFrame=NULL;
+  this->viewerFrame2=NULL;
+  this->controlFrame=NULL;
+  this->show_controlframe=1;
+
+
+  this->display_mode=6;
+  this->display3d_mode=1;
+  this->display3d_axisoutlinemode=1;
+
+  this->offset=0;
+
+  this->OrthoSliceVisibility=1;
+
+  this->orthoSlice=NULL;
+  this->render_widget=NULL;
+  this->MouseSliceChangeMode=1;
+  this->Volume=NULL;
+
+  this->VolumeControl=NULL;
+  this->ObliqueControl=NULL;
+
+  this->createTalairachButtons=PXTrue;
+  for (int i=0;i<=2;i++)
+    imageSlice[i]=NULL;
+  this->obliqueSlice=NULL;
+
+  for (int j=0;j<=3;j++)
+    {
+      renderer[j]=NULL;
+      outline[j]=NULL;
+      outlineFilter[j]=NULL;
+    }
+  this->BackgroundRenderer=NULL;  
+
+  
+  for (int k=0;k<10;k++)
+    axisActor[k]=NULL;
+
+  render_widget=NULL;
+
+  // If not initialized in BaseImageViewer
+  if (this->talairachTransform==NULL)
+    this->talairachTransform=vtkpxTalairachTransform::New();
+
+  this->TraceVolume=1;
+  this->TraceVolumeVOI=0;
+  this->TraceVolumeWeightedMode=0;
+  this->TraceGeometry=0;
+  this->TraceVolumeToleranceMode=1;
+
+
+  this->oldorientation=-1;
+  this->firsttimereset=1;
+  this->inexpose=0;
+  this->inexposecount=0;
+  this->LastClickedSlice=2;
+
+  this->NavigationPointer=NULL;
+  this->WidgetInteractor=NULL;
+  this->EventResponseFromWidget=0;
+  this->SynchNavigationalPointerWithCrossHairs=0;
+  this->NavigationRadius=4;
+  this->NavigationRadius_X= this->NavigationRadius_Y= this->NavigationRadius_Z= 10; 
+  this->NavigationPointerDrawMode=0;
+  this->NavigationPointerActor=NULL;
+  this->NavigationPointerGeometry=NULL;
+  this->NavigationPointerActorMode=0;
+  this->NavigationConeSource=NULL;
+  this->NavigationSphereSource=NULL;
+  this->NavigationCubeSource=NULL;
+  this->NavigationEllipseSource=NULL;
+  this->NavigationCylinderSource=NULL;
+  this->NavigationCylinderFilter=NULL;
+  this->NavigationCylinderTransform=NULL;
+
+  this->NavigationPointerTip[0]=0;   this->NavigationPointerTip[1]=0;   this->NavigationPointerTip[2]=0; 
+  this->NavigationPointerBase[0]=0;   this->NavigationPointerBase[1]=-30.0;   this->NavigationPointerBase[2]=0; 
+}
+
+vtkpxGUIOrthogonalViewer::~vtkpxGUIOrthogonalViewer()
+{
+
+  for (int i=0;i<=2;i++)
+    if (imageSlice[i]!=NULL)
+      imageSlice[i]->Delete();
+
+  if (orthoSlice!=NULL)
+    orthoSlice->Delete();
+
+  if (obliqueSlice!=NULL)
+    {
+      obliqueSlice->Delete();
+      this->ObliqueControl->Delete();
+    }
+
+  if (this->Volume!=NULL)
+    {
+      this->Volume->Delete();
+      this->VolumeControl->Delete();
+    }
+
+
+  if (render_widget!=NULL)
+    delete render_widget;
+
+  for (int j=0;j<=3;j++)
+    {
+      if (renderer[j]!=NULL) renderer[j]->Delete();
+      if (outline[j]!=NULL) outline[j]->Delete();
+      if (outlineFilter[j]!=NULL) outlineFilter[j]->Delete();
+
+    }
+  
+  for (int k=0;k<10;k++)
+    if (axisActor[k]!=NULL)
+      axisActor[k]->Delete();
+
+
+  if (this->NavigationPointer!=NULL)
+    this->NavigationPointer->Delete();
+
+  if (this->WidgetInteractor!=NULL)
+    this->WidgetInteractor->Delete();
+
+  if (this->NavigationPointerActor!=NULL)
+    this->NavigationPointerActor->Delete();
+
+  if (this->NavigationPointerGeometry!=NULL)
+    this->NavigationPointerGeometry->Delete();
+
+  if (this->NavigationConeSource!=NULL)
+    this->NavigationConeSource->Delete();
+
+  if (this->NavigationSphereSource!=NULL)
+  this->NavigationSphereSource->Delete();
+  
+  if (this->NavigationCubeSource!=NULL)
+    this->NavigationCubeSource->Delete();
+
+  if (this->NavigationCylinderSource!=NULL)
+    this->NavigationCylinderSource->Delete();
+
+  if (this->NavigationCylinderFilter!=NULL)
+    this->NavigationCylinderFilter->Delete();
+
+  if (this->NavigationCylinderTransform!=NULL)
+    this->NavigationCylinderTransform->Delete();
+
+
+
+}
+/* -------------------------------------------------------------------------*/
+
+char* vtkpxGUIOrthogonalViewer::Initialize(const char* name,int inside)
+{
+  return Initialize(name,name,inside);
+}
+
+char* vtkpxGUIOrthogonalViewer::Initialize(const char* name,const char* name2,int inside)
+{
+  if (this->Initialized==1)
+    return GetWidgetName();
+  
+  
+
+  vtkpxGUIComponent::Initialize(name,inside);
+
+
+  PXTkFrame* manager=(PXTkFrame*)(this->EventManager->getMainWindow());
+  viewerFrame=new PXTkFrame(this->EventManager,manager);
+  manager->setPackMode(PXTrue);
+  manager->addChildren("-side left -expand true -fill both",viewerFrame);
+      
+  if (strcmp(name,name2)==0)
+    {
+      viewerFrame2=viewerFrame;
+    }
+  else
+    {
+      PXTkFrame* manager2=new PXTkFrame(NULL,name2);
+      manager2->setPackMode(PXTrue);
+      viewerFrame2=new PXTkFrame(this->EventManager,manager2);
+      manager2->addChildren("-side left -expand true -fill both",viewerFrame2);
+    }
+
+  InitControls(0);
+  InitViewer();
+
+  /* vol Commented*/
+  this->VolumeControl=vtkpxGUIVolumeControl::New();
+  this->VolumeControl->Initialize(viewerFrame2->getWidgetName(),0);
+  this->VolumeControl->GetEventManager()->setTitle("Volume Control"); 
+  this->VolumeControl->SetOrthoViewer(this);
+
+  this->ObliqueControl=vtkpxGUIObliqueImageSliceControl::New();
+  this->ObliqueControl->Initialize(viewerFrame2->getWidgetName(),0);
+  this->ObliqueControl->GetEventManager()->setTitle("Oblique Slice Control"); 
+  
+  AdjustViewports(-1);
+  
+  return GetWidgetName();
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::UpdateDisplay()
+{
+  if (inexpose==1 || this->EnableRendering==0)
+    {
+      ++inexposecount;
+      return TCL_OK;
+      }
+ 
+  inexpose=1;
+  PXTkApp::executeTclCommand("update idletasks");
+  render_widget->getRenderWindow()->Render();  
+  this->LastEvent=-1;
+  inexposecount=0;
+  inexpose=0;
+  return TCL_OK;
+}
+
+
+// -------------------------------------------------------------------------
+
+int vtkpxGUIOrthogonalViewer::HandleEvent(int event)
+{
+  if (event>0 && event<10)
+      return this->EventManager->handleDirectEvent(event);
+
+
+  if (!hasImage && event!=201)
+    return TCL_OK;
+
+  switch (event)
+      {
+      case 200:
+	{
+	  int* x=render_widget->getRenderWindow()->GetSize();
+	  int mouse=PXTkApp::getIntArgument(0);
+	  int state=PXTkApp::getIntArgument(1);
+	  int x1=PXTkApp::getIntArgument(2);
+	  int x2=x[1]-PXTkApp::getIntArgument(3);
+	  HandleMouseButtonEvent(mouse,state,x1,x2,this->EventManager);
+	}
+	break;
+	
+      case 201:
+	if (this->LastEvent!=201)
+	  {
+	    this->RenderDelay(200);
+	  }
+	break;
+	
+      case 300: // Interpolation;
+	{
+	  PXBool interp=interpolateMode->getState();
+	  this->SetInterpolation((int)interp);
+	  UpdateDisplay();
+	}
+	 break;
+
+
+      case 301:
+	  {
+	    int cf=int(coordScale[3]->getValue()-1);
+	    this->ChangeFrame(cf);
+	    this->UpdateDisplay();
+	  }
+	break;
+
+	
+      case 302: // Coordinate Change
+	{
+	    int lv[3];
+	    double lvv[3],lvs[3];
+	    double   sp[3],ori[3];
+	    currentImage->GetSpacing(sp);
+	    currentImage->GetOrigin(ori);
+	    
+	    for (int ia=0;ia<=2;ia++)
+	      {
+		lv[ia]=int(coordScale[ia]->getValue()-offset);
+		lvv[ia]=double(lv[ia]);
+		lvs[ia]=lvv[ia]*sp[ia]+ori[ia];
+	      }
+	    this->ChangeSliceLevels(lv);
+	    this->SetLastClickedPoint(lvv);
+	    this->SetLastClickedPointScaled(lvs);
+	    
+	    this->ExecuteCoordinatesChangeCallback();
+	    //this->UpdateDisplay();
+	  }
+	break;
+
+	
+      case 303: // Colormap
+	if (this->ColormapEditor!=NULL)
+	  this->ColormapEditor->Show();
+	break;
+	
+	
+      case 304:
+      case 305: // Zoom
+	if (event==305)
+	  {
+	    renderer[0]->Zoom(renderer[0]->GetCameraScale()*1.2,PXFalse);
+	    renderer[3]->Zoom(renderer[0]->GetCameraScale()*1.2,PXFalse);
+	  }
+	else
+	  {
+	    renderer[0]->Zoom(renderer[0]->GetCameraScale()*0.833,PXFalse);
+	    renderer[3]->Zoom(renderer[0]->GetCameraScale()*1.2,PXFalse);
+	  }
+	
+	for (int kk=1;kk<3;kk++)
+	  renderer[kk]->Zoom(renderer[0]->GetCameraScale(),PXFalse);
+	
+	 
+	UpdateDisplay();
+	break;
+	
+      case 306: // Reset
+	for (int i=0;i<=3;i++)
+	  renderer[i]->Reset();
+	
+	this->MoveAxis(1);
+	UpdateDisplay();
+	break;
+
+      case 307:
+	display_mode=(int)displayMode->getIndex();
+	AdjustViewports(display_mode);
+	break;
+
+      case 308:
+	if (freezeMode->getState())
+	  this->MouseSliceChangeMode=1;
+	else
+	  this->MouseSliceChangeMode=0;
+	break;
+
+
+      case 309:
+      case 310:
+      case 311:
+      case 312:
+      case 313:
+	this->SetPresetLookupTable(event-310);
+	break;
+
+      case 314:
+	this->SetPresetLookupTable(6);
+	break;
+	
+      case 315:
+	this->SaveAsTiff(render_widget->getRenderWindow());
+	break;
+
+      case 316:
+	this->SaveAllAsTiff(render_widget->getRenderWindow());
+	break;
+
+      case 317:
+	{
+	  if (showaxisc->getState()==PXTrue)
+	    this->ShowCrossHairs(1);
+	  else
+	    this->ShowCrossHairs(0);
+	}
+	break;
+
+      case 318:
+	if (this->NavigationPointer!=NULL)
+	  {
+	    // Pointer
+	    if (showPointer->getState()==PXTrue)
+	      {
+		this->SynchNavigationalPointerWithCrossHairs=1;
+		if (this->NavigationPointerDrawMode==0)
+		  this->RenderNavigationPointer(3);
+		else
+		  this->RenderNavigationPointer(-1);
+	      }
+	    else
+	      {
+		this->SynchNavigationalPointerWithCrossHairs=0;
+		this->RenderDelay(200);
+	      }
+	  }
+	break;
+
+      case 320:
+	if (this->talairachTransform==NULL)
+	  this->talairachTransform=vtkpxTalairachTransform::New();
+	this->talairachTransform->SetColinMode(1,this->currentImage);
+	this->talairachTransform->Modified();
+	this->MoveAxis(1);
+	break;
+
+      case 322:
+	if (this->talairachTransform==NULL)
+	  this->talairachTransform=vtkpxTalairachTransform::New();
+
+	this->talairachTransform->SetColinMode(-1,this->currentImage);
+	this->talairachTransform->Modified();
+	this->MoveAxis(1);
+	break;
+
+
+
+      case 330: // Show Volume Controls
+	if (this->VolumeControl!=NULL)
+	{
+	  this->VolumeControl->Show(1);
+	}
+	break;
+
+
+      case 333: // Show Volume Controls
+	if (this->ObliqueControl!=NULL)
+	  this->ObliqueControl->Show(1);
+	break;
+
+
+      case 331:
+	if (display_mode == 2 || display_mode ==7 || display_mode==6)
+	  {
+	    display3d_mode=(int)display3DMode->getIndex();
+	    if (this->Orientation==3 && display3d_mode>=2)
+	      {
+		display3DMode->setIndex(1);
+		display3d_mode=1;
+	      }
+	    SetDisplay3DMode(display3d_mode);
+	    this->UpdateDisplay();
+	  }
+	else {
+	  display3DMode->setIndex(display3d_mode);
+	}
+	break;
+
+      case 332:
+	display3d_axisoutlinemode=(int)display3DAxisOutlineMode->getIndex();
+	SetDisplay3DAxisOutlineMode(display3d_axisoutlinemode);
+	this->UpdateDisplay();
+	break;
+
+	
+      case 350: // Hide Widget
+	SetShowControls(1-this->show_controlframe);
+	break;
+      }
+
+  this->LastEvent=event;
+
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::SetCurrentFrame(int t)
+  {
+  if (this->CurrentImageIsColor)
+    return;
+
+  if (t<0)
+    t=this->NumberOfFrames-1;
+  if (t>this->NumberOfFrames-1)
+    t=0;
+
+  if (!this->Initialized)
+    return;
+
+  coordScale[3]->setValue(t+1);
+  this->ChangeFrame(t);
+
+  this->UpdateDisplay();
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::SetPresetLookupTable(int mode)
+{
+  if (!hasImage)
+    return;
+
+  vtkpxGUIBaseImageViewer::SetPresetLookupTable(mode);
+  if (this->VolumeControl!=NULL && this->Orientation!=3)
+    this->VolumeControl->SetPresetLookupTable(this->PresetLookupTableMode);
+  
+}
+// -------------------------------------------------------------------------
+void  vtkpxGUIOrthogonalViewer::SetCoordinates(int lx,int ly,int lz,int infoonly)
+{
+  if (this->Initialized==0 || !hasImage)
+    return;
+  
+  int lv[3];
+  lv[0]=lx; lv[1]=ly; lv[2]=lz;
+			
+  for (int ia=0;ia<=2;ia++)
+    coordScale[ia]->setValue(lv[ia]+offset);
+
+  this->ChangeSliceLevels(lv,infoonly);
+}
+// -------------------------------------------------------------------------
+void  vtkpxGUIOrthogonalViewer::SetScaledCoordinates(float lx,float ly,float lz,int infoonly)
+{
+  if (this->Initialized==0 || !hasImage)
+    return;
+  
+  float lvv[3];
+  lvv[0]=lx; lvv[1]=ly; lvv[2]=lz;
+		
+  int lv[3];
+
+  double   sp[3],ori[3];
+  currentImage->GetSpacing(sp);
+  currentImage->GetOrigin(ori);
+  
+  for (int ic=0;ic<=2;ic++)
+    lv[ic]=int(0.5+ (lvv[ic]-ori[ic])/sp[ic]);
+
+  this->SetCoordinates(lv[0],lv[1],lv[2],infoonly);
+  this->UpdateDisplay();
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::SendEventToWidgetInteractor(int x,int y,int button,int state)
+{
+
+  if (this->WidgetInteractor==NULL)
+    return 0;
+
+
+
+  int cntrl=0;
+  int shift=0;
+
+  if (button>3 && button<=6)
+    {
+      shift=1;
+      button=button-3;
+    }
+  else if (button>6)
+    {
+      cntrl=1;
+      button=button-6;
+    }
+
+
+  this->WidgetInteractor->SetEventPosition(x,y);
+  this->WidgetInteractor->SetControlKey(cntrl);
+  this->WidgetInteractor->SetShiftKey(shift);
+  this->WidgetInteractor->SetRepeatCount(0);
+
+  if (state==1)
+    {
+      this->WidgetInteractor->MouseMoveEvent();
+    }
+  else if (button == 1 )
+    {
+      if (state==0)
+	this->WidgetInteractor->LeftButtonPressEvent();
+      else if (state==2)
+	this->WidgetInteractor->LeftButtonReleaseEvent();
+    }
+  else if (button == 2 )
+    {
+      if (state==0)
+	this->WidgetInteractor->MiddleButtonPressEvent();
+      else if (state==2)
+	this->WidgetInteractor->MiddleButtonReleaseEvent();
+    }
+
+  else if (button == 3 )
+    {
+      if (state==0)
+	this->WidgetInteractor->RightButtonPressEvent();
+      else if (state==2)
+	this->WidgetInteractor->RightButtonReleaseEvent();
+    }
+
+  return 1;
+
+}
+
+
+int vtkpxGUIOrthogonalViewer::HandleMouseButtonEvent(int nbutton,int state,
+						     int x,int y,PXTkEventObj* ev)
+{
+
+  // Not There for Polar Images 
+
+  if (nbutton==9 && state==2)
+    {
+      if (this->NavigationPointer->GetEnabled())
+	{
+	  this->RenderNavigationPointer(0);
+	}
+      else
+	{
+	  this->RenderNavigationPointer(3);
+	}
+      return 1;
+    }
+
+  int status=1;
+  int found=-1;
+  if (ev==NULL)
+    return 0;
+
+  for (int i=3;i>=0;i-=1)
+      {
+	if (renderer[i]->InViewport(x,y))
+	    found=i;
+      }
+
+  double lvv[3];
+  for (int ic=0;ic<=2;ic++)
+    lvv[ic]=float(-1);
+
+  if (found==-1)
+    {
+      this->SetLastClickedPoint(lvv);
+      this->SetLastClickedPointScaled(lvv);
+      return 0;
+    }
+
+  if (found==3)
+    {
+      this->EventResponseFromWidget=0;
+      this->SendEventToWidgetInteractor(x,y,nbutton,state);
+      if (this->EventResponseFromWidget==1)
+	{
+	  // Now we can do stuff like .....
+	  // Update Volume Control for example from here
+	  // this->VolumeControl->UpdatePosition(this->NavigationPointer);
+
+	  double p1[3];   this->NavigationPointer->GetPoint1(p1);
+	  double p2[3];   this->NavigationPointer->GetPoint2(p2);
+	  double d=sqrt(vtkMath::Distance2BetweenPoints(p2,p1));
+	  char line[20]; sprintf(line,"Distance = %.3f",d);
+	  this->renderer[3]->ShowLabel();
+	  this->renderer[3]->SetLabel(line,0.05,0.05,1,0,0);
+	  this->UpdateNavigationActorGeometry((state==2));
+	  return 1;
+	}
+
+
+
+      if (this->TraceVolume && nbutton==4 && this->Orientation!=3)
+	{
+	  this->SetLastClickedPoint(lvv);
+	  this->SetLastClickedPointScaled(lvv);
+	  return this->VolumePick(x,y,renderer[3]->GetRenderer());
+	}
+      else if (this->TraceGeometry && nbutton == 4 )
+	{
+	  this->SetLastClickedPoint(lvv);
+	  this->SetLastClickedPointScaled(lvv);
+	  return this->GeometryPick(x,y,renderer[3]->GetRenderer());
+	}
+      else
+	{
+	  this->SetLastClickedPoint(lvv);
+	  this->SetLastClickedPointScaled(lvv);
+	  return renderer[found]->HandleMouseButtonEvent(nbutton,state,x,y,ev);
+	}
+    }
+
+
+
+  if (!hasImage || this->Orientation==3)
+    {
+      this->SetLastClickedPoint(lvv);
+      this->SetLastClickedPointScaled(lvv);
+      return 0;
+    }
+
+  double px1,py1;
+  renderer[found]->Get2DClickedPoint(px1,py1,x,y);
+  
+  if (nbutton==4 || nbutton==7 || nbutton==1 )
+      {
+	double sp[3];    currentImage->GetSpacing(sp);
+	double ori[3];   currentImage->GetOrigin(ori);
+
+	int lv[3];
+	double lvs[3];
+	for (int ib=0;ib<=2;ib++)
+	  {
+	    lv[ib]=int(coordScale[ib]->getValue())-offset;
+	    lvs[ib]=lv[ib]*sp[ib]+ori[ib];
+	  }
+
+	switch(found)
+	  {
+	  case 0:
+	    lv[1]=(int)((px1-ori[1])/sp[1]+0.5);
+	    lv[2]=(int)((py1-ori[2])/sp[2]+0.5);
+	    lvs[1]=px1;
+	    lvs[2]=py1;
+	    break;
+	  case 1:
+	    lv[0]=(int)((px1-ori[0])/sp[0]+0.5);
+	    lv[2]=(int)((py1-ori[2])/sp[2]+0.5);
+	    lvs[0]=px1;
+	    lvs[2]=py1;
+	    //sliceControl->SetScaleValues(px1,-1,py1,1);
+	    break;
+	  case 2:
+	    //  sliceControl->SetScaleValues(px1,py1,-1,2);
+	    lv[0]=(int)((px1-ori[0])/sp[0]+0.5);
+	    lv[1]=(int)((py1-ori[1])/sp[1]+0.5);
+	    lvs[0]=px1;
+	    lvs[1]=py1;
+	    break;
+	  }
+
+	this->LastClickedSlice=found;
+
+
+	if (state !=0)
+	  {
+	    if (this->MouseSliceChangeMode && this->Orientation!=3)
+	      {
+		this->SetCoordinates(lv[0],lv[1],lv[2]);
+
+	      }
+	    else
+	      {
+		this->ChangeSliceLevels(lv,1);
+	      }
+	    this->SetLastClickedPointScaled(lvs);
+	    this->ExecuteCoordinatesChangeCallback();
+	  }
+	else
+	  {
+	    //	    this->SetLastClickedPointScaled(lvs);
+	    double lvv[3];
+	    for (int ia=0;ia<=2;ia++)
+	      lvv[ia]=double(lv[ia]);
+	    this->SetLastClickedPoint(lvv);
+	    this->SetLastClickedPointScaled(lvs);
+	  }
+	status=1;
+      }
+  else
+    {
+      int lv[3];
+      lv[0]=-1;lv[1]=-1;lv[2]=-1;
+      this->ChangeSliceLevels(lv,1);
+      status=0;
+    }
+  
+  if (nbutton!=1 && nbutton!=4 && nbutton!=7)
+    {
+      return renderer[found]->HandleMouseButtonEvent(nbutton,state,x,y,ev);
+    }
+  
+  return status;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::GetDisplayMode()
+{
+  return display_mode;
+}
+
+int vtkpxGUIOrthogonalViewer::GetDisplayMode3D()
+{
+  if (display_mode==2 || display_mode==6 || display_mode==7)
+    return 1;
+  else
+    return 0;
+}
+
+void vtkpxGUIOrthogonalViewer::SetDisplayMode3D()
+{
+  AdjustViewports(6);
+}
+
+void vtkpxGUIOrthogonalViewer::SetDisplayMode3DIfNeeded()
+{
+  if (display_mode !=2 && display_mode!=6 && display_mode!=7)
+    this->AdjustViewports(6);
+}
+
+
+void vtkpxGUIOrthogonalViewer::SetDisplayMode2D()
+{
+  AdjustViewports(1);
+}
+// ---------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::UpdateKeyRenderer()
+{
+  this->AdjustViewports(this->display_mode);
+}
+// ---------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::AdjustViewports(int mode)
+{
+  if (!this->Initialized)
+    {
+      return;
+    }
+
+
+  // Force 3d Mode if no image to anchor other views 
+  if (!hasImage)
+    {
+      mode=1; 
+    }
+
+  display_mode=Irange(mode,0,7);
+  if (displayMode->getIndex()!=display_mode)
+    displayMode->setIndex(display_mode);
+
+  double sp[3];    
+  int dim[3];   
+  double len[3];
+  double ori[3];
+
+  if (hasImage && (display_mode<=2 || display_mode==7))
+    {
+      currentImage->GetSpacing(sp);
+      currentImage->GetOrigin(ori);
+      currentImage->GetDimensions(dim);
+    }
+
+  for (int ia=0;ia<=2;ia++)
+      len[ia]=sp[ia]*float(dim[ia]);
+
+  // Eliminate all renderers first 
+
+  for (int i=0;i<=3;i++)
+    {
+      renderer[i]->SetViewport(0.99999,0.9999,1.0,1.0);
+      render_widget->getRenderWindow()->GetRenderers()->RemoveItem(renderer[i]->GetRenderer());
+    }
+  this->KeyRenderer->SetViewport(0.99,0.99,1.0,1.0);
+  render_widget->getRenderWindow()->GetRenderers()->RemoveItem(this->KeyRenderer);
+
+  double yvalues[2] = { 0.05,0.525 };
+  if (this->ShowKeyRenderer==0)
+    {
+      yvalues[0]=0.0;
+      yvalues[1]=0.5;
+
+    }
+  else
+    {
+      render_widget->getRenderWindow()->GetRenderers()->AddItem(this->KeyRenderer);      
+      this->KeyRenderer->SetViewport(0.0,0.0,1.0,0.05);
+    }
+  render_widget->getRenderWindow()->GetRenderers()->InitTraversal();
+      
+  // Three types of modes 3-slice 4-renderers 1-renderer
+
+
+  if (display_mode>2 && display_mode!=7)
+    {
+      // Single Renderer Mode Only, things are very easy here
+      int r=display_mode-3;
+      render_widget->getRenderWindow()->AddRenderer(renderer[r]->GetRenderer());
+      renderer[r]->SetViewport(0.0, yvalues[0], 1.0, 1.0);
+    }
+
+
+  int oldstyleorient=vtkpxGUIBaseImageViewer::MapOrientationToOldStyle(this->Orientation);
+  if (this->Orientation>=40)
+    oldstyleorient+=4;
+  
+  if (display_mode==1 || display_mode==2 || display_mode==7)
+    {
+      int vr[3];
+      switch (oldstyleorient)
+	{
+	case 1:
+	  vr[0]=0; vr[1]=2; vr[2]=1;
+	  break;
+	case 0:
+	  vr[0]=0; vr[1]=1; vr[2]=2;
+	  break;
+	case 2:
+	  vr[0]=2; vr[1]=0; vr[2]=1;
+	  break;
+	case 3:
+	  vr[0]=2; vr[1]=1; vr[2]=0;
+	  break;
+
+	case 4: // Transposed Axial OK
+	  vr[0]=1; vr[1]=0; vr[2]=2;
+	  break;
+	case 5: // Tranposed Coronal
+	  vr[0]=1; vr[1]=2; vr[2]=0;
+	  break;
+	case 6: // tranposed to come
+	  vr[0]=2; vr[1]=1; vr[2]=0;
+	  break;
+
+	}
+
+      for (int r=0;r<=2;r++)
+	{
+	  render_widget->getRenderWindow()->AddRenderer(renderer[r]->GetRenderer());
+	}
+      
+      if (display_mode==2)
+	{
+	  render_widget->getRenderWindow()->AddRenderer(renderer[3]->GetRenderer());
+	  renderer[vr[0]]->SetViewport(0.5, 0.7, 0.8, 1.0);
+	  renderer[vr[1]]->SetViewport(0.0, 0.7, 0.3, 1.0);
+	  renderer[vr[2]]->SetViewport(0.0, 0.2, 0.3, 0.5);
+	  renderer[3]->SetViewport(0.3, yvalues[0], 1.0, 0.7);
+	}  
+      else if (display_mode == 7 )
+	{
+	  render_widget->getRenderWindow()->AddRenderer(renderer[3]->GetRenderer());
+	  renderer[vr[0]]->SetViewport(0.5, yvalues[1], 1.0, 1.0);
+	  renderer[vr[1]]->SetViewport(0.0, yvalues[1], 0.5, 1.0);
+	  renderer[vr[2]]->SetViewport(0.0, yvalues[0], 0.5, yvalues[1]);
+	  renderer[3]->SetViewport(0.5,yvalues[0],1.0,yvalues[1]);
+	}
+      else
+	{
+	  renderer[vr[0]]->SetViewport(0.5, yvalues[1], 1.0, 1.0);
+	  renderer[vr[1]]->SetViewport(0.0, yvalues[1], 0.5, 1.0);
+	  renderer[vr[2]]->SetViewport(0.0, yvalues[0],  0.5, yvalues[1]);
+	}
+    } 
+
+  if (display_mode==0)
+    {
+      for (int r=0;r<=2;r++)
+	render_widget->getRenderWindow()->AddRenderer(renderer[r]->GetRenderer());
+
+      float r1,r2;
+      r1=len[1]/(len[1]+2*len[0]);
+      r2=r1+len[0]/(len[1]+2*len[0]);
+
+
+      renderer[0]->SetViewport( 0.0, yvalues[0] , r1 , 1.0);
+      renderer[1]->SetViewport(  r1, yvalues[0] , r2 , 1.0);
+      renderer[2]->SetViewport(  r2, yvalues[0] , 1.0, 1.0);
+    }
+
+
+  for (int kk=3;kk>=0;kk-=1)
+    {
+      if (display_mode==2 || display_mode==6 )
+	renderer[kk]->HideLabel();
+      else
+	renderer[kk]->ShowLabel();
+      renderer[kk]->SetAutoZoom(1.0);
+      renderer[kk]->Reset();
+    }
+
+
+
+  if (hasImage==PXTrue)
+    {
+      MoveAxis(1);
+    }
+  else 
+    {
+      this->UpdateDisplay();
+    }
+
+
+     
+}  
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::SetOffset(int of)
+{
+  if (this->Initialized==0)
+      this->offset=of;
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::InitControls(int )
+{
+  viewerFrame2->setPackMode(PXTrue);
+
+  PXTkFrame* sideFrame=new PXTkFrame(this->EventManager,viewerFrame2);
+  sideFrame->setPackMode(PXFalse);
+  
+  if (viewerFrame==viewerFrame2)
+    {
+      viewerFrame2->addChildren("-side right -expand false -fill y",sideFrame);
+      PXTkButton* hideButton=new PXTkButton(this->EventManager,sideFrame,"x",350);
+      hideButton->configure("-bg","white");
+      hideButton->configure("-fg","black");
+      hideButton->configure("-width","1");
+      sideFrame->gridRowColumnChild(hideButton,0,1);
+      sideFrame->childConfigure(hideButton,"-padx","0");
+      sideFrame->childConfigure(hideButton,"-pady","0");
+      sideFrame->childConfigure(hideButton,"-ipadx","0");
+      sideFrame->childConfigure(hideButton,"-ipady","0");
+      sideFrame->childConfigure(hideButton,"-sticky","nw");
+    }
+  else 
+    viewerFrame2->addChildren("-side right -expand true -fill both",sideFrame);
+
+
+  sideFrame->gridExpandColumnConfigure(0,1,0,0);
+  sideFrame->gridExpandColumnConfigure(1,0,0,0);
+
+  controlFrame=new PXTkFrame(this->EventManager,sideFrame);
+
+  if (this->show_controlframe==1)
+    sideFrame->gridRowColumnChild(controlFrame,1,0,1,2);
+
+  displayMode=new PXTkOptionMenu(this->EventManager,controlFrame,"Simple Mode",307);
+  displayMode->addOption("3-Slice Mode");
+  displayMode->addOption("3-Slice+3D Mode");
+  displayMode->addOption("Coronal Only");
+  displayMode->addOption("Axial Only");
+  displayMode->addOption("Sagittal Only");
+  displayMode->addOption("3D Only");
+  displayMode->addOption("3-Slice+3D Mode(2)");
+
+  displayMode->setIndex(display_mode);
+  PXTkFrame* threedframe=new PXTkFrame(this->EventManager,controlFrame);
+  PXTkFrame* threedframe2=new PXTkFrame(this->EventManager,controlFrame);
+
+
+  display3DMode=new PXTkOptionMenu(this->EventManager,threedframe,"None",331);
+  display3DMode->addOption("3-slice");
+  display3DMode->addOption("Volume");
+  display3DMode->addOption("Oblique");
+  display3DMode->addOption("Obl+Vol");
+  display3DMode->addOption("Obl+3-s");
+  display3DMode->addOption("3-s+vol");
+  display3DMode->addOption("3s+vl+o");
+
+  display3DMode->setIndex(display3d_mode);
+
+  display3DAxisOutlineMode=new PXTkOptionMenu(this->EventManager,threedframe,"None",332);
+  display3DAxisOutlineMode->addOption("Box");
+  display3DAxisOutlineMode->addOption("Axis");
+  display3DAxisOutlineMode->addOption("Both");
+  display3DAxisOutlineMode->setIndex(display3d_axisoutlinemode);
+
+  PXTkButton* b1h=new PXTkButton(this->EventManager,threedframe2,"Volume",330);
+  PXTkButton* b1h2=new PXTkButton(this->EventManager,threedframe2,"Oblique",333);
+  threedframe->addChildren("-side left -expand t -fill x -padx 0",display3DMode,display3DAxisOutlineMode);
+  threedframe2->addChildren("-side left -expand t -fill x -padx 0",b1h,b1h2);
+  controlFrame->addChildren("-side top -expand false -fill x",displayMode,threedframe,threedframe2);
+
+
+  // CheckButton Frame 
+  PXTkFrame* checkFrame=new PXTkFrame(this->EventManager,controlFrame);
+  controlFrame->addChildren("-side top -expand false -fill x",checkFrame);
+  checkFrame->setPackMode(PXFalse);
+
+
+  interpolateMode=new PXTkCheckButton(this->EventManager,checkFrame,"Interp",300);
+  interpolateMode->setState(PXTrue);
+  interpolateMode->configure("-padx","0");
+  checkFrame->gridRowColumnChild(interpolateMode,0,2);
+
+
+  this->showPointer=new PXTkCheckButton(this->EventManager,checkFrame,"-P-",318);
+  showPointer->setState(PXFalse);
+  showPointer->configure("-padx","0");
+  checkFrame->gridRowColumnChild(showPointer,0,3);
+
+
+  freezeMode=new PXTkCheckButton(this->EventManager,checkFrame,"x-hairs",308);
+  if (this->MouseSliceChangeMode)
+    freezeMode->setState(PXTrue);
+  else
+    freezeMode->setState(PXFalse);
+  freezeMode->configure("-padx","0");
+  checkFrame->gridRowColumnChild(freezeMode,0,0);
+
+
+  showaxisc=new PXTkCheckButton(this->EventManager,checkFrame,"Lb",317);
+  showaxisc->setState(PXTrue);
+  showaxisc->configure("-padx","0");
+  checkFrame->gridRowColumnChild(showaxisc,0,1);
+
+
+  // Talairach Frame 
+  PXTkFrame* tframe=new PXTkFrame(this->EventManager,controlFrame);
+  controlFrame->addChildren("-side top -expand true -fill x",tframe);
+
+  talairachlabel=new PXTkLabel(this->EventManager,tframe,"");
+  talairachlabel->configure("-bg","black");
+  talairachlabel->configure("-fg","white");
+  talairachlabel->configure("-width","20");
+  talairachlabel->configure("-padx","0");
+  tframe->addChildren("-side left -expand true -fill x -padx 2",talairachlabel);
+
+  if (this->createTalairachButtons)
+    {
+      PXTkFrame* tframe2=new PXTkFrame(this->EventManager,controlFrame);
+      controlFrame->addChildren("-side top -expand true -fill x",tframe2);
+
+      PXTkButton*   talairachButton[2];
+      talairachButton[0]=new PXTkButton(this->EventManager,tframe2,"Tal",320);
+      talairachButton[0]->configure("-pady","0");
+      talairachButton[0]->configure("-padx","1");
+      talairachButton[0]->configure("-fg","red");
+      talairachButton[1]=new PXTkButton(this->EventManager,tframe2,"Tal NEU",322);
+
+
+      //      talairachButton[1]->configure("-pady","0");
+      //      talairachButton[1]->configure("-padx","1");
+
+
+      mnilabel=new PXTkLabel(this->EventManager,tframe2,"");
+      mnilabel->configure("-bg","black");
+      mnilabel->configure("-fg","white");
+      mnilabel->configure("-width","15");
+      mnilabel->configure("-padx","0");
+      //      tframe2->addChildren("-side right -expand false",talairachButton[1],talairachButton[0]);
+      //      tframe2->addChildren("-side right -expand false",talairachButton[0]);
+      tframe2->addChildren("-side left -expand true -fill x -padx 2",mnilabel);
+    }
+
+
+  extraFrame=new PXTkFrame(this->EventManager,controlFrame);
+  coordScaleFrame=new PXTkFrame(this->EventManager,controlFrame);
+  controlFrame->addChildren("-side top -expand true -fill x",extraFrame,coordScaleFrame);
+
+  for (int k=0;k<=3;k++)
+      {
+	switch(k)
+	    {
+	    case 0:
+	      strcpy(pxtk_buffer4,"i-Coord:"); break;
+	    case 1:
+	      strcpy(pxtk_buffer4,"j-Coord:"); break;	 
+	    case 2:
+	      strcpy(pxtk_buffer4,"k-Coord:"); break;
+	    case 3:
+	      strcpy(pxtk_buffer4,"Frame:"); break;
+	    }
+	if (k!=3)
+	  {
+	    coordScale[k]=new PXTkArrowScale(this->EventManager,coordScaleFrame,pxtk_buffer4,302,PXTrue);
+	    coordScale[k]->setRange(0.0+offset,1.0+offset);
+	  }
+	else
+	  {
+	    coordScale[k]=new PXTkArrowScale(this->EventManager,coordScaleFrame,pxtk_buffer4,301,PXTrue);
+	    coordScale[k]->setRange(1,10);
+	  }
+	coordScale[k]->setValue(float(0.0));
+	coordScale[k]->setLengthWidth(120,10);
+	coordScale[k]->setIncrement(1.0);
+	coordScale[k]->setResolution(1.0);
+	coordScaleFrame->addChildren("-side top -expand false -fill x",coordScale[k]->getMainWindow());
+	if (k==3 && this->CurrentImageIsColor==1)
+	  this->ShowFrameControls(0);
+      }
+
+
+	
+  PXTkFrame* colFrame=new PXTkFrame(this->EventManager,controlFrame);
+  PXTkButton* b1c0=new PXTkButton(this->EventManager,colFrame,"St",309);
+  PXTkButton* b1c=new PXTkButton(this->EventManager,colFrame,"Nr",310);
+  PXTkButton* b1d=new PXTkButton(this->EventManager,colFrame,"F1",311);
+  PXTkButton* b1e=new PXTkButton(this->EventManager,colFrame,"F2",312);
+  PXTkButton* b1f2=new PXTkButton(this->EventManager,colFrame,"F4",314);
+  PXTkButton* b1g=new PXTkButton(this->EventManager,colFrame,"Cmap",303);
+
+  b1c0->configure("-padx",1);
+  b1c->configure("-padx",1);
+  b1d->configure("-padx",1);
+  b1e->configure("-padx",1);
+  b1f2->configure("-padx",1);
+
+
+  colFrame->addChildren("-side left -expand f ",b1c0,b1c);
+  colFrame->addChildren("-side left -expand f ",b1d,b1e,b1f2);
+  colFrame->addChildren("-side right -expand true -fill x",b1g);
+  PXTkDualArrowLabel* zoom=new PXTkDualArrowLabel(this->EventManager,controlFrame,"Zoom",304,305,0);
+  PXTkFrame* botFrame=new PXTkFrame(this->EventManager,controlFrame);
+  controlFrame->addChildren("-side top -expand true -fill both",colFrame,zoom,botFrame);
+  PXTkButton* b1=new PXTkButton(this->EventManager,botFrame,"Reset",306);
+  PXTkButton* b2=new PXTkButton(this->EventManager,botFrame,"Save Snapshot",315);
+  saveAllButton=new PXTkButton(this->EventManager,botFrame,"Save All",316);
+  controlFrame->addChildren("-side left -expand true -fill both",b1,b2);
+}
+
+// -------------------------------------------------------------------------
+
+vtkpxGUIRenderer* vtkpxGUIOrthogonalViewer::GetRenderer(int i)
+{
+  return renderer[Irange(i,0,3)];
+}
+
+vtkpxImageSlice* vtkpxGUIOrthogonalViewer::GetImageSlice(int i)
+{
+  return imageSlice[Irange(i,0,2)];
+}
+
+vtkpxOrthoImageSlice* vtkpxGUIOrthogonalViewer::GetOrthoImageSlice()
+{
+  return orthoSlice;
+}
+
+vtkpxObliqueImageSlice* vtkpxGUIOrthogonalViewer::GetObliqueImageSlice()
+{
+  return this->obliqueSlice;
+}
+
+vtkpxGUIObliqueImageSliceControl*  vtkpxGUIOrthogonalViewer::GetObliqueControl()
+{
+  return this->ObliqueControl;
+}
+
+vtkpxGUIVolumeControl*  vtkpxGUIOrthogonalViewer::GetVolumeControl()
+{
+  return this->VolumeControl;
+}
+
+vtkActor* vtkpxGUIOrthogonalViewer::GetOutlineActor(int i)
+{
+  return outline[Irange(i,0,3)];
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::SetOrthoSliceVisibility(int orthovis)
+{
+  this->OrthoSliceVisibility=orthovis>0;
+  if (hasImage)
+    {
+      if (orthoSlice!=NULL)
+	{
+	  orthoSlice->SetDisplayMode(3);
+	  orthoSlice->SetVisibility(this->OrthoSliceVisibility);
+	}
+    }
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::SetVolumeVisibility(int volvis)
+{
+  volvis=volvis>0;
+  if (hasImage)
+    {
+      if (this->VolumeControl!=NULL)
+	this->VolumeControl->SetVisibility(volvis);
+      if (volvis>0)
+	this->Volume->Update();
+      
+    }
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::SetObliqueSliceVisibility(int oblvis)
+{
+  oblvis=oblvis>0;
+  if (hasImage)
+    {
+      if (this->ObliqueControl!=NULL) 
+	this->ObliqueControl->SetVisibility(oblvis);
+    }
+}
+// -------------------------------------------------------------------------
+char* vtkpxGUIOrthogonalViewer::GetRenderWidgetName()
+{
+  if (this->render_widget==NULL)
+    return NULL;
+  else
+    return this->render_widget->getWidgetName();
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::SetMouseSliceChangeMode(int m)
+{
+  m=(m>0);
+  if (m==this->MouseSliceChangeMode)
+    return;
+
+  this->MouseSliceChangeMode=m;
+  if (!this->Initialized)
+      return;
+
+  if (this->MouseSliceChangeMode)
+    freezeMode->setState(PXTrue);
+  else
+    freezeMode->setState(PXFalse);
+}
+// -------------------------------------------------------------------------
+char* vtkpxGUIOrthogonalViewer::GetControlFrameName()
+{
+  if (this->controlFrame!=NULL)
+    return this->controlFrame->getWidgetBaseName();
+  else
+    return NULL;
+
+}
+
+char* vtkpxGUIOrthogonalViewer::GetViewerFrameName()
+{
+  if (this->viewerFrame!=NULL)
+    return this->viewerFrame->getWidgetBaseName();
+  else
+    return NULL;
+}
+
+
+void  vtkpxGUIOrthogonalViewer::SetShowControls(int show)
+{
+  show=(show>0);
+  if (show==this->show_controlframe)
+    return;
+
+  this->show_controlframe=show;
+
+  PXTkFrame* fr=(PXTkFrame*)controlFrame->getGadgetParent();
+  if (this->controlFrame!=NULL && fr!=NULL)
+    {
+      if (this->show_controlframe==1)
+	fr->gridRowColumnChild(controlFrame,1,0,4,4);
+      else
+	fr->unmapChild(controlFrame);
+    }
+}
+// -------------------------------------------------------------------------
+
+int vtkpxGUIOrthogonalViewerinBounds(float p[3],float bounds[6])
+{
+  if (p[0]<bounds[0] || p[0]>bounds[1] ||
+      p[1]<bounds[2] || p[1]>bounds[3] ||
+      p[2]<bounds[4] || p[2]>bounds[5])
+    return 0;
+  else
+    return 1;
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::VolumePick(int clickx, int clicky, vtkRenderer* pick_renderer)
+{
+  if (!hasImage)
+    return 0;
+
+  if (this->Volume==NULL)
+    return 0;
+
+
+  int   dim[3];     currentImage->GetDimensions(dim);
+  double sp[3];      currentImage->GetSpacing(sp);
+  double ori[3];     currentImage->GetOrigin(ori);
+  int   boundsv[6]; this->Volume->GetCroppingRange(boundsv);
+
+  float searchdim=Fmin(sp[0],Fmin(sp[1],sp[2]));
+
+  switch(this->TraceVolumeToleranceMode)
+    {
+    case 0:
+      searchdim*=2.0;
+      break;
+    case 2:
+      searchdim/=2.0;
+      break;
+    default:
+      searchdim*=1.0;
+      break;
+    }
+  
+  int i;
+  
+  float SelectionPoint[3];
+  SelectionPoint[0] = float(clickx);
+  SelectionPoint[1] = float(clicky);
+  SelectionPoint[2] = 0.0;
+  
+  float selectionX=SelectionPoint[0];
+  float selectionY=SelectionPoint[1];
+  float selectionZ=SelectionPoint[2];
+  
+  // Get camera focal point and position. Convert to display (screen) 
+  // coordinates. We need a depth value for z-buffer.
+  vtkCamera* camera = pick_renderer->GetActiveCamera();
+  double cameraPos[4], cameraFP[4];
+  camera->GetPosition((double *)cameraPos);  cameraPos[3] = 1.0;
+  camera->GetFocalPoint((double *)cameraFP); cameraFP[3] = 1.0;
+  
+  pick_renderer->SetWorldPoint(cameraFP);
+  pick_renderer->WorldToDisplay();
+  double* displayCoords = pick_renderer->GetDisplayPoint();
+  selectionZ = displayCoords[2];
+  
+  // Convert the selection point into world coordinates.
+  pick_renderer->SetDisplayPoint(selectionX, selectionY, selectionZ);
+  pick_renderer->DisplayToWorld();
+  double* worldCoords = pick_renderer->GetWorldPoint();
+  float PickPosition[4];
+  for (i=0; i < 3; i++) 
+    PickPosition[i] = worldCoords[i] / worldCoords[3];
+  
+  //  Compute the ray endpoints.  The ray is along the line running from
+  //  the camera position to the selection point, starting where this line
+  //  intersects the front clipping plane, and terminating where this
+  //  line intersects the back clipping plane.
+  double ray[3], rayLength;
+  for (i=0; i<3; i++)
+    ray[i] = PickPosition[i] - cameraPos[i];
+  
+  double cameraDOP[3];
+  for (i=0; i<3; i++)
+    cameraDOP[i] = cameraFP[i] - cameraPos[i];
+  vtkMath::Normalize(cameraDOP);
+  
+  if (( rayLength = vtkMath::Dot(cameraDOP,ray)) == 0.0 ) 
+    return 0;
+  
+  double* clipRange = camera->GetClippingRange();
+  double tF, tB;
+  double p1World[3], p2World[3];
+  
+  if ( camera->GetParallelProjection() )
+    {
+      tF = clipRange[0] - rayLength;
+      tB = clipRange[1] - rayLength;
+      for (i=0; i<3; i++) 
+	{
+	  p1World[i] = PickPosition[i] + tF*cameraDOP[i];
+	  p2World[i] = PickPosition[i] + tB*cameraDOP[i];
+	}
+    }
+  else
+    {
+      tF = clipRange[0] / rayLength;
+      tB = clipRange[1] / rayLength;
+      for (i=0; i<3; i++) 
+	{
+	  p1World[i] = cameraPos[i] + tF*ray[i];
+	  p2World[i] = cameraPos[i] + tB*ray[i];
+	}
+    }
+  
+  
+  // Probe to Find Point
+  // -------------------
+  double tlength=sqrt(vtkMath::Distance2BetweenPoints(p1World,p2World));
+  int   numsegments=int(tlength/searchdim);
+  if (numsegments<10)
+    numsegments=10;
+
+  vtkLineSource* ln=vtkLineSource::New();
+  ln->SetResolution(numsegments);
+  ln->SetPoint1(p1World);
+  ln->SetPoint2(p2World);
+  ln->Update();
+
+  int found=0,index=0,lvs[3];
+  double vl=0.0;
+  vtkPoints* pt=ln->GetOutput()->GetPoints();
+  int np=pt->GetNumberOfPoints();
+
+  while (index<np && found == 0 )
+    {
+      double p[3];
+      pt->GetPoint(index,p);
+      for (int ik=0;ik<=2;ik++)
+	lvs[ik]=int(p[ik]/sp[ik]-ori[ik]);
+	      
+      if (lvs[0]>=boundsv[0] && lvs[0]<=boundsv[1]  &&
+	  lvs[1]>=boundsv[2] && lvs[1]<=boundsv[3]  &&
+	  lvs[2]>=boundsv[4] && lvs[2]<=boundsv[5])
+	{
+	  vl=this->currentImage->GetScalarComponentAsDouble(lvs[0],lvs[1],lvs[2],0);
+	  if (vl>0.0)
+	    found=1;
+	}
+      ++index;
+    }
+  ln->Delete();
+
+  
+  if (found)
+    {
+      double lvv[3];
+      // -------------- Electrode ---------------
+      if (this->TraceVolumeVOI>0 )
+	this->FindCentroid(this->currentImage,lvs,lvv,this->TraceVolumeVOI);
+      // -------------- Electrode ---------------
+      
+      if (this->MouseSliceChangeMode)
+	this->SetCoordinates(lvs[0],lvs[1],lvs[2]);
+      else 
+	this->UpdateDisplay();
+
+      if (this->TraceVolumeVOI>0 )
+	this->SetLastClickedPoint(lvv);
+    }
+  
+  
+  return (found);
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::GeometryPick(int clickx, int clicky, vtkRenderer* pick_renderer)
+{
+  double ori[3],sp[3];
+
+  if (!hasImage)
+    {
+      for (int ia=0;ia<=2;ia++)
+	{
+	  ori[ia]=0.0; sp[ia]=1.0;
+	}
+    }
+  else
+    {
+      currentImage->GetOrigin(ori);
+      currentImage->GetSpacing(sp);
+    }
+
+  vtkCellPicker* picker=vtkCellPicker::New();
+  picker->SetTolerance(0.005);
+
+  int ok=picker->Pick(float(clickx),float(clicky),float(0.0),pick_renderer);
+  if (ok)
+    {
+      double lvv[3], lvs[3];
+      picker->GetPickPosition(lvv);
+      picker->Delete();
+     
+      for (int ic=0;ic<=2;ic++)
+	lvs[ic]=(lvv[ic]-ori[ic])/sp[ic];
+            
+      if (this->MouseSliceChangeMode && hasImage)
+	this->SetCoordinates((int)lvs[0],(int)lvs[1],(int)lvs[2],0);
+
+      this->SetLastClickedPoint(lvv);
+      this->SetLastClickedPointScaled(lvs);
+
+    }
+  /*  else
+      fprintf(stderr,"Failed to find point\n");*/
+  return (ok);
+}
+// -------------------------------------------------------------------------
+//   The Following is overriden in vtkpxGUIOrthogonal4DViewer
+// -------------------------------------------------------------------------
+
+
+int vtkpxGUIOrthogonalViewer::InitializeViewer()
+{
+  if ((!hasImage && this->Initialized))
+      return 0;
+
+
+  this->ColormapEditor=vtkpxGUIColormapEditor::New();
+  this->ColormapEditor->SetSimpleMode(0);
+  this->ColormapEditor->SetCallback(this,201);
+  this->ColormapEditor->Initialize(this->GetWidgetName(),0);
+
+ 
+  for (int k=0;k<=2;k++)
+      {
+	imageSlice[k]=vtkpxImageSlice::New();
+	imageSlice[k]->SetAutoUpdate(0);
+	imageSlice[k]->SetInput(currentImage);
+	imageSlice[k]->SetFrame(0);
+	imageSlice[k]->SetCurrentPlane(k);
+	imageSlice[k]->PickableOff();
+	imageSlice[k]->SetColorMode(this->CurrentImageIsColor);
+	renderer[k]->GetRenderer()->AddActor(imageSlice[k]);
+      }
+
+  orthoSlice=vtkpxOrthoImageSlice::New();
+  orthoSlice->SetAutoUpdate(0);
+  orthoSlice->SetInput(currentImage);
+  orthoSlice->SetColorMode(this->CurrentImageIsColor);
+  orthoSlice->SetFrame(0);
+  orthoSlice->PickableOff();
+  renderer[3]->GetRenderer()->AddActor(orthoSlice);
+  orthoSlice->SetVisibility(this->OrthoSliceVisibility);
+
+
+  obliqueSlice=vtkpxObliqueImageSlice::New();
+  obliqueSlice->SetAutoUpdate(0);
+  obliqueSlice->SetInput(currentImage);
+  obliqueSlice->SetColorMode(this->CurrentImageIsColor);
+  obliqueSlice->SetFrame(0);
+  obliqueSlice->SetVisibility(0);
+  obliqueSlice->PickableOff();
+  this->ObliqueControl->SetObliqueImageSliceRenderer(this->obliqueSlice,renderer[3]);
+  renderer[3]->GetRenderer()->AddActor(obliqueSlice);
+  obliqueSlice->SetAutoUpdate(1);
+
+ 
+  /*  Vol Commented*/
+  this->Volume=vtkpxVolume::New();
+  this->Volume->SetInput(currentImage,this->Orientation);
+  this->Volume->SetFrame(0);
+  this->Volume->SetVisibility(0);
+  this->VolumeControl->SetVolumeRenderer(this->Volume,renderer[3]);
+  this->Volume->Update();
+  renderer[3]->GetRenderer()->AddVolume(this->Volume); 
+
+   /*  Volume2 Commented*/
+  /*  this->Volume2=vtkpxVolume::New();
+  this->Volume2->SetInput(currentImage,this->Orientation);
+  this->Volume2->SetFrame(0);
+  this->Volume2->SetVisibility(0);
+  this->VolumeControl->SetVolumeRenderer(this->Volume2,renderer[3]);
+  this->Volume2->Update();
+  renderer[3]->GetRenderer()->AddVolume(this->Volume2); 
+  printf("added 2nd volume\n"); */
+  
+  
+  for (int i=0;i<=3;i++)
+      {
+	outlineFilter[i]=vtkOutlineFilter::New();
+	outlineFilter[i]->SetInput(currentImage);
+	
+	vtkPolyDataMapper *mapOutline = vtkPolyDataMapper::New();
+	mapOutline->SetInput(outlineFilter[i]->GetOutput());
+	
+	outline[i] = vtkActor::New();
+	outline[i]->SetMapper(mapOutline);
+	outline[i]->GetProperty()->SetColor(0.0,1.0,0.0);
+	outline[i]->GetProperty()->SetAmbient(1.0);
+	outline[i]->GetProperty()->SetDiffuse(0.0);
+	outline[i]->GetProperty()->SetSpecular(0.0);
+	outline[i]->GetProperty()->SetRepresentationToWireframe();
+	outline[i]->PickableOff();
+	//	outline[i]->GetProperty()->SetOpacity(0.8);
+
+	if (i!=3)
+	  {
+	    renderer[i]->GetRenderer()->AddActor(outline[i]);
+	  }
+	else
+	  {
+	    vtkAssembly* ass=vtkAssembly::New();
+	    ass->AddPart(outline[i]);
+	    renderer[i]->GetRenderer()->AddActor(ass);
+	    ass->Delete();
+	  }
+	//	outline->Delete();
+	mapOutline->Delete();
+
+	switch(i)
+	    {
+	    case 0:
+	      renderer[i]->SetLabel("Coronal-jk",0.05,0.05,0.73,0.73,0.0);
+	      break;
+	    case 1:
+	      renderer[i]->SetLabel("Axial-ik",0.05,0.05,0.73,0.73,0.0);
+	      break;
+	    case 2:
+	      renderer[i]->SetLabel("Sagittal-ij",0.05,0.05,0.73,0.73,0.0);
+	      break;
+	    case 3:
+	      //renderer[i]->SetTitle("3D View");
+	      break;
+	    }
+      }
+
+  this->SetDisplay3DMode(display3d_mode);
+  this->SetDisplay3DAxisOutlineMode(display3d_axisoutlinemode);
+  AdjustViewports(display_mode);
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIOrthogonalViewer::CreateNavigationPointer()
+{
+  vtkPolyData *point = vtkPolyData::New();
+  
+
+ 
+  vtkmyPWCallback* pointcallback= vtkmyPWCallback::New();
+  pointcallback->Viewer=this;
+
+  this->NavigationPointer = vtkLineWidget::New();
+  this->NavigationPointer->SetInteractor(this->WidgetInteractor);
+  this->NavigationPointer->SetInput(this->currentImage);
+  this->NavigationPointer->SetPoint1(0,0,0);
+  this->NavigationPointer->SetPoint2(20,20,20);
+  this->NavigationPointer->SetResolution(1);
+  //  this->NavigationPointer->PlaceWidget();
+  this->NavigationPointer->AddObserver(vtkCommand::InteractionEvent,pointcallback);
+  this->UpdateNavigationActorGeometry();
+
+  double plocation[3] = {20.0, 20.0, 20.0};
+  this->Volume->SetProbeLocation(plocation);
+  this->Volume->Update();
+
+  return 1;
+}
+
+int vtkpxGUIOrthogonalViewer::MoveNavigationPointer()
+{
+  if (this->NavigationPointer==NULL)
+    return 0;
+
+  // In mm
+  double lvs[3]; this->GetLastClickedPointScaled(lvs);
+
+  // in voxels
+  double lvv[3]; this->GetLastClickedPoint(lvv);
+  int dim[3]; this->currentImage->GetDimensions(dim);
+  double spa[3]; this->currentImage->GetSpacing(spa);
+
+  double pos[3] = { 0.0,0.0,0.0};
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (lvv[ia]>dim[ia]/2)
+	pos[ia]=double(dim[ia]-1.0)*spa[ia];
+    }
+
+  this->NavigationPointer->SetPoint2(lvs);
+  this->NavigationPointer->SetPoint1(pos);
+  this->UpdateNavigationActorGeometry(1);
+
+return 1;
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIOrthogonalViewer::InitViewer()
+{
+  render_widget=new PXVTkTkRenderWidget(this->EventManager,viewerFrame,200);
+  render_widget->setWidthHeight(400,400);
+  render_widget->bindMouseEvents();
+  viewerFrame->addChildren("-side left -expand true -fill both",render_widget);
+  
+  // Background renderer 
+  //  render_widget->getRenderWindow()->DebugOn();
+
+  /*  vtkRenderWindow* rw=render_widget->getRenderWindow();
+      fprintf(stderr,"swap buffers=%d\n",rw->GetSwapBuffers());*/
+
+  //  render_widget->getRenderWindow()->SetNumberOfLayers(2);
+
+  this->KeyRenderer->SetViewport(0.0,0.0,1.0,0.001);
+  this->KeyRenderer->SetBackground(0.2,0.2,0.2);
+  //  this->KeyRenderer->SetLayer(0.0);
+  render_widget->getRenderWindow()->AddRenderer(this->KeyRenderer);
+
+
+  for (int ia=1;ia>=0;ia=ia-1)
+      {
+	for (int ib=1;ib>=0;ib-=1)
+	  {
+	    int index=ia*2+ib;
+	    vtkRenderer* ren=vtkRenderer::New();
+	    ren->SetLayer(0);
+	    // ren->TwoSidedLightingOff();
+	    render_widget->getRenderWindow()->AddRenderer(ren);
+	    renderer[index]=vtkpxGUIRenderer::New();
+	    renderer[index]->SetAutoZoom(1.0);
+	    renderer[index]->SetFlipMode(0);
+	    if (index!=3)
+	      {
+		renderer[index]->SetNoGUI(PXTrue);
+		renderer[index]->SetPlaneMode(Irange(index,0,2));
+		renderer[index]->SetClipMode(PXTrue);
+		renderer[index]->SetClipThickness(2.0);
+		renderer[index]->SetEnableActorTransform(0);
+	      }
+	    else
+	      {
+		renderer[index]->SetClipMode(PXFalse);
+		renderer[index]->SetClipThickness(0.25);
+		renderer[index]->SetVerticalDecoration(PXFalse);
+		renderer[index]->SetEnableActorTransform(1);
+	      }
+	    renderer[index]->Initialize(viewerFrame->getWidgetName(),ren,0);
+	    renderer[index]->SetViewport((ia)*0.5,(1-ib)*0.475+0.05,(1+ia)*0.5,(2-ib)*0.475+0.05);
+	    renderer[index]->Reset();
+	  }
+      }
+
+  this->BackgroundRenderer=vtkRenderer::New();
+  render_widget->getRenderWindow()->AddRenderer(this->BackgroundRenderer);
+  //  this->BackgroundRenderer->SetLayer(1);
+  //  this->BackgroundRenderer->SetBackground(00.,0.2,0.0);
+  this->BackgroundRenderer->SetViewport(0.0,0.0,1.0,1.0);
+
+
+  this->WidgetInteractor=vtkGenericRenderWindowInteractor::New();
+  this->WidgetInteractor->SetRenderWindow(render_widget->getRenderWindow());
+  this->WidgetInteractor->SetInteractorStyle(NULL);
+
+  this->WidgetInteractor->Initialize();
+  vtkInteractorObserver* obs=this->WidgetInteractor->GetInteractorStyle();
+  this->UpdateDisplay();
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::ChangeSliceLevels(int lv[3],int infoonly)
+{
+  if (this->Initialized==0 || !hasImage)
+    return;
+
+  double sp[3];    currentImage->GetSpacing(sp);
+  double ori[3];   currentImage->GetOrigin(ori);
+
+  if (infoonly==0)
+    {
+      for (int ia=0;ia<=2;ia++)
+	imageSlice[ia]->SetLevel(lv[ia]);
+      orthoSlice->SetLevels(lv[0],lv[1],lv[2]);
+    }
+
+  double lvv[3],lvs[3];
+  for (int ic=0;ic<=2;ic++)
+    {
+      lvv[ic]=float(lv[ic]);
+      lvs[ic]=lvv[ic]*sp[ic]+ori[ic];
+    }
+  this->SetLastClickedPoint(lvv);
+  this->SetLastClickedPointScaled(lvs);
+
+  if (infoonly==0)
+    {
+      MoveAxis(1);
+    }
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::ChangeFrame(int newframe)
+{
+  if (this->Initialized==0 || !hasImage)
+    return;
+
+  if (newframe==this->CurrentFrame)
+    return;
+   
+  this->CurrentFrame=Irange(newframe,0,this->NumberOfFrames-1);
+  for (int ia=0;ia<=2;ia++)
+    imageSlice[ia]->SetFrame(this->CurrentFrame);
+  orthoSlice->SetFrame(this->CurrentFrame);
+  obliqueSlice->SetFrame(this->CurrentFrame);
+  
+
+  if (this->Volume!=NULL)
+    this->Volume->SetFrame(this->CurrentFrame);
+
+  /*  if (this->Volume2!=NULL)
+      this->Volume2->SetFrame(this->CurrentFrame);*/
+
+  this->UpdateIntensityLabelInfo();
+  this->ExecuteFrameChangeCallback();
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::SetInterpolation(int interp)
+{
+
+
+  for (int k=0;k<3;k++)
+    imageSlice[k]->SetInterpolation(interp);
+  orthoSlice->SetInterpolation(interp);
+  obliqueSlice->SetInterpolation(interp);
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::SetDisplay3DMode(int m) 
+{
+  display3d_mode=Irange(m,0,7);
+
+  switch (display3d_mode)
+    {
+    case 1: // 3-slice
+      this->SetOrthoSliceVisibility(1);
+      this->SetObliqueSliceVisibility(0);
+      this->SetVolumeVisibility(0);
+      break;
+
+    case 2: // Volume
+      this->SetOrthoSliceVisibility(0);
+      this->SetObliqueSliceVisibility(0);
+      this->SetVolumeVisibility(1);
+      break;
+
+    case 3: // Oblique
+      this->SetOrthoSliceVisibility(0);
+      this->SetObliqueSliceVisibility(1);
+      this->SetVolumeVisibility(0);
+      break;
+
+    case 4: // Oblique + Volume
+      this->SetOrthoSliceVisibility(0);
+      this->SetObliqueSliceVisibility(1);
+      this->SetVolumeVisibility(1);
+      break;
+      
+    case 5: // Oblique + 3-slice
+      this->SetOrthoSliceVisibility(1);
+      this->SetObliqueSliceVisibility(1);
+      this->SetVolumeVisibility(0);
+      break;
+
+    case 6: // 3-slice + volume
+      this->SetOrthoSliceVisibility(1);
+      this->SetObliqueSliceVisibility(0);
+      this->SetVolumeVisibility(1);
+      break;
+
+    case 7: // everything
+      this->SetOrthoSliceVisibility(1);
+      this->SetObliqueSliceVisibility(1);
+      this->SetVolumeVisibility(1);
+      break;
+
+    default: // None 
+      this->SetOrthoSliceVisibility(0);
+      this->SetObliqueSliceVisibility(0);
+      this->SetVolumeVisibility(0);
+      break;
+    }
+
+  display3DMode->setIndex(display3d_mode);  
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::SetDisplay3DAxisOutlineMode(int m)
+{
+  display3d_axisoutlinemode=Irange(m,0,3);
+
+  if (axisActor[0]!=NULL)
+    {
+      if (display3d_axisoutlinemode==0 || display3d_axisoutlinemode==1)
+	{
+	  for (int k=6;k<10;k++)
+	    axisActor[k]->SetVisibility(0);
+	}
+      else 
+	{
+	  for (int k=6;k<10;k++)
+	    axisActor[k]->SetVisibility(1);
+	}
+    }
+
+  if (outline[3]!=NULL)
+    {
+      if (display3d_axisoutlinemode==0 || display3d_axisoutlinemode==2)
+	outline[3]->SetVisibility(0);
+      else
+	outline[3]->SetVisibility(1);
+    }
+}
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::ShowCrossHairs(int mode)
+{
+  if (axisActor[0]==NULL)
+    return;
+
+  for (int k=0;k<=5;k++)
+    axisActor[k]->SetVisibility((mode>0));
+  
+  for (int j=0;j<=3;j++)
+    {
+      if (mode>0)
+        renderer[j]->ShowLabel();
+      else
+	renderer[j]->HideLabel();
+    }
+  this->MoveAxis(1);
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::ShowFrameControls(int show)
+{
+  if (!this->Initialized)
+    return;
+
+  if (show==0)
+    {
+      coordScaleFrame->unmapChild(coordScale[3]->getMainWindow());
+      controlFrame->unmapChild(saveAllButton);
+    }
+  else
+    {
+      coordScaleFrame->addChildren("-side top -expand false -fill x",coordScale[3]->getMainWindow());
+      controlFrame->addChildren("-side right -expand true -fill both",saveAllButton);
+    }
+
+  
+}
+void vtkpxGUIOrthogonalViewer::SetRendererName(vtkpxGUIRenderer* ren,const char* basename,
+					       int axis,
+					       int dmindex)
+{
+  char line[100];
+  //  fprintf(stderr,"Basename=%s orientation=%d axis=%d\n",basename,this->Orientation,axis);
+  sprintf(line,"%s",basename);
+  /*  for (int i=0;i<=2;i++)
+    {
+      if (i!=axis)
+	{
+	  switch(i)
+	    {
+	    case 0: 
+	      sprintf(line,"%s i -> %s",line,this->OrientationToAxisName(this->Orientation,i));
+	      break;
+	    case 1: 
+	      sprintf(line,"%s j -> %s",line,this->OrientationToAxisName(this->Orientation,i));
+	      break;
+	    case 2: 
+	      sprintf(line,"%s k -> %s",line,this->OrientationToAxisName(this->Orientation,i));
+	      break;
+	    }
+	}
+	}*/
+  ren->SetLabel(line,0.05,0.05,0.73,0.73,0.0);
+  if (dmindex>=0)
+    displayMode->changeLabel(dmindex,basename);
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::ResetCoordinateScalesAndLabels()
+{
+  //  fprintf(stderr,"In Reset Coordinate Scales and Labels %d\n",this->Orientation);
+  int oldstyleorient=vtkpxGUIBaseImageViewer::MapOrientationToOldStyle(this->Orientation);
+
+  if (this->Orientation>=40)
+    oldstyleorient+=4;
+
+  switch (oldstyleorient)
+    {
+    case 0: // Axial
+      this->SetRendererName(renderer[0],"Sagital-jk",0,3);
+      this->SetRendererName(renderer[1],"Coronal-ik",1,4);
+      this->SetRendererName(renderer[2],"Axial-ij",2,5);
+      break;
+    case 1:
+      this->SetRendererName(renderer[0],"Sagittal-jk",0,3);
+      this->SetRendererName(renderer[1],"Axial-ik",1,4);
+      this->SetRendererName(renderer[2],"Coronal-ij",2,5);
+      break;
+    case 2:
+      this->SetRendererName(renderer[0],"Coronal-jk",0,3);
+      this->SetRendererName(renderer[1],"Axial-ik",1,4);
+      this->SetRendererName(renderer[2],"Sagittal-ij",2,5);
+      break;
+    case 3: // Polar
+      displayMode->changeLabel(3,"Short-Axis");
+      displayMode->changeLabel(4,"Radial-1");
+      displayMode->changeLabel(5,"Radial-2");
+      renderer[2]->SetLabel("Short-Axis",0.05,0.05,0.73,0.73,0.0);
+      renderer[1]->SetLabel("Radial-2",0.05,0.05,0.73,0.73,0.0);
+      renderer[0]->SetLabel("Radial-1",0.05,0.05,0.73,0.73,0.0);
+      break;
+
+
+    case 4: // Axial Transpose
+      this->SetRendererName(renderer[1],"Sagital-ik",1,4);
+      this->SetRendererName(renderer[0],"Coronal-jk",0,3);
+      this->SetRendererName(renderer[2],"Axial-ji",2,5);
+      break;
+    case 5: // Coronal Transpose
+      this->SetRendererName(renderer[1],"Sagittal-ki",1,4);
+      this->SetRendererName(renderer[0],"Axial-jk",0,3);
+      this->SetRendererName(renderer[2],"Coronal-ji",2,5);
+      break;
+    case 6: // Sagittal Tranpose
+      this->SetRendererName(renderer[1],"Coronal-ki",1,4);
+      this->SetRendererName(renderer[0],"Axial-kj",0,3);
+      this->SetRendererName(renderer[2],"Sagittal-ji",2,5);
+      break;
+
+    }
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::ModifyPolarImageSpacing()
+{
+  double sp[3]; currentImage->GetSpacing(sp);
+  int  dim[3]; currentImage->GetDimensions(dim);
+  sp[2]=float(dim[1]*sp[1])/float(dim[2]);
+  sp[1]=float(dim[0]*sp[0])/float(dim[1]);
+  currentImage->SetSpacing(sp);
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::ResetViewerUpdatePolar()
+{
+  int   range[3]; 
+  currentImage->GetDimensions(range);
+
+  coordScale[0]->setLabel("Z-Coord");
+  coordScale[1]->setLabel("Angle 1");
+  coordScale[2]->setLabel("Angle 2");
+  
+  for (int ia=0;ia<=2;ia++)
+    {
+      renderer[ia]->SetClipMode(PXTrue);
+      imageSlice[ia]->SetAutoUpdate(0);
+      imageSlice[ia]->SetCurrentPlane(ia);
+      renderer[ia]->SetPlaneMode(ia);
+    }
+  
+  int levels[3];
+  orthoSlice->GetLevels(levels);
+  
+  for (int sc=0;sc<=2;sc++)
+    {
+      int sp=1;
+      if (sc>0)
+	sp=2;
+      levels[sc]=range[sp]/2;
+      if (sc==1)
+	levels[1]=0;
+      coordScale[sc]->setRange(offset,range[sp]-1+offset);  
+      coordScale[sc]->setValue(levels[sc]+offset);
+      coordScale[sc]->setResolution(1.0);
+      imageSlice[sc]->SetLevel(levels[sc]);
+      imageSlice[sc]->Update();
+      imageSlice[sc]->SetAutoUpdate(1);
+    }
+
+  orthoSlice->SetAutoUpdate(0);
+  orthoSlice->SetLevels(levels[0],levels[1],levels[2]);
+  orthoSlice->Update();
+  orthoSlice->SetAutoUpdate(1);
+
+  coordScale[3]->setRange(1,this->NumberOfFrames);
+  coordScale[3]->setValue(this->CurrentFrame+offset);
+  coordScale[3]->setResolution(1.0);
+
+
+  if (range[2]==1)
+    {
+      if (display_mode!=5)
+	{
+	  display_mode=5;
+	  AdjustViewports(display_mode);
+	}
+    }
+  else  
+    {
+      display_mode=(int)displayMode->getIndex();
+      AdjustViewports(display_mode);
+    }
+  for (int i=0;i<=3;i++)
+    renderer[i]->Reset();
+
+  this->MoveAxisPolar(1);
+  return 1;
+}
+// ------------------------------------------------------------------------- 
+int vtkpxGUIOrthogonalViewer::ResetViewerUpdateCartesian() 
+{
+  int   range[3]; 
+  currentImage->GetDimensions(range);
+
+  coordScale[0]->setLabel("i-Coord:");
+  coordScale[1]->setLabel("j-Coord:");
+  coordScale[2]->setLabel("k-Coord:");
+  double sp[3]; currentImage->GetSpacing(sp);
+  double ori[3];  currentImage->GetOrigin(ori);
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      imageSlice[ia]->SetAutoUpdate(0);
+      imageSlice[ia]->SetCurrentPlane(ia);
+      renderer[ia]->SetClipMode(PXTrue);
+      renderer[ia]->SetPlaneMode(ia);
+      renderer[ia]->SetClipThickness(sp[ia]);
+    }
+  
+  orthoSlice->SetAutoUpdate(0);
+
+
+  orthoSlice->SetLevels(range[0]/2,range[1]/2,range[2]/2);
+  orthoSlice->Update();
+  orthoSlice->SetAutoUpdate(1);
+
+  for (int kk=0;kk<=2;kk++)
+    {
+      imageSlice[kk]->SetLevel(range[kk]/2);
+      imageSlice[kk]->Update();
+      imageSlice[kk]->SetAutoUpdate(1);
+    }
+  
+  int levels[3];
+  orthoSlice->GetLevels(levels);
+  
+
+  
+  double lvv[3],lvs[3];
+  for (int ic=0;ic<=2;ic++)
+    {
+      lvv[ic]=float(levels[ic]);
+      lvs[ic]=lvv[ic]*sp[ic]+ori[ic];
+    }
+  this->SetLastClickedPoint(lvv);
+  this->SetLastClickedPointScaled(lvs);
+  
+  coordScale[3]->setRange(1,this->NumberOfFrames);
+  coordScale[3]->setValue(this->CurrentFrame+offset);
+  coordScale[3]->setResolution(1.0);
+  
+  if (range[2]==1)
+    {
+      if (display_mode!=5)
+	{
+	  display_mode=5;
+	  AdjustViewports(display_mode);
+	}
+    }
+  else  
+    {
+      display_mode=(int)displayMode->getIndex();
+      AdjustViewports(display_mode);
+    }
+
+
+  /*  if (this->Orientation==2)
+    {
+      vtkTransform* tr2=vtkTransform::New();
+      fprintf(stderr,"Orientation =2 using flip transform\n");
+      float ori[3]; currentImage->GetOrigin(ori);
+      float sp[3];  currentImage->GetSpacing(sp);
+      int  dim[3];  currentImage->GetDimensions(dim);
+
+      float maxz=ori[2]+float(dim[2]-1)*sp[2];
+      float minz=ori[2];
+      float newz=-maxz;
+      float offset=minz-newz;
+      fprintf(stderr,"Bounds Orientation =2 using flip transform\n");
+      tr2->Identity();
+      tr2->PostMultiply();
+      tr2->Scale(1,1,-1);
+      tr2->Translate(0,0,offset);
+      vtkpxCamera* cam=(vtkpxCamera*)(renderer[3]->GetRenderer()->GetActiveCamera());
+      cam->SetUserTransform(tr2);
+      tr2->Delete();    
+    }
+  else
+    {
+      vtkpxCamera* cam=(vtkpxCamera*)(renderer[3]->GetRenderer()->GetActiveCamera());
+      cam->SetUserTransform(NULL);
+      }*/
+
+  for (int i=0;i<=3;i++)
+    renderer[i]->Reset();
+  this->MoveAxisCartesian(1);
+  
+  for (int sc=0;sc<=2;sc++)
+    {
+      coordScale[sc]->setRange(offset,range[sc]-1+offset);  
+      coordScale[sc]->setValue(levels[sc]+offset);
+      coordScale[sc]->setResolution(1.0);
+    }
+
+  
+
+
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::ResetViewer()
+{
+
+  if (!(hasImage && this->Initialized))
+      return 0;
+
+  
+  if (!hasImage)
+    {
+      oldorientation=-1;
+      firsttimereset=-1;
+    }
+
+
+  if (this->Orientation==3)
+    this->ModifyPolarImageSpacing();
+
+  for (int i=0;i<=2;i++)
+    {
+      imageSlice[i]->SetInput(currentImage);
+      imageSlice[i]->SetColorMode(this->CurrentImageIsColor);
+      imageSlice[i]->SetFrame(this->CurrentFrame);
+      imageSlice[i]->SetLookupTable(mainLookupTable);
+
+      if (this->Orientation==3)
+	imageSlice[i]->SetPolarMode(1);
+      else
+	imageSlice[i]->SetPolarMode(0);
+
+      imageSlice[i]->Update();
+      outlineFilter[i]->SetInput(currentImage);
+
+      if (this->Orientation==3)
+	outline[i]->SetVisibility(0);
+      else
+	outline[i]->SetVisibility(1);
+    }
+
+  orthoSlice->SetInput(currentImage);
+  orthoSlice->SetColorMode(this->CurrentImageIsColor);
+  orthoSlice->SetFrame(this->CurrentFrame);
+  orthoSlice->SetLookupTable(mainLookupTable);
+
+ 
+  if (this->Orientation==3)
+    {
+      orthoSlice->SetPolarMode(1);
+    }
+  else
+    {
+      orthoSlice->SetPolarMode(0);
+    }
+  outlineFilter[3]->SetInput(currentImage);
+  
+
+  if (this->Volume!=NULL && this->Orientation!=3)
+    {
+      this->Volume->SetInput(currentImage,this->Orientation);
+      this->Volume->SetFrame(this->CurrentFrame);
+      this->VolumeControl->Update(1);
+      if (this->Volume->GetVisibility())
+	this->Volume->Update();
+    }
+
+  if (this->obliqueSlice!=NULL && this->Orientation!=3)
+    {
+      this->obliqueSlice->SetAutoUpdate(0);
+      this->obliqueSlice->SetColorMode(this->CurrentImageIsColor);
+      this->obliqueSlice->SetInput(currentImage);
+      this->obliqueSlice->SetFrame(this->CurrentFrame);
+      this->obliqueSlice->SetLookupTable(mainLookupTable);
+      this->ObliqueControl->Update(1);
+      renderer[3]->SetCameraCallback(this->ObliqueControl,140);
+      this->obliqueSlice->SetAutoUpdate(1);
+    }
+
+
+
+  int   range[3]; 
+  currentImage->GetDimensions(range);
+
+  int doupdate=1;
+  if (firsttimereset==0)
+    {
+      int flag=0;
+      for (int i=0;i<=2;i++)
+	if (range[i]!=(int(coordScale[i]->getmax())+1-offset))
+	  flag++;
+      if (this->NumberOfFrames!=(int(coordScale[3]->getmax())))
+	flag++;
+
+      doupdate=(flag>0);
+    }
+
+
+  if (oldorientation!=this->Orientation)
+    {
+      doupdate=1;
+      oldorientation=this->Orientation;
+      this->ResetCoordinateScalesAndLabels();
+    }
+
+  if (range[2]==1 && display_mode!=5)
+    doupdate=1;
+
+  for (int ia=0;ia<=2;ia++)
+    renderer[ia]->SetCurrentImageOrientation(currentImage,this->Orientation,doupdate);
+  if (doupdate)
+    renderer[3]->SetPlaneMode(2);
+  renderer[3]->GetRenderer()->SetBackground(0.0,0.0,0.0);//0.2,0.2,0.3);
+  renderer[3]->SetCurrentImageOrientation(currentImage,this->Orientation,doupdate);
+
+
+  // Do something about Talairach ....
+  if (this->talairachTransform!=NULL)
+    {
+      int md=this->talairachTransform->GetColinMode();
+      if (md==1 || md==-1)
+	{
+	  this->talairachTransform->SetColinMode(md,this->currentImage);
+	  this->talairachTransform->Modified();
+	  this->UpdateTalairachGrid(1);
+	}
+      else
+	{
+	  this->talairachTransform->SetStandardModeOn();
+	}
+    }
+    
+  // ................................
+
+  if (doupdate)
+    {
+      if (this->Orientation!=3)
+	this->ResetViewerUpdateCartesian();
+      else
+	this->ResetViewerUpdatePolar();
+    }
+
+  if (!this->CurrentImageIsColor)
+    this->ShowFrameControls(this->NumberOfFrames>1);
+  else
+    this->ShowFrameControls(0);
+  
+  firsttimereset=0;
+
+  this->UpdateIntensityLabelInfo();
+
+
+  if (this->talairachTransform==NULL)
+    this->talairachTransform=vtkpxTalairachTransform::New();
+  this->talairachTransform->SetColinMode(1,this->currentImage);
+  this->talairachTransform->Modified();
+  this->MoveAxis(1);
+
+
+  if (this->NavigationPointer==NULL)
+    this->CreateNavigationPointer();
+
+  double spa[3]; this->currentImage->GetSpacing(spa);
+  this->NavigationRadius=3.0*spa[0];
+  this->NavigationRadius_X = this->NavigationRadius_Y = this->NavigationRadius_Z = 3.0*spa[0];
+
+
+  
+
+
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::MoveAxisPolar(int force)
+{
+  // Ultrasound Stuff
+  for (int rend=0;rend<=2;rend++)
+    for (int axis=0;axis<=1;axis++)
+      {
+	int index=rend*2+axis;
+	if (axisActor[index]!=NULL)
+	  axisActor[index]->SetVisibility(0);
+      }
+  
+  int lv[3];
+  for (int iaa=0;iaa<=2;iaa++)
+    lv[iaa]=int(imageSlice[iaa]->GetLevel());
+  
+  for (int i=0;i<=3;i++)
+    {
+      this->renderer[i]->SetViewerCoordinates(lv[0],lv[1],lv[2]);
+      if (i<3)
+	renderer[i]->MoveAbove(-1);
+    }
+  
+  if (this->createTalairachButtons)
+    talairachlabel->setText("3D Echo");
+
+  return 1;
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::MoveAxisCartesian(int force)
+{
+  if (axisActor[0]==NULL)
+    {
+      // Create Axis 
+      for (int rend=0;rend<=2;rend++)
+	for (int axis=0;axis<=1;axis++)
+	  {
+	    int index=rend*2+axis;
+	    axisActor[index]=vtkActor::New();
+	    axisActor[index]->PickableOff();
+	    renderer[rend]->GetRenderer()->AddActor(axisActor[index]);
+	  }
+
+      vtkAssembly* ass=vtkAssembly::New();
+      for (int i=6;i<=9;i++)
+	{
+	  axisActor[i]=vtkActor::New();
+	  axisActor[i]->PickableOff();
+	  ass->AddPart(axisActor[i]);
+	  axisActor[i]->SetVisibility(0);
+	}
+      renderer[3]->GetRenderer()->AddActor(ass);
+      ass->Delete();
+    }
+  
+  // Move Axis
+  
+  double sp[3];    currentImage->GetSpacing(sp);
+  double ori[3];   currentImage->GetOrigin(ori);
+  
+  if (force==1)
+    {
+      float bounds[6];
+      int   dim[3]; currentImage->GetDimensions(dim);
+      float meansp=0.0;
+      
+      for (int k=0;k<=2;k++)
+	{
+	  bounds[2*k]  =      ori[k]-0.5*sp[k];
+	  bounds[2*k+1]=float(dim[k]-0.5)*sp[k]+ori[k];
+	  meansp+=0.333*sp[k];
+	  //	  fprintf(stderr,"Bounds 2*k=%f Bounds 2*k+1 = %f\n",bounds[2*k],bounds[2*k+1]);
+	}
+      
+      float thick=meansp*0.01;
+
+      for (int axis=0;axis<=2;axis++)
+	{
+	  vtkCubeSource* cube=vtkCubeSource::New();
+	  double c[3];
+	  for (int ia=0;ia<=2;ia++)
+	    c[ia]=0.0;
+	  int pt[3];
+	  
+	  switch (axis)
+	    {
+	    case 0: // X-axis
+	      cube->SetBounds(bounds[0],bounds[1], -thick,thick, -thick,thick);
+	      pt[0]=2; pt[1]=4; pt[2]=6; c[0]=1.0;
+	      break;
+	    case 1:
+	      cube->SetBounds(-thick,thick,bounds[2],bounds[3],	-thick,thick);
+	      pt[0]=0; pt[1]=5; pt[2]=7; c[1]=1.0;
+	      break;
+	    case 2:
+	      cube->SetBounds(-thick,thick,-thick,thick,bounds[4],bounds[5]);
+	      pt[0]=1; pt[1]=3; pt[2]=8; c[2]=1.0;
+	      break;
+	    }
+	  
+	  for (int k=0;k<=2;k++)
+	    {
+	      int index=pt[k];
+	      axisActor[index]->GetProperty()->SetColor(c);
+	      axisActor[index]->GetProperty()->SetAmbient(1.0);
+	      axisActor[index]->GetProperty()->SetDiffuse(0.0);
+	      axisActor[index]->GetProperty()->SetSpecular(0.0);
+	      
+	      vtkPolyDataMapper *curveMapper = vtkPolyDataMapper::New();
+	      curveMapper->SetInput(cube->GetOutput());
+	      
+	      axisActor[index]->SetMapper(curveMapper);
+	      axisActor[index]->GetProperty()->SetOpacity(0.5);
+	      axisActor[index]->GetProperty()->SetRepresentationToWireframe();
+	      curveMapper->Delete();
+	    }
+	  cube->Delete();
+	}
+      
+      // Now do the origin bit!!!
+      vtkSphereSource* sphere=vtkSphereSource::New();
+      sphere->SetRadius(3.0);	  
+      vtkPolyDataMapper *map0=vtkPolyDataMapper::New();
+      map0->SetInput(sphere->GetOutput());
+      axisActor[9]->SetMapper(map0);
+      map0->Delete();
+      sphere->Delete();
+      axisActor[9]->GetProperty()->SetColor(1.0,0.0,0.0);
+    }
+  
+  
+  double pos[3];
+  int level[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      int dim[3]; this->currentImage->GetDimensions(dim);
+      level[ia]=Irange(imageSlice[ia]->GetLevel(),0,dim[ia]-1);
+      pos[ia]=imageSlice[ia]->GetLevel()*sp[ia]+ori[ia];
+    }
+  
+  axisActor[0]->SetPosition(pos[0],0.0,pos[2]);     // 
+  axisActor[1]->SetPosition(pos[0],pos[1],0.0);
+  axisActor[2]->SetPosition(0.0,pos[1],pos[2]);
+  axisActor[3]->SetPosition(pos[0],pos[1],0.0);
+  axisActor[4]->SetPosition(0.0,pos[1],pos[2]);
+  axisActor[5]->SetPosition(pos[0],0.0,pos[2]);
+  
+
+
+  int lv[3];
+  for (int iaa=0;iaa<=2;iaa++)
+    {
+      lv[iaa]=int(imageSlice[iaa]->GetLevel());
+      //      fprintf(stderr,"Getting Level %d,%d\n",iaa,lv[iaa]);
+    }
+  
+
+
+  for (int i=0;i<=3;i++)
+    {
+      this->renderer[i]->SetViewerCoordinates(lv[0],lv[1],lv[2]);
+      renderer[i]->SetClipBounds(lv[0],lv[1],lv[2],sp,ori);
+      if (i<3)
+	renderer[i]->Clip();
+    }
+  
+  if (this->SynchNavigationalPointerWithCrossHairs)
+    this->MoveNavigationPointer();
+  
+
+  this->UpdateIntensityLabelInfo();
+  this->UpdateDisplay(); 
+
+  return 1;
+}
+
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::UpdateIntensityLabelInfo()
+{
+  double sp[3];    currentImage->GetSpacing(sp);
+  double ori[3];   currentImage->GetOrigin(ori);
+  int    dim[3];   currentImage->GetDimensions(dim);
+  double pos[3];
+  int level[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      level[ia]=imageSlice[ia]->GetLevel();
+      level[ia]=Irange(level[ia],0,dim[ia]-1);
+      pos[ia]=double(level[ia])*sp[ia]+ori[ia];
+    }
+
+  if (this->createTalairachButtons)
+    {
+      if (this->talairachTransform==NULL)
+	{
+	  talairachlabel->setText("");
+	}
+      else
+	{
+	  this->DisplayNeuroCoordinates(pos,level,talairachlabel,mnilabel);
+	}
+    }
+  else
+    {
+      double vl=0.0;
+      if (this->valueImage!=NULL)
+	vl=valueImage->GetScalarComponentAsDouble(level[0],level[1],level[2],this->CurrentFrame);
+      else
+	vl=currentImage->GetScalarComponentAsDouble(level[0],level[1],level[2],this->CurrentFrame);
+      
+      std::string objlabel=this->GetObjectmapValueAsText(level[0],level[1],level[2]);
+      sprintf(pxtk_buffer,"(%d %d %d) %s %s",level[0],level[1],level[2],this->GetFormatedNumber(vl,3),objlabel.c_str());
+      talairachlabel->setText(pxtk_buffer);
+    }
+
+  return 1;
+}
+
+// -------------------------------------------------------------------------
+void vtkpxGUIOrthogonalViewer::MoveAxis(int force)
+{
+  if (!hasImage)
+      return;
+
+  //fprintf(stderr,"In Move Axis %d\n",force);
+
+  if (this->Orientation!=3)
+    this->MoveAxisCartesian(force);
+  else
+    this->MoveAxisPolar(force);
+
+
+  if (this->EventParent!=NULL && this->CallbackNo>0)
+    {
+      this->EventParent->HandleEvent(CallbackNo);
+    }
+  else
+    {
+      if (this->CallbackName!=NULL)
+	PXTkApp::executeTclCommand(this->CallbackName);
+    }
+}
+// -------------------------------------------------------------------------
+int vtkpxGUIOrthogonalViewer::FindCentroid(vtkImageData* img,int location[3],double lvv[3],int radius)
+{
+  int min_loc[3],max_loc[3],idim[3];
+  img->GetDimensions(idim);
+
+  for (int k=0;k<=2;k++)
+    {
+      min_loc[k]=Irange(location[k]-radius,0,idim[k]-2);
+      max_loc[k]=Irange(location[k]+radius,min_loc[k]+1,idim[k]-1);
+    }
+
+
+  vtkpxImageExtractVOI* voi=vtkpxImageExtractVOI::New();
+  voi->SetInput(img);
+  voi->SetVOI(min_loc[0],max_loc[0],
+	      min_loc[1],max_loc[1],
+	      min_loc[2],max_loc[2]);
+  voi->Update();
+
+	      
+  vtkImageThreshold* thr=vtkImageThreshold::New();
+  thr->SetInput(voi->GetOutput());
+  thr->ThresholdByUpper(1);
+  thr->SetInValue(1);
+  thr->SetOutValue(0);
+  thr->ReplaceInOn();
+  thr->ReplaceOutOn();
+  thr->SetOutputScalarTypeToUnsignedChar();
+  
+  vtkImageSeedConnectivity* connectivity=vtkImageSeedConnectivity::New();
+  connectivity->SetInput(thr->GetOutput());
+  connectivity->SetInputConnectValue(1);
+  connectivity->AddSeed(location[0]-min_loc[0],location[1]-min_loc[1],location[2]-min_loc[2]);
+  connectivity->SetOutputConnectedValue(100);
+  connectivity->SetOutputUnconnectedValue(0);
+  connectivity->SetDimensionality(3);
+  connectivity->Update();
+
+
+  vtkImageData* mask=connectivity->GetOutput();
+  int dim[3]; mask->GetDimensions(dim);
+
+  //  fprintf(stderr,"dim= %d x %d x %d\n",dim[0],dim[1],dim[2]);
+
+  double sum[3], wsum=0.0;
+  for (int j=0;j<=2;j++)
+    sum[j]=0.0;
+
+
+  for (int ia=0;ia<dim[0];ia++)
+    for (int ib=0;ib<dim[1];ib++)
+      for (int ic=0;ic<dim[2];ic++)
+	{
+	  double v=mask->GetScalarComponentAsDouble(ia,ib,ic,0);
+
+	  if (v>0)
+	    {
+	      double w=1.0;
+	      if (this->TraceVolumeWeightedMode)
+		w=fabs(v);
+
+	      sum[0]+=double(ia)*w;
+	      sum[1]+=double(ib)*w;
+	      sum[2]+=double(ic)*w;
+	      wsum+=w;
+	    }
+	}
+
+  double ori[3];  mask->GetOrigin(ori); 
+  double spa[3];  mask->GetSpacing(spa);
+  for (int ia=0;ia<=2;ia++)
+    lvv[ia]=0.0;
+
+  
+  /*  fprintf(stderr,"Ori=%.2f,%.2f,%.2f spa=%.2f,%.2f,%.2f np=%d sum=%d %d %d\n",
+	  ori[0],ori[1],ori[2],
+	  spa[0],spa[1],spa[2],
+	  np,
+	  sum[0],sum[1],sum[2]);*/
+
+  if (wsum>0.0)
+    {
+      for (int j=0;j<=2;j++)
+	{
+	  location[j]=int(sum[j]/wsum+0.5)+min_loc[j];
+	  lvv[j]=ori[j]+spa[j]*sum[j]/wsum;
+	}
+      fprintf(stderr,"Loc = %d %d %d (Raw = %.3f %.3f %.3f)\n",
+	      location[0],location[1],location[2],
+	      lvv[0],lvv[1],lvv[2]);
+
+    }
+
+  //  this->SetLastClickedPoint(lvv);
+
+
+  thr->Delete();
+  voi->Delete();
+  connectivity->Delete();
+  return (wsum>0.0);
+
+}
+// ------------------------------------------------------------------------- 
+vtkCamera* vtkpxGUIOrthogonalViewer::GetCurrentCamera()
+{
+
+  if (renderer[3]==NULL)
+    return NULL;
+  
+  if (renderer[3]->GetRenderer()==NULL)
+    return NULL;
+
+  return renderer[3]->GetRenderer()->GetActiveCamera();
+}
+// ------------------------------------------------------------------------- 
+int vtkpxGUIOrthogonalViewer::CopyCamera(vtkpxGUIOrthogonalViewer* other)
+{
+  return this->CopyCamera(other->GetCurrentCamera());
+}
+
+int vtkpxGUIOrthogonalViewer::CopyCamera(vtkCamera* othercamera)
+{
+  vtkCamera* thiscamera=this->GetCurrentCamera();
+
+  if (thiscamera==NULL || othercamera==NULL)
+    return 0;
+
+  vtkpxGUIRenderer::CopyCamera(thiscamera,othercamera);
+  return 1;
+}
+// ------------------------------------------------------------------------- 
+void vtkpxGUIOrthogonalViewer::SetLookupTable(vtkLookupTable* lkp)
+{
+  vtkpxGUIBaseImageViewer::SetLookupTable(lkp);
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (imageSlice[ia]!=NULL) 
+	{
+	  imageSlice[ia]->UpdateTexture();
+	  imageSlice[ia]->Modified();
+	}
+    }
+
+  if (orthoSlice)
+    orthoSlice->Modified();
+
+  if (this->obliqueSlice)
+    this->obliqueSlice->Modified();
+
+  this->UpdateDisplay();
+}
+
+// ------------------------------------------------------------------------- 
+void vtkpxGUIOrthogonalViewer::SetNavigationPointerGeometryToEllipse(double radius_x, double radius_y, double radius_z)
+{
+  //  printf(" in ellipse\n");
+  this->NavigationPointerActorMode=2;
+  this->NavigationRadius_X =radius_x;
+  this->NavigationRadius_Y =radius_y;
+  this->NavigationRadius_Z =radius_z;
+
+  this->UpdateNavigationActorGeometry(0);
+}
+
+
+// ------------------------------------------------------------------------- 
+void vtkpxGUIOrthogonalViewer::SetNavigationPointerGeometryToCone(double radius)
+{
+  //  printf(" in ellipse\n");
+  this->NavigationPointerActorMode=2;
+  this->NavigationRadius=radius;
+  this->UpdateNavigationActorGeometry(0);
+}
+
+void vtkpxGUIOrthogonalViewer::SetNavigationPointerGeometryToCylinder(double radius)
+{
+  //printf(" in cylinder\n");
+  this->NavigationPointerActorMode=3;
+  this->NavigationRadius=radius;
+  this->UpdateNavigationActorGeometry(0);
+}
+
+
+void vtkpxGUIOrthogonalViewer::SetNavigationPointerGeometryToSphere(double radius)
+{
+  this->NavigationPointerActorMode=0;
+  this->NavigationRadius=radius;
+  this->UpdateNavigationActorGeometry(0);
+}
+
+
+void vtkpxGUIOrthogonalViewer::SetNavigationPointerGeometryToCube(double cubelength)
+{
+  this->NavigationPointerActorMode=1;
+  this->NavigationLength = cubelength;
+  this->UpdateNavigationActorGeometry(0);
+
+}
+// ------------------------------------------------------------------------- 
+int vtkpxGUIOrthogonalViewer::UpdateNavigationActorGeometry(int updatevolumecrop)
+{
+
+  if (this->NavigationPointer==NULL)
+    return 0;
+
+  if (this->NavigationPointerGeometry==NULL)
+    this->NavigationPointerGeometry=vtkPolyData::New();
+  
+  double p1[3];   this->NavigationPointer->GetPoint1(p1);
+  double p2[3];   this->NavigationPointer->GetPoint2(p2);
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->NavigationPointerTip[ia]=p2[ia];
+      this->NavigationPointerBase[0]=p1[ia];   
+    }
+
+
+  double cnt[3],n[3],dist[3];
+  double len=sqrt(vtkMath::Distance2BetweenPoints(p2,p1));
+  for (int ia=0;ia<=2;ia++)
+    {
+      cnt[ia]=0.5*(p2[ia]+p1[ia]);
+      dist[ia]=p2[ia]-p1[ia];
+      n[ia]=dist[ia];
+    }
+  vtkMath::Normalize(n);
+
+  
+  if (this->NavigationPointerActorMode<0 || this->NavigationPointerActorMode>3)
+    this->NavigationPointerActorMode=0;
+
+
+  switch (this->NavigationPointerActorMode)
+    {
+    case 0: // Sphere
+      {
+	if (this->NavigationSphereSource==NULL)
+	  this->NavigationSphereSource=vtkSphereSource::New();
+	
+	this->NavigationSphereSource->SetRadius(this->NavigationRadius-1);
+	this->NavigationSphereSource->SetCenter(p2);
+	this->NavigationSphereSource->SetPhiResolution(18);
+	this->NavigationSphereSource->SetThetaResolution(18);
+	this->NavigationSphereSource->Update();
+	this->NavigationPointerGeometry->ShallowCopy(this->NavigationSphereSource->GetOutput());
+	
+	if(updatevolumecrop)
+	  this->Volume->SetCropValues(0, this->NavigationRadius, 10, 10, 10, 10, 10, 10, 10, 10, n);		
+      }
+      break;
+   
+
+    case 1: // Cube
+      {
+	if (this->NavigationCubeSource==NULL)
+	  this->NavigationCubeSource=vtkCubeSource::New();
+	
+	this->NavigationCubeSource->SetXLength(2.0*fabs(dist[0]));
+	this->NavigationCubeSource->SetYLength(2.0*fabs(dist[1]));
+	this->NavigationCubeSource->SetZLength(2.0*fabs(dist[2]));
+	this->NavigationCubeSource->SetCenter(p2);
+	this->NavigationCubeSource->Update();
+	this->NavigationPointerGeometry->ShallowCopy(this->NavigationCubeSource->GetOutput());
+
+	//printf("updatevolume crop %d\n", updatevolumecrop); 
+
+	//if(updatevolumecrop)
+	  this->Volume->SetCropValues(1, 10, 2.0*fabs(dist[0]), 2.0*fabs(dist[1]), 2.0*fabs(dist[2]), 10, 10, 10, 10, 10, n);
+
+      }
+      break;
+
+	  case 2: // Ellipse
+      {
+
+	  	if (this->NavigationEllipseSource==NULL)
+			this->NavigationEllipseSource=vtkEllipseSource::New();	
+
+		this->NavigationEllipseSource->SetRadiusX(this->NavigationRadius_X); 
+		this->NavigationEllipseSource->SetRadiusY(this->NavigationRadius_Y); 
+		this->NavigationEllipseSource->SetRadiusZ(this->NavigationRadius_Z); 
+		this->NavigationEllipseSource->SetCenter(p2); 
+
+		this->NavigationEllipseSource->SetPhiResolution(18);
+		this->NavigationEllipseSource->SetThetaResolution(18);
+		this->NavigationEllipseSource->Update();
+		this->NavigationPointerGeometry->ShallowCopy(this->NavigationEllipseSource->GetOutput());
+
+		if(updatevolumecrop)
+			this->Volume->SetCropValues(2, 10, 10, 10, 10, this->NavigationRadius_X, this->NavigationRadius_Y, this->NavigationRadius_Z, 10, 10, n);		
+      }
+      break;
+
+
+    case 3: // Cylinder
+      {
+	if (this->NavigationCylinderSource==NULL)
+	  this->NavigationCylinderSource=vtkCylinderSource::New();
+
+	this->NavigationCylinderSource->SetCenter(0,0,0);
+	this->NavigationCylinderSource->SetRadius(this->NavigationRadius);		
+	this->NavigationCylinderSource->SetResolution(12); 
+	this->NavigationCylinderSource->SetHeight(len);
+	this->NavigationCylinderSource->Update();
+
+
+	if (this->NavigationCylinderTransform==NULL)
+	  {
+	    this->NavigationCylinderTransform=vtkTransform::New();
+	    this->NavigationCylinderTransform->PostMultiply();
+	  }
+	this->NavigationCylinderTransform->Identity();
+
+	double cr[3];
+	double ax[3]={0,1,0};
+	vtkMath::Cross(n,ax,cr);
+	double t=acos(vtkMath::Dot(n,ax))*180.0/vtkMath::Pi();
+
+	this->NavigationCylinderTransform->RotateWXYZ(-t,cr[0],cr[1],cr[2]);
+      	this->NavigationCylinderTransform->Translate(cnt);
+	
+	  
+	if (this->NavigationCylinderFilter==NULL)
+	  {
+	    this->NavigationCylinderFilter=vtkTransformPolyDataFilter::New();
+	  }
+	this->NavigationCylinderFilter->SetInput(this->NavigationCylinderSource->GetOutput());
+	this->NavigationCylinderFilter->SetTransform(NavigationCylinderTransform);
+	this->NavigationCylinderFilter->Update();
+	this->NavigationPointerGeometry->ShallowCopy(this->NavigationCylinderFilter->GetOutput());
+
+	if(updatevolumecrop)
+	  this->Volume->SetCropValues(3, 10, 10, 10, 10, 10, 10, 10, this->NavigationRadius, len, n);
+      }
+      break;
+    }
+      
+  if (this->NavigationPointerActor==NULL)
+    {
+      vtkPolyDataMapper *map=vtkPolyDataMapper::New();
+      map->SetInput(this->NavigationPointerGeometry);
+      this->NavigationPointerActor=vtkActor::New();
+      this->NavigationPointerActor->SetMapper(map);
+      this->NavigationPointerActor->GetProperty()->SetOpacity(1.0);
+      this->NavigationPointerActor->GetProperty()->SetColor(0.2, 0.8, 0.2);
+      renderer[3]->GetRenderer()->AddActor(this->NavigationPointerActor);
+      this->NavigationPointerActor->SetVisibility(0);
+    }
+  else
+    {
+      vtkPolyDataMapper *map=(vtkPolyDataMapper*)this->NavigationPointerActor->GetMapper();
+      map->SetInput(this->NavigationPointerGeometry);
+      this->NavigationPointerActor->Modified();
+    }
+
+  this->NavigationPointerActor->Modified();
+
+  //if(updatevolumecrop)
+  //{  
+    this->Volume->SetProbeLocation(p2);
+  //}
+return 1;
+}
+// -----------------------------------------------------------------------------------------------
+
+int vtkpxGUIOrthogonalViewer::RenderNavigationPointer(int dm)
+{
+  if (dm>=0 && dm<=3 && dm!=this->NavigationPointerDrawMode)
+    this->SetNavigationPointerDrawMode(dm);
+
+  // Line Widget
+  if (this->NavigationPointerDrawMode==0 || this->NavigationPointerDrawMode==2)
+    this->NavigationPointer->Off();
+  else
+    this->NavigationPointer->On();
+
+  // Pointer Actor = Decoration
+  if (this->NavigationPointerDrawMode==0 || this->NavigationPointerDrawMode==1)
+    {
+      this->NavigationPointerActor->SetVisibility(0);
+      this->renderer[3]->HideLabel();
+
+    }
+  else if (this->NavigationPointerDrawMode==2)
+    {
+      this->NavigationPointerActor->GetProperty()->SetRepresentationToSurface();
+      this->NavigationPointerActor->GetProperty()->SetDiffuse(1.0);
+      this->NavigationPointerActor->GetProperty()->SetAmbient(0.0);
+      this->NavigationPointerActor->GetProperty()->SetSpecular(0.0);
+      this->NavigationPointerActor->SetVisibility(1);
+    }
+  else
+    {
+      this->NavigationPointerActor->GetProperty()->SetRepresentationToWireframe();
+      this->NavigationPointerActor->GetProperty()->SetLineWidth(0.5);
+      this->NavigationPointerActor->GetProperty()->SetAmbient(1.0);
+      this->NavigationPointerActor->GetProperty()->SetDiffuse(0.0);
+      this->NavigationPointerActor->GetProperty()->SetSpecular(0.0);
+      this->NavigationPointerActor->SetVisibility(1);
+    }
+
+  this->RenderDelay(100);
+
+  return 1; 
+}
+
+
+int vtkpxGUIOrthogonalViewer::SetNavigationalPointerFromTool(vtkPoints* pts  )
+{
+  if (pts==NULL)
+    return 0;
+
+  if (pts->GetNumberOfPoints()<2)
+    return 0;
+
+  double tip[3];   pts->GetPoint(0,tip);
+  double base[3];  pts->GetPoint(1,base);
+  return this->SetNavigationalPointerFromTool(tip,base);
+
+}
+
+int vtkpxGUIOrthogonalViewer::SetNavigationalPointerFromTool(vtkTransform* tr)
+{
+  if (tr==NULL)
+    return 0;
+
+  double base[3] = { 0.0 , -40 , 0.0};
+  double tip[3] = {  0.0 , 0.0 , 0.0 };
+
+  float sc[3];  tr->GetScale(sc);
+  double sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+    sum+=fabs(sc[ia]-100.0);
+
+  fprintf(stderr,"Scales = %.2f,%.2f,%.2f sum=%f\n",sc[0],sc[1],sc[2],sum);
+
+
+  if (sum>0.001)
+    base[1]=-1.0;
+
+  tr->TransformPoint(base,base);
+  tr->TransformPoint(tip,tip);
+  return this->SetNavigationalPointerFromTool(tip,base);
+}
+
+int vtkpxGUIOrthogonalViewer::SetNavigationalPointerFromTool(double p2[3],double p1[3])
+{
+  
+  double cnt[3],n[3],dist[3];
+  double len=sqrt(vtkMath::Distance2BetweenPoints(p2,p1));
+  for (int ia=0;ia<=2;ia++)
+    {
+      cnt[ia]=0.5*(p2[ia]+p1[ia]);
+      dist[ia]=p2[ia]-p1[ia];
+      n[ia]=dist[ia];
+    }
+  vtkMath::Normalize(n);
+
+  if (this->NavigationConeSource==NULL)
+    this->NavigationConeSource=vtkConeSource::New();
+  
+
+  this->NavigationConeSource->SetHeight(len);
+  this->NavigationConeSource->SetRadius(this->NavigationRadius);
+  this->NavigationConeSource->SetCenter(cnt);
+  this->NavigationConeSource->SetDirection(n);
+  this->NavigationConeSource->CappingOn();
+  this->NavigationConeSource->SetResolution(36);
+  this->NavigationConeSource->Update();
+  this->NavigationPointerGeometry->ShallowCopy(this->NavigationConeSource->GetOutput());
+
+  this->RenderNavigationPointer(2);
+
+  return 1; 
+}
+
+void vtkpxGUIOrthogonalViewer::SetBackgroundColor(vtkRenderWindow* renwin)
+{
+  vtkRenderer* ren=renderer[0]->GetRenderer();
+
+  double c[3];   ren->GetBackground(c);
+  int a=this->EventManager->d_colorBox("Background Color",c[0],c[1],c[2]);
+
+  if (a==0)
+    return;
+
+  for (int i=0;i<=3;i++)
+    renderer[i]->GetRenderer()->SetBackground(c);
+  this->KeyRenderer->SetBackground(c);
+  this->BackgroundRenderer->SetBackground(c);
+  render_widget->getRenderWindow()->Render();  
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIOrthogonalViewer.h b/bioimagesuite30_src/GUI/vtkpxGUIOrthogonalViewer.h
new file mode 100644
index 0000000..1c1d335
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIOrthogonalViewer.h
@@ -0,0 +1,389 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkpxGUIOrthogonalViewer 
+// .SECTION Description
+
+#ifndef __vtkpxGUIOrthogonalViewer_h
+#define __vtkpxGUIOrthogonalViewer_h
+
+#include "vtkpxGUIBaseImageViewer.h"
+#include "vtkPolyData.h"
+#include "vtkEllipseSource.h"
+#include "pxvtkgadgets.h"
+
+#include "pxtkscale.h"
+#include "pxtkframe.h"
+#include "pxtkoptionmenu.h"
+#include "pxtklabel.h"
+#include "pxutil.h"
+
+class vtkActor;
+class vtkpxGUIRenderer;
+class vtkpxImageSlice;
+class vtkpxOrthoImageSlice;
+class vtkpxVolume;
+class vtkpxGUIVolumeControl;
+class vtkpxGUIObliqueImageSliceControl;
+class vtkOutlineFilter;
+class vtkpxVolume;
+class vtkpxObliqueImageSlice;
+class vtkCamera;
+class vtkGenericRenderWindowInteractor;
+class vtkLineWidget;
+class vtkConeSource;
+class vtkCubeSource;
+class vtkSphereSource;
+class vtkCylinderSource;
+class vtkTransformPolyDataFilter;
+class vtkTransform;
+
+class  vtkpxGUIOrthogonalViewer : public vtkpxGUIBaseImageViewer 
+{
+public:
+  
+  static vtkpxGUIOrthogonalViewer *New();
+  vtkTypeMacro(vtkpxGUIOrthogonalViewer,vtkpxGUIBaseImageViewer);
+
+
+  // Desription:
+  // tk interface
+  virtual char* Initialize(const char* name,int inside);
+  virtual char* Initialize(const char* name,const char* name2,int inside);
+  virtual char* GetRenderWidgetName();
+  virtual char* GetControlFrameName();
+  virtual char* GetViewerFrameName();
+  virtual void  SetShowControls(int show=1);
+  virtual void SetBackgroundColor(vtkRenderWindow* renwin);
+
+  // Description:
+  // Colormap Stuff --> Volume
+  virtual void  SetPresetLookupTable(int mode);
+  virtual void SetLookupTable(vtkLookupTable* lkp);
+
+  // Description:
+  // Offset for 0 offset or 1 offset
+  virtual void  SetOffset(int off);
+
+  // Description:
+  // Create and Reset Viewer and Update
+  virtual int   InitializeViewer();
+  virtual int   ResetViewer();
+  virtual int   UpdateDisplay();
+  virtual void  Update() { UpdateDisplay();}
+
+  // Description:
+  // Event Loop Handling
+  virtual int   HandleEvent(int eventno);
+  virtual int   HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev);
+
+  // Description:
+  // Coordinate Changes
+  virtual void  SetCoordinates(int lx,int ly,int lz,int infoonly=0);
+  virtual void  SetScaledCoordinates(float lx,float ly,float lz,int infoonly);
+  virtual void  SetScaledCoordinates(float lx,float ly,float lz) { SetScaledCoordinates(lx,ly,lz,0); }
+  virtual void  SetCurrentFrame(int t);
+  virtual void  ChangeFrame(int newframe);
+
+  // Description:
+  // Set Viewer Modes
+  virtual void  AdjustViewports(int mode);
+  virtual void  SetDisplayMode(int dm) { AdjustViewports(dm);}
+  virtual int  GetDisplayMode();
+  virtual int  GetDisplayMode3D();
+  virtual void SetDisplayMode3D();
+  virtual void SetDisplayMode3DIfNeeded();
+  virtual void SetDisplayMode2D();
+  virtual void ShowFrameControls(int show=1);
+  virtual void UpdateKeyRenderer();
+
+
+  // Description:
+  // Display 3D Volume or axis outline
+  virtual void SetDisplay3DMode(int dm);
+  virtual void SetDisplay3DAxisOutlineMode(int mode);
+
+  // Description:
+  // Set Visibility for Volume Ortho and Oblique Slices
+  virtual void SetOrthoSliceVisibility(int orthovis);
+  virtual void SetVolumeVisibility(int volvis);
+  virtual void SetObliqueSliceVisibility(int volvis);
+
+
+  // Decription:
+  // Enable/Disable Mouse updates
+  virtual void SetMouseSliceChangeMode(int m);
+  vtkGetMacro(MouseSliceChangeMode,int);
+
+  // Description:
+  // Get access to internal stuff
+  virtual vtkpxGUIRenderer*     GetRenderer(int i);
+  virtual vtkpxImageSlice*      GetImageSlice(int i);
+  virtual vtkpxObliqueImageSlice*  GetObliqueImageSlice();
+  virtual vtkpxGUIObliqueImageSliceControl*  GetObliqueControl();
+  virtual vtkpxGUIVolumeControl*     GetVolumeControl();
+  virtual vtkpxOrthoImageSlice* GetOrthoImageSlice();
+  virtual vtkActor*             GetOutlineActor(int i);
+  virtual vtkActor*             GetAxisActor(int i) { return axisActor[Irange(i,0,9)]; }
+
+  // Description:
+  // View Synchronization
+  virtual vtkCamera*            GetCurrentCamera();
+  virtual int                   CopyCamera(vtkpxGUIOrthogonalViewer* other);
+  virtual int                   CopyCamera(vtkCamera* camera);
+  
+  
+  // Description:
+  // Tracing/Clicking Interface
+  vtkGetMacro(TraceVolume,int);
+  vtkSetMacro(TraceVolume,int);
+
+
+  vtkGetMacro(TraceVolumeVOI,int);
+  vtkSetClampMacro(TraceVolumeVOI,int,0,40);
+  vtkSetClampMacro(TraceVolumeWeightedMode,int,0,1);
+  vtkGetMacro(TraceVolumeWeightedMode,int);
+
+  vtkGetMacro(TraceGeometry,int);
+  vtkSetMacro(TraceGeometry,int);
+  vtkGetMacro(TraceVolumeToleranceMode,int);
+  vtkSetMacro(TraceVolumeToleranceMode,int);
+
+  vtkGetMacro(LastClickedSlice,int);
+
+  
+  // Description:
+  // Show Cross Hairs and Update stuff
+  virtual void ShowCrossHairs(int mode);
+  virtual void MoveAxis(int force=0);
+
+  // Description:
+  // Event Response from Widget
+  vtkSetClampMacro(EventResponseFromWidget,int,0,1);
+  vtkGetMacro(EventResponseFromWidget,int);
+
+
+  // Description:
+  // Sync Widget With Cross Hairs
+  vtkSetClampMacro(SynchNavigationalPointerWithCrossHairs,int,0,1);
+  vtkGetMacro(SynchNavigationalPointerWithCrossHairs,int);
+
+  // Description:
+  // Modes
+  // 0 = show nothing
+  // 1 = show line widget only
+  // 2 = show decoration only
+  // 3 = show line widget + decoration wireframe
+  vtkSetClampMacro(NavigationPointerDrawMode,int,0,3);
+  vtkGetMacro(NavigationPointerDrawMode,int);
+  // Setting dm will set NavigationPointerDraw Mode (-1 stays as is)
+  virtual int RenderNavigationPointer(int dm=-1);
+
+  // Description:
+  // Force Surgical Mode Pointer
+  virtual int SetNavigationalPointerFromTool(vtkPoints* pts  );
+  virtual int SetNavigationalPointerFromTool(vtkTransform* tr);
+  virtual int SetNavigationalPointerFromTool(double tip[3],double base[3]);
+  
+
+  // Tool Position
+  vtkGetVectorMacro(NavigationPointerTip,double,3);
+  vtkGetVectorMacro(NavigationPointerBase,double,3);
+
+
+  // Description:
+  // Access the Line Widget
+  vtkGetObjectMacro(NavigationPointer,vtkLineWidget);
+
+  // Description:
+  // Navigational Pointer Actor
+  // Mode 0 = Cone, 1 = Sphere, 2= Cube, 3= Cylinder
+  vtkGetMacro(NavigationPointerActorMode,int);
+  virtual void SetNavigationPointerGeometryToCone(double radius);
+  virtual void SetNavigationPointerGeometryToSphere(double radius);
+  virtual void SetNavigationPointerGeometryToCube(double cubelength);
+  virtual void SetNavigationPointerGeometryToEllipse(double radius_x, double radius_y, double radius_z);
+  virtual void SetNavigationPointerGeometryToCylinder(double radius);
+  vtkGetObjectMacro(NavigationPointerActor,vtkActor);
+  
+protected:
+
+  vtkpxGUIOrthogonalViewer();
+  virtual ~vtkpxGUIOrthogonalViewer();
+
+  vtkpxGUIRenderer*         renderer[4];
+  vtkRenderer*              BackgroundRenderer;
+  PXVTkTkRenderWidget*      render_widget;
+  vtkpxImageSlice*          imageSlice[3];
+  vtkpxObliqueImageSlice*   obliqueSlice;
+
+  vtkpxOrthoImageSlice       *orthoSlice;
+  vtkActor*                  axisActor[10];
+  vtkOutlineFilter*          outlineFilter[4];
+  vtkActor*                  outline[4];
+  vtkpxVolume*               Volume;
+
+  vtkpxGUIVolumeControl*     VolumeControl;
+  vtkpxGUIObliqueImageSliceControl*    ObliqueControl;
+
+  int                        display_mode;
+  int                        display3d_mode;
+  int                        display3d_axisoutlinemode;
+  int                        offset;
+  int                        OrthoSliceVisibility;
+  int                        MouseSliceChangeMode;
+  int                        show_controlframe;
+  int                        TraceVolume;
+  int                        TraceVolumeVOI;
+  int                        TraceVolumeWeightedMode;
+  int                        TraceGeometry;
+  int                        TraceVolumeToleranceMode;
+  int                        EnableFrameChangeOnCallback;
+
+
+  PXTkOptionMenu*           displayMode;
+  PXTkOptionMenu*           display3DMode;
+  PXTkOptionMenu*           display3DAxisOutlineMode;
+  PXTkFrame*                viewerFrame;
+  PXTkFrame*                viewerFrame2;
+  PXTkFrame*                controlFrame;
+  PXTkFrame*                extraFrame;
+  PXTkFrame*                coordScaleFrame;
+
+  PXTkCheckButton*          showaxisc;
+  PXTkCheckButton*          interpolateMode;
+  PXTkCheckButton*          showPointer;
+  PXTkCheckButton*          freezeMode;
+  PXTkArrowScale            *coordScale[4];
+  PXTkButton*               saveAllButton;
+
+
+  PXTkLabel*                talairachlabel;
+  PXTkLabel*                mnilabel;
+
+
+  // Description:
+  // Initialization Stuff 
+  virtual void InitControls(int hm=1);
+  virtual void InitViewer();
+
+
+  // Description:
+  // Picking Stuff 
+  int VolumePick(int clickx, int clicky, vtkRenderer* pick_renderer);
+  int GeometryPick(int clickx, int clicky, vtkRenderer* pick_renderer);
+
+  // Description:
+  // Change Coordinates Frame Stuff 
+  virtual void ChangeSliceLevels(int lv[3],int infoonly=0);
+  virtual void SetInterpolation(int interp);
+
+
+  // Description:
+  // Polar and Cartesian Stuff
+  virtual int ResetCoordinateScalesAndLabels();
+  virtual int ModifyPolarImageSpacing();
+
+
+  virtual int ResetViewerUpdatePolar();
+  virtual int ResetViewerUpdateCartesian();
+  virtual int MoveAxisPolar(int force);
+  virtual int MoveAxisCartesian(int force);
+  virtual int UpdateIntensityLabelInfo();
+
+  // Description:
+  // Find Centroid of clicked volume
+  virtual int FindCentroid(vtkImageData* img,int location[3],double lvv[3],int radius);
+
+  // Description:
+  // Some Flags which used to be static 
+  //BTX
+  int inexpose,inexposecount,oldorientation,firsttimereset;
+  int LastClickedSlice;
+  //ETX
+
+  // Description:
+  // Interactor and LineWidget Stuff
+  vtkLineWidget*  NavigationPointer;
+  vtkGenericRenderWindowInteractor* WidgetInteractor;
+  int EventResponseFromWidget;
+  int SynchNavigationalPointerWithCrossHairs;
+
+
+  // Descrition:
+  // Mode = 0 - Sphere, 1 - Cube, 2 - Ellipse, 3 - Cylinder
+  int NavigationPointerActorMode;
+
+  // Description:
+  // Cone/Ellipse Radius
+  double NavigationRadius;
+  double NavigationRadius_X;
+  double NavigationRadius_Y;
+  double NavigationRadius_Z;
+
+
+  // Description:
+  // Cube Length
+  double NavigationLength;
+
+  // Description:
+  // The underlying objects for the pointero
+  vtkPolyData* NavigationPointerGeometry;
+  vtkActor* NavigationPointerActor;
+  vtkConeSource*     NavigationConeSource;
+  vtkSphereSource*   NavigationSphereSource;
+  vtkCubeSource*     NavigationCubeSource;
+  vtkEllipseSource*  NavigationEllipseSource;
+  vtkCylinderSource* NavigationCylinderSource;
+  vtkTransformPolyDataFilter* NavigationCylinderFilter;
+  vtkTransform* NavigationCylinderTransform;
+  double NavigationPointerTip[3];
+  double NavigationPointerBase[3];
+  // 
+  int           NavigationPointerDrawMode;
+  
+  // Description:
+  // Pointer Stuff
+  virtual int CreateNavigationPointer();
+  virtual int MoveNavigationPointer();
+  virtual int SendEventToWidgetInteractor(int x,int y,int button,int state);
+  virtual int UpdateNavigationActorGeometry(int updatevolumecrop=0);
+
+  // Description:
+  // Next Gen Renderer Name Stuff
+  virtual void SetRendererName(vtkpxGUIRenderer* ren,const char* basename,
+			       int axis,int dmindex=-1);
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIPolyDataControl.cpp b/bioimagesuite30_src/GUI/vtkpxGUIPolyDataControl.cpp
new file mode 100644
index 0000000..5d12bd9
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIPolyDataControl.cpp
@@ -0,0 +1,2579 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+#include "pxutil.h"
+#include "vtkActor.h"
+#include "vtkAppendPolyData.h"
+#include "vtkCellData.h"
+#include "vtkCleanPolyData.h"
+#include "vtkClipPolyData.h"
+#include "vtkContourFilter.h"
+#include "vtkDecimatePro.h"
+#include "vtkDelaunay3D.h"
+#include "vtkGeometryFilter.h"
+#include "vtkIdList.h"
+#include "vtkIdentityTransform.h"
+#include "vtkImageData.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkbisImageResample.h"
+#include "vtkImageThreshold.h"
+#include "vtkImplicitVolume.h"
+#include "vtkLinearSubdivisionFilter.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyDataConnectivityFilter.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkPolyDataNormals.h"
+#include "vtkPolyDataReader.h"
+#include "vtkPolyDataWriter.h"
+#include "vtkProperty.h"
+#include "vtkQuadricClustering.h"
+#include "vtkSmoothPolyDataFilter.h"
+#include "vtkSphereSource.h"
+#include "vtkThresholdPoints.h"
+#include "vtkTransformPolyDataFilter.h"
+#include "vtkTriangleFilter.h"
+#include "vtkUnstructuredGridToPolyDataFilter.h"
+#include "vtkWindowedSincPolyDataFilter.h"
+#include "vtkpxGUICallback.h"
+#include "vtkpxGUIPolyDataControl.h"
+#include "vtkpxMapActivationToPolyData.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkpxTstackReader.h"
+#include "vtkpxUtil.h"
+
+// *********************************************
+// ******* vtkpxGUIPolyDataControl Class *******
+// *********************************************
+
+
+vtkPolyData* vtkpxGUIPolyDataControl::clipboardPolyData=NULL;
+char vtkpxGUIPolyDataControl::clipboardName[200];
+
+
+vtkpxGUIPolyDataControl* vtkpxGUIPolyDataControl::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIPolyDataControl");
+  if(ret)
+      {
+	return (vtkpxGUIPolyDataControl*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIPolyDataControl;
+}
+
+
+vtkpxGUIPolyDataControl::vtkpxGUIPolyDataControl()
+{
+  num_surfaces=10;
+  current_surface=0;
+
+  has_surface=PXFalse;
+  simple_mode=PXFalse;
+  save_binary=PXTrue;
+  this->CurrentImage=NULL;
+
+ 
+  previousPolyData=NULL;
+  tempPolyData=NULL;
+  //clipboardPolyData=NULL;
+
+  internalTransform=vtkIdentityTransform::New();
+  owns_transform=PXTrue;  
+
+  num_renderers=4;
+
+  for (int i=0;i<num_surfaces;i++)
+      {
+	polyData[i]=NULL;
+	displayPolyData[i]=(i==0);
+	polyDataFilter[i]=NULL;
+	for (int j=0;j<num_renderers;j++)
+	  surfaceActor[j][i]=NULL;
+      }
+
+  for (int j=0;j<num_renderers;j++)
+    renderer[j]=NULL;
+
+  wireFrame=PXFalse;
+
+
+  has_surface=PXFalse;
+
+  decimateGUI=NULL;
+  smoothGUI=NULL;
+  normalsGUI=NULL;
+
+  cleanGUI=NULL;
+  curvatureGUI=NULL;
+  connectGUI=NULL;
+  extractGUI=NULL;
+  thresholdPointsGUI=NULL;
+  appendGUI=NULL;
+  extractObjectMapGUI=NULL;
+  mapFunctionalGUI=NULL;
+  extractObjectMapGUI=NULL;
+  displaySizeGUI=NULL;
+
+  opacityGUI=NULL;
+
+  //  transformControl=NULL;
+  if (clipboardPolyData==NULL)
+    strcpy(clipboardName,"None");
+  for (int ia=0;ia<=2;ia++)
+    lastPoint[ia]=0.0;
+  
+}
+
+vtkpxGUIPolyDataControl::~vtkpxGUIPolyDataControl()
+{
+  if (this->internalTransform!=NULL && owns_transform==PXTrue)
+    internalTransform->Delete();
+
+  if (!has_surface)
+      return;
+
+  previousPolyData->Delete();
+  tempPolyData->Delete();
+  //  clipboardPolyData->Delete();
+
+  
+  for (int i=0;i<num_surfaces;i++)
+    {
+      if (polyData[i]!=NULL)
+	polyData[i]->Delete();
+
+      if (polyDataFilter[i]!=NULL)
+	polyDataFilter[i]->Delete();
+      
+      for (int j=0;j<num_renderers;j++)
+	if (surfaceActor[j][i]!=NULL)
+	  surfaceActor[j][i]->Delete();
+    }
+}
+
+void vtkpxGUIPolyDataControl::SetSimpleMode()
+{
+  if (!this->Initialized)
+    simple_mode=PXTrue;
+}
+
+void vtkpxGUIPolyDataControl::InitGraphics()
+{
+  if (has_surface)
+    return;
+  
+  has_surface=PXTrue;
+  
+  previousPolyData=vtkPolyData::New();
+  tempPolyData=vtkPolyData::New();
+  if (clipboardPolyData==NULL)
+    clipboardPolyData=vtkPolyData::New();
+
+  vtkSphereSource* sphere=vtkSphereSource::New();
+  sphere->SetRadius(0.01);
+  sphere->SetThetaResolution(3);
+  sphere->SetPhiResolution(3);
+  sphere->Update();
+ 
+  for (int i=0;i<num_surfaces;i++)
+      {
+	polyData[i]=vtkPolyData::New();
+	polyData[i]->CopyStructure(sphere->GetOutput());
+
+	polyDataFilter[i]=vtkTransformPolyDataFilter::New();
+	polyDataFilter[i]->SetInput(polyData[i]);
+	polyDataFilter[i]->SetTransform(this->internalTransform);
+	double c[3];
+	vtkpxSurfaceUtil::GetColor(i,c);
+	for (int j=0;j<num_renderers;j++)
+	  {
+	    vtkPolyDataMapper* surfaceMapper=vtkPolyDataMapper::New();
+	    surfaceMapper->SetInput(polyDataFilter[i]->GetOutput());
+	    surfaceActor[j][i]=vtkActor::New();
+	    surfaceActor[j][i]->SetVisibility(0);
+	    surfaceActor[j][i]->GetProperty()->SetColor(c[0],c[1],c[2]);
+	    surfaceActor[j][i]->GetProperty()->SetLineWidth(2.0);
+	    surfaceActor[j][i]->SetMapper(surfaceMapper);
+	    surfaceMapper->Delete();
+	  }
+      }
+
+  sphere->Delete();
+}
+
+void vtkpxGUIPolyDataControl::SetRenderer(vtkRenderer *new_viewer,int num,int clip)
+{
+  num=Irange(num,0,3);
+  
+  if (renderer[num]!=NULL)
+    return;
+
+  InitGraphics();
+
+  renderer[num]=new_viewer;
+
+  //  fprintf(stderr,"Num=%d, clip=%d\n",num,clip);
+  
+  for (int i=0;i<num_surfaces;i++)
+    {
+      surfaceActor[num][i]->PickableOn();
+      renderer[num]->AddActor(surfaceActor[num][i]);
+      if (clip>0)
+	{
+	  /*if (i==0)
+	    fprintf(stderr,"Clipping viewer %d\n",num);*/
+	  surfaceActor[num][i]->GetProperty()->SetRepresentationToWireframe();
+	  surfaceActor[num][i]->GetProperty()->SetAmbient(1.0);
+	  surfaceActor[num][i]->GetProperty()->SetDiffuse(0.0);
+	  surfaceActor[num][i]->GetProperty()->SetSpecular(0.0);
+	}
+    }
+      
+  UpdateDisplay();
+  UpdateStatus();
+}
+/* -------------------------------------------------------------------------*/
+char* vtkpxGUIPolyDataControl::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+    return GetWidgetName();
+  
+  
+  vtkpxGUIComponent::Initialize(name,inside);
+  //  PXTkDialog::initDisplay();
+
+  PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+  
+  PXTkFrame* menubar=new PXTkFrame(this->EventManager,polyFrame);
+  polyFrame->addChildren("-side top -expand false -fill x",menubar);
+
+  PXTkLabel* lab=new PXTkLabel(this->EventManager,menubar,"");
+  lab->configure("-image","$::pxtclvtkpxcontrib::smalllogo ");
+  menubar->addChildren("-side right -expand false  -padx 5 -pady 5",lab);
+
+
+
+  PXTkMenuButton* but1=new PXTkMenuButton(this->EventManager,menubar,"File",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but1);
+  
+  PXTkMenu *menu1=new PXTkMenu(this->EventManager,but1,PXFalse);
+  menu1->addButton("Load",101);
+  //  menu1->addButton("Save",102);
+  menu1->addButton("Save As",103);
+  menu1->addSeparator();
+  menu1->addCheckBox("Binary Save",0,save_binary,104);
+  menu1->addSeparator();
+  if (this->EventParent)
+      menu1->addButton("Close",3);
+  else
+      menu1->addButton("Exit",1);
+  
+  PXTkMenuButton* but2=new PXTkMenuButton(this->EventManager,menubar,"Edit",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but2);
+  
+  PXTkMenu *menu2=new PXTkMenu(this->EventManager,but2,PXFalse);
+  menu2->addButton("Undo",201);
+  menu2->addSeparator();
+  menu2->addButton("Copy",202);
+  menu2->addButton("Paste",203);
+  menu2->addSeparator();
+  menu2->addButton("Append",310);
+  
+  PXTkMenuButton* but3=new PXTkMenuButton(this->EventManager,menubar,"Tools",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but3);
+  
+  PXTkMenu *menu3=new PXTkMenu(this->EventManager,but3,PXFalse);
+  menu3->addButton("Smooth",301);
+  menu3->addButton("Decimate",300);
+  menu3->addButton("Subdivide",316);
+  menu3->addButton("Cluster",304);
+  menu3->addButton("Normals",302);
+
+  if (!simple_mode)
+    {
+      //      menu3->addButton("Transform",306);
+      //      menu3->addSeparator();
+      menu3->addButton("Triangulate",303);
+      menu3->addButton("Connectivity",305);
+      menu3->addButton("Clip in Image",311);
+      menu3->addButton("Convex Hull",315);
+      menu3->addButton("Compute Curvatures",320);
+
+    }
+  menu3->addSeparator();
+  menu3->addButton("Extract Iso-Contour",307);
+  menu3->addButton("Threshold Points",312);
+  menu3->addButton("Extract Object-Map",309);
+  //  menu3->addSeparator();
+  //  menu3->addButton("Map Activation",308);
+
+  PXTkMenuButton* but4=new PXTkMenuButton(this->EventManager,menubar,"Display",-1,PXTrue);
+  menubar->addChildren("-side left -expand false ",but4);
+  
+  PXTkMenu *menu4=new PXTkMenu(this->EventManager,but4,PXFalse);
+  menu4->addButton("Surface Color",400);
+  menu4->addButton("Surface Opacity",406);
+  menu4->addButton("Display Size",314);
+  menu4->addSeparator();
+  menu4->addButton("Objectmap Colormap",402);
+  menu4->addButton("ShapeIndex Colormap",404);
+  menu4->addButton("Curvature  Colormap",405);
+  menu4->addSeparator();
+  menu4->addButton("Clear Attributes",204);
+  menu4->addSeparator();
+  menu4->addButton("Info",403);
+  menu4->addSeparator();
+  menu4->addButton("Hide All",401);
+
+
+  PXTkLabelFrame* vFrame=new PXTkLabelFrame(this->EventManager,polyFrame,"General Properties");
+  polyFrame->addChildren("-side bottom -expand false  -padx 5 -pady 5",vFrame);
+  vFrame->setPackMode(PXFalse);
+  
+  message=new PXTkLabel(this->EventManager,vFrame,"Num");
+  vFrame->gridRowColumnChild(message,0,0,1,3);
+  message->configure("-relief","ridge");
+  
+  currentSurface=new PXTkOptionMenu(this->EventManager,vFrame,"Surface 1",500);
+  for (int i=1;i<num_surfaces;i++)
+      {
+	sprintf(pxtk_buffer,"Surface %d",i+1);
+	currentSurface->addOption(pxtk_buffer);
+      }
+  vFrame->gridRowColumnChild(currentSurface,1,1);
+
+  /*displaySurface=new PXTkCheckButton(this->EventManager,vFrame,"Show Surface",501);
+    displaySurface->setState(displayPolyData[0]);*/
+  displayMode=new PXTkOptionMenu(this->EventManager,vFrame,"Do Not Show",501);
+  displayMode->addOption("Show as Surface");
+  displayMode->addOption("Show as Wireframe");
+  displayMode->addOption("Show as Points");
+  displayMode->setIndex(displayPolyData[0]);
+  vFrame->gridRowColumnChild(displayMode,1,2);
+  //  vFrame->gridRowColumnChild(displaySurface,1,2);
+
+  UpdateStatus();
+  return GetWidgetName();
+
+}
+/* -------------------------------------------------------------------------*/
+void  vtkpxGUIPolyDataControl::UpdateDisplay()
+{
+  if (!has_surface)
+    return;
+
+  int flag=0;
+
+  for (int i=0;i<num_surfaces;i++)
+    {
+      int np=polyData[i]->GetNumberOfPoints();
+      if (np<1)
+	{
+	  for (int j=0;j<num_renderers;j++)
+	    surfaceActor[j][i]->SetVisibility(0);
+	}
+      else
+	{
+	  flag++;
+	  double range[2];
+	  range[0]=0.0;
+	  range[1]=1.0;
+	  if (polyData[i]->GetPointData()->GetScalars()!=NULL)
+	    polyData[i]->GetPointData()->GetScalars()->GetRange(range);
+	  
+	  for (int j=0;j<num_renderers;j++)
+	    {
+	      if (displayPolyData[i]==0)
+		{
+		  surfaceActor[j][i]->SetVisibility(0);
+		}
+	      else
+		{
+		  vtkProperty* prop=surfaceActor[j][i]->GetProperty();
+		  switch (displayPolyData[i])
+		    {
+		    case 1:
+		      prop->SetRepresentationToSurface();
+		      prop->SetDiffuse(1.0);
+		      prop->SetAmbient(0.0);
+		      prop->SetSpecular(0.0);
+		      // changes by mpj
+		      //		      prop->SetOpacity(0.5);
+		      // changes by mpj
+		      break;
+		    case 2:
+		      prop->SetRepresentationToWireframe();
+		      prop->SetDiffuse(0.0);
+		      prop->SetAmbient(1.0);
+		      prop->SetSpecular(0.0);
+		      break;
+		    case 3:
+		      prop->SetRepresentationToPoints();
+		      prop->SetDiffuse(0.0);
+		      prop->SetAmbient(1.0);
+		      prop->SetSpecular(0.0);
+		      prop->SetPointSize(3.0);
+		      break;
+		    }
+		  surfaceActor[j][i]->SetVisibility(1);
+		  if (polyData[i]->GetPointData()->GetScalars()!=NULL)
+		    {
+		      if (polyData[i]->GetPointData()->GetScalars()->GetNumberOfComponents()==1)
+			{
+			  surfaceActor[j][i]->GetMapper()->SetScalarRange(range);
+			  surfaceActor[j][i]->GetMapper()->ScalarVisibilityOn();
+			} 
+		      else 
+			{
+			  //fprintf(stderr,"Scalars (3)\n");
+			  surfaceActor[j][i]->GetMapper()->ScalarVisibilityOn();
+			  surfaceActor[j][i]->GetMapper()->SetColorModeToDefault();
+			}
+		    }
+		      
+		}
+	    }
+	}
+    }
+
+  if (flag)
+    {
+      for (int i=0;i<num_renderers;i++)
+	if (renderer[i]!=NULL)
+	  renderer[i]->Render();
+    }
+
+  return;
+}
+
+int  vtkpxGUIPolyDataControl::SetCurrentSurface(int s)
+{
+  s=Irange(s,0,num_surfaces-1);
+  if (s==current_surface)
+      return s;
+
+  current_surface=s;
+  displayMode->setIndex(displayPolyData[current_surface]);
+
+  UpdateDisplay();
+  UpdateStatus();
+  return current_surface;
+}
+
+int  vtkpxGUIPolyDataControl::UpdateStatus()
+{
+  if (has_surface)
+    {
+      sprintf(pxtk_buffer,"Name=%s Points=%d Polys=%d",
+	      currentSurface->getLabel(current_surface),
+	      polyData[current_surface]->GetNumberOfPoints(),
+	      polyData[current_surface]->GetNumberOfCells());
+      return message->setText(pxtk_buffer);
+    }
+  else
+    return 0;
+}
+
+
+int  vtkpxGUIPolyDataControl::HandleEvent(int event)
+{
+  if (!this->Initialized)
+      return TCL_OK;
+
+  if (event<10)
+      return this->EventManager->handleDirectEvent(event);
+
+  int dorender=0;
+
+  if (!has_surface)
+      return TCL_OK;
+
+  switch(event)
+      {
+      case 101: // Load Surface
+	dorender=this->LoadCurrentSurface("");
+	break;
+	
+      case 102: // Save Surface
+      case 103:
+	{
+	  if (polyData[current_surface]->GetNumberOfPoints()<1)
+	    {
+	      this->EventManager->messageBox("Cannot Save Surface, no surface in memory!","Error Message ...");
+	    }
+	  else
+	    {
+	      if (event==103)
+		{
+		  char *line=this->EventManager->getSaveFilenameComplex("Save PolyData","sur.vtk",
+									"{\"VTK File\" {\".vtk\"}}  {\"All Files\" {\"*\"}}");
+		  if (line==NULL)
+		    break;
+		  if (strlen(line)<1)
+		    break;
+		
+		  strcpy(pxtk_buffer2,line);
+		}
+	      else
+		{
+		  int offset=0;
+		  if (current_surface==9)
+		    offset=1;
+		  int n=strlen(currentSurface->getLabel(current_surface))-2-offset;
+		  strncpy(pxtk_buffer2,currentSurface->getLabel(current_surface),n);
+		  if (strcmp(pxtk_buffer2,"Surface")==0)
+		    {
+		      n+=2+offset;
+		      strncpy(pxtk_buffer2,currentSurface->getLabel(current_surface),n);
+		    }
+		  pxtk_buffer2[n]=(char)0;
+		  for (int i=0;i<n;i++)
+		    {
+		      if (pxtk_buffer2[i]==' ')
+			pxtk_buffer2[i]='_';
+		    }
+		  
+		  char* newname=anacreatefilename(pxtk_buffer2,".vtk",".vtk");
+		  strcpy(pxtk_buffer2,newname);
+		  delete [] newname;
+		}
+	      vtkPolyDataWriter* writer=vtkPolyDataWriter::New();
+	      vtkpxGUICallback* clb=this->AddMethodsToFilter(writer,"Saving Surface");
+	      
+	      writer->SetFileName(pxtk_buffer2);
+	      writer->SetInput(polyData[current_surface]);
+	      if (this->save_binary==PXTrue)
+		writer->SetFileTypeToBinary();
+	      else
+		{
+		  writer->SetFileTypeToASCII();
+		  //fprintf(stderr,"Saving Ascii\n");
+		}
+	      this->WatchOn();
+	      writer->Update();
+	      writer->Delete();
+	      clb->Delete();
+	      sprintf(pxtk_buffer2,"%s.%d",PXTkApp::getFilenameTail(pxtk_buffer2),current_surface+1);
+	      currentSurface->changeLabel(current_surface,pxtk_buffer2);
+	      UpdateStatus();
+	      this->WatchOff();
+	    }
+	}
+	break;
+
+      case 104:
+	if (save_binary==PXTrue)
+	  save_binary=PXFalse;
+	else
+	  save_binary=PXTrue;
+	break;
+
+      case 201: // Undo
+	polyData[current_surface]->ShallowCopy(previousPolyData);
+	UpdateStatus();
+	dorender=1;
+	break;
+	
+      case 202: // Copy
+	clipboardPolyData->ShallowCopy(polyData[current_surface]);
+	strncpy(clipboardName,currentSurface->getLabel(current_surface),200);
+	break;
+	
+      case 203: // Paste
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	polyData[current_surface]->ShallowCopy(clipboardPolyData);
+	if (clipboardName[0]!='?')
+	  sprintf(pxtk_buffer2,"Copy of %s.%d",clipboardName,current_surface+1);
+	else
+	  sprintf(pxtk_buffer2,"%s.%d",&clipboardName[1],current_surface+1);
+	currentSurface->changeLabel(current_surface,pxtk_buffer2);
+	UpdateStatus();
+	UpdateDisplay();
+	dorender=1;
+	break;
+	
+      case 204: // Clear Pre-loaded colors etc 
+	polyData[current_surface]->GetPointData()->SetScalars(NULL);
+	dorender=1;
+	break;
+
+      case 300: // Decimate
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	doDecimate(0);
+	break;
+	
+      case 350:
+	dorender=doDecimate(1);
+	UpdateStatus();
+	break;
+	
+      case 301: // Smooth;
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	doSmooth(0);
+	break;
+
+      case 351:
+	dorender=doSmooth(1);
+	break;
+
+      case 302: // Normals;
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	doNormals(0);
+	break;
+       
+      case 352:
+	dorender=doNormals(1);
+	break;
+	
+      case 303: // Triangulate
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	dorender=doTriangulate();
+	UpdateStatus();
+	break;
+	
+      case 304: // Clean
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	doClean(0);
+	break;
+	
+      case 354:
+	dorender=doClean(1);
+	UpdateStatus();
+	break;
+	
+      case 305: // Connectivity
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	doConnect(0);
+	break;
+
+      case 355:
+	dorender=doConnect(1);
+	UpdateStatus();
+	break;
+
+	/*      case 306:
+	doTransform(0);
+	break;
+
+      case 356:
+	dorender=doTransform(1);
+	UpdateStatus();
+	break;*/
+
+      case 307:
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	doExtract(0);
+	break;
+
+      case 308:
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	doMapFunctional(0);
+	break;
+
+      case 309:
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	doExtractObjectMap(0);
+	break;
+
+      case 310:
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	doAppend(0);
+	break;
+      
+      case 311: // Clip
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	dorender=doClip();
+	UpdateStatus();
+	break;
+
+      case 312:
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	this->doThresholdPoints(0);
+	break;
+
+
+      case 314:
+	doChangeDisplaySize(0);
+	break;
+
+      case 315:
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	dorender=doDelaunay3D();
+	break;
+
+      case 316:
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	dorender=doSubdivision();
+	break;
+
+
+      case 320: // Compute Curvature
+	previousPolyData->ShallowCopy(polyData[current_surface]);
+	doCurvature(0);
+	break;
+	
+      case 321:
+	dorender=doCurvature(1);
+	UpdateStatus();
+	break;
+	
+
+
+      case 357:
+	dorender=doExtract(1);
+	UpdateStatus();
+	break;
+
+      case 358:
+	dorender=doMapFunctional(1);
+	UpdateStatus();
+	break;
+
+      case 359:
+	dorender=doExtractObjectMap(1);
+	UpdateStatus();
+	break;
+
+
+      case 360:
+	dorender=doAppend(1);
+	UpdateStatus();
+	break;
+
+      case 361:
+	dorender=doAppend(2);
+	UpdateStatus();
+	break;
+
+
+      case 362:
+	dorender=this->doThresholdPoints(1);
+	UpdateStatus();
+	break;
+
+      case 363:
+	dorender=this->doThresholdPoints(2);
+	UpdateStatus();
+	break;
+
+
+      case 374:
+	doChangeDisplaySize(1);
+	break;
+
+      case 375:
+	doChangeDisplaySize(2);
+	break;
+
+
+      case 400: // Surface Color
+	{
+	  double c[3];
+	  vtkProperty* prop=surfaceActor[0][current_surface]->GetProperty();
+	  prop->GetColor(c);
+	  int a=this->EventManager->d_colorBox("Surface Color",c[0],c[1],c[2]);
+	  if (a==1)
+	    {
+	      for (int k=0;k<num_renderers;k++)
+		surfaceActor[k][current_surface]->GetProperty()->SetColor(c[0],c[1],c[2]);
+	      dorender=1;
+	    }
+	}
+	break;
+	
+      case 401:
+	{
+	  for (int i=0;i<num_surfaces;i++)
+	    displayPolyData[i]=0;
+	  UpdateDisplay();
+	  dorender=1;
+	}
+	break;
+
+      case 402:
+	dorender=vtkpxSurfaceUtil::AddObjectMapLookupTableToSurface(polyData[current_surface]);
+	break;
+
+      case 404:
+	dorender=vtkpxSurfaceUtil::AddShapeIndexLookupTableToSurface(polyData[current_surface]);
+	break;
+
+      case 405:
+	dorender=vtkpxSurfaceUtil::AddCurvatureLookupTableToSurface(polyData[current_surface]);
+	break;
+
+
+	// mpj
+      case 406:
+	dorender=doOpacity(0);
+	UpdateStatus();
+	break;
+      case 407:
+	dorender=doOpacity(1);
+	break;
+	// mpj
+
+      case 403:
+	if (has_surface)
+	  {
+	    double range[2];
+	    if (polyData[current_surface]->GetPointData()->GetScalars()!=NULL)
+	      {
+		int ns=polyData[current_surface]->GetPointData()->GetScalars()->GetNumberOfTuples();
+		polyData[current_surface]->GetPointData()->GetScalars()->GetRange(range);
+		if (polyData[current_surface]->GetPointData()->GetScalars()->GetLookupTable()!=NULL)
+		  sprintf(pxtk_buffer2,"\n scalars=%d LKPT (range=%.1f:%.1f)",ns,range[0],range[1]);
+		else
+		  sprintf(pxtk_buffer2,"\n scalars=%d NONE (range=%.1f:%.1f)",ns,range[0],range[1]);
+	      }
+	    else 
+	      strcpy(pxtk_buffer2," \n no scalars ");
+	    
+	    if (polyData[current_surface]->GetPointData()->GetNormals()!=NULL)
+	      {
+		int ns=polyData[current_surface]->GetPointData()->GetNormals()->GetNumberOfTuples();
+		sprintf(pxtk_buffer3,"%s\n Normals=%d ",pxtk_buffer2,ns);
+	      }
+	    else
+	      sprintf(pxtk_buffer3," %s\n no normals",pxtk_buffer2);
+	    
+	    sprintf(pxtk_buffer,"Points=%d Polys=%d  %s",
+		    polyData[current_surface]->GetNumberOfPoints(),
+		    polyData[current_surface]->GetNumberOfCells(),
+		    pxtk_buffer3);
+	    this->EventManager->messageBox(pxtk_buffer,"Current Surface Info ...");
+	  }
+	break;
+	    
+      case 500: // Current Surface;
+	SetCurrentSurface(currentSurface->getIndex());
+	dorender=1;
+	break;
+	
+      case 501: // Show Surface
+	displayPolyData[currentSurface->getIndex()]=displayMode->getIndex();
+	UpdateDisplay();
+	dorender=1;
+	break;
+      }
+
+  if (dorender)
+    {
+      if (this->EventParent!=NULL && this->CallbackNo>0)
+	{
+	  this->EventParent->HandleEvent(CallbackNo);
+	}
+      else 
+	{
+	  for (int i=0;i<num_renderers;i++)
+	    if (renderer[i]!=NULL)
+	      renderer[i]->Render();
+	}
+    }
+  return TCL_OK;
+}
+
+
+int vtkpxGUIPolyDataControl::GetCurrentSurface()
+{
+  return current_surface;
+}
+
+vtkPolyData* vtkpxGUIPolyDataControl::GetSurface(int index)
+{
+  int i=index;
+  if (index==-1)
+    i=current_surface;
+  else
+    i=Irange(index,0,num_surfaces-1);
+
+  return polyData[i];
+}
+     
+void vtkpxGUIPolyDataControl::SetSurface(int index,vtkPolyData* data)
+{
+  int i=Irange(index,0,num_surfaces-1);
+  previousPolyData->ShallowCopy(polyData[i]);
+  polyData[i]->ShallowCopy(data);
+  polyData[i]->Modified();
+  
+  for (int v=0;v<num_renderers;v++)
+    {
+      if (renderer[v]!=NULL)
+	{
+	  if (surfaceActor[v][i]->GetVisibility()==1)
+	    {
+	      surfaceActor[v][i]->GetMapper()->Modified();
+	      surfaceActor[v][i]->Modified();
+	      renderer[v]->Render();
+	    }
+	}
+    }
+  UpdateStatus();
+}
+
+void vtkpxGUIPolyDataControl::SetSurface(int index,vtkPolyData* data,const char* name)
+{
+  int i=Irange(index,0,num_surfaces-1);
+  SetSurface(i,data);
+
+  sprintf(pxtk_buffer2,"%s.%d",name,i+1);
+  currentSurface->changeLabel(i,pxtk_buffer2);
+
+}
+
+void vtkpxGUIPolyDataControl::SetClipboardSurface(vtkPolyData* data,const char* name)
+{
+  if (clipboardPolyData!=NULL)
+    {
+      clipboardPolyData->ShallowCopy(data);
+      if (name!=NULL)
+	  strcpy(clipboardName,name);
+    }
+}
+
+void vtkpxGUIPolyDataControl::SetImage(vtkImageData* new_image)
+{
+  this->CurrentImage=new_image;
+
+  if (extractGUI!=NULL)
+    {
+      if (extractGUI->isOpen())
+	extractGUI->popdownDialog();
+    }
+
+  if (thresholdPointsGUI!=NULL)
+    {
+      if (thresholdPointsGUI->isOpen())
+	thresholdPointsGUI->popdownDialog();
+    }
+
+
+  if (extractObjectMapGUI!=NULL)
+    {
+      if (extractObjectMapGUI->isOpen())
+	extractObjectMapGUI->popdownDialog();
+    }
+
+  if (mapFunctionalGUI!=NULL)
+    {
+      if (mapFunctionalGUI->isOpen())
+	mapFunctionalGUI->popdownDialog();
+    }
+
+  /*  if (transformControl!=NULL)
+    {
+      if (this->CurrentImage!=NULL)
+	transformControl->SetDimensions(this->CurrentImage);
+	}*/
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIPolyDataControl::SetLastPoint(double pt[3])
+{
+  for (int ia=0;ia<=2;ia++)
+    lastPoint[ia]=pt[ia];
+  
+  if (connectGUI!=NULL)
+    {
+      if (connectGUI->isOpen())
+	{
+	  sprintf(pxtk_buffer,"Last Point (%6.2f,%6.2f,%6.2f)",lastPoint[0],lastPoint[1],lastPoint[2]);
+	  connectPoint->setText(pxtk_buffer);
+	}
+    }
+}
+
+int vtkpxGUIPolyDataControl::doOpacity(int apply)
+{
+
+  if (apply==0)
+    {
+      if (opacityGUI==NULL) {
+	
+	PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	opacityGUI=new PXTkDialog(this->EventManager,polyFrame,"Opacity Controls",PXFalse);
+	opacityGUI->initDisplay();
+	
+	PXTkFrame* frame=(PXTkFrame*)opacityGUI->getMainWindow();
+	opacityFactor=new PXTkScale(opacityGUI,frame,"Opacity Factor",-1,PXTrue);
+	opacityFactor->setRange(0.0,1.0);
+	opacityFactor->setResolution(0.01);
+	opacityFactor->setValue(1.0);
+
+	PXTkFrame* fr2=new PXTkFrame(opacityGUI,frame);
+	PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Apply",407);
+	PXTkButton* b4=new PXTkButton(opacityGUI,fr2,"Close",3);
+
+	frame->addChildren("-side top -expand true -fill x",opacityFactor,fr2);
+	fr2->addChildren("-side left -expand true -fill x",b2,b4);
+
+      }
+      
+      vtkProperty* prop=surfaceActor[0][current_surface]->GetProperty();
+      
+      opacityFactor->setValue(prop->GetOpacity());
+
+      opacityGUI->popupDialog();
+      
+      return 0;
+
+    }
+  
+  for (int k=0;k<num_renderers;k++)
+    surfaceActor[k][current_surface]->GetProperty()->SetOpacity(opacityFactor->getValue());
+  
+  return 1;
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIPolyDataControl::doDecimate(int apply)
+{
+
+  if (polyData[current_surface]->GetNumberOfPoints()<2)
+    {
+      this->EventManager->messageBox("Cannot Decimate Surface, no surface in memory!","Error Message ...");
+      return 0;
+    }
+
+  if (apply==0)
+      {
+	if (decimateGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	      decimateGUI=new PXTkDialog(this->EventManager,polyFrame,"Decimate Controls",PXFalse);
+	      decimateGUI->initDisplay();
+	      
+	      PXTkFrame* frame=(PXTkFrame*)decimateGUI->getMainWindow();
+	      decimateFactor=new PXTkScale(decimateGUI,frame,"Factor",-1,PXTrue);
+	      decimateFactor->setRange(0.0,1.0);
+	      decimateFactor->setResolution(0.01);
+	      decimateFactor->setValue(0.0);
+	      
+	      preserveTopology=new PXTkCheckButton(decimateGUI,frame,"Preserve Topology",-1);
+	      preserveTopology->setState(PXTrue);
+
+	      PXTkFrame* fr2=new PXTkFrame(decimateGUI,frame);
+	      PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Decimate",350);
+	      PXTkButton* b3=new PXTkButton(this->EventManager,fr2,"Undo",201);
+	      PXTkButton* b4=new PXTkButton(decimateGUI,fr2,"Close",3);
+	      frame->addChildren("-side top -expand true -fill x",decimateFactor,preserveTopology,fr2);
+	      fr2->addChildren("-side left -expand true -fill x",b2,b3,b4);
+	    }
+  	decimateGUI->popupDialog();
+	//decimateGUI->setModality(PXTrue);
+	return 0;
+      }
+
+  
+  //decimateGUI->popdownDialog();
+
+  vtkTriangleFilter* triFilter=vtkTriangleFilter::New();
+  triFilter->SetInput(polyData[current_surface]);
+  
+  vtkDecimatePro* deciFilter=vtkDecimatePro::New();
+  vtkpxGUICallback* clb=this->AddMethodsToFilter(deciFilter,"Decimating Surface");
+  deciFilter->SetInput(triFilter->GetOutput());
+  deciFilter->SetTargetReduction(decimateFactor->getValue());
+  
+  if (preserveTopology->getState()==PXTrue)
+      deciFilter->PreserveTopologyOn();
+  else
+      deciFilter->PreserveTopologyOff();
+
+  this->WatchOn();
+  triFilter->Update();
+  deciFilter->Update();
+  polyData[current_surface]->ShallowCopy(deciFilter->GetOutput());
+
+  deciFilter->Delete();
+  triFilter->Delete();
+  this->WatchOff();  
+  clb->Delete();
+
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIPolyDataControl::doSmooth(int apply)
+{
+  if (polyData[current_surface]->GetNumberOfPoints()<2)
+    {
+      this->EventManager->messageBox("Cannot Smooth Surface, no surface in memory!","Error Message ...");
+      return 0;
+    }
+
+  if (apply==0)
+      {
+	if (smoothGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	      smoothGUI=new PXTkDialog(this->EventManager,polyFrame,"Smooth Controls",PXFalse);
+	      smoothGUI->initDisplay();
+	      
+	      PXTkFrame* frame=(PXTkFrame*)smoothGUI->getMainWindow();
+	      smoothIterations=new PXTkScale(smoothGUI,frame,"Iterations",-1,PXTrue);
+	      smoothIterations->setRange(0.0,200);
+	      smoothIterations->setResolution(1);
+	      smoothIterations->setValue(0.0);
+	      
+	      smoothRelaxation=new PXTkScale(smoothGUI,frame,"Relaxation Factor (Lapl)",-1,PXTrue);
+	      smoothRelaxation->setRange(0.0,1.0);
+	      smoothRelaxation->setResolution(0.02);
+	      smoothRelaxation->setValue(0.2);
+
+	      smoothEdgeButton=new PXTkCheckButton(smoothGUI,frame,"Smooth Boundaries (Sinc)",-1,PXTrue);
+
+	      smoothMethod=new PXTkOptionMenu(smoothGUI,frame,"Laplacian",-1);
+	      smoothMethod->addOption("Windowed Sinc");
+	      smoothMethod->setIndex(1);
+	      	      
+	      PXTkFrame* fr2=new PXTkFrame(smoothGUI,frame);
+	      PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Smooth",351);
+	      PXTkButton* b4=new PXTkButton(this->EventManager,fr2,"Undo",201);
+	      PXTkButton* b3=new PXTkButton(smoothGUI,fr2,"Close",3);
+	      frame->addChildren("-side top -expand true -fill x",smoothMethod,smoothIterations,smoothRelaxation,smoothEdgeButton);
+	      frame->addChildren("-side top -expand true -fill x",fr2);
+	      fr2->addChildren("-side left -expand true -fill x",b2,b4,b3);
+	    }
+  
+	smoothGUI->popupDialog();
+	//smoothGUI->setModality(PXTrue);
+	return 0;
+      }
+
+  if (smoothMethod->getIndex()==0)
+    {
+      vtkSmoothPolyDataFilter* smoothFilter=vtkSmoothPolyDataFilter::New();  
+
+      vtkpxGUICallback* clb=this->AddMethodsToFilter(smoothFilter,"Smoothing Surface");
+      //this->WatchOn();      
+      smoothFilter->SetInput(polyData[current_surface]);
+      smoothFilter->SetNumberOfIterations(int(smoothIterations->getValue()));
+      smoothFilter->SetRelaxationFactor(smoothRelaxation->getValue());
+      smoothFilter->Update();
+      polyData[current_surface]->ShallowCopy(smoothFilter->GetOutput());
+      smoothFilter->Delete();
+      clb->Delete();
+
+      //      this->WatchOff();
+    }
+  else
+    {
+      vtkWindowedSincPolyDataFilter* smoothFilter=vtkWindowedSincPolyDataFilter::New();  
+      vtkpxGUICallback* clb=this->AddMethodsToFilter(smoothFilter,"Smoothing Surface");
+      this->WatchOn();      
+      smoothFilter->SetInput(polyData[current_surface]);
+      smoothFilter->SetNumberOfIterations(int(smoothIterations->getValue()));
+      if (smoothEdgeButton->getState())
+	smoothFilter->SetBoundarySmoothing(1);
+      else
+	smoothFilter->SetBoundarySmoothing(0);
+      smoothFilter->Update();
+      polyData[current_surface]->ShallowCopy(smoothFilter->GetOutput());
+      smoothFilter->Delete();
+      this->WatchOff();
+      clb->Delete();
+
+    }
+  return 1;
+}
+/* -------------------------------------------------------------------------*/ 
+int vtkpxGUIPolyDataControl::doNormals(int apply)
+{
+
+  if (polyData[current_surface]->GetNumberOfPoints()<2)
+    {
+      this->EventManager->messageBox("Cannot Calculate Surface Normals, no surface in memory!","Error Message ...");
+      return 0;
+    }
+
+  if (apply==0)
+      {
+	if (normalsGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	      normalsGUI=new PXTkDialog(this->EventManager,polyFrame,"Normals Controls",PXFalse);
+	      normalsGUI->initDisplay();
+	      
+	      PXTkFrame* frame=(PXTkFrame*)normalsGUI->getMainWindow();
+	      featureAngle=new PXTkScale(normalsGUI,frame,"Feature Angle",-1,PXTrue);
+	      featureAngle->setRange(0.0,180.0);
+	      featureAngle->setResolution(1.0);
+	      featureAngle->setValue(30.0);
+	      
+	      edgeSplitButton=new PXTkCheckButton(normalsGUI,frame,"Edge Splitting",-1);
+	      edgeSplitButton->setState(PXTrue);
+	      
+	      flipNormalsButton=new PXTkCheckButton(normalsGUI,frame,"Flip Normals",-1);
+	      flipNormalsButton->setState(PXFalse);
+
+	      PXTkFrame* fr2=new PXTkFrame(normalsGUI,frame);
+	      PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Apply",352);
+	      PXTkButton* b4=new PXTkButton(this->EventManager,fr2,"Undo",201);
+	      PXTkButton* b3=new PXTkButton(normalsGUI,fr2,"Close",3);
+	      frame->addChildren("-side top -expand true -fill x",featureAngle,edgeSplitButton,flipNormalsButton,fr2);
+	      fr2->addChildren("-side left -expand true -fill x",b2,b4,b3);
+	    }
+	
+	normalsGUI->popupDialog();
+	//normalsGUI->setModality(PXTrue);
+	return 0;
+      }
+
+  
+  //normalsGUI->popdownDialog();
+  this->WatchOn();
+
+  vtkPolyDataNormals* normalsFilter=vtkPolyDataNormals::New();
+  vtkpxGUICallback* clb=this->AddMethodsToFilter(normalsFilter,"Calculating Normals");
+  normalsFilter->SetInput(polyData[current_surface]);
+  normalsFilter->SetFeatureAngle(featureAngle->getValue());
+  if (edgeSplitButton->getState()==PXTrue)
+      normalsFilter->SetSplitting(1);
+  else
+      normalsFilter->SetSplitting(0);
+
+  if (flipNormalsButton->getState()==PXTrue)
+      normalsFilter->SetFlipNormals(1);
+  else
+      normalsFilter->SetFlipNormals(0);
+  normalsFilter->Update();
+  polyData[current_surface]->ShallowCopy(normalsFilter->GetOutput());
+  normalsFilter->Delete();
+  this->WatchOff();
+  clb->Delete();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIPolyDataControl::doTriangulate(int apply)
+{
+  if (polyData[current_surface]->GetNumberOfPoints()<2)
+    {
+      this->EventManager->messageBox("Cannot Triangulate Surface, no surface in memory!","Error Message ...");
+      return 0;
+    }
+
+  this->WatchOn();
+  vtkTriangleFilter* triFilter=vtkTriangleFilter::New();
+  vtkpxGUICallback* clb=this->AddMethodsToFilter(triFilter,"Triangulating Surface");
+  triFilter->SetInput(polyData[current_surface]);
+  triFilter->Update();
+  polyData[current_surface]->ShallowCopy(triFilter->GetOutput());
+  triFilter->Delete();
+  clb->Delete();
+  this->WatchOff();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/ 
+int vtkpxGUIPolyDataControl::doDelaunay3D(int apply)
+{
+  if (polyData[current_surface]->GetNumberOfPoints()<2)
+    {
+      this->EventManager->messageBox("Cannot do Delaunay3D, no surface in memory!","Error Message ...");
+      return 0;
+    }
+
+  this->WatchOn();
+  vtkDelaunay3D* dFilter=vtkDelaunay3D::New();
+  dFilter->SetInput(polyData[current_surface]);
+  dFilter->Update();
+
+  vtkDataSet* dt=(vtkDataSet*)(dFilter->GetOutput());
+  /*  vtkUnstructuredGridToPolyDataFilter* filt=vtkUnstructuredGridToPolyDataFilter::New();
+  filt->SetInput(dFilter->GetOutput());*/
+  
+
+  vtkGeometryFilter* geom=vtkGeometryFilter::New();
+  geom->SetInput(dt);
+
+
+  vtkpxGUICallback* clb2=this->AddMethodsToFilter(geom,"Extracting Outer Surface");
+  geom->MergingOn();
+  geom->Update();
+
+  polyData[current_surface]->ShallowCopy(geom->GetOutput());
+  dFilter->Delete();
+  geom->Delete();
+//  filt->Delete();
+  clb2->Delete();
+  this->WatchOff();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/ 
+int vtkpxGUIPolyDataControl::doSubdivision(int apply)
+{
+  if (polyData[current_surface]->GetNumberOfPoints()<2)
+    {
+      this->EventManager->messageBox("Cannot do Delaunay3D, no surface in memory!","Error Message ...");
+      return 0;
+    }
+
+  this->WatchOn();
+  vtkLinearSubdivisionFilter* dFilter=vtkLinearSubdivisionFilter::New();
+  dFilter->SetInput(polyData[current_surface]);
+  dFilter->SetNumberOfSubdivisions(1);
+  vtkpxGUICallback* clb2=this->AddMethodsToFilter(dFilter,"Extracting Outer Surface");
+  dFilter->Update();
+
+  polyData[current_surface]->ShallowCopy(dFilter->GetOutput());
+  dFilter->Delete();
+  clb2->Delete();
+  this->WatchOff();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/ 
+int vtkpxGUIPolyDataControl::doConnect(int apply)
+{
+
+  if (polyData[current_surface]->GetNumberOfPoints()<2)
+    {
+      this->EventManager->messageBox("Cannot Connect Surface, no surface in memory!","Error Message ...");
+      return 0;
+    }
+
+  if (apply==0)
+      {
+	if (connectGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	      connectGUI=new PXTkDialog(this->EventManager,polyFrame,"Connect Controls",PXFalse);
+	      connectGUI->initDisplay();
+	      
+	      PXTkFrame* frame=(PXTkFrame*)connectGUI->getMainWindow();
+	      connectType=new PXTkOptionMenu(connectGUI,frame,"Largest Region",-1);
+	      connectType->addOption("Nearest Point");
+	      connectType->setIndex(0);
+
+	      connectPoint=new PXTkLabel(this->EventManager,frame,"");
+
+	      PXTkFrame* fr2=new PXTkFrame(connectGUI,frame);
+	      PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Apply",355);
+	      PXTkButton* b4=new PXTkButton(this->EventManager,fr2,"Undo",201);
+	      PXTkButton* b3=new PXTkButton(connectGUI,fr2,"Close",3);
+	      frame->addChildren("-side top -expand true -fill x",connectType,connectPoint,fr2);
+	      fr2->addChildren("-side left -expand true -fill x",b2,b4,b3);
+	    }
+	
+	sprintf(pxtk_buffer,"Last Point (%6.2f,%6.2f,%6.2f)",lastPoint[0],lastPoint[1],lastPoint[2]);
+	connectPoint->setText(pxtk_buffer);
+	connectGUI->popupDialog();
+	return 0;
+      }
+
+  this->WatchOn();
+  vtkPolyDataConnectivityFilter* connectFilter=vtkPolyDataConnectivityFilter::New();
+  vtkpxGUICallback* clb=this->AddMethodsToFilter(connectFilter,"Connectivity Filter");
+  connectFilter->SetInput(polyData[current_surface]);
+  if (connectType->getIndex()==0)
+      {
+	connectFilter->SetExtractionModeToLargestRegion();
+      }
+  else if (connectType->getIndex()==1)
+      {
+	connectFilter->SetExtractionModeToClosestPointRegion();
+	connectFilter->SetClosestPoint(lastPoint);
+      }
+	
+  connectFilter->Update();
+  //fprintf(stderr,"Number of Regions=%d\n",connectFilter->GetNumberOfExtractedRegions());
+ 
+
+  polyData[current_surface]->ShallowCopy(connectFilter->GetOutput());
+  connectFilter->Delete();
+  clb->Delete();
+  this->WatchOff();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/  
+int vtkpxGUIPolyDataControl::doClean(int apply)
+{
+
+  if (polyData[current_surface]->GetNumberOfPoints()<2)
+    {
+      this->EventManager->messageBox("Cannot Clean Surface, no surface in memory!","Error Message ...");
+      return 0;
+    }
+
+  if (apply==0)
+      {
+	if (cleanGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	      cleanGUI=new PXTkDialog(this->EventManager,polyFrame,"Clean Controls",PXFalse);
+	      cleanGUI->initDisplay();
+	      PXTkFrame* frame=(PXTkFrame*)cleanGUI->getMainWindow();
+
+	      cleanMethod=new PXTkOptionMenu(cleanGUI,frame,"Distance Sampling",-1);
+	      cleanMethod->addOption("Quadric Clustering");
+	      cleanMethod->setIndex(0);
+	      
+	      cleanTolerance=new PXTkScale(cleanGUI,frame,"Tolerance",-1,PXTrue);
+	      cleanTolerance->setRange(0.0,15.0);
+	      cleanTolerance->setResolution(0.1);
+	      cleanTolerance->setValue(1.0);
+	      
+	      PXTkFrame* fr2=new PXTkFrame(cleanGUI,frame);
+	      PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Apply",354);
+	      PXTkButton* b4=new PXTkButton(this->EventManager,fr2,"Undo",201);
+	      PXTkButton* b3=new PXTkButton(cleanGUI,fr2,"Close",3);
+	      frame->addChildren("-side top -expand true -fill x",cleanMethod,cleanTolerance,fr2);
+	      fr2->addChildren("-side left -expand true -fill x",b2,b4,b3);
+	    }
+	
+	cleanGUI->popupDialog();
+	//cleanGUI->setModality(PXTrue);
+	return 0;
+      }
+
+  //  cleanGUI->popdownDialog();
+  this->WatchOn();
+
+  if (cleanMethod->getIndex()==0)
+    {
+      vtkCleanPolyData* cleanerFilter=vtkCleanPolyData::New();
+      vtkpxGUICallback* clb=this->AddMethodsToFilter(cleanerFilter,"Clean Surface Filter");
+      cleanerFilter->SetInput(polyData[current_surface]);
+      cleanerFilter->DebugOff();
+      cleanerFilter->SetToleranceIsAbsolute(1);
+      cleanerFilter->SetAbsoluteTolerance(cleanTolerance->getValue());
+      cleanerFilter->Update();
+      polyData[current_surface]->ShallowCopy(cleanerFilter->GetOutput());
+      cleanerFilter->Delete();
+      clb->Delete();
+    }
+  else
+    {
+      vtkTriangleFilter* triFilter=vtkTriangleFilter::New();
+      triFilter->SetInput(polyData[current_surface]);
+      triFilter->Update();
+
+      double bounds[6];
+      triFilter->GetOutput()->GetBounds(bounds);
+      double sp=cleanTolerance->getValue();
+
+      vtkQuadricClustering* clusterFilter=vtkQuadricClustering::New();
+      vtkpxGUICallback* clb=this->AddMethodsToFilter(clusterFilter,"Cluster Surface Filter");
+      clusterFilter->SetInput(triFilter->GetOutput());
+
+      clusterFilter->SetDivisionOrigin(bounds[0],bounds[2],bounds[4]);
+      clusterFilter->SetDivisionSpacing(sp,sp,sp);
+      clusterFilter->SetNumberOfXDivisions(int(1.5+(bounds[1]-bounds[0])/sp));
+      clusterFilter->SetNumberOfYDivisions(int(1.5+(bounds[3]-bounds[2])/sp));
+      clusterFilter->SetNumberOfZDivisions(int(1.5+(bounds[5]-bounds[4])/sp));
+      clusterFilter->Update();
+
+
+      int copydirect=1;
+      if (polyData[current_surface]->GetPointData()!=NULL)
+	{
+	  if (polyData[current_surface]->GetPointData()->GetScalars()!=NULL)
+	    {
+	      vtkPolyData* temp=vtkPolyData::New();
+	      temp->ShallowCopy(clusterFilter->GetOutput());
+	      int docopy=vtkpxSurfaceUtil::MapScalarsToSurface(polyData[current_surface],temp);
+	      if (docopy)
+		{
+		  polyData[current_surface]->ShallowCopy(temp);
+		  copydirect=0;
+		}
+	      temp->Delete();
+	    }
+	}
+	
+      if (copydirect)
+	polyData[current_surface]->ShallowCopy(clusterFilter->GetOutput());
+      clusterFilter->Delete();
+      triFilter->Delete();
+      clb->Delete();
+
+    }
+  this->WatchOff();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+/*int vtkpxGUIPolyDataControl::doTransform(int apply)
+{
+  if (polyData[current_surface]->GetNumberOfPoints()<2)
+    {
+      this->EventManager->messageBox("Cannot Transform Surface, no surface in memory!","Error Message ...");
+      return 0;
+    }
+
+    if (apply==0)
+      {
+	if (transformControl==NULL)
+	  {
+	    transformControl=vtkpxGUITransformControl::New();
+	    transformControl->Initialize(this->GetWidgetName(),0);
+	    transformControl->SetCallback(this,356);
+	  }
+	transformControl->SetDimensions(this->CurrentImage);
+	//sprintf(pxtk_buffer,"wm deiconify %s",transformControl->GetWidgetName());
+	//PXTkApp::executeTclCommand(pxtk_buffer);
+	transformControl->Show();
+	return 0;
+      }
+    
+    this->WatchOn();
+    vtkTransformPolyDataFilter* transformFilter=vtkTransformPolyDataFilter::New();
+    vtkpxGUICallback* clb=this->AddMethodsToFilter(transformFilter,"Transforming Surface");
+    transformFilter->SetInput(polyData[current_surface]);
+    transformFilter->SetTransform(transformControl->GetCurrentTransform());
+    transformFilter->Update();
+    polyData[current_surface]->ShallowCopy(transformFilter->GetOutput());
+    transformFilter->Delete();
+    this->WatchOff();
+    clb->Delete();
+    return 1;
+}*/
+/* -------------------------------------------------------------------------*/
+void vtkpxguipolydatacontrolextractstats(vtkImageData* img,const char* name)
+{
+  double range[2];
+  int dim[3];
+  img->GetDimensions(dim);
+  img->GetPointData()->GetScalars()->GetRange(range);
+  /*fprintf(stderr,"Image %s dimensions %dx%dx%d range %.1f:%.1f\n",
+    name,dim[0],dim[1],dim[2],range[0],range[1]);*/
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIPolyDataControl::doExtract(int apply)
+{
+  if (this->CurrentImage==NULL)
+    {
+      this->EventManager->messageBox("Cannot Extract Iso-Contour, no image in memory!","Error Message ...");
+      return 0;
+    }
+
+  if (apply==0)
+      {
+	if (extractGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	      extractGUI=new PXTkDialog(this->EventManager,polyFrame,"Extract Controls",PXFalse);
+	      extractGUI->initDisplay();
+	      PXTkFrame* frame=(PXTkFrame*)extractGUI->getMainWindow();	      
+	      
+	      PXTkLabelFrame* valFrame=new PXTkLabelFrame(extractGUI,frame,"Iso-Contour Level");
+	      PXTkLabelFrame* smtFrame=new PXTkLabelFrame(extractGUI,frame,"Smooth Image");
+	      PXTkLabelFrame* resFrame=new PXTkLabelFrame(extractGUI,frame,"Resample Image");
+	      PXTkLabelFrame* thrFrame=new PXTkLabelFrame(extractGUI,frame,"Threshold Image");
+	      frame->addChildren("-side top -fill x -expand f",valFrame,thrFrame,smtFrame,resFrame);
+
+	      // Smooth GUI
+	      extractDoSmooth=new PXTkOptionMenu(extractGUI,smtFrame,"No Smoothing",-1);
+	      extractDoSmooth->addOption("Smooth");
+	      extractDoSmooth->setIndex(0);
+
+	      extractSmoothScale=new PXTkArrowScale(extractGUI,smtFrame,"Sigma",-1,PXTrue,PXTrue);
+	      extractSmoothScale->setRange(0.25,6.0);
+	      extractSmoothScale->setValue(1.0);
+	      extractSmoothScale->setIncrement(0.25);
+	      extractSmoothScale->setResolution(0.01);
+	      extractSmoothScale->setLengthWidth(60,8);
+	      extractSmoothScale->setDecimalPoints(2);
+	      smtFrame->addChildren("-side left -fill x -expand f",extractDoSmooth,extractSmoothScale->getMainWindow());
+
+	      extractDoResample=new PXTkCheckButton(extractGUI,resFrame,"Resample",-1);
+	      extractDoResample->setState(PXFalse);
+	      extractResampleScale=new PXTkArrowScale(extractGUI,resFrame,"Factor",-1,PXTrue,PXTrue);
+	      extractResampleScale->setRange(1.0,6.0);
+	      extractResampleScale->setValue(2.0);
+	      extractResampleScale->setIncrement(0.5);
+	      extractResampleScale->setResolution(0.5);
+	      extractResampleScale->setLengthWidth(60,8);
+	      extractResampleScale->setDecimalPoints(1);
+	      smtFrame->addChildren("-side left -fill x -expand f",extractDoResample,extractResampleScale->getMainWindow());
+	      
+	      extractDoThreshold=new PXTkCheckButton(extractGUI,thrFrame,"Threshold",-1);
+	      extractDoThreshold->setState(PXFalse);
+	      thrFrame->addChildren("-side top -fill x -expand f",extractDoThreshold);
+
+	      for (int ia=0;ia<=2;ia++)
+		{
+		  switch (ia)
+		    {
+		    case 0:
+		      thresholdScale[ia]=new PXTkArrowScale(extractGUI,valFrame,"Extract Level",-1,PXTrue,PXTrue);
+		      valFrame->addChildren("-side top -fill x -expand f",thresholdScale[ia]->getMainWindow());
+		      thresholdScale[ia]->setRange(0.0,255.0);
+		      thresholdScale[ia]->setValue(128.0);
+		      thresholdScale[ia]->setDecimalPoints(2);
+		      break;
+		    case 1:
+		      thresholdScale[ia]=new PXTkArrowScale(extractGUI,thrFrame,"Low Threshold",-1,PXTrue,PXTrue);
+		      thrFrame->addChildren("-side top -fill x -expand f",thresholdScale[ia]->getMainWindow());
+		      thresholdScale[ia]->setRange(0.0,255.0);
+		      thresholdScale[ia]->setValue(0.0);
+		      break;
+		    case 2:
+		      thresholdScale[ia]=new PXTkArrowScale(extractGUI,thrFrame,"High Threshold",-1,PXTrue,PXTrue);
+		      thrFrame->addChildren("-side top -fill x -expand f",thresholdScale[ia]->getMainWindow());
+		      thresholdScale[ia]->setRange(0.0,255.0);
+		      thresholdScale[ia]->setValue(255.0);
+		      break;
+		    }
+		  thresholdScale[ia]->setIncrement(1);
+		  thresholdScale[ia]->setResolution(0.5);
+		  thresholdScale[ia]->setLengthWidth(120,8);
+		}
+		  
+	      PXTkFrame* fr2=new PXTkFrame(extractGUI,frame);
+	      PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Apply",357);
+	      PXTkButton* b4=new PXTkButton(this->EventManager,fr2,"Undo",201);
+	      PXTkButton* b3=new PXTkButton(extractGUI,fr2,"Close",3);
+	      frame->addChildren("-side top -expand true -fill x",fr2);
+	      fr2->addChildren("-side left -expand true -fill x",b2,b4,b3);
+	    }
+
+	double range[2];
+	this->CurrentImage->GetPointData()->GetScalars()->GetRange(range);
+	//fprintf(stderr,"Image Range %f:%f\n",range[0],range[1]);
+	for (int ia=0;ia<=2;ia++)
+	  thresholdScale[ia]->setRange(range[0],range[1]);
+
+	thresholdScale[0]->setValue(0.5*(range[0]+range[1]));
+	thresholdScale[1]->setValue(range[0]);
+	thresholdScale[2]->setValue(range[1]);
+
+	double drange=range[1]-range[0];
+	int    decimalpoints=1;
+	double goodrange=50.0;
+	double inc=1.0;
+
+	if (range[1]-range[0]>50.0)
+	  {
+	    decimalpoints=0;
+	  }
+	else
+	  {
+	    while (drange<goodrange)
+	      {
+		decimalpoints+=1;
+		drange*=10.0;
+		inc*=0.2;
+	      }
+	  }
+
+	for (int ia=0;ia<=2;ia++)
+	  {
+	    thresholdScale[ia]->setDecimalPoints(decimalpoints);
+	    thresholdScale[ia]->setIncrement(inc);
+	    thresholdScale[ia]->setResolution( (range[1]-range[0])/100.0);
+	  }
+
+	extractGUI->popupDialog();
+	return 0;
+      }
+
+  this->WatchOn();
+
+  vtkImageData* lastOutput=vtkImageData::New();
+  lastOutput->ShallowCopy(this->CurrentImage);
+
+  if (extractDoSmooth->getIndex()>0)
+    {
+      float sm=extractSmoothScale->getValue();
+      int   smrad=int(sm*2.0+1.5);
+      vtkImageGaussianSmooth* smoothFilter=vtkImageGaussianSmooth::New();
+      smoothFilter->SetInput(lastOutput);
+      smoothFilter->SetStandardDeviations(sm,sm,sm);
+      smoothFilter->SetRadiusFactors(smrad,smrad,smrad);
+      vtkpxGUICallback* clb1=this->AddMethodsToFilter(smoothFilter,"Smoothing Image");
+      smoothFilter->Update();
+      clb1->Delete();
+      //      smoothFilter->DebugOn();
+      lastOutput->ShallowCopy(smoothFilter->GetOutput());
+      smoothFilter->Delete();
+      vtkpxguipolydatacontrolextractstats(lastOutput,"Smoothing");
+    }
+
+
+  if (extractDoResample->getState()==PXTrue)
+    {
+      float scalefact=1.0/Frange(extractResampleScale->getValue(),0.001,10.0);
+      vtkbisImageResample* resl=vtkbisImageResample::New();
+      resl->SetInput(lastOutput);
+      resl->SetInterpolate(1);
+      resl->SetAxisMagnificationFactor(0,scalefact);
+      resl->SetAxisMagnificationFactor(1,scalefact);
+      resl->SetAxisMagnificationFactor(2,scalefact);
+      vtkpxGUICallback* clb2=this->AddMethodsToFilter(resl,"Resampling Image");
+      resl->Update();
+      clb2->Delete();
+      lastOutput->ShallowCopy(resl->GetOutput());
+      //      resl->DebugOn();
+      resl->Delete();
+      vtkpxguipolydatacontrolextractstats(lastOutput,"Resampling");
+    }
+
+  if (extractDoThreshold->getState()==PXTrue)
+    {
+      float lowt=thresholdScale[1]->getValue();
+      float hight=thresholdScale[2]->getValue();
+      
+      if (lowt>hight)
+	{
+	  float t=hight;
+	  hight=lowt;
+	  lowt=t;
+	  thresholdScale[1]->setValue(lowt);
+	  thresholdScale[2]->setValue(hight);
+	}
+      vtkImageThreshold* thrFilter=vtkImageThreshold::New();
+      thrFilter->SetInput(lastOutput);
+      vtkpxGUICallback* clb0=NULL;
+      if (extractDoSmooth->getIndex()==2)
+	{
+	  thrFilter->ThresholdByUpper(lowt);
+	  clb0=this->AddMethodsToFilter(thrFilter,"Thresholding Grad Image");
+	}
+      else
+	{
+	  thrFilter->ThresholdBetween(lowt,hight);
+	  clb0=this->AddMethodsToFilter(thrFilter,"Thresholding Inten Image");
+	}
+      thrFilter->SetOutValue(0.0);
+      thrFilter->ReplaceInOff();
+      thrFilter->Update();
+      clb0->Delete();
+      
+      lastOutput->ShallowCopy(thrFilter->GetOutput());
+      vtkpxguipolydatacontrolextractstats(lastOutput,"Thresholding");
+      thrFilter->Delete();
+    }
+
+  vtkpxguipolydatacontrolextractstats(lastOutput,"Final Output");
+  vtkContourFilter* skinExtractor=vtkContourFilter::New();
+  skinExtractor->SetInput(lastOutput);
+  skinExtractor->SetUseScalarTree(0);
+
+  int dim[3];   lastOutput->GetDimensions(dim);
+  double r[2]; lastOutput->GetPointData()->GetScalars()->GetRange(r);
+  sprintf(pxtk_buffer,"Extracting %dx%dx%d %.0f:%.0f",dim[0],dim[1],dim[2],r[0],r[1]);
+  vtkpxGUICallback* clb=this->AddMethodsToFilter(skinExtractor,pxtk_buffer);
+  
+  skinExtractor->SetNumberOfContours(1);
+  skinExtractor->SetValue(0,thresholdScale[0]->getValue());
+  skinExtractor->ComputeScalarsOff();
+  skinExtractor->ComputeGradientsOff();
+  skinExtractor->ComputeNormalsOff();
+  skinExtractor->Update();
+
+  polyData[current_surface]->ShallowCopy(skinExtractor->GetOutput());
+  skinExtractor->Delete();
+  lastOutput->Delete();
+  clb->Delete();
+  this->WatchOff();
+  UpdateDisplay();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIPolyDataControl::SetTransform(vtkAbstractTransform* trans)
+{
+  if (trans==NULL)
+    return;
+
+  if (this->internalTransform!=NULL && owns_transform==PXTrue)
+    internalTransform->Delete();
+
+  this->internalTransform=trans;
+  owns_transform=PXFalse;
+
+  if (has_surface)
+    {
+      for (int i=0;i<num_surfaces;i++)
+	{
+	  polyDataFilter[i]->SetTransform(this->internalTransform);
+	  polyDataFilter[i]->Update();
+	}
+    }
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIPolyDataControl::doMapFunctional(int apply)
+{
+  if (this->CurrentImage==NULL)
+    {
+      this->EventManager->messageBox("Cannot Map Functional, no image in memory!","Error Message ...");
+      return 0;
+    }
+
+  if (apply==0)
+      {
+	if (mapFunctionalGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	      mapFunctionalGUI=new PXTkDialog(this->EventManager,polyFrame,"Extract Controls",PXFalse);
+	      mapFunctionalGUI->initDisplay();
+	      PXTkFrame* frame=(PXTkFrame*)mapFunctionalGUI->getMainWindow();	      
+	      
+	      mapFunctionalType=new PXTkOptionMenu(this->EventManager,frame,"Map Positive Only",500);
+	      mapFunctionalType->addOption("Map Negative Only");
+	      mapFunctionalType->addOption("Map Both");
+	      frame->addChildren("-side top -fill x -expand f",mapFunctionalType);
+
+	      mapFunctionalMode=new PXTkOptionMenu(this->EventManager,frame,"Maximum Value",-1);
+	      mapFunctionalMode->addOption("Average Value");
+	      frame->addChildren("-side top -fill x -expand f",mapFunctionalMode);
+	      
+	      for (int ia=0;ia<=1;ia++)
+		{
+		  if (ia==0)
+		    sprintf(pxtk_buffer2,"Low Threshold");
+		  else
+		    sprintf(pxtk_buffer2,"High Threshold");
+		  
+		  mapThreshold[ia]=new PXTkArrowScale(mapFunctionalGUI,frame,pxtk_buffer2,-1,PXTrue,PXTrue);
+		  mapThreshold[ia]->setRange(0.0,255.0);
+		  mapThreshold[ia]->setValue(float(64*(ia+1)));
+		  mapThreshold[ia]->setIncrement(1);
+		  mapThreshold[ia]->setResolution(1);
+		  mapThreshold[ia]->setLengthWidth(120,8);
+		  frame->addChildren("-side top -fill x -expand f",mapThreshold[ia]->getMainWindow());
+		}
+
+	      for (int ib=0;ib<=1;ib++)
+		{
+		  if (ib==1)
+		    sprintf(pxtk_buffer2,"Max Distance");
+		  else
+		    sprintf(pxtk_buffer2,"Min Distance");
+		  
+		  mapDistance[ib]=new PXTkArrowScale(mapFunctionalGUI,frame,pxtk_buffer2,-1,PXTrue,PXTrue);
+		  mapDistance[ib]->setRange(-50.0,50.0);
+		  if (ib==1)
+		    mapDistance[ib]->setValue(10.0);
+		  else
+		    mapDistance[ib]->setValue(0.0);
+		  mapDistance[ib]->setIncrement(1.0);
+		  mapDistance[ib]->setResolution(0.5);
+		  mapDistance[ib]->setLengthWidth(120,8);
+		  frame->addChildren("-side top -fill x -expand f",mapDistance[ib]->getMainWindow());
+		}
+
+	      PXTkFrame* fr2=new PXTkFrame(mapFunctionalGUI,frame);
+	      PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Apply",358);
+	      PXTkButton* b4=new PXTkButton(this->EventManager,fr2,"Undo",201);
+	      PXTkButton* b3=new PXTkButton(mapFunctionalGUI,fr2,"Close",3);
+	      frame->addChildren("-side top -expand true -fill x",fr2);
+	      fr2->addChildren("-side left -expand true -fill x",b2,b4,b3);
+	    }
+
+	double range[2];
+	this->CurrentImage->GetPointData()->GetScalars()->GetRange(range);
+	if (range[0]<0.0)
+	    {
+	      if (range[0]>range[1])
+		range[1]=range[0];
+	      range[0]=0.0;
+	    }
+	  
+	  if (range[1]<0.0)
+	    range[1]=fabs(range[1]);
+
+	  for (int ia=0;ia<=1;ia++)
+	    mapThreshold[ia]->setRange(range[0],range[1]);
+	  
+	  // For Binary Images allow 0.5 increments
+	  if ((range[1]-range[0])<10.0)
+	    {
+	      for (int ia=0;ia<=1;ia++)
+		{
+		  mapThreshold[ia]->setResolution(0.25);
+		  mapThreshold[ia]->setIncrement(0.5);
+		  mapThreshold[ia]->getScale()->setDigits(3);
+		}
+	  }
+	else
+	  {
+	    for (int ia=0;ia<=1;ia++)
+	      {
+		mapThreshold[ia]->setDecimalPoints(0);
+		mapThreshold[ia]->setIncrement(1);
+		mapThreshold[ia]->setResolution(1);
+	      }
+	  }
+
+	mapFunctionalGUI->popupDialog();
+	return 0;
+      }
+
+  //  fprintf(stderr,"Extracting 1\n");
+
+  this->WatchOn();
+  vtkpxMapActivationToPolyData* functionMapper=vtkpxMapActivationToPolyData::New();
+  vtkpxGUICallback* clb=this->AddMethodsToFilter(functionMapper,"Mapping Function");
+  functionMapper->DebugOn();
+  functionMapper->SetInput(polyData[current_surface]);
+  functionMapper->SetFunctionalData(this->CurrentImage);
+  functionMapper->SetLowThreshold(mapThreshold[0]->getValue());
+  functionMapper->SetHighThreshold(mapThreshold[1]->getValue());
+
+  if (mapFunctionalType->getIndex()==0)
+    {
+      functionMapper->SetThresholdPositive(1);
+      functionMapper->SetThresholdNegative(0);
+    }
+  else if (mapFunctionalType->getIndex()==1)
+    {
+      functionMapper->SetThresholdPositive(0);
+      functionMapper->SetThresholdNegative(1);
+    }
+  else
+    {
+      functionMapper->SetThresholdPositive(1);
+      functionMapper->SetThresholdNegative(1);
+    }
+
+  functionMapper->SetMinDistance(mapDistance[0]->getValue());
+  functionMapper->SetMaxDistance(mapDistance[1]->getValue());
+  functionMapper->SetAverageMode(mapFunctionalMode->getIndex());
+  functionMapper->Update();
+
+  polyData[current_surface]->ShallowCopy(functionMapper->GetOutput());
+  functionMapper->Delete();
+  clb->Delete();
+  this->WatchOff();
+  UpdateDisplay();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+
+int vtkpxGUIPolyDataControl::doExtractObjectMap(int apply)
+{
+  if (this->CurrentImage==NULL)
+    {
+      this->EventManager->messageBox("Cannot Extract Object-Map, no image in memory!","Error Message ...");
+      return 0;
+    }
+
+  if (apply==0)
+      {
+	if (extractObjectMapGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	      extractObjectMapGUI=new PXTkDialog(this->EventManager,polyFrame,"ObjectMap",PXFalse);
+	      extractObjectMapGUI->initDisplay();
+	      PXTkFrame* frame=(PXTkFrame*)extractObjectMapGUI->getMainWindow();	      
+	      
+	      PXTkLabelFrame* thrFrame=new PXTkLabelFrame(extractObjectMapGUI,frame,"Object Map Range");
+	      frame->addChildren("-side top -fill x -expand f",thrFrame);
+
+	      for (int ia=0;ia<=1;ia++)
+		{
+		  switch (ia)
+		    {
+		    case 0:
+		      objectMapRange[ia]=new PXTkArrowScale(extractObjectMapGUI,thrFrame,"Low Threshold",-1,PXTrue,PXTrue);
+		      thrFrame->addChildren("-side top -fill x -expand f",objectMapRange[ia]->getMainWindow());
+		      objectMapRange[ia]->setRange(0.0,255.0);
+		      objectMapRange[ia]->setValue(0.0);
+		      break;
+		    case 1:
+		      objectMapRange[ia]=new PXTkArrowScale(extractObjectMapGUI,thrFrame,"High Threshold",-1,PXTrue,PXTrue);
+		      thrFrame->addChildren("-side top -fill x -expand f",objectMapRange[ia]->getMainWindow());
+		      objectMapRange[ia]->setRange(0.0,255.0);
+		      objectMapRange[ia]->setValue(255.0);
+		      break;
+		    }
+		  objectMapRange[ia]->setIncrement(1);
+		  objectMapRange[ia]->setResolution(1);
+		  objectMapRange[ia]->setLengthWidth(120,8);
+		}
+		
+	      PXTkFrame* f1=new PXTkFrame(extractObjectMapGUI,frame);
+	      PXTkFrame* f2=new PXTkFrame(extractObjectMapGUI,frame);
+	      PXTkFrame* f3=new PXTkFrame(extractObjectMapGUI,frame);
+
+	      frame->addChildren("-side top -fill x -expand f",f1,f3,f2);
+
+	      PXTkLabel* l1=new PXTkLabel(extractObjectMapGUI,f1,"Smooth XY:");
+	      objectMapValues[0]=new PXTkOptionMenu(extractObjectMapGUI,f1,"0.0",-1);
+	      objectMapValues[0]->addOption("1.0");
+	      objectMapValues[0]->addOption("2.0");
+	      objectMapValues[0]->addOption("3.0");
+	      objectMapValues[0]->addOption("4.0");
+
+	      PXTkLabel* l3=new PXTkLabel(extractObjectMapGUI,f3,"Smooth Z:");
+	      objectMapValues[2]=new PXTkOptionMenu(extractObjectMapGUI,f3,"0.0",-1);
+	      objectMapValues[2]->addOption("1.0");
+	      objectMapValues[2]->addOption("2.0");
+	      objectMapValues[2]->addOption("3.0");
+	      objectMapValues[2]->addOption("4.0");
+
+
+	      PXTkLabel* l2=new PXTkLabel(extractObjectMapGUI,f2,"Resample:");
+	      objectMapValues[1]=new PXTkOptionMenu(extractObjectMapGUI,f2,"1.0",-1);
+	      objectMapValues[1]->addOption("2.0");
+	      objectMapValues[1]->addOption("3.0");
+	      objectMapValues[1]->addOption("4.0");
+	      f1->addChildren("-side left -expand f -fill x",l1,objectMapValues[0]);
+	      f2->addChildren("-side left -expand f -fill x",l2,objectMapValues[1]);
+	      f3->addChildren("-side left -expand f -fill x",l3,objectMapValues[2]);
+	        
+	      PXTkFrame* fr2=new PXTkFrame(extractObjectMapGUI,frame);
+	      PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Apply",359);
+	      PXTkButton* b4=new PXTkButton(this->EventManager,fr2,"Undo",201);
+	      PXTkButton* b3=new PXTkButton(extractObjectMapGUI,fr2,"Close",3);
+	      frame->addChildren("-side top -expand true -fill x",fr2);
+	      fr2->addChildren("-side left -expand true -fill x",b2,b4,b3);
+	    }
+	
+	double range[2];
+	this->CurrentImage->GetPointData()->GetScalars()->GetRange(range);
+	for (int ia=0;ia<=1;ia++)
+	  objectMapRange[ia]->setRange(1,range[1]);
+
+	objectMapRange[0]->setValue(range[0]+1);
+	objectMapRange[1]->setValue(range[1]);
+
+	extractObjectMapGUI->popupDialog();
+	return 0;
+      }
+
+  this->WatchOn();
+
+  int low=(int)objectMapRange[0]->getValue();
+  int high=(int)objectMapRange[1]->getValue();
+
+  vtkPolyData* temp=vtkPolyData::New();
+  if (vtkpxSurfaceUtil::ObjectMapToPolyData(this->CurrentImage,temp,low,high,
+					    objectMapValues[0]->getIndex(),
+					    objectMapValues[2]->getIndex(),
+					    1.0+objectMapValues[1]->getIndex())>0)
+    polyData[current_surface]->ShallowCopy(temp);
+  temp->Delete();
+
+
+  this->WatchOff();
+  UpdateDisplay();
+  return 1;
+}
+
+/* -------------------------------------------------------------------------*/
+
+int vtkpxGUIPolyDataControl::doAppend(int apply)
+{
+  if (apply==0)
+      {
+	if (appendGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	      appendGUI=new PXTkDialog(this->EventManager,polyFrame,"Append Surfaces",PXFalse);
+	      appendGUI->initDisplay();
+	      PXTkFrame* frame=(PXTkFrame*)appendGUI->getMainWindow();	      
+	      
+	      PXTkLabelFrame* thrFrame=new PXTkLabelFrame(appendGUI,frame,"Input Surfaces");
+	      frame->addChildren("-side top -fill x -expand f",thrFrame);
+
+
+	      PXTkLabelFrame* reFrame=new PXTkLabelFrame(appendGUI,frame,"Output Surface");
+
+	      appendResult=new PXTkOptionMenu(appendGUI,reFrame,"Surface 1",-1);
+	      reFrame->addChildren("-side top -fill x -expand f",appendResult);
+
+	      for (int ia=0;ia<num_surfaces;ia++)
+		{
+		  sprintf(pxtk_buffer,"Surface %d",ia+1);
+		  appendButton[ia]=new PXTkCheckButton(appendGUI,thrFrame,pxtk_buffer,-1);
+		  appendButton[ia]->setState(PXFalse);
+		  thrFrame->addChildren("-side top -fill x -expand f",appendButton[ia]);
+		  if (ia>0)
+		    appendResult->addOption(pxtk_buffer);
+		}
+	      
+	      appendObjectMap=new PXTkCheckButton(appendGUI,frame,"Preserve Labels",-1);
+	      appendObjectMap->setState(PXTrue);
+
+	      PXTkFrame* frame2=new PXTkFrame(appendGUI,frame);
+	      frame->addChildren("-side top -fill x -expand f",appendObjectMap,reFrame,frame2);
+
+
+	      PXTkButton* b1=new PXTkButton(this->EventManager,frame2,"Append",360);
+	      PXTkButton* b2=new PXTkButton(this->EventManager,frame2,"Undo",201);
+	      PXTkButton* b3=new PXTkButton(this->EventManager,frame2,"Reset",361);
+	      PXTkButton* b4=new PXTkButton(appendGUI,frame2,"Close",3);
+	      frame2->addChildren("-side left -expand true -fill x",b1,b2,b3,b4);
+	    }
+
+	appendResult->setIndex(current_surface);
+	appendGUI->popupDialog();
+	return 0;
+      }
+
+  if (apply==2 && appendGUI!=NULL)
+    {
+      for (int ia=0;ia<num_surfaces;ia++)
+	appendButton[ia]->setState(PXFalse);
+      appendResult->setIndex(current_surface);
+      appendObjectMap->setState(PXTrue);
+      return 0;
+    }
+
+
+  // Check First that at least one surface has been selected 
+  int numsur=0;
+  for (int i=0;i<num_surfaces;i++)
+    if (appendButton[i]->getState()==PXTrue)
+      numsur++;
+  if (numsur==0)
+    return 0;
+
+  vtkAppendPolyData* append=vtkAppendPolyData::New();
+
+  int offset=0;
+  int result=appendResult->getIndex();
+  for (int j=0;j<num_surfaces;j++)
+    {
+      if (appendButton[j]->getState()==PXTrue)
+	{
+	  vtkPolyData* temp=vtkPolyData::New();
+	  temp->ShallowCopy(polyData[j]);
+	  offset+=vtkpxSurfaceUtil::AddObjectLabelsToSurface(temp,offset);
+	  //  fprintf(stderr,"Surface = %d , offset=%d\n",j,offset);
+	  append->AddInput(temp);
+	  temp->Delete();
+	}
+    }
+  append->Update();
+  polyData[result]->ShallowCopy(append->GetOutput());
+  append->Delete();
+  vtkpxSurfaceUtil::AddObjectMapLookupTableToSurface(polyData[result]);
+
+  this->WatchOff();
+  UpdateDisplay();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIPolyDataControl::doClip(int apply)
+{
+  if (this->CurrentImage==NULL)
+    {
+      this->EventManager->messageBox("Cannot Clip Surface, no image in memory!","Error Message ...");
+      return 0;
+    }
+
+  this->WatchOn();
+
+  vtkImageThreshold* thrFilter=vtkImageThreshold::New();
+  thrFilter->SetInput(this->CurrentImage);
+  thrFilter->ThresholdByUpper(1.0);
+  thrFilter->SetOutValue(0.0);
+  thrFilter->SetInValue(1.0);
+  thrFilter->ReplaceInOn();
+  thrFilter->ReplaceOutOn();
+  thrFilter->Update();
+
+  vtkImplicitVolume* vol=vtkImplicitVolume::New();
+  vol->SetVolume(thrFilter->GetOutput());
+  vol->SetOutValue(0.0);
+
+  thrFilter->Delete();
+
+  vtkClipPolyData* clipFilter=vtkClipPolyData::New();
+  vtkpxGUICallback* clb=this->AddMethodsToFilter(clipFilter,"Clipping Surface");
+  clipFilter->SetInput(polyData[current_surface]);
+  clipFilter->SetClipFunction(vol);
+  clipFilter->GenerateClipScalarsOff();
+  clipFilter->SetValue(0.5);
+  clipFilter->Update();
+
+  polyData[current_surface]->ShallowCopy(clipFilter->GetOutput());
+  clipFilter->Delete();
+  vol->Delete();
+  clb->Delete();
+  this->WatchOff();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIPolyDataControl::LoadCurrentSurface(const char* fname)
+{
+  if (strlen(fname)<2)
+    {
+      char* line=this->EventManager->getOpenFilenameComplex("Load Surface",
+							    "{\"Surface/Tstack Files\" {\".vtk\" \".tstack\" } } { \"Polydata File\" {\"*.vtk\"}} {\"Tstack File\" {\"*.tstack\"}}");
+      if (line==NULL)
+	return 0;
+      if (strlen(line)<1)
+	return 0;
+      strcpy(pxtk_buffer2,line);
+    }
+  else
+    {
+      strcpy(pxtk_buffer2,fname);
+    }
+
+  char* ext=PXTkApp::getFilenameExtension(pxtk_buffer2);
+
+  if (strcmp(ext,".vtk")==0 || strcmp(ext,".VTK")==0)
+    {
+      vtkPolyDataReader* Reader=vtkPolyDataReader::New();
+      vtkpxGUICallback* clb=this->AddMethodsToFilter(Reader,"Loading Surface");
+      Reader->SetFileName(pxtk_buffer2);
+      this->WatchOn();
+      Reader->Update();
+      previousPolyData->ShallowCopy(polyData[current_surface]);
+      polyData[current_surface]->ShallowCopy(Reader->GetOutput());
+      Reader->Delete();
+      clb->Delete();
+    }
+  else
+    {
+      vtkpxTstackReader* Reader=vtkpxTstackReader::New();
+      vtkpxGUICallback* clb=this->AddMethodsToFilter(Reader,"Loading Surface");
+      Reader->SetFileName(pxtk_buffer2);
+      this->WatchOn();
+      Reader->Update();
+      previousPolyData->ShallowCopy(polyData[current_surface]);
+      polyData[current_surface]->ShallowCopy(Reader->GetOutput());
+      Reader->Delete();
+      clb->Delete();
+    }
+
+
+  //  sprintf(pxtk_buffer2,"%s.%d",PXTkApp::getFilenameTail(pxtk_buffer2),current_surface+1);
+  sprintf(pxtk_buffer2,"%s.%d",anaeatpath(pxtk_buffer2),current_surface+1);
+  currentSurface->changeLabel(current_surface,pxtk_buffer2);
+  
+  this->WatchOff();
+  UpdateStatus();
+  UpdateDisplay();
+  return 1;
+}
+
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIPolyDataControl::doThresholdPoints(int apply)
+{
+  if (this->CurrentImage==NULL)
+    {
+      this->EventManager->messageBox("Cannot Threshold Points, no image in memory!","Error Message ...");
+      return 0;
+    }
+
+  if (apply==0)
+      {
+	if (thresholdPointsGUI==NULL)
+	    {
+	      PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	      thresholdPointsGUI=new PXTkDialog(this->EventManager,polyFrame,"Threshold Points Controls",PXFalse);
+	      thresholdPointsGUI->initDisplay();
+	      PXTkFrame* frame=(PXTkFrame*)thresholdPointsGUI->getMainWindow();	      
+	      
+	      PXTkLabelFrame* valFrame=new PXTkLabelFrame(thresholdPointsGUI,frame,"Set Levels");
+	      PXTkLabelFrame* reFrame=new PXTkLabelFrame(thresholdPointsGUI,frame,"Input Data-set");
+	      frame->addChildren("-side top -fill x -expand f",reFrame,valFrame);
+
+	      for (int ia=0;ia<=1;ia++)
+		{
+		  if (ia==0)
+		    {
+		      pointsThresholdScale[ia]=new PXTkArrowScale(thresholdPointsGUI,valFrame,"Low Threshold",-1,PXTrue,PXTrue);
+		      valFrame->addChildren("-side top -fill x -expand f",pointsThresholdScale[ia]->getMainWindow());
+		      pointsThresholdScale[ia]->setRange(0.0,255.0);
+		      pointsThresholdScale[ia]->setValue(0.0);
+		    } 
+		  else
+		    {
+		      pointsThresholdScale[ia]=new PXTkArrowScale(thresholdPointsGUI,valFrame,"High Threshold",363,PXTrue,PXTrue);
+		      valFrame->addChildren("-side top -fill x -expand f",pointsThresholdScale[ia]->getMainWindow());
+		      pointsThresholdScale[ia]->setRange(0.0,255.0);
+		      pointsThresholdScale[ia]->setValue(255.0);
+		    }
+		  pointsThresholdScale[ia]->setIncrement(1);
+		  pointsThresholdScale[ia]->setResolution(0.5);
+		  pointsThresholdScale[ia]->setLengthWidth(120,8);
+		}
+	      
+	      
+	      pointsThresholdInput=new PXTkOptionMenu(this->EventManager,reFrame,"Surface 1",362);
+	      reFrame->addChildren("-side top -fill x -expand f",pointsThresholdInput);
+	      for (int i=1;i<num_surfaces;i++)
+		{
+		  sprintf(pxtk_buffer,"Surface %d",i+1);
+		  pointsThresholdInput->addOption(pxtk_buffer);
+		}
+	      pointsThresholdInput->addOption("Current Image");
+	      
+	      PXTkFrame* fr2=new PXTkFrame(thresholdPointsGUI,frame);
+	      PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Apply",363);
+	      PXTkButton* b4=new PXTkButton(this->EventManager,fr2,"Undo",201);
+	      PXTkButton* b3=new PXTkButton(thresholdPointsGUI,fr2,"Close",3);
+	      frame->addChildren("-side top -expand true -fill x",fr2);
+	      fr2->addChildren("-side left -expand true -fill x",b2,b4,b3);
+	    }
+      }
+
+  //fprintf(stderr,"apply=%d\n",apply);
+
+  if (apply==0 || apply ==1)
+    {
+      vtkDataSet* data=this->CurrentImage;
+      int index=pointsThresholdInput->getIndex();
+      if (index<num_surfaces)
+	data=(polyData[index]);
+
+      double range[2];
+      if (data->GetPointData()->GetScalars()!=NULL)
+	{
+	  data->GetPointData()->GetScalars()->GetRange(range);
+	  //fprintf(stderr,"pdata");
+	}
+      else if (data->GetCellData()->GetScalars()!=NULL)
+	{
+	  data->GetCellData()->GetScalars()->GetRange(range);
+	  //	  fprintf(stderr,"cdata");
+	}
+      else
+	{
+	  data=this->CurrentImage;
+	  range[0]=0.0;
+	  range[1]=1.0;
+	}
+      //fprintf(stderr,"Image Range %f:%f\n",range[0],range[1]);
+      for (int ia=0;ia<=1;ia++)
+	pointsThresholdScale[ia]->setRange(range[0],range[1]);
+      
+	pointsThresholdScale[0]->setValue(range[0]);
+	pointsThresholdScale[1]->setValue(range[1]);
+	
+	// For Binary Images allow 0.5 increments
+	if ((range[1]-range[0])<20.0)
+	  {
+	    for (int ia=0;ia<=1;ia++)
+	      {
+		pointsThresholdScale[ia]->setResolution(0.1);
+		pointsThresholdScale[ia]->setIncrement(0.1);
+		pointsThresholdScale[ia]->getScale()->setDigits(3);
+	      }
+	  }
+	else
+	  {
+	    for (int ia=0;ia<=1;ia++)
+	      {
+		pointsThresholdScale[ia]->setDecimalPoints(1);
+		pointsThresholdScale[ia]->setIncrement(1);
+		pointsThresholdScale[ia]->setResolution(0.5);
+	      }
+	  }
+
+	if (apply==0)
+	  thresholdPointsGUI->popupDialog();
+	return 0;
+    }
+
+  this->WatchOn();
+
+
+  float lowt=pointsThresholdScale[0]->getValue();
+  float hight=pointsThresholdScale[1]->getValue();
+  
+  if (lowt>hight)
+    {
+      float t=hight;
+      hight=lowt;
+      lowt=t;
+      pointsThresholdScale[0]->setValue(lowt);
+      pointsThresholdScale[1]->setValue(hight);
+    }
+
+
+  vtkThresholdPoints* thrFilter=vtkThresholdPoints::New();  
+
+  int index=pointsThresholdInput->getIndex();
+  if (index>=num_surfaces)
+    thrFilter->SetInput(this->CurrentImage);
+  else
+    thrFilter->SetInput(polyData[index]);
+
+  //  vtkpxGUICallback* clb0=NULL;
+  thrFilter->ThresholdBetween(lowt,hight);
+  thrFilter->Update();
+  //  clb0->Delete();
+  
+  polyData[current_surface]->ShallowCopy(thrFilter->GetOutput());
+  thrFilter->Delete();
+  this->WatchOff();
+  UpdateDisplay();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIPolyDataControl::doChangeDisplaySize(int apply)
+{
+  if (apply==0)
+    {
+      if (displaySizeGUI==NULL)
+	{
+	  PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	  displaySizeGUI=new PXTkDialog(this->EventManager,polyFrame,"Display Sizes",PXFalse);
+	  displaySizeGUI->initDisplay();
+	  PXTkFrame* frame=(PXTkFrame*)displaySizeGUI->getMainWindow();	      
+	  
+	  PXTkLabelFrame* thrFrame=new PXTkLabelFrame(displaySizeGUI,frame,"Widths");
+	  frame->addChildren("-side top -fill x -expand f",thrFrame);
+	  
+	  for (int ia=0;ia<=1;ia++)
+	    {
+	      switch (ia)
+		{
+		case 0:
+		  displaySize[ia]=new PXTkArrowScale(displaySizeGUI,thrFrame,"Line Width",-1,PXTrue,PXTrue);
+		  thrFrame->addChildren("-side top -fill x -expand f",displaySize[ia]->getMainWindow());
+		  displaySize[ia]->setRange(0.01,10.0);
+		  displaySize[ia]->setValue(1.0);
+		  break;
+		case 1:
+		  displaySize[ia]=new PXTkArrowScale(displaySizeGUI,thrFrame,"Point Size",-1,PXTrue,PXTrue);
+		  thrFrame->addChildren("-side top -fill x -expand f",displaySize[ia]->getMainWindow());
+		  displaySize[ia]->setRange(0.01,10.0);
+		  displaySize[ia]->setValue(1.0);
+		  break;
+		}
+	      displaySize[ia]->setIncrement(1);
+	      displaySize[ia]->setResolution(0.2);
+	      displaySize[ia]->setLengthWidth(120,8);
+	    }
+	  
+	  PXTkFrame* fr2=new PXTkFrame(displaySizeGUI,frame);
+	  PXTkButton* b1=new PXTkButton(this->EventManager,fr2,"Apply",374);
+	  PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Apply All",375);
+	  PXTkButton* b3=new PXTkButton(displaySizeGUI,fr2,"Close",3);
+	  frame->addChildren("-side top -expand true -fill x",fr2);
+	  fr2->addChildren("-side left -expand true -fill x",b1,b2,b3);
+	}
+      
+      vtkProperty* prop=surfaceActor[0][current_surface]->GetProperty();
+      float lw=prop->GetLineWidth();
+      float pz=prop->GetPointSize();
+      
+      displaySize[0]->setValue(lw);
+      displaySize[1]->setValue(pz);
+      
+      displaySizeGUI->popupDialog();
+      return 0;
+    }
+
+  this->WatchOn();
+
+  float lw=displaySize[0]->getValue();
+  float  pz=displaySize[1]->getValue();
+  
+  for (int i=0;i<num_surfaces;i++)
+    {
+      if (i==current_surface || apply==2)
+	{
+	  for (int j=0;j<num_renderers;j++)
+	    {
+	      vtkProperty* prop=surfaceActor[j][i]->GetProperty();
+	      prop->SetLineWidth(lw);
+	      prop->SetPointSize(pz);
+	      surfaceActor[j][i]->Modified();
+	    }
+	}
+    }
+  this->WatchOff();
+  UpdateDisplay();
+  return 1;
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIPolyDataControl::doCurvature(int apply)
+{
+
+  if (polyData[current_surface]->GetNumberOfPoints()<2)
+    {
+      this->EventManager->messageBox("Cannot Compute Surface Curvature, no surface in memory!","Error Message ...");
+      return 0;
+    }
+
+  if (apply==0)
+      {
+	if (curvatureGUI==NULL)
+	  {
+	    PXTkFrame* polyFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+	    curvatureGUI=new PXTkDialog(this->EventManager,polyFrame,"Curvature Controls",PXFalse);
+	    curvatureGUI->initDisplay();
+	    PXTkFrame* frame=(PXTkFrame*)curvatureGUI->getMainWindow();
+
+	    curvatureType=new PXTkOptionMenu(curvatureGUI,frame,"Normal",-1);
+	    curvatureType->addOption("Open Surface");
+	    curvatureType->setIndex(0);
+
+	    curvatureMode=new PXTkOptionMenu(curvatureGUI,frame,"ShapeIndex",-1);
+	    curvatureMode->addOption("Mean");
+	    curvatureMode->addOption("Gaussian");
+	    curvatureMode->addOption("K1");
+	    curvatureMode->addOption("K2");
+	    curvatureMode->setIndex(0);
+
+	    curvatureScale=new PXTkScale(curvatureGUI,frame,"Scale",-1,PXTrue);
+	    curvatureScale->setRange(2.0,8.0);
+	    curvatureScale->setResolution(1.0);
+	    curvatureScale->setValue(4.0);
+
+	    curvatureRange=new PXTkScale(curvatureGUI,frame,"Range",-1,PXTrue);
+	    curvatureRange->setRange(0.1,5.0);
+	    curvatureRange->setResolution(0.1);
+	    curvatureRange->setValue(1.0);
+	      
+	    PXTkFrame* fr2=new PXTkFrame(curvatureGUI,frame);
+	    PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Apply",321);
+	    PXTkButton* b4=new PXTkButton(this->EventManager,fr2,"Undo",201);
+	    PXTkButton* b3=new PXTkButton(curvatureGUI,fr2,"Close",3);
+	    frame->addChildren("-side top -expand true -fill x",curvatureType,curvatureMode);
+	    frame->addChildren("-side top -expand true -fill x",curvatureScale,curvatureRange,fr2);
+	    fr2->addChildren("-side left -expand true -fill x",b2,b4,b3);
+	  }
+	
+	curvatureGUI->popupDialog();
+	return 0;
+      }
+
+  this->WatchOn();
+
+  int opensurface=0;
+  if (curvatureType->getIndex()==1)
+    opensurface=1;
+
+  int cmode=curvatureMode->getIndex();
+
+  float range=curvatureRange->getValue();
+  int scale=(int)curvatureScale->getValue();
+
+  vtkpxSurfaceUtil::CalculateCurvatures(polyData[current_surface],scale,opensurface,cmode,range);
+
+  this->WatchOff();
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIPolyDataControl.h b/bioimagesuite30_src/GUI/vtkpxGUIPolyDataControl.h
new file mode 100644
index 0000000..a8da175
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIPolyDataControl.h
@@ -0,0 +1,262 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSurfaceUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIPolyDataControl - Base Image Viewer
+// .SECTION Description
+
+#ifndef __vtkpxGUIPolyDataControl_h
+#define __vtkpxGUIPolyDataControl_h
+
+
+#include "pxtkapp.h"
+#include "pxtkcomplexwidgets.h"
+#include "pxtkdialog.h"
+#include "pxtkgadgets.h"
+#include "pxvtkgadgets.h"
+#include "vtkPolyData.h"
+#include "vtkpxGUIComponent.h"
+
+class  vtkImageData;
+//class  vtkpxGUITransformControl;
+class vtkActor;
+class vtkPolyDataMapper;
+class vtkProperty;
+class vtkRenderer;
+class vtkAbstractTransform;
+class vtkIdentityTransform;
+class vtkTransformPolyDataFilter;
+
+class vtkpxGUIPolyDataControl : public vtkpxGUIComponent 
+{
+public:
+
+  static vtkpxGUIPolyDataControl *New();
+  vtkTypeMacro(vtkpxGUIPolyDataControl,vtkpxGUIComponent);
+  
+  // Initialize Display  
+  virtual char*  Initialize(const char* name,int inside);
+
+  virtual void SetRenderer(vtkRenderer *v) { SetRenderer(v,0,0);}
+  virtual void SetRenderer(vtkRenderer *v,int num,int clip=0);
+
+  virtual void UpdateDisplay();
+  virtual int  HandleEvent(int);
+
+  virtual int  SetCurrentSurface(int s);
+  virtual int  UpdateStatus();
+
+  virtual int  GetCurrentSurface();
+  virtual vtkPolyData* GetSurface(int index=-1);
+
+  virtual void SetSurface(int index,vtkPolyData* data);
+  virtual void SetSurface(int index,vtkPolyData* data,const char* name);
+
+
+  // Clipboard Surface Stuff -- all static
+  // -------------------------------------
+  static void SetClipboardSurface(vtkPolyData* data,const char* name=NULL);
+  static vtkPolyData* GetClipboardSurface() { return clipboardPolyData;}
+  static char* GetClipboardSurfaceName() { return clipboardName;}
+
+  virtual void SetImage(vtkImageData* new_image);
+  virtual void SetLastPoint(double pt[3]);
+  virtual void SetLastPoint(double x,double y,double z) 
+  { double p[3]; p[0]=x; p[1]=y; p[2]=z; SetLastPoint(p);}
+
+  virtual void SetTransform(vtkAbstractTransform* trans);
+  virtual vtkAbstractTransform* GetTransform() { return this->internalTransform;}
+
+  virtual void SetSimpleMode();
+
+  virtual int GetNumberOfSurfaces() { return num_surfaces;}
+  
+  // GetImage Macro
+  vtkGetObjectMacro(CurrentImage,vtkImageData);
+
+  virtual int LoadCurrentSurface(const char* fname);
+
+protected:
+
+  vtkpxGUIPolyDataControl();
+  virtual ~vtkpxGUIPolyDataControl();
+
+  vtkImageData                 *CurrentImage;
+  
+  PXBool                        simple_mode;
+  vtkActor                      *surfaceActor[4][10];
+  vtkPolyData                   *polyData[10];
+  int                           displayPolyData[10];
+  vtkTransformPolyDataFilter    *polyDataFilter[10];
+  vtkPolyData                   *previousPolyData;
+  vtkPolyData                   *tempPolyData;
+  static vtkPolyData            *clipboardPolyData;
+  static char                    clipboardName[200];
+  double                         lastPoint[3];
+  
+  vtkAbstractTransform*         internalTransform;
+  vtkRenderer                   *renderer[4];
+  PXBool                        has_surface;
+  PXBool                        wireFrame;
+  PXBool                        owns_transform;
+  PXBool                        save_binary;
+
+  int                           num_surfaces;
+  int                           current_surface;
+  int                           num_renderers;
+
+  PXTkOptionMenu* currentSurface;
+  PXTkLabel*      message;
+  PXTkOptionMenu* displayMode;
+
+  //  vtkpxGUITransformControl* transformControl;
+  PXTkDialog      *decimateGUI;
+  PXTkDialog      *smoothGUI;
+  PXTkDialog      *normalsGUI;
+  PXTkDialog      *cleanGUI;
+  PXTkDialog      *curvatureGUI;
+  PXTkDialog      *connectGUI;
+  PXTkDialog      *extractGUI;
+  PXTkDialog      *extractObjectMapGUI;
+  PXTkDialog      *displaySizeGUI;
+  PXTkDialog      *mapFunctionalGUI;
+  PXTkDialog      *appendGUI;
+  PXTkDialog      *thresholdPointsGUI;
+  // mpj
+  PXTkDialog      *opacityGUI;
+  PXTkScale       *opacityFactor;
+  // mpj
+
+  PXTkArrowScale  *thresholdScale[3];
+  PXTkCheckButton *extractDoThreshold;
+  PXTkArrowScale  *extractSmoothScale;
+  PXTkOptionMenu  *extractDoSmooth;
+  PXTkArrowScale  *extractResampleScale;
+  PXTkCheckButton *extractDoResample;
+
+  PXTkCheckButton *appendButton[10];
+  PXTkCheckButton *appendObjectMap;
+  PXTkOptionMenu  *appendResult;
+
+  PXTkScale       *decimateFactor;
+  PXTkCheckButton *preserveTopology;
+  
+  PXTkScale         *smoothIterations;
+  PXTkScale         *smoothRelaxation;
+  PXTkCheckButton*  smoothEdgeButton;
+  PXTkOptionMenu*   smoothMethod;
+  
+  PXTkLabel*        extractObjectMapLabel;
+  PXTkArrowScale   *objectMapRange[2];
+  PXTkOptionMenu   *objectMapValues[3];
+
+  PXTkScale*        featureAngle;
+  PXTkCheckButton*  edgeSplitButton;
+  PXTkCheckButton*  flipNormalsButton;
+
+  PXTkOptionMenu*   cleanMethod;
+  PXTkScale*        cleanTolerance;
+
+  PXTkOptionMenu*   curvatureType;
+  PXTkOptionMenu*   curvatureMode;
+  PXTkScale*        curvatureScale;
+  PXTkScale*        curvatureRange;
+
+ 
+  PXTkOptionMenu* connectType;
+  PXTkLabel*      connectPoint;
+
+  PXTkOptionMenu* mapFunctionalType;
+  PXTkOptionMenu* mapFunctionalMode;
+  PXTkArrowScale*      mapThreshold[2];
+  PXTkArrowScale*      mapDistance[2];
+
+  PXTkArrowScale*    displaySize[2];
+  
+
+
+  PXTkArrowScale*      pointsThresholdScale[2];
+  PXTkOptionMenu*      pointsThresholdInput;
+
+  
+  virtual void InitGraphics();
+
+
+  virtual int doDecimate(int apply=0);
+  virtual int doSmooth(int apply=0);
+  virtual int doNormals(int apply=0);
+
+  virtual int doTriangulate(int apply=0);
+  virtual int doDelaunay3D(int apply=0);
+  virtual int doSubdivision(int apply=0);
+  virtual int doClip(int apply=0);
+  virtual int doConnect(int apply=0);
+  virtual int doClean(int apply=0);
+  virtual int doCurvature(int apply=0);
+  //  virtual int doTransform(int apply=0);
+  virtual int doExtract(int apply=0);
+  virtual int doMapFunctional(int apply=0);
+  virtual int doExtractObjectMap(int apply=0);
+  virtual int doChangeDisplaySize(int apply=0);
+  virtual int doAppend(int apply=0);
+  virtual int doThresholdPoints(int apply=0);
+
+  virtual int doOpacity(int apply=0);
+};
+
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIRenderer.cpp b/bioimagesuite30_src/GUI/vtkpxGUIRenderer.cpp
new file mode 100644
index 0000000..9b295d1
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIRenderer.cpp
@@ -0,0 +1,3120 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIRenderer.cpp,v $
+  Language:  C++
+  Date:      $Date: 2003/05/15 15:33:58 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxGUIRenderer.h"
+#include "vtkObjectFactory.h"
+#include "pxtkcomplexwidgets.h"
+#include <vtkVRMLExporter.h>
+#include <vtkTextMapper.h>
+#include <vtkTIFFWriter.h> 
+#include <vtkJPEGWriter.h> 
+#include <vtkIVExporter.h> 
+#include <vtkActor2D.h>
+#include <vtkRendererSource.h>
+#include <vtkCubeSource.h>
+#include <vtkPolyDataMapper.h>
+#include <vtkActor.h>
+#include <vtkMath.h>
+#include "pxutil.h"
+#include "pxtkapp.h"
+#include "vtkImageConstantPad.h"
+#include "pxitkcombobox.h"
+#include "vtkCommand.h"
+#include "vtkTransform.h"
+#include "vtkActorCollection.h"
+#include "vtkVolumeCollection.h"
+#include "vtkTextProperty.h"
+#include "vtkpxGUIBaseImageViewer.h"
+// ------------------------------------- Helper Class ------------------------------
+
+class vtkpxGUIRendererCallback : public vtkCommand
+{
+public:
+
+  static vtkpxGUIRendererCallback *New() {
+    return new vtkpxGUIRendererCallback;
+  }
+  vtkTypeMacro(vtkpxGUIRendererCallback,vtkCommand);
+  virtual void AttachFilter(vtkpxGUIRenderer* guiren0) { this->guiren=guiren0; }
+  virtual void Execute(vtkObject *caller,unsigned long event, void* vtkNotUsed(v)) {
+    
+    if (this->guiren==NULL)
+      return;
+    if (caller)
+      this->guiren->RendererEvent();
+  }
+
+protected:
+
+  vtkpxGUIRendererCallback() {
+    this->guiren=NULL;
+  }
+
+  vtkpxGUIRendererCallback(const vtkpxGUIRendererCallback&) {};
+  void operator=(const vtkpxGUIRendererCallback&) {};
+
+  vtkpxGUIRenderer*   guiren;
+};
+
+
+
+// ---------------------------------------------------------------------------------
+
+
+vtkpxGUIRenderer* vtkpxGUIRenderer::New()
+{
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIRenderer");
+  if(ret)
+      {
+	return (vtkpxGUIRenderer*)ret;
+      }
+  return new vtkpxGUIRenderer;
+}
+
+// -----------------------------------------------------------------------------------
+// Construct object with no children.
+// -----------------------------------------------------------------------------------
+vtkpxGUIRenderer::vtkpxGUIRenderer()
+{
+  this->renderer=NULL;
+  this->CurrentImage=NULL;
+  this->textActor=NULL;
+  this->main_light=NULL;
+  this->mode_menu=NULL;
+  this->mode_button=NULL;
+  this->plane_button=NULL;
+  this->plane_menu=NULL;
+  this->angle_menu=NULL;
+  this->last_axis=-1;
+
+  this->flip_mode=0;
+  this->clip_mode=PXFalse;
+  this->vertical_decoration=PXFalse;
+  this->no_gui=PXFalse;
+  this->plane_mode=-1;
+  this->orientation=0;
+
+  this->NoPolyClipControls=0;
+  
+  for (int k=0;k<3;k++)
+      {
+	this->bounds[2*k]=0;
+	this->bounds[2*k+1]=1.0;
+	this->clipBounds[k]=0.5;
+      }
+
+  this->update_rate[0]=0.1;
+  this->update_rate[1]=15.0;
+  this->enableClip=NULL;
+
+  this->clipping_thickness=2.0;
+  this->clipping_front=-1.0;
+  this->camera_scale=1.0;
+  this->auto_zoom=1.0;
+
+  this->clip_min=NULL;
+  this->clip_thickness=NULL;
+  this->hasclipcontrols=0;
+
+  this->ViewerCoordinates[0]=0;
+  this->ViewerCoordinates[1]=0;
+  this->ViewerCoordinates[2]=0;
+
+  this->CameraEventParent=NULL;
+  this->CameraCallbackNo=-1;
+  this->CameraCallbackName=NULL;
+  this->CameraPresets=vtkpxCameraInfo::New();
+  this->RendererCallback=NULL;
+  this->ActorTransform=NULL;
+  this->EnableActorTransform=0;
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      for (int ib=0;ib<=1;ib++)
+	{
+	  int index=2*ia+ib;
+	  this->ClippingPlanes[index]=vtkPlane::New();
+	  double p[3]= { 0.0,0.0,0.0};
+	  double n[3]= { 0.0,0.0,0.0};
+	  if (ib==1)
+	    {
+	      p[ia]=1.0;
+	      n[ia]=-1.0;
+	    }
+	  else
+	    {
+	      n[ia]=1.0;
+	    }
+
+	  this->ClippingPlanes[index]->SetOrigin(p);
+	  this->ClippingPlanes[index]->SetNormal(n);
+	}
+    }
+}
+// -----------------------------------------------------------------------------------
+vtkpxGUIRenderer::~vtkpxGUIRenderer()
+{
+  if (this->renderer)
+    this->renderer->Delete();
+  if (this->textActor)
+    this->textActor->Delete();
+  if (this->main_light)
+    this->main_light->Delete();
+
+  if (this->CameraCallbackName!=NULL)
+    delete [] this->CameraCallbackName;
+
+
+  if (this->RendererCallback!=NULL)
+    this->RendererCallback->Delete();
+
+  this->SetCurrentImage(NULL);
+  this->CameraPresets->Delete();
+
+  if (this->ActorTransform!=NULL)
+    this->ActorTransform->Delete();
+
+  for (int ia=0;ia<=5;ia++)
+    {
+      if (this->ClippingPlanes[ia]!=NULL)
+	this->ClippingPlanes[ia]->Delete();
+    }
+}
+// -----------------------------------------------------------------------
+void vtkpxGUIRenderer::SetCameraCallback(vtkpxGUIComponent* comp,int call_no)
+{
+  this->CameraEventParent=comp;
+  this->CameraCallbackNo=call_no;
+}
+
+void vtkpxGUIRenderer::SetCameraCallback(const char* name)
+{
+  if (name==NULL)
+    return;
+
+  if (this->CameraCallbackName!=NULL)
+    delete [] this->CameraCallbackName;
+
+  this->CameraCallbackName=new char[strlen(name)+1];
+  strcpy(this->CameraCallbackName,name);
+}
+// -----------------------------------------------------------------------  
+
+
+
+// -------------------------------------------------------------------
+//  
+//    I n i t i a l i z e    ( and GUI if present)
+//
+// -------------------------------------------------------------------
+char* vtkpxGUIRenderer::Initialize(const char* widgetname,vtkRenderer* ren,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+
+  this->renderer=ren;
+  vtkpxGUIComponent::Initialize(widgetname,inside);
+  
+  this->RendererCallback=vtkpxGUIRendererCallback::New();
+  this->RendererCallback->AttachFilter(this);
+  this->renderer->AddObserver(vtkCommand::StartEvent,this->RendererCallback);
+
+
+
+
+  
+  if (inside==0)
+    this->EventManager->setTitle("3D Renderer Controls");
+  
+  PXTkFrame* manager=(PXTkFrame*)this->EventManager->getMainWindow();
+
+  // Just add Light and make sure camera is parallel
+
+  main_light=vtkLight::New();
+  renderer->AddLight(main_light);
+  renderer->GetActiveCamera()->ParallelProjectionOn();
+
+  // Add Controls here 
+  // -----------------
+
+  if (no_gui==PXFalse)
+      {
+	PXTkDualArrowLabel* zoom,*rotate,*rotate2;
+	PXTkFrame* topframe,*bottomframe,*middleframe;
+
+	if (vertical_decoration==PXFalse)
+	  {
+	    topframe=new PXTkFrame(this->EventManager,manager);
+	    middleframe=new PXTkFrame(this->EventManager,manager);
+	    bottomframe=new PXTkFrame(this->EventManager,manager);
+	    manager->addChildren("-side top -expand true -fill x ",topframe,middleframe,bottomframe);      
+	  } 
+	else
+	  {
+	    topframe=manager;
+	    middleframe=manager;
+	    bottomframe=manager;
+	  }
+
+	if (vertical_decoration)
+	  {
+	    zoom=new PXTkDualArrowLabel(this->EventManager,topframe,"Zm",102,101,1);
+	    rotate=new PXTkDualArrowLabel(this->EventManager,topframe,"Az",106,107,1);
+	    rotate2=new PXTkDualArrowLabel(this->EventManager,topframe,"El",116,117,1);
+	  }
+	else
+	  {
+	    zoom=new PXTkDualArrowLabel(this->EventManager,topframe,"Zm",102,101,0);
+	    rotate=new PXTkDualArrowLabel(this->EventManager,topframe,"Az",106,107,0);
+	    rotate2=new PXTkDualArrowLabel(this->EventManager,topframe,"El",116,117,0);
+	    this->angle_menu=new PXTkOptionMenu(this->EventManager,topframe,"5.0",-1);
+	    this->angle_menu->addOption("10.0");
+	    this->angle_menu->addOption("15.0");
+	    this->angle_menu->addOption("30.0");
+	    this->angle_menu->addOption("45.0");
+	    this->angle_menu->addOption("60.0");
+	    this->angle_menu->addOption("90.0");
+	    this->angle_menu->addOption("1200.0");
+	  }
+	
+	plane_button=new PXTkButton(this->EventManager,topframe,"Rt",103); 
+	
+	SetPlaneMode(plane_mode);
+	plane_button->setPadding(1,3,3);
+
+	PXTkButton* cp=new PXTkButton(this->EventManager,topframe,"Cl",123);
+
+	if (vertical_decoration)
+	  {
+	    topframe->addChildren("-side top -expand false ",zoom,rotate,this->angle_menu,rotate2);     
+ 	    topframe->addChildren("-side top -expand false ",plane_button,cp);      
+	  }
+	else
+	  {
+	    topframe->addChildren("-side left -expand false ",zoom,rotate,this->angle_menu,rotate2);     
+ 	    topframe->addChildren("-side left -expand false ",plane_button,cp);      
+	  }
+	
+	
+	if (plane_mode==-1)
+	    {
+	      plane_menu=new PXITkComboBox(this->EventManager,middleframe,"View:",109);
+	      plane_menu->addOption("XY",109);
+	      plane_menu->addOption("XZ",109);
+	      plane_menu->addOption("XY",109);
+	      plane_menu->addOption("-YZ",109);
+	      plane_menu->addOption("-XZ",109);
+	      plane_menu->addOption("-XY",109);
+	      int tmp=this->orientation;
+	      this->orientation=-1;
+	      this->SetOrientation(tmp);
+
+	      PXTkButton* ad=new PXTkButton(this->EventManager,middleframe,"Add",110); 
+	      update_plane=new PXTkButton(this->EventManager,middleframe,"Upd",111); 
+	      PXTkButton* ld=new PXTkButton(this->EventManager,middleframe,"Load",112); 
+	      PXTkButton* sv=new PXTkButton(this->EventManager,middleframe,"Save",113); 
+	      
+	      if (vertical_decoration)
+		{
+		  middleframe->addChildren("-side top -expand false",plane_menu,ad);      
+		  middleframe->addChildren("-side top -expand false",update_plane,ld,sv);
+		}
+	      else
+		{
+		  middleframe->addChildren("-side left -expand false",plane_menu,ad);      
+		  middleframe->addChildren("-side left -expand false",update_plane,ld,sv);
+		}
+	      plane_menu->selectItem(2);
+	      plane_menu->enableEntry(PXFalse);
+	      update_plane->enable(PXFalse);
+	    }
+
+
+	PXTkButton* save=new PXTkButton(this->EventManager,topframe,"Sv",114);
+	save->setPadding(1,3,3);
+
+  
+	if (vertical_decoration)
+	    {
+	      mode_button=new PXTkButton(this->EventManager,topframe,"Nr",105);
+	      mode_button->setPadding(1,3,3);
+	      topframe->addChildren("-side top ",mode_button,save);      
+	    }
+	else
+	    {
+	      mode_menu=new PXTkOptionMenu(this->EventManager,topframe,"Flipped",104);
+	      mode_menu->addOption("Normal");
+	      topframe->addChildren("-side left",mode_menu,save);      
+	    }
+
+	if (!flip_mode)
+	    SetFlipMode(flip_mode);
+	
+	if (!this->EventManager->isInside())
+	    {
+	      PXTkButton* cl=new PXTkButton(this->EventManager,topframe,"Ok",3);
+	      if (vertical_decoration)
+		{
+		  topframe->addChildren("-side top",cl);
+		}
+	      else
+		{
+		  cl->setText("Close");
+		  topframe->addChildren("-side left ",cl);
+		}
+	    } 
+	
+	if (bottomframe!=topframe)
+	  {
+	    PXTkFrame* b2=new PXTkFrame(this->EventManager,manager);
+	    PXTkFrame* b3=new PXTkFrame(this->EventManager,manager);
+	    bottomframe->addChildren("-side right -expand f" ,b3);
+	    bottomframe->addChildren("-side left -expand t -fill x",b2);
+	    
+	    PXTkButton* rt=new PXTkButton(this->EventManager,b3,"Rt",122,PXTrue);
+	    b3->addChildren("-side right -expand f",rt);
+	    
+	    clip_min=new PXTkArrowScale(this->EventManager,b2,"Near Plane:",120,PXTrue);
+	    clip_thickness=new PXTkArrowScale(this->EventManager,b2,"Thickness:",121,PXTrue);
+	    
+	    clip_min->setLengthWidth(120,10);
+	    clip_thickness->setLengthWidth(150,10);
+	    clip_thickness->setRange(0.01,200.0);
+	    clip_min->setIncrement(1);
+	    clip_thickness->setIncrement(1);
+	    clip_min->setRange(0.01,200.0);
+	    clip_thickness->setValue(this->clipping_thickness);
+	    this->hasclipcontrols=1;
+
+	    b2->addChildren("-side top -expand t -fill x",clip_min->getMainWindow(),clip_thickness->getMainWindow());
+
+	    if (this->NoPolyClipControls==0)
+	      {
+		
+		PXTkLabelFrame* labfr=new PXTkLabelFrame(this->EventManager,b2,"Polygonal Clipping");
+		b2->addChildren("-side top -expand false -fill x",labfr);
+		
+		for (int ia=0;ia<=2;ia++)
+		  {
+		    PXTkFrame* fr=new PXTkFrame(this->EventManager,labfr);
+		    labfr->addChildren("-side top -expand false -fill x",fr);
+		    for (int ib=0;ib<=1;ib++)
+		      {
+			int index=ia*2+ib;
+			if (ia==0)
+			  strcpy(pxtk_buffer4,"x-");
+			else if (ia==1)
+			  strcpy(pxtk_buffer4,"y-");
+			else
+			  strcpy(pxtk_buffer4,"z-");
+			
+			if (ib==0)
+			  sprintf(pxtk_buffer4,"%s-min",pxtk_buffer4);
+			else
+			  sprintf(pxtk_buffer4,"%s-max",pxtk_buffer4);
+			
+			clip_planes[index]=new PXTkArrowScale(this->EventManager,fr,pxtk_buffer4,125);
+			clip_planes[index]->setRange(0,400);
+			clip_planes[index]->setLengthWidth(120,10);
+			//		    clip_planes[index]->setDigits(4);
+			clip_planes[index]->setResolution(1);
+		      }
+		    fr->addChildren("-side left -expand true -fill x ",clip_planes[2*ia]->getMainWindow(),
+				    clip_planes[2*ia+1]->getMainWindow());
+		  }
+		this->enableClip=new PXTkCheckButton(this->EventManager,labfr,"Enable Polygonal Clipping",124);
+		this->enableClip->setState(PXFalse);
+		labfr->addChildren("-side bottom -expand false -fill x",this->enableClip);
+	      }
+	  }
+      }
+  View();
+  return GetWidgetName();
+}
+/* -------------------------------------------------------------------------
+
+    R e n d e r    S t u f f
+
+
+ -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::Render()
+{
+  if (renderer==NULL)
+    return;
+
+  vtkCamera* camera=renderer->GetActiveCamera();
+  main_light->SetPosition(camera->GetPosition());
+  main_light->SetFocalPoint(camera->GetFocalPoint());
+  renderer->GetRenderWindow()->Render();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::RenderDelay(int t)
+{
+  Render();
+  /*if (renderer!=NULL)
+    Tcl_CreateTimerHandler(t,vtkpxGUIRenderer::HandleRenderEvent,this);*/
+}
+
+void vtkpxGUIRenderer::HandleRenderEvent(void *arg1)
+{
+  ((vtkpxGUIRenderer*)arg1)->Render();
+}
+
+/* -------------------------------------------------------------------------*/
+//
+//   A c c e s s  (Get/Set) Stuff from Outside 
+//
+/* -------------------------------------------------------------------------*/
+vtkRenderer* vtkpxGUIRenderer::GetRenderer()
+{
+  return renderer;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::GetBounds(double bd[6])
+{
+ for (int k=0;k<6;k++)
+      bd[k]=bounds[k];
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIRenderer::GetFlipMode()
+{
+  return flip_mode;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIRenderer::GetPlaneMode()
+{
+  return plane_mode;
+}
+/* -------------------------------------------------------------------------*/
+double vtkpxGUIRenderer::GetCameraScale()
+{
+  return camera_scale;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetLabel(const char* text,double x,double y,double c1,double c2,double c3)
+{
+  if (renderer==NULL)
+      return;
+  
+  vtkTextMapper* tm=vtkTextMapper::New();
+
+  if (tm==NULL)
+      return;
+
+  int havetextactor=1;
+
+  tm->SetInput(text);
+  if (textActor==NULL)
+      {
+	havetextactor=0;
+	textActor=vtkActor2D::New();
+      }
+  
+  textActor->SetMapper(tm);
+  tm->GetTextProperty()->BoldOn();
+  tm->GetTextProperty()->SetFontFamilyToArial();
+  tm->GetTextProperty()->ShadowOff();
+  tm->GetTextProperty()->SetFontSize(14);
+
+  textActor->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
+  textActor->SetPosition(x,y);
+  textActor->GetProperty()->SetColor(c1,c2,c3);
+  textActor->GetProperty()->SetOpacity(1);
+  textActor->GetProperty()->SetDisplayLocationToForeground();
+
+  textActor->SetVisibility(1);
+  //  textActor->Update();
+  
+  
+  if (havetextactor==0)
+    renderer->AddActor2D(textActor);
+
+  tm->Delete();
+}
+ 
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::HideLabel()
+{
+  if (textActor!=NULL)
+      textActor->SetVisibility(0);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::ShowLabel()
+{
+  if (textActor!=NULL)
+      textActor->SetVisibility(1);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetFlipMode(int mode)
+{
+  flip_mode=mode;
+  if (mode_menu!=NULL)
+      {
+	if (flip_mode)
+	    mode_menu->setIndex(0);
+	else
+	    mode_menu->setIndex(1);
+      }
+  else if (mode_button!=NULL)
+      {
+	if (flip_mode)
+	    mode_button->setText("Nr");
+	else
+	    mode_button->setText("Fl");
+      }
+
+  if (renderer!=NULL)
+      MoveAbove(plane_mode);
+}
+/* -------------------------------------------------------------------------*/
+int  vtkpxGUIRenderer::GetOrientation()
+{
+  return this->orientation;
+}
+// -----------------------------------------------------------------------------------
+void vtkpxGUIRenderer::SetOrientation(int orient,int doupdate)
+{
+  int orn=this->orientation;
+  this->orientation=orient;
+
+  if (orn!=this->orientation && this->plane_menu!=NULL)
+    {
+      int old=plane_menu->getIndex();
+      int oldstyleorient=vtkpxGUIBaseImageViewer::MapOrientationToOldStyle(this->orientation);
+
+      if (this->orientation>=40)
+	oldstyleorient+=4;
+
+      switch(oldstyleorient)
+	{
+	case 0:
+	  plane_menu->changeLabel(0,"Sagittal-YZ");
+	  plane_menu->changeLabel(1,"Coronal-XZ");
+	  plane_menu->changeLabel(2,"Axial-XY");
+	  plane_menu->changeLabel(3,"Rev Sagittal-YZ");
+	  plane_menu->changeLabel(4,"Rev Coronal-XZ");
+	  plane_menu->changeLabel(5,"Rev Axial-XY");
+	  break;
+	case 1:
+	  plane_menu->changeLabel(0,"Sagittal-YZ");
+	  plane_menu->changeLabel(1,"Axial-XZ");
+	  plane_menu->changeLabel(2,"Coronal-XY");
+	  plane_menu->changeLabel(3,"Rev Sagittal-YZ");
+	  plane_menu->changeLabel(4,"Rev Axial-XZ");
+	  plane_menu->changeLabel(5,"Rev Coronal-XY");
+	  break;
+	case 2:
+	  plane_menu->changeLabel(0,"Coronal-YZ");
+	  plane_menu->changeLabel(1,"Axial-XZ");
+	  plane_menu->changeLabel(2,"Sagittal-XY");
+	  plane_menu->changeLabel(3,"Rev Coronal-YZ");
+	  plane_menu->changeLabel(4,"Rev Axial-XZ");
+	  plane_menu->changeLabel(5,"Rev Sagittal-XY");
+	  break;
+	case 3:
+	  plane_menu->changeLabel(0,"Short Axis");
+	  plane_menu->changeLabel(1,"Radial-1");
+	  plane_menu->changeLabel(2,"Radial-2");
+	  plane_menu->changeLabel(3,"Rev Short-Axis");
+	  plane_menu->changeLabel(4,"Rev Radial-1");
+	  plane_menu->changeLabel(5,"Rev Radial-2");
+
+	  // Tranposed Axuak
+	case 4:
+	  plane_menu->changeLabel(0,"Coronal-YZ");
+	  plane_menu->changeLabel(1,"Sagittal-XZ");
+	  plane_menu->changeLabel(2,"Axial-YX");
+	  plane_menu->changeLabel(3,"Rev Coronal-YZ");
+	  plane_menu->changeLabel(4,"Rev Sagittal-XZ");
+	  plane_menu->changeLabel(5,"Rev Axial-YX");
+	  break;
+	case 5:
+	  plane_menu->changeLabel(0,"Axial-YZ");
+	  plane_menu->changeLabel(1,"Sagittal-ZX");
+	  plane_menu->changeLabel(2,"Coronal-YX");
+	  plane_menu->changeLabel(4,"Rev Sagittal-ZX");
+	  plane_menu->changeLabel(3,"Rev Axial-YZ");
+	  plane_menu->changeLabel(5,"Rev Coronal-YX");
+	  break;
+	case 6:
+	  plane_menu->changeLabel(1,"Coronal-ZX");
+	  plane_menu->changeLabel(0,"Axial-ZY");
+	  plane_menu->changeLabel(2,"Sagittal-YX");
+	  plane_menu->changeLabel(4,"Rev Coronal-ZX");
+	  plane_menu->changeLabel(3,"Rev Axial-ZY");
+	  plane_menu->changeLabel(5,"Rev Sagittal-YX");
+	  break;
+	  break;
+	}
+      plane_menu->setIndex(old);
+    }
+
+
+  if (renderer!=NULL && doupdate>0)
+      MoveAbove(plane_mode);
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetClipMode(PXBool m)
+{
+  clip_mode=m;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetPlaneMode(int m)
+{
+  if (m>5)
+    {
+      int preset=m-6;
+      this->CameraPresets->UpdateCamera(this->renderer->GetActiveCamera(),preset);
+      this->Render();
+      return;
+    }
+
+  plane_mode=Irange(m,-1,5);
+  
+  if (plane_button!=NULL)
+      {
+	switch(plane_mode)
+	    {
+	    case 2:
+	    case 5:
+	      plane_button->setText("XY");
+	      break;
+	    case 1:
+	    case 4:
+	      plane_button->setText("XZ");
+	      break;
+	    case 0:
+	    case 3:
+	      plane_button->setText("YZ");
+	      break;
+	    case -1:
+	      plane_button->setText("Va");
+	      break;
+	    }
+      }
+  
+  camera_scale=GetCameraWidth();
+  if (renderer!=NULL)
+    MoveAbove(plane_mode);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetCameraScale(double autoz)
+{
+  camera_scale=autoz;
+}
+
+void vtkpxGUIRenderer::SetAutoZoom(double autoz)
+{
+  auto_zoom=Frange(autoz,0.5,2.0);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetCameraScale(vtkpxGUIRenderer* ren)
+{
+  if (ren==NULL || renderer==NULL)
+      return;
+
+  double scale2= ren->GetCameraScale();
+  double wd1   = this->GetCameraWidth();
+  double wd2   = ren->GetCameraWidth();
+
+  if (wd1>0 && wd2>0)
+      {
+	double scale=wd1*scale2/wd2;
+	Zoom(scale,PXTrue);
+      }
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetViewport(double x0,double y0,double x1,double y1)
+{
+  if (renderer!=NULL)
+      {
+	renderer->SetViewport(x0,y0,x1,y1);
+	renderer->Render();
+      }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetUpdateRate(double interactiverate,double staticrate)
+{
+  if (renderer!=NULL)
+      renderer->GetRenderWindow()->SetDesiredUpdateRate(staticrate);
+
+  update_rate[0]=staticrate;  update_rate[1]=interactiverate;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetVerticalDecoration(PXBool m)
+{
+  if (this->Initialized==0)
+      vertical_decoration=m;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetNoGUI(PXBool gui)
+{
+  no_gui=PXTrue;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetBounds(double bd[6])
+{
+  for (int k=0;k<6;k++)
+    this->bounds[k]=bd[k];
+
+  this->ResetClipScales();
+
+}
+/* -------------------------------------------------------------------------*/ 
+void vtkpxGUIRenderer::SetBounds(vtkDataSet* dataset)
+{
+  dataset->GetBounds(this->bounds);
+  this->ResetClipScales();
+}
+/* -------------------------------------------------------------------------*/ 
+double vtkpxGUIRenderer::GetClipFront()
+{
+  return clipping_front;
+}
+
+double vtkpxGUIRenderer::GetClipThickness()
+{
+  return clipping_thickness;
+}
+
+void vtkpxGUIRenderer::SetClipFront(double fr)
+{
+  clipping_front=fr;
+}
+
+void vtkpxGUIRenderer::SetClipThickness(double thick)
+{
+  if (thick<0.0)
+    {
+      if (this->orientation!=3 || this->CurrentImage==NULL && plane_mode!=-1)
+	switch (plane_mode)
+	  {
+	  case 2:
+	  case 5:
+	    thick=this->CurrentImage->GetSpacing()[2];
+	    break;
+	  case 1:
+	  case 4:
+	    thick=this->CurrentImage->GetSpacing()[1];
+	    break;
+	  case 0:
+	  case 3:
+	    thick=this->CurrentImage->GetSpacing()[0];
+	    break;
+	  }
+    }
+  clipping_thickness=thick;
+  View();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetClipBounds(double x,double y,double z)
+{
+  clipBounds[0]=x;
+  clipBounds[1]=y;
+  clipBounds[2]=z;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetClipBounds(int x,int y,int z,double sp[3],double ori[3])
+{
+  clipBounds[0]=x*sp[0]+ori[0];
+  clipBounds[1]=y*sp[1]+ori[1];
+  clipBounds[2]=z*sp[2]+ori[2];
+}  
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIRenderer::InViewport(int x1,int x2)
+{
+  if (renderer==NULL)
+      return 0;
+  
+  int *sz=renderer->GetRenderWindow()->GetSize();
+  double* vp=renderer->GetViewport();
+
+  // Check for inside the viewpoer stuff
+  if (x1<vp[0]*sz[0] || x1>vp[2]*sz[0])
+      return 0;
+  if (x2<vp[1]*sz[1] || x2>vp[3]*sz[1])
+      return 0;
+
+  return 1;
+}
+/* -------------------------------------------------------------------------
+   
+   M o u s e    C a l l b a c k   H a n d l i ng 
+
+ -------------------------------------------------------------------------*/
+
+int vtkpxGUIRenderer::MouseEventRotate(int state,int x1,int x2)
+{
+
+  static int oldx1=-1,oldx2=-1;
+  static double deltaElevation=0.1,deltaAzimuth=0.1;
+
+  switch (state)
+    {
+    case 0:
+      {
+	oldx1=x1;
+	oldx2=x2;
+	renderer->GetRenderWindow()->SetDesiredUpdateRate(update_rate[1]);
+	
+	int *sz=renderer->GetRenderWindow()->GetSize();
+	double* vp=renderer->GetViewport();
+	
+	double vsize[2];
+	vsize[0]=sz[0]*(vp[2]-vp[0]);
+	vsize[1]=sz[1]*(vp[3]-vp[1]);
+	
+	deltaElevation = -20.0/ vsize[1]*  10.0;
+	deltaAzimuth   = -20.0/ vsize[0] * 10.0;
+      }
+      break;
+      
+    case 1:
+      {
+	vtkCamera* camera=renderer->GetActiveCamera();
+	
+	double rxf = (double)(x1 - oldx1) * deltaAzimuth;
+	double ryf = (double)(x2 - oldx2) * deltaElevation;
+	
+	camera->Azimuth(rxf);
+	camera->Elevation(ryf);
+	camera->OrthogonalizeViewUp();
+	
+	oldx1=x1;
+	oldx2=x2;
+	this->CameraModifiedCallback();
+	Render();
+      }
+      break;
+    case 2:
+      renderer->GetRenderWindow()->SetDesiredUpdateRate(update_rate[0]);
+      this->CameraModifiedCallback();
+      Render();
+      break;
+    }
+
+  return 1;
+
+}
+
+int vtkpxGUIRenderer::MouseEventPan(int state,int x1,int x2)
+{
+  static int oldx1=-1,oldx2=-1;
+  switch (state)
+    {
+    case 0:
+      oldx1=x1;
+      oldx2=x2;
+      renderer->GetRenderWindow()->SetDesiredUpdateRate(update_rate[1]);
+      break;
+      
+    case 1:
+      {
+	vtkCamera* camera=renderer->GetActiveCamera();
+	double FPoint[3],PPoint[3];
+	camera->GetFocalPoint(FPoint);
+	camera->GetPosition(PPoint);
+
+	renderer->SetWorldPoint(FPoint[0],FPoint[1],FPoint[2],1.0);
+	renderer->WorldToDisplay();
+	
+	double DPoint[3],focalDepth;
+	
+	this->renderer->GetDisplayPoint(DPoint);
+	focalDepth=DPoint[2];
+
+	/*sprintf(line,"FPoint=(%.1f,%.1f,%.1f) PPoint=(%.1f,%.1f,%.1f) focDepth=%.1f\n",
+	  FPoint[0],FPoint[1],FPoint[2],
+	  PPoint[0],PPoint[1],PPoint[2],focalDepth);
+	  PXTkApp::printToConsole(line);*/
+
+	int *sz=renderer->GetRenderWindow()->GetSize();
+	double* vp=renderer->GetViewport();
+
+	double WindowCenterX=0.5*(vp[0]+vp[2])*sz[0];
+	double WindowCenterY=0.5*(vp[1]+vp[3])*sz[1];
+
+	double APoint0=WindowCenterX + (x1 - oldx1 );
+	double APoint1=WindowCenterY + (x2 - oldx2 );
+
+	this->renderer->SetDisplayPoint(APoint0,APoint1,focalDepth);
+	this->renderer->DisplayToWorld();
+
+	double RPoint[4];
+	this->renderer->GetWorldPoint(RPoint);
+
+	if ( RPoint[3] != 0.0 )
+	  {
+	    for (int ia=0;ia<=2;ia++)
+	      RPoint[ia]/=RPoint[3];
+	  }
+	camera->SetFocalPoint(
+			      (FPoint[0]-RPoint[0])/2.0+FPoint[0],
+			      (FPoint[1]-RPoint[1])/2.0+FPoint[1],
+			      (FPoint[2]-RPoint[2])/2.0+FPoint[2]);
+	camera->SetPosition(
+			    (FPoint[0]-RPoint[0])/2.0+PPoint[0],
+			    (FPoint[1]-RPoint[1])/2.0+PPoint[1],
+			    (FPoint[2]-RPoint[2])/2.0+PPoint[2]); 
+
+	oldx1=x1;
+	oldx2=x2;
+	this->CameraModifiedCallback();
+	Render();
+      }
+      break;
+    case 2:
+      renderer->GetRenderWindow()->SetDesiredUpdateRate(update_rate[0]);
+      this->CameraModifiedCallback();
+      Render();
+      break;
+    }
+  return 1;
+}
+
+int vtkpxGUIRenderer::MouseEventZoom(int state,int x1,int x2)
+{
+  static int oldx1=-1,oldx2=-1;
+  switch (state)
+    {
+    case 0:
+      oldx1=x1;
+      oldx2=x2;
+      renderer->GetRenderWindow()->SetDesiredUpdateRate(update_rate[1]);
+      break;
+      
+    case 1:
+      {
+	double zoomFactor=pow(1.02,0.5*(x2-oldx2));
+	vtkCamera* camera=renderer->GetActiveCamera();
+	if (camera->GetParallelProjection() ) 
+	  {
+	    double parallelScale=camera->GetParallelScale()*zoomFactor;
+	    camera->SetParallelScale(parallelScale);
+	  } 
+	else 
+	  {
+	    camera->Dolly(zoomFactor);
+	    this->ResetCameraClippingRange();
+	  }
+	oldx1=x1;
+	oldx2=x2;
+	Render();
+      }
+      break;
+
+    case 2:
+      renderer->GetRenderWindow()->SetDesiredUpdateRate(update_rate[0]);
+      Render();
+      break;
+    }
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIRenderer::ShowCameraControls()
+{
+  if (!this->EventManager->isInside() && !no_gui)
+    {
+      this->EventManager->popupDialog();
+      return 1;
+    }
+  return 0;
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIRenderer::HandleMouseButtonEvent(int nbutton,int state,int x1,int x2,PXTkEventObj* ev)
+{
+  if (!InViewport(x1,x2))
+      return 0;
+  
+  if (renderer==NULL)
+      return 0;
+
+  if( nbutton==6 && state==0)
+    {
+      return this->ShowCameraControls();
+    }
+
+  if (nbutton==5 && state==0)
+    {
+      this->Reset();
+      return 1;
+    }
+
+  if (nbutton==2 || nbutton==9)
+    return this->MouseEventZoom(state,x1,x2);
+  
+  if (nbutton==1 || nbutton==4)
+    return this->MouseEventRotate(state,x1,x2);
+  
+  if (nbutton==3)
+    return this->MouseEventPan(state,x1,x2);
+  
+  return 0;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIRenderer::Get2DClickedPoint(double& px,double& py,int mousex,int mousey,int orient)
+{
+  px=0.0;    py=0.0;	
+
+  if (!InViewport(mousex,mousey))
+      return 0;
+
+
+  if (orient==-1)
+    {
+      orient=last_axis;
+      if (orient==-1)
+	orient=2;
+    }
+  else
+    {
+      orient=vtkpxGUIBaseImageViewer::MapOrientationToOldStyle(orient);
+    }
+
+  vtkCoordinate* coord=vtkCoordinate::New();
+  coord->SetCoordinateSystemToDisplay();
+  coord->SetValue(mousex,mousey,0.0);
+  double* out=coord->GetComputedWorldValue(renderer);
+  //  fprintf(stderr,"out=%.2f,%.2f,%.2f inp=%d,%d\n",out[0],out[1],out[2],mousex,mousey);
+
+  switch (orient)
+      {
+      case 0: // yz plane
+	 px=out[1];
+	 py=out[2];
+	 break;
+      case 1: // xz plane
+	 px=out[0];
+	 py=out[2];
+	 break;
+      case 2: // xy plane
+	 px=out[0];
+	 py=out[1];
+	 break;
+       }
+  coord->Delete();
+  return 1;
+  
+}
+/* -------------------------------------------------------------------------*/
+//
+//   Generic Operations View/Reset/Zoom
+//
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::View(int axis)
+{
+  if (renderer==NULL)
+    return;
+  
+  if (axis==-1)
+    last_axis=plane_mode;
+  else
+    last_axis=axis;
+  
+  if (axis!=-1)
+    {
+      MoveAbove(last_axis);
+      this->CameraModifiedCallback();
+    }
+  else 
+    {
+      this->ResetCamera();
+      this->CameraModifiedCallback();
+      RenderDelay();
+    }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::Reset()
+{
+  SetCameraScale(GetCameraWidth());
+  View(plane_mode);
+  RenderDelay();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::Zoom(double scale,PXBool dorender)
+{
+  if (renderer==NULL)
+      return;
+
+  if (scale<1.0)
+      scale=GetCameraWidth();
+  else
+      scale=Frange(scale,0.001,10000.0);
+  renderer->GetActiveCamera()->SetParallelScale(scale);
+  camera_scale=renderer->GetActiveCamera()->GetParallelScale();
+
+  if (dorender)
+      RenderDelay(); 
+}
+
+void vtkpxGUIRenderer::Rotate(double angle,int doazimuth)
+{
+  this->Rotate(angle,doazimuth,PXTrue);
+}
+
+void vtkpxGUIRenderer::Rotate(double angle,int doazimuth,PXBool dorender)
+{
+  if (renderer==NULL)
+      return;
+
+  if ( (angle==1000.0 || angle==-1000.0) && this->angle_menu!=NULL )
+    {
+      int opt=angle_menu->getIndex();
+      float sgn=2.0*(angle>0)-1.0;
+      switch (opt)
+	{
+	case 0:	  angle=5.0; break;
+	case 1:	  angle=10.0; break;
+	case 2:	  angle=15.0; break;
+	case 3:	  angle=30.0; break;
+	case 4:	  angle=45.0; break;
+	case 5:	  angle=60.0; break;
+	case 6:	  angle=90.0; break;
+	case 7:	  angle=120.0; break;
+	}
+      angle=sgn*angle;
+    }
+  else
+    angle=Frange(angle,-30.0,30.0);
+  
+  if (doazimuth)
+    renderer->GetActiveCamera()->Azimuth(angle);
+  else
+    renderer->GetActiveCamera()->Elevation(angle);
+  renderer->GetActiveCamera()->OrthogonalizeViewUp();
+  if (dorender)
+    RenderDelay(); 
+}
+/* -------------------------------------------------------------------------*/
+// Save as TiFF
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIRenderer::SaveAsTIFF(const char* fname,PXBool wholewindow)
+{
+  if (renderer==NULL)
+      return 0;
+
+  strcpy(pxtk_buffer,fname);
+  char* ln=eatsuffix(fname);
+  sprintf(pxtk_buffer,"%s.tif",ln);
+  delete [] ln;
+  
+  renderer->GetRenderWindow()->Render();
+  char line[400];
+  strncpy(line,fname,400);
+  PXTkApp::executeTclCommand("update idletasks");
+
+  vtkRendererSource* renSrc=vtkRendererSource::New();
+  renSrc->SetInput(renderer);
+  if (wholewindow)
+    renSrc->WholeWindowOn();
+  else
+    renSrc->WholeWindowOff();
+  renSrc->Update();	
+
+  int dim[3]; renSrc->GetOutput()->GetDimensions(dim);
+  
+  vtkImageConstantPad* pad=vtkImageConstantPad::New();
+  pad->SetInput(renSrc->GetOutput());
+  
+  vtkImageWriter* writer=NULL;
+
+  if (strcmp(PXTkApp::getFilenameExtension(line),".jpg")==0 ||
+      (strcmp(PXTkApp::getFilenameExtension(line),".jpeg")==0) )
+    {
+      writer=vtkJPEGWriter::New();
+      int d[3];
+      for (int ia=0;ia<=2;ia++)
+	{
+	  double a=log(float(dim[ia]))/log(float(2.0));
+	  int   t=int(a+0.999);
+	  d[ia]=(int)pow(float(2.0),float(t));
+	}
+      pad->SetOutputWholeExtent(0,d[0]-1,0,d[1]-1,0,0);
+    }
+  else
+    {
+      writer=vtkTIFFWriter::New();
+      pad->SetOutputWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+    }
+
+  pad->SetOutputNumberOfScalarComponents(renSrc->GetOutput()->GetNumberOfScalarComponents());
+  pad->SetConstant(0.0);
+  writer->SetInput(pad->GetOutput());
+
+  writer->SetFileName(line);
+  writer->Write();
+  writer->Delete();
+  renSrc->Delete();
+  pad->Delete();
+
+
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+//
+//  GUI Callback Router
+//
+/* -------------------------------------------------------------------------*/
+int vtkpxGUIRenderer::HandleEvent(int event)
+{
+  if (event<10)
+      return this->EventManager->handleDirectEvent(event);
+  
+
+  switch(event)
+      {
+      case 101:
+	SetCameraScale(GetCameraScale()*1.25);
+	Zoom(camera_scale,PXTrue);
+	if (this->EventParent!=NULL && this->CallbackNo>0)
+	    this->EventParent->HandleEvent(CallbackNo);
+	break;
+	  
+      case 102:
+	SetCameraScale(GetCameraScale()*0.8);
+	Zoom(camera_scale,PXTrue);
+	if (this->EventParent!=NULL && this->CallbackNo>0)
+	    this->EventParent->HandleEvent(CallbackNo);
+	break;
+
+      case 103:
+	Reset();
+	if (this->EventParent!=NULL && this->CallbackNo>0)
+	    this->EventParent->HandleEvent(CallbackNo);
+	break;
+
+      case 104:
+	if (mode_menu->getIndex()==1)
+	  flip_mode=0;
+	else
+	  flip_mode=1;
+
+	Reset();
+	if (this->EventParent!=NULL && this->CallbackNo>0)
+	    this->EventParent->HandleEvent(CallbackNo);
+	break;
+
+      case 105:
+	if (flip_mode)
+	    SetFlipMode(0);
+	else
+	    SetFlipMode(1);
+	Reset();
+	if (this->EventParent!=NULL && this->CallbackNo>0)
+	    this->EventParent->HandleEvent(CallbackNo);
+	break;
+	
+      case 106:
+	Rotate(-1000.0,1,PXTrue);  
+	break;
+
+      case 107:
+	Rotate(1000.0,1,PXTrue); 
+	break;
+
+      case 116:
+	Rotate(-1000.0,0,PXTrue);  
+	break;
+
+      case 117:
+	Rotate(1000.0,0,PXTrue);
+	break;
+
+      case 114:
+	{
+	  char *line=this->EventManager->getSaveFilenameComplex(pxtk_buffer,"screen.jpg",
+								"{\"JPEG Files\" {\"*.jpeg\"}} {\"TIFF File\" {\".tif\"}}");
+
+	  if (line==NULL)
+	      return 0;
+	  if (strlen(line)<1)
+	      return 0;
+
+	  SaveAsTIFF(line,PXFalse);
+	}
+	break;
+
+      case 109:
+	SetPlaneMode(plane_menu->getIndex());
+	if (plane_menu->getIndex()<6)
+	  {
+	    Reset();
+	  }
+	else
+	  return TCL_OK;
+
+	break;
+
+      case 110:
+	if (this->CameraPresets->InsertCamera(this->renderer->GetActiveCamera())>0)
+	  {
+	    char line[30];
+	    sprintf(line,"Custom %d",this->CameraPresets->GetNumberOfCameras());
+	    plane_menu->addOption(line,109);
+	    plane_menu->selectItem(this->CameraPresets->GetNumberOfCameras()+5);
+	    update_plane->enable(PXTrue);
+	  }
+	break;
+
+      case 111:
+	if (plane_menu->getIndex()>5)
+	  this->CameraPresets->CopyCamera(this->renderer->GetActiveCamera(),plane_menu->getIndex()-6);
+	break;
+
+      case 112: // Load
+	{
+	  char* line=this->EventManager->getOpenFilename("Load Camera Presets","Cameras","*.cm");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		{
+		  int old=this->CameraPresets->GetNumberOfCameras();
+		  int ok=this->CameraPresets->Load(line);
+		  if (ok)
+		    {
+		      for (int i=old-1;i>=0;i=i-1)
+			this->plane_menu->clearItem(i);
+		      int np=this->CameraPresets->GetNumberOfCameras();
+		      if (np>0)
+			{
+			  char line2[30];
+			  for (int i=0;i<np;i++)
+			    {
+			      sprintf(line2,"Custom %d",i+1);
+			      plane_menu->addOption(line2,109);
+			      plane_menu->setIndex(6,PXTrue);
+			    }
+			  update_plane->enable(PXTrue);
+			}
+		      else
+			{
+			  plane_menu->setIndex(0,PXTrue);
+			  update_plane->enable(PXFalse);
+			}
+		    }
+		}
+	    }
+	}
+      	break;
+
+      case 113: // Save
+	{
+	  char* line=this->EventManager->getSaveFilename("Save Camera Presets","cameras.cm","Cameras","*.cm");
+	  if (line!=NULL)
+	    {
+	      if (strlen(line)>0)
+		this->CameraPresets->Save(line);
+	    }
+	}
+      	break;
+
+
+
+
+
+      case 120:
+      case 121:
+	// Clip Stuff 
+	{
+	  SetClipFront(clip_min->getValue());
+	  clipping_thickness=clip_thickness->getValue();
+	  vtkCamera* camera=renderer->GetActiveCamera();
+	  camera->SetClippingRange(clipping_front,clipping_front+clipping_thickness);
+	  this->CameraModifiedCallback();
+	  RenderDelay();
+	}
+	break;
+
+      case 122:
+	{
+	  this->ResetCamera();
+	  double r[2]; renderer->GetActiveCamera()->GetClippingRange(r);
+	  clip_min->setRange(r[0],r[1]);
+	  clip_min->setValue(r[0]);
+	  clip_thickness->setRange(0.01,r[1]-r[0]);
+	  clip_thickness->setValue(r[1]-r[0]);
+	  this->CameraModifiedCallback();
+	  RenderDelay();
+	}
+	break;
+	
+	
+	// Forced Clip
+      case 123:
+	{
+	  //	  PXBool a=this->clip_mode;
+	  if (plane_menu!=NULL)
+	    SetPlaneMode(plane_menu->getIndex());
+	  this->MoveAbove(-1);
+	  this->Clip(-1);
+	}
+	break;
+
+      case 124:
+	this->SetPolygonalClipping(-1);
+	this->Render();
+	break;
+
+      case 125:
+	this->UpdateClippingPlanes();
+	this->Render();
+	break;
+      }
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+//
+//  More Complex Stuff 
+//
+/* -------------------------------------------------------------------------*/
+double vtkpxGUIRenderer::GetCameraWidth()
+{
+  double mmwidth=1.0;
+
+  if (renderer==NULL)
+      return mmwidth;
+  
+  double bd[6];
+  renderer->ComputeVisiblePropBounds(bd);
+
+  int w_plane_mode=plane_mode;
+  if (w_plane_mode==-1)
+      {
+	this->ResetCamera();
+	w_plane_mode=last_axis;
+	if (w_plane_mode==-1)
+	    w_plane_mode=2;
+      }
+
+  if (this->orientation!=3 || this->CurrentImage==NULL)
+    {
+      switch (w_plane_mode)
+	{
+	case 2:
+	case 5:
+	  mmwidth=Fmax(bd[3]-bd[2],bd[1]-bd[0]);
+	  break;
+	case 1:
+	case 4:
+	  mmwidth=Fmax(bd[1]-bd[0],bd[5]-bd[4]);
+	  break;
+	case 0:
+	case 3:
+	  mmwidth=Fmax(bd[3]-bd[2],bd[5]-bd[4]);
+	  break;
+	}
+    }
+  else
+    {
+      int   dim[3]; this->CurrentImage->GetDimensions(dim);
+      double  sp[3]; this->CurrentImage->GetSpacing(sp);
+      double ori[3]; this->CurrentImage->GetOrigin(ori);
+      double w=double(dim[0])*sp[0];
+      double h=double(dim[2])*sp[2];
+
+      if (w_plane_mode == 0 || w_plane_mode==3)
+	mmwidth=w;
+      else
+	mmwidth=Fmax(h,w);
+    }
+
+  if (mmwidth<1.0/auto_zoom)
+    return 1.0;
+
+  return mmwidth*auto_zoom;
+}
+/* -------------------------------------------------------------------------*/
+//                     Sagittal/Axial/Coronal -- original image orientations
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::moveAboveSagittal(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis)
+{
+  // If image-orientation is sagittal then
+  // axis = 2 XY --> Sagittal
+  // axis = 1 XZ --> Coronal
+  // axis = 0 YZ --> Axial
+  // suborientation is now a number between 0 and 7
+
+
+  if (this->orientation>=40)
+    {
+      this->moveAboveTransposedSagittal(midx,midy,midz,distance,camera,flip,axis);
+      return;
+    }
+
+
+
+
+  int suborientation=vtkpxGUIBaseImageViewer::MapOrientationToNewStyle(this->orientation)-30;
+
+  int wrongx=(suborientation & 1);
+  int wrongy=(suborientation & 2);
+  int wrongz=(suborientation & 4);
+
+
+  //  fprintf(stderr,"sag orientation=%d suborientation=%d wrongx=%d, wrongy=%d, wrongz=%d flip=%d axis=%d\n",this->orientation,suborientation,
+  //	  wrongx,wrongy,wrongz,flip,axis);
+
+  
+  // First pass to handle flips ....
+  if (wrongz>0 && (axis==0 || axis==1 || axis== 3 || axis == 4))
+    {
+      axis=axis+3;
+      if (axis>5)
+	axis=axis-6;
+    }
+
+  if (wrongx>0) 
+    {
+      if (axis==2 || axis==5)
+	{
+	  axis=axis+3;
+	  if (axis>5)
+	    axis=axis-6;
+	}
+      else if (axis==1 || axis==4)
+	{
+	  flip=1-(flip>0);
+	}
+    }
+
+  if (wrongy>0 && (axis==0 || axis==2 || axis==3 || axis==5))
+    {
+      flip=1-(flip>0);
+    }
+
+  //  fprintf(stderr,"\t\t flip=%d axis=%d\n\n\n\n",flip,axis);
+  //  fflush(stderr);
+
+
+  camera->SetFocalPoint(midx,midy,midz);
+  switch(axis)
+    {
+    case 5: // Axial
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy,midz-distance);
+	  camera->SetViewUp(0,1,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy,midz+distance);
+	  camera->SetViewUp(0,-1,0);
+	}
+      break;
+
+    case 4: // Coronal
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy-distance,midz);
+	  camera->SetViewUp(-1,0,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy+distance,midz);
+	  camera->SetViewUp(1,0,0);
+	}
+      break;
+      
+    case 3: // Sagital
+
+      if (!flip)
+	{
+	  camera->SetPosition(midx-distance,midy,midz);
+	  camera->SetViewUp(0,1,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx+distance,midy,midz);
+	  camera->SetViewUp(0,-1,0);
+	}
+      break;
+
+    case 2: // Axial
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy,midz+distance);
+	  camera->SetViewUp(0,1,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy,midz-distance);
+	  camera->SetViewUp(0,-1,0);
+	}
+      break;
+
+    case 1:
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy+distance,midz);
+	  camera->SetViewUp(-1,0,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy-distance,midz);
+	  camera->SetViewUp(1,0,0);
+	}
+      break;
+      
+    case 0:
+      if (!flip)
+	{
+	  camera->SetPosition(midx+distance,midy,midz);
+	  camera->SetViewUp(0,1,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx-distance,midy,midz);
+	  camera->SetViewUp(0,-1,0);
+	}
+
+      break;
+    }
+  camera->ComputeViewPlaneNormal();
+}
+
+void vtkpxGUIRenderer::moveAboveCoronal(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis)
+{
+  // If image-orientation is axial then
+  // axis = 0 YZ --> Sagittal
+  // axis = 1 XZ --> Axial
+  // axis = 2 XY --> Coronal
+
+  if (this->orientation>=40)
+    {
+      this->moveAboveTransposedCoronal(midx,midy,midz,distance,camera,flip,axis);
+      return;
+    }
+
+
+  // suborientation is now a number between 0 and 7
+  int suborientation=vtkpxGUIBaseImageViewer::MapOrientationToNewStyle(this->orientation)-20;
+
+  int wrongx=(suborientation & 1);
+  int wrongy=(suborientation & 2);
+  int wrongz=(suborientation & 4);
+
+  //  fprintf(stderr,"coronal orientation=%d suborientation=%d wrongx=%d, wrongy=%d, wrongz=%d flip=%d axis=%d\n",this->orientation,suborientation,
+  //	  wrongx,wrongy,wrongz,flip,axis);
+
+  
+  // First pass to handle flips ....
+  // Affects Axial + Coronal
+  if (wrongx>0 && (axis==5 || axis==2 || axis== 4 || axis == 1))
+    {
+      //      fprintf(stderr,"doing x ...");
+      axis=axis+3;
+      if (axis>5)
+	axis=axis-6;
+    }
+
+  // Affects Axial + Sagital
+  if (wrongz>0) 
+    {
+      if (axis==1 || axis==4 )
+	{
+	  flip=1-(flip>0);
+	}
+      else if (axis==0 || axis==3)
+	{
+	  axis+=3;
+	  if (axis>5)
+	    axis=axis-6;
+	}
+    }
+
+  if (wrongy>0 && (axis==0 || axis==2 || axis==3 || axis==5))
+    {
+      //      fprintf(stderr,"doing y ...");
+      flip=1-(flip>0);
+    }
+
+  //  fprintf(stderr,"\t\t flip=%d axis=%d\n\n\n\n",flip,axis);
+  //  fflush(stderr);
+
+
+  camera->SetFocalPoint(midx,midy,midz);
+
+  switch (axis)
+    {
+    case 5: // Coronal Reverse
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy,midz+distance);
+	  camera->SetViewUp(0,-1,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy,midz-distance);
+	  camera->SetViewUp(0,1,0);
+	}
+      break;
+
+    case 4: // Axial Reverse
+      
+      if (flip)
+	{
+	  camera->SetPosition(midx,midy+distance,midz);
+	  camera->SetViewUp(0,0,+1);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy-distance,midz);
+	  camera->SetViewUp(0,0,-1);
+	}
+
+      break;
+      
+    case 3: // Sagittal Reverse
+      
+      if (!flip)
+	{
+	  camera->SetPosition(midx-distance,midy,midz);
+	  camera->SetViewUp(0,-1,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx+distance,midy,midz);
+	  camera->SetViewUp(0,1,0);
+	}
+
+      break;
+
+    case 2: // Coronal
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy,midz-distance);
+	  camera->SetViewUp(0,-1,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy,midz+distance);
+	  camera->SetViewUp(0,1,0);
+	}
+      break;
+
+    case 1: // Axial
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy+distance,midz);
+	  camera->SetViewUp(0,0,-1);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy-distance,midz);
+	  camera->SetViewUp(0,0,+1);
+	}
+      break;
+      
+    case 0: // Sagittal
+      if (!flip)
+	{
+	  camera->SetPosition(midx+distance,midy,midz);
+	  camera->SetViewUp(0,-1,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx-distance,midy,midz);
+	  camera->SetViewUp(0,+1,0);
+	}
+      break;
+    }
+  camera->ComputeViewPlaneNormal();
+}
+
+void vtkpxGUIRenderer::moveAboveAxial(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis)
+{
+
+  if (this->orientation>=40)
+    {
+      this->moveAboveTransposedAxial(midx,midy,midz,distance,camera,flip,axis);
+      return;
+    }
+
+  // If image-orientation is axial then
+  // axis = 0 YZ --> Sagittal
+  // axis = 1 XZ --> Coronal
+  // axis = 2 XY --> Axial
+
+  // suborientation is now a number between 0 and 7
+  int suborientation=vtkpxGUIBaseImageViewer::MapOrientationToNewStyle(this->orientation)-10;
+
+  int wrongx=(suborientation & 1);
+  int wrongy=(suborientation & 2);
+  int wrongz=(suborientation & 4);
+
+  //  fprintf(stderr,"axial orientation=%d suborientation=%d wrongx=%d, wrongy=%d, wrongz=%d\n",this->orientation,suborientation,
+  //	  wrongx,wrongy,wrongz);
+  
+  // First pass to handle flips ....
+  // 
+  if (wrongx>0 && (axis==5 || axis==2 || axis== 4 || axis == 1))
+    {
+      axis=axis+3;
+      if (axis>5)
+	axis=axis-6;
+    }
+
+  if (wrongy>0)
+    {
+      if (axis==2 || axis==5)
+	{
+	  flip=1-(flip>0);
+	}
+      else if (axis==0 || axis==3)
+	{
+	  axis=axis+3;
+	  if (axis>5) 
+	    axis=axis-6;
+	}
+    }
+  if (wrongz>0 && (axis==0 || axis==1 || axis==3 || axis==4))
+    {
+      flip=1-(flip>0);
+    }
+
+  camera->SetFocalPoint(midx,midy,midz);
+
+  switch (axis)
+    {
+
+    case 5: // Axial -- flip LR
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy,midz+distance);
+	  camera->SetViewUp(0,-1,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy,midz-distance);
+	  camera->SetViewUp(0,1,0);
+	}
+      break;
+
+    case 4: // Coronal -- flip LR
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy+distance,midz);
+	  camera->SetViewUp(0,0,1);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy-distance,midz);
+	  camera->SetViewUp(0,0,-1);
+	}
+      break;
+
+    case 3: // Sagital -- flip AP
+      if (!flip)
+	{
+	  camera->SetPosition(midx-distance,midy,midz);
+	  camera->SetViewUp(0,0,1);
+	}
+      else
+	{
+	  camera->SetPosition(midx+distance,midy,midz);
+	  camera->SetViewUp(0,0,-1);
+	}
+
+      break;
+
+    case 2: // Axial 
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy,midz-distance);
+	  camera->SetViewUp(0,-1,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy,midz+distance);
+	  camera->SetViewUp(0,1,0);
+	}
+
+      break;
+
+    case 1: // Coronal
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy-distance,midz);
+	  camera->SetViewUp(0,0,1);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy+distance,midz);
+	  camera->SetViewUp(0,0,-1);
+	}
+      break;
+      
+    case 0: // Sagital
+      if (!flip)
+	{
+	  camera->SetPosition(midx+distance,midy,midz);
+	  camera->SetViewUp(0,0,1);
+	}
+      else
+	{
+	  camera->SetPosition(midx-distance,midy,midz);
+	  camera->SetViewUp(0,0,-1);
+	}
+      break;
+
+    }
+
+  camera->ComputeViewPlaneNormal();
+
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::moveAbovePolar(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis)
+{
+
+  if (this->CurrentImage==NULL)
+    {
+      //      fprintf(stderr,"No Image Set\n");
+      return;
+    }
+
+  int   dim[3]; this->CurrentImage->GetDimensions(dim);
+  double  sp[3]; this->CurrentImage->GetSpacing(sp);
+  double ori[3]; this->CurrentImage->GetOrigin(ori);
+
+  double ox=ori[0]+sp[0]*double(dim[0]-1)*0.5;
+  int slice_no=this->ViewerCoordinates[1];
+  if (axis == 2)
+    slice_no=this->ViewerCoordinates[2];
+  double theta=double(slice_no)/double(dim[2])*M_PI;  
+  double z=sp[0]*double(this->ViewerCoordinates[0])+ori[1];
+
+  
+  switch(axis)
+    {
+    case 0: // Short-Axis
+      camera->SetFocalPoint(ox,ox,z);
+      camera->SetPosition(ox,ox,z+distance);
+      camera->SetViewUp(0,1,0);
+      camera->ComputeViewPlaneNormal();
+      break;
+
+    case 3: // Reverse Short-Axis
+      camera->SetFocalPoint(ox,ox,z);
+      camera->SetPosition(ox,ox,z-distance);
+      camera->SetViewUp(0,1,0);
+      camera->ComputeViewPlaneNormal();
+      break;
+
+    case 2:
+    case 1: // Radial 1 & 2
+      camera->SetFocalPoint(ox,ox,midz);
+      camera->SetPosition(ox-distance*sin(theta),ox+distance*cos(theta),midz);
+      camera->SetViewUp(0,0,1);
+      camera->ComputeViewPlaneNormal();
+      break;
+
+    case 4: // Reverse Radial 1 & 2 
+    case 5:
+      camera->SetFocalPoint(ox,ox,midz);
+      camera->SetPosition(ox+distance*sin(theta),ox-distance*cos(theta),midz);
+      camera->SetViewUp(0,0,1);
+      camera->ComputeViewPlaneNormal();
+    }
+
+
+}
+
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::MoveAbove(int axis)
+{
+  if (renderer==NULL)
+      return;
+
+  if (axis==-1)
+      {
+	if (plane_mode!=-1)
+	  axis=plane_mode;
+	else
+	  return;
+      }
+ 
+
+  
+  double midx,midy,midz;
+
+  if (this->CurrentImage!=NULL)
+    {
+      int   dim[3]; this->CurrentImage->GetDimensions(dim);
+      double  sp[3]; this->CurrentImage->GetSpacing(sp);
+      double ori[3]; this->CurrentImage->GetOrigin(ori);
+
+      midx=double((dim[0]-1)*sp[0])*0.5+ori[0];
+      midy=double((dim[1]-1)*sp[1])*0.5+ori[1];
+      midz=double((dim[2]-1)*sp[2])*0.5+ori[2];
+    }
+  else
+    {
+      renderer->ComputeVisiblePropBounds(bounds);
+      midx=0.5*(bounds[0]+bounds[1]);
+      midy=0.5*(bounds[2]+bounds[3]);
+      midz=0.5*(bounds[4]+bounds[5]);
+    }
+      
+
+  vtkCamera*  camera=renderer->GetActiveCamera();
+  double width=this->GetCameraWidth();
+  double distance=width/tan(camera->GetViewAngle()*vtkMath::Pi()/360.0);
+
+  //  fprintf(stderr,"Move Above this=%d axis=%d orientation=%d, flip_mode=%d\n",this,axis,orientation,flip_mode);
+
+  int oldstyleorient=vtkpxGUIBaseImageViewer::MapOrientationToOldStyle(this->orientation);
+  //  fprintf(stderr,"orientation=%d oldstyle=%d\n",this->orientation,oldstyleorient);
+  switch (oldstyleorient)
+    {
+    case 3:
+      moveAbovePolar(midx,midy,midz,distance,camera,flip_mode,axis);
+      break;
+      
+    case 2:
+      moveAboveSagittal(midx,midy,midz,distance,camera,flip_mode,axis);
+      break;
+    case 1:
+      moveAboveCoronal(midx,midy,midz,distance,camera,flip_mode,axis);
+      break;
+    default:
+      moveAboveAxial(midx,midy,midz,distance,camera,flip_mode,axis);
+      break;
+    }
+
+  this->ResetCameraClippingRange();
+  //  fprintf(stderr,"Camera _scale =%f\n",camera_scale);
+
+  Zoom(camera_scale,PXFalse);
+  
+  if (clip_mode==PXFalse)
+    {
+      this->CameraModifiedCallback();
+      RenderDelay();
+      return;
+    }
+  else
+    {
+      main_light->SetPosition(camera->GetPosition());
+      main_light->SetFocalPoint(camera->GetFocalPoint());
+      Clip(axis);
+    }
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::Clip(int axis)
+{
+  if (renderer==NULL)
+      return;
+
+  if (axis==-1)
+    {
+      if (plane_mode!=-1)
+	axis=plane_mode;
+      else
+	return;
+    }
+
+  vtkCamera*  camera=renderer->GetActiveCamera();
+  double p[3]; camera->GetPosition(p);
+  double front=this->clipping_front;
+  double width=this->GetCameraWidth();
+  double distance=width/tan(camera->GetViewAngle()*vtkMath::Pi()/360.0);
+	  
+  if (this->orientation!=3)
+    {
+      if (this->clipping_front==-1.0)
+	front=fabs(p[axis]-clipBounds[axis])-0.5*clipping_thickness;
+      camera->SetClippingRange(front,front+clipping_thickness);
+    }
+  else
+    {
+      if (this->clipping_front==-1.0)
+	front=distance-0.5*clipping_thickness;
+      camera->SetClippingRange(front,front+clipping_thickness);
+    }
+
+  if (hasclipcontrols)
+    {
+      clip_min->setValue(front);
+      clip_thickness->setValue(clipping_thickness);
+    }
+
+  this->CameraModifiedCallback();
+
+}
+/* -------------------------------------------------------------------------*/
+// Reset Camera
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::ResetCamera()
+{
+  if (this->renderer==NULL)
+    return;
+  double bd[6];
+  renderer->ComputeVisiblePropBounds(bd);
+  this->ResetCamera(bd);
+}
+
+void vtkpxGUIRenderer::ResetCamera(double nbounds[6])
+{
+  if (this->renderer==NULL)
+    return;
+  
+  double center[3];
+  double distance;
+  double width;
+  double vn[3], *vup;
+  
+  vtkCamera* camera=renderer->GetActiveCamera();
+  
+  if ( camera == NULL )
+    return;
+
+  camera->GetViewPlaneNormal(vn);
+  center[0] = (nbounds[0] + nbounds[1])/2.0;
+  center[1] = (nbounds[2] + nbounds[3])/2.0;
+  center[2] = (nbounds[4] + nbounds[5])/2.0;
+
+  width = nbounds[3] - nbounds[2];
+  if (width < (nbounds[1] - nbounds[0]))
+    width = nbounds[1] - nbounds[0];
+  
+  // If we have just a single point, pick a width of 1.0
+  width = (width==0)?(1.0):(width);
+  
+  distance = 0.8*width/tan(camera->GetViewAngle()*vtkMath::Pi()/360.0);
+  distance = distance + (nbounds[5] - nbounds[4])/2.0;
+
+  // check view-up vector against view plane normal
+  vup = camera->GetViewUp();
+  if ( fabs(vtkMath::Dot(vup,vn)) > 0.999 )
+    {
+      vtkWarningMacro(<<"Resetting view-up since view plane normal is parallel");
+      camera->SetViewUp(-vup[2], vup[0], vup[1]);
+    }
+  
+  // update the camera
+  camera->SetFocalPoint(center[0],center[1],center[2]);
+  camera->SetPosition(center[0]+distance*vn[0],
+                                  center[1]+distance*vn[1],
+                                  center[2]+distance*vn[2]);
+
+  this->ResetCameraClippingRange( nbounds );
+
+  // setup default parallel scale
+  camera->SetParallelScale(width);
+}
+
+/* -------------------------------------------------------------------------*/
+// Reset the camera clipping range to include this entire bounding box
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::ResetCameraClippingRange()
+{
+  if (this->renderer==NULL)
+    return;
+  double bd[6];
+  renderer->ComputeVisiblePropBounds(bd);
+  this->ResetCameraClippingRange(bd);
+}
+
+void vtkpxGUIRenderer::ResetCameraClippingRange( double nbounds[6] )
+{
+  if (this->renderer==NULL)
+    return;
+  
+  vtkCamera* camera=renderer->GetActiveCamera();
+  double  vn[3], position[3], a, b, c, d;
+  double  range[2], dist;
+  int     i, j, k;
+
+  // Don't reset the clipping range when we don't have any 3D visible props
+  if ( nbounds[0] == VTK_LARGE_FLOAT )
+    return;
+  
+  if ( camera == NULL )
+    return;
+  
+  // Find the plane equation for the camera view plane
+  camera->GetViewPlaneNormal(vn);
+  camera->GetPosition(position);
+  a = -vn[0];
+  b = -vn[1];
+  c = -vn[2];
+  d = -(a*position[0] + b*position[1] + c*position[2]);
+
+  // Set the max near clipping plane and the min far clipping plane
+  range[0] = a*nbounds[0] + b*nbounds[2] + c*nbounds[4] + d;
+  range[1] = 1e-18;
+
+  // Find the closest / farthest bounding box vertex
+  for ( k = 0; k < 2; k++ )
+    {
+      for ( j = 0; j < 2; j++ )
+	{
+	  for ( i = 0; i < 2; i++ )
+	    {
+	      dist = a*nbounds[i] + b*nbounds[2+j] + c*nbounds[4+k] + d;
+	      range[0] = (dist<range[0])?(dist):(range[0]);
+	      range[1] = (dist>range[1])?(dist):(range[1]);
+	    }
+	}
+    }
+  
+  // Do not let the range behind the camera throw off the calculation.
+  if (range[0] < 0.0)
+    range[0] = 0.0;
+  
+  // Give ourselves a little breathing room
+  range[0] = 0.99*range[0] - (range[1] - range[0])*0.5;
+  range[1] = 1.01*range[1] + (range[1] - range[0])*0.5;
+  
+  // Make sure near is not bigger than far
+  range[0] = (range[0] >= range[1])?(0.01*range[1]):(range[0]);
+
+  // Make sure near is at least some fraction of far - this prevents near
+  // from being behind the camera or too close in front. How close is too
+  // close depends on the resolution of the depth buffer
+  int ZBufferDepth = 16;
+  if (this->renderer->GetRenderWindow())
+    ZBufferDepth = this->renderer->GetRenderWindow()->GetDepthBufferSize();
+
+  if ( ZBufferDepth <= 16 )
+    {
+      range[0] = (range[0] < 0.01*range[1])?(0.01*range[1]):(range[0]);
+    }
+  else if ( ZBufferDepth <= 24 )
+    {
+      range[0] = (range[0] < 0.01*range[1])?(0.01*range[1]):(range[0]);
+    }
+  else
+    {
+      range[0] = (range[0] < 0.01*range[1])?(0.01*range[1]):(range[0]);
+    }
+  
+  camera->SetClippingRange( range );
+
+
+  if (hasclipcontrols)
+    {
+      double r[2];
+      camera->GetClippingRange(r);
+      double t=fabs(r[1]-r[0]);
+      r[0]-=t;
+      if (r[0]<10.0)
+	r[0]=10.0;
+      r[1]=r[0]+2.0*t;
+      clip_min->setRange(r[0]-10.0,r[1]+100.0);
+      clip_min->setResolution(1.0);
+      clip_min->setValue(r[0]);
+      clip_thickness->setRange(1.0,1.5*(r[1]-r[0]));
+      if (clip_mode)
+	clip_thickness->setValue(this->clipping_thickness);
+      else
+	clip_thickness->setValue(r[1]-r[0]);	
+      clip_thickness->setResolution(1.0);
+      this->clipping_front=-1.0;
+    }
+
+
+  this->ResetClipScales();
+
+}
+
+
+void vtkpxGUIRenderer::CameraModifiedCallback()
+{
+  if (this->renderer!=NULL)
+    {
+      double r[2]; renderer->GetActiveCamera()->GetClippingRange(r);
+
+      if (this->clip_min!=NULL && this->clip_thickness!=NULL)
+	{
+	  
+	  clip_min->setValue(r[0]);
+	  //clip_min->setRange(r[0],r[1]);
+
+	  //	  clip_thickness->setRange(0.01,r[1]-r[0]);
+	  clip_thickness->setValue(r[1]-r[0]);
+	}
+      
+      if (this->CameraEventParent!=NULL && this->CameraCallbackNo>0)
+	{
+	  this->CameraEventParent->HandleEvent(CameraCallbackNo);
+	}
+    }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRendererInterpolateValues(double* a,double* b,double w1,double w2,double* c,int n)
+{
+  for (int ia=0;ia<n;ia++)
+    c[ia]=w1*a[ia]+w2*b[ia];
+}
+
+void vtkpxGUIRenderer::InterpolateCamera(vtkCamera* newCamera,vtkCamera* oldCamera,vtkCamera* oldCamera2,double weight)
+{
+  if (weight<0.0)
+    weight=0.0;
+  else if (weight>1.0)
+    weight=1.0;
+  
+  double w1=weight;
+  double w2=1.0-w1;
+
+  double x[3],y[3],z[3];
+  oldCamera->GetFocalPoint(x);   oldCamera2->GetFocalPoint(y);
+  vtkpxGUIRendererInterpolateValues(&x[0],&y[0],w1,w2,&z[0],3);
+  newCamera->SetFocalPoint(z);
+
+  oldCamera->GetPosition(x);   oldCamera2->GetPosition(y);
+  vtkpxGUIRendererInterpolateValues(&x[0],&y[0],w1,w2,&z[0],3);
+  newCamera->SetPosition(z);
+
+  oldCamera->GetViewUp(x);   oldCamera2->GetViewUp(y);
+  vtkpxGUIRendererInterpolateValues(&x[0],&y[0],w1,w2,&z[0],3);
+
+  // ***** 
+  newCamera->SetViewUp(z);
+  newCamera->ComputeViewPlaneNormal();
+
+  double x2[2],y2[2],z2[2];
+  oldCamera->GetClippingRange(x2);   oldCamera2->GetClippingRange(y2);
+  vtkpxGUIRendererInterpolateValues(&x2[0],&y2[0],w1,w2,&z2[0],3);
+  newCamera->SetClippingRange(z2);
+
+  newCamera->SetParallelProjection(oldCamera->GetParallelProjection());
+
+  
+  newCamera->SetParallelScale(w1*oldCamera->GetParallelScale()+w2*oldCamera2->GetParallelScale());
+
+}
+
+void vtkpxGUIRenderer::CopyCamera(vtkCamera* newCamera,vtkCamera* oldCamera)
+{
+  newCamera->SetFocalPoint(oldCamera->GetFocalPoint());
+  newCamera->SetPosition(oldCamera->GetPosition());
+  newCamera->SetViewUp(oldCamera->GetViewUp());
+  newCamera->ComputeViewPlaneNormal();
+  newCamera->SetClippingRange(oldCamera->GetClippingRange());
+  newCamera->SetParallelProjection(oldCamera->GetParallelProjection());
+  newCamera->SetParallelScale(oldCamera->GetParallelScale());
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::RendererEvent()
+{
+  if (this->EnableActorTransform==0)
+    return;
+
+
+  vtkPropCollection* collection[3];
+  collection[0]=this->renderer->GetActors();
+  collection[1]=this->renderer->GetVolumes();
+  collection[2]=this->renderer->GetViewProps();
+
+  vtkLinearTransform* newt=this->ActorTransform;
+
+  for (int c=0;c<=2;c++)
+    {
+      collection[c]->InitTraversal();
+      for (int j=0;j<collection[c]->GetNumberOfItems();j++)
+	{
+	  vtkProp* prop0=collection[c]->GetNextProp();
+	  if (prop0->IsA("vtkProp3D")==1)
+	    {
+	      vtkProp3D* prop=(vtkProp3D*)prop0;
+	      vtkLinearTransform* current_t=prop->GetUserTransform();
+	      if (newt!=current_t)
+		{
+		  prop->SetUserTransform(newt);
+		  prop->Modified();
+		  //		  fprintf(stderr,"Modifying c=%d j=%d %s\n",c,j,prop0->GetClassName());
+		}
+	    }
+	}
+    }
+  this->renderer->SetTwoSidedLighting(1);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUIRenderer::SetCurrentImageOrientation(vtkImageData* img,int new_orientation,int doupdate)
+{
+  if (new_orientation!=-1)
+    this->SetOrientation(new_orientation,doupdate);
+  
+  this->SetCurrentImage(img);
+  
+  if (this->EnableActorTransform==0)
+    return;
+ 
+
+  // Temporary bypass option
+  this->EnableActorTransform=0;
+  return;
+
+  // Fix this at some point
+  /*  if (this->orientation!=2)
+    {
+      if (this->ActorTransform!=NULL)
+	this->ActorTransform->Delete();
+      this->ActorTransform=NULL;
+      return;
+    }
+     
+  if (this->ActorTransform==NULL)
+    this->ActorTransform=vtkTransform::New();
+
+  this->ActorTransform->Identity();
+  this->ActorTransform->PostMultiply();
+  this->ActorTransform->Scale(1.0,1.0,-1.0);
+
+  if (this->GetCurrentImage()!=NULL)
+    {
+      vtkImageData* n_image=this->GetCurrentImage();
+      double sp[3];  n_image->GetSpacing(sp);
+      double ori[3]; n_image->GetOrigin(ori);
+      int    dim[3]; n_image->GetDimensions(dim);
+      double shift_z=sp[2]*double(dim[2]-1)+ori[2];
+
+      this->ActorTransform->Translate(0.0,0.0,shift_z);
+    }
+
+  fprintf(stderr,"Marix = \n");
+  vtkMatrix4x4* matrix=this->ActorTransform->GetMatrix();
+	  
+  for(int i=0;i<=3;i++)
+    {
+      for (int j=0;j<=3;j++)
+	fprintf(stderr,"%7.3f ",matrix->GetElement(i,j));
+      fprintf(stderr,"\n");
+    }
+  */
+
+
+}
+
+int  vtkpxGUIRenderer::GetClipScaleValue(int i)
+{
+  if (i<0 || i >5  || this->enableClip==NULL)
+    return -1;
+
+  return (int) clip_planes[i]->getValue();
+
+}
+
+void vtkpxGUIRenderer::SetClipScaleValue(int i,int v)
+{
+  if (i<0 || i >5)
+    return;
+
+  if (this->enableClip==NULL)
+    return;
+
+  if (v==-1)
+    {
+      if ( i==0 || i==2 || i ==4 )
+	{
+	  v=int(clip_planes[i]->getmin());
+	} 
+      else 
+	{
+	  v=int(clip_planes[i]->getmax());
+	}
+    }
+  clip_planes[i]->setValue(float(v));
+}
+
+void vtkpxGUIRenderer::ResetClipScales()
+{
+  if (this->enableClip!=NULL)
+    {
+      for (int ia=0;ia<=2;ia++)
+	{
+	  int x1=ia*2;
+	  int x2=ia*2+1;
+	  
+	  for (int ib=0;ib<=1;ib++)
+	    {
+	      int index=ia*2+ib;
+	      clip_planes[index]->setRange(bounds[x1]-10.0,bounds[x2]+10.0);
+	      if (ib==0)
+		clip_planes[index]->setValue(clip_planes[index]->getmin());
+	      else
+		clip_planes[index]->setValue(clip_planes[index]->getmax());
+	    }
+	}
+      this->UpdateClippingPlanes();
+    }
+}
+
+void vtkpxGUIRenderer::SetPolygonalClipping(int mode)
+{
+  if (this->enableClip==NULL)
+    return;
+
+  if (mode==-1)
+    {
+      if (this->enableClip->getState()==PXTrue)
+	mode=1;
+      else
+	mode=0;
+    }
+  mode=(mode>0);
+  if (mode>0)
+    this->enableClip->setState(PXTrue);
+  else
+    this->enableClip->setState(PXFalse);
+
+  //  fprintf(stderr,"Set Polygonal Clipping mode=%d\n",mode);
+
+  vtkPropCollection* propC=renderer->GetViewProps();
+  if (propC==NULL)
+    return;
+  propC->InitTraversal();
+
+  for (int j=0;j<propC->GetNumberOfItems();j++)
+    {
+      vtkProp* prop=propC->GetNextProp();
+      if (prop!=NULL)
+	{
+	  if (prop->IsA("vtkActor"))
+	    {
+	      //	      fprintf(stderr,"Item %d type=%s\n",j,prop->GetClassName());
+	      vtkMapper *mapper=((vtkActor*)prop)->GetMapper();
+	      if (mapper!=NULL)
+		{
+		  mapper->RemoveAllClippingPlanes();
+		  if (mode==1)
+		    {
+		      for (int ia=0;ia<=5;ia++)
+			mapper->AddClippingPlane(this->ClippingPlanes[ia]);
+		    }
+		  prop->Modified();
+		  mapper->Modified();
+		}
+	    }
+	}
+    }
+}
+
+void vtkpxGUIRenderer::UpdateClippingPlanes()
+{
+  if (this->enableClip==NULL)
+    return;
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      for (int ib=0;ib<=1;ib++)
+	{
+	  int index=2*ia+ib;
+	  this->ClippingPlanes[index]=vtkPlane::New();
+	  double p[3]= { 0.0,0.0,0.0};
+	  double n[3]= { 0.0,0.0,0.0};
+	  if (ib==1)
+	    n[ia]=-1.0;
+	  else
+	    n[ia]=1.0;
+
+	  if (this->enableClip!=NULL)
+	    p[ia]=clip_planes[index]->getValue();
+
+	  //	  this->ClippingPlanes[index]->DebugOn();
+	  this->ClippingPlanes[index]->SetOrigin(p);
+	  this->ClippingPlanes[index]->SetNormal(n);
+	  //	  this->ClippingPlanes[index]->DebugOff();
+	}
+    }
+
+  if (this->enableClip->getState()!=PXTrue)
+    return;
+
+  this->SetPolygonalClipping(1);
+}
+
+/* ------------------------------------------------------------------------------------*/
+//                     Sagittal/Axial/Coronal -- original image orientations tranposed
+//
+//
+//      This implies that the x and y axis are tranposed
+//
+/* ------------------------------------------------------------------------------------*/
+
+void vtkpxGUIRenderer::moveAboveTransposedAxial(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis)
+{
+
+  // If image-orientation is axial then
+  // axis = 0 YZ --> Sagittal
+  // axis = 1 XZ --> Coronal
+  // axis = 2 XY --> Axial
+
+  // suborientation is now a number between 0 and 7
+  int suborientation=vtkpxGUIBaseImageViewer::MapOrientationToNewStyle(this->orientation)-40;
+
+  int wrongx=(suborientation & 1);
+  int wrongy=(suborientation & 2);
+  int wrongz=(suborientation & 4);
+
+  /*  wrongx=0;
+  wrongy=0;
+  wrongz=0;*/
+
+  //  fprintf(stderr,"transp axial orientation=%d suborientation=%d axis=%d, flip=%d\n\t\twrongx=%d, wrongy=%d, wrongz=%d\n",this->orientation,suborientation,axis,flip,
+  //  wrongx,wrongy,wrongz);
+  
+  // First pass to handle flips ....
+  // 
+  if (wrongx>0)
+    {
+      if (axis== 4 || axis == 1)
+	{
+	  axis=axis+3;
+	  if (axis>5)
+	    axis=axis-6;
+	}
+      if (axis==2 || axis==5)
+	flip=1-(flip>0);
+    }
+
+  if (wrongy>0)
+    {
+      if (axis==2 || axis==5 || axis==0 || axis==3)
+	{
+	  axis=axis+3;
+	  if (axis>5) 
+	    axis=axis-6;
+	}
+    }
+  if (wrongz>0 && (axis==0 || axis==1 || axis==3 || axis==4))
+    {
+      flip=1-(flip>0);
+    }
+  //  fprintf(stderr,"\t\t flip=%d axis=%d\n\n\n\n",flip,axis);
+  //  fflush(stderr);
+
+  camera->SetFocalPoint(midx,midy,midz);
+
+  switch (axis)
+    {
+
+    case 5: // Axial -- flip LR --- DONE -----------
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy,midz-distance);
+	  camera->SetViewUp(-1,0,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy,midz+distance);
+	  camera->SetViewUp(1,0,0);
+	}
+      break;
+
+    case 4: // Sagittal -- flip LR -- DONE --------
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy+distance,midz);
+	  camera->SetViewUp(0,0,1);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy-distance,midz);
+	  camera->SetViewUp(0,0,-1);
+	}
+      break;
+
+    case 3: // Coronal -- flip AP  -- DONE --------
+      if (!flip)
+	{
+	  camera->SetPosition(midx-distance,midy,midz);
+	  camera->SetViewUp(0,0,1);
+	}
+      else
+	{
+	  camera->SetPosition(midx+distance,midy,midz);
+	  camera->SetViewUp(0,0,-1);
+	}
+
+      break;
+
+    case 2: // Axial  -- DONE -------------
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy,midz+distance);
+	  camera->SetViewUp(-1,0,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy,midz-distance);
+	  camera->SetViewUp(1,0,0);
+	}
+
+      break;
+
+    case 1: // Sagittal  -- DONE --------
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy-distance,midz);
+	  camera->SetViewUp(0,0,1);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy+distance,midz);
+	  camera->SetViewUp(0,0,-1);
+	}
+      break;
+      
+    case 0: // Coronal  -- DONE --------
+      if (!flip)
+	{
+	  camera->SetPosition(midx+distance,midy,midz);
+	  camera->SetViewUp(0,0,1);
+	}
+      else
+	{
+	  camera->SetPosition(midx-distance,midy,midz);
+	  camera->SetViewUp(0,0,-1);
+	}
+      break;
+
+    }
+
+  camera->ComputeViewPlaneNormal();
+
+}
+
+/* -------------------------------------------------------------------------*/
+
+void vtkpxGUIRenderer::moveAboveTransposedCoronal(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis)
+{
+  // If image-orientation is axial then
+  // axis = 0 YZ --> Sagittal
+  // axis = 1 XZ --> Axial
+  // axis = 2 XY --> Coronal
+
+  // suborientation is now a number between 0 and 7
+  int suborientation=vtkpxGUIBaseImageViewer::MapOrientationToNewStyle(this->orientation)-50;
+
+  int wrongx=(suborientation & 1);
+  int wrongy=(suborientation & 2);
+  int wrongz=(suborientation & 4);
+
+  //  fprintf(stderr,"transp coronal orientation=%d suborientation=%d wrongx=%d, wrongy=%d, wrongz=%d flip=%d axis=%d\n",this->orientation,suborientation,
+  //	  wrongx,wrongy,wrongz,flip,axis);
+
+  
+  // First pass to handle flips ....
+  // Affects Axial + Coronal
+  if (wrongx>0 && (axis==5 || axis==2 || axis== 4 || axis == 1))
+    {
+      flip=1-(flip>0);
+    }
+
+  // Affects Axial + Sagital
+  if (wrongz>0) 
+    {
+      if (axis==0 || axis==3 )
+	{
+	  flip=1-(flip>0);
+	}
+      else if (axis==1 || axis==4)
+	{
+	  axis+=3;
+	  if (axis>5)
+	    axis=axis-6;
+	}
+    }
+
+  if (wrongy>0 && (axis==0 || axis==2 || axis==3 || axis==5))
+    {
+      axis+=3;
+      if (axis>5)
+	axis=axis-6;
+    }
+
+  //  fprintf(stderr,"\t\t flip=%d axis=%d\n\n\n\n",flip,axis);
+  //  fflush(stderr);
+
+
+  camera->SetFocalPoint(midx,midy,midz);
+
+  switch (axis)
+    {
+    case 5: // Coronal Reverse -------------- DONE --------
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy,midz-distance);
+	  camera->SetViewUp(-1,0,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy,midz+distance);
+	  camera->SetViewUp(1,0,0);
+	}
+      break;
+
+    case 4: // Sagittal Reverse ------------ DONE ---------
+      
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy+distance,midz);
+	  camera->SetViewUp(-1,0,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy-distance,midz);
+	  camera->SetViewUp(1,0,0);
+	}
+      break;
+
+      
+    case 3: // Axial Reverse ------------- DONE ----------
+       
+      if (!flip)
+	{
+	  camera->SetPosition(midx+distance,midy,midz);
+	  camera->SetViewUp(0,0,-1);
+	}
+      else
+	{
+	  camera->SetPosition(midx-distance,midy,midz);
+	  camera->SetViewUp(0,0,1);
+	}
+      break;
+
+    case 2: // Coronal ---------------- DONE -----------
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy,midz+distance);
+	  camera->SetViewUp(-1,0,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy,midz-distance);
+	  camera->SetViewUp(1,0,0);
+	}
+      break;
+
+    case 1: // Sagittal -------------- DONE -----------
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy-distance,midz);
+	  camera->SetViewUp(-1,0,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy+distance,midz);
+	  camera->SetViewUp(1,0,0);
+	}
+      break;
+      
+    case 0: // Axial ------------- DONE ----------
+      if (!flip)
+	{
+	  camera->SetPosition(midx-distance,midy,midz);
+	  camera->SetViewUp(0,0,-1);
+	}
+      else
+	{
+	  camera->SetPosition(midx+distance,midy,midz);
+	  camera->SetViewUp(0,0,1);
+	}
+      break;
+    }
+  camera->ComputeViewPlaneNormal();
+}
+
+// ----------------------------------------------------------------------------------------------------------------------------------------
+void vtkpxGUIRenderer::moveAboveTransposedSagittal(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis)
+{
+  // If image-orientation is sagittal then
+  // axis = 2 XY --> Sagittal
+  // axis = 1 XZ --> Coronal
+  // axis = 0 YZ --> Axial
+  // suborientation is now a number between 0 and 7
+  int suborientation=vtkpxGUIBaseImageViewer::MapOrientationToNewStyle(this->orientation)-60;
+
+  int wrongx=(suborientation & 1);
+  int wrongy=(suborientation & 2);
+  int wrongz=(suborientation & 4);
+
+
+  //  fprintf(stderr,"trans sag orientation=%d suborientation=%d wrongx=%d, wrongy=%d, wrongz=%d flip=%d axis=%d\n",this->orientation,suborientation,
+  //  	  wrongx,wrongy,wrongz,flip,axis);
+
+  
+  // First pass to handle flips ....
+  if (wrongz>0 && (axis==0 || axis==1 || axis== 3 || axis == 4))
+    {
+      axis=axis+3;
+      if (axis>5)
+	axis=axis-6;
+    }
+
+  if (wrongx>0) 
+    {
+      if (axis==2 || axis==5)
+	{
+	  flip=1-(flip>0);
+	}
+      else if (axis==1 || axis==4)
+	{
+	  flip=1-(flip>0);
+	}
+    }
+
+  if (wrongy>0 )
+    {
+      if ((axis==0 || axis==3))
+	{
+	  flip=1-(flip>0);
+	}
+      else if (axis==2 || axis==5)
+	{
+	  axis=axis+3;
+	  if (axis>5)
+	    axis=axis-6;
+	}
+    }
+  
+  //  fprintf(stderr,"\t\t flip=%d axis=%d\n\n\n\n",flip,axis);
+  //  fflush(stderr);
+
+
+  camera->SetFocalPoint(midx,midy,midz);
+  switch(axis)
+    {
+    case 5: // Reverse Sagittal ---------- DONE -------
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy,midz+distance);
+	  camera->SetViewUp(1,0,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy,midz-distance);
+	  camera->SetViewUp(-1,0,0);
+	}
+      break;
+
+
+    case 4: // Reverse Coronal - ----- DONE -------
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy+distance,midz);
+	  camera->SetViewUp(1,0,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy-distance,midz);
+	  camera->SetViewUp(-1,0,0);
+	}
+      break;
+      
+    case 3: // Reverse Axial -------- DONE ---------
+      if (!flip)
+	{
+	  camera->SetPosition(midx+distance,midy,midz);
+	  camera->SetViewUp(0,-1,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx-distance,midy,midz);
+	  camera->SetViewUp(0,1,0);
+	}
+      break;
+
+    case 2: // Sagittal ----------- DONE ----------
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy,midz-distance);
+	  camera->SetViewUp(1,0,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy,midz+distance);
+	  camera->SetViewUp(-1,0,0);
+	}
+      break;
+
+    case 1: // Coronal -------------- DONE ----------
+      if (!flip)
+	{
+	  camera->SetPosition(midx,midy-distance,midz);
+	  camera->SetViewUp(1,0,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx,midy+distance,midz);
+	  camera->SetViewUp(-1,0,0);
+	}
+      break;
+      
+    case 0: // Axial -------------- DONE -----------
+      if (!flip)
+	{
+	  camera->SetPosition(midx-distance,midy,midz);
+	  camera->SetViewUp(0,-1,0);
+	}
+      else
+	{
+	  camera->SetPosition(midx+distance,midy,midz);
+	  camera->SetViewUp(0,1,0);
+	}
+
+      break;
+    }
+  camera->ComputeViewPlaneNormal();
+}
+// ----------------------------------------------------------------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIRenderer.h b/bioimagesuite30_src/GUI/vtkpxGUIRenderer.h
new file mode 100644
index 0000000..902218e
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIRenderer.h
@@ -0,0 +1,284 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkpxGUIRenderer - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkpxGUIRenderer_h
+#define __vtkpxGUIRenderer_h
+
+#include "vtkpxGUIBaseRenderer.h"
+#include "pxtkbutton.h"
+#include "pxtkoptionmenu.h"
+#include "pxtkscale.h"
+#include "pxtkcheckbutton.h"
+#include "vtkCamera.h"
+#include "vtkImageData.h"
+#include "vtkRenderWindow.h"
+#include "vtkLight.h"
+#include "vtkProperty2D.h"
+#include "pxtkcomplexwidgets.h"
+#include "vtkpxCameraInfo.h"
+#include "vtkPlane.h"
+
+//BTX
+class PXITkComboBox;
+class vtkpxGUIRendererCallback;
+class vtkTransform;
+//ETX
+
+class  vtkpxGUIRenderer : public vtkpxGUIBaseRenderer
+{
+public:
+  static vtkpxGUIRenderer *New();
+  vtkTypeMacro(vtkpxGUIRenderer,vtkpxGUIBaseRenderer);
+  
+  virtual char* Initialize(const char* widgetname,vtkRenderer*, int inside);
+  virtual vtkRenderer* GetRenderer();
+
+
+  // Description:
+  // Bounds related
+  virtual void   SetBounds(double bd[6]);
+  virtual void   SetBounds(vtkDataSet* dataset);
+  virtual void   GetBounds(double bd[6]);
+  virtual void   SetClipBounds(double x,double y,double z);
+  virtual void   SetClipBounds(int x,int y,int z,double sp[3],double ori[3]);
+
+  // Description:
+  // Rendering
+  virtual void   SetViewport(double x0,double y0,double x1,double y1);
+  virtual int    InViewport(int mousex,int mousey);
+  virtual void   Render();
+  virtual void   RenderDelay(int a=-1);
+  virtual void   SetUpdateRate(double interactiverate=15.0,double staticrate=0.1);
+  virtual void   Zoom(double scale=1.0,PXBool dorender=PXTrue);
+  virtual void   Rotate(double angle=5.0,int doazimuth=1);
+  virtual void   Rotate(double angle,int doazimuth,PXBool dorender);
+  virtual void   MoveAbove(int axis=-1);
+  virtual void   Clip(int axis=-1);
+  virtual void   View(int axis=-1);
+  virtual void   Reset();
+  virtual int    SaveAsTIFF(const char* fname,PXBool wholewindow=PXFalse);  
+
+
+
+  // Description:
+  // Event Handling
+  virtual int    HandleEvent(int event);
+  virtual int    HandleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* ev);
+  virtual int    Get2DClickedPoint(double& px,double& py,int mousex,int mousey,int orient=-1);
+
+  // Description:
+  // Access Internal Stuff
+  virtual int    GetFlipMode();
+  virtual int    GetPlaneMode();
+  virtual void   SetFlipMode(int mode=0);
+  virtual void   SetOrientation(int orient=0,int doupdate=1);
+  virtual int    GetOrientation();
+
+  virtual void   SetClipMode(PXBool mode=PXTrue);
+  virtual void   SetPlaneMode(int plane=2);
+  virtual void   SetAutoZoom(double autoz=1.0);
+
+  // Description:
+  // Enable Actor Transform --> flip left/right in Sagital Images for Volume Rendering etc
+  vtkSetMacro(EnableActorTransform,int);
+  vtkGetMacro(EnableActorTransform,int);
+
+
+  // Description:
+  // Reset Camera Stuff 
+  virtual void ResetCamera(double bounds[6]);
+  virtual void ResetCamera();
+
+  // Description:
+  // Reset Camera Clipping Range
+  virtual void ResetCameraClippingRange(double bounds[6]);
+  virtual void ResetCameraClippingRange();
+
+  // Description:
+  // Callback On Camera Modified
+  virtual void CameraModifiedCallback();
+
+  // Description:
+  // Camera Modified Callback
+  virtual void   SetCameraCallback(vtkpxGUIComponent* comp,int callno);
+  virtual void   SetCameraCallback(const char* CallbackName);
+
+  // Description:
+  // Copy Camera Attributes
+  static void CopyCamera(vtkCamera* newCamera,vtkCamera* oldCamera);
+  static void InterpolateCamera(vtkCamera* newCamera,vtkCamera* oldCamera,vtkCamera* oldCamera2,double weight);
+
+  // Description:
+  // More Camera Stuff
+  virtual double  GetCameraScale();
+  virtual double  GetCameraWidth();
+  virtual void   SetCameraScale(double autoz=1.0);
+  virtual void   SetCameraScale(vtkpxGUIRenderer* ren);
+  virtual double  GetClipFront();
+  virtual double  GetClipThickness();
+  virtual void   SetClipFront(double fr=-1.0);
+  virtual void   SetClipThickness(double thick);
+
+  // Description:
+  // Label Stuff
+  virtual void   SetLabel(const char* text,double x,double y,double c1=1.0,double c2=0.0,double c3=0.0);
+  virtual void   HideLabel();
+  virtual void   ShowLabel();
+
+
+  // Description:
+  // GUI 
+  virtual void   SetVerticalDecoration(PXBool dec);
+  virtual void   SetNoGUI(PXBool gui=PXTrue);
+
+  // Description:
+  // Set Polar Angle coordinates in case of polar images 
+  virtual void   SetViewerCoordinates(int x,int y,int z)
+  { this->ViewerCoordinates[0]=x; this->ViewerCoordinates[1]=y; this->ViewerCoordinates[2]=z; }
+
+  // Description:
+  // Renderer Event --- the renderer may invoke this prior to rendering
+  virtual void RendererEvent();
+  
+  // Description:
+  // Set/Get Current Image
+  virtual void SetCurrentImageOrientation(vtkImageData* img,int orientation=-1,int doupdate=1);
+  vtkGetObjectMacro(CurrentImage, vtkImageData);
+
+  // Description:
+  // Clip Stuff
+  virtual int  GetClipScaleValue(int i);
+  virtual void SetClipScaleValue(int i,int v);
+  virtual void ResetClipScales();
+  virtual void SetPolygonalClipping(int mode);
+  virtual void UpdateClippingPlanes();
+
+
+  // Description:
+  // Hide PolyClip Controls
+  vtkSetClampMacro(NoPolyClipControls,int,0,1);
+  vtkGetMacro(NoPolyClipControls,int);
+
+
+  // Description:
+  // Show Camera Controls
+  virtual int ShowCameraControls();
+
+
+protected:
+
+  vtkpxGUIRenderer();
+  virtual        ~vtkpxGUIRenderer();
+  
+  // Hide this one so that no-one can access it
+  virtual char* Initialize(const char* widgetname,int inside) {return NULL;}
+  static void   HandleRenderEvent(void *arg1);
+
+  vtkRenderer*       renderer;
+  vtkActor2D*        textActor;
+  vtkLight*          main_light;
+
+  virtual void moveAbovePolar(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis);
+
+  virtual void moveAboveSagittal(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis);
+  virtual void moveAboveAxial(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis);
+  virtual void moveAboveCoronal(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis);
+
+  virtual void moveAboveTransposedSagittal(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis);
+  virtual void moveAboveTransposedAxial(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis);
+  virtual void moveAboveTransposedCoronal(double midx,double midy,double midz,double distance,vtkCamera* camera,int flip,int axis);
+
+  // Description:
+  // Handle Mouse Events --from TkInteractor.tcl
+  // -------------------------------------------
+  virtual int MouseEventRotate(int state,int x1,int x2);
+  virtual int MouseEventPan(int state,int x1,int x2);
+  virtual int MouseEventZoom(int state,int x1,int x2);
+
+  int                EnableActorTransform;
+  int                flip_mode;
+  PXBool	     clip_mode;
+  PXBool	     vertical_decoration;
+  PXBool	     no_gui;
+  int                plane_mode;
+  int		     last_axis;
+  PXTkButton*        plane_button;
+  PXTkButton*	     mode_button;
+  PXTkOptionMenu*    mode_menu;
+  PXTkOptionMenu*    angle_menu;
+
+  PXITkComboBox*     plane_menu;
+  PXTkButton*        update_plane;
+  //  PXTkOptionMenu*    plane_menu;
+  PXTkArrowScale     *clip_min;
+  PXTkArrowScale     *clip_thickness;
+
+  int                NoPolyClipControls;
+  PXTkArrowScale     *clip_planes[6];
+  PXTkCheckButton    *enableClip;
+
+  int                hasclipcontrols;
+		  
+  int                orientation;
+  double              clipping_thickness;
+  double              clipping_front;
+  double              bounds[6];
+  double              clipBounds[3];
+  double              update_rate[2];
+  double              camera_scale;
+  double              auto_zoom;
+
+
+  vtkImageData*      CurrentImage;
+  int                ViewerCoordinates[3];
+
+  // Callback Stuff
+  int                CameraCallbackNo;
+  char*              CameraCallbackName;
+  vtkpxGUIComponent* CameraEventParent;	  
+
+  // Camera Info
+  vtkpxCameraInfo*          CameraPresets;
+  vtkpxGUIRendererCallback* RendererCallback;
+  vtkTransform*             ActorTransform;
+  vtkPlane*                 ClippingPlanes[6];
+
+  // Description:
+  // Set Current Image Stuff 
+  vtkSetObjectMacro(CurrentImage, vtkImageData);
+
+
+  
+};
+#endif
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUISplineControl.cpp b/bioimagesuite30_src/GUI/vtkpxGUISplineControl.cpp
new file mode 100644
index 0000000..fcb8e9b
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUISplineControl.cpp
@@ -0,0 +1,1616 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// 	$Id: vtkpxGUISplineControl.cpp,v 1.2 2003/09/11 13:34:39 xenios Exp xenios $	
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkpxGUISplineControl.h"
+#include "vtkpxUtil.h"
+#include "vtkActor.h"
+#include "vtkAssembly.h"
+#include "vtkRenderer.h"
+#include "vtkRenderWindow.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxImageExtract.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkImageData.h"
+#include "vtkProperty.h"
+#include "vtkPoints.h"
+#include "pxfpbsplinestack.h"
+/* -------------------------------------------------------------------------*/
+vtkpxGUISplineControl* vtkpxGUISplineControl::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUISplineControl");
+  if(ret)
+      {
+	return (vtkpxGUISplineControl*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUISplineControl;
+}
+
+// ----------------------------------------------------------------------------
+vtkpxGUISplineControl::vtkpxGUISplineControl()
+{
+  this->NumberOfSplines=50;
+  this->clipboardSpline=NULL;
+  this->undoSpline=NULL;
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->origin[ia]=0.0;
+      this->spacing[ia]=1.0;
+      this->dimensions[ia]=100;
+    }
+
+
+  this->DefaultScaleMode=4;
+  
+  for (int i=0;i<this->NumberOfSplines;i++)
+    {
+      splineSet[i]=NULL;
+      splineActor[i]=NULL;
+      if (i<2)
+	display_mode[i]=PXTrue;
+      else
+	display_mode[i]=PXFalse;
+      spline_enabled[i]=1;
+      for (int j=0;j<=2;j++)
+	{
+	  ghostSet[j][i]=NULL;
+	  ghostActor[j][i]=NULL;
+	}
+      this->changed[i]=0;
+      scale_mode[i]=this->DefaultScaleMode;
+    }
+  ghostMode=NULL;
+  editCurve=NULL;
+  manualEditCurve=NULL;
+  extractGUI=NULL;
+
+  editActor=NULL;
+  manualEditActor=NULL;
+  this->Renderer=NULL;
+  current_spline=0;
+  currentSpline=NULL;
+  snakeGUI=NULL;
+  image=NULL;
+  image_level=0;
+  image_frame=0;
+  slice_offset=-0.02;
+  ghost_displaymode=0;
+  autoUpdate=NULL;
+  AutoUpdateMode=1;
+  
+  this->SlaveMode=0;
+  this->DistanceThreshold=1.0;
+  this->ControlPointScaleFactor=1.0;
+  this->manual_add_mode=0;
+  this->manual_zcoord=0.0;
+  this->DefaultSmoothing=1.0;
+
+  char* line=PXTkApp::getTclVariable("pxtcl_pref_array(SplineSmoothing)");
+  if (line!=NULL)
+      this->DefaultSmoothing=Frange(atof(line),0.0001,10.0);
+
+  this->ShowGhostControls=1;
+}
+// ----------------------------------------------------------------------------
+vtkpxGUISplineControl::~vtkpxGUISplineControl()
+{
+  
+  if (clipboardSpline!=NULL)
+    clipboardSpline->Delete();
+  
+  if (undoSpline!=NULL)
+    undoSpline->Delete();
+
+  if (editCurve!=NULL)
+    editCurve->Delete();
+  if (editActor!=NULL)
+    editActor->Delete();
+
+  if (manualEditCurve!=NULL)
+    manualEditCurve->Delete();
+  if (manualEditActor!=NULL)
+    manualEditActor->Delete();
+
+
+  for (int i=0;i<this->NumberOfSplines;i++)
+    {
+      if (splineSet[i]!=NULL)
+	splineSet[i]->Delete();
+      if (splineActor[i]!=NULL)
+	splineActor[i]->Delete();
+      for (int j=0;j<2;j++)
+	{
+	  if (ghostActor[j][i]!=NULL)
+	    ghostActor[j][i]->Delete();
+	  if (ghostSet[j][i]!=NULL)
+	    ghostSet[j][i]->Delete();
+	}
+    }
+    
+  if (this->image!=NULL)
+    this->image->Delete();
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::SetNumberOfSplines(int a)
+{
+  if (this->Initialized==1)
+    return;
+  
+  this->NumberOfSplines=Irange(a,1,SP_MAX_COLLECTIONS);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::InitializeSplines()
+{
+  for (int i=0;i<this->NumberOfSplines;i++)
+    {
+      splineSet[i]=vtkpxSplineSource::New();
+      splineSet[i]->SetResolution(0.01);
+      splineSet[i]->SetEllipse(8,
+			       spacing[0]*dimensions[0]/8.0*(1.0+i),
+			       spacing[1]*dimensions[1]/8.0*(1.0+i),
+			       origin[0]+spacing[0]*dimensions[0]/2.0,
+			       origin[1]+spacing[1]*dimensions[1]/2.0,
+			       0.0,2);
+      for (int j=0;j<2;j++)
+	{
+	  splineSet[i]->SetResolution(0.03);
+	  ghostSet[j][i]=vtkpxSplineSource::New();;
+	  ghostSet[j][i]->Copy(splineSet[i]);
+	}
+      scale_mode[i]=this->DefaultScaleMode;
+    }
+
+
+
+  editCurve=vtkpxBaseCurve::New();
+  editCurve->SetShowCurve(0);
+  editCurve->SetShowControls(1);
+  editCurve->SetControlsDisplayModeToDisc();
+  editCurve->SetPointScale(1.0);
+  editCurve->SetOrigin(this->origin);
+  editCurve->SetSpacing(this->spacing);
+  
+
+  manualEditCurve=vtkpxBaseCurve::New();
+  manualEditCurve->SetShowControls(1);
+  manualEditCurve->SetShowCurve(1);
+  manualEditCurve->SetControlsDisplayModeToDisc();
+  manualEditCurve->SetPointScale(1.0);
+  manualEditCurve->SetOrigin(this->origin);
+  manualEditCurve->SetSpacing(this->spacing);
+  
+
+  splineSet[0]->ExportToBaseCurve(editCurve);
+  splineSet[0]->ExportToBaseCurve(manualEditCurve);
+  current_spline=0;
+  currentSpline=splineSet[current_spline];
+
+  clipboardSpline=vtkpxSplineSource::New();
+  clipboardSpline->Copy(currentSpline);
+
+  undoSpline=vtkpxSplineSource::New();
+  undoSpline->Copy(currentSpline);
+
+}
+/* -------------------------------------------------------------------------*/
+char* vtkpxGUISplineControl::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+
+  InitializeSplines();
+
+  vtkpxGUIComponent::Initialize(name,inside);
+  PXTkFrame* mFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+  PXTkLabelFrame* landmarkFrame=new PXTkLabelFrame(this->EventManager,mFrame,"Spline Control");
+  mFrame->addChildren("-side top -expand t -fill both -padx 4 -pady 4 ",landmarkFrame);
+
+  // Control Properties
+  // ---------------------
+  PXTkLabelFrame* vFrame=new PXTkLabelFrame(this->EventManager,landmarkFrame,"Global Properties");
+  landmarkFrame->addChildren("-side top -expand false -fill x -padx 5 -pady 5",vFrame);
+  vFrame->setPackMode(PXFalse);
+ 
+  mouseMode=new PXTkCheckButton(this->EventManager,vFrame,"Edit Mode",-1);
+  mouseMode->setState(PXTrue);
+  vFrame->gridRowColumnChild(mouseMode,0,0);
+
+
+  editMode=new PXTkCheckButton(this->EventManager,vFrame,"Manual Mode",510);
+  editMode->setState(PXFalse);
+  vFrame->gridRowColumnChild(editMode,0,1);
+
+  ExtractButton=new PXTkButton(this->EventManager,vFrame,"Extr",606);
+  ExtractButton->enable(PXFalse);
+  vFrame->gridRowColumnChild(ExtractButton,0,2);
+  
+
+  showControls=new PXTkCheckButton(this->EventManager,vFrame,"Controls",502);
+  showControls->setState(PXTrue);
+  vFrame->gridRowColumnChild(showControls,1,0,1,2);
+
+  PXTkButton* b0=new PXTkButton(this->EventManager,vFrame,"(-)",504);
+  b0->configure("-padx",1);
+  vFrame->gridRowColumnChild(b0,1,2);
+
+  if (this->ShowGhostControls)
+    {
+      PXTkLabel* lab1=new PXTkLabel(this->EventManager,vFrame,"Ghost Display:");
+      ghostMode=new PXTkOptionMenu(this->EventManager,vFrame,"Hide All",507);
+      ghostMode->addOption("Prev Only");
+      ghostMode->addOption("Next Only");
+      ghostMode->addOption("Show Both");
+      ghostMode->setIndex(ghost_displaymode);
+      
+      vFrame->gridRowColumnChild(lab1,2,0);
+      vFrame->gridRowColumnChild(ghostMode,2,1);
+    }
+  
+  PXTkButton* b0a=new PXTkButton(this->EventManager,vFrame,"Show All",506);
+  PXTkButton* b0b=new PXTkButton(this->EventManager,vFrame,"Hide All",505);
+  PXTkLabel* lab=new PXTkLabel(this->EventManager,vFrame,"");
+  lab->configure("-image","$::pxtclvtkpxcontrib::smalllogo ");
+  vFrame->gridRowColumnChild(lab,4,0,1,2);
+  vFrame->gridRowColumnChild(b0a,3,0);
+  vFrame->gridRowColumnChild(b0b,3,1);
+  
+  // Collection Properties 
+  // ---------------------
+  PXTkLabelFrame* pFrame=new PXTkLabelFrame(this->EventManager,landmarkFrame,"Spline Properties");
+  landmarkFrame->addChildren("-side top -expand true -fill both -padx 2 -pady 2",pFrame);
+  pFrame->setPackMode(PXFalse);
+
+  PXTkLabel* labs=new PXTkLabel(this->EventManager,pFrame,"Current Spline:");
+  currentCollection=new PXTkOptionMenu(this->EventManager,pFrame,"Spline 1",500);
+  for (int i=1;i<this->NumberOfSplines;i++)
+    {
+      sprintf(pxtk_buffer4,"Spline %d",i+1);
+      currentCollection->addOption(pxtk_buffer4);
+    }
+  currentCollection->setIndex(current_spline);
+  pFrame->gridRowColumnChild(labs,0,0,1,2);
+  pFrame->gridRowColumnChild(currentCollection,0,2);
+
+
+  
+  message=new PXTkLabel(this->EventManager,pFrame,"Num");
+  pFrame->gridRowColumnChild(message,1,0,1,3);
+  message->configure("-relief","ridge");
+
+  displayMode=new PXTkCheckButton(this->EventManager,pFrame,"Display",501);
+  displayMode->setState(display_mode[current_spline]);
+  pFrame->gridRowColumnChild(displayMode,2,0);
+
+  PXTkLabel* lab0=new PXTkLabel(this->EventManager,pFrame,"Size:");
+  pFrame->gridRowColumnChild(lab0,2,1);
+  
+  scaleMode=new PXTkOptionMenu(this->EventManager,pFrame,"0.25",503);
+  for (float s=0.50;s<=4.5;s+=0.25)
+      {
+	sprintf(pxtk_buffer,"%3.2f",s);
+	scaleMode->addOption(pxtk_buffer);
+      }
+  scaleMode->setIndex(scale_mode[current_spline]);
+  pFrame->gridRowColumnChild(scaleMode,2,2);
+
+  // Collection Operations 
+  // ---------------------
+  PXTkLabelFrame* oFrame=new PXTkLabelFrame(this->EventManager,landmarkFrame,"Operations on Current Spline");
+  bottomButtonFrame=new PXTkFrame(this->EventManager,landmarkFrame);  
+  landmarkFrame->addChildren("-side bottom -expand false -fill x -padx 00",bottomButtonFrame);
+
+  landmarkFrame->addChildren("-side top -expand true -fill both -padx 2 -pady 1",oFrame);
+
+
+  PXTkFrame* topfr=new PXTkFrame(this->EventManager,oFrame);
+  PXTkFrame* midfr=new PXTkFrame(this->EventManager,oFrame);
+  PXTkFrame* midfr2=new PXTkFrame(this->EventManager,oFrame);
+  PXTkFrame* midfr3=new PXTkFrame(this->EventManager,oFrame);
+  PXTkFrame* botfr=new PXTkFrame(this->EventManager,oFrame);  
+  PXTkFrame* botfr2=new PXTkFrame(this->EventManager,oFrame);  
+  oFrame->addChildren("-side top -pady 1 -expand f -fill x",topfr,midfr,midfr3,midfr2);
+  oFrame->addChildren("-side top -pady 1 -expand f -fill x",botfr,botfr2);
+
+  
+
+  PXTkButton* but3=new PXTkButton(this->EventManager,topfr,"x0.8",600);
+  PXTkButton* but4=new PXTkButton(this->EventManager,topfr,"x1.0",601);
+  PXTkButton* but4a=new PXTkButton(this->EventManager,topfr,"x1.25",602);
+  PXTkButton* but4b=new PXTkButton(this->EventManager,topfr,"x2",603);
+
+  SmoothingEntry=new PXTkEntry(this->EventManager,topfr);
+  SmoothingEntry->configure("-width",6);
+  SmoothingEntry->configure("-bg","red");
+  char line[10]; sprintf(line,"%f",this->DefaultSmoothing); SmoothingEntry->setText(line);
+  PXTkButton* but4c=new PXTkButton(this->EventManager,topfr,"sm",604);
+  
+  but3->configure("-padx",1);
+  but4->configure("-padx",1);
+  but4a->configure("-padx",1);
+  but4b->configure("-padx",1);
+  but4c->configure("-padx",1);
+
+  topfr->addChildren("-side left ",but3,but4);
+  topfr->addChildren("-side left ",but4a,but4b,SmoothingEntry,but4c);
+  
+
+  PXTkButton* but6=new PXTkButton(this->EventManager,midfr,"Color",450);
+  PXTkButton* but7=new PXTkButton(this->EventManager,midfr,"C-Color",451);
+  PXTkButton* but5=new PXTkButton(this->EventManager,midfr,"Ellipse",452);
+  PXTkButton* bbut5=new PXTkButton(this->EventManager,midfr,"Area",453);
+  but5->configure("-padx",0);
+  but6->configure("-padx",0);
+  but7->configure("-padx",0);
+  bbut5->configure("-padx",0);
+  midfr->addChildren("-side left -padx 0 -expand t -fill x",but6,but7,but5,bbut5);
+
+
+  if (this->SlaveMode==0)
+    {
+      for (int j=0;j<=1;j++)
+	{
+	  thresholdEntry[j]=new PXTkEntry(this->EventManager,midfr3);
+	  thresholdEntry[j]->configure("-width",6);
+	  thresholdEntry[j]->setText("0.1");
+	}
+      thresholdEntry[1]->setText("50.0");
+      PXTkButton* bbut6=new PXTkButton(this->EventManager,midfr3,"ROI Props >",454);
+      bbut6->configure("-padx",0);
+      midfr3->addChildren("-side left -padx 0 -expand t -fill x",bbut6,thresholdEntry[0],thresholdEntry[1]);
+    }
+
+  PXTkButton* but9=new PXTkButton(this->EventManager,midfr2,"Snake",610);
+  PXTkButton* but10=new PXTkButton(this->EventManager,midfr2,"Upd Snake",612);
+  but9->configure("-padx",0);
+  but10->configure("-padx",0);
+  midfr2->addChildren("-side left -padx 0 -expand t -fill x",but9,but10);
+
+  if (this->SlaveMode==0)
+    {
+      PXTkButton* but1=new PXTkButton(this->EventManager,botfr,"Load",401);
+      PXTkButton* but2=new PXTkButton(this->EventManager,botfr,"Save",402);
+      PXTkButton* but2a=new PXTkButton(this->EventManager,botfr,"Export",403);
+      but1->configure("-padx",0);
+      but2->configure("-padx",0);
+      but2a->configure("-padx",0);
+      botfr->addChildren("-side left -padx 0 -expand t -fill x",but1,but2,but2a);
+    }
+
+  PXTkButton* cp=new PXTkButton(this->EventManager,botfr2,"Copy",590);
+  PXTkButton* pt=new PXTkButton(this->EventManager,botfr2,"Paste",591);
+  PXTkButton* ptf=new PXTkButton(this->EventManager,botfr2,"Paste Flip",592);
+  PXTkButton* un=new PXTkButton(this->EventManager,botfr2,"Undo",593);
+  
+  cp->configure("-padx",0);
+  pt->configure("-padx",0);
+  ptf->configure("-padx",0);
+  un->configure("-padx",0);
+  botfr2->addChildren("-side left -padx 0 -expand f -fill x",cp,pt,ptf,un);
+
+
+
+
+  if ( (this->EventParent!=NULL && this->CallbackNo>0) || ( this->CallbackName!=NULL ))
+    {
+      autoUpdate=new PXTkCheckButton(this->EventManager,bottomButtonFrame,"Auto Upd",615);
+      if (this->AutoUpdateMode)
+	autoUpdate->setState(PXTrue);
+      PXTkButton* updB=new PXTkButton(this->EventManager,bottomButtonFrame,"Update",614);
+      bottomButtonFrame->addChildren("-side left -padx 10 -expand t -fill x",updB,autoUpdate);
+    }
+  
+  if (inside==0)
+    {
+      PXTkButton* closeB;
+      if (this->EventParent)
+	closeB=new PXTkButton(this->EventManager,bottomButtonFrame,"Close",3);
+      else
+	closeB=new PXTkButton(this->EventManager,bottomButtonFrame,"Exit",1);
+      bottomButtonFrame->addChildren("-side right -expand false -fill x -padx 10",closeB);
+    }
+
+  // Other Stuff 
+  UpdateStatus();
+  return GetWidgetName();
+}
+
+/* -------------------------------------------------------------------------*/ 
+void vtkpxGUISplineControl::SetRenderer(vtkRenderer *ren,int num)
+{
+  this->SetRenderer(ren);
+}
+
+void vtkpxGUISplineControl::SetRenderer(vtkRenderer* ren)
+{
+  for (int i=0;i<this->NumberOfSplines;i++)
+    {
+      double c[3]; vtkpxSurfaceUtil::GetColor(i,c);
+      if (splineActor[i]==NULL)
+	{
+	  vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+	  map->SetInput(splineSet[i]->GetOutput());
+	  
+	  splineActor[i]=vtkActor::New();
+	  splineActor[i]->SetMapper(map);
+	  
+	  if (display_mode[i])
+	    splineActor[i]->SetVisibility(1);
+	  else
+	    splineActor[i]->SetVisibility(0);
+	  splineActor[i]->GetProperty()->SetColor(c);
+	  map->Delete();
+	}
+      ren->AddActor(splineActor[i]);      
+      for (int j=0;j<2;j++)
+	{
+	  if (ghostActor[j][i]==NULL)
+	    {
+	      vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+	      map->SetInput(ghostSet[j][i]->GetOutput());
+	  
+	      ghostActor[j][i]=vtkActor::New();
+	      ghostActor[j][i]->SetMapper(map);
+	      ghostActor[j][i]->GetProperty()->SetOpacity(0.3);
+
+	      if (j==0 && (ghost_displaymode==1 || ghost_displaymode==3))
+		ghostActor[j][i]->SetVisibility(1);
+	      else if (j==1 && ghost_displaymode>=2)
+		ghostActor[j][i]->SetVisibility(1);
+	      else
+		ghostActor[j][i]->SetVisibility(0);
+	      map->Delete();
+	    }
+	  ren->AddActor(ghostActor[j][i]);
+	}
+    }
+  
+  if (editActor==NULL)
+    {
+      vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+      map->SetInput(editCurve->GetOutput());
+
+      editActor=vtkActor::New();
+      editActor->SetMapper(map);
+      map->Delete();
+    }
+
+  if (manualEditActor==NULL)
+    {
+      vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+      map->SetInput(manualEditCurve->GetOutput());
+
+      manualEditActor=vtkActor::New();
+      manualEditActor->SetMapper(map);
+      manualEditActor->SetVisibility(0);
+      map->Delete();
+    }
+
+  ren->AddActor(editActor);
+  ren->AddActor(manualEditActor);
+  this->Renderer=ren;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::Update()
+{
+  if (this->splineActor[0]==NULL)
+      return;
+
+  for (int i=0;i<this->NumberOfSplines;i++)
+      {
+	if (display_mode[i] && spline_enabled[i]==1)
+	  splineActor[i]->SetVisibility(1);
+	else
+	  splineActor[i]->SetVisibility(0);
+
+	double c[3];
+	for (int ib=0;ib<=2;ib++)
+	  c[ib]=0.1;
+	double w=splineActor[i]->GetProperty()->GetLineWidth();
+	w*=0.5;
+
+	for (int j=0;j<2;j++)
+	  {
+	    if (j==0)
+	      {
+		if ((ghost_displaymode==1 || ghost_displaymode==3) && spline_enabled[i]==1)
+		  ghostActor[j][i]->SetVisibility(1);
+		else
+		  ghostActor[j][i]->SetVisibility(0);
+	      }
+	    else if (j==1)
+	      {
+		if (ghost_displaymode>=2 && spline_enabled[i]==1)
+		  ghostActor[j][i]->SetVisibility(1);
+		else
+		  ghostActor[j][i]->SetVisibility(0);
+	      }
+	    ghostActor[j][i]->GetProperty()->SetColor(c);
+	    ghostActor[j][i]->GetProperty()->SetLineWidth(w);
+	  }
+      }
+
+  editActor->SetVisibility(splineActor[current_spline]->GetVisibility());
+
+  // Curve Stuff 
+  UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::UpdateDisplay()
+{
+  if (this->Renderer!=NULL)
+    this->Renderer->GetRenderWindow()->Render();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::UpdateStatus()
+{
+  if (!this->Initialized)
+      return;
+
+  if (spline_enabled[current_spline]==1)
+    sprintf(pxtk_buffer4,"Num Points=%d Edit=%d",
+	    currentSpline->GetNumPoints(),
+	    editCurve->GetNumPoints());
+  else
+    sprintf(pxtk_buffer4,"Spline Disabled!");
+  message->setText(pxtk_buffer4);
+}
+/* -------------------------------------------------------------------------*/
+int  vtkpxGUISplineControl::HandleEvent(int event)
+{
+  if (!this->Initialized)
+    return TCL_OK;
+  
+  if (event<10)
+    return this->EventManager->handleDirectEvent(event);
+
+  if (event==500)
+    {
+      SetCurrentCollection(currentCollection->getIndex());
+      if (mouseMode->getState())
+	{
+	  if (currentSpline->GetNumPoints()==0)
+	    mouseMode->setState(PXFalse);
+	}
+    }
+  else if (event==607 || event==606)
+    {
+      DoExtract(event-606);
+    }
+  else if (event==614)
+    {
+      if (spline_enabled[current_spline]==1)
+	this->CopySpline();
+
+
+      if (this->EventParent!=NULL && this->CallbackNo>0)
+	this->EventParent->HandleEvent(CallbackNo);
+      else
+	if (this->CallbackName!=NULL)
+	  PXTkApp::executeTclCommand(this->CallbackName);
+    }
+  else if (event==615)
+    {
+      if (autoUpdate->getState())
+	this->AutoUpdateMode=1;
+      else
+	this->AutoUpdateMode=0;
+    }
+  else if (spline_enabled[current_spline]==1)
+    {
+      switch(event)
+	{
+	case 401:
+	  {
+	    int ok=1;
+	    if (currentSpline->GetNumPoints()>0)
+	      ok=this->EventManager->questionBox("Loading will delete your old spline. Are you sure?");
+	    if (ok)
+	      {
+		char* line=this->EventManager->getOpenFilename("Load splines","Splines","*.spl");
+		if (line!=NULL)
+		  {
+		    if (strlen(line)>0)
+		      LoadSpline(line);
+		  }
+	      }
+	  }
+	  break;
+	  
+	case 402:
+	  {
+	    char* line=this->EventManager->getSaveFilename("Save Splines","spline.spl","Splines","*.spl");
+	    if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		  {
+		    strcpy(pxtk_buffer2,line);
+		    if(currentSpline->Save(line))
+		      {
+			this->SetItemFilename(current_spline,pxtk_buffer2);
+			UpdateStatus();
+		      }
+		    else
+		      {
+			sprintf(pxtk_buffer2,"Failed to save splines %d in %s",current_spline+1,line);
+			this->EventManager->messageBox(pxtk_buffer2,"Save Failure");
+		      }
+		  }
+	      }
+	  }
+	  break;
+	  
+	case 403:
+	  {
+	    char* line=this->EventManager->getSaveFilename("Save Contour","spline.cntr","Contours","*.cntr");
+	    if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		  {
+		    strcpy(pxtk_buffer2,line);
+		    vtkPoints* temp=vtkPoints::New();
+		    this->currentSpline->ExportKnotPointsToPoints(temp);
+		    FILE* fout=fopen(line,"w");
+		    if (fout)
+		      {
+			fprintf(fout,"#Number of Landmarks \n%d\n",temp->GetNumberOfPoints());
+			fprintf(fout,"#Landmarks\n");
+			for (int i=0;i<temp->GetNumberOfPoints();i++)
+			  {
+			    double x[3];
+			    temp->GetPoint(i,x);
+			    fprintf(fout,"%6.2f %6.2f %6.2f\n",x[0],x[1],x[2]);
+			  }
+			fclose(fout);
+		      }
+		    temp->Delete();
+		  }
+	      }
+	  }
+	  break;
+	  
+	case 450:
+	  if (splineActor[current_spline]!=NULL)
+	    {
+	      double c[3];
+	      splineActor[current_spline]->GetProperty()->GetColor(c);
+	      int a=this->EventManager->d_colorBox("Spline Color",c[0],c[1],c[2]);
+	      if (a==1)
+		this->SetItemColor(current_spline,c);
+	    }
+	  break;
+	  
+	case 451:
+	  if (editActor!=NULL)
+	    {
+	      double c[3];
+	      editActor->GetProperty()->GetColor(c);
+	      int a=this->EventManager->d_colorBox("Controls Color",c[0],c[1],c[2]);
+	      if (a==1)
+		editActor->GetProperty()->SetColor(c);
+	    }
+	  break;
+	  
+	case 452: // Ellipse
+	  this->CopyToUndoSpline();
+	  currentSpline->SetEllipse(8,
+				    spacing[0]*float(dimensions[0])/8.0*(1.0+current_spline),
+				    spacing[1]*float(dimensions[0])/8.0*(1.0+current_spline),
+				    origin[0]+spacing[0]*dimensions[0]/2.0,
+				    origin[1]+spacing[1]*dimensions[1]/2.0,
+				    slice_offset+float(image_level)*this->spacing[2]+this->origin[2]);
+	  UpdateControlsFromCurrentSpline();
+	  break;
+	  
+	case 453:
+	  sprintf(pxtk_buffer,"Curve %d Area=%8.1f mm^2\n",current_spline+1,currentSpline->GetArea());
+	  PXTkApp::printToConsole(pxtk_buffer);
+	  this->EventManager->messageBox(pxtk_buffer,"Curve Area ...");
+	  break;
+	  
+	case 454:
+	  if (image!=NULL)
+	    {
+	      float area[2],mean[2],std[2],threshold[2];
+	      int np[2];
+	      for (int ii=0;ii<2;ii++)
+		{
+		  threshold[ii]=atof(thresholdEntry[ii]->getText());
+		  sprintf(pxtk_buffer,"%5.2f",threshold[ii]);
+		  thresholdEntry[ii]->setText(pxtk_buffer);
+		}
+	      
+	      int nt=currentSpline->GetDualVOIProperties(image,image_level,image_frame,
+							 area,mean,std,np,threshold);
+	      
+	      if (area[0]<0.0001)
+		area[0]=0.0001;
+	      
+	      sprintf(pxtk_buffer,"Curve %d Total Enclosed Area=%8.1f mm^2 npix=%d\n",
+		      current_spline+1,currentSpline->GetArea(),nt);
+	      PXTkApp::printToConsole(pxtk_buffer);
+	      for (int i=0;i<=1;i++)
+		{
+		  sprintf(pxtk_buffer,"\t ROI %d area >%.1f \t= %6.1f (mm^2) mean=%5.1f std=%5.1f npix=%6d\n",
+			  i+1,threshold[i],area[i],mean[i],std[i],np[i]);
+		  PXTkApp::printToConsole(pxtk_buffer);
+		}
+	      sprintf(pxtk_buffer, "\t Ratio 2/1  \t= %5.2f %% \n\n",
+		      area[1]/area[0]*100.0);
+	      PXTkApp::printToConsole(pxtk_buffer);
+	      PXTkApp::popupConsole();
+	    }
+	  break;
+	  
+	case 501:
+	  display_mode[current_spline]=displayMode->getState();
+	  Update();
+	  break;
+
+	case 502:
+	  if (editActor!=NULL)
+	    {
+	      if (showControls->getState())
+		editActor->SetVisibility(1);
+	      else
+	      editActor->SetVisibility(0);
+	  }
+	  break;
+	  
+	case 503:
+	  scale_mode[current_spline]=scaleMode->getIndex();
+	  editCurve->SetPointScale(0.25+0.25*float(scale_mode[current_spline])*this->ControlPointScaleFactor);
+	  /*fprintf(stderr,"Dist Threshold=%f controlpointscalefactor=%f pointscale=%f\n",
+		  this->DistanceThreshold,this->ControlPointScaleFactor,
+		  editCurve->GetPointScale());*/
+	  break;
+	  
+	case 504:
+	  slice_offset=-slice_offset;
+	  this->SetLevel(image_level);
+	  break;
+	  
+	case 505:
+	  {
+	    for  (int i=0;i<this->NumberOfSplines;i++)
+	      display_mode[i]=PXFalse;
+	    displayMode->setState(PXFalse);
+	  }
+	  Update();
+	  break;
+	  
+	case 506:
+	{
+	  for  (int i=0;i<this->NumberOfSplines;i++)
+	    display_mode[i]=PXTrue;
+	  displayMode->setState(PXTrue);
+	}
+	Update();
+	break;
+	
+	case 507:
+	  ghost_displaymode=ghostMode->getIndex();
+	  Update();
+	  break;
+	  
+	case 510:
+	  if (editMode->getState()==PXFalse)
+	    {
+	      ExtractButton->enable(PXFalse);
+	      if (this->manual_add_mode==1)
+		this->FitSplineToCurrentControls();
+	    }
+	  else
+	    {
+	      this->manual_add_mode=1;
+	      ExtractButton->enable(PXTrue);
+	      splineSet[current_spline]->ExportToBaseCurve(this->manualEditCurve);
+	      this->manualEditCurve->SetPointScale(editCurve->GetPointScale()*0.5);
+	      this->manualEditCurve->DeleteAllPoints();
+	      this->manualEditActor->SetVisibility(1);
+	    }
+	  break;
+
+	case 600: // x0.8
+	  {
+	    this->CopyToUndoSpline();
+	    float s=this->currentSpline->GetSpline()->getlength(0.0,1.0,0.01)/100.0;
+	    currentSpline->ChangeSpacing(this->DefaultSmoothing*s,(80*currentSpline->GetNumPoints())/100);
+	    this->changed[current_spline]=1;
+	    UpdateControlsFromCurrentSpline();
+	  }
+	  break;
+	  
+	case 601: // x1.0
+	  {
+	    this->CopyToUndoSpline();
+	    float s=this->currentSpline->GetSpline()->getlength(0.0,1.0,0.01)/100.0;
+	    fprintf(stderr,"S=%.2f, this->Default=%f\n",s,this->DefaultSmoothing);
+	    currentSpline->ChangeSpacing(this->DefaultSmoothing*s,currentSpline->GetNumPoints());
+	    this->changed[current_spline]=1;
+	    UpdateControlsFromCurrentSpline();
+	  }
+	  break;
+	  
+	case 602: // x1.25
+	  {
+	    this->CopyToUndoSpline();
+	    float s=this->currentSpline->GetSpline()->getlength(0.0,1.0,0.01)/100.0;
+	    currentSpline->ChangeSpacing(this->DefaultSmoothing*s,(125*currentSpline->GetNumPoints())/100);
+	    this->changed[current_spline]=1;
+	    UpdateControlsFromCurrentSpline();
+	  }
+	  break;
+	  
+	case 603: // x2.0
+	  {
+	    this->CopyToUndoSpline();
+	    float s=this->currentSpline->GetSpline()->getlength(0.0,1.0,0.001)/100.0;
+	    currentSpline->ChangeSpacing(this->DefaultSmoothing*s,(200*currentSpline->GetNumPoints())/100);
+	    this->changed[current_spline]=1;
+	    UpdateControlsFromCurrentSpline();
+	    PXFPBSpline::debugmode=0;
+	  }
+	  break;
+	  
+	case 604: // sD
+	  {
+	    this->CopyToUndoSpline();
+	    float s=this->currentSpline->GetSpline()->getlength(0.0,1.0,0.01)/100.0;
+	    float t=Frange(atof(SmoothingEntry->getText()),0.0001,10.0);
+	    char line[10]; sprintf(line,"%f",t); SmoothingEntry->setText(line);
+	    currentSpline->ChangeSpacing(t*s,-1);
+	    this->changed[current_spline]=1;
+	    UpdateControlsFromCurrentSpline();
+	  }
+	break;
+	
+	  
+	case 590:
+	  this->CopySpline();
+	  break;
+	  
+	case 591:
+	  this->PasteSpline();
+	  break;
+
+	case 592:
+	  this->PasteFlipSpline();
+	  break;
+	  
+	case 593:
+	  this->UndoSpline();
+	  break;
+	  
+	case 610:
+	  DoSnake(0);
+	  break;
+	  
+	case 611:
+	  this->CopyToUndoSpline();
+	  DoSnake(1);
+	  break;
+	  
+	case 612:
+	  this->CopyToUndoSpline();
+	  DoSnake(2);
+	  break;
+	  
+	case 613:
+	  DoSnake(3);
+	  break;
+	  
+	}
+    }
+
+
+  UpdateDisplay();
+
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::SetItemColor(int index,double color[3])
+{
+  if (splineActor[index]!=NULL)
+    splineActor[index]->GetProperty()->SetColor(color);
+
+}
+
+void vtkpxGUISplineControl::SetItemFilename(int index,const char* s)
+{
+  if (this->Initialized==0)
+    return;
+
+  //  fprintf(stderr,"GUISpline:index=%d s=%s\n",index,s);
+
+  if (index==-1)
+    {
+      sprintf(pxtk_buffer3,"%s.%d",PXTkApp::getFilenameTail(s),current_spline+1);
+      currentCollection->changeLabel(current_spline,pxtk_buffer3);
+      return;
+    }
+
+  sprintf(pxtk_buffer4,"%s.%d",PXTkApp::getFilenameTail(s),index+1);
+  currentCollection->changeLabel(index,pxtk_buffer4);
+}
+
+/* -------------------------------------------------------------------------*/
+
+void vtkpxGUISplineControl::CopySpline()
+{
+  clipboardSpline->Copy(currentSpline);
+}
+
+void vtkpxGUISplineControl::PasteSpline()	
+{
+  if (clipboardSpline->GetNumPoints()>0)
+    SetSpline(clipboardSpline,-1);
+}
+
+
+void vtkpxGUISplineControl::PasteFlipSpline()	
+{
+  if (clipboardSpline->GetNumPoints()<1)
+    return;
+
+  PXFPBSpline* spl=clipboardSpline->GetSpline();
+
+  float cx=spacing[0]*dimensions[0]/2+origin[0];
+
+  for (int i=0;i<spl->getnumcontrolpoints();i++)
+    {
+      float x1=spl->getcontrolx(i);
+      spl->shiftcontrol(i,-2.0*(x1-cx),0,0);
+    }
+
+  SetSpline(clipboardSpline,-1);
+}
+
+
+void vtkpxGUISplineControl::CopyToUndoSpline()
+{
+  undoSpline->Copy(currentSpline);
+}
+
+void vtkpxGUISplineControl::UndoSpline()	
+{
+  if (undoSpline->GetNumPoints()>0)
+    SetSpline(undoSpline,-1);
+}
+
+/* -------------------------------------------------------------------------*/
+vtkpxSplineSource* vtkpxGUISplineControl::GetSpline(int index)
+{
+  if (index==-1)
+      index=current_spline;
+
+  return splineSet[Irange(index,0,this->NumberOfSplines-1)];
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUISplineControl::GetCurrentIndex()
+{
+  return current_spline;
+}
+
+int  vtkpxGUISplineControl::GetCurrentSliceNumber()
+{
+  return image_level;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::SetSpline(vtkpxSplineSource* land,int index)
+{
+  if (index==-1)
+    index=current_spline;
+
+  index=Irange(index,0,this->NumberOfSplines-1);
+
+  splineSet[index]->Copy(land);
+  float zlev=image_level*this->spacing[2]+this->origin[2];
+  splineSet[index]->SetZlevel(zlev+slice_offset);
+  this->manual_zcoord=zlev+slice_offset;
+  this->changed[index]=1;  
+
+
+  if (index==current_spline)
+    UpdateControlsFromCurrentSpline();
+  
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::SetChangedStatus(int index,int val)
+{
+  index=Irange(index,0,this->NumberOfSplines-1);
+  this->changed[index]=(val>0);
+
+}
+
+int  vtkpxGUISplineControl::GetChangedStatus(int index)
+{
+  index=Irange(index,0,this->NumberOfSplines-1);
+  return this->changed[index];
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::SetGhostSpline(vtkpxSplineSource* land,int ghost,int index)
+{
+  if (index==-1)
+      index=current_spline;
+  ghost=Irange(ghost,0,1);
+  index=Irange(index,0,this->NumberOfSplines-1);
+
+  ghostSet[ghost][index]->Copy(land);
+  float zlev=image_level*this->spacing[2]+this->origin[2];
+  ghostSet[ghost][index]->SetZlevel(zlev+slice_offset);
+}
+/* -------------------------------------------------------------------------*/
+vtkpxSplineSource* vtkpxGUISplineControl::GetGhostSpline(int ghost,int index)
+{
+ if (index==-1)
+      index=current_spline;
+  ghost=Irange(ghost,0,1);
+  index=Irange(index,0,this->NumberOfSplines-1);
+  return ghostSet[ghost][index];
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::SetImage(vtkImageData* img,int plane,int level,int frame)
+{
+  if (img!=NULL)
+    {
+      if (this->image!=NULL)
+	this->image->Delete();
+      this->image=vtkImageData::New();
+      this->image->ShallowCopy(img);
+      
+      int d[3]; double sp[3],ori[3];
+      image->GetSpacing(sp);
+      image->GetOrigin(ori);
+      image->GetDimensions(d);
+
+      double sum=0.0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=fabs(float(d[ia]-this->dimensions[ia]))+fabs(sp[ia]-this->spacing[ia])+fabs(ori[ia]-this->origin[ia]);
+
+      if (sum>0.01)
+	{
+	  this->SetSpacingOrigin(sp,ori);
+	  this->SetLevel(level);
+	  image->GetDimensions(d);
+	  image->GetDimensions(this->dimensions);
+	  	  
+	  for (int i=0;i<this->NumberOfSplines;i++)
+	    {
+	      splineSet[i]->SetEllipse(6,
+				       spacing[0]*dimensions[0]/8.0*(1.0+i),
+				       spacing[1]*dimensions[1]/8.0*(1.0+i),
+				       origin[0]+spacing[0]*dimensions[0]/2.0,
+				       origin[1]+spacing[1]*dimensions[1]/2.0,
+				       0.0,2);
+	      splineSet[i]->SetResolution(sp[0]);
+	      for (int j=0;j<2;j++)
+		ghostSet[j][i]->Copy(splineSet[i]);
+	    }
+
+	  this->DistanceThreshold=(spacing[0]*dimensions[0])/50.0;
+	  this->ControlPointScaleFactor=this->DistanceThreshold*0.5;
+	  editCurve->SetPointScale(0.25+0.25*float(scale_mode[current_spline])*this->ControlPointScaleFactor);
+	  /*fprintf(stderr,"Dist Threshold=%f controlpointscalefactor=%f pointscale=%f\n",
+		  this->DistanceThreshold,this->ControlPointScaleFactor,
+		  editCurve->GetPointScale());*/
+	}
+      else
+	{
+	  if (level!=image_level)
+	    this->SetLevel(level);
+	  image_frame=frame;
+	}
+    }
+}
+
+void vtkpxGUISplineControl::SetPlaneLevel(int plane,int level)
+{
+  this->SetLevel(level);
+}
+
+
+void vtkpxGUISplineControl::SetSpacingOrigin(double sp[3],double ori[3])
+{
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->origin[ia]=ori[ia];
+      this->spacing[ia]=sp[ia];
+    }
+
+
+  for (int i=0;i<this->NumberOfSplines;i++)
+    {
+      splineSet[i]->SetImageOrigin(this->origin);
+      splineSet[i]->SetImageSpacing(this->spacing);
+    }
+
+}
+
+void vtkpxGUISplineControl::SetLevel(int level)
+{
+  image_level=level;
+  double zlev=level*this->spacing[2]+this->origin[2];
+  this->manual_zcoord=zlev+slice_offset;
+  for (int i=0;i<this->NumberOfSplines;i++)
+    {
+      splineSet[i]->SetZlevel(zlev+slice_offset);
+      for (int j=0;j<=1;j++)
+	ghostSet[j][i]->SetZlevel(zlev+slice_offset);
+    }
+  //fprintf(stderr,"Set Zlevel =%.1f (level=%d ori=%.1f sp=%.1f)\n",zlev,image_level,origin[2],spacing[2]);
+  UpdateControlsFromCurrentSpline();
+}
+
+/* -------------------------------------------------------------------------*/
+int vtkpxGUISplineControl::HandleClickedPoint(float x,float y,float z,int scaled,int state)
+{
+  static int found_point=-1;
+  if (!mouseMode->getState())
+    return 0;
+
+  if (spline_enabled[current_spline]==0)
+    return 0;
+
+
+  if (this->manual_add_mode==1)
+    {
+      switch (state)
+	{
+	case 0:
+	  this->manualEditCurve->AddPoint(x,y,manual_zcoord,scaled);
+	  break;
+	case 1:
+	  this->manualEditCurve->SetPoint(this->manualEditCurve->GetNumPoints()-1,x,y,manual_zcoord,scaled);
+	  break;
+	case 2:
+	  break;
+	}
+      return 1;
+    }
+
+
+  if (editActor==NULL)
+    return 0;
+
+  if (editActor->GetVisibility()==0)
+    return 0;
+
+
+  int numitems=currentSpline->GetNumPoints();//listBox->getNumItems();
+  if (numitems<1)
+    return 0;
+
+  double lx[3];
+  switch (state)
+    {
+    case 0:
+    case 6:
+      {
+	lx[0]=x;lx[1]=y;lx[2]=z;
+	found_point=editCurve->FindClosestPoint(lx,this->DistanceThreshold,1);
+	if (found_point>=0)
+	  return 1;
+      }
+      break;
+
+    case 1:
+      if (found_point>=0)
+	{
+	  double x1,y1,z1;
+	  editCurve->GetPoint(found_point,x1,y1,z1);
+	  editCurve->SetPoint(found_point,x,y,z1,scaled);
+	  currentSpline->SetFromBaseCurve(editCurve);
+	  this->SetChangedStatus(current_spline,1);
+	  return 1;
+	  return 1;
+	}
+      break;
+
+    case 7:
+      if (found_point>=0)
+	{
+	  double x1,y1,z1;
+	  editCurve->GetPoint(found_point,x1,y1,z1);
+	  float dx=x-x1;
+	  float dy=y-y1;
+	  int np=editCurve->GetNumPoints();
+	  for (int ia=0;ia<np;ia++)
+	    {
+	      editCurve->GetPoint(ia,x1,y1,z1);
+	      editCurve->SetPoint(ia,x1+dx,y1+dy,z1,scaled);
+	    }
+	  currentSpline->SetFromBaseCurve(editCurve);
+	  this->SetChangedStatus(current_spline,1);
+	  return 1;
+	}
+      break;
+
+    case 2:
+    case 8:
+      if (found_point>=0)
+	{
+	  found_point=-1;
+	  UpdateStatus();
+	  return 1;
+	}
+      break;
+
+    case 5:
+      {
+	int ok=currentSpline->InsertKnot(x,y);
+	if (ok==1)
+	  {
+	    UpdateControlsFromCurrentSpline();
+	  }
+      }
+      break;
+    }
+  return 0;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::LoadSpline(const char* fname)
+{
+  strcpy(pxtk_buffer2,fname);
+  int ok=currentSpline->Load(fname);
+  if (!ok)
+      {
+	sprintf(pxtk_buffer2,"Failed to load landmarks %d from %s",current_spline+1,fname);
+	this->EventManager->messageBox(pxtk_buffer2,"Load Failure");
+      }
+  else
+    {
+      this->SetItemFilename(current_spline,pxtk_buffer2);
+      UpdateControlsFromCurrentSpline();
+    }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::SetCurrentCollection(int num)
+{
+  num=Irange(num,0,this->NumberOfSplines-1);
+  if (num==current_spline)
+      return;
+  current_spline=num;
+
+  currentSpline=splineSet[current_spline];  
+  UpdateControlsFromCurrentSpline();
+  UpdateStatus();
+  Update();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::UpdateControlsFromCurrentSpline()
+{
+  if (spline_enabled[current_spline]==0)
+    {
+      UpdateStatus();
+      return;
+    }
+  this->editCurve->SetShowCurve(0);
+  splineSet[current_spline]->ExportToBaseCurve(editCurve);
+  displayMode->setState(display_mode[current_spline]);
+  scaleMode->setIndex(scale_mode[current_spline]);
+  UpdateStatus();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUISplineControl::DoSnake(int apply)
+{
+  if (image==NULL)
+      return 0;
+  
+  if (apply==0)
+    {
+      if (snakeGUI==NULL)
+	{
+	  PXTkFrame* polyFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+	  snakeGUI=new PXTkDialog(this->EventManager,polyFrame,"Snake Controls",PXFalse);
+	  snakeGUI->initDisplay();
+	  PXTkFrame* frame=(PXTkFrame*)snakeGUI->getMainWindow();
+	  
+	  snakeEdgeWeight=new PXTkArrowScale(snakeGUI,frame,"Edge Weight",-1,PXTrue);
+	  snakeEdgeWeight->setRange(0.0,10.0);
+	  snakeEdgeWeight->setIncrement(0.5);
+	  snakeEdgeWeight->setResolution(0.1);
+	  snakeEdgeWeight->setDecimalPoints(1);
+	  snakeEdgeWeight->setLengthWidth(120,8);
+	  
+	  snakeSmoothWeight=new PXTkArrowScale(snakeGUI,frame,"Smoothness Weight",-1,PXTrue);
+	  snakeSmoothWeight->setRange(0.0,10.0);
+	  snakeSmoothWeight->setIncrement(0.5);
+	  snakeSmoothWeight->setResolution(0.1);
+	  snakeSmoothWeight->setDecimalPoints(1);
+	  snakeSmoothWeight->setLengthWidth(120,8);
+	  
+	  snakeSigma=new PXTkArrowScale(snakeGUI,frame,"Sigma",-1,PXTrue);
+	  snakeSigma->setRange(0.0,4.0);
+	  snakeSigma->setIncrement(0.5);
+	  snakeSigma->setResolution(0.1);
+	  snakeSigma->setDecimalPoints(1);
+	  snakeSigma->setLengthWidth(120,8);
+	  
+	  snakeIterations=new PXTkArrowScale(snakeGUI,frame,"Iterations",-1,PXTrue);
+	  snakeIterations->setRange(1,20);
+	  snakeIterations->setIncrement(3);
+	  snakeIterations->setResolution(1);
+	  snakeIterations->setDecimalPoints(0);
+	  snakeIterations->setLengthWidth(120,8);
+	  
+
+	  snakeStep=new PXTkArrowScale(snakeGUI,frame,"Step",-1,PXTrue);
+	  snakeStep->setRange(0.0,1.0);
+	  snakeStep->setIncrement(0.05);
+	  snakeStep->setResolution(0.01);
+	  snakeStep->setDecimalPoints(2);
+	  snakeStep->setLengthWidth(120,8);
+
+	  PXTkFrame* fr2=new PXTkFrame(snakeGUI,frame);
+	  PXTkButton* b1=new PXTkButton(this->EventManager,fr2,"Create",611);
+	  PXTkButton* b2=new PXTkButton(this->EventManager,fr2,"Update",612);
+	  PXTkButton* b3=new PXTkButton(this->EventManager,fr2,"Reset",613);
+	  PXTkButton* b4=new PXTkButton(snakeGUI,fr2,"Close",3);
+	  
+	  b1->configure("-padx",1);
+	  b2->configure("-padx",1);
+	  b3->configure("-padx",1);
+	  b4->configure("-padx",1);
+	  
+	  frame->addChildren("-side top -expand true -fill x",
+			     snakeEdgeWeight->getMainWindow(),
+			     snakeSmoothWeight->getMainWindow(),
+			     snakeIterations->getMainWindow());
+	  frame->addChildren("-side bottom -expand true -fill x",
+			     fr2,
+			     snakeSigma->getMainWindow(),
+			     snakeStep->getMainWindow());
+	  fr2->addChildren("-side left -expand true -fill x",b1,b2,b3,b4);
+	}
+      
+      /*snakeEdgeWeight->setRange(image_range[0],image_range[1]);
+	snakeEdgeWeight->setValue(Frange(snakeEdgeWeight->getValue(),image_range[0],image_range[1]));*/
+      snakeGUI->popupDialog();
+      DoSnake(3);
+    }
+  
+
+  if (snakeGUI==NULL)
+    {
+      DoSnake(0);
+      snakeGUI->popdownDialog();
+    }
+  
+  
+  if (apply==3)
+    {
+      snakeEdgeWeight->setValue(3.0);
+      snakeSmoothWeight->setValue(3.0);
+      snakeSigma->setValue(1.0);
+      snakeIterations->setValue(5);
+      snakeStep->setValue(0.05);
+    }
+
+  if (apply==1)
+    {
+      float w_img=snakeEdgeWeight->getValue()*10.0;
+      float w_smo=snakeSmoothWeight->getValue()*0.1;
+      float sigma=snakeSigma->getValue();
+      float stp=snakeStep->getValue();
+      int   iter=(int)snakeIterations->getValue();
+      
+      currentSpline->CreateSnake(image,image_level,image_frame,w_img,w_smo,stp,sigma,iter);
+      this->changed[current_spline]=1;
+    }
+
+  if (apply==1 || apply==2)
+    {
+      float w_img=snakeEdgeWeight->getValue()*10.0;
+      float w_smo=snakeSmoothWeight->getValue()*0.1;
+      if (mouseMode->getState()==PXFalse)
+	mouseMode->setState(PXTrue);
+      currentSpline->UpdateSnake(w_img,w_smo);
+      this->changed[current_spline]=1;
+      UpdateControlsFromCurrentSpline();
+    }
+
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::EnableSpline(int i)
+{
+  i=Irange(i,0,this->NumberOfSplines-1);
+  spline_enabled[i]=1;
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::DisableSpline(int i)
+{
+  i=Irange(i,0,this->NumberOfSplines-1);
+  spline_enabled[i]=0;
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineControl::FitSplineToCurrentControls()
+{
+  int nump=manualEditCurve->GetNumPoints();
+  int ok=0;
+
+  if (nump<4)
+    ok=this->EventManager->questionBox("Not enough points to fit spline! Do you want to add more points? (No will revert to current spline)");
+  else
+    ok=this->EventManager->questionBox("Do you want to fit spline to current set of controls? This will delete your old spline. Are you sure?");
+
+  if (ok==0)
+    {
+      this->manual_add_mode=0;
+      this->manualEditActor->SetVisibility(0);
+      return;
+    }
+
+  if (nump<4)
+    {
+      editMode->setState(PXTrue);
+      ExtractButton->enable(PXTrue);
+      return;
+    }
+
+  //  this->CopyToUndoSpline();
+  manualEditCurve->Compact();
+  float z=this->currentSpline->GetZlevel();
+  this->currentSpline->FitPoints(manualEditCurve->GetPoints(),0.1,-1,1,100);
+  this->currentSpline->ChangeSpacing(1.0,currentSpline->GetNumPoints());
+  this->currentSpline->SetZlevel(z);
+  this->currentSpline->Modified();
+
+  this->manualEditActor->SetVisibility(0);
+  this->manual_add_mode=0;
+  UpdateControlsFromCurrentSpline();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUISplineControl::DoExtract(int apply)
+{
+  if (image==NULL)
+      return 0;
+
+  if (this->manual_add_mode==0)
+    {
+      this->EventManager->messageBox("Must be in Manual point, and curve must have at least one point to do extraction","Error!");
+      return 0;
+    }
+
+  if (manualEditCurve->GetNumPoints()==0)
+    {
+      this->EventManager->messageBox("Need at least a seed point to do extraction","Error!");
+      return 0;
+    }
+
+  if (apply==0)
+    {
+      if (extractGUI==NULL)
+	{
+	  PXTkFrame* polyFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+	  extractGUI=new PXTkDialog(this->EventManager,polyFrame,"Extract Controls",PXFalse);
+	  extractGUI->initDisplay();
+	      
+	  PXTkFrame* frame=(PXTkFrame*)extractGUI->getMainWindow();
+	  extractType=new PXTkOptionMenu(extractGUI,frame,"Auto Threshold",-1);
+	  extractType->addOption("Manual Threshold");
+	  extractType->setIndex(0);
+	  
+	  thresholdScale=new PXTkArrowScale(extractGUI,frame,"Threshold",-1,PXTrue);
+	  thresholdScale->setRange(0.0,255.0);
+	  thresholdScale->setValue(128.0);
+	  thresholdScale->setIncrement(1);
+	  thresholdScale->setResolution(1);
+	  thresholdScale->setLengthWidth(120,8);
+	  
+	  medianScale=new PXTkArrowScale(extractGUI,frame,"Median Radius",-1,PXTrue);
+	  medianScale->setRange(0.0,4.0);
+	  medianScale->setValue(0.0);
+	  medianScale->setIncrement(1.0);
+	  medianScale->setResolution(1.0);
+	  medianScale->setLengthWidth(120,8);
+	  
+	  sigmaScale=new PXTkArrowScale(extractGUI,frame,"Sigma",-1,PXTrue);
+	  sigmaScale->setRange(0.0,5.0);
+	  sigmaScale->setValue(0.0);
+	  sigmaScale->setIncrement(0.5);
+	  sigmaScale->setResolution(0.1);
+	  sigmaScale->setDecimalPoints(1);
+	  sigmaScale->setLengthWidth(120,8);
+	  
+	  PXTkFrame* fr2=new PXTkFrame(extractGUI,frame);
+	  PXTkButton* b1=new PXTkButton(this->EventManager,fr2,"Extract",607);
+		  PXTkButton* b3=new PXTkButton(extractGUI,fr2,"Close",3);
+	  frame->addChildren("-side top -expand true -fill x",extractType,thresholdScale->getMainWindow(),
+			     medianScale->getMainWindow(),sigmaScale->getMainWindow(),fr2);
+	  fr2->addChildren("-side left -expand true -fill x",b1/*,b2*/,b3);
+	}
+      
+      image->GetPointData()->GetScalars()->GetRange(image_range);
+      thresholdScale->setRange(image_range[0],image_range[1]);
+      thresholdScale->setValue(Frange(thresholdScale->getValue(),image_range[0],image_range[1]));
+      extractGUI->popupDialog();
+      return 0;
+    }
+  
+  if (extractGUI==NULL)
+    {
+      DoExtract(0);
+      extractGUI->popdownDialog();
+    }
+
+
+  int ok=0;
+
+
+
+  if (extractType->getIndex()==0)
+      {
+	float threshold=-200000.0;
+	ok=manualEditCurve->ExtractImageContour(image,2,image_level,image_frame,
+					  threshold,
+					  (int)medianScale->getValue(),sigmaScale->getValue());
+	if (ok)
+	  thresholdScale->setValue(threshold);
+      }
+  else
+      {
+	float threshold=thresholdScale->getValue();
+	ok=manualEditCurve->ExtractImageContour(image,2,image_level,image_frame,threshold,
+						   (int)medianScale->getValue(),sigmaScale->getValue());
+      }
+
+  if (ok)
+    {
+      int num=manualEditCurve->GetNumPoints();
+      for (int i=0;i<num;i++)
+	{
+	  double x,y,z;
+	  manualEditCurve->GetPoint(i,x,y,z);
+	  manualEditCurve->SetPoint(i,x,y,this->manual_zcoord,0);
+	}
+      UpdateDisplay();
+    }
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUISplineControl.h b/bioimagesuite30_src/GUI/vtkpxGUISplineControl.h
new file mode 100644
index 0000000..f6910b9
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUISplineControl.h
@@ -0,0 +1,324 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUISplineControl.h,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:29 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUISplineControl - Base Image Viewer
+// .SECTION Description
+
+#ifndef __vtkpxGUISplineControl_h
+#define __vtkpxGUISplineControl_h
+
+#include "vtkpxSplineSource.h"
+#include "vtkpxBaseCurve.h"
+#include "vtkpxGUIBaseCurveEditor.h"
+#include "vtkActor.h"
+#include "pxtkapp.h"
+#include "pxtkeventobj.h"
+#include "pxtkgadgets.h"
+#include "pxtkcomplexwidgets.h"
+#include "pxtkdialog.h"
+#include "pxtkmenu.h"
+#include "pxcontour.h"
+
+
+const int SP_MAX_COLLECTIONS = 50; 
+
+class vtkpxGUISplineControl : public vtkpxGUIBaseCurveEditor 
+{
+public:
+
+  static vtkpxGUISplineControl *New();
+  vtkTypeMacro(vtkpxGUISplineControl,vtkpxGUIBaseCurveEditor);
+  
+
+  // Description:
+  // Set/Get Number Of Splines 
+  virtual void SetNumberOfSplines(int a);
+  vtkGetMacro(NumberOfSplines,int);
+
+  // Description:
+  // Initialize Display and add Renderer 
+  virtual char*  Initialize(const char* name,int inside);
+  virtual void   SetRenderer(vtkRenderer *rendererer,int num);
+  virtual void   SetRenderer(vtkRenderer *rendererer);
+
+  // Description:
+  // Update Display
+  virtual void   Update();
+  virtual void   UpdateDisplay();
+
+  // Description:
+  // Event Manager 
+  virtual int    HandleEvent(int);
+  
+  // Description:
+  // Update status label with info on current spline 
+  virtual void    UpdateStatus();
+
+  // Description:
+  // Handle mouse point 
+  virtual int     HandleClickedPoint(float x,float y,float z,int scaled=1,int state=0);
+
+  // Description:
+  // Get and Set Current Spline 
+  virtual vtkpxSplineSource* GetSpline(int index=-1);
+  virtual vtkObject* GetItem(int index) { return GetSpline(index);}
+  virtual int  GetCurrentIndex();
+  virtual void SetSpline(vtkpxSplineSource* land,int index=-1);
+  virtual void SetGhostSpline(vtkpxSplineSource* land,int index1=0,int index2=-1);
+  virtual vtkpxSplineSource* GetGhostSpline(int index1=0,int index2=-1);
+  virtual int  GetCurrentSliceNumber();
+  virtual void SetItemColor(int index,double color[3]);
+  virtual void SetItemFilename(int index,const char* s);
+
+  // Description:
+  // Set Current Image , including slice and orientation
+  // Discards plane and assumes plane =2 
+  virtual void SetImage(vtkImageData* image,int plane=2,int level=0,int frame=0);
+  virtual void SetPlaneLevel(int plane,int level);
+  virtual void SetSpacingOrigin(double sp[3],double ori[3]);
+  virtual void SetLevel(int level);
+  
+  // Description:
+  // Snake Operations 
+  virtual int  DoSnake(int apply);
+  virtual int  DoExtract(int apply);
+
+  // Description:
+  // Callback Handlers for Clipboard Operations
+  virtual void CopySpline();
+  virtual void PasteSpline();
+  virtual void PasteFlipSpline();
+  virtual void CopyToUndoSpline();
+  virtual void UndoSpline();
+  virtual void UpdateControlsFromCurrentSpline();
+  virtual void FitSplineToCurrentControls();
+
+  //BTX
+  PXTkFrame* getBottomButtonFrame() { return bottomButtonFrame;}
+  //ETX
+
+
+  // Description:
+  // Enable/Disable Spline
+  virtual void EnableSpline(int i);
+  virtual void DisableSpline(int i);
+
+  // Description:
+  // Get Auto Update Mode
+  vtkGetMacro(AutoUpdateMode,int);
+
+  // Description:
+  // Clean Changed Status
+  virtual void SetChangedStatus(int index,int val);
+  virtual int  GetChangedStatus(int index);
+
+  // Description:
+  // Slave Mode i.e. not main program
+  vtkSetClampMacro(SlaveMode,int,0,1);
+  vtkGetMacro(SlaveMode,int);
+  vtkBooleanMacro(SlaveMode,int);
+
+
+  // Description:
+  // Default Scale Mode
+  vtkSetClampMacro(DefaultScaleMode,int,0,8);
+  vtkGetMacro(DefaultScaleMode,int);
+  
+  // Description:
+  // Default Smoothing 
+  vtkSetClampMacro(DefaultSmoothing,double,0.0001,10.0);
+  vtkGetMacro(DefaultSmoothing,double);
+
+  // Description:
+  // Show or not Ghost Controls
+  vtkSetClampMacro(ShowGhostControls,int,0,1);
+  vtkGetMacro(ShowGhostControls,int);
+
+protected:
+
+  vtkpxGUISplineControl();
+  virtual ~vtkpxGUISplineControl();
+
+  // Description:
+  // Splines for editing backup and pointer to current 
+  vtkpxSplineSource *currentSpline;
+  vtkpxSplineSource *splineSet[SP_MAX_COLLECTIONS];
+  vtkpxSplineSource *ghostSet[2][SP_MAX_COLLECTIONS];
+  vtkpxSplineSource *clipboardSpline;
+  vtkpxSplineSource *undoSpline;
+  vtkRenderer* Renderer;
+
+  // Description:
+  // Curve to display control points 
+  vtkpxBaseCurve    *editCurve;
+  vtkpxBaseCurve    *manualEditCurve;
+
+  // Description:
+  // vtkActors which capture curves/control points 
+  vtkActor*         splineActor[SP_MAX_COLLECTIONS];
+  vtkActor*         ghostActor[2][SP_MAX_COLLECTIONS];
+  vtkActor*         editActor;
+  vtkActor*         manualEditActor;
+
+  // Description:
+  // Gadgets/Widgets for Snakes
+  PXTkDialog*       snakeGUI;
+  PXTkArrowScale* snakeEdgeWeight;
+  PXTkArrowScale* snakeSmoothWeight;
+  PXTkArrowScale* snakeStep;
+  PXTkArrowScale* snakeSigma;
+  PXTkArrowScale* snakeIterations;
+
+  PXTkDialog*     extractGUI;
+  PXTkOptionMenu* extractType;
+  PXTkArrowScale* thresholdScale;
+  PXTkArrowScale* medianScale;
+  PXTkArrowScale* sigmaScale;
+  PXTkButton*     ExtractButton;
+ 
+
+  // Description:
+  // Gadgets/Widgets for Snakes
+  PXTkDialog*       resampleGUI;
+  PXTkArrowScale*   resampleNumberOfPoints;
+  PXTkArrowScale*   resampleSmoothing;
+  PXTkArrowScale*   resampleDs;
+  PXTkArrowScale*   resamplePreSmooth;
+  PXTkArrowScale*   resamplePreSmoothIterations;
+
+
+  // Description:
+  // Index of Current Spline and Number of Splines 
+  int             current_spline;
+  int             NumberOfSplines;
+
+  // Description:
+  // Visibility and Size (in units 0f 0.25 pixels) of all splines 
+  PXBool          display_mode[SP_MAX_COLLECTIONS];
+  int             scale_mode[SP_MAX_COLLECTIONS];
+  int             DefaultScaleMode;
+  int             spline_enabled[SP_MAX_COLLECTIONS];
+  int             manual_add_mode;
+  int             SlaveMode;
+  float           manual_zcoord;
+
+
+  // Description:
+  // Status Label
+  PXTkLabel*       message;
+
+  // Description:
+  // Options to select whether to show/hide controls mouse mode etc
+  PXTkCheckButton*  showControls;
+  PXTkCheckButton*  mouseMode;
+  PXTkCheckButton*  editMode;
+  PXTkCheckButton*  autoUpdate;
+  PXTkOptionMenu   *currentCollection;
+
+  // Description:
+  // Show/Hide Current Spline, size of current spline 
+  PXTkCheckButton  *displayMode;
+  PXTkOptionMenu   *scaleMode;
+  PXTkFrame        *bottomButtonFrame;
+  PXTkEntry        *thresholdEntry[2];
+  PXTkEntry        *SmoothingEntry;
+
+  // Description:
+  // Show Hide Ghost Splines (i.e. previous and next frames)
+  PXTkOptionMenu   *ghostMode;
+  int               ghost_displaymode;
+
+  // Description:
+  // Current Image and Energy map as well as image properties
+  vtkImageData    *image;
+  int             image_level;
+  int             image_frame;
+  double          image_range[2];
+  double          spacing[3];
+  double          origin[3];
+  double          DefaultSmoothing;
+  int             dimensions[3];
+  double           slice_offset;
+  int             AutoUpdateMode;
+  float           DistanceThreshold;
+  float           ControlPointScaleFactor;
+  int             changed[SP_MAX_COLLECTIONS];
+  int             ShowGhostControls;
+  
+
+  // Description:
+  // Callback Handlers for Changing Spline, Updating GUI and Loading Spline
+  virtual void SetCurrentCollection(int num);
+  virtual void LoadSpline(const char* fname);
+
+  // Description:
+  // Initialize Splines
+  virtual void InitializeSplines();
+
+
+  // Description:
+  // Following Needed to satisfy undefined calls
+  virtual void SetFrame(int) { } 
+  virtual void SetLookupTable (vtkLookupTable *) { }
+  virtual void SetTransform(vtkAbstractTransform *) { } 
+  virtual vtkAbstractTransform* GetTransform () { return NULL;}
+
+};
+
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUISplineEditor.cpp b/bioimagesuite30_src/GUI/vtkpxGUISplineEditor.cpp
new file mode 100644
index 0000000..da2fb65
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUISplineEditor.cpp
@@ -0,0 +1,320 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUISplineEditor.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:14 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxGUISplineEditor.h"
+#include "vtkObjectFactory.h"
+
+vtkpxGUISplineEditor* vtkpxGUISplineEditor::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUISplineEditor");
+  if(ret)
+      {
+	return (vtkpxGUISplineEditor*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUISplineEditor;
+}
+
+// Construct object with no children.
+vtkpxGUISplineEditor::vtkpxGUISplineEditor()
+{
+  single_slice_mode=PXTrue;
+  xy_slice_only=PXTrue;
+  this->NumberOfViewers=1;
+  this->NumberOfColumns=1;
+  this->NumberOfRows=1;
+  this->MaximumNumberOfViewers=1;
+
+  this->CreateHighlights=0;
+  this->SplineControl=NULL;
+  this->NumberOfSplines=4;
+  this->ColorMode=0;
+  this->CurrentSlice=-1;
+  this->ForceNoAutoUpdate=0;
+  this->sliceChangeCallbackName=NULL;
+  this->EnableSliceChangeCallback=1;
+  this->SlaveMode=0;
+  this->DefaultScaleMode=4;
+  this->EnableAutoUpdateModeCallback=1;
+}
+/* -------------------------------------------------------------------------*/
+vtkpxGUISplineEditor::~vtkpxGUISplineEditor()
+{
+  if (this->SplineControl)
+    this->SplineControl->Delete();
+
+  if (this->sliceChangeCallbackName!=NULL)
+    delete [] this->sliceChangeCallbackName;
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineEditor::SetNumberOfSplines(int a)
+{
+  if (this->Initialized==1)
+    return;
+  
+  this->NumberOfSplines=Irange(a,1,SP_MAX_COLLECTIONS);
+}
+
+/* -------------------------------------------------------------------------*/
+char* vtkpxGUISplineEditor::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+  
+  vtkpxGUIComponent::Initialize(name,inside);
+
+  PXTkFrame* manager=(PXTkFrame*)(this->EventManager->getMainWindow());
+
+  PXTkFrame* tframe=new PXTkFrame(this->EventManager,manager);
+  PXTkFrame* bframe=new PXTkFrame(this->EventManager,manager);
+
+  manager->setPackMode(PXTrue);
+  manager->addChildren("-side bottom -expand false -fill x",bframe);
+  manager->addChildren("-side top    -expand true  -fill both",tframe);
+
+  PXTkFrame* lframe=new PXTkFrame(this->EventManager,tframe);
+  PXTkFrame* rframe=new PXTkFrame(this->EventManager,tframe);
+  PXTkFrame* lframe2=new PXTkFrame(this->EventManager,bframe);
+  PXTkFrame* rframe2=new PXTkFrame(this->EventManager,bframe);
+
+
+  tframe->addChildren("-side right -expand false -fill y",rframe);
+  tframe->addChildren("-side left -expand true -fill both",lframe);
+
+
+  bframe->addChildren("-side right -expand false -fill y",rframe2);
+  bframe->addChildren("-side left -expand true -fill both",lframe2);
+
+  InitControls(lframe2,this->CreateHighlights);
+  this->ShowFrameControls(0);
+  InitViewer(lframe);
+
+
+  this->SplineControl=vtkpxGUISplineControl::New();
+  this->SplineControl->SetNumberOfSplines(this->NumberOfSplines);
+  this->SplineControl->SetSlaveMode(this->SlaveMode);
+  this->SplineControl->SetDefaultScaleMode(this->DefaultScaleMode);
+  this->SetEditor(this->SplineControl);
+  this->SetMouseToEditor(1);
+  if (this->EventParent!=NULL && this->CallbackNo>0)
+    this->SplineControl->SetCallback(this,800);
+  this->SplineControl->Initialize(rframe->getWidgetName(),1);
+     
+  if (!inside)
+    {
+      PXTkFrame* bottomButtonFrame=rframe2;
+      PXTkButton* closeB;
+      if (this->EventParent!=NULL || this->CallbackName!=NULL)
+	closeB=new PXTkButton(this->EventManager,bottomButtonFrame,"Close",3);
+      else
+	closeB=new PXTkButton(this->EventManager,bottomButtonFrame,"Exit",1);
+      bottomButtonFrame->addChildren("-side right -expand false -fill x -padx 10",closeB);
+    }
+
+  this->ShowFrameControls(0);
+
+  return GetWidgetName();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUISplineEditor::HandleEvent(int event)
+{
+  switch(event)
+    {
+    case 800:
+      if (this->EventParent!=NULL && this->CallbackNo>0)
+	this->EventParent->HandleEvent(CallbackNo+1);
+      else
+	if (this->CallbackName!=NULL)
+	  PXTkApp::executeTclCommand(this->CallbackName);
+      break;
+      
+    default:
+      vtkpxGUIMosaicViewer::HandleEvent(event);
+    }
+  
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineEditor::SetSlice(int sl)
+{
+  if (!hasImage)
+    return;
+
+  int dim[3];
+  currentImage->GetDimensions(dim);
+  
+  if (sl<0)
+    sl=dim[2]/2;
+  else
+    sl=Irange(sl,0,dim[2]-1);
+ 
+  int a=this->ForceNoAutoUpdate;
+  this->ForceNoAutoUpdate=1;
+  ChangeSliceIncrement(sl,-1,-1);
+  this->CurrentSlice=vtkpxGUIMosaicViewer::GetBeginSlice();
+  this->ForceNoAutoUpdate=a;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUISplineEditor::IsAutoUpdateModeEnabled()
+{
+
+  if (this->SplineControl->GetAutoUpdateMode()==1 && this->ForceNoAutoUpdate==0)
+    return 1;
+  
+  return 0;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineEditor::ChangeSliceIncrement(int sl,int incr,int fr)
+{
+
+  if (this->SplineControl!=NULL)
+    {
+      if (this->IsAutoUpdateModeEnabled()==1  && this->EnableAutoUpdateModeCallback==1)
+	{
+	  this->HandleEvent(800);
+	}
+    }
+
+  this->CurrentSlice=vtkpxGUIMosaicViewer::GetBeginSlice();
+  vtkpxGUIMosaicViewer::ChangeSliceIncrement(sl,incr,fr);
+  PXTkApp::executeTclCommand("update idletasks");
+
+  char line[300];
+  sprintf(line,"SplineEditor Slice=%d Frame=%d",
+	  this->GetBeginSlice(),this->GetCurrentFrame()+1);
+  this->EventManager->setTitle(line);
+
+  this->ExecuteSliceChangeCallback();
+}
+/* -------------------------------------------------------------------------*/
+// Description:
+// Enable/Disable Spline
+void vtkpxGUISplineEditor::EnableSpline(int i)
+{
+  if (this->SplineControl==NULL)
+    return;
+  this->SplineControl->EnableSpline(i);
+}
+
+void vtkpxGUISplineEditor::DisableSpline(int i)
+{
+ if (this->SplineControl==NULL)
+   return;
+ this->SplineControl->DisableSpline(i);
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUISplineEditor::GetBeginSlice()
+{
+  if (this->CurrentSlice==-1)
+    this->CurrentSlice=vtkpxGUIMosaicViewer::GetBeginSlice();
+  return this->CurrentSlice;
+}
+
+int vtkpxGUISplineEditor::ResetViewer()
+{
+  if (this->Orientation==3)
+    this->Orientation=1;
+  return vtkpxGUIMosaicViewer::ResetViewer();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineEditor::CreateSnake()
+{
+  if (this->SplineControl!=NULL)
+    this->SplineControl->DoSnake(1);
+}
+
+void vtkpxGUISplineEditor::UpdateSnake()
+{
+  if (this->SplineControl!=NULL)
+    this->SplineControl->DoSnake(2);
+
+}
+
+void vtkpxGUISplineEditor::CopyCallback()
+{
+  if (this->SplineControl!=NULL)
+    this->SplineControl->CopySpline();
+}
+
+void vtkpxGUISplineEditor::PasteCallback()
+{
+  if (this->SplineControl!=NULL)
+    this->SplineControl->PasteSpline();
+}
+
+void vtkpxGUISplineEditor::SetSliceChangeCallback(const char* name)
+{
+  if (name==NULL)
+    return;
+
+  if (this->sliceChangeCallbackName!=NULL)
+    delete [] this->sliceChangeCallbackName;
+
+  this->sliceChangeCallbackName=new char[strlen(name)+1];
+  strcpy(this->sliceChangeCallbackName,name);
+}
+
+void  vtkpxGUISplineEditor::ExecuteSliceChangeCallback()
+{
+  if (this->EnableSliceChangeCallback==0 || this->sliceChangeCallbackName==NULL)
+    return;
+
+  PXTkApp::executeTclCommand(this->sliceChangeCallbackName);
+
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUISplineEditor.h b/bioimagesuite30_src/GUI/vtkpxGUISplineEditor.h
new file mode 100644
index 0000000..8d38352
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUISplineEditor.h
@@ -0,0 +1,174 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUISplineEditor.h,v $
+  Language:  C++
+  Date:      $Date: 2002/12/18 16:11:33 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUISplineEditor 
+// .SECTION Description
+
+#ifndef __vtkpxGUISplineEditor_h
+#define __vtkpxGUISplineEditor_h
+
+#include "vtkpxGUIMosaicViewer.h"
+#include "vtkpxGUISplineControl.h"
+#include "vtkpxGUIBaseCurveControl.h"
+const int CSE_MAX_STACKS=50;
+
+class  vtkpxGUISplineEditor : public vtkpxGUIMosaicViewer {
+  
+public:
+
+  static vtkpxGUISplineEditor *New();
+  vtkTypeMacro(vtkpxGUISplineEditor,vtkpxGUIMosaicViewer);
+  
+  // Description:
+  // Initialize Display  
+  virtual char*  Initialize(const char* name,int inside);
+
+  // Description:
+  // Handle Events
+  virtual int  HandleEvent(int eventno);
+
+  // Description:
+  // Set/Get Number Of Splines 
+  virtual void SetNumberOfSplines(int a);
+  vtkGetMacro(NumberOfSplines,int);
+
+  // Description:
+  // Get Spline Control Editor 
+  vtkGetObjectMacro(SplineControl,vtkpxGUISplineControl);
+
+  // Set Slice 
+  void SetSlice(int sl=-1);
+
+  // Description:
+  // Set Slice Increment, Frame 
+  virtual void ChangeSliceIncrement(int sl=-1,int incr=-1,int fr=-1);
+
+  // Description:
+  // Enable/Disable Spline
+  void EnableSpline(int i);
+  void DisableSpline(int i);
+
+  // Description:
+  // Get Current Slice
+  virtual int GetBeginSlice();
+
+  // Description:
+  // Automation Interface
+  virtual void CreateSnake();
+  virtual void UpdateSnake();
+  virtual void CopyCallback();
+  virtual void PasteCallback();
+
+  // Description:
+  // Keep Auto Update Off
+  vtkSetMacro(ForceNoAutoUpdate,int);
+  vtkGetMacro(ForceNoAutoUpdate,int);
+
+  // Description:
+  // Slave Mode i.e. not main program
+  vtkSetClampMacro(SlaveMode,int,0,1);
+  vtkGetMacro(SlaveMode,int);
+  vtkBooleanMacro(SlaveMode,int);
+
+  // Description:
+  // Default Scale Mode
+  vtkSetClampMacro(DefaultScaleMode,int,0,8);
+  vtkGetMacro(DefaultScaleMode,int);
+
+
+  // Description;
+  // Slice Changed Callback 
+  virtual void   SetSliceChangeCallback(const char* CallbackName);
+  vtkGetMacro(EnableSliceChangeCallback,int);
+  vtkSetClampMacro(EnableSliceChangeCallback,int,0,1);
+  virtual void  ExecuteSliceChangeCallback();
+
+  // Descrpition:
+  // DisableAutoUpdateCallback() -- disables autoupdate callback for 4D editors
+  vtkSetClampMacro(EnableAutoUpdateModeCallback,int,0,1);
+  vtkGetMacro(EnableAutoUpdateModeCallback,int);
+  vtkBooleanMacro(EnableAutoUpdateModeCallback,int);
+
+  // Description:
+  // Is AutoUpdateMode Enabled
+  virtual int IsAutoUpdateModeEnabled();
+
+protected:
+
+  vtkpxGUISplineEditor();
+  virtual ~vtkpxGUISplineEditor();
+
+  vtkpxGUISplineControl* SplineControl;
+
+
+  virtual int  ResetViewer();
+
+  int NumberOfSplines;
+  int CurrentSlice;
+  int ForceNoAutoUpdate;
+  int SlaveMode;
+  int EnableAutoUpdateModeCallback;
+
+
+  char*                   sliceChangeCallbackName; 
+  int                     EnableSliceChangeCallback;
+  int                     DefaultScaleMode;
+
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUISplineStackControl.cpp b/bioimagesuite30_src/GUI/vtkpxGUISplineStackControl.cpp
new file mode 100644
index 0000000..2bc242d
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUISplineStackControl.cpp
@@ -0,0 +1,1047 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// 	$Id: vtkpxGUISplineStackControl.cpp,v 1.4 2003/11/13 17:56:57 xenios Exp xenios $	
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkpxGUISplineStackControl.h"
+#include "vtkpxUtil.h"
+#include "vtkActor.h"
+#include "vtkAssembly.h"
+#include "vtkRenderer.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxImageExtract.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkImageData.h"
+#include "vtkProperty.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkpxGUIBaseImageViewer.h"
+#include "pxfpbsplinestack.h"
+/* -------------------------------------------------------------------------*/
+vtkpxGUISplineStackControl* vtkpxGUISplineStackControl::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUISplineStackControl");
+  if(ret)
+      {
+	return (vtkpxGUISplineStackControl*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUISplineStackControl;
+}
+
+// ----------------------------------------------------------------------------
+vtkpxGUISplineStackControl::vtkpxGUISplineStackControl()
+{
+  this->optionDialog=NULL;
+  this->CurrentFrame=0;
+
+  this->NumberOfSplineStacks=50;
+  {
+    for (int ia=0;ia<=2;ia++)
+      {
+	this->origin[ia]=0.0;
+	this->spacing[ia]=1.0;
+	this->dimensions[ia]=50;
+      }
+  }
+  this->orientation=0;
+  
+  for (int i=0;i<this->NumberOfSplineStacks;i++)
+    {
+      splineStackSet[i]=NULL;
+      for (int j=0;j<SSP_MAX_RENDERERS;j++)
+	splineStackActor[j][i]=NULL;
+      
+      if (i==0)
+	display_mode[i]=1;
+      else
+	display_mode[i]=0;
+    }
+
+  for (int j=0;j<SSP_MAX_RENDERERS;j++)
+    this->Renderer[j]=NULL;
+
+  for (int ia=0;ia<SSP_MAX_COLLECTIONS;ia++)
+    {
+      surface_filename[ia]=new char[20];
+      sprintf(surface_filename[ia],"unnamed_%d",ia+1);
+      surface_modified[ia]=0;
+    }
+
+
+  
+  current_splinestack=0;
+  this->currentSplineStack=NULL;
+
+  clipboardSplineStack=NULL;
+  image=NULL;
+  this->SplineEditor=NULL;
+  this->BlockEditorCallback=0;
+
+  this->defaultsmoothing=5.0;
+  char* line=PXTkApp::getTclVariable("pxtcl_pref_array(SplineSmoothing)");
+  if (line!=NULL)
+    {
+      this->defaultsmoothing=Frange(atof(line),0.1,10.0);
+    }
+
+}
+// ----------------------------------------------------------------------------
+vtkpxGUISplineStackControl::~vtkpxGUISplineStackControl()
+{
+  
+  if (clipboardSplineStack!=NULL)
+    clipboardSplineStack->Delete();
+
+  
+  for (int i=0;i<this->NumberOfSplineStacks;i++)
+    {
+      if (splineStackSet[i]!=NULL)
+	splineStackSet[i]->Delete();
+      for (int j=0;j<SSP_MAX_RENDERERS;j++)
+	if (splineStackActor[j][i]!=NULL)
+	  splineStackActor[j][i]->Delete();
+    }
+
+  if (this->image!=NULL)
+    this->image->Delete();
+
+  for (int ia=0;ia<SSP_MAX_COLLECTIONS;ia++)
+    delete [] surface_filename[ia];
+
+    
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::SetNumberOfSplineStacks(int a)
+{
+  if (this->Initialized==1)
+    return;
+
+  this->NumberOfSplineStacks=Irange(a,1,SSP_MAX_COLLECTIONS);
+}
+// ----------------------------------------------------------------------------
+void vtkpxGUISplineStackControl::SetSplineEditor(vtkpxGUISplineEditor* splineControl)
+{
+  this->SplineEditor=splineControl;
+  if (this->SplineEditor!=NULL)
+    {
+      this->SplineEditor->SetNumberOfSplines(this->NumberOfSplineStacks);
+      this->SplineEditor->SetCallback(this,700);
+    }
+}
+// ----------------------------------------------------------------------------
+void vtkpxGUISplineStackControl::InitializeSplineStacks()
+{
+
+  for (int i=0;i<this->NumberOfSplineStacks;i++)
+    {
+      splineStackSet[i]=vtkpxSplineStackSource::New();
+      //      fprintf(stderr,"Init Spline Stacks Setting Elliptical Cylinder i=%d, %.2f\n",i,this->spacing[2]);
+      splineStackSet[i]->SetEllipticalCylinder(8,
+					       this->dimensions[2],
+					       spacing[0]*dimensions[0]/(2.00*this->NumberOfSplineStacks)*(1.0+i),
+					       spacing[1]*dimensions[1]/(2.00*this->NumberOfSplineStacks)*(1.0+i),
+					       origin[0]+spacing[0]*dimensions[0]/2.0,
+					       origin[1]+spacing[1]*dimensions[1]/2.0,
+					       this->spacing[2],
+					       this->origin[2]);
+      splineStackSet[i]->SetDrawMode(0);
+      surface_modified[i]=0;
+    }
+
+  
+  current_splinestack=0;
+  currentSplineStack=splineStackSet[current_splinestack];
+
+  clipboardSplineStack=vtkpxSplineStackSource::New();
+  clipboardSplineStack->Copy(currentSplineStack);
+
+}
+/* -------------------------------------------------------------------------*/
+char* vtkpxGUISplineStackControl::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+
+  InitializeSplineStacks();
+
+  vtkpxGUIComponent::Initialize(name,inside);
+  PXTkFrame* mFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+  this->controlFrame=new PXTkFrame(this->EventManager,mFrame);
+  mFrame->addChildren("-side top -expand t -fill x -padx 0 -pady 2",this->controlFrame);
+
+  // Control Properties
+  // ---------------------
+  PXTkLabelFrame* vFrame=new PXTkLabelFrame(this->EventManager,this->controlFrame,"Global Properties");
+  this->controlFrame->addChildren("-side top -expand false -fill x -padx 0 -pady 5",vFrame);
+  vFrame->setPackMode(PXFalse);
+ 
+  PXTkButton* b0a=new PXTkButton(this->EventManager,vFrame,"Show All",506);
+  PXTkButton* b0b=new PXTkButton(this->EventManager,vFrame,"Hide All",505);
+  vFrame->gridRowColumnChild(b0a,1,0);
+  vFrame->gridRowColumnChild(b0b,1,1);
+  
+  // Collection Properties 
+  // ---------------------
+  PXTkLabelFrame* pFrame=new PXTkLabelFrame(this->EventManager,this->controlFrame,"Spline Stack Properties");
+  this->controlFrame->addChildren("-side top -expand t -fill both -padx 0 -pady 2",pFrame);
+
+  PXTkFrame* pfr0=new PXTkFrame(this->EventManager,pFrame);
+  PXTkFrame* pfr05=new PXTkFrame(this->EventManager,pFrame);
+  PXTkFrame* pfr1=new PXTkFrame(this->EventManager,pFrame);
+  PXTkFrame* pfr2=new PXTkFrame(this->EventManager,pFrame);  
+  pFrame->addChildren("-side top -pady 1 -expand t -fill x",pfr0,pfr05,pfr1,pfr2);
+
+
+  PXTkLabel* labs=new PXTkLabel(this->EventManager,pfr0,"Current Stack:");
+  currentCollection=new PXTkOptionMenu(this->EventManager,pfr0,"Stack 1",500);
+  for (int ip=1;ip<this->NumberOfSplineStacks;ip++)
+    {
+      sprintf(pxtk_buffer4,"Stack %d",ip+1);
+      currentCollection->addOption(pxtk_buffer4);
+    }
+  currentCollection->setIndex(current_splinestack);
+  pfr0->addChildren("-side left -expand t -fill x",labs,currentCollection);
+
+  PXTkLabel* labd=new PXTkLabel(this->EventManager,pfr1,"Display Mode:");
+  displayMode=new PXTkOptionMenu(this->EventManager,pfr1,"Hide",501);
+  displayMode->addOption("Fast Surface");
+  displayMode->addOption("Full Surface");
+  displayMode->setIndex(display_mode[current_splinestack]);
+  pfr0->addChildren("-side left -expand t -fill x",labd,displayMode);
+
+  PXTkLabel* labd5=new PXTkLabel(this->EventManager,pfr05,"Draw Mode:");
+  drawMode=new PXTkOptionMenu(this->EventManager,pfr05,"Open Surface",501);
+  drawMode->addOption("Bottom Closed");
+  drawMode->addOption("Top Closed");
+  drawMode->addOption("Both Closed");
+  drawMode->setIndex(0);
+  pfr05->addChildren("-side left -expand t -fill x",labd5,drawMode);
+
+  for (int i=0;i<=1;i++)
+    {
+      if (i==0)
+	trimScale[i]=new PXTkArrowScale(this->EventManager,pfr2,"Bot Trim",502,PXTrue);
+      else
+	trimScale[i]=new PXTkArrowScale(this->EventManager,pfr2,"Top Trim",503,PXTrue);
+      trimScale[i]->setRange(0,this->dimensions[2]-1);
+      trimScale[i]->setIncrement(1);
+      trimScale[i]->setResolution(1.0);
+      trimScale[i]->setDecimalPoints(0);
+      trimScale[i]->setLengthWidth(55,8);
+      pfr2->addChildren("-side left -expand t -fill x",trimScale[i]->getMainWindow());
+    }
+  trimScale[0]->setValue(0);
+  trimScale[1]->setValue(dimensions[2]-1);
+
+
+  // Collection Operations 
+  // ---------------------
+  PXTkLabelFrame* oFrame=new PXTkLabelFrame(this->EventManager,this->controlFrame,"Operations on Current Stack");
+  this->controlFrame->addChildren("-side top -expand t -fill both -padx 1 -pady 1",oFrame);
+
+
+  PXTkFrame* topfr=new PXTkFrame(this->EventManager,oFrame);
+  PXTkFrame* midfr=new PXTkFrame(this->EventManager,oFrame);
+  PXTkFrame* midfr2=new PXTkFrame(this->EventManager,oFrame);
+  PXTkFrame* midfr3=new PXTkFrame(this->EventManager,oFrame);
+
+  PXTkFrame* botfr=new PXTkFrame(this->EventManager,oFrame);  
+  PXTkFrame* botfr2=new PXTkFrame(this->EventManager,oFrame);  
+  oFrame->addChildren("-side top -pady 1 -expand t -fill x",topfr,midfr,midfr2,midfr3);
+  oFrame->addChildren("-side top -pady 1 -expand t -fill x",botfr,botfr2);
+  
+
+  PXTkButton* but3=new PXTkButton(this->EventManager,topfr,"x0.5",600);
+  PXTkButton* but4=new PXTkButton(this->EventManager,topfr,"x0.8",601);
+  PXTkButton* but4a=new PXTkButton(this->EventManager,topfr,"x1.25",602);
+  PXTkButton* but4b=new PXTkButton(this->EventManager,topfr,"x2",603);
+  PXTkButton* but4c=new PXTkButton(this->EventManager,topfr,"s2",604);
+  PXTkButton* but4d=new PXTkButton(this->EventManager,topfr,"s5",605);
+  PXTkButton* but4e=new PXTkButton(this->EventManager,topfr,"FlipX",606);
+
+  but3->configure("-padx",2);
+  but4->configure("-padx",2);
+  but4a->configure("-padx",2);
+  but4b->configure("-padx",2);
+  but4c->configure("-padx",2);
+  but4d->configure("-padx",2);
+  topfr->addChildren("-side right ",but4e);
+  topfr->addChildren("-side left ",but3,but4,but4a);
+  topfr->addChildren("-side left ",but4b,but4c,but4d);
+
+  
+
+  PXTkButton* but6=new PXTkButton(this->EventManager,midfr,"Color",450);
+  PXTkButton* but5=new PXTkButton(this->EventManager,midfr,"Cylinder",452);
+
+  but5->configure("-padx",0);
+  but6->configure("-padx",0);
+  if (strcmp(this->GetClassName(),"vtkpxGUI4DSplineStackControl")!=0)
+    midfr->addChildren("-side left -padx 1 -expand t -fill x",but6,but5);
+  else
+    midfr->addChildren("-side left -padx 1 -expand t -fill x",but6);
+
+  PXTkButton* bbut5=new PXTkButton(this->EventManager,midfr2,"Volume",453);
+  bbut5->configure("-padx",0);
+  midfr2->addChildren("-side left -padx 1 -expand t -fill x",bbut5);
+
+  PXTkButton* bbut6=new PXTkButton(this->EventManager,midfr3,"VOI Prop",454);
+  bbut6->configure("-padx",0);
+  for (int j=0;j<=1;j++)
+    {
+      thresholdEntry[j]=new PXTkEntry(this->EventManager,midfr3);
+      thresholdEntry[j]->configure("-width",6);
+      thresholdEntry[j]->setText("0.1");
+    }
+  thresholdEntry[1]->setText("50.0");
+  midfr3->addChildren("-side left -padx 1 -expand t -fill x",bbut6,thresholdEntry[0],thresholdEntry[1]);
+
+  if (strcmp(this->GetClassName(),"vtkpxGUI4DSplineStackControl")!=0)
+    {
+      PXTkButton* but1=new PXTkButton(this->EventManager,botfr,"Load",401);
+      PXTkButton* but2=new PXTkButton(this->EventManager,botfr,"Save",402);
+      
+      but1->configure("-padx",0);
+      but2->configure("-padx",0);
+      botfr->addChildren("-side left -padx 1 -expand t -fill x",but1,but2);
+    }
+
+  PXTkButton* cp=new PXTkButton(this->EventManager,botfr2,"Copy",590);
+  PXTkButton* pt=new PXTkButton(this->EventManager,botfr2,"Paste",591);
+  cp->configure("-padx",0);
+  pt->configure("-padx",0);
+  botfr2->addChildren("-side left -padx 1 -expand t -fill x",cp,pt);
+
+
+
+  if (!inside)
+    {
+      PXTkButton* closeB;
+      if (this->EventParent)
+	closeB=new PXTkButton(this->EventManager,this->controlFrame,"Close",3);
+      else
+	closeB=new PXTkButton(this->EventManager,this->controlFrame,"Exit",1);
+      this->controlFrame->addChildren("-side bottom -expand false -fill x -padx 2",closeB);
+    }
+
+  if ( (this->EventParent!=NULL && this->CallbackNo>0) || ( this->CallbackName!=NULL ))
+    {
+      PXTkButton* updB=new PXTkButton(this->EventManager,this->controlFrame,"Update",614);
+      this->controlFrame->addChildren("-side top -padx 2 -expand t -fill x",updB);
+    }
+
+  if (this->optionDialog==NULL)
+    this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,10);
+
+
+  // Other Stuff 
+  return GetWidgetName();
+}
+
+/* -------------------------------------------------------------------------*/ 
+void vtkpxGUISplineStackControl::SetRenderer(vtkRenderer* ren,int index)
+{
+  this->SetRenderer(ren,index,0);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::SetRenderer(vtkRenderer *ren,int index,int wireframe)
+{
+  index=Irange(index,0,SSP_MAX_RENDERERS-1);
+
+  if (this->Renderer[index]!=NULL)
+    return;
+
+  for (int i=0;i<this->NumberOfSplineStacks;i++)
+    {
+      double c[3]; vtkpxSurfaceUtil::GetColor(i,c);
+      if (splineStackActor[index][i]==NULL)
+	{
+	  vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+	  map->SetInput(splineStackSet[i]->GetOutput());
+	  
+	  splineStackActor[index][i]=vtkActor::New();
+	  splineStackActor[index][i]->SetMapper(map);
+	  if (display_mode[i]!=0)
+	    splineStackActor[index][i]->SetVisibility(1);
+	  else
+	    splineStackActor[index][i]->SetVisibility(0);
+	  
+	  if (wireframe>0)
+	    {
+	      splineStackActor[index][i]->GetProperty()->SetRepresentationToWireframe();
+	      splineStackActor[index][i]->GetProperty()->SetLineWidth(2.0);
+	      splineStackActor[index][i]->GetProperty()->SetAmbient(1.0);
+	      splineStackActor[index][i]->GetProperty()->SetDiffuse(0.0);
+	      splineStackActor[index][i]->GetProperty()->SetSpecular(0.0);
+	    } 
+	  
+	  
+	  splineStackActor[index][i]->GetProperty()->SetColor(c);
+	  map->Delete();
+	}
+      ren->AddActor(splineStackActor[index][i]);
+    }
+  
+  this->Renderer[index]=ren;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::Update()
+{
+  if (this->splineStackActor[0]==NULL)
+      return;
+
+  for (int j=0;j<SSP_MAX_RENDERERS;j++)
+    {
+      if (this->Renderer[j]!=NULL)
+	{
+	  for (int i=0;i<this->NumberOfSplineStacks;i++)
+	    {
+	      if (display_mode[i])
+		splineStackActor[j][i]->SetVisibility(1);
+	      else
+		splineStackActor[j][i]->SetVisibility(0);
+	    }
+	}
+    }
+
+  // Curve Stuff 
+  UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::UpdateDisplay()
+{
+  if (this->Renderer[0]!=NULL)
+    this->Renderer[0]->GetRenderWindow()->Render();
+
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::UpdateAfterExternalEditing()
+{
+  this->UpdateControlsFromCurrentSplineStack();
+}
+/* -------------------------------------------------------------------------*/
+
+
+int  vtkpxGUISplineStackControl::HandleEvent(int event)
+{
+  if (!this->Initialized)
+      return TCL_OK;
+
+  if (event<10)
+      return this->EventManager->handleDirectEvent(event);
+
+  if (this->currentSplineStack==NULL)
+    return TCL_OK;
+
+
+  int updateeditor=this->HandleEventSecond(event);
+
+  if (this->BlockEditorCallback==0 && (updateeditor==1 || event== 700))
+    {
+      //      fprintf(stderr,"Calling Update Spline Editor %s\n",this->GetClassName());
+      this->UpdateSplineEditor();
+    }
+
+  UpdateDisplay();
+
+  return TCL_OK;
+
+}
+  
+
+int  vtkpxGUISplineStackControl::HandleEventSecond(int event)
+{
+  int updateeditor=0;
+
+  switch(event)
+      {
+      case 401:
+	{
+	  int ok=this->EventManager->questionBox("Loading will delete your old splinestack. Are you sure?");
+	  if (ok)
+	      {
+		char* line=this->EventManager->getOpenFilename("Load splinestacks","SplineStacks","*.sur");
+		if (line!=NULL)
+		    {
+		      if (strlen(line)>0)
+			{
+			  char newline[400]; strncpy(newline,line,400); 
+			  //			  fprintf(stderr,"Loading from %s\n",newline);
+			  LoadSplineStack(newline);
+			}
+		      updateeditor=1;
+		    }
+	      }
+	}
+	break;
+	
+      case 402:
+	{
+	  sprintf(pxtk_buffer,"%s",surface_filename[current_splinestack]);
+	  //	  fprintf(stderr,"Old filename = %s\n",surface_filename[current_splinestack]);
+	  char* line=this->EventManager->getSaveFilename("Save SplineStacks",pxtk_buffer,"SplineStacks","*.sur");
+	  if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		  {
+		    char newline[400];
+		    strncpy(newline,line,400);
+		    SaveSplineStack(newline);
+		  }
+	      }
+	}
+	break;
+  	
+      case 450:
+	if (splineStackActor[0][current_splinestack]!=NULL)
+	  {
+	    double c[3];
+	    splineStackActor[0][current_splinestack]->GetProperty()->GetColor(c);
+	    int a=this->EventManager->d_colorBox("SplineStack Color",c[0],c[1],c[2]);
+	    if (a==1)
+		this->SetItemColor(current_splinestack,c);
+	  }
+	break;
+	
+
+      case 452: // Ellipse
+	currentSplineStack->SetEllipticalCylinder(8,
+						  dimensions[2],
+						  spacing[0]*float(dimensions[0])/(2.00*this->NumberOfSplineStacks)*(1.0+current_splinestack),
+						  spacing[1]*float(dimensions[1])/(2.00*this->NumberOfSplineStacks)*(1.0+current_splinestack),
+						  origin[0]+spacing[0]*dimensions[0]/2.0,
+						  origin[1]+spacing[1]*dimensions[1]/2.0,
+						  spacing[2],
+						  origin[2]);
+	surface_modified[current_splinestack]=0;
+	currentSplineStack->SetDrawMode(0);
+	updateeditor=1;
+	this->UpdateAfterExternalEditing();
+	sprintf(pxtk_buffer2,"CStack");
+	this->SetItemFilename(current_splinestack,pxtk_buffer2);
+	break;
+	  
+      case 453:
+	this->WatchOn();
+	sprintf(pxtk_buffer,"Stack %d Volume=%8.1f mm^3\n",current_splinestack+1,currentSplineStack->GetVolume());
+	PXTkApp::printToConsole(pxtk_buffer);
+	this->EventManager->messageBox(pxtk_buffer,"Stack Volume ...");
+	this->WatchOff();
+	break;
+
+      case 454:
+	this->ComputeVOIProperties(0);
+	break;
+	
+      case 500:
+	SetCurrentCollection(currentCollection->getIndex());
+	break;
+	
+      case 501:
+	display_mode[current_splinestack]=displayMode->getIndex();
+	currentSplineStack->SetDrawMode(drawMode->getIndex());
+	if (display_mode[current_splinestack]==1 && currentSplineStack->GetWholeSurface()==1)
+	  currentSplineStack->SetWholeSurface(0);
+	if (display_mode[current_splinestack]==2 && currentSplineStack->GetWholeSurface()==0)
+	  currentSplineStack->SetWholeSurface(1);
+	Update();
+	break;
+
+      case 502: // Trim Bottom
+	currentSplineStack->SetTrimBottom((int)trimScale[0]->getValue());
+	trimScale[0]->setValue(currentSplineStack->GetTrimBottom());
+	surface_modified[current_splinestack]=1;
+	Update();
+	break;
+
+      case 503:
+	currentSplineStack->SetTrimTop((int)trimScale[1]->getValue());
+	trimScale[1]->setValue(currentSplineStack->GetTrimTop());
+	surface_modified[current_splinestack]=1;
+	Update();
+	break;
+
+      case 505:
+	{
+	  for  (int i=0;i<this->NumberOfSplineStacks;i++)
+	    display_mode[i]=0;
+	  displayMode->setIndex(0);
+	}
+	Update();
+	break;
+
+	
+      case 506:
+	{
+	  for  (int i=0;i<this->NumberOfSplineStacks;i++)
+	    display_mode[i]=2;
+	  displayMode->setIndex(2);
+	}
+	Update();
+	break;
+
+	
+      case 600: // x0.5
+	currentSplineStack->ChangeSpacing(this->defaultsmoothing,0.5);
+	updateeditor=1;
+	this->UpdateAfterExternalEditing();
+	break;
+
+      case 601: // x0.8
+	currentSplineStack->ChangeSpacing(this->defaultsmoothing,0.8);
+	updateeditor=1;
+	this->UpdateAfterExternalEditing();
+	break;
+
+      case 602: // x1.25
+	currentSplineStack->ChangeSpacing(this->defaultsmoothing,1.25);
+	updateeditor=1;
+	this->UpdateAfterExternalEditing();
+	break;
+
+      case 603: // x2.0
+	currentSplineStack->ChangeSpacing(this->defaultsmoothing,2.0);
+	updateeditor=1;
+	this->UpdateAfterExternalEditing();
+	break;
+
+      case 604: // s1.0
+	currentSplineStack->ChangeSpacing(this->defaultsmoothing,-1.0);
+	updateeditor=1;
+	this->UpdateAfterExternalEditing();
+	break;
+
+      case 605: // s5.0
+	currentSplineStack->ChangeSpacing(2.0,-1.0);
+	updateeditor=1;
+	this->UpdateAfterExternalEditing();
+	break;
+
+      case 606:
+	{
+	  int ok=currentSplineStack->FlipX(this->image);
+	  if (ok>0)
+	    {
+	      updateeditor=1;
+	      this->UpdateAfterExternalEditing();
+	    }
+	}
+	break;
+
+      case 590:
+	this->CopySplineStack();
+	break;
+	
+      case 591:
+	this->PasteSplineStack();
+	surface_modified[current_splinestack]=1;
+	updateeditor=1;
+	break;
+
+
+      case 614:
+	if (this->EventParent!=NULL && this->CallbackNo>0)
+	  this->EventParent->HandleEvent(CallbackNo);
+	else
+	  if (this->CallbackName!=NULL)
+	    PXTkApp::executeTclCommand(this->CallbackName);
+	break;
+
+      case 701:
+	if (this->BlockEditorCallback==0)
+	  this->UpdateFromSplineEditor();
+	break;
+      }
+
+
+  return updateeditor;
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::SetItemColor(int index,double color[3])
+{
+  for (int j=0;j<SSP_MAX_RENDERERS;j++)
+    {
+      if (splineStackActor[j][index]!=NULL)
+	splineStackActor[j][index]->GetProperty()->SetColor(color);
+
+      this->SplineEditor->GetSplineControl()->SetItemColor(index,color);
+    }
+
+}
+// -------------------------------------------------------------------------
+void vtkpxGUISplineStackControl::SetItemFilename(int index,const char* s)
+{
+  //  fprintf(stderr,"Here SetFileName GUISPlineControl\n");
+  delete surface_filename[index];
+  surface_filename[index]=new char[strlen(s)+1];
+  strcpy(surface_filename[index],s);
+
+  if (this->Initialized==1)
+    {
+      strcpy(pxtk_buffer4,s);
+      sprintf(pxtk_buffer4,"%s.%d",PXTkApp::getFilenameTail(pxtk_buffer4),index+1);
+      currentCollection->changeLabel(index,pxtk_buffer4);
+    }
+  //  fprintf(stderr,"Setting Filename of %d = %s\n",index,s);
+  this->SplineEditor->GetSplineControl()->SetItemFilename(index,surface_filename[index]);
+}
+// -------------------------------------------------------------------------
+void vtkpxGUISplineStackControl::CopySplineStack()
+{
+  clipboardSplineStack->Copy(currentSplineStack);
+}
+
+void vtkpxGUISplineStackControl::PasteSplineStack()	
+{
+    SetSplineStack(clipboardSplineStack,-1);
+}
+/* -------------------------------------------------------------------------*/
+vtkpxSplineStackSource* vtkpxGUISplineStackControl::GetSplineStack(int index)
+{
+  if (index==-1)
+      index=current_splinestack;
+
+  return splineStackSet[Irange(index,0,this->NumberOfSplineStacks-1)];
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUISplineStackControl::GetCurrentIndex()
+{
+  return current_splinestack;
+}
+
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::SetSplineStack(vtkpxSplineStackSource* land,int index)
+{
+  if (index==-1)
+      index=current_splinestack;
+
+  index=Irange(index,0,this->NumberOfSplineStacks-1);
+
+  splineStackSet[index]->Copy(land);
+  
+  if (index==current_splinestack)
+    this->UpdateAfterExternalEditing();
+    
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::SetImage(vtkImageData* img,int orient,int lv,int fr)
+{
+  if (img!=NULL)
+    {
+      if (this->image!=NULL)
+	this->image->Delete();
+      this->image=vtkImageData::New();
+      this->image->ShallowCopy(img);
+      this->orientation=vtkpxGUIBaseImageViewer::MapOrientationToOldStyle(orient);
+      
+      int d[3]; double sp[3],ori[3];
+      this->image->GetSpacing(sp);
+      this->image->GetOrigin(ori);
+      this->image->GetDimensions(d);
+      
+      float sum=0.0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=
+	  fabs(float(d[ia]-this->dimensions[ia]))+
+	  fabs(sp[ia]-this->spacing[ia])+
+	  fabs(ori[ia]-this->origin[ia]);
+      
+        if ( (splineStackSet[0]->GetPolarMode()==0 && this->orientation==3) || 
+	     (splineStackSet[0]->GetPolarMode()==1 && this->orientation!=3))
+       sum=1.0;
+
+
+
+      if (sum>0.01)
+	{
+	  this->image->GetOrigin(this->origin);
+	  this->image->GetSpacing(this->spacing);
+	  this->image->GetDimensions(this->dimensions);
+	  
+	  for (int i=0;i<this->NumberOfSplineStacks;i++)
+	    {
+	      //	      fprintf(stderr,"New Image::Set Elliptical Cylinder %d spa=%.2f\n",i,this->spacing[2]);
+	      if (this->orientation==3)
+		splineStackSet[i]->SetPolarMode(1);
+	      else
+		splineStackSet[i]->SetPolarMode(0);
+			      
+	      surface_modified[i]=0;
+	      splineStackSet[i]->SetEllipticalCylinder(8,
+						       this->dimensions[2],
+						       spacing[0]*dimensions[0]/8.0*(1.0+i),
+						       spacing[1]*dimensions[1]/8.0*(1.0+i),
+						       origin[0]+spacing[0]*dimensions[0]/2.0,
+						       origin[1]+spacing[1]*dimensions[1]/2.0,
+						       this->spacing[2],
+						       this->origin[2]);
+	      splineStackSet[i]->SetResolutionU(2.0*spacing[1]);
+	      splineStackSet[i]->SetResolutionV(spacing[2]);
+	    }
+	  
+	  trimScale[0]->setRange(0,this->dimensions[2]-1);
+	  trimScale[1]->setRange(0,this->dimensions[2]-1);
+	  trimScale[0]->setValue(0);
+	  trimScale[1]->setValue(dimensions[2]-1);
+	}
+
+      this->BlockEditorCallback=1;
+      if (this->SplineEditor!=NULL)
+	{
+	  this->SplineEditor->SetImage(this->image,this->orientation);
+	  this->SplineEditor->SetSlice(-1);
+	  this->UpdateSplineEditor();
+	}
+      this->BlockEditorCallback=0;
+    }
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::SaveSplineStack(const char* fname)
+{
+  char* noext1=nothisextension(fname,".sur");
+  sprintf(pxtk_buffer2,"%s.sur",noext1);
+  //  delete [] noext1;
+  
+  if(currentSplineStack->Save(pxtk_buffer2))
+    {
+      this->SetItemFilename(current_splinestack,pxtk_buffer2);
+      surface_modified[current_splinestack]=0;
+    }
+  else
+    {
+      sprintf(pxtk_buffer2,"Failed to save splinestack %d in %s (Check Permissions)",current_splinestack+1,pxtk_buffer2);
+      this->EventManager->messageBox(pxtk_buffer2,"Save Failure");
+    }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::LoadSplineStack(const char* fname)
+{
+  strcpy(pxtk_buffer2,fname);
+
+  int ok=currentSplineStack->Load(fname);
+  if (!ok)
+      {
+	sprintf(pxtk_buffer2,"Failed to load splinestack %d from %s",current_splinestack+1,fname);
+	this->EventManager->messageBox(pxtk_buffer2,"Load Failure");
+      }
+  else
+    {
+      //      fprintf(stderr,"Here %s\n",pxtk_buffer2);
+      this->SetItemFilename(current_splinestack,pxtk_buffer2);
+      //      fprintf(stderr,"Here %s\n",surface_filename[current_splinestack]);
+      surface_modified[current_splinestack]=0;
+      this->UpdateAfterExternalEditing();
+    }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::SetCurrentCollection(int num)
+{
+  num=Irange(num,0,this->NumberOfSplineStacks-1);
+  if (num==current_splinestack)
+      return;
+  current_splinestack=num;
+
+  currentSplineStack=splineStackSet[current_splinestack];  
+  this->UpdateAfterExternalEditing();
+  
+  Update();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::UpdateControlsFromCurrentSplineStack()
+{
+  displayMode->setIndex(display_mode[current_splinestack]);
+  drawMode->setIndex(currentSplineStack->GetDrawMode());
+  trimScale[0]->setValue(currentSplineStack->GetTrimBottom());
+  trimScale[1]->setValue(currentSplineStack->GetTrimTop());
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::UpdateFromSplineEditor()
+{
+  if (this->SplineEditor==NULL)
+    {
+      vtkErrorMacro(<<"No Spline Editor\n");
+      return;
+    }
+  int sl=this->SplineEditor->GetBeginSlice();
+  int num=this->GetNumberOfSplineStacks();
+
+  //  fprintf(stderr,"\tSTACK:: Receiving Update From Spline Editor slice=%d BLOCK=%d\n",sl,this->BlockEditorCallback);
+  for (int i=0;i<num;i++)
+    {
+      if (this->SplineEditor->GetSplineControl()->GetChangedStatus(i)==1)
+	{
+	  vtkpxSplineStackSource* stack=this->GetSplineStack(i);
+	  vtkpxSplineSource*spl=this->SplineEditor->GetSplineControl()->GetSpline(i);
+	  fprintf(stderr,"Changing Curve %d on Surface %d\n",i+1,sl);
+	  stack->SetSpline(spl,sl);
+	  surface_modified[i]=1;
+	  fprintf(stderr,"Updating spline %d\n",i+1);
+	}
+      else 
+	{
+	  fprintf(stderr,"Not Updating spline %d\n",i+1);
+	}
+    }
+  this->UpdateDisplay();
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::UpdateSplineEditor()
+{
+
+  if (this->SplineEditor==NULL)
+    {
+      vtkErrorMacro(<<"No Spline Editor\n");
+      return;
+    }
+
+  int sl=this->SplineEditor->GetBeginSlice();
+  int num=this->GetNumberOfSplineStacks();
+
+ 
+
+  //  fprintf(stderr,"\tSTACK:: Sending Update To Spline Editor slice=%d BLOCK=%d\n",sl,this->BlockEditorCallback);
+
+  for (int i=0;i<num;i++)
+    {
+      vtkpxSplineStackSource* stack=this->GetSplineStack(i);
+      if (sl>=stack->GetTrimBottom() && sl<=stack->GetTrimTop())
+	{
+	  vtkpxSplineSource* spl=this->SplineEditor->GetSplineControl()->GetSpline(i);
+	  stack->SetSplineFromSplineStack(spl,sl);
+	  this->SplineEditor->EnableSpline(i);
+	  this->SplineEditor->GetSplineControl()->SetChangedStatus(i,0);
+	}
+      else
+	{
+	  this->SplineEditor->DisableSpline(i);
+	}
+    }
+  this->SplineEditor->GetSplineControl()->UpdateControlsFromCurrentSpline();
+  this->SplineEditor->GetSplineControl()->Update();
+  
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::ComputeVOIProperties(int frame)
+{
+  this->WatchOn();
+  if (this->image!=NULL)
+    {
+      float volume[2],mean[2],std[2],threshold[2];
+      int numvox[2];
+
+      for (int ii=0;ii<2;ii++)
+	{
+	  threshold[ii]=atof(thresholdEntry[ii]->getText());
+	  sprintf(pxtk_buffer,"%5.2f",threshold[ii]);
+	  thresholdEntry[ii]->setText(pxtk_buffer);
+	}
+      
+      int nt=currentSplineStack->GetDualVOIProperties(this->image,frame,
+						      volume,mean,std,numvox,threshold);
+
+      if (volume[0]<0.0001)
+	volume[0]=0.0001;
+	    
+      sprintf(pxtk_buffer,"Stack %d Volume=%8.1f mm^3 numvox=%d\n",
+	      current_splinestack+1,currentSplineStack->GetVolume(),nt);
+      PXTkApp::printToConsole(pxtk_buffer);
+      for (int i=0;i<=1;i++)
+	{
+	  sprintf(pxtk_buffer,"\t ROI %d vol >%.1f \t= %6.1f (mm^3) mean=%5.1f std=%5.1f npix=%6d\n",
+		  i+1,threshold[i],volume[i],mean[i],std[i],numvox[i]);
+	  PXTkApp::printToConsole(pxtk_buffer);
+	}
+      
+      sprintf(pxtk_buffer,"\t Inside Volume  %.1f > t  >%.1f \t= %6.1f (cc) %d voxels (%.2f x %.2f %.2f mm)\n\n",
+	      threshold[0],threshold[1],0.001*(volume[0]-volume[1]),numvox[0]-numvox[1],spacing[0],spacing[1],spacing[2]);
+      PXTkApp::printToConsole(pxtk_buffer);
+      PXTkApp::popupConsole();
+    }
+  this->WatchOff();
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUISplineStackControl::DoImport(int mode,int moption)
+{
+  fprintf(stderr,"Do Import this->Dim=%d,%d,%d mode=%d moption=%d\n",this->dimensions[0],this->dimensions[1],this->dimensions[2],mode,moption);
+
+  if (mode==0)
+    {
+      if (this->optionDialog!=NULL)
+	{
+	  if (this->optionDialog->isOpen())
+	    {
+	      fprintf(stderr,"Dialog is open\n");
+	      return;
+	    }
+	  
+	  delete this->optionDialog;
+	}
+      fprintf(stderr,"This far\n");
+      this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,4);
+      this->optionDialog->initDisplay();
+
+      this->optionDialog->setTitleDescription("Import Surface From Binary Image",
+					      "Enter Smoothing and Slice Range Parameters");
+      this->optionDialog->setfoption(0,"Surface Smoothness","%.1f",1.0);
+      this->optionDialog->setfoption(1,"Image   Smoothness","%.1f",1.0);
+      this->optionDialog->setioption(2,"Bottom  Slice","%d",0);
+      this->optionDialog->setioption(3,"Top     Slice","%d",this->dimensions[2]-1) ;
+      this->optionDialog->setMenuOption(moption);
+      this->optionDialog->popupDialog();
+      return;
+    }
+
+  fprintf(stderr,"On to extract ...");
+  float smooth=Frange(this->optionDialog->getfoption(0),0.1,10.0);
+  float sigma=Frange(this->optionDialog->getfoption(1),0.1,4.0);
+  int   minslice=Irange(this->optionDialog->getioption(2),0,this->dimensions[2]-2);
+  int   maxslice=Irange(this->optionDialog->getioption(3),minslice,this->dimensions[2]-1);
+  
+  currentSplineStack->CreateSurfaceFromImage(this->image,minslice,maxslice,
+					     this->CurrentFrame,smooth,sigma);
+  this->UpdateAfterExternalEditing();
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUISplineStackControl.h b/bioimagesuite30_src/GUI/vtkpxGUISplineStackControl.h
new file mode 100644
index 0000000..b093a47
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUISplineStackControl.h
@@ -0,0 +1,242 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUISplineStackControl.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUISplineStackControl - Base Image Viewer
+// .SECTION Description
+
+#ifndef __vtkpxGUISplineStackControl_h
+#define __vtkpxGUISplineStackControl_h
+
+#include "vtkpxSplineStackSource.h"
+#include "vtkpxBaseCurve.h"
+#include "vtkpxGUIBaseCurveEditor.h"
+#include "vtkpxGUISplineEditor.h"
+#include "vtkActor.h"
+#include "pxtkapp.h"
+#include "pxtkeventobj.h"
+#include "pxtkgadgets.h"
+#include "pxtkcomplexwidgets.h"
+#include "pxtkdialog.h"
+#include "pxtkmenu.h"
+#include "pxcontour.h"
+#include "pxtkseldialog.h"
+
+class vtkImageData;
+
+const int SSP_MAX_COLLECTIONS = 50; 
+const int SSP_MAX_RENDERERS   = 4; 
+
+class vtkpxGUISplineStackControl : public vtkpxGUIBaseCurveEditor 
+{
+public:
+
+  static vtkpxGUISplineStackControl *New();
+  vtkTypeMacro(vtkpxGUISplineStackControl,vtkpxGUIBaseCurveEditor);
+  
+  // Description:
+  // Set/Get NumberOfSplineStacks
+  virtual void SetNumberOfSplineStacks(int a);
+  vtkGetMacro(NumberOfSplineStacks,int);
+
+  // Description:
+  // Initialize Display and add Renderer 
+  virtual char*  Initialize(const char* name,int inside);
+  virtual void   SetRenderer(vtkRenderer *rendererer,int num);
+  virtual void   SetRenderer(vtkRenderer *rendererer,int num,int wireframe);
+
+  // Description:
+  // Update Display
+  virtual void   Update();
+  virtual void   UpdateDisplay();
+
+  // Description:
+  // If outside process modified splines (using GetSplineStack) this functions needs to
+  // be called to re-synchronize the GUI etc
+  virtual void UpdateAfterExternalEditing();
+
+
+  // Description:
+  // Event Manager 
+  virtual int    HandleEvent(int);
+  virtual int    HandleEventSecond(int);
+  
+
+  // Get and Set Current SplineStack 
+  virtual vtkpxSplineStackSource* GetSplineStack(int index=-1);
+  virtual vtkObject* GetItem(int index) { return GetSplineStack(index);}
+  virtual int  GetCurrentIndex();
+  virtual void SetSplineStack(vtkpxSplineStackSource* land,int index=-1);
+
+  // Description:
+  // Set Current Image , including slice and orientation and frame
+  // Discards plane and assumes plane =2 , and discards frame
+  virtual void SetImage(vtkImageData* image,int orientation,int level=0,int frame=0);
+  
+  // Description:
+  // Callback Handlers for Clipboard Operations
+  virtual void CopySplineStack();
+  virtual void PasteSplineStack();
+
+  // Description:
+  // Set Spline Control to facilitate proper updating
+  virtual void SetSplineEditor(vtkpxGUISplineEditor* splineeditor);
+
+  // Description:
+  // Communication with SplineEditor
+  virtual void UpdateSplineEditor();
+  virtual void UpdateFromSplineEditor();
+
+protected:
+
+  vtkpxGUISplineStackControl();
+  virtual ~vtkpxGUISplineStackControl();
+
+  // Description:
+  // SplineStacks for editing backup and pointer to current 
+  vtkpxSplineStackSource *currentSplineStack;
+  vtkpxSplineStackSource *splineStackSet[SSP_MAX_COLLECTIONS];
+  vtkpxSplineStackSource *clipboardSplineStack;
+ 
+
+  // Description:
+  // Spline Control used for Editing Splines
+  vtkpxGUISplineEditor* SplineEditor;
+
+   // Description:
+  // vtkActors which capture curves/control points 
+  vtkActor*         splineStackActor[SSP_MAX_RENDERERS][SSP_MAX_COLLECTIONS];
+  vtkRenderer*      Renderer[SSP_MAX_RENDERERS];
+
+  // Description:
+  // Index of Current SplineStack and Number of SplineStacks 
+  int             current_splinestack;
+  int             NumberOfSplineStacks;
+  int             BlockEditorCallback;
+
+  // Description:
+  // Visibility 0= No 1=Spline Only 2=Surface
+  int         display_mode[SSP_MAX_COLLECTIONS];
+  char*       surface_filename[SSP_MAX_COLLECTIONS];
+  int         surface_modified[SSP_MAX_COLLECTIONS];
+
+  // Description:
+  // Options to select whether to show/hide controls mouse mode etc
+  PXTkOptionMenu   *currentCollection;
+
+  // Description:
+  // Show/Hide Current SplineStack, size of current spline 
+  PXTkOptionMenu   *displayMode;
+  PXTkOptionMenu   *drawMode;
+  PXTkOptionMenu   *scaleMode;
+  PXTkArrowScale   *trimScale[2];
+  PXTkFrame        *controlFrame;
+  PXTkEntry        *thresholdEntry[2];
+
+  // Descrtiption:
+  // Needed by The Import From Image GUI
+  PXTkSelDialog*  optionDialog;
+  
+
+  // Description:
+  // Current Image and Energy map as well as image properties
+  vtkImageData    *image;
+  double           spacing[3];
+  double           origin[3];
+  double           defaultsmoothing;
+  int             dimensions[3];
+  int             orientation;
+  int             CurrentFrame;
+
+  // Description:
+  // Callback Handlers for Changing SplineStack, Updating GUI and Loading SplineStack
+  virtual void SetCurrentCollection(int num);
+  virtual void UpdateControlsFromCurrentSplineStack();
+  virtual void LoadSplineStack(const char* fname);
+  virtual void SaveSplineStack(const char* fname);
+  virtual void SetItemColor(int index,double color[3]);
+  virtual void SetItemFilename(int index,const char* s);
+
+  // Description:
+  // Initialize SplineStacks
+  virtual void InitializeSplineStacks();
+
+  // Description:
+  // VOI Property Stuff
+  virtual void ComputeVOIProperties(int frame=0);
+
+  // Description:
+  // Import From Image
+  virtual void DoImport(int mode,int moption);
+
+
+  // Description:
+  // Following Needed to satisfy undefined calls
+  virtual int  HandleClickedPoint (float, float, float, int , int ) { return TCL_OK;}
+  virtual void SetSpacingOrigin (double sp[3], double ori[3]) { }
+  virtual void SetPlaneLevel(int, int) { }
+  virtual void SetFrame(int) { } 
+  virtual void SetLookupTable (vtkLookupTable *) { }
+  virtual void SetTransform(vtkAbstractTransform *) { } 
+  virtual vtkAbstractTransform* GetTransform () { return NULL;}
+
+
+
+};
+
+
+#endif   
+
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUITriangulatedStackControl.cpp b/bioimagesuite30_src/GUI/vtkpxGUITriangulatedStackControl.cpp
new file mode 100644
index 0000000..b053626
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUITriangulatedStackControl.cpp
@@ -0,0 +1,613 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// 	$Id: vtkpxGUITriangulatedStackControl.cpp,v 1.3 2002/12/18 16:11:09 papad Exp papad $	
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkpxGUITriangulatedStackControl.h"
+#include "vtkpxUtil.h"
+#include "vtkActor.h"
+#include "vtkAssembly.h"
+#include "vtkRenderer.h"
+#include "vtkRenderWindow.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxImageExtract.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkImageData.h"
+#include "vtkProperty.h"
+#include "pxfpbsplinestack.h"
+#include "pxtriangulatedstack.h"
+/* -------------------------------------------------------------------------*/
+vtkpxGUITriangulatedStackControl* vtkpxGUITriangulatedStackControl::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUITriangulatedStackControl");
+  if(ret)
+      {
+	return (vtkpxGUITriangulatedStackControl*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUITriangulatedStackControl;
+}
+
+// ----------------------------------------------------------------------------
+vtkpxGUITriangulatedStackControl::vtkpxGUITriangulatedStackControl()
+{
+  this->NumberOfTriangulatedStacks=4;
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->origin[ia]=0.0;
+      this->spacing[ia]=1.0;
+      this->dimensions[ia]=50;
+    }
+  this->orientation=0;
+  
+  for (int i=0;i<this->NumberOfTriangulatedStacks;i++)
+    {
+      triangulatedStackSet[i]=NULL;
+      for (int j=0;j<TSP_MAX_RENDERERS;j++)
+	triangulatedStackActor[j][i]=NULL;
+      display_mode[i]=0;
+      color_mode[i]=-1;
+    }
+
+  for (int j=0;j<TSP_MAX_RENDERERS;j++)
+    this->Renderer[j]=NULL;
+  
+  current_triangulatedstack=0;
+  this->currentTriangulatedStack=NULL;
+  clipboardTriangulatedStack=NULL;
+  image=NULL;
+}
+// ----------------------------------------------------------------------------
+vtkpxGUITriangulatedStackControl::~vtkpxGUITriangulatedStackControl()
+{
+  
+  if (clipboardTriangulatedStack!=NULL)
+    clipboardTriangulatedStack->Delete();
+
+ 
+  for (int i=0;i<this->NumberOfTriangulatedStacks;i++)
+    {
+      if (triangulatedStackSet[i]!=NULL)
+	triangulatedStackSet[i]->Delete();
+      for (int j=0;j<TSP_MAX_RENDERERS;j++)
+	if (triangulatedStackActor[j][i]!=NULL)
+	  triangulatedStackActor[j][i]->Delete();
+    }
+
+  if (this->image!=NULL)
+    this->image->Delete();
+    
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUITriangulatedStackControl::SetNumberOfTriangulatedStacks(int a)
+{
+  if (this->Initialized==1)
+    return;
+
+  this->NumberOfTriangulatedStacks=Irange(a,1,TSP_MAX_COLLECTIONS);
+}
+// ----------------------------------------------------------------------------
+void vtkpxGUITriangulatedStackControl::InitializeTriangulatedStacks()
+{
+
+
+  for (int i=0;i<this->NumberOfTriangulatedStacks;i++)
+    {
+      triangulatedStackSet[i]=vtkpxTriangulatedStackSource::New();
+      PXContourStack* cstack=new PXContourStack(this->dimensions[2]);
+      cstack->setellipticalcylinder(8,
+				    spacing[0]*dimensions[0]/8.0*(1.0+i),
+				    spacing[1]*dimensions[1]/8.0*(1.0+i),
+				    origin[0]+spacing[0]*dimensions[0]/2.0,
+				    origin[1]+spacing[1]*dimensions[1]/2.0);
+
+      triangulatedStackSet[i]->SetFromContourStack(cstack);
+      delete cstack;
+    }
+
+  current_triangulatedstack=0;
+  currentTriangulatedStack=triangulatedStackSet[current_triangulatedstack];
+
+  clipboardTriangulatedStack=vtkpxTriangulatedStackSource::New();
+  clipboardTriangulatedStack->Copy(currentTriangulatedStack);
+
+}
+/* -------------------------------------------------------------------------*/
+char* vtkpxGUITriangulatedStackControl::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+
+  InitializeTriangulatedStacks();
+
+  vtkpxGUIComponent::Initialize(name,inside);
+  PXTkFrame* mFrame=(PXTkFrame*)this->EventManager->getMainWindow();
+  this->controlFrame=new PXTkLabelFrame(this->EventManager,mFrame,"Triangulated Stack Control");
+  mFrame->addChildren("-side top -expand t -fill x -padx 0 -pady 4 ",this->controlFrame);
+
+  // Control Properties
+  // ---------------------
+  PXTkLabelFrame* vFrame=new PXTkLabelFrame(this->EventManager,this->controlFrame,"Global Properties");
+  this->controlFrame->addChildren("-side top -expand false -fill x -padx 0 -pady 5",vFrame);
+  vFrame->setPackMode(PXFalse);
+ 
+  PXTkButton* b0a=new PXTkButton(this->EventManager,vFrame,"Show All",506);
+  PXTkButton* b0b=new PXTkButton(this->EventManager,vFrame,"Hide All",505);
+  vFrame->gridRowColumnChild(b0a,1,0);
+  vFrame->gridRowColumnChild(b0b,1,1);
+  
+  // Collection Properties 
+  // ---------------------
+  PXTkLabelFrame* pFrame=new PXTkLabelFrame(this->EventManager,this->controlFrame,"Triangulated Stack Properties");
+  this->controlFrame->addChildren("-side top -expand t -fill both -padx 0 -pady 2",pFrame);
+
+  PXTkFrame* pfr0=new PXTkFrame(this->EventManager,pFrame);
+  PXTkFrame* pfr1=new PXTkFrame(this->EventManager,pFrame);
+  PXTkFrame* pfr2=new PXTkFrame(this->EventManager,pFrame);
+
+  pFrame->addChildren("-side top -pady 0 -expand t -fill x",pfr0,pfr1,pfr2);
+
+
+  PXTkLabel* labs=new PXTkLabel(this->EventManager,pfr0,"Current Stack:");
+  currentCollection=new PXTkOptionMenu(this->EventManager,pfr0,"Stack 1",500);
+  for (int ip=1;ip<this->NumberOfTriangulatedStacks;ip++)
+    {
+      sprintf(pxtk_buffer4,"Stack %d",ip+1);
+      currentCollection->addOption(pxtk_buffer4);
+    }
+  currentCollection->setIndex(current_triangulatedstack);
+  pfr0->addChildren("-side left -expand t -fill x",labs,currentCollection);
+
+  PXTkLabel* labd=new PXTkLabel(this->EventManager,pfr1,"Display Mode:");
+  displayMode=new PXTkOptionMenu(this->EventManager,pfr1,"Hide",501);
+  displayMode->addOption("Points");
+  displayMode->addOption("Wireframe");
+  displayMode->addOption("Surface");
+  displayMode->setIndex(display_mode[current_triangulatedstack]);
+  pfr1->addChildren("-side left -expand t -fill x",labd,displayMode);
+
+  PXTkLabel* labe=new PXTkLabel(this->EventManager,pfr2,"Color Mode:");
+  colorMode=new PXTkOptionMenu(this->EventManager,pfr2,"None",501);
+  colorMode->addOption("Gaussian");
+  colorMode->addOption("Mean");
+  colorMode->addOption("1st Princ");
+  colorMode->addOption("2nd Princ");
+  colorMode->addOption("Bending");
+  colorMode->addOption("Shape Index");
+  colorMode->setIndex(color_mode[current_triangulatedstack]);
+  pfr2->addChildren("-side left -expand t -fill x",labe,colorMode);
+
+
+  // Collection Operations 
+  // ---------------------
+  PXTkLabelFrame* oFrame=new PXTkLabelFrame(this->EventManager,this->controlFrame,"Operations on Current Stack");
+  this->controlFrame->addChildren("-side top -expand t -fill both -padx 1 -pady 0",oFrame);
+
+  PXTkFrame* midfr=new PXTkFrame(this->EventManager,oFrame);
+
+  PXTkFrame* botfr=new PXTkFrame(this->EventManager,oFrame);  
+  PXTkFrame* botfr2=new PXTkFrame(this->EventManager,oFrame);  
+  oFrame->addChildren("-side top -pady 0 -expand t -fill x",midfr,botfr,botfr2);
+  
+  PXTkButton* but6=new PXTkButton(this->EventManager,midfr,"Color",450);
+  PXTkButton* but5=new PXTkButton(this->EventManager,midfr,"Cylinder",452);
+  
+  but5->configure("-padx",0);
+  but6->configure("-padx",0);
+  midfr->addChildren("-side left -padx 1 -expand t -fill x",but6,but5);
+
+  PXTkButton* but1=new PXTkButton(this->EventManager,botfr,"Load",401);
+  PXTkButton* but2=new PXTkButton(this->EventManager,botfr,"Save",402);
+  but1->configure("-padx",0);
+  but2->configure("-padx",0);
+  botfr->addChildren("-side left -padx 1 -expand t -fill x",but1,but2);
+
+  PXTkButton* cp=new PXTkButton(this->EventManager,botfr2,"Copy",590);
+  PXTkButton* pt=new PXTkButton(this->EventManager,botfr2,"Paste",591);
+  cp->configure("-padx",0);
+  pt->configure("-padx",0);
+  botfr2->addChildren("-side left -padx 1 -expand t -fill x",cp,pt);
+
+  
+  if (!inside)
+    {
+      PXTkButton* closeB;
+      if (this->EventParent)
+	closeB=new PXTkButton(this->EventManager,mFrame,"Close",3);
+      else
+	closeB=new PXTkButton(this->EventManager,mFrame,"Exit",1);
+      mFrame->addChildren("-side bottom -expand false -fill x -padx 2",closeB);
+    }
+
+
+  this->optionDialog=new PXTkSelDialog(this->EventManager,this->controlFrame,10);
+
+  // Other Stuff 
+  return GetWidgetName();
+}
+
+/* -------------------------------------------------------------------------*/ 
+void vtkpxGUITriangulatedStackControl::SetRenderer(vtkRenderer* ren,int index)
+{
+  this->SetRenderer(ren,index,0);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUITriangulatedStackControl::SetRenderer(vtkRenderer *ren,int index,int wireframe)
+{
+  index=Irange(index,0,TSP_MAX_RENDERERS-1);
+
+  if (this->Renderer[index]!=NULL)
+    return;
+
+  for (int i=0;i<this->NumberOfTriangulatedStacks;i++)
+      {
+	if (triangulatedStackActor[index][i]==NULL)
+	    {
+	      vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+	      map->SetInput(triangulatedStackSet[i]->GetOutput());
+
+	      triangulatedStackActor[index][i]=vtkActor::New();
+	      triangulatedStackActor[index][i]->SetMapper(map);
+	      if (display_mode[i]!=0)
+		triangulatedStackActor[index][i]->SetVisibility(1);
+	      else
+		triangulatedStackActor[index][i]->SetVisibility(0);
+
+	      if (display_mode[i]==1 || display_mode[i]==2)
+		{
+		  triangulatedStackActor[index][i]->GetProperty()->SetLineWidth(2.0);
+		  triangulatedStackActor[index][i]->GetProperty()->SetAmbient(1.0);
+		  triangulatedStackActor[index][i]->GetProperty()->SetDiffuse(0.0);
+		  triangulatedStackActor[index][i]->GetProperty()->SetSpecular(0.0);
+		  if (display_mode[i]==2)
+		    triangulatedStackActor[index][i]->GetProperty()->SetRepresentationToWireframe();
+		  else
+		    triangulatedStackActor[index][i]->GetProperty()->SetRepresentationToPoints();
+		}
+	      
+	      map->Delete();
+	    }
+	ren->AddActor(triangulatedStackActor[index][i]);
+      }
+
+  this->Renderer[index]=ren;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUITriangulatedStackControl::Update()
+{
+  if (this->triangulatedStackActor[0]==NULL)
+      return;
+
+  for (int j=0;j<TSP_MAX_RENDERERS;j++)
+    {
+      if (this->Renderer[j]!=NULL)
+	{
+	  for (int i=0;i<this->NumberOfTriangulatedStacks;i++)
+	    {
+	      if (j==0)
+		{
+		  if (triangulatedStackSet[i]->GetColorMode()!=color_mode[i])
+		    triangulatedStackSet[i]->SetColorMode(color_mode[i]);
+		}
+
+	      if (display_mode[i]==0)
+		{
+		  triangulatedStackActor[j][i]->SetVisibility(0);
+		}
+	      else
+		{
+		  vtkProperty* prop=triangulatedStackActor[j][i]->GetProperty();
+		  switch (display_mode[i])
+		    {
+		    case 3:
+		      prop->SetRepresentationToSurface();
+		      prop->SetDiffuse(1.0);
+		      prop->SetAmbient(0.0);
+		      prop->SetSpecular(0.0);
+		      break;
+		    case 2:
+		      prop->SetRepresentationToWireframe();
+		      prop->SetDiffuse(0.0);
+		      prop->SetAmbient(1.0);
+		      prop->SetSpecular(0.0);
+		      break;
+		    case 1:
+		      prop->SetRepresentationToPoints();
+		      prop->SetDiffuse(0.0);
+		      prop->SetAmbient(1.0);
+		      prop->SetSpecular(0.0);
+		      prop->SetPointSize(3.0);		
+		      break;
+		    }
+		  triangulatedStackActor[j][i]->SetVisibility(1);
+		}
+	    }
+	}
+    }
+  
+  // Curve Stuff 
+  UpdateDisplay();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUITriangulatedStackControl::UpdateDisplay()
+{
+  if (this->Renderer[0]!=NULL)
+    this->Renderer[0]->GetRenderWindow()->Render();
+
+}
+/* -------------------------------------------------------------------------*/
+
+int  vtkpxGUITriangulatedStackControl::HandleEvent(int event)
+{
+  if (!this->Initialized)
+      return TCL_OK;
+
+  if (event<10)
+      return this->EventManager->handleDirectEvent(event);
+
+  if (this->currentTriangulatedStack==NULL)
+    return TCL_OK;
+  
+  switch(event)
+      {
+      case 401:
+	{
+	  int ok=this->EventManager->questionBox("Loading will delete your old triangulatedstack. Are you sure?");
+	  if (ok)
+	      {
+		char* line=this->EventManager->getOpenFilename("Load triangulatedstacks","TriangulatedStacks","*.tstack");
+		if (line!=NULL)
+		    {
+		      if (strlen(line)>0)
+			LoadTriangulatedStack(line);
+		    }
+	      }
+	}
+	break;
+	
+      case 402:
+	{
+	  char* line=this->EventManager->getSaveFilename("Save TriangulatedStacks","surface.tstack","TriangulatedStacks","*.tstack");
+	  if (line!=NULL)
+	      {
+		if (strlen(line)>0)
+		    {
+		      strcpy(pxtk_buffer2,line);
+		      if(currentTriangulatedStack->Save(line))
+			{
+			  sprintf(pxtk_buffer2,"%s.%d",PXTkApp::getFilenameTail(pxtk_buffer2),current_triangulatedstack+1);
+			  currentCollection->changeLabel(current_triangulatedstack,pxtk_buffer2);
+			  
+			}
+		      else
+			{
+			  sprintf(pxtk_buffer2,"Failed to save triangulatedstack %d in %s",current_triangulatedstack+1,line);
+			  this->EventManager->messageBox(pxtk_buffer2,"Save Failure");
+			}
+		    }
+	      }
+	}
+	break;
+  
+
+	
+      case 450:
+	if (triangulatedStackActor[0][current_triangulatedstack]!=NULL)
+	  {
+	    double c[3];
+	    triangulatedStackActor[0][current_triangulatedstack]->GetProperty()->GetColor(c);
+	    int a=this->EventManager->d_colorBox("TriangulatedStack Color",c[0],c[1],c[2]);
+	    if (a==1)
+	      {
+		for (int j=0;j<TSP_MAX_RENDERERS;j++)
+		  {
+		    if (triangulatedStackActor[j][current_triangulatedstack]!=NULL)
+		      triangulatedStackActor[j][current_triangulatedstack]->GetProperty()->SetColor(c);
+		  }
+	      }
+	  }
+	break;
+	
+
+      case 452: // Ellipse
+	{
+	  PXContourStack* cstack=new PXContourStack(this->dimensions[2]);
+	  cstack->setellipticalcylinder(8,
+					spacing[0]*float(dimensions[0])/8.0*(1.0+current_triangulatedstack),
+					spacing[1]*float(dimensions[1])/8.0*(1.0+current_triangulatedstack),
+					origin[0]+spacing[0]*dimensions[0]/2.0,
+					origin[1]+spacing[1]*dimensions[1]/2.0);
+	  currentTriangulatedStack->SetFromContourStack(cstack);
+	  delete cstack;
+	}
+	break;
+	  
+      case 500:
+	SetCurrentCollection(currentCollection->getIndex());
+	break;
+	
+      case 501:
+	display_mode[current_triangulatedstack]=displayMode->getIndex();
+	color_mode[current_triangulatedstack]=colorMode->getIndex()-1;
+	Update();
+	break;
+
+	
+      case 505:
+	{
+	  for  (int i=0;i<this->NumberOfTriangulatedStacks;i++)
+	    display_mode[i]=0;
+	  displayMode->setIndex(0);
+	}
+	Update();
+	break;
+
+	
+      case 506:
+	{
+	  for  (int i=0;i<this->NumberOfTriangulatedStacks;i++)
+	    display_mode[i]=2;
+	  displayMode->setIndex(3);
+	}
+	Update();
+	break;
+	
+      case 590:
+	this->CopyTriangulatedStack();
+	break;
+	
+      case 591:
+	this->PasteTriangulatedStack();
+	break;
+
+
+      case 614:
+	if (this->EventParent!=NULL && this->CallbackNo>0)
+	  this->EventParent->HandleEvent(CallbackNo);
+	else
+	  if (this->CallbackName!=NULL)
+	    PXTkApp::executeTclCommand(this->CallbackName);
+	break;
+
+      }
+
+  UpdateDisplay();
+
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUITriangulatedStackControl::CopyTriangulatedStack()
+{
+  clipboardTriangulatedStack->Copy(currentTriangulatedStack);
+}
+
+void vtkpxGUITriangulatedStackControl::PasteTriangulatedStack()	
+{
+    SetTriangulatedStack(clipboardTriangulatedStack,-1);
+}
+/* -------------------------------------------------------------------------*/
+vtkpxTriangulatedStackSource* vtkpxGUITriangulatedStackControl::GetTriangulatedStack(int index)
+{
+  if (index==-1)
+      index=current_triangulatedstack;
+
+  return triangulatedStackSet[Irange(index,0,this->NumberOfTriangulatedStacks-1)];
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxGUITriangulatedStackControl::GetCurrentIndex()
+{
+  return current_triangulatedstack;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUITriangulatedStackControl::SetTriangulatedStack(vtkpxTriangulatedStackSource* land,int index)
+{
+  if (index==-1)
+      index=current_triangulatedstack;
+
+  index=Irange(index,0,this->NumberOfTriangulatedStacks-1);
+
+  triangulatedStackSet[index]->Copy(land);
+ 
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUITriangulatedStackControl::SetImage(vtkImageData* img,int orient,int lv,int fr)
+{
+  if (img!=NULL)
+    {
+      if (this->image!=NULL)
+	this->image->Delete();
+      this->image=vtkImageData::New();
+      this->image->ShallowCopy(img);
+      this->orientation=Irange(orient,0,3);
+      
+      int d[3]; double sp[3],ori[3];
+      this->image->GetSpacing(sp);
+      this->image->GetOrigin(ori);
+      this->image->GetDimensions(d);
+      
+      float sum=0.0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=
+	  fabs(float(d[ia]-this->dimensions[ia]))+
+	  fabs(sp[ia]-this->spacing[ia])+
+	  fabs(ori[ia]-this->origin[ia]);
+      
+      
+      if (sum>0.01)
+	{
+	  this->image->GetOrigin(this->origin);
+	  this->image->GetSpacing(this->spacing);
+	  this->image->GetDimensions(this->dimensions);
+	}
+    }
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxGUITriangulatedStackControl::LoadTriangulatedStack(const char* fname)
+{
+  strcpy(pxtk_buffer2,fname);
+  int ok=currentTriangulatedStack->Load(fname);
+  if (!ok)
+      {
+	sprintf(pxtk_buffer2,"Failed to load landmarks %d from %s",current_triangulatedstack+1,fname);
+	this->EventManager->messageBox(pxtk_buffer2,"Load Failure");
+      }
+  else
+    {
+      sprintf(pxtk_buffer2,"%s.%d",PXTkApp::getFilenameTail(pxtk_buffer2),current_triangulatedstack+1);
+      currentCollection->changeLabel(current_triangulatedstack,pxtk_buffer2);
+    }
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxGUITriangulatedStackControl::SetCurrentCollection(int num)
+{
+  
+  if (num==current_triangulatedstack)
+      return;
+  current_triangulatedstack=num;
+
+  currentTriangulatedStack=triangulatedStackSet[current_triangulatedstack];  
+  displayMode->setIndex(display_mode[current_triangulatedstack]);
+  colorMode->setIndex(color_mode[current_triangulatedstack]+1);
+  Update();
+}
+/* -------------------------------------------------------------------------*/
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUITriangulatedStackControl.h b/bioimagesuite30_src/GUI/vtkpxGUITriangulatedStackControl.h
new file mode 100644
index 0000000..b3077ff
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUITriangulatedStackControl.h
@@ -0,0 +1,199 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUITriangulatedStackControl.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUITriangulatedStackControl - Base Image Viewer
+// .SECTION Description
+
+#ifndef __vtkpxGUITriangulatedStackControl_h
+#define __vtkpxGUITriangulatedStackControl_h
+
+#include "vtkpxTriangulatedStackSource.h"
+#include "vtkpxBaseCurve.h"
+#include "vtkpxGUIBaseCurveEditor.h"
+#include "vtkActor.h"
+#include "pxtkapp.h"
+#include "pxtkeventobj.h"
+#include "pxtkgadgets.h"
+#include "pxtkcomplexwidgets.h"
+#include "pxtkdialog.h"
+#include "pxtkmenu.h"
+#include "pxcontour.h"
+#include "pxtkseldialog.h"
+
+class vtkImageData;
+
+const int TSP_MAX_COLLECTIONS = 12; 
+const int TSP_MAX_RENDERERS   = 4; 
+
+class vtkpxGUITriangulatedStackControl : public vtkpxGUIBaseCurveEditor 
+{
+public:
+
+  static vtkpxGUITriangulatedStackControl *New();
+  vtkTypeMacro(vtkpxGUITriangulatedStackControl,vtkpxGUIBaseCurveEditor);
+  
+  // Description:
+  // Set/Get NumberOfTriangulatedStacks
+  virtual void SetNumberOfTriangulatedStacks(int a);
+  vtkGetMacro(NumberOfTriangulatedStacks,int);
+
+  // Description:
+  // Initialize Display and add Renderer 
+  virtual char*  Initialize(const char* name,int inside);
+  virtual void   SetRenderer(vtkRenderer *rendererer,int num);
+  virtual void   SetRenderer(vtkRenderer *rendererer,int num,int wireframe);
+
+  // Description:
+  // Update Display
+  virtual void   Update();
+  virtual void   UpdateDisplay();
+
+  // Description:
+  // Event Manager 
+  virtual int    HandleEvent(int);
+  
+  // Get and Set Current TriangulatedStack 
+  virtual vtkpxTriangulatedStackSource* GetTriangulatedStack(int index=-1);
+  virtual vtkObject* GetItem(int index) { return GetTriangulatedStack(index);}
+  virtual int  GetCurrentIndex();
+  virtual void SetTriangulatedStack(vtkpxTriangulatedStackSource* land,int index=-1);
+
+  // Description:
+  // Set Current Image , including slice and orientation and frame
+  // Discards plane and assumes plane =2 , and discards frame
+  virtual void SetImage(vtkImageData* image,int orientation,int level=0,int frame=0);
+  
+  // Description:
+  // Callback Handlers for Clipboard Operations
+  virtual void CopyTriangulatedStack();
+  virtual void PasteTriangulatedStack();
+
+protected:
+
+  vtkpxGUITriangulatedStackControl();
+  virtual ~vtkpxGUITriangulatedStackControl();
+
+  // Description:
+  // TriangulatedStacks for editing backup and pointer to current 
+  vtkpxTriangulatedStackSource *currentTriangulatedStack;
+  vtkpxTriangulatedStackSource *triangulatedStackSet[TSP_MAX_COLLECTIONS];
+  vtkpxTriangulatedStackSource *clipboardTriangulatedStack;
+ 
+   // Description:
+  // vtkActors which capture curves/control points 
+  vtkActor*         triangulatedStackActor[TSP_MAX_RENDERERS][TSP_MAX_COLLECTIONS];
+  vtkRenderer*      Renderer[TSP_MAX_RENDERERS];
+
+  // Description:
+  // Index of Current TriangulatedStack and Number of TriangulatedStacks 
+  int             current_triangulatedstack;
+  int             NumberOfTriangulatedStacks;
+
+  // Description:
+  // Visibility 0= No 1=Points 2=Wireframe 3=Solid
+  int         display_mode[TSP_MAX_COLLECTIONS];
+  int         color_mode[TSP_MAX_COLLECTIONS];
+
+  // Description:
+  // Options to select whether to show/hide controls mouse mode etc
+  PXTkOptionMenu   *currentCollection;
+
+  // Description:
+  // Show/Hide Current TriangulatedStack, size of current triangulated 
+  PXTkOptionMenu   *displayMode;
+  PXTkOptionMenu   *colorMode;
+  PXTkLabelFrame   *controlFrame;
+
+  // Description:
+  // Current Image and Energy map as well as image properties
+  vtkImageData    *image;
+  double           spacing[3];
+  double           origin[3];
+  int             dimensions[3];
+  int             orientation;
+
+
+  // Description:
+  // Widgets for various GUIS
+  // 1. Curvatures
+  // 2. Solid
+  // 3. Shape Tracking
+  PXTkSelDialog*  optionDialog;
+
+  // Description:
+  // Callback Handlers for Changing TriangulatedStack, Updating GUI and Loading TriangulatedStack
+  virtual void SetCurrentCollection(int num);
+  virtual void LoadTriangulatedStack(const char* fname);
+
+  // Description:
+  // Initialize TriangulatedStacks
+  virtual void InitializeTriangulatedStacks();
+
+  // Description:
+  // Following Needed to satisfy undefined calls
+  virtual int  HandleClickedPoint (float, float, float, int , int ) { return TCL_OK;}
+  virtual void SetSpacingOrigin (double sp[3], double ori[3]) { }
+  virtual void SetPlaneLevel(int, int) { }
+  virtual void SetFrame(int) { } 
+  virtual void SetLookupTable (vtkLookupTable *) { }
+  virtual void SetTransform(vtkAbstractTransform *) { } 
+  virtual vtkAbstractTransform* GetTransform () { return NULL;}
+
+};
+
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIVolumeControl.cpp b/bioimagesuite30_src/GUI/vtkpxGUIVolumeControl.cpp
new file mode 100644
index 0000000..60bd1e6
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIVolumeControl.cpp
@@ -0,0 +1,865 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIVolumeControl.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/05/08 16:04:58 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxGUIColormapEditor.h"
+#include "vtkpxGUIVolumeControl.h"
+#include "vtkPolyData.h"
+#include "vtkObjectFactory.h"
+#include "pxtkapp.h"
+#include "pxutil.h"
+#include "vtkpxBaseCurve.h"
+
+vtkpxGUIVolumeControl* vtkpxGUIVolumeControl::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGUIVolumeControl");
+  if(ret)
+      {
+	return (vtkpxGUIVolumeControl*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxGUIVolumeControl;
+}
+
+// Construct object with no children.
+vtkpxGUIVolumeControl::vtkpxGUIVolumeControl()
+{
+  has_volume=PXFalse;
+  this->Volume=NULL;
+
+  this->ColormapEditor=NULL;
+  this->Viewer=NULL;
+  this->internal_viewer=NULL;
+  this->show_volume=NULL;
+  this->Visibility=PXFalse;
+  this->DualInput=PXFalse;
+  this->OrthoViewer=NULL;
+  this->LandmarkControl=NULL;
+}
+// ------------------------------------------------------------------------------------
+void vtkpxGUIVolumeControl::SetVolumeRenderer(vtkpxVolume* vol,vtkpxGUIBaseRenderer* view)
+{
+  if (vol!=NULL)
+    {
+      this->Volume=vol;
+      //outline=outl;
+      this->Viewer=view;
+      has_volume=PXTrue;
+      resliceMode->setIndex(this->Volume->GetResliceMode());
+      interpolationMode->setIndex(Irange(this->Volume->GetInterpolationMode(),0,2));
+      //interpolationMode->selectItem(Irange(this->Volume->GetInterpolationMode(),0,2));
+      this->Update(1);
+    }
+
+}
+// ------------------------------------------------------------------------------------
+void  vtkpxGUIVolumeControl::UpdateVolumeRenderer(vtkpxVolume* vol,vtkpxGUIBaseRenderer* ren)
+{
+  if (vol==NULL || ren==NULL)
+    return;
+
+  if (has_volume==PXFalse)
+    {
+      this->SetVolumeRenderer(vol,ren);
+      return;
+    }
+
+  int d1[6]; this->Volume->GetImageRange(d1);
+  int d2[6]; vol->GetImageRange(d2);
+
+
+  int d=0;
+  for (int ia=1;ia<=5;ia+=2)
+    d+=abs(d1[ia]-d2[ia]);
+
+
+
+  this->Volume=vol;
+  this->Viewer=ren;
+  this->Volume->SetResliceInterpolationModes(resliceMode->getIndex(),interpolationMode->getIndex());
+
+  if (this->DualInput)
+    this->Volume->SetDualInputMode(1);
+  else
+    this->Volume->SetDualInputMode(0);
+  
+  if (this->Volume->GetDualInputMode()==1)
+    this->DualInput=PXTrue;
+  else
+    this->DualInput=PXFalse;
+
+
+  if (d>0)
+    this->Update(0);
+  else
+    this->UpdateCrop();
+}
+// ------------------------------------------------------------------------------------
+void vtkpxGUIVolumeControl::SetRenderer(vtkpxGUIBaseRenderer* viewer1)
+{
+  this->Viewer=viewer1;
+}
+// ------------------------------------------------------------------------------------
+char*  vtkpxGUIVolumeControl::Initialize(const char* name,int inside)
+{
+  if (this->Initialized==1)
+      return GetWidgetName();
+  
+  vtkpxGUIComponent::Initialize(name,inside);
+
+  PXTkFrame* parentFrame=(PXTkFrame*)(this->EventManager->getMainWindow());
+  viewerFrame=new PXTkFrame(this->EventManager,parentFrame);
+
+  volFrame=new PXTkFrame(this->EventManager,parentFrame);
+  
+  parentFrame->setPackMode(PXTrue);
+  parentFrame->addChildren("-side left -expand false -fill both",viewerFrame,volFrame);
+
+  volFrame->setPackMode(PXFalse);
+
+  show_volume=new PXTkCheckButton(this->EventManager,volFrame,"Show Volume",104);
+  show_volume->setState(this->Visibility);
+
+
+  shadeOn=new PXTkCheckButton(this->EventManager,volFrame,"Shading",105);
+  shadeOn->setState(PXFalse);
+
+  fourColorMode=new PXTkCheckButton(this->EventManager,volFrame,"RGBA",108);
+  fourColorMode->setState(PXFalse);
+
+  volumeRenderingMode=new PXTkOptionMenu(this->EventManager,volFrame,"RayCasting",106);
+  volumeRenderingMode->addOption("MIP");
+  volumeRenderingMode->addOption("Texture2D");
+  volumeRenderingMode->addOption("Texture3D");
+  volumeRenderingMode->addOption("CropRay");
+  volumeRenderingMode->setIndex(2);
+
+
+  irregularClipping =new PXTkCheckButton(this->EventManager,volFrame,"Functional crop", 109);
+  gradientEnhancement =new PXTkCheckButton(this->EventManager,volFrame,"Gradient Enhancement", 114);
+ 
+
+  char* line=PXTkApp::getTclVariable("pxtcl_pref_array(VolumeTextureMode)");
+
+  if (line==NULL)
+    {
+      volumeRenderingMode->setIndex(2);
+    }
+  else
+    {
+      int a=atoi(line);
+      if (a==1 || a==2)
+	volumeRenderingMode->setIndex(2);
+      else if (a==3)
+	volumeRenderingMode->setIndex(3);
+      else
+	volumeRenderingMode->setIndex(0);
+    }
+
+  volFrame->gridRowColumnChild(show_volume,0,0);
+  volFrame->gridRowColumnChild(shadeOn,0,1);
+  volFrame->gridRowColumnChild(volumeRenderingMode,1,0);  
+  volFrame->gridRowColumnChild(fourColorMode,1,1);
+  volFrame->gridRowColumnChild(irregularClipping,2,0);  
+  volFrame->gridRowColumnChild(gradientEnhancement,2,1);  
+
+  rateScale=new PXTkScale(this->EventManager,volFrame,"Interactive Rate",102,PXTrue);
+  rateScale->setRange(0.0,60.0);
+  rateScale->setDigits(4);
+  rateScale->setValue(float(40));
+  rateScale->setLengthWidth(120,10);
+  rateScale->setResolution(1.0);
+
+  rateScale2=new PXTkScale(this->EventManager,volFrame,"Still Rate",102,PXTrue);
+  rateScale2->setRange(0.00,5.0);
+  rateScale2->setDigits(4);
+  rateScale2->setValue(float(1.0));
+  rateScale2->setLengthWidth(120,10);
+  rateScale2->setResolution(0.25);
+
+  cropSphereRadius=new PXTkScale(this->EventManager,volFrame,"Sphere Radius",112,PXTrue);
+  cropSphereRadius->setRange(1.0,100.0);
+  cropSphereRadius->setDigits(4);
+  cropSphereRadius->setValue(float(25));
+  cropSphereRadius->setLengthWidth(120,10);
+  cropSphereRadius->setResolution(1.0);
+  
+  cropCubeLength=new PXTkScale(this->EventManager,volFrame,"Cube Length",112,PXTrue);
+  cropCubeLength->setRange(10.0,150.0);
+  cropCubeLength->setDigits(4);
+  cropCubeLength->setValue(float(0.1));
+  cropCubeLength->setLengthWidth(120,10);
+  cropCubeLength->setResolution(0.25);
+
+  cropEllipseRadiusX=new PXTkScale(this->EventManager,volFrame,"Ellipsoidal Radius-X",112,PXTrue);
+  cropEllipseRadiusX->setRange(10.0,100.0);
+  cropEllipseRadiusX->setDigits(4);
+  cropEllipseRadiusX->setValue(float(25));
+  cropEllipseRadiusX->setLengthWidth(120,10);
+  cropEllipseRadiusX->setResolution(5.0);
+  
+
+  cropEllipseRadiusY=new PXTkScale(this->EventManager,volFrame,"Ellipsoidal Radius-Y",112,PXTrue);
+  cropEllipseRadiusY->setRange(10.0,100.0);
+  cropEllipseRadiusY->setDigits(4);
+  cropEllipseRadiusY->setValue(float(15));
+  cropEllipseRadiusY->setLengthWidth(120,10);
+  cropEllipseRadiusY->setResolution(5.0);  
+
+
+  cropEllipseRadiusZ=new PXTkScale(this->EventManager,volFrame,"Ellipsoidal Radius-Z",112,PXTrue);
+  cropEllipseRadiusZ->setRange(10.0,150.0);
+  cropEllipseRadiusZ->setDigits(4);
+  cropEllipseRadiusZ->setValue(float(15));
+  cropEllipseRadiusZ->setLengthWidth(120,10);
+  cropEllipseRadiusZ->setResolution(5.0);
+  
+
+  
+  cropCylinderRadius=new PXTkScale(this->EventManager,volFrame,"Cylinder Radius",112,PXTrue);
+  cropCylinderRadius->setRange(10.0,150.0);
+  cropCylinderRadius->setDigits(4);
+  cropCylinderRadius->setValue(float(0.1));
+  cropCylinderRadius->setLengthWidth(120,10);
+  cropCylinderRadius->setResolution(0.25);
+  
+  
+  volFrame->gridRowColumnChild(cropSphereRadius,5,0);      
+  volFrame->gridRowColumnChild(cropCubeLength,5,1);      
+  volFrame->gridRowColumnChild(cropEllipseRadiusX,5,2);      
+  volFrame->gridRowColumnChild(cropEllipseRadiusY,5,3);      
+  volFrame->gridRowColumnChild(cropEllipseRadiusZ,5,4);      
+  volFrame->gridRowColumnChild(cropCylinderRadius,5,5);      
+  
+  resliceMode=new PXTkOptionMenu(this->EventManager,volFrame,"Original Dimensions",103);
+  resliceMode->addOption("Half Original");
+  resliceMode->addOption("Quarter Original");
+  resliceMode->addOption("64x64x64");
+  resliceMode->addOption("128x128x64");
+  resliceMode->addOption("128x128x128");
+  resliceMode->addOption("256x256x128");
+  resliceMode->addOption("256x256x256");
+  resliceMode->addOption("512x512x256");
+  resliceMode->addOption("512x512x512");
+  resliceMode->setIndex(3);
+  volFrame->gridRowColumnChild(resliceMode,6,0);
+
+  interpolationMode=new PXTkOptionMenu(this->EventManager,volFrame,"No Interpolation",101);
+  interpolationMode->addOption("Linear");
+  interpolationMode->addOption("Cubic");
+  interpolationMode->setIndex(1);
+
+  croppingShape =new PXTkOptionMenu(this->EventManager,volFrame,"Sphere",113);
+  croppingShape->addOption("Cube");
+  croppingShape->addOption("Ellipsoid");
+  croppingShape->addOption("Cylinder");
+  croppingShape->setIndex(0);
+
+  /*  interpolationMode=new PXITkComboBox(this->EventManager,volFrame,"Interp",101);
+  interpolationMode->addItem("None");
+  interpolationMode->addItem("Linear");
+  interpolationMode->addItem("Cubic");
+  interpolationMode->selectItem(1);*/
+
+  volFrame->gridRowColumnChild(croppingShape,6,1);
+
+  volFrame->gridRowColumnChild(interpolationMode,7,1);
+
+  PXTkLabelFrame* cropFrame=new PXTkLabelFrame(this->EventManager,volFrame,"Cropping");
+  volFrame->gridRowColumnChild(cropFrame,8,0,1,2);
+  cropFrame->setPackMode(PXFalse);
+
+
+
+  for (int ia=0;ia<=2;ia++)
+      {
+	for (int ib=0;ib<=1;ib++)
+	    {
+	      if (ia==0)
+		  strcpy(pxtk_buffer4,"x-");
+	      else if (ia==1)
+		  strcpy(pxtk_buffer4,"y-");
+	      else
+		  strcpy(pxtk_buffer4,"z-");
+	      
+	      if (ib==0)
+		  sprintf(pxtk_buffer4,"%s-min",pxtk_buffer4);
+	      else
+		  sprintf(pxtk_buffer4,"%s-max",pxtk_buffer4);
+	      
+	      int index=ia*2+ib;
+	      clipScale[index]=new PXTkScale(this->EventManager,cropFrame,pxtk_buffer4,107);
+	      clipScale[index]->setRange(0,100);
+	      clipScale[index]->setLengthWidth(120,10);
+	      clipScale[index]->setDigits(4);
+	      clipScale[index]->setResolution(1);
+	      volFrame->gridRowColumnChild(clipScale[index],1+ia,ib);
+	    }
+      }
+  
+  PXTkFrame*  mFrame=new PXTkFrame(this->EventManager,volFrame);
+  volFrame->gridRowColumnChild(mFrame,9,0,1,2);
+
+
+  PXTkButton* b1c0=new PXTkButton(this->EventManager,mFrame,"St",120);
+  PXTkButton* b1c=new PXTkButton(this->EventManager,mFrame,"Nr",121);
+  PXTkButton* b1d=new PXTkButton(this->EventManager,mFrame,"F1",122);
+  PXTkButton* b1e=new PXTkButton(this->EventManager,mFrame,"F2",123);
+  PXTkButton* b1f=new PXTkButton(this->EventManager,mFrame,"F4",124);
+  PXTkButton* b1g=new PXTkButton(this->EventManager,mFrame,"Colormap",110);
+
+
+  b1c0->configure("-padx",1);
+  b1c->configure("-padx",1);
+  b1d->configure("-padx",1);
+  b1e->configure("-padx",1);
+  b1f->configure("-padx",1);
+  b1g->configure("-padx",1);
+
+  mFrame->addChildren("-side left ",b1c0,b1c,b1d);
+  mFrame->addChildren("-side left ",b1e,b1f);
+  mFrame->addChildren("-side right -expand true -fill both",b1g);
+
+  if (!this->EventManager->isInside())
+      {
+	PXTkButton* b5=new PXTkButton(this->EventManager,volFrame,"Close",3); 
+	volFrame->gridRowColumnChild(b5,10,1,1,2);
+
+	PXTkLabel* lab=new PXTkLabel(this->EventManager,volFrame,"");
+	lab->configure("-image","$::pxtclvtkpxcontrib::smalllogo ");
+	volFrame->gridRowColumnChild(lab,10,0);
+      }
+
+  
+  ColormapEditor=vtkpxGUIColormapEditor::New();
+  ColormapEditor->SetSimpleMode(0);
+  ColormapEditor->SetVolumeMode(1);
+  ColormapEditor->SetCallback(this,111);
+  ColormapEditor->Initialize(this->GetWidgetName(),0);
+  ColormapEditor->SetRange(0,255);
+
+
+  int vm=this->volumeRenderingMode->getIndex();
+  if (vm==2 || vm==3)
+    this->ShowRateControls(0);
+  else
+    this->ShowRateControls(1);
+
+  if(vm ==4)
+	this->ShowCropControls(1);
+  else
+	this->ShowCropControls(0);
+
+
+  this->Initialized=1;
+
+  return GetWidgetName();
+}
+ // ------------------------------------------------------------------------------------
+void vtkpxGUIVolumeControl::Update(int full)
+{
+  if (!this->Initialized || !has_volume)
+      return;
+
+  
+  int range[6]; 
+  this->Volume->GetImageRange(range);
+  if (full>0)
+    {
+      for (int ia=0;ia<3;ia++)
+	for (int ib=0;ib<2;ib++)
+	  {
+	    int index=ia*2+ib;
+	    int vindex=ia*2+1;
+	    clipScale[index]->setRange(0,(float)range[vindex]);
+	    clipScale[index]->setResolution(1);
+	    
+	    if (ib==0)
+	      clipScale[index]->setValue(0);
+	    else
+	      clipScale[index]->setValue((float)range[index]);
+	  }
+
+
+      if (full==1)
+	{
+	  //	  fprintf(stderr,"Setting Colormap Range\n");
+	  ColormapEditor->SetRange(0,this->Volume->GetMaxIntensity());
+	  //	  fprintf(stderr,"Done\n");
+	  this->UpdateCrop();
+	}
+    }
+
+  this->Volume->SetFromLookupTable(ColormapEditor->GetColormap());
+  this->Volume->SetResliceInterpolationModes(resliceMode->getIndex(),interpolationMode->getIndex());
+
+  
+  if (this->Visibility)	
+    {
+      this->Volume->SetShadingMode(shadeOn->getState());
+      
+      int vm=this->volumeRenderingMode->getIndex();
+      this->Volume->SetVolumeRenderingMode(vm);
+      this->Volume->SetVisibility(1);
+    }
+  else
+    {
+      this->Volume->SetVisibility(0);
+      int range[6];
+      for (int ia=0;ia<=5;ia++)
+	range[ia]=(int)(clipScale[ia]->getValue());
+      this->Volume->SetCroppingRange(range);
+    }
+
+  if (full==2)
+    this->UpdateCrop();
+
+}
+// ------------------------------------------------------------------------------------
+void vtkpxGUIVolumeControl::UpdateDisplay()
+{
+  if (!this->Initialized || !has_volume)
+      return;
+
+  this->Viewer->SetUpdateRate(rateScale->getValue(),rateScale2->getValue());
+  if (!this->Visibility)
+      return;
+  
+  this->UpdateCrop();
+}
+// ------------------------------------------------------------------------------------
+int  vtkpxGUIVolumeControl::GetClipScaleValue(int i)
+{
+  if (i<0) i=0;
+  if (i>5) i=5;
+  int v=(int)(clipScale[i]->getValue());
+  return v;
+}
+
+void vtkpxGUIVolumeControl::SetClipScaleValue(int i,int v)
+{
+  if (i<0) i=0;
+  if (i>5) i=5;
+  if (v!=-1)
+    {
+      clipScale[i]->setValue((float)v);
+    }
+  else
+    {
+      int d1[6]; this->Volume->GetImageRange(d1);
+      clipScale[i]->setValue(float(d1[i]));
+    }
+    
+}
+
+int vtkpxGUIVolumeControl::UpdateCrop()
+{
+  if (!this->Initialized || !has_volume)
+      return 0;
+
+  int range[6],oldrange[6];
+
+  this->Volume->GetCroppingRange(oldrange);
+  
+  int sum=0;
+
+  for (int ia=0;ia<=5;ia++)
+    {
+      range[ia]=(int)(clipScale[ia]->getValue());
+      sum+=abs(range[ia]-oldrange[ia]);
+    }
+
+  if (sum>0)
+    this->Volume->SetCroppingRange(range);
+
+  if (this->Visibility)	
+    this->Volume->Update();
+
+  return 1;
+}
+// ------------------------------------------------------------------------------------
+void vtkpxGUIVolumeControl::SetVisibility(int vis)
+{
+  vis=(vis>0);
+  if (vis)
+    this->Visibility=PXTrue;
+  else
+    this->Visibility=PXFalse;
+
+  if (this->show_volume!=NULL)
+    show_volume->setState(this->Visibility);
+  
+  if (this->Volume!=NULL)
+    {
+      if (this->Visibility)
+	this->Volume->SetVisibility(1);
+      else
+	this->Volume->SetVisibility(0);
+    }
+
+}
+// ------------------------------------------------------------------------------------
+void vtkpxGUIVolumeControl::ShowRateControls(int show)
+{
+  if (!this->Initialized)
+    return;
+  
+  if (show==0)
+    {
+      volFrame->unmapChild(rateScale);
+      volFrame->unmapChild(rateScale2);
+    }
+  else
+    {
+      volFrame->gridRowColumnChild(rateScale,4,0);
+      volFrame->gridRowColumnChild(rateScale2,4,1);
+    }
+
+}
+// ------------------------------------------------------------------------------------
+void vtkpxGUIVolumeControl::ShowCropControls(int show)
+{
+  if (!this->Initialized)
+    return;
+  
+  
+
+  if (show==0)
+  {
+	  volFrame->unmapChild(croppingShape); // needs to be fixed. 
+	  volFrame->unmapChild(cropSphereRadius);
+	  volFrame->unmapChild(cropCubeLength);		
+	  volFrame->unmapChild(cropEllipseRadiusX);
+	  volFrame->unmapChild(cropEllipseRadiusY);
+	  volFrame->unmapChild(cropEllipseRadiusZ);
+	  volFrame->unmapChild(cropCylinderRadius);		
+  }
+  else if(show==1)
+  {
+	  volFrame->gridRowColumnChild(croppingShape,6,1);
+	  volFrame->gridRowColumnChild(cropSphereRadius,5,0);      	 
+	  volFrame->unmapChild(cropCubeLength);		
+	  volFrame->unmapChild(cropEllipseRadiusX);
+	  volFrame->unmapChild(cropEllipseRadiusY);
+	  volFrame->unmapChild(cropEllipseRadiusZ);
+	  volFrame->unmapChild(cropCylinderRadius);		
+	  volFrame->gridRowColumnChild(resliceMode,6,0);
+  }
+  else if(show==2)
+  {
+	  volFrame->gridRowColumnChild(croppingShape,6,1);
+	  volFrame->gridRowColumnChild(cropCubeLength,5,0);      	
+	  volFrame->unmapChild(cropSphereRadius);		
+	  volFrame->unmapChild(cropEllipseRadiusX);
+	  volFrame->unmapChild(cropEllipseRadiusY);
+	  volFrame->unmapChild(cropEllipseRadiusZ);
+	  volFrame->unmapChild(cropCylinderRadius);
+	  volFrame->gridRowColumnChild(resliceMode,6,0);
+  }
+  else if(show==3)
+  {
+	  volFrame->gridRowColumnChild(croppingShape,7,1);
+	  volFrame->gridRowColumnChild(cropEllipseRadiusX,5,0);      
+	  volFrame->gridRowColumnChild(cropEllipseRadiusY,5,1);      
+	  volFrame->gridRowColumnChild(cropEllipseRadiusZ,6,0);      
+	  volFrame->unmapChild(cropSphereRadius);
+	  volFrame->unmapChild(cropCubeLength);				 
+	  volFrame->unmapChild(cropCylinderRadius);
+	  volFrame->gridRowColumnChild(resliceMode,7,0);
+  }
+  else if(show==4)
+  {
+	  volFrame->gridRowColumnChild(croppingShape,6,1);
+	  volFrame->gridRowColumnChild(cropCylinderRadius,5,0);      
+	  volFrame->unmapChild(cropSphereRadius);
+	  volFrame->unmapChild(cropCubeLength);		
+	  volFrame->unmapChild(cropEllipseRadiusX);
+	  volFrame->unmapChild(cropEllipseRadiusY);
+	  volFrame->unmapChild(cropEllipseRadiusZ);
+	  volFrame->gridRowColumnChild(resliceMode,6,0);
+
+  }
+
+}
+
+// -------------------------------------------------------------------------
+
+int  vtkpxGUIVolumeControl::HandleEvent(int event)
+{
+	double dirvec[3] = {1, 0, 0};
+
+  if (event<=10)
+      return this->EventManager->handleDirectEvent(event);
+
+  if (!has_volume)    // Nothing to do 
+      return TCL_OK;
+
+  /*  if (this->LandmarkControl!=NULL)
+    {
+      vtkpxBaseCurve* land=this->LandmarkControl->GetCollection(-1);
+      double sp[3]; land->GetSpacing(sp);
+      double ori[3]; land->GetOrigin(ori);
+      fprintf(stdout,"num land points=%d\n",land->GetNumPoints());
+      vtkPoints* pts=land->GetPoints();
+      if (land->GetNumPoints()>0)
+	{
+	  double x[3];
+	  pts->GetPoint(0,x);
+	  fprintf(stderr, "First Point Raw = %f %f %f\n",x[0],x[1],x[2]);
+	  for (int ia=0;ia<=2;ia++)
+	    x[ia]=x[ia]*sp[ia]+ori[ia];
+	  fprintf(stderr, "First Point = %f %f %f\n",x[0],x[1],x[2]);
+	}
+    }
+  else
+  fprintf(stderr,"Landmark Control is NULL\n");*/
+
+
+  switch (event)
+      {
+      case 101:
+	this->Volume->SetResliceInterpolationModes(resliceMode->getIndex(),interpolationMode->getIndex());
+	break;
+
+      case 102:
+	UpdateDisplay();
+	break;
+	
+      case 103:
+	this->Update(2);
+	break;
+
+      case 104:
+	this->Visibility=show_volume->getState();
+	if (this->Visibility)
+	  this->Volume->SetVisibility(1);
+	else
+	  this->Volume->SetVisibility(0);
+	break;
+	
+      case 105:
+	this->Volume->SetShadingMode((int)shadeOn->getState());
+	UpdateCrop();
+	break;
+	
+      case 106:
+	{
+	  int vm=this->volumeRenderingMode->getIndex();
+	  if (vm==2 || vm==3)
+	    {
+	      this->ShowRateControls(0);
+	      this->ShowCropControls(0);
+	    }
+	  else
+	    {
+	      this->ShowRateControls(1);		
+	      this->ShowCropControls(1);		
+	    }
+	  this->Volume->SetVolumeRenderingMode(vm);
+	  UpdateCrop();
+	}
+	break;
+
+      case 107:
+	UpdateCrop();
+	break;
+
+      case 108:
+	this->Volume->SetRGBAMode((int)fourColorMode->getState());
+	UpdateCrop();
+	break;
+
+      case 109:
+	if(this->irregularClipping->getState())
+	  this->Volume->SetIrregularCroppingMode(1);
+	else
+	  this->Volume->SetIrregularCroppingMode(0);
+	break;
+	
+      case 110:
+	ColormapEditor->Show();
+	break;
+
+      case 112:
+	
+	this->Volume->SetCropValues((int)croppingShape->getIndex(), 
+				    (double)cropSphereRadius->getValue(),
+				    (double)cropCubeLength->getValue(),
+				    (double)cropCubeLength->getValue(),
+				    (double)cropCubeLength->getValue(),
+				    (double)cropEllipseRadiusX->getValue(),
+					(double)cropEllipseRadiusY->getValue(),
+					(double)cropEllipseRadiusZ->getValue(),
+				    (double)cropCylinderRadius->getValue(),
+				    20, dirvec);	
+	this->UpdateOrthogonalViewerNavigationPointer();		  
+	
+	break; 
+
+
+      case 113:		
+	this->ShowCropControls((int)croppingShape->getIndex()+1);			
+	this->UpdateOrthogonalViewerNavigationPointer();
+	
+	this->Volume->SetCropValues((int)croppingShape->getIndex(), 
+				    (double)cropSphereRadius->getValue(),
+				    (double)cropCubeLength->getValue(),
+				    (double)cropCubeLength->getValue(),
+				    (double)cropCubeLength->getValue(),
+				    (double)cropEllipseRadiusX->getValue(),
+					(double)cropEllipseRadiusY->getValue(),
+					(double)cropEllipseRadiusZ->getValue(),
+				    (double)cropCylinderRadius->getValue(), 20, dirvec);		
+	
+	break;
+	
+	// gradient enhancement
+      case 114:
+	if(this->gradientEnhancement->getState())
+	  this->Volume->SetGradientEnhancementMode(1);
+	else
+	  this->Volume->SetGradientEnhancementMode(0);
+	break;
+	
+      case 120:
+      case 121:
+      case 122:
+      case 123:
+      case 124:
+	this->SetPresetLookupTable(event-121);
+	break;
+
+      case 111:
+	if (ColormapEditor!=NULL)
+	  {
+	    this->Volume->SetFromLookupTable(ColormapEditor->GetColormap());
+	  }		    
+	break;
+
+
+      }
+  
+  Viewer->Render();
+  return TCL_OK;
+}
+// ------------------------------------------------------------------------------------
+vtkpxGUIBaseRenderer* vtkpxGUIVolumeControl::GetViewer()
+{
+  return this->Viewer;
+}
+
+void vtkpxGUIVolumeControl::SetPresetLookupTable(int m)
+{
+  m=Irange(m,-1,5);
+  if (ColormapEditor!=NULL)
+    {
+
+      int oldint=(interpolationMode->getIndex()>0);
+      int newint=0;
+      if (m>0)
+	newint=0;
+      else
+	newint=1;
+
+      if (oldint!=newint)
+	{
+	  interpolationMode->setIndex(newint);
+	  //interpolationMode->selectItem(newint);
+	  this->Volume->SetResliceInterpolationModes(resliceMode->getIndex(),interpolationMode->getIndex());
+	}
+      ColormapEditor->SetFmriMode(m);
+    }
+}
+// ------------------------------------------------------------------------------------
+void vtkpxGUIVolumeControl::SetLookupTable(vtkLookupTable* lkup,int auto_convert)
+{
+
+
+
+}
+// ------------------------------------------------------------------------------------
+int vtkpxGUIVolumeControl::UpdateOrthogonalViewerNavigationPointer()
+{
+  if (this->OrthoViewer==NULL)
+    return 0;
+  
+  int md=(int)croppingShape->getIndex();
+  
+  double r=(double)cropSphereRadius->getValue();
+  
+  double cubelength = (double)cropCubeLength->getValue();
+  
+  if (md==0)
+    this->OrthoViewer->SetNavigationPointerGeometryToSphere(r);
+  else if (md==1)
+    this->OrthoViewer->SetNavigationPointerGeometryToCube(cubelength);
+  else if (md==2)
+    {
+      // This needs to be changed to do ellipse in ortho viewer but KEEP cone
+      this->OrthoViewer->SetNavigationPointerGeometryToEllipse(cropEllipseRadiusX->getValue(), cropEllipseRadiusY->getValue(), cropEllipseRadiusZ->getValue());
+    }
+  else if (md==3)
+    {
+      this->OrthoViewer->SetNavigationPointerGeometryToCylinder(cropCylinderRadius->getValue()); 
+    }
+
+  int dm=this->OrthoViewer->GetNavigationPointerDrawMode();
+
+  if (dm<2)
+    this->OrthoViewer->RenderNavigationPointer(3);
+
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxGUIVolumeControl.h b/bioimagesuite30_src/GUI/vtkpxGUIVolumeControl.h
new file mode 100644
index 0000000..a658279
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxGUIVolumeControl.h
@@ -0,0 +1,174 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGUIVolumeControl.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxGUIVolumeControl - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkpxGUIVolumeControl_h
+#define __vtkpxGUIVolumeControl_h
+
+#include "vtkpxGUIComponent.h"
+#include "vtkpxVolume.h"
+#include "vtkpxGUIBaseRenderer.h"
+
+#include "pxtkframe.h"
+#include "pxtkscale.h"
+#include "pxitkcombobox.h"
+#include "vtkpxGUIOrthogonalViewer.h"
+#include "vtkpxGUIBaseCurveControl.h"
+
+class vtkpxGUIColormapEditor;
+
+class vtkpxGUIVolumeControl : public vtkpxGUIComponent
+{
+public:
+  static vtkpxGUIVolumeControl *New();
+  vtkTypeMacro(vtkpxGUIVolumeControl,vtkpxGUIComponent);
+
+  virtual char* Initialize(const char* name,int inside);
+  virtual int   HandleEvent(int );
+
+  virtual void         SetVolumeRenderer(vtkpxVolume* vol,vtkpxGUIBaseRenderer* viewer1);
+  virtual void         SetRenderer(vtkpxGUIBaseRenderer* viewer1);
+
+  virtual void         UpdateVolumeRenderer(vtkpxVolume* vol,vtkpxGUIBaseRenderer* ren);
+
+  virtual void Update(int full=1);
+  virtual void UpdateDisplay();
+  virtual int  UpdateCrop();
+  virtual vtkpxGUIBaseRenderer* GetViewer();
+  virtual void SetVisibility(int vis);
+  virtual void SetPresetLookupTable(int m);
+
+  virtual vtkpxGUIColormapEditor* GetColorMapEditor() { return ColormapEditor;}
+
+  virtual void SetLookupTable(vtkLookupTable* lkup,int auto_convert=1);
+
+  virtual int  GetClipScaleValue(int i);
+  virtual void SetClipScaleValue(int i,int v);
+
+
+ // Description:
+ // Pointer for Ortho Viewer
+   vtkGetObjectMacro(OrthoViewer,vtkpxGUIOrthogonalViewer);
+   vtkSetObjectMacro(OrthoViewer,vtkpxGUIOrthogonalViewer);
+
+ // Description:
+ // Pointer for Landmark Control
+   vtkGetObjectMacro(LandmarkControl,vtkpxGUIBaseCurveControl);
+   vtkSetObjectMacro(LandmarkControl,vtkpxGUIBaseCurveControl);
+
+
+protected:
+
+  vtkpxGUIVolumeControl();
+
+  vtkpxVolume            *Volume;
+  vtkpxGUIBaseRenderer      *Viewer;
+  vtkpxGUIBaseRenderer      *internal_viewer;
+  vtkpxGUIOrthogonalViewer  *OrthoViewer;
+  vtkpxGUIBaseCurveControl* LandmarkControl;
+  PXBool                 has_volume;
+  PXBool                 Visibility;
+  PXBool                 DualInput;
+
+  /*PXTkScale              *minIntensityScale;
+    PXTkScale              *maxIntensityScale;
+    PXTkScale              *minTransparencyScale;
+    PXTkScale              *maxTransparencyScale;*/
+
+  
+  // irregular cropping
+  PXTkScale              *cropSphereRadius;
+  PXTkScale              *cropCubeLength;
+  PXTkScale              *cropEllipseRadiusX;
+  PXTkScale              *cropEllipseRadiusY;
+  PXTkScale              *cropEllipseRadiusZ;   
+  PXTkScale              *cropCylinderRadius;
+
+
+  PXTkScale              *clipScale[6];
+  PXTkScale              *rateScale;
+  PXTkScale              *rateScale2;  
+  PXTkOptionMenu         *resliceMode;
+  PXTkOptionMenu         *interpolationMode;
+  PXTkOptionMenu         *croppingShape;
+  //  PXITkComboBox          *interpolationMode;
+
+  PXTkCheckButton        *show_volume;
+  PXTkCheckButton        *dual_input;
+  PXTkCheckButton        *shadeOn;
+  PXTkCheckButton        *fourColorMode;
+
+  PXTkOptionMenu         *volumeRenderingMode;
+  PXTkCheckButton        *irregularClipping;
+  PXTkCheckButton        *gradientEnhancement;
+  PXTkCheckButton        *show_outline;
+  vtkpxGUIColormapEditor *ColormapEditor;
+  PXTkFrame              *viewerFrame;
+  PXTkFrame              *volFrame;
+
+  // Description:
+  // Show/Hide Rate Controls
+  virtual void ShowRateControls(int show);
+  virtual void ShowCropControls(int show);
+
+  // Description:
+  // Update Orthogonal Viewer
+  virtual int UpdateOrthogonalViewerNavigationPointer();
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/GUI/vtkpxTalairachTransform.cpp b/bioimagesuite30_src/GUI/vtkpxTalairachTransform.cpp
new file mode 100644
index 0000000..110e8d1
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxTalairachTransform.cpp
@@ -0,0 +1,1289 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxTalairachTransform.cpp,v $
+  Language:  C++
+  Date:      $Date: 2003/04/11 20:00:25 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxTalairachTransform.h"
+#include "vtkpxTalairachTransformHelper.h"
+#include "vtkMath.h"
+#include "vtkTransform.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxBaseCurve.h"
+#include "vtkTransformFilter.h"
+#include "vtkPolyData.h"
+#include "vtkPointSet.h"
+#include "vtkCellArray.h"
+#include "vtkDataArray.h"
+#include "vtkPoints.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkImageData.h"
+#include "vtkbisImageReslice.h"
+#include "vtkImageFlip.h"
+#include "vtkpxAnalyzeImageSource.h"
+//----------------------------------------------------------------------------
+vtkpxTalairachTransform* vtkpxTalairachTransform::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxTalairachTransform");
+  if(ret)
+    {
+      return (vtkpxTalairachTransform*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxTalairachTransform;
+}
+
+//------------------------------------------------------------------------
+vtkpxTalairachTransform::vtkpxTalairachTransform()
+{
+  this->Landmarks=NULL;
+  this->InverseTolerance = 0.001;
+  this->InverseIterations = 500;
+  this->LinearTransform=NULL;
+  this->ColinMode=0;
+  this->ColinYSize=0;
+
+  // Some Random values for ac,pc, extents !!
+  for (int ia=0;ia<=2;ia++)
+    {
+      minc[ia]=0.0;
+      maxc[ia]=1.0;
+      pc[ia]=0.3;
+      ac[ia]=0.2;
+    }
+
+  // X-coordinate 
+  RIGHT_AC=69.0;
+  AC_LEFT=69.0;
+  
+  // Y-Coordinate 
+  BACK_PC=104.0-24.0;
+  PC_AC=24.0;
+  AC_FRONT=69.0;
+   
+  // Z-Coordinate 
+  BOTTOM_AC=43.0;
+  AC_TOP=74.0;
+
+  this->Offset=6;
+  this->AdditionalZOffset=24;
+  this->SetStandardModeOn();
+  
+}
+
+//------------------------------------------------------------------------
+vtkpxTalairachTransform::~vtkpxTalairachTransform()
+{
+  if (this->Landmarks)
+    {
+      this->Landmarks->Delete();
+    }
+
+  if (this->LinearTransform)
+    {
+      this->LinearTransform->Delete();
+    }
+
+
+}
+
+//------------------------------------------------------------------------
+void vtkpxTalairachTransform::SetLandmarks(vtkPoints *source)
+{
+  if (source==NULL)
+    return;
+
+  if (this->Landmarks != NULL)
+    this->Landmarks->Delete();
+
+  this->Landmarks=vtkPoints::New();
+  this->Landmarks ->DeepCopy(source);
+  this->StandardMode=0;
+  this->Modified();
+}
+//------------------------------------------------------------------------
+unsigned long vtkpxTalairachTransform::GetMTime()
+{
+  unsigned long result = this->vtkWarpTransform::GetMTime();
+  unsigned long mtime;
+
+  if (this->Landmarks)
+    {
+      mtime = this->Landmarks->GetMTime(); 
+      if (mtime > result)
+	{
+	  result = mtime;
+	}
+    }
+  return result;
+}
+//------------------------------------------------------------------------
+void vtkpxTalairachTransform::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkWarpTransform::PrintSelf(os,indent);
+  
+  os << indent << "Landmarks: " << this->Landmarks << "\n";
+  if (this->Landmarks)
+    {
+      this->Landmarks->PrintSelf(os,indent.GetNextIndent());
+    }
+}
+
+//----------------------------------------------------------------------------
+vtkAbstractTransform *vtkpxTalairachTransform::MakeTransform()
+{
+  return vtkpxTalairachTransform::New(); 
+}
+
+//----------------------------------------------------------------------------
+void vtkpxTalairachTransform::InternalDeepCopy(vtkAbstractTransform *transform)
+{
+  vtkpxTalairachTransform *t = (vtkpxTalairachTransform *)transform;
+
+  this->SetInverseTolerance(t->InverseTolerance);
+  this->SetInverseIterations(t->InverseIterations);
+  this->SetLandmarks(t->Landmarks);
+
+  if (this->InverseFlag != t->InverseFlag)
+    {
+      this->InverseFlag = t->InverseFlag;
+      this->Modified();
+    }
+}
+//------------------------------------------------------------------------
+void vtkpxTalairachTransform::InternalUpdate()
+{
+  if (this->StandardMode==-1 || this->ColinMode==1 || this->ColinMode==-1)
+    {
+      vtkDebugMacro(<<"Nothing to do, loaded transform\n");
+      return;
+    }
+
+  if (this->StandardMode==1)
+    {
+      if (this->LinearTransform==NULL)
+	this->LinearTransform=vtkTransform::New();
+
+      vtkMatrix4x4* mat=vtkMatrix4x4::New();
+      mat->Identity();
+      
+
+      this->LinearTransform->SetMatrix(mat);
+      mat->Delete();
+
+      // Define the bounds 
+      this->scalex0=1.0;
+      this->scalex1=1.0;
+
+      this->scalez0=1.0;
+      this->scalez1=1.0;
+
+      this->scaley0=1.0;
+      this->scaley1=1.0;
+      this->scaley2=1.0;
+      return;
+    }
+
+
+  // Non-Standard Mode 
+  int i,ia;
+
+  if (this->Landmarks == NULL)
+    {
+      return;
+    }
+
+  if (this->Landmarks->GetNumberOfPoints() < 4 )
+    {
+      vtkErrorMacro("Update: At least 4 points needed to define talairach coordinate system");
+      return;
+    }
+
+  //  fprintf(stderr,"Here in Talairach Transform");
+
+  this->StandardMode=0;
+  // ----------------------------------- 1. Find Linear Transform ---------------------------
+
+  // First Get the AC and the PC 
+  this->Landmarks->GetPoint(0,ac);
+  this->Landmarks->GetPoint(1,pc);
+
+  // Now convert Create Rotation to AC/PC Line
+  if (this->LinearTransform==NULL)
+    this->LinearTransform=vtkTransform::New();
+  this->LinearTransform->Identity();
+
+  double x1[3],x2[3],x3[3];
+
+  //  Make ac the origin (0,0,0) by adding a -ac translation 
+  this->LinearTransform->Translate(-ac[0],-ac[1],-ac[2]); 
+
+  this->Landmarks->GetPoint(2,x1);
+  this->Landmarks->GetPoint(3,x3);
+  
+  // Find ac pc line and store in x2 to become the y-axis 
+  for (ia=0;ia<=2;ia++)
+    {
+      x2[ia]=ac[ia]-pc[ia];
+      x3[ia]=x3[ia]-x1[ia];
+    }
+  vtkMath::Normalize(x2);
+  vtkMath::Normalize(x3);
+
+
+  // Find the x-axis x1 as the cross-product of x2 and x3
+  // Double cross-product to orthogonalize x2 and x3 !!
+  vtkMath::Cross(x2,x3,x1);
+  vtkMath::Normalize(x1);
+
+  vtkMath::Cross(x1,x2,x3);
+  vtkMath::Normalize(x3);
+
+  // These creates a rotation with the AC/PC Line as the y-axis 
+  // By Setting the 3x3 Section of mat
+  vtkMatrix4x4* mat=vtkMatrix4x4::New();
+  mat->Identity();
+
+  for (i=0;i<=2;i++)
+    {
+      mat->SetElement(0,i,x1[i]);
+      mat->SetElement(1,i,x2[i]);
+      mat->SetElement(2,i,x3[i]);
+    }
+
+  // Combine mat with translation to get complete transform in AC/PC Space 
+  this->LinearTransform->PostMultiply();
+  this->LinearTransform->Concatenate(mat);
+
+  // ----------------------------------- 2. Find Bounding Box --------------------------------------
+  // Find Bounding Box in original coordinate system 
+  vtkPolyData* temppoly=vtkPolyData::New();
+  temppoly->SetPoints(this->Landmarks);
+
+  vtkTransformFilter* tfilt=vtkTransformFilter::New();
+  tfilt->SetTransform(this->LinearTransform);
+  tfilt->SetInput(temppoly);
+  tfilt->Update();
+  
+  vtkPointSet* newpoly=tfilt->GetOutput();  
+  newpoly->ComputeBounds();
+  double bounds[6];
+
+  newpoly->GetBounds(bounds);
+
+  for (i=0;i<=2;i++)
+    {
+      minc[i]=bounds[i*2];
+      maxc[i]=bounds[i*2+1];
+    }
+
+  tfilt->Delete();
+  temppoly->Delete();
+
+  // Avoid division by zero stuff 
+  for (int ib=0;ib<=2;ib++)
+    {
+      if (maxc[ib]==minc[ib])
+	maxc[ib]=minc[ib]+1.0;
+    }
+
+  // ----------------------------------- 3. Transform PC  ---------------------------
+  // Transform PC into this space   
+  double tpc[3];
+  for (int id=0;id<=2;id++)
+    tpc[id]=pc[id];
+  LinearTransform->TransformPoint(tpc,pc);
+
+
+  // ----------------------------------- 4. Scaling Constants  ---------------------------
+  this->SetScalingConstants();
+  return;
+}
+//------------------------------------------------------------------------
+void vtkpxTalairachTransform::SetScalingConstants()
+{
+  // Geared Towards inverse transform;
+  //  float scalex0,scalex1,scaley0,scaley1,scaley2,scalez0,scalez1;
+  this->scalex0=fabs(minc[0]/RIGHT_AC);
+  this->scalex1=fabs(maxc[0]/AC_LEFT);
+  this->scalez0=fabs(minc[2]/BOTTOM_AC);
+  this->scalez1=fabs(maxc[2]/AC_TOP);
+
+  this->scaley0=fabs((minc[1]-pc[1])/BACK_PC);
+  this->scaley1=fabs(pc[1]/PC_AC);
+  this->scaley2=fabs(maxc[1]/AC_FRONT);
+
+  return;
+}
+//------------------------------------------------------------------------
+int vtkpxTalairachTransform::GetMNICoordinates(double x[3],double mni[3])
+{
+  if (this->GetColinMode()!=0 && vtkpxTalairachTransformHelper::ColinLookup!=NULL)
+    {
+      if (this->ColinYSize==216)
+	{
+	  // Flip X
+	  mni[0]=(180-x[0])-90.0;
+	  mni[2]=(x[2]-72.0);
+
+	  // Flip Y
+	  if (this->GetColinMode()==-1)
+	    {
+	      mni[1]=x[1]-127;
+
+	      // Also Flip Right/Left
+	      mni[0]=-mni[0];
+	    }
+	  else
+	    {
+	      mni[1]=(216-x[1])-127;
+	    }
+
+	  // 1 offset !!!
+	  mni[1]+=1.0;
+
+
+	  return 1;
+	}
+    }
+  return 0;
+}
+template<class T>
+static inline void vtkpxTalairachForwardTransformPoint(vtkpxTalairachTransform *self,
+						       const T point[3], T output[3],
+						       vtkTransform* LinearTransform,
+						       const double ac[3],const double pc[3],const double minc[3],const double maxc[3],
+						       const double RIGHT_AC,const double AC_LEFT,
+						       const double BACK_PC,const double PC_AC,const double AC_FRONT,
+						       const double BOTTOM_AC,const double AC_TOP)
+{
+
+  if (self->GetColinMode()!=0 && vtkpxTalairachTransformHelper::ColinLookup!=NULL)
+    {
+      int pt[3];
+      for (int i=0;i<=2;i++)
+	pt[i]=(int)point[i];
+      if (self->GetColinMode()==-1)
+	pt[1]=self->GetColinYSize()-pt[1];
+      
+      if (vtkpxTalairachTransformHelper::ColinLookup->GetScalarType()==VTK_SHORT)
+	{
+	  //	  fprintf(stderr, "In Short mode=%d, size=%d %d %d %d\n",self->GetColinMode(),self->GetColinYSize(),pt[0],pt[1],pt[2]);
+	  for (int ia=0;ia<=2;ia++)
+	    output[ia]=vtkpxTalairachTransformHelper::ColinLookup->GetScalarComponentAsDouble(pt[0],pt[1],pt[2],ia)*0.1;
+	} 
+      else
+	{
+	  for (int ia=0;ia<=2;ia++)
+	    output[ia]=vtkpxTalairachTransformHelper::ColinLookup->GetScalarComponentAsDouble(pt[0],pt[1],pt[2],ia)-128;
+	}
+
+      if (self->GetColinMode()==-1)
+	output[0]=-output[0];
+
+      return;
+    }
+
+  if (self->GetStandardMode()==1)
+    {
+      for (int i=0;i<=2;i++)
+	output[i]=point[i];
+    }
+
+
+
+  if (LinearTransform==NULL)
+    {
+      for (int ia=0;ia<=2;ia++)
+	output[ia]=point[ia];
+      return;
+    }
+
+  T tempoutput[3];
+
+  //  fprintf(stderr,"Point = %f %f %f\n",point[0],point[1],point[2]);
+
+  // Output x,y,z now in AC/PC space with ac as origin
+  LinearTransform->TransformPoint(point,tempoutput);
+
+  
+  //  fprintf(stderr,"Post Linear = %f %f %f\n",tempoutput[0],tempoutput[1],tempoutput[2]);
+
+
+  // Now we need to scale appropriately
+  // First x-coordinate 
+  if (tempoutput[0]<0.0)
+    tempoutput[0]=-RIGHT_AC*fabs(tempoutput[0]/minc[0]);
+  else
+    tempoutput[0]= AC_LEFT *fabs(tempoutput[0]/maxc[0]);
+
+  //  fprintf(stderr,"Post X = %f %f %f\n",tempoutput[0],tempoutput[1],tempoutput[2]);
+
+  // Then y-coordinate in three steps
+  if (tempoutput[1]<pc[1])
+    tempoutput[1]=-1.0*PC_AC-BACK_PC*fabs( (tempoutput[1]-pc[1])/(minc[1]-pc[1]) );
+  else if (tempoutput[1]>=pc[1] && tempoutput[1]<=0.0)
+    tempoutput[1]=-1.0*PC_AC*fabs( tempoutput[1]/pc[1]);
+  else
+    tempoutput[1]=AC_FRONT*fabs(tempoutput[1]/maxc[1]);
+
+  //  fprintf(stderr,"Post Y = %f %f %f\n",tempoutput[0],tempoutput[1],tempoutput[2]);
+
+  // Then z-coordinate 
+  if (tempoutput[2]<0.0)
+    tempoutput[2]=-BOTTOM_AC*fabs(tempoutput[2]/minc[2]);
+  else
+    tempoutput[2]= AC_TOP*fabs(tempoutput[2]/maxc[2]);
+ 
+  //fprintf(stderr,"Post Z = %f %f %f\n",tempoutput[0],tempoutput[1],tempoutput[2]);
+
+  for (int ia=0;ia<=2;ia++)
+    output[ia]=tempoutput[ia];
+
+  //  fprintf(stderr,"\n\n");
+
+}
+//------------------------------------------------------------------------
+
+template<class T>
+static inline void vtkpxTalairachInverseTransformPoint(const T point[3], T output[3],
+						       vtkTransform* LinearTransform,
+						       const double PC_AC,const double pc,
+						       const double scalex0,const double scalex1,
+						       const double scaley0,const double scaley1,const double scaley2,
+						       const double scalez0,const double scalez1)
+{
+  if (LinearTransform==NULL)
+    {
+      for (int ia=0;ia<=2;ia++)
+	output[ia]=point[ia];
+      return;
+    }
+
+  // Then x-coordinate this is easy 
+  if (point[0]<0.0)
+    output[0]=point[0]*scalex0;
+  else
+    output[0]=point[0]*scalex1;
+
+  // Then y-coordinate in three steps
+  if (point[1]<-PC_AC)
+    output[1]=(point[1]+PC_AC)*scaley0+pc;
+  else if (point[1]<=0.0)
+    output[1]=point[1]*scaley1;
+  else
+    output[1]=point[1]*scaley2;
+
+  // Then z-coordinate this is again easy 
+  if (point[2]<0.0)
+    output[2]= point[2]*scalez0;
+  else
+    output[2]= point[2]*scalez1;
+
+  // Output x,y,z now in AC/PC space with ac as origin
+  (LinearTransform->GetLinearInverse())->TransformPoint(output,output);
+}
+
+//------------------------------------------------------------------------
+void vtkpxTalairachTransform::ForwardTransformPoint(const double point[3], 
+						    double output[3])
+{
+  if (this->InverseFlag)
+    {
+      vtkpxTalairachInverseTransformPoint(point,output,this->LinearTransform,PC_AC,pc[1],
+					  scalex0,scalex1,scaley0,scaley1,scaley2,scalez0,scalez1);
+      return;
+    }
+
+  vtkpxTalairachForwardTransformPoint(this,point,output,this->LinearTransform,this->ac,this->pc,this->minc,this->maxc,
+				      RIGHT_AC,AC_LEFT,BACK_PC,PC_AC,AC_FRONT,BOTTOM_AC,AC_TOP);
+
+}
+
+void vtkpxTalairachTransform::ForwardTransformPoint(const float point[3], 
+						    float output[3])
+{
+  if (this->InverseFlag)
+    {
+      vtkpxTalairachInverseTransformPoint(point,output,this->LinearTransform,PC_AC,pc[1],
+					  scalex0,scalex1,scaley0,scaley1,scaley2,scalez0,scalez1);
+      return;
+    }
+
+  vtkpxTalairachForwardTransformPoint(this,point,output,this->LinearTransform,this->ac,this->pc,this->minc,this->maxc,
+				      RIGHT_AC,AC_LEFT,BACK_PC,PC_AC,AC_FRONT,BOTTOM_AC,AC_TOP);
+
+}
+
+void vtkpxTalairachTransform::InverseTransformPoint(const float point[3], float output[3])
+{
+  if (this->InverseFlag)
+    {
+      vtkpxTalairachInverseTransformPoint(point,output,this->LinearTransform,PC_AC,pc[1],
+					  scalex0,scalex1,scaley0,scaley1,scaley2,scalez0,scalez1);
+      return;
+    }
+
+  vtkpxTalairachForwardTransformPoint(this,point,output,this->LinearTransform,this->ac,this->pc,this->minc,this->maxc,
+				      RIGHT_AC,AC_LEFT,BACK_PC,PC_AC,AC_FRONT,BOTTOM_AC,AC_TOP);
+}
+
+void vtkpxTalairachTransform::InverseTransformPoint(const double point[3], double output[3])
+{
+  if (this->InverseFlag)
+    {
+      vtkpxTalairachInverseTransformPoint(point,output,this->LinearTransform,PC_AC,pc[1],
+					  scalex0,scalex1,scaley0,scaley1,scaley2,scalez0,scalez1);
+      return;
+    }
+
+  vtkpxTalairachForwardTransformPoint(this,point,output,this->LinearTransform,this->ac,this->pc,this->minc,this->maxc,
+				      RIGHT_AC,AC_LEFT,BACK_PC,PC_AC,AC_FRONT,BOTTOM_AC,AC_TOP);
+}
+//------------------------------------------------------------------------
+void vtkpxTalairachTransform::ForwardTransformDerivative(const double point[3],
+							 double output[3],
+							 double derivative[3][3])
+{
+  if (this->LinearTransform!=NULL)
+    {
+      for (int ia=0;ia<=2;ia++)
+	for (int ib=0;ib<=2;ib++)
+	  derivative[ia][ib]=this->LinearTransform->GetMatrix()->GetElement(ia,ib);
+    }
+  
+}
+
+void vtkpxTalairachTransform::ForwardTransformDerivative(const float point[3],
+							 float output[3],
+							 float derivative[3][3])
+{
+  if (this->LinearTransform!=NULL)
+    {
+      for (int ia=0;ia<=2;ia++)
+	for (int ib=0;ib<=2;ib++)
+	  derivative[ia][ib]=this->LinearTransform->GetMatrix()->GetElement(ia,ib);
+    }
+}
+//------------------------------------------------------------------------
+vtkPolyData* vtkpxTalairachTransform::GetTalairachCube(int inverse)
+{
+
+  if (inverse)
+    this->Inverse();
+
+  vtkPoints* gridpoints=vtkPoints::New();
+  int c_dim[3];
+  c_dim[0]=9;	  c_dim[1]=12;	  c_dim[2]=13;
+
+  gridpoints->SetNumberOfPoints(c_dim[0]*c_dim[1]*c_dim[2]);
+
+  vtkUnsignedCharArray* scal=vtkUnsignedCharArray::New();
+  scal->SetNumberOfComponents(3);
+  scal->SetNumberOfTuples(c_dim[0]*c_dim[1]*c_dim[2]);
+
+  float x[3];
+  int index=0,i=0;
+
+  for (i=0;i<c_dim[0];i++)
+    {
+      if (i<4)
+	x[0]=-0.25*float(4-i)*this->GetRIGHT_AC();
+      else if (i>4)
+	x[0]=+0.25*float(i-4)*this->GetAC_LEFT();
+      else
+	x[0]=0.0;
+
+      for (int j=0;j<c_dim[1];j++)
+	{
+	  if (j<4)
+	    x[1]=-0.25*float(4-j)*this->GetBACK_PC()-this->GetPC_AC();
+	  else if (j==4)
+	    x[1]=-this->GetPC_AC();
+	  else if (j==5)
+	    x[1]=-2.0/3.0*this->GetPC_AC();
+	  else if (j==6)
+	    x[1]=-1.0/3.0*this->GetPC_AC();
+	  else if (j==7)
+	    x[1]=0.0;
+	  else
+	    x[1]=0.25*float(j-7)*this->GetAC_FRONT();
+	
+
+	  for (int k=0;k<c_dim[2];k++)
+	    {
+	      if ( k<4)
+		x[2]=-0.25*float(4-k)*this->GetBOTTOM_AC();
+	      else if (k==4)
+		x[2]=0.0;
+	      else 
+		x[2]=0.125*float(k-4)*this->GetAC_TOP();
+	      
+	      float c[3];
+	      c[0]=0; c[1]=0; c[2]=0;
+
+	      float tx[3];
+	      this->TransformPoint(x,tx);
+
+	      if (this->StandardMode==1)
+		{
+		  tx[1]=(AC_FRONT+this->Offset)-x[1];
+		  tx[0]=(AC_LEFT+this->Offset)-x[0];
+		}
+      	      
+	      
+	      if (i==4)
+		{
+		  c[0]=255.0;
+		  c[1]=255.0;
+		  c[2]=0.0;
+		}
+	      else
+		{
+		  c[0]=64-float(i-4)*12.0;
+
+		  if (j==4)
+		    {
+		      c[0]=128.0;
+		      c[1]=128.0;
+		      c[2]=128.0;
+		    }
+		  else if (j==7)
+		    {
+		      c[0]=255.0;
+		      c[1]=255.0;
+		      c[2]=255.0;
+		    }
+		  else if (j==5 || j==6)
+		    {
+		      c[0]=192.0;
+		      c[1]=192.0;
+		      c[2]=192.0;
+		    }
+		  else 
+		    {
+		      if (j<4)
+			c[1]=abs(4-j)*12;
+		      else if (j>7)
+			c[1]=abs(j-7)*12;
+		      
+		      if (k==4)
+			c[2]=255.0;
+		      else
+			c[2]=0.0;
+		    }
+		}
+	      gridpoints->SetPoint(index,tx);
+	      scal->SetTuple(index,c);
+	      index++;
+	    }
+	}
+    }
+
+  if (inverse)
+    this->Inverse();
+
+  // Do Lines Now
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  c_lines->Allocate(3*c_dim[0]*c_dim[1]*c_dim[2],10);
+  int c_dim12=c_dim[1]*c_dim[2];
+  for (i=0;i<c_dim[0];i++)
+    for (int j=0;j<c_dim[1];j++)
+      for (int k=0;k<c_dim[2];k++)
+	{
+	  int index=k+j*c_dim[2]+i*c_dim12;
+
+	  if (k<c_dim[2]-1)
+	    {
+	      c_lines->InsertNextCell(2);
+	      c_lines->InsertCellPoint(index);
+	      c_lines->InsertCellPoint(index+1);
+	    }
+
+	  if (j<c_dim[1]-1)
+	    {
+	      c_lines->InsertNextCell(2);
+	      c_lines->InsertCellPoint(index);
+	      c_lines->InsertCellPoint(index+c_dim[2]);
+	    }
+
+	  if (i<c_dim[0]-1)
+	    {
+	      c_lines->InsertNextCell(2);
+	      c_lines->InsertCellPoint(index);
+	      c_lines->InsertCellPoint(index+c_dim12);
+	    }
+	}
+  
+	  
+  //vtkStructuredGrid* sgrid=vtkStructuredGrid::New();
+  //  sgrid->SetDimensions(c_dim[2],c_dim[1],c_dim[0]);
+  //sgrid->SetPoints(gridpoints);
+  //sgrid->GetPointData()->SetScalars(scal);
+
+  vtkPolyData* sgrid=vtkPolyData::New();
+  sgrid->SetPoints(gridpoints);
+  sgrid->SetLines(c_lines);
+  sgrid->GetPointData()->SetScalars(scal);
+  
+
+  scal->Delete();
+  gridpoints->Delete();
+  c_lines->Delete();
+  return sgrid;
+}
+//------------------------------------------------------------------------
+void vtkpxTalairachTransform::SetStandardModeOn()
+{
+  this->ColinMode=0;
+  this->StandardMode=1;
+  this->Modified();
+}
+
+int vtkpxTalairachTransform::Load(const char* fname)
+{
+  char line[200];
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+      {
+	vtkErrorMacro(<<"Failed to Read Talairach Transform from "<< fname << ". Bad filename.");
+	return 0;
+      }
+  
+  gzgets(fin,line,100);
+  // fprintf(stderr,"line=%s\n",line);
+  if (gzfindstringinstring(line,"#Talairach Transform")==0)
+    {
+      vtkErrorMacro(<<"Failed to Read Talairach Transform from "<< fname << ". Bad Header.");
+      gzclose(fin);
+      return 0;
+    }
+
+  gzgets(fin,line,100); // Linear Transform Header
+  if (this->LinearTransform==NULL)
+    this->LinearTransform=vtkTransform::New();
+  this->LinearTransform->Identity();
+  
+  vtkMatrix4x4* matrix=vtkMatrix4x4::New();
+  matrix->Identity();
+  float tmp[4];
+  for (int i=0;i<=3;i++)
+    {
+      gzgets(fin,line,100); 
+      // fprintf(stderr,"line=%s\n",line);
+      sscanf(line,"%f %f %f %f",&tmp[0],&tmp[1],&tmp[2],&tmp[3]);
+      for (int j=0;j<=3;j++)
+	{
+	  //	  fprintf(stderr,"Setting Elment %d, %d to %.1f\n",i,j,tmp[j]);
+	  matrix->SetElement(i,j,tmp[j]);
+	}
+    }
+      
+  this->LinearTransform->Identity();
+  this->LinearTransform->PostMultiply();
+  this->LinearTransform->Concatenate(matrix);
+  matrix->Delete();
+  
+      
+  gzgets(fin,line,100);  // AC Header
+  gzgets(fin,line,100); 
+  // fprintf(stderr,"line=%s\n",line);
+  sscanf(line,"%lf %lf %lf",&ac[0],&ac[1],&ac[2]);
+  // fprintf(stderr,"Setting Ac %.1f %.1f %.1f\n",ac[0],ac[1],ac[2]);
+  
+  gzgets(fin,line,100);  // PC Header
+  gzgets(fin,line,100); 
+  // fprintf(stderr,"line=%s\n",line);
+  sscanf(line,"%lf %lf %lf",&pc[0],&pc[1],&pc[2]);
+  // fprintf(stderr,"Setting Pc %.1f %.1f %.1f\n",pc[0],pc[1],pc[2]);
+  
+  gzgets(fin,line,100);  // MINC Header
+  gzgets(fin,line,100); 
+  // fprintf(stderr,"line=%s\n",line);
+  sscanf(line,"%lf %lf %lf",&minc[0],&minc[1],&minc[2]);
+  // fprintf(stderr,"Setting Minc %.1f %.1f %.1f\n",minc[0],minc[1],minc[2]);
+  
+  gzgets(fin,line,100);  // MAXC Header
+  gzgets(fin,line,100); 
+  // fprintf(stderr,"line=%s\n",line);
+  sscanf(line,"%lf %lf %lf",&maxc[0],&maxc[1],&maxc[2]);
+  // fprintf(stderr,"Setting Maxc %.1f %.1f %.1f\n",maxc[0],maxc[1],maxc[2]);
+  
+  gzgets(fin,line,100);  // RIGHT_AC,LEFT_AC Header
+  gzgets(fin,line,100); 
+  // fprintf(stderr,"line=%s\n",line);
+  sscanf(line,"%lf %lf", &RIGHT_AC, &AC_LEFT);
+  
+  gzgets(fin,line,100);  // BACK_PC,PC_AC,AC_FRONT Header
+  gzgets(fin,line,100); 
+  //fprintf(stderr,"line=%s\n",line);
+  sscanf(line,"%lf %lf %lf",&BACK_PC,&PC_AC,&AC_FRONT);
+  
+  gzgets(fin,line,100);  // BOTTOM_AC,LEFT_AC Header
+  gzgets(fin,line,100); 
+  // fprintf(stderr,"line=%s\n",line);
+  sscanf(line,"%lf %lf", &BOTTOM_AC, &AC_TOP);
+  
+  gzclose(fin);
+  
+  this->ColinMode=0;
+  this->StandardMode=-1;
+  this->SetScalingConstants();
+  this->Modified();
+  return(1);
+}
+
+int vtkpxTalairachTransform::Save(const char* fname)
+{
+  if (this->LinearTransform==NULL)
+    {
+      vtkErrorMacro(<<"Cannot Save Talairach Transform, no linear transform");
+      return 0;
+    }
+
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+    {
+      vtkErrorMacro(<<"Cannot Save Talairach Transform, bad filename " << fname);
+      return 0;
+    }
+
+  fprintf(fout,"#Talairach Transform\n");
+
+  fprintf(fout,"#Linear Transform\n");
+  vtkMatrix4x4* matrix=this->LinearTransform->GetMatrix();
+  for (int i=0;i<=3;i++)
+    {
+      for (int j=0;j<=3;j++)
+	fprintf(fout,"%7.3f ",matrix->GetElement(i,j));
+      fprintf(fout,"\n");
+    }
+  fprintf(fout,"#AC\n");
+  fprintf(fout,"%.2f %.2f %.2f\n",ac[0],ac[1],ac[2]);
+  fprintf(fout,"#PC\n");
+  fprintf(fout,"%.2f %.2f %.2f\n",pc[0],pc[1],pc[2]);
+  fprintf(fout,"#Minc\n");
+  fprintf(fout,"%.2f %.2f %.2f\n",minc[0],minc[1],minc[2]);
+  fprintf(fout,"#Maxc\n");
+  fprintf(fout,"%.2f %.2f %.2f\n",maxc[0],maxc[1],maxc[2]);
+  fprintf(fout,"#RIGHT_AC,LEFT_AC\n%.1f %.1f\n", RIGHT_AC, AC_LEFT);
+  fprintf(fout,"#BACK_PC,PC_AC,AC_FRONT\n%.1f %.1f %.1f\n",BACK_PC,PC_AC,AC_FRONT);
+  fprintf(fout,"#BOTTOM_AC, AC_TOP\n%.1f %.1f\n",BOTTOM_AC,AC_TOP);
+
+  fclose(fout);
+  return 1;
+}
+//------------------------------------------------------------------------
+//   Talairach Reslice Image 
+//------------------------------------------------------------------------
+vtkImageData* vtkpxTalairachTransform::ResliceImage(vtkImageData* image,int linearOnly)
+{
+  return ResliceImage(image,linearOnly,NULL);
+}
+
+vtkImageData* vtkpxTalairachTransform::ResliceImage(vtkImageData* image,int linearOnly,vtkbisImageReslice* resl)
+{
+  if (image==NULL)
+    {
+      vtkErrorMacro(<<"NULL Input Cannot Reslice");
+      return NULL;
+    }
+
+  if (LinearTransform==NULL)
+    {
+      vtkErrorMacro(<<"No Transform Cannot Reslice");
+      return NULL;
+    }
+
+  vtkbisImageReslice* reslice;
+
+  if (resl!=NULL)
+    {
+      reslice=resl;
+    }
+  else
+    {
+      reslice=vtkbisImageReslice::New();
+      reslice->SetInterpolationModeToLinear();
+      reslice->SetBackgroundLevel(10.0) ;
+      reslice->OptimizationOff();
+    }
+  
+  reslice->SetInput(image);
+
+  int dim[3];
+  dim[0]=this->Offset*2+int(RIGHT_AC+AC_LEFT)+1;
+  dim[1]=this->Offset*2+int(BACK_PC+PC_AC+AC_FRONT);
+  dim[2]=this->Offset*2+int(BOTTOM_AC+AC_TOP)+this->AdditionalZOffset;
+   
+  double ori[3];
+  ori[0]=-(float(this->Offset)+RIGHT_AC);
+  ori[1]=-(float(this->Offset)+BACK_PC+PC_AC);
+  ori[2]=-(float(this->Offset+this->AdditionalZOffset)+BOTTOM_AC);
+  
+  if (linearOnly)
+    {
+      vtkTransform *tr=vtkTransform::New();
+      tr->PostMultiply();
+      tr->Identity();
+      tr->Translate(-ac[0],-ac[1],-ac[2]);
+      tr->Concatenate(this->LinearTransform->GetLinearInverse());
+      
+      reslice->SetResliceTransform(tr);
+      tr->Delete();
+      reslice->SetInformationInput(image);
+    }
+  else
+    {
+      reslice->SetOutputOrigin(ori);
+      reslice->SetOutputExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+      reslice->SetOutputSpacing(1.0,1.0,1.0);
+      reslice->SetResliceTransform(this);
+      this->InverseFlag=1;
+    }
+
+
+
+  vtkImageFlip* flip=vtkImageFlip::New();
+  flip->SetInput(reslice->GetOutput());
+  flip->SetFilteredAxis(1);
+  flip->Update();
+
+  this->InverseFlag=0;
+
+  vtkImageData* output=vtkImageData::New();
+  output->ShallowCopy(flip->GetOutput());
+  output->SetOrigin(0,0,0);
+  
+  flip->Delete();
+
+  if (resl==NULL)
+    reslice->Delete();
+  return output;
+
+}
+
+//------------------------------------------------------------------------
+void vtkpxTalairachTransform::SetColinMode(int colinmode,vtkImageData* img)
+{
+  int debug=0;
+  if(debug>0) 
+    fprintf(stderr,"Setting Colin Mode=%d\n",colinmode);
+
+  int ok=0;
+  int badimage=0;
+  int np=0;
+  if (img==NULL)
+    {
+      badimage=1;
+    }
+  else
+    {
+      np=img->GetNumberOfPoints();
+      if (np!=5903040 && np!=7109137 && np!=902629)
+	badimage=1;
+    }
+  
+  if (badimage==1)
+    {
+      if(debug>0)      fprintf(stderr,"Not the Colin Brain\n");
+      this->ColinMode=0;
+      this->SetStandardModeOn();
+      this->Modified();
+      return;
+    }
+
+  if(debug>0) 
+    fprintf(stderr,"Still Setting Colin Mode=%d np=%d\n",colinmode,np);
+
+  if (colinmode!=0)
+    {
+      if(debug>0)
+	fprintf(stderr,"Loading Colin %d\n",np);
+      ok=vtkpxTalairachTransformHelper::LoadColinLookup(np);
+    }
+  
+  if(debug>0)
+    fprintf(stderr,"Ok=%d\n",ok);
+  
+  if (ok==0)
+    {
+      if(debug>0)
+	fprintf(stderr,"Setting Colin Mode to 0\n");
+      this->ColinMode=0;
+      this->SetStandardModeOn();
+      this->Modified();
+      return;
+    }
+  else if (colinmode<0)
+    {
+      this->SetMontrealMode(0);
+      this->ColinMode=-1;
+      if(debug>0)
+	fprintf(stderr,"Setting Colin Mode to -1\n");
+    }
+  else if (colinmode>0)
+    {
+      this->SetMontrealMode(1);
+      this->ColinMode=1;
+      if(debug>0)
+	fprintf(stderr,"Setting Colin Mode to 1\n");
+    }
+
+  if(debug>0)
+    fprintf(stderr,"before talairach helper\n");
+
+  int d[3]; vtkpxTalairachTransformHelper::ColinLookup->GetDimensions(d);
+
+  if(debug>0)
+    fprintf(stderr,"after talairach helper\n");
+
+  this->ColinYSize=d[1]-1;
+
+  if(debug>0)
+    fprintf(stderr,"Final Colin Mode=%d\n",this->ColinMode);
+  this->Modified();
+  this->Update();
+}
+
+void vtkpxTalairachTransform::SetMontrealMode(int yaxisfronttoback)
+{
+  static double pts[10][3]= { 
+    {  87.00, 91.00, 66.00 },
+    {  87.00,121.00, 66.00 },
+    {  87.00,121.00, 66.00 },
+    {  87.00,121.00,139.00 },
+    {  97.00,131.00,155.00 },
+    { 103.00, 20.00, 74.00 },
+    {  76.00,199.00, 67.00 },
+    { 158.00,120.00, 57.00 },
+    {  14.00,124.00, 71.00 },
+    {  58.00,100.00, 17.00 }};
+  /*
+    { 87.00,  91.00,  66.00},
+    { 87.00, 121.00,  66.00},
+    { 87.00, 121.00,  66.00},
+    { 87.00, 121.00, 139.00},
+    { 97.00, 131.00, 153.00},
+    {103.00,  20.00,  74.00},
+    { 76.00, 199.00,  67.00},
+    {158.00, 120.00,  57.00},
+    { 14.00, 124.00,  71.00},
+    { 58.00,  98.00,  21.00}};*/
+
+
+  vtkPoints* points=vtkPoints::New();
+  points->SetNumberOfPoints(10);
+  for (int ia=0;ia<10;ia++)
+    {
+      if (yaxisfronttoback)
+	points->SetPoint(ia,pts[ia][0],pts[ia][1],pts[ia][2]);
+      else
+	points->SetPoint(ia,pts[ia][0],219.0-pts[ia][1],pts[ia][2]);
+    }
+
+  this->SetLandmarks(points);
+  points->Delete();
+  this->ColinMode=0;
+  return;
+	
+  /*  
+  if (this->LinearTransform==NULL)
+    this->LinearTransform=vtkTransform::New();
+  this->LinearTransform->Identity();
+  
+  vtkMatrix4x4* matrix=vtkMatrix4x4::New();
+  matrix->Identity();
+
+
+    {
+      matrix->SetElement(0,0,-1);
+      matrix->SetElement(1,1,-1);
+      matrix->SetElement(0,3,87);
+      matrix->SetElement(1,3,90);
+      matrix->SetElement(2,3,-64);
+      
+      this->LinearTransform->Identity();
+      this->LinearTransform->PostMultiply();
+      this->LinearTransform->Concatenate(matrix);
+      matrix->Delete();
+      
+      //#AC
+      ac[0]=87.00; ac[1]=90.00; ac[2]=64.00;
+      //#PC
+      pc[0]=0.00; pc[1]= -32.0; pc[2]=0.00;
+      //#Minc
+      minc[0]=-72.0; minc[1]=-110.0; minc[2]=-44.0;
+      //#Maxc
+      maxc[0]=75.00; maxc[1]=71.00; maxc[2]=90.0;
+    } 
+  else
+    {
+      matrix->SetElement(0,3,-87.0);
+      matrix->SetElement(1,3,-129.0);
+      matrix->SetElement(2,3,-64);
+      
+      this->LinearTransform->Identity();
+      this->LinearTransform->PostMultiply();
+      this->LinearTransform->Concatenate(matrix);
+      matrix->Delete();
+      
+      //#AC
+      ac[0]=87.00; ac[1]=129.00; ac[2]=64.00;
+      //#PC
+      pc[0]=0.00; pc[1]= -32.0; pc[2]=0.00;
+      //#Minc
+      minc[0]=-75.0; minc[1]=-110.0; minc[2]=-44.0;
+      //#Maxc
+      maxc[0]=72.00; maxc[1]=71.00; maxc[2]=90.0;
+    }
+    
+  //#RIGHT_AC,LEFT_AC
+  RIGHT_AC=69.0; AC_LEFT=69.0;
+  //#BACK_PC,PC_AC,AC_FRONT
+  BACK_PC=80.0; PC_AC=24.0; AC_FRONT=69.0;
+  //#BOTTOM_AC, AC_TOP
+  BOTTOM_AC=43.0; AC_TOP=74.0;
+  
+  this->StandardMode=-1;
+  this->SetScalingConstants();5
+  this->Modified();
+  return;*/
+}
+
+int vtkpxTalairachTransform::SetColinLookupFileName(char* fname,int mode)
+{
+  //  fprintf(stderr,"Setting Filename from vtkpxTalairachTransform %s (mode=%d)\n",fname,mode);
+  return vtkpxTalairachTransformHelper::SetColinLookupFileName(fname,mode);
+}
+
+
+vtkImageData* vtkpxTalairachTransform::GenerateLookupTable(vtkImageData* img,vtkAbstractTransform* tr)
+{
+  if (img==NULL)
+    {
+      vtkErrorMacro(<<"Bad Input\n");
+      return NULL;
+    }
+
+  vtkImageData* out=vtkImageData::New();
+  out->CopyStructure(img);
+  out->SetScalarTypeToFloat();
+  out->SetNumberOfScalarComponents(3);
+  out->AllocateScalars();
+
+  vtkDataArray* dat=out->GetPointData()->GetScalars();
+  int np=dat->GetNumberOfTuples();
+  for (int i=0;i<np;i++)
+    {
+      double x[3];
+      img->GetPoint(i,x);
+      if (tr!=NULL)
+	tr->TransformPoint(x,x);
+      this->TransformPoint(x,x);
+
+      double x2[3];
+      for (int ia=0;ia<=2;ia++)
+	{
+	  //	  int a=int(x[ia]+0.5);
+	  x2[ia]=x[ia]*10.0;//a+128;
+	}
+      dat->SetTuple(i,x2);
+    }
+
+  return out;
+}
+
+int vtkpxTalairachTransform::ReorientCoordinates(vtkImageData* img, int inputorientation,double x[3],double y[3])
+{
+  if ( (inputorientation!=1 && inputorientation!=2) || (img == NULL))
+    {
+      for (int ia=0;ia<=2;ia++)
+	y[ia]=x[ia];
+      return 0;
+    }
+
+
+  int dim[3]; img->GetDimensions(dim);
+  double spa[3]; img->GetSpacing(spa);
+  double ori[3]; img->GetOrigin(ori);
+  
+
+  if (inputorientation==1)
+    {
+      // x->x
+      y[0]=x[0];
+      // z->y
+      y[1]=x[2];
+      // -y->z
+      y[2]=x[1]-ori[1];
+      y[2]=(double(dim[1]-1.0)*spa[2])-y[2];
+      y[2]+=ori[1];
+
+      // z->y
+
+      return 1;
+    }
+
+  // Sagital
+  //     mat->SetElement(0, 0,  0) ;  mat->SetElement(0, 1, 1) ;  mat->SetElement(0, 2, 0);
+  y[1]=x[0];
+  //      mat->SetElement(1, 0,  0) ;  mat->SetElement(1, 1, 0) ;  mat->SetElement(1, 2, 1);
+  y[2]=x[1];
+  //      mat->SetElement(2, 0, -1) ;  mat->SetElement(2, 1, 0) ;  mat->SetElement(2, 2, 0);
+  y[0]=x[2]-ori[2];
+  y[0]=(double(dim[2]-1.0)*spa[2])-y[0];
+  y[0]+=ori[2];
+    
+  return 1;
+
+}
+
diff --git a/bioimagesuite30_src/GUI/vtkpxTalairachTransform.h b/bioimagesuite30_src/GUI/vtkpxTalairachTransform.h
new file mode 100644
index 0000000..b00bd22
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxTalairachTransform.h
@@ -0,0 +1,256 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxTalairachTransform.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+ ========================================================================*/
+
+#ifndef __vtkpxTalairachTransform_h
+#define __vtkpxTalairachTransform_h
+
+#include "vtkWarpTransform.h"
+
+class vtkTransform;
+class vtkPolyData;
+class vtkImageData;
+class vtkbisImageReslice;
+
+
+
+class vtkpxTalairachTransform : public vtkWarpTransform
+{
+public:
+  vtkTypeMacro(vtkpxTalairachTransform,vtkWarpTransform);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  static vtkpxTalairachTransform *New();
+
+  // Description:
+  // Set the source landmarks for the warp.  If you add or change the
+  // vtkPoints object, you must call Modified() on it or the transformation
+  // might not update.
+  // Point 0 = AC , Point 1 = PC , Points 2-7 Define Bounds 
+  virtual void SetLandmarks(vtkPoints *source);
+  vtkGetObjectMacro(Landmarks,vtkPoints);
+
+
+  // Description:
+  // Get the MTime.
+  unsigned long GetMTime();
+
+  // Description:
+  // Make another transform of the same type.
+  vtkAbstractTransform *MakeTransform();
+
+  // Description:
+  // Generate a talarach cube 
+  virtual vtkPolyData* GetTalairachCube(int inverse=1);
+  
+  // Description:
+  // Reslice image to standard image (MNI?) given this talairach transform 
+  vtkImageData* ResliceImage(vtkImageData* image,int linearOnly=0);
+
+  // Description:
+  // Reslice image as above but with given vtkbisImageReslice (allows for ProgressMethod stuff)
+  vtkImageData* ResliceImage(vtkImageData* image,int linearOnly,vtkbisImageReslice* resl);
+
+  // Description:
+  // Define Talairach Atlas in mm
+  vtkSetMacro(AC_FRONT,double);
+  vtkGetMacro(AC_FRONT,double);
+  vtkSetMacro(PC_AC,double);
+  vtkGetMacro(PC_AC,double);
+  vtkSetMacro(BACK_PC,double);
+  vtkGetMacro(BACK_PC,double);
+  vtkSetMacro(RIGHT_AC,double);
+  vtkGetMacro(RIGHT_AC,double);
+  vtkSetMacro(AC_LEFT,double);
+  vtkGetMacro(AC_LEFT,double);
+  vtkSetMacro(BOTTOM_AC,double);
+  vtkGetMacro(BOTTOM_AC,double);
+  vtkSetMacro(AC_TOP,double);
+  vtkGetMacro(AC_TOP,double);
+
+  // Description:
+  // Define offset of image boundaries to talaraich cube
+  vtkSetMacro(Offset,int);
+  vtkGetMacro(Offset,int);
+
+  // Description:
+  // Define offset of image boundaries to talaraich cube
+  vtkSetMacro(AdditionalZOffset,int);
+  vtkGetMacro(AdditionalZOffset,int);
+
+  // Description:
+  // If StandardMode = 1 then image has been resliced to Talairach Axis etc.
+  vtkGetMacro(StandardMode,int);
+  virtual void SetStandardModeOn();
+    
+  // Description:
+  // Get Linear Transform
+  vtkTransform* GetLinearTransform() 
+  { return this->LinearTransform;}
+
+  // Description:
+  // Save & Load Transform into .tal file
+  int Load(const char* fname);
+  int Save(const char* fname);
+
+
+  // Description:
+  // Set To MNI Brain Coordinates
+  void SetMontrealMode(int yaxisfronttoback=1);
+
+  // Description:
+  // Colin Mode = 0  : not using the colin brain
+  // Colin Mode = 1  : Colin Brain yaxis front to back.
+  // Colin Mode = -1 : Colin Brain yaxis back to front.
+  vtkGetMacro(ColinMode,int);
+  vtkGetMacro(ColinYSize,int);
+  void SetColinMode(int mode,vtkImageData* img);
+
+  // Description:
+  // Get MNI Coordinates
+  virtual int GetMNICoordinates(double x[3],double mni[3]);
+
+  // Description:
+  // Map Coordinates from different orientations
+  virtual int ReorientCoordinates(vtkImageData* img, int inputorientation,double x[3],double y[3]);
+
+  // Description:
+  // Generates a Lookup Table from the Current Transformation
+  virtual vtkImageData* GenerateLookupTable(vtkImageData* img,vtkAbstractTransform* tr=NULL);
+
+  // Description:
+  // Set Colin Lookup Table Name
+  virtual int SetColinLookupFileName(char* fname,int mode=0);
+
+protected:
+  vtkpxTalairachTransform();
+  ~vtkpxTalairachTransform();
+  vtkpxTalairachTransform(const vtkpxTalairachTransform&) {};
+  void operator=(const vtkpxTalairachTransform&) {};
+
+  // Description:
+  // Prepare the transformation for application.
+  void InternalUpdate();
+
+  // Description:
+  // This method does no type checking, use DeepCopy instead.
+  void InternalDeepCopy(vtkAbstractTransform *transform);
+
+  // Description:
+  // Forward Transform Point -- OK
+  void ForwardTransformPoint(const float in[3], float out[3]);
+  void ForwardTransformPoint(const double in[3], double out[3]);
+
+  // Description:
+  // Forward Transform Derivative (Not done yet) -- OK
+  void ForwardTransformDerivative(const float in[3], float out[3],
+				  float derivative[3][3]);
+  void ForwardTransformDerivative(const double in[3], double out[3],
+				  double derivative[3][3]);
+
+
+  // Description:
+  // If the InverseFlag is set to 1, then a call to InternalTransformPoint
+  // results in a call to InverseTransformPoint.  The inverse transformation
+  // is calculated from using Newton's method.
+  virtual void InverseTransformPoint(const float in[3], float out[3]);
+  virtual void InverseTransformPoint(const double in[3], double out[3]);
+
+  vtkPoints *Landmarks;
+  vtkTransform* LinearTransform;
+
+  //BTX
+  double minc[3],maxc[3],ac[3],pc[3];
+  //ETX
+
+  // Description:
+  // TalairachParameters --- Anterior to Posterior 
+  double AC_FRONT;
+  double PC_AC;
+  double BACK_PC;
+  
+  // Description:
+  // Talairach Parameters --- Right to Left
+  double RIGHT_AC;
+  double AC_LEFT;
+
+  // Description:
+  // Talairach Parameters -- Bottom to Bot
+  double BOTTOM_AC;
+  double AC_TOP;
+
+  // Description:
+  // Reslice Offset -- add extra boundary around
+  int Offset;
+  int AdditionalZOffset;
+  int StandardMode;
+
+  // Colin Mode, 0=No,1=Yes Y=Front-to-Back,-1=Yes Y=Back to Front
+  int ColinMode;
+  int ColinYSize;
+
+  
+  //BTX
+  double scalex0,scalex1,scaley0,scaley1,scaley2,scalez0,scalez1;
+  void SetScalingConstants();
+  //ETX
+};
+
+//----------------------------------------------------------------------------
+
+#endif
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxTalairachTransformHelper.cpp b/bioimagesuite30_src/GUI/vtkpxTalairachTransformHelper.cpp
new file mode 100644
index 0000000..4ac0cf6
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxTalairachTransformHelper.cpp
@@ -0,0 +1,167 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkpxTalairachTransformHelper.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxBaseCurve.h"
+#include "vtkImageData.h"
+#include "vtkpxAnalyzeImageSource.h"
+//----------------------------------------------------------------------------
+vtkImageData* vtkpxTalairachTransformHelper::ColinLookup=NULL;
+char* vtkpxTalairachTransformHelper::ColinLookupFileName=NULL;
+char* vtkpxTalairachTransformHelper::ColinLookupFileName2=NULL;
+
+//----------------------------------------------------------------------------
+vtkpxTalairachTransformHelper* vtkpxTalairachTransformHelper::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxTalairachTransformHelper");
+  if(ret)
+    {
+      return (vtkpxTalairachTransformHelper*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxTalairachTransformHelper;
+}
+
+//------------------------------------------------------------------------
+int vtkpxTalairachTransformHelper::SetColinLookupFileName(char* fname,int mode)
+{
+  if (fname==NULL)
+    {
+      fprintf(stderr,"No FileName Specified\n");
+      return 0;
+    }
+
+  // fprintf(stderr,"In Set Lookup File Name %s %d\n",fname,mode);
+
+  if (mode<1)
+    mode=0;
+  else
+    mode=1;
+
+  if (mode==0)
+    {
+      if (vtkpxTalairachTransformHelper::ColinLookupFileName!=NULL)
+	{
+	  if (strcmp(vtkpxTalairachTransformHelper::ColinLookupFileName,fname)==0)
+	    {
+	      // fprintf(stderr,"Same Name =%s\n",fname);
+	      return 1;
+	    }
+	delete [] vtkpxTalairachTransformHelper::ColinLookupFileName;
+	}
+      vtkpxTalairachTransformHelper::ColinLookupFileName=new char[strlen(fname)+1];
+      strcpy(vtkpxTalairachTransformHelper::ColinLookupFileName,fname);
+      // fprintf(stderr,"Lookup Table Filename =%s\n",vtkpxTalairachTransformHelper::ColinLookupFileName);
+    }
+  else
+    {
+      if (vtkpxTalairachTransformHelper::ColinLookupFileName2!=NULL)
+	{
+	  if (strcmp(vtkpxTalairachTransformHelper::ColinLookupFileName2,fname)==0)
+	    {
+	      // fprintf(stderr,"Same Name =%s\n",fname);
+	      return 1;
+	    }
+	  delete [] vtkpxTalairachTransformHelper::ColinLookupFileName2;
+	}
+      vtkpxTalairachTransformHelper::ColinLookupFileName2=new char[strlen(fname)+1];
+      strcpy(vtkpxTalairachTransformHelper::ColinLookupFileName2,fname);
+      // fprintf(stderr,"Lookup Table Filename 2=%s\n",vtkpxTalairachTransformHelper::ColinLookupFileName2);
+    }
+
+
+  return 1;
+}
+
+int vtkpxTalairachTransformHelper::LoadColinLookup(int numberofvoxels)
+{
+  //  fprintf(stderr,"Number of Voxels=%d\n",numberofvoxels);
+  int mode=-1;
+
+  if (numberofvoxels==902629)
+    numberofvoxels=7109137;
+
+  switch(numberofvoxels)
+    {
+    case 7109137:
+      if (vtkpxTalairachTransformHelper::ColinLookupFileName2!=NULL)
+	{
+	  mode=1;
+	  // fprintf(stderr,"Setting Filename to %s (numberofvoxels=%d)\n",ColinLookupFileName2,numberofvoxels);
+	}
+      break;
+    case 5903040:
+      if (vtkpxTalairachTransformHelper::ColinLookupFileName!=NULL)
+	{
+	  mode=0;
+	  // fprintf(stderr,"Setting Filename to %s (numberofvoxels=%d)",ColinLookupFileName,numberofvoxels);
+	}
+      break;
+    }
+
+  if (mode==-1)
+    {
+      // fprintf(stderr,"Cannot Load Colin Lookup Table (No FileName)\n");
+      return 0;
+    }
+
+  if(vtkpxTalairachTransformHelper::ColinLookup!=NULL)
+    {
+      int np=vtkpxTalairachTransformHelper::ColinLookup->GetNumberOfPoints();
+      if (np==numberofvoxels)
+	{
+	  //  fprintf(stderr,"Proper Colin Lookup Table %d already loaded\n",np);
+	  return 1;
+	}
+    }
+
+
+  //  fprintf(stderr,"TH::Loading Colin Lookup Table mode=%d\n",mode);
+  vtkpxAnalyzeImageSource* ana=vtkpxAnalyzeImageSource::New();
+  if (mode==0)
+    ana->Load(vtkpxTalairachTransformHelper::ColinLookupFileName);
+  else
+    ana->Load(vtkpxTalairachTransformHelper::ColinLookupFileName2);
+  int vox=ana->GetOutput()->GetNumberOfPoints();
+  int ok=0;
+  if (vox==5903040 || vox==7109137)
+    {
+      ok=1;
+      if(vtkpxTalairachTransformHelper::ColinLookup==NULL)
+	vtkpxTalairachTransformHelper::ColinLookup=vtkImageData::New();
+      vtkpxTalairachTransformHelper::ColinLookup->ShallowCopy(ana->GetOutput());
+    }
+  ana->Delete();
+  //fprintf(stderr,"Done Loading Colin Lookup Table %d\n",ok);
+  return ok;
+}
+
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxTalairachTransformHelper.h b/bioimagesuite30_src/GUI/vtkpxTalairachTransformHelper.h
new file mode 100644
index 0000000..92ac5dc
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxTalairachTransformHelper.h
@@ -0,0 +1,101 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxTalairachTransform.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+ ========================================================================*/
+
+#ifndef __vtkpxTalairachTransformHelper_h
+#define __vtkpxTalairachTransformHelper_h
+
+#include "vtkObject.h"
+
+class vtkTransform;
+class vtkPolyData;
+class vtkImageData;
+class vtkbisImageReslice;
+//#include "vtkAbstractTransform.h"
+
+
+class vtkpxTalairachTransformHelper : public vtkObject
+{
+public:
+  vtkTypeMacro(vtkpxTalairachTransformHelper,vtkObject);
+  static vtkpxTalairachTransformHelper *New();
+
+  // Description:
+  // This is the Colin Brain Talairach Transform Lookup Table
+  static vtkImageData* ColinLookup;
+  static char*         ColinLookupFileName;
+  static char*         ColinLookupFileName2;
+
+  static int SetColinLookupFileName(char* fname,int mode=0);
+  static int LoadColinLookup(int numberofvoxels);
+  
+
+
+protected:
+  vtkpxTalairachTransformHelper() {};
+  ~vtkpxTalairachTransformHelper() {};
+  vtkpxTalairachTransformHelper(const vtkpxTalairachTransformHelper&) {};
+  void operator=(const vtkpxTalairachTransformHelper&) {};
+
+
+};
+
+//----------------------------------------------------------------------------
+
+#endif
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/GUI/vtkpxtkGUIlib.cpp b/bioimagesuite30_src/GUI/vtkpxtkGUIlib.cpp
new file mode 100644
index 0000000..46604b0
--- /dev/null
+++ b/bioimagesuite30_src/GUI/vtkpxtkGUIlib.cpp
@@ -0,0 +1,62 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+Initialization of pxtklib dll
+
+=========================================================================*/
+#include "pxtkapp.h"
+#include "vtkTclUtil.h"
+
+/* --------------- Win32 Stuff -------------------- */
+
+extern "C" {
+int VTK_EXPORT Vtkpxtklib_Init(Tcl_Interp* interp);
+int VTK_EXPORT Vtkpxtklib_SafeInit(Tcl_Interp* interp);
+int VTK_EXPORT Vtkpxguitcl_Init(Tcl_Interp *interp);
+}
+
+int Vtkpxtklib_Init(Tcl_Interp* interp)
+{
+  int a=PXTkApp::initialize(interp);
+  PXTkApp::createConsole();
+  Vtkpxguitcl_Init(interp);
+  return a;
+}
+
+int Vtkpxtklib_SafeInit(Tcl_Interp* interp)
+{
+  return Vtkpxtklib_Init(interp);
+}
+
+
+
diff --git a/bioimagesuite30_src/Graphics/CMakeLists.txt b/bioimagesuite30_src/Graphics/CMakeLists.txt
new file mode 100644
index 0000000..0ee15ab
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/CMakeLists.txt
@@ -0,0 +1,124 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/Graphics)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/CudaVolumeRendering)
+
+SET(KIT vtkpxGraphics)
+
+SET (3D_TEXTURE_MAP 0)
+
+SET (KITSRCS
+vtkpxSurfaceUtil.cpp
+vtkpxAppendAndLabelPolyData.cpp
+vtkpxAddDisplacementVectorToPolyData.cpp
+vtkpxColorMapUtil.cpp
+vtkpxCurveEditUtil.cpp
+vtkpxEnclosedPipeline.cpp
+vtkpxImageSlice.cpp
+vtkpx2DImageSlice.cpp
+vtkpxMapActivationToPolyData.cpp
+vtkpxNormalShrinkPolyData.cpp
+vtkpxOrthoImageSlice.cpp
+vtkpxVolume.cpp
+vtkpxObliqueImageSlice.cpp
+vtkpxCameraInfo.cpp
+#vtkCroppedVolumeRayCastCompositeFunction.cxx
+#vtkCroppedVolumeRayCastFunction.cxx
+#vtkCroppedVolumeRayCastMapper.cxx
+vtkEllipseSource.cxx
+vtkCropVolumeRayCastMapper.cxx
+vtkCropVolumeRayCastCompositeHelper.cxx
+vtkCropVolumeRayCastCompositeShadeHelper.cxx
+vtkCropVolumeRayCastCompositeGOHelper.cxx
+vtkCropVolumeRayCastCompositeGOShadeHelper.cxx
+#
+# Electrode Stuff
+#
+vtkpxElectrodeGridToSurfaceFilter.cpp
+vtkpxElectrodeSource.cpp
+vtkpxElectrodeGridSource.cpp
+vtkpxElectrodeMultiGridSource.cpp
+vtkpxPredictElectrodeStrip.cpp
+)
+
+#SET_SOURCE_FILES_PROPERTIES(	
+#vtkCroppedVolumeRayCastFunction.cxx
+#vtkCroppedVolumeRayCastCompositeFunction.cxx
+#ABSTRACT
+#)
+
+SET_SOURCE_FILES_PROPERTIES(
+#vtkCroppedVolumeRayCastCompositeFunction.cxx
+#vtkCroppedVolumeRayCastFunction.cxx
+#vtkCroppedVolumeRayCastMapper.cxx
+vtkCropVolumeRayCastMapper.cxx
+vtkCropVolumeRayCastCompositeHelper.cxx
+vtkCropVolumeRayCastCompositeShadeHelper.cxx
+vtkCropVolumeRayCastCompositeGOHelper.cxx
+vtkCropVolumeRayCastCompositeGOShadeHelper.cxx
+WRAP_EXCLUDE
+)
+
+
+SET(KITLIBS
+  vtkVolumeRendering
+  vtkpxCommon
+  vtkpxCommonTCL
+  numerics
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+)
+
+SET(KITJAVALIBS
+  vtkVolumeRendering
+  vtkpxCommon
+  vtkpxCommonJava
+  numerics
+  ${BIOIMAGESUITE3_COMMON_JAVALIBS}
+)
+
+
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+SET (KITEXTRAFILES)
+SET (KITTCLSRCS )
+bis_complex("Graphics" ${KIT} ${FILELIST})
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeGOHelper.cxx b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeGOHelper.cxx
new file mode 100644
index 0000000..162c2f1
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeGOHelper.cxx
@@ -0,0 +1,1393 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkCropVolumeRayCastCompositeGOHelper.cxx,v $
+  Language:  C++
+  Date:      $Date: 2007-11-08 16:51:06 $
+  Version:   $Revision: 1.9 $
+
+  Copyright (c) 1993-2002 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 "vtkCropVolumeRayCastCompositeGOHelper.h"
+
+#include "vtkImageData.h"
+#include "vtkCommand.h"
+#include "vtkCropVolumeRayCastMapper.h"
+#include "vtkObjectFactory.h"
+#include "vtkRenderWindow.h"
+#include "vtkVolume.h"
+#include "vtkVolumeProperty.h"
+#include "vtkFixedPointRayCastImage.h"
+#include "vtkDataArray.h"
+
+#include <math.h>
+
+void GOIrregularCropper(unsigned short *val, unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper);
+void GOIrregularCropperArray(unsigned short val[4], unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper);
+
+vtkCxxRevisionMacro(vtkCropVolumeRayCastCompositeGOHelper, "$Revision: 1.9 $");
+vtkStandardNewMacro(vtkCropVolumeRayCastCompositeGOHelper);
+
+// Construct a new vtkCropVolumeRayCastCompositeGOHelper with default values
+vtkCropVolumeRayCastCompositeGOHelper::vtkCropVolumeRayCastCompositeGOHelper()
+{
+}
+
+// Destruct a vtkCropVolumeRayCastCompositeGOHelper - clean up any memory used
+vtkCropVolumeRayCastCompositeGOHelper::~vtkCropVolumeRayCastCompositeGOHelper()
+{
+}
+
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has one component and scale == 1.0 and shift == 0.0. In the inner
+// loop we get the data value as an unsigned short, and use this index to
+// lookup a color and opacity for this sample. We then composite this into
+// the color computed so far along the ray, and check if we can terminate at
+// this point (if the accumulated opacity is higher than some threshold).
+// Finally we move on to the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOHelperGenerateImageOneSimpleNN( T *data,
+                                                   int threadID,
+                                                   int threadCount,
+                                                   vtkCropVolumeRayCastMapper *mapper,
+                                                   vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGONN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_InitializeCompositeGONN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleGONN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short val = static_cast<unsigned short>(((*dptr)));
+    unsigned char  mag = *magPtr;
+
+    VTKKWRCHelper_LookupColorGOUS( colorTable[0], scalarOpacityTable[0],
+                                   gradientOpacityTable[0], val, mag, tmp );
+
+    if ( tmp[3] )
+      {
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has one component. In the inner loop we get the data value as
+// an unsigned short using the scale/shift, and use this index to lookup
+// a color and opacity for this sample. We then composite this into the
+// color computed so far along the ray, and check if we can terminate at
+// this point (if the accumulated opacity is higher than some threshold).
+// Finally we move on to the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOHelperGenerateImageOneNN( T *data,
+                                             int threadID,
+                                             int threadCount,
+                                             vtkCropVolumeRayCastMapper *mapper,
+                                             vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGONN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_InitializeCompositeGONN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleGONN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short val = static_cast<unsigned short>(((*dptr) + shift[0])*scale[0]);
+    unsigned char  mag = *magPtr;
+
+    VTKKWRCHelper_LookupColorGOUS( colorTable[0], scalarOpacityTable[0],
+                                   gradientOpacityTable[0], val, mag, tmp );
+
+    if ( tmp[3] )
+      {
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has two components which are not considered independent. In the
+// inner loop we compute the two unsigned short index values from the data
+// values (using the scale/shift). We use the first index to lookup a color,
+// and we use the second index to look up the opacity. We then composite
+// the color into the color computed so far along this ray, and check to
+// see if we can terminate here (if the opacity accumulated exceed some
+// threshold). Finally we move to the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOHelperGenerateImageTwoDependentNN( T *data,
+                                                      int threadID,
+                                                      int threadCount,
+                                                      vtkCropVolumeRayCastMapper *mapper,
+                                                      vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGONN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_InitializeCompositeGONN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleGONN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short val[2];
+    val[0] = static_cast<unsigned short>(((*(dptr  )) + shift[0])*scale[0]);
+    val[1] = static_cast<unsigned short>(((*(dptr+1)) + shift[1])*scale[1]);
+    unsigned char  mag = *magPtr;
+
+    tmp[3] = (scalarOpacityTable[0][val[1]] * gradientOpacityTable[0][mag] + 0x3fff)>>(VTKKW_FP_SHIFT);
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    tmp[0] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[1] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[2] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has four components which are not considered independent . This
+// means that the first three components directly represent color, and this
+// data must be of unsigned char type. In the inner loop we directly access
+// the four data values (no scale/shift is needed). The first three are the
+// color of this sample and the fourth is used to look up an opacity in the
+// scalar opacity transfer function. We then composite this color into the
+// color we have accumulated so far along the ray, and check if we can
+// terminate here (if our accumulated opacity has exceed some threshold).
+// Finally we move onto the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOHelperGenerateImageFourDependentNN( T *data,
+                                                         int threadID,
+                                                         int threadCount,
+                                                         vtkCropVolumeRayCastMapper *mapper,
+                                                         vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGONN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_InitializeCompositeGONN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleGONN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short val[4];
+    val[0] = *(dptr  );
+    val[1] = *(dptr+1);
+    val[2] = *(dptr+2);
+    val[3] = static_cast<unsigned short>(((*(dptr+3)) + shift[3])*scale[3]);
+
+    unsigned char  mag = *magPtr;
+
+    tmp[3] = (scalarOpacityTable[0][val[3]] * gradientOpacityTable[0][mag] + 0x3fff)>>(VTKKW_FP_SHIFT);
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    tmp[0] = (val[0]*tmp[3]+0x7f)>>(8);
+    tmp[1] = (val[1]*tmp[3]+0x7f)>>(8);
+    tmp[2] = (val[2]*tmp[3]+0x7f)>>(8);
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has more than one component and the components are considered to
+// be independent. In the inner loop we access each component value, using
+// the scale/shift to turn the data value into an unsigned short index. We
+// then lookup the color/opacity for each component and combine them according
+// to the weighting value for each component. We composite this resulting
+// color into the color already accumulated for this ray, and we check
+// wether we can terminate here (if the accumulated opacity exceeds some
+// threshold). Finally we increment to the next sample on the ray.
+template <class T>
+void vtkCropCompositeGOHelperGenerateImageIndependentNN( T *data,
+                                                     int threadID,
+                                                     int threadCount,
+                                                     vtkCropVolumeRayCastMapper *mapper,
+                                                     vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializeWeights();
+  VTKKWRCHelper_InitializationAndLoopStartGONN();
+  VTKKWRCHelper_InitializeCompositeMultiNN();
+  VTKKWRCHelper_InitializeCompositeGONN();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleGONN();
+      }
+
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned char mag[4];
+    for ( c = 0; c < components; c++ )
+      {
+      val[c] = static_cast<unsigned short>(((*(dptr+c)) + shift[c])*scale[c]);
+      mag[c] = static_cast<unsigned short>(*(magPtr+c));
+      }
+
+    VTKKWRCHelper_LookupAndCombineIndependentColorsGOUS( colorTable, scalarOpacityTable,
+                                                         gradientOpacityTable,
+                                                         val, mag, weights, components, tmp );
+
+    if ( tmp[3] )
+      {
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is linear and the data
+// has one component and scale = 1.0 and shift = 0.0. In the inner loop we
+// get the data value for the eight cell corners (if we have changed cells)
+// as an unsigned short (the range must be right and we don't need the
+// scale/shift). We compute our weights within the cell according to our
+// fractional position within the cell, apply trilinear interpolation to
+// compute the index, and use this index to lookup a color and opacity for
+// this sample. We then composite this into the color computed so far along
+// the ray, and check if we can terminate at this point (if the accumulated
+// opacity is higher than some threshold). Finally we move on to the next
+// sample along the ray.
+template <class T>
+void vtkCropCompositeGOHelperGenerateImageOneSimpleTrilin( T *data,
+                                                       int threadID,
+                                                       int threadCount,
+                                                       vtkCropVolumeRayCastMapper *mapper,
+                                                       vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGOTrilin();
+  VTKKWRCHelper_InitializeCompositeOneTrilin();
+  VTKKWRCHelper_InitializeCompositeOneGOTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  int needToSampleGO = 0;
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellScalarValuesSimple( dptr );
+      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      needToSampleGO = 1;
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalar(val);
+
+    tmp[3] = scalarOpacityTable[0][val];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleGO )
+      {
+      VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
+      needToSampleGO = 0;
+      }
+
+    VTKKWRCHelper_InterpolateMagnitude(mag);
+    tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT;
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+	
+	GOIrregularCropper(&val, tmp, pos, mapper);
+
+    tmp[0] = static_cast<unsigned short>
+      ((colorTable[0][3*val  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[1] = static_cast<unsigned short>
+      ((colorTable[0][3*val+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[2] = static_cast<unsigned short>
+      ((colorTable[0][3*val+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is linear and the data
+// has one component and scale != 1.0 or shift != 0.0. In the inner loop we
+// get the data value for the eight cell corners (if we have changed cells)
+// as an unsigned short (we use the scale/shift to ensure the correct range).
+// We compute our weights within the cell according to our fractional position
+// within the cell, apply trilinear interpolation to compute the index, and use
+// this index to lookup a color and opacity for this sample. We then composite
+// this into the color computed so far along the ray, and check if we can
+// terminate at this point (if the accumulated opacity is higher than some
+// threshold). Finally we move on to the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOHelperGenerateImageOneTrilin( T *data,
+                                                 int threadID,
+                                                 int threadCount,
+                                                 vtkCropVolumeRayCastMapper *mapper,
+                                                 vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGOTrilin();
+  VTKKWRCHelper_InitializeCompositeOneTrilin();
+  VTKKWRCHelper_InitializeCompositeOneGOTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  int needToSampleGO = 0;
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellScalarValues( dptr, scale[0], shift[0] );
+      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      needToSampleGO = 1;
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalar(val);
+
+    tmp[3] = scalarOpacityTable[0][val];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleGO )
+      {
+      VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
+      needToSampleGO = 0;
+      }
+    VTKKWRCHelper_InterpolateMagnitude(mag);
+
+    tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT;
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    tmp[0] = static_cast<unsigned short>
+      ((colorTable[0][3*val  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[1] = static_cast<unsigned short>
+      ((colorTable[0][3*val+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[2] = static_cast<unsigned short>
+      ((colorTable[0][3*val+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+// This method is used when the interpolation type is linear, the data has
+// two components and the components are not considered independent. In the
+// inner loop we get the data value for the eight cell corners (if we have
+// changed cells) for both components as an unsigned shorts (we use the
+// scale/shift to ensure the correct range). We compute our weights within
+// the cell according to our fractional position within the cell, and apply
+// trilinear interpolation to compute the two index value. We use the first
+// index to lookup a color and the second to look up an opacity for this sample.
+// We then composite this into the color computed so far along the ray, and
+// check if we can terminate at this point (if the accumulated opacity is
+// higher than some threshold). Finally we move on to the next sample along
+// the ray.
+template <class T>
+void vtkCropCompositeGOHelperGenerateImageTwoDependentTrilin( T *data,
+                                                          int threadID,
+                                                          int threadCount,
+                                                          vtkCropVolumeRayCastMapper *mapper,
+                                                          vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGOTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiTrilin();
+  VTKKWRCHelper_InitializeCompositeOneGOTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  int needToSampleGO = 0;
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] );
+
+      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      needToSampleGO = 1;
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalarComponent( val, c, 2 );
+
+    tmp[3] = scalarOpacityTable[0][val[1]];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleGO )
+      {
+      VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
+      needToSampleGO = 0;
+      }
+
+    VTKKWRCHelper_InterpolateMagnitude(mag);
+    tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT;
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    tmp[0] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[1] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[2] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+
+// This method is used when the interpolation type is linear, the data has
+// four components and the components are not considered independent. In the
+// inner loop we get the data value for the eight cell corners (if we have
+// changed cells) for all components as an unsigned shorts (we don't have to
+// use the scale/shift because only unsigned char data is supported for four
+// component data when the components are not independent). We compute our
+// weights within the cell according to our fractional position within the cell,
+// and apply trilinear interpolation to compute a value for each component. We
+// use the first three directly as the color of the sample, and the fourth is
+// used to look up an opacity for this sample. We then composite this into the
+// color computed so far along the ray, and check if we can terminate at this
+// point (if the accumulated opacity is higher than some threshold). Finally we
+// move on to the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOHelperGenerateImageFourDependentTrilin( T *data,
+                                                             int threadID,
+                                                             int threadCount,
+                                                             vtkCropVolumeRayCastMapper *mapper,
+                                                             vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGOTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiTrilin();
+  VTKKWRCHelper_InitializeCompositeOneGOTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  int needToSampleGO = 0;
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 0 );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 1 );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 2 );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] );
+
+      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      needToSampleGO = 1;
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalarComponent( val, c, 4 );
+
+	GOIrregularCropperArray(val, tmp, pos, mapper);
+
+    tmp[3] = scalarOpacityTable[0][val[3]];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleGO )
+      {
+      VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
+      needToSampleGO = 0;
+      }
+
+    VTKKWRCHelper_InterpolateMagnitude(mag);
+    tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT;
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    tmp[0] = (val[0]*tmp[3]+0x7f)>>8;
+    tmp[1] = (val[1]*tmp[3]+0x7f)>>8;
+    tmp[2] = (val[2]*tmp[3]+0x7f)>>8;
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is linear, the data has
+// more than one component and the components are considered independent. In
+// the inner loop we get the data value for the eight cell corners (if we have
+// changed cells) for all components as an unsigned shorts (we have to use the
+// scale/shift to ensure that we obtained unsigned short indices) We compute our
+// weights within the cell according to our fractional position within the cell,
+// and apply trilinear interpolation to compute a value for each component. We
+// look up a color/opacity for each component and blend them according to the
+// component weights. We then composite this resulting color into the
+// color computed so far along the ray, and check if we can terminate at this
+// point (if the accumulated opacity is higher than some threshold). Finally we
+// move on to the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOHelperGenerateImageIndependentTrilin( T *data,
+                                                         int threadID,
+                                                         int threadCount,
+                                                         vtkCropVolumeRayCastMapper *mapper,
+                                                         vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializeWeights();
+  VTKKWRCHelper_InitializationAndLoopStartGOTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiGOTrilin();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] );
+
+      if ( components > 2 )
+        {
+        dptr++;
+        VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] );
+        if ( components > 3 )
+          {
+          dptr++;
+          VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] );
+          }
+        }
+
+
+      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 0 );
+
+      magPtrABCD++;
+      magPtrEFGH++;
+      VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 1 );
+
+      if ( components > 2 )
+        {
+        magPtrABCD++;
+        magPtrEFGH++;
+        VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 2 );
+        if ( components > 3 )
+          {
+          magPtrABCD++;
+          magPtrEFGH++;
+          VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 3 );
+          }
+        }
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalarComponent( val, c, components );
+    VTKKWRCHelper_InterpolateMagnitudeComponent( mag, c, components );
+
+
+    VTKKWRCHelper_LookupAndCombineIndependentColorsGOUS( colorTable, scalarOpacityTable,
+                                                         gradientOpacityTable, val, mag,
+                                                         weights, components, tmp );
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+void vtkCropVolumeRayCastCompositeGOHelper::GenerateImage( int threadID,
+                                                 int threadCount,
+                                                 vtkVolume *vol,
+                                                 vtkCropVolumeRayCastMapper *mapper )
+{
+  void *data     = mapper->GetCurrentScalars()->GetVoidPointer(0);
+  int scalarType = mapper->GetCurrentScalars()->GetDataType();
+
+  // Nearest Neighbor interpolate
+  if ( mapper->ShouldUseNearestNeighborInterpolation( vol ) )
+    {
+    // One component data
+    if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 1 )
+      {
+      // Scale == 1.0 and shift == 0.0 - simple case (faster)
+      if ( mapper->GetTableScale()[0] == 1.0 && mapper->GetTableShift()[0] == 0.0 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropCompositeGOHelperGenerateImageOneSimpleNN(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      else
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropCompositeGOHelperGenerateImageOneNN(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      }
+    // More that one independent components
+    else if ( vol->GetProperty()->GetIndependentComponents() )
+      {
+      switch ( scalarType )
+        {
+        vtkTemplateMacro(
+          vtkCropCompositeGOHelperGenerateImageIndependentNN(
+            static_cast<VTK_TT *>(data),
+            threadID, threadCount, mapper, vol) );
+        }
+      }
+    // Dependent (color) components
+    else
+      {
+      // Two components - the first specifies color (through a lookup table) and
+      // the second specified opacity (through a lookup table)
+      if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 2 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropCompositeGOHelperGenerateImageTwoDependentNN(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      // Four components - they must be unsigned char, the first three directly
+      // specify color and the fourth specifies opacity (through a lookup table)
+      else
+        {
+        if ( scalarType == VTK_UNSIGNED_CHAR )
+          {
+          vtkCropCompositeGOHelperGenerateImageFourDependentNN(
+            static_cast<unsigned char *>(data), threadID, threadCount, mapper,
+            vol );
+          }
+        else
+          {
+          vtkErrorMacro("Four component dependent must be unsigned char!");
+          }
+        }
+      }
+    }
+  // Trilinear Interpolation
+  else
+    {
+    // One component
+    if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 1 )
+      {
+      // Scale == 1.0 and shift == 0.0 - simple case (faster)
+      if ( mapper->GetTableScale()[0] == 1.0 &&
+           mapper->GetTableShift()[0] == 0.0 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropCompositeGOHelperGenerateImageOneSimpleTrilin(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop
+      else
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropCompositeGOHelperGenerateImageOneTrilin(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      }
+    // Indepedent components (more than one)
+    else if ( vol->GetProperty()->GetIndependentComponents() )
+      {
+      switch ( scalarType )
+        {
+        vtkTemplateMacro(
+          vtkCropCompositeGOHelperGenerateImageIndependentTrilin(
+            static_cast<VTK_TT *>(data),
+            threadID, threadCount, mapper, vol) );
+        }
+      }
+    // Dependent components
+    else
+      {
+      // Two components - the first specifies color (through a lookup table)
+      // and the second specified opacity (through a lookup table)
+      if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 2 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropCompositeGOHelperGenerateImageTwoDependentTrilin(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      // Four components - they must be unsigned char, the first three directly
+      // specify color and the fourth specifies opacity (through a lookup
+      // table)
+      else
+        {
+        if ( scalarType == VTK_UNSIGNED_CHAR )
+          {
+          vtkCropCompositeGOHelperGenerateImageFourDependentTrilin(
+            static_cast<unsigned char *>(data), threadID, threadCount, mapper,
+            vol );
+          }
+        else
+          {
+          vtkErrorMacro("Four component dependent must be unsigned char!");
+          }
+        }
+      }
+    }
+}
+
+// Print method for vtkCropVolumeRayCastCompositeGOHelper
+void vtkCropVolumeRayCastCompositeGOHelper::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+}
+
+
+void GOIrregularCropper(unsigned short *val, unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper)
+{
+
+	double distance_from_point = 0.0;
+	int translucency_set = 0;
+	float end_vector[3];
+
+	float ray_position[3];
+	ray_position[0] = pos[0]/32767 ;
+	ray_position[1] = pos[1]/32767;
+	ray_position[2] = pos[2]/32767;
+
+	double locationxyz[3];
+	double FixedCubeLength[3];
+	double FixedEllipseRadius[3];
+	double CylinderAxis[3];
+
+	locationxyz[0] = locationxyz[1] = locationxyz[2] = 0.0;
+	mapper->GetFixedSphereCenter(locationxyz);
+
+	float angle = 0, centroid_angle =0;
+	float total_distance = 0;
+	int c = 0;
+
+	int score = 0;
+	
+	switch(mapper->GetProbeShape())
+	{
+	case 0:
+		// sphere
+		distance_from_point = sqrt(pow((double)ray_position[0]-locationxyz[0], 2.0) +
+			pow((double)ray_position[1]-locationxyz[1], 2.0) +
+			pow((double)ray_position[2]-locationxyz[2], 2.0));
+	
+		// for translucency
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			if(*val> 250)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			*val= 0;
+			tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+		}
+		break;
+
+	case 1:
+		// cube
+		
+		mapper->GetFixedCubeLength(FixedCubeLength);
+		if(fabs(ray_position[0]-(float)locationxyz[0]) < FixedCubeLength[0]/2.0 &&
+			fabs(ray_position[1]-(float)locationxyz[1]) < FixedCubeLength[1]/2.0 &&
+			fabs(ray_position[2]-(float)locationxyz[2]) < FixedCubeLength[2]/2.0)
+		{
+
+			if(*val > 250)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			*val = 0; tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;			
+			if(translucency_set > 1)
+				tmp[2] = 50;
+
+		}
+
+		break;
+
+	case 2:
+		// ellipse
+		
+		mapper->GetFixedEllipseRadius(FixedEllipseRadius); 
+
+		distance_from_point = pow(ray_position[0]-(float)locationxyz[0], 2.0f)/ pow(FixedEllipseRadius[0], 2.0) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f)/ pow(FixedEllipseRadius[1], 2.0) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f)/ pow(FixedEllipseRadius[2], 2.0); 
+
+		if(distance_from_point < 1.0)
+		{
+			//printf("distance is %.2f\n", distance_from_point); 
+			//printf("%f %f %f\n", FixedEllipseRadius[0], FixedEllipseRadius[1], FixedEllipseRadius[2]); 
+
+			if(*val > 20)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			//printf("getting here in irregular cropper\n"); 
+
+			*val = pow(2.0, distance_from_point); tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;			
+			if(translucency_set > 1)
+				tmp[2] = 10;
+
+		}		
+		break;
+
+	case 3:
+		// cylinder
+		
+		mapper->GetFixedCylinderAxis(CylinderAxis);
+
+		for(float t=0;t<mapper->GetFixedCylinderHeight();t=t+mapper->GetFixedCylinderHeight()/10)
+		{
+			end_vector[0] = locationxyz[0] - ( CylinderAxis[0] * t);
+			end_vector[1] = locationxyz[1] - ( CylinderAxis[1] * t);
+			end_vector[2] = locationxyz[2] - ( CylinderAxis[2] * t);
+
+			distance_from_point = sqrt(pow(ray_position[0]-(float)end_vector[0], 2.0f) +
+				pow(ray_position[1]-(float)end_vector[1], 2.0f) +
+				pow(ray_position[2]-(float)end_vector[2], 2.0f));
+
+			//if(distance_from_point < mapper->GetCylinderRadius())
+			if(distance_from_point < mapper->GetFixedCylinderRadius())
+			{
+
+				if(*val > 0)
+					translucency_set = 2;
+				else
+					translucency_set = 1;
+				*val = 0; tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+				break;
+			}
+		}
+
+
+		break;
+
+	default:
+		// sphere
+		
+		distance_from_point = sqrt(pow(ray_position[0]-(float)locationxyz[0], 2.0f) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f));
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			translucency_set = 1;
+			if(*val > 0)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+			*val = 0; tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+		}
+		break;
+	}
+}
+
+void GOIrregularCropperArray(unsigned short val[4], unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper)
+{
+
+	double distance_from_point = 0.0;
+	int translucency_set = 0;
+	float end_vector[3];
+
+	float ray_position[3];
+	ray_position[0] = pos[0]/32767 ;
+	ray_position[1] = pos[1]/32767;
+	ray_position[2] = pos[2]/32767;
+
+	//double CubeX, CubeY, CubeZ;
+
+	double locationxyz[3];
+	double FixedCubeLength[3];
+	double FixedEllipseRadius[3];
+	double CylinderAxis[3];
+
+	locationxyz[0] = locationxyz[1] = locationxyz[2] = 0.0;
+	mapper->GetFixedSphereCenter(locationxyz);
+
+	int greyscale_flag = 0; 
+
+	float angle = 0, centroid_angle =0;
+	
+	float total_distance = 0;
+	int c = 0;
+	
+	int score = 0;
+	double axis_magnitude = 0; 
+
+
+	switch(mapper->GetProbeShape())
+	{
+	case 0:
+		// sphere
+		distance_from_point = sqrt(pow((double)ray_position[0]-locationxyz[0], 2.0) +
+			pow((double)ray_position[1]-locationxyz[1], 2.0) +
+			pow((double)ray_position[2]-locationxyz[2], 2.0));
+		// for translucency
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			if(val[0] > 10)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{					
+					if(translucency_set == 2)
+					{	
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+						tmp[2] = 10;
+					}
+					else
+					{
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+
+					}
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+		break;
+
+	case 1:
+		// cube
+		mapper->GetFixedCubeLength(FixedCubeLength);
+		if(fabs(ray_position[0]-(float)locationxyz[0]) < FixedCubeLength[0]/2.0 &&
+		   fabs(ray_position[1]-(float)locationxyz[1]) < FixedCubeLength[1]/2.0 &&
+		   fabs(ray_position[2]-(float)locationxyz[2]) < FixedCubeLength[2]/2.0)
+		  {
+
+			if(val[0] > 10)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{
+					val[0] = val[1] = val[2] = val[3] = 0;
+					tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+					if(translucency_set > 0)
+					{
+						tmp[2] = 10;
+					}
+					else
+					{
+						tmp[2] = 0;
+					}
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+		break;
+
+	case 2:
+		// ellipse 
+		mapper->GetFixedEllipseRadius(FixedEllipseRadius); 
+
+		distance_from_point = pow(ray_position[0]-(float)locationxyz[0], 2.0f)/ pow(FixedEllipseRadius[0], 2.0) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f)/ pow(FixedEllipseRadius[1], 2.0) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f)/ pow(FixedEllipseRadius[2], 2.0); 
+
+		if(distance_from_point < 1.0)
+		{
+		
+			if(val[0] > 0)
+				translucency_set = 2;
+			else
+				translucency_set = 1; 			
+		
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{
+					
+					if(translucency_set == 2)
+					{	
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+						tmp[2] = 50;
+					}
+					else
+					{
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+
+					}
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+
+		break;
+
+
+	case 3:
+		// cylinder
+		mapper->GetFixedCylinderAxis(CylinderAxis);
+	
+		axis_magnitude = sqrt(CylinderAxis[0] *  CylinderAxis[0] + 
+							  CylinderAxis[1] *  CylinderAxis[1] +
+							  CylinderAxis[2] *  CylinderAxis[2]); 
+
+		CylinderAxis[0] /= axis_magnitude;
+		CylinderAxis[1] /= axis_magnitude;
+		CylinderAxis[2] /= axis_magnitude;
+
+		
+		//for(float t=0;t<mapper->GetFixedCylinderHeight();t=t+ mapper->GetFixedCylinderRadius()/4)
+		for(float t=0;t<mapper->GetFixedCylinderHeight();t=t+ mapper->GetFixedCylinderHeight()/10)
+		{
+			end_vector[0] = locationxyz[0] - ( CylinderAxis[0] * t);
+			end_vector[1] = locationxyz[1] - ( CylinderAxis[1] * t);
+			end_vector[2] = locationxyz[2] - ( CylinderAxis[2] * t);
+
+			distance_from_point = sqrt(pow(ray_position[0]-(float)end_vector[0], 2.0f) +
+				pow(ray_position[1]-(float)end_vector[1], 2.0f) +
+				pow(ray_position[2]-(float)end_vector[2], 2.0f));
+
+			if(distance_from_point < mapper->GetFixedCylinderRadius())				 
+			{
+
+				if(*val > 0)
+					translucency_set = 2;
+				else
+					translucency_set = 1;
+
+				// Check if functional crop is set - If set then dont crop functional data
+				if(mapper->GetFunctionalCropOn() == 1)
+				{
+					if(abs(val[0] - val[1]) < 1)
+					{
+						if(abs(val[1] - val[2]) < 1)
+						{
+							greyscale_flag = 1; 
+						}
+					}
+
+					if(greyscale_flag == 1)
+					{
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+					}
+				}
+				else // Crop everything including functional data. 
+				{
+					val[0] = val[1] = val[2] = val[3] = 0;
+					tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+				}
+
+				break;
+			}
+		}
+
+
+		break;
+
+	default:
+		// sphere
+
+		distance_from_point = sqrt(pow(ray_position[0]-(float)locationxyz[0], 2.0f) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f));
+
+		printf("in default: %d\n", mapper->GetProbeShape()); 
+
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			translucency_set = 1;
+			if(*val > 0)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{
+					val[0] = val[1] = val[2] = val[3] = 0;
+					tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+		break;
+	}
+}
+
diff --git a/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeGOHelper.h b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeGOHelper.h
new file mode 100644
index 0000000..c2ca6f6
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeGOHelper.h
@@ -0,0 +1,89 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkCropVolumeRayCastCompositeGOHelper.h,v $
+  Language:  C++
+  Date:      $Date: 2008-06-16 08:27:56 $
+  Version:   $Revision: 1.2 $
+
+  Copyright (c) 1993-2002 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 vtkCropVolumeRayCastCompositeGOHelper - A helper that generates composite images for the volume ray cast mapper
+// .SECTION Description
+// This is one of the helper classes for the vtkCropVolumeRayCastMapper.
+// It will generate composite images using an alpha blending operation.
+// This class should not be used directly, it is a helper class for
+// the mapper and has no user-level API.
+//
+// .SECTION see also
+// vtkCropVolumeRayCastMapper
+
+#ifndef __vtkCropVolumeRayCastCompositeGOHelper_h
+#define __vtkCropVolumeRayCastCompositeGOHelper_h
+
+#include "vtkFixedPointVolumeRayCastHelper.h"
+
+
+class vtkCropVolumeRayCastMapper;
+class vtkVolume;
+
+class vtkCropVolumeRayCastCompositeGOHelper : public vtkFixedPointVolumeRayCastHelper
+{
+public:
+  static vtkCropVolumeRayCastCompositeGOHelper *New();
+  vtkTypeRevisionMacro(vtkCropVolumeRayCastCompositeGOHelper,vtkFixedPointVolumeRayCastHelper);
+  void PrintSelf( ostream& os, vtkIndent indent );
+
+  virtual void  GenerateImage( int threadID,
+                               int threadCount,
+                               vtkVolume *vol,
+                               vtkCropVolumeRayCastMapper *mapper);
+
+protected:
+  vtkCropVolumeRayCastCompositeGOHelper();
+  ~vtkCropVolumeRayCastCompositeGOHelper();
+
+private:
+  vtkCropVolumeRayCastCompositeGOHelper(const vtkCropVolumeRayCastCompositeGOHelper&);  // Not implemented.
+  void operator=(const vtkCropVolumeRayCastCompositeGOHelper&);  // Not implemented.
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeGOShadeHelper.cxx b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeGOShadeHelper.cxx
new file mode 100644
index 0000000..ea30a0b
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeGOShadeHelper.cxx
@@ -0,0 +1,1482 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkCropVolumeRayCastCompositeGOShadeHelper.cxx,v $
+  Language:  C++
+  Date:      $Date: 2007/11/08 16:51:06 $
+  Version:   $Revision: 1.9 $
+
+  Copyright (c) 1993-2002 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 "vtkCropVolumeRayCastCompositeGOShadeHelper.h"
+
+#include "vtkImageData.h"
+#include "vtkCommand.h"
+#include "vtkCropVolumeRayCastMapper.h"
+#include "vtkObjectFactory.h"
+#include "vtkRenderWindow.h"
+#include "vtkVolume.h"
+#include "vtkVolumeProperty.h"
+#include "vtkFixedPointRayCastImage.h"
+#include "vtkDataArray.h"
+
+#include <math.h>
+
+void GOShadeIrregularCropper(unsigned short *val, unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper);
+void GOShadeIrregularCropperArray(unsigned short val[4], unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper);
+
+vtkCxxRevisionMacro(vtkCropVolumeRayCastCompositeGOShadeHelper, "$Revision: 1.9 $");
+vtkStandardNewMacro(vtkCropVolumeRayCastCompositeGOShadeHelper);
+
+// Construct a new vtkCropVolumeRayCastCompositeGOShadeHelper with default values
+vtkCropVolumeRayCastCompositeGOShadeHelper::vtkCropVolumeRayCastCompositeGOShadeHelper()
+{
+}
+
+// Destruct a vtkCropVolumeRayCastCompositeGOShadeHelper - clean up any memory used
+vtkCropVolumeRayCastCompositeGOShadeHelper::~vtkCropVolumeRayCastCompositeGOShadeHelper()
+{
+}
+
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has one component and scale == 1.0 and shift == 0.0. In the inner
+// loop we get the data value as an unsigned short, and use this index to
+// lookup a color and opacity for this sample. We then composite this into
+// the color computed so far along the ray, and check if we can terminate at
+// this point (if the accumulated opacity is higher than some threshold).
+// Finally we move on to the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOShadeHelperGenerateImageOneSimpleNN( T *data,
+                                                          int threadID,
+                                                          int threadCount,
+                                                          vtkCropVolumeRayCastMapper *mapper,
+                                                          vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGOShadeNN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_InitializeCompositeShadeNN();
+  VTKKWRCHelper_InitializeCompositeGONN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleGOShadeNN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+    unsigned short val    = static_cast<unsigned short>(((*dptr)));
+    unsigned char  mag    = *magPtr;
+
+
+    VTKKWRCHelper_LookupColorGOUS( colorTable[0], scalarOpacityTable[0],
+                                   gradientOpacityTable[0], val, mag, tmp );
+
+    if ( tmp[3] )
+      {
+      unsigned short normal = *dirPtr;
+      VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp );
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has one component. In the inner loop we get the data value as
+// an unsigned short using the scale/shift, and use this index to lookup
+// a color and opacity for this sample. We then composite this into the
+// color computed so far along the ray, and check if we can terminate at
+// this point (if the accumulated opacity is higher than some threshold).
+// Finally we move on to the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOShadeHelperGenerateImageOneNN( T *data,
+                                             int threadID,
+                                             int threadCount,
+                                             vtkCropVolumeRayCastMapper *mapper,
+                                             vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGOShadeNN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_InitializeCompositeShadeNN();
+  VTKKWRCHelper_InitializeCompositeGONN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleGOShadeNN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+    unsigned short val    = static_cast<unsigned short>(((*dptr) + shift[0])*scale[0]);
+    unsigned char  mag    = *magPtr;
+
+    VTKKWRCHelper_LookupColorGOUS( colorTable[0], scalarOpacityTable[0],
+                                   gradientOpacityTable[0], val, mag, tmp );
+
+    if ( tmp[3] )
+      {
+      unsigned short normal = *dirPtr;
+      VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp );
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has two components which are not considered independent. In the
+// inner loop we compute the two unsigned short index values from the data
+// values (using the scale/shift). We use the first index to lookup a color,
+// and we use the second index to look up the opacity. We then composite
+// the color into the color computed so far along this ray, and check to
+// see if we can terminate here (if the opacity accumulated exceed some
+// threshold). Finally we move to the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOShadeHelperGenerateImageTwoDependentNN( T *data,
+                                                      int threadID,
+                                                      int threadCount,
+                                                      vtkCropVolumeRayCastMapper *mapper,
+                                                      vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGOShadeNN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_InitializeCompositeShadeNN();
+  VTKKWRCHelper_InitializeCompositeGONN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleGOShadeNN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+    unsigned short val[2];
+
+    val[1] = static_cast<unsigned short>(((*(dptr+1)) + shift[1])*scale[1]);
+    unsigned char  mag     = *magPtr;
+
+    tmp[3] = (scalarOpacityTable[0][val[1]] * gradientOpacityTable[0][mag] + 0x3fff)>>(VTKKW_FP_SHIFT);
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    val[0] = static_cast<unsigned short>(((*(dptr  )) + shift[0])*scale[0]);
+    unsigned short normal  = *dirPtr;
+
+    tmp[0] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[1] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[2] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+
+    VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp );
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has four components which are not considered independent . This
+// means that the first three components directly represent color, and this
+// data must be of unsigned char type. In the inner loop we directly access
+// the four data values (no scale/shift is needed). The first three are the
+// color of this sample and the fourth is used to look up an opacity in the
+// scalar opacity transfer function. We then composite this color into the
+// color we have accumulated so far along the ray, and check if we can
+// terminate here (if our accumulated opacity has exceed some threshold).
+// Finally we move onto the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOShadeHelperGenerateImageFourDependentNN( T *data,
+                                                       int threadID,
+                                                       int threadCount,
+                                                       vtkCropVolumeRayCastMapper *mapper,
+                                                       vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGOShadeNN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_InitializeCompositeShadeNN();
+  VTKKWRCHelper_InitializeCompositeGONN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleGOShadeNN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+    unsigned short val[4];
+
+    val[3] = static_cast<unsigned short>(((*(dptr+3)) + shift[3])*scale[3]);
+
+    unsigned char  mag   = *magPtr;
+
+    tmp[3] = (scalarOpacityTable[0][val[3]] * gradientOpacityTable[0][mag] + 0x3fff)>>(VTKKW_FP_SHIFT);
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    val[0] = *(dptr  );
+    val[1] = *(dptr+1);
+    val[2] = *(dptr+2);
+    unsigned short normal = *dirPtr;
+
+    tmp[0] = (val[0]*tmp[3]+0x7f)>>(8);
+    tmp[1] = (val[1]*tmp[3]+0x7f)>>(8);
+    tmp[2] = (val[2]*tmp[3]+0x7f)>>(8);
+
+    VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp );
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has more than one component and the components are considered to
+// be independent. In the inner loop we access each component value, using
+// the scale/shift to turn the data value into an unsigned short index. We
+// then lookup the color/opacity for each component and combine them according
+// to the weighting value for each component. We composite this resulting
+// color into the color already accumulated for this ray, and we check
+// wether we can terminate here (if the accumulated opacity exceeds some
+// threshold). Finally we increment to the next sample on the ray.
+template <class T>
+void vtkCropCompositeGOShadeHelperGenerateImageIndependentNN( T *data,
+                                                     int threadID,
+                                                     int threadCount,
+                                                     vtkCropVolumeRayCastMapper *mapper,
+                                                     vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializeWeights();
+  VTKKWRCHelper_InitializationAndLoopStartGOShadeNN();
+  VTKKWRCHelper_InitializeCompositeMultiNN();
+  VTKKWRCHelper_InitializeCompositeShadeNN();
+  VTKKWRCHelper_InitializeCompositeGONN();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleGOShadeNN();
+      }
+
+    VTKKWRCHelper_CroppingCheckNN( pos );
+    unsigned short normal[4];
+    unsigned char  mag[4];
+    for ( c = 0; c < components; c++ )
+      {
+      val[c]     = static_cast<unsigned short>(((*(dptr+c)) + shift[c])*scale[c]);
+      mag[c]     = static_cast<unsigned short>(*(magPtr+c));
+      normal[c]  = *(dirPtr+c);
+      }
+
+    VTKKWRCHelper_LookupAndCombineIndependentColorsGOShadeUS( colorTable, scalarOpacityTable,
+                                                              gradientOpacityTable,
+                                                              diffuseShadingTable,
+                                                              specularShadingTable,
+                                                              val, mag, normal, weights,
+                                                              components, tmp );
+
+    if ( tmp[3] )
+      {
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is linear and the data
+// has one component and scale = 1.0 and shift = 0.0. In the inner loop we
+// get the data value for the eight cell corners (if we have changed cells)
+// as an unsigned short (the range must be right and we don't need the
+// scale/shift). We compute our weights within the cell according to our
+// fractional position within the cell, apply trilinear interpolation to
+// compute the index, and use this index to lookup a color and opacity for
+// this sample. We then composite this into the color computed so far along
+// the ray, and check if we can terminate at this point (if the accumulated
+// opacity is higher than some threshold). Finally we move on to the next
+// sample along the ray.
+template <class T>
+void vtkCropCompositeGOShadeHelperGenerateImageOneSimpleTrilin( T *data,
+                                                       int threadID,
+                                                       int threadCount,
+                                                       vtkCropVolumeRayCastMapper *mapper,
+                                                       vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeOneTrilin();
+  VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeOneGOTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  int needToSampleDirection = 0;
+  int needToSampleMagnitude = 0;
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellScalarValuesSimple( dptr );
+
+      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      needToSampleMagnitude = 1;
+
+      dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      needToSampleDirection = 1;
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalar(val);
+
+    tmp[3] = scalarOpacityTable[0][val];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleMagnitude )
+      {
+      VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
+      needToSampleMagnitude = 0;
+      }
+    VTKKWRCHelper_InterpolateMagnitude(mag);
+    tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT;
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+	GOShadeIrregularCropper(&val, tmp, pos, mapper);
+
+    tmp[0] = static_cast<unsigned short>
+      ((colorTable[0][3*val  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[1] = static_cast<unsigned short>
+      ((colorTable[0][3*val+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[2] = static_cast<unsigned short>
+      ((colorTable[0][3*val+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+
+
+
+    if ( needToSampleDirection )
+      {
+      VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH );
+      needToSampleDirection = 0;
+      }
+
+    VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp );
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is linear and the data
+// has one component and scale != 1.0 or shift != 0.0. In the inner loop we
+// get the data value for the eight cell corners (if we have changed cells)
+// as an unsigned short (we use the scale/shift to ensure the correct range).
+// We compute our weights within the cell according to our fractional position
+// within the cell, apply trilinear interpolation to compute the index, and use
+// this index to lookup a color and opacity for this sample. We then composite
+// this into the color computed so far along the ray, and check if we can
+// terminate at this point (if the accumulated opacity is higher than some
+// threshold). Finally we move on to the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOShadeHelperGenerateImageOneTrilin( T *data,
+                                                 int threadID,
+                                                 int threadCount,
+                                                 vtkCropVolumeRayCastMapper *mapper,
+                                                 vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeOneTrilin();
+  VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeOneGOTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  int needToSampleDirection = 0;
+  int needToSampleMagnitude = 0;
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellScalarValues( dptr, scale[0], shift[0] );
+
+      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      needToSampleMagnitude = 1;
+
+      dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      needToSampleDirection = 1;
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalar(val);
+
+    tmp[3] = scalarOpacityTable[0][val];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleMagnitude )
+      {
+      VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
+      needToSampleMagnitude = 0;
+      }
+    VTKKWRCHelper_InterpolateMagnitude(mag);
+    tmp[3] = (tmp[3] * gradientOpacityTable[0][mag] + 0x7fff)>>VTKKW_FP_SHIFT;
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleDirection )
+      {
+      VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH );
+      needToSampleDirection = 0;
+      }
+
+    tmp[0] = static_cast<unsigned short>
+      ((colorTable[0][3*val  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[1] = static_cast<unsigned short>
+      ((colorTable[0][3*val+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[2] = static_cast<unsigned short>
+      ((colorTable[0][3*val+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+
+    VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp );
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+// This method is used when the interpolation type is linear, the data has
+// two components and the components are not considered independent. In the
+// inner loop we get the data value for the eight cell corners (if we have
+// changed cells) for both components as an unsigned shorts (we use the
+// scale/shift to ensure the correct range). We compute our weights within
+// the cell according to our fractional position within the cell, and apply
+// trilinear interpolation to compute the two index value. We use the first
+// index to lookup a color and the second to look up an opacity for this sample.
+// We then composite this into the color computed so far along the ray, and
+// check if we can terminate at this point (if the accumulated opacity is
+// higher than some threshold). Finally we move on to the next sample along
+// the ray.
+template <class T>
+void vtkCropCompositeGOShadeHelperGenerateImageTwoDependentTrilin( T *data,
+                                                          int threadID,
+                                                          int threadCount,
+                                                          vtkCropVolumeRayCastMapper *mapper,
+                                                          vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiTrilin();
+  VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeOneGOTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  int needToSampleDirection = 0;
+  int needToSampleMagnitude = 0;
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] );
+
+      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      needToSampleMagnitude = 1;
+
+      dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      needToSampleDirection = 1;
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalarComponent( val, c, 2 );
+
+    tmp[3] = scalarOpacityTable[0][val[1]];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleMagnitude )
+      {
+      VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
+      needToSampleMagnitude = 0;
+      }
+    VTKKWRCHelper_InterpolateMagnitude(mag);
+    tmp[3] = (0x7fff + tmp[3]*gradientOpacityTable[0][mag])>>(VTKKW_FP_SHIFT);
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleDirection )
+      {
+      VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH );
+      needToSampleDirection = 0;
+      }
+
+    tmp[0] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[1] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[2] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+
+    VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp );
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+
+// This method is used when the interpolation type is linear, the data has
+// four components and the components are not considered independent. In the
+// inner loop we get the data value for the eight cell corners (if we have
+// changed cells) for all components as an unsigned shorts (we don't have to
+// use the scale/shift because only unsigned char data is supported for four
+// component data when the components are not independent). We compute our
+// weights within the cell according to our fractional position within the cell,
+// and apply trilinear interpolation to compute a value for each component. We
+// use the first three directly as the color of the sample, and the fourth is
+// used to look up an opacity for this sample. We then composite this into the
+// color computed so far along the ray, and check if we can terminate at this
+// point (if the accumulated opacity is higher than some threshold). Finally we
+// move on to the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOShadeHelperGenerateImageFourDependentTrilin( T *data,
+                                                           int threadID,
+                                                           int threadCount,
+                                                           vtkCropVolumeRayCastMapper *mapper,
+                                                           vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiTrilin();
+  VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeOneGOTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  int needToSampleDirection = 0;
+  int needToSampleMagnitude = 0;
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 0 );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 1 );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 2 );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] );
+
+      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      needToSampleMagnitude = 1;
+
+      dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      needToSampleDirection = 1;
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalarComponent( val, c, components );
+
+	GOShadeIrregularCropperArray(val, tmp, pos, mapper);
+
+    tmp[3] = scalarOpacityTable[0][val[3]];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleMagnitude )
+      {
+      VTKKWRCHelper_GetCellMagnitudeValues( magPtrABCD, magPtrEFGH );
+      needToSampleMagnitude = 0;
+      }
+    VTKKWRCHelper_InterpolateMagnitude(mag);
+    tmp[3] = (0x7fff + tmp[3]*gradientOpacityTable[0][mag])>>(VTKKW_FP_SHIFT);
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleDirection )
+      {
+      VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH );
+      needToSampleDirection = 0;
+      }
+
+    tmp[0] = (val[0]*tmp[3]+0x7f)>>8;
+    tmp[1] = (val[1]*tmp[3]+0x7f)>>8;
+    tmp[2] = (val[2]*tmp[3]+0x7f)>>8;
+
+    VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp );
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is linear, the data has
+// more than one component and the components are considered independent. In
+// the inner loop we get the data value for the eight cell corners (if we have
+// changed cells) for all components as an unsigned shorts (we have to use the
+// scale/shift to ensure that we obtained unsigned short indices) We compute our
+// weights within the cell according to our fractional position within the cell,
+// and apply trilinear interpolation to compute a value for each component. We
+// look up a color/opacity for each component and blend them according to the
+// component weights. We then composite this resulting color into the
+// color computed so far along the ray, and check if we can terminate at this
+// point (if the accumulated opacity is higher than some threshold). Finally we
+// move on to the next sample along the ray.
+template <class T>
+void vtkCropCompositeGOShadeHelperGenerateImageIndependentTrilin( T *data,
+                                                         int threadID,
+                                                         int threadCount,
+                                                         vtkCropVolumeRayCastMapper *mapper,
+                                                         vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializeWeights();
+  VTKKWRCHelper_InitializationAndLoopStartGOShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiGOTrilin();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] );
+
+      if ( components > 2 )
+        {
+        dptr++;
+        VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] );
+        if ( components > 3 )
+          {
+          dptr++;
+          VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] );
+          }
+        }
+
+      magPtrABCD = gradientMag[spos[2]  ] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      magPtrEFGH = gradientMag[spos[2]+1] + spos[0]*mInc[0] + spos[1]*mInc[1];
+      VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 0 );
+
+      magPtrABCD++;
+      magPtrEFGH++;
+      VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 1 );
+
+      if ( components > 2 )
+        {
+        magPtrABCD++;
+        magPtrEFGH++;
+        VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 2 );
+        if ( components > 3 )
+          {
+          magPtrABCD++;
+          magPtrEFGH++;
+          VTKKWRCHelper_GetCellComponentMagnitudeValues( magPtrABCD, magPtrEFGH, 3 );
+          }
+        }
+
+      dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 0 );
+
+      dirPtrABCD++;
+      dirPtrEFGH++;
+      VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 1 );
+
+      if ( components > 2 )
+        {
+        dirPtrABCD++;
+        dirPtrEFGH++;
+        VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 2 );
+        if ( components > 3 )
+          {
+          dirPtrABCD++;
+          dirPtrEFGH++;
+          VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 3 );
+          }
+        }
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalarComponent( val, c, components );
+    VTKKWRCHelper_InterpolateMagnitudeComponent( mag, c, components );
+
+    VTKKWRCHelper_LookupAndCombineIndependentColorsGOInterpolateShadeUS(
+      colorTable, scalarOpacityTable, gradientOpacityTable,
+      diffuseShadingTable, specularShadingTable,
+      val, mag, weights, components, tmp );
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+void vtkCropVolumeRayCastCompositeGOShadeHelper::GenerateImage( int threadID,
+                                                 int threadCount,
+                                                 vtkVolume *vol,
+                                                 vtkCropVolumeRayCastMapper *mapper )
+{
+  void *data     = mapper->GetCurrentScalars()->GetVoidPointer(0);
+  int scalarType = mapper->GetCurrentScalars()->GetDataType();
+
+  // Nearest Neighbor interpolate
+  if ( mapper->ShouldUseNearestNeighborInterpolation( vol ) )
+    {
+    // One component data
+    if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 1 )
+      {
+      // Scale == 1.0 and shift == 0.0 - simple case (faster)
+      if ( mapper->GetTableScale()[0] == 1.0 &&
+           mapper->GetTableShift()[0] == 0.0 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropCompositeGOShadeHelperGenerateImageOneSimpleNN(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      else
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropCompositeGOShadeHelperGenerateImageOneNN(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      }
+    // More that one independent components
+    else if ( vol->GetProperty()->GetIndependentComponents() )
+      {
+      switch ( scalarType )
+        {
+        vtkTemplateMacro(
+          vtkCropCompositeGOShadeHelperGenerateImageIndependentNN(
+            static_cast<VTK_TT *>(data),
+            threadID, threadCount, mapper, vol) );
+        }
+      }
+    // Dependent (color) components
+    else
+      {
+      // Two components - the first specifies color (through a lookup table)
+      // and the second specified opacity (through a lookup table)
+      if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 2 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropCompositeGOShadeHelperGenerateImageTwoDependentNN(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      // Four components - they must be unsigned char, the first three directly
+      // specify color and the fourth specifies opacity (through a lookup
+      // table)
+      else
+        {
+        if ( scalarType == VTK_UNSIGNED_CHAR )
+          {
+          vtkCropCompositeGOShadeHelperGenerateImageFourDependentNN(
+            static_cast<unsigned char *>(data), threadID, threadCount, mapper,
+            vol );
+          }
+        else
+          {
+          vtkErrorMacro("Four component dependent data must be unsigned char");
+          }
+        }
+      }
+    }
+  // Trilinear Interpolation
+  else
+    {
+    // One component
+    if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 1 )
+      {
+      // Scale == 1.0 and shift == 0.0 - simple case (faster)
+      if ( mapper->GetTableScale()[0] == 1.0 &&
+           mapper->GetTableShift()[0] == 0.0 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropCompositeGOShadeHelperGenerateImageOneSimpleTrilin(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop
+      else
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropCompositeGOShadeHelperGenerateImageOneTrilin(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      }
+    // Indepedent components (more than one)
+    else if ( vol->GetProperty()->GetIndependentComponents() )
+      {
+      switch ( scalarType )
+        {
+        vtkTemplateMacro(
+          vtkCropCompositeGOShadeHelperGenerateImageIndependentTrilin(
+            static_cast<VTK_TT *>(data),
+            threadID, threadCount, mapper, vol) );
+        }
+      }
+    // Dependent components
+    else
+      {
+      // Two components - the first specifies color (through a lookup table)
+      // and the second specified opacity (through a lookup table)
+      if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 2 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropCompositeGOShadeHelperGenerateImageTwoDependentTrilin(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      // Four components - they must be unsigned char, the first three directly
+      // specify color and the fourth specifies opacity (through a lookup
+      // table)
+      else
+        {
+        if ( scalarType == VTK_UNSIGNED_CHAR )
+          {
+          vtkCropCompositeGOShadeHelperGenerateImageFourDependentTrilin(
+            static_cast<unsigned char *>(data), threadID, threadCount, mapper,
+            vol );
+          }
+        else
+          {
+          vtkErrorMacro("Four component dependent data must be unsigned char");
+          }
+        }
+      }
+    }
+}
+
+// Print method for vtkCropVolumeRayCastCompositeGOShadeHelper
+void vtkCropVolumeRayCastCompositeGOShadeHelper::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+}
+
+
+void  GOShadeIrregularCropper(unsigned short *val, unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper)
+{
+
+	double distance_from_point = 0.0;
+	int translucency_set = 0;
+	float end_vector[3];
+
+	float ray_position[3];
+	ray_position[0] = pos[0]/32767 ;
+	ray_position[1] = pos[1]/32767;
+	ray_position[2] = pos[2]/32767;
+
+	double locationxyz[3];
+	double FixedCubeLength[3];
+	double FixedEllipseRadius[3];
+	double CylinderAxis[3];
+
+	locationxyz[0] = locationxyz[1] = locationxyz[2] = 0.0;
+	mapper->GetFixedSphereCenter(locationxyz);
+
+	float angle = 0, centroid_angle =0;
+
+	float total_distance = 0;
+	int c = 0;
+
+	int score = 0;
+	
+	switch(mapper->GetProbeShape())
+	{
+	case 0:
+		// sphere
+		distance_from_point = sqrt(pow((double)ray_position[0]-locationxyz[0], 2.0) +
+			pow((double)ray_position[1]-locationxyz[1], 2.0) +
+			pow((double)ray_position[2]-locationxyz[2], 2.0));
+	
+		// for translucency
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			if(*val> 250)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			*val= 0;
+			tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+		}
+		break;
+
+	case 1:
+		// cube
+		
+		mapper->GetFixedCubeLength(FixedCubeLength);
+		if(fabs(ray_position[0]-(float)locationxyz[0]) < FixedCubeLength[0]/2.0 &&
+			fabs(ray_position[1]-(float)locationxyz[1]) < FixedCubeLength[1]/2.0 &&
+			fabs(ray_position[2]-(float)locationxyz[2]) < FixedCubeLength[2]/2.0)
+		{
+
+			if(*val > 250)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			//printf("getting here in irregular cropper\n"); 
+
+			*val = 0; tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;			
+			if(translucency_set > 1)
+				tmp[2] = 50;
+
+		}
+
+		break;
+
+	case 2:
+		// ellipse
+		
+		mapper->GetFixedEllipseRadius(FixedEllipseRadius); 
+
+		distance_from_point = pow(ray_position[0]-(float)locationxyz[0], 2.0f)/ pow(FixedEllipseRadius[0], 2.0) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f)/ pow(FixedEllipseRadius[1], 2.0) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f)/ pow(FixedEllipseRadius[2], 2.0); 
+
+		if(distance_from_point < 1.0)
+		{
+			if(*val > 20)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			*val = pow(2.0, distance_from_point); tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;			
+			if(translucency_set > 1)
+				tmp[2] = 10;
+
+		}		
+		break;
+
+	case 3:
+		// cylinder
+		
+		mapper->GetFixedCylinderAxis(CylinderAxis);
+
+		for(float t=0;t<mapper->GetFixedCylinderHeight();t=t+mapper->GetFixedCylinderHeight()/10)
+		{
+			end_vector[0] = locationxyz[0] - ( CylinderAxis[0] * t);
+			end_vector[1] = locationxyz[1] - ( CylinderAxis[1] * t);
+			end_vector[2] = locationxyz[2] - ( CylinderAxis[2] * t);
+
+			distance_from_point = sqrt(pow(ray_position[0]-(float)end_vector[0], 2.0f) +
+				pow(ray_position[1]-(float)end_vector[1], 2.0f) +
+				pow(ray_position[2]-(float)end_vector[2], 2.0f));
+
+			
+			if(distance_from_point < mapper->GetFixedCylinderRadius())
+			{
+
+				if(*val > 0)
+					translucency_set = 2;
+				else
+					translucency_set = 1;
+				*val = 0; tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+				break;
+			}
+		}
+
+
+		break;
+
+	default:
+		// sphere
+		
+		distance_from_point = sqrt(pow(ray_position[0]-(float)locationxyz[0], 2.0f) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f));
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			translucency_set = 1;
+			if(*val > 0)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+			*val = 0; tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+		}
+		break;
+	}
+}
+
+void GOShadeIrregularCropperArray(unsigned short val[4], unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper)
+{
+
+	double distance_from_point = 0.0;
+	int translucency_set = 0;
+	float end_vector[3];
+
+	float ray_position[3];
+	ray_position[0] = pos[0]/32767 ;
+	ray_position[1] = pos[1]/32767;
+	ray_position[2] = pos[2]/32767;
+
+	double locationxyz[3];
+	double FixedCubeLength[3];
+	double FixedEllipseRadius[3];
+	double CylinderAxis[3];
+
+	locationxyz[0] = locationxyz[1] = locationxyz[2] = 0.0;
+	mapper->GetFixedSphereCenter(locationxyz);
+
+	int greyscale_flag = 0; 
+
+	float angle = 0, centroid_angle =0;
+	
+	float total_distance = 0;
+	int c = 0;
+	int score = 0;
+	double axis_magnitude = 0; 
+
+
+	switch(mapper->GetProbeShape())
+	{
+	case 0:
+		// sphere
+		distance_from_point = sqrt(pow((double)ray_position[0]-locationxyz[0], 2.0) +
+			pow((double)ray_position[1]-locationxyz[1], 2.0) +
+			pow((double)ray_position[2]-locationxyz[2], 2.0));
+		// for translucency
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			if(val[0] > 10)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{					
+					if(translucency_set == 2)
+					{	
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+						tmp[2] = 10;
+					}
+					else
+					{
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+
+					}
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+		break;
+
+	case 1:
+		// cube
+		mapper->GetFixedCubeLength(FixedCubeLength);
+		if(fabs(ray_position[0]-(float)locationxyz[0]) < FixedCubeLength[0]/2.0 &&
+		   fabs(ray_position[1]-(float)locationxyz[1]) < FixedCubeLength[1]/2.0 &&
+		   fabs(ray_position[2]-(float)locationxyz[2]) < FixedCubeLength[2]/2.0)
+		  {
+
+			if(val[0] > 10)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{
+					val[0] = val[1] = val[2] = val[3] = 0;
+					tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+					if(translucency_set > 0)
+					{
+						tmp[2] = 10;
+					}
+					else
+					{
+						tmp[2] = 0;
+					}
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+		break;
+
+	case 2:
+		// ellipse 
+		mapper->GetFixedEllipseRadius(FixedEllipseRadius); 
+
+		distance_from_point = pow(ray_position[0]-(float)locationxyz[0], 2.0f)/ pow(FixedEllipseRadius[0], 2.0) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f)/ pow(FixedEllipseRadius[1], 2.0) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f)/ pow(FixedEllipseRadius[2], 2.0); 
+
+		if(distance_from_point < 1.0)
+		{
+		
+			if(val[0] > 0)
+				translucency_set = 2;
+			else
+				translucency_set = 1; 			
+		
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{
+					
+					if(translucency_set == 2)
+					{	
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+						tmp[2] = 50;
+					}
+					else
+					{
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+
+					}
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+
+		break;
+
+
+	case 3:
+		// cylinder
+		mapper->GetFixedCylinderAxis(CylinderAxis);
+	
+		axis_magnitude = sqrt(CylinderAxis[0] *  CylinderAxis[0] + 
+							  CylinderAxis[1] *  CylinderAxis[1] +
+							  CylinderAxis[2] *  CylinderAxis[2]); 
+
+		CylinderAxis[0] /= axis_magnitude;
+		CylinderAxis[1] /= axis_magnitude;
+		CylinderAxis[2] /= axis_magnitude;
+
+		
+		//for(float t=0;t<mapper->GetFixedCylinderHeight();t=t+ mapper->GetFixedCylinderRadius()/4)
+		for(float t=0;t<mapper->GetFixedCylinderHeight();t=t+ mapper->GetFixedCylinderHeight()/10)
+		{
+			end_vector[0] = locationxyz[0] - ( CylinderAxis[0] * t);
+			end_vector[1] = locationxyz[1] - ( CylinderAxis[1] * t);
+			end_vector[2] = locationxyz[2] - ( CylinderAxis[2] * t);
+
+			distance_from_point = sqrt(pow(ray_position[0]-(float)end_vector[0], 2.0f) +
+				pow(ray_position[1]-(float)end_vector[1], 2.0f) +
+				pow(ray_position[2]-(float)end_vector[2], 2.0f));
+
+			if(distance_from_point < mapper->GetFixedCylinderRadius())				 
+			{
+
+				if(*val > 0)
+					translucency_set = 2;
+				else
+					translucency_set = 1;
+
+				// Check if functional crop is set - If set then dont crop functional data
+				if(mapper->GetFunctionalCropOn() == 1)
+				{
+					if(abs(val[0] - val[1]) < 1)
+					{
+						if(abs(val[1] - val[2]) < 1)
+						{
+							greyscale_flag = 1; 
+						}
+					}
+
+					if(greyscale_flag == 1)
+					{
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+					}
+				}
+				else // Crop everything including functional data. 
+				{
+					val[0] = val[1] = val[2] = val[3] = 0;
+					tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+				}
+
+				break;
+			}
+		}
+
+
+		break;
+
+	default:
+		// sphere
+
+		distance_from_point = sqrt(pow(ray_position[0]-(float)locationxyz[0], 2.0f) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f));
+
+		printf("in default: %d\n", mapper->GetProbeShape()); 
+
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			translucency_set = 1;
+			if(*val > 0)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{
+					val[0] = val[1] = val[2] = val[3] = 0;
+					tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+		break;
+	}
+}
+
diff --git a/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeGOShadeHelper.h b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeGOShadeHelper.h
new file mode 100644
index 0000000..0e202ae
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeGOShadeHelper.h
@@ -0,0 +1,88 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkCropVolumeRayCastCompositeGOShadeHelper.h,v $
+  Language:  C++
+  Date:      $Date: 2008-06-16 08:27:56 $
+  Version:   $Revision: 1.2 $
+
+  Copyright (c) 1993-2002 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 vtkCropVolumeRayCastCompositeGOShadeHelper - A helper that generates composite images for the volume ray cast mapper
+// .SECTION Description
+// This is one of the helper classes for the vtkCropVolumeRayCastMapper.
+// It will generate composite images using an alpha blending operation.
+// This class should not be used directly, it is a helper class for
+// the mapper and has no user-level API.
+//
+// .SECTION see also
+// vtkCropVolumeRayCastMapper
+
+#ifndef __vtkCropVolumeRayCastCompositeGOShadeHelper_h
+#define __vtkCropVolumeRayCastCompositeGOShadeHelper_h
+
+#include "vtkFixedPointVolumeRayCastHelper.h"
+
+class vtkCropVolumeRayCastMapper;
+class vtkVolume;
+
+class vtkCropVolumeRayCastCompositeGOShadeHelper : public vtkFixedPointVolumeRayCastHelper
+{
+public:
+  static vtkCropVolumeRayCastCompositeGOShadeHelper *New();
+  vtkTypeRevisionMacro(vtkCropVolumeRayCastCompositeGOShadeHelper,vtkFixedPointVolumeRayCastHelper);
+  void PrintSelf( ostream& os, vtkIndent indent );
+
+  virtual void  GenerateImage( int threadID,
+                               int threadCount,
+                               vtkVolume *vol,
+                               vtkCropVolumeRayCastMapper *mapper);
+
+protected:
+  vtkCropVolumeRayCastCompositeGOShadeHelper();
+  ~vtkCropVolumeRayCastCompositeGOShadeHelper();
+
+private:
+  vtkCropVolumeRayCastCompositeGOShadeHelper(const vtkCropVolumeRayCastCompositeGOShadeHelper&);  // Not implemented.
+  void operator=(const vtkCropVolumeRayCastCompositeGOShadeHelper&);  // Not implemented.
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeHelper.cxx b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeHelper.cxx
new file mode 100644
index 0000000..b32882a
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeHelper.cxx
@@ -0,0 +1,1321 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkCropVolumeRayCastCompositeHelper.cxx,v $
+  Language:  C++
+  Date:      $Date: 2007/11/08 16:51:06 $
+  Version:   $Revision: 1.9 $
+
+  Copyright (c) 1993-2002 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 "vtkCropVolumeRayCastCompositeHelper.h"
+
+#include "vtkImageData.h"
+#include "vtkCommand.h"
+#include "vtkCropVolumeRayCastMapper.h"
+#include "vtkObjectFactory.h"
+#include "vtkRenderWindow.h"
+#include "vtkVolume.h"
+#include "vtkVolumeProperty.h"
+#include "vtkFixedPointRayCastImage.h"
+#include "vtkDataArray.h"
+
+#include <math.h>
+
+void  IrregularCropper(unsigned short *val, unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper);
+void  IrregularCropperArray(unsigned short val[4], unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper);
+
+vtkCxxRevisionMacro(vtkCropVolumeRayCastCompositeHelper, "$Revision: 1.9 $");
+vtkStandardNewMacro(vtkCropVolumeRayCastCompositeHelper);
+
+
+// Construct a new vtkCropVolumeRayCastCompositeHelper with default values
+vtkCropVolumeRayCastCompositeHelper::vtkCropVolumeRayCastCompositeHelper()
+{
+}
+
+// Destruct a vtkCropVolumeRayCastCompositeHelper - clean up any memory used
+vtkCropVolumeRayCastCompositeHelper::~vtkCropVolumeRayCastCompositeHelper()
+{
+}
+
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has one component and scale == 1.0 and shift == 0.0. In the inner
+// loop we get the data value as an unsigned short, and use this index to
+// lookup a color and opacity for this sample. We then composite this into
+// the color computed so far along the ray, and check if we can terminate at
+// this point (if the accumulated opacity is higher than some threshold).
+// Finally we move on to the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeHelperGenerateImageOneSimpleNN( T *data,
+                                                   int threadID,
+                                                   int threadCount,
+                                                   vtkCropVolumeRayCastMapper *mapper,
+                                                   vtkVolume *vtkNotUsed(vol))
+{
+  VTKKWRCHelper_InitializationAndLoopStartNN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+    printf("1 simple nn\n");
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleNN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short val = static_cast<unsigned short>(((*dptr)));
+
+    VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp );
+
+    // IrregularCropper(&val, tmp, pos, mapper);
+
+    if ( tmp[3] )
+      {
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has one component. In the inner loop we get the data value as
+// an unsigned short using the scale/shift, and use this index to lookup
+// a color and opacity for this sample. We then composite this into the
+// color computed so far along the ray, and check if we can terminate at
+// this point (if the accumulated opacity is higher than some threshold).
+// Finally we move on to the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeHelperGenerateImageOneNN( T *data,
+                                             int threadID,
+                                             int threadCount,
+                                             vtkCropVolumeRayCastMapper *mapper,
+                                             vtkVolume *vtkNotUsed(vol))
+{
+  VTKKWRCHelper_InitializationAndLoopStartNN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+    printf("1 nn\n");
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleNN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short val = static_cast<unsigned short>(((*dptr) + shift[0])*scale[0]);
+
+    VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp );
+
+	// IrregularCropper(&val, tmp, pos, mapper);
+
+    if ( tmp[3] )
+      {
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has two components which are not considered independent. In the
+// inner loop we compute the two unsigned short index values from the data
+// values (using the scale/shift). We use the first index to lookup a color,
+// and we use the second index to look up the opacity. We then composite
+// the color into the color computed so far along this ray, and check to
+// see if we can terminate here (if the opacity accumulated exceed some
+// threshold). Finally we move to the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeHelperGenerateImageTwoDependentNN( T *data,
+                                                      int threadID,
+                                                      int threadCount,
+                                                      vtkCropVolumeRayCastMapper *mapper,
+                                                      vtkVolume *vtkNotUsed(vol))
+{
+  VTKKWRCHelper_InitializationAndLoopStartNN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+    printf("2 dep nn\n");
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleNN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short val[2];
+    val[1] = static_cast<unsigned short>(((*(dptr+1)) + shift[1])*scale[1]);
+
+    tmp[3] = scalarOpacityTable[0][val[1]];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    val[0] = static_cast<unsigned short>(((*(dptr  )) + shift[0])*scale[0]);
+
+    tmp[0] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[1] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[2] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+
+	// Two component 
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has four components which are not considered independent . This
+// means that the first three components directly represent color, and this
+// data must be of unsigned char type. In the inner loop we directly access
+// the four data values (no scale/shift is needed). The first three are the
+// color of this sample and the fourth is used to look up an opacity in the
+// scalar opacity transfer function. We then composite this color into the
+// color we have accumulated so far along the ray, and check if we can
+// terminate here (if our accumulated opacity has exceed some threshold).
+// Finally we move onto the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeHelperGenerateImageFourDependentNN( T *data,
+                                                       int threadID,
+                                                       int threadCount,
+                                                       vtkCropVolumeRayCastMapper *mapper,
+                                                       vtkVolume *vtkNotUsed(vol))
+{
+  VTKKWRCHelper_InitializationAndLoopStartNN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+    printf("4 dep nn\n");
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleNN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short val[4];
+    val[3] = static_cast<unsigned short>(((*(dptr+3)) + shift[3])*scale[3]);
+
+    tmp[3] = scalarOpacityTable[0][val[3]];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    val[0] = *(dptr  );
+    val[1] = *(dptr+1);
+    val[2] = *(dptr+2);
+
+    tmp[0] = (val[0]*tmp[3]+0x7f)>>(8);
+    tmp[1] = (val[1]*tmp[3]+0x7f)>>(8);
+    tmp[2] = (val[2]*tmp[3]+0x7f)>>(8);
+
+	// IrregularCropperArray(val, tmp, pos, mapper);
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has more than one component and the components are considered to
+// be independent. In the inner loop we access each component value, using
+// the scale/shift to turn the data value into an unsigned short index. We
+// then lookup the color/opacity for each component and combine them according
+// to the weighting value for each component. We composite this resulting
+// color into the color already accumulated for this ray, and we check
+// wether we can terminate here (if the accumulated opacity exceeds some
+// threshold). Finally we increment to the next sample on the ray.
+template <class T>
+void vtkCropFixedPointCompositeHelperGenerateImageIndependentNN( T *data,
+                                                     int threadID,
+                                                     int threadCount,
+                                                     vtkCropVolumeRayCastMapper *mapper,
+                                                     vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializeWeights();
+  VTKKWRCHelper_InitializationAndLoopStartNN();
+  VTKKWRCHelper_InitializeCompositeMultiNN();
+
+    printf("1 indep nn\n");
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleNN();
+      }
+
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    for ( c = 0; c < components; c++ )
+      {
+      val[c] = static_cast<unsigned short>(((*(dptr+c)) + shift[c])*scale[c]);
+      }
+
+
+    VTKKWRCHelper_LookupAndCombineIndependentColorsUS( colorTable, scalarOpacityTable,
+                                                       val, weights, components, tmp );
+
+	// Multiple irregular 
+	// IrregularCropperArray(val, tmp, pos, mapper);
+
+    if ( tmp[3] )
+      {
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is linear and the data
+// has one component and scale = 1.0 and shift = 0.0. In the inner loop we
+// get the data value for the eight cell corners (if we have changed cells)
+// as an unsigned short (the range must be right and we don't need the
+// scale/shift). We compute our weights within the cell according to our
+// fractional position within the cell, apply trilinear interpolation to
+// compute the index, and use this index to lookup a color and opacity for
+// this sample. We then composite this into the color computed so far along
+// the ray, and check if we can terminate at this point (if the accumulated
+// opacity is higher than some threshold). Finally we move on to the next
+// sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeHelperGenerateImageOneSimpleTrilin( T *data,
+                                                       int threadID,
+                                                       int threadCount,
+                                                       vtkCropVolumeRayCastMapper *mapper,
+                                                       vtkVolume *vtkNotUsed(vol))
+{
+  VTKKWRCHelper_InitializationAndLoopStartTrilin();
+  VTKKWRCHelper_InitializeCompositeOneTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellScalarValuesSimple( dptr );
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalar(val);
+
+	
+    VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp );
+    
+   // IrregularCropper(&val, tmp, pos, mapper);	
+
+	IrregularCropper(&val, tmp, pos, mapper);
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+
+  }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is linear and the data
+// has one component and scale != 1.0 or shift != 0.0. In the inner loop we
+// get the data value for the eight cell corners (if we have changed cells)
+// as an unsigned short (we use the scale/shift to ensure the correct range).
+// We compute our weights within the cell according to our fractional position
+// within the cell, apply trilinear interpolation to compute the index, and use
+// this index to lookup a color and opacity for this sample. We then composite
+// this into the color computed so far along the ray, and check if we can
+// terminate at this point (if the accumulated opacity is higher than some
+// threshold). Finally we move on to the next sample along the ray.
+template <class T> 
+void vtkCropFixedPointCompositeHelperGenerateImageOneTrilin( T *data,
+                                                 int threadID,
+                                                 int threadCount,
+                                                 vtkCropVolumeRayCastMapper *mapper,
+                                                 vtkVolume *vtkNotUsed(vol))
+{
+  VTKKWRCHelper_InitializationAndLoopStartTrilin();
+  VTKKWRCHelper_InitializeCompositeOneTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+    printf("1 trilinear\n");
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellScalarValues( dptr, scale[0], shift[0] );
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalar(val);
+
+    VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp );
+
+//    IrregularCropper(&val, tmp, pos, mapper);
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+// This method is used when the interpolation type is linear, the data has
+// two components and the components are not considered independent. In the
+// inner loop we get the data value for the eight cell corners (if we have
+// changed cells) for both components as an unsigned shorts (we use the
+// scale/shift to ensure the correct range). We compute our weights within
+// the cell according to our fractional position within the cell, and apply
+// trilinear interpolation to compute the two index value. We use the first
+// index to lookup a color and the second to look up an opacity for this sample.
+// We then composite this into the color computed so far along the ray, and
+// check if we can terminate at this point (if the accumulated opacity is
+// higher than some threshold). Finally we move on to the next sample along
+// the ray.
+template <class T>
+void vtkCropFixedPointCompositeHelperGenerateImageTwoDependentTrilin( T *data,
+                                                          int threadID,
+                                                          int threadCount,
+                                                          vtkCropVolumeRayCastMapper *mapper,
+                                                          vtkVolume *vtkNotUsed(vol))
+{
+  VTKKWRCHelper_InitializationAndLoopStartTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+    
+  printf("2 dep trilinear\n");
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] );
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalarComponent( val, c, 2 );
+
+    tmp[3] = scalarOpacityTable[0][val[1]];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    tmp[0] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[1] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[2] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+
+	// Two 
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+
+
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+
+// This method is used when the interpolation type is linear, the data has
+// four components and the components are not considered independent. In the
+// inner loop we get the data value for the eight cell corners (if we have
+// changed cells) for all components as an unsigned shorts (we don't have to
+// use the scale/shift because only unsigned char data is supported for four
+// component data when the components are not independent). We compute our
+// weights within the cell according to our fractional position within the cell,
+// and apply trilinear interpolation to compute a value for each component. We
+// use the first three directly as the color of the sample, and the fourth is
+// used to look up an opacity for this sample. We then composite this into the
+// color computed so far along the ray, and check if we can terminate at this
+// point (if the accumulated opacity is higher than some threshold). Finally we
+// move on to the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeHelperGenerateImageFourDependentTrilin( T *data,
+                                                           int threadID,
+                                                           int threadCount,
+                                                           vtkCropVolumeRayCastMapper *mapper,
+                                                           vtkVolume *vtkNotUsed(vol))
+{
+  VTKKWRCHelper_InitializationAndLoopStartTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 0 );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 1 );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 2 );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] );
+
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalarComponent( val, c, components );
+
+    tmp[3] = scalarOpacityTable[0][val[3]];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    tmp[0] = (val[0]*tmp[3]+0x7f)>>8;
+    tmp[1] = (val[1]*tmp[3]+0x7f)>>8;
+    tmp[2] = (val[2]*tmp[3]+0x7f)>>8;
+
+	IrregularCropperArray(val, tmp, pos, mapper);
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is linear, the data has
+// more than one component and the components are considered independent. In
+// the inner loop we get the data value for the eight cell corners (if we have
+// changed cells) for all components as an unsigned shorts (we have to use the
+// scale/shift to ensure that we obtained unsigned short indices) We compute our
+// weights within the cell according to our fractional position within the cell,
+// and apply trilinear interpolation to compute a value for each component. We
+// look up a color/opacity for each component and blend them according to the
+// component weights. We then composite this resulting color into the
+// color computed so far along the ray, and check if we can terminate at this
+// point (if the accumulated opacity is higher than some threshold). Finally we
+// move on to the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeHelperGenerateImageIndependentTrilin( T *data,
+                                                         int threadID,
+                                                         int threadCount,
+                                                         vtkCropVolumeRayCastMapper *mapper,
+                                                         vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializeWeights();
+  VTKKWRCHelper_InitializationAndLoopStartTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiTrilin();
+
+	    printf("1 indep trilinear\n");
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] );
+
+      if ( components > 2 )
+        {
+        dptr++;
+        VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] );
+        }
+
+      if ( components > 3 )
+        {
+        dptr++;
+        VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] );
+        }
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalarComponent( val, c, components );
+
+    VTKKWRCHelper_LookupAndCombineIndependentColorsUS( colorTable, scalarOpacityTable,
+                                                       val, weights, components, tmp );
+
+	// Multiple irregular
+	// IrregularCropperArray(val, tmp, pos, mapper);
+	
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+void vtkCropVolumeRayCastCompositeHelper::GenerateImage(
+  int threadID,
+  int threadCount,
+  vtkVolume *vol,
+  vtkCropVolumeRayCastMapper *mapper )
+{
+  void *data     = mapper->GetCurrentScalars()->GetVoidPointer(0);
+  int scalarType = mapper->GetCurrentScalars()->GetDataType();
+
+  // Nearest Neighbor interpolate
+  if ( mapper->ShouldUseNearestNeighborInterpolation( vol ) )
+    {
+    // One component data
+    if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 1 )
+      {
+      // Scale == 1.0 and shift == 0.0 - simple case (faster)
+      if ( mapper->GetTableScale()[0] == 1.0 &&
+           mapper->GetTableShift()[0] == 0.0 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropFixedPointCompositeHelperGenerateImageOneSimpleNN(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      else
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropFixedPointCompositeHelperGenerateImageOneNN(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      }
+    // More that one independent components
+    else if ( vol->GetProperty()->GetIndependentComponents() )
+      {
+      switch ( scalarType )
+        {
+        vtkTemplateMacro(
+          vtkCropFixedPointCompositeHelperGenerateImageIndependentNN(
+            static_cast<VTK_TT *>(data),
+            threadID, threadCount, mapper, vol) );
+        }
+      }
+    // Dependent (color) components
+    else
+      {
+      // Two components - the first specifies color (through a lookup table)
+      // and the second specified opacity (through a lookup table)
+      if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 2 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropFixedPointCompositeHelperGenerateImageTwoDependentNN(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      // Four components - they must be unsigned char, the first three directly
+      // specify color and the fourth specifies opacity (through a lookup
+      // table)
+      else
+        {
+        if ( scalarType == VTK_UNSIGNED_CHAR )
+          {
+          vtkCropFixedPointCompositeHelperGenerateImageFourDependentNN(
+            static_cast<unsigned char *>(data), threadID, threadCount, mapper,
+            vol );
+          }
+        else
+          {
+          vtkErrorMacro("Four component dependent data must be unsigned char!");
+          }
+        }
+      }
+    }
+  // Trilinear Interpolation
+  else
+    {
+    // One component
+    if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 1 )
+      {
+      // Scale == 1.0 and shift == 0.0 - simple case (faster)
+	//	  printf("Scale == 1.0 and shift == 0.0 - simple case (faster)\n");
+      if ( mapper->GetTableScale()[0] == 1.0 &&
+           mapper->GetTableShift()[0] == 0.0 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropFixedPointCompositeHelperGenerateImageOneSimpleTrilin(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop
+      else
+        {
+	//		printf("Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop\n");
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropFixedPointCompositeHelperGenerateImageOneTrilin(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      }
+    // Indepedent components (more than one)
+    else if ( vol->GetProperty()->GetIndependentComponents() )
+      {
+		  printf("Indepedent components (more than one)\n");
+      switch ( scalarType )
+        {
+        vtkTemplateMacro(
+          vtkCropFixedPointCompositeHelperGenerateImageIndependentTrilin(
+            static_cast<VTK_TT *>(data),
+            threadID, threadCount, mapper, vol) );
+        }
+      }
+    // Dependent components
+    else
+      {
+      // Two components - the first specifies color (through a lookup table)
+      // and the second specified opacity (through a lookup table)
+      if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 2 )
+        {
+			printf("two components\n");
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropFixedPointCompositeHelperGenerateImageTwoDependentTrilin(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      // Four components - they must be unsigned char, the first three directly
+      // specify color and the fourth specifies opacity (through a lookup
+      // table)
+      else
+        {
+			//printf("four components\n");
+        if ( scalarType == VTK_UNSIGNED_CHAR )
+          {
+          vtkCropFixedPointCompositeHelperGenerateImageFourDependentTrilin(
+            static_cast<unsigned char *>(data), threadID, threadCount, mapper,
+            vol );
+          }
+        else
+          {
+          vtkErrorMacro("Four component dependent data must be unsigned char!");
+          }
+        }
+      }
+    }
+}
+
+// Print method for vtkCropVolumeRayCastCompositeHelper
+void vtkCropVolumeRayCastCompositeHelper::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+}
+
+float dotproduct(float a[3], float b[3])
+{
+	float dp = a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
+
+	return dp;
+}
+
+
+
+float vector_magnitude(float a[3])
+{
+	return (sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]));
+}
+
+
+
+
+
+void  IrregularCropper(unsigned short *val, unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper)
+{
+
+	double distance_from_point = 0.0;
+	int translucency_set = 0;
+	float end_vector[3];
+
+	float ray_position[3];
+	ray_position[0] = pos[0]/32767 ;
+	ray_position[1] = pos[1]/32767;
+	ray_position[2] = pos[2]/32767;
+
+	double locationxyz[3];
+	double FixedCubeLength[3];
+	double FixedEllipseRadius[3];
+	double CylinderAxis[3];
+
+	locationxyz[0] = locationxyz[1] = locationxyz[2] = 0.0;
+	mapper->GetFixedSphereCenter(locationxyz);
+
+	float angle = 0, centroid_angle =0;	
+	float total_distance = 0;
+	int c = 0;
+	
+	int score = 0;
+	
+	switch(mapper->GetProbeShape())
+	{
+	case 0:
+		// sphere
+		distance_from_point = sqrt(pow((double)ray_position[0]-locationxyz[0], 2.0) +
+			pow((double)ray_position[1]-locationxyz[1], 2.0) +
+			pow((double)ray_position[2]-locationxyz[2], 2.0));
+	
+		// for translucency
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			if(*val> 250)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			*val= 0;
+			tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+		}
+		break;
+
+	case 1:
+		// cube
+		
+		mapper->GetFixedCubeLength(FixedCubeLength);
+		if(fabs(ray_position[0]-(float)locationxyz[0]) < FixedCubeLength[0]/2.0 &&
+			fabs(ray_position[1]-(float)locationxyz[1]) < FixedCubeLength[1]/2.0 &&
+			fabs(ray_position[2]-(float)locationxyz[2]) < FixedCubeLength[2]/2.0)
+		{
+			if(*val > 250)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			
+			*val = 0; tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;			
+			if(translucency_set > 1)
+				tmp[2] = 50;
+		}
+
+	
+		break;
+
+	case 2:
+		// ellipse
+		
+		mapper->GetFixedEllipseRadius(FixedEllipseRadius); 
+
+		distance_from_point = pow(ray_position[0]-(float)locationxyz[0], 2.0f)/ pow(FixedEllipseRadius[0], 2.0) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f)/ pow(FixedEllipseRadius[1], 2.0) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f)/ pow(FixedEllipseRadius[2], 2.0); 
+
+		if(distance_from_point < 1.0)
+		{
+
+			if(*val > 20)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			*val = pow(2.0, distance_from_point); tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;			
+			if(translucency_set > 1)
+				tmp[2] = 10;
+
+		}		
+		break;
+
+	case 3:
+		// cylinder
+		
+		mapper->GetFixedCylinderAxis(CylinderAxis);
+
+		for(float t=0;t<mapper->GetFixedCylinderHeight();t=t+mapper->GetFixedCylinderHeight()/10)
+		{
+			end_vector[0] = locationxyz[0] - ( CylinderAxis[0] * t);
+			end_vector[1] = locationxyz[1] - ( CylinderAxis[1] * t);
+			end_vector[2] = locationxyz[2] - ( CylinderAxis[2] * t);
+
+			distance_from_point = sqrt(pow(ray_position[0]-(float)end_vector[0], 2.0f) +
+				pow(ray_position[1]-(float)end_vector[1], 2.0f) +
+				pow(ray_position[2]-(float)end_vector[2], 2.0f));
+
+			if(distance_from_point < mapper->GetFixedCylinderRadius())
+			{
+
+				if(*val > 0)
+					translucency_set = 2;
+				else
+					translucency_set = 1;
+				*val = 0; tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+				break;
+			}
+		}
+
+
+		break;
+
+	default:
+		// sphere
+		
+		distance_from_point = sqrt(pow(ray_position[0]-(float)locationxyz[0], 2.0f) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f));
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			translucency_set = 1;
+			if(*val > 0)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+			*val = 0; tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+		}
+		break;
+	}
+}
+
+void IrregularCropperArray(unsigned short val[4], unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper)
+{
+
+	double distance_from_point = 0.0;
+	int translucency_set = 0;
+	float end_vector[3];
+
+	float ray_position[3];
+	ray_position[0] = pos[0]/32767 ;
+	ray_position[1] = pos[1]/32767;
+	ray_position[2] = pos[2]/32767;
+
+	double locationxyz[3];
+	double FixedCubeLength[3];
+	double FixedEllipseRadius[3];
+	double CylinderAxis[3];
+
+	locationxyz[0] = locationxyz[1] = locationxyz[2] = 0.0;
+	mapper->GetFixedSphereCenter(locationxyz);
+
+	int greyscale_flag = 0; 
+
+	float angle = 0, centroid_angle =0;
+	float total_distance = 0;
+	int c = 0;
+	
+	int score = 0;
+	double axis_magnitude = 0; 
+
+
+	switch(mapper->GetProbeShape())
+	{
+	case 0:
+		// sphere
+		distance_from_point = sqrt(pow((double)ray_position[0]-locationxyz[0], 2.0) +
+			pow((double)ray_position[1]-locationxyz[1], 2.0) +
+			pow((double)ray_position[2]-locationxyz[2], 2.0));
+		// for translucency
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			if(val[0] > 10)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{					
+					if(translucency_set == 2)
+					{	
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+						tmp[2] = 10;
+					}
+					else
+					{
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+
+					}
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+		break;
+
+	case 1:
+		// cube
+
+		mapper->GetFixedCubeLength(FixedCubeLength);
+		if(fabs(ray_position[0]-(float)locationxyz[0]) < FixedCubeLength[0]/2.0 &&
+		   fabs(ray_position[1]-(float)locationxyz[1]) < FixedCubeLength[1]/2.0 &&
+		   fabs(ray_position[2]-(float)locationxyz[2]) < FixedCubeLength[2]/2.0)
+		  {
+
+			if(val[0] > 10)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{
+					val[0] = val[1] = val[2] = val[3] = 0;
+					tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+					// Gives the blue tint 
+					if(translucency_set > 0)
+					{
+						tmp[2] = 10;
+					}
+					else
+					{
+						tmp[2] = 0;
+					}
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+		break;
+
+	case 2:
+		// ellipse 
+		mapper->GetFixedEllipseRadius(FixedEllipseRadius); 
+
+		distance_from_point = pow(ray_position[0]-(float)locationxyz[0], 2.0f)/ pow(FixedEllipseRadius[0], 2.0) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f)/ pow(FixedEllipseRadius[1], 2.0) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f)/ pow(FixedEllipseRadius[2], 2.0); 
+
+		if(distance_from_point < 1.0)
+		{
+		
+			if(val[0] > 0)
+				translucency_set = 2;
+			else
+				translucency_set = 1; 			
+		
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{
+					
+					if(translucency_set == 2)
+					{	
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+						tmp[2] = 50;
+					}
+					else
+					{
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+
+					}
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+
+		break;
+
+
+	case 3:
+		// cylinder
+		mapper->GetFixedCylinderAxis(CylinderAxis);
+	
+		axis_magnitude = sqrt(CylinderAxis[0] *  CylinderAxis[0] + 
+							  CylinderAxis[1] *  CylinderAxis[1] +
+							  CylinderAxis[2] *  CylinderAxis[2]); 
+
+		CylinderAxis[0] /= axis_magnitude;
+		CylinderAxis[1] /= axis_magnitude;
+		CylinderAxis[2] /= axis_magnitude;
+
+		
+		//for(float t=0;t<mapper->GetFixedCylinderHeight();t=t+ mapper->GetFixedCylinderRadius()/4)
+		for(float t=0;t<mapper->GetFixedCylinderHeight();t=t+ mapper->GetFixedCylinderHeight()/10)
+		{
+			end_vector[0] = locationxyz[0] - ( CylinderAxis[0] * t);
+			end_vector[1] = locationxyz[1] - ( CylinderAxis[1] * t);
+			end_vector[2] = locationxyz[2] - ( CylinderAxis[2] * t);
+
+			distance_from_point = sqrt(pow(ray_position[0]-(float)end_vector[0], 2.0f) +
+				pow(ray_position[1]-(float)end_vector[1], 2.0f) +
+				pow(ray_position[2]-(float)end_vector[2], 2.0f));
+
+			if(distance_from_point < mapper->GetFixedCylinderRadius())				 
+			{
+
+				if(*val > 0)
+					translucency_set = 2;
+				else
+					translucency_set = 1;
+
+				// Check if functional crop is set - If set then dont crop functional data
+				if(mapper->GetFunctionalCropOn() == 1)
+				{
+					if(abs(val[0] - val[1]) < 1)
+					{
+						if(abs(val[1] - val[2]) < 1)
+						{
+							greyscale_flag = 1; 
+						}
+					}
+
+					if(greyscale_flag == 1)
+					{
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+					}
+				}
+				else // Crop everything including functional data. 
+				{
+					val[0] = val[1] = val[2] = val[3] = 0;
+					tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+				}
+
+				break;
+			}
+		}
+
+
+		break;
+
+	default:
+		// sphere
+
+		distance_from_point = sqrt(pow(ray_position[0]-(float)locationxyz[0], 2.0f) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f));
+		
+
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			translucency_set = 1;
+			if(*val > 0)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{
+					val[0] = val[1] = val[2] = val[3] = 0;
+					tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+		break;
+	}
+}
+
diff --git a/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeHelper.h b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeHelper.h
new file mode 100644
index 0000000..6c79c8e
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeHelper.h
@@ -0,0 +1,90 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkCropVolumeRayCastCompositeHelper.h,v $
+  Language:  C++
+  Date:      $Date: 2005/05/04 14:13:58 $
+  Version:   $Revision: 1.1 $
+
+  Copyright (c) 1993-2002 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 vtkCropVolumeRayCastCompositeHelper - A helper that generates composite images for the volume ray cast mapper
+// .SECTION Description
+// This is one of the helper classes for the vtkCropVolumeRayCastMapper.
+// It will generate composite images using an alpha blending operation.
+// This class should not be used directly, it is a helper class for
+// the mapper and has no user-level API.
+//
+// .SECTION see also
+// vtkCropVolumeRayCastMapper
+
+#ifndef __vtkCropVolumeRayCastCompositeHelper_h
+#define __vtkCropVolumeRayCastCompositeHelper_h
+
+#include "vtkFixedPointVolumeRayCastHelper.h"
+
+class vtkCropVolumeRayCastMapper;
+class vtkVolume;
+
+class  vtkCropVolumeRayCastCompositeHelper : public vtkFixedPointVolumeRayCastHelper
+{
+public:
+  static vtkCropVolumeRayCastCompositeHelper *New();
+  vtkTypeRevisionMacro(vtkCropVolumeRayCastCompositeHelper,vtkFixedPointVolumeRayCastHelper);
+  void PrintSelf( ostream& os, vtkIndent indent );
+
+  virtual void  GenerateImage( int threadID,
+                               int threadCount,
+                               vtkVolume *vol,
+                               vtkCropVolumeRayCastMapper *mapper);
+
+
+protected:
+  vtkCropVolumeRayCastCompositeHelper();
+  ~vtkCropVolumeRayCastCompositeHelper();
+
+private:
+  vtkCropVolumeRayCastCompositeHelper(const vtkCropVolumeRayCastCompositeHelper&);  // Not implemented.
+  void operator=(const vtkCropVolumeRayCastCompositeHelper&);  // Not implemented.
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeShadeHelper.cxx b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeShadeHelper.cxx
new file mode 100644
index 0000000..d43ac4e
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeShadeHelper.cxx
@@ -0,0 +1,1482 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkCropVolumeRayCastCompositeShadeHelper.cxx,v $
+  Language:  C++
+  Date:      $Date: 2007-11-08 16:51:06 $
+  Version:   $Revision: 1.9 $
+
+  Copyright (c) 1993-2002 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 "vtkCropVolumeRayCastCompositeShadeHelper.h"
+
+#include "vtkImageData.h"
+#include "vtkCommand.h"
+#include "vtkCropVolumeRayCastMapper.h"
+#include "vtkObjectFactory.h"
+#include "vtkRenderWindow.h"
+#include "vtkVolume.h"
+#include "vtkVolumeProperty.h"
+#include "vtkFixedPointRayCastImage.h"
+#include "vtkDataArray.h"
+
+#include <math.h>
+
+
+void ShadeIrregularCropper(unsigned short *val, unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper);
+void ShadeIrregularCropperArray(unsigned short val[4], unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper);
+
+vtkCxxRevisionMacro(vtkCropVolumeRayCastCompositeShadeHelper, "$Revision: 1.9 $");
+vtkStandardNewMacro(vtkCropVolumeRayCastCompositeShadeHelper);
+
+
+// Construct a new vtkCropVolumeRayCastCompositeShadeHelper with default values
+vtkCropVolumeRayCastCompositeShadeHelper::vtkCropVolumeRayCastCompositeShadeHelper()
+{
+}
+
+// Destruct a vtkCropVolumeRayCastCompositeShadeHelper - clean up any memory used
+vtkCropVolumeRayCastCompositeShadeHelper::~vtkCropVolumeRayCastCompositeShadeHelper()
+{
+}
+
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has one component and scale == 1.0 and shift == 0.0. In the inner
+// loop we get the data value as an unsigned short, and use this index to
+// lookup a color and opacity for this sample. We then composite this into
+// the color computed so far along the ray, and check if we can terminate at
+// this point (if the accumulated opacity is higher than some threshold).
+// Finally we move on to the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeShadeHelperGenerateImageOneSimpleNN( T *data,
+                                                   int threadID,
+                                                   int threadCount,
+                                                   vtkCropVolumeRayCastMapper *mapper,
+                                                   vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartShadeNN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_InitializeCompositeShadeNN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleShadeNN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short val    = static_cast<unsigned short>(((*dptr)));
+    VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp );
+    if (tmp[3])
+      {
+      unsigned short normal = *dirPtr;
+      VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp );
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has one component. In the inner loop we get the data value as
+// an unsigned short using the scale/shift, and use this index to lookup
+// a color and opacity for this sample. We then composite this into the
+// color computed so far along the ray, and check if we can terminate at
+// this point (if the accumulated opacity is higher than some threshold).
+// Finally we move on to the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeShadeHelperGenerateImageOneNN( T *data,
+                                             int threadID,
+                                             int threadCount,
+                                             vtkCropVolumeRayCastMapper *mapper,
+                                             vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartShadeNN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_InitializeCompositeShadeNN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleShadeNN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short val    = static_cast<unsigned short>(((*dptr) + shift[0])*scale[0]);
+    VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp );
+    if (tmp[3])
+      {
+      unsigned short normal = *dirPtr;
+      VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp );
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has two components which are not considered independent. In the
+// inner loop we compute the two unsigned short index values from the data
+// values (using the scale/shift). We use the first index to lookup a color,
+// and we use the second index to look up the opacity. We then composite
+// the color into the color computed so far along this ray, and check to
+// see if we can terminate here (if the opacity accumulated exceed some
+// threshold). Finally we move to the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeShadeHelperGenerateImageTwoDependentNN( T *data,
+                                                      int threadID,
+                                                      int threadCount,
+                                                      vtkCropVolumeRayCastMapper *mapper,
+                                                      vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartShadeNN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_InitializeCompositeShadeNN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleShadeNN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short val[2];
+    val[0] = static_cast<unsigned short>(((*(dptr  )) + shift[0])*scale[0]);
+    val[1] = static_cast<unsigned short>(((*(dptr+1)) + shift[1])*scale[1]);
+
+    tmp[3] = scalarOpacityTable[0][val[1]];
+    if (tmp[3])
+      {
+      tmp[0] = static_cast<unsigned short>
+        ((colorTable[0][3*val[0]  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+      tmp[1] = static_cast<unsigned short>
+        ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+      tmp[2] = static_cast<unsigned short>
+        ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+
+      unsigned short normal = *dirPtr;
+      VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp );
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has four components which are not considered independent . This
+// means that the first three components directly represent color, and this
+// data must be of unsigned char type. In the inner loop we directly access
+// the four data values (no scale/shift is needed). The first three are the
+// color of this sample and the fourth is used to look up an opacity in the
+// scalar opacity transfer function. We then composite this color into the
+// color we have accumulated so far along the ray, and check if we can
+// terminate here (if our accumulated opacity has exceed some threshold).
+// Finally we move onto the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeShadeHelperGenerateImageFourDependentNN( T *data,
+                                                       int threadID,
+                                                       int threadCount,
+                                                       vtkCropVolumeRayCastMapper *mapper,
+                                                       vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartShadeNN();
+  VTKKWRCHelper_InitializeCompositeOneNN();
+  VTKKWRCHelper_InitializeCompositeShadeNN();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleShadeNN();
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short val[4];
+    val[0] = *(dptr  );
+    val[1] = *(dptr+1);
+    val[2] = *(dptr+2);
+    val[3] = static_cast<unsigned short>(((*(dptr+3)) + shift[3])*scale[3]);
+
+    tmp[3] = scalarOpacityTable[0][val[3]];
+    if ( tmp[3] )
+      {
+      tmp[0] = (val[0]*tmp[3]+0x7f)>>(8);
+      tmp[1] = (val[1]*tmp[3]+0x7f)>>(8);
+      tmp[2] = (val[2]*tmp[3]+0x7f)>>(8);
+
+      unsigned short normal   = *dirPtr;
+      VTKKWRCHelper_LookupShading( diffuseShadingTable[0], specularShadingTable[0], normal, tmp );
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is nearest neighbor and
+// the data has more than one component and the components are considered to
+// be independent. In the inner loop we access each component value, using
+// the scale/shift to turn the data value into an unsigned short index. We
+// then lookup the color/opacity for each component and combine them according
+// to the weighting value for each component. We composite this resulting
+// color into the color already accumulated for this ray, and we check
+// wether we can terminate here (if the accumulated opacity exceeds some
+// threshold). Finally we increment to the next sample on the ray.
+//
+// TODO: short circuit calculations when opacity is 0
+template <class T>
+void vtkCropFixedPointCompositeShadeHelperGenerateImageIndependentNN( T *data,
+                                                     int threadID,
+                                                     int threadCount,
+                                                     vtkCropVolumeRayCastMapper *mapper,
+                                                     vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializeWeights();
+  VTKKWRCHelper_InitializationAndLoopStartShadeNN();
+  VTKKWRCHelper_InitializeCompositeMultiNN();
+  VTKKWRCHelper_InitializeCompositeShadeNN();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      VTKKWRCHelper_MoveToNextSampleShadeNN();
+      }
+
+    VTKKWRCHelper_CroppingCheckNN( pos );
+
+    unsigned short normal[4];
+    for ( c = 0; c < components; c++ )
+      {
+      val[c]    = static_cast<unsigned short>(((*(dptr+c)) + shift[c])*scale[c]);
+      normal[c] = *(dirPtr+c);
+      }
+
+    VTKKWRCHelper_LookupAndCombineIndependentColorsShadeUS( colorTable, scalarOpacityTable,
+                                                            diffuseShadingTable,
+                                                            specularShadingTable,
+                                                            val, normal, weights,
+                                                            components, tmp );
+
+    if ( tmp[3] )
+      {
+      VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+      }
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is linear and the data
+// has one component and scale = 1.0 and shift = 0.0. In the inner loop we
+// get the data value for the eight cell corners (if we have changed cells)
+// as an unsigned short (the range must be right and we don't need the
+// scale/shift). We compute our weights within the cell according to our
+// fractional position within the cell, apply trilinear interpolation to
+// compute the index, and use this index to lookup a color and opacity for
+// this sample. We then composite this into the color computed so far along
+// the ray, and check if we can terminate at this point (if the accumulated
+// opacity is higher than some threshold). Finally we move on to the next
+// sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeShadeHelperGenerateImageOneSimpleTrilin( T *data,
+                                                       int threadID,
+                                                       int threadCount,
+                                                       vtkCropVolumeRayCastMapper *mapper,
+                                                       vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeOneTrilin();
+  VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+ // printf("in lit trilinear\n"); 
+
+  int needToSampleDirection = 0;
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellScalarValuesSimple( dptr );
+      dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      needToSampleDirection = 1;
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalar(val);
+
+    VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp );
+
+	ShadeIrregularCropper(&val, tmp, pos, mapper);	
+
+    if ( needToSampleDirection )
+      {
+      VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH );
+      needToSampleDirection = 0;
+      }
+
+    VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp );
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is linear and the data
+// has one component and scale != 1.0 or shift != 0.0. In the inner loop we
+// get the data value for the eight cell corners (if we have changed cells)
+// as an unsigned short (we use the scale/shift to ensure the correct range).
+// We compute our weights within the cell according to our fractional position
+// within the cell, apply trilinear interpolation to compute the index, and use
+// this index to lookup a color and opacity for this sample. We then composite
+// this into the color computed so far along the ray, and check if we can
+// terminate at this point (if the accumulated opacity is higher than some
+// threshold). Finally we move on to the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeShadeHelperGenerateImageOneTrilin( T *data,
+                                                 int threadID,
+                                                 int threadCount,
+                                                 vtkCropVolumeRayCastMapper *mapper,
+                                                 vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeOneTrilin();
+  VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  int needToSampleDirection = 0;
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellScalarValues( dptr, scale[0], shift[0] );
+      dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      needToSampleDirection = 1;
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalar(val);
+
+    VTKKWRCHelper_LookupColorUS( colorTable[0], scalarOpacityTable[0], val, tmp );
+    if ( needToSampleDirection )
+      {
+      VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH );
+      needToSampleDirection = 0;
+      }
+    VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp );
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+// This method is used when the interpolation type is linear, the data has
+// two components and the components are not considered independent. In the
+// inner loop we get the data value for the eight cell corners (if we have
+// changed cells) for both components as an unsigned shorts (we use the
+// scale/shift to ensure the correct range). We compute our weights within
+// the cell according to our fractional position within the cell, and apply
+// trilinear interpolation to compute the two index value. We use the first
+// index to lookup a color and the second to look up an opacity for this sample.
+// We then composite this into the color computed so far along the ray, and
+// check if we can terminate at this point (if the accumulated opacity is
+// higher than some threshold). Finally we move on to the next sample along
+// the ray.
+template <class T>
+void vtkCropFixedPointCompositeShadeHelperGenerateImageTwoDependentTrilin( T *data,
+                                                          int threadID,
+                                                          int threadCount,
+                                                          vtkCropVolumeRayCastMapper *mapper,
+                                                          vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiTrilin();
+  VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  int needToSampleDirection = 0;
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] );
+
+      dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      needToSampleDirection = 1;
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalarComponent( val, c, 2 );
+
+    tmp[3] = scalarOpacityTable[0][val[1]];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleDirection )
+      {
+      VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH );
+      needToSampleDirection = 0;
+      }
+
+    tmp[0] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]  ]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[1] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+1]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+    tmp[2] = static_cast<unsigned short>
+      ((colorTable[0][3*val[0]+2]*tmp[3] + 0x7fff)>>(VTKKW_FP_SHIFT));
+
+    VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp );
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+
+// This method is used when the interpolation type is linear, the data has
+// four components and the components are not considered independent. In the
+// inner loop we get the data value for the eight cell corners (if we have
+// changed cells) for all components as an unsigned shorts (we don't have to
+// use the scale/shift because only unsigned char data is supported for four
+// component data when the components are not independent). We compute our
+// weights within the cell according to our fractional position within the cell,
+// and apply trilinear interpolation to compute a value for each component. We
+// use the first three directly as the color of the sample, and the fourth is
+// used to look up an opacity for this sample. We then composite this into the
+// color computed so far along the ray, and check if we can terminate at this
+// point (if the accumulated opacity is higher than some threshold). Finally we
+// move on to the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeShadeHelperGenerateImageFourDependentTrilin( T *data,
+                                                           int threadID,
+                                                           int threadCount,
+                                                           vtkCropVolumeRayCastMapper *mapper,
+                                                           vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializationAndLoopStartShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiTrilin();
+  VTKKWRCHelper_InitializeCompositeOneShadeTrilin();
+  VTKKWRCHelper_SpaceLeapSetup();
+
+  int needToSampleDirection = 0;
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_SpaceLeapCheck();
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 0 );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 1 );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentRawScalarValues( dptr, 2 );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] );
+
+      dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      needToSampleDirection = 1;
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalarComponent( val, c, components );
+
+	ShadeIrregularCropperArray(val, tmp, pos, mapper);
+
+    tmp[3] = scalarOpacityTable[0][val[3]];
+    if ( !tmp[3] )
+      {
+      continue;
+      }
+
+    if ( needToSampleDirection )
+      {
+      VTKKWRCHelper_GetCellDirectionValues( dirPtrABCD, dirPtrEFGH );
+      needToSampleDirection = 0;
+      }
+
+    tmp[0] = (val[0]*tmp[3]+0x7f)>>8;
+    tmp[1] = (val[1]*tmp[3]+0x7f)>>8;
+    tmp[2] = (val[2]*tmp[3]+0x7f)>>8;
+
+    VTKKWRCHelper_InterpolateShading( diffuseShadingTable[0], specularShadingTable[0], tmp );
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+// This method is used when the interpolation type is linear, the data has
+// more than one component and the components are considered independent. In
+// the inner loop we get the data value for the eight cell corners (if we have
+// changed cells) for all components as an unsigned shorts (we have to use the
+// scale/shift to ensure that we obtained unsigned short indices) We compute our
+// weights within the cell according to our fractional position within the cell,
+// and apply trilinear interpolation to compute a value for each component. We
+// look up a color/opacity for each component and blend them according to the
+// component weights. We then composite this resulting color into the
+// color computed so far along the ray, and check if we can terminate at this
+// point (if the accumulated opacity is higher than some threshold). Finally we
+// move on to the next sample along the ray.
+template <class T>
+void vtkCropFixedPointCompositeShadeHelperGenerateImageIndependentTrilin( T *data,
+                                                         int threadID,
+                                                         int threadCount,
+                                                         vtkCropVolumeRayCastMapper *mapper,
+                                                         vtkVolume *vol)
+{
+  VTKKWRCHelper_InitializeWeights();
+  VTKKWRCHelper_InitializationAndLoopStartShadeTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiTrilin();
+  VTKKWRCHelper_InitializeCompositeMultiShadeTrilin();
+
+  for ( k = 0; k < numSteps; k++ )
+    {
+    if ( k )
+      {
+      mapper->FixedPointIncrement( pos, dir );
+      }
+
+    VTKKWRCHelper_CroppingCheckTrilin( pos );
+
+    mapper->ShiftVectorDown( pos, spos );
+    if ( spos[0] != oldSPos[0] ||
+         spos[1] != oldSPos[1] ||
+         spos[2] != oldSPos[2] )
+      {
+      oldSPos[0] = spos[0];
+      oldSPos[1] = spos[1];
+      oldSPos[2] = spos[2];
+
+      dptr = data + spos[0]*inc[0] + spos[1]*inc[1] + spos[2]*inc[2];
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 0, scale[0], shift[0] );
+
+      dptr++;
+      VTKKWRCHelper_GetCellComponentScalarValues( dptr, 1, scale[1], shift[1] );
+
+      if ( components > 2 )
+        {
+        dptr++;
+        VTKKWRCHelper_GetCellComponentScalarValues( dptr, 2, scale[2], shift[2] );
+        if ( components > 3 )
+          {
+          dptr++;
+          VTKKWRCHelper_GetCellComponentScalarValues( dptr, 3, scale[3], shift[3] );
+          }
+        }
+
+
+      dirPtrABCD = gradientDir[spos[2]  ] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      dirPtrEFGH = gradientDir[spos[2]+1] + spos[0]*dInc[0] + spos[1]*dInc[1];
+      VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 0 );
+
+      dirPtrABCD++;
+      dirPtrEFGH++;
+      VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 1 );
+
+      if ( components > 2 )
+        {
+        dirPtrABCD++;
+        dirPtrEFGH++;
+        VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 2 );
+        if ( components > 3 )
+          {
+          dirPtrABCD++;
+          dirPtrEFGH++;
+          VTKKWRCHelper_GetCellComponentDirectionValues( dirPtrABCD, dirPtrEFGH, 3 );
+          }
+        }
+      }
+
+    VTKKWRCHelper_ComputeWeights(pos);
+    VTKKWRCHelper_InterpolateScalarComponent( val, c, components );
+
+    VTKKWRCHelper_LookupAndCombineIndependentColorsInterpolateShadeUS(
+      colorTable, scalarOpacityTable, diffuseShadingTable,
+      specularShadingTable, val, weights, components, tmp );
+
+    VTKKWRCHelper_CompositeColorAndCheckEarlyTermination( color, tmp, remainingOpacity );
+    }
+
+  VTKKWRCHelper_SetPixelColor( imagePtr, color, remainingOpacity );
+  VTKKWRCHelper_IncrementAndLoopEnd();
+}
+
+
+void vtkCropVolumeRayCastCompositeShadeHelper::GenerateImage(
+  int threadID,
+  int threadCount,
+  vtkVolume *vol,
+  vtkCropVolumeRayCastMapper *mapper )
+{
+  void *data     = mapper->GetCurrentScalars()->GetVoidPointer(0);
+  int scalarType = mapper->GetCurrentScalars()->GetDataType();
+
+  // Nearest Neighbor interpolate
+  if ( mapper->ShouldUseNearestNeighborInterpolation( vol ) )
+    {
+    // One component data
+    if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 1 )
+      {
+      // Scale == 1.0 and shift == 0.0 - simple case (faster)
+      if ( mapper->GetTableScale()[0] == 1.0 &&
+           mapper->GetTableShift()[0] == 0.0 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropFixedPointCompositeShadeHelperGenerateImageOneSimpleNN(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      else
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropFixedPointCompositeShadeHelperGenerateImageOneNN(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      }
+    // More that one independent components
+    else if ( vol->GetProperty()->GetIndependentComponents() )
+      {
+      switch ( scalarType )
+        {
+        vtkTemplateMacro(
+          vtkCropFixedPointCompositeShadeHelperGenerateImageIndependentNN(
+            static_cast<VTK_TT *>(data),
+            threadID, threadCount, mapper, vol) );
+        }
+      }
+    // Dependent (color) components
+    else
+      {
+      // Two components - the first specifies color (through a lookup table)
+      // and the second specified opacity (through a lookup table)
+      if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 2 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropFixedPointCompositeShadeHelperGenerateImageTwoDependentNN(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      // Four components - they must be unsigned char, the first three directly
+      // specify color and the fourth specifies opacity (through a lookup
+      // table)
+      else
+        {
+        if ( scalarType == VTK_UNSIGNED_CHAR )
+          {
+          vtkCropFixedPointCompositeShadeHelperGenerateImageFourDependentNN(
+            static_cast<unsigned char *>(data), threadID, threadCount, mapper,
+            vol );
+          }
+        else
+          {
+          vtkErrorMacro("Four component dependent data must be unsigned char");
+          }
+        }
+      }
+    }
+  // Trilinear Interpolation
+  else
+    {
+    // One component
+    if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 1 )
+      {
+      // Scale == 1.0 and shift == 0.0 - simple case (faster)
+      if ( mapper->GetTableScale()[0] == 1.0 &&
+           mapper->GetTableShift()[0] == 0.0 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropFixedPointCompositeShadeHelperGenerateImageOneSimpleTrilin(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      // Scale != 1.0 or shift != 0.0 - must apply scale/shift in inner loop
+      else
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropFixedPointCompositeShadeHelperGenerateImageOneTrilin(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      }
+    // Indepedent components (more than one)
+    else if ( vol->GetProperty()->GetIndependentComponents() )
+      {
+      switch ( scalarType )
+        {
+        vtkTemplateMacro(
+          vtkCropFixedPointCompositeShadeHelperGenerateImageIndependentTrilin(
+            static_cast<VTK_TT *>(data),
+            threadID, threadCount, mapper, vol) );
+        }
+      }
+    // Dependent components
+    else
+      {
+      // Two components - the first specifies color (through a lookup table)
+      // and the second specified opacity (through a lookup table)
+      if ( mapper->GetCurrentScalars()->GetNumberOfComponents() == 2 )
+        {
+        switch ( scalarType )
+          {
+          vtkTemplateMacro(
+            vtkCropFixedPointCompositeShadeHelperGenerateImageTwoDependentTrilin(
+              static_cast<VTK_TT *>(data),
+              threadID, threadCount, mapper, vol) );
+          }
+        }
+      // Four components - they must be unsigned char, the first three directly
+      // specify color and the fourth specifies opacity (through a lookup
+      // table)
+      else
+        {
+        if ( scalarType == VTK_UNSIGNED_CHAR )
+          {
+          vtkCropFixedPointCompositeShadeHelperGenerateImageFourDependentTrilin(
+            static_cast<unsigned char *>(data), threadID, threadCount, mapper,
+            vol );
+          }
+        else
+          {
+          vtkErrorMacro("Four component dependent data must be unsigned char");
+          }
+        }
+      }
+    }
+}
+
+// Print method for vtkCropVolumeRayCastCompositeShadeHelper
+void vtkCropVolumeRayCastCompositeShadeHelper::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+}
+
+
+void  ShadeIrregularCropper(unsigned short *val, unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper)
+{
+
+	double distance_from_point = 0.0;
+	int translucency_set = 0;
+	float end_vector[3];
+
+	float ray_position[3];
+	ray_position[0] = pos[0]/32767 ;
+	ray_position[1] = pos[1]/32767;
+	ray_position[2] = pos[2]/32767;
+
+	double locationxyz[3];
+	double FixedCubeLength[3];
+	double FixedEllipseRadius[3];
+	double CylinderAxis[3];
+
+	locationxyz[0] = locationxyz[1] = locationxyz[2] = 0.0;
+	mapper->GetFixedSphereCenter(locationxyz);
+
+	float angle = 0, centroid_angle =0;
+	float vector1[3], vector2[3], centroid_vector[3], center_distance[3];
+	float total_distance = 0;
+	int c = 0;
+	int i, j;
+	int score = 0;
+	
+	switch(mapper->GetProbeShape())
+	{
+	case 0:
+		// sphere
+		distance_from_point = sqrt(pow((double)ray_position[0]-locationxyz[0], 2.0) +
+			pow((double)ray_position[1]-locationxyz[1], 2.0) +
+			pow((double)ray_position[2]-locationxyz[2], 2.0));
+	
+		// for translucency
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			if(*val> 250)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			*val= 0;
+			tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+		}
+		break;
+
+	case 1:
+		// cube
+		
+		mapper->GetFixedCubeLength(FixedCubeLength);
+		if(fabs(ray_position[0]-(float)locationxyz[0]) < FixedCubeLength[0]/2.0 &&
+			fabs(ray_position[1]-(float)locationxyz[1]) < FixedCubeLength[1]/2.0 &&
+			fabs(ray_position[2]-(float)locationxyz[2]) < FixedCubeLength[2]/2.0)
+		{
+
+			if(*val > 250)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			//printf("getting here in irregular cropper\n"); 
+
+			*val = 0; tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;			
+			if(translucency_set > 1)
+				tmp[2] = 50;
+
+		}
+
+		//angle = 0;
+
+		//center_distance[0] = points[0][0]- centroid[0];
+		//center_distance[1] = points[0][1]- centroid[1];
+		//center_distance[2] = points[0][2]- centroid[2];
+
+		//total_distance = 0;
+		//for(int index=0;index<number_of_landmarks-1;index++)
+		//{
+		//	// ray - index, index - index+1 < 359
+
+		//	vector1[0] = points[index][0]- ray_position[0];
+		//	vector1[1] = points[index][1]- ray_position[1];
+		//	vector1[2] = points[index][2]- ray_position[2];
+
+		//	vector2[0] = points[index+1][0]- ray_position[0];
+		//	vector2[1] = points[index+1][1]- ray_position[1];
+		//	vector2[2] = points[index+1][2]- ray_position[2];
+
+		//	//angle = (vector1[0]*vector2[0] + vector1[1]*vector2[1] + vector1[2]*vector2[2])/;
+		//	angle += acos(dotproduct(vector1, vector2)/(vector_magnitude(vector1) * vector_magnitude(vector2)));
+
+		//	centroid_vector[0] = ray_position[0]- centroid[0];
+		//	centroid_vector[1] = ray_position[1]- centroid[1];
+		//	centroid_vector[2] = ray_position[2]- centroid[2];
+
+		//	total_distance+= vector_magnitude(centroid_vector);
+		//	//printf("inside angle =%f\n", angle);
+		//}
+
+		////printf("angle =%f\n", angle);
+
+		//if(((angle*180.0)/3.14) > 315)
+		//{
+		//	/*if(ray_position[0] > minpos[0] && ray_position[1] > minpos[1] && ray_position[2] > minpos[2] &&
+		//		ray_position[0] < maxpos[0] && ray_position[1] < maxpos[1] && ray_position[2] < maxpos[2])
+		//	{*/
+		//	if(*val>10)
+		//	{
+		//		tmp[0] = tmp[1] = tmp[3] = 0;
+		//		tmp[2] = 100; 
+		//	}
+		//	else
+		//	{
+		//		tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+		//	}
+		//	*val = 0; 
+		//	//}
+		//}
+
+
+		break;
+
+	case 2:
+		// ellipse
+		
+		mapper->GetFixedEllipseRadius(FixedEllipseRadius); 
+
+		distance_from_point = pow(ray_position[0]-(float)locationxyz[0], 2.0f)/ pow(FixedEllipseRadius[0], 2.0) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f)/ pow(FixedEllipseRadius[1], 2.0) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f)/ pow(FixedEllipseRadius[2], 2.0); 
+
+		if(distance_from_point < 1.0)
+		{
+			//printf("distance is %.2f\n", distance_from_point); 
+			//printf("%f %f %f\n", FixedEllipseRadius[0], FixedEllipseRadius[1], FixedEllipseRadius[2]); 
+
+			if(*val > 20)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			//printf("getting here in irregular cropper\n"); 
+
+			*val = pow(2.0, distance_from_point); tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;			
+			if(translucency_set > 1)
+				tmp[2] = 10;
+
+		}		
+		break;
+
+	case 3:
+		// cylinder
+		
+		mapper->GetFixedCylinderAxis(CylinderAxis);
+
+		for(float t=0;t<mapper->GetFixedCylinderHeight();t=t+mapper->GetFixedCylinderHeight()/10)
+		{
+			end_vector[0] = locationxyz[0] - ( CylinderAxis[0] * t);
+			end_vector[1] = locationxyz[1] - ( CylinderAxis[1] * t);
+			end_vector[2] = locationxyz[2] - ( CylinderAxis[2] * t);
+
+			distance_from_point = sqrt(pow(ray_position[0]-(float)end_vector[0], 2.0f) +
+				pow(ray_position[1]-(float)end_vector[1], 2.0f) +
+				pow(ray_position[2]-(float)end_vector[2], 2.0f));
+
+			//if(distance_from_point < mapper->GetCylinderRadius())
+			if(distance_from_point < mapper->GetFixedCylinderRadius())
+			{
+
+				if(*val > 0)
+					translucency_set = 2;
+				else
+					translucency_set = 1;
+				*val = 0; tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+				break;
+			}
+		}
+
+
+		break;
+
+	default:
+		// sphere
+		
+		distance_from_point = sqrt(pow(ray_position[0]-(float)locationxyz[0], 2.0f) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f));
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			translucency_set = 1;
+			if(*val > 0)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+			*val = 0; tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+		}
+		break;
+	}
+}
+
+
+void ShadeIrregularCropperArray(unsigned short val[4], unsigned short tmp[4], unsigned int pos[3], vtkCropVolumeRayCastMapper *mapper)
+{
+
+	double distance_from_point = 0.0;
+	int translucency_set = 0;
+	float end_vector[3];
+
+	float ray_position[3];
+	ray_position[0] = pos[0]/32767 ;
+	ray_position[1] = pos[1]/32767;
+	ray_position[2] = pos[2]/32767;
+
+	//double CubeX, CubeY, CubeZ;
+
+	double locationxyz[3];
+	double FixedCubeLength[3];
+	double FixedEllipseRadius[3];
+	double CylinderAxis[3];
+
+	locationxyz[0] = locationxyz[1] = locationxyz[2] = 0.0;
+	mapper->GetFixedSphereCenter(locationxyz);
+
+	int greyscale_flag = 0; 
+
+	float angle = 0, centroid_angle =0;
+	float vector1[3], vector2[3], centroid_vector[3], center_distance[3];
+	float total_distance = 0;
+	int c = 0;
+	int i, j;
+	int score = 0;
+	double axis_magnitude = 0; 
+
+
+	switch(mapper->GetProbeShape())
+	{
+	case 0:
+		// sphere
+		distance_from_point = sqrt(pow((double)ray_position[0]-locationxyz[0], 2.0) +
+			pow((double)ray_position[1]-locationxyz[1], 2.0) +
+			pow((double)ray_position[2]-locationxyz[2], 2.0));
+		// for translucency
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			if(val[0] > 10)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{					
+					if(translucency_set == 2)
+					{	
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+						tmp[2] = 10;
+					}
+					else
+					{
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+
+					}
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+		break;
+
+	case 1:
+		// cube
+		//angle = 0;
+
+		//center_distance[0] = points[0][0]- centroid[0];
+		//center_distance[1] = points[0][1]- centroid[1];
+		//center_distance[2] = points[0][2]- centroid[2];
+
+		//total_distance = 0;
+		//for(int index=0;index<number_of_landmarks-1;index++)
+		//{
+		//	// ray - index, index - index+1 < 359
+
+		//	vector1[0] = points[index][0]- ray_position[0];
+		//	vector1[1] = points[index][1]- ray_position[1];
+		//	vector1[2] = points[index][2]- ray_position[2];
+
+		//	vector2[0] = points[index+1][0]- ray_position[0];
+		//	vector2[1] = points[index+1][1]- ray_position[1];
+		//	vector2[2] = points[index+1][2]- ray_position[2];
+
+		//	//angle = (vector1[0]*vector2[0] + vector1[1]*vector2[1] + vector1[2]*vector2[2])/;
+		//	angle += acos(dotproduct(vector1, vector2)/(vector_magnitude(vector1) * vector_magnitude(vector2)));
+
+		//	centroid_vector[0] = ray_position[0]- centroid[0];
+		//	centroid_vector[1] = ray_position[1]- centroid[1];
+		//	centroid_vector[2] = ray_position[2]- centroid[2];
+
+		//	total_distance+= vector_magnitude(centroid_vector);
+		//	//printf("inside angle =%f\n", angle);
+		//}
+
+		////printf("angle =%f\n", angle);
+
+		//if(((angle*180.0)/3.14) > 315)
+		//{
+		//	/*if(ray_position[0] > minpos[0] && ray_position[1] > minpos[1] && ray_position[2] > minpos[2] &&
+		//		ray_position[0] < maxpos[0] && ray_position[1] < maxpos[1] && ray_position[2] < maxpos[2])
+		//	{*/
+		//	/*if(*val>10)
+		//	{
+		//		tmp[0] = tmp[1] = tmp[3] = 0;
+		//		tmp[2] = 100; 
+		//	}
+		//	else
+		//	{
+		//		tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+		//	}
+		//	val[0] = val[1] = val[2] = val[3] = 0;	*/		
+
+		//	if(mapper->GetFunctionalCropOn() == 1)
+		//	{
+		//		if(abs(val[0] - val[1]) < 1)
+		//		{
+		//			if(abs(val[1] - val[2]) < 1)
+		//			{
+		//				greyscale_flag = 1; 
+		//			}
+		//		}
+
+		//		if(greyscale_flag == 1)
+		//		{
+		//			val[0] = val[1] = val[2] = val[3] = 0;
+		//			tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+		//			if(translucency_set > 0)
+		//			{
+		//				tmp[2] = 50;
+		//			}
+		//			else
+		//			{
+		//				tmp[2] = 0;
+		//			}
+		//		}
+		//	}
+		//	else // Crop everything including functional data. 
+		//	{
+		//		val[0] = val[1] = val[2] = val[3] = 0;
+		//		tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+		//	}
+
+
+		//	//}
+		//}
+
+		// old stuff 
+		mapper->GetFixedCubeLength(FixedCubeLength);
+		if(fabs(ray_position[0]-(float)locationxyz[0]) < FixedCubeLength[0]/2.0 &&
+		   fabs(ray_position[1]-(float)locationxyz[1]) < FixedCubeLength[1]/2.0 &&
+		   fabs(ray_position[2]-(float)locationxyz[2]) < FixedCubeLength[2]/2.0)
+		  {
+
+			if(val[0] > 10)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{
+					val[0] = val[1] = val[2] = val[3] = 0;
+					tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+					if(translucency_set > 0)
+					{
+						tmp[2] = 10;
+					}
+					else
+					{
+						tmp[2] = 0;
+					}
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+		break;
+
+	case 2:
+		// ellipse 
+		distance_from_point = pow(ray_position[0]-(float)locationxyz[0], 2.0f)/50.0 +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f)/100.0 +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f)/50.0;
+
+		  if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+		
+			if(val[0] > 0)
+				translucency_set = 2;
+			else
+				translucency_set = 1; 			
+		
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{
+					
+					if(translucency_set == 2)
+					{	
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+						tmp[2] = 50;
+					}
+					else
+					{
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+
+					}
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+
+		break;
+
+
+	case 3:
+		// cylinder
+		mapper->GetFixedCylinderAxis(CylinderAxis);
+	
+		axis_magnitude = sqrt(CylinderAxis[0] *  CylinderAxis[0] + 
+							  CylinderAxis[1] *  CylinderAxis[1] +
+							  CylinderAxis[2] *  CylinderAxis[2]); 
+
+		CylinderAxis[0] /= axis_magnitude;
+		CylinderAxis[1] /= axis_magnitude;
+		CylinderAxis[2] /= axis_magnitude;
+
+		
+		//for(float t=0;t<mapper->GetFixedCylinderHeight();t=t+ mapper->GetFixedCylinderRadius()/4)
+		for(float t=0;t<mapper->GetFixedCylinderHeight();t=t+ mapper->GetFixedCylinderHeight()/10)
+		{
+			end_vector[0] = locationxyz[0] - ( CylinderAxis[0] * t);
+			end_vector[1] = locationxyz[1] - ( CylinderAxis[1] * t);
+			end_vector[2] = locationxyz[2] - ( CylinderAxis[2] * t);
+
+			distance_from_point = sqrt(pow(ray_position[0]-(float)end_vector[0], 2.0f) +
+				pow(ray_position[1]-(float)end_vector[1], 2.0f) +
+				pow(ray_position[2]-(float)end_vector[2], 2.0f));
+
+			if(distance_from_point < mapper->GetFixedCylinderRadius())				 
+			{
+
+				if(*val > 0)
+					translucency_set = 2;
+				else
+					translucency_set = 1;
+
+				// Check if functional crop is set - If set then dont crop functional data
+				if(mapper->GetFunctionalCropOn() == 1)
+				{
+					if(abs(val[0] - val[1]) < 1)
+					{
+						if(abs(val[1] - val[2]) < 1)
+						{
+							greyscale_flag = 1; 
+						}
+					}
+
+					if(greyscale_flag == 1)
+					{
+						val[0] = val[1] = val[2] = val[3] = 0;
+						tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+					}
+				}
+				else // Crop everything including functional data. 
+				{
+					val[0] = val[1] = val[2] = val[3] = 0;
+					tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+				}
+
+				break;
+			}
+		}
+
+
+		break;
+
+	default:
+		// sphere
+
+		distance_from_point = sqrt(pow(ray_position[0]-(float)locationxyz[0], 2.0f) +
+			pow(ray_position[1]-(float)locationxyz[1], 2.0f) +
+			pow(ray_position[2]-(float)locationxyz[2], 2.0f));
+
+		printf("in default: %d\n", mapper->GetProbeShape()); 
+
+		if(distance_from_point < mapper->GetFixedSphereRadius())
+		{
+			translucency_set = 1;
+			if(*val > 0)
+				translucency_set = 2;
+			else
+				translucency_set = 1;
+
+			// Check if functional crop is set - If set then dont crop functional data
+			if(mapper->GetFunctionalCropOn() == 1)
+			{
+				if(abs(val[0] - val[1]) < 1)
+				{
+					if(abs(val[1] - val[2]) < 1)
+					{
+						greyscale_flag = 1; 
+					}
+				}
+
+				if(greyscale_flag == 1)
+				{
+					val[0] = val[1] = val[2] = val[3] = 0;
+					tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+				}
+			}
+			else // Crop everything including functional data. 
+			{
+				val[0] = val[1] = val[2] = val[3] = 0;
+				tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
+			}
+		}
+		break;
+	}
+}
+
diff --git a/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeShadeHelper.h b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeShadeHelper.h
new file mode 100644
index 0000000..812d213
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastCompositeShadeHelper.h
@@ -0,0 +1,88 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkCropVolumeRayCastCompositeShadeHelper.h,v $
+  Language:  C++
+  Date:      $Date: 2008-06-16 08:27:56 $
+  Version:   $Revision: 1.2 $
+
+  Copyright (c) 1993-2002 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 vtkCropVolumeRayCastCompositeShadeHelper - A helper that generates composite images for the volume ray cast mapper
+// .SECTION Description
+// This is one of the helper classes for the vtkFixedPointVolumeRayCastMapper.
+// It will generate composite images using an alpha blending operation.
+// This class should not be used directly, it is a helper class for
+// the mapper and has no user-level API.
+//
+// .SECTION see also
+// vtkFixedPointVolumeRayCastMapper
+
+#ifndef __vtkCropVolumeRayCastCompositeShadeHelper_h
+#define __vtkCropVolumeRayCastCompositeShadeHelper_h
+
+#include "vtkFixedPointVolumeRayCastHelper.h"
+
+class vtkCropVolumeRayCastMapper;
+class vtkVolume;
+
+class vtkCropVolumeRayCastCompositeShadeHelper : public vtkFixedPointVolumeRayCastHelper
+{
+public:
+  static vtkCropVolumeRayCastCompositeShadeHelper *New();
+  vtkTypeRevisionMacro(vtkCropVolumeRayCastCompositeShadeHelper,vtkFixedPointVolumeRayCastHelper);  
+  void PrintSelf( ostream& os, vtkIndent indent );
+
+  virtual void  GenerateImage( int threadID,
+                               int threadCount,
+                               vtkVolume *vol,
+                               vtkCropVolumeRayCastMapper *mapper);
+
+protected:
+  vtkCropVolumeRayCastCompositeShadeHelper();
+  ~vtkCropVolumeRayCastCompositeShadeHelper();
+
+private:
+  vtkCropVolumeRayCastCompositeShadeHelper(const vtkCropVolumeRayCastCompositeShadeHelper&);  // Not implemented.
+  void operator=(const vtkCropVolumeRayCastCompositeShadeHelper&);  // Not implemented.
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastMapper.cxx b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastMapper.cxx
new file mode 100644
index 0000000..fa22435
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastMapper.cxx
@@ -0,0 +1,3719 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkCropVolumeRayCastMapper.cxx,v $
+
+  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 "vtkCropVolumeRayCastMapper.h"
+
+#include "vtkCamera.h"
+#include "vtkColorTransferFunction.h"
+#include "vtkDataArray.h"
+#include "vtkEncodedGradientShader.h"
+#include "vtkFiniteDifferenceGradientEstimator.h"
+#include "vtkImageData.h"
+#include "vtkCommand.h"
+#include "vtkGraphicsFactory.h"
+#include "vtkSphericalDirectionEncoder.h"
+#include "vtkCropVolumeRayCastCompositeGOHelper.h"
+#include "vtkCropVolumeRayCastCompositeGOShadeHelper.h"
+#include "vtkCropVolumeRayCastCompositeHelper.h"
+#include "vtkCropVolumeRayCastCompositeShadeHelper.h"
+#include "vtkFixedPointVolumeRayCastMIPHelper.h"
+#include "vtkLight.h"
+#include "vtkMath.h"
+#include "vtkMultiThreader.h"
+#include "vtkObjectFactory.h"
+#include "vtkPiecewiseFunction.h"
+#include "vtkPlaneCollection.h"
+#include "vtkPointData.h"
+#include "vtkRenderWindow.h"
+#include "vtkRenderer.h"
+#include "vtkTimerLog.h"
+#include "vtkTransform.h"
+#include "vtkVolumeProperty.h"
+#include "vtkRayCastImageDisplayHelper.h"
+#include "vtkFixedPointRayCastImage.h"
+
+#include <math.h>
+
+vtkCxxRevisionMacro(vtkCropVolumeRayCastMapper, "$Revision: 1.46 $");
+vtkStandardNewMacro(vtkCropVolumeRayCastMapper);
+vtkCxxSetObjectMacro(vtkCropVolumeRayCastMapper, RayCastImage, vtkFixedPointRayCastImage);
+
+// Macro for tri-linear interpolation - do four linear interpolations on
+// edges, two linear interpolations between pairs of edges, then a final
+// interpolation between faces
+#define vtkTrilinFuncMacro(v,x,y,z,a,b,c,d,e,f,g,h)         \
+        t00 =   a + (x)*(b-a);      \
+        t01 =   c + (x)*(d-c);      \
+        t10 =   e + (x)*(f-e);      \
+        t11 =   g + (x)*(h-g);      \
+        t0  = t00 + (y)*(t01-t00);  \
+        t1  = t10 + (y)*(t11-t10);  \
+        v   =  t0 + (z)*(t1-t0);
+
+
+#define vtkVRCMultiplyPointMacro( A, B, M ) \
+  B[0] = A[0]*M[0]  + A[1]*M[1]  + A[2]*M[2]  + M[3]; \
+  B[1] = A[0]*M[4]  + A[1]*M[5]  + A[2]*M[6]  + M[7]; \
+  B[2] = A[0]*M[8]  + A[1]*M[9]  + A[2]*M[10] + M[11]; \
+  B[3] = A[0]*M[12] + A[1]*M[13] + A[2]*M[14] + M[15]; \
+  if ( B[3] != 1.0 ) { B[0] /= B[3]; B[1] /= B[3]; B[2] /= B[3]; }
+
+#define vtkVRCMultiplyViewPointMacro( A, B, M ) \
+  B[0] = A[0]*M[0]  + A[1]*M[1]  + A[2]*M[2]  + M[3]; \
+  B[1] = A[0]*M[4]  + A[1]*M[5]  + A[2]*M[6]  + M[7]; \
+  B[3] = A[0]*M[12] + A[1]*M[13] + A[2]*M[14] + M[15]; \
+  if ( B[3] != 1.0 ) { B[0] /= B[3]; B[1] /= B[3]; }
+
+#define vtkVRCMultiplyNormalMacro( A, B, M ) \
+  B[0] = A[0]*M[0]  + A[1]*M[4]  + A[2]*M[8]; \
+  B[1] = A[0]*M[1]  + A[1]*M[5]  + A[2]*M[9]; \
+  B[2] = A[0]*M[2]  + A[1]*M[6]  + A[2]*M[10]
+
+template <class T>
+void vtkCropVolumeRayCastMapperFillInMinMaxVolume( T *dataPtr, unsigned short *minMaxVolume,
+                                                         int fullDim[3], int smallDim[4],
+                                                         int independent, int components,
+                                                         float *shift, float *scale )
+{
+  int i, j, k, c;
+  int sx1, sx2, sy1, sy2, sz1, sz2;
+  int x, y, z;
+
+  T *dptr = dataPtr;
+
+  for ( k = 0; k < fullDim[2]; k++ )
+    {
+    sz1 = (k < 1)?(0):(static_cast<int>((k-1)/4));
+    sz2 =              static_cast<int>((k  )/4);
+    sz2 = ( k == fullDim[2]-1 )?(sz1):(sz2);
+    for ( j = 0; j < fullDim[1]; j++ )
+      {
+      sy1 = (j < 1)?(0):(static_cast<int>((j-1)/4));
+      sy2 =              static_cast<int>((j  )/4);
+      sy2 = ( j == fullDim[1]-1 )?(sy1):(sy2);
+      for ( i = 0; i < fullDim[0]; i++ )
+        {
+        sx1 = (i < 1)?(0):(static_cast<int>((i-1)/4));
+        sx2 =              static_cast<int>((i  )/4);
+        sx2 = ( i == fullDim[0]-1 )?(sx1):(sx2);
+
+        for ( c = 0; c < smallDim[3]; c++ )
+          {
+          unsigned short val;
+          if ( independent )
+            {
+            val = static_cast<unsigned short>((*dptr + shift[c]) * scale[c]);
+            dptr++;
+            }
+          else
+            {
+            val = static_cast<unsigned short>((*(dptr+components-1) +
+                   shift[components-1]) * scale[components-1]);
+            dptr += components;
+            }
+
+          for ( z = sz1; z <= sz2; z++ )
+            {
+            for ( y = sy1; y <= sy2; y++ )
+              {
+              for ( x = sx1; x <= sx2; x++ )
+                {
+                unsigned short *tmpPtr = minMaxVolume +
+                  3*( z*smallDim[0]*smallDim[1]*smallDim[3] +
+                      y*smallDim[0]*smallDim[3] +
+                      x*smallDim[3] + c);
+
+                tmpPtr[0] = (val<tmpPtr[0])?(val):(tmpPtr[0]);
+                tmpPtr[1] = (val>tmpPtr[1])?(val):(tmpPtr[1]);
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+}
+
+template <class T>
+void vtkCropVolumeRayCastMapperComputeCS1CGradients( T *dataPtr,
+                                                           int dim[3],
+                                                           double spacing[3],
+                                                           double scalarRange[2],
+                                                           unsigned short **gradientNormal,
+                                                           unsigned char  **gradientMagnitude,
+                                                           vtkDirectionEncoder *directionEncoder,
+                                                           int thread_id, int thread_count,
+                                                           vtkCropVolumeRayCastMapper *me )
+{
+  int                 x, y, z;
+  int                 x_start, x_limit;
+  int                 y_start, y_limit;
+  int                 z_start, z_limit;
+  T                   *dptr;
+  float               n[3], t;
+  float               gvalue=0;
+  int                 xlow, xhigh;
+  double              aspect[3];
+  float               scale;
+  unsigned short      *dirPtr;
+  unsigned char       *magPtr;
+
+
+  me->InvokeEvent( vtkCommand::VolumeMapperComputeGradientsStartEvent, NULL );
+
+  double avgSpacing = (spacing[0]+spacing[1]+spacing[2])/3.0;
+
+  // adjust the aspect
+  aspect[0] = spacing[0] * 2.0 / avgSpacing;
+  aspect[1] = spacing[1] * 2.0 / avgSpacing;
+  aspect[2] = spacing[2] * 2.0 / avgSpacing;
+
+  if ( scalarRange[1] - scalarRange[0] )
+    {
+    scale = 255.0 / (0.25*(scalarRange[1] - scalarRange[0]));
+    }
+  else
+    {
+    scale = 1.0;
+    }
+
+  x_start = 0;
+  x_limit = dim[0];
+  y_start = 0;
+  y_limit = dim[1];
+  z_start = (int)(( (float)thread_id / (float)thread_count ) *
+                  dim[2] );
+  z_limit = (int)(( (float)(thread_id + 1) / (float)thread_count ) *
+                  dim[2] );
+
+  // Do final error checking on limits - make sure they are all within bounds
+  // of the scalar input
+
+  x_start = (x_start<0)?(0):(x_start);
+  y_start = (y_start<0)?(0):(y_start);
+  z_start = (z_start<0)?(0):(z_start);
+
+  x_limit = (x_limit>dim[0])?(dim[0]):(x_limit);
+  y_limit = (y_limit>dim[1])?(dim[1]):(y_limit);
+  z_limit = (z_limit>dim[2])?(dim[2]):(z_limit);
+
+
+  int *dxBuffer = new int[dim[0]];
+  int *dyBuffer = new int[dim[0]];
+  int *dzBuffer = new int[dim[0]];
+
+  for ( z = z_start; z < z_limit; z++ )
+    {
+    unsigned short *gradientDirPtr = gradientNormal[z];
+    unsigned char *gradientMagPtr = gradientMagnitude[z];
+
+    for ( y = y_start; y < y_limit; y++ )
+      {
+      xlow = x_start;
+      xhigh = x_limit;
+
+      dirPtr  = gradientDirPtr + y * dim[0] + xlow;
+      magPtr  = gradientMagPtr + y * dim[0] + xlow;
+
+      // Working on dx - that is this row
+      dptr = dataPtr + z * dim[0] * dim[1] + y * dim[0] + xlow;
+      // add this into our dxBuffer
+      dxBuffer[0] = *dptr;
+      for ( x = xlow+1; x < xhigh; x++ )
+        {
+        *(dxBuffer+x) = *(dptr+x-1);
+        }
+
+      // subtract this from our dxBuffer
+      for ( x = xlow; x < xhigh-1; x++ )
+        {
+        *(dxBuffer+x) -= *(dptr+x+1);
+        }
+      dxBuffer[xhigh-1] -= dptr[xhigh-1];
+
+      // working on dy - need the row before and the row after.
+      // first, the row before, or this row if we are at the edge
+      if ( y > 0 )
+        {
+        dptr = dataPtr + z * dim[0] * dim[1] + (y-1) * dim[0] + xlow;
+        }
+      else
+        {
+        dptr = dataPtr + z * dim[0] * dim[1] + y * dim[0] + xlow;
+        }
+      // add this into our dyBuffer
+      for ( x = xlow; x < xhigh; x++ )
+        {
+        dyBuffer[x] = dptr[x];
+        }
+
+      // now the row after
+      if ( y < y_limit-1 )
+        {
+        dptr = dataPtr + z * dim[0] * dim[1] + (y+1) * dim[0] + xlow;
+        }
+      else
+        {
+        dptr = dataPtr + z * dim[0] * dim[1] + y * dim[0] + xlow;
+        }
+      // subtract this from our dyBuffer
+      for ( x = xlow; x < xhigh; x++ )
+        {
+        dyBuffer[x] -= dptr[x];
+        }
+
+      // Find the pointer for the slice before - use this if there is
+      // no slice before
+      if ( z > 0 )
+        {
+        dptr = dataPtr + (z-1) * dim[0] * dim[1] + y * dim[0] + xlow;
+        }
+      else
+        {
+        dptr = dataPtr + z * dim[0] * dim[1] + y * dim[0] + xlow;
+        }
+
+      // add this into our dzBuffer
+      for ( x = xlow; x < xhigh; x++ )
+        {
+        dzBuffer[x] = dptr[x];
+        }
+
+      // Find the pointer for the slice after - use this if there is
+      // no slice after
+      if ( z < z_limit-1 )
+        {
+        dptr = dataPtr + (z+1) * dim[0] * dim[1] + y * dim[0] + xlow;
+        }
+      else
+        {
+        dptr = dataPtr + z * dim[0] * dim[1] + y * dim[0] + xlow;
+        }
+
+      // add this into our dzBuffer
+      for ( x = xlow; x < xhigh; x++ )
+        {
+        dzBuffer[x] -= dptr[x];
+        }
+
+      // now one more loop to generate the normals
+      for ( x = xlow; x < xhigh; x++ )
+        {
+        n[0] = dxBuffer[x];
+        n[1] = dyBuffer[x];
+        n[2] = dzBuffer[x];
+
+        // Take care of the aspect ratio of the data
+        // Scaling in the vtkVolume is isotropic, so this is the
+        // only place we have to worry about non-isotropic scaling.
+        n[0] /= aspect[0];
+        n[1] /= aspect[1];
+        n[2] /= aspect[2];
+
+        // Compute the gradient magnitude
+        t = sqrt( (double)( n[0]*n[0] +
+                            n[1]*n[1] +
+                            n[2]*n[2] ) );
+
+
+        // Encode this into an 8 bit value
+        gvalue = t * scale;
+
+        gvalue = (gvalue<0.0)?(0.0):(gvalue);
+        gvalue = (gvalue>255.0)?(255.0):(gvalue);
+
+        // Normalize the gradient direction
+        if ( t > 0.0 )
+          {
+          n[0] /= t;
+          n[1] /= t;
+          n[2] /= t;
+          }
+        else
+          {
+          n[0] = n[1] = n[2] = 0.0;
+          }
+
+        *(magPtr++) = static_cast<unsigned char>(gvalue + 0.5);
+        *(dirPtr++) = directionEncoder->GetEncodedDirection( n );
+        }
+      }
+
+    if ( z%8 == 7 && thread_id == 0)
+      {
+      double args[1];
+      args[0] =
+        static_cast<float>(z - z_start) /
+        static_cast<float>(z_limit - z_start - 1);
+      me->InvokeEvent( vtkCommand::VolumeMapperComputeGradientsProgressEvent, args );
+      }
+    }
+
+  delete[] dxBuffer;
+  delete[] dyBuffer;
+  delete[] dzBuffer;
+
+  me->InvokeEvent( vtkCommand::VolumeMapperComputeGradientsEndEvent, NULL );
+}
+
+VTK_THREAD_RETURN_TYPE vtkCropFPVRCMSwitchOnDataType( void *arg )
+{
+  vtkCropVolumeRayCastMapper   *mapper;
+  int                                 thread_count;
+  int                                 thread_id;
+
+  thread_id = ((vtkMultiThreader::ThreadInfo *)(arg))->ThreadID;
+  thread_count = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads;
+  mapper = (vtkCropVolumeRayCastMapper *)
+    (((vtkMultiThreader::ThreadInfo *)(arg))->UserData);
+
+  vtkImageData *input = mapper->GetInput();
+
+  void *dataPtr = mapper->GetCurrentScalars()->GetVoidPointer(0);
+  int scalarType   = mapper->GetCurrentScalars()->GetDataType();
+
+  int dim[3];
+  double spacing[3];
+  input->GetDimensions(dim);
+  input->GetSpacing(spacing);
+
+  // Find the scalar range
+  double scalarRange[2];
+  mapper->GetCurrentScalars()->GetRange(scalarRange, 0);
+
+  if ( scalarType == VTK_UNSIGNED_CHAR )
+    {
+    vtkCropVolumeRayCastMapperComputeCS1CGradients(
+      (unsigned char *)(dataPtr), dim, spacing, scalarRange,
+      mapper->GradientNormal,
+      mapper->GradientMagnitude,
+      mapper->DirectionEncoder,
+      thread_id, thread_count,
+      mapper);
+    }
+  else if ( scalarType == VTK_UNSIGNED_SHORT )
+    {
+    vtkCropVolumeRayCastMapperComputeCS1CGradients(
+      (unsigned short *)(dataPtr), dim, spacing, scalarRange,
+      mapper->GradientNormal,
+      mapper->GradientMagnitude,
+      mapper->DirectionEncoder,
+      thread_id, thread_count,
+      mapper);
+    }
+  else if ( scalarType == VTK_CHAR )
+    {
+    vtkCropVolumeRayCastMapperComputeCS1CGradients(
+      (char *)(dataPtr), dim, spacing, scalarRange,
+      mapper->GradientNormal,
+      mapper->GradientMagnitude,
+      mapper->DirectionEncoder,
+      thread_id, thread_count,
+      mapper);
+    }
+  else if ( scalarType == VTK_SHORT )
+    {
+    vtkCropVolumeRayCastMapperComputeCS1CGradients(
+      (short *)(dataPtr), dim, spacing, scalarRange,
+      mapper->GradientNormal,
+      mapper->GradientMagnitude,
+      mapper->DirectionEncoder,
+      thread_id, thread_count,
+      mapper);
+    }
+
+  return VTK_THREAD_RETURN_VALUE;
+}
+
+
+template <class T>
+void vtkCropVolumeRayCastMapperComputeGradients( T *dataPtr,
+                                                       int dim[3],
+                                                       double spacing[3],
+                                                       int components,
+                                                       int independent,
+                                                       double scalarRange[4][2],
+                                                       unsigned short **gradientNormal,
+                                                       unsigned char  **gradientMagnitude,
+                                                       vtkDirectionEncoder *directionEncoder,
+                                                       vtkCropVolumeRayCastMapper *me )
+{
+  int                 x, y, z, c;
+  int                 x_start, x_limit;
+  int                 y_start, y_limit;
+  int                 z_start, z_limit;
+  T                   *dptr, *cdptr;
+  float               n[3], t;
+  float               gvalue=0;
+  int                 xlow, xhigh;
+  double              aspect[3];
+  int                 xstep, ystep, zstep;
+  float               scale[4];
+  unsigned short      *dirPtr, *cdirPtr;
+  unsigned char       *magPtr, *cmagPtr;
+
+
+  me->InvokeEvent( vtkCommand::VolumeMapperComputeGradientsStartEvent, NULL );
+
+  double avgSpacing = (spacing[0]+spacing[1]+spacing[2])/3.0;
+
+  // adjust the aspect
+  aspect[0] = spacing[0] * 2.0 / avgSpacing;
+  aspect[1] = spacing[1] * 2.0 / avgSpacing;
+  aspect[2] = spacing[2] * 2.0 / avgSpacing;
+
+  // Compute steps through the volume in x, y, and z
+  xstep = components;
+  ystep = components*dim[0];
+  zstep = components*dim[0] * dim[1];
+
+  if ( !independent )
+    {
+    if ( scalarRange[components-1][1] - scalarRange[components-1][0] )
+      {
+      scale[0] = 255.0 / (0.25*(scalarRange[components-1][1] - scalarRange[components-1][0]));
+      }
+    else
+      {
+      scale[0] = 0.0;
+      }
+    }
+  else
+    {
+    for (c = 0; c < components; c++ )
+      {
+      if ( scalarRange[c][1] - scalarRange[c][0] )
+        {
+        scale[c] = 255.0 / (0.25*(scalarRange[c][1] - scalarRange[c][0]));
+        }
+      else
+        {
+        scale[c] = 1.0;
+        }
+      }
+    }
+  int thread_id = 0;
+  int thread_count = 1;
+
+  x_start = 0;
+  x_limit = dim[0];
+  y_start = 0;
+  y_limit = dim[1];
+  z_start = (int)(( (float)thread_id / (float)thread_count ) *
+                  dim[2] );
+  z_limit = (int)(( (float)(thread_id + 1) / (float)thread_count ) *
+                  dim[2] );
+
+  // Do final error checking on limits - make sure they are all within bounds
+  // of the scalar input
+
+  x_start = (x_start<0)?(0):(x_start);
+  y_start = (y_start<0)?(0):(y_start);
+  z_start = (z_start<0)?(0):(z_start);
+
+  x_limit = (x_limit>dim[0])?(dim[0]):(x_limit);
+  y_limit = (y_limit>dim[1])?(dim[1]):(y_limit);
+  z_limit = (z_limit>dim[2])?(dim[2]):(z_limit);
+
+
+  int increment = (independent)?(components):(1);
+
+  float tolerance[4];
+  for ( c = 0; c < components; c++ )
+    {
+    tolerance[c] = .00001 * (scalarRange[c][1] - scalarRange[c][0]);
+    }
+
+  // Loop through all the data and compute the encoded normal and
+  // gradient magnitude for each scalar location
+  for ( z = z_start; z < z_limit; z++ )
+    {
+    unsigned short *gradientDirPtr = gradientNormal[z];
+    unsigned char *gradientMagPtr = gradientMagnitude[z];
+
+    for ( y = y_start; y < y_limit; y++ )
+      {
+      xlow = x_start;
+      xhigh = x_limit;
+
+      dptr = dataPtr + components*(z * dim[0] * dim[1] + y * dim[0] + xlow);
+
+      dirPtr  = gradientDirPtr    + (y * dim[0] + xlow)*increment;
+      magPtr  = gradientMagPtr    + (y * dim[0] + xlow)*increment;
+
+      for ( x = xlow; x < xhigh; x++ )
+        {
+        for ( c = 0; ( independent && c < components ) || c == 0; c++ )
+          {
+          cdptr   = dptr   + ((independent)?(c):(components-1));
+          cdirPtr = dirPtr + ((independent)?(c):(0));
+          cmagPtr = magPtr + ((independent)?(c):(0));
+
+          // Allow up to 3 tries to find the gadient - looking out at a distance of
+          // 1, 2, and 3 units.
+          int foundGradient = 0;
+          for ( int d = 1; d <= 3 && !foundGradient; d++ )
+            {
+            // Use a central difference method if possible,
+            // otherwise use a forward or backward difference if
+            // we are on the edge
+            // Compute the X component
+            if ( x < d )
+              {
+              n[0] = 2.0*((float)*(cdptr) - (float)*(cdptr+d*xstep));
+              }
+            else if ( x >= dim[0] - d )
+              {
+              n[0] = 2.0*((float)*(cdptr-d*xstep) - (float)*(cdptr));
+              }
+            else
+              {
+            n[0] = (float)*(cdptr-d*xstep) - (float)*(cdptr+d*xstep);
+              }
+
+            // Compute the Y component
+            if ( y < d )
+              {
+              n[1] = 2.0*((float)*(cdptr) - (float)*(cdptr+d*ystep));
+              }
+            else if ( y >= dim[1] - d )
+              {
+              n[1] = 2.0*((float)*(cdptr-d*ystep) - (float)*(cdptr));
+              }
+            else
+              {
+              n[1] = (float)*(cdptr-d*ystep) - (float)*(cdptr+d*ystep);
+              }
+
+            // Compute the Z component
+            if ( z < d )
+              {
+              n[2] = 2.0*((float)*(cdptr) - (float)*(cdptr+d*zstep));
+              }
+            else if ( z >= dim[2] - d )
+              {
+              n[2] = 2.0*((float)*(cdptr-d*zstep) - (float)*(cdptr));
+              }
+            else
+              {
+              n[2] = (float)*(cdptr-d*zstep) - (float)*(cdptr+d*zstep);
+              }
+
+            // Take care of the aspect ratio of the data
+            // Scaling in the vtkVolume is isotropic, so this is the
+            // only place we have to worry about non-isotropic scaling.
+            n[0] /= d*aspect[0];
+            n[1] /= d*aspect[1];
+            n[2] /= d*aspect[2];
+
+            // Compute the gradient magnitude
+            t = sqrt( (double)( n[0]*n[0] +
+                                n[1]*n[1] +
+                                n[2]*n[2] ) );
+
+
+            // Encode this into an 8 bit value
+            gvalue = t * scale[c];
+
+            if ( d > 1 )
+              {
+              gvalue = 0;
+              }
+
+            gvalue = (gvalue<0.0)?(0.0):(gvalue);
+            gvalue = (gvalue>255.0)?(255.0):(gvalue);
+
+            // Normalize the gradient direction
+            if ( t > tolerance[c] )
+              {
+              n[0] /= t;
+              n[1] /= t;
+              n[2] /= t;
+              foundGradient = 1;
+              }
+            else
+              {
+              n[0] = n[1] = n[2] = 0.0;
+            }
+          }
+
+
+          *cmagPtr = static_cast<unsigned char>(gvalue + 0.5);
+          *cdirPtr = directionEncoder->GetEncodedDirection( n );
+          }
+
+        dptr    +=   components;
+        dirPtr  +=   increment;
+        magPtr  +=   increment;
+        }
+      }
+    if ( z%8 == 7 )
+      {
+      double args[1];
+      args[0] =
+        static_cast<float>(z - z_start) /
+        static_cast<float>(z_limit - z_start - 1);
+      me->InvokeEvent( vtkCommand::VolumeMapperComputeGradientsProgressEvent, args );
+      }
+    }
+
+  me->InvokeEvent( vtkCommand::VolumeMapperComputeGradientsEndEvent, NULL );
+}
+
+// Construct a new vtkCropVolumeRayCastMapper with default values
+vtkCropVolumeRayCastMapper::vtkCropVolumeRayCastMapper()
+{
+  this->SampleDistance                   =  1.0;
+  this->InteractiveSampleDistance        =  2.0;
+  this->ImageSampleDistance              =  1.0;
+  this->MinimumImageSampleDistance       =  1.0;
+  this->MaximumImageSampleDistance       = 10.0;
+  this->AutoAdjustSampleDistances        =  1;
+  this->LockSampleDistanceToInputSpacing =  0;
+
+  // Should never be used without initialization, but
+  // set here to avoid compiler warnings
+  this->OldSampleDistance          =  1.0;
+  this->OldImageSampleDistance     =  1.0;
+
+  this->PerspectiveMatrix      = vtkMatrix4x4::New();
+  this->ViewToWorldMatrix      = vtkMatrix4x4::New();
+  this->ViewToVoxelsMatrix     = vtkMatrix4x4::New();
+  this->VoxelsToViewMatrix     = vtkMatrix4x4::New();
+  this->WorldToVoxelsMatrix    = vtkMatrix4x4::New();
+  this->VoxelsToWorldMatrix    = vtkMatrix4x4::New();
+
+  this->VolumeMatrix           = vtkMatrix4x4::New();
+
+  this->PerspectiveTransform   = vtkTransform::New();
+  this->VoxelsTransform        = vtkTransform::New();
+  this->VoxelsToViewTransform  = vtkTransform::New();
+
+  this->Threader               = vtkMultiThreader::New();
+
+  this->RayCastImage           = vtkFixedPointRayCastImage::New();
+
+  this->RowBounds              = NULL;
+  this->OldRowBounds           = NULL;
+
+  this->RenderTimeTable        = NULL;
+  this->RenderVolumeTable      = NULL;
+  this->RenderRendererTable    = NULL;
+  this->RenderTableSize        = 0;
+  this->RenderTableEntries     = 0;
+
+  this->RenderWindow           = NULL;
+
+  this->MIPHelper              = vtkFixedPointVolumeRayCastMIPHelper::New();
+  this->CompositeHelper        = vtkCropVolumeRayCastCompositeHelper::New();
+  this->CompositeGOHelper      = vtkCropVolumeRayCastCompositeGOHelper::New();
+  this->CompositeShadeHelper   = vtkCropVolumeRayCastCompositeShadeHelper::New();
+  this->CompositeGOShadeHelper = vtkCropVolumeRayCastCompositeGOShadeHelper::New();
+
+  this->IntermixIntersectingGeometry = 1;
+
+  int i;
+  for ( i = 0; i < 4; i++ )
+    {
+    this->SavedRGBFunction[i]             = NULL;
+    this->SavedGrayFunction[i]            = NULL;
+    this->SavedScalarOpacityFunction[i]   = NULL;
+    this->SavedGradientOpacityFunction[i] = NULL;
+    this->SavedColorChannels[i]           = 0;
+    this->SavedScalarOpacityDistance[i]   = 0;
+    }
+
+  this->SavedSampleDistance          = 0;
+  this->SavedBlendMode               = -1;
+
+  this->SavedGradientsInput          = NULL;
+  this->SavedParametersInput         = NULL;
+
+  this->NumberOfGradientSlices       = 0;
+  this->GradientNormal               = NULL;
+  this->GradientMagnitude            = NULL;
+  this->ContiguousGradientNormal     = NULL;
+  this->ContiguousGradientMagnitude  = NULL;
+
+  this->DirectionEncoder             = vtkSphericalDirectionEncoder::New();
+  this->GradientShader               = vtkEncodedGradientShader::New();
+  this->GradientEstimator            = vtkFiniteDifferenceGradientEstimator::New();
+
+  this->GradientEstimator->SetDirectionEncoder( this->DirectionEncoder );
+
+  this->ShadingRequired              = 0;
+  this->GradientOpacityRequired      = 0;
+
+  this->CroppingRegionMask[0] = 1;
+  for ( i = 1; i < 27; i++ )
+    {
+    this->CroppingRegionMask[i] = this->CroppingRegionMask[i-1]*2;
+    }
+
+  this->NumTransformedClippingPlanes = 0;
+  this->TransformedClippingPlanes    = NULL;
+
+  // Which scalar field are we rendering this time, and which
+  // did we render last time (so we can check if it is changing)
+  this->CurrentScalars = NULL;
+  this->PreviousScalars = NULL;
+
+  this->ImageDisplayHelper  = vtkRayCastImageDisplayHelper::New();
+  this->ImageDisplayHelper->PreMultipliedColorsOn();
+  this->ImageDisplayHelper->SetPixelScale( 2.0 );
+
+  // This is the min max volume used for space leaping. Each 4x4x4 cell from
+  // the original input volume has three values per component - a minimum scalar
+  // index, maximum scalar index, and a values used for both the maximum gradient
+  // magnitude and a flag. The flag is used to indicate for the
+  // current transfer function whether any non-zero opacity exists between the
+  // minimum and maximum scalar values and up to the maximum gradient magnitude
+  this->MinMaxVolume = NULL;
+  this->MinMaxVolumeSize[0] = 0;
+  this->MinMaxVolumeSize[1] = 0;
+  this->MinMaxVolumeSize[2] = 0;
+  this->MinMaxVolumeSize[3] = 0;
+  this->SavedMinMaxInput = NULL;
+
+  this->Volume = NULL;
+
+  this->FinalColorWindow           = 1.0;
+  this->FinalColorLevel            = 0.5;
+
+  this->FlipMIPComparison = 0;
+  this->FixedSphereCenter[0] = this->FixedSphereCenter[1] = this->FixedSphereCenter[2] = 0.0;
+  this->FixedSphereRadius = 100.0;
+  this->FixedCubeLength[0] = this->FixedCubeLength[1] = this->FixedCubeLength[2] = 10.0;
+  this->FixedCylinderHeight = 20.0; 
+  this->FixedCylinderRadius = 30.0; 
+  this->FixedEllipseRadius[0] = this->FixedEllipseRadius[2] = 50.0;
+  this->FixedEllipseRadius[1] = 100.0;
+  this->FunctionalCropOn = 0; 
+
+}
+
+// Destruct a vtkCropVolumeRayCastMapper - clean up any memory used
+vtkCropVolumeRayCastMapper::~vtkCropVolumeRayCastMapper()
+{
+  this->PerspectiveMatrix->Delete();
+  this->ViewToWorldMatrix->Delete();
+  this->ViewToVoxelsMatrix->Delete();
+  this->VoxelsToViewMatrix->Delete();
+  this->WorldToVoxelsMatrix->Delete();
+  this->VoxelsToWorldMatrix->Delete();
+
+  this->VolumeMatrix->Delete();
+
+  this->VoxelsTransform->Delete();
+  this->VoxelsToViewTransform->Delete();
+  this->PerspectiveTransform->Delete();
+
+  this->Threader->Delete();
+
+  this->MIPHelper->Delete();
+  this->CompositeHelper->Delete();
+  this->CompositeGOHelper->Delete();
+  this->CompositeShadeHelper->Delete();
+  this->CompositeGOShadeHelper->Delete();
+
+  if ( this->RayCastImage )
+    {
+    this->RayCastImage->Delete();
+    this->RayCastImage = NULL;
+    }
+
+  delete [] this->RenderTimeTable;
+  delete [] this->RenderVolumeTable;
+  delete [] this->RenderRendererTable;
+
+  delete [] this->RowBounds;
+  delete [] this->OldRowBounds;
+
+  int i;
+  if ( this->GradientNormal )
+    {
+    // Contiguous? Delete in one chunk otherwise delete slice by slice
+    if ( this->ContiguousGradientNormal )
+      {
+      delete [] this->ContiguousGradientNormal;
+      this->ContiguousGradientNormal = NULL;
+      }
+    else
+      {
+      for ( i = 0; i < this->NumberOfGradientSlices; i++ )
+        {
+        delete [] this->GradientNormal[i];
+        }
+      }
+    delete [] this->GradientNormal;
+    this->GradientNormal = NULL;
+    }
+
+  if ( this->GradientMagnitude )
+    {
+    // Contiguous? Delete in one chunk otherwise delete slice by slice
+    if ( this->ContiguousGradientMagnitude )
+      {
+      delete [] this->ContiguousGradientMagnitude;
+      this->ContiguousGradientMagnitude = NULL;
+      }
+    else
+      {
+      for ( i = 0; i < this->NumberOfGradientSlices; i++ )
+        {
+        delete [] this->GradientMagnitude[i];
+        }
+      }
+    delete [] this->GradientMagnitude;
+    this->GradientMagnitude = NULL;
+    }
+
+  this->DirectionEncoder->Delete();
+  this->GradientShader->Delete();
+  this->GradientEstimator->Delete();
+
+  delete [] this->TransformedClippingPlanes;
+
+  this->ImageDisplayHelper->Delete();
+
+  // Delete storage used by min/max volume
+  delete [] this->MinMaxVolume;
+}
+
+float vtkCropVolumeRayCastMapper::ComputeRequiredImageSampleDistance( float desiredTime,
+                                                                            vtkRenderer *ren )
+{
+  return this->ComputeRequiredImageSampleDistance( desiredTime, ren, NULL );
+}
+
+float vtkCropVolumeRayCastMapper::ComputeRequiredImageSampleDistance( float desiredTime,
+                                                                            vtkRenderer *ren,
+                                                                            vtkVolume *vol )
+{
+  float result;
+
+  float oldTime;
+
+  if ( vol )
+    {
+    oldTime = this->RetrieveRenderTime( ren, vol );
+    }
+  else
+    {
+    oldTime = this->RetrieveRenderTime( ren );
+    }
+
+  float newTime = desiredTime;
+
+  if ( oldTime == 0.0 )
+    {
+    if ( newTime > 10 )
+      {
+      result = this->MinimumImageSampleDistance;
+      }
+    else
+      {
+      result = this->MaximumImageSampleDistance / 2.0;
+      }
+    }
+  else
+    {
+    oldTime /= (this->ImageSampleDistance * this->ImageSampleDistance);
+    result = this->ImageSampleDistance * sqrt(oldTime / newTime);
+    result = (result > this->MaximumImageSampleDistance)?
+      (this->MaximumImageSampleDistance):(result);
+    result =
+      (result<this->MinimumImageSampleDistance)?
+      (this->MinimumImageSampleDistance):(result);
+    }
+
+  return result;
+}
+
+float vtkCropVolumeRayCastMapper::RetrieveRenderTime( vtkRenderer *ren,
+                                                            vtkVolume   *vol )
+{
+  int i;
+
+  for ( i = 0; i < this->RenderTableEntries; i++ )
+    {
+    if ( this->RenderVolumeTable[i] == vol &&
+         this->RenderRendererTable[i] == ren )
+      {
+      return this->RenderTimeTable[i];
+      }
+    }
+
+  return 0.0;
+}
+
+float vtkCropVolumeRayCastMapper::RetrieveRenderTime( vtkRenderer *ren )
+{
+  int i;
+
+  for ( i = 0; i < this->RenderTableEntries; i++ )
+    {
+    if ( this->RenderRendererTable[i] == ren )
+      {
+      return this->RenderTimeTable[i];
+      }
+    }
+
+  return 0.0;
+}
+
+void vtkCropVolumeRayCastMapper::StoreRenderTime( vtkRenderer *ren,
+                                                        vtkVolume   *vol,
+                                                        float       time )
+{
+  int i;
+  for ( i = 0; i < this->RenderTableEntries; i++ )
+    {
+    if ( this->RenderVolumeTable[i] == vol &&
+         this->RenderRendererTable[i] == ren )
+      {
+      this->RenderTimeTable[i] = time;
+      return;
+      }
+    }
+
+
+  // Need to increase size
+  if ( this->RenderTableEntries >= this->RenderTableSize )
+    {
+    if ( this->RenderTableSize == 0 )
+      {
+      this->RenderTableSize = 10;
+      }
+    else
+      {
+      this->RenderTableSize *= 2;
+      }
+
+    float        *oldTimePtr     = this->RenderTimeTable;
+    vtkVolume   **oldVolumePtr   = this->RenderVolumeTable;
+    vtkRenderer **oldRendererPtr = this->RenderRendererTable;
+
+    this->RenderTimeTable     = new float [this->RenderTableSize];
+    this->RenderVolumeTable   = new vtkVolume *[this->RenderTableSize];
+    this->RenderRendererTable = new vtkRenderer *[this->RenderTableSize];
+
+    for (i = 0; i < this->RenderTableEntries; i++ )
+      {
+      this->RenderTimeTable[i] = oldTimePtr[i];
+      this->RenderVolumeTable[i] = oldVolumePtr[i];
+      this->RenderRendererTable[i] = oldRendererPtr[i];
+      }
+
+    delete [] oldTimePtr;
+    delete [] oldVolumePtr;
+    delete [] oldRendererPtr;
+    }
+
+  this->RenderTimeTable[this->RenderTableEntries] = time;
+  this->RenderVolumeTable[this->RenderTableEntries] = vol;
+  this->RenderRendererTable[this->RenderTableEntries] = ren;
+
+  this->RenderTableEntries++;
+}
+
+void vtkCropVolumeRayCastMapper::SetNumberOfThreads( int num )
+{
+  this->Threader->SetNumberOfThreads( num );
+}
+
+int vtkCropVolumeRayCastMapper::GetNumberOfThreads()
+{
+  if (this->Threader)
+    {
+    return this->Threader->GetNumberOfThreads();
+    }
+  return 0;
+}
+
+void vtkCropVolumeRayCastMapper::FillInMaxGradientMagnitudes( int fullDim[3],
+                                                                    int smallDim[4] )
+{
+  int i, j, k, c;
+  int sx1, sx2, sy1, sy2, sz1, sz2;
+  int x, y, z;
+
+
+  for ( k = 0; k < fullDim[2]; k++ )
+    {
+    sz1 = (k < 1)?(0):(static_cast<int>((k-1)/4));
+    sz2 =              static_cast<int>((k  )/4);
+    sz2 = ( k == fullDim[2]-1 )?(sz1):(sz2);
+
+    unsigned char *dptr = this->GradientMagnitude[k];
+
+    for ( j = 0; j < fullDim[1]; j++ )
+      {
+      sy1 = (j < 1)?(0):(static_cast<int>((j-1)/4));
+      sy2 =              static_cast<int>((j  )/4);
+      sy2 = ( j == fullDim[1]-1 )?(sy1):(sy2);
+
+      for ( i = 0; i < fullDim[0]; i++ )
+        {
+        sx1 = (i < 1)?(0):(static_cast<int>((i-1)/4));
+        sx2 =              static_cast<int>((i  )/4);
+        sx2 = ( i == fullDim[0]-1 )?(sx1):(sx2);
+
+        for ( c = 0; c < smallDim[3]; c++ )
+          {
+          unsigned char val;
+          val = *dptr;
+          dptr++;
+
+          for ( z = sz1; z <= sz2; z++ )
+            {
+            for ( y = sy1; y <= sy2; y++ )
+              {
+              for ( x = sx1; x <= sx2; x++ )
+                {
+                unsigned short *tmpPtr = this->MinMaxVolume +
+                  3*( z*smallDim[0]*smallDim[1]*smallDim[3] +
+                      y*smallDim[0]*smallDim[3] +
+                      x*smallDim[3] + c);
+
+                // Need to keep track of max gradient magnitude in upper
+                // eight bits. No need to preserve lower eight (the flag)
+                // since we will be recomputing this.
+                tmpPtr[2] = (val>(tmpPtr[2]>>8))?(val<<8):(tmpPtr[2]);
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+}
+
+// This method should be called after UpdateColorTables since it
+// relies on some information (shift and scale) computed in that method,
+// as well as the last built time for the color tables.
+void vtkCropVolumeRayCastMapper::UpdateMinMaxVolume( vtkVolume *vol )
+{
+  int i, j, k, c;
+
+  // A three bit variable:
+  //   first bit indicates need to update flags
+  //   second bit indicates need to update scalars
+  //   third bit indicates need to update gradient magnitudes
+  int needToUpdate = 0;
+
+  // Get the image data
+  vtkImageData *input = this->GetInput();
+
+  // We'll need this info later
+  int components   = this->CurrentScalars->GetNumberOfComponents();
+  int independent  = vol->GetProperty()->GetIndependentComponents();
+  int dim[3];
+  input->GetDimensions( dim );
+
+  // Has the data itself changed?
+  if ( input != this->SavedMinMaxInput ||
+       input->GetMTime() > this->SavedMinMaxBuildTime.GetMTime() ||
+       this->CurrentScalars != this->PreviousScalars )
+    {
+    needToUpdate |= 0x03;
+    }
+
+  // Do the gradient magnitudes need to be filled in?
+  if ( this->GradientOpacityRequired &&
+       ( needToUpdate&0x02 ||
+         this->SavedGradientsMTime.GetMTime() >
+         this->SavedMinMaxBuildTime.GetMTime() ) )
+    {
+    needToUpdate |= 0x05;
+    }
+
+  // Have the parameters changed which means the flags need
+  // to be recomputed. Actually, we could be checking just
+  // a subset of these parameters (we don't need to recompute
+  // the flags if the colors change, but unless these seems
+  // like a significant performance problem, I'd rather not
+  // complicate the code)
+  if ( !(needToUpdate&0x01) &&
+       this->SavedParametersMTime.GetMTime() >
+       this->SavedMinMaxFlagTime.GetMTime() )
+    {
+    needToUpdate |= 0x01;
+    }
+
+
+  if ( !needToUpdate )
+    {
+    return;
+    }
+
+  // Regenerate the min max values if necessary
+  if ( needToUpdate&0x02 )
+    {
+    // How big should the min/max volume be?
+    int targetSize[4];
+
+    for ( i = 0; i < 3; i++ )
+      {
+      // We group four cells (which require 5 samples) into one element in the min/max tree
+      targetSize[i] =
+        (dim[i] < 2) ? (1) : ( 1 + static_cast<int>((dim[i] - 2)/4));
+      }
+
+    // This fourth dimension is the number of independent components for which we
+    // need to keep track of min/max
+    targetSize[3] = (independent)?(components):(1);
+
+    if ( this->MinMaxVolumeSize[0] != targetSize[0] ||
+         this->MinMaxVolumeSize[1] != targetSize[1] ||
+         this->MinMaxVolumeSize[2] != targetSize[2] ||
+         this->MinMaxVolumeSize[3] != targetSize[3] )
+      {
+      delete [] this->MinMaxVolume;
+
+      // One entry for min, one for max, one shared by max gradient
+      // magnitude, and a flag set based on opacity transfer functions
+      this->MinMaxVolume = new unsigned short [3 * ( targetSize[0] *
+                                                     targetSize[1] *
+                                                     targetSize[2] *
+                                                     targetSize[3] ) ];
+
+      // Don't really do anything about it - but reporting this error may
+      // save some debugging time later...
+      if ( !this->MinMaxVolume )
+        {
+        vtkErrorMacro( "Problem allocating min/max volume" );
+        this->MinMaxVolumeSize[0] = 0;
+        this->MinMaxVolumeSize[1] = 0;
+        this->MinMaxVolumeSize[2] = 0;
+        this->MinMaxVolumeSize[3] = 0;
+        return;
+        }
+
+      this->MinMaxVolumeSize[0] = targetSize[0];
+      this->MinMaxVolumeSize[1] = targetSize[1];
+      this->MinMaxVolumeSize[2] = targetSize[2];
+      this->MinMaxVolumeSize[3] = targetSize[3];
+
+      // Initialize the structure
+      unsigned short *tmpPtr = this->MinMaxVolume;
+      for ( i = 0; i < targetSize[0] * targetSize[1] * targetSize[2]; i++ )
+        {
+        for ( j = 0; j < targetSize[3]; j++ )
+          {
+          *(tmpPtr++) = 0xffff;  // Min Scalar
+          *(tmpPtr++) = 0;       // Max Scalar
+          *(tmpPtr++) = 0;       // Max Gradient Magnitude and
+          }                      // Flag computed from transfer functions
+        }
+
+      // Now put the scalar data values into the structure
+      int scalarType   = this->CurrentScalars->GetDataType();
+      void *dataPtr = this->CurrentScalars->GetVoidPointer(0);
+
+      switch ( scalarType )
+        {
+        vtkTemplateMacro(
+          vtkCropVolumeRayCastMapperFillInMinMaxVolume(
+            (VTK_TT *)(dataPtr), this->MinMaxVolume, dim, targetSize,
+            independent, components, this->TableShift, this->TableScale) );
+        }
+      }
+
+    this->SavedMinMaxInput = input;
+    this->SavedMinMaxBuildTime.Modified();
+    }
+
+  if ( needToUpdate&0x04 )
+    {
+    // Now put the gradient magnitude values into the structure
+    this->FillInMaxGradientMagnitudes( dim, this->MinMaxVolumeSize );
+
+    // It is OK to use this same variable for scalars and gradient magnitudes - either
+    // we just rebuilt the min max volume from the scalars, or the MTime on the input
+    // is already less than this build time so updating it again won't matter for
+    // future checks
+    this->SavedMinMaxBuildTime.Modified();
+    }
+
+  // Update the flags now
+  unsigned short *minNonZeroScalarIndex = new unsigned short [this->MinMaxVolumeSize[3]];
+  for ( c = 0; c < this->MinMaxVolumeSize[3]; c++ )
+    {
+    for ( i = 0; i < this->TableSize[c]; i++ )
+      {
+      if ( this->ScalarOpacityTable[c][i] )
+        {
+        break;
+        }
+      }
+    minNonZeroScalarIndex[c] = i;
+    }
+
+  unsigned char *minNonZeroGradientMagnitudeIndex = new unsigned char [this->MinMaxVolumeSize[3]];
+  for ( c = 0; c < this->MinMaxVolumeSize[3]; c++ )
+    {
+    for ( i = 0; i < 256; i++ )
+      {
+      if ( this->GradientOpacityTable[c][i] )
+        {
+        break;
+        }
+      }
+    minNonZeroGradientMagnitudeIndex[c] = i;
+    }
+
+  unsigned short *tmpPtr = this->MinMaxVolume;
+  int zero = 0;
+  int nonZero = 0;
+
+  for ( k = 0; k < this->MinMaxVolumeSize[2]; k++ )
+    {
+    for ( j = 0; j < this->MinMaxVolumeSize[1]; j++ )
+      {
+      for ( i = 0; i < this->MinMaxVolumeSize[0]; i++ )
+        {
+        for ( c = 0; c < this->MinMaxVolumeSize[3]; c++ )
+          {
+          // We definite have 0 opacity because our maximum scalar value in
+          // this region is below the minimum scalar value with non-zero opacity
+          // for this component
+          if ( tmpPtr[1] < minNonZeroScalarIndex[c] )
+            {
+            tmpPtr[2] &= 0xff00;
+            zero++;
+            }
+          // We have 0 opacity because we are using gradient magnitudes and
+          // the maximum gradient magnitude in this area is below the minimum
+          // gradient magnitude with non-zero opacity for this component
+          else if ( this->GradientOpacityRequired &&
+                    (tmpPtr[2]>>8) < minNonZeroGradientMagnitudeIndex[c] )
+            {
+            tmpPtr[2] &= 0xff00;
+            zero++;
+            }
+          // We definitely have non-zero opacity because our minimum scalar
+          // value is lower than our first scalar with non-zero opacity, and
+          // the maximum scalar value is greater than this threshold - so
+          // we must encounter scalars with opacity in between
+          else if ( tmpPtr[0] < minNonZeroScalarIndex[c] )
+            {
+            tmpPtr[2] &= 0xff00;
+            tmpPtr[2] |= 0x0001;
+            nonZero++;
+            }
+          // We have to search between min scalar value and the
+          // max scalar stored in the minmax volume to look for non-zero
+          // opacity since both values must be above our first non-zero
+          // threshold so we don't have information in this area
+          else
+            {
+            int loop;
+            for ( loop = tmpPtr[0]; loop <= tmpPtr[1]; loop++ )
+              {
+              if ( this->ScalarOpacityTable[c][loop] )
+                {
+                break;
+                }
+              }
+            if ( loop <= tmpPtr[1] )
+              {
+              tmpPtr[2] &= 0xff00;
+              tmpPtr[2] |= 0x0001;
+              nonZero++;
+              }
+            else
+              {
+              tmpPtr[2] &= 0xff00;
+              zero++;
+              }
+            }
+          tmpPtr += 3;
+          }
+        }
+      }
+    }
+
+  this->SavedMinMaxFlagTime.Modified();
+
+  delete [] minNonZeroGradientMagnitudeIndex;
+  delete [] minNonZeroScalarIndex;
+}
+
+void vtkCropVolumeRayCastMapper::UpdateCroppingRegions()
+{
+  this->ConvertCroppingRegionPlanesToVoxels();
+
+  int i;
+  for ( i = 0; i < 6; i++ )
+    {
+    this->FixedPointCroppingRegionPlanes[i] =
+      this->ToFixedPointPosition( this->VoxelCroppingRegionPlanes[i] );
+    }
+
+}
+
+// This is the initialization that should be done once per image
+// The render has been broken into several parts to support AMR
+// volume rendering. Basically, this is done by having the AMR
+// mapper call the PerImageInitialization once, then the
+// PerVolumeInitialization once for each volume in the hierarchical
+// structure. Finally, the AMR mapper divides all the volumes
+// into subvolumes in order to render everything in a back-to-front
+// order. The PerSubVolumeInitialization is called for each subvolume,
+// then the RenderSubVolume is called. Finally, the DisplayImage method
+// is called to map the image onto the screen. When this class is used
+// directly as the mapper, the Render method calls these initialization
+// methods and the RenderSubVolumeMethod. The AMR mapper will set the
+// multiRender flag to 1 indicating that the PerImageInitialization
+// should fully polulate the RayCastImage class based on the
+// origin, spacing, and extent passed in. This will result in computing
+// some things twice - once for the "full" volume (the extent bounding
+// all volumes in the hierarchy), then once for each volume in the
+// hierarchy. This does not make sense when rendering just a single
+// volume so the multiRender flag indicates whether to do this
+// computation here or skip it for later.
+int vtkCropVolumeRayCastMapper::PerImageInitialization( vtkRenderer *ren,
+                                                              vtkVolume *vol,
+                                                              int multiRender,
+                                                              double inputOrigin[3],
+                                                              double inputSpacing[3],
+                                                              int    inputExtent[6] )
+{
+  // Save this so that we can restore it if the image is cancelled
+  this->OldImageSampleDistance = this->ImageSampleDistance;
+  this->OldSampleDistance      = this->SampleDistance;
+
+  // If we are automatically adjusting the size to achieve a desired frame
+  // rate, then do that adjustment here. Base the new image sample distance
+  // on the previous one and the previous render time. Don't let
+  // the adjusted image sample distance be less than the minimum image sample
+  // distance or more than the maximum image sample distance.
+  if ( this->AutoAdjustSampleDistances )
+    {
+    this->ImageSampleDistance =
+      this->ComputeRequiredImageSampleDistance( vol->GetAllocatedRenderTime(), ren, vol );
+
+    // If this is an interactive render (faster than 1 frame per second) then we'll
+    // increase the sample distance along the ray to improve performance
+    if ( vol->GetAllocatedRenderTime() < 1.0 )
+      {
+      this->SampleDistance = this->InteractiveSampleDistance;
+      }
+    }
+
+  // Pass the ImageSampleDistance on the RayCastImage
+  this->RayCastImage->SetImageSampleDistance( this->ImageSampleDistance );
+
+  // The full image fills the viewport. First, compute the actual viewport
+  // size, then divide by the ImageSampleDistance to find the full image
+  // size in pixels
+  int width, height;
+  ren->GetTiledSize(&width, &height);
+  this->RayCastImage->SetImageViewportSize(
+    static_cast<int>(width/this->ImageSampleDistance),
+    static_cast<int>(height/this->ImageSampleDistance) );
+
+  if ( multiRender )
+    {
+    this->UpdateCroppingRegions();
+    this->ComputeMatrices( inputOrigin,
+                           inputSpacing,
+                           inputExtent,
+                           ren, vol );
+
+    if ( !this->ComputeRowBounds( ren, 1, 0, inputExtent )  )
+      {
+      return 0;
+      }
+    }
+
+  return 1;
+}
+
+// This is the initialization that should be done once per volume
+void vtkCropVolumeRayCastMapper::PerVolumeInitialization( vtkRenderer *ren, vtkVolume *vol )
+{
+  // This is the input of this mapper
+  vtkImageData *input = this->GetInput();
+  this->PreviousScalars = this->CurrentScalars;
+
+
+  // make sure that we have scalar input and update the scalar input
+  if ( input == NULL )
+    {
+    vtkErrorMacro(<< "No Input!");
+    return;
+    }
+  else
+    {
+    input->UpdateInformation();
+    input->SetUpdateExtentToWholeExtent();
+    input->Update();
+    }
+
+  int usingCellColors;
+  this->CurrentScalars =
+    this->GetScalars( input, this->ScalarMode,
+                      this->ArrayAccessMode,
+                      this->ArrayId,
+                      this->ArrayName,
+                      usingCellColors );
+
+  if ( usingCellColors )
+    {
+    vtkErrorMacro("Cell Scalars not supported");
+    return;
+    }
+
+  // Compute some matrices from voxels to view and vice versa based
+  // on the whole input
+  double inputSpacing[3];
+  double inputOrigin[3];
+  int    inputExtent[6];
+  input->GetSpacing( inputSpacing );
+  input->GetOrigin( inputOrigin );
+  input->GetExtent( inputExtent );
+
+  this->ComputeMatrices( inputOrigin,
+                         inputSpacing,
+                         inputExtent,
+                         ren, vol );
+
+  this->RenderWindow = ren->GetRenderWindow();
+  this->Volume = vol;
+
+  // Adjust the sample spacing if necessary
+  if ( this->LockSampleDistanceToInputSpacing )
+    {
+    // compute 1/2 the average spacing
+    double dist =
+      (inputSpacing[0] + inputSpacing[1] + inputSpacing[2])/6.0;
+    double avgNumVoxels =
+      pow(static_cast<double>((inputExtent[1] - inputExtent[0]) *
+                              (inputExtent[3] - inputExtent[2]) *
+                              (inputExtent[5] - inputExtent[4])),
+          static_cast<double>(0.333));
+
+    if (avgNumVoxels < 100)
+      {
+      dist *= 0.01 + (1 - 0.01) * avgNumVoxels / 100;
+      }
+
+    // Need to treat interactive renders differently, because if
+    // AutoAdjustSampleDistances is on, then we doubled the sample
+    // distance
+    if ( this->AutoAdjustSampleDistances &&
+         vol->GetAllocatedRenderTime() < 1.0 )
+      {
+      if ( this->SampleDistance / (dist*2) < 0.999 ||
+           this->SampleDistance / (dist*2) > 1.001)
+        {
+        this->OldSampleDistance         = dist;
+        this->SampleDistance            = dist*2;
+        this->InteractiveSampleDistance = dist*2;
+        }
+      }
+    else if ( this->SampleDistance / dist < 0.999 ||
+              this->SampleDistance / dist > 1.001 )
+      {
+      this->OldSampleDistance         = dist;
+      this->SampleDistance            = dist;
+      this->InteractiveSampleDistance = dist*2;
+      }
+    }
+
+  this->UpdateColorTable( vol );
+  this->UpdateGradients( vol );
+  this->UpdateShadingTable( ren, vol );
+  this->UpdateMinMaxVolume( vol );
+}
+
+// This is the initialization that should be done once per subvolume
+void vtkCropVolumeRayCastMapper::PerSubVolumeInitialization( vtkRenderer *ren, vtkVolume *vol, int multiRender )
+{
+  this->UpdateCroppingRegions();
+
+  // Compute row bounds. This will also compute the size of the image to
+  // render, allocate the space if necessary, and clear the image where
+  // required. If no rays need to be cast, restore the old image sample
+  // distance and return
+  int inputExtent[6];
+  vtkImageData *input = this->GetInput();
+  input->GetExtent( inputExtent );
+
+  // If this is part of a multirender (AMR volume rendering) then
+  // the image parameters have already been computed and we can skip
+  // that. In all cases we need to compute the row bounds so pass in
+  // a 1 for that flag
+  int imageFlag = (multiRender)?(0):(1);
+  if ( !this->ComputeRowBounds( ren, imageFlag, 1, inputExtent )  )
+    {
+    this->AbortRender();
+    return;
+    }
+
+  // If this is part of a multiRender, then we've already captured the z buffer,
+  // otherwise we need to do it here
+  if ( !multiRender )
+    {
+    this->CaptureZBuffer( ren );
+    }
+
+  this->InitializeRayInfo( vol );
+}
+
+// This is the render method for the subvolume
+void vtkCropVolumeRayCastMapper::RenderSubVolume()
+{
+  // Set the number of threads to use for ray casting,
+  // then set the execution method and do it.
+  this->InvokeEvent( vtkCommand::VolumeMapperRenderStartEvent, NULL );
+  this->Threader->SetSingleMethod( CropFixedPointVolumeRayCastMapper_CastRays,
+                                   (void *)this);
+  this->Threader->SingleMethodExecute();
+  this->InvokeEvent( vtkCommand::VolumeMapperRenderEndEvent, NULL );
+}
+
+// This method displays the image that has been created
+void vtkCropVolumeRayCastMapper::DisplayRenderedImage( vtkRenderer *ren,
+                                                             vtkVolume   *vol )
+{
+  float depth;
+  if ( this->IntermixIntersectingGeometry )
+    {
+    depth = this->MinimumViewDistance;
+    }
+  else
+    {
+    depth = -1;
+    }
+
+
+  if( this->FinalColorWindow != 1.0 ||
+      this->FinalColorLevel != 0.5 )
+    {
+    this->ApplyFinalColorWindowLevel();
+    }
+
+  this->ImageDisplayHelper->
+    RenderTexture( vol, ren,
+                   this->RayCastImage,
+                   depth );
+}
+
+void vtkCropVolumeRayCastMapper::ApplyFinalColorWindowLevel()
+{
+  double scale=1.0/this->FinalColorWindow;
+  double bias=0.5-this->FinalColorLevel/this->FinalColorWindow;
+
+  unsigned short *image = this->RayCastImage->GetImage();
+  unsigned short *iptr;
+
+  int fullSize[2];
+  this->RayCastImage->GetImageMemorySize(fullSize);
+
+  int size[2];
+  this->RayCastImage->GetImageInUseSize(size);
+
+  int i, j;
+
+  for ( j = 0; j < fullSize[1]; j++ )
+    {
+    iptr = image + 4*j*fullSize[0];
+    for ( i = 0; i < size[0]; i++ )
+      {
+      int tmp;
+
+      // Red component
+      tmp = (int)((float)(*iptr)*scale + bias * (float)(*(iptr+3)));
+      tmp = (tmp<0)?(0):(tmp);
+      tmp = (tmp>32767)?(32767):(tmp);
+      *iptr = tmp;
+
+      // Green component
+      iptr++;
+      tmp = (int)((float)(*iptr)*scale + bias * (float)(*(iptr+2)));
+      tmp = (tmp<0)?(0):(tmp);
+      tmp = (tmp>32767)?(32767):(tmp);
+      *iptr = tmp;
+
+      // Green component
+      iptr++;
+      tmp = (int)((float)(*iptr)*scale + bias * (float)(*(iptr+1)));
+      tmp = (tmp<0)?(0):(tmp);
+      tmp = (tmp>32767)?(32767):(tmp);
+      *iptr = tmp;
+
+      // alpha - do nothing
+      iptr++;
+      iptr++;
+      }
+    }
+}
+
+// This method should be called when the render is aborted to restore previous values.
+// Otherwise, the old time is still stored, with the newly computed sample distances,
+// and that will cause problems on the next render.
+void vtkCropVolumeRayCastMapper::AbortRender()
+{
+  // Restore values
+  this->ImageSampleDistance = this->OldImageSampleDistance;
+  this->SampleDistance      = this->OldSampleDistance;
+}
+
+// Capture the ZBuffer to use for intermixing with opaque geometry
+// that has already been rendered
+void vtkCropVolumeRayCastMapper::CaptureZBuffer( vtkRenderer *ren )
+{
+  // How big is the viewport in pixels?
+  double *viewport   =  ren->GetViewport();
+  int *renWinSize   =  ren->GetRenderWindow()->GetSize();
+
+  // Do we need to capture the z buffer to intermix intersecting
+  // geometry? If so, do it here
+  if ( this->IntermixIntersectingGeometry &&
+       ren->GetNumberOfPropsRendered() )
+    {
+    int x1, x2, y1, y2;
+
+    // turn ImageOrigin into (x1,y1) in window (not viewport!)
+    // coordinates.
+    int imageOrigin[2];
+    int imageInUseSize[2];
+    this->RayCastImage->GetImageOrigin( imageOrigin );
+    this->RayCastImage->GetImageInUseSize( imageInUseSize );
+
+    x1 = static_cast<int> (
+      viewport[0] * static_cast<float>(renWinSize[0]) +
+      static_cast<float>(imageOrigin[0]) * this->ImageSampleDistance );
+    y1 = static_cast<int> (
+      viewport[1] * static_cast<float>(renWinSize[1]) +
+      static_cast<float>(imageOrigin[1]) * this->ImageSampleDistance);
+
+    int zbufferSize[2];
+    int zbufferOrigin[2];
+
+    // compute z buffer size
+    zbufferSize[0] = static_cast<int>(
+      static_cast<float>(imageInUseSize[0]) * this->ImageSampleDistance);
+    zbufferSize[1] = static_cast<int>(
+      static_cast<float>(imageInUseSize[1]) * this->ImageSampleDistance);
+
+    // Use the size to compute (x2,y2) in window coordinates
+    x2 = x1 + zbufferSize[0] - 1;
+    y2 = y1 + zbufferSize[1] - 1;
+
+    // This is the z buffer origin (in viewport coordinates)
+    zbufferOrigin[0] = static_cast<int>(
+      static_cast<float>(imageOrigin[0]) * this->ImageSampleDistance);
+    zbufferOrigin[1] = static_cast<int>(
+      static_cast<float>(imageOrigin[1]) * this->ImageSampleDistance);
+
+    this->RayCastImage->SetZBufferSize( zbufferSize );
+    this->RayCastImage->SetZBufferOrigin( zbufferOrigin );
+    this->RayCastImage->AllocateZBuffer();
+
+    // Capture the z buffer
+    ren->GetRenderWindow()->GetZbufferData( x1, y1, x2, y2,
+                                            this->RayCastImage->GetZBuffer() );
+
+    this->RayCastImage->UseZBufferOn();
+    }
+  else
+    {
+    this->RayCastImage->UseZBufferOff();
+    }
+}
+
+
+void vtkCropVolumeRayCastMapper::Render( vtkRenderer *ren, vtkVolume *vol )
+{
+  this->Timer->StartTimer();
+
+  // Since we are passing in a value of 0 for the multiRender flag
+  // (this is a single render pass - not part of a multipass AMR render)
+  // then we know the origin, spacing, and extent values will not
+  // be used so just initialize everything to 0. No need to check
+  // the return value of the PerImageInitialization method - since this
+  // is not a multirender it will always return 1.
+  double dummyOrigin[3]  = {0.0, 0.0, 0.0};
+  double dummySpacing[3] = {0.0, 0.0, 0.0};
+  int dummyExtent[6] = {0, 0, 0, 0, 0, 0};
+  this->PerImageInitialization( ren, vol, 0,
+                                dummyOrigin,
+                                dummySpacing,
+                                dummyExtent );
+
+  this->PerVolumeInitialization( ren, vol );
+
+  vtkRenderWindow *renWin=ren->GetRenderWindow();
+
+  if ( renWin && renWin->CheckAbortStatus() )
+    {
+    this->AbortRender();
+    return;
+    }
+
+  this->PerSubVolumeInitialization( ren, vol, 0 );
+  if ( renWin && renWin->CheckAbortStatus() )
+    {
+    this->AbortRender();
+    return;
+    }
+
+  this->RenderSubVolume();
+
+  if ( renWin && renWin->CheckAbortStatus() )
+    {
+    this->AbortRender();
+    return;
+    }
+
+  this->DisplayRenderedImage( ren, vol );
+
+  this->Timer->StopTimer();
+  this->TimeToDraw = this->Timer->GetElapsedTime();
+  // If we've increased the sample distance, account for that in the stored time. Since we
+  // don't get linear performance improvement, use a factor of .66
+  this->StoreRenderTime( ren, vol,
+                         this->TimeToDraw *
+                         this->ImageSampleDistance *
+                         this->ImageSampleDistance *
+                         ( 1.0 + 0.66*
+                           (this->SampleDistance - this->OldSampleDistance) /
+                           this->OldSampleDistance ) );
+
+  this->SampleDistance = this->OldSampleDistance;
+}
+
+VTK_THREAD_RETURN_TYPE CropFixedPointVolumeRayCastMapper_CastRays( void *arg )
+{
+  // Get the info out of the input structure
+  int threadID    = ((vtkMultiThreader::ThreadInfo *)(arg))->ThreadID;
+  int threadCount = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads;
+
+  vtkCropVolumeRayCastMapper *me = (vtkCropVolumeRayCastMapper *)(((vtkMultiThreader::ThreadInfo *)arg)->UserData);
+
+  if ( !me )
+    {
+    vtkGenericWarningMacro("Irrecoverable error: no mapper specified");
+    return VTK_THREAD_RETURN_VALUE;
+    }
+
+  vtkVolume *vol = me->GetVolume();
+
+  if ( me->GetBlendMode() == vtkVolumeMapper::MAXIMUM_INTENSITY_BLEND ||
+       me->GetBlendMode() == vtkVolumeMapper::MINIMUM_INTENSITY_BLEND )
+    {
+    me->GetMIPHelper()->GenerateImage( threadID, threadCount, vol, (vtkFixedPointVolumeRayCastMapper *)me );
+    }
+  else
+    {
+    if ( me->GetShadingRequired() == 0 )
+      {
+      if ( me->GetGradientOpacityRequired() == 0 )
+        {
+        me->GetCompositeHelper()->GenerateImage( threadID, threadCount, vol, me );
+        }
+      else
+        {
+        me->GetCompositeGOHelper()->GenerateImage( threadID, threadCount, vol, (vtkCropVolumeRayCastMapper *)me );
+        }
+      }
+    else
+      {
+      if ( me->GetGradientOpacityRequired() == 0 )
+        {
+        me->GetCompositeShadeHelper()->GenerateImage( threadID, threadCount, vol, (vtkCropVolumeRayCastMapper *)me );
+        }
+      else
+        {
+        me->GetCompositeGOShadeHelper()->GenerateImage( threadID, threadCount, vol, (vtkCropVolumeRayCastMapper *)me );
+        }
+      }
+    }
+
+  return VTK_THREAD_RETURN_VALUE;
+}
+
+// Create an image into the vtkImageData argmument. Used generally for
+// creating thumbnail images
+void vtkCropVolumeRayCastMapper::CreateCanonicalView( vtkVolume *vol,
+                                                            vtkImageData *image,
+                                                            int blend_mode,
+                                                            double direction[3],
+                                                            double viewUp[3] )
+{
+  // Make sure we have as long as we'd like so that the
+  // image sample distance will be 1.0
+  vol->SetAllocatedRenderTime(VTK_DOUBLE_MAX, NULL);
+
+  // Create a renderer / camera with the right parameters
+  // These will never be mapped to the screen - just used
+  // to hold parameters such as size, view direction, aspect,
+  // etc.
+  vtkRenderWindow *renWin = vtkRenderWindow::New();
+  vtkRenderer *ren = vtkRenderer::New();
+  vtkCamera *cam = ren->GetActiveCamera();
+
+  renWin->AddRenderer(ren);
+  int dim[3];
+  image->GetDimensions(dim);
+
+  // The size of the window is the size of the image
+  renWin->SetSize( dim[0], dim[1] );
+
+  double *center =  vol->GetCenter();
+
+  double bnds[6];
+  vol->GetBounds(bnds);
+  double d = sqrt((bnds[1]-bnds[0])*(bnds[1]-bnds[0]) +
+                  (bnds[3]-bnds[2])*(bnds[3]-bnds[2]) +
+                  (bnds[5]-bnds[4])*(bnds[5]-bnds[4]));
+
+  // For now use x distance - need to change this
+  d = bnds[1]-bnds[0];
+
+  // Set up the camera in parallel
+  cam->SetFocalPoint( center );
+  cam->ParallelProjectionOn();
+  cam->SetPosition( center[0] - d*direction[0],
+                    center[1] - d*direction[1],
+                    center[2] - d*direction[2] );
+  cam->SetViewUp(viewUp);
+
+  cam->SetParallelScale(d/2);
+
+  // Add a light
+  vtkLight *light = vtkLight::New();
+  light->SetPosition( center[0] - d*direction[0],
+                      center[1] - d*direction[1],
+                      center[2] - d*direction[2] );
+  light->SetFocalPoint( center );
+  ren->AddLight(light);
+
+  int savedBlendMode = this->BlendMode;
+  this->BlendMode = blend_mode;
+  int savedCropping = this->Cropping;
+  this->Cropping = 0;
+
+  // Do all the initialization. This is not a multipass image
+  // so just pass in dummy origin, spacing, and extent here
+  double dummyOrigin[3]  = {0.0, 0.0, 0.0};
+  double dummySpacing[3] = {0.0, 0.0, 0.0};
+  int dummyExtent[6] = {0, 0, 0, 0, 0, 0};
+  this->PerImageInitialization( ren, vol, 0,
+                                dummyOrigin,
+                                dummySpacing,
+                                dummyExtent );
+  this->PerVolumeInitialization( ren, vol );
+  this->PerSubVolumeInitialization( ren, vol, 0 );
+
+  // Render the image
+  this->RenderSubVolume();
+
+  // Now copy the image into the vtkImageData
+  unsigned char *outPtr = (unsigned char *)image->GetScalarPointer();
+  unsigned short *inPtr = this->RayCastImage->GetImage();
+
+  int viewportSize[2];
+  int inUseSize[2];
+  int memorySize[2];
+  int origin[2];
+
+  this->RayCastImage->GetImageViewportSize( viewportSize );
+  this->RayCastImage->GetImageInUseSize( inUseSize );
+  this->RayCastImage->GetImageMemorySize( memorySize );
+  this->RayCastImage->GetImageOrigin( origin );
+
+  int i, j;
+  for ( j = 0; j < dim[1]; j++ )
+    {
+    for ( i = 0; i < dim[0]; i++ )
+      {
+      if ( j < origin[1] || (j-origin[1]) >= inUseSize[1] ||
+           i < origin[0] || (i-origin[0]) >= inUseSize[0] )
+        {
+        *(outPtr++) = 0;
+        *(outPtr++) = 0;
+        *(outPtr++) = 0;
+        }
+      else
+        {
+        unsigned short *tmp = inPtr + (j-origin[1])*memorySize[0]*4 + (i-origin[0])*4;
+        *(outPtr++) = (*(tmp++))>>7;
+        *(outPtr++) = (*(tmp++))>>7;
+        *(outPtr++) = (*(tmp++))>>7;
+        }
+      }
+    }
+
+  // Restore
+
+  this->SampleDistance = this->OldSampleDistance;
+  this->BlendMode = savedBlendMode;
+  this->Cropping = savedCropping;
+
+  //Clean up
+  renWin->RemoveRenderer(ren);
+  ren->RemoveLight(light);
+
+  renWin->Delete();
+  ren->Delete();
+  light->Delete();
+}
+
+void vtkCropVolumeRayCastMapper::ComputeRayInfo( int x, int y, unsigned int pos[3],
+                                                       unsigned int dir[3],
+                                                       unsigned int *numSteps )
+{
+  float viewRay[3];
+  float rayDirection[3];
+  float rayStart[4], rayEnd[4];
+
+  int imageViewportSize[2];
+  int imageOrigin[2];
+  this->RayCastImage->GetImageViewportSize( imageViewportSize );
+  this->RayCastImage->GetImageOrigin( imageOrigin );
+
+  float offsetX = 1.0 / static_cast<float>(imageViewportSize[0]);
+  float offsetY = 1.0 / static_cast<float>(imageViewportSize[1]);
+
+
+  // compute the view point y value for this row. Do this by
+  // taking our pixel position, adding the image origin then dividing
+  // by the full image size to get a number from 0 to 1-1/fullSize. Then,
+  // multiply by two and subtract one to get a number from
+  // -1 to 1 - 2/fullSize. Then add offsetX (which is 1/fullSize) to
+  // center it.
+  viewRay[1] = ((static_cast<float>(y) +
+                 static_cast<float>(imageOrigin[1])) /
+                imageViewportSize[1]) * 2.0 - 1.0 + offsetY;
+
+  // compute the view point x value for this pixel. Do this by
+  // taking our pixel position, adding the image origin then dividing
+  // by the full image size to get a number from 0 to 1-1/fullSize. Then,
+  // multiply by two and subtract one to get a number from
+  // -1 to 1 - 2/fullSize. Then add offsetX (which is 1/fullSize) to
+  // center it.
+  viewRay[0] = ((static_cast<float>(x) +
+                 static_cast<float>(imageOrigin[0])) /
+                imageViewportSize[0]) * 2.0 - 1.0 + offsetX;
+
+  // Now transform this point with a z value of 0 for the ray start, and
+  // a z value of 1 for the ray end. This corresponds to the near and far
+  // plane locations. If IntermixIntersectingGeometry is on, then use
+  // the zbuffer value instead of 1.0
+  viewRay[2] = 0.0;
+  vtkVRCMultiplyPointMacro( viewRay, rayStart,
+                            this->ViewToVoxelsArray );
+
+  viewRay[2] = this->RayCastImage->GetZBufferValue(x,y);
+
+  vtkVRCMultiplyPointMacro( viewRay, rayEnd,
+                            this->ViewToVoxelsArray );
+
+  rayDirection[0] = rayEnd[0] - rayStart[0];
+  rayDirection[1] = rayEnd[1] - rayStart[1];
+  rayDirection[2] = rayEnd[2] - rayStart[2];
+
+  float originalRayStart[3];
+  originalRayStart[0] = rayStart[0];
+  originalRayStart[1] = rayStart[1];
+  originalRayStart[2] = rayStart[2];
+
+
+  // Initialize with 0, fill in with actual number of steps
+  // if necessary
+  *numSteps = 0;
+
+  if ( this->ClipRayAgainstVolume( rayStart,
+                                   rayEnd,
+                                   rayDirection,
+                                   this->CroppingBounds ) &&
+       ( this->NumTransformedClippingPlanes == 0 ||
+         this->ClipRayAgainstClippingPlanes( rayStart,
+                                             rayEnd,
+                                             this->NumTransformedClippingPlanes,
+                                             this->TransformedClippingPlanes ) ) )
+    {
+    double worldRayDirection[3];
+    worldRayDirection[0] = rayDirection[0]*this->SavedSpacing[0];
+    worldRayDirection[1] = rayDirection[1]*this->SavedSpacing[1];
+    worldRayDirection[2] = rayDirection[2]*this->SavedSpacing[2];
+    double worldLength =
+      vtkMath::Normalize( worldRayDirection ) / this->SampleDistance;
+
+    rayDirection[0] /= worldLength;
+    rayDirection[1] /= worldLength;
+    rayDirection[2] /= worldLength;
+
+    float diff[3];
+    diff[0] = (rayStart[0] - originalRayStart[0])*((rayDirection[0]<0)?(-1):(1));
+    diff[1] = (rayStart[1] - originalRayStart[1])*((rayDirection[1]<0)?(-1):(1));
+    diff[2] = (rayStart[2] - originalRayStart[2])*((rayDirection[2]<0)?(-1):(1));
+
+    int steps = -1;
+
+    if ( diff[0] >= diff[1] && diff[0] >= diff[2] && rayDirection[0])
+      {
+      steps = 1 + static_cast<int>( diff[0] /
+                                    ((rayDirection[0]<0)?(-rayDirection[0]):(rayDirection[0])) );
+      }
+
+    if ( diff[1] >= diff[0] && diff[1] >= diff[2] && rayDirection[2])
+      {
+      steps = 1 + static_cast<int>( diff[1] /
+                                    ((rayDirection[1]<0)?(-rayDirection[1]):(rayDirection[1])) );
+      }
+
+    if ( diff[2] >= diff[0] && diff[2] >= diff[1] && rayDirection[2])
+      {
+      steps = 1 + static_cast<int>( diff[2] /
+                                    ((rayDirection[2]<0)?(-rayDirection[2]):(rayDirection[2])) );
+      }
+
+    if ( steps > 0 )
+      {
+      rayStart[0] = originalRayStart[0] + steps*rayDirection[0];
+      rayStart[1] = originalRayStart[1] + steps*rayDirection[1];
+      rayStart[2] = originalRayStart[2] + steps*rayDirection[2];
+      }
+
+    if ( rayStart[0] > 0.0 && rayStart[1] > 0.0 && rayStart[2] > 0.0 )
+      {
+      pos[0] = this->ToFixedPointPosition(rayStart[0]);
+      pos[1] = this->ToFixedPointPosition(rayStart[1]);
+      pos[2] = this->ToFixedPointPosition(rayStart[2]);
+      dir[0] = this->ToFixedPointDirection(rayDirection[0]);
+      dir[1] = this->ToFixedPointDirection(rayDirection[1]);
+      dir[2] = this->ToFixedPointDirection(rayDirection[2]);
+
+      int stepLoop;
+      int stepsValid = 0;
+      unsigned int currSteps;
+      for ( stepLoop = 0; stepLoop < 3; stepLoop++ )
+        {
+        if ( !( dir[stepLoop]&0x7fffffff ) )
+          {
+          continue;
+          }
+
+        unsigned int endVal = this->ToFixedPointPosition(rayEnd[stepLoop]);
+
+        if ( dir[stepLoop]&0x80000000 )
+          {
+          if ( endVal > pos[stepLoop] )
+            {
+            currSteps = static_cast<unsigned int>(
+              1 + (endVal - pos[stepLoop])/(dir[stepLoop]&0x7fffffff));
+            }
+          else
+            {
+            currSteps = 0;
+            }
+          }
+        else
+          {
+          if ( pos[stepLoop] > endVal )
+            {
+            currSteps = 1 + (pos[stepLoop]- endVal)/dir[stepLoop];
+            }
+          else
+            {
+            currSteps = 0;
+            }
+          }
+
+        if ( !stepsValid || currSteps < *numSteps )
+          {
+          *numSteps = currSteps;
+          stepsValid = 1;
+          }
+        }
+      }
+    }
+}
+
+void vtkCropVolumeRayCastMapper::InitializeRayInfo( vtkVolume   *vol )
+{
+  if ( !vol )
+    {
+    return;
+    }
+
+  // Copy the viewToVoxels matrix to 16 floats
+  int i, j;
+  for ( j = 0; j < 4; j++ )
+    {
+    for ( i = 0; i < 4; i++ )
+      {
+      this->ViewToVoxelsArray[j*4+i] =
+        static_cast<float>(this->ViewToVoxelsMatrix->GetElement(j,i));
+      }
+    }
+
+  // Copy the worldToVoxels matrix to 16 floats
+  for ( j = 0; j < 4; j++ )
+    {
+    for ( i = 0; i < 4; i++ )
+      {
+      this->WorldToVoxelsArray[j*4+i] =
+        static_cast<float>(this->WorldToVoxelsMatrix->GetElement(j,i));
+      }
+    }
+
+  // Copy the voxelsToWorld matrix to 16 floats
+  for ( j = 0; j < 4; j++ )
+    {
+    for ( i = 0; i < 4; i++ )
+      {
+      this->VoxelsToWorldArray[j*4+i] =
+        static_cast<float>(this->VoxelsToWorldMatrix->GetElement(j,i));
+      }
+    }
+
+  int dim[3];
+  this->GetInput()->GetDimensions(dim);
+  this->CroppingBounds[0] = this->CroppingBounds[2] = this->CroppingBounds[4] = 0.0;
+  this->CroppingBounds[1] = dim[0]-1;
+  this->CroppingBounds[3] = dim[1]-1;
+  this->CroppingBounds[5] = dim[2]-1;
+
+
+  // Do some initialization of the clipping planes
+  this->NumTransformedClippingPlanes = (this->ClippingPlanes)?(this->ClippingPlanes->GetNumberOfItems()):(0);
+
+  // Clear out old clipping planes
+  delete [] this->TransformedClippingPlanes;
+  this->TransformedClippingPlanes = NULL;
+
+  // Do we have any clipping planes
+  if ( this->NumTransformedClippingPlanes > 0 )
+    {
+    // Allocate some space to store the plane equations
+    this->TransformedClippingPlanes = new float [4*this->NumTransformedClippingPlanes];
+
+    // loop through all the clipping planes
+    for ( i = 0; i < this->NumTransformedClippingPlanes; i++ )
+      {
+      // Convert plane into voxel coordinate system
+      double worldNormal[3], worldOrigin[3];
+      double inputOrigin[4];
+      vtkPlane *onePlane = (vtkPlane *)this->ClippingPlanes->GetItemAsObject(i);
+      onePlane->GetNormal(worldNormal);
+      onePlane->GetOrigin(worldOrigin);
+      float *planePtr = this->TransformedClippingPlanes + 4*i;
+      vtkVRCMultiplyNormalMacro( worldNormal,
+                                 planePtr,
+                                 this->VoxelsToWorldArray );
+      vtkVRCMultiplyPointMacro( worldOrigin, inputOrigin,
+                                this->WorldToVoxelsArray );
+
+      float t = sqrt( planePtr[0]*planePtr[0] +
+                      planePtr[1]*planePtr[1] +
+                      planePtr[2]*planePtr[2] );
+      if ( t )
+        {
+        planePtr[0] /= t;
+        planePtr[1] /= t;
+        planePtr[2] /= t;
+        }
+
+      planePtr[3] = -(planePtr[0]*inputOrigin[0] +
+                      planePtr[1]*inputOrigin[1] +
+                      planePtr[2]*inputOrigin[2]);
+      }
+    }
+
+  // If we have a simple crop box then we can tighten the bounds
+  if ( this->Cropping && this->CroppingRegionFlags == 0x2000 )
+    {
+    this->CroppingBounds[0] = this->VoxelCroppingRegionPlanes[0];
+    this->CroppingBounds[1] = this->VoxelCroppingRegionPlanes[1];
+    this->CroppingBounds[2] = this->VoxelCroppingRegionPlanes[2];
+    this->CroppingBounds[3] = this->VoxelCroppingRegionPlanes[3];
+    this->CroppingBounds[4] = this->VoxelCroppingRegionPlanes[4];
+    this->CroppingBounds[5] = this->VoxelCroppingRegionPlanes[5];
+    }
+
+  this->CroppingBounds[0] = (this->CroppingBounds[0] < 0)?(0):(this->CroppingBounds[0]);
+  this->CroppingBounds[0] = (this->CroppingBounds[0] > dim[0]-1)?(dim[0]-1):(this->CroppingBounds[0]);
+  this->CroppingBounds[1] = (this->CroppingBounds[1] < 0)?(0):(this->CroppingBounds[1]);
+  this->CroppingBounds[1] = (this->CroppingBounds[1] > dim[0]-1)?(dim[0]-1):(this->CroppingBounds[1]);
+  this->CroppingBounds[2] = (this->CroppingBounds[2] < 0)?(0):(this->CroppingBounds[2]);
+  this->CroppingBounds[2] = (this->CroppingBounds[2] > dim[1]-1)?(dim[1]-1):(this->CroppingBounds[2]);
+  this->CroppingBounds[3] = (this->CroppingBounds[3] < 0)?(0):(this->CroppingBounds[3]);
+  this->CroppingBounds[3] = (this->CroppingBounds[3] > dim[1]-1)?(dim[1]-1):(this->CroppingBounds[3]);
+  this->CroppingBounds[4] = (this->CroppingBounds[4] < 0)?(0):(this->CroppingBounds[4]);
+  this->CroppingBounds[4] = (this->CroppingBounds[4] > dim[2]-1)?(dim[2]-1):(this->CroppingBounds[4]);
+  this->CroppingBounds[5] = (this->CroppingBounds[5] < 0)?(0):(this->CroppingBounds[5]);
+  this->CroppingBounds[5] = (this->CroppingBounds[5] > dim[2]-1)?(dim[2]-1):(this->CroppingBounds[5]);
+
+  // Save spacing because for some reason this call is really really slow!
+  this->GetInput()->GetSpacing(this->SavedSpacing);
+}
+
+// Return 0 if our volume is outside the view frustum, 1 if it
+// is in the view frustum.
+int vtkCropVolumeRayCastMapper::ComputeRowBounds(vtkRenderer *ren,
+                                                       int imageFlag,
+                                                       int rowBoundsFlag,
+                                                       int inputExtent[6] )
+{
+  float voxelPoint[3];
+  float viewPoint[8][4];
+  int i, j, k;
+  unsigned short *ucptr;
+  float minX, minY, maxX, maxY, minZ, maxZ;
+
+  minX =  1.0;
+  minY =  1.0;
+  maxX = -1.0;
+  maxY = -1.0;
+  minZ =  1.0;
+  maxZ =  0.0;
+
+  float bounds[6];
+  int dim[3];
+  dim[0] = inputExtent[1] - inputExtent[0] + 1;
+  dim[1] = inputExtent[3] - inputExtent[2] + 1;
+  dim[2] = inputExtent[5] - inputExtent[4] + 1;
+
+
+  bounds[0] = bounds[2] = bounds[4] = 0.0;
+  bounds[1] = static_cast<float>(dim[0]-1);
+  bounds[3] = static_cast<float>(dim[1]-1);
+  bounds[5] = static_cast<float>(dim[2]-1);
+
+  int insideFlag = 0;
+  double camPos[4];
+  ren->GetActiveCamera()->GetPosition( camPos );
+  camPos[3] = 1.0;
+  this->WorldToVoxelsMatrix->MultiplyPoint( camPos, camPos );
+  if ( camPos[3] )
+    {
+    camPos[0] /= camPos[3];
+    camPos[1] /= camPos[3];
+    camPos[2] /= camPos[3];
+    }
+
+
+  // If we have a simple crop box then we can tighten the bounds
+  if ( this->Cropping && this->CroppingRegionFlags == 0x2000 )
+    {
+    bounds[0] = this->VoxelCroppingRegionPlanes[0];
+    bounds[1] = this->VoxelCroppingRegionPlanes[1];
+    bounds[2] = this->VoxelCroppingRegionPlanes[2];
+    bounds[3] = this->VoxelCroppingRegionPlanes[3];
+    bounds[4] = this->VoxelCroppingRegionPlanes[4];
+    bounds[5] = this->VoxelCroppingRegionPlanes[5];
+    }
+
+
+  if ( camPos[0] >= bounds[0] &&
+       camPos[0] <= bounds[1] &&
+       camPos[1] >= bounds[2] &&
+       camPos[1] <= bounds[3] &&
+       camPos[2] >= bounds[4] &&
+       camPos[2] <= bounds[5] )
+    {
+    insideFlag = 1;
+    }
+
+  // Copy the voxelsToView matrix to 16 floats
+  float voxelsToViewMatrix[16];
+  for ( j = 0; j < 4; j++ )
+    {
+    for ( i = 0; i < 4; i++ )
+      {
+      voxelsToViewMatrix[j*4+i] =
+        static_cast<float>(this->VoxelsToViewMatrix->GetElement(j,i));
+      }
+    }
+
+  // Convert the voxel bounds to view coordinates to find out the
+  // size and location of the image we need to generate.
+  int idx = 0;
+  if ( insideFlag )
+    {
+    minX = -1.0;
+    maxX =  1.0;
+    minY = -1.0;
+    maxY =  1.0;
+    minZ =  0.001;
+    maxZ =  0.001;
+    }
+  else
+    {
+    for ( k = 0; k < 2; k++ )
+      {
+      voxelPoint[2] = bounds[4+k];
+      for ( j = 0; j < 2; j++ )
+        {
+        voxelPoint[1] = bounds[2+j];
+        for ( i = 0; i < 2; i++ )
+          {
+          voxelPoint[0] = bounds[i];
+          vtkVRCMultiplyPointMacro( voxelPoint, viewPoint[idx],
+                                    voxelsToViewMatrix );
+
+          minX = (viewPoint[idx][0]<minX)?(viewPoint[idx][0]):(minX);
+          minY = (viewPoint[idx][1]<minY)?(viewPoint[idx][1]):(minY);
+          maxX = (viewPoint[idx][0]>maxX)?(viewPoint[idx][0]):(maxX);
+          maxY = (viewPoint[idx][1]>maxY)?(viewPoint[idx][1]):(maxY);
+          minZ = (viewPoint[idx][2]<minZ)?(viewPoint[idx][2]):(minZ);
+          maxZ = (viewPoint[idx][2]>maxZ)?(viewPoint[idx][2]):(maxZ);
+          idx++;
+          }
+        }
+      }
+    }
+
+  if ( minZ < 0.001 || maxZ > 0.9999 )
+    {
+    minX = -1.0;
+    maxX =  1.0;
+    minY = -1.0;
+    maxY =  1.0;
+    insideFlag = 1;
+    }
+
+  this->MinimumViewDistance =
+    (minZ<0.001)?(0.001):((minZ>0.999)?(0.999):(minZ));
+
+  int imageViewportSize[2];
+  int imageOrigin[2];
+  int imageMemorySize[2];
+  int imageInUseSize[2];
+  this->RayCastImage->GetImageViewportSize( imageViewportSize );
+  this->RayCastImage->GetImageOrigin( imageOrigin );
+  this->RayCastImage->GetImageMemorySize( imageMemorySize );
+
+  // We have min/max values from -1.0 to 1.0 now - we want to convert
+  // these to pixel locations. Give a couple of pixels of breathing room
+  // on each side if possible
+  minX = ( minX + 1.0 ) * 0.5 * imageViewportSize[0] - 2;
+  minY = ( minY + 1.0 ) * 0.5 * imageViewportSize[1] - 2;
+  maxX = ( maxX + 1.0 ) * 0.5 * imageViewportSize[0] + 2;
+  maxY = ( maxY + 1.0 ) * 0.5 * imageViewportSize[1] + 2;
+
+  // If we are outside the view frustum return 0 - there is no need
+  // to render anything
+  if ( ( minX < 0 && maxX < 0 ) ||
+       ( minY < 0 && maxY < 0 ) ||
+       ( minX > imageViewportSize[0]-1 &&
+         maxX > imageViewportSize[0]-1 ) ||
+       ( minX > imageViewportSize[0]-1 &&
+         maxX > imageViewportSize[0]-1 ) )
+    {
+    return 0;
+    }
+
+  int oldImageMemorySize[2];
+  oldImageMemorySize[0] = imageMemorySize[0];
+  oldImageMemorySize[1] = imageMemorySize[1];
+
+  // Check the bounds - the volume might project outside of the
+  // viewing box / frustum so clip it if necessary
+  minX = (minX<0)?(0):(minX);
+  minY = (minY<0)?(0):(minY);
+  maxX = (maxX>imageViewportSize[0]-1)?
+    (imageViewportSize[0]-1):(maxX);
+  maxY = (maxY>imageViewportSize[1]-1)?
+    (imageViewportSize[1]-1):(maxY);
+
+  // Create the new image, and set its size and position
+  imageInUseSize[0] = static_cast<int>(maxX - minX + 1.0);
+  imageInUseSize[1] = static_cast<int>(maxY - minY + 1.0);
+
+  // What is a power of 2 size big enough to fit this image?
+  imageMemorySize[0] = 32;
+  imageMemorySize[1] = 32;
+  while ( imageMemorySize[0] < imageInUseSize[0] )
+    {
+    imageMemorySize[0] *= 2;
+    }
+  while ( imageMemorySize[1] < imageInUseSize[1] )
+    {
+    imageMemorySize[1] *= 2;
+    }
+
+  imageOrigin[0] = static_cast<int>(minX);
+  imageOrigin[1] = static_cast<int>(minY);
+
+  // If the old image size is much too big (more than twice in
+  // either direction) then set the old width to 0 which will
+  // cause the image to be recreated
+  if ( oldImageMemorySize[0] > 4*imageMemorySize[0] ||
+       oldImageMemorySize[1] > 4*imageMemorySize[1] )
+    {
+    oldImageMemorySize[0] = 0;
+    }
+
+  // If the old image is big enough (but not too big - we handled
+  // that above) then we'll bump up our required size to the
+  // previous one. This will keep us from thrashing.
+  if ( oldImageMemorySize[0] >= imageMemorySize[0] &&
+       oldImageMemorySize[1] >= imageMemorySize[1] )
+    {
+    imageMemorySize[0] = oldImageMemorySize[0];
+    imageMemorySize[1] = oldImageMemorySize[1];
+    }
+
+  if ( imageFlag )
+    {
+    this->RayCastImage->SetImageOrigin( imageOrigin );
+    this->RayCastImage->SetImageMemorySize( imageMemorySize );
+    this->RayCastImage->SetImageInUseSize( imageInUseSize );
+
+    // Do we already have a texture big enough? If not, create a new one and
+    // clear it.
+    if ( imageMemorySize[0] > oldImageMemorySize[0] ||
+         imageMemorySize[1] > oldImageMemorySize[1] )
+      {
+      this->RayCastImage->AllocateImage();
+      delete [] this->RowBounds;
+      delete [] this->OldRowBounds;
+
+      this->RayCastImage->ClearImage();
+
+      if ( rowBoundsFlag )
+        {
+        // Create the row bounds array. This will store the start / stop pixel
+        // for each row. This helps eleminate work in areas outside the bounding
+        // hexahedron since a bounding box is not very tight. We keep the old ones
+        // too to help with only clearing where required
+        this->RowBounds = new int [2*imageMemorySize[1]];
+        this->OldRowBounds = new int [2*imageMemorySize[1]];
+
+        for ( i = 0; i < imageMemorySize[1]; i++ )
+          {
+          this->RowBounds[i*2]      = imageMemorySize[0];
+          this->RowBounds[i*2+1]    = -1;
+          this->OldRowBounds[i*2]   = imageMemorySize[0];
+          this->OldRowBounds[i*2+1] = -1;
+          }
+        }
+      }
+    }
+
+  if ( !rowBoundsFlag )
+    {
+    return 1;
+    }
+
+
+  // Swap the row bounds
+  int *tmpptr;
+  tmpptr = this->RowBounds;
+  this->RowBounds = this->OldRowBounds;
+  this->OldRowBounds = tmpptr;
+
+  // If we are inside the volume our row bounds indicate every ray must be
+  // cast - we don't need to intersect with the 12 lines
+  if ( insideFlag )
+    {
+    for ( j = 0; j < imageInUseSize[1]; j++ )
+      {
+      this->RowBounds[j*2] = 0;
+      this->RowBounds[j*2+1] = imageInUseSize[0] - 1;
+      }
+    }
+  else
+    {
+    // create an array of lines where the y value of the first vertex is less
+    // than or equal to the y value of the second vertex. There are 12 lines,
+    // each containing x1, y1, x2, y2 values.
+    float lines[12][4];
+    float x1, y1, x2, y2;
+    int xlow, xhigh;
+    int lineIndex[12][2] = {{0,1}, {2,3}, {4,5}, {6,7},
+                            {0,2}, {1,3} ,{4,6}, {5,7},
+                            {0,4}, {1,5}, {2,6}, {3,7}};
+
+    for ( i = 0; i < 12; i++ )
+      {
+      x1 = (viewPoint[lineIndex[i][0]][0]+1.0) *
+        0.5*imageViewportSize[0] - imageOrigin[0];
+
+      y1 = (viewPoint[lineIndex[i][0]][1]+1.0) *
+        0.5*imageViewportSize[1] - imageOrigin[1];
+
+      x2 = (viewPoint[lineIndex[i][1]][0]+1.0) *
+        0.5*imageViewportSize[0] - imageOrigin[0];
+
+      y2 = (viewPoint[lineIndex[i][1]][1]+1.0) *
+        0.5*imageViewportSize[1] - imageOrigin[1];
+
+      if ( y1 < y2 )
+        {
+        lines[i][0] = x1;
+        lines[i][1] = y1;
+        lines[i][2] = x2;
+        lines[i][3] = y2;
+        }
+      else
+        {
+        lines[i][0] = x2;
+        lines[i][1] = y2;
+        lines[i][2] = x1;
+        lines[i][3] = y1;
+        }
+      }
+
+    // Now for each row in the image, find out the start / stop pixel
+    // If min > max, then no intersection occurred
+    for ( j = 0; j < imageInUseSize[1]; j++ )
+      {
+      this->RowBounds[j*2] = imageMemorySize[0];
+      this->RowBounds[j*2+1] = -1;
+      for ( i = 0; i < 12; i++ )
+        {
+        if ( j >= lines[i][1] && j <= lines[i][3] &&
+             ( lines[i][1] != lines[i][3] ) )
+          {
+          x1 = lines[i][0] +
+            (static_cast<float>(j) - lines[i][1])/(lines[i][3] - lines[i][1]) *
+            (lines[i][2] - lines[i][0] );
+
+          xlow  = static_cast<int>(x1 + 1.5);
+          xhigh = static_cast<int>(x1 - 1.0);
+
+          xlow = (xlow<0)?(0):(xlow);
+          xlow = (xlow>imageInUseSize[0]-1)?
+            (imageInUseSize[0]-1):(xlow);
+
+          xhigh = (xhigh<0)?(0):(xhigh);
+          xhigh = (xhigh>imageInUseSize[0]-1)?(
+            imageInUseSize[0]-1):(xhigh);
+
+          if ( xlow < this->RowBounds[j*2] )
+            {
+            this->RowBounds[j*2] = xlow;
+            }
+          if ( xhigh > this->RowBounds[j*2+1] )
+            {
+            this->RowBounds[j*2+1] = xhigh;
+            }
+          }
+        }
+      // If they are the same this is either a point on the cube or
+      // all lines were out of bounds (all on one side or the other)
+      // It is safe to ignore the point (since the ray isn't likely
+      // to travel through it enough to actually take a sample) and it
+      // must be ignored in the case where all lines are out of range
+      if ( this->RowBounds[j*2] == this->RowBounds[j*2+1] )
+        {
+        this->RowBounds[j*2] = imageMemorySize[0];
+        this->RowBounds[j*2+1] = -1;
+        }
+      }
+    }
+
+  for ( j = imageInUseSize[1]; j < imageMemorySize[1]; j++ )
+    {
+    this->RowBounds[j*2] = imageMemorySize[0];
+    this->RowBounds[j*2+1] = -1;
+    }
+
+  unsigned short *image = this->RayCastImage->GetImage();
+
+  for ( j = 0; j < imageMemorySize[1]; j++ )
+    {
+    if ( j%64 == 1 &&
+         this->RenderWindow && this->RenderWindow->CheckAbortStatus() )
+      {
+      return 0;
+      }
+
+    // New bounds are not overlapping with old bounds - clear between
+    // old bounds only
+    if ( this->RowBounds[j*2+1] < this->OldRowBounds[j*2] ||
+         this->RowBounds[j*2]   > this->OldRowBounds[j*2+1] )
+      {
+      ucptr = image + 4*( j*imageMemorySize[0] +
+                                this->OldRowBounds[j*2] );
+      for ( i = 0;
+            i <= (this->OldRowBounds[j*2+1] - this->OldRowBounds[j*2]);
+            i++ )
+        {
+        *(ucptr++) = 0;
+        *(ucptr++) = 0;
+        *(ucptr++) = 0;
+        *(ucptr++) = 0;
+        }
+      }
+    // New bounds do overlap with old bounds
+    else
+      {
+      // Clear from old min to new min
+      ucptr = image + 4*( j*imageMemorySize[0] +
+                          this->OldRowBounds[j*2] );
+      for ( i = 0;
+            i < (this->RowBounds[j*2] - this->OldRowBounds[j*2]);
+            i++ )
+        {
+        *(ucptr++) = 0;
+        *(ucptr++) = 0;
+        *(ucptr++) = 0;
+        *(ucptr++) = 0;
+        }
+
+      // Clear from new max to old max
+      ucptr = image + 4*( j*imageMemorySize[0] +
+                          this->RowBounds[j*2+1]+1 );
+      for ( i = 0;
+            i < (this->OldRowBounds[j*2+1] - this->RowBounds[j*2+1]);
+            i++ )
+        {
+        *(ucptr++) = 0;
+        *(ucptr++) = 0;
+        *(ucptr++) = 0;
+        *(ucptr++) = 0;
+        }
+
+      }
+    }
+
+  return 1;
+}
+
+
+void vtkCropVolumeRayCastMapper::ComputeMatrices( double inputOrigin[3],
+                                                        double inputSpacing[3],
+                                                        int inputExtent[6],
+                                                        vtkRenderer *ren,
+                                                        vtkVolume *vol )
+{
+  // Get the camera from the renderer
+  vtkCamera *cam = ren->GetActiveCamera();
+
+  // Get the aspect ratio from the renderer. This is needed for the
+  // computation of the perspective matrix
+  ren->ComputeAspect();
+  double *aspect = ren->GetAspect();
+
+  // Keep track of the projection matrix - we'll need it in a couple of places
+  // Get the projection matrix. The method is called perspective, but
+  // the matrix is valid for perspective and parallel viewing transforms.
+  // Don't replace this with the GetCompositePerspectiveTransformMatrix
+  // because that turns off stereo rendering!!!
+  this->PerspectiveTransform->Identity();
+  this->PerspectiveTransform->
+    Concatenate(cam->GetPerspectiveTransformMatrix(aspect[0]/aspect[1],
+                                                   0.0, 1.0 ));
+  this->PerspectiveTransform->Concatenate(cam->GetViewTransformMatrix());
+  this->PerspectiveMatrix->DeepCopy(this->PerspectiveTransform->GetMatrix());
+
+
+  // Compute the origin of the extent the volume origin is at voxel (0,0,0)
+  // but we want to consider (0,0,0) in voxels to be at
+  // (inputExtent[0], inputExtent[2], inputExtent[4]).
+  double extentOrigin[3];
+  extentOrigin[0] = inputOrigin[0] + inputExtent[0]*inputSpacing[0];
+  extentOrigin[1] = inputOrigin[1] + inputExtent[2]*inputSpacing[1];
+  extentOrigin[2] = inputOrigin[2] + inputExtent[4]*inputSpacing[2];
+
+  // Get the volume matrix. This is a volume to world matrix right now.
+  // We'll need to invert it, translate by the origin and scale by the
+  // spacing to change it to a world to voxels matrix.
+  this->VolumeMatrix->DeepCopy( vol->GetMatrix() );
+
+  this->VoxelsToViewTransform->SetMatrix( this->VolumeMatrix );
+
+  // Create a transform that will account for the scaling and translation of
+  // the scalar data. The is the volume to voxels matrix.
+  this->VoxelsTransform->Identity();
+  this->VoxelsTransform->Translate(extentOrigin[0],
+                                   extentOrigin[1],
+                                   extentOrigin[2] );
+
+  this->VoxelsTransform->Scale( inputSpacing[0],
+                                inputSpacing[1],
+                                inputSpacing[2] );
+
+  // Now concatenate the volume's matrix with this scalar data matrix
+  this->VoxelsToViewTransform->PreMultiply();
+  this->VoxelsToViewTransform->Concatenate( this->VoxelsTransform->GetMatrix() );
+
+  // Now we actually have the world to voxels matrix - copy it out
+  this->WorldToVoxelsMatrix->DeepCopy( this->VoxelsToViewTransform->GetMatrix() );
+  this->WorldToVoxelsMatrix->Invert();
+
+  // We also want to invert this to get voxels to world
+  this->VoxelsToWorldMatrix->DeepCopy( this->VoxelsToViewTransform->GetMatrix() );
+
+  // Compute the voxels to view transform by concatenating the
+  // voxels to world matrix with the projection matrix (world to view)
+  this->VoxelsToViewTransform->PostMultiply();
+  this->VoxelsToViewTransform->Concatenate( this->PerspectiveMatrix );
+
+  this->VoxelsToViewMatrix->DeepCopy( this->VoxelsToViewTransform->GetMatrix() );
+
+  this->ViewToVoxelsMatrix->DeepCopy( this->VoxelsToViewMatrix );
+  this->ViewToVoxelsMatrix->Invert();
+}
+
+int vtkCropVolumeRayCastMapper::ClipRayAgainstClippingPlanes( float rayStart[3],
+                                                            float rayEnd[3],
+                                                            int numClippingPlanes,
+                                                            float *clippingPlanes )
+{
+
+  float    *planePtr;
+  int      i;
+  float    t, point[3], dp;
+  float    rayDir[3];
+
+  rayDir[0] = rayEnd[0] - rayStart[0];
+  rayDir[1] = rayEnd[1] - rayStart[1];
+  rayDir[2] = rayEnd[2] - rayStart[2];
+
+  // loop through all the clipping planes
+  for ( i = 0; i < numClippingPlanes; i++ )
+    {
+    planePtr = clippingPlanes + 4*i;
+
+    dp =
+      planePtr[0]*rayDir[0] +
+      planePtr[1]*rayDir[1] +
+      planePtr[2]*rayDir[2];
+
+    if ( dp != 0.0 )
+      {
+      t =
+        -( planePtr[0]*rayStart[0] +
+           planePtr[1]*rayStart[1] +
+           planePtr[2]*rayStart[2] + planePtr[3]) / dp;
+
+      if ( t > 0.0 && t < 1.0 )
+        {
+        point[0] = rayStart[0] + t*rayDir[0];
+        point[1] = rayStart[1] + t*rayDir[1];
+        point[2] = rayStart[2] + t*rayDir[2];
+
+        if ( dp > 0.0 )
+          {
+          rayStart[0] = point[0];
+          rayStart[1] = point[1];
+          rayStart[2] = point[2];
+          }
+        else
+          {
+          rayEnd[0] = point[0];
+          rayEnd[1] = point[1];
+          rayEnd[2] = point[2];
+          }
+
+        rayDir[0] = rayEnd[0] - rayStart[0];
+        rayDir[1] = rayEnd[1] - rayStart[1];
+        rayDir[2] = rayEnd[2] - rayStart[2];
+
+        }
+      // If the clipping plane is outside the ray segment, then
+      // figure out if that means the ray segment goes to zero (if so
+      // return 0) or doesn't affect it (if so do nothing)
+      else
+        {
+        if ( dp >= 0.0 && t >= 1.0 )
+          {
+          return 0;
+          }
+        if ( dp <= 0.0 && t <= 0.0 )
+          {
+          return 0;
+          }
+        }
+      }
+    else
+      {
+      // rayDir is perpendicular to planePtr; i.e., the ray does not
+      // intersect the plane. Determine which side of the plane the ray
+      // is on.
+      float side = planePtr[0]*rayStart[0] + planePtr[1]*rayStart[1] +
+        planePtr[2]*rayStart[2] + planePtr[3];
+      if (side < 0)
+        {
+        // clip
+        return 0;
+        }
+      }
+    }
+
+  return 1;
+}
+
+
+int vtkCropVolumeRayCastMapper::ClipRayAgainstVolume( float rayStart[3],
+                                                    float rayEnd[3],
+                                                    float rayDirection[3],
+                                                    double bounds[6] )
+{
+  int    loop;
+  float  diff;
+  float  t;
+
+  if ( rayStart[0] >= bounds[1] ||
+       rayStart[1] >= bounds[3] ||
+       rayStart[2] >= bounds[5] ||
+       rayStart[0] < bounds[0] ||
+       rayStart[1] < bounds[2] ||
+       rayStart[2] < bounds[4] )
+    {
+    for ( loop = 0; loop < 3; loop++ )
+      {
+      diff = 0;
+
+      if ( rayStart[loop] < (bounds[2*loop]+0.01) )
+        {
+        diff = (bounds[2*loop]+0.01) - rayStart[loop];
+        }
+      else if ( rayStart[loop] > (bounds[2*loop+1]-0.01) )
+        {
+        diff = (bounds[2*loop+1]-0.01) - rayStart[loop];
+        }
+
+      if ( diff )
+        {
+        if ( rayDirection[loop] != 0.0 )
+          {
+          t = diff / rayDirection[loop];
+          }
+        else
+          {
+          t = -1.0;
+          }
+
+        if ( t > 0.0 )
+          {
+          rayStart[0] += rayDirection[0] * t;
+          rayStart[1] += rayDirection[1] * t;
+          rayStart[2] += rayDirection[2] * t;
+          }
+        }
+      }
+    }
+
+  // If the voxel still isn't inside the volume, then this ray
+  // doesn't really intersect the volume
+
+  if ( rayStart[0] >= bounds[1] ||
+       rayStart[1] >= bounds[3] ||
+       rayStart[2] >= bounds[5] ||
+       rayStart[0] < bounds[0] ||
+       rayStart[1] < bounds[2] ||
+       rayStart[2] < bounds[4] )
+    {
+    return 0;
+    }
+
+  // The ray does intersect the volume, and we have a starting
+  // position that is inside the volume
+  if ( rayEnd[0] >= bounds[1] ||
+       rayEnd[1] >= bounds[3] ||
+       rayEnd[2] >= bounds[5] ||
+       rayEnd[0] < bounds[0] ||
+       rayEnd[1] < bounds[2] ||
+       rayEnd[2] < bounds[4] )
+    {
+    for ( loop = 0; loop < 3; loop++ )
+      {
+      diff = 0;
+
+      if ( rayEnd[loop] < (bounds[2*loop]+0.01) )
+        {
+        diff = (bounds[2*loop]+0.01) - rayEnd[loop];
+        }
+      else if ( rayEnd[loop] > (bounds[2*loop+1]-0.01) )
+        {
+        diff = (bounds[2*loop+1]-0.01) - rayEnd[loop];
+        }
+
+      if ( diff )
+        {
+        if ( rayDirection[loop] != 0.0 )
+          {
+          t = diff / rayDirection[loop];
+          }
+        else
+          {
+          t = 1.0;
+          }
+
+        if ( t < 0.0 )
+          {
+          rayEnd[0] += rayDirection[0] * t;
+          rayEnd[1] += rayDirection[1] * t;
+          rayEnd[2] += rayDirection[2] * t;
+          }
+        }
+      }
+    }
+
+  // To be absolutely certain our ray remains inside the volume,
+  // recompute the ray direction (since it has changed - it is not
+  // normalized and therefore changes when start/end change) and move
+  // the start/end points in by 1/1000th of the distance.
+  float offset;
+  offset = (rayEnd[0] - rayStart[0])*0.001;
+  rayStart[0] += offset;
+  rayEnd[0]   -= offset;
+
+  offset = (rayEnd[1] - rayStart[1])*0.001;
+  rayStart[1] += offset;
+  rayEnd[1]   -= offset;
+
+  offset = (rayEnd[2] - rayStart[2])*0.001;
+  rayStart[2] += offset;
+  rayEnd[2]   -= offset;
+
+  if ( rayEnd[0] >= bounds[1] ||
+       rayEnd[1] >= bounds[3] ||
+       rayEnd[2] >= bounds[5] ||
+       rayEnd[0] < bounds[0] ||
+       rayEnd[1] < bounds[2] ||
+       rayEnd[2] < bounds[4] )
+    {
+      return 0;
+    }
+
+  if ( (rayEnd[0]-rayStart[0])*rayDirection[0] < 0.0 ||
+       (rayEnd[1]-rayStart[1])*rayDirection[1] < 0.0 ||
+       (rayEnd[2]-rayStart[2])*rayDirection[2] < 0.0 )
+    {
+    return 0;
+    }
+
+  return 1;
+}
+
+
+void vtkCropVolumeRayCastMapper::ComputeGradients( vtkVolume *vol )
+{
+  vtkImageData *input = this->GetInput();
+
+  void *dataPtr = this->CurrentScalars->GetVoidPointer(0);
+
+ int scalarType   = this->CurrentScalars->GetDataType();
+ int components   = this->CurrentScalars->GetNumberOfComponents();
+ int independent  = vol->GetProperty()->GetIndependentComponents();
+
+ int dim[3];
+ double spacing[3];
+ input->GetDimensions(dim);
+ input->GetSpacing(spacing);
+
+ // Find the scalar range
+ double scalarRange[4][2];
+ int c;
+ for ( c = 0; c < components; c++ )
+   {
+   this->CurrentScalars->GetRange(scalarRange[c], c);
+   }
+
+ int sliceSize = dim[0]*dim[1]*((independent)?(components):(1));
+ int numSlices = dim[2];
+
+ int i;
+
+ // Delete the prior gradient normal information
+ if ( this->GradientNormal )
+   {
+   // Contiguous? Delete in one chunk otherwise delete slice by slice
+   if ( this->ContiguousGradientNormal )
+     {
+     delete [] this->ContiguousGradientNormal;
+     this->ContiguousGradientNormal = NULL;
+     }
+   else
+     {
+     for ( i = 0; i < this->NumberOfGradientSlices; i++ )
+       {
+       delete [] this->GradientNormal[i];
+       }
+     }
+   delete [] this->GradientNormal;
+   this->GradientNormal = NULL;
+   }
+
+ // Delete the prior gradient magnitude information
+ if ( this->GradientMagnitude )
+   {
+   // Contiguous? Delete in one chunk otherwise delete slice by slice
+   if ( this->ContiguousGradientMagnitude )
+     {
+     delete [] this->ContiguousGradientMagnitude;
+     this->ContiguousGradientMagnitude = NULL;
+     }
+   else
+     {
+     for ( i = 0; i < this->NumberOfGradientSlices; i++ )
+       {
+       delete [] this->GradientMagnitude[i];
+       }
+     }
+   delete [] this->GradientMagnitude;
+   this->GradientMagnitude = NULL;
+   }
+
+  this->NumberOfGradientSlices = numSlices;
+  this->GradientNormal  = new unsigned short *[numSlices];
+  this->GradientMagnitude = new unsigned char *[numSlices];
+
+  // first, attempt contiguous memory. If this fails, then go
+  // for non-contiguous
+  this->ContiguousGradientNormal = new unsigned short [numSlices * sliceSize];
+  this->ContiguousGradientMagnitude = new unsigned char [numSlices * sliceSize];
+
+  if ( this->ContiguousGradientNormal )
+    {
+    // We were able to allocate contiguous space - we just need to set the
+    // slice pointers here
+    for ( i = 0; i < numSlices; i++ )
+      {
+      this->GradientNormal[i]  = this->ContiguousGradientNormal + i*sliceSize;
+      }
+    }
+  else
+    {
+    // We were not able to allocate contigous space - allocate it slice by slice
+    for ( i = 0; i < numSlices; i++ )
+      {
+      this->GradientNormal[i]  = new unsigned short [sliceSize];
+      }
+    }
+
+  if ( this->ContiguousGradientMagnitude )
+    {
+    // We were able to allocate contiguous space - we just need to set the
+    // slice pointers here
+    for ( i = 0; i < numSlices; i++ )
+      {
+      this->GradientMagnitude[i]  = this->ContiguousGradientMagnitude + i*sliceSize;
+      }
+    }
+  else
+    {
+    // We were not able to allocate contigous space - allocate it slice by slice
+    for ( i = 0; i < numSlices; i++ )
+      {
+      this->GradientMagnitude[i] = new unsigned char [sliceSize];
+      }
+    }
+
+  vtkTimerLog *timer = vtkTimerLog::New();
+  timer->StartTimer();
+
+  if ( components == 1 &&
+       (scalarType == VTK_UNSIGNED_CHAR ||
+        scalarType == VTK_CHAR ||
+        scalarType == VTK_UNSIGNED_SHORT ||
+        scalarType == VTK_SHORT ) )
+    {
+      this->Threader->SetSingleMethod( vtkCropFPVRCMSwitchOnDataType,
+                                       (vtkObject *)this );
+      this->Threader->SingleMethodExecute();
+    }
+
+  else
+    {
+    switch ( scalarType )
+      {
+      vtkTemplateMacro(
+        vtkCropVolumeRayCastMapperComputeGradients(
+          (VTK_TT *)(dataPtr), dim, spacing, components,
+          independent, scalarRange,
+          this->GradientNormal,
+          this->GradientMagnitude,
+          this->DirectionEncoder,
+          this) );
+      }
+    }
+
+  timer->StopTimer();
+  //cout << "Gradients computed in " << timer->GetElapsedTime() << " seconds " << endl;
+  timer->Delete();
+}
+
+int vtkCropVolumeRayCastMapper::UpdateShadingTable( vtkRenderer *ren,
+                                                          vtkVolume *vol )
+{
+  if ( this->ShadingRequired == 0 )
+    {
+    return 0;
+    }
+
+  // How many components?
+  int components = this->CurrentScalars->GetNumberOfComponents();
+
+  int c;
+  for ( c = 0; c < ((vol->GetProperty()->GetIndependentComponents())?(components):(1)); c++ )
+    {
+    this->GradientShader->SetActiveComponent( c );
+    this->GradientShader->UpdateShadingTable( ren, vol, this->GradientEstimator );
+
+    float *r = this->GradientShader->GetRedDiffuseShadingTable(vol);
+    float *g = this->GradientShader->GetGreenDiffuseShadingTable(vol);
+    float *b = this->GradientShader->GetBlueDiffuseShadingTable(vol);
+
+    float *rptr = r;
+    float *gptr = g;
+    float *bptr = b;
+
+    unsigned short *tablePtr = this->DiffuseShadingTable[c];
+
+    int i;
+    for ( i = 0; i < this->DirectionEncoder->GetNumberOfEncodedDirections(); i++ )
+      {
+      *(tablePtr++) = static_cast<unsigned short>((*(rptr++))*VTKKW_FP_SCALE + 0.5);
+      *(tablePtr++) = static_cast<unsigned short>((*(gptr++))*VTKKW_FP_SCALE + 0.5);
+      *(tablePtr++) = static_cast<unsigned short>((*(bptr++))*VTKKW_FP_SCALE + 0.5);
+      }
+
+    r = this->GradientShader->GetRedSpecularShadingTable(vol);
+    g = this->GradientShader->GetGreenSpecularShadingTable(vol);
+    b = this->GradientShader->GetBlueSpecularShadingTable(vol);
+
+    rptr = r;
+    gptr = g;
+    bptr = b;
+
+    tablePtr = this->SpecularShadingTable[c];
+
+
+    for ( i = 0; i < this->DirectionEncoder->GetNumberOfEncodedDirections(); i++ )
+      {
+      *(tablePtr++) = static_cast<unsigned short>((*(rptr++))*VTKKW_FP_SCALE + 0.5);
+      *(tablePtr++) = static_cast<unsigned short>((*(gptr++))*VTKKW_FP_SCALE + 0.5);
+      *(tablePtr++) = static_cast<unsigned short>((*(bptr++))*VTKKW_FP_SCALE + 0.5);
+      }
+    }
+
+  return 1;
+}
+
+int vtkCropVolumeRayCastMapper::UpdateGradients( vtkVolume *vol )
+{
+  int needToUpdate = 0;
+
+  this->GradientOpacityRequired = 0;
+  this->ShadingRequired         = 0;
+
+  // Get the image data
+  vtkImageData *input = this->GetInput();
+
+  if ( vol->GetProperty()->GetShade() )
+    {
+    needToUpdate = 1;
+    this->ShadingRequired = 1;
+    }
+
+  for ( int c = 0; c < this->CurrentScalars->GetNumberOfComponents(); c++ )
+    {
+    vtkPiecewiseFunction *f = vol->GetProperty()->GetGradientOpacity(c);
+    if ( strcmp(f->GetType(), "Constant") || f->GetValue(0.0) != 1.0 )
+      {
+      needToUpdate = 1;
+      this->GradientOpacityRequired = 1;
+      }
+    }
+
+  if ( !needToUpdate )
+    {
+    return 0;
+    }
+
+  // Check if the input has changed
+  if ( input == this->SavedGradientsInput &&
+       this->CurrentScalars == this->PreviousScalars &&
+       input->GetMTime() < this->SavedGradientsMTime.GetMTime() )
+    {
+    return 0;
+    }
+
+  this->ComputeGradients( vol );
+
+  // Time to save the input used to update the tabes
+  this->SavedGradientsInput = this->GetInput();
+  this->SavedGradientsMTime.Modified();
+
+  return 1;
+}
+
+int vtkCropVolumeRayCastMapper::UpdateColorTable( vtkVolume *vol )
+{
+  int needToUpdate = 0;
+
+  // Get the image data
+  vtkImageData *input = this->GetInput();
+
+  // Has the data itself changed?
+  if ( input != this->SavedParametersInput ||
+       this->CurrentScalars != this->PreviousScalars ||
+       input->GetMTime() > this->SavedParametersMTime.GetMTime() )
+    {
+    needToUpdate = 1;
+    }
+
+  // What is the blending mode?
+  int blendMode = this->GetBlendMode();
+  if ( blendMode != this->SavedBlendMode )
+    {
+    needToUpdate = 1;
+
+    if ( this->GetBlendMode() == vtkVolumeMapper::MINIMUM_INTENSITY_BLEND )
+      {
+      this->FlipMIPComparison = 1;
+      }
+    else
+      {
+      this->FlipMIPComparison = 0;
+      }
+    }
+
+  // How many components?
+  int components = this->CurrentScalars->GetNumberOfComponents();
+
+  // Has the sample distance changed?
+  if ( this->SavedSampleDistance != this->SampleDistance )
+    {
+    needToUpdate = 1;
+    }
+
+  vtkColorTransferFunction *rgbFunc[4];
+  vtkPiecewiseFunction     *grayFunc[4];
+  vtkPiecewiseFunction     *scalarOpacityFunc[4];
+  vtkPiecewiseFunction     *gradientOpacityFunc[4];
+  int                       colorChannels[4];
+  float                     scalarOpacityDistance[4];
+
+  int c;
+
+  for ( c = 0; c < ((vol->GetProperty()->GetIndependentComponents())?(components):(1)); c++ )
+    {
+    colorChannels[c]         = vol->GetProperty()->GetColorChannels(c);
+    if ( colorChannels[c] == 1 )
+      {
+      rgbFunc[c]               = NULL;
+      grayFunc[c]              = vol->GetProperty()->GetGrayTransferFunction(c);
+      }
+    else
+      {
+      rgbFunc[c]               = vol->GetProperty()->GetRGBTransferFunction(c);
+      grayFunc[c]              = NULL;
+      }
+    scalarOpacityFunc[c]     = vol->GetProperty()->GetScalarOpacity(c);
+    gradientOpacityFunc[c]   = vol->GetProperty()->GetGradientOpacity(c);
+    scalarOpacityDistance[c] = vol->GetProperty()->GetScalarOpacityUnitDistance(c);
+
+    // Has the number of color channels changed?
+    if ( this->SavedColorChannels[c] != colorChannels[c] )
+      {
+      needToUpdate = 1;
+      }
+
+    // Has the color transfer function changed in some way,
+    // and we are using it?
+    if ( colorChannels[c] == 3 )
+      {
+      if ( this->SavedRGBFunction[c] != rgbFunc[c] ||
+           this->SavedParametersMTime.GetMTime() < rgbFunc[c]->GetMTime() )
+        {
+        needToUpdate = 1;
+        }
+      }
+
+    // Has the gray transfer function changed in some way,
+    // and we are using it?
+    if ( colorChannels[c] == 1 )
+      {
+      if ( this->SavedGrayFunction[c] != grayFunc[c] ||
+           this->SavedParametersMTime.GetMTime() < grayFunc[c]->GetMTime() )
+        {
+        needToUpdate = 1;
+        }
+      }
+
+    // Has the scalar opacity transfer function changed in some way?
+    if ( this->SavedScalarOpacityFunction[c] != scalarOpacityFunc[c] ||
+         this->SavedParametersMTime.GetMTime() < scalarOpacityFunc[c]->GetMTime() )
+      {
+      needToUpdate = 1;
+      }
+
+    // Has the gradient opacity transfer function changed in some way?
+    if ( this->SavedGradientOpacityFunction[c] != gradientOpacityFunc[c] ||
+         this->SavedParametersMTime.GetMTime() < gradientOpacityFunc[c]->GetMTime() )
+      {
+      needToUpdate = 1;
+      }
+
+    // Has the distance over which the scalar opacity function is defined changed?
+    if ( this->SavedScalarOpacityDistance[c] != scalarOpacityDistance[c] )
+      {
+      needToUpdate = 1;
+      }
+    }
+
+  // If we have not found any need to update, return now
+  if ( !needToUpdate )
+    {
+    return 0;
+    }
+
+
+  for ( c = 0; c < ((vol->GetProperty()->GetIndependentComponents())?(components):(1)); c++ )
+    {
+    this->SavedRGBFunction[c]             = rgbFunc[c];
+    this->SavedGrayFunction[c]            = grayFunc[c];
+    this->SavedScalarOpacityFunction[c]   = scalarOpacityFunc[c];
+    this->SavedGradientOpacityFunction[c] = gradientOpacityFunc[c];
+    this->SavedColorChannels[c]           = colorChannels[c];
+    this->SavedScalarOpacityDistance[c]   = scalarOpacityDistance[c];
+    }
+
+  this->SavedSampleDistance          = this->SampleDistance;
+  this->SavedBlendMode               = blendMode;
+  this->SavedParametersInput         = input;
+
+  this->SavedParametersMTime.Modified();
+
+  int scalarType = this->CurrentScalars->GetDataType();
+
+  int i;
+  float tmpArray[3*32768];
+
+  // Find the scalar range
+  double scalarRange[4][2];
+  for ( c = 0; c < components; c++ )
+    {
+    this->CurrentScalars->GetRange(scalarRange[c], c);
+
+    // Is the difference between max and min less than 32768? If so, and if
+    // the data is not of float or double type, use a simple offset mapping.
+    // If the difference between max and min is 32768 or greater, or the data
+    // is of type float or double, we must use an offset / scaling mapping.
+    // In this case, the array size will be 32768 - we need to figure out the
+    // offset and scale factor.
+    float offset;
+    float scale;
+
+    int arraySizeNeeded;
+
+    if ( scalarType == VTK_FLOAT ||
+         scalarType == VTK_DOUBLE ||
+         scalarRange[c][1] - scalarRange[c][0] > 32767 )
+      {
+      arraySizeNeeded = 32768;
+      offset          = -scalarRange[c][0];
+
+      if ( scalarRange[c][1] - scalarRange[c][0] )
+        {
+        scale = 32767.0 / (scalarRange[c][1] - scalarRange[c][0]);
+        }
+      else
+        {
+        scale = 1.0;
+        }
+      }
+    else
+      {
+      arraySizeNeeded = (int)(scalarRange[c][1] - scalarRange[c][0] + 1);
+      offset          = -scalarRange[c][0];
+      scale           = 1.0;
+      }
+
+    this->TableSize[c]   = arraySizeNeeded;
+    this->TableShift[c]  = offset;
+    this->TableScale[c]  = scale;
+    }
+
+  if ( vol->GetProperty()->GetIndependentComponents() )
+    {
+    for ( c = 0; c < components; c++ )
+      {
+      // Sample the transfer functions between the min and max.
+      if ( colorChannels[c] == 1 )
+        {
+        float tmpArray2[32768];
+        grayFunc[c]->GetTable( scalarRange[c][0], scalarRange[c][1],
+                               this->TableSize[c], tmpArray2 );
+        for ( int index = 0; index < this->TableSize[c]; index++ )
+          {
+          tmpArray[3*index  ] = tmpArray2[index];
+          tmpArray[3*index+1] = tmpArray2[index];
+          tmpArray[3*index+2] = tmpArray2[index];
+          }
+        }
+      else
+        {
+        rgbFunc[c]->GetTable( scalarRange[c][0], scalarRange[c][1],
+                              this->TableSize[c], tmpArray );
+        }
+      // Convert color to short format
+      for ( i = 0; i < this->TableSize[c]; i++ )
+        {
+        this->ColorTable[c][3*i  ] =
+          static_cast<unsigned short>(tmpArray[3*i  ]*VTKKW_FP_SCALE + 0.5);
+        this->ColorTable[c][3*i+1] =
+          static_cast<unsigned short>(tmpArray[3*i+1]*VTKKW_FP_SCALE + 0.5);
+        this->ColorTable[c][3*i+2] =
+          static_cast<unsigned short>(tmpArray[3*i+2]*VTKKW_FP_SCALE + 0.5);
+        }
+
+      scalarOpacityFunc[c]->GetTable( scalarRange[c][0], scalarRange[c][1],
+                                   this->TableSize[c], tmpArray );
+
+      // Correct the opacity array for the spacing between the planes if we are
+      // using a composite blending operation
+      if ( this->BlendMode == vtkVolumeMapper::COMPOSITE_BLEND )
+        {
+        float *ptr = tmpArray;
+        double factor;
+          {
+          factor = this->SampleDistance / vol->GetProperty()->GetScalarOpacityUnitDistance(c);
+          }
+
+        for ( i = 0; i < this->TableSize[c]; i++ )
+          {
+          if ( *ptr > 0.0001 )
+            {
+            *ptr =  1.0-pow((double)(1.0-(*ptr)),factor);
+            }
+          ptr++;
+          }
+        }
+
+      // Convert tables to short format
+      for ( i = 0; i < this->TableSize[c]; i++ )
+        {
+        this->ScalarOpacityTable[c][i] =
+          static_cast<unsigned short>(tmpArray[i]*VTKKW_FP_SCALE + 0.5);
+        }
+
+      if ( scalarRange[c][1] - scalarRange[c][0] )
+        {
+        gradientOpacityFunc[c]->GetTable( 0,
+                                          (scalarRange[c][1] - scalarRange[c][0])*0.25,
+                                          256, tmpArray );
+
+        for ( i = 0; i < 256; i++ )
+          {
+          this->GradientOpacityTable[c][i] =
+            static_cast<unsigned short>(tmpArray[i]*VTKKW_FP_SCALE + 0.5);
+          }
+        }
+      else
+        {
+        for ( i = 0; i < 256; i++ )
+          {
+          this->GradientOpacityTable[c][i] = 0x0000;
+          }
+        }
+      }
+    }
+  else
+    {
+    if ( components ==  2 )
+      {
+      // Sample the transfer functions between the min and max.
+      if ( colorChannels[0] == 1 )
+        {
+        float tmpArray2[32768];
+        grayFunc[0]->GetTable( scalarRange[0][0], scalarRange[0][1],
+                               this->TableSize[0], tmpArray2 );
+        for ( int index = 0; index < this->TableSize[0]; index++ )
+          {
+          tmpArray[3*index  ] = tmpArray2[index];
+          tmpArray[3*index+1] = tmpArray2[index];
+          tmpArray[3*index+2] = tmpArray2[index];
+          }
+        }
+      else
+        {
+        rgbFunc[0]->GetTable( scalarRange[0][0], scalarRange[0][1],
+                           this->TableSize[0], tmpArray );
+        }
+
+      // Convert color to short format
+      for ( i = 0; i < this->TableSize[0]; i++ )
+        {
+        this->ColorTable[0][3*i  ] =
+          static_cast<unsigned short>(tmpArray[3*i  ]*VTKKW_FP_SCALE + 0.5);
+        this->ColorTable[0][3*i+1] =
+          static_cast<unsigned short>(tmpArray[3*i+1]*VTKKW_FP_SCALE + 0.5);
+        this->ColorTable[0][3*i+2] =
+          static_cast<unsigned short>(tmpArray[3*i+2]*VTKKW_FP_SCALE + 0.5);
+        }
+      }
+
+    // The opacity table is indexed with the last component
+    scalarOpacityFunc[0]->GetTable( scalarRange[components-1][0], scalarRange[components-1][1],
+                                    this->TableSize[components-1], tmpArray );
+
+    // Correct the opacity array for the spacing between the planes if we are
+    // using a composite blending operation
+    if ( this->BlendMode == vtkVolumeMapper::COMPOSITE_BLEND )
+      {
+      float *ptr = tmpArray;
+      double factor =
+        this->SampleDistance / vol->GetProperty()->GetScalarOpacityUnitDistance();
+      for ( i = 0; i < this->TableSize[components-1]; i++ )
+        {
+        if ( *ptr > 0.0001 )
+          {
+          *ptr =  1.0-pow((double)(1.0-(*ptr)),factor);
+          }
+        ptr++;
+        }
+      }
+
+      // Convert tables to short format
+      for ( i = 0; i < this->TableSize[components-1]; i++ )
+        {
+        this->ScalarOpacityTable[0][i] =
+          static_cast<unsigned short>(tmpArray[i]*VTKKW_FP_SCALE + 0.5);
+        }
+
+      if ( scalarRange[components-1][1] - scalarRange[components-1][0] )
+        {
+        gradientOpacityFunc[0]->GetTable( 0,
+                                          (scalarRange[components-1][1] -
+                                           scalarRange[components-1][0])*0.25,
+                                          256, tmpArray );
+
+        for ( i = 0; i < 256; i++ )
+          {
+          this->GradientOpacityTable[0][i] =
+            static_cast<unsigned short>(tmpArray[i]*VTKKW_FP_SCALE + 0.5);
+          }
+        }
+      else
+        {
+        for ( i = 0; i < 256; i++ )
+          {
+          this->GradientOpacityTable[0][i] = 0x0000;
+          }
+        }
+    }
+
+  return 1;
+}
+
+
+int vtkCropVolumeRayCastMapper::ShouldUseNearestNeighborInterpolation( vtkVolume *vol )
+{
+//  return ( this->UseShortCuts ||
+//           vol->GetProperty()->GetInterpolationType() == VTK_NEAREST_INTERPOLATION );
+  return ( vol->GetProperty()->GetInterpolationType() == VTK_NEAREST_INTERPOLATION );
+}
+
+// Print method for vtkCropVolumeRayCastMapper
+void vtkCropVolumeRayCastMapper::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+
+  os << indent << "Sample Distance: " << this->SampleDistance << endl;
+  os << indent << "Interactive Sample Distance: "
+     << this->InteractiveSampleDistance << endl;
+  os << indent << "Image Sample Distance: "
+     << this->ImageSampleDistance << endl;
+  os << indent << "Minimum Image Sample Distance: "
+     << this->MinimumImageSampleDistance << endl;
+  os << indent << "Maximum Image Sample Distance: "
+     << this->MaximumImageSampleDistance << endl;
+  os << indent << "Auto Adjust Sample Distances: "
+     << this->AutoAdjustSampleDistances << endl;
+  os << indent << "LockSampleDistanceToInputSpacing: "
+    << (this->LockSampleDistanceToInputSpacing ? "On\n" : "Off\n");
+  os << indent << "Intermix Intersecting Geometry: "
+    << (this->IntermixIntersectingGeometry ? "On\n" : "Off\n");
+  os << indent << "Final Color Window: " << this->FinalColorWindow << endl;
+  os << indent << "Final Color Level: " << this->FinalColorLevel << endl;
+
+  // These are all things that shouldn't be printed....
+  //os << indent << "ShadingRequired: " << this->ShadingRequired << endl;
+  //os << indent << "GradientOpacityRequired: " << this->GradientOpacityRequired
+  //   << endl;
+
+  //os << indent << "CurrentScalars: " << this->CurrentScalars << endl;
+  //os << indent << "PreviousScalars: " << this->PreviousScalars << endl;
+
+  //if ( this->RayCastImage )
+  //  {
+  //  os << indent << "Ray Cast Image:\n";
+  //  this->RayCastImage->PrintSelf(os,indent.GetNextIndent());
+  //  }
+  //else
+  //  {
+  //  os << indent << "Ray Cast Image: (none)\n";
+  //  }
+
+  //os << indent << "RenderWindow: " << this->RenderWindow << endl;
+
+  //os << indent << "CompositeHelper: " << this->CompositeHelper << endl;
+  //os << indent << "CompositeShadeHelper: " << this->CompositeShadeHelper << endl;
+  //os << indent << "CompositeGOHelper: " << this->CompositeGOHelper << endl;
+  //os << indent << "CompositeGOShadeHelper: " << this->CompositeGOShadeHelper << endl;
+  //os << indent << "MIPHelper: " << this->MIPHelper << endl;
+
+  //os << indent << "TableShift: " << this->TableShift[0] << " "
+  //   << this->TableShift[1] << " " << this->TableShift[2] << " "
+  //   << this->TableShift[3] << endl;
+  //os << indent << "TableScale: " << this->TableScale[0] << " "
+  //   << this->TableScale[1] << " " << this->TableScale[2] << " "
+  //   << this->TableScale[3] << endl;
+
+  // os << indent << "Flip Mip Comparison" << this->FlipMIPComparison << end;"
+}
+
+
+void vtkCropVolumeRayCastMapper::SetIrregularCropCylinderDimensions(double radius, double height, double dir_vector[3])
+{
+	FixedCylinderRadius = radius;
+	FixedCylinderHeight = height;
+	for(int ia=0;ia<3;ia++)
+		FixedCylinderAxis[ia] = dir_vector[ia];
+};
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastMapper.h b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastMapper.h
new file mode 100644
index 0000000..6871bee
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkCropVolumeRayCastMapper.h
@@ -0,0 +1,825 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkCropVolumeRayCastMapper.h,v $
+
+  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 vtkCropVolumeRayCastMapper - A fixed point mapper for volumes
+// .SECTION Description
+// This is a software ray caster for rendering volumes in vtkImageData.
+// It works with all input data types and up to four components. It performs
+// composite or MIP rendering, and can be intermixed with geometric data.
+// Space leaping is used to speed up the rendering process. In addition,
+// calculation are performed in 15 bit fixed point precision. This mapper
+// is threaded, and will interleave scan lines across processors.
+//
+// This mapper is a good replacement for vtkVolumeRayCastMapper EXCEPT:
+//   - it does not do isosurface ray casting
+//   - it does only interpolate before classify compositing
+//   - it does only maximum scalar value MIP
+//
+// The vtkVolumeRayCastMapper CANNOT be used in these instances when a
+// vtkCropVolumeRayCastMapper can be used:
+//   - if the data is not unsigned char or unsigned short
+//   - if the data has more than one component
+//
+// This mapper handles all data type from unsigned char through double.
+// However, some of the internal calcultions are performed in float and
+// therefore even the full float range may cause problems for this mapper
+// (both in scalar data values and in spacing between samples).
+//
+// Space leaping is performed by creating a sub-sampled volume. 4x4x4
+// cells in the original volume are represented by a min, max, and
+// combined gradient and flag value. The min max volume has three
+// unsigned shorts per 4x4x4 group of cells from the original volume -
+// one reprenting the minumum scalar index (the scalar value adjusted
+// to fit in the 15 bit range), the maximum scalar index, and a
+// third unsigned short which is both the maximum gradient opacity in
+// the neighborhood (an unsigned char) and the flag that is filled
+// in for the current lookup tables to indicate whether this region
+// can be skipped.
+
+// .SECTION see also
+// vtkVolumeMapper
+
+#ifndef __vtkCropVolumeRayCastMapper_h
+#define __vtkCropVolumeRayCastMapper_h
+
+#include "vtkVolumeMapper.h"
+
+#define VTKKW_FP_SHIFT       15
+#define VTKKW_FPMM_SHIFT     17
+#define VTKKW_FP_MASK        0x7fff
+#define VTKKW_FP_SCALE       32767.0
+
+class vtkMatrix4x4;
+class vtkMultiThreader;
+class vtkPlaneCollection;
+class vtkRenderer;
+class vtkTimerLog;
+class vtkVolume;
+class vtkTransform;
+class vtkRenderWindow;
+class vtkColorTransferFunction;
+class vtkPiecewiseFunction;
+class vtkFixedPointVolumeRayCastMIPHelper;
+class vtkCropVolumeRayCastCompositeHelper;
+class vtkCropVolumeRayCastCompositeGOHelper;
+class vtkCropVolumeRayCastCompositeGOShadeHelper;
+class vtkCropVolumeRayCastCompositeShadeHelper;
+class vtkDirectionEncoder;
+class vtkEncodedGradientShader;
+class vtkFiniteDifferenceGradientEstimator;
+class vtkRayCastImageDisplayHelper;
+class vtkFixedPointRayCastImage;
+class vtkDataArray;
+
+//BTX
+// Forward declaration needed for use by friend declaration below.
+VTK_THREAD_RETURN_TYPE CropFixedPointVolumeRayCastMapper_CastRays( void *arg );
+VTK_THREAD_RETURN_TYPE vtkCropFPVRCMSwitchOnDataType( void *arg );
+//ETX
+
+class  vtkCropVolumeRayCastMapper : public vtkVolumeMapper
+{
+public:
+  static vtkCropVolumeRayCastMapper *New();
+  vtkTypeRevisionMacro(vtkCropVolumeRayCastMapper,vtkVolumeMapper);
+  void PrintSelf( ostream& os, vtkIndent indent );
+
+  // Description:
+  // Set/Get the distance between samples used for rendering
+  // when AutoAdjustSampleDistances is off, or when this mapper
+  // has more than 1 second allocated to it for rendering.
+  vtkSetMacro( SampleDistance, float );
+  vtkGetMacro( SampleDistance, float );
+
+  // Description:
+  // Set/Get the distance between samples when interactive rendering is happening.
+  // In this case, interactive is defined as this volume mapper having less than 1
+  // second allocated for rendering. When AutoAdjustSampleDistance is On, and the
+  // allocated render time is less than 1 second, then this InteractiveSampleDistance
+  // will be used instead of the SampleDistance above.
+  vtkSetMacro( InteractiveSampleDistance, float );
+  vtkGetMacro( InteractiveSampleDistance, float );
+
+  // Description:
+  // Sampling distance in the XY image dimensions. Default value of 1 meaning
+  // 1 ray cast per pixel. If set to 0.5, 4 rays will be cast per pixel. If
+  // set to 2.0, 1 ray will be cast for every 4 (2 by 2) pixels. This value
+  // will be adjusted to meet a desired frame rate when AutoAdjustSampleDistances
+  // is on.
+  vtkSetClampMacro( ImageSampleDistance, float, 0.1f, 100.0f );
+  vtkGetMacro( ImageSampleDistance, float );
+
+  // Description:
+  // This is the minimum image sample distance allow when the image
+  // sample distance is being automatically adjusted.
+  vtkSetClampMacro( MinimumImageSampleDistance, float, 0.1f, 100.0f );
+  vtkGetMacro( MinimumImageSampleDistance, float );
+
+  // Description:
+  // This is the maximum image sample distance allow when the image
+  // sample distance is being automatically adjusted.
+  vtkSetClampMacro( MaximumImageSampleDistance, float, 0.1f, 100.0f );
+  vtkGetMacro( MaximumImageSampleDistance, float );
+
+  // Description:
+  // If AutoAdjustSampleDistances is on, the the ImageSampleDistance
+  // and the SampleDistance will be varied to achieve the allocated
+  // render time of this prop (controlled by the desired update rate
+  // and any culling in use). If this is an interactive render (more
+  // than 1 frame per second) the SampleDistance will be increased,
+  // otherwise it will not be altered (a binary decision, as opposed
+  // to the ImageSampleDistance which will vary continuously).
+  vtkSetClampMacro( AutoAdjustSampleDistances, int, 0, 1 );
+  vtkGetMacro( AutoAdjustSampleDistances, int );
+  vtkBooleanMacro( AutoAdjustSampleDistances, int );
+
+  // Description:
+  // Automatically compute the sample distance from the data spacing.  When
+  // the number of voxels is 8, the sample distance will be roughly 1/200
+  // the average voxel size. The distance will grow proportionally to
+  // numVoxels^(1/3) until it reaches 1/2 average voxel size when number of
+  // voxels is 1E6. Note that ScalarOpacityUnitDistance is still taken into
+  // account and if different than 1, will effect the sample distance.
+  vtkSetClampMacro( LockSampleDistanceToInputSpacing, int, 0, 1 );
+  vtkGetMacro( LockSampleDistanceToInputSpacing, int );
+  vtkBooleanMacro( LockSampleDistanceToInputSpacing, int );
+
+  // Description:
+  // Set/Get the number of threads to use. This by default is equal to
+  // the number of available processors detected.
+  void SetNumberOfThreads( int num );
+  int GetNumberOfThreads();
+
+  // Description:
+  // If IntermixIntersectingGeometry is turned on, the zbuffer will be
+  // captured and used to limit the traversal of the rays.
+  vtkSetClampMacro( IntermixIntersectingGeometry, int, 0, 1 );
+  vtkGetMacro( IntermixIntersectingGeometry, int );
+  vtkBooleanMacro( IntermixIntersectingGeometry, int );
+
+  // Description:
+  // What is the image sample distance required to achieve the desired time?
+  // A version of this method is provided that does not require the volume
+  // argument since if you are using an LODProp3D you may not know this information.
+  // If you use this version you must be certain that the ray cast mapper is
+  // only used for one volume (and not shared among multiple volumes)
+  float ComputeRequiredImageSampleDistance( float desiredTime,
+                                            vtkRenderer *ren );
+  float ComputeRequiredImageSampleDistance( float desiredTime,
+                                            vtkRenderer *ren,
+                                            vtkVolume *vol );
+
+//BTX
+  // Description:
+  // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE
+  // Initialize rendering for this volume.
+  void Render( vtkRenderer *, vtkVolume * );
+
+  unsigned int ToFixedPointPosition( float val );
+  void ToFixedPointPosition( float in[3], unsigned int out[3] );
+  unsigned int ToFixedPointDirection( float dir );
+  void ToFixedPointDirection( float in[3], unsigned int out[3] );
+  void FixedPointIncrement( unsigned int position[3], unsigned int increment[3] );
+  void GetFloatTripleFromPointer( float v[3], float *ptr );
+  void GetUIntTripleFromPointer( unsigned int v[3], unsigned int *ptr );
+  void ShiftVectorDown( unsigned int in[3], unsigned int out[3] );
+  int CheckMinMaxVolumeFlag( unsigned int pos[3], int c );
+  int CheckMIPMinMaxVolumeFlag( unsigned int pos[3], int c, unsigned short maxIdx, int flip );
+
+  void LookupColorUC( unsigned short *colorTable,
+                      unsigned short *scalarOpacityTable,
+                      unsigned short index,
+                      unsigned char  color[4] );
+  void LookupDependentColorUC( unsigned short *colorTable,
+                               unsigned short *scalarOpacityTable,
+                               unsigned short index[4],
+                               int            components,
+                               unsigned char  color[4] );
+  void LookupAndCombineIndependentColorsUC(
+    unsigned short *colorTable[4],
+    unsigned short *scalarOpacityTable[4],
+    unsigned short index[4],
+    float          weights[4],
+    int            components,
+    unsigned char  color[4] );
+  int CheckIfCropped( unsigned int pos[3] );
+
+//ETX
+
+//BTX
+  
+  /*void SetSphereCenter(double center[3]);
+  void GetSphereCenter(double SphereCenter[3]);*/
+
+  //void SelectIrregularShape(int selection);
+  //void SetIrregularCropCubeLength(double cubelengthX, double cubelengthY, double cubelengthZ) ;
+  //void SetIrregularCropEllipseSize(double radiusx, double radiusy, double radiusz);
+  void SetIrregularCropCylinderDimensions(double radius, double height, double dir_vector[3]);
+
+  vtkSetVector3Macro(FixedEllipseRadius, double);
+  vtkGetVectorMacro(FixedEllipseRadius, double,3);
+
+  vtkSetVector3Macro(FixedCylinderAxis, double);
+  vtkGetVectorMacro(FixedCylinderAxis, double,3);
+
+  vtkSetVector3Macro(FixedCubeLength, double);
+  vtkGetVectorMacro(FixedCubeLength, double,3);
+
+  vtkSetVector3Macro(FixedSphereCenter, double);
+  vtkGetVectorMacro(FixedSphereCenter, double,3);
+
+  vtkSetMacro( FixedSphereRadius,  double);
+  vtkGetMacro( FixedSphereRadius,  double);
+
+  vtkSetMacro( FixedCylinderHeight,  double);
+  vtkGetMacro( FixedCylinderHeight,  double);
+
+  vtkSetMacro( FunctionalCropOn,  int);
+  vtkGetMacro( FunctionalCropOn,  int);
+
+
+  vtkSetMacro( FixedCylinderRadius,  double );
+  vtkGetMacro( FixedCylinderRadius,  double);
+
+  vtkSetMacro( ProbeShape,  int );
+  vtkGetMacro( ProbeShape,  int);
+
+
+  double FixedSphereRadius;
+  double FixedCubeLength[3];
+  double FixedEllipseRadius[3];
+  double FixedCylinderRadius, FixedCylinderHeight;
+  double FixedCylinderAxis[3];
+  int ProbeShape;
+  double FixedSphereCenter[3];
+  int FunctionalCropOn; 
+
+//ETX
+
+  vtkGetObjectMacro( RenderWindow, vtkRenderWindow );
+  vtkGetObjectMacro( MIPHelper, vtkFixedPointVolumeRayCastMIPHelper );
+  vtkGetObjectMacro( CompositeHelper, vtkCropVolumeRayCastCompositeHelper );
+  vtkGetObjectMacro( CompositeGOHelper, vtkCropVolumeRayCastCompositeGOHelper );
+  vtkGetObjectMacro( CompositeGOShadeHelper, vtkCropVolumeRayCastCompositeGOShadeHelper );
+  vtkGetObjectMacro( CompositeShadeHelper, vtkCropVolumeRayCastCompositeShadeHelper );
+  vtkGetVectorMacro( TableShift, float, 4 );
+  vtkGetVectorMacro( TableScale, float, 4 );
+  vtkGetMacro( ShadingRequired, int );
+  vtkGetMacro( GradientOpacityRequired, int );
+
+  vtkGetObjectMacro( CurrentScalars, vtkDataArray );
+  vtkGetObjectMacro( PreviousScalars, vtkDataArray );
+
+
+  int             *GetRowBounds()                 {return this->RowBounds;}
+  unsigned short  *GetColorTable(int c)           {return this->ColorTable[c];}
+  unsigned short  *GetScalarOpacityTable(int c)   {return this->ScalarOpacityTable[c];}
+  unsigned short  *GetGradientOpacityTable(int c) {return this->GradientOpacityTable[c];}
+  vtkVolume       *GetVolume()                    {return this->Volume;}
+  unsigned short **GetGradientNormal()            {return this->GradientNormal;}
+  unsigned char  **GetGradientMagnitude()         {return this->GradientMagnitude;}
+  unsigned short  *GetDiffuseShadingTable(int c)  {return this->DiffuseShadingTable[c];}
+  unsigned short  *GetSpecularShadingTable(int c) {return this->SpecularShadingTable[c];}
+
+  void ComputeRayInfo( int x, int y,
+                       unsigned int pos[3],
+                       unsigned int dir[3],
+                       unsigned int *numSteps );
+
+  void InitializeRayInfo( vtkVolume *vol );
+
+  int ShouldUseNearestNeighborInterpolation( vtkVolume *vol );
+
+  // Description:
+  // Set / Get the underlying image object. One will be automatically
+  // created - only need to set it when using from an AMR mapper which
+  // renders multiple times into the same image.
+  void SetRayCastImage( vtkFixedPointRayCastImage * );
+  vtkGetObjectMacro( RayCastImage, vtkFixedPointRayCastImage  );
+
+  int PerImageInitialization( vtkRenderer *, vtkVolume *, int,
+                              double *, double *, int * );
+  void PerVolumeInitialization( vtkRenderer *, vtkVolume * );
+  void PerSubVolumeInitialization( vtkRenderer *, vtkVolume *, int );
+  void RenderSubVolume();
+  void DisplayRenderedImage( vtkRenderer *, vtkVolume * );
+  void AbortRender();
+
+  void CreateCanonicalView( vtkVolume *volume,
+                            vtkImageData *image,
+                            int blend_mode,
+                            double viewDirection[3],
+                            double viewUp[3] );
+
+  // Description:
+  // Get an estimate of the rendering time for a given volume / renderer.
+  // Only valid if this mapper has been used to render that volume for
+  // that renderer previously. Estimate is good when the viewing parameters
+  // have not changed much since that last render.
+  float GetEstimatedRenderTime( vtkRenderer *ren,
+                                vtkVolume   *vol )
+    { return this->RetrieveRenderTime( ren, vol ); }
+  float GetEstimatedRenderTime( vtkRenderer *ren )
+    { return this->RetrieveRenderTime( ren ); }
+
+
+  // Description:
+  // Set/Get the window / level applied to the final color.
+  // This allows brightness / contrast adjustments on the
+  // final image.
+  // window is the width of the window.
+  // level is the center of the window.
+  // Initial window value is 1.0
+  // Initial level value is 0.5
+  // window cannot be null but can be negative, this way
+  // values will be reversed.
+  // |window| can be larger than 1.0
+  // level can be any real value.
+  vtkSetMacro( FinalColorWindow, float );
+  vtkGetMacro( FinalColorWindow, float );
+  vtkSetMacro( FinalColorLevel,  float );
+  vtkGetMacro( FinalColorLevel,  float );
+
+
+  // Here to be used by the mapper to tell the helper
+  // to flip the MIP comparison in order to support
+  // minimum intensity blending
+  vtkGetMacro( FlipMIPComparison, int );
+
+protected:
+  vtkCropVolumeRayCastMapper();
+  ~vtkCropVolumeRayCastMapper();
+
+  // The helper class that displays the image
+  vtkRayCastImageDisplayHelper *ImageDisplayHelper;
+
+  // The distance between sample points along the ray
+  float                        SampleDistance;
+  float                        InteractiveSampleDistance;
+
+  // The distance between rays in the image
+  float                        ImageSampleDistance;
+  float                        MinimumImageSampleDistance;
+  float                        MaximumImageSampleDistance;
+  int                          AutoAdjustSampleDistances;
+  int                          LockSampleDistanceToInputSpacing;
+
+  // Saved values used to restore
+  float                        OldSampleDistance;
+  float                        OldImageSampleDistance;
+
+  // Internal method for computing matrices needed during
+  // ray casting
+  void ComputeMatrices( double volumeOrigin[3],
+                        double volumeSpacing[3],
+                        int volumeExtent[6],
+                        vtkRenderer  *ren,
+                        vtkVolume    *vol );
+
+  int ComputeRowBounds( vtkRenderer *ren,
+                        int imageFlag, int rowBoundsFlag,
+                        int volumeExtent[6]);
+
+  void CaptureZBuffer( vtkRenderer *ren );
+
+  friend VTK_THREAD_RETURN_TYPE CropFixedPointVolumeRayCastMapper_CastRays( void *arg );
+  friend VTK_THREAD_RETURN_TYPE vtkCropFPVRCMSwitchOnDataType( void *arg );
+
+  vtkMultiThreader  *Threader;
+
+  vtkMatrix4x4   *PerspectiveMatrix;
+  vtkMatrix4x4   *ViewToWorldMatrix;
+  vtkMatrix4x4   *ViewToVoxelsMatrix;
+  vtkMatrix4x4   *VoxelsToViewMatrix;
+  vtkMatrix4x4   *WorldToVoxelsMatrix;
+  vtkMatrix4x4   *VoxelsToWorldMatrix;
+
+  vtkMatrix4x4   *VolumeMatrix;
+
+  vtkTransform   *PerspectiveTransform;
+  vtkTransform   *VoxelsTransform;
+  vtkTransform   *VoxelsToViewTransform;
+
+  // This object encapsulated the image and all related information
+  vtkFixedPointRayCastImage *RayCastImage;
+
+  int             *RowBounds;
+  int             *OldRowBounds;
+
+  float           *RenderTimeTable;
+  vtkVolume      **RenderVolumeTable;
+  vtkRenderer    **RenderRendererTable;
+  int              RenderTableSize;
+  int              RenderTableEntries;
+
+  void             StoreRenderTime( vtkRenderer *ren, vtkVolume *vol, float t );
+  float            RetrieveRenderTime( vtkRenderer *ren, vtkVolume *vol );
+  float            RetrieveRenderTime( vtkRenderer *ren );
+
+  int              IntermixIntersectingGeometry;
+
+  float            MinimumViewDistance;
+
+  vtkColorTransferFunction *SavedRGBFunction[4];
+  vtkPiecewiseFunction     *SavedGrayFunction[4];
+  vtkPiecewiseFunction     *SavedScalarOpacityFunction[4];
+  vtkPiecewiseFunction     *SavedGradientOpacityFunction[4];
+  int                       SavedColorChannels[4];
+  float                     SavedScalarOpacityDistance[4];
+  int                       SavedBlendMode;
+  vtkImageData             *SavedParametersInput;
+  vtkTimeStamp              SavedParametersMTime;
+
+  vtkImageData             *SavedGradientsInput;
+  vtkTimeStamp              SavedGradientsMTime;
+
+  float                     SavedSampleDistance;
+
+
+  unsigned short            ColorTable[4][32768*3];
+  unsigned short            ScalarOpacityTable[4][32768];
+  unsigned short            GradientOpacityTable[4][256];
+  int                       TableSize[4];
+  float                     TableScale[4];
+  float                     TableShift[4];
+
+  float                     GradientMagnitudeScale[4];
+  float                     GradientMagnitudeShift[4];
+
+  unsigned short           **GradientNormal;
+  unsigned char            **GradientMagnitude;
+  unsigned short            *ContiguousGradientNormal;
+  unsigned char             *ContiguousGradientMagnitude;
+
+  int                        NumberOfGradientSlices;
+
+  vtkDirectionEncoder       *DirectionEncoder;
+
+  vtkEncodedGradientShader  *GradientShader;
+
+  vtkFiniteDifferenceGradientEstimator *GradientEstimator;
+
+  unsigned short             DiffuseShadingTable [4][65536*3];
+  unsigned short             SpecularShadingTable[4][65536*3];
+
+  int                        ShadingRequired;
+  int                        GradientOpacityRequired;
+
+  vtkDataArray              *CurrentScalars;
+  vtkDataArray              *PreviousScalars;
+
+  vtkRenderWindow           *RenderWindow;
+  vtkVolume                 *Volume;
+
+  int           ClipRayAgainstVolume( float rayStart[3],
+                                      float rayEnd[3],
+                                      float rayDirection[3],
+                                      double bounds[6] );
+
+  int           UpdateColorTable( vtkVolume *vol );
+  int           UpdateGradients( vtkVolume *vol );
+  int           UpdateShadingTable( vtkRenderer *ren,
+                                    vtkVolume *vol );
+  void          UpdateCroppingRegions();
+
+  void          ComputeGradients( vtkVolume *vol );
+
+  int           ClipRayAgainstClippingPlanes( float  rayStart[3],
+                                              float  rayEnd[3],
+                                              int    numClippingPlanes,
+                                              float *clippingPlanes );
+
+  unsigned int  FixedPointCroppingRegionPlanes[6];
+  unsigned int  CroppingRegionMask[27];
+
+  // Get the ZBuffer value corresponding to location (x,y) where (x,y)
+  // are indexing into the ImageInUse image. This must be converted to
+  // the zbuffer image coordinates. Nearest neighbor value is returned.
+  float         GetZBufferValue( int x, int y );
+
+  vtkFixedPointVolumeRayCastMIPHelper              *MIPHelper;
+  vtkCropVolumeRayCastCompositeHelper        *CompositeHelper;
+  vtkCropVolumeRayCastCompositeGOHelper      *CompositeGOHelper;
+  vtkCropVolumeRayCastCompositeShadeHelper   *CompositeShadeHelper;
+  vtkCropVolumeRayCastCompositeGOShadeHelper *CompositeGOShadeHelper;
+
+  // Some variables used for ray computation
+  float ViewToVoxelsArray[16];
+  float WorldToVoxelsArray[16];
+  float VoxelsToWorldArray[16];
+
+  double CroppingBounds[6];
+
+  int NumTransformedClippingPlanes;
+  float *TransformedClippingPlanes;
+
+  double SavedSpacing[3];
+
+
+  // Min Max structured used to do space leaping
+  unsigned short *MinMaxVolume;
+  int             MinMaxVolumeSize[4];
+  vtkImageData   *SavedMinMaxInput;
+  vtkTimeStamp    SavedMinMaxBuildTime;
+  vtkTimeStamp    SavedMinMaxGradientTime;
+  vtkTimeStamp    SavedMinMaxFlagTime;
+
+  void            UpdateMinMaxVolume( vtkVolume *vol );
+  void            FillInMaxGradientMagnitudes( int fullDim[3],
+                                               int smallDim[3] );
+
+  float FinalColorWindow;
+  float FinalColorLevel;
+
+  int FlipMIPComparison;
+
+  void ApplyFinalColorWindowLevel();
+
+
+
+
+private:
+  vtkCropVolumeRayCastMapper(const vtkCropVolumeRayCastMapper&);  // Not implemented.
+  void operator=(const vtkCropVolumeRayCastMapper&);  // Not implemented.
+
+
+};
+
+
+inline unsigned int vtkCropVolumeRayCastMapper::ToFixedPointPosition( float val )
+{
+  return static_cast<unsigned int>(val * VTKKW_FP_SCALE + 0.5);
+}
+
+inline void vtkCropVolumeRayCastMapper::ToFixedPointPosition( float in[3], unsigned int out[3] )
+{
+  out[0] = static_cast<unsigned int>(in[0] * VTKKW_FP_SCALE + 0.5);
+  out[1] = static_cast<unsigned int>(in[1] * VTKKW_FP_SCALE + 0.5);
+  out[2] = static_cast<unsigned int>(in[2] * VTKKW_FP_SCALE + 0.5);
+}
+
+inline unsigned int vtkCropVolumeRayCastMapper::ToFixedPointDirection( float dir )
+{
+  return ((dir<0.0)?
+          (static_cast<unsigned int>(-dir * VTKKW_FP_SCALE + 0.5)):
+          (0x80000000+static_cast<unsigned int>(dir*VTKKW_FP_SCALE + 0.5)));
+}
+
+inline void vtkCropVolumeRayCastMapper::ToFixedPointDirection( float in[3], unsigned int out[3] )
+{
+  out[0] = ((in[0]<0.0)?
+            (static_cast<unsigned int>(-in[0] * VTKKW_FP_SCALE + 0.5)):
+            (0x80000000+
+             static_cast<unsigned int>(in[0]*VTKKW_FP_SCALE + 0.5)));
+  out[1] = ((in[1]<0.0)?
+            (static_cast<unsigned int>(-in[1] * VTKKW_FP_SCALE + 0.5)):
+            (0x80000000+
+             static_cast<unsigned int>(in[1]*VTKKW_FP_SCALE + 0.5)));
+  out[2] = ((in[2]<0.0)?
+            (static_cast<unsigned int>(-in[2] * VTKKW_FP_SCALE + 0.5)):
+            (0x80000000+
+             static_cast<unsigned int>(in[2]*VTKKW_FP_SCALE + 0.5)));
+}
+
+inline void vtkCropVolumeRayCastMapper::FixedPointIncrement( unsigned int position[3], unsigned int increment[3] )
+{
+  if ( increment[0]&0x80000000 )
+    {
+    position[0] += (increment[0]&0x7fffffff);
+    }
+  else
+    {
+    position[0] -= increment[0];
+    }
+  if ( increment[1]&0x80000000 )
+    {
+    position[1] += (increment[1]&0x7fffffff);
+    }
+  else
+    {
+    position[1] -= increment[1];
+    }
+  if ( increment[2]&0x80000000 )
+    {
+    position[2] += (increment[2]&0x7fffffff);
+    }
+  else
+    {
+    position[2] -= increment[2];
+    }
+}
+
+
+inline void vtkCropVolumeRayCastMapper::GetFloatTripleFromPointer( float v[3], float *ptr )
+{
+  v[0] = *(ptr);
+  v[1] = *(ptr+1);
+  v[2] = *(ptr+2);
+}
+
+inline void vtkCropVolumeRayCastMapper::GetUIntTripleFromPointer( unsigned int v[3], unsigned int *ptr )
+{
+  v[0] = *(ptr);
+  v[1] = *(ptr+1);
+  v[2] = *(ptr+2);
+}
+
+inline void vtkCropVolumeRayCastMapper::ShiftVectorDown( unsigned int in[3],
+                                                       unsigned int out[3] )
+{
+  out[0] = in[0] >> VTKKW_FP_SHIFT;
+  out[1] = in[1] >> VTKKW_FP_SHIFT;
+  out[2] = in[2] >> VTKKW_FP_SHIFT;
+}
+
+inline int vtkCropVolumeRayCastMapper::CheckMinMaxVolumeFlag( unsigned int mmpos[3], int c )
+{
+  unsigned int offset =
+    this->MinMaxVolumeSize[3] *
+    ( mmpos[2]*this->MinMaxVolumeSize[0]*this->MinMaxVolumeSize[1] +
+      mmpos[1]*this->MinMaxVolumeSize[0] +
+      mmpos[0] ) + c;
+
+  return ((*(this->MinMaxVolume + 3*offset + 2))&0x00ff);
+}
+
+inline int vtkCropVolumeRayCastMapper::CheckMIPMinMaxVolumeFlag( unsigned int mmpos[3], int c,
+                                                                       unsigned short maxIdx, int flip )
+{
+  unsigned int offset =
+    this->MinMaxVolumeSize[3] *
+    ( mmpos[2]*this->MinMaxVolumeSize[0]*this->MinMaxVolumeSize[1] +
+      mmpos[1]*this->MinMaxVolumeSize[0] +
+      mmpos[0] ) + c;
+
+  if ( (*(this->MinMaxVolume + 3*offset + 2)&0x00ff) )
+    {
+    if (flip)
+      {
+      return ( *(this->MinMaxVolume + 3*offset) < maxIdx );
+      }
+    else
+      {
+      return ( *(this->MinMaxVolume + 3*offset + 1) > maxIdx );
+      }
+    }
+  else
+    {
+    return 0;
+    }
+}
+
+inline void vtkCropVolumeRayCastMapper::LookupColorUC( unsigned short *colorTable,
+                                                     unsigned short *scalarOpacityTable,
+                                                     unsigned short index,
+                                                     unsigned char  color[4] )
+{
+  unsigned short alpha = scalarOpacityTable[index];
+  color[0] = static_cast<unsigned char>
+    ((colorTable[3*index  ]*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8));
+  color[1] = static_cast<unsigned char>
+    ((colorTable[3*index+1]*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8));
+  color[2] = static_cast<unsigned char>
+    ((colorTable[3*index+2]*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8));
+  color[3] = static_cast<unsigned char>(alpha>>(VTKKW_FP_SHIFT - 8));
+}
+
+inline void vtkCropVolumeRayCastMapper::LookupDependentColorUC( unsigned short *colorTable,
+                                                              unsigned short *scalarOpacityTable,
+                                                              unsigned short index[4],
+                                                              int            components,
+                                                              unsigned char  color[4] )
+{
+  unsigned short alpha;
+  switch ( components )
+    {
+    case 2:
+      alpha = scalarOpacityTable[index[1]];
+      color[0] = static_cast<unsigned char>
+        ((colorTable[3*index[0]  ]*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8));
+      color[1] = static_cast<unsigned char>
+        ((colorTable[3*index[0]+1]*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8));
+      color[2] = static_cast<unsigned char>
+        ((colorTable[3*index[0]+2]*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8));
+      color[3] = static_cast<unsigned char>(alpha>>(VTKKW_FP_SHIFT - 8));
+      break;
+    case 4:
+      alpha = scalarOpacityTable[index[3]];
+      color[0] = static_cast<unsigned char>((index[0]*alpha + 0x7fff)>>VTKKW_FP_SHIFT );
+      color[1] = static_cast<unsigned char>((index[1]*alpha + 0x7fff)>>VTKKW_FP_SHIFT );
+      color[2] = static_cast<unsigned char>((index[2]*alpha + 0x7fff)>>VTKKW_FP_SHIFT );
+      color[3] = static_cast<unsigned char>(alpha>>(VTKKW_FP_SHIFT - 8));
+      break;
+    }
+}
+
+
+inline void vtkCropVolumeRayCastMapper::LookupAndCombineIndependentColorsUC( unsigned short *colorTable[4],
+                                                                           unsigned short *scalarOpacityTable[4],
+                                                                           unsigned short  index[4],
+                                                                           float           weights[4],
+                                                                           int             components,
+                                                                           unsigned char   color[4] )
+{
+  unsigned int tmp[4] = {0,0,0,0};
+
+  for ( int i = 0; i < components; i++ )
+    {
+    unsigned short alpha = static_cast<unsigned short>(scalarOpacityTable[i][index[i]]*weights[i]);
+    tmp[0] += static_cast<unsigned char>(((colorTable[i][3*index[i]  ])*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8));
+    tmp[1] += static_cast<unsigned char>(((colorTable[i][3*index[i]+1])*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8));
+    tmp[2] += static_cast<unsigned char>(((colorTable[i][3*index[i]+2])*alpha + 0x7fff)>>(2*VTKKW_FP_SHIFT - 8));
+    tmp[3] += static_cast<unsigned char>(alpha>>(VTKKW_FP_SHIFT - 8));
+    }
+
+  color[0] = (tmp[0]>255)?(255):(tmp[0]);
+  color[1] = (tmp[1]>255)?(255):(tmp[1]);
+  color[2] = (tmp[2]>255)?(255):(tmp[2]);
+  color[3] = (tmp[3]>255)?(255):(tmp[3]);
+
+}
+
+inline int vtkCropVolumeRayCastMapper::CheckIfCropped( unsigned int pos[3] )
+{
+  int idx;
+
+  if ( pos[2] < this->FixedPointCroppingRegionPlanes[4] )
+    {
+    idx = 0;
+    }
+  else if ( pos[2] > this->FixedPointCroppingRegionPlanes[5] )
+    {
+    idx = 18;
+    }
+  else
+    {
+    idx = 9;
+    }
+
+  if ( pos[1] >= this->FixedPointCroppingRegionPlanes[2] )
+    {
+    if ( pos[1] > this->FixedPointCroppingRegionPlanes[3] )
+      {
+      idx += 6;
+      }
+    else
+      {
+      idx += 3;
+      }
+    }
+
+  if ( pos[0] >= this->FixedPointCroppingRegionPlanes[0] )
+    {
+    if ( pos[0] > this->FixedPointCroppingRegionPlanes[1] )
+      {
+      idx += 2;
+      }
+    else
+      {
+      idx += 1;
+      }
+    }
+
+  return !(this->CroppingRegionFlags&this->CroppingRegionMask[idx]);
+}
+
+#endif
+
diff --git a/bioimagesuite30_src/Graphics/vtkEllipseSource.cxx b/bioimagesuite30_src/Graphics/vtkEllipseSource.cxx
new file mode 100644
index 0000000..da7ff0d
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkEllipseSource.cxx
@@ -0,0 +1,370 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkEllipseSource.cxx,v $
+
+  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 "vtkEllipseSource.h"
+
+#include "vtkCellArray.h"
+#include "vtkFloatArray.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+#include <math.h>
+
+//----------------------------------------------------------------------------
+// Construct Ellipse with radiusx=0.5, radiusy=1.0, radiusz=0.5 and default resolution 8 in both Phi
+// and Theta directions. Theta ranges from (0,360) and phi (0,180) degrees.
+vtkEllipseSource::vtkEllipseSource(int res)
+{
+  res = res < 4 ? 4 : res;
+  this->RadiusX = 0.5;
+  this->RadiusY = 0.5;
+  this->RadiusZ = 0.5;
+  this->Center[0] = 0.0;
+  this->Center[1] = 0.0;
+  this->Center[2] = 0.0;
+
+  this->ThetaResolution = res;
+  this->PhiResolution = res;
+  this->StartTheta = 0.0;
+  this->EndTheta = 360.0;
+  this->StartPhi = 0.0;
+  this->EndPhi = 180.0;
+  this->LatLongTessellation = 0;
+
+  this->SetNumberOfInputPorts(0);
+}
+
+vtkEllipseSource* vtkEllipseSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkEllipseSource");
+  if(ret)
+      {
+	return (vtkEllipseSource*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkEllipseSource;
+}
+
+//----------------------------------------------------------------------------
+int vtkEllipseSource::RequestData(
+  vtkInformation *vtkNotUsed(request),
+  vtkInformationVector **vtkNotUsed(inputVector),
+  vtkInformationVector *outputVector)
+{
+  // get the info object
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  // get the ouptut
+  vtkPolyData *output = vtkPolyData::SafeDownCast(
+    outInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+  int i, j;
+  int jStart, jEnd, numOffset;
+  int numPts, numPolys;
+  vtkPoints *newPoints;
+  vtkFloatArray *newNormals;
+  vtkCellArray *newPolys;
+  double x[3], n[3], deltaPhi, deltaTheta, phi, theta, norm;
+  double startTheta, endTheta, startPhi, endPhi;
+  int base, numPoles=0, thetaResolution, phiResolution;
+  vtkIdType pts[4];
+  int piece =
+    outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
+  int numPieces =
+    outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
+
+  if (numPieces > this->ThetaResolution)
+    {
+    numPieces = this->ThetaResolution;
+    }
+  if (piece >= numPieces)
+    {
+    // Although the super class should take care of this,
+    // it cannot hurt to check here.
+    return 1;
+    }
+
+  // I want to modify the ivars resoultion start theta and end theta,
+  // so I will make local copies of them.  THese might be able to be merged
+  // with the other copies of them, ...
+  int localThetaResolution = this->ThetaResolution;
+  double localStartTheta = this->StartTheta;
+  double localEndTheta = this->EndTheta;
+
+  while (localEndTheta < localStartTheta)
+    {
+    localEndTheta += 360.0;
+    }
+  deltaTheta = (localEndTheta - localStartTheta) / localThetaResolution;
+
+  // Change the ivars based on pieces.
+  int start, end;
+  start = piece * localThetaResolution / numPieces;
+  end = (piece+1) * localThetaResolution / numPieces;
+  localEndTheta = localStartTheta + (double)(end) * deltaTheta;
+  localStartTheta = localStartTheta + (double)(start) * deltaTheta;
+  localThetaResolution = end - start;
+
+  // Set things up; allocate memory
+  //
+  vtkDebugMacro("EllipseSource Executing piece index " << piece
+                << " of " << numPieces << " pieces.");
+
+  numPts = this->PhiResolution * localThetaResolution + 2;
+  // creating triangles
+  numPolys = this->PhiResolution * 2 * localThetaResolution;
+
+  newPoints = vtkPoints::New();
+  newPoints->Allocate(numPts);
+  newNormals = vtkFloatArray::New();
+  newNormals->SetNumberOfComponents(3);
+  newNormals->Allocate(3*numPts);
+  newNormals->SetName("Normals");
+  
+  newPolys = vtkCellArray::New();
+  newPolys->Allocate(newPolys->EstimateSize(numPolys, 3));
+
+  // Create sphere
+  //
+  // Create north pole if needed
+  if ( this->StartPhi <= 0.0 )
+    {
+    x[0] = this->Center[0];
+    x[1] = this->Center[1];
+    x[2] = this->Center[2] + this->RadiusZ;
+    newPoints->InsertPoint(numPoles,x);
+
+    x[0] = x[1] = 0.0; x[2] = 1.0;
+    newNormals->InsertTuple(numPoles,x);
+    numPoles++;
+    }
+
+  // Create south pole if needed
+  if ( this->EndPhi >= 180.0 )
+    {
+    x[0] = this->Center[0];
+    x[1] = this->Center[1];
+    x[2] = this->Center[2] - this->RadiusZ;
+    newPoints->InsertPoint(numPoles,x);
+
+    x[0] = x[1] = 0.0; x[2] = -1.0;
+    newNormals->InsertTuple(numPoles,x);
+    numPoles++;
+    }
+
+  // Check data, determine increments, and convert to radians
+  startTheta = (localStartTheta < localEndTheta ? localStartTheta : localEndTheta);
+  startTheta *= vtkMath::Pi() / 180.0;
+  endTheta = (localEndTheta > localStartTheta ? localEndTheta : localStartTheta);
+  endTheta *= vtkMath::Pi() / 180.0;
+  
+  startPhi = (this->StartPhi < this->EndPhi ? this->StartPhi : this->EndPhi);
+  startPhi *= vtkMath::Pi() / 180.0;
+  endPhi = (this->EndPhi > this->StartPhi ? this->EndPhi : this->StartPhi);
+  endPhi *= vtkMath::Pi() / 180.0;
+
+  phiResolution = this->PhiResolution - numPoles;
+  deltaPhi = (endPhi - startPhi) / (this->PhiResolution - 1);
+  thetaResolution = localThetaResolution;
+  if (fabs(localStartTheta - localEndTheta) < 360.0)
+    {
+    ++localThetaResolution;
+    }
+  deltaTheta = (endTheta - startTheta) / thetaResolution;
+
+  jStart = (this->StartPhi <= 0.0 ? 1 : 0);
+  jEnd = (this->EndPhi >= 180.0 ? this->PhiResolution - 1
+        : this->PhiResolution);
+
+  this->UpdateProgress(0.1);
+
+  // Create intermediate points
+  for (i=0; i < localThetaResolution; i++)
+    {
+    theta = localStartTheta * vtkMath::Pi() / 180.0 + i*deltaTheta;
+
+    for (j=jStart; j<jEnd; j++)
+      {
+      phi = startPhi + j*deltaPhi;
+      //radiusx = this->RadiusX * sin((double)phi);
+      n[0] = this->RadiusX * sin((double)phi) * cos((double)theta);
+      n[1] = this->RadiusY * sin((double)phi) * sin((double)theta);
+      //n[2] = this->RadiusZ * sin((double)phi) * cos((double)phi);
+	  n[2] = this->RadiusZ * cos((double)phi);
+      x[0] = n[0] + this->Center[0];
+      x[1] = n[1] + this->Center[1];
+      x[2] = n[2] + this->Center[2];
+      newPoints->InsertNextPoint(x);
+
+      if ( (norm = vtkMath::Norm(n)) == 0.0 )
+        {
+        norm = 1.0;
+        }
+      n[0] /= norm; n[1] /= norm; n[2] /= norm;
+      newNormals->InsertNextTuple(n);
+      }
+    this->UpdateProgress (0.10 + 0.50*i/static_cast<float>(localThetaResolution));
+    }
+
+  // Generate mesh connectivity
+  base = phiResolution * localThetaResolution;
+
+  if (fabs(localStartTheta - localEndTheta) < 360.0)
+    {
+    --localThetaResolution;
+    }
+  
+  if ( this->StartPhi <= 0.0 )  // around north pole
+    {
+    for (i=0; i < localThetaResolution; i++)
+      {
+      pts[0] = phiResolution*i + numPoles;
+      pts[1] = (phiResolution*(i+1) % base) + numPoles;
+      pts[2] = 0;
+      newPolys->InsertNextCell(3, pts);
+      }
+    }
+  
+  if ( this->EndPhi >= 180.0 ) // around south pole
+    {
+    numOffset = phiResolution - 1 + numPoles;
+    
+    for (i=0; i < localThetaResolution; i++)
+      {
+      pts[0] = phiResolution*i + numOffset;
+      pts[2] = ((phiResolution*(i+1)) % base) + numOffset;
+      pts[1] = numPoles - 1;
+      newPolys->InsertNextCell(3, pts);
+      }
+    }
+  this->UpdateProgress (0.70);
+
+  // bands in-between poles
+  for (i=0; i < localThetaResolution; i++)
+    {
+    for (j=0; j < (phiResolution-1); j++)
+      {
+      pts[0] = phiResolution*i + j + numPoles;
+      pts[1] = pts[0] + 1;
+      pts[2] = ((phiResolution*(i+1)+j) % base) + numPoles + 1;
+      if ( !this->LatLongTessellation )
+        {
+        newPolys->InsertNextCell(3, pts);
+        pts[1] = pts[2];
+        pts[2] = pts[1] - 1;
+        newPolys->InsertNextCell(3, pts);
+        }
+      else
+        {
+        pts[3] = pts[2] - 1;
+        newPolys->InsertNextCell(4, pts);
+        }
+      }
+    this->UpdateProgress (0.70 + 0.30*i/static_cast<double>(localThetaResolution));
+    }
+
+  // Update ourselves and release memeory
+  //
+  newPoints->Squeeze();
+  output->SetPoints(newPoints);
+  newPoints->Delete();
+
+  newNormals->Squeeze();
+  output->GetPointData()->SetNormals(newNormals);
+  newNormals->Delete();
+
+  newPolys->Squeeze();
+  output->SetPolys(newPolys);
+  newPolys->Delete();
+
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+//void vtkEllipseSource::PrintSelf(ostream& os, vtkIndent indent)
+//{
+//  this->Superclass::PrintSelf(os,indent);
+//
+//  os << indent << "Theta Resolution: " << this->ThetaResolution << "\n";
+//  os << indent << "Phi Resolution: " << this->PhiResolution << "\n";
+//  os << indent << "Theta Start: " << this->StartTheta << "\n";
+//  os << indent << "Phi Start: " << this->StartPhi << "\n";
+//  os << indent << "Theta End: " << this->EndTheta << "\n";
+//  os << indent << "Phi End: " << this->EndPhi << "\n";
+//  os << indent << "RadiusX: " << this->RadiusX << "\n";
+//  os << indent << "RadiusY: " << this->RadiusY << "\n";
+//  os << indent << "RadiusZ: " << this->RadiusZ << "\n";
+//  os << indent << "Center: (" << this->Center[0] << ", " 
+//     << this->Center[1] << ", " << this->Center[2] << ")\n";
+//  os << indent
+//     << "LatLong Tessellation: " << this->LatLongTessellation << "\n";
+//}
+
+//----------------------------------------------------------------------------
+int vtkEllipseSource::RequestInformation(
+  vtkInformation *vtkNotUsed(request),
+  vtkInformationVector **vtkNotUsed(inputVector),
+  vtkInformationVector *outputVector)
+{
+  // get the info object
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(),
+               -1);
+
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_BOUNDING_BOX(),
+               this->Center[0] - this->RadiusX,
+               this->Center[0] + this->RadiusX,
+               this->Center[1] - this->RadiusY,
+               this->Center[1] + this->RadiusY,
+               this->Center[2] - this->RadiusZ,
+               this->Center[2] + this->RadiusZ);
+
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Graphics/vtkEllipseSource.h b/bioimagesuite30_src/Graphics/vtkEllipseSource.h
new file mode 100644
index 0000000..7fc4304
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkEllipseSource.h
@@ -0,0 +1,164 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkEllipseSource.h,v $
+
+  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 vtkEllipseSource - create a polygonal sphere centered at the origin
+// .SECTION Description
+// vtkEllipseSource creates a sphere (represented by polygons) of specified
+// radius centered at the origin. The resolution (polygonal discretization)
+// in both the latitude (phi) and longitude (theta) directions can be
+// specified. It also is possible to create partial spheres by specifying
+// maximum phi and theta angles. By default, the surface tessellation of
+// the sphere uses triangles; however you can set LatLongTessellation to
+// produce a tessellation using quadrilaterals.
+// .SECTION Caveats
+// Resolution means the number of latitude or longitude lines for a complete 
+// sphere. If you create partial spheres the number of latitude/longitude 
+// lines may be off by one. 
+
+#ifndef __vtkEllipseSource_h
+#define __vtkEllipseSource_h
+
+#include "vtkPolyDataAlgorithm.h"
+
+#define VTK_MAX_SPHERE_RESOLUTION 1024
+
+
+class  vtkEllipseSource : public vtkPolyDataAlgorithm 
+{
+public:
+  
+//  static EllipseSource *New();
+//  vtkTypeMacro(vtkEllipseSource,vtkPolyDataAlgorithm);
+
+
+
+  // Description:
+  // Construct sphere with radius=0.5 and default resolution 8 in both Phi
+  // and Theta directions. Theta ranges from (0,360) and phi (0,180) degrees.
+  static vtkEllipseSource *New();
+  vtkTypeMacro(vtkEllipseSource,vtkPolyDataAlgorithm);
+
+  // Description:
+  // Set radius of sphere. Default is .5.
+  vtkSetClampMacro(RadiusX,double,0.0,VTK_DOUBLE_MAX);
+  vtkGetMacro(RadiusX,double);
+
+  vtkSetClampMacro(RadiusY,double,0.0,VTK_DOUBLE_MAX);
+  vtkGetMacro(RadiusY,double);
+
+  vtkSetClampMacro(RadiusZ,double,0.0,VTK_DOUBLE_MAX);
+  vtkGetMacro(RadiusZ,double);
+
+  // Description:
+  // Set the center of the sphere. Default is 0,0,0.
+  vtkSetVector3Macro(Center,double);
+  vtkGetVectorMacro(Center,double,3);
+
+  // Description:
+  // Set the number of points in the longitude direction (ranging from
+  // StartTheta to EndTheta).
+  vtkSetClampMacro(ThetaResolution,int,3,VTK_MAX_SPHERE_RESOLUTION);
+  vtkGetMacro(ThetaResolution,int);
+
+  // Description:
+  // Set the number of points in the latitude direction (ranging
+  // from StartPhi to EndPhi).
+  vtkSetClampMacro(PhiResolution,int,3,VTK_MAX_SPHERE_RESOLUTION);
+  vtkGetMacro(PhiResolution,int);
+
+  // Description:
+  // Set the starting longitude angle. By default StartTheta=0 degrees.
+  vtkSetClampMacro(StartTheta,double,0.0,360.0);
+  vtkGetMacro(StartTheta,double);
+
+  // Description:
+  // Set the ending longitude angle. By default EndTheta=360 degrees.
+  vtkSetClampMacro(EndTheta,double,0.0,360.0);
+  vtkGetMacro(EndTheta,double);
+
+  // Description:
+  // Set the starting latitude angle (0 is at north pole). By default
+  // StartPhi=0 degrees.
+  vtkSetClampMacro(StartPhi,double,0.0,360.0);
+  vtkGetMacro(StartPhi,double);
+
+  // Description:
+  // Set the ending latitude angle. By default EndPhi=180 degrees.
+  vtkSetClampMacro(EndPhi,double,0.0,360.0);
+  vtkGetMacro(EndPhi,double);
+
+  // Description:
+  // Cause the sphere to be tessellated with edges along the latitude
+  // and longitude lines. If off, triangles are generated at non-polar
+  // regions, which results in edges that are not parallel to latitude and
+  // longitude lines. If on, quadrilaterals are generated everywhere
+  // except at the poles. This can be useful for generating a wireframe
+  // sphere with natural latitude and longitude lines.
+  vtkSetMacro(LatLongTessellation,int);
+  vtkGetMacro(LatLongTessellation,int);
+  vtkBooleanMacro(LatLongTessellation,int);
+
+protected:
+  vtkEllipseSource(int res=8);
+  ~vtkEllipseSource() {}
+
+  int RequestData(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
+  int RequestInformation(vtkInformation *, vtkInformationVector **, vtkInformationVector *);
+
+  double RadiusX;
+  double RadiusY;
+  double RadiusZ;
+  double Center[3];
+  int ThetaResolution;
+  int PhiResolution;
+  double StartTheta;
+  double EndTheta;
+  double StartPhi;
+  double EndPhi;
+  int LatLongTessellation;
+
+private:
+  vtkEllipseSource(const vtkEllipseSource&);  // Not implemented.
+  void operator=(const vtkEllipseSource&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Graphics/vtkpx2DImageSlice.cpp b/bioimagesuite30_src/Graphics/vtkpx2DImageSlice.cpp
new file mode 100644
index 0000000..a83ea37
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpx2DImageSlice.cpp
@@ -0,0 +1,400 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpx2DImageSlice.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/02/03 15:28:43 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpx2DImageSlice.h"
+#include "vtkObjectFactory.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkpxUtil.h"
+#include "vtkImageMapToColors.h"
+#include "vtkpxColorMapUtil.h"
+#include "vtkImageToStructuredPoints.h"
+//------------------------------------------------------------------------------
+vtkpx2DImageSlice* vtkpx2DImageSlice::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpx2DImageSlice");
+  if(ret)
+    {
+    return (vtkpx2DImageSlice*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpx2DImageSlice;
+}
+//------------------------------------------------------------------------------
+// Construct object with no children.
+vtkpx2DImageSlice::vtkpx2DImageSlice()
+{
+  this->ImageSlice=NULL;         
+  this->ImagePlane=NULL;         
+  this->ImageTexture=NULL; 
+  this->CurrentImage=NULL;
+
+  this->Level=-1;              
+  this->Opacity=1.0;            
+  this->Interpolation=0;      
+  this->ColorMap=NULL;           
+  this->OwnsColorMap=1;   
+
+  this->CurrentPlane=2;
+
+  this->ColorMap=vtkLookupTable::New();
+  this->ColorMap->SetNumberOfTableValues(256);
+  this->ColorMap->SetTableRange(0,255);
+
+  this->PolarMode=0;
+  this->PolarMiddle=-1.0;
+  
+  for (int i=0;i<=255;i++)
+    {
+      float v=float(i)/float(255.0);
+      this->ColorMap->SetTableValue(i,v,v,v,1.0);
+    }
+  
+  this->AutoUpdate=1;
+}
+//------------------------------------------------------------------------------
+vtkpx2DImageSlice::~vtkpx2DImageSlice()
+{
+  if (this->CurrentImage)
+    this->CurrentImage->Delete();
+
+  if (this->ImagePlane)
+    this->ImagePlane->Delete();
+  
+  if (this->ImageSlice)
+    this->ImageSlice->Delete();
+  
+  if (this->ImageTexture)
+    ImageTexture->Delete();
+  
+  if (this->OwnsColorMap)
+    {
+      if (this->ColorMap)
+	this->ColorMap->Delete();
+    }
+}
+
+//------------------------------------------------------------------------------
+void vtkpx2DImageSlice::SetInput(vtkImageData* image)
+{
+  if (image==NULL)
+    return;
+  
+  int dim[3]; image->GetDimensions(dim);
+
+  if (dim[0]!=1 && dim[1]!=1 && dim[2]!=1)
+    {
+      //      fprintf(stderr,"3D Image Input Ignoring %d,%d,%d\n",dim[0],dim[1],dim[2]);
+      return;
+    }
+	
+
+  if (this->CurrentImage==NULL)
+    this->CurrentImage=vtkImageData::New();
+
+  this->CurrentImage->ShallowCopy(image);
+
+  BuildImageSlice();
+  if (this->OwnsColorMap)
+    vtkpxColorMapUtil::AutoUpdateColormapRange(this->ColorMap,this->CurrentImage);
+  
+  UpdateSlice();
+}
+//------------------------------------------------------------------------------
+void vtkpx2DImageSlice::SetLookupTable(vtkLookupTable* table)
+{
+  if (!table)
+      return;
+
+  if (table==this->ColorMap)
+      return;
+
+  if (this->ImageTexture)
+      this->ImageTexture->SetLookupTable(table);
+
+  if (this->OwnsColorMap)
+      {
+	this->ColorMap->Delete();
+	this->OwnsColorMap=0;
+      }
+
+  this->ColorMap=table;  
+  this->Update();
+}
+//------------------------------------------------------------------------------
+void vtkpx2DImageSlice::SetInterpolation(int on)
+{
+  this->Interpolation=on>0;
+  if (this->ImageTexture)
+    {
+      if (this->Interpolation==1)
+	this->ImageTexture->InterpolateOn();
+      else
+	this->ImageTexture->InterpolateOff();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpx2DImageSlice::SetOpacity(float opacity)
+{
+  this->Opacity=Frange(opacity,0.0,1.0);
+  if (this->ImageSlice)
+    {
+      this->ImageSlice->GetProperty()->SetOpacity(this->Opacity);
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpx2DImageSlice::SetPolarMode(int mode)
+{
+  int p=(mode>0);
+  if (p!=this->PolarMode)
+    {
+      this->PolarMode=p;
+      if (this->ImageSlice && this->AutoUpdate)
+	UpdateSlice();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpx2DImageSlice::SetPolarMiddle(float pm)
+{
+  if (pm!=this->PolarMiddle)
+    {
+      this->PolarMiddle=pm;
+      if (this->PolarMode && this->ImageSlice)
+	UpdateSlice();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpx2DImageSlice::SetLevel(int level)
+{
+  if (this->Level!=level)
+    {
+      this->Level=level;
+      if (this->ImageSlice && this->AutoUpdate==1)
+	UpdateSlice();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpx2DImageSlice::SetCurrentPlane(int currentplane)
+{
+  if (currentplane!=this->CurrentPlane)
+    {
+      this->CurrentPlane=currentplane;
+      if (this->ImageSlice && this->AutoUpdate==1)
+	UpdateSlice();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpx2DImageSlice::BuildImageSlice()
+{
+  if (!this->ImageSlice)
+    {
+      this->ImagePlane=vtkPlaneSource::New();
+      this->ImagePlane->SetXResolution(1);
+      this->ImagePlane->SetYResolution(1);
+      
+      // ImageSlice
+      this->ImageSlice=vtkActor::New();
+      this->ImageSlice->PickableOff();
+      this->ImageTexture=vtkTexture::New();
+      
+      this->ImageTexture->SetInput(this->CurrentImage);
+      if (this->Interpolation==0)
+	this->ImageTexture->InterpolateOn();
+      else
+	this->ImageTexture->InterpolateOff();
+      this->ImageTexture->SetLookupTable(this->ColorMap);
+      this->ImageTexture->MapColorScalarsThroughLookupTableOn();
+      this->ImageTexture->RepeatOff();
+      
+      vtkPolyDataMapper* imageMapper=vtkPolyDataMapper::New();
+      imageMapper->SetInput(this->ImagePlane->GetOutput());
+            
+      this->ImageSlice->SetMapper(imageMapper);
+      this->ImageSlice->GetProperty()->SetOpacity(this->Opacity);
+      this->ImageSlice->GetProperty()->SetInterpolationToFlat();
+      this->ImageSlice->SetTexture(this->ImageTexture);
+      
+      AddPart(this->ImageSlice);
+      imageMapper->Delete();  
+    }
+}
+//------------------------------------------------------------------------------  
+void vtkpx2DImageSlice::UpdateTexture()
+{
+  if (!this->CurrentImage || !this->ImageSlice)
+      return;
+
+  this->ImageSlice->GetTexture()->Modified();
+  this->ImageSlice->Modified();
+
+}
+//------------------------------------------------------------------------------  
+void vtkpx2DImageSlice::UpdateSlice()
+{
+  if (!this->CurrentImage)
+      return;
+
+  if (this->PolarMode)
+    {
+      UpdateSlicePolar();
+      return;
+    }
+
+  vtkImageData* img=this->CurrentImage;
+  int range[3];  img->GetDimensions(range);
+  double sp[3];   img->GetSpacing(sp);
+  double ori[3];  img->GetOrigin(ori);
+
+  this->CurrentPlane=Irange(this->CurrentPlane,0,2);
+  
+  if (this->Level==-1)
+      this->Level=range[this->CurrentPlane]/2;
+  
+  this->Level=Irange(this->Level,0,range[this->CurrentPlane]-1);
+
+  double d1[3];
+  double d0[3];
+  for (int i=0;i<=2;i++)
+      {
+	if (i!=this->CurrentPlane)
+	    {
+	      d1[i]=sp[i]*double(range[i]-0.5)+ori[i];
+	      d0[i]=sp[i]*double(-0.5)+ori[i];
+	    }
+	else
+	    {
+	      d1[i]=sp[i]*double(this->Level)+ori[i];
+	      d0[i]=d1[i];
+	    }
+      }
+
+  switch (this->CurrentPlane)
+    {
+    case 0: // yz
+      this->ImagePlane->SetOrigin(d1[0] , d0[1] , d0[2]);
+      this->ImagePlane->SetPoint1(d1[0] , d1[1] , d0[2]);
+      this->ImagePlane->SetPoint2(d1[0] , d0[1] , d1[2]);
+      break;
+      
+    case 1: // xz
+      this->ImagePlane->SetOrigin(d0[0] , d1[1] , d0[2]);
+      this->ImagePlane->SetPoint1(d1[0] , d1[1] , d0[2]);
+      this->ImagePlane->SetPoint2(d0[0] , d1[1] , d1[2]);
+      break;
+      
+    case 2: // xy
+      this->ImagePlane->SetOrigin(d0[0] , d0[1] , d1[2]);
+      this->ImagePlane->SetPoint1(d1[0] , d0[1] , d1[2]);
+      this->ImagePlane->SetPoint2(d0[0] , d1[1] , d1[2]);
+      break;
+    }
+  this->ImagePlane->Update();
+  
+}
+
+// ------------------------------------------------------------------------------------------
+void vtkpx2DImageSlice::UpdateSlicePolar()
+{
+  vtkImageData* img=this->CurrentImage;
+  int dim[3];  img->GetDimensions(dim);
+  double sp[3];   img->GetSpacing(sp);
+  double ori[3];  img->GetOrigin(ori);
+
+  this->CurrentPlane=Irange(this->CurrentPlane,0,2);
+  
+  if (this->Level<0)
+    {
+      if (this->CurrentPlane == 0)
+	this->Level=dim[1]/2;
+      else
+	this->Level=dim[2]/2;
+    }
+
+  if (this->CurrentPlane==0 && this->Level>=dim[1])
+    {
+      this->Level=dim[1]-1;
+    }
+  else if (this->CurrentPlane>0 && this->Level>=dim[2])
+    {
+      this->Level=dim[2]-1;
+    }
+
+
+  double r=0.5*double(dim[0])*sp[0];
+  double ox=ori[0]+double(sp[0]*(dim[0]-1))*0.5;
+
+  if (this->CurrentPlane>0)
+    {
+      double theta=180.0*double(this->Level)/double(dim[2]);
+      theta*=M_PI/180.0;
+      this->ImagePlane->SetOrigin(ox-r*cos(theta),ox-r*sin(theta),ori[1]-0.5*sp[0]);
+      this->ImagePlane->SetPoint1(ox+r*cos(theta),ox+r*sin(theta),ori[1]-0.5*sp[0]);
+      this->ImagePlane->SetPoint2(ox-r*cos(theta),ox-r*sin(theta),ori[1]+(dim[1]-0.5)*sp[0]);
+    }
+  else
+    {
+      double z=sp[0]*double(this->Level)+ori[1];
+      this->ImagePlane->SetOrigin(ox-r,ox-r,z);
+      this->ImagePlane->SetPoint1(ox+r,ox-r,z);
+      this->ImagePlane->SetPoint2(ox-r,ox+r,z);
+    }
+
+  this->ImagePlane->Update();
+
+}
+
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpx2DImageSlice.h b/bioimagesuite30_src/Graphics/vtkpx2DImageSlice.h
new file mode 100644
index 0000000..5789f95
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpx2DImageSlice.h
@@ -0,0 +1,153 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpx2DImageSlice.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+// .NAME vtkpx2DImageSlice - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkpx2DImageSlice_h
+#define __vtkpx2DImageSlice_h
+
+#include "vtkpxEnclosedPipeline.h"
+#include "vtkImageData.h"
+#include "vtkpxImageExtract.h"
+#include "vtkLookupTable.h"
+#include "vtkPlaneSource.h"
+#include "vtkTexture.h"
+#include "vtkCubeSource.h"
+#include "vtkProperty.h"
+
+class vtkpx2DImageSlice : public vtkpxEnclosedPipeline
+{
+public:
+  static vtkpx2DImageSlice *New();
+  vtkTypeMacro(vtkpx2DImageSlice,vtkpxEnclosedPipeline);
+
+  // Description:
+  // Add a part to the list of parts.
+  virtual void SetInput(vtkImageData* image);
+  virtual void SetLookupTable(vtkLookupTable* table);
+  virtual void SetInterpolation(int on);
+  virtual void SetOpacity(float opacity);
+
+  // Description:
+  // Set Key Location Parameters 
+  virtual void SetLevel(int level);
+  virtual void SetCurrentPlane(int CurrentPlane);
+
+  virtual void SetPolarMode(int mode);
+  virtual void SetPolarMiddle(float polarmiddle=-1);
+
+  vtkGetMacro(CurrentPlane,int);
+  vtkGetMacro(Level,int);
+
+  vtkGetMacro(Opacity,float);
+  vtkGetMacro(Interpolation,int);
+
+  vtkGetMacro(OwnsColorMap,int);
+
+  vtkGetMacro(PolarMode,int);
+  vtkGetMacro(PolarMiddle,float);
+
+  vtkSetClampMacro(AutoUpdate,int,0,1);
+  vtkGetMacro(AutoUpdate,int);
+  vtkBooleanMacro(AutoUpdate,int);
+
+
+  virtual void Update() { this->UpdateSlice();}
+  virtual void UpdateTexture();
+
+  vtkGetObjectMacro(CurrentImage,vtkImageData);
+
+protected:
+
+  vtkActor*                    ImageSlice;
+  vtkPlaneSource*              ImagePlane;
+  vtkImageData*                CurrentImage;
+  vtkTexture*                  ImageTexture;
+  int                          Level;
+
+  float                        OutlineBounds[6];
+  int                          CurrentPlane;
+
+  float                        Opacity;
+  int                          Interpolation;
+  int                          AutoUpdate;
+
+  vtkLookupTable*              ColorMap;
+  int                          OwnsColorMap;   
+
+  int                          PolarMode;
+  float                        PolarMiddle;
+
+  vtkpx2DImageSlice();
+  virtual ~vtkpx2DImageSlice();
+  vtkpx2DImageSlice(const vtkpx2DImageSlice&) {};
+  void operator=(const vtkpx2DImageSlice&) {};
+
+  // Slice Stuff
+  virtual void BuildImageSlice();
+  virtual void UpdateSlice();
+  virtual void UpdateSlicePolar();
+
+
+};
+
+
+#endif
+
+
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxAddDisplacementVectorToPolyData.cpp b/bioimagesuite30_src/Graphics/vtkpxAddDisplacementVectorToPolyData.cpp
new file mode 100644
index 0000000..9510fdc
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxAddDisplacementVectorToPolyData.cpp
@@ -0,0 +1,159 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAddDisplacementVectorToPolyData.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/07/15 14:14:00 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxAddDisplacementVectorToPolyData.h"
+#include "pxutil.h"
+#include "vtkObjectFactory.h"
+#include "vtkPolyDataNormals.h"
+#include "vtkFloatArray.h"
+#include "vtkPoints.h"
+#include "vtkCleanPolyData.h"
+#include "vtkPointLocator.h"
+//--------------------------------------------------------------------------
+vtkpxAddDisplacementVectorToPolyData* vtkpxAddDisplacementVectorToPolyData::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxAddDisplacementVectorToPolyData");
+  if(ret)
+    {
+    return (vtkpxAddDisplacementVectorToPolyData*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxAddDisplacementVectorToPolyData;
+}
+
+vtkpxAddDisplacementVectorToPolyData::vtkpxAddDisplacementVectorToPolyData()
+{
+  this->SamplingDistance = 0.5;
+  this->Scale=1.0;
+  this->Displacements=NULL;
+}
+
+void vtkpxAddDisplacementVectorToPolyData::SetDisplacements(vtkFloatArray* disp)
+{
+  this->Displacements=disp;
+}
+
+void vtkpxAddDisplacementVectorToPolyData::Execute()
+{
+  vtkPolyData *source = this->GetInput();
+  vtkPolyData *destination= this->GetOutput();
+
+  fprintf(stderr,"Here\n");
+  if (this->Displacements==NULL || source==NULL || destination==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs\n");
+      return;
+    }
+  
+  if (this->Displacements->GetNumberOfTuples()!=source->GetNumberOfPoints())
+    {
+      vtkErrorMacro(<<"Not Enough Displacemnts\n");
+      return;
+    }
+
+  
+  vtkDebugMacro(<<"Beginning\n "<<source->GetNumberOfPoints()<<","<<this->Displacements->GetNumberOfTuples()<<"\n");
+
+  vtkCleanPolyData* clean=vtkCleanPolyData::New();
+  clean->SetToleranceIsAbsolute(1);
+  clean->SetAbsoluteTolerance(this->SamplingDistance);
+  clean->SetInput(source);
+  clean->Update();
+
+  int np=clean->GetOutput()->GetNumberOfPoints();
+  vtkPoints* oldpoints=clean->GetOutput()->GetPoints();
+
+  vtkPoints* points=vtkPoints::New();
+  points->SetNumberOfPoints(np*2);
+
+  vtkPointLocator* locator=vtkPointLocator::New();
+  locator->SetDataSet(clean->GetOutput());
+  locator->BuildLocator();
+
+  vtkCellArray* lines=vtkCellArray::New();
+  lines->Allocate(np,10);
+
+  vtkIdType pt[2];
+  double x[3],dx[3];
+  for (int i=0;i<np;i++)
+    {
+      oldpoints->GetPoint(i,x);
+      points->SetPoint(i,x);
+
+      int id=locator->FindClosestPoint(x);
+      this->Displacements->GetTuple(id,dx);
+      
+      for (int ia=0;ia<=2;ia++)
+	dx[ia]=x[ia]+this->Scale*dx[ia];
+      points->SetPoint(i+np,dx);
+      pt[0]=i;
+      pt[1]=pt[0]+np;
+      lines->InsertNextCell(2,pt);
+    }
+
+  destination->SetPoints(points);
+  destination->SetPolys(clean->GetOutput()->GetPolys());
+  destination->SetLines(lines);
+
+  points->Delete();
+  lines->Delete();
+  clean->Delete();
+  locator->Delete();
+}
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxAddDisplacementVectorToPolyData.h b/bioimagesuite30_src/Graphics/vtkpxAddDisplacementVectorToPolyData.h
new file mode 100644
index 0000000..cb9fc5c
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxAddDisplacementVectorToPolyData.h
@@ -0,0 +1,104 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAddDisplacementVectorToPolyData.h,v $
+  Language:  C++
+  Date:      $Date: 2002/07/15 14:13:22 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#ifndef __vtkpxAddDisplacementVectorToPolyData_h
+#define __vtkpxAddDisplacementVectorToPolyData_h
+
+class vtkDataSet;
+#include "vtkFloatArray.h"
+#include "vtkPolyDataToPolyDataFilter.h"
+#include "vtkDataArray.h"
+#include "vtkCellArray.h"
+#include "vtkDataObject.h"
+#include "vtkPolyData.h"
+#include "vtkPointData.h"
+
+class vtkpxAddDisplacementVectorToPolyData : public vtkPolyDataToPolyDataFilter 
+{
+public:
+  static vtkpxAddDisplacementVectorToPolyData *New();
+  vtkTypeMacro(vtkpxAddDisplacementVectorToPolyData,vtkPolyDataToPolyDataFilter);
+
+  // Description:
+  // Set/Get the scaling factor for the displacement
+  vtkSetMacro(Scale,float);
+  vtkGetMacro(Scale,float);
+
+  // Description:
+  // Get/Set the sampling distance
+  vtkSetMacro(SamplingDistance,float);
+  vtkGetMacro(SamplingDistance,float);
+
+  // Description:
+  // Get/Set Vector Data
+  void SetDisplacements(vtkFloatArray* Displacements);
+
+protected:
+  vtkpxAddDisplacementVectorToPolyData();
+
+  vtkpxAddDisplacementVectorToPolyData(const vtkpxAddDisplacementVectorToPolyData&) {};
+  void operator=(const vtkpxAddDisplacementVectorToPolyData&) {};
+
+  void Execute();
+  float SamplingDistance;
+  float Scale;
+  vtkFloatArray* Displacements;
+
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxAppendAndLabelPolyData.cpp b/bioimagesuite30_src/Graphics/vtkpxAppendAndLabelPolyData.cpp
new file mode 100644
index 0000000..629f228
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxAppendAndLabelPolyData.cpp
@@ -0,0 +1,785 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+#include "vtkpxAppendAndLabelPolyData.h"
+
+#include "vtkAlgorithmOutput.h"
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkDataSetAttributes.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkLookupTable.h"
+
+vtkCxxRevisionMacro(vtkpxAppendAndLabelPolyData, "$Revision: 1.103 $");
+vtkStandardNewMacro(vtkpxAppendAndLabelPolyData);
+
+//----------------------------------------------------------------------------
+vtkpxAppendAndLabelPolyData::vtkpxAppendAndLabelPolyData()
+{
+  this->ParallelStreaming = 0;
+  this->UserManagedInputs = 0;
+}
+
+//----------------------------------------------------------------------------
+vtkpxAppendAndLabelPolyData::~vtkpxAppendAndLabelPolyData()
+{
+}
+
+//----------------------------------------------------------------------------
+// Add a dataset to the list of data to append.
+void vtkpxAppendAndLabelPolyData::AddInput(vtkPolyData *ds)
+{
+  if (this->UserManagedInputs)
+    {
+    vtkErrorMacro(<<
+      "AddInput is not supported if UserManagedInputs is true");
+    return;
+    }
+  this->Superclass::AddInput(ds);
+}
+
+//----------------------------------------------------------------------------
+// Remove a dataset from the list of data to append.
+void vtkpxAppendAndLabelPolyData::RemoveInput(vtkPolyData *ds)
+{
+  if (this->UserManagedInputs)
+    {
+    vtkErrorMacro(<<
+      "RemoveInput is not supported if UserManagedInputs is true");
+    return;
+    }
+
+  vtkAlgorithmOutput *algOutput = 0;
+  if (ds)
+    {
+    algOutput = ds->GetProducerPort();
+    }
+
+  this->RemoveInputConnection(0, algOutput);
+}
+
+//----------------------------------------------------------------------------
+// make ProcessObject function visible
+// should only be used when UserManagedInputs is true.
+void vtkpxAppendAndLabelPolyData::SetNumberOfInputs(int num)
+{
+  if (!this->UserManagedInputs)
+    {
+    vtkErrorMacro(<<
+      "SetNumberOfInputs is not supported if UserManagedInputs is false");
+    return;
+    }
+
+  // Ask the superclass to set the number of connections.
+  this->SetNumberOfInputConnections(0, num);
+}
+
+//----------------------------------------------------------------------------
+// Set Nth input, should only be used when UserManagedInputs is true.
+void vtkpxAppendAndLabelPolyData::SetInputByNumber(int num, vtkPolyData *input)
+{
+  if (!this->UserManagedInputs)
+    {
+    vtkErrorMacro(<<
+      "SetInputByNumber is not supported if UserManagedInputs is false");
+    return;
+    }
+
+  // Ask the superclass to connect the input.
+  this->SetNthInputConnection(0, num, input? input->GetProducerPort() : 0);
+}
+
+//----------------------------------------------------------------------------
+// This method is much too long, and has to be broken up!
+// Append data sets into single polygonal data set.
+int vtkpxAppendAndLabelPolyData::RequestData(vtkInformation *vtkNotUsed(request),
+                                   vtkInformationVector **inputVector,
+                                   vtkInformationVector *outputVector)
+{
+  // get the info object
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  // get the ouptut
+  vtkPolyData *output = vtkPolyData::SafeDownCast(
+    outInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+  int idx;
+  vtkPolyData *ds;
+  vtkPoints  *inPts;
+  vtkPoints *newPts;
+  vtkCellArray *inVerts, *newVerts;
+  vtkCellArray *inLines, *newLines;
+  vtkCellArray *inPolys, *newPolys;
+  vtkIdType sizePolys, numPolys;
+  vtkCellArray *inStrips, *newStrips;
+  vtkIdType numPts, numCells;
+  vtkPointData *inPD = NULL;
+  vtkCellData *inCD = NULL;
+  vtkPointData *outputPD = output->GetPointData();
+  vtkCellData *outputCD = output->GetCellData();
+  vtkDataArray *newPtScalars = vtkDataArray::CreateDataArray(VTK_SHORT);
+  vtkDataArray *newPtVectors = NULL;
+  vtkDataArray *newPtNormals = NULL;
+  vtkDataArray *newPtTCoords = NULL;
+  vtkDataArray *newPtTensors = NULL;
+  int i;
+  vtkIdType *pts = 0;
+  vtkIdType *pPolys;
+  vtkIdType npts = 0;
+  vtkIdType ptId, cellId;
+  
+  vtkDebugMacro(<<"Appending polydata");
+
+  // loop over all data sets, checking to see what point data is available.
+  numPts = 0;
+  numCells = 0;
+  sizePolys = numPolys = 0;
+
+  int countPD=0;
+  int countCD=0;
+
+  vtkIdType numVerts = 0, numLines = 0, numStrips = 0;
+
+  int numInputs = this->GetNumberOfInputConnections(0);
+  vtkInformation *inInfo;
+
+  // These Field lists are very picky.  Count the number of non empty inputs
+  // so we can initialize them properly.
+  for (idx = 0; idx < numInputs; ++idx)
+    {
+    inInfo = inputVector[0]->GetInformationObject(idx);
+    ds = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
+    if (ds != NULL)
+      {
+      if ( ds->GetNumberOfPoints() > 0)
+        {
+        ++countPD;
+        }
+      if (ds->GetNumberOfCells() > 0 )  
+        {
+        ++countCD;
+        } // for a data set that has cells
+      } // for a non NULL input
+    } // for each input
+
+  // These are used to determine which fields are available for appending
+  vtkDataSetAttributes::FieldList ptList(countPD);
+  vtkDataSetAttributes::FieldList cellList(countCD);  
+  
+  countPD = countCD = 0;
+  for (idx = 0; idx < numInputs; ++idx)
+    {
+    inInfo = inputVector[0]->GetInformationObject(idx);
+    ds = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
+    if (ds != NULL)
+      {
+      // Skip points and cells if there are no points.  Empty inputs may have no arrays.
+      if ( ds->GetNumberOfPoints() > 0)
+        {
+        numPts += ds->GetNumberOfPoints();
+        // Take intersection of available point data fields.
+        inPD = ds->GetPointData();
+        if ( countPD == 0 )
+          {
+          ptList.InitializeFieldList(inPD);
+          }
+        else
+          {
+          ptList.IntersectFieldList(inPD);
+          }
+        ++countPD;
+        } // for a data set that has points
+        
+      // Although we cannot have cells without points ... let's not nest.
+      if (ds->GetNumberOfCells() > 0 )  
+        {
+        // keep track of the size of the poly cell array
+        if (ds->GetPolys())
+          {
+          sizePolys += ds->GetPolys()->GetNumberOfConnectivityEntries();
+          }
+        numCells += ds->GetNumberOfCells();
+        // Count the cells of each type.
+        // This is used to ensure that cell data is copied at the correct
+        // locations in the output.
+        numVerts += ds->GetNumberOfVerts();
+        numLines += ds->GetNumberOfLines();
+        numPolys += ds->GetNumberOfPolys();
+        numStrips += ds->GetNumberOfStrips();
+        
+        inCD = ds->GetCellData();
+        if ( countCD == 0 )
+          {
+          cellList.InitializeFieldList(inCD);
+          }
+        else
+          {
+          cellList.IntersectFieldList(inCD);
+          }
+        ++countCD;
+        } // for a data set that has cells
+      } // for a non NULL input
+    } // for each input
+
+  if ( numPts < 1 || numCells < 1 )
+    {
+    vtkDebugMacro(<<"No data to append!");
+    return 1;
+    }
+  this->UpdateProgress(0.10);
+
+  // AllocateScalars
+  if (newPtScalars)
+    {
+      newPtScalars->SetNumberOfComponents(1);
+      newPtScalars->SetNumberOfTuples(numPts);
+    }
+
+  // Allocate Scalar Lookup Table 
+  vtkLookupTable*cmap =vtkLookupTable::New();
+  cmap->SetNumberOfTableValues(numInputs);
+  cmap->SetTableRange(0,numInputs);
+  float numc=float(cmap->GetNumberOfColors());
+  for (i=0;i<cmap->GetNumberOfColors();i++)
+      {
+	float v=float(i+1)/float(numc);
+	cmap->SetTableValue(i,v,v,1-v,1.0);
+      }
+  newPtScalars->SetLookupTable(cmap);
+  cmap->Delete();
+
+
+  // Examine the points and check if they're the same type. If not,
+  // use highest (double probably), otherwise the type of the first
+  // array (float no doubt). Depends on defs in vtkSetGet.h - Warning.
+  int ttype, firstType=1, AllSame=1;
+  int pointtype = 0;
+
+  // Keep track of types for fast point append
+  for (idx = 0; idx < numInputs; ++idx)
+    {
+    inInfo = inputVector[0]->GetInformationObject(idx);
+    ds = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
+    if (ds != NULL && ds->GetNumberOfPoints()>0)
+      {
+      if ( firstType )
+        {
+        firstType = 0;
+        pointtype = ds->GetPoints()->GetData()->GetDataType();
+        }
+      ttype = ds->GetPoints()->GetData()->GetDataType();
+      
+      if ( ttype != pointtype )
+        {
+        AllSame = 0;
+        vtkDebugMacro(<<"Different point data types");
+        }
+      pointtype = pointtype > ttype ? pointtype : ttype;
+      }
+    }
+
+  // Allocate geometry/topology
+  newPts = vtkPoints::New(pointtype);
+  newPts->SetNumberOfPoints(numPts);
+
+  newVerts = vtkCellArray::New();
+  newVerts->Allocate(numCells*4);
+
+  newLines = vtkCellArray::New();
+  newLines->Allocate(numCells*4);
+
+  newStrips = vtkCellArray::New();
+  newStrips->Allocate(numCells*4);
+
+  newPolys = vtkCellArray::New();
+  pPolys = newPolys->WritePointer(numPolys, sizePolys);
+
+  if (!pPolys && sizePolys > 0)
+    {
+    vtkErrorMacro(<<"Memory allocation failed in append filter");
+    return 0;
+    }
+
+
+  // loop over all input sets
+  vtkIdType ptOffset = 0;
+  vtkIdType vertOffset = 0;
+  vtkIdType linesOffset = 0;
+  vtkIdType polysOffset = 0;
+  vtkIdType stripsOffset = 0;
+  countPD = countCD = 0;
+  for (idx = 0; idx < numInputs; ++idx)
+    {
+    this->UpdateProgress(0.2 + 0.8*idx/numInputs);
+    inInfo = inputVector[0]->GetInformationObject(idx);
+    ds = vtkPolyData::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
+    // this check is not necessary, but I'll put it in anyway
+    if (ds != NULL)
+      {
+      numPts = ds->GetNumberOfPoints();
+      numCells = ds->GetNumberOfCells();
+      if ( numPts <= 0 && numCells <= 0 )
+        {
+        continue; //no input, just skip
+        }
+
+      inPD = ds->GetPointData();
+      inCD = ds->GetCellData();
+
+      inPts = ds->GetPoints();
+      inVerts = ds->GetVerts();
+      inLines = ds->GetLines();
+      inPolys = ds->GetPolys();
+      inStrips = ds->GetStrips();
+
+      if (ds->GetNumberOfPoints() > 0)
+        {
+        // copy points directly
+        if (AllSame)
+          {
+          this->AppendData(newPts->GetData(),
+                           inPts->GetData(), ptOffset);
+          }
+        else
+          {
+          this->AppendDifferentPoints(newPts->GetData(),
+                                      inPts->GetData(), ptOffset);
+          }
+        // copy scalars directly
+	if (newPtScalars)
+	  {
+	    for (i=0;i<ds->GetNumberOfPoints();i++)
+	      newPtScalars->SetComponent(i+ptOffset,0,idx);
+	  }
+	
+        // copy normals directly
+        if (newPtNormals)
+          {
+	    this->AppendData(newPtNormals, inPD->GetNormals(), ptOffset);
+          }
+        // copy vectors directly
+        if (newPtVectors)
+          {
+	    this->AppendData(newPtVectors, inPD->GetVectors(), ptOffset);
+          }
+        // copy tcoords directly
+        if (newPtTCoords)
+          {
+	    this->AppendData(newPtTCoords, inPD->GetTCoords() , ptOffset);
+          }
+        // copy tensors directly
+        if (newPtTensors)
+          {
+	    this->AppendData(newPtTensors, inPD->GetTensors(), ptOffset);
+          }
+        // append the remainder of the field data
+        for (ptId=0; ptId < numPts; ptId++)
+          {
+	    outputPD->CopyData(ptList,inPD,countPD,ptId,ptId+ptOffset);
+          }
+        ++countPD;
+        }
+
+
+      if (ds->GetNumberOfCells() > 0)
+        {
+        // These are the cellIDs at which each of the cell types start.
+        vtkIdType linesIndex = ds->GetNumberOfVerts();
+        vtkIdType polysIndex = linesIndex + ds->GetNumberOfLines();
+        vtkIdType stripsIndex = polysIndex + ds->GetNumberOfPolys();
+
+        // cell data could be made efficient like the point data,
+        // but I will wait on that.
+        // copy cell data
+        for (cellId=0; cellId < numCells; cellId++)
+          {
+          vtkIdType outCellId = 0;
+          if (cellId < linesIndex)
+            {
+            outCellId = vertOffset;
+            vertOffset++;
+            }
+          else if (cellId < polysIndex)
+            {
+            // outCellId = number of lines we already added + total number of 
+            // verts expected in the output.
+            outCellId = linesOffset + numVerts;
+            linesOffset++;
+            }
+          else if (cellId < stripsIndex)
+            {
+            // outCellId = number of polys we already added + total number of 
+            // verts and lines expected in the output.
+            outCellId = polysOffset + numLines + numVerts;
+            polysOffset++;
+            }
+          else
+            {
+            // outCellId = number of tstrips we already added + total number of 
+            // polys, verts and lines expected in the output.
+            outCellId = stripsOffset + numPolys + numLines + numVerts;
+            stripsOffset++;
+            }
+          outputCD->CopyData(cellList,inCD,countCD,cellId,outCellId);
+          }
+        ++countCD;
+        
+        // copy the cells
+        pPolys = this->AppendCells(pPolys, inPolys, ptOffset);
+        
+        // These other cell arrays could be made efficient like polys ...
+        for (inVerts->InitTraversal(); inVerts->GetNextCell(npts,pts); )
+          {
+          newVerts->InsertNextCell(npts);
+          for (i=0; i < npts; i++)
+            {
+            newVerts->InsertCellPoint(pts[i]+ptOffset);
+            }
+          }
+        
+        for (inLines->InitTraversal(); inLines->GetNextCell(npts,pts); )
+          {
+          newLines->InsertNextCell(npts);
+          for (i=0; i < npts; i++)
+            {
+            newLines->InsertCellPoint(pts[i]+ptOffset);
+            }
+          }
+
+        for (inStrips->InitTraversal(); inStrips->GetNextCell(npts,pts); )
+          {
+          newStrips->InsertNextCell(npts);
+          for (i=0; i < npts; i++)
+            {
+            newStrips->InsertCellPoint(pts[i]+ptOffset);
+            }
+          }
+        }
+      ptOffset += numPts;
+      }
+    }
+  
+  // Update ourselves and release memory
+  //
+  output->SetPoints(newPts);
+  newPts->Delete();
+
+  if (newPtScalars)
+    {
+    output->GetPointData()->SetScalars(newPtScalars);
+    newPtScalars->Delete();
+    }
+  if (newPtNormals)
+    {
+    output->GetPointData()->SetNormals(newPtNormals);
+    newPtNormals->Delete();
+    }
+  if (newPtVectors)
+    {
+    output->GetPointData()->SetVectors(newPtVectors);
+    newPtVectors->Delete();
+    }
+  if (newPtTCoords)
+    {
+    output->GetPointData()->SetTCoords(newPtTCoords);
+    newPtTCoords->Delete();
+    }
+  if (newPtTensors)
+    {
+    output->GetPointData()->SetTensors(newPtTensors);
+    newPtTensors->Delete();
+    }
+  
+  if ( newVerts->GetNumberOfCells() > 0 )
+    {
+    output->SetVerts(newVerts);
+    }
+  newVerts->Delete();
+
+  if ( newLines->GetNumberOfCells() > 0 )
+    {
+    output->SetLines(newLines);
+    }
+  newLines->Delete();
+
+  if ( newPolys->GetNumberOfCells() > 0 )
+    {
+    output->SetPolys(newPolys);
+    }
+  newPolys->Delete();
+
+  if ( newStrips->GetNumberOfCells() > 0 )
+    {
+    output->SetStrips(newStrips);
+    }
+  newStrips->Delete();
+
+  // When all optimizations are complete, this squeeze will be unecessary.
+  // (But it does not seem to cost much.)
+  output->Squeeze();
+
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+int vtkpxAppendAndLabelPolyData::RequestUpdateExtent(vtkInformation *vtkNotUsed(request),
+                                           vtkInformationVector **inputVector,
+                                           vtkInformationVector *outputVector)
+{
+  // get the output info object
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  int piece, numPieces, ghostLevel;
+  int idx;
+
+  piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
+  numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
+  ghostLevel = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
+  
+  // make sure piece is valid
+  if (piece < 0 || piece >= numPieces)
+    {
+    return 0;
+    }
+
+  int numInputs = this->GetNumberOfInputConnections(0);
+  if (this->ParallelStreaming)
+    {
+    piece = piece * numInputs;
+    numPieces = numPieces * numInputs;
+    }
+ 
+  vtkInformation *inInfo;
+  // just copy the Update extent as default behavior.
+  for (idx = 0; idx < numInputs; ++idx)
+    {
+    inInfo = inputVector[0]->GetInformationObject(idx);
+    if (inInfo)
+      {
+      if (this->ParallelStreaming)
+        {
+        inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
+                    piece + idx);
+        inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
+                    numPieces);
+        inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
+                    ghostLevel);
+        }
+      else
+        {
+        inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(),
+                    piece);
+        inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(),
+                    numPieces);
+        inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(),
+                    ghostLevel);
+        }
+      }
+    }
+  
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+vtkPolyData *vtkpxAppendAndLabelPolyData::GetInput(int idx)
+{
+  return vtkPolyData::SafeDownCast(
+    this->GetExecutive()->GetInputData(0, idx));
+}
+
+//----------------------------------------------------------------------------
+void vtkpxAppendAndLabelPolyData::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+
+  os << "ParallelStreaming:" << (this->ParallelStreaming?"On":"Off") << endl;
+  os << "UserManagedInputs:" << (this->UserManagedInputs?"On":"Off") << endl;
+}
+
+//----------------------------------------------------------------------------
+template <class T>
+size_t vtkpxAppendAndLabelPolyDataGetTypeSize(T*)
+{
+  return sizeof(T);
+}
+
+//----------------------------------------------------------------------------
+void vtkpxAppendAndLabelPolyData::AppendData(vtkDataArray *dest, vtkDataArray *src,
+                                   vtkIdType offset)
+{
+  void *pSrc, *pDest;
+  vtkIdType length;
+
+  // sanity checks
+  if (src->GetDataType() != dest->GetDataType())
+    {
+    vtkErrorMacro("Data type mismatch.");
+    return;
+    }
+  if (src->GetNumberOfComponents() != dest->GetNumberOfComponents())
+    {
+    vtkErrorMacro("NumberOfComponents mismatch.");
+    return;
+    }
+  if (src->GetNumberOfTuples() + offset > dest->GetNumberOfTuples())
+    {
+    vtkErrorMacro("Destination not big enough");
+    return;
+    }
+  
+  // convert from tuples to components.
+  offset *= src->GetNumberOfComponents();
+  length = src->GetMaxId() + 1;
+
+  switch (src->GetDataType())
+    {
+    vtkTemplateMacro(
+      length *= vtkpxAppendAndLabelPolyDataGetTypeSize(static_cast<VTK_TT*>(0))
+      );
+    default:
+      vtkErrorMacro("Unknown data type " << src->GetDataType());
+    }
+
+  pSrc  = src->GetVoidPointer(0);
+  pDest = dest->GetVoidPointer(offset);
+
+  memcpy(pDest, pSrc, length);
+}
+
+//----------------------------------------------------------------------------
+void vtkpxAppendAndLabelPolyData::AppendDifferentPoints(vtkDataArray *dest,
+                                              vtkDataArray *src,
+                                              vtkIdType offset)
+{
+  float  *fSrc;
+  double *dSrc, *dDest;
+  vtkIdType p;
+
+  if (src->GetNumberOfTuples() + offset > dest->GetNumberOfTuples())
+    {
+    vtkErrorMacro("Destination not big enough");
+    return;
+    }
+
+  vtkIdType vals = src->GetMaxId()+1;
+  switch (dest->GetDataType())
+    {
+    //
+    // Dest is FLOAT - if sources are not all same type, dest ought to
+    // be double. (assuming float and double are the only choices)
+    //
+    case VTK_FLOAT:
+        vtkErrorMacro("Dest type should be double? "
+            << dest->GetDataType());
+        break;
+    //
+    // Dest is DOUBLE - sources may be mixed float/double combinations
+    //
+
+    case VTK_DOUBLE:
+      dDest = static_cast<double*>(
+        dest->GetVoidPointer(offset*src->GetNumberOfComponents()));
+      //
+      switch (src->GetDataType())
+        {
+        case VTK_FLOAT:
+          fSrc = static_cast<float*>(src->GetVoidPointer(0));
+          for (p=0; p<vals; p++)
+            {
+            dDest[p] = static_cast<double>(fSrc[p]);
+            }
+          break;
+        case VTK_DOUBLE:
+          dSrc = static_cast<double*>(src->GetVoidPointer(0));
+          memcpy(dDest, dSrc, vals*sizeof(double));
+          break;
+        default:
+          vtkErrorMacro("Unknown data type " << dest->GetDataType());
+        }
+      break;
+      //
+    default:
+      vtkErrorMacro("Unknown data type " << dest->GetDataType());
+    }
+
+}
+
+
+//----------------------------------------------------------------------------
+// returns the next pointer in dest
+vtkIdType *vtkpxAppendAndLabelPolyData::AppendCells(vtkIdType *pDest, vtkCellArray *src,
+                                          vtkIdType offset)
+{
+  vtkIdType *pSrc, *end, *pNum;
+
+  if (src == NULL)
+    {
+    return pDest;
+    }
+
+  pSrc = src->GetPointer();
+  end = pSrc + src->GetNumberOfConnectivityEntries();
+  pNum = pSrc;
+  
+  while (pSrc < end)
+    {
+    if (pSrc == pNum)
+      {
+      // move cell pointer to next cell
+      pNum += 1+*pSrc;
+      // copy the number of cells
+      *pDest++ = *pSrc++;
+      }
+    else
+      {
+      // offset the point index
+      *pDest++ = offset + *pSrc++;
+      }
+    }
+  
+  return pDest;
+}
+
+//----------------------------------------------------------------------------
+int vtkpxAppendAndLabelPolyData::FillInputPortInformation(int port, vtkInformation *info)
+{
+  if (!this->Superclass::FillInputPortInformation(port, info))
+    {
+    return 0;
+    }
+  info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1);
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxAppendAndLabelPolyData.h b/bioimagesuite30_src/Graphics/vtkpxAppendAndLabelPolyData.h
new file mode 100644
index 0000000..b02b217
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxAppendAndLabelPolyData.h
@@ -0,0 +1,156 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    $RCSfile: vtkpxAppendAndLabelPolyData.h,v $
+
+  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 vtkpxAppendAndLabelPolyData - appends one or more polygonal datasets together
+// .SECTION Description
+// 
+// vtkpxAppendAndLabelPolyData is a filter that appends one of more polygonal datasets
+// into a single polygonal dataset. All geometry is extracted and appended,
+// but point and cell attributes (i.e., scalars, vectors, normals) are
+// extracted and appended only if all datasets have the point and/or cell
+// attributes available.  (For example, if one dataset has point scalars but
+// another does not, point scalars will not be appended.)
+
+// .SECTION See Also
+// vtkpxAppendAndLabelFilter
+
+#ifndef __vtkpxAppendAndLabelPolyData_h
+#define __vtkpxAppendAndLabelPolyData_h
+
+#include "vtkPolyDataAlgorithm.h"
+
+class vtkCellArray;
+class vtkDataArray;
+class vtkPoints;
+class vtkPolyData;
+
+class  vtkpxAppendAndLabelPolyData : public vtkPolyDataAlgorithm
+{
+public:
+  static vtkpxAppendAndLabelPolyData *New();
+
+  vtkTypeRevisionMacro(vtkpxAppendAndLabelPolyData,vtkPolyDataAlgorithm);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // UserManagedInputs allows the user to set inputs by number instead of
+  // using the AddInput/RemoveInput functions. Calls to
+  // SetNumberOfInputs/SetInputByNumber should not be mixed with calls
+  // to AddInput/RemoveInput. By default, UserManagedInputs is false.
+  vtkSetMacro(UserManagedInputs,int);
+  vtkGetMacro(UserManagedInputs,int);
+  vtkBooleanMacro(UserManagedInputs,int);
+
+  // Description:
+  // Add a dataset to the list of data to append. Should not be
+  // used when UserManagedInputs is true, use SetInputByNumber instead.
+  void AddInput(vtkPolyData *);
+
+  // Description:
+  // Remove a dataset from the list of data to append. Should not be
+  // used when UserManagedInputs is true, use SetInputByNumber (NULL) instead.
+  void RemoveInput(vtkPolyData *);
+
+  // Description:
+  // Get any input of this filter.
+//BTX
+  vtkPolyData *GetInput(int idx);
+  vtkPolyData *GetInput() { return this->GetInput( 0 ); };
+//ETX
+
+  // Description:
+  // Directly set(allocate) number of inputs, should only be used
+  // when UserManagedInputs is true.
+  void SetNumberOfInputs(int num);
+
+  // Set Nth input, should only be used when UserManagedInputs is true.
+  void SetInputByNumber(int num, vtkPolyData *input);
+
+  // Description:
+  // ParallelStreaming is for a particular application.
+  // It causes this filter to ask for a different piece
+  // from each of its inputs.  If all the inputs are the same,
+  // then the output of this append filter is the whole dataset
+  // pieced back together.  Duplicate points are create 
+  // along the seams.  The purpose of this feature is to get 
+  // data parallelism at a course scale.  Each of the inputs
+  // can be generated in a different process at the same time.
+  vtkSetMacro(ParallelStreaming, int); 
+  vtkGetMacro(ParallelStreaming, int); 
+  vtkBooleanMacro(ParallelStreaming, int); 
+
+protected:
+  vtkpxAppendAndLabelPolyData();
+  ~vtkpxAppendAndLabelPolyData();
+
+  // Flag for selecting parallel streaming behavior
+  int ParallelStreaming;
+
+  // Usual data generation method
+  virtual int RequestData(vtkInformation *, 
+                          vtkInformationVector **, vtkInformationVector *);
+  virtual int RequestUpdateExtent(vtkInformation *, 
+                                  vtkInformationVector **, vtkInformationVector *);
+  virtual int FillInputPortInformation(int, vtkInformation *);
+
+  // An efficient way to append data/cells.
+  void AppendData(vtkDataArray *dest, vtkDataArray *src, vtkIdType offset);
+  void AppendDifferentPoints(vtkDataArray *dest, vtkDataArray *src,
+                             vtkIdType offset);
+  vtkIdType *AppendCells(vtkIdType *pDest, vtkCellArray *src,
+                         vtkIdType offset);
+
+ private:
+  // hide the superclass' AddInput() from the user and the compiler
+  void AddInput(vtkDataObject *)
+    { vtkErrorMacro( << "AddInput() must be called with a vtkPolyData not a vtkDataObject."); };
+
+  int UserManagedInputs;
+
+private:
+  vtkpxAppendAndLabelPolyData(const vtkpxAppendAndLabelPolyData&);  // Not implemented.
+  void operator=(const vtkpxAppendAndLabelPolyData&);  // Not implemented.
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxCameraInfo.cpp b/bioimagesuite30_src/Graphics/vtkpxCameraInfo.cpp
new file mode 100644
index 0000000..625787f
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxCameraInfo.cpp
@@ -0,0 +1,270 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCameraInfo.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/28 03:51:32 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxCameraInfo.h"
+#include "pxutil.h"
+//------------------------------------------------------------------------------
+vtkpxCameraInfo* vtkpxCameraInfo::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxCameraInfo");
+  if(ret)
+    {
+      return (vtkpxCameraInfo*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxCameraInfo;
+}
+vtkpxCameraInfo::vtkpxCameraInfo()
+{
+  this->CameraParameters=vtkDoubleArray::New();
+  this->CameraParameters->SetNumberOfComponents(13);
+  this->CameraParameters->Allocate(10,5);
+  // Focal Point[3]
+  params[0]=0.0; params[1]=0.0; params[2]=1.0;
+  // Position[3]
+  params[3]=0.0; params[4]=0.0; params[5]=1.0;
+  // ViewUp[3]
+  params[6]=0.0; params[7]=0.0; params[8]=1.0;
+  // ClippingRange[2]
+  params[9]=0.0; params[10]=100.0;
+  // Parallel Projection
+  params[11]=1.0;
+  // Parallel Scale
+  params[12]=1.0;
+
+  // this->CameraParameters->InsertNextTuple(params);
+}
+//------------------------------------------------------------------------------
+// Destruct a volume
+vtkpxCameraInfo::~vtkpxCameraInfo()
+{
+  this->CameraParameters->Delete();
+}
+//------------------------------------------------------------------------------
+int vtkpxCameraInfo::GetNumberOfCameras()
+{
+  return this->CameraParameters->GetNumberOfTuples();
+}
+//------------------------------------------------------------------------------
+int vtkpxCameraInfo::UpdateRenderer(vtkRenderer* ren,int index)
+{
+  if (ren==NULL)
+    return 0;
+  return this->UpdateCamera(ren->GetActiveCamera());
+}
+//------------------------------------------------------------------------------
+int vtkpxCameraInfo::UpdateCamera(vtkCamera* camera,int index)
+{
+  if (camera==NULL || this->GetNumberOfCameras()==0)
+    return 0;
+  
+  index=Irange(index,0,this->GetNumberOfCameras()-1);
+
+  this->CameraParameters->GetTuple(index,params);
+
+  camera->SetFocalPoint(params[0],params[1],params[2]);
+  camera->SetPosition(params[3],params[4],params[5]);
+  camera->SetViewUp(params[6],params[7],params[8]);
+  camera->ComputeViewPlaneNormal();
+  camera->SetClippingRange(params[9],params[10]);
+  camera->SetParallelProjection((int)params[11]);
+  camera->SetParallelScale(params[12]);
+  
+  /*  fprintf(stderr,"\t\t Setting params index=%d = %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n\n",
+	 params[0],params[1],params[2],
+	 params[3],params[4],params[5],
+	 params[6],params[7],params[8],
+	 params[9],params[10],params[11],
+	 params[12]);*/
+  
+  return 1;
+}
+//------------------------------------------------------------------------------
+int vtkpxCameraInfo::CopyRenderer(vtkRenderer* ren,int index)
+{
+ if (ren==NULL)
+   {
+     fprintf(stderr,"Bad Renderer\n");
+     return 0;
+   }
+  return this->CopyCamera(ren->GetActiveCamera());
+}
+//------------------------------------------------------------------------------
+int vtkpxCameraInfo::CopyCamera(vtkCamera* camera,int index)
+{
+ if (camera==NULL)
+   {
+     fprintf(stderr,"Bad Camera\n");
+     return 0;
+   }
+
+ if (index>=0)
+   {
+     index=Irange(index,0,this->GetNumberOfCameras()-1);
+   }
+ else
+   {
+     // Allocate a new one if (-1)
+     this->CameraParameters->InsertNextTuple(params);
+     index=this->GetNumberOfCameras()-1;
+   }
+    
+ for (int ia=0;ia<=2;ia++)
+   {
+     params[0+ia]=camera->GetFocalPoint()[ia];
+     params[3+ia]=camera->GetPosition()[ia];
+     params[6+ia]=camera->GetViewUp()[ia];
+     if (ia<2)
+       params[9+ia]=camera->GetClippingRange()[ia];
+   }
+ params[11]=(double)camera->GetParallelProjection();
+ params[12]=(double)camera->GetParallelScale();
+ 
+ /* fprintf(stderr,"Setting tuple=%d / %d\n",index,this->GetNumberOfCameras());
+ fprintf(stderr,"\t\t params = %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n",
+	 params[0],params[1],params[2],
+	 params[3],params[4],params[5],
+	 params[6],params[7],params[8],
+	 params[9],params[10],params[11],
+	 params[12]);*/
+ this->CameraParameters->SetTuple(index,params);  
+ this->CameraParameters->GetTuple(index,params);
+ /* fprintf(stderr,"\t\t Checking params = %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n\n",
+	 params[0],params[1],params[2],
+	 params[3],params[4],params[5],
+	 params[6],params[7],params[8],
+	 params[9],params[10],params[11],
+	 params[12]);
+
+	 this->Save("/tmp/camera.list");*/
+
+ return 1;
+
+}
+
+//------------------------------------------------------------------------------
+int vtkpxCameraInfo::Load(const char* fname)
+{
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (fin)
+    {
+      int ok=this->Load(fin);
+      gzclose(fin);
+      return ok;
+    }
+  return 0;
+}
+
+//------------------------------------------------------------------------------
+int vtkpxCameraInfo::Save(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout)
+    {
+      int ok=this->Save(fout);
+      fclose(fout);
+      return ok;
+    }
+  return 0;
+}
+//------------------------------------------------------------------------------
+
+int vtkpxCameraInfo::Load(gzFile fin)
+{
+  char line[400];
+  gzgets(fin,line,100);
+  if (gzfindstringinstring(line,"#vtkpxCameraInfo File")==0)
+    return 0;
+  
+  gzgets(fin,line,100); 	
+  gzgets(fin,line,100);
+  int num=0;
+  sscanf(line,"%d ",&num);
+  this->CameraParameters->Delete();
+  this->CameraParameters=vtkDoubleArray::New();
+  this->CameraParameters->SetNumberOfComponents(13);
+  this->CameraParameters->Allocate(num,5);
+  for (int i=0;i<num;i++)
+    {
+      gzgets(fin,line,399);
+      sscanf(line,"%lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
+	     &params[0],&params[1],&params[2],
+	     &params[3],&params[4],&params[5],
+	     &params[6],&params[7],&params[8],
+	     &params[9],&params[10],&params[11],
+	     &params[12]);
+      this->CameraParameters->InsertNextTuple(params);
+    }
+  return 1;
+}
+//------------------------------------------------------------------------------
+int vtkpxCameraInfo::Save(FILE*  fout)
+{
+  fprintf(fout,"#vtkpxCameraInfo File\n");
+  fprintf(fout,"#Number Of Camers\n%d\n",this->GetNumberOfCameras());
+  int nc=this->CameraParameters->GetNumberOfComponents();
+  for (int i=0;i<this->GetNumberOfCameras();i++)
+    {
+      this->CameraParameters->GetTuple(i,params);
+      for (int j=0;j<nc;j++)
+	fprintf(fout,"%.3f ",params[j]);
+      fprintf(fout,"\n");
+    }
+  return 1;
+}
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxCameraInfo.h b/bioimagesuite30_src/Graphics/vtkpxCameraInfo.h
new file mode 100644
index 0000000..6c22c97
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxCameraInfo.h
@@ -0,0 +1,122 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCameraInfo.h,v $
+  Language:  C++
+  Date:      $Date: 2002/07/15 12:58:30 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxCameraInfo - 
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+
+
+#ifndef __vtkpxCameraInfo_h
+#define __vtkpxCameraInfo_h
+
+#include "vtkObject.h"
+#include "vtkCamera.h"
+#include "vtkRenderer.h"
+#include "pxutil.h"
+#include "vtkDoubleArray.h"
+
+class vtkpxCameraInfo : public vtkObject
+{
+public:
+  static vtkpxCameraInfo *New();
+  vtkTypeMacro(vtkpxCameraInfo,vtkObject);
+  
+  // Description:
+  // Number of cameras
+  virtual int GetNumberOfCameras();
+
+  // Description:
+  // Interact with Camera and/or Renderer
+  virtual int UpdateCamera(vtkCamera* camera,int index=0);
+  virtual int UpdateRenderer(vtkRenderer* ren,int index=0);
+
+  // Description:
+  // Store camera info in this
+  virtual int CopyCamera(vtkCamera* camera,int index=-1);
+  virtual int CopyRenderer(vtkRenderer* ren,int index=-1);
+
+// Description:
+  // Store camera info in this
+  virtual int InsertCamera(vtkCamera* camera) { return this->CopyCamera(camera,-1); }
+  virtual int InsertRenderer(vtkRenderer* ren,int index=-1) { return this->CopyRenderer(ren,-1); }
+  
+
+  // Description:
+  // Load/Save Information
+  virtual int Load(const char* fname);
+  virtual int Load(gzFile fin);
+
+  virtual int Save(const char* fname);
+  virtual int Save(FILE*  fout);
+
+protected:
+  vtkpxCameraInfo();
+  virtual ~vtkpxCameraInfo();
+
+  // Description:
+  // Variables --- there are 13 components --> a Double Array should do it
+  vtkDoubleArray* CameraParameters;
+  double          params[13];
+  /*  double FocalPoint[3];
+  double Position[3];
+  double ViewUp[3];
+  double ClippingRange[2];
+  int    ParallelProjection;
+  double ParallelScale;*/
+  
+};
+#endif
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxColorMapUtil.cpp b/bioimagesuite30_src/Graphics/vtkpxColorMapUtil.cpp
new file mode 100644
index 0000000..6f5d28d
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxColorMapUtil.cpp
@@ -0,0 +1,1347 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxColorMapUtil.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/05/07 16:07:56 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxUtil.h"
+#include "vtkImageData.h"
+#include "vtkLookupTable.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkpxColorMapUtil.h"
+#include "vtkDataArray.h"
+#include "vtkImageQuantizeRGBToIndex.h"
+#include "vtkpxUtil.h"
+
+using namespace bioimagesuite_legacy;
+
+// ---------------------------
+
+vtkpxColorMapUtil* vtkpxColorMapUtil::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxColorMapUtil");
+  if(ret)
+      {
+	return (vtkpxColorMapUtil*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxColorMapUtil;
+}
+
+
+void vtkpxColorMapUtil::SetGammaColorMap(vtkLookupTable *cmap,float gamma,float min_value,float max_value,
+				       int num_colors,int vol)
+{
+
+  if (min_value==max_value)
+    ++max_value;
+  gamma=Frange(gamma,0.001,100.0);
+  if (num_colors!=cmap->GetNumberOfColors())
+      cmap->SetNumberOfTableValues(num_colors);
+  cmap->SetTableRange(min_value,max_value);
+
+  double gm=1.0/gamma;
+
+  for (int i=0;i<num_colors;i++)
+      {
+	double v=(float(i)/float(num_colors-1));
+
+	float vl=pow(v,gm);
+
+	if (vol)
+	  cmap->SetTableValue(i,vl,vl,vl,vl);
+	else if (i>0)
+	  cmap->SetTableValue(i,vl,vl,vl,1.0);
+	else
+	  cmap->SetTableValue(i,vl,vl,vl,0.0);
+      }
+
+  
+  
+}
+// ---------------------------------------------------------------------------------------------------------
+void vtkpxColorMapUtil::SetConstantHueColorMap(vtkLookupTable* cmap,float intensity,float hue1,float hue2,float cutoff,
+					     float min_value,float max_value,int num_colors,int vol)
+{
+
+  if (num_colors!=cmap->GetNumberOfColors() && num_colors>0)
+      cmap->SetNumberOfTableValues(num_colors);
+  //  fprintf(stderr,"\t ConstHue Number of Colors=%d\n",num_colors);
+  float numc=float(num_colors-1.0);
+  float inormal=numc/2.0;
+  if (cutoff==0.0)
+    cutoff=1.0;
+
+
+  cmap->SetTableRange(-cutoff,cutoff);
+
+
+  double fraction=1.0/inormal;
+
+  for (int j=0;j<num_colors;j++)
+      {
+	float s=float(j-inormal)/inormal;
+	float v=intensity;
+	float h=hue1;
+
+	if (s<0.0)
+	  {
+	    s=-s;
+	    h=hue2;
+	  }
+	
+	h*=6.0;
+	int i=int(h);
+	float aa,bb,cc,f,r=0,g=0,b=0;
+
+	f=h-float(i);
+
+	aa= v*(1.0-s);
+	bb= v*(1.0- (s*f));
+	cc= v*(1.0- (s* (1.0-f)));
+
+	switch (i)
+	    {
+	    case 0:
+	      r=v; g=cc; b=aa;
+	      break;
+	    case 1:
+	      r=bb; g=v; b=aa;
+	      break;
+	    case 2:
+	      r=aa; g=v; b=cc;
+	      break;
+	    case 3:
+	      r=aa; g=bb; b=v;
+	      break;
+	    case 4:
+	      r=cc; g=aa; b=v;
+	      break;
+	    case 5:
+	      r=v;  g=aa; b=bb;
+	      break;
+	    }
+
+	if (vol)
+	    cmap->SetTableValue(j,r,g,b,float(j)/float(num_colors));
+	else if (fabs(s)>fraction)
+	  cmap->SetTableValue(j,r,g,b,1.0);
+	else
+	  cmap->SetTableValue(j,r,g,b,0.0);
+      }
+}
+// ---------------------------------------------------------------------------------------------------------
+void vtkpxColorMapUtil::SetRainbowColorMap(vtkLookupTable *cmap,float min,float max,float min_value,float max_value,
+				      int num_colors,int vol)
+{
+  double gap=fabs(min_value-max_value)*0.1;
+
+  if (gap<1e-7)
+    {
+      max=min+1e-7;
+      gap=(min_value-max_value)*0.1;
+    }
+
+  min=Frange(min,min_value,max_value-gap);
+  max=Frange(max,min_value+gap,max_value);
+
+  if (max_value<(min_value+gap))
+      max_value+=gap;
+
+  float range=max_value-min_value;
+
+  if (num_colors!=cmap->GetNumberOfColors() && num_colors>0)
+      cmap->SetNumberOfTableValues(num_colors);
+
+  cmap->SetTableRange(min_value,max_value);
+
+  float numc=float(num_colors-1);
+
+  int imin=int(0.5+numc*float(min-min_value)/range);
+  int imax=int(0.5+numc*float(max-min_value)/range);
+
+  float rgb[3];
+  
+  for (int i=0;i<num_colors;i++)
+    {
+      float v=0.0;
+      if (i<=imin)
+	v=0.0;
+      else if (i>=imax)
+			v=1.0;
+      else
+	v=float(i-imin)/float(imax-imin);
+      
+      float H,S,V;
+      //H = (double)i/(double)num_colors * 340.0;
+      H = v * 340.0;
+      S = V = 1.0;
+      vtkpxColorMapUtil::HSVtoRGB(&rgb[0], &rgb[1], &rgb[2], H,S,V);
+      
+      if(vol)
+	cmap->SetTableValue(i, rgb[0], rgb[1], rgb[2], .5 *v);
+      else if (i>0)
+	cmap->SetTableValue(i, rgb[0], rgb[1], rgb[2], 1.0);
+      else 
+      	cmap->SetTableValue(i, rgb[0], rgb[1], rgb[2], 0.0);
+    }
+}
+
+// ---------------------------------------------------------------------------------------------------------
+void vtkpxColorMapUtil::SetReverseRainbowColorMap(vtkLookupTable *cmap,float min,float max,float min_value,float max_value,
+				      int num_colors,int vol)
+{
+  double gap=fabs(min_value-max_value)*0.1;
+
+  if (gap<1e-7)
+    {
+      max=min+1e-7;
+      gap=(min_value-max_value)*0.1;
+    }
+
+  min=Frange(min,min_value,max_value-gap);
+  max=Frange(max,min_value+gap,max_value);
+
+  if (max_value<(min_value+gap))
+    max_value+=gap;
+  
+  float range=max_value-min_value;
+
+  if (num_colors!=cmap->GetNumberOfColors() && num_colors>0)
+      cmap->SetNumberOfTableValues(num_colors);
+
+  cmap->SetTableRange(min_value,max_value);
+
+  float numc=float(num_colors-1);
+
+  int imin=int(0.5+numc*float(min-min_value)/range);
+  int imax=int(0.5+numc*float(max-min_value)/range);
+
+  float rgb[3];
+
+  for (int i=0;i<num_colors;i++)
+    {
+      float v=0.0;
+      if (i<=imin)
+	v=0.0;
+      else if (i>=imax)
+	v=1.0;
+      else
+	v=float(i-imin)/float(imax-imin);
+      
+      float H,S,V;
+      //H = 340.0 - ((double)i/(double)num_colors * 340.0);
+      H = v * 340.0;
+      S = V = 1.0;
+      vtkpxColorMapUtil::HSVtoRGB(&rgb[0], &rgb[1], &rgb[2], H,S,V);
+      
+      if(vol)
+	cmap->SetTableValue(i, rgb[0], rgb[1], rgb[2], .5 *v);
+      else if (i>0)
+	cmap->SetTableValue(i, rgb[0], rgb[1], rgb[2], 1.0);
+      else
+	cmap->SetTableValue(i, rgb[0], rgb[1], rgb[2], 0.0);
+    }
+}
+
+// ---------------------------------------------------------------------------------------------------------
+void vtkpxColorMapUtil::SetBlackBodyColorMap(vtkLookupTable *cmap,float min,float max,float min_value,float max_value,
+				      int num_colors,int vol)
+{
+  double gap=fabs(min_value-max_value)*0.1;
+
+  if (gap<1e-7)
+    {
+      max=min+1e-7;
+      gap=(min_value-max_value)*0.1;
+    }
+
+  min=Frange(min,min_value,max_value-gap);
+  max=Frange(max,min_value+gap,max_value);
+
+  if (max_value<(min_value+gap))
+      max_value+=gap;
+
+  float range=max_value-min_value;
+
+  if (num_colors!=cmap->GetNumberOfColors() && num_colors>0)
+      cmap->SetNumberOfTableValues(num_colors);
+
+  cmap->SetTableRange(min_value,max_value);
+
+  float numc=float(num_colors-1);
+
+  int imin=int(0.5+numc*float(min-min_value)/range);
+  int imax=int(0.5+numc*float(max-min_value)/range);
+  
+  float rgb[3], rgbmin[3], rgbmax[3]; ;
+  float blackbody[9][3] = {{255, 255, 229} ,
+			   {255, 247, 188},
+			   {254, 227, 145},
+			   {254, 196, 79},
+			   {254, 153, 41},
+			   {236, 112, 20},
+			   {204, 76, 2},
+			   {153, 52, 4},
+			   {102, 37, 6}};
+    
+    
+    for (int i=0;i<num_colors;i++)
+      {
+	float v=0.0;
+	if (i<=imin)
+	  v=0.0;
+	else if (i>=imax)
+	  v=1.0;
+	else
+	  v=float(i-imin)/float(imax-imin);
+	
+	int table_index_min = int(floor(8.0 * (1.0-v)));
+	int table_index_max = int(ceil(8.0 * (1.0-v)));
+	
+	float actual_value = (8.0 * (1.0-v)) - table_index_min;
+	
+	rgbmin[0] = blackbody[table_index_min][0]/255.0f;
+	rgbmin[1] = blackbody[table_index_min][1]/255.0f;
+	rgbmin[2] = blackbody[table_index_min][2]/255.0f;
+	
+	rgbmax[0] = blackbody[table_index_max][0]/255.0f;
+	rgbmax[1] = blackbody[table_index_max][1]/255.0f;
+	rgbmax[2] = blackbody[table_index_max][2]/255.0f;
+	
+	rgb[0] = rgbmin[0] + actual_value * (rgbmax[0] - rgbmin[0]);
+	rgb[1] = rgbmin[1] + actual_value * (rgbmax[1] - rgbmin[1]);
+	rgb[2] = rgbmin[2] + actual_value * (rgbmax[2] - rgbmin[2]);
+	
+	if(vol)
+	  cmap->SetTableValue(i, rgb[0], rgb[1], rgb[2], .5 *v);
+	else if (i>0)
+	  cmap->SetTableValue(i, rgb[0], rgb[1], rgb[2], 1.0);
+	else
+	  cmap->SetTableValue(i, rgb[0], rgb[1], rgb[2], 0.0);
+      }
+}
+// ---------------------------------------------------------------------------------------------------------
+void vtkpxColorMapUtil::SetStepColorMap(vtkLookupTable *cmap,float min,float max,float min_value,float max_value,
+				      int num_colors,int vol)
+{
+  double gap=fabs(min_value-max_value)*0.1;
+  //  fprintf(stderr,"Gap=%f min=%f,max=%f,minv=%f maxv=%f\n",gap,min,max,min_value,max_value);
+  if (gap<1e-7)
+    {
+      max=min+1e-7;
+      gap=(min_value-max_value)*0.1;
+    }
+  //  fprintf(stderr,"New Gap=%f min=%f,max=%f,minv=%f maxv=%f\n",gap,min,max,min_value,max_value);
+  min=Frange(min,min_value,max_value-gap);
+  max=Frange(max,min_value+gap,max_value);
+
+  if (max_value<(min_value+gap))
+      max_value+=gap;
+
+  float range=max_value-min_value;
+
+  if (num_colors!=cmap->GetNumberOfColors() && num_colors>0)
+      cmap->SetNumberOfTableValues(num_colors);
+  //  fprintf(stderr,"\t Step Number of Colors=%d\n",num_colors);
+  cmap->SetTableRange(min_value,max_value);
+
+  float numc=float(num_colors-1);
+
+  int imin=int(0.5+numc*float(min-min_value)/range);
+  int imax=int(0.5+numc*float(max-min_value)/range);
+
+   // fprintf(stderr,"imin=%d imax=%d num_colors=%d\n",imin,imax,num_colors);
+
+  for (int i=0;i<num_colors;i++)
+  {
+    float v=0.0;
+    if (i<=imin)
+      v=0.0;
+    else if (i>=imax)
+      v=1.0;
+    else
+      v=float(i-imin)/float(imax-imin);
+    if (vol)
+      cmap->SetTableValue(i,v,v,v,v*0.5);
+    else if (v>0.0)
+      cmap->SetTableValue(i,v,v,v,1.0);
+    else
+      cmap->SetTableValue(i,v,v,v,0.0);
+  }
+}
+//------------------------------------------------------------------------------
+void vtkpxColorMapUtil::CreateOverlayColorMap(vtkLookupTable *cmap,int mode,float min,float max,float min_value,float max_value,
+					      float intensity,float hue1,float hue2,int vol,int updatefunction)
+{
+  int numc=cmap->GetNumberOfColors();
+
+  if (mode!=64)
+    mode=256;
+
+  if (numc!=mode)
+    {
+      numc=mode;
+      cmap->SetNumberOfTableValues(numc);
+    }
+
+  int midrange=192;
+  int crange=32;
+
+  if (numc==64)
+    {
+      midrange=56;
+      crange=4;
+    }
+
+  int imin=int(0.5+numc*float(min-min_value)/float(midrange));
+  int imax=int(0.5+numc*float(max-min_value)/float(midrange));
+
+
+  cmap->SetTableRange(0,numc-1);
+
+  // Bottom Grayscale range
+  for (int i=0;i<midrange;i++)
+    {
+	float v=0.0;
+	if (i<=imin)
+	  v=0.0;
+	else if (i>=imax)
+	  v=1.0;
+	else
+	  v=float(i-imin)/float(imax-imin);
+
+	if (vol)
+	  cmap->SetTableValue(i,v,v,v,v*0.5);
+	else if (v>0.0)
+	  cmap->SetTableValue(i,v,v,v,1.0);
+	else
+	  cmap->SetTableValue(i,v,v,v,0.0);
+    }
+
+
+  if (updatefunction==1)
+    {
+      for (int j=0;j<2*crange;j++)
+	{
+	  float s=0.5*float(j-crange)/float(crange);
+	  float v=intensity;
+	  float h=hue1;
+
+	  if (s<0.0)
+	    {
+	      s=-s;
+	      h=hue2;
+	    }
+
+	  if (s<0.0)
+	    s-=0.5;
+	  else
+	    s+=0.5;
+
+	  h*=6.0;
+	  int i=int(h);
+	  float aa,bb,cc,f,r=0,g=0,b=0;
+
+	  f=h-float(i);
+
+	  aa= v*(1.0-s);
+	  bb= v*(1.0- (s*f));
+	  cc= v*(1.0- (s* (1.0-f)));
+
+	  switch (i)
+	    {
+	    case 0:
+	      r=v; g=cc; b=aa;
+	      break;
+	    case 1:
+	      r=bb; g=v; b=aa;
+	      break;
+	    case 2:
+	      r=aa; g=v; b=cc;
+	      break;
+	    case 3:
+	      r=aa; g=bb; b=v;
+	      break;
+	    case 4:
+	      r=cc; g=aa; b=v;
+	      break;
+	    case 5:
+	      r=v;  g=aa; b=bb;
+	      break;
+	    }
+
+	  if (vol)
+	    cmap->SetTableValue(j+midrange,r,g,b,fabs(s));
+	  else
+	    cmap->SetTableValue(j+midrange,r,g,b,1.0);
+	}
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxColorMapUtil::AutoUpdateColormapRange(vtkLookupTable* cmap,vtkImageData* img)
+{
+  if (img==NULL)
+      return;
+
+  double range[2];
+  img->GetPointData()->GetScalars()->GetRange(range);
+  //  fprintf(stderr,"Image Range %f:%f\n",range[0],range[1]);
+
+  //if (range[0]>=0.0)
+  vtkpxColorMapUtil::SetStepColorMap(cmap,range[0],range[1],range[0],range[1],256);
+  /*else
+    vtkpxColorMapUtil::SetConstantHueColorMap(cmap,0.5,0.02,0.58,
+			     Fmax(fabs(range[0]),fabs(range[1])),
+			     range[0],range[1],256);*/
+}
+//------------------------------------------------------------------------------
+void vtkpxColorMapUtil::ComputeStepBounds(vtkImageData* image,vtkDataArray* output,int np,float nsigma)
+{
+  if (image==NULL || output == NULL)
+    return;
+
+  nsigma=Frange(nsigma,0.01,10.0);
+
+  //  output->SetDataType(VTK_FLOAT);
+  output->SetNumberOfTuples(2);
+
+  double range[2];
+  vtkDataArray* scal=image->GetPointData()->GetScalars();
+  scal->GetRange(range);
+  int n=scal->GetNumberOfTuples(),inc=1;
+  if (n>np)
+    inc=int(n/np);
+
+  float mean=0.0,mean2=0.0;
+  int num=0;
+  for (int i=0;i<n;i+=inc)
+    {
+      float v=scal->GetComponent(i,0);
+      if (v!=0.0)
+	{
+	  mean+=v;
+	  mean2+=v*v;
+	  ++num;
+	}
+    }
+
+  if (num==0)
+    return;
+
+  mean/=float(num);
+  mean2/=float(num);
+  float std=sqrt(mean2-mean*mean);
+
+  output->SetComponent(0,0,Frange(mean-nsigma*std,range[0],range[1]-1.0));
+  output->SetComponent(1,0,Frange(mean+nsigma*std,range[0]+1.0,range[1]));
+}
+
+void vtkpxColorMapUtil::HSVtoRGB( float *r, float *g, float *b, float h, float s, float v )
+{
+	int i;
+	float f, p, q, t;
+
+	if( s == 0 ) {
+		// achromatic (grey)
+		*r = *g = *b = v;
+		return;
+	}
+
+	h /= 60;			// sector 0 to 5
+	i = int(floor( h ));
+	f = h - i;			// factorial part of h
+	p = v * ( 1 - s );
+	q = v * ( 1 - s * f );
+	t = v * ( 1 - s * ( 1 - f ) );
+
+	switch( i ) {
+		case 0:
+			*r = v;
+			*g = t;
+			*b = p;
+			break;
+		case 1:
+			*r = q;
+			*g = v;
+			*b = p;
+			break;
+		case 2:
+			*r = p;
+			*g = v;
+			*b = t;
+			break;
+		case 3:
+			*r = p;
+			*g = q;
+			*b = v;
+			break;
+		case 4:
+			*r = t;
+			*g = p;
+			*b = v;
+			break;
+		default:		// case 5:
+			*r = v;
+			*g = p;
+			*b = q;
+			break;
+	}
+
+}
+
+
+
+//------------------------------------------------------------------------------
+ // r,g,b values are from 0 to 1
+// h = [0,360], s = [0,1], v = [0,1]
+//              if s == 0, then h = -1 (undefined)
+
+void vtkpxColorMapUtil::RGBtoHSV( float r, float g, float b, float &h, float &s, float &v )
+{
+  float min, max, delta;
+
+  min = Fmin(r,Fmin(g,b));
+  max = Fmax(r,Fmax(g,b));
+  v = max;                               // v
+
+  delta = max - min;
+
+  if( max != 0 )
+      {
+	s = delta / max;               // s
+      }
+  else
+      {
+	// r = g = b = 0                // s = 0, v is undefined
+	s = 0;
+	h = -1;
+	return;
+      }
+
+  if( r == max )
+      h = ( g - b ) / delta;         // between yellow & magenta
+  else if( g == max )
+      h = 2 + ( b - r ) / delta;     // between cyan & yellow
+  else
+      h = 4 + ( r - g ) / delta;     // between magenta & cyan
+
+  h = 60;                               // degrees
+  if( h < 0 )
+      h += 360;
+  h=h/360.0;
+
+}
+
+int vtkpxColorMapUtil::QuantizeColorImage(vtkImageData* destination,vtkImageData* source,vtkLookupTable* cmap)
+{
+  vtkImageQuantizeRGBToIndex* quantizeFilter=vtkImageQuantizeRGBToIndex::New();
+  quantizeFilter->SetInput(source);
+  quantizeFilter->SetNumberOfColors(2048);
+  quantizeFilter->Update();
+
+  vtkLookupTable* oldlookup=quantizeFilter->GetLookupTable();
+  cmap->DeepCopy(oldlookup);
+  destination->ShallowCopy(quantizeFilter->GetOutput());
+
+  fprintf(stderr,"Done with quantize\n");
+
+  return 1;
+  /*
+
+  int numc=oldlookup->GetNumberOfColors();
+  cmap->SetNumberOfTableValues(numc);
+  double dat[2];
+  oldlookup->GetTableRange(dat);
+  cmap->SetTableRange(dat);
+
+		      minval=V;
+		      best=c2;
+		    }
+		  else if (H==minhue)
+		    {
+		      if (V<minval)
+			{
+			  minval=V;
+			  best=c2;
+			}
+		    }
+		}
+	    }
+	map[best]=color;
+	double val[4];
+	oldlookup->GetTableValue(best,val);
+	cmap->SetTableValue(color,val);
+	done[best]=1;
+      }
+
+  destination->ShallowCopy(quantizeFilter->GetOutput());
+
+  vtkDataArray* destScalars=destination->GetPointData()->GetScalars();
+  for (int j=0;j<destScalars->GetNumberOfTuples();j++)
+    {
+      int v=(int)destScalars->GetComponent(j,0);
+      destScalars->SetComponent(j,0,map[v]);
+    }
+  quantizeFilter->Delete();
+  delete [] map;
+  delete [] done;
+  return 1;*/
+}
+
+void vtkpxColorMapUtil::SetFmriMergeColormap(vtkLookupTable* cmap,int mode,int vol)
+{
+  // Mode 0 is old default 64 colors no flips
+  // Mode 1 is new 256 colors
+  // Mode 2 is new 256 colors flipped
+  // Mode 3 is Spect 64
+  // Mode 4 is Spect 256
+  // Mode 5 is Pawel
+  // Mode 6 is Pawl flipped
+  // Mode 7 is Rainbow color map
+  mode=Irange(mode,0,6);
+
+  if (mode==3 || mode ==4)
+    {
+      // Mode 3 is spect 64   colors green/blue
+      // Mode 4 is spect 256  colors green/blue
+      switch (mode)
+	{
+	case 3:
+	  CreateOverlayColorMap(cmap,64,0.0,55.0,0.0,55.0,1.0,0.35,0.58,vol);
+	  break;
+	case 4:
+	  CreateOverlayColorMap(cmap,256,0.0,191.0,0.0,191.0,1.0,0.35,0.58,vol);
+	  break;
+
+
+	}
+      return;
+    }
+
+  int numc=64;
+  int numanat=56;
+  if (mode==1 || mode ==2)
+    {
+      numc=256;
+      numanat=192;
+    }
+
+  if (mode==5 || mode ==6)
+    {
+      numc=256;
+      numanat=238;
+    }
+
+
+  if (cmap->GetNumberOfColors()!=numc)
+    cmap->SetNumberOfTableValues(numc);
+  cmap->SetTableRange(0,numc-1);
+
+  if (vol==0)
+    {
+      for (int i=0;i<numanat;i++)
+	{
+	  float v=float(i)/float(numanat-1);
+	  if (i>0)
+	    cmap->SetTableValue(i,v,v,v,1.0);
+	  else
+	    cmap->SetTableValue(i,v,v,v,0.0);
+	}
+    }
+  else if (vol==1)
+    {
+      for (int i=0;i<numanat;i++)
+	{
+	  float v=0.75*float(i)/float(numanat-1);
+	  float vt=0.25*float(i)/float(numanat-1);
+	  if (i>5)
+	    v+=0.2;
+	  cmap->SetTableValue(i,v,v,v,vt);
+	}
+    }
+  else if (vol==2)
+    {
+      for (int i=0;i<numanat;i++)
+	{
+	  float v=0.5*float(i)/float(numanat-1);
+	  float v2=0.0;
+	  if (i>5)
+	    v2=0.1*v+0.7;
+
+	  cmap->SetTableValue(i,v2,v2,v2,v);
+	}
+    }
+
+  if (mode == 0 )
+    {
+      if (vol>0)
+	{
+	  // Matlab based cool(4), then hot(4)
+	  cmap->SetTableValue(56, 0      , 1.0000 , 1.0000,1.00);
+	  cmap->SetTableValue(57, 0.3333 , 0.6667 , 1.0000,0.95);
+	  cmap->SetTableValue(58, 0.6667 , 0.3333 , 1.0000,0.90);
+	  cmap->SetTableValue(59, 1.0000 , 0      , 1.0000,0.85);
+	  cmap->SetTableValue(60, 1.0000 , 0      , 0     ,0.85);
+	  cmap->SetTableValue(61, 1.0000 , 1.0000 , 0.    ,0.90 );
+	  cmap->SetTableValue(62, 1.0000 , 1.0000 , 0.3333,0.95);
+	  cmap->SetTableValue(63, 1.0000 , 1.0000 , 0.6667,1.00);
+	}
+      else
+	{
+	  cmap->SetTableValue(56, 0      , 1.0000 , 1.0000);
+	  cmap->SetTableValue(57, 0.3333 , 0.6667 , 1.0000);
+	  cmap->SetTableValue(58, 0.6667 , 0.3333 , 1.0000);
+	  cmap->SetTableValue(59, 1.0000 , 0      , 1.0000);
+	  cmap->SetTableValue(60, 1.0000 , 0      , 0     );
+	  cmap->SetTableValue(61, 1.0000 , 1.0000 , 0.    );
+	  cmap->SetTableValue(62, 1.0000 , 1.0000 , 0.3333);
+	  cmap->SetTableValue(63, 1.0000 , 1.0000 , 0.6667);
+	}
+    }
+  else if (mode == 1)
+    {
+      for (int i=0;i<32;i++)
+	{
+	  if (vol>0)
+	    cmap->SetTableValue(223-i,float(i)*0.032258,0.0,1.0,
+				0.66+float(32-i)/32.0*0.34);
+	  else
+	    cmap->SetTableValue(223-i,float(i)*0.032258,0.0,1.0,1.0);
+	}
+
+      // set hot temp ramp - 32 tones from red to yellow
+      for (int i=0;i<32;i++)
+	{
+	  if (vol>0)
+	    {
+	      if (i <= 24)
+		cmap->SetTableValue(224+i,1.0,float(i)*0.032258,0.0,0.66+float(i)/32.0*0.34);
+	      else
+		cmap->SetTableValue(224+i,1.0,float(i)*0.032258,(8-32+i)*0.125,0.66+float(i)/32.0*0.34);
+	    }
+	  else
+	    {
+	      if (i<8)
+		{
+		  double frac=double(i)/8.0;
+		  cmap->SetTableValue(224+i, 1.0000 , frac      , 0     );
+		}
+	      else
+		{
+		  double frac=double(i-8)/24.0*0.667;
+		  cmap->SetTableValue(224+i, 1.0000 , 1.0000 , frac    );
+		}
+	      /*
+	      if (i <= 24)
+		cmap->SetTableValue(224+i,1.0,float(i)*0.032258,0.0,1.0);
+	      else
+	      cmap->SetTableValue(224+i,1.0,float(i)*0.032258,(8-32+i)*0.125,1.0);*/
+	    }
+	}
+    }
+  else if (mode == 2 )
+    {
+      for (int i=0;i<32;i++)
+	{
+	  if (vol>0)
+	    cmap->SetTableValue(224+i,float(i)*0.032258,0.0,1.0,
+				    0.66+float(32-i)/32.0*0.34);
+	  else
+	    cmap->SetTableValue(224+i,float(i)*0.032258,0.0,1.0,1.0);
+	}
+
+      // set hot temp ramp - 32 tones from red to yellow
+      for (int i=0;i<32;i++)
+	{
+	  if (vol>0)
+	    {
+	      if (i <= 24)
+		cmap->SetTableValue(223-i,1.0,float(i)*0.032258,0.0,0.66+float(i)/32.0*0.34);
+	      else
+		cmap->SetTableValue(223-i,1.0,float(i)*0.032258,(8-32+i)*0.125,0.66+float(i)/32.0*0.34);
+	    }
+	  else
+	    {
+	      if (i <= 24)
+		cmap->SetTableValue(223-i,1.0,float(i)*0.032258,0.0,1.0);
+	      else
+		cmap->SetTableValue(223-i,1.0,float(i)*0.032258,(8-32+i)*0.125,1.0);
+	    }
+	}
+    }
+  else if (mode == 5 )
+    {
+      if (vol>0)
+	{
+	  // Matlab based cool(4), then hot(4)
+	  cmap->SetTableValue(238,  51.0/255.0, 204.0/255.0, 1.0,0.99);
+	  cmap->SetTableValue(239,  68.0/255.0, 187.0/255.0, 1.0,0.97);
+	  cmap->SetTableValue(240,  85.0/255.0, 170.0/255.0, 1.0,0.95);
+	  cmap->SetTableValue(241, 102.0/255.0, 153.0/255.0, 1.0,0.93);
+	  cmap->SetTableValue(242, 119.0/255.0, 136.0/255.0, 1.0,0.91);
+	  cmap->SetTableValue(243, 136.0/255.0, 119.0/255.0, 1.0,0.89);
+	  cmap->SetTableValue(244, 153.0/255.0, 102.0/255.0, 1.0,0.87);
+	  cmap->SetTableValue(245, 170.0/255.0,  85.0/255.0, 1.0,0.85);
+	  cmap->SetTableValue(246, 187.0/255.0,  68.0/255.0, 1.0,0.83);
+
+	  cmap->SetTableValue(247, 175.0/255.0,         0.0, 0.0,0.83);
+	  cmap->SetTableValue(248, 204.0/255.0,         0.0, 0.0,0.85);
+	  cmap->SetTableValue(249, 255.0/255.0,         0.0, 0.0,0.87);
+	  cmap->SetTableValue(250, 255.0/255.0,  51.0/255.0, 0.0,0.89);
+	  cmap->SetTableValue(251, 255.0/255.0, 102.0/255.0, 0.0,0.91);
+	  cmap->SetTableValue(252, 255.0/255.0, 158.0/255.0, 0.0,0.93);
+	  cmap->SetTableValue(253, 255.0/255.0, 204.0/255.0, 0.0,0.95);
+	  cmap->SetTableValue(254, 255.0/255.0, 255.0/255.0, 0.0,0.97);
+	  cmap->SetTableValue(255, 255.0/255.0, 255.0/255.0, 68.0/255.0,0.99);
+	}
+      else
+	{
+	  cmap->SetTableValue(238,  51.0/255.0, 204.0/255.0, 1.0);
+	  cmap->SetTableValue(239,  68.0/255.0, 187.0/255.0, 1.0);
+	  cmap->SetTableValue(240,  85.0/255.0, 170.0/255.0, 1.0);
+	  cmap->SetTableValue(241, 102.0/255.0, 153.0/255.0, 1.0);
+	  cmap->SetTableValue(242, 119.0/255.0, 136.0/255.0, 1.0);
+	  cmap->SetTableValue(243, 136.0/255.0, 119.0/255.0, 1.0);
+	  cmap->SetTableValue(244, 153.0/255.0, 102.0/255.0, 1.0);
+	  cmap->SetTableValue(245, 170.0/255.0,  85.0/255.0, 1.0);
+	  cmap->SetTableValue(246, 187.0/255.0,  68.0/255.0, 1.0);
+
+	  cmap->SetTableValue(247, 175.0/255.0,         0.0, 0.0);
+	  cmap->SetTableValue(248, 204.0/255.0,         0.0, 0.0);
+	  cmap->SetTableValue(249, 255.0/255.0,         0.0, 0.0);
+	  cmap->SetTableValue(250, 255.0/255.0,  51.0/255.0, 0.0);
+	  cmap->SetTableValue(251, 255.0/255.0, 102.0/255.0, 0.0);
+	  cmap->SetTableValue(252, 255.0/255.0, 158.0/255.0, 0.0);
+	  cmap->SetTableValue(253, 255.0/255.0, 204.0/255.0, 0.0);
+	  cmap->SetTableValue(254, 255.0/255.0, 255.0/255.0, 0.0);
+	  cmap->SetTableValue(255, 255.0/255.0, 255.0/255.0, 68.0/255.0);
+	}
+    }
+  else if (mode == 6 )
+    {
+      if (vol>0)
+	{
+	  // Matlab based cool(4), then hot(4)
+	  cmap->SetTableValue(255,  51.0/255.0, 204.0/255.0, 1.0,0.99);
+	  cmap->SetTableValue(254,  68.0/255.0, 187.0/255.0, 1.0,0.97);
+	  cmap->SetTableValue(253,  85.0/255.0, 170.0/255.0, 1.0,0.95);
+	  cmap->SetTableValue(252, 102.0/255.0, 153.0/255.0, 1.0,0.93);
+	  cmap->SetTableValue(251, 119.0/255.0, 136.0/255.0, 1.0,0.91);
+	  cmap->SetTableValue(250, 136.0/255.0, 119.0/255.0, 1.0,0.89);
+	  cmap->SetTableValue(249, 153.0/255.0, 102.0/255.0, 1.0,0.87);
+	  cmap->SetTableValue(248, 170.0/255.0,  85.0/255.0, 1.0,0.85);
+	  cmap->SetTableValue(247, 187.0/255.0,  68.0/255.0, 1.0,0.83);
+
+	  cmap->SetTableValue(246, 175.0/255.0,         0.0, 0.0,0.83);
+	  cmap->SetTableValue(245, 204.0/255.0,         0.0, 0.0,0.85);
+	  cmap->SetTableValue(244, 255.0/255.0,         0.0, 0.0,0.87);
+	  cmap->SetTableValue(243, 255.0/255.0,  51.0/255.0, 0.0,0.89);
+	  cmap->SetTableValue(242, 255.0/255.0, 102.0/255.0, 0.0,0.91);
+	  cmap->SetTableValue(241, 255.0/255.0, 158.0/255.0, 0.0,0.93);
+	  cmap->SetTableValue(240, 255.0/255.0, 204.0/255.0, 0.0,0.95);
+	  cmap->SetTableValue(239, 255.0/255.0, 255.0/255.0, 0.0,0.97);
+	  cmap->SetTableValue(238, 255.0/255.0, 255.0/255.0, 68.0/255.0,0.99);
+	}
+      else
+	{
+	  cmap->SetTableValue(255,  51.0/255.0, 204.0/255.0, 1.0);
+	  cmap->SetTableValue(254,  68.0/255.0, 187.0/255.0, 1.0);
+	  cmap->SetTableValue(253,  85.0/255.0, 170.0/255.0, 1.0);
+	  cmap->SetTableValue(252, 102.0/255.0, 153.0/255.0, 1.0);
+	  cmap->SetTableValue(251, 119.0/255.0, 136.0/255.0, 1.0);
+	  cmap->SetTableValue(250, 136.0/255.0, 119.0/255.0, 1.0);
+	  cmap->SetTableValue(249, 153.0/255.0, 102.0/255.0, 1.0);
+	  cmap->SetTableValue(248, 170.0/255.0,  85.0/255.0, 1.0);
+	  cmap->SetTableValue(247, 187.0/255.0,  68.0/255.0, 1.0);
+
+	  cmap->SetTableValue(246, 175.0/255.0,         0.0, 0.0);
+	  cmap->SetTableValue(245, 204.0/255.0,         0.0, 0.0);
+	  cmap->SetTableValue(244, 255.0/255.0,         0.0, 0.0);
+	  cmap->SetTableValue(243, 255.0/255.0,  51.0/255.0, 0.0);
+	  cmap->SetTableValue(242, 255.0/255.0, 102.0/255.0, 0.0);
+	  cmap->SetTableValue(241, 255.0/255.0, 158.0/255.0, 0.0);
+	  cmap->SetTableValue(240, 255.0/255.0, 204.0/255.0, 0.0);
+	  cmap->SetTableValue(239, 255.0/255.0, 255.0/255.0, 0.0);
+	  cmap->SetTableValue(238, 255.0/255.0, 255.0/255.0, 68.0/255.0);
+	}
+    }
+}
+
+
+void vtkpxColorMapUtil::SetScalarBarColormap(vtkLookupTable* cmap,int mode,double minv,double maxv,int positive)
+{
+  // Mode 0 is old default 64 colors no flips
+  // Mode 1 is new 256 colors
+  // Mode 2 is new 256 colors flipped
+  // Mode 3 is Spect 64
+  // Mode 4 is Spect 256
+  // Mode 5 is Pawel
+  // Mode 6 is Pawl flipped
+  mode=Irange(mode,0,6);
+
+  if (positive>=1)
+    positive=1;
+  else
+    positive=0;
+
+  minv=fabs(minv);
+  maxv=fabs(maxv);
+  if (minv==maxv)
+    maxv=minv+1.0;
+  if (minv>maxv)
+    {
+      double a=minv;
+      minv=maxv;
+      maxv=a;
+    }
+
+  cmap->SetTableRange(minv,maxv);
+
+  if (mode==2)
+    {
+      positive=1-positive;
+      mode=1;
+    }
+
+  if (mode==6)
+    {
+      positive=1-positive;
+      mode=5;
+    }
+
+  if (mode == 0 )
+    {
+      cmap->SetNumberOfTableValues(4);
+      if (!positive)
+	{
+	  cmap->SetTableValue(3, 0      , 1.0000 , 1.0000);
+	  cmap->SetTableValue(2, 0.3333 , 0.6667 , 1.0000);
+	  cmap->SetTableValue(1, 0.6667 , 0.3333 , 1.0000);
+	  cmap->SetTableValue(0, 1.0000 , 0      , 1.0000);
+	}
+      else
+	{
+	  cmap->SetTableValue(0, 1.0000 , 0      , 0     );
+	  cmap->SetTableValue(1, 1.0000 , 1.0000 , 0.    );
+	  cmap->SetTableValue(2, 1.0000 , 1.0000 , 0.3333);
+	  cmap->SetTableValue(3, 1.0000 , 1.0000 , 0.6667);
+	}
+    }
+  else if (mode == 1)
+    {
+      cmap->SetNumberOfTableValues(32);
+      if (!positive)
+	{
+	  for (int i=0;i<32;i++)
+	    cmap->SetTableValue(i,float(i)*0.032258,0.0,1.0,1.0);
+	}
+      else
+	{
+	  for (int i=0;i<32;i++)
+	    {
+	      if (i<8)
+		{
+		  double frac=double(i)/8.0;
+		  cmap->SetTableValue(i, 1.0000 , frac      , 0     );
+		}
+	      else
+		{
+		  double frac=double(i-8)/24.0*0.667;
+		  cmap->SetTableValue(i, 1.0000 , 1.0000 , frac    );
+		}
+	    }
+	}
+    }
+  else if (mode == 5 )
+    {
+      cmap->SetNumberOfTableValues(9);
+      if (!positive)
+	{
+	  cmap->SetTableValue(0,  51.0/255.0, 204.0/255.0, 1.0,0.99);
+	  cmap->SetTableValue(1,  68.0/255.0, 187.0/255.0, 1.0,0.97);
+	  cmap->SetTableValue(2,  85.0/255.0, 170.0/255.0, 1.0,0.95);
+	  cmap->SetTableValue(3, 102.0/255.0, 153.0/255.0, 1.0,0.93);
+	  cmap->SetTableValue(4, 119.0/255.0, 136.0/255.0, 1.0,0.91);
+	  cmap->SetTableValue(5, 136.0/255.0, 119.0/255.0, 1.0,0.89);
+	  cmap->SetTableValue(6, 153.0/255.0, 102.0/255.0, 1.0,0.87);
+	  cmap->SetTableValue(7, 170.0/255.0,  85.0/255.0, 1.0,0.85);
+	  cmap->SetTableValue(8, 187.0/255.0,  68.0/255.0, 1.0,0.83);
+	}
+      else
+	{
+	  cmap->SetTableValue(0, 175.0/255.0,         0.0, 0.0,0.83);
+	  cmap->SetTableValue(1, 204.0/255.0,         0.0, 0.0,0.85);
+	  cmap->SetTableValue(2, 255.0/255.0,         0.0, 0.0,0.87);
+	  cmap->SetTableValue(3, 255.0/255.0,  51.0/255.0, 0.0,0.89);
+	  cmap->SetTableValue(4, 255.0/255.0, 102.0/255.0, 0.0,0.91);
+	  cmap->SetTableValue(5, 255.0/255.0, 158.0/255.0, 0.0,0.93);
+	  cmap->SetTableValue(6, 255.0/255.0, 204.0/255.0, 0.0,0.95);
+	  cmap->SetTableValue(7, 255.0/255.0, 255.0/255.0, 0.0,0.97);
+	  cmap->SetTableValue(8, 255.0/255.0, 255.0/255.0, 68.0/255.0,0.99);
+	}
+    }
+  else if (mode==3 || mode ==4)
+    {
+      // Mode 3 is spect 64   colors green/blue
+      // Mode 4 is spect 256  colors green/blue
+      vtkLookupTable* tmp=vtkLookupTable::New();
+      int numc=4,maxc=64;
+      switch (mode)
+	{
+	case 3:
+	  CreateOverlayColorMap(tmp,64,0.0,55.0,0.0,55.0,1.0,0.35,0.58,0);
+	  break;
+	case 4:
+	  numc=32;
+	  maxc=256;
+	  CreateOverlayColorMap(tmp,256,0.0,191.0,0.0,191.0,1.0,0.35,0.58,0);
+	  break;
+	}
+
+      cmap->SetNumberOfTableValues(numc);
+      for (int i=0;i<numc;i++)
+	{
+	  int index=(maxc-numc)+i;
+	  if (!positive)
+	    index=(maxc-numc-1)-i;
+	  double val[4]; tmp->GetTableValue(index,val);
+	  cmap->SetTableValue(i,val);
+	}
+     }
+}
+
+
+void vtkpxColorMapUtil::CopyLookupTable(vtkLookupTable* in,vtkLookupTable* out)
+{
+  if (in==NULL || out ==NULL)
+    {
+      fprintf(stderr,"Bad LookupTable to copy\n");
+      return;
+    }
+  //  fprintf(stderr,"Copying Lookup Table ....");
+  out->DeepCopy(in);
+  //  fprintf(stderr,"done\n");
+  return;
+  /*  out->SetNumberOfTableValues(in->GetNumberOfColors());
+  out->SetTableRange(in->GetTableRange());
+
+
+  for (int int i=0;i<out->GetNumberOfColors();i++)
+  out->SetTableValue(i,in->GetTableValue(i));*/
+}
+
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxColorMapUtil::LoadColormap(vtkLookupTable* colormap,const char* name)
+{
+  if (colormap==NULL)
+      return 0;
+
+  gzFile fin=gzsuffixopen(name,"rb");
+  if (!fin)
+    return 0;
+
+  char line[102];
+  gzgets(fin,line,100);
+  if (gzfindstringinstring(line,"#IPAGRGBAColormap")==0)
+      {
+	gzclose(fin);
+	return 0;
+      }
+
+  gzgets(fin,line,100);  gzgets(fin,line,100);
+  int numc;
+  sscanf(line,"%d",&numc);
+  if (numc!=colormap->GetNumberOfColors())
+      colormap->SetNumberOfTableValues(numc);
+
+  double dat[2];
+  gzgets(fin,line,100);  gzgets(fin,line,100);
+  sscanf(line,"%lf %lf",&dat[0],&dat[1]);
+  colormap->SetTableRange(dat);
+
+  gzgets(fin,line,100);  gzgets(fin,line,100);
+  for (int i=0;i<colormap->GetNumberOfColors();i++)
+      {
+	double val[4];
+	int tmp;
+	gzgets(fin,line,100);
+	sscanf(line,"%d %lf %lf %lf %lf",&tmp,&val[0],&val[1],&val[2],&val[3]);
+	colormap->SetTableValue(tmp,val);
+      }
+  gzclose(fin);
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxColorMapUtil::SaveColormap(vtkLookupTable* colormap,const char* name)
+{
+  if (colormap==NULL)
+      return 0;
+
+  FILE* fout=fopen(name,"w");
+
+  if (!fout)
+      return 0;
+
+  fprintf(fout,"#IPAGRGBAColormap\n");
+  fprintf(fout,"#Number of Colors\n%d\n",colormap->GetNumberOfColors());
+
+  double dat[2];
+  colormap->GetTableRange(dat);
+  fprintf(fout,"#Range\n %6.3f %6.3f \n",dat[0],dat[1]);
+
+  fprintf(fout,"#Colors\n#Index  R     G     B  Alpha\n");
+  for (int i=0;i<colormap->GetNumberOfColors();i++)
+      {
+	double val[4];
+	colormap->GetTableValue(i,val);
+	fprintf(fout,"%4d %5.3f %5.3f %5.3f %5.3f\n",i,val[0],val[1],val[2],val[3]);
+      }
+  fclose(fout);
+  return 1;
+
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxColorMapUtil::LoadAnalyzeColormap(vtkLookupTable* colormap,const char* name,int volume_mode)
+{
+  if (colormap==NULL)
+    return 0;
+
+  FILE* fin=fopen(name,"r");
+  if (!fin)
+      return 0;
+
+  double colors[256][3];
+  for (int i=0;i<255;i++)
+      for (int j=0;j<3;j++)
+	  {
+	    colors[i][j]=double(i)/double(255);
+	    fscanf(fin,"%lf ",&colors[i][j]);
+	    colors[i][j]/=255.0;
+	    colors[i][j]=Frange(colors[i][j],0.0,1.0);
+	  }
+  fclose(fin);
+
+  if (colormap->GetNumberOfColors()!=256)
+      colormap->SetNumberOfTableValues(256);
+
+  for (int ia=0;ia<256;ia++)
+    {
+      double val[4];
+      if (volume_mode)
+	val[3]=double(ia)/double(256);
+      else
+	val[3]=1.0;
+      for (int j=0;j<=2;j++)
+	val[j]=colors[ia][j];
+      colormap->SetTableValue(ia,val);
+    }
+  gzclose(fin);
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxColorMapUtil::SaveAnalyzeColormap(vtkLookupTable* colormap,const char* name)
+{
+  if (colormap==NULL)
+      return 0;
+
+  if (colormap->GetNumberOfColors()!=256)
+    {
+      fprintf(stderr,"Cannot export colormap as it does not have 256 colors\n");
+      return 0;
+    }
+
+  FILE* fout=fopen(name,"w");
+
+  if (!fout)
+      return 0;
+
+  for (int i=0;i<colormap->GetNumberOfColors();i++)
+      {
+	double val[4];
+	colormap->GetTableValue(i,val);
+	fprintf(fout,"%3d %3d %3d \n",int(val[0]*255.0),int(val[1]*255.0),int(val[2]*255.0));
+      }
+  fprintf(fout,"\n");
+  fclose(fout);
+  return 1;
+}
+// -----------------------------------------------------------------------------------------------------------------------
+void vtkpxColorMapUtil::SetAutoStepColorMap(vtkImageData* img,vtkLookupTable* cmap,int robust,int num_colors,int volume)
+{
+  if (img==NULL || cmap==NULL)
+    return;
+
+  double range[2]; img->GetPointData()->GetScalars()->GetRange(range);
+
+  float           auto_min,auto_max;
+  if (robust)
+    {
+      vtkpxUtil::ImageRobustRange(img,0.01,0.99,auto_min,auto_max);
+    }
+  else
+    {
+      auto_min=range[0];
+      auto_max=range[1];
+    }
+
+  if (auto_min==auto_max)
+    auto_max+=1.0;
+
+  vtkpxColorMapUtil::SetStepColorMap(cmap,auto_min,auto_max,range[0],range[1],num_colors,volume);
+}
+// -----------------------------------------------------------------------------------------------------------------------
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxColorMapUtil.h b/bioimagesuite30_src/Graphics/vtkpxColorMapUtil.h
new file mode 100644
index 0000000..7f256f0
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxColorMapUtil.h
@@ -0,0 +1,159 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxColorMapUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/24 14:39:36 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxColorMapUtil - a collection of static utility functions
+// .SECTION Description
+// This class contains a collection of <EM>static</EM> utility functions for use elsewhere ala vtkMath
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// This requires pxutil 
+
+#ifndef __vtkpxColorMapUtil_h
+#define __vtkpxColorMapUtil_h
+
+#include "vtkObject.h"
+
+class vtkImageData;
+class vtkLookupTable;
+class vtkImageData;
+class vtkDataArray;
+
+class vtkpxColorMapUtil : public vtkObject
+{
+public:
+  static vtkpxColorMapUtil *New();
+  vtkTypeMacro(vtkpxColorMapUtil,vtkObject);
+  
+
+
+  // Description:
+  // Gets intensity range of image and computes bounds for step function 
+  static void  ComputeStepBounds(vtkImageData* image,vtkDataArray* output,int np=1001,float nsigma=3.0);
+
+  // Colormap Stuff
+  // Description:
+  // Update Colormap from image
+  static void AutoUpdateColormapRange(vtkLookupTable* cmap,vtkImageData* img);
+
+  // Description:
+  // Create qunatized version of image source to destination and accompanying vtkLookupTable
+  static int  QuantizeColorImage(vtkImageData* destination,vtkImageData* source,vtkLookupTable* cmap);
+
+  // Description:
+  // Creates gamma modified colormap (vol=1, is for volume rendering)
+  static void SetGammaColorMap(vtkLookupTable *cmap,float gamma,float min_value,float max_value,
+					 int num_colors,int vol=0);
+
+  // Description:
+  // Creates constant hue colormap (vol=1, is for volume rendering)
+  static void SetConstantHueColorMap(vtkLookupTable* cmap,float intensity,float hue1,float hue2,float cutoff,
+				     float min_value,float max_value,int num_colors,int vol=0);
+
+  // Description:
+  // Creates step colormap (vol=1, is for volume rendering)
+  static void SetStepColorMap(vtkLookupTable *cmap,float min,float max,float min_value,float max_value,
+			      int num_colors,int vol=0);
+
+  // Description:
+  // Creates a rainbow colormap (vol=1, is for volume rendering)
+  static void SetRainbowColorMap(vtkLookupTable *cmap,float min,float max,float min_value,float max_value,
+			      int num_colors,int vol=0);
+
+    // Description:
+  // Creates an inverted rainbow colormap (vol=1, is for volume rendering)
+  static void SetReverseRainbowColorMap(vtkLookupTable *cmap,float min,float max,float min_value,float max_value,
+			      int num_colors,int vol=0);
+
+    // Description:
+  // Creates an blackbody radiation colormap (vol=1, is for volume rendering)
+  static void SetBlackBodyColorMap(vtkLookupTable *cmap,float min,float max,float min_value,float max_value,
+			      int num_colors,int vol=0);
+
+  // Description:
+  // Set Auto Step Colormap
+  static void SetAutoStepColorMap(vtkImageData* img,vtkLookupTable* cmap,int robust,int num_colors,int volume);
+
+
+  // Description:
+  // Creates  colormap for fmri overlays (vol=1, is for volume rendering)
+  static void SetFmriMergeColormap(vtkLookupTable* cmap,int mode=0,int vol=0);
+  static void SetScalarBarColormap(vtkLookupTable* cmap,int mode,double minv,double maxv,int positive=1);
+
+  // Description:
+  // Create Overlay Color Map
+  static void CreateOverlayColorMap(vtkLookupTable *cmap,int mode,float min,float max,float min_value,float max_value,
+				    float intensity,float hue1,float hue2,int vol,int updatefunction=1);
+
+  // Description:
+  // CopyLookupTable
+  static void CopyLookupTable(vtkLookupTable* in,vtkLookupTable* out);
+
+  //BTX
+  // Description:
+  // Convert RGB to HSV
+  static void RGBtoHSV( float r, float g, float b, float &h, float &s, float &v );
+  static void HSVtoRGB( float *r, float *g, float *b, float h, float s, float v );
+  //ETX
+
+  // Description:
+  // Colormap Load and Save both native .cmap and Analyze
+  static int LoadColormap(vtkLookupTable* colormap,const char* name);
+  static int SaveColormap(vtkLookupTable* colormap,const char* name);
+  static int LoadAnalyzeColormap(vtkLookupTable* colormap,const char* name,int volume_mode=0);
+  static int SaveAnalyzeColormap(vtkLookupTable* colormap,const char* name);
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxCurveEditUtil.cpp b/bioimagesuite30_src/Graphics/vtkpxCurveEditUtil.cpp
new file mode 100644
index 0000000..c78296e
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxCurveEditUtil.cpp
@@ -0,0 +1,257 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCurveEditUtil.cpp,v $
+  Language:  C++
+  Date:      $Date: 2003/06/05 21:01:46 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxCurveEditUtil.h"
+#include "vtkpxUtil.h"
+#include "vtkpxBaseCurve.h"
+#include "vtkActor.h"
+#include "vtkSphereSource.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+
+// ---------------------------
+
+vtkpxCurveEditUtil* vtkpxCurveEditUtil::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxCurveEditUtil");
+  if(ret)
+      {
+	return (vtkpxCurveEditUtil*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxCurveEditUtil;
+}
+
+// ------------------------------------------------------------------------------------------------------------------
+
+void vtkpxCurveEditUtil::AddListLandmark(float x,float y,float z,
+					 int index,int scaled,
+					 vtkpxBaseCurve* landmarkCollection)
+{
+  if (index==-1)
+    landmarkCollection->AddPoint(x,y,z,scaled);
+  else
+    landmarkCollection->SetPoint(index,x,y,z,scaled);    
+
+  landmarkCollection->Modified();
+  landmarkCollection->Update();
+}
+
+// ------------------------------------------------------------------------------------------------------------------
+
+int vtkpxCurveEditUtil::HandleClickedPoint(float x,float y,float z,int scaled,
+					   int state,int mode,int index,
+					   vtkpxBaseCurve* landmarkCollection,
+					   vtkSphereSource* highlightData,
+					   vtkActor* highlightActor)
+{
+  if (mode==0)
+      return -1;
+  
+  //int index=this->highlightIndex;//listBox->getCurrentItem();
+  int numitems=landmarkCollection->GetNumPoints();//listBox->getNumItems();
+  
+  switch (mode)
+    {
+    case 4:  // Continuous Add Mode 
+      switch(state)
+	{
+	case 0:
+	  break;
+	case 1:
+	  vtkpxCurveEditUtil::AddListLandmark(x,y,z,-1,scaled,landmarkCollection);
+	  break;
+	case 2:
+	  vtkpxCurveEditUtil::SetHighlight(landmarkCollection,highlightData,highlightActor,index);
+	  break;
+	}
+      return index;
+      break;
+      
+
+    case 3:  // Add Mode 
+      switch(state)
+	{
+	case 0:
+	  vtkpxCurveEditUtil::AddListLandmark(x,y,z,-1,scaled,landmarkCollection);
+	  index=landmarkCollection->GetNumPoints()-1;
+	  vtkpxCurveEditUtil::SetHighlight(landmarkCollection,highlightData,highlightActor,index);
+	  break;
+	case 1:
+	  vtkpxCurveEditUtil::AddListLandmark(x,y,z,index,scaled,landmarkCollection);
+	  vtkpxCurveEditUtil::SetHighlight(landmarkCollection,highlightData,highlightActor,index);
+	  break;
+	case 2:
+	  vtkpxCurveEditUtil::AddListLandmark(x,y,z,index,scaled,landmarkCollection);
+	  vtkpxCurveEditUtil::SetHighlight(landmarkCollection,highlightData,highlightActor,index);
+	  break;
+	}
+      return index;
+      break;
+      
+    case 1: // Pick Mode 
+      if (numitems<1)
+	return -1;
+      switch (state)
+	{
+	case 0:
+	  {
+	    double lx[3];
+	    lx[0]=x;lx[1]=y;lx[2]=z;
+	    index=landmarkCollection->FindClosestPoint(lx,landmarkCollection->GetPointScale()*1.2,scaled);
+	    vtkpxCurveEditUtil::SetHighlight(landmarkCollection,highlightData,highlightActor,index);
+	    break;
+	  }
+	case 1:
+	  if (index>=0)
+	    {
+	      vtkpxCurveEditUtil::AddListLandmark(x,y,z,index,scaled,landmarkCollection);
+	      vtkpxCurveEditUtil::SetHighlight(landmarkCollection,highlightData,highlightActor,index);
+	    }
+	    break;
+	case 2:
+	  if (index>=0)
+	    {
+	      vtkpxCurveEditUtil::AddListLandmark(x,y,z,index,scaled,landmarkCollection);
+	      vtkpxCurveEditUtil::SetHighlight(landmarkCollection,highlightData,highlightActor,index);
+	    }
+	  break;
+	}
+      return index;
+      break;
+      
+    case 2: // Edit Mode 
+      if (index<0)
+	return 0;
+      switch(state)
+	{
+	case 0:
+	  vtkpxCurveEditUtil::AddListLandmark(x,y,z,index,scaled,landmarkCollection);
+	  break;
+	case 1:
+	  vtkpxCurveEditUtil::AddListLandmark(x,y,z,index,scaled,landmarkCollection);
+	  vtkpxCurveEditUtil::SetHighlight(landmarkCollection,highlightData,highlightActor,index);
+	  break;
+	case 2:
+	  vtkpxCurveEditUtil::AddListLandmark(x,y,z,index,scaled,landmarkCollection);
+	  if (index<numitems-1)
+	    index++;
+	  vtkpxCurveEditUtil::SetHighlight(landmarkCollection,highlightData,highlightActor,index);
+	  break;
+	}
+      return index;
+    }
+  return -1;
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxCurveEditUtil::SetHighlightDisplay(int disp,int highlightIndex,
+					     vtkSphereSource* highlightData,vtkActor* highlightActor)
+{
+  int flag=1;
+  if (disp==0 || highlightIndex==-1)
+    flag=0;
+
+  if (highlightActor!=NULL)
+    {
+      if (highlightActor->GetVisibility() != flag )
+	    highlightActor->SetVisibility(flag);
+    }
+
+}	  
+
+
+void vtkpxCurveEditUtil::SetHighlight(vtkpxBaseCurve* landmarkCollection,vtkSphereSource* highlightData,
+				      vtkActor* highlightActor,int numh)
+{
+
+  if (highlightData==NULL || landmarkCollection==NULL)
+    {
+      SetHighlightDisplay(0,-1,highlightData,highlightActor);
+      return;
+    }
+
+  int np=landmarkCollection->GetNumPoints();
+  
+  if (numh<0 || np<1)
+    {
+      highlightData->SetRadius(0.01);
+      highlightData->Update();
+      SetHighlightDisplay(0,-1,highlightData,highlightActor);
+      return;
+    }
+
+  numh=Irange(numh,0,np-1);
+
+  double sp[3]; landmarkCollection->GetSpacing(sp);
+  double ori[3]; landmarkCollection->GetOrigin(ori);
+
+  numh=Irange(numh,0,np-1);
+
+  double x[3];
+  landmarkCollection->GetPoints()->GetPoint(numh,x);
+  for (int ia=0;ia<=2;ia++)
+    x[ia]=x[ia]*sp[ia]+ori[ia];
+
+  highlightData->SetCenter(x);
+  highlightData->SetRadius(1.5*landmarkCollection->GetPointScale());
+  highlightData->Update();
+  SetHighlightDisplay(1,numh,highlightData,highlightActor);
+}
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxCurveEditUtil.h b/bioimagesuite30_src/Graphics/vtkpxCurveEditUtil.h
new file mode 100644
index 0000000..a0e5a4a
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxCurveEditUtil.h
@@ -0,0 +1,103 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCurveEditUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxBrainStripUtil - a collection of static utility functions to interface to Xiaolan's code
+// .SECTION Description
+// This class contains a collection of <EM>static</EM> utility functions for use elsewhere ala vtkMath
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// None
+
+#ifndef __vtkpxCurveEditUtil_h
+#define __vtkpxCurveEditUtil_h
+
+#include "vtkProcessObject.h"
+
+class vtkSphereSource;
+class vtkActor;
+class vtkpxBaseCurve;
+
+class vtkpxCurveEditUtil : public vtkProcessObject
+{
+public:
+  static vtkpxCurveEditUtil *New();
+  vtkTypeMacro(vtkpxCurveEditUtil,vtkProcessObject);
+  
+  // Description:
+  // Coupled Levelset Wrapper functions 
+ 
+  static int HandleClickedPoint(float x,float y,float z,int scaled,
+				int state,int mode,int index,
+				vtkpxBaseCurve* landmarkCollection,
+				vtkSphereSource* highlightData,
+				vtkActor* highlightActor);
+
+
+protected:
+  
+  static void AddListLandmark(float x,float y,float z,
+			      int index,int scaled,
+			      vtkpxBaseCurve* landmarkCollection);
+
+  static void SetHighlightDisplay(int disp,int highlightIndex,
+				  vtkSphereSource* highlightData,vtkActor* highlightActor);
+  
+  static void SetHighlight(vtkpxBaseCurve* landmarkCollection,vtkSphereSource* highlightData,
+			   vtkActor* highlightActor,int numh);
+
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxElectrodeGridSource.cpp b/bioimagesuite30_src/Graphics/vtkpxElectrodeGridSource.cpp
new file mode 100644
index 0000000..bfe674d
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxElectrodeGridSource.cpp
@@ -0,0 +1,865 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+ see vtkpxElectrodeGridSource.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkAppendPolyData.h"
+#include "vtkCellArray.h"
+#include "vtkUnsignedShortArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkpxElectrodeGridSource.h"
+#include "vtkpxElectrodeSource.h"
+#include "vtkCollection.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkShortArray.h"
+#include "vtkMath.h"
+#include "vtkFloatArray.h"
+#include "vtkThinPlateSplineTransform.h"
+#include "pxutil.h"
+//------------------------------------------------------------------------------
+vtkpxElectrodeGridSource* vtkpxElectrodeGridSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxElectrodeGridSource");
+  if(ret)
+    {
+      return (vtkpxElectrodeGridSource*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxElectrodeGridSource;
+}
+
+// Construct object with no children.
+vtkpxElectrodeGridSource::vtkpxElectrodeGridSource()
+{
+  this->Dimensions[0]=0; this->Dimensions[1]=0;
+  this->ElectrodeSpacing[0]=10.0;   this->ElectrodeSpacing[1]=10.0;
+  this->ElectrodeType=0;
+  this->Radius=2.0;
+  this->Thickness=0.05;
+  this->GridName=NULL; this->SetGridName("Grid");
+  this->ElectrodeCollection=vtkCollection::New();
+  this->Visible=1;
+  this->EnableSynchronization=1;
+  this->JustShowElectrodes=0;
+  this->Color[0]=0.8;
+  this->Color[1]=0.8;
+  this->Color[2]=0.8;
+  this->LabelSurface=vtkPolyData::New();
+  this->ShowLabelsGap=1;
+  this->ColorMode=0;
+}
+
+/* -------------------------------------------------------------------------*/
+ 
+vtkpxElectrodeGridSource::~vtkpxElectrodeGridSource()
+{
+  this->ElectrodeCollection->Delete();
+  if (this->GridName!=NULL)
+    delete [] GridName;
+  this->LabelSurface->Delete();
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxElectrodeGridSource::CopyAttributes(vtkpxElectrodeGridSource* other)
+{
+ int d[2]; other->GetDimensions(d);
+ if (d[0]==this->Dimensions[0] && d[1]==this->Dimensions[1])
+   {
+
+     this->SetElectrodeSpacing(other->GetElectrodeSpacing());
+     this->ElectrodeType=other->GetElectrodeType();
+     this->Radius=other->GetRadius();
+     this->Thickness=other->GetThickness();
+     this->ElectrodeCollection->InitTraversal();
+     this->SetGridName(other->GetGridName());
+     this->SetColor(other->GetColor());
+
+     int total=this->Dimensions[0]*this->Dimensions[1];
+     for (int i=0;i<total;i++)
+       this->GetElectrode(i)->CopyAttributes(other->GetElectrode(i));
+   }
+
+}
+
+void vtkpxElectrodeGridSource::Copy(vtkpxElectrodeGridSource* other)
+{
+  int d[2]; other->GetDimensions(d);
+
+  this->InitializeGrid(d[0],d[1]);
+  this->SetElectrodeSpacing(other->GetElectrodeSpacing());
+  this->ElectrodeType=other->GetElectrodeType();
+  this->Radius=other->GetRadius();
+  this->Thickness=other->GetThickness();
+  this->ElectrodeCollection->InitTraversal();
+  this->SetGridName(other->GetGridName());
+  this->SetColor(other->GetColor());
+
+
+  int total=this->Dimensions[0]*this->Dimensions[1];
+  for (int i=0;i<total;i++)
+    this->GetElectrode(i)->Copy(other->GetElectrode(i));
+
+  this->SynchronizeElectrodeTypeAndDimensions();
+  this->Modified();
+
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxElectrodeGridSource::GetElectrodeRealIndex(int index)
+{
+  int j=index/this->Dimensions[0];
+  int i=(index-j*this->Dimensions[0]);
+  //  fprintf(stderr,"index=%d --> (%d,%d) ",index,i,j);
+  return this->GetElectrodeRealIndex(i,j);
+
+}
+
+int vtkpxElectrodeGridSource::GetElectrodeRealIndex(int i,int j)
+{
+  i=Irange(i,0,this->Dimensions[0]-1);
+  j=Irange(j,0,this->Dimensions[1]-1);
+  
+
+  int index=i*this->Dimensions[1]+(this->Dimensions[1]-j);
+  //  fprintf(stderr,"  (%d,%d) --> %d\n",i,j,index);
+  return index;
+  
+
+}
+
+vtkpxElectrodeSource* vtkpxElectrodeGridSource::GetElectrode(int i,int j)
+{
+  i=Irange(i,0,this->Dimensions[0]-1);
+  j=Irange(j,0,this->Dimensions[1]-1);
+
+  int index=j*this->Dimensions[0]+i;
+  vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetItemAsObject(index));//
+  //return this->GetElectrode(index);
+  return electrode;
+}
+
+vtkpxElectrodeSource* vtkpxElectrodeGridSource::GetElectrode(int index) 
+{
+  int size=this->Dimensions[0]*this->Dimensions[1];
+  index=Irange(index,0,size-1);
+  vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetItemAsObject(index));
+  return electrode;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxElectrodeGridSource::InitializeGrid(int dimx,int dimy)
+{
+  this->Dimensions[0]=Irange(dimx,1,22);
+  this->Dimensions[1]=Irange(dimy,1,22);
+  if (this->ElectrodeCollection->GetNumberOfItems()>0)
+    this->ElectrodeCollection->RemoveAllItems();
+  for (int j=0;j<Dimensions[1];j++)
+    for (int i=0;i<Dimensions[0];i++)
+      {
+	vtkpxElectrodeSource* electrode=vtkpxElectrodeSource::New();
+	double d[3];
+	d[0]=i*this->ElectrodeSpacing[0];
+	d[1]=j*this->ElectrodeSpacing[1];
+	d[2]=0.0;
+	electrode->SetPosition(d);
+	this->ElectrodeCollection->AddItem(electrode);
+	electrode->Delete();
+      }
+
+  this->Modified();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxElectrodeGridSource::GridFlipX()
+{
+  vtkpxElectrodeSource* tmp_electrode=vtkpxElectrodeSource::New();
+  for (int j=0;j<Dimensions[1];j++)
+    for (int i=0;i<Dimensions[0]/2;i++)
+      {
+	int ia=(this->Dimensions[0]-i-1);
+	vtkpxElectrodeSource* first=this->GetElectrode(i,j);
+	vtkpxElectrodeSource* second=this->GetElectrode(ia,j);
+	tmp_electrode->Copy(second);
+	second->Copy(first);
+	first->Copy(tmp_electrode);
+      }
+  
+  tmp_electrode->Delete();
+  this->Modified();
+}
+
+void vtkpxElectrodeGridSource::GridFlipY()
+{
+  vtkpxElectrodeSource* tmp_electrode=vtkpxElectrodeSource::New();
+
+  for (int i=0;i<Dimensions[0];i++)
+    for (int j=0;j<Dimensions[1]/2;j++)
+      {
+	int ja=(this->Dimensions[1]-j-1);
+	vtkpxElectrodeSource* first=this->GetElectrode(i,j);
+	vtkpxElectrodeSource* second=this->GetElectrode(i,ja);
+	tmp_electrode->Copy(second);
+	second->Copy(first);
+	first->Copy(tmp_electrode);
+      }
+  
+  this->Modified();
+  tmp_electrode->Delete();
+}
+
+void vtkpxElectrodeGridSource::TransposeGrid()
+{
+  if (this->Dimensions[0]!=1 && this->Dimensions[1]!=1)
+    {
+      int total=Dimensions[0]*Dimensions[1];
+      vtkCollection* tmpCollection=vtkCollection::New();
+
+      this->ElectrodeCollection->InitTraversal();
+
+      for (int i=0;i<Dimensions[0];i++)
+	for (int j=0;j<Dimensions[1];j++)
+	{
+	  vtkpxElectrodeSource* orig=this->GetElectrode(i,j);
+	  vtkpxElectrodeSource* tmp_electrode=vtkpxElectrodeSource::New();
+	  tmp_electrode->Copy(orig);
+	  tmpCollection->AddItem(tmp_electrode);
+	}
+
+      
+      this->InitializeGrid(this->Dimensions[1],this->Dimensions[0]);
+      this->ElectrodeCollection->InitTraversal();
+      tmpCollection->InitTraversal();
+
+      for (int i=0;i<total;i++)
+	{
+	  vtkpxElectrodeSource* target=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+	  vtkpxElectrodeSource* source=(vtkpxElectrodeSource*)(tmpCollection->GetNextItemAsObject());
+	  target->Copy(source);
+	}
+
+      tmpCollection->RemoveAllItems();
+      tmpCollection->Delete();
+    }
+  else
+    {
+      int tmp=this->Dimensions[1];
+      this->Dimensions[1]=this->Dimensions[0];
+      this->Dimensions[0]=tmp;
+    }
+  this->Modified();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxElectrodeGridSource::Load(const char* fname)
+{  
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  int ok=Load(fin);
+  gzclose(fin);
+
+  return ok;
+}
+
+int vtkpxElectrodeGridSource::Load(gzFile fin)
+{
+  char line[255];
+  gzgets(fin,line,100);
+  int mode=0;
+
+  if (gzfindstringinstring(line,"#vtkpxElectrodeGridSource File")==0)
+    return 0;
+
+  if (gzfindstringinstring(line,"#vtkpxElectrodeGridSource File v2")==1)
+    mode=1;
+
+
+  gzgets(fin,line,250);   gzgets(fin,line,250); 
+
+  int a=strlen(line);  line[a-1]=(char)0;
+  this->SetGridName(line);
+
+  int d[2];
+  gzgets(fin,line,250); gzgets(fin,line,250); sscanf(line,"%d %d",&d[0],&d[1]);
+
+  this->InitializeGrid(d[0],d[1]);
+  gzgets(fin,line,250); gzgets(fin,line,250); sscanf(line,"%f %f",&this->ElectrodeSpacing[0],&this->ElectrodeSpacing[1]);
+  gzgets(fin,line,250); gzgets(fin,line,250); sscanf(line,"%d",&this->ElectrodeType);
+  gzgets(fin,line,250); gzgets(fin,line,250); sscanf(line,"%f",&this->Radius);
+  gzgets(fin,line,250); gzgets(fin,line,250); sscanf(line,"%f",&this->Thickness);
+  if (mode==1)
+    {
+      gzgets(fin,line,250); 
+      gzgets(fin,line,250); 
+      sscanf(line,"%f %f %f",&this->Color[0],&this->Color[1],&this->Color[2]);
+    }
+  else
+    {
+      this->Color[0]=0.8;
+      this->Color[1]=0.8;
+      this->Color[2]=0.8;
+    }
+
+  this->ElectrodeCollection->InitTraversal();
+  for (int j=0;j<this->Dimensions[1];j++)
+    for (int i=0;i<this->Dimensions[0];i++)
+      {
+	gzgets(fin,line,250); gzgets(fin,line,250);gzgets(fin,line,250);
+	vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+	electrode->Load(fin);
+      }
+
+  this->SynchronizeElectrodeTypeAndDimensions();
+  return 1;
+}
+//----------------------------------------------------------------------------
+int vtkpxElectrodeGridSource::Save(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+    return 0;
+  
+  int ok=Save(fout);
+  fclose(fout);
+  return ok;
+}
+
+int vtkpxElectrodeGridSource::Save(FILE* fout)
+{
+  this->SynchronizeElectrodeTypeAndDimensions();
+  fprintf(fout,"#vtkpxElectrodeGridSource File v2\n");
+  fprintf(fout,"#Description\n%s\n",GridName);
+  fprintf(fout,"#Dimensions\n %d %d\n",this->Dimensions[0],this->Dimensions[1]);
+  fprintf(fout,"#Electrode Spacing\n %.4f %.4f\n",this->ElectrodeSpacing[0],this->ElectrodeSpacing[1]);
+  fprintf(fout,"#Electrode Type\n%d\n",this->ElectrodeType);
+  fprintf(fout,"#Radius \n%f\n",this->Radius);
+  fprintf(fout,"#Thickeness\n%f\n",this->Thickness);
+  fprintf(fout,"#Color\n%.3f %.3f %.3f\n",this->Color[0],this->Color[1],this->Color[2]);
+
+  this->ElectrodeCollection->InitTraversal();
+  for (int j=0;j<this->Dimensions[1];j++)
+    for (int i=0;i<this->Dimensions[0];i++)
+      {
+	fprintf(fout,"#- - - - - - - - - - - - - - - - - - -\n# Electrode %d %d\n- - - - - - - - - - - - - - - - - - -\n",i,j);
+	vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+	electrode->Save(fout);
+      }
+
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+int vtkpxElectrodeGridSource::ApplyTransformation(vtkAbstractTransform* tr,int forward)
+{
+  if (tr==NULL)
+    return 0;
+ 
+  this->ElectrodeCollection->InitTraversal();
+  for (int j=0;j<this->Dimensions[1];j++)
+    for (int i=0;i<this->Dimensions[0];i++)
+      {
+	vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+	if (electrode!=NULL)
+	  electrode->ApplyTransformation(tr,forward);
+      }
+  this->Modified();
+  return 1;
+}
+//----------------------------------------------------------------------------
+void vtkpxElectrodeGridSource::SetNumberOfValues(int vl)
+{
+  this->ElectrodeCollection->InitTraversal();
+  for (int j=0;j<this->Dimensions[1];j++)
+    for (int i=0;i<this->Dimensions[0];i++)
+      {
+	vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+	if (electrode!=NULL)
+	  electrode->SetNumberOfValues(vl);
+      }
+}
+//----------------------------------------------------------------------------
+int vtkpxElectrodeGridSource::GetNumberOfValues()
+{
+  this->ElectrodeCollection->InitTraversal();
+  vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+  if (electrode!=NULL)
+    return electrode->GetNumberOfValues();
+  return 0;
+}
+//----------------------------------------------------------------------------
+void vtkpxElectrodeGridSource::SynchronizeElectrodeTypeAndDimensions()
+{
+  this->ElectrodeCollection->InitTraversal();
+  for (int j=0;j<this->Dimensions[1];j++)
+    for (int i=0;i<this->Dimensions[0];i++)
+      {
+	vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+	if (electrode->GetElectrodeType()!=this->ElectrodeType)
+	  electrode->SetElectrodeType(this->ElectrodeType);
+	if (electrode->GetRadius()!=this->Radius)
+	  electrode->SetRadius(this->Radius);
+	if (electrode->GetThickness()!=this->Thickness)
+	  electrode->SetThickness(this->Thickness);
+      }
+
+}
+//----------------------------------------------------------------------------
+int vtkpxElectrodeGridSource::CheckWhetherToShowLabelName(int i,int j)
+{
+  if (this->ShowLabelsGap==0 || this->Dimensions[0]*this->Dimensions[1]==1)
+    return 1;
+
+  j=(this->Dimensions[1]-j-1);
+
+  int sp=this->ShowLabelsGap+1;
+
+  if (this->Dimensions[1]<3)
+    {
+      if (i % sp == 0 )
+	return 1;
+      return 0;
+    }
+
+  else if (this->Dimensions[0]<3)
+    {
+      if (j % sp == 0 )
+	return 1;
+      return 0;
+    }
+  
+  if (this->ShowLabelsGap==1)
+    {
+      if (  (j % 2) ==  (i % 2)) 
+	   return 1;
+      else
+	return 0;
+    }
+
+  if ( ( j % this->ShowLabelsGap) == 0 && (i %this->ShowLabelsGap) ==0 )
+    return 1;
+  
+  return 0;
+}
+
+void vtkpxElectrodeGridSource::Execute()
+{
+  vtkPolyData* output = this->GetOutput();
+
+  if (this->EnableSynchronization)
+    this->SynchronizeElectrodeTypeAndDimensions();
+
+  // First add all preset electrodes 
+  vtkAppendPolyData* append=vtkAppendPolyData::New();
+  vtkPoints    *c_points    = vtkPoints::New();
+  c_points->SetNumberOfPoints(this->Dimensions[0]*this->Dimensions[1]);
+
+
+  vtkPoints      *c_labeledpoints  = vtkPoints::New();
+  vtkShortArray* c_labelnumbers    = vtkShortArray::New();
+  c_labelnumbers->SetNumberOfComponents(1);
+
+
+  int j=0,index=0;
+  //  fprintf(stderr,"Grid Color Mode=%d\n",this->ColorMode);
+  this->ElectrodeCollection->InitTraversal();
+  for (j=0;j<this->Dimensions[1];j++)
+    {
+      for (int i=0;i<this->Dimensions[0];i++)
+	{
+	  vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+	  if (electrode->GetElectrodePresent()==1)
+	    {
+	      if (this->ColorMode==0)
+		{
+		  electrode->SetColor(this->Color);
+		  electrode->SetColorModeToManual();
+		}
+	      else if (this->ColorMode==1)
+		electrode->SetColorModeToNormal();
+	      else
+		electrode->SetColorModeToManual();
+
+	      electrode->Update();
+	      append->AddInput(electrode->GetOutput());
+	    }
+	  c_points->SetPoint(index,electrode->GetPosition());
+	  
+	  if (electrode->GetElectrodePresent()==1)
+	    {
+	      if (this->CheckWhetherToShowLabelName(i,j)==1)
+		{
+		  c_labeledpoints->InsertNextPoint(electrode->GetPosition());
+		  c_labelnumbers->InsertNextTuple1(float(this->GetElectrodeRealIndex(i,j)));
+		}
+	    }
+	  
+	  ++index;
+	}
+    }
+
+  this->LabelSurface->SetPoints(c_labeledpoints);
+  this->LabelSurface->GetPointData()->SetScalars(c_labelnumbers);
+  c_labelnumbers->Delete();
+  c_labeledpoints->Delete();
+
+
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  c_lines->Allocate(this->Dimensions[0]+this->Dimensions[1],10);
+  
+  
+  vtkIdType pt[2];
+  for (j=0;j<this->Dimensions[1];j++)
+    for (int i=0;i<this->Dimensions[0];i++)
+      {
+	vtkpxElectrodeSource* electrode=this->GetElectrode(i,j);
+	pt[0]=j*this->Dimensions[0]+i;
+	if (electrode->GetElectrodePresent())
+	  {
+	    if (i<this->Dimensions[0]-1)
+	      {
+		vtkpxElectrodeSource* electrodex=this->GetElectrode(i+1,j);
+		if (electrodex->GetElectrodePresent())
+		  {
+		    pt[1]=pt[0]+1;
+		    c_lines->InsertNextCell(2,pt);
+		  }
+	      }
+	    if (j<this->Dimensions[1]-1)
+	      {
+		vtkpxElectrodeSource* electrodey=this->GetElectrode(i,j+1);
+		if (electrodey->GetElectrodePresent())
+		  {
+		    pt[1]=pt[0]+this->Dimensions[0];
+		    c_lines->InsertNextCell(2,pt);
+		  }
+	      }
+	  }
+      }
+
+  
+  unsigned char d[3];
+  for (int ia=0;ia<=2;ia++)
+    d[ia]=int(255*this->Color[ia]);
+
+  if (this->JustShowElectrodes==0)
+    {
+      vtkUnsignedCharArray* color_array=vtkUnsignedCharArray::New();
+      color_array->SetNumberOfComponents(3);
+      color_array->SetNumberOfTuples(this->Dimensions[0]*this->Dimensions[1]);
+      for (int k=0;k<color_array->GetNumberOfTuples();k++)
+	color_array->SetTuple3(k,d[0],d[1],d[2]);
+      
+      
+      vtkPolyData* lines=vtkPolyData::New();  
+      lines->SetPoints(c_points);
+      lines->SetLines(c_lines);
+      
+      lines->GetPointData()->SetScalars(color_array);
+      color_array->Delete();
+      c_lines->Delete();
+      
+      append->AddInput(lines);
+      append->Update();
+      lines->Delete();
+    }
+        
+  append->Update();
+  output->ShallowCopy(append->GetOutput());
+  append->Delete();
+  c_points->Delete();
+
+}
+
+//----------------------------------------------------------------------------
+int vtkpxElectrodeGridSource::FindClosestElectrodeIndex(float x,float y,float z)
+{
+  float q[3]; q[0]=x; q[1]=y; q[2]=z;
+  return FindClosestElectrodeIndex(x,y,z);
+}
+//----------------------------------------------------------------------------
+int vtkpxElectrodeGridSource::FindClosestElectrodeIndex(double q[3])
+{
+  int closest=-1;
+  float d=pow(float(this->Radius*5.0),float(2.0));
+  double p[3];
+  float maxd2=pow(float(this->Radius),float(2.0));
+  int index=0;
+  this->ElectrodeCollection->InitTraversal();
+  for (int j=0;j<this->Dimensions[1];j++)
+    for (int i=0;i<this->Dimensions[0];i++)
+      {
+	vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+	if (electrode->GetElectrodePresent()>0)
+	  {
+	    electrode->GetPosition(p);
+	    float d2=vtkMath::Distance2BetweenPoints(p,q);
+	    if (d2<maxd2 && d2<d )
+	      {
+		d=d2;
+		closest=index;
+	      }
+	  }
+      	++index;
+      }
+  return closest;
+}
+//----------------------------------------------------------------------------
+int vtkpxElectrodeGridSource::HandleClickedPoint(float x,float y,float z,int state)
+{
+  static int last_electrode=-1;
+  int dm=this->Dimensions[0]*this->Dimensions[1];
+  if (dm<1)
+    return 0;
+
+  double q[3]; q[0]=x; q[1]=y; q[2]=z;
+
+  int found=-1;
+
+  if (state==0)
+    {
+      found=this->FindClosestElectrodeIndex(q);
+      if (found>-1)
+	{
+	  vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetItemAsObject(found));
+	  this->EnableSynchronization=0;
+	  electrode->SetRadius(2.0*this->GetRadius());
+	  last_electrode=found;
+	}
+    }
+  else if (state==1 && last_electrode>=0)
+    {
+      vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetItemAsObject(last_electrode));
+      electrode->SetPosition(q);
+      found=last_electrode;
+    }
+  else if (state==2 && last_electrode>=0)
+    {
+      vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetItemAsObject(last_electrode));
+      electrode->SetPosition(q);
+      this->EnableSynchronization=1;
+      found=last_electrode;
+      last_electrode=-1;
+    }
+  
+  if (found==-1)
+    return -1;
+
+
+  this->Modified();
+  return found;
+}
+
+//----------------------------------------------------------------------------
+void vtkpxElectrodeGridSource::GetNeighborDistances(int index,vtkFloatArray* array)
+{
+  index=Irange(index,0,this->Dimensions[0]*this->Dimensions[1]-1);
+  vtkpxElectrodeSource* this_electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetItemAsObject(index));
+  double p[3];
+  this_electrode->GetPosition(p);
+  this->GetNeighborDistances(index,array,p[0],p[1],p[2]);
+}
+
+void vtkpxElectrodeGridSource::GetNeighborDistances(int index,vtkFloatArray* array,float px,float py,float pz)
+{
+  if (array==NULL)
+    return;
+
+  if (array->GetNumberOfComponents()!=1)
+    array->SetNumberOfComponents(1);
+
+  if (array->GetNumberOfTuples()!=4)
+    array->SetNumberOfTuples(4);
+
+  index=Irange(index,0,this->Dimensions[0]*this->Dimensions[1]-1);
+  
+  double p[3]; p[0]=px; p[1]=py; p[2]=pz;
+  double q[3];
+ 
+  int index2=index;
+  for (int i=0;i<=3;i++)
+    {
+      switch (i) 
+	{
+	case 0:
+	  index2=index-1;
+	  break;
+	case 1:
+	  index2=index+1;
+	  break;
+	case 2:
+	  index2=index-Dimensions[0];
+	  break;
+	case 3:
+	  index2=index+Dimensions[0];
+	  break;
+	}
+
+      if (index2<0 || index2>=this->Dimensions[0]*this->Dimensions[1])
+	{
+	  array->SetComponent(i,0,-1);
+	}
+      else 
+	{
+	  vtkpxElectrodeSource* other_electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetItemAsObject(index2));
+	  if (other_electrode->GetElectrodePresent())
+	    {
+	      other_electrode->GetPosition(q);
+	      array->SetComponent(i,0,sqrt(vtkMath::Distance2BetweenPoints(p,q)));
+	    }
+	  else
+	    {
+	      array->SetComponent(i,0,-1);
+	    }
+	}
+    }
+}
+
+// ---------------------------------------------------------------------------------------
+int vtkpxElectrodeGridSource::IsElectrodeModified(int index)
+{
+  int j=index/this->Dimensions[0];
+  int i=(index-j*this->Dimensions[0]);
+
+  double d[3],x[3];
+  d[0]=i*this->ElectrodeSpacing[0];
+  d[1]=j*this->ElectrodeSpacing[1];
+  d[2]=0.0;
+  this->GetElectrode(index)->GetPosition(x);
+  if (vtkMath::Distance2BetweenPoints(x,d)<0.01)
+    return 0;
+  return 1;
+}
+
+// ---------------------------------------------------------------------------------------
+int vtkpxElectrodeGridSource::GetNumberOfModifiedElectrodes()
+{
+  int index=0;
+  int sum=0;
+  for (int j=0;j<this->Dimensions[1];j++)
+    for (int i=0;i<this->Dimensions[0];i++)
+      {
+	sum+=IsElectrodeModified(index);
+	++index;
+      }
+  return sum;
+}
+
+// ---------------------------------------------------------------------------------------
+int vtkpxElectrodeGridSource::AutoWarp()
+{
+  int nummod=this->GetNumberOfModifiedElectrodes();
+  if (nummod<3)
+    return 0;
+
+  vtkPoints* points1=vtkPoints::New();
+  vtkPoints* points2=vtkPoints::New();
+  points1->SetNumberOfPoints(nummod);
+  points2->SetNumberOfPoints(nummod);
+
+  int index=0;
+  double d[3],x[3];
+  this->ElectrodeCollection->InitTraversal();
+  for (int j=0;j<this->Dimensions[1];j++)
+    for (int i=0;i<this->Dimensions[0];i++)
+      {
+
+	d[0]=i*this->ElectrodeSpacing[0];
+	d[1]=j*this->ElectrodeSpacing[1];
+	d[2]=0.0;
+	vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+	electrode->GetPosition(x);
+	if (vtkMath::Distance2BetweenPoints(x,d)>0.01)
+	  {
+	    points1->SetPoint(index,d);
+	    points2->SetPoint(index,x);
+	    ++index;
+	  }
+      }
+
+  vtkThinPlateSplineTransform* spl=vtkThinPlateSplineTransform::New();
+  spl->SetSourceLandmarks(points1);
+  spl->SetTargetLandmarks(points2);
+  spl->SetSigma(2.0);
+  spl->SetBasisToR();
+  points1->Delete();
+  points2->Delete();
+  spl->Update();
+  
+  this->ElectrodeCollection->InitTraversal();
+
+  for (int j=0;j<this->Dimensions[1];j++)
+    for (int i=0;i<this->Dimensions[0];i++)
+      {
+	d[0]=i*this->ElectrodeSpacing[0];
+	d[1]=j*this->ElectrodeSpacing[1];
+	d[2]=0.0;
+	spl->TransformPoint(d,x);
+	vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+	electrode->SetPreviousPosition(electrode->GetPosition());
+	electrode->SetPosition(x);
+	electrode->Modified();
+      }
+  this->Modified();
+  spl->Delete();
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+void vtkpxElectrodeGridSource::SetCurrentValueIndex(int a)
+{
+  this->ElectrodeCollection->InitTraversal();
+  for (int j=0;j<this->Dimensions[1];j++)
+    for (int i=0;i<this->Dimensions[0];i++)
+      {
+	vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+	electrode->SetCurrentValueIndex(a);
+	electrode->Modified();
+      }
+  this->Modified();
+}
+
+int  vtkpxElectrodeGridSource::GetCurrentValueIndex()
+{
+ this->ElectrodeCollection->InitTraversal();
+ vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(this->ElectrodeCollection->GetNextItemAsObject());
+  if (electrode==NULL)
+    return -1;
+  
+  return electrode->GetCurrentValueIndex();
+}
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxElectrodeGridSource.h b/bioimagesuite30_src/Graphics/vtkpxElectrodeGridSource.h
new file mode 100644
index 0000000..8a739e6
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxElectrodeGridSource.h
@@ -0,0 +1,267 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxElectrodeGridSource.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxElectrodeGridSource - stores and manipulates a set of electrodes arranged as a grid
+// .SECTION Description
+// This class stores all the necesary information for an implanted Electrode Grid such as
+// width x height (in electrodes e.g. 8x8)
+// electrode spacing x,y
+// electrode type and dimensions
+// grid name
+// and finally an array of the actual electrodes
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkPoints vtkPolyData vtkPolyDataSource vtkpxElectrodeSource
+
+
+
+#ifndef __vtkpxElectrodeGridSource_h
+#define __vtkpxElectrodeGridSource_h
+
+class vtkPoints;
+class vtkPolyData;
+
+class vtkPoints;
+class vtkPolyData;
+class vtkCollection;
+class vtkFloatArray;
+class vtkAbstractTransform;
+#include "vtkpxElectrodeSource.h"
+#include "vtkPolyDataSource.h"
+
+
+class vtkpxElectrodeGridSource : public vtkPolyDataSource 
+{
+public:
+  static vtkpxElectrodeGridSource *New();
+  vtkTypeMacro(vtkpxElectrodeGridSource,vtkPolyDataSource);
+
+public:
+
+  // Description:
+  // Grid Dimensions
+  vtkGetVectorMacro(Dimensions,int,2);
+
+  // Description:
+  // Electrode Spacing
+  vtkGetVectorMacro(ElectrodeSpacing,float,2);
+  vtkSetVectorMacro(ElectrodeSpacing,float,2);
+
+
+  // Description:
+  // Electrode Spacing
+  vtkGetVectorMacro(Color,float,3);
+  vtkSetVectorMacro(Color,float,3);
+
+  // Description:
+  // Marker Type 0=Sphere, 1= Disc
+  vtkGetMacro(ElectrodeType,int);
+  vtkSetClampMacro(ElectrodeType,int,0,1);
+  void SetElectrodeTypeToSphere() { this->SetElectrodeType(0);}
+  void SetElectrodeTypeToDisc()   { this->SetElectrodeType(1);}
+  
+  // Description:
+  // Set/Get Radius and Thickness (for disc) between 0.5 and 20mm
+  vtkGetMacro(Radius,float);
+  vtkSetClampMacro(Radius,float,0.5,20.0);
+
+  vtkGetMacro(Thickness,float);
+  vtkSetClampMacro(Thickness,float,0.01,2.0);
+
+  // Description:
+  // Specify name of the Grid 
+  vtkSetStringMacro(GridName);
+  vtkGetStringMacro(GridName);
+
+  // Description:
+  // Set/Get Current Value Index
+  virtual void SetCurrentValueIndex(int a);
+  virtual int  GetCurrentValueIndex();
+
+
+  // Description:
+  // Visible -- to enable/disable drawing for ElectrodeGridCollection
+  vtkSetClampMacro(Visible,int,0,1);
+  vtkGetMacro(Visible,int);
+  vtkBooleanMacro(Visible,int);
+
+  // Description:
+  // ColorMode = 0 : ForceUniform,  1=Electrode Normal, 2=Electrode Manual
+  vtkSetClampMacro(ColorMode,int,0,2);
+  vtkGetMacro(ColorMode,int);
+
+  // Description:
+  // Visible -- to enable/disable drawing lines for ElectrodeGridCollection
+  vtkSetClampMacro(JustShowElectrodes,int,0,1);
+  vtkGetMacro(JustShowElectrodes,int);
+  vtkBooleanMacro(JustShowElectrodes,int);
+
+  // Description:
+  // Visible -- to enable Synchronization of radius/thickness/type during drawing
+  vtkSetClampMacro(EnableSynchronization,int,0,1);
+  vtkGetMacro(EnableSynchronization,int);
+  vtkBooleanMacro(EnableSynchronization,int);
+
+    // Description:
+  // Load/Save Electrode in file
+  virtual int Load(const char* fname);
+  virtual int Save(const char* fname);
+
+  //BTX
+  // Description:
+  // Load/Save Electrode from already open file
+  virtual int Load(gzFile fin);
+  virtual int Save(FILE* fout);
+  //ETX
+
+  // Description:
+  // Copy Electrode Attributs from another Electrode
+  virtual void Copy(vtkpxElectrodeGridSource* other);
+  virtual void CopyAttributes(vtkpxElectrodeGridSource* other);
+
+  // Description:
+  // Get Individual Electrode
+  virtual vtkpxElectrodeSource* GetElectrode(int i,int j);
+  virtual vtkpxElectrodeSource* GetElectrode(int index);
+  virtual int GetElectrodeRealIndex(int i,int j);
+  virtual int GetElectrodeRealIndex(int index);
+
+  // Description:
+  // Label Stuff
+  virtual int CheckWhetherToShowLabelName(int i,int j);
+
+  vtkSetClampMacro(ShowLabelsGap,int,0,3);
+  vtkGetMacro(ShowLabelsGap,int);
+  vtkBooleanMacro(ShowLabelsGap,int);
+
+
+
+  // Description:
+  // Get Distances
+  virtual void GetNeighborDistances(int index,vtkFloatArray* array);
+  virtual void GetNeighborDistances(int index,vtkFloatArray* array,float x,float y,float z);
+
+  // Description:
+  // Initialze Grid
+  virtual void InitializeGrid(int dimx,int dimy);
+  virtual void TransposeGrid();
+  virtual void GridFlipX();
+  virtual void GridFlipY();
+
+  // Description:
+  // Ensure that all electrodes have the same type and dimensions
+  virtual void SynchronizeElectrodeTypeAndDimensions();
+  
+  // Description:
+  // Handle Mouse Event from Viewer (for Editing Purposes)
+  virtual int HandleClickedPoint(float x,float y,float z,int state);
+  virtual int FindClosestElectrodeIndex(double x[3]);
+  virtual int FindClosestElectrodeIndex(float x,float y,float z);
+
+  // Description: 
+  // Get Object Stuff
+  vtkGetObjectMacro(LabelSurface, vtkPolyData);
+  vtkGetObjectMacro(ElectrodeCollection,vtkCollection);
+
+  // Description:
+  // Apply Transformation
+  virtual int ApplyTransformation(vtkAbstractTransform* tr,int forward=1);
+
+  // Description:
+  // Is Electrode Modified
+  virtual int IsElectrodeModified(int index);
+  virtual int GetNumberOfModifiedElectrodes();
+  virtual int AutoWarp();
+
+  // Description:
+  // Set Number Of Values for all electrodes
+  virtual void SetNumberOfValues(int vl);
+  virtual int  GetNumberOfValues();
+
+    
+protected:
+  vtkpxElectrodeGridSource();
+  virtual ~vtkpxElectrodeGridSource();
+
+  vtkpxElectrodeGridSource(const vtkpxElectrodeGridSource&) {};
+  void operator=(const vtkpxElectrodeGridSource&) {};
+
+  virtual void Execute();  
+
+
+  //BTX
+  int   Dimensions[2];
+  float ElectrodeSpacing[2];
+  float Color[3];
+  int   ElectrodeType;
+  float Radius,Thickness;
+  char *GridName;
+  vtkCollection*  ElectrodeCollection;
+  vtkPolyData*    LabelSurface;
+
+  // Display Only Stuff
+  int   Visible;
+  int   JustShowElectrodes;
+  int   EnableSynchronization;
+  int   ShowLabelsGap;
+  int   ColorMode;
+  //ETX
+
+
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxElectrodeGridToSurfaceFilter.cpp b/bioimagesuite30_src/Graphics/vtkpxElectrodeGridToSurfaceFilter.cpp
new file mode 100644
index 0000000..8e74af1
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxElectrodeGridToSurfaceFilter.cpp
@@ -0,0 +1,561 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+ see vtkpxElectrodeGridToSurfaceFilter.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkCellArray.h"
+#include "vtkCollection.h"
+#include "vtkDiskSource.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkDoubleArray.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkThinPlateSplineTransform.h"
+#include "vtkTransformPolyDataFilter.h"
+#include "vtkpxElectrodeGridToSurfaceFilter.h"
+#include "vtkpxElectrodeSource.h"
+#include "vtkProbeFilter.h"
+//------------------------------------------------------------------------------
+vtkpxElectrodeGridToSurfaceFilter* vtkpxElectrodeGridToSurfaceFilter::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxElectrodeGridToSurfaceFilter");
+  if(ret)
+    {
+      return (vtkpxElectrodeGridToSurfaceFilter*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxElectrodeGridToSurfaceFilter;
+}
+
+// Construct object with no children.
+vtkpxElectrodeGridToSurfaceFilter::vtkpxElectrodeGridToSurfaceFilter()
+{
+  this->Grid=NULL;
+  this->BaseImage=NULL;
+  this->Transformation=NULL;
+  this->Sigma=1.0;
+  this->Lambda=1.0;
+  this->CTMode=1;
+  this->BaseSurface=NULL;
+  this->GridPointSurface=NULL;
+  this->SmoothImage=NULL;
+
+  this->SampleRate=4;
+}
+
+/* -------------------------------------------------------------------------*/
+ 
+vtkpxElectrodeGridToSurfaceFilter::~vtkpxElectrodeGridToSurfaceFilter()
+{
+  if (this->Transformation!=NULL)
+    this->Transformation->Delete();
+  this->SetBaseImage(NULL);
+  this->SetGrid(NULL);
+
+  if (this->BaseSurface!=NULL)
+    this->BaseSurface->Delete();
+
+  if (this->GridPointSurface!=NULL)
+    this->GridPointSurface->Delete();
+  
+  if (this->SmoothImage!=NULL)
+    this->SmoothImage->Delete();
+
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxElectrodeGridToSurfaceFilter::SetElectrodeGrid(vtkpxElectrodeGridSource* grd)
+{
+  this->SetGrid(grd);
+  if (this->BaseSurface!=NULL)
+    {
+      this->BaseSurface->Delete();
+      this->BaseSurface=NULL;
+    }
+
+  if (this->GridPointSurface!=NULL)
+    {
+      this->GridPointSurface->Delete();
+      this->GridPointSurface=NULL;
+    }
+  
+  if (this->Transformation!=NULL)
+    {
+      this->Transformation->Delete();
+      this->Transformation=NULL;
+    }
+}
+
+void vtkpxElectrodeGridToSurfaceFilter::SetImage(vtkImageData* img)
+{
+  this->SetBaseImage(img);
+  if (this->SmoothImage==NULL)
+    return;
+    
+  this->SmoothImage->Delete();
+  this->SmoothImage=NULL;
+}
+/* -------------------------------------------------------------------------*/
+//
+// Optimization Stuff
+//
+/* -------------------------------------------------------------------------*/
+
+double vtkpxElectrodeGridToSurfaceFilter::CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output)
+{
+  return ((vtkpxElectrodeGridToSurfaceFilter*)self)->OptimizerGradient(position,output);
+}
+
+double vtkpxElectrodeGridToSurfaceFilter::CalculateFunction(vtkObject* self,vtkDoubleArray* position)
+{
+  return ((vtkpxElectrodeGridToSurfaceFilter*)self)->OptimizerValue(position);
+}
+
+void vtkpxElectrodeGridToSurfaceFilter::OptimizerFeedback(vtkObject* self,const char* line,double val)
+{
+  fprintf(stderr,"Output %s : %.3f\n",line,val);
+}
+//-------------------------------------------------------------------------
+void vtkpxElectrodeGridToSurfaceFilter::Execute()
+{
+  vtkPolyData* output = this->GetOutput();
+
+  if (this->Grid==NULL)
+    {
+      vtkDiskSource* disk=vtkDiskSource::New();
+      disk->SetRadialResolution(2);
+      disk->SetCircumferentialResolution(2);
+      disk->Update();
+      output->ShallowCopy(disk->GetOutput());
+      disk->Delete();
+      return;
+    }
+
+  if (this->BaseSurface==NULL)
+    this->GenerateBaseSurface();
+
+  if (this->Transformation==NULL)
+    {
+      output->ShallowCopy(this->BaseSurface);
+      return;
+    }
+
+  vtkTransformPolyDataFilter* trF=vtkTransformPolyDataFilter::New();
+  trF->SetInput(this->BaseSurface);
+  trF->SetTransform(this->Transformation);
+  trF->Update();
+
+  output->ShallowCopy(trF->GetOutput());
+  trF->Delete();
+     
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxElectrodeGridToSurfaceFilter::Optimize(int iterations)
+{
+  if (this->Grid==NULL)
+    return 0;
+
+  if (this->SmoothImage==NULL)
+    this->GenerateSmoothImage();
+
+  if (this->BaseSurface==NULL)
+    this->GenerateBaseSurface();
+
+  if (this->Transformation==NULL)
+    this->InitializeTransformation();
+
+  int np=this->Transformation->GetSourceLandmarks()->GetNumberOfPoints();
+
+  int dims[2]; this->Grid->GetDimensions(dims);
+		 
+  vtkpxOptimizer* optimizer=vtkpxOptimizer::New();
+  vtkDoubleArray* position=vtkDoubleArray::New();
+  vtkDoubleArray* temp=vtkDoubleArray::New();
+  position->SetNumberOfTuples(np*3);
+  this->GetCurrentParameters(position);
+  optimizer->SetMasterObject(this);
+
+  optimizer->SetEvaluateFunctionMethod(&vtkpxElectrodeGridToSurfaceFilter::CalculateFunction);
+  optimizer->SetEvaluateGradientMethod(&vtkpxElectrodeGridToSurfaceFilter::CalculateGradient);
+  optimizer->SetFeedbackMethod(&vtkpxElectrodeGridToSurfaceFilter::OptimizerFeedback);
+
+  optimizer->ComputeConjugateGradient(position,iterations,0.001);
+    
+  optimizer->Delete();
+  position->Delete();
+  temp->Delete();
+  
+  return 1;
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxElectrodeGridToSurfaceFilter::GenerateSmoothImage()
+{
+  if (this->BaseImage==NULL)
+    return 0;
+
+  vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+  smooth->SetInput(this->BaseImage);
+  smooth->SetStandardDeviations(this->Sigma,this->Sigma,this->Sigma);
+  smooth->Update();
+
+  if (this->SmoothImage==NULL)
+    this->SmoothImage=vtkImageData::New();
+  this->SmoothImage->ShallowCopy(smooth->GetOutput());
+  smooth->Delete();
+  return 1;
+}
+
+int vtkpxElectrodeGridToSurfaceFilter::InitializeTransformation()
+{
+  if (this->Grid==NULL)
+    return 0;
+
+  if (this->BaseSurface==NULL)
+    this->GenerateBaseSurface();
+
+  vtkPoints* points1=vtkPoints::New();
+  vtkPoints* points2=vtkPoints::New();
+  
+  int dims[2]; this->Grid->GetDimensions(dims);
+  int num=dims[0]*dims[1];
+
+  this->Grid->AutoWarp();
+
+  points1->Allocate(num,2);
+  points2->Allocate(num,2);
+
+  double d[3],x[3];
+  vtkCollection* ElectrodeCollection=this->Grid->GetElectrodeCollection();
+  float sp[2]; this->Grid->GetElectrodeSpacing(sp);
+
+  int index=0;
+  ElectrodeCollection->InitTraversal();
+  for (int j=0;j<dims[1];j++)
+    for (int i=0;i<dims[0];i++)
+      {
+	d[0]=i*sp[0];
+	d[1]=j*sp[1];
+	d[2]=0.0;
+	vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(ElectrodeCollection->GetNextItemAsObject());
+	if (electrode->GetElectrodePresent())
+	  {
+	    electrode->GetPosition(x);
+	    points1->InsertNextPoint(d);
+	    points2->InsertNextPoint(x);
+	    ++index;
+	  }
+      }
+	    
+  if (this->Transformation==NULL)
+    this->Transformation=vtkThinPlateSplineTransform::New();
+  this->Transformation->SetSourceLandmarks(points1);
+  this->Transformation->SetTargetLandmarks(points2);
+  this->Transformation->SetSigma(2.0);
+  this->Transformation->SetBasisToR();
+  points1->Delete();
+  points2->Delete();
+  this->Transformation->Update();
+  return 1;
+
+}
+
+// ------------------------------------------------------------------------------------------------------------------------------------------
+int vtkpxElectrodeGridToSurfaceFilter::GenerateBaseSurface()
+{
+  if (this->GridPointSurface==NULL)
+    this->GridPointSurface=vtkPolyData::New();
+
+  int dims[2]; this->Grid->GetDimensions(dims);
+  
+  vtkCollection* ElectrodeCollection=this->Grid->GetElectrodeCollection();
+  float sp[2]; this->Grid->GetElectrodeSpacing(sp);
+
+  vtkPoints    *c_points2    = vtkPoints::New();
+  c_points2->Allocate(dims[0]*dims[1]*(1+this->SampleRate)*(1+this->SampleRate),20);
+
+  ElectrodeCollection->InitTraversal();
+
+  for (int j=0;j<dims[1];j++)
+    for (int i=0;i<dims[0];i++)
+      {
+	vtkpxElectrodeSource* electrode=(vtkpxElectrodeSource*)(ElectrodeCollection->GetNextItemAsObject());
+	if (electrode->GetElectrodePresent())
+	  {
+	    double d[3];
+	    d[0]=i*sp[0];	d[1]=j*sp[1];	    d[2]=0.0;
+	    c_points2->InsertNextPoint(electrode->GetPosition());
+	  }
+      }
+  this->GridPointSurface->SetPoints(c_points2);
+  c_points2->Delete();
+
+  int numx=dims[0]+(dims[0]-1)*this->SampleRate;
+  int numy=dims[1]+(dims[1]-1)*this->SampleRate;
+
+
+  vtkPoints    *c_points    = vtkPoints::New();
+  c_points->SetNumberOfPoints(numx*numy);
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  c_lines->Allocate(numx*numy,10);
+  
+  double newsp[2];
+  newsp[0]=sp[0]/double(this->SampleRate+1);
+  newsp[1]=sp[1]/double(this->SampleRate+1);
+
+  vtkIdType index=0;
+  vtkIdType pt[2];
+  for (int j=0;j<numy;j++)
+    for (int i=0;i<numx;i++)
+      {
+	double d[3];
+	d[0]=i*newsp[0];
+	d[1]=j*newsp[1];
+	d[2]=0.0;
+	c_points->SetPoint(index,d);
+	pt[0]=index;
+
+	if (i!=numx-1)
+	  {
+	    pt[1]=index+1;
+	    c_lines->InsertNextCell(2,pt);
+	  }
+	if (j!=numy-1)
+	  {
+	    pt[1]=index+numx;
+	    c_lines->InsertNextCell(2,pt);
+	  }
+	++index;
+      }
+
+  if (this->BaseSurface==NULL)
+    this->BaseSurface=vtkPolyData::New();
+  this->BaseSurface->SetPoints(c_points);
+  this->BaseSurface->SetLines(c_lines);
+
+  c_points->Delete();
+  c_lines->Delete();
+
+  return 1;
+}
+
+
+/* -------------------------------------------------------------------------*/
+double vtkpxElectrodeGridToSurfaceFilter::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+{
+  if (grad->GetNumberOfTuples()!=params->GetNumberOfTuples())
+    grad->SetNumberOfTuples(params->GetNumberOfTuples());
+
+  grad->FillComponent(0,0.0);
+  double GradientNorm = 0;
+  double step=1.0;
+
+  int np=grad->GetNumberOfTuples();
+
+  for (int i=0;i<np;i++)
+    {
+      double orig=params->GetComponent(i,0);
+      params->SetComponent(i, 0, orig + step);
+      double a=this->OptimizerValue(params);
+      
+      params->SetComponent(i, 0, orig - step);
+      double b=this->OptimizerValue(params);
+      
+      params->SetComponent(i, 0, orig);
+      this->SetCurrentParameters(params);
+
+      double g=-0.5*(b-a)/step;
+      grad->SetComponent(i,0,g);
+      GradientNorm+=pow(g,2.0);
+    }
+
+  GradientNorm = (sqrt(GradientNorm));
+  // -------------------------
+  // Hirohito Found this One!!
+  // -------------------------
+  for (int j=0;j<np;j++)
+    grad->SetComponent(j,0,grad->GetComponent(j,0)/GradientNorm);
+      
+  return GradientNorm;
+}
+
+ 
+double vtkpxElectrodeGridToSurfaceFilter::OptimizerValue(vtkDoubleArray* params)
+{
+  this->SetCurrentParameters(params);
+  
+  // First The Image Adherence Term
+  vtkTransformPolyDataFilter* trF=vtkTransformPolyDataFilter::New();
+  trF->SetInput(this->GridPointSurface);
+  trF->SetTransform(this->Transformation);
+  trF->Update();
+
+  vtkProbeFilter* probe=vtkProbeFilter::New();
+  probe->SetInput(trF->GetOutput());
+  probe->SetSource(this->SmoothImage);
+  probe->Update();
+      
+  vtkDataArray* data=probe->GetOutput()->GetPointData()->GetScalars();
+  double sum=0.0;
+
+  float sp[2]; this->Grid->GetElectrodeSpacing(sp);
+  double newsp[2];
+  newsp[0]=sp[0]/double(this->SampleRate+1);
+  newsp[1]=sp[1]/double(this->SampleRate+1);
+
+  int   np=data->GetNumberOfTuples();
+  for (int i=0;i<np;i++)
+    sum+=data->GetComponent(i,0);
+  probe->Delete();
+  trF->Delete();
+
+  if (np>0)
+    sum/=double(np);
+
+  if (this->CTMode==0)
+    sum=-sum;
+  
+  double ImageAdherence=sum;
+
+
+  // Then Smoothness Term
+
+  vtkTransformPolyDataFilter* trF2=vtkTransformPolyDataFilter::New();
+  trF2->SetInput(this->BaseSurface);
+  trF2->SetTransform(this->Transformation);
+  trF2->Update();
+
+  vtkPoints* pts=trF2->GetOutput()->GetPoints();
+
+  int dims[2]; this->Grid->GetDimensions(dims);
+  int numx=dims[0]+(dims[0]-1)*this->SampleRate;
+  int numy=dims[1]+(dims[1]-1)*this->SampleRate;
+
+
+  double distance=0.0;
+  int   numlines=0;
+
+  int index=0;
+  double x1[3],x2[3];
+  for (int j=0;j<numy;j++)
+    for (int i=0;i<numx;i++)
+      {
+	pts->GetPoint(index,x1);
+	if (i!=numx-1)
+	  {
+	    pts->GetPoint(index+1,x2);
+	    distance+=pow( sqrt(vtkMath::Distance2BetweenPoints(x1,x2))-newsp[0],2.0);
+	    ++numlines;
+	  }
+	if (j!=numy-1)
+	  {
+	    pts->GetPoint(index+numx,x2);
+	    distance+=pow( sqrt(vtkMath::Distance2BetweenPoints(x1,x2))-newsp[0],2.0);
+	    ++numlines;
+	  }
+	++index;
+      }
+
+
+
+  if (numlines>0)
+    distance=distance/double(numlines);
+
+  trF2->Delete();
+  
+  double total=-ImageAdherence - this->Lambda*distance;
+  fprintf(stderr,"ImageAdherence=%.3f distance=%.3f \t\t Total=%.3f\n",ImageAdherence,distance,total);
+
+  return total;
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxElectrodeGridToSurfaceFilter::SetCurrentParameters(vtkDoubleArray* params)
+{
+  int np=this->Transformation->GetSourceLandmarks()->GetNumberOfPoints();
+  if (params->GetNumberOfTuples()!=np*3)
+    {
+      vtkErrorMacro(<<"Bad Number Of Parameters\n");
+      return;
+    }
+
+  vtkPoints* points=this->Transformation->GetSourceLandmarks();
+
+  int index=0;
+  for (int i=0;i<np;i++)
+    {
+      double x[3];
+      for (int j=0;j<=2;j++)
+	{
+	  x[j]=params->GetComponent(index,0);
+	  ++index;
+	}
+      points->SetPoint(i,x);
+    }
+  this->Transformation->Update();
+}
+
+void vtkpxElectrodeGridToSurfaceFilter::GetCurrentParameters(vtkDoubleArray* params)
+{
+  int np=this->Transformation->GetSourceLandmarks()->GetNumberOfPoints();
+  if (params->GetNumberOfTuples()!=np*3)
+    {
+      params->SetNumberOfComponents(1);
+      params->SetNumberOfTuples(np*3);
+    }
+
+  vtkPoints* points=this->Transformation->GetSourceLandmarks();
+
+  int index=0;
+  for (int i=0;i<np;i++)
+    {
+      double x[3]; points->GetPoint(i,x);
+      for (int j=0;j<=2;j++)
+	{
+	  params->SetComponent(index,0,x[j]);
+	  ++index;
+	}
+    }
+
+
+}
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxElectrodeGridToSurfaceFilter.h b/bioimagesuite30_src/Graphics/vtkpxElectrodeGridToSurfaceFilter.h
new file mode 100644
index 0000000..50c5692
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxElectrodeGridToSurfaceFilter.h
@@ -0,0 +1,192 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxElectrodeGridToSurfaceFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxElectrodeGridToSurfaceFilter - stores and manipulates a set of electrodes arranged as a grid
+// .SECTION Description
+// This class stores all the necesary information for an implanted Electrode Grid such as
+// width x height (in electrodes e.g. 8x8)
+// electrode spacing x,y
+// electrode type and dimensions
+// grid name
+// and finally an array of the actual electrodes
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkPoints vtkPolyData vtkPolyDataSource vtkpxElectrodeSource
+
+
+
+#ifndef __vtkpxElectrodeGridToSurfaceFilter_h
+#define __vtkpxElectrodeGridToSurfaceFilter_h
+
+class vtkPoints;
+class vtkPolyData;
+class vtkCollection;
+class vtkDoubleArray;
+
+#include "vtkpxElectrodeSource.h"
+#include "vtkPolyDataSource.h"
+#include "vtkpxElectrodeGridSource.h"
+#include "vtkThinPlateSplineTransform.h"
+#include "vtkImageData.h"
+#include "vtkpxOptimizer.h"
+#include "vtkDoubleArray.h"
+
+class vtkpxElectrodeGridToSurfaceFilter : public vtkPolyDataSource 
+{
+public:
+  static vtkpxElectrodeGridToSurfaceFilter *New();
+  vtkTypeMacro(vtkpxElectrodeGridToSurfaceFilter,vtkPolyDataSource);
+
+public:
+
+  // Description:
+  // Copy Electrode Attributs from another Electrode
+  vtkGetObjectMacro(Grid,vtkpxElectrodeGridSource);
+  virtual void SetElectrodeGrid(vtkpxElectrodeGridSource* grd);
+
+  // Description:
+  // Copy Electrode Attributs from another Electrode
+  vtkGetObjectMacro(BaseImage,vtkImageData);
+  virtual void SetImage(vtkImageData* img);
+
+  // Description:
+  // Get the Transformation
+  vtkGetObjectMacro(Transformation,vtkThinPlateSplineTransform);
+
+  // Description:
+  // Sigma == smoothing kernel for blurring the input image
+  vtkGetMacro(Sigma,double);
+  vtkSetMacro(Sigma,double);
+
+  // Descripion:
+  // Lambda == smoothness of spline
+  vtkGetMacro(Lambda,double);
+  vtkSetMacro(Lambda,double);
+  
+  // Description:
+  // Mode 0 = MRI, 1= CT
+  vtkSetClampMacro(CTMode,int,0,1);
+  vtkGetMacro(CTMode,int);
+  vtkBooleanMacro(CTMode,int);
+
+  // Description:
+  // SampleRate
+  vtkSetClampMacro(SampleRate,int,1,10);
+  vtkGetMacro(SampleRate,int);
+
+  // Description:
+  // Optimize Grid
+  virtual int Optimize(int iterations);
+
+  // Description:
+  // Optimization Routines
+  static void  OptimizerFeedback(vtkObject* self,const char* line,double val);
+  static double CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output);
+  static double CalculateFunction(vtkObject* self,vtkDoubleArray* position);
+
+  // Description:
+  // Modify Image
+  virtual int GenerateSmoothImage();
+  virtual int GenerateBaseSurface();
+  virtual int InitializeTransformation();
+    
+protected:
+  vtkpxElectrodeGridToSurfaceFilter();
+  virtual ~vtkpxElectrodeGridToSurfaceFilter();
+
+  vtkpxElectrodeGridToSurfaceFilter(const vtkpxElectrodeGridToSurfaceFilter&) {};
+  void operator=(const vtkpxElectrodeGridToSurfaceFilter&) {};
+
+
+  // Description:
+  // Update Output 
+  virtual void Execute();  
+
+  
+  // Description:
+  // Needed for Optimizer -- set,get,optimizer,optimizervalue
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+  virtual void  SetCurrentParameters(vtkDoubleArray* params);
+  virtual void  GetCurrentParameters(vtkDoubleArray* params);
+
+  // Description:
+  // Protected to avoid setting directly
+  vtkSetObjectMacro(BaseImage,vtkImageData);
+  vtkSetObjectMacro(Grid,vtkpxElectrodeGridSource);
+
+
+  // Description:
+  // Data Members
+  //BTX
+  vtkpxElectrodeGridSource*    Grid;
+  vtkPolyData*                 BaseSurface;
+  vtkPolyData*                 GridPointSurface;
+  vtkImageData*                BaseImage;
+  vtkImageData*                SmoothImage;
+  vtkThinPlateSplineTransform* Transformation;
+
+  double  Sigma;
+  double  Lambda;
+  int    CTMode;
+  int    SampleRate;
+  //ETX
+
+
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxElectrodeMultiGridSource.cpp b/bioimagesuite30_src/Graphics/vtkpxElectrodeMultiGridSource.cpp
new file mode 100644
index 0000000..c7e36e2
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxElectrodeMultiGridSource.cpp
@@ -0,0 +1,659 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+ see vtkpxElectrodeMultiGridSource.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkAppendPolyData.h"
+#include "vtkCellArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkpxElectrodeMultiGridSource.h"
+#include "vtkpxElectrodeGridSource.h"
+#include "vtkCollection.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkFloatArray.h"
+#include "vtkSphereSource.h"
+#include "vtkImageData.h"
+#include "vtkMath.h"
+#include "vtkShortArray.h"
+#include "vtkLookupTable.h"
+#include "sstream"
+//------------------------------------------------------------------------------
+vtkpxElectrodeMultiGridSource* vtkpxElectrodeMultiGridSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxElectrodeMultiGridSource");
+  if(ret)
+    {
+      return (vtkpxElectrodeMultiGridSource*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxElectrodeMultiGridSource;
+}
+
+// Construct object with no children.
+vtkpxElectrodeMultiGridSource::vtkpxElectrodeMultiGridSource()
+{
+  this->Description=NULL; this->SetDescription("patient");
+  this->Comment=NULL; this->SetComment("no additional comment");
+  this->ElectrodeGridCollection=vtkCollection::New();
+  this->LabelSurface=vtkPolyData::New();
+}
+
+/* -------------------------------------------------------------------------*/
+ 
+vtkpxElectrodeMultiGridSource::~vtkpxElectrodeMultiGridSource()
+{
+  this->ElectrodeGridCollection->Delete();
+  if (this->Description!=NULL)
+    delete [] Description;
+  if (this->Comment!=NULL)
+    delete [] Comment;
+  this->LabelSurface->Delete();
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxElectrodeMultiGridSource::CopyAttributes(vtkpxElectrodeMultiGridSource* other)
+{
+  int d=this->ElectrodeGridCollection->GetNumberOfItems();
+  int num=other->GetNumberOfGrids();
+
+  if (d!=num)
+    {
+      vtkErrorMacro(<<"Cannot copy attributes .. different number of grids\n");
+      return;
+    }
+
+  this->ElectrodeGridCollection->InitTraversal();
+
+  for (int i=0;i<d;i++)
+    {
+      vtkpxElectrodeGridSource* electrodegrid=(vtkpxElectrodeGridSource*)(this->ElectrodeGridCollection->GetNextItemAsObject());
+      electrodegrid->CopyAttributes(other->GetElectrodeGrid(i));
+    }
+  this->Modified();
+
+}
+
+
+void vtkpxElectrodeMultiGridSource::Copy(vtkpxElectrodeMultiGridSource* other)
+{
+  int num=other->GetNumberOfGrids();
+  this->InitializeMultiGrid(num);
+
+  this->SetComment(other->GetComment());
+  this->SetDescription(other->GetDescription());
+
+  int d=this->ElectrodeGridCollection->GetNumberOfItems();
+  this->ElectrodeGridCollection->InitTraversal();
+
+  for (int i=0;i<d;i++)
+      {
+	vtkpxElectrodeGridSource* electrodegrid=(vtkpxElectrodeGridSource*)(this->ElectrodeGridCollection->GetNextItemAsObject());
+	electrodegrid->Copy(other->GetElectrodeGrid(i));
+      }
+  this->Modified();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxElectrodeMultiGridSource::GetNumberOfGrids()
+{
+  return this->ElectrodeGridCollection->GetNumberOfItems();
+}
+/* -------------------------------------------------------------------------*/
+vtkpxElectrodeGridSource* vtkpxElectrodeMultiGridSource::GetElectrodeGrid(int i)
+{
+  int d=this->ElectrodeGridCollection->GetNumberOfItems();
+  i=Irange(i,0,d-1);
+  vtkpxElectrodeGridSource* electrodegrid=(vtkpxElectrodeGridSource*)(this->ElectrodeGridCollection->GetItemAsObject(i));
+  return electrodegrid;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxElectrodeMultiGridSource::InitializeMultiGrid(int numgrids)
+{
+  numgrids=Irange(numgrids,0,40);
+
+  if (this->ElectrodeGridCollection->GetNumberOfItems()>0)
+    this->ElectrodeGridCollection->RemoveAllItems();
+  for (int i=0;i<numgrids;i++)
+      {
+	vtkpxElectrodeGridSource* electrodegrid=vtkpxElectrodeGridSource::New();
+	if (i==0)
+	  electrodegrid->InitializeGrid(8,8);
+	else
+	  electrodegrid->InitializeGrid(1,8);
+	this->ElectrodeGridCollection->AddItem(electrodegrid);
+	electrodegrid->Delete();
+      }
+
+  this->Modified();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxElectrodeMultiGridSource::Load(const char* fname)
+{  
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  int ok=Load(fin);
+  gzclose(fin);
+
+  return ok;
+}
+
+int vtkpxElectrodeMultiGridSource::Load(gzFile fin)
+{
+  char line[255];
+  gzgets(fin,line,100);
+  if (gzfindstringinstring(line,"#vtkpxElectrodeMultiGridSource File")==0)
+    return 0;
+
+  int a=0;
+  gzgets(fin,line,100);   gzgets(fin,line,100); a=strlen(line);  line[a-1]=(char)0;  this->SetDescription(line);
+  gzgets(fin,line,100);   gzgets(fin,line,100); a=strlen(line);  line[a-1]=(char)0;  this->SetComment(line);
+
+
+  int d;
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&d);
+  this->InitializeMultiGrid(d);
+  d=this->ElectrodeGridCollection->GetNumberOfItems();
+
+  this->ElectrodeGridCollection->InitTraversal();
+  for (int i=0;i<d;i++)
+      {
+	gzgets(fin,line,100);
+	gzgets(fin,line,100);
+	gzgets(fin,line,100);
+	vtkpxElectrodeGridSource* electrodegrid=(vtkpxElectrodeGridSource*)(this->ElectrodeGridCollection->GetNextItemAsObject());
+	if (electrodegrid==NULL)
+	  fprintf(stderr,"Bad Grid %d\n",i);
+	electrodegrid->Load(fin);
+      }
+  
+  return 1;
+}
+//----------------------------------------------------------------------------
+int vtkpxElectrodeMultiGridSource::Save(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+    return 0;
+  
+  int ok=Save(fout);
+  fclose(fout);
+  return ok;
+}
+
+int vtkpxElectrodeMultiGridSource::Save(FILE* fout)
+{
+  fprintf(fout,"#vtkpxElectrodeMultiGridSource File\n");
+  fprintf(fout,"#Description\n%s\n",Description);
+  fprintf(fout,"#Comment\n%s\n",Comment);
+  int num=this->GetNumberOfGrids();
+  fprintf(fout,"#Number of Grids\n %d \n",num);
+  this->ElectrodeGridCollection->InitTraversal();
+  for (int i=0;i<num;i++)
+    {
+      fprintf(fout,"#- - - - - - - - - - - - - - - - - - -\n# Electrode Grid %d\n- - - - - - - - - - - - - - - - - - -\n",i);
+      vtkpxElectrodeGridSource* electrodegrid=(vtkpxElectrodeGridSource*)(this->ElectrodeGridCollection->GetNextItemAsObject());
+      electrodegrid->Save(fout);
+    }
+  
+  return 1;
+}
+//----------------------------------------------------------------------------
+void vtkpxElectrodeMultiGridSource::SetNumberOfValues(int vl)
+{
+  int num=this->GetNumberOfGrids();
+  this->ElectrodeGridCollection->InitTraversal();
+  for (int i=0;i<num;i++)
+    {
+      vtkpxElectrodeGridSource* electrodegrid=(vtkpxElectrodeGridSource*)(this->ElectrodeGridCollection->GetNextItemAsObject());
+      if (electrodegrid!=NULL)
+	electrodegrid->SetNumberOfValues(vl);
+    }
+  this->Modified();
+}
+//----------------------------------------------------------------------------
+int vtkpxElectrodeMultiGridSource::GetNumberOfValues()
+{
+  int num=this->GetNumberOfGrids();
+  this->ElectrodeGridCollection->InitTraversal();
+  for (int i=0;i<num;i++)
+    {
+      vtkpxElectrodeGridSource* electrodegrid=(vtkpxElectrodeGridSource*)(this->ElectrodeGridCollection->GetNextItemAsObject());
+      if (electrodegrid!=NULL)
+	return electrodegrid->GetNumberOfValues();
+    }
+  return 0;
+}
+//----------------------------------------------------------------------------
+void vtkpxElectrodeMultiGridSource::ShowLabelsGap(int all)
+{
+  int num=this->GetNumberOfGrids();
+  this->ElectrodeGridCollection->InitTraversal();
+  for (int i=0;i<num;i++)
+    {
+      vtkpxElectrodeGridSource* electrodegrid=(vtkpxElectrodeGridSource*)(this->ElectrodeGridCollection->GetNextItemAsObject());
+      if (electrodegrid!=NULL)
+	electrodegrid->SetShowLabelsGap(all);
+    }
+  this->Modified();
+}
+
+int vtkpxElectrodeMultiGridSource::ApplyTransformation(vtkAbstractTransform* tr,int forward)
+{
+  if (tr==NULL)
+    return 0;
+ 
+  int num=this->GetNumberOfGrids();
+  this->ElectrodeGridCollection->InitTraversal();
+  for (int i=0;i<num;i++)
+    {
+      vtkpxElectrodeGridSource* electrodegrid=(vtkpxElectrodeGridSource*)(this->ElectrodeGridCollection->GetNextItemAsObject());
+      if (electrodegrid!=NULL)
+	electrodegrid->ApplyTransformation(tr,forward);
+    }
+  this->Modified();
+  return 1;
+}
+
+
+
+//----------------------------------------------------------------------------
+
+
+void vtkpxElectrodeMultiGridSource::Execute()
+{
+  vtkPolyData* output = this->GetOutput();
+
+  
+  // First add all preset electrodes 
+  vtkAppendPolyData* append=vtkAppendPolyData::New();
+
+  int num=this->GetNumberOfGrids();
+  this->ElectrodeGridCollection->InitTraversal();
+  int num_grids_to_display=0;
+  int ntotalp=0;
+
+  for (int i=0;i<num;i++)
+    {
+      vtkpxElectrodeGridSource* electrodegrid=(vtkpxElectrodeGridSource*)(this->ElectrodeGridCollection->GetNextItemAsObject());
+      if (electrodegrid->GetVisible()==1)
+	{
+	  electrodegrid->Update();
+	  append->AddInput(electrodegrid->GetOutput());
+	  ntotalp+=electrodegrid->GetLabelSurface()->GetNumberOfPoints();
+
+	  ++num_grids_to_display;
+	}
+    }
+
+  if (ntotalp>0)
+    {
+      vtkPoints* pt=vtkPoints::New();
+      pt->SetNumberOfPoints(ntotalp);
+
+      vtkShortArray* pl=vtkShortArray::New();
+      pl->SetNumberOfComponents(1);
+      pl->SetNumberOfTuples(ntotalp);
+      
+      int index=0;
+
+      this->ElectrodeGridCollection->InitTraversal();
+      for (int i=0;i<num;i++)
+	{
+	  vtkpxElectrodeGridSource* electrodegrid=(vtkpxElectrodeGridSource*)(this->ElectrodeGridCollection->GetNextItemAsObject());
+	  if (electrodegrid->GetVisible()==1)
+	    {
+	      int n=electrodegrid->GetLabelSurface()->GetNumberOfPoints();
+	      vtkPoints* t_p=electrodegrid->GetLabelSurface()->GetPoints();
+	      vtkDataArray* t_d=electrodegrid->GetLabelSurface()->GetPointData()->GetScalars();
+	      for (int j=0;j<n;j++)
+		{
+		  pt->SetPoint(index,t_p->GetPoint(j));
+		  pl->SetComponent(index,0,t_d->GetComponent(j,0));
+		  ++index;
+		}
+	    }
+	}
+      this->LabelSurface->SetPoints(pt);
+      this->LabelSurface->GetPointData()->SetScalars(pl);
+      pt->Delete();
+      pl->Delete();
+    }
+
+  if (num_grids_to_display==0)
+    {
+      vtkSphereSource* sphere=vtkSphereSource::New();
+      sphere->SetRadius(0.01);
+      sphere->SetThetaResolution(3);
+      sphere->SetPhiResolution(3);
+      sphere->Update();
+      output->ShallowCopy(sphere->GetOutput());
+      this->LabelSurface->ShallowCopy(sphere->GetOutput());
+      sphere->Delete();
+    }
+  else
+    {
+      append->Update();
+
+      output->ShallowCopy(append->GetOutput());
+    }
+  append->Delete();
+
+}
+
+//----------------------------------------------------------------------------
+void vtkpxElectrodeMultiGridSource::InsertNewGrid()
+{
+  vtkpxElectrodeGridSource* electrodegrid=vtkpxElectrodeGridSource::New();
+  electrodegrid->InitializeGrid(1,8);
+  char line[20];  sprintf(line,"grid_%d",this->GetNumberOfGrids()+1);
+  electrodegrid->SetGridName(line);
+  this->ElectrodeGridCollection->AddItem(electrodegrid);
+  electrodegrid->Delete();
+  this->Modified();
+}
+//----------------------------------------------------------------------------
+void vtkpxElectrodeMultiGridSource::DeleteGrid(int index)
+{
+  if (this->GetNumberOfGrids()<2)
+    return;
+
+  if (index<0 || index>=this->GetNumberOfGrids())
+    return;
+  
+  this->ElectrodeGridCollection->RemoveItem(index);
+
+}
+//----------------------------------------------------------------------------
+vtkPolyData* vtkpxElectrodeMultiGridSource::ExportToPolyDataAsPoints(int Mode)
+{
+  return this->ExportToPolyDataAsPoints(Mode,-1.0);
+}
+//----------------------------------------------------------------------------
+vtkPolyData* vtkpxElectrodeMultiGridSource::ExportToPolyDataAsPoints(int Mode,float radius)
+{
+  vtkPoints* points=vtkPoints::New();
+  points->Allocate(100,20);
+
+  vtkFloatArray* labels=vtkFloatArray::New();
+  labels->SetNumberOfComponents(1);
+  labels->Allocate(100,20);
+
+  int num=this->GetNumberOfGrids();
+  this->ElectrodeGridCollection->InitTraversal();
+  for (int i=0;i<num;i++)
+    {
+      vtkpxElectrodeGridSource* electrodegrid=(vtkpxElectrodeGridSource*)(this->ElectrodeGridCollection->GetNextItemAsObject());
+      if (electrodegrid->GetVisible()==1)
+	{
+	  int dim[2];
+	  electrodegrid->GetDimensions(dim);
+	  int tdim=dim[0]*dim[1];
+	  for (int j=0;j<tdim;j++)
+	    {
+	      vtkpxElectrodeSource* electrode=electrodegrid->GetElectrode(j);
+	      if (electrode->GetElectrodePresent()==1)
+		{
+		  double p[3]; electrode->GetPosition(p);
+		  points->InsertNextPoint(p);
+		  double m=(double)electrode->GetFunctionalInfo(Mode);
+		  labels->InsertNextTuple1(m);
+		}
+	    }
+	}
+    }
+
+  vtkPolyData* output=vtkPolyData::New();
+  output->SetPoints(points);
+  output->GetPointData()->SetScalars(labels);
+
+  points->Delete();
+  labels->Delete();
+  
+  return output;
+}
+
+//----------------------------------------------------------------------------
+vtkImageData* vtkpxElectrodeMultiGridSource::CreateSinglePixelImage(vtkDataArray* ModeArray,vtkImageData* baseimage)
+{
+  if (baseimage==NULL || ModeArray==NULL)
+    {
+      vtkErrorMacro(<<"Bad BaseImage or Mode Array\n");
+      return NULL;
+    }
+
+  int ncomp=ModeArray->GetNumberOfTuples();
+
+  vtkImageData* output=vtkImageData::New();
+  output->CopyStructure(baseimage);
+  output->SetScalarTypeToUnsignedChar();
+  output->SetNumberOfScalarComponents(ncomp);
+  output->AllocateScalars();
+  vtkDataArray* outarr=output->GetPointData()->GetScalars();
+
+
+  double sp[3],ori[3];
+  output->GetSpacing(sp);
+  output->GetOrigin(ori);
+
+  int dim[3]; output->GetDimensions(dim);
+
+  for (int comp=0;comp<ncomp;comp++)
+    {
+      outarr->FillComponent(comp,0.0);
+      int Mode=(int)ModeArray->GetComponent(comp,0);
+      fprintf(stderr,"Component=%d Mode=%d\n",comp,Mode);
+      vtkPolyData* poly=this->ExportToPolyDataAsPoints(Mode,1.0);
+      vtkDataArray* inarr=poly->GetPointData()->GetScalars();
+
+      vtkPoints* pts=poly->GetPoints();
+      int np=pts->GetNumberOfPoints();
+      for (int i=0;i<np;i++)
+	{
+	  double x[3]; pts->GetPoint(i,x);
+	  int   px[3],goodpoint=1;
+	  for (int ia=0;ia<=2;ia++)
+	    {
+	      px[ia]=int( (x[ia]-ori[ia])/sp[ia]+0.5);
+	      if (px[ia]<0 || px[ia]>=dim[ia])
+		goodpoint=0;
+	    }
+	  if (goodpoint == 1 && inarr->GetComponent(i,0)>0 )
+	    output->SetScalarComponentFromDouble(px[0],px[1],px[2],comp,100);
+	}
+      poly->Delete();
+    }
+  return output;
+}
+
+//----------------------------------------------------------------------------
+int vtkpxElectrodeMultiGridSource::PickFunction(vtkImageData* img)
+{
+  double origin[3],spacing[3];
+  img->GetOrigin(origin);
+  img->GetSpacing(spacing);
+  int imgdim[3];
+  img->GetDimensions(imgdim);
+
+  int nc=img->GetNumberOfScalarComponents();
+
+  fprintf(stderr,"Image Dimensions %d %d %d fr=%d\n",imgdim[0],imgdim[1],imgdim[2],nc);
+
+  int d=this->ElectrodeGridCollection->GetNumberOfItems();
+  for (int k=0;k<d;k++)
+      {
+	vtkpxElectrodeGridSource* electrodegrid=this->GetElectrodeGrid(k);
+	int dim[2]; 	electrodegrid->GetDimensions(dim);
+	//fprintf(stderr,"Reading grid %d (%d x %d ) name=%s\n",k,dim[0],dim[1],electrodegrid->GetGridName());
+	for (int j=0;j<dim[1];j++)
+	  for (int i=0;i<dim[0];i++)
+	  {
+	    vtkpxElectrodeSource* electrode=electrodegrid->GetElectrode(i,j);
+	    if (electrode->GetElectrodePresent()==1)
+	      {
+		//int realindex=electrodegrid->GetElectrodeRealIndex(i,j);
+		double p[3]; 
+		electrode->GetPosition(p);
+		int c[3];
+		int allok=1;
+		for (int ia=0;ia<=2;ia++)
+		  {
+		    c[ia]=int((p[ia]-origin[ia])/spacing[ia]);
+		    if (c[ia]<0)
+		      allok=0;
+		    if (c[ia]>=imgdim[ia])
+		      allok=0;
+		  }
+		
+		//float val=0.0;
+
+
+		if (allok)
+		  {
+		    vtkFloatArray* values=electrode->GetValues();
+		    values->SetNumberOfComponents(1);
+		    values->SetNumberOfTuples(nc);
+		    for (int ia=0;ia<nc;ia++)
+		      values->SetComponent(ia,0,img->GetScalarComponentAsDouble(c[0],c[1],c[2],ia));
+		  }
+	      }
+	  }
+	electrodegrid->Modified();
+      }
+  this->Modified();
+  return 0;
+}
+
+
+int vtkpxElectrodeMultiGridSource::ExportValues(const char* fname,const char* description,const char* column,const char* columnnames)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+    return 0;
+
+
+
+  fprintf(fout,"#%s\n",description);
+  fprintf(fout,"#Electrode \t positionx \t positiony \t positionz \t %s \n",columnnames);
+  int d=this->ElectrodeGridCollection->GetNumberOfItems();
+  for (int k=0;k<d;k++)
+    {
+      vtkpxElectrodeGridSource* electrodegrid=this->GetElectrodeGrid(k);
+      int dim[2]; electrodegrid->GetDimensions(dim);
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {
+	    vtkpxElectrodeSource* electrode=electrodegrid->GetElectrode(i,j);
+
+	    if (electrode->GetElectrodePresent()==1)
+	      {
+		double pos[3]; electrode->GetPosition(pos);
+		int realindex=electrodegrid->GetElectrodeRealIndex(i,j);
+		std::stringstream s2;
+		s2 << electrodegrid->GetGridName();
+		s2 << realindex;
+		s2 << "\t" << pos[0] << "\t" << pos[1] << "\t" << pos[2];
+		std::string s= electrodegrid->GetGridName();	s+= "\t";
+		s+=column; s+= "\t";
+		s+=s2.str();
+		//		fprintf(fout,"%s \t %s \t %s",electrodegrid->GetGridName(),line,column);
+		fprintf(fout,"%s",s.c_str());
+		vtkFloatArray* values=electrode->GetValues();
+		for (int ia=0;ia<values->GetNumberOfTuples();ia++)
+		  fprintf(fout,"\t %.3f",values->GetComponent(ia,0));
+		fprintf(fout,"\n");
+	      }
+	  }
+    }
+  fclose(fout);
+  return 1;
+}
+
+
+int vtkpxElectrodeMultiGridSource::SetElectrodeColorsFromFunction(vtkLookupTable* cmap)
+{
+  if (cmap==NULL)
+    return 0;
+
+  int d=this->ElectrodeGridCollection->GetNumberOfItems();
+  for (int k=0;k<d;k++)
+    {
+      vtkpxElectrodeGridSource* electrodegrid=this->GetElectrodeGrid(k);
+      electrodegrid->SetColorMode(2);
+      int dim[2]; 	electrodegrid->GetDimensions(dim);
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {
+	    vtkpxElectrodeSource* electrode=electrodegrid->GetElectrode(i,j);
+	    if (electrode->GetElectrodePresent()==1)
+	      {
+		double v=electrode->GetValues()->GetComponent(0,0);
+		double c[3];
+		cmap->GetColor(v,c);
+		float c1[3]= { c[0],c[1],c[2]};
+		electrode->SetColor(c1);
+	      }
+	  }
+      electrodegrid->Modified();
+    }
+  return 1;
+
+
+}
+//----------------------------------------------------------------------------
+void vtkpxElectrodeMultiGridSource::SetCurrentValueIndex(int a)
+{
+  int d=this->ElectrodeGridCollection->GetNumberOfItems();
+  for (int k=0;k<d;k++)
+    {
+      vtkpxElectrodeGridSource* electrodegrid=this->GetElectrodeGrid(k);
+      electrodegrid->SetCurrentValueIndex(a);
+    }
+  this->Modified();
+}
+
+int  vtkpxElectrodeMultiGridSource::GetCurrentValueIndex()
+{
+  vtkpxElectrodeGridSource* electrodegrid=this->GetElectrodeGrid(0);
+  if (electrodegrid==NULL)
+    return -1;
+  
+  return electrodegrid->GetCurrentValueIndex();
+}
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxElectrodeMultiGridSource.h b/bioimagesuite30_src/Graphics/vtkpxElectrodeMultiGridSource.h
new file mode 100644
index 0000000..81069c7
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxElectrodeMultiGridSource.h
@@ -0,0 +1,203 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxElectrodeMultiGridSource.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxElectrodeMultiGridSource - stores and manipulates a set of electrodes arranged as a grid
+// .SECTION Description
+// This class stores all the necesary information for a collection
+// of electrode grids as implanted in a patient e.g.
+// number of grids
+// patient name
+// patient id
+// and finally an array of the actual electrodegrods
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkPoints vtkPolyData vtkPolyDataSource vtkpxElectrodeGridSource vtkpxElectrodeSource
+
+
+
+#ifndef __vtkpxElectrodeMultiGridSource_h
+#define __vtkpxElectrodeMultiGridSource_h
+
+class vtkPoints;
+class vtkPolyData;
+class vtkImageData;
+class vtkPoints;
+class vtkPolyData;
+class vtkCollection;
+class vtkAbstractTransform;
+class vtkLookupTable;
+#include "vtkpxElectrodeGridSource.h"
+#include "vtkPolyDataSource.h"
+
+
+
+class vtkpxElectrodeMultiGridSource : public vtkPolyDataSource 
+{
+public:
+  static vtkpxElectrodeMultiGridSource *New();
+  vtkTypeMacro(vtkpxElectrodeMultiGridSource,vtkPolyDataSource);
+
+public:
+  
+  // Description:
+  virtual int GetNumberOfGrids();
+
+  // Description:
+  // Specify Description
+  vtkSetStringMacro(Description);
+  vtkGetStringMacro(Description);
+
+  // Description:
+  // Specify additional comment
+  vtkSetStringMacro(Comment);
+  vtkGetStringMacro(Comment);
+
+    // Description:
+  // Load/Save Electrode in file
+  virtual int Load(const char* fname);
+  virtual int Save(const char* fname);
+  virtual int ExportValues(const char* fname,const char* description,const char* column,const char* columnnames);
+
+  //BTX
+  // Description:
+  // Load/Save Electrode from already open file
+  virtual int Load(gzFile fin);
+  virtual int Save(FILE* fout);
+  //ETX
+
+
+  // Description:
+  // Copy From Old Grid 
+  virtual void Copy(vtkpxElectrodeMultiGridSource* other);
+  virtual void CopyAttributes(vtkpxElectrodeMultiGridSource* other);
+
+  // Description:
+  // Get Individual Electrode
+  virtual vtkpxElectrodeGridSource* GetElectrodeGrid(int i);
+
+  // Description:
+  // Initialze Grid
+  virtual void InitializeMultiGrid(int numgrids);
+
+  // Description:
+  // Insert New Grid
+  virtual void InsertNewGrid();
+
+  // Description:
+  // Delete Grid
+  virtual void DeleteGrid(int index);
+
+  // Description:
+  // Export to Single Points Surface for Reconstruction Purposes
+  // Mode = Functional Mode (see vtkpxElectrode::GetFunctionalInfo(Mode))
+  virtual vtkPolyData* ExportToPolyDataAsPoints(int Mode);
+  virtual vtkPolyData* ExportToPolyDataAsPoints(int Mode,float radius);
+
+  // Description:
+  // Create Image where number is 1 for electrode present 0 absent
+  virtual vtkImageData* CreateSinglePixelImage(vtkDataArray* ModeArray,vtkImageData* baseimage);
+
+  // Description:
+  // Get Labels Surface
+  vtkGetObjectMacro(LabelSurface, vtkPolyData);
+
+  // Description:
+  // Show All Labels
+  virtual void ShowLabelsGap(int all=0);
+
+
+  // Description:
+  // Apply Transformation
+  virtual int ApplyTransformation(vtkAbstractTransform* tr,int forward=1);
+
+  // Description:
+  // Apply Transformation
+  virtual int PickFunction(vtkImageData* img);
+  virtual int SetElectrodeColorsFromFunction(vtkLookupTable* cmap);
+
+  // Description:
+  // Set Number Of Values for all electrodes
+  virtual void SetNumberOfValues(int vl);
+  virtual int  GetNumberOfValues();
+
+  // Description:
+  // Set/Get Current Value Index
+  virtual void SetCurrentValueIndex(int a);
+  virtual int  GetCurrentValueIndex();
+
+  
+protected:
+  vtkpxElectrodeMultiGridSource();
+  virtual ~vtkpxElectrodeMultiGridSource();
+
+  vtkpxElectrodeMultiGridSource(const vtkpxElectrodeMultiGridSource&) {};
+  void operator=(const vtkpxElectrodeMultiGridSource&) {};
+
+  virtual void Execute();  
+
+
+  //BTX
+  char *Description;
+  char *Comment;
+  vtkCollection*  ElectrodeGridCollection;
+  vtkPolyData* LabelSurface;
+  //ETX
+
+
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxElectrodeSource.cpp b/bioimagesuite30_src/Graphics/vtkpxElectrodeSource.cpp
new file mode 100644
index 0000000..7cbcbe3
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxElectrodeSource.cpp
@@ -0,0 +1,657 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+ see vtkpxElectrodeSource.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+#include "vtkAppendPolyData.h"
+#include "vtkDiskSource.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkOutlineFilter.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkpxCrossHairSource.h"
+#include "vtkTransform.h"
+#include "vtkTransformPolyDataFilter.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkpxElectrodeSource.h"
+#include "vtkGridTransform.h"
+#include "vtkTransformToGrid.h"
+#include "vtkFloatArray.h"
+#include "pxutil.h"
+//------------------------------------------------------------------------------
+vtkpxElectrodeSource* vtkpxElectrodeSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxElectrodeSource");
+  if(ret)
+    {
+      return (vtkpxElectrodeSource*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxElectrodeSource;
+}
+
+// Construct object with no children.
+vtkpxElectrodeSource::vtkpxElectrodeSource()
+{
+  this->ColorName=new char[40];
+  this->Values=vtkFloatArray::New();
+  this->Reset();
+  this->CurrentValueIndex=-1;
+}
+/* -------------------------------------------------------------------------*/
+vtkpxElectrodeSource::~vtkpxElectrodeSource()
+{
+  delete [] this->ColorName;
+  this->Values->Delete();
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxElectrodeSource::Reset()
+{
+  this->MotorFunction=0;
+  this->SensoryFunction=0;
+  this->VisualFunction=0;
+  this->LanguageFunction=0;
+  this->AuditoryFunction=0;
+  this->User1Function=0;
+  this->User2Function=0;
+
+  this->SeizureOnset=0;
+  this->SpikesPresent=0;
+  
+  this->Position[0]=0;this->Position[1]=0;this->Position[2]=0;
+  this->SetPreviousPosition(this->Position);
+  this->Normal[0]=1.0;this->Normal[1]=0.0;  this->Normal[2]=0.0;
+						
+  this->ElectrodeType=0;
+  this->ElectrodePresent=1;
+
+  this->Radius=5.0;
+  this->Thickness=0.05;
+  this->Color[0]=1.0; 
+  this->Color[1]=1.0; 
+  this->Color[2]=1.0;
+  this->StoreColorInColorName();
+  this->Values->SetNumberOfTuples(1);
+  this->Values->SetComponent(0,0,0.0);
+  this->ColorMode=1;
+}
+
+/* -------------------------------------------------------------------------*/
+int  vtkpxElectrodeSource::GetNumberOfValues()
+{
+  return this->Values->GetNumberOfTuples();
+}
+    
+void vtkpxElectrodeSource::SetNumberOfValues(int vl)
+{
+  vl=Irange(vl,1,1000);
+  int nt=this->GetNumberOfValues();
+  if (nt!=vl)
+    {
+      this->Values->SetNumberOfComponents(1);
+      this->Values->SetNumberOfTuples(vl);
+      this->Values->FillComponent(0,0.0);
+    }
+} 
+/* -------------------------------------------------------------------------*/
+void vtkpxElectrodeSource::Copy(vtkpxElectrodeSource* other)
+{
+  this->SetPosition(other->GetPosition());
+  this->SetPreviousPosition(other->GetPreviousPosition());
+  this->SetNormal(other->GetNormal());
+  this->CopyAttributes(other);
+}
+
+void vtkpxElectrodeSource::CopyAttributes(vtkpxElectrodeSource* other)
+{
+  this->MotorFunction=other->GetMotorFunction();
+  this->SensoryFunction=other->GetSensoryFunction();
+  this->VisualFunction=other->GetVisualFunction();
+  this->LanguageFunction=other->GetLanguageFunction();
+  this->AuditoryFunction=other->GetAuditoryFunction();
+  this->User1Function=other->GetUser1Function();
+  this->User2Function=other->GetUser2Function();
+
+  this->SeizureOnset=other->GetSeizureOnset();
+  this->SpikesPresent=other->GetSpikesPresent();
+  
+						
+  this->ElectrodeType=other->GetElectrodeType();
+  this->ElectrodePresent=other->GetElectrodePresent();
+
+  this->Radius=other->GetRadius();
+  this->Thickness=other->GetThickness();
+  this->StoreColorInColorName();
+
+  this->Values->DeepCopy(other->GetValues());
+  this->CurrentValueIndex=other->GetCurrentValueIndex();
+
+  this->Modified();
+}
+/* -------------------------------------------------------------------------*/
+int vtkpxElectrodeSource::ComputeColor()
+{
+  int score=0;
+
+  for (int i=0;i<=2;i++)
+    this->InternalColor[i]=this->Color[i];
+
+  if (this->ElectrodePresent==0)
+    {
+      this->InternalColor[0]=0;      this->InternalColor[1]=0;      this->InternalColor[2]=0;
+      this->Color[0]=0;      this->Color[1]=0;      this->Color[2]=0;
+      return 0;
+    }
+  
+  if (this->LanguageFunction==1)
+    score=3;
+  else if (this->MotorFunction==1)
+    score=1;
+  else if (this->VisualFunction==1)
+    score=8;
+  else if (this->SensoryFunction==1)
+    score=5;
+  else if (this->AuditoryFunction==1)
+    score=6;
+  else if (this->User1Function==1)
+    score=2;
+  else if (this->User2Function==1)
+    score=4;
+
+
+  
+
+  switch (score)
+    {
+    case 1: // Red
+      this->InternalColor[0]=1.0; this->InternalColor[1]=0.2; this->InternalColor[2]=0.1;
+      break;
+    case 2: // Orange
+      this->InternalColor[0]=1.0; this->InternalColor[1]=0.62; this->InternalColor[2]=0.0;
+      break;
+    case 3: // Yellow
+      this->InternalColor[0]=1.0; this->InternalColor[1]=1.0; this->InternalColor[2]=0.1;
+      break;
+    case 4: // Green
+      this->InternalColor[0]=0.0; this->InternalColor[1]=1.0; this->InternalColor[2]=0.0;
+      break;
+    case 5: // Blue
+      this->InternalColor[0]=0.13; this->InternalColor[1]=0.5; this->InternalColor[2]=0.78;
+      break;
+    case 6: // Indigo
+      this->InternalColor[0]=0.6; this->InternalColor[1]=0.6; this->InternalColor[2]=0.6;
+      break;
+    case 7: // Cyan
+      this->InternalColor[0]=0.5; this->InternalColor[1]=0.9; this->InternalColor[2]=0.75;
+      break;
+    case 8: // Brown
+      this->InternalColor[0]=0.65; this->InternalColor[1]=0.56; this->InternalColor[2]=0.16;
+      break;
+    }
+
+
+  if (this->ColorMode==0)
+    return -score;
+
+  for (int i=0;i<=2;i++)
+    this->Color[i]=this->InternalColor[i];
+
+  return score;
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxElectrodeSource::Execute()
+{
+  vtkPolyData* inner_shape=this->GetOutput();
+
+  int showcube=0;
+
+  if (this->CurrentValueIndex>=0 && this->CurrentValueIndex<this->Values->GetNumberOfTuples())
+    {
+      if (this->Values->GetComponent(this->CurrentValueIndex,0)>0.0)
+	showcube=2;
+    }
+  else if (this->SpikesPresent==1 || this->SeizureOnset==1)
+    showcube=1;
+
+  if (showcube>0)
+    {
+      inner_shape=vtkPolyData::New();
+    } 
+
+  int colormode=this->ComputeColor();
+  double scale=1.0;
+  if (colormode!=0)
+    scale=1.2;
+  else
+    scale=0.8;
+
+  if (this->ElectrodeType==0)
+    {
+      vtkpxCrossHairSource* sphere=vtkpxCrossHairSource::New();
+      sphere->SetPosition(this->Position);
+      sphere->SetLength(this->Radius*scale);
+      sphere->SetThickness(0.5);
+      sphere->SetShowSphere(1);
+      sphere->Update();
+      inner_shape->ShallowCopy(sphere->GetOutput());
+      sphere->Delete();
+    }
+  else
+    {
+      vtkDiskSource* disk=vtkDiskSource::New();
+      disk->SetInnerRadius(this->Radius*0.1);
+      disk->SetOuterRadius(this->Radius*scale);
+      disk->SetRadialResolution(2);
+      disk->SetCircumferentialResolution(8);
+
+      vtkTransform* tr=vtkTransform::New();
+      tr->PostMultiply();
+      // need to add orientation stuff ... do this later 
+      tr->Translate(this->Position);
+
+      vtkTransformPolyDataFilter* trF=vtkTransformPolyDataFilter::New();
+      trF->SetInput(disk->GetOutput());
+      trF->SetTransform(tr);
+      trF->Update();
+
+      inner_shape->ShallowCopy(trF->GetOutput());
+      disk->Delete();
+      tr->Delete();
+      trF->Delete();
+    }
+
+  // Color inner with functional info
+
+
+
+  unsigned char d[3],d2[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      d[ia]=(unsigned char)(this->Color[ia]*255.0);
+      d2[ia]=(unsigned char)(this->InternalColor[ia]*255.0);
+    }
+
+
+  vtkUnsignedCharArray* color_array=vtkUnsignedCharArray::New();
+  color_array->SetNumberOfComponents(3);
+  color_array->SetNumberOfTuples(inner_shape->GetNumberOfPoints());
+
+  for (int ka=0;ka<color_array->GetNumberOfTuples();ka+=2)
+    {
+      color_array->SetTuple3(ka,d[0],d[1],d[2]);
+      color_array->SetTuple3(ka+1,d2[0],d2[1],d2[2]);
+    }
+  
+  inner_shape->GetPointData()->SetScalars(color_array);
+  color_array->Delete();
+  
+
+  if (showcube==0)
+    return;
+
+  
+
+  // other wise put color_box around it
+  vtkOutlineFilter* filt=vtkOutlineFilter::New();
+  filt->SetInput(inner_shape);
+  filt->Update();
+
+  vtkPolyData* outer_shape= vtkPolyData::New();
+  outer_shape->CopyStructure(filt->GetOutput());
+  filt->Delete();
+
+  d[0]=255;    d[1]=0;    d[2]=0;
+  
+  if (this->SeizureOnset==0)
+    d[1]=255;
+  
+  if (this->CurrentValueIndex>=0 && this->CurrentValueIndex<this->Values->GetNumberOfTuples())
+    {
+      if (this->Values->GetComponent(this->CurrentValueIndex,0)>0.0)
+	d[2]=255;
+    }
+
+  vtkUnsignedCharArray* color_array2=vtkUnsignedCharArray::New();
+  color_array2->SetNumberOfComponents(3);
+  color_array2->SetNumberOfTuples(outer_shape->GetNumberOfPoints());
+
+
+  //  fprintf(stderr,"showcube=%d SeizureOnset=%d SpikesPresent=%d\n",showcube,this->SeizureOnset,this->SpikesPresent);
+
+  for (int k=0;k<color_array2->GetNumberOfTuples();k++)
+    {
+      color_array2->SetTuple3(k,d[0],d[1],d[2]);
+      if ( showcube==1 && this->SeizureOnset==1 && this->SpikesPresent==1)
+	{
+	  d[1]=255-d[1];
+	}
+    }
+	
+  
+  outer_shape->GetPointData()->SetScalars(color_array2);
+  color_array2->Delete();
+
+  vtkAppendPolyData* append=vtkAppendPolyData::New();
+  append->AddInput(inner_shape);
+  append->AddInput(outer_shape);
+
+  append->Update();
+
+  this->GetOutput()->ShallowCopy(append->GetOutput());
+  append->Delete();
+  inner_shape->Delete();
+  outer_shape->Delete();
+
+}
+//----------------------------------------------------------------------------
+int vtkpxElectrodeSource::Load(const char* fname)
+{  
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  int ok=Load(fin);
+  gzclose(fin);
+
+  return ok;
+}
+
+int vtkpxElectrodeSource::Load(gzFile fin)
+{
+  char line[255];
+  gzgets(fin,line,100);
+  int mode=0;
+  if (gzfindstringinstring(line,"#vtkpxElectrodeSource File")==0)
+    {
+        if (gzfindstringinstring(line,"#vtkpxElectrodeSource2 File")==0)
+	  return 0;
+	else
+	  mode=1;
+    }
+  else
+    {
+      mode=0;
+    }
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%lf %lf %lf",&this->Position[0],&this->Position[1],&this->Position[2]);
+  this->SetPreviousPosition(this->Position);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%lf %lf %lf",&this->Normal[0],&this->Normal[1],&this->Normal[2]);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&this->MotorFunction);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&this->VisualFunction);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&this->SensoryFunction);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&this->LanguageFunction);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&this->AuditoryFunction);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&this->User1Function);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&this->User2Function);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&this->SeizureOnset);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&this->SpikesPresent);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&this->ElectrodePresent);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&this->ElectrodeType);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%f",&this->Radius);
+  gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%f",&this->Thickness);
+  if (mode==1)
+    {
+      int tmp;
+      gzgets(fin,line,100); gzgets(fin,line,100); sscanf(line,"%d",&tmp);
+      this->Values->SetNumberOfComponents(1);
+      this->Values->SetNumberOfTuples(tmp);
+      float dtmp;
+      for (int j=0;j<this->Values->GetNumberOfTuples();j++)
+	{
+	  gzgets(fin,line,100); sscanf(line,"%f",&dtmp);
+	  this->Values->SetComponent(j,0,dtmp);
+	}
+    }
+
+  //
+  this->Color[0]=1.0;   this->Color[1]=1.0;   this->Color[2]=1.0;
+  this->CurrentValueIndex=-1;
+  return 1;
+}
+//----------------------------------------------------------------------------
+int vtkpxElectrodeSource::Save(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+    return 0;
+  
+  int ok=Save(fout);
+  fclose(fout);
+  return ok;
+}
+
+int vtkpxElectrodeSource::Save(FILE* fout)
+{
+  fprintf(fout,"#vtkpxElectrodeSource2 File\n");
+  fprintf(fout,"#Position\n %.4f %.4f %.4f\n",this->Position[0],this->Position[1],this->Position[2]);
+  fprintf(fout,"#Normal\n %.4f %.4f %.4f\n",this->Normal[0],this->Normal[1],this->Normal[2]);
+  fprintf(fout,"#Motor Function\n%d\n",this->MotorFunction);
+  fprintf(fout,"#Sensory Function\n%d\n",this->SensoryFunction);
+  fprintf(fout,"#Visual Function\n%d\n",this->VisualFunction);
+  fprintf(fout,"#Language Function\n%d\n",this->LanguageFunction);
+  fprintf(fout,"#Auditory Function\n%d\n",this->AuditoryFunction);
+  fprintf(fout,"#User1 Function\n%d\n",this->User1Function);
+  fprintf(fout,"#User2 Function\n%d\n",this->User2Function);
+  fprintf(fout,"#Seizure Onset\n%d\n",this->SeizureOnset);
+  fprintf(fout,"#Spikes Present\n%d\n",this->SpikesPresent);
+  fprintf(fout,"#Electrode Present\n%d\n",this->ElectrodePresent);
+  fprintf(fout,"#Electrode Type\n%d\n",this->ElectrodeType);
+  fprintf(fout,"#Radius \n%f\n",this->Radius);
+  fprintf(fout,"#Thickeness\n%f\n",this->Thickness);
+  fprintf(fout,"#Values\n%d\n",this->Values->GetNumberOfTuples());
+  for (int j=0;j<this->Values->GetNumberOfTuples();j++)
+    fprintf(fout,"%f\n",this->Values->GetComponent(j,0));
+  return 1;
+}
+
+int vtkpxElectrodeSource::ApplyTransformation(vtkAbstractTransform* tr,int forward)
+{
+  if (tr==NULL)
+    return 0;
+  
+  double p[3],pq[3];
+  if (forward)
+    {
+      tr->TransformPoint(this->Position,p);
+    }
+  else
+    {
+      vtkTransformToGrid* tgrid=vtkTransformToGrid::New();
+      tgrid->SetGridExtent(0,2,0,2,0,2);
+      tgrid->SetGridOrigin(this->Position[0]-1.0,this->Position[1]-1.0,this->Position[2]-1.0);
+      tgrid->SetGridSpacing(1,1,1);
+      tgrid->SetInput(tr);
+      tgrid->Update();
+
+      vtkGridTransform* trg=vtkGridTransform::New();
+      trg->SetDisplacementGrid(tgrid->GetOutput());
+      trg->SetInterpolationModeToLinear();
+      trg->Inverse();
+      
+      trg->TransformPoint(this->Position,p);
+      tr->TransformPoint(p,pq);
+
+      trg->Delete();
+      tgrid->Delete();
+    }
+
+  /*  fprintf(stderr,"forward=%d Pos=(%.1f %.1f %.1f) --> (%.1f %.1f %.1f) --> (%.1f %.1f %.1f) \n",
+	  forward,
+	  this->Position[0],
+	  this->Position[1],
+	  this->Position[2],
+	  p[0],p[1],p[2],
+	  pq[0],pq[1],pq[2]);*/
+  this->SetPosition(p);
+  this->Modified();
+  return 1;
+}
+//----------------------------------------------------------------------------
+void vtkpxElectrodeSource::StoreColorInColorName()
+{
+  this->ComputeColor();
+  
+  int c[3];
+  c[0]=int(Frange(this->InternalColor[0],0,1.0)*255.0);
+  c[1]=int(Frange(this->InternalColor[1],0,1.0)*255.0);
+  c[2]=int(Frange(this->InternalColor[2],0,1.0)*255.0);
+
+  strcpy(this->ColorName,"#");
+  for (int k=0;k<=2;k++)
+    {
+      for (int byte=0;byte<=1;byte++)
+	{
+	  int val=0;
+	  switch(byte)
+	    {
+	    case 0:
+	      val=c[k]/16;
+	      break;
+	    case 1:
+	      val=c[k]-16*int(c[k]/16);
+	      break;
+	    }
+	  
+	  if (val<10)
+	    {
+	      sprintf(this->ColorName,"%s%1d",this->ColorName,val);
+	    }
+	  else
+	    {
+	      switch (val)
+		{
+		case 10:
+		  strcat(this->ColorName,"A");
+		  break;
+		case 11:
+		  strcat(this->ColorName,"B");
+		  break;
+		case 12:
+		  strcat(this->ColorName,"C");
+		  break;
+		case 13:
+		  strcat(this->ColorName,"D");
+		  break;
+		case 14:
+		  strcat(this->ColorName,"E");
+		  break;
+		case 15:
+		  strcat(this->ColorName,"F");
+		  break;
+		}
+	    }
+	}
+    }
+
+}
+//----------------------------------------------------------------------------
+int vtkpxElectrodeSource::GetFunctionalInfo(int Mode)
+{
+  // Description:
+  // Get Functional Info
+  // Mode Settings
+  /*
+    Location Alone = 0;
+    Epilepsy Map   = 1  (4 gray levels, 0 no electrode, 1 electrode, 2=spikes present 3=seizure onset)
+    Any Functional = 2;
+    Motor Function = 3
+    Sensory Function = 4
+    Visual Function = 5
+    Language Function = 6;
+    Auditory Function = 7;
+    User 1 Function = 8;
+    User 2 Function = 9;
+
+    Values = 20 ---> 20 + numberoftuples -1
+  */
+
+  if (Mode>=20)
+    {
+      int nt=Irange(Mode-20,0,this->GetNumberOfValues()-1);
+      return (int)this->Values->GetComponent(nt,0);
+    }
+
+  switch (Mode)
+    {
+    case 1:
+      if (this->SeizureOnset)
+	return 2;
+      if (this->SpikesPresent)
+	return 1;
+      else
+	return 0;
+      break;
+      
+    case 2:
+      if (this->MotorFunction ||   this->SensoryFunction || this->VisualFunction ||
+	  this->LanguageFunction || this->AuditoryFunction || this->User1Function || this->User2Function )
+	return 1;
+      else
+	return 0;
+      break;
+
+    case 3:
+      return this->MotorFunction;
+      break;
+
+    case 4:
+      return this->SensoryFunction;
+      break;
+    case 5:
+      return this->VisualFunction;
+      break;
+    case 6:
+      return this->LanguageFunction;
+      break;
+    case 7:
+      return this->AuditoryFunction;
+      break;
+    case 8:
+      return this->User1Function;
+      break;
+    case 9:
+      return this->User2Function;
+      break;
+    case 0:
+      return 1;
+      break;
+    }      
+     
+  return 0;
+
+}
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxElectrodeSource.h b/bioimagesuite30_src/Graphics/vtkpxElectrodeSource.h
new file mode 100644
index 0000000..3e0c41b
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxElectrodeSource.h
@@ -0,0 +1,270 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxElectrodeSource.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxElectrodeSource - stores the information for a single electrode
+// .SECTION Description
+// This class stores all the necessary information for a single electrode
+// including position and normal (for a disc)
+// type (sphere/disc) dimensions r,t
+// functional attributes motor,sensory,visual,auditory,language,user1,user2
+// electrical attributes seizure onset, spikes
+// and finally whether it actually was implanted or not 
+// <br> <br> <EM>Copyright (c) 1995-2003 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkPoints vtkPolyData vtkPolyDataSource 
+
+
+#ifndef __vtkpxElectrodeSource_h
+#define __vtkpxElectrodeSource_h
+
+class vtkPoints;
+class vtkPolyData;
+#include "vtkAbstractTransform.h"
+#include "vtkPolyDataSource.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "pxutil.h"
+
+class vtkpxElectrodeSource : public vtkPolyDataSource 
+{
+public:
+  static vtkpxElectrodeSource *New();
+  vtkTypeMacro(vtkpxElectrodeSource,vtkPolyDataSource);
+
+public:
+
+  // Description:
+  // Get Functional Info
+  // Mode Settings
+  /*
+    Location Alone = 0;
+    Epilepsy Map   = 1  (1=spikes present 2=seizure onset)
+    Any Functional = 2;
+    Motor Function = 3
+    Sensory Function = 4
+    Visual Function = 5
+    Language Function = 6;
+    Auditory Function = 7;
+    User 1 Function = 8;
+    User 2 Function = 9;
+  */
+  virtual int GetFunctionalInfo(int Mode);
+
+  // Description:
+  // Functional Attributes 
+  vtkSetClampMacro(ColorMode,int,0,1);
+  vtkGetMacro(ColorMode,int);
+  virtual void SetColorModeToNormal() { this->SetColorMode(1); }
+  virtual void SetColorModeToManual() { this->SetColorMode(0); }
+
+  // Description:
+  // Functional Attributes 
+  vtkSetClampMacro(MotorFunction,int,0,1);
+  vtkGetMacro(MotorFunction,int);
+  vtkBooleanMacro(MotorFunction,int);
+
+  vtkSetClampMacro(SensoryFunction,int,0,1);
+  vtkGetMacro(SensoryFunction,int);
+  vtkBooleanMacro(SensoryFunction,int);
+
+  vtkSetClampMacro(VisualFunction,int,0,1);
+  vtkGetMacro(VisualFunction,int);
+  vtkBooleanMacro(VisualFunction,int);
+
+  vtkSetClampMacro(AuditoryFunction,int,0,1);
+  vtkGetMacro(AuditoryFunction,int);
+  vtkBooleanMacro(AuditoryFunction,int);
+
+  vtkSetClampMacro(LanguageFunction,int,0,1);
+  vtkGetMacro(LanguageFunction,int);
+  vtkBooleanMacro(LanguageFunction,int);
+
+  vtkSetClampMacro(User1Function,int,0,1);
+  vtkGetMacro(User1Function,int);
+  vtkBooleanMacro(User1Function,int);
+
+  vtkSetClampMacro(User2Function,int,0,1);
+  vtkGetMacro(User2Function,int);
+  vtkBooleanMacro(User2Function,int);
+
+  // Description:
+  // Epilepsy Related Flags
+  vtkSetClampMacro(SeizureOnset,int,0,1);
+  vtkGetMacro(SeizureOnset,int);
+  vtkBooleanMacro(SeizureOnset,int);
+
+  vtkSetClampMacro(SpikesPresent,int,0,1);
+  vtkGetMacro(SpikesPresent,int);
+  vtkBooleanMacro(SpikesPresent,int);
+
+  // Description:
+  // If Current Value !=-1 draw box if current value > 0
+  vtkSetClampMacro(CurrentValueIndex,int,-1,20);
+  vtkGetMacro(CurrentValueIndex,int);
+
+  // Description:
+  // Value -- Continuos Sampling
+  vtkGetObjectMacro(Values,vtkFloatArray);
+  
+  // Description:
+  // Number of Tuples in Values (vtkFloatArray Components=1)
+  virtual void SetNumberOfValues(int vl);
+  virtual int  GetNumberOfValues();
+
+
+  // Description:
+  // Location and Normal
+  vtkGetVectorMacro(Position,double,3);
+  vtkSetVectorMacro(Position,double,3);
+
+  // Description:
+  // Previous Position
+  vtkGetVectorMacro(PreviousPosition,double,3);
+  vtkSetVectorMacro(PreviousPosition,double,3);
+  vtkGetVectorMacro(Normal,double,3);
+  vtkSetVectorMacro(Normal,double,3);
+
+  // Description:
+  // Marker Type 0=Sphere, 1= Disc
+  vtkGetMacro(ElectrodeType,int);
+  vtkSetClampMacro(ElectrodeType,int,0,1);
+  void SetElectrodeTypeToSphere() { this->SetElectrodeType(0);}
+  void SetElectrodeTypeToDisc()   { this->SetElectrodeType(1);}
+  
+  // Description:
+  // Set/Get Radius and Thickness (for disc) between 0.5 and 20mm
+  vtkGetMacro(Radius,float);
+  vtkSetClampMacro(Radius,float,0.5,20.0);
+
+  vtkGetMacro(Thickness,float);
+  vtkSetClampMacro(Thickness,float,0.01,2.0);
+
+  // Description:
+  // Is the electrode Present or has it been cut off
+  vtkSetClampMacro(ElectrodePresent,int,0,1);
+  vtkGetMacro(ElectrodePresent,int);
+  vtkBooleanMacro(ElectrodePresent,int);
+
+  // Description:
+  // Get Color Name and Other Color Info
+  vtkGetStringMacro(ColorName);
+  virtual void StoreColorInColorName();
+  virtual int ComputeColor();
+  vtkGetVectorMacro(Color,float,3);
+  vtkSetVectorMacro(Color,float,3);
+
+  // Description:
+  // Load/Save Electrode in file
+  virtual int Load(const char* fname);
+  virtual int Save(const char* fname);
+
+  //BTX
+  // Description:
+  // Load/Save Electrode from already open file
+  virtual int Load(gzFile fin);
+  virtual int Save(FILE* fout);
+  //ETX
+
+  // Description:
+  // Copy Electrode Attributs from another Electrode
+  virtual void Copy(vtkpxElectrodeSource* other);
+  virtual void CopyAttributes(vtkpxElectrodeSource* other);
+
+  // Description:
+  // Reset Default Attributes
+  virtual void Reset();
+
+  // Description:
+  // Apply Transformation
+  virtual int ApplyTransformation(vtkAbstractTransform* tr,int forward=1);
+
+protected:
+  vtkpxElectrodeSource();
+  virtual ~vtkpxElectrodeSource();
+
+  vtkpxElectrodeSource(const vtkpxElectrodeSource&) {};
+  void operator=(const vtkpxElectrodeSource&) {};
+
+  // Description:
+  // Enclose attributs in BTX..ETX block to hide them from the TCL parser
+  //BTX
+  int   MotorFunction,SensoryFunction,VisualFunction,LanguageFunction;
+  int   User1Function,User2Function,AuditoryFunction;
+  int   SeizureOnset,SpikesPresent;
+  double Position[3],Normal[3],PreviousPosition[3];
+  int   ElectrodeType,ElectrodePresent;
+  float Radius,Thickness;
+  char* ColorName;
+  float Color[3];
+  float InternalColor[3];
+  vtkFloatArray* Values;
+  int   ColorMode;
+  int   CurrentValueIndex;
+  //ETX
+
+  // Description:
+  // Determine Color for Surface
+  //BTX
+
+  //ETX
+
+  // Description:
+  // Generate Output Surface
+  virtual void Execute();  
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxEnclosedPipeline.cpp b/bioimagesuite30_src/Graphics/vtkpxEnclosedPipeline.cpp
new file mode 100644
index 0000000..ccbcb72
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxEnclosedPipeline.cpp
@@ -0,0 +1,117 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxEnclosedPipeline.h"
+#include "vtkObjectFactory.h"
+//------------------------------------------------------------------------------
+vtkpxEnclosedPipeline* vtkpxEnclosedPipeline::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxEnclosedPipeline");
+  if(ret)
+    {
+    return (vtkpxEnclosedPipeline*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxEnclosedPipeline;
+}
+
+// Construct object with no children.
+vtkpxEnclosedPipeline::vtkpxEnclosedPipeline()
+{
+}
+
+vtkpxEnclosedPipeline::~vtkpxEnclosedPipeline()
+{
+}
+
+/*
+// Add a part to the list of Parts.
+void vtkpxEnclosedPipeline::AddPart(vtkActor *actor)
+{
+  vtkAssembly::AddPart(actor);
+}
+
+// Remove a part from the list of parts,
+void vtkpxEnclosedPipeline::RemovePart(vtkActor *actor)
+{
+  vtkAssembly::RemovePart(actor);
+}
+
+void vtkpxEnclosedPipeline::InitPartTraversal()
+{
+  vtkAssembly::InitPartTraversal();
+}
+
+// Return the next part in the hierarchy of assembly Parts.  This method 
+// returns a properly transformed and updated actor.
+vtkActor *vtkpxEnclosedPipeline::GetNextPart()
+
+{
+  return vtkAssembly::GetNextPart();
+}
+
+int vtkpxEnclosedPipeline::GetNumberOfParts()
+{
+  return vtkAssembly::GetNumberOfParts();
+}
+
+void vtkpxEnclosedPipeline::SetProperty (vtkProperty *lut)
+{
+  vtkAssembly::SetProperty(lut);
+}
+
+void vtkpxEnclosedPipeline::SetBackfaceProperty (vtkProperty *lut)
+{
+ vtkAssembly::SetBackfaceProperty(lut);
+}
+
+void vtkpxEnclosedPipeline::SetTexture ( vtkTexture *t)
+{
+ vtkAssembly::SetTexture(t);
+}
+
+void vtkpxEnclosedPipeline::SetMapper ( vtkMapper *m)
+{
+  vtkAssembly::SetMapper(m);
+}
+
+void vtkpxEnclosedPipeline::SetProperty (vtkProperty& lut)
+{
+  vtkAssembly::SetProperty(lut);
+}
+
+void vtkpxEnclosedPipeline::SetBackfaceProperty (vtkProperty& lut)
+{
+  vtkAssembly::SetBackfaceProperty(lut);
+}
+*/
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxEnclosedPipeline.h b/bioimagesuite30_src/Graphics/vtkpxEnclosedPipeline.h
new file mode 100644
index 0000000..cd79434
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxEnclosedPipeline.h
@@ -0,0 +1,109 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxEnclosedPipeline.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxBaseCurve - an abstract base class derived from vtkAssembly
+// .SECTION Description
+// This is an abstract base class of vtkAssembly used to parent
+// classes aiming at constructing complex objects consisting of multiple actors
+// Methos SetMapper SetTexture SetProperty etc are made protected
+// so as not to allow external access.
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkpxImageSlice 
+
+#ifndef __vtkpxEnclosedPipeline_h
+#define __vtkpxEnclosedPipeline_h
+
+#include "vtkAssembly.h"
+
+
+class vtkpxEnclosedPipeline : public vtkAssembly
+{
+public:
+  static vtkpxEnclosedPipeline *New();
+  vtkTypeMacro(vtkpxEnclosedPipeline,vtkAssembly);
+
+
+protected:
+
+  //BTX
+  vtkpxEnclosedPipeline();
+  virtual ~vtkpxEnclosedPipeline();
+  vtkpxEnclosedPipeline(const vtkpxEnclosedPipeline&) {};
+  void operator=(const vtkpxEnclosedPipeline&) {};
+
+  // stuff that follows is made protected 
+  // To avoid external wrtite-access to internals of pipeline 
+  //ETX
+
+  // Description:
+  // Made protected to remove external access
+  /*void AddPart(vtkActor *);
+  void RemovePart(vtkActor *);
+  vtkActorCollection *GetParts();
+  void InitPartTraversal();
+  vtkActor *GetNextPart();
+  int GetNumberOfParts();
+  void UpdatePaths();
+  virtual void SetProperty (vtkProperty *lut);
+  virtual void SetBackfaceProperty (vtkProperty *lut);
+  virtual void SetTexture ( vtkTexture *);
+  virtual void SetMapper ( vtkMapper *);
+  virtual void SetProperty (vtkProperty& lut);
+  virtual void SetBackfaceProperty (vtkProperty& lut);*/
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxImageSlice.cpp b/bioimagesuite30_src/Graphics/vtkpxImageSlice.cpp
new file mode 100644
index 0000000..ae033a6
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxImageSlice.cpp
@@ -0,0 +1,761 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageSlice.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/02/03 15:28:43 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxImageSlice.h"
+#include "vtkObjectFactory.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkpxUtil.h"
+#include "vtkImageMapToColors.h"
+#include "vtkpxColorMapUtil.h"
+#include "vtkImageToStructuredPoints.h"
+
+using namespace bioimagesuite_legacy;
+//------------------------------------------------------------------------------
+vtkpxImageSlice* vtkpxImageSlice::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageSlice");
+  if(ret)
+    {
+    return (vtkpxImageSlice*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageSlice;
+}
+//------------------------------------------------------------------------------
+// Construct object with no children.
+vtkpxImageSlice::vtkpxImageSlice()
+{
+  this->ImageSliceHighlight=NULL;
+  this->ImageSliceOutline=NULL;    
+  this->ImageSlice=NULL;         
+  this->ImagePlane=NULL;         
+  this->ImageHighlightPlane=NULL;         
+  this->ImageVOI=NULL;           
+  this->ImageTexture=NULL; 
+  this->CurrentImage=NULL;
+  this->Level=-1;              
+  this->Frame=0;
+  this->NumberOfFrames=1;
+
+  this->Opacity=1.0;            
+  this->Interpolation=1;      
+  this->ColorMap=NULL;           
+  this->OwnsColorMap=1;   
+
+  this->CurrentPlane=2;
+  this->DisplayMode=2;
+  this->ShowHighlight=0;
+
+  this->ColorMap=vtkLookupTable::New();
+  this->ColorMap->SetNumberOfTableValues(256);
+  this->ColorMap->SetTableRange(0,255);
+  this->ColorMode=0;
+
+  this->PolarMode=0;
+  this->PolarMiddle=-1.0;
+  
+  for (int i=0;i<=255;i++)
+    {
+      float v=float(i)/float(255.0);
+      this->ColorMap->SetTableValue(i,v,v,v,1.0);
+    }
+  
+  this->AutoUpdate=1;
+}
+//------------------------------------------------------------------------------
+vtkpxImageSlice::~vtkpxImageSlice()
+{
+  if (this->CurrentImage)
+    this->CurrentImage->Delete();
+
+  if (this->ImagePlane)
+    this->ImagePlane->Delete();
+
+  if (this->ImageHighlightPlane)
+    this->ImageHighlightPlane->Delete();
+  
+  if (this->ImageSliceOutline)
+    this->ImageSliceOutline->Delete();
+  
+  if (this->ImageSlice)
+    this->ImageSlice->Delete();
+  
+  if (this->ImageVOI)
+    ImageVOI->Delete();
+  
+  if (this->ImageTexture)
+    ImageTexture->Delete();
+  
+  if (this->ImageHighlightCube)
+    this->ImageHighlightCube->Delete();
+  
+  if (this->ImageSliceHighlight)
+    ImageSliceHighlight->Delete();
+  
+  if (this->OwnsColorMap)
+    {
+      if (this->ColorMap)
+	this->ColorMap->Delete();
+    }
+}
+
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::SetInput(vtkImageData* image)
+{
+  if (image==NULL)
+    return;
+  
+  if (this->CurrentImage!=NULL)
+    this->CurrentImage->Delete();
+  this->CurrentImage=vtkImageData::New();
+  this->CurrentImage->ShallowCopy(image);
+  BuildImageSlice();
+  if (this->OwnsColorMap)
+    vtkpxColorMapUtil::AutoUpdateColormapRange(this->ColorMap,this->CurrentImage);
+  
+  int dim[3]; this->CurrentImage->GetDimensions(dim);
+  this->NumberOfFrames=this->CurrentImage->GetNumberOfScalarComponents();
+  this->Frame=0;
+  
+  /*  if (this->CurrentPlane==1)
+    {
+      double spa[3]; this->CurrentImage->GetSpacing(spa);
+      fprintf(stderr,"Input Spacing =%.2f %.2f %.2f\n",spa[0],spa[1],spa[2]);
+      }*/
+
+  // Create New Image Voi and Texture 
+  this->ImageVOI->SetInput(this->CurrentImage);
+  this->ImageVOI->Modified();
+
+  double sp[3];   this->CurrentImage->GetSpacing(sp);
+  double ori[3];  this->CurrentImage->GetOrigin(ori);
+
+  /*  int uext[6],wext[6]; 
+  image->GetUpdateExtent(uext);
+  image->GetWholeExtent(wext);
+  fprintf(stderr,"Whole Extent =%d %d %d %d %d %d\n",wext[0],wext[1],wext[2],wext[3],wext[4],wext[5]);
+  fprintf(stderr,"Updat Extent =%d %d %d %d %d %d\n",uext[0],uext[1],uext[2],uext[3],uext[4],uext[5]);*/
+ 
+
+
+  for (int ka=0;ka<=2;ka++)
+    {
+      OutlineBounds[ka*2]=0.0;
+      OutlineBounds[ka*2+1]=dim[ka]*sp[ka]+ori[ka];
+    }
+  
+  UpdateSlice();
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::SetLookupTable(vtkLookupTable* table)
+{
+  if (!table)
+      return;
+
+  if (table==this->ColorMap)
+      return;
+
+  if (this->ImageTexture)
+      this->ImageTexture->SetLookupTable(table);
+
+  if (this->OwnsColorMap)
+      {
+	this->ColorMap->Delete();
+	this->OwnsColorMap=0;
+      }
+
+  this->ColorMap=table;  
+  this->Update();
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::SetInterpolation(int on)
+{
+  int old=this->Interpolation;
+  this->Interpolation=(on>0);
+
+  if (this->Interpolation==old)
+    return;
+
+  if (!this->ImageTexture)
+    return;
+
+  if (this->Interpolation==1)
+    {
+      this->ImageTexture->InterpolateOn();
+      this->ImageVOI->ForcePowerOfTwoOff();
+    }
+  else
+    {
+      this->ImageTexture->InterpolateOff();
+      this->ImageVOI->ForcePowerOfTwoOn();
+    }
+
+this->ImageVOI->Modified();
+  this->UpdateSlice();
+
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::SetOpacity(float opacity)
+{
+  this->Opacity=Frange(opacity,0.0,1.0);
+  if (this->ImageSlice)
+    {
+      this->ImageSlice->GetProperty()->SetOpacity(this->Opacity);
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::SetFrame(int frame)
+{
+  if (this->ColorMode==0)
+    {
+      frame=Irange(frame,0,this->NumberOfFrames-1);
+      this->Frame=frame;
+      if (this->ImageSlice && this->AutoUpdate==1)
+	UpdateSlice();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::SetColorMode(int cm)
+{
+  if (this->ColorMode!=cm)
+    {
+      this->ColorMode=(cm>0);
+      if (this->ImageSlice && this->AutoUpdate==1)
+	UpdateSlice();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::SetPolarMode(int mode)
+{
+  int p=(mode>0);
+  if (p!=this->PolarMode)
+    {
+      this->PolarMode=p;
+      if (this->ImageSlice && this->AutoUpdate)
+	UpdateSlice();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::SetPolarMiddle(float pm)
+{
+  if (pm!=this->PolarMiddle)
+    {
+      this->PolarMiddle=pm;
+      if (this->PolarMode && this->ImageSlice)
+	UpdateSlice();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::SetLevel(int level)
+{
+  if (this->Level!=level)
+    {
+      this->Level=level;
+      if (this->ImageSlice && this->AutoUpdate==1)
+	UpdateSlice();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::SetCurrentPlane(int currentplane)
+{
+  if (currentplane!=this->CurrentPlane)
+    {
+      this->CurrentPlane=currentplane;
+      if (this->ImageSlice && this->AutoUpdate==1)
+	UpdateSlice();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::SetDisplayMode(int md)
+{
+  this->DisplayMode=md;
+  if (this->ImageSlice)
+    {
+      this->SetVisibility(1);
+      
+      if (this->DisplayMode==2 || this->DisplayMode==3)
+	this->ImageSlice->SetVisibility(1);
+      else
+	this->ImageSlice->SetVisibility(0);
+      
+      
+      if (this->DisplayMode==1 || this->DisplayMode==3)
+	this->ImageSliceOutline->SetVisibility(1);
+      else
+	this->ImageSliceOutline->SetVisibility(0);
+      
+      /*fprintf(stderr,"DIsplayMode=%d ,outline=%d, image=%d\n",
+	this->DisplayMode,
+	this->ImageSliceOutline->GetVisibility(),
+	this->ImageSlice->GetVisibility());*/
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::BuildImageSlice()
+{
+  //  fprintf(stderr,"In Build Image Slice %d, color mode=%d\n",(int)this,this->ColorMode);
+
+  if (!this->ImageSliceOutline)
+    {
+      // ImageOutline
+      this->ImageSliceOutline=vtkActor::New();
+      this->ImageSliceOutline->PickableOff();
+      this->ImageSliceOutline->SetVisibility(0);
+      
+      this->ImagePlane=vtkPlaneSource::New();
+      this->ImagePlane->SetXResolution(1);
+      this->ImagePlane->SetYResolution(1);
+      
+      this->ImageHighlightPlane=vtkPlaneSource::New();
+      this->ImageHighlightPlane->SetXResolution(1);
+      this->ImageHighlightPlane->SetYResolution(1);
+      
+
+      vtkPolyDataMapper* mappd=vtkPolyDataMapper::New();
+      mappd->SetInput(this->ImageHighlightPlane->GetOutput());
+      
+      this->ImageSliceOutline->SetMapper(mappd);
+      this->ImageSliceOutline->GetProperty()->SetColor(0.5, 0.5, 0.5);
+      this->ImageSliceOutline->GetProperty()->SetRepresentationToWireframe();
+      this->ImageSliceOutline->GetProperty()->SetAmbient(1.0);
+      this->ImageSliceOutline->GetProperty()->SetDiffuse(0.0);
+      this->ImageSliceOutline->GetProperty()->SetSpecular(0.0);
+      this->ImageSliceOutline->GetProperty()->SetRepresentationToWireframe();
+      
+      mappd->Delete();   
+      
+      this->AddPart(ImageSliceOutline);
+      
+      // ImageSlice
+      this->ImageSlice=vtkActor::New();
+      this->ImageSlice->PickableOff();
+      this->ImageTexture=vtkTexture::New();
+      this->ImageVOI=vtkpxImageExtract::New();
+      this->ImageVOI->LimitTextureSizeOff();
+      if (!this->Interpolation)
+	{
+	  this->ImageVOI->ForcePowerOfTwoOn();
+	  this->ImageVOI->SetMaximumTextureSize(512);
+	}
+
+      if (this->ColorMode)
+	this->ImageVOI->ExtractAllFramesOn();
+      else
+	this->ImageVOI->ExtractAllFramesOff();
+      
+      this->ImageVOI->SetInput((vtkImageData*)NULL);
+      
+      //setCoordinates(-1,-1);
+
+      this->ImageTexture->SetInput(this->ImageVOI->GetOutput());
+      if (this->Interpolation==1)
+	this->ImageTexture->InterpolateOn();
+      else
+	this->ImageTexture->InterpolateOff();
+
+      if (this->ColorMode)
+	{
+	  this->ImageTexture->SetLookupTable(NULL);
+	  this->ImageTexture->MapColorScalarsThroughLookupTableOff();
+	}
+      else
+	{
+	  this->ImageTexture->SetLookupTable(this->ColorMap);
+	  this->ImageTexture->MapColorScalarsThroughLookupTableOn();
+	}
+      this->ImageTexture->RepeatOff();
+
+      
+      vtkPolyDataMapper* imageMapper=vtkPolyDataMapper::New();
+      imageMapper->SetInput(this->ImagePlane->GetOutput());
+            
+      this->ImageSlice->SetMapper(imageMapper);
+      this->ImageSlice->GetProperty()->SetOpacity(this->Opacity);
+      this->ImageSlice->GetProperty()->SetInterpolationToFlat();
+      this->ImageSlice->SetTexture(this->ImageTexture);
+      
+      AddPart(this->ImageSlice);
+      imageMapper->Delete();  
+      
+      this->SetDisplayMode(this->DisplayMode);
+    }
+
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::UpdateSlice()
+{
+  if (!this->ImageVOI)
+      return;
+
+  if (this->PolarMode)
+    {
+      UpdateSlicePolar();
+      return;
+    }
+
+  vtkImageData* img=this->CurrentImage;
+  int range[3];  img->GetDimensions(range);
+  double sp[3];   img->GetSpacing(sp);
+  double ori[3];  img->GetOrigin(ori);
+
+
+  this->CurrentPlane=Irange(this->CurrentPlane,0,2);
+  
+  if (this->Level==-1)
+    this->Level=range[this->CurrentPlane]/2;
+  
+  this->Level=Irange(this->Level,0,range[this->CurrentPlane]-1);
+
+  //  fprintf(stderr,"Updating Slice, level=%d, plane=%d interpolation=%d\n",this->Level,this->CurrentPlane,this->Interpolation);
+
+
+  int newrange[3];
+
+  if (this->Interpolation == 0 )
+    {
+      for (int ia=0;ia<=2;ia++)
+	{
+	  int d=2;
+	  while (d<range[ia])
+	    d*=2;
+	  newrange[ia]=d;
+	}
+    }
+  else
+    {
+      for (int ia=0;ia<=2;ia++)
+	newrange[ia]=range[ia];
+    }
+
+  double d1[3];
+  double d0[3];
+  double d2[3];
+  double d3[3];
+
+  for (int i=0;i<=2;i++)
+    {
+      if (i!=this->CurrentPlane)
+	{
+	  d3[i]=sp[i]*double(range[i]-0.5)+ori[i];
+	  d1[i]=sp[i]*double(newrange[i]-0.5)+ori[i];
+	  d0[i]=sp[i]*double(-0.5)+ori[i];
+	}
+      else
+	{
+	  d1[i]=sp[i]*double(this->Level)+ori[i];
+	  d0[i]=d1[i];
+	  d3[i]=d1[i];
+	}
+      d2[i]=d0[i];
+      //      fprintf(stderr,"d1[%d]=%f, d3[%d]=%f\n",i,d1[i],i,d3[i]);
+    }
+
+  this->ImageVOI->SetPolarMode(0);
+  
+  switch (this->CurrentPlane)
+    {
+    case 0: // yz
+      this->ImagePlane->SetOrigin(d1[0] , d0[1] , d0[2]);
+      this->ImagePlane->SetPoint1(d1[0] , d1[1] , d0[2]);
+      this->ImagePlane->SetPoint2(d1[0] , d0[1] , d1[2]);
+
+      this->ImageHighlightPlane->SetOrigin(d3[0] , d2[1] , d2[2]);
+      this->ImageHighlightPlane->SetPoint1(d3[0] , d3[1] , d2[2]);
+      this->ImageHighlightPlane->SetPoint2(d3[0] , d2[1] , d3[2]);
+      
+      this->ImageVOI->SetCurrentPlane(0);
+      this->ImageVOI->SetSliceNo(this->Level);
+      this->ImageVOI->SetFrame(this->Frame);
+
+      break;
+      
+    case 1: // xz
+      this->ImagePlane->SetOrigin(d0[0] , d1[1] , d0[2]);
+      this->ImagePlane->SetPoint1(d1[0] , d1[1] , d0[2]);
+      this->ImagePlane->SetPoint2(d0[0] , d1[1] , d1[2]);
+
+      this->ImageHighlightPlane->SetOrigin(d2[0] , d3[1] , d2[2]);
+      this->ImageHighlightPlane->SetPoint1(d3[0] , d3[1] , d2[2]);
+      this->ImageHighlightPlane->SetPoint2(d2[0] , d3[1] , d3[2]);
+
+
+      this->ImageVOI->SetCurrentPlane(1);
+      this->ImageVOI->SetSliceNo(this->Level);
+      this->ImageVOI->SetFrame(this->Frame);
+      break;
+      
+    case 2: // xy
+      this->ImagePlane->SetOrigin(d0[0] , d0[1] , d1[2]);
+      this->ImagePlane->SetPoint1(d1[0] , d0[1] , d1[2]);
+      this->ImagePlane->SetPoint2(d0[0] , d1[1] , d1[2]);
+
+      this->ImageHighlightPlane->SetOrigin(d2[0] , d2[1] , d3[2]);
+      this->ImageHighlightPlane->SetPoint1(d3[0] , d2[1] , d3[2]);
+      this->ImageHighlightPlane->SetPoint2(d2[0] , d3[1] , d3[2]);
+
+      this->ImageVOI->SetCurrentPlane(2);
+      this->ImageVOI->SetSliceNo(this->Level);
+      this->ImageVOI->SetFrame(this->Frame);
+      break;
+    }
+
+  if (this->ColorMode)
+    {
+      this->ImageVOI->ExtractAllFramesOn();
+      this->ImageTexture->MapColorScalarsThroughLookupTableOff();
+    }
+  else
+    {
+      this->ImageVOI->ExtractAllFramesOff();
+      this->ImageTexture->MapColorScalarsThroughLookupTableOn();
+    }
+  this->ImageVOI->Modified();
+  
+  //  this->ImageVOI->Update();
+
+  /*  if (this->ImageSliceHighlight)
+      this->SetHighlightBounds(-1,-1, -1,-1, -1,-1);*/
+
+  /*  fprintf(stderr,"Cartesian Image Plane (%d), origin=(%.2f,%.2f,%.2f) p1=(%.2f,%.2f,%.2f) p2=(%.2f,%.2f,%.2f)\n",
+	  this->CurrentPlane,
+	  this->ImagePlane->GetOrigin()[0],
+	  this->ImagePlane->GetOrigin()[1],
+	  this->ImagePlane->GetOrigin()[2],
+	  this->ImagePlane->GetPoint1()[0],
+	  this->ImagePlane->GetPoint1()[1],
+	  this->ImagePlane->GetPoint1()[2],
+	  this->ImagePlane->GetPoint2()[0],
+	  this->ImagePlane->GetPoint2()[1],
+	  this->ImagePlane->GetPoint2()[2]);*/
+
+  //  fprintf(stderr,"Cartesian Image Plane / Level this=%d (%d,%d)\n",(int)this,this->CurrentPlane,this->Level);
+  //this->ImageSliceOutline->SetVisibility(1);				 
+}
+
+// ------------------------------------------------------------------------------------------
+
+void vtkpxImageSlice::SetDisplayHighlight(int hg)
+{
+  this->ShowHighlight=hg>0;
+  if (this->ShowHighlight==0)
+      {
+	if (this->ImageSliceHighlight)
+	    ImageSliceHighlight->SetVisibility(0);
+      }
+  else
+      {
+	if (!this->ImageSliceHighlight)
+	    this->SetHighlightBounds(-1,-1, -1,-1, -1,-1);
+
+	if (this->ImageSliceHighlight)
+	    ImageSliceHighlight->SetVisibility(1);
+      }
+}
+//------------------------------------------------------------------------------
+void vtkpxImageSlice::SetHighlightBounds(int b1,int b2,int b3,int b4,int b5,int b6)
+{
+  if (!this->ImageVOI)
+      return;
+
+  if (!this->ImageSliceHighlight)
+      {
+	
+	this->ImageHighlightCube=vtkCubeSource::New();
+	vtkPolyDataMapper* mappd=vtkPolyDataMapper::New();
+	mappd->SetInput(this->ImageHighlightCube->GetOutput());
+
+	this->ImageSliceHighlight=vtkActor::New();
+	this->ImageSliceHighlight->PickableOff();
+	this->ImageSliceHighlight->SetMapper(mappd);
+	this->ImageSliceHighlight->GetProperty()->SetColor(1.0,0.0,0.0);
+	this->ImageSliceHighlight->GetProperty()->SetRepresentationToWireframe();
+	this->ImageSliceHighlight->GetProperty()->SetLineWidth(1.0);
+	this->ImageSliceHighlight->GetProperty()->SetAmbient(1.0);
+	this->ImageSliceHighlight->GetProperty()->SetDiffuse(0.0);
+	this->ImageSliceHighlight->GetProperty()->SetSpecular(0.0);
+	
+	mappd->Delete();   
+	this->AddPart(ImageSliceHighlight);
+      }
+
+  vtkImageData* img=this->CurrentImage;
+
+  int   range[3];   img->GetDimensions(range);
+  double sp[3];     img->GetSpacing(sp);
+  double ori[3];    img->GetOrigin(ori);
+ 
+ 
+  if (b1>=0)      OutlineBounds[0]=b1*sp[0]+ori[0];   
+  if (b2>=0)      OutlineBounds[1]=b2*sp[0]+ori[0];
+  if (b3>=0)      OutlineBounds[2]=b3*sp[1]+ori[1];  
+  if (b4>=0)      OutlineBounds[3]=b4*sp[1]+ori[1]; 
+  if (b5>=0)      OutlineBounds[4]=b5*sp[2]+ori[2];  
+  if (b6>=0)      OutlineBounds[5]=b6*sp[2]+ori[2];
+
+
+  // Sort the Levels
+  for (int ka=0;ka<=2;ka++)
+      for (int kb=0;kb<=1;kb++)
+	  OutlineBounds[ka*2+kb]=Frange(OutlineBounds[ka*2+kb],ori[ka],(range[ka]-1)*sp[ka]+ori[ka]);
+
+
+  double level=this->Level*sp[this->CurrentPlane]+ori[this->CurrentPlane];
+
+  switch (this->CurrentPlane)
+    {
+    case 0: // saggital
+      this->ImageHighlightCube->SetBounds(level-0.1,level+0.1,
+					  OutlineBounds[2],OutlineBounds[3],
+					  OutlineBounds[4],OutlineBounds[5]);
+      break;
+      
+    case 1: // coronal
+      this->ImageHighlightCube->SetBounds(OutlineBounds[0],OutlineBounds[1],
+					  level-0.1,level+0.1,
+					  OutlineBounds[4],OutlineBounds[5]);
+      break;
+      
+    case 2: // axial
+      this->ImageHighlightCube->SetBounds(OutlineBounds[0],OutlineBounds[1],
+					  OutlineBounds[2],OutlineBounds[3],
+					  level-0.1,level+0.1);
+      break;
+    }
+
+}
+
+// ------------------------------------------------------------------------------------------
+void vtkpxImageSlice::UpdateSlicePolar()
+{
+  vtkImageData* img=this->CurrentImage;
+  int dim[3];  img->GetDimensions(dim);
+  double sp[3];   img->GetSpacing(sp);
+  double ori[3];  img->GetOrigin(ori);
+
+  this->CurrentPlane=Irange(this->CurrentPlane,0,2);
+  
+  if (this->Level<0)
+    {
+      if (this->CurrentPlane == 0)
+	this->Level=dim[1]/2;
+      else
+	this->Level=dim[2]/2;
+    }
+
+  if (this->CurrentPlane==0 && this->Level>=dim[1])
+    {
+      this->Level=dim[1]-1;
+    }
+  else if (this->CurrentPlane>0 && this->Level>=dim[2])
+    {
+      this->Level=dim[2]-1;
+    }
+
+
+  double r=0.5*double(dim[0])*sp[0];
+  double ox=ori[0]+double(sp[0]*(dim[0]-1))*0.5;
+
+  this->ImageVOI->SetPolarMode(1);
+  this->ImageVOI->SetPolarMiddle(this->PolarMiddle);
+
+  if (this->CurrentPlane>0)
+    {
+      double theta=180.0*double(this->Level)/double(dim[2]);
+      //fprintf(stderr,"\n\t this=%d,Current Plane = %d  theta=%.2f voi=%d\n",this,CurrentPlane,theta,this->ImageVOI);
+      // ------------------------
+      // -- Convert To Radians --
+      // ------------------------
+      theta*=M_PI/180.0;
+
+      this->ImagePlane->SetOrigin(ox-r*cos(theta),ox-r*sin(theta),ori[1]-0.5*sp[0]);
+      this->ImagePlane->SetPoint1(ox+r*cos(theta),ox+r*sin(theta),ori[1]-0.5*sp[0]);
+      this->ImagePlane->SetPoint2(ox-r*cos(theta),ox-r*sin(theta),ori[1]+(dim[1]-0.5)*sp[0]);
+
+      this->ImageVOI->SetCurrentPlane(this->CurrentPlane);
+      this->ImageVOI->SetSliceNo(this->Level);
+      this->ImageVOI->SetFrame(this->Frame);
+      this->ImageSliceOutline->SetVisibility(0);
+    }
+  else
+    {
+      double z=sp[0]*double(this->Level)+ori[1];
+      //fprintf(stderr,"\n\t this=%d Current Plane = %d  z=%.2f ImageVOI=%d\n",this,CurrentPlane,z,this->ImageVOI);
+      this->ImagePlane->SetOrigin(ox-r,ox-r,z);
+      this->ImagePlane->SetPoint1(ox+r,ox-r,z);
+      this->ImagePlane->SetPoint2(ox-r,ox+r,z);
+      this->ImageVOI->SetCurrentPlane(0);
+      this->ImageVOI->SetSliceNo(this->Level);
+      this->ImageVOI->SetFrame(this->Frame);
+      this->ImageSliceOutline->SetVisibility(1);
+    }
+
+  //  fprintf(stderr,"Polar Image Plane / Level this=%d (%d,%d)\n",(int)this,this->CurrentPlane,this->Level);
+  this->SetDisplayHighlight(0);
+
+}
+
+
+void vtkpxImageSlice::UpdateTexture()
+{
+  if (!this->CurrentImage || !this->ImageSlice)
+      return;
+
+  this->ImageSlice->GetTexture()->Modified();
+  this->ImageSlice->Modified();
+
+}
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxImageSlice.h b/bioimagesuite30_src/Graphics/vtkpxImageSlice.h
new file mode 100644
index 0000000..6872050
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxImageSlice.h
@@ -0,0 +1,176 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageSlice.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+// .NAME vtkpxImageSlice - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkpxImageSlice_h
+#define __vtkpxImageSlice_h
+
+#include "vtkpxEnclosedPipeline.h"
+#include "vtkImageData.h"
+#include "vtkpxImageExtract.h"
+#include "vtkLookupTable.h"
+#include "vtkPlaneSource.h"
+#include "vtkTexture.h"
+#include "vtkCubeSource.h"
+#include "vtkProperty.h"
+
+class vtkpxImageSlice : public vtkpxEnclosedPipeline
+{
+public:
+  static vtkpxImageSlice *New();
+  vtkTypeMacro(vtkpxImageSlice,vtkpxEnclosedPipeline);
+
+  // Description:
+  // Add a part to the list of parts.
+
+  virtual void SetInput(vtkImageData* image);
+
+
+  virtual void SetLookupTable(vtkLookupTable* table);
+  virtual void SetInterpolation(int on);
+  virtual void SetOpacity(float opacity);
+  virtual void SetLevel(int level);
+  virtual void SetFrame(int frame);
+  virtual void SetCurrentPlane(int CurrentPlane);
+
+  // If 1 -> Ignore lookup table and render directly
+  virtual void SetColorMode(int mode);
+
+  virtual void SetPolarMode(int mode);
+  virtual void SetPolarMiddle(float polarmiddle=-1);
+
+
+  virtual void SetDisplayMode(int md);
+
+  virtual void SetDisplayHighlight(int hg);
+  virtual void SetHighlightBounds(int b1,int b2,int b3,int b4,int b5,int b6);
+
+  vtkGetMacro(CurrentPlane,int);
+  vtkGetMacro(Level,int);
+  vtkGetMacro(Frame,int);
+  vtkGetMacro(NumberOfFrames,int);
+
+  vtkGetMacro(DisplayMode,int);
+  vtkGetMacro(Opacity,float);
+  vtkGetMacro(Interpolation,int);
+
+  vtkGetMacro(OwnsColorMap,int);
+
+  vtkGetMacro(PolarMode,int);
+  vtkGetMacro(PolarMiddle,float);
+
+
+  vtkSetClampMacro(AutoUpdate,int,0,1);
+  vtkGetMacro(AutoUpdate,int);
+  vtkBooleanMacro(AutoUpdate,int);
+
+
+  virtual void Update() { this->UpdateSlice();}
+  virtual void UpdateTexture();
+
+protected:
+
+  vtkActor*                    ImageSliceHighlight;
+  vtkActor*                    ImageSliceOutline;
+  vtkActor*                    ImageSlice;
+  vtkPlaneSource*              ImagePlane;
+  vtkPlaneSource*              ImageHighlightPlane;
+  vtkCubeSource*               ImageHighlightCube;
+  vtkpxImageExtract*           ImageVOI;
+  vtkImageData*                CurrentImage;
+  vtkTexture*                  ImageTexture;
+  int                          Level;
+
+  int                          Frame;
+  int                          NumberOfFrames;
+
+  float                        OutlineBounds[6];
+  int                          CurrentPlane;
+
+  float                        Opacity;
+  int                          Interpolation;
+  int                          DisplayMode;
+  int                          ShowHighlight;
+  int                          AutoUpdate;
+
+  vtkLookupTable*              ColorMap;
+  int                          OwnsColorMap;   
+  int                          ColorMode;
+
+  int                          PolarMode;
+  float                        PolarMiddle;
+
+  vtkpxImageSlice();
+  virtual ~vtkpxImageSlice();
+  vtkpxImageSlice(const vtkpxImageSlice&) {};
+  void operator=(const vtkpxImageSlice&) {};
+
+  // Slice Stuff
+  virtual void BuildImageSlice();
+  virtual void UpdateSlice();
+  virtual void UpdateSlicePolar();
+
+
+};
+
+
+#endif
+
+
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxMapActivationToPolyData.cpp b/bioimagesuite30_src/Graphics/vtkpxMapActivationToPolyData.cpp
new file mode 100644
index 0000000..0375869
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxMapActivationToPolyData.cpp
@@ -0,0 +1,376 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxMapActivationToPolyData.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/06/04 00:05:14 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxMapActivationToPolyData.h"
+#include "vtkObjectFactory.h"
+#include "vtkPolyDataNormals.h"
+#include "vtkFloatArray.h"
+#include "vtkPoints.h"
+#include "vtkProbeFilter.h"
+#include "vtkDataSet.h"
+#include "vtkLineSource.h"
+#include "vtkUnsignedCharArray.h"
+#include "pxutil.h"
+//--------------------------------------------------------------------------
+vtkpxMapActivationToPolyData* vtkpxMapActivationToPolyData::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxMapActivationToPolyData");
+  if(ret)
+    {
+    return (vtkpxMapActivationToPolyData*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxMapActivationToPolyData;
+}
+
+vtkpxMapActivationToPolyData::vtkpxMapActivationToPolyData()
+{
+  this->MaxDistance = 10.0;
+  this->MinDistance = 10.0;
+  this->AverageMode = 0;
+  this->Resolution=1.0;
+  this->FunctionalData=NULL;
+
+  this->LowThreshold=0.0;
+  this->HighThreshold=1.0;
+
+  this->ThresholdPositive=1;
+  this->ThresholdNegative=0;
+
+}
+
+
+vtkpxMapActivationToPolyData::~vtkpxMapActivationToPolyData()
+{
+  this->ReleaseFunctionalData();
+}
+
+void vtkpxMapActivationToPolyData::Execute()
+{
+  vtkPolyData *source = this->GetInput();
+  vtkPolyData *destination= this->GetOutput();
+  
+  destination->CopyStructure(source);
+
+  if (this->FunctionalData==NULL)
+    {
+      vtkErrorMacro(<<"No Functional Data Leaving Surface as is\n");
+      destination->GetPointData()->PassData(source->GetPointData());
+      return;
+    }
+
+  if (this->FunctionalData->GetPointData()->GetScalars()==NULL)
+    {
+      vtkErrorMacro(<<"No Functional Data (Structures) Leaving Surface as is\n");
+      destination->GetPointData()->PassData(source->GetPointData());
+      return;
+    }
+
+  int np=source->GetPoints()->GetNumberOfPoints();
+
+  if (np<20)
+    return;
+
+  vtkPolyDataNormals* polyNormals=vtkPolyDataNormals::New();
+  vtkDataArray* normals=source->GetPointData()->GetNormals();
+  if (normals==NULL)
+    {
+      polyNormals->SetInput(source);
+      polyNormals->SplittingOff();
+      polyNormals->ComputePointNormalsOn();
+      vtkDebugMacro(<<"Computing our own normals ... bad idea\n");
+      polyNormals->Update();
+      normals=polyNormals->GetOutput()->GetPointData()->GetNormals();
+      //destination->GetPointData()->SetNormals(normals);
+    }
+
+  this->UpdateProgress(0.2);
+
+
+  vtkDataArray* newscalars = vtkDataArray::CreateDataArray(VTK_UNSIGNED_CHAR);
+  newscalars->SetNumberOfComponents(3);
+  newscalars->SetNumberOfTuples(np);
+  destination->GetPointData()->SetScalars(newscalars);
+
+  vtkUnsignedCharArray* scaldata=(vtkUnsignedCharArray*)newscalars;
+  float c[3];
+  c[0]=190;  c[1]=190; c[2]=190;
+  for (int k=0;k<=np;k++)
+    scaldata->SetTuple(k,c);
+
+  vtkDebugMacro(<<"Creating " << np << "newscalars\n");
+
+  float length=fabs(this->MaxDistance-this->MinDistance);
+  if (length<0.01)
+      length=1.0;
+
+  int res=int(length/this->Resolution+0.5);
+  if (res<2)
+    res=2;
+
+  vtkLineSource* ln=vtkLineSource::New();
+  ln->SetResolution(res);
+
+  vtkProbeFilter* probe=vtkProbeFilter::New();
+  probe->SetSource(this->FunctionalData);
+
+  if (this->LowThreshold<0.0)
+    this->LowThreshold=0.0;
+
+  float scalefactor=fabs(this->HighThreshold-this->LowThreshold);
+  if (scalefactor==0.0)
+    scalefactor=1.0;
+  scalefactor=3.0/scalefactor;
+  
+  vtkDebugMacro(<< "Thresholds : " << this->LowThreshold << "," << this->HighThreshold << ", SF= " << scalefactor );
+  int numset=0;
+
+  this->UpdateProgress(0.3);
+
+  int frac=int(np/10);
+  float npf=float(1.25*np);
+
+  for (int i=0;i<np;i++)
+    {
+      int index=int(i/frac);
+      if (index*frac==i)
+	{
+	  float factor=float(i)/npf+0.2;
+	  this->UpdateProgress(factor);
+	}
+
+      double x[3],n[3],tx[3],ox[3];
+      source->GetPoints()->GetPoint(i,x);
+      normals->GetTuple(i,n);
+
+      float m=sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);
+      if (fabs(m-1.0)>0.001)
+	fprintf(stderr,"Normal %d %.1f %.1f %.1f == %.1f\n",
+	i,n[0],n[1],n[2],m);
+
+      for (int ia=0;ia<=2;ia++)
+	{
+	  //	  n[ia]=Frange(n[ia],0.001,1.0);
+	  ox[ia]=x[ia]-this->MinDistance*n[ia];
+	  tx[ia]=x[ia]-this->MaxDistance*n[ia];
+	  if (ox[ia]==tx[ia])
+	    tx[ia]+=1.0;
+	}
+
+      ln->SetPoint1(ox);
+      ln->SetPoint2(tx);
+      ln->Modified();
+      ln->Update();
+      probe->SetInput(ln->GetOutput());
+      probe->Modified();
+      probe->Update();
+
+      float max=0.0;
+      vtkPolyData*  dat=(vtkPolyData*)probe->GetOutput();
+      if (dat!=NULL)
+	{
+	  vtkDataArray* inten=dat->GetPointData()->GetScalars();
+	  if (inten!=NULL)
+	    {
+	      int nump=inten->GetNumberOfTuples();
+	      max=inten->GetComponent(0,0);
+	      float sum=max;
+	      for (int j=1;j<nump;j++)
+		{
+		  float v=inten->GetComponent(j,0);
+		  sum+=v;
+		  if (v>max)
+		    max=v;
+		}
+	      
+	      if (nump>0)
+		{
+		  if (this->AverageMode)
+		    max=sum/nump;
+		}
+	    }
+	}
+
+      if ( fabs(max)>this->LowThreshold)
+	{
+	  float c[3];
+	  int v=int(0.5+(fabs(max)-this->LowThreshold)*scalefactor);
+	  if (max<0)
+	    {
+	      if (this->ThresholdNegative)
+		{
+		  switch (v)
+		    {
+		    case 3:
+		      c[0]=1.0;c[1]=1.0;c[2]=1.0;
+		      break;
+		    case 2:
+		      c[0]=0.3333; c[1]=0.6667; c[2]=1.0000;
+		      break;
+		    case 1:
+		      c[0]=0.6667; c[1]=0.3333; c[2]=1.0000;
+		      break;
+		    default:
+		      c[0]=1.0; c[1]=0.0; c[2]=1.0;
+		      break;
+		    }
+		  for (int ia=0;ia<=2;ia++)
+		    c[ia]*=255.0;
+		  scaldata->SetTuple(i,c);
+		  numset++;
+		}
+	    }
+	  else
+	    {
+	      if (this->ThresholdPositive)
+		{
+		  switch (v)
+		    {
+		    case 3:
+		      c[0]=1.0000; c[1]=1.0000; c[2]=0.6667;
+		      break;
+		    case 2:
+		      c[0]=1.0000; c[1]=1.0000; c[2]=0.3333;
+		      break;
+		    case 1:
+		      c[0]=1.0000; c[1]=1.0000; c[2]=0;
+		      break;
+		    default:
+		      c[0]=1.0000; c[1]=0.0; c[2]=0.0;
+		      break;
+		    }
+		  for (int ia=0;ia<=2;ia++)
+		    c[ia]*=255.0;
+
+		  scaldata->SetTuple(i,c);
+		  numset++;
+		}
+	    }
+	}
+    }
+
+  if (this->Debug)
+    {
+      double range[2];
+      this->FunctionalData->GetPointData()->GetScalars()->GetRange(range);
+      vtkDebugMacro(<<"Functional Range = " << range[0] << ":" << range[1] << " (res="<<res<<", distance = " << this->MaxDistance <<")\n");
+      vtkDebugMacro(<<"Num Set= " << numset  << " numtotal = " << np << " Fraction = " << fabs(float(numset))/fabs(float(np))*100.0 );
+    }
+
+  polyNormals->Delete();
+  newscalars->Delete();
+  ln->Delete();
+  probe->Delete();
+}
+
+
+void vtkpxMapActivationToPolyData::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkPolyDataToPolyDataFilter::PrintSelf(os,indent);
+  os << indent << "Max Distance    : " << this->MaxDistance << "\n";
+  os << indent << "Resolution      : " << this->Resolution  << "\n";
+  os << indent << "Functional Data : " << this->FunctionalData << "\n";
+  os << indent << "Thresholds      : " << this->LowThreshold << ":" <<  this->HighThreshold << "\n";
+}
+
+void vtkpxMapActivationToPolyData::ReleaseFunctionalData() 
+{
+  if (this->FunctionalData) 
+    {
+    this->FunctionalData->UnRegister(this);
+    this->FunctionalData = NULL;
+    }
+}
+
+
+void vtkpxMapActivationToPolyData::SetFunctionalData(vtkDataSet *FunctionalData)
+{
+  if (this->FunctionalData == FunctionalData)
+    {
+      return;
+    }
+
+  if (this->FunctionalData)
+    {
+      this->ReleaseFunctionalData();
+    }
+
+  if (FunctionalData)
+    {
+      FunctionalData->Register(this);
+    }
+
+  this->FunctionalData = FunctionalData;
+
+  if (this->LowThreshold==0.0 && this->HighThreshold==1.0 )
+    {
+      vtkPointData* dt=this->FunctionalData->GetPointData();
+      if (dt!=NULL)
+	{
+	  vtkDataArray* scal=dt->GetScalars();
+	  if (scal!=NULL)
+	    {
+	      double range[2];
+	      scal->GetRange(range);
+	      this->LowThreshold=0.0;
+	      this->HighThreshold=range[1];
+	    }
+	}
+    }
+
+  this->Modified();
+}
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxMapActivationToPolyData.h b/bioimagesuite30_src/Graphics/vtkpxMapActivationToPolyData.h
new file mode 100644
index 0000000..e88fb1d
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxMapActivationToPolyData.h
@@ -0,0 +1,170 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxMapActivationToPolyData.h,v $
+  Language:  C++
+  Date:      $Date: 2003/06/05 21:02:51 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+// .NAME vtkpxMapActivationToPolyData - shrink cells composing PolyData
+// .SECTION Description
+// vtkpxMapActivationToPolyData shrinks cells composing a polygonal dataset (e.g., 
+// vertices, lines, polygons, and triangle strips) towards their centroid. 
+// The centroid of a cell is computed as the average position of the
+// cell points. Shrinking results in disconnecting the cells from
+// one another. The output dataset type of this filter is polygonal data.
+//
+// During execution the filter passes its input cell data to its
+// output. Point data attributes are copied to the points created during the
+// shrinking process.
+
+// .SECTION Caveats
+// It is possible to turn cells inside out or cause self intersection
+// in special cases.
+
+// .SECTION See Also
+// vtkShrinkFilter
+
+#ifndef __vtkpxMapActivationToPolyData_h
+#define __vtkpxMapActivationToPolyData_h
+
+class vtkDataSet;
+
+#include "vtkPolyDataToPolyDataFilter.h"
+#include "vtkDataArray.h"
+#include "vtkCellArray.h"
+#include "vtkDataObject.h"
+#include "vtkPolyData.h"
+#include "vtkPointData.h"
+
+class vtkpxMapActivationToPolyData : public vtkPolyDataToPolyDataFilter 
+{
+public:
+  static vtkpxMapActivationToPolyData *New();
+  vtkTypeMacro(vtkpxMapActivationToPolyData,vtkPolyDataToPolyDataFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Set the distance to move in/out from the normal
+  vtkSetClampMacro(MaxDistance,float,-20.0,20.0);
+
+  // Description:
+  // Get the distance to move in/out from the normal
+  vtkGetMacro(MaxDistance,float);
+
+  // Description:
+  // Set the distance to move in/out from the normal
+  vtkSetClampMacro(MinDistance,float,-20.0,20.0);
+
+  // Description:
+  // Get the distance to move in/out from the normal
+  vtkGetMacro(MinDistance,float);
+
+
+  // Description:
+  // Set the resolution to sample functional data
+  vtkSetClampMacro(Resolution,float,0.1,10.0);
+
+  // Description:
+  // Get the resolution to sample functional data
+  vtkGetMacro(Resolution,float);
+
+  // Description:
+  // Set The Functional Data 
+  virtual void SetFunctionalData(vtkDataSet *FunctionalData);
+
+
+  // Description:
+  // Thresholds determine the functional range to be mapped
+  vtkSetMacro(LowThreshold,float);
+  vtkGetMacro(LowThreshold,float);
+  vtkSetMacro(HighThreshold,float);
+  vtkGetMacro(HighThreshold,float);
+
+  // Description:
+  // Threshold Positive/Negative/Both (default=Positive)
+  vtkBooleanMacro(ThresholdPositive, int);
+  vtkSetMacro(ThresholdPositive, int);
+  vtkGetMacro(ThresholdPositive, int);
+
+  vtkBooleanMacro(ThresholdNegative, int);
+  vtkSetMacro(ThresholdNegative, int);
+  vtkGetMacro(ThresholdNegative, int);
+
+  // Description:
+  // Average Mode (default = false)
+  vtkBooleanMacro(AverageMode, int);
+  vtkSetMacro(AverageMode, int);
+  vtkGetMacro(AverageMode, int);
+
+
+protected:
+  vtkpxMapActivationToPolyData();
+  virtual ~vtkpxMapActivationToPolyData();
+  vtkpxMapActivationToPolyData(const vtkpxMapActivationToPolyData&) {};
+  void operator=(const vtkpxMapActivationToPolyData&) {};
+
+  void Execute();
+  float MaxDistance;
+  float MinDistance;
+  float Resolution;
+  float LowThreshold;
+  float HighThreshold;
+  int   ThresholdPositive;
+  int   AverageMode;
+  int   ThresholdNegative;
+  vtkDataSet* FunctionalData;
+
+  void ReleaseFunctionalData();
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxNormalShrinkPolyData.cpp b/bioimagesuite30_src/Graphics/vtkpxNormalShrinkPolyData.cpp
new file mode 100644
index 0000000..98d36c1
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxNormalShrinkPolyData.cpp
@@ -0,0 +1,146 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxNormalShrinkPolyData.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/10/07 00:57:07 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxNormalShrinkPolyData.h"
+#include "pxutil.h"
+#include "vtkObjectFactory.h"
+#include "vtkPolyDataNormals.h"
+#include "vtkFloatArray.h"
+#include "vtkPoints.h"
+
+//--------------------------------------------------------------------------
+vtkpxNormalShrinkPolyData* vtkpxNormalShrinkPolyData::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxNormalShrinkPolyData");
+  if(ret)
+    {
+    return (vtkpxNormalShrinkPolyData*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxNormalShrinkPolyData;
+}
+
+vtkpxNormalShrinkPolyData::vtkpxNormalShrinkPolyData()
+{
+  this->Distance = 1.0;
+
+}
+
+void vtkpxNormalShrinkPolyData::Execute()
+{
+  vtkPolyData *source = this->GetInput();
+  vtkPolyData *destination= this->GetOutput();
+  
+  destination->CopyStructure(source);
+  int np=source->GetPoints()->GetNumberOfPoints();
+
+  vtkPolyDataNormals* polyNormals=vtkPolyDataNormals::New();
+  vtkDataArray* normals=source->GetPointData()->GetNormals();
+  if (normals==NULL)
+    {
+      polyNormals->SetInput(source);
+      polyNormals->SplittingOff();
+      polyNormals->ComputePointNormalsOn();
+      vtkDebugMacro(<<"Computing our own normals ... bad idea\n");
+      polyNormals->Update();
+      normals=polyNormals->GetOutput()->GetPointData()->GetNormals();
+      //destination->GetPointData()->SetNormals(normals);
+    }
+
+  this->UpdateProgress(0.2);
+
+
+  vtkPoints* newpoints = vtkPoints::New();
+  newpoints->SetNumberOfPoints(np);
+
+  float npf=float(1.25*np);
+  int count=0,maxcount=np/10;
+
+  for (int i=0;i<np;i++)
+    {
+      count++;
+      if (count==maxcount)
+	{
+	  count=0;
+	  float factor=float(i)/npf+0.2;
+	  this->UpdateProgress(factor);
+	}
+
+      double x[3],n[3],tx[3];
+      source->GetPoints()->GetPoint(i,x);
+      normals->GetTuple(i,n);
+
+      for (int ia=0;ia<=2;ia++)
+	tx[ia]=x[ia]+this->Distance*n[ia];
+
+      newpoints->SetPoint(i,tx);
+    }
+
+
+  destination->SetPoints(newpoints);
+  newpoints->Delete();
+  polyNormals->Delete();
+
+}
+
+
+void vtkpxNormalShrinkPolyData::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkPolyDataToPolyDataFilter::PrintSelf(os,indent);
+  os << indent << "Distance    : " << this->Distance << "\n";
+}
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxNormalShrinkPolyData.h b/bioimagesuite30_src/Graphics/vtkpxNormalShrinkPolyData.h
new file mode 100644
index 0000000..440e6b0
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxNormalShrinkPolyData.h
@@ -0,0 +1,116 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxNormalShrinkPolyData.h,v $
+  Language:  C++
+  Date:      $Date: 2003/06/05 21:03:09 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+// .NAME vtkpxNormalShrinkPolyData - shrink cells composing PolyData
+// .SECTION Description
+// vtkpxNormalShrinkPolyData shrinks cells composing a polygonal dataset (e.g., 
+// vertices, lines, polygons, and triangle strips) towards their centroid. 
+// The centroid of a cell is computed as the average position of the
+// cell points. Shrinking results in disconnecting the cells from
+// one another. The output dataset type of this filter is polygonal data.
+//
+// During execution the filter passes its input cell data to its
+// output. Point data attributes are copied to the points created during the
+// shrinking process.
+
+// .SECTION Caveats
+// It is possible to turn cells inside out or cause self intersection
+// in special cases.
+
+// .SECTION See Also
+// vtkShrinkFilter
+
+#ifndef __vtkpxNormalShrinkPolyData_h
+#define __vtkpxNormalShrinkPolyData_h
+
+class vtkDataSet;
+
+#include "vtkPolyDataToPolyDataFilter.h"
+#include "vtkDataArray.h"
+#include "vtkCellArray.h"
+#include "vtkDataObject.h"
+#include "vtkPolyData.h"
+#include "vtkPointData.h"
+
+class vtkpxNormalShrinkPolyData : public vtkPolyDataToPolyDataFilter 
+{
+public:
+  static vtkpxNormalShrinkPolyData *New();
+  vtkTypeMacro(vtkpxNormalShrinkPolyData,vtkPolyDataToPolyDataFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Set the distance to move in/out from the normal
+  vtkSetClampMacro(Distance,float,-20.0,20.0);
+
+  // Description:
+  // Get the distance to move in/out from the normal
+  vtkGetMacro(Distance,float);
+
+
+protected:
+  vtkpxNormalShrinkPolyData();
+
+  vtkpxNormalShrinkPolyData(const vtkpxNormalShrinkPolyData&) {};
+  void operator=(const vtkpxNormalShrinkPolyData&) {};
+
+  void Execute();
+  float Distance;
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxObliqueImageSlice.cpp b/bioimagesuite30_src/Graphics/vtkpxObliqueImageSlice.cpp
new file mode 100644
index 0000000..be61341
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxObliqueImageSlice.cpp
@@ -0,0 +1,900 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxObliqueImageSlice.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/03/19 14:14:48 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxObliqueImageSlice.h"
+#include "vtkObjectFactory.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkPolyDataWriter.h"
+#include "vtkpxUtil.h"
+#include "vtkImageMapToColors.h"
+#include "vtkpxColorMapUtil.h"
+#include "vtkOutlineFilter.h"
+#include "vtkMath.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+//------------------------------------------------------------------------------
+vtkpxObliqueImageSlice* vtkpxObliqueImageSlice::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxObliqueImageSlice");
+  if(ret)
+    {
+    return (vtkpxObliqueImageSlice*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxObliqueImageSlice;
+}
+//------------------------------------------------------------------------------
+// Construct object with no children.
+vtkpxObliqueImageSlice::vtkpxObliqueImageSlice()
+{
+  this->ImageMapper=NULL;
+  this->ImageComponentExtractor=NULL;
+  this->ImageSliceOutline=NULL;    
+  this->ImageSlice=NULL;         
+  this->ImagePlane=NULL;         
+  this->InputImage=NULL;
+
+  this->ImageTexture=NULL; 
+  this->BaseImageReslicer=NULL;
+  this->BaseImageTransform=NULL;
+
+  this->InitialPoints=vtkPoints::New();
+  this->InitialPoints->SetNumberOfPoints(3);
+
+      
+  this->Frame=0;
+  this->Resolution=256;
+  this->NumberOfFrames=1;
+  this->ShowNormalArrow=0;
+  this->NormalArrowColor=0;
+
+  this->Interpolation=1;      
+  this->Opacity=1.0;
+
+  this->ColorMap=NULL;           
+  this->OwnsColorMap=1;   
+  this->DisplayMode=3;
+
+  this->ColorMap=vtkLookupTable::New();
+  this->ColorMap->SetNumberOfTableValues(256);
+  this->ColorMap->SetTableRange(0,255);
+  this->ColorMode=0;
+
+  for (int i=0;i<=255;i++)
+    {
+      double v=double(i)/double(255.0);
+      this->ColorMap->SetTableValue(i,v,v,v,1.0);
+    }
+
+  this->Normal[0]=0.0;   this->Normal[1]=0.0;  this->Normal[2]=1.0; 
+  this->Center[0]=0.0;   this->Center[1]=0.0;  this->Center[2]=0.0;
+  this->Distance=0.0;
+ 
+  this->AutoUpdate=1;
+}
+//------------------------------------------------------------------------------
+vtkpxObliqueImageSlice::~vtkpxObliqueImageSlice()
+{
+  if (this->ImageComponentExtractor!=NULL)
+    this->ImageComponentExtractor->Delete();
+
+  if (this->InputImage)
+    this->InputImage->Delete();
+
+  if (this->ImagePlane)
+    this->ImagePlane->Delete();
+
+  if (this->ImageMapper)
+    this->ImageMapper->Delete();
+  
+  if (this->ImageSliceOutline)
+    this->ImageSliceOutline->Delete();
+  
+  if (this->ImageSlice)
+    this->ImageSlice->Delete();
+  
+
+  if (this->BaseImageReslicer)
+    this->BaseImageReslicer->Delete();
+
+  if (this->BaseImageTransform)
+    this->BaseImageTransform->Delete();
+
+  if (this->ImageTexture)
+    ImageTexture->Delete();
+
+  this->InitialPoints->Delete();
+
+  if (this->OwnsColorMap)
+    {
+      if (this->ColorMap)
+	this->ColorMap->Delete();
+    }
+}
+
+//------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::SetInput(vtkImageData* image)
+{
+  if (image==NULL)
+    return;
+
+  int dochange=1;
+  
+  if (this->InputImage==NULL)
+    this->InputImage=vtkImageData::New();
+
+  int dim1[3]; double sp1[3],ori1[3];
+  image->GetDimensions(dim1); image->GetSpacing(sp1); image->GetOrigin(ori1);
+  int dim2[3]; double sp2[3],ori2[3];
+  this->InputImage->GetDimensions(dim2); this->InputImage->GetSpacing(sp2); this->InputImage->GetOrigin(ori2);
+  
+  int sum=0;
+  for (int ia=0;ia<=2;ia++)
+    {
+      sum+=   abs(dim1[ia] -dim2[ia]);
+      sum+=( fabs(sp1[ia]  -sp2[ia])>0.01);
+      sum+=( fabs(ori1[ia] -ori2[ia])>0.01);
+    }
+  if (sum==0)
+    dochange=0;
+
+  this->InputImage->ShallowCopy(image);
+  this->InputImage->Modified();
+
+  BuildImageSlice();
+  if (this->OwnsColorMap)
+    vtkpxColorMapUtil::AutoUpdateColormapRange(this->ColorMap,image);
+  
+  int dim[3]; image->GetDimensions(dim);
+  this->NumberOfFrames=image->GetNumberOfScalarComponents();
+  this->Frame=0;
+  
+  // Create New Image Voi and Texture 
+  this->ImageComponentExtractor->SetInput(this->InputImage);
+  
+  if (this->ColorMode)
+    {
+      this->ImageComponentExtractor->SetComponents(0,1,2);
+    }
+  else
+    {
+      this->ImageComponentExtractor->SetComponents(this->Frame);
+    }
+  
+  this->ImageComponentExtractor->Modified();
+
+  if (dochange)
+    {
+      double sp[3];   this->InputImage->GetSpacing(sp);
+      double ori[3];  this->InputImage->GetOrigin(ori);
+      
+      double length2=0.0,length[3];
+      for (int ka=0;ka<=2;ka++)
+	{
+	  length[ka]=sp[ka]*(dim[ka]-1);
+	  length2+=pow(length[ka],2.0);
+	}
+      length2=sqrt(length2);
+      
+      for (int ka=0;ka<=2;ka++)
+	{
+	  if (ka==2)
+	    {
+	      OutlineBounds[ka*2]=0.0;
+	      OutlineBounds[ka*2+1]=double(dim[ka]-1)*sp[ka]+ori[ka];
+	    }
+	  else
+	    {
+	      float half=0.5*(length2-length[ka]);
+	      OutlineBounds[ka*2]=ori[ka]-half;
+	      OutlineBounds[ka*2+1]=double(dim[ka]-1)*sp[ka]+ori[ka]+half;
+	    }
+	}
+      
+
+      double p1[3],p2[3],p3[3];
+      
+      this->ImagePlane->SetOrigin(OutlineBounds[0],OutlineBounds[2],0.5*(OutlineBounds[4]+OutlineBounds[5]));
+      this->ImagePlane->GetOrigin(p1); 
+      this->InitialPoints->SetPoint(0,p1);
+      
+      this->ImagePlane->SetPoint1(OutlineBounds[1],OutlineBounds[2],0.5*(OutlineBounds[4]+OutlineBounds[5]));
+      this->ImagePlane->GetPoint1(p2); 
+      this->InitialPoints->SetPoint(1,p2);
+      
+      this->ImagePlane->SetPoint2(OutlineBounds[0],OutlineBounds[3],0.5*(OutlineBounds[4]+OutlineBounds[5]));
+      this->ImagePlane->GetPoint2(p3); 
+      this->InitialPoints->SetPoint(2,p3);
+      
+      for (int ia=0;ia<=2;ia++)
+	this->Center[ia]=0.5*(OutlineBounds[ia*2]+OutlineBounds[ia*2+1]);
+      
+      for (int ia=0;ia<=2;ia++)
+	this->BaseImageOrigin[ia]=p1[ia];
+      this->BaseImageSpacing[0]=(OutlineBounds[1]-OutlineBounds[0]-1.0)/double(this->Resolution);
+      this->BaseImageSpacing[1]=(OutlineBounds[3]-OutlineBounds[2]-1.0)/double(this->Resolution);
+      this->BaseImageSpacing[2]=1.0;
+      
+      this->BaseImageExtent[0]=0;      this->BaseImageExtent[2]=0;      this->BaseImageExtent[4]=0;
+      this->BaseImageExtent[1]=this->Resolution-1;
+      this->BaseImageExtent[3]=this->Resolution-1;
+      this->BaseImageExtent[5]=0;
+      
+      this->Distance=0.0;
+      this->Normal[0]=0.0;   this->Normal[1]=0.0;  this->Normal[2]=1.0;  
+      this->ArrowSource->SetHeight(0.2*(OutlineBounds[5]-OutlineBounds[4]));
+      this->ArrowSource->Modified();
+
+    }
+  UpdateSlice();
+}
+//------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::SetLookupTable(vtkLookupTable* table)
+{
+  if (!table)
+      return;
+
+  if (table==this->ColorMap)
+      return;
+
+  if (this->ImageTexture)
+    this->ImageTexture->SetLookupTable(table);
+
+  if (this->OwnsColorMap)
+      {
+	this->ColorMap->Delete();
+	this->OwnsColorMap=0;
+      }
+
+  this->ColorMap=table;  
+  this->Update();
+  /*  if (this->ImageMapper!=NULL)
+      this->ImageMapper->SetLookupTable(this->ColorMap);*/
+}
+//------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::SetInterpolation(int on)
+{
+  this->Interpolation=on>0;
+  if (this->ImageTexture)
+      {
+	if (this->Interpolation==1)
+	  {
+	    this->ImageTexture->InterpolateOn();
+	    this->BaseImageReslicer->SetInterpolationModeToLinear();
+	  }
+	else
+	  {
+	    this->ImageTexture->InterpolateOff();
+	    this->BaseImageReslicer->SetInterpolationModeToNearestNeighbor();
+	  }
+      }
+}
+//------------------------------------------------------------------------------
+
+void vtkpxObliqueImageSlice::SetOpacity(double opacity)
+{
+  this->Opacity=Frange(opacity,0.0,1.0);
+  if (this->ImageSlice)
+    this->ImageSlice->GetProperty()->SetOpacity(this->Opacity);
+}
+//------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::SetResolution(int res)
+{
+  int r=Irange(res,2,1024);
+
+  if (this->Resolution==r)
+    return;
+
+  this->Resolution=r;
+
+  if (this->ImagePlane)
+    {
+      this->BaseImageSpacing[0]=(OutlineBounds[1]-OutlineBounds[0])/double(this->Resolution);
+      this->BaseImageSpacing[1]=(OutlineBounds[3]-OutlineBounds[2])/double(this->Resolution);
+      this->BaseImageSpacing[2]=1.0;
+
+      this->BaseImageExtent[0]=0;      this->BaseImageExtent[2]=0;      this->BaseImageExtent[4]=0;
+      this->BaseImageExtent[1]=this->Resolution-1;
+      this->BaseImageExtent[3]=this->Resolution-1;
+      this->BaseImageExtent[5]=0;
+
+      this->BaseImageReslicer->SetOutputOrigin(this->BaseImageOrigin);
+      this->BaseImageReslicer->SetOutputSpacing(this->BaseImageSpacing);
+      this->BaseImageReslicer->SetOutputExtent(this->BaseImageExtent);
+
+
+      if (this->ImageSlice && this->AutoUpdate==1)
+	{
+	  this->BaseImageReslicer->Modified();
+	  UpdateSlice();
+	}
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::SetFrame(int frame)
+{
+  if (this->ColorMode==0)
+    {
+      frame=Irange(frame,0,this->NumberOfFrames-1);
+      this->Frame=frame;
+      
+      if (this->ImageComponentExtractor!=NULL)
+	{
+	  this->ImageComponentExtractor->SetComponents(this->Frame);
+	  this->ImageComponentExtractor->Update();
+	}
+      if (this->ImageSlice && this->AutoUpdate==1)
+	UpdateSlice();
+    }
+}
+
+void vtkpxObliqueImageSlice::SetColorMode(int cm)
+{
+  if (this->ColorMode!=cm)
+    {
+      this->ColorMode=(cm>0);
+      if (this->ImageComponentExtractor!=NULL)
+	{
+	  if (this->ColorMode)
+	    this->ImageComponentExtractor->SetComponents(0,1,2);
+	  else
+	    this->ImageComponentExtractor->SetComponents(this->Frame);
+	}
+      if (this->ImageSlice && this->AutoUpdate==1)
+	UpdateSlice();
+    }
+}
+
+//------------------------------------------------------------------------------
+
+
+void vtkpxObliqueImageSlice::UpdateTexture()
+{
+  if (!this->InputImage || !this->ImageSlice)
+      return;
+
+  this->ImageSlice->GetTexture()->Modified();
+  this->ImageSlice->Modified();
+}
+
+
+//------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::SetDisplayMode(int md)
+{
+  this->DisplayMode=md;
+  if (this->ImageSlice)
+    {
+      this->SetVisibility(1);
+      
+      if (this->DisplayMode==2 || this->DisplayMode==3)
+	this->ImageSlice->SetVisibility(1);
+      else
+	this->ImageSlice->SetVisibility(0);
+      
+      
+      if (this->DisplayMode==1 || this->DisplayMode==3)
+	this->ImageSliceOutline->SetVisibility(1);
+      else
+	this->ImageSliceOutline->SetVisibility(0);
+      
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::BuildImageSlice()
+{
+  if (this->ImageSliceOutline!=NULL)
+    return;
+
+  // Everything goes through this one 
+  this->ImageComponentExtractor=vtkImageExtractComponents::New();
+  this->ImageComponentExtractor->SetComponents(0);
+
+  this->ImagePlane=vtkPlaneSource::New();
+  this->ImagePlane->SetXResolution(2);//this->Resolution);
+  this->ImagePlane->SetYResolution(2);//this->Resolution);
+  this->ImagePlane->SetOrigin(-1.0,-1.0,0.0);
+  this->ImagePlane->SetPoint1(1.0,-1.0,0.0);
+  this->ImagePlane->SetPoint2(-1.0,1.0,0.0);
+  
+
+
+
+  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  // Outline
+  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  // Mapper 
+  vtkPolyDataMapper* mappd=vtkPolyDataMapper::New();
+  mappd->SetInput(this->ImagePlane->GetOutput());
+
+  // Actor
+  this->ImageSliceOutline=vtkActor::New();
+  this->ImageSliceOutline->PickableOff();
+  this->ImageSliceOutline->SetVisibility(0);
+  this->ImageSliceOutline->SetMapper(mappd);
+  this->ImageSliceOutline->GetProperty()->SetColor(0.5, 0.5, 0.0);
+  this->ImageSliceOutline->GetProperty()->SetRepresentationToWireframe();
+  this->ImageSliceOutline->GetProperty()->SetAmbient(1.0);
+  this->ImageSliceOutline->GetProperty()->SetDiffuse(0.0);
+  this->ImageSliceOutline->GetProperty()->SetSpecular(0.0);
+
+  mappd->Delete();   
+  
+  this->AddPart(ImageSliceOutline);
+
+
+  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  // Slice 
+  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+  this->BaseImageTransform=vtkTransform::New();
+
+  this->BaseImageReslicer=vtkbisImageReslice::New();
+  this->BaseImageReslicer->OptimizationOff();
+  this->BaseImageReslicer->SetOutputOrigin(this->BaseImageOrigin);
+  this->BaseImageReslicer->SetOutputSpacing(this->BaseImageSpacing);
+  this->BaseImageReslicer->SetOutputExtent(this->BaseImageExtent);
+  this->BaseImageReslicer->SetInput(this->ImageComponentExtractor->GetOutput());
+  this->BaseImageReslicer->SetResliceTransform(this->BaseImageTransform);
+  this->BaseImageReslicer->SetInterpolationModeToLinear();
+  
+  this->ImageTexture=vtkTexture::New();
+  this->ImageTexture->SetInput(this->BaseImageReslicer->GetOutput());
+
+  if (this->Interpolation==0)
+    this->ImageTexture->InterpolateOn();
+  else
+    this->ImageTexture->InterpolateOff();
+
+  this->ImageTexture->SetLookupTable(this->ColorMap);
+  this->ImageTexture->MapColorScalarsThroughLookupTableOn();
+  this->ImageTexture->RepeatOff();
+      
+  this->ImageMapper=vtkPolyDataMapper::New();
+  this->ImageMapper->SetInput(this->ImagePlane->GetOutput());
+
+  this->ImageSlice=vtkActor::New();
+  this->ImageSlice->SetMapper(this->ImageMapper);
+  this->ImageSlice->GetProperty()->SetOpacity(1.0);
+  this->ImageSlice->GetProperty()->SetInterpolationToFlat();
+  this->ImageSlice->SetTexture(this->ImageTexture);
+  
+  AddPart(this->ImageSlice);
+
+  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  // Arrow 
+  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+  this->ArrowSource=vtkConeSource::New();
+  this->ArrowSource->SetHeight(20.0);
+  this->ArrowSource->SetRadius(5.0);
+  this->ArrowSource->SetDirection(1,0,0);
+  this->ArrowSource->SetCenter(0,0,0);
+  this->ArrowSource->CappingOn();
+
+  vtkPolyDataMapper* map=vtkPolyDataMapper::New();
+  map->SetInput(this->ArrowSource->GetOutput());
+
+  this->NormalArrow=vtkActor::New();
+  this->NormalArrow->SetMapper(map); map->Delete();
+  this->NormalArrow->SetVisibility(this->ShowNormalArrow);
+  if (this->NormalArrowColor==0)
+    this->NormalArrow->GetProperty()->SetColor(1,0,0);
+  else
+    this->NormalArrow->GetProperty()->SetColor(0,1,0);
+  AddPart(this->NormalArrow);
+
+  
+  this->SetDisplayMode(this->DisplayMode);
+
+}
+//------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::SetShowNormalArrow(int a)
+{
+  this->ShowNormalArrow=(a>0);
+  this->NormalArrow->SetVisibility(this->ShowNormalArrow);
+  if (this->NormalArrowColor==0)
+    this->NormalArrow->GetProperty()->SetColor(1,0,0);
+  else
+    this->NormalArrow->GetProperty()->SetColor(0,1,0);
+
+  this->NormalArrow->Modified();
+}
+
+void vtkpxObliqueImageSlice::UpdateSlice()
+{
+  if (!this->BaseImageTransform)
+    return;
+
+  double f1[3]; this->ImagePlane->GetCenter(f1);
+  double n1[3]; this->ImagePlane->GetNormal(n1);
+  for (int ia=0;ia<=2;ia++)
+    f1[ia]=f1[ia]+0.5*n1[ia]*this->ArrowSource->GetHeight();
+  
+  this->ArrowSource->SetCenter(f1);
+  this->ArrowSource->SetDirection(n1);
+  this->ArrowSource->Update();
+
+  this->BaseImageReslicer->SetOutputOrigin(this->BaseImageOrigin);
+  this->BaseImageReslicer->SetOutputSpacing(this->BaseImageSpacing);
+  this->BaseImageReslicer->SetOutputExtent(this->BaseImageExtent);
+  this->BaseImageReslicer->Modified();
+  this->BaseImageReslicer->Update();
+
+  
+  if (this->ColorMode)
+    {
+
+      this->ImageTexture->SetLookupTable(NULL);
+      this->ImageTexture->MapColorScalarsThroughLookupTableOff();
+    }
+  else
+    {
+      this->ImageTexture->SetLookupTable(this->ColorMap);
+      this->ImageTexture->MapColorScalarsThroughLookupTableOn();
+    }
+
+
+  this->ImagePlane->Modified();
+  this->ImageSliceOutline->Modified();
+  this->ImageSliceOutline->GetMapper()->Modified();
+  this->ImageTexture->Modified();
+  this->Modified();
+  //  fprintf(stderr,"Oblique Slice --> Image Slice Updated %.2f,%.2f,%.2f\n",n1[0],n1[1],n1[2]);
+
+}
+// ------------------------------------------------------------------------------------------
+vtkImageData* vtkpxObliqueImageSlice::GetObliqueImage()
+{
+  if (this->BaseImageReslicer==NULL)
+    return NULL;
+
+  return this->BaseImageReslicer->GetOutput();
+}
+// ------------------------------------------------------------------------------------------
+vtkTransform* vtkpxObliqueImageSlice::GetObliqueTransform()
+{
+  if (this->BaseImageTransform==NULL)
+    return NULL;
+
+  return this->BaseImageTransform;
+}
+// ------------------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::GetImageRange(float bounds[6])
+{
+  if (this->ImageComponentExtractor==NULL)
+    {
+      for (int i=0;i<=2;i++)
+	{
+	  bounds[i*2]=0;
+	  bounds[i*2+1]=1;
+	}
+      return;
+    }
+
+  vtkImageData* img=(this->ImageComponentExtractor->GetOutput());
+
+  int dim[3]; img->GetDimensions(dim);
+  double spa[3]; img->GetSpacing(spa);
+  double ori[3]; img->GetOrigin(ori);
+  for (int i=0;i<=2;i++)
+    {
+      bounds[i*2]=ori[i];
+      bounds[i*2+1]=ori[i]+spa[i]*double(dim[i]-1);
+    }
+}
+
+// ------------------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::UpdateImagePlane(vtkCamera* camera,int mode)
+{
+  double c[3]; camera->GetPosition(c);
+  double f[3]; camera->GetFocalPoint(f);
+  double d[2]; camera->GetClippingRange(d);
+
+  double mid;
+
+  if (mode==0)
+    mid=0.5*(d[0]+d[1]);
+  else
+    mid=0.98*d[0]+0.02*d[1];
+
+
+  double n[3],magn=0.0;
+  for (int i=0;i<=2;i++)
+    {
+      n[i]=f[i]-c[i];
+      magn+=n[i]*n[i];
+    }
+  magn=sqrt(magn);
+
+  for (int j=0;j<=2;j++)
+    {
+      n[j]/=magn;
+      f[j]=c[j]+mid*n[j];
+    }
+
+  double f1[3]; this->ImagePlane->GetCenter(f1);
+  double n1[3]; this->ImagePlane->GetNormal(n1);
+
+  double dist=0.0;
+  for (int ia=0;ia<=2;ia++)
+    dist+=fabs(f1[ia]-f[ia])+10.0*fabs(n1[ia]-n[ia]);
+
+				  
+  if (dist>1e-3)
+    this->UpdateImagePlane(f[0],f[1],f[2],n[0],n[1],n[2]);
+
+  
+
+}
+
+//------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::Reset()
+{
+  if (this->ImageComponentExtractor==NULL)
+    return;
+
+  this->ImageComponentExtractor->Modified();
+  this->ImageComponentExtractor->Update();
+
+  vtkImageData* image=this->ImageComponentExtractor->GetOutput();
+
+  double sp[3];   image->GetSpacing(sp);
+  double ori[3];  image->GetOrigin(ori);
+  int  dim[3];   image->GetDimensions(dim);
+
+  for (int ka=0;ka<=2;ka++)
+    {
+      OutlineBounds[ka*2]=0.0;
+      OutlineBounds[ka*2+1]=(dim[ka]-1)*sp[ka]+ori[ka];
+    }
+ 
+  this->ImagePlane->SetOrigin(OutlineBounds[0],OutlineBounds[2],0.5*(OutlineBounds[4]+OutlineBounds[5]));
+  this->ImagePlane->SetPoint1(OutlineBounds[1],OutlineBounds[2],0.5*(OutlineBounds[4]+OutlineBounds[5]));
+  this->ImagePlane->SetPoint2(OutlineBounds[0],OutlineBounds[3],0.5*(OutlineBounds[4]+OutlineBounds[5]));
+
+  for (int ia=0;ia<=2;ia++)
+    this->Center[ia]=0.5*(OutlineBounds[ia*2]+OutlineBounds[ia*2+1]);
+  this->Distance=0.0;
+  this->Normal[0]=0.0;   this->Normal[1]=0.0;  this->Normal[2]=1.0; 
+
+  UpdateSlice();
+}
+// ------------------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::UpdateImagePlane(double dist,double n1,double n2,double n3)
+{
+  double magn=0.0;
+  this->Normal[0] = n1;  this->Normal[1] = n2; this->Normal[2]=n3;
+
+  for (int j=0;j<=2;j++)
+    magn+=this->Normal[j]*this->Normal[j];
+
+
+  magn=sqrt(magn);
+  if (magn==0.0)
+    {
+      this->Normal[0]=0; 
+      this->Normal[1]=0; 
+      this->Normal[2]=1.0;
+    } 
+  else
+    {
+      for (int j=0;j<=2;j++)
+	this->Normal[j]=this->Normal[j]/magn;
+    }
+
+  this->Distance=dist;
+
+  for (int ia=0;ia<=2;ia++)
+    this->Center[ia]=0.5*(OutlineBounds[ia*2]+OutlineBounds[ia*2+1])+this->Distance*this->Normal[ia];
+  
+
+
+  this->InternalUpdatePlane();
+}
+
+// ------------------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::UpdateImagePlane(double x1,double y1,double z1,
+					      double n1,double n2,double n3)
+{
+  this->Normal[0] = n1;  this->Normal[1] = n2; this->Normal[2]=n3;
+  this->Center[0]=  x1;  this->Center[1]=  y1; this->Center[2]=z1;
+
+  this->Distance=sqrt(pow( this->Center[0] - 0.5*(OutlineBounds[0]+OutlineBounds[1]),2.0)+
+		      pow( this->Center[1] - 0.5*(OutlineBounds[2]+OutlineBounds[3]),2.0)+
+		      pow( this->Center[2] - 0.5*(OutlineBounds[4]+OutlineBounds[5]),2.0));
+		      
+
+
+  double magn=0.0;
+  for (int j=0;j<=2;j++)
+    magn+=this->Normal[j]*this->Normal[j];
+
+  magn=sqrt(magn);
+  if (magn==0.0)
+    {
+      this->Normal[0]=0; 
+      this->Normal[1]=0; 
+      this->Normal[2]=1.0;
+    } 
+  else
+    {
+      for (int j=0;j<=2;j++)
+	this->Normal[j]=this->Normal[j]/magn;
+
+    }
+  
+  this->InternalUpdatePlane();
+}
+// ------------------------------------------------------------------------------------------
+void vtkpxObliqueImageSlice::InternalUpdatePlane()
+{
+  if (!this->ImagePlane)
+    return;
+
+  double thisn[3];   thisn[0]=0; thisn[1]=0; thisn[2]=1.0;
+  
+  // Compute rotation vector using a transformation matrix.
+  // Note that if normals are parallel then the rotation is either
+  // 0 or 180 degrees.
+  //double dp = vtkMath::Dot(this->Normal,thisn);
+  double dp=this->Normal[2];
+  
+  double p0[3],p1[3],p2[3];
+  this->InitialPoints->GetPoint(0,p0);
+  this->InitialPoints->GetPoint(1,p1);
+  this->InitialPoints->GetPoint(2,p2);
+  double theta=0.0,rotVector[3],center[3];
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      rotVector[ia]=p1[ia]-p0[ia];
+      center[ia]=0.5*(OutlineBounds[ia*2]+OutlineBounds[ia*2+1]);
+    }
+      
+ 
+  if ( dp >= 1.0 )
+    {
+      theta=0.0;
+    }
+  else if ( dp <= -1.0 )
+    {
+      theta = 180.0;
+    }
+  else
+    {
+      vtkMath::Cross(thisn,(double*)this->Normal,rotVector);
+#if ((VTK_MAJOR_VERSION >= 5)&&(VTK_MINOR_VERSION >= 4))
+      theta = vtkMath::DegreesFromRadians(acos((double)dp));
+#else
+      theta = acos((double)dp) / vtkMath::DoubleDegreesToRadians();
+#endif
+
+    }
+
+  // create rotation matrix
+  this->BaseImageTransform->Identity();
+  this->BaseImageTransform->PostMultiply();
+  this->BaseImageTransform->Translate(-center[0],-center[1],-center[2]);
+  this->BaseImageTransform->RotateWXYZ(theta,rotVector[0],rotVector[1],rotVector[2]);
+  this->BaseImageTransform->Translate(this->Center[0],this->Center[1],this->Center[2]);
+  this->BaseImageTransform->TransformPoint(p0,p0); this->ImagePlane->SetOrigin(p0);
+  this->BaseImageTransform->TransformPoint(p1,p1); this->ImagePlane->SetPoint1(p1);
+  this->BaseImageTransform->TransformPoint(p2,p2); this->ImagePlane->SetPoint2(p2);
+  this->ImagePlane->Modified();
+
+  this->UpdateSlice(); 
+}
+// ------------------------------------------------------------------------------------------
+
+vtkImageData* vtkpxObliqueImageSlice::GetMaskImage(vtkImageData* input,int above,int binary)
+{
+  if (input==NULL)
+    return NULL;
+
+  float abv=-1.0;
+  if (above>0)
+    abv=1.0;
+  binary=(binary>0);
+
+  //  fprintf(stderr,"Above = %.2f binary=%d\n",abv,binary);
+
+  double c[3]; ImagePlane->GetCenter(c);
+  //  fprintf(stderr,"C=%.2f,%.2f,%.2f\n",c[0],c[1],c[2]);
+  double n[3]; ImagePlane->GetNormal(n);
+
+  vtkImageData* img=vtkImageData::New();
+  img->CopyStructure(input);
+  img->SetNumberOfScalarComponents(input->GetNumberOfScalarComponents());
+  if (binary)
+    {
+      img->SetNumberOfScalarComponents(1);
+      img->SetScalarTypeToChar();
+    }
+  img->AllocateScalars();
+
+  int np=img->GetNumberOfPoints();
+  int nc=img->GetNumberOfScalarComponents();
+  vtkDataArray* data=img->GetPointData()->GetScalars();
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  for (int i=0;i<nc;i++)
+    data->FillComponent(i,0.0);
+
+  for (int i=0;i<np;i++)
+    {
+      double x[3];
+      img->GetPoint(i,x);
+      double sum=0.0;
+      for (int ia=0;ia<=2;ia++)
+	sum+= (x[ia]-c[ia])*n[ia];
+
+      if (sum*abv>0)
+	{
+	  if (binary)
+	    {
+	      data->SetComponent(i,0,1);
+	    }
+	  else
+	    {
+	      for (int c=0;c<nc;c++)
+		data->SetComponent(i,c,inp->GetComponent(i,c));
+	    }
+	}
+    }
+  return img;
+}
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxObliqueImageSlice.h b/bioimagesuite30_src/Graphics/vtkpxObliqueImageSlice.h
new file mode 100644
index 0000000..e3e69c5
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxObliqueImageSlice.h
@@ -0,0 +1,211 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxObliqueImageSlice.h,v $
+  Language:  C++
+  Date:      $Date: 2004/03/19 14:14:45 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+// .NAME vtkpxObliqueImageSlice - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkpxObliqueImageSlice_h
+#define __vtkpxObliqueImageSlice_h
+
+#include "vtkpxEnclosedPipeline.h"
+#include "vtkImageData.h"
+
+
+#include "vtkbisImageReslice.h"
+#include "vtkTransform.h"
+#include "vtkTexture.h"
+#include "vtkLookupTable.h"
+#include "vtkPlaneSource.h"
+#include "vtkCubeSource.h"
+#include "vtkProperty.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkCamera.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkConeSource.h"
+
+class vtkpxObliqueImageSlice : public vtkpxEnclosedPipeline
+{
+public:
+  static vtkpxObliqueImageSlice *New();
+  vtkTypeMacro(vtkpxObliqueImageSlice,vtkpxEnclosedPipeline);
+
+  // Description:
+  // Add a part to the list of parts.
+
+  virtual void SetInput(vtkImageData* image);
+  virtual void SetLookupTable(vtkLookupTable* table);
+
+  virtual void SetInterpolation(int on);
+  virtual void SetOpacity(double opacity);
+  virtual void SetFrame(int frame);
+  virtual void SetResolution(int frame);
+
+  // If 1 -> Ignore lookup table and render directly
+  virtual void SetColorMode(int mode);
+
+  virtual void UpdateImagePlane(double dist,double n1,double n2,double n3);
+  virtual void UpdateImagePlane(double x1,double y1,double z1,
+				double n1,double n2,double n3);
+  virtual void UpdateImagePlane(vtkCamera* camera,int mode=0);
+  
+  virtual void SetDisplayMode(int md);
+
+  virtual vtkImageData* GetMaskImage(vtkImageData* input,int above,int binary);
+
+  // Description:
+  // Internal Stuff
+  virtual vtkImageData* GetObliqueImage();
+  virtual vtkTransform* GetObliqueTransform();
+
+  vtkGetMacro(Frame,int);
+  vtkGetMacro(NumberOfFrames,int);
+
+  vtkGetMacro(DisplayMode,int);
+  vtkGetMacro(Opacity,double);
+  vtkGetMacro(Interpolation,int);
+
+  vtkGetObjectMacro(ImagePlane,vtkPlaneSource);
+  vtkGetObjectMacro(InputImage,vtkImageData);
+
+  
+  vtkGetMacro(OwnsColorMap,int);
+
+  vtkSetClampMacro(AutoUpdate,int,0,1);
+  vtkGetMacro(AutoUpdate,int);
+  vtkBooleanMacro(AutoUpdate,int);
+
+  virtual void SetShowNormalArrow(int a);
+  vtkGetMacro(ShowNormalArrow,int);
+
+  vtkSetClampMacro(NormalArrowColor,int,0,1);
+  vtkGetMacro(NormalArrowColor,int);
+
+
+  virtual void Update() { this->UpdateSlice();}
+  virtual void UpdateTexture();
+  virtual void Reset();
+
+  virtual void GetImageRange(float bounds[6]);
+
+  vtkGetMacro(Distance,double);
+  vtkGetVectorMacro(Center,double,3);
+  vtkGetVectorMacro(Normal,double,3);
+
+  
+
+protected:
+
+  vtkActor*                    ImageSliceOutline;
+  vtkActor*                    ImageSlice;
+  vtkActor*                    NormalArrow;
+  int                          NormalArrowColor;
+  vtkPlaneSource*              ImagePlane;
+
+
+  vtkImageExtractComponents*   ImageComponentExtractor;
+  vtkPolyDataMapper*           ImageMapper;
+  vtkConeSource*               ArrowSource;
+
+  vtkTexture*                  ImageTexture;
+  double                       BaseImageOrigin[3];
+  double                       BaseImageSpacing[3];
+  int                          BaseImageExtent[6];
+
+
+  vtkbisImageReslice*             BaseImageReslicer;
+  vtkTransform*                BaseImageTransform;
+  vtkImageData*                InputImage;
+
+  int                          Frame;
+  int                          Resolution;
+  int                          NumberOfFrames;
+
+  float                        OutlineBounds[6];
+  vtkPoints*                   InitialPoints;
+
+  double                       Opacity;
+  int                          Interpolation;
+  int                          DisplayMode;
+  int                          AutoUpdate;
+  int                          ShowNormalArrow;
+
+  vtkLookupTable*              ColorMap;
+  int                          OwnsColorMap;   
+  int                          ColorMode;
+
+  double                        Center[3];
+  double                        Normal[3];
+  double                        Distance;
+
+  vtkpxObliqueImageSlice();
+  virtual ~vtkpxObliqueImageSlice();
+  vtkpxObliqueImageSlice(const vtkpxObliqueImageSlice&) {};
+  void operator=(const vtkpxObliqueImageSlice&) {};
+
+  // Slice Stuff
+  virtual void BuildImageSlice();
+  virtual void UpdateSlice();
+
+  virtual void InternalUpdatePlane();
+
+};
+
+
+#endif
+
+
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxOrthoImageSlice.cpp b/bioimagesuite30_src/Graphics/vtkpxOrthoImageSlice.cpp
new file mode 100644
index 0000000..12af9a3
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxOrthoImageSlice.cpp
@@ -0,0 +1,333 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxOrthoImageSlice.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxOrthoImageSlice.h"
+#include "vtkObjectFactory.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkpxColorMapUtil.h"
+
+
+//------------------------------------------------------------------------------
+vtkpxOrthoImageSlice* vtkpxOrthoImageSlice::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxOrthoImageSlice");
+  if(ret)
+    {
+    return (vtkpxOrthoImageSlice*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxOrthoImageSlice;
+}
+//------------------------------------------------------------------------------
+// Construct object with no children.
+vtkpxOrthoImageSlice::vtkpxOrthoImageSlice()
+{
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->ImageSlice[ia]=NULL;
+      this->Levels[ia]=-1;
+    }
+  this->Frame=-1;
+
+  this->PolarMode=0;
+  this->PolarMiddle=-1.0;
+ 
+
+  this->Opacity=1.0;            
+  this->Interpolation=0;      
+
+  this->ColorMap=NULL;           
+  this->ColorMode=0;
+  this->OwnsColorMap=1;   
+  
+  this->InputImage=NULL;
+
+  this->ColorMap=vtkLookupTable::New();
+  this->ColorMap->SetNumberOfTableValues(256);
+  this->ColorMap->SetTableRange(0,255);
+  this->DisplayMode=2;
+
+  
+  for (int i=0;i<=255;i++)
+    {
+      float v=float(i)/float(255.0);
+      this->ColorMap->SetTableValue(i,v,v,v,1.0);
+    }
+
+  this->AutoUpdate=1;
+}
+//------------------------------------------------------------------------------
+vtkpxOrthoImageSlice::~vtkpxOrthoImageSlice()
+{
+  for (int i=0;i<=2;i++)
+  if (this->ImageSlice[i])
+    this->ImageSlice[i]->Delete();
+  
+  if (this->OwnsColorMap)
+    {
+      if (this->ColorMap)
+	this->ColorMap->Delete();
+    }
+
+  if (this->InputImage)
+    this->InputImage->Delete();
+
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::SetInput(vtkImageData* image)
+{
+  if (image==NULL)
+    return;
+
+  if (this->InputImage==NULL)
+    this->InputImage=vtkImageData::New();
+
+  this->InputImage->ShallowCopy(image);
+  BuildSlices();
+  if (this->OwnsColorMap)
+    vtkpxColorMapUtil::AutoUpdateColormapRange(this->ColorMap,this->InputImage);
+  for (int i=0;i<=2;i++)
+    {
+      this->ImageSlice[i]->SetInput(this->InputImage);
+      this->ImageSlice[i]->SetPolarMode(this->PolarMode);
+      this->Levels[i]=this->ImageSlice[i]->GetLevel();
+    }
+  this->Frame=this->ImageSlice[0]->GetFrame();
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::SetLookupTable(vtkLookupTable* table)
+{
+  if (!table)
+      return;
+
+  if (table==this->ColorMap)
+      return;
+
+  if (this->OwnsColorMap)
+      {
+	this->ColorMap->Delete();
+	this->OwnsColorMap=0;
+      }
+
+  this->ColorMap=table;  
+  for (int i=0;i<=2;i++)
+    {
+      if (this->ImageSlice[i])
+	this->ImageSlice[i]->SetLookupTable(this->ColorMap);
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::SetDisplayMode(int md)
+{
+  this->DisplayMode=md;
+  int hide=0;
+
+  if (this->DisplayMode<0)
+    {
+      hide=1;
+      this->DisplayMode=abs(this->DisplayMode);
+    }
+  
+  for (int i=0;i<=2;i++)
+    {
+      if (this->ImageSlice[i])
+	{
+	  if (hide==0 || i==2)
+	    this->ImageSlice[i]->SetDisplayMode(this->DisplayMode);
+	  else
+	    this->ImageSlice[i]->SetDisplayMode(0);
+	}
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::SetInterpolation(int on)
+{
+  this->Interpolation=on>0;
+  for (int i=0;i<=2;i++)
+    {
+      if (this->ImageSlice[i])
+	this->ImageSlice[i]->SetInterpolation(this->Interpolation);
+    }
+
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::SetPolarMode(int mode)
+{
+  this->PolarMode=(mode>0);
+  for (int i=0;i<=2;i++)
+    {
+      if (this->ImageSlice[i])
+	this->ImageSlice[i]->SetPolarMode(this->PolarMode);
+    }
+
+}
+
+void vtkpxOrthoImageSlice::SetColorMode(int mode)
+{
+  this->ColorMode=(mode>0);
+  for (int i=0;i<=2;i++)
+    {
+      if (this->ImageSlice[i])
+	this->ImageSlice[i]->SetColorMode(this->ColorMode);
+    }
+
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::SetPolarMiddle(float middle)
+{
+  this->PolarMiddle=middle;
+  for (int i=0;i<=2;i++)
+    {
+      if (this->ImageSlice[i])
+	this->ImageSlice[i]->SetPolarMiddle(this->PolarMiddle);
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::SetOpacity(float opacity)
+{
+  this->Opacity=opacity;
+  if (this->Opacity<0.0)
+    this->Opacity=0.0;
+  else if (this->Opacity>1.0)
+    this->Opacity=1.0;
+
+  for (int i=0;i<=2;i++)
+    {
+      if (this->ImageSlice[i])
+	this->ImageSlice[i]->SetOpacity(this->Opacity);
+    }
+
+}
+//------------------------------------------------------------------------------ 
+void vtkpxOrthoImageSlice::SetLevelsFrame(int level1,int level2,int level3,int frame)
+{
+  int a=this->AutoUpdate;
+  if (a)
+    this->SetAutoUpdate(0);
+  this->SetFrame(frame);
+  if (a)
+    this->SetAutoUpdate(1);
+  this->SetLevels(level1,level2,level3);
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::SetFrame(int frame)
+{
+  for (int i=0;i<=2;i++)
+    {
+      if (this->ImageSlice[i])
+	this->ImageSlice[i]->SetFrame(frame);
+    }
+  if (this->ImageSlice[0])
+    this->Frame=this->ImageSlice[0]->GetFrame();
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::SetLevels(int level1,int level2,int level3)
+{
+  this->Levels[0]=level1;
+  this->Levels[1]=level2;
+  this->Levels[2]=level3;
+  
+  for (int i=0;i<=2;i++)
+    {
+      if (this->ImageSlice[i])
+	this->ImageSlice[i]->SetLevel(this->Levels[i]);
+    }
+
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::BuildSlices()
+{
+  for (int i=0;i<=2;i++)
+    {
+      if (!this->ImageSlice[i])
+	{
+	  this->ImageSlice[i]=vtkpxImageSlice::New();
+	  this->ImageSlice[i]->SetAutoUpdate(0);
+	  this->ImageSlice[i]->SetPolarMode(this->PolarMode);
+	  this->ImageSlice[i]->SetColorMode(this->ColorMode);
+	  this->ImageSlice[i]->SetCurrentPlane(i);
+	  this->ImageSlice[i]->SetLookupTable(this->ColorMap);
+	  this->ImageSlice[i]->SetAutoUpdate(this->AutoUpdate);
+	  this->AddPart(ImageSlice[i]);
+	}
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::Update()
+{
+  for (int i=0;i<=2;i++)
+    if (this->ImageSlice[i]!=NULL)
+      this->ImageSlice[i]->Update();
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::SetAutoUpdate(int a)
+{
+  this->AutoUpdate=(a>0);
+  for (int i=0;i<=2;i++)
+    if (this->ImageSlice[i]!=NULL)
+      this->ImageSlice[i]->SetAutoUpdate(this->AutoUpdate);
+}
+//------------------------------------------------------------------------------
+void vtkpxOrthoImageSlice::UpdateTexture()
+{
+  for (int i=0;i<=2;i++)
+    if (this->ImageSlice[i]!=NULL)
+      {
+	this->ImageSlice[i]->UpdateTexture();
+	this->ImageSlice[i]->Update();
+      }
+}
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxOrthoImageSlice.h b/bioimagesuite30_src/Graphics/vtkpxOrthoImageSlice.h
new file mode 100644
index 0000000..3299d16
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxOrthoImageSlice.h
@@ -0,0 +1,151 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxOrthoImageSlice.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxOrthoImageSlice - create hierarchies of actors
+// .SECTION Description
+#ifndef __vtkpxOrthoImageSlice_h
+#define __vtkpxOrthoImageSlice_h
+
+#include "vtkpxEnclosedPipeline.h"
+#include "vtkpxImageSlice.h"
+
+
+
+class vtkpxOrthoImageSlice : public vtkpxEnclosedPipeline
+{
+public:
+  static vtkpxOrthoImageSlice *New();
+  vtkTypeMacro(vtkpxOrthoImageSlice,vtkpxEnclosedPipeline);
+
+  // Description:
+  // Add a part to the list of parts.
+
+  virtual void SetInput(vtkImageData* image);
+
+  virtual void SetLookupTable(vtkLookupTable* table);
+  virtual void SetInterpolation(int on);
+  virtual void SetOpacity(float opacity);
+  virtual void SetLevels(int level1,int level2,int level3);
+  virtual void SetFrame(int frame);
+  virtual void SetLevelsFrame(int level1,int level2,int level3,int frame);
+  virtual void SetDisplayMode(int md);
+
+  // If 1 -> Ignore lookup table and render directly
+  virtual void SetColorMode(int mode);
+
+
+  vtkGetVectorMacro(Levels,int,3);
+  vtkGetMacro(Opacity,float);
+  vtkGetMacro(Interpolation,int);
+
+  vtkGetMacro(OwnsColorMap,int);
+  vtkGetMacro(DisplayMode,int);
+  vtkGetMacro(Frame,int);
+
+  virtual void SetPolarMode(int mode);
+  virtual void SetPolarMiddle(float polarmiddle=-1);
+
+  vtkGetMacro(PolarMode,int);
+  vtkGetMacro(PolarMiddle,float);
+
+
+  virtual vtkImageData* GetInput() { return InputImage;}
+  virtual vtkLookupTable*      GetColorMap() { return ColorMap;}
+
+  virtual void Update();
+  virtual void UpdateTexture();
+
+  // Auto Update Stuff -- pass to slices 
+  vtkGetMacro(AutoUpdate,int);
+  virtual void SetAutoUpdate(int a);
+  vtkBooleanMacro(AutoUpdate,int);
+
+
+protected:
+
+  vtkpxImageSlice*             ImageSlice[3];
+  int                          Levels[3];
+  int                          Frame;
+
+  float                        Opacity;
+  int                          Interpolation;
+  int                          DisplayMode;
+
+  int                          PolarMode;
+  float                        PolarMiddle;
+  int                          AutoUpdate;
+  int                          ColorMode;
+
+  vtkImageData*         InputImage;
+  vtkLookupTable*              ColorMap;
+  int                          OwnsColorMap;   
+
+  vtkpxOrthoImageSlice();
+  virtual ~vtkpxOrthoImageSlice();
+
+  vtkpxOrthoImageSlice(const vtkpxOrthoImageSlice&) {};
+  void operator=(const vtkpxOrthoImageSlice&) {};
+
+  // Slice Stuff
+  virtual void BuildSlices();
+};
+
+
+#endif
+
+
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxPredictElectrodeStrip.cpp b/bioimagesuite30_src/Graphics/vtkpxPredictElectrodeStrip.cpp
new file mode 100644
index 0000000..165691f
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxPredictElectrodeStrip.cpp
@@ -0,0 +1,197 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+ This file is part of the PXTk library 
+
+ Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+ see vtkpxPredictElectrodeStrip.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+#include "vtkAppendPolyData.h"
+#include "vtkCellArray.h"
+#include "vtkUnsignedShortArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkpxPredictElectrodeStrip.h"
+#include "vtkpxElectrodeSource.h"
+#include "vtkCollection.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkShortArray.h"
+#include "vtkMath.h"
+#include "vtkFloatArray.h"
+#include "vtkThinPlateSplineTransform.h"
+//------------------------------------------------------------------------------
+vtkpxPredictElectrodeStrip* vtkpxPredictElectrodeStrip::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxPredictElectrodeStrip");
+  if(ret)
+    {
+      return (vtkpxPredictElectrodeStrip*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxPredictElectrodeStrip;
+}
+
+// Construct object with no children.
+vtkpxPredictElectrodeStrip::vtkpxPredictElectrodeStrip()
+{
+  this->Length=50.0;
+  this->Step=5.0;  
+  this->Point1[0]=1.0;  this->Point1[1]=1.0;  this->Point1[2]=1.0;
+  this->Point2[0]=0.8;  this->Point2[1]=0.8;  this->Point2[2]=0.8;
+  this->Input=NULL;
+  this->Smoothness=0.8;
+}
+
+/* -------------------------------------------------------------------------*/
+ 
+vtkpxPredictElectrodeStrip::~vtkpxPredictElectrodeStrip()
+{
+  this->SetInput(NULL);
+}
+/* -------------------------------------------------------------------------*/
+void vtkpxPredictElectrodeStrip::SetInputSurface(vtkPolyData* poly)
+{
+  this->SetInput(poly);
+  if (this->Input==NULL)
+    return;
+    
+  //  this->Input->BuildLinks();
+  //  this->Input->BuildCells();
+}
+
+/* -------------------------------------------------------------------------*/
+void vtkpxPredictElectrodeStrip::Execute()
+{
+  if (this->Input==NULL)
+    {
+      vtkErrorMacro(<<"No Input Surface, not executing\n");
+      return;
+    }
+
+
+  vtkPolyData* output = this->GetOutput();
+  vtkPoints*   points    = vtkPoints::New();
+  vtkPoints*   points2   = vtkPoints::New();
+
+  int maxpoints=int(this->Length/this->Step+1.5);
+  if (maxpoints<2)
+    maxpoints=2;
+  float spacing=this->Length/double(maxpoints-1);
+
+  //  fprintf(stderr,"Spacing=%.2f\n",spacing);
+
+  points->Allocate(maxpoints+1,10);
+
+  double Origin[3],Second[3],Direction[3];
+  for (int i=0;i<=2;i++)
+    Direction[i]=this->Point2[i]-this->Point1[i];
+  vtkMath::Normalize(Direction);
+  
+
+  int id=this->Input->FindPoint(this->Point1);
+  this->Input->GetPoint(id,Origin);
+
+  for (int ia=0;ia<=2;ia++)
+    Second[ia]=Origin[ia]+spacing*Direction[ia];
+
+  points->InsertNextPoint(Origin);
+  points->InsertNextPoint(Second);
+  
+  int numpoints=2,flag=1;
+
+  while (numpoints<maxpoints && flag==1)
+    {
+      // Insert Dummy Point
+      points->InsertNextPoint(0.0,0.0,0.0);
+      ++numpoints;
+      
+      // Reset First Point
+
+      for (int i=2;i<numpoints;i++)
+	{
+	  double p0[3]; points->GetPoint(i-2,p0);
+	  double p1[3]; points->GetPoint(i-1,p1);
+	  float d[3];
+	  for (int ia=0;ia<=2;ia++)
+	    d[ia]=p1[ia]-p0[ia];
+	  vtkMath::Normalize(d);
+	  for (int ia=0;ia<=2;ia++)
+	    p1[ia]+=d[ia]*spacing;
+
+	  int id=this->Input->FindPoint(p1);
+	  this->Input->GetPoint(id,p1);
+	  points->SetPoint(i,p1);
+	}
+
+      points2->DeepCopy(points);
+  
+      double off_w=(1.0-this->Smoothness);
+      
+      for (int i=2;i<numpoints;i++)
+	{
+	  double p[3],p1[3];
+	  points2->GetPoint(i, p);
+
+	  int im=i-1;
+	  points2->GetPoint(im,p1);
+	  
+	  for (int ia=0;ia<=2;ia++)
+	    p[ia]=off_w*p[ia]+this->Smoothness*(p1[ia]);
+	  
+	  int id=this->Input->FindPoint(p);
+	  this->Input->GetPoint(id,p);
+	  points->SetPoint(i,p);
+	}
+    }
+      
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  c_lines->Allocate(points->GetNumberOfPoints(),10);
+
+  for (int i=0;i<points->GetNumberOfPoints()-1;i++)
+    {
+      vtkIdType pt[2];
+      pt[0]=i; pt[1]=pt[0]+1;
+      c_lines->InsertNextCell(2,pt);
+    }
+
+  output->SetPoints(points); points->Delete();
+  output->SetLines(c_lines); c_lines->Delete();
+  points2->Delete();
+}
+
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxPredictElectrodeStrip.h b/bioimagesuite30_src/Graphics/vtkpxPredictElectrodeStrip.h
new file mode 100644
index 0000000..525e62a
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxPredictElectrodeStrip.h
@@ -0,0 +1,142 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxPredictElectrodeStrip.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxPredictElectrodeStrip - stores and manipulates a set of electrodes arranged as a grid
+// .SECTION Description
+// This class stores all the necesary information for an implanted Electrode Grid such as
+// width x height (in electrodes e.g. 8x8)
+// electrode spacing x,y
+// electrode type and dimensions
+// grid name
+// and finally an array of the actual electrodes
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkPoints vtkPolyData vtkPolyDataSource vtkpxElectrodeSource
+
+
+
+#ifndef __vtkpxPredictElectrodeStrip_h
+#define __vtkpxPredictElectrodeStrip_h
+
+
+#include "vtkPolyData.h"
+#include "vtkPolyDataSource.h"
+
+
+
+class vtkpxPredictElectrodeStrip : public vtkPolyDataSource 
+{
+public:
+  static vtkpxPredictElectrodeStrip *New();
+  vtkTypeMacro(vtkpxPredictElectrodeStrip,vtkPolyDataSource);
+
+public:
+
+  // Description:
+  // Grid Dimensions
+  vtkSetClampMacro(Length,float,2.0,200.0);
+  vtkGetMacro(Length,float);
+
+  // Description:
+  // Electrode Spacing
+  vtkGetMacro(Step,float);
+  vtkSetClampMacro(Step,float,1.0,50.0);
+
+  // Description:
+  // Electrode Spacing
+  vtkGetMacro(Smoothness,double);
+  vtkSetClampMacro(Smoothness,double,0.01,0.99);
+
+  // Description:
+  // Initial Points 1 & 2
+  vtkSetVectorMacro(Point1,double,3);
+  vtkGetVectorMacro(Point1,double,3);
+
+  vtkSetVectorMacro(Point2,double,3);
+  vtkGetVectorMacro(Point2,double,3);
+
+  // Description:
+  // Initial Points 1 & 2
+  vtkGetObjectMacro(Input,vtkPolyData);
+
+  // Description:
+  // Set Input Surface
+  virtual void SetInputSurface(vtkPolyData* poly);
+    
+protected:
+  vtkpxPredictElectrodeStrip();
+  virtual ~vtkpxPredictElectrodeStrip();
+
+  vtkpxPredictElectrodeStrip(const vtkpxPredictElectrodeStrip&) {};
+  void operator=(const vtkpxPredictElectrodeStrip&) {};
+  virtual void Execute();  
+
+  vtkSetObjectMacro(Input,vtkPolyData);
+
+
+  //BTX
+  float Length;
+  float Step;
+  double Smoothness;
+  double Point1[3];
+  double Point2[3];
+  vtkPolyData* Input;
+  //ETX
+
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxSurfaceUtil.cpp b/bioimagesuite30_src/Graphics/vtkpxSurfaceUtil.cpp
new file mode 100644
index 0000000..8ac871c
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxSurfaceUtil.cpp
@@ -0,0 +1,1596 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSurfaceUtil.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/07/15 12:58:44 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "pxcontour.h"
+#include "pxtriangulatedstack.h"
+#include "vtkAppendPolyData.h"
+#include "vtkCellArray.h"
+#include "vtkContourFilter.h"
+#include "vtkDataArray.h"
+#include "vtkFloatArray.h"
+#include "vtkImageCast.h"
+#include "vtkImageData.h"
+#include "vtkImageData.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageResample.h"
+#include "vtkImageThreshold.h"
+#include "vtkIntArray.h"
+#include "vtkLookupTable.h"
+#include "vtkMath.h"
+#include "vtkMatrix4x4.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointLocator.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataCollection.h"
+#include "vtkPolyDataNormals.h"
+#include "vtkSurfaceReconstructionFilter.h"
+#include "vtkpxAppendAndLabelPolyData.h"
+#include "vtkpxColorMapUtil.h"
+#include "vtkpxMath.h"
+#include "vtkpxSurfaceUtil.h"
+// ---------------------------
+
+std::string vtkpxSurfaceUtil::buffer="";
+
+vtkpxSurfaceUtil* vtkpxSurfaceUtil::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxSurfaceUtil");
+  if(ret)
+      {
+	return (vtkpxSurfaceUtil*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxSurfaceUtil;
+}
+
+
+// --------------------------------------------------------------------------------------
+//                      Surface Stuff
+// --------------------------------------------------------------------------------------
+
+void vtkpxSurfaceUtil::createsinglesection(vtkPolyData* sep,
+				    PXContour* c1,PXContour* c2,
+				    float z1,float z2,
+				    float du,int debug)
+{
+  sep->Initialize();
+  float z[2],*x[2],*y[2];
+  int np[2];
+  z[0]=z1; z[1]=z2;
+  np[0]=c1->getnumpoints();
+  np[1]=c2->getnumpoints();
+  PXContour* cn[2];
+  cn[0]=c1;
+  cn[1]=c2;
+
+  int c;
+  for (c=0;c<=1;c++)
+      {
+	PXContourPoint* pts=NULL;
+	PXContour* cntr=NULL;
+	if (du>0.01)
+	    {
+	      cntr=new PXContour(cn[c]); 
+	      cntr->Equispace(du);    
+	      pts=cntr->gettoppoint();
+	      np[c]=cntr->getnumpoints();
+	    }
+	else
+	    {
+	      pts=cn[c]->gettoppoint();
+	      np[c]=cn[c]->getnumpoints();
+	    }
+
+	x[c]=new float[np[c]]; 
+	y[c]=new float[np[c]];
+	
+	for(int i=0;i<np[c];i++)
+	    {
+	      x[c][i]=pts->x;  y[c][i]=pts->y;
+	      pts=pts->next;
+	    }
+	if (du>0.01)
+	    delete cntr;
+      }
+
+  // Add the Points 
+  vtkPoints    *c_points    = vtkPoints::New();
+  c_points->SetNumberOfPoints(np[0]+np[1]);
+
+
+  int index=0; 
+  for (c=0;c<=1;c++)
+      {
+	for(int i=0;i<np[c];i++)
+	    {
+	      c_points->SetPoint(index,x[c][i],y[c][i],z[c]);
+	      index++;
+	    }
+      }
+
+  int origin[2];
+  PXTriangulatedStack::findorigin2D(np,x,y,origin);
+  PXNeighboursList* facelist=new PXNeighboursList;
+  int numfaces=PXTriangulatedStack::triangulate2D(np,x,y,origin,facelist,9000);
+
+
+  // Add the Triangles 
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  c_lines->Allocate(numfaces,5);
+
+  vtkIdType indices[3];
+  facelist->Rewind();
+  for (int fc=0;fc<numfaces;fc++)
+      {
+	PXNeighboursNode* current=facelist->getcurrentnode();
+	PXIntegerList* list=(current->points);
+
+	list->Rewind();
+	indices[0]  =list->getcurrent();
+	list->Next();
+	indices[1]=list->getcurrent();
+	list->Next();
+	indices[2]=list->getcurrent();
+	c_lines->InsertNextCell(3,indices);
+	facelist->Next();
+      }
+
+  sep->SetPoints(c_points);
+  c_points->Delete();
+  sep->SetPolys(c_lines);
+  c_lines->Delete();
+
+  // Clean-up
+  for(c=0;c<=1;c++)
+      {
+	delete [] x[c];
+	delete [] y[c];
+      }
+  delete facelist;
+}
+// --------------------------------------------------------------
+void vtkpxSurfaceUtil::createsinglepolarsection(vtkPolyData* sep,PXContour* c1,PXContour* c2,
+					 float theta1,float theta2,float middlex,
+					 float du,int debug)
+{
+  sep->Initialize();
+  float *x[2],*y[2],*z[2],theta[2];
+  int np[2];
+  theta[0]=theta1*M_PI/180.0; 
+  theta[1]=theta2*M_PI/180.0;
+  np[0]=c1->getnumpoints();
+  np[1]=c2->getnumpoints();
+  PXContour* cn[2];
+  cn[0]=c1;
+  cn[1]=c2;
+  // fprintf(stderr,"[Ar: %d,%d" ,np[0],np[1]);
+  // Create Point Arrays 
+  // -------------------
+  int c;
+  for (c=0;c<=1;c++)
+      {
+	PXContourPoint* pts=NULL;
+	PXContour* cntr=NULL;
+	if (du>0.01)
+	    {
+	      cntr=new PXContour(cn[c]); 
+	      cntr->Equispace(du);    
+	      pts=cntr->gettoppoint();
+	      np[c]=cntr->getnumpoints();
+	    }
+	else
+	    {
+	      pts=cn[c]->gettoppoint();
+	      np[c]=cn[c]->getnumpoints();
+	    }
+	// fprintf(stderr,"Numpoints(%d) %d\n",c,np[c]);
+	x[c]=new float[np[c]]; 	y[c]=new float[np[c]];	z[c]=new float[np[c]];
+	
+	for(int i=0;i<np[c];i++)
+	    {
+	      float r=(pts->x-middlex);
+	      x[c][i]=(middlex+r*cos(theta[c]));
+	      y[c][i]=(middlex+r*sin(theta[c]));
+	      z[c][i]=pts->y;
+	      pts=pts->next;
+	    }
+	if (du>0.01)
+	    delete cntr;
+      }
+  
+
+  // Add Points To Scene 
+  // -------------------
+  int index=0; 
+  vtkPoints    *c_points    = vtkPoints::New();
+  c_points->SetNumberOfPoints(np[0]+np[1]);
+
+  for (c=0;c<=1;c++)
+      {
+	for(int i=0;i<np[c];i++)
+	    {
+	      c_points->SetPoint(index,x[c][i],y[c][i],z[c][i]);
+	      index++;
+	    }
+      }
+
+  // Clean-up
+  // Find Triangulation
+  // ------------------
+  int origin[2];
+  PXTriangulatedStack::findorigin(np,x,y,z,origin);
+  PXNeighboursList* facelist=new PXNeighboursList;
+  int numfaces=PXTriangulatedStack::triangulate(np,x,y,z,origin,facelist,9000);
+
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  c_lines->Allocate(numfaces,5);
+
+  vtkIdType indices[3];
+  facelist->Rewind();
+
+  for (int fc=0;fc<numfaces;fc++)
+      {
+	PXNeighboursNode* current=facelist->getcurrentnode();
+	PXIntegerList* list=(current->points);
+	list->Rewind();
+
+	indices[0]  =list->getcurrent();
+	list->Next();
+	indices[1]=list->getcurrent();
+	list->Next();
+	indices[2]=list->getcurrent();
+	c_lines->InsertNextCell(3,indices);
+	facelist->Next();
+      }
+
+  sep->SetPoints(c_points);
+  c_points->Delete();
+  sep->SetPolys(c_lines);
+  c_lines->Delete();
+
+  for(c=0;c<=1;c++)
+      {
+	delete [] x[c];
+	delete [] y[c];
+	delete [] z[c];
+      }
+
+  delete facelist;
+}
+
+void vtkpxSurfaceUtil::createsection(PXContourStack* stack,vtkPolyData* grp,
+			      int polar,float middlex,
+			      int begin,int end)
+{
+  if (begin<0) begin=0;
+  if (end>stack->getnumcontours()-1)
+      end=stack->getnumcontours()-1;
+
+  if (end<begin)
+      return;
+
+  vtkPolyDataCollection* collection=vtkPolyDataCollection::New();
+  
+  for (int i=begin;i<end;i++)
+      {
+	vtkPolyData* polydata=vtkPolyData::New();
+	if (!polar)
+	    vtkpxSurfaceUtil::createsinglesection(polydata,
+					   stack->getcontour(i),stack->getcontour(i+1),
+					   stack->getzlevel(i),stack->getzlevel(i+1),0.0,1);
+	else
+	    vtkpxSurfaceUtil::createsinglepolarsection(polydata,
+						stack->getcontour(i),stack->getcontour(i+1),
+						stack->getzlevel(i),stack->getzlevel(i+1),
+						middlex,0.0,1);
+	collection->AddItem(polydata);
+	polydata->Delete();
+      }
+
+  vtkAppendPolyData* append=vtkAppendPolyData::New();
+  collection->InitTraversal();
+  for (int j=0;j<collection->GetNumberOfItems();j++)
+      append->AddInput(collection->GetNextItem());
+
+  append->Update();
+  grp->CopyStructure(append->GetOutput());
+  append->Delete();
+  collection->Delete();
+}
+
+
+void vtkpxSurfaceUtil::drawtstack(vtkPolyData* surface,PXTriangulatedStack* tstack)
+{
+  if (tstack==NULL || surface==NULL)
+      return;
+
+  surface->Initialize();
+
+  vtkPoints *points = vtkPoints::New();
+  points->SetNumberOfPoints(tstack->getnumpoints());
+  
+  vtkCellArray *polys = vtkCellArray::New();
+
+  int i;
+  for (i=0; i<tstack->getnumpoints(); i++) 
+      {
+	PXTriangulatedStackPoint* pt=tstack->getpoint(i);
+	points->SetPoint(i,pt->x);
+      }
+  for (i=0; i<tstack->getnumtriangles(); i++) 
+      {
+	PXTriangle* tri=tstack->gettriangle(i);
+	vtkIdType pp[3];
+	for (int ia=0;ia<=2;ia++)
+	  pp[ia]=tri->p[ia];
+
+	polys->InsertNextCell(3,pp);
+      }
+  
+  surface->SetPoints(points);
+  points->Delete();
+  surface->SetPolys(polys);
+  polys->Delete();
+  
+
+}
+
+//------------------------------------------------------------------------
+// Parse Object Maps
+//------------------------------------------------------------------------
+int vtkpxSurfaceUtil::ObjectMapToPolyData(vtkImageData* image,vtkPolyData* poly)
+{
+  return vtkpxSurfaceUtil::ObjectMapToPolyData(image,poly,-1,-1);
+}
+//------------------------------------------------------------------------
+int vtkpxSurfaceUtil::ObjectMapToPolyData(vtkImageData* image,vtkPolyData* poly,
+					  int minobj,int maxobj,double gaussianxy,double gaussianz, double resample)
+{
+
+  //  fprintf(stderr,"Gaussian=%f resample=%f\n",gaussian,resample);
+
+  if (image==NULL || poly==NULL)
+    return 0;
+ 
+  double range[2];
+  image->GetPointData()->GetScalars()->GetRange(range);
+  double sp[3];image->GetSpacing(sp);
+  
+  if (minobj==-1)
+    minobj=(int)range[0];
+  if (maxobj==-1)
+    maxobj=(int)range[1];
+
+  if (maxobj<minobj)
+    {
+      int a=minobj;
+      minobj=maxobj;
+      maxobj=a;
+    }
+  minobj=Irange(minobj,1,(int)range[1]);
+  maxobj=Irange(maxobj,1,(int)range[1]);
+
+  vtkpxAppendAndLabelPolyData* append=vtkpxAppendAndLabelPolyData::New();
+  append->UserManagedInputsOn();
+  append->SetNumberOfInputs(maxobj-minobj+1);
+
+  resample=Frange(resample,1.0,5.0);
+  gaussianxy=Frange(gaussianxy,0.0,10.0);
+  gaussianz=Frange(gaussianz,0.0,10.0);
+
+  vtkImageCast* cast=vtkImageCast::New();
+  cast->SetInput(image);
+  cast->SetOutputScalarTypeToFloat();
+  cast->Update();
+
+
+  for (int level=minobj;level<=maxobj;level++)
+    {
+      double lowt=double(level)-0.5;
+      double hight=double(level)+0.5;
+      
+      //      fprintf(stderr,"level = %d lowt=%.2f hight=%.2f\n",level,lowt,hight);
+
+      vtkImageThreshold* thr=vtkImageThreshold::New();
+      thr->SetInput(cast->GetOutput());
+      thr->ThresholdBetween(lowt,hight);
+      thr->ReplaceInOn();
+      thr->ReplaceOutOn();
+      thr->SetInValue(100.0);
+      thr->SetOutValue(0.0);
+      
+      vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+      smooth->SetInput(thr->GetOutput());
+      smooth->SetStandardDeviations(gaussianxy,gaussianxy,gaussianz);
+      
+      vtkImageResample* res=vtkImageResample::New();
+      res->InterpolateOn();
+      res->SetDimensionality(3);
+      for (int ib=0;ib<=2;ib++)
+	res->SetAxisOutputSpacing(ib,sp[ib]*resample);
+      res->SetInput(smooth->GetOutput());
+      res->Update();
+
+      vtkContourFilter* contFilt=vtkContourFilter::New();
+      contFilt->SetInput(res->GetOutput());
+      contFilt->SetNumberOfContours(1);
+      contFilt->SetValue(0,50.0);
+      contFilt->ComputeScalarsOff();
+      contFilt->ComputeGradientsOff();
+      contFilt->ComputeNormalsOff();
+      contFilt->Update();
+
+      append->SetInputByNumber(level-minobj,contFilt->GetOutput());
+      contFilt->Delete();
+      res->Delete();
+      smooth->Delete();
+      thr->Delete();
+    }
+
+  append->Update();
+  cast->Delete();
+  poly->CopyStructure(append->GetOutput());
+  poly->GetPointData()->PassData(append->GetOutput()->GetPointData());
+  append->Delete();
+  
+  return 1;
+}
+//------------------------------------------------------------------------
+int vtkpxSurfaceUtil::MapScalarsToSurface(vtkPolyData* source,vtkPolyData* destination)
+{
+  if (source==NULL || destination==NULL)
+    return 0;
+
+  if (destination->GetPoints()==NULL)
+    return 0;
+
+  if (source->GetPointData()==NULL)
+    return 0;
+
+  if (source->GetPointData()->GetScalars()==NULL)
+    return 0;
+	
+  vtkPointLocator* locator=vtkPointLocator::New();
+  locator->SetDataSet(source);
+  locator->BuildLocator();
+  
+  vtkDataArray* newPtScalars = vtkDataArray::CreateDataArray(source->GetPointData()->GetScalars()->GetDataType());
+  newPtScalars->SetNumberOfTuples(destination->GetPoints()->GetNumberOfPoints());
+  vtkIdList* idlist=vtkIdList::New();
+  idlist->SetNumberOfIds(destination->GetPoints()->GetNumberOfPoints());
+  
+  for (int i=0;i<destination->GetPoints()->GetNumberOfPoints();i++)
+    {
+      double x[3];
+      destination->GetPoints()->GetPoint(i,x);
+      int id=locator->FindClosestPoint(x);
+      if (id>=0)
+	idlist->SetId(i,id);
+      else
+	idlist->SetId(i,0);
+    }
+  
+  source->GetPointData()->GetScalars()->GetTuples(idlist,newPtScalars);
+
+  if (source->GetPointData()->GetScalars()->GetLookupTable()!=NULL)
+    newPtScalars->SetLookupTable(source->GetPointData()->GetScalars()->GetLookupTable());
+
+  destination->GetPointData()->SetScalars(newPtScalars);
+  newPtScalars->Delete();
+  idlist->Delete();
+  
+  return 1;
+
+}
+//------------------------------------------------------------------------
+
+int vtkpxSurfaceUtil::AddShapeIndexLookupTableToSurface(vtkPolyData* source)
+{
+  vtkLookupTable*cmap =vtkLookupTable::New();
+  cmap->SetNumberOfTableValues(256);
+  float numc=0.5*float(255);
+	  
+  for (int i=0;i<=255;i++)
+    {
+      float v=(float(i)-127.5)/numc;
+
+      if (v<-0.875)      { cmap->SetTableValue(i,0.0, 1.0 , 0.3,1.0); }
+      else if(v<-0.625) { cmap->SetTableValue(i,0.0, 1.0 , 0.6,1.0); }
+      else if(v<-0.375) { cmap->SetTableValue(i,0.0, 1.0 , 1.0,1.0); }
+      else if(v<-0.125) { cmap->SetTableValue(i,0.5, 1.0 , 1.0,1.0); }
+      else if(v<0.125)  { cmap->SetTableValue(i,1.0, 1.0 , 1.0,1.0); }
+      else if(v<0.375)  { cmap->SetTableValue(i,1.0, 1.0 , 0.5,1.0); }
+      else if(v<0.625)  { cmap->SetTableValue(i,1.0, 1.0 , 0.0,1.0); }
+      else if(v<0.875)  { cmap->SetTableValue(i,1.0, 0.65, 0.0,1.0); }
+      else              { cmap->SetTableValue(i,1.0, 0.41, 0.0,1.0); }
+    }
+
+  cmap->SetTableRange(-1.0,1.0);
+  source->GetPointData()->GetScalars()->SetLookupTable(cmap);
+  cmap->Delete();
+  return 1;
+}
+
+
+int vtkpxSurfaceUtil::AddCurvatureLookupTableToSurface(vtkPolyData* source)
+{
+  vtkLookupTable*cmap =vtkLookupTable::New();
+  vtkpxColorMapUtil::SetConstantHueColorMap(cmap,0.5,0.02,0.58,0.4,-0.4,0.4,256);
+  cmap->SetTableRange(-1.0,1.0);
+  source->GetPointData()->GetScalars()->SetLookupTable(cmap);
+  cmap->Delete();
+  return 1;
+}
+//------------------------------------------------------------------------
+int vtkpxSurfaceUtil::DefaultObjectMapLookupTableNumberOfColors() 
+{ 
+  return 120;
+}
+//------------------------------------------------------------------------
+int vtkpxSurfaceUtil::DefaultObjectMapLookupTable(vtkLookupTable* cmap,int num,int blackzero)
+{
+  static float stcolors [480] = {
+    0.000,0.000,0.000,0.200,
+    1.000,0.000,0.000,1.000,
+    1.000,0.620,0.000,1.000,
+    1.000,1.000,0.000,1.000,
+    0.000,1.000,0.000,1.000,
+    0.000,0.420,1.000,1.000,
+    0.823,0.623,0.792,1.000,
+    0.173,0.965,1.000,1.000,
+    0.525,0.431,0.000,1.000,
+    0.992,0.565,0.000,1.000,
+    0.400,0.004,0.400,1.000,
+    1.000,0.000,1.000,1.000,
+    1.000,0.643,1.000,1.000,
+    1.000,0.529,0.518,1.000,
+    0.514,0.075,0.192,1.000,
+    0.129,0.094,0.776,1.000,
+    0.639,0.510,1.000,1.000,
+    0.518,0.000,1.000,1.000,
+    0.016,0.251,0.910,1.000,
+    0.451,0.580,0.000,1.000,
+    0.514,0.012,0.000,1.000,
+    0.000,0.380,0.012,1.000,
+    0.000,0.000,0.463,1.000,
+    0.922,0.839,0.663,1.000,
+    1.000,0.275,0.000,1.000,
+    0.510,0.616,0.996,1.000,
+    0.643,0.086,0.431,1.000,
+    0.149,0.643,0.475,1.000,
+    0.639,0.455,0.016,1.000,
+    0.600,0.200,0.200,1.000,
+    0.922,0.106,0.808,1.000,
+    0.600,1.000,0.200,1.000,
+    0.200,0.600,0.200,1.000,
+    0.329,0.702,0.380,1.000,
+    0.996,0.753,0.996,1.000,
+    0.373,1.000,0.600,1.000,
+    0.247,0.757,0.200,1.000,
+    0.600,1.000,1.000,1.000,
+    0.000,0.600,0.600,1.000,
+    0.600,0.200,1.000,1.000,
+    0.753,0.576,0.267,1.000,
+    0.996,0.549,0.984,1.000,
+    0.600,0.867,0.749,1.000,
+    0.329,0.294,0.376,1.000,
+    0.569,0.706,0.847,1.000,
+    0.718,0.200,0.600,1.000,
+    0.965,0.592,0.949,1.000,
+    0.580,0.784,0.439,1.000,
+    0.733,0.094,0.361,1.000,
+    0.200,0.000,0.212,1.000,
+    0.612,0.392,0.392,1.000,
+    0.522,1.000,0.863,1.000,
+    0.835,0.851,0.482,1.000,
+    0.451,0.310,0.086,1.000,
+    0.243,0.286,0.631,1.000,
+    0.984,0.839,0.784,1.000,
+    0.239,0.655,0.216,1.000,
+    0.200,0.400,0.400,1.000,
+    0.800,0.420,0.400,1.000,
+    0.800,0.600,0.400,1.000,
+    0.400,0.200,0.400,1.000,
+    0.529,0.302,0.580,1.000,
+    0.988,0.612,0.000,0.988,
+    0.988,0.988,0.000,0.988,
+    0.000,0.988,0.000,0.988,
+    0.129,0.498,0.773,0.988,
+    0.604,0.596,0.604,0.988,
+    0.173,0.957,0.988,0.988,
+    0.639,0.553,0.000,0.988,
+    0.988,0.988,0.988,0.988,
+    0.396,0.396,0.396,0.988,
+    0.988,0.000,0.988,0.988,
+    0.988,0.635,0.988,0.988,
+    0.000,0.529,0.545,0.988,
+    0.988,0.659,0.545,0.988,
+    0.129,0.094,0.769,0.988,
+    0.631,0.506,0.988,0.988,
+    0.514,0.000,0.988,0.988,
+    0.576,0.988,0.510,0.988,
+    0.447,0.576,0.000,0.988,
+    0.510,0.012,0.000,0.988,
+    0.000,0.376,0.012,0.988,
+    0.000,0.000,0.459,0.988,
+    0.914,0.831,0.655,0.988,
+    0.988,0.271,0.000,0.988,
+    0.247,0.110,0.482,0.988,
+    0.635,0.086,0.427,0.988,
+    0.149,0.635,0.471,0.988,
+    0.631,0.451,0.016,0.988,
+    0.592,0.196,0.196,0.988,
+    0.592,0.812,0.196,0.988,
+    0.592,0.988,0.196,0.988,
+    0.196,0.592,0.196,0.988,
+    0.325,0.694,0.376,0.988,
+    0.208,0.796,0.804,0.988,
+    0.369,0.988,0.592,0.988,
+    0.243,0.749,0.196,0.988,
+    0.592,0.988,0.988,0.988,
+    0.000,0.592,0.592,0.988,
+    0.592,0.196,0.988,0.988,
+    0.592,0.835,0.988,0.988,
+    0.196,0.725,0.149,0.988,
+    0.592,0.859,0.741,0.988,
+    0.325,0.290,0.373,0.988,
+    0.831,0.702,0.592,0.988,
+    0.710,0.196,0.592,0.988,
+    0.773,0.592,0.706,0.988,
+    0.643,0.180,0.196,0.988,
+    0.114,0.208,0.196,0.988,
+    0.196,0.000,0.208,0.988,
+    0.196,0.196,0.063,0.988,
+    0.518,0.988,0.855,0.988,
+    0.592,0.471,0.196,0.988,
+    0.447,0.306,0.086,0.988,
+    0.239,0.282,0.624,0.988,
+    0.345,0.239,0.667,0.988,
+    0.235,0.647,0.212,0.988,
+    0.196,0.396,0.396,0.988,
+    0.792,0.416,0.396,0.988,
+    0.792,0.592,0.396,0.988};
+
+
+  if (num<0)
+    num=vtkpxSurfaceUtil::DefaultObjectMapLookupTableNumberOfColors();
+
+  int maxcolor=120;
+  blackzero=(blackzero>0);
+
+
+  cmap->SetNumberOfTableValues(num);
+  cmap->SetTableRange(0,num-1);
+  float numc=float(cmap->GetNumberOfColors());
+  //  fprintf(stderr,"NUMC = %f blackzero=%d\n",numc,blackzero);
+
+  for (int i=blackzero;i<cmap->GetNumberOfColors();i++)
+    {
+      if (i<maxcolor)
+	{
+	  cmap->SetTableValue(i,stcolors[i*4],stcolors[i*4+1],stcolors[i*4+2],stcolors[i*4+3]);
+	}
+      else
+	{
+	  int sc=int(i/60);
+	  int sh=i-sc*60;
+	  double vv[4];
+	  cmap->GetTableValue(sh,vv);
+	  for (int ia=0;ia<sc;ia++)
+	    for (int ib=0;ib<=3;ib++)
+	      vv[ib]=0.99*vv[ib];
+	  cmap->SetTableValue(i,vv);
+	}
+    }
+  if (blackzero)
+    cmap->SetTableValue(0,0.0,0.0,0.0,0.0);
+  return 1;
+}
+//------------------------------------------------------------------------
+int vtkpxSurfaceUtil::VOIObjectMapLookupTable(vtkLookupTable* cmap,int num)
+{
+  static float stcolors [60] = {
+    0.000 ,0.000 ,0.000,
+    1.000 ,0.412 ,1.000,
+    0.000 ,0.620 ,0.035,
+    0.173 ,0.965 ,1.000,
+    0.839 ,0.996 ,0.741,
+    0.000 ,1.000 ,0.000,
+    0.678 ,0.827 ,0.906,
+    1.000 ,0.486 ,0.451,
+    0.737 ,0.490 ,0.776,
+    0.973 ,1.000 ,0.776,
+    0.400 ,0.004 ,0.400,
+    0.518 ,0.451 ,0.318,
+    0.816 ,0.733 ,1.000,
+    0.878 ,0.733 ,0.518,
+    0.996 ,0.839 ,0.965,
+    0.765 ,0.765 ,0.000,
+    0.647 ,0.000 ,1.000,
+    0.518 ,0.000 ,0.000,
+    0.984 ,0.788 ,0.263,
+    0.000 ,0.580 ,0.612};
+
+  if (num<0)
+    num=vtkpxSurfaceUtil::DefaultObjectMapLookupTableNumberOfColors();
+
+  int maxcolor=20;
+  int blackzero=1;
+
+
+  cmap->SetNumberOfTableValues(num);
+  cmap->SetTableRange(0,num-1);
+
+  //  fprintf(stderr,"Num=%d\n",num);
+
+  float numc=float(cmap->GetNumberOfColors());
+
+
+  for (int i=blackzero;i<cmap->GetNumberOfColors();i++)
+    {
+      if (i<maxcolor)
+	{
+	  cmap->SetTableValue(i,stcolors[i*3],stcolors[i*3+1],stcolors[i*3+2],1.0);
+	}
+      else
+	{
+	  int sc=int(i/60);
+	  int sh=i-sc*60;
+	  double vv[4];
+	  cmap->GetTableValue(sh,vv);
+	  for (int ia=0;ia<sc;ia++)
+	    for (int ib=0;ib<=3;ib++)
+	      vv[ib]=0.99*vv[ib];
+	  cmap->SetTableValue(i,vv);
+	}
+    }
+  if (blackzero)
+    cmap->SetTableValue(0,0.0,0.0,0.0,0.0);
+  return 1;
+}
+//------------------------------------------------------------------------
+
+int vtkpxSurfaceUtil::AddObjectMapLookupTableToSurface(vtkPolyData* source)
+{
+  if (source==NULL)
+    return 0;
+
+  if (source->GetPointData()==NULL)
+    return 0;
+
+  if (source->GetPointData()->GetScalars()==NULL)
+    return 0;
+
+
+  double range[2];
+  source->GetPointData()->GetScalars()->GetRange(range);
+  if (range[1]==range[0])
+    range[1]+=1.0;
+
+  int num=int(range[1]-range[0])+1;
+  vtkLookupTable*cmap =vtkLookupTable::New();
+  vtkpxSurfaceUtil::DefaultObjectMapLookupTable(cmap,num);
+  cmap->SetTableRange(range[0],range[1]);
+
+  source->GetPointData()->GetScalars()->SetLookupTable(cmap);
+  cmap->Delete();
+  return 1;
+}
+//--------------------------------------------------------------------------------------
+int vtkpxSurfaceUtil::AddObjectLabelsToSurface(vtkPolyData* source,int offset)
+{
+  if (source==NULL)
+    return 0;
+
+  if (source->GetPointData()==NULL)
+    return 0;
+
+  int useold=0;
+
+  int out_offset=1;
+
+  vtkDataArray* oldScalars=source->GetPointData()->GetScalars();
+
+  if (offset >=0 ) 
+    {
+      if (oldScalars!=NULL)
+	{
+	  double range[2];
+	  oldScalars->GetRange(range);
+	  out_offset+=(int)range[1];
+	  useold=1;
+	}
+    }
+  else 
+    {
+      offset=-offset;
+      useold=0;
+    }
+
+  vtkDataArray* ptScalars=vtkDataArray::CreateDataArray(VTK_SHORT);
+  ptScalars->SetNumberOfComponents(1);
+  ptScalars->SetNumberOfTuples(source->GetPoints()->GetNumberOfPoints());
+  for (int i=0;i<ptScalars->GetNumberOfTuples();i++)
+    {
+      int old=0;
+      if (useold==1)
+	old=(int)oldScalars->GetComponent(i,0);
+      ptScalars->SetComponent(i,0,offset+old);
+    }
+  source->GetPointData()->SetScalars(ptScalars);
+  ptScalars->Delete();
+  return out_offset;
+
+}
+
+//--------------------------------------------------------------------------------------
+// Neighbours Stuff -- needed for curvature tracking etc 
+//--------------------------------------------------------------------------------------
+PXIntegerList* vtkpxSurfaceUtil::GenerateNeighbors(vtkPolyData* poly,int opensurface)
+{
+  static int debugmode=0;
+  vtkPoints* points=poly->GetPoints();
+  vtkCellArray* cells=poly->GetPolys();
+
+  int numpoints=points->GetNumberOfPoints();
+  int numtriangles=cells->GetNumberOfCells();
+
+  PXIntegerList* neighbours=new PXIntegerList[numpoints];
+
+  if (debugmode)
+    fprintf(stderr,"Generating Neighbours (pt=%d,tr=%d):: ",numpoints,numtriangles);
+  
+  opensurface=Irange(opensurface,0,1);
+
+  double bounds[6];
+  poly->GetBounds(bounds);
+
+  float bz=bounds[4]+0.002*(bounds[5]-bounds[4]);
+  float tz=bounds[5]-0.002*(bounds[5]-bounds[4]);
+  
+  cells->InitTraversal();
+  for (int tr=0;tr<numtriangles;tr++)
+    {
+      vtkIdType *cell,cellp;
+      cells->GetNextCell(cellp,cell);
+      for (int k=0;k<cellp;k++)
+	{
+	  int pt=cell[k];
+	  double x[3];
+	  points->GetPoint(pt,x);
+	  for (int j=0;j<cellp;j++)
+	    {
+	      int pt2=cell[j];
+	      if (pt2!=pt)
+		{
+		  double x2[3];
+		  points->GetPoint(pt2,x2);
+		  if (!opensurface)
+		    {
+		      neighbours[pt].AddNonDuplicate(pt2);
+		    }
+		  else
+		    {
+		      if (x[2]>=bz && x[2]<tz)
+			{
+			  neighbours[pt].AddNonDuplicate(pt2);
+			}
+		      else if (x[2]<bz && x2[2]<bz)
+			{
+			  neighbours[pt].AddNonDuplicate(pt2);
+			}
+		      else if (x[2]>tz && x2[2]>tz)
+			{
+			  neighbours[pt].AddNonDuplicate(pt2);
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+  return neighbours;
+}
+
+//--------------------------------------------------------------------------------------
+int vtkpxSurfaceUtil::CollectNeighbours(vtkPolyData* polydata,int point,int distance,PXIntegerList* list,
+					PXIntegerList* neighbours)
+{
+
+  list->DeleteAll();
+  distance=Irange(distance,0,10);
+
+  int numpoints=polydata->GetNumberOfPoints();
+
+  point=Irange(point,0,numpoints-1);
+  
+  neighbours[point].Rewind();
+  list->Add(point);
+  
+  if (distance==0)
+    return list->getnumnodes();
+
+  for (int i=0;i<neighbours[point].getnumnodes();i++)
+      {
+	list->Add(neighbours[point].getcurrent());
+	neighbours[point].Next();
+      }
+  
+  
+  if (distance==1)
+      return list->getnumnodes();
+      
+  int begin=1;
+  for (int sc=2;sc<=distance;sc++)
+      {
+	list->Rewind();
+	int end  =list->getnumnodes();
+	// Skip over previously examined points 
+	int k;
+	for (k=0;k<begin;k++)
+	  list->Next();
+	for (k=begin;k<end;k++)
+	  {
+	    int pt=list->getcurrent();
+	    neighbours[pt].Rewind();
+	    for (int i=0;i<neighbours[pt].getnumnodes();i++)
+	      {
+		list->AddNonDuplicate(neighbours[pt].getcurrent(),-1);
+		neighbours[pt].Next();
+	      }
+	  }
+	begin=end;
+      }
+  return list->getnumnodes();
+}
+//--------------------------------------------------------------------------------------
+
+int vtkpxSurfaceUtil::NonShrinkSmooth(vtkPolyData* poly,int opensurface,
+				      float alpha,float beta,int iterations,int movez)
+{
+  PXIntegerList* listn=vtkpxSurfaceUtil::GenerateNeighbors(poly,opensurface);
+  int ok=vtkpxSurfaceUtil::NonShrinkSmooth(poly,listn,alpha,beta,iterations,movez);
+  delete [] listn;
+  return ok;
+
+}
+int vtkpxSurfaceUtil::NonShrinkSmooth(vtkPolyData* poly,PXIntegerList* neighbours,
+				      float alpha,float beta,int iterations,int movez)
+{
+  int debugmode=0;
+  movez=Irange(movez,0,2);
+  
+  vtkPoints* points=poly->GetPoints();
+  vtkPoints* temp=vtkPoints::New();
+
+  
+  double bounds[6]; poly->GetBounds(bounds);
+  float minz=bounds[4];
+  float maxz=bounds[5];
+	      
+  if (debugmode)
+    fprintf(stderr,"Smoothing , iterations (movez=%d,alpha=%5.3f,beta=%5.3f,iter=%d): ",
+	    movez,alpha,beta,iterations);
+
+  for (int iter=1;iter<=iterations;iter++)
+      {
+	if (debugmode)
+	  {
+	    if (20*int(iter/20)==iter)
+	      fprintf(stderr,"%d ",iter);
+	  }
+	for(int pass=0;pass<=1;pass++)
+	  {
+	    temp->DeepCopy(points);
+	    for(int i=0;i<points->GetNumberOfPoints();i++)
+	      {
+		double oldx[3],newx[3];
+		temp->GetPoint(i,oldx);
+		
+		for (int ia=0;ia<=2;ia++)
+		  newx[ia]=0.0;
+		float total=0.0;
+		    
+		for(int j=0;j<(neighbours[i].getnumnodes());j++)
+		  {
+		    int p=neighbours[i].getcurrent();
+		    for (int ia=0;ia<=2;ia++)
+		      newx[ia]+=temp->GetPoint(p)[ia];
+		    total+=1.0;
+		    neighbours[i].Next();
+		  }
+		if (total>0.0)
+		  {
+		    for (int ia=0;ia<=2;ia++)
+		      newx[ia]=newx[ia]/total;
+		    float factor;
+		    if(pass==0)
+		      factor=alpha;
+		    else
+		      factor=beta;
+		    
+		    double newp[3];
+		    points->GetPoint(i,newp);
+		    for (int ib=0;ib<=1;ib++)
+		      newp[ib]=(1.0-factor)*oldx[ib]+factor*newx[ib];
+
+
+		    switch(movez)
+		      {
+		      case 1:
+			if (newp[2]>minz+0.01 && newp[2]<maxz-0.01)
+			  newp[2]=(1.0-factor)*oldx[2]+factor*newx[2];
+			break;
+		      case 2:
+			newp[2]=(1.0-factor)*oldx[2]+factor*newx[2];
+			break;
+		      }
+		    points->SetPoint(i,newp);
+		  }
+	      }
+	  }
+      }
+  temp->Delete();
+
+  if (debugmode)
+    fprintf(stderr,"\n");
+  return 1;
+}
+
+//------------------------------------------------------------------------------
+int vtkpxSurfaceUtil::CalculateCurvatures(vtkPolyData* polydata,int scale,PXIntegerList* neighbours)
+{
+  return vtkpxMath::CalculateCurvatures(polydata,scale,neighbours);
+}
+
+int vtkpxSurfaceUtil::CalculateCurvatures(vtkPolyData* polydata,int scale,int opensurface,int c_mode,float upper)
+{
+  PXIntegerList* listn=vtkpxSurfaceUtil::GenerateNeighbors(polydata,opensurface);
+  int ok=vtkpxSurfaceUtil::CalculateCurvatures(polydata,scale,listn);
+  delete [] listn;
+
+  vtkDataArray* dat=polydata->GetPointData()->GetScalars();
+  int nt=dat->GetNumberOfTuples();
+  float k[2];
+
+  vtkFloatArray* out=vtkFloatArray::New();
+  out->SetNumberOfTuples(nt);
+
+  if (c_mode==2)
+    upper*=upper;
+
+  float max=Frange(upper,0.01,10.0);
+  float min=-max;
+
+  float k0=2.0/M_PI;
+
+  for (int i=0;i<nt;i++)
+    {
+
+      for (int ia=0;ia<=1;ia++)
+	k[ia]=dat->GetComponent(i,ia);
+
+      float meancurv =0.5*(k[0]+k[1]);
+      float gausscurv=k[0]*k[1];
+
+      float shapeindex=0.0;
+      if(k[0]==k[1])
+	shapeindex=1;
+      else 
+	shapeindex=k0*atan2( k[0]+k[1] , k[0]-k[1] );
+		  
+      switch (c_mode)
+	{
+	case 0:
+	  out->SetComponent(i,0,shapeindex);
+	  break;
+	case 1:
+	  out->SetComponent(i,0,Frange(meancurv,min,max));
+	  break;
+	case 2:
+	  out->SetComponent(i,0,Frange(gausscurv,min,max));
+	  break;
+	case 4:
+	  out->SetComponent(i,0,Frange(k[1],min,max));
+	  break;
+	default:
+	  out->SetComponent(i,0,Frange(k[0],min,max));
+	  break;
+	}
+    }
+  polydata->GetPointData()->SetScalars(out);
+
+  if (c_mode==0)
+    vtkpxSurfaceUtil::AddShapeIndexLookupTableToSurface(polydata);
+  else
+    vtkpxSurfaceUtil::AddCurvatureLookupTableToSurface(polydata);
+  
+      
+  out->Delete();
+
+  return ok;
+}
+
+
+//------------------------------------------------------------------------------
+void vtkpxSurfaceUtil::ZeroAllDisplacements(vtkPolyData* poly,vtkFloatArray* displ)
+{
+  int num=poly->GetNumberOfPoints();
+  displ->SetNumberOfComponents(3);
+  displ->SetNumberOfTuples(num);
+  displ->FillComponent(0,0.0);
+  displ->FillComponent(1,0.0);
+  displ->FillComponent(2,0.0);
+
+}
+//------------------------------------------------------------------------------
+int vtkpxSurfaceUtil::AddToDisplacements(vtkPolyData* orig,vtkPolyData* targ,vtkFloatArray* displ)
+{
+  int np=orig->GetNumberOfPoints();
+  if (np!=targ->GetNumberOfPoints() || np!=displ->GetNumberOfTuples())
+    return 0;
+
+
+  vtkPoints* pt1=orig->GetPoints();
+  vtkPoints* pt2=targ->GetPoints();
+
+  double x1[3],x2[3];
+  for (int ia=0;ia<np;ia++)
+    {
+      pt1->GetPoint(ia,x1);
+      pt2->GetPoint(ia,x2);
+      for (int ib=0;ib<=2;ib++)
+	displ->SetComponent(ia,ib,displ->GetComponent(ia,ib)+x2[ib]-x1[ib]);
+    }
+
+  return 1;
+}
+//------------------------------------------------------------------------------
+int vtkpxSurfaceUtil::ShiftPointsByDisplacements(vtkPolyData* poly,vtkFloatArray* displ,float factor)
+{
+  vtkPoints* points=poly->GetPoints();
+  int np=displ->GetNumberOfTuples();
+  if (points->GetNumberOfPoints()!=np)
+    {
+      fprintf(stderr,"Bad Number of Displacements, cannot shift\n");
+      return 0;
+    }
+
+
+  for (int i=0;i<np;i++)
+    {
+      double x[3],tx[3];
+      points->GetPoint(i,x);
+      for (int ia=0;ia<3;ia++)
+	tx[ia]=x[ia]+displ->GetComponent(i,ia)*factor;
+      points->SetPoint(i,tx);
+    }
+  return 1;
+}
+//------------------------------------------------------------------------------
+void vtkpxSurfaceUtil::GetColor(int i,double c[3])
+{
+  i=Irange(i,0,12);
+  switch(i)
+    {
+    case 0:
+      c[0]=0.89;c[1]=0.09;c[2]=0.04;
+      break;
+    case 1:
+      c[0]=0.925;c[1]=0.957;c[2]=0.329;
+      break;
+    case 2:
+      c[0]=0.188;c[1]=0.886;c[2]=0.259;
+      break;
+    case 3:
+      c[0]=0.118;c[1]=0.714;c[2]=0.949;
+      break;
+    case 4:
+      c[0]=0.949;c[1]=0.275;c[2]=0.871;
+      break;
+    case 5:
+      c[0]=0.949;c[1]=0.275;c[2]=0.110;
+      break;
+    case 6:
+      c[0]=0.5;c[1]=0.9;c[2]=0.75;
+      break;
+    case 7:
+      c[0]=1.0; c[1]=1.0; c[2]=1.0;
+    default:
+      c[0]=0.1*i;c[1]=0.05*i;c[2]=0.1*i;
+      break;
+    }
+}
+
+
+const char* vtkpxSurfaceUtil::GetColor(int i) {
+  double c[3];
+  vtkpxSurfaceUtil::GetColor(i,c);
+  char line[100];
+  sprintf(line,"%.3f %.3f %.3f",c[0],c[1],c[2]);
+  buffer=line;
+  return buffer.c_str();
+}
+
+//------------------------------------------------------------------------------
+int vtkpxSurfaceUtil::CleanPoints(vtkPolyData* input,vtkPolyData* other,vtkImageData* mask,int usemask)
+{
+  
+  if (input==NULL || other==NULL)
+    {
+      fprintf(stderr,"Bad Inputs to CleanPoints\n");
+      return 0;
+    }
+
+  if (mask==NULL)
+    usemask=0;
+
+  double sp[3],ori[3];
+  if (usemask)
+    {
+      mask->GetSpacing(sp);
+      mask->GetOrigin(ori);
+    }
+
+
+  int npoints=input->GetNumberOfPoints();
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+
+  int allocate=0;
+  if (inp==NULL)
+    allocate=1;
+  else if (inp->GetNumberOfTuples()!=npoints)
+    allocate=1;
+
+  if (allocate || usemask)
+    {
+      vtkFloatArray* flarr=vtkFloatArray::New();
+      flarr->SetNumberOfTuples(npoints);
+      flarr->FillComponent(0,1000.0);
+      input->GetPointData()->SetScalars(flarr);
+      fprintf(stderr,"Allocating\n");
+      flarr->Delete();
+    }
+
+  inp=input->GetPointData()->GetScalars();
+
+
+  double x[3],tx[3];
+  vtkPoints* p_inp=input->GetPoints();
+  vtkPoints* p_ref=other->GetPoints();
+
+  int smaller=0;
+
+  for (int i=0;i<npoints;i++)
+    {
+      p_inp->GetPoint(i,x);
+      int id=other->FindPoint(x);
+      p_ref->GetPoint(id,tx);
+      float d=sqrt(vtkMath::Distance2BetweenPoints(x,tx));
+      float scale=1.0;
+
+      if (usemask)
+	{
+	  int x1=int(x[0]/sp[0]-ori[0]+0.5);
+	  int y1=int(x[1]/sp[1]-ori[1]+0.5);
+	  int z1=int(x[2]/sp[2]-ori[2]+0.5);
+	  double m=mask->GetScalarComponentAsDouble(x1,y1,z1,0);
+	  if (m<1.0)
+	    scale=0.0;
+	}
+      else
+	{
+	  float f=inp->GetComponent(i,0);
+	  if (f<d)
+	    {
+	      ++smaller;
+	      d=f;
+	    }
+	}
+      inp->SetComponent(i,0,d*scale);
+    }
+
+  fprintf(stderr,"Done smaller=%d  \n",smaller);
+	  
+
+  return 1;
+}
+
+int vtkpxSurfaceUtil::ExportQHull(vtkPolyData* input,const char* fname)
+{
+  vtkPoints* pts=input->GetPoints();
+  int numpoints=pts->GetNumberOfPoints();
+
+  FILE* fout=fopen(fname,"w");
+  if (fout)
+      {
+	fprintf(fout,"3\n");
+	fprintf(fout,"%d\n",numpoints);
+	for (int j=0;j<numpoints;j++)
+	  {
+	    double x[3]; pts->GetPoint(j,x);
+	    fprintf(fout,"%6.3f %6.3f %6.3f\n",x[0],x[1],x[2]);
+	  }
+	fclose(fout);
+      }
+  fprintf(stderr,"Done save qhull in %s\n",fname);
+  return 1;
+}
+
+vtkPolyData* vtkpxSurfaceUtil::ReadQHull(const char* fname)
+{
+  FILE* fin=fopen(fname,"r");
+  if (fin)
+    {
+      int good=0,bad=0;
+      char command[200];
+      vtkPoints*     pts  = vtkPoints::New();
+      vtkCellArray* cells = vtkCellArray::New();
+      fgets(command,200,fin);
+      int np,temp,nt;
+      fscanf(fin,"%d %d %d\n",&np,&nt,&temp);
+      fprintf(stderr,"Reading %s points=%d, tetra=%d\n",fname,np,nt);
+      pts->SetNumberOfPoints(np);
+      cells->Allocate(nt*4,10);
+      
+      float x1,y1,z1,t1;
+      for (int j=0;j<np;j++)
+	{
+	  fscanf(fin,"%f %f %f %f\n",&x1,&y1,&z1,&t1);
+	  pts->SetPoint(j,x1,y1,z1);
+	}
+      int points[4];
+      for (int i=0;i<nt;i++)
+	{
+	  int npt;
+	  fgets(command,200,fin);
+	  sscanf(command,"%d %d %d %d %d",&npt,&points[0],&points[1],&points[2],&points[3]);
+	  //	    fprintf(stderr,"%d : (%s)\n",npt,command);
+	  if (npt==4)
+	    {
+	      vtkIdType p1[3],p2[3],p3[3],p4[3];
+	      p1[0]=points[0]; 		p1[1]=points[1]; 		p1[2]=points[2];
+	      p2[0]=points[3]; 		p2[1]=points[1]; 		p2[2]=points[0];
+	      p3[0]=points[1];		p3[1]=points[2];		p3[2]=points[3];
+	      p4[0]=points[0]; 		p4[1]=points[2]; 		p4[2]=points[3];
+	      
+	      cells->InsertNextCell(3,p1);
+	      cells->InsertNextCell(3,p2);
+	      cells->InsertNextCell(3,p3);
+	      cells->InsertNextCell(3,p4);
+	      ++good;
+	    }
+	  else
+	    ++bad;
+	}
+      
+      fclose(fin);
+      fprintf(stderr,"Good=%d bad=%d\n",good,bad);
+      vtkPolyData* out=vtkPolyData::New();
+      out->SetPoints(pts);
+      out->SetPolys(cells);
+      pts->Delete();
+      cells->Delete();
+      return out;
+    }
+  return NULL;
+}
+
+// --------------------------------------------------------------------------------------
+int vtkpxSurfaceUtil::AddLabels(vtkPolyData* inout,vtkPolyData* other)
+{
+  if (inout==NULL || other==NULL)
+    {
+      fprintf(stderr,"Bad Inputs to Add Labels\n");
+      return 0;
+    }
+  
+  int npoints=inout->GetNumberOfPoints();
+  vtkFloatArray* flarr=vtkFloatArray::New();
+  flarr->SetNumberOfTuples(npoints);
+  flarr->FillComponent(0,1000.0);
+  inout->GetPointData()->SetScalars(flarr);
+  flarr->Delete();
+  
+  vtkDataArray* inp=inout->GetPointData()->GetScalars();
+  vtkDataArray* ref=other->GetPointData()->GetScalars();
+  
+  double x[3];
+  vtkPoints* p_inp=inout->GetPoints();
+  
+  for (int i=0;i<npoints;i++)
+    {
+      p_inp->GetPoint(i,x);
+      int id=other->FindPoint(x);
+      float c=ref->GetComponent(id,0);
+      inp->SetComponent(i,0,c);
+    }
+  
+  return 1;
+}
+// --------------------------------------------------------------------------------------
+int vtkpxSurfaceUtil::SaveAbaqus(vtkPolyData* qhullsurface,const char* abname)
+{
+  vtkPoints* pts=qhullsurface->GetPoints();
+  vtkCellArray* cells=qhullsurface->GetPolys();
+
+
+  FILE* fout=fopen(abname,"w");
+
+  int numnodes=pts->GetNumberOfPoints();
+  int numelements=cells->GetNumberOfCells()/4;
+
+  fprintf(fout,"*HEADING\nPelvic Model\n");
+  fprintf(fout,"** numnodes=%d, numelements=%d\n",numnodes,numelements);
+  fprintf(fout,"** ----------------------------------------------------\n");
+  fprintf(fout,"** Shrink .dat file\n*PREPRINT,ECHO=NO,MODEL=NO,HISTORY=NO\n**\n");
+
+
+  fprintf(fout,"*MATERIAL,NAME=SOFT\n*ELASTIC\n");
+  fprintf(fout,"%8.2f,%8.2f\n",1.0,0.4);
+  fprintf(fout,"*MATERIAL,NAME=BONE\n*ELASTIC\n");
+  fprintf(fout,"%8.2f,%8.2f\n",100000.0,0.3);
+  fprintf(fout,"*MATERIAL,NAME=BLADDER\n*ELASTIC\n");
+  fprintf(fout,"%8.2f,%8.2f\n",3.0,0.4);
+  fprintf(fout,"*MATERIAL,NAME=PROSTATE\n*ELASTIC\n");
+  fprintf(fout,"%8.2f,%8.2f\n",3.0,0.4);
+  fprintf(fout,"*MATERIAL,NAME=RECTUM\n*ELASTIC\n");
+  fprintf(fout,"%8.2f,%8.2f\n",3.0,0.4);
+
+  vtkDataArray* lab=qhullsurface->GetPointData()->GetScalars();
+
+  double r2[2]; lab->GetRange(r2);
+  int r[2]; r[0]=int(r2[0]); r[1]=(int)r2[1];
+  double x[3];
+  
+  fprintf(fout,"** ---------- Nodes  --------------------------------------\n");
+
+  for (int pass=r[0];pass<=r[1];pass++)
+      {
+	fprintf(fout,"*NODE,NSET=N_%d\n",pass);
+	for (int index=0;index<numnodes;index++)
+	  {
+	    int p=(int)lab->GetComponent(index,0);
+	    if (p==pass)
+	      {
+		pts->GetPoint(index,x);
+		fprintf(fout," %5d , %7.3f , %7.3f , %7.3f \n",
+			index+1000,
+			x[0],x[1],x[2]);
+	      }
+	  }
+      }
+  
+  fprintf(fout,"**\n");
+  fprintf(fout,"*NSET, NSET=ALLNODES\n");
+  for (int pass=r[0];pass<=r[1];pass++)
+      {
+	fprintf(fout,"N_%d",pass);
+	if (pass!=r[1])
+	  fprintf(fout,",");
+      }
+  fprintf(fout,"\n*NSET, NSET=N_DUMMY\n1000\n");
+  
+  
+  fprintf(fout,"** ---------- Elements --------------------------------------\n");  
+  char elementname[20];
+  sprintf(elementname,"C3D4");
+
+  fprintf(stderr,"Using element type=%s\n",elementname);
+
+
+
+  int elindex=1000;
+
+  for (int pass=r[0];pass<=r[1];pass++)
+    {
+      cells->InitTraversal();
+      fprintf(fout,"*ELEMENT, TYPE=%s, ELSET=E_%d\n",elementname,pass);
+      for (int element=0;element<numelements;element++)
+	{
+	  vtkIdType p[4],q[4],npts;
+	  vtkIdType *p1,*p2,*p3,*p4;
+	  cells->GetNextCell(npts,p1);
+	  cells->GetNextCell(npts,p2);
+	  cells->GetNextCell(npts,p3);
+	  cells->GetNextCell(npts,p4);
+	  
+	  for (int ia=0;ia<=2;ia++)
+	    p[ia]=p1[ia];
+	  p[3]=p2[0];
+	  
+	  int mode=1;
+	  for (int ia=0;ia<=3;ia++)
+	    q[ia]=(int)lab->GetComponent(p[ia],0);
+	  if (q[0]==q[1] && q[0]==q[2] && q[0]==q[3])
+	    mode=q[0];
+	  else
+	    mode=1;
+	  
+	  fprintf(fout,"%d, %d,%d,%d,%d\n",elindex,p[0]+1000,p[1]+1000,p[2]+1000,p[3]+1000);
+	  ++elindex;
+	}
+    }
+  fprintf(fout,"** \n");
+  fprintf(fout,"*ELSET, ELSET=E_DUMMY\n1000\n**\n");
+  fprintf(fout,"*ELSET, ELSET=PELVIS\n");  
+  fprintf(fout,"E_1,E_2,E_3,E_4,E_5\n");
+
+  fprintf(fout,"** ---------- Solid  --------------------------------------\n");
+  fprintf(fout,"*SOLID SECTION, ELSET=E_1,MATERIAL=SOFT\n**\n");
+  fprintf(fout,"*SOLID SECTION, ELSET=E_2,MATERIAL=BONE\n**\n");
+  fprintf(fout,"*SOLID SECTION, ELSET=E_3,MATERIAL=BLADDER\n**\n");
+  fprintf(fout,"*SOLID SECTION, ELSET=E_4,MATERIAL=PROSTATE\n**\n");
+  fprintf(fout,"*SOLID SECTION, ELSET=E_5,MATERIAL=RECTUM\n**\n");
+
+  fprintf(fout,"** Dummy Step\n");
+  fprintf(fout,"*STEP");
+  //fprintf(fout,",NLGEOM");
+  fprintf(fout,",INC=50\n*STATIC\n*BOUNDARY\nALLNODES,1,3,0.0\n");
+  fprintf(fout,"*EL PRINT,POSITION=CENTROIDAL,ELSET=E_DUMMY\nEP1\n");
+  fprintf(fout,"*NODE PRINT,NSET=N_DUMMY\nU1\n");
+  fprintf(fout,"*EL FILE,POSITION=CENTROIDAL,ELSET=PELVIS\nE\n");
+  fprintf(fout,"*EL FILE,ELSET=PELVIS\nEVOL\n*NODE FILE,NSET=ALLNODES\nU\n");
+  //  if (resout>0)
+  fprintf(fout,"*RESTART,WRITE\n");
+  fprintf(fout,"*END STEP\n");
+
+  fclose(fout);
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxSurfaceUtil.h b/bioimagesuite30_src/Graphics/vtkpxSurfaceUtil.h
new file mode 100644
index 0000000..071ae9f
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxSurfaceUtil.h
@@ -0,0 +1,173 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSurfaceUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/07/15 12:58:30 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxSurfaceUtil - a collection of static utility functions
+// .SECTION Description
+// This class contains a collection of <EM>static</EM> utility functions for use elsewhere ala vtkMath
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// This requires pxutil 
+
+#ifndef __vtkpxSurfaceUtil_h
+#define __vtkpxSurfaceUtil_h
+
+#include "vtkObject.h"
+#include "pxutil.h"
+#include "pxcontour.h"
+#include "pxcontourstack.h"
+#include "pxgeometrystruct.h"
+#include "pxtriangulatedstack.h"
+#include "vtkPointData.h"
+#include <string>
+
+class vtkImageData;
+class vtkLookupTable;
+class vtkImageData;
+class vtkPolyData;
+class vtkTransform;
+class vtkPoints;
+class vtkMatrix4x4;
+class vtkThinPlateSplineTransform;
+class vtkGridTransform;
+class vtkContourFilter;
+class vtkHomogeneousTransform;
+class vtkAbstractTransform;
+class vtkDataArray;
+class vtkFloatArray;
+class vtkUnsignedCharArray;
+class vtkPointLocator;
+
+class vtkpxSurfaceUtil : public vtkObject
+{
+public:
+  static vtkpxSurfaceUtil *New();
+  vtkTypeMacro(vtkpxSurfaceUtil,vtkObject);
+  
+  //BTX
+  // Draw Contour Stuff
+  static void createsinglesection(vtkPolyData* sep,PXContour* cnt1,PXContour* cnt2,float z1,float z2,
+				  float du=1.0,int debug=0);
+  static void createsinglepolarsection(vtkPolyData* sep,PXContour* cnt1,PXContour* cnt2,
+				       float theta1,float theta2,float middlex,
+				       float du=1.0,int debug=0);
+  static void createsection(PXContourStack* stack,vtkPolyData* grp,int polar=0,float middlex=0.0,int begin=-1,int end=100000);
+  static void drawtstack(vtkPolyData* surface,PXTriangulatedStack* tstack);
+  //ETX
+
+
+  // -------------------------------------------------
+  // ObjectMap  To PolyData
+  // -------------------------------------------------
+  
+  static int ObjectMapToPolyData(vtkImageData* image,vtkPolyData* poly);
+  static int ObjectMapToPolyData(vtkImageData* image,vtkPolyData* poly,int minobj,int maxobj,
+				 double smooth=1.0,double smoothz=1.0,double reslice=1.0);
+  static int MapScalarsToSurface(vtkPolyData* source,vtkPolyData* destination);
+  static int AddObjectLabelsToSurface(vtkPolyData* source,int offset);
+
+  static int DefaultObjectMapLookupTableNumberOfColors(); 
+  static int DefaultObjectMapLookupTable(vtkLookupTable* lkp,int numc=-1,int blackzero=0);
+  static int VOIObjectMapLookupTable(vtkLookupTable* lkp,int numc=-1);
+
+  static int AddObjectMapLookupTableToSurface(vtkPolyData* source);
+  static int AddShapeIndexLookupTableToSurface(vtkPolyData* source);
+  static int AddCurvatureLookupTableToSurface(vtkPolyData* source);
+
+
+  // --------------------------------------------------
+  // Mesh Generation Random Stuff
+  // --------------------------------------------------
+  static int CleanPoints(vtkPolyData* input,vtkPolyData* other,vtkImageData* mask,int usemask);
+  static int ExportQHull(vtkPolyData* input,const char* fname);
+  static int AddLabels(vtkPolyData* inout,vtkPolyData* ref);
+  static vtkPolyData* ReadQHull(const char* fname);
+  static int SaveAbaqus(vtkPolyData* qhullsurface,const char* abname);
+
+  // --------------------------------------------------
+  // Neighbors Stuff -- needed for shape tracking etc
+  // --------------------------------------------------
+  static PXIntegerList* GenerateNeighbors(vtkPolyData* polydata,int opensurface);
+  static int            CollectNeighbours(vtkPolyData* polydata,int point,int distance,
+					  PXIntegerList* list,PXIntegerList* neighbors_array);
+  static int            CalculateCurvatures(vtkPolyData* polydata,int scale,int opensurface,int c_mode=2,float upper=1.0);
+  static int            CalculateCurvatures(vtkPolyData* polydata,int scale,PXIntegerList* neighbours);
+
+  static int            NonShrinkSmooth(vtkPolyData* poly,int opensurface,
+					float alpha,float beta,int iterations,int movez);
+  static int            NonShrinkSmooth(vtkPolyData*,PXIntegerList* neighbors_array,
+					float alpha,float beta,int iterations,int movez);
+
+  // ---------------------------------------------------
+  // Displacement Stuff
+  // ---------------------------------------------------
+  static void ZeroAllDisplacements(vtkPolyData* poly,vtkFloatArray* displ);
+  static int  AddToDisplacements(vtkPolyData* orig,vtkPolyData* targ,vtkFloatArray* displ);
+  static int  ShiftPointsByDisplacements(vtkPolyData* poly,vtkFloatArray* displ,float factor=1.0);
+
+
+  // ---------------------------------------------------
+  // Some Standard Colors
+  // ---------------------------------------------------
+  static void GetColor(int i,double c[3]);
+  static const char* GetColor(int i);
+  
+
+  //BTX
+  static std::string buffer;
+  //ETX
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxVolume.cpp b/bioimagesuite30_src/Graphics/vtkpxVolume.cpp
new file mode 100644
index 0000000..a49e0a0
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxVolume.cpp
@@ -0,0 +1,1284 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+#include <stdlib.h>
+#include <math.h>
+#include "pxutil.h"
+#include "vtkColorTransferFunction.h"
+#include "vtkImageShiftScale.h"
+#include "vtkLookupTable.h"
+#include "vtkObjectFactory.h"
+#include "vtkPiecewiseFunction.h"
+#include "vtkImageData.h"
+#include "vtkAbstractVolumeMapper.h"
+#include "vtkVolumeMapper.h"
+#include "vtkVolumeProperty.h"
+#include "vtkVolumeRayCastMIPFunction.h"
+//#include "vtkCroppedVolumeRayCastCompositeFunction.h"
+//#include "vtkCroppedVolumeRayCastMapper.h"
+
+
+
+#include "vtkVolumeRayCastCompositeFunction.h"
+#include "vtkVolumeRayCastMapper.h"
+
+#include "vtkFixedPointVolumeRayCastMapper.h"
+
+#include "vtkCropVolumeRayCastMapper.h"
+
+#include "vtkVolumeTextureMapper2D.h"
+#include "vtkpxVolume.h"
+#include "vtkImageReslice.h"
+#include "vtkIdentityTransform.h"
+#include "vtkImageContinuousDilate3D.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkpxColorMapUtil.h"
+#include "vtkImageBlend.h"
+#include "vtkImageMapToRGBA.h"
+#include "vtkpxUtil.h"
+#include<vtkVolumeTextureMapper3D.h>
+#include "vtkImageMapToColors.h"
+
+
+
+using namespace bioimagesuite_legacy;
+
+
+//------------------------------------------------------------------------------
+vtkpxVolume* vtkpxVolume::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxVolume");
+  if(ret)
+    {
+    return (vtkpxVolume*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxVolume;
+}
+
+
+// Creates a Volume with the following defaults: origin(0,0,0)
+// position=(0,0,0) scale=1 visibility=1 pickable=1 dragable=
+//------------------------------------------------------------------------------
+
+vtkpxVolume::vtkpxVolume()
+{
+  this->VolumeRenderingMode= 2;
+  this->ResliceMode=-1;
+  this->TargetSampleDistance=1.0;
+  this->InterpolationMode=1;
+  this->Orientation=0;
+  this->ShadingMode                 = 0;
+  this->MinValue                   = 0.0;
+  this->MaxValue                   = 255.0;
+  this->MaxIntensity               = 255;
+  this->probeLocation[0] = this->probeLocation[1] = this->probeLocation[2] = 0.0;
+
+  this->CropShape = 0;
+  this->CropSphereRadius = 50.0;
+  this->gradientEnhancementMode = 0;
+
+  this->ShiftScale                  = NULL;
+  this->SecondShiftScale                  = NULL;
+
+  this->cTFun                       = NULL;
+  this->oTFun                       = NULL;
+
+  this->oTFun = vtkPiecewiseFunction::New();
+  this->oTFun->AddSegment(0, 0.0, 255, 1.0);
+
+  this->dualTransferFunction=vtkPiecewiseFunction::New();
+  this->dualTransferFunction->AddSegment(0, 0.0, 255, 1.0);
+
+  // Create a transfer function mapping scalar value to color (grey)
+  this->cTFun = vtkColorTransferFunction::New();
+  this->cTFun->AddRGBPoint(0,0.0,0.0,0.0);
+  this->cTFun->AddRGBPoint(255,1.0,1.0,1.0);
+
+  this->gTFun = vtkPiecewiseFunction::New();
+  this->gTFun->AddSegment(0, 0.0, 255, 1.0);
+
+  this->gTFun2 = vtkPiecewiseFunction::New();
+  this->gTFun2->AddSegment(0, 1.0, 255, 1.0);
+
+
+  this->LookupTable=vtkLookupTable::New();
+  vtkpxColorMapUtil::SetStepColorMap(this->LookupTable,0,255,0,255,256,1);
+
+  this->SecondLookupTable=vtkLookupTable::New();
+  vtkpxColorMapUtil::SetStepColorMap(this->SecondLookupTable,0,255,0,255,256,1);
+
+  this->Property = vtkVolumeProperty::New();
+  if (ShadingMode)
+    this->Property->ShadeOn();
+  else
+    this->Property->ShadeOff();
+  this->Property->SetInterpolationTypeToLinear();
+  this->Property->SetColor(this->cTFun);
+  this->Property->SetScalarOpacity(0,this->oTFun);
+
+  this->ImageReslice=NULL;
+  this->SecondImageReslice=NULL;
+  this->ImageMapToColors=vtkImageMapToColors::New();
+  this->ImageMapToColors->SetOutputFormatToRGBA();
+  //this->ImageMapToColors->SetLookupTable(this->LookupTable());
+
+  this->Frame=0;
+  this->NumberOfFrames=1;
+  this->ExtractFrame=NULL;
+  this->SecondExtractFrame=NULL;
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->TargetDimensions[ia]=64;
+      this->TargetOrigin[ia]=0.0;
+      this->TargetSpacing[ia]=1.0;
+    }
+  this->InputImage=vtkImageData::New();
+  this->SecondInputImage=NULL;
+  this->DualInputMode=0;
+  this->ImageBlend=NULL;
+  this->ImageMapToRGBA1=NULL;
+  this->ImageMapToRGBA2=NULL;
+  this->RGBAMode=0;
+  this->RGBAMode_changed = 0;
+}
+//------------------------------------------------------------------------------
+// Destruct a volume
+vtkpxVolume::~vtkpxVolume()
+{
+  if (this->ShiftScale )
+    this->ShiftScale->Delete();
+
+  if (this->SecondShiftScale )
+    this->SecondShiftScale->Delete();
+
+  if (this->oTFun )
+    this->oTFun->Delete();
+
+  if (this->cTFun )
+    this->cTFun->Delete();
+
+  if (this->dualTransferFunction )
+    this->dualTransferFunction->Delete();
+
+  if (this->ImageReslice )
+    this->ImageReslice->Delete();
+
+  if (this->SecondImageReslice )
+    this->SecondImageReslice->Delete();
+
+  if (this->ImageMapToRGBA1)
+    this->ImageMapToRGBA1->Delete();
+
+  if (this->ImageMapToRGBA2)
+    this->ImageMapToRGBA2->Delete();
+
+  if (this->ImageBlend)
+    this->ImageBlend->Delete();
+
+  if (this->ImageMapToColors)
+    this->ImageMapToColors->Delete();
+  if (this->ExtractFrame)
+    this->ExtractFrame->Delete();
+
+  if (this->SecondExtractFrame)
+    this->SecondExtractFrame->Delete();
+
+
+  if (this->InputImage)
+    this->InputImage->Delete();
+
+  if (this->SecondInputImage)
+    this->SecondInputImage->Delete();
+
+  if (this->LookupTable)
+    this->LookupTable->Delete();
+
+  if (this->SecondLookupTable)
+    this->SecondLookupTable->Delete();
+
+}
+//------------------------------------------------------------------------------
+
+void vtkpxVolume::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkProp3D::PrintSelf(os,indent);
+
+  if( this->Property )
+    {
+      os << indent << "Property:\n";
+      this->Property->PrintSelf(os,indent.GetNextIndent());
+    }
+  else
+    {
+      os << indent << "Property: (not defined)\n";
+    }
+
+  if( this->Mapper )
+    {
+      os << indent << "Mapper:\n";
+      this->Mapper->PrintSelf(os,indent.GetNextIndent());
+    }
+  else
+    {
+      os << indent << "Mapper: (not defined)\n";
+    }
+
+  // make sure our bounds are up to date
+  if ( this->Mapper )
+    {
+      this->GetBounds();
+      os << indent << "Bounds: (" << this->Bounds[0] << ", "
+	 << this->Bounds[1] << ") (" << this->Bounds[2] << ") ("
+	 << this->Bounds[3] << ") (" << this->Bounds[4] << ") ("
+	 << this->Bounds[5] << ")\n";
+    }
+  else
+    {
+      os << indent << "Bounds: (not defined)\n";
+    }
+}
+
+//------------------------------------------------------------------------------
+void vtkpxVolume::SetSecondLookupTable(vtkLookupTable* table)
+{
+  if (!table)
+    return;
+
+  vtkpxColorMapUtil::CopyLookupTable(table,this->SecondLookupTable);
+}
+
+void vtkpxVolume::SetFromLookupTable(vtkLookupTable* table)
+{
+  if (!table)
+    return;
+
+  vtkpxColorMapUtil::CopyLookupTable(table,this->LookupTable);
+
+  if (!this->oTFun)
+    this->oTFun = vtkPiecewiseFunction::New();
+
+  if (!this->cTFun)
+    this->cTFun = vtkColorTransferFunction::New();
+
+  this->oTFun->RemoveAllPoints();
+  this->oTFun->ClampingOn();
+
+  this->cTFun->RemoveAllPoints();
+  this->cTFun->ClampingOn();
+
+  double dat[2];  table->GetTableRange(dat);
+  double diff=dat[1]-dat[0];
+  if ( fabs(dat[1]-dat[0])<1e-7)
+    {
+      dat[1]=dat[0]+1e-7;
+    }
+  diff=dat[1]-dat[0]+1.0;
+  double step=diff/float(table->GetNumberOfColors());
+
+  //  fprintf(stderr,"Dat = %.2f:%.2f step=%f\n",dat[0],dat[1],step);
+
+  for (int i=0;i<table->GetNumberOfColors();i++)
+    {
+      double val[4];
+      double base=float(i)*step+dat[0];
+      table->GetTableValue(i,val);
+      this->cTFun->AddRGBPoint(base,val[0],val[1],val[2]);
+      //      if (i>245 && i <250)
+      //	fprintf(stderr,"%.2f (%.2f, %.2f,%.2f)\n",base,val[0],val[1],val[2]);
+      this->oTFun->AddPoint(base,val[3]);
+    }
+
+  if (this->ImageMapToColors!=NULL)
+    {
+      this->ImageMapToColors->SetLookupTable(this->LookupTable);
+      this->ImageMapToColors->Modified();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::UpdateRange()
+{
+  int dim[3]; this->InputImage->GetDimensions(dim);
+  double range[2];  this->InputImage->GetPointData()->GetScalars()->GetRange(range,this->Frame);
+
+  this->MinValue=range[0];
+  this->MaxValue=range[1];
+
+  if (ShiftScale==NULL)
+    return;
+
+  if (fabs(this->MinValue-this->MaxValue)<1e-4)
+    {
+      ShiftScale->SetShift(0);
+      ShiftScale->SetScale(1.0);
+      this->MinValue=0.0;
+      this->MaxValue=255.0;
+    }
+  else if (fabs(range[0]-range[1])<1.0)
+    {
+      float sc=255.0/(range[1]-range[0]);
+      ShiftScale->SetShift(-range[0]);
+      ShiftScale->SetScale(sc);
+      this->MinValue=0.0;
+      this->MaxValue=255.0;
+    }
+  else if (range[0]>=0.0 && range[1]<25.0)
+    {
+      ShiftScale->SetShift(0);
+      ShiftScale->SetScale(10.0);
+    }
+  else if (range[0]>=0.0 && range[1]<256.0)
+    {
+      ShiftScale->SetShift(0);
+      ShiftScale->SetScale(1.0);
+    }
+  else if (range[0]>=0.0 && range[1]<512.0)
+    {
+      ShiftScale->SetShift(0);
+      ShiftScale->SetScale(0.5);
+      this->MaxValue=0.5*this->MaxValue;
+    }
+  else
+    {
+      float sc=255.0/(range[1]-range[0]);
+      ShiftScale->SetShift(-range[0]);
+      ShiftScale->SetScale(sc);
+      this->MinValue=0.0;
+      this->MaxValue=255.0;
+    }
+
+  /*  fprintf(stderr,"Shift=%f, Scale=%f range=%f:%f\n",
+      ShiftScale->GetShift(),ShiftScale->GetScale(),range[0],range[1]);*/
+
+  this->MaxIntensity=(int)this->MaxValue;
+  this->ShiftScale->Modified();
+
+
+  if (this->SecondShiftScale!=NULL)
+    {
+      double range[2];  this->SecondInputImage->GetPointData()->GetScalars()->GetRange(range,this->Frame);
+
+      if (fabs(range[1]-range[0])<1e-4)
+	{
+	  this->SecondShiftScale->SetShift(0);
+	  this->SecondShiftScale->SetScale(1.0);
+	}
+      else if (range[0]>=0.0 && range[1]<256.0)
+	{
+	  this->SecondShiftScale->SetShift(0);
+	  this->SecondShiftScale->SetScale(1.0);
+	}
+      else if (range[0]>=0.0 && range[1]<512.0)
+	{
+	  this->SecondShiftScale->SetShift(0);
+	  this->SecondShiftScale->SetScale(0.5);
+	}
+      else
+	{
+	  float sc=255.0/(range[1]-range[0]);
+	  this->SecondShiftScale->SetShift(-range[0]);
+	  this->SecondShiftScale->SetScale(sc);
+	}
+      this->SecondShiftScale->Modified();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::SetFrame(int fr)
+{
+  if (!this->ExtractFrame)
+    return;
+
+  int oldframe=this->Frame;
+  this->Frame=Irange(fr,0,this->NumberOfFrames-1);
+  if (oldframe!=this->Frame)
+    {
+      this->ExtractFrame->SetComponents(this->Frame);
+      if (this->SecondExtractFrame!=NULL)
+	{
+	  int fr=this->SecondInputImage->GetNumberOfScalarComponents();
+	  int sfr=this->Frame;
+	  if (this->Frame>=fr)
+	    sfr=fr-1;
+	  this->SecondExtractFrame->SetComponents(sfr);
+	  //	  fprintf(stderr,"Frame=%d, sfr=%d\n",this->Frame,sfr);
+	}
+      this->UpdateRange();
+      this->Modified();
+    }
+
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::SetInput(vtkImageData* image)
+{
+  this->SetInput(image,0);
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::SetInput(vtkImageData* image,int orientation)
+{
+  if (image==NULL)
+    return;
+
+  this->Orientation=Irange(orientation,0,3);
+
+  if (this->InputImage!=NULL)
+    this->InputImage->Delete();
+  this->InputImage=vtkImageData::New();
+  this->InputImage->ShallowCopy(image);
+
+  int dim[3]; this->InputImage->GetDimensions(dim);
+
+  this->NumberOfFrames=this->InputImage->GetNumberOfScalarComponents();
+  this->Frame=0;
+
+  if (this->ExtractFrame!=NULL)
+    this->ExtractFrame->Delete();
+
+  this->ExtractFrame=vtkImageExtractComponents::New();
+  this->ExtractFrame->SetInput(this->InputImage);
+  this->ExtractFrame->SetComponents(this->Frame);
+  this->ExtractFrame->Modified();
+
+  if (ShiftScale!=NULL)
+    this->ShiftScale->Delete();
+
+  ShiftScale=vtkImageShiftScale::New();
+  ShiftScale->SetOutputScalarTypeToUnsignedChar();
+  ShiftScale->ClampOverflowOn();
+  ShiftScale->SetInput(this->ExtractFrame->GetOutput());
+
+  if (ImageReslice!=NULL)
+    this->ImageReslice->Delete();
+
+  ImageReslice=vtkImageReslice::New();
+  ImageReslice->SetInput(this->ShiftScale->GetOutput());
+
+  this->UpdateRange();
+  this->GetImageRange(cropping_range);
+  this->SetResliceInterpolationModes(abs(this->ResliceMode),this->InterpolationMode);
+
+  if (this->Mapper)
+    {
+      this->Mapper->Delete();
+      this->Mapper=NULL;
+    }
+  this->Modified();
+
+  this->DualInputMode=0;
+
+  this->Update();
+}
+// -----------------------------------------------------------------------------------------------
+void vtkpxVolume::SetSecondInput(vtkImageData* image)
+{
+  if (image==NULL || this->ImageReslice==NULL)
+    return;
+
+  int nc=image->GetNumberOfScalarComponents();
+  int onc=this->InputImage->GetNumberOfScalarComponents();
+
+  if (onc<nc)
+    {
+      this->DualInputMode=0;
+      return;
+    }
+
+  if (this->SecondInputImage==NULL)
+    this->SecondInputImage=vtkImageData::New();
+  this->SecondInputImage->ShallowCopy(image);
+
+  if (this->SecondExtractFrame!=NULL)
+    this->SecondExtractFrame->Delete();
+
+  int fr=this->Frame;
+  if (fr>=nc)
+    fr=nc-1;
+
+  this->SecondExtractFrame=vtkImageExtractComponents::New();
+  this->SecondExtractFrame->SetInput(this->SecondInputImage);
+  this->SecondExtractFrame->SetComponents(fr);
+  this->SecondExtractFrame->Modified();
+
+  if (SecondShiftScale!=NULL)
+    this->SecondShiftScale->Delete();
+
+  SecondShiftScale=vtkImageShiftScale::New();
+  SecondShiftScale->SetOutputScalarTypeToUnsignedChar();
+  SecondShiftScale->ClampOverflowOn();
+  SecondShiftScale->SetInput(this->SecondExtractFrame->GetOutput());
+
+  if (SecondImageReslice!=NULL)
+    this->SecondImageReslice->Delete();
+
+  SecondImageReslice=vtkImageReslice::New();
+  SecondImageReslice->SetInput(this->SecondShiftScale->GetOutput());
+
+  this->UpdateRange();
+  this->GetImageRange(cropping_range);
+  this->SetResliceInterpolationModes(abs(this->ResliceMode),this->InterpolationMode,1);
+
+
+  // ------------------ But there is more ---------------------------------------
+  //        Blend Images
+  // ----------------------------------------------------------------------------
+
+  if (this->ImageMapToRGBA1!=NULL)
+    this->ImageMapToRGBA1->Delete();
+
+  this->ImageMapToRGBA1=vtkImageMapToRGBA::New();
+  this->ImageMapToRGBA1->SetInput(this->ImageReslice->GetOutput());
+  this->ImageMapToRGBA1->SetLookupTable(this->LookupTable);
+
+  if (this->ImageMapToRGBA2!=NULL)
+    this->ImageMapToRGBA2->Delete();
+
+  this->ImageMapToRGBA2=vtkImageMapToRGBA::New();
+  this->ImageMapToRGBA2->SetInput(this->SecondImageReslice->GetOutput());
+  this->ImageMapToRGBA2->SetLookupTable(this->SecondLookupTable);
+
+  if (this->ImageBlend!=NULL)
+    this->ImageBlend->Delete();
+
+  this->ImageBlend=vtkImageBlend::New();
+  this->ImageBlend->AddInput(this->ImageMapToRGBA1->GetOutput());
+  this->ImageBlend->AddInput(this->ImageMapToRGBA2->GetOutput());
+  this->ImageBlend->SetBlendModeToNormal();
+  this->DualInputMode=1;
+  //  fprintf(stderr,"Done Setting Second Input, DualInputMode=%d\n",this->DualInputMode);
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::SetMapper(vtkVolumeMapper *mapper)
+{
+  Update();
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::SetProperty(vtkVolumeProperty *property)
+{
+  return;
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::SetProbeLocation(double location[3]) // use another function name.
+{
+
+  for(int ia=0;ia<3;ia++)
+    {
+      probeLocation[ia] = (location[ia]-this->TargetOrigin[ia])/this->TargetSpacing[ia];
+
+    }
+  //printf("pl :%f %f %f\n",  probeLocation[0], probeLocation[1], probeLocation[2]);
+
+  this->Modified();
+  this->Update();
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::SetIrregularCroppingMode(int inputCropMode)
+{
+  if (inputCropMode<-1)
+    inputCropMode=-1;
+  else if (inputCropMode>1)
+    inputCropMode=1;
+
+  if (cropMode==inputCropMode)
+      return;
+
+  cropMode = inputCropMode;
+
+  //printf("crop mode is %d\n", inputCropMode);
+  this->Update();
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::SetGradientEnhancementMode(int inputgradientEnhancementMode)
+{
+  if (inputgradientEnhancementMode<-1)
+    inputgradientEnhancementMode=-1;
+  else if (inputgradientEnhancementMode>1)
+    inputgradientEnhancementMode=1;
+
+  if (gradientEnhancementMode==inputgradientEnhancementMode)
+      return;
+
+  gradientEnhancementMode = inputgradientEnhancementMode;
+
+  this->Update();
+}
+
+//------------------------------------------------------------------------------
+void vtkpxVolume::SetCropValues(int Control_shapeIndex,
+								double Control_SphereRadius,
+								double Control_CubeLengthX,
+								double Control_CubeLengthY,
+								double Control_CubeLengthZ,
+								double Control_EllipseRadius_X,
+								double Control_EllipseRadius_Y,
+								double Control_EllipseRadius_Z,
+								double Control_CylinderRadius,
+								double Control_CylinderHeight,
+								double normal_vector[3])
+{
+
+
+	CropShape = Control_shapeIndex;
+
+	CropSphereRadius = Control_SphereRadius/this->TargetSpacing[0];
+	CropCubeLengthX = Control_CubeLengthX/this->TargetSpacing[0];
+	CropCubeLengthY = Control_CubeLengthY/this->TargetSpacing[1];
+	CropCubeLengthZ = Control_CubeLengthZ/this->TargetSpacing[2];
+	CropEllipseRadiusX = Control_EllipseRadius_X;
+	CropEllipseRadiusY = Control_EllipseRadius_Y;
+	CropEllipseRadiusZ = Control_EllipseRadius_Z;
+
+
+	CropCylinderRadius = Control_CylinderRadius/this->TargetSpacing[0];
+	CropCylinderHeight = Control_CylinderHeight;
+
+	direction_vector[0] = normal_vector[0];
+	direction_vector[1] = normal_vector[1];
+	direction_vector[2] = normal_vector[2];
+
+    this->Update();
+	this->Modified();
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::SetVolumeRenderingMode(int m)
+{
+  // Alark: Note If Changing number of modes add here
+
+  if (m<0 || m > 5)
+    m=0;
+
+  if (m==5)
+    m=4;
+  
+  if (m==this->VolumeRenderingMode)
+    return;
+  this->VolumeRenderingMode=m;
+  //  fprintf(stderr,"Setting Volume Rendering Mode=%d\n",this->VolumeRenderingMode);
+  this->Modified();
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::SetShadingMode(int shad)
+{
+  shad=shad>0;
+  if (shad==ShadingMode)
+    return;
+  else
+    ShadingMode=shad;
+  this->Modified();
+}
+//------------------------------------------------------------------------------
+int vtkpxVolume::RenderTranslucentGeometry( vtkViewport *vp )
+{
+  if (!this->Mapper)
+    this->Update();
+  // ALARK LOOK AT THIS
+  //return vtkVolume::RenderTranslucentGeometry(vp);
+  return 1;
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::GetImageRange(int bounds[6])
+{
+  int dim[3]; this->InputImage->GetDimensions(dim);
+  for (int i=0;i<=2;i++)
+    {
+      bounds[i*2]=0;
+      bounds[i*2+1]=dim[i]-1;
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::GetCroppingRange(int bounds[6])
+{
+  for (int ia=0;ia<=5;ia++)
+      bounds[ia]=cropping_range[ia];
+}
+//------------------------------------------------------------------------------
+
+void vtkpxVolume::GetProbeLocation(double location[3])
+{
+  for (int ia=0;ia<3;ia++)
+      location[ia]=probeLocation[ia];
+}
+
+//------------------------------------------------------------------------------
+
+void vtkpxVolume::ResetCroppingRange()
+{
+  GetImageRange(cropping_range);
+  vtkVolumeMapper* map=(vtkVolumeMapper*)this->GetMapper();
+  if (map!=NULL)
+    map->CroppingOff();
+}
+
+// ---------------------------------------------------------------------------
+void vtkpxVolume::SetResliceMode(int re)
+{
+  SetResliceInterpolationModes(re,this->InterpolationMode);
+}
+
+void vtkpxVolume::SetInterpolationMode(int interp)
+{
+  SetResliceInterpolationModes(this->ResliceMode,interp);
+}
+
+
+void vtkpxVolume::SetRGBAMode(int m)
+{
+   int q=(m>0);
+   if (q==this->RGBAMode)
+   {
+	   this->RGBAMode_changed = 0;
+	   return;
+   }
+
+   printf("RGBA mode is %d\n", m);
+   this->RGBAMode=m;
+   this->RGBAMode_changed = 1;
+   this->Update();
+}
+
+void vtkpxVolume::SetDualInputMode(int dm)
+{
+  dm=(dm>0);
+  if (this->DualInputMode==dm)
+    return;
+
+  if (dm==1 && this->SecondImageReslice==NULL)
+    return;
+
+  this->DualInputMode=dm;
+  //  fprintf(stderr,"Setting Dual Input Mode = %d\n",dm);
+  if (this->Mapper)
+    {
+      this->Mapper->Delete();
+      this->Mapper=NULL;
+    }
+  this->Modified();
+}
+
+// ---------------------------------------------------------------------------
+
+void vtkpxVolume::SetResliceInterpolationModes(int re,int interp,int force)
+{
+  re=Irange(abs(re),0,9);
+  interp=Irange(interp,0,2);
+  if (interp==2)
+    interp=3;
+  int doreslice=0;
+  if (force==0)
+    {
+      if (this->ResliceMode!=re)
+	{
+	  this->ResliceMode=re;
+	  doreslice=1;
+	}
+
+      if (this->InterpolationMode!=interp)
+	{
+	  this->InterpolationMode=interp;
+	  doreslice=1;
+	}
+    }
+  else
+    doreslice=1;
+
+  if (this->ImageReslice==NULL  || this->ShiftScale==NULL || doreslice==0)
+    return;
+
+  int dim[3];  double sp[3],ori[3];
+  this->InputImage->GetDimensions(dim);
+  this->InputImage->GetSpacing(sp);
+  this->InputImage->GetOrigin(ori);
+
+
+  int ia;
+
+  switch (this->ResliceMode)
+    {
+    case 0:
+      for (ia=0;ia<=2;ia++)
+	TargetDimensions[ia]=dim[ia];
+      break;
+    case 1:
+      for (ia=0;ia<=2;ia++)
+	TargetDimensions[ia]=dim[ia]/2;
+      break;
+    case 2:
+      for (ia=0;ia<=2;ia++)
+	TargetDimensions[ia]=dim[ia]/4;
+      break;
+    case 3:
+      TargetDimensions[0]=64;
+      TargetDimensions[1]=64;
+      TargetDimensions[2]=64;
+      break;
+    case 4:
+      TargetDimensions[0]=128;
+      TargetDimensions[1]=128;
+      TargetDimensions[2]=64;
+      break;
+    case 5:
+      TargetDimensions[0]=128;
+      TargetDimensions[1]=128;
+      TargetDimensions[2]=128;
+      break;
+    case 6:
+      TargetDimensions[0]=256;
+      TargetDimensions[1]=256;
+      TargetDimensions[2]=128;
+      break;
+    case 7:
+      TargetDimensions[0]=256;
+      TargetDimensions[1]=256;
+      TargetDimensions[2]=256;
+      break;
+    case 8:
+      TargetDimensions[0]=512;
+      TargetDimensions[1]=512;
+      TargetDimensions[2]=256;
+      break;
+    case 9:
+      TargetDimensions[0]=512;
+      TargetDimensions[1]=512;
+      TargetDimensions[2]=512;
+      break;
+    default:
+      TargetDimensions[0]=64;
+      TargetDimensions[1]=64;
+      TargetDimensions[2]=64;
+      break;
+    }
+
+  /*  fprintf(stderr,"Using Reslice Mode = %d Dims=%d x %d x %d\n",this->ResliceMode,this->TargetDimensions[0],
+	  this->TargetDimensions[1],
+	  this->TargetDimensions[2]);*/
+
+  for (ia=0;ia<=2;ia++)
+    if (TargetDimensions[ia]<2)
+      TargetDimensions[ia]=2;
+
+  if (this->Mapper!=NULL)
+    {
+      for (int ia=0;ia<=2;ia++)
+	{
+	  dim[ia]=cropping_range[ia*2+1]-cropping_range[ia*2];
+	  ori[ia]=ori[ia]+sp[ia]*cropping_range[ia*2];
+	}
+    }
+
+  //  fprintf(stderr,"\n\nInput Dimensions = %d,%d,%d\n",dim[0],dim[1],dim[2]);
+  //  fprintf(stderr,"Input Spacing = %.2f,%.2f,%.2f\n",sp[0],sp[1],sp[2]);
+
+  this->TargetSampleDistance=0.0;
+  for (ia=0;ia<=2;ia++)
+    {
+      if (TargetDimensions[ia]>dim[ia])
+	TargetDimensions[ia]=dim[ia];
+
+      if (TargetDimensions[ia]<4)
+	{
+	  this->InterpolationMode=0;
+	  TargetDimensions[ia]=4;
+	}
+      this->TargetSpacing[ia]=sp[ia]*double(dim[ia])/double(TargetDimensions[ia]);
+      if (ia!=0)
+	this->TargetSampleDistance=Fmin(this->TargetSampleDistance,this->TargetSpacing[ia]);
+      else
+	this->TargetSampleDistance=this->TargetSpacing[ia];
+      this->TargetOrigin[ia]=ori[ia];
+    }
+
+  //fprintf(stderr,"Output Dimensions = %d,%d,%d\n",TargetDimensions[0],TargetDimensions[1],TargetDimensions[2]);
+  //  fprintf(stderr,"Output Spacing = %.2f,%.2f,%.2f\n\n",TargetSpacing[0],TargetSpacing[1],TargetSpacing[2]);
+  //  fprintf(stderr,"Output Origin = %.2f,%.2f,%.2f\n\n",TargetOrigin[0],TargetOrigin[1],TargetOrigin[2]);
+  //  fprintf(stderr,"Recomputed Target Sample Distance=%.2f\n",this->TargetSampleDistance);
+
+  ImageReslice->SetOutputOrigin(this->TargetOrigin);
+  ImageReslice->AutoCropOutputOff();
+
+  ImageReslice->SetOutputSpacing(this->TargetSpacing);
+  ImageReslice->SetOutputExtent(0,TargetDimensions[0]-1,0,TargetDimensions[1]-1,0,TargetDimensions[2]-1);
+  ImageReslice->SetInterpolationMode(this->InterpolationMode);
+  ImageReslice->OptimizationOff();
+  ImageReslice->Modified();
+
+  if (this->SecondImageReslice!=NULL)
+    {
+      SecondImageReslice->SetOutputOrigin(this->TargetOrigin);
+      SecondImageReslice->SetOutputSpacing(this->TargetSpacing);
+      SecondImageReslice->SetOutputExtent(0,TargetDimensions[0]-1,0,TargetDimensions[1]-1,0,TargetDimensions[2]-1);
+      SecondImageReslice->SetInterpolationMode(0);
+      SecondImageReslice->Modified();
+    }
+
+}
+
+
+
+// ---------------------------------------------------------------------------
+
+void vtkpxVolume::SetCroppingRange(int bounds[6])
+{
+  if (this->ShiftScale==NULL)
+    return;
+
+  vtkVolumeMapper* map=(vtkVolumeMapper*)this->GetMapper();
+
+  if (map==NULL || this->InputImage==NULL)
+    return;
+
+
+  for (int ia=0;ia<=5;ia++)
+    cropping_range[ia]=bounds[ia];
+
+  for (int ind1=0;ind1<=4;ind1+=2)
+    {
+      int ind2=ind1+1;
+      if (cropping_range[ind1]==cropping_range[ind2])
+	{
+	  if (cropping_range[ind1]>0)
+	    cropping_range[ind1]-=1;
+	  else
+	    cropping_range[ind2]+=1;
+	}
+      else if (cropping_range[ind1]>cropping_range[ind2])
+	{
+	  cropping_range[ind1]=bounds[ind2];
+	  cropping_range[ind2]=bounds[ind1];
+	}
+    }
+
+  map->CroppingOff();
+  /*  fprintf(stderr,"Cropping Range =%d:%d, %d:%d, %d:%d\n",
+	  cropping_range[0],
+	  cropping_range[1],
+	  cropping_range[2],
+	  cropping_range[3],
+	  cropping_range[4],
+	  cropping_range[5]);*/
+  this->SetResliceInterpolationModes(abs(this->ResliceMode),this->InterpolationMode,1);
+}
+
+// ----------------------------------------------------------------------------------
+//   Update and Helper Functions
+// ----------------------------------------------------------------------------------
+
+int vtkpxVolume::Update_IsModeTheSame()
+{
+  if (this->Mapper==NULL )
+    return 0;
+
+  // Alark: Note If Changing number of modes add here
+
+  //printf("volume rendering mode is %d\n", this->VolumeRenderingMode);
+
+  switch (this->VolumeRenderingMode)
+    {
+    case 0:
+		return this->Mapper->IsA("vtkFixedPointVolumeRayCastMapper");
+      break;
+
+    case 1:
+      return this->Mapper->IsA("vtkVolumeRayCastMapper");
+      break;
+
+    case 2:
+      return this->Mapper->IsA("vtkVolumeTextureMapper2D");
+      break;
+    case 3:
+      return this->Mapper->IsA("vtkVolumeTextureMapper3D");
+      break;
+	
+    case 4:
+      return this->Mapper->IsA("vtkCropVolumeRayCastMapper");
+      break;
+
+    case 5:
+      return 0;
+      break;
+
+    case 6:
+      return this->Mapper->IsA("vtkFixedPointVolumeRayCastMapper");
+      break;
+    }
+
+  return 0;
+}
+//------------------------------------------------------------------------------
+int vtkpxVolume::Update_UpdateMapper()
+{
+
+  // Either Bad Mapper
+  if ( this->Mapper == NULL)
+    {
+      vtkErrorMacro(<<"No Mapper Set\n");
+      return 0;
+    }
+
+
+  if (this->Mapper->IsA("vtkVolumeTextureMapper2D"))
+    {
+      ((vtkVolumeTextureMapper2D*)this->Mapper)->SetTargetTextureSize(this->TargetDimensions[0],
+								      this->TargetDimensions[1]);
+      ((vtkVolumeTextureMapper2D*)this->Mapper)->CroppingOff();
+    }
+  else if (this->Mapper->IsA("vtkVolumeTextureMapper3D"))
+    {
+      ((vtkVolumeTextureMapper3D*)this->Mapper)->SetSampleDistance(this->TargetSampleDistance);
+      ((vtkVolumeTextureMapper3D*)this->Mapper)->CroppingOff();
+    }
+  else if (this->Mapper->IsA("vtkFixedPointVolumeRayCastMapper"))
+    {
+      ((vtkFixedPointVolumeRayCastMapper*)this->Mapper)->AutoAdjustSampleDistancesOn();
+      ((vtkFixedPointVolumeRayCastMapper*)this->Mapper)->CroppingOff();
+    }
+  else if (this->Mapper->IsA("vtkVolumeRayCastMapper"))
+    {
+      vtkVolumeRayCastMapper* map=((vtkVolumeRayCastMapper*)this->Mapper);
+      map->CroppingOff();
+      map->SetSampleDistance(this->TargetSampleDistance);
+      vtkVolumeRayCastFunction* funct=map->GetVolumeRayCastFunction();
+
+      int ismip=0,isray=0;
+      if (funct!=NULL)
+	{
+	  ismip=funct->IsA("vtkVolumeRayCastMIPFunction");
+	  isray=funct->IsA("vtkVolumeRayCastCompositeFunction");
+	}
+
+      if (this->VolumeRenderingMode==1 && ismip==0)
+	{
+	  vtkVolumeRayCastMIPFunction* mipFunction=vtkVolumeRayCastMIPFunction::New();
+	  mipFunction->SetMaximizeMethodToScalarValue();
+	  map->SetVolumeRayCastFunction(mipFunction);
+	  mipFunction->Delete();
+	}
+      else if (this->VolumeRenderingMode==0 && isray==0)
+	{
+	 vtkVolumeRayCastCompositeFunction *compositeFunction =
+	   vtkVolumeRayCastCompositeFunction::New();
+	 map->SetVolumeRayCastFunction(compositeFunction);
+	 compositeFunction->Delete();
+	}
+    }
+  else
+    {
+      vtkCropVolumeRayCastMapper *map = ((vtkCropVolumeRayCastMapper*)this->Mapper);
+      //map->SetSampleDistance(this->TargetSampleDistance/4.0);
+      map->CroppingOff();
+      
+      map->AutoAdjustSampleDistancesOn();
+      map->SetImageSampleDistance(.5);
+      map->SetSampleDistance(.25);
+      
+      //map->SelectIrregularShape(this->CropShape);
+      map->SetProbeShape(this->CropShape);
+      
+      // Get probe location for irregular cropping
+      double ptr_location[3];
+      this->GetProbeLocation(ptr_location);
+      
+      
+      map->SetFixedSphereCenter(ptr_location);
+      map->SetFunctionalCropOn(this->cropMode);
+      
+      switch(this->CropShape)
+	{
+	case 0:
+	  map->SetFixedSphereRadius(this->CropSphereRadius);
+	  break;
+	  
+	case 1:
+	  map->SetFixedCubeLength(this->CropCubeLengthX, this->CropCubeLengthY, this->CropCubeLengthZ);
+	  break;
+	case 2:
+	  map->SetFixedEllipseRadius(this->CropEllipseRadiusX, this->CropEllipseRadiusY, this->CropEllipseRadiusZ);
+	  //map->SetSphereSize(this->CropEllipseRadius);
+	  break;
+	  
+	case 3:
+	  map->SetIrregularCropCylinderDimensions(this->CropCylinderRadius, this->CropCylinderHeight, this->direction_vector);
+	  break;
+	  
+	default:
+	  //printf("pxvolume shape selection default\n");
+	  map->SetFixedSphereRadius(this->CropSphereRadius);
+	  break;
+	}
+    }
+
+
+  int canwedorgba=0;
+  //printf("volume mapper name is %s\n", this->Mapper->GetClassName());
+
+  if ( this->Mapper->IsA("vtkVolumeTextureMapper3D") || this->Mapper->IsA("vtkFixedPointVolumeRayCastMapper") || this->Mapper->IsA("vtkCropVolumeRayCastMapper"))
+    canwedorgba=1;
+
+
+  //  fprintf(stderr,"In Update Mapper, candorgba=%d RGBAMOde=%d DualInputMode=%d\n",canwedorgba,this->RGBAMode,this->DualInputMode);
+
+  int doingrgba=0;
+
+  if (this->DualInputMode==1 && canwedorgba==1)
+    {
+      this->ImageBlend->Update();
+      int d[3]; this->ImageBlend->GetOutput()->GetDimensions(d);
+      int nc=this->ImageBlend->GetOutput()->GetNumberOfScalarComponents();
+      /*      fprintf(stderr,"Dual Input Mode is ON (common) %s (%d x %d x %d , %d)\n",this->Mapper->GetClassName(),
+	      d[0],d[1],d[2],nc);*/
+      this->Mapper->SetInput(this->ImageBlend->GetOutput());
+      doingrgba=1;
+
+    }
+  else if (this->RGBAMode==1 && canwedorgba==1)
+    {
+      this->ImageMapToColors->SetLookupTable(this->LookupTable);
+      this->ImageMapToColors->SetInput(ImageReslice->GetOutput());
+      this->ImageMapToColors->Update();
+      int d[3]; this->ImageMapToColors->GetOutput()->GetDimensions(d);
+      int nc=this->ImageMapToColors->GetOutput()->GetNumberOfScalarComponents();
+      /*      fprintf(stderr,"RGBA Mode is ON (common) %s (%d x %d x %d , %d)\n",this->Mapper->GetClassName(),
+	      d[0],d[1],d[2],nc);*/
+      this->Mapper->SetInput(this->ImageMapToColors->GetOutput());
+      doingrgba=1;
+    }
+  else
+    {
+      //      fprintf(stderr,"RGBA Mode is Off %s\n",this->Mapper->GetClassName());
+      this->Mapper->SetInput(ImageReslice->GetOutput());
+      ImageReslice->Update();
+      int d[3]; this->ImageReslice->GetOutput()->GetDimensions(d);
+      int nc=this->ImageReslice->GetOutput()->GetNumberOfScalarComponents();
+      //fprintf(stderr,"RGBA Mode is OFF %s (%d x %d x %d , %d)\n",this->Mapper->GetClassName(), d[0],d[1],d[2],nc);
+    }
+
+  if (ShadingMode)
+    this->Property->ShadeOn();
+  else
+    this->Property->ShadeOff();
+
+  this->Property->SetInterpolationTypeToLinear();
+
+  if(gradientEnhancementMode==1)
+    {
+      //printf("in gradient opacity\n");
+      this->Property->SetGradientOpacity(0, this->gTFun);
+    }
+  else
+    {
+      this->Property->SetGradientOpacity(0, this->gTFun2);
+      //this->Property->SetDisableGradientOpacity(0, 1);
+    }
+
+
+
+  this->Property->SetColor(this->cTFun);
+  this->Property->SetScalarOpacity(0,this->oTFun);
+
+  if (doingrgba==1)
+    {
+      this->Property->IndependentComponentsOff();
+    }
+
+  this->Mapper->Update();
+
+  return 1;
+}
+//------------------------------------------------------------------------------
+void vtkpxVolume::Update()
+{
+  if (ImageReslice==NULL)
+      return;
+
+  // Texture Mode
+  // 1 = Texture Mapping
+  // 0  = Ray Casting Normal
+  // -1 = Ray Casting MIP
+
+
+
+
+  int proceed=this->Update_IsModeTheSame();
+  //fprintf(stderr,"\nIn Update, DualInputMode=%d proceed=%d RGBAMode_changed %d\n",this->DualInputMode,proceed, this->RGBAMode_changed);
+
+
+	 if(this->RGBAMode_changed == 1)
+	 {
+		if (proceed==1)
+		{
+		  this->Update_UpdateMapper();
+		  return;
+		}
+		this->RGBAMode_changed = 0;
+	 }
+
+  // Alark: Note If Changing number of modes add here
+  if (this->VolumeRenderingMode<0)
+    this->VolumeRenderingMode=0;
+  else if (this->VolumeRenderingMode>5)
+    this->VolumeRenderingMode=5;
+
+  // Create the Mapper Here
+
+  if (this->Mapper)
+    this->Mapper->Delete();
+
+    //fprintf(stderr,"Creating a new Mapper mode = %d\n",this->VolumeRenderingMode);
+
+  switch (this->VolumeRenderingMode)
+    {
+    case 1: // MIP
+      this->Mapper=vtkVolumeRayCastMapper::New();
+      break;
+    case 2: // Text2D
+      this->Mapper=vtkVolumeTextureMapper2D::New();
+      break;
+    case 3: // Text3D
+      this->Mapper=vtkVolumeTextureMapper3D::New();
+      break;
+    case 4: // Cropped
+      //this->Mapper=vtkCroppedVolumeRayCastMapper::New();
+      this->Mapper = vtkCropVolumeRayCastMapper::New();
+      break;
+    default: // RayCast or Default
+      this->Mapper=vtkFixedPointVolumeRayCastMapper::New();
+      break;
+    }
+
+
+  if (this->Mapper!=NULL)
+    {
+      this->Update_UpdateMapper();
+    }
+  else
+    {
+      vtkErrorMacro(<<"Bad Update \n");
+    }
+}
+// ---------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Graphics/vtkpxVolume.h b/bioimagesuite30_src/Graphics/vtkpxVolume.h
new file mode 100644
index 0000000..587b456
--- /dev/null
+++ b/bioimagesuite30_src/Graphics/vtkpxVolume.h
@@ -0,0 +1,316 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxVolume.h,v $
+  Language:  C++
+  Date:      $Date: 2005/11/11 15:11:09 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxVolume - represents a volume (data & properties) in a rendered scene
+//
+// .SECTION Description
+// vtkpxVolume is a derived class of vtkVolume which was used
+//  to represent a volumetric entity in a rendering scene.
+// It's additional features include (mandatory)
+// internal mappers and switching of modes as well as
+// The use of a lookup table
+//
+// .SECTION see also
+// vtkVolume vtkVolumeMapper vtkVolumeProperty vtkProp3D
+
+#ifndef __vtkpxVolume_h
+#define __vtkpxVolume_h
+
+class vtkPiecewiseFunction;
+class vtkColorTransferFunction;
+class vtkLookupTable;
+class vtkImageShiftScale;
+class vtkVolumeMapper;
+class vtkImageReslice;
+class vtkImageExtractComponents;
+class vtkImageMapToColors;
+class vtkImageBlend;
+class vtkImageMapToRGBA; 
+
+class vtkCudaVolumeMapper; 
+
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkVolume.h"
+
+class vtkpxVolume : public vtkVolume
+{
+public:
+  vtkTypeMacro(vtkpxVolume,vtkVolume);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Creates a Volume with the following defaults: origin(0,0,0) 
+  // position=(0,0,0) scale=1 visibility=1 pickable=1 dragable=1
+  static vtkpxVolume *New();
+
+  // Description:
+  virtual void SetVolumeRenderingMode(int text);
+  vtkGetMacro(VolumeRenderingMode,int);
+  virtual void SetVolumeRenderingModeToRayCast() { this->SetVolumeRenderingMode(0);}
+  virtual void SetVolumeRenderingModeToMIP() { this->SetVolumeRenderingMode(1);}
+  virtual void SetVolumeRenderingModeToTextureMap() { this->SetVolumeRenderingMode(2);}
+  virtual void SetVolumeRenderingModeToTextureMap3D() { this->SetVolumeRenderingMode(3);}
+  virtual void SetVolumeRenderingModeToCroppedRayCast() { this->SetVolumeRenderingMode(4);}
+  virtual void SetVolumeRenderingModeToCUDA() { this->SetVolumeRenderingMode(5);}
+
+
+  // Description:
+  // Set Cropping Mode 1=Yes, 0=No
+  void SetIrregularCroppingMode(int inputCropMode);
+  vtkGetMacro(cropMode,int);
+
+  // Description:
+  // Set Cropping Mode 1=Yes, 0=No
+  void SetGradientEnhancementMode(int inputgradientEnhancementMode);
+  vtkGetMacro(gradientEnhancementMode,int);
+
+   // Description:
+  // Set Cropping Mode 1=Yes, 0=No
+  void SetCropValues(int shapeIndex, double SphereRadius, double CubeLengthX, double CubeLengthY, double CubeLengthZ, double EllipseRadiusX, double EllipseRadiusY,  double EllipseRadiusZ, double CylinderRadius, double CylinderHeight, double dirvec[3]);
+  
+
+  // Description:
+  // Set Reslice Factor, to shrink image before rendering
+  void SetResliceMode(int re);
+  vtkGetMacro(ResliceMode,int);
+
+  // Description:
+  // Set Reslice Factor, to shrink image before rendering
+  void SetDualInputMode(int m);
+  vtkGetMacro(DualInputMode,int);
+
+  
+  // Description:
+  // Set Reslice Factor, to shrink image before rendering
+  virtual void SetRGBAMode(int m);
+  vtkGetMacro(RGBAMode,int);
+
+  // Description:
+  // Reslice Mode Macros 
+  void SetResliceModeToOriginal() { this->SetResliceMode(0); }
+  void SetResliceModeToHalfOriginal() { this->SetResliceMode(1); }
+  void SetResliceModeToQuarterOriginal() { this->SetResliceMode(2); }
+  void SetResliceModeTo64_64() { this->SetResliceMode(3); }
+  void SetResliceModeTo128_64() { this->SetResliceMode(4); }
+  void SetResliceModeTo128_128() { this->SetResliceMode(5); }
+  void SetResliceModeTo256_128() { this->SetResliceMode(6); }
+  void SetResliceModeTo256_256() { this->SetResliceMode(7); }
+  void SetResliceModeTo512_256() { this->SetResliceMode(8); }
+  void SetResliceModeTo512_512() { this->SetResliceMode(9); }
+  
+
+  // Description:
+  // Set Reslice Factor, to shrink image before rendering
+  void SetInterpolationMode(int re);
+  vtkGetMacro(InterpolationMode,int);
+
+  // Description:
+  // Set Smooth and Reslice Factors
+  void SetResliceInterpolationModes(int re,int interp,int force=0);
+
+  // Description:
+  // Set Shading Mode 1=Yes, 0=No
+  void SetShadingMode(int shad);
+  vtkGetMacro(ShadingMode,int);
+
+  // Description:
+  // Max Intensity
+  vtkGetMacro(MaxIntensity,int);
+
+  // Description:
+  // Set Transparency/Intensity from LookupTable
+  virtual void SetFromLookupTable(vtkLookupTable* table);
+  virtual void SetSecondLookupTable(vtkLookupTable* table);
+
+  // Description:
+  // Update 
+  virtual void Update();
+  virtual void UpdateRange();
+
+  // Description:
+  // Cropping Stuff
+  virtual void               GetImageRange(int bounds[6]);
+  virtual void               GetCroppingRange(int bounds[6]);
+  virtual void               SetCroppingRange(int bounds[6]);
+  virtual void               ResetCroppingRange();
+
+
+  // irregular cropping functions 
+  virtual void               GetProbeLocation(double probeLocation[3]);
+  virtual void               SetProbeLocation(double probeLocation[3]);
+
+
+  // Description:
+  // Set Input Image
+  virtual void SetInput(vtkImageData* image);
+  virtual void SetInput(vtkImageData* image,int orientation);
+  virtual void SetSecondInput(vtkImageData* img);
+
+
+  vtkImageData* GetInputImage() { return this->InputImage;}
+  vtkImageData* GetSecondInputImage() { return this->SecondInputImage;}
+
+  // Description:
+  // Set Frame Number
+  virtual void SetFrame(int frame);
+
+  // Description:
+  // WARNING: INTERNAL METHOD - NOT INTENDED FOR GENERAL USE
+  // DO NOT USE THIS METHOD OUTSIDE OF THE RENDERING PROCESS
+  // Support the standard render methods.
+  // Depending on the mapper type, the volume may be rendered using
+  // this method (FRAMEBUFFER volume such as texture mapping will
+  // be rendered this way)
+  int RenderTranslucentGeometry(vtkViewport *viewport);
+
+  // Description:
+  // Get Min/Max Value for Colormap
+  vtkGetMacro(MinValue,float);
+  vtkGetMacro(MaxValue,float);
+
+protected: 
+
+  
+  vtkpxVolume();
+  virtual ~vtkpxVolume();
+
+  // Made inaccesible 
+  // Description:
+  // Set The Mapper 
+  virtual void SetMapper(vtkVolumeMapper *mapper);
+
+  // Description:
+  // Set/Get the volume property.
+  virtual void SetProperty(vtkVolumeProperty *property);
+
+  
+
+  float MinValue;
+  float MaxValue;
+  int VolumeRenderingMode;
+  int ShadingMode;
+  int cropMode;
+  int gradientEnhancementMode;
+  double probeLocation[3]; 
+  int cropping_range[6];
+  int ResliceMode;
+  int  InterpolationMode;
+  int RGBAMode;	
+  int RGBAMode_changed; 
+  int DualInputMode;
+
+  // Cropping parameters
+  int CropShape;
+  double CropSphereRadius;
+  double CropCubeLengthX;
+  double CropCubeLengthY;
+  double CropCubeLengthZ;
+  double CropEllipseRadiusX;
+  double CropEllipseRadiusY;
+  double CropEllipseRadiusZ;  
+  double direction_vector[3];
+  double CropCylinderRadius; 
+  double CropCylinderHeight; 
+
+
+  int                          MaxIntensity;
+  int                          Frame;
+  int                          Orientation;
+  int                          NumberOfFrames;
+  int                          TargetDimensions[3];
+  double                        TargetOrigin[3];
+  double                        TargetSpacing[3];
+  double                        TargetSampleDistance;
+
+
+  vtkImageExtractComponents*   ExtractFrame;
+  vtkImageExtractComponents*   SecondExtractFrame;
+
+  vtkImageShiftScale*          ShiftScale;
+  vtkImageShiftScale*          SecondShiftScale;
+
+  vtkImageReslice*             ImageReslice;
+  vtkImageReslice*             SecondImageReslice;
+
+  vtkImageBlend*               ImageBlend;
+  vtkImageMapToRGBA*         ImageMapToRGBA1;
+  vtkImageMapToRGBA*         ImageMapToRGBA2;
+  vtkImageMapToColors*         ImageMapToColors;	
+
+  vtkImageData*                InputImage;
+  vtkImageData*                SecondInputImage;
+
+
+  vtkColorTransferFunction     *cTFun;
+  vtkPiecewiseFunction         *oTFun;
+  vtkPiecewiseFunction         *gTFun;
+  vtkPiecewiseFunction         *gTFun2;
+  vtkPiecewiseFunction         *dualTransferFunction;
+  vtkLookupTable               *LookupTable;
+  vtkLookupTable               *SecondLookupTable;
+
+
+
+  // Description:
+  // Update Helper Functions
+  virtual int Update_IsModeTheSame();
+  virtual int Update_UpdateMapper();
+
+};
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Imaging/CMakeLists.txt b/bioimagesuite30_src/Imaging/CMakeLists.txt
new file mode 100644
index 0000000..043e8de
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/CMakeLists.txt
@@ -0,0 +1,246 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+SET(KITBASE Imaging)
+SET(KIT vtkpx${KITBASE})
+
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/${KITBASE})
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Graphics)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Connectivity)
+INCLUDE_DIRECTORIES(${ITK_INCLUDE_DIRS})
+
+
+
+SET (KITSRCS
+vtkbisImageAverageComponents.cpp
+vtkpxBinaryImageMedian3D.cpp
+vtkpxCreateCheckerBoardImage.cpp
+vtkpxCSIStackImages.cpp
+vtkpxImageAlgebra.cpp
+vtkpxImageCylindricalCrop.cpp
+vtkpxImageIDFilter.cpp
+vtkpxImageAddGaussianNoise.cpp
+vtkpxImageVariableSmoothing.cpp
+vtkpxImageFeatureExtract.cpp
+vtkpxImageGaussianNoiseSource.cpp
+vtkpxImageNormalizeIntensity.cpp
+vtkpxImageComputeNormalizedDifference.cpp
+vtkpxImageComputeNormalizedRatio.cpp
+vtkpxImageMask.cpp
+vtkpxImageNormalizeIntensityToReference.cpp
+vtkpxImageComputeVOIStats.cpp
+vtkpxImagePolarToEuclidean.cpp
+vtkpxImageSincInterpolation.cpp
+vtkpxImageStitch.cpp
+vtkpxImageHistogramEqualization.cpp
+vtkpxSimpleImageThreshold.cpp
+vtkpxWeightedSmoothImage.cpp
+vtkpxImageCorrectNonUniformZ.cpp
+vtkpxImageAttenuationCorrection.cpp
+vtkpxMaximumImages.cpp
+vtkpxImageThresholdedIntersection.cpp
+#vtkpxImageAnisotropicDiffusion3D.cpp
+vtkpxNormalizedSmoothImage.cpp
+vtkxqImageHessian.cpp
+vtkxqImageVesselEnhancement.cpp
+vtkpxImageReorientTensorOrVector.cpp
+vtkdsSpectUtil.cpp
+vtkbisObjectmapRegularization.cpp
+vtkxqImageKMeansVesselnessFilter.cpp
+vtkxqImageODFVesselnessFilter.cpp
+vtkxqImageFourierConvolution.cpp
+vtkpxAverageImages.cpp
+#
+#
+# From old Nmrlib
+#
+vtkpxAddMotionToTimeSeries.cpp
+#vtkpxComputeFieldMap.cpp
+#vtkpxComputeFieldConstant.cpp
+#vtkpxComputeShims.cpp
+#vtkpxComputeShimsNmr47.cpp
+vtkpxComputeTmap.cpp
+vtkpxCreateSyntheticFmri.cpp
+vtkpxCreateThickSlices.cpp
+vtkpxImageAddPhaseCorrection.cpp
+vtkpxImageRemoveLinearPhase.cpp
+vtkpxMergeFmriConventional.cpp
+vtkpxProcessFmri.cpp
+vtkpxProcessRawBrukerFIDImage.cpp
+#vtkpxExtractMarkersUtil.cpp
+#vtkpxExtractCylindricalMarkers.cpp
+#vtkpxEpiDistortionModel.cpp
+vtknrImageCluster.cpp
+#
+# MRS Stuff
+#
+vtkpxPhaseCorrectCSIData.cpp
+vtkpxCSIOffsetCorrection.cpp
+#pet stuff
+#vtkbisMRTM.cpp
+#vtkbisMRTM2.cpp
+#vtkbisMRTM3.cpp
+#vtkmsMRTM2.cpp
+# AFNI Inspired/Derived Modules
+#
+vtkbisWaver.cpp
+vtkbisTimeSeriesNormalize.cpp
+vtkbisComputeGLM.cpp
+#vtkbisImageCluster.cpp
+#vtkbisMonteCarlo.cpp
+vtkbisCudaFFT.cpp
+vtkbisCudaRFFT.cpp
+vtkbisCudaConvolution.cpp
+vtkbisCudaEdgeDetect.cpp
+vtkbisCudaHessian.cpp
+#
+vtkbisZscoretoPvalue.cpp
+vtkbisRtoTmap.cpp
+vtkbisFDR.cpp
+vtkbisImageUtil.cpp
+vtkbisRtoPvalue.cpp
+#
+vtkbisSiemensMosaicConverter.cpp
+vtkbisSiemensDWIArrange.cpp
+)
+
+IF(BIOIMAGESUITE3_HAVE_PET_SOURCE)
+SET (KITSRCS
+${KITSRCS}
+vtkbisMRTM.cpp
+vtkbisMRTM2.cpp
+)
+ENDIF(BIOIMAGESUITE3_HAVE_PET_SOURCE)
+
+# Excluded TCL Code 
+
+# ----------------------------------------------
+# CUDA Conditional Compilation
+# -----------------------------------------------
+
+IF (BIOIMAGESUITE3_USE_CUDA)
+
+  SET (KITSRCS
+    ${KITSRCS}
+    vtkbisCUDAUtil.cpp
+    vtkbisCUDASparseMatrix.cpp
+    vtkbisCUDAROICorrelation.cpp
+    vtkbisCUDAIntrinsicCorrelation.cpp
+    )
+
+  SET(CUDAKIT vtkpx${KITBASE}_Cuda)
+
+  CUDA_INCLUDE_DIRECTORIES(
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    )
+  
+  
+  CUDA_ADD_LIBRARY(${CUDAKIT} STATIC 
+    edgedetection.cu
+    convolution.cu
+    convolutionFFT.cu
+    convolutionRFFT.cu
+    biscudautil.cu
+    biscorrelation.cu
+    rglm.cu	
+    )
+  TARGET_LINK_LIBRARIES (${CUDAKIT} ${KITLIBS})
+  install (TARGETS ${CUDAKIT} DESTINATION lib)
+
+  
+
+
+  SET_SOURCE_FILES_PROPERTIES(
+    edgedetection.cu
+    convolution.cu
+    convolutionFFT.cu
+    convolutionRFFT.cu
+    rglm.cu
+    biscudautil.cu
+    WRAP_EXCLUDE
+    )
+
+
+  
+ELSE(BIOIMAGESUITE3_USE_CUDA)
+  SET (CUDAKIT )
+ENDIF(BIOIMAGESUITE3_USE_CUDA)
+# -----------------------------------------------
+
+
+
+SET(KITLIBS
+  vtkpxCommon
+  vtkpxCommonTCL
+  ${CUDAKIT}
+  numerics
+  vtkCommonTCL
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+)
+
+SET(KITJAVALIBS
+  vtkpxCommonJava
+  vtkpxCommon
+  ${CUDAKIT}
+  numerics
+  vtkFilteringJava
+  ${BIOIMAGESUITE3_COMMON_JAVALIBS}
+)
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+IF (BIOIMAGESUITE3_USE_CUDA)
+SET (KITEXTRAFILES
+  Imaging/edgedetection.cu
+  Imaging/convolutionFFT.cu
+  Imaging/convolutionRFFT.cu
+  Imaging/convolution.cu
+  Imaging/rglm.cu
+  Imaging/book.h
+  Imaging/biscudautil.cu
+  Imaging/biscudacommon.h
+  Imaging/biscorrelation.cu
+  Imaging/biscorrelation.h
+  )
+ENDIF (BIOIMAGESUITE3_USE_CUDA)
+
+SET (KITTCLSRCS )
+bis_complex("Imaging" ${KIT} ${FILELIST})
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisComputeGLM.cpp b/bioimagesuite30_src/Imaging/vtkbisComputeGLM.cpp
new file mode 100644
index 0000000..5646a42
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisComputeGLM.cpp
@@ -0,0 +1,675 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkbisComputeGLM.h"
+#include "vtkpxAnalyzeImageWriter.h"
+
+vtkbisComputeGLM* vtkbisComputeGLM::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisComputeGLM");
+  if(ret)
+    {
+      return (vtkbisComputeGLM*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisComputeGLM;
+}
+
+vtkbisComputeGLM::vtkbisComputeGLM()
+{
+  this->DebugName=NULL;
+  this->ImageMask=NULL;
+  this->ResidualImage=NULL;
+  this->TmapImage=NULL;
+  this->UnfitTimeSeries=NULL;
+  this->DriftBetaValues=NULL;
+  this->RegressorMatrix=NULL;
+  this->NULLRegressorMatrix=vtkpxMatrix::New();
+  this->OrderOfFstatDriftPolynomial=3;
+  this->NumberOfTasks=-1;
+  this->TempMatrix1=vtkpxMatrix::New();
+  this->TempMatrix2=vtkpxMatrix::New();
+  this->TempMatrix3=vtkpxMatrix::New();
+  this->TempMatrix4=vtkpxMatrix::New();
+
+  this->DebugIndex=-1;
+  //  this->DebugIndex=51232;
+  //  this->SetDebugName("test43");
+}
+
+vtkbisComputeGLM::~vtkbisComputeGLM()
+{
+  if (this->DebugName!=NULL)
+    delete [] this->DebugName;
+
+  this->SetImageMask(NULL);
+  this->SetResidualImage(NULL);
+  this->SetTmapImage(NULL);
+  this->SetRegressorMatrix(NULL);
+  this->SetUnfitTimeSeries(NULL);
+  this->SetDriftBetaValues(NULL);
+  this->TempMatrix1->Delete();
+  this->TempMatrix2->Delete();
+  this->TempMatrix3->Delete();
+  this->TempMatrix4->Delete();
+  this->NULLRegressorMatrix->Delete();
+
+
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisComputeGLM::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+
+  int nt=this->NumberOfTasks;
+  if (this->RegressorMatrix!=NULL)
+    {
+      int sz[2]; this->RegressorMatrix->GetSize(sz);
+      if (nt>sz[1] || nt<1)
+	nt=sz[1];
+    }
+
+  if (nt<0)
+    nt=1;
+
+  output->SetScalarTypeToFloat();
+  output->SetNumberOfScalarComponents(nt+1);
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+/*
+  Problem =  A x = B  where X is unknown
+
+ First premultiply by A':  A'A x = A'B
+ Solution x = (A'A)^{-1}.A'.B
+
+  LSQ = (A'A)^{-1}.A'
+*/
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisComputeGLM::CreateNULLRegressorMarix(vtkpxMatrix* output,vtkpxMatrix* regressor,int order)
+{
+  int sz[2]; regressor->GetSize(sz);
+  output->Zeros(sz[0],order+1);
+
+  double t0=0.0;
+  double t1=double(sz[0]-1);
+  double dt=0.5*(t1-t0);
+
+
+  for (int row=0;row<sz[0];row++)
+    {
+      double r=double(row);
+      double t=(r-t0)/dt-1.0;
+      double t2=t*t;
+      double t3=t*t2;
+
+      for (int pol=0;pol<=order;pol++)
+	{
+	  switch(pol)
+	    {
+	    case 0: // P_0(x)=1;
+	      output->SetDirectElement(row,pol,1.0);
+	      break;
+	    case 1: // P_1(x)=x;
+	      output->SetDirectElement(row,pol,t);
+	      break;
+	    case 2: // P_2(x)=0.5*(3x^2-1)
+	      output->SetDirectElement(row,pol,1.5*t2-0.5);
+	      break;
+	    case 3: // P_3(x) =0.5*(5x^3-3x)
+	      output->SetDirectElement(row,pol,2.5*t3-1.5*t);
+	      break;
+	    }
+	}
+    }
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+
+vtkpxMatrix* vtkbisComputeGLM::ComputeLSQMatrix(vtkpxMatrix* A,vtkpxMatrix* S2BMatrix)
+{
+  vtkpxMatrix* At=vtkpxMatrix::New();
+  At->Copy(A);
+  At->Transpose();
+
+  vtkpxMatrix* AtA=vtkpxMatrix::New();
+  if (S2BMatrix!=NULL)
+    AtA=S2BMatrix;
+  else
+    AtA=vtkpxMatrix::New();
+
+  vtkpxMatrix::Multiply(At,A,AtA);
+  AtA->Invert();
+
+
+  vtkpxMatrix* LSQ=vtkpxMatrix::New();
+  vtkpxMatrix::Multiply(AtA,At,LSQ);
+
+  if (S2BMatrix==NULL)
+    AtA->Delete();
+  At->Delete();
+
+  return LSQ;
+
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisComputeGLM::StoreVoxelIndexIntoColumn(vtkDataArray* dat,int index,vtkpxMatrix* colvect)
+{
+  int nc=dat->GetNumberOfComponents();
+  colvect->Zeros(nc,1);
+  for (int i=0;i<nc;i++)
+    colvect->SetDirectElement(i,0,dat->GetComponent(index,i));
+}
+
+void vtkbisComputeGLM::StoreColumnIntoVoxelIndex(vtkpxMatrix* vect,vtkDataArray* dat,int index)
+{
+  int nc=dat->GetNumberOfComponents();
+  for (int i=0;i<nc;i++)
+    dat->SetComponent(index,i,vect->GetDirectElement(i,0));
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------
+//    r = || A.beta - colvect ||
+// ---------------------------------------------------------------------------------------------------------------------------
+
+double vtkbisComputeGLM::ComputeFStats(vtkpxMatrix* A,vtkpxMatrix* ReducedA,vtkpxMatrix* beta,vtkpxMatrix* nullbeta,
+				       vtkpxMatrix* colvect,double factor,double tmapdof,vtkDataArray* res,vtkDataArray* unfit,int index,int debug)
+{
+  vtkpxMatrix::Multiply(A,beta,this->TempMatrix1);
+  vtkpxMatrix::Add(1.0,this->TempMatrix1,-1.0,colvect,this->TempMatrix2);
+
+  int nc=unfit->GetNumberOfComponents();
+  for (int i=0;i<nc;i++)
+    unfit->SetComponent(index,i,-1.0*this->TempMatrix2->GetDirectElement(i,0));
+  double SSEF=this->TempMatrix2->SumSquares();
+
+  if (debug)
+    {
+      A->Save("A.matr");
+      ReducedA->Save("RA.matr");
+      beta->Save("beta.matr");
+      colvect->Save("col.matr");
+      this->TempMatrix1->Save("t1.matr");
+      this->TempMatrix2->Save("t2.matr");
+      fprintf(stdout,"SSEF = %f\n",SSEF);
+    }
+
+
+  double MSE=(SSEF/tmapdof);
+
+
+  vtkpxMatrix::Multiply(ReducedA,nullbeta,this->TempMatrix3);
+  vtkpxMatrix::Add(1.0,this->TempMatrix3,-1.0,colvect,this->TempMatrix4);
+  double SSEB=this->TempMatrix4->SumSquares();
+
+  res->SetComponent(index,0,MSE);
+
+  if (debug)
+    {
+      this->TempMatrix1->Save("rbeta.matr");
+      this->TempMatrix3->Save("t3.matr");
+      this->TempMatrix4->Save("t4.matr");
+      fprintf(stdout,"SSEB = %f\n",SSEB);
+      fprintf(stdout,"index=%d\n",index);
+      fprintf(stdout,"MSE =%f\n",res->GetComponent(index,0));
+      fprintf(stdout,"R^2  = %f\n",1.0-SSEF/SSEB);
+      beta->Print("B=");
+    }
+
+
+  if (SSEF<0.0001)
+    return -1.0;
+
+  double f = factor*(SSEB-SSEF)/SSEF;
+
+  if (debug)
+    fprintf(stdout,"F-Stat=%f\n",f);
+
+  return f;
+
+}
+
+
+
+
+
+// ---------------------------------------------------------------------------------------------------------------------------
+//   beta= LSQ * colvect
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisComputeGLM::ComputeBetas(vtkpxMatrix* LSQ,vtkpxMatrix* beta,vtkpxMatrix* colvect)
+{
+  vtkpxMatrix::Multiply(LSQ,colvect,beta);
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisComputeGLM::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+
+  fprintf(stdout,"Beginning ComputeGLM\n");
+
+  if (input==NULL || output==NULL || this->RegressorMatrix==NULL)
+    {
+      fprintf(stdout,"Bad Image Input to vtkbisComputeGLM SimpleExecute\n");
+      return;
+    }
+
+
+  if (this->ImageMask!=NULL)
+    {
+      int dim[3]; this->ImageMask->GetDimensions(dim);
+      int dim2[3]; input->GetDimensions(dim2);
+      int sum=0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=abs(dim[ia]-dim2[ia]);
+      if (sum>0)
+	fprintf(stdout,"Bad Mask Input to vtkbisComputeGLM SimpleExecute\n");
+      return;
+    }
+
+
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  int nt=inp->GetNumberOfTuples();
+  int nc=inp->GetNumberOfComponents();
+
+  int sz[2]; this->RegressorMatrix->GetSize(sz);
+  if (sz[0]!=nc)
+    {
+      fprintf(stdout,"Bad Regressor Matrix %d x %d numframes=%d\n",sz[0],sz[1],nc);
+      return;
+    }
+
+  int nc2=output->GetNumberOfScalarComponents();
+  int numdrift=sz[1]-this->NumberOfTasks;
+  int maxtask=sz[1];
+
+  // First Component of output is f-stat
+  if ( (maxtask-numdrift)!=(nc2-1))
+    {
+      fprintf(stdout,"Bad Task Number Matrix %d x %d (Task columns %d:%d) vs output numframes=%d\n",sz[0],sz[1],
+	      numdrift,maxtask,nc2-1);
+      return;
+    }
+
+
+  if (this->ResidualImage!=NULL)
+    this->ResidualImage->Delete();
+
+  this->ResidualImage=vtkImageData::New();
+  this->ResidualImage->CopyStructure(input);
+  this->ResidualImage->SetNumberOfScalarComponents(1);
+  this->ResidualImage->SetScalarTypeToFloat();
+  this->ResidualImage->AllocateScalars();
+
+  if (this->UnfitTimeSeries!=NULL)
+    this->UnfitTimeSeries->Delete();
+
+  this->UnfitTimeSeries=vtkImageData::New();
+  this->UnfitTimeSeries->CopyStructure(input);
+  this->UnfitTimeSeries->SetNumberOfScalarComponents(input->GetNumberOfScalarComponents());
+  this->UnfitTimeSeries->SetScalarTypeToFloat();
+  this->UnfitTimeSeries->AllocateScalars();
+
+  int createnullregressormatrix=0;
+  if (numdrift<1)
+    {
+      createnullregressormatrix=1;
+      if (this->OrderOfFstatDriftPolynomial<0)
+	this->OrderOfFstatDriftPolynomial=0;
+      else if (this->OrderOfFstatDriftPolynomial>3)
+	this->OrderOfFstatDriftPolynomial=3;
+      numdrift=this->OrderOfFstatDriftPolynomial+1;
+    }
+
+  if (this->DriftBetaValues!=NULL)
+    this->DriftBetaValues->Delete();
+
+  this->DriftBetaValues=vtkImageData::New();
+  this->DriftBetaValues->CopyStructure(input);
+  this->DriftBetaValues->SetNumberOfScalarComponents(numdrift);
+  this->DriftBetaValues->SetScalarTypeToFloat();
+  this->DriftBetaValues->AllocateScalars();
+  vtkDataArray* driftbeta=this->DriftBetaValues->GetPointData()->GetScalars();
+  for (int ia=0;ia<driftbeta->GetNumberOfComponents();ia++)
+    driftbeta->FillComponent(ia,0.0);
+  fprintf(stdout,"Done allocating DriftBetaValues numc=%d (numdrift=%d)\n",driftbeta->GetNumberOfComponents(),numdrift);
+
+  if (this->TmapImage!=NULL)
+    this->TmapImage->Delete();
+  this->TmapImage=vtkImageData::New();
+  this->TmapImage->CopyStructure(output);
+  this->TmapImage->SetNumberOfScalarComponents(output->GetNumberOfScalarComponents());
+  this->TmapImage->AllocateScalars();
+
+  fprintf(stdout,"Done Allocating Memory, %d, %d\n",
+	  output->GetNumberOfScalarComponents(),
+	  this->TmapImage->GetNumberOfScalarComponents());
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* tmap=this->TmapImage->GetPointData()->GetScalars();
+  for (int ia=0;ia<nc2;ia++)
+    {
+      out->FillComponent(ia,0.0);
+      tmap->FillComponent(ia,0.0);
+    }
+
+  vtkDataArray* res=this->ResidualImage->GetPointData()->GetScalars();
+  res->FillComponent(0,0.0);
+
+  vtkDataArray* unfit=this->UnfitTimeSeries->GetPointData()->GetScalars();
+
+
+  vtkDataArray* msk=NULL;
+  if (this->ImageMask!=NULL)
+    msk=this->ImageMask->GetPointData()->GetScalars();
+
+  //  fprintf(stdout,"All Set to GO out numcomponents=%d\n",nc2);
+
+  if (createnullregressormatrix==0)
+    {
+      fprintf(stdout,"Creating NULL Regressor Matrix from first %d columns of Regressor Matrix\n",numdrift);
+      this->NULLRegressorMatrix->Copy(this->RegressorMatrix,-1,-1,0,numdrift-1);
+    }
+  else
+    {
+      fprintf(stdout,"Creating NULL Regressor Matrix with %d columns as direct polynomail fit\n",numdrift);
+      this->CreateNULLRegressorMarix(this->NULLRegressorMatrix,this->RegressorMatrix,numdrift-1);
+    }
+
+  vtkpxMatrix* S2BMatrix=vtkpxMatrix::New();
+  vtkpxMatrix* LSQ=this->ComputeLSQMatrix(this->RegressorMatrix,S2BMatrix);
+
+  int sk[2]; S2BMatrix->GetSize(sk);
+  for (int ia=0;ia<sk[0];ia++)
+    {
+      double v=S2BMatrix->GetElement(ia,ia);
+      S2BMatrix->SetElement(ia,ia,sqrt(v));
+    }
+
+  vtkpxMatrix* NULL_LSQ=this->ComputeLSQMatrix(this->NULLRegressorMatrix);
+
+  std::string debugfname;
+  if (this->DebugName!=NULL)
+    {
+      debugfname=this->DebugName; debugfname+="_lsq.matr";
+      LSQ->Save(debugfname.c_str());
+      fprintf(stdout,"LSQ Matrix Saved in %s\n",debugfname.c_str());
+
+      debugfname=this->DebugName; debugfname+="_drift.matr";
+      this->NULLRegressorMatrix->Save(debugfname.c_str());
+      fprintf(stdout,"NULL Regressor Matrix Saved in %s\n",debugfname.c_str());
+    }
+
+
+  vtkpxMatrix* colvect=vtkpxMatrix::New();
+  colvect->Zeros(nc,1);
+  this->TempMatrix1->Zeros(nc,1);
+  this->TempMatrix2->Zeros(nc,1);
+  this->TempMatrix3->Zeros(numdrift,1);
+  this->TempMatrix4->Zeros(numdrift,1);
+
+
+  vtkpxMatrix* betas=vtkpxMatrix::New();
+  vtkpxMatrix* null_betas=vtkpxMatrix::New();
+  betas->Zeros(1,sz[1]);
+  null_betas->Zeros(1,sz[1]);
+
+  int maxcount=int(nt/10);
+  int count=0;
+  double pog=0.0;
+  this->UpdateProgress(0.01);
+  fprintf(stdout,"GLM Compute : ");
+  int numdone=0;
+
+  // factor= dff/(dfb-dff)
+  double factor_forfstat= double(sz[0]-sz[1])/double(this->NumberOfTasks);
+  double tmapdof=(sz[0]-sz[1]);
+  fprintf(stdout,"Factor for fstat=%f nummdof for tmap=%f\n",factor_forfstat,tmapdof);
+
+  int found=0;
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      int dodebugsave=0;
+      if (this->DebugName!=NULL && voxel==this->DebugIndex)
+	dodebugsave=1;
+
+      int doglm=1;
+      if (msk!=NULL)
+	{
+	  if (msk->GetComponent(voxel,0)<1)
+	    doglm=0;
+	}
+      else
+	{
+	  this->StoreVoxelIndexIntoColumn(inp,voxel,colvect);
+	  double a=colvect->SumMagnitude();
+	  if (a<0.001)
+	    doglm=0;
+	}
+
+      if (doglm==1)
+	{
+	  // Step 1
+
+
+	  if (dodebugsave)
+	    {
+	      debugfname=this->DebugName; debugfname+="_vect.matr";
+	      colvect->Save(debugfname.c_str());
+	      fprintf(stdout,"Column Vector Saved in %s\n",debugfname.c_str());
+	    }
+
+	  this->ComputeBetas(LSQ,betas,colvect);
+	  this->ComputeBetas(NULL_LSQ,null_betas,colvect);
+	  if (dodebugsave)
+	    {
+	      debugfname=this->DebugName; debugfname+="_betas.matr";
+	      betas->Save(debugfname.c_str());
+	      fprintf(stdout,"Beta Vector Saved in %s\n",debugfname.c_str());
+	    }
+
+
+	  double f=this->ComputeFStats(this->RegressorMatrix,this->NULLRegressorMatrix,betas,null_betas,colvect,
+				       factor_forfstat,tmapdof,res,unfit,voxel,dodebugsave);
+
+	  out->SetComponent(voxel,0,f);
+	  double MSE=res->GetComponent(voxel,0);
+	  tmap->SetComponent(voxel,0,MSE);
+	  double sqMSE=sqrt(MSE);
+
+	  for (int task=numdrift;task<maxtask;task++)
+	    {
+	      int outind=task-numdrift+1;
+	      double b=betas->GetElement(task,0);
+	      out->SetComponent(voxel,outind,b);
+
+	      if (dodebugsave)
+		fprintf(stdout,"Storing voxel=%d outind=%d with beta=%f from task=%d (%d,%d)\n",voxel,outind,b,task,betas->GetSize()[0],betas->GetSize()[1]);
+
+	      double tval= b/ (S2BMatrix->GetElement(task,task)*sqMSE);
+	      if (fabs(b)>1e-4)
+		tmap->SetComponent(voxel,outind,tval);
+	      else
+		tmap->SetComponent(voxel,outind,0.0);
+
+	      //	      if (found==0)
+	      //		{
+	      //		  fprintf(stderr,"b=%f S2B=%f sqMSE=%f t=%f\n",
+	      //			  b,S2BMatrix->GetElement(task,task),sqMSE,tval);
+	      //		  found=1;
+	      //		}
+	    }
+
+	  if (numdrift>0)
+	    {
+	      for (int t=0;t<numdrift;t++)
+		driftbeta->SetComponent(voxel,t,betas->GetElement(t,0));
+	    }
+	  ++numdone;
+	}
+      ++count;
+      if (count==maxcount)
+	{
+	  pog+=0.1;
+	  this->UpdateProgress(pog);
+	  count=0;
+	  fprintf(stdout," %.2f/100 (%d) ",100.0*pog,numdone);
+	}
+    }
+
+  fprintf(stdout,"\n");
+  betas->Delete();
+  null_betas->Delete();
+  colvect->Delete();
+  LSQ->Delete();
+  NULL_LSQ->Delete();
+  S2BMatrix->Delete();
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------------------------------------------
+vtkImageData* vtkbisComputeGLM::MatrixImageMultiply(vtkImageData* betasimage,vtkpxMatrix* glmmatrix)
+{
+  if (glmmatrix==NULL || betasimage==NULL)
+    {
+      fprintf(stdout,"Either matrix or betasimage image is NULL");
+      return NULL;
+    }
+
+  vtkDataArray* betas=betasimage->GetPointData()->GetScalars();
+
+
+  int nc=betas->GetNumberOfComponents();
+  int nt=betas->GetNumberOfTuples();
+
+  int sz[2]; glmmatrix->GetSize(sz);
+  if (sz[1] != nc)
+    {
+      fprintf(stdout,"Bad Dimensions image (%d voxels x %d frames), matrix=(%d rows x %d columns)\n",
+	      nt,nc,sz[0],sz[1]);
+      return NULL;
+    }
+
+  vtkImageData* outimage=vtkImageData::New();
+  outimage->CopyStructure(betasimage);
+  outimage->SetNumberOfScalarComponents(sz[0]);
+  outimage->AllocateScalars();
+
+  vtkDataArray* outdata=outimage->GetPointData()->GetScalars();
+
+  vtkpxMatrix* temp1=vtkpxMatrix::New();
+  vtkpxMatrix* temp2=vtkpxMatrix::New();
+  vtkpxMatrix* At=vtkpxMatrix::New();
+  At->Copy(glmmatrix);
+  At->Transpose();
+  temp1->Zeros(sz[1],1);
+  temp2->Zeros(sz[0],1);
+
+  int sum=(nt/10);
+  int count=0;
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      ++count;
+      if (count==sum)
+	{
+	  fprintf(stdout,"Computing image multiply voxel = %d/%d\n",voxel,nt);
+	  count=0;
+	}
+      vtkbisComputeGLM::StoreVoxelIndexIntoColumn(betas,voxel,temp1);
+      vtkpxMatrix::Multiply(glmmatrix,temp1,temp2);
+      vtkbisComputeGLM::StoreColumnIntoVoxelIndex(temp2,outdata,voxel);
+    }
+
+  temp1->Delete();
+  temp2->Delete();
+  At->Delete();
+  return outimage;
+
+
+}
+
+vtkImageData* vtkbisComputeGLM::ComputeSimpleGLM(vtkImageData* timeseriesimage,vtkpxMatrix* glmmatrix)
+{
+  if (glmmatrix==NULL || timeseriesimage==NULL)
+    {
+      fprintf(stdout,"Either matrix or timeseriesimage image is NULL");
+      return NULL;
+    }
+
+  vtkDataArray* timeseries=timeseriesimage->GetPointData()->GetScalars();
+  int nc=timeseries->GetNumberOfComponents();
+  int nt=timeseries->GetNumberOfTuples();
+
+  int sz[2]; glmmatrix->GetSize(sz);
+  if (sz[0] != nc)
+    {
+      fprintf(stdout,"Bad Dimensions image (%d voxels x %d frames), matrix=(%d rows x %d columns)\n",
+	      nt,nc,sz[0],sz[1]);
+      return NULL;
+    }
+
+  vtkImageData* outimage=vtkImageData::New();
+  outimage->CopyStructure(timeseriesimage);
+  outimage->SetNumberOfScalarComponents(sz[1]);
+  outimage->SetScalarTypeToFloat();
+  outimage->AllocateScalars();
+
+  vtkDataArray* outdata=outimage->GetPointData()->GetScalars();
+
+  vtkpxMatrix* temp1=vtkpxMatrix::New();
+  vtkpxMatrix* temp2=vtkpxMatrix::New();
+  vtkpxMatrix* LSQ=vtkbisComputeGLM::ComputeLSQMatrix(glmmatrix,NULL);
+  temp1->Zeros(sz[1],1);
+  temp2->Zeros(sz[1],1);
+
+  int sum=(nt/10);
+  int count=0;
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      ++count;
+      if (count==sum)
+	{
+	  fprintf(stdout,"Computing simple glm voxel = %d/%d\n",voxel,nt);
+	  count=0;
+	}
+      vtkbisComputeGLM::StoreVoxelIndexIntoColumn(timeseries,voxel,temp1);
+      vtkpxMatrix::Multiply(LSQ,temp1,temp2);
+      vtkbisComputeGLM::StoreColumnIntoVoxelIndex(temp2,outdata,voxel);
+    }
+
+  temp1->Delete();
+  temp2->Delete();
+  LSQ->Delete();
+  return outimage;
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisComputeGLM.h b/bioimagesuite30_src/Imaging/vtkbisComputeGLM.h
new file mode 100644
index 0000000..dab4fcb
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisComputeGLM.h
@@ -0,0 +1,148 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkbisComputeGLM_h
+#define __vtkbisComputeGLM_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkpxMatrix.h"
+
+
+class vtkbisComputeGLM : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkbisComputeGLM *New();
+  vtkTypeMacro(vtkbisComputeGLM,vtkpxSimpleImageToImageFilter);
+
+  // Parameters
+  // Regressor matrix
+  vtkSetObjectMacro(RegressorMatrix,vtkpxMatrix);
+  vtkGetObjectMacro(RegressorMatrix,vtkpxMatrix);
+
+  // Mask Image
+  vtkSetObjectMacro(ImageMask,vtkImageData);
+  vtkGetObjectMacro(ImageMask,vtkImageData);
+
+  // Residual Image
+  vtkGetObjectMacro(ResidualImage,vtkImageData);
+
+
+  // Residual Image
+  vtkGetObjectMacro(UnfitTimeSeries,vtkImageData);
+
+  // Drift Terms
+  vtkGetObjectMacro(DriftBetaValues,vtkImageData);
+
+  // If using ``pre-corrected'' stuff then set num of drift terms explicitly here (this is only for fstat computation)
+  // This is ignored unless NumberOfTasks = Number of columns of supplied regressor matrix
+  vtkSetClampMacro(OrderOfFstatDriftPolynomial,int,0,3);
+  vtkGetMacro(OrderOfFstatDriftPolynomial,int);
+
+
+  // Invidual Regressor Ttest Image
+  vtkGetObjectMacro(TmapImage,vtkImageData);
+
+  // Number of Tasks (last N columns of regressor matrix, first few columns are drift)
+  vtkSetMacro(NumberOfTasks,int);
+  vtkGetMacro(NumberOfTasks,int);
+
+  // Number of Tasks (last N columns of regressor matrix, first few columns are drift)
+  vtkSetMacro(DebugIndex,int);
+  vtkGetMacro(DebugIndex,int);
+
+
+  // Debug name for saving intermediate results
+  vtkSetStringMacro(DebugName);
+  vtkGetStringMacro(DebugName);
+
+
+
+  // Inverse of GLM
+  // Multiple Matrix with Image and save
+  static vtkImageData* MatrixImageMultiply(vtkImageData* betas,vtkpxMatrix* glmmatrix);
+
+  // Compute Direct GLM
+  static vtkImageData* ComputeSimpleGLM(vtkImageData* timeseriesimage,vtkpxMatrix* glmmatrix);
+
+protected:
+
+
+  vtkbisComputeGLM();
+  virtual ~vtkbisComputeGLM();
+
+  // Description:
+  // Threshold mode 0 = absolute, 1 = normalized i.e. 0:1
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual void ExecuteInformation();
+
+  // Description:
+  // GLM Basics
+  static vtkpxMatrix* ComputeLSQMatrix(vtkpxMatrix* A,vtkpxMatrix* S2BMatrix=NULL);
+  static  void  StoreVoxelIndexIntoColumn(vtkDataArray* dat,int index,vtkpxMatrix* colvect);
+  static  void  StoreColumnIntoVoxelIndex(vtkpxMatrix* vect,vtkDataArray* dat,int index);
+
+  virtual void   ComputeBetas(vtkpxMatrix* SQL,vtkpxMatrix* beta,vtkpxMatrix* colvect);
+
+  virtual double ComputeFStats(vtkpxMatrix* A,vtkpxMatrix* ReducedA,vtkpxMatrix* beta,vtkpxMatrix* nullbeta,
+			       vtkpxMatrix* colvect,double factor,double tmapdof,vtkDataArray* res,vtkDataArray* unfit,int index,int debug=0);
+
+
+  // Description:
+  // Fill In Drift Terms
+  virtual void CreateNULLRegressorMarix(vtkpxMatrix* inout,vtkpxMatrix* regressor,int order);
+
+  int OrderOfFstatDriftPolynomial;
+  vtkImageData* ImageMask;
+  vtkImageData* ResidualImage;
+  vtkImageData* UnfitTimeSeries;
+  vtkImageData* DriftBetaValues;
+  vtkImageData* TmapImage;
+  vtkpxMatrix*  RegressorMatrix;
+  vtkpxMatrix*  TempMatrix1;
+  vtkpxMatrix*  TempMatrix2;
+  vtkpxMatrix*  TempMatrix3;
+  vtkpxMatrix*  TempMatrix4;
+
+  vtkpxMatrix*  NULLRegressorMatrix;
+  char* DebugName;
+  int   NumberOfTasks;
+  int   DebugIndex;
+
+  // This is protected it should not be needed
+  vtkSetObjectMacro(ResidualImage,vtkImageData);
+  vtkSetObjectMacro(TmapImage,vtkImageData);
+  vtkSetObjectMacro(UnfitTimeSeries,vtkImageData);
+  vtkSetObjectMacro(DriftBetaValues,vtkImageData);
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisCudaConvolution.cpp b/bioimagesuite30_src/Imaging/vtkbisCudaConvolution.cpp
new file mode 100644
index 0000000..72c25bf
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisCudaConvolution.cpp
@@ -0,0 +1,253 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "bioimagesuite_settings.h"
+#include "vtkbisCudaConvolution.h"
+#include "vtkpxUtil.h"
+#include "vtkMath.h"
+#include "vtkImageCast.h"
+#include <time.h>
+
+#ifdef BIOIMAGESUITE3_USE_CUDA
+
+#include <cufft.h>
+#include <cuda.h>
+#include <cuda_runtime.h>
+
+extern "C" void FFTFirstImage(float *cuInp1,cufftComplex *fft1,int dim1[3],int convdim[3]);
+extern "C" void ConvolveWithFilter(cufftComplex *fft1,float *cuInp2,float *cuOut,int dim1[3],int dim2[3],int convdim[3]);
+
+#endif
+
+const int CUDA_FFT_LIMIT = 256*256*128;
+
+vtkbisCudaConvolution* vtkbisCudaConvolution::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisCudaConvolution");
+  if(ret)
+    {
+      return (vtkbisCudaConvolution*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisCudaConvolution;
+}
+
+vtkbisCudaConvolution::vtkbisCudaConvolution() 
+{
+  this->Filter=NULL;
+}
+
+vtkbisCudaConvolution::~vtkbisCudaConvolution() 
+{  
+  this->SetFilter(NULL);
+}
+int vtkbisCudaConvolution::RequestInformation(vtkInformation *request,
+				      vtkInformationVector **inputVector,
+				      vtkInformationVector *outputVector)
+{
+  int nc=this->Filter->GetNumberOfScalarComponents();
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, nc);
+  return 1;
+}
+
+
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisCudaConvolution::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+
+#ifndef BIOIMAGESUITE3_USE_CUDA
+  fprintf(stderr,"\nCuda disabled exiting now\n");
+  return;
+#endif
+#ifdef BIOIMAGESUITE3_USE_CUDA
+
+ 
+  if (this->Filter==NULL)
+    {
+      fprintf(stderr,"Image not set\n Exiting Now!!!!");
+      return;
+    }
+  
+  fprintf(stderr,"\nBeginning vtkbisCudaConvolution\n");
+  
+  int dim1[3]; input->GetDimensions(dim1);
+  int dim2[3]; this->Filter->GetDimensions(dim2);
+  int nc=this->Filter->GetNumberOfScalarComponents();
+  
+  int convdim[3];
+  for (int i=0;i<3;i++)
+    convdim[i]=dim1[i]+dim2[i]-1;
+
+  int ntconv=convdim[0]*convdim[1]*convdim[2];
+  int nt1=dim1[0]*dim1[1]*dim1[2];
+  int nt2=dim2[0]*dim2[1]*dim2[2];
+
+  if(ntconv>CUDA_FFT_LIMIT)
+    {
+      fprintf(stderr,"\nError resultant convolution is too big for CUDA FFT\n");
+      return;
+    }
+
+  vtkImageCast* cast=vtkImageCast::New();
+  cast->SetInput(input);
+  cast->SetOutputScalarTypeToFloat();
+  cast->Update();
+
+  const int size=sizeof(float);
+  const int mem_size_inp1=size*nt1;
+  const int mem_size_inp2=size*nt2;
+  const int mem_size_conv=sizeof(cufftComplex)*ntconv;
+
+  float* inp1=(float*)cast->GetOutput()->GetPointData()->GetScalars()->GetVoidPointer(0);
+  float* inp2=(float*)this->Filter->GetPointData()->GetScalars()->GetVoidPointer(0);
+  float* out =(float*)output->GetPointData()->GetScalars()->GetVoidPointer(0);
+  
+  float* cuInp1;
+  cudaMalloc((void**)&cuInp1,mem_size_inp1); 
+  cudaMemcpy(cuInp1,inp1,mem_size_inp1,cudaMemcpyHostToDevice);
+
+  float* cuInp2;
+  cudaMalloc((void**)&cuInp2,mem_size_inp2); 
+
+  float* cuOut;
+  cudaMalloc((void**)&cuOut,mem_size_inp1); 
+  
+  cufftComplex *fft1;
+  cudaMalloc((void**)&fft1,mem_size_conv); 
+
+  cudaMemcpyToSymbol( "CONVSIZE", &ntconv, sizeof(int) );
+
+  FFTFirstImage(cuInp1,fft1,dim1,convdim);
+
+  float* framein =new float[nt2];
+  float* frameout=new float[nt1];
+  
+  for(int i=0;i<nc;i++)
+    {
+      printf("\ndoing frame %d\n",i);
+      
+      for(int j=0;j<nt2;j++)
+	framein[j]=*(inp2+i+j*nc);
+      
+      cudaMemcpy(cuInp2,framein,mem_size_inp2,cudaMemcpyHostToDevice);      
+      
+      ConvolveWithFilter(fft1,cuInp2,cuOut,dim1,dim2,convdim);
+      
+      cudaMemcpy(frameout,cuOut,mem_size_inp1,cudaMemcpyDeviceToHost);
+      
+      for(int j=0;j<nt1;j++)
+	*(out+i+j*nc)=frameout[j];
+    }
+  
+  cudaFree(fft1);
+  cudaFree(cuInp1);
+  cudaFree(cuInp2);
+  cudaFree(cuOut);
+
+  delete [] framein;
+  delete [] frameout;
+
+  cast->Delete();
+   
+#endif
+}
+
+void vtkbisCudaConvolution::CreateHessian(double sigma1,double sigma2,double sigma3,double radius)
+{
+ 
+  double sigma[3] = { sigma1, sigma2, sigma3 };
+  int dim[3];
+  for (int ia=0;ia<=2;ia++)
+    dim[ia]=int(radius*sigma[ia]+0.5)*2+1;
+
+  vtkImageData* newimg=vtkImageData::New();
+  newimg->SetScalarTypeToFloat();
+  newimg->SetNumberOfScalarComponents(6);
+  newimg->SetDimensions(dim);
+  newimg->AllocateScalars();
+
+  
+  double midx=0.5*double(dim[0]-1);
+  double midy=0.5*double(dim[1]-1);
+  double midz=0.5*double(dim[2]-1);
+  
+  double invs2[3];
+  double s2[3];
+  double invs4[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      s2[ia]=sigma[ia]*sigma[ia];
+      invs2[ia]=1.0/(s2[ia]);
+      invs4[ia]=invs2[ia]*invs2[ia];
+    }
+
+  double scalefactor=1.0/(sqrt(2.0*vtkMath::Pi())*sqrt(2.0*vtkMath::Pi())*sqrt(2.0*vtkMath::Pi())*sigma[0]*sigma[1]*sigma[2]); // should be sqrt(2pi)^3 but just a constant...
+
+  for (int k=0;k<dim[2];k++)
+    {
+      double z=double(k)-midz;
+      double z2=z*z*invs2[2];
+      
+      for (int j=0;j<dim[1];j++)
+	{
+	  double y=double(j)-midy;
+	  double y2=y*y*invs2[1];
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      double x=double(i)-midx;
+	      double x2=x*x*invs2[0];
+
+	      double G=scalefactor*exp(- 0.5*( x2+y2+z2));
+
+	      newimg->SetScalarComponentFromDouble(i,j,k,0, (x*x - s2[0])*invs4[0]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,3, (y*y - s2[1])*invs4[1]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,5, (z*z - s2[2])*invs4[2]*G);
+
+	      newimg->SetScalarComponentFromDouble(i,j,k,1, x*y * invs2[0]*invs2[1]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,2, x*z * invs2[0]*invs2[2]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,4, y*z * invs2[1]*invs2[2]*G);
+
+	    }
+	}
+    }
+  
+  this->SetFilter(newimg);
+  newimg->Delete();
+
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisCudaConvolution.h b/bioimagesuite30_src/Imaging/vtkbisCudaConvolution.h
new file mode 100644
index 0000000..d41779e
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisCudaConvolution.h
@@ -0,0 +1,65 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//#ifdef BIOIMAGESUITE3_USE_CUDA
+#ifndef VTKBISCUDAConvolution_H_
+#define VTKBISCUDAConvolution_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkbisCudaConvolution : public vtkSimpleImageToImageFilter {
+ public:
+  static vtkbisCudaConvolution *New();
+  vtkTypeMacro(vtkbisCudaConvolution,vtkSimpleImageToImageFilter);
+  vtkSetObjectMacro(Filter,vtkImageData);
+  vtkSetObjectMacro(Image, vtkImageData);
+  
+  virtual void CreateHessian(double sigma1,double sigma2,double sigma3,double radius);
+  
+ protected:
+  vtkbisCudaConvolution();
+  virtual ~vtkbisCudaConvolution();
+  
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  
+				 vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+  //virtual void PadImage(vtkImageData* imgIn, vtkImageData* imgOut,  int paddim[3]);
+  
+  vtkImageData *Filter;
+  vtkImageData *Image;
+  
+ private:
+  vtkbisCudaConvolution(const vtkbisCudaConvolution& src){};
+  vtkbisCudaConvolution& operator=(const vtkbisCudaConvolution& rhs){};
+};
+
+#endif /* VTKBISCUDAConvolution_H_ */
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisCudaEdgeDetect.cpp b/bioimagesuite30_src/Imaging/vtkbisCudaEdgeDetect.cpp
new file mode 100644
index 0000000..b1ba711
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisCudaEdgeDetect.cpp
@@ -0,0 +1,132 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "bioimagesuite_settings.h"
+#include "vtkbisCudaEdgeDetect.h"
+#include "vtkpxUtil.h"
+#include "vtkMath.h"
+#include "vtkImageCast.h"
+#include <time.h>
+
+#ifdef BIOIMAGESUITE3_USE_CUDA
+
+#include <cufft.h>
+#include <cuda.h>
+#include <cuda_runtime.h>
+
+extern "C" void EdgeDetection(float *input,float *output,int dim[3],float spa[3]);
+extern "C" void Test(float *input,float *output,int dim[3]);
+
+#endif
+
+vtkbisCudaEdgeDetect* vtkbisCudaEdgeDetect::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisCudaEdgeDetect");
+  if(ret)
+    {
+      return (vtkbisCudaEdgeDetect*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisCudaEdgeDetect;
+}
+
+vtkbisCudaEdgeDetect::vtkbisCudaEdgeDetect() { }
+
+vtkbisCudaEdgeDetect::~vtkbisCudaEdgeDetect() { }
+
+int vtkbisCudaEdgeDetect::RequestInformation(vtkInformation *request,
+				      vtkInformationVector **inputVector,
+				      vtkInformationVector *outputVector)
+{
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, 1);
+  return 1;
+}
+
+
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisCudaEdgeDetect::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+
+#ifndef BIOIMAGESUITE3_USE_CUDA
+  fprintf(stderr,"\nCuda disabled exiting now\n");
+  return;
+#endif
+#ifdef BIOIMAGESUITE3_USE_CUDA
+
+  fprintf(stderr,"\nBeginning vtkbisCudaEdgeDetect\n");
+  
+  int dim1[3]; input->GetDimensions(dim1);
+  int nt1=dim1[0]*dim1[1]*dim1[2];
+
+  double tmp[3]; float spa[3];
+  input->GetSpacing(tmp);
+  spa[0]=(float)tmp[0];
+  spa[1]=(float)tmp[1];
+  spa[2]=(float)tmp[2];
+
+  const int mem_size_inp1=sizeof(float)*nt1;
+
+  vtkImageCast* cast=vtkImageCast::New();
+  cast->SetInput(input);
+  cast->SetOutputScalarTypeToFloat();
+  cast->Update();
+
+  float* inp=(float*)cast->GetOutput()->GetPointData()->GetScalars()->GetVoidPointer(0);
+  float* out=(float*)output->GetPointData()->GetScalars()->GetVoidPointer(0);
+  
+  float* cuInp1;
+  cudaMalloc((void**)&cuInp1,mem_size_inp1); 
+  cudaMemcpy(cuInp1,inp,mem_size_inp1,cudaMemcpyHostToDevice);
+
+  float* cuOut;
+  cudaMalloc((void**)&cuOut,mem_size_inp1); 
+  
+  //Test(cuInp1,cuOut,dim1);
+  EdgeDetection(cuInp1,cuOut,dim1,spa);
+      
+  cudaMemcpy(out,cuOut,mem_size_inp1,cudaMemcpyDeviceToHost);
+    
+  cudaFree(cuInp1);
+  cudaFree(cuOut);
+
+  cast->Delete();
+   
+#endif
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisCudaEdgeDetect.h b/bioimagesuite30_src/Imaging/vtkbisCudaEdgeDetect.h
new file mode 100644
index 0000000..758c7f8
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisCudaEdgeDetect.h
@@ -0,0 +1,57 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//#ifdef BIOIMAGESUITE3_USE_CUDA
+#ifndef VTKBISCUDAEdgeDetect_H_
+#define VTKBISCUDAEdgeDetect_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkbisCudaEdgeDetect : public vtkSimpleImageToImageFilter {
+ public:
+  static vtkbisCudaEdgeDetect *New();
+  vtkTypeMacro(vtkbisCudaEdgeDetect,vtkSimpleImageToImageFilter);
+  
+ protected:
+  vtkbisCudaEdgeDetect();
+  virtual ~vtkbisCudaEdgeDetect();
+  
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  
+				 vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+ private:
+  vtkbisCudaEdgeDetect(const vtkbisCudaEdgeDetect& src){};
+  vtkbisCudaEdgeDetect& operator=(const vtkbisCudaEdgeDetect& rhs){};
+};
+
+#endif /* VTKBISCUDAEdgeDetect_H_ */
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisCudaFFT.cpp b/bioimagesuite30_src/Imaging/vtkbisCudaFFT.cpp
new file mode 100644
index 0000000..d4ce0f4
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisCudaFFT.cpp
@@ -0,0 +1,147 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "bioimagesuite_settings.h"
+#include "vtkbisCudaFFT.h"
+
+#ifdef BIOIMAGESUITE3_USE_CUDA
+
+#include <cufft.h>
+#include <cuda.h>
+#include <cuda_runtime.h>
+
+extern "C" void bisCUDA_FFT(float *input, int dim[3],int forward);
+
+#endif
+
+vtkbisCudaFFT* vtkbisCudaFFT::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisCudaFFT");
+  if(ret)
+    {
+      return (vtkbisCudaFFT*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisCudaFFT;
+}
+
+
+vtkbisCudaFFT::vtkbisCudaFFT() 
+{
+
+}
+
+vtkbisCudaFFT::~vtkbisCudaFFT() 
+{
+
+}
+
+
+int vtkbisCudaFFT::RequestInformation(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+				      vtkInformationVector *outputVector)
+
+{ 
+  vtkInformation *outInfo = outputVector->GetInformationObject(0); 
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_DOUBLE, -1);
+#ifdef BIOIMAGESUITE3_USE_CUDA
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, 2);
+#else
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, 1);
+#endif
+  return 1;
+}
+
+
+ /*void vtkbisCudaFFT::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+
+  output->SetScalarTypeToDouble();
+#ifdef BIOIMAGESUITE3_USE_CUDA
+  output->SetNumberOfScalarComponents(2);
+#else
+  output->SetNumberOfScalarComponents(1);
+#endif
+}*/
+
+
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisCudaFFT::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+#ifndef BIOIMAGESUITE3_USE_CUDA
+
+  fprintf(stderr,"\nCuda disabled exiting now\n");
+  return;
+
+#else
+ 
+ fprintf(stderr,"\nBeginning vtkbisCudaFFT\n");
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  int nc=out->GetNumberOfComponents();
+  for (int ia=0;ia<nc;ia++)
+    out->FillComponent(ia,0.0);
+
+  int dim[3]; input->GetDimensions(dim);
+  int nt0=dim[0]*dim[1]*dim[2];
+  float* inputdata=new float[nt0*2];
+
+  fprintf(stderr,"nt0=%d nc1=%d dims=(%d,%d,%d)\n",nt0,1,dim[0],dim[1],dim[2]);
+
+  // setting the real part first
+  for (int i=0;i<nt0;i++)
+    {
+      int index=i*2;
+      inputdata[index]=(float)inp->GetComponent(i,0); 	  
+      inputdata[index+1]=0.0f;
+    }
+ 
+  bisCUDA_FFT(inputdata, dim, 1);  
+
+  for (int i=0;i<nt0;i++)
+    {
+      int index=2*i;
+      out->SetComponent(i,0,inputdata[index]);
+      out->SetComponent(i,1,inputdata[index+1]);
+    }
+
+  delete [] inputdata;
+#endif
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisCudaFFT.h b/bioimagesuite30_src/Imaging/vtkbisCudaFFT.h
new file mode 100644
index 0000000..c56f36f
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisCudaFFT.h
@@ -0,0 +1,62 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//#ifdef BIOIMAGESUITE3_USE_CUDA
+#ifndef VTKBISCUDAFFT_H_
+#define VTKBISCUDAFFT_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+//class vtkbisCudaFFT : public vtkpxSimpleImageToImageFilter {
+class vtkbisCudaFFT : public vtkSimpleImageToImageFilter {
+public:
+	static vtkbisCudaFFT *New();
+	vtkTypeMacro(vtkbisCudaFFT,vtkSimpleImageToImageFilter);
+
+protected:
+  vtkbisCudaFFT();
+  virtual ~vtkbisCudaFFT();
+  
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  //  virtual void ExecuteInformation();
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  
+				 vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+
+
+private:
+  vtkbisCudaFFT(const vtkbisCudaFFT& src){};
+  vtkbisCudaFFT& operator=(const vtkbisCudaFFT& rhs){};
+};
+
+#endif /* VTKBISCUDAFFT_H_ */
+//#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisCudaHessian.cpp b/bioimagesuite30_src/Imaging/vtkbisCudaHessian.cpp
new file mode 100644
index 0000000..ed21c15
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisCudaHessian.cpp
@@ -0,0 +1,196 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "bioimagesuite_settings.h"
+#include "vtkbisCudaConvolution.h"
+#include "vtkbisCudaHessian.h"
+#include "vtkMath.h"
+#include "vtkImageExtractComponents.h"
+
+#include <time.h>
+
+vtkbisCudaHessian* vtkbisCudaHessian::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisCudaHessian");
+  if(ret)
+    {
+      return (vtkbisCudaHessian*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisCudaHessian;
+}
+
+vtkbisCudaHessian::vtkbisCudaHessian() 
+{
+  this->Filter=NULL;
+}
+
+vtkbisCudaHessian::~vtkbisCudaHessian() 
+{  
+  this->SetFilter(NULL);
+}
+
+int vtkbisCudaHessian::RequestInformation(vtkInformation *request,
+				      vtkInformationVector **inputVector,
+				      vtkInformationVector *outputVector)
+{
+  if (this->Filter==NULL)
+    {
+      vtkErrorMacro(<<"No Filter Bank Image Set\n");
+      return 1;
+    } 
+
+  int nc=this->Filter->GetNumberOfScalarComponents();
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, nc);
+  
+  return 1;
+}
+
+void vtkbisCudaHessian::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+
+    if (input==NULL || this->Filter ==NULL )
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkxqImageFourierConvolution");
+      return;
+    }
+    
+    vtkDataArray* out=output->GetPointData()->GetScalars();
+
+    int nc=this->Filter->GetNumberOfScalarComponents();
+    
+    for(int i=0;i<nc;i++)
+      {
+	vtkImageExtractComponents* comp=vtkImageExtractComponents::New();
+	vtkbisCudaConvolution* conv=vtkbisCudaConvolution::New();
+
+	conv->SetInput(input);
+	comp->SetInput(this->Filter);
+
+	comp->SetComponents(i);
+	comp->Update();
+	
+	conv->SetFilter(comp->GetOutput());
+	
+	//clock_t before=clock();
+	conv->Update();
+	//printf("\ncuda convolution took %f seconds\n",((clock()-before)/CLOCKS_PER_SEC));
+
+	out->CopyComponent(i,conv->GetOutput()->GetPointData()->GetScalars(),0);
+
+	comp->Delete();
+	conv->Delete();
+      }
+}
+
+void vtkbisCudaHessian::CreateHessian(double sigma1,double sigma2,double sigma3,double radius)
+{
+ 
+  double sigma[3] = { sigma1, sigma2, sigma3 };
+  int dim[3];
+  for (int ia=0;ia<=2;ia++)
+    dim[ia]=int(radius*sigma[ia]+0.5)*2+1;
+
+  vtkImageData* newimg=vtkImageData::New();
+  newimg->SetScalarTypeToDouble();
+  //  newimg->SetNumberOfScalarComponents(6);
+  newimg->SetNumberOfScalarComponents(12);
+  newimg->SetDimensions(dim);
+  newimg->AllocateScalars();
+
+  
+  double midx=0.5*double(dim[0]-1);
+  double midy=0.5*double(dim[1]-1);
+  double midz=0.5*double(dim[2]-1);
+  
+  double invs2[3];
+  double s2[3];
+  double invs4[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      s2[ia]=sigma[ia]*sigma[ia];
+      invs2[ia]=1.0/(s2[ia]);
+      invs4[ia]=invs2[ia]*invs2[ia];
+    }
+
+  double scalefactor=1.0/(sqrt(2.0*vtkMath::Pi())*sqrt(2.0*vtkMath::Pi())*sqrt(2.0*vtkMath::Pi())*sigma[0]*sigma[1]*sigma[2]); // should be sqrt(2pi)^3 but just a constant...
+
+  for (int k=0;k<dim[2];k++)
+    {
+      double z=double(k)-midz;
+      double z2=z*z*invs2[2];
+      
+      for (int j=0;j<dim[1];j++)
+	{
+	  double y=double(j)-midy;
+	  double y2=y*y*invs2[1];
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      double x=double(i)-midx;
+	      double x2=x*x*invs2[0];
+
+	      double G=scalefactor*exp(- 0.5*( x2+y2+z2));
+
+	      newimg->SetScalarComponentFromDouble(i,j,k,1, (y*y - s2[1])*invs4[1]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,2, (z*z - s2[2])*invs4[2]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,3, (x*x - s2[0])*invs4[0]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,4, (y*y - s2[1])*invs4[1]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,5, (z*z - s2[2])*invs4[2]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,6, (x*x - s2[0])*invs4[0]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,7, (y*y - s2[1])*invs4[1]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,8, (z*z - s2[2])*invs4[2]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,9, (x*x - s2[0])*invs4[0]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,10, (y*y - s2[1])*invs4[1]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,11, (z*z - s2[2])*invs4[2]*G);
+
+	      /*
+	      newimg->SetScalarComponentFromDouble(i,j,k,0, (x*x - s2[0])*invs4[0]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,3, (y*y - s2[1])*invs4[1]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,5, (z*z - s2[2])*invs4[2]*G);
+
+	      newimg->SetScalarComponentFromDouble(i,j,k,1, x*y * invs2[0]*invs2[1]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,2, x*z * invs2[0]*invs2[2]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,4, y*z * invs2[1]*invs2[2]*G);
+	      */
+	    }
+	}
+    }
+  
+  this->SetFilter(newimg);
+  newimg->Delete();
+
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisCudaHessian.h b/bioimagesuite30_src/Imaging/vtkbisCudaHessian.h
new file mode 100644
index 0000000..00773cb
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisCudaHessian.h
@@ -0,0 +1,62 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//#ifdef BIOIMAGESUITE3_USE_CUDA
+#ifndef VTKBISCUDAHessian_H_
+#define VTKBISCUDAHessian_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkbisCudaHessian : public vtkSimpleImageToImageFilter {
+public:
+  static vtkbisCudaHessian *New();
+  vtkTypeMacro(vtkbisCudaHessian,vtkSimpleImageToImageFilter);
+  vtkSetObjectMacro(Filter,vtkImageData);
+
+  virtual void CreateHessian(double sigma1,double sigma2,double sigma3,double radius);
+  
+ protected:
+  vtkbisCudaHessian();
+  virtual ~vtkbisCudaHessian();
+  
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  
+				 vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+  vtkImageData *Filter;
+  
+ private:
+  vtkbisCudaHessian(const vtkbisCudaHessian& src){};
+  vtkbisCudaHessian& operator=(const vtkbisCudaHessian& rhs){};
+};
+
+#endif /* VTKBISCUDAHessian_H_ */
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisCudaRFFT.cpp b/bioimagesuite30_src/Imaging/vtkbisCudaRFFT.cpp
new file mode 100644
index 0000000..a7c3a63
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisCudaRFFT.cpp
@@ -0,0 +1,143 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "bioimagesuite_settings.h"
+#include "vtkbisCudaRFFT.h"
+
+#ifdef BIOIMAGESUITE3_USE_CUDA
+
+#include <cufft.h>
+#include <cuda.h>
+#include <cuda_runtime.h>
+
+extern "C" void bisCUDA_FFT(float *input, int dim[3],int forward);
+
+#endif
+
+vtkbisCudaRFFT* vtkbisCudaRFFT::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisCudaRFFT");
+  if(ret)
+    {
+      return (vtkbisCudaRFFT*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisCudaRFFT;
+}
+
+
+vtkbisCudaRFFT::vtkbisCudaRFFT() 
+{
+
+}
+
+vtkbisCudaRFFT::~vtkbisCudaRFFT() 
+{
+
+}
+
+/*void vtkbisCudaRFFT::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+
+  output->SetScalarTypeToDouble();
+#ifdef BIOIMAGESUITE3_USE_CUDA
+  output->SetNumberOfScalarComponents(1);
+#else
+  output->SetNumberOfScalarComponents(2);
+#endif
+}*/
+
+
+int vtkbisCudaRFFT::RequestInformation(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+				      vtkInformationVector *outputVector)
+
+{ 
+  vtkInformation *outInfo = outputVector->GetInformationObject(0); 
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_DOUBLE, -1);
+#ifdef BIOIMAGESUITE3_USE_CUDA
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, 1);
+#else
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, 2);
+#endif
+  return 1;
+}
+
+
+
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisCudaRFFT::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+#ifndef BIOIMAGESUITE3_USE_CUDA
+
+  fprintf(stderr,"\nCuda disabled\n");
+  return;
+
+#else
+ 
+  fprintf(stderr,"\nBeginning vtkbisCudaRFFT\n");
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  int nc=out->GetNumberOfComponents();
+  for (int ia=0;ia<nc;ia++)
+    out->FillComponent(ia,0.0);
+  
+  int dim[3]; input->GetDimensions(dim);
+  int nt0=dim[0]*dim[1]*dim[2];
+  float* inputdata=new float[nt0*2];
+
+  fprintf(stderr,"nt0=%d nc1=%d dims=(%d,%d,%d)\n",nt0,1,dim[0],dim[1],dim[2]);
+
+  // setting the real part first
+  for (int i=0;i<nt0;i++)
+    {
+      int index=i*2;
+      inputdata[index]=(float)inp->GetComponent(i,0); 	  
+      inputdata[index+1]=(float)inp->GetComponent(i,1); 	  
+    }
+ 
+  bisCUDA_FFT(inputdata, dim, 0);  
+
+  for (int i=0;i<nt0;i++)
+    out->SetComponent(i,0,inputdata[i*2]);
+  
+  delete [] inputdata;
+#endif
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisCudaRFFT.h b/bioimagesuite30_src/Imaging/vtkbisCudaRFFT.h
new file mode 100644
index 0000000..d270521
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisCudaRFFT.h
@@ -0,0 +1,63 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//#ifdef BIOIMAGESUITE3_USE_CUDA
+#ifndef VTKBISCUDARFFT_H_
+#define VTKBISCUDARFFT_H_
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+  //class vtkbisCudaRFFT : public vtkpxSimpleImageToImageFilter {
+
+class vtkbisCudaRFFT : public vtkSimpleImageToImageFilter {
+  
+public:
+	static vtkbisCudaRFFT *New();
+	vtkTypeMacro(vtkbisCudaRFFT,vtkSimpleImageToImageFilter);
+
+protected:
+	vtkbisCudaRFFT();
+	virtual ~vtkbisCudaRFFT();
+
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  //  virtual void ExecuteInformation();
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  
+				 vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+  
+
+private:
+	vtkbisCudaRFFT(const vtkbisCudaRFFT& src){};
+	vtkbisCudaRFFT& operator=(const vtkbisCudaRFFT& rhs){};
+};
+
+#endif /* VTKBISCUDARFFT_H_ */
+//#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisFDR.cpp b/bioimagesuite30_src/Imaging/vtkbisFDR.cpp
new file mode 100644
index 0000000..f65e186
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisFDR.cpp
@@ -0,0 +1,223 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisFDR.cpp
+ *
+ *  Created on: Apr 17, 2009
+ *      Author: Isabella Murphy, Xilin Shen
+ *      @Input:3D image, all voxel values have transformed to p-value.
+ *      @Output:3D image, 1 or 0
+ */
+
+#include <vtkbisFDR.h>
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkSortDataArray.h"
+#include "vtkTimerLog.h"
+#include "vtkImageCast.h"
+#include "vtkDoubleArray.h"
+#include "math.h"
+#include "vtkMath.h"
+#include "vtkIntArray.h"
+
+
+using namespace std;
+
+vtkbisFDR* vtkbisFDR::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisFDR");
+  if(ret)
+  {
+      return (vtkbisFDR*)ret;
+  }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisFDR;
+}
+vtkbisFDR::vtkbisFDR() {
+  this->Q=0;
+  this->MaxPvalue=0.0;
+  this->ImageMask = NULL;
+
+}
+vtkbisFDR::~vtkbisFDR()
+{
+  this->SetImageMask(NULL);
+}
+/*-------------------------------------------------------------------------------------
+ * force the output data type to float, need to change extend information to let
+ * the pipeline know the difference
+ * @Set: output data type = float, number of components 1. First components set all the voxels with p(i)<=iq/Vc(V) to 1
+ * and p(i)>iq/Vc(V) to 0.
+ */
+
+int vtkbisFDR::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+					  vtkInformationVector *outputVector)
+{
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_UNSIGNED_CHAR, 1);
+  return 1;
+}
+
+// -------------------------------------------------------------------------------------
+
+void vtkbisFDR::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (this->ImageMask!=NULL)
+  {
+      int dim[3]; this->ImageMask->GetDimensions(dim);
+      int dim2[3]; input->GetDimensions(dim2);
+      int sum=0;
+      for (int ia=0;ia<=2;ia++)
+    	  sum+=abs(dim[ia]-dim2[ia]);
+      if (sum>0)
+      {
+    	  fprintf(stderr,"Bad Mask Input to vtkbisFDR SimpleExecute, input image and mask image have different dimension.\n");
+    	  return;
+      }
+  }
+
+  // --------------------------------------------
+
+  double r = 0.5772;
+  vtkTimerLog *timer = vtkTimerLog::New();
+
+  vtkDataArray*   out=output->GetPointData()->GetScalars();
+  // Cleanup first -- fill output with 1s
+  out->FillComponent(0,0.0);
+
+  vtkDataArray* msk=NULL;
+  if (this->ImageMask!=NULL)
+    msk=this->ImageMask->GetPointData()->GetScalars();
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  int nt=inp->GetNumberOfTuples();
+
+  vtkDoubleArray* values=vtkDoubleArray::New();
+  values->SetNumberOfComponents(2);
+  values->Allocate(nt/2,nt/5);
+  //  values->FillComponent(0,0.0);
+  //  values->FillComponent(1,0.0);
+
+  double val[2];
+
+  // ----------------------------------------------------
+
+  int maxcount=int(nt/10),count=0;
+  double pog=0.0;
+  this->UpdateProgress(0.01);// for the use interface to show progress
+
+  for (int i = 0; i < nt; i++)
+  {
+      int usevoxel=1;
+      if (msk!=NULL)
+      {
+    	  if (msk->GetComponent(i,0)<1)
+    		  usevoxel=0;
+      }
+      if (usevoxel)
+      {
+    	  val[0]=double(i);
+    	  val[1]=inp->GetComponent(i,0);
+    	  values->InsertNextTuple2(val[0],val[1]);
+      }
+  }
+
+  //sort the values array base on component 1
+  timer->StartTimer();
+  vtkSortDataArray::SortArrayByComponent(values,1);
+  timer->StopTimer();
+  cout << "Time to sort array: " << timer->GetElapsedTime() << " sec" <<","<< "voxels in image= " << nt << ", voxels in sorting array= " << values->GetNumberOfTuples() << "," << endl;
+  nt=values->GetNumberOfTuples();
+  double counter=double(nt);
+  for (int i = 0; i < 11; i++)
+    {
+	  cout<<values->GetComponent(i, 1)<<"|";
+    }
+
+  for (int i = 0; i < nt-1; i++)
+  {
+      if (values->GetComponent(i, 1) > values->GetComponent(i+1, 1))
+      {
+    	  cout<<i<<":"<<values->GetComponent(i, 1)<<">"<<values->GetComponent(i+1, 1)<<"Array not properly sorted!" << endl;
+    	  break;
+      }
+  }
+  cout << "Array consistency check finished\n" << endl;
+  this->UpdateProgress(0.5);
+
+  //if p(i)<= i*q/(V*c(V)) = i*q/(V*(ln(V)+r)) = i*q/(V*(ln(V)+0.5772)), v(i)=1
+  //       double constant=this->Q/(double)(double(counter)*(log(double(counter))+r));
+  //       int i = 0;
+
+  fprintf(stderr,"Q=%f, counter=%f r=%f\n",this->Q,counter,r);
+  //double constant=this->Q/(counter*(log(counter)+r));
+  double constant=this->Q/counter;
+  fprintf(stderr,"Constant=%f\n",constant);
+
+  double maxpvalue=values->GetComponent(0,1);
+  fprintf(stderr,"Maxpvalue =%f\n",maxpvalue);
+  //de
+int counter2=0;
+//de
+  for (int i=0;i<nt;i++)
+  {
+      int voxelindex=(int)values->GetComponent(i,0);
+      double v=values->GetComponent(i,1);
+      double thr=double(i+1)*constant;
+
+      if( v <= thr)
+      {
+    	  out->SetComponent(voxelindex,0,1);
+    	     	  if (v>maxpvalue)
+    		  maxpvalue=v;
+    	     	  //de
+    	     	  ++counter2;
+    	     	  //de
+      }
+      ++count;
+      if (count==maxcount)
+      {
+    	  pog=double(i)/double(nt);
+    	  this->UpdateProgress(pog);
+    	  count=0;
+      }
+  }
+  cout<<"final count:"<<counter2<<"\n";
+  this->MaxPvalue=maxpvalue;
+  fprintf(stderr,"Final Maxpvalue =%f\n",maxpvalue);
+
+
+  timer->Delete();
+  values->Delete();
+  this->UpdateProgress(1.0);
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisFDR.h b/bioimagesuite30_src/Imaging/vtkbisFDR.h
new file mode 100644
index 0000000..767f711
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisFDR.h
@@ -0,0 +1,73 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisFDR.h
+ *
+ *  Created on: Apr 17, 2009
+ *      Author: Isabella Murphy, Xilin Shen
+ */
+
+#ifndef VTKBISFDR_H_
+#define VTKBISFDR_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkbisFDR : public vtkSimpleImageToImageFilter{
+public:
+	static vtkbisFDR *New();
+	vtkTypeMacro(vtkbisFDR,vtkSimpleImageToImageFilter);
+
+	//Q
+	vtkSetClampMacro(Q,float,0.0,1.0);
+	vtkGetMacro(Q,float);
+
+	//Description:
+	// This is the Maxpvalue that made it
+	vtkGetMacro(MaxPvalue,float);
+
+	// Mask Image
+	vtkSetObjectMacro(ImageMask,vtkImageData);
+	vtkGetObjectMacro(ImageMask,vtkImageData);
+protected:
+	virtual int RequestInformation(vtkInformation *request,
+				 vtkInformationVector **inputVector,
+				 vtkInformationVector *outputVector);
+	virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+	vtkbisFDR();
+	virtual ~vtkbisFDR();
+private:
+	vtkbisFDR(const vtkbisFDR& src){};
+	vtkbisFDR& operator=(const vtkbisFDR& rhs){};
+	float Q;
+	float MaxPvalue;
+	vtkImageData* ImageMask;
+};
+
+#endif /* VTKBISFDR_H_ */
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisImageAverageComponents.cpp b/bioimagesuite30_src/Imaging/vtkbisImageAverageComponents.cpp
new file mode 100644
index 0000000..01198f9
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisImageAverageComponents.cpp
@@ -0,0 +1,151 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisImageAverageComponents.cpp
+ *
+ *  Created on: Sep 26, 2008
+ *      Author: Isabella Murphy; Xilin Lin
+ * @Input: 4D image and an ROI(Region of Interest) 3D image,
+ * @output: average time courses in each ROI region.Dimension: number of regions*1*1*N
+ * Assume user name each region using integer
+ * In output vtkImageData object, voxel 0 = region 0, voxel 10 = region 10 and so on.
+ * dimension is number of regions *1*1*1
+ */
+
+#include <vtkbisImageAverageComponents.h>
+#include "vtkObjectFactory.h"
+#include "vtkObject.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkPoints.h"
+
+using namespace std;
+
+vtkbisImageAverageComponents* vtkbisImageAverageComponents::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisImageAverageComponents");
+  if(ret)
+    {
+      return (vtkbisImageAverageComponents*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisImageAverageComponents;
+}
+
+vtkbisImageAverageComponents::vtkbisImageAverageComponents() {
+  this->StandardDeviationImage=NULL;
+}
+
+vtkbisImageAverageComponents::~vtkbisImageAverageComponents() {
+
+  if (this->StandardDeviationImage!=NULL)
+    this->StandardDeviationImage->Delete();
+}
+
+/*-------------------------------------------------------------------------------------
+ * Input/Output number of voxels are different, need to change extend information to let
+ * the pipeline know the difference
+ * @Set: output dimension = number of regions*1*1*N
+ * !!!Output will loose the ROI region information
+ */
+int vtkbisImageAverageComponents::RequestInformation(vtkInformation *request,
+				      vtkInformationVector **inputVector,
+				      vtkInformationVector *outputVector)
+{
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, 1);
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------------------------
+//   Main Function
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisImageAverageComponents::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+  if (this->GetNumberOfInputPorts()==0 || this->GetImageDataInput(0)==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+
+  if (this->StandardDeviationImage!=NULL)
+    this->StandardDeviationImage->Delete();
+
+  this->StandardDeviationImage=vtkImageData::New();
+  this->StandardDeviationImage->CopyStructure(output);
+  this->StandardDeviationImage->SetNumberOfScalarComponents(output->GetNumberOfScalarComponents());
+  this->StandardDeviationImage->AllocateScalars();
+  
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* out2=this->StandardDeviationImage->GetPointData()->GetScalars();
+  int numvoxels=inp->GetNumberOfTuples();
+  int numframes=inp->GetNumberOfComponents();
+
+  this->UpdateProgress(0.01);
+  float pog=0.00;
+
+  float tenth=(numvoxels)/10.0;
+  int count=0;
+
+  double correction=sqrt((double(numframes)))/sqrt(double(numframes-1));
+
+
+  double factor=double(1.0/numframes);
+  for (int n=0;n<numvoxels;n++)
+    {
+      double sum=0.0;
+      double sum2=0.0;
+      for (int frame=0;frame<numframes;frame++)
+	{
+	  double v=inp->GetComponent(n,frame);
+	  sum+=v;
+	  sum2+=v*v;
+	}
+      double mean =sum*factor;
+      out->SetComponent(n,0,mean);
+      double sigma=sqrt(sum2*factor-mean*mean)*correction;
+      out2->SetComponent(n,0,sigma);
+  
+      count++;
+      if (count==tenth)
+	{
+	  pog+=0.1;
+	  this->UpdateProgress(pog);
+	  count=0;
+	}
+    }
+  this->UpdateProgress(1.0);
+}
+
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisImageAverageComponents.h b/bioimagesuite30_src/Imaging/vtkbisImageAverageComponents.h
new file mode 100644
index 0000000..fdc0ca1
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisImageAverageComponents.h
@@ -0,0 +1,76 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*!
+ * vtkbisImageAverageComponents.h
+ *
+ *  Created on: Sep 26, 2008
+ *      Author: Isabella Murphy; Xilin Lin
+ *      calculate the mean time series of each ROI region
+ */
+
+#ifndef VTKBISIMAGEAVERAGECOMPONENTS_H_
+#define VTKBISIMAGEAVERAGECOMPONENTS_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include <string>
+#include <iostream>
+
+class vtkInformation;
+class vtkPoints;
+class vtkInformationVector;
+
+
+class vtkbisImageAverageComponents : public vtkSimpleImageToImageFilter {
+
+public:
+
+  static vtkbisImageAverageComponents *New();
+  vtkTypeMacro(vtkbisImageAverageComponents,vtkSimpleImageToImageFilter);
+
+  // Mask Image
+  vtkGetObjectMacro(StandardDeviationImage,vtkImageData);
+
+protected:
+  vtkbisImageAverageComponents();
+  virtual ~vtkbisImageAverageComponents();
+  virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector,
+				 vtkInformationVector *outputVector);
+
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+  vtkImageData* StandardDeviationImage;
+
+
+private:
+  vtkbisImageAverageComponents(const vtkbisImageAverageComponents& src){};
+  vtkbisImageAverageComponents& operator=(const vtkbisImageAverageComponents& rhs){};
+};
+
+#endif /* VTKBISIMAGEAVERAGECOMPONENTS_H_ */
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisImageUtil.cpp b/bioimagesuite30_src/Imaging/vtkbisImageUtil.cpp
new file mode 100644
index 0000000..faf173a
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisImageUtil.cpp
@@ -0,0 +1,73 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisImageUtil.cpp
+ *
+ *  Created on: May 18, 2009
+ *      Author: Isabella Murphy
+ */
+
+#include <vtkbisImageUtil.h>
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+
+vtkbisImageUtil* vtkbisImageUtil::New()
+{
+	// First try to create the object from the vtkObjectFactory
+	vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisImageUtil");
+	if(ret)
+    {
+		return (vtkbisImageUtil*)ret;
+    }
+	// If the factory was unable to create the object, then create it here.
+	return new vtkbisImageUtil;
+}
+
+vtkImageData* vtkbisImageUtil::OneminusPvalue(vtkImageData* pimage)
+{
+	cout<<"start compute 1-p"<<endl;
+
+	vtkImageData* out=vtkImageData::New();
+	out->CopyStructure(pimage);
+	out->SetNumberOfScalarComponents(pimage->GetNumberOfScalarComponents());
+	out->AllocateScalars();
+
+	vtkDataArray* pval=pimage->GetPointData()->GetScalars();
+	vtkDataArray* onempval=out->GetPointData()->GetScalars();
+	onempval->FillComponent(0,0);
+
+	int nt=pval->GetNumberOfTuples();
+
+	for (int t=0;t<nt;t++)
+	{
+		onempval->SetComponent(t,0,(1-pval->GetComponent(t,0)));
+	}
+	return out;
+
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisImageUtil.h b/bioimagesuite30_src/Imaging/vtkbisImageUtil.h
new file mode 100644
index 0000000..b6db655
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisImageUtil.h
@@ -0,0 +1,57 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisImageUtil.h
+ *
+ *  Created on: May 18, 2009
+ *      Author: Isabella Murphy
+ */
+
+#ifndef VTKBISIMAGEUTIL_H_
+#define VTKBISIMAGEUTIL_H_
+
+#include "vtkObject.h"
+#include "vtkImageData.h"
+
+class vtkbisImageUtil : public vtkObject{
+public:
+	vtkTypeMacro(vtkbisImageUtil,vtkObject);
+	static vtkbisImageUtil *New();
+
+	//static functions
+	static vtkImageData* OneminusPvalue(vtkImageData* image);
+
+};
+
+#endif /* VTKBISIMAGEUTIL_H_ */
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisObjectmapRegularization.cpp b/bioimagesuite30_src/Imaging/vtkbisObjectmapRegularization.cpp
new file mode 100644
index 0000000..2a95441
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisObjectmapRegularization.cpp
@@ -0,0 +1,406 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkObjectFactory.h"
+#include "vtkbisObjectmapRegularization.h"
+#include "vtkDoubleArray.h"
+#include "vtkMath.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+
+vtkbisObjectmapRegularization* vtkbisObjectmapRegularization::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisObjectmapRegularization");
+  if(ret)
+    {
+      return (vtkbisObjectmapRegularization*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisObjectmapRegularization;
+}
+
+// Construct object with no children.
+vtkbisObjectmapRegularization::vtkbisObjectmapRegularization()
+{
+  this->Smoothness=2.0;
+  this->NumberOfIterations=20;
+  this->ConvergencePercentage=0.2;
+  this->DebugVoxel=-1;
+  //  this->DebugVoxel=481439;
+}
+
+// ----------------------------------------------------------------------------
+vtkbisObjectmapRegularization::~vtkbisObjectmapRegularization()
+{
+
+}
+// ----------------------------------------------------------------------------
+//
+// M - Step
+//
+// ---------------------------------------------------------------------------
+//
+//   Total Minus Log Probability is sum of log likelihood and log MRF (MRF=Gibbs Model, log MRF=Energy Term)
+//
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+double vtkbisObjectmapRegularization::ComputeTotalMinusLogProbability(double    intensity,
+								      int    current_voxel,
+								      double    trylabel,
+								      vtkDataArray* labels,
+								      int incr[26],double wgth[26],
+								      double smoothness)
+{
+  double pmrf  =0.0;
+
+  if (smoothness>0.001)
+    {
+      for (int i=0;i<=25;i++)
+	{
+	  if ( fabs(trylabel-labels->GetComponent(current_voxel+incr[i],0))>0.0001)
+	    pmrf+=wgth[i];
+	}
+    }
+
+  pmrf=pmrf*smoothness;
+
+  if (current_voxel==this->DebugVoxel)
+    fprintf(stderr,"MRF Term = %lf",pmrf);
+
+  
+  if ( fabs(trylabel-intensity)>0.0001)
+    {
+      pmrf+=1.0;
+      if (current_voxel==this->DebugVoxel)
+	fprintf(stderr," + Intensity 1.0 = %lf\n",pmrf);
+    }
+  else if (current_voxel==this->DebugVoxel)
+    fprintf(stderr," + Intensity 0.0 = %lf\n",pmrf);
+  
+
+  return pmrf;
+}
+// --------------------------------------------------------------------------------------------
+//
+//  This is a greedy optimization scheme in which the label for each voxel
+//  is updated separately to maxmize the probablity of this voxel having class=label
+//
+// --------------------------------------------------------------------------------------------
+int  vtkbisObjectmapRegularization::ClassifyVoxel(int voxel_index,vtkDataArray* intensities,vtkDataArray* labels,vtkDataArray* outlabels,
+						  int incr[26],double wgth[26],
+						  double smoothness,vtkIdList* nlist)
+{
+
+  int current_label=(int)(labels->GetComponent(voxel_index,0)+0.00001);
+  double v=intensities->GetComponent(voxel_index,0);
+
+  if (voxel_index==this->DebugVoxel)
+    fprintf(stderr,"Beginning Classify Voxel voxel_index=%d, current_label=%d, intensity=%.0f\n",voxel_index,current_label,v);
+
+
+
+  // We need a different loop here to identify numclasses ......
+  nlist->SetNumberOfIds(0);
+  nlist->InsertNextId(current_label);
+  for (int ia=0;ia<=25;ia++)
+    {
+      int l=(int)(intensities->GetComponent(voxel_index+incr[ia],0)+0.00001);
+      nlist->InsertUniqueId(l);
+      //      if (this->DebugVoxel)
+      //	fprintf(stderr,"Inserting Unique Id  ia=%d  %d --> %d\n",ia,l,nlist->GetNumberOfIds());
+    }
+
+  double bestprob=0.0;
+  int    bestclass=current_label;
+  int numclasses=nlist->GetNumberOfIds();
+
+  if (voxel_index==this->DebugVoxel)
+    fprintf(stderr,"NumClasses=%d\n",numclasses);
+
+  if (numclasses>1)
+    {
+      for (int i=0;i< numclasses;i++)
+	{
+	  int cl=nlist->GetId(i);
+	  double clp=double(cl);
+	  double prob=this->ComputeTotalMinusLogProbability(v,voxel_index,clp,labels,incr,wgth,smoothness);
+	  if ( (prob-bestprob)<0.000001 || i==0)
+	    {
+	      bestprob=prob;
+	      bestclass=cl;
+	    }
+	  if (voxel_index==this->DebugVoxel)
+	    fprintf(stderr,"Examining Class %d prob=%lf (bestprob=%lf bestclass=%d)\n",
+		    cl,prob,bestprob,bestclass);
+	}
+
+      if (bestclass!=current_label)
+	{
+	  outlabels->SetComponent(voxel_index,0,(double)(bestclass+0.00001));
+	  //	  fprintf(stderr,"Changing voxel =%d\n",voxel_index);
+	  return 1;
+	}
+    }
+  
+  outlabels->SetComponent(voxel_index,0,(double)(current_label+0.0001));
+
+  return 0;
+}
+// ----------------------------------------------------------------------------------------------------
+//  High Level Routines for Maximization
+// ----------------------------------------------------------------------------------------------------
+// Computes the distances in (voxel index or raster index) between a voxel and its neighbors incr[26]
+// The weights are proportional to the inverse of the distance between each voxel and its neighbors
+//      these are constant if the image has isotropic resolution.
+// --------------------------------------------------------------------------------------------------
+int  vtkbisObjectmapRegularization::ComputeMRFIncrementsAndWeights(vtkImageData* img,int incr[26],double wgt[26])
+{
+  int dim[3]; img->GetDimensions(dim);
+  double sp[3];img->GetSpacing(sp);
+
+  int slicesize=dim[0]*dim[1];
+  int index=0;
+  double d[3];
+
+  for (int ic=-1;ic<=1;ic++)
+    {
+      d[2]=pow(sp[2]*ic,2.0);
+      for (int ib=-1;ib<=1;ib++)
+	{
+	  d[1]=pow(sp[1]*ib,2.0);
+	  for (int ia=-1;ia<=1;ia++)
+	    {
+	      d[0]=pow(sp[0]*ia,2.0);
+	      if (!(ia==0 && ib==0 && ic==0))
+		{
+		  incr[index]=ia+ib*dim[0]+ic*slicesize;
+		  wgt[index]=1.0/sqrt(d[0]+d[1]+d[2]);
+
+		  /*		  fprintf(stderr,"Ia=%d ib=%d ic=%d \tincr[index]=%d \twgt[index]=%.5f \td[0]=%.3f d[1]=%.3f d[2]=%.3f\n",
+		    ia,ib,ic,incr[index],wgt[index],d[0],d[1],d[2]);*/
+		  ++index;
+		}
+	    }
+	}
+    }
+
+  //  fprintf(stderr,"Done setting, number=%d\n",index-1);
+
+  double sum=0.0;
+  for (int l=0;l<=25;l++)
+    sum+=wgt[l];
+
+  for (int k=0;k<=25;k++)
+    {
+      wgt[k]/=sum;
+      //      fprintf(stderr,"Index=%d  incr=%d weight=%.3f\n",k,incr[k],wgt[k]);
+    }
+  
+    
+  return 1;
+}
+// ----------------------------------------------------------------------------
+/*double vtkbisObjectmapRegularization::DoMaximizationStep(vtkImageData* intensity_image,
+							 vtkImageData* label_image,
+							 vtkImageData* output_label_image,
+							 double smoothness,
+							 int maxiter)
+{
+
+  //  fprintf(stderr,"\n ******* Beginning Maximimization Step\n ------------------------------\n");
+
+  vtkDataArray* intensities=intensity_image->GetPointData()->GetScalars();
+  vtkDataArray* labels=label_image->GetPointData()->GetScalars();
+  vtkDataArray* out_labels=output_label_image->GetPointData()->GetScalars();
+  
+  double r1[2],r2[2];
+  intensities->GetRange(r1);
+  labels->GetRange(r2);
+  //  fprintf(stderr,"Input Range = %.0f:%.0f , Label Range=%.0f:%.0f\n",r1[0],r1[1],r2[0],r2[1]);
+
+  vtkIdList* nlist=vtkIdList::New();
+  nlist->SetNumberOfIds(26);
+
+  int nt=intensities->GetNumberOfTuples();
+  int dim[3]; intensity_image->GetDimensions(dim);
+  int incr[26]; double weights[26]; this->ComputeMRFIncrementsAndWeights(intensity_image,incr,weights);
+  int done=0,iter=0;
+  int tenth=nt/11;
+
+  // Only Classify voxels that are not on the image boundary. 
+  // Check for 2D Images here
+  int mink=1,maxk=dim[2]-1;
+  if (dim[2]==1)
+    {
+      mink=0;
+      maxk=1;
+    }
+
+  if (smoothness<0.001)
+    maxiter=1;
+
+  int slicesize=dim[0]*dim[1];
+
+  double total=0.0;
+  double changed=0.0;
+  int    count=0;
+      
+  fprintf(stderr,"*** MRF Regularization (%.2f) :",smoothness);
+  for (int k=mink;k<maxk;k++)
+    {
+      for (int j=1;j<dim[1]-1;j++)
+	{
+	  int vox=k*slicesize+j*dim[0]+1;
+	  for (int i=1;i<dim[0]-1;i++)
+	    {
+	      if (count==tenth)
+		{
+		  fprintf(stderr,".");
+		  count=0;
+		}
+	      
+	      changed+=this->ClassifyVoxel(vox,intensities,labels,out_labels,incr,weights,smoothness,nlist);
+	      ++vox;
+	      ++total;
+	      ++count;
+	    }
+	}
+    }
+         
+  changed=100.0*changed/total;
+  fprintf(stderr,"changed=%.4f\n",changed);
+  nlist->Delete();
+  return changed;
+  }*/
+// ----------------------------------------------------------------------------
+//
+//     Execute Segmentation 
+//
+// ----------------------------------------------------------------------------
+int vtkbisObjectmapRegularization::RequestInformation (vtkInformation * request,
+						       vtkInformationVector ** inputVector,
+						       vtkInformationVector * outputVector)
+{
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_SHORT, 1);
+  return 1;
+}
+
+void vtkbisObjectmapRegularization::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if ( input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs (one of them is NULL\n");
+      return;
+    }
+
+  int np1=input->GetNumberOfPoints();
+  double range[2]; input->GetPointData()->GetScalars()->GetRange(range);
+ 
+  this->UpdateProgress(double(0.2)/double(this->NumberOfIterations+1));
+
+
+  output->GetPointData()->GetScalars()->CopyComponent(0,input->GetPointData()->GetScalars(),0);
+  //classification->GetPointData()->GetScalars()->FillComponent(0,0.0);
+
+  vtkImageData* tmp=vtkImageData::New();
+  tmp->CopyStructure(output);
+  tmp->SetNumberOfScalarComponents(1);
+  tmp->AllocateScalars();
+  tmp->GetPointData()->GetScalars()->FillComponent(0,0);
+  
+
+  vtkIdList* nlist=vtkIdList::New();
+  nlist->SetNumberOfIds(26);
+
+  vtkDataArray* intensities=input->GetPointData()->GetScalars();
+  int nt=intensities->GetNumberOfTuples();
+  int dim[3]; input->GetDimensions(dim);
+  int incr[26]; double weights[26]; this->ComputeMRFIncrementsAndWeights(input,incr,weights);
+  int done=0,iter=0;
+  int tenth=nt/11;
+
+  // Only Classify voxels that are not on the image boundary. 
+  // Check for 2D Images here
+  int mink=1,maxk=dim[2]-1;
+  if (dim[2]==1)
+    {
+      mink=0;
+      maxk=1;
+    }
+
+  int slicesize=dim[0]*dim[1];
+  int iterations=1;
+  fprintf(stderr,"\n -----------------------------------\n Beginning Objectmap Regularization\n");
+  while(iterations<=this->NumberOfIterations)
+    {
+
+      vtkDataArray* labels=tmp->GetPointData()->GetScalars();
+      vtkDataArray* out_labels=output->GetPointData()->GetScalars();
+  
+      fprintf(stderr,"\n + + + + + +  Iteration %d (%.3f): ",iterations, this->Smoothness);
+      labels->CopyComponent(0,out_labels,0);
+      double changed=0.0;
+      double total=0.0;
+      int    count=0;
+      
+      for (int k=mink;k<maxk;k++)
+	for (int j=1;j<dim[1]-1;j++)
+	  {
+	    int vox=k*slicesize+j*dim[0]+1;
+	    for (int i=1;i<dim[0]-1;i++)
+	      {
+		if (count==tenth)
+		  {
+		    fprintf(stderr,".");
+		    count=0;
+		  }
+		
+		changed+=double(this->ClassifyVoxel(vox,intensities,labels,out_labels,incr,weights,this->Smoothness,nlist));
+		++vox;
+		++total;
+		++count;
+	      }
+	  }
+      changed=100.0*changed/total;
+      fprintf(stderr,"changed=%.6f\n",changed);
+      if (changed<this->ConvergencePercentage)
+	iterations=this->NumberOfIterations+1;
+      ++iterations;
+    }
+
+
+  nlist->Delete();
+  tmp->Delete();
+  this->UpdateProgress(1.0);
+}
+
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisObjectmapRegularization.h b/bioimagesuite30_src/Imaging/vtkbisObjectmapRegularization.h
new file mode 100644
index 0000000..e2f7c58
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisObjectmapRegularization.h
@@ -0,0 +1,114 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef __vtkbisObjectmapRegularization_h
+#define __vtkbisObjectmapRegularization_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkDoubleArray.h"
+#include "vtkShortArray.h"
+#include "vtkIdList.h"
+
+class vtkbisObjectmapRegularization : public vtkSimpleImageToImageFilter
+{
+public:
+  static vtkbisObjectmapRegularization *New();
+  vtkTypeMacro(vtkbisObjectmapRegularization,vtkSimpleImageToImageFilter);
+
+  // Description:
+  // Number Of Iterations (EM Iterations)
+  vtkGetMacro(NumberOfIterations,int);
+  vtkSetClampMacro(NumberOfIterations,int,0,20);
+
+  // Description:
+  // Weight of MRF Smoothness Term
+  vtkGetMacro(Smoothness,double);
+  vtkSetClampMacro(Smoothness,double,0,10000.0);
+
+
+  // Description:
+  // Max Percentage of Voxels changing needed for iteration to converge (0 == all voxels)
+  vtkGetMacro(ConvergencePercentage,double);
+  vtkSetClampMacro(ConvergencePercentage,double,0,0.4);
+
+  // Description:
+  // Debug Voxel ...
+  vtkGetMacro(DebugVoxel,int);
+  vtkSetMacro(DebugVoxel,int);
+
+
+
+protected:
+
+  vtkbisObjectmapRegularization();
+  virtual ~vtkbisObjectmapRegularization();
+  vtkbisObjectmapRegularization(const vtkbisObjectmapRegularization&) {};
+  void operator=(const vtkbisObjectmapRegularization&) {};
+
+
+  // Description:
+  // Basic Stuff
+  virtual void SimpleExecute(vtkImageData* in,vtkImageData* out);
+
+  virtual int RequestInformation (vtkInformation * request,
+				  vtkInformationVector ** inputVector,
+				  vtkInformationVector * outputVector);
+
+			      
+  // M-Step
+  // -----------------------------------
+
+  virtual double ComputeTotalMinusLogProbability(double   intensity,
+						 int      current_voxel,
+						 double   current_label,
+						 vtkDataArray* labels,
+						 int incr[26],double wgth[26],
+						 double smoothness);
+  
+  virtual int  ComputeMRFIncrementsAndWeights(vtkImageData* img,int incr[26],double wgt[26]);
+  virtual int  ClassifyVoxel(int voxel_index,vtkDataArray* intensities,vtkDataArray* labels,vtkDataArray* outlabels,int incr[26],double wgth[26],
+			     double smoothness,vtkIdList* nlist);
+  /*  virtual double DoMaximizationStep(vtkImageData* intensity_image,
+				    vtkImageData* label_image,
+				    vtkImageData* output_label_image,
+				    double smoothness,
+				    int maxiter);*/
+
+
+
+  // Descrtiption:
+  // Key Variables
+  double          Smoothness;
+  double          ConvergencePercentage;
+  int             NumberOfIterations;
+  int             DebugVoxel;
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisRtoPvalue.cpp b/bioimagesuite30_src/Imaging/vtkbisRtoPvalue.cpp
new file mode 100644
index 0000000..acd73ee
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisRtoPvalue.cpp
@@ -0,0 +1,139 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisRtoPvalue.cpp
+ *
+ *  Created on: May 18, 2009
+ *      Author: Isabella Murphy,Xilin Shen
+ *      take behavior correlation R value and number of study subjects as input,
+ *      calculate 1-p value
+ */
+
+#include <vtkbisRtoPvalue.h>
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkImageCast.h"
+#include "vtkbisRtoTmap.h"
+#include "vtkpxComputeTmap.h"
+#include "vtkbisImageUtil.h"
+#include "math.h"
+#include "pxisinf.h"
+// This creates the "New" Function
+vtkStandardNewMacro(vtkbisRtoPvalue);
+
+
+vtkbisRtoPvalue::vtkbisRtoPvalue() {
+	this->NumSubject=6;
+	this->ScaleFactor=1.0;
+	this->DOF=5;
+
+}
+
+
+
+
+int vtkbisRtoPvalue::RequestInformation(vtkInformation*,vtkInformationVector**,vtkInformationVector* outputVector)
+{
+  vtkInformation* outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+  return 1;
+}
+
+void vtkbisRtoPvalue::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+	cout<<"start vtkbisRtoPvalue"<<endl;
+
+	vtkImageCast* cast=vtkImageCast::New();
+	cast->SetInput(input);
+	cast->SetOutputScalarTypeToFloat();
+	cast->Update();
+
+	vtkImageData* temp=vtkImageData::New();
+	temp->ShallowCopy(cast->GetOutput());
+	cast->Delete();
+
+	vtkDataArray*   inp=temp->GetPointData()->GetScalars();
+	int nt=inp->GetNumberOfTuples();
+
+	vtkDataArray*   out=output->GetPointData()->GetScalars();
+	// Cleanup first -- fill output with zeros
+	out->FillComponent(0,0.0);
+
+	vtkbisRtoTmap* r2t = vtkbisRtoTmap::New();
+	r2t->SetNumSubject(this->GetNumSubject());
+
+	int maxcount=int(nt/10);
+	int count=0;
+	float pog=0.0;
+
+	this->UpdateProgress(0.01);
+
+	for (int t=0;t<nt;t++)
+	{
+		out->SetComponent(t,0,r2t->RtoTmap(inp->GetComponent(t,0)));
+
+		++count;
+		if (count==maxcount)
+		{
+			pog=float(t)/float(nt);
+			this->UpdateProgress(pog);
+			count=0;
+			//fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(numdone)/float(nt));
+		}
+	}
+	//calculate t to p
+	vtkImageData* pmap=vtkImageData::New();
+	vtkpxComputeTmap* t2p =vtkpxComputeTmap::New();
+	pmap=t2p->TmapToPvalueConversion(output,this->DOF,this->ScaleFactor);
+
+	//calculate 1-p
+	vtkImageData* oneminuspvalue=vtkImageData::New();
+	oneminuspvalue=vtkbisImageUtil::OneminusPvalue(pmap);
+	vtkDataArray* onempval=oneminuspvalue->GetPointData()->GetScalars();
+
+	//check if r < 0
+	for (int k=0;k<nt;k++)
+	{
+		out->SetComponent(k,0,onempval->GetComponent(k,0));
+		if(inp->GetComponent(k,0)<0)
+		{
+			if(onempval->GetComponent(k,0)>0)
+			{
+				out->SetComponent(k,0,-1*onempval->GetComponent(k,0));
+			}
+		}
+	}
+
+	this->UpdateProgress(1.0);
+	temp->Delete();
+
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisRtoPvalue.h b/bioimagesuite30_src/Imaging/vtkbisRtoPvalue.h
new file mode 100644
index 0000000..765434d
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisRtoPvalue.h
@@ -0,0 +1,79 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisRtoPvalue.h
+ *
+ *  Created on: May 18, 2009
+ *      Author: Isabella Murphy
+ */
+
+#ifndef VTKBISRTOPVALUE_H_
+#define VTKBISRTOPVALUE_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+
+class vtkbisRtoPvalue : public vtkSimpleImageToImageFilter{
+public:
+	static vtkbisRtoPvalue *New();
+	vtkTypeMacro(vtkbisRtoPvalue,vtkSimpleImageToImageFilter);
+
+	//number of subjects
+	vtkSetClampMacro(NumSubject,int,6,100000000);
+	vtkGetMacro(NumSubject,int);
+
+	// Set value of scalefactor to multiply t-values
+	vtkGetMacro(ScaleFactor,float);
+	vtkSetMacro(ScaleFactor,float);
+
+	//degree of freedom
+	vtkSetClampMacro(DOF,int,4,100000000);
+	vtkGetMacro(DOF,int);
+protected:
+
+	vtkbisRtoPvalue();
+	virtual ~vtkbisRtoPvalue(){};
+
+	virtual int RequestInformation(vtkInformation*,vtkInformationVector**,vtkInformationVector* outputVector);
+	// Execute Function -- main function
+	virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+private:
+	vtkbisRtoPvalue(const vtkbisRtoPvalue& src) {};
+	vtkbisRtoPvalue& operator=(const vtkbisRtoPvalue& rhs) {};
+	int NumSubject;
+	float ScaleFactor;
+	int DOF;
+};
+
+#endif /* VTKBISRTOPVALUE_H_ */
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisRtoTmap.cpp b/bioimagesuite30_src/Imaging/vtkbisRtoTmap.cpp
new file mode 100644
index 0000000..0d7c802
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisRtoTmap.cpp
@@ -0,0 +1,128 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisRtoTmap.cpp
+ *
+ *  Created on: May 6, 2009
+ *      Author: Isabella Murphy,Xilin Shen
+ *      take behavior correlation R value and number of study subjects as input,
+ *      calculate t value using the equation: t=r/sqrt[(1-r*r)/(N-2)]
+ */
+
+#include <vtkbisRtoTmap.h>
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkImageCast.h"
+#include "math.h"
+#include "pxisinf.h"
+// This creates the "New" Function
+vtkStandardNewMacro(vtkbisRtoTmap);
+
+vtkbisRtoTmap::vtkbisRtoTmap()
+{
+  this->NumSubject=0;
+}
+int vtkbisRtoTmap::RequestInformation(vtkInformation*,
+                                           vtkInformationVector**,
+                                           vtkInformationVector* outputVector)
+{
+  vtkInformation* outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+  return 1;
+}
+float vtkbisRtoTmap::RtoTmap(float r)
+{
+	unsigned long long raw = 0x7fc00000;
+	float posnan = *( float* )&raw;
+	float deno=0.0;
+
+	if (isnan(r) || isinf(r) || fabs(r)>1 )
+		return posnan;
+	if ( fabs(r) == 1 )
+	{
+		deno = 0.000001;
+		return float(r/deno);
+	}
+
+	deno = (float)sqrt((1-float(pow(r,2)))/(this->NumSubject-2));
+
+	return float(r/deno);
+
+}
+void vtkbisRtoTmap::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+	cout<<"start vtkbisRtoTmap"<<endl;
+
+		vtkImageCast* cast=vtkImageCast::New();
+		cast->SetInput(input);
+		cast->SetOutputScalarTypeToFloat();
+		cast->Update();
+
+		vtkImageData* temp=vtkImageData::New();
+		temp->ShallowCopy(cast->GetOutput());
+		cast->Delete();
+
+		vtkDataArray*   inp=temp->GetPointData()->GetScalars();
+		int nt=inp->GetNumberOfTuples();
+		int nc=inp->GetNumberOfComponents();
+
+		vtkDataArray*   out=output->GetPointData()->GetScalars();
+		// Cleanup first -- fill output with zeros
+		for (int ia=0;ia<nc;ia++)
+		  out->FillComponent(ia,0);
+
+		int maxcount=int(nt/10);
+		int count=0;
+		float pog=0.0;
+
+		this->UpdateProgress(0.01);
+
+		for (int t=0;t<nt;t++)
+		{
+			for (int c=0;c<nc;c++)
+			{
+				out->SetComponent(t,c,this->RtoTmap(inp->GetComponent(t,c)));
+
+			}
+			++count;
+			if (count==maxcount)
+			{
+				pog=float(t)/float(nt);
+			    this->UpdateProgress(pog);
+			    count=0;
+			    //fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,float(numdone)/float(nt));
+			}
+		}
+		this->UpdateProgress(1.0);
+		temp->Delete();
+
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisRtoTmap.h b/bioimagesuite30_src/Imaging/vtkbisRtoTmap.h
new file mode 100644
index 0000000..85bf965
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisRtoTmap.h
@@ -0,0 +1,64 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisRtoTmap.h
+ *
+ *  Created on: May 6, 2009
+ *      Author: isabella
+ */
+
+#ifndef VTKBISRTOTMAP_H_
+#define VTKBISRTOTMAP_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+
+class vtkbisRtoTmap : public vtkSimpleImageToImageFilter{
+public:
+	static vtkbisRtoTmap *New();
+	vtkTypeMacro(vtkbisRtoTmap,vtkSimpleImageToImageFilter);
+
+	//number of subjects
+	vtkSetMacro(NumSubject,int);
+	vtkGetMacro(NumSubject,int);
+
+	virtual float RtoTmap(float r);
+protected:
+	vtkbisRtoTmap();
+	virtual ~vtkbisRtoTmap(){};
+	virtual int RequestInformation(vtkInformation*,vtkInformationVector**,vtkInformationVector* outputVector);
+	// Execute Function -- main function
+	virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+private:
+	vtkbisRtoTmap(const vtkbisRtoTmap& src) {};
+	vtkbisRtoTmap& operator=(const vtkbisRtoTmap& rhs) {};
+	int NumSubject;
+
+};
+
+#endif /* VTKBISRTOTMAP_H_ */
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisSiemensDWIArrange.cpp b/bioimagesuite30_src/Imaging/vtkbisSiemensDWIArrange.cpp
new file mode 100644
index 0000000..b58b39b
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisSiemensDWIArrange.cpp
@@ -0,0 +1,134 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkbisSiemensDWIArrange.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkbisImageReslice.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include <stdio.h>
+#include "pxutil.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "nifti1_io.h"
+
+
+vtkbisSiemensDWIArrange* vtkbisSiemensDWIArrange::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisSiemensDWIArrange");
+  if(ret)
+    {
+      return (vtkbisSiemensDWIArrange*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisSiemensDWIArrange;
+}
+
+
+// Construct object to extract all of the input data.
+vtkbisSiemensDWIArrange::vtkbisSiemensDWIArrange()
+{
+  this->NumberOfSlices=1;
+}
+
+// ---------------------------------------------------------------------------
+
+void vtkbisSiemensDWIArrange::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkSimpleImageToImageFilter::PrintSelf(os,indent);
+}
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+int vtkbisSiemensDWIArrange::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+					  vtkInformationVector *outputVector)
+{
+  vtkInformation *inInfo =  inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  int wholeExtent[6]; inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
+  double sp[3];  inInfo->Get(vtkDataObject::SPACING(), sp);
+  double origin[3];  inInfo->Get(vtkDataObject::ORIGIN(),  origin);
+
+  int totalslices=wholeExtent[5]-wholeExtent[4]+1;
+  int numframes=int(totalslices)/int(this->NumberOfSlices);
+  
+  wholeExtent[4]=0;
+  wholeExtent[5]=this->NumberOfSlices-1;
+
+
+  origin[0]=0.0; origin[1]=0.0; origin[2]=0.0;
+
+  outInfo->Set(vtkDataObject::ORIGIN(), origin, 3);
+  outInfo->Set(vtkDataObject::SPACING(), sp, 3);
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6);
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, numframes);
+  return 1;
+}
+// ---------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+void vtkbisSiemensDWIArrange::SimpleExecute(vtkImageData* input, vtkImageData* output) 
+{
+  
+  int indim[3]; input->GetDimensions(indim);
+  int odim[3]; output->GetDimensions(odim);
+  int ncout=output->GetNumberOfScalarComponents();
+  int ncin=input->GetNumberOfScalarComponents();
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  /*  fprintf(stderr,"odim=%dx%dx%d,%d idim=%dx%dx%d,%d\n",
+	  odim[0],odim[1],odim[2],ncout,
+	  indim[0],indim[1],indim[2],ncin);*/
+  
+  for (int ia=0;ia<ncout;ia++)
+    out->FillComponent(0,0.0);
+
+  int slizesize=odim[1]*odim[0];
+  int inindex=0;
+  for (int newz=0;newz<odim[2];newz++)
+    for (int newt=0;newt<ncout;newt++)
+      {
+	int outindex=newz*slizesize;
+	for (int pixel=0;pixel<slizesize;pixel++)
+	  {
+	    out->SetComponent(outindex,newt,inp->GetComponent(inindex,0));
+	    ++inindex;
+	    ++outindex;
+	  }
+      }
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisSiemensDWIArrange.h b/bioimagesuite30_src/Imaging/vtkbisSiemensDWIArrange.h
new file mode 100644
index 0000000..9fac879
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisSiemensDWIArrange.h
@@ -0,0 +1,105 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+  
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkbisSiemensDWIArrange.h,v $
+  Language:  C++
+  Date:      $Date: 2003/05/13 15:37:02 $
+  Version:   $Revision: 1.2 $
+  
+  
+  Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+  All rights reserved.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+  
+=========================================================================*/
+// .NAME vtkbisSiemensDWIArrange - Splits a Siemens Mosaic Image into its parts
+
+
+#ifndef __vtkbisSiemensDWIArrange_h
+#define __vtkbisSiemensDWIArrange_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkbisImageHeader.h"
+
+class vtkbisSiemensDWIArrange : public vtkSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkbisSiemensDWIArrange,vtkSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  
+  // Description:
+  // Construct object to extract all of the input data.
+  
+  static vtkbisSiemensDWIArrange *New();
+
+  // Width * Height
+  vtkSetClampMacro(NumberOfSlices,int,1,1024);
+  vtkGetMacro(NumberOfSlices,int);
+
+protected:
+
+  //BTX
+  vtkbisSiemensDWIArrange();
+  ~vtkbisSiemensDWIArrange() {};
+  vtkbisSiemensDWIArrange(const vtkbisSiemensDWIArrange&) {};
+  void operator=(const vtkbisSiemensDWIArrange&) {};
+
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+  
+  // Execute Information Replacements
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+  //BTX
+  // Variables
+  vtkbisImageHeader* InputImageHeader;
+  vtkbisImageHeader* OutputImageHeader;
+  int NumberOfSlices;
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisSiemensMosaicConverter.cpp b/bioimagesuite30_src/Imaging/vtkbisSiemensMosaicConverter.cpp
new file mode 100644
index 0000000..297a7fd
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisSiemensMosaicConverter.cpp
@@ -0,0 +1,181 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkbisSiemensMosaicConverter.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkbisImageReslice.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include <stdio.h>
+#include "pxutil.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "nifti1_io.h"
+
+
+vtkbisSiemensMosaicConverter* vtkbisSiemensMosaicConverter::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisSiemensMosaicConverter");
+  if(ret)
+    {
+      return (vtkbisSiemensMosaicConverter*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisSiemensMosaicConverter;
+}
+
+
+// Construct object to extract all of the input data.
+vtkbisSiemensMosaicConverter::vtkbisSiemensMosaicConverter()
+{
+  this->MosaicWidth=64;
+  this->MosaicHeight=64;
+  this->MosaicDepth=20;
+}
+
+// ---------------------------------------------------------------------------
+
+void vtkbisSiemensMosaicConverter::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkSimpleImageToImageFilter::PrintSelf(os,indent);
+}
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+int vtkbisSiemensMosaicConverter::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+					  vtkInformationVector *outputVector)
+{
+  vtkInformation *inInfo =  inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  int wholeExtent[6]; inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
+  double sp[3];  inInfo->Get(vtkDataObject::SPACING(), sp);
+  double origin[3];  inInfo->Get(vtkDataObject::ORIGIN(),  origin);
+
+  int nframes=wholeExtent[5]-wholeExtent[4]+1;
+
+  int oldwidth=wholeExtent[3]-wholeExtent[2]+1;
+  int oldheight=wholeExtent[1]-wholeExtent[0]+1;
+
+  int nd=(oldwidth*oldheight)/(this->MosaicWidth*this->MosaicHeight);
+
+  if (nd>this->MosaicDepth)
+    nd=this->MosaicDepth;
+  else
+    this->MosaicDepth=nd;
+  /*  fprintf(stderr,"oldwidth=%d, oldheight=%d nd=%d,nf=%d\n",
+      oldwidth,oldheight,nd,nframes);*/
+  
+  wholeExtent[0]=0;
+  wholeExtent[1]=this->MosaicWidth-1;
+  wholeExtent[2]=0;
+  wholeExtent[3]=this->MosaicHeight-1;
+  wholeExtent[4]=0;
+  wholeExtent[5]=nd-1;
+
+
+  origin[0]=0.0;
+  origin[1]=0.0;
+  origin[2]=0.0;
+
+  outInfo->Set(vtkDataObject::ORIGIN(), origin, 3);
+  outInfo->Set(vtkDataObject::SPACING(), sp, 3);
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6);
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, nframes);
+  return 1;
+}
+// ---------------------------------------------------------------------------
+
+// ---------------------------------------------------------------------------
+void vtkbisSiemensMosaicConverter::SimpleExecute(vtkImageData* input, vtkImageData* output) 
+{
+  
+
+  int indim[3]; input->GetDimensions(indim);
+  int odim[3]; output->GetDimensions(odim);
+  int ncout=output->GetNumberOfScalarComponents();
+  int ncin=input->GetNumberOfScalarComponents();
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  /*  fprintf(stderr,"odim=%dx%dx%d,%d idim=%dx%dx%d,%d\n",
+	  odim[0],odim[1],odim[2],ncout,
+	  indim[0],indim[1],indim[2],ncin);*/
+  /*  double a[3]; output->GetOrigin(a);
+  fprintf(stderr,"Out Ori=%f,%f,%f\n",a[0],a[1],a[2]);
+   input->GetOrigin(a);
+   fprintf(stderr,"In Ori=%f,%f,%f\n",a[0],a[1],a[2]);*/
+
+  int inmatrix=indim[0]*indim[1];
+  int numimageswide=indim[0]/odim[0];
+  int numimagestall=indim[1]/odim[1];
+
+  //  fprintf(stderr,"Numimageswide=%d\n",numimageswide);
+  //  int outindex=0;
+
+  for (int ia=0;ia<ncout;ia++)
+    out->FillComponent(0,0.0);
+
+
+  for (int newz=0;newz<odim[2];newz++)
+    {
+      int Bigy=int(newz/numimageswide);
+      int Bigx=newz-int(Bigy*numimageswide);
+      Bigy=(numimagestall-1)-Bigy;
+      int outindex_z=newz*odim[0]*odim[1];
+      //      fprintf(stderr,"\n ********* newz=%d BigY=%d BigX=%d\n",newz,Bigy,Bigx);
+      for (int ny=0;ny<odim[1];ny++)
+	{
+	  //  int index=(Bigy+newy)*indim[0]+Bigx*odim[0];
+	  int newy=(odim[1]-1)-ny;
+	  int bigj=Bigy*odim[1]+newy;
+	  int outindex=outindex_z+newy*odim[0];
+	  int inindex =bigj*indim[0]+Bigx*odim[0];
+	  for (int newx=0;newx<odim[0];newx++)
+	    {
+	      //	      int bigi=Bigx*odim[0]+newx;
+	      for (int c=0;c<ncout;c++)
+		out->SetComponent(outindex,c,inp->GetComponent(inindex+c*inmatrix,0));
+		//		out->SetComponent(outindex,c,input->GetScalarComponentAsDouble(bigi,bigj,c,0));
+		//		output->SetScalarComponentFromDouble(newx,newy,nz,c,input->GetScalarComponentAsDouble(bigi,bigj,c,0));
+	      outindex++;
+	      inindex++;
+	    }
+	}
+    }
+ 
+  //  this->OutputImageHeader->ReconcileImage(output,0);
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisSiemensMosaicConverter.h b/bioimagesuite30_src/Imaging/vtkbisSiemensMosaicConverter.h
new file mode 100644
index 0000000..eab889e
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisSiemensMosaicConverter.h
@@ -0,0 +1,112 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+  
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkbisSiemensMosaicConverter.h,v $
+  Language:  C++
+  Date:      $Date: 2003/05/13 15:37:02 $
+  Version:   $Revision: 1.2 $
+  
+  
+  Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+  All rights reserved.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+  
+=========================================================================*/
+// .NAME vtkbisSiemensMosaicConverter - Splits a Siemens Mosaic Image into its parts
+
+
+#ifndef __vtkbisSiemensMosaicConverter_h
+#define __vtkbisSiemensMosaicConverter_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkbisImageHeader.h"
+
+class vtkbisSiemensMosaicConverter : public vtkSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkbisSiemensMosaicConverter,vtkSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  
+  // Description:
+  // Construct object to extract all of the input data.
+  
+  static vtkbisSiemensMosaicConverter *New();
+
+  // Width * Height
+  vtkSetClampMacro(MosaicWidth,int,1,1024);
+  vtkSetClampMacro(MosaicHeight,int,1,1024);
+  vtkSetClampMacro(MosaicDepth,int,1,1024);
+
+  vtkGetMacro(MosaicWidth,int);
+  vtkGetMacro(MosaicHeight,int);
+  vtkGetMacro(MosaicDepth,int);
+
+protected:
+
+  //BTX
+  vtkbisSiemensMosaicConverter();
+  ~vtkbisSiemensMosaicConverter() {};
+  vtkbisSiemensMosaicConverter(const vtkbisSiemensMosaicConverter&) {};
+  void operator=(const vtkbisSiemensMosaicConverter&) {};
+
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+  
+  // Execute Information Replacements
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+  //BTX
+  // Variables
+  vtkbisImageHeader* InputImageHeader;
+  vtkbisImageHeader* OutputImageHeader;
+  int  MosaicHeight;
+  int MosaicWidth;
+  int MosaicDepth;
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisTimeSeriesNormalize.cpp b/bioimagesuite30_src/Imaging/vtkbisTimeSeriesNormalize.cpp
new file mode 100644
index 0000000..6019e93
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisTimeSeriesNormalize.cpp
@@ -0,0 +1,148 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkbisTimeSeriesNormalize.h"
+#include "vtkpxAnalyzeImageWriter.h"
+
+vtkbisTimeSeriesNormalize* vtkbisTimeSeriesNormalize::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisTimeSeriesNormalize");
+  if(ret)
+    {
+      return (vtkbisTimeSeriesNormalize*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisTimeSeriesNormalize;
+}
+
+vtkbisTimeSeriesNormalize::vtkbisTimeSeriesNormalize()
+{
+  this->NormalizedThreshold=1;
+  this->Threshold=0.05;
+  this->DebugName=NULL;
+  this->ComputeMeanOnly=0;
+}
+
+vtkbisTimeSeriesNormalize::~vtkbisTimeSeriesNormalize()
+{
+  if (this->DebugName!=NULL)
+    delete [] this->DebugName;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------
+void vtkbisTimeSeriesNormalize::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+
+  output->SetScalarTypeToFloat();
+  if (this->ComputeMeanOnly==1)
+    output->SetNumberOfScalarComponents(1);
+}
+
+void vtkbisTimeSeriesNormalize::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+  if (input==NULL || output==NULL)
+    {
+      fprintf(stderr,"Bad Image Input to vtkbisTimeSeriesNormalize SimpleExecute\n");
+      return;
+    }
+
+  
+  vtkImageData* mean=vtkImageData::New();
+  mean->CopyStructure(input);
+  mean->SetNumberOfScalarComponents(1);
+  mean->SetScalarTypeToDouble();
+  mean->AllocateScalars();
+
+  vtkDataArray* marr = mean->GetPointData()->GetScalars();
+  vtkDataArray* inp = input->GetPointData()->GetScalars();
+  vtkDataArray* out =output->GetPointData()->GetScalars();
+
+  int nt=inp->GetNumberOfTuples();
+  int nc=inp->GetNumberOfComponents();
+
+  for (int i=0;i<nt;i++)
+    {
+      double sum=0.0;
+      for (int j=0;j<nc;j++)
+	sum+=inp->GetComponent(i,j);
+      sum/=double(nc);
+      marr->SetComponent(i,0,sum);
+    }
+
+  if (this->ComputeMeanOnly)
+    {
+      out->CopyComponent(0,marr,0);
+    }
+  else
+    {
+      double thr=this->Threshold;
+      if (this->NormalizedThreshold>0)
+	{
+	  double range[2]; marr->GetRange(range);
+	  thr=this->Threshold*(range[1]-range[0])+range[0];
+	}
+      
+      //      fprintf(stderr,"Using Threhsold = %.2f (%.3f)\n",thr,this->Threshold);
+
+      for (int i=0;i<nt;i++)
+	{
+	  double m=marr->GetComponent(i,0);
+	  if (m>thr)
+	    {
+	      double scale=100.0/m;
+	      for (int j=0;j<nc;j++)
+		out->SetComponent(i,j,inp->GetComponent(i,j)*scale);
+	    }
+	  else
+	    {
+	      for (int j=0;j<nc;j++)
+		out->SetComponent(i,j,0.0);
+	    }
+	}
+      
+      
+      if (this->DebugName!=NULL)
+	{
+	  vtkpxAnalyzeImageWriter* w=vtkpxAnalyzeImageWriter::New();
+	  w->SetInput(mean);
+	  w->Save(this->DebugName);
+	  fprintf(stderr,"Mean Image saved in %s\n",this->DebugName);
+	  w->Delete();
+	}
+    }
+  mean->Delete();
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisTimeSeriesNormalize.h b/bioimagesuite30_src/Imaging/vtkbisTimeSeriesNormalize.h
new file mode 100644
index 0000000..91152c2
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisTimeSeriesNormalize.h
@@ -0,0 +1,86 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkbisTimeSeriesNormalize_h
+#define __vtkbisTimeSeriesNormalize_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+
+
+class vtkbisTimeSeriesNormalize : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkbisTimeSeriesNormalize *New();
+  vtkTypeMacro(vtkbisTimeSeriesNormalize,vtkpxSimpleImageToImageFilter);
+
+
+  // Parameters
+  // Defaults is 5% of maximum mean intensity
+  vtkSetMacro(Threshold,double);
+  vtkGetMacro(Threshold,double);
+
+  vtkSetClampMacro(NormalizedThreshold, int,0,1);
+  vtkGetMacro(NormalizedThreshold, int);
+  vtkBooleanMacro(NormalizedThreshold, int);
+
+
+  // If set to 1 simply computes the average of the time series
+  vtkSetClampMacro(ComputeMeanOnly, int,0,1);
+  vtkGetMacro(ComputeMeanOnly, int);
+  vtkBooleanMacro(ComputeMeanOnly, int);
+
+
+  vtkSetStringMacro(DebugName);
+  vtkGetStringMacro(DebugName);
+
+
+protected:
+
+
+  vtkbisTimeSeriesNormalize();
+  virtual ~vtkbisTimeSeriesNormalize();
+
+  // Description:
+  // Static Routines
+  // Threshold mode 0 = absolute, 1 = normalized i.e. 0:1
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual void ExecuteInformation();
+
+  int NormalizedThreshold;
+  int ComputeMeanOnly;
+  double Threshold;
+  char* DebugName;
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisWaver.cpp b/bioimagesuite30_src/Imaging/vtkbisWaver.cpp
new file mode 100644
index 0000000..1982806
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisWaver.cpp
@@ -0,0 +1,615 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// ------------------------------------------------------------------------
+//
+//         Some of this code derives from AFNI Source and is released
+// 
+// ------------------------------------------------------------------------
+
+/*****************************************************************************
+   Major portions of this software are copyrighted by the Medical College
+   of Wisconsin, 1994-2000, and are released under the Gnu General Public
+   License, Version 2.  See the file README.Copyright for details.
+******************************************************************************/
+
+#include "vtkObjectFactory.h"
+#include "vtkIntArray.h"
+#include "vtkpxMatrix.h"
+#include "vtkbisWaver.h"
+#include "vtkstd/string"
+
+vtkbisWaver* vtkbisWaver::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisWaver");
+  if(ret)
+    {
+      return (vtkbisWaver*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisWaver;
+}
+
+// ---------------------------------------------------------------------------------------------------------------------------
+
+vtkbisWaver::vtkbisWaver() 
+{
+  this->Status=NULL;
+  this->ResetParameters();
+}
+
+vtkbisWaver::~vtkbisWaver() 
+{
+  if (this->Status!=NULL)
+    delete [] this->Status;
+}
+
+void vtkbisWaver::ResetParameters() 
+{
+  // This is GAM
+  this->Waveform_type    = 1;
+
+  this->WAV_delay_time   =  2.0 ;
+  this->WAV_rise_time    =  4.0 ;
+  this->WAV_fall_time    =  6.0 ;
+  this->WAV_undershoot   =  0.2 ;
+  this->WAV_restore_time =  2.0 ;
+
+  this->Peak=1.0;
+  this->TR=1.0 ;
+
+  this->GAM_power        = 8.6 ;
+  this->GAM_time         = 0.547 ;
+  this->GAM_ampl         = 0.0 ;
+  this->GAM_delay_time   = 0.0 ;
+  this->SetStatus("None");
+}
+
+
+/*----------------------------------------------------------------
+  Function that transitions from 0 to 1 over input x in [0,1].
+------------------------------------------------------------------*/
+
+
+double vtkbisWaver::ztone( double x )
+{
+#ifndef PI
+#  define PI 3.14159265358979323846
+#endif
+
+#define ZT_FAC 0.50212657
+#define ZT_ADD 0.99576486
+   double y , z ;
+
+   if( x <= 0.0 ) return 0.0 ;
+   if( x >= 1.0 ) return 1.0 ;
+
+   y = (0.5*PI) * ( 1.6 * x - 0.8 ) ;
+   z = ZT_FAC * ( tanh(tan(y)) + ZT_ADD ) ;
+   return z ;
+#undef ZT_FAC
+#undef ZT_ADD
+#undef PI
+}
+
+double vtkbisWaver::waveform( double t )
+{
+  
+  switch (this->Waveform_type)
+    {
+    case 0:
+      if (t==0.0)
+	return 1.0;
+      else
+	return 0.0;
+      break;
+    case 2:
+      return waveform_GAM(t) ;
+    case 3:
+      return waveform_doublegamma(t);
+    case 4:
+      return waveform_triplegamma(t);
+    case 5:
+      return waveform_spm(t);
+    default:
+      return waveform_WAV(t);
+    }
+}
+
+/*----------------------------------------------------------------*/
+
+// Rajeevan Notation from vtknrGammaSourceNew ->
+//  this->Alpha -> GAM_Power
+//  this->Beta  -> GAM_Time
+//  0           -> this->GAM_DelayTime
+//  1.0/MaxAmpl -> GAM_Ampl
+
+double vtkbisWaver::gammafunction( double t,double gpower,double gtime,double gpeak)
+{
+  if (t<0.0)
+    return 0.0;
+
+  double ampl= gpeak*exp(gpower) / pow(gpower*gtime,gpower) ;
+  return ampl * pow(t,gpower) * exp(-t/gtime) ;
+}
+/*----------------------------------------------------------------*/
+// The following three functions come vtknrHrfSource (N. Rajeevan)
+/*----------------------------------------------------------------*/
+double vtkbisWaver::waveform_doublegamma( double t ) 
+{
+  double v=this->gammafunction(t,5.0,1.1,1.0);
+  return v+this->gammafunction(t,12.0,0.9,-0.4);
+}
+/*----------------------------------------------------------------*/
+double vtkbisWaver::waveform_triplegamma( double t ) 
+{
+  double v=this->waveform_doublegamma(t);
+  return v+this->gammafunction(t,3.0,0.4,-0.25);
+}
+/*----------------------------------------------------------------*/
+double vtkbisWaver::waveform_spm( double t ) 
+{
+  double v=this->gammafunction(t, 5.0,1.0,1.0);
+  return v+this->gammafunction(t,16.0,1.0,-0.1667);
+}
+/*----------------------------------------------------------------*/
+
+double vtkbisWaver::waveform_GAM( double t )
+{
+  if( GAM_ampl == 0.0 ){
+    GAM_ampl = exp(GAM_power) / pow(GAM_power*GAM_time,GAM_power) ;
+  }
+  
+  if( t-GAM_delay_time <= 0.0 ) return 0.0 ;
+  
+  return GAM_ampl * pow((t-GAM_delay_time),GAM_power) * exp(-(t-GAM_delay_time)/GAM_time) ;
+}
+
+/*----------------------------------------------------------------*/
+
+double vtkbisWaver::waveform_WAV( double t )
+{
+
+  double      WAV_rise_start   = WAV_delay_time ;
+  double      WAV_fall_start   = WAV_rise_start + WAV_rise_time ;
+  double      WAV_fall_end     = WAV_fall_start + WAV_fall_time ;
+  double      WAV_restore_end  = WAV_fall_end   + WAV_restore_time ;
+
+   if( t < WAV_rise_start )
+      return 0.0 ;
+
+   if( t < WAV_fall_start )
+      return ztone( (t-WAV_rise_start)/WAV_rise_time ) ;
+
+   if( t < WAV_fall_end )
+      return (1.0+WAV_undershoot) * ztone( (WAV_fall_end-t)/WAV_fall_time )
+             - WAV_undershoot ;
+
+   if( t < WAV_restore_end )
+      return -WAV_undershoot * ztone( (WAV_restore_end-t)/WAV_restore_time ) ;
+
+   return 0.0 ;
+}
+
+double vtkbisWaver::ComputeGammaDuration(double G_power,double G_time)
+{
+  double bal = 5.5/G_power + 1.0 ;
+  double al  = bal ;
+  double lal = log(al) ;
+      
+  while( al < bal + lal ){ al = bal + 1.1*lal ; lal = log(al) ; }
+  
+  return al * G_power * G_time ;
+}
+/*----------------------------------------------------------------*/
+double vtkbisWaver::ComputeDuration()
+{
+  double   WAV_duration = -666.0 ;
+
+  //  fprintf(stderr,"Waveform_type=%d\n",this->Waveform_type);
+
+  switch (this->Waveform_type)
+    {
+    case 2:
+      WAV_duration=this->ComputeGammaDuration(GAM_power,GAM_time);
+      break;
+    case 3:
+    case 4:
+      WAV_duration=this->ComputeGammaDuration(5.0,1.1)*1.5;
+      break;
+    case 5:
+      WAV_duration=this->ComputeGammaDuration(5.0,1.0)*1.5;
+      break;
+    default:
+      WAV_duration = WAV_delay_time + WAV_rise_time + WAV_fall_time
+	+ ( (WAV_undershoot != 0.0) ? WAV_restore_time : 0.0 ) ;
+    }
+  return WAV_duration;
+}
+
+/*----------------------------------------------------------------*/
+vtkDoubleArray* vtkbisWaver::GenerateResponseFunction()
+{
+  double   WAV_duration = this->ComputeDuration();
+  //  fprintf(stderr,"Waveform_type=%d\n",this->Waveform_type);
+  
+  int WAV_npts = (int)(1 + ceil(WAV_duration/this->TR)) ;
+  //fprintf(stderr,"WAV_Npts=%d, %d, %f\n",WAV_npts,WAV_duration,this->TR);
+  vtkDoubleArray* arr=vtkDoubleArray::New();
+  arr->SetNumberOfComponents(1);
+  arr->SetNumberOfTuples(WAV_npts);
+
+  for(int  ii=0 ; ii < WAV_npts ; ii++ )
+    arr->SetComponent(ii,0, this->Peak * this->waveform(this->TR*double(ii) ));
+
+  char line[200];
+  
+
+  if (this->Waveform_type==1)
+    {
+      sprintf(line,"Cox Waveform: del=%.3f rist=%.3f fall=%.3f under=%.3f restore=%.3f peak=%.3f TR=%.3f",
+	      this->WAV_delay_time,this->WAV_rise_time,this->WAV_fall_time,this->WAV_undershoot,this->WAV_restore_time,
+	      this->Peak,this->TR);
+      this->SetStatus(line);
+    }
+  else if (this->Waveform_type==3)
+    {
+      this->SetStatus("Canonical Double Gamma");
+    }
+  else if (this->Waveform_type==4)
+    {
+      this->SetStatus("Canonical Triple Gamma");
+    }
+  else if (this->Waveform_type==5)
+    {
+      this->SetStatus("SPM Double Gamma");
+    }
+  else
+    {
+      sprintf(line,"Gamma Waveform: power=%.3f time=%.3f ampl=%.3f delay_time=%.3f peak=%.3f TR=%.3f",
+	      this->GAM_power,this->GAM_time,this->GAM_ampl,this->GAM_delay_time,
+	      this->Peak,this->TR);
+      this->SetStatus(line);
+    }
+
+  return arr;
+}
+
+/*----------------------------------------------------------------*/
+vtkpxMatrix* vtkbisWaver::GenerateResponseFunctionForAllOptions()
+{
+  int old_waveform_type=this->Waveform_type;
+
+  double duration=0.0;
+  for (int i=1;i<=5;i++)
+    {
+      this->Waveform_type=i;
+      double v=this->ComputeDuration();
+      if (v>duration)
+	duration=v;
+    }
+
+  int WAV_npts = (int)(1 + ceil(duration/this->TR)) ;
+  vtkpxMatrix* plots=vtkpxMatrix::New();
+  plots->Zeros(WAV_npts,5);
+
+  for (int i=1;i<=5;i++)
+    {
+      this->Waveform_type=i;
+      for(int  ii=0 ; ii < WAV_npts ; ii++ )
+	plots->SetDirectElement(ii, i -1, this->Peak * this->waveform(this->TR*double(ii) ));
+    }
+
+  this->Waveform_type=old_waveform_type;
+  return plots;
+}
+/*----------------------------------------------------------------*/
+int vtkbisWaver::CreateWaveform(vtkpxMatrix* input,vtkpxMatrix* output)
+{
+
+  if (input==NULL || output==NULL)
+    {
+      fprintf(stderr,"Bad Matrix Input to vtkbisWaver::CreateWaveform\n");
+      return 0;
+    }
+
+  
+   /*---- if no input timeseries, just output waveform ----*/
+
+  int size[2]; input->GetSize(size);
+
+  int  IN_npts=size[0];
+
+  vtkDoubleArray* resp=this->GenerateResponseFunction();
+  int WAV_npts=resp->GetNumberOfTuples();
+
+  /*  fprintf(stderr,"Response Function\n");
+    for (int i=0;i<WAV_npts;i++)
+    fprintf(stderr,"%d \t %.5f\n",i,resp->GetComponent(i,0));*/
+  
+  int OUT_npts = IN_npts + WAV_npts ;
+
+
+
+  output->Zeros(OUT_npts,size[1]);
+
+  for (int column=0;column<size[1];column++)
+    {
+      for(int jj=0 ; jj < IN_npts ; jj++ )
+	{
+	  double val = input->GetDirectElement(jj,column);
+	  if( val == 0.0 || fabs(val) >= 33333.0 ) 
+	    continue ;
+	  for(int ii=0 ; ii < WAV_npts && ii+jj < OUT_npts ; ii++ )
+	    output->AddToElement(ii+jj,column,val * resp->GetComponent(ii,0));
+	}
+      
+      for(int jj=0 ; jj < IN_npts ; jj++ )
+	{
+	  double val = input->GetDirectElement(jj,column);
+	  if( fabs(val) >= 33333.0 ) 
+	    output->SetDirectElement(jj,column,99999.0);
+	}
+      
+    }
+  resp->Delete();
+  return 1;
+}
+
+int vtkbisWaver::CreateStackedWaveform(vtkpxMatrix* input,vtkpxMatrix* output,vtkIntArray* breaks)
+{
+  if (input==NULL || output==NULL || breaks==NULL)
+    {
+      fprintf(stderr,"Bad Matrix Input to vtkbisWaver::CreateStacked Waveform\n");
+      return 0;
+    }
+  
+
+  int nruns=breaks->GetNumberOfTuples();
+  if (nruns<1)
+    {
+      fprintf(stderr,"Bad Breaks Input to vtkbisWaver::CreateStacked Waveform\n");
+      return 0;
+    }
+
+  vtkpxMatrix* subinput=vtkpxMatrix::New();
+  vtkpxMatrix* suboutput=vtkpxMatrix::New();
+
+  int size[2]; input->GetSize(size);
+  output->Zeros(size[0],size[1]);
+
+  for (int i=0;i<nruns;i++)
+    {
+      int minrow=(int)breaks->GetComponent(i,0);
+      int maxrow=size[0]-1;
+      if (i<(nruns-1))
+	maxrow=(int)(breaks->GetComponent(i+1,0))-1;
+
+      fprintf(stderr,"Waver Matrix Run %d rows=%d:%d\n",i+1,minrow,maxrow);
+
+      subinput->Copy(input,minrow,maxrow,-1,-1);
+      
+      this->CreateWaveform(subinput,suboutput);
+
+      //      char line[300];
+      /*      sprintf(line,"submatrix_%d.matr",i+1);
+      suboutput->Save(line);
+      sprintf(line,"subinput_%d.matr",i+1);
+      subinput->Save(line);*/
+      
+      // Copy Stuff back into main matrix
+      for (int row=minrow;row<=maxrow;row++)
+	for (int col=0;col<size[1];col++)
+	  output->SetDirectElement(row,col,suboutput->GetDirectElement(row-minrow,col));
+    }
+  subinput->Delete();
+  suboutput->Delete();
+
+  return 1;
+
+
+}
+/*----------------------------------------------------------------*/
+int vtkbisWaver::AddDriftTerms(vtkpxMatrix* input,vtkpxMatrix* output,vtkIntArray* breaks,int polorder)
+{
+  if (input==NULL || output == NULL || breaks==NULL)
+    {
+      fprintf(stderr,"Bad Input to bisWaver::AddDriftTerms\n");
+      return 0;
+    }
+
+  if (polorder<-1)
+    {
+      output->Copy(input);
+      return 1;
+    }
+
+  if (polorder>3)
+    polorder=3;
+
+
+  int nruns=breaks->GetNumberOfTuples();
+  fprintf(stderr,"Breaks = %d : ",nruns);
+  for (int i=0;i<nruns;i++)
+    fprintf(stderr,"%d ",(int)breaks->GetComponent(i,0));
+  fprintf(stderr,"\n");
+
+
+  int size[2]; input->GetSize(size);
+  int numterms=polorder+1;
+  int numextra=nruns*numterms;
+  int numcols= size[1]+numextra;
+
+  output->Zeros(size[0],numcols);
+
+  for (int r=0;r<size[0];r++)
+    for (int c=numextra;c<numcols;c++)
+      output->SetDirectElement(r,c,input->GetDirectElement(r,c-numextra));
+  //  output->Save("simple_copy_afni.matr");
+
+  for (int i=0;i<nruns;i++)
+    {
+      int minrow=(int)breaks->GetComponent(i,0);
+      int maxrow=size[0]-1;
+      if (i<(nruns-1))
+	maxrow=int(breaks->GetComponent(i+1,0))-1;
+      
+      if ( (polorder>-1) && (maxrow>minrow))
+	{
+	  for (int row=minrow;row<=maxrow;row++)
+	    {
+	      // Next the Legendre Stuff
+	      int mincol=i*numterms;
+	      int maxcol=mincol+numterms;
+
+	      double t0=double(minrow);
+	      double t1=double(maxrow);
+	      double dt=0.5*(t1-t0);
+	      double r=double(row);
+	      double t=(r-t0)/dt-1.0;
+	      double t2=t*t;
+	      double t3=t*t2;
+
+	      // This is needed to match AFNI Exactly
+	      double afni_offset=0.5/dt;
+	      
+	      for (int pol=0;pol<numterms;pol++)
+		{
+		  if (row==minrow)
+		    fprintf(stderr,"run=%d (rows=%d:%d) \t\t pol=%d col=%d (mincol=%d)\n",i,minrow,maxrow,pol,mincol+pol,mincol);
+
+		  switch(pol)
+		    {
+		    case 0: // P_0(x)=1;
+		      output->SetDirectElement(row,mincol+pol,1.0); 
+		      break;
+		    case 1: // P_1(x)=x;
+		      output->SetDirectElement(row,mincol+pol,t); 
+		      break;
+		    case 2: // P_2(x)=0.5*(3x^2-1)
+		      output->SetDirectElement(row,mincol+pol,1.5*t2-0.5-afni_offset); 
+		      break;
+		    case 3: // P_3(x) =0.5*(5x^3-3x)
+		      output->SetDirectElement(row,mincol+pol,2.5*t3-1.5*t); 
+		      break;
+		    }
+		}
+	    }
+	}
+    }
+  return 1;
+}
+
+// ---------------------------------------------------------------------------
+// More complex GLM with rates
+// ---------------------------------------------------------------------------
+
+int vtkbisWaver::AddDriftAndRateTerms(vtkpxMatrix* input,vtkpxMatrix* output,vtkIntArray* breaks,int polorder,int numrates)
+{
+  if (numrates<0)
+    numrates=0;
+  else if (numrates>3)
+    numrates=3;
+
+
+  int ok=vtkbisWaver::AddDriftTerms(input,output,breaks,polorder);
+
+  if (ok==0)
+    return 0;
+
+  if (numrates==0)
+    return ok;
+  
+  int insize[2]; input->GetSize(insize);
+  int outsize[2]; output->GetSize(outsize);
+
+  vtkpxMatrix* temp=vtkpxMatrix::New();
+  temp->Copy(output);
+
+  int outcolumns=outsize[1]+insize[1]*numrates;
+  output->Zeros(outsize[0],outcolumns);
+  for (int i=0;i<outsize[0];i++)
+    for (int j=0;j<outsize[1];j++)
+      output->SetDirectElement(i,j,temp->GetDirectElement(i,j));
+
+  // On to creating normalized versions for higher orders .....
+
+  
+  int maxdrift=outsize[1]-insize[1];
+  for (int task=0;task<insize[1];task++)
+    {
+      temp->Zeros(outsize[0],1+numrates);
+      int tindex=task+maxdrift;
+      double magn=0.0;
+      for (int i=0;i<outsize[0];i++)
+	{
+	  double v=output->GetDirectElement(i,tindex);
+	  magn+=v*v;
+	  temp->SetDirectElement(i,0,v);
+	}
+      magn=sqrt(magn);
+      temp->NormalizeColumns(0,0);
+      
+      for (int order=1;order<=numrates;order++)
+	{
+	  double t=double(order);
+	  for (int i=0;i<outsize[0];i++)
+	    {
+	      double x=double(i);
+	      temp->SetDirectElement(i,order,pow(x,t)*output->GetDirectElement(i,tindex));
+	    }
+	  temp->NormalizeColumns(order,order);
+
+	  // Orthogonalize to all previous columns of temp matrix
+	  for (int orthog=0;orthog<order;orthog++)
+	    {
+	      double dot=0.0;
+	      for (int i=0;i<outsize[0];i++)
+		dot+=(temp->GetDirectElement(i,orthog)*temp->GetDirectElement(i,order));
+	      //	      fprintf(stderr,"Orthogonalizing order=%d to column=%d, dot=%.5f\n",order,orthog,dot);
+
+	      for (int i=0;i<outsize[0];i++)
+		temp->SetDirectElement(i,order,temp->GetDirectElement(i,order)-dot*temp->GetDirectElement(i,orthog));
+	      temp->NormalizeColumns(order,order);
+	    }
+	  
+      int outcol=outsize[1]+(order-1)*insize[1]+task;
+	  fprintf(stderr,"Storing rate terms for task=%d (rate=%d) which lies in column=%d --> stored in %d\n",task,order,tindex,outcol);
+
+	  for (int i=0;i<outsize[0];i++)
+	    output->SetDirectElement(i,outcol,magn*(temp->GetDirectElement(i,order)));
+	}
+    }
+
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisWaver.h b/bioimagesuite30_src/Imaging/vtkbisWaver.h
new file mode 100644
index 0000000..e87877e
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisWaver.h
@@ -0,0 +1,166 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkbisWaver_h
+#define __vtkbisWaver_h
+
+#include "vtkObject.h"
+#include "vtkDoubleArray.h"
+
+class vtkpxMatrix;
+class vtkIntArray;
+
+class vtkbisWaver : public vtkObject
+{
+public:
+  static vtkbisWaver *New();
+  vtkTypeMacro(vtkbisWaver,vtkObject);
+
+
+  // Description:
+  // Compute Waveform commands
+
+  // Waveform for a single run, input is matrix of 1s and 0s, 1 column per task
+  virtual int CreateWaveform(vtkpxMatrix* input,vtkpxMatrix* output);
+
+  // Waveform for multiple runs, input is matrix of 1s and 0s, 1 column per task
+    virtual int CreateStackedWaveform(vtkpxMatrix* input,vtkpxMatrix* output,vtkIntArray* breaks);
+
+  // Add drift terms to stacked waveform output, input is output of stacked waveform
+  virtual int AddDriftTerms(vtkpxMatrix* input,vtkpxMatrix* output,vtkIntArray* breaks,int polorder=3);
+
+  // Add rate terms (linear, quadratic etc) for tasks
+  virtual int AddDriftAndRateTerms(vtkpxMatrix* input,vtkpxMatrix* output,vtkIntArray* breaks,int polorder,int numrates=1);
+
+  // Description:
+  // Generate Response Function
+  vtkDoubleArray* GenerateResponseFunction();
+  vtkpxMatrix*    GenerateResponseFunctionForAllOptions();
+
+  // Description:
+  // Status is final result
+  vtkGetStringMacro(Status);
+  vtkSetStringMacro(Status);
+
+
+
+  // Description:
+  // Set Parameters for Waver things -- see  Waver documentation for details
+  // 0 = Cox Type, 1 = GAM
+  vtkGetMacro(Waveform_type,int);
+  vtkSetClampMacro(Waveform_type,int,0,5);
+  virtual void SetWaveformToNone() { this->SetWaveform_type(0);}
+  virtual void SetWaveformToWAV() { this->SetWaveform_type(1);}
+  virtual void SetWaveformToGAM() { this->SetWaveform_type(2);}
+  virtual void SetWaveformToDoubleGamma() { this->SetWaveform_type(3);}
+  virtual void SetWaveformToTripleGamma() { this->SetWaveform_type(4);}
+  virtual void SetWaveformToSPMCanonical() { this->SetWaveform_type(5);}
+
+
+  
+  vtkGetMacro(WAV_delay_time,double);
+  vtkSetMacro(WAV_delay_time,double);
+
+  vtkGetMacro(WAV_rise_time,double);
+  vtkSetMacro(WAV_rise_time,double);
+
+  vtkGetMacro(WAV_fall_time,double);
+  vtkSetMacro(WAV_fall_time,double);
+
+  vtkGetMacro(WAV_undershoot,double);
+  vtkSetMacro(WAV_undershoot,double);
+
+  vtkGetMacro(WAV_restore_time,double);
+  vtkSetMacro(WAV_restore_time,double);
+
+  vtkGetMacro(Peak,double);
+  vtkSetMacro(Peak,double);
+
+  vtkGetMacro(TR,double);
+  vtkSetMacro(TR,double);
+
+  vtkGetMacro(GAM_power,double);
+  vtkSetMacro(GAM_power,double);
+
+  vtkGetMacro(GAM_time,double);
+  vtkSetMacro(GAM_time,double);
+
+  vtkGetMacro(GAM_ampl,double);
+  vtkSetMacro(GAM_ampl,double);
+  
+  vtkGetMacro(GAM_delay_time,double);
+  vtkSetMacro(GAM_delay_time,double);
+
+protected:
+
+  vtkbisWaver();
+  ~vtkbisWaver();
+  vtkbisWaver(const vtkbisWaver&) {};
+  void operator=(const vtkbisWaver&) {};
+
+  // Set all to defaults
+  virtual void ResetParameters();
+  virtual double ComputeGammaDuration(double G_power,double G_time);
+  virtual double ComputeDuration();
+
+
+  // Internal Functions from afni waver
+  double gammafunction( double t,double gpower,double gtime,double gpeak);
+  virtual double ztone( double x ) ;
+  virtual double waveform_GAM( double t ) ;
+  virtual double waveform_WAV( double t ) ;
+  virtual double waveform_doublegamma( double t ) ;
+  virtual double waveform_triplegamma( double t ) ;
+  virtual double waveform_spm( double t ) ;
+  virtual double waveform( double t ) ;
+
+
+  int    Waveform_type;
+  
+  double WAV_delay_time;
+  double WAV_rise_time;
+  double WAV_fall_time;
+  double WAV_undershoot;
+  double WAV_restore_time;
+
+  double Peak;
+  double TR;
+
+  double GAM_power;
+  double GAM_time;
+  double GAM_ampl;
+  double GAM_delay_time;
+
+  char* Status;
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisZscoretoPvalue.cpp b/bioimagesuite30_src/Imaging/vtkbisZscoretoPvalue.cpp
new file mode 100644
index 0000000..3b75f63
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisZscoretoPvalue.cpp
@@ -0,0 +1,112 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisZscoretoPvalue.cpp
+ *
+ *  Created on: Apr 16, 2009
+ *      Author: Isabella Murphy
+ */
+
+#include <vtkbisZscoretoPvalue.h>
+#include "vtkObjectFactory.h"
+#include <vtkpxMath.h>
+#include <vtkImageCast.h>
+#include <vtkImageData.h>
+#include <vtkDataArray.h>
+#include <vtkInformation.h>
+#include <vtkInformationVector.h>
+#include <vtkPointData.h>
+
+using namespace std;
+
+// This creates the "New" Function
+vtkStandardNewMacro(vtkbisZscoretoPvalue);
+
+
+//----------------------------------------------------------------------------
+int vtkbisZscoretoPvalue::RequestInformation(vtkInformation*,
+                                           vtkInformationVector**,
+                                           vtkInformationVector* outputVector)
+{
+  vtkInformation* outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+  return 1;
+}
+void vtkbisZscoretoPvalue::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+	cout<<"start vtkbisZscoretoPvalue"<<endl;
+
+	vtkImageCast* cast=vtkImageCast::New();
+	cast->SetInput(input);
+	cast->SetOutputScalarTypeToFloat();
+	cast->Update();
+
+	vtkImageData* temp=vtkImageData::New();
+	temp->ShallowCopy(cast->GetOutput());
+	cast->Delete();
+
+	vtkDataArray*   inp=temp->GetPointData()->GetScalars();
+	int nt=inp->GetNumberOfTuples();
+	int nc=inp->GetNumberOfComponents();
+
+	vtkDataArray*   out=output->GetPointData()->GetScalars();
+	// Cleanup first -- fill output with zeros
+	for (int ia=0;ia<nc;ia++)
+	  out->FillComponent(ia,0);
+
+	vtkpxMath* math=vtkpxMath::New();
+	int maxcount=int(nt/10);
+	int count=0;
+	double pog=0.0;
+
+	this->UpdateProgress(0.01);
+
+	for (int t=0;t<nt;t++)
+	{
+		for (int c=0;c<nc;c++)
+		{
+			out->SetComponent(t,c,math->ZscoreToPvalue(inp->GetComponent(t,c)));
+
+		}
+		++count;
+		if (count==maxcount)
+		{
+			pog=double(t)/double(nt);
+		    this->UpdateProgress(pog);
+		    count=0;
+		    //fprintf(stderr," %.2f/100 (%.2f good) ",100.0*pog,double(numdone)/double(nt));
+		}
+	}
+	this->UpdateProgress(1.0);
+
+	math->Delete();
+	temp->Delete();
+
+
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkbisZscoretoPvalue.h b/bioimagesuite30_src/Imaging/vtkbisZscoretoPvalue.h
new file mode 100644
index 0000000..8713bbf
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkbisZscoretoPvalue.h
@@ -0,0 +1,59 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisZscoretoPvalue.h
+ *
+ *  Created on: Apr 16, 2009
+ *      Author: Isabella Murphy
+ */
+
+#ifndef VTKBISZSCORETOPVALUE_H_
+#define VTKBISZSCORETOPVALUE_H_
+
+#include "vtkSimpleImageToImageFilter.h"
+
+class vtkbisZscoretoPvalue : public vtkSimpleImageToImageFilter
+{
+public:
+	static vtkbisZscoretoPvalue *New();
+	vtkTypeMacro(vtkbisZscoretoPvalue,vtkSimpleImageToImageFilter);
+
+protected:
+	vtkbisZscoretoPvalue(){};
+	virtual ~vtkbisZscoretoPvalue(){};
+
+	virtual int RequestInformation(vtkInformation*,vtkInformationVector**,vtkInformationVector* outputVector);
+	// Execute Function -- main function
+	virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+private:
+	vtkbisZscoretoPvalue(const vtkbisZscoretoPvalue& src) {};
+	vtkbisZscoretoPvalue& operator=(const vtkbisZscoretoPvalue& rhs) {};
+};
+
+#endif /* VTKBISZSCORETOPVALUE_H_ */
+
diff --git a/bioimagesuite30_src/Imaging/vtkdsSpectUtil.cpp b/bioimagesuite30_src/Imaging/vtkdsSpectUtil.cpp
new file mode 100644
index 0000000..9749c83
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkdsSpectUtil.cpp
@@ -0,0 +1,412 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkdsSpectUtil.h"
+#include "vtkObjectFactory.h"
+#include <stdio.h>
+#include "vtkImageData.h"
+#include "vtkDataArray.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkpxMath.h"
+//#include "vtkSortDataArray.h"
+
+vtkStandardNewMacro(vtkdsSpectUtil);
+
+vtkFloatArray* vtkdsSpectUtil::ClusterImage(vtkImageData* zscoreImage,vtkImageData* clusterId,vtkImageData* clusterSize,float En,float EM)
+{	
+  
+  if (clusterId==NULL || zscoreImage==NULL || clusterSize==NULL)
+    {
+      fprintf(stderr,"BAD INPUTS IMAGES!!!!!!!\n"); 
+      return NULL;
+    }
+
+  if (clusterId->GetNumberOfPoints()   != clusterSize->GetNumberOfPoints() ||
+	  clusterId->GetNumberOfPoints()   != zscoreImage->GetNumberOfPoints() ||
+	  zscoreImage->GetNumberOfPoints() != clusterSize->GetNumberOfPoints())
+    {
+      fprintf(stderr,"BAD INPUTS IMAGES they have different size !!!!!!!\n"); 
+      return NULL;
+    }
+
+  double range[2] ;clusterId->GetPointData()->GetScalars()->GetRange(range);
+  int numbersOfCluster=int(range[1]-range[0])+1;
+
+  fprintf(stderr,"\n %i total number of cluster\n",numbersOfCluster);
+
+  vtkFloatArray* clusterInfo=vtkFloatArray::New();
+  
+  // numvoxels clusterprob maxzscore x y z 
+  clusterInfo->SetNumberOfComponents(7);//columns
+  clusterInfo->SetNumberOfTuples(numbersOfCluster);//rows
+  
+  for (int i=0;i<6;i++)
+  clusterInfo->FillComponent(i,0.0);
+
+  int clustersAboveMin = 0;
+  int dim[3]; clusterId->GetDimensions(dim);
+
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	  {	
+	    int id=(int)clusterId->GetScalarComponentAsDouble(i,j,k,0);
+	    int kSize=(int)clusterSize->GetScalarComponentAsDouble(i,j,k,0);
+	    double zscore=zscoreImage->GetScalarComponentAsDouble(i,j,k,0);
+	    
+	    if (clusterInfo->GetComponent(id-1,0) == 0 && fabs(zscore)>0)
+	      {
+		float clusterPvalue = exp(-pow((1.3378/En*kSize/(17.2/2*16.6/2*18.3/2)),(2.0/3.0)));//1.3293
+		float correctPvalue = 1 - exp(-EM*clusterPvalue);
+		clusterInfo->SetComponent(id-1,0,kSize);
+		clusterInfo->SetComponent(id-1,1,clusterPvalue);
+		clusterInfo->SetComponent(id-1,2,correctPvalue);
+		clustersAboveMin++;
+		//		fprintf(stderr,"\n %i %f %f\n",kSize,clusterPvalue,correctPvalue);
+	      }
+	    if (fabs(zscore)>fabs(clusterInfo->GetComponent(id-1,3)))
+	      {
+		clusterInfo->SetComponent(id-1,3,(float)zscore);
+		clusterInfo->SetComponent(id-1,4,i);
+		clusterInfo->SetComponent(id-1,5,j);
+		clusterInfo->SetComponent(id-1,6,k);
+	      }
+	  }
+  
+  fprintf(stderr,"\n %i clusters above minimum threshold\n",clustersAboveMin);
+  /*
+    vtkSortDataArray sort=vtkSortDataArray::New();
+    sort->ArrayByComponent(clusterInfo,0);
+    sort->Delete():
+  */
+  vtkFloatArray* output=vtkFloatArray::New();
+  output->SetNumberOfComponents(7);
+  output->SetNumberOfTuples(clustersAboveMin);
+  int tupleCount = 0;
+  
+  for (int index=0;index<numbersOfCluster;index++) 
+    {
+      if (clusterInfo->GetComponent(index,0) != 0)
+	{
+	  //fprintf(stderr,"\n");
+	  for (int index2=0;index2<7;index2++) 
+	    {
+	      output->SetComponent(tupleCount,index2,clusterInfo->GetComponent(index,index2));
+	      //fprintf(stderr,"%f\n",output->GetComponent(tupleCount,index2));
+	    }
+	  //fprintf(stderr,"\n");
+	  tupleCount++;
+	}
+    }
+  clusterInfo->Delete();
+  return output;
+}
+
+
+vtkFloatArray* vtkdsSpectUtil::ClusterImage(vtkImageData* tscoreimage,vtkImageData* clusterId,vtkImageData* clusterSize,float En,float EM,float tscore,int ext)
+{	
+
+  if (clusterId==NULL || tscoreimage==NULL || clusterSize==NULL)
+    {
+      fprintf(stderr,"BAD INPUTS IMAGES!!!!!!!\n"); 
+      return NULL;
+    }
+  
+  if (clusterId->GetNumberOfPoints()   != clusterSize->GetNumberOfPoints() ||
+	  clusterId->GetNumberOfPoints()   != tscoreimage->GetNumberOfPoints() ||
+	  tscoreimage->GetNumberOfPoints() != clusterSize->GetNumberOfPoints())
+    {
+      fprintf(stderr,"BAD INPUTS IMAGES they have different size !!!!!!!\n"); 
+      return NULL;
+    }
+
+  double range[2] ;clusterId->GetPointData()->GetScalars()->GetRange(range);
+  int numbersOfCluster=int(range[1]-range[0])+1;
+
+  fprintf(stderr,"\n %i total number of cluster\n",numbersOfCluster);
+
+  vtkFloatArray* clusterInfo=vtkFloatArray::New();
+  
+  // numvoxels clusterprob maxzscore x y z 
+  clusterInfo->SetNumberOfComponents(7);//columns
+  clusterInfo->SetNumberOfTuples(numbersOfCluster);//rows
+  
+  for (int i=0;i<6;i++)
+  clusterInfo->FillComponent(i,0.0);
+
+  int clustersAboveMin = 0;
+  int dim[3]; clusterId->GetDimensions(dim);
+
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	  {	
+	    int id=(int)clusterId->GetScalarComponentAsDouble(i,j,k,0);
+	    int kSize=(int)clusterSize->GetScalarComponentAsDouble(i,j,k,0);
+	    double tval=tscoreimage->GetScalarComponentAsDouble(i,j,k,0);
+	    if (tval>=tscore && kSize>=ext && id>0)
+	      {
+		if (clusterInfo->GetComponent(id-1,0) == 0)
+		  {
+		    float clusterPvalue = exp(-pow((1.3378/En*kSize/(17.2/2*16.6/2*18.3/2)),(2.0/3.0)));//1.3293
+		    float correctPvalue = 1 - exp(-EM*clusterPvalue);
+		    clusterInfo->SetComponent(id-1,0,kSize);
+		    clusterInfo->SetComponent(id-1,1,clusterPvalue);
+		    clusterInfo->SetComponent(id-1,2,correctPvalue);
+		    clustersAboveMin++;
+		    fprintf(stderr,"\n %d %f %f\n",kSize,clusterPvalue,correctPvalue);
+		  }
+		if (tval>clusterInfo->GetComponent(id-1,3))
+		  {
+		    clusterInfo->SetComponent(id-1,3,tval);
+		    clusterInfo->SetComponent(id-1,4,i);
+		    clusterInfo->SetComponent(id-1,5,j);
+		    clusterInfo->SetComponent(id-1,6,k);
+		  }
+	      }
+	  }
+  
+  fprintf(stderr,"\n %i clusters above minimum threshold\n",clustersAboveMin);
+  /*
+  vtkSortDataArray sort=vtkSortDataArray::New();
+  sort->ArrayByComponent(clusterInfo,0);
+  sort->Delete():
+  */
+  vtkFloatArray* output=vtkFloatArray::New();
+  output->SetNumberOfComponents(7);
+  output->SetNumberOfTuples(clustersAboveMin);
+  int tupleCount = 0;
+  
+  for (int index=0;index<numbersOfCluster;index++) 
+    {
+      if (clusterInfo->GetComponent(index,0) != 0)
+	{
+	  //fprintf(stderr,"\n");
+	  for (int index2=0;index2<7;index2++) 
+	    {
+	      output->SetComponent(tupleCount,index2,clusterInfo->GetComponent(index,index2));
+	      //fprintf(stderr,"%f\n",output->GetComponent(tupleCount,index2));
+	    }
+	  //fprintf(stderr,"\n");
+	  tupleCount++;
+	}
+    }
+  clusterInfo->Delete();
+  return output;
+}
+
+float vtkdsSpectUtil::imageMean(vtkImageData* image,float min)
+{
+  vtkDataArray* in=image->GetPointData()->GetScalars();
+  
+  int numscalars=in->GetNumberOfTuples();
+  
+  float sum=0.0;
+  float count=0;
+  for (int pixel=0;pixel<numscalars;pixel++)
+    {
+      float v1=in->GetComponent(pixel,0);
+      if (v1>min)
+	{	
+	  sum+=v1;
+	  count++;
+	}	
+    }
+  sum/=count;
+  return sum;
+}
+
+void vtkdsSpectUtil::HAI(vtkImageData* image)
+{
+  if (image==NULL)
+    {
+      fprintf(stderr,"BAD INPUTS IMAGES!!!!!!!\n"); 
+      return;
+    }
+  
+  int volume(0);int leftHemi(0);
+  int dim[3]; image->GetDimensions(dim);
+  
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  if (fabs(image->GetScalarComponentAsDouble(i,j,k,0))>0 && i!=45)
+	    {
+	      volume++; 
+	      if (i>45)
+		leftHemi++;
+	    }
+	}
+  float HAI=2.0*leftHemi/volume-1.0;
+  fprintf(stderr,"leftHemi=%d,righthemi=%d",leftHemi,volume-leftHemi);
+  fprintf(stderr,"\nHAI = %f\n", HAI); 
+}
+
+vtkFloatArray* vtkdsSpectUtil::reselCount(vtkImageData* image)
+{
+  if (image==NULL)
+    {
+      fprintf(stderr,"BAD INPUTS IMAGES!!!!!!!\n"); 
+      return NULL;
+    }
+  
+  int volume(0);int cubes(0);int xyFaces(0);int yzFaces(0);int xzFaces(0);int xEdges(0);int yEdges(0);int zEdges(0);
+  int dim[3]; image->GetDimensions(dim);
+  
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  
+	  if (fabs(image->GetScalarComponentAsDouble(i,j,k,0))>0)
+	    {
+	      volume++; 
+	      if (fabs(image->GetScalarComponentAsDouble(i+1,j,k,0))>0)
+		{
+		  xEdges++;
+		  if (fabs(image->GetScalarComponentAsDouble(i,j+1,k,0))>0 && fabs(image->GetScalarComponentAsDouble(i+1,j+1,k,0))>0)
+		    {
+		      xyFaces++;
+		      if (fabs(image->GetScalarComponentAsDouble(i,j,k+1,0))>0   && fabs(image->GetScalarComponentAsDouble(i+1,j,k+1,0))>0 &&
+			  fabs(image->GetScalarComponentAsDouble(i,j+1,k+1,0))>0 && fabs(image->GetScalarComponentAsDouble(i+1,j+1,k+1,0))>0)
+			{ 
+			  cubes++;
+			}
+		    }
+		}
+	      if (fabs(image->GetScalarComponentAsDouble(i,j+1,k,0))>0)
+		{
+		  yEdges++;
+		  if (fabs(image->GetScalarComponentAsDouble(i,j,k+1,0))>0 && fabs(image->GetScalarComponentAsDouble(i,j+1,k+1,0))>0)
+		    {
+		      yzFaces++;
+		    }
+		}
+	      if (fabs(image->GetScalarComponentAsDouble(i,j,k+1,0))>0)
+		{
+		  zEdges++;
+		  if (fabs(image->GetScalarComponentAsDouble(i+1,j,k,0))>0 && fabs(image->GetScalarComponentAsDouble(i+1,j,k+1,0))>0)
+		    {
+		      xzFaces++;
+		    }
+		}
+	    }
+	} 
+  vtkFloatArray* output=vtkFloatArray::New();
+  output->SetNumberOfComponents(8);
+  output->SetNumberOfTuples(1);
+  output->SetComponent(0,0,volume);
+  output->SetComponent(0,1,cubes);
+  output->SetComponent(0,2,xyFaces);
+  output->SetComponent(0,3,yzFaces);
+  output->SetComponent(0,4,xzFaces);
+  output->SetComponent(0,5,xEdges);
+  output->SetComponent(0,6,yEdges);
+  output->SetComponent(0,7,zEdges);
+  //for (int i=0;i<8;i++)
+  //fprintf(stderr,"%f",output->GetComponent(0,i));
+  return output;
+}
+
+double vtkdsSpectUtil::reselCount(vtkImageData* image, float eulerDensity1, float eulerDensity2, float eulerDensity3, float eulerDensity4)
+{
+  float eulerDensity[4];
+  eulerDensity[0]=eulerDensity1;
+  eulerDensity[1]=eulerDensity2;
+  eulerDensity[2]=eulerDensity3;
+  eulerDensity[3]=eulerDensity4;
+  return reselCount(image,eulerDensity);
+}
+
+double vtkdsSpectUtil::reselCount(vtkImageData* image, float eulerDensity[4] )
+{
+  if (image==NULL)
+    {
+      fprintf(stderr,"BAD INPUTS IMAGES!!!!!!!\n"); 
+      return 0.0;
+    }
+  
+  float volume(0);float cubes(0);float xyFaces(0);float yzFaces(0);float xzFaces(0);float xEdges(0);float yEdges(0);float zEdges(0);
+  int dim[3]; image->GetDimensions(dim);
+  
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  if (fabs(image->GetScalarComponentAsDouble(i,j,k,0))>0)
+	    {
+	      volume++; 
+	      if (fabs(image->GetScalarComponentAsDouble(i+1,j,k,0))>0)
+		{
+		  xEdges++;
+		  if (fabs(image->GetScalarComponentAsDouble(i,j+1,k,0))>0 && fabs(image->GetScalarComponentAsDouble(i+1,j+1,k,0))>0)
+		    {
+		      xyFaces++;
+		      if (fabs(image->GetScalarComponentAsDouble(i,j,k+1,0))>0   && fabs(image->GetScalarComponentAsDouble(i+1,j,k+1,0))>0 &&
+			  fabs(image->GetScalarComponentAsDouble(i,j+1,k+1,0))>0 && fabs(image->GetScalarComponentAsDouble(i+1,j+1,k+1,0))>0)
+			{ 
+			  cubes++;
+			}
+		    }
+		}
+	      if (fabs(image->GetScalarComponentAsDouble(i,j+1,k,0))>0)
+		{
+		  yEdges++;
+		  if (fabs(image->GetScalarComponentAsDouble(i,j,k+1,0))>0 && fabs(image->GetScalarComponentAsDouble(i,j+1,k+1,0))>0)
+		    {
+		      yzFaces++;
+		    }
+		}
+	      if (fabs(image->GetScalarComponentAsDouble(i,j,k+1,0))>0)
+		{
+		  zEdges++;
+		  if (fabs(image->GetScalarComponentAsDouble(i+1,j,k,0))>0 && fabs(image->GetScalarComponentAsDouble(i+1,j,k+1,0))>0)
+		    {
+		      xzFaces++;
+		    }
+		}
+	    }
+	} 
+
+  float xDim=0.11627907; float yDim=0.120481928; float zDim=0.109289617;
+
+  float reselCount[4];
+  reselCount[0]=(volume-xEdges-yEdges-zEdges+xyFaces+xzFaces+yzFaces-cubes);
+  reselCount[1]=(xEdges-xyFaces-xzFaces+cubes)*xDim+(yEdges-xyFaces-yzFaces+cubes)*yDim+(zEdges-yzFaces-xzFaces+cubes)*zDim;
+  reselCount[2]=(xyFaces-cubes)*xDim*yDim+(xzFaces-cubes)*xDim*zDim+(yzFaces-cubes)*zDim*yDim;
+  reselCount[3]=cubes*xDim*yDim*zDim;
+  
+  float expectedNumOfCluster=0.0;
+  for (int kk=0;kk<4;kk++)  
+    expectedNumOfCluster+=eulerDensity[kk]*reselCount[kk];
+
+  return expectedNumOfCluster;
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkdsSpectUtil.h b/bioimagesuite30_src/Imaging/vtkdsSpectUtil.h
new file mode 100644
index 0000000..891e859
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkdsSpectUtil.h
@@ -0,0 +1,58 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef __vtkdsSpectUtil_h
+#define __vtkdsSpectUtil_h
+
+#include <vtkObject.h>
+
+class vtkImageData;
+class vtkFloatArray;
+
+class vtkdsSpectUtil : public vtkObject
+{
+
+ public:
+  static vtkdsSpectUtil *New();
+  vtkTypeMacro(vtkdsSpectUtil,vtkObject);
+
+  static vtkFloatArray* reselCount(vtkImageData* image);
+  static double reselCount(vtkImageData* image, float eulerDensity1, float eulerDensity2, float eulerDensity3, float eulerDensity4);
+  static double reselCount(vtkImageData* image, float eulerDensity[4]);
+  static vtkFloatArray* ClusterImage(vtkImageData* zscore,vtkImageData* clusterId,vtkImageData* clusterSize,float En,float EM);
+  static vtkFloatArray* ClusterImage(vtkImageData* zscore,vtkImageData* clusterId,vtkImageData* clusterSize,float En,float EM,float tscore,int ext);
+  static float imageMean(vtkImageData* image,float min);
+  static void HAI(vtkImageData* image);
+    
+ protected:
+  vtkdsSpectUtil() {};
+  virtual ~vtkdsSpectUtil() {};
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtknrImageCluster.cpp b/bioimagesuite30_src/Imaging/vtknrImageCluster.cpp
new file mode 100644
index 0000000..c14cff4
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtknrImageCluster.cpp
@@ -0,0 +1,537 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtknrImageCluster.h,v $
+  Language:  C++
+  Date:      $Date: 2005/08/10 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 2005 Nallakkandi Rajeevan, Ph.D.  n.rajeevan at yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+// vtknrImageCluster is a class to extract all the clusters in an image and
+// threshold clusters based on its size.  This class also provides cluster
+// probability distribution function that can be used in the calculation of
+// false positive probability in fMRI and PET image analysis.
+//                                             -- Rajeevan  August 15, 2005
+//
+
+/******************************************************************************/
+
+#include "vtknrImageCluster.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageMask.h"
+#include "vtkImageThreshold.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+#include "vtkImageDataGeometryFilter.h"
+#include "vtkThresholdPoints.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkImageAccumulate.h"
+#include "vtkIntArray.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkpxUtil.h"
+#include <vector>
+#include <stack>
+using namespace std;
+
+/******************************************************************************/
+
+vtknrImageCluster* vtknrImageCluster::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtknrImageCluster");
+  if(ret)
+    {
+    return (vtknrImageCluster*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtknrImageCluster;
+}
+
+/******************************************************************************/
+
+vtknrImageCluster::vtknrImageCluster()
+{
+   this->MaxClusterSize       = 0;
+   this->IntensityThreshold   = 0.0;
+   this->ClusterNumberImage   = NULL;
+   this->Clusters=NULL;
+   this->ClusterHistogram=NULL;
+   this->OneConnected=1;
+   //  fprintf(stderr,"in vtknrImage Cluster :: Constructor\n");
+
+}
+
+/******************************************************************************/
+
+vtknrImageCluster::~vtknrImageCluster()
+{
+
+  this->SetClusters(NULL);
+  this->SetClusterHistogram(NULL);
+
+  if (this->ClusterNumberImage!=NULL)
+     this->ClusterNumberImage->Delete();
+}
+
+/******************************************************************************/
+int vtknrImageCluster::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+					  vtkInformationVector *outputVector)
+{
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, 1);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_INT, -1);
+  return 1;
+}
+
+/******************************************************************************/
+vtkImageData* vtknrImageCluster::ColorInClusterCentroids(vtkImageData* clustermap)
+{
+  if (clustermap==NULL)
+    {
+      fprintf(stderr,"Bad Input Clustermap\n");
+      return NULL;
+    }
+
+  vtkDataArray* inp=clustermap->GetPointData()->GetScalars();
+  double range[2]; inp->GetRange(range);
+  if (range[0]!=0 || range[1]>100000)
+    {
+      fprintf(stderr,"Bad Range of input clustermap %f:%f\n",range[0],range[1]);
+      return NULL;
+    }
+
+  vtkImageData* output=vtkImageData::New();
+  output->CopyStructure(clustermap);
+  output->SetScalarTypeToShort();
+  output->AllocateScalars();
+  output->GetPointData()->GetScalars()->FillComponent(0,0.0);
+
+  double spa[3]; clustermap->GetSpacing(spa);
+  double ori[3]; clustermap->GetOrigin(ori);
+ 
+  vtkImageDataGeometryFilter* filt=vtkImageDataGeometryFilter::New();
+  filt->SetInput(clustermap);
+  filt->Update();
+
+  vtkDataSet* dataset=(vtkDataSet*)filt->GetOutput();
+
+  int maxrange=(int)range[1];
+
+  for (int index=1;index<maxrange;index++)
+    {
+      float minv=float(index)-0.5;
+      float maxv=minv+1.0;
+
+      vtkThresholdPoints* thrPoints=vtkThresholdPoints::New();
+      thrPoints->SetInput(filt->GetOutput());
+      thrPoints->ThresholdBetween(minv,maxv);
+      thrPoints->Update();
+      vtkPoints* pts=thrPoints->GetOutput()->GetPoints();
+
+      int np=pts->GetNumberOfPoints();
+      if (np>0)
+	{
+	  double sum[3]={0.0,0.0,0.0};
+	  for (int ia=0;ia<np;ia++)
+	    {
+	      double x[3]; pts->GetPoint(ia,x);
+	      for (int ib=0;ib<=2;ib++)
+		sum[ib]+=x[ib];
+	    }
+	  
+	  int vox[3];
+	  for (int ib=0;ib<=2;ib++)
+	    vox[ib]= int( (sum[ib]/double(np)-ori[ib])/spa[ib]);
+
+	  //	  fprintf(stderr,"Setting index=%d np=%d      (%d,%d,%d) to %f\n",index,np,
+	  //		  vox[0],vox[1],vox[2],double(index));
+	  output->SetScalarComponentFromDouble(vox[0],vox[1],vox[2],0,double(index));
+		  
+	}
+      thrPoints->Delete();
+    }
+  filt->Delete();
+  return output;
+
+}
+
+// ------------------------------------------------------------------------------------------
+int vtknrImageCluster::RenumberClusterImage(vtkImageData* img,int sizethreshold)
+{
+  if (img==NULL)
+    return 0;
+
+
+  vtkDataArray* arr=img->GetPointData()->GetScalars();
+  double r[2];   
+  arr->GetRange(r,0);
+
+  int maxn=int(r[1]);
+
+  //  fprintf(stderr,"Renumbering Cluster Image maxn=%d\n",maxn);
+
+
+  vtkImageAccumulate* accumulate=vtkImageAccumulate::New();
+  accumulate->SetInput(img);
+  accumulate->SetComponentExtent(0,maxn+1,0,0,0,0);
+  accumulate->SetComponentOrigin(0,0,0);
+  accumulate->SetComponentSpacing(1,1,1);
+  accumulate->Update();
+
+  vtkDataArray* data=accumulate->GetOutput()->GetPointData()->GetScalars();
+  vtkIntArray*  cum=vtkIntArray::New();
+  cum->SetNumberOfComponents(1);
+  cum->SetNumberOfTuples(data->GetNumberOfTuples());
+  cum->FillComponent(0,0.0);
+  
+  int numclusters=0;
+  for (int i=1;i<data->GetNumberOfTuples();i++)
+    {
+      double v=data->GetComponent(i,0);
+      //      fprintf(stderr,"Data i=%d v=%f\n",i,v);
+      if (v>sizethreshold)
+	{
+	  ++numclusters;
+	  cum->SetComponent(i,0,numclusters);
+	  //	  fprintf(stderr,"Mapping %d to %d\n",i,numclusters);
+	}
+    }
+
+
+
+
+
+  if (numclusters>0)
+    {
+      int nt=arr->GetNumberOfTuples();
+      for (int i=0;i<nt;i++)
+	{
+	  double v=arr->GetComponent(i,0);
+	  if (v>0)
+	    {
+	      int index=int(v);
+	      double val=cum->GetComponent(0,index);
+	      arr->SetComponent(i,0,val);
+	    }
+	}
+    }
+
+  cum->Delete();
+  accumulate->Delete();
+
+  return numclusters;
+}
+// -----------------------------------------------------------------------------------------
+
+int vtknrImageCluster::ComputeClusters(vtkImageData* input,vtkImageData* output)
+{
+  this->Clusters->SetNumberOfTuples(0);
+  this->Clusters->FillComponent(0,0.0);
+  // Get increments to march through data 
+
+
+   int dim[3];
+   input->GetDimensions(dim);
+   //fprintf(stderr,"Dimensions = %d,%d,%d\n",dim[0],dim[1],dim[2]);
+
+   double sp[3];
+   input->GetSpacing(sp);
+
+   int shift[27][3];
+   int maxshift=0;
+
+   int index=0;
+   int maxc=2;
+   if (dim[2]==1)
+     maxc=0;
+
+   if (this->OneConnected==0)
+     {
+       for (int ic=0;ic<=maxc;ic++)
+	 {
+	   int k=ic;
+	   if (k>1)
+	     k=-1;
+	   for (int ia=-1;ia<=1;ia++)
+	     for (int ib=-1;ib<=1;ib++)
+	       {
+		 shift[index][0]=ia;
+		 shift[index][1]=ib;
+		 shift[index][2]=k;
+		 ++index;
+	       }
+	 }
+       maxshift=27;
+     }
+   else
+     {
+       for (int i=0;i<=6;i++)
+	 for (int j=0;j<=2;j++)
+	   shift[i][j]=0;
+       
+       shift[1][0]=-1;        shift[2][0]=1;
+       shift[3][1]=-1;        shift[4][1]=1;
+       shift[5][2]=-1;        shift[6][2]=1;
+       maxshift=7;
+     }
+
+   
+   int LimitSize  = dim[0]*dim[1]*dim[2];
+   fprintf(stdout,"MaxShift=%d, OneConnected=%d LimitSize=%d, %d\n",maxshift,OneConnected,LimitSize);
+
+   int tmp=0;
+   this->Clusters->InsertNextTuple1(0);
+   
+   // Loop through ouput pixels
+   int CP[4];
+   int ClusterNumber=1;
+   double VoxelVisited=-1.0;
+   
+   output->GetPointData()->GetScalars()->FillComponent(0,0.0);
+   
+
+  
+   double voxelValue=0.0;
+   vtkDataArray* inparray=input->GetPointData()->GetScalars();
+   vtkDataArray* outarray=output->GetPointData()->GetScalars();
+   int slicesize=dim[1]*dim[0];
+   
+   int voxelindex=-1;
+
+   for (int idxZ = 0; idxZ < dim[2]; idxZ++)
+     for (int idxY = 0; idxY < dim[1]; idxY++)
+       for (int idxX = 0; idxX < dim[0]; idxX++)
+	 {
+	   ++voxelindex;
+	   int nClusterVoxels=0;
+	   
+	   // Only Use First Component
+	   double value = inparray->GetComponent(voxelindex,0);
+	   double otval = outarray->GetComponent(voxelindex,0);
+	   double voxelsign=1.0;
+	   if (value<0.0)
+	     voxelsign=-1.0;
+	   value=fabs(value);
+	   
+	   if(value >= this->IntensityThreshold && otval == 0.0 )
+	     {
+	       std::stack<std::vector<int> > voxelStack;
+	       //	       fprintf(stderr,"Beginning to Cluster (%d,%d,%d)\n",idxX,idxY,idxZ);
+	       outarray->SetComponent(voxelindex,0,double(ClusterNumber));
+	       std::vector<int> voxel;
+	       voxel.push_back(0);
+	       voxel.push_back(idxX);
+	       voxel.push_back(idxY);
+	       voxel.push_back(idxZ);
+	       voxelStack.push(voxel);
+
+	       //	       fprintf(stderr,"\t\t\t Adding %d %d %d to stack\n",idxX,idxY,idxZ);
+	       //output->SetScalarComponentFromDouble(idxX,idxY,idxZ,0, double(ClusterNumber));
+	       if(nClusterVoxels < LimitSize - 1 )
+		 nClusterVoxels++;
+	       
+	       // ----------------------------------------------------------------------------------------
+	       while(!voxelStack.empty())
+		 {
+		   //		   fprintf(stderr,"\t\t Beginning Recursion\n");
+		   CP[0] = voxelStack.top()[0];
+		   CP[1] = voxelStack.top()[1];
+		   CP[2] = voxelStack.top()[2];
+		   CP[3] = voxelStack.top()[3];
+		   voxelStack.pop();
+
+		   for (int nb=1;nb<maxshift;nb++)
+		     {
+		       int i1=CP[1]+shift[nb][0];
+		       int i2=CP[2]+shift[nb][1];
+		       int i3=CP[3]+shift[nb][2];
+		 
+		       int inindex=i3*slicesize+i2*dim[0]+i1;
+      
+		       if (i1>=0 && i1<dim[0] && i2>=0 && i2<dim[1] && i3>=0 && i3<dim[2])
+			 {
+			   double ot=outarray->GetComponent(inindex,0);
+			   if ( fabs(ot) < 0.00001) 
+			     {
+			       double it=voxelsign*inparray->GetComponent(inindex,0);
+			       if (it >= this->IntensityThreshold)
+				 {
+				   outarray->SetComponent(inindex,0,double (ClusterNumber));
+				   std::vector<int> voxel;                       
+				   voxel.push_back(0);
+				   voxel.push_back(i1);
+				   voxel.push_back(i2);
+				   voxel.push_back(i3);
+				   voxelStack.push(voxel);
+				   
+				   if(nClusterVoxels < LimitSize - 1)
+				     nClusterVoxels++;
+				 }
+			       else
+				 {
+				   outarray->SetComponent(inindex,0,(VoxelVisited));
+				 }
+			     }
+			 }
+		     } // End of Inner Loop
+		 }
+	       if(nClusterVoxels > 0)
+		 {
+		   this->Clusters->InsertNextTuple1(nClusterVoxels);
+		   ClusterNumber++;
+		 }
+	     }
+	   else if (otval==0.0)
+	     output->SetScalarComponentFromDouble(idxX,idxY,idxZ,0,(VoxelVisited));
+	 }
+   fprintf(stdout,"Max Clusters=%d\n",ClusterNumber);
+   
+   //vtkDataArray* out=output->GetPointData()->GetScalars();
+   return 1;
+}
+
+
+/******************************************************************************/
+int vtknrImageCluster::IntegrateHistogram()
+{
+  double range[2]; this->Clusters->GetRange(range);
+
+  int nt=this->ClusterHistogram->GetNumberOfTuples();
+  int nnt=int(range[1])+1;
+  if (nt < nnt)
+    this->ClusterHistogram->SetNumberOfTuples(nnt);
+  this->ClusterHistogram->FillComponent(0,0.0);
+
+  int nclust=this->Clusters->GetNumberOfTuples();
+  for (int i=0;i<nclust;i++)
+    {
+      int v=(int)(this->Clusters->GetComponent(i,0));
+      //      if (i<10)
+      //      fprintf(stderr,"Cluster = %d vol=%d\n",i,v);
+      this->ClusterHistogram->SetComponent(v,0,this->ClusterHistogram->GetComponent(v,0)+1);
+    }
+
+  return nnt;
+}
+
+int vtknrImageCluster::ComputeOutputImage(vtkImageData* input,vtkImageData* output)
+{
+  vtkDataArray* inp=input->GetPointData()->GetScalars(); 
+  vtkDataArray* out=output->GetPointData()->GetScalars(); 
+
+  int nt=inp->GetNumberOfTuples();
+  int nv=out->GetNumberOfTuples();
+
+  //  fprintf(stderr,"nt=%d, nv=%d\n",nt,nv);
+
+  out->FillComponent(0,0.0);
+  for (int vox=0;vox<nt;vox++)
+    {
+      int val=(int)inp->GetComponent(vox,0);
+      if (val>=1)
+	{
+	  double vol=(this->Clusters->GetComponent(val,0));
+	  out->SetComponent(vox,0,vol);
+	}
+    }
+  return 1;
+}
+/******************************************************************************/
+void vtknrImageCluster::SimpleExecute(vtkImageData *inData, vtkImageData *outData)
+{
+  //  fprintf(stderr,"This Far\n\n\n\n\n");
+  if (inData==NULL)
+    {
+      fprintf(stderr,"No Input Specified\n");
+      return;
+    }
+
+  //  fprintf(stderr,"This Far\n");
+
+  if (this->Clusters==NULL)
+    {
+      vtkIntArray* cl=vtkIntArray::New();
+      cl->SetNumberOfComponents(1);
+      cl->Allocate(100,100);
+      this->SetClusters(cl);
+      cl->Delete();
+    }
+
+  if (this->ClusterHistogram==NULL)
+    {
+      vtkIntArray* cl=vtkIntArray::New();
+      cl->SetNumberOfComponents(1);
+      cl->Allocate(100,100);
+      this->SetClusterHistogram(cl);
+      cl->Delete();
+    }
+
+  if (this->ClusterNumberImage!=NULL)
+    this->ClusterNumberImage->Delete();
+
+  this->ClusterNumberImage=vtkImageData::New();
+  this->ClusterNumberImage->CopyStructure(outData);
+  this->ClusterNumberImage->AllocateScalars();
+  
+  //  fprintf(stderr,"\n\nClusterRadius=%.2f\n\n\n",this->ClusterRadius);
+  this->ComputeClusters(inData,this->ClusterNumberImage);
+
+  //  vtkpxUtil::SaveAnalyze("00cnumber.hdr",this->ClusterNumberImage,9);
+
+  this->IntegrateHistogram();
+  this->ComputeOutputImage(this->ClusterNumberImage,outData);
+
+
+
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtknrImageCluster.h b/bioimagesuite30_src/Imaging/vtknrImageCluster.h
new file mode 100644
index 0000000..279e739
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtknrImageCluster.h
@@ -0,0 +1,136 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtknrcontrib library file
+  Module:    $RCSfile: vtknrImageCluster.h,v $
+  Language:  C++
+  Date:      $Date: 2003/07/25 10:59:12 $
+  Version:   $Revision: 1.0 $
+
+
+Copyright (c) 2003 Nallakkandi Rajeevan, Ph.D. n.rajeevan at yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#ifndef __vtknrImageCluster_h
+#define __vtknrImageCluster_h
+
+#include "vtkIntArray.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+
+class  vtknrImageCluster : public vtkpxSimpleImageToImageFilter
+{
+public:
+
+  static vtknrImageCluster *New();
+  vtkTypeMacro(vtknrImageCluster, vtkpxSimpleImageToImageFilter);
+
+
+  // Description:
+  // This is the intensity Threshold
+  vtkGetMacro(IntensityThreshold, float);
+  vtkSetMacro(IntensityThreshold, float);
+  
+  // This is the connectivity of the cluster
+  vtkGetMacro(OneConnected, int);
+  vtkSetClampMacro(OneConnected, int,0,1);
+
+  // This is the connectivity of the cluster
+  vtkGetMacro(CubeConnected, int);
+  vtkSetClampMacro(CubeConnected, int,0,1);
+    
+  // This is the Maximum Cluster Size
+  vtkGetMacro(MaxClusterSize, int);
+  vtkSetMacro(MaxClusterSize, int);
+
+  // This is the Double Array for storing clusters
+  vtkSetObjectMacro(Clusters,vtkIntArray);
+  vtkGetObjectMacro(Clusters,vtkIntArray);
+
+  // This is the Double Array for storing clusters
+  vtkSetObjectMacro(ClusterHistogram,vtkIntArray);
+  vtkGetObjectMacro(ClusterHistogram,vtkIntArray);
+
+  // This is the Cluster Number Image
+  vtkGetObjectMacro(ClusterNumberImage, vtkImageData);
+
+  // Description:
+  // Get Cluster Centroids -- image has values 0..N where N=number of clusters
+  static vtkImageData* ColorInClusterCentroids(vtkImageData* clustermap);
+
+  // Description:
+  // Added by XP May 5th 2008
+  // Goal of this function is to have surviving clusters numbered 1..N
+  static int RenumberClusterImage(vtkImageData* img,int sizethreshold);
+  
+
+
+protected:
+
+   vtknrImageCluster();
+   virtual ~vtknrImageCluster();
+   vtknrImageCluster(const vtknrImageCluster&) {};
+   void operator=(const vtknrImageCluster&) {};
+
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+  virtual void SimpleExecute(vtkImageData *inData, vtkImageData *outData);
+
+
+  int    OneConnected;
+  int    CubeConnected;
+  int    MaxClusterSize;
+  float  IntensityThreshold;
+
+
+  vtkIntArray*  Clusters;
+  vtkIntArray*  ClusterHistogram;
+  vtkImageData* ClusterNumberImage;
+
+  // Description:
+  // Method to Integrate Clusters
+  virtual int IntegrateHistogram();
+  virtual int ComputeClusters(vtkImageData* input,vtkImageData* output);
+  virtual int ComputeOutputImage(vtkImageData* clusternumber,vtkImageData* output);
+};
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxAddMotionToTimeSeries.cpp b/bioimagesuite30_src/Imaging/vtkpxAddMotionToTimeSeries.cpp
new file mode 100644
index 0000000..8364a82
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxAddMotionToTimeSeries.cpp
@@ -0,0 +1,653 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAddMotionToTimeSeries.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/26 17:28:22 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "math.h"
+#include "vtkAbstractTransform.h"
+#include "vtkFloatArray.h"
+#include "vtkGeneralTransform.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkbisImageReslice.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkTransform.h"
+#include "vtkpxAddMotionToTimeSeries.h"
+#include "vtkpxUtil.h"
+
+//------------------------------------------------------------------------------
+vtkpxAddMotionToTimeSeries* vtkpxAddMotionToTimeSeries::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxAddMotionToTimeSeries");
+  if(ret)
+    {
+    return (vtkpxAddMotionToTimeSeries*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxAddMotionToTimeSeries;
+}
+
+// ----------------------------------------------------------------------------
+vtkpxAddMotionToTimeSeries::vtkpxAddMotionToTimeSeries()
+{
+  this->TransformationParameters=NULL;
+  this->ReferenceImage=NULL;
+  this->BlockPeriod=4;
+  this->UseMotionParameters=1;
+  this->ObliqueTransform=NULL;
+  this->SliceThickness=-1.0;
+}
+// ----------------------------------------------------------------------------
+vtkpxAddMotionToTimeSeries::~vtkpxAddMotionToTimeSeries()
+{
+  if (this->TransformationParameters!=NULL)
+    {
+      this->TransformationParameters->UnRegister(this);
+      this->TransformationParameters=NULL;
+    }
+
+  if (this->ReferenceImage!=NULL)
+    {
+      this->ReferenceImage->UnRegister(this);
+      this->ReferenceImage=NULL;
+    }
+
+  if (this->ObliqueTransform!=NULL)
+    {
+      this->ObliqueTransform->UnRegister(this);
+      this->ObliqueTransform=NULL;
+    }
+
+
+}
+// --------------------------------------------------------------------------------------
+void vtkpxAddMotionToTimeSeries::ExecuteInformation()
+{
+  vtkImageData *input=this->GetImageDataInput(0);
+  vtkDataArray* scal=this->GetTransformationParameters();
+  
+
+  if (input==NULL || scal==NULL)
+      {
+	vtkErrorMacro(<<"No Input FMRI Data or no Input Motion Parameters!!");
+	return;
+      }
+
+  vtkImageData *output=this->GetOutput();
+
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  output->SetNumberOfScalarComponents(scal->GetNumberOfTuples());
+
+}
+
+// --------------------------------------------------------------------------------------
+// Helper Routines for Execute
+// --------------------------------------------------------------------------------------
+void vtkpxAddMotionToTimeSeries::ResampleAndSmoothImage(vtkImageData* image,
+							vtkImageData* ref,
+							float SliceThickness,
+							vtkAbstractTransform* xform1,
+							vtkAbstractTransform* xform2)
+
+{
+  double sp1[3],sp2[3];
+  image->GetSpacing(sp1);
+  ref->GetSpacing(sp2);
+
+  // Use SliceThickness if Set!
+  if (SliceThickness>0.0)
+    sp2[2]=SliceThickness;
+
+  vtkGeneralTransform* generalxform=vtkGeneralTransform::New();
+  generalxform->Identity();
+  generalxform->PostMultiply();
+  if (xform2!=NULL)
+    generalxform->Concatenate(xform2);
+
+  if (xform1!=NULL)
+    generalxform->Concatenate(xform1);
+
+
+  /*float spr[3],orr[3]; int dimr[3];
+  ref->GetSpacing(spr);
+  ref->GetOrigin(orr);
+  ref->GetDimensions(dimr);
+
+  float p[3],q[3],q1[3],q2[3];
+  for (int ib=0;ib<=2;ib++)
+    p[ib]=orr[ib]+0.5*spr[ib]*dimr[ib];
+
+  
+  float bounds[6]; image->GetBounds(bounds);
+  float boundsr[6]; ref->GetBounds(boundsr);
+  generalxform->TransformPoint(p,q);
+  if (xform2!=NULL)
+    xform2->TransformPoint(p,q1);
+  fprintf(stderr,"Transforming p (%.1f,%.1f,%.1f) to q(%.1f,%.1f,%.1f) q1(%.2f,%.2f,%.2f)\n\t bounds = %.1f:%.1f, %.1f:%.1f %.1f:%.1f \n\t boundsref = %.1f:%.1f, %.1f:%.1f %.1f:%.1f \n",
+	  p[0],p[1],p[2],q[0],q[1],q[2],q1[0],q1[1],q1[2],
+	  bounds[0],bounds[1],bounds[2],bounds[3],bounds[4],bounds[5],
+	  boundsr[0],boundsr[1],boundsr[2],boundsr[3],boundsr[4],boundsr[5]);*/
+
+
+  double sigma[3],radius[3],ratio[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      ratio[ia]=sp2[ia]/sp1[ia];
+      sigma[ia] =10.0;
+      radius[ia]=0.5*(ratio[ia]/sigma[ia]);
+    }
+
+  
+
+
+
+  vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+  smooth->SetInput(image);
+  smooth->SetStandardDeviations(sigma);
+  smooth->SetRadiusFactors(radius);
+
+  vtkbisImageReslice* reslice=vtkbisImageReslice::New(); reslice->OptimizationOff();
+  reslice->SetInput(smooth->GetOutput());
+  reslice->SetInterpolationModeToCubic();
+  reslice->SetBackgroundLevel(0.0) ;
+  reslice->SetInformationInput(ref);
+  reslice->SetResliceTransform(generalxform);
+  reslice->Update();
+
+  image->ShallowCopy(reslice->GetOutput());
+  reslice->Delete();
+  smooth->Delete();
+  generalxform->Delete();
+}
+
+// --------------------------------------------------------------------------------------
+void vtkpxAddMotionToTimeSeries::CopyComponent(vtkImageData* input,vtkImageData* output,
+							 int inframe,int outframe)
+
+{
+  int dim[3];
+  input->GetDimensions(dim);
+
+  vtkDataArray* inScalars=input->GetPointData()->GetScalars();
+  vtkDataArray* outScalars=output->GetPointData()->GetScalars();
+
+  outScalars->CopyComponent(outframe,inScalars,inframe);
+
+  /*  int nt=inScalars->GetNumberOfTuples();
+
+  for (int k=0;k<nt;k++)
+  outScalars->SetComponent(k,outframe,inScalars->GetComponent(k,inframe));*/
+
+  
+}
+
+// --------------------------------------------------------------------------------------
+void vtkpxAddMotionToTimeSeries::SetMotionTransform(vtkTransform* transform,
+						    vtkFloatArray* parameters,int frame,
+						    float minusshift[3],float shift[3])
+{
+  transform->Identity();
+  transform->PostMultiply();
+  transform->Translate(minusshift);
+  transform->RotateX(parameters->GetComponent(frame,3));
+  transform->RotateY(parameters->GetComponent(frame,4));
+  transform->RotateZ(parameters->GetComponent(frame,5));
+  transform->Translate(shift);
+  transform->Translate(parameters->GetComponent(frame,0),
+		       parameters->GetComponent(frame,1),
+		       parameters->GetComponent(frame,2));
+}
+
+// --------------------------------------------------------------------------------------
+//  Reslice and Create Motion Path 
+// --------------------------------------------------------------------------------------
+
+void PrintImageSpecs(vtkImageData* im,char* name)
+{
+  int dim[3],numc;
+  im->GetDimensions(dim);
+  numc=im->GetNumberOfScalarComponents();
+  double sp[3],ori[3];
+  im->GetOrigin(ori);
+  im->GetSpacing(sp);
+  fprintf(stderr,"Image %s dim= [ %d %d %d, %d ] sp =[ %.2f %.2f %.2f ] or = [ %.2f %.2f %.2f ]\n",
+	  name,dim[0],dim[1],dim[2],numc,sp[0],sp[1],sp[2],ori[0],ori[1],ori[2]);
+}
+
+void vtkpxAddMotionToTimeSeries::SimpleExecute(vtkImageData* input,vtkImageData *output)
+{
+
+  if (input==NULL || this->TransformationParameters==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+
+  int inputFrames=input->GetNumberOfScalarComponents();
+  int numframes=this->TransformationParameters->GetNumberOfTuples();
+
+  if (inputFrames!=2 && inputFrames!=numframes)
+    {
+      vtkErrorMacro(<<"Bad Number of Frames Supplied in Input Time Series\n Exiting\n");
+      return;
+    }
+
+  vtkImageData *ref=this->GetReferenceImage();
+  if (ref==NULL)
+    ref=input;
+
+  output->SetSpacing(ref->GetSpacing());
+  output->SetOrigin(ref->GetOrigin());
+  output->SetScalarType(input->GetScalarType());
+  output->SetDimensions(ref->GetDimensions());
+  output->SetWholeExtent(ref->GetWholeExtent());
+  output->SetNumberOfScalarComponents(numframes);
+  output->AllocateScalars();
+
+  float shift[3], minusshift[3]; double sp[3];
+  int  dim[3];
+
+  input->GetSpacing(sp);
+  input->GetDimensions(dim);
+
+  // Create Base Transformation Stuff
+  // --------------------------------
+  vtkTransform* transform=vtkTransform::New();
+  transform->Identity();
+  for (int ia=0;ia<=2;ia++)
+    {
+      shift[ia]=0.5*dim[ia]*sp[ia];
+      minusshift[ia]=-0.5*float(dim[ia])*sp[ia];
+    }
+  
+
+  // Create Sequence 
+  // ---------------
+  int count=0,origframe=0;
+
+  //PrintImageSpecs(input," Input Image");
+  //PrintImageSpecs(ref,"Reference Image");
+
+  int numf=numframes;
+  //  numf=2;
+  
+  for (int f=0;f<numf;f++)
+    {
+      //      fprintf(stderr,"Creating Frame %d from %d\n",f,origframe);
+      vtkImageExtractComponents* extr=vtkImageExtractComponents::New();
+      extr->SetComponents(origframe);
+      extr->SetInput(input);
+      extr->Update();
+
+      //PrintImageSpecs(extr->GetOutput(),"Extract Component");
+
+      vtkImageData* tmp=vtkImageData::New();
+      tmp->ShallowCopy(extr->GetOutput());
+      extr->Delete();
+
+      if (this->UseMotionParameters)
+	SetMotionTransform(transform,this->TransformationParameters,f,
+			   minusshift,shift);
+
+      ResampleAndSmoothImage(tmp,ref,
+			     this->SliceThickness,
+			     transform,this->ObliqueTransform);
+      //PrintImageSpecs(tmp,"Resampled tmp");
+
+      CopyComponent(tmp,output,0,f);
+
+      //PrintImageSpecs(output,"Output");
+
+      if (inputFrames==numframes)
+	{
+	  ++origframe;
+	}
+      else
+	{
+	  ++count;
+	  if (count==this->BlockPeriod)
+	    {
+	      count=0;
+	      origframe=1-origframe;
+	    }
+	}
+      tmp->Delete();
+      this->UpdateProgress(float(f+1)/float(numframes));
+    }
+
+
+  transform->Delete();
+}	     
+
+
+// --------------------------------------------------------------------------------------
+//   Create Motion Path Stuff 
+// --------------------------------------------------------------------------------------
+
+float vtkpxAddMotionToTimeSeries::GaussianRandom()
+{
+  static int iset=0;
+  static float gset;
+  float fac,rsq,v1,v2;
+
+  if  (iset == 0) 
+    {
+      do {
+	v1=2.0*vtkMath::Random()-1.0;
+	v2=2.0*vtkMath::Random()-1.0;
+	rsq=v1*v1+v2*v2;
+      } 
+      while (rsq >= 1.0 || rsq == 0.0);
+      
+      fac=sqrt(-2.0*log(rsq)/rsq);
+      gset=v1*fac;
+      iset=1;
+      return v2*fac;
+    } 
+  else
+    {
+      iset=0;
+      return gset;
+    }
+}
+// --------------------------------------------------------------------------------------
+int vtkpxAddMotionToTimeSeries::SampleMotionPath(vtkFloatArray* param_in,vtkFloatArray* param_out,
+						 int samplerate)
+{
+  int framestep=Irange(samplerate,1,3);
+
+  if (framestep==1)
+    {
+      param_out->DeepCopy(param_in);
+      return 1;
+    }
+
+  int numframes=param_in->GetNumberOfTuples();
+  int outnframes;
+
+  if (framestep==2)
+    outnframes=(2*numframes)/3;
+  else
+    outnframes=(numframes)/3;
+
+  int nc=param_in->GetNumberOfComponents();
+
+  param_out->SetNumberOfComponents(nc);
+  param_out->SetNumberOfTuples(outnframes);
+
+  int fcount=0,frames=0;
+  for (int outframes=0;outframes<outnframes;outframes++)
+    {
+      for (int ia=0;ia<nc;ia++)
+	param_out->SetComponent(outframes,ia,param_in->GetComponent(frames,ia));
+      
+      switch (framestep) 
+	{
+	case 2:
+	  ++fcount;
+	  ++frames;
+	  if (fcount==2)
+	    {
+	      ++frames;
+	      fcount=0;
+	    }
+	  break;
+	case 3:
+	  frames+=3;
+	  break;
+	}
+    }
+  return outnframes;
+}
+// --------------------------------------------------------------------------------------
+int vtkpxAddMotionToTimeSeries::CreateMotionPath(vtkFloatArray* newScalars,int numframes,
+						 float rotation,float translation,int orientation,
+						 float noise1,float noise2)
+{
+  newScalars->SetNumberOfComponents(6);
+  newScalars->SetNumberOfTuples(numframes);
+
+  int rot=3,trans=0;
+
+  switch (orientation)
+    {
+    case 0: // Axial 
+      rot=3;
+      trans=2;
+      break;
+    case 1: // Coronal
+      rot=3;
+      trans=1;
+      break;
+    case 2: // Sagittal 
+      rot=5;
+      trans=1;
+      break;
+    }
+
+
+  float p[6];
+  for (int ia=0;ia<=5;ia++)
+    p[ia]=0.0;
+  
+
+  for (int frames=0;frames<numframes;frames++)
+    {
+      float fraction=float(frames)/float(numframes-1);
+      float rot_v=rotation*fraction;
+      float trans_v=translation*fraction;
+
+      for (int i=0;i<=5;i++)
+	{ 
+	  if (i!=rot && i!=trans )
+	    p[i]=GaussianRandom()*noise1+p[i];
+	  else
+	    p[i]=GaussianRandom()*noise2;
+	}
+      
+      // Fix ty and rx
+      p[rot]+=rot_v;
+      p[trans]+=trans_v;
+
+      for (int ib=0;ib<=5;ib++)
+	newScalars->SetComponent(frames,ib,p[ib]);
+    }
+
+  for (int ib=0;ib<=5;ib++)
+    newScalars->SetComponent(0,ib,0.0);
+
+  return 1;
+}
+ 
+// --------------------------------------------------------------------------------------
+int vtkpxAddMotionToTimeSeries::CreateMotionPath(vtkFloatArray* newScalars,int numframes,
+						 vtkFloatArray* params)
+
+{
+  if (params->GetNumberOfComponents()!=2 && params->GetNumberOfTuples()!=6)
+    return 0;
+
+  newScalars->SetNumberOfComponents(6);
+  newScalars->SetNumberOfTuples(numframes);
+
+  float p[6],mean[6],noise[6];
+  for (int ia=0;ia<=5;ia++)
+    {
+      p[ia]=0.0;
+      mean[ia]=params->GetComponent(ia,0);
+      noise[ia]=params->GetComponent(ia,1);
+      newScalars->FillComponent(ia,0.0);
+    }
+  
+  
+  for (int frames=1;frames<numframes;frames++)
+    {
+      float fraction=float(frames)/float(numframes-1);
+      for (int i=0;i<=5;i++)
+	p[i]+=GaussianRandom()*noise[i]+fraction*mean[i];
+
+      newScalars->SetTuple(frames,p);
+    }
+
+  return 1;
+}
+ 
+// --------------------------------------------------------------------------------------
+//   Transformation Parameter Comparison Stuff 
+// --------------------------------------------------------------------------------------
+
+int vtkpxAddMotionToTimeSeries::MultiplyTransformationParameters(int beginp,int endp,
+							       float factor,vtkFloatArray* scal)
+{
+
+  if (scal==NULL)
+    return 0;
+
+  int nframes=scal->GetNumberOfTuples();
+  for (int param=beginp;param<=endp;param++)
+    {
+      for (int frames=0;frames<nframes;frames++)
+	{
+	  float v=scal->GetComponent(frames,param);
+	  scal->SetComponent(frames,param,factor*v);
+	}
+    }
+  return endp-beginp+1;
+}
+// --------------------------------------------------------------------------------------
+int vtkpxAddMotionToTimeSeries::CompareTransformationParameters(vtkFloatArray* scal1,vtkFloatArray* scal2,
+							      vtkFloatArray *output)
+{
+  if (scal1==NULL || scal2==NULL || output==NULL)
+    return 0;
+
+
+  int n1=scal1->GetNumberOfTuples();
+  int nc1=scal1->GetNumberOfComponents();
+  int n2=scal2->GetNumberOfTuples();
+  int nc2=scal2->GetNumberOfComponents();
+
+  if (n1!=n2 || nc2!=nc1)
+    {
+      output->SetNumberOfTuples(0);
+      return 0;
+    }
+
+  int nframes=n1;
+  int numparam=nc1;
+
+  output->SetNumberOfComponents(8);
+  output->SetNumberOfTuples(numparam); // Mean, std ,correlation ratio, mean1 , std1, mean2, std2 ,  maxdiff
+
+  for (int param=0;param<numparam;param++)
+    {
+      float mean[3],var[3],sum[3],sum2[3],sumprod=0.0,maxd=0.0;
+      for (int ia=0;ia<=2;ia++)
+	{
+	  sum[ia]=0.0;
+	  sum2[ia]=0.0;
+	}
+  
+      for (int frames=0;frames<nframes;frames++)
+	{
+	  float v0=scal1->GetComponent(frames,param);
+	  sum[0]+=v0;
+	  sum2[0]+=v0*v0;
+	  
+	  float v1=scal2->GetComponent(frames,param);
+	  sum[1]+=v1;
+	  sum2[1]+=v1*v1;
+	  
+	  sumprod+=v0*v1;
+
+	  float d=fabs(v0-v1);
+
+	  sum[2]+=d;
+	  sum2[2]+=d*d;
+
+	  if (d>maxd)
+	    maxd=d;
+	}
+      
+      
+      for (int j=0;j<=2;j++)
+	{
+	  mean[j]=sum[j]/float(nframes);
+	  var[j] =Fmax(sum2[j]/float(nframes)-mean[j]*mean[j],0.0001);
+	}
+
+      float covar=pow(sumprod/float(nframes)-mean[0]*mean[1],float(2.0));
+      float covar2=covar/(var[0]*var[1]);
+      
+      float std=sqrt(var[2]);
+
+      output->SetComponent(param,0,mean[2]);
+      output->SetComponent(param,1,std);
+      output->SetComponent(param,2,covar2);
+      output->SetComponent(param,3,mean[0]);
+      output->SetComponent(param,4,sqrt(var[0]));
+      output->SetComponent(param,5,mean[1]);
+      output->SetComponent(param,6,sqrt(var[1]));
+      output->SetComponent(param,7,maxd);
+
+      /*fprintf(stderr,"Meand = %4.2f +- %4.2f  r2=%4.2f means=(%4.2f +- %4.2f ,%4.2f +- %4.2f ) maxd=%4.2f \n",
+	mean[2],std,covar2,mean[0],sqrt(var[0]),mean[1],sqrt(var[1]),maxd);*/
+    }
+  
+  return numparam;
+}
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxAddMotionToTimeSeries.h b/bioimagesuite30_src/Imaging/vtkpxAddMotionToTimeSeries.h
new file mode 100644
index 0000000..84250a2
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxAddMotionToTimeSeries.h
@@ -0,0 +1,177 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAddMotionToTimeSeries.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/26 17:28:15 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxAddMotionToTimeSeries
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxAddMotionToTimeSeries_h
+#define __vtkpxAddMotionToTimeSeries_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkAbstractTransform.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+class vtkTransform;
+
+
+class vtkpxAddMotionToTimeSeries : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxAddMotionToTimeSeries *New();
+  vtkTypeMacro(vtkpxAddMotionToTimeSeries,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set value of the block period e.g 8on/8off
+  vtkGetMacro(BlockPeriod,int);
+  vtkSetClampMacro(BlockPeriod,int,1,100);
+
+  // Description:
+  // Set value of the block period e.g 8on/8off
+  vtkGetMacro(UseMotionParameters,int);
+  vtkSetClampMacro(UseMotionParameters,int,0,1);
+
+
+  // Description:
+  // Transformation Parameters -- used for computing motion for sequence 
+  vtkSetObjectMacro(TransformationParameters,vtkFloatArray);
+  vtkGetObjectMacro(TransformationParameters,vtkFloatArray);
+
+
+  // Description:
+  // Transformation Parameters -- used for computing motion for sequence 
+  vtkSetObjectMacro(ReferenceImage,vtkImageData);
+  vtkGetObjectMacro(ReferenceImage,vtkImageData);
+
+
+  // Description:
+  // Transformation Parameters -- used for computing motion for sequence 
+  vtkSetObjectMacro(ObliqueTransform,vtkAbstractTransform);
+  vtkGetObjectMacro(ObliqueTransform,vtkAbstractTransform);
+
+  // Description:
+  // Set the slice thickness if different from slice spacing
+  vtkGetMacro(SliceThickness,float);
+  vtkSetClampMacro(SliceThickness,float,0.0,100.0);
+
+  // Description:
+  // Create Gaussain random variable
+  static float GaussianRandom();
+
+
+  // Description:
+  // Create Sagging Head Motion Path 
+  static int CreateMotionPath(vtkFloatArray* newScalars,int numframes,
+			      float rotation,float translation,int orientation,
+			      float noise1,float noise2);
+  static int CreateMotionPath(vtkFloatArray* newScalars,int numframes,
+			      vtkFloatArray* parameters);
+
+  static int SampleMotionPath(vtkFloatArray* param_in,vtkFloatArray* param_out,int samplerate);
+
+  // Description:
+  // Multiply Transformation Parameters and Compare Them 
+  // These are used for validation of motion correction schemes 
+  static int MultiplyTransformationParameters(int beginp,int endp,float factor,vtkFloatArray* scal);
+  static int CompareTransformationParameters(vtkFloatArray* scal1,vtkFloatArray* scal2,
+					     vtkFloatArray *ouput);
+
+
+protected:
+
+  vtkpxAddMotionToTimeSeries();
+  virtual ~vtkpxAddMotionToTimeSeries();
+  vtkpxAddMotionToTimeSeries(const vtkpxAddMotionToTimeSeries&) {};
+  void operator=(const vtkpxAddMotionToTimeSeries&) {};
+
+  void SimpleExecute(vtkImageData *input,vtkImageData *out);
+  void ExecuteInformation();
+
+  vtkAbstractTransform* ObliqueTransform;
+  vtkFloatArray*        TransformationParameters;
+  vtkImageData*  ReferenceImage;
+  int                   BlockPeriod;
+  int                   UseMotionParameters;  
+  float                 SliceThickness;
+
+
+  // Description:
+  // ResampleImage image in space defined by ref using tr=xform and Cubic Interpolation
+  static void ResampleAndSmoothImage(vtkImageData* image,
+				     vtkImageData* ref,
+				     float SliceThickness,
+				     vtkAbstractTransform* xform1,
+				     vtkAbstractTransform* xform2);
+  
+
+  // Description:
+  // Copy Component of input  into component of output 
+  static void CopyComponent(vtkImageData* input,vtkImageData* output,
+			    int incomp,int outcomp);
+
+
+  // Description:
+  // Set Transformation Needed 
+  static void SetMotionTransform(vtkTransform* transform,
+				 vtkFloatArray* parameters,
+				 int frame,float minusshift[3],float shift[3]);
+
+
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxAverageImages.cpp b/bioimagesuite30_src/Imaging/vtkpxAverageImages.cpp
new file mode 100644
index 0000000..f7b7ebe
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxAverageImages.cpp
@@ -0,0 +1,312 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAverageImages.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:09:25 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkpxAverageImages.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+//------------------------------------------------------------------------------
+vtkpxAverageImages* vtkpxAverageImages::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxAverageImages");
+  if(ret)
+    {
+    return (vtkpxAverageImages*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxAverageImages;
+}
+
+// Construct object with no children.
+vtkpxAverageImages::vtkpxAverageImages()
+{
+  this->Median=1;
+  this->IgnoreFlag=0;
+  this->IgnoreValue=-32767.0;
+  this->IgnoreValueOutput=0.0;
+  this->ComputeStandardDeviation=0;
+  this->OutputStandardDeviation=NULL;
+  this->SumOnly=0;
+}
+// ----------------------------------------------------------------------------
+vtkpxAverageImages::~vtkpxAverageImages()
+{
+  if (this->OutputStandardDeviation!=NULL)
+    this->OutputStandardDeviation->Delete();
+}
+// ----------------------------------------------------------------------------
+void vtkpxAverageImages::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+  output->SetScalarTypeToFloat();
+}
+
+void vtkpxAverageImages::SimpleExecute(vtkImageData* ,vtkImageData* output)
+{
+
+  if (this->GetNumberOfInputPorts()==0 || this->GetImageDataInput(0)==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+
+  int dim_0[3];
+  this->GetImageDataInput(0)->GetDimensions(dim_0);
+  int num_comp=this->GetImageDataInput(0)->GetNumberOfScalarComponents();
+
+  for (int i=1;i<this->GetNumberOfInputPorts();i++)
+      {
+	if (this->GetImageDataInput(i)==NULL)
+	  {
+	    vtkErrorMacro(<<"No Input Image Data " << i << " !!");
+	    return;
+	  }
+	else
+	  {
+	    int dim_1[3];
+	    this->GetImageDataInput(i)->GetDimensions(dim_1);
+	    int sum=0;
+	    for (int kk=0;kk<=2;kk++)
+	      sum+=abs(dim_1[kk]-dim_0[kk]);
+	    sum+=abs(num_comp-this->GetImageDataInput(i)->GetNumberOfScalarComponents());
+	    if (sum!=0)
+	      {
+		vtkErrorMacro(<<"Multiple Images have different Dimensions !!");
+		return;
+	      }
+	  }
+      }
+
+
+  // Create Output Array
+  // -------------------
+  int   dim[3];  this->GetImageDataInput(0)->GetDimensions(dim);
+  vtkDebugMacro(<< "Averaging Images\n" <<  "Dimensions " << dim[0] <<","<< dim[1] <<","<< dim[2] << "Components " << num_comp << "\n");
+  
+  output->SetSpacing(this->GetImageDataInput(0)->GetSpacing());
+  output->SetOrigin(this->GetImageDataInput(0)->GetOrigin());
+  output->SetScalarType(VTK_FLOAT);
+  output->SetNumberOfScalarComponents(num_comp);
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  output->AllocateScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  int numscalars=out->GetNumberOfTuples();
+
+  this->UpdateProgress(0.01);
+  float pog=0.00;
+
+  float tenth=(numscalars*num_comp)/10.0;
+  int count=0;
+
+  int domean=1;
+
+  if (this->Median==1 && this->GetNumberOfInputPorts()>=3 && this->ComputeStandardDeviation==0)
+    domean=0;
+
+  fprintf(stderr,"domean = %d\n",domean);
+
+  vtkDataArray* outsigma=NULL;
+  if (this->ComputeStandardDeviation)
+    {
+      if (this->OutputStandardDeviation==NULL)
+	this->OutputStandardDeviation=vtkImageData::New();
+      this->OutputStandardDeviation->SetSpacing(this->GetImageDataInput(0)->GetSpacing());
+      this->OutputStandardDeviation->SetOrigin(this->GetImageDataInput(0)->GetOrigin());
+      this->OutputStandardDeviation->SetScalarType(VTK_FLOAT);
+      this->OutputStandardDeviation->SetNumberOfScalarComponents(num_comp);
+      this->OutputStandardDeviation->SetDimensions(dim[0],dim[1],dim[2]);
+      this->OutputStandardDeviation->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+      this->OutputStandardDeviation->AllocateScalars();
+      outsigma=this->OutputStandardDeviation->GetPointData()->GetScalars();
+      outsigma->FillComponent(0,-1.0);
+    }
+
+
+  // If number of inputs < 3 median = mean
+
+  float correction=sqrt((float(this->GetNumberOfInputPorts())))/sqrt(float(this->GetNumberOfInputPorts()-1));
+
+  fprintf(stderr,"Sum Only=%d\n",SumOnly);
+
+  for (int component=0;component<num_comp;component++)
+    {
+      if (domean)
+	{
+	  float factor=float(1.0/this->GetNumberOfInputPorts());
+	  if (this->SumOnly)
+	    factor=1.0;
+	  for (int n=0;n<numscalars;n++)
+	    {
+	      int flag=1;
+	      if (this->IgnoreFlag>0)
+		{
+		  int series=0;
+		  while(series < this->GetNumberOfInputPorts() && flag==1) 
+		    {
+		      if (this->GetImageDataInput(series)->GetPointData()->GetScalars()->GetComponent(n,component)==
+			  this->IgnoreValue)
+			{
+			  flag=0;
+			  out->SetComponent(n,component,this->IgnoreValueOutput);		      
+			}
+		      ++series;
+		    }
+		}
+	      
+	      if (flag==1) 
+		{
+		  float sum=0.0;
+		  float sum2=0.0;
+		  for (int series=0;series<this->GetNumberOfInputPorts();series++)
+		    {
+		      float v=this->GetImageDataInput(series)->GetPointData()->GetScalars()->GetComponent(n,component);
+		      sum+=v;
+		      sum2+=v*v;
+		    }
+		  float mean =sum*factor;
+		  out->SetComponent(n,component,mean);
+		  
+		  if (this->ComputeStandardDeviation)
+		    {
+		      float sigma=sqrt(sum2*factor-mean*mean)*correction;
+		      outsigma->SetComponent(n,component,sigma);
+		    }
+		}
+	      
+	      count++;
+	      if (count==tenth)
+		{
+		  pog+=0.1;
+		  this->UpdateProgress(pog);
+		  count=0;
+		}
+	    }
+	} 
+      else 
+	{
+	  float *v=new float[this->GetNumberOfInputPorts()+1];
+	  
+	  int numhalf=int(this->GetNumberOfInputPorts())/2;
+	  int odd=1;
+	  
+	  if (numhalf*2 == this->GetNumberOfInputPorts())
+	    odd=0;
+
+	  if (odd)
+	    numhalf+=1;
+
+	  //	  fprintf(stderr,"numhalf=%d,odd=%d, numinpts=%d\n",numhalf,odd,this->GetNumberOfInputPorts());
+	  
+	  for (int n=0;n<numscalars;n++)
+	    {
+	      int flag=1;
+	      for (int series=0;series<this->GetNumberOfInputPorts();series++)
+		{
+		  v[series]=this->GetImageDataInput(series)->GetPointData()->GetScalars()->GetComponent(n,component);
+		  if ( v[series]==this->IgnoreValue && this->IgnoreFlag==1)
+		    flag=0;
+		}
+	      
+	      float max=0.0,prevmax=0.0;
+	      int position;
+	      
+	      if (flag==1)
+		{
+		  for(int outer=0;outer<numhalf;outer++)
+		    {
+		      max=v[0];
+		      position=0;
+		      for(int inner=1;inner<this->GetNumberOfInputPorts();inner++)
+			{
+			  if (v[inner]>max)
+			    {
+			      prevmax=max;
+			      max=v[inner];
+			      position=inner;
+			    }
+			}
+		      v[position]=-1.0e+38; // Large Negative Number
+		    }
+		  
+		  if (odd) 
+		    {
+		      out->SetComponent(n,component,max);
+		    } 
+		  else 
+		    {
+		      out->SetComponent(n,component,0.5*(max+prevmax));
+		}
+		}
+	      else 
+		out->SetComponent(n,component,this->IgnoreValueOutput);
+	      
+	      count++;
+	      if (count==tenth)
+		{
+		  pog+=0.1;
+		  this->UpdateProgress(pog);
+		  count=0;
+		}
+	    }
+	}
+    }
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxAverageImages.h b/bioimagesuite30_src/Imaging/vtkpxAverageImages.h
new file mode 100644
index 0000000..e68cfa9
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxAverageImages.h
@@ -0,0 +1,136 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAverageImages.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:08:12 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxAverageImages -- combines images to form either mean or median
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxAverageImages_h
+#define __vtkpxAverageImages_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+
+class vtkpxAverageImages : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxAverageImages *New();
+  vtkTypeMacro(vtkpxAverageImages,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Median, 0=Mean 1=Median 
+  vtkGetMacro(Median,int);
+  vtkSetClampMacro(Median,int,0,1);
+  vtkBooleanMacro(Median,int);
+
+  // Description:
+  // SumOnly if (median==0) do sum not mean
+  vtkGetMacro(SumOnly,int);
+  vtkSetClampMacro(SumOnly,int,0,1);
+  vtkBooleanMacro(SumOnly,int);
+
+  // Description: 
+  // Ignore Flag -- if set to 1 if any one image has a pixel value = Ignore Value
+  // The output there will be set to 0.0
+  vtkSetClampMacro(IgnoreFlag, int,0,1);
+  vtkGetMacro(IgnoreFlag, int);
+  vtkBooleanMacro(IgnoreFlag, int);
+
+  // Description:
+  // Ignore Value -- used for test
+  vtkSetMacro(IgnoreValue, float);
+  vtkGetMacro(IgnoreValue, float);
+  
+  // Description:
+  // Ignore Value -- used for test
+  vtkSetMacro(IgnoreValueOutput, float);
+  vtkGetMacro(IgnoreValueOutput, float);
+
+  // Description:
+  // Flag to Compute StandardDeviation -- to be obtained from StandardDeviationOutput
+  vtkSetClampMacro(ComputeStandardDeviation, int,0,1);
+  vtkGetMacro(ComputeStandardDeviation, int);
+  vtkBooleanMacro(ComputeStandardDeviation, int);
+
+
+  // Description: 
+  // Get the Output Standard Deviation
+  vtkGetObjectMacro(OutputStandardDeviation, vtkImageData);
+
+protected:
+
+  //BTX
+  vtkpxAverageImages();
+  virtual ~vtkpxAverageImages();
+  vtkpxAverageImages(const vtkpxAverageImages&) {};
+  void operator=(const vtkpxAverageImages&) {};
+
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual void ExecuteInformation();
+
+  int         Median;
+  int         SumOnly;
+  float       IgnoreValue;
+  float       IgnoreValueOutput;
+  int         IgnoreFlag;
+  int         ComputeStandardDeviation;
+  vtkImageData* OutputStandardDeviation;
+
+
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxBinaryImageMedian3D.cpp b/bioimagesuite30_src/Imaging/vtkpxBinaryImageMedian3D.cpp
new file mode 100644
index 0000000..2b80e90
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxBinaryImageMedian3D.cpp
@@ -0,0 +1,367 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxBinaryImageMedian3D.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkImageData.h"
+
+#include "vtkpxBinaryImageMedian3D.h"
+#include "vtkImageEllipsoidSource.h"
+#include "vtkObjectFactory.h"
+
+
+
+//------------------------------------------------------------------------------
+vtkpxBinaryImageMedian3D* vtkpxBinaryImageMedian3D::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxBinaryImageMedian3D");
+  if(ret)
+    {
+    return (vtkpxBinaryImageMedian3D*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxBinaryImageMedian3D;
+}
+
+
+
+
+
+//----------------------------------------------------------------------------
+// Construct an instance of vtkpxBinaryImageMedian3D fitler.
+// By default zero values are eroded.
+vtkpxBinaryImageMedian3D::vtkpxBinaryImageMedian3D()
+{
+  this->HandleBoundaries = 1;
+  this->KernelSize[0] = 1;
+  this->KernelSize[1] = 1;
+  this->KernelSize[2] = 1;
+
+  this->Ellipse = vtkImageEllipsoidSource::New();
+  // Setup the Ellipse to default size
+  this->SetKernelSize(1, 1, 1);
+}
+
+
+//----------------------------------------------------------------------------
+vtkpxBinaryImageMedian3D::~vtkpxBinaryImageMedian3D()
+{
+  if (this->Ellipse)
+    {
+    this->Ellipse->Delete();
+    this->Ellipse = NULL;
+    }
+}
+
+
+//----------------------------------------------------------------------------
+void vtkpxBinaryImageMedian3D::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkImageSpatialFilter::PrintSelf(os,indent);
+}
+
+//----------------------------------------------------------------------------
+// This method sets the size of the neighborhood.  It also sets the 
+// default middle of the neighborhood and computes the eliptical foot print.
+void vtkpxBinaryImageMedian3D::SetKernelSize(int size0, int size1, int size2)
+{
+  int modified = 0;
+  
+  if (this->KernelSize[0] != size0)
+    {
+    modified = 1;
+    this->KernelSize[0] = size0;
+    this->KernelMiddle[0] = size0 / 2;
+    }
+  if (this->KernelSize[1] != size1)
+    {
+    modified = 1;
+    this->KernelSize[1] = size1;
+    this->KernelMiddle[1] = size1 / 2;
+    }
+  if (this->KernelSize[2] != size2)
+    {
+    modified = 1;
+    this->KernelSize[2] = size2;
+    this->KernelMiddle[2] = size2 / 2;
+    }
+
+  if (modified)
+    {
+    this->Modified();
+    this->Ellipse->SetWholeExtent(0, this->KernelSize[0]-1, 
+				  0, this->KernelSize[1]-1, 
+				  0, this->KernelSize[2]-1);
+    this->Ellipse->SetCenter((float)(this->KernelSize[0]-1)*0.5,
+			     (float)(this->KernelSize[1]-1)*0.5,
+			     (float)(this->KernelSize[2]-1)*0.5);
+    this->Ellipse->SetRadius((float)(this->KernelSize[0])*0.5,
+			     (float)(this->KernelSize[1])*0.5,
+			     (float)(this->KernelSize[2])*0.5);
+    // make sure scalars have been allocated (needed if multithreaded is used)
+    this->Ellipse->GetOutput()->SetUpdateExtent(0, this->KernelSize[0]-1, 
+						0, this->KernelSize[1]-1, 
+						0, this->KernelSize[2]-1);
+    this->Ellipse->GetOutput()->Update();
+    }
+}
+
+
+//----------------------------------------------------------------------------
+// This templated function executes the filter on any region,
+// whether it needs boundary checking or not.
+// If the filter needs to be faster, the function could be duplicated
+// for strictly center (no boundary ) processing.
+template <class T>
+static void vtkpxBinaryImageMedian3DExecute(vtkpxBinaryImageMedian3D *self,
+					     vtkImageData *mask,
+					     vtkImageData *inData, T *inPtr, 
+					     vtkImageData *outData, 
+					     int *outExt, T *outPtr, int id)
+{
+  int *kernelMiddle, *kernelSize;
+  // For looping though output (and input) pixels.
+  int outMin0, outMax0, outMin1, outMax1, outMin2, outMax2;
+  int outIdx0, outIdx1, outIdx2;
+  vtkIdType inInc0, inInc1, inInc2;
+  vtkIdType outInc0, outInc1, outInc2;
+  T *inPtr0, *inPtr1, *inPtr2;
+  T *outPtr0, *outPtr1, *outPtr2;
+  int numComps, outIdxC;
+  // For looping through hood pixels
+  int hoodMin0, hoodMax0, hoodMin1, hoodMax1, hoodMin2, hoodMax2;
+  int hoodIdx0, hoodIdx1, hoodIdx2;
+  T *hoodPtr0, *hoodPtr1, *hoodPtr2;
+  // For looping through the mask.
+  unsigned char *maskPtr, *maskPtr0, *maskPtr1, *maskPtr2;
+  vtkIdType maskInc0, maskInc1, maskInc2;
+  // The extent of the whole input image
+  int inImageMin0, inImageMin1, inImageMin2;
+  int inImageMax0, inImageMax1, inImageMax2;
+  // to compute the range
+  int numPlusPixels;
+  int numMinusPixels;
+  unsigned long count = 0;
+  unsigned long target;
+
+  // Get information to march through data
+  inData->GetIncrements(inInc0, inInc1, inInc2); 
+  self->GetInput()->GetWholeExtent(inImageMin0, inImageMax0, inImageMin1,
+				   inImageMax1, inImageMin2, inImageMax2);
+  outData->GetIncrements(outInc0, outInc1, outInc2); 
+  outMin0 = outExt[0];   outMax0 = outExt[1];
+  outMin1 = outExt[2];   outMax1 = outExt[3];
+  outMin2 = outExt[4];   outMax2 = outExt[5];
+  numComps = outData->GetNumberOfScalarComponents();
+  
+  
+  // Get ivars of this object (easier than making friends)
+  kernelSize = self->GetKernelSize();
+  kernelMiddle = self->GetKernelMiddle();
+  hoodMin0 = - kernelMiddle[0];
+  hoodMin1 = - kernelMiddle[1];
+  hoodMin2 = - kernelMiddle[2];
+  hoodMax0 = hoodMin0 + kernelSize[0] - 1;
+  hoodMax1 = hoodMin1 + kernelSize[1] - 1;
+  hoodMax2 = hoodMin2 + kernelSize[2] - 1;
+
+  // Setup mask info
+  maskPtr = (unsigned char *)(mask->GetScalarPointer());
+  mask->GetIncrements(maskInc0, maskInc1, maskInc2);
+  
+  // in and out should be marching through corresponding pixels.
+  inPtr = (T *)(inData->GetScalarPointer(outMin0, outMin1, outMin2));
+
+  target = (unsigned long)(numComps*(outMax2-outMin2+1)*
+			   (outMax1-outMin1+1)/50.0);
+  target++;
+  
+  // loop through components
+  for (outIdxC = 0; outIdxC < numComps; ++outIdxC)
+    {
+      // loop through pixels of output
+      outPtr2 = outPtr;
+      inPtr2 = inPtr;
+      for (outIdx2 = outMin2; outIdx2 <= outMax2; ++outIdx2)
+	{
+	  outPtr1 = outPtr2;
+	  inPtr1 = inPtr2;
+	  for (outIdx1 = outMin1; 
+	       !self->AbortExecute && outIdx1 <= outMax1; ++outIdx1)
+	    {
+	      if (!id) 
+		{
+		  if (!(count%target))
+		    {
+		      self->UpdateProgress(count/(50.0*target));
+		    }
+		  count++;
+		}
+	      outPtr0 = outPtr1;
+	      inPtr0 = inPtr1;
+	      for (outIdx0 = outMin0; outIdx0 <= outMax0; ++outIdx0)
+		{
+		  
+		  // Find min
+		  numMinusPixels=0;
+		  numPlusPixels=0;
+		  
+		  // loop through neighborhood pixels
+		  // as sort of a hack to handle boundaries, 
+		  // input pointer will be marching through data that does not exist.
+		  hoodPtr2 = inPtr0 - kernelMiddle[0] * inInc0 
+		    - kernelMiddle[1] * inInc1 - kernelMiddle[2] * inInc2;
+		  maskPtr2 = maskPtr;
+		  for (hoodIdx2 = hoodMin2; hoodIdx2 <= hoodMax2; ++hoodIdx2)
+		    {
+		      hoodPtr1 = hoodPtr2;
+		      maskPtr1 = maskPtr2;
+		      for (hoodIdx1 = hoodMin1; hoodIdx1 <= hoodMax1; ++hoodIdx1)
+			{
+			  hoodPtr0 = hoodPtr1;
+			  maskPtr0 = maskPtr1;
+			  for (hoodIdx0 = hoodMin0; hoodIdx0 <= hoodMax0; ++hoodIdx0)
+			    {
+			      // A quick but rather expensive way to handle boundaries
+			      if ( outIdx0 + hoodIdx0 >= inImageMin0 &&
+				   outIdx0 + hoodIdx0 <= inImageMax0 &&
+				   outIdx1 + hoodIdx1 >= inImageMin1 &&
+				   outIdx1 + hoodIdx1 <= inImageMax1 &&
+				   outIdx2 + hoodIdx2 >= inImageMin2 &&
+				   outIdx2 + hoodIdx2 <= inImageMax2)
+				{
+				  if (*maskPtr0)
+				    {
+				      if (*hoodPtr0 > 0.0)
+					numPlusPixels++;
+				      else
+					numMinusPixels++;
+				    }
+				}
+			      
+			      hoodPtr0 += inInc0;
+			      maskPtr0 += maskInc0;
+			    }
+			  hoodPtr1 += inInc1;
+			  maskPtr1 += maskInc1;
+			}
+		      hoodPtr2 += inInc2;
+		      maskPtr2 += maskInc2;
+		    }
+		  if ( numPlusPixels > numMinusPixels)
+		    *outPtr0 = 1;
+		  else
+		    *outPtr0 = 0;
+		  //		  fprintf(stderr,"NumPlus=%d, numMinus=%d\n",numPlusPixels,numMinusPixels);
+		  
+		  inPtr0 += inInc0;
+		  outPtr0 += outInc0;
+		}
+	      inPtr1 += inInc1;
+	      outPtr1 += outInc1;
+	    }
+	  inPtr2 += inInc2;
+	  outPtr2 += outInc2;
+	}
+      ++inPtr;
+      ++outPtr;
+    }
+}
+
+
+		
+
+//----------------------------------------------------------------------------
+// This method contains the first switch statement that calls the correct
+// templated function for the input and output Data types.
+// It hanldes image boundaries, so the image does not shrink.
+void vtkpxBinaryImageMedian3D::ThreadedExecute(vtkImageData *inData, 
+						vtkImageData *outData, 
+						int outExt[6], int id)
+{
+  void *inPtr = inData->GetScalarPointerForExtent(outExt);
+  void *outPtr = outData->GetScalarPointerForExtent(outExt);
+  vtkImageData *mask;
+
+  // Error checking on mask
+  this->Ellipse->GetOutput()->Update();
+  mask = this->Ellipse->GetOutput();
+  if (mask->GetScalarType() != VTK_UNSIGNED_CHAR)
+    {
+    vtkErrorMacro(<< "Execute: mask has wrong scalar type");
+    return;
+    }
+
+  // this filter expects the output type to be same as input
+  if (outData->GetScalarType() != inData->GetScalarType())
+    {
+    vtkErrorMacro(<< "Execute: output ScalarType, " 
+      << vtkImageScalarTypeNameMacro(outData->GetScalarType())
+      << " must match input scalar type");
+    return;
+    }
+  
+  switch (inData->GetScalarType())
+    {
+    vtkTemplateMacro8(vtkpxBinaryImageMedian3DExecute, this, mask, 
+                      inData, (VTK_TT *)(inPtr), outData, outExt, 
+                      (VTK_TT *)(outPtr),id);
+    default:
+      vtkErrorMacro(<< "Execute: Unknown ScalarType");
+      return;
+    }
+}
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxBinaryImageMedian3D.h b/bioimagesuite30_src/Imaging/vtkpxBinaryImageMedian3D.h
new file mode 100644
index 0000000..4ec8627
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxBinaryImageMedian3D.h
@@ -0,0 +1,103 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxBinaryImageMedian3D.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxBinaryImageMedian3D - Erosion implemented as a minimum.
+// .SECTION Description
+// vtkpxBinaryImageMedian3D replaces a pixel with the median over
+// an ellipsoidal neighborhood.  If KernelSize of an axis is 1, no processing
+// is done on that axis. It assumes that the image is binary for speed.
+
+
+#ifndef __vtkpxBinaryImageMedian3D_h
+#define __vtkpxBinaryImageMedian3D_h
+
+
+#include "vtkImageSpatialFilter.h"
+
+class vtkImageEllipsoidSource;
+
+class vtkpxBinaryImageMedian3D : public vtkImageSpatialFilter
+{
+public:
+  // Description:
+  // Construct an instance of vtkpxBinaryImageMedian3D filter.
+  // By default zero values are eroded.
+  static vtkpxBinaryImageMedian3D *New();
+  vtkTypeMacro(vtkpxBinaryImageMedian3D,vtkImageSpatialFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  
+  // Description:
+  // This method sets the size of the neighborhood.  It also sets the 
+  // default middle of the neighborhood and computes the elliptical foot print.
+  void SetKernelSize(int size0, int size1, int size2);
+
+  
+protected:
+  vtkpxBinaryImageMedian3D();
+  ~vtkpxBinaryImageMedian3D();
+  vtkpxBinaryImageMedian3D(const vtkpxBinaryImageMedian3D&) {};
+  void operator=(const vtkpxBinaryImageMedian3D&) {};
+
+  vtkImageEllipsoidSource *Ellipse;
+    
+  void ThreadedExecute(vtkImageData *inData, vtkImageData *outData, 
+		       int extent[6], int id);
+};
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxCSIOffsetCorrection.cpp b/bioimagesuite30_src/Imaging/vtkpxCSIOffsetCorrection.cpp
new file mode 100644
index 0000000..9e4c3ba
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxCSIOffsetCorrection.cpp
@@ -0,0 +1,655 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCSIOffsetCorrection.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxCSIOffsetCorrection.h"
+#include "vtkpxUtil.h"
+#include "vtkFloatArray.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkMath.h"
+//------------------------------------------------------------------------------
+
+vtkpxCSIOffsetCorrection* vtkpxCSIOffsetCorrection::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxCSIOffsetCorrection");
+  if(ret)
+    {
+      return (vtkpxCSIOffsetCorrection*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxCSIOffsetCorrection;
+}
+
+
+
+vtkpxCSIOffsetCorrection::vtkpxCSIOffsetCorrection()
+{
+  this->Threshold=0.05;
+  this->WaterPeak=-1;
+  this->FatPeak=-1;
+  this->Input2=NULL;
+  this->FatPercentageOutput=NULL;
+  this->GlobalFatPercentageOutput=NULL;
+  this->OffsetMap=NULL;
+  this->GlobalOutput=NULL;
+  this->Spectrum=NULL;
+  this->Scale=0.000001;
+  this->Lambda=1.0;
+  this->Iterations=10;
+  this->SpectralSigma=1.0;
+}
+// ----------------------------------------------------------------------------
+vtkpxCSIOffsetCorrection::~vtkpxCSIOffsetCorrection()
+{
+  this->SetInput2(NULL);
+
+  if (this->FatPercentageOutput!=NULL)
+    this->FatPercentageOutput->Delete();
+  this->FatPercentageOutput=NULL;
+
+  if (this->GlobalFatPercentageOutput!=NULL)
+    this->GlobalFatPercentageOutput->Delete();
+  this->GlobalFatPercentageOutput=NULL;
+  
+  if (this->Spectrum!=NULL)
+    this->Spectrum->Delete();
+  this->Spectrum=NULL;
+ 
+  if (this->OffsetMap!=NULL)
+    this->OffsetMap->Delete();
+  this->OffsetMap=NULL;
+
+  if (this->GlobalOutput!=NULL)
+    this->GlobalOutput->Delete();
+  this->GlobalOutput=NULL;
+
+}
+
+// ---------------------------------------------------------------------------------------------
+vtkImageData* vtkpxCSIOffsetCorrection::GenerateFatPercentageOutput(vtkImageData* input)
+{
+  if (input==NULL)
+    return NULL;
+  float thr=Frange(this->Threshold,0.0,0.5);
+
+  if (input->GetNumberOfScalarComponents()<2)
+    return NULL;
+
+  vtkImageData* fat_out=vtkImageData::New();
+  fat_out->CopyStructure(input);
+  fat_out->SetNumberOfScalarComponents(1);
+  fat_out->SetScalarTypeToShort();
+  fat_out->AllocateScalars();
+
+  vtkDataArray* data_in=input->GetPointData()->GetScalars();
+  vtkDataArray* data_out=fat_out->GetPointData()->GetScalars();
+
+  int nt=data_in->GetNumberOfTuples();
+  double range1[2]; data_in->GetRange(range1,0);
+  double range2[2]; data_in->GetRange(range2,1);
+  float threshold1=thr*(range1[1]-range1[0])+range1[0];
+  float threshold2=thr*(range2[1]-range2[0])+range2[0];
+
+  fprintf(stderr,"Threshold1=%.3f (%.2f:%.2f)\n",threshold1,range1[0],range1[1]);
+  fprintf(stderr,"Threshold2=%.3f (%.2f:%.2f)\n",threshold2,range2[0],range2[1]);
+
+  for (int i=0;i<nt;i++)
+    {
+      float water=data_in->GetComponent(i,0);
+      float fat  =data_in->GetComponent(i,1);
+
+      if (water < threshold1 && fat < threshold2)
+	data_out->SetComponent(i,0,0.0);
+      else
+	{
+	  float p=100.0*fat/(fat+water);
+	  if (p>=1.0)
+	    data_out->SetComponent(i,0,p);
+	  else
+	    data_out->SetComponent(i,0,0.0);
+	}
+    }
+
+  return fat_out;
+}
+// ---------------------------------------------------------------------------------------------
+vtkImageData* vtkpxCSIOffsetCorrection::GenerateSmoothInputSpectrum(vtkImageData* realimg,vtkImageData* imagimg,float sigma,float scale)
+{
+  float s[5];
+  static int   dt[5] = { -2,-1,0,1,2};
+
+  if (sigma<0.1)
+    sigma=0.1;
+
+  float sum=0.0;
+  float sigma2=sigma*sigma;
+  for (int i=0;i<5;i++)
+    {
+      float ds=float(dt[i]);
+      s[i]=exp(-0.5*(ds*ds)/sigma2);
+      sum+=s[i];
+    }
+  for (int i=0;i<5;i++)
+    {
+      s[i]/=sum;
+      fprintf(stderr,"i=%d dt=%d s[%d]=%.2f\n",i,dt[i],i,s[i]);
+    }
+
+
+  vtkImageData* magn=vtkImageData::New();
+  magn->CopyStructure(realimg);
+  magn->AllocateScalars();
+
+  int dim[3]; realimg->GetDimensions(dim);
+  int nc=realimg->GetNumberOfScalarComponents();
+  for (int k=0;k<dim[2];k++)
+    {
+      fprintf(stderr,"Smoothing slice %d /%d\n",k,dim[2]);
+      for (int i=0;i<dim[0];i++)
+	for (int j=0;j<dim[1];j++)
+	  for (int c=0;c<nc;c++)
+	    {
+	      float sum=0.0;
+	      for (int t=0;t<5;t++)
+		{
+		  int tc=Irange(c+dt[t],0,nc-1);
+		  float re=realimg->GetScalarComponentAsDouble(i,j,k,tc);
+		  float im=imagimg->GetScalarComponentAsDouble(i,j,k,tc);
+		  sum+=s[t]*sqrt(re*re+im*im);
+		}
+	      magn->SetScalarComponentFromDouble(i,j,k,c,sum*scale);
+	    }
+    }
+  return magn;
+}
+
+// ---------------------------------------------------------------------------------------------
+vtkImageData* vtkpxCSIOffsetCorrection::ComputeInitialOffsetmap(vtkImageData* magnitude)
+{
+  if (magnitude==NULL)
+    return NULL;
+
+  vtkImageData* peaks=vtkImageData::New();
+
+  peaks->CopyStructure(magnitude);
+  peaks->SetScalarTypeToFloat();
+  peaks->SetNumberOfScalarComponents(1);
+  peaks->AllocateScalars();
+
+  int dim[3]; magnitude->GetDimensions(dim);
+  int nc=magnitude->GetNumberOfScalarComponents();
+
+  
+  float fat_peak=this->FatPeak;
+  float water_peak=this->WaterPeak;
+
+  int gap=int(0.4*fabs(fat_peak-water_peak)+0.5);
+
+  fprintf(stderr,"\n\n Input looking for water peak in %.1f:%.1f (%.1f) and fat_peak in %.1f:%.1f (%.1f) gap=%d\n",
+	  water_peak-gap,water_peak+gap,water_peak,
+	  fat_peak-gap,fat_peak+gap,fat_peak,gap);
+
+
+  for (int k=0;k<dim[2];k++)
+    {
+      fprintf(stderr,"\tSlice %d/%d \n",k+1,dim[2]);
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {
+	    //
+	    //  Identify Peaks via shift 
+	    //
+	    float max_sum=0.0;
+	    int shift=0;
+
+	    for (int s=-gap;s<=gap;s++)
+	      {
+		int c[2];
+		c[0]=Irange(int(water_peak)+s,0,nc-1);
+		c[1]=Irange(int(fat_peak)+s,0,nc-1);
+		
+		float v1=magnitude->GetScalarComponentAsDouble(i,j,k,c[0]);
+		float v2=magnitude->GetScalarComponentAsDouble(i,j,k,c[1]);
+		float v=v1+v2;
+		
+		if (v>max_sum)
+		  {
+		    max_sum=v;
+		    shift=s;
+		  }
+	      }
+	    peaks->SetScalarComponentFromDouble(i,j,k,0,shift);
+	  }
+    }
+
+  return peaks;
+
+}
+// ---------------------------------------------------------------------------------------------
+void vtkpxCSIOffsetCorrection::IntegrateMagnitude(vtkImageData* realimg,vtkImageData* imagimg,vtkImageData* peaks,
+						  vtkImageData* output,vtkFloatArray* volint)
+
+						  
+{
+  float water_peak=this->WaterPeak;
+  float fat_peak=this->FatPeak;
+
+  int dim[3]; realimg->GetDimensions(dim);
+  int nc=realimg->GetNumberOfScalarComponents();
+  float scale=1.0/(dim[0]*dim[1]*dim[2]);
+
+  volint->SetNumberOfComponents(3);
+  volint->SetNumberOfTuples(nc);
+  volint->FillComponent(0,0.0);
+  volint->FillComponent(1,0.0);
+  volint->FillComponent(2,0.0);
+
+  if (this->GlobalOutput!=NULL)
+    this->GlobalOutput->Delete();
+  this->GlobalOutput=vtkImageData::New();
+  this->GlobalOutput->CopyStructure(output);
+  this->GlobalOutput->AllocateScalars();
+
+  vtkFloatArray* data=(vtkFloatArray*)output->GetPointData()->GetScalars();
+  vtkFloatArray* gdata=(vtkFloatArray*)this->GlobalOutput->GetPointData()->GetScalars();
+  
+  float gap=0.5*fabs(fat_peak-water_peak);
+  float lw=water_peak-gap;
+  float uw=water_peak+gap;
+  float lf=fat_peak-gap;
+  float uf=fat_peak+gap;
+
+  int c2high=nc-int(gap);
+  int c2low=int(gap);
+  float nt=float(dim[2]*dim[1]*dim[0]);
+  int  globshift=int(water_peak-nc/2);
+
+
+  fprintf(stderr,"Input looking for water peak in %.1f:%.1f (%.1f) and fat_peak in %.1f:%.1f (%.1f) globshift=%d scale=%.4f\n",
+	  lw,uw,water_peak,lf,uf,fat_peak,globshift,scale);
+
+
+  int voxel=0;
+
+  fprintf(stderr,"slice :");
+
+  for (int k=0;k<dim[2];k++)
+    {
+      fprintf(stderr,"%d/%d ",k+1,dim[2]);
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {
+	    float shift=peaks->GetScalarComponentAsDouble(i,j,k,0);
+	    float wat_p=water_peak+shift;
+	    float fat_p=fat_peak+shift;
+
+	    int  dshift=int(wat_p-nc/2);
+	    
+	    float gp=fabs(fat_p-wat_p)*0.5;
+	    float l1=wat_p-gp;
+	    float m1=wat_p+gp;
+	    float u1=fat_p+gp;
+
+	    float lg1=water_peak-gp;
+	    float mg1=water_peak+gp;
+	    float mu1=fat_peak  +gp;
+
+	    
+	    if (i==dim[0]/2 && j==dim[0]/2)
+	      {
+		fprintf(stderr,"k=%d,water = %.1f:%.1f fat=%.1f:%.1f   offset=%.0f\n",k,
+			l1,m1,
+			m1,u1,shift);
+	      }
+	    
+	    float wat=0.0,fat=0.0,gwat=0.0,gfat=0.0;
+	    for (int c=0;c<nc;c++)
+	      {
+		float v1=realimg->GetScalarComponentAsDouble(i,j,k,c);
+		float v2=imagimg->GetScalarComponentAsDouble(i,j,k,c);
+		float v=sqrt(v1*v1+v2*v2);
+
+		int c2=c-dshift;
+		if (c2>c2low && c2<c2high)
+		  volint->SetComponent(c2,0,volint->GetComponent(c2,0)+v);
+
+		int c3=c-globshift;
+		if (c3>c2low && c3<c2high)
+		  volint->SetComponent(c3,1,volint->GetComponent(c3,1)+v);
+
+		volint->SetComponent(c,2,volint->GetComponent(c,2)+v);
+
+
+		if (c>=l1 && c<=m1)
+		  wat+=v;
+		else if (c>=m1 && c<=u1)
+		  fat+=v;
+		
+
+		if (c>=lg1 && c<=mg1)
+		  gwat+=v;
+		else if (c>=mg1 &&  c <= mu1)
+		  gfat+=v;
+
+		
+
+	      }
+	    
+	    data->SetComponent(voxel,0,wat*scale);
+	    data->SetComponent(voxel,1,fat*scale);
+	    
+	    gdata->SetComponent(voxel,0,gwat*scale);
+	    gdata->SetComponent(voxel,1,gfat*scale);
+	    
+
+	    if (i==dim[0]/2 && j==dim[0]/2)
+	      {
+		fprintf(stderr,"k=%d, local (%.1f %.1f) global (%.1f,%.1f) \n",k,
+			data->GetComponent(voxel,0),
+			data->GetComponent(voxel,1),
+			gdata->GetComponent(voxel,0),
+			gdata->GetComponent(voxel,1));
+
+	      }
+	    ++voxel;
+	  }
+    }
+
+
+  for (int c=0;c<nc;c++)
+    for (int d=0;d<=2;d++)
+      volint->SetComponent(c,d,volint->GetComponent(c,d)/nt);
+
+
+
+}
+
+// ----------------------------------------------------------------------------
+int  vtkpxCSIOffsetCorrection::UpdateVoxel(int eveni,int evenj,int evenk,int pass)
+{
+  int update_voxel=0;
+  if (eveni == evenj) update_voxel=1;
+  if (evenk)   	  update_voxel=1-update_voxel;
+  if (pass==1) 	  update_voxel=1-update_voxel;
+  
+  return update_voxel;
+}
+
+// ----------------------------------------------------------------------------
+float vtkpxCSIOffsetCorrection::OptimalOffsetForVoxel(int i,int j,int k,int dim[3],float weights[6],float lambda,float current,int nc)
+{
+  static int shift[6][3] = { { -1 ,0,0}, { 1,0,0},{ 0,-1,0 },{0,1,0} , { 0,0,-1},{0,0,1}};
+
+  float best=0.0;
+  float bestshift=current;
+  int   flag=0;
+  /*  if (i==dim[0]/ 2 && j==dim[1]/2 && k==dim[2]/2)
+      flag=1;*/
+  for (int s=-3;s<=3;s++)
+    {
+      int c[2];
+      c[0]=Irange(int(this->WaterPeak+current+s),0,nc-1);
+      c[1]=Irange(int(this->FatPeak  +current+s),0,nc-1);
+		
+      float s1=this->SmoothMagnitude->GetScalarComponentAsDouble(i,j,k,c[0]);
+      float s2=this->SmoothMagnitude->GetScalarComponentAsDouble(i,j,k,c[1]);
+      float this_voxel=s1+s2;
+
+      if (flag)
+	fprintf(stderr,"\n shift=%.1f (%d) s1=%.1f s2=%.1f, \t ",current+s,s,s1,s2);
+	
+      float sum=0.0;
+      float other_voxels=0.0;
+      for (int t=0;t<6;t++)
+	{
+	  int newi=Irange(i+shift[t][0],0,dim[0]-1);
+	  int newj=Irange(j+shift[t][1],0,dim[1]-1);
+	  int newk=Irange(k+shift[t][2],0,dim[2]-1);
+	  float sp=this->OffsetMap->GetScalarComponentAsDouble(newi,newj,newk,0);
+	  
+	  c[0]=Irange(int(this->WaterPeak+sp),0,nc-1);
+	  c[1]=Irange(int(this->FatPeak  +sp),0,nc-1);
+	  float s1=this->SmoothMagnitude->GetScalarComponentAsDouble(newi,newj,newk,c[0]);
+	  float s2=this->SmoothMagnitude->GetScalarComponentAsDouble(newi,newj,newk,c[1]);
+	  other_voxels+=weights[t]*(s1+s2);
+	  
+	  float dv=-weights[t]*pow(sp-(current+s),float(2.0));
+	  sum+=dv;
+	  if (flag)
+	    fprintf(stderr,"(t=%d s1=%.1f s2=%.1f sp=%.1f) ",t,s1,s2,sp,dv);
+	}
+
+      
+      float a=this_voxel/(this_voxel+other_voxels);
+      float b=1.0-a;
+      sum=a*this_voxel+b*lambda*sum;
+
+      if (flag)
+	fprintf(stderr,"\n\n\t a=%.1f b=%.1f sum=%.1f\n",a,b,sum);
+
+      if (s==-1.0 || sum>best)
+	{
+	  best=sum;
+	  bestshift=float(s+current);
+	}
+    }
+  
+  if (flag)
+    fprintf(stderr,"**** bestshift=%.1f best=%.1f\n\n",bestshift,best);
+
+  return bestshift;
+}
+
+// ----------------------------------------------------------------------------
+
+int vtkpxCSIOffsetCorrection::OptimizeOffsetMap()
+{
+  int iter=1;
+  int maxiter=this->Iterations;
+	  
+  int dim[3];   this->OffsetMap->GetDimensions(dim);
+  double sp[3]; this->OffsetMap->GetSpacing(sp);
+  
+  int nc=this->SmoothMagnitude->GetNumberOfScalarComponents();
+  float wgt[6];
+  wgt[5]=1.0/sp[2];   wgt[4]=1.0/sp[2];
+  wgt[3]=1.0/sp[1];   wgt[2]=1.0/sp[1];
+  wgt[1]=1.0/sp[0];   wgt[0]=1.0/sp[0];
+  
+   float sum=0.0;
+  for (int l=0;l<=5;l++)
+    sum+=wgt[l];
+
+  for (int k=0;k<=5;k++)
+    wgt[k]/=sum;
+
+  int done=0;
+
+  int nt=dim[0]*dim[1]*dim[2];
+  int tenth=nt/11;
+
+  while (done==0 && iter<maxiter)
+    {
+      float changed=0,total=0.0;
+      
+      int order=(vtkMath::Random()>0.5);
+  
+      fprintf(stderr,"\t **** MRF Regularization (%.2f) iter=%d :",this->Lambda,iter+1);
+      int count=0;
+
+      for (int pass=0;pass<=1;pass++)
+	{
+	  int realpass=pass;
+	  if (order==1)
+	    realpass=1-pass;
+
+	  for (int k=1;k<dim[2]-1;k++)
+	    {
+	      int evenk= ( ( k % 2 )  == 0);
+	      for (int j=1;j<dim[1]-1;j++)
+		{
+		  int evenj= ( ( j % 2 ) == 0 );
+		  for (int i=1;i<dim[0]-1;i++)
+		    {
+		      int eveni= ( ( i % 2 ) == 0 );
+		      ++count;
+		      if (count==tenth)
+			{
+			  fprintf(stderr,".");
+			  count=0;
+			}
+
+		      // ----------------------------
+		      // Updating Voxel
+		      // ----------------------------
+		      
+		      if ( this->UpdateVoxel(eveni,evenj,evenk,pass)==1)
+			{
+			  float current=this->OffsetMap->GetScalarComponentAsDouble(i,j,k,0);
+			  float best   =this->OptimalOffsetForVoxel(i,j,k,dim,wgt,this->Lambda,current,nc);
+			  if (fabs(current-best)>0.5)
+			    changed+=1.0;
+			  this->OffsetMap->SetScalarComponentFromDouble(i,j,k,0,best);
+			  total+=1.0;
+			}
+		    }
+		}
+	    }
+	}
+      
+      changed=100.0*changed/total;
+      fprintf(stderr,"changed=%.2f\n\n",changed);
+      if (changed<1)
+	done=1;
+      ++iter;
+    }
+ return 1;
+}
+// ----------------------------------------------------------------------------
+void vtkpxCSIOffsetCorrection::ExecuteInformation()
+{
+  if (this->GetImageDataInput(0)==NULL)
+    return;
+
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+  output->SetNumberOfScalarComponents(2);
+  output->SetScalarType(VTK_FLOAT);
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxCSIOffsetCorrection::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+
+ 
+  if (input==NULL    || this->Input2==NULL )
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxCSIOffsetCorrection");
+      return;
+    }
+
+
+  int dim[3],dim2[3];
+  input->GetDimensions(dim);
+  this->Input2->GetDimensions(dim2);
+  
+  int sum=0;
+  for (int ia=0;ia<=2;ia++)
+    sum+=abs(dim[ia]-dim2[ia]);
+  if (sum!=0)
+    {
+      vtkErrorMacro(<<"Bad Input Dimensions");
+      return;
+    }
+
+  if (this->WaterPeak==-1 || this->FatPeak==-1)
+    {
+      int nc=input->GetNumberOfScalarComponents();
+      this->WaterPeak=nc/2;
+      this->FatPeak=int(0.65*nc);
+    }
+
+
+  // First Smooth Input Spectrum
+  this->SmoothMagnitude=this->GenerateSmoothInputSpectrum(input,this->Input2,SpectralSigma,this->Scale);
+  this->UpdateProgress(0.1);
+  fprintf(stderr,"Done with Smooth Magnitude -- works \n");
+
+  // Then Compute Initial Offsets
+  this->OffsetMap=this->ComputeInitialOffsetmap(this->SmoothMagnitude);
+  this->UpdateProgress(0.2);
+  fprintf(stderr,"Done with Initial Offset Map\n");
+
+  
+  // Then Horror of Horrors Optimize Offset Map
+  if (this->Iterations>0)
+    this->OptimizeOffsetMap();
+  this->UpdateProgress(0.9);
+  fprintf(stderr,"Done with Final Offset Map\n");
+  
+  // Then Compute Integrated Output map
+  this->Spectrum=vtkFloatArray::New();
+  this->IntegrateMagnitude(input,this->Input2,this->OffsetMap,output,this->Spectrum);
+
+
+  fprintf(stderr,"Done with Int Magn Map\n");
+  this->FatPercentageOutput=this->GenerateFatPercentageOutput(output);
+  this->GlobalFatPercentageOutput=this->GenerateFatPercentageOutput(this->GlobalOutput);
+  fprintf(stderr,"Done with Fat Percentage\n");
+
+  this->UpdateProgress(1.0);
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxCSIOffsetCorrection.h b/bioimagesuite30_src/Imaging/vtkpxCSIOffsetCorrection.h
new file mode 100644
index 0000000..dc5df69
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxCSIOffsetCorrection.h
@@ -0,0 +1,183 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCSIOffsetCorrection.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxCSIOffsetCorrection -- corrects for B0 inhomogeneity in 1-H CSI Data for fat quantification
+
+#ifndef __vtkpxCSIOffsetCorrection_h
+#define __vtkpxCSIOffsetCorrection_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkFloatArray.h"
+
+class vtkpxCSIOffsetCorrection : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxCSIOffsetCorrection *New();
+  vtkTypeMacro(vtkpxCSIOffsetCorrection,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  //Set the level between 0 and 1 below which the data (in the ref image) is
+  // not used to compute fat percentage stuff
+  vtkGetMacro(Threshold,float);
+  vtkSetClampMacro(Threshold,float,0.001,1.0);
+
+  // Description:
+  // Set the original location of the water_peak and the fat_peak in the integrated spectrum
+  vtkGetMacro(WaterPeak,float);
+  vtkSetMacro(WaterPeak,float);
+  vtkGetMacro(FatPeak,float);
+  vtkSetMacro(FatPeak,float);
+
+  // Description:
+  // Scale Factor, multiply output data by constant=0.00001 to keep numbers small
+  vtkGetMacro(Scale,float);
+  vtkSetMacro(Scale,float);
+
+  // Description:
+  // MRF Smoothness Factor
+  vtkGetMacro(Lambda,float);
+  vtkSetClampMacro(Lambda,float,0.0,200.0);
+
+  // Description:
+  // MRF Iterations
+  vtkGetMacro(Iterations,int);
+  vtkSetClampMacro(Iterations,int,0,30);
+  
+  
+
+  // Description:
+  // Spectral Smoothing (Sigma=1.0)
+  vtkGetMacro(SpectralSigma,float);
+  vtkSetClampMacro(SpectralSigma,float,0.0,2.0);
+
+  // Description:
+  // Input2 -- imaginary data
+  // Input  -- real      data
+  vtkSetObjectMacro(Input2,vtkImageData);
+  vtkGetObjectMacro(Input2,vtkImageData);
+
+  // Description:
+  // FatPercentageOuput and integrated Spectrum
+  vtkGetObjectMacro(FatPercentageOutput, vtkImageData);
+  vtkGetObjectMacro(GlobalFatPercentageOutput, vtkImageData);
+  vtkGetObjectMacro(Spectrum, vtkFloatArray);
+  vtkGetObjectMacro(OffsetMap, vtkImageData);
+  vtkGetObjectMacro(SmoothMagnitude, vtkImageData);
+  vtkGetObjectMacro(GlobalOutput, vtkImageData);
+
+protected:
+
+  vtkpxCSIOffsetCorrection();
+  virtual ~vtkpxCSIOffsetCorrection();
+  vtkpxCSIOffsetCorrection(const vtkpxCSIOffsetCorrection&) {};
+  void operator=(const vtkpxCSIOffsetCorrection&) {};
+
+
+  // Description
+  // Boilerplate code from filter
+  virtual void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  // Description:
+  // Generate Smooth Input Spectrum
+  virtual vtkImageData* GenerateSmoothInputSpectrum(vtkImageData* real,vtkImageData* imag,float sigma,float scale);
+
+  // Description
+  // Generate PercentageFatOutput once correction is done, input is this->GetOutput()
+  virtual vtkImageData* GenerateFatPercentageOutput(vtkImageData* input);
+  
+  // Description:
+  // Compute Initial Object Map on a per voxel basis 
+  virtual vtkImageData* ComputeInitialOffsetmap(vtkImageData* magnitude);
+    
+  
+  // Description:
+  // Optimization Process -- Greedy Search
+  virtual int   UpdateVoxel(int eveni,int evenj,int evenk,int pass);
+  virtual float OptimalOffsetForVoxel(int i,int j,int k,int dim[3],float weights[6],float lambda,float current,int nc);
+  virtual int   OptimizeOffsetMap();
+
+  // Description:
+  // Integrate Spectrum Given Offset Map
+  void IntegrateMagnitude(vtkImageData* realimg,vtkImageData* imagimg,vtkImageData* peaks,
+			  vtkImageData* output,vtkFloatArray* volint);
+
+
+
+  // Description
+  // Data Members
+  float       Threshold;
+  float       WaterPeak;
+  float       FatPeak;
+  float       Scale;
+  float       Lambda;
+  int         Iterations;
+  float       SpectralSigma;
+  vtkImageData*  Input2;
+  vtkImageData*  FatPercentageOutput;
+  vtkImageData*  GlobalFatPercentageOutput;
+  vtkImageData*  OffsetMap;
+  vtkImageData*  SmoothMagnitude;
+  vtkImageData*  GlobalOutput;
+  vtkFloatArray* Spectrum;
+
+
+
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxCSIStackImages.cpp b/bioimagesuite30_src/Imaging/vtkpxCSIStackImages.cpp
new file mode 100644
index 0000000..bc29cd1
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxCSIStackImages.cpp
@@ -0,0 +1,308 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCSIStackImages.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:09:25 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkpxCSIStackImages.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkbisImageReslice.h"
+#include "vtkTransform.h"
+//------------------------------------------------------------------------------
+vtkpxCSIStackImages* vtkpxCSIStackImages::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxCSIStackImages");
+  if(ret)
+    {
+      return (vtkpxCSIStackImages*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxCSIStackImages;
+}
+
+// Construct object with no children.
+vtkpxCSIStackImages::vtkpxCSIStackImages()
+{
+  this->AnatomicalOutput=NULL;
+  this->AnatomicalInput=NULL;
+  this->ResolutionXY=1.0;
+  this->ResolutionZ=1.0;
+}
+// ----------------------------------------------------------------------------
+vtkpxCSIStackImages::~vtkpxCSIStackImages()
+{
+  if (this->AnatomicalOutput!=NULL)
+    this->AnatomicalOutput->Delete();
+  this->SetAnatomicalInput(NULL);
+}
+// ----------------------------------------------------------------------------
+void vtkpxCSIStackImages::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  if (this->GetNumberOfInputPorts()<1 || this->AnatomicalInput == NULL)
+    {
+      vtkErrorMacro(<<"Need At least one input and an Anatomical Input\n");
+      return;
+    }
+
+  // Compute Anatomical Extent
+  double anat_ori[3]; this->AnatomicalInput->GetOrigin(anat_ori);
+  double anat_spa[3]; this->AnatomicalInput->GetSpacing(anat_spa);
+  int    anat_dim[3]; this->AnatomicalInput->GetDimensions(anat_dim);
+  double  anat_ext[3][2] = { 0.0,1.0,0.0,1.0,0.0,1.0};
+
+  vtkImageData* CSI=this->GetImageDataInput(0);
+  int    csi_dim[3]; CSI->GetDimensions(csi_dim);
+  double csi_spa[3]; CSI->GetSpacing(csi_spa);
+  double csi_ori[3]; CSI->GetOrigin(csi_ori);
+
+  double  csi_ext[3][2] = { 0.0,1.0,0.0,1.0,0.0,1.0};
+
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      anat_ext[ia][0]=anat_ori[ia];
+      anat_ext[ia][1]=anat_ext[ia][0]+double(anat_dim[ia]-1)*anat_spa[ia];
+      csi_ext[ia][0]=csi_ori[ia];
+      csi_ext[ia][1]=csi_ext[ia][0]+double(csi_dim[ia]-1)*csi_spa[ia];
+    }
+  anat_ext[2][0]=-0.5*double(anat_dim[2]-1)*anat_spa[2];
+  anat_ext[2][1]=+0.5*double(anat_dim[2]-1)*anat_spa[2];
+
+
+  fprintf(stderr,"CSI Extent 0 = %.2f:%.2f  %.2f:%.2f  %.2f:%.2f\n",
+	  csi_ext[0][0],csi_ext[0][1],csi_ext[1][0],csi_ext[1][1],csi_ext[2][0],csi_ext[2][1]);
+
+  if (this->GetNumberOfInputPorts()>1)
+    {
+      for (int j=1;j<this->GetNumberOfInputPorts();j++)
+	{
+	  double z=this->GetImageDataInput(j)->GetOrigin()[2];
+
+	  if (csi_ext[2][0]>z)
+	    csi_ext[2][0]=z;
+	  if (csi_ext[2][1]<z)
+	    csi_ext[2][1]=z;
+	  fprintf(stderr,"CSI Extent %d = %.2f:%.2f  %.2f:%.2f  %.2f:%.2f\n",j,
+		  csi_ext[0][0],csi_ext[0][1],csi_ext[1][0],csi_ext[1][1],csi_ext[2][0],csi_ext[2][1]);
+	}
+    }
+
+  fprintf(stderr,"CSI Center = (%.2f,%.2f,%.2f)\n",
+	  0.5*(csi_ext[0][0]+csi_ext[0][1]),
+	  0.5*(csi_ext[1][0]+csi_ext[1][1]),
+	  0.5*(csi_ext[2][0]+csi_ext[2][1]));
+  
+  fprintf(stderr,"Anatomical Extent = %.2f:%.2f  %.2f:%.2f  %.2f:%.2f\n",
+	  anat_ext[0][0],anat_ext[0][1],anat_ext[1][0],anat_ext[1][1],anat_ext[2][0],anat_ext[2][1]);
+  fprintf(stderr,"Anatomical Center = (%.2f,%.2f,%.2f)\n",
+	  0.5*(anat_ext[0][0]+anat_ext[0][1]),
+	  0.5*(anat_ext[1][0]+anat_ext[1][1]),
+	  0.5*(anat_ext[2][0]+anat_ext[2][1]));
+
+
+  double half=0.5*(csi_spa[2])-0.5*this->ResolutionZ;
+
+  double minz=csi_ext[2][0]-half;
+  while (minz>anat_ext[2][0])
+    minz-=this->ResolutionZ;
+
+  double maxz=csi_ext[2][1]+half;
+  while (maxz<anat_ext[2][1])
+    maxz+=this->ResolutionZ;
+
+  fprintf(stderr,"Final Z-Range = %.2f:%.2f\n",minz,maxz);
+
+  int wholeExtent[6]= { 0,1,0,1,0,1};
+  wholeExtent[1] = int(csi_dim[0]*csi_spa[0]/this->ResolutionXY)-1;
+  wholeExtent[3] = int(csi_dim[1]*csi_spa[1]/this->ResolutionXY)-1;
+  wholeExtent[5] = int((maxz-minz)/this->ResolutionZ+0.5);
+  
+  fprintf(stderr,"Output Dimensions = %d,%d,%d\n",wholeExtent[1]+1,wholeExtent[3]+1,wholeExtent[5]+1);
+
+  vtkImageData *output=this->GetOutput();
+  output->DebugOn();
+  output->SetSpacing(this->ResolutionXY,this->ResolutionXY,this->ResolutionZ);
+  output->SetOrigin(0.0,0.0,minz);
+  output->SetWholeExtent( wholeExtent );
+  output->DebugOff();
+  output->SetUpdateExtent( wholeExtent );
+
+  output->SetScalarType(CSI->GetScalarType());
+  output->SetNumberOfScalarComponents(CSI->GetNumberOfScalarComponents());
+
+}
+
+// ----------------------------------------------------------------------------
+void vtkpxCSIStackImages::SimpleExecute(vtkImageData* ,vtkImageData* output)
+{
+
+  if (this->GetNumberOfInputPorts()==0 || this->GetImageDataInput(0)==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+
+  int dim[3];    output->GetDimensions(dim);
+  double spa[3]; output->GetSpacing(spa);
+  double ori[3]; output->GetOrigin(ori);
+  fprintf(stderr,"Output Origin = %.2f %.2f %.2f\n",ori[0],ori[1],ori[2]);
+
+  double spa_csi[3]; this->GetImageDataInput(0)->GetSpacing(spa_csi);
+  int ratiox=int(spa_csi[0]/spa[0]);
+  int ratioy=int(spa_csi[1]/spa[1]);
+  int* index=new int[dim[2]];
+
+  for (int i=0;i<dim[2];i++)
+    {
+      index[i]=-1;
+      double zlevel=ori[2]+double(i)*spa[2];
+
+      int j=0;
+      while (j<this->GetNumberOfInputPorts() && index[i]==-1)
+	{
+	  double z=this->GetImageDataInput(j)->GetOrigin()[2];
+	  
+	  if (zlevel>=(z-0.5*spa_csi[2]) && zlevel<(z+0.5*spa_csi[2]))
+	    index[i]=j;
+	  ++j;
+	}
+
+      if (index[i]!=-1)
+	fprintf(stderr,"zlevel = %.2f \t  index=%d\n",zlevel,index[i]);
+      else
+	fprintf(stderr,"zlevel = %.2f \t  index= *\n",zlevel);
+    }
+
+  this->UpdateProgress(0.2);
+
+  int nc=output->GetNumberOfScalarComponents();
+
+  for (int k=0;k<dim[2];k++)
+    {
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {
+	    if (index[k]==-1)
+	      {
+		for (int c=0;c<nc;c++)
+		  output->SetScalarComponentFromDouble(i,j,k,c,0.0);
+	      }
+	    else
+	      {
+		vtkImageData* input=this->GetImageDataInput(index[k]);
+		int in_i=i/ratiox;
+		int in_j=j/ratioy;
+		for (int c=0;c<nc;c++)
+		  output->SetScalarComponentFromDouble(i,j,k,c,input->GetScalarComponentAsDouble(in_i,in_j,0,c));
+	      }
+	  }
+    }
+
+  delete [] index;
+
+
+  this->UpdateProgress(0.8);
+
+  double anat_ori[3]; this->AnatomicalInput->GetOrigin(anat_ori);
+  double anat_spa[3]; this->AnatomicalInput->GetSpacing(anat_spa);
+  int    anat_dim[3]; this->AnatomicalInput->GetDimensions(anat_dim);
+  
+  double shift[3] = { 0.0,0.0,0.0};
+
+  fprintf(stderr,"Origin = %.2f %.2f %.2f\n",ori[0],ori[1],ori[2]);
+  fprintf(stderr,"Spacing = %.2f %.2f %.2f\n",spa[0],spa[1],spa[2]);
+  fprintf(stderr,"Dimensions = %d %d %d\n",dim[0],dim[1],dim[2]);
+
+  for (int i=0;i<=1;i++)
+    {
+      double c0=ori[i]+0.5*(double(dim[i]-1))*spa[i];
+      double c1=anat_ori[i]+0.5*(double(anat_dim[i]-1))*anat_spa[i];
+      shift[i]=c1-c0;
+      fprintf(stderr,"i=%d c0=%.2f c1=%.2f shift[i]=%.2f\n",
+	      i,c0,c1,shift[i]);
+    }
+  shift[2]=+0.5*double(anat_dim[2]-1)*anat_spa[2];
+
+  fprintf(stderr,"Shift = %.2f %.2f %.2f\n",shift[0],shift[1],shift[2]);
+
+  vtkTransform* tr=vtkTransform::New();
+  tr->Identity();
+  tr->DebugOn();
+  tr->Translate(shift);
+  tr->DebugOff();
+
+  vtkbisImageReslice* resl=vtkbisImageReslice::New(); resl->OptimizationOff();
+  resl->SetInput(this->AnatomicalInput);
+  resl->SetInformationInput(this->GetOutput());
+  resl->SetResliceTransform(tr);
+  resl->SetInterpolationMode(1);
+  resl->SetBackgroundLevel(0.0);
+  resl->Update();
+  
+  if (this->AnatomicalOutput!=NULL)
+    this->AnatomicalOutput->Delete();
+
+  this->AnatomicalOutput=vtkImageData::New();
+  this->AnatomicalOutput->ShallowCopy(resl->GetOutput());
+  resl->Delete();
+  tr->Delete();
+
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxCSIStackImages.h b/bioimagesuite30_src/Imaging/vtkpxCSIStackImages.h
new file mode 100644
index 0000000..517a193
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxCSIStackImages.h
@@ -0,0 +1,113 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAverageImages.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:08:12 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxAverageImages -- combines images to form either mean or median
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxCSIStackImages_h
+#define __vtkpxCSIStackImages_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkpxCSIStackImages : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxCSIStackImages *New();
+  vtkTypeMacro(vtkpxCSIStackImages,vtkpxSimpleImageToImageFilter);
+
+
+  // Description:
+  // Output Resolution 
+  vtkGetMacro(ResolutionXY,float);
+  vtkSetClampMacro(ResolutionXY,float,0.25,10.0);
+  vtkGetMacro(ResolutionZ,float);
+  vtkSetClampMacro(ResolutionZ,float,0.25,10.0);
+
+  // Description: 
+  // Get the Transformation Between Anatomical 
+  vtkGetObjectMacro(AnatomicalOutput, vtkImageData);
+
+  // Description: 
+  // Set the Input Anatomical Image
+  // These all should have the same dimensions but different z-shifts!!!
+  vtkSetObjectMacro(AnatomicalInput, vtkImageData);
+  vtkGetObjectMacro(AnatomicalInput, vtkImageData);
+
+protected:
+
+  //BTX
+  vtkpxCSIStackImages();
+  virtual ~vtkpxCSIStackImages();
+  vtkpxCSIStackImages(const vtkpxCSIStackImages&) {};
+  void operator=(const vtkpxCSIStackImages&) {};
+
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual void ExecuteInformation();
+
+
+  float       ResolutionXY;
+  float       ResolutionZ;
+  vtkImageData* AnatomicalOutput;
+  vtkImageData* AnatomicalInput;
+
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxComputeTmap.cpp b/bioimagesuite30_src/Imaging/vtkpxComputeTmap.cpp
new file mode 100644
index 0000000..d41d775
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxComputeTmap.cpp
@@ -0,0 +1,361 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxComputeTmap.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 19:05:57 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxComputeTmap.h"
+#include "vtkpxUtil.h"
+#include "vtkpxMath.h"
+#include "pxisinf.h"
+
+//------------------------------------------------------------------------------
+vtkpxComputeTmap* vtkpxComputeTmap::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxComputeTmap");
+  if(ret)
+    {
+    return (vtkpxComputeTmap*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxComputeTmap;
+}
+
+// Construct object with no children.
+vtkpxComputeTmap::vtkpxComputeTmap()
+{
+  this->ScaleFactor=1000.0;
+  this->NumberOfInputs=2;
+  this->Input2=NULL;
+  this->InputStandardDeviation=NULL;
+  this->InputStandardDeviation2=NULL;
+  this->NumberOfSamples1=-1;
+  this->NumberOfSamples2=-1;
+  this->OutputZScore=NULL;
+  this->ComputeZScore=0;
+}
+// ----------------------------------------------------------------------------
+vtkpxComputeTmap::~vtkpxComputeTmap()
+{
+  this->SetInput2(NULL);
+  this->SetInputStandardDeviation(NULL);
+  this->SetInputStandardDeviation2(NULL);
+  if (this->OutputZScore!=NULL)
+    this->OutputZScore->Delete();
+}
+// ----------------------------------------------------------------------------
+void vtkpxComputeTmap::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+  output->SetScalarTypeToFloat();
+}
+
+void vtkpxComputeTmap::SimpleExecute(vtkImageData* inp,vtkImageData* outp)
+{
+  if (this->NumberOfSamples1+this->NumberOfSamples2<2)
+    {
+      vtkErrorMacro(<<"The total number of samples must be greater than 2!\n");
+      return;
+    }
+
+  if ( this->NumberOfInputs == 2 ) 
+    {
+      if (this->GetImageDataInput(0)==NULL    || this->Input2==NULL ||
+	  this->InputStandardDeviation==NULL || ( this->InputStandardDeviation2==NULL && this->NumberOfSamples2>1))
+	{
+	  vtkErrorMacro(<<"Bad Inputs to vtkpxComputeTmap");
+	  return;
+	}
+      if (this->NumberOfSamples2<1)
+	this->NumberOfSamples2=1;
+      
+    } 
+  else if (this->GetImageDataInput(0)==NULL || this->InputStandardDeviation==NULL )
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxComputeTmap");
+      return;
+    }
+
+  int dim[3],dim1[3],dim2[3],dim3[3],comp[4];
+  this->GetImageDataInput(0)->GetDimensions(dim);
+  this->GetInputStandardDeviation()->GetDimensions(dim2);
+  comp[0]=this->GetImageDataInput(0)->GetNumberOfScalarComponents();
+  comp[1]=this->GetInputStandardDeviation()->GetNumberOfScalarComponents();
+
+  if (this->NumberOfInputs==2)
+    {
+      this->GetInput2()->GetDimensions(dim1);
+      comp[2]=this->GetInput2()->GetNumberOfScalarComponents();
+      comp[3]=this->GetInputStandardDeviation2()->GetNumberOfScalarComponents();
+      this->GetInputStandardDeviation2()->GetDimensions(dim3);
+    }
+  else
+    {
+      this->GetImageDataInput(0)->GetDimensions(dim1);
+      this->GetInputStandardDeviation()->GetDimensions(dim3);
+      comp[2]=this->GetImageDataInput(0)->GetNumberOfScalarComponents();
+      comp[3]=this->GetInputStandardDeviation()->GetNumberOfScalarComponents();
+
+    }
+  
+  int sum=0;
+  for (int ia=0;ia<=2;ia++)
+    sum+=abs(dim[ia]-dim1[ia])+abs(dim[ia]-dim2[ia])+abs(dim[ia]-dim3[ia]);
+
+  for (int ib=1;ib<=3;ib++)
+    sum+=abs(comp[ib]-comp[0]);
+
+  
+
+  if (sum!=0)
+    {
+      vtkErrorMacro(<<"Bad Input Dimensions");
+      return;
+    }
+  //  else
+  //    fprintf(stderr,"Components = %d(%d) , (%d,%d)\n",comp[0],comp[1],comp[2],comp[3]);
+
+  
+
+  vtkDataArray* out=outp->GetPointData()->GetScalars();
+
+  int numscalars=out->GetNumberOfTuples();
+
+  vtkDataArray* in1=this->GetImageDataInput(0)->GetPointData()->GetScalars();
+  vtkDataArray* sig1=this->GetInputStandardDeviation()->GetPointData()->GetScalars();
+
+  vtkDataArray* in2=NULL,*sig2=NULL;
+
+  if ( this->NumberOfInputs==2 ) 
+    {
+      in2=this->GetInput2()->GetPointData()->GetScalars();
+      sig2=this->GetInputStandardDeviation2()->GetPointData()->GetScalars();
+    }
+
+  this->UpdateProgress(0.01);
+  float pog=0.00;
+  float tenth=(numscalars*comp[0])/10.0;
+  int count=0;
+
+  float rootn1=sqrt(float(this->NumberOfSamples1));
+
+  float scaledenominator=1.0;
+  if ( this->NumberOfInputs==2  ) 
+    {
+      if (this->NumberOfSamples2>1 && this->NumberOfSamples1>1)
+	scaledenominator=sqrt(1.0/float(this->NumberOfSamples1)+1.0/float(this->NumberOfSamples2));
+      else if (this->NumberOfSamples2<2)
+	scaledenominator=1.0;//sqrt(1.0/float(this->NumberOfSamples1));
+      else
+	scaledenominator=1.0;//sqrt(1.0/float(this->NumberOfSamples2));
+    }
+
+  fprintf(stderr,"Scaledenominator=%f (%d,%d) numinp=%d\n",scaledenominator,this->NumberOfSamples1,this->NumberOfSamples2,this->NumberOfInputs);
+  fprintf(stderr,"sc=%f  rootn1=%f Samples=%d,%d\n",this->ScaleFactor,rootn1,this->NumberOfSamples1,this->NumberOfSamples2);
+
+  //  int maxtval=(int)(200.0*this->ScaleFactor);
+
+  for (int component=0;component<comp[0];component++)
+    {
+      out->FillComponent(component,-1.0);
+      for (int pixel=0;pixel<numscalars;pixel++)
+	{
+	  float mean1=in1->GetComponent(pixel,component);
+	  float sigma1=sig1->GetComponent(pixel,component);
+	  double tvalue=0.0;
+	  
+	  if ( this->NumberOfInputs==2  ) 
+	    {
+	      float mean2=in2->GetComponent(pixel,component);
+	      float sigma2=sig2->GetComponent(pixel,component);
+	      
+	      if ( fabs(sigma1)<0.00001 ||  fabs(sigma2)<0.00001)
+		{
+		  tvalue=0;
+		}
+	      else
+		{
+		  float combinedsigma=0.0;
+		  if (this->NumberOfSamples2>1 && this->NumberOfSamples1>1)
+		    combinedsigma=sqrt( ( (this->NumberOfSamples1-1.0)*sigma1*sigma1+(this->NumberOfSamples2-1.0)*sigma2*sigma2)/
+					float(this->NumberOfSamples1+this->NumberOfSamples2-2.0));
+		  else if (this->NumberOfSamples2<2)
+		    combinedsigma=sigma1;
+		  else
+		    combinedsigma=sigma2;
+		  
+		  float tsigma=combinedsigma*scaledenominator;
+
+		  if (this->Debug)
+		    {
+		      if (pixel==0)
+			fprintf(stderr,"CombinedSigma=%.3f, mean1=%.3f,mean2=%.3f\n",tsigma,mean1,mean2);
+		    }
+		  
+		  if ( fabs(mean1)<0.00001 || fabs(mean2)<0.00001 || fabs(tsigma)<0.00001 || sigma1<0.00001 || sigma2<0.00001 )
+		    {
+		      tvalue=0;
+		    }
+		  else 
+		    {
+		      if (tsigma<0.00001)
+			tsigma=0.00001;
+		      tvalue=this->ScaleFactor*((mean1-mean2)/tsigma);
+		    }
+		}
+	    }
+	  else  // Number Of Inputs = 1
+	    {
+	      /*      if (component==0 && pixel==0)
+		      fprintf(stderr,"* One Inputs\n");*/
+
+	      if ( fabs(mean1)<0.00001 && fabs(sigma1)<0.00001)
+		{
+		  tvalue=0;
+		}
+	      else if (isnan(sigma1) || isnan(mean1) || sigma1<0.00001)
+		{
+		  tvalue=0;
+		}
+	      else
+		{
+		  tvalue=this->ScaleFactor*(mean1*rootn1/sigma1);
+		}
+	    }
+	  //	  tvalue=Irange(tvalue,-maxtval,maxtval);
+	  out->SetComponent(pixel,component,double(tvalue));
+	  count++;
+	  if (count==tenth)
+	    {
+	      pog+=0.1;
+	      this->UpdateProgress(pog);
+	      count=0;
+	    }
+	}
+    }
+  this->UpdateProgress(0.99);
+  if (this->ComputeZScore>0)
+    this->ComputeTmapToZScoreConversion(outp);
+  this->UpdateProgress(1.0);
+
+}
+
+void vtkpxComputeTmap::ComputeTmapToZScoreConversion(vtkImageData* tmap)
+{
+  if (this->OutputZScore!=NULL)
+    this->OutputZScore->Delete();
+
+  int dof=  this->NumberOfSamples1+this->NumberOfSamples2-2;
+
+  this->OutputZScore=vtkpxComputeTmap::TmapToZScoreConversion(tmap,dof,this->ScaleFactor);
+}
+
+vtkImageData* vtkpxComputeTmap::TmapToZScoreConversion(vtkImageData* tmap,int dof,double scale)
+{
+  vtkImageData* out=vtkImageData::New();
+  out->CopyStructure(tmap);
+  out->AllocateScalars();
+
+  vtkDataArray* tval=tmap->GetPointData()->GetScalars();
+  vtkDataArray* zval=out->GetPointData()->GetScalars();
+
+  int nt=tval->GetNumberOfTuples();
+
+
+  for (int i=0;i<nt;i++)
+    {
+      double t=tval->GetComponent(i,0)/scale;
+      double factor=1.0;
+      if (t<0.0)
+	{
+	  t=-t;
+	  factor=-1.0;
+	}
+      double p=vtkpxMath::TtestToPvalue(t,dof);
+      double z=factor*vtkpxMath::PvalueToZscore(p);
+      zval->SetComponent(i,0,z);
+    }
+
+  return out;
+}
+
+vtkImageData* vtkpxComputeTmap::TmapToPvalueConversion(vtkImageData* tmap,int dof,double scale)
+{
+  vtkImageData* out=vtkImageData::New();
+  out->CopyStructure(tmap);
+  out->AllocateScalars();
+
+  vtkDataArray* tval=tmap->GetPointData()->GetScalars();
+  vtkDataArray* pval=out->GetPointData()->GetScalars();
+
+  int nt=tval->GetNumberOfTuples();
+
+
+  for (int i=0;i<nt;i++)
+    {
+      double t=tval->GetComponent(i,0)/scale;
+      double factor=1.0;
+      if (t<0.0)
+	{
+	  t=-t;
+	  factor=-1.0;
+	}
+      double p=vtkpxMath::TtestToPvalue(t,dof);
+      pval->SetComponent(i,0,p);
+    }
+
+  return out;
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxComputeTmap.h b/bioimagesuite30_src/Imaging/vtkpxComputeTmap.h
new file mode 100644
index 0000000..7770395
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxComputeTmap.h
@@ -0,0 +1,147 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxComputeTmap.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 19:05:20 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxComputeTmap -- compute a tmap from two input images and two input variances
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxComputeTmap_h
+#define __vtkpxComputeTmap_h
+
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+
+class vtkpxComputeTmap : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxComputeTmap *New();
+  vtkTypeMacro(vtkpxComputeTmap,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set value of scalefactor to multiply t-values
+  vtkGetMacro(ScaleFactor,float);
+  vtkSetMacro(ScaleFactor,float);
+
+  // Description:
+  // Input2 -- second input to compare with input
+  vtkSetObjectMacro(Input2,vtkImageData);
+  vtkGetObjectMacro(Input2,vtkImageData);
+
+  // Description:
+  // Input StandardDeviation , i.e. variance of first input 
+  vtkSetObjectMacro(InputStandardDeviation,vtkImageData);
+  vtkGetObjectMacro(InputStandardDeviation,vtkImageData);
+
+  // Description:
+  // Input StandardDeviation2 , i.e. variance of second input 
+  vtkSetObjectMacro(InputStandardDeviation2,vtkImageData);
+  vtkGetObjectMacro(InputStandardDeviation2,vtkImageData);
+
+
+  // Description:
+  // Set ScannerIndex of Fitting 
+  vtkSetClampMacro(NumberOfInputs,int,1,2);
+  vtkGetMacro(NumberOfInputs,int);
+
+  // Description:
+  // Set Number Of Samples 
+  vtkSetMacro(NumberOfSamples1, int);
+  vtkGetMacro(NumberOfSamples1, int);
+
+  vtkSetMacro(NumberOfSamples2, int);
+  vtkGetMacro(NumberOfSamples2, int);
+
+  // Description:
+  // Get "Gaussianized" output
+  vtkGetObjectMacro(OutputZScore,vtkImageData);
+
+// Description:
+  // Set Number Of Samples 
+  vtkSetClampMacro(ComputeZScore, int,0,1);
+  vtkGetMacro(ComputeZScore, int);
+
+
+  // Description:
+  // Convert ZScore to TMap
+  static vtkImageData* TmapToZScoreConversion(vtkImageData* tmap,int ndof,double scale=1.0);
+  static vtkImageData* TmapToPvalueConversion(vtkImageData* tmap,int dof,double scale=1.0);
+
+protected:
+
+  vtkpxComputeTmap();
+  virtual ~vtkpxComputeTmap();
+  vtkpxComputeTmap(const vtkpxComputeTmap&) {};
+  void operator=(const vtkpxComputeTmap&) {};
+
+  void ExecuteInformation();
+  void SimpleExecute(vtkImageData* inp,vtkImageData* outp);
+
+  float       ScaleFactor;
+  int         NumberOfInputs;
+  int         NumberOfSamples1;
+  int         NumberOfSamples2;
+  int         ComputeZScore;
+
+  vtkImageData* Input2;
+  vtkImageData* InputStandardDeviation;
+  vtkImageData* InputStandardDeviation2;
+  vtkImageData* OutputZScore;
+
+  void ComputeTmapToZScoreConversion(vtkImageData* tmap);
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxCreateCheckerBoardImage.cpp b/bioimagesuite30_src/Imaging/vtkpxCreateCheckerBoardImage.cpp
new file mode 100644
index 0000000..0e5a66c
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxCreateCheckerBoardImage.cpp
@@ -0,0 +1,248 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCreateCheckerBoardImage.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:22:26 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxCreateCheckerBoardImage.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxUtil.h"
+
+//------------------------------------------------------------------------------
+vtkpxCreateCheckerBoardImage* vtkpxCreateCheckerBoardImage::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxCreateCheckerBoardImage");
+  if(ret)
+    {
+    return (vtkpxCreateCheckerBoardImage*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxCreateCheckerBoardImage;
+}
+
+// Construct object with no children.
+vtkpxCreateCheckerBoardImage::vtkpxCreateCheckerBoardImage()
+{
+  this->NormalizeImages=1;
+  this->Input2=NULL;
+  this->SquareSize=8;
+}
+
+vtkpxCreateCheckerBoardImage::~vtkpxCreateCheckerBoardImage()
+{
+  this->SetInput2(NULL);
+}
+
+//------------------------------------------------------------------------------
+void vtkpxCreateCheckerBoardImage::ComputeStepBounds(vtkImageData* image,double range[2],int mode)
+{
+  vtkDataArray* scal=image->GetPointData()->GetScalars();
+  scal->GetRange(range);
+  
+  if (mode==0)
+    return;
+
+  int n=scal->GetNumberOfTuples(),inc=1;
+  if (n>133)
+    inc=int(n/133);
+
+  double mean=0.0,mean2=0.0;
+  int num=0;
+  for (int i=0;i<n;i+=inc)
+    {
+      double v=scal->GetComponent(i,0);
+      if (v!=0.0)
+	{
+	  mean+=v;
+	  mean2+=v*v;
+	  ++num;
+	}
+    }
+
+  if (num==0)
+    return;
+
+  mean/=double(num);
+  mean2/=double(num);
+  double std=sqrt(mean2-mean*mean);
+
+  range[0]=Frange(mean-3.0*std,range[0],range[1]-1.0);
+  range[1]=Frange(mean+3.0*std,range[0]+1.0,range[1]);
+}
+//------------------------------------------------------------------------------
+double vtkpxCreateCheckerBoardImage::ComputeAnatomicalVoxelValue(double vox,double range0,double range1,
+								double min,double max)
+{
+  
+  if (vox<=range0)
+    return min;
+  if (vox>=range1)
+    return max;
+
+  return min+(max-min)/(range1-range0)*(vox-range0);
+
+}
+//------------------------------------------------------------------------------
+
+void vtkpxCreateCheckerBoardImage::SimpleExecute(vtkImageData* i1,vtkImageData* o1)
+{
+  vtkImageData *input[2];
+  input[0]=this->GetImageDataInput(0);
+  input[1]=this->GetInput2();
+  vtkImageData *output=this->GetOutput();
+
+  if (input[0]==NULL || input[1]==NULL)
+      {
+	vtkErrorMacro(<<"No input images!");
+	return;
+      }
+
+
+  int dim[3];     input[0]->GetDimensions(dim);
+  int dim2[3];    input[1]->GetDimensions(dim2);
+
+
+  int diff=0;
+  int ia;
+  for (ia=0;ia<=2;ia++)
+    diff+=abs(dim[ia]-dim2[ia]);
+  if (diff>0)
+    {
+      vtkErrorMacro(<<"Images Have Different Dimensions\n");
+      return;
+    }
+
+  // On To Merge
+
+  this->UpdateProgress(0.05);
+
+  double range[2][2];
+
+  for (ia=0;ia<=1;ia++)
+    {
+      double r[2];
+      this->ComputeStepBounds(input[ia],r,this->NormalizeImages);
+      range[ia][0]=r[0];
+      range[ia][1]=r[1];
+      if (range[ia][0]==range[ia][1])
+	range[ia][1]+=1.0;
+    }
+
+  int numpixels=dim[0]*dim[1];  
+  
+  output->SetSpacing(input[0]->GetSpacing());
+  output->SetOrigin(input[0]->GetOrigin());
+  output->SetScalarType(input[0]->GetScalarType());
+  output->SetNumberOfScalarComponents(1);
+  output->SetDimensions(input[0]->GetDimensions());
+  output->SetWholeExtent(input[0]->GetWholeExtent());
+  output->AllocateScalars();
+  vtkDataArray* outScalars=output->GetPointData()->GetScalars();
+  
+  int odd[3],count[3];
+  
+  odd[0]=0;  count[0]=0;
+  for (int sl=0;sl<dim[2];sl++)
+    {
+      int offset=sl*numpixels;
+      odd[1]=0;  count[1]=0;
+      
+      for (int iy=0;iy<dim[1];iy++)
+	{
+	  int offset2=offset+iy*dim[0];
+	  odd[2]=0;  count[2]=0;
+	  
+	  for (int ix=0;ix<dim[0];ix++)
+	    {
+	      
+	      int sum=odd[0]+odd[1]+odd[2];
+	      int imgno=1;
+	      if (sum == 0 || sum== 2)
+		imgno=0;
+	      
+	      double vc=input[imgno]->GetPointData()->GetScalars()->GetComponent(ix+offset2,0);
+	      int c=(int)this->ComputeAnatomicalVoxelValue(vc,range[imgno][0],range[imgno][1],0,255);
+	      outScalars->SetComponent(ix+offset2,0,double(c));
+	      
+	      ++count[2];
+	      if (count[2]==this->SquareSize)
+		{
+		  count[2]=0;
+		  odd[2]=1-odd[2];
+		}
+	    }
+	  
+	  ++count[1];
+	  if (count[1]==this->SquareSize)
+	    {
+	      count[1]=0;
+	      odd[1]=1-odd[1];
+	    }
+	}
+      
+      ++count[0];
+      if (count[0]==this->SquareSize)
+	{
+	  count[0]=0;
+	  odd[0]=1-odd[0];
+	}
+      
+      
+      double pog=double(sl)/double(dim[2]);
+      this->UpdateProgress(pog);	
+    }
+
+  this->UpdateProgress(1.0);
+}
+//------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxCreateCheckerBoardImage.h b/bioimagesuite30_src/Imaging/vtkpxCreateCheckerBoardImage.h
new file mode 100644
index 0000000..755c84e
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxCreateCheckerBoardImage.h
@@ -0,0 +1,117 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCreateCheckerBoardImage.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:23:09 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+// .NAME vtkpxCreateCheckerBoardImage - creates a checker board image 
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// .SECTION See Also
+//  vtkpxProcessFmri
+
+
+#ifndef __vtkpxCreateCheckerBoardImage_h
+#define __vtkpxCreateCheckerBoardImage_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkTransform;
+class vtkAbstractTransform;
+
+class vtkpxCreateCheckerBoardImage : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxCreateCheckerBoardImage *New();
+  vtkTypeMacro(vtkpxCreateCheckerBoardImage,vtkpxSimpleImageToImageFilter);
+
+  // Description: 
+  // Set/Get the Field Map Image 
+  vtkSetObjectMacro(Input2, vtkImageData);
+  vtkGetObjectMacro(Input2, vtkImageData);
+
+  // Description:
+  // Set Spacing 
+  vtkSetMacro(SquareSize,int);
+  vtkGetMacro(SquareSize,int);
+
+  // Description:
+  // Normalize Intensity
+  vtkSetClampMacro(NormalizeImages,int,0,1);
+  vtkGetMacro(NormalizeImages,int);
+
+
+protected:
+
+  vtkpxCreateCheckerBoardImage();
+  virtual ~vtkpxCreateCheckerBoardImage();
+  vtkpxCreateCheckerBoardImage(const vtkpxCreateCheckerBoardImage&) {};
+  void operator=(const vtkpxCreateCheckerBoardImage&) {};
+
+  virtual void SimpleExecute(vtkImageData*,vtkImageData*);
+
+
+  vtkImageData* Input2;
+  int SquareSize;
+  int NormalizeImages;
+
+  void ComputeStepBounds(vtkImageData* image,double range[2],int mode);
+  double ComputeAnatomicalVoxelValue(double vox,double range0,double range1,double min,double max);
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxCreateSyntheticFmri.cpp b/bioimagesuite30_src/Imaging/vtkpxCreateSyntheticFmri.cpp
new file mode 100644
index 0000000..d940c13
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxCreateSyntheticFmri.cpp
@@ -0,0 +1,508 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCreateSyntheticFmri.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/23 21:21:45 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxCreateSyntheticFmri.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkbisImageReslice.h"
+#include "vtkpxUtil.h"
+#include "vtkAbstractTransform.h"
+#include "vtkTransform.h"
+#include "vtkGeneralTransform.h"
+#include "math.h"
+#include "vtkPlaneSource.h"
+#include "vtkAppendPolyData.h"
+#include "vtkPolyData.h"
+#include "vtkbisImageReslice.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageExtractComponents.h"
+//------------------------------------------------------------------------------
+vtkpxCreateSyntheticFmri* vtkpxCreateSyntheticFmri::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxCreateSyntheticFmri");
+  if(ret)
+    {
+    return (vtkpxCreateSyntheticFmri*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxCreateSyntheticFmri;
+}
+
+// Construct object with no children.
+vtkpxCreateSyntheticFmri::vtkpxCreateSyntheticFmri()
+{
+  this->ScaleFactor=0.1;
+  this->NumberOfFrames=2;
+  this->BlockPeriod=1;
+  this->ActivationMap=NULL;
+}
+// ----------------------------------------------------------------------------
+vtkpxCreateSyntheticFmri::~vtkpxCreateSyntheticFmri()
+{
+  if (this->ActivationMap!=NULL)
+    {
+      this->ActivationMap->UnRegister(this);
+      this->ActivationMap=NULL;
+    }
+
+}
+// --------------------------------------------------------------------------------------
+// New Code 
+// --------------------------------------------------------------------------------------
+
+void vtkpxCreateSyntheticFmri::ExecuteInformation()
+{
+  vtkImageData *input=this->GetImageDataInput(0);
+  if (input==NULL || this->ActivationMap == NULL )
+    {
+      vtkErrorMacro(<<"No Input or no Activation Data !!");
+      return;
+    }
+
+  vtkImageData *output=this->GetOutput();
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  output->SetNumberOfScalarComponents(this->NumberOfFrames);
+
+}
+
+// ----------------------------------------------------------------------------
+void vtkpxCreateSyntheticFmri::SimpleExecute(vtkImageData*,vtkImageData*)
+{
+
+  if (this->GetImageDataInput(0)==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+
+  if (this->ActivationMap==NULL)
+    {
+      vtkErrorMacro(<<"No Activation Map\n Exiting\n");
+      return;
+    }
+
+
+  vtkImageData* input=this->GetImageDataInput(0);
+
+  // Check Dimensions to make sure all phase images have the same dimensions
+  // -----------------------------------------------------------------------
+  int dim[3];
+  input->GetDimensions(dim);
+
+  int dim_1[3];
+  this->ActivationMap->GetDimensions(dim_1);
+  int sum=0;
+  for (int kk=0;kk<=2;kk++)
+    sum+=abs(dim_1[kk]-dim[kk]);
+  if (sum!=0)
+    {
+      vtkErrorMacro(<<"Activation Map and Input Image have different Dimensions !!");
+      return;
+    }
+  
+  
+  vtkDebugMacro(<< "Creating Output\n" <<  "Dimensions " << dim[0] <<","<< dim[1] <<","<< dim[2] << "nf=" << this->NumberOfFrames << "\n");
+  
+  vtkImageData* output=this->GetOutput();
+  output->SetSpacing(input->GetSpacing());
+  output->SetOrigin(input->GetOrigin());
+  output->SetScalarType(input->GetScalarType());
+  output->SetDimensions(input->GetDimensions());
+  output->SetWholeExtent(input->GetWholeExtent());
+  output->SetNumberOfScalarComponents(this->NumberOfFrames);
+  output->AllocateScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+
+  int slicesize=dim[0]*dim[1];
+  int activation=0,count=0;
+  static int count2=0;
+  int tenth=this->NumberOfFrames*dim[0]*dim[1]*dim[2]/10;
+  this->UpdateProgress(0.0);
+  float pog=0.0;
+
+  for (int f=0;f<this->NumberOfFrames;f++)
+    {
+      for (int k=0;k<dim[2];k++)
+	for (int i=0;i<dim[0];i++)
+	  for (int j=0;j<dim[1];j++)
+	    {
+	      int pixel=k*slicesize + j*dim[0] + i;
+	      
+	      float oldintensity=input->GetScalarComponentAsDouble(i,j,k,0);
+	      float tmapvalue=this->ActivationMap->GetScalarComponentAsDouble(i,j,k,0)*this->ScaleFactor;
+	      float newintensity=(1.0+float(activation)*tmapvalue)*oldintensity;
+	      if (newintensity<0.0)
+		newintensity=0.0;
+	      out->SetComponent(pixel,f,newintensity);
+
+	      ++count2;
+	      if (count2==tenth)
+		{
+		  pog+=0.1;
+		  this->UpdateProgress(pog);
+		  count2=0;
+		}
+
+	    }
+      ++count;
+      if (count==this->BlockPeriod)
+	{
+	  count=0;
+	  activation=1-activation;
+	}
+    }
+}
+
+// --------------------------------------------------------------------------------------
+//   Tmap Comparison Stuff 
+// --------------------------------------------------------------------------------------
+
+int vtkpxCreateSyntheticFmri::DoROCAnalysis(vtkImageData* input,
+					    vtkImageData* roi_img,
+					    vtkFloatArray* tvaluesin,
+					    vtkFloatArray* tripletsout,
+					    float ignore)
+
+{
+  if (input==NULL || roi_img==NULL || tvaluesin==NULL || tripletsout==NULL )
+    return 0;
+
+  int numtests=tvaluesin->GetNumberOfTuples();
+  tripletsout->SetNumberOfComponents(4);
+  tripletsout->SetNumberOfTuples(numtests);
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* roi=roi_img->GetPointData()->GetScalars();
+
+  int np1=inp->GetNumberOfTuples();
+  int np2=roi->GetNumberOfTuples();
+
+  if (np1!=np2)
+    {
+      fprintf(stderr,"Different Number Of Scalars\n");
+      return 0;
+    }
+
+  for (int ia=0;ia<4;ia++)
+    tripletsout->FillComponent(ia,0.0);
+
+  
+  for (int test=0;test<numtests;test++)
+    {
+      float threshold=tvaluesin->GetComponent(test,0);
+      int   numtrue=0,totalnumtrue=0,numfalse=0,totalnumfalse=0;
+
+      for (int pixel=0;pixel<np1;pixel++)
+	{
+	  float act=inp->GetComponent(pixel,0);
+	  float flag=roi->GetComponent(pixel,0);
+	  
+	  if (act != ignore ) 
+	    {
+	      if (flag>0)
+		++totalnumtrue;
+	      else
+		++totalnumfalse;
+	      
+	      if (fabs(act)>threshold)
+		{
+		  if (flag>0)
+		    ++numtrue;
+		  else
+		    ++numfalse;
+		}
+	    } 
+	}
+      
+      float truepos=100.0*float(numtrue)/float(totalnumtrue);
+      float falsepos=100.0*float(numfalse)/float(totalnumfalse);
+      float fraction=100.0*float(totalnumtrue)/float(totalnumtrue+totalnumfalse);
+      tripletsout->SetComponent(test,0,threshold);
+      tripletsout->SetComponent(test,1,truepos);
+      tripletsout->SetComponent(test,2,falsepos);
+      tripletsout->SetComponent(test,3,fraction);
+      //fprintf(stderr,"Np1=%d totalnumtrue=%d totalnumfalse=%d numtrue=%d numfalse=%d\n",
+      //np1,totalnumtrue,totalnumfalse,numtrue,numfalse);
+    }
+
+  
+  return 1;
+  
+}
+
+// --------------------------------------------------------------------------------------
+//   Smart Reslice Stuff 
+// --------------------------------------------------------------------------------------
+int vtkpxCreateSyntheticFmri::ComputeResliceTransformation(vtkTransform* trans,
+							   vtkImageData* inputImage,
+							   float offsetx,float offsety,float offsetz,
+							   int   dimx,int dimy,int dimz,
+							   float fovx,float fovy,float slicespacing,
+							   float anglex,float angley,float anglez)
+{
+
+  if (trans==NULL || inputImage==NULL)
+    return 0;
+
+
+  double sp[3],ori[3];
+  int dim[3];
+
+  inputImage->GetSpacing(sp);
+  inputImage->GetOrigin(ori);
+  inputImage->GetDimensions(dim);
+
+  double cent[3];
+  for (int ia=0;ia<=2;ia++)
+    cent[ia]=ori[ia]+float(dim[ia])*sp[ia]*0.5;
+
+  fprintf(stderr,"Center = %.1f %.1f %.1f\n",cent[0],cent[1],cent[2]);
+  fprintf(stderr,"Angles = %.1f %.1f %.1f\n",anglex,angley,anglez);
+  fprintf(stderr,"offsets = %.1f %.1f %.1f\n",offsetx,offsety,offsetz);
+
+  trans->PostMultiply();
+  trans->Identity();
+
+  trans->Translate(-cent[0],-cent[1],-cent[2]);
+  trans->RotateX(anglex);
+  trans->RotateY(angley);
+  trans->RotateZ(anglez);
+  trans->Translate(offsetx,offsety,offsetz);
+  trans->Translate(cent[0],cent[1],cent[2]);
+  
+  for(int i=0;i<=3;i++)
+    {
+      for (int j=0;j<=3;j++)
+	fprintf(stderr,"%6.2f ",trans->GetMatrix()->GetElement(i,j));
+      fprintf(stderr,"\n");
+    }
+
+
+  return 1;
+}
+// --------------------------------------------------------------------------------------
+int vtkpxCreateSyntheticFmri::ResliceImageUsingOffsets(vtkImageData* inputImage,
+						       vtkImageData* outputImage,
+						       vtkTransform* trans,
+						       int dimx,int dimy,int dimz,
+						       float fovx,float fovy,float slicespacing,
+						       float slicethickness,
+						       int interpolation_mode)
+{
+  if (trans==NULL || inputImage==NULL)
+    return 0;
+
+
+  double sp[3],ori[3];
+  int dim[3];
+
+  inputImage->GetSpacing(sp);
+  inputImage->GetOrigin(ori);
+  inputImage->GetDimensions(dim);
+
+  double cent[3];
+  for (int ia=0;ia<=2;ia++)
+    cent[ia]=ori[ia]+float(dim[ia])*sp[ia]*0.5;
+
+  float cx=fovx*10.0*0.5;
+  float xsp=fovx*10.0/float(dimx);
+
+  float cy=10.0*fovy*0.5;
+  float ysp=10.0*fovy/float(dimy);
+  
+  float zl= 0.5* float(dimz-1) * slicespacing;
+
+  double p[3];
+  p[0]=cent[0]-cx;
+  p[1]=cent[1]-cy;
+  p[2]=cent[2]-zl;
+
+  double sigma[3],radius[3],ratio[3];
+  ratio[0]=(xsp/sp[0]);
+  ratio[1]=(ysp/sp[1]);
+  ratio[2]=(slicethickness/sp[2]);
+
+  for (int i=0;i<=2;i++)
+    {
+      sigma[i] =10.0;
+      radius[i]=0.5*(ratio[i]/sigma[i]);
+    }
+
+
+  vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+  smooth->SetInput(inputImage);
+  smooth->SetStandardDeviations(sigma);
+  smooth->SetRadiusFactors(radius);
+
+
+  vtkbisImageReslice* resl=vtkbisImageReslice::New(); resl->OptimizationOff();
+  resl->SetInput(smooth->GetOutput());
+  resl->SetInterpolationMode(interpolation_mode);
+  resl->SetResliceTransform(trans);
+  resl->SetOutputSpacing(xsp,ysp,slicespacing);
+  resl->SetOutputOrigin(p);
+  resl->SetOutputExtent(0,dimx-1,0,dimy-1,0,dimz-1);
+  resl->Update();
+  outputImage->ShallowCopy(resl->GetOutput());
+  resl->Delete();
+
+  return 1;
+}
+
+// --------------------------------------------------------------------------------------
+int vtkpxCreateSyntheticFmri::CreateReferenceImageGeometry(vtkImageData* inputImage,
+							   vtkImageData* outputReference,
+							   int dimx,int dimy,int dimz,
+							   float fovx,float fovy,float slicespacing)
+{
+  if (inputImage==NULL)
+    return 0;
+
+
+  double sp[3],ori[3];
+  int dim[3];
+
+  inputImage->GetSpacing(sp);
+  inputImage->GetOrigin(ori);
+  inputImage->GetDimensions(dim);
+
+  double cent[3];
+  for (int ia=0;ia<=2;ia++)
+    cent[ia]=ori[ia]+float(dim[ia])*sp[ia]*0.5;
+
+  fprintf(stderr,"Offset Center = %.1f %.1f %.1f\n",cent[0],cent[1],cent[2]);
+
+  float cx=fovx*10.0*0.5;
+  float xsp=fovx*10.0/float(dimx);
+
+  float cy=10.0*fovy*0.5;
+  float ysp=10.0*fovy/float(dimy);
+  
+  float zl= 0.5* float(dimz-1) * slicespacing;
+
+  double p[3];
+  p[0]=cent[0]-cx;
+  p[1]=cent[1]-cy;
+  p[2]=cent[2]-zl;
+
+
+  outputReference->Initialize();
+  outputReference->SetOrigin(p);
+  outputReference->SetSpacing(xsp,ysp,slicespacing);
+  outputReference->SetDimensions(dimx,dimy,dimz);
+  outputReference->SetWholeExtent(0,dimx-1,0,dimy-1,0,dimz-1);
+  outputReference->SetScalarType(VTK_CHAR);
+  outputReference->SetNumberOfScalarComponents(1);
+  outputReference->AllocateScalars();
+
+
+  return 1;
+}
+// --------------------------------------------------------------------------------------
+int vtkpxCreateSyntheticFmri::CreatePolyData(vtkTransform* trans,
+					     vtkImageData* inputImage,
+					     vtkPolyData* polydata,
+					     int xr,int yr,
+					     int   dimx,int dimy,int dimz,
+					     float fovx,float fovy,float slicespacing)
+{
+
+  if (trans==NULL || inputImage==NULL || polydata == NULL)
+    return 0;
+
+  double  sp[3],ori[3];
+  int dim[3];
+
+  inputImage->GetSpacing(sp);
+  inputImage->GetOrigin(ori);
+  inputImage->GetDimensions(dim);
+
+  double cent[3];
+  for (int ia=0;ia<=2;ia++)
+    cent[ia]=ori[ia]+float(dim[ia])*sp[ia]*0.5;
+
+  float width = fovx*10.0;
+  float height= fovy*10.0;
+
+  float cx=width*0.5;
+  float xsp=width/dimx;
+  float cy=height*0.5;
+  float ysp=height/dimy;
+  float zl= 0.5* float(dimz-1) * slicespacing;
+
+
+  vtkAppendPolyData* append=vtkAppendPolyData::New();
+  
+  for (int sl=0;sl<dimz;sl++)
+    {
+      vtkPlaneSource* pl=vtkPlaneSource::New();
+      pl->SetResolution(xr,yr);
+      pl->SetOrigin(cent[0]-cx    ,cent[1]-cy    ,cent[2]-zl + sl*slicespacing);
+      pl->SetPoint1(cent[0]+cx-xsp,cent[1]-cy    ,cent[2]-zl + sl*slicespacing);
+      pl->SetPoint2(cent[0]-cx    ,cent[1]+cy-ysp,cent[2]-zl + sl*slicespacing);
+      pl->Update();
+      append->AddInput(pl->GetOutput());
+      pl->Delete();
+    }
+  append->Update();
+  polydata->DeepCopy(append->GetOutput());
+  append->Delete();
+  return 1;
+}
+  
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxCreateSyntheticFmri.h b/bioimagesuite30_src/Imaging/vtkpxCreateSyntheticFmri.h
new file mode 100644
index 0000000..9daa523
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxCreateSyntheticFmri.h
@@ -0,0 +1,155 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCreateSyntheticFmri.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxCreateSyntheticFmri -- compute Field Map from succesive phase images 
+// .SECTION Description
+
+#ifndef __vtkpxCreateSyntheticFmri_h
+#define __vtkpxCreateSyntheticFmri_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkPolyData;
+class vtkAbstractTransform;
+class vtkTransform;
+
+class vtkpxCreateSyntheticFmri : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxCreateSyntheticFmri *New();
+  vtkTypeMacro(vtkpxCreateSyntheticFmri,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set the number of frames 
+  vtkGetMacro(NumberOfFrames,int);
+  vtkSetClampMacro(NumberOfFrames,int,2,200);
+
+  // Description:
+  // Set value of the block period e.g 8on/8off
+  vtkGetMacro(BlockPeriod,int);
+  vtkSetClampMacro(BlockPeriod,int,1,100);
+
+  // Description:
+  // Set value of scale factor to add step change on on blocks
+  vtkGetMacro(ScaleFactor,float);
+  vtkSetClampMacro(ScaleFactor,float,0.0001,1.0);
+
+  // Description: 
+  // Set/Get the Activation Image 
+  vtkSetObjectMacro(ActivationMap, vtkImageData);
+  vtkGetObjectMacro(ActivationMap, vtkImageData);
+
+  // Description:
+  // Perform ROC Analysis on Tmaps to find true positives and false positives 
+  static int DoROCAnalysis(vtkImageData* input1,
+			   vtkImageData* trueinput,
+			   vtkFloatArray* tvaluesin,
+			   vtkFloatArray* tripletsout,
+			   float ignore=-32000);
+
+
+  // Description:
+  // Compute Reslice Transformation given Reslice Set and Reslice Image 
+  static int ComputeResliceTransformation(vtkTransform* trans,
+					  vtkImageData* inputImage,
+					  float offsetx,float offsety,float offsetz,
+					  int   dimx,int dimy,int dimz,
+					  float fovx,float fovy,float slicespacing,
+					  float anglex,float angley,float anglez);  
+  
+  static int  ResliceImageUsingOffsets(vtkImageData* inputImage,
+				       vtkImageData* outputImage,
+				       vtkTransform* trans,
+				       int dimx,int dimy,int dimz,
+				       float fovx,float fovy,float slicespacing,
+				       float slicethickness,
+				       int interpolation_mode);
+
+  static int CreateReferenceImageGeometry(vtkImageData* inputImage,
+					  vtkImageData* outputReference,
+					  int dimx,int dimy,int dimz,
+					  float fovx,float fovy,float slicespacing);
+
+  static int CreatePolyData(vtkTransform* trans,
+			    vtkImageData* inputImage,
+			    vtkPolyData* polydata,
+			    int xr,int yr,
+			    int   dimx,int dimy,int dimz,
+			    float fovx,float fovy,float slicespacing);
+  
+  
+protected:
+
+  vtkpxCreateSyntheticFmri();
+  virtual ~vtkpxCreateSyntheticFmri();
+  vtkpxCreateSyntheticFmri(const vtkpxCreateSyntheticFmri&) {};
+  void operator=(const vtkpxCreateSyntheticFmri&) {};
+
+  void SimpleExecute(vtkImageData* input,vtkImageData *output);  
+  void ExecuteInformation();
+
+  float                ScaleFactor;
+  int                  NumberOfFrames;
+  int                  BlockPeriod;
+  vtkImageData* ActivationMap;
+
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxCreateThickSlices.cpp b/bioimagesuite30_src/Imaging/vtkpxCreateThickSlices.cpp
new file mode 100644
index 0000000..8ade927
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxCreateThickSlices.cpp
@@ -0,0 +1,187 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCreateThickSlices.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkpxCreateThickSlices.h"
+#include <vtkDataArray.h>
+#include <vtkImageData.h>
+
+//------------------------------------------------------------------------------
+vtkpxCreateThickSlices* vtkpxCreateThickSlices::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxCreateThickSlices");
+  if(ret)
+    {
+    return (vtkpxCreateThickSlices*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxCreateThickSlices;
+}
+
+// Construct object with no children.
+vtkpxCreateThickSlices::vtkpxCreateThickSlices()
+{
+  this->InPlaneSample=1;
+  this->SliceSample=1;
+  this->SumOnly=0;
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxCreateThickSlices::ExecuteInformation()
+{
+  vtkImageData *input=this->GetImageDataInput(0);
+
+  if (input==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image !!");
+	return;
+      }
+
+  vtkImageData *output=this->GetOutput();
+
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int wholeExtent[6];
+  input->GetWholeExtent( wholeExtent );
+
+  int dims[3];
+
+  dims[0] = int ( (wholeExtent[1] - wholeExtent[0] +1 ) / this->InPlaneSample);
+  dims[1] = int ( (wholeExtent[3] - wholeExtent[2] +1 ) / this->InPlaneSample);
+  dims[2] = int ( (wholeExtent[5] - wholeExtent[4] +1 ) / this->SliceSample);
+
+  wholeExtent[0] = 0;
+  wholeExtent[1] = dims[0] - 1;
+  wholeExtent[2] = 0;
+  wholeExtent[3] = dims[1] - 1;
+  wholeExtent[4] = 0;
+  wholeExtent[5] = dims[2] - 1;
+  output->SetWholeExtent( wholeExtent );
+}
+
+// ----------------------------------------------------------------------------
+
+void vtkpxCreateThickSlices::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  
+  // Create Output Array
+  // -------------------
+  int   dim[3]; input->GetDimensions(dim);
+  double sp[3];  input->GetSpacing(sp);
+  
+  dim[0]=int(dim[0]/this->InPlaneSample);
+  dim[1]=int(dim[1]/this->InPlaneSample);
+  dim[2]=int(dim[2]/this->SliceSample);
+  sp[0]=sp[0]*float(this->InPlaneSample);
+  sp[1]=sp[1]*float(this->InPlaneSample);
+  sp[2]=sp[2]*float(this->SliceSample);
+
+    
+  output->SetSpacing(sp);
+  output->SetOrigin(input->GetOrigin());
+  output->SetScalarType(input->GetScalarType());
+  output->SetNumberOfScalarComponents(input->GetNumberOfScalarComponents());
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  output->SetUpdateExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  output->AllocateScalars();
+
+  
+  float progress=0.0;
+  float dprog=1.0/float(output->GetNumberOfScalarComponents()*dim[2]);
+
+  float factor=1.0/float(this->SliceSample*this->InPlaneSample*this->InPlaneSample);
+  if (this->SumOnly==1)
+    factor=1.0;
+
+  for (int comp=0;comp<output->GetNumberOfScalarComponents();comp++)
+    {
+      for (int k=0;k<dim[2];k++)
+	{
+	  int kmin=k*this->SliceSample;
+	  int kmax=kmin+this->SliceSample;
+	  for (int j=0;j<dim[1];j++)
+	    {
+	      int jmin=j*this->InPlaneSample;
+	      int jmax=jmin+this->InPlaneSample;
+	      for (int i=0;i<dim[0];i++)
+		{
+		  int imin=i*this->InPlaneSample;
+		  int imax=imin+this->InPlaneSample;
+	      
+		  float sum=0.0;
+		  
+		  for (int ka=kmin;ka<kmax;ka++)
+		    for (int ja=jmin;ja<jmax;ja++)
+		      for (int ia=imin;ia<imax;ia++)
+			sum+=input->GetScalarComponentAsDouble(ia,ja,ka,comp);
+		  
+		  int index=k*dim[1]*dim[0]+j*dim[0]+i;
+		  output->GetPointData()->GetScalars()->SetComponent(index,comp,sum*factor);
+		}
+	    }
+	  progress+=dprog;
+	  this->UpdateProgress(progress);
+	  char line[100];
+	  sprintf(line,"prog=%f k=%d\n",progress,k);
+	  vtkDebugMacro(<<line);
+	}
+    }
+
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxCreateThickSlices.h b/bioimagesuite30_src/Imaging/vtkpxCreateThickSlices.h
new file mode 100644
index 0000000..aaf3e37
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxCreateThickSlices.h
@@ -0,0 +1,110 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCreateThickSlices.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxCreateThickSlices -- creates activation maps from raw fmri data
+// .SECTION Description
+// This class takes a number of fmri image series and a description of activations
+// and generates t-maps of the activation.
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxCreateThickSlices_h
+#define __vtkpxCreateThickSlices_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkPolyData;
+
+
+class vtkpxCreateThickSlices : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxCreateThickSlices *New();
+  vtkTypeMacro(vtkpxCreateThickSlices,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Sets the In Plane Sampling Level
+  vtkGetMacro(InPlaneSample,int);
+  vtkSetClampMacro(InPlaneSample,int,1,10);
+
+  // Description:
+  // Sets the Slice Sampling Level
+  vtkGetMacro(SliceSample,int);
+  vtkSetClampMacro(SliceSample,int,1,10);
+
+  // Description:
+  // Sets the Slice Sampling Level
+  vtkGetMacro(SumOnly,int);
+  vtkSetClampMacro(SumOnly,int,0,1);
+
+
+protected:
+
+  vtkpxCreateThickSlices();
+  vtkpxCreateThickSlices(const vtkpxCreateThickSlices&) {};
+  void operator=(const vtkpxCreateThickSlices&) {};
+
+  virtual void SimpleExecute(vtkImageData*,vtkImageData*);
+  void ExecuteInformation();
+
+  int         InPlaneSample;
+  int         SliceSample;
+  int         SumOnly;
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageAddGaussianNoise.cpp b/bioimagesuite30_src/Imaging/vtkpxImageAddGaussianNoise.cpp
new file mode 100644
index 0000000..3581e4b
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageAddGaussianNoise.cpp
@@ -0,0 +1,151 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageAddGaussianNoise.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxImageAddGaussianNoise.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+
+//------------------------------------------------------------------------------
+vtkpxImageAddGaussianNoise* vtkpxImageAddGaussianNoise::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageAddGaussianNoise");
+  if(ret)
+    {
+    return (vtkpxImageAddGaussianNoise*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageAddGaussianNoise;
+}
+
+// Construct object with no children.
+vtkpxImageAddGaussianNoise::vtkpxImageAddGaussianNoise()
+{
+  this->NoiseLevel=10.0;
+  this->ForcePositive=0;
+}
+// ----------------------------------------------------------------------------
+vtkpxImageAddGaussianNoise::~vtkpxImageAddGaussianNoise()
+{
+}
+// --------------------------------------------------------------------------------------
+float vtkpxImageAddGaussianNoise::GaussianRandom()
+{
+  static int iset=0;
+  static float gset;
+  float fac,rsq,v1,v2;
+
+  if  (iset == 0) 
+    {
+      do 
+	{
+	  v1=2.0*vtkMath::Random()-1.0;
+	  v2=2.0*vtkMath::Random()-1.0;
+	  rsq=v1*v1+v2*v2;
+	} 
+      while (rsq >= 1.0 || rsq == 0.0);
+      
+      fac=sqrt(-2.0*log(rsq)/rsq);
+      gset=v1*fac;
+      iset=1;
+      return v2*fac;
+    } 
+  else
+    {
+      iset=0;
+      return gset;
+    }
+}
+// --------------------------------------------------------------------------------------
+// New Code 
+// --------------------------------------------------------------------------------------
+void vtkpxImageAddGaussianNoise::SimpleExecute(vtkImageData* input,vtkImageData *output)
+{
+  output->DeepCopy(input);
+
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  int numtuples=out->GetNumberOfTuples();
+  int numframes=out->GetNumberOfComponents();
+
+  int tenth=int(numtuples/10);
+  int count=0;
+
+  this->UpdateProgress(0.02);
+
+  for (int vx=0;vx<numtuples;vx++)
+    {
+      for (int fr=0;fr<numframes;fr++)
+	{
+	  float vl=in->GetComponent(vx,fr);
+	  vl=vl+this->NoiseLevel*this->GaussianRandom();
+	  if (this->ForcePositive && vl<=0)
+	    vl=0.0;
+	  out->SetComponent(vx,fr,vl);
+	}
+      ++count;
+      if (count==tenth)
+	{
+	  this->UpdateProgress(float(vx)/float(numtuples));
+	  count=0;
+	}
+    }
+  this->UpdateProgress(1.0);
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageAddGaussianNoise.h b/bioimagesuite30_src/Imaging/vtkpxImageAddGaussianNoise.h
new file mode 100644
index 0000000..9bd86a9
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageAddGaussianNoise.h
@@ -0,0 +1,115 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageAddGaussianNoise.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageAddGaussianNoise -- compute Field Map from succesive phase images 
+// .SECTION Description
+// This class takes a number of MR phaseimages and a description of the TE times
+// and generates field maps.
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageAddGaussianNoise_h
+#define __vtkpxImageAddGaussianNoise_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkPolyData;
+class vtkAbstractTransform;
+class vtkTransform;
+
+class vtkpxImageAddGaussianNoise : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageAddGaussianNoise *New();
+  vtkTypeMacro(vtkpxImageAddGaussianNoise,vtkpxSimpleImageToImageFilter);
+
+
+  // Description:
+  // Set value of scalefactor to convert input phase values to radians
+  vtkGetMacro(NoiseLevel,float);
+  vtkSetClampMacro(NoiseLevel,float,0.0001,100.0);
+
+  // Description:
+  // Set value of scalefactor to convert input phase values to radians
+  vtkGetMacro(ForcePositive,int);
+  vtkSetClampMacro(ForcePositive,int,0,1);
+
+
+  // Description:
+  // Compute Normally Distributed Random Variable with mean 0 sigma=1
+  static float GaussianRandom();
+
+protected:
+
+  vtkpxImageAddGaussianNoise();
+  virtual ~vtkpxImageAddGaussianNoise();
+  vtkpxImageAddGaussianNoise(const vtkpxImageAddGaussianNoise&) {};
+  void operator=(const vtkpxImageAddGaussianNoise&) {};
+
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData *out);
+
+  float                NoiseLevel;
+  int                  ForcePositive;
+
+
+};
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageAddPhaseCorrection.cpp b/bioimagesuite30_src/Imaging/vtkpxImageAddPhaseCorrection.cpp
new file mode 100644
index 0000000..05c6691
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageAddPhaseCorrection.cpp
@@ -0,0 +1,745 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageAddPhaseCorrection.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/03/08 15:11:46 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include <math.h>
+#include "vtkpxImageAddPhaseCorrection.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxUtil.h"
+#include "vtkImageFFT.h"
+#include "vtkImageFourierCenter.h"
+#include "vtkImageRFFT.h"
+#include "vtkpxImageExtract.h"
+#include "vtkExtractVOI.h"
+#include "vtkDataArray.h"
+#include "vtkImageMagnitude.h"
+#include "vtkImageAppendComponents.h"
+#include "vtkpxImagePolarToEuclidean.h"
+//------------------------------------------------------------------------------
+vtkpxImageAddPhaseCorrection* vtkpxImageAddPhaseCorrection::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageAddPhaseCorrection");
+  if(ret)
+    {
+      return (vtkpxImageAddPhaseCorrection*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageAddPhaseCorrection;
+}
+//----------------------------------------------------------------------------
+vtkpxImageAddPhaseCorrection::vtkpxImageAddPhaseCorrection()
+{
+  this->PhaseOffset=0.0;
+  this->PhaseShift=0.0;
+  this->SingleValue=1;
+  this->PhaseOffsetArray=NULL;
+  this->PhaseShiftArray=NULL;
+}
+
+//----------------------------------------------------------------------------
+// This templated function executes the filter for any type of data.
+template <class T>
+static void vtkpxImageAddPhaseCorrectionExecute(vtkpxImageAddPhaseCorrection *self,
+					      vtkImageData *inData, T *inPtr,
+					      vtkImageData *outData, T *outPtr,
+					      int outExt[6], int id)
+{
+  int idxX, idxY, idxZ;
+  int maxC, maxX, maxY, maxZ;
+  vtkIdType inIncX, inIncY, inIncZ;
+  vtkIdType outIncX, outIncY, outIncZ;
+  unsigned long count = 0;
+  unsigned long target;
+  float  Theta, R , X , Y;
+  float PhaseOffset = self->GetPhaseOffset();
+  float PhaseShift  = self->GetPhaseShift();
+
+  int SingleValue=self->GetSingleValue();
+  vtkFloatArray* PhaseOffsetArray=NULL;
+  vtkFloatArray* PhaseShiftArray=NULL;
+
+  if (SingleValue==0)
+    {
+      PhaseOffsetArray=self->GetPhaseOffsetArray();
+      PhaseShiftArray=self->GetPhaseShiftArray();
+    }
+  
+  // find the region to loop over
+  maxC = inData->GetNumberOfScalarComponents();
+  maxX = outExt[1] - outExt[0]; 
+  maxY = outExt[3] - outExt[2]; 
+  maxZ = outExt[5] - outExt[4];
+  target = (unsigned long)((maxZ+1)*(maxY+1)/50.0);
+  target++;
+
+
+  // Get increments to march through data 
+  inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
+  outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
+
+  // Loop through ouput pixels
+
+  float addoffset=0.0;
+
+  float t_offset=PhaseOffset;
+  float t_shift=PhaseShift;
+
+  for (idxZ = 0; idxZ <= maxZ; idxZ++)
+    {
+      if (SingleValue==0)
+	{
+	  t_offset=PhaseOffsetArray->GetComponent(idxZ+outExt[4],0);
+	  t_shift=PhaseShiftArray->GetComponent(idxZ+outExt[4],0);
+	  fprintf(stderr,"Slice= %d (offset(odd,even)=%.2f shift(translation)=%.2f)\n",
+		  outExt[4]+idxZ,t_offset,t_shift);
+	}
+	
+
+      for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++)
+	{
+	  if (!id) 
+	    {
+	      if (!(count%target))
+		{
+		  self->UpdateProgress(count/(50.0*target));
+		}
+	      count++;
+	    }
+
+	  if ( !( (idxY + outExt[2]) & 1 ))
+	    addoffset=t_offset;
+	  else
+	    addoffset=0.0;
+
+	  addoffset+=t_shift*float(idxY+outExt[2]);
+
+	  for (idxX = 0; idxX <= maxX; idxX++)
+	    {
+	      // Pixel operation
+	      X = (float)(*inPtr);
+	      Y = (float)(inPtr[1]);
+
+	      Theta = atan2(Y, X);
+	      R = sqrt(X*X + Y*Y);
+	      
+	      Theta +=addoffset;
+	      
+	      X=R*cos(Theta);
+	      Y=R*sin(Theta);
+	      
+	      *outPtr = (T)(X);
+	      outPtr[1] = (T)(Y);
+	      inPtr += maxC;
+	      outPtr += maxC;
+	    }
+	  outPtr += outIncY;
+	  inPtr += inIncY;
+	}
+      outPtr += outIncZ;
+      inPtr += inIncZ;
+    }
+}
+
+//----------------------------------------------------------------------------
+void vtkpxImageAddPhaseCorrection::ThreadedExecute(vtkImageData *inData, 
+						 vtkImageData *outData,
+						 int outExt[6], int id)
+{
+  void *inPtr = inData->GetScalarPointerForExtent(outExt);
+  void *outPtr = outData->GetScalarPointerForExtent(outExt);
+  
+  vtkDebugMacro(<< "Execute: inData = " << inData 
+		<< ", outData = " << outData);
+  
+  // this filter expects that input is the same type as output.
+  if (inData->GetScalarType() != outData->GetScalarType())
+    {
+      vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType()
+      << ", must match out ScalarType " << outData->GetScalarType());
+      return;
+    }
+  
+  // input must have at least two components
+  if (inData->GetNumberOfScalarComponents() < 2)
+    {
+      vtkErrorMacro(<< "Execute: input does not have at least two components");
+      return;
+    }
+  
+  switch (inData->GetScalarType())
+    {
+      vtkTemplateMacro7(vtkpxImageAddPhaseCorrectionExecute, this, 
+			inData, (VTK_TT *)(inPtr), 
+			outData, (VTK_TT *)(outPtr), outExt, id);
+    default:
+      vtkErrorMacro(<< "Execute: Unknown ScalarType");
+      return;
+    }
+}
+
+void vtkpxImageAddPhaseCorrection::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkImageToImageFilter::PrintSelf(os,indent);
+  os << indent << "Phase Shift: " << this->PhaseShift << "\n";
+  os << indent << "Phase Offset: " << this->PhaseOffset << "\n";
+}
+
+//----------------------------------------------------------------------------
+float vtkpxImageAddPhaseCorrection::GetIntensitySum(vtkImageData* image,
+						    int slice,float topline)
+{
+
+  if (image==NULL)
+    return 0.0;
+
+  topline=Frange(topline,0,0.5);
+
+  int dim[3];
+  image->GetDimensions(dim);
+
+  float sum_in=0.0;
+  slice=Irange(slice,0,dim[2]-1);
+  
+  int ja=int(topline*float(dim[1]));
+  int jb=Irange(int((topline+0.5)*float(dim[1])),0,dim[1]);
+
+  for (int i=0;i<dim[0];i+=1)
+    for (int j=ja;j<jb;j+=1)
+      sum_in+=fabs(image->GetScalarComponentAsDouble(i,j,slice,0));
+
+  return sum_in;
+  
+}
+//----------------------------------------------------------------------------
+float vtkpxImageAddPhaseCorrection::ComputeCorrelationCoefficient(vtkDataArray* scal0,vtkDataArray* scal1,
+								  int debug)
+{
+  
+  int numscalars=scal0->GetNumberOfTuples();
+  int numscalars2=scal1->GetNumberOfTuples();
+  if (numscalars!=numscalars2)
+    {
+      fprintf(stderr,"Different num scalars %d %d\n",numscalars,numscalars2);
+      return 0.0;
+    }
+
+  float mean[2],var[2],sum[2],sum2[2],sumprod=0.0;
+  sum[0]=0.0; sum[1]=0.0; sum2[0]=0.0; sum2[1]=0.0;
+  
+  for (int i=0;i<numscalars;i++)
+    {
+      float v0=scal0->GetComponent(i,0);
+      sum[0]+=v0;
+      sum2[0]+=v0*v0;
+
+      float v1=scal1->GetComponent(i,0);
+      sum[1]+=v1;
+      sum2[1]+=v1*v1;
+
+      sumprod+=v0*v1;
+    }
+  
+
+  for (int j=0;j<=1;j++)
+    {
+      mean[j]=sum[j]/float(numscalars);
+      var[j] =Fmax(sum2[j]/float(numscalars)-mean[j]*mean[j],0.0001);
+    }
+
+  float covar=pow(sumprod/float(numscalars)-mean[0]*mean[1],float(2.0));
+  float covar2=covar/(var[0]*var[1]);
+
+  if (debug)
+    fprintf(stderr,"NumScalars = %d (mean,var = %.1f + %.1f, %.1f + %.1f covar=%.2f, ratio=%.2f\n",
+	    numscalars,mean[0],var[0],mean[1],var[1],covar,covar2);
+
+  return covar2;
+  
+}
+//----------------------------------------------------------------------------
+float vtkpxImageAddPhaseCorrection::ComputeSimilarity(vtkImageData *img,
+						      vtkImageData* ref,
+						      float shift,float offset,
+						      int mode,float topline,int dofft)
+{
+  mode=Irange(mode,0,1);
+
+  vtkImageFFT* fft=vtkImageFFT::New();
+  fft->SetDimensionality(2);
+  fft->SetInput(img);
+  
+  vtkpxImageAddPhaseCorrection* addphase=vtkpxImageAddPhaseCorrection::New();
+  if (dofft)
+    addphase->SetInput(fft->GetOutput());
+  else
+    addphase->SetInput(img);
+  addphase->SetPhaseShift(shift);
+  addphase->SetPhaseOffset(offset);
+	      
+  vtkImageRFFT* rft=vtkImageRFFT::New();
+  rft->SetDimensionality(2);
+  rft->SetInput(addphase->GetOutput());
+
+  vtkImageMagnitude* magn=vtkImageMagnitude::New();
+  magn->SetInput(rft->GetOutput());
+  magn->Update();
+
+  float d=0.0;
+
+  switch (mode)
+    {
+    case 1:
+      d=vtkpxImageAddPhaseCorrection::GetIntensitySum(magn->GetOutput(),
+						      0,topline);
+      break;
+
+    case 0:
+      d=vtkpxImageAddPhaseCorrection::ComputeCorrelationCoefficient(magn->GetOutput()->GetPointData()->GetScalars(),
+								    ref->GetPointData()->GetScalars(),0);
+      break;
+    }
+							  
+  magn->Delete();
+  rft->Delete();
+  addphase->Delete();
+  fft->Delete();
+	
+  return d;
+}
+//----------------------------------------------------------------------------
+float vtkpxImageAddPhaseCorrection::ComputeTopLine(vtkImageData* ref)
+{
+
+  float besttopline=0.25;
+  float best=GetIntensitySum(ref,0,besttopline);
+
+
+  float increment=0.1;
+  int   iter=0;
+
+
+  while (iter<20 && increment>0.001 && besttopline>=0.01 && besttopline<=0.49 )
+    {
+      int besttest=0;
+      float topline=besttopline;
+      
+      for (int test=-1;test<=1;test+=2)
+	{
+	  float testline  = topline + float (test)* increment;
+	  float d=GetIntensitySum(ref,0,testline);
+
+
+	  if ( d > best ) 
+	    {
+	      besttopline=testline;
+	      best=d;
+	      besttest=test;
+	      fprintf(stderr,"\t Testline=%6.3f (test=%d topline=%.4f) d=%.1f (best=%.1f) (incr=%.4f)\n",testline,
+		      test,topline,d,best,increment);
+	    }
+	}
+
+      if (besttest==0)
+	increment*=0.5;
+      
+      ++iter;
+    }
+      
+  besttopline=Frange(besttopline,0.0,0.499);
+  fprintf(stderr,"Bestline=%6.3f  bestd=%.3f (incr=%.4f)\n\n",besttopline,best,increment);
+  return besttopline;
+  
+}
+//----------------------------------------------------------------------------
+int vtkpxImageAddPhaseCorrection::OptimizeSimilarity(vtkImageData* image,
+						     vtkImageData* reference,
+						     vtkFloatArray* shiftScalars,
+						     vtkFloatArray* offsetScalars)
+
+{
+  static float dp[4][2] = { { -1.0,0.0 }, { 1.0,0.0 }, { 0.0,1.0}, { 0.0,-1.0} };
+
+  if (image==NULL || reference==NULL)
+    return 0;
+
+  int dim[3];
+  image->GetDimensions(dim);
+
+  vtkImageData* resl_ref=vtkImageData::New();
+  vtkpxUtil::EquiReslice(resl_ref,reference,image);
+  
+  shiftScalars->SetNumberOfComponents(1);
+  shiftScalars->SetNumberOfTuples(dim[2]);
+  shiftScalars->FillComponent(0,0.0);
+
+  offsetScalars->SetNumberOfComponents(1);
+  offsetScalars->SetNumberOfTuples(dim[2]);
+  offsetScalars->FillComponent(0,0.0);
+  
+
+  vtkpxImageExtract* extr=vtkpxImageExtract::New();
+  extr->SetInput(image);
+  extr->SetCurrentPlane(2);
+
+  vtkpxImageExtract* extr2=vtkpxImageExtract::New();
+  extr2->SetInput(resl_ref);
+  extr2->SetCurrentPlane(2);
+
+  for (int slice=0;slice<dim[2];slice++)
+    {
+      fprintf(stderr,"-----------------------------------\n Beginning Slice = %d\n",slice);
+      extr->SetSliceNo(slice);
+      extr->Update();
+      
+      extr2->SetSliceNo(slice);
+      extr2->Update();
+
+      float topline=ComputeTopLine(extr2->GetOutput());
+      float bestshift=0.0,bestoffset=0.0;
+
+      float best;
+      int iter;
+      float increment;
+      
+      iter=0;
+      increment=M_PI/16.0;
+
+      best=ComputeSimilarity(extr->GetOutput(),extr2->GetOutput(),
+			     bestshift,bestoffset,
+			     0,topline,1);
+
+      // Step 1 Optimize Shift for correlation coefficient
+      while (iter < 40 && increment> 0.001 )
+	{
+	  int besttest=-1;
+	  float shift=bestshift;
+
+	  for (int test=0;test<=1;test++)
+	    {
+	      
+	      float test_shift  = shift + dp[test][0]*increment;
+	      float d=ComputeSimilarity(extr->GetOutput(),extr2->GetOutput(),
+					test_shift,bestoffset,
+					0,topline,1);
+	      if ( d > best ) 
+		{
+		  bestshift =test_shift;
+		  best=d;
+		  besttest=test;
+		  fprintf(stderr,"\t Shift=%5.2f Offset=%5.2f d0=%.4f (incr=%.4f)\n",bestshift,bestoffset,best,
+			  increment);
+		}
+	    }
+
+	  if (besttest==-1)
+	    increment*=0.5;
+
+	  ++iter;
+	}
+      
+      fprintf(stderr,"Stage 1 Shift=%5.2f Offset=%5.2f d0=%.4f (incr=%.4f iter=%d)\n",bestshift,bestoffset,best,
+	      increment,iter);
+
+
+      iter=0;
+      increment=M_PI/16.0;
+      best=ComputeSimilarity(extr->GetOutput(),extr2->GetOutput(),
+			     bestshift,bestoffset,
+			     1,topline,1);
+
+      
+
+      // Step 2 Optimize Shift + Offset for Sum 
+      while (iter < 40 && increment> 0.001 )
+	{
+	  int besttest=-1;
+	  float offset=bestoffset;
+
+	  for (int test=0;test<=1;test++)
+	    {
+	      
+	      float test_offset = offset+ dp[test][0]*increment;
+	      float d=ComputeSimilarity(extr->GetOutput(),extr2->GetOutput(),
+					bestshift,test_offset,
+					1,topline,1);
+	      if ( d > best ) 
+		{
+		  bestoffset=test_offset;
+		  best=d;
+		  besttest=test;
+		  fprintf(stderr,"\t Shift=%5.2f Offset=%5.2f d0=%.4f (incr=%.4f)\n",bestshift,bestoffset,best,
+			  increment);
+		}
+	    }
+
+	  if (besttest==-1)
+	    increment*=0.5;
+
+	  ++iter;
+	}
+
+      fprintf(stderr,"Stage 2 Shift=%5.2f Offset=%5.2f d0=%.4f (incr=%.4f iter=%d)\n",bestshift,bestoffset,best,
+	      increment,iter);
+
+      
+      best=ComputeSimilarity(extr->GetOutput(),extr2->GetOutput(),
+			     bestshift,bestoffset,
+			     0,topline,1);
+      
+      fprintf(stderr,"Final Shift=%5.2f Offset=%5.2f d0=%.4f (incr=%.4f iter=%d)\n",bestshift,bestoffset,best,
+	      increment,iter);
+      shiftScalars->SetComponent(slice,0,bestshift);
+      offsetScalars->SetComponent(slice,0,bestoffset);
+    }
+  extr2->Delete();
+  extr->Delete();
+  resl_ref->Delete();
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+int vtkpxImageAddPhaseCorrection::CorrectEPIPhase(vtkImageData* image,
+						  vtkFloatArray* shiftScalars,
+						  vtkFloatArray* offsetScalars)
+{
+
+  if (image==NULL || shiftScalars == NULL || offsetScalars ==NULL)
+    return 0;
+
+  vtkImageFFT* fft=vtkImageFFT::New();
+  fft->SetDimensionality(2);
+  fft->SetInput(image);
+  
+  vtkpxImageAddPhaseCorrection* addphase=vtkpxImageAddPhaseCorrection::New();
+  addphase->SetInput(fft->GetOutput());
+  addphase->SetSingleValue(0);
+  addphase->SetPhaseOffsetArray(offsetScalars);
+  addphase->SetPhaseShiftArray(shiftScalars);
+  
+  vtkImageRFFT* rfft=vtkImageRFFT::New();
+  rfft->SetInput(addphase->GetOutput());
+  rfft->SetDimensionality(2);
+  rfft->Update();
+  
+  image->ShallowCopy(rfft->GetOutput());
+  rfft->Delete();
+  addphase->Delete();
+  fft->Delete();
+
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+int vtkpxImageAddPhaseCorrection::DoGhostCorrection(vtkImageData* image,float topline)
+{
+  int dim[3];
+  image->GetDimensions(dim);
+
+  int nc=image->GetNumberOfScalarComponents();
+  fprintf(stderr,"Ghost Dimensions = %d %d %d x %d\n",dim[0],dim[1],dim[2],nc);
+  
+
+  vtkFloatArray* shiftScalars=vtkFloatArray::New();
+  shiftScalars->SetNumberOfComponents(1);
+  shiftScalars->SetNumberOfTuples(dim[2]);
+  shiftScalars->FillComponent(0,0.0);
+
+  vtkFloatArray* offsetScalars=vtkFloatArray::New();
+  offsetScalars->SetNumberOfComponents(1);
+  offsetScalars->SetNumberOfTuples(dim[2]);
+  offsetScalars->FillComponent(0,0.0);
+  
+  vtkpxImageExtract* extr=vtkpxImageExtract::New();
+  extr->SetInput(image);
+
+  vtkpxImageExtract* extr2=vtkpxImageExtract::New();
+  extr2->SetInput(image);
+
+  vtkImageAppendComponents* comp=vtkImageAppendComponents::New();
+
+  for (int slice=0;slice<dim[2];slice++)
+    {
+      fprintf(stderr,"-----------------------------------\n Beginning Slice = %d\n",slice);
+      extr->SetSliceNo(slice);
+      extr->SetFrame(0);
+      extr->Update();
+      
+      extr2->SetSliceNo(slice);
+      extr2->SetFrame(1);
+      extr2->Update();
+      
+      comp->AddInput(extr->GetOutput());
+      comp->AddInput(extr2->GetOutput());
+      comp->Update();
+      
+
+      vtkImageData* im=comp->GetOutput();
+      int d[3];	im->GetDimensions(d);
+      int n=im->GetNumberOfScalarComponents();
+      fprintf(stderr,"Ghost Dimensions = %d %d %d x %d\n",d[0],d[1],d[2],n);
+
+
+      float bestoffset=0.0;
+      int iter =0;
+      float increment=M_PI/3.0;
+      float best=ComputeSimilarity(comp->GetOutput(),comp->GetOutput(),
+				   0.0,bestoffset,
+				   1,topline,0);
+
+      for (int kk=1;kk<=7;kk++)
+	{
+	  float offset=float(kk)/4.0*M_PI;
+	  float b=ComputeSimilarity(comp->GetOutput(),comp->GetOutput(),
+				   0.0,offset,
+				   1,topline,0);
+	  if (b>best)
+	    {
+	      best=b;
+	      bestoffset=offset;
+	    }
+	}
+
+      // Step 2 Optimize Shift + Offset for Sum 
+      while (iter < 40 && increment> 0.001 )
+	{
+	  int besttest=-1;
+	  float offset=bestoffset;
+
+	  for (int test=-1;test<=1;test+=2)
+	    {
+	      float test_offset = offset+ float(test)*increment;
+	      float da=ComputeSimilarity(comp->GetOutput(),comp->GetOutput(),
+					0.0,test_offset,
+					1,topline,0);
+	      if ( da > best ) 
+		{
+		  bestoffset=test_offset;
+		  best=da;
+		  besttest=test;
+		  fprintf(stderr,"\tOffset=%5.2f d0=%.4f (incr=%.4f)\n",bestoffset,best,increment);
+		}
+	    }
+
+	  if (besttest==-1)
+	    increment*=0.5;
+
+	  ++iter;
+	}
+
+      fprintf(stderr,"Stage 2  Offset=%5.2f d0=%.4f (incr=%.4f iter=%d)\n",bestoffset,best,
+	      increment,iter);
+
+      best=ComputeSimilarity(comp->GetOutput(),comp->GetOutput(),
+			     0.0,bestoffset,
+			     0,topline,0);
+      
+      fprintf(stderr,"Final Offset=%5.2f d0=%.4f (incr=%.4f iter=%d)\n",bestoffset,best,
+	      increment,iter);
+      shiftScalars->SetComponent(slice,0,0.0);
+      offsetScalars->SetComponent(slice,0,bestoffset);
+    }
+
+  vtkpxImageAddPhaseCorrection* addphase=vtkpxImageAddPhaseCorrection::New();
+  addphase->SetInput(image);
+  addphase->SetSingleValue(0);
+  addphase->SetPhaseOffsetArray(offsetScalars);
+  addphase->SetPhaseShiftArray(shiftScalars);
+  addphase->Update();
+  image->ShallowCopy(addphase->GetOutput());
+  addphase->Delete();
+
+  extr->Delete();
+  extr2->Delete();
+  comp->Delete();
+  shiftScalars->Delete();
+  offsetScalars->Delete();
+
+  return 1;
+}
+
+int vtkpxImageAddPhaseCorrection::DoGhostCorrectionPolarComplex(vtkImageData* image,float topline)
+{
+  vtkpxImagePolarToEuclidean* pol=vtkpxImagePolarToEuclidean::New();
+  pol->SetInput(image);
+  
+  vtkImageFFT* fft=vtkImageFFT::New();
+  fft->SetDimensionality(2);
+  fft->SetInput(pol->GetOutput());
+  fft->Update();
+  pol->Delete();
+
+  vtkImageData* tmp=vtkImageData::New();
+  tmp->ShallowCopy(fft->GetOutput());
+  fft->Delete();
+
+  DoGhostCorrection(tmp,topline);
+
+  vtkImageRFFT* rfft=vtkImageRFFT::New();
+  rfft->SetDimensionality(2);
+  rfft->SetInput(tmp);
+
+  vtkpxImagePolarToEuclidean* pol2=vtkpxImagePolarToEuclidean::New();
+  pol2->InverseOn();
+  pol2->SetInput(rfft->GetOutput());
+  pol2->Update();
+  
+  rfft->Delete();
+  image->ShallowCopy(pol2->GetOutput());
+  pol2->Delete();
+ 
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageAddPhaseCorrection.h b/bioimagesuite30_src/Imaging/vtkpxImageAddPhaseCorrection.h
new file mode 100644
index 0000000..020f746
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageAddPhaseCorrection.h
@@ -0,0 +1,158 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageAddPhaseCorrection.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageAddPhaseCorrection - Add Phase Offsets to Correct EPI ghosting 
+// .SECTION Description
+// For each pixel with vector components real imaginary this filter outputs 
+// real in component0, and imaginary in component1, adding phaseoffset to the phase component
+
+#ifndef __vtkpxImageAddPhaseCorrection_h
+#define __vtkpxImageAddPhaseCorrection_h
+
+
+#include "vtkImageToImageFilter.h"
+#include "vtkFloatArray.h"
+
+
+class vtkpxImageAddPhaseCorrection : public vtkImageToImageFilter
+{
+public:
+  static vtkpxImageAddPhaseCorrection *New();
+  vtkTypeMacro(vtkpxImageAddPhaseCorrection,vtkImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Phase Offset for odd lines 
+  vtkSetMacro(PhaseOffset,float);
+  vtkGetMacro(PhaseOffset,float);
+
+  // Description:
+  // Phase Offset for all lines 
+  // i.e. odd lines = PhaseOffset+PhaseShift
+  vtkSetMacro(PhaseShift,float);
+  vtkGetMacro(PhaseShift,float);
+
+  // Description:
+  // Optimize Shift
+  static int  OptimizeSimilarity(vtkImageData* image,vtkImageData* reference,
+				 vtkFloatArray* optimal_shifts,vtkFloatArray* optimal_offsets);
+
+  
+  // Description:
+  // Do Ghost Correction
+  static int DoGhostCorrection(vtkImageData* image,float topline=0.25);
+  static int DoGhostCorrectionPolarComplex(vtkImageData* image,float topline=0.25);
+
+  // Description:
+  // Correct Image
+  static int CorrectEPIPhase(vtkImageData* image,vtkFloatArray* optimal_shifts,
+			     vtkFloatArray* optimal_offsets);
+
+
+  // Description:
+  // Flag to Determine whether to use a single value for shift/offset or one value per slice 
+  vtkSetClampMacro(SingleValue, int,0,1);
+  vtkGetMacro(SingleValue, int);
+  vtkBooleanMacro(SingleValue, int);
+
+  // Description:
+  // PhaseOffset Array
+  vtkGetObjectMacro(PhaseOffsetArray,vtkFloatArray);
+  vtkSetObjectMacro(PhaseOffsetArray,vtkFloatArray);
+
+  // Description:
+  // PhaseShift Array
+  vtkGetObjectMacro(PhaseShiftArray,vtkFloatArray);
+  vtkSetObjectMacro(PhaseShiftArray,vtkFloatArray);
+
+  
+protected:
+  vtkpxImageAddPhaseCorrection();
+  ~vtkpxImageAddPhaseCorrection() {};
+  vtkpxImageAddPhaseCorrection(const vtkpxImageAddPhaseCorrection&) {};
+  void operator=(const vtkpxImageAddPhaseCorrection&) {};
+
+  float PhaseOffset;
+  float PhaseShift;
+  int   SingleValue;
+  vtkFloatArray* PhaseOffsetArray;
+  vtkFloatArray* PhaseShiftArray;
+
+  void ThreadedExecute(vtkImageData *inData, vtkImageData *outData,int ext[6], int id);
+
+
+  static float ComputeSimilarity(vtkImageData *img,
+				 vtkImageData* ref,
+				 float shift,float offset,
+				 int mode,float topline=0.25,int dofft=1);
+
+  // Description:
+  // Compute Signal in outer-lobes vs signal inside using reference image 
+  static float GetIntensitySum(vtkImageData* image,int slice,float topline=0.25);
+
+
+  // Description:
+  // Determine Location of anatomical image in slice to find good window 
+  static float ComputeTopLine(vtkImageData* ref);
+  static float ComputeCorrelationCoefficient(vtkDataArray* scal0,vtkDataArray* scal1,
+					     int debug);
+
+};
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageAlgebra.cpp b/bioimagesuite30_src/Imaging/vtkpxImageAlgebra.cpp
new file mode 100644
index 0000000..55cc87f
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageAlgebra.cpp
@@ -0,0 +1,314 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageAlgebra.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxImageAlgebra.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxUtil.h"
+#include "vtkImageToImageFilter.h"
+#include "vtkDoubleArray.h"
+#include "vtkImageProgressIterator.h"
+
+//------------------------------------------------------------------------------
+vtkpxImageAlgebra* vtkpxImageAlgebra::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageAlgebra");
+  if(ret)
+    {
+    return (vtkpxImageAlgebra*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageAlgebra;
+}
+
+//----------------------------------------------------------------------------
+// Constructor sets default values
+vtkpxImageAlgebra::vtkpxImageAlgebra()
+{
+  this->OutputScalarType = -1;
+  this->Map=NULL;
+}
+
+vtkpxImageAlgebra::~vtkpxImageAlgebra()
+{
+    this->SetMap(NULL);
+}
+
+//----------------------------------------------------------------------------
+void vtkpxImageAlgebra::ExecuteInformation(vtkImageData *inData, 
+					    vtkImageData *outData)
+{
+  this->vtkImageToImageFilter::ExecuteInformation( inData, outData );
+
+  if (this->OutputScalarType != -1)
+    outData->SetScalarType(this->OutputScalarType);
+
+}
+
+//----------------------------------------------------------------------------
+// This templated function executes the filter for any type of data.
+template <class IT, class OT>
+void vtkpxImageAlgebraExecute(vtkpxImageAlgebra *self,
+				     vtkImageData *inData, 
+				     vtkImageData *outData, 
+				     int outExt[6], int id,  IT *, OT *)
+{
+
+  vtkDoubleArray* Map=self->GetMap();
+  if (Map==NULL)
+    return;
+
+  int numt=Map->GetNumberOfTuples();
+  //  fprintf(stderr,"Numt A=%d %d:%d %d:%d %d:%d\n\n",numt,outExt[0],outExt[1],outExt[2],outExt[3],outExt[4],outExt[5]);
+
+  vtkImageIterator<IT> inIt(inData, outExt);
+  vtkImageProgressIterator<OT> outIt(outData, outExt, self, id);
+
+  // for preventing overflow
+  double outTypeMin = outData->GetScalarTypeMin();
+  double outTypeMax = outData->GetScalarTypeMax();
+  
+
+  int dt=outData->GetScalarType();
+  int doround=1;
+  if (dt==VTK_FLOAT || dt==VTK_DOUBLE)
+    doround=0;
+
+  /*  fprintf(stderr,"Data type=%d (fl=%d db=%d) round=%d\n",
+      dt,VTK_FLOAT,VTK_DOUBLE,doround);*/
+
+  while (!outIt.IsAtEnd())
+    {
+      IT* inSI = inIt.BeginSpan();
+      OT* outSI = outIt.BeginSpan();
+      OT* outSIEnd = outIt.EndSpan();
+
+      while (outSI != outSIEnd)
+        {
+	  double val = ((float)(*inSI)); 
+	  
+	  int flag=0,test=0;
+	  while (test<numt-1 && flag==0)
+	    {
+	      if (val< Map->GetComponent(test,0))
+		{
+		  val= Map->GetComponent(test,1)+val*Map->GetComponent(test,2);
+		  flag=1;
+		}
+	      ++test;
+	    }
+	  
+	  if (flag==0)
+	    val= Map->GetComponent(numt-1,1)+val*Map->GetComponent(numt-1,2);
+	  
+	  if (val>outTypeMax)
+	    val=outTypeMax;
+	  else if (val<outTypeMin)
+	    val=outTypeMin;
+	  
+	  if (doround)
+	    *outSI = (OT)(val+0.5);
+	  else
+	    *outSI = (OT)(val);
+	  ++outSI;
+	  ++inSI;
+	}
+      inIt.NextSpan();
+      outIt.NextSpan();
+    }
+}
+
+template <class T>
+void vtkpxImageAlgebraExecute1(vtkpxImageAlgebra *self,
+			       vtkImageData *inData,
+			       vtkImageData *outData,
+			       int outExt[6], int id, T *)
+{
+  switch (outData->GetScalarType())
+    {
+      vtkTemplateMacro7(vtkpxImageAlgebraExecute, self, inData,
+			outData,outExt, id,
+			static_cast<T *>(0), static_cast<VTK_TT *>(0));
+    default:
+      vtkGenericWarningMacro("Execute: Unknown input ScalarType");
+      return;
+    }
+}
+
+//----------------------------------------------------------------------------
+// This method is passed a input and output data, and executes the filter
+// algorithm to fill the output from the input.
+// It just executes a switch statement to call the correct function for
+// the datas data types.
+void vtkpxImageAlgebra::ThreadedExecute(vtkImageData *inData, 
+					vtkImageData *outData,
+					int outExt[6], int id)
+{
+  if (this->Map==NULL)
+    {
+      vtkErrorMacro(<<"No Mapping Array supplied");
+      return;
+    }
+
+  int numc=this->Map->GetNumberOfComponents();
+  int numt=this->Map->GetNumberOfTuples();
+
+  /*  fprintf(stderr,"Numt=%d numc=%d\n",numt,numc);
+
+  for (int i=0;i<numt;i++)
+    fprintf(stderr,"Map i=%d  x=%f \t a1=%f \t a2=%f\n",i,
+	    this->Map->GetComponent(i,0),
+	    this->Map->GetComponent(i,1),
+	    this->Map->GetComponent(i,2));
+	    fprintf(stderr,"\n");*/
+
+  /*  int nt1=inData->GetPointData()->GetScalars()->GetNumberOfTuples();
+      int nt2=outData->GetPointData()->GetScalars()->GetNumberOfTuples();*/
+  
+  if (numc!=3)
+    {
+      vtkErrorMacro(<<"Bad Mapping Array supplied components="<<numc<<"!=3");
+      return;
+    }
+  if (numt<1)
+    {
+      vtkErrorMacro(<<"Bad Mapping Array supplied tuples="<<numt<<"<1");
+      return;
+    }
+
+  switch (inData->GetScalarType())
+    {
+      vtkTemplateMacro6(vtkpxImageAlgebraExecute1,this, 
+			inData, outData, outExt, id,static_cast<VTK_TT *>(0));
+    default:
+      vtkErrorMacro(<< "Execute: Unknown ScalarType");
+      return;
+    }
+}
+
+
+
+void vtkpxImageAlgebra::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkImageToImageFilter::PrintSelf(os,indent);
+  os << indent << "OutputMap: "<<this->Map;
+  os << indent << "Output Scalar Type: " << this->OutputScalarType << "\n";
+}
+
+
+int vtkpxImageAlgebra::CreateMapArrayFromKnots(vtkDoubleArray* knots)
+{
+  int numknots=knots->GetNumberOfTuples();
+  int numcomp=knots->GetNumberOfComponents();
+
+  if (numknots<1 || numcomp!=2)
+    return 0;
+
+
+  //  fprintf(stderr,"Creating map array from knots Numt=%d numc=%d\n",numknots,numcomp);
+
+  vtkDoubleArray*  newmap= vtkDoubleArray::New();
+  newmap->SetNumberOfComponents(3);
+
+  int count=0;
+  double oldx=0.0,oldy=0.0;
+
+  
+  for (int i=0;i<numknots;i++)
+    {
+      double x=knots->GetComponent(i,0);
+      double y=knots->GetComponent(i,1);
+
+      if (count==0)
+	{
+	  newmap->InsertNextTuple3(x,y,0.0);
+	} 
+      else 
+	{
+	  double d1=y-oldy;
+	  double d2=x-oldx;
+	  double a=0.0;
+	  if (d2>0.0)
+	    a=d1/d2;
+	  double b=y-a*x;
+	  newmap->InsertNextTuple3(x,b,a);
+	}
+      oldx=x;
+      oldy=y;
+      ++count;
+    }
+  this->SetMap(newmap);
+
+
+  for (int i=0;i<numknots;i++)
+    {
+      double x=newmap->GetComponent(i,0);
+      double b=newmap->GetComponent(i,1);
+      double a=newmap->GetComponent(i,2);
+      double y=a*x+b;
+
+      double b1=newmap->GetComponent(i+1,1);
+      double a1=newmap->GetComponent(i+1,2);
+      double y1=a1*x+b1;
+      //      fprintf(stdout,"Mapping %.2f  -> %f or %f\n",x,y,y1);
+    }
+	  
+
+  newmap->Delete();
+  return count;
+
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageAlgebra.h b/bioimagesuite30_src/Imaging/vtkpxImageAlgebra.h
new file mode 100644
index 0000000..07a1b37
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageAlgebra.h
@@ -0,0 +1,147 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageAlgebra.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageAlgebra - piecewise linear intensity map
+// .SECTION Description
+// With vtkpxImageAlgebra Pixels Intensities are mapped using
+// a piecewise linear function defined by nodes specified in the
+// mapping scalar array. The mapping array must have three components
+// t , a , b and the t's are assumed to be ordered in ascending order.
+// The mapping is as follows:
+// if incoming intensity in < t_i   out = a_i + b_i * in
+// else check next t_i until the last one
+// As a convenience, this class allows you to set the output scalar type
+// similar to vtkImageCast.
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+
+#ifndef __vtkpxImageAlgebra_h
+#define __vtkpxImageAlgebra_h
+
+
+class vtkImageToImageFilter;
+
+#include "vtkImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkDoubleArray.h"
+
+class vtkpxImageAlgebra : public vtkImageToImageFilter
+{
+public:
+  static vtkpxImageAlgebra *New();
+  vtkTypeMacro(vtkpxImageAlgebra,vtkImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  
+  // Description:
+  // Set/Get the Mapping
+  vtkSetObjectMacro(Map,vtkDoubleArray);
+  vtkGetObjectMacro(Map,vtkDoubleArray);
+
+  // Description:
+  // Create Map Array from Knots
+  virtual int CreateMapArrayFromKnots(vtkDoubleArray* knots);
+
+
+  // Set the desired output scalar type.  The result of the algebra
+  // operations is cast to the type specified.
+  vtkSetMacro(OutputScalarType, int);
+  vtkGetMacro(OutputScalarType, int);
+  void SetOutputScalarTypeToDouble()
+    {this->SetOutputScalarType(VTK_DOUBLE);}
+  void SetOutputScalarTypeToFloat()
+    {this->SetOutputScalarType(VTK_FLOAT);}
+  void SetOutputScalarTypeToLong()
+    {this->SetOutputScalarType(VTK_LONG);}
+  void SetOutputScalarTypeToUnsignedLong()
+    {this->SetOutputScalarType(VTK_UNSIGNED_LONG);};
+  void SetOutputScalarTypeToInt()
+    {this->SetOutputScalarType(VTK_INT);}
+  void SetOutputScalarTypeToUnsignedInt()
+    {this->SetOutputScalarType(VTK_UNSIGNED_INT);}
+  void SetOutputScalarTypeToShort()
+    {this->SetOutputScalarType(VTK_SHORT);}
+  void SetOutputScalarTypeToUnsignedShort()
+    {this->SetOutputScalarType(VTK_UNSIGNED_SHORT);}
+  void SetOutputScalarTypeToChar()
+    {this->SetOutputScalarType(VTK_CHAR);}
+  void SetOutputScalarTypeToUnsignedChar()
+    {this->SetOutputScalarType(VTK_UNSIGNED_CHAR);}
+
+
+
+protected:
+  //BTX
+  vtkpxImageAlgebra();
+  ~vtkpxImageAlgebra();
+  vtkpxImageAlgebra(const vtkpxImageAlgebra&) {};
+  void operator=(const vtkpxImageAlgebra&) {};
+
+
+  vtkDoubleArray* Map;
+  int OutputScalarType;
+
+  void ExecuteInformation(vtkImageData *inData, vtkImageData *outData);
+  void ExecuteInformation(){this->vtkImageToImageFilter::ExecuteInformation();};
+  void ThreadedExecute(vtkImageData *inData, vtkImageData *outData,
+		       int extent[6], int id);
+  //ETX
+};
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageAttenuationCorrection.cpp b/bioimagesuite30_src/Imaging/vtkpxImageAttenuationCorrection.cpp
new file mode 100644
index 0000000..6cfe766
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageAttenuationCorrection.cpp
@@ -0,0 +1,155 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageAttenuationCorrection.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxImageAttenuationCorrection.h"
+#include "vtkpxUtil.h"
+#include "vtkIntArray.h"
+#include "vtkImageGaussianSmooth.h"
+
+
+//------------------------------------------------------------------------------
+vtkpxImageAttenuationCorrection* vtkpxImageAttenuationCorrection::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageAttenuationCorrection");
+  if(ret)
+    {
+    return (vtkpxImageAttenuationCorrection*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageAttenuationCorrection;
+}
+
+// Construct object with no children.
+vtkpxImageAttenuationCorrection::vtkpxImageAttenuationCorrection()
+{
+  this->Threshold=1.0;
+  this->Sigma=2.0;
+  this->Factor=0.999;
+  this->AttenuationMap=NULL;
+}
+
+vtkpxImageAttenuationCorrection::~vtkpxImageAttenuationCorrection()
+{
+  if (this->AttenuationMap!=NULL)
+    this->AttenuationMap->Delete();
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageAttenuationCorrection::SimpleExecute(vtkImageData* input,vtkImageData* output )
+{
+
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Input to vtkpxImageAttenuationCorrection");
+      return;
+    }
+
+  double sp[3];    input->GetSpacing(sp);
+
+  double gp[3];
+  for (int ia=0;ia<=2;ia++)
+    gp[ia]=2.0*sp[0]/sp[2];
+
+  vtkImageGaussianSmooth* sm=vtkImageGaussianSmooth::New();
+  sm->SetInput(input);
+  sm->SetStandardDeviations(gp);
+  sm->Update();
+
+  fprintf(stderr,"Smoothing Done\n");
+
+  this->AttenuationMap=vtkImageData::New();
+  this->AttenuationMap->CopyStructure(input);
+  this->AttenuationMap->SetScalarTypeToFloat();
+  this->AttenuationMap->SetNumberOfScalarComponents(1);
+  this->AttenuationMap->AllocateScalars();
+
+  vtkImageData* tmp=sm->GetOutput();
+  int dim[3];   tmp->GetDimensions(dim);
+  vtkDataArray* tmp_arr=tmp->GetPointData()->GetScalars();
+  vtkDataArray* out_arr=output->GetPointData()->GetScalars();
+  vtkDataArray* in_arr=input->GetPointData()->GetScalars();
+  vtkDataArray* at_arr=this->AttenuationMap->GetPointData()->GetScalars();
+
+  int slicesize=dim[0]*dim[1];
+  double* factor=new double[slicesize];
+  fprintf(stderr,"Correcting : ");
+  for (int slice=0;slice<dim[2];slice++)
+    {
+      fprintf(stderr,"%d ",slice);
+      int offset=slice*slicesize;
+      for (int pixel=0;pixel<slicesize;pixel++)
+	{
+	  int index=offset+pixel;
+	  if (slice==0)
+	    {
+	      factor[pixel]=1.0;
+	    }
+	  else
+	    {
+	      if ( tmp_arr->GetComponent(index-slicesize,0)>this->Threshold)
+		factor[pixel]*=this->Factor;
+	    }
+	  out_arr->SetComponent(index,0,in_arr->GetComponent(index,0)/factor[pixel]);
+	  at_arr->SetComponent(index,0,factor[pixel]*100.0);
+	}
+    }
+
+  delete [] factor;
+  fprintf(stderr,"\n");
+  sm->Delete();
+
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageAttenuationCorrection.h b/bioimagesuite30_src/Imaging/vtkpxImageAttenuationCorrection.h
new file mode 100644
index 0000000..4818ec9
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageAttenuationCorrection.h
@@ -0,0 +1,111 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageSimpleImageThreshold.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageImageAttenuationCorrection -- compute the difference and a normalized difference
+// between two images
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageImageAttenuationCorrection_h
+#define __vtkpxImageImageAttenuationCorrection_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkpxImageAttenuationCorrection : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageAttenuationCorrection *New();
+  vtkTypeMacro(vtkpxImageAttenuationCorrection,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set the thresholds between which output is 1
+  vtkGetMacro(Threshold,float);
+  vtkSetMacro(Threshold,float);
+
+  // Description:
+  // Smoothness
+  vtkGetMacro(Sigma,float);
+  vtkSetMacro(Sigma,float);
+
+  // Description:
+  // Attenuation Factor
+  vtkGetMacro(Factor,float);
+  vtkSetMacro(Factor,float);
+
+  // Description:
+  // Attenuation Map (*100)
+  vtkGetObjectMacro(AttenuationMap,vtkImageData);
+
+protected:
+
+  vtkpxImageAttenuationCorrection();
+  virtual ~vtkpxImageAttenuationCorrection();
+  vtkpxImageAttenuationCorrection(const vtkpxImageAttenuationCorrection&) {}
+  void operator=(const vtkpxImageAttenuationCorrection&) {};
+
+  // Description:
+  // Do Thresholding Operation 
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  //BTX
+  float       Threshold,Sigma,Factor;
+  vtkImageData* AttenuationMap;
+  //ETX
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageComputeNormalizedDifference.cpp b/bioimagesuite30_src/Imaging/vtkpxImageComputeNormalizedDifference.cpp
new file mode 100644
index 0000000..fff16cf
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageComputeNormalizedDifference.cpp
@@ -0,0 +1,237 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageComputeNormalizedDifference.cpp,v $
+  Language:  C++  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxImageComputeNormalizedDifference.h"
+#include "vtkpxUtil.h"
+#include "vtkFloatArray.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkpxUtil.h"
+//------------------------------------------------------------------------------
+vtkpxImageComputeNormalizedDifference* vtkpxImageComputeNormalizedDifference::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageComputeNormalizedDifference");
+  if(ret)
+    {
+    return (vtkpxImageComputeNormalizedDifference*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageComputeNormalizedDifference;
+}
+
+// Construct object with no children.
+vtkpxImageComputeNormalizedDifference::vtkpxImageComputeNormalizedDifference()
+{
+  this->Threshold=0.1;
+  this->PercentageThreshold=0.05;
+  this->Input2=NULL;
+  this->PercentageOutput=NULL;
+  this->NormalizedSecondImage=NULL;
+  this->Scale=1.0;
+  this->Shift=0.0;
+  this->Sigma=1.0;
+}
+// ----------------------------------------------------------------------------
+vtkpxImageComputeNormalizedDifference::~vtkpxImageComputeNormalizedDifference()
+{
+  this->SetInput2(NULL);
+  if (this->PercentageOutput!=NULL)
+    this->PercentageOutput->Delete();
+
+  if (this->NormalizedSecondImage!=NULL)
+    this->NormalizedSecondImage->Delete();
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageComputeNormalizedDifference::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+
+  if (this->GetImageDataInput(0)==NULL    || this->Input2==NULL )
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxImageComputeNormalizedDifference");
+      return;
+    }
+
+
+  int dim[3],dim2[3];
+  input->GetDimensions(dim);
+  this->Input2->GetDimensions(dim2);
+  
+  int sum=0;
+  for (int ia=0;ia<=2;ia++)
+    sum+=abs(dim[ia]-dim2[ia]);
+  if (sum!=0)
+    {
+      vtkErrorMacro(<<"Bad Input Dimensions");
+      return;
+    }
+    
+  vtkImageData* tmp=vtkImageData::New();
+  tmp->CopyStructure(input);
+  tmp->SetScalarType(VTK_FLOAT);
+  tmp->SetNumberOfScalarComponents(1);
+  tmp->AllocateScalars();
+  vtkDataArray* out=tmp->GetPointData()->GetScalars();
+
+  if (this->PercentageOutput==NULL)
+    this->PercentageOutput=vtkImageData::New();
+
+  this->PercentageOutput->CopyStructure(tmp);
+  this->PercentageOutput->AllocateScalars();
+
+
+  vtkDataArray* outper=this->PercentageOutput->GetPointData()->GetScalars();
+
+  vtkDataArray* in1=input->GetPointData()->GetScalars();  
+  vtkDataArray* in2=this->Input2->GetPointData()->GetScalars();
+
+
+  float tlow,thigh;
+  vtkpxUtil::ImageRobustRange(input,0.02,0.98,tlow,thigh);
+  float threshold=this->Threshold*(thigh-tlow)+tlow;
+  float perthreshold=this->PercentageThreshold*(thigh-tlow)+tlow;
+
+  int numscalars=out->GetNumberOfTuples();
+
+  float sxx=0.0,sxy=0.0;
+  for (int jj=0;jj<numscalars;jj++) 
+    {
+      float x=in1->GetComponent(jj,0);
+      float y=in2->GetComponent(jj,0);
+      
+      if (x>=threshold)
+	{
+	  sxy += x*y;
+	  sxx += x*x;
+	}
+    }
+
+  this->Shift=0.0;
+  this->Scale=sxy/sxx;
+  
+  this->UpdateProgress(0.01);
+  float pog=0.00;
+  float tenth=numscalars/10.0;
+  int count=0;
+
+  if (this->NormalizedSecondImage!=NULL)
+    this->NormalizedSecondImage->Delete();
+
+  this->NormalizedSecondImage=vtkImageData::New();
+  this->NormalizedSecondImage->CopyStructure(this->Input2);
+  this->NormalizedSecondImage->SetNumberOfScalarComponents(this->Input2->GetNumberOfScalarComponents());
+  this->NormalizedSecondImage->AllocateScalars();
+  vtkDataArray* norm2=  this->NormalizedSecondImage->GetPointData()->GetScalars();
+
+  //  fprintf(stderr,"Minimum thresholds both SPECTS =%.2f\n",perthreshold);
+
+  for (int pixel=0;pixel<numscalars;pixel++)
+    {
+      float v1=in1->GetComponent(pixel,0);
+      float v2=in2->GetComponent(pixel,0);
+
+      v2=(v2-this->Shift)/this->Scale;
+
+      if (v1>perthreshold && v2>perthreshold)
+	{
+	  out->SetComponent(pixel,0,float(v2-v1));
+	  norm2->SetComponent(pixel,0,v2);
+	}
+      else
+	{
+	  norm2->SetComponent(pixel,0,0.0);
+	}
+    
+      count++;
+      if (count==tenth)
+	{
+	  pog+=0.05;
+	  this->UpdateProgress(pog);
+	  count=0;
+	}
+    }
+
+
+  vtkImageGaussianSmooth* sm=vtkImageGaussianSmooth::New();
+  sm->SetInput(tmp);
+  sm->SetStandardDeviations(this->Sigma,this->Sigma,this->Sigma);
+  sm->Update();
+  tmp->Delete();
+
+  output->ShallowCopy(sm->GetOutput());
+  sm->Delete();
+
+
+  vtkDataArray* diff=output->GetPointData()->GetScalars();
+
+  for (int pix=0;pix<numscalars;pix++)
+    {
+      float d=diff->GetComponent(pix,0);
+      float v1=in1->GetComponent(pix,0);
+
+      float p=0.0;
+
+      if (v1>perthreshold)
+	p=100.0*d/v1;
+      outper->SetComponent(pix,0,p);
+      
+      count++;
+      if (count==tenth)
+	{
+	  pog+=0.05;
+	  this->UpdateProgress(pog);
+	  count=0;
+	}
+    }
+  this->UpdateProgress(1.0);
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageComputeNormalizedDifference.h b/bioimagesuite30_src/Imaging/vtkpxImageComputeNormalizedDifference.h
new file mode 100644
index 0000000..928655e
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageComputeNormalizedDifference.h
@@ -0,0 +1,128 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageComputeNormalizedDifference.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageComputeNormalizedDifference -- compute the difference and a normalized difference
+// between two images
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageComputeNormalizedDifference_h
+#define __vtkpxImageComputeNormalizedDifference_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkpxImageComputeNormalizedDifference : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageComputeNormalizedDifference *New();
+  vtkTypeMacro(vtkpxImageComputeNormalizedDifference,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  //Set the level between 0 and 1 below which the data (in the ref image) is
+  // not used to compute the scale and shift parameters
+  vtkGetMacro(Threshold,float);
+  vtkSetClampMacro(Threshold,float,0.001,1.0);
+
+  // Description:
+  // Set value of threshold between 0 and 1 below which the percentage
+  // change is set to zero by default
+  vtkGetMacro(PercentageThreshold,float);
+  vtkSetClampMacro(PercentageThreshold,float,0.001,1.0);
+
+  // Description:
+  // Determines the function between Input1 and Input2
+  // i.e. Input2= Scale*Input1+Shift
+  // Do not confuse with vtkImageShiftScale where out=(shift+input)*scale
+  vtkGetMacro(Scale,float);
+  vtkGetMacro(Shift,float);
+
+  // Description:
+  // Smooth Difference before computing percentages
+  vtkGetMacro(Sigma,float);
+  vtkSetClampMacro(Sigma,float,0.0,3.0);
+
+  // Description:
+  // Input2 -- second input to compare with input
+  vtkSetObjectMacro(Input2,vtkImageData);
+  vtkGetObjectMacro(Input2,vtkImageData);
+
+  // Description:
+  // PercentageOuput
+  vtkGetObjectMacro(PercentageOutput, vtkImageData);
+  vtkGetObjectMacro(NormalizedSecondImage, vtkImageData);
+
+protected:
+
+  vtkpxImageComputeNormalizedDifference();
+  virtual ~vtkpxImageComputeNormalizedDifference();
+  vtkpxImageComputeNormalizedDifference(const vtkpxImageComputeNormalizedDifference&) {};
+  void operator=(const vtkpxImageComputeNormalizedDifference&) {};
+
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  float       Threshold;
+  float       PercentageThreshold;
+  float       Scale;
+  float       Shift;
+  float       Sigma;
+  vtkImageData* Input2;
+  vtkImageData* NormalizedSecondImage;
+  vtkImageData* PercentageOutput;
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageComputeNormalizedRatio.cpp b/bioimagesuite30_src/Imaging/vtkpxImageComputeNormalizedRatio.cpp
new file mode 100644
index 0000000..1f997f5
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageComputeNormalizedRatio.cpp
@@ -0,0 +1,223 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageComputeNormalizedRatio.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxImageComputeNormalizedRatio.h"
+#include "vtkpxUtil.h"
+#include "vtkFloatArray.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkpxUtil.h"
+//------------------------------------------------------------------------------
+vtkpxImageComputeNormalizedRatio* vtkpxImageComputeNormalizedRatio::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageComputeNormalizedRatio");
+  if(ret)
+    {
+    return (vtkpxImageComputeNormalizedRatio*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageComputeNormalizedRatio;
+}
+
+// Construct object with no children.
+vtkpxImageComputeNormalizedRatio::vtkpxImageComputeNormalizedRatio()
+{
+  this->Threshold=0.1;
+  this->NormalizedThreshold=0.05;
+  this->Input2=NULL;
+  this->NormalizedOutput=NULL;
+  this->AverageRatio=1;
+  this->Sigma=1.0;
+}
+// ----------------------------------------------------------------------------
+vtkpxImageComputeNormalizedRatio::~vtkpxImageComputeNormalizedRatio()
+{
+  this->SetInput2(NULL);
+  if (this->NormalizedOutput!=NULL)
+    this->NormalizedOutput->Delete();
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageComputeNormalizedRatio::SimpleExecute(vtkImageData* ,vtkImageData* )
+{
+
+  if (this->GetImageDataInput(0)==NULL    || this->Input2==NULL )
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxImageComputeNormalizedRatio");
+      return;
+    }
+
+
+  int dim[3],dim2[3];
+  this->GetImageDataInput(0)->GetDimensions(dim);
+  this->GetInput2()->GetDimensions(dim2);
+  
+  int ssum=0;
+  for (int ia=0;ia<=2;ia++)
+    ssum+=abs(dim[ia]-dim2[ia]);
+  if (ssum!=0)
+    {
+      vtkErrorMacro(<<"Bad Input Dimensions");
+      return;
+    }
+    
+  vtkImageData* output=this->GetOutput();
+  output->SetSpacing(this->GetImageDataInput(0)->GetSpacing());
+  output->SetOrigin(this->GetImageDataInput(0)->GetOrigin());
+  output->SetScalarType(VTK_FLOAT);
+  output->SetNumberOfScalarComponents(1);
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  output->AllocateScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+
+  if (this->NormalizedOutput==NULL)
+    this->NormalizedOutput=vtkImageData::New();
+
+  this->NormalizedOutput->SetSpacing(this->GetImageDataInput(0)->GetSpacing());
+  this->NormalizedOutput->SetOrigin(this->GetImageDataInput(0)->GetOrigin());
+  this->NormalizedOutput->SetScalarType(VTK_FLOAT);
+  this->NormalizedOutput->SetNumberOfScalarComponents(1);
+  this->NormalizedOutput->SetDimensions(dim[0],dim[1],dim[2]);
+  this->NormalizedOutput->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->NormalizedOutput->AllocateScalars();
+  vtkDataArray* outper=this->NormalizedOutput->GetPointData()->GetScalars();
+
+
+  vtkImageGaussianSmooth* sm=vtkImageGaussianSmooth::New();
+  sm->SetInput(this->GetImageDataInput(0));
+  sm->SetStandardDeviations(this->Sigma,this->Sigma,this->Sigma);
+  sm->Update();
+
+  vtkImageGaussianSmooth* sm2=vtkImageGaussianSmooth::New();
+  sm2->SetInput(this->GetInput2());
+  sm2->SetStandardDeviations(this->Sigma,this->Sigma,this->Sigma);
+  sm2->Update();
+
+
+  vtkDataArray* in1=sm->GetOutput()->GetPointData()->GetScalars();  
+  vtkDataArray* in2=sm2->GetOutput()->GetPointData()->GetScalars();
+
+  float tlow,thigh;
+  vtkpxUtil::ImageRobustRange(this->GetImageDataInput(0),0.02,0.98,tlow,thigh);
+  float threshold=this->Threshold*(thigh-tlow)+tlow;
+  float perthreshold=this->NormalizedThreshold*(thigh-tlow)+tlow;
+
+  vtkpxUtil::ImageRobustRange(this->GetInput2(),0.02,0.98,tlow,thigh);
+  float perthreshold2=this->NormalizedThreshold*(thigh-tlow)+tlow;
+
+  fprintf(stderr,"Minimum thresholds PET=%.2f SPECT=%.2f\n",perthreshold2,perthreshold);
+
+  int numscalars=out->GetNumberOfTuples();
+
+  this->UpdateProgress(0.01);
+  float pog=0.00;
+  float tenth=numscalars/10.0;
+  int count=0;
+  int pixel=0;
+
+  float sxx=0.0,sxy=0.0;
+
+  for (pixel=0;pixel<numscalars;pixel++)
+    {
+      float v1=in1->GetComponent(pixel,0);
+      float v2=in2->GetComponent(pixel,0);
+      float r=0.0;
+      if (fabs(v1)>0.0001 && v1>perthreshold && v2>perthreshold2 )
+	{
+	  r=v2/v1;
+	  if (v1>threshold)
+	    {
+	      sxx+=v1*v1;
+	      sxy+=v1*v2;
+	    }
+	}
+      out->SetComponent(pixel,0,r);
+      count++;
+      if (count==tenth)
+	{
+	  pog+=0.05;
+	  this->UpdateProgress(pog);
+	  count=0;
+	}
+    }
+
+  this->AverageRatio=sxy/sxx;
+
+  for (pixel=0;pixel<numscalars;pixel++)
+    {
+      float v1=in1->GetComponent(pixel,0);
+      float v2=in2->GetComponent(pixel,0);
+      float r=0.0;
+      if (v1>perthreshold && fabs(v1)>0.0001 )
+	r=(v2/v1)/this->AverageRatio-1.0;
+
+      outper->SetComponent(pixel,0,r);
+      count++;
+      if (count==tenth)
+	{
+	  pog+=0.05;
+	  this->UpdateProgress(pog);
+	  count=0;
+	}
+    }
+  this->UpdateProgress(1.0);
+
+  sm2->Delete();
+  sm->Delete();
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageComputeNormalizedRatio.h b/bioimagesuite30_src/Imaging/vtkpxImageComputeNormalizedRatio.h
new file mode 100644
index 0000000..fdcc4b5
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageComputeNormalizedRatio.h
@@ -0,0 +1,122 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageComputeNormalizedRatio.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageComputeNormalizedRatio -- compute the ratio and a normalized ratio between two images
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageComputeNormalizedRatio_h
+#define __vtkpxImageComputeNormalizedRatio_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkpxImageComputeNormalizedRatio : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageComputeNormalizedRatio *New();
+  vtkTypeMacro(vtkpxImageComputeNormalizedRatio,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  //Set the level between 0 and 1 below which the data (in the ref image) is
+  // not used to compute the scale and shift parameters
+  vtkGetMacro(Threshold,float);
+  vtkSetClampMacro(Threshold,float,0,1);
+
+  // Description:
+  // Set value of threshold between 0 and 1 below which the percentage
+  // change is set to zero by default
+  vtkGetMacro(NormalizedThreshold,float);
+  vtkSetClampMacro(NormalizedThreshold,float,0,1);
+
+  // Description:
+  // Average Ratio
+  vtkGetMacro(AverageRatio,float);
+
+  // Description:
+  // Smooth Difference before computing percentages
+  vtkGetMacro(Sigma,float);
+  vtkSetClampMacro(Sigma,float,0.0,3.0);
+
+
+  // Description:
+  // Input2 -- second input to compare with input
+  vtkSetObjectMacro(Input2,vtkImageData);
+  vtkGetObjectMacro(Input2,vtkImageData);
+
+  // Description:
+  // NormalizedOuput
+  vtkGetObjectMacro(NormalizedOutput, vtkImageData);
+
+protected:
+
+  vtkpxImageComputeNormalizedRatio();
+  virtual ~vtkpxImageComputeNormalizedRatio();
+  vtkpxImageComputeNormalizedRatio(const vtkpxImageComputeNormalizedRatio&) {};
+  void operator=(const vtkpxImageComputeNormalizedRatio&) {};
+
+  virtual void SimpleExecute(vtkImageData* in,vtkImageData* out);
+
+  float       Threshold;
+  float       NormalizedThreshold;
+  float       AverageRatio;
+  float       Sigma;
+  vtkImageData* Input2;
+  vtkImageData* NormalizedOutput;
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageComputeVOIStats.cpp b/bioimagesuite30_src/Imaging/vtkpxImageComputeVOIStats.cpp
new file mode 100644
index 0000000..09a7433
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageComputeVOIStats.cpp
@@ -0,0 +1,198 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageComputeVOIStats.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxImageComputeVOIStats.h"
+#include "vtkpxUtil.h"
+#include "vtkFloatArray.h"
+#include "vtkImageGaussianSmooth.h"
+
+//------------------------------------------------------------------------------
+vtkpxImageComputeVOIStats* vtkpxImageComputeVOIStats::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageComputeVOIStats");
+  if(ret)
+    {
+    return (vtkpxImageComputeVOIStats*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageComputeVOIStats;
+}
+
+// Construct object with no children.
+vtkpxImageComputeVOIStats::vtkpxImageComputeVOIStats()
+{
+  this->VOI=NULL;
+  this->AbsoluteValue=0;
+}
+// ----------------------------------------------------------------------------
+vtkpxImageComputeVOIStats::~vtkpxImageComputeVOIStats()
+{
+  this->SetVOI(NULL);
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageComputeVOIStats::SimpleExecute(vtkImageData* ,vtkImageData* output)
+{
+
+  if (this->GetImageDataInput(0)==NULL    || this->VOI==NULL )
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxImageComputeVOIStats");
+      return;
+    }
+
+  int dim[3],dim2[3];
+  this->GetImageDataInput(0)->GetDimensions(dim);
+  this->VOI->GetDimensions(dim2);
+  
+  int s=0;
+  for (int ia=0;ia<=2;ia++)
+    s+=abs(dim[ia]-dim2[ia]);
+  if (s!=0)
+    {
+      vtkErrorMacro(<<"Bad Input Dimensions");
+      return;
+    }
+ 
+  double range[2]; this->VOI->GetPointData()->GetScalars()->GetRange(range);
+  int numv=int(range[1]-range[0]);
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* in1=this->GetImageDataInput(0)->GetPointData()->GetScalars();  
+  vtkDataArray* in2=this->VOI->GetPointData()->GetScalars();
+
+  int* numvox=new int[numv];
+  float* sum=new float[numv];
+  float* sum2=new float[numv];
+
+  for (int i=0;i<numv;i++)
+    {
+      numvox[i]=0;
+      sum[i]=0.0;
+      sum2[i]=0.0;
+    }
+
+  int numscalars=in1->GetNumberOfTuples();
+  this->UpdateProgress(0.1);
+  
+  for (int jj=0;jj<numscalars;jj++) 
+    {
+      float x=in1->GetComponent(jj,0);
+      int y=int(in2->GetComponent(jj,0)-range[0])-1;
+
+      if (this->AbsoluteValue)
+	x=fabs(x);
+
+
+      if (y>=0)
+	{
+	  ++numvox[y];
+	  sum[y]+=x;
+	  sum2[y]+=x*x;
+	}
+    }
+  this->UpdateProgress(0.9);
+
+  for (int region=0;region<numv;region++)
+    {
+      if (numvox[region]<1)
+	{
+	  out->SetComponent(region,0,0);
+	  out->SetComponent(region,1,-1);
+	}
+      else
+	{
+	  float mean=sum[region]/float(numvox[region]);
+	  float std =sqrt(sum2[region]/float(numvox[region]) - mean*mean);
+	  
+	  out->SetComponent(region,0,mean);
+	  out->SetComponent(region,1,std);
+	  
+	  fprintf(stderr,"VOI int=%d,\t mean=%.2f\t std=%.2f\n",
+		  int(region+range[0]+1),
+		  mean,
+		  std);
+	}
+    }
+
+  delete [] sum2;
+  delete [] sum;
+  delete [] numvox;
+  
+  this->UpdateProgress(1);
+
+}
+
+// ----------------------------------------------------------------------------
+void vtkpxImageComputeVOIStats::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  vtkImageData *output=this->GetOutput();
+  output->SetSpacing(1,1,1);
+  output->SetOrigin(0,0,0);
+  output->SetWholeExtent(0,0,0,0,0,0);
+
+  if (this->VOI==NULL)
+    return;
+
+  double range[2]; this->VOI->GetPointData()->GetScalars()->GetRange(range);
+  int numv=int(range[1]-range[0]);
+  
+  output->SetScalarTypeToFloat();
+  output->SetWholeExtent(0,numv-1,0,0,0,0);
+  output->SetNumberOfScalarComponents(2);
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageComputeVOIStats.h b/bioimagesuite30_src/Imaging/vtkpxImageComputeVOIStats.h
new file mode 100644
index 0000000..8df01ff
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageComputeVOIStats.h
@@ -0,0 +1,100 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageComputeVOIStats.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageComputeVOIStats -- compute the difference and a normalized difference
+// between two images
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageComputeVOIStats_h
+#define __vtkpxImageComputeVOIStats_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkpxImageComputeVOIStats : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageComputeVOIStats *New();
+  vtkTypeMacro(vtkpxImageComputeVOIStats,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // VOI -- second input to compare with input
+  vtkSetObjectMacro(VOI,vtkImageData);
+  vtkGetObjectMacro(VOI,vtkImageData);
+
+  // Description:
+  // AbsoluteValue,
+  vtkGetMacro(AbsoluteValue,int);
+  vtkSetClampMacro(AbsoluteValue,int,0,1);
+  vtkBooleanMacro(AbsoluteValue,int);
+
+protected:
+
+  vtkpxImageComputeVOIStats();
+  virtual ~vtkpxImageComputeVOIStats();
+  vtkpxImageComputeVOIStats(const vtkpxImageComputeVOIStats&) {};
+  void operator=(const vtkpxImageComputeVOIStats&) {};
+
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+  virtual void  ExecuteInformation();
+
+  vtkImageData* VOI;
+  int  AbsoluteValue;
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageCorrectNonUniformZ.cpp b/bioimagesuite30_src/Imaging/vtkpxImageCorrectNonUniformZ.cpp
new file mode 100644
index 0000000..8ce2b17
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageCorrectNonUniformZ.cpp
@@ -0,0 +1,236 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxImageCorrectNonUniformZ.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include <stdio.h>
+#include "pxutil.h"
+#include "vtkpxBSpline.h"
+
+vtkpxImageCorrectNonUniformZ* vtkpxImageCorrectNonUniformZ::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageCorrectNonUniformZ");
+  if(ret)
+    {
+      return (vtkpxImageCorrectNonUniformZ*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageCorrectNonUniformZ;
+}
+
+
+// Construct object to extract all of the input data.
+vtkpxImageCorrectNonUniformZ::vtkpxImageCorrectNonUniformZ()
+{
+  this->ZLevels=NULL;
+  this->Spacing=1.0;
+}
+
+// ---------------------------------------------------------------------------
+vtkpxImageCorrectNonUniformZ::~vtkpxImageCorrectNonUniformZ()
+{
+  this->SetZLevels(NULL);
+}
+
+// ---------------------------------------------------------------------------
+void vtkpxImageCorrectNonUniformZ::ExecuteInformation()
+{
+  if (this->ZLevels==NULL)
+    {
+      vtkErrorMacro(<<"No Z-Levels Specified\n");
+      return;
+    }
+
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  vtkImageData *input=this->GetImageDataInput(0);
+  vtkImageData *output=this->GetOutput();
+
+  if (input==NULL)
+    {
+      output->SetSpacing(1,1,1);
+      output->SetOrigin(0,0,0);
+      output->SetWholeExtent(0,0,0,0,0,0);
+
+      return;
+    }
+
+  double sp[3]; input->GetSpacing(sp);
+
+  int wholeExtent[6];
+  int dims[3]; 
+  input->GetDimensions(dims);
+  
+  wholeExtent[0]=0;  
+  wholeExtent[2]=0;
+  wholeExtent[4]=0;  
+    
+  wholeExtent[1] = dims[0]-1;
+  wholeExtent[3] = dims[1]-1;
+
+  float z1=this->ZLevels->GetComponent(0,0);
+  float z2=this->ZLevels->GetComponent(dims[2]-1,0);
+  float dz=fabs(z2-z1);
+
+  wholeExtent[5]= int(dz/this->Spacing+1);
+
+  output->SetSpacing(sp[0],sp[1],this->Spacing);
+  output->SetOrigin(input->GetOrigin());
+  output->SetWholeExtent( wholeExtent );
+  output->SetScalarType(input->GetScalarType());
+  output->SetNumberOfScalarComponents(input->GetNumberOfScalarComponents());
+}
+// ---------------------------------------------------------------------------
+void vtkpxImageCorrectNonUniformZ::SimpleExecute(vtkImageData* input, vtkImageData* output) 
+{
+  if (this->ZLevels==NULL)
+    {
+      vtkErrorMacro(<<"No Z-Levels Specified\n");
+      return;
+    }
+
+
+  fprintf(stderr,"Input Components\n--------------------------\n");
+  int numtuples=this->ZLevels->GetNumberOfTuples();
+  for (int i=0;i<numtuples;i++)
+    fprintf(stderr,"i=%d, z=%.2f\n",i,this->ZLevels->GetComponent(i,0));
+  fprintf(stderr,"\n\n");
+
+  vtkDebugMacro(<< "Resampling CT");
+  this->Spacing=Frange(this->Spacing,0.1,100.0);
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  int dim_o[3]; output->GetDimensions(dim_o);
+  int dim_i[3]; input->GetDimensions(dim_i);
+
+  double spa[3]; output->GetSpacing(spa);
+  double sp_in[3]; input->GetSpacing(sp_in);  
+
+  float z1=this->ZLevels->GetComponent(0,0);
+  float z2=this->ZLevels->GetComponent(dim_i[2]-1,0);
+  float dz=fabs(z2-z1);
+
+  fprintf(stderr,"Dims = %d,%d,%d --> %d,%d,%d,  nom=%.2fx%.2fx%.2f (dz=%.2f)->%.2fx%.2fx%.2f\n",
+	  dim_i[0],dim_i[1],dim_i[2],
+	  dim_o[0],dim_o[1],dim_o[2],
+	  sp_in[0],sp_in[1],sp_in[2],dz,
+	  spa[0],spa[1],spa[2]);
+
+  int slicesize=dim_o[0]*dim_o[1];
+
+  vtkFloatArray* data=vtkFloatArray::New();
+  data->SetNumberOfTuples(dim_i[2]);
+  
+  double ori[3]; output->GetOrigin(ori);
+
+  int numc=input->GetNumberOfScalarComponents();
+  
+  for (int ka=0;ka<dim_o[2];ka++)
+    {
+      float wgt[2],zl[2];
+
+      int baseindex=0;
+      int nextindex=1;
+      wgt[0]=1.0; 
+      wgt[1]=0.0; 
+      zl[0]=this->ZLevels->GetComponent(0,0);
+      zl[1]=this->ZLevels->GetComponent(1,0);
+      float dzl=zl[1]-zl[0];
+
+      float z=ori[2]+ka*spa[2];
+      int reached_top=0;
+      int firstpass=0;
+      /*      fprintf(stderr,"\n ---------------------------- \n Starting z=%.2f zl=%.2f, %.2f indices=%d,%d\n",
+	      z,zl[0],zl[1],baseindex,nextindex);*/
+	
+      
+
+	while (z>zl[1] && reached_top==0)
+	  {
+	    baseindex+=1;
+	    if (baseindex>numtuples-2)
+	      {
+		reached_top=1;
+		baseindex=numtuples-2;
+	      }
+	    
+	    zl[0]=this->ZLevels->GetComponent(baseindex,0);
+	    nextindex=baseindex+1;
+	    zl[1]=this->ZLevels->GetComponent(nextindex,0);
+	    dzl=zl[1]-zl[0];
+	    /*	    fprintf(stderr,"\t  zl=%.2f, %.2f indices=%d,%d\n",
+	      zl[0],zl[1],baseindex,nextindex);*/
+	}
+	  
+      if (z>=zl[0] && z<zl[1])
+	{
+	  wgt[0]=(zl[1]-z)/dzl;
+	  wgt[1]=1.0-wgt[0];
+	}
+      else if (z<zl[0])
+	{
+	  wgt[0]=1.0;
+	  wgt[1]=0.0;
+	}
+      else
+	{
+	  wgt[0]=0.0;
+	  wgt[1]=1.0;
+	}
+
+      fprintf(stderr,"ka=%d z=%.2f ( base=%d,zl[0]=%.2f,wgt[0]=%.3f \t next=%d zl[1]=%.2f,wgt[1]=%.3f) dzl=%.2f\n",
+	      ka,z,
+	      baseindex,zl[0],wgt[0],
+	      nextindex,zl[1],wgt[1],dzl);
+
+      int index=ka*slicesize;
+      for (int j=0;j<dim_o[1];j++)
+	for (int i=0;i<dim_o[0];i++)
+	  {
+	    for (int comp=0;comp<numc;comp++)
+	      out->SetComponent(index,comp,
+				wgt[0]*input->GetScalarComponentAsDouble(i,j,baseindex,comp)+
+				wgt[1]*input->GetScalarComponentAsDouble(i,j,nextindex,comp));
+	    ++index;
+	  }
+    }
+  fprintf(stderr,"\nDone\n");
+  
+  data->Delete();
+
+  
+}
+  
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageCorrectNonUniformZ.h b/bioimagesuite30_src/Imaging/vtkpxImageCorrectNonUniformZ.h
new file mode 100644
index 0000000..908c0e0
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageCorrectNonUniformZ.h
@@ -0,0 +1,113 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+  
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageCorrectNonUniformZ.h,v $
+  Language:  C++
+  Date:      $Date: 2003/05/13 15:37:02 $
+  Version:   $Revision: 1.2 $
+  
+  
+  Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+  All rights reserved.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+  
+=========================================================================*/
+// .NAME vtkpxImageCorrectNonUniformZ - extracts slices from 3D Images
+// .SECTION Description
+// Extracts single 2D slice from 3D Images determined by slice number, CurrentPlane and flip 
+// CurrentPlane = 0=YZ, 1=XZ, 2=XY
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkExtractVOI
+
+#ifndef __vtkpxImageCorrectNonUniformZ_h
+#define __vtkpxImageCorrectNonUniformZ_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+
+class vtkpxImageCorrectNonUniformZ : public vtkpxSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkpxImageCorrectNonUniformZ,vtkpxSimpleImageToImageFilter);
+  // Description:
+  // Construct object to extract all of the input data.
+  static vtkpxImageCorrectNonUniformZ *New();
+
+  
+  
+  // Description:
+  // Use this to set sliceno,numslices and currentplane
+  // for extracting frames
+  vtkSetObjectMacro(ZLevels,vtkFloatArray);
+  vtkGetObjectMacro(ZLevels,vtkFloatArray);
+
+  // Description:
+  // Output Spacing
+  vtkSetMacro(Spacing,float);
+  vtkGetMacro(Spacing,float);
+
+
+
+protected:
+  //BTX
+  vtkpxImageCorrectNonUniformZ();
+  virtual ~vtkpxImageCorrectNonUniformZ();
+  vtkpxImageCorrectNonUniformZ(const vtkpxImageCorrectNonUniformZ&) {};
+  void operator=(const vtkpxImageCorrectNonUniformZ&) {};
+
+
+
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+  virtual void ExecuteInformation();
+
+  float Spacing;
+  vtkFloatArray* ZLevels;
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageCylindricalCrop.cpp b/bioimagesuite30_src/Imaging/vtkpxImageCylindricalCrop.cpp
new file mode 100644
index 0000000..e19d220
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageCylindricalCrop.cpp
@@ -0,0 +1,118 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxImageCylindricalCrop.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+
+vtkpxImageCylindricalCrop* vtkpxImageCylindricalCrop::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageCylindricalCrop");
+  if(ret)
+    {
+      return (vtkpxImageCylindricalCrop*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageCylindricalCrop;
+}
+
+
+// Construct object to extract all of the input data.
+vtkpxImageCylindricalCrop::vtkpxImageCylindricalCrop()
+{
+
+  this->Center[0]=-1000;
+  this->Center[1]=-1000;
+  this->Center[2]=-1000;
+  this->Radius=-1;
+}
+
+// ---------------------------------------------------------------------------
+void vtkpxImageCylindricalCrop::SimpleExecute(vtkImageData* input, vtkImageData* output) 
+{
+  int dim[3]; input->GetDimensions(dim);
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (this->Center[ia]==-1000)
+	this->Center[ia]=dim[ia]/2;
+    }
+  if (this->Radius<0)
+    this->Radius=dim[0]/2;
+    
+  int numc=input->GetNumberOfScalarComponents();
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  
+  for (int c=0;c<numc;c++)
+    out->FillComponent(c,0.0);
+
+
+  /*  fprintf(stderr,"Cropping Center (%d,%d,%d) Radius=%d\n",
+	  this->Center[0],
+	  this->Center[1],
+	  this->Center[2],
+	  this->Radius);*/
+
+  int index=0;
+  this->UpdateProgress(0.01);
+
+  double thr=double(this->Radius*this->Radius);
+
+  for (int k=0;k<dim[2];k++)
+    {
+      for (int j=0;j<dim[1];j++)
+	{
+	  double dj=pow(double(j-this->Center[1]),2.0);
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      double di=pow(double(i-this->Center[0]),2.0);
+	      double d=di+dj;
+	      
+	      if (d<thr)
+		{
+		  for (int c=0;c<numc;c++)
+		    out->SetComponent(index,c,inp->GetComponent(index,c));
+		}
+
+	      ++index;
+	    }
+	}
+      this->UpdateProgress(float(k+1)/float(dim[2]));
+    }
+}
+  
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageCylindricalCrop.h b/bioimagesuite30_src/Imaging/vtkpxImageCylindricalCrop.h
new file mode 100644
index 0000000..4a25938
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageCylindricalCrop.h
@@ -0,0 +1,98 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+  
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageCylindricalCrop.h,v $
+  Language:  C++
+  Date:      $Date: 2003/05/13 15:37:02 $
+  Version:   $Revision: 1.2 $
+  
+  
+  Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+  All rights reserved.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+  
+=========================================================================*/
+// .NAME vtkpxImageCylindricalCrop - extracts slices from 3D Images
+
+
+
+#ifndef __vtkpxImageCylindricalCrop_h
+#define __vtkpxImageCylindricalCrop_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+
+class vtkpxImageCylindricalCrop : public vtkpxSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkpxImageCylindricalCrop,vtkpxSimpleImageToImageFilter);
+  // Description:
+  // Construct object to extract all of the input data.
+  static vtkpxImageCylindricalCrop *New();
+
+  // Description:
+  // Radius
+  vtkSetMacro(Radius,int);
+  vtkGetMacro(Radius,int);
+
+  // Description:
+  vtkSetVector3Macro( Center, int );
+  vtkGetVector3Macro( Center, int );
+
+protected:
+  //BTX
+  vtkpxImageCylindricalCrop();
+  vtkpxImageCylindricalCrop(const vtkpxImageCylindricalCrop&);
+  void operator=(const vtkpxImageCylindricalCrop&) {};
+
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+
+  int Radius;
+  int Center[3];
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageFeatureExtract.cpp b/bioimagesuite30_src/Imaging/vtkpxImageFeatureExtract.cpp
new file mode 100644
index 0000000..2119f22
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageFeatureExtract.cpp
@@ -0,0 +1,314 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageFeatureExtract.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:14:21 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkFloatArray.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageGradient.h"
+#include "vtkImageMathematics.h"
+#include "vtkImageNonMaximumSuppression.h"
+#include "vtkImageShiftScale.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxImageFeatureExtract.h"
+#include "vtkpxUtil.h"
+#include "vtkDataArray.h"
+vtkpxImageFeatureExtract* vtkpxImageFeatureExtract::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageFeatureExtract");
+  if(ret)
+      {
+	return (vtkpxImageFeatureExtract*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageFeatureExtract;
+}
+
+
+// Construct object to extract all of the input data.
+vtkpxImageFeatureExtract::vtkpxImageFeatureExtract()
+{
+  this->CornerThreshold=0.5;
+  this->DetectionThreshold=1.0;
+  this->Mode=0;
+  this->NonMaximumSuppression=0;
+  this->SmoothSigma=1.0;
+  this->DataDimensions=3;
+}
+
+
+void vtkpxImageFeatureExtract::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkpxSimpleImageToImageFilter::PrintSelf(os,indent);
+  os << indent << "  DataDimensions " << this->DataDimensions << "\n";
+  os << indent << "  Mode " << this->Mode << "\n";
+  os << indent << "  SmoothSigma " << this->SmoothSigma << "\n";
+  os << indent << "  CornerThreshold " << this->CornerThreshold << "\n";
+  os << indent << "  DetectionThreshold " << this->DetectionThreshold << "\n";
+  os << indent << "  NonMaximumSuppression " << this->NonMaximumSuppression << "\n";
+}
+
+
+
+float vtkpxImageFeatureExtract::ComputeFeatureValue(float Cg[3][3])
+{
+  float detCg=0.0,traceCg=0.0;
+  int ia;
+  // Dim=2,3 
+  switch (this->DataDimensions)
+    {
+    case 2:
+      traceCg=Cg[0][0]+Cg[1][1];
+      detCg=Cg[0][0]*Cg[1][1]-Cg[0][1]*Cg[1][0];
+      break;
+    case 3:
+      traceCg=0.0;
+      for (ia=0;ia<=2;ia++)
+	traceCg+=Cg[ia][ia];
+      detCg=vtkMath::Determinant3x3(Cg);
+      break;
+    }
+
+  if (traceCg<this->DetectionThreshold)
+    return 0.0;
+
+  float Op=fabs(detCg/traceCg);
+
+  if (this->Mode==0)
+    return sqrt(traceCg);
+
+  if (this->Mode==1)
+    return sqrt(fabs(detCg));
+
+  if (this->Mode==2)
+    {
+      if (Op<this->DetectionThreshold)
+	return 0.0;
+      else
+	return Op;
+    }
+
+  float fdim=float(this->DataDimensions);
+  float ifdim=1.0/fdim;
+  float OpR=fabs(detCg/pow(ifdim*traceCg,fdim));
+
+  if (OpR<CornerThreshold || Op<this->DetectionThreshold)
+    return 0.0;
+  else 
+    return  Op;
+  
+}
+
+void vtkpxImageFeatureExtract::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  vtkDebugMacro(<< "Extracting Features");
+
+  // Step 1: Smooth Image 
+  int ia,ib;
+  float Cg[3][3];
+
+  // Step 1: Smooth Image  
+  vtkImageGaussianSmooth* presmooth=vtkImageGaussianSmooth::New();
+  presmooth->SetInput(input);
+  presmooth->SetDimensionality(this->DataDimensions);
+  presmooth->SetStandardDeviations(this->SmoothSigma,this->SmoothSigma,this->SmoothSigma);
+  presmooth->Update();
+  vtkDebugMacro(<< "1. Presmooth Done");
+
+  // Step 2: Calculate Gradients  
+  vtkImageGradient* gradFilter=vtkImageGradient::New();
+  gradFilter->SetInput(presmooth->GetOutput());
+  gradFilter->SetDimensionality(this->DataDimensions);
+  gradFilter->HandleBoundariesOn();
+  gradFilter->Update();
+  presmooth->Delete();
+
+  vtkDebugMacro(<< "2. Gradients Done");
+
+  // Step 3: Extract Components of Smoothed  Gradients  
+  vtkImageExtractComponents* compFilter[3];
+  for (ia=0;ia<this->DataDimensions;ia++)
+    {
+      compFilter[ia]=vtkImageExtractComponents::New();
+
+      compFilter[ia]->SetInput(gradFilter->GetOutput());
+      compFilter[ia]->SetComponents(ia);
+      compFilter[ia]->Update();
+      vtkDebugMacro(<< "3." << ia+1  << " Extrating Component ("<<ia+1<<") Done");
+    }
+  
+
+  // Step 4: Compute 3x3 Matrix C
+  vtkImageMathematics* compCg[3][3];
+
+  for (ia=0;ia<this->DataDimensions;ia++)
+    for (ib=ia;ib<this->DataDimensions;ib++)
+      {
+	compCg[ia][ib]=vtkImageMathematics::New();
+
+	compCg[ia][ib]->SetOperationToMultiply();
+	compCg[ia][ib]->SetInput1(compFilter[ia]->GetOutput());
+	compCg[ia][ib]->SetInput2(compFilter[ib]->GetOutput());
+	compCg[ia][ib]->Update();
+	vtkDebugMacro(<< "4." << ia+1 <<"."<<ib+1<< " Computing Product ("<<ia+1<<"x"<<ib+1<<") Done");
+      }
+  for (ia=0;ia<this->DataDimensions;ia++)
+    compFilter[ia]->Delete();
+
+  vtkImageGaussianSmooth* matrixCg[3][3];
+  for (ia=0;ia<this->DataDimensions;ia++)
+    for (ib=ia;ib<this->DataDimensions;ib++)
+      {
+	matrixCg[ia][ib]=vtkImageGaussianSmooth::New();
+	matrixCg[ia][ib]->SetInput(compCg[ia][ib]->GetOutput());
+	matrixCg[ia][ib]->SetStandardDeviations(this->SmoothSigma,this->SmoothSigma,this->SmoothSigma);
+	matrixCg[ia][ib]->SetDimensionality(this->DataDimensions);
+	//	matrixCg[ia][ib]->BypassOn();
+	matrixCg[ia][ib]->Update();
+	vtkDebugMacro(<< "5." << ia+1 <<"."<<ib+1<< " Computing Smooth Product ("<<ia+1<<"x"<<ib+1<<") Done");
+      }
+ 
+  for (ia=0;ia<this->DataDimensions;ia++)
+    for (ib=ia;ib<this->DataDimensions;ib++)
+      compCg[ia][ib]->Delete();
+
+  // Step 6: For Each voxel get appropriate components and store in matrix C 
+  // Then compute Feature Values 
+
+  // First Allocate Output 
+
+  int dty=matrixCg[0][0]->GetOutput()->GetPointData()->GetScalars()->GetDataType();
+  int dim[3];
+  matrixCg[0][0]->GetOutput()->GetDimensions(dim);
+  
+  output->SetDimensions(matrixCg[0][0]->GetOutput()->GetDimensions());
+  output->SetWholeExtent(matrixCg[0][0]->GetOutput()->GetWholeExtent());
+  output->SetUpdateExtent(matrixCg[0][0]->GetOutput()->GetWholeExtent());
+  output->SetSpacing(matrixCg[0][0]->GetOutput()->GetSpacing());
+  output->SetOrigin(matrixCg[0][0]->GetOutput()->GetOrigin());
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(dty);
+  output->AllocateScalars();
+
+
+  // First make Cg = identity 
+  for (ia=0;ia<=2;ia++)
+    for (ib=0;ib<=2;ib++)
+      Cg[ia][ib]=float(ia==ib);
+  
+  int totalsize=dim[0]*dim[1]*dim[2];
+
+  vtkDebugMacro(<< "6. Pointers in place totalsize="<<totalsize);
+
+  for (int pixel=0;pixel<totalsize;pixel++)
+    {
+      for (ia=0;ia<this->DataDimensions;ia++)
+	{
+	  Cg[ia][ia]=matrixCg[ia][ia]->GetOutput()->GetPointData()->GetScalars()->GetComponent(pixel,0);
+	  for (ib=ia+1;ib<this->DataDimensions;ib++)
+	    {
+	      Cg[ia][ib]=matrixCg[ia][ib]->GetOutput()->GetPointData()->GetScalars()->GetComponent(pixel,0);
+	      Cg[ib][ia]=Cg[ia][ib];
+	    }
+	}
+      float v=ComputeFeatureValue(Cg);
+      output->GetPointData()->GetScalars()->SetComponent(pixel,0,v);
+    }
+
+  for (ia=0;ia<this->DataDimensions;ia++)
+    for (ib=ia;ib<this->DataDimensions;ib++)
+      matrixCg[ia][ib]->Delete();
+
+  vtkImageData* std=vtkImageData::New();
+  std->ShallowCopy(output);
+
+  if (this->NonMaximumSuppression)
+    {
+      vtkImageNonMaximumSuppression* nonMax=vtkImageNonMaximumSuppression::New();
+      nonMax->SetVectorInput(gradFilter->GetOutput());
+      nonMax->SetMagnitudeInput(std);
+      nonMax->SetDimensionality(this->DataDimensions);
+      nonMax->Update();
+      std->ShallowCopy(nonMax->GetOutput());
+      nonMax->Delete();
+      vtkDebugMacro(<< "6.5 NonMaximum Suppression Done");
+    }
+
+  output->GetDimensions(dim);  
+  double range[2];
+  output->GetPointData()->GetScalars()->GetRange(range);
+  float sc2=255.0/(range[1]-range[0]);
+
+  vtkImageShiftScale *shiftscale=vtkImageShiftScale::New();
+  shiftscale->SetInput(std);
+  shiftscale->SetShift(-range[0]);
+  shiftscale->SetScale(sc2);
+  shiftscale->SetOutputScalarTypeToUnsignedChar();
+  shiftscale->Update();
+  output->ShallowCopy(shiftscale->GetOutput());
+  output->GetPointData()->GetScalars()->GetRange(range);
+
+  vtkDebugMacro(<< "7. Scaled Output to lie in 0:255");
+  
+  shiftscale->Delete();
+  std->Delete();
+  gradFilter->Delete();
+
+}
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageFeatureExtract.h b/bioimagesuite30_src/Imaging/vtkpxImageFeatureExtract.h
new file mode 100644
index 0000000..cbccc51
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageFeatureExtract.h
@@ -0,0 +1,132 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageFeatureExtract.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:13:39 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxBrainPreSegment - simple brain segmentation algorithm
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageFeatureExtract_h
+#define __vtkpxImageFeatureExtract_h
+
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+
+class vtkpxImageFeatureExtract : public vtkpxSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkpxImageFeatureExtract,vtkpxSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Construct object to extract all of the input data.
+
+  static vtkpxImageFeatureExtract *New();
+
+  // Description:
+  // Set Detection Threshold for C/det ratio
+  vtkSetMacro(DetectionThreshold,float);
+  vtkGetMacro(DetectionThreshold,float);
+
+  // Description:
+  // Set Detection Threshold for Corner Ratio 
+  vtkSetClampMacro(CornerThreshold,float,0.0,1.0);
+  vtkGetMacro(CornerThreshold,float);
+
+  // Description:
+  // Flag to determine whether to extract only corners
+  vtkGetMacro(Mode,int);
+  vtkSetClampMacro(Mode,int,0,3);
+
+  // Description:
+  // Flag to determine whether to extract only corners
+  vtkGetMacro(NonMaximumSuppression,int);
+  vtkSetClampMacro(NonMaximumSuppression,int,0,1);
+  vtkBooleanMacro(NonMaximumSuppression,int);
+
+  // Description:
+  // Smoothing for initial gradient extraction
+  vtkGetMacro(SmoothSigma,float);
+  vtkSetMacro(SmoothSigma,float);
+
+  // Description:
+  // Number of Erosions/Dilations if enabled
+  vtkGetMacro(DataDimensions,int);
+  vtkSetClampMacro(DataDimensions,int,2,3);
+
+protected:
+  //BTX
+  vtkpxImageFeatureExtract();
+  ~vtkpxImageFeatureExtract() {};
+  vtkpxImageFeatureExtract(const vtkpxImageFeatureExtract&) {};
+  void operator=(const vtkpxImageFeatureExtract&) {};
+
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData *out);
+
+  float ComputeFeatureValue(float Cg[3][3]);
+
+  float CornerThreshold;
+  float DetectionThreshold;
+  int   Mode;
+  float SmoothSigma;
+  int   DataDimensions;
+  int   NonMaximumSuppression;
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageGaussianNoiseSource.cpp b/bioimagesuite30_src/Imaging/vtkpxImageGaussianNoiseSource.cpp
new file mode 100644
index 0000000..7f36399
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageGaussianNoiseSource.cpp
@@ -0,0 +1,223 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSurfaceUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include <math.h>
+
+#include "vtkpxImageGaussianNoiseSource.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+
+//------------------------------------------------------------------------------
+vtkpxImageGaussianNoiseSource* vtkpxImageGaussianNoiseSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageGaussianNoiseSource");
+  if(ret)
+    {
+    return (vtkpxImageGaussianNoiseSource*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageGaussianNoiseSource;
+}
+
+
+
+
+//----------------------------------------------------------------------------
+vtkpxImageGaussianNoiseSource::vtkpxImageGaussianNoiseSource()
+{
+  this->Magnitude = 2.0;
+  this->NumberOfComponents= 1;
+  this->WholeExtent[0]=0;   this->WholeExtent[1]=255;
+  this->WholeExtent[2]=0;   this->WholeExtent[3]=255;
+  this->WholeExtent[4]=0;   this->WholeExtent[5]=255;
+}
+
+
+//----------------------------------------------------------------------------
+void vtkpxImageGaussianNoiseSource::SetWholeExtent(int xMin, int xMax, 
+						   int yMin, int yMax,
+						   int zMin, int zMax)
+{
+  int modified = 0;
+  
+  if (this->WholeExtent[0] != xMin)
+    {
+    modified = 1;
+    this->WholeExtent[0] = xMin ;
+    }
+  if (this->WholeExtent[1] != xMax)
+    {
+    modified = 1;
+    this->WholeExtent[1] = xMax ;
+    }
+  if (this->WholeExtent[2] != yMin)
+    {
+    modified = 1;
+    this->WholeExtent[2] = yMin ;
+    }
+  if (this->WholeExtent[3] != yMax)
+    {
+    modified = 1;
+    this->WholeExtent[3] = yMax ;
+    }
+  if (this->WholeExtent[4] != zMin)
+    {
+    modified = 1;
+    this->WholeExtent[4] = zMin ;
+    }
+  if (this->WholeExtent[5] != zMax)
+    {
+    modified = 1;
+    this->WholeExtent[5] = zMax ;
+    }
+  if (modified)
+    {
+    this->Modified();
+    }
+}
+
+//----------------------------------------------------------------------------
+float vtkpxImageGaussianNoiseSource::GaussianRandom()
+{
+  static int iset=0;
+  static float gset;
+  float fac,rsq,v1,v2;
+
+  if  (iset == 0) 
+    {
+      do 
+	{
+	  v1=2.0*vtkMath::Random()-1.0;
+	  v2=2.0*vtkMath::Random()-1.0;
+	  rsq=v1*v1+v2*v2;
+	} 
+      while (rsq >= 1.0 || rsq == 0.0);
+      
+      fac=sqrt(-2.0*log(rsq)/rsq);
+      gset=v1*fac;
+      iset=1;
+      return v2*fac;
+    } 
+  else
+    {
+      iset=0;
+      return gset;
+    }
+}
+//----------------------------------------------------------------------------
+void vtkpxImageGaussianNoiseSource::ExecuteInformation()
+{
+  vtkImageData *output = this->GetOutput();
+  
+  output->SetWholeExtent(this->WholeExtent);
+  output->SetScalarType(VTK_FLOAT);
+  output->SetNumberOfScalarComponents(this->NumberOfComponents);
+}
+
+void vtkpxImageGaussianNoiseSource::ExecuteData(vtkDataObject *output)
+{
+  vtkImageData *data = this->AllocateOutputData(output);
+
+  if (data->GetScalarType() != VTK_FLOAT)
+    vtkErrorMacro("Execute: This source only outputs floats");
+  
+  int *outExt = data->GetExtent();
+  
+  // find the region to loop over
+
+  int rowLength = (outExt[1] - outExt[0]+1)*data->GetNumberOfScalarComponents();
+  int maxY = outExt[3] - outExt[2]; 
+  int maxZ = outExt[5] - outExt[4];
+  
+  // Get increments to march through data 
+
+  vtkIdType outIncX, outIncY, outIncZ;
+  data->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
+  float*  outPtr = (float *) data->GetScalarPointer(outExt[0],outExt[2],outExt[4]);
+  
+  unsigned long target = (unsigned long)((maxZ+1)*(maxY+1)/50.0);
+  unsigned long count = 0;
+  target++;
+
+  for (int idxZ = 0; idxZ <= maxZ; idxZ++)
+    {
+      for (int idxY = 0; !this->AbortExecute && idxY <= maxY; idxY++)
+	{
+	  if (!(count%target))
+	    this->UpdateProgress(count/(50.0*target));
+	  
+	  count++;
+	  for (int idxR = 0; idxR < rowLength; idxR++)
+	    {
+	      *outPtr = this->Magnitude * vtkpxImageGaussianNoiseSource::GaussianRandom();
+	      outPtr++;
+	    }
+	  outPtr += outIncY;
+	}
+      outPtr += outIncZ;
+    }
+}
+
+void vtkpxImageGaussianNoiseSource::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkImageSource::PrintSelf(os,indent);
+  os << indent << "NumberOfComponents: " << this->NumberOfComponents << "\n";
+  os << indent << "Magnitude: " << this->Magnitude << "\n";
+}
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageGaussianNoiseSource.h b/bioimagesuite30_src/Imaging/vtkpxImageGaussianNoiseSource.h
new file mode 100644
index 0000000..0d982ee
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageGaussianNoiseSource.h
@@ -0,0 +1,106 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSurfaceUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageGaussianNoiseSource - Create an image of Gaussian noise 
+// .SECTION Description
+// vtkpxImageGaussianNoiseSource just produces images with pixel values determined 
+// by a Gaussian noise model
+
+#ifndef __vtkpxImageGaussianNoiseSource_h
+#define __vtkpxImageGaussianNoiseSource_h
+
+#include "vtkImageSource.h"
+
+class  vtkpxImageGaussianNoiseSource : public vtkImageSource
+{
+public:
+  static vtkpxImageGaussianNoiseSource *New();
+  vtkTypeMacro(vtkpxImageGaussianNoiseSource,vtkImageSource);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Set/Get the extent of the whole output image.
+  void SetWholeExtent(int xMinx, int xMax, int yMin, int yMax,int zMin, int zMax);
+  
+  // Description:
+  // Set/Get the standard deviation of the gaussian
+  vtkSetMacro(Magnitude, float);
+  vtkGetMacro(Magnitude, float);
+
+  // Description:
+  // Set the number of Components in time 
+  vtkSetMacro(NumberOfComponents, int);
+  vtkGetMacro(NumberOfComponents, int);
+
+protected:
+  vtkpxImageGaussianNoiseSource();
+  ~vtkpxImageGaussianNoiseSource() {};
+
+
+  int WholeExtent[6];
+  int NumberOfComponents;
+  float Magnitude;
+
+  virtual void ExecuteInformation();
+  virtual void ExecuteData(vtkDataObject *data);
+  static  float GaussianRandom();
+private:
+  vtkpxImageGaussianNoiseSource(const vtkpxImageGaussianNoiseSource&);  // Not implemented.
+  void operator=(const vtkpxImageGaussianNoiseSource&);  // Not implemented.
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageHistogramEqualization.cpp b/bioimagesuite30_src/Imaging/vtkpxImageHistogramEqualization.cpp
new file mode 100644
index 0000000..b4a9fa9
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageHistogramEqualization.cpp
@@ -0,0 +1,191 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageHistogramEqualization.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxImageHistogramEqualization.h"
+#include "vtkpxUtil.h"
+#include "vtkIntArray.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageAccumulate.h"
+#include "vtkImageExtractComponents.h"
+//------------------------------------------------------------------------------
+vtkpxImageHistogramEqualization* vtkpxImageHistogramEqualization::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageHistogramEqualization");
+  if(ret)
+    {
+    return (vtkpxImageHistogramEqualization*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageHistogramEqualization;
+}
+
+// Construct object with no children.
+vtkpxImageHistogramEqualization::vtkpxImageHistogramEqualization()
+{
+  this->LowerThreshold=-1.0e+9;
+  this->UpperThreshold= 1.0e+9;
+  this->NumberOfBins=256;
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageHistogramEqualization::SimpleExecute(vtkImageData* input ,vtkImageData* output)
+{
+
+  if (this->GetImageDataInput(0)==NULL)
+    {
+      vtkErrorMacro(<<"Bad Input to vtkpxImageHistogramEqualization");
+      return;
+    }
+
+  // Compute Histogram with N-bins from Threshold to max
+  // Compute Cumulative Histogram
+  // Normalize Intensity
+
+  int dim[3];
+  this->GetImageDataInput(0)->GetDimensions(dim);
+
+  int numcomp=input->GetNumberOfScalarComponents();
+  int numvox=dim[0]*dim[1]*dim[2];
+
+  vtkDataArray* inarray=input->GetPointData()->GetScalars();
+  vtkDataArray* outarray=output->GetPointData()->GetScalars();
+
+
+  vtkImageExtractComponents* comp=vtkImageExtractComponents::New();
+  comp->SetInput(input);
+  
+ 
+  vtkIntArray* hist=vtkIntArray::New();
+  hist->SetNumberOfComponents(1);
+
+
+  vtkImageAccumulate* accum=vtkImageAccumulate::New(); 
+  accum->SetInput(comp->GetOutput());
+
+  this->UpdateProgress(0.01);
+
+
+  
+  for (int component=0;component<numcomp;component++)
+    {
+      comp->SetComponents(component);
+      comp->Update();
+      int numbins=this->NumberOfBins;
+
+
+      double r[2]; comp->GetOutput()->GetPointData()->GetScalars()->GetRange(r);
+
+      float pmin=Fmax(this->LowerThreshold,r[0]);
+      float pmax=Fmin(this->UpperThreshold,r[1]);
+      if (pmax<pmin)
+	{
+	  float t=pmax;
+	  pmax=pmin;
+	  pmin=t;
+	}
+
+      float prange=pmax-pmin;
+      if (numbins>prange)
+	numbins=(int)prange;
+      float pspacing=prange/float(numbins);
+      
+      // Computes the Histogram
+      accum->SetComponentExtent(0,numbins-1,0,0,0,0);
+      accum->SetComponentOrigin(pmin,0,0);
+      accum->SetComponentSpacing(pspacing,1,1);
+      accum->Update();
+     
+
+      // Compute Cumulative Histogram
+      if (hist->GetNumberOfTuples()!=numbins)
+	hist->SetNumberOfTuples(numbins);
+      hist->CopyComponent(0,accum->GetOutput()->GetPointData()->GetScalars(),0);
+
+      for (int ia=1;ia<numbins;ia++)
+	hist->SetComponent(ia,0,hist->GetComponent(ia,0)+hist->GetComponent(ia-1,0));
+      float totalv=hist->GetComponent(numbins-1,0);
+
+      // Re-normalize intensity 
+
+      for (int i=0;i<numvox;i++)
+	{
+	  float v=inarray->GetComponent(i,component);
+	  if (v<=pmin)
+	    {
+	      v=0;
+	    }
+	  else if (v>=pmax)
+	    {
+	      v=numbins-1;
+	    }
+	  else
+	    {
+	      int index=int(0.5+float(numbins-1)*(v-pmin)/prange);
+	      float numv=hist->GetComponent(index,0);
+	      v=numv/totalv*float(numbins-1);
+	    }
+	  outarray->SetComponent(i,component,v);
+	}
+      this->UpdateProgress(float(component+1)/float(numcomp));      
+    }
+	      
+  hist->Delete();
+  comp->Delete();
+  accum->Delete();
+
+  this->UpdateProgress(1.0);
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageHistogramEqualization.h b/bioimagesuite30_src/Imaging/vtkpxImageHistogramEqualization.h
new file mode 100644
index 0000000..053c41f
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageHistogramEqualization.h
@@ -0,0 +1,103 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageHistogramEqualization.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageHistogramEqualization -- compute the difference and a normalized difference
+// between two images
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageHistogramEqualization_h
+#define __vtkpxImageHistogramEqualization_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkpxImageHistogramEqualization : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageHistogramEqualization *New();
+  vtkTypeMacro(vtkpxImageHistogramEqualization,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set the level between 0 and 1 below which the data (in the ref image) is
+  // not used to compute the equalization
+  vtkGetMacro(LowerThreshold,float);
+  vtkSetMacro(LowerThreshold,float);
+  vtkGetMacro(UpperThreshold,float);
+  vtkSetMacro(UpperThreshold,float);
+
+  // Description:
+  // Number of Bins to Compute Histogram
+  vtkGetMacro(NumberOfBins,int);
+  vtkSetClampMacro(NumberOfBins,int,8,1024);
+
+
+protected:
+
+  vtkpxImageHistogramEqualization();
+  vtkpxImageHistogramEqualization(const vtkpxImageHistogramEqualization&) {};
+  void operator=(const vtkpxImageHistogramEqualization&) {};
+
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  //BTX
+  float       LowerThreshold,UpperThreshold;
+  int         NumberOfBins;
+  //ETX
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageIDFilter.cpp b/bioimagesuite30_src/Imaging/vtkpxImageIDFilter.cpp
new file mode 100644
index 0000000..d54fe8d
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageIDFilter.cpp
@@ -0,0 +1,212 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageIDFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxImageIDFilter.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxUtil.h"
+#include "vtkImageToImageFilter.h"
+#include "vtkIdList.h"
+//------------------------------------------------------------------------------
+vtkpxImageIDFilter* vtkpxImageIDFilter::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageIDFilter");
+  if(ret)
+    {
+    return (vtkpxImageIDFilter*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageIDFilter;
+}
+
+//----------------------------------------------------------------------------
+// Constructor sets default values
+vtkpxImageIDFilter::vtkpxImageIDFilter()
+{
+  this->OutputScalarType = VTK_UNSIGNED_CHAR;
+  this->IdList=NULL;
+  this->InValue=1.0;
+  this->OutValue=0.0;
+}
+
+vtkpxImageIDFilter::~vtkpxImageIDFilter()
+{
+  this->SetIdList(NULL);
+}
+
+//----------------------------------------------------------------------------
+void vtkpxImageIDFilter::ExecuteInformation(vtkImageData *inData, 
+					    vtkImageData *outData)
+{
+  this->vtkImageToImageFilter::ExecuteInformation( inData, outData );
+
+  if (this->OutputScalarType != -1)
+    outData->SetScalarType(this->OutputScalarType);
+}
+
+//----------------------------------------------------------------------------
+// This templated function executes the filter for any type of data.
+template <class IT, class OT>
+static void vtkpxImageIDFilterExecute(vtkpxImageIDFilter *self,
+				      vtkImageData *inData, IT *inPtr,
+				      vtkImageData *outData, OT *outPtr,
+				      int outExt[6], int id)
+{
+
+  vtkIdList* IdList=self->GetIdList();
+  float InValue=self->GetInValue();
+  float OutValue=self->GetOutValue();
+
+  int idxR, idxY, idxZ;
+  int maxY, maxZ;
+  vtkIdType inIncX, inIncY, inIncZ;
+  vtkIdType outIncX, outIncY, outIncZ;
+  int rowLength;
+  unsigned long count = 0;
+  unsigned long target;
+
+
+  // find the region to loop over
+  rowLength = (outExt[1] - outExt[0]+1)*inData->GetNumberOfScalarComponents();
+  maxY = outExt[3] - outExt[2]; 
+  maxZ = outExt[5] - outExt[4];
+  target = (unsigned long)((maxZ+1)*(maxY+1)/50.0);
+  target++;
+  
+  // Get increments to march through data 
+  inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
+  outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
+  
+  // Loop through ouput pixels
+  for (idxZ = 0; idxZ <= maxZ; idxZ++)
+    {
+    for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++)
+      {
+	if (!id) 
+	  {
+	    if (!(count%target))
+	      {
+		self->UpdateProgress(count/(50.0*target));
+	      }
+	    count++;
+	  }
+	
+	for (idxR = 0; idxR < rowLength; idxR++)
+	  {
+	  // Pixel operation
+	    vtkIdType val = ((vtkIdType)(*inPtr)); 
+	    if (IdList->IsId(val)>=0)
+	      *outPtr = (OT)(InValue);
+	    else
+	      *outPtr = (OT)(OutValue);
+	    outPtr++;
+	    inPtr++;
+	  }
+	
+	outPtr += outIncY;
+	inPtr += inIncY;
+      }
+    outPtr += outIncZ;
+    inPtr += inIncZ;
+    }
+}
+//----------------------------------------------------------------------------
+// This method is passed a input and output data, and executes the filter
+// algorithm to fill the output from the input.
+// It just executes a switch statement to call the correct function for
+// the datas data types.
+void vtkpxImageIDFilter::ThreadedExecute(vtkImageData *inData, 
+					vtkImageData *outData,
+					int outExt[6], int id)
+{
+  void *inPtr = inData->GetScalarPointerForExtent(outExt);
+  void *outPtr = outData->GetScalarPointerForExtent(outExt);
+  
+  vtkIdList* Map=this->GetIdList();
+  if (Map->GetNumberOfIds()<1)
+    {
+      vtkErrorMacro(<<"Bad ID List number of ids="<<Map->GetNumberOfIds()<<"<1");
+      return;
+    }
+
+
+
+  switch (inData->GetScalarType())
+    {
+      vtkTemplateMacro7(vtkpxImageIDFilterExecute,this, 
+			inData, (VTK_TT *)(inPtr), 
+			outData,(VTK_TT *)(outPtr), 
+			outExt, id);
+
+    default:
+      vtkErrorMacro(<< "Execute: Unknown ScalarType");
+      return;
+    }
+}
+
+
+
+void vtkpxImageIDFilter::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkImageToImageFilter::PrintSelf(os,indent);
+  os << indent << "IdList: "<<this->IdList;
+  os << indent << "InValue: "<<this->InValue;
+  os << indent << "OutValue: "<<this->OutValue;
+  os << indent << "Output Scalar Type: " << this->OutputScalarType << "\n";
+}
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageIDFilter.h b/bioimagesuite30_src/Imaging/vtkpxImageIDFilter.h
new file mode 100644
index 0000000..0d113f1
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageIDFilter.h
@@ -0,0 +1,133 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageIDFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageIDFilter - piecewise linear intensity map
+// .SECTION Description
+// This filter maps intensities to either InValue or OutValue
+// depending on whether the input value is in IdList
+// <br> <br> <EM>Copyright (c) 1995-2005 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+
+#ifndef __vtkpxImageIDFilter_h
+#define __vtkpxImageIDFilter_h
+
+
+class vtkImageToImageFilter;
+
+#include "vtkImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkIdList.h"
+
+
+class vtkpxImageIDFilter : public vtkImageToImageFilter
+{
+public:
+  static vtkpxImageIDFilter *New();
+  vtkTypeMacro(vtkpxImageIDFilter,vtkImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  
+  // Description:
+  // Set/Get the InputLevels
+  vtkSetObjectMacro(IdList,vtkIdList);
+  vtkGetObjectMacro(IdList,vtkIdList);
+
+  // Description:
+  // Index in Region
+  vtkGetMacro(InValue,float);
+  vtkSetMacro(InValue,float);
+
+  // Description:
+  // Index in Region
+  vtkGetMacro(OutValue,float);
+  vtkSetMacro(OutValue,float);
+
+  // Set the desired output scalar type.  The result of the algebra
+  // operations is cast to the type specified.
+  vtkSetMacro(OutputScalarType, int);
+  vtkGetMacro(OutputScalarType, int);
+  void SetOutputScalarTypeToShort()
+    {this->SetOutputScalarType(VTK_SHORT);}
+  void SetOutputScalarTypeToChar()
+    {this->SetOutputScalarType(VTK_CHAR);}
+  void SetOutputScalarTypeToUnsignedChar()
+    {this->SetOutputScalarType(VTK_UNSIGNED_CHAR);}
+
+
+protected:
+  //BTX
+  vtkpxImageIDFilter();
+  ~vtkpxImageIDFilter();
+  vtkpxImageIDFilter(const vtkpxImageIDFilter&) {};
+  void operator=(const vtkpxImageIDFilter&) {};
+
+
+  vtkIdList* IdList;
+  float InValue;
+  float OutValue;
+  int OutputScalarType;
+
+  void ExecuteInformation(vtkImageData *inData, vtkImageData *outData);
+  void ExecuteInformation(){this->vtkImageToImageFilter::ExecuteInformation();};
+  void ThreadedExecute(vtkImageData *inData, vtkImageData *outData,
+		       int extent[6], int id);
+  //ETX
+};
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageMask.cpp b/bioimagesuite30_src/Imaging/vtkpxImageMask.cpp
new file mode 100644
index 0000000..efc2c34
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageMask.cpp
@@ -0,0 +1,147 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageMask.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxImageMask.h"
+#include "vtkpxUtil.h"
+#include "vtkFloatArray.h"
+#include "vtkImageGaussianSmooth.h"
+//------------------------------------------------------------------------------
+vtkpxImageMask* vtkpxImageMask::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageMask");
+  if(ret)
+    {
+    return (vtkpxImageMask*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageMask;
+}
+
+// Construct object with no children.
+vtkpxImageMask::vtkpxImageMask()
+{
+  this->Mask=NULL;
+}
+// ----------------------------------------------------------------------------
+vtkpxImageMask::~vtkpxImageMask()
+{
+  this->SetMask(NULL);
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageMask::SimpleExecute(vtkImageData* input ,vtkImageData* output )
+{
+
+  if (input==NULL    || this->Mask==NULL )
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxImageMask");
+      return;
+    }
+
+
+  int dim[3],dim2[3];
+  this->GetImageDataInput(0)->GetDimensions(dim);
+  this->GetMask()->GetDimensions(dim2);
+  
+  int sum=0;
+  for (int ia=0;ia<=2;ia++)
+    sum+=abs(dim[ia]-dim2[ia]);
+  if (sum!=0)
+    {
+      vtkErrorMacro(<<"Bad Input Dimensions");
+      return;
+    }
+    
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* inp=this->GetImageDataInput(0)->GetPointData()->GetScalars();  
+  vtkDataArray* msk=this->GetMask()->GetPointData()->GetScalars();
+
+  int numscalars=out->GetNumberOfTuples();
+  int tenth=numscalars/10;
+  this->UpdateProgress(0.01);
+  float pog=0.0;
+
+  int count=0;
+  int numcomp=inp->GetNumberOfComponents();
+
+  for (int pixel=0;pixel<numscalars;pixel++)
+    {
+      float m=(msk->GetComponent(pixel,0));
+	       
+      if (m>0.0)
+	{
+	  for (int c=0;c< numcomp;c++)
+	    out->SetComponent(pixel,c,inp->GetComponent(pixel,c));
+	}
+      else
+	{
+	  for (int c=0;c< numcomp;c++)
+	    out->SetComponent(pixel,c,0.0);
+	}
+	  
+      count++;
+      if (count==tenth)
+	{
+	  pog+=0.1;
+	  this->UpdateProgress(pog);
+	  count=0;
+	}
+    }
+
+
+  this->UpdateProgress(1.0);
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageMask.h b/bioimagesuite30_src/Imaging/vtkpxImageMask.h
new file mode 100644
index 0000000..aa9948e
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageMask.h
@@ -0,0 +1,90 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageMask.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageMask -- compute the difference and a normalized difference
+// between two images
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageMask_h
+#define __vtkpxImageMask_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkpxImageMask : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageMask *New();
+  vtkTypeMacro(vtkpxImageMask,vtkpxSimpleImageToImageFilter);
+
+  // Input2 -- second input to compare with input
+  vtkSetObjectMacro(Mask,vtkImageData);
+  vtkGetObjectMacro(Mask,vtkImageData);
+
+protected:
+
+  vtkpxImageMask();
+  virtual ~vtkpxImageMask();
+  vtkpxImageMask(const vtkpxImageMask&) {};
+  void operator=(const vtkpxImageMask&) {};
+
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  vtkImageData* Mask;
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageNormalizeIntensity.cpp b/bioimagesuite30_src/Imaging/vtkpxImageNormalizeIntensity.cpp
new file mode 100644
index 0000000..376f6f3
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageNormalizeIntensity.cpp
@@ -0,0 +1,250 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxImageNormalizeIntensity.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxUtil.h"
+#include "vtkImageToImageFilter.h"
+
+//------------------------------------------------------------------------------
+vtkpxImageNormalizeIntensity* vtkpxImageNormalizeIntensity::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageNormalizeIntensity");
+  if(ret)
+    {
+    return (vtkpxImageNormalizeIntensity*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageNormalizeIntensity;
+}
+
+//----------------------------------------------------------------------------
+// Constructor sets default values
+vtkpxImageNormalizeIntensity::vtkpxImageNormalizeIntensity()
+{
+  this->InputLevel1=-1;
+  this->InputLevel2=0;
+  this->InputLevel3=1;
+  this->InputLevel4=-1;
+
+  this->OutputLevel0=-1;
+  this->OutputLevel1=-1;
+  this->OutputLevel2=0;
+  this->OutputLevel3=1;
+  this->OutputLevel4=-1;
+}
+
+//----------------------------------------------------------------------------
+// This templated function executes the filter for any type of data.
+template <class IT, class OT>
+static void vtkpxImageNormalizeIntensityExecute(vtkpxImageNormalizeIntensity *self,
+				      vtkImageData *inData, IT *inPtr,
+				      vtkImageData *outData, OT *outPtr,
+				      int outExt[6], int id)
+{
+
+  float InputLevel1=self->GetInputLevel1();
+  float InputLevel2=self->GetInputLevel2();
+  float InputLevel3=self->GetInputLevel3();
+  float InputLevel4=self->GetInputLevel4();
+  
+  float OutputLevel0=self->GetOutputLevel0();
+  float OutputLevel1=self->GetOutputLevel1();
+  float OutputLevel2=self->GetOutputLevel2();
+  float OutputLevel3=self->GetOutputLevel3();
+  float OutputLevel4=self->GetOutputLevel4();
+
+
+  // for preventing overflow
+  float outTypeMin = outData->GetScalarTypeMin();
+  float outTypeMax = outData->GetScalarTypeMax();
+
+  float inTypeMin = inData->GetScalarTypeMin();
+  float inTypeMax = inData->GetScalarTypeMax();
+
+  // Set Outer Levels if set to default to correspond to typemin,typemax
+  if (InputLevel1==-1)
+    InputLevel1=inTypeMin;
+  if (InputLevel4==-1)
+    InputLevel4=inTypeMax;
+
+  if (OutputLevel0<outTypeMin || OutputLevel0>outTypeMax)
+    OutputLevel0=outTypeMin;
+
+  if (OutputLevel1<OutputLevel0)
+    OutputLevel1=OutputLevel0;
+  else
+    OutputLevel1=Frange(OutputLevel1,outTypeMin,outTypeMax);
+
+  if (OutputLevel4==-1)
+    OutputLevel4=outTypeMax;
+  else
+    OutputLevel4=Frange(OutputLevel4,outTypeMin,outTypeMax);
+  
+  OutputLevel2=Frange(OutputLevel2,outTypeMin,outTypeMax);
+  OutputLevel3=Frange(OutputLevel3,outTypeMin,outTypeMax);
+
+
+  // Eliminate Division by Zero Errors
+  if (InputLevel1<=0)
+    InputLevel1=0;
+
+  if (InputLevel1>=InputLevel2)
+    InputLevel2=InputLevel1+1.0;
+  if (InputLevel2>=InputLevel3)
+    InputLevel3=InputLevel2+1;
+  if (InputLevel3>=InputLevel4)
+    InputLevel4=InputLevel3+1;
+
+  float scale1=(OutputLevel2-OutputLevel1)/(InputLevel2-InputLevel1);
+  float scale2=(OutputLevel3-OutputLevel2)/(InputLevel3-InputLevel2);
+  float scale3=(OutputLevel4-OutputLevel3)/(InputLevel4-InputLevel3);
+
+  /*  fprintf(stderr, "Processing Levels Inputs  (%f,%f,%f,%f)\n Processing Levels Outputs (%f,%f,%f,%f,%f)\n Processing Levels Scales  (%f,%f,%f)\n\n",
+	  InputLevel1,InputLevel2,InputLevel3,InputLevel4,
+	  OutputLevel0,OutputLevel1,OutputLevel2,OutputLevel3,OutputLevel4,
+	  scale1,scale2,scale3);*/
+
+  int idxR, idxY, idxZ;
+  int maxY, maxZ;
+  vtkIdType inIncX, inIncY, inIncZ;
+  vtkIdType outIncX, outIncY, outIncZ;
+  int rowLength;
+  unsigned long count = 0;
+  unsigned long target;
+
+
+  // find the region to loop over
+  rowLength = (outExt[1] - outExt[0]+1)*inData->GetNumberOfScalarComponents();
+  maxY = outExt[3] - outExt[2]; 
+  maxZ = outExt[5] - outExt[4];
+  target = (unsigned long)((maxZ+1)*(maxY+1)/50.0);
+  target++;
+  
+  // Get increments to march through data 
+  inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
+  outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
+
+  // Loop through ouput pixels
+  for (idxZ = 0; idxZ <= maxZ; idxZ++)
+    {
+    for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++)
+      {
+	if (!id) 
+	  {
+	    if (!(count%target))
+	      {
+		self->UpdateProgress(count/(50.0*target));
+	      }
+	    count++;
+	  }
+	
+	for (idxR = 0; idxR < rowLength; idxR++)
+	  {
+	  // Pixel operation
+	    float val = ((float)(*inPtr)); 
+	    
+	    if (val<InputLevel1)
+	      {
+		val=OutputLevel0;
+	      }
+	    else if (val<InputLevel2)
+	      {
+		val=(val-InputLevel1)*scale1+OutputLevel1;
+	      }
+	    else if (val<InputLevel3)
+	      {
+		val=(val-InputLevel2)*scale2+OutputLevel2;
+	      }
+	    else if (val<InputLevel4)
+	      {
+		val=(val-InputLevel3)*scale3+OutputLevel3;
+	      }
+	    else
+	      {
+		val=OutputLevel4;
+	      }
+	    
+	    *outPtr = (OT)(val);
+	    outPtr++;
+	    inPtr++;
+	  }
+	
+	outPtr += outIncY;
+	inPtr += inIncY;
+      }
+    outPtr += outIncZ;
+    inPtr += inIncZ;
+    }
+}
+
+
+//----------------------------------------------------------------------------
+// This method is passed a input and output data, and executes the filter
+// algorithm to fill the output from the input.
+// It just executes a switch statement to call the correct function for
+// the datas data types.
+void vtkpxImageNormalizeIntensity::ThreadedExecute(vtkImageData *inData, 
+						   vtkImageData *outData,
+						   int outExt[6], int id)
+{
+  void *inPtr = inData->GetScalarPointerForExtent(outExt);
+  void *outPtr = outData->GetScalarPointerForExtent(outExt);
+  
+  switch (inData->GetScalarType())
+    { 
+      vtkTemplateMacro7(vtkpxImageNormalizeIntensityExecute,this, 
+			inData, (VTK_TT *)(inPtr), 
+			outData,(VTK_TT *)(outPtr), 
+			outExt, id);
+
+    default:
+      vtkErrorMacro(<< "Execute: Unknown ScalarType");
+      return;
+    }
+}
+
+
+
+void vtkpxImageNormalizeIntensity::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkImageToImageFilter::PrintSelf(os,indent);
+
+  os << indent << "InputLevels: "<<this->InputLevel1<<this->InputLevel2<<this->InputLevel3<<this->InputLevel4<<"\n";
+  os << indent << "OutputLevels: "<<this->OutputLevel1<<this->OutputLevel2<<this->OutputLevel3<<this->OutputLevel4<<"\n";
+}
+
+void vtkpxImageNormalizeIntensity::SetInputToNull(vtkImageToImageFilter* source)
+{
+  source->SetInput(NULL);
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageNormalizeIntensity.h b/bioimagesuite30_src/Imaging/vtkpxImageNormalizeIntensity.h
new file mode 100644
index 0000000..c133e03
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageNormalizeIntensity.h
@@ -0,0 +1,164 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageNormalizeIntensity.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageNormalizeIntensity - piecewise linear intensity map
+// .SECTION Description
+// With vtkpxImageNormalizeIntensity Pixels Intensities are mapped using
+// a piecewise linear function defined by the 4-nodes
+// (InputLeveln,OutputLeveln) where n=1-4
+// A value less than InputLeveln goes to OutputLevel0 and a value>InputLevel4 goes to OutputLevel4
+// As a convenience, this class allows you to set the output scalar type
+// similar to vtkImageCast.
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+
+#ifndef __vtkpxImageNormalizeIntensity_h
+#define __vtkpxImageNormalizeIntensity_h
+
+
+class vtkImageToImageFilter;
+
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkImageToImageFilter.h"
+
+class vtkpxImageNormalizeIntensity : public vtkImageToImageFilter
+{
+public:
+  static vtkpxImageNormalizeIntensity *New();
+  vtkTypeMacro(vtkpxImageNormalizeIntensity,vtkImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  
+  // Description:
+  // Set/Get the InputLevel1
+  vtkSetMacro(InputLevel1,float);
+  vtkGetMacro(InputLevel1,float);
+
+  // Description:
+  // Set/Get the InputLevel2
+  vtkSetMacro(InputLevel2,float);
+  vtkGetMacro(InputLevel2,float);
+
+  // Description:
+  // Set/Get the InputLevel3
+  vtkSetMacro(InputLevel3,float);
+  vtkGetMacro(InputLevel3,float);
+
+  // Description:
+  // Set/Get the InputLevel4
+  vtkSetMacro(InputLevel4,float);
+  vtkGetMacro(InputLevel4,float);
+
+  // Description:
+  // Set/Get the OutputLevel0
+  vtkSetMacro(OutputLevel0,float);
+  vtkGetMacro(OutputLevel0,float);
+
+  // Description:
+  // Set/Get the OutputLevel1
+  vtkSetMacro(OutputLevel1,float);
+  vtkGetMacro(OutputLevel1,float);
+
+  // Description:
+  // Set/Get the OutputLevel2
+  vtkSetMacro(OutputLevel2,float);
+  vtkGetMacro(OutputLevel2,float);
+
+  // Description:
+  // Set/Get the OutputLevel3
+  vtkSetMacro(OutputLevel3,float);
+  vtkGetMacro(OutputLevel3,float);
+
+  // Description:
+  // Set/Get the OutputLevel4
+  vtkSetMacro(OutputLevel4,float);
+  vtkGetMacro(OutputLevel4,float);
+
+
+  // Description:
+  // Helper Routine for Tcl Scripts 
+  static void SetInputToNull(vtkImageToImageFilter* source);
+  
+  
+protected:
+  //BTX
+  vtkpxImageNormalizeIntensity();
+  ~vtkpxImageNormalizeIntensity() {};
+  vtkpxImageNormalizeIntensity(const vtkpxImageNormalizeIntensity&) {};
+  void operator=(const vtkpxImageNormalizeIntensity&) {};
+
+
+
+  float InputLevel1;
+  float InputLevel2;
+  float InputLevel3;
+  float InputLevel4;
+
+  float OutputLevel0;
+  float OutputLevel1;
+  float OutputLevel2;
+  float OutputLevel3;
+  float OutputLevel4;
+
+  void ThreadedExecute(vtkImageData *inData, vtkImageData *outData,
+		       int extent[6], int id);
+  //ETX
+};
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageNormalizeIntensityToReference.cpp b/bioimagesuite30_src/Imaging/vtkpxImageNormalizeIntensityToReference.cpp
new file mode 100644
index 0000000..b268f75
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageNormalizeIntensityToReference.cpp
@@ -0,0 +1,197 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageNormalizeIntensityToReference.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxImageNormalizeIntensityToReference.h"
+#include "vtkpxUtil.h"
+#include "vtkFloatArray.h"
+#include "vtkpxUtil.h"
+#include "vtkpxMatrix.h"
+//------------------------------------------------------------------------------
+vtkpxImageNormalizeIntensityToReference* vtkpxImageNormalizeIntensityToReference::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageNormalizeIntensityToReference");
+  if(ret)
+    {
+    return (vtkpxImageNormalizeIntensityToReference*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageNormalizeIntensityToReference;
+}
+
+// Construct object with no children.
+vtkpxImageNormalizeIntensityToReference::vtkpxImageNormalizeIntensityToReference()
+{
+  this->Threshold=0.02;
+  this->Reference=NULL;
+  this->Order=1;
+}
+// ----------------------------------------------------------------------------
+vtkpxImageNormalizeIntensityToReference::~vtkpxImageNormalizeIntensityToReference()
+{
+  this->SetReference(NULL);
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageNormalizeIntensityToReference::SimpleExecute(vtkImageData* ,vtkImageData* )
+{
+
+  if (this->GetImageDataInput(0)==NULL    || this->Reference==NULL )
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxImageNormalizeIntensityToReference");
+      return;
+    }
+
+
+  int dim[3],dim2[3];
+  this->GetImageDataInput(0)->GetDimensions(dim);
+  this->GetReference()->GetDimensions(dim2);
+  
+  int ssum=0;
+  for (int ia=0;ia<=2;ia++)
+    ssum+=abs(dim[ia]-dim2[ia]);
+
+  ssum+=abs(this->GetImageDataInput(0)->GetNumberOfScalarComponents()-this->GetReference()->GetNumberOfScalarComponents());
+  if (ssum!=0)
+    {
+      vtkErrorMacro(<<"Bad Input Dimensions");
+      return;
+    }
+    
+  vtkImageData* output=this->GetOutput();
+  output->SetSpacing(this->GetImageDataInput(0)->GetSpacing());
+  output->SetOrigin(this->GetImageDataInput(0)->GetOrigin());
+  output->SetScalarType(VTK_FLOAT);
+  output->SetNumberOfScalarComponents(this->GetImageDataInput(0)->GetNumberOfScalarComponents());
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  output->AllocateScalars();
+
+
+  float minr,maxr;
+  vtkpxUtil::ImageRobustRange(this->GetImageDataInput(0),this->Threshold,1-this->Threshold,minr,maxr);
+  fprintf(stderr,"Using range %.2f:%.2f (Thr=%f)\n",minr,maxr,this->Threshold);
+  
+  vtkDataArray* in1=this->GetImageDataInput(0)->GetPointData()->GetScalars();  
+  vtkDataArray* in2=this->GetReference()->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  int nt=in1->GetNumberOfTuples();
+  
+  float sx[5],sy[3];
+  for (int iq=0;iq<5;iq++)
+  {
+	sx[iq]=0;
+	if (iq<3)
+		sy[iq]=0;
+  }
+
+  { for (int i=0;i<nt;i++)
+    {
+      float x=in1->GetComponent(i,0);
+      if (x>minr && x<maxr && x!=-1)
+	{
+	  float y=in2->GetComponent(i,0);
+	  float x2=x*x;
+	  sx[0]+=1;
+	  sx[1]+=x;
+	  sx[2]+=x2;
+	  sx[3]+=x2*x;
+	  sx[4]+=x2*x2;
+	  sy[0]+=y;
+	  sy[1]+=x*y;
+	  sy[2]+=x2*y;
+	}
+    }
+  }
+
+  vtkpxMatrix* A=vtkpxMatrix::New();
+  vtkpxMatrix* B=vtkpxMatrix::New();
+  vtkpxMatrix* X=vtkpxMatrix::New();
+
+  A->Zeros(this->Order+1,this->Order+1);
+  B->Zeros(this->Order+1,1);
+  X->Zeros(this->Order+1,1);
+
+  for (int i=0;i<this->Order+1;i++)
+    {
+      B->SetElement(i,0,sy[i]);
+      for (int j=0;j<this->Order+1;j++)
+	A->SetElement(i,j,sx[i+j]);
+    }
+  
+  A->Print("A=");
+  B->Print("B=");
+  A->Invert();
+  vtkpxMatrix::Multiply(A,B,X);
+
+  X->Print("X");
+
+  float f[3];
+  f[2]=0.0;
+  {  for (int i=0;i<this->Order+1;i++)
+	  f[i]=X->GetElement(i,0);}
+
+  
+  {for (int i=0;i<nt;i++)
+    for (int c=0;c<output->GetNumberOfScalarComponents();c++)
+      {
+	float x=in1->GetComponent(i,c);
+	float y=f[0]+f[1]*x+f[2]*x*x;
+	out->SetComponent(i,c,y);
+  }}
+  this->UpdateProgress(1.0);
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageNormalizeIntensityToReference.h b/bioimagesuite30_src/Imaging/vtkpxImageNormalizeIntensityToReference.h
new file mode 100644
index 0000000..15e7f45
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageNormalizeIntensityToReference.h
@@ -0,0 +1,104 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageNormalizeIntensityToReference.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageNormalizeIntensityToReference -- compute the ratio and a normalized ratio between two images
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageNormalizeIntensityToReference_h
+#define __vtkpxImageNormalizeIntensityToReference_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkpxImageNormalizeIntensityToReference : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageNormalizeIntensityToReference *New();
+  vtkTypeMacro(vtkpxImageNormalizeIntensityToReference,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  //Set the level between 0 and 1 below which the data (in the ref image) is
+  // not used to compute the scale and shift parameters
+  vtkGetMacro(Threshold,float);
+  vtkSetClampMacro(Threshold,float,0,1);
+
+  // Description:
+  // Smooth Difference before computing percentages
+  vtkGetMacro(Order,int);
+  vtkSetClampMacro(Order,int,1,2);
+
+  // Description:
+  // Input2 -- second input to compare with input
+  vtkSetObjectMacro(Reference,vtkImageData);
+  vtkGetObjectMacro(Reference,vtkImageData);
+
+protected:
+
+  vtkpxImageNormalizeIntensityToReference();
+  virtual ~vtkpxImageNormalizeIntensityToReference();
+  vtkpxImageNormalizeIntensityToReference(const vtkpxImageNormalizeIntensityToReference&) {};
+  void operator=(const vtkpxImageNormalizeIntensityToReference&) {};
+
+  virtual void SimpleExecute(vtkImageData* in,vtkImageData* out);
+
+  float        Threshold;
+  int          Order;
+  vtkImageData* Reference;
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImagePolarToEuclidean.cpp b/bioimagesuite30_src/Imaging/vtkpxImagePolarToEuclidean.cpp
new file mode 100644
index 0000000..6f5dd58
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImagePolarToEuclidean.cpp
@@ -0,0 +1,209 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImagePolarToEuclidean.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include <math.h>
+#include "vtkpxImagePolarToEuclidean.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxMath.h"
+
+
+//------------------------------------------------------------------------------
+vtkpxImagePolarToEuclidean* vtkpxImagePolarToEuclidean::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImagePolarToEuclidean");
+  if(ret)
+    {
+    return (vtkpxImagePolarToEuclidean*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImagePolarToEuclidean;
+}
+
+
+
+
+
+
+//----------------------------------------------------------------------------
+vtkpxImagePolarToEuclidean::vtkpxImagePolarToEuclidean()
+{
+  this->Inverse=0;
+}
+
+//----------------------------------------------------------------------------
+// This templated function executes the filter for any type of data.
+template <class T>
+static void vtkpxImagePolarToEuclideanExecute(vtkpxImagePolarToEuclidean *self,
+					      vtkImageData *inData, T *inPtr,
+					      vtkImageData *outData, T *outPtr,
+					      int outExt[6], int id)
+{
+  int idxX, idxY, idxZ;
+  int maxC, maxX, maxY, maxZ;
+  vtkIdType inIncX, inIncY, inIncZ;
+  vtkIdType outIncX, outIncY, outIncZ;
+  unsigned long count = 0;
+  unsigned long target;
+  float X, Y, Theta, R;
+  int   inverse=self->GetInverse();
+
+  // find the region to loop over
+  maxC = inData->GetNumberOfScalarComponents();
+  maxX = outExt[1] - outExt[0]; 
+  maxY = outExt[3] - outExt[2]; 
+  maxZ = outExt[5] - outExt[4];
+  target = (unsigned long)((maxZ+1)*(maxY+1)/50.0);
+  target++;
+
+  // Get increments to march through data 
+  inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
+  outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
+
+  // Loop through ouput pixels
+  for (idxZ = 0; idxZ <= maxZ; idxZ++)
+    {
+      for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++)
+	{
+	  if (!id) 
+	    {
+	      if (!(count%target))
+		{
+		  self->UpdateProgress(count/(50.0*target));
+		}
+	      count++;
+	    }
+
+	  /*if ( !( (idxY + outExt[2]) & 1 ))
+	    fprintf(stderr,"Even Number %d\n",idxY);*/
+
+	  for (idxX = 0; idxX <= maxX; idxX++)
+	    {
+	      if (inverse==0)
+		{
+		  // Pixel operation
+		  Theta = (float)(*inPtr);
+		  R = (float)(inPtr[1]);
+		  
+		  X=R*sin(Theta);
+		  Y=R*cos(Theta);
+		  
+		  *outPtr = (T)(X);
+		  outPtr[1] = (T)(Y);
+		}
+	      else
+		{
+		  X=(float)(*inPtr);
+		  Y=(float)(inPtr[1]);
+		  vtkpxMath::EuclideanToPolar(X,Y,R,Theta);
+		  *outPtr= (T)(Theta);
+		  outPtr[1]=(T)(R);
+		}
+	      inPtr += maxC;
+	      outPtr += maxC;
+	    }
+	  outPtr += outIncY;
+	  inPtr += inIncY;
+	}
+      outPtr += outIncZ;
+      inPtr += inIncZ;
+    }
+}
+
+//----------------------------------------------------------------------------
+void vtkpxImagePolarToEuclidean::ThreadedExecute(vtkImageData *inData, 
+						 vtkImageData *outData,
+						 int outExt[6], int id)
+{
+  void *inPtr = inData->GetScalarPointerForExtent(outExt);
+  void *outPtr = outData->GetScalarPointerForExtent(outExt);
+  
+  vtkDebugMacro(<< "Execute: inData = " << inData 
+		<< ", outData = " << outData);
+  
+  // this filter expects that input is the same type as output.
+  if (inData->GetScalarType() != outData->GetScalarType())
+    {
+      vtkErrorMacro(<< "Execute: input ScalarType, " << inData->GetScalarType()
+      << ", must match out ScalarType " << outData->GetScalarType());
+      return;
+    }
+  
+  // input must have at least two components
+  if (inData->GetNumberOfScalarComponents() < 2)
+    {
+      vtkErrorMacro(<< "Execute: input does not have at least two components");
+      return;
+    }
+  
+  switch (inData->GetScalarType())
+    {
+      vtkTemplateMacro7(vtkpxImagePolarToEuclideanExecute, this, 
+			inData, (VTK_TT *)(inPtr), 
+			outData, (VTK_TT *)(outPtr), outExt, id);
+    default:
+      vtkErrorMacro(<< "Execute: Unknown ScalarType");
+      return;
+    }
+}
+
+void vtkpxImagePolarToEuclidean::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkImageToImageFilter::PrintSelf(os,indent);
+  os << indent << "Value of Pi: " << this->ValueOfPi << "\n";
+  os << indent << "Inverse    : " << this->Inverse   << "\n";
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImagePolarToEuclidean.h b/bioimagesuite30_src/Imaging/vtkpxImagePolarToEuclidean.h
new file mode 100644
index 0000000..b98e693
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImagePolarToEuclidean.h
@@ -0,0 +1,102 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImagePolarToEuclidean.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImagePolarToEuclidean - Converts 2D polar coordinates to euclidean.
+// .SECTION Description
+// For each pixel with vector components theta,r, this filter outputs 
+// real in component0, and imaginary in component1.
+
+#ifndef __vtkpxImagePolarToEuclidean_h
+#define __vtkpxImagePolarToEuclidean_h
+
+
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkImageToImageFilter.h"
+
+class vtkpxImagePolarToEuclidean : public vtkImageToImageFilter
+{
+public:
+  static vtkpxImagePolarToEuclidean *New();
+  vtkTypeMacro(vtkpxImagePolarToEuclidean,vtkImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // if Inverse = 1 then we go from Euclidean To Polar
+    // Description:
+  // Flag to Determine whether to fit a line or to compute median difference 
+  vtkSetClampMacro(Inverse, int,0,1);
+  vtkGetMacro(Inverse, int);
+  vtkBooleanMacro(Inverse, int);
+  
+  
+protected:
+  vtkpxImagePolarToEuclidean();
+  ~vtkpxImagePolarToEuclidean() {};
+  vtkpxImagePolarToEuclidean(const vtkpxImagePolarToEuclidean&) {};
+  void operator=(const vtkpxImagePolarToEuclidean&) {};
+
+  float ValueOfPi;
+  float MagnitudeScale;
+  int   Inverse;
+  
+  void ThreadedExecute(vtkImageData *inData, vtkImageData *outData,int ext[6], int id);
+};
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageRemoveLinearPhase.cpp b/bioimagesuite30_src/Imaging/vtkpxImageRemoveLinearPhase.cpp
new file mode 100644
index 0000000..5046d30
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageRemoveLinearPhase.cpp
@@ -0,0 +1,279 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageRemoveLinearPhase.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkImageFFT.h"
+#include "vtkImageRFFT.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxMath.h"
+#include "vtkpxImagePolarToEuclidean.h"
+#include "vtkpxImageRemoveLinearPhase.h"
+#include "vtkpxUtil.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkImageShiftScale.h"
+#include "vtkImageAppendComponents.h"
+//------------------------------------------------------------------------------
+vtkpxImageRemoveLinearPhase* vtkpxImageRemoveLinearPhase::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageRemoveLinearPhase");
+  if(ret)
+    {
+      return (vtkpxImageRemoveLinearPhase*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageRemoveLinearPhase;
+}
+//----------------------------------------------------------------------------
+vtkpxImageRemoveLinearPhase::vtkpxImageRemoveLinearPhase()
+{
+  this->InputIsPolarComplex=1;
+  this->PhaseAxis=1;
+}
+
+//----------------------------------------------------------------------------
+void vtkpxImageRemoveLinearPhase::SimpleExecute(vtkImageData* input,vtkImageData *output) 
+{
+  if (input->GetNumberOfScalarComponents()!=2)
+    {
+      vtkErrorMacro(<<"Input Must Be Complex!\n");
+      return;
+    }
+
+
+  if (this->InputIsPolarComplex)
+    {
+      vtkImageData* temp=vtkImageData::New();
+      vtkImageData* temp2=vtkImageData::New();
+
+      vtkpxImagePolarToEuclidean* pol=vtkpxImagePolarToEuclidean::New();
+      pol->SetInput(input);
+  
+      vtkImageFFT* fft=vtkImageFFT::New();
+      fft->SetInput(pol->GetOutput());
+      pol->Delete();
+      fft->Update();
+
+      temp->ShallowCopy(fft->GetOutput());
+      fft->Delete();
+
+
+      vtkpxImageRemoveLinearPhase::RemoveLinearPhase(temp2,temp,this->PhaseAxis);
+
+      vtkImageRFFT* rfft=vtkImageRFFT::New();
+      rfft->SetInput(temp2);
+      
+      vtkpxImagePolarToEuclidean* euc2=vtkpxImagePolarToEuclidean::New();
+      euc2->InverseOn();
+      euc2->SetInput(rfft->GetOutput());
+      rfft->Delete();
+      euc2->Update();
+      
+      output->ShallowCopy(euc2->GetOutput());
+      euc2->Delete();
+
+      
+      temp->Delete();
+      temp2->Delete();
+    }
+  else
+    {
+      fprintf(stderr,"Straight Fourier Image Processing\n");
+      vtkpxImageRemoveLinearPhase::RemoveLinearPhase(output,input,this->PhaseAxis);
+    }
+
+
+}
+
+//----------------------------------------------------------------------------
+int vtkpxImageRemoveLinearPhase::RemoveLinearPhase(vtkImageData* output,vtkImageData* input,int axis)
+
+{
+#ifndef M_PI
+#define M_PI 3.1415926854
+#endif
+
+  vtkpxImagePolarToEuclidean* pol=vtkpxImagePolarToEuclidean::New();
+  pol->InverseOn();
+  pol->SetInput(input);
+  pol->Update();
+
+  vtkImageData* tmpoutput=vtkImageData::New();
+  tmpoutput->ShallowCopy(pol->GetOutput());
+  pol->Delete();
+
+  int dim[3];
+  vtkDataArray* scal=tmpoutput->GetPointData()->GetScalars();
+  tmpoutput->GetDimensions(dim);
+
+  double r[2];
+  scal->GetRange(r);
+  fprintf(stderr,"Input scalar range = %f:%f\n",r[0],r[1]);
+  
+  int slicesize=dim[0]*dim[1];
+  float Theta,R,sum=0.0;
+  float a,b,abdev;	      
+
+  fprintf(stderr,"Dim=%d,%d,%d  Axis=%d\n",dim[0],dim[1],dim[2],axis);
+
+  if (axis==1)
+    {
+      float* ph=new float[dim[1]];
+      float* pj=new float[dim[1]];
+      for (int k=0;k<dim[2];k++)
+	{
+	  int j;
+	  for (j=0;j<dim[1];j++)
+	    {
+	      ph[j]=0.0;
+	      pj[j]=float(j);
+	      sum=0.0;
+	      for (int i=0;i<dim[0];i++)
+		{
+		  Theta=tmpoutput->GetScalarComponentAsDouble(i,j,k,0);
+		  R=tmpoutput->GetScalarComponentAsDouble(i,j,k,1);
+		  ph[j]+=Theta;
+		  sum+=1.0;
+		  if (i==dim[0]/2 && j==dim[1]/2 && k==dim[2]/2)
+		    fprintf(stderr," ijk=%d,%d,%d th=%f\n",i,j,k,Theta);
+		}
+	      ph[j]/=sum;
+	    }
+	  
+	  vtkpxMath::Meanfit(pj,ph,dim[1],a,b,abdev);
+	  fprintf(stderr,"Slice = %d a=%.2f b=%.2f abdev=%.2f\n",k,a,b,abdev);
+	  
+	  int index=k*slicesize;
+	  for (j=0;j<dim[1];j++)
+	    {
+	      float shift=a+b*float(j);
+	      for (int i=0;i<dim[0];i++)
+		{
+		  Theta=tmpoutput->GetScalarComponentAsDouble(i,j,k,0);
+		  R=tmpoutput->GetScalarComponentAsDouble(i,j,k,1);
+		  Theta-=shift;
+		  scal->SetComponent(index,0,Theta);
+		  scal->SetComponent(index,1,R);
+		  if (i==dim[0]/2 && j==dim[1]/2 && k==dim[2]/2)
+		    fprintf(stderr," ijk=%d,%d,%d (%d) v=%f --> %f\n",i,j,k,index,Theta+shift,Theta);
+		  ++index;
+		}
+	    }
+	}
+      delete [] ph;
+      delete [] pj;
+    }
+  else
+    {
+      int sz=dim[0];
+      float* ph=new float[sz];
+      float* pi=new float[sz];
+      for (int k=0;k<dim[2];k++)
+	{
+	  ph[0]=tmpoutput->GetScalarComponentAsDouble(0,0,k,0);
+	  pi[0]=0.0;
+	  int i;
+	  for (i=1;i<sz;i++)
+	    {
+	      pi[i]=float(i);
+	      float t=tmpoutput->GetScalarComponentAsDouble(i,0,k,0);
+	      ph[i]=vtkpxMath::FindMinAngleDistance(t,ph[i-1])+ph[i-1];
+	    }
+	  
+	  vtkpxMath::Medfit(pi,ph,sz,a,b,abdev);
+	  fprintf(stderr,"Slice = %d a=%.2f b=%.2f abdev=%.2f\n",k,a,b,abdev);
+
+	  int base=k*slicesize;
+	  for (i=0;i<dim[0];i++)
+	    {
+	      float shift=-b*float(i);
+	      for (int j=0;j<dim[1];j++)
+		{
+		  int index=base+j*dim[0]+i;
+		  float t1=tmpoutput->GetScalarComponentAsDouble(i,j,k,0);
+		  float t2=t1-shift;
+		  while (t2<M_PI)
+		    t2+=2.0*M_PI;
+		  while (t2>M_PI)
+		    t2-=2.0*M_PI;
+
+		  if (j==dim[1]/2 && k==dim[2]/2)
+		    {
+		      fprintf(stderr,"i=%d j=%d k=%d shift=%f t1=%.1f -> t2=%.1f\n",
+			      i,j,k,shift,t1,t2);
+		    }
+
+		  scal->SetComponent(index,0,t2);
+		}
+	    }
+	}
+      delete [] ph;
+      delete [] pi;
+    }
+
+
+
+  vtkpxImagePolarToEuclidean* pol2=vtkpxImagePolarToEuclidean::New();
+  pol2->SetInput(tmpoutput);
+  pol2->Update();
+
+  output->DeepCopy(pol2->GetOutput());
+  pol2->Delete();
+
+  return 1;
+
+
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageRemoveLinearPhase.h b/bioimagesuite30_src/Imaging/vtkpxImageRemoveLinearPhase.h
new file mode 100644
index 0000000..237c019
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageRemoveLinearPhase.h
@@ -0,0 +1,110 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxProcessRawBrukerFIDImage.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageRemoveLinearPhase - Elminates Linear Phase in Fourier Space 
+// .SECTION Description
+
+
+#ifndef __vtkpxImageRemoveLinearPhase_h
+#define __vtkpxImageRemoveLinearPhase_h
+
+
+#include "vtkpxSimpleImageToImageFilter.h"
+
+class vtkpxImageRemoveLinearPhase : public vtkpxSimpleImageToImageFilter
+{
+public:
+
+  static vtkpxImageRemoveLinearPhase *New();
+  vtkTypeMacro(vtkpxImageRemoveLinearPhase,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Flag to Determine whether input is fourier space (normal) or
+  // Polar Complex Intensity (comp0 =phase comp1=magnitude)
+  vtkSetClampMacro(InputIsPolarComplex, int,0,1);
+  vtkGetMacro(InputIsPolarComplex, int);
+  vtkBooleanMacro(InputIsPolarComplex, int);
+
+  // Description:
+  // Flag to Determine direction of phase-axis
+  // default = 1
+  vtkSetClampMacro(PhaseAxis, int,0,1);
+  vtkGetMacro(PhaseAxis, int);
+
+protected:
+  vtkpxImageRemoveLinearPhase();
+  ~vtkpxImageRemoveLinearPhase() {};
+  vtkpxImageRemoveLinearPhase(const vtkpxImageRemoveLinearPhase&) {};
+  void operator=(const vtkpxImageRemoveLinearPhase&) {};
+
+  int InputIsPolarComplex;
+  int PhaseAxis;
+
+  // Description:
+  // Main Execute Function
+  void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+  // Description:
+  // Static Routine to operate on Fourier Transform Image  
+  // Assumes polar Fourier Decomposition, 
+  static int RemoveLinearPhase(vtkImageData* output,vtkImageData* input,int axis);
+
+};
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageReorientTensorOrVector.cpp b/bioimagesuite30_src/Imaging/vtkpxImageReorientTensorOrVector.cpp
new file mode 100644
index 0000000..8b23cb6
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageReorientTensorOrVector.cpp
@@ -0,0 +1,500 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageReorinetTensorOrVector.cpp,v $
+  Language:  C++  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxImageReorientTensorOrVector.h"
+#include "vtkMatrix4x4.h"
+#include "vtkPoints.h"
+#include "vtkPointData.h"
+#include "vtkLandmarkTransform.h"
+#include "vtkTransformToGrid.h"
+#include "stdio.h"
+//------------------------------------------------------------------------------
+vtkpxImageReorientTensorOrVector* vtkpxImageReorientTensorOrVector::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageReorientTensorOrVector");
+  if(ret)
+    {
+    return (vtkpxImageReorientTensorOrVector*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageReorientTensorOrVector;
+}
+
+// Construct object with no children.
+vtkpxImageReorientTensorOrVector::vtkpxImageReorientTensorOrVector()
+{
+  this->Transformation=NULL;
+  this->DisplacementField=NULL;
+  this->GlobalMatrix=NULL;
+  this->Use7Points=0;
+
+  // A bunch of temp structures so we don't allocate and free memory all the time!
+  this->TempMatrix1=vtkMatrix4x4::New();
+  this->TempMatrix2=vtkMatrix4x4::New();
+  this->TempMatrix3=vtkMatrix4x4::New();
+  this->TempPoints1=vtkPoints::New();
+  this->TempPoints2=vtkPoints::New();
+  this->TempLandmarkTransform=vtkLandmarkTransform::New();
+
+  this->FlipX=0;  this->FlipY=0;  this->FlipZ=0;
+  this->Flips[0]=1.0;  this->Flips[1]=1.0;  this->Flips[2]=1.0;
+}
+// ----------------------------------------------------------------------------
+vtkpxImageReorientTensorOrVector::~vtkpxImageReorientTensorOrVector()
+{
+  this->SetTransformation(NULL);
+  this->SetDisplacementField(NULL);
+
+  // Clean up Global Matrix if it exists
+  if (this->GlobalMatrix!=NULL)
+    this->GlobalMatrix->Delete();
+
+  // Clean up Temp Structures
+  this->TempMatrix1->Delete();
+  this->TempMatrix2->Delete();
+  this->TempMatrix3->Delete();
+  this->TempPoints1->Delete();
+  this->TempPoints2->Delete();
+  this->TempLandmarkTransform->Delete();
+}
+// ----------------------------------------------------------------------------
+void r_print_mat44(vtkMatrix4x4* mat,const char* s)
+{
+  fprintf(stdout,"\n\n %s = \n",s);
+  for (int ia=0;ia<3;ia++)
+    {
+      fprintf(stdout,"\t [ ");
+      for (int ib=0;ib<3;ib++)
+	fprintf(stdout," %+5.3f  ", mat->GetElement(ia,ib));
+      fprintf(stdout,"]\n");
+    }
+}
+
+
+// ----------------------------------------------------------------------------
+void vtkpxImageReorientTensorOrVector::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  // Check Input Image
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"No Input to vtkpxImageReorientTensorOrVector");
+      return;
+    }
+
+  int nc=input->GetNumberOfScalarComponents();
+  if (nc!=3 && nc!=6)
+    {
+      vtkErrorMacro(<<"Bad Input to vtkpxImageReorientTensorOrVector, not a tensor or vector image\n");
+      return;
+    }
+      
+
+  // Either Transformation or Displacement Field must be set!
+  if (this->Transformation==NULL && this->DisplacementField==NULL)
+    {
+      vtkErrorMacro(<<"Specify either a DisplacementField or a Transformation as inputs vtkpxImageReorientTensorOrVector");
+      return;
+    }
+
+  // If Transformation == NULL  then Displacement Field is used,
+  // It must have 3 components and the same number of voxels as the input image
+  if (this->Transformation==NULL)
+    {
+      int dim[3],dim2[3];
+      input->GetDimensions(dim);
+      this->DisplacementField->GetDimensions(dim2);
+      int nc=this->DisplacementField->GetNumberOfScalarComponents();
+  
+      int sum=0;
+      for (int ia=0;ia<=2;ia++)
+	sum+=abs(dim[ia]-dim2[ia]);
+      if (sum!=0 || nc!=3)
+	{
+	  vtkErrorMacro(<<"Bad Displacement Field Dimensions");
+	  return;
+	}
+    }
+    
+  
+  if (this->Debug)
+    fprintf(stderr,"\n\n This Far All OK\n");
+
+  if (this->FlipX)
+    this->Flips[0]=-1.0;
+  else
+    this->Flips[0]=1.0;
+
+  if (this->FlipY)
+    this->Flips[1]=-1.0;
+  else
+    this->Flips[1]=1.0;
+
+  if (this->FlipZ)
+    this->Flips[2]=-1.0;
+  else
+    this->Flips[2]=1.0;
+  
+  if (this->Debug)
+    fprintf(stderr,"Flip factors : X = %.0f, Y=%.0f, Z=%.0f\n",this->Flips[0],this->Flips[1],this->Flips[2]);
+
+  vtkMatrix4x4* local=vtkMatrix4x4::New();
+  
+  // Process the transformation if it is not null
+  // If linear then this->GlobalMatrix is created else it is set to NULL
+  //    and we compute this->DisplacementField
+  if (this->Transformation!=NULL)
+    this->ProcessInputTransformation(input);
+
+
+  if (this->GlobalMatrix==NULL)
+    {
+      // Set the defaults for fitting in the case of a 
+      // displacement field
+      if (this->Use7Points)
+	{
+	  this->TempPoints1->SetNumberOfPoints(7);
+	  this->TempPoints2->SetNumberOfPoints(7);
+	}
+      else
+	{
+	  this->TempPoints1->SetNumberOfPoints(27);
+	  this->TempPoints2->SetNumberOfPoints(27);
+	}
+      this->TempLandmarkTransform->SetSourceLandmarks(this->TempPoints1);
+      this->TempLandmarkTransform->SetTargetLandmarks(this->TempPoints2);
+      this->TempLandmarkTransform->SetModeToRigidBody();
+    }
+  else
+    {
+      // Store local which is the matrix to be computed at each voxel
+      // in the case of a displacement field once and for all
+      // if the transformation is linear
+      local->DeepCopy(this->GlobalMatrix);
+    }
+      
+  int dim[3]; input->GetDimensions(dim);
+  int istensor=0; 
+  if (input->GetNumberOfScalarComponents()==6)
+    istensor=1;
+
+  this->UpdateProgress(0.01);
+
+  // Zero out output image
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  for (int ia=0;ia<out->GetNumberOfComponents();ia++)
+    out->FillComponent(ia,0.0);
+
+  double origin[3]; input->GetOrigin(origin);
+  double spacing[3]; input->GetSpacing(spacing);
+
+  // For each voxel
+  for (int k=1;k<dim[2]-1;k++)
+    {
+      for (int j=1;j<dim[1]-1;j++)
+	for (int i=1;i<dim[0]-1;i++)
+	  {
+	    if (this->GlobalMatrix==NULL)
+	      this->ComputeLocalRotation(this->DisplacementField,i,j,k,origin,spacing,local);
+	    
+	    if (istensor)
+	      this->WarpTensor(input,output,i,j,k,local);
+	    else
+	      this->WarpVector(input,output,i,j,k,local);
+	  }
+      this->UpdateProgress(double(k+1)/double(dim[2]));
+    }
+	      
+  local->Delete();
+}
+
+// --------------------------------------------------------------------------------------------
+void vtkpxImageReorientTensorOrVector::WarpTensor(vtkImageData* input,vtkImageData* output,int i,int j,int k,vtkMatrix4x4* matrix)
+{
+  //
+  //  Multiplcation is R^t * H * R  (R is the inverse of usual matrix!)
+  //
+  //  TempMatrix 1 = R^t
+  //  matrix = R
+  // Image Data is H
+
+  int doprint=0; 
+  if (i==64 && j==69 && k==13 && this->Debug)
+    {
+      fprintf(stderr,"i=%d j=%d k=%d\n",i,j,k);
+      doprint=1;
+    }
+
+
+  if (doprint)
+    r_print_mat44(matrix,"Input matrix");
+
+  this->TempMatrix1->Invert(matrix,this->TempMatrix1);
+
+  if (doprint)
+    r_print_mat44(this->TempMatrix1,"matrix^-1");
+
+
+  this->TempMatrix2->Identity();
+  this->TempMatrix2->SetElement(0,0,input->GetScalarComponentAsDouble(i,j,k,0));
+  
+  double tmp;
+
+  tmp=input->GetScalarComponentAsDouble(i,j,k,1)*this->Flips[0]*this->Flips[1];
+  this->TempMatrix2->SetElement(0,1,tmp);   this->TempMatrix2->SetElement(1,0,tmp);
+
+  tmp=input->GetScalarComponentAsDouble(i,j,k,2)*this->Flips[0]*this->Flips[2];
+  this->TempMatrix2->SetElement(0,2,tmp);   this->TempMatrix2->SetElement(2,0,tmp);
+
+  tmp=input->GetScalarComponentAsDouble(i,j,k,3);  this->TempMatrix2->SetElement(1,1,tmp);  
+
+  tmp=input->GetScalarComponentAsDouble(i,j,k,4)*this->Flips[1]*this->Flips[2];
+  this->TempMatrix2->SetElement(1,2,tmp);   this->TempMatrix2->SetElement(2,1,tmp);
+
+  tmp=input->GetScalarComponentAsDouble(i,j,k,5);  this->TempMatrix2->SetElement(2,2,tmp);  
+
+
+  if (doprint)
+    r_print_mat44(this->TempMatrix2,"Input Tensor");
+
+
+  vtkMatrix4x4::Multiply4x4(this->TempMatrix2,this->TempMatrix1,this->TempMatrix3);
+  vtkMatrix4x4::Multiply4x4(matrix,this->TempMatrix3,this->TempMatrix2);
+
+  if (doprint)
+    r_print_mat44(this->TempMatrix2,"Output Tensor");
+
+  output->SetScalarComponentFromDouble(i,j,k,0,this->TempMatrix2->GetElement(0,0));
+  output->SetScalarComponentFromDouble(i,j,k,1,this->TempMatrix2->GetElement(0,1));
+  output->SetScalarComponentFromDouble(i,j,k,2,this->TempMatrix2->GetElement(0,2));
+  output->SetScalarComponentFromDouble(i,j,k,3,this->TempMatrix2->GetElement(1,1));
+  output->SetScalarComponentFromDouble(i,j,k,4,this->TempMatrix2->GetElement(1,2));
+  output->SetScalarComponentFromDouble(i,j,k,5,this->TempMatrix2->GetElement(2,2));
+}
+
+// --------------------------------------------------------------------------------------------
+void vtkpxImageReorientTensorOrVector::WarpVector(vtkImageData* inp,vtkImageData* output,int i,int j,int k,vtkMatrix4x4* matrix)
+{
+  double vec[4],vecout[4]; vec[3]=1.0;
+  for (int ia=0;ia<=2;ia++)
+    vec[ia]=inp->GetScalarComponentAsDouble(i,j,k,ia);
+
+  matrix->MultiplyPoint(vec,vecout);
+
+  if (output->GetScalarType()!=VTK_UNSIGNED_CHAR)
+    {
+      for (int ia=0;ia<=2;ia++)
+	output->SetScalarComponentFromDouble(i,j,k,ia,vecout[ia]);
+    }
+  else
+    {
+      for (int ia=0;ia<=2;ia++)
+	output->SetScalarComponentFromDouble(i,j,k,ia,fabs(vecout[ia]));
+    }
+}
+// --------------------------------------------------------------------------------------------
+void vtkpxImageReorientTensorOrVector::ProcessInputTransformation(vtkImageData* input)
+{
+  vtkDebugMacro(<<"Processing Input Transformation\n");
+
+  if (this->Transformation->IsA("vtkHomogeneousTransform")==0)
+    {
+      vtkDebugMacro(<<"Computing Displacement Field");
+      vtkTransformToGrid* tgr=vtkTransformToGrid::New();
+      tgr->SetGridOrigin(input->GetOrigin());
+      tgr->SetGridSpacing(input->GetSpacing());
+      tgr->SetGridExtent(input->GetExtent());
+      tgr->SetGridScalarTypeToFloat();
+      tgr->SetInput(this->Transformation);
+      tgr->Update();
+      
+      vtkDebugMacro(<<"Done Computing\n");
+
+      if (this->DisplacementField!=NULL)
+	this->DisplacementField->Delete();
+      
+      this->DisplacementField=vtkImageData::New();
+      this->DisplacementField->ShallowCopy(tgr->GetOutput());
+      tgr->Delete();
+
+      vtkDebugMacro(<<"Copied Field\n");
+
+      if (this->GlobalMatrix!=NULL)
+	this->GlobalMatrix->Delete();
+      this->GlobalMatrix=NULL;
+
+      vtkDebugMacro(<<"Cleanup Global Matrix\n");
+      return;
+    }
+
+  vtkDebugMacro(<<"Fiting Global Rigid Transformation");
+
+  vtkPoints* tmp1=vtkPoints::New();
+  vtkPoints* tmp2=vtkPoints::New();
+
+  tmp1->SetNumberOfPoints(8);
+  tmp2->SetNumberOfPoints(8);
+
+  tmp1->SetPoint(0,-5.0,-5.0,-5.0);
+  tmp1->SetPoint(1, 5.0,-5.0,-5.0);
+  tmp1->SetPoint(2,-5.0, 5.0,-5.0);
+  tmp1->SetPoint(3, 5.0, 5.0,-5.0);
+  tmp1->SetPoint(4,-5.0,-5.0, 5.0);
+  tmp1->SetPoint(5, 5.0,-5.0, 5.0);
+  tmp1->SetPoint(6,-5.0, 5.0, 5.0);
+  tmp1->SetPoint(7, 5.0, 5.0, 5.0);
+  
+  vtkDebugMacro(<<"On To Transform Points\n");
+
+  for (int i=0;i<=7;i++)
+    {
+      double x[3];       tmp1->GetPoint(i,x);
+      if (this->Debug)
+	fprintf(stderr,"Mapping (%.2f,%.2f,%.2f) \t ",x[0],x[1],x[2]);
+
+      this->Transformation->TransformPoint(x,x);
+      if (this->Debug)
+	fprintf(stderr,"to (%.2f,%.2f,%.2f) \n ",x[0],x[1],x[2]);
+      tmp2->SetPoint(i,x);
+    }
+
+  if (this->Debug)
+    fprintf(stderr,"Number Of Points %d vs %d\n",
+	    tmp1->GetNumberOfPoints(),
+	    tmp2->GetNumberOfPoints());
+
+  vtkLandmarkTransform* templan=vtkLandmarkTransform::New();
+  templan->DebugOn();
+  templan->SetSourceLandmarks(tmp1);
+  templan->SetTargetLandmarks(tmp2);
+  templan->SetModeToRigidBody();
+  templan->Modified();
+  templan->Update();
+  templan->DebugOff();
+  this->GlobalMatrix=vtkMatrix4x4::New();
+  templan->GetMatrix(this->GlobalMatrix);
+  templan->Delete();
+  tmp1->Delete();
+  tmp2->Delete();
+
+  for (int ia=0;ia<=2;ia++)
+    this->GlobalMatrix->SetElement(ia,3,0.0);
+
+
+  r_print_mat44(this->GlobalMatrix,"global matrix");
+  
+}
+
+// --------------------------------------------------------------------------------------------
+void vtkpxImageReorientTensorOrVector::ComputeLocalRotation(vtkImageData* dispfield,int i,int j,int k,
+							    double origin[3],double spacing[3],vtkMatrix4x4* matrix)
+{
+  
+  /*  const int offset[7][3] = { 
+    { 0,0,0 }, 
+    { -1,0,0},{1,0,0},
+    {0,-1,0}, {0,1,0},
+    { 0,0,-1},{0,0,1}};*/
+
+  int maxpoints=27;
+  if (this->Use7Points)
+    maxpoints=7;
+
+  const double offset[27][3] = { 
+    { 0.0,0.0,0.0 }, 
+    { -1.0,0.0,0.0},{1.0,0.0,0.0},
+    {0.0,-1.0,0.0}, {0.0,1.0,0.0},
+    { 0.0,0.0,-1.0},{0.0,0.0,1.0},
+    { -1.0,-1.0,-1.0 } , { -1.0 ,0.0 , -1.0 } , { -1.0 , 1.0 -1.0 } , { 0.0,-1.0,-1.0} , 
+    { 0.0,1.0,-1.0}, { 1.0,-1.0,-1.0} , { 1.0,0.0,-1.0},{1.0,1.0,-1.0},
+    { -1.0,-1.0,0.0}   , { -1.0,1.0,0.0} , { 1.0,-1.0,0.0}, { 1.0,1.0,0.0},
+    { -1.0,-1.0,1.0 } , { -1.0 ,0.0 , 1.0 } , { -1.0 , 1.0, 1.0 } , { 0.0,-1.0,1.0} , 
+    { 0.0,1.0,1.0}, { 1.0,-1.0,1.0} , { 1.0,0.0,-1.0},{1.0,1.0,1.0}
+  };
+
+  int doprint=0; 
+  if (i==14 && j==15 && k==14 && this->Debug)
+    {
+      fprintf(stderr,"i=%d j=%d k=%d\n",i,j,k);
+      doprint=1;
+    }
+
+
+  int ijk[3];  ijk[0]=i;  ijk[1]=j;  ijk[2]=k;
+
+  double x[3],y[3],d[3];
+  for (int ia=0;ia<maxpoints;ia++)
+    {
+      for (int ib=0;ib<=2;ib++)
+	{
+	  //	  x[ib]=origin[ib]+double(ijk[ib]+offset[ia][ib])*spacing[ib];
+	  x[ib]=offset[ia][ib]*spacing[ib];
+	  d[ib]=dispfield->GetScalarComponentAsDouble(i+(int)offset[ia][0],j+(int)offset[ia][1],k+(int)offset[ia][2],ib);
+	  y[ib]=x[ib]+d[ib];
+	}
+      this->TempPoints1->SetPoint(ia,x);
+      this->TempPoints2->SetPoint(ia,y);
+      if (doprint)
+	fprintf(stderr,"point %d (%.2f,%.2f,%.2f) + (%.2f,%.2f,%.2f) --> (%.2f,%.2f,%.2f)\n",
+		ia,x[0],x[1],x[2],d[0],d[1],d[2],y[0],y[1],y[2]);
+    }
+  this->TempLandmarkTransform->Modified();
+  this->TempLandmarkTransform->Update();
+  this->TempLandmarkTransform->GetMatrix(matrix);
+  for (int ia=0;ia<=2;ia++)
+    matrix->SetElement(ia,3,0.0);
+  
+  if (doprint)
+    r_print_mat44(matrix,"Fitted matrix");
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageReorientTensorOrVector.h b/bioimagesuite30_src/Imaging/vtkpxImageReorientTensorOrVector.h
new file mode 100644
index 0000000..c5cb28f
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageReorientTensorOrVector.h
@@ -0,0 +1,150 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageReorientTensorOrVector.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageReorientTensorOrVector -- compute the difference and a normalized difference
+// between two images
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageReorientTensorOrVector_h
+#define __vtkpxImageReorientTensorOrVector_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkAbstractTransform.h"
+
+class vtkMatrix4x4;
+class vtkPoints;
+class vtkLandmarkTransform;
+
+class vtkpxImageReorientTensorOrVector : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageReorientTensorOrVector *New();
+  vtkTypeMacro(vtkpxImageReorientTensorOrVector,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // DisplacementField -- second input to compare with input
+  vtkSetObjectMacro(DisplacementField,vtkImageData);
+  vtkGetObjectMacro(DisplacementField,vtkImageData);
+
+  // Description:
+  // DisplacementField -- second input to compare with input
+  vtkSetObjectMacro(Transformation,vtkAbstractTransform);
+  vtkGetObjectMacro(Transformation,vtkAbstractTransform);
+
+  // Description:
+  // Use Only 7 Points
+  vtkGetMacro(Use7Points,int);
+  vtkSetClampMacro(Use7Points,int,0,1);
+  vtkBooleanMacro(Use7Points,int);
+
+
+  // Description:
+  // Flip X,Y or Z axis
+  vtkGetMacro(FlipX,int);
+  vtkSetClampMacro(FlipX,int,0,1);
+  vtkBooleanMacro(FlipX,int);
+
+  vtkGetMacro(FlipY,int);
+  vtkSetClampMacro(FlipY,int,0,1);
+  vtkBooleanMacro(FlipY,int);
+
+  vtkGetMacro(FlipZ,int);
+  vtkSetClampMacro(FlipZ,int,0,1);
+  vtkBooleanMacro(FlipZ,int);
+
+protected:
+
+  vtkpxImageReorientTensorOrVector();
+  virtual ~vtkpxImageReorientTensorOrVector();
+  vtkpxImageReorientTensorOrVector(const vtkpxImageReorientTensorOrVector&) {};
+  void operator=(const vtkpxImageReorientTensorOrVector&) {};
+
+  vtkImageData* DisplacementField;
+  vtkAbstractTransform* Transformation;
+  vtkMatrix4x4* GlobalMatrix;
+
+  // Cached Data Structures to Eliminate allocate/deallocate
+  vtkMatrix4x4* TempMatrix1;
+  vtkMatrix4x4* TempMatrix2;
+  vtkMatrix4x4* TempMatrix3;
+  vtkPoints* TempPoints1;
+  vtkPoints* TempPoints2;
+  vtkLandmarkTransform* TempLandmarkTransform;
+  int Use7Points;
+  int FlipX;
+  int FlipY;
+  int FlipZ;
+  double Flips[3];
+  
+  // Execute Warping
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+
+  // Description:
+  // Compute Local Rotation at each voxel
+  virtual void ComputeLocalRotation(vtkImageData* inp,int i,int j,int k,double origin[3],double spacing[3],vtkMatrix4x4* matrix);
+  virtual void WarpTensor(vtkImageData* inp,vtkImageData* output,int i,int j,int k,vtkMatrix4x4* matrix);
+  virtual void WarpVector(vtkImageData* inp,vtkImageData* output,int i,int j,int k,vtkMatrix4x4* matrix);
+
+  // Description:
+  // Postprocess transformation to yield either displacement field or global matrix
+  virtual void ProcessInputTransformation(vtkImageData* input);
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageSincInterpolation.cpp b/bioimagesuite30_src/Imaging/vtkpxImageSincInterpolation.cpp
new file mode 100644
index 0000000..ec59249
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageSincInterpolation.cpp
@@ -0,0 +1,222 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageSincInterpolation.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkpxImageSincInterpolation.h"
+
+#include <vtkDataArray.h>
+#include <vtkImageData.h>
+#include <vtkImageExtractComponents.h>
+#include <vtkImageFFT.h>
+#include <vtkImageFourierCenter.h>
+#include <vtkImageRFFT.h>
+#include <vtkImageConstantPad.h>
+#include <vtkImageMagnitude.h>
+#include <vtkImageShiftScale.h>
+//------------------------------------------------------------------------------
+vtkpxImageSincInterpolation* vtkpxImageSincInterpolation::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageSincInterpolation");
+  if(ret)
+    {
+    return (vtkpxImageSincInterpolation*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageSincInterpolation;
+}
+
+// Construct object with no children.
+vtkpxImageSincInterpolation::vtkpxImageSincInterpolation()
+{
+  this->Factor=1;
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageSincInterpolation::ExecuteInformation()
+{
+  vtkImageData *input=this->GetImageDataInput(0);
+
+  if (input==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image !!");
+	return;
+      }
+
+  vtkImageData *output=this->GetOutput();
+
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int wholeExtent[6];
+  input->GetWholeExtent( wholeExtent );
+
+  int dims[3];
+
+  dims[0] =  (wholeExtent[1] - wholeExtent[0] );
+  dims[1] =  (wholeExtent[3] - wholeExtent[2] );
+  dims[2] =  (wholeExtent[5] - wholeExtent[4] );
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      int a=int(log(float(dims[ia]))/log(2.0)+0.99);
+      int d=int(pow(2.0,a)*this->Factor);
+      //int d=dims[ia]*this->Factor;
+      dims[ia]=d;
+    }
+
+  wholeExtent[0] = 0;
+  wholeExtent[1] = dims[0] - 1;
+  wholeExtent[2] = 0;
+  wholeExtent[3] = dims[1] - 1;
+  wholeExtent[4] = 0;
+  wholeExtent[5] = dims[2] - 1;
+  output->SetWholeExtent( wholeExtent );
+}
+
+// ----------------------------------------------------------------------------
+
+void vtkpxImageSincInterpolation::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  
+  // Create Output Array
+  // -------------------
+  int   dim[3]; input->GetDimensions(dim);
+  int   pdim[3];
+  int   newdim[3],newextent[6];
+  double sp[3];  input->GetSpacing(sp);
+  double ori[3];  input->GetOrigin(ori);
+  
+  for (int ia=0;ia<=2;ia++)
+    {
+      int a=int(log(float(dim[ia]))/log(2.0)+0.99);
+      pdim[ia]=int(pow(2.0,a));
+      //pdim[ia]=dim[ia];
+      newdim[ia]=int(pdim[ia]*this->Factor);
+      newextent[2*ia]=(pdim[ia]-newdim[ia])/2;
+      newextent[2*ia+1]=(pdim[ia]+newdim[ia])/2-1;
+      sp[ia]=float(dim[ia])/float(newdim[ia])*sp[ia];
+    }
+
+  output->SetSpacing(sp);
+  output->SetOrigin(input->GetOrigin());
+  output->SetScalarType(input->GetScalarType());
+  output->SetNumberOfScalarComponents(input->GetNumberOfScalarComponents());
+  output->SetDimensions(newdim[0],newdim[1],newdim[2]);
+  output->SetWholeExtent(0,newdim[0]-1,0,newdim[1]-1,0,newdim[2]-1);
+  output->SetUpdateExtent(0,newdim[0]-1,0,newdim[1]-1,0,newdim[2]-1);
+  output->AllocateScalars();
+
+  float progress=0.0;
+  float dprog=1.0/float(output->GetNumberOfScalarComponents());
+
+  vtkDataArray* out_array=output->GetPointData()->GetScalars();
+
+  this->UpdateProgress(0.0);
+
+  for (int comp=0;comp<output->GetNumberOfScalarComponents();comp++)
+    {
+      vtkImageExtractComponents* compExtract=vtkImageExtractComponents::New();
+      compExtract->SetInput(input);
+      compExtract->SetComponents(comp);
+      compExtract->Update();
+
+      vtkImageShiftScale* sc=vtkImageShiftScale::New();
+      sc->SetInput(compExtract->GetOutput());
+      compExtract->Delete();
+      sc->SetOutputScalarTypeToFloat();
+      sc->SetShift(0.0);
+      sc->SetScale(this->Factor*this->Factor*this->Factor);
+      sc->Update();
+
+      vtkImageFFT* fft=vtkImageFFT::New();
+      fft->SetInput(sc->GetOutput());
+      sc->Delete();
+      fft->SetDimensionality(3);
+      fft->Update();
+
+      vtkImageFourierCenter* cent=vtkImageFourierCenter::New();
+      cent->SetInput(fft->GetOutput());
+      fft->Delete();
+
+      vtkImageConstantPad* padFilter=vtkImageConstantPad::New();
+      padFilter->SetInput(cent->GetOutput());
+      cent->Delete();
+      padFilter->SetConstant(0);
+      padFilter->SetOutputWholeExtent(newextent);
+      padFilter->Update();
+      
+      vtkImageRFFT* rfft=vtkImageRFFT::New();
+      rfft->SetInput(padFilter->GetOutput());
+      padFilter->Delete();
+      rfft->SetDimensionality(3);
+      rfft->Update();
+
+      vtkImageMagnitude* magn=vtkImageMagnitude::New();
+      magn->SetInput(rfft->GetOutput());
+      rfft->Delete();
+      magn->Update();
+
+      vtkDataArray* in_array=magn->GetOutput()->GetPointData()->GetScalars();
+      out_array->CopyComponent(comp,in_array,0);
+
+      progress+=dprog;
+      this->UpdateProgress(progress);
+      
+      magn->Delete();
+    }
+}
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageSincInterpolation.h b/bioimagesuite30_src/Imaging/vtkpxImageSincInterpolation.h
new file mode 100644
index 0000000..4a73d15
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageSincInterpolation.h
@@ -0,0 +1,93 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageSincInterpolation.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageSincInterpolation -- creates activation maps from raw fmri data
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageSincInterpolation_h
+#define __vtkpxImageSincInterpolation_h
+
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+
+
+class vtkpxImageSincInterpolation : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageSincInterpolation *New();
+  vtkTypeMacro(vtkpxImageSincInterpolation,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Sets the In Plane Sampling Level
+  vtkGetMacro(Factor,int);
+  vtkSetClampMacro(Factor,int,1,10);
+
+protected:
+
+  vtkpxImageSincInterpolation();
+  vtkpxImageSincInterpolation(const vtkpxImageSincInterpolation&) {};
+  void operator=(const vtkpxImageSincInterpolation&) {};
+
+  virtual void SimpleExecute(vtkImageData*,vtkImageData*);
+  void ExecuteInformation();
+
+  int  Factor;
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageStitch.cpp b/bioimagesuite30_src/Imaging/vtkpxImageStitch.cpp
new file mode 100644
index 0000000..fed8580
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageStitch.cpp
@@ -0,0 +1,188 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageStitch.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxImageStitch.h"
+#include "vtkpxUtil.h"
+#include "vtkFloatArray.h"
+#include "vtkImageGaussianSmooth.h"
+//------------------------------------------------------------------------------
+vtkpxImageStitch* vtkpxImageStitch::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageStitch");
+  if(ret)
+    {
+    return (vtkpxImageStitch*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageStitch;
+}
+
+// Construct object with no children.
+vtkpxImageStitch::vtkpxImageStitch()
+{
+  this->Axis=0;
+  this->SeamCoordinate=-1;
+  this->Input2=NULL;
+  this->FlipOrientation=0;
+  //  this->Transformation=NULL;
+  //  this->AutoAdjustImageSize=0;
+}
+// ----------------------------------------------------------------------------
+vtkpxImageStitch::~vtkpxImageStitch()
+{
+  this->SetInput2(NULL);
+  //  this->SetTransformation(NULL);
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageStitch::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+
+  if (input==NULL    || this->Input2==NULL )
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxImageStitch");
+      return;
+    }
+   
+
+  int dim[3],dim2[3];
+  input->GetDimensions(dim);
+  this->Input2->GetDimensions(dim2);
+  
+  int ssum=0;
+  for (int ia=0;ia<=2;ia++)
+    ssum+=abs(dim[ia]-dim2[ia]);
+
+  ssum+=abs(input->GetNumberOfScalarComponents()-this->Input2->GetNumberOfScalarComponents());
+  if (ssum!=0)
+    {
+      vtkErrorMacro(<<"Bad Input Dimensions");
+      return;
+    }
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* inp[2];
+  inp[0]= input->GetPointData()->GetScalars();
+  inp[1]= Input2->GetPointData()->GetScalars();
+
+  this->UpdateProgress(0.01);
+  
+  float pog=0.00;
+  float tenth=out->GetNumberOfTuples()/10.0;
+  int count=0;
+  int pixel=0;
+  int currentimage=0;
+  int nc=out->GetNumberOfComponents();
+
+  if (this->SeamCoordinate<0)
+    this->SeamCoordinate=dim[this->Axis]/2;
+
+  //  fprintf(stderr,"Beginning Stitching Axis=%d Coordinate=%d\n",this->Axis,this->SeamCoordinate);
+
+  for (int k=0;k<dim[2];k++)
+    {
+      if (this->Axis==2)
+	{
+	  if (k<this->SeamCoordinate)
+	    currentimage=0;
+	  else
+	    currentimage=1;
+	  if (this->FlipOrientation)
+	    currentimage=1-currentimage;
+	}
+
+      for (int j=0;j<dim[1];j++)
+	{
+	  if (this->Axis==1)
+	    {
+	      if (j<this->SeamCoordinate)
+		currentimage=0;
+	      else
+		currentimage=1;
+	      if (this->FlipOrientation)
+		currentimage=1-currentimage;
+	    }
+
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      if (this->Axis==0)
+		{
+		  if (i<this->SeamCoordinate)
+		    currentimage=0;
+		  else
+		    currentimage=1;
+		  if (this->FlipOrientation)
+		    currentimage=1-currentimage;
+		}
+	      
+	      for (int c=0;c<nc;c++)
+		out->SetComponent(pixel,c,inp[currentimage]->GetComponent(pixel,c));
+	      ++pixel;
+	      ++count;
+	      if (count==tenth)
+		{
+		  pog+=0.05;
+		  this->UpdateProgress(pog);
+		  count=0;
+		}
+	    }
+	}
+    }
+
+  this->UpdateProgress(1.0);
+
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageStitch.h b/bioimagesuite30_src/Imaging/vtkpxImageStitch.h
new file mode 100644
index 0000000..2768bb6
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageStitch.h
@@ -0,0 +1,113 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageStitch.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageStitch -- compute the ratio and a normalized ratio between two images
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageStitch_h
+#define __vtkpxImageStitch_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkpxImageStitch : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageStitch *New();
+  vtkTypeMacro(vtkpxImageStitch,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set value of threshold between 0 and 1 below which the percentage
+  // change is set to zero by default
+  vtkGetMacro(SeamCoordinate,int);
+  vtkSetMacro(SeamCoordinate,int);
+
+  // Description:
+  // Smooth Difference before computing percentages
+  vtkGetMacro(Axis,int);
+  vtkSetClampMacro(Axis,int,0,2);
+
+  // Description:
+  // Smooth Difference before computing percentages
+  vtkGetMacro(FlipOrientation,int);
+  vtkSetClampMacro(FlipOrientation,int,0,1);
+  vtkBooleanMacro(FlipOrientation,int);
+
+  // Description:
+  // Input2 -- second input to stitch with input
+  vtkSetObjectMacro(Input2,vtkImageData);
+  vtkGetObjectMacro(Input2,vtkImageData);
+
+
+protected:
+
+  vtkpxImageStitch();
+  virtual ~vtkpxImageStitch();
+  vtkpxImageStitch(const vtkpxImageStitch&) {};
+  void operator=(const vtkpxImageStitch&) {};
+
+  virtual void SimpleExecute(vtkImageData* in,vtkImageData* out);
+
+  int         Axis;
+  int         SeamCoordinate;
+  int         FlipOrientation;
+  vtkImageData* Input2;
+
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageThresholdedIntersection.cpp b/bioimagesuite30_src/Imaging/vtkpxImageThresholdedIntersection.cpp
new file mode 100644
index 0000000..596d0ee
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageThresholdedIntersection.cpp
@@ -0,0 +1,209 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageThresholdedIntersection.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:09:25 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkpxImageThresholdedIntersection.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+//------------------------------------------------------------------------------
+vtkpxImageThresholdedIntersection* vtkpxImageThresholdedIntersection::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageThresholdedIntersection");
+  if(ret)
+    {
+    return (vtkpxImageThresholdedIntersection*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageThresholdedIntersection;
+}
+
+// Construct object with no children.
+vtkpxImageThresholdedIntersection::vtkpxImageThresholdedIntersection()
+{
+  this->ThresholdMode=0;
+  this->Threshold=2000.0;
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageThresholdedIntersection::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+  output->SetScalarTypeToFloat();
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageThresholdedIntersection::SimpleExecute(vtkImageData* ,vtkImageData* output)
+{
+
+  if (this->GetNumberOfInputPorts()==0 || this->GetImageDataInput(0)==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+
+  int dim_0[3];
+  this->GetImageDataInput(0)->GetDimensions(dim_0);
+  int num_comp=this->GetImageDataInput(0)->GetNumberOfScalarComponents();
+
+  for (int i=1;i<this->GetNumberOfInputPorts();i++)
+    {
+      if (this->GetImageDataInput(i)==NULL)
+	{
+	  vtkErrorMacro(<<"No Input Image Data " << i << " !!");
+	  return;
+	}
+      else
+	{
+	  int dim_1[3];
+	  this->GetImageDataInput(i)->GetDimensions(dim_1);
+	  int sum=0;
+	  for (int kk=0;kk<=2;kk++)
+	    sum+=abs(dim_1[kk]-dim_0[kk]);
+	  sum+=abs(num_comp-this->GetImageDataInput(i)->GetNumberOfScalarComponents());
+	  if (sum!=0)
+	    {
+	      vtkErrorMacro(<<"Multiple Images have different Dimensions !!");
+	      return;
+	    }
+	}
+    }
+  
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  int numscalars=out->GetNumberOfTuples();
+  
+  this->UpdateProgress(0.01);
+  float pog=0.00;
+
+
+
+
+
+  float tenth=(numscalars*num_comp)/10.0;
+  int count=0;
+
+  int domean=1;
+
+  this->Threshold=fabs(this->Threshold);
+  double minusThreshold=-1.0*this->Threshold;
+
+
+  float factor=float(1.0/this->GetNumberOfInputPorts());
+
+  /*  fprintf(stderr,"Computing Intersection %d %d (thresholds=%.2f %.2f) mode=%d\n",numscalars,out->GetNumberOfComponents(),
+      this->Threshold,minusThreshold,this->ThresholdMode);*/
+
+
+  for (int component=0;component<num_comp;component++)
+    {
+      out->FillComponent(component,0.0);
+      for (int n=0;n<numscalars;n++)
+	{
+	  int flag=1;
+	  int series=0;
+	  int positive=1;
+	  double v0=0.0;
+	  while(series < this->GetNumberOfInputPorts() && flag==1) 
+	    {
+	      double v=this->GetImageDataInput(series)->GetPointData()->GetScalars()->GetComponent(n,component);
+	      if (series==0)
+		v0=v;
+	      
+	      switch (this->ThresholdMode)
+		{
+		case 0:
+		  if (v<this->Threshold)
+		    flag=0;
+		  break;
+		case 1:
+		  if (v>minusThreshold)
+		    flag=0;
+		  break;
+		case 2:
+		  if (v<this->Threshold && v > minusThreshold)
+		    flag=0;
+		  else if ( (series > 0) && (v*v0 < 0.0) )
+		    flag=0;
+		  break;
+		}
+	      ++series;
+	    }
+	  
+	  if (flag==1) 
+	    {
+	      float sum=0.0;
+	      for (int series=0;series<this->GetNumberOfInputPorts();series++)
+		{
+		  float v=this->GetImageDataInput(series)->GetPointData()->GetScalars()->GetComponent(n,component);
+		  sum+=v;
+		}
+	      float mean =sum*factor;
+	      out->SetComponent(n,component,mean);
+	    }
+	  
+	  count++;
+	  if (count==tenth)
+	    {
+	      pog+=0.1;
+	      this->UpdateProgress(pog);
+	      count=0;
+	    }
+	}
+    }
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageThresholdedIntersection.h b/bioimagesuite30_src/Imaging/vtkpxImageThresholdedIntersection.h
new file mode 100644
index 0000000..85c3e12
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageThresholdedIntersection.h
@@ -0,0 +1,103 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageThresholdedIntersection.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:08:12 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageThresholdedIntersection -- combines images to form either mean or median
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageThresholdedIntersection_h
+#define __vtkpxImageThresholdedIntersection_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+
+class vtkpxImageThresholdedIntersection : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageThresholdedIntersection *New();
+  vtkTypeMacro(vtkpxImageThresholdedIntersection,vtkpxSimpleImageToImageFilter);
+
+
+  // Description:
+  // Set Threhold Mode 
+  vtkSetClampMacro(ThresholdMode,int,0,2);
+  vtkGetMacro(ThresholdMode,int);
+  virtual void ThresholdPositiveOnly() { this->SetThresholdMode(0); }
+  virtual void ThresholdNegativeOnly() { this->SetThresholdMode(1); }
+  virtual void ThresholdBoth()         { this->SetThresholdMode(2); }
+
+  // Description:
+  // Threshold Value
+  vtkSetMacro(Threshold, double);
+  vtkGetMacro(Threshold, double);
+
+
+protected:
+
+  //BTX
+  vtkpxImageThresholdedIntersection();
+  vtkpxImageThresholdedIntersection(const vtkpxImageThresholdedIntersection&) {};
+  void operator=(const vtkpxImageThresholdedIntersection&) {};
+
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual void ExecuteInformation();
+  int         ThresholdMode;
+  double      Threshold;
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageVariableSmoothing.cpp b/bioimagesuite30_src/Imaging/vtkpxImageVariableSmoothing.cpp
new file mode 100644
index 0000000..e8644b4
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageVariableSmoothing.cpp
@@ -0,0 +1,179 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageVariableSmoothing.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxImageVariableSmoothing.h"
+#include "vtkpxUtil.h"
+#include "vtkFloatArray.h"
+#include "vtkImageGaussianSmooth.h"
+//------------------------------------------------------------------------------
+vtkpxImageVariableSmoothing* vtkpxImageVariableSmoothing::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageVariableSmoothing");
+  if(ret)
+    {
+    return (vtkpxImageVariableSmoothing*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageVariableSmoothing;
+}
+
+// Construct object with no children.
+vtkpxImageVariableSmoothing::vtkpxImageVariableSmoothing()
+{
+  this->LowerThreshold=2.0;
+  this->LowerSigma=1.0;
+  this->UpperThreshold=5.0;
+  this->UpperSigma=3.0;
+  this->DistanceMap=NULL;
+  this->RatioMap=NULL;
+}
+// ----------------------------------------------------------------------------
+vtkpxImageVariableSmoothing::~vtkpxImageVariableSmoothing()
+{
+  this->SetDistanceMap(NULL);
+  if (this->RatioMap!=NULL)
+    this->RatioMap->Delete();
+}
+// ----------------------------------------------------------------------------
+void vtkpxImageVariableSmoothing::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL    || this->DistanceMap==NULL )
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxImageVariableSmoothing");
+      return;
+    }
+
+  int dim[3],dim2[3];
+  input->GetDimensions(dim);
+  this->DistanceMap->GetDimensions(dim2);
+  
+  int sum=0;
+  for (int ia=0;ia<=2;ia++)
+    sum+=abs(dim[ia]-dim2[ia]);
+  if (sum!=0)
+    {
+      vtkErrorMacro(<<"Bad Input/Distance Map  Dimensions");
+      return;
+    }
+    
+  vtkImageGaussianSmooth* smooth[2];
+  vtkDataArray* sm_img[2];
+
+  double sp[3]; input->GetSpacing(sp);
+
+  for (int ia=0;ia<=1;ia++)
+    {
+      smooth[ia]=vtkImageGaussianSmooth::New();
+      smooth[ia]->SetInput(input);
+      float sigma=this->LowerSigma;
+      if (ia==1)
+	sigma=this->UpperSigma;
+      smooth[ia]->SetStandardDeviations(sigma,sigma*sp[0]/sp[1],sigma*sp[0]/sp[2]);
+      smooth[ia]->Update();
+      sm_img[ia]=smooth[ia]->GetOutput()->GetPointData()->GetScalars();
+      this->UpdateProgress(0.2*double(ia+1));
+    }
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  if (this->RatioMap==NULL)
+    this->RatioMap=vtkImageData::New();
+  this->RatioMap->CopyStructure(this->DistanceMap);
+  this->RatioMap->AllocateScalars();
+
+  vtkDataArray* dist=this->DistanceMap->GetPointData()->GetScalars();
+  vtkDataArray* rmap=this->RatioMap->GetPointData()->GetScalars();
+  int np=out->GetNumberOfTuples();
+  int nc=out->GetNumberOfComponents();
+
+  // A Hack but ...
+  if (this->UpperThreshold<=this->LowerThreshold)
+    this->UpperThreshold=this->LowerThreshold+1.0;
+  float diff=this->UpperThreshold-this->LowerThreshold;
+
+  for (int i=0;i<np;i++)
+    {
+      float d=fabs(dist->GetComponent(i,0));
+      for (int j=0;j<nc;j++)
+	{
+	  if (d<=this->LowerThreshold)
+	    {
+	      out->SetComponent(i,j,sm_img[0]->GetComponent(i,j));
+	      rmap->SetComponent(i,j,0.0);
+	    }
+	  else if (d>=this->UpperThreshold)
+	    {
+	      out->SetComponent(i,j,sm_img[1]->GetComponent(i,j));
+	      rmap->SetComponent(i,j,100.0);
+	    }
+	  else
+	    {
+	      float ratio=(d-this->LowerThreshold)/diff;
+	      out->SetComponent(i,j,
+				(1.0-ratio)*sm_img[0]->GetComponent(i,j)+
+				ratio*sm_img[1]->GetComponent(i,j));
+	      rmap->SetComponent(i,j,100.0*ratio);
+	    }
+	}
+    }
+
+  smooth[0]->Delete();
+  smooth[1]->Delete();
+
+  this->UpdateProgress(1.0);
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxImageVariableSmoothing.h b/bioimagesuite30_src/Imaging/vtkpxImageVariableSmoothing.h
new file mode 100644
index 0000000..45134a4
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxImageVariableSmoothing.h
@@ -0,0 +1,117 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageVariableSmoothing.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageVariableSmoothing -- compute the difference and a normalized difference
+// between two images
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageVariableSmoothing_h
+#define __vtkpxImageVariableSmoothing_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkpxImageVariableSmoothing : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxImageVariableSmoothing *New();
+  vtkTypeMacro(vtkpxImageVariableSmoothing,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // If (dist< LowerThreshld smooth with Smooth Value= Lower Sigma)
+  vtkGetMacro(LowerThreshold,float);
+  vtkSetClampMacro(LowerThreshold,float,0.001,10.0);
+
+  vtkGetMacro(LowerSigma,float);
+  vtkSetClampMacro(LowerSigma,float,0.5,10.0);
+
+  // Description:
+  // If (dist> UpperThreshld smooth with Smooth Value = UpperSigma)
+  // Else Interpolate .....
+  vtkGetMacro(UpperThreshold,float);
+  vtkSetClampMacro(UpperThreshold,float,0.001,10.0);
+
+  vtkGetMacro(UpperSigma,float);
+  vtkSetClampMacro(UpperSigma,float,0.5,10.0);
+
+  // Description:
+  // DistanceMap -- distance from traced structure
+  vtkSetObjectMacro(DistanceMap,vtkImageData);
+  vtkGetObjectMacro(DistanceMap,vtkImageData);
+
+  // Description:
+  // Ratio Map (debug how things were mixed);
+  vtkGetObjectMacro(RatioMap,vtkImageData);
+
+protected:
+
+  vtkpxImageVariableSmoothing();
+  virtual ~vtkpxImageVariableSmoothing();
+  vtkpxImageVariableSmoothing(const vtkpxImageVariableSmoothing&) {};
+  void operator=(const vtkpxImageVariableSmoothing&) {};
+
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  float         LowerThreshold;
+  float         LowerSigma;
+  float         UpperThreshold;
+  float         UpperSigma;
+  vtkImageData* DistanceMap;
+  vtkImageData* RatioMap;
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxMaximumImages.cpp b/bioimagesuite30_src/Imaging/vtkpxMaximumImages.cpp
new file mode 100644
index 0000000..fc669d4
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxMaximumImages.cpp
@@ -0,0 +1,183 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxMaximumImages.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:09:25 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkpxMaximumImages.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+//------------------------------------------------------------------------------
+vtkpxMaximumImages* vtkpxMaximumImages::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxMaximumImages");
+  if(ret)
+    {
+    return (vtkpxMaximumImages*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxMaximumImages;
+}
+
+// Construct object with no children.
+vtkpxMaximumImages::vtkpxMaximumImages()
+{
+  this->OutputIndex=0;
+  this->DoMinimum=0;
+}
+// ----------------------------------------------------------------------------
+vtkpxMaximumImages::~vtkpxMaximumImages()
+{
+}
+// ----------------------------------------------------------------------------
+void vtkpxMaximumImages::SimpleExecute(vtkImageData* ,vtkImageData* output)
+{
+
+  if (this->GetNumberOfInputPorts()==0 || this->GetImageDataInput(0)==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+
+  int dim_0[3];
+  this->GetImageDataInput(0)->GetDimensions(dim_0);
+  int num_comp=this->GetImageDataInput(0)->GetNumberOfScalarComponents();
+
+  fprintf(stderr, "Number of inputs: %d\n", this->GetNumberOfInputPorts());
+
+  for (int i=1;i<this->GetNumberOfInputPorts();i++)
+      {
+	if (this->GetImageDataInput(i)==NULL)
+	  {
+	    vtkErrorMacro(<<"No Input Image Data " << i << " !!");
+	    return;
+	  }
+	else
+	  {
+	    int dim_1[3];
+	    this->GetImageDataInput(i)->GetDimensions(dim_1);
+	    int sum=0;
+	    for (int kk=0;kk<=2;kk++)
+	      sum+=abs(dim_1[kk]-dim_0[kk]);
+	    sum+=abs(num_comp-this->GetImageDataInput(i)->GetNumberOfScalarComponents());
+	    if (sum!=0)
+	      {
+		vtkErrorMacro(<<"Multiple Images have different Dimensions !!");
+		return;
+	      }
+	  }
+      }
+
+
+  // Create Output Array
+  // -------------------
+  int   dim[3];  this->GetImageDataInput(0)->GetDimensions(dim);
+  vtkDebugMacro(<< "Maximum Value from Images\n" <<  "Dimensions " << dim[0] <<","<< dim[1] <<","<< dim[2] << "Components " << num_comp << "\n");
+
+  output->CopyStructure(this->GetImageDataInput(0));
+  output->SetNumberOfScalarComponents(this->GetImageDataInput(0)->GetNumberOfScalarComponents());
+  output->AllocateScalars();
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  int numscalars=out->GetNumberOfTuples();
+
+  this->UpdateProgress(0.01);
+  float pog=0.00;
+
+  int tenth=(numscalars*num_comp)/10;
+  int count=0;
+
+  //  int domean=1;
+  for (int component=0;component<num_comp;component++)
+    {
+      for (int n=0;n<numscalars;n++)
+	{
+	  float max=this->GetImageDataInput(0)->GetPointData()->GetScalars()->GetComponent(n,component);
+	  int bestindex=0;
+	  for (int series=1;series<this->GetNumberOfInputPorts();series++)
+	    {
+	      float v=this->GetImageDataInput(series)->GetPointData()->GetScalars()->GetComponent(n,component);
+	      if ( this->DoMinimum)
+		{
+		  if (v<max)
+		    {
+		      max=v;
+		      bestindex=series;
+		    }
+		} 
+	      else if (v>max)
+		{
+		  max=v;
+		  bestindex=series;
+		}
+	    }
+
+	  if (this->OutputIndex)
+	    out->SetComponent(n,component,bestindex+1);
+	  else
+	    out->SetComponent(n,component,max);
+	}
+      
+      count++;
+      if (count==tenth)
+	{
+	  pog+=0.1;
+	  this->UpdateProgress(pog);
+	  count=0;
+	}
+    }
+  this->UpdateProgress(1.0);
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxMaximumImages.h b/bioimagesuite30_src/Imaging/vtkpxMaximumImages.h
new file mode 100644
index 0000000..698b6df
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxMaximumImages.h
@@ -0,0 +1,102 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxMaximumImages.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:08:12 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxMaximumImages -- combines images to form either mean or median
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxMaximumImages_h
+#define __vtkpxMaximumImages_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+
+class vtkpxMaximumImages : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxMaximumImages *New();
+  vtkTypeMacro(vtkpxMaximumImages,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Output Index i.e. best image as opposed to best value
+  vtkGetMacro(OutputIndex,int);
+  vtkSetClampMacro(OutputIndex,int,0,1);
+
+  vtkGetMacro(DoMinimum,int);
+  vtkSetClampMacro(DoMinimum,int,0,1);
+
+  
+
+protected:
+
+  //BTX
+  vtkpxMaximumImages();
+  virtual ~vtkpxMaximumImages();
+  vtkpxMaximumImages(const vtkpxMaximumImages&) {};
+  void operator=(const vtkpxMaximumImages&) {};
+
+  int OutputIndex;
+  int DoMinimum;
+
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+
+
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxMergeFmriConventional.cpp b/bioimagesuite30_src/Imaging/vtkpxMergeFmriConventional.cpp
new file mode 100644
index 0000000..52e486c
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxMergeFmriConventional.cpp
@@ -0,0 +1,998 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxMergeFmriConventional.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/02/03 16:36:54 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxMergeFmriConventional.h"
+#include "vtkSource.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxUtil.h"
+#include "vtkMatrix4x4.h"
+#include "vtkTransform.h"
+#include "vtkAbstractTransform.h"
+#include "vtkbisImageReslice.h"
+#include "vtkImageData.h"
+#include "vtkImageMedian3D.h"
+#include "vtkImageFlip.h"
+#include "vtkGeneralTransform.h"
+#include "vtkIdentityTransform.h"
+#include "vtkAbstractTransform.h"
+#include "vtkLongArray.h"
+#include "vtkDoubleArray.h"
+//------------------------------------------------------------------------------
+vtkpxMergeFmriConventional* vtkpxMergeFmriConventional::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxMergeFmriConventional");
+  if(ret)
+    {
+    return (vtkpxMergeFmriConventional*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxMergeFmriConventional;
+}
+
+// Construct object with no children.
+vtkpxMergeFmriConventional::vtkpxMergeFmriConventional()
+{
+
+  this->NormalizeAnatomical=1;
+  this->MinimumThreshold=0;
+  this->MaximumThreshold=1;
+  this->ThresholdMode=1;
+  this->IntensityThreshold=5;
+
+  this->fmriInput=NULL;
+  this->Transform1=NULL;
+  this->Transform2=NULL;
+  this->OutputMode=0;
+
+  this->SingleFrameMode=1;
+  this->CurrentFrame=0;
+
+  this->MedianFiltering=0;
+  this->FlipFmri=0;
+  
+  for (int i=0;i<3;i++)
+    for (int j=0;j<2;j++)
+      {
+	this->SourceBounds[i*2+j]=j;
+	this->TargetBounds[i*2+j]=j;
+      }
+  this->PositiveLaterality=0.0;
+  this->NegativeLaterality=0.0;
+}
+
+vtkpxMergeFmriConventional::~vtkpxMergeFmriConventional()
+{
+
+  if (this->fmriInput!=NULL)
+    {
+      this->fmriInput->UnRegister(this);
+      this->fmriInput=NULL;
+    }
+
+  if (this->Transform1!=NULL)
+    {
+      this->Transform1->UnRegister(this);
+      this->Transform1=NULL;
+    }
+
+  if (this->Transform2!=NULL)
+    {
+      this->Transform2->UnRegister(this);
+      this->Transform2=NULL;
+    }
+
+ 
+}
+
+void vtkpxMergeFmriConventional::ThresholdPositiveOnly()
+{
+  this->SetThresholdMode(1);
+}
+
+void vtkpxMergeFmriConventional::ThresholdNegativeOnly()
+{
+  this->SetThresholdMode(2);
+}
+
+void vtkpxMergeFmriConventional::ThresholdBoth()
+{
+  this->SetThresholdMode(3);
+}
+
+void vtkpxMergeFmriConventional::ThresholdNone()
+{
+  this->SetThresholdMode(0);
+}
+
+//------------------------------------------------------------------------------
+void vtkpxMergeFmriConventional::SetTransformation1(vtkAbstractTransform* tr)
+{
+  if (this->Transform1!=NULL)
+    this->Transform1->UnRegister(this);
+
+  this->Transform1=tr;
+
+  if (this->Transform1!=NULL)
+    this->Transform1->Register(this);
+
+}
+
+vtkAbstractTransform* vtkpxMergeFmriConventional::GetTransformation1()
+{
+  return this->Transform1;
+}
+
+void vtkpxMergeFmriConventional::SetTransformation2(vtkAbstractTransform* tr)
+{
+  if (this->Transform2!=NULL)
+    this->Transform2->UnRegister(this);
+
+  this->Transform2=tr;
+
+  if (this->Transform2!=NULL)
+    this->Transform2->Register(this);
+
+}
+
+vtkAbstractTransform* vtkpxMergeFmriConventional::GetTransformation2()
+{
+  return this->Transform2;
+}
+
+//------------------------------------------------------------------------------
+
+void vtkpxMergeFmriConventional::SetConventional(vtkImageData* img)
+{
+  this->SetInput(img);
+}
+
+void vtkpxMergeFmriConventional::SetFmriInput(vtkImageData* fmri)
+{
+  this->SetfmriInput(fmri);
+
+  if (this->fmriInput==NULL)
+    return;
+
+
+  if (this->MinimumThreshold==0 && this->MaximumThreshold==1)
+    {
+      double range[2];
+      this->fmriInput->GetPointData()->GetScalars()->GetRange(range);
+
+      if (range[0]<0.0 && range[1]>0.0)
+	{
+	  this->MinimumThreshold=range[1]*0.5;
+	  this->MaximumThreshold=range[1];
+	}
+      else
+	{
+	  if (range[1]>0.0)
+	    {
+	      this->MinimumThreshold=(range[0]);
+	      this->MaximumThreshold=(range[1]);
+	    }
+	  else
+	    {
+	      this->MinimumThreshold=fabs(range[1]);
+	      this->MaximumThreshold=fabs(range[0]);
+	    }
+	}
+    }
+
+}
+//------------------------------------------------------------------------------
+vtkImageData* vtkpxMergeFmriConventional::DealWithTransformStuff()
+{
+  vtkGeneralTransform* combotransform=NULL;
+
+  if (this->Transform1!=NULL || this->Transform2 !=NULL )
+    {
+      combotransform=vtkGeneralTransform::New();
+      combotransform->PostMultiply();
+      if (this->Transform1!=NULL)
+	combotransform->Concatenate(this->Transform1);
+      if (this->Transform2!=NULL)
+	combotransform->Concatenate(this->Transform2);
+    }
+
+  vtkImageData* fmri=EquiResample(fmriInput,this->GetInput(),combotransform,0,0);//this->FlipFmri);
+
+  if (combotransform!=NULL)
+    combotransform->Delete();
+
+  return fmri;
+}
+//------------------------------------------------------------------------------
+void vtkpxMergeFmriConventional::ComputeStepBounds(vtkImageData* image,double range[2],int mode)
+{
+  vtkDataArray* scal=image->GetPointData()->GetScalars();
+  scal->GetRange(range);
+  
+  if (mode==0)
+    return;
+
+  int n=scal->GetNumberOfTuples(),inc=1;
+  if (n>1033)
+    inc=int(n/1033);
+
+  float mean=0.0,mean2=0.0;
+  int num=0;
+  for (int i=0;i<n;i+=inc)
+    {
+      float v=scal->GetComponent(i,0);
+      if (v!=0.0)
+	{
+	  mean+=v;
+	  mean2+=v*v;
+	  ++num;
+	}
+    }
+
+  if (num==0)
+    return;
+
+  mean/=float(num);
+  mean2/=float(num);
+  float std=sqrt(mean2-mean*mean);
+
+  range[0]=Frange(mean-3.0*std,range[0],range[1]-1.0);
+  range[1]=Frange(mean+3.0*std,range[0]+1.0,range[1]);
+}
+//------------------------------------------------------------------------------ 
+float vtkpxMergeFmriConventional::ComputeAnatomicalVoxelValue(float vox,double range[2],float min,float max)
+{
+  
+  if (vox<=range[0])
+    return min;
+  if (vox>=range[1])
+    return max;
+
+  return min+(max-min)/(range[1]-range[0])*(vox-range[0]);
+
+}
+//------------------------------------------------------------------------------
+vtkImageData* vtkpxMergeFmriConventional::EquiResample(vtkImageData* source,
+							      vtkImageData* target,
+							      vtkAbstractTransform* xform,
+							      int median,int flipx)
+{
+
+  if (source==NULL || target==NULL)
+    {
+      fprintf(stderr,"Source or Target=NULL\n");
+      return NULL;
+    }
+
+  vtkbisImageReslice* reslice=vtkbisImageReslice::New(); reslice->OptimizationOff();
+  reslice->SetInput(source);
+  reslice->SetInterpolationModeToLinear();
+  reslice->SetBackgroundLevel(1.0) ;
+  reslice->SetOutputSpacing(target->GetSpacing());
+  reslice->SetOutputOrigin(target->GetOrigin());
+  reslice->SetOutputExtent(target->GetExtent());
+  if (xform!=NULL)
+    {
+      reslice->SetResliceTransform(xform);
+    }
+  else
+    {
+      vtkIdentityTransform* tmp=vtkIdentityTransform::New();
+      reslice->SetResliceTransform(tmp);
+      tmp->Delete();
+    }
+  reslice->Update();
+
+  vtkImageData* tmp=vtkImageData::New();
+  if (flipx)
+    {
+      vtkImageFlip* imageFlip=vtkImageFlip::New();
+      imageFlip->SetInput(reslice->GetOutput());
+      imageFlip->SetFilteredAxis(0);
+      imageFlip->SetPreserveImageExtent(1);
+      imageFlip->Update();
+      tmp->ShallowCopy(imageFlip->GetOutput());
+      imageFlip->Delete();
+    }
+  else
+    tmp->ShallowCopy(reslice->GetOutput());
+  reslice->Delete();
+
+  vtkImageData* output2=vtkImageData::New();
+  if (median<1)
+    {
+      vtkImageMedian3D* imageMedian=vtkImageMedian3D::New();
+      imageMedian->SetInput(tmp);
+      imageMedian->Update();
+      output2->ShallowCopy(imageMedian->GetOutput());
+      imageMedian->Delete();
+    }
+  else
+    output2->ShallowCopy(tmp);
+
+  tmp->Delete();
+
+  return output2;
+}
+//------------------------------------------------------------------------------
+vtkTransform* vtkpxMergeFmriConventional::GetBoundsTransform(vtkImageData* conventional,
+							     vtkImageData* functional,
+							     int SourceBounds[6],int TargetBounds[6])
+							
+{
+  vtkTransform* Transform=vtkTransform::New();
+  Transform->Identity();
+
+  if (conventional==NULL || functional == NULL)
+    return Transform;
+  
+  double spf[3],spc[3];
+
+  // Functional To Conventional 
+  functional->GetSpacing(spf);
+  conventional->GetSpacing(spc);
+
+  double t1[3],t2[3],sc[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      t1[ia]=float(SourceBounds[ia*2])*spf[ia];
+      t2[ia]=-float(TargetBounds[ia*2])*spc[ia];
+      sc[ia]=1.0;
+      float bottom=SourceBounds[ia*2+1]*spf[ia];
+      float top=TargetBounds[ia*2+1]*spc[ia];
+      if (bottom!=0.0)
+	sc[ia]=top/bottom;
+    }
+      
+  
+  Transform->PostMultiply();
+  Transform->Translate(t2);
+  Transform->Scale(sc);
+  Transform->Translate(t1);
+
+  /*{
+    int i,j; 
+    for(i = 0; i < 4; i++) 
+      {
+	for(j = 0; j < 4; j++) 
+	  {
+	    cerr << Transform->GetMatrix()->GetElement(i,j) << ((j != 3) ? " " : "\n");
+	  }
+      }
+      }*/
+
+  return Transform;
+}
+//------------------------------------------------------------------------------
+
+vtkTransform* vtkpxMergeFmriConventional::GetBoundsTransform()
+{
+  return this->GetBoundsTransform(this->GetInput(),this->fmriInput,
+				  this->SourceBounds,this->TargetBounds);
+}
+
+//---------------------------------------------------------------------------------------------
+//  
+//                        Simple Execute 
+//
+
+//---------------------------------------------------------------------------------------------
+void vtkpxMergeFmriConventional::SimpleExecute(vtkImageData* conventional,vtkImageData* output)
+{
+  if (this->fmriInput==NULL)
+      {
+	vtkErrorMacro(<<"No fmri images!");
+	return;
+      }
+
+  int dim[3];     conventional->GetDimensions(dim);
+  int dim2[3];    this->fmriInput->GetDimensions(dim2);
+
+  vtkImageData* fmri;
+  int doresample=0;
+
+  int diff=0;
+  for (int ia=0;ia<=2;ia++)
+    diff+=abs(dim[ia]-dim2[ia]);
+  if (diff>0)
+    {
+      doresample=1;
+      fmri=DealWithTransformStuff();
+    }
+  else
+    {
+      fmri=this->fmriInput;
+      doresample=0;
+    }
+
+
+  // -------------------------
+  // Next Allocate Output Data
+  // -------------------------
+  int numcomponents=1;
+  int usecomponent=0;
+  if (this->SingleFrameMode==0)
+    numcomponents=fmri->GetNumberOfScalarComponents();
+  else
+    usecomponent=Irange(this->CurrentFrame,0,fmri->GetNumberOfScalarComponents()-1);
+  
+  output->SetSpacing(conventional->GetSpacing());
+  output->SetOrigin(conventional->GetOrigin());
+  output->SetScalarType(VTK_UNSIGNED_CHAR);
+  output->SetNumberOfScalarComponents(numcomponents);
+  output->SetDimensions(conventional->GetDimensions());
+  output->SetWholeExtent(conventional->GetWholeExtent());
+  output->AllocateScalars();
+  vtkDataArray* outScalars=output->GetPointData()->GetScalars();
+
+  this->UpdateProgress(0.05);
+
+
+  // -------------------------
+  // Set Color Mapping Parameters
+  // -------------------------
+  float fmri_numcol=3.0, fnum_col=55.0;
+  int   mid_fmri=60,min_fmri=56,max_fmri=63;
+  if (this->OutputMode==1)
+    {
+      fnum_col=191.0;
+      fmri_numcol=31.0;
+      min_fmri=192;
+      max_fmri=255;
+      mid_fmri=224;
+    }
+  else if (this->OutputMode==2)
+    {
+      fnum_col=237.0;
+      fmri_numcol=8.0;
+      min_fmri=238;
+      max_fmri=255;
+      mid_fmri=247;
+    }
+
+  // -------------------------------------
+  // Normalize Anatomical Stuff
+  // -------------------------------------
+  double crange[2];  this->ComputeStepBounds(conventional,crange,this->NormalizeAnatomical);
+
+  // Scale factor for conv  0..55
+  if (crange[0]==crange[1])
+    crange[1]+=1.0;
+  float convscale=fnum_col/(crange[1]-crange[0]);
+
+
+  // ------------------------------------------
+  // Do fMRI Stuff  -- once component at a time
+  // ------------------------------------------
+  this->PositiveLaterality=0.0;
+  this->NegativeLaterality=0.0;
+  double poscount[2],negcount[2];
+  for (int ia=0;ia<=1;ia++)
+    {
+      poscount[ia]=0.0; negcount[ia]=0.0;
+    }
+     
+
+  for (int outputcomponent=0;outputcomponent<numcomponents;outputcomponent++)
+    {
+
+      int inputcomponent=outputcomponent;
+      if (this->SingleFrameMode)
+	inputcomponent=usecomponent;
+
+      double fmrirange[2];
+      fmri->GetPointData()->GetScalars()->GetRange(fmrirange,inputcomponent);
+
+      // Scale fmri 
+      if (this->MaximumThreshold==this->MinimumThreshold)
+	this->MaximumThreshold+=1.0;
+      float fmriscale=fmri_numcol/(this->MaximumThreshold-this->MinimumThreshold);
+      
+      outScalars->FillComponent(outputcomponent,0.0);
+
+      vtkDebugMacro(<< "Current Component = " << inputcomponent << " ---> " << outputcomponent << "\n");
+      vtkDebugMacro(<< "Ranges: conv " << crange[0] <<","<< crange[1] <<",  fmri:"<< fmrirange[0]<<","<<fmrirange[1]);
+      vtkDebugMacro(<< "Thresholds : min : " << this->MinimumThreshold << " max: " <<  this->MaximumThreshold  << " Intensity : " << this->IntensityThreshold );
+      vtkDebugMacro(<< "Convscale = " << convscale << ", ThresholdMode " << this->ThresholdMode << " FlipFmri=" << this->FlipFmri << "\n");
+      
+      // Lopp Through all voxels 
+      // -----------------------
+      
+      int numpixels=dim[0]*dim[1];
+      
+
+      int midpoint=dim[0]/2;
+
+      for (int sl=0;sl<dim[2];sl++)
+	{
+	  int offset=sl*numpixels;
+	  for (int iy=0;iy<dim[1];iy++)
+	    {
+	      int offset2=offset+iy*dim[0];
+	      for (int ix=0;ix<dim[0];ix++)
+		{
+		  float vc=conventional->GetPointData()->GetScalars()->GetComponent(ix+offset2,0);
+		  int c=(int)this->ComputeAnatomicalVoxelValue(vc,crange,0,fnum_col);
+		  
+		  float fm;
+		  if (!this->FlipFmri)
+		    fm=fmri->GetPointData()->GetScalars()->GetComponent(ix+offset2,inputcomponent);
+		  else
+		    fm=fmri->GetScalarComponentAsDouble(dim[0]-ix-1,iy,sl,inputcomponent);
+	      
+		  if (c>=this->IntensityThreshold)
+		    {
+		      if (fm>0.0 && 
+			  ( this->ThresholdMode==1 || this->ThresholdMode==3) && 
+			  fm>=this->MinimumThreshold )
+			{
+			  float fm2=(fm-this->MinimumThreshold)*fmriscale;
+			  c=Irange(int(fm2+mid_fmri+0.5),mid_fmri,max_fmri);
+			  if (ix<midpoint)
+			    poscount[0]++;
+			  else
+			    poscount[1]++;
+			}
+		      else if (fm<0.0 && 
+			       ( this->ThresholdMode==2 || this->ThresholdMode==3) && 
+			       fabs(fm)>=this->MinimumThreshold )  
+			{
+			  float fm2=(fabs(fm)-this->MinimumThreshold)*fmriscale;
+			  c=Irange(int(0.5+mid_fmri-fm2),min_fmri,mid_fmri-1);
+			  if (ix<midpoint)
+			    negcount[0]++;
+			  else
+			    negcount[1]++;
+			}
+		      
+		    }
+		  outScalars->SetComponent(ix+offset2,outputcomponent,float(c));
+		  //numtotal++;
+		}
+	    }
+	  
+	  float pog=float(sl)/float(dim[2]*numcomponents)+float(outputcomponent+1)/float(numcomponents);
+	  this->UpdateProgress(pog);	
+	}
+    }
+  
+  if ((poscount[0]+poscount[1])>0.0)
+    {
+      this->PositiveLaterality=(poscount[1]-poscount[0])/(poscount[0]+poscount[1]);
+    }
+  
+  if ((negcount[0]+negcount[1])>0.0)
+    {
+      this->NegativeLaterality=(negcount[1]-negcount[0])/(negcount[0]+negcount[1]);
+    }
+    
+
+
+
+  this->UpdateProgress(1.0);
+
+  if (doresample==1)
+    {
+      //      fprintf(stderr,"Deleting fmri\n");
+      fmri->Delete();
+    }
+
+}
+//------------------------------------------------------------------------------
+/*
+
+8 components
+
+0  index
+2  number of voxels
+3  sum                --> Mean
+4  sum**2             --> SIGMA
+5  number of voxels > 0
+6  vol
+7  vol in mm^3
+8  max value
+9  max location x
+10 max location y
+11 max location z
+12 mean location x
+13 mean location x
+14 mean location x
+
+
+
+
+*/
+// -----------------------------------------------------------------------------------
+
+
+
+int vtkpxMergeFmriConventional::ComputeROIStatistics(vtkImageData* input,vtkImageData* roi,
+						     vtkAbstractTransform* tr,vtkFloatArray *inout_stats)
+{
+  if (input==NULL || roi==NULL || tr==NULL || inout_stats==NULL)
+    {
+      fprintf(stderr,"Compute ROI Inout_Stats bad inputs\n");
+      return 0;
+    }
+	      
+  int nt1=input->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nt2=roi->GetPointData()->GetScalars()->GetNumberOfTuples();
+
+  vtkImageData* tmp=vtkImageData::New();
+
+  if (nt1!=nt2)
+    {
+      vtkbisImageReslice* reslice=vtkbisImageReslice::New(); reslice->OptimizationOff();
+      reslice->SetInterpolationMode(0);
+      reslice->SetBackgroundLevel(0);
+      reslice->SetInput(roi);
+      reslice->SetInformationInput(input);
+      reslice->SetResliceTransform(tr);
+      reslice->Update();
+      tmp->ShallowCopy(reslice->GetOutput());
+      reslice->Delete();
+    }
+  else
+    {
+      //      fprintf(stderr,"Identical Dimensions NOT Reslicing\n");
+      tmp->ShallowCopy(roi);
+    }
+
+
+  double sp[3];  input->GetSpacing(sp);
+  double voxel_size=sp[0]*sp[1]*sp[2];
+
+  vtkDataArray* data_in=input->GetPointData()->GetScalars();
+  vtkDataArray* roi_array=tmp->GetPointData()->GetScalars();
+  
+  int nvox=data_in->GetNumberOfTuples();
+  int nc=data_in->GetNumberOfComponents();
+
+  //  fprintf(stderr,"Num vox =%d numframes=%d\n",nvox,nc);
+
+  double range[2];
+  roi_array->GetRange(range);
+  int r0=int(range[0]);
+  int r1=int(range[1]);
+  int numlevels=r1-r0+1;
+
+  //  fprintf(stderr,"Range of roi=%.1f:%.1f or %d:%d numlevels=%d\n",range[0],range[1],r0,r1,numlevels);
+
+  
+  int isinteger=0;
+  /*if (input->GetScalarType()==VTK_SHORT ||
+      input->GetScalarType()==VTK_CHAR ||
+      input->GetScalarType()==VTK_UNSIGNED_SHORT ||
+      input->GetScalarType()==VTK_UNSIGNED_CHAR ||
+      input->GetScalarType()==VTK_INT ||
+      input->GetScalarType()==VTK_UNSIGNED_INT  ||
+      input->GetScalarType()==VTK_LONG ||
+      input->GetScalarType()==VTK_UNSIGNED_LONG )
+    {
+      isinteger=1;
+      fprintf(stderr,"Input Data is Integer\n");
+      }*/
+  vtkDataArray* stats=NULL;
+  if (isinteger==0)
+    stats=vtkDoubleArray::New();
+  else
+    stats=vtkLongArray::New();
+  
+  stats->SetNumberOfComponents(15);
+  stats->SetNumberOfTuples(nc*numlevels);
+  inout_stats->SetNumberOfComponents(15);
+  inout_stats->SetNumberOfTuples(nc*numlevels);
+
+  for (int j=0;j<15;j++)
+    stats->FillComponent(j,0.0);
+
+  for (int k=0;k<nc;k++)
+    for (int j=0;j<numlevels;j++)
+      {
+	stats->SetComponent(k*numlevels+j,0,k);
+	stats->SetComponent(k*numlevels+j,1,r0+j);
+      }
+
+
+  
+  int voxel=0;
+  int dim[3]; input->GetDimensions(dim);
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  int index=(int)roi_array->GetComponent(voxel,0);
+	  for (int frame=0;frame<nc;frame++)
+	    {
+	      float v=data_in->GetComponent(voxel,frame);
+	      
+	      int outindex=frame*numlevels+index;
+	      stats->SetComponent(outindex,2,stats->GetComponent(outindex,2)+1);
+	      stats->SetComponent(outindex,3,stats->GetComponent(outindex,3)+v);
+	      stats->SetComponent(outindex,4,stats->GetComponent(outindex,4)+v*v);
+	      if (v>0.0)
+		stats->SetComponent(outindex,5,stats->GetComponent(outindex,5)+1);
+
+	      if (fabs(v)> fabs(stats->GetComponent(outindex,8)))
+		{
+		  stats->SetComponent(outindex,8,v);
+		  stats->SetComponent(outindex,9,double(i));
+		  stats->SetComponent(outindex,10,double(j));
+		  stats->SetComponent(outindex,11,double(k));
+		}
+
+	      stats->SetComponent(outindex,12,stats->GetComponent(outindex,12)+double(i));
+	      stats->SetComponent(outindex,13,stats->GetComponent(outindex,13)+double(j));
+	      stats->SetComponent(outindex,14,stats->GetComponent(outindex,14)+double(k));
+	    }
+	  ++voxel;
+	}
+
+
+  for (int ka=0;ka<nc;ka++)
+    for (int ja=0;ja<numlevels;ja++)
+      {
+	int outindex=ka*numlevels+ja;
+	double nt=stats->GetComponent(outindex,2);
+	double vol=nt*voxel_size;
+	double mean=0.0,sigma=1.0, centroid[3];
+	if (nt>=1.0)
+	  {
+	    double correction=sqrt(nt)/sqrt(nt-1.0);
+	    double factor=1.0/(nt);
+	    
+	    double sum=stats->GetComponent(outindex,3);
+	    double sum2=stats->GetComponent(outindex,4);
+	    if (isinteger)
+	      {
+		sum=double(int(sum+0.5));
+		sum2=double(int(sum2+0.5));
+	      }
+
+	    mean = sum*factor;
+	    double diff=sum2*factor-mean*mean;
+	    if (fabs(diff)<1.0e-7)
+	      sigma=0.0;
+	    else if (diff<0.0)
+	      sigma=-1.0;
+	    else
+	      sigma  = sqrt(sum2*factor-mean*mean)*correction;
+
+	    //	    fprintf(stderr,"ka=%d ja=%d,diff=%f sigma=%f\n",ka,ja,diff,sigma);
+
+	    centroid[0]=factor*stats->GetComponent(outindex,12);
+	    centroid[1]=factor*stats->GetComponent(outindex,13);
+	    centroid[2]=factor*stats->GetComponent(outindex,14);
+
+	  }
+	stats->SetComponent(outindex,3,mean);
+	stats->SetComponent(outindex,4,sigma);
+	stats->SetComponent(outindex,12,centroid[0]);
+	stats->SetComponent(outindex,13,centroid[1]);
+	stats->SetComponent(outindex,14,centroid[2]);
+	stats->SetComponent(outindex,6,vol);
+	stats->SetComponent(outindex,7,stats->GetComponent(outindex,5)*voxel_size);
+      }
+
+  for (int c=0;c<15;c++)
+    inout_stats->CopyComponent(c,stats,c);
+  stats->Delete();
+  tmp->Delete();
+  return numlevels*nc;
+}
+//------------------------------------------------------------------------------
+int vtkpxMergeFmriConventional::ModifyMask(vtkImageData* input,int x,int y,int z)
+{
+  
+  int dim[3];  input->GetDimensions(dim); 
+  vtkDataArray* data_in=input->GetPointData()->GetScalars();
+
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  int index=i+j*dim[0]+k*dim[1]*dim[0];
+	  float v=data_in->GetComponent(index,0);
+	  if (v>0)
+	    {
+	      if (i<x && j < y )
+		{
+		  if (k<65)
+		    data_in->SetComponent(index,0,2);
+		  else
+		    data_in->SetComponent(index,0,3);
+		}
+	      else
+		data_in->SetComponent(index,0,1);
+	    }
+
+	  }
+	return 1;
+}
+//------------------------------------------------------------------------------
+/*int vtkpxMergeFmriConventional::ComputeROIStatisticsComplex(vtkImageData* input,vtkImageData* roi,vtkFloatArray *stats)
+{
+  return vtkpxMergeFmriConventional::ComputeROIStatisticsComplex(input,roi,NULL,stats);
+  }*/
+//------------------------------------------------------------------------------
+ /*int vtkpxMergeFmriConventional::ComputeROIStatisticsComplex(vtkImageData* input,vtkImageData* roi,
+							    vtkFloatArray* ranges,vtkFloatArray *stats)
+{
+  if (input==NULL || roi==NULL ||  stats==NULL)
+    {
+      fprintf(stderr,"Compute ROI Stats bad inputs\n");
+      return 0;
+    }
+
+  int numranges=0;
+  if (ranges!=NULL)
+    {
+      if (ranges->GetNumberOfComponents()==2)
+	numranges=ranges->GetNumberOfTuples();
+    }
+
+	      
+  double sp[3];  input->GetSpacing(sp);
+  double voxel_size=sp[0]*sp[1]*sp[2];
+
+  vtkDataArray* data_in=input->GetPointData()->GetScalars();
+  vtkDataArray* roi_array=roi->GetPointData()->GetScalars();
+  
+  int nvox =data_in->GetNumberOfTuples();
+  int nc=data_in->GetNumberOfComponents();
+  int nmask=roi_array->GetNumberOfTuples();
+  
+  if (nvox!=nmask)
+    {
+      fprintf(stderr,"Cannont Compute ROI Stats, different size images %d vs %d\n",nvox,nmask);
+      return 0;
+    }
+
+
+  fprintf(stderr,"Computing ROI Statistics Num vox =%d numframes=%d number of ranges = %d\n",nvox,nc,numranges);
+
+  double range[2];
+  roi_array->GetRange(range);
+  int r0=int(range[0]);
+  int r1=int(range[1]);
+  int numlevels=r1-r0+1;
+
+  fprintf(stderr,"Range of roi=%.1f:%.1f or %d:%d numlevels=%d\n",range[0],range[1],r0,r1,numlevels);
+
+  stats->SetNumberOfComponents(2+3*(numranges+1));
+  int numcomp=stats->GetNumberOfComponents();
+  stats->SetNumberOfTuples(nc*numlevels);
+  for (int j=0;j<numcomp;j++)
+    stats->FillComponent(j,0);
+  
+  for (int k=0;k<nc;k++)
+    for (int j=0;j<numlevels;j++)
+      {
+	stats->SetComponent(k*numlevels+j,0,k);
+	stats->SetComponent(k*numlevels+j,1,r0+j);
+      }
+  
+  float* minv=new float[numranges+1];
+  float* maxv=new float[numranges+1];
+  if (numranges>0)
+    {
+      for (int i=0;i<numranges;i++)
+	{
+	  minv[i]=ranges->GetComponent(i,0);
+	  maxv[i]=ranges->GetComponent(i,1);
+	}
+    }
+  
+  for (int voxel=0;voxel<nvox;voxel++)
+    {
+      int index=(int)roi_array->GetComponent(voxel,0);
+      for (int frame=0;frame<nc;frame++)
+	{
+	  float v=data_in->GetComponent(voxel,frame);
+	  int outindex=frame*numlevels+index;
+	  stats->SetComponent(outindex,2,stats->GetComponent(outindex,2)+1);
+	  stats->SetComponent(outindex,3,stats->GetComponent(outindex,3)+v);
+	  stats->SetComponent(outindex,4,stats->GetComponent(outindex,4)+v*v);
+	  int offset=5;
+	  for (int j=0;j<numranges;j++)
+	    {
+	      if (v>=minv[j] && v< maxv[j])
+		{
+		  stats->SetComponent(outindex,offset, stats->GetComponent(outindex, offset)+1);
+		  stats->SetComponent(outindex,offset+1,stats->GetComponent(outindex,offset+1)+v);
+		  stats->SetComponent(outindex,offset+2,stats->GetComponent(outindex,offset+2)+v*v);
+		}
+	      offset+=3;
+	    }
+	}
+    }
+
+  for (int ka=0;ka<nc;ka++)
+    for (int ja=0;ja<numlevels;ja++)
+      {
+	int outindex=ka*numlevels+ja;
+
+	int offset=2;
+	for (int ia=0;ia<=numranges;ia++)
+	  {
+	    double nt=stats->GetComponent(outindex,offset);
+	    double mean=0.0,sigma=1.0;
+	    if (nt>0)
+	      {
+		double correction=sqrt(nt)/sqrt(nt-1.0);
+		double factor=1.0/(nt);
+		
+		double sum=stats->GetComponent(outindex,offset+1);
+		double sum2=stats->GetComponent(outindex,offset+2);
+		
+		mean = sum*factor;
+		double diff=sum2*factor-mean*mean;
+		if (fabs(diff)<1.0e-7)
+		  sigma=0.0;
+		else if (diff<0.0)
+		  sigma=-1.0;
+		else
+		  sigma  = sqrt(sum2*factor-mean*mean)*correction;
+	      }
+	    stats->SetComponent(outindex,offset+1,mean);
+	    stats->SetComponent(outindex,offset+2,sigma);
+	    offset+=3;
+	  }
+      }
+
+  delete [] minv;
+  delete [] maxv;
+  return numlevels*nc;
+  }*/
+//------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxMergeFmriConventional.h b/bioimagesuite30_src/Imaging/vtkpxMergeFmriConventional.h
new file mode 100644
index 0000000..75c88f4
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxMergeFmriConventional.h
@@ -0,0 +1,237 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxMergeFmriConventional.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 19:00:04 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+// .NAME vtkpxMergeFmriConventional - merges and creates overlays between t-maps and anatomic images
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// .SECTION See Also
+//  vtkpxProcessFmri
+
+
+#ifndef __vtkpxMergeFmriConventional_h
+#define __vtkpxMergeFmriConventional_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+
+class vtkTransform;
+class vtkAbstractTransform;
+
+class vtkpxMergeFmriConventional : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxMergeFmriConventional *New();
+  vtkTypeMacro(vtkpxMergeFmriConventional,vtkpxSimpleImageToImageFilter);
+
+
+  // Description:
+  // SetInputs coventional and fmri t-maps 
+  virtual void SetConventional(vtkImageData* img);
+  virtual void SetFmriInput(vtkImageData* fmri);
+
+  virtual vtkImageData* GetFunctionalInput() { return this->fmriInput; }
+
+
+  // Description:
+  // Set Thresholds for overlays 
+  vtkGetMacro(MinimumThreshold,float);
+  vtkSetMacro(MinimumThreshold,float);
+
+  vtkGetMacro(MaximumThreshold,float);
+  vtkSetMacro(MaximumThreshold,float);
+
+  vtkGetMacro(IntensityThreshold,int);
+  vtkSetMacro(IntensityThreshold,int);
+
+
+  // Description:
+  // Select one frame or multiple frames
+  vtkSetClampMacro(SingleFrameMode,int,0,1);
+  vtkGetMacro(SingleFrameMode,int);
+  vtkBooleanMacro(SingleFrameMode,int);
+
+  // Description:
+  // Select Frame 
+  vtkSetMacro(CurrentFrame,int);
+  vtkGetMacro(CurrentFrame,int);
+
+  // Description:
+  // Mode 0 or 1 , 0 0:55 for anatomy and 56:63 for function
+  // 1 0:191 for anatomy and 192:255 for function 
+  // 2 0:225 for anatomy and 226:255 for function
+  vtkGetMacro(OutputMode,int);
+  vtkSetClampMacro(OutputMode,int,0,2);
+
+  // Description:
+  // Set Threhold Mode 
+  vtkSetMacro(ThresholdMode,int);
+  vtkGetMacro(ThresholdMode,int);
+  virtual void ThresholdPositiveOnly();
+  virtual void ThresholdNegativeOnly();
+  virtual void ThresholdBoth();
+  virtual void ThresholdNone();
+
+  // Description:
+  // L-R Flip of Fmri
+  vtkGetMacro(FlipFmri,int);
+  vtkSetMacro(FlipFmri,int);
+
+  // Description:
+  // Do Median Filter of t-maps before overlay 
+  vtkGetMacro(MedianFiltering,int);
+  vtkSetMacro(MedianFiltering,int);
+
+  // Description:
+  // Normalize Anatomical Intensity
+  vtkSetClampMacro(NormalizeAnatomical,int,0,1);
+  vtkGetMacro(NormalizeAnatomical,int);
+
+
+  // Description:
+  // Set Transformation  for transformation 1
+  virtual void SetTransformation1(vtkAbstractTransform* trans);
+  virtual vtkAbstractTransform* GetTransformation1();
+
+  // Description:
+  // Set Transformation  for transformation 2
+  virtual void SetTransformation2(vtkAbstractTransform* trans);
+  virtual vtkAbstractTransform* GetTransformation2();
+
+  
+  // Description:
+  // Create Bounds Transform from Bounds (Todd's current practice similarity!)
+  vtkSetVectorMacro(SourceBounds,int,6);
+  vtkGetVectorMacro(SourceBounds,int,6);
+  vtkSetVectorMacro(TargetBounds,int,6);
+  vtkGetVectorMacro(TargetBounds,int,6);
+  virtual vtkTransform* GetBoundsTransform();
+
+
+  // Description:
+  // Get Laterality Indices
+  vtkGetMacro(PositiveLaterality,double);
+  vtkGetMacro(NegativeLaterality,double);
+
+
+  // Description:
+  // Equi-transform a `target'-image to have same dimensions as source using transform xform
+  static vtkImageData* EquiResample(vtkImageData* source,vtkImageData* target,
+					   vtkAbstractTransform* xform,
+					   int median=0,int flipx=0);
+
+  // Description:
+  // Compute ROI Stats
+  static int ComputeROIStatistics(vtkImageData* input,vtkImageData* target,vtkAbstractTransform* tr,vtkFloatArray* stats);
+  //  static int ComputeROIStatisticsComplex(vtkImageData* input,vtkImageData* roidefinigion,vtkFloatArray* stats);
+  //  static int ComputeROIStatisticsComplex(vtkImageData* input,vtkImageData* roidefinigion,vtkFloatArray* ranges,vtkFloatArray* stats);
+
+
+  static int ModifyMask(vtkImageData* input,int x,int y,int z);
+  
+protected:
+
+  vtkpxMergeFmriConventional();
+  virtual ~vtkpxMergeFmriConventional();
+  vtkpxMergeFmriConventional(const vtkpxMergeFmriConventional&) {};
+  void operator=(const vtkpxMergeFmriConventional&) {};
+
+  virtual void SimpleExecute(vtkImageData*,vtkImageData*);
+
+  vtkImageData* DealWithTransformStuff();
+
+  vtkImageData* fmriInput;
+  int NormalizeAnatomical;
+  int ThresholdMode;
+  float MinimumThreshold;
+  float MaximumThreshold;
+  int IntensityThreshold;
+  int SourceBounds[6];
+  int TargetBounds[6];
+  int MedianFiltering;
+  int FlipFmri;
+  int OutputMode;
+  int  SingleFrameMode;
+  int  CurrentFrame;
+  
+  double PositiveLaterality;
+  double NegativeLaterality;
+
+  vtkAbstractTransform* Transform1;
+  vtkAbstractTransform* Transform2;
+  
+  // Description:
+  // This is the function actually used to generate the Bounds Transform!
+  static vtkTransform*  GetBoundsTransform(vtkImageData* conventional,
+					   vtkImageData* fmriInput,
+					   int SourceBounds[6],int TargetBounds[6]);
+
+  // Description:
+  // Find Step Function for anatomical and normalize intensity
+  void ComputeStepBounds(vtkImageData* image,double range[2],int mode);
+  float ComputeAnatomicalVoxelValue(float vox,double range[2],float min,float max);
+
+
+  // Description:
+  // Set fmriInput Image
+  vtkSetObjectMacro(fmriInput,vtkImageData);
+
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxNormalizedSmoothImage.cpp b/bioimagesuite30_src/Imaging/vtkpxNormalizedSmoothImage.cpp
new file mode 100644
index 0000000..76a355e
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxNormalizedSmoothImage.cpp
@@ -0,0 +1,160 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxNormalizedSmoothImage.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:09:25 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxNormalizedSmoothImage.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkDataArray.h"
+//------------------------------------------------------------------------------
+vtkpxNormalizedSmoothImage* vtkpxNormalizedSmoothImage::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxNormalizedSmoothImage");
+  if(ret)
+    {
+      return (vtkpxNormalizedSmoothImage*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxNormalizedSmoothImage;
+}
+
+// Construct object with no children.
+vtkpxNormalizedSmoothImage::vtkpxNormalizedSmoothImage()
+{
+  this->Sigma=3.0;
+  this->NormalizerInput=NULL;
+  this->NormalizeScale=1000.0;
+
+}
+// ----------------------------------------------------------------------------
+vtkpxNormalizedSmoothImage::~vtkpxNormalizedSmoothImage()
+{
+  this->SetNormalizerInput(NULL);
+}
+// --------------------------------------------------------------------------------------------
+void vtkpxNormalizedSmoothImage::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+
+  //  int nimpc=input->GetNumberOfScalarComponents();
+
+
+  this->UpdateProgress(0.01);
+
+  vtkImageGaussianSmooth* sm=vtkImageGaussianSmooth::New();
+  sm->SetInput(this->GetImageDataInput(0));
+  double sp[3],sigma[3]; input->GetSpacing(sp);
+  for (int i=0;i<=2;i++)
+    sigma[i]=this->Sigma/sp[i];
+  sm->SetStandardDeviations(sigma);
+  sm->Update();
+
+  this->UpdateProgress(0.7);
+
+  vtkDataArray* norm=sm->GetOutput()->GetPointData()->GetScalars();
+  int offset=1;
+
+  if (this->NormalizerInput!=NULL)
+    {
+      norm=this->NormalizerInput->GetPointData()->GetScalars();
+      offset=0;
+    }
+
+
+  fprintf(stderr,"Offset = %d\n",offset);
+  
+  vtkDataArray* inp=sm->GetOutput()->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  if (offset==1)
+    out->CopyComponent(0,inp,0);
+  
+  int nt1=inp->GetNumberOfTuples();
+  int nt2=norm->GetNumberOfTuples();
+  if (nt1!=nt2)
+    {
+      vtkErrorMacro(<<"Cannot Normalize Bad Input Dimensions");
+    }
+  else
+    {
+      int nt=out->GetNumberOfTuples();
+      int nc=out->GetNumberOfComponents();
+      
+      for (int i=0;i<nt;i++)
+	{
+	  float divisor=norm->GetComponent(i,0);
+	  for (int j=offset;j<nc;j++)
+	    {
+	      double v=inp->GetComponent(i,j);
+	      if (fabs(divisor)>0.001)
+		out->SetComponent(i,j,this->NormalizeScale*v/divisor);
+	      else
+		out->SetComponent(i,j,0.0);
+	    }
+
+
+	}
+    }
+
+  sm->Delete();
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxNormalizedSmoothImage.h b/bioimagesuite30_src/Imaging/vtkpxNormalizedSmoothImage.h
new file mode 100644
index 0000000..5e8b85c
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxNormalizedSmoothImage.h
@@ -0,0 +1,104 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxNormalizedSmoothImage.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:08:12 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#ifndef __vtkpxNormalizedSmoothImage_h
+#define __vtkpxNormalizedSmoothImage_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+
+class vtkpxNormalizedSmoothImage : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxNormalizedSmoothImage *New();
+  vtkTypeMacro(vtkpxNormalizedSmoothImage,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set Smoothing Sigma 
+  vtkGetMacro(Sigma,float);
+  vtkSetMacro(Sigma,float);
+
+  // Description:
+  // Bright Structure
+  vtkSetMacro(NormalizeScale,float);
+  vtkGetMacro(NormalizeScale,float);
+
+  // Description:
+  // Bright Structure
+  vtkSetObjectMacro(NormalizerInput,vtkImageData);
+  vtkGetObjectMacro(NormalizerInput,vtkImageData);
+
+  
+protected:
+
+  //BTX
+  vtkpxNormalizedSmoothImage();
+  virtual ~vtkpxNormalizedSmoothImage();
+  vtkpxNormalizedSmoothImage(const vtkpxNormalizedSmoothImage&) {};
+  void operator=(const vtkpxNormalizedSmoothImage&) {};
+  //ETX
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+  vtkImageData* NormalizerInput;
+  float         NormalizeScale;
+  float         Sigma;
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxPhaseCorrectCSIData.cpp b/bioimagesuite30_src/Imaging/vtkpxPhaseCorrectCSIData.cpp
new file mode 100644
index 0000000..99455de
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxPhaseCorrectCSIData.cpp
@@ -0,0 +1,1401 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxPhaseCorrectCSIData.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/03/23 19:20:08 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+
+// vtk includes
+#include "pxutil.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxPhaseCorrectCSIData.h"
+#include "vtkMath.h"
+#include "vtkpxUtil.h"
+#include "vtkpxOptimizer.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkImageAppendComponents.h"
+#include "vtkImageFFT.h"
+#include "vtkImageFourierCenter.h"
+#include "vtkpxAnalyzeImageWriter.h"
+#include "vtkImageGaussianSmooth.h"
+
+vtkpxPhaseCorrectCSIData* vtkpxPhaseCorrectCSIData::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxPhaseCorrectCSIData");
+  if(ret)
+    {
+      return (vtkpxPhaseCorrectCSIData*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxPhaseCorrectCSIData;
+}
+
+
+vtkpxPhaseCorrectCSIData::vtkpxPhaseCorrectCSIData()
+{
+  this->OptimizationMethod=4;
+  this->parameters=vtkDoubleArray::New();
+  this->parameters->SetNumberOfComponents(1);
+  this->parameters->SetNumberOfTuples(2);
+  this->parameters->FillComponent(0,0.0);
+  this->FunctionEvaluation=0;
+  this->DerivEvaluation=0;
+  this->Step=0.01;
+  this->Tolerance=0.001;
+  this->Iterations=25;
+  this->InputReal=NULL;
+  this->InputImag=NULL;
+  this->OutputReal=NULL;
+  this->OutputImag=NULL;
+  this->FirstOrderPhase=0.0;
+  this->OptimizeZeroOrder=0;
+  this->FirstOrderPhases=vtkDoubleArray::New();
+  this->ZeroOrderPhases=vtkDoubleArray::New();
+}
+
+vtkpxPhaseCorrectCSIData::~vtkpxPhaseCorrectCSIData()
+{
+  this->parameters->Delete();
+  this->FirstOrderPhases->Delete();
+  this->ZeroOrderPhases->Delete();
+  
+  if (this->InputReal!=NULL)
+    this->InputReal->Delete();
+
+  if (this->InputImag!=NULL)
+    this->InputImag->Delete();
+}
+
+//-------------------------------------------------------------------------
+void vtkpxPhaseCorrectCSIData::SetOutputStatus(const char* line,double v)
+{
+  fprintf(stderr,"**Opt=%s (%.8f)\n",line,v);
+}
+
+//-------------------------------------------------------------------------
+double vtkpxPhaseCorrectCSIData::CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output)
+{
+  return ((vtkpxPhaseCorrectCSIData*)self)->OptimizerGradient(position,output);
+}
+
+double vtkpxPhaseCorrectCSIData::CalculateFunction(vtkObject* self,vtkDoubleArray* position)
+{
+  return ((vtkpxPhaseCorrectCSIData*)self)->OptimizerValue(position);
+}
+
+void vtkpxPhaseCorrectCSIData::OptimizerFeedback(vtkObject* self,const char* line,double val)
+{
+  ((vtkpxPhaseCorrectCSIData*)self)->SetOutputStatus(line,val);
+}
+//-------------------------------------------------------------------------
+void vtkpxPhaseCorrectCSIData::SetCurrentParameters(vtkDoubleArray* par)
+{
+  static int firsttime=0;
+
+  int numt=this->parameters->GetNumberOfTuples();
+  int num=par->GetNumberOfTuples();
+
+  if (num!=numt)
+    {
+      vtkErrorMacro(<<"Bad Data for Optimization");
+      return;
+    }
+
+  for (int i=0;i<numt;i++)
+    {
+      this->parameters->SetComponent(i,0,par->GetComponent(i,0));
+      if (firsttime)
+	fprintf(stderr,"Setting %d to %f to parameter=%f\n",i,par->GetComponent(i,0),this->parameters->GetComponent(i,0));
+    }
+  
+  //  firsttime=0;
+}
+ 
+void vtkpxPhaseCorrectCSIData::GetCurrentParameters(vtkDoubleArray* par)
+{
+  int numt=this->parameters->GetNumberOfTuples();
+  int num=par->GetNumberOfTuples();
+  static int firsttime=0;
+
+  if (num!=numt)
+    par->SetNumberOfTuples(numt);
+
+  for (int i=0;i<numt;i++)
+    {
+      par->SetComponent(i,0,this->parameters->GetComponent(i,0)*1.0);
+      if (firsttime)
+	fprintf(stderr,"Getting %d, parameter=%f to %f\n",i,this->parameters->GetComponent(i,0),par->GetComponent(i,0));
+    }
+  //  firsttime=0;
+}
+//-------------------------------------------------------------------------
+double vtkpxPhaseCorrectCSIData::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+{
+  int np=params->GetNumberOfTuples();
+  int nt=grad->GetNumberOfTuples();
+
+  if (np!=nt)
+    grad->SetNumberOfTuples(np);
+
+  double magn=0.0;
+
+  for (int i=0;i<np;i++)
+    {
+      double orig=params->GetComponent(i,0);
+      params->SetComponent(i,0,orig+this->Step);
+      double vp=this->OptimizerValue(params);
+      params->SetComponent(i,0,orig-this->Step);
+      double vm=this->OptimizerValue(params);
+      params->SetComponent(i,0,orig);
+      double g=(vp-vm)/this->Step;
+      magn+=g*g;
+      grad->SetComponent(i,0,g);
+    }
+
+
+  ++this->DerivEvaluation;
+  return sqrt(magn);
+}
+//------------------------------------------------------------------------- 
+double vtkpxPhaseCorrectCSIData::OptimizerValue(vtkDoubleArray* params)
+{
+  ++this->FunctionEvaluation;
+  this->SetCurrentParameters(params);
+  double sum=this->GenerateOutputImages(this->InputReal,this->InputImag,
+				       this->OutputReal,this->OutputImag,
+				       this->parameters);
+
+  return sum;
+}
+//------------------------------------------------------------------------- 
+void vtkpxPhaseCorrectCSIData::GenerateInputs(vtkImageData* real,vtkImageData* imag, vtkImageData* outreal,vtkImageData* outimag)
+{
+  if (this->InputReal==NULL)
+    this->InputReal=vtkImageData::New();
+  this->InputReal->ShallowCopy(real);
+
+  this->OutputReal=outreal;
+  this->OutputReal->DeepCopy(this->InputReal);
+
+  if (this->InputImag==NULL)
+    this->InputImag=vtkImageData::New();
+  this->InputImag->ShallowCopy(imag);
+
+  this->OutputImag=outimag;
+  this->OutputImag->DeepCopy(this->InputImag);
+}
+
+//------------------------------------------------------------------------- 
+void vtkpxPhaseCorrectCSIData::RunFirstOrderPhase(vtkImageData* real,vtkImageData* imag, vtkImageData* outreal,vtkImageData* outimag)
+{
+  this->GenerateInputs(real,imag,outreal,outimag);
+
+  int dim[3];
+  real->GetDimensions(dim);
+  int nvoxels=dim[0]*dim[1]*dim[2];
+
+  this->FirstOrderPhases->SetNumberOfTuples(nvoxels);
+  this->FirstOrderPhases->FillComponent(0,this->FirstOrderPhase);
+
+  int voxel=0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+
+	  double pinit=this->FirstOrderPhases->GetComponent(voxel,0);
+	  double pmax=pinit+1.0;
+	  double pmin=pinit-1.0;
+	  double pstep=0.05;
+	  double pstep2=0.05;
+	  double best=this->CorrectVoxel(this->InputReal,this->InputImag,this->OutputReal,this->OutputImag,
+					i,j,k,0,pmin,voxel);
+	  double bestp=pmin;
+
+	  pmin+=pstep;
+	  
+	  for (int level=0;level<=9;level++)
+	    {
+	      for (double p1=pmin;p1<=pmax;p1+=pstep)
+		{
+		  double v=this->CorrectVoxel(this->InputReal,this->InputImag,this->OutputReal,this->OutputImag,
+					     i,j,k,0,p1,voxel);
+		  
+		  if (v<best)
+		    {
+		      best=v;
+		      bestp=p1;
+		    }
+		  //fprintf(stderr,"Evaluating %.5f %f \t\t\t best=%.5f %f\n",p1,v,bestp,best);
+		}
+	      if (level==9)
+		fprintf(stderr,"Searched P1 level=%d (%d,%d,%d) %.2f:%.2f:%.2f --> best=%.5f,%f\n",level,
+			i,j,k,
+		      pmin,pstep,pmax,bestp,best);
+	      if (2*(level/2)==level)
+		{
+		  if (4*(level/4)==level)
+		    pstep2=0.666*pstep2;
+		  pmin=bestp-9*pstep2;
+		  pmax=bestp+95*pstep2;
+		  pstep=pstep2;
+		}
+	      else 
+		{
+		  pmin=Frange(bestp-4.0,this->FirstOrderPhase-4.0,this->FirstOrderPhase+4.0);
+		  pmax=Frange(bestp+4.0,this->FirstOrderPhase-4.0,this->FirstOrderPhase+4.0);
+		  pstep=1.0;
+		}
+	    }
+	  
+	  this->FirstOrderPhases->SetComponent(voxel,0,bestp);
+	  if (i==dim[0]/2 && j==dim[1]/2 && k==dim[2]/2)
+	    this->FirstOrderPhase=bestp;
+	  ++voxel;
+	}
+
+  this->GenerateFirstOrderPhaseOutputImages(this->InputReal,this->InputImag,this->OutputReal,this->OutputImag,this->FirstOrderPhases);
+}
+
+
+
+void vtkpxPhaseCorrectCSIData::RunZeroOrderPhase(vtkImageData* real,vtkImageData* imag, vtkImageData* outreal,vtkImageData* outimag)
+{
+    this->GenerateInputs(real,imag,outreal,outimag);
+
+  int dim[3];
+  real->GetDimensions(dim);
+  int nvoxels=dim[0]*dim[1]*dim[2];
+
+
+  this->ZeroOrderPhases->SetNumberOfTuples(nvoxels);
+  this->ZeroOrderPhases->FillComponent(0,0.0);
+
+  int voxel=0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  double pfirst=this->FirstOrderPhases->GetComponent(voxel,0);
+	  double pinit=this->ZeroOrderPhases->GetComponent(voxel,0);
+	  double pmax=pinit+0.3;
+	  double pmin=pinit-0.3;
+	  double pstep=0.03;
+	  double pstep2=0.03;
+	  double best=this->CorrectVoxel(this->InputReal,this->InputImag,this->OutputReal,this->OutputImag,
+					i,j,k,pmin,pfirst,voxel);
+	  double bestp=pmin;
+
+	  pmin+=pstep;
+	  
+	  for (int level=0;level<=4;level++)
+	    {
+	      for (double p0=pmin;p0<=pmax;p0+=pstep)
+		{
+		  double v=this->CorrectVoxel(this->InputReal,this->InputImag,this->OutputReal,this->OutputImag,
+					     i,j,k,p0,pfirst,voxel);
+		  
+		  if (v<best)
+		    {
+		      best=v;
+		      bestp=p0;
+		    }
+		}
+	      if (level==4)
+		fprintf(stderr,"Searched P0 level=%d (%d,%d,%d) %.2f:%.2f:%.2f --> best=%.5f,%f\n",level,
+			i,j,k,
+			pmin,pstep,pmax,bestp,best);
+	      
+	      pstep2=0.1*pstep;
+	      pmin=bestp-1.9*pstep;
+	      pmax=bestp+1.9*pstep;
+	      pstep=pstep2;
+	    }
+	
+	  this->ZeroOrderPhases->SetComponent(voxel,0,bestp);
+	  ++voxel;
+	}
+
+  this->GenerateZeroAndFirstOrderPhaseOutputImages(this->InputReal,this->InputImag,this->OutputReal,this->OutputImag,
+						   this->ZeroOrderPhases,this->FirstOrderPhases);
+
+
+
+
+
+}
+
+
+void vtkpxPhaseCorrectCSIData::Run(vtkImageData* real,vtkImageData* imag, vtkImageData* outreal,vtkImageData* outimag)
+{
+  // Create Real and Imaginary Stuff 
+  // -------------------------------
+  this->GenerateInputs(real,imag,outreal,outimag);
+  
+  // one parameter for each voxel (zero-order phase) + 1 global first-order phase 
+  // ----------------------------------------------------------------------------
+  int dim[3]; this->InputReal->GetDimensions(dim);
+  int numparam=dim[0]*dim[1]*dim[2];
+
+  this->parameters->SetNumberOfTuples(numparam*2);
+  this->parameters->FillComponent(0,0);
+  
+  vtkpxOptimizer* optimizer=vtkpxOptimizer::New();
+
+  vtkDoubleArray* position=vtkDoubleArray::New();
+  this->GetCurrentParameters(position);
+
+  vtkDoubleArray* temp=vtkDoubleArray::New();
+
+
+  optimizer->SetMasterObject(this);
+  optimizer->SetEvaluateFunctionMethod(&vtkpxPhaseCorrectCSIData::CalculateFunction);
+  optimizer->SetEvaluateGradientMethod(&vtkpxPhaseCorrectCSIData::CalculateGradient);
+  optimizer->SetFeedbackMethod(&vtkpxPhaseCorrectCSIData::OptimizerFeedback);
+
+  fprintf(stderr,"Starting meth=%d\n",this->OptimizationMethod);
+  this->FunctionEvaluation=0;
+  this->DerivEvaluation=0;
+
+  double st=this->Step;
+
+  if (numparam==1 && this->OptimizationMethod==5)
+    {
+      optimizer->Compute1DMinimization(position,-1.0,1.0,this->Tolerance);
+    }
+  else
+    {
+      switch (this->OptimizationMethod)
+	{
+	case -1:
+	case 0:
+	  optimizer->ComputeOldGradientDescent(position,this->Step,this->Tolerance);
+	  break;
+	case 2:
+	  optimizer->ComputeGradientDescent(position,this->Iterations,this->Tolerance);
+	  break;
+	case 1:
+	  
+	  {
+	    for (int j=0;j<4;j++)
+	      {
+		fprintf(stderr,"\n\t\t j=%d Step=%f\n",j,st);
+		optimizer->ComputeSlowClimb(position,st,this->Iterations);
+		st=st*0.5;
+	      }
+	  }
+	  break;
+	case 3:
+	  optimizer->ComputePowell(position,temp,this->Iterations,this->Tolerance);
+	  break;
+	case 4:
+	  optimizer->ComputeConjugateGradient(position,this->Iterations,this->Tolerance);
+	  break;
+	}
+    }
+
+  fprintf(stderr,"First Value %f %f\n",position->GetComponent(0,0),this->parameters->GetComponent(0,0));
+  this->parameters->DeepCopy(position);
+  fprintf(stderr,"First Value After %f %f\n",position->GetComponent(0,0),this->parameters->GetComponent(0,0));
+
+  optimizer->Delete();
+  position->Delete();
+  temp->Delete();
+
+  this->GenerateOutputImages(this->InputReal,this->InputImag,this->OutputReal,this->OutputImag,this->parameters);
+ 
+}
+
+//----------------------------------------------------------------------------------------------------------
+double vtkpxPhaseCorrectCSIData::GenerateOutputImages(vtkImageData* inreal,vtkImageData* inimag,
+						     vtkImageData* outreal,vtkImageData* outimag,
+						     vtkDoubleArray* params)
+{
+  int dim[3]; inreal->GetDimensions(dim);
+  double sum=0.0;
+
+  int index=0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  double p0=parameters->GetComponent(index,0);
+	  sum+=this->CorrectVoxel(inreal,inimag,outreal,outimag,i,j,k,p0,this->FirstOrderPhase,index);
+	  ++index;
+	}
+  
+  return sum;
+}
+
+// ------------------------------------------------------------------------------------------------------------------
+
+double vtkpxPhaseCorrectCSIData::GenerateFirstOrderPhaseOutputImages(vtkImageData* inreal,vtkImageData* inimag,
+								    vtkImageData* outreal,vtkImageData* outimag,
+								    vtkDoubleArray* p1_params)
+{
+  int dim[3]; inreal->GetDimensions(dim);
+  double sum=0.0;
+
+  int index=0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  sum+=this->CorrectVoxel(inreal,inimag,outreal,outimag,i,j,k,0.0,p1_params->GetComponent(index,0),index);
+	  ++index;
+	}
+  
+  return sum;
+}
+
+//----------------------------------------------------------------------------------------------------------
+double vtkpxPhaseCorrectCSIData::GenerateZeroAndFirstOrderPhaseOutputImages(vtkImageData* inreal,vtkImageData* inimag,
+									   vtkImageData* outreal,vtkImageData* outimag,
+									   vtkDoubleArray* p0_params,
+									   vtkDoubleArray* p1_params)
+{
+  int dim[3]; inreal->GetDimensions(dim);
+  double sum=0.0;
+
+  int index=0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  sum+=this->CorrectVoxel(inreal,inimag,outreal,outimag,i,j,k,
+				  p0_params->GetComponent(index,0),
+				  p1_params->GetComponent(index,0),
+				  index);
+	  ++index;
+	}
+  
+  return sum;
+}
+
+//----------------------------------------------------------------------------------------------------------
+double vtkpxPhaseCorrectCSIData::CorrectVoxel(vtkImageData* inreal,vtkImageData* inimag,
+					    vtkImageData* outreal,vtkImageData* outimag,
+					    int x,int y,int z,double p0,double p1,int index)
+{
+
+  int nc=inreal->GetNumberOfScalarComponents();
+  double sum=0.0;
+
+
+  vtkDoubleArray* outr=(vtkDoubleArray*)outreal->GetPointData()->GetScalars();
+  vtkDoubleArray* outi=(vtkDoubleArray*)outimag->GetPointData()->GetScalars();
+
+  double scalefactor=2.0*vtkMath::Pi()/double(nc);
+
+  for (int c=0;c<nc;c++)
+    {
+      double X=inreal->GetScalarComponentAsDouble(x,y,z,c);
+      double Y=inimag->GetScalarComponentAsDouble(x,y,z,c);
+
+      double Theta = atan2(Y, X);
+      double R = sqrt(X*X + Y*Y);
+	      
+      double Theta2= Theta + p0 + p1 *double(c) * scalefactor;
+
+      double X2=R*cos(Theta2);
+      double Y2=R*sin(Theta2);
+	      
+      outr->SetComponent(index,c,X2);
+      outi->SetComponent(index,c,Y2);
+
+      /*  if (c==nc/2)
+	fprintf(stderr,"\nc=%d p0=%f p1=%f Input(%.0f,%.0f) --> Output (%.0f,%.0f) Theta2-Theta=%f\n",
+	c,p0,p1,X,Y,X2,Y2,Theta2-Theta);*/
+
+      sum+=X2;
+      
+      /*      if (c<nc/6 || 5*c>nc/6)
+	      sum-=fabs(X2);*/
+
+    }
+
+  //  fprintf(stderr,"Corrected Voxel (%d,%d,%d, ind=%d) p0=%f p1=%f sum=%f\n",x,y,z,index,p0,p1,fabs(sum));
+
+  return -(sum);
+}
+//----------------------------------------------------------------------------------------------------------
+int vtkpxPhaseCorrectCSIData::ReadFIDFile(const char* fname,int width,int height,int depth,int components,
+					  vtkImageData* Real,vtkImageData* Imaginary)
+{
+  gzFile fp = gzsuffixopen(fname,"rb");//fopen(fname,"rb");
+  if ( fp==Z_NULL)
+    {
+      fprintf(stderr,"Cannot Open File %s\n", fname );
+      return 0;
+    }
+  
+  fprintf(stderr,"\nReading %s, Size of long = %d\n",fname,sizeof(long));
+  int numelements=2*width*height*depth*components;
+  long* data=new long[numelements];
+  //  int np=fread(&data[0],sizeof(long),numelements,fp);
+  int np=gzread(fp,&data[0],sizeof(long)*numelements);
+  gzclose(fp);
+
+  fprintf(stderr,"np=%d numelements=%d  bytes=%d\n",np,numelements,np*sizeof(long));
+
+  int depth_components=depth*components;
+  int depth_components_width=depth_components*width;
+
+  fprintf(stderr,"\n Read %d values (%d)\n",np,numelements);
+
+  Real->SetScalarTypeToDouble();
+  Real->SetNumberOfScalarComponents(components);
+  Real->SetDimensions(width,height,depth);
+  Real->SetWholeExtent(0,width-1,0,height-1,0,depth-1);
+  Real->SetExtent(0,width-1,0,height-1,0,depth-1);
+  Real->SetSpacing(1.0,1.0,double(height)/double(depth));
+  Real->AllocateScalars();
+  
+  Imaginary->SetScalarTypeToDouble();
+  Imaginary->SetNumberOfScalarComponents(components);
+  Imaginary->SetDimensions(width,height,depth);
+  Imaginary->SetWholeExtent(0,width-1,0,height-1,0,depth-1);
+  Imaginary->SetExtent(0,width-1,0,height-1,0,depth-1);
+  Imaginary->SetSpacing(1.0,1.0,double(height)/double(depth));
+  Imaginary->AllocateScalars();
+
+  fprintf(stderr,"Output Real/Imag (dim=%dx%dx%d, %d)\n",
+	  Real->GetDimensions()[0],
+	  Real->GetDimensions()[1],
+	  Real->GetDimensions()[2],
+	  Real->GetNumberOfScalarComponents());
+  
+
+  vtkImageData* img=vtkImageData::New();
+  img->SetScalarTypeToDouble();
+  img->SetNumberOfScalarComponents(2);
+  img->SetDimensions(width,height,components);
+  img->SetWholeExtent(0,width-1,0,height-1,0,components-1);
+  img->SetExtent(0,width-1,0,height-1,0,components-1);
+  img->SetSpacing(1.0,1.0,double(height)/double(components));
+  img->AllocateScalars();
+
+  vtkDoubleArray* array=(vtkDoubleArray*)(img->GetPointData()->GetScalars());
+  vtkDoubleArray* real_array=(vtkDoubleArray*)(Real->GetPointData()->GetScalars());
+  vtkDoubleArray* imag_array=(vtkDoubleArray*)(Imaginary->GetPointData()->GetScalars());
+
+  // Flip Left right and flip sign for odd voxels 
+
+  for (int sl=0;sl<depth;sl++)
+    {
+      // If Even
+      int sliceno=0;
+
+      if (2*int(sl/2)==sl)
+	{
+	  fprintf(stderr,"*");
+	  sliceno=sl/2;
+	}
+      else
+	{
+	  fprintf(stderr,"+");
+	  sliceno=sl/2+depth/2;
+	  if (2*int(depth/2)!=depth)
+	    sliceno+=1;
+	}
+
+      fprintf(stderr,"\tReal Slice = %2d, Imaged Slice= %2d\t components=%d depth_components=%d depth_components_width=%d\n",
+	      sl,sliceno,components,depth_components,depth_components_width);
+
+      int index=0;
+      for (int c=0;c<components;c++)
+	for (int j=0;j<height;j++)
+	  for (int i=0;i<width;i++)
+	    {
+	      int offset= ((components-1)-c) + sliceno*components +  (width-1-i) * depth_components +  j * depth_components_width;
+
+	      /*	      if (i==0 && j==0 && c==components-1)
+			      fprintf(stderr,"\tInner offset =%d\n",offset);*/
+	      
+	      offset=2*offset;
+	      array->SetComponent(index,0,data[offset]);
+	      array->SetComponent(index,1,data[offset+1]);
+	      ++index;
+	    }
+
+
+      vtkImageFFT* fft=vtkImageFFT::New();
+      fft->SetDimensionality(3);
+      fft->SetInput(img);
+
+      vtkImageFourierCenter* fft_c=vtkImageFourierCenter::New();
+      fft_c->SetDimensionality(3);
+      fft_c->SetInput(fft->GetOutput());
+      fft_c->Update();
+
+      vtkImageData* sliceimage=fft_c->GetOutput();
+
+      int out_index=sl*width*height;
+
+      for (int j=0;j<height;j++)
+	for (int i=0;i<width;i++)
+	  {
+	    for (int c=0;c<components;c++)
+	      {
+		double re=sliceimage->GetScalarComponentAsDouble(i,j,c,0);
+		double im=sliceimage->GetScalarComponentAsDouble(i,j,c,1);
+		real_array->SetComponent(out_index,c,re);
+		imag_array->SetComponent(out_index,c,im);
+	      }
+	    ++out_index;
+	  }
+
+      fft->Delete();
+      fft_c->Delete();
+    }
+  delete [] data;
+  return 1;
+}
+// --------------------------------------------------------------------------------------------------
+int vtkpxPhaseCorrectCSIData::SaveFIDFile(const char* fname,vtkImageData* Real,vtkImageData* Imaginary,int mode)
+{
+  char line[400];
+
+  if (mode==0)
+    {
+      vtkpxAnalyzeImageWriter* ana=vtkpxAnalyzeImageWriter::New();
+      ana->SetInput(Real);
+      ana->SetCompression(6);
+      sprintf(line,"%s_real.hdr",fname);
+      ana->Save(line);
+
+      fprintf(stderr,"Output Saved in %s (dim=%dx%dx%d, %d)\n",
+	      line,
+	      Real->GetDimensions()[0],
+	      Real->GetDimensions()[1],
+	      Real->GetDimensions()[2],
+	      Real->GetNumberOfScalarComponents());
+
+
+      ana->SetInput(Imaginary);
+      ana->SetCompression(6);
+      sprintf(line,"%s_imag.hdr",fname);
+      ana->Save(line);
+
+      fprintf(stderr,"Output Saved in %s (dim=%dx%dx%d, %d)\n",
+	      line,
+	      Imaginary->GetDimensions()[0],
+	      Imaginary->GetDimensions()[1],
+	      Imaginary->GetDimensions()[2],
+	      Imaginary->GetNumberOfScalarComponents());
+
+
+      ana->Delete();
+    }
+  else
+    {
+      int dim[3]; Real->GetDimensions(dim);
+      int components=Real->GetNumberOfScalarComponents();
+
+      vtkImageData* magn=vtkImageData::New();
+      magn->SetScalarTypeToDouble();
+      magn->SetNumberOfScalarComponents(components);
+      magn->SetDimensions(dim);
+      magn->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+      magn->SetExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+      magn->SetSpacing(Real->GetSpacing());
+      magn->AllocateScalars();
+ 
+      vtkDoubleArray* array=(vtkDoubleArray*)(magn->GetPointData()->GetScalars());
+      vtkDoubleArray* real_array=(vtkDoubleArray*)(Real->GetPointData()->GetScalars());
+      vtkDoubleArray* imag_array=(vtkDoubleArray*)(Imaginary->GetPointData()->GetScalars());
+      
+      int nt=dim[0]*dim[1]*dim[2];
+
+      for (int i=0;i<nt;i++)
+	for (int c=0;c<components;c++)
+	  {
+	    double v1=real_array->GetComponent(i,c);
+	    double v2=imag_array->GetComponent(i,c);
+	    double m=sqrt(v1*v1+v2*v2);
+	    array->SetComponent(i,c,m);
+	  }
+
+
+      vtkpxAnalyzeImageWriter* ana=vtkpxAnalyzeImageWriter::New();
+
+      if (mode==1)
+	{
+	  ana->SetInput(magn);
+	  ana->SetCompression(6);
+	  ana->Save(fname);
+
+	  fprintf(stderr,"Output Saved in %s (dim=%dx%dx%d, %d)\n",
+		  fname,
+		  magn->GetDimensions()[0],
+		  magn->GetDimensions()[1],
+		  magn->GetDimensions()[2],
+		  magn->GetNumberOfScalarComponents());
+	}
+      else
+	{
+	  vtkImageData* temp=vtkImageData::New();
+	  vtkpxUtil::ReorderImage(temp,magn);
+	  ana->SetInput(temp);
+	  ana->SetCompression(6);
+	  ana->Save(fname);
+	  temp->Delete();
+	  fprintf(stderr,"Output Saved in %s (dim=%dx%dx%d, %d)\n",
+		  fname,
+		  temp->GetDimensions()[0],
+		  temp->GetDimensions()[1],
+		  temp->GetDimensions()[2],
+		  temp->GetNumberOfScalarComponents());
+	}
+      ana->Delete();
+      magn->Delete();
+    }
+
+  return 1;
+}
+// --------------------------------------------------------------------------------------------------
+int vtkpxPhaseCorrectCSIData::SaveIntegralFIDFile(const char* fname,vtkImageData* Real,vtkImageData* Imaginary)
+{
+  int components=Real->GetNumberOfScalarComponents();
+  double* sum=new double[components];
+
+  vtkDoubleArray* real_array=(vtkDoubleArray*)(Real->GetPointData()->GetScalars());
+  vtkDoubleArray* imag_array=(vtkDoubleArray*)(Imaginary->GetPointData()->GetScalars());
+      
+  int nt=real_array->GetNumberOfTuples();
+
+  for (int c=0;c<components;c++)
+    {
+      sum[c]=0.0;
+      for (int i=0;i<nt;i++)
+	{
+	  double v1=real_array->GetComponent(i,c);
+	  double v2=imag_array->GetComponent(i,c);
+	  double m=sqrt(v1*v1+v2*v2);
+	  sum[c]+=m;
+	}
+      sum[c]/=double(nt);
+    }
+  
+  FILE* fout=fopen(fname,"w");
+  int ok=0;
+  if (fout)
+    {
+      fprintf(fout,"# Component \t Average\n");
+      for (int c=0;c<components;c++)
+	fprintf(fout,"%5d \t %.2f\n",c,sum[c]);
+
+      fclose(fout);
+      ok=1;
+    }
+
+  delete [] sum;
+  return ok;
+}
+
+// --------------------------------------------------------------------------------------------------
+int vtkpxPhaseCorrectCSIData::ExtractSingleVoxel(vtkImageData* Real,vtkImageData* Imaginary,vtkImageData* OutReal,vtkImageData* OutImag,
+						 vtkImageData* Magn,int x,int y,int z)
+{
+  
+  int nc=Real->GetNumberOfScalarComponents();
+
+  OutReal->SetDimensions(1,1,nc);
+  OutReal->SetNumberOfScalarComponents(1);
+  OutReal->AllocateScalars();
+
+  OutImag->SetDimensions(1,1,nc);
+  OutImag->SetNumberOfScalarComponents(1);
+  OutImag->AllocateScalars();
+
+  Magn->SetDimensions(1,1,nc);
+  Magn->SetNumberOfScalarComponents(1);
+  Magn->AllocateScalars();
+
+  vtkDataArray* data_real=OutReal->GetPointData()->GetScalars();
+  vtkDataArray* data_imag=OutImag->GetPointData()->GetScalars();
+  vtkDataArray* data_magn=Magn->GetPointData()->GetScalars();
+
+  for (int i=0;i<nc;i++)
+    {
+      double X=Real->GetScalarComponentAsDouble(x,y,z,i);
+      double Y=Imaginary->GetScalarComponentAsDouble(x,y,z,i);
+      data_real->SetComponent(i,0,X);
+      data_imag->SetComponent(i,0,Y);
+      data_magn->SetComponent(i,0,sqrt(X*X+Y*Y));
+    }
+
+  return 1;
+}
+
+int vtkpxPhaseCorrectCSIData::ExtractSingleVoxelAsComponent(vtkImageData* Real,vtkImageData* Imaginary,vtkImageData* OutReal,vtkImageData* OutImag,
+							    int x,int y,int z)
+{
+  int nc=Real->GetNumberOfScalarComponents();
+
+  OutReal->SetDimensions(1,1,1);
+  OutReal->SetNumberOfScalarComponents(nc);
+  OutReal->AllocateScalars();
+
+  OutImag->SetDimensions(1,1,1);
+  OutImag->SetNumberOfScalarComponents(nc);
+  OutImag->AllocateScalars();
+
+  vtkDataArray* data_real=OutReal->GetPointData()->GetScalars();
+  vtkDataArray* data_imag=OutImag->GetPointData()->GetScalars();
+
+  for (int i=0;i<nc;i++)
+    {
+      data_real->SetComponent(0,i,Real->GetScalarComponentAsDouble(x,y,z,i));
+      data_imag->SetComponent(0,i,Imaginary->GetScalarComponentAsDouble(x,y,z,i));
+    }
+
+  return 1;
+}
+
+// --------------------------------------------------------------------------------------------------
+double vtkpxPhaseCorrectCSIData::AddPhaseOffsets(vtkImageData* realimg,vtkImageData* imagimg,double theta0,double theta1)
+{
+  int dim[3]; realimg->GetDimensions(dim);
+
+  vtkDoubleArray* data_real=(vtkDoubleArray*)realimg->GetPointData()->GetScalars();
+  vtkDoubleArray* data_imag=(vtkDoubleArray*)imagimg->GetPointData()->GetScalars();
+
+  int index=0;
+  double offset0=theta0;
+
+  double sumreal=0.0;
+  double sumimag=0.0;
+
+  for (int k=0;k<dim[2];k++)
+    {
+      double offset1 =theta1*double(k)*2.0*vtkMath::Pi()/double(dim[2]);
+
+
+      if (k==dim[2]/2)
+	fprintf(stderr,"Offsets = %f %f\n",offset0,offset1);
+
+      for (int i=0;i<dim[0];i++)
+	for (int j=0;j<dim[1];j++)
+	  {
+	    double X = data_real->GetComponent(index,0);
+	    double Y = data_imag->GetComponent(index,0);
+	    
+	    double Theta = atan2(Y, X);
+	    double R = sqrt(X*X + Y*Y);
+	      
+	    double Theta2= Theta + offset0 + offset1;
+	    double X2=R*cos(Theta2);
+	    double Y2=R*sin(Theta2);
+	  
+	    sumreal+=X2;
+	    sumimag+=Y2;
+
+	    data_real->SetComponent(index,0,X2);
+	    data_imag->SetComponent(index,0,Y2);
+	    ++index;
+	  }
+    }
+
+  return fabs(sumreal);
+}
+// --------------------------------------------------------------------------------------------------
+
+
+double vtkpxPhaseCorrectCSIData::GlobalPhaseCorrection(vtkImageData* realimg,vtkImageData* imagimg,double theta1)
+{
+  int dim[3]; realimg->GetDimensions(dim);
+
+  vtkDoubleArray* data_real=(vtkDoubleArray*)realimg->GetPointData()->GetScalars();
+  vtkDoubleArray* data_imag=(vtkDoubleArray*)imagimg->GetPointData()->GetScalars();
+
+  int index=0;
+
+  double sumreal=0.0;
+  double sumimag=0.0;
+
+  int numcomp=data_real->GetNumberOfComponents();
+
+  fprintf(stderr,"slice :");
+  for (int slices=0;slices<dim[2];slices++)
+    {
+      fprintf(stderr,"%d/%d ",slices+1,dim[2]);
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {
+	    int evensum=i+j;
+	    double scale=1.0;
+	    if (evensum % 2 == 0)
+	      scale=1.0;
+	    
+	    for (int k=0;k<numcomp;k++)
+	      {
+		double offset =(theta1)*double(k)*2.0*vtkMath::Pi()/double(numcomp);
+		
+		double X = scale*data_real->GetComponent(index,k);
+		double Y = scale*data_imag->GetComponent(index,k);
+		
+		double Theta = atan2(Y, X);
+		double R = sqrt(X*X + Y*Y);
+		
+		double Theta2= Theta + offset;
+		double X2=R*cos(Theta2);
+		double Y2=R*sin(Theta2);
+		
+		sumreal+=X2;
+		sumimag+=Y2;
+		
+		data_real->SetComponent(index,k,X2);
+		data_imag->SetComponent(index,k,Y2);
+	      }
+	    ++index;
+	  }
+    }
+  fprintf(stderr,"\n");
+
+  return fabs(sumreal);
+
+}
+// --------------------------------------------------------------------------------------------------
+void vtkpxPhaseCorrectCSIData::IntegrateReal(vtkImageData* realimg,vtkImageData* output,
+					     double water1,double water2,
+					     double sat1,double sat2,
+					     double unsat1,double unsat2)
+{
+  output->CopyStructure(realimg);
+  output->SetScalarTypeToDouble();
+  output->SetNumberOfScalarComponents(3);
+  output->AllocateScalars();
+
+  
+  int dim[3]; realimg->GetDimensions(dim);
+  int nc=realimg->GetNumberOfScalarComponents();
+
+  vtkDoubleArray* data=(vtkDoubleArray*)output->GetPointData()->GetScalars();
+
+  int voxel=0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  double wat=0.0,ufat=0.0,sfat=0.0;
+	  for (int c=0;c<nc;c++)
+	    {
+	      double v=realimg->GetScalarComponentAsDouble(i,j,k,c);
+
+	      if (c>=water1 && c<=water2)
+		wat+=v;
+	      else if (c>=sat1 && c<=sat2)
+		sfat+=v;
+	      else if (c>=unsat1 && c<=unsat2)
+		ufat+=v;
+	    }
+	  data->SetComponent(voxel,0,wat);
+	  data->SetComponent(voxel,1,sfat);
+	  data->SetComponent(voxel,2,ufat);
+	  ++voxel;
+	}
+}
+
+
+void vtkpxPhaseCorrectCSIData::IntegrateMagnitudeAndComputeRatio(vtkImageData* realimg,vtkImageData* imagimg,
+								 vtkImageData* output,
+								 double waterwidth)
+						  
+{
+  output->CopyStructure(realimg);
+  output->SetScalarTypeToDouble();
+  output->SetNumberOfScalarComponents(2);
+  output->AllocateScalars();
+  
+  
+  int dim[3]; realimg->GetDimensions(dim);
+  int nc=realimg->GetNumberOfScalarComponents();
+
+  vtkDoubleArray* data=(vtkDoubleArray*)output->GetPointData()->GetScalars();
+  
+  int lower=int(0.5+nc*(0.5-waterwidth));
+  int upper=int(0.0+nc*(0.5+waterwidth));
+  fprintf(stderr,"\t\t Integrating Water range = %d:%d (%d,%.2f)\n",lower,upper,nc,waterwidth);
+
+  int voxel=0;
+  fprintf(stderr,"slice :");
+  for (int k=0;k<dim[2];k++)
+    {
+      fprintf(stderr,"%d/%d ",k+1,dim[2]);
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {
+	    double wat=0.0,fat=0.0;
+	    for (int c=0;c<nc;c++)
+	      {
+		double v1=realimg->GetScalarComponentAsDouble(i,j,k,c);
+		double v2=imagimg->GetScalarComponentAsDouble(i,j,k,c);
+		double v=sqrt(v1*v1+v2*v2);
+		
+		if (c>=lower && c<=upper)
+		  wat+=v;
+		else 
+		  fat+=v;
+	      }
+	    data->SetComponent(voxel,0,wat);
+	    data->SetComponent(voxel,1,fat);
+	    ++voxel;
+	  }
+    }
+}
+
+void vtkpxPhaseCorrectCSIData::IntegrateMagnitude(vtkImageData* realimg,vtkImageData* imagimg,
+						   vtkImageData* output,
+						  double water1,double water2,
+						  double sat1,double sat2,
+						  double unsat1,double unsat2)
+{
+  output->CopyStructure(realimg);
+  output->SetScalarTypeToDouble();
+  output->SetNumberOfScalarComponents(2);
+  output->AllocateScalars();
+
+  
+  int dim[3]; realimg->GetDimensions(dim);
+  int nc=realimg->GetNumberOfScalarComponents();
+
+  vtkDoubleArray* data=(vtkDoubleArray*)output->GetPointData()->GetScalars();
+
+  int voxel=0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  double wat=0.0,ufat=0.0,sfat=0.0;
+	  for (int c=0;c<nc;c++)
+	    {
+	      double v1=realimg->GetScalarComponentAsDouble(i,j,k,c);
+	      double v2=imagimg->GetScalarComponentAsDouble(i,j,k,c);
+	      double v=sqrt(v1*v1+v2*v2);
+
+	      if (c>=water1 && c<=water2)
+		wat+=v;
+	      else if (c>=sat1 && c<=sat2)
+		sfat+=v;
+	      else if (c>=unsat1 && c<=unsat2)
+		ufat+=v;
+	    }
+	  data->SetComponent(voxel,0,wat);
+	  data->SetComponent(voxel,1,sfat);
+	  data->SetComponent(voxel,2,ufat);
+	  ++voxel;
+	}
+}
+
+
+
+void vtkpxPhaseCorrectCSIData::IntegrateMagnitudeGlobal(vtkImageData* realimg,vtkImageData* imagimg,
+							vtkImageData* output,
+							double water_peak,double fat_peak,double scalefactor)
+{
+  output->CopyStructure(realimg);
+  output->SetScalarTypeToDouble();
+  output->SetNumberOfScalarComponents(2);
+  output->AllocateScalars();
+  
+  
+  int dim[3]; realimg->GetDimensions(dim);
+  int nc=realimg->GetNumberOfScalarComponents();
+
+  vtkDoubleArray* data=(vtkDoubleArray*)output->GetPointData()->GetScalars();
+  
+  double gap=0.5*fabs(fat_peak-water_peak);
+
+  double lower=water_peak-gap;
+  double middle=water_peak+gap;
+  double upper=fat_peak+gap;
+
+  fprintf(stderr,"\t\t Integrating Water range = %.1f:%.1f fat_range %.1f:%.1f, water_p=%.1f fat_p=%.1f\n",lower,middle,middle,upper,water_peak,fat_peak);
+
+  int voxel=0;
+  fprintf(stderr,"slice :");
+  for (int k=0;k<dim[2];k++)
+    {
+      fprintf(stderr,"%d/%d ",k+1,dim[2]);
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {
+	    double wat=0.0,fat=0.0;
+	    for (int c=0;c<nc;c++)
+	      {
+		double v1=realimg->GetScalarComponentAsDouble(i,j,k,c);
+		double v2=imagimg->GetScalarComponentAsDouble(i,j,k,c);
+		double v=sqrt(v1*v1+v2*v2);
+		
+		if (c>=lower && c<=middle)
+		  wat+=v;
+		else if (c>=middle && c<=upper)
+		  fat+=v;
+	      }
+	    data->SetComponent(voxel,0,wat*scalefactor);
+	    data->SetComponent(voxel,1,fat*scalefactor);
+	    ++voxel;
+	  }
+    }
+}
+// --------------------------------------------------------------------------------------------------
+// ----------------------------------------------------- Local Stuff --------------------------------
+// --------------------------------------------------------------------------------------------------
+
+void vtkpxPhaseCorrectCSIData::GenerateLocalPeaks(vtkImageData* realimg,vtkImageData* imagimg,
+						  vtkImageData* output,
+						  double water_peak,double fat_peak,double sigma)
+{
+  output->CopyStructure(realimg);
+  output->SetScalarTypeToDouble();
+  output->SetNumberOfScalarComponents(1);
+  output->AllocateScalars();
+
+  
+  int dim[3]; realimg->GetDimensions(dim);
+  int nc=realimg->GetNumberOfScalarComponents();
+
+  vtkDoubleArray* data=(vtkDoubleArray*)output->GetPointData()->GetScalars();
+  
+  int gap=int(0.4*fabs(fat_peak-water_peak)+0.5);
+
+  fprintf(stderr,"Input looking for water peak in %.1f:%.1f (%.1f) and fat_peak in %.1f:%.1f (%.1f)\n",
+	  water_peak-gap,water_peak+gap,water_peak,
+	  fat_peak-gap,fat_peak+gap,fat_peak);
+
+  int voxel=0;
+  int offset[5] = { -2, -1 , 0 , 1 , 2 };
+  double weights[5]={ 0.05,0.25,0.4,0.25,0.05 };
+
+  for (int k=0;k<dim[2];k++)
+    {
+      fprintf(stderr,"%d/%d ",k+1,dim[2]);
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {
+
+	    //
+	    //  Identify Peaks via shift 
+	    //
+	    double max_sum=0.0;
+	    int shift=0;
+
+	    for (int s=-gap;s<=gap;s++)
+	      {
+		double v=0.0;
+		for (int conv=0;conv<=4;conv++)
+		  {
+		    int c[2];
+		    c[0]=Irange(int(water_peak)+s+offset[conv],0,nc-1);
+		    c[1]=Irange(int(fat_peak)+s+offset[conv],0,nc-1);
+		
+		    for (int q=0;q<=1;q++)
+		      {
+			double v1=realimg->GetScalarComponentAsDouble(i,j,k,c[q]);
+			double v2=imagimg->GetScalarComponentAsDouble(i,j,k,c[q]);
+			v+=weights[conv]*sqrt(v1*v1+v2*v2);
+		      }
+		  }
+		
+		if (v>max_sum)
+		  {
+		    max_sum=v;
+		    shift=s;
+		  }
+	      }
+	    data->SetComponent(voxel,0,shift);
+	    ++voxel;
+	  }
+    }
+
+  double gp[3],sp[3];
+  output->GetSpacing(sp);
+
+  gp[0]=sigma;
+  gp[1]=sigma*sp[0]/sp[1];
+  gp[2]=sigma*sp[0]/sp[2];
+
+  vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+  smooth->SetInput(output);
+  smooth->SetStandardDeviations(gp);
+  smooth->Update();
+  fprintf(stderr,"Done Smoothing Local Peaks\n");
+
+  output->ShallowCopy(smooth->GetOutput());
+  smooth->Delete();
+
+  fprintf(stderr,"Done Generating Local Peaks\n");
+
+}
+
+
+
+void vtkpxPhaseCorrectCSIData::IntegrateMagnitudeLocal(vtkImageData* realimg,vtkImageData* imagimg,
+						       vtkImageData* output,vtkDoubleArray* volint,
+						       double water_peak,double fat_peak,double scalefactor)
+{
+  int dim[3]; realimg->GetDimensions(dim);
+  int nc=realimg->GetNumberOfScalarComponents();
+
+  volint->SetNumberOfComponents(3);
+  volint->SetNumberOfTuples(nc);
+  volint->FillComponent(0,0.0);
+  volint->FillComponent(1,0.0);
+  volint->FillComponent(2,0.0);
+
+  output->CopyStructure(realimg);
+  output->SetScalarTypeToDouble();
+  output->SetNumberOfScalarComponents(3);
+  output->AllocateScalars();
+
+  vtkImageData* peaks=vtkImageData::New();
+  vtkpxPhaseCorrectCSIData::GenerateLocalPeaks(realimg,imagimg,peaks,water_peak,fat_peak,1.5);
+  
+  vtkDoubleArray* data=(vtkDoubleArray*)output->GetPointData()->GetScalars();
+  
+  double gap=0.5*fabs(fat_peak-water_peak);
+  double lw=water_peak-gap;
+  double uw=water_peak+gap;
+  double lf=fat_peak-gap;
+  double uf=fat_peak+gap;
+
+  int c2high=nc-int(gap);
+  int c2low=int(gap);
+  double nt=double(dim[2]*dim[1]*dim[0]);
+  int  globshift=int(water_peak-nc/2);
+
+
+  fprintf(stderr,"Input looking for water peak in %.1f:%.1f (%.1f) and fat_peak in %.1f:%.1f (%.1f) globshift=%d\n",
+	  lw,uw,water_peak,lf,uf,fat_peak,globshift);
+
+
+  int voxel=0;
+
+
+
+  fprintf(stderr,"slice :");
+
+  for (int k=0;k<dim[2];k++)
+    {
+      fprintf(stderr,"%d/%d ",k+1,dim[2]);
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {
+	    double shift=peaks->GetScalarComponentAsDouble(i,j,k,0);
+	    data->SetComponent(voxel,2,shift);
+	    double wat_p=water_peak+shift;
+	    double fat_p=fat_peak+shift;
+
+	    int  dshift=int(wat_p-nc/2);
+
+
+	    
+	    double gp=fabs(fat_p-wat_p)*0.5;
+	    double l1=wat_p-gp;
+	    double m1=wat_p+gp;
+	    double u1=fat_p+gp;
+	    
+	    if (i==dim[0]/2 && j==dim[0]/2)
+	      {
+		fprintf(stderr,"k=%d,water = %.1f:%.1f fat=%.1f:%.1f\n",
+			k,l1,m1,m1,u1);
+	      }
+	    
+	    double wat=0.0,fat=0.0;
+	    for (int c=0;c<nc;c++)
+	      {
+		double v1=realimg->GetScalarComponentAsDouble(i,j,k,c);
+		double v2=imagimg->GetScalarComponentAsDouble(i,j,k,c);
+		double v=sqrt(v1*v1+v2*v2);
+
+		int c2=c-dshift;
+		if (c2>c2low && c2<c2high)
+		  volint->SetComponent(c2,0,volint->GetComponent(c2,0)+v);
+
+		int c3=c-globshift;
+		if (c3>c2low && c3<c2high)
+		  volint->SetComponent(c3,1,volint->GetComponent(c3,1)+v);
+
+		volint->SetComponent(c,2,volint->GetComponent(c,2)+v);
+		if (c>=l1 && c<=m1)
+		  wat+=v;
+		else if (c>=m1 && c<=u1)
+		  fat+=v;
+	      }
+	    
+	    data->SetComponent(voxel,0,wat*scalefactor);
+	    data->SetComponent(voxel,1,fat*scalefactor);
+	    
+	    if (i==dim[0]/2 && j==dim[0]/2)
+	      {
+		fprintf(stderr,"k=%d, %.1f %.1f %.1f\n",k,
+			data->GetComponent(voxel,0),
+			data->GetComponent(voxel,1),
+			data->GetComponent(voxel,2));
+	      }
+
+	    ++voxel;
+	  }
+    }
+
+
+  for (int c=0;c<nc;c++)
+    for (int d=0;d<=2;d++)
+      volint->SetComponent(c,d,volint->GetComponent(c,d)/nt);
+
+  peaks->Delete();
+
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxPhaseCorrectCSIData.h b/bioimagesuite30_src/Imaging/vtkpxPhaseCorrectCSIData.h
new file mode 100644
index 0000000..148eb56
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxPhaseCorrectCSIData.h
@@ -0,0 +1,252 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxPhaseCorrectCSIData.h,v $
+  Language:  C++
+  Date:      $Date: 2004/03/23 19:19:45 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#ifndef __VTKPXCOMPUTEFIELDCONSTANT_H
+#define __VTKPXCOMPUTEFIELDCONSTANT_H
+
+#include "vtkProcessObject.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+
+
+class vtkpxPhaseCorrectCSIData : public vtkProcessObject {
+
+public:
+
+  vtkTypeMacro(vtkpxPhaseCorrectCSIData,vtkProcessObject);
+
+  // Description:
+  // This one also 
+  static vtkpxPhaseCorrectCSIData* New();
+  
+  // Description:
+  // These are needed for the Optimizer 
+  static void  OptimizerFeedback(vtkObject* self,const char* line,double val);
+  static double CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output);
+  static double CalculateFunction(vtkObject* self,vtkDoubleArray* position);
+
+  // Description:
+  // Optimization Method
+  vtkSetMacro(OptimizationMethod,int);
+  vtkGetMacro(OptimizationMethod,int);
+
+  
+  // Description:
+  // Global First order phase correction
+  vtkSetMacro(FirstOrderPhase,double);
+  vtkGetMacro(FirstOrderPhase,double);
+
+
+  // Description:
+  // Optimization Method Parameters
+  vtkSetMacro(Step,double);
+  vtkGetMacro(Step,double);
+
+  vtkSetMacro(Tolerance,double);
+  vtkGetMacro(Tolerance,double);
+
+  vtkSetMacro(Iterations,int);
+  vtkGetMacro(Iterations,int);
+
+  vtkSetMacro(OptimizeZeroOrder,int);
+  vtkGetMacro(OptimizeZeroOrder,int);
+
+
+  // Description:
+  // Shorthand for different optimization methods 
+  virtual void SetOptimizationMethodToOldStyle() { this->SetOptimizationMethod(-1); }
+  virtual void SetOptimizationMethodToDefault() { this->SetOptimizationMethod(0); }
+  virtual void SetOptimizationMethodToSlowClimb() { this->SetOptimizationMethod(1); }
+  virtual void SetOptimizationMethodToGradientDescent() { this->SetOptimizationMethod(2); }
+
+  // Description:
+  // Run Optimization
+  virtual void Run(vtkImageData* real,vtkImageData* imag, vtkImageData* outreal,vtkImageData* outimag);
+  virtual void RunFirstOrderPhase(vtkImageData* real,vtkImageData* imag, vtkImageData* outreal,vtkImageData* outimag);
+  virtual void RunZeroOrderPhase(vtkImageData* real,vtkImageData* imag, vtkImageData* outreal,vtkImageData* outimag);
+
+
+  
+  // Description:
+  // Load Brucker Data
+  static int ReadFIDFile(const char* fname,int width,int height,int depth,int components,
+			 vtkImageData* Real,vtkImageData* Imaginary);
+
+
+  // Description:
+  // Save FID Stuff
+  static int SaveFIDFile(const char* fname,vtkImageData* Real,vtkImageData* Imaginary,int mode);
+  static int SaveIntegralFIDFile(const char* fname,vtkImageData* Real,vtkImageData* Imaginary);
+
+  // Description:
+  // Extract Single Row for Plotting (x_const,y_const,z_const,c) --> (0,0,c)
+  static int ExtractSingleVoxel(vtkImageData* Real,vtkImageData* Imaginary,vtkImageData* OutReal,vtkImageData* OutImag,vtkImageData* Magn,
+				int x,int y, int z);
+  static int ExtractSingleVoxelAsComponent(vtkImageData* Real,vtkImageData* Imaginary,vtkImageData* OutReal,vtkImageData* OutImag,
+					   int x,int y, int z);
+
+
+  // Description:
+  // Add Phase Offsets to Image 
+  static double AddPhaseOffsets(vtkImageData* realimg,vtkImageData* imagimg,double theta0,double theta1);
+  static double GlobalPhaseCorrection(vtkImageData* realimg,vtkImageData* imagimg,double theta1);
+
+  // Description:
+  // Access Parameters 
+  virtual void  SetCurrentParameters(vtkDoubleArray* par);
+  virtual void  GetCurrentParameters(vtkDoubleArray* par);
+
+  // Description:
+  // FirstOrderPhases
+  vtkGetObjectMacro(FirstOrderPhases,vtkDoubleArray);
+  vtkGetObjectMacro(ZeroOrderPhases,vtkDoubleArray);
+
+
+  // Description:
+  // Integrate 
+  static void IntegrateReal(vtkImageData* realimg,vtkImageData* output,
+			    double water1,double water2,
+			    double sat1,double sat2,
+			    double unsat1,double unsat2);
+
+  static void IntegrateMagnitude(vtkImageData* realimg,vtkImageData* imagimg,vtkImageData* output,
+				 double water1,double water2,
+				 double sat1,double sat2,
+				 double unsat1,double unsat2);
+
+
+  static void IntegrateMagnitudeAndComputeRatio(vtkImageData* realimg,vtkImageData* imagimg,
+						vtkImageData* output,
+						double waterwidth=0.02);
+						  
+
+  static void IntegrateMagnitudeGlobal(vtkImageData* realimg,vtkImageData* imagimg,
+				       vtkImageData* output,
+				       double water_peak,double fat_peak,double scalefactor=1.0);
+						  
+
+  static void GenerateLocalPeaks(vtkImageData* realimg,vtkImageData* imagimg,
+				 vtkImageData* output,
+				 double water_peak,double fat_peak,double sigma=1.0);
+
+  static void IntegrateMagnitudeLocal(vtkImageData* realimg,vtkImageData* imagimg,
+				      vtkImageData* output,vtkDoubleArray* volint,
+				      double water_peak,double fat_peak,double scalefactor=1.0);
+						  
+
+
+protected:
+
+  // Description:
+  // Make all these protected 
+  // Constructor
+  vtkpxPhaseCorrectCSIData();
+  virtual ~vtkpxPhaseCorrectCSIData();
+  vtkpxPhaseCorrectCSIData(const vtkpxPhaseCorrectCSIData&) {};
+  void operator=(const vtkpxPhaseCorrectCSIData&) {};
+
+
+  // Description:
+  // Various Control Parameters
+  int   OptimizationMethod;
+  vtkDoubleArray* parameters;
+  vtkDoubleArray* FirstOrderPhases;
+  vtkDoubleArray* ZeroOrderPhases;
+  int   FunctionEvaluation;
+  int   DerivEvaluation;
+  double Step;
+  double Tolerance;
+  int   Iterations;
+  int   OptimizeZeroOrder;
+  double FirstOrderPhase;
+
+  // Description:
+  // Image Pointers
+  vtkImageData* InputReal;
+  vtkImageData* InputImag;
+  vtkImageData* OutputReal;
+  vtkImageData* OutputImag;
+  
+
+  // Description:
+  // Needed for Optimizer -- set,get,optimizer,optimizervalue
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+  virtual void  SetOutputStatus(const char* line,double v);
+
+  virtual double CorrectVoxel(vtkImageData* inreal,vtkImageData* inimag,
+			     vtkImageData* outreal,vtkImageData* outimag,
+			     int x,int y,int z,double p0,double p1,int index);
+
+  virtual double GenerateOutputImages(vtkImageData* inreal,vtkImageData* inimag,
+				     vtkImageData* outreal,vtkImageData* outimag,
+				     vtkDoubleArray* parameters);
+
+  virtual double GenerateFirstOrderPhaseOutputImages(vtkImageData* inreal,vtkImageData* inimag,
+						    vtkImageData* outreal,vtkImageData* outimag,
+						    vtkDoubleArray* p1);
+
+  virtual double GenerateZeroAndFirstOrderPhaseOutputImages(vtkImageData* inreal,vtkImageData* inimag,
+							   vtkImageData* outreal,vtkImageData* outimag,
+							   vtkDoubleArray* p0,
+							   vtkDoubleArray* p1);
+
+  virtual void GenerateInputs(vtkImageData* real,vtkImageData* imag, vtkImageData* outreal,vtkImageData* outimag);
+};
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxProcessFmri.cpp b/bioimagesuite30_src/Imaging/vtkpxProcessFmri.cpp
new file mode 100644
index 0000000..3eefbe8
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxProcessFmri.cpp
@@ -0,0 +1,431 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxProcessFmri.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/08/16 15:24:36 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkImageFlip.h"
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkpxProcessFmri.h"
+#include "vtkpxUtil.h"
+#include <vtkImageShiftScale.h> 
+#include <vtkLineSource.h>
+#include <vtkPolyData.h>
+#include <vtkMath.h>
+#include <vtkbisImageReslice.h>
+#include <vtkTransform.h>
+#include <vtkDataArray.h>
+#include <vtkFloatArray.h>
+//------------------------------------------------------------------------------
+vtkpxProcessFmri* vtkpxProcessFmri::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxProcessFmri");
+  if(ret)
+    {
+    return (vtkpxProcessFmri*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxProcessFmri;
+}
+
+// Construct object with no children.
+vtkpxProcessFmri::vtkpxProcessFmri()
+{
+  this->Activations=NULL;
+  this->ScaleFactor=1000.0;
+  this->IntensityRescaling=1;
+  this->FlipLeftRight=1;
+}
+// ----------------------------------------------------------------------------
+vtkpxProcessFmri::~vtkpxProcessFmri()
+{
+  if (this->Activations!=NULL)
+    {
+      this->Activations->UnRegister(this);
+      this->Activations=NULL;
+    }
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxProcessFmri::SetActivations(vtkDataArray* act)
+{
+  if (this->Activations != NULL )
+    this->Activations->UnRegister(this);
+  
+  this->Activations=act;
+  if (this->Activations!=NULL)
+    this->Activations->Register(this);
+}
+// ----------------------------------------------------------------------------
+void vtkpxProcessFmri::ExecuteInformation()
+{
+  vtkImageData *input=this->GetImageDataInput(0);
+
+  if (input==NULL)
+      {
+	vtkErrorMacro(<<"No Input FMRI Data !!");
+	return;
+      }
+
+  vtkImageData *output=this->GetOutput();
+
+  vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  output->SetNumberOfScalarComponents(1);
+  output->SetScalarType(VTK_SHORT);
+}
+
+// ----------------------------------------------------------------------------
+void vtkpxProcessFmri::CheckActivationSeries(vtkDataArray* act,int timeframes,
+					     float& Numbaseline,float& Numactivation)
+{
+
+  Numbaseline=0.0;
+  Numactivation=0.0;
+  for (int tm=0;tm<timeframes;tm++)
+    {
+      int v=(int)act->GetComponent(tm,0);
+      if (v==0)
+	Numbaseline+=1.0;
+      else if (v==1)
+	Numactivation+=1.0;
+    }
+
+  if (Numbaseline<1 || Numactivation<1)
+    {
+      vtkErrorMacro(<<"Bad activation scalars ("<<Numbaseline<<","<<Numactivation<<")\n");
+      return;
+    }
+  vtkDebugMacro(<<"Activation scalars ("<<Numbaseline<<","<<Numactivation<<")\n");
+
+}
+
+// ----------------------------------------------------------------------------
+
+void vtkpxProcessFmri::NormalizeIntensity(vtkImageData* input,vtkImageData* output,
+					  float newmean)
+{
+
+  int dim[3];   input->GetDimensions(dim);
+  
+  output->SetSpacing(input->GetSpacing());
+  output->SetOrigin(input->GetOrigin());
+  output->SetScalarType(VTK_SHORT);
+  output->SetNumberOfScalarComponents(1);
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  output->AllocateScalars();
+  vtkDataArray* outScal=output->GetPointData()->GetScalars();
+  vtkDataArray* inScal=input->GetPointData()->GetScalars();
+ 
+  int slicesize=dim[0]*dim[1];
+  for (int sl=0;sl<dim[2];sl++)
+    {
+      int offset=sl*slicesize;
+      float sum=0.0;
+      for (int pixel=0;pixel<slicesize;pixel++)
+	sum+=inScal->GetComponent(offset+pixel,0);
+      sum/=float(slicesize);
+	    
+      if (sum==0.0)
+	sum=1.0;
+
+      float scale=newmean/sum;
+
+      float newsum=0.0;
+      for (int px=0;px<slicesize;px++)
+	{
+	  int index=offset+px;
+	  float v=scale*inScal->GetComponent(index,0);
+	  newsum+=v;
+	  outScal->SetComponent(index,0,v);
+	}
+
+      newsum/=float(slicesize);
+    }
+}
+// ----------------------------------------------------------------------------
+
+
+void vtkpxProcessFmri::SimpleExecute(vtkImageData* input,vtkImageData *output)
+{
+  if (this->Activations==NULL)
+      {
+	vtkErrorMacro(<<"No Activation Scalars Supplied\n");
+	return;
+      }
+
+  int numtimeframes=input->GetNumberOfScalarComponents();
+  int dim[3];
+  input->GetDimensions(dim);
+
+  if (this->Activations->GetNumberOfTuples()<numtimeframes)
+      {
+	vtkErrorMacro(<<"Not Enough Activation Scalars Supplied ");
+	vtkErrorMacro(<< this->Activations->GetNumberOfTuples()<<" <" <<numtimeframes<< "\n");
+	return;
+      }
+  
+  // Create Output Array
+  // -------------------
+  this->UpdateProgress(0.01);
+  float oldpog=0.00;
+
+
+  // First Check Activation Series 
+  float Numbaseline=0.0,Numactivation=0.0;
+  this->CheckActivationSeries(this->Activations,numtimeframes,Numbaseline,Numactivation);
+
+  vtkImageData* fmriData=this->GetImageDataInput(0);
+  if (this->IntensityRescaling)
+    {
+      // Normalize all slices to have mean 1200 for some reason of Todd's crafting
+      fmriData=vtkImageData::New();
+      vtkpxProcessFmri::NormalizeIntensity(this->GetImageDataInput(0),fmriData,1200.0);
+      oldpog=0.4;
+      this->UpdateProgress(oldpog);
+    }
+
+
+  output->SetSpacing(this->GetImageDataInput(0)->GetSpacing());
+  output->SetOrigin(this->GetImageDataInput(0)->GetOrigin());
+  output->SetScalarType(VTK_SHORT);
+  output->SetNumberOfScalarComponents(1);
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  output->AllocateScalars();
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* fmriScalars=fmriData->GetPointData()->GetScalars();
+  
+  int slicesize=dim[0]*dim[1];
+  for (int sl=0;sl<dim[2];sl++)
+    {
+      for (int i=0;i<dim[0];i++)
+	{
+	  int outi=i;
+	  if (this->FlipLeftRight)
+	    outi=(dim[0]-1)-i;
+	  for (int j=0;j<dim[1];j++)
+	    {
+	      int bpixel=j*dim[0];
+	      int pixel=bpixel+i;
+	      int outpixel=bpixel+outi;
+	      float sumbase=0.0,sum2base=0.0,sumact=0.0,sum2act=0.0;
+	      
+	      int   readindex =pixel+sl*slicesize;
+	      int   writeindex=outpixel+sl*slicesize;
+	      
+	      for (int tm=0;tm<numtimeframes;tm++)
+		{
+
+		  float val=fmriScalars->GetComponent(readindex,tm);
+		  int   act=(int)Activations->GetComponent(tm,0);
+		 	  
+		  if (act==0)
+		    {
+		      sumbase+=val;
+		      sum2base+= (val*val);
+		    }
+		  else if (act==1)
+		    {
+		      sumact+=val;
+		      sum2act+= (val*val);
+		    }
+		}
+
+	      
+	      float meanbase  =sumbase  /Numbaseline;
+	      float meanact   =sumact   /Numactivation;
+	      
+	      float mean2base =sum2base /Numbaseline;
+	      float mean2act  =sum2act  /Numactivation;
+	      
+	      float sigmabase=sqrt(mean2base-meanbase*meanbase);
+	      float sigmaact =sqrt(mean2act -meanact*meanact);
+	      
+	      float tsigma=0.5*(sigmabase+sigmaact);
+	      
+	      if (tsigma<0.00001)
+		  tsigma=0.00001;
+	      
+
+	      int  tvalue=int(0.5+this->ScaleFactor*(meanact-meanbase)/tsigma);
+	      out->SetComponent(writeindex,0,float(tvalue));
+	    }
+	}
+      float pog=(0.4+0.6*float(sl)/float(dim[2]));
+      if (pog-oldpog>0.1)
+	{
+	  this->UpdateProgress(pog);	
+	  oldpog=pog;
+	}
+      
+    }
+  
+  this->UpdateProgress(oldpog+0.5);
+  this->UpdateProgress(1.0);
+
+  if (this->IntensityRescaling)
+    fmriData->Delete();
+}
+
+// -------------------------------------------------------------------------------------------
+//     GUI Support Functions for handling activations as stings of ranges 
+// -------------------------------------------------------------------------------------------
+void addScalars(vtkDataArray* scal,int num,char* specs,int val,int tshift)
+{
+  if (scal==NULL || specs==NULL || num<2)
+    return;
+  
+  char* out=strtok(specs," ");  
+  for (int i=0;i<num/2;i++)
+    {
+      int begin=0,end=0;
+      if (out!=NULL)
+	begin=atoi(out)+tshift;
+      out=strtok(NULL," ");
+      if (out!=NULL)
+	end=atoi(out)+tshift;
+      
+      //fprintf(stderr,"Setting values %d:%d as %d\n",begin,end,val);
+      for (int j=begin-1;j<end;j++)
+	{
+	  if (j<scal->GetNumberOfTuples() && j>=0)
+	    scal->SetComponent(j,0,val);
+	}
+      out=strtok(NULL," ");
+    }
+}
+// ----------------------------------------------------------------------------------------------
+void vtkpxProcessFmri::CreatePolyDataFromScalars(vtkDataArray* activations,vtkPolyData* polydata)
+{
+  if (polydata==NULL || activations==NULL)
+      return;
+
+  int frames=activations->GetNumberOfTuples();
+
+  vtkLineSource* linesource=vtkLineSource::New();
+  linesource->SetResolution(frames);
+  linesource->SetPoint1(0.0, 0.0,  0.0);
+  linesource->SetPoint2(1.0, 0.0,  0.0);
+  linesource->Update();
+
+  polydata->CopyStructure(linesource->GetOutput());
+  linesource->Delete();
+  
+  vtkFloatArray* tmpScalars=vtkFloatArray::New();
+  tmpScalars->SetNumberOfTuples(frames +1);
+  tmpScalars->SetComponent(0,0,0.5);
+
+  for (int k=1;k<=frames;k++)
+      {
+	float val=activations->GetComponent(k-1,0);
+	if (val<0.0)
+	    val=0.5;
+	tmpScalars->SetComponent(k,0,val);
+      }
+  polydata->GetPointData()->SetScalars(tmpScalars);
+  tmpScalars->Delete();
+
+
+}
+// --------------------------------------------------------------------------------------
+void vtkpxProcessFmri::CreatePolyDataFromScalars(vtkDataArray* activations,vtkPolyData* polydata,float scale)
+{
+  if (polydata==NULL || activations==NULL)
+      return;
+
+  int frames=activations->GetNumberOfTuples();
+
+  vtkLineSource* linesource=vtkLineSource::New();
+  linesource->SetResolution(frames);
+  linesource->SetPoint1(0.0, 0.0,  0.0);
+  linesource->SetPoint2(1.0, 0.0,  0.0);
+  linesource->Update();
+
+  polydata->CopyStructure(linesource->GetOutput());
+  linesource->Delete();
+  
+  vtkFloatArray* tmpScalars=vtkFloatArray::New();
+  tmpScalars->SetNumberOfTuples(frames +1);
+  tmpScalars->SetComponent(0,0,0.0);
+
+  for (int k=1;k<=frames;k++)
+      {
+	float val=activations->GetComponent(k-1,0);
+	tmpScalars->SetComponent(k,0,val*scale);
+      }
+  polydata->GetPointData()->SetScalars(tmpScalars);
+  tmpScalars->Delete();
+
+}
+// --------------------------------------------------------------------------------------
+void vtkpxProcessFmri::ProcessScalars(vtkDataArray* activations,int frames,int tshift,
+				      int numact,char* act,
+				      int numbase,char* base)
+{
+  if (activations==NULL)
+      return;
+
+  activations->SetNumberOfTuples(frames);
+  for (int i=0;i<frames;i++)
+      activations->SetComponent(i,0,-1);
+
+  char longline[300];
+  strncpy(longline,act,300);   addScalars(activations,numact,longline,1,tshift);
+  strncpy(longline,base,300);  addScalars(activations,numbase,longline,0,tshift);
+
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxProcessFmri.h b/bioimagesuite30_src/Imaging/vtkpxProcessFmri.h
new file mode 100644
index 0000000..d520934
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxProcessFmri.h
@@ -0,0 +1,132 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxProcessFmri.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 19:13:42 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxProcessFmri -- creates activation maps from raw fmri data
+// .SECTION Description
+// This class takes a number of fmri image series and a description of activations
+// and generates t-maps of the activation.
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxProcessFmri_h
+#define __vtkpxProcessFmri_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkPolyData;
+class vtkDataArray;
+
+class vtkpxProcessFmri : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxProcessFmri *New();
+  vtkTypeMacro(vtkpxProcessFmri,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Sets the activation black diagram for input=0 (If others are NULL this is used for all inputs)
+  virtual void SetActivations(vtkDataArray* act);
+
+  // Description:
+  // Set value of scalefactor to multiply t-values
+  vtkGetMacro(ScaleFactor,float);
+  vtkSetMacro(ScaleFactor,float);
+
+  // Description:
+  // Enable IntensityRescaling of each slice to have the same mean
+  vtkGetMacro(IntensityRescaling,int);
+  vtkSetMacro(IntensityRescaling,int);
+
+  // Description:
+  // Enable Right/Left Flip of Output
+  vtkGetMacro(FlipLeftRight,int);
+  vtkSetMacro(FlipLeftRight,int);
+
+  // BTX
+  static void ProcessScalars(vtkDataArray* activations,int frames,int tshift,
+			     int numact,char* activ,
+			     int numbase,char* base);
+  static void CreatePolyDataFromScalars(vtkDataArray* activations,vtkPolyData* polydata);
+  // ETX
+  static void CreatePolyDataFromScalars(vtkDataArray* activations,vtkPolyData* polydata,float scale);
+
+
+  // Description:
+  // MR Intensity Gain Estimation and Re-Normalization
+  static void NormalizeIntensity(vtkImageData* input,vtkImageData* output,float newmean);
+  
+protected:
+
+  vtkpxProcessFmri();
+  virtual ~vtkpxProcessFmri();
+  vtkpxProcessFmri(const vtkpxProcessFmri&) {};
+  void operator=(const vtkpxProcessFmri&) {};
+
+  void SimpleExecute(vtkImageData*,vtkImageData*);
+  void ExecuteInformation();
+
+  vtkDataArray* Activations;
+  float       ScaleFactor;
+  int         IntensityRescaling;
+  int         FlipLeftRight;
+
+
+  void CheckActivationSeries(vtkDataArray* act,int timeframes,float& Numbaseline,float& Numactivation);
+
+  
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxProcessRawBrukerFIDImage.cpp b/bioimagesuite30_src/Imaging/vtkpxProcessRawBrukerFIDImage.cpp
new file mode 100644
index 0000000..30e97b1
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxProcessRawBrukerFIDImage.cpp
@@ -0,0 +1,1008 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxProcessRawBrukerFIDImage.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxProcessRawBrukerFIDImage.h"
+#include "vtkpxUtil.h"
+#include "vtkImageRFFT.h"
+#include "vtkImageFFT.h"
+#include "vtkImageFourierCenter.h"
+#include "vtkImageShiftScale.h"
+#include "vtkImageCast.h"
+#include "vtkpxImagePolarToEuclidean.h"
+#include "vtkpxImageExtract.h"
+#include "vtkbisImageReslice.h"
+#include "vtkImagePermute.h"
+#include "vtkTransform.h"
+#include "pxutil.h"
+#include "vtkpxImageAddPhaseCorrection.h"
+#include "vtkpxMatrix.h"
+#include "vtkpxMath.h"
+#include "vtkImageMedian3D.h"
+
+#ifndef M_PI
+#define M_PI 3.1415926854
+#endif
+
+//------------------------------------------------------------------------------
+vtkpxProcessRawBrukerFIDImage* vtkpxProcessRawBrukerFIDImage::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxProcessRawBrukerFIDImage");
+  if(ret)
+    {
+    return (vtkpxProcessRawBrukerFIDImage*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxProcessRawBrukerFIDImage;
+}
+
+// Construct object with no children.
+vtkpxProcessRawBrukerFIDImage::vtkpxProcessRawBrukerFIDImage()
+{
+  this->EchoPlanarMode=0;
+  this->PolarComplexMode=1;
+  this->ShiftSpectrum=1;
+  this->ConventionalAppendMultiSliceMode=0;
+}
+// ----------------------------------------------------------------------------
+void vtkpxProcessRawBrukerFIDImage::ExecuteInformation()
+{
+  vtkImageData *input=this->GetImageDataInput(0);
+
+  if (input==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+
+  vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+  output->SetScalarType(VTK_FLOAT);
+}
+
+
+void vtkpxProcessRawBrukerFIDImage::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  vtkImageData* tmp=vtkImageData::New();
+  tmp->CopyStructure(input);
+  int numscalars=input->GetNumberOfScalarComponents();
+
+  // If multi-echo put echos last to make slices 
+  if (numscalars!=2)
+    {
+      int dim[3]; input->GetDimensions(dim);
+      tmp->SetDimensions(dim[0],dim[1],dim[2]*(numscalars/2));
+      tmp->SetNumberOfScalarComponents(2);
+      tmp->AllocateScalars();
+      vtkpxProcessRawBrukerFIDImage::ReOrderMultipleEchos(input,tmp);
+    }
+  else
+    {
+      tmp->AllocateScalars();
+    }
+
+  
+  if (this->EchoPlanarMode==0)
+    {
+      if (this->ConventionalAppendMultiSliceMode==1)
+	{
+	  vtkDebugMacro(<<"Simple Deep Copy\n");
+	  output->DeepCopy(input);
+	}
+      else
+	{
+	  vtkpxProcessRawBrukerFIDImage::ConvertConventional(input,tmp);
+	  vtkDebugMacro(<<"Convert Conventional\n");
+	}
+    }
+  else
+    {
+      vtkDebugMacro(<<"Convert Echoplanar\n");
+      vtkpxProcessRawBrukerFIDImage::ConvertEchoPlanar(input,tmp);
+    }
+  
+  if (this->PolarComplexMode)
+    {
+      vtkDebugMacro(<<"IFFT\n");
+      vtkpxProcessRawBrukerFIDImage::PerformInverseFourierTransform(tmp,output,this->ShiftSpectrum);
+    }
+  else
+    {
+      vtkImageCast* cast=vtkImageCast::New();
+      cast->SetInput(tmp);
+      cast->SetOutputScalarTypeToFloat();
+      cast->Update();
+
+      if (this->ShiftSpectrum)
+	{
+	  vtkImageData* tmp2=vtkImageData::New();
+	  vtkDebugMacro(<<"Shift Spectrum\n");
+	  vtkpxProcessRawBrukerFIDImage::DoShiftSpectrum(cast->GetOutput(),tmp2);
+	  output->ShallowCopy(tmp2);
+	  tmp2->Delete();
+	}
+      else
+	{
+	  output->ShallowCopy(cast->GetOutput());
+	}
+
+      cast->Delete();
+    }
+
+  tmp->Delete();
+
+}
+// ----------------------------------------------------------------------------
+int vtkpxProcessRawBrukerFIDImage::ConvertConventional(vtkImageData* input,vtkImageData* output)
+{
+  
+  vtkIntArray* out=(vtkIntArray*)output->GetPointData()->GetScalars();
+  vtkIntArray* inp=(vtkIntArray*)input ->GetPointData()->GetScalars();
+
+  int* in=(int*)inp->GetVoidPointer(0);
+  int* ou=(int*)out->GetVoidPointer(0);
+
+
+  int dim[3];
+  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+
+  int outindex=0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      {
+	int inindex=2*(j*dim[2]+k)*dim[0];
+	for (int i=0;i<dim[0];i++)
+	  for (int c=0;c<nc;c++)
+	    {
+	      ou[outindex]=in[inindex];
+	      ++outindex;
+	      ++inindex;
+	    }
+      }
+
+  return 1;
+}
+// ---------------------------------------------------------------------------- 
+int vtkpxProcessRawBrukerFIDImage::ConvertEchoPlanar(vtkImageData* input,vtkImageData*output)
+{
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* inp=input ->GetPointData()->GetScalars();
+
+  int* in=(int*)inp->GetVoidPointer(0);
+  int* ou=(int*)out->GetVoidPointer(0);
+
+  int dim[3];
+  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+  int slicesize=dim[0]*dim[1];
+
+  int revi=0;
+  int half=dim[2]/2;
+  if (half*2<dim[2])
+    half+=1;
+
+  for (int k=0;k<dim[2];k++)
+    {
+      int outslice=0;
+      if (k<half)
+	outslice=k*2;
+      else
+	outslice=(k-half)*2+1;
+
+      for (int j=0;j<dim[1];j++)
+	{
+	  for (int ti=0;ti<dim[0];ti++)
+	    {
+	      int i=ti;
+	      if (revi==1)
+		i=dim[0]-1-ti;
+	      for (int c=0;c<nc;c++)
+		{
+		  int outindex=2*(outslice*slicesize+j*dim[0]+i)+c;
+		  int inpindex=2*(k*slicesize+j*dim[0]+ti)+c;
+		  ou[outindex]=in[inpindex];
+		  //out->SetComponent(outindex,c,inp->GetComponent(inpindex,c));
+		}
+	    }
+	  revi=1-revi;
+	}
+    }
+  return 1;
+}
+// ----------------------------------------------------------------------------
+int vtkpxProcessRawBrukerFIDImage::PerformInverseFourierTransform(vtkImageData* input,
+								  vtkImageData*output,int shiftspectrum)
+{
+  vtkImageCast* cast=vtkImageCast::New();
+  cast->SetInput(input);
+  cast->SetOutputScalarTypeToFloat();
+  cast->Update();
+
+  vtkImageRFFT* rfft=vtkImageRFFT::New();
+  rfft->SetDimensionality(2);
+
+  if (shiftspectrum)
+    {
+      vtkImageData* tmp=vtkImageData::New();
+      vtkpxProcessRawBrukerFIDImage::DoShiftSpectrum(cast->GetOutput(),tmp); 
+      rfft->SetInput(tmp);
+      tmp->Delete();
+    }
+  else
+    rfft->SetInput(cast->GetOutput());
+
+
+  vtkTransform* tr=vtkTransform::New();
+  double sp[3];  input->GetSpacing(sp);
+  int   dim[3]; input->GetDimensions(dim);
+  tr->Identity();
+  tr->Translate(0.5*dim[0]*sp[0],0.5*dim[1]*sp[1],0);
+      
+  vtkbisImageReslice* resl=vtkbisImageReslice::New(); resl->OptimizationOff();
+  resl->SetInput(rfft->GetOutput());
+  resl->SetInformationInput(input);
+  resl->SetResliceTransform(tr);
+  tr->Delete();
+  resl->WrapOn();
+  resl->SetInterpolationMode(0);
+  
+
+  vtkpxImagePolarToEuclidean* pol=vtkpxImagePolarToEuclidean::New();
+  pol->SetInput(resl->GetOutput());
+  pol->SetInverse(1);
+  pol->Update();
+  output->ShallowCopy(pol->GetOutput());
+
+  pol->Delete();
+  resl->Delete();
+  rfft->Delete();
+  cast->Delete();
+
+
+  return 1;
+}
+
+// ----------------------------------------------------------------------------
+int vtkpxProcessRawBrukerFIDImage::DoShiftSpectrum(vtkImageData* input,vtkImageData* output)
+{
+  int dim[3];
+  input->GetDimensions(dim);
+
+  output->CopyStructure(input);
+  output->AllocateScalars();
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  for (int sl=0;sl<dim[2];sl++)
+    {
+      float maxmagn=0.0;
+      int i=0,j=0,besti=0,bestj=0;
+      
+      for (j=0;j<dim[1];j++)
+	for (i=0;i<dim[0];i++)
+	  {
+	    float re=input->GetScalarComponentAsDouble(i,j,sl,0);
+	    float im=input->GetScalarComponentAsDouble(i,j,sl,1);
+	    float magn=re*re+im*im;
+	    if (magn>maxmagn)
+	      {
+		maxmagn=magn;
+		besti=i;
+		bestj=j;
+	      }
+	  }
+      
+      /*besti=0;
+	bestj=0;*/
+	  
+      int index=sl*dim[0]*dim[1];
+      for (j=0;j<dim[1];j++)
+	{
+	  int oj=Icyclic(j+bestj,dim[1]);
+	  
+	  for (i=0;i<dim[0];i++)
+	    {
+	      int oi=Icyclic(i+besti,dim[0]);
+	      float a=input->GetScalarComponentAsDouble(oi,oj,sl,0);
+	      float b=input->GetScalarComponentAsDouble(oi,oj,sl,1);
+	      out->SetComponent(index,0,a);
+	      out->SetComponent(index,1,b);
+	      ++index;
+	    }
+	}
+    }
+
+  /*if (this->EchoPlanarMode)
+    vtkpxImageAddPhaseCorrection::DoGhostCorrection(output,0.25);*/
+
+  return 1;
+}
+// ----------------------------------------------------------------------------
+int vtkpxProcessRawBrukerFIDImage::ReOrderMultipleEchos(vtkImageData* input,vtkImageData* output)
+{
+  vtkIntArray* out=(vtkIntArray*)output->GetPointData()->GetScalars();
+  vtkIntArray* inp=(vtkIntArray*)input ->GetPointData()->GetScalars();
+
+  int* in=(int*)inp->GetVoidPointer(0);
+  int* ou=(int*)out->GetVoidPointer(0);
+
+  int dim[3];
+  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+
+  int nechos=nc/2;
+
+  fprintf(stderr,"In Order Echoes dim=%dx%dx%d nc=%d (%d)\n",dim[0],dim[1],dim[2],nc,nechos);
+
+  
+  int slicesize=dim[0]*dim[1];
+  int volsize=slicesize*dim[2];
+
+  int inindex=0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  int outindex= k*slicesize+j*dim[0]+i;
+	  
+	  for (int echo=0;echo<nechos;echo++)
+	    {
+	      for (int c=0;c<2;c++)
+		{
+		  ou[outindex]=in[inindex];
+		  ++outindex;
+		  ++inindex;
+		}
+	      outindex+=volsize;
+	    }
+	}
+  return 1;
+}
+
+// ----------------------------------------------------------------------------
+void vtkpxProcessRawBrukerFIDImage::FitFIDIntoGnuplot(char* fname1,char* fname2,int width,int height,int depth,int components)
+{
+  gzFile fp=gzsuffixopen(fname1,"rb");//FILE* fp = fopen(fname1,"rb");
+  if ( !fp)
+    {
+      fprintf(stderr,"Cannot Open File %s\n", fname1 );
+      return;
+    }
+  
+  fprintf(stderr,"Size of long = %d\n",sizeof(long));
+
+  int numelements=2*width*height*depth*components;
+  long* data=new long[numelements];
+  //fread(&data[0],sizeof(long),numelements,fp);
+  //fclose(fp);
+  gzread(fp,&data[0],sizeof(long)*numelements);
+  gzclose(fp);
+
+  FILE* fout=fopen(fname2,"w");
+  fprintf(fout,"# ZIndex \t Components \n");
+  for (int k=0;k<numelements;k+=2)
+    fprintf(fout,"%d %d %d %f",k,(int)data[k],(int)data[k+1],(float)sqrt(float(data[k]*data[k]+data[k+1]*data[k+1])));
+
+  fclose(fout);
+  delete [] data;
+}
+
+vtkImageData* vtkpxProcessRawBrukerFIDImage::ReadFIDSpectrum(char* fname,int width,int height,int sliceno,int depth,int components)
+{
+  //FILE* fp = fopen(fname,"rb");
+  gzFile fp = gzsuffixopen(fname,"rb");
+  if ( !fp)
+    {
+      fprintf(stderr,"Cannot Open File %s\n", fname );
+      return NULL;
+    }
+  
+  fprintf(stderr,"Size of long = %d\n",sizeof(long));
+
+  int numelements=2*width*height*depth*components;
+  long* data=new long[numelements];
+  /*  int np=fread(&data[0],sizeof(long),numelements,fp);
+      fclose(fp);*/
+  int np=gzread(fp,&data[0],sizeof(long)*numelements);
+  gzclose(fp);
+
+
+  fprintf(stderr,"np=%d numelements=%d  bytes=%d\n",np,numelements,np*sizeof(long));
+
+  int depth_components=depth*components;
+  int depth_components_width=depth_components*width;
+
+  fprintf(stderr,"Read %d values (%d)\n",np,numelements);
+
+  vtkImageData* img=vtkImageData::New();
+  img->SetScalarTypeToFloat();
+  img->SetNumberOfScalarComponents(2);
+  img->SetDimensions(width,height,components);
+  img->SetWholeExtent(0,width-1,0,height-1,0,components-1);
+  img->SetExtent(0,width-1,0,height-1,0,components-1);
+  img->SetSpacing(1.0,1.0,float(height)/float(components));
+  img->AllocateScalars();
+
+
+  vtkFloatArray* array=(vtkFloatArray*)(img->GetPointData()->GetScalars());
+
+  fprintf(stderr,"sliceno=%d components=%d depth_components=%d depth_components_width=%d\n",
+	  sliceno,components,depth_components,depth_components_width);
+
+  int index=0;
+  for (int c=0;c<components;c++)
+    for (int j=0;j<height;j++)
+      for (int i=0;i<width;i++)
+	{
+	  int offset= ((components-1)-c) + sliceno*components +  i * depth_components +  j * depth_components_width;
+
+	  offset=2*offset;
+	  array->SetComponent(index,0,data[offset]);
+	  array->SetComponent(index,1,data[offset+1]);
+	  ++index;
+	}
+
+  delete [] data;
+
+  return img;
+}
+
+vtkImageData* vtkpxProcessRawBrukerFIDImage::ProcessFIDSpectrum(char* fname,int width,int height,int sliceno,int depth,
+								int components,float scalefactor)
+{
+  
+  vtkImageData* img=vtkpxProcessRawBrukerFIDImage::ReadFIDSpectrum(fname,width,height,sliceno,depth,components);
+
+  if (img==NULL)
+    return NULL;
+
+  vtkImageFFT* sh=vtkImageFFT::New();
+  sh->SetDimensionality(3);
+  sh->SetInput(img);
+
+  vtkImageFourierCenter* ct2=vtkImageFourierCenter::New();
+  ct2->SetDimensionality(3);
+  ct2->SetInput(sh->GetOutput());
+
+  vtkImageShiftScale* sc=vtkImageShiftScale::New();
+  sc->SetInput(ct2->GetOutput());
+  sc->SetScale(scalefactor);
+  sc->Update();
+
+  vtkImageData* output=vtkpxProcessRawBrukerFIDImage::PhaseCorrection(sc->GetOutput(),2.0,0.0);
+
+  sc->Delete();
+  ct2->Delete();
+  sh->Delete();
+  img->Delete();
+
+  return output;
+
+
+}
+
+
+int vtkpxProcessRawBrukerFIDImage::PlotImageComponentToGnuplot(vtkImageData* image,int x,int y,char* output)
+{
+  FILE* fout=fopen(output,"w");
+  if (fout==NULL)
+    return 0;
+
+  int dim[3]; image->GetDimensions(dim);
+
+  fprintf(fout,"# ZIndex \t Components \n");
+  for (int k=0;k<dim[2];k++)
+    {
+      fprintf(fout,"%d ",k);
+      for (int c=0;c<image->GetNumberOfScalarComponents();c++)
+	fprintf(fout,"%.3f ",image->GetScalarComponentAsDouble(x,y,k,c));
+      fprintf(fout,"\n");
+    }
+
+  fclose(fout);
+  return 1;
+}
+
+int vtkpxProcessRawBrukerFIDImage::ReadFIDSpectrumAndSpitIntoFile(char* fname,char* outname,int width,int height,int depth,int components)
+{
+  gzFile fp = gzsuffixopen(fname,"rb");//  FILE* fp = fopen(fname,"rb");
+  if ( !fp)
+    {
+      fprintf(stderr,"Cannot Open File %s\n", fname );
+      return 0;
+    }
+  
+  fprintf(stderr,"Size of long = %d\n",sizeof(long));
+  
+  int numelements=2*width*height*depth*components;
+  long* data=new long[numelements];
+  /*  int np=fread(&data[0],sizeof(long),numelements,fp);
+      fclose(fp);*/
+  int np=gzread(fp,&data[0],sizeof(long)*numelements);
+  gzclose(fp);
+
+
+  fprintf(stderr,"np=%d numelements=%d  bytes=%d\n",np,numelements,np*sizeof(long));
+
+  FILE* fout=fopen(outname,"w");
+  for (int i=0;i<numelements;i+=2)
+    fprintf(fout,"%d %d %d\n",i/2,(int)data[i],(int)data[i+1]);
+  fclose(fout);
+      
+  return 1;
+
+}
+
+
+vtkImageData* vtkpxProcessRawBrukerFIDImage::PhaseCorrection(vtkImageData* complexinput,float theta,float theta2)
+{
+  vtkImageData* output=vtkImageData::New();
+  output->DeepCopy(complexinput);
+
+  int dim[3]; output->GetDimensions(dim);
+
+  vtkFloatArray* data=(vtkFloatArray*)output->GetPointData()->GetScalars();
+
+  int index=0;
+  
+  float t1=theta;
+  float t2=theta2;
+
+  fprintf(stderr,"t1=%.2f, t2=%.2f (theta=%.2f,theta2=%.2f)\n",t1,t2,theta,theta2);
+
+  for (int k=0;k<dim[2];k++)
+    {
+      float offset =t1*float(k);
+      float offset2=t2;
+
+      if (k==dim[2]/2)
+	fprintf(stderr,"Offsets = %f %f\n",offset,offset2);
+
+      for (int i=0;i<dim[0];i++)
+	for (int j=0;j<dim[1];j++)
+	  {
+	    float X = data->GetComponent(index,0);
+	    float Y = data->GetComponent(index,1);
+	    
+	    float Theta = atan2(Y, X);
+	    float R = sqrt(X*X + Y*Y);
+	      
+	    float Theta2= Theta + offset + offset2;
+	    float X2=R*cos(Theta2);
+	    float Y2=R*sin(Theta2);
+	      
+	    data->SetComponent(index,0,X2);
+	    data->SetComponent(index,1,Y2);
+
+	    /*	    if (i==16 && j==16 && k==256)
+	      {
+		fprintf(stderr,"X=%f Y=%f --> (R=%f,T=%.f + %.f -->%f) --> X2=%f Y2=%f   magn=%.2f\n",
+			X,Y,R,Theta,offset,Theta2,X2,Y2,sqrt(X2*X2+Y2*Y2));
+			}*/
+  
+	    ++index;
+	  }
+    }
+
+  return output;
+}
+
+float vtkpxProcessRawBrukerFIDImage::AutoPhaseCorrection(vtkImageData* complexinput)
+{
+  int dim[3]; complexinput->GetDimensions(dim);
+
+  int midi=dim[0]/2+1;
+  int midj=dim[1]/2+1;
+  float maxmagn=0.0;
+  float sumreal=0.0,sumimag=0.0;
+  int bestk=dim[2]/2;
+
+  for (int k=0;k<dim[2];k++)
+    {
+      
+      float v1=complexinput->GetScalarComponentAsDouble(midi,midj,k,0);
+      sumreal+=v1;
+      float v2=complexinput->GetScalarComponentAsDouble(midi,midj,k,1);
+      sumimag+=v2;
+      float magn=v1*v1+v2*v2;
+      
+      if (magn>maxmagn)
+	{
+	  maxmagn=magn;
+	  bestk=k;
+	}
+    }
+
+  fprintf(stderr,"\t\tOffset = %d sums=%.2f,%.2f\n",bestk,sumreal,sumimag);
+
+  return fabs(float(dim[2]/2-bestk));
+
+}
+
+void vtkpxProcessRawBrukerFIDImage::ComputeSums(vtkImageData* img)
+{
+  int dim[3]; img->GetDimensions(dim);
+
+  float sumreal=0.0,sumimag=0.0,sumtail=0.0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  sumreal+=img->GetScalarComponentAsDouble(i,j,k,0);
+	  sumimag+=img->GetScalarComponentAsDouble(i,j,k,1);
+
+	  if (k<dim[2]/8 || k> (4*dim[2])/8)
+	    sumtail+=fabs(img->GetScalarComponentAsDouble(i,j,k,0));
+	}
+
+  fprintf(stderr,"Sumreal = %.2f, Sumimag=%.2f tail=%.2f\n",sumreal,sumimag,sumtail);
+}
+
+vtkImageData* vtkpxProcessRawBrukerFIDImage::CenterPhaseData(vtkImageData* complexinput)
+{
+  vtkImageData* output=vtkImageData::New();
+  output->DeepCopy(complexinput);
+
+  int dim[3]; output->GetDimensions(dim);
+
+  vtkFloatArray* data=(vtkFloatArray*)output->GetPointData()->GetScalars();
+
+  int dim01=dim[0]*dim[1];
+
+  for (int i=0;i<dim[0];i++)
+    for (int j=0;j<dim[1];j++)
+      {
+	int offset=0;
+	float maxR=0.0;
+	for (int k=0;k<dim[2];k++)
+	  {
+	    float X = complexinput->GetScalarComponentAsDouble(i,j,k,0);
+	    float Y = complexinput->GetScalarComponentAsDouble(i,j,k,1);
+	    float R = sqrt(X*X + Y*Y);
+	      
+	    if (R>maxR)
+	      {
+		maxR=R;
+		offset=k-dim[2]/2;
+	      }
+	  }
+
+	if (i>dim[0]/4 && i< 3*dim[0]/4 &&
+	    j>dim[1]/4 && j< 3*dim[1]/4)
+	  fprintf(stderr,"i=%d j=%d; offset=%d (%f)\n",i,j,offset,maxR);
+
+	for (int k2=0;k2<dim[2];k2++)
+	  {
+	    int index=k2*dim01+j*dim[0]+i;
+	    int otherk=k2+offset;
+	    if (otherk>=dim[2])
+	      otherk-=dim[2];
+	    else if (otherk<0)
+	      otherk+=dim[2];
+	    
+	    data->SetComponent(index,0,complexinput->GetScalarComponentAsDouble(i,j,otherk,0));
+	    data->SetComponent(index,1,complexinput->GetScalarComponentAsDouble(i,j,otherk,1));
+	  }
+      }
+  return output;
+}
+// ----------------------------------------------------------------------------
+int vtkpxProcessRawBrukerFIDImage::FitExponentialT2Model(vtkImageData* input,vtkImageData* output,float first,float dt,
+							 int mode,float threshold,float int_threshold,float max_t2)
+{
+  int numechos=input->GetNumberOfScalarComponents();
+
+  output->CopyStructure(input);
+  output->SetScalarTypeToFloat();
+  if (mode==1)
+    output->SetNumberOfScalarComponents(5);
+  else
+    output->SetNumberOfScalarComponents(1);
+  output->AllocateScalars();
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  //  int numechos=6;
+
+  vtkpxMatrix* A=vtkpxMatrix::New();
+  vtkpxMatrix* At=vtkpxMatrix::New();
+  vtkpxMatrix* B=vtkpxMatrix::New();
+  vtkpxMatrix* F=vtkpxMatrix::New();
+
+  A->Ones(numechos,2);
+  At->Ones(2,numechos);
+  for (int i=0;i<numechos;i++)
+    {
+      A->SetElement(i,1,-1.0*(first+float(i)*dt));
+      At->SetElement(1,i,-1.0*(first+float(i)*dt));
+    }
+
+  vtkpxMatrix::Multiply(At,A,B);
+  B->Invert();
+
+  vtkpxMatrix::Multiply(B,At,F);
+
+  A->Zeros(numechos,1);
+  At->Zeros(numechos,1);
+  B->Zeros(2,1);
+
+  int nt=inp->GetNumberOfTuples();
+
+
+  fprintf(stderr,"nt=%d numechos=%d\n",nt,numechos);
+
+  int dim[3]; input->GetDimensions(dim);
+
+
+
+  double range[2]; inp->GetRange(range);
+  int_threshold=int_threshold*(range[1]);
+  int voxel_index=0;
+
+  for (int ic=0;ic<dim[2];ic++)
+    for (int ib=0;ib<dim[1];ib++)
+      for (int ia=0;ia<dim[0];ia++)
+	{
+	  int flag=0;
+
+	  float sigma=0.0;
+	  for (int c=0;c<numechos;c++)
+	    {
+	      float v=Frange(inp->GetComponent(voxel_index,c),1.0,1e+10);
+	      sigma+=fabs(v);
+
+	      A->SetDirectElement(c,0,log(v));
+	      At->SetDirectElement(c,0,v);
+	    }
+	  sigma=sigma/float(numechos);
+	  float sigma2=sigma*sigma;
+
+	  vtkpxMatrix::Multiply(F,A,B);
+	  float loga=B->GetDirectElement(0,0);
+	  float r2=Frange(B->GetDirectElement(1,0),1.0e-7,1.0e+7);
+	  float alpha=exp(loga);
+	  float t2=1.0/r2;
+	 
+	  out->SetComponent(voxel_index,0,Frange(t2,1.0,max_t2));
+	  if (mode==1)
+	    out->SetComponent(voxel_index,1,alpha);
+
+	  float error=0.0;
+	  float chisq=0.0;
+	  
+	  if (flag)
+	    fprintf(stderr,"# alpha=%.f t2=%.2f\n#Echo \t t \t Model \t Data\n",alpha,t2);
+
+
+	  
+	  for (int k=0;k<numechos;k++)
+	    {
+	      float t=first+float(k)*dt;
+	      float model=alpha*exp(-t/t2);
+	      float data=inp->GetComponent(voxel_index,k);
+	      if (flag)
+		fprintf(stderr,"%d \t %.2f \t %.2f \t %.2f\n",k+1,t,model,data);
+	      error+=fabs(model-data);
+	      chisq+=pow(model-data,float(2.0))/sigma2;
+	    }
+
+	  float perror=fabs(100.0*error/(float(numechos)*inp->GetComponent(voxel_index,0)));
+	  if (mode==1)
+	    {
+	      out->SetComponent(voxel_index,2,perror);
+	      out->SetComponent(voxel_index,3,chisq);
+	    }
+
+	  if (flag)
+	    fprintf(stderr,"Single perror (%d,%d,%d) =%f (%5.4f) chisq=%.4f\n",ia,ib,ic,error,perror,chisq);
+
+	  float vp=inp->GetComponent(voxel_index,0);
+	  if (perror>threshold || vp<int_threshold)
+	    out->SetComponent(voxel_index,0,0.0);
+	  
+	  float tor2=out->GetComponent(voxel_index,0);
+	  if (tor2>0.0)
+	    tor2=10000.0/tor2;
+	  out->SetComponent(voxel_index,4,tor2);
+	  ++voxel_index;
+	}
+
+  
+			    
+  A->Delete();
+  At->Delete();
+  B->Delete();
+  F->Delete();
+
+  return 1;
+}
+// ----------------------------------------------------------------------------
+int vtkpxProcessRawBrukerFIDImage::FillMap(vtkImageData* map,vtkImageData* density,float thr,int bimap)
+{
+  vtkImageMedian3D* median=vtkImageMedian3D::New();
+  median->SetKernelSize(3,3,3);
+
+  double range[2]; density->GetPointData()->GetScalars()->GetRange(range);
+  
+  thr=thr*range[1];
+  int nc=map->GetNumberOfScalarComponents();
+  int dim[3]; map->GetDimensions(dim);
+  int done=0,iter=1;
+
+  if (nc<6)
+    bimap=0;
+
+  fprintf(stderr,"Bimap=%d\n",bimap);
+
+  while (done==0 && iter<20)
+    {
+      median->SetInput(map);
+      median->Modified();
+      median->Update();
+      vtkImageData* tmp=median->GetOutput();
+
+      vtkDataArray* inp_array=map->GetPointData()->GetScalars();
+      vtkDataArray* med_array=tmp->GetPointData()->GetScalars();
+      vtkDataArray* den_array=density->GetPointData()->GetScalars();
+
+      int numbad=0,dim10=dim[1]*dim[0];
+      for (int k=1;k<dim[2]-1;k++)
+	for (int j=1;j<dim[1]-1;j++)
+	  {
+	    int index=k*dim10+j*dim[0]+1;
+	    for (int i=1;i<dim[0]-1;i++)
+	      {
+		if (bimap==0)
+		  {
+		    float d=den_array->GetComponent(index,0);
+		    if (d>thr)
+		      {
+			float v=inp_array->GetComponent(index,0);
+			float m=med_array->GetComponent(index,0);
+			if (v<1.0 && m>=1.0)
+			  {
+			    for (int comp=0;comp<nc;comp++)
+			      inp_array->SetComponent(index,comp,med_array->GetComponent(index,comp));
+			    ++numbad;
+			  }
+		      }
+		  }
+		else
+		  {
+		    float d=den_array->GetComponent(index,0);
+		    if (d>thr)
+		      {
+			float v=inp_array->GetComponent(index,5);
+			float m=med_array->GetComponent(index,5);
+			if (v<1.0 && m>=1.0)
+			  {
+			    for (int comp=4;comp<=5;comp++)
+			      inp_array->SetComponent(index,comp,med_array->GetComponent(index,comp));
+
+			    inp_array->SetComponent(index,0,med_array->GetComponent(index,4));
+			    inp_array->SetComponent(index,1,med_array->GetComponent(index,5));
+			    inp_array->SetComponent(index,2,med_array->GetComponent(index,4));
+			    inp_array->SetComponent(index,3,0.0);
+			    ++numbad;
+			  }
+		      }
+		  }
+		++index;
+	      }
+	  }
+      fprintf(stderr,"End of Iteration %d numbad=%d\n",iter,numbad);
+      ++iter;
+      if (numbad==0)
+	done=1;
+    }
+  median->Delete();
+  return 1;
+}
+// ----------------------------------------------------------------------------
+vtkImageData* vtkpxProcessRawBrukerFIDImage::GenerateSyntheticData(float d1,float d2,float t1,float t2,
+								    float dte,int numechos,float noise)
+{
+  vtkImageData* img=vtkImageData::New();
+  img->SetScalarTypeToFloat();
+  img->SetNumberOfScalarComponents(numechos);
+  img->SetDimensions(100,100,1);
+  img->SetWholeExtent(0,99,0,99,0,0);
+  img->SetExtent(0,99,0,99,0,0);
+  img->SetSpacing(1.0,1.0,1.0);
+  img->AllocateScalars();
+  vtkFloatArray* array=(vtkFloatArray*)(img->GetPointData()->GetScalars());
+
+  for (int c=0;c<numechos;c++)
+    array->FillComponent(c,0.0);
+
+
+
+  int index=0;
+  for (int j=0;j<100;j++)
+    {
+      int a=int(j/10);
+      float w=float(a)*0.1;
+      float dw=1.0-w;
+      for (int i=0;i<100;i++)
+	{
+	  for (int k=0;k<numechos;k++)
+	    {
+	      float t=float(k+1)*dte;
+	      float v1=d1*exp(-t/t1);
+	      float v2=d2*exp(-t/t2);
+	      float n=noise*vtkpxMath::GaussianRandom();
+
+	      float v=w*v1+dw*v2+n;
+	      if (v<0.0)
+		v=0.0;
+	      array->SetComponent(index,k,v);
+
+	      if (i==50 && ( j==50 || j==0 ))
+		fprintf(stderr,"i=%d j=%d t=%.2f v1=%.2f v2=%.2f n=%.2f w=%.2f dw=%.2f v=%.2f\n",
+			i,j,t,v1,v2,n,w,dw,v);
+	      
+	    }
+	  ++index;
+	}
+    }
+
+  return img;
+}
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxProcessRawBrukerFIDImage.h b/bioimagesuite30_src/Imaging/vtkpxProcessRawBrukerFIDImage.h
new file mode 100644
index 0000000..8049f7b
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxProcessRawBrukerFIDImage.h
@@ -0,0 +1,152 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxProcessRawBrukerFIDImage.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxProcessRawBrukerFIDImage -- compute phase/magnitude from raw reconstruction image on Bruker
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxProcessRawBrukerFIDImage_h
+#define __vtkpxProcessRawBrukerFIDImage_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkIntArray.h"
+
+
+class vtkpxProcessRawBrukerFIDImage : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxProcessRawBrukerFIDImage *New();
+  vtkTypeMacro(vtkpxProcessRawBrukerFIDImage,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Mode -- is input echoplanar or not
+  vtkSetClampMacro(EchoPlanarMode,int,0,1);
+  vtkGetMacro(EchoPlanarMode,int);
+  vtkBooleanMacro(EchoPlanarMode, int);
+
+  // Description:
+  // Mode -- is input echoplanar or not
+  vtkSetClampMacro(ConventionalAppendMultiSliceMode,int,0,1);
+  vtkGetMacro(ConventionalAppendMultiSliceMode,int);
+  vtkBooleanMacro(ConventionalAppendMultiSliceMode, int);
+
+
+  // Description:
+  // Output Mode -- Output Polar Complex (non FFT) Or Not
+  vtkSetClampMacro(PolarComplexMode,int,0,1);
+  vtkGetMacro(PolarComplexMode,int);
+  vtkBooleanMacro(PolarComplexMode, int);
+
+  // Description:
+  // Output Mode -- Output Polar Complex (non FFT) Or Not
+  vtkSetClampMacro(ShiftSpectrum,int,0,1);
+  vtkGetMacro(ShiftSpectrum,int);
+  vtkBooleanMacro(ShiftSpectrum, int);
+
+
+  static int ConvertConventional(vtkImageData* input,vtkImageData* output);	
+  static int ConvertEchoPlanar(vtkImageData* input,vtkImageData*output);
+  static int PerformInverseFourierTransform(vtkImageData* input,vtkImageData*output,int shiftspectrum);
+  static int DoShiftSpectrum(vtkImageData* input,vtkImageData* output);
+  static int ReOrderMultipleEchos(vtkImageData* input,vtkImageData* output);	
+
+  // Exponential T2 Maps
+  static int FillMap(vtkImageData* map,vtkImageData* density,float thr,int bimap);
+
+  // Main Routines
+  static int FitExponentialT2Model(vtkImageData* input,vtkImageData* output,float first=15.0,float dt=15.0,int mode=1,float threshold=10.0,
+				   float int_threshold=0.02,float maxt2=2000.0);
+
+  static vtkImageData* GenerateSyntheticData(float d1,float d2,float t1,float t2,float dte,int nte,float noise);
+
+  // 3D Fourier Spectra 
+  // ------------------
+
+  static int ReadFIDSpectrumAndSpitIntoFile(char* fname,char* outname,int width,int height,int depth,int components);
+
+  static vtkImageData* ReadFIDSpectrum(char* fname,int width,int height,int sliceno,int depth,int components);
+  static vtkImageData* ProcessFIDSpectrum(char* fname,int width,int height,int sliceno,int depth,int components,float scalefactor=0.00001);
+  static void ComputeSums(vtkImageData* img);
+  static void FitFIDIntoGnuplot(char* fname1,char* fname2,int width,int height,int depth,int components);
+
+  static float AutoPhaseCorrection(vtkImageData* complexinput);
+  static vtkImageData* PhaseCorrection(vtkImageData* complexinput,float theta,float theta2);
+  static vtkImageData* CenterPhaseData(vtkImageData* complexinput);
+
+  static int PlotImageComponentToGnuplot(vtkImageData* image,int x,int y,char* output);
+
+  
+protected:
+
+  vtkpxProcessRawBrukerFIDImage();
+  vtkpxProcessRawBrukerFIDImage(const vtkpxProcessRawBrukerFIDImage&) {};
+  void operator=(const vtkpxProcessRawBrukerFIDImage&) {};
+
+  virtual void SimpleExecute(vtkImageData*,vtkImageData*);
+  void ExecuteInformation();
+
+  int EchoPlanarMode;
+  int PolarComplexMode;
+  int ShiftSpectrum;
+  int ConventionalAppendMultiSliceMode;
+
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxSimpleImageThreshold.cpp b/bioimagesuite30_src/Imaging/vtkpxSimpleImageThreshold.cpp
new file mode 100644
index 0000000..40c9807
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxSimpleImageThreshold.cpp
@@ -0,0 +1,107 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSimpleImageThreshold.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageThreshold.h"
+#include "vtkpxUtil.h"
+#include "vtkIntArray.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageAccumulate.h"
+#include "vtkImageExtractComponents.h"
+//------------------------------------------------------------------------------
+vtkpxSimpleImageThreshold* vtkpxSimpleImageThreshold::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxSimpleImageThreshold");
+  if(ret)
+    {
+    return (vtkpxSimpleImageThreshold*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxSimpleImageThreshold;
+}
+
+// Construct object with no children.
+vtkpxSimpleImageThreshold::vtkpxSimpleImageThreshold()
+{
+  this->LowerThreshold=-1.0e+9;
+  this->UpperThreshold= 1.0e+9;
+}
+// ----------------------------------------------------------------------------
+void vtkpxSimpleImageThreshold::SimpleExecute(vtkImageData* input,vtkImageData* output )
+{
+
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Input to vtkpxSimpleImageThreshold");
+      return;
+    }
+
+  int dim[3]; input->GetDimensions(dim);
+  int numvox=dim[0]*dim[1]*dim[2];
+  int numcomp=input->GetNumberOfScalarComponents();
+
+  vtkDataArray* inarray=input->GetPointData()->GetScalars();
+  vtkDataArray* outarray=output->GetPointData()->GetScalars();
+
+  for (int component=0;component<numcomp;component++)
+    {
+      for (int i=0;i<numvox;i++)
+	{
+	  float out=0.0;
+	  float v=inarray->GetComponent(i,component);
+	  if (v>=this->LowerThreshold && v<=this->UpperThreshold)
+	    out=1.0;
+	  outarray->SetComponent(i,component,out);
+	}
+    }
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxSimpleImageThreshold.h b/bioimagesuite30_src/Imaging/vtkpxSimpleImageThreshold.h
new file mode 100644
index 0000000..72c7e18
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxSimpleImageThreshold.h
@@ -0,0 +1,93 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageSimpleImageThreshold.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxImageSimpleImageThreshold -- compute the difference and a normalized difference
+// between two images
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxImageSimpleImageThreshold_h
+#define __vtkpxImageSimpleImageThreshold_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkpxSimpleImageThreshold : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxSimpleImageThreshold *New();
+  vtkTypeMacro(vtkpxSimpleImageThreshold,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set the thresholds between which output is 1
+  vtkGetMacro(LowerThreshold,float);
+  vtkSetMacro(LowerThreshold,float);
+  vtkGetMacro(UpperThreshold,float);
+  vtkSetMacro(UpperThreshold,float);
+
+protected:
+
+  vtkpxSimpleImageThreshold();
+  vtkpxSimpleImageThreshold(const vtkpxSimpleImageThreshold&) {};
+  void operator=(const vtkpxSimpleImageThreshold&) {};
+
+  // Description:
+  // Do Thresholding Operation 
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  //BTX
+  float       LowerThreshold,UpperThreshold;
+  //ETX
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxWeightedSmoothImage.cpp b/bioimagesuite30_src/Imaging/vtkpxWeightedSmoothImage.cpp
new file mode 100644
index 0000000..8647d99
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxWeightedSmoothImage.cpp
@@ -0,0 +1,207 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxWeightedSmoothImage.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/05/01 13:49:39 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkpxWeightedSmoothImage.h"
+#include "vtkDataArray.h"
+#include "math.h"
+#include "vtkpxUtil.h"
+#include "vtkGridTransform.h"
+#include "vtkFloatArray.h"
+//------------------------------------------------------------------------------
+vtkpxWeightedSmoothImage* vtkpxWeightedSmoothImage::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxWeightedSmoothImage");
+  if(ret)
+    {
+    return (vtkpxWeightedSmoothImage*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxWeightedSmoothImage;
+}
+
+// Construct object with no children.
+vtkpxWeightedSmoothImage::vtkpxWeightedSmoothImage()
+{
+  this->Smoothness=0.5;
+  this->Dimensionality=2;
+  this->Iterations=5;
+}
+// ----------------------------------------------------------------------------
+vtkpxWeightedSmoothImage::~vtkpxWeightedSmoothImage()
+{
+}
+// ----------------------------------------------------------------------------
+int vtkpxWeightedSmoothImage::CheckInputs()
+{
+ if (this->GetImageDataInput(0)==NULL)
+    {
+      vtkErrorMacro(<<"No Input Field Map Supplied\n");
+      return 0;
+    }
+
+ int dim1[3];
+ this->GetImageDataInput(0)->GetDimensions(dim1);
+
+ int c=this->GetImageDataInput(0)->GetNumberOfScalarComponents();
+
+ if (dim1[0]<4 || dim1[1]<4 || dim1[2]<1 || c<2)
+   {
+     vtkErrorMacro(<<"Image Dimensions are too small ( 16x16x1 minimum 2 components (1=intensity,2=weights))");
+     return 0;
+   }
+
+
+ return 1;
+}
+// ----------------------------------------------------------------------------
+void vtkpxWeightedSmoothImage::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (this->CheckInputs()==0)
+    return;
+
+  output->DeepCopy(input);
+
+  if (this->Iterations==0)
+    return;
+
+  const int searchdir[6][3]= { 
+    { 1 , 0 , 0 } ,     { -1 ,  0 ,  0 } ,
+    { 0 , 1 , 0 } ,     {  0 , -1 ,  0 } ,
+    { 0 , 0 , 1 } ,     {  0 ,  0 , -1 } };
+
+
+  vtkDataArray* outscal=output->GetPointData()->GetScalars();
+  vtkDataArray* temp=vtkDataArray::CreateDataArray(outscal->GetDataType());
+  temp->SetNumberOfComponents(2);
+
+  int dim[3];
+  output->GetDimensions(dim);
+
+  int numsearch=this->Dimensionality*2;
+  int iter=0;
+
+  float msmooth=1.0-this->Smoothness;
+
+  while ( iter < this->Iterations ) 
+    {
+      temp->DeepCopy(outscal);
+
+      int index=0;
+      for (int k=0;k<dim[2];k++)
+	for (int j=0;j<dim[1];j++)
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      int debug=0;
+
+	      if (i==dim[0]/2 && j==dim[1]/2)
+		debug=1;
+
+	      float tw1=0.0;
+	      float tc1=0.0;
+	      for (int s=0;s<numsearch;s++)
+		{
+		  int newi=Irange(i+searchdir[s][0],0,dim[0]-1);
+		  int newj=Irange(j+searchdir[s][1],0,dim[1]-1);
+		  int newk=Irange(k+searchdir[s][2],0,dim[2]-1);
+
+		  float c1=output->GetScalarComponentAsDouble(newi,newj,newk,0);
+		  float w1=output->GetScalarComponentAsDouble(newi,newj,newk,1);
+
+		  tc1+=w1*c1;
+		  tw1+=w1;
+
+		  if (debug)
+		    fprintf(stderr,"\tScanning %d,%d,%d = %.1f,%.1f totals = %.1f,%.1f\n",
+			    newi,newj,newk,c1,w1,tc1,tw1);
+		}
+
+	      if (tw1>=0.01)
+		tc1=tc1/tw1;
+	      else
+		tw1=0.0;
+	      tw1=tw1*this->Smoothness/float(numsearch);
+	      if (debug)
+		fprintf(stderr,"\t\t mn = %.1f,%.1f\n",tc1,tw1);
+
+	      
+	      float c=output->GetScalarComponentAsDouble(i,j,k,0);
+	      float w=output->GetScalarComponentAsDouble(i,j,k,1)*msmooth;
+
+	      float sumconf=w+tw1;
+	      float vout=c;
+
+	      if (sumconf>0.0001)
+		vout = ( w*c+ tw1*tc1)/(w+tw1);
+
+	      if (debug)
+		fprintf(stderr,"Point =%d,%d,%d \t\tc,w=%.1f,%.1f \n\t vout = %.2f\n\n",
+			i,j,k,c,w,vout);
+
+	      temp->SetComponent(index,0,vout);
+	      ++index;
+	    }
+    
+      fprintf(stderr,"Smoothing Iteration = %d \n",iter);
+      ++iter;
+      outscal->DeepCopy(temp);
+    }
+  temp->Delete();
+  return;
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkpxWeightedSmoothImage.h b/bioimagesuite30_src/Imaging/vtkpxWeightedSmoothImage.h
new file mode 100644
index 0000000..e7f9b84
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkpxWeightedSmoothImage.h
@@ -0,0 +1,111 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxWeightedSmoothImage.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:20:36 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxWeightedSmoothImage -- Given two inputs field map and condifence compute complete and smoothed field map for distortion correction/shimming 
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxWeightedSmoothImage_h
+#define __vtkpxWeightedSmoothImage_h
+
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+
+
+class vtkGridTransform;
+
+class vtkpxWeightedSmoothImage : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxWeightedSmoothImage *New();
+  vtkTypeMacro(vtkpxWeightedSmoothImage,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Smoothness Weight 0.0 - 1.0
+  vtkGetMacro(Smoothness,float);
+  vtkSetClampMacro(Smoothness,float,0.0,1.0);
+
+  // Description:
+  // SmoothIterations 0 - 100
+  vtkGetMacro(Iterations,int);
+  vtkSetClampMacro(Iterations,int,0,100);
+
+
+  // Description:
+  // Dimensionality 2 (slice-by-slice) or 3 (full 3D)
+  vtkGetMacro(Dimensionality,int);
+  vtkSetClampMacro(Dimensionality,int,2,3);
+
+
+protected:
+
+  vtkpxWeightedSmoothImage();
+  virtual ~vtkpxWeightedSmoothImage();
+  vtkpxWeightedSmoothImage(const vtkpxWeightedSmoothImage&) {};
+  void operator=(const vtkpxWeightedSmoothImage&) {};
+
+
+  float                  Smoothness;
+  int                    Dimensionality;
+  int                    Iterations;
+
+  virtual int CheckInputs();
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkxqImageFourierConvolution.cpp b/bioimagesuite30_src/Imaging/vtkxqImageFourierConvolution.cpp
new file mode 100644
index 0000000..bdc1739
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkxqImageFourierConvolution.cpp
@@ -0,0 +1,1958 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkxqImageFourierConvolution.h"
+#include "vtkImageReslice.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkImageFFT.h"
+#include "vtkImageRFFT.h"
+#include "vtkImageFFT.h"
+#include "vtkImageRFFT.h"
+#include "vtkpxUtil.h"
+
+#include "vtkImageCast.h"
+#include "vtkImageMagnitude.h"
+#include "vtkImageMathematics.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+#include "vtkImageShiftScale.h"
+#include "vtkMath.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataWriter.h"
+#include "vtkCellArray.h"
+#include "vtkSphereSource.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkjoSphereSource.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+
+#include "pxisinf.h"
+#include "bioimagesuite_settings.h"
+// -------------------------------------------------------
+// CUDA Definitions
+// -------------------------------------------------------
+// CUDA include files
+#include "vtkbisCudaFFT.h"
+#include "vtkbisCudaRFFT.h"
+
+// -------------------------------------------------------
+
+// Uncomment to force CPU
+//#undef BIOIMAGESUITE3_USE_CUDA
+
+//------------------------------------------------------------------------------
+vtkxqImageFourierConvolution* vtkxqImageFourierConvolution::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkxqImageFourierConvolution");
+  if(ret)
+    {
+    return (vtkxqImageFourierConvolution*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkxqImageFourierConvolution;
+}
+
+// Construct object with no children.
+vtkxqImageFourierConvolution::vtkxqImageFourierConvolution()
+{
+  this->Mode=1;
+  this->DoublePrecision=1;
+    this->FilterBank=NULL;
+  this->SecondOutput=NULL;
+  this->ForceCPU=0;
+}
+// ----------------------------------------------------------------------------
+vtkxqImageFourierConvolution::~vtkxqImageFourierConvolution()
+{
+  this->SetFilterBank(NULL);
+  if (this->SecondOutput!=NULL)
+    this->SecondOutput->Delete();
+}
+
+// ----------------------------------------------------------------------------
+int vtkxqImageFourierConvolution::RequestInformation(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+						     vtkInformationVector *outputVector)
+
+{  
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, 1);
+
+  if (this->FilterBank==NULL)
+    {
+      vtkErrorMacro(<<"No Filter Bank Image Set\n");
+      return 1;
+    }
+  int nc=this->FilterBank->GetNumberOfScalarComponents();
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, nc);
+  return 1; 
+}
+// -------------------------------------------------------------------------------------------------------------
+vtkImageData* vtkxqImageFourierConvolution::PadImage(vtkImageData* img,int paddim[3])
+{
+  //  static int count=1;
+
+  int dim[3]; img->GetDimensions(dim);
+  double ori[3];  img->GetOrigin(ori);
+  double spa[3];  img->GetSpacing(spa);
+  if (this->Debug)
+    fprintf(stderr,"\t Padding = (%d,%d,%d) ori=(%.1f,%.1f,%.1f) spa=(%.1f,%.1f,%.1f)\n",
+	    dim[0],	  dim[1],	  dim[2],
+	    ori[0],	  ori[1],	  ori[2],
+	    spa[0],	  spa[1],	  spa[2]);
+
+  
+
+  vtkImageReslice* resl=vtkImageReslice::New();
+  resl->SetInput(img);
+  resl->SetOutputExtent(0,paddim[0]-1,0,paddim[1]-1,0,paddim[2]-1);
+  resl->SetOutputOrigin(img->GetOrigin());
+  resl->SetOutputSpacing(img->GetSpacing());
+  resl->SetInterpolationMode(0);
+  resl->SetBackgroundLevel(0.0);
+  resl->Update();
+  
+  vtkImageData* out=vtkImageData::New();
+  out->ShallowCopy(resl->GetOutput());
+  resl->Delete();
+
+  out->GetDimensions(dim);
+  out->GetOrigin(ori);
+  out->GetSpacing(spa);
+
+  if (this->Debug)
+    {
+      fprintf(stderr,"\t Padding Done = (%d,%d,%d) ori=(%.1f,%.1f,%.1f) spa=(%.1f,%.1f,%.1f)\n",
+	      dim[0],	  dim[1],	  dim[2],
+	      ori[0],	  ori[1],	  ori[2],
+	      spa[0],	  spa[1],	  spa[2]);
+      
+      
+      /*      char line[100];
+      sprintf(line,"padded_%d.nii.gz",count); ++count;
+      vtkpxUtil::SaveAnalyze(line,out,9);
+      fprintf(stderr,"padded image saved in %s\n",line);*/
+    }
+  return out;
+}
+// -------------------------------------------------------------------------------------------------------------
+vtkImageData* vtkxqImageFourierConvolution::FFTImage(vtkImageData* img,int frame,int paddim[3],int dosquare)
+{
+  int dim[3]; img->GetDimensions(dim);
+  int nc=img->GetNumberOfScalarComponents();
+  if (this->Debug)
+    fprintf(stderr,"Performing FFT (%d x %d x %d, %d) --> (%d x %d x %d at %d) dosquare=%d\n",
+	    dim[0],dim[1],dim[2],nc,
+	    paddim[0],paddim[1],paddim[2],
+	    frame,dosquare);
+
+  vtkImageCast* cast=vtkImageCast::New();
+  vtkImageData* tmp=NULL;
+  if (img->GetNumberOfScalarComponents()>1)
+    {
+      vtkImageExtractComponents* comp=vtkImageExtractComponents::New();
+      comp->SetInput(img);
+      comp->SetComponents(frame);
+      if (this->Debug)
+	fprintf(stderr,"\t\t Extracting frame=%d\n",frame);
+      comp->Update();
+      tmp=this->PadImage(comp->GetOutput(),paddim);
+      comp->Delete();
+    }
+  else
+    {
+     tmp=this->PadImage(img,paddim);
+    }
+
+
+  cast->SetInput(tmp);
+  tmp->Delete();
+  if (this->DoublePrecision)
+    cast->SetOutputScalarTypeToDouble();
+  else
+    cast->SetOutputScalarTypeToFloat();
+  //  cast->Update();
+
+  vtkImageMathematics* math=vtkImageMathematics::New();	
+  
+  
+  /*
+#ifndef BIOIMAGESUITE3_USE_CUDA
+  fprintf(stderr,"\nUsing cpu\n");
+  vtkImageFourierFilter* fft=vtkImageFFT::New();  
+  fft->SetDimensionality(3);
+#else
+  fprintf(stderr,"\nUsing CUDA\n");
+  vtkbisCudaFFT* fft=vtkbisCudaFFT::New();  
+#endif
+  */
+
+  int usegpu=0;
+#ifdef BIOIMAGESUITE3_USE_CUDA
+  if (this->ForceCPU==0)
+    usegpu=1;
+#endif
+  
+  vtkImageAlgorithm* fft=NULL;
+  if (usegpu)
+    {
+      if (this->Debug)
+	fprintf(stderr,"\nUsing CUDA\n");
+      fft=vtkbisCudaFFT::New();  
+    }
+  else
+    {
+      if (this->Debug)
+	fprintf(stdout,"\nUsing cpu this->ForceCPU=%d, %d\n",this->ForceCPU,usegpu);
+      vtkImageFourierFilter* fft2=vtkImageFFT::New();  
+      fft2->SetDimensionality(3);
+      fft=fft2;   
+    }
+ 
+
+  if (dosquare)
+    {
+      math->SetInput1(cast->GetOutput());
+      math->SetOperationToSquare();
+      math->Update();
+      fft->SetInput(math->GetOutput());
+    }
+  else
+    {
+      fft->SetInput(cast->GetOutput());
+    }
+ 
+  fft->Update();
+
+  vtkImageData* out=vtkImageData::New();
+  out->ShallowCopy(fft->GetOutput());
+
+  double range1[2];out->GetPointData()->GetScalars()->GetRange(range1,0);
+  double range2[2];out->GetPointData()->GetScalars()->GetRange(range2,1);
+  if (this->Debug)
+    fprintf(stderr,"\t FFT RANGE=%f:%f\n",range1[0],range1[1],range2[0],range2[1]);
+
+  out->GetDimensions(dim);
+  if (this->Debug)
+    fprintf(stderr,"\t FFT Done (%dx%dx%d,%d)\n",
+	    dim[0],dim[1],dim[2],out->GetNumberOfScalarComponents());
+
+
+  cast->Delete(); 
+  fft->Delete();
+  math->Delete();
+
+  return out;
+}
+// -------------------------------------------------------------------------------------------------------------
+vtkImageData* vtkxqImageFourierConvolution::DoFourierConvolution(vtkImageData* img1,vtkImageData* img2,int origdim[3],double origori[3],int dosquare)
+{
+  //  static int count=1;
+  int dim1[3];  img1->GetDimensions(dim1);
+  double ori1[3]; img1->GetOrigin(ori1);
+
+  // Force Origin and Spacing the same -- not that it should matter
+  img2->SetSpacing(img1->GetSpacing());
+  img2->SetOrigin(img1->GetOrigin());
+
+  int dim2[3]; img2->GetDimensions(dim2);
+  double ori2[3]; img2->GetOrigin(ori2);
+
+  int nc1=img1->GetNumberOfScalarComponents();
+  int nc2=img2->GetNumberOfScalarComponents();
+  if (this->Debug)
+    fprintf(stderr,"Performing F-Conv (%d x %d x %d, %d) and (%d x %d x %d, %d) ori1=(%.1f,%.1f,%.1f), ori2=(%.1f,%.1f,%.1f)--> (%d x %d x %d ), oriout=(%.1f,%.1f,%.1f)\n",
+	    dim1[0],dim1[1],dim1[2],nc1,
+	    dim2[0],dim2[1],dim2[2],nc2,
+	    ori1[0],ori1[1],ori1[2],
+	    ori2[0],ori2[1],ori2[2],
+	    origdim[0],origdim[1],origdim[2],
+	    origori[0],origori[1],origori[2]);
+
+
+
+  vtkImageMathematics* math=vtkImageMathematics::New();
+  math->DebugOff();
+  math-> SetInput1(img1);
+  math-> SetInput2(img2);
+  math->SetOperationToComplexMultiply();
+  //  math->Update();
+
+  /*#ifndef BIOIMAGESUITE3_USE_CUDA
+  fprintf(stderr,"\nUsing cpu\n");
+  vtkImageFourierFilter* rfft=vtkImageRFFT::New();
+  rfft->SetDimensionality(3);
+  rfft->DebugOff();
+#else
+  fprintf(stderr,"\nUsing CUDA\n");
+  vtkbisCudaRFFT* rfft=vtkbisCudaRFFT::New();  
+  #endif
+  */
+  
+  int usegpu=0;
+#ifdef BIOIMAGESUITE3_USE_CUDA
+  if (this->ForceCPU==0)
+    usegpu=1;
+#endif
+
+  vtkImageAlgorithm* rfft=NULL;
+  if (usegpu)
+    {
+      if (this->Debug)
+	fprintf(stderr,"\nUsing CUDA\n");
+      rfft=vtkbisCudaRFFT::New();  
+    }
+  else
+    {
+      if (this->Debug)
+	fprintf(stderr,"\nUsing cpu\n");
+      vtkImageFourierFilter* rfft2=vtkImageRFFT::New();  
+      rfft2->SetDimensionality(3);
+      rfft=rfft2;
+    }
+  
+
+  rfft->SetInput(math->GetOutput());
+  math->Delete();
+  rfft->Update();
+
+  rfft->GetOutput()->GetDimensions(dim1);
+  rfft->GetOutput()->GetOrigin(ori1);
+  nc1=rfft->GetOutput()->GetNumberOfScalarComponents();
+
+  if (this->Debug)
+    fprintf(stderr,"\t RFFT Done (%d x %d x %d, %d) ori=(%.1f,%.1f,%.1f)\n",
+	    dim1[0],dim1[1],dim1[2],nc1,
+	    ori1[0],ori1[1],ori1[2]);
+
+  vtkImageCast* cast=vtkImageCast::New();
+  cast->SetInput(rfft->GetOutput());
+  cast->SetOutputScalarTypeToFloat();
+  rfft->Delete();
+
+
+  //  vtkImageData* tmp_img1=vtkImageData::New();
+  vtkImageReslice* resl=vtkImageReslice::New();
+  double ori[3];  
+
+  if (this->Mode==1 || dosquare == 1)
+    {
+      // Get the Magnitude
+      // -----------------
+      vtkImageMagnitude* magn=vtkImageMagnitude::New();
+      magn->DebugOff();
+      magn->SetInput(cast->GetOutput());
+      magn->Update();
+      resl->SetInput(magn->GetOutput());
+      magn->GetOutput()->GetOrigin(ori);
+      //  tmp_img1->ShallowCopy(magn->GetOutput());
+      
+      magn->Delete();
+    }
+  else
+    {
+      // Get the Real Part, convolution of two real images should be real
+      // ----------------------------------------------------------------
+      vtkImageExtractComponents* comp=vtkImageExtractComponents::New();
+      comp->SetInput(cast->GetOutput());
+      comp->SetComponents(0);
+      comp->Update();
+      resl->SetInput(comp->GetOutput());
+      //    tmp_img1->ShallowCopy(comp->GetOutput());
+
+      comp->GetOutput()->GetOrigin(ori);
+      comp->Delete();
+      
+    }
+  cast->Delete();
+  resl->SetOutputExtent(0,origdim[0]-1,0,origdim[1]-1,0,origdim[2]-1);
+  resl->SetOutputOrigin(origori);
+  resl->SetOutputSpacing(img1->GetSpacing());
+  resl->SetInterpolationMode(0);
+  resl->SetBackgroundLevel(0.0);
+  resl->Update();
+  
+  vtkImageData* out=vtkImageData::New();
+  out->ShallowCopy(resl->GetOutput());
+  resl->Delete();
+
+  if (this->Debug)
+    {
+      fprintf(stderr,"Reslice Input Origin = (%.3f,%.3f,%.3f)\n",ori[0],ori[1],ori[2]);
+      fprintf(stderr,"Reslice Output Origin = (%.3f,%.3f,%.3f)\n",origori[0],origori[1],origori[2]);
+      /*
+      char line[100];
+      sprintf(line,"zz_uncrop_%d.nii.gz",count); 
+      vtkpxUtil::SaveAnalyze(line,tmp_img1,9);
+      fprintf(stderr,"uncropped image saved in %s\n",line);
+      
+      sprintf(line,"zz_crop_%d.nii.gz",count); 
+      vtkpxUtil::SaveAnalyze(line,out,9);
+      fprintf(stderr,"uncropped image saved in %s\n",line);*/
+    }
+
+  //  tmp_img1->Delete();
+  //  ++count;
+
+
+  out->GetDimensions(dim1);
+  out->GetOrigin(ori1);
+  nc1=out->GetNumberOfScalarComponents();
+
+  double range[2];out->GetPointData()->GetScalars()->GetRange(range);
+
+  if (this->Debug)
+    fprintf(stderr,"\t Done F-Conv (%d x %d x %d, %d) ori=(%.1f,%.1f,%.1f) RANGE=%f:%f\n",
+	    dim1[0],dim1[1],dim1[2],nc1,
+	    ori1[0],ori1[1],ori1[2],range[0],range[1]);
+
+  return out;
+}
+
+void vtkxqImageFourierConvolution::normalizeFilters(vtkImageData* FILTERS)
+{
+  vtkDataArray* filters=FILTERS->GetPointData()->GetScalars();
+  double r[2]; filters->GetRange(r);
+  if (r[0]<0.0)
+    {
+      if (this->Debug)
+	fprintf(stderr,"Not normalizing, r[0]=%.2f\n",r[0]);
+      return;
+    }
+  if (this->Debug)
+    fprintf(stderr, "Normalizing filters.\n");
+  
+
+  int frames=FILTERS->GetNumberOfScalarComponents();
+  for (int i=0; i<frames; i++){
+    int points=filters->GetNumberOfTuples();
+    double sum=0.0;
+    for (int j=0; j<points; j++)
+      sum+=filters->GetComponent(j, i);
+
+    if (sum>0.0001)
+      {
+	for (int j=0; j<points; j++)
+	  filters->SetComponent(j, i, (filters->GetComponent(j, i))/sum);
+      }
+  }
+}
+
+
+  
+// -------------------------------------------------------------------------------------------------------------
+void vtkxqImageFourierConvolution::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (this->Debug)
+    fprintf(stderr, "In simple execute of FOURIER CONVOLUTION ..........................\n");
+  if (input==NULL    || this->FilterBank ==NULL )
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkxqImageFourierConvolution");
+      return;
+    }
+
+  this->normalizeFilters(this->FilterBank);
+
+  
+  int nc=this->FilterBank->GetNumberOfScalarComponents();
+  int original_dim[3];    input->GetDimensions(original_dim);
+  double offset_origin[3]; input->GetOrigin(offset_origin);
+  double spa[3]; input->GetSpacing(spa);
+  int fdim[3]; this->FilterBank->GetDimensions(fdim);
+  
+  if (this->SecondOutput!=NULL)
+    this->SecondOutput->Delete();
+  this->SecondOutput=NULL;
+
+  if (this->Mode==2)
+    {
+      this->SecondOutput=vtkImageData::New();
+      this->SecondOutput->CopyStructure(output);
+      this->SecondOutput->SetNumberOfScalarComponents(output->GetNumberOfScalarComponents());
+      this->SecondOutput->SetScalarTypeToFloat();
+      this->SecondOutput->AllocateScalars();
+      if (this->Debug)
+	fprintf(stderr, "fb nc: %d output nc:%d secondoutput nc: %d\n", nc, output->GetNumberOfScalarComponents(), this->SecondOutput->GetNumberOfScalarComponents());
+    }
+
+
+  int paddim[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      paddim[ia]=original_dim[ia]+fdim[ia]+1;
+      offset_origin[ia]+=0.5*spa[ia]*double(fdim[ia]-1);
+    }
+
+  if (this->Debug)
+    {
+      fprintf(stderr,"Beginning Image Fourier Convolution: Mode = %d , Double Precision =%d\n",
+	      this->Mode,this->DoublePrecision);
+      fprintf(stderr,"Input dims = (%d,%d,%d) filter=(%d,%d,%d) nc=%d padded=(%d,%d,%d) ori=(%.1f,%.1f,%.1f)\n",
+	      original_dim[0],   original_dim[1],   original_dim[2],
+	      fdim[0],  fdim[1],  fdim[2],nc,
+	      paddim[0],paddim[1],paddim[2],
+	      offset_origin[0],offset_origin[1],offset_origin[2]);
+    }
+
+  int odim[3]; output->GetDimensions(odim);
+  int onc=output->GetNumberOfScalarComponents();
+  if (this->Debug)
+    fprintf(stderr,"Output = (%d,%d,%d, %d) \n",
+	    odim[0],odim[1],odim[2],onc);
+
+
+  // Normalize Image between 0 and 1
+  // --------------------------------
+  double range[2]; input->GetPointData()->GetScalars()->GetRange(range);
+  double sc=1.0/(range[1]-range[0]);
+
+  if (this->Debug)
+    fprintf(stderr,"Range = %f:%f, scale=%f\n",range[0],range[1],sc);
+  
+  vtkImageCast* cast=vtkImageCast::New();
+  cast->SetInput(input);
+  cast->SetOutputScalarTypeToFloat();
+  cast->GetOutput()->SetDimensions(input->GetDimensions()); 
+  cast->Update();
+
+  vtkImageData* normalized=vtkImageData::New();
+  if (this->Mode>=1)
+    {
+      vtkImageShiftScale* shiftscale=vtkImageShiftScale::New();
+      shiftscale->SetInput(cast->GetOutput());
+      shiftscale->SetShift(-range[0]);
+      shiftscale->SetScale(sc);
+      shiftscale->Update();
+      normalized->ShallowCopy(shiftscale->GetOutput());
+      shiftscale->Delete();
+    } 
+  else
+    {
+      cast->Update();
+      normalized->ShallowCopy(cast->GetOutput());
+    }
+  cast->Delete();
+
+  // --------------------------------
+
+  vtkImageData* FI=this->FFTImage(normalized,0,paddim,0);
+  vtkImageData* FI2=NULL;
+
+  if (this->Mode==1 || this->Mode==2)
+    {
+      FI2=this->FFTImage(normalized,0,paddim,1);
+    }
+  
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  vtkDataArray *inp=normalized->GetPointData()->GetScalars();
+
+  vtkDataArray *out2=NULL;
+  if (this->SecondOutput!=NULL)
+    out2=this->SecondOutput->GetPointData()->GetScalars();
+  
+  //  out->SetNumberOfComponents(output->GetNumberOfScalarComponents()); 
+  
+  
+  //  fprintf(stderr, "outnc: %d, nc2: %d \n", out->GetNumberOfComponents(), out2->GetNumberOfComponents()); 
+
+  int nt=out->GetNumberOfTuples();
+
+  for (int frame=0;frame<nc;frame++)
+  {
+    out->FillComponent(frame,0.0);
+    if (out2!=NULL)
+      out2->FillComponent(frame,0.0);
+  }
+  
+  int debugv=original_dim[0]/2+original_dim[0]*(original_dim[1]/2)+(original_dim[0]*original_dim[1])*original_dim[2]/2;
+
+  //  if (nc>10)
+  //    nc=10;
+
+  for (int frame=0;frame<nc;frame++)
+    {
+      if (this->Debug)
+	fprintf(stderr,"\n Beginning Filter %d/%d\n",frame+1,nc);
+      this->UpdateProgress(double(frame)/double(nc));
+      
+      vtkImageData* Bi = FFTImage(this->FilterBank,frame,paddim,0);
+      vtkImageData* IxBi=this->DoFourierConvolution(FI,Bi,original_dim,offset_origin,0);
+      vtkDataArray *data=IxBi->GetPointData()->GetScalars();
+
+      if (this->Mode==1 || this->Mode==2)
+	{
+	  vtkImageData* I2xBi=this->DoFourierConvolution(FI2,Bi,original_dim,offset_origin,1);
+	  vtkDataArray *data2=I2xBi->GetPointData()->GetScalars();
+	  
+	  for (int j=0;j<nt;j++)
+	    {
+	      double lm=inp->GetComponent(j,0);
+	      double vl=data2->GetComponent(j,0)-
+		2.0*lm*data->GetComponent(j,0)+
+		lm*lm;
+	      if (isnan(vl) || isinf(vl))	
+		vl=0.0;
+	      out->SetComponent(j,frame,vl);
+
+	      if (j==debugv && this->Debug)
+		fprintf(stderr,"Image Center vals = image=%f,  I2xBi=%f, IxBI=%f out=%f\n",
+			lm,
+			data2->GetComponent(j,0),
+			data->GetComponent(j,0),
+			out->GetComponent(j,frame));
+	    }
+	  I2xBi->Delete();
+	  if (this->Mode==2)
+	    {
+	      if (this->Debug)
+		fprintf(stderr,"Mode=2, frame=%d\n",frame);
+	      out2->CopyComponent(frame,data,0);
+	    }
+	}
+      else
+	{
+	  if (this->Debug)
+	    fprintf(stderr,"Mode=0, frame=%d\n",frame);
+	  out->CopyComponent(frame,data,0);
+	}
+      //      fprintf(stderr,"Cleaning up 1\n");
+      IxBi->Delete();
+      Bi->Delete();
+    }
+  
+  //  fprintf(stderr,"Cleaning up 2\n");
+  FI->Delete();
+
+
+  //  fprintf(stderr,"Cleaning up 3\n");
+  if (FI2!=NULL)
+    FI2->Delete();
+
+  //  fprintf(stderr,"Cleaning up 4\n");
+  normalized->Delete();
+
+  //  fprintf(stderr,"Cleaning up 5\n");
+
+  //fprintf(stderr,"nc = %d,  nc2=%d, \n", output->GetNumberOfScalarComponents(), this->SecondOutput->GetNumberOfScalarComponents());
+  this->UpdateProgress(1.0);
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// More Fourier Filters
+// -------------------------------------------------------------------------------------------------------------
+int vtkxqImageFourierConvolution::SetFilterBankToGaussian(double sigma1,double sigma2,double sigma3,double radius) 
+{
+  double sigma[3] = { sigma1, sigma2, sigma3 };
+  int dim[3];
+  for (int ia=0;ia<=2;ia++)
+    dim[ia]=int(radius*sigma[ia]+0.5)*2+1;
+
+  vtkImageData* tmp=vtkxqImageFourierConvolution::Gaussian(sigma,dim);
+  this->SetFilterBank(tmp);
+  this->SetMode(0);
+  tmp->Delete();
+
+  return 1;
+
+}
+// -------------------------------------------------------------------------------------------------------------
+int vtkxqImageFourierConvolution::SetFilterBankToGaussianDerivative(double sigma1,double sigma2,double sigma3,double radius) 
+{
+  double sigma[3] = { sigma1, sigma2, sigma3 };
+  int dim[3];
+  for (int ia=0;ia<=2;ia++)
+    dim[ia]=int(radius*sigma[ia]+0.5)*2+1;
+
+  vtkImageData* tmp=vtkxqImageFourierConvolution::GaussianDerivative(sigma,dim);
+  this->SetFilterBank(tmp);
+  this->SetMode(0);
+  tmp->Delete();
+
+  return 1;
+
+
+}
+// -------------------------------------------------------------------------------------------------------------
+int vtkxqImageFourierConvolution::SetFilterBankToHessian(double sigma1,double sigma2,double sigma3,double radius)
+{
+  double sigma[3] = { sigma1, sigma2, sigma3 };
+  int dim[3];
+  for (int ia=0;ia<=2;ia++)
+    dim[ia]=int(radius*sigma[ia]+0.5)*2+1;
+
+  vtkImageData* tmp=vtkxqImageFourierConvolution::Hessian(sigma,dim);
+  this->SetFilterBank(tmp);
+  this->SetMode(0);
+  tmp->Delete();
+
+  return 1;
+}
+// -------------------------------------------------------------------------------------------------------------
+int vtkxqImageFourierConvolution::SetFilterBankToGaussianDerivative(double sigma)
+{
+  int length=int(3.0*sigma+0.5)*2+1;
+  vtkImageData* tmp=vtkxqImageFourierConvolution::GaussianDerivative(sigma,length);
+  this->SetFilterBank(tmp);
+  tmp->Delete();
+  this->SetMode(0);
+  return 1;
+}
+
+int vtkxqImageFourierConvolution::SetFilterBankToGaussian(double sigma)
+{
+  int length=int(3.0*sigma+0.5)*2+1;
+  vtkImageData* tmp=vtkxqImageFourierConvolution::Gaussian(sigma,length);
+  this->SetFilterBank(tmp);
+  this->SetMode(0);
+
+  //  vtkpxUtil::SaveAnalyze("filter.hdr",tmp,9);
+  tmp->Delete();
+
+  return 1;
+}
+
+
+
+int vtkxqImageFourierConvolution::SetFilterBankToHessian(double sigma)
+{
+  int length=int(3.0*sigma+0.5)*2+1;
+  vtkImageData* tmp=vtkxqImageFourierConvolution::Hessian(sigma,length);
+  this->SetFilterBank(tmp);
+  tmp->Delete();
+  this->SetMode(0);
+  return 1;
+}
+
+
+vtkImageData* vtkxqImageFourierConvolution::GaussianDerivative(double sigma,int dim)
+{
+  int d[3]; double s[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      d[ia]=dim;
+      s[ia]=sigma;
+    }
+
+  return vtkxqImageFourierConvolution::GaussianDerivative(s,d);
+}
+
+vtkImageData* vtkxqImageFourierConvolution::GaussianDerivative(double sigma[3],int dim[3])
+{
+  vtkImageData* newimg=vtkImageData::New();
+  newimg->SetScalarTypeToDouble();
+  newimg->SetNumberOfScalarComponents(3);
+  newimg->SetDimensions(dim);
+  newimg->AllocateScalars();
+  
+  double midx=0.5*double(dim[0]-1);
+  double midy=0.5*double(dim[1]-1);
+  double midz=0.5*double(dim[2]-1);
+  
+  double invs2[3];
+  for (int ia=0;ia<=2;ia++)
+    invs2[ia]=1.0/(sigma[ia]*sigma[ia]);
+
+  double scalefactor=1.0/(sqrt(2.0*vtkMath::Pi())*sigma[0]*sigma[1]*sigma[2]);
+
+
+  double scale[3];
+  for (int k=0;k<dim[2];k++)
+    {
+      double z=double(k)-midz;
+      double z2=z*z*invs2[2];
+      
+      for (int j=0;j<dim[1];j++)
+	{
+	  double y=double(j)-midy;
+	  double y2=y*y*invs2[1];
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      double x=double(i)-midx;
+	      double x2=x*x*invs2[0];
+
+	      double G=scalefactor*exp(- ( x2+y2+z2));
+	      newimg->SetScalarComponentFromDouble(i,j,k,0, -x*invs2[0]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,1, -y*invs2[1]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,2, -z*invs2[2]*G);
+	    }
+	}
+    }
+	
+
+  return newimg;
+}
+// ---------------------------------------------------------------------------------------
+vtkImageData* vtkxqImageFourierConvolution::Hessian(double sigma,int dim)
+{
+  int d[3]; double s[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      d[ia]=dim;
+      s[ia]=sigma;
+    }
+
+  return vtkxqImageFourierConvolution::Hessian(s,d);
+}
+
+// -------------------------------------------------------------------------------------------------------------------------
+int vtkxqImageFourierConvolution::SetFilterBankToHessian(double sigma[3])
+{
+  int length[3]; 
+  double max_sigma = sigma[0];
+  for (int ia=1; ia<=2; ia++)
+    if (max_sigma < sigma[ia])
+      max_sigma = sigma[ia];
+  for (int ia=0; ia<=2; ia++)
+    length[ia] = int(3.0*max_sigma+0.5)*2+1;
+  
+  vtkImageData* tmp=vtkxqImageFourierConvolution::Hessian(sigma,length);
+  this->SetFilterBank(tmp);
+  
+  if (this->Debug)
+    {
+      int fdim[3]; tmp->GetDimensions(fdim);
+      if (this->Debug)
+	{
+	  fprintf(stderr,"filterbank: \n");
+	  fprintf(stderr,"filter=(%d,%d,%d); length = (%d %d %d)\n",
+		  fdim[0],  fdim[1],  fdim[2],
+		  length[0], length[1], length[2]);
+	}
+      this->FilterBank->GetDimensions(fdim);
+    }
+  tmp->Delete();
+  return 1;
+}
+
+
+vtkImageData* vtkxqImageFourierConvolution::Hessian(double sigma[3],int dim[3])
+{
+  vtkImageData* newimg=vtkImageData::New();
+  newimg->SetScalarTypeToDouble();
+  newimg->SetNumberOfScalarComponents(6);
+  newimg->SetDimensions(dim);
+  newimg->AllocateScalars();
+
+  
+	double midx=0.5*double(dim[0]-1);
+  double midy=0.5*double(dim[1]-1);
+  double midz=0.5*double(dim[2]-1);
+  
+  double invs2[3];
+  double s2[3];
+  double invs4[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      s2[ia]=sigma[ia]*sigma[ia];
+      invs2[ia]=1.0/(s2[ia]);
+      invs4[ia]=invs2[ia]*invs2[ia];
+    }
+
+  double scalefactor=1.0/(sqrt(2.0*vtkMath::Pi())*sqrt(2.0*vtkMath::Pi())*sqrt(2.0*vtkMath::Pi())*sigma[0]*sigma[1]*sigma[2]); // should be sqrt(2pi)^3 but just a constant...
+
+  for (int k=0;k<dim[2];k++)
+    {
+      double z=double(k)-midz;
+      double z2=z*z*invs2[2];
+      
+      for (int j=0;j<dim[1];j++)
+	{
+	  double y=double(j)-midy;
+	  double y2=y*y*invs2[1];
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      double x=double(i)-midx;
+	      double x2=x*x*invs2[0];
+
+	      double G=scalefactor*exp(- 0.5*( x2+y2+z2));
+	      newimg->SetScalarComponentFromDouble(i,j,k,0, (x*x - s2[0])*invs4[0]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,3, (y*y - s2[1])*invs4[1]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,5, (z*z - s2[2])*invs4[2]*G);
+
+	      newimg->SetScalarComponentFromDouble(i,j,k,1, x*y * invs2[0]*invs2[1]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,2, x*z * invs2[0]*invs2[2]*G);
+	      newimg->SetScalarComponentFromDouble(i,j,k,4, y*z * invs2[1]*invs2[2]*G);
+	      
+	    }
+	}
+    }
+  
+  return newimg;
+}
+// ---------------------------------------------------------------------------------------  
+int vtkxqImageFourierConvolution::SetFilterBankToVessel(double anglespacing,int radius,double sigma,double sigma_r)
+{
+  vtkImageData* tmp=vtkxqImageFourierConvolution::qVesselFilter(anglespacing,radius,sigma,sigma_r);
+  this->SetFilterBank(tmp);
+  tmp->Delete();
+  this->SetMode(1);
+  return 1;
+}
+
+int vtkxqImageFourierConvolution::SetFilterBankToSheet(double anglespacing,double anglespacing2,int radius,double sigma,double sigma_r)
+{
+  vtkImageData* tmp=vtkxqImageFourierConvolution::qSheetFilter(anglespacing,anglespacing2,radius,sigma,sigma_r);
+  this->SetFilterBank(tmp);
+  tmp->Delete();
+  this->SetMode(1);
+  return 1;
+}
+// ---------------------------------------------------------------------------------------  
+
+
+vtkPoints* vtkxqImageFourierConvolution::GenerateSpherePoints(int radius)
+{
+  vtkPoints* points=vtkPoints::New();
+    
+  // Create the initial sphere source based on the radius and COG
+  vtkjoSphereSource* sphereSrc = vtkjoSphereSource::New();
+  sphereSrc->SetRadius(radius);
+  sphereSrc->SetCenter(0,0,0);
+  sphereSrc->IcosahedralTessellationOn();
+  sphereSrc->SetSubdivisionLevels(10);
+  sphereSrc->Update();
+  points->ShallowCopy(sphereSrc->GetOutput()->GetPoints());
+  sphereSrc->Delete();
+
+  /*if (this->Debug)
+    fprintf(stderr,"here inside new gen sphere");*/
+    
+  return points;
+}
+
+vtkPoints* vtkxqImageFourierConvolution::GenerateSpherePoints(double& anglespacing,int halfspace,vtkFloatArray* angles)
+{
+  int Debug=0;
+  /* When halfspace ==1  this is supposed to generate points for half a sphere
+     BUG -- equator needs to be cut in half
+  */
+  if (Debug)
+    fprintf(stderr,"Input Spacing=%f\n",anglespacing);
+  int res=int(180.0/anglespacing+0.5);
+  if (res<2)
+    res=2;
+
+  int numtheta=res*2;
+  int numphi=res-1;
+  int numpoints=(numtheta*numphi)+2;
+
+  double pi=vtkMath::Pi();
+  anglespacing=360.0/double(numtheta);
+  double theta_spacing = anglespacing;
+  double phi_spacing = anglespacing;
+  
+  if (halfspace==1)
+    {
+	  if ((int)fmod((float)numphi, 2.0f) == 0)
+		numphi = numphi/2;
+	  else
+	    numphi = int(double(numphi)/2.0+0.5);
+	  if (numphi<2)
+		numphi=2;
+	  phi_spacing = 90.0/double(numphi);
+      
+      numpoints=numtheta*(numphi-1)+numtheta/2+1;
+    }
+
+  if (Debug)
+    fprintf(stderr,"Output numtheta=%d numphi=%d numtotal=%d new spacing=%f halfspace=%d\n",
+	    numtheta,numphi,numpoints,anglespacing,halfspace);
+  
+  double kwdt=theta_spacing*pi/180.0;
+  double kwdp=phi_spacing*pi/180.0;
+
+  int index=0;
+
+  vtkPoints* points=vtkPoints::New();
+  points->SetNumberOfPoints(numpoints);
+  points->SetPoint(0,0.0,0.0,1.0);  index++;
+  if (Debug)
+    fprintf(stderr,"Inserting Point %d (%.2f,%.2f,%.2f)  (theta=%.2f,phi=%.2f)\n",
+	    index,0.0,0.0,1.0,0.0,0.0);
+
+  if (angles!=NULL)
+    {
+      angles->SetNumberOfComponents(2);
+      angles->SetNumberOfTuples(numpoints);
+      angles->SetComponent(0,0,0.0);
+      angles->SetComponent(0,1,0);
+    }
+
+
+  if (!halfspace)
+  {
+  for (int i_phi=1;i_phi<=numphi;i_phi++)
+    {
+      double phi=double(i_phi)*kwdp;
+      for (int i_theta=0;i_theta<numtheta;i_theta++)
+	{
+	  double theta=double(i_theta)*kwdt;
+	  double x=cos(theta)*sin(phi);
+	  double y=sin(theta)*sin(phi);
+	  double z=cos(phi);
+
+	  if (angles!=NULL)
+	    {
+	      angles->SetComponent(0,0,theta);
+	      angles->SetComponent(0,1,phi);
+	    }
+
+	  points->SetPoint(index,x,y,z);
+	  if (Debug)
+	    fprintf(stderr,"Inserting Point %d (%.2f,%.2f,%.2f)  (theta=%.2f,phi=%.2f)\n",
+		    index,x,y,z,theta*180.0/pi,phi*180.0/pi);
+	  ++index;
+	}
+    }
+    points->SetPoint(index,0.0,0.0,-1.0);  
+    if (angles!=NULL)
+    {
+      angles->SetComponent(0,0,0);
+      angles->SetComponent(0,1,pi);
+    }
+
+  }
+  else
+  {
+  for (int i_phi=1;i_phi<numphi;i_phi++)
+    {
+      double phi=double(i_phi)*kwdp;
+      for (int i_theta=0;i_theta<numtheta;i_theta++)
+	{
+	  double theta=double(i_theta)*kwdt;
+	  double x=cos(theta)*sin(phi);
+	  double y=sin(theta)*sin(phi);
+	  double z=cos(phi);
+
+	  if (angles!=NULL)
+	    {
+	      angles->SetComponent(0,0,theta);
+	      angles->SetComponent(0,1,phi);
+	    }
+
+	  points->SetPoint(index,x,y,z);
+	  if (Debug)
+	    fprintf(stderr,"Inserting Point %d (%.2f,%.2f,%.2f)  (theta=%.2f,phi=%.2f)\n",
+		    index,x,y,z,theta*180.0/pi,phi*180.0/pi);
+	  ++index;
+	}
+	}
+	double phi=pi/2.0;
+    for (int i_theta=0;i_theta<(numtheta/2);i_theta++)
+	{
+	  double theta=double(i_theta)*kwdt;
+	  double x=cos(theta)*sin(phi);
+	  double y=sin(theta)*sin(phi);
+	  double z=cos(phi);
+
+	  if (angles!=NULL)
+	    {
+	      angles->SetComponent(0,0,theta);
+	      angles->SetComponent(0,1,phi);
+	    }
+
+	  points->SetPoint(index,x,y,z);
+	  if (Debug)
+	    fprintf(stderr,"Inserting Point %d (%.2f,%.2f,%.2f)  (theta=%.2f,phi=%.2f)\n",
+		    index,x,y,z,theta*180.0/pi,phi*180.0/pi);
+	  ++index;
+	}
+    
+
+
+  }
+
+  return points;
+}    
+
+// ---------------------------------------------------------------------------------------  
+// --- should take more trivial ones (uniform sampling problem on spheres)
+vtkImageData* vtkxqImageFourierConvolution::VesselFilter(double anglespacing,int radius,double sigma,double sigma_r)
+{
+  int Debug=0;
+  int rectmode=0;
+  if (sigma<0.01 || sigma_r<0.01)
+    {
+      rectmode=1;
+      // dummy values here
+      sigma=1.0;
+      sigma_r=1.0;
+    }
+  
+  int dim=radius*2+1;
+  double mid[3];
+  for (int ia=0;ia<=2;ia++)
+    mid[ia]=0.5*double(dim-1);
+
+  double newsp=anglespacing;
+
+  vtkPoints* points=vtkxqImageFourierConvolution::GenerateSpherePoints(newsp);
+  //vtkPoints* points=vtkxqImageFourierConvolution::GenerateSpherePoints(radius);
+  int numfilters=points->GetNumberOfPoints();
+  if (Debug)
+    fprintf(stderr,"\n-%d-\n",numfilters);
+
+  vtkImageData* newimg=vtkImageData::New();
+  newimg->SetScalarTypeToDouble();
+  newimg->SetNumberOfScalarComponents(numfilters);
+  newimg->SetDimensions(dim,dim,dim);
+  newimg->AllocateScalars();
+
+  vtkDataArray* data_arr=newimg->GetPointData()->GetScalars();
+  int numtuples=data_arr->GetNumberOfTuples();
+
+  // Fill Filter
+  vtkDataArray *data=newimg->GetPointData()->GetScalars();  
+  for (int i=0;i<numfilters;i++)
+    data->FillComponent(i,0.0);
+
+  double pi=vtkMath::Pi();
+  double kwd=newsp*pi/180.0;
+  double halfkwd=kwd*0.5;
+
+  double dradius=double(radius);
+  double norm_r=1.0/(sqrt(2.0*pi)*sigma_r);
+  double denom_r=2.0*sigma_r*sigma_r;
+
+  //  sigma=sigma/(dradius*sin(kwd));
+
+  sigma=sigma/(6.0*kwd);
+  double norm  =1.0/(sqrt(2.0*pi)*sigma);
+  double denom=2.0*sigma*sigma;
+
+  if (Debug)
+    {
+      fprintf(stderr,"Rectmode = %d\n",rectmode);
+      fprintf(stderr,"Constants (R) sigma_r=%f norm_r=%f denom_r=%f\n",
+	      sigma_r,norm_r,denom_r);
+      
+      fprintf(stderr,"Constants (A) sigma=%f norm=%f denom=%f\n",
+	      sigma,norm,denom);
+    }
+
+  vtkPoints* points2=vtkPoints::New();
+  points2->Allocate(50,10);
+
+  vtkCellArray* lines2=vtkCellArray::New();
+  lines2->Allocate(50,10);
+
+  points2->InsertNextPoint(mid);
+
+
+  for (int index=0;index<numfilters;index++)
+    {
+      double x[3];
+      points->GetPoint(index,x);
+      vtkMath::Normalize(x);
+
+      double p1[3];
+      for (int ia=0;ia<=2;ia++)
+	p1[ia]=radius*x[ia]+mid[ia];
+
+      int pindex=points2->GetNumberOfPoints();
+      points2->InsertNextPoint(p1);
+
+      vtkIdType ln[2];
+      ln[0]=0; ln[1]=pindex;
+      lines2->InsertNextCell(2,ln);
+	      
+      double sumframe=0.0;
+      for (int k=0;k<dim;k++)
+	{
+	  double p[3];
+	  p[2]=double(k)-mid[2];
+	  for (int j=0;j<dim;j++)
+	    {
+	      p[1]=double(j)-mid[1];
+	      for (int i=0;i<dim;i++)
+		{
+		  p[0]=double(i)-mid[0];
+		  
+		  double r=vtkMath::Norm(p); //+0.0001;
+		  double dotx=(p[0]*x[0]+p[1]*x[1]+p[2]*x[2]);
+		  double g=1.0;
+
+		  double q[3];
+		  for (int ia=0;ia<=2;ia++)
+		    q[ia]=p[ia]-dotx*x[ia];
+		  double dist=vtkMath::Norm(q);
+ 
+		  double normalized_r=r/dradius;
+		  double normalized_d;
+		  if (r>0.0)
+			  normalized_d=asin(dist/r);
+		  else 
+			  normalized_d=0.0;
+
+		  if (dotx<0.0)
+		    normalized_d=pi-normalized_d;
+			  
+		  if (rectmode==0)
+		    g=norm_r*exp(-pow(normalized_r,2.0)/denom_r);
+		  if (normalized_r>1.0)
+		    g=0.0;
+		      
+		  if (rectmode==0)
+		    g*=norm*exp(-pow(normalized_d,2.0)/denom);
+		  if (normalized_d>halfkwd)
+		    g=0.0;
+
+		  sumframe+=g;
+		  newimg->SetScalarComponentFromDouble(i,j,k,index,g);
+		}
+	    }
+	}
+      
+      for (int i=0;i<numtuples;i++)
+	data_arr->SetComponent(i,index,data_arr->GetComponent(i,index)/sumframe);
+    }
+
+
+
+  vtkPolyData* poly=vtkPolyData::New();
+  poly->SetPoints(points2); points2->Delete();
+  poly->SetLines(lines2);   lines2->Delete();
+  
+  /*  vtkPolyDataWriter* w=vtkPolyDataWriter::New();
+  w->SetInput(poly);
+  w->SetFileName("ves.vtk");
+  w->Update();
+  w->Delete();*/
+  poly->Delete();
+  points->Delete();
+
+
+  return newimg;
+}
+
+
+// ---------------------------------------------------------------------------------------  
+// --- should take more trivial ones (uniform sampling problem on spheres)
+vtkImageData* vtkxqImageFourierConvolution::qVesselFilter(double anglespacing,int radius,double sigma,double sigma_r)
+{
+  int Debug=0;
+  if (Debug)
+    fprintf(stderr, "In qvessel\n"); 
+  int rectmode=0;
+  if (sigma<0.01 || sigma_r<0.01)
+    {
+      rectmode=1;
+      // dummy values here
+      sigma=1.0;
+      sigma_r=1.0;
+    }
+  
+  int dim=radius*2+1;
+  double mid[3];
+  for (int ia=0;ia<=2;ia++)
+    mid[ia]=0.5*double(dim-1);
+
+
+  int res=int(180.0/anglespacing+0.5);
+  if (res<2)
+    res=2;
+
+  int numtheta=res*2;
+  int numphi=res;
+  int numfilters=(numtheta*numphi);
+
+  vtkImageData* newimg=vtkImageData::New();
+  newimg->SetScalarTypeToDouble();
+  newimg->SetNumberOfScalarComponents(numfilters);
+  newimg->SetDimensions(dim,dim,dim);
+  newimg->AllocateScalars();
+
+
+  vtkDataArray* data_arr=newimg->GetPointData()->GetScalars();
+  int numtuples=data_arr->GetNumberOfTuples();
+
+  // Fill Filter
+  vtkDataArray *data=newimg->GetPointData()->GetScalars();  
+  for (int i=0;i<numfilters;i++)
+    data->FillComponent(i,0.0);
+
+
+  double pi=vtkMath::Pi();
+  double kwd=anglespacing*pi/180.0;
+  double halfkwd=kwd*0.5;
+
+  double dradius=double(radius);
+  double norm_r=1.0/(sqrt(2.0*pi)*sigma_r);
+  double denom_r=2.0*sigma_r*sigma_r;
+
+  //  sigma=sigma/(dradius*sin(kwd));
+
+  sigma=sigma/(6.0*kwd);
+  double norm  =1.0/(sqrt(2.0*pi)*sigma);
+  double denom=2.0*sigma*sigma;
+
+
+  if (Debug)
+    {
+      fprintf(stderr,"Rectmode = %d\n",rectmode);
+      fprintf(stderr,"Constants (R) sigma_r=%f norm_r=%f denom_r=%f\n",
+	      sigma_r,norm_r,denom_r);
+      
+      fprintf(stderr,"Constants (A) sigma=%f norm=%f denom=%f\n",
+	      sigma,norm,denom);
+    }
+
+  int aindex = 0;
+  for (int index=0;index<numphi;index++)
+    {
+      double sphi = index*kwd;
+      double ephi = (index+1)*kwd;
+      double mphi = sphi + halfkwd;
+      for (int indt=0; indt<numtheta; indt++)
+	{
+	  double stht = indt*kwd; 
+	  double etht = (indt+1)*kwd;
+	  double mtht = stht + halfkwd;
+	  
+	  
+	  double sumframe=0.0;
+	  for (int k=0;k<dim;k++)
+	    {
+	      double p[3];
+	      p[2]=double(k)-mid[2];
+	      for (int j=0;j<dim;j++)
+		{
+		  p[1]=double(j)-mid[1];
+		  for (int i=0;i<dim;i++)
+		    {
+		      p[0]=double(i)-mid[0];
+		      
+		      double r=vtkMath::Norm(p); //+0.0001;
+		      double g=1.0;
+		      
+		      // another way:
+		      double cs; 
+		      if (r>0.0)
+			cs = acos(p[2]/r);
+		      else
+			cs = 0.0;
+		      
+		      double xcs;
+		      double xr = sqrt(p[0]*p[0]+p[1]*p[1]);
+		      if (xr > 0.0)
+			{
+			  xcs = acos(p[0]/xr);
+			  if (p[1]<0.0)
+			    xcs = 2*pi - xcs;
+			}
+		      else
+			xcs = 0.0;
+		      
+		      
+		      double normalized_r=r/dradius;
+		      
+		      if (rectmode==0)
+			g=norm_r*exp(-pow(normalized_r,2.0)/denom_r);
+		      else if (normalized_r>1.0)
+			g=0.0;
+		      
+		      if (rectmode==0)
+			{
+			  double normalized_d = fabs(cs-mphi);
+			  double normalized_xd = fabs(xcs-mtht);
+			  if (normalized_xd > fabs(xcs-mtht+2*pi))
+			    normalized_xd = fabs(xcs-mtht+2*pi);
+			  if (normalized_xd > fabs(xcs-mtht-2*pi))
+			    normalized_xd = fabs(xcs-mtht-2*pi);
+			  
+			  g*=norm*exp(-(pow(normalized_d,2.0)+pow(normalized_xd,2.0))/denom);
+			}
+		      else
+			{
+			  if ((cs >= ephi) || (cs < sphi))
+		    g=0.0;
+			  else
+			    {
+			      if ((xcs >= etht) || (xcs < stht))
+				g = 0.0;
+			    }
+			}
+		      
+		      sumframe+=g;
+		      newimg->SetScalarComponentFromDouble(i,j,k,aindex,g);
+		    }
+		}
+	    }
+	  
+	  for (int i=0;i<numtuples;i++)
+	    data_arr->SetComponent(i,aindex,data_arr->GetComponent(i,aindex)/sumframe);
+	  ++aindex;
+	}
+    }
+
+  return newimg;
+}
+// ---------------------------------------------------------------------------------------  
+vtkImageData* vtkxqImageFourierConvolution::SumComponents(vtkImageData* img)
+{
+  if (img==NULL)
+    return NULL;
+
+  vtkImageData* newimg=vtkImageData::New();
+  newimg->CopyStructure(img);
+  newimg->SetNumberOfScalarComponents(1);
+  newimg->AllocateScalars();
+  
+  vtkDataArray* out=newimg->GetPointData()->GetScalars();
+  vtkDataArray* inp=img->GetPointData()->GetScalars();
+  int numtuples=inp->GetNumberOfTuples();
+  int numframes=inp->GetNumberOfComponents();
+
+  for (int i=0;i<numtuples;i++)
+    {
+      double sum=0.0;
+      for (int j=0;j<numframes;j++)
+	sum+=inp->GetComponent(i,j);
+      out->SetComponent(i,0,sum);
+    }
+  return newimg;
+}
+// ---------------------------------------------------------------------------------------  
+vtkImageData* vtkxqImageFourierConvolution::SheetFilter(double anglespacing,double anglespacing2,int radius,double sigma,double sigma_r)
+{
+  int Debug=0;
+  int rectmode=0;
+  if (sigma<0.01 || sigma_r<0.01)
+    {
+      rectmode=1;
+      // dummy values here
+      sigma=1.0;
+      sigma_r=1.0;
+    }
+
+  double newsp=anglespacing;
+  vtkPoints* points=vtkxqImageFourierConvolution::GenerateSpherePoints(newsp,1);
+
+  
+  //  int numrotations=int(180.0/anglespacing2+0.5);
+  //  if (numrotations<1 || )
+  int numrotations=4;  // quarter-diskcs
+  
+  int numlines=points->GetNumberOfPoints();
+  int numfilters=numlines*numrotations;
+
+  int dim=radius*2+1;
+
+  vtkImageData* newimg=vtkImageData::New();
+  newimg->SetScalarTypeToDouble();
+  newimg->SetNumberOfScalarComponents(numfilters);
+  newimg->SetDimensions(dim,dim,dim);
+  newimg->AllocateScalars();
+
+  vtkDataArray* data_arr=newimg->GetPointData()->GetScalars();
+  int numtuples=data_arr->GetNumberOfTuples();
+
+  if (Debug)
+    fprintf(stderr,"Numlines=%d numrotations=%d numfilters=%d\n",numlines,numrotations,numfilters);
+  
+  double mid[3];
+  for (int ia=0;ia<=2;ia++)
+    mid[ia]=0.5*double(dim-1);
+
+  // Fill Filter
+  vtkDataArray *data=newimg->GetPointData()->GetScalars();  
+  for (int i=0;i<numfilters;i++)
+    data->FillComponent(i,0.0);
+
+  double pi=vtkMath::Pi();
+  double kwd=newsp*pi/180.0;
+
+  double norm_r=1.0/(sqrt(2.0*pi)*sigma_r);
+  double denom_r=2.0*sigma_r*sigma_r;
+
+  sigma=sigma*0.4*sin(0.5*kwd);
+
+  double norm  =1.0/(sqrt(2.0*pi)*sigma);
+  double denom=2.0*sigma*sigma;
+
+  if (Debug)
+    {
+      fprintf(stderr,"Rectmode = %d\n",rectmode);
+      fprintf(stderr,"Constants (R) sigma_r=%f norm_r=%f denom_r=%f\n",
+	      sigma_r,norm_r,denom_r);
+      
+      fprintf(stderr,"Constants (A) sigma=%f norm=%f denom=%f\n",
+	      sigma,norm,denom);
+    }
+
+
+  vtkPoints* points2=vtkPoints::New();
+  points2->Allocate(50,10);
+
+  vtkCellArray* lines2=vtkCellArray::New();
+  lines2->Allocate(50,10);
+
+  points2->InsertNextPoint(mid);
+  int index=0;
+  double dradius=double(radius);
+
+  for (int outer=0;outer<numlines;outer++)
+    {
+      double x[3]; points->GetPoint(outer,x);
+      vtkMath::Normalize(x);
+      for (int inner=0;inner<numrotations;inner++)
+	{
+	  double angle=pi*double(inner)/double(numrotations);
+	  double y[3],z[3]; vtkMath::Perpendiculars(x,y,z,angle);
+
+	  vtkMath::Normalize(y);
+	  vtkMath::Normalize(z);
+	  double p1[3],p2[3];
+	  int pindex=points2->GetNumberOfPoints();
+	  for (int ia=0;ia<=2;ia++)
+	    {
+	      p1[ia]=20.0*x[ia]+mid[ia];
+	      p2[ia]=5.0*y[ia]+p1[ia];
+	    }
+	  points2->InsertNextPoint(p1);
+	  points2->InsertNextPoint(p2);
+	  vtkIdType ln[2];
+	  ln[0]=0; ln[1]=pindex;
+	  lines2->InsertNextCell(2,ln);
+	  ln[0]=pindex+1;
+	  lines2->InsertNextCell(2,ln);
+	      
+	  double sumframe=0.0;
+	  for (int k=0;k<dim;k++)
+	    {
+	      double p[3];
+	      p[2]=double(k)-mid[2];
+	      for (int j=0;j<dim;j++)
+		{
+		  p[1]=double(j)-mid[1];
+		  for (int i=0;i<dim;i++)
+		    {
+		      p[0]=double(i)-mid[0];
+
+		      double r=vtkMath::Norm(p)+0.001;
+		      double dotx=(p[0]*x[0]+p[1]*x[1]+p[2]*x[2]);
+		      double g=1.0;
+		      dotx=fabs(dotx);
+
+		      if (dotx>=0.0)
+			{
+			  double dot=(p[0]*z[0]+p[1]*z[1]+p[2]*z[2]);
+			  double normalized_r=r/dradius;
+			  double normalized_d=fabs(dot)/dradius;
+			  
+			  if (rectmode==0)
+			    g=norm_r*exp(-pow(normalized_r,2.0)/denom_r);
+			  if (normalized_r>1.0)
+			    g=0.0;
+			  
+			  if (rectmode==0)
+			    g*=norm*exp(-pow(normalized_d,2.0)/denom);
+			  else if (normalized_d>0.2)
+			    g=0.0;
+			}
+		      else
+			{
+			  g=0.0;
+			}
+		      sumframe+=g;
+		      newimg->SetScalarComponentFromDouble(i,j,k,index,g);
+		    }
+		}
+	    }
+
+
+	  for (int i=0;i<numtuples;i++)
+	    data_arr->SetComponent(i,index,data_arr->GetComponent(i,index)/sumframe);
+	  ++index;
+	}
+    }
+
+
+  vtkPolyData* poly=vtkPolyData::New();
+  poly->SetPoints(points2); points2->Delete();
+  poly->SetLines(lines2);   lines2->Delete();
+  
+  /*  vtkPolyDataWriter* w=vtkPolyDataWriter::New();
+  w->SetInput(poly);
+  w->SetFileName("sheet.vtk");
+  w->Update();
+  w->Delete();*/
+  poly->Delete();
+  points->Delete();
+
+  return newimg;
+}
+
+// ---------------------------------------------------------------------------------------  
+vtkImageData* vtkxqImageFourierConvolution::qSheetFilter(double anglespacing,double anglespacing2,int radius,double sigma,double sigma_r)
+{
+  int Debug=0;
+  int rectmode=0;
+  if (sigma<0.01 || sigma_r<0.01)
+    {
+      rectmode=1;
+      // dummy values here
+      sigma=1.0;
+      sigma_r=1.0;
+    }
+
+  double newsp=anglespacing;
+  vtkPoints* points=vtkxqImageFourierConvolution::GenerateSpherePoints(newsp,1);
+
+  
+  //  int numrotations=int(180.0/anglespacing2+0.5);
+  //  if (numrotations<1 || )
+  int numrotations=4;  // quarter-diskcs
+  
+  int numlines=points->GetNumberOfPoints();
+  int numfilters=numlines*numrotations;
+
+  int dim=radius*2+1;
+
+  vtkImageData* newimg=vtkImageData::New();
+  newimg->SetScalarTypeToDouble();
+  newimg->SetNumberOfScalarComponents(numfilters);
+  newimg->SetDimensions(dim,dim,dim);
+  newimg->AllocateScalars();
+
+  vtkDataArray* data_arr=newimg->GetPointData()->GetScalars();
+  int numtuples=data_arr->GetNumberOfTuples();
+
+  if (Debug)
+    fprintf(stderr,"Numlines=%d numrotations=%d numfilters=%d\n",numlines,numrotations,numfilters);
+  
+  double mid[3];
+  for (int ia=0;ia<=2;ia++)
+    mid[ia]=0.5*double(dim-1);
+
+  // Fill Filter
+  vtkDataArray *data=newimg->GetPointData()->GetScalars();  
+  for (int i=0;i<numfilters;i++)
+    data->FillComponent(i,0.0);
+
+  double pi=vtkMath::Pi();
+  double kwd=newsp*pi/180.0;
+
+  double norm_r=1.0/(sqrt(2.0*pi)*sigma_r);
+  double denom_r=2.0*sigma_r*sigma_r;
+
+  sigma=sigma*0.4*sin(0.5*kwd);
+
+  double norm  =1.0/(sqrt(2.0*pi)*sigma);
+  double denom=2.0*sigma*sigma;
+
+  if (Debug)
+    {
+      fprintf(stderr,"Rectmode = %d\n",rectmode);
+      fprintf(stderr,"Constants (R) sigma_r=%f norm_r=%f denom_r=%f\n",
+	      sigma_r,norm_r,denom_r);
+      
+      fprintf(stderr,"Constants (A) sigma=%f norm=%f denom=%f\n",
+	      sigma,norm,denom);
+    }
+
+  int index=0;
+  double dradius=double(radius);
+
+  for (int outer=0;outer<numlines;outer++)
+    {
+      double x[3]; points->GetPoint(outer,x);
+      vtkMath::Normalize(x);
+	  
+      for (int inner=0;inner<numrotations;inner++)
+	{
+	  double angle=2*pi*double(inner)/double(numrotations);
+	  double y[3],z[3]; vtkMath::Perpendiculars(x,y,z,angle);
+
+	  vtkMath::Normalize(y);
+	  vtkMath::Normalize(z);
+
+      //fprintf(stderr,"out%i\t x= (%f %f %f); \n\t y=(%f %f %f); \n\t z= (%f %f %f)\n",
+	  //outer, x[0], x[1], x[2], y[0], y[1], y[2], z[0], z[1], z[2]);
+
+	  double sumframe=0.0;
+	  for (int k=0;k<dim;k++)
+	    {
+	      double p[3];
+	      p[2]=double(k)-mid[2];
+	      for (int j=0;j<dim;j++)
+		{
+		  p[1]=double(j)-mid[1];
+		  for (int i=0;i<dim;i++)
+		    {
+		      p[0]=double(i)-mid[0];
+
+		      double r=vtkMath::Norm(p)+0.001;
+		      double dotx=(p[0]*x[0]+p[1]*x[1]+p[2]*x[2]);
+			  double doty=(p[0]*y[0]+p[1]*y[1]+p[2]*y[2]);
+			  double dotz=(p[0]*z[0]+p[1]*z[1]+p[2]*z[2]);
+		      double g=1.0;
+		      //dotx=fabs(dotx);
+
+		      if (doty>=0.0 && dotz>=0.0)
+			{
+			  double normalized_r=r/dradius;
+			  double normalized_d=fabs(dotx)/dradius;
+			  
+			  if (rectmode==0)
+			    g=norm_r*exp(-pow(normalized_r,2.0)/denom_r);
+			  else if (normalized_r>1.0)
+			    g=0.0;
+			  
+			  if (rectmode==0)
+			    g*=norm*exp(-pow(normalized_d,2.0)/denom);
+			  else if (normalized_d>0.3)
+			    g=0.0;
+//      fprintf(stderr,"Rectmode = %d\n",rectmode);
+//  fprintf(stderr,"Constants (R) normalized_r=%f normalized_d=%f g=%f\n",
+//	  normalized_r,normalized_d,g);
+			}
+		      else
+			{
+			  g=0.0;
+			}
+		      sumframe+=g;
+		      newimg->SetScalarComponentFromDouble(i,j,k,index,g);
+
+		    }
+		}
+	    }
+
+	  for (int i=0;i<numtuples;i++)
+	    data_arr->SetComponent(i,index,data_arr->GetComponent(i,index)/sumframe);
+	  ++index;
+	}
+    }
+
+  points->Delete();
+
+  return newimg;
+}
+// -------------------------------------------------------------------------------------------
+vtkImageData* vtkxqImageFourierConvolution::Gaussian(double sigma,int dim)
+{
+  int d[3]; double s[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      d[ia]=dim;
+      s[ia]=sigma;
+    }
+
+  return vtkxqImageFourierConvolution::Gaussian(s,d);
+}
+
+vtkImageData* vtkxqImageFourierConvolution::Gaussian(double sigma[3],int dim[3])
+{
+  vtkImageData* newimg=vtkImageData::New();
+  newimg->SetScalarTypeToDouble();
+  newimg->SetNumberOfScalarComponents(1);
+  newimg->SetDimensions(dim);
+  newimg->AllocateScalars();
+  
+  double midx=0.5*double(dim[0]-1);
+  double midy=0.5*double(dim[1]-1);
+  double midz=0.5*double(dim[2]-1);
+  
+  double invs2[3];
+  for (int ia=0;ia<=2;ia++)
+    invs2[ia]=1.0/(sigma[ia]*sigma[ia]);
+
+  double scalefactor=1.0/(sqrt(2.0*vtkMath::Pi())*sigma[0]*sigma[1]*sigma[2]);
+  double sum=1.0;
+
+  double scale[3];
+  for (int k=0;k<dim[2];k++)
+    {
+      double z=double(k)-midz;
+      double z2=z*z*invs2[2];
+      
+      for (int j=0;j<dim[1];j++)
+	{
+	  double y=double(j)-midy;
+	  double y2=y*y*invs2[1];
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      double x=double(i)-midx;
+	      double x2=x*x*invs2[0];
+
+	      double G=exp(- ( x2+y2+z2));
+	      sum+=G;
+	      newimg->SetScalarComponentFromDouble(i,j,k,0, G);
+	    }
+	}
+    }
+
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	newimg->SetScalarComponentFromDouble(i,j,k,0, newimg->GetScalarComponentAsDouble(i,j,k,0)/sum);
+
+	
+  return newimg;
+}
+
+int vtkxqImageFourierConvolution::SetFilterBankToMultiScaleBlob(double scalefactor,double sigma)
+{
+  vtkFloatArray* s=vtkFloatArray::New();
+  s->SetNumberOfTuples(1);
+  s->SetComponent(0,0,sigma);
+  int ok=this->SetFilterBankToMultiScaleBlob(scalefactor,s);
+  s->Delete();
+  return ok;
+}
+  
+
+int vtkxqImageFourierConvolution::SetFilterBankToMultiScaleBlob(double scalefactor,vtkFloatArray* sigmas)
+{
+  if (sigmas==NULL)
+    return 0;
+
+
+  int nfilters=sigmas->GetNumberOfTuples();
+  double range[2]; sigmas->GetRange(range);
+
+  int length=int(2.0*range[1]+0.5)*2+1;
+  double mid=int(2.0*range[1]+0.5);
+
+  length=3;
+  mid=1.0;
+
+
+  if (length<3)
+    {
+      length=3;
+      mid=1.0;
+    }
+
+  vtkImageData* newimg=vtkImageData::New();
+
+  newimg->SetScalarTypeToDouble();
+  newimg->SetNumberOfScalarComponents(nfilters);
+  newimg->SetDimensions(length,length,length);
+  newimg->AllocateScalars();
+
+  fprintf(stderr,"Image Size=%d, mid=%f\n",length,mid);
+
+
+
+  for (int i=0;i<=2;i++)
+    for (int j=0;j<=2;j++)
+      for (int k=0;k<=2;k++)
+	{
+	  double v=0.0;
+	  if (i==1 && j==1 && k==1)
+	    v=1.0;
+	  else if ( (i==0 || i==2) && j==1 && k==1)
+	    v=-0.125;
+	  else if ( (j==0 || j==2) && i==1 && k==1)
+	    v=-0.125;
+	  else if ( (k==0 || k==2) && j==1 && i==1)
+	    v=-0.125;
+	  for (int f=0;f<nfilters;f++)
+	    newimg->SetScalarComponentFromDouble(i,j,k,f,v);
+	}
+  
+  this->SetFilterBank(newimg);
+  this->SetMode(0);
+  newimg->Delete();
+  return 1;
+
+
+
+
+
+
+
+  for (int f=0;f<nfilters;f++)
+    {
+      double sigma=sigmas->GetComponent(f,0);
+      double s2=sigma*sigma;
+      double invs2=1.0/(s2);
+      double invs4=invs2*invs2;
+      double norm=scalefactor/(sqrt(2.0*vtkMath::Pi())*sqrt(2.0*vtkMath::Pi())*sqrt(2.0*vtkMath::Pi())*sigma*sigma*sigma); // should be sqrt(2pi)^3 but just a constant...
+
+      fprintf(stderr,"sigma=%.2f f=%d/%d length=%d\n",sigma,f,nfilters,length);
+
+      double sum=0.0;
+      for (int k=0;k<length;k++)
+	{
+	  double z=double(k)-mid;
+	  double z2=z*z*invs2;
+
+	  for (int j=0;j<length;j++)
+	    {
+	      double y=double(j)-mid;
+	      double y2=y*y*invs2;
+	      for (int i=0;i<length;i++)
+		{
+		  double x=double(i)-mid;
+		  double x2=x*x*invs2;
+		  
+		  /*		  double G=scalefactor*exp(- 0.5*( x2+y2+z2));
+
+		  double zf=(z*z - s2);
+		  double yf=(x*x - s2);
+		  double xf=(y*y - s2);
+
+		  double v=(xf+yf+zf)*invs4[0]*G;*/
+
+		  double rsq=x*x+y*y+z*z;
+		  double r=sqrt(rsq);
+		  double r2=r*r*invs2;
+		  double G=norm*exp(- 0.5*r2);
+		  double v=(rsq - s2)*invs4*G;
+		  newimg->SetScalarComponentFromDouble(i,j,k,f,v);
+		  sum+=v;
+		}
+	    }
+	}
+      
+      double mean=sum/(length*length*length);
+      fprintf(stdout,"f=%d, siggma=%f mean=%f\n",f,sigma,mean);
+      for (int k=0;k<length;k++)
+	for (int j=0;j<length;j++)
+	  for (int i=0;i<length;i++)
+	    newimg->SetScalarComponentFromDouble(i,j,k,f,
+						 newimg->GetScalarComponentAsDouble(i,j,k,f)-mean);
+    }
+  
+
+  this->SetFilterBank(newimg);
+  this->SetMode(0);
+  newimg->Delete();
+
+
+
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkxqImageFourierConvolution.h b/bioimagesuite30_src/Imaging/vtkxqImageFourierConvolution.h
new file mode 100644
index 0000000..6199c6b
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkxqImageFourierConvolution.h
@@ -0,0 +1,179 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkxqImageFourierConvolution.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkxqImageFourierConvolution -- compute Convolution of Image with Filter Bank
+// in Fourier Space
+
+#ifndef __vtkxqImageFourierConvolution_h
+#define __vtkxqImageFourierConvolution_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPoints.h"
+#include "vtkFloatArray.h"
+
+class vtkxqImageFourierConvolution : public vtkSimpleImageToImageFilter
+{
+public:
+  static vtkxqImageFourierConvolution *New();
+  vtkTypeMacro(vtkxqImageFourierConvolution,vtkSimpleImageToImageFilter);
+
+  // Description:
+  // DistanceMap -- distance from traced structure
+  vtkSetObjectMacro(FilterBank,vtkImageData);
+  vtkGetObjectMacro(FilterBank,vtkImageData);
+
+  // Description:
+  // Mode
+  vtkGetMacro(Mode,int);
+  vtkSetClampMacro(Mode,int,0,2);
+  virtual void SetModeToConvolve()  { this->SetMode(0); }
+  virtual void SetModeToDeviation() { this->SetMode(1); }
+  virtual void SetModeToBoth()      { this->SetMode(2); }
+
+  // Description:
+  // Second Output is Mean Image in case when Mode = 2
+  vtkGetObjectMacro(SecondOutput,vtkImageData);
+
+  // Description:
+  // Precision
+  vtkSetClampMacro(DoublePrecision,int,0,1);
+  vtkGetMacro(DoublePrecision,int);
+
+  // Description:
+  // Precision
+  vtkSetClampMacro(ForceCPU,int,0,1);
+  vtkGetMacro(ForceCPU,int);
+
+
+  // Description:
+  // Standard Filter Banks for gradients/hessian/vessel filters and sheet filters
+  // ----------------------------------------------------------------------------
+  virtual int SetFilterBankToGaussianDerivative(double sigma);
+  virtual int SetFilterBankToGaussian(double sigma);
+  virtual int SetFilterBankToHessian(double sigma);
+
+  virtual int SetFilterBankToGaussianDerivative(double sigma1,double sigma2,double sigma3,double radius);
+  virtual int SetFilterBankToGaussian(double sigma1,double sigma2,double sigma3,double radius);
+  virtual int SetFilterBankToHessian(double sigma1,double sigma2,double sigma3,double radius);
+
+
+  virtual int SetFilterBankToHessian(double sigma[3]);
+  virtual int SetFilterBankToVessel(double anglespacing,int radius,double sigma_r=2.0,double sigma=2.0);
+  virtual int SetFilterBankToSheet(double anglespacing,double anglespacing2,int radius,double sigma_r=2.0,double sigma=2.0);
+
+  // Description:
+  virtual int SetFilterBankToMultiScaleBlob(double scalefactor,double sigma);
+  virtual int SetFilterBankToMultiScaleBlob(double scalefactor,vtkFloatArray* sigmas);
+
+  // Description:
+  // Static Utility Functions to Generate Some Standard Filters
+  // ----------------------------------------------------------------------------
+  static vtkImageData* Gaussian(double sigma,int dim);
+  static vtkImageData* Gaussian(double sigma[3],int dim[3]);
+  static vtkImageData* GaussianDerivative(double sigma,int dim);
+  static vtkImageData* GaussianDerivative(double sigma[3],int dim[3]);
+
+  static vtkImageData* Hessian(double sigma,int dim);
+  static vtkImageData* Hessian(double sigma[3],int dim[3]);
+
+  // Set sigmas to 0 to get rectmode
+  static vtkImageData* VesselFilter(double anglespacing,int radius,double sigma_r=3.0,double sigma=2.0);
+  static vtkImageData* SheetFilter(double anglespacing,double anglespacing2,int radius,double sigma=0.2,double sigma_r=1.0);
+
+  // XQ's version:
+  static vtkImageData* qVesselFilter(double anglespacing,int radius,double sigma_r=3.0,double sigma=2.0);
+  static vtkImageData* qSheetFilter(double anglespacing,double anglespacing2,int radius,double sigma=0.2,double sigma_r=1.0);
+  
+  static vtkImageData* SumComponents(vtkImageData* img);
+  static vtkPoints* GenerateSpherePoints(double& anglespacing,int halfspace=0,vtkFloatArray* angles=NULL);
+  static vtkPoints* GenerateSpherePoints(int radius);
+protected:
+
+  vtkxqImageFourierConvolution();
+  virtual ~vtkxqImageFourierConvolution();
+  vtkxqImageFourierConvolution(const vtkxqImageFourierConvolution&) {};
+  void operator=(const vtkxqImageFourierConvolution&) {};
+
+  // Description:
+  // Basic Input Outputs
+  // ----------------------------------------------------------------------------
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  
+				 vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  // Description:
+  // Data
+  // ----------------------------------------------------------------------------
+  vtkImageData* FilterBank;
+  vtkImageData* SecondOutput;
+  int           Mode;
+  int           DoublePrecision;
+  int           ForceCPU;
+
+  // Description:
+  // Normalize 'new' sphere filters.
+  virtual void normalizeFilters(vtkImageData* FILTERS);
+  // Description:
+  // Basic Operations for Convolutions in Fourier Space
+  // ----------------------------------------------------------------------------
+  virtual vtkImageData* PadImage(vtkImageData* img,int paddim[3]);
+  virtual vtkImageData* FFTImage(vtkImageData* img,int frame,int paddim[3],int dosquare);
+  virtual vtkImageData* DoFourierConvolution(vtkImageData* img1,vtkImageData* img2,int origdim[3],double origori[3], int DoSqaure);
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkxqImageHessian.cpp b/bioimagesuite30_src/Imaging/vtkxqImageHessian.cpp
new file mode 100644
index 0000000..5fd9088
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkxqImageHessian.cpp
@@ -0,0 +1,107 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkxqImageHessian.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageGradient.h"
+#include "vtkImageExtractComponents.h"
+
+//#include "vtkpxAppendComponents.h"
+#include "vtkImageShiftScale.h"
+#include "vtkImageMathematics.h"
+#include "vtkImageCast.h"
+#include "vtkMath.h"
+#include "vtkImageReslice.h"
+#include "vtkImageFFT.h"
+#include "vtkImageRFFT.h"
+#include "bioimagesuite_settings.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+
+
+//------------------------------------------------------------------------------
+vtkxqImageHessian* vtkxqImageHessian::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkxqImageHessian");
+  if(ret)
+    {
+      return (vtkxqImageHessian*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkxqImageHessian;
+}
+
+// Construct object with no children.
+vtkxqImageHessian::vtkxqImageHessian()
+{
+  this->Sigma=1.0;
+  this->Mode=0;
+}
+
+// -------------------------------------------------------------------------------------------------------------------
+int vtkxqImageHessian::RequestInformation(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+						     vtkInformationVector *outputVector)
+
+{  
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+  vtkDataObject::SetPointDataActiveScalarInfo(outInfo, VTK_FLOAT, -1);
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), -1, 6);
+  return 1; 
+}
+// -------------------------------------------------------------------------------------------------------------------
+void vtkxqImageHessian::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs");
+      return;
+    }
+
+  if (input->GetNumberOfScalarComponents()!=1)
+    {
+      vtkErrorMacro(<<"Only Single Component Images are valid inputs\n");
+      return;
+    }
+
+  double sp[3]; input->GetSpacing(sp);
+  double sig[3];
+  for (int ia=0;ia<=2;ia++)
+    sig[ia]=this->Sigma*sp[0]/sp[ia];      
+  this->SetFilterBankToHessian(sig);
+  this->UpdateProgress(0.05);
+
+
+  this->vtkxqImageFourierConvolution::SimpleExecute(input,output);
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkxqImageHessian.h b/bioimagesuite30_src/Imaging/vtkxqImageHessian.h
new file mode 100644
index 0000000..9dc7028
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkxqImageHessian.h
@@ -0,0 +1,71 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+/* Computes the Hessian image */
+
+#ifndef __vtkxqImageHessian_h
+#define __vtkxqImageHessian_h
+
+#include "vtkImageData.h"
+#include "vtkxqImageFourierConvolution.h"
+
+class vtkxqImageHessian : public vtkxqImageFourierConvolution
+{
+public:
+  static vtkxqImageHessian *New();
+  vtkTypeMacro(vtkxqImageHessian,vtkxqImageFourierConvolution);
+
+  // Description:
+  // Set Scale Sigma
+  vtkGetMacro(Sigma,float);
+  vtkSetMacro(Sigma,float);
+
+protected:
+
+  //BTX
+  vtkxqImageHessian();
+  vtkxqImageHessian(const vtkxqImageHessian&) {};
+  void operator=(const vtkxqImageHessian&) {};
+  //ETX
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  
+				 vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+  float Sigma;
+
+  // Description:
+  // Filter Bank Image -- Make this protected now
+  vtkSetObjectMacro(FilterBank,vtkImageData);
+  
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkxqImageKMeansVesselnessFilter.cpp b/bioimagesuite30_src/Imaging/vtkxqImageKMeansVesselnessFilter.cpp
new file mode 100644
index 0000000..452477f
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkxqImageKMeansVesselnessFilter.cpp
@@ -0,0 +1,442 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkxqImageKMeansVesselnessFilter.h"
+#include "vtkImageReslice.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkImageFFT.h"
+#include "vtkImageRFFT.h"
+//#include "vtkpxImageFloatFFT.h"
+//#include "vtkpxImageFloatRFFT.h"
+#include "vtkImageCast.h"
+#include "vtkImageMagnitude.h"
+#include "vtkImageMathematics.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+#include "vtkImageShiftScale.h"
+#include "vtkMath.h"
+#include "pxisinf.h"
+
+//------------------------------------------------------------------------------
+vtkxqImageKMeansVesselnessFilter* vtkxqImageKMeansVesselnessFilter::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkxqImageKMeansVesselnessFilter");
+  if(ret)
+    {
+    return (vtkxqImageKMeansVesselnessFilter*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkxqImageKMeansVesselnessFilter;
+}
+
+// Construct object with no children.
+vtkxqImageKMeansVesselnessFilter::vtkxqImageKMeansVesselnessFilter()
+{
+  this->Sigma=0.2;
+  this->Beta=5.0;
+  this->Alpha=1.0;
+  this->ComputeAuxOutput=1;
+  this->AuxOutput=NULL;
+  this->SecondInput=NULL;
+}
+// ----------------------------------------------------------------------------
+vtkxqImageKMeansVesselnessFilter::~vtkxqImageKMeansVesselnessFilter()
+{
+  this->SetSecondInput(NULL);
+  if (this->AuxOutput!=NULL)
+    this->AuxOutput->Delete();
+
+
+}
+// ----------------------------------------------------------------------------
+void vtkxqImageKMeansVesselnessFilter::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData* input=this->GetInput();
+  vtkImageData* output=this->GetOutput();
+
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"No Input Set");
+      return;
+    }
+  output->SetScalarTypeToFloat();
+  output->SetNumberOfScalarComponents(1);
+}
+// -------------------------------------------------------------------------------------------------------------
+void vtkxqImageKMeansVesselnessFilter::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Input to vtkxqImageKMeansVesselnessFilter");
+      return;
+    }
+  
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* inp2=NULL;
+
+  if (this->SecondInput!=NULL)
+    inp2=this->SecondInput->GetPointData()->GetScalars();
+
+  if (this->AuxOutput!=NULL)
+    {
+      this->AuxOutput->Delete();
+      this->AuxOutput=NULL;
+    }
+
+
+  vtkDataArray* auxout=NULL;
+  if (this->ComputeAuxOutput)
+    {
+      this->AuxOutput=vtkImageData::New();
+      this->AuxOutput->CopyStructure(input);
+      this->AuxOutput->SetScalarTypeToFloat();
+      this->AuxOutput->SetNumberOfScalarComponents(10);
+      this->AuxOutput->AllocateScalars();
+      auxout=this->AuxOutput->GetPointData()->GetScalars();
+      for (int ia=0;ia<auxout->GetNumberOfComponents();ia++)
+	auxout->FillComponent(ia,-1.0);
+    }
+
+  output->GetPointData()->GetScalars()->FillComponent(0,-1.0);
+  this->ComputeMeasure(inp,inp2,out,auxout);
+  this->UpdateProgress(1.0);
+}
+// -------------------------------------------------------------------------------------------------------------
+int vtkxqImageKMeansVesselnessFilter::ComputeClustering(int np,double* data,double* data2,double mean[2],double sigma[2],double meanint[2],double sigmaint[2],int debug)
+{
+  // Inititalize
+  double minv=data[0],maxv=data[0];
+  for (int i=1;i<np;i++)
+    {
+      if (data[i]<minv)
+	minv=data[i];
+      else if (data[i]>maxv)
+	maxv=data[i];
+    }
+	
+  double threshold=0.5*(maxv+minv);
+
+
+  if (debug)
+    {
+      fprintf(stderr,"\n\n -------------------------------------------------------------\n min=%f , max=%f\n",minv,maxv);
+      for (int i=0;i<np;i++)
+	{
+	  fprintf(stderr,"Data Element %d \t %f",i,data[i]);
+	  if (data2!=NULL)
+	    fprintf(stderr,"\t %f",data2[i]);
+	  fprintf(stderr,"\n");
+	}
+      fprintf(stderr,"Beginning Iteration %d\t min=%f \t max=%f \t thr=%f\n",0,minv,maxv,threshold);
+    }
+
+  double dthreshold=fabs(threshold*0.05);
+  double lastchange=dthreshold+1.0;
+  int    iter=0,maxiter=20;
+  int num[2];
+
+  while (iter<maxiter && lastchange > dthreshold)
+    {
+      for (int cl=0;cl<=1;cl++)
+	{
+	  num[cl]=0;
+	  mean[cl]=0.0;
+	}
+      
+      for (int i=0;i<np;i++)
+	{
+	  int cl=1;
+	  if (data[i] < threshold)
+	    cl=0;
+	  num[cl]++;
+	  mean[cl]+=data[i];
+	}
+      
+      if (num[0]==0 && num[1]==0)  //?
+	{
+	  for (int ia=0;ia<=1;ia++)
+	    {
+	      mean[ia]=0.0; sigma[ia]=1.0;
+	      meanint[ia]=0.0; sigmaint[ia]=1.0;
+	    }
+	  return 0;
+	}
+      
+      for (int cl=0;cl<=1;cl++)
+	mean[cl]/=double(num[cl]);
+
+      double oldthr=threshold;
+      threshold=0.5*(mean[0]+mean[1]);
+      lastchange=fabs(threshold-oldthr);
+      ++iter;
+
+      if (debug)
+	fprintf(stderr,"End Of Iteration %d\t mean[0]=%f \t mean[1]=%f \t threshold=%f oldthr=%f lastchange=%f, dthreshold=%f\n",iter,mean[0],mean[1],threshold,oldthr,lastchange,dthreshold);
+    }
+
+  
+
+  // By now we are all converged so compute output sums
+  for (int cl=0;cl<=1;cl++)
+    {
+      num[cl]=0;
+      mean[cl]=0.0;
+      sigma[cl]=0.0;
+      meanint[cl]=0.0;
+      sigmaint[cl]=0.0;
+    }
+    
+  for (int i=0;i<np;i++)
+    {
+      int cl=1;
+      if (data[i] < threshold)
+	cl=0;
+      num[cl]+=1;
+      mean[cl]+=data[i];
+      sigma[cl]+=pow(data[i],2.0);
+
+      if (data2!=NULL)
+	{
+	  meanint[cl]+=data2[i];
+	  sigmaint[cl]+=pow(data2[i],2.0);
+	}
+    }
+
+  // Compute Sigma, Meanint and sigmaint
+  for (int cl=0;cl<=1;cl++)
+    {
+      if (num[cl]!=0)
+	{
+	  mean[cl]/=double(num[cl]);
+	  sigma[cl]/=double(num[cl]);
+	  sigma[cl]=sqrt(sigma[cl]-(mean[cl]*mean[cl]));
+
+	  if (debug)
+	    {
+	      fprintf(stderr, "c1: %d sigma-c1 %f\n", cl, sigma[cl]);
+	      fprintf(stderr,"\t\t Class %d (deviation)\t num=%d\t mean=%f \t sigma=%f\n",cl,num[cl],mean[cl],sigma[cl]);
+	    }
+	  
+	  if (data2!=NULL)
+	    {
+	      meanint[cl]/=double(num[cl]);
+	      sigmaint[cl]/=double(num[cl]);
+	      sigmaint[cl]=sqrt(sigmaint[cl]-meanint[cl]*meanint[cl]);
+	      if (debug)
+		fprintf(stderr,"\t\t Class %d (intensity)\t num=%d\t %f \t %f\n",cl,num[cl],meanint[cl],sigmaint[cl]);
+	    }
+	}
+      else
+	{
+	  fprintf(stderr,"*");
+	  mean[cl]=0.0;
+	  sigma[cl]=0.0;
+	  if (data2!=NULL)
+	    {
+	      meanint[cl]=0.0;
+	      sigmaint[cl]=0.0;
+	    }
+	}
+    }
+
+  if (debug)
+    fprintf(stderr," -------------------------------------------------------------\n\n");
+
+
+  return num[0];
+}
+// -------------------------------------------------------------------------------------------------------------
+void vtkxqImageKMeansVesselnessFilter::ComputeMeasure(vtkDataArray* inp,vtkDataArray* inp2,vtkDataArray* out,vtkDataArray* auxout)
+{
+  int nc=inp->GetNumberOfComponents();
+  int nt=inp->GetNumberOfTuples();
+
+  fprintf(stderr,"\t nc=%d  nt=%d Beta=%.2f \n",nc, nt, this->Beta);
+  double* dt=new double[nc];
+  double* dt2=NULL;
+  double mean[2],sigma[2],meanint[2],sigmaint[2];
+
+  if (inp2!=NULL)
+    dt2=new double[nc];
+
+  int tenth=nt/10;
+  int count=0;
+
+  double clustersigma2=2.0*pow((this->Sigma)*double(nc),2.0);  
+
+
+  double range[2]; inp->GetRange(range);
+  double threshold=range[0];//0.95*range[0]+0.05*range[1];
+
+  fprintf(stderr,"Threshold=%.2f \n",threshold);
+
+
+
+
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      int debug=0;
+      if (voxel==16820)
+	debug=1;
+
+      double meanraw=0.0;
+      double minraw=inp->GetComponent(voxel,0);
+      for (int comp=0;comp<nc;comp++)
+	{
+	  double v=inp->GetComponent(voxel,comp);
+	  meanraw+=v;
+	  if (v<minraw)
+	    minraw=v;
+	}
+      minraw=0.0;
+      
+      meanraw=meanraw/double(nc);
+      if (meanraw>threshold)
+	{
+	  // Create Arrays (dt,dt2)
+	  for (int comp=0;comp<nc;comp++)
+	    {
+	      dt[comp]=inp->GetComponent(voxel,comp);
+	      if (inp2!=NULL)
+		dt2[comp]=inp2->GetComponent(voxel,comp);
+	    }
+	  
+	  // Do Clustering and extract values
+	  int numc1=this->ComputeClustering(nc,dt,dt2,mean,sigma,meanint,sigmaint,debug);
+	  int numc2=nc-numc1;
+	  
+	  mean[0]=-mean[0];
+	  mean[1]=-mean[1];
+
+	  double meandiff = fabs(mean[0]-mean[1]);
+	  double x2=pow(double(numc1),2.0);
+
+	  double sizeweight=exp(-x2/clustersigma2);
+	  double vess= pow(meanint[0],this->Alpha)*sizeweight;
+	  double vess2=pow(meanint[0],this->Alpha)*pow(double(numc2),this->Beta);
+	  if (isnan(vess))
+	    vess=-1.0;
+	  if (isnan(vess2))
+	    vess2=-1.0;
+
+	  // Compute main value vesselness
+	  out->SetComponent(voxel,0,vess2);
+
+	  // Store aux values
+	  if (auxout!=NULL)
+	    {
+
+	      if (isnan(mean[0]) || isnan(mean[1]) || isnan(meanint[0]) || isnan(meanint[1]))
+		{
+		  mean[0]=0.0;
+		  mean[1]=0.0;
+		  meanint[0]=0.0;
+		  meanint[1]=0.0;
+		}
+
+
+	      // Cluster vesselness
+	      // Frame 1
+	      auxout->SetComponent(voxel,0,vess2);
+	      
+	      // Alternative vesselness
+	      // Frame 2
+	      auxout->SetComponent(voxel,1,vess);
+
+	      // Numbers in each cluster
+	      // Frames 3 & 4
+	      auxout->SetComponent(voxel,2,numc1);
+	      auxout->SetComponent(voxel,3,numc2);
+	      
+	      // Means of Vesslness in each cluster
+	      // Frames 5 & 6
+	      auxout->SetComponent(voxel,4,mean[0]);
+	      auxout->SetComponent(voxel,5,mean[1]);
+
+	      // Means of Intensity in each cluster
+	      // Frames 7 & 8
+	      auxout->SetComponent(voxel,6,meanint[0]);
+	      auxout->SetComponent(voxel,7,meanint[1]);
+
+	      // Components of final vesselness
+	      // Frame 9
+	      // Frame 10
+	      auxout->SetComponent(voxel,8,pow(meanint[0],this->Alpha));
+	      auxout->SetComponent(voxel,9,pow(double(numc2),this->Beta));
+	    }
+	  
+
+	}
+
+      ++count;
+      if (count==tenth)
+	{
+	  this->UpdateProgress(this->GetProgress()+0.1);
+	  count=0;
+	}
+    }
+
+  if (dt2!=NULL)
+    delete [] dt2;
+  delete [] dt;
+
+  if (auxout!=NULL)
+    {
+      for (int ia=0;ia<auxout->GetNumberOfComponents();ia++)
+	{
+	  if (ia!=3 && ia!=2)
+	    {
+	      double r[2]; auxout->GetRange(r,ia);
+	      if (fabs(r[1]-r[0])<0.000001)
+		r[1]+=0.01;
+	      double shift=r[0];
+	      double scale=100.0/(r[1]-r[0]);
+	      fprintf(stderr,"ia=%d r=%f:%f shift=%f scale=%f\n",ia,r[0],r[1],shift,scale);
+	      for (int voxel=0;voxel<nt;voxel++)
+		{
+		  double v=auxout->GetComponent(voxel,ia);
+		  auxout->SetComponent(voxel,ia,scale*(v-shift));
+		}
+	    }
+	}
+      
+      auxout->Modified();
+      
+      for (int ia=0;ia<auxout->GetNumberOfComponents();ia++)
+	{
+	  double r[2]; auxout->GetRange(r,ia);
+	  fprintf(stderr,"Out Range ia=%d r=%f:%f \n",ia,r[0],r[1]);
+	}
+    }
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkxqImageKMeansVesselnessFilter.h b/bioimagesuite30_src/Imaging/vtkxqImageKMeansVesselnessFilter.h
new file mode 100644
index 0000000..452f4a5
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkxqImageKMeansVesselnessFilter.h
@@ -0,0 +1,104 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkxqImageKMeansVesselnessFilter_h
+#define __vtkxqImageKMeansVesselnessFilter_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkxqImageKMeansVesselnessFilter : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkxqImageKMeansVesselnessFilter *New();
+  vtkTypeMacro(vtkxqImageKMeansVesselnessFilter,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Generate  Image
+  vtkSetClampMacro(ComputeAuxOutput,int,0,1);
+  vtkGetMacro(ComputeAuxOutput,int);
+  
+  // Description
+  // Sigma Filtering For Cluster Size
+  vtkSetMacro(Sigma,double);
+  vtkGetMacro(Sigma,double);
+
+  // Description:
+  // Beta value for entropy computation, ignored otherwise
+  vtkSetMacro(Beta,double);
+  vtkGetMacro(Beta,double);
+
+  // Description:
+  // Alpha value for entropy computation, raise input image to Alpha prior to clustering
+  vtkSetMacro(Alpha,double);
+  vtkGetMacro(Alpha,double);
+
+
+  // Description:
+  // ODF Image if stored
+  // xq: Brightness mask
+  vtkGetObjectMacro(AuxOutput,vtkImageData);
+
+  // Description:
+  // ODF Image if stored
+  // xq: oriented mean
+  vtkSetObjectMacro(SecondInput,vtkImageData);
+  vtkGetObjectMacro(SecondInput,vtkImageData);
+
+protected:
+
+  vtkxqImageKMeansVesselnessFilter();
+  virtual ~vtkxqImageKMeansVesselnessFilter();
+  vtkxqImageKMeansVesselnessFilter(const vtkxqImageKMeansVesselnessFilter&) {};
+  void operator=(const vtkxqImageKMeansVesselnessFilter&) {};
+
+  // Description:
+  // Basic Input Outputs
+  virtual void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  // Description:
+  // Data
+  double        Sigma;
+  double        Beta;
+  double        Alpha;
+  vtkImageData* AuxOutput;
+  vtkImageData* SecondInput;
+  int           ComputeAuxOutput;
+
+  // Description:
+  virtual int    ComputeClustering(int np,double* data,double* data2,double mean[2],double sigma[2],double meanint[2],double sigmaint[2],int debug=0);
+  virtual void ComputeMeasure(vtkDataArray* inp,vtkDataArray* inp2,vtkDataArray* out,vtkDataArray* aux);
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkxqImageODFVesselnessFilter.cpp b/bioimagesuite30_src/Imaging/vtkxqImageODFVesselnessFilter.cpp
new file mode 100644
index 0000000..8896872
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkxqImageODFVesselnessFilter.cpp
@@ -0,0 +1,167 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkxqImageODFVesselnessFilter.h"
+#include "vtkImageReslice.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkImageFFT.h"
+#include "vtkImageRFFT.h"
+//#include "vtkpxImageFloatFFT.h"
+//#include "vtkpxImageFloatRFFT.h"
+#include "vtkImageCast.h"
+#include "vtkImageMagnitude.h"
+#include "vtkImageMathematics.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+#include "vtkImageShiftScale.h"
+#include "vtkMath.h"
+//------------------------------------------------------------------------------
+vtkxqImageODFVesselnessFilter* vtkxqImageODFVesselnessFilter::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkxqImageODFVesselnessFilter");
+  if(ret)
+    {
+    return (vtkxqImageODFVesselnessFilter*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkxqImageODFVesselnessFilter;
+}
+
+// Construct object with no children.
+vtkxqImageODFVesselnessFilter::vtkxqImageODFVesselnessFilter()
+{
+  this->Tau=1.0;
+  this->Beta=0.01;
+  this->OutputODF=0;
+  this->ODFImage=NULL;
+}
+// ----------------------------------------------------------------------------
+vtkxqImageODFVesselnessFilter::~vtkxqImageODFVesselnessFilter()
+{
+  if (this->ODFImage!=NULL)
+    this->ODFImage->Delete();
+}
+// ----------------------------------------------------------------------------
+void vtkxqImageODFVesselnessFilter::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData* input=this->GetInput();
+  vtkImageData* output=this->GetOutput();
+
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"No Input Set");
+      return;
+    }
+  output->SetNumberOfScalarComponents(1);
+}
+// -------------------------------------------------------------------------------------------------------------
+
+
+void vtkxqImageODFVesselnessFilter::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Input to vtkxqImageODFVesselnessFilter");
+      return;
+    }
+  
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+
+  if (this->ODFImage!=NULL)
+    {
+      this->ODFImage->Delete();
+      this->ODFImage=NULL;
+    }
+
+  vtkDataArray* odf=NULL;
+  if (this->OutputODF)
+    {
+      this->ODFImage=vtkImageData::New();
+      this->ODFImage->CopyStructure(input);
+      this->ODFImage->SetScalarTypeToFloat();
+      this->ODFImage->AllocateScalars();
+      odf=this->ODFImage->GetPointData()->GetScalars();
+    }
+
+  this->ComputeEntropyMeasure(inp,out,odf);
+    
+  this->UpdateProgress(1.0);
+}
+
+void vtkxqImageODFVesselnessFilter::ComputeEntropyMeasure(vtkDataArray* inp,vtkDataArray* out,vtkDataArray* odf)
+{
+  int nc=inp->GetNumberOfComponents();
+  int nt=inp->GetNumberOfTuples();
+  double* p=new double[nc];
+
+  int tenth=nt/10;
+  int count=0;
+
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      double sum=0.0;
+      for (int comp=0;comp<nc;comp++)
+	{
+	  double v=inp->GetComponent(voxel,comp);
+	  p[comp]=exp(-this->Beta*v);
+	  sum+=p[comp];
+	}
+
+      double entropy=0.0;
+      for (int comp=0;comp<nc;comp++)
+	{
+	  if (sum>1e-6)
+	    p[comp]/=sum;
+	  else
+	    p[comp]=0.0;
+
+	  if (odf!=NULL)
+	    odf->SetComponent(voxel,comp,p[comp]);
+	  if (p[comp]>1e-6)
+	    entropy+= p[comp]*log(p[comp]);
+	}
+
+      double vess=exp(this->Tau*entropy);
+      //      fprintf(stderr,"\n%f____%f\n",entropy,vess);
+      out->SetComponent(voxel,0,vess);
+      ++count;
+      if (count==tenth)
+	{
+	  this->UpdateProgress(this->GetProgress()+0.1);
+	  count=0;
+	}
+    }
+  delete [] p;
+}
+
+
diff --git a/bioimagesuite30_src/Imaging/vtkxqImageODFVesselnessFilter.h b/bioimagesuite30_src/Imaging/vtkxqImageODFVesselnessFilter.h
new file mode 100644
index 0000000..c4598f8
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkxqImageODFVesselnessFilter.h
@@ -0,0 +1,89 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkxqImageODFVesselnessFilter_h
+#define __vtkxqImageODFVesselnessFilter_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+class vtkxqImageODFVesselnessFilter : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkxqImageODFVesselnessFilter *New();
+  vtkTypeMacro(vtkxqImageODFVesselnessFilter,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Beta Parameter for Distribution
+  vtkSetMacro(Beta,double);
+  vtkGetMacro(Beta,double);
+  
+  // Description
+  // Tau Parameter for Entropy
+  vtkSetMacro(Tau,double);
+  vtkGetMacro(Tau,double);
+  
+  // Description:
+  // Generate ODF Image
+  vtkSetClampMacro(OutputODF,int,0,1);
+  vtkGetMacro(OutputODF,int);
+  
+
+  // Description:
+  // ODF Image if stored
+  vtkGetObjectMacro(ODFImage,vtkImageData);
+
+
+protected:
+
+  vtkxqImageODFVesselnessFilter();
+  virtual ~vtkxqImageODFVesselnessFilter();
+  vtkxqImageODFVesselnessFilter(const vtkxqImageODFVesselnessFilter&) {};
+  void operator=(const vtkxqImageODFVesselnessFilter&) {};
+
+  // Description:
+  // Basic Input Outputs
+  virtual void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  // Description:
+  // Data
+  double      Beta;
+  double      Tau;
+  vtkImageData* ODFImage;
+  int         OutputODF;
+
+  // Description:
+  virtual void ComputeEntropyMeasure(vtkDataArray* inp,vtkDataArray* out,vtkDataArray* odf);
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Imaging/vtkxqImageVesselEnhancement.cpp b/bioimagesuite30_src/Imaging/vtkxqImageVesselEnhancement.cpp
new file mode 100644
index 0000000..86e1a48
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkxqImageVesselEnhancement.cpp
@@ -0,0 +1,415 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkxqImageVesselEnhancement.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkMath.h"
+#include "vtkpxMath.h"
+#include "vtkxqImageHessian.h"
+//#include "nrutil.h"
+#include "math.h"
+#include "pxisinf.h"
+//------------------------------------------------------------------------------
+vtkxqImageVesselEnhancement* vtkxqImageVesselEnhancement::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkxqImageVesselEnhancement");
+  if(ret)
+    {
+    return (vtkxqImageVesselEnhancement*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkxqImageVesselEnhancement;
+}
+
+// Construct object with no children.
+vtkxqImageVesselEnhancement::vtkxqImageVesselEnhancement()
+{
+  this->Alpha=0.5;
+  this->Beta=0.5;
+  this->Gamma=0.25;
+  this->Aa = 0.2;
+  this->Sigma=1.0;
+  this->Mask = NULL;
+  this->BrightStructure=1;
+  this->StructureType=0;
+
+}
+
+// ----------------------------------------------------------------------------
+vtkxqImageVesselEnhancement::~vtkxqImageVesselEnhancement()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();  
+}
+
+// ----------------------------------------------------------------------------
+void vtkxqImageVesselEnhancement::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+  output->SetScalarTypeToFloat();
+  if (this->StructureType==3)
+    output->SetNumberOfScalarComponents(6);
+  else if (this->StructureType==4)
+    output->SetNumberOfScalarComponents(3);
+  else
+    output->SetNumberOfScalarComponents(1);
+}
+
+// ----------------------------------------------------------------------------
+double vtkxqImageVesselEnhancement::ComputexqVesselLikelihood(float lambda[3],int bright,double a)
+{
+  if (lambda[1]>0.0 || lambda[2]>0.0)
+    return 0.0;
+
+  double dnm = lambda[0]*lambda[0] + lambda[1]*lambda[1] + lambda[2]*lambda[2] - lambda[0]*lambda[1]
+              - lambda[0]*lambda[2] - lambda[1]*lambda[2];
+  double dom = 2*sqrt(dnm);
+  double nc = (2*lambda[0]-lambda[1]-lambda[2])/dom;
+
+  double lm = exp(-a*(nc-1.0)*(nc-1.0));
+    
+  double V = -lm*lambda[1];
+
+  return V;
+}
+
+// ----------------------------------------------------------------------------
+double vtkxqImageVesselEnhancement::ComputeVesselLikelihood(float lambda[3],int bright,double a2,double b2,double c2)
+{
+  if (lambda[1]>0.0 || lambda[2]>0.0)
+    return 0.0;
+
+  double RA= fabs(lambda[1]/lambda[2]);
+  double RB= fabs(lambda[0]/sqrt(fabs(lambda[1]*lambda[2])));
+  double S= sqrt(lambda[0]*lambda[0]+lambda[1]*lambda[1]+lambda[2]*lambda[2]);
+  
+  double V1=(1.0-exp(RA*RA*a2));
+  double V2=exp(RB*RB*b2);
+  double V3=(1.0-exp(S*S*c2));
+  double V=V1*V2*V3;
+  return V;
+}
+// --------------------------------------------------------------------------------------------
+
+double vtkxqImageVesselEnhancement::ComputePlateLikelihood(float lambda[3],int bright,double a2,double b2,double c2)
+{
+  //	      fprintf(stderr,"does it come here?2\n");
+  // modified by xq4, adopting Descoteaux's sheetness measure:
+  if (lambda[2]>0.0)
+    return 0.0;
+
+  double RB= fabs(lambda[1]/lambda[2]);
+  double RA= fabs(2*fabs(lambda[2])-fabs(lambda[1])-fabs(lambda[0]))/fabs(lambda[2]);
+  double S= sqrt(lambda[0]*lambda[0]+lambda[1]*lambda[1]+lambda[2]*lambda[2]);
+  
+  double V1=(1.0-exp(RA*RA*a2));
+  double V2=exp(RB*RB*b2);
+  double V3=(1.0-exp(S*S*c2));
+  double V=V1*V2*V3;
+  return V;
+ 
+  /*
+  double V=exp(-lambda[2]/lambda[1]);
+  if (V<0.0)
+    return 0.0;
+  if (V>40.0)
+    return 40.0;
+  return V;
+  */
+}
+
+// --------------------------------------------------------------------------------------------
+double vtkxqImageVesselEnhancement::ComputeBlobLikelihood(float lambda[3],int bright,double a2,double b2,double c2)
+{
+  if (lambda[2]>0.0)
+    return 0.0;
+
+  double RB= fabs(lambda[1]/lambda[2]);
+  double RA= fabs(2*fabs(lambda[2])-fabs(lambda[1])-fabs(lambda[0]))/fabs(lambda[2]);
+  double S= sqrt(lambda[0]*lambda[0]+lambda[1]*lambda[1]+lambda[2]*lambda[2]);
+  
+  double V1=(1.0-exp(RA*RA*a2));
+  double V2=exp(RB*RB*b2);
+  double V3=(1.0-exp(S*S*c2));
+  double V=V1*V2*V3;
+  return V;
+  /*
+  double V=exp(-lambda[2]/lambda[0]);
+	      fprintf(stderr,"does it come here?3\n");
+  if (V<0.0)
+    return 0.0;
+  if (V>40.0)
+    return 40.0;
+  return V;
+  */
+}
+
+// --------------------------------------------------------------------------------------------
+void vtkxqImageVesselEnhancement::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+
+  int nimpc=input->GetNumberOfScalarComponents();
+
+  if (nimpc!=1 && nimpc!=6)
+    {
+      vtkErrorMacro(<<"Either One or Six Component Images are valid inputs (i.e. Hessians)\n ****** \n\n\n\n\n\n");
+      return;
+    }
+
+  vtkImageData* hessian=vtkImageData::New();
+  if (nimpc==6)
+    {
+      hessian->ShallowCopy(input);
+    }
+  else
+    {
+      vtkxqImageHessian* hes=vtkxqImageHessian::New();
+      hes->SetInput(input);
+      hes->SetSigma(this->Sigma);
+      hes->Update();
+      hessian->ShallowCopy(hes->GetOutput());
+      hes->Delete();
+    }
+
+  this->UpdateProgress(0.5);
+
+  vtkDataArray* data=hessian->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  float A[3][3],lambda[3],W[3][3];
+
+  int nc=out->GetNumberOfComponents();
+  for (int i=0;i<nc;i++)
+    out->FillComponent(i,0.0);
+
+  int np=data->GetNumberOfTuples();
+
+  //  fprintf(stderr,"Beginning Alpha=%.2f, Beta=%.2f Gamma=%.2f\n",Alpha,Beta,Gamma);
+
+  double a2=-1.0/(this->Alpha*this->Alpha*2.0);
+  double b2=-1.0/(this->Beta*this->Beta*2.0);
+  double c2=-1.0/(this->Gamma*this->Gamma*2.0);
+
+  double aa = this->Aa;
+
+  vtkDataArray *mask=NULL;
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  int count=0;
+  int tenth=np/10;
+  for (int i=0;i<np;i++)
+    {
+      if (!((mask != NULL)?(mask->GetComponent(i, 0) > 0):1))
+	continue;
+      
+      A[0][0]=data->GetComponent(i,0);
+      A[0][1]=data->GetComponent(i,1);
+      A[1][0]=A[0][1];
+
+      A[0][2]=data->GetComponent(i,2);
+      A[2][0]=A[0][2];
+
+      A[1][1]=data->GetComponent(i,3);
+      A[1][2]=data->GetComponent(i,4);
+      A[2][1]=A[1][2];
+      
+      A[2][2]=data->GetComponent(i,5);
+      
+      vtkMath::Diagonalize3x3(A,lambda,W);
+
+      for (int ia=0;ia<=1;ia++)
+	{
+	  double min=fabs(lambda[ia]);
+	  int best=ia;
+	  for (int ib=ia+1;ib<=2;ib++)
+	    {
+	      if (fabs(lambda[ib]) < min )
+		{
+		  min=fabs(lambda[ib]);
+		  best=ib;
+		}
+	    }
+	  if (best!=ia)
+	    {
+	      double tmp=lambda[ia];
+	      lambda[ia]=lambda[best];
+	      lambda[best]=tmp;
+	    }
+	}
+
+      double V=0.0,V3=0.0,V2=0.0;
+      int offset=-1;
+
+      if (!isinf(lambda[0]) && !isinf(lambda[1]) && !isinf(lambda[2]))
+	{
+	  switch (this->StructureType)
+	    {
+	    case 0:
+	      //V=this->ComputeVesselLikelihood(lambda,this->BrightStructure,a2,b2,c2);
+  		  V=this->ComputexqVesselLikelihood(lambda,this->BrightStructure,aa);
+	      break;
+	    case 1:
+	      V=this->ComputePlateLikelihood(lambda,this->BrightStructure,a2,b2,c2);
+	      fprintf(stderr,"does it come here?\n");
+	      break;
+	    case 2:
+	      V=this->ComputeBlobLikelihood(lambda,this->BrightStructure,a2,b2,c2);
+	      break;
+	    case 3:
+	      V=this->ComputeVesselLikelihood(lambda,this->BrightStructure,a2,b2,c2);
+	      V2=this->ComputePlateLikelihood(lambda,this->BrightStructure,a2,b2,c2);
+	      V3=this->ComputeBlobLikelihood(lambda,this->BrightStructure,a2,b2,c2);
+	      offset=3;
+	      break;
+	    case 4:
+	      offset=0;
+	    }
+	  
+
+	  if (!isinf(V))
+	    out->SetComponent(i,0,V);
+
+	  if (this->StructureType==3)
+	    {
+	      offset=3;
+	      if (!isinf(V2))
+		out->SetComponent(i,1,V2);
+	      if (!isinf(V3))
+		out->SetComponent(i,2,V3);
+	    }
+
+	  if (offset>-1)
+	    {
+	      out->SetComponent(i,offset,lambda[0]);
+	      out->SetComponent(i,offset+1,lambda[1]);
+	      out->SetComponent(i,offset+2,lambda[2]);
+	    }
+	}
+      
+      ++count;
+      if (count==tenth)
+	{
+	  this->UpdateProgress(this->GetProgress()+0.05);
+	  count=0;
+	}
+    }
+  
+  hessian->Delete();
+}
+
+// -----------------------------------------------------------------------------------------------------------
+
+int vtkxqImageVesselEnhancement::UpdateHessianResponse(vtkImageData* hessian1,vtkImageData* vessel1,vtkImageData* sigma1,
+							vtkImageData* hessian2,vtkImageData* vessel2,double newsigma)
+{
+
+  if (hessian1==NULL || vessel1==NULL || sigma1==NULL || hessian2 == NULL || vessel2==NULL)
+    {
+      fprintf(stderr,"Bad Inputs to Update Hessian Response (NULL)\n");
+      return 0;
+    }
+
+  vtkDataArray* array[3][2];
+  array[0][0]=hessian1->GetPointData()->GetScalars();
+  array[1][0]=vessel1->GetPointData()->GetScalars();
+  array[2][0]=sigma1->GetPointData()->GetScalars();
+
+  array[0][1]=hessian2->GetPointData()->GetScalars();
+  array[1][1]=vessel2->GetPointData()->GetScalars();
+
+
+  int numvoxels=array[0][0]->GetNumberOfTuples();
+
+  int flag=0;
+  int nc[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      int nt1=array[ia][0]->GetNumberOfTuples();
+      int nc1=array[ia][0]->GetNumberOfComponents();
+
+      int nt2=nt1,nc2=1;
+      if (ia!=2)
+	{
+	  nt2=array[ia][1]->GetNumberOfTuples();
+	  nc2=array[ia][1]->GetNumberOfComponents();
+	}
+
+      //      fprintf(stderr,"Checking row=%d   set1=%d x %d  set2=%d x %d\n",ia,nt1,nc1,nt2,nc2);
+
+      if (nt1!=nt2 || nt1!=numvoxels || nc1!=nc2)
+	{
+	  flag=1;
+	  ia=4;
+	}
+      nc[ia]=nc1;
+    }
+
+  if (flag==1)
+    {
+      fprintf(stderr,"Bad Inputs (Dimensions) to Update Hessian Response\n");
+      return 0;
+    }
+
+  for (int voxel=0;voxel<numvoxels;voxel++)
+    {
+      double v1=array[1][0]->GetComponent(voxel,0);
+      double v2=array[1][1]->GetComponent(voxel,0);
+      double oldsig = array[2][0]->GetComponent(voxel,0);
+      if ((v2/newsigma)>(v1/oldsig))
+	{
+	  for (int row=0;row<=1;row++)
+	    for (int ia=0;ia<nc[row];ia++)
+	      {
+		if (row == 0)
+		  array[row][0]->SetComponent(voxel,ia,array[row][1]->GetComponent(voxel,ia));
+		else
+		  array[row][0]->SetComponent(voxel,ia,(array[row][1]->GetComponent(voxel,ia)/newsigma));
+	      }
+
+	  array[2][0]->SetComponent(voxel,0,newsigma);
+	}
+    }
+
+  for (int ia=0;ia<=2;ia++)
+    array[ia][0]->Modified();
+
+  //fprintf(stderr, "ok\n");
+
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Imaging/vtkxqImageVesselEnhancement.h b/bioimagesuite30_src/Imaging/vtkxqImageVesselEnhancement.h
new file mode 100644
index 0000000..20b610c
--- /dev/null
+++ b/bioimagesuite30_src/Imaging/vtkxqImageVesselEnhancement.h
@@ -0,0 +1,152 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkxqImageVesselEnhancement.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:08:12 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkxqImageVesselEnhancement -- combines images to form either mean or median
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// Implements Vessel Enhancement Filter from Chen and Amini TMI October 2004
+
+#ifndef __vtkxqImageVesselEnhancement_h
+#define __vtkxqImageVesselEnhancement_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkFloatArray.h"
+
+class vtkxqImageVesselEnhancement : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkxqImageVesselEnhancement *New();
+  vtkTypeMacro(vtkxqImageVesselEnhancement,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set Parameters Alpha, Beta and Gamma
+  vtkGetMacro(Alpha,float);
+  vtkSetClampMacro(Alpha,float,0.05,10.0);
+
+  vtkGetMacro(Beta,float);
+  vtkSetClampMacro(Beta,float,0.05,10.0);
+
+  vtkGetMacro(Gamma,float);
+  vtkSetMacro(Gamma,float);
+
+  vtkGetMacro(Aa,float);
+  vtkSetMacro(Aa,float);
+
+  // Description:
+  // Set Smoothing Sigma for Hessian Computation
+  vtkGetMacro(Sigma,float);
+  vtkSetMacro(Sigma,float);
+
+  // Description:
+  // Bright Structure
+  vtkSetClampMacro(BrightStructure,int,0,2);
+  vtkGetMacro(BrightStructure,int);
+  virtual void SetBrightStructureToDark()   { this->SetBrightStructure(0); }
+  virtual void SetBrightStructureToBright() { this->SetBrightStructure(1); }
+  virtual void SetBrightStructureToBoth()   { this->SetBrightStructure(2); }
+
+  // Description: 
+  // Sets/Gets mask for computing statistics.
+  // If a mask is not provided, tensor is
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+  
+  // Description:
+  // Bright Structure
+  vtkSetClampMacro(StructureType,int,0,4);
+  vtkGetMacro(StructureType,int);
+  virtual void SetStructureTypeToTubular() { this->SetStructureType(0); }
+  virtual void SetStructureTypeToPlate()   { this->SetStructureType(1); }
+  virtual void SetStructureTypeToBlob()    { this->SetStructureType(2); }
+  virtual void SetStructureTypeToAll()     { this->SetStructureType(3); }
+  virtual void SetStructureTypeToNone()    { this->SetStructureType(4); }
+
+  // Description:
+  // This a messy function that takes as inputs
+  // Hessian1, Vessel1, Sigma1, Hessian2, Vessel2, Sigma2, and spits out a corrected Set 1 by using the maximum of the vessel number
+  static int UpdateHessianResponse(vtkImageData* hessian1,vtkImageData* vessel1,vtkImageData* sigma,
+				   vtkImageData* hessian2,vtkImageData* vessel2,double newsigma);
+  
+protected:
+
+  //BTX
+  vtkxqImageVesselEnhancement();
+  virtual ~vtkxqImageVesselEnhancement();
+  vtkxqImageVesselEnhancement(const vtkxqImageVesselEnhancement&) {};
+  void operator=(const vtkxqImageVesselEnhancement&) {};
+  //ETX
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual void ExecuteInformation();
+
+  // Description:
+  // Workhorse Functions
+  virtual double ComputeVesselLikelihood(float lambda[3],int bright,double a2,double b2,double c2);
+  virtual double ComputexqVesselLikelihood(float lambda[3], int bright, double a);
+  virtual double ComputePlateLikelihood(float lambda[3],int bright,double a2,double b2,double c2);
+  virtual double ComputeBlobLikelihood(float lambda[3],int bright,double a2,double b2,double c2);
+
+  vtkImageData *Mask;
+
+  double Alpha;
+  double Beta;
+  double Gamma;
+  double Sigma;
+  double Aa;
+  int    BrightStructure;
+  int    StructureType;
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Legacy/CMakeLists.txt b/bioimagesuite30_src/Legacy/CMakeLists.txt
new file mode 100644
index 0000000..b8aaf67
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/CMakeLists.txt
@@ -0,0 +1,94 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+SET(KITBASE Legacy)
+SET(KIT vtkpx${KITBASE})
+
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/${KITBASE})
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Graphics)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/numerics)
+
+SET (KITSRCS
+vtkpxContourSource.cpp
+vtkpxFemSolid.cpp
+vtkpxShapeTracking.cpp
+vtkpxSplineSource.cpp
+vtkpxSplineSourceUndoStack.cpp
+vtkpxSplineStackSource.cpp
+vtkpxTriangulatedStackSource.cpp
+vtkpxTstackReader.cpp
+vtkpxComputeStrains.cpp)
+    
+
+IF (BIOIMAGESUITE3_EXPERIMENTAL)
+
+SET(KITSRCS
+  ${KITSRCS}
+  vtkpxSulcalTrace.cpp
+)
+ENDIF (BIOIMAGESUITE3_EXPERIMENTAL)
+
+SET(KITLIBS
+  vtkpxGraphics
+  vtkpxGraphicsTCL
+  vtkpxCommon
+  vtkpxCommonTCL
+  numerics
+  vtkCommonTCL
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+  ${TK_LIBRARY}
+)
+
+SET(KITJAVALIBS
+  vtkpxGraphics
+  vtkpxGraphicsJava
+  vtkpxCommon
+  vtkpxCommonJava
+  numerics
+  ${BIOIMAGESUITE3_COMMON_JAVALIBS}
+)
+
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+SET (KITEXTRAFILES)
+SET (KITTCLSRCS )
+bis_complex("Legacy" ${KIT} ${FILELIST})
+
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxComputeStrains.cpp b/bioimagesuite30_src/Legacy/vtkpxComputeStrains.cpp
new file mode 100644
index 0000000..1bc6547
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxComputeStrains.cpp
@@ -0,0 +1,318 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxComputeStrains.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/04/01 14:18:13 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "pxabaqussolid.h"
+#include "pxabaqusstructures.h"
+#include "pxutil.h"
+#include "vtkFloatArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkpxComputeStrains.h"
+#include "vtkMath.h"
+#include "vtkPointData.h"
+//------------------------------------------------------------------------------
+vtkpxComputeStrains* vtkpxComputeStrains::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxComputeStrains");
+  if(ret)
+    {
+      return (vtkpxComputeStrains*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxComputeStrains;
+}
+//------------------------------------------------------------------------------
+vtkpxComputeStrains::vtkpxComputeStrains()
+{
+  this->BaseSolid=NULL;
+  this->Transformation=NULL;
+  this->CoordinateFrame=1;
+}
+//------------------------------------------------------------------------------
+vtkpxComputeStrains::~vtkpxComputeStrains()
+{
+  this->SetBaseSolid(NULL);
+  this->SetTransformation(NULL);
+}
+//------------------------------------------------------------------------------
+int vtkpxComputeStrains::SaveOutput(const char* fname)
+{
+  if (this->BaseSolid==NULL)
+      return 0;
+  
+  return this->BaseSolid->SaveFemData(fname);
+}
+//------------------------------------------------------------------------------
+int vtkpxComputeStrains::Run()
+{
+  if (this->BaseSolid==NULL || this->Transformation==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs");
+      return 0;
+    }
+
+  this->BaseSolid->CreateFemData();
+  PXAbaqusSolid* solid=this->BaseSolid->GetInternalSolid();
+
+  int numel=solid->getelements()->getnumnodes();
+  int numnodes=solid->getnodes()->getnumnodes();
+
+  // 1. Displacements -- this is trivial
+  for (int ia=0;ia<numnodes;ia++)
+    {
+      float p1[3],p2[3];
+      for (int ib=0;ib<=2;ib++)
+	p1[ib]=solid->getnodes()->getpoint(ia)->x[ib];
+
+      this->Transformation->TransformPoint(p1,p2);
+      solid->getfemdata()->setNodeInfo(ia,p2[0]-p1[0],p2[1]-p1[1],p2[2]-p1[2]);
+      if (ia==200)
+	fprintf(stderr,"Node %d (%.1f,%.1f,%.1f) --> (%.1f,%.1f,%.1f)\n",
+		ia,p1[0],p1[1],p1[2],p2[0],p2[1],p2[2]);
+    }
+      
+  // 2. Strains 
+  // ----------------------------
+  PXNeighboursList* elements=solid->getelements();
+  elements->Rewind();
+
+  float R[3][3];
+  float E[3][3];
+  float E2[3][3];
+
+  for (int el=0;el<numel;el++)
+    {
+      float p1[3],p2[3],der[3][3];
+      PXIntegerList* intList=(elements->getcurrentnode())->points;
+      solid->getElementCentroid(intList,p1[0],p1[1],p1[2]);
+
+      float cz=p1[2];
+      this->Transformation->InternalTransformDerivative(p1,p2,der);
+      for (int i=0;i<=2;i++)
+	for (int j=0;j<=2;j++)
+	  E[i][j]=0.5*(der[i][j]+der[j][i]);
+
+      int layer=0;
+
+      for (int ka=0;ka<intList->getnumnodes();ka++)
+	{
+	  layer+=solid->getnodes()->getindex(intList->getcurrent(),0); 
+	  intList->Next();
+	}
+      layer=layer/intList->getnumnodes();
+
+      if (this->CoordinateFrame!=0)
+	{
+	  float x1,x2,x3,y1,y2,y3,z1,z2,z3;
+	  intList->Rewind();
+	  solid->getdirections(intList,
+			       x2,y2,z2,x3,y3,z3,x1,y1,z1,0);
+	  
+	  if (this->CoordinateFrame==2)
+	    {
+	      float angle=solid->getFibreAngle(cz,layer);
+	      
+	      solid->rotateFibreAngle(x3,y3,z3,  
+				      x1,y1,z1,
+				      x2,y2,z2, // Keep Radial Fixed
+				      angle);
+	      R[0][0]=x1; R[1][0]=y1; R[2][0]=z1; // Cross
+	      R[0][1]=x2; R[1][1]=y2; R[2][1]=z2; // Radial
+	      R[0][2]=x3; R[1][2]=y3; R[2][2]=z3; // Fibre
+	    }
+	  else
+	    {
+	      R[0][0]=x2; R[1][0]=y2; R[2][0]=z2; // Radial
+	      R[0][1]=x3; R[1][1]=y3; R[2][1]=z3; // Radial
+	      R[0][2]=x1; R[1][2]=y1; R[2][2]=z1; // Radial
+	  
+	    }
+
+	  for (int i=0;i<=2;i++)
+	    for (int j=0;j<=2;j++)
+	      {
+		E2[i][j]=0.0;
+		for (int k=0;k<=2;k++)
+		  for (int m=0;m<=2;m++)
+		    E2[i][j] += R[i][k]*E[k][m]*R[j][m];
+	      }
+
+	  E2[0][0]-=1.0;
+	  E2[1][1]-=1.0;
+	  E2[2][2]-=1.0;
+
+	  solid->getfemdata()->setElementInfo(el,2,1.0,
+					      E2[0][0],E2[1][1],E2[2][2],E2[0][1],E2[0][2],E2[1][2]);
+	}
+      else 
+	{
+	  E[0][0]-=1.0;
+	  E[1][1]-=1.0;
+	  E[2][2]-=1.0;
+
+	  solid->getfemdata()->setElementInfo(el,2,1.0,
+					      E[0][0],E[1][1],E[2][2],E[0][1],E[0][2],E[1][2]);
+	}
+
+      solid->getfemdata()->setCentroid(el,p1[0],p1[1],p1[2]);
+      elements->Next();
+    }
+
+  return 1;
+}
+
+int vtkpxComputeStrains::GenerateStudyFile(const char* namestem,const char* sldname,int nframes)
+{
+  vtkpxFemSolid* sld=vtkpxFemSolid::New();
+  int ok=sld->Load(sldname);
+  if (ok==0)
+    {
+      sld->Delete();
+      return 0;
+    }
+
+  fprintf(stderr,"Solid Read!\n");
+
+  char line[400];
+  sprintf(line,"%s.stat",namestem);
+
+  int numnd=sld->GetInternalSolid()->getnodes()->getnumnodes();
+  int numel=sld->GetInternalSolid()->getelements()->getnumnodes();
+
+  
+  FILE* fout=fopen(line,"w");
+  fprintf(fout,"#AbaqusResults File Set frames,nodes,elements\n%d\n%d\n%d\n",nframes,numnd,numel);
+  fprintf(fout,"#Solid name\n%s\n",sldname);
+  fprintf(fout,"#Step name\n%s\n",namestem);
+  fprintf(fout,"#Step Statistics\n");
+  for (int i=1;i<=nframes;i++)
+    {
+      sprintf(line,"%s.%02d.dat",namestem,i);
+      fprintf(fout,"%s\t\t 		(step/inc=1/1)\n",line);
+    }
+  fclose(fout);
+  sld->Delete();
+  return 1;
+}
+
+
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxComputeStrains::Run(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL || output==NULL || this->Transformation==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs");
+      return 0;
+    }
+
+  output->CopyStructure(input);
+  output->SetScalarTypeToFloat();
+  output->SetNumberOfScalarComponents(7);
+  output->AllocateScalars();
+  
+  //  float R[3][3];
+  float E[3][3];
+  //float E2[3][3];
+
+
+  int dim[3]; output->GetDimensions(dim);
+  double sp[3]; output->GetSpacing(sp);
+  double ori[3]; output->GetOrigin(ori);
+  
+  float p1[3],p2[3],der[3][3];
+
+  vtkFloatArray* outscal=(vtkFloatArray*)output->GetPointData()->GetScalars();
+
+  int index=0;
+  for (int i=0;i<dim[0];i++)
+    {
+      p1[0]=i*sp[0]+ori[0];
+      for (int j=0;j<dim[1];j++)
+	{
+	  p1[1]=j*sp[1]+ori[1];
+	  for (int k=0;k<dim[2];k++)
+	    {
+	      p2[2]=k*sp[2]+ori[2];
+
+	      this->Transformation->InternalTransformDerivative(p1,p2,der);
+	      float det=vtkMath::Determinant3x3(der);
+	      for (int i=0;i<=2;i++)
+		for (int j=0;j<=2;j++)
+		  E[i][j]=0.5*(der[i][j]+der[j][i]);
+	      
+	      E[0][0]-=1.0;
+	      E[1][1]-=1.0;
+	      E[2][2]-=1.0;
+	      
+
+	      outscal->SetComponent(index,0,E[0][0]);
+	      outscal->SetComponent(index,1,E[1][1]);
+	      outscal->SetComponent(index,2,E[2][2]);
+	      outscal->SetComponent(index,3,E[0][1]);
+	      outscal->SetComponent(index,4,E[0][2]);
+	      outscal->SetComponent(index,5,E[1][2]);
+	      outscal->SetComponent(index,6,det);
+	      ++index;
+	    }
+	}
+    }
+
+  return 1;
+}
+
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxComputeStrains.h b/bioimagesuite30_src/Legacy/vtkpxComputeStrains.h
new file mode 100644
index 0000000..b3c7688
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxComputeStrains.h
@@ -0,0 +1,122 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxComputeStrains.h,v $
+  Language:  C++
+  Date:      $Date: 2003/02/17 16:20:30 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#ifndef __vtkpxComputeStrains_h
+#define __vtkpxComputeStrains_h
+
+#include "vtkpxFemSolid.h"
+#include "vtkAbstractTransform.h"
+#include "vtkProcessObject.h"
+#include "vtkImageData.h"
+
+class vtkpxComputeStrains : public vtkProcessObject
+{
+public:
+
+  static vtkpxComputeStrains *New();
+  vtkTypeMacro(vtkpxComputeStrains,vtkProcessObject);
+
+  // Description:
+  // Set Solid
+  vtkSetObjectMacro(BaseSolid,vtkpxFemSolid);
+  vtkGetObjectMacro(BaseSolid,vtkpxFemSolid);
+
+  // Description:
+  // Set Transformation
+  vtkSetObjectMacro(Transformation,vtkAbstractTransform);
+  vtkGetObjectMacro(Transformation,vtkAbstractTransform);
+
+  // Description:
+  // Set/Get Coordinate Frame
+  vtkSetClampMacro(CoordinateFrame,int,0,2);
+  vtkGetMacro(CoordinateFrame,int);
+  void SetCoordinateFrameToXYZ() { this->SetCoordinateFrame(0);}
+  void SetCoordinateFrameToRadial() { this->SetCoordinateFrame(1);}
+  void SetCoordinateFrameToFibres() { this->SetCoordinateFrame(2);}
+  
+  // Description:
+  // I/O Code -- save as .sld file 
+  virtual int SaveOutput(const char* fname);
+
+  // Description:
+  // Generate Output
+  virtual int Run();
+
+  // Description:
+  // Generate Output Image Instead
+  virtual int Run(vtkImageData* in,vtkImageData* out);
+
+
+  // Description:
+  // Generate .stat file
+  static int GenerateStudyFile(const char* namestem,const char* sldname,int nframes);
+
+protected:
+
+  vtkpxComputeStrains();
+  virtual ~vtkpxComputeStrains();
+  vtkpxComputeStrains(const vtkpxComputeStrains&) {};
+  void operator=(const vtkpxComputeStrains&) {};
+  
+  vtkpxFemSolid* BaseSolid;
+  vtkAbstractTransform* Transformation;
+  int            CoordinateFrame;
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxContourSource.cpp b/bioimagesuite30_src/Legacy/vtkpxContourSource.cpp
new file mode 100644
index 0000000..2d0f2c6
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxContourSource.cpp
@@ -0,0 +1,819 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkCellArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkpxContourSource.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkpxContourSource.h"
+#include "pxfpbsplinestack.h"
+#include "pxutil.h"
+//------------------------------------------------------------------------------
+vtkpxContourSource* vtkpxContourSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxContourSource");
+  if(ret)
+    {
+      return (vtkpxContourSource*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxContourSource;
+}
+//------------------------------------------------------------------------------
+vtkpxContourSource::vtkpxContourSource()
+{
+  this->Points=vtkPoints::New();
+  this->Points->SetNumberOfPoints(0);
+  this->Closed=1;
+}
+//------------------------------------------------------------------------------
+vtkpxContourSource::~vtkpxContourSource()
+{
+  if (this->Points)
+    this->Points->Delete();
+}
+//------------------------------------------------------------------------------
+int vtkpxContourSource::Save(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout!=NULL)
+      {
+	int np=this->Points->GetNumberOfPoints();
+	for (int ib=0;ib<np;ib++)
+	  {
+	    double x[3];
+	    this->Points->GetPoint(ib,x);
+	    fprintf(fout,"%6.2f  %6.2f \n",x[0],x[1]);
+
+	  }
+	fclose(fout);
+	return(1);
+      }
+  return(0);
+
+}
+//------------------------------------------------------------------------------
+int vtkpxContourSource::Load(const char* fname)
+{
+  FILE* fin;
+  char line[200];
+
+  int numpoints=0;
+  fin=fopen(fname,"r");
+  if (fin==NULL)
+    return 0;
+
+  while ( fgets(line,100,fin)!=NULL ) 
+    numpoints++;
+  fclose(fin);
+
+  if (numpoints<1)
+    return 0;
+    
+  fin=fopen(fname,"r");
+  this->Points->SetNumberOfPoints(numpoints);
+
+  for (int i=0;i<numpoints;i++)
+    {
+      float x,y,z=0.0;
+      fscanf(fin,"%f %f", &x,&y);
+      this->Points->SetPoint(i,x,y,z);
+    }
+  fclose(fin);
+  this->Modified();
+  return numpoints;
+}
+//------------------------------------------------------------------------------
+void vtkpxContourSource::Copy(vtkpxContourSource* other)
+{
+  this->Points->DeepCopy(other->GetPoints());
+  this->Closed=other->GetClosed();
+  this->Modified();
+}
+//------------------------------------------------------------------------------
+void vtkpxContourSource::SetFromSplineStackSource(vtkpxSplineStackSource* vtksur,int level,float dist)
+{
+  PXFPBSplineStack* sur=vtksur->GetSplineStack();
+  PXFPBSpline* spline=sur->getspline(level);
+  
+  this->SetClosed(spline->isclosed());
+  float z=spline->getzlevel();
+  dist=Frange(dist,0.01,20.0);
+  float length=spline->getlength(0.0,1.0,0.05);
+  int np=int(length/dist+0.5);
+  float ds=1.0/float(2*np);
+  length=spline->getlength(0.0,1.0,ds);
+  np=int(length/dist+0.5);
+  float step=1.0/(float(np)*5.0);
+
+  PXFPBSpline* temp=new PXFPBSpline(spline);
+  temp->changespacing(0.5,-1,step);
+  this->Points->SetNumberOfPoints(np);
+  float x,y;
+  for (int i=0;i<np;i++)
+    {
+      float s=float(i)/float(np);
+      temp->getposition(s,x,y);
+      this->Points->SetPoint(i,x,y,z);
+    }
+  delete temp;
+  this->Modified();
+}
+//------------------------------------------------------------------------------
+void vtkpxContourSource::SetFromContourStack(PXContourStack* stack,int level)
+{
+  PXContour* cntr=stack->getcontour(level);
+  this->SetFromContour(cntr);
+}
+
+void vtkpxContourSource::SetFromContour(PXContour* cntr)
+{
+  this->Points->SetNumberOfPoints(cntr->getnumpoints());
+  this->SetClosed(cntr->isclosed());
+
+  if (cntr->getnumpoints()==0)
+    return;
+  
+  PXContourPoint* temp=cntr->gettoppoint(); 
+
+  for (int i=0; i<cntr->getnumpoints(); i++) 
+    {
+      this->Points->SetPoint(i,temp->x,temp->y,0.0);
+      temp=temp->next;
+    }
+  this->Modified();
+}
+
+//------------------------------------------------------------------------------
+int vtkpxContourSource::EnsureAnticlockwise()
+{
+  return this->SetDirection(1);
+}
+
+// ***********************************************************************
+int vtkpxContourSource::EnsureClockwise()
+{
+  return this->SetDirection(-1);
+}
+// ***********************************************************************
+int vtkpxContourSource::SetDirection(int dir)
+{
+    int numpoints=this->Points->GetNumberOfPoints();
+  if (numpoints<3)
+    return 0;
+
+  int np=numpoints;
+  double px0[3],px1[3],px2[3];
+
+  this->Points->GetPoint(0,px0);
+  this->Points->GetPoint(np/3,px1);
+  this->Points->GetPoint((2*np)/3,px2);
+	
+  float v1x=px1[0]-px0[0];
+  float v1y=px1[1]-px0[1];
+  float v2x=px2[0]-px1[0];
+  float v2y=px2[1]-px1[1];
+  float zz=(v1x*v2y-v2x*v1y);
+
+  int flag=0;
+  if (dir>0 && zz<0.0)
+    flag=1;
+  if (dir<=0 && zz>0.0) 
+    flag=1;
+
+  if (flag)
+    {
+      vtkPoints* temp=vtkPoints::New();
+      temp->DeepCopy(this->Points);
+      for (int i=0;i<np;i++)
+	this->Points->SetPoint(i,temp->GetPoint(np-1-i));
+      temp->Delete();
+      this->Modified();
+    }
+  return flag;
+}
+// ------------------------------------------------------------------------------------
+void vtkpxContourSource::SetCircle(int np,float radius,float x,float y)
+{
+  this->Points->SetNumberOfPoints(np);
+  for (int j=0;j<np;j++)
+    {
+      float t=3.141592*2.0*(float(j)/float(np));
+      float xx=radius*cos(t)+x;
+      float yy=radius*sin(t)+y;
+      this->Points->SetPoint(j,xx,yy,0.0);
+    }
+  this->Closed=1;
+  this->Modified();
+}
+// ------------------------------------------------------------------------------------
+int  vtkpxContourSource::Intersect (float x1,float y1, 
+				    float x2,float y2, 
+				    float x,float y)
+{
+  float xint;			// co-ordinate of the intersection 
+  
+  int intersect=0;	       	// 1 if line l intersects the edge      
+  int ToTheLeft=0;	       	// 1 if the intersection is on the left 
+				//      of z = (x, y)                           
+
+  if (y1 < y2) 
+      {
+	if ((y1 <= y)  && (y  <  y2)) 
+	    {	
+	      // l intersects edge 
+	      intersect = 1;
+	      xint = x1 + (y - y1) * (x2 - x1) /(y2 - y1);
+	      ToTheLeft = (xint <= x);
+	    }
+	else 
+	    intersect = 0;
+      }
+  else 
+      if (y2 < y1) 
+	  {
+	    if ((y2 <= y) && (y  <  y1)) 
+		{
+		  // l intersects edge 
+		  intersect = 1;
+		  xint = x1 + (y - y1) * (x2 - x1) /(y2 - y1);
+		  ToTheLeft = (xint <= x);
+		}
+	    else 
+		intersect = 0;
+	  }
+      else				// horizontal edge   
+	  intersect = 0;
+  
+  return ((intersect) && (ToTheLeft));
+}
+    
+/*
+ *--------------------------------------------------------------------------
+ *_Subject : Test wether a point z = (x,y) is internal to a simple N-gon.
+ *           
+ *_Author: Francois G. Meyer 
+ *_History  :                 Initial Key-In
+ *
+ *_Reference : Computational Geometry, Preparata and Shamos
+ *--------------------------------------------------------------------------
+ */
+int vtkpxContourSource::IsInside (float testpointx,float testpointy)
+{
+  int numberofpoints=this->Points->GetNumberOfPoints();
+  int  index=0,count=0;
+  float x1, y1,x2, y2;
+
+  x2 = this->Points->GetPoint(index)[0];
+  y2 = this->Points->GetPoint(index)[1];
+  
+  while (index<numberofpoints) 
+      {
+	index++;
+	x1 = x2;
+	y1 = y2;
+	x2 = this->Points->GetPoint(index)[0];
+	y2 = this->Points->GetPoint(index)[1];
+	if (this->Intersect (x1, y1, x2, y2, testpointx, testpointy))
+	  count ++;
+      }
+  
+  int isodd=count%2;
+  return isodd;
+
+}
+// ------------------------------------------------------------------------------------
+float vtkpxContourSource::GetArea()
+{
+  int numpoints=this->Points->GetNumberOfPoints();
+  if (numpoints<3)
+      return 0.0;
+
+  if (this->Closed==0)
+    return -1.0;
+  
+  float area=0.0;
+
+ 
+  //	2 A( P ) = sum_{i=0}^{n-1} (x_i y_{i+1} - y_i x_{i+1}).
+  
+  for (int i=0;i<numpoints;i++)
+    {
+      float xi = this->Points->GetPoint(i)[0];
+      float yi = this->Points->GetPoint(i)[1];
+      float xip,yip;
+      if (i!=numpoints-1)
+	{
+	  xip=this->Points->GetPoint(i+1)[0];
+	  yip=this->Points->GetPoint(i+1)[1];
+	}
+      else
+	{
+	  xip=this->Points->GetPoint(0)[0];
+	  yip=this->Points->GetPoint(0)[1];
+	}
+      area+= xi*yip-yi*xip;
+    }
+  return fabs(area*0.5);
+}
+// ------------------------------------------------------------------------------------
+float vtkpxContourSource::GetContourLength()
+{
+  int numpoints=this->Points->GetNumberOfPoints();
+  if (numpoints<1)
+    return 0.0;
+
+  float length=0.0;
+  double x[3],y[3];
+
+  for (int i=0;i<numpoints-1;i++)
+    {
+      this->Points->GetPoint(i,x);
+      this->Points->GetPoint(i+1,y);
+      length+=sqrt(vtkMath::Distance2BetweenPoints(x,y));
+    }
+
+  if (this->Closed)
+    {
+      this->Points->GetPoint(numpoints-1,x);
+      this->Points->GetPoint(0,y);
+      length+=sqrt(vtkMath::Distance2BetweenPoints(x,y));
+    }
+  return length;
+}
+// ------------------------------------------------------------------------------------
+void vtkpxContourSource::GetCentroid(float& xm,float& ym)
+{
+  int numpoints=this->Points->GetNumberOfPoints();
+  if (numpoints<1)
+    {
+      xm=0.0;
+      ym=0.0;
+      return;
+    }
+
+  float sum[3];
+  for (int i=0;i<numpoints;i++)
+    {
+      double x[3];
+      this->Points->GetPoint(i,x);
+      for (int ia=0;ia<=2;ia++)
+	sum[ia]+=x[ia];
+    }
+
+  for (int ia=0;ia<=2;ia++)
+    sum[ia]/=float(numpoints);
+  
+  xm=sum[0]; 
+  ym=sum[1];
+}
+// ------------------------------------------------------------------------------------
+void vtkpxContourSource::Smooth(float relaxation)
+{
+  
+  if (this->Points->GetNumberOfPoints()<5)
+      return;
+
+  relaxation=Frange(relaxation,0.0,0.99);
+  vtkPoints* tmpPoints=vtkPoints::New();
+  int np=this->Points->GetNumberOfPoints();
+
+  for (int pass=0;pass<=1;pass++)
+      {
+	tmpPoints->DeepCopy(this->Points);
+	
+	for (int i=0;i<np;i++)
+	  {
+	    int p0,p1;
+	    if (this->Closed)
+	      {
+		p0=Icyclic(i-1,np);
+		p1=Icyclic(i+1,np);
+	      }
+	    else
+	      {
+		p0=Irange(i-1,0,np-1);
+		p1=Irange(i+1,0,np-1);
+	      }
+	    
+	    double x0[3],x1[3],x[3];
+	    tmpPoints->GetPoint(p0,x0);
+	    tmpPoints->GetPoint(i,x);
+	    tmpPoints->GetPoint(p1,x1);
+	      
+	    for (int ia=0;ia<=2;ia++)
+	      {
+		if (pass==0)
+		  x[ia]=(1.0-relaxation)*x[ia]+0.5*relaxation*(x0[ia]+x1[ia]);
+		else
+		  x[ia]=(1.0-relaxation)*x[ia]+0.5*relaxation*(x0[ia]+x1[ia]);
+	      }
+	    this->Points->SetPoint(i,x);
+	  }
+	relaxation=-1.0*(relaxation+0.01);
+      }
+  tmpPoints->Delete();
+  this->Modified();
+
+
+}
+// ------------------------------------------------------------------------------------
+void vtkpxContourSource::Sample(int rate)
+{
+  if (this->Points->GetNumberOfPoints()<4)
+      return;
+
+  vtkPoints* tmpPoints=vtkPoints::New();
+  tmpPoints->DeepCopy(this->Points);
+  
+  this->Points->SetNumberOfPoints(0);
+  for (int j=0;j<tmpPoints->GetNumberOfPoints();j+=rate)
+    this->Points->InsertNextPoint(tmpPoints->GetPoint(j));
+
+  tmpPoints->Delete();
+  this->Modified();
+
+
+}
+// ------------------------------------------------------------------------------------
+void vtkpxContourSource::Subsample(int rate)
+{
+  if (this->Points->GetNumberOfPoints()<2)
+    return;
+
+  vtkPoints* tmpPoints=vtkPoints::New();
+  tmpPoints->SetNumberOfPoints(this->Points->GetNumberOfPoints()+1);
+  for (int i=0;i<this->Points->GetNumberOfPoints();i++)
+    tmpPoints->SetPoint(i,this->Points->GetPoint(i));
+
+  int np=this->Points->GetNumberOfPoints();
+
+  if (this->Closed)
+    {
+      tmpPoints->SetPoint(this->Points->GetNumberOfPoints(),this->Points->GetPoint(0));
+      np+=1;
+    }
+  
+  this->Points->SetNumberOfPoints(0);
+
+  for (int j=0;j<np-1;j++)
+    {
+      double x1[3],x2[3];
+      tmpPoints->GetPoint(j,x1);
+      tmpPoints->GetPoint(j+1,x2);
+
+      for (int k=0;k<rate;k++)
+	{
+	  float ratio2=((float)k)/((float)rate);
+	  float ratio1=1.0-ratio2;
+	  for (int l=0;l<=2;l++)
+	    x1[l]=ratio1*x1[l]+ratio2*x2[l];
+	  this->Points->InsertNextPoint(x1);
+	}
+    }
+  
+  // Add Last Point if open if closed this is the starting point hence ignore
+  if (!this->Closed)
+    this->Points->InsertNextPoint(tmpPoints->GetPoint(np-1));
+  tmpPoints->Delete();
+  this->Modified();
+}
+// ------------------------------------------------------------------------------------
+void vtkpxContourSource::Equispace(float sp)
+{
+  if (this->Points->GetNumberOfPoints()<2)
+      return;
+
+  int NumPoints=this->Points->GetNumberOfPoints();
+  float perimeter=this->GetContourLength();
+  float Spacing=sp;
+  if (Spacing<0.0)
+    Spacing=perimeter/float(NumPoints);
+  
+  // Copy Point to temp array
+  vtkPoints* tmpPoints=vtkPoints::New();
+  tmpPoints->SetNumberOfPoints(NumPoints+1);
+  int np=NumPoints;
+  for (int j=0;j<NumPoints;j++)
+    tmpPoints->SetPoint(j,this->Points->GetPoint(j));
+  if (this->Closed)
+    {
+      tmpPoints->SetPoint(NumPoints,this->Points->GetPoint(0));
+      np++;
+    }
+
+  // Allocate New set of points 
+  // Start New Set of Points at point 0
+  this->Points->SetNumberOfPoints(0);
+  this->Points->InsertNextPoint(tmpPoints->GetPoint(0));
+
+  // Initialize Control Points x0 and x1 
+  int index=0;
+  double x0[3],x1[3];
+  tmpPoints->GetPoint(index,x0);
+  tmpPoints->GetPoint(index+1,x1);  
+  float segment=0.0;
+  while(index<np-1)
+      {
+	float part=Fdist(x0[0],x0[1],x0[2],x1[0],x1[1],x1[2]);
+	segment+=part;
+	while (segment>=Spacing)
+	  {
+	    float ratio=1.0-(segment-Spacing)/part;
+	    segment=segment-Spacing;
+	    float tx[3];
+	    for (int ia=0;ia<=2;ia++)
+	      {
+		tx[ia]=(1.0-ratio)*x0[ia]+ratio*x1[ia];
+	      }
+	      this->Points->InsertNextPoint(tx);
+	  }
+	index++;
+	tmpPoints->GetPoint(index,x0);
+	tmpPoints->GetPoint(index+1,x1);
+      }
+
+  if (!this->Closed)
+    this->Points->InsertNextPoint(tmpPoints->GetPoint(np-1));
+
+  tmpPoints->Delete();
+  this->Modified();
+}
+
+// ------------------------------------------------------------------------------------
+void vtkpxContourSource::Equisample(int npoints)
+{
+  if (this->Points->GetNumberOfPoints()<2)
+    return;
+  
+  float perimeter=this->GetContourLength();
+  float sp=perimeter/float(npoints);
+  this->Equispace(sp);
+}
+
+// ------------------------------------------------------------------------------------
+int vtkpxContourSource::CyclicDistance(int p1,int p2,int np)
+{
+  int half=np/2;
+  int dist=0;
+  if (abs(p1-p2)<half)
+      {
+	dist=p1-p2;
+      }
+  else
+    {
+      if (p1>p2)
+	dist=p2+np-p1;
+      else
+	dist=p1+np-p2;
+    }
+  
+  return abs(dist);  
+}
+// ------------------------------------------------------------------------------------
+vtkpxContourSource* vtkpxContourSource::MapContours(vtkpxContourSource* cntr1,
+						    vtkpxContourSource* cntr2,
+						    int resample)
+{
+  if (resample)
+    {
+      cntr2->SetClosed(1);
+      cntr2->Equisample(cntr1->GetPoints()->GetNumberOfPoints()*8);
+      cntr2->Smooth(0.5);
+    }
+  
+  int np1=cntr1->GetPoints()->GetNumberOfPoints();
+  int np2=cntr2->GetPoints()->GetNumberOfPoints();
+
+  vtkPoints* points1=vtkPoints::New();
+  points1->DeepCopy(cntr1->GetPoints());
+  
+  vtkPoints* points2=vtkPoints::New();
+  points2->DeepCopy(cntr2->GetPoints());
+  
+  int* corr   =new int[np1];
+  int* used   =new int[np1];
+  int* fixed  =new int[np1];
+    
+  // Pass 1 --- Find all points that have symmetric neighbours
+  // ---------------------------------------------------------
+  for (int p1=0;p1<np1;p1++)
+    {
+      used[p1]=0;
+      fixed[p1]=0;
+      corr[p1]=-1;
+      float mindist=10000000.0;
+      int   besti=0;
+      for (int i=0;i<np2;i++)
+	{
+	  float dist=vtkMath::Distance2BetweenPoints(points1->GetPoint(p1),points2->GetPoint(i));
+	  if (dist<mindist)
+	    {
+	      mindist=dist;
+	      besti=i;
+	    }
+	}
+      
+      mindist=10000000.0;
+      int bestj=p1;
+      for (int j=0;j<np1;j++)
+	    {
+	      float dist=vtkMath::Distance2BetweenPoints(points1->GetPoint(j),points2->GetPoint(besti));
+	      if (dist<mindist)
+		{
+		  bestj=j;
+		  mindist=dist;
+		}
+	    }
+      
+      if (bestj==p1)
+	{
+	  used[p1]=1;
+	  fixed[p1]=1;
+	  corr[p1]=besti;
+	}
+    }
+  
+  // Pass 2: Fill in by averaging 
+  int notdone=1;
+  while (notdone==1)
+    {
+      notdone=0;
+      int p1;
+      for (p1=0;p1<np1;p1++)
+	{
+	  if (used[p1]==0)
+	    {
+	      int p0=Icyclic(p1-1,np1);
+	      while (used[p0]==0)
+		p0=Icyclic(p0-1,np1);
+	      int p2=Icyclic(p1+1,np1);
+	      while (used[p2]==0)
+		p2=Icyclic(p2+1,np1);
+	      
+	      int dist0=vtkpxContourSource::CyclicDistance(p0,p1,np1);
+	      int dist2=vtkpxContourSource::CyclicDistance(p1,p2,np1);
+	      float frac=(float(dist0)/float(dist0+dist2));
+	      
+	      int c1=0;
+	      if (corr[p2]<corr[p0])
+		c1=int(float(corr[p2]+np2-corr[p0])*frac+corr[p0]);
+	      else
+		c1=int(float(corr[p2]-corr[p0])*frac+corr[p0]);
+	      corr[p1]=Icyclic(c1,np2);
+	    }
+	}
+      for (p1=0;p1<np1;p1++)
+	{
+	  if (corr[p1]>=0)
+	    used[p1]=1;
+	}
+    }
+  
+  // Pass 3: Smoothing Iterations
+  // ----------------------------
+  int nummoved=1,iter=1;
+  while(nummoved>0 && iter<500)
+    {
+      nummoved=0;
+      for (int p=0;p<np1;p++)
+	{
+	  int p1=p;
+	  if (fixed[p1]==0 || iter>0)
+	    {
+	      int bestdist=1000000000;
+	      int shift=0;
+	      for (int s=0;s<=2;s++)
+		{
+		  int sh=s;
+		  if (s==2)
+		    sh=-1;
+		  int maxd=0,mind=100000000;
+		  int ptest=Icyclic(corr[p1]+sh,np2);
+		  for (int k=-1;k<=1;k+=2)
+		    {
+		      int p2=Icyclic(p1+k,np1);
+		      int dist=vtkpxContourSource::CyclicDistance(corr[p2],ptest,np2);
+		      maxd=Imax(maxd,dist);
+		      mind=Imin(mind,dist);
+		    }
+		  if (maxd<bestdist)
+		    {
+		      bestdist=maxd;
+		      shift=sh;
+		    }
+		}
+	      if (shift!=0)
+		{
+		  nummoved++;
+		  corr[p1]=Icyclic(corr[p1]+shift,np2);
+		}
+	    }
+	}
+      iter++;
+    }
+
+  // Cleanup
+  // -------
+  vtkpxContourSource* out=vtkpxContourSource::New();
+  out->SetClosed(1);
+  vtkPoints* outp=out->GetPoints();
+  for (int i=0;i<np1;i++)
+  outp->InsertNextPoint(points2->GetPoint(corr[i]));
+			
+  delete [] corr; delete [] used; delete [] fixed;
+  return out;
+}
+
+void vtkpxContourSource::Execute()
+{
+vtkPolyData* output = this->GetOutput();
+
+if (this->Points->GetNumberOfPoints()==0)
+    return;
+
+  vtkPoints    *c_points    = vtkPoints::New();
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  
+  c_points->DeepCopy(this->Points);
+  c_lines->Allocate(this->Points->GetNumberOfPoints()+2);
+  
+  int np=this->Points->GetNumberOfPoints();
+  vtkIdType pt[2];
+  for (int i=0;i<np;i++)
+    {
+      pt[0]=i;
+      pt[1]=i+1;
+      c_lines->InsertNextCell(2,pt);
+    }
+  
+  if (this->Closed==1)
+    {
+      pt[0]=np-1;
+      pt[1]=0;
+      c_lines->InsertNextCell(2,pt);
+    }
+  
+  output->SetPoints(c_points);
+  output->SetLines(c_lines);
+  c_points->Delete();
+  c_lines->Delete();
+}
+
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxContourSource.h b/bioimagesuite30_src/Legacy/vtkpxContourSource.h
new file mode 100644
index 0000000..4d93764
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxContourSource.h
@@ -0,0 +1,160 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxContourSource.h,v $
+  Language:  C++
+  Date:      $Date: 2002/04/02 15:57:16 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxContourSource 
+
+
+#ifndef __vtkpxContourSource_h
+#define __vtkpxContourSource_h
+
+#include "vtkPolyDataSource.h"
+#include "vtkpxSplineStackSource.h"
+
+
+class vtkPolyDataCollection;
+
+class vtkpxContourSource : public vtkPolyDataSource
+{
+public:
+  static vtkpxContourSource *New();
+  vtkTypeMacro(vtkpxContourSource,vtkPolyDataSource);
+
+  // Description:
+  // Is Contour Closed?
+  vtkSetClampMacro(Closed,int,0,1);
+  vtkGetMacro(Closed,int);
+  vtkBooleanMacro(Closed, int);
+
+  // Description:
+  // Get Points
+  vtkGetObjectMacro(Points,vtkPoints)
+
+  // Description:
+  // I/O Code
+  virtual int Load(const char* fname);
+  virtual int Save(const char* fname);
+
+  // Description:
+  // Initialization
+  virtual void Copy(vtkpxContourSource* other);
+  virtual void SetFromSplineStackSource(vtkpxSplineStackSource* sur,int level,float dist);
+
+  //BTX
+  // Description:
+  // Set From Contour Stack (For Internal use only)
+  virtual void SetFromContourStack(PXContourStack* cstack,int level);
+  virtual void SetFromContour(PXContour* cntr);
+  //ETX
+
+  // Description:
+  // Orientation Stuff
+  virtual int  EnsureAnticlockwise();
+  virtual int  EnsureClockwise();
+  virtual int  SetDirection(int dir=1); // + = Anti , -1 =Clock
+
+  // Description:
+  // Initialize 
+  virtual void SetCircle(int np=10,float radius=5.0,float x=50.0,float y=50.0);
+
+
+  // Description:
+  // Check Inside/Outside
+  virtual int   IsInside (float testpointx,float testpointy);
+  static  int   Intersect (float x1,float y1, 
+			   float x2,float y2, 
+			   float x,float y); 
+  // Description:
+  // Contour Statistics
+  // ----------------------
+  virtual float GetArea();  
+  virtual float GetContourLength();
+  virtual void  GetCentroid(float& x,float& y);
+
+ 
+  // Description:
+  // Contour Manipulation
+  // ------------------------
+  virtual void  Smooth(float relaxation);
+  virtual void  Sample(int width);
+  virtual void  Subsample(int maxratio);
+
+  virtual void  Equispace(float spacing);
+  virtual void  Equisample(int npoints);
+
+
+  // Description:
+  // Symmetric Nearest Neighbor Map of Contours
+  // ------------------------------------------
+  static vtkpxContourSource*  MapContours(vtkpxContourSource* cnt1,vtkpxContourSource* cntr2,int resample=1);
+  static int                  CyclicDistance(int p1,int p2,int np);
+
+protected:
+
+  vtkpxContourSource();
+  virtual ~vtkpxContourSource();
+  vtkpxContourSource(const vtkpxContourSource&) {};
+  void operator=(const vtkpxContourSource&) {};
+  
+  void Execute();
+
+
+  vtkPoints* Points;
+  int        Closed;
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxFemSolid.cpp b/bioimagesuite30_src/Legacy/vtkpxFemSolid.cpp
new file mode 100644
index 0000000..3e8841f
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxFemSolid.cpp
@@ -0,0 +1,1412 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxFemSolid.cpp,v $
+  Language:  C++
+  Date:      $Date: 2003/06/05 21:07:43 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "pxutil.h"
+#include "pxabaqussolid.h"
+#include "vtkCellArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkpxFemSolid.h"
+#include "vtkFloatArray.h"
+#include "pxabaqussolid.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkSphereSource.h"
+#include "vtkCollection.h"
+#include "vtkCellData.h"
+#include "vtkMath.h"
+#include "nrutil.h"
+#include "pxgeometrystruct.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+//------------------------------------------------------------------------------
+vtkpxFemSolid* vtkpxFemSolid::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxFemSolid");
+  if(ret)
+    {
+    return (vtkpxFemSolid*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxFemSolid;
+}
+//------------------------------------------------------------------------------
+vtkpxFemSolid::vtkpxFemSolid()
+{
+  this->InternalSolid=new PXAbaqusSolid();
+  this->ColorMode=0;
+  this->StrainMode=0;
+  this->WarpMode=0;
+}
+//------------------------------------------------------------------------------
+vtkpxFemSolid::~vtkpxFemSolid()
+{
+  if (this->InternalSolid)
+      delete this->InternalSolid;
+
+}
+//------------------------------------------------------------------------------
+int vtkpxFemSolid::Save(const char* fname)
+{
+  if (this->InternalSolid==NULL)
+      return 0;
+  return this->InternalSolid->Save(fname);
+}
+//------------------------------------------------------------------------------
+int vtkpxFemSolid::Load(const char* fname)
+{
+  int ok=this->InternalSolid->Load(fname);
+  if (ok)
+    this->Modified();
+
+  return ok;
+}
+//------------------------------------------------------------------------------
+PXAbaqusSolid* vtkpxFemSolid::GetInternalSolid()
+{
+  return this->InternalSolid;
+
+}
+
+PXAbaqusOutputData* vtkpxFemSolid::GetInternalFemData()
+{
+  return this->InternalSolid->getfemdata();
+}
+//------------------------------------------------------------------------------
+void vtkpxFemSolid::Copy(vtkpxFemSolid* other)
+{
+  this->InternalSolid->Copy(other->GetInternalSolid());
+  this->Modified();
+}
+//------------------------------------------------------------------------------
+int vtkpxFemSolid::CreateFemData()
+{
+  this->InternalSolid->allocateFemData();
+  return 1;
+}
+
+int vtkpxFemSolid::LoadFemData(const char* line)
+{
+  return this->InternalSolid->getfemdata()->Load(line);
+}
+
+int vtkpxFemSolid::SaveFemData(const char* line)
+{ 
+  return this->InternalSolid->getfemdata()->Save(line);
+}
+
+float vtkpxFemSolid::GetDisplacement(int node,int comp)
+{
+  if (this->InternalSolid->getfemdata()!=NULL)
+    return this->InternalSolid->getfemdata()->getdispcomponent(node,comp);
+  
+  return -1.0;
+}
+
+float vtkpxFemSolid::GetStrain(int node,int comp)
+{
+  if (this->InternalSolid->getfemdata()!=NULL)
+    return this->InternalSolid->getfemdata()->getstraincomponent(node,comp);
+ 
+  return 0.0;
+}
+
+//------------------------------------------------------------------------------
+int vtkpxFemSolid::GenerateHexahedralSolid(vtkpxTriangulatedStackSource* endo,
+					    vtkpxTriangulatedStackSource* epi,
+					    int nodes,int totalnumstacks,int bias)
+{
+  return this->GenerateHexahedralSolid(endo,epi,nodes,totalnumstacks,bias,1.0,0);
+}
+//------------------------------------------------------------------------------
+int vtkpxFemSolid::GenerateHexahedralSolid(vtkpxTriangulatedStackSource* endo,
+					   vtkpxTriangulatedStackSource* epi,
+					   int nodes,int totalnumstacks,int bias,float sample,
+					   int skipslices)
+{
+  if (endo==NULL || epi == NULL )
+    return 0;
+
+  PXAbaqusSolid::debugmode=0;
+
+  PXAbaqusSolid* temp=new PXAbaqusSolid(endo->GetTStack(),epi->GetTStack());
+  int ok=temp->generateHexahedralSolid(nodes,totalnumstacks,bias,sample,skipslices);
+  temp->allocateMaterial();
+  temp->allocateSpringSpace(1);
+  PXAbaqusMaterialModel* mat=temp->getmaterial();
+  mat->setElastic();
+  temp->setSpringParameters(1,1.0);
+  
+  if (ok==0)
+    {
+      delete temp;
+      return 0;
+    }
+  
+  delete this->InternalSolid;
+  this->InternalSolid=temp;
+  this->Modified();
+  return 1;
+}
+//------------------------------------------------------------------------------
+void vtkpxFemSolid::Execute()
+{
+  if (!this->InternalSolid->haselements() || !this->InternalSolid->hasnodes())
+    {
+      vtkSphereSource* sph=vtkSphereSource::New();
+      sph->SetRadius(0.1);
+      sph->Update();
+      this->GetOutput()->ShallowCopy(sph->GetOutput());
+      sph->Delete();
+      return;
+    }
+
+  PXNeighboursList* elements=this->InternalSolid->getelements();
+  PXSolidNodes* nodes=this->InternalSolid->getnodes();
+
+  int nel=elements->getnumnodes();
+  int nump=nodes->getnumnodes();
+  
+  vtkPoints *points = vtkPoints::New();
+  points->SetNumberOfPoints(nump);
+  
+  int doscalars=0,dowarp=0;
+  PXAbaqusOutputData* femdata=this->InternalSolid->getfemdata();
+
+  if ( this->InternalSolid->hasfemdata()==1 && this->ColorMode>0)
+    doscalars=1;
+ 
+  if ( this->InternalSolid->hasfemdata()==1 && this->WarpMode>0)
+    dowarp=1;
+
+
+  vtkCellArray *polys = vtkCellArray::New();
+  vtkUnsignedCharArray* col=vtkUnsignedCharArray::New();
+
+  if (doscalars)
+    {
+      col->SetNumberOfComponents(3);
+      col->Allocate(nel*6,20);
+    }
+  
+
+  if (dowarp==0)
+    {
+      for(int i=0; i<nump; i++)
+	points->SetPoint(i,nodes->getpoint(i)->x[0], nodes->getpoint(i)->x[1], nodes->getpoint(i)->x[2]);	       
+    }
+  else
+    {
+      for(int i=0; i<nump; i++)
+	points->SetPoint(i,
+			 nodes->getpoint(i)->x[0]+femdata->getdispcomponent(i,0), 
+			 nodes->getpoint(i)->x[1]+femdata->getdispcomponent(i,1), 
+			 nodes->getpoint(i)->x[2]+femdata->getdispcomponent(i,1));	       
+    }
+
+  
+  elements->Rewind();
+  int cindex=0;
+  for(int e=0; e<nel; e++)
+    {
+      PXIntegerList* intList=((elements->getcurrentnode())->points);
+      float c[3];
+      int numcolors=0;
+      
+      if (doscalars)
+	{
+	  float val=femdata->getstraincomponent(e,this->StrainMode);
+	  if (this->ColorMode ==1 || this->ColorMode == 2)
+	    val=float(e);
+	  this->LookupColorMode(c,val,this->ColorMode);
+	}
+	 
+      intList->Rewind();
+      if (intList->getnumnodes()==8)
+	{
+	  vtkIdType pt[4],index[8];
+	  for (int ia=0;ia<8;ia++)
+	    {
+	      index[ia]=intList->getcurrent();  
+	      intList->Next(); 
+	    }
+	  pt[0]=index[0]; pt[1]=index[3]; pt[2]=index[7]; pt[3]=index[4]; polys->InsertNextCell(4,pt);
+	  pt[0]=index[1]; pt[1]=index[2]; pt[2]=index[6]; pt[3]=index[5]; polys->InsertNextCell(4,pt);
+	  pt[0]=index[0]; pt[1]=index[1]; pt[2]=index[2]; pt[3]=index[3]; polys->InsertNextCell(4,pt);
+	  pt[0]=index[4]; pt[1]=index[5]; pt[2]=index[6]; pt[3]=index[7]; polys->InsertNextCell(4,pt);
+	  pt[0]=index[0]; pt[1]=index[1]; pt[2]=index[5]; pt[3]=index[4]; polys->InsertNextCell(4,pt);
+	  pt[0]=index[2]; pt[1]=index[3]; pt[2]=index[7]; pt[3]=index[6]; polys->InsertNextCell(4,pt);
+	  numcolors=6;
+	}
+      else
+	{
+	  vtkIdType pt[3],index[4];
+	  for (int ia=0;ia<4;ia++)
+	    {
+	      index[ia]=intList->getcurrent();  
+	      intList->Next(); 
+	    }
+	  
+	  /* the twelve triangles */
+	  pt[0]  = index[0]; pt[1]  = index[1]; pt[2]  = index[2];  polys->InsertNextCell(3,pt);
+	  pt[0]  = index[0]; pt[1]  = index[1]; pt[2]  = index[3];  polys->InsertNextCell(3,pt);
+	  pt[0]  = index[0]; pt[1]  = index[2]; pt[2]  = index[3];  polys->InsertNextCell(3,pt);
+	  pt[0]  = index[1]; pt[1]  = index[2]; pt[2]  = index[3];  polys->InsertNextCell(3,pt);
+	  numcolors=4;
+	}
+      
+
+      if (doscalars)
+	{
+	  for (int ia=0;ia<numcolors;ia++)
+	    col->InsertNextTuple3(c[0],c[1],c[2]);
+	  ++cindex;
+	}
+      elements->Next();
+    }
+  
+  vtkPolyData *output = this->GetOutput();
+  output->SetPoints(points);
+  points->Delete();
+  output->SetPolys(polys);
+  polys->Delete();
+
+  if (doscalars)
+    output->GetCellData()->SetScalars(col);
+  col->Delete();
+
+}
+//------------------------------------------------------------------------------
+void vtkpxFemSolid::LookupColorMode(float t[3],float val,int mode)
+{
+  float x[3];
+  /*
+
+  Modes
+
+  1 = Pies BW
+  2 = Pies
+  3 = Strain Peng-Cheng
+  4 = Strain Threshold
+  5,6 = Strain HSV
+
+  */
+
+
+  if (mode==1 || mode ==2)
+    {
+      int element=int(val);
+      int se=this->GetInternalFemData()->getnumsectors(); 
+      int nt=this->GetInternalFemData()->getnumtransmural();
+      int pie=this->GetInternalFemData()->getpieindex(element);
+
+      int slno=pie/(se*nt);
+      int odd=1;
+      if (2*int(slno/2)==slno)
+	odd=0;
+      
+      int pi=pie-slno*se;
+      int pi2=Icyclic(pi,3);
+
+      if (odd==0)
+	{
+	  if (mode==2)
+	    {
+	      if (pi==0)
+		{
+		  x[0]=0.7; x[1]=0.7; x[2]=0.7;
+		}
+	      else if (pi==se-1)
+		{
+		  x[0]=0.2; x[1]=0.2; x[2]=0.2; 
+		}
+	      else
+		{
+		  switch(pi2)
+		    {
+		    case 0:
+		      x[0]=0.2; x[1]=0.9; x[2]=0.9; break;
+		    case 1:
+		      x[0]=0.95; x[1]=1.0; x[2]=0.5; break;
+		    case 2:
+		      x[0]=1.0; x[1]=0.5; x[2]=0.2; break;
+		    }
+		}
+	    }
+	  else
+	    {
+	      switch (pi2)
+		{
+		case 0:
+		  x[0]=0.35; x[1]=0.35; x[2]=0.35; break;
+		case 1:
+		  x[0]=0.85; x[1]=0.85; x[2]=0.85; break;
+		case 2:
+		  x[0]=0.65; x[1]=0.65; x[2]=0.65; break;
+		  
+		}
+	    }
+	}
+      else
+	{
+	  if (mode==2)
+	    {
+	      if (pi==0)
+		{
+		  x[0]=0.9; x[1]=0.9; x[2]=0.9;
+		}
+	      else if (pi==se-1)
+		{
+		  x[0]=0.2; x[1]=0.1; x[2]=0.1;
+		}
+	      else
+		{
+		  switch(pi2)
+		    {
+		    case 0:
+		      x[0]=1.0; x[1]=0.5; x[2]=0.75; break;
+		    case 1:
+		      x[0]=0.5; x[1]=1.0; x[2]=0.78; break;
+		    case 2:
+		      x[0]=1.0; x[1]=0.7; x[2]=0.4; break;
+		    }
+		}
+	    }
+	  else
+	    {
+	      switch(pi2)
+		{
+		case 1:
+		  x[0]=0.3; x[1]=0.3; x[2]=0.3; break;
+		case 2:
+		  x[0]=0.8; x[1]=0.8; x[2]=0.8; break;
+		case 0:
+		  x[0]=0.5; x[1]=0.5; x[2]=0.5; break;
+		}
+	    }
+	}
+    }
+  else if (mode==3)
+    {
+      // Standard Peng-Cheng Color Scheme
+      if(val > 0.325)       x[0]=(0.75);
+      else if(val > 0.275)  x[0]=(1.00);	
+      else if(val > 0.225)  x[0]=(1.00);
+      else if(val > 0.175)  x[0]=(1.00);	
+      else if(val > 0.125)  x[0]=(1.00);	
+      else if(val > 0.075)  x[0]=(1.00);	
+      else if(val > 0.025)  x[0]=(1.00);	
+      else if(val > -0.025) x[0]=(1.00);	
+      else if(val > -0.075) x[0]=(0.80);	
+      else if(val > -0.125) x[0]=(0.40);	
+      else if(val > -0.175) x[0]=(0.0);	
+      else if(val > -0.225) x[0]=(0.60);	
+      else if(val > -0.275) x[0]=(0.20);	
+      else if(val > -0.325) x[0]=(0.0);	
+      else                  x[0]=(0.0);	
+      
+      if(val > 0.325)       x[1]=(0.0);
+      else if(val > 0.275)  x[1]=(0.2);	
+      else if(val > 0.225)  x[1]=(0.5);
+      else if(val > 0.175)  x[1]=(0.8);	
+      else if(val > 0.125)  x[1]=(0.8);	
+      else if(val > 0.075)  x[1]=(1.00);	
+      else if(val > 0.025)  x[1]=(1.00);	
+      else if(val > -0.025) x[1]=(1.00);	
+      else if(val > -0.075) x[1]=(1.00);	
+      else if(val > -0.125) x[1]=(1.00);	
+      else if(val > -0.175) x[1]=(0.5);	
+      else if(val > -0.225) x[1]=(1.00);	
+      else if(val > -0.275) x[1]=(0.50);	
+      else if(val > -0.325) x[1]=(0.0);	
+      else                  x[1]=(0.0);	
+      
+      if(val > 0.325)       x[2]=(0.15);
+      else if(val > 0.275)  x[2]=(0.3);	
+      else if(val > 0.225)  x[2]=(0.55);
+      else if(val > 0.175)  x[2]=(0.8);	
+      else if(val > 0.125)  x[2]=(0.0);	
+      else if(val > 0.075)  x[2]=(0.00);	
+      else if(val > 0.025)  x[2]=(0.75);	
+      else if(val > -0.025) x[2]=(1.00);	
+      else if(val > -0.075) x[2]=(0.6);	
+      else if(val > -0.125) x[2]=(0.2);	
+      else if(val > -0.175) x[2]=(0.0);	
+      else if(val > -0.225) x[2]=(1.00);	
+      else if(val > -0.275) x[2]=(1.0);	
+      else if(val > -0.325) x[2]=(1.0);	
+      else                  x[2]=(0.5);	
+      
+    }
+  else if (mode==4)
+    {
+      float v=0.0;
+      if (val>0.3)
+	v=1.0;
+      else if (val<=0.3 && val>=-0.3)
+	v=(val+0.3)*(1.666667);
+      else
+	v=-1.0;
+      
+      for (int ia=0;ia<=2;ia++)
+	x[ia]=v;
+    }
+  else if (mode==5 || mode==6)
+    {
+      
+      float h=0.60,s=0.0;
+      
+      if (mode==4)
+	{
+	  // Spect Data
+	  h=0.58;
+	  s=Frange(val/100.0,0.0,1.0);
+	}
+      else
+	{
+	  h=0.60;
+	  if (val>0.0)
+	    h=0.00;
+	  s=3.0*Frange(fabs(val),0.0,0.33);
+	}
+      
+      float v=0.8;
+      
+      h*=6.0;
+      int i=int(h);
+      float aa,bb,cc,f,r=0,g=0,b=0;
+      
+      f=h-float(i);
+      
+      aa= v*(1.0-s);
+      bb= v*(1.0- (s*f));
+      cc= v*(1.0- (s* (1.0-f)));
+      
+      switch (i)
+	{
+	case 0: 
+	  r=v; g=cc; b=aa; 
+	  break;
+	case 1: 
+	  r=bb; g=v; b=aa;
+	  break;
+	case 2:
+	  r=aa; g=v; b=cc;
+	  break;
+	case 3:
+	  r=aa; g=bb; b=v;
+	  break;
+	case 4:
+	  r=cc; g=aa; b=v;
+	  break;
+	case 5:
+	  r=v;  g=aa; b=bb;
+	  break;
+	}
+      x[0]=r;
+      x[1]=g;
+      x[2]=b;
+    }
+  else
+    {
+      x[0]=0.5;
+      x[1]=0.5;
+      x[2]=0.5;
+    }
+  
+  for (int ia=0;ia<=2;ia++)
+    t[ia]=(unsigned char)(254.0 * x[ia] +0.5);
+}
+
+
+// --------------------------------------------------------------
+
+
+void vtkpxFemSolid::Scale(float s)
+{
+  PXSolidNodes* nodes=this->InternalSolid->getnodes();
+  int nump=nodes->getnumnodes();
+
+  for(int i=0; i<nump; i++)
+    for (int ia=0;ia<=2;ia++)
+      nodes->getpoint(i)->x[ia]=s*nodes->getpoint(i)->x[ia];
+    
+  if (this->InternalSolid->hasstacks())
+    {
+      this->InternalSolid->getstack(0)->scalepoints(s,s,s);
+      this->InternalSolid->getstack(1)->scalepoints(s,s,s);
+    }
+}
+
+int vtkpxFemSolid::GetNumberOfNodes()
+{
+ PXSolidNodes* nodes=this->InternalSolid->getnodes();
+ return nodes->getnumnodes();
+
+}
+
+int vtkpxFemSolid::GetNumberOfElements()
+{
+  PXNeighboursList* elements=this->InternalSolid->getelements();
+  return elements->getnumnodes();
+}
+
+// --------------------------------------------------------------
+//  Reslice into pies
+// --------------------------------------------------------------
+
+int vtkpxFemSolid::ReslicePies(vtkCollection* solidCollection,int numframes,
+			       int numslices,int numsectors,int numtransmural,int anti,
+			       float ref[3])
+{
+  PXAbaqusSolid* basesolid=((vtkpxFemSolid*)solidCollection->GetItemAsObject(0))->GetInternalSolid();
+  if (basesolid->hasfemdata()==PXFalse)
+    {
+      fprintf(stderr,"No Data!\n");
+      return 0;
+    }
+
+  numslices=Irange(numslices,1,100);
+  numsectors=Irange(numsectors,1,100);
+  numtransmural=Irange(numtransmural,1,3);
+
+  fprintf(stderr,"++++++++++++++ Subdivide Pies (anti=%d) numslices=%d numsectors=%d numt=%d\n",anti,
+	  numslices,numsectors,numtransmural);
+  fprintf(stderr,"++++++++++++++ Ref = (%f,%f,%f) \n",ref[0],ref[1],ref[2]);
+
+
+  int numpies=numslices*numsectors*numtransmural;
+  fprintf(stderr,"Numpies=%d nodes=%d elements=%d frames=%d\n",numpies,
+	  basesolid->getnodes()->getnumnodes(),
+	  basesolid->getelements()->getnumnodes(),
+	  numframes);
+
+  // Precompute some stuff 
+  // Global Solid Stuff
+  float globalminz=100000.0,globalmaxz=-1000000.0,cx=0.0,cy=0.0,tvol=0.0;
+  int i=0;
+  for (i=0;i<basesolid->getnodes()->getnumnodes();i++)
+    {
+      float z=basesolid->getnodes()->getpoint(i)->x[2];
+      globalminz=Fmin(globalminz,z);
+      globalmaxz=Fmax(globalmaxz,z);
+    }
+
+  for (i=0;i<basesolid->getelements()->getnumnodes();i++)
+    {
+      float v=basesolid->getfemdata()->getvolume(i);
+      if (v<0.01)
+	v=1.0;
+      cx+=(basesolid->getfemdata()->getcentroid(i))->x[0]*v;
+      cy+=(basesolid->getfemdata()->getcentroid(i))->x[1]*v;
+      tvol+=v;
+    }
+  cx/=tvol; cy/=tvol;
+
+  fprintf(stderr,"tvol=%.2f cx=%.2f cy=%.2f zrange=%.1f:%.1f\n",tvol,cx,cy,globalminz,globalmaxz);
+
+  
+  // For all elements stuff
+  // ----------------------
+  float* elementZmin=new float[basesolid->getelements()->getnumnodes()];
+  float* elementZmax=new float[basesolid->getelements()->getnumnodes()];
+  float* elementPmin=new float[basesolid->getelements()->getnumnodes()];
+  float* elementPmax=new float[basesolid->getelements()->getnumnodes()];
+  float* elementTmin=new float[basesolid->getelements()->getnumnodes()];
+  float* elementTmax=new float[basesolid->getelements()->getnumnodes()];
+  float *ave=new float[numpies];
+  float *vol0=new float[numpies];
+
+  float phase_ref=atan2(ref[1]-cy,ref[0]-cx)*180/M_PI;
+
+  basesolid->getelements()->Rewind();
+  for (int el=0;el<basesolid->getelements()->getnumnodes();el++)
+    {
+      PXAbaqusSolid::getElementRange(basesolid->getelements()->getcurrentnode()->points,
+				     basesolid->getnodes(),
+				     cx,cy,phase_ref,
+				     elementZmin[el],elementZmax[el],elementPmin[el],elementPmax[el],
+				     elementTmin[el],elementTmax[el]);
+      basesolid->getelements()->Next();
+    }
+  
+  
+  int maxstrain=5;
+  int orient=basesolid->getorientationmode();
+  if (orient==5)
+    maxstrain=2;
+  
+  for (int f=0;f<numframes;f++)
+    {
+      PXAbaqusOutputData* currentdata=((vtkpxFemSolid*)solidCollection->GetItemAsObject(f))->GetInternalFemData();
+      currentdata->setPieStats(numpies,
+			       numsectors,numslices,numtransmural);
+      
+      for (int strain=0;strain<=maxstrain;strain++)
+	{
+	  for (int j=0;j<numpies;j++)
+	    {
+	      ave[j]=0.0;
+	      if (f==0)
+		vol0[j]=0.0;
+	    }
+
+	  for (int el=0;el<basesolid->getelements()->getnumnodes();el++)
+	    {
+	      float elvol0=(basesolid->getfemdata())->getvolume(el);
+	      int   bestpie=0;
+	      float maxfr=0.0;
+
+	      for (int slice=0;slice<numslices;slice++)
+		{
+		  float zfr=1.0;
+		  if (numslices>1)
+		    zfr=PXAbaqusSolid::returnElementFraction(elementZmin[el],elementZmax[el],
+							     globalminz,globalmaxz,slice,numslices);
+		  
+		  for (int sector=0;sector<numsectors;sector++)
+		    {
+		      int realsector=(numsectors)-sector;
+		      if (anti==1)
+			realsector=sector+1;
+		      
+		      if (realsector==numsectors)
+			realsector=0;
+		      
+		      float secfr=1.0;
+		      if (numsectors>1)
+			{
+			  float elminangle= elementPmin[el];
+			  float elmaxangle= elementPmax[el];
+			  
+			  if (sector<numsectors-1)
+			    {
+			      if (elminangle>elmaxangle)
+				elminangle-=360.0;
+			    }
+			  else
+			    {
+			      if (elminangle>elmaxangle)
+				elmaxangle+=360.0;
+			    }
+			  
+			  secfr=PXAbaqusSolid::returnElementFraction(elminangle,elmaxangle,
+								     0.0,360.0,
+								     sector,numsectors);
+			}
+		      
+		      for (int subsector=0;subsector<numtransmural;subsector++)
+			{
+			  float wedfr=1.0;
+			  int   pie=(subsector+(realsector*numtransmural)+(slice*numsectors*numtransmural));
+		      
+			  if (numtransmural>1)
+			    {
+			      wedfr=PXAbaqusSolid::returnElementFraction(elementTmin[el],
+									 elementTmax[el],
+									 0,100,subsector,numtransmural);
+			    }
+
+			  float frac=secfr*zfr*wedfr;
+			  
+			  if (f==0)
+			    vol0[pie]+=frac*elvol0;
+			  
+			  float stcomp=
+			    currentdata->getstraincomponent(el,strain);
+			  ave[pie]+=stcomp*frac*elvol0;
+
+			  if (strain==0)
+			    {
+			      if (frac>maxfr)
+				{
+				  maxfr=frac;
+				  bestpie=pie;
+
+				}
+			    }
+			}
+		    }
+		}
+	      if (strain==0)
+		currentdata->setElementPieIndex(el,bestpie);
+	    }
+	  
+	  for (int i=0;i<numpies;i++)
+	    {
+	      if (vol0[i]<0.001)
+		ave[i]=0.0;
+	      else
+		ave[i]/=vol0[i];
+	    }
+	      
+	  for (int el2=0;el2<basesolid->getelements()->getnumnodes();el2++)
+	    {
+	      int pindex=currentdata->getpieindex(el2);
+	      currentdata->setstraincomponent(el2,strain+6,ave[pindex]);
+	    }
+	}
+    }
+
+  for (int f2=0;f2<numframes;f2++)
+    ((vtkpxFemSolid*)solidCollection->GetItemAsObject(0))->Modified();
+    
+  delete [] ave;
+  delete [] vol0;
+  delete [] elementZmin;
+  delete [] elementZmax;
+  delete [] elementPmin;
+  delete [] elementPmax;
+  delete [] elementTmin;
+  delete [] elementTmax;
+
+  return 1;
+
+}
+
+// --------------------------------------------------------------
+
+int vtkpxFemSolid::SavePies(const char* fname,vtkCollection* solidCollection,int numframes,
+			    int numslices,int numsectors,int numtransmural,int anticlockwise,
+			    float ref[3])
+{
+  PXAbaqusSolid* basesolid=((vtkpxFemSolid*)solidCollection->GetItemAsObject(0))->GetInternalSolid();
+  if (basesolid->hasfemdata()==PXFalse)
+    {
+      fprintf(stderr,"No Data!\n");
+      return 0;
+    }
+
+
+  numslices=Irange(numslices,1,100);
+  numsectors=Irange(numsectors,1,100);
+  numtransmural=Irange(numtransmural,1,3);
+
+  int numpies=numslices*numsectors*numtransmural;
+  fprintf(stderr,"Numpies=%d\n",numpies);
+  fprintf(stderr,"++++++++++++++ Subdivide and Save in `%s' (anti=%d) \n",fname,anticlockwise);
+
+  if (!basesolid->hasfemdata())
+      return 0;
+
+  FILE* fout=fopen(fname,"w");
+  if (fout==NULL)
+      return 0;
+
+
+  fprintf(fout,"# Pie data \n");
+  int orient=basesolid->getorientationmode();
+  {
+    if (orient==1 || orient==3)
+      fprintf(fout,"# Strains defined in Cardiac Coordinate Space\n");
+    else if (orient==5)
+      fprintf(fout,"# Strains defined in Principal Directions\n");
+    else
+      fprintf(fout,"# Strains defined in Fibre-Specific Coordinate Space\n");
+  }
+  
+  // Precompute some stuff 
+  // Global Solid Stuff
+  float globalminz=100000.0,globalmaxz=-1000000.0,cx=0.0,cy=0.0,tvol=0.0;
+  {
+    for (int i=0;i<basesolid->getnodes()->getnumnodes();i++)
+      {
+	float z=basesolid->getnodes()->getpoint(i)->x[2];
+	globalminz=Fmin(globalminz,z);
+	globalmaxz=Fmax(globalmaxz,z);
+      }
+    
+    
+    {
+      for (int i=0;i<basesolid->getelements()->getnumnodes();i++)
+	{
+	  float v=basesolid->getfemdata()->getvolume(i);
+	  if (v<0.01)
+	    v=1.0;
+	  cx+=(basesolid->getfemdata()->getcentroid(i))->x[0]*v;
+	  cy+=(basesolid->getfemdata()->getcentroid(i))->x[1]*v;
+	  tvol+=v;
+	}
+    }
+    cx/=tvol; cy/=tvol;
+    fprintf(fout,"# Total volume= %9.3f\n",tvol);
+  }
+  
+  // For all elements stuff
+  // ----------------------
+  float* elementZmin=new float[basesolid->getelements()->getnumnodes()];
+  float* elementZmax=new float[basesolid->getelements()->getnumnodes()];
+  float* elementPmin=new float[basesolid->getelements()->getnumnodes()];
+  float* elementPmax=new float[basesolid->getelements()->getnumnodes()];
+  float* elementTmin=new float[basesolid->getelements()->getnumnodes()];
+  float* elementTmax=new float[basesolid->getelements()->getnumnodes()];
+
+  float phase_ref=atan2(ref[1]-cy,ref[0]-cx)*180/M_PI;
+
+  fprintf(stderr,"Phase_ref=%f\n",phase_ref);
+  
+
+  fprintf(fout,"# LV-RV Junction Defined as (%6.2f,%6.2f,%6.2f)\n",ref[0],ref[1],ref[2]);
+  fprintf(fout,"# Phase_ref =%6.3f degrees (cx=%6.2f,cy=%6.2f)\n",phase_ref,cx,cy);
+  fprintf(fout,"# Number of slices=%d, sectors=%d\n",numslices,numsectors);
+
+  basesolid->getelements()->Rewind();
+  for (int el=0;el<basesolid->getelements()->getnumnodes();el++)
+      {
+	PXAbaqusSolid::getElementRange(basesolid->getelements()->getcurrentnode()->points,
+				       basesolid->getnodes(),
+				       cx,cy,phase_ref,
+				       elementZmin[el],elementZmax[el],elementPmin[el],elementPmax[el],
+				       elementTmin[el],elementTmax[el]);
+	/*	if (10*int(el/10)==el)
+	    fprintf(stderr,"Element el=%d %f:%f\n",el,elementTmin[el],elementTmax[el]);*/
+	basesolid->getelements()->Next();
+      }
+  
+  float *piesmat=new float [numpies*numframes];
+  float *ave=new float[numpies];
+  float *vol=new float[numpies];
+  float *vol0=new float[numpies];
+  int numel=basesolid->getelements()->getnumnodes();
+
+  int start=-1;
+  
+  int maxstrain=5;
+  if (orient==5)
+      maxstrain=2;
+  
+  for (int strain=start;strain<=maxstrain;strain++)
+      {
+	for (int f=0;f<numframes;f++)
+	    {
+	      PXAbaqusOutputData* currentdata=((vtkpxFemSolid*)solidCollection->GetItemAsObject(f))->GetInternalFemData();
+	      for (int j=0;j<numpies;j++)
+		  {
+		    ave[j]=0.0;
+		    vol[j]=0.0;
+		    if (f==0)
+			vol0[j]=0.0;
+		  }
+	      
+	      if (strain==start)
+		  currentdata->setPieStats(numslices*numsectors*numtransmural,
+							 numsectors*numtransmural,numslices);
+
+	      for (int el=0;el<basesolid->getelements()->getnumnodes();el++)
+		  {
+		    float elvol0=(basesolid->getfemdata())->getvolume(el);
+		    float elvol =currentdata->getvolume(el);
+		    
+		    int bestpie=0;
+		    float maxfr=0.0;
+		    for (int slice=0;slice<numslices;slice++)
+			{
+			  float zfr=1.0;
+			  if (numslices>1)
+			    zfr=PXAbaqusSolid::returnElementFraction(elementZmin[el],elementZmax[el],
+								     globalminz,globalmaxz,slice,numslices);
+			  
+			  for (int sector=0;sector<numsectors;sector++)
+			      {
+				int realsector=(numsectors)-sector;
+				if (anticlockwise==1)
+				    realsector=sector+1;
+
+				if (realsector==numsectors)
+				    realsector=0;
+
+				float secfr=1.0;
+				if (numsectors>1)
+				    {
+				      float elminangle= elementPmin[el];
+				      float elmaxangle= elementPmax[el];
+				      
+				      if (sector<numsectors-1)
+					  {
+					    if (elminangle>elmaxangle)
+						elminangle-=360.0;
+					  }
+				      else
+					  {
+					    if (elminangle>elmaxangle)
+						elmaxangle+=360.0;
+					  }
+				      
+				      secfr=PXAbaqusSolid::returnElementFraction(elminangle,elmaxangle,
+										 0.0,360.0,
+										 sector,numsectors);
+				    }
+				for (int subsector=0;subsector<numtransmural;subsector++)
+				    {
+				      int   pie=subsector+realsector*numtransmural+
+					  slice*numsectors*numtransmural;
+				      
+				      float wedfr=1.0;
+				      if (numtransmural>1)
+					  {
+					    wedfr=PXAbaqusSolid::returnElementFraction(elementTmin[el],
+										       elementTmax[el],
+										       0,100,subsector,numtransmural);
+					  }
+				      float frac=secfr*zfr*wedfr;
+				      
+				      if (frac>maxfr)
+					  {
+					    maxfr=frac;
+					    bestpie=pie;
+					  }
+				      vol[pie]+=frac*elvol;
+				      if (f==0)
+					  vol0[pie]+=frac*elvol0;
+				      if (strain>=0)
+					  {
+					    float stcomp=
+						currentdata->getstraincomponent(el,strain);
+					    ave[pie]+=stcomp*frac*elvol0;
+					  }
+				    }
+			      }
+			}
+		    if (strain==start)
+			currentdata->setElementPieIndex(el,bestpie);
+		  }
+	      if (strain>=0)
+		  {
+		    for (int i=0;i<numpies;i++)
+			{
+			  if (vol0[i]<0.001)
+			      ave[i]=0.0;
+			  else
+			      ave[i]/=vol0[i];
+			}
+		    for (int j=0;j<numpies;j++)
+			piesmat[j*numframes+f]=ave[j];
+		  }
+	      else
+		  {
+		    for (int j=0;j<numpies;j++)
+			piesmat[j*numframes+f]=vol[j];
+		  } 
+	    }
+	fprintf(fout,"\n");
+	
+	if (orient<2 || orient==3 || strain<0)
+	    {
+	      switch(strain)
+		  {
+		  case -1:
+		    fprintf(fout,"#\n\t\t Volume \n"); break;
+		  case 0:
+		    fprintf(fout,"#\n\t\t Radial Strain RR\n"); break;
+		  case 1:
+		    fprintf(fout,"#\n\t\t Circumferential Strain CC\n"); break;
+		  case 2:
+		    fprintf(fout,"#\n\t\t Longitudinal Strain LL\n"); break;
+		  case 3:
+		    fprintf(fout,"#\n\t\t Radial-Circumferential Shear Strain RC\n"); break;
+		  case 4:
+		    fprintf(fout,"#\n\t\t Radial-Longitudinal Strain RL\n"); break;
+		  case 5:
+		    fprintf(fout,"#\n\t\t Circumferential-Longitudinal Strain CL\n"); break;
+		  }
+	    }
+	else if (orient==5)
+	    {
+	      fprintf(fout,"#\n\t\t Principal Strain %d\n",strain+1);
+	    }
+	else
+	    {
+	      switch(strain)
+		  {
+		  case 0:
+		    fprintf(fout,"#\n\t\t Circumferential Cross-Fibre Strain XX\n"); break;
+		  case 1:
+		    fprintf(fout,"#\n\t\t Radial Strain RR\n"); break;
+		  case 2:
+		    fprintf(fout,"#\n\t\t Fibre Strain FF\n"); break;
+		  case 3:
+		    fprintf(fout,"#\n\t\t Circumferential-Radial Shear Strain XR\n"); break;
+		  case 4:
+		    fprintf(fout,"#\n\t\t Circumferential-Fibre Strain XF\n"); break;
+		  case 5:
+		    fprintf(fout,"#\n\t\t Radial-Fibre Strain RF\n"); break;
+		  }
+	    }
+	
+	fprintf(fout,"Pie/Frame ");
+	{
+	  for (int f=0;f<numframes;f++)
+	      fprintf(fout," %7d",f+1);
+	}
+	fprintf(fout,"\n");
+	int minj=0;
+	if (basesolid->getnodes()->getnumnodes()<100)
+	    minj=2;
+	for (int j=minj;j<numpies;j++)
+	    {
+	      fprintf(fout,"  %7d   ",j+1);
+	      for (int f=0;f<numframes;f++)
+		  if (strain==-1)
+		      fprintf(fout," %6.1f ",piesmat[j*numframes+f]);
+		  else
+		      fprintf(fout," %6.3f ",piesmat[j*numframes+f]);
+	      fprintf(fout,"\n");
+	    }
+      }
+  
+  if (basesolid->getnodes()->getnumnodes()<100)
+      {
+	fprintf(fout, "\n\nPie division for each elements\nElement\tPie\n");
+	for (int i=0;i<numel;i++)
+	    {
+	      int p=basesolid->getfemdata()->getpieindex(i);
+	      fprintf(fout,"%d \t%d\n!",i+1,p);
+	    }
+      }
+  
+  fclose(fout);
+  char line[500];
+  sprintf(line,"%s.pieindex",fname);
+  basesolid->getfemdata()->savePieDivision(line);
+
+  delete [] piesmat;
+  delete [] ave;
+  delete [] vol;
+  delete [] vol0;
+  delete [] elementZmin;
+  delete [] elementZmax;
+  delete [] elementPmin;
+  delete [] elementPmax;
+  delete [] elementTmin;
+  delete [] elementTmax;
+  return 1;
+}
+
+
+int vtkpxFemSolid::ReorientStrainsToFiberOrientation(vtkImageData* e1xyzimage)
+{
+  
+  if (e1xyzimage==NULL)
+    {
+      fprintf(stderr,"Bad Image\n");
+      return 0;
+    }
+
+  if (this->InternalSolid->getfemdata()==NULL)
+    {
+      fprintf(stderr,"No displacement/strain data\n");
+      return 0;
+    }
+
+
+  PXAbaqusOutputData* femData=this->InternalSolid->getfemdata();
+  
+  float** R	 = matrix(0, 2, 0, 2);
+  float** R1	 = matrix(0, 2, 0, 2);
+  float** R2	 = matrix(0, 2, 0, 2);
+  float** E	 = matrix(0, 2, 0, 2);
+  float** E2	 = matrix(0, 2, 0, 2);
+
+  // inverse = 1
+  fprintf(stderr,"Rotating strains Cardiac --> Fibre \n");
+  
+
+  PXNeighboursList* elements=this->InternalSolid->getelements();
+  PXSolidNodes*    nodes   =this->InternalSolid->getnodes();   
+
+  elements->Rewind();
+  for (int el=0;el<elements->getnumnodes();el++)
+      {
+	PXIntegerList* intList=((elements->getcurrentnode())->points);
+	elements->Next();
+
+	float cx,cy,cz;
+	int layer=0;
+	this->InternalSolid->getElementCentroid(intList,cx,cy,cz);
+	for (int ka=0;ka<intList->getnumnodes();ka++)
+	  {
+	      layer+=nodes->getindex(intList->getcurrent(),0); 
+	      intList->Next();
+	    }
+	layer=layer/intList->getnumnodes();
+
+	float x1,x2,x3,y1,y2,y3,z1,z2,z3;
+	
+	intList->Rewind();
+	this->InternalSolid->getdirections(intList,
+					   x2,y2,z2,x3,y3,z3,x1,y1,z1,0);
+	
+	R1[0][0]=x2; R1[1][0]=y2; R1[2][0]=z2; // Radial
+	R1[0][1]=x3; R1[1][1]=y3; R1[2][1]=z3; // Circ?
+	R1[0][2]=x1; R1[1][2]=y1; R1[2][2]=z1; // Long?
+
+
+	float angle=this->InternalSolid->getFibreAngle(cz,layer);
+	this->InternalSolid->rotateFibreAngle(x3,y3,z3,  
+					      x1,y1,z1,
+					      x2,y2,z2, // Keep Radial Fixed
+					      angle);
+	
+	
+	double rad[3]; rad[0]=x2; rad[1]=y2; rad[2]=z2;
+	vtkMath::Normalize(rad);
+
+	double oldf[3];  oldf[0]=x3; oldf[1]=y3; oldf[2]=z3;
+	vtkMath::Normalize(oldf);
+
+	// here get fiber orientations
+	int img_index=e1xyzimage->FindPoint(cx,cy,cz);
+
+	double fib[3];
+	for (int ia=0;ia<=2;ia++)
+	  fib[ia]=e1xyzimage->GetPointData()->GetScalars()->GetComponent(img_index,ia);
+	
+	vtkMath::Normalize(fib);
+	
+	fprintf(stderr,"Element = %d --> centroid (%.2f,%.2f,%.2f) --> fibres (%.2f,%.2f,%.2f) , oldf (%.2f,%.2f,%.2f)\n",
+		el,cx,cy,cz,fib[0],fib[1],fib[2],oldf[0],oldf[1],oldf[2]);
+
+	double cfib[3];
+	vtkMath::Cross(fib,rad,cfib);
+	vtkMath::Cross(cfib,fib,rad);
+	
+	fprintf(stderr,"\t\t Final --> fibres (%.2f,%.2f,%.2f) , radial (%.2f,%.2f,%.2f) cf (%.2f,%.2f,%.2f)\n",
+		fib[0],fib[1],fib[2],rad[0],rad[1],rad[2],cfib[0],cfib[1],cfib[2]);
+	
+	
+	R2[0][0]=rad[0]; R2[1][0]=rad[1]; R2[2][0]=rad[2]; // Cross
+	R2[0][1]=cfib[0]; R2[1][1]=cfib[1]; R2[2][1]=cfib[2]; // Radial
+	R2[0][2]=fib[0]; R2[1][2]=fib[1]; R2[2][2]=fib[2]; // Fibre
+	
+	for(int i=0; i<=2; i++)
+	  for(int j=0; j<=2; j++)
+	    {
+	      R[i][j]=0.0;
+	      for(int m=0; m<=2; m++)
+		R[i][j] += R2[m][i] * R1[m][j];
+	    }
+      	
+	E[0][0] = femData->getstraincomponent(el,0); 
+	E[0][1] = femData->getstraincomponent(el,3); 
+	E[0][2] = femData->getstraincomponent(el,4); 
+
+	E[1][0] = femData->getstraincomponent(el,3); 
+	E[1][1] = femData->getstraincomponent(el,1); 
+	E[1][2] = femData->getstraincomponent(el,5); 
+
+	E[2][0] = femData->getstraincomponent(el,4); 
+	E[2][1] = femData->getstraincomponent(el,5);
+	E[2][2] = femData->getstraincomponent(el,2); 
+
+	
+	// E2=R*E*R' --> E2(i,j)=R(i,k)*E(k,m)*R'(m,j)
+	for (int i=0;i<=2;i++)
+	  for (int j=0;j<=2;j++)
+	    {
+	      E2[i][j]=0.0;
+	      for (int k=0;k<=2;k++)
+		for (int m=0;m<=2;m++)
+		  E2[i][j] += R[i][k]*E[k][m]*R[j][m];
+	    }
+	
+	femData->setElementInfo(el,1,-1.0,
+				E2[0][0],E2[1][1],E2[2][2],E2[0][1],E2[0][2],E2[1][2]);
+	
+	
+	/*if (el==0)
+	  {
+	      fprintf(stderr," E= %5.2f %5.2f %5.2f\n    %5.2f, %5.2f %5.2f\n    %5.2f %5.2f %5.2f\n\n",
+		       E[0][0], E[0][1], E[0][2], E[1][0], E[1][1], E[1][2], E[2][0], E[2][1], E[2][2]);
+	      fprintf(stderr,"E2= %5.2f %5.2f %5.2f\n    %5.2f, %5.2f %5.2f\n    %5.2f %5.2f %5.2f\n\n",
+		      E2[0][0],E2[0][1],E2[0][2],E2[1][0],E2[1][1],E2[1][2],E2[2][0],E2[2][1],E2[2][2]);
+	      E[0][0] = femData->getstraincomponent(el,0); 
+	      E[0][1] = femData->getstraincomponent(el,3); 
+	      E[0][2] = femData->getstraincomponent(el,4); 
+	      
+	      E[1][0] = femData->getstraincomponent(el,3); 
+	      E[1][1] = femData->getstraincomponent(el,1); 
+	      E[1][2] = femData->getstraincomponent(el,5); 
+	      
+	      E[2][0] = femData->getstraincomponent(el,4); 
+	      E[2][1] = femData->getstraincomponent(el,5);
+	      E[2][2] = femData->getstraincomponent(el,2); 
+	      fprintf(stderr,"+E= %5.2f %5.2f %5.2f\n    %5.2f, %5.2f %5.2f\n    %5.2f %5.2f %5.2f\n\n",
+		      E[0][0], E[0][1], E[0][2], E[1][0], E[1][1], E[1][2], E[2][0], E[2][1], E[2][2]);
+	    }*/
+	
+	
+      }
+
+  free_matrix(R,0,2,0,2); free_matrix(R1,0,2,0,2); free_matrix(R2,0,2,0,2);
+  free_matrix(E,0,2,0,2); free_matrix(E2,0,2,0,2);
+  return 1;
+}
+
+vtkPolyData* vtkpxFemSolid::GenerateFibreMaps(vtkImageData* e1xyzimage,double scale)
+{
+  
+  if (e1xyzimage==NULL)
+    {
+      fprintf(stderr,"Bad Image\n");
+      return NULL;
+    }
+
+  PXNeighboursList* elements=this->InternalSolid->getelements();
+
+  vtkPoints *c_points = vtkPoints::New();
+  c_points->SetNumberOfPoints(elements->getnumnodes()*2);
+
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  c_lines->Allocate(elements->getnumnodes(),10);
+
+  elements->Rewind();
+  for (int el=0;el<elements->getnumnodes();el++)
+    {
+      PXIntegerList* intList=((elements->getcurrentnode())->points);
+      elements->Next();
+      
+      float cx,cy,cz;
+
+      this->InternalSolid->getElementCentroid(intList,cx,cy,cz);
+	
+      // here get fiber orientations
+      int img_index=e1xyzimage->FindPoint(cx,cy,cz);
+      
+      double fib[3];
+      for (int ia=0;ia<=2;ia++)
+	fib[ia]=e1xyzimage->GetPointData()->GetScalars()->GetComponent(img_index,ia);
+      
+      vtkMath::Normalize(fib);
+	
+	
+      c_points->SetPoint(el*2,cx,cy,cz);
+      c_points->SetPoint(el*2+1,cx+scale*fib[0],cy+scale*fib[1],cz+scale*fib[2]);
+
+      vtkIdType pt[2];
+      pt[0]=el*2;
+      pt[1]=el*2+1;
+      c_lines->InsertNextCell(2,pt);
+    }
+
+  vtkPolyData* sur=vtkPolyData::New();
+  sur->SetPoints(c_points);
+  sur->SetLines(c_lines);
+  c_points->Delete();
+  c_lines->Delete();
+
+  return sur;
+}
+
+// -------------------------------------------------------------------------------------
+
+vtkPolyData* vtkpxFemSolid::GenerateInternalFibreMaps(double scale)
+{
+
+
+
+  PXNeighboursList* elements=this->InternalSolid->getelements();
+  PXSolidNodes* nodes=this->InternalSolid->getnodes();
+
+  vtkPoints *c_points = vtkPoints::New();
+  c_points->SetNumberOfPoints(elements->getnumnodes()*2);
+
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  c_lines->Allocate(elements->getnumnodes(),10);
+
+  elements->Rewind();
+  for (int el=0;el<elements->getnumnodes();el++)
+    {
+      PXIntegerList* intList=((elements->getcurrentnode())->points);
+      elements->Next();
+      
+      float cx,cy,cz;
+      this->InternalSolid->getElementCentroid(intList,cx,cy,cz);
+      int layer=0;
+      for (int ka=0;ka<intList->getnumnodes();ka++)
+	{
+	  layer+=nodes->getindex(intList->getcurrent(),0); 
+	  intList->Next();
+	}
+      layer=layer/intList->getnumnodes();
+      
+      float x1,x2,x3,y1,y2,y3,z1,z2,z3;
+	
+      intList->Rewind();
+      this->InternalSolid->getdirections(intList,x2,y2,z2,x3,y3,z3,x1,y1,z1,0);
+      	
+      double fib[3]; fib[0]=x3; fib[1]=y3;fib[2]=z3;
+      vtkMath::Normalize(fib);
+
+      c_points->SetPoint(el*2,cx,cy,cz);
+      c_points->SetPoint(el*2+1,cx+scale*fib[0],cy+scale*fib[1],cz+scale*fib[2]);
+
+      vtkIdType pt[2];
+      pt[0]=el*2;
+      pt[1]=el*2+1;
+      c_lines->InsertNextCell(2,pt);
+    }
+
+  vtkPolyData* sur=vtkPolyData::New();
+  sur->SetPoints(c_points);
+  sur->SetLines(c_lines);
+  c_points->Delete();
+  c_lines->Delete();
+
+  return sur;
+}
+
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxFemSolid.h b/bioimagesuite30_src/Legacy/vtkpxFemSolid.h
new file mode 100644
index 0000000..5f2ecc9
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxFemSolid.h
@@ -0,0 +1,183 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxFemSolid.h,v $
+  Language:  C++
+  Date:      $Date: 2003/05/28 16:42:57 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxFemSolid 
+
+
+#ifndef __vtkpxFemSolid_h
+#define __vtkpxFemSolid_h
+
+
+#include "vtkPolyDataSource.h"
+#include "vtkpxTriangulatedStackSource.h"
+
+
+class vtkPolyDataCollection;
+class vtkCollection;
+//BTX
+class PXAbaqusSolid;
+class PXAbaqusOutputData;
+//ETX
+
+class vtkpxFemSolid : public vtkPolyDataSource
+{
+public:
+  static vtkpxFemSolid *New();
+  vtkTypeMacro(vtkpxFemSolid,vtkPolyDataSource);
+
+  // Description:
+  // Initialization
+  virtual void Copy(vtkpxFemSolid* other);
+
+  // Description:
+  // Create Mesh 
+  virtual int GenerateHexahedralSolid(vtkpxTriangulatedStackSource* endo,
+				       vtkpxTriangulatedStackSource* epi,
+				       int nodes,int totalnumstacks,int bias);
+
+  virtual int GenerateHexahedralSolid(vtkpxTriangulatedStackSource* endo,
+				       vtkpxTriangulatedStackSource* epi,
+				       int nodes,int totalnumstacks,int bias,float sample,
+				       int skipslices);
+  
+  // Description:
+  // I/O Code -- save as .sld file 
+  virtual int Load(const char* fname);
+  virtual int Save(const char* fname);
+
+
+  // Description:
+  // Modes for Strain Value / Color Mode 
+  vtkSetClampMacro(ColorMode,int,0,6);
+  vtkGetMacro(ColorMode,int);
+  vtkSetClampMacro(StrainMode,int,0,11);
+  vtkGetMacro(StrainMode,int);
+
+  // Description:
+  // If Warp=on transform mesh using internal displacements 
+  vtkSetClampMacro(WarpMode,int,0,1);
+  vtkGetMacro(WarpMode,int);
+
+  // Description:
+  // Access Fem Data
+  virtual int CreateFemData();
+  virtual int LoadFemData(const char* line);
+  virtual int SaveFemData(const char* line);
+
+  // Description:
+  // Access Fem Data
+  virtual float GetDisplacement(int node,int comp);
+  virtual float GetStrain(int node,int comp);
+
+  // Description:
+  // Get Internal Solid and Fem Data
+  //BTX
+  virtual PXAbaqusSolid*      GetInternalSolid();
+  virtual PXAbaqusOutputData* GetInternalFemData();
+  //ETX
+
+  // Description:
+  // Scale Points
+  virtual void Scale(float s);
+
+
+  virtual int GetNumberOfNodes();
+  virtual int GetNumberOfElements();
+
+
+  // Description:
+  // Some Static Stuff
+  //BTX
+  static int ReslicePies(vtkCollection* solidCollection,int numframes,
+			 int numslices,int numsectors,int numtransmural,int anti,
+			 float ref[3]);
+  static int SavePies(const char* fname,vtkCollection* solidCollection,int numframes,
+		      int numslices,int numsectors,int numtransmural,int anti,
+		      float ref[3]);
+  //ETX
+
+
+  // Description:
+  // Final Issues
+  virtual int ReorientStrainsToFiberOrientation(vtkImageData* img);
+  virtual vtkPolyData* GenerateFibreMaps(vtkImageData* img,double scale=2.0);
+  virtual vtkPolyData* GenerateInternalFibreMaps(double scale=2.0);
+
+
+protected:
+
+  vtkpxFemSolid();
+  virtual ~vtkpxFemSolid();
+  vtkpxFemSolid(const vtkpxFemSolid&) {};
+  void operator=(const vtkpxFemSolid&) {};
+  
+  PXAbaqusSolid* InternalSolid;
+  int            ColorMode;
+  int            StrainMode;
+  int            WarpMode;
+
+  // Description:
+  // Generate Output
+  void Execute();
+  
+  // Description:
+  // Get Color Value for Scalars
+  void LookupColorMode(float t[3],float val,int mode);
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxShapeTracking.cpp b/bioimagesuite30_src/Legacy/vtkpxShapeTracking.cpp
new file mode 100644
index 0000000..33636f9
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxShapeTracking.cpp
@@ -0,0 +1,840 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxShapeTracking.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/04/01 14:18:13 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "pxutil.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkpxShapeTracking.h"
+#include "vtkFloatArray.h"
+#include "vtkpxSurfaceUtil.h"
+#include "pxshapetrackingclass.h"
+#include "vtkpxTriangulatedStackSource.h"
+#include "vtkIterativeClosestPointTransform.h"
+#include "vtkLandmarkTransform.h"
+#include "vtkMath.h"
+#include "vtkpxUtil.h"
+#include "vtkPointLocator.h"
+//------------------------------------------------------------------------------
+vtkpxShapeTracking* vtkpxShapeTracking::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxShapeTracking");
+  if(ret)
+    {
+    return (vtkpxShapeTracking*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxShapeTracking;
+}
+//------------------------------------------------------------------------------
+vtkpxShapeTracking::vtkpxShapeTracking()
+{
+  this->Displacements=vtkFloatArray::New();
+  this->Displacements->SetNumberOfComponents(3);
+  this->Confidences=vtkFloatArray::New();
+  this->Confidences->SetNumberOfComponents(1);
+  this->Flags=vtkIntArray::New();
+  this->Flags->SetNumberOfComponents(3);
+
+  this->Mode=4;
+  this->SearchRadius=0;
+  this->ReferenceSurface=NULL;
+  this->TargetSurface=NULL;
+  this->InterpolateIterations=10;
+  this->InterpolateThreshold=0.1;
+  this->InitialMode=VTK_LANDMARK_AFFINE;
+}
+//------------------------------------------------------------------------------
+vtkpxShapeTracking::~vtkpxShapeTracking()
+{
+  this->Displacements->Delete();
+  this->Confidences->Delete();
+  this->Flags->Delete();
+}
+//------------------------------------------------------------------------------
+float vtkpxShapeTracking::GetDisplacement(int node,int comp)
+{
+  if (this->Displacements==NULL)
+      return 0;
+
+  comp=Irange(comp,0,this->Displacements->GetNumberOfComponents()-1);
+  node=Irange(node,0,this->Displacements->GetNumberOfTuples()-1);
+  return this->Displacements->GetComponent(node,comp);
+}
+//------------------------------------------------------------------------------
+float vtkpxShapeTracking::GetConfidence(int node)
+{
+  if (this->Confidences==NULL)
+      return 0;
+
+  node=Irange(node,0,this->Confidences->GetNumberOfTuples()-1);
+  return this->Confidences->GetComponent(node,0);
+}
+//------------------------------------------------------------------------------
+void vtkpxShapeTracking::Execute()
+{
+  if (this->ReferenceSurface==NULL || this->TargetSurface==NULL)
+    {
+      vtkErrorMacro(<< "Bad Inputs\n");
+      return;
+    }
+
+  vtkPolyData* output=this->GetOutput();
+  output->DeepCopy(this->ReferenceSurface);
+
+  vtkPolyData* tmp=vtkPolyData::New();
+
+
+  switch (this->Mode)
+    {
+    case 1:
+      this->ComputeSymmetricNearestNeighbor(this->ReferenceSurface,this->TargetSurface,
+					    this->Displacements,this->Flags);
+      break;
+    case 2:
+      this->ComputeAffineMatch(this->ReferenceSurface,this->TargetSurface,this->Displacements);
+      tmp->DeepCopy(this->ReferenceSurface);
+      vtkpxSurfaceUtil::ShiftPointsByDisplacements(tmp,this->Displacements,1.0);
+      this->ComputeNearestNeighbor(tmp,this->TargetSurface,this->Displacements,this->Flags);
+      vtkpxSurfaceUtil::AddToDisplacements(this->ReferenceSurface,tmp,this->Displacements);
+      break;
+    case 3:
+      this->ComputeAffineMatch(this->ReferenceSurface,this->TargetSurface,this->Displacements);
+      tmp->DeepCopy(this->ReferenceSurface);
+      vtkpxSurfaceUtil::ShiftPointsByDisplacements(tmp,this->Displacements,1.0);
+      this->ComputeSymmetricNearestNeighbor(tmp,this->TargetSurface,this->Displacements,this->Flags);
+      vtkpxSurfaceUtil::AddToDisplacements(this->ReferenceSurface,tmp,this->Displacements);
+      break;
+
+    default:
+      this->ComputeNearestNeighbor(this->ReferenceSurface,this->TargetSurface,
+				   this->Displacements,this->Flags);
+      break;
+
+    }
+
+  this->Confidences->SetNumberOfTuples(this->Displacements->GetNumberOfTuples());
+  this->Confidences->FillComponent(0,1.0);
+
+  if (this->SearchRadius>1)
+    this->DoCurvatureTracking(this->ReferenceSurface,this->TargetSurface,
+			      this->Displacements,this->Flags,this->Confidences);
+
+  vtkpxSurfaceUtil::ShiftPointsByDisplacements(output,this->Displacements,1.0);
+  tmp->Delete();
+
+}
+//------------------------------------------------------------------------------
+int vtkpxShapeTracking::Save(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout==NULL)
+    return 0;
+
+  fprintf(fout,"#PXShapeTrackingClass numstacks,hasdisplacements,numpoints\n");
+  fprintf(fout,"0\n1\n%d\n",this->Displacements->GetNumberOfTuples());
+  fprintf(fout,"#-----------------Displacements-------------------------\n");
+  for (int i=0;i<this->Displacements->GetNumberOfTuples();i++)
+    fprintf(fout,"%6.3f %6.3f %6.3f %5.3f %.0f %.0f %.0f\n",
+	     this->Displacements->GetComponent(i,0),
+	     this->Displacements->GetComponent(i,1),
+	     this->Displacements->GetComponent(i,2),
+	     this->Confidences->GetComponent(i,0),
+	     this->Flags->GetComponent(i,0),
+	     this->Flags->GetComponent(i,1),
+	     this->Flags->GetComponent(i,2));
+      
+  fclose(fout);
+  return 1;
+}
+// --------------------------------------------------------------------------
+int vtkpxShapeTracking::Load(const char* fname)
+{
+  gzFile fin=gzsuffixopen(fname,"r");
+  if (!fin)
+    return 0;
+
+  char line[200];
+  gzgets(fin,line,200);
+  if (gzfindstringinstring(line,"#PXShapeTrackingClass")==0)
+    return 0;
+  
+  gzgets(fin,line,200);
+  gzgets(fin,line,200);
+  int num=0;
+  gzgets(fin,line,200);  sscanf(line,"%d",&num);
+
+  this->Displacements->SetNumberOfComponents(3);
+  this->Displacements->SetNumberOfTuples(num);
+  this->Confidences->SetNumberOfComponents(1);
+  this->Confidences->SetNumberOfTuples(num);
+  this->Flags->SetNumberOfComponents(3);
+  this->Flags->SetNumberOfTuples(num);
+  gzgets(fin,line,200);
+  for (int ia=0;ia<num;ia++)
+    {
+      gzgets(fin,line,200);
+      float x[3],c,f[3];
+      sscanf(line,"%f %f %f %f %f %f %f",&x[0],&x[1],&x[2],&c,&f[0],&f[1],&f[2]);
+      this->Displacements->SetTuple(ia,&x[0]);
+      this->Confidences->SetComponent(ia,0,c);
+      this->Flags->SetTuple(ia,&f[0]);
+    }
+  gzclose(fin);
+  return 1;
+}
+//------------------------------------------------------------------------------
+// Using Old Code
+//------------------------------------------------------------------------------
+
+void vtkpxShapeTracking::OldStyleShapeTracking(vtkpxTriangulatedStackSource* st1,
+					       vtkpxTriangulatedStackSource* st2,
+					       int searchwindow,
+					       vtkFloatArray *displacements,
+					       const char* fname)
+{
+  if (displacements!=NULL)
+    vtkpxShapeTracking::OldStyleShapeTracking(st1,st2,displacements,searchwindow);
+  else if (fname!=NULL)
+    vtkpxShapeTracking::OldStyleShapeTracking(st1,st2,fname,searchwindow);
+}
+//------------------------------------------------------------------------------
+void vtkpxShapeTracking::OldStyleShapeTracking(vtkpxTriangulatedStackSource* st1,
+					       vtkpxTriangulatedStackSource* st2,
+					       vtkFloatArray *displ,
+					       int searchwindow)
+{
+  PXShapeTrackingClass* shapeTr=new PXShapeTrackingClass(st1->GetTStack(),
+							 st2->GetTStack());
+  shapeTr->findSmoothMap(1,5,5,1);
+  if (searchwindow>0)
+    shapeTr->initialCurvatureTracking(searchwindow);
+  
+  int n=st1->GetTStack()->getnumpoints();
+  
+  displ->SetNumberOfComponents(3);
+  displ->SetNumberOfTuples(n);
+  
+  for (int i=0;i<n;i++)
+    {
+      PX3Vector* vec=shapeTr->getdisplacement(i);
+      displ->SetTuple(i,vec->x);
+    }
+  
+  delete shapeTr;
+}
+//------------------------------------------------------------------------------
+int vtkpxShapeTracking::OldStyleShapeTracking(vtkpxTriangulatedStackSource* st1,
+					      vtkpxTriangulatedStackSource* st2,
+					      const char *filename,
+					      int searchwindow,int subdivide)
+{
+
+
+
+  PXShapeTrackingClass* shapeTr=new PXShapeTrackingClass(st1->GetTStack(),
+							 st2->GetTStack());
+  shapeTr->findSmoothMap(1,5,5,subdivide);
+  if (searchwindow>0)
+    shapeTr->initialCurvatureTracking(searchwindow);
+  int ok=shapeTr->Save(filename,1);
+  delete shapeTr;
+  return ok;
+}
+
+int vtkpxShapeTracking::OldStyleShapeTracking(const char* name1,const char* name2,
+					       char *outfilename,
+					       int searchwindow,
+					       int subdivide)
+{
+
+  PXShapeTrackingClass* shapeTr=new PXShapeTrackingClass(name1,name2);
+  shapeTr->findSmoothMap(1,5,5,subdivide);
+  if (searchwindow>0)
+    shapeTr->initialCurvatureTracking(searchwindow);
+  int ok=shapeTr->Save(outfilename,1);
+  delete shapeTr;
+  return ok;
+}
+//------------------------------------------------------------------------------
+//
+//
+//                 New Implementations of Old Code
+//
+//
+//------------------------------------------------------------------------------
+void vtkpxShapeTracking::InitializeFlags(vtkPolyData* poly,vtkIntArray* flags)
+{
+  int num=poly->GetNumberOfPoints();
+  flags->SetNumberOfComponents(3);
+  flags->SetNumberOfTuples(num);
+  flags->FillComponent(0,0);
+  flags->FillComponent(1,0);
+  flags->FillComponent(2,-1);
+}
+//------------------------------------------------------------------------------
+void vtkpxShapeTracking::ComputeNearestNeighbor(vtkPolyData* ref,vtkPolyData* targ,
+						vtkFloatArray* displ,vtkIntArray* flags)
+{
+  vtkpxSurfaceUtil::ZeroAllDisplacements(ref,displ);
+  this->InitializeFlags(ref,flags);
+
+  vtkPointLocator* locator=vtkPointLocator::New();
+  locator->SetDataSet(targ);
+  locator->BuildLocator();
+
+  vtkPoints* points=ref->GetPoints();
+  vtkPoints* points2=targ->GetPoints();
+  int nump=points->GetNumberOfPoints();
+  fprintf(stderr,"Tuples=%d (%d) Comp=%d\n",displ->GetNumberOfTuples(),nump,displ->GetNumberOfComponents());
+
+  for (int ia=0;ia<nump;ia++)
+    {
+      double x[3],tx[3];
+      points->GetPoint(ia,x);
+      int id=locator->FindClosestPoint(x);
+      points2->GetPoint(id,tx);
+      for (int ib=0;ib<=2;ib++)
+	displ->SetComponent(ia,ib,tx[ib]-x[ib]);
+      flags->SetComponent(ia,0,0);
+      flags->SetComponent(ia,1,1);
+      flags->SetComponent(ia,2,id);
+      
+      if (ia<5)
+	fprintf(stderr,"x=%.1f,%.1f,%.1f tx=%.1f,%.1f,%.1f  d=%.3f %.3f %.3f\n",
+		x[0],x[1],x[2],tx[0],tx[1],tx[2],
+		displ->GetComponent(ia,0),
+		displ->GetComponent(ia,1),
+		displ->GetComponent(ia,2));
+    }
+  
+  locator->Delete();
+}
+//------------------------------------------------------------------------------
+void vtkpxShapeTracking::ComputeSymmetricNearestNeighbor(vtkPolyData* ref,vtkPolyData* targ,
+							 vtkFloatArray* displ,
+							 vtkIntArray* flags)
+
+
+{
+  vtkpxSurfaceUtil::ZeroAllDisplacements(ref,displ);
+  this->InitializeFlags(ref,flags);
+
+  vtkPoints* points=ref->GetPoints();
+  vtkPoints* points2=targ->GetPoints();
+
+  vtkPointLocator* locator=vtkPointLocator::New();
+  locator->SetDataSet(targ);
+  locator->BuildLocator();
+
+  vtkPointLocator* locator2=vtkPointLocator::New();
+  locator2->SetDataSet(ref);
+  locator2->BuildLocator();
+  
+  int nump=points->GetNumberOfPoints();
+
+  int numgood=0;
+
+  for (int ia=0;ia<nump;ia++)
+    {
+      double x[3],tx[3],x2[3];
+      points->GetPoint(ia,x);
+
+      int id1=locator->FindClosestPoint(x);
+      points2->GetPoint(id1,tx);
+      int id2=locator2->FindClosestPoint(tx);
+      points->GetPoint(id2,x2);
+      
+      if (id2==ia)
+	{
+	  flags->SetComponent(ia,0,1);
+	  flags->SetComponent(ia,1,1);
+	  flags->SetComponent(ia,2,id1);
+	  for (int ib=0;ib<=2;ib++)
+	    displ->SetComponent(ia,ib,tx[ib]-x[ib]);
+	  ++numgood;
+	}
+    }
+
+  
+  fprintf(stderr,"Done with initial symmetric neighbor numpoints=%d\n",numgood);
+
+  vtkpxShapeTracking::InterpolateSymmetricNearestNeighbor(ref,targ,displ,
+							  flags,locator,
+							  this->InterpolateIterations,
+							  this->InterpolateThreshold);
+
+  locator->Delete();
+  locator2->Delete();
+}
+
+//------------------------------------------------------------------------------
+void vtkpxShapeTracking::ComputeAffineMatch(vtkPolyData* ref,vtkPolyData* targ,vtkFloatArray* displ)
+{
+  vtkpxSurfaceUtil::ZeroAllDisplacements(ref,displ);
+  
+  vtkIterativeClosestPointTransform* icp=vtkIterativeClosestPointTransform::New();
+  icp->SetSource(ref);
+  icp->SetTarget(targ);
+  icp->GetLandmarkTransform()->SetMode(this->InitialMode);
+  icp->SetMaximumNumberOfLandmarks(200);
+  if (this->Debug)
+    icp->DebugOn();
+  icp->Update();
+
+  vtkPoints* points=ref->GetPoints();
+  int nump=points->GetNumberOfPoints();
+
+  for (int ia=0;ia<nump;ia++)
+    {
+      double x[3],tx[3];
+      points->GetPoint(ia,x);
+      icp->TransformPoint(x,tx);
+      for (int ib=0;ib<=2;ib++)
+	displ->SetComponent(ia,ib,tx[ib]-x[ib]);
+    }
+
+  icp->Delete();
+}
+//------------------------------------------------------------------------------
+int   vtkpxShapeTracking::SmoothSpreadDisplacements(PXIntegerList* neighbors,
+						    vtkFloatArray* displ,vtkFloatArray* olddisp,
+						    vtkIntArray* flags,int movefixed)
+{
+  int good=0;
+  for (int pt=0;pt<displ->GetNumberOfTuples();pt++)
+    {
+      // If Point is not fixed or movefixed==1
+      int fixed=(int)flags->GetComponent(pt,0);
+      int hasdispl=(int)flags->GetComponent(pt,1);
+
+      if ( fixed==0 || movefixed>0)
+	{
+	  neighbors[pt].Rewind();
+	  int numgood=0;
+	  double newx[3];
+	  for (int ia=0;ia<=2;ia++)
+	    newx[ia]=0.0;
+	  for (int n=0;n<neighbors[pt].getnumnodes();n++)
+	    {
+	      int ind=neighbors[pt].getcurrent();
+	      
+	      if (flags->GetComponent(ind,1)==1)
+		{
+		  ++numgood;
+		  for (int ia=0;ia<=2;ia++)
+		    newx[ia]+=olddisp->GetComponent(ind,ia);
+		}
+	      neighbors[pt].Next();
+	    }
+	  
+	  if (numgood>0)
+	    {
+	      int ia;
+	      for (ia=0;ia<=2;ia++)
+		newx[ia]=newx[ia]/float(numgood);
+	      float factor=0.75;
+	      if (flags->GetComponent(pt,1)<0.01)
+		factor=1.0;
+	      for (ia=0;ia<=2;ia++)
+		displ->SetComponent(pt,ia,(1.0-factor)*olddisp->GetComponent(pt,ia)+factor*newx[ia]);
+
+	      if (hasdispl==0)
+		flags->SetComponent(pt,1,1.0);
+	      ++good;
+	      //fprintf(stderr,"pt = %d ... hasdispl=%d numneighbors=%d\n",pt,hasdispl,numgood);
+	    }
+	  else if ( hasdispl==1)
+	    {
+	      //fprintf(stderr,"pt = %d ... hasdispl=%d numneighbors=%d\n",pt,hasdispl,numgood);
+	      ++good;
+	    }
+	  else
+	    {
+	      fprintf(stderr,"pt= %d hasdispl=%d numneighbors=%d B A D \n\t",pt,hasdispl,
+		      neighbors[pt].getnumnodes());
+	      neighbors[pt].Rewind();
+	      for (int n=0;n<neighbors[pt].getnumnodes();n++)
+		{
+		  int ind=neighbors[pt].getcurrent();
+		  int gd=(int)flags->GetComponent(ind,1);
+		  fprintf(stderr,"pt=%d(%d) ",ind,gd);
+		  neighbors[pt].Next();
+		}
+	      fprintf(stderr,"\n");
+	    }
+	}
+      else if (movefixed==0 && fixed==1)
+	{
+	  //fprintf(stderr,"pt = %d ... fixed\n",pt);
+	  ++good;
+	}
+    }
+
+  return good;
+}
+//------------------------------------------------------------------------------
+float vtkpxShapeTracking::MapDisplacements(vtkPoints* refpoints,vtkPoints* targpoints,
+					   vtkFloatArray* displ,vtkFloatArray* olddisp,
+					   vtkIntArray* flags,
+					   vtkPointLocator* locator)
+{
+  float dist=0.0,maxshift=0.0,maxdist=0.0;
+  int good=0;
+  for (int pt=0;pt<refpoints->GetNumberOfPoints();pt++)
+    {
+      if (this->Debug)
+	{
+	  if (100*int(pt/100)==pt && pt>0)
+	    fprintf(stderr,"%d/%d ",pt,refpoints->GetNumberOfPoints());
+	  if (600*int(pt/600)==pt && pt>0)
+	    fprintf(stderr,"\n");
+	}
+
+      if (flags->GetComponent(pt,1)>0)
+	{
+	  ++good;
+	  double x[3];  refpoints->GetPoint(pt,x);
+	  double x2[3];
+	  for (int ib=0;ib<=2;ib++)
+	    x2[ib]=x[ib]+displ->GetComponent(pt,ib);
+	  int id=locator->FindClosestPoint(x2);
+	  double y[3]; targpoints->GetPoint(id,y);
+	  float d=sqrt(vtkMath::Distance2BetweenPoints(x,y));
+	  dist+=d;
+	  maxdist=Fmax(maxdist,d);
+	  flags->SetComponent(pt,2,id);
+	  for (int ia=0;ia<=2;ia++)
+	    displ->SetComponent(pt,ia,y[ia]-x[ia]);
+	  
+	  maxshift=Fmax(maxshift,vtkMath::Distance2BetweenPoints(olddisp->GetTuple(pt),displ->GetTuple(pt)));
+	}
+    }
+     
+  if (this->Debug)
+    fprintf(stderr,"\t\taverage mapping distance %6.3f (max=%6.3f) maxshift=%6.3f good=%d\n",
+	    dist/float(good),maxdist,sqrt(maxshift),good);
+  
+  return sqrt(maxshift);
+}
+
+//------------------------------------------------------------------------------
+void vtkpxShapeTracking::InterpolateSymmetricNearestNeighbor(vtkPolyData* ref,
+							     vtkPolyData* targ,
+							     vtkFloatArray* displ,
+							     vtkIntArray* flags,
+							     vtkPointLocator* loc,
+							     int iterations,
+							     float threshold)
+{
+  // old fixed[pt] == flags component 0
+  // old used[pt]  == flags component 1
+  // old correspondence[pt] = flags component 2
+
+  PXIntegerList* neighbors=vtkpxSurfaceUtil::GenerateNeighbors(ref,0);
+
+  /*  for (int pt=0;pt<ref->GetNumberOfPoints();pt++)
+    {
+      int num=neighbors[pt].getnumnodes();
+      fprintf(stderr,"pt=%d num=%d\t",pt,num);
+      neighbors[pt].Rewind();
+      for (int n=0;n<num;n++)
+	{
+	  int ind=neighbors[pt].getcurrent();
+	  int gd=(int)flags->GetComponent(ind,1);
+	  fprintf(stderr,"%d (%d) ",ind,gd);
+	  neighbors[pt].Next();
+	}
+      fprintf(stderr,"\n");
+    }
+    exit(1);*/
+
+  iterations=Irange(iterations,1,20)+50;
+
+  int movefixed=0;
+
+  vtkFloatArray* olddisp=vtkFloatArray::New();
+  olddisp->SetNumberOfComponents(3);
+  olddisp->SetNumberOfTuples(displ->GetNumberOfTuples());
+  vtkPoints* refpoints=ref->GetPoints();
+  vtkPoints* targpoints=targ->GetPoints();
+
+  vtkPolyData* tmpSurface=vtkPolyData::New();
+
+
+  int good=0;
+  for(int pt=0;pt<refpoints->GetNumberOfPoints();pt++)
+    good+=(int)flags->GetComponent(pt,1);
+  if (good==refpoints->GetNumberOfPoints())
+    movefixed=1;
+        
+  for (int iter=1;iter<=iterations;iter++)
+    {
+
+      // Smooth Step
+      // -----------
+      if (this->Debug)
+	{
+	  fprintf(stderr,"----------------------\n Smoothing iteration %d/%d in_good=%d\n",iter,iterations,good);
+	  fprintf(stderr,"\t1. Averaging step (moving fixed=%d)\n",movefixed);
+	}
+      olddisp->DeepCopy(displ);
+      int good=vtkpxShapeTracking::SmoothSpreadDisplacements(neighbors,displ,olddisp,flags,movefixed);
+      if ( good==refpoints->GetNumberOfPoints())
+	movefixed=1;
+      
+      // Map Step
+      // --------
+      if (this->Debug)
+	{
+	  fprintf(stderr,"\t\t (%d/%d) points have displacements\n",good,refpoints->GetNumberOfPoints());
+	  fprintf(stderr,"\t2. Mapping step\n");
+	}
+  
+      float maxshift=vtkpxShapeTracking::MapDisplacements(refpoints,targpoints,displ,olddisp,flags,loc);
+    
+      if (movefixed>0)
+	{
+	  if (this->Debug)
+	    fprintf(stderr,"\n Over Smoothing:\n");
+	  tmpSurface->DeepCopy(ref);
+	  vtkpxSurfaceUtil::ShiftPointsByDisplacements(tmpSurface,displ,1.0);
+	  vtkpxSurfaceUtil::NonShrinkSmooth(tmpSurface,neighbors,0.16,-0.165,10,1);
+	  vtkpxSurfaceUtil::ZeroAllDisplacements(ref,displ);
+	  vtkpxSurfaceUtil::AddToDisplacements(ref,tmpSurface,displ);
+	  
+	  if (maxshift<threshold)
+	    iter=iterations+1;
+	}
+    }
+
+  olddisp->Delete();
+  tmpSurface->Delete();
+  delete [] neighbors;
+}
+//------------------------------------------------------------------------------
+int vtkpxShapeTracking::DoCurvatureTracking(vtkPolyData* ref,vtkPolyData* targ,
+					    vtkFloatArray* Displacements,
+					    vtkIntArray* Correspondences,
+					    vtkFloatArray* Confidences)
+{
+  int searchwindow=Irange(this->SearchRadius,0,20);
+  if (this->Debug)
+      fprintf(stderr,"\n Initial Curvature Matching Step (window=%d)\n",searchwindow);
+
+  int numpoints=Displacements->GetNumberOfTuples();
+
+  PXIntegerList* neighbors=vtkpxSurfaceUtil::GenerateNeighbors(targ,1);
+  PXIntegerList* searchPoints=new PXIntegerList();
+  double min1=100000.0,min2=100000.0;
+  int nptot=0;
+
+  // conf=new PX3Vector[numpoints];
+  double* minMatchDist=new double[numpoints];
+  double* aveMatchDist=new double[numpoints];
+  double* sigMatchDist=new double[numpoints];
+  double* extraFactor =new double[numpoints];
+
+  vtkPoints* refpoints=ref->GetPoints();
+  vtkPoints* targpoints=targ->GetPoints();
+  
+  vtkDataArray* refcurvatures=ref->GetPointData()->GetScalars();
+  vtkDataArray* targcurvatures=targ->GetPointData()->GetScalars();
+
+  // Find Initial Match 
+  int pt1=0,pt2=0;
+
+  double point2_k[3],point1_k[2],point1_x[3],point2_x[3];
+
+
+  for (pt1=0;pt1<numpoints;pt1++)
+    {
+      refpoints->GetPoint(pt1,point1_x);
+      refcurvatures->GetTuple(pt1,point1_k);
+      pt2=(int)Correspondences->GetComponent(pt1,2);
+      
+      int np2=vtkpxSurfaceUtil::CollectNeighbours(targ,pt2,searchwindow,searchPoints,&neighbors[0]);
+      nptot+=np2;
+      int bestpt2=pt2;
+      searchPoints->Rewind();
+      
+      double minebe=100000.0,sumebe=0.0,sum2ebe=0.0;
+      for (pt2=0;pt2<np2;pt2++)
+	{
+	  int cur=searchPoints->getcurrent();
+	  targcurvatures->GetTuple(cur,point1_k);
+	  double ebe=0.0;
+	  
+	  for (int ia=0;ia<=1;ia++)
+	    ebe+=pow(point2_k[ia]-point1_k[ia],2.0);
+	  
+	  ebe*=0.5;
+
+	  if (ebe<minebe)
+	    {
+	      minebe=ebe;
+	      bestpt2=searchPoints->getcurrent();
+	    }
+	    			
+	    sumebe+=ebe;
+	    sum2ebe+=pow(ebe,2.0);
+	    searchPoints->Next();
+	  }
+	
+      targpoints->GetPoint(bestpt2,point2_x);
+      
+      // This is the actual displacement estimate
+      for (int ia=0;ia<=2;ia++)
+	Displacements->SetComponent(pt1,ia,point2_x[ia]-point1_x[ia]);
+      
+      // Store min difference, mean difference and sigma for confidence estimation 
+      if (np2>1)
+	{
+	  sumebe=(sumebe-minebe)/double(np2-1);
+	  sum2ebe=(sum2ebe-minebe*minebe)/double(np2-1);
+	  minMatchDist[pt1]=minebe;
+	  aveMatchDist[pt1]=sumebe;
+	  sigMatchDist[pt1]=(sum2ebe-pow(aveMatchDist[pt1],2.0));
+	  double bend=pow(point1_k[0],2.0)+pow(point1_k[1],2.0);
+	  if (bend<0.001)
+	    bend=0.0001;
+	  extraFactor[pt1]=sqrt(bend);// *double(np2);
+	}
+      else
+	{
+	  // In this unlikely case let it blow up to large values low confidence 
+	  fprintf(stderr,"*np2=0*pt=%d\n",pt1);
+	  minMatchDist[pt1]=10000.1;
+	  aveMatchDist[pt1]=10000.0;
+	  sigMatchDist[pt1]=10000.0;
+	  extraFactor[pt1]=0.01;
+	}
+      
+      
+      // This is needed for scaling
+      min1=Fmin(min1,minMatchDist[pt1]);
+      min2=Fmin(min2,minMatchDist[pt1]/(Fmax(aveMatchDist[pt1]-sigMatchDist[pt1],0.00001)));
+      
+      if (this->Debug)
+	{
+	  if (100*int(pt1/100)==pt1)
+	    {
+	      fprintf(stderr,"%d/%d (np=%d,min=%10.8f ave=%10.8f sig=%10.8f)\n",
+		      pt1,ref->GetNumberOfPoints(),np2,
+		      minMatchDist[pt1],aveMatchDist[pt1],sigMatchDist[pt1]);
+	      fprintf(stderr,"\t\t minebe=%f, sumebe=%f sum2ebe=%f\n",
+		      minebe,sumebe,sum2ebe);
+	      fprintf(stderr," pt1=%d k1=%7.5f k2=%7.5f \t pt2=%d k1=%7.5f k2=%7.5f\n",
+		      pt1,point1_k[0],point1_k[1],bestpt2,point2_k[0],point2_k[1]);
+	    }
+	}
+    }
+  
+  double K1 = 0.01 / Fmax(min1,0.0001);
+  double K2 = 0.01 / Fmax(min2,0.0001);
+  
+  float maxconf=0.0;
+  for(pt1=0; pt1<ref->GetNumberOfPoints(); pt1++)
+    {
+      double mg=minMatchDist[pt1];
+      double mu=minMatchDist[pt1]/Fmax(aveMatchDist[pt1]-sigMatchDist[pt1],0.00001);
+      Confidences->SetComponent(pt1,0,/*extraFactor[pt1]*/(1.0 / (  ( 1.0+ K1*mg)*(1.0+K2*mu))));
+      maxconf=Fmax(maxconf,Confidences->GetComponent(pt1,0));
+    }
+  
+  float sumconf=0.0;
+  for (pt1=0;pt1<ref->GetNumberOfPoints();pt1++)
+    {
+      Confidences->SetComponent(pt1,0,Confidences->GetComponent(pt1,0)/maxconf);
+      sumconf+=Confidences->GetComponent(pt1,0);;
+    }
+  sumconf/=(float(ref->GetNumberOfPoints()));
+  // Do Gamma-like correction so that mean becomes 0.5
+  float gamma=log(0.5)/log(sumconf);
+  
+  if (this->Debug)
+    fprintf(stderr,"Done with confidence values\n\t mean=%6.4f gamma=%6.4f \n",sumconf,gamma);
+  
+  sumconf=0.0; 
+  float sum2conf=0.0;
+  
+  for (pt1=0;pt1<ref->GetNumberOfPoints();pt1++)
+    {
+      float c=pow(Confidences->GetComponent(pt1,0),double(gamma));
+      Confidences->SetComponent(pt1,0,c);
+      sumconf+=c;
+      sum2conf+=pow(c,float(2.0));
+    }
+  sumconf/=(float(ref->GetNumberOfPoints()));
+  sum2conf/=(float(ref->GetNumberOfPoints())); 
+  if (this->Debug)
+    {
+      fprintf(stderr,"Done with adjusting confidence values\n\t mean=%6.4f std=%6.4f\n",
+	      sumconf,sqrt(sum2conf-sumconf*sumconf));
+      fprintf(stderr,"Total points compared =%d ave=%6.2f\n",nptot,
+	      float(nptot)/float(ref->GetNumberOfPoints()));
+    }
+  
+  delete searchPoints;
+  delete [] neighbors;
+  delete [] minMatchDist;
+  delete [] aveMatchDist;
+  delete [] sigMatchDist;
+  delete [] extraFactor;
+  return 1;
+}
+//------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxShapeTracking.h b/bioimagesuite30_src/Legacy/vtkpxShapeTracking.h
new file mode 100644
index 0000000..e2cf6a9
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxShapeTracking.h
@@ -0,0 +1,222 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxShapeTracking.h,v $
+  Language:  C++
+  Date:      $Date: 2002/04/01 14:18:00 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxShapeTracking 
+
+
+#ifndef __vtkpxShapeTracking_h
+#define __vtkpxShapeTracking_h
+
+#include "vtkPolyDataSource.h"
+#include "pxgeometrystruct.h"
+#include "vtkLandmarkTransform.h"
+#include "vtkPolyData.h"
+
+class vtkPointLocator;
+class vtkFloatArray;
+class vtkIntArray;
+class vtkpxTriangulatedStackSource;
+
+class vtkpxShapeTracking : public vtkPolyDataSource
+{
+public:
+  static vtkpxShapeTracking *New();
+  vtkTypeMacro(vtkpxShapeTracking,vtkPolyDataSource);
+
+  //Description:
+  // Input Surfaces Reference and Target
+  vtkSetObjectMacro(ReferenceSurface,vtkPolyData);
+  vtkGetObjectMacro(ReferenceSurface,vtkPolyData);
+  vtkSetObjectMacro(TargetSurface,vtkPolyData);
+  vtkGetObjectMacro(TargetSurface,vtkPolyData);
+
+  //Description:
+  // I/O Code -- save as .disp file 
+  virtual int Load(const char* fname);
+  virtual int Save(const char* fname);
+
+  //Description:
+  // Mode for the transformation
+  vtkSetClampMacro(Mode,int,0,3);
+  vtkGetMacro(Mode,int);
+  virtual void SetModeToNearestNeighbor()     { this->SetMode(0);}
+  virtual void SetModeToSymmetricNeighbor()   { this->SetMode(1);}
+  virtual void SetModeToAffinePlusNN()        { this->SetMode(2);}
+  virtual void SetModeToAffinePlusSNN()       { this->SetMode(3);}
+
+  // Description:
+  // Set Mode for Affine Initialization
+  vtkSetMacro(InitialMode,int);
+  void SetInitialModeToRigidBody() { this->SetInitialMode(VTK_LANDMARK_RIGIDBODY); };
+  void SetInitialModeToSimilarity() { this->SetInitialMode(VTK_LANDMARK_SIMILARITY); };
+  void SetInitialModeToAffine() { this->SetInitialMode(VTK_LANDMARK_AFFINE); };
+  vtkGetMacro(InitialMode,int);
+
+  
+  // Description:
+  // Window Size for Shape Match
+  vtkSetClampMacro(SearchRadius,int,0,3);
+  vtkGetMacro(SearchRadius,int);
+
+  // Description:
+  // Number of Iterations for Symmetric Nearest Neighbor Interpolation
+  vtkSetClampMacro(InterpolateIterations,int,2,50);
+  vtkGetMacro(InterpolateIterations,int);
+
+  // Description:
+  // Threshold for Symmetric Nearest Neighbor Interpolation Convergence
+  vtkSetClampMacro(InterpolateThreshold,float,0,3);
+  vtkGetMacro(InterpolateThreshold,float);
+
+
+  // Description:
+  // Access Fem Data
+  virtual float GetDisplacement(int node,int comp);
+  virtual float GetConfidence(int node);
+
+  // Description:
+  // Get Displacements as Scalars
+  vtkGetObjectMacro(Displacements,vtkFloatArray);
+
+  // Description:
+  // Old Style Shape Tracking
+  static void OldStyleShapeTracking(vtkpxTriangulatedStackSource* st1,
+			     vtkpxTriangulatedStackSource* st2,
+			     int searchwindow,
+			     vtkFloatArray *displacements,
+			     const char* fname);
+
+
+  static void OldStyleShapeTracking(vtkpxTriangulatedStackSource* st1,
+			     vtkpxTriangulatedStackSource* st2,
+			     vtkFloatArray *displ,
+			     int searchwindow=3);
+
+  static int OldStyleShapeTracking(vtkpxTriangulatedStackSource* st1,
+				   vtkpxTriangulatedStackSource* st2,
+				   const char *filename,
+				   int searchwindow=3,
+				   int subdivide=1);
+
+
+  static int OldStyleShapeTracking(const char* name1,const char* name2,
+				   char *outfilename,
+				   int searchwindow=3,
+				   int subdivide=1);
+
+
+
+protected:
+
+  vtkpxShapeTracking();
+  virtual ~vtkpxShapeTracking();
+  vtkpxShapeTracking(const vtkpxShapeTracking&) {};
+  void operator=(const vtkpxShapeTracking&) {};
+  
+  vtkFloatArray* Displacements;
+  vtkFloatArray* Confidences;
+  vtkIntArray*   Flags;
+  vtkPolyData*   ReferenceSurface;
+  vtkPolyData*   TargetSurface;
+    
+  int            Mode;
+  int            InitialMode;
+  int            SearchRadius;
+  int            InterpolateIterations;
+  float          InterpolateThreshold;
+
+  // Description:
+  // Generate Output
+  void Execute();
+
+  // Description:
+  // Actual Shape Tracking Routine 
+  int DoCurvatureTracking(vtkPolyData* ref,vtkPolyData* targ,
+			  vtkFloatArray* displ,vtkIntArray* flags,vtkFloatArray* Confidences);
+
+  // --------------------------------------------------
+  // Surface Matching Stuff
+  // --------------------------------------------------
+  void InitializeFlags(vtkPolyData* poly,vtkIntArray* flags);
+  void ComputeNearestNeighbor(vtkPolyData* ref,vtkPolyData* targ,vtkFloatArray* displ,vtkIntArray* flags);
+  void ComputeSymmetricNearestNeighbor(vtkPolyData* ref,vtkPolyData* targ,vtkFloatArray* displ,vtkIntArray* flags);
+  void ComputeAffineMatch(vtkPolyData* ref,vtkPolyData* targ,vtkFloatArray* displ);
+
+
+  // ------------------------------------------------
+  // Interpolate SymmetricNearestNeighbor Stuff
+  // ------------------------------------------------
+
+  int   SmoothSpreadDisplacements(PXIntegerList* neighbors,
+				  vtkFloatArray* displ,vtkFloatArray* olddisp,
+				  vtkIntArray* flags,
+				  int movefixed);
+
+  float MapDisplacements(vtkPoints* refpoints,vtkPoints* targpoints,
+			 vtkFloatArray* displ,vtkFloatArray* olddisp,
+			 vtkIntArray* flags,
+			 vtkPointLocator* locator);
+
+  void InterpolateSymmetricNearestNeighbor(vtkPolyData* ref,vtkPolyData* targ,vtkFloatArray* displ,
+					   vtkIntArray* flags,vtkPointLocator* loc,
+					   int iterations=5,float threshold=0.1);
+  
+  
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxSplineSource.cpp b/bioimagesuite30_src/Legacy/vtkpxSplineSource.cpp
new file mode 100644
index 0000000..86a5cbf
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxSplineSource.cpp
@@ -0,0 +1,971 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSurfaceUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "pxutil.h"
+#include "pxfpbspline.h"
+#include "pxcontour.h"
+#include "pxchamferdistancemap.h"
+#include "vtkCellArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkpxBaseCurve.h"
+#include "vtkpxSplineSource.h"
+#include "vtkTransform.h"
+#include "vtkImageData.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageGradientMagnitude.h"
+#include "vtkpxImageExtract.h"
+#include "vtkProbeFilter.h"
+#include "vtkDoubleArray.h"
+//------------------------------------------------------------------------------
+vtkpxSplineSource* vtkpxSplineSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxSplineSource");
+  if(ret)
+    {
+    return (vtkpxSplineSource*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxSplineSource;
+}
+
+//------------------------------------------------------------------------------
+vtkpxSplineSource::vtkpxSplineSource()
+{
+  this->Spline=new PXFPBSpline();
+  this->Spline->setellipse(6,1,1,0,0,3);
+  this->Resolution=1.0;
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->ImageOrigin[ia]=0.0;
+      this->ImageSpacing[ia]=0.0;
+    }
+
+  // SNAKE Stuff
+  this->SNAKE_img=3.0;
+  this->SNAKE_smooth=0.5;
+  this->SNAKE_step=0.5;
+  this->SNAKE_baloon=0.0; 
+  this->SNAKE_niterations=20;
+  this->SNAKE_imagemax=1.0;
+
+  this->EdgeImage=NULL;
+  this->Optimizer=NULL;
+  this->Position=NULL;
+}
+//------------------------------------------------------------------------------
+vtkpxSplineSource::~vtkpxSplineSource()
+{
+  if (this->Spline)
+      delete this->Spline;
+
+  if (this->EdgeImage!=NULL)
+    this->EdgeImage->Delete();
+
+  if (this->Optimizer!=NULL)
+    this->Optimizer->Delete();
+
+  if (this->Position!=NULL)
+    this->Position->Delete();
+
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::Save(const char* fname)
+{
+  if (this->Spline==NULL)
+      return 0;
+  return this->Spline->Save(fname);
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::Load(const char* fname)
+{
+  if (this->Spline==NULL)
+      this->Spline=new PXFPBSpline();
+  this->Modified();
+  return this->Spline->Load(fname);
+
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineSource::SetEllipse(int np,
+				   float radiusx,float radiusy,
+				   float x,float y,float z,int dim)
+{
+  if (this->Spline==NULL)
+      this->Spline=new PXFPBSpline(3,2,z,1);
+
+  this->Spline->setellipse(np,radiusx,radiusy,x,y,dim);
+  this->Spline->setzlevel(z);
+  this->Modified();
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineSource::Copy(vtkpxSplineSource* other)
+{
+  this->Spline->copypoints(other->GetSpline());
+  this->SetResolution(other->GetResolution());
+  this->SetImageSpacing(other->GetImageSpacing());
+  this->SetImageOrigin(other->GetImageOrigin());
+  this->Modified();
+}
+//------------------------------------------------------------------------------
+int   vtkpxSplineSource::GetNumPoints()
+{
+  return this->Spline->getnumpoints();
+}
+//------------------------------------------------------------------------------
+float vtkpxSplineSource::GetZlevel()
+{
+  return this->Spline->getzlevel();
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineSource::SetZlevel(float lev)
+{
+  this->Spline->setzlevel(lev);
+  this->Modified();
+}
+//------------------------------------------------------------------------------
+PXFPBSpline* vtkpxSplineSource::GetSpline()
+{
+  return this->Spline;
+}
+//------------------------------------------------------------------------------
+// Contour, vtkPoints Interfaces
+PXContour* vtkpxSplineSource::ExportToContour()
+{
+  return this->Spline->exporttocontour(this->Resolution);
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::FitToContour(PXContour* cntr,float smooth,float csmooth,
+			   int numpoints,int closed,int iterations)
+{
+  int ok=this->Spline->fittocontour(cntr,smooth,csmooth,numpoints,
+				    closed,iterations);
+  this->Modified();
+  return ok;
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::ExportToPoints(vtkPoints* points)
+{
+  if (points==NULL)
+      return -1;
+
+  float length=this->Spline->getlength(0.0,1.0,0.05);
+  int np=int(length/(0.5*this->Resolution)+0.5);
+  float res=1.0/float(np);
+  points->SetNumberOfPoints(np);
+
+  for (int i=0;i<np;i++)
+    {
+      real  x,y,z;
+      this->Spline->getposition(float(i*res),x,y,z);
+      points->SetPoint(i,float(x),float(y),float(z));
+    }
+  return np;
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::ExportKnotPointsToPoints(vtkPoints* points)
+{
+  if (points==NULL)
+      return -1;
+
+  int np=this->Spline->getnumpoints();
+  points->SetNumberOfPoints(np);
+
+  real xp,yp,zp;
+  for (int ib=0;ib<this->Spline->getnumpoints();ib++)
+    {
+      this->Spline->getposition(this->Spline->getcknot(ib),xp,yp,zp);
+      points->SetPoint(ib,xp,yp,zp);
+    }
+  return np;
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::ExportToBaseCurve(vtkpxBaseCurve* baseCurve)
+{
+  if (baseCurve==NULL)
+    return 0;
+  baseCurve->DeleteAllPoints();
+
+  int np=this->Spline->getnumpoints();
+  (baseCurve->GetPoints())->SetNumberOfPoints(np+10);
+  real xp,yp,zp;
+  for (int ib=0;ib<this->Spline->getnumpoints();ib++)
+    {
+      this->Spline->getposition(this->Spline->getcknot(ib),xp,yp,zp);
+      baseCurve->AddPoint(xp,yp,zp,0);
+    }
+  return np;
+  
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::SetFromBaseCurve(vtkpxBaseCurve* baseCurve)
+{
+  if (baseCurve==NULL)
+    return 0;
+  if (baseCurve->GetNumPoints()<4)
+    return 0;
+  return this->SetControlPoints(baseCurve->GetPoints(),baseCurve->GetNumPoints());
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::InsertKnot(float x,float y)
+{
+  float s=this->Spline->getlength(0.0,1.0,0.05);
+  float n=float(this->GetNumPoints());
+  float d=s/(3.0*n);
+
+  return this->InsertKnot(x,y,d);
+}
+
+int vtkpxSplineSource::InsertKnot(float x,float y,float mindist)
+{
+  real xn=x,yn=y;
+  //  real md=mindist;
+
+
+  this->Spline->insertknot(xn,yn,mindist);
+  return 1;
+}
+
+
+int vtkpxSplineSource::SetControlPoints(vtkPoints* points,int np)
+{
+  if (points==NULL)
+      return 0;
+
+  if (np==-1)
+      np=points->GetNumberOfPoints();
+  
+  vtkDebugMacro(<<"Setting Control Points np="<<np<<", dimensions="<<this->Spline->getdimension());
+
+  real* xp=new real[np];
+  real* yp=new real[np];
+  real* zp=NULL;
+
+  if (this->Spline->getdimension()==3)
+      zp=new real[np];
+
+  for (int i=0;i<np;i++)
+      {
+	double x[3];
+	points->GetPoint(i,x);
+	xp[i]=x[0];
+	yp[i]=x[1];
+	if (this->Spline->getdimension()==3)
+	    zp[i]=x[2];
+      }
+
+  if (this->Spline->getdimension()==3)
+      {
+	this->Spline->ResetPoints(np,xp,yp,zp);
+      }
+  else
+      {
+	this->Spline->ResetPoints(np,xp,yp);
+      }
+
+  if (zp!=NULL)
+    delete [] zp;
+
+  delete [] xp;
+  delete [] yp;
+
+  this->Modified();
+  return 1;
+}
+//------------------------------------------------------------------------------
+  // Modify 
+int vtkpxSplineSource::Resample(float ds_step,int npoints)
+{
+  int ok=this->Spline->resample(ds_step,npoints);
+  this->Modified();
+  return ok;
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::ChangeSpacing(float smooth,int npoints,
+				     float step,float csmooth,int iterations)
+{
+  int ok=this->Spline->changespacing(smooth,npoints,step,csmooth,iterations);
+  this->Modified();
+  return ok;
+
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::FitPoints(vtkPoints* points,float smooth,int numpoints,
+				 int closed,int iterations)
+{
+  if (points==NULL)
+      return 0;
+
+  PXContour* cntr=new PXContour();
+  for (int i=0;i<points->GetNumberOfPoints();i++)
+      {
+	double x[3];
+	points->GetPoint(i,x);
+	cntr->Add(x[0],x[1]);
+      }
+  int ok=this->FitToContour(cntr,smooth,0.5,numpoints,closed,iterations);
+
+  delete cntr;
+  return ok;
+}
+//------------------------------------------------------------------------------
+
+int vtkpxSplineSource::Transform(vtkTransform* transform)
+{
+  if (transform==NULL)
+      return 0;
+
+  float p[3],q[3];
+  for(int i=0;i<this->Spline->getnumpoints();i++)
+    {
+      p[0]=this->Spline->getcontrolx(i);
+      p[1]=this->Spline->getcontroly(i);
+      p[2]=this->Spline->getcontrolz(i);
+      
+      transform->TransformPoint(p,q);
+      if (this->Spline->getdimension()==2)
+	q[2]=p[2];
+      /*fprintf(stderr,"Point %d (%.1f,%.1f,%.1f) --> (%.1f,%.1f,%.1f)\n",
+	i,p[0],p[1],p[2],q[0],q[1],q[2]);*/
+      this->Spline->setcontrol(i,q[0],q[1],q[2]);
+    }
+  this->Modified();
+  //fprintf(stderr,"\n");
+  return 1;
+}
+//------------------------------------------------------------------------------
+
+void vtkpxSplineSource::Execute()
+{
+
+  if (this->Spline==NULL)
+      {
+	vtkErrorMacro(<<"No spline available");
+	return;
+      }
+
+  float length=this->Spline->getlength(0.0,1.0,0.05);
+  int np=int(length/(0.5*this->Resolution)+0.5);
+  float res=1.0/float(np);
+
+  int   closed=0;
+
+  if (this->Spline->isclosed()>0)
+      closed=1;
+
+  vtkPoints    *c_points    = vtkPoints::New();
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  
+  c_points->SetNumberOfPoints(np);
+  c_lines->Allocate(np-1+closed,5);
+
+
+  for (int i=0;i<np;i++)
+      {
+	real  x,y,z;
+	this->Spline->getposition(float(i*res),x,y,z);
+	c_points->SetPoint(i,float(x),float(y),float(z));
+	vtkIdType pt[2];
+
+	if (i<np-1 && np>1)
+	    {
+	      pt[0]=i;
+	      pt[1]=i+1;
+	      c_lines->InsertNextCell(2,pt);
+	    }
+	if (i==np-1 && closed==1)
+	    {
+	      pt[0]=i;
+	      pt[1]=0;
+	      c_lines->InsertNextCell(2,pt);
+	    }
+      }
+
+  vtkPolyData* curve = this->GetOutput();
+  curve->SetPoints(c_points);
+  c_points->Delete();
+  curve->SetLines(c_lines);
+  c_lines->Delete();
+}
+
+//------------------------------------------------------------------------------
+float vtkpxSplineSource::GetArea()
+{
+  PXContour* cntr=this->ExportToContour();
+  float area=cntr->getarea();
+  delete cntr;
+  return area;
+}
+
+//------------------------------------------------------------------------------
+float vtkpxSplineSource::GetVOIArea(vtkImageData* image,int level,int frame,float threshold)
+{
+  float area=1.0,mean=0.0,std=0.0;
+  this->GetVOIProperties(image,level,frame,area,mean,std,threshold);
+  return area;
+}
+//------------------------------------------------------------------------------
+int  vtkpxSplineSource::GetVOIProperties(vtkImageData* image,int level,int frame,
+					  float& area,float& mean,float& std,float threshold)
+{
+  
+  PXContour* cntr=this->ExportToContour();
+  
+  int dim[3];
+  image->GetDimensions(dim);
+  level=Irange(level,0,dim[2]-1);
+
+  double sp[3],ori[3];
+  image->GetSpacing(sp);
+  image->GetOrigin(ori);
+
+  int numpixels=0;
+  float sum=0.0,sum2=0.0;
+
+  for (int i=0;i<dim[0];i++)
+    for (int j=0;j<dim[1];j++)
+      {
+	float v=image->GetScalarComponentAsDouble(i,j,level,frame);
+	float x[2];
+	x[0]=float(i)*sp[0]+ori[0];
+	x[1]=float(j)*sp[1]+ori[1];
+	if ( (v>=threshold) && ( cntr->IsInside(x[0],x[1]) > 0 ))
+	  {
+	    ++numpixels;
+	    sum+=v;
+	    sum2+=v*v;
+	  }
+      }
+	
+  
+  mean=sum/float(numpixels);
+  std= sqrt( sum2/float(numpixels)-mean*mean);
+  area=float(numpixels)*sp[0]*sp[1];
+
+  /*fprintf(stderr,"Sum=%.1f sum2=%.1f numpixels=%d np2=%d (sp=%.1f,%.1f,%.1f) mean=%.1f, std=%.1f, area=%.1f\n",
+    sum,sum2,numpixels,np2,sp[0],sp[1],sp[2],mean,std,area);*/
+
+  delete cntr;
+  return numpixels;
+
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::GetDualVOIProperties(vtkImageData* image,int level,int frame,
+					    float area[2],float mean[2],float std[2],int numpixels[2],
+					    float threshold[2])
+{
+  PXContour* cntr=this->ExportToContour();
+  
+  int dim[3];
+  image->GetDimensions(dim);
+  level=Irange(level,0,dim[2]-1);
+
+  double sp[3],ori[3];
+  image->GetSpacing(sp);
+  image->GetOrigin(ori);
+
+  numpixels[0]=0; numpixels[1]=0;
+  int total=0;
+  float sum[2],sum2[2];
+  
+  sum[0]=0.0; sum[1]=0.0; sum2[0]=0.0; sum2[1]=0.0;
+
+  for (int i=0;i<dim[0];i++)
+    for (int j=0;j<dim[1];j++)
+      {
+	float v=image->GetScalarComponentAsDouble(i,j,level,frame);
+	float x[2];
+	x[0]=float(i)*sp[0]+ori[0];
+	x[1]=float(j)*sp[1]+ori[1];
+	if (cntr->IsInside(x[0],x[1]) > 0)
+	  {
+	    ++total;
+	    for (int r=0;r<=1;r++)
+	      {
+		if (v>threshold[r])
+		  {
+		    ++numpixels[r];
+		    sum[r]+=v;
+		    sum2[r]+=v*v;
+		  }
+	      }
+	  }
+      }
+	
+  for (int r=0;r<=1;r++)
+    {
+      mean[r]=sum[r]/float(numpixels[r]+0.00001);
+      std[r]= sqrt( sum2[r]/float(numpixels[r]+0.00001)-mean[r]*mean[r]);
+      area[r]=float(numpixels[r])*sp[0]*sp[1];
+    }
+
+  delete cntr;
+  return total;
+
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::ThresholdAddToObjectMap(vtkImageData* objectmap,vtkImageData* img,
+					       int level,int imagelevel,
+					       float value,int thresholdmode,float min,float max)
+{
+  if (objectmap==NULL)
+    return -1;
+  
+  double sp[3],ori[3];
+  int dim[3];
+  objectmap->GetDimensions(dim);
+  objectmap->GetSpacing(sp);
+  objectmap->GetOrigin(ori);
+  
+  int numvoxels=0;
+  level=Irange(level,0,dim[2]-1);
+  int offset=dim[0]*dim[1]*level;
+  
+  vtkDataArray* objectmapScalars=objectmap->GetPointData()->GetScalars();
+  int numscalars=objectmapScalars->GetNumberOfTuples();
+
+  PXContour* cntr=this->Spline->exporttocontour(0.05);
+  
+  float x1,x2,y1,y2;
+  cntr->getextent(x1,x2,y1,y2);
+  int imin=Irange( int((x1/sp[0])-ori[0]-2.0),0,dim[0]-2);
+  int imax=Irange( int((x2/sp[0])-ori[0]+2.0),imin+1,dim[0]-1);
+
+  int jmin=Irange( int((y1/sp[1])-ori[1]-2.0),0,dim[1]-2);
+  int jmax=Irange( int((y2/sp[1])-ori[1]+2.0),jmin+1,dim[1]-1);
+
+  for (int i=imin;i<=imax;i++)
+    for (int j=jmin;j<=jmax;j++)
+      {
+	float x[2];
+	x[0]=float(i)*sp[0]+ori[0];
+	x[1]=float(j)*sp[1]+ori[1];
+	
+	if ( cntr->IsInside(x[0],x[1]) > 0 )
+	  {
+	    ++numvoxels;
+	    int index=Irange(offset+j*dim[0]+i,0,numscalars-1);
+
+	    int doadd=0;
+	    if (thresholdmode==1)
+	      {
+		float v=img->GetScalarComponentAsDouble(i,j,imagelevel,0);
+		if (v>=min && v<=max)
+		  doadd=1;
+	      }
+
+	    if (thresholdmode==0 || doadd==1)
+	      objectmapScalars->SetComponent(index,0,value);
+
+	  }
+      }
+  delete cntr;
+  return numvoxels;
+}
+
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::AddToObjectMap(vtkImageData* objectmap,int level,float value,int add)
+{
+  if (objectmap==NULL)
+    return -1;
+  
+  double sp[3],ori[3];
+  int dim[3];
+  objectmap->GetDimensions(dim);
+  objectmap->GetSpacing(sp);
+  objectmap->GetOrigin(ori);
+  
+  int numvoxels=0;
+  level=Irange(level,0,dim[2]-1);
+  int offset=dim[0]*dim[1]*level;
+  
+  vtkDataArray* objectmapScalars=objectmap->GetPointData()->GetScalars();
+  int numscalars=objectmapScalars->GetNumberOfTuples();
+
+  PXContour* cntr=this->Spline->exporttocontour(0.05);
+  
+  float x1,x2,y1,y2;
+  cntr->getextent(x1,x2,y1,y2);
+  int imin=Irange( int((x1/sp[0])-ori[0]-2.0),0,dim[0]-2);
+  int imax=Irange( int((x2/sp[0])-ori[0]+2.0),imin+1,dim[0]-1);
+
+  int jmin=Irange( int((y1/sp[1])-ori[1]-2.0),0,dim[1]-2);
+  int jmax=Irange( int((y2/sp[1])-ori[1]+2.0),jmin+1,dim[1]-1);
+
+  /*  fprintf(stderr,"Ranges = %.1f:%.1f %.1f:%.1f --> vox (%d:%d %d:%d)\n",
+      x1,y1,x2,y2,imin,jmin,imax,jmax);*/
+
+  
+
+  for (int i=imin;i<=imax;i++)
+    for (int j=jmin;j<=jmax;j++)
+      {
+	float x[2];
+	x[0]=float(i)*sp[0]+ori[0];
+	x[1]=float(j)*sp[1]+ori[1];
+
+	if ( cntr->IsInside(x[0],x[1]) > 0 )
+	  {
+	    ++numvoxels;
+	    int index=Irange(offset+j*dim[0]+i,0,numscalars-1);
+	    if (add)
+	      objectmapScalars->SetComponent(index,0,value+objectmapScalars->GetComponent(index,0));
+	    else
+	      objectmapScalars->SetComponent(index,0,value);
+	  }
+      }
+  delete cntr;
+  return numvoxels;
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineSource::AddToDistanceMap(vtkImageData* distancemap,int level)
+{
+  if (distancemap==NULL)
+    return -1;
+  
+  double sp[3],ori[3];
+  int dim[3];
+  distancemap->GetDimensions(dim);
+  distancemap->GetSpacing(sp);
+  distancemap->GetOrigin(ori);
+  
+  //  int numvoxels=0;
+  level=Irange(level,0,dim[2]-1);
+  int offset=dim[0]*dim[1]*level;
+
+  PXChamferDistanceMap::pixel_size=short(sp[0]*100.0);
+  PXChamferDistanceMap::obj_gray=10000;
+  PXChamferDistanceMap::out_gray=-10000;
+  
+  // Export To Contour and Scale in Voxel Units
+  PXContour* cntr=this->Spline->exporttocontour(0.05);
+  PXContourPoint* pts=cntr->gettoppoint();
+  int np=cntr->getnumpoints();
+  for (int ib=1;ib<=np;ib++)
+    {
+      pts->x=(pts->x-ori[0])/sp[0];
+      pts->y=(pts->y-ori[1])/sp[1];
+      pts=pts->next;
+    }
+  
+  PXChamferDistanceMap* map=new PXChamferDistanceMap(cntr,1);
+  vtkDataArray* distances=distancemap->GetPointData()->GetScalars();
+
+  for (int j=0;j<dim[1];j++)
+    for (int i=0;i<dim[0];i++)
+      {
+	float v=(float(map->getvalue(i,j)));
+	int index=offset+j*dim[0]+i;
+	distances->SetComponent(index,0,v);
+      }
+  delete map;
+  delete cntr;
+  return 1;
+}
+//------------------------------------------------------------------------------
+int   vtkpxSplineSource::HasSnake()
+{
+  if (this->EdgeImage==NULL)
+    return 0;
+  return 1;
+}
+//-------------------------------------------------------------------------
+double vtkpxSplineSource::CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output)
+{
+  return ((vtkpxSplineSource*)self)->OptimizerGradient(position,output);
+}
+
+double vtkpxSplineSource::CalculateFunction(vtkObject* self,vtkDoubleArray* position)
+{
+  return ((vtkpxSplineSource*)self)->OptimizerValue(position);
+}
+
+void vtkpxSplineSource::OptimizerFeedback(vtkObject* self,const char* line,double val)
+{
+  fprintf(stderr,"Current Snake = %s \t %f\n",line,val);
+}
+//-------------------------------------------------------------------------
+void vtkpxSplineSource::SetCurrentParameters(vtkDoubleArray* par)
+{
+  int np=Spline->getnumpoints();
+  int nt=np*2;
+  if (par->GetNumberOfTuples()!=nt)
+    {
+      vtkErrorMacro(<<"Bad Parameter Array\n");
+      return;
+    }
+
+  for(int i=0;i<np;i++)
+    this->Spline->setClosedControl(i,par->GetComponent(i*2,0),par->GetComponent(i*2+1,0));
+  this->Modified();
+}
+
+void vtkpxSplineSource::GetCurrentParameters(vtkDoubleArray* par)
+{
+  int np=Spline->getnumpoints();
+  int nt=np*2;
+  if (par->GetNumberOfTuples()!=nt)
+    par->SetNumberOfTuples(nt);
+
+  for(int i=0;i<np;i++)
+    {
+      par->SetComponent(i*2,0,this->Spline->getcontrolx(i));
+      par->SetComponent(i*2+1,0,this->Spline->getcontroly(i));
+    }
+}
+
+double vtkpxSplineSource::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+{
+  if (grad->GetNumberOfTuples()!=params->GetNumberOfTuples())
+    grad->SetNumberOfTuples(params->GetNumberOfTuples());
+
+  int nt=params->GetNumberOfTuples();
+
+  double GradientNorm=0.0;
+
+  for (int dof=0;dof<nt;dof++)
+    {
+      double orig=params->GetComponent(dof,0);
+      params->SetComponent(dof,0,orig+this->SNAKE_step);
+      double a=this->OptimizerValue(params);
+      params->SetComponent(dof,0,orig-this->SNAKE_step);
+      double b=this->OptimizerValue(params);
+      params->SetComponent(dof,0,orig);
+      double g=-0.5*(b-a)/this->SNAKE_step;
+      grad->SetComponent(dof,0,g);
+      GradientNorm+=pow(g,2.0);
+    }
+  GradientNorm = (sqrt(GradientNorm));
+
+  for (int j=0;j<nt;j++)
+    grad->SetComponent(j,0,grad->GetComponent(j,0)/GradientNorm);
+
+  return GradientNorm;
+}
+ 
+double vtkpxSplineSource::OptimizerValue(vtkDoubleArray* params)
+{
+
+  this->SetCurrentParameters(params);
+
+  if (this->EdgeImage==NULL)
+    return 0.0;
+
+  float spa=this->EdgeImage->GetSpacing()[0];
+  float length=this->Spline->getlength(0.0,1.0,0.05);
+  int np=int(length/(0.5*spa+0.5));
+  float res=1.0/float(np);
+	     
+  vtkPoints* points=vtkPoints::New();
+  points->SetNumberOfPoints(np);
+  
+  for (int i=0;i<np;i++)
+    {
+      real  x,y,z;
+      this->Spline->getposition(float(i*res),x,y,z);
+      points->SetPoint(i,float(x),float(y),0.0);
+    }
+
+  double bend=0.0;
+
+  for (int i=0;i<np;i++)
+    {
+      int ip=i-1; if (ip<0)    ip=np-1;
+      int in=i+1; if (in>np-1) in=0;
+      
+      double x[3],x2[3],x0[3];
+      points->GetPoint(i,x);
+      points->GetPoint(ip,x0);
+      points->GetPoint(in,x2);
+      bend+=pow(x2[0]+x0[0]-2.0*x[0],2.0)+pow(x2[1]+x0[1]-2.0*x[1],2.0);
+    }
+
+  vtkPolyData* poly=vtkPolyData::New();
+  poly->SetPoints(points);
+
+  vtkProbeFilter* probe=vtkProbeFilter::New();
+  probe->SetInput(poly);
+  probe->SetSource(this->EdgeImage);
+  probe->Update();
+  
+  vtkDataArray* data=probe->GetOutput()->GetPointData()->GetScalars();
+      
+  int   np2=data->GetNumberOfTuples();
+  double sum=0.0;
+  for (int i=0;i<np2;i++)
+    {
+      double v=data->GetComponent(i,0);
+      sum+=v*v;
+    }
+  sum/=double(np2*this->SNAKE_imagemax*this->SNAKE_imagemax);
+  bend/=double(np2);
+
+  probe->Delete();
+  poly->Delete();
+  points->Delete();
+
+  if (this->Debug)
+    fprintf(stderr,"\n OptimizerValue:\t\t img=%.2f Smooth=%.2f\n",
+	    -SNAKE_img*sum,SNAKE_smooth*bend);
+
+  return -SNAKE_img*sum+SNAKE_smooth*bend;
+}
+//------------------------------------------------------------------------------
+
+float vtkpxSplineSource::UpdateSnake(float img_weight,float smooth_weight)
+{
+  // If snake not created simply return 0.0
+  // --------------------------------------
+  if (this->Position==NULL)
+    return 0.0;
+  // --------------------------------------
+
+  if (img_weight>=0.0)
+    this->SNAKE_img=img_weight;
+  
+  if (smooth_weight>=0.0)
+    this->SNAKE_smooth=smooth_weight;
+
+  this->GetCurrentParameters(this->Position);
+
+  this->DebugOn();
+  this->OptimizerValue(this->Position);
+  this->DebugOff();
+  fprintf(stderr,"\n\n Updating Snake (%.2f)\n\n",this->SNAKE_imagemax);
+  
+
+  if (this->Optimizer!=NULL)
+    return this->Optimizer->ComputeConjugateGradient(this->Position,SNAKE_niterations,SNAKE_step);
+
+    
+  this->DebugOn();
+  this->OptimizerValue(this->Position);
+  fprintf(stderr,"\n\n Updating Snake Done\n\n");
+  this->DebugOff();
+
+  return 0.0;
+}
+//------------------------------------------------------------------------------
+
+void vtkpxSplineSource::CreateSnake(vtkImageData* image,int level,int frame,
+				    float img_coeff,float smooth_coeff,
+				    float timestep,float sigma,int niter)
+{
+  if (image==NULL)
+      return;
+
+  this->SNAKE_niterations=niter;
+  this->SNAKE_step=timestep;
+  this->SNAKE_smooth=smooth_coeff;
+  this->SNAKE_img=img_coeff;
+
+  
+  vtkpxImageExtract* extr=vtkpxImageExtract::New();
+  extr->SetInput(image);
+  extr->SetSliceNo(level);
+  extr->SetFrame(frame);
+  extr->SetCurrentPlane(2);
+  extr->Update();
+  
+  vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+  smooth->SetInput(extr->GetOutput());
+  smooth->SetDimensionality(2);
+  smooth->SetStandardDeviations(sigma,sigma,0.0);
+
+  vtkImageGradientMagnitude* magn=vtkImageGradientMagnitude::New();
+  magn->SetInput(smooth->GetOutput());
+  magn->HandleBoundariesOn();
+  magn->SetDimensionality(2);
+  magn->Update();
+
+  if (this->EdgeImage==NULL)
+    this->EdgeImage=vtkImageData::New();
+
+  this->EdgeImage->ShallowCopy(magn->GetOutput());
+  this->SNAKE_imagemax=this->EdgeImage->GetPointData()->GetScalars()->GetRange()[1];
+
+  magn->Delete();
+  smooth->Delete();
+  extr->Delete();
+
+  this->EdgeImage->SetSpacing(1.0,1.0,1.0);
+  this->EdgeImage->SetOrigin(0.0,0.0,0.0);
+      
+  int np=this->Spline->getnumpoints()*2;
+
+  if (this->Optimizer!=NULL)
+    {
+      this->Optimizer->Delete();
+      this->Position->Delete();
+    }
+
+  this->Optimizer=vtkpxOptimizer::New();
+  this->Position=vtkDoubleArray::New();
+
+  this->GetCurrentParameters(this->Position);
+  this->Optimizer->SetMasterObject(this);
+  this->Optimizer->SetEvaluateFunctionMethod(&vtkpxSplineSource::CalculateFunction);
+  this->Optimizer->SetEvaluateGradientMethod(&vtkpxSplineSource::CalculateGradient);
+  this->Optimizer->SetFeedbackMethod(&vtkpxSplineSource::OptimizerFeedback);
+  this->Optimizer->ComputeConjugateGradient(this->Position,niter,timestep);
+
+    
+}
+//------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxSplineSource.h b/bioimagesuite30_src/Legacy/vtkpxSplineSource.h
new file mode 100644
index 0000000..f992a96
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxSplineSource.h
@@ -0,0 +1,254 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSurfaceUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+// .NAME vtkpxSplineSource - BSpline parameterized curve 
+// .SECTION Description
+// vtkSplineSource is a source object that creates loads and saves b-spline curves
+// .SECTION Caveats
+// Binary files written on one system may not be readable on other systems.
+
+#ifndef __vtkpxSplineSource_h
+#define __vtkpxSplineSource_h
+
+#include "vtkPolyDataSource.h"
+#include "vtkpxOptimizer.h"
+#include "pxutil.h"
+
+class vtkImageData;
+class vtkTransform;
+class vtkPoints;
+class vtkpxBaseCurve;
+
+//BTX
+class PXFPBSpline;
+class PXContour;
+//ETX
+
+class vtkpxSplineSource : public vtkPolyDataSource
+{
+
+public:
+  static vtkpxSplineSource *New();
+  vtkTypeMacro(vtkpxSplineSource,vtkPolyDataSource);
+
+  // Description:
+  // Initialization -- Set as Ellipse and Copy Other 
+  virtual void SetEllipse(int np,float radiusx=10.0,float radiusy=5.0,
+			  float x=50.0,float y=50.0,float z=0.0,int dim=2);
+  virtual void Copy(vtkpxSplineSource* other);
+  
+  // Description:
+  // Input/Output to standard .spl format 
+  virtual int  Load(const char* fname);
+  virtual int  Save(const char* fname);
+  
+  // Description:
+  // Display Parameter 
+  vtkGetMacro(Resolution,float);
+  vtkSetMacro(Resolution,float);
+
+  // Description:
+  // Information regarding spline 
+  virtual int   GetNumPoints();
+  virtual int   HasSnake();
+
+  // Description:
+  // Zlevel is constant z-coordinate or slice level 
+  virtual float GetZlevel();
+  virtual void  SetZlevel(float lev);
+
+  // Description:
+  // Interface to vtkPoints 
+  virtual int ExportToPoints(vtkPoints* points);
+  virtual int ExportKnotPointsToPoints(vtkPoints* points);
+
+  virtual int FitPoints(vtkPoints* points,float smooth,int numpoints,
+			int closed,int iterations);
+  virtual int FitPoints(vtkPoints* points,float smooth=2.0,int numpoints=-1)
+      { return FitPoints(points,smooth,numpoints,1,100); }
+
+  virtual int SetControlPoints(vtkPoints* points,int np);
+  virtual int SetControlPoints(vtkPoints* points)
+      { return SetControlPoints(points,-1);}
+
+
+  // Description:
+  // Interface to vtkpxBaseCurve
+  virtual int ExportToBaseCurve(vtkpxBaseCurve* baseCurve);
+  virtual int SetFromBaseCurve(vtkpxBaseCurve* baseCurve);
+
+  // Description:
+  // Resample and Smooth Spline 
+  virtual int Resample(float ds_step,int npoints);
+  virtual int Resample(int npoints) { return Resample(0.01,npoints);}
+  virtual int Resample(float ds) { return Resample(ds,-1);}
+  virtual int ChangeSpacing(float smooth=0.5,int npoints=-1,
+			    float step=-1.0,float csmooth=0.0,int iterations=50);
+
+  
+  // Description:
+  // Scale factors to scale from voxels (used for snake stuff) to mm 
+  vtkGetVectorMacro(ImageSpacing,double,3);
+  vtkSetVectorMacro(ImageSpacing,double,3);
+
+  // Description:
+  // Shift factor to translate from voxels (used for snake stuff) to mm 
+  vtkGetVectorMacro(ImageOrigin,double,3);
+  vtkSetVectorMacro(ImageOrigin,double,3);
+
+
+  // Description:
+  // Apply Transformation to BSpline
+  virtual int Transform(vtkTransform* Transform);
+
+  // Description:
+  // Snake Stuff -- crude segmentation algorithm
+  virtual void CreateSnake(vtkImageData* image,int level,int frame,
+			   float img_coeff,float smooth_coeff,
+			   float timestep,float sigma,int niter);
+  virtual void CreateSnake(vtkImageData* image,int level,int frame,float img_coeff=5.0,float smooth_coeff=0.5)
+  {	CreateSnake(image,level,frame,img_coeff,smooth_coeff,0.05,1.0,10);}
+
+  virtual float UpdateSnake(float img_coeff,float smooth_coeff);
+  virtual float UpdateSnake() { return UpdateSnake(-1.0,-1.0);}
+
+
+  // Description: 
+  // VOI Stuff area, mean intensity area>0 std of mean intensity 
+  virtual float GetArea();
+  virtual float GetVOIArea(vtkImageData* image,int level,int frame,float threshold=0.1);
+  virtual int   GetVOIProperties(vtkImageData* image,int level,int frame,
+				 float& area,float& mean,float& std,float threshold=0.0);
+  
+  virtual int   GetDualVOIProperties(vtkImageData* image,int level,int frame,
+				     float area[2],float mean[2],float std[2],
+				     int numpixels[2],float threshold[2]);
+  
+
+
+  // Description:
+  virtual int  InsertKnot(float x,float y);
+  virtual int  InsertKnot(float x,float y,float mindist);
+
+  //BTX
+  // Code to Interface to Internal Data Structures 
+  virtual PXFPBSpline* GetSpline();
+
+  // Contour, vtkPoints Interfaces
+  virtual PXContour* ExportToContour();
+  virtual int FitToContour(PXContour* cntr,float smooth=2.0,float csmooth=0.0,
+			   int numpoints=-1,int closed=1,int iterations=100);
+
+  //ETX 
+
+
+  // Description:
+  // Add To Objectmap
+  virtual int  AddToObjectMap(vtkImageData* objectmap,int level=0,float value=1.0,int add=0);		    
+  virtual int  ThresholdAddToObjectMap(vtkImageData* objectmap,vtkImageData*img, int level,int imagelevel,
+				       float value=1.0,int thresholdmode=0,float min=0.0,float max=0.0);
+  virtual int  AddToDistanceMap(vtkImageData* distancemap,int level=0);		    
+
+
+  // Description:
+  // Optimization Stuff
+  static void  OptimizerFeedback(vtkObject* self,const char* line,double val);
+  static double CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output);
+  static double CalculateFunction(vtkObject* self,vtkDoubleArray* position);
+
+
+protected:
+
+  vtkpxSplineSource();
+  virtual ~vtkpxSplineSource();
+  vtkpxSplineSource(const vtkpxSplineSource&) {};
+  void operator=(const vtkpxSplineSource&) {};
+  
+  void Execute();
+  
+  //BTX
+  PXFPBSpline* Spline;
+  float Resolution;
+  //ETX
+
+  double ImageSpacing[3];
+  double ImageOrigin[3];
+
+
+  // Description:
+  // Snake Stuff
+  //BTX
+  float SNAKE_img, SNAKE_step, SNAKE_sigma, SNAKE_baloon,SNAKE_smooth,SNAKE_imagemax;
+  int   SNAKE_niterations;
+  vtkImageData* EdgeImage;
+  vtkpxOptimizer* Optimizer;
+  vtkDoubleArray* Position;
+  //ETX
+
+    // Description:
+  // Needed for Optimizer -- set,get,optimizer,optimizervalue
+  virtual void SetCurrentParameters(vtkDoubleArray* par);
+  virtual void GetCurrentParameters(vtkDoubleArray* par);
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxSplineSourceUndoStack.cpp b/bioimagesuite30_src/Legacy/vtkpxSplineSourceUndoStack.cpp
new file mode 100644
index 0000000..17b42bb
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxSplineSourceUndoStack.cpp
@@ -0,0 +1,60 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSplineSource.h"
+#include "vtkpxSplineSourceUndoStack.h"
+
+vtkpxSplineSourceUndoStack* vtkpxSplineSourceUndoStack::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxSplineSourceUndoStack");
+  if(ret)
+      {
+	return (vtkpxSplineSourceUndoStack*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxSplineSourceUndoStack;
+}
+
+// Construct object with no children.
+// ---------------------------------------------------------------------------------------------
+vtkObject* vtkpxSplineSourceUndoStack::CreateNewElement()
+{
+  vtkpxSplineSource* arr=vtkpxSplineSource::New();
+  return arr;
+}
+// ---------------------------------------------------------------------------------------------
+void vtkpxSplineSourceUndoStack::InitializeElement(int index)
+{
+  vtkpxSplineSource* arr=(vtkpxSplineSource*)this->Elements[index];
+  arr->SetEllipse(8);
+}
+
+// ---------------------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxSplineSourceUndoStack.h b/bioimagesuite30_src/Legacy/vtkpxSplineSourceUndoStack.h
new file mode 100644
index 0000000..a580d6b
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxSplineSourceUndoStack.h
@@ -0,0 +1,62 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkpxSplineSourceStack_h
+#define __vtkpxSplineSourceStack_h
+
+#include "vtkpxGenericUndoStack.h"
+#include "vtkpxSplineSource.h"
+
+
+class vtkpxSplineSourceUndoStack : public vtkpxGenericUndoStack {
+  
+public:
+  static vtkpxSplineSourceUndoStack *New();
+  vtkTypeMacro(vtkpxSplineSourceUndoStack,vtkpxGenericUndoStack);
+
+  // Description:
+  // Insert Stuff
+  virtual vtkpxSplineSource* GetNextSpline()     { return (vtkpxSplineSource*)(this->GetNextObject());}
+  virtual vtkpxSplineSource* GetCurrentSpline()  { return (vtkpxSplineSource*)(this->GetCurrentObject());}
+  virtual vtkpxSplineSource* GetNextUndoSpline() { return (vtkpxSplineSource*)(this->GetNextUndoObject());}
+  virtual vtkpxSplineSource* GetNextRedoSpline() { return (vtkpxSplineSource*)(this->GetNextRedoObject());}
+
+
+  
+protected:
+  // Description:
+  // Stuff Needed
+  virtual vtkObject* CreateNewElement();
+  virtual void InitializeElement(int index);
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxSplineStackSource.cpp b/bioimagesuite30_src/Legacy/vtkpxSplineStackSource.cpp
new file mode 100644
index 0000000..b948f7f
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxSplineStackSource.cpp
@@ -0,0 +1,1903 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSplineStackSource.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/02/03 15:58:09 $
+  Version:   $Revision: 1.3 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "pxutil.h"
+#include "vtkCellArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkpxSplineStackSource.h"
+#include "vtkPolyDataCollection.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkAppendPolyData.h"
+#include "vtkPolyDataNormals.h"
+#include "vtkCollection.h"
+#include "vtkImageData.h"
+#include "pxcontour.h"
+#include "pxchamferdistancemap.h"
+#include "vtkImageThreshold.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkpxBaseCurve.h"
+#include "vtkImageSeedConnectivity.h"
+#include "vtkPolyDataConnectivityFilter.h"
+#include "vtkpxImageExtract.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkContourFilter.h"
+#include "vtkPoints.h"
+#include "vtkpxUtil.h"
+#include "pxfpbsplinestack.h"
+//------------------------------------------------------------------------------
+vtkpxSplineStackSource* vtkpxSplineStackSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxSplineStackSource");
+  if(ret)
+    {
+    return (vtkpxSplineStackSource*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxSplineStackSource;
+}
+//------------------------------------------------------------------------------
+vtkpxSplineStackSource::vtkpxSplineStackSource()
+{
+  this->SplineStack=new PXFPBSplineStack();
+  this->SplineStack->setellipticalcylinder(6,2,10.0,10.0,0.0,0.0,1.0,0.0);
+  this->sliceSurfaceData=NULL;
+  this->wholeSurfaceData=NULL;
+
+  this->ResolutionU=2.0;
+  this->ResolutionV=2.0;
+  this->WholeSurface=0;
+  this->PolarMode=0;
+
+  this->DrawMode=0;
+  this->PolarMiddle=0.0;
+  this->RedrawSurface=1;
+  this->ZDisplayOffset=0.001;
+}
+//------------------------------------------------------------------------------
+vtkpxSplineStackSource::~vtkpxSplineStackSource()
+{
+  if (this->SplineStack)
+      delete this->SplineStack;
+  if (this->sliceSurfaceData)
+    this->sliceSurfaceData->Delete();
+  if (this->wholeSurfaceData)
+    this->wholeSurfaceData->Delete();
+
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::Save(const char* fname)
+{
+  if (this->SplineStack==NULL)
+      return 0;
+  return this->SplineStack->Save(fname);
+}
+
+int vtkpxSplineStackSource::Save(FILE* fout)
+{
+  if (this->SplineStack==NULL)
+      return 0;
+  return this->SplineStack->Save(fout);
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::Load(const char* fname)
+{
+  if (this->SplineStack==NULL)
+      this->SplineStack=new PXFPBSplineStack();
+  int ok=this->SplineStack->Load(fname);
+  if (ok)
+    {
+      this->SplineStack->enableapex(0);
+      this->Modified();
+      this->RedrawSurface=1;
+      this->ResolutionV=this->GetZSpacing();
+    }
+  return ok;
+}
+
+int vtkpxSplineStackSource::Load(gzFile fin)
+{
+  if (this->SplineStack==NULL)
+      this->SplineStack=new PXFPBSplineStack();
+  int ok=this->SplineStack->Load(fin);
+  if (ok)
+    {
+      this->SplineStack->enableapex(0);
+      this->Modified();
+      this->RedrawSurface=1;
+      this->ResolutionV=this->GetZSpacing();
+    }
+  return ok;
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::SetEllipticalCylinder(int np,int numslices,float radiusx,float radiusy,
+						   float x,float y,float zspacing,float bottomz)
+{
+  if (this->SplineStack==NULL)
+      this->SplineStack=new PXFPBSplineStack();
+
+
+  this->SplineStack->setellipticalcylinder(np,numslices,radiusx,radiusy,x,y,zspacing,bottomz);
+  this->Modified();
+  this->RedrawSurface=1;
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::SetLizzardCylinder(int np,int numslices,int bottomtrim,
+					       int lizzardslices,int blendslices,int thinslices,
+					       float minradius,float maxradius,float yscale,
+						float x,float y,float 
+					       zspacing,float bottomz)
+{
+  if (numslices< (lizzardslices+bottomtrim))
+    {
+      vtkErrorMacro(<<"Bad Lizzard Cylinder slices spec total= " << numslices << " lizzard " <<lizzardslices << "trim= " << bottomtrim << "\n");
+      return 0;
+    }
+
+  if (lizzardslices< 2*(blendslices+thinslices))
+    {
+      vtkErrorMacro(<<"Bad Lizzard Cylinder slices spec total= " << lizzardslices << " blend=2x " << blendslices << " min=2x " << thinslices << "\n");
+      return 0;
+    }
+  
+
+  if (this->SplineStack==NULL)
+    this->SplineStack=new PXFPBSplineStack();
+
+ this->SplineStack->setellipticalcylinder(np,numslices,minradius,minradius*yscale,x,y,zspacing,bottomz);
+ this->SetTrimBottom(bottomtrim);
+ this->SetTrimTop(bottomtrim+lizzardslices-1);
+
+
+
+ int lowslice=bottomtrim+thinslices;
+ int highslice=bottomtrim+lizzardslices-thinslices;
+
+ int lowblend=lowslice+blendslices;
+ int highblend=highslice-blendslices;
+
+ fprintf(stderr,"Modifying %d:%d  no-blend %d:%d \n",lowslice,highslice,lowblend,highblend);
+
+ for (int slice=lowslice;slice< highslice;slice++)
+   {
+     float ratio=1.0;
+     if (slice< lowblend)
+       {
+	 ratio=float(slice-lowslice)/float(blendslices);
+       }
+     else if (slice>=highblend)
+       {
+	 ratio=float(highslice-slice)/float(blendslices);
+       }
+
+     float r=(-2.0*pow(ratio,float(3.0))+3.0*pow(ratio,float(2.0)))*(maxradius-minradius)+minradius;
+
+
+     fprintf(stderr,"slice=%d r=%.2f (ratio=%.2f lowblend=%d, highblend=%d minr=%.2f,maxr=%.2f)\n",slice,r,ratio,lowblend,highblend,minradius,maxradius);
+     float z=this->GetSpline(slice)->getzlevel();
+     this->GetSpline(slice)->setellipse(np,r,r*yscale,x,y,2);
+     this->GetSpline(slice)->setzlevel(z);
+   }
+ return 1;
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::Copy(vtkpxSplineStackSource* other,int ignore)
+{
+  this->SplineStack->copypoints(other->GetSplineStack(),ignore);
+  this->SplineStack->enableapex(0);
+  this->Modified();
+  this->RedrawSurface=1;
+}
+//------------------------------------------------------------------------------
+int  vtkpxSplineStackSource::GetTrimBottom()
+{
+  return this->SplineStack->gettrimbottom();
+}
+//------------------------------------------------------------------------------
+int  vtkpxSplineStackSource::GetTrimTop()
+{
+  return this->SplineStack->gettrimtop();
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::SetTrimBottom(int tb)
+{
+  tb=Irange(tb,0,this->SplineStack->gettrimtop());
+  if (tb==this->SplineStack->gettrimbottom())
+    return;
+
+  if (this->WholeSurface==1 || this->sliceSurfaceData==NULL)
+    {
+      this->SplineStack->settrimbottom(tb);
+      this->Modified();
+      this->RedrawSurface=1;
+    }
+  else
+    {
+      if (tb>this->SplineStack->gettrimbottom())
+	{
+	  int tb2=this->SplineStack->gettrimbottom();
+	  this->SplineStack->settrimbottom(tb);
+	  this->Modified();
+	  this->RemoveSections(tb2,tb+1);
+	  this->AddSections(tb,tb+1);
+	}
+      else
+	{
+	  int tb2=this->SplineStack->gettrimbottom();
+	  this->SplineStack->settrimbottom(tb);
+	  this->Modified();
+
+	  this->RemoveSections(tb2,tb2+1);
+	  this->AddSections(tb,tb2+1);
+	}
+      if (this->PolarMode)
+	this->AddSections(this->SplineStack->gettrimtop(),this->SplineStack->gettrimtop()+1);
+      this->Modified();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::SetTrimTop(int tt)
+{
+  tt=Irange(tt,this->SplineStack->gettrimbottom(),this->SplineStack->getnumsplines()-1);
+  if (tt==this->SplineStack->gettrimtop())
+    return;
+
+  if (this->WholeSurface==1 || this->sliceSurfaceData==NULL)
+    {
+      this->SplineStack->settrimtop(tt);
+      this->Modified();
+      this->RedrawSurface=1;
+    }
+  else
+    {
+      if (tt<this->SplineStack->gettrimtop())
+	{
+	  int tt2=this->SplineStack->gettrimtop();
+	  this->SplineStack->settrimtop(tt);
+	  this->Modified();
+	  this->RemoveSections(tt-1,tt2);
+	  this->AddSections(tt-1,tt);
+	}
+      else
+	{
+	  int tt2=this->SplineStack->gettrimtop();
+	  this->SplineStack->settrimtop(tt);
+	  this->Modified();
+	  this->RemoveSections(tt2-1,tt2);
+	  this->AddSections(tt2-1,tt);
+	}
+      
+      if (this->PolarMode)
+	this->AddSections(this->SplineStack->gettrimtop(),this->SplineStack->gettrimtop()+1);
+      this->Modified();
+    }
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::GetNumSplines()
+{
+  return this->SplineStack->getnumsplines();
+}
+//------------------------------------------------------------------------------
+PXFPBSpline* vtkpxSplineStackSource::GetSpline(int i)
+{
+  return this->SplineStack->getspline(i);
+}
+//------------------------------------------------------------------------------
+PXFPBSplineStack* vtkpxSplineStackSource::GetSplineStack()
+{
+  return this->SplineStack;
+}
+//------------------------------------------------------------------------------
+float vtkpxSplineStackSource::GetZSpacing()
+{
+  float a=fabs(this->SplineStack->getspline(this->SplineStack->gettrimbottom()+1)->getzlevel()-
+	       this->SplineStack->getspline(this->SplineStack->gettrimbottom())->getzlevel());
+  if (a<0.01)
+    a=1.0;
+  return a;
+}
+
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::FitToContourStack(PXContourStack* stack,float smooth,float csmooth,
+					      int npoints,int closed)
+{
+  fprintf(stderr,"Fitting to Contour Stack\n\n");
+  int ok=this->SplineStack->fittocontourstack(stack,smooth,csmooth,npoints,closed);
+  fprintf(stderr,"Done Fitting to Contour Stack\n\n");
+  this->Modified();
+  this->RedrawSurface=1;
+  return ok;
+}
+//------------------------------------------------------------------------------
+PXContourStack* vtkpxSplineStackSource::ExportToContourStack(real dist)
+{
+  return this->SplineStack->exporttocontourstack(dist);
+}
+//------------------------------------------------------------------------------
+PXContourStack* vtkpxSplineStackSource::ExportToContourStack(real dist,real zdist)
+{
+  return this->SplineStack->exporttocontourstack(dist,zdist);
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::SetApex(float x,float y,float z)
+{
+  this->SplineStack->setapex(x,y,z);
+  if (this->PolarMode)
+    return;
+
+  if ( this->WholeSurface==1)
+    {
+      this->RedrawSurface=1;
+      this->Modified();
+    }
+  else
+    {
+      AddApex();
+    }
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::GetApex(float &x,float &y,float &z)
+{
+  PX3Vector* vect=this->SplineStack->getapex();
+  x=vect->x[0];
+  y=vect->x[1];
+  z=vect->x[2];
+}
+//------------------------------------------------------------------------------   
+void vtkpxSplineStackSource::EnableApex(int enable)
+{
+  if (this->SplineStack->apexenabled()!=enable)
+    {
+      this->SplineStack->enableapex(enable);
+      if (this->PolarMode)
+	return;
+
+      if ( this->WholeSurface==1)
+	{
+	  this->RedrawSurface=1;
+	  this->Modified();
+	}
+      else
+	{
+	  AddApex();
+	}
+    }
+}
+//------------------------------------------------------------------------------
+int  vtkpxSplineStackSource::ApexEnabled()
+{
+  return this->SplineStack->apexenabled();
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::AutoSetApex(int active)
+{
+  this->SplineStack->autosetapex(active);
+  
+  if (this->PolarMode)
+    return;
+  
+  if ( this->WholeSurface==1)
+    {
+      this->RedrawSurface=1;
+      this->Modified();
+    }
+  else
+    {
+      AddApex();
+    }
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::Resample(float ds_step,int npoints)
+{
+  for (int i=this->GetTrimBottom(); i<=this->GetTrimTop();i++)
+      this->SplineStack->getspline(i)->resample(ds_step,npoints);
+  this->Modified();
+  this->RedrawSurface=1;
+  return 1;
+}
+
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::ChangeSpacing(float smooth,float npoints,
+					  float step,float csmooth,int iterations)
+{
+  for (int i=this->GetTrimBottom(); i<=this->GetTrimTop();i++)
+    {
+      int np=-1;
+      if (npoints!=-1.0)
+	np=int(0.5+float(npoints*this->SplineStack->getspline(i)->getnumpoints())*npoints);
+      this->SplineStack->getspline(i)->changespacing(smooth,np,step,csmooth,iterations);
+    }
+  this->Modified();
+  this->RedrawSurface=1;
+  return 1;
+
+
+}
+
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::SetSpline(vtkpxSplineSource* source,int ind)
+{
+  return this->SetSpline(source->GetSpline(),ind);
+}
+
+int vtkpxSplineStackSource::SetSplineFromSplineStack(vtkpxSplineSource* source,int ind)
+{
+ if (ind>=GetTrimBottom() && ind<=GetTrimTop())
+   {
+     float z=source->GetSpline()->getzlevel();
+     source->GetSpline()->copypoints(this->SplineStack->getspline(ind));
+     source->GetSpline()->setzlevel(z);
+     source->Modified();
+     return ind;
+   }
+ else
+   return -1;
+
+}
+
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::SetSpline(PXFPBSpline* spl,int ind)
+{
+  if (ind>=GetTrimBottom() && ind<=GetTrimTop())
+      {
+	if (spl!=NULL)
+	  {
+	    float z=this->SplineStack->getspline(ind)->getzlevel();
+	    this->SplineStack->getspline(ind)->copypoints(spl);
+	    this->SplineStack->getspline(ind)->setzlevel(z);
+	  }
+
+	if ( this->WholeSurface==1 || this->sliceSurfaceData==NULL)
+	  {
+	    this->RedrawSurface=1;
+	    this->Modified();
+	  }
+	else
+	  {
+	    int bottom=ind-1;
+	    if (bottom<this->SplineStack->gettrimbottom())
+	      bottom=this->SplineStack->gettrimbottom();
+	    int top=ind+1;
+	    if (top>this->SplineStack->gettrimtop())
+	      top=this->SplineStack->gettrimtop();
+
+	    this->AddSections(bottom,top);
+	    if (this->PolarMode && (ind==this->SplineStack->gettrimbottom() || ind==this->SplineStack->gettrimtop()))
+	      this->AddSections(this->SplineStack->gettrimtop(),this->SplineStack->gettrimtop()+1);
+	    this->Modified();
+	  }
+	return ind;
+      }
+  else
+    {
+      fprintf(stderr,"Out out Bounds\n");
+    }
+  return -1;
+}
+
+// -------------------------------------- Display Garbage --------------------------------
+void vtkpxSplineStackSource::CreateSurface()
+{
+  if (this->SplineStack->gettrimbottom() == this->SplineStack->gettrimtop())
+    {
+      this->WholeSurface=1;
+      if (this->RedrawSurface==1 || this->wholeSurfaceData==NULL)
+	{
+	  if (this->wholeSurfaceData==NULL)
+	    this->wholeSurfaceData=vtkPolyData::New();
+
+	  PXContourStack* stack=this->SplineStack->exporttocontourstack(this->ResolutionU);
+	  stack->getcontour(1)->copypoints(stack->getcontour(0));
+	  stack->setzlevel(1,stack->getzlevel(0)+0.1);
+	  stack->setzlevel(0,stack->getzlevel(0)-0.1);
+	  PXTriangulatedStack* ts=new PXTriangulatedStack(stack,0);
+	  vtkpxSurfaceUtil::drawtstack(this->wholeSurfaceData,ts);
+	  delete ts;
+	  delete stack;
+	  this->RedrawSurface=0;
+	}
+      return;
+    }
+
+
+  if (this->WholeSurface)
+      {
+	if (this->RedrawSurface==1 || this->wholeSurfaceData==NULL)
+	  {
+	    vtkDebugMacro(<<"Creating Whole Surface DrawMode =" << this->DrawMode << " Pmode = " << this->PolarMode);
+	    if (this->wholeSurfaceData==NULL)
+	      this->wholeSurfaceData=vtkPolyData::New();
+
+	    PXContourStack* stack;
+	    PXTriangulatedStack* ts;
+	    if (this->PolarMode)
+	      {
+		stack=this->SplineStack->polarexporttocontourstack(this->PolarMiddle,this->ResolutionU);
+		stack->nonShrinkSmooth2D(this->ResolutionU,1.0,50);
+		ts=new PXTriangulatedStack(stack,0);
+	      }
+	    else
+	      {
+		if (this->DrawMode==0 || this->SplineStack->apexenabled() )
+		  {
+		    vtkDebugMacro(<<"In DrawMode == 0 ");
+		    stack=this->SplineStack->exporttocontourstack(this->ResolutionU,this->ResolutionV,1);
+		  }
+		else
+		  {
+		    vtkDebugMacro(<<"In Comples DrawMode ");
+		    PXContourStack* stack2=this->SplineStack->exporttocontourstack(this->ResolutionU,this->ResolutionV,0);
+		    switch (this->DrawMode)
+		      {
+		      case 3:
+			stack=new PXContourStack(stack2,0,0,1,1);
+			break;
+		      case 2:
+			stack=new PXContourStack(stack2,0,0,0,1);
+			break;
+		      default:
+			stack=new PXContourStack(stack2,0,0,1,0);
+			break;
+		      }
+		    delete stack2;
+		  }
+		ts=new PXTriangulatedStack(stack,0);
+	      }
+	    //int num=this->SplineStack->getnumsplines();
+	    vtkpxSurfaceUtil::drawtstack(this->wholeSurfaceData,ts);
+	    delete ts;
+	    delete stack;
+	    this->RedrawSurface=0;
+	  }
+      }
+  else if (this->RedrawSurface==1 || this->sliceSurfaceData==NULL)
+    {
+      vtkDebugMacro(<<"Creating Slice Surface");
+
+      // First Make Sure that wholeSurfaceData has the right dimensions etc
+      int num=this->SplineStack->getnumsplines()-1;
+      if (this->PolarMode)
+	++num;
+      
+      int doadd=0;
+      if (this->sliceSurfaceData==NULL)
+	{
+	  this->sliceSurfaceData=vtkPolyDataCollection::New();
+	  doadd=1;
+	}
+      else if (this->sliceSurfaceData->GetNumberOfItems()!=num)
+	doadd=1;
+      
+      if (doadd==1)
+	{
+	  this->sliceSurfaceData->RemoveAllItems();
+	  for (int i=0;i<num;i++)
+	    {
+	      vtkPolyData* poly=vtkPolyData::New();
+	      this->sliceSurfaceData->AddItem(poly);
+	      poly->Delete();
+	    }
+	  //vtkDebugMacro(<<"Created "<< this->sliceSurfaceData->GetNumberOfItems() << "Sub slices");
+	}
+
+      if (this->PolarMode)
+	this->AddSections(this->SplineStack->gettrimbottom(),this->SplineStack->gettrimtop()+1);
+      else
+	this->AddSections(this->SplineStack->gettrimbottom(),this->SplineStack->gettrimtop());
+      this->RedrawSurface=0;
+    }
+  else
+    vtkDebugMacro(<<"Surface is up to date");
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::AddApex()
+{
+  if (this->PolarMode || !ApexEnabled())
+      return;
+
+  // Do Something Here 
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::AddSections(int lower,int upper)
+{
+  if (lower<0)
+    lower=0;
+  if (upper>=this->SplineStack->getnumsplines())
+    upper=this->SplineStack->getnumsplines();
+
+  for (int splineno=lower;splineno<upper;splineno++)
+    CreateSingleSection(splineno);
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::RemoveSections(int lower,int upper)
+{
+  if (this->sliceSurfaceData==NULL)
+    return;
+
+  if (lower<0)
+    lower=0;
+  if (upper>=this->SplineStack->getnumsplines())
+    upper=this->SplineStack->getnumsplines();
+
+
+  for (int splineno=lower;splineno<upper;splineno++)
+      {
+	vtkPolyData* poly=(vtkPolyData*)this->sliceSurfaceData->GetItemAsObject(splineno);
+	if (poly!=NULL)
+	  poly->Initialize();
+      }
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::CreateSingleSection(int splineno)
+{
+  vtkPolyData* sep=(vtkPolyData*)this->sliceSurfaceData->GetItemAsObject(splineno);
+  if (sep==NULL)
+      return;
+
+  //  vtkDebugMacro(<<"Creating Section " << splineno);
+
+  sep->Initialize();
+
+  int oldap=this->SplineStack->apexenabled();
+  int tb=this->SplineStack->gettrimbottom();
+  int tt=this->SplineStack->gettrimtop();
+  this->SplineStack->enableapex(0);
+
+  PXContourStack* cstack;
+
+  if (!this->PolarMode)
+      {
+	this->SplineStack->settrimbottom(splineno);
+	this->SplineStack->settrimtop(splineno+1);
+	if (splineno==tt-1 && splineno==tb  && this->DrawMode==3)
+	  {
+	    PXContourStack* cstack2=this->SplineStack->exporttocontourstack(this->ResolutionU,this->ResolutionV,1);
+	    cstack=new PXContourStack(cstack2,0,0,1,1);
+	    delete cstack2;
+	  }
+	else if (splineno==tt-1 && this->DrawMode>=2)
+	  {
+	    PXContourStack* cstack2=this->SplineStack->exporttocontourstack(this->ResolutionU,this->ResolutionV,1);
+	    cstack=new PXContourStack(cstack2,0,0,0,1);
+	    delete cstack2;
+	  }
+	else  if (splineno==tb && ( this->DrawMode==1 || this->DrawMode==3))
+	  {
+	    PXContourStack* cstack2=this->SplineStack->exporttocontourstack(this->ResolutionU,this->ResolutionV,1);
+	    cstack=new PXContourStack(cstack2,0,0,1,0);
+	    delete cstack2;
+	  }
+	else
+	  cstack=this->SplineStack->exporttocontourstack(this->ResolutionU,this->ResolutionV,1);
+      }
+  else
+      {
+	if (splineno!=this->SplineStack->gettrimtop())
+	    {
+	      this->SplineStack->settrimbottom(splineno);
+	      this->SplineStack->settrimtop(splineno+1);
+	      cstack=this->SplineStack->exporttocontourstack(this->ResolutionU);
+	    }
+	else
+	    {
+	      cstack=new PXContourStack(2);
+	      (cstack->getcontour(0))->copypoints(this->SplineStack->getspline(this->SplineStack->gettrimtop())->exporttocontour(this->ResolutionU));
+	      cstack->setzlevel(0,this->SplineStack->getspline(this->SplineStack->gettrimtop())->getzlevel());
+	      (cstack->getcontour(0))->ensureAnticlockwise();
+	      (cstack->getcontour(1))->copypoints(this->SplineStack->getspline(this->SplineStack->gettrimbottom())->exporttocontour(this->ResolutionU));
+	      cstack->setzlevel(1,this->SplineStack->getspline(this->SplineStack->gettrimbottom())->getzlevel());      
+	      (cstack->getcontour(1))->ensureClockwise();
+	    }
+      }
+  
+  this->SplineStack->settrimbottom(tb);
+  this->SplineStack->settrimtop(tt);
+  this->SplineStack->enableapex(oldap);
+  
+  if (!this->PolarMode)
+      {
+	PXTriangulatedStack* ts=new PXTriangulatedStack(cstack,0);
+	vtkDebugMacro(<<"Drawing Section " << splineno << "Np="<< ts->getnumpoints()<<" Nt="<<ts->getnumtriangles());
+	vtkpxSurfaceUtil::drawtstack(sep,ts);
+	delete ts;
+      }
+  else
+      {	
+	//vtkDebugMacro(<<"Drawing Section " << splineno);
+	vtkpxSurfaceUtil::createsection(cstack,sep,1,this->PolarMiddle);
+      }
+  delete cstack;
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::Execute()
+{
+  if (this->SplineStack==NULL)
+      {
+	vtkErrorMacro(<<"No spline available");
+	return;
+      }
+  vtkPolyData* output = this->GetOutput();
+
+  CreateSurface();
+
+  if (this->WholeSurface)
+      {
+	if (this->SplineStack->gettrimbottom() < this->SplineStack->gettrimtop())
+	  {
+	    vtkDebugMacro(<<"Using Whole Surface");
+	    vtkPolyDataNormals* normalsFilter=vtkPolyDataNormals::New();
+	    normalsFilter->SetInput(wholeSurfaceData);
+	    normalsFilter->SetFeatureAngle(0.0);
+	    normalsFilter->SetSplitting(0);
+	    normalsFilter->Update();
+	    output->ShallowCopy(normalsFilter->GetOutput());
+	    output->GetPointData()->PassData(normalsFilter->GetOutput()->GetPointData());
+	    normalsFilter->Delete();
+	  }
+	else
+	  {
+	    output->ShallowCopy(wholeSurfaceData);
+	  }
+      }
+  else
+      {
+	vtkDebugMacro(<<"Using Spline Surface " << sliceSurfaceData->GetNumberOfItems()<< ","<<this->SplineStack->getnumsplines());
+	this->sliceSurfaceData->InitTraversal();
+	vtkAppendPolyData* append=vtkAppendPolyData::New();
+	for (int j=0;j<sliceSurfaceData->GetNumberOfItems();j++)
+	  {
+	    vtkPolyData* poly=this->sliceSurfaceData->GetNextItem();
+	    if (j>=SplineStack->gettrimbottom() && j<=SplineStack->gettrimtop() && poly!=NULL)
+		append->AddInput(poly);
+	  }
+
+	append->Update();
+	output->CopyStructure(append->GetOutput());
+	append->Delete();
+      }
+
+
+  int tb=this->SplineStack->gettrimbottom();
+  int tt=this->SplineStack->gettrimtop();
+
+  if (tb==tt)
+    return;
+
+
+  // From here this is a tiny hack to make sure things display OK
+  // when clipped close to bottom or top XY image slice
+  // Xenios Jan 31st 2010
+  double numgap=double(tt-tb);
+
+
+  double bounds[6]; output->GetBounds(bounds);
+  vtkPoints* outp=output->GetPoints();
+  int np=outp->GetNumberOfPoints();
+  //  int nshift=0;
+
+  double offset=(bounds[5]-bounds[4])/numgap*this->ZDisplayOffset;
+
+  for (int i=0;i<np;i++)
+    {
+      double p[3];
+      outp->GetPoint(i,p);
+      if ( fabs(p[2]-bounds[4])<offset)
+	{
+	  p[2]=p[2]-offset;
+	  outp->SetPoint(i,p);
+	  //  ++nshift;
+	}
+      else if (fabs(p[2]-bounds[5])<offset)
+	{
+	  p[2]=p[2]+offset;
+	  outp->SetPoint(i,p);
+	  //	  ++nshift;
+	}
+    }
+  //  fprintf(stdout,"nshift=%d point shifted by %f\n",nshift,offset);
+}
+//------------------------------------------------------------------------------
+float vtkpxSplineStackSource::GetVolume()
+{
+  float totalarea=0.0;
+  for (int i=this->GetTrimBottom(); i<=this->GetTrimTop();i++)
+    {
+      PXContour* cntr=this->SplineStack->getspline(i)->exporttocontour(0.05);
+      totalarea+=cntr->getarea();
+      delete cntr;
+    }
+
+  int tb=this->GetTrimBottom();
+  int tt=this->GetTrimTop();
+
+  float z2=this->GetSpline(tt)->getzlevel();
+  float z1=this->GetSpline(tb)->getzlevel();
+
+  float dz=(z2-z1)/float(tt-tb);
+
+  return totalarea*dz;
+}
+
+//------------------------------------------------------------------------------
+float vtkpxSplineStackSource::GetVOIVolume(vtkImageData* image,int frame,float threshold)
+{
+  float volume=1.0,mean=0.0,std=0.0;
+  this->GetVOIProperties(image,frame,volume,mean,std,threshold);
+  return volume;
+}
+//------------------------------------------------------------------------------
+int  vtkpxSplineStackSource::GetVOIProperties(vtkImageData* image,int frame,
+					      float& volume,float& mean,float& std,float threshold)
+{
+  if (image==NULL)
+    return -1;
+
+  double sp[3],ori[3];
+  int dim[3];
+  image->GetDimensions(dim);
+  image->GetSpacing(sp);
+  image->GetOrigin(ori);
+
+  int numvoxels=0;
+  float sum=0.0,sum2=0.0;
+
+
+  for (int k=this->GetTrimBottom(); k<=this->GetTrimTop();k++)
+    {
+      int level=Irange(k,0,dim[2]-1);
+      PXContour* cntr=this->SplineStack->getspline(level)->exporttocontour(0.05);
+      
+      float x1,x2,y1,y2;
+      cntr->getextent(x1,x2,y1,y2);
+      int imin=Irange( int((x1/sp[0])-ori[0]-1.0),0,dim[0]-2);
+      int imax=Irange( int((x2/sp[0])-ori[0]-1.0),imin+1,dim[0]-1);
+      
+      int jmin=Irange( int((y1/sp[1])-ori[1]-1.0),0,dim[1]-2);
+      int jmax=Irange( int((y2/sp[1])-ori[1]-1.0),jmin+1,dim[1]-1);
+      
+      
+      for (int i=imin;i<=imax;i++)
+	for (int j=jmin;j<=jmax;j++)
+	  {
+	    float x[2];
+	    x[0]=float(i)*sp[0]+ori[0];
+	    x[1]=float(j)*sp[1]+ori[1];
+
+	    float v=image->GetScalarComponentAsDouble(i,j,level,frame);
+	    if ( (v>=threshold) && ( cntr->IsInside(x[0],x[1]) > 0 ))
+	      {
+		++numvoxels;
+		sum+=v;
+		sum2+=v*v;
+	      }
+	  }
+      delete cntr;
+    }
+
+  mean=0.0;std=0.0;volume=0.0;
+
+  if (numvoxels>0)
+    {
+      mean=sum/float(numvoxels);
+      std= sqrt( sum2/float(numvoxels)-mean*mean);
+      volume=float(numvoxels)*sp[0]*sp[1]*sp[2];
+    }
+
+  return numvoxels;
+
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::AddToObjectMap(vtkImageData* objectmap,float value,int add,int background)
+{
+  if (objectmap==NULL)
+    return -1;
+  
+  double sp[3],ori[3];
+  int dim[3];
+  objectmap->GetDimensions(dim);
+  objectmap->GetSpacing(sp);
+  objectmap->GetOrigin(ori);
+  
+  int numvoxels=0;
+  int slicesize=dim[1]*dim[0];
+  vtkDataArray* objectmapScalars=objectmap->GetPointData()->GetScalars();
+  int numscalars=objectmapScalars->GetNumberOfTuples();
+
+  fprintf(stderr,"Slices %d:%d ",this->GetTrimBottom(),this->GetTrimTop());
+  for (int k=this->GetTrimBottom(); k<=this->GetTrimTop();k++)
+    {
+      fprintf(stderr,"%d ",k);
+      int level=Irange(k,0,dim[2]-1);
+      PXContour* cntr=this->SplineStack->getspline(level)->exporttocontour(0.05);
+      float x1,x2,y1,y2;
+      cntr->getextent(x1,x2,y1,y2);
+      int imin=Irange( int((x1/sp[0])-ori[0]-2.0),0,dim[0]-2);
+      int imax=Irange( int((x2/sp[0])-ori[0]+2.0),imin+1,dim[0]-1);
+      
+      int jmin=Irange( int((y1/sp[1])-ori[1]-2.0),0,dim[1]-2);
+      int jmax=Irange( int((y2/sp[1])-ori[1]+2.0),jmin+1,dim[1]-1);
+      
+      /*fprintf(stderr,"Level = %d Ranges = %.1f:%.1f %.1f:%.1f --> vox (%d:d %d:%d)\n",
+	k,x1,y1,x2,y2,imin,jmin,imax,jmax);*/
+      
+      for (int i=imin;i<=imax;i++)
+	for (int j=jmin;j<=jmax;j++)
+	  {
+	    float x[2];
+	    x[0]=float(i)*sp[0]+ori[0];
+	    x[1]=float(j)*sp[1]+ori[1];
+
+	    if ( cntr->IsInside(x[0],x[1]) > 0 )
+	      {
+		++numvoxels;
+		int index=Irange(k*slicesize+j*dim[0]+i,0,numscalars-1);
+		int current=(int)objectmapScalars->GetComponent(index,0);
+		
+		if (current==background || add==0)
+		  {
+		    objectmapScalars->SetComponent(index,0,value);
+		  }
+		else
+		  {
+		    objectmapScalars->SetComponent(index,0,value+current);
+		  }
+	      }
+	  }
+      delete cntr;
+    }
+  fprintf(stderr,"\n");
+  return numvoxels;
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::CreateBoundedObjectMap(vtkpxSplineStackSource* bounding,vtkImageData* objectmap,
+						   int inside_below,int inside_above,
+						   int outside,int offslice)
+{
+  if (objectmap==NULL || bounding==NULL)
+    return -1;
+  
+  double sp[3],ori[3];
+  int dim[3];
+  objectmap->GetDimensions(dim);
+  objectmap->GetSpacing(sp);
+  objectmap->GetOrigin(ori);
+  
+  int numvoxels=0;
+  int slicesize=dim[1]*dim[0];
+  vtkDataArray* objectmapScalars=objectmap->GetPointData()->GetScalars();
+  objectmapScalars->FillComponent(0,double(offslice));
+  int numscalars=objectmapScalars->GetNumberOfTuples();
+
+  for (int k=this->GetTrimBottom(); k<=this->GetTrimTop();k++)
+    {
+      int level=Irange(k,0,dim[2]-1);
+      PXContour* cntr=this->SplineStack->getspline(level)->exporttocontour(0.05);
+      float x1,x2,y1,y2;
+      cntr->getextent(x1,x2,y1,y2);
+      int imin=Irange( int((x1/sp[0])-ori[0]-2.0),0,dim[0]-2);
+      int imax=Irange( int((x2/sp[0])-ori[0]+2.0),imin+1,dim[0]-1);
+      
+      int jmin=Irange( int((y1/sp[1])-ori[1]-2.0),0,dim[1]-2);
+      int jmax=Irange( int((y2/sp[1])-ori[1]+2.0),jmin+1,dim[1]-1);
+      
+
+      PXContour* cntr2=bounding->GetSplineStack()->getspline(level)->exporttocontour(0.05);
+      cntr2->getextent(x1,x2,y1,y2);
+      double  boundy=y1;
+
+      int baseindex=k*slicesize;
+      for (int ia=0; ia <slicesize ; ia++)
+	objectmapScalars->SetComponent(baseindex+ia,0,(double)outside);
+      
+      for (int i=imin;i<=imax;i++)
+	for (int j=jmin;j<=jmax;j++)
+	  {
+	    float x[2];
+	    x[0]=float(i)*sp[0]+ori[0];
+	    x[1]=float(j)*sp[1]+ori[1];
+	    int index=Irange(k*slicesize+j*dim[0]+i,0,numscalars-1);
+	    if ( cntr->IsInside(x[0],x[1]) > 0 )
+	      {
+		++numvoxels;
+		if (x[1]>boundy)
+		  objectmapScalars->SetComponent(index,0,(double)inside_below);
+		else
+		  objectmapScalars->SetComponent(index,0,(double)inside_above);
+	      }
+	    else
+	      {
+		objectmapScalars->SetComponent(index,0,(double)outside);
+	      }
+	  }
+      delete cntr;
+      delete cntr2;
+    }
+  return numvoxels;
+}
+
+int vtkpxSplineStackSource::CreateObjectMap(vtkImageData* objectmap,int inside,int outside,int offslice)
+{
+  if (objectmap==NULL)
+    return -1;
+  
+  double sp[3],ori[3];
+  int dim[3];
+  objectmap->GetDimensions(dim);
+  objectmap->GetSpacing(sp);
+  objectmap->GetOrigin(ori);
+  
+  int numvoxels=0;
+  int slicesize=dim[1]*dim[0];
+  vtkDataArray* objectmapScalars=objectmap->GetPointData()->GetScalars();
+  objectmapScalars->FillComponent(0,double(offslice));
+  int numscalars=objectmapScalars->GetNumberOfTuples();
+
+  for (int k=this->GetTrimBottom(); k<=this->GetTrimTop();k++)
+    {
+      int level=Irange(k,0,dim[2]-1);
+      PXContour* cntr=this->SplineStack->getspline(level)->exporttocontour(0.05);
+
+      float x1,x2,y1,y2;
+      cntr->getextent(x1,x2,y1,y2);
+      int imin=Irange( int((x1/sp[0])-ori[0]-2.0),0,dim[0]-2);
+      int imax=Irange( int((x2/sp[0])-ori[0]+2.0),imin+1,dim[0]-1);
+      
+      int jmin=Irange( int((y1/sp[1])-ori[1]-2.0),0,dim[1]-2);
+      int jmax=Irange( int((y2/sp[1])-ori[1]+2.0),jmin+1,dim[1]-1);
+      
+      int baseindex=k*slicesize;
+      for (int ia=0; ia <slicesize ; ia++)
+	objectmapScalars->SetComponent(baseindex+ia,0,(double)outside);
+      
+      for (int i=imin;i<=imax;i++)
+	for (int j=jmin;j<=jmax;j++)
+	  {
+	    float x[2];
+	    x[0]=float(i)*sp[0]+ori[0];
+	    x[1]=float(j)*sp[1]+ori[1];
+	    int index=Irange(k*slicesize+j*dim[0]+i,0,numscalars-1);
+	    if ( cntr->IsInside(x[0],x[1]) > 0 )
+	      {
+		++numvoxels;
+		objectmapScalars->SetComponent(index,0,(double)inside);
+	      }
+	    else
+	      {
+		objectmapScalars->SetComponent(index,0,(double)outside);
+	      }
+	  }
+      delete cntr;
+    }
+  return numvoxels;
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::ScaleShiftZ(float shift,float scale)
+{
+  if (scale<=0.01)
+    scale=1.0;
+
+  int ns=this->SplineStack->getnumsplines();
+  for (int i=0;i<ns;i++)
+    {
+      PXFPBSpline* spl=this->SplineStack->getspline(i);
+      if (spl!=NULL)
+	{
+	  float z=spl->getzlevel();
+	  spl->setzlevel(shift+scale*z);
+	}
+    }
+  this->Modified();
+  this->RedrawSurface=1;
+}
+
+void vtkpxSplineStackSource::ScaleShiftXY(float shiftx,float shifty,float scalex,float scaley)
+{
+   int ns=this->SplineStack->getnumsplines();
+  for (int i=0;i<ns;i++)
+    {
+      PXFPBSpline* spl=this->SplineStack->getspline(i);
+      if (spl!=NULL)
+	spl->scaleshift2D(shiftx,shifty,scalex,scaley);
+    }
+  this->Modified();
+  this->RedrawSurface=1;
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::AdjustNumberOfSplines(int newnumber)
+{
+  this->SplineStack->adjustnumberofsplines(newnumber);
+}
+//------------------------------------------------------------------------------
+int  vtkpxSplineStackSource::GetDualVOIProperties(vtkImageData* image,int frame,
+						  float volume[2],float mean[2],float std[2],int numvoxels[2],
+						  float threshold[2])
+{
+  if (image==NULL)
+    return -1;
+
+  double sp[3],ori[3];
+  int dim[3];
+  image->GetDimensions(dim);
+  image->GetSpacing(sp);
+  image->GetOrigin(ori);
+
+  numvoxels[0]=0; numvoxels[1]=0;
+  int total=0;
+  float sum[2],sum2[2];
+  
+  sum[0]=0.0; sum[1]=0.0; sum2[0]=0.0; sum2[1]=0.0;
+
+
+  for (int k=this->GetTrimBottom(); k<=this->GetTrimTop();k++)
+    {
+      int level=Irange(k,0,dim[2]-1);
+      PXContour* cntr=this->SplineStack->getspline(level)->exporttocontour(0.05);
+      float x1,x2,y1,y2;
+      cntr->getextent(x1,x2,y1,y2);
+      int imin=Irange( int((x1/sp[0])-ori[0]-1.0),0,dim[0]-2);
+      int imax=Irange( int((x2/sp[0])-ori[0]-1.0),imin+1,dim[0]-1);
+      
+      int jmin=Irange( int((y1/sp[1])-ori[1]-1.0),0,dim[1]-2);
+      int jmax=Irange( int((y2/sp[1])-ori[1]-1.0),jmin+1,dim[1]-1);
+
+      fprintf(stderr,"k=%d i=%d:%d j=%d:%d\n",k,imin,imax,jmin,jmax);
+      
+      for (int i=imin;i<=imax;i++)
+	for (int j=jmin;j<=jmax;j++)
+	  {
+	    float v=image->GetScalarComponentAsDouble(i,j,level,frame);
+	    float x[2];
+	    x[0]=float(i)*sp[0]+ori[0];
+	    x[1]=float(j)*sp[1]+ori[1];
+	    if (cntr->IsInside(x[0],x[1]) > 0)
+	      {
+		++total;
+		for (int r=0;r<=1;r++)
+		  {
+		    if (v>threshold[r])
+		      {
+			++numvoxels[r];
+			sum[r]+=v;
+			sum2[r]+=v*v;
+		      }
+		  }
+	      }
+	  }
+      delete cntr;
+    }
+	
+  for (int r=0;r<=1;r++)
+    {
+      mean[r]=sum[r]/float(numvoxels[r]+0.00001);
+      std[r]= sqrt( sum2[r]/float(numvoxels[r]+0.0001)-mean[r]*mean[r]);
+      volume[r]=float(numvoxels[r])*sp[0]*sp[1]*sp[2];
+    }
+
+  return total;
+
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::LoadAndFitContourStack(const char* fname)
+{
+  PXContourStack* cnt=new PXContourStack();
+  int ok=cnt->Load(fname);
+  if (ok)
+    this->FitToContourStack(cnt,2.0,0.5,25,1);
+  delete cnt;
+}
+//------------------------------------------------------------------------------  
+int vtkpxSplineStackSource::ComputeZRange(vtkCollection* collection,int numframes,int numsurfaces,
+					  int beginframe,int endframe,
+					  int index,float z[2])
+{
+  float minz=0,maxz=0;
+  index=Irange(index,0,numsurfaces-1);
+
+  beginframe=Irange(beginframe,0,numframes-1);
+  endframe=Irange(endframe,beginframe,numframes-1);
+
+  for (int frame=beginframe;frame<=endframe;frame++)
+    {
+      vtkpxSplineStackSource* stack=(vtkpxSplineStackSource*)collection->GetItemAsObject(frame*numsurfaces+index);
+      
+      if (stack->GetPolarMode()==0)
+	{
+	  if (frame==beginframe)
+	    {
+	      minz=(float)stack->GetTrimBottom();
+	      maxz=(float)stack->GetTrimTop();
+	    }
+	  else
+	    {
+	      minz=Fmax(minz,(float)stack->GetTrimBottom());
+	      maxz=Fmin(maxz,(float)stack->GetTrimTop());
+	    }
+	  //fprintf(stderr,"Frame=%d minz=%.1f maxz=%.1f\n",frame,minz,maxz);
+	}
+      else
+	{
+	  if (frame==beginframe)
+	    {
+	      minz=stack->GetSplineStack()->getpolarbottomz()+3.0;
+	      maxz=stack->GetSplineStack()->getpolartopz()-3.0;
+	    }
+	  else
+	    {
+	      minz=Fmax(minz,stack->GetSplineStack()->getpolarbottomz()+3.0);
+	      maxz=Fmin(maxz,stack->GetSplineStack()->getpolartopz()-3.0);
+	    }
+	}
+    }
+
+  z[0]=minz;
+  z[1]=maxz;
+
+  return 1;
+}
+
+void vtkpxSplineStackSource::SetDrawMode(int dm)
+{
+  dm=Irange(dm,0,3);
+  if (this->DrawMode!=dm)
+    {
+      this->DrawMode=dm;
+      this->RedrawSurface=1;
+      this->Modified();
+    }
+}
+
+void vtkpxSplineStackSource::SetPolarMode(int pm)
+{
+  pm=pm>0;
+  if (this->PolarMode!=pm)
+    {
+      this->PolarMode=pm;
+      this->RedrawSurface=1;
+      this->Modified();
+    }
+}
+
+
+void vtkpxSplineStackSource::SetWholeSurface(int pm)
+{
+  pm=pm>0;
+  if (this->WholeSurface!=pm)
+    {
+      this->WholeSurface=pm;
+      this->RedrawSurface=1;
+      this->Modified();
+    }
+}
+// ------------------------------------------------------------------------------------------------------------------
+int vtkpxSplineStackSource::FillDistanceMap(vtkImageData* distancemap)
+{
+  if (distancemap==NULL)
+    return -1;
+  
+  double sp[3],ori[3];
+  int dim[3];
+  distancemap->GetDimensions(dim);
+  distancemap->GetSpacing(sp);
+  distancemap->GetOrigin(ori);
+  
+  float pxl=(sp[0]*100.0);
+  PXChamferDistanceMap::pixel_size=short(pxl);
+  PXChamferDistanceMap::obj_gray=10000;
+  PXChamferDistanceMap::out_gray=-10000;
+  
+  int slicesize=dim[1]*dim[0];
+  vtkDataArray* distances=distancemap->GetPointData()->GetScalars();
+  distances->FillComponent(0,-10000);
+
+
+  for (int k=this->GetTrimBottom(); k<=this->GetTrimTop();k++)
+    {
+      int level=k;
+      int offset=slicesize*level;
+
+      // Export To Contour and Scale in Voxel Units
+      PXContour* cntr=this->SplineStack->getspline(level)->exporttocontour(0.05);
+
+      PXContourPoint* pts=cntr->gettoppoint();
+      int np=cntr->getnumpoints();
+      for (int ib=1;ib<=np;ib++)
+	{
+	  pts->x=(pts->x-ori[0])/sp[0];
+	  pts->y=(pts->y-ori[1])/sp[1];
+	  pts=pts->next;
+	}
+      
+      PXChamferDistanceMap* map=new PXChamferDistanceMap(cntr,1);
+
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {
+	    float v=(float(map->getvalue(i,j)));
+	    int index=offset+j*dim[0]+i;
+	    distances->SetComponent(index,0,v);
+	  }
+      delete map;
+      delete cntr;
+    }
+
+  
+  if (this->GetTrimBottom()>0)
+    {
+      int trim=this->GetTrimBottom();
+
+      for (int k=trim-1;k>=0;k=k-1)
+	{
+	  int offset1=slicesize*k;
+	  int offset2=slicesize+offset1;
+	  
+	  float maxv=1.0;
+	  if (k==trim-1)
+	    {
+	      for (int index=0;index<slicesize;index++)
+		maxv=Fmax(maxv,distances->GetComponent(index+offset2,0));
+	    }
+	  
+	  for (int index=0;index<slicesize;index++)
+	    {
+	      float v=distances->GetComponent(index+offset2,0);
+	      if (v<0.0)
+		{
+		  distances->SetComponent(index+offset1,0,v-sp[2]*100.0);
+		}
+	      else
+		{
+		  // True Boundary is tloc at away from bottom slice
+		  // Hence distancemap at tloc=0
+		  // d=  (1-tloc)*v + (tloc)*newv = 0
+		  // --> newv=-(1-tloc)*v/tloc
+
+		  // tloc=0.5 at v=maxv  and 0 and v=0
+		  float tloc=0.5*pow(v/maxv,float(2.0));
+		  float newv=-(1.0-tloc)*v/tloc;
+		  distances->SetComponent(index+offset1,0,newv);
+		}
+	    }
+	}
+    }
+
+
+  if (this->GetTrimTop()<dim[2]-1)
+    {
+      int trim=this->GetTrimTop();
+
+      for (int k=trim+1;k<dim[2];k++)
+	{
+	  int offset1=slicesize*k;
+	  int offset2=offset1-slicesize;
+	  
+	  float maxv=1.0;
+	  if (k==trim+1)
+	    {
+	      for (int index=0;index<slicesize;index++)
+		maxv=Fmax(maxv,distances->GetComponent(index+offset2,0));
+	    }
+	  
+	  for (int index=0;index<slicesize;index++)
+	    {
+	      float v=distances->GetComponent(index+offset2,0);
+	      if (v<0.0)
+		{
+		  distances->SetComponent(index+offset1,0,v-sp[2]*100.0);
+		}
+	      else
+		{
+		  // True Boundary is tloc at away from bottom slice
+		  // Hence distancemap at tloc=0
+		  // d=  (1-tloc)*v + (tloc)*newv = 0
+		  // --> newv=-(1-tloc)*v/tloc
+
+		  // tloc=0.5 at v=maxv  and 0 and v=0
+		  float tloc=0.5*pow(v/maxv,float(2.0));
+		  float newv=-(1.0-tloc)*v/tloc;
+		  distances->SetComponent(index+offset1,0,newv);
+		}
+	    }
+	}
+    }
+
+
+  return 1;
+}
+//------------------------------------------------------------------------------
+void vtkpxSplineStackSource::UpSample()
+{
+  PXFPBSplineStack* newstack=new PXFPBSplineStack(this->SplineStack,1,1,0);
+  delete this->SplineStack;
+  this->SplineStack=newstack;
+}
+
+int vtkpxSplineStackSource::FlipX(vtkImageData* image)
+{
+  if (image==NULL)
+    return 0;
+
+  double spacing[3]; image->GetSpacing(spacing);
+  double origin[3];  image->GetOrigin(origin);
+  int dimensions[3]; image->GetDimensions(dimensions);
+  float cx=spacing[0]*dimensions[0]/2+origin[0];
+  
+  for (int k=this->GetTrimBottom(); k<=this->GetTrimTop();k++)
+    {
+      PXFPBSpline* spl=this->SplineStack->getspline(k);
+
+      for (int i=0;i<spl->getnumcontrolpoints();i++)
+	{
+	  float x1=spl->getcontrolx(i);
+	  spl->shiftcontrol(i,-2.0*(x1-cx),0,0);
+	  float x2=spl->getcontrolx(i);
+	  //	  fprintf(stderr,"x1=%.2f --> x2=%.2f\n",x1,x2);
+	}
+      
+    }
+  this->RedrawSurface=1;
+  this->Modified();
+  
+  return 1;
+}
+
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::CreateSurfaceFromImage(vtkImageData* img,int minslice0,int maxslice0,int frame,float curvesmooth,float smoothness)
+{
+  if (img==NULL)
+    {
+      return 0;
+    }
+
+  int nc=img->GetNumberOfScalarComponents();
+  if (frame<1)
+    frame=1;
+  if (frame>nc)
+    frame=nc;
+
+  int minslice=minslice0;
+  int maxslice=maxslice0;
+
+  vtkImageData* thr=vtkpxSplineStackSource::PreprocessBinaryImage(img,frame-1);
+  PXContourStack* stack=ExtractContourStackFromImage(thr,minslice,maxslice,smoothness);
+  
+  int ok=this->SplineStack->fittocontourstack(stack,curvesmooth,0.05,-1,1);
+  fprintf(stderr,"Final Trims = %d:%d\n",minslice,maxslice);
+  this->SetTrimBottom(minslice);
+  this->SetTrimTop(maxslice);
+  
+  delete stack;
+  thr->Delete();
+
+  this->Modified();
+  this->RedrawSurface=1;
+
+  return ok;
+  
+}
+//------------------------------------------------------------------------------
+vtkImageData* vtkpxSplineStackSource::PreprocessBinaryImage(vtkImageData* img,int frame)
+{
+  if (img==NULL)
+    {
+      // fprintf();
+      return NULL;
+    }
+  
+  double range[2]; img->GetPointData()->GetScalars()->GetRange(range);
+  double threshold=0.5*(range[1]+range[0]);
+  if (fabs(range[0]-0)<0.01 && fabs(range[1]-1.0)<0.01)
+    threshold=1.0;
+
+  fprintf(stderr,"Threshold=%.2f\n",threshold);
+
+  
+  vtkImageExtractComponents* comp=  vtkImageExtractComponents::New();
+  comp->SetInput(img);
+  comp->SetComponents(frame);
+  
+  vtkImageThreshold* thr=vtkImageThreshold::New();
+  thr->SetInput(comp->GetOutput());
+  thr->ThresholdBetween(threshold,range[1]+1.0);
+  thr->ReplaceInOn();
+  thr->ReplaceOutOn();
+  thr->SetInValue(100);
+  thr->SetOutValue(0);
+  thr->SetOutputScalarTypeToUnsignedChar();
+  thr->Update();
+  
+  vtkImageData* tmp=vtkImageData::New();
+  tmp->ShallowCopy(thr->GetOutput());
+  //  smooth->Delete();
+  thr->Delete();
+  comp->Delete();
+  
+  return tmp;
+}
+//------------------------------------------------------------------------------
+PXContourStack* vtkpxSplineStackSource::ExtractContourStackFromImage(vtkImageData* img,int& minslice,int& maxslice,float sigma)
+{
+  int dim[3]; img->GetDimensions(dim);
+  double ori[3]; img->GetOrigin(ori);
+  double spa[3]; img->GetSpacing(spa);
+  
+   
+  PXContourStack* stack=new PXContourStack(dim[2]);
+
+  double c[2],r[2];
+  for (int ia=0;ia<=1;ia++)
+    {
+      c[ia]=ori[ia]+0.5*spa[ia]*double(dim[ia]-1);
+      r[ia]=0.2*spa[ia]*double(dim[ia]-1);
+    }
+  stack->setellipticalcylinder(4,r[0],r[1],c[0],c[1]);
+  
+  for (int i=0;i<dim[2];i++)
+    {
+      double z=double(i)*spa[2]+ori[2];
+      stack->setzlevel(i,z);
+    }
+
+  int found=0,newmin=minslice,newmax=maxslice;
+
+  for (int i=minslice;i<=maxslice;i++)
+    {
+      PXContour* cntr=ExtractContourFromImage(img,i,sigma);
+      if (cntr!=NULL)
+	{
+	  stack->getcontour(i)->copypoints(cntr);
+	  delete cntr;
+	  if (found==0)
+	    {
+	      newmin=i;
+	      newmax=i;
+	      found=1;
+	    }
+	  else if (found==1)
+	    {
+	      ++newmax;
+	    }
+	}
+      else
+	{
+	  if (found==1)
+	    i=maxslice+1;
+	}
+    }
+
+   
+  minslice=newmin;
+  maxslice=newmax;
+
+  return stack;
+  
+
+}
+//------------------------------------------------------------------------------
+int vtkpxSplineStackSource::SetFromPolyData(PXContour* cntr,vtkPolyData* polydata)
+{
+  if (polydata==NULL || cntr==NULL)
+      return 0;
+
+  cntr->DeleteAll();
+
+
+  vtkPoints* newPoints=polydata->GetPoints();
+  int np=newPoints->GetNumberOfPoints();
+
+	
+  int* neigh=new int[np*2];
+  int* used=new int[np];
+
+  for (int ib=0;ib<np*2;ib++)
+      neigh[ib]=-1;
+  for (int ic=0;ic<np;ic++)
+      used[ic]=0;
+ 
+  vtkCellArray* lines=polydata->GetLines();
+  int numlines=lines->GetNumberOfCells();
+  lines->InitTraversal();
+  for (int ia=0;ia<numlines;ia++)
+    {
+      vtkIdType nump;
+      vtkIdType *p;
+      lines->GetNextCell(nump,p);
+      
+      for (int k=0;k<=1;k++)
+	{
+	  int index=p[k]*2;
+	  if (neigh[index]==-1)
+	    neigh[index]=p[1-k];
+	  else
+	    neigh[index+1]=p[1-k];
+	}
+    }
+
+  int nearest=0;
+  double x[3];
+  newPoints->GetPoint(nearest,x);
+
+  int done=0,numlinks=0,firstpoint=nearest;
+
+  while (done==0 && numlinks<np-1)
+      {
+	int index=firstpoint*2;
+	used[firstpoint]=1;
+
+	//fprintf(stderr,"Parsing Point=%3d Neighbours %3d,%3d\n",firstpoint,neigh[index],neigh[index+1]);
+	if (neigh[index]==-1 || neigh[index+1]==-1)
+	    {
+	      done=1;
+
+	      // Unless we can merge 
+	      double x1[3],x2[3];
+	      newPoints->GetPoint(firstpoint,x1);
+	      for (int kk=0;kk<np;kk++)
+		  {
+		    if (kk!=firstpoint)
+			{
+			  int index2=kk*2;
+			  if (neigh[index2]==-1 || neigh[index2+1]==-1)
+			      {
+				newPoints->GetPoint(kk,x2);
+				if (Fsqdist(x1[0],x1[1],x1[2],x2[0],x2[1],x2[2])<1.0)
+				    {
+				      /*fprintf(stderr,"\tAdding Link from %5.1f,%5.1f,%5.1f to %5.1f,%5.1f,%5.1f (index=%d,%d)\n",
+					      x1[0],x1[1],x1[2],x2[0],x2[1],x2[2],kk,firstpoint);*/
+				      done=0;
+
+				      if (neigh[index]==-1)
+					  neigh[index]=kk;
+				      else
+					  neigh[index+1]=kk;
+
+				      // Chain Back
+
+				      if (neigh[index2]==-1)
+					  neigh[index2]=firstpoint;
+				      else
+					  neigh[index2+1]=firstpoint;
+				      kk=np;
+				    }
+			      }
+			}
+		  }
+
+	    }
+
+	if (done==0)
+	    {
+	      int keeplooking=1;
+
+	      if (neigh[index]!=-1)
+		  {
+		    if (used[neigh[index]]==0)
+			{
+			  firstpoint=neigh[index];
+			  keeplooking=0;
+			}
+		  }
+
+	      if (keeplooking==1 && neigh[index+1]!=-1)
+		  {
+		    if (used[neigh[index+1]]==0)
+			{
+			  firstpoint=neigh[index+1];
+			  keeplooking=0;
+			}
+		  }
+
+	      if (keeplooking==1)
+		  done=1;
+	      else
+		  numlinks++;
+	    }
+      }
+
+  /*fprintf(stderr,"\tFirstPoint =%d (Neighbours=%d,%d) numlinks=%d (np=%d)\n",firstpoint,neigh[firstpoint*2],
+	  neigh[firstpoint*2+1],numlinks,np);*/
+
+  for (int ie=0;ie<np;ie++)
+      used[ie]=0;
+
+  int numgoodpoints=0,found=0;
+  int nextpoint=firstpoint;
+  while (found==0 && numgoodpoints<np)
+      {
+	int currentpoint=nextpoint;
+	used[currentpoint]=1;
+	int index=currentpoint*2;
+
+	/*fprintf(stderr,"Parsing Point=%3d Neighbours %3d,%3d Used=%d,%d\n",
+		currentpoint,neigh[index],neigh[index+1],used[neigh[index]],
+		used[neigh[index+1]]);*/
+	numgoodpoints++;
+
+	int keeplooking=1;
+	if (neigh[index]!=-1)
+	    {
+	      if (used[neigh[index]]==0)
+		  {
+		    nextpoint=neigh[index];
+		    keeplooking=0;
+		  }
+	    }
+	
+	if (keeplooking==1 && neigh[index+1]!=-1)
+	    {
+	      if (used[neigh[index+1]]==0)
+		  {
+		    nextpoint=neigh[index+1];
+		    keeplooking=0;
+		  }
+	    }
+
+	if (keeplooking==1)
+	    found=1;
+      }
+
+  //fprintf(stderr,"\tNumgoodpoints=%d\n",numgoodpoints);
+
+  // Restablish all links
+  for (int iaa=0;iaa<np;iaa++)
+      used[iaa]=0;
+
+  for (int k=0;k<numgoodpoints;k++)
+      {
+	double x[3],y[3];
+	newPoints->GetPoint(firstpoint,x);
+	used[firstpoint]=1;
+
+	cntr->Add(x[0],x[1]);
+	int index=firstpoint*2;
+	int keeplooking=1;
+
+	if (neigh[index]!=-1)
+	    {
+	      if (used[neigh[index]]==0)
+		  {
+		    firstpoint=neigh[index];
+		    keeplooking=0;
+		  }
+	    }
+
+	if (keeplooking==1 && neigh[index+1]!=1)
+	  {
+	      if (used[neigh[index+1]]==0)
+		  {
+		    firstpoint=neigh[index+1];
+		    keeplooking=0;
+		  }
+	    }
+
+	if (keeplooking==1)
+	    {
+	      k=np;
+	    }
+      }
+  
+  delete [] used;
+  delete [] neigh;
+  return 1;
+}
+
+PXContour* vtkpxSplineStackSource::ExtractContourFromImage(vtkImageData* img,int slice,float sigma)
+{
+  vtkpxImageExtract* extr=vtkpxImageExtract::New();
+  extr->SetInput(img);
+  extr->SetCurrentPlane(2);
+  extr->SetSliceNo(slice);
+  extr->SetFrame(1);
+  extr->Update();
+
+  vtkImageSeedConnectivity* seed=  vtkImageSeedConnectivity::New();
+  seed->SetInput(extr->GetOutput());
+  seed->SetInputConnectValue(0);
+  seed->SetOutputConnectedValue(0);
+  seed->SetOutputUnconnectedValue(100);
+  seed->AddSeed(0,0,0);
+  seed->Update();
+
+  vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+  smooth->SetInput(seed->GetOutput());
+  smooth->SetStandardDeviations(sigma,sigma,0.0);
+  smooth->SetDimensionality(2);
+  smooth->Update();
+  
+  vtkContourFilter* contourExtractor = vtkContourFilter::New();
+  contourExtractor->SetInput(smooth->GetOutput());
+  contourExtractor->SetValue(0,50.0);
+  contourExtractor->ComputeScalarsOff();
+  contourExtractor->ComputeGradientsOff();
+  contourExtractor->ComputeNormalsOff() ;
+  contourExtractor->Update();
+
+  vtkPolyDataConnectivityFilter* polycon=vtkPolyDataConnectivityFilter::New();
+  polycon->SetInput(contourExtractor->GetOutput());
+  polycon->SetExtractionModeToLargestRegion();
+  polycon->Update();
+
+  PXContour* cntr=NULL;
+  vtkPoints* pts=polycon->GetOutput()->GetPoints();
+  int np=0;
+
+  if (pts!=NULL)
+    np=pts->GetNumberOfPoints();
+
+  if (np>0)
+    {
+      cntr=new PXContour();
+      cntr->closedcontour(1);
+      SetFromPolyData(cntr,polycon->GetOutput());
+      fprintf(stderr,"Extracted %d points\n",np);
+    }
+  else
+    {
+      fprintf(stderr,"Failed to Extract Curve! slice=%d\n",slice);
+    }
+  polycon->Delete();
+  contourExtractor->Delete();
+  seed->Delete();
+  smooth->Delete();
+  extr->Delete();
+
+  return cntr;
+}
+
+      
+      
+      
+  
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxSplineStackSource.h b/bioimagesuite30_src/Legacy/vtkpxSplineStackSource.h
new file mode 100644
index 0000000..3035df7
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxSplineStackSource.h
@@ -0,0 +1,289 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSurfaceUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2002 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#ifndef __vtkpxSplineStackSource_h
+#define __vtkpxSplineStackSource_h
+
+#include "vtkPolyDataSource.h"
+
+
+//BTX
+class PXContourStack;
+class PXFPBSpline;
+class PXFPBSplineStack;
+//ETX
+
+typedef float real;
+
+#include "vtkpxSplineSource.h"
+
+class vtkImageData;
+class vtkPolyDataCollection;
+class vtkCollection;
+
+class vtkpxSplineStackSource : public vtkPolyDataSource
+{
+public:
+  static vtkpxSplineStackSource *New();
+  vtkTypeMacro(vtkpxSplineStackSource,vtkPolyDataSource);
+
+
+  // Description:
+  // Initialization
+  virtual void SetEllipticalCylinder(int np,int numslices,float radiusx=10.0,float radiusy=5.0,
+				     float x=50.0,float y=50.0,float zspacing=1.0,float bottomz=0.0);
+  virtual int SetLizzardCylinder(int np,int numslices,int bottomtrim,
+				 int lizzardslices, 
+				 int blendslices,int thinslices,
+				 float minradius,float maxradius,
+				 float yscale=1.2,
+				 float x=50.0,float y=50.0,float 
+				 zspacing=1.0,float bottomz=0.0);
+
+  virtual void Copy(vtkpxSplineStackSource* other,int ignoretrim);
+  virtual void Copy(vtkpxSplineStackSource* other) { Copy(other,0);}
+  
+  // Descripition
+  // Input/Output to .sur format 
+  virtual int  Load(const char* fname);
+  virtual int  Load(gzFile fin);
+  virtual int  Save(const char* fname);
+  virtual int  Save(FILE* fout);
+  
+  // Description:
+  // Display Parameter 
+  vtkGetMacro(DrawMode,int);
+  virtual void SetDrawMode(int md);
+
+  // Description:
+  // Sampling Rate in-plane 
+  vtkGetMacro(ResolutionU,float);
+  vtkSetMacro(ResolutionU,float);
+
+  // Description:
+  // Display Offset for top & bottom slices to make them visible
+  vtkGetMacro(ZDisplayOffset,float);
+  vtkSetMacro(ZDisplayOffset,float);
+
+  // Description:
+  // Sampling Rate out-of-plane
+  vtkGetMacro(ResolutionV,float);
+  vtkSetMacro(ResolutionV,float);
+
+  // Description:
+  // Center of rotation for polar (3D ultrasound) spline 
+  vtkGetMacro(PolarMiddle,float);
+  vtkSetMacro(PolarMiddle,float);
+
+  // Description:
+  // Set/Get Polar Mode 
+  vtkGetMacro(PolarMode,int);
+  virtual void SetPolarMode(int pm);
+
+  // Description:
+  // Update Whole Surface 
+  vtkGetMacro(WholeSurface,int);
+  virtual void SetWholeSurface(int ws);
+
+
+  // Description:
+  // Force Re-Draw of Surface 
+  vtkSetMacro(RedrawSurface,int);
+  vtkGetMacro(RedrawSurface,int);
+
+  // Description:
+  // Trims are extent of spline in image numsplines = numslices 
+  virtual int  GetTrimBottom();
+  virtual int  GetTrimTop();
+  virtual void SetTrimBottom(int tb);
+  virtual void SetTrimTop(int tt);
+  virtual int  GetNumSplines();
+  virtual float GetZSpacing();
+  
+  // Description:
+  // Set Spline 
+  int SetSpline(vtkpxSplineSource* source,int ind);
+  int SetSplineFromSplineStack(vtkpxSplineSource* source,int ind);
+
+  // BTX
+  virtual PXFPBSpline* GetSpline(int i);
+  virtual int SetSpline(PXFPBSpline* spl,int i);
+
+  // ContourStac Interface
+  virtual int FitToContourStack(PXContourStack* stack,float smooth=5.0,float csmooth=0.5,
+				int npoints=-1,int closed=1);
+  virtual PXContourStack* ExportToContourStack(real dist);
+  virtual PXContourStack* ExportToContourStack(real dist,real dist2);
+  // ETX
+
+  // Description:
+  // Cardiac Related Isuues, to set Apex 
+  virtual void SetApex(float x,float y,float z);
+  virtual void GetApex(float &x,float &y,float &z);
+  virtual void EnableApex(int enable=1);
+  virtual int  ApexEnabled();
+  virtual void AutoSetApex(int active=1);
+
+
+
+  // Description:
+  // Resample and Smooth Spline 
+  virtual int Resample(float ds_step,int npoints);
+  virtual int Resample(int npoints) { return Resample(0.01,npoints);}
+  virtual int Resample(float ds) { return Resample(ds,-1);}
+  virtual int ChangeSpacing(float smooth=0.5,float npoints=-1.0,
+			    float step=0.05,float csmooth=0.0,int iterations=50);
+
+
+  // Description:
+  // Shift And Scale Z-Coordinate 
+  virtual void ScaleShiftZ(float shift,float scale);
+  virtual void ScaleShiftXY(float shiftx,float shifty,float scalex,float scaley);
+  virtual void AdjustNumberOfSplines(int newnumber);
+
+  // Description: 
+  // VOI Stuff area, mean intensity area>0 std of mean intensity 
+  virtual float GetVolume();
+  virtual float GetVOIVolume(vtkImageData* image,int frame,float threshold=0.1);
+  virtual int   GetVOIProperties(vtkImageData* image,int frame,
+				 float& volume,float& mean,float& std,float threshold=0.0);
+  virtual int   GetDualVOIProperties(vtkImageData* image,int frame,
+				     float volume[2],float mean[2],float std[2],
+				     int numvoxels[2],float threshold[2]);
+  
+
+  
+  virtual int  AddToObjectMap(vtkImageData* objectmap,float value=1.0,int add=0,int background=0);
+  virtual int  CreateObjectMap(vtkImageData* objectmap,int inside=2,int outside=1,int offslice=0);
+  virtual int  CreateBoundedObjectMap(vtkpxSplineStackSource* bounding,vtkImageData* objectmap,
+				      int inside_below=2,int inside_above=3,
+				      int outside=1,int offslice=0);
+  virtual int  FillDistanceMap(vtkImageData* distancemap);
+
+
+  // Description:
+  // Flip Left
+  virtual int FlipX(vtkImageData* image);
+
+  // Description:
+  // Get the raw spline stack
+  virtual PXFPBSplineStack* GetSplineStack();
+
+  // Description:
+  virtual void LoadAndFitContourStack(const char* fname);
+
+
+  // Description:
+  // Compute Z-range
+  static int ComputeZRange(vtkCollection* collection,int numframes,int numsurfaces,
+			   int beginframe,int endframe,
+			   int index,float z[2]);
+
+
+  // Description:
+  // Upsample, i.e. from interpoated tracings add in-between slice
+  virtual void UpSample();
+
+  // Description:
+  // 
+  virtual int CreateSurfaceFromImage(vtkImageData* img,int minslice,int maxslice,int frame,float curvesmooth=1.0,float sigma=1.0);
+
+  // Description:
+  // A few static methods for Zak
+  static vtkImageData* PreprocessBinaryImage(vtkImageData* img,int frame);
+  static int SetFromPolyData(PXContour* cntr,vtkPolyData* polydata);
+  static PXContour* ExtractContourFromImage(vtkImageData* img,int slice,float sigma);
+  static PXContourStack* ExtractContourStackFromImage(vtkImageData* img,int& minslice,int& maxslice,float sigma=1.0);
+
+  
+		    
+protected:
+
+  vtkpxSplineStackSource();
+  virtual ~vtkpxSplineStackSource();
+  vtkpxSplineStackSource(const vtkpxSplineStackSource&) {};
+  void operator=(const vtkpxSplineStackSource&) {};
+  
+  void Execute();
+  
+  PXFPBSplineStack* SplineStack;
+  float ResolutionU;
+  float ResolutionV;
+  float PolarMiddle;
+  int   DrawMode;
+  float ZDisplayOffset;
+
+  int      WholeSurface;
+  int      PolarMode;
+  int      ShowSplinesOnly;
+  int      RedrawSurface;
+
+  vtkPolyDataCollection* sliceSurfaceData;
+  vtkPolyData*           wholeSurfaceData;
+
+
+  void  CreateSurface();
+  void  AddApex();
+  void  AddSections(int lower,int upper);
+  void  RemoveSections(int lower,int upper);
+  void  CreateSingleSection(int splineno);
+
+
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxTriangulatedStackSource.cpp b/bioimagesuite30_src/Legacy/vtkpxTriangulatedStackSource.cpp
new file mode 100644
index 0000000..79c8151
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxTriangulatedStackSource.cpp
@@ -0,0 +1,409 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxTriangulatedStackSource.cpp,v $
+  Language:  C++
+  Date:      $Date: 2003/05/28 21:03:01 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "pxutil.h"
+#include "pxgeometrystruct.h"
+#include "pxcontourstack.h"
+#include "pxfpbsplinestack.h"
+#include "vtkCellArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkpxTriangulatedStackSource.h"
+#include "vtkFloatArray.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkTriangleFilter.h"
+#include "vtkPointData.h"
+//------------------------------------------------------------------------------
+vtkpxTriangulatedStackSource* vtkpxTriangulatedStackSource::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxTriangulatedStackSource");
+  if(ret)
+    {
+    return (vtkpxTriangulatedStackSource*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxTriangulatedStackSource;
+}
+//------------------------------------------------------------------------------
+vtkpxTriangulatedStackSource::vtkpxTriangulatedStackSource()
+{
+  this->TriangulatedStack=new PXTriangulatedStack();
+  this->ColorMode=5;
+  this->ColorGamma=1.0;
+}
+//------------------------------------------------------------------------------
+vtkpxTriangulatedStackSource::~vtkpxTriangulatedStackSource()
+{
+  if (this->TriangulatedStack)
+      delete this->TriangulatedStack;
+
+}
+//------------------------------------------------------------------------------
+int vtkpxTriangulatedStackSource::Save(const char* fname)
+{
+  if (this->TriangulatedStack==NULL)
+      return 0;
+  return this->TriangulatedStack->Save(fname);
+}
+//------------------------------------------------------------------------------
+int vtkpxTriangulatedStackSource::Load(const char* fname)
+{
+  int ok=this->TriangulatedStack->Load(fname);
+  if (ok)
+    this->Modified();
+
+  return ok;
+}
+//------------------------------------------------------------------------------
+PXTriangulatedStack* vtkpxTriangulatedStackSource::GetTStack()
+{
+  return this->TriangulatedStack;
+}
+//------------------------------------------------------------------------------
+void vtkpxTriangulatedStackSource::Copy(vtkpxTriangulatedStackSource* other)
+{
+  this->TriangulatedStack->Copy(other->GetTStack());
+  this->Modified();
+}
+//------------------------------------------------------------------------------
+void vtkpxTriangulatedStackSource::SetFromSplineStackSource(vtkpxSplineStackSource* vtksur,float dist,
+							    float zmin,float zmax)
+{
+  PXFPBSplineStack* sur=vtksur->GetSplineStack();
+  int tb=sur->gettrimbottom();
+  int tt=sur->gettrimtop();
+  sur->autosettrims(zmin,zmax);
+
+  PXContourStack* stack=sur->exporttocontourstack(dist);
+  this->TriangulatedStack->setfromcontourstack(stack,0);
+  delete stack;
+  
+  sur->settrimbottom(tb);
+  sur->settrimtop(tt);
+  this->Modified();
+}
+//------------------------------------------------------------------------------
+void vtkpxTriangulatedStackSource::SetFromSplineStackSource2(vtkpxSplineStackSource* vtksur,float dist,float zdist,
+							    float zmin,float zmax)
+{
+  PXFPBSplineStack* sur=vtksur->GetSplineStack();
+  int tb=sur->gettrimbottom();
+  int tt=sur->gettrimtop();
+  sur->autosettrims(zmin,zmax);
+
+  fprintf(stderr,"Exporting to Contour Stack %.2f %.2f\n",dist,zdist);
+  PXContourStack* stack=NULL;
+  if (vtksur->GetPolarMode()==0)
+    {
+      stack=sur->exporttocontourstack(dist,zdist);
+    }
+  else
+    {
+      stack=sur->polarexporttocontourstack(vtksur->GetPolarMiddle(),dist);
+      stack->nonShrinkSmooth2D(dist,1.0,50);
+    }
+  this->TriangulatedStack->setfromcontourstack(stack,0);
+  delete stack;
+
+  sur->settrimbottom(tb);
+  sur->settrimtop(tt);
+  this->Modified();
+}
+//------------------------------------------------------------------------------
+void vtkpxTriangulatedStackSource::SetFromContourStack(PXContourStack* stack)
+{
+  this->TriangulatedStack->setfromcontourstack(stack,0);
+  this->Modified();
+}
+
+//------------------------------------------------------------------------------
+void vtkpxTriangulatedStackSource::ComputeCurvatures(int scale)
+{
+ if (this->TriangulatedStack->hasneighbours()==0)
+    this->TriangulatedStack->generateNeighbours(0);
+ this->TriangulatedStack->calculateCurvatures(scale);
+}
+//------------------------------------------------------------------------------
+void vtkpxTriangulatedStackSource::Execute()
+{
+  int nump=this->TriangulatedStack->getnumpoints();
+  int numt=this->TriangulatedStack->getnumtriangles();
+
+  if (nump<3 || numt < 1 )
+    return;
+
+  vtkPoints *points = vtkPoints::New();
+  points->SetNumberOfPoints(nump);
+
+  vtkFloatArray* norm=vtkFloatArray::New();
+  
+  int hascurvatures=this->TriangulatedStack->hascurvatures();
+  int hasnormals=this->TriangulatedStack->hasnormals();
+
+  if (hasnormals)
+    {
+      norm->SetNumberOfComponents(3);
+      norm->SetNumberOfTuples(nump);
+    }
+
+  for (int i=0;i<nump;i++)
+    {
+      PXTriangulatedStackPoint* point=this->TriangulatedStack->getpoint(i);
+      points->SetPoint(i,point->x[0],point->x[1],point->x[2]);
+      if (hasnormals)
+	{
+	  norm->SetComponent(i,0,point->nx[0]);
+	  norm->SetComponent(i,1,point->nx[1]);
+	  norm->SetComponent(i,2,point->nx[2]);
+	}
+    }
+
+  vtkCellArray *polys = vtkCellArray::New();
+
+  for (int j=0;j<numt;j++)
+    {
+      PXTriangle* tri=this->TriangulatedStack->gettriangle(j);
+      vtkIdType pp[3];
+      for (int ia=0;ia<=2;ia++)
+	pp[ia]=tri->p[ia];
+	
+      polys->InsertNextCell(3,pp);
+    }
+  
+
+  vtkPolyData *output = this->GetOutput();
+  output->SetPoints(points);
+  points->Delete();
+  output->SetPolys(polys);
+  polys->Delete();
+
+  if (hasnormals)
+    {
+      output->GetPointData()->SetNormals(norm);
+    }
+  norm->Delete();
+
+  if (hascurvatures>0 && this->ColorMode>=0)
+    {
+      vtkUnsignedCharArray* curvcolor=vtkUnsignedCharArray::New();
+      this->ComputeColors(curvcolor);
+      output->GetPointData()->SetScalars(curvcolor);
+      curvcolor->Delete();
+    }
+
+
+
+}
+//------------------------------------------------------------------------------
+void vtkpxTriangulatedStackSource::SetFromPolyData(vtkPolyData* polydata)
+{
+  if (polydata==NULL)
+    return;
+  
+  vtkTriangleFilter* filt=vtkTriangleFilter::New();
+  filt->SetInput(polydata);
+  filt->PassLinesOff();
+  filt->PassVertsOff();
+  filt->Update();
+
+  vtkPoints* pts=filt->GetOutput()->GetPoints();
+  vtkCellArray* cells=filt->GetOutput()->GetPolys();
+
+  int nump=pts->GetNumberOfPoints();
+  int numt=cells->GetNumberOfCells();
+  this->TriangulatedStack->init(nump,numt);
+
+  double p[3];
+  for (int ia=0;ia<nump;ia++)
+    {
+      PXTriangulatedStackPoint* pt=this->TriangulatedStack->getpoint(ia);
+      pts->GetPoint(ia,p);
+      for (int ib=0;ib<=2;ib++)
+	pt->x[ib]=p[ib];
+    }
+
+
+  cells->InitTraversal();
+  vtkIdType *ln,num;
+  for (int ic=0;ic<numt;ic++)
+    {
+      cells->GetNextCell(num,ln);
+      PXTriangle* tri=this->TriangulatedStack->gettriangle(ic);
+      for (int ib=0;ib<=2;ib++)
+	tri->p[ib]=ln[ib];
+    }
+
+  filt->Delete();
+}
+//------------------------------------------------------------------------------
+void vtkpxTriangulatedStackSource::NonShrinkSmooth(float alpha,float beta,int iterations)
+{
+  if (this->TriangulatedStack->hasneighbours()==0)
+    this->TriangulatedStack->generateNeighbours(0);
+  this->TriangulatedStack->nonShrinkSmooth(0.33,-0.34,iterations);
+}
+//------------------------------------------------------------------------------
+void vtkpxTriangulatedStackSource::Scale(float scale)
+{
+  this->TriangulatedStack->scalepoints(scale,scale,scale);
+}
+//------------------------------------------------------------------------------
+void vtkpxTriangulatedStackSource::LoadAndFitContourStack(const char* fname)
+{
+  PXContourStack* cnt=new PXContourStack();
+  int ok=cnt->Load(fname);
+  if (ok)
+    this->SetFromContourStack(cnt);
+  delete cnt;
+}
+  
+//------------------------------------------------------------------------------
+void vtkpxTriangulatedStackSource::ComputeColors(vtkUnsignedCharArray* colors)
+{
+  int numpoints=this->TriangulatedStack->getnumpoints();
+  float value=1.0,max_value=0.0,red,green,blue;
+
+  colors->SetNumberOfComponents(3);
+  colors->SetNumberOfTuples(numpoints);
+
+
+
+  int minpass=1;
+  if (this->ColorMode==4)
+    minpass=0;
+
+  for (int pass=minpass;pass<=1;pass++)
+    {
+      for (int i=0;i<numpoints;i++)
+	{
+	  PXTriangulatedStackPoint* point=this->TriangulatedStack->getpoint(i);
+
+	  switch (this->ColorMode)
+	    {  
+	      //(K=0, H=1, k1=2, k2=3, B=4, Index=5)
+	    case 0: // Gaussian
+	      value=point->k[0]*point->k[1];
+	      break;
+	    case 1: // Mean Curvature
+	      value=0.5*(point->k[0]+point->k[1]);
+	      break;
+	    case 2: // Principal Curvature 1
+	      value=point->k[0];
+	      break;
+	    case 3: // Principal Curvature 2
+	      value=point->k[1];
+	      break;
+	    case 4: // Bending Energy
+	      value=sqrt(0.5*(pow(point->k[0],float(2.0))+pow(point->k[1],float(2.0))));
+	      break;
+	    case 5: // Shape Index 
+	      if(point->k[0]==point->k[1])
+		  {
+		    if(point->k[0]>0.0)  value =  1.0;
+		    if(point->k[0]<0.0)  value = -1.0;
+		    if(point->k[0]==0.0) value =  0.0;
+		  }
+	      else
+		value = 2.0 / M_PI * atan((point->k[1]+point->k[0])/(point->k[1]-point->k[0]));
+	      break;
+	    }
+	  
+	  if (pass==0 && this->ColorMode==4)
+	    {
+	      if (i==0)
+		max_value=fabs(value);
+	      else
+		max_value=Fmax(fabs(value),max_value);
+	    }
+	  
+	  if (pass==1)
+	    {
+	      if (this->ColorMode==4)
+		{
+		  value=pow(value/max_value,float(1.0/this->ColorGamma));
+		  green=PXTriangulatedStack::bending_energy_lookup_green(value);
+		  red=PXTriangulatedStack::bending_energy_lookup_red(value);
+		  blue=PXTriangulatedStack::bending_energy_lookup_blue(value);
+		}
+	      else if (this->ColorMode==5)
+		{
+		  red=PXTriangulatedStack::shape_index_lookup_red(value);
+		  green=PXTriangulatedStack::shape_index_lookup_green(value);
+		  blue=PXTriangulatedStack::shape_index_lookup_blue(value);
+		}
+	      else
+		{
+		  value=Frange(value,-0.3,0.3);
+		  value=value/(0.6);
+		  float v=pow(fabs(value),float(1.0/this->ColorGamma));
+		  if (value<0.0)
+		    v=0.5-v;
+		  else
+		    v=0.5+v;
+		  v=Frange(v,0.0,1.0);
+		  red=PXTriangulatedStack::curvature_lookup_red(v);
+		  green=PXTriangulatedStack::curvature_lookup_green(v);
+		  blue=PXTriangulatedStack::curvature_lookup_blue(v);
+		}
+
+	      colors->SetTuple3(i,red*255.0,green*255.0,blue*255.0);
+	    }
+	}
+    }
+}
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxTriangulatedStackSource.h b/bioimagesuite30_src/Legacy/vtkpxTriangulatedStackSource.h
new file mode 100644
index 0000000..da3a8e5
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxTriangulatedStackSource.h
@@ -0,0 +1,149 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxTriangulatedStackSource 
+
+
+#ifndef __vtkpxTriangulatedStackSource_h
+#define __vtkpxTriangulatedStackSource_h
+
+#include "vtkPolyDataSource.h"
+#include "vtkpxSplineStackSource.h"
+#include "vtkUnsignedCharArray.h"
+
+class vtkPolyDataCollection;
+//BTX
+class PXTriangulatedStack;
+//ETX
+class vtkpxTriangulatedStackSource : public vtkPolyDataSource
+{
+public:
+  static vtkpxTriangulatedStackSource *New();
+  vtkTypeMacro(vtkpxTriangulatedStackSource,vtkPolyDataSource);
+
+  // Description:
+  // Initialization
+  virtual void Copy(vtkpxTriangulatedStackSource* other);
+  virtual void SetFromSplineStackSource(vtkpxSplineStackSource* sur,
+					float dist,float zmin=-1.0,float zmax=1000.0);
+  virtual void SetFromSplineStackSource2(vtkpxSplineStackSource* sur,
+					float dist,float zdist,float zmin=-1.0,float zmax=1000.0);
+
+  //BTX
+  // Description:
+  // Set From Contour Stack (For Internal use only)
+  virtual void SetFromContourStack(PXContourStack* cstack);
+  //ETX
+  
+
+  // Description:
+  // Set From Ordinary Poly Data ( Useful for computing curvatures)
+  virtual void SetFromPolyData(vtkPolyData* polydata);
+
+  // Description:
+  // Compute Curvatures
+  virtual void ComputeCurvatures(int scale);
+  virtual void NonShrinkSmooth(float alpha,float beta,int iterations);
+
+  // Description:
+  // I/O Code
+  virtual int Load(const char* fname);
+  virtual int Save(const char* fname);
+
+
+  // Description:
+  // Raw Data Structure Output
+  virtual PXTriangulatedStack* GetTStack();
+
+  // Description:
+  // Scale all in-plane points
+  virtual void Scale(float scale);
+
+  // Description:
+  virtual void LoadAndFitContourStack(const char* fname);
+
+  // Description:
+  // Modes for Strain Value / Color Mode 
+  vtkSetClampMacro(ColorMode,int,-1,5);
+  vtkGetMacro(ColorMode,int);
+
+  // Description:
+  // Modes for Strain Value / Color Gamma 
+  vtkSetClampMacro(ColorGamma,float,0.01,5);
+  vtkGetMacro(ColorGamma,float);
+
+
+
+
+protected:
+
+  vtkpxTriangulatedStackSource();
+  virtual ~vtkpxTriangulatedStackSource();
+  vtkpxTriangulatedStackSource(const vtkpxTriangulatedStackSource&) {};
+  void operator=(const vtkpxTriangulatedStackSource&) {};
+  
+  void Execute();
+  PXTriangulatedStack* TriangulatedStack;
+
+  void ComputeColors(vtkUnsignedCharArray* colors);
+
+  int ColorMode;
+  float ColorGamma;
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxTstackReader.cpp b/bioimagesuite30_src/Legacy/vtkpxTstackReader.cpp
new file mode 100644
index 0000000..06f6416
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxTstackReader.cpp
@@ -0,0 +1,241 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSurfaceUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxTstackReader.h"
+#include "vtkObjectFactory.h"
+#include "vtkPolyDataMapper.h"
+#include "vtkPolyData.h"
+#include "vtkPoints.h"
+#include "vtkCellArray.h"
+#include "pxutil.h"
+#include "vtkFloatArray.h"
+#include "vtkPointData.h"
+//------------------------------------------------------------------------------
+vtkpxTstackReader* vtkpxTstackReader::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxTstackReader");
+  if(ret)
+    {
+    return (vtkpxTstackReader*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxTstackReader;
+}
+
+
+vtkpxTstackReader::vtkpxTstackReader()
+{
+  this->Filename=NULL;
+}
+
+vtkpxTstackReader::~vtkpxTstackReader()
+{
+  if (this->Filename)
+      delete this->Filename;
+}
+
+
+// Specify file name of vtk polygonal data file to read.
+void vtkpxTstackReader::SetFileName(const char* name) 
+{
+  if (this->Filename)
+      delete this->Filename;
+
+  this->Filename=new char[strlen(name)+1];
+  strcpy(this->Filename,name);
+}
+char *vtkpxTstackReader::GetFileName() 
+{
+  return this->Filename;
+}
+
+void vtkpxTstackReader::Execute()
+{
+  vtkPolyData *output = this->GetOutput();
+  vtkDebugMacro(<<"Reading tstack data...");
+
+
+  gzFile fin=gzsuffixopen(this->Filename,"r");
+  if (!fin)
+    {
+      vtkErrorMacro(<<"Failed to read tstack from "<<this->Filename);
+      return;
+    }
+
+  vtkDebugMacro(<<"Reading "<<this->Filename);
+
+  char line[400];
+  gzgets(fin,line,200);
+  if (gzfindstringinstring(line, "#TriangulatedStack")==0)
+      {
+	gzclose(fin);
+	vtkErrorMacro(<<"Bad Header in "<<this->Filename);
+	return;
+      }
+
+
+  int npoints,ntriangles,connect,hasnormals,hascurvatures,ncntr;
+  gzgets(fin,line,200); sscanf(line,"#%d\n",&ncntr);
+  gzgets(fin,line,200); sscanf(line,"#%d\n",&npoints);
+  gzgets(fin,line,200); sscanf(line,"#%d\n",&ntriangles);
+  gzgets(fin,line,200); sscanf(line,"#%d\n",&connect);
+  gzgets(fin,line,200); sscanf(line,"#%d\n",&hasnormals);
+  gzgets(fin,line,200); sscanf(line,"#%d\n",&hascurvatures);
+
+  //init(npoints,ntriangles);
+
+  vtkDebugMacro(<<"Points = "<<npoints<<", Triangles = "<<ntriangles);
+  vtkDebugMacro(<<"Hasnormals="<<hasnormals<<", hascurvatures="<<hascurvatures);
+  if (npoints<1 || ntriangles<1)
+      {
+	vtkErrorMacro("Insufficient Data:: Points = "<<npoints<<", Triangles = "<<ntriangles);
+	gzclose(fin);
+	return;
+      }
+
+  if (ncntr>0)
+      {
+	gzgets(fin,line,200); 
+	for (int i=0;i<ncntr;i++)
+	    gzgets(fin,line,200);
+      }
+
+  
+  vtkPoints *points = vtkPoints::New();
+  points->SetNumberOfPoints(npoints);
+
+
+  vtkFloatArray* normals=NULL;
+  vtkFloatArray* curvatures=NULL;
+
+  if (hasnormals)
+    {
+      normals=vtkFloatArray::New();
+      normals->SetNumberOfComponents(3);
+      normals->SetNumberOfTuples(npoints);
+    }
+  if (hascurvatures)
+    {
+      curvatures=vtkFloatArray::New();
+      curvatures->SetNumberOfComponents(2);
+      curvatures->SetNumberOfTuples(npoints);
+    }
+
+  int i;
+  gzgets(fin,line,200); 
+  for (i=0;i<npoints;i++)
+      {
+	gzgets(fin,line,200);
+	int index;
+	float x[3],nx[3],k[2];
+	sscanf(line,"%d %f %f %f %f %f %f %f %f\n",
+	       &index,&x[0],&x[1],&x[2],
+	       &nx[0],&nx[1],&nx[2],&k[0],&k[1]);
+	points->SetPoint(i,x);
+	if (hasnormals)
+	  normals->SetTuple(i,nx);
+	if (hascurvatures)
+	  curvatures->SetTuple(i,k);
+      }
+  
+  vtkCellArray *polys = vtkCellArray::New();
+  gzgets(fin,line,200);
+  for (i=0;i<ntriangles;i++)
+      {
+	gzgets(fin,line,200);
+	int index,p[3];
+	sscanf(line,"%d %d %d %d\n",&index,&p[0],&p[1],&p[2]);
+	vtkIdType pp[3];
+	for (int ia=0;ia<=2;ia++)
+	  pp[ia]=p[ia];
+	polys->InsertNextCell(3,pp);
+      }
+  
+  if (output==NULL)
+      {
+	vtkErrorMacro("Null Output\n");
+	return;
+      }
+
+  vtkDebugMacro ("Setting Points\n");
+  
+  output->SetPoints(points);
+  points->Delete();
+  output->SetPolys(polys);
+  polys->Delete();
+
+  if (hasnormals)
+    {
+      output->GetPointData()->SetNormals(normals);
+      normals->Delete();
+    }
+
+  if (hascurvatures)
+    {
+      output->GetPointData()->SetScalars(curvatures);
+      curvatures->Delete();
+    }
+
+
+
+}
+
+
+void vtkpxTstackReader::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkPolyDataSource::PrintSelf(os,indent);
+}
+
diff --git a/bioimagesuite30_src/Legacy/vtkpxTstackReader.h b/bioimagesuite30_src/Legacy/vtkpxTstackReader.h
new file mode 100644
index 0000000..6b4ed2d
--- /dev/null
+++ b/bioimagesuite30_src/Legacy/vtkpxTstackReader.h
@@ -0,0 +1,105 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxTstackReader.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxTstackReader - reads .tstack files from disk
+// .SECTION Description
+// Reads files stored in .tstack format (optionally gzipped compressed .tstack.gz)
+// from disk
+// The output of this class is vtkPolyData
+// snakes
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats:
+// Uses the pxutil library
+// .SECTION See Also
+//  vtkPoints vtkPolyData vtkPolyDataSource 
+
+#ifndef __vtkpxTstackReader_h
+#define __vtkpxTstackReader_h
+
+#include "vtkPolyDataSource.h"
+#include "vtkDataReader.h"
+
+class vtkpxTstackReader : public vtkPolyDataSource
+{
+public:
+  static vtkpxTstackReader *New();
+  vtkTypeMacro(vtkpxTstackReader,vtkPolyDataSource);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+
+  // Description:
+  // Set / get the file name of vtk polygonal data file to read.
+  void  SetFileName(const char *name);
+  char *GetFileName();
+
+
+protected:
+
+  //BTX
+  char* Filename;
+
+  vtkpxTstackReader();
+  virtual ~vtkpxTstackReader();
+  vtkpxTstackReader(const vtkpxTstackReader&) {};
+  void operator=(const vtkpxTstackReader&) {};
+  
+  void Execute();
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Registration/CMakeLists.txt b/bioimagesuite30_src/Registration/CMakeLists.txt
new file mode 100644
index 0000000..4692e62
--- /dev/null
+++ b/bioimagesuite30_src/Registration/CMakeLists.txt
@@ -0,0 +1,224 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+# ------------------------------------------------------------------------
+#
+# Some of the code in this directory file derives from original work
+# in the vtkCISG Toolkit
+# that was released under the terms of 
+# the GNU General Public License (either version 2,
+# of the License, or any later version.)
+# 
+#  Authors   : Thomas Hartkens <thomas at hartkens.de>
+#              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+#	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+#	        under the supervision of Dave Hawkes and Derek Hill
+#  Web       : http:#www.image-registration.com
+#  Copyright : King's College London
+#              Div. of Radiological Sciences, 
+#              Computational Imaging Science Group, 1997 - 2000
+#	        http://www-ipg.umds.ac.uk/cisg
+#
+# -----------------------------------------------------------------------
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+SET(KITBASE Registration)
+SET(KIT vtkpx${KITBASE})
+
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/${KITBASE})
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Imaging)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Graphics)
+INCLUDE_DIRECTORIES(${ITK_INCLUDE_DIRS})
+
+SET (KITSRCS
+# Basic Code
+vtkpxTransformationUtil.cpp
+vtkbisTransformationTestUtil.cpp
+vtkpxJointHistogram.cpp
+vtkpxRegistration.cpp
+vtkpxSparseMatrix.cpp
+#
+# Transformation
+#
+vtkpxLinearTransform.cpp
+vtkpxBaseGridTransform.cpp
+vtkpxGridTransform.cpp
+vtkpxComboTransform.cpp
+vtkpxWeightedLandmarkTransform.cpp
+
+#
+# Intensity Based
+#
+vtkpxAbstractIntensityRegistration.cpp
+vtkpxLinearRegistration.cpp
+vtkpxMidlineSymmetricRegistration.cpp
+vtkpxNonLinearRegistration.cpp
+vtkpxNonLinearLabelRegistration.cpp
+vtkpxDistortionCorrection.cpp
+# 
+# RPM Stuff
+#
+vtkpxRPMCorrespondenceFinder.cpp
+vtkpxAbstractRPMRegistration.cpp
+vtkpxLinearRPMRegistration.cpp
+vtkpxTPSRPMRegistration.cpp
+vtkpxBSplineRPMRegistration.cpp
+vtkpxBSplinePriorRPMRegistration.cpp
+#
+# Integrated Stuff
+#
+vtkpxNonLinearIntegratedRegistration.cpp
+#
+vtkpxLinearMotionCorrect.cpp
+vtkokKochCoefficientSource.cpp
+#
+vtkpxSimilarityTransform.cpp
+vtkpxPolyAbstractTransform.cpp
+vtkpxPolySimilarityTransform.cpp
+vtkpxArticulatedJointTransform.cpp
+
+
+
+)
+
+SET_SOURCE_FILES_PROPERTIES(
+vtkpxBaseGridTransform.cpp
+ABSTRACT
+)
+
+# Excluded TCL Code 
+
+
+
+# ----------------------------------------------
+# CUDA Conditional Compilation
+# -----------------------------------------------
+
+IF (BIOIMAGESUITE3_USE_CUDA)
+
+  SET (KITSRCS
+   ${KITSRCS}
+   vtkbisCUDAFloatVector.cpp
+   vtkbisCUDAOptimizer.cpp
+   vtkbisCUDATestOptimizer.cpp
+   vtkbisCUDAJointHistogram.cpp
+   vtkbisCUDAApproximateGridTransform.cpp
+   vtkbisCUDALinearRegistration.cpp
+   vtkbisCUDANonLinearRegistration.cpp
+   vtkbisCUDARegistrationUtil.cpp)
+ 
+  SET(CUDAKIT vtkpx${KITBASE}_Cuda)
+
+  CUDA_INCLUDE_DIRECTORIES(
+    ${CMAKE_CURRENT_SOURCE_DIR}
+    )
+  
+  
+  CUDA_ADD_LIBRARY(${CUDAKIT} STATIC 
+    koch.cu
+    warmup.cu   
+    linearreslice.cu 
+    biscudabendingenergy.cu
+    biscudaregistrationutil.cu
+    biscudajointhistogram.cu
+    biscudavectorutil.cu
+    )
+  TARGET_LINK_LIBRARIES (${CUDAKIT} ${KITLIBS})
+  install (TARGETS ${CUDAKIT} DESTINATION lib)
+
+  SET_SOURCE_FILES_PROPERTIES(
+    #ssd.cu  
+    koch.cu
+    warmup.cu   
+ # demonregistration.cu
+    linearreslice.cu 
+bisCUDA_BendingEnergy.cu 
+    WRAP_EXCLUDE
+    )
+
+  INCLUDE_DIRECTORIES(${CUDA_INSTALL_PREFIX}/../include)
+  INCLUDE_DIRECTORIES(${FOUND_CUDA_NVCC_INCLUDE})
+  
+ELSE (BIOIMAGESUITE3_USE_CUDA)
+  SET (CUDAKIT )
+ENDIF (BIOIMAGESUITE3_USE_CUDA)
+# -----------------------------------------------
+
+
+SET(KITLIBS
+  numerics
+  vtkpxCommon
+  ${CUDAKIT}
+  vtkpxImaging
+  vtkpxLegacy
+  vtkpxCommonTCL
+  vtkCommonTCL
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+)
+
+SET(KITJAVALIBS
+  numerics
+  vtkpxCommon
+  ${CUDAKIT}
+  vtkpxImaging
+  vtkpxLegacy
+  vtkpxCommonJava
+   ${BIOIMAGESUITE3_COMMON_JAVALIBS}
+)
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+
+IF (BIOIMAGESUITE3_USE_CUDA)
+SET (KITEXTRAFILES
+Registration/linearreslice.cu 
+Registration/warmup.cu   			      
+Registration/dvSparseMatrix.h
+Registration/koch.cu
+Registration/biscudaregistrationutil.cu
+Registration/biscudaregistrationutil.h
+Registration/biscudajointhistogram.cu
+Registration/biscudajointhistogram.h
+Registration/biscudabendingenergy.cu
+Registration/biscudavectorutil.cu
+)
+ENDIF (BIOIMAGESUITE3_USE_CUDA)
+
+SET (KITTCLSRCS )
+bis_complex("Registration" ${KIT} ${FILELIST})
+
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkbisTransformationTestUtil.cpp b/bioimagesuite30_src/Registration/vtkbisTransformationTestUtil.cpp
new file mode 100644
index 0000000..6d359a5
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkbisTransformationTestUtil.cpp
@@ -0,0 +1,212 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkDataArray.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkMath.h"
+#include "vtkbisTransformationTestUtil.h"
+#include "vtkPointData.h"
+#include "vtkCellData.h"
+#include "vtkCellArray.h"
+
+
+// ---------------------------
+
+vtkbisTransformationTestUtil* vtkbisTransformationTestUtil::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisTransformationTestUtil");
+  if(ret)
+      {
+	return (vtkbisTransformationTestUtil*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisTransformationTestUtil;
+}
+
+vtkbisTransformationTestUtil::vtkbisTransformationTestUtil()
+{
+  this->ClearStatus();
+}
+
+const char* vtkbisTransformationTestUtil::ReturnStatus() 
+{
+  return this->Status.c_str();
+}
+
+void vtkbisTransformationTestUtil::ClearStatus()
+{
+  this->Status="";
+}
+
+
+// ----------------------------------------------------------------------------------------------------
+//
+//  Core Method
+//
+// ----------------------------------------------------------------------------------------------------
+int vtkbisTransformationTestUtil::CompareTransformations(vtkAbstractTransform* tr1,vtkAbstractTransform* tr2)
+{
+  return this->CompareTransformations(tr1,tr2,0.001);
+}
+
+int vtkbisTransformationTestUtil::CompareTransformations(vtkAbstractTransform* tr1,vtkAbstractTransform* tr2,double threshold)
+{
+  if (tr1==NULL && tr2==NULL)
+    return 1;
+
+  if (tr1==NULL || tr2==NULL)
+    return 0;
+
+
+  const char* name1=tr1->GetClassName();
+  const char* name2=tr2->GetClassName();
+  if (strcmp(name1,name2)!=0)
+    return 0;
+
+  if (tr1->IsA("vtkHomogeneousTransform")==1)
+    return this->CompareHomogeneousTransformations((vtkHomogeneousTransform*)tr1,
+					      (vtkHomogeneousTransform*)tr2,
+					      threshold);
+
+  if (tr1->IsA("vtkThinPlateSplineTransform"))
+    return this->CompareThinPlateSplineTransformations((vtkThinPlateSplineTransform*)tr1,
+						       (vtkThinPlateSplineTransform*)tr2,
+						       threshold);
+
+  if (tr1->IsA("vtkpxComboTransform"))
+    return this->CompareComboTransformations((vtkpxComboTransform*)tr1,
+								     (vtkpxComboTransform*)tr2,
+								     threshold);
+  if (tr1->IsA("vtkGridTransform"))
+    return this->CompareGridTransformations((vtkGridTransform*)tr1,
+								    (vtkGridTransform*)tr2,
+								    threshold);
+  
+  return 0;
+
+}
+// ----------------------------------------------------------------------------------------------------
+int vtkbisTransformationTestUtil::CompareHomogeneousTransformations(vtkHomogeneousTransform* tr1,
+								vtkHomogeneousTransform* tr2,
+								double threshold)
+{
+  vtkMatrix4x4* mat1=tr1->GetMatrix();
+  vtkMatrix4x4* mat2=tr2->GetMatrix();
+
+  double maxd=0.0;
+  for (int ia=0;ia<=3;ia++)
+    for (int ib=0;ib<=3;ib++)
+      {
+	double v=fabs(mat1->GetElement(ia,ib)-mat2->GetElement(ia,ib));
+	if (v>maxd)
+	  maxd=v;
+      }
+
+  sprintf(this->Buffer," Comparing 4x4 Matrix max=%.5f, thr=%.5f",maxd,threshold);
+  this->Status+=Buffer;
+  if (maxd>threshold)
+    return 0;
+
+  return 1;
+}
+
+// ----------------------------------------------------------------------------------------------------
+int vtkbisTransformationTestUtil::CompareThinPlateSplineTransformations(vtkThinPlateSplineTransform* tr1,
+								    vtkThinPlateSplineTransform* tr2,
+								    double threshold)
+{
+  if (tr1->GetBasis()!=tr2->GetBasis())
+    return 0;
+
+  vtkPoints* pt1=tr1->GetSourceLandmarks();
+  vtkPoints* pt2=tr2->GetSourceLandmarks();
+
+  vtkbisTestUtil* ut=vtkbisTestUtil::New();
+  ut->ClearStatus();
+  int ok=ut->ComparePoints(pt1,pt2,threshold);
+  this->Status+=ut->ReturnStatus();
+  ut->Delete();
+  return ok;
+}
+// ----------------------------------------------------------------------------------------------------
+int vtkbisTransformationTestUtil::CompareGridTransformations(vtkGridTransform* tr1,
+							     vtkGridTransform* tr2,
+							     double threshold)
+{
+  if (tr1->GetInterpolationMode()!=tr2->GetInterpolationMode())
+    return 0;
+
+  vtkImageData* im1=tr1->GetDisplacementGrid();
+  vtkImageData* im2=tr2->GetDisplacementGrid();
+  vtkbisTestUtil* ut=vtkbisTestUtil::New();
+  ut->ClearStatus();
+  int ok=ut->CompareImages(im1,im2,threshold);
+  this->Status+=ut->ReturnStatus();
+  ut->Delete();
+  return ok;
+}
+// ----------------------------------------------------------------------------------------------------
+int vtkbisTransformationTestUtil::CompareComboTransformations(vtkpxComboTransform* tr1,
+							      vtkpxComboTransform* tr2,
+							      double threshold)
+{
+  if (tr1->GetNonLinearFirst()!=tr2->GetNonLinearFirst())
+    return 0;
+
+  int ok2=this->CompareHomogeneousTransformations(tr1->GetLinearTransform(),
+									  tr2->GetLinearTransform(),
+									  threshold);
+  if (ok2==0)
+    return 0;
+
+
+  int n1=tr1->GetNumberOfGridTransformations();
+  int n2=tr2->GetNumberOfGridTransformations();
+  if (n1!=n2)
+    return 0;
+
+
+
+  for (int ia=0;ia<n1;ia++)
+    {
+      int ok=this->CompareGridTransformations(tr1->GetGridTransformByIndex(ia),
+					      tr2->GetGridTransformByIndex(ia),
+					      threshold);
+      if (ok==0)
+	return 0;
+    }
+
+  return 1;
+}
+
+
diff --git a/bioimagesuite30_src/Registration/vtkbisTransformationTestUtil.h b/bioimagesuite30_src/Registration/vtkbisTransformationTestUtil.h
new file mode 100644
index 0000000..d04d694
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkbisTransformationTestUtil.h
@@ -0,0 +1,96 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkbisTransformationTestUtil_h
+#define __vtkbisTransformationTestUtil_h
+
+#include "vtkObject.h"
+#include "vtkDataArray.h"
+#include "vtkImageData.h"
+#include "vtkbisTestUtil.h"
+#include "vtkpxTransformationUtil.h"
+#include "vtkAbstractTransform.h"
+#include "vtkHomogeneousTransform.h"
+#include "vtkThinPlateSplineTransform.h"
+#include "vtkpxGridTransform.h"
+#include "vtkpxComboTransform.h"
+
+class vtkbisTransformationTestUtil : public vtkObject
+{
+public:
+  static vtkbisTransformationTestUtil *New();
+  vtkTypeMacro(vtkbisTransformationTestUtil,vtkObject);
+  
+  // -------------------------------------------------------
+  // Compare Image and Surfaces
+  // -------------------------------------------------------
+
+  int CompareTransformations(vtkAbstractTransform* tr1,vtkAbstractTransform* tr2);
+  int CompareTransformations(vtkAbstractTransform* tr1,vtkAbstractTransform* tr2,double threshold);
+
+  int CompareHomogeneousTransformations(vtkHomogeneousTransform* tr1,
+					       vtkHomogeneousTransform* tr2,
+					       double threshold);
+
+  
+  int CompareThinPlateSplineTransformations(vtkThinPlateSplineTransform* tr1,
+						   vtkThinPlateSplineTransform* tr2,
+						   double threshold);
+  
+  
+  
+
+  int CompareGridTransformations(vtkGridTransform* tr1,
+					vtkGridTransform* tr2,
+					double threshold);
+  
+  
+  int CompareComboTransformations(vtkpxComboTransform* tr1,
+					 vtkpxComboTransform* tr2,
+					 double threshold);
+  
+  
+  const char* ReturnStatus();
+  void ClearStatus();
+  
+
+protected:
+  //BTX
+  vtkbisTransformationTestUtil();
+
+  std::string Status;
+  char Buffer[200];
+  //ETX
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkokKochCoefficientSource.cpp b/bioimagesuite30_src/Registration/vtkokKochCoefficientSource.cpp
new file mode 100644
index 0000000..332def7
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkokKochCoefficientSource.cpp
@@ -0,0 +1,439 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkokKochCoefficientSource.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkImageData.h"
+#include "vtkImageFFT.h"
+#include "vtkImageRFFT.h"
+#include "vtkImageMathematics.h"
+#include "vtkImageShiftScale.h"
+#include "vtkImagePermute.h"
+#include "vtkDataArray.h"
+#include "vtkExtractVOI.h"
+#include "vtkImageAccumulate.h"
+#include "vtkImageThreshold.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkInformation.h"
+#include "pxisinf.h"
+
+vtkCxxRevisionMacro(vtkokKochCoefficientSource, "$Revision: 1.00 $");
+vtkStandardNewMacro(vtkokKochCoefficientSource);
+
+//----------------------------------------------------------------------------
+vtkokKochCoefficientSource::vtkokKochCoefficientSource()
+{
+  this->ScaleFactorOfDisplacement=1000.0;
+  this->B0=1.0;
+  this->OutputScalarType = VTK_DOUBLE;
+  this->mode= 0;
+
+  this->ImageFFT               = vtkImageData::New();
+  this->ImageCoefficient       = vtkImageData::New();
+  this->ImageMultiplied        = vtkImageData::New();
+  this->ImageRFFT              = vtkImageData::New();
+  this->InducedField           = vtkImageData::New();
+  this->CoefficientMap         = vtkImageData::New();
+  this->Padding=20;
+}
+
+//----------------------------------------------------------------------------
+vtkokKochCoefficientSource::~vtkokKochCoefficientSource(){
+    this->ImageFFT->Delete();
+    this->ImageCoefficient->Delete();
+    this->ImageMultiplied->Delete();
+    this->ImageRFFT->Delete();
+    this->InducedField->Delete();
+    this->CoefficientMap->Delete();
+
+  };
+
+//----------------------------------------------------------------------------
+void vtkokKochCoefficientSource::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+
+  os << indent << "OutputScalarType: " << this->OutputScalarType << "\n";
+}
+//----------------------------------------------------------------------------
+// Compute the "Coeffcient Image" Ck(kx,ky,kz) of
+// B_dz(kx,ky,kz) = B0 * Ck(kx,ky,kz) * Chi(kx,ky,kz)
+// where
+// B_dz() : induced field caused by target susceptibility in fourier domain
+// B0     : static magnetic field
+// Chi()  : susceptibility in fourier domain
+//
+// In case the argument "mode" is set to nonzero value, small value will be 
+// assigned to voxels whose values are zero according to the above formula.
+// This computation
+// Refer to (10) of "Rapid calculations of susceptibility-induced magnetic field
+// perturbations for in vivo magnetic resonance", Koch et al,Phys. Med.BioL 
+// 51(2006)6831-6402
+//----------------------------------------------------------------------------
+template <class IT,class OT>
+void vtkokKochCoefficientSourceExecute(vtkokKochCoefficientSource *self,
+				       vtkImageData *input,vtkImageData* output,
+				       int mode,
+				       IT *,OT* )
+{
+  double tmpx,tmpy,tmpz,denom;
+  OT outVal;
+
+  int extent[6]; input->GetExtent(extent);
+  OT* ptr = (OT*)output->GetScalarPointerForExtent(extent);
+
+  fprintf(stderr,"In Source Execute %d:%d %d:%d %d:%d\n",
+	  extent[0],extent[1],extent[2],extent[3],extent[4],extent[5]);
+
+  //center of the fourier space
+  float c0 = 0.5*(extent[0]+extent[1]);
+  float c1 = 0.5*(extent[2]+extent[3]);
+  float c2 = 0.5*(extent[4]+extent[5]);
+
+  double spacing[3];
+  output->GetSpacing(spacing);
+
+  int min0 = extent[0];
+  int max0 = extent[1];
+
+  vtkIdType inc0, inc1, inc2;
+
+  output->GetContinuousIncrements(extent, inc0, inc1, inc2);
+  inc0 = 2;
+
+  printf("center = %f %f %f \n",c0,c1,c2);
+  printf("extent = %d %d %d %d %d %d \n",extent[0],extent[1],extent[2],extent[3],extent[4],extent[5]);
+  //printf("inc = %d %d %d \n",(int)inc0,inc1,inc2);
+  cout << "inc = " << inc0 << " " << inc1 << " " << inc2 << endl;
+
+  printf("spacing = %f %f %f \n",spacing[0],spacing[1],spacing[2]);
+  double tmp0,tmp1,tmp2;
+
+  tmp0 = spacing[0]*spacing[0];
+  tmp1 = spacing[1]*spacing[1];
+  tmp2 = spacing[2]*spacing[2];
+
+  for (int idx2 = extent[4]; idx2 <= extent[5]; ++idx2)
+    {
+      tmpz = (idx2<c2)?(idx2*idx2*tmp2):((extent[5]-idx2)*(extent[5]-idx2)*tmp2);
+      for (int idx1 = extent[2]; idx1 <= extent[3]; ++idx1)
+	{
+	  tmpy = (idx1<c1)?(idx1*idx1*tmp1):((extent[3]-idx1)*(extent[3]-idx1)*tmp1);
+	  for (int idx0 = extent[0]; idx0 <= extent[1]; ++idx0)
+	    {
+	      tmpx = (idx0<c0)?(idx0*idx0*tmp0):((extent[1]-idx0)*(extent[1]-idx0)*tmp0);
+	      denom = tmpx + tmpy + tmpz;
+	      if (denom == 0 )
+		{
+		  outVal = (OT)0.0;
+		}
+	      else
+		{
+		  outVal = (OT)((1.0/3.0 - tmpz/(tmpx+tmpy+tmpz)));
+		}
+	      if (mode == 0 )
+		{
+		  *ptr = outVal;
+		  ptr+=inc0;
+		}
+	      else 
+		{ 
+		  double epsilon=0.01;
+		  if(outVal < epsilon && outVal > -epsilon)
+		    outVal = OT(epsilon);
+		  *ptr++ = outVal;
+		  *ptr++ = outVal;
+		}
+	    }
+	  ptr += inc1;
+	}
+      ptr += inc2;
+    }
+  fprintf(stderr,"Done Source Execute\n");
+}
+
+
+
+
+//----------------------------------------------------------------------------
+//  Compute induced displacement field from susceptibility map
+//  Input  : this->Input 
+//  Coefficient Source == KochCoefficient
+//  Output : this->Output
+//----------------------------------------------------------------------------
+
+vtkImageData* vtkokKochCoefficientSource::EstimateInductionField(vtkImageData* SusceptibilityField,
+								 vtkImageData* KochCoefficient)
+{
+   //Compute fourier transform Chi(kx,ky,kz) of susceptibility map 
+   vtkDebugMacro(<<"#FFT");
+   vtkImageFFT *fftfilter = vtkImageFFT::New();
+   fftfilter->SetDimensionality(3);
+   fftfilter->SetInput(SusceptibilityField);
+   fftfilter->Update();
+   this->ImageFFT->ShallowCopy(fftfilter->GetOutput());
+   this->ImageFFT->SetSpacing(KochCoefficient->GetSpacing());
+
+   // Compute the "Coeffcient Image" Ck(kx,ky,kz)
+
+   vtkDebugMacro(<<"#Image Coefficient");
+   this->ImageCoefficient->ShallowCopy(KochCoefficient);
+
+   //Compute Ck(kx,ky,kz) * Chi(kx,ky,kz)
+
+   vtkDebugMacro(<<"#Multiply Coefficient");
+   this->ImageMultiplied->ShallowCopy(this->ImageCoefficient);
+   vtkImageMathematics *math = vtkImageMathematics::New();
+   math->SetInput1(this->ImageCoefficient);
+   math->SetInput2(this->ImageFFT);
+   math->SetOperationToComplexMultiply();
+   math->Update();
+   this->ImageMultiplied->ShallowCopy(math->GetOutput());
+
+   //Compute Inverse transform of Ck(kx,ky,kz) * Chi(kx,ky,kz)
+   //which equals B_dz(x,y,z)*B0^(-1)
+   //where B_dz(x,y,z) is the induced field and B0 is the static
+   //magnetic field
+
+   vtkDebugMacro(<<"#Inverse fft");
+   vtkImageRFFT* rfft = vtkImageRFFT::New();
+   rfft->SetDimensionality(3);
+   rfft->SetInput(this->ImageMultiplied);
+   rfft->Update();
+   this->ImageRFFT->ShallowCopy(rfft->GetOutput());
+   this->ImageRFFT->SetSpacing(SusceptibilityField->GetSpacing());
+
+   //Compute induced field B_dz(x,y,z)
+   vtkDebugMacro(<<"#Induced Field");
+   //ImageRFFT:[ppm  ]
+   //c:[Hz]=[T]*[Hz/T]
+   double c = 1.0*this->B0;
+   printf("c = %f\n",c);
+   vtkImageShiftScale* scale = vtkImageShiftScale::New();
+   scale->SetScale(c);
+   scale->SetInput(this->ImageRFFT);
+   scale->Update();
+   this->InducedField->ShallowCopy(scale->GetOutput());
+
+   //Convert unit from induced field to displacement field
+   vtkDebugMacro(<<"#Displacement Field");
+   vtkDataArray* data1 = this->ImageRFFT->GetPointData()->GetScalars();
+
+   
+   double mean=0.0;
+   if(this->MeanDisplacementToZero)
+     {
+       vtkDebugMacro(<<"Computing Mean ");
+       vtkDataArray* arr=SusceptibilityField->GetPointData()->GetScalars();
+       int nt=arr->GetNumberOfTuples();
+       int nv=0.0;
+
+       for (int i=0;i<nt;i++)
+	 {
+	   double v=arr->GetComponent(i,0);
+	   if (fabs(v+9.0)<0.01)
+	     {
+	       nv++;
+	       mean+=data1->GetComponent(i,0);
+	     }
+	 }
+       if(nv>0) mean/=nv;
+       fprintf(stderr,"mean = %f\n",mean);
+   } 
+
+   //shift image so that the average of VOI becomes zero.
+
+   vtkImageData* dispfield=vtkImageData::New();
+   dispfield->ShallowCopy(this->ImageRFFT);
+   dispfield->SetScalarType(this->OutputScalarType);
+   dispfield->AllocateScalars();
+
+
+   vtkDataArray* arr=dispfield->GetPointData()->GetScalars();
+   int nt=arr->GetNumberOfTuples();
+   for (int i=0;i<nt;i++)
+     {
+       double v=data1->GetComponent(i,0);
+       arr->SetComponent(i,0,v-mean);
+     }
+   fftfilter->Delete();
+   math->Delete();
+   rfft->Delete();
+   scale->Delete();
+
+
+   return dispfield;
+
+}
+//----------------------------------------------------------------------------
+vtkImageData* vtkokKochCoefficientSource::PadImage(vtkImageData* img,int padsize)
+{
+  vtkImageReslice* resl=vtkImageReslice::New();
+  resl->SetInput(img);
+
+  int dim[3]; img->GetDimensions(dim);
+  int paddim[3];
+  for (int i=0;i<=2;i++)
+    paddim[i]=2*padsize+dim[i];
+
+
+  double ori[3];  img->GetOrigin(ori);
+  double spa[3];  img->GetSpacing(spa);
+  double neworigin[3];
+  if (this->Debug)
+    fprintf(stderr,"\t Padding = (%d,%d,%d) ori=(%.1f,%.1f,%.1f) spa=(%.1f,%.1f,%.1f)\n",
+	    dim[0],	  dim[1],	  dim[2],
+	    ori[0],	  ori[1],	  ori[2],
+	    spa[0],	  spa[1],	  spa[2]);
+
+  
+  for (int ia=0;ia<=2;ia++)
+    {
+      int offset=(paddim[ia]-dim[ia])/2;
+      neworigin[ia]=ori[ia];//-spa[ia]*double(offset);
+    }
+  
+
+  resl->SetOutputExtent(0,paddim[0]-1,0,paddim[1]-1,0,paddim[2]-1);
+  resl->SetOutputOrigin(neworigin);
+  resl->SetOutputSpacing(spa);
+
+  resl->SetInterpolationMode(0);
+  resl->SetBackgroundLevel(0.0);
+  resl->Update();
+  
+  vtkImageData* out=vtkImageData::New();
+  out->ShallowCopy(resl->GetOutput());
+  resl->Delete();
+
+  out->GetDimensions(dim);
+  out->GetOrigin(ori);
+  out->GetSpacing(spa);
+
+  if (this->Debug)
+    fprintf(stderr,"\t Padding Done = (%d,%d,%d) ori=(%.1f,%.1f,%.1f) spa=(%.1f,%.1f,%.1f)\n",
+	    dim[0],	  dim[1],	  dim[2],
+	    ori[0],	  ori[1],	  ori[2],
+	    spa[0],	  spa[1],	  spa[2]);
+  
+  return out;
+}
+
+//----------------------------------------------------------------------------
+int vtkokKochCoefficientSource::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+						    vtkInformationVector *outputVector)
+{
+  vtkInformation *inInfo =  inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  int wholeExtent[6]; inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
+  double sp[3];  inInfo->Get(vtkDataObject::SPACING(), sp);
+  double origin[3];  inInfo->Get(vtkDataObject::ORIGIN(),  origin);
+
+  outInfo->Set(vtkDataObject::ORIGIN(),  origin, 3);
+  outInfo->Set(vtkDataObject::SPACING(),sp , 3);
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6);
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), this->OutputScalarType, 1);
+
+  return 1;
+}
+//----------------------------------------------------------------------------
+template <class T>
+void vtkokKochCoefficientSourceExecute1(vtkokKochCoefficientSource *self,
+					vtkImageData *inData,
+					vtkImageData *outData,int mode,
+					T *)
+{
+  fprintf(stderr,"In Simple Execute 1\n");
+  switch (outData->GetScalarType())
+    {
+      vtkTemplateMacro6(vtkokKochCoefficientSourceExecute, self, inData,
+			outData,mode,
+			static_cast<T *>(0), static_cast<VTK_TT *>(0));
+    default:
+      vtkGenericWarningMacro("Execute: Unknown input ScalarType");
+      return;
+    }
+}
+
+void vtkokKochCoefficientSource::SimpleExecute(vtkImageData* input,vtkImageData *output)
+{
+  fprintf(stderr,"In Simple Execute\n");
+
+
+
+  // Pad Input by a number of voxels
+  // 
+  vtkImageData* paddedinput=this->PadImage(input,this->Padding);
+
+
+  double FOV[3];
+  int wholeExtent[6]; paddedinput->GetWholeExtent(wholeExtent);
+  FOV[0] = (wholeExtent[1] - wholeExtent[0] +1);
+  FOV[1] = (wholeExtent[3] - wholeExtent[2] +1);
+  FOV[2] = (wholeExtent[5] - wholeExtent[4] +1);
+
+  double sp[3];     sp[0]=2*M_PI/FOV[0];  sp[1]=2*M_PI/FOV[1];  sp[2]=2*M_PI/FOV[2];
+  double origin[3]; paddedinput->GetOrigin(origin);
+  int    dim[3];    paddedinput->GetDimensions(dim);
+
+
+  this->CoefficientMap->CopyStructure(paddedinput);
+  this->CoefficientMap->SetOrigin(origin);
+  this->CoefficientMap->SetDimensions(dim);
+  this->CoefficientMap->SetNumberOfScalarComponents(2);
+  this->CoefficientMap->SetScalarType(this->OutputScalarType);
+  this->CoefficientMap->AllocateScalars();
+
+  switch (paddedinput->GetScalarType())
+    {
+      vtkTemplateMacro5(vtkokKochCoefficientSourceExecute1,
+			this,paddedinput,this->CoefficientMap,this->mode,
+			static_cast<VTK_TT *>(0));
+    default:
+      vtkErrorMacro("Execute: Unknown output ScalarType");
+    }
+
+  vtkDebugMacro(<<"vtkokKochCoefficientSourceExecute done..");
+
+  vtkImageData* tmpout=this->EstimateInductionField(paddedinput,this->CoefficientMap);
+
+  vtkImageReslice* resl=vtkImageReslice::New();
+  resl->SetInformationInput(input);
+  resl->SetInput(tmpout);
+  resl->SetInterpolationMode(0);
+  resl->SetBackgroundLevel(0.0);
+  resl->Update();
+  
+  output->ShallowCopy(resl->GetOutput());
+  resl->Delete();
+  // Unpad Output .....
+}
+
+
diff --git a/bioimagesuite30_src/Registration/vtkokKochCoefficientSource.h b/bioimagesuite30_src/Registration/vtkokKochCoefficientSource.h
new file mode 100644
index 0000000..4892d5d
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkokKochCoefficientSource.h
@@ -0,0 +1,218 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// .NAME vtkokKochCoefficientSource - Compute displacement field caused
+//  by target susceptibility based on Koch Koch's model.
+//  Input  : SusceptibilityField 
+//  Output : DisplacementField
+// .SECTION Description
+// Take susceptibility map as input, estimate induced field and displacement 
+// field based on Koch Koch's model. You need to create susceptibility map
+// in advance.
+// Refer to (10) of "Rapid calculations of susceptibility-induced magnetic field
+// perturbations for in vivo magnetic resonance", Koch Koch et al,Phys. Med.BioL 
+// 51(2006)6831-6402
+
+
+#ifndef __vtkokKochCoefficientSource_h
+#define __vtkokKochCoefficientSource_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+
+#define OLD_SOURCE 0
+
+class vtkokKochCoefficientSource : public vtkSimpleImageToImageFilter
+{
+public:
+  static vtkokKochCoefficientSource *New();
+  vtkTypeRevisionMacro(vtkokKochCoefficientSource,vtkSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);   
+  
+  // Description:
+  // Chi(kx,ky,kz),fourier transform of the susceptibility field
+  vtkGetObjectMacro(ImageFFT,vtkImageData);
+
+  // Description:
+  // coefficient image Ck(kx,ky,kz) in the fourier domain
+  vtkGetObjectMacro(ImageCoefficient,vtkImageData);
+
+  // Description:
+  // Chi(kx,ky,kz) * Ck(kx,ky,kz)
+  vtkGetObjectMacro(ImageMultiplied,vtkImageData);
+
+  // Description:
+  //Inverse transform of Ck(kx,ky,kz) * Chi(kx,ky,kz)
+  //which equals B_dz(x,y,z)*B0^(-1)
+  vtkGetObjectMacro(ImageRFFT,vtkImageData);
+
+  // Description:
+  //induced field B_dz(x,y,z)
+  vtkGetObjectMacro(InducedField,vtkImageData);
+  
+  // Description:
+  // displacement field
+  vtkGetObjectMacro(CoefficientMap,vtkImageData);
+
+  // Description:
+  // scaling factor to convert from induced field to displacement field
+  vtkSetMacro(ScaleFactorOfDisplacement,float);
+
+  // Description:
+  //static magnetic field
+  vtkSetMacro(B0,float);
+  vtkGetMacro(B0,float);
+
+
+  // Description:
+  vtkSetMacro(OutputScalarType,int);
+  vtkGetMacro(OutputScalarType,int);
+
+  // Description:
+  // If set to 1, average displacement in the BrainVOI will 
+  // be caribrated as zero
+  vtkSetMacro(MeanDisplacementToZero,int);
+  vtkGetMacro(MeanDisplacementToZero,int);
+
+  void SetMeanDisplacementToZeroOn()
+    {this->SetMeanDisplacementToZero(1);}
+  void SetMeanDisplacementToZeroOff()
+    {this->SetMeanDisplacementToZero(0);}
+
+  // Description:
+  void SetOutputScalarTypeToFloat()
+  {this->OutputScalarType=VTK_FLOAT;}
+  void SetOutputScalarTypeToDouble()
+  {this->OutputScalarType=VTK_DOUBLE;}
+  
+
+  // Description:
+  // Padding Width --> add voxels of air around image to improve accuracy
+  vtkSetClampMacro(Padding,int,0,99);
+  vtkGetMacro(Padding,int);
+
+protected:
+  vtkokKochCoefficientSource();
+  ~vtkokKochCoefficientSource();
+
+  // Description:
+  // suscptibility field
+  vtkImageData*  SusceptibilityField; //[ppm = e-06]
+
+  // Description:
+  //Compute fourier transform Chi(kx,ky,kz) of susceptibility map 
+  vtkImageData*  ImageFFT;
+
+  // Description:
+  //"Coeffcient Image" Ck(kx,ky,kz)
+  vtkImageData*  ImageCoefficient;
+
+  // Description:
+  // Ck(kx,ky,kz) * Chi(kx,ky,kz)
+  vtkImageData*  ImageMultiplied;
+
+  // Description:
+  // Inverse transform of Ck(kx,ky,kz) * Chi(kx,ky,kz)
+  // which equals B_dz(x,y,z)*B0^(-1)
+  vtkImageData*  ImageRFFT;
+
+  // Description:
+  // Induced field B_dz(x,y,z)
+  vtkImageData*  InducedField;//[Hz]
+
+  // Description:
+  // Padded Input
+  vtkImageData*  PaddedInput;
+
+  // Description:
+  // Coefficient Output
+  vtkImageData*  CoefficientMap; 
+
+  // Description:
+  // BrainVOI 
+  vtkImageData*  ExtractedVOI;
+
+  // Description:
+  //Optionally compute average displacement in this region.
+  //Comptuted average displacement is subtracted from the
+  //estimated displacemnt so that the average displacement
+  //in the region should be zero.
+  int    BrainVOI[6];
+
+  // Description:
+  int    OutputScalarType;
+
+  // Description:
+  // scaling factor to convert from induced field to displacement field
+  float  ScaleFactorOfDisplacement;
+
+  // Description:
+  // Static magnetic field
+  float  B0; //[T]
+
+  // Description:
+  // Amount of Air Image to Add around input for computational purposes
+  int  Padding;//[voxels]
+
+  // Description:
+  // If set to 1, average displacement in soft tissuue (susc=-9.0) will 
+  // be caribrated as zero
+  int    MeanDisplacementToZero;
+
+  // Description:
+  // In case the argument "mode" is set to nonzero value, small
+  // value will be assigned to voxels whose values are zero in the ImageMultiplied.
+  int    mode;
+
+  // Description:
+  // Run The Filter
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+
+  // Execute Information Replacements
+  virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+
+  // Description:
+  //  Compute induced displacement field from susceptibility map
+  virtual vtkImageData* EstimateInductionField(vtkImageData* susceptibilitymap,vtkImageData* kochcoefficient);
+
+  // Description:
+  // Pad Image To Compute Field
+  virtual vtkImageData* PadImage(vtkImageData* img,int padsize);
+
+
+private:
+  vtkokKochCoefficientSource(const vtkokKochCoefficientSource&);  // Not implemented.
+  void operator=(const vtkokKochCoefficientSource&);  // Not implemented.
+};
+
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxAbstractIntensityRegistration.cpp b/bioimagesuite30_src/Registration/vtkpxAbstractIntensityRegistration.cpp
new file mode 100644
index 0000000..f777409
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxAbstractIntensityRegistration.cpp
@@ -0,0 +1,662 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+
+
+
+#include "pxutil.h"
+#include "vtkImageData.h"
+#include "vtkImageCast.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkbisImageResample.h"
+#include "vtkbisImageReslice.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxRegistration.h"
+#include "vtkMath.h"
+#include "vtkpxMath.h"
+#include "vtkLandmarkTransform.h"
+#include "vtkpxUtil.h"
+#include "vtkTransform.h"
+#include "vtkImageShiftScale.h"
+#include "vtkPoints.h"
+#include "vtkpxComboTransform.h"
+#include "vtkpxAbstractIntensityRegistration.h"
+#include "vtkbisImageHeader.h"
+#include "vtkTimerLog.h"
+
+vtkpxAbstractIntensityRegistration* vtkpxAbstractIntensityRegistration::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxAbstractIntensityRegistration");
+  if(ret)
+    {
+      return (vtkpxAbstractIntensityRegistration*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxAbstractIntensityRegistration;
+}
+
+
+vtkpxAbstractIntensityRegistration::vtkpxAbstractIntensityRegistration()
+{
+  // Set parameters
+  this->ReferenceImage=NULL;
+  this->TransformImage=NULL;
+  this->SampledReferenceImage=NULL;
+  this->SampledTransformImage=NULL;
+
+  this->ReferenceWeightImage=NULL;
+  this->TransformWeightImage=NULL;
+  this->SampledReferenceWeightImage=NULL;
+  this->SampledTransformWeightImage=NULL;
+
+
+  this->Histogram=NULL;
+  this->NumberOfLevels=3;
+  this->NumberOfExtraLevels=0;
+  this->NumberOfBins=64;
+  this->NumberOfSteps=4;
+  this->Resolution=2.0;
+  this->InternalResolution=2.0;
+  this->InterpolationMode=1;
+  this->StepSize=2.0;
+  this->InternalStepSize=2.0;
+  this->CurrentStepSize=2.0;
+  this->CurrentResolution=2.0;
+  this->ProvideFeedback=1;
+  this->NumberOfIterations=25;
+  this->SimilarityMeasure=5;
+  strcpy(this->OutputStatus,"Nothing going on");
+  this->LastProgress=0.0;
+  this->ReferenceOrientation=0;
+  this->TransformOrientation=0;
+  this->LogarithmMode=0;
+  this->PositiveIntensitiesOnly=0;
+  this->BlurFactor=0.4247;
+  this->OptimizationMethod=0;
+  this->KeepSameNumberOfSlices=0;
+  this->AutoNormalizeIntensities=1;
+  this->JointlyNormalizeIntensities=0;
+  for (int i=0;i<=2;i++)
+    this->BaseResolution[i]=1.0;
+  this->ResolutionRate=2.0;
+  this->MidlineSymmetricMode=0;
+}
+
+vtkpxAbstractIntensityRegistration::~vtkpxAbstractIntensityRegistration()
+{
+  if (this->ReferenceImage!=NULL)
+    this->ReferenceImage->Delete();
+  if (this->TransformImage!=NULL)
+    this->TransformImage->Delete();
+  if (this->SampledReferenceImage!=NULL)
+    this->SampledReferenceImage->Delete();
+  if (this->SampledTransformImage!=NULL)
+    this->SampledTransformImage->Delete();
+  if (this->Histogram!=NULL)
+    this->Histogram->Delete();
+
+
+ if (this->ReferenceWeightImage!=NULL)
+    this->ReferenceWeightImage->Delete();
+  if (this->TransformWeightImage!=NULL)
+    this->TransformWeightImage->Delete();
+  if (this->SampledReferenceWeightImage!=NULL)
+    this->SampledReferenceWeightImage->Delete();
+  if (this->SampledTransformWeightImage!=NULL)
+    this->SampledTransformWeightImage->Delete();
+ 
+}
+
+
+//----------------------------------------------------------------------------
+void vtkpxAbstractIntensityRegistration::SetReferenceImage(vtkImageData* img,int frame)
+{
+  if (img==NULL)
+    return;
+
+  if (this->ReferenceImage==NULL)
+    this->ReferenceImage=vtkImageData::New();
+
+  vtkpxRegistration::ExtractComponentAndCastImageToShort(this->ReferenceImage,img,frame);
+}
+//----------------------------------------------------------------------------
+void vtkpxAbstractIntensityRegistration::SetTransformImage(vtkImageData* img,int frame)
+{
+  if (img==NULL)
+    return;
+
+  if (this->TransformImage==NULL)
+    this->TransformImage=vtkImageData::New();
+
+  vtkpxRegistration::ExtractComponentAndCastImageToShort(this->TransformImage,img,frame);
+}
+
+//----------------------------------------------------------------------------
+void vtkpxAbstractIntensityRegistration::PrintSelf(ostream& os, vtkIndent indent)
+{
+  os << indent << "### " << this->GetClassName() << " ### \n";
+  if (this->GetTransformation()!=NULL)
+    this->GetTransformation()->PrintSelf(os,indent.GetNextIndent());
+  this->ReferenceImage->PrintSelf(os,indent.GetNextIndent());
+  TransformImage->PrintSelf(os,indent.GetNextIndent());
+}
+
+//-------------------------------------------------------------------------
+//                      Similarity Measure
+//-------------------------------------------------------------------------
+const char *vtkpxAbstractIntensityRegistration::GetOutputStatus()
+{
+  return this->OutputStatus;
+}
+//-------------------------------------------------------------------------
+const char *vtkpxAbstractIntensityRegistration::NameOfMeasure()
+{
+  return vtkpxJointHistogram::NameOfMeasure(this->SimilarityMeasure);
+}
+//-------------------------------------------------------------------------
+double vtkpxAbstractIntensityRegistration::Similarity(vtkpxJointHistogram* histo)
+{
+  //  fprintf(stdout,"\n\n\n In ABS Reg Similarity \n\n\n");
+
+  if (histo==NULL)
+    histo=this->Histogram;
+
+  // Evaluate similarity from histogram
+  if (histo==NULL)
+    return -1.0;
+  
+  return histo->Similarity(this->SimilarityMeasure);
+}
+
+// ----------------------------------------------------------------------
+// Run --- start procedure for all iterations
+// ----------------------------------------------------------------------
+void vtkpxAbstractIntensityRegistration::Run()
+{
+  if (this->TransformImage == NULL)
+    {
+      vtkErrorMacro(<< "::Run: Filter has no source input");
+      return;
+    }
+
+  if (this->ReferenceImage == NULL)
+    {
+      vtkErrorMacro(<< "::Run: Filter has no target input");
+      return;
+    }
+  
+  vtkTimerLog* globtimer=vtkTimerLog::New();
+  vtkTimerLog* timer=vtkTimerLog::New();
+  globtimer->StartTimer();
+
+  float optimizetime=0.0;
+
+  vtkDebugMacro(<<"Initializing All");
+  int ok=this->InitializeAll();
+  if (ok==0)
+    {
+      vtkErrorMacro(<<"Initialization Failed\n");
+      return;
+    }
+
+  for (int level=this->NumberOfLevels;level>=1;level=level-1)
+    {
+      vtkDebugMacro(<<"Initializing Level="<<level);
+      fprintf(stderr,"\n\n\n--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--_--\n ++++++++++++++++ Beginning Level %d\n\n",level);
+      this->Initialize(level);
+
+      vtkDebugMacro(<<"Compute Registration Level="<<level);
+      timer->StartTimer();
+      this->ComputeRegistration(level);
+      timer->StopTimer();
+      optimizetime+=timer->GetElapsedTime();
+      vtkDebugMacro(<<"Finalizing Level="<<level);
+      this->Finalize(level);
+    }
+
+  //  fprintf(stderr,"On to Extra Levels=%d\n",this->NumberOfExtraLevels);
+  for (int extra=1;extra<=this->NumberOfExtraLevels;extra++)
+    {
+      vtkDebugMacro(<<"Initializing Extra Level="<<extra);
+      vtkDebugMacro(<<"\n\n Beginning Extra Level  " << extra << "/" << this->NumberOfExtraLevels << "\n");
+      this->Initialize(1);
+      vtkDebugMacro(<<"Compute Registration Extra Level="<<extra);
+      this->ComputeRegistration(1);
+      vtkDebugMacro(<<"Finalizing Extra Level="<<extra);
+      this->Finalize(1);
+    }
+
+  vtkDebugMacro(<<"Finalizing All");
+  this->FinalizeAll();
+  globtimer->StopTimer();
+  float globtime=globtimer->GetElapsedTime();
+  timer->Delete();
+  globtimer->Delete();
+  fprintf(stderr,"\n\t\t\t Total Time = %.5fs compute time =%.5fs percentage = %.2f \%\n\n\n",
+	  globtime,optimizetime,100.0*optimizetime/globtime);
+  vtkDebugMacro(<<"vtkpxAbstractIntensityRegistration::Run() ends\n");
+
+}
+//-------------------------------------------------------------------------
+int vtkpxAbstractIntensityRegistration::InitializeAll()
+{
+  if (this->TransformImage==NULL || this->ReferenceImage==NULL)
+    {
+      vtkErrorMacro(<<"Both Images Need to be non-NULL for registration to work");
+      return 0;
+    }
+
+  if (this->SampledReferenceImage!=NULL)
+    this->SampledReferenceImage->Delete();
+  
+  if (this->SampledTransformImage!=NULL)
+    this->SampledTransformImage->Delete();
+
+ if (this->SampledReferenceWeightImage!=NULL)
+    this->SampledReferenceWeightImage->Delete();
+  
+  if (this->SampledTransformWeightImage!=NULL)
+    this->SampledTransformWeightImage->Delete();
+
+
+  this->SampledReferenceImage=vtkImageData::New();
+  this->SampledTransformImage=vtkImageData::New();
+  if (this->ReferenceWeightImage!=NULL)
+    this->SampledReferenceWeightImage=vtkImageData::New();
+
+  if (this->TransformWeightImage!=NULL)
+    this->SampledTransformWeightImage=vtkImageData::New();
+
+  this->NumberOfLevels=Irange(this->NumberOfLevels,1,8);
+  this->NumberOfBins=Irange(this->NumberOfBins,2,1024);
+  this->NumberOfIterations=Irange(this->NumberOfIterations,1,400);
+  this->NumberOfSteps=Irange(this->NumberOfSteps,1,8);
+
+  this->ReferenceImage->GetSpacing(this->BaseResolution);
+  this->MinimumResolution=Fmin(this->BaseResolution[0],Fmin(this->BaseResolution[1],this->BaseResolution[2]));
+  
+  this->MeanResolution=0.0;
+  for (int kk=0;kk<=2;kk++)
+    {
+      this->MeanResolution+=this->BaseResolution[kk]/3.0;
+
+      // Make mostly isotropic data 
+      if (this->BaseResolution[kk]>1.2*this->MinimumResolution)
+	this->BaseResolution[kk]=1.2*this->MinimumResolution;
+    }
+
+  if (this->Resolution<0.0)
+    this->InternalResolution=1.0;
+  else
+    this->InternalResolution=Frange(this->Resolution,0.25,50.0);
+
+
+  double targ[3]; this->TransformImage->GetSpacing(targ);
+  double tmin=Fmin(targ[0],Fmin(targ[1],targ[2]));
+  
+  double ratio=tmin/this->MinimumResolution;
+
+  if (ratio>this->InternalResolution*2.0)
+    {
+      double a=this->InternalResolution;
+      this->InternalResolution=ratio/2.0;
+      this->CurrentResolution=this->InternalResolution;
+      sprintf(this->OutputStatus,"\n\n Given Resolution Ratio of %.2f adjusting resolution from %.2f to %.2f\n",
+	      ratio,a,this->InternalResolution);
+      this->UpdateProgress(this->LastProgress);
+    }
+
+
+
+  this->CurrentResolution=this->InternalResolution;
+
+  this->InterpolationMode=Irange(this->InterpolationMode,-5,3);
+  if (this->InterpolationMode==2 || this->InterpolationMode==-1)
+    this->InterpolationMode=1;
+
+  this->InternalStepSize=Frange(this->StepSize,0.01,4.0);
+  this->InternalStepSize*=this->MeanResolution;
+  this->CurrentStepSize=this->InternalStepSize;
+  //  fprintf(stdout,"MeanRes=%f, Step=%f\n",this->MeanResolution,this->CurrentStepSize);
+
+  this->SimilarityMeasure=Irange(this->SimilarityMeasure,1,10);
+
+  this->ReferenceOrientation=vtkbisImageHeader::MapOrientationToOldStyle(this->ReferenceOrientation);
+  this->TransformOrientation=vtkbisImageHeader::MapOrientationToOldStyle(this->TransformOrientation);
+
+
+  if (this->ReferenceOrientation!=this->TransformOrientation)
+    {
+      vtkpxRegistration::ReOrientImage(this->TransformImage,this->TransformImage,this->TransformOrientation,
+				       this->ReferenceOrientation);
+
+      if (this->TransformWeightImage!=NULL)
+	vtkpxRegistration::ReOrientImage(this->TransformWeightImage,this->TransformWeightImage,this->TransformOrientation,
+					 this->ReferenceOrientation);
+
+      sprintf(this->OutputStatus,"Reorienting transform image image from %d to %d\n",
+	      this->TransformOrientation,this->ReferenceOrientation);
+      vtkDebugMacro(<<this->OutputStatus);
+      this->UpdateProgress(this->LastProgress);
+    }  
+
+  sprintf(this->OutputStatus,"Beginning Registration SimilarityMetric = %s (%d)\n",
+	  this->NameOfMeasure(),this->SimilarityMeasure);
+  vtkDebugMacro(<<this->OutputStatus);
+  //  fprintf(stderr,"%s\n",this->OutputStatus);
+  this->UpdateProgress(this->LastProgress);
+  return 1;
+   
+}
+//-------------------------------------------------------------------------
+
+int vtkpxAbstractIntensityRegistration::Initialize(int level)
+{
+  double reduction=pow(this->ResolutionRate,double(level-1.0));
+  this->CurrentStepSize=this->InternalStepSize*reduction;
+  this->CurrentResolution=this->InternalResolution*reduction;
+  this->InternalBlurFactor=this->BlurFactor;
+  if (this->CurrentResolution==1.0)
+    this->InternalBlurFactor=0.0;
+
+  if (this->SampledReferenceImage==NULL)
+    this->SampledReferenceImage=vtkImageData::New();
+  if (this->SampledTransformImage==NULL)
+    this->SampledTransformImage=vtkImageData::New();
+
+  // This forces the same slices regardless of level 
+
+  //  vtkpxRegistration::PrintImageInfo(this->SampledReferenceImage,"Before");
+
+
+  vtkpxRegistration::ResampleAndSmoothImage(this->SampledReferenceImage,this->ReferenceImage,
+					    this->BaseResolution,
+					    this->InternalBlurFactor*this->CurrentResolution,
+					    this->CurrentResolution,this->KeepSameNumberOfSlices);
+
+   
+  //  vtkpxRegistration::PrintImageInfo(this->SampledReferenceImage,"ResandSmooth");
+
+  vtkpxRegistration::ResampleAndSmoothImage(this->SampledTransformImage,this->TransformImage,
+					    this->BaseResolution,
+					    this->InternalBlurFactor*this->CurrentResolution,
+					    this->CurrentResolution,this->KeepSameNumberOfSlices);
+
+  short minr=0,maxr=1,mint=0,maxt=1;
+  int num_ref,num_tar;
+
+  sprintf(this->OutputStatus,"Going to Calc Range and Adjust \n\n");
+  this->UpdateProgress(this->LastProgress);
+
+  if (this->JointlyNormalizeIntensities)
+    {
+      num_ref=vtkpxRegistration::CalculateNumberOfBinsAndAdjustImages(this->SampledReferenceImage,
+								      this->SampledTransformImage,
+								      this->NumberOfBins,minr,maxr,
+								      this->LogarithmMode,
+								      this->PositiveIntensitiesOnly,
+								      this->AutoNormalizeIntensities);
+      num_tar=num_ref;
+      mint=minr;
+      maxt=maxr;
+    }
+  else
+    {
+      num_ref=vtkpxRegistration::CalculateNumberOfBinsAndAdjustImage(this->SampledReferenceImage,
+								     this->NumberOfBins,minr,maxr,
+								     this->LogarithmMode,
+								     this->PositiveIntensitiesOnly,
+								     this->AutoNormalizeIntensities);
+      num_tar=vtkpxRegistration::CalculateNumberOfBinsAndAdjustImage(this->SampledTransformImage,
+								     this->NumberOfBins,mint,maxt,
+								     this->LogarithmMode,
+								     this->PositiveIntensitiesOnly,
+								     this->AutoNormalizeIntensities);
+    }
+
+
+  sprintf(this->OutputStatus,"Resample and Smooth Images \n\n");
+  this->UpdateProgress(this->LastProgress);
+
+
+  if (this->ReferenceWeightImage!=NULL)
+    {
+      vtkpxRegistration::ResampleAndSmoothImage(this->SampledReferenceWeightImage,this->ReferenceWeightImage,
+						this->BaseResolution,
+						this->InternalBlurFactor*this->CurrentResolution,
+						this->CurrentResolution,this->KeepSameNumberOfSlices);
+
+
+      
+
+      vtkpxRegistration::ScaleWeightImage(this->SampledReferenceWeightImage,this->SampledReferenceImage,100.0);
+
+      //      vtkpxUtil::SaveAnalyze("weight_image_raw.nii.gz",this->ReferenceWeightImage,9);
+      //      vtkpxUtil::SaveAnalyze("ref_image.nii.gz",this->SampledReferenceImage,9);
+      //      vtkpxUtil::SaveAnalyze("weight_image_scaled.nii.gz",this->SampledReferenceWeightImage,9);
+      //      exit(0);
+    }
+
+  if (this->TransformWeightImage!=NULL)
+    {
+      vtkpxRegistration::ResampleAndSmoothImage(this->SampledTransformWeightImage,this->TransformWeightImage,
+						this->BaseResolution,
+						this->InternalBlurFactor*this->CurrentResolution,
+						this->CurrentResolution,this->KeepSameNumberOfSlices);
+      vtkpxRegistration::ScaleWeightImage(this->SampledTransformWeightImage,this->SampledTransformImage,100.0);
+    }
+
+
+  //  vtkpxRegistration::PrintImageInfo(this->SampledReferenceImage,"postNorm");
+
+  if (this->Histogram!=NULL)
+    this->Histogram->Delete();
+  this->Histogram=vtkpxJointHistogram::New();
+  if (!this->MidlineSymmetricMode)
+    this->Histogram->Allocate(num_ref,num_tar);
+  else
+    this->Histogram->Allocate(num_tar,num_tar);
+
+  double sp1[3],sp2[3],or1[3],or2[3];
+  int   dim1[3],dim2[3];
+
+  this->SampledReferenceImage->GetSpacing(sp1);
+  this->SampledReferenceImage->GetDimensions(dim1);
+  this->SampledReferenceImage->GetOrigin(or1);
+  this->SampledTransformImage->GetSpacing(sp2);
+  this->SampledTransformImage->GetDimensions(dim2);
+  this->SampledTransformImage->GetOrigin(or2);
+
+  sprintf(this->OutputStatus,"\nEnd Of Initialization Of Level =%d,%d",level,this->NumberOfLevels);
+  sprintf(this->OutputStatus,
+	  "%s\n Reference = %d x %d x %d (%.2f %.2f %.2f) (or=%.1f,%.1f,%.1f), Range=%d:%d bins=%d kern=%5.2f",
+	  this->OutputStatus,dim1[0],dim1[1],dim1[2],sp1[0],sp1[1],sp1[2],or1[0],or1[1],or1[2],
+	  minr,maxr,num_ref,this->InternalBlurFactor*this->CurrentResolution);
+  sprintf(this->OutputStatus,
+	  "%s\nTransform  = %d x %d x %d (%.2f %.2f %.2f) (or=%.1f,%.1f,%.1f), Range=%d:%d bins=%d kern=%5.2f midline=%d\n",
+	  this->OutputStatus,dim2[0],dim2[1],dim2[2],sp2[0],sp2[1],sp2[2],or2[0],or2[1],or2[2],
+	  mint,maxt,num_tar,this->InternalBlurFactor*this->CurrentResolution,this->MidlineSymmetricMode);
+
+
+  if (this->SampledReferenceWeightImage!=NULL)
+    {
+      this->SampledReferenceWeightImage->GetSpacing(sp2);
+      this->SampledReferenceWeightImage->GetDimensions(dim2);
+      this->SampledReferenceWeightImage->GetOrigin(or2);
+      double range[2]; this->SampledReferenceWeightImage->GetPointData()->GetScalars()->GetRange(range);
+
+      sprintf(this->OutputStatus,
+	      "%s Ref Weight  = %d x %d x %d (%.2f %.2f %.2f) (or=%.1f,%.1f,%.1f) range=%.2f:%.2f\n",
+	      this->OutputStatus,dim2[0],dim2[1],dim2[2],sp2[0],sp2[1],sp2[2],or2[0],or2[1],or2[2],range[0],range[1]);
+    }
+  else
+    { 
+      sprintf(this->OutputStatus,"%s Ref Weight Image not set\n",this->OutputStatus);
+    }
+
+  if (this->SampledTransformWeightImage!=NULL)
+    {
+      this->SampledTransformWeightImage->GetSpacing(sp2);
+      this->SampledTransformWeightImage->GetDimensions(dim2);
+      this->SampledTransformWeightImage->GetOrigin(or2);
+      double range[2]; this->SampledTransformWeightImage->GetPointData()->GetScalars()->GetRange(range);
+      sprintf(this->OutputStatus,
+	      "%s Transform Weight  = %d x %d x %d (%.2f %.2f %.2f) (or=%.1f,%.1f,%.1f) range=%.2f:%.2f\n\n",
+	      this->OutputStatus,dim2[0],dim2[1],dim2[2],sp2[0],sp2[1],sp2[2],or2[0],or2[1],or2[2],range[0],range[1]);
+    }
+  else
+    {
+      sprintf(this->OutputStatus,"%s Transform Weight Image not set\n\n",this->OutputStatus);
+    }
+
+  vtkDebugMacro(<<this->OutputStatus);
+  //fprintf(stderr,"%s\n",this->OutputStatus);
+  this->UpdateProgress(this->LastProgress);
+  return 1;
+
+}
+//-------------------------------------------------------------------------
+int vtkpxAbstractIntensityRegistration::Finalize(int level)
+{
+ 
+//  this->SampledReferenceImage->Initialize();
+//  this->SampledTransformImage->Initialize();
+
+  sprintf(this->OutputStatus,"\n\n **** Done with level %d\n ------------------------------------------------------------ \n\n",level);
+  vtkDebugMacro(<<this->OutputStatus);
+  this->UpdateProgress(this->LastProgress);
+  //  sprintf(this->OutputStatus,"****Finalize level %d done",level);
+  //  vtkDebugMacro(<<this->OutputStatus);
+  return 1;
+
+}
+//-------------------------------------------------------------------------
+int vtkpxAbstractIntensityRegistration::FinalizeAll()
+{
+  //  printf("int vtkpxAbstractIntensityRegistration::FinalizeAll() starts..\n");
+  /*this->SampledReferenceImage->Delete();
+    this->SampledTransformImage->Delete();
+    this->SampledReferenceImage=NULL;
+    this->SampledTransformImage=NULL;*/
+  return 1;
+
+}
+//-------------------------------------------------------------------------
+double vtkpxAbstractIntensityRegistration::Evaluate()
+{
+  return vtkpxRegistration::HistogramEvaluate(this->SampledReferenceImage,this->SampledTransformImage,
+					      this->GetTransformation(),
+					      this->Histogram,this->SimilarityMeasure,
+					      this->InterpolationMode);
+}
+//-------------------------------------------------------------------------
+double vtkpxAbstractIntensityRegistration::WeightedEvaluate()
+{
+  if (this->SampledReferenceWeightImage==NULL)
+    return this->Evaluate();
+
+  return vtkpxRegistration::WeightedHistogramEvaluate(this->SampledReferenceImage,
+						      this->SampledReferenceWeightImage,
+						      this->SampledTransformImage,
+						      this->SampledTransformWeightImage,
+						      this->GetTransformation(),
+						      this->Histogram,this->SimilarityMeasure,
+						      this->InterpolationMode);
+}
+
+//-------------------------------------------------------------------------
+void vtkpxAbstractIntensityRegistration::GenerateOutput(int level, int step,int iter,double stepsize,double actualSimilarity)
+{
+  double sc=1.0/double(this->NumberOfLevels);
+  double pog=(double(step)/double(this->NumberOfSteps+1) + double(this->NumberOfLevels-level))*sc;
+  this->LastProgress=pog;
+  this->UpdateProgress(pog);
+  //  vtkDebugMacro(<<this->OutputStatus);
+  return;
+}
+//-------------------------------------------------------------------------
+// Optimizer SsFinalizetuff
+//-------------------------------------------------------------------------
+void vtkpxAbstractIntensityRegistration::SetOutputStatus(const char* line,double v)
+{
+  sprintf(this->OutputStatus,"**Opt=%s (%.5f)\n",line,v);
+  this->UpdateProgress(this->LastProgress);
+}
+
+//-------------------------------------------------------------------------
+double vtkpxAbstractIntensityRegistration::CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output)
+{
+  return ((vtkpxAbstractIntensityRegistration*)self)->OptimizerGradient(position,output);
+}
+
+double vtkpxAbstractIntensityRegistration::CalculateFunction(vtkObject* self,vtkDoubleArray* position)
+{
+  return ((vtkpxAbstractIntensityRegistration*)self)->OptimizerValue(position);
+}
+
+double vtkpxAbstractIntensityRegistration::OnBeginIteration(vtkObject* self,vtkDoubleArray* position)
+{
+  //  fprintf(stderr,"On Begin Iteration Abstract\n");
+  return ((vtkpxAbstractIntensityRegistration*)self)->OnBeginIteration(position);
+}
+
+
+void vtkpxAbstractIntensityRegistration::OptimizerFeedback(vtkObject* self,const char* line,double val)
+{
+  ((vtkpxAbstractIntensityRegistration*)self)->SetOutputStatus(line,val);
+}
+//-------------------------------------------------------------------------
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxAbstractIntensityRegistration.h b/bioimagesuite30_src/Registration/vtkpxAbstractIntensityRegistration.h
new file mode 100644
index 0000000..7923533
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxAbstractIntensityRegistration.h
@@ -0,0 +1,369 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+
+
+
+
+
+#ifndef __VTKPXABSREGISTRATION_H
+#define __VTKPXABSREGISTRATION_H
+
+#include "vtkObject.h"
+#include "vtkAbstractTransform.h"
+#include "vtkpxJointHistogram.h"
+#include "vtkProcessObject.h"
+#include "vtkDoubleArray.h"
+
+class vtkpxAbstractIntensityRegistration : public vtkProcessObject {
+
+public:
+
+  vtkTypeMacro(vtkpxAbstractIntensityRegistration,vtkProcessObject);
+  virtual void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // This one also 
+  static vtkpxAbstractIntensityRegistration* New();
+  
+  // Description:
+  // Sets input for the registration filter
+  virtual void SetReferenceImage(vtkImageData* targ,int frame);
+  virtual void SetReferenceImage(vtkImageData* targ) { this->SetReferenceImage(targ,0);}
+  
+  virtual void SetTransformImage(vtkImageData* src ,int frame);
+  virtual void SetTransformImage(vtkImageData* src ) { this->SetTransformImage(src,0); }
+
+  // Description:
+  // Set Reference and Target Weights (Target Weights unused mostly)
+  vtkSetObjectMacro(ReferenceWeightImage,vtkImageData);
+  vtkGetObjectMacro(ReferenceWeightImage,vtkImageData);
+  vtkSetObjectMacro(TransformWeightImage,vtkImageData);
+  vtkGetObjectMacro(TransformWeightImage,vtkImageData);
+
+
+  // Description:
+  // Set Orientations if needed
+  vtkGetMacro(ReferenceOrientation,int);
+  vtkSetClampMacro(ReferenceOrientation,int,0,100);
+  vtkGetMacro(TransformOrientation,int);
+  vtkSetClampMacro(TransformOrientation,int,0,100);
+
+
+  // Description:
+  // Feedback Stuff
+  vtkSetMacro(ProvideFeedback,int);
+  vtkGetMacro(ProvideFeedback,int);
+  vtkBooleanMacro(ProvideFeedback,int);
+
+  // Description:
+  // Feedback Stuff
+  vtkSetClampMacro(LogarithmMode,int,0,1);
+  vtkGetMacro(LogarithmMode,int);
+  vtkBooleanMacro(LogarithmMode,int);
+
+
+  // Description:
+  // Feedback Stuff
+  vtkSetClampMacro(InterpolationMode,int,-5,3);
+  vtkGetMacro(InterpolationMode,int);
+
+  // Description:
+  // Positive Intensities Only
+  vtkSetClampMacro(PositiveIntensitiesOnly,int,0,1);
+  vtkGetMacro(PositiveIntensitiesOnly,int);
+  vtkBooleanMacro(PositiveIntensitiesOnly,int);
+
+  // Description:
+  // Normalize Intensities
+  vtkSetClampMacro(AutoNormalizeIntensities,int,0,1);
+  vtkGetMacro(AutoNormalizeIntensities,int);
+  vtkBooleanMacro(AutoNormalizeIntensities,int);
+
+  // Description:
+  // Intra Modality Use same range
+  vtkSetClampMacro(JointlyNormalizeIntensities,int,0,1);
+  vtkGetMacro(JointlyNormalizeIntensities,int);
+  vtkBooleanMacro(JointlyNormalizeIntensities,int);
+  
+
+  // Description:
+  // Histogram Stuff
+  vtkSetObjectMacro(Histogram,vtkpxJointHistogram);
+  vtkGetObjectMacro(Histogram,vtkpxJointHistogram);
+
+
+  // Description:
+  // GetTransformation
+  virtual vtkAbstractTransform* GetTransformation() { return NULL;}
+
+
+  // Description:
+  // NumberOfLevels, NumberOfSteps, Resolution
+  vtkSetMacro(NumberOfLevels,int);
+  vtkGetMacro(NumberOfLevels,int);
+
+  // Description:
+  // Number Of Extra Levels
+  vtkSetMacro(NumberOfExtraLevels,int);
+  vtkGetMacro(NumberOfExtraLevels,int);
+
+  vtkSetMacro(NumberOfBins,int);
+  vtkGetMacro(NumberOfBins,int);
+  vtkSetMacro(NumberOfIterations,int);
+  vtkGetMacro(NumberOfIterations,int);
+  vtkSetMacro(NumberOfSteps,int);
+  vtkGetMacro(NumberOfSteps,int);
+  vtkSetMacro(Resolution,double);
+  vtkGetMacro(Resolution,double);
+  vtkSetClampMacro(BlurFactor,double,0.0,5.0);
+  vtkGetMacro(BlurFactor,double);
+  vtkSetMacro(StepSize,double);
+  vtkGetMacro(StepSize,double);
+
+  // Description:
+  // Similarity Measure
+  vtkGetMacro(SimilarityMeasure,int);
+  vtkSetMacro(SimilarityMeasure,int);
+
+  virtual void SetSimilarityMeasureToJointEntropy() { this->SetSimilarityMeasure(1);}
+  virtual void SetSimilarityMeasureToCorrelation()  { this->SetSimilarityMeasure(2);}
+  virtual void SetSimilarityMeasureToGradientCorrelation() { this->SetSimilarityMeasure(3);}
+  virtual void SetSimilarityMeasureToMutualInformation() { this->SetSimilarityMeasure(4);}
+  virtual void SetSimilarityMeasureToNormalizedMutualInformation() { this->SetSimilarityMeasure(5);}
+  virtual void SetSimilarityMeasureToSumofSquaredDifferences() { this->SetSimilarityMeasure(6);}
+  virtual void SetSimilarityMeasureToCorrelationRatioYX() { this->SetSimilarityMeasure(7);}
+  virtual void SetSimilarityMeasureToCorrelationRatioXY() { this->SetSimilarityMeasure(8);}
+  virtual void SetSimilarityMeasureToProduct() { this->SetSimilarityMeasure(9);}
+  virtual void SetSimilarityMeasureToDifferenceEntropy() { this->SetSimilarityMeasure(10);}
+
+  // Description:
+  // Runs the registration filter
+  virtual void Run();
+
+  // Description:
+  // Returns the name of the similarity measure
+  const char *NameOfMeasure();
+
+  // Description:
+  // Prints information about the progress of the registration
+  virtual void PrintInformation() {};
+
+  // Description:
+  // GetOutputStatus 
+  const char *GetOutputStatus();
+
+  // Description:
+  // Get Update Transformation
+  vtkAbstractTransform* GetUpdateTransformation() { return this->GetTransformation(); }
+
+  // Description:
+  // These are needed for the Optimizer 
+  static void  OptimizerFeedback(vtkObject* self,const char* line,double val);
+  static double CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output);
+  static double CalculateFunction(vtkObject* self,vtkDoubleArray* position);
+  static double OnBeginIteration(vtkObject* self,vtkDoubleArray* position);
+
+  // Description:
+  // Optimization Method
+  vtkSetMacro(OptimizationMethod,int);
+  vtkGetMacro(OptimizationMethod,int);
+
+  // Description:
+  // Shorthand for different optimization methods 
+  virtual void SetOptimizationMethodToOldStyle() { this->SetOptimizationMethod(-1); }
+  virtual void SetOptimizationMethodToDefault() { this->SetOptimizationMethod(0); }
+  virtual void SetOptimizationMethodToSlowClimb() { this->SetOptimizationMethod(1); }
+  virtual void SetOptimizationMethodToPowell() { this->SetOptimizationMethod(2); }
+  virtual void SetOptimizationMethodToGradientDescent() { this->SetOptimizationMethod(3); }
+  virtual void SetOptimizationMethodToConjugateGradient() { this->SetOptimizationMethod(4); }
+  virtual void SetOptimizationMethodToHybrid() { this->SetOptimizationMethod(5); }
+ 
+  // Description:
+  // Get Last Output Measures
+  vtkGetMacro(LastSimilarity,double);
+  vtkGetMacro(LastSmoothness,double);
+
+  // Description:
+  // Set Grid Spacing at highest resolution
+  vtkSetClampMacro(ResolutionRate,double,1.01,2.0);
+  vtkGetMacro(ResolutionRate,double);
+
+protected:
+
+  // Description:
+  // Make all these protected 
+  // Constructor
+  vtkpxAbstractIntensityRegistration();
+  virtual ~vtkpxAbstractIntensityRegistration();
+  vtkpxAbstractIntensityRegistration(const vtkpxAbstractIntensityRegistration&) {};
+  void operator=(const vtkpxAbstractIntensityRegistration&) {};
+
+
+
+  // Description:
+  // First input image. This image is denoted as target image and its 
+  // coordinate system defines the frame of reference for the registration.
+  vtkImageData *ReferenceImage;
+  vtkImageData *SampledReferenceImage;
+  vtkImageData *ReferenceWeightImage;
+  vtkImageData *SampledReferenceWeightImage;
+  int           ReferenceOrientation;
+
+  // Description:
+  // Second input image. This image is denoted as source image. The goal of
+  // the registration is to find the transformation which maps the source 
+  // image into the coordinate system of the target image.
+  vtkImageData *TransformImage;
+  vtkImageData *TransformWeightImage;
+  vtkImageData *SampledTransformImage;
+  vtkImageData *SampledTransformWeightImage;
+  int           TransformOrientation;
+
+  // Description:
+  // Histogram
+  vtkpxJointHistogram *Histogram;
+
+  // Description:
+  // Various Control Parameters
+  int   NumberOfLevels;
+  int   NumberOfExtraLevels;
+  int   NumberOfIterations;
+  int   NumberOfSteps;
+  int   NumberOfBins;
+  int   LogarithmMode;
+  int   InterpolationMode;
+  int   PositiveIntensitiesOnly;
+  int   AutoNormalizeIntensities;
+  int   JointlyNormalizeIntensities;
+  int   OptimizationMethod;
+  int   MidlineSymmetricMode;
+
+  // Description:
+  // Make these private
+  double StepSize;
+  double Resolution;
+  double BlurFactor;
+
+  double ResolutionRate;
+  double InternalResolution;
+  double InternalStepSize;
+  int   ProvideFeedback;
+  double CurrentResolution;
+  double CurrentStepSize;
+  double InternalBlurFactor;
+  int   SimilarityMeasure;
+  int   KeepSameNumberOfSlices;
+  char  OutputStatus[800];
+  double LastProgress;
+  double BaseResolution[3];
+  double MinimumResolution;
+  double MeanResolution;
+
+  //BTX
+  double LastSimilarity,LastSmoothness;
+  //ETX
+
+  // Description:
+  // Initial set up for the registration at all levels
+  virtual int InitializeAll();
+
+  // Description:
+  // Initial set up for the registration at a multiresolution level
+  virtual int Initialize(int Level);
+
+  // Description:
+  // Run Optimization for Level level
+  virtual int ComputeRegistration(int level) { return 0 ;}
+  
+  // Description:
+  // Final set up for the registration at a multiresolution level
+  virtual int Finalize(int level);
+
+  // Description:
+  // Final set up for the registration at all levels
+  virtual int FinalizeAll();
+
+  // Description:
+  // Generate Output
+  virtual void GenerateOutput(int level, int step,int iter,double stepsize,double simil);
+  
+  // Description:
+  // Evaluates the similarity measure. This function returns the value of the 
+  // appropriate similarity measure from the joint histogram of the target 
+  // and source image. if NULL uses this->Histogram
+  virtual double Similarity(vtkpxJointHistogram* histogram=NULL);
+
+  // Description:
+  // Evaluates the registration. This function evaluates the registration by
+  // looping over the target image and interpolating the transformed source 
+  // image while filling the joint histogram. This function returns the value
+  // of the similarity measure using Similarity().
+  double Evaluate();
+  double WeightedEvaluate();
+  
+  
+  // Description:
+  // Set The OutputStatus 
+  virtual void SetOutputStatus(const char* line,double val);
+
+
+  // Description:
+  // Needed for Optimizer -- set,get,optimizer,optimizervalue
+  virtual void SetCurrentParameters(vtkDoubleArray* par) {}
+  virtual void GetCurrentParameters(vtkDoubleArray* par) {}
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad) {return 0.0;}
+  virtual double OptimizerValue(vtkDoubleArray* params) {return 0.0;}
+  virtual double OnBeginIteration(vtkDoubleArray* params) {return 0.0;}
+
+};
+
+
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxAbstractRPMRegistration.cpp b/bioimagesuite30_src/Registration/vtkpxAbstractRPMRegistration.cpp
new file mode 100644
index 0000000..fafaa4b
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxAbstractRPMRegistration.cpp
@@ -0,0 +1,154 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAbstractRPMRegistration.cpp,v $
+  Language:  C++
+  Date:      $Date: 2003/03/06 16:34:20 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxAbstractRPMRegistration.h"
+#include "vtkObjectFactory.h"
+//-----------------------------------------------------------------------------------
+vtkpxAbstractRPMRegistration* vtkpxAbstractRPMRegistration::New()
+{
+  // First try to create the object from the vtkObjectFactory
+
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxAbstractRPMRegistration");
+  if(ret)
+    {
+      return (vtkpxAbstractRPMRegistration*)ret;
+    }
+
+  // If the factory was unable to create the object, then create it here.
+
+  return new vtkpxAbstractRPMRegistration;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxAbstractRPMRegistration::vtkpxAbstractRPMRegistration()
+{
+
+  this->CurrentlyUpdating=0;
+  this->InitialTemperature=0.2;
+  this->FinalTemperature=0.2/100;
+  this->AnnealRate=0.93;
+  this->InitialSmoothnessFactor=1.0;
+  this->FinalSmoothnessFactor=0.1;
+  this->UseSymmetricCorrespondence=0;
+  this->SymmetryWeight=0.25;
+}
+
+//----------------------------------------------------------------------------
+
+void vtkpxAbstractRPMRegistration::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkpxRPMCorrespondenceFinder::PrintSelf(os,indent);
+
+  os << indent << "AnnealRate: " << this->AnnealRate << "\n";
+  os << indent << "InitialTemperature: " << this->InitialTemperature << "\n";
+  os << indent << "FinalTemperature: " << this->FinalTemperature << "\n";
+  os << indent << "InitialSmoothnessFactor: " << this->InitialSmoothnessFactor << "\n";
+  os << indent << "FinalSmoothnessFactor: " << this->FinalSmoothnessFactor << "\n";
+  
+}
+
+//----------------------------------------------------------------------------
+
+void vtkpxAbstractRPMRegistration::Run()
+{
+  // Check source, target
+  if (this->CurrentlyUpdating==1)
+    {
+      return;
+    }
+
+  if (this->Source == NULL || !this->Source->GetNumberOfPoints())
+    {
+      vtkErrorMacro(<<"Can't execute with NULL or empty input");
+      return;
+    }
+  
+  if (this->Target == NULL || !this->Target->GetNumberOfPoints())
+    {
+      vtkErrorMacro(<<"Can't execute with NULL or empty target");
+      return;
+    }
+
+  this->AbortExecute=0;
+  this->CurrentlyUpdating=1;
+  if (this->UseSymmetricCorrespondence)
+    this->SymmetricAnneal();
+  else
+    this->Anneal();
+  this->CurrentlyUpdating=0;
+}
+
+void vtkpxAbstractRPMRegistration::SymmetricAnneal()
+{
+  vtkErrorMacro(<<"No Symmetric Anneal Defined! Running Standard Annealing\n");
+  this->UseSymmetricCorrespondence=0;
+  this->Anneal();
+  this->UseSymmetricCorrespondence=1;
+}
+
+void vtkpxAbstractRPMRegistration::Anneal()
+{
+  vtkErrorMacro(<<"No  Anneal Defined! \n");
+}
+
+//----------------------------------------------------------------------------
+vtkAbstractTransform* vtkpxAbstractRPMRegistration::GetCurrentTransformation()
+{
+  return NULL;
+}
+//----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Registration/vtkpxAbstractRPMRegistration.h b/bioimagesuite30_src/Registration/vtkpxAbstractRPMRegistration.h
new file mode 100644
index 0000000..dd6737e
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxAbstractRPMRegistration.h
@@ -0,0 +1,152 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAbstractRPMRegistration.h,v $
+  Language:  C++
+  Date:      $Date: 2003/03/06 16:34:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#ifndef __vtkpxAbstractRPMRegistration_h
+#define __vtkpxAbstractRPMRegistration_h
+
+class vtkpxGridTransform;
+class vtkpxMatrix;
+class vtkPointLocator;
+class vtkPoints;
+class vtkPolyData;
+class vtkTransform;
+class vtkMatrix4x4;
+class vtkCollection;
+
+#include "vtkAbstractTransform.h"
+#include "vtkpxAbstractMatrix.h"
+#include "vtkpxMatrix.h"
+#include "vtkpxRPMCorrespondenceFinder.h"
+
+class vtkpxAbstractRPMRegistration : public vtkpxRPMCorrespondenceFinder
+{
+public:
+  static vtkpxAbstractRPMRegistration *New();
+  vtkTypeMacro(vtkpxAbstractRPMRegistration,vtkpxRPMCorrespondenceFinder);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Get Current Transformation -- needed for displaying updates 
+  virtual vtkAbstractTransform* GetCurrentTransformation();
+
+  // Description:
+  // Initial Temperature for deterministic annealing
+  vtkSetClampMacro(InitialTemperature,float,0.0,1000.0);
+  vtkGetMacro(InitialTemperature,float);
+
+  // Description:
+  // Final Temperature for deterministic annealing
+  vtkSetClampMacro(FinalTemperature,float,0.0,1000.0);
+  vtkGetMacro(FinalTemperature,float);
+
+  // Description:
+  // AnnealRate for annealing 
+  vtkSetClampMacro(AnnealRate,float,0.5,0.999);
+  vtkGetMacro(AnnealRate,float);
+
+  // Description:
+  // Smoothness Factors
+  vtkSetClampMacro(InitialSmoothnessFactor,float,0.02,200.0);
+  vtkGetMacro(InitialSmoothnessFactor,float);
+  vtkSetClampMacro(FinalSmoothnessFactor,float,0.02,200.0);
+  vtkGetMacro(FinalSmoothnessFactor,float);
+
+  // Description: 
+  // Symmetry Weight for exchanging parameters
+  vtkSetClampMacro(SymmetryWeight, float,0,0.5);
+  vtkGetMacro(SymmetryWeight, float);
+
+  // Description: 
+  // UseInitialTransform
+  vtkSetClampMacro(UseSymmetricCorrespondence, int,0,1);
+  vtkGetMacro(UseSymmetricCorrespondence, int);
+  vtkBooleanMacro(UseSymmetricCorrespondence, int);
+  
+  // Description:
+  // Execute The Transformation
+  virtual void Run();
+
+
+protected:
+
+  vtkpxAbstractRPMRegistration();
+  vtkpxAbstractRPMRegistration(const vtkpxAbstractRPMRegistration&) {};
+  void operator=(const vtkpxAbstractRPMRegistration&) {};
+
+
+  float AnnealRate;
+  float InitialSmoothnessFactor;
+  float FinalSmoothnessFactor;
+  float InitialTemperature;
+  float FinalTemperature;
+  int   UseSymmetricCorrespondence;
+  float SymmetryWeight;
+  int CurrentlyUpdating;
+
+  // -----------------------------------------------------------
+  // Description:
+  // Annealing Procedures
+  // -----------------------------------------------------------
+  virtual void Anneal();
+  virtual void SymmetricAnneal();
+
+  
+
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxArticulatedJointTransform.cpp b/bioimagesuite30_src/Registration/vtkpxArticulatedJointTransform.cpp
new file mode 100644
index 0000000..fae6918
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxArticulatedJointTransform.cpp
@@ -0,0 +1,1271 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include <stdlib.h>
+#include "vtkpxArticulatedJointTransform.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxUtil.h"
+#include "vtkTransform.h"
+#include "pxisinf.h"
+
+//----------------------------------------------------------------------------
+vtkpxArticulatedJointTransform* vtkpxArticulatedJointTransform::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxArticulatedJointTransform");
+  if(ret)
+    {
+      return (vtkpxArticulatedJointTransform*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxArticulatedJointTransform;
+}
+
+//----------------------------------------------------------------------------
+vtkpxArticulatedJointTransform::vtkpxArticulatedJointTransform()
+{
+  this->DetailMode=0;
+  this->BlendedMode=0;
+  this->CubicBlending=0;
+  this->RegionLabelIndex=-1;
+  this->ChildRegionLabelIndex=-1000;
+  this->ChildRegionLabelIndex2=-1000;
+  this->MinimumSectorAngle=5.0;
+  this->BlendingWindow=1.0;
+  this->SmoothingRadius=1.0;
+  this->SmoothingMode=0;
+  this->RegionLabelImage=NULL;
+  this->SimilarityTransform=vtkpxSimilarityTransform::New();
+  this->ZSimilarityTransform=vtkpxSimilarityTransform::New();
+  this->SetModeToRotationOnly();
+  this->AngleAxisTransform=vtkTransform::New();
+  this->AlignmentTransform=NULL;
+  this->AlignmentTransformIndex=-1;
+  this->SeparateZRotation=0;
+  this->ZBlendingSize=5.0;
+  this->JointName=NULL; this->SetJointName("Joint");
+  this->Active=1;
+}
+
+//----------------------------------------------------------------------------
+vtkpxArticulatedJointTransform::~vtkpxArticulatedJointTransform()
+{
+  if (this->RegionLabelImage!=NULL)
+    this->SetRegionLabelImage(NULL);
+
+  if (this->AlignmentTransform!=NULL)
+    this->SetAlignmentTransform(NULL);
+
+
+  this->AngleAxisTransform->Delete();
+  this->SimilarityTransform->Delete();
+  this->ZSimilarityTransform->Delete();
+
+  if (this->JointName!=NULL)
+    delete [] JointName;
+
+}
+
+
+void vtkpxArticulatedJointTransform::Identity()
+{
+  this->SimilarityTransform->Identity();
+  this->ZSimilarityTransform->Identity();
+}
+//----------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::ExternalSetRegionLabelImage(vtkImageData* img)
+{
+  this->SetRegionLabelImage(img);
+  if (this->RegionLabelImage!=NULL)
+    {
+      float mean=0.0;
+      for (int kk=0;kk<=2;kk++)
+	mean+=img->GetSpacing()[kk]/3.0;
+      this->SimilarityTransform->SetTranslationScale(mean);
+      this->ZSimilarityTransform->SetTranslationScale(mean);
+    }
+  else
+    {
+      this->SimilarityTransform->SetTranslationScale(1.0);
+      this->ZSimilarityTransform->SetTranslationScale(1.0);
+    }
+}
+//----------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::PrintSelf(ostream& os, vtkIndent indent)
+{
+  os << indent << "### " << this->GetClassName() << " ### \n";
+  os << indent << "Joint Name : " << this->JointName << "\n";
+  os << indent << "SeparateZRotation: " << this->SeparateZRotation << "\n";
+  os << indent << "BlendedMode: " << this->BlendedMode << "\n";
+  os << indent << "BlendingWindow: " << this->BlendingWindow << "\n";
+  os << indent << "ZBlendingSize: " << this->ZBlendingSize << "\n";
+  os << indent << "SmoothingMode: " << this->SmoothingMode << "\n";
+  os << indent << "SmoothingRadius: " << this->SmoothingRadius << "\n";
+  os << indent << "MinimumSectorAngle: " << this->MinimumSectorAngle << "\n";
+  os << indent << "CubicBlending: " << this->CubicBlending << "\n";
+  os << indent << "RegionLabelImage:      " << this->RegionLabelImage << "\n";
+  os << indent << "RegionLabelIndex:      " << this->RegionLabelIndex << "\n";
+  os << indent << "ChildRegionLabelIndex:      " << this->ChildRegionLabelIndex << "\n";
+  os << indent << "ChildRegionLabelIndex2:      " << this->ChildRegionLabelIndex2 << "\n";
+  os << indent << "SimilarityTransform: " << this->SimilarityTransform << "\n";
+  os << indent << "ZSimilarityTransform: " << this->ZSimilarityTransform << "\n";
+  os << indent << "AlignmentTransformIndex:" << this->AlignmentTransformIndex << "\n";
+  os << indent << "AlignmentTransform:" << this->AlignmentTransform << "\n";
+}
+
+vtkAbstractTransform *vtkpxArticulatedJointTransform::MakeTransform()
+{
+  return vtkpxArticulatedJointTransform::New(); 
+}
+
+//----------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::SetMode(int m)
+{
+  int newm=1;
+  if (m>=-1 && m<=5)
+    newm=m;
+  
+  if (m==1)
+    {
+      this->SeparateZRotation=1;
+      this->SimilarityTransform->SetMode(0);
+      this->ZSimilarityTransform->SetMode(9);
+    }
+  else
+    {
+      this->SeparateZRotation=0;
+      this->SimilarityTransform->SetMode(m);
+      this->ZSimilarityTransform->SetMode(-1);
+    }
+  if (m!=0 && m!=1 && m!=5)
+    this->SetBlendedMode(0);
+
+}
+//----------------------------------------------------------------------------  
+void vtkpxArticulatedJointTransform::SetActive(int m)
+{
+  m=(m>0);
+  if (this->Active==m)
+    return;
+
+  if (this->Active==1)
+    {
+      this->OldSimilarityMode=this->SimilarityTransform->GetMode();
+      this->OldZSimilarityMode=this->SimilarityTransform->GetMode();
+      this->OldBlendedMode=this->BlendedMode;
+      this->OldSeparateZRotation=this->SeparateZRotation;
+
+      this->SetModeToFixedParameters();
+      this->Active=0;
+    }
+  else
+    {
+      this->SeparateZRotation=this->OldSeparateZRotation;
+      this->SimilarityTransform->SetMode(this->OldSimilarityMode);
+      this->ZSimilarityTransform->SetMode(this->OldZSimilarityMode);
+      this->BlendedMode=this->OldBlendedMode;
+      this->Active=1;
+    }
+}
+//----------------------------------------------------------------------------  
+int vtkpxArticulatedJointTransform::Load(const char* fname)
+{
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  int ok=this->Load(fin);
+  gzclose(fin);
+  return ok;
+}
+
+int vtkpxArticulatedJointTransform::Load(gzFile fin)
+{
+  char pxtk_buffer[101];
+  gzgets(fin,pxtk_buffer,100);
+
+  int mode=1;
+  int tmp; float ftmp;
+
+  if (gzfindstringinstring(pxtk_buffer,"#vtkpxArticulatedJointTransform3")==0)
+    {
+      return 0;
+    }
+
+  gzgets(fin,pxtk_buffer,101); 
+  int a=strlen(pxtk_buffer);  pxtk_buffer[a-1]=(char)0;
+  this->SetJointName(pxtk_buffer);
+
+
+  this->SimilarityTransform->Load(fin);
+  this->ZSimilarityTransform->Load(fin);
+  gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100); sscanf(pxtk_buffer,"%d",&tmp);   this->SetSeparateZRotation(tmp);
+  gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100); sscanf(pxtk_buffer,"%f",&ftmp);  this->SetZBlendingSize(ftmp);
+
+  gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100); sscanf(pxtk_buffer,"%d",&tmp);   this->SetBlendedMode(tmp);
+  gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100); sscanf(pxtk_buffer,"%f",&ftmp);  this->SetBlendingWindow(ftmp);
+  gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100); sscanf(pxtk_buffer,"%d",&tmp);   this->SetSmoothingMode(tmp);
+  gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100); sscanf(pxtk_buffer,"%f",&ftmp);  this->SetSmoothingRadius(ftmp);
+  gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100); sscanf(pxtk_buffer,"%f",&ftmp);  this->SetMinimumSectorAngle(ftmp);
+  gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100); sscanf(pxtk_buffer,"%d",&tmp);   this->SetCubicBlending(tmp);
+  gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100); sscanf(pxtk_buffer,"%d",&tmp);   this->SetRegionLabelIndex(tmp);
+  gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100); sscanf(pxtk_buffer,"%d",&tmp);   this->SetChildRegionLabelIndex(tmp);
+  gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100); sscanf(pxtk_buffer,"%d",&tmp);   this->SetChildRegionLabelIndex2(tmp);
+  gzgets(fin,pxtk_buffer,100); gzgets(fin,pxtk_buffer,100); sscanf(pxtk_buffer,"%d",&tmp);   this->SetAlignmentTransformIndex(tmp);
+
+  this->Active=1;
+
+  return 1;
+}
+//----------------------------------------------------------------------------
+int vtkpxArticulatedJointTransform::Save(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+    return 0;
+  
+  int ok=this->Save(fout);
+  fclose(fout);
+  return ok;
+}
+
+int vtkpxArticulatedJointTransform::Save(FILE* fout)
+{
+  fprintf(fout,"#vtkpxArticulatedJointTransform3\n");
+  fprintf(fout,"%s\n",this->JointName);
+  this->SimilarityTransform->Save(fout);
+  this->ZSimilarityTransform->Save(fout);
+  fprintf(fout,"#SeparateZRotation\n%d\n",this->SeparateZRotation);
+  fprintf(fout,"#ZBlendingSize\n%.3f\n",this->ZBlendingSize);
+  fprintf(fout,"#BlendedMode\n%d\n",this->BlendedMode);
+  fprintf(fout,"#BlendingWindow\n%.2f\n",this->BlendingWindow);
+  fprintf(fout,"#SmoothingMode\n%d\n",this->SmoothingMode);
+  fprintf(fout,"#SmoothingRadius\n%.2f\n",this->SmoothingRadius);
+  fprintf(fout,"#MiniumSectorAngle\n%.2f\n",this->MinimumSectorAngle);
+  fprintf(fout,"#CubicBlending\n%d\n",this->CubicBlending);
+  fprintf(fout,"#RegionLabelIndex\n%d\n",this->RegionLabelIndex);
+  fprintf(fout,"#ChildRegionLabelIndex\n%d\n",this->ChildRegionLabelIndex);
+  fprintf(fout,"#ChildRegionLabelIndex2\n%d\n",this->ChildRegionLabelIndex2);
+  fprintf(fout,"#AlignmentTransformIndex\n%d\n",this->AlignmentTransformIndex);
+  return 1;
+}
+//----------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::Copy(vtkpxArticulatedJointTransform* other)
+{
+  if (other==NULL)
+    return;
+  
+  this->SetJointName(other->GetJointName());
+  this->SimilarityTransform->Copy(other->GetSimilarityTransform());
+  this->ZSimilarityTransform->Copy(other->GetZSimilarityTransform());
+  this->SetSeparateZRotation(other->GetSeparateZRotation());
+  this->SetBlendedMode(other->GetBlendedMode());
+  this->SetBlendingWindow(other->GetBlendingWindow());
+  this->SetSmoothingMode(other->GetSmoothingMode());
+  this->SetSmoothingRadius(other->GetSmoothingRadius());
+  this->SetMinimumSectorAngle(other->GetMinimumSectorAngle());
+  this->SetCubicBlending(other->GetCubicBlending());
+  this->SetRegionLabelIndex(other->GetRegionLabelIndex());
+  this->SetChildRegionLabelIndex(other->GetChildRegionLabelIndex());
+  this->SetChildRegionLabelIndex2(other->GetChildRegionLabelIndex2());
+  this->SetMode(other->GetMode());
+  this->SetRegionLabelImage(other->GetRegionLabelImage());
+  this->SetAlignmentTransform(other->GetAlignmentTransform());
+  this->SetAlignmentTransformIndex(other->GetAlignmentTransformIndex());
+}
+//----------------------------------------------------------------------------
+int vtkpxArticulatedJointTransform::IsInsideRegion(const double x[3])
+{
+  if (this->RegionLabelImage==NULL)
+    return -1;
+
+  int p=this->RegionLabelImage->FindPoint(x[0],x[1],x[2]);
+  if (p==-1)
+    return -1;
+  
+  int l=(int)this->RegionLabelImage->GetPointData()->GetScalars()->GetComponent(p,0);
+  if (l==-1)
+    return -1;
+
+  int md=0;
+  if (l==this->RegionLabelIndex)
+    md=1;
+  else if (l>=this->ChildRegionLabelIndex && l <= this->ChildRegionLabelIndex2 && this->ChildRegionLabelIndex<=this->ChildRegionLabelIndex2)
+    md=1;
+  
+
+  if (this->DetailMode)
+    fprintf(stderr,"p=%.1f,%.1f,%.1f l=%d mode=%d\n",x[0],x[1],x[2],l,md);
+
+  return md;
+}
+//----------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::CreateAngleAxisTransformation(double theta,vtkpxSimilarityTransform* trans)
+{
+  
+  float* origin=trans->GetOrigin();
+  float*   axis=trans->GetRotationAxis();
+
+  this->AngleAxisTransform->Identity();
+  this->AngleAxisTransform->PostMultiply();
+  this->AngleAxisTransform->Translate(-origin[0],-origin[1],-origin[2]);
+  if (isnan(theta))
+    {
+      fprintf(stderr,"Bad Theta *");
+      theta=0.0;
+    }
+  float magn=axis[0]*axis[0]+axis[1]*axis[1]+axis[2]*axis[2];
+  if (magn<0.1)
+    {
+      fprintf(stderr,"* Bad Axis %.2f %.2f %.2f\n",axis[0],axis[1],axis[2]);
+      axis[0]=1.0;
+      axis[1]=0.0;
+      axis[2]=0.0;
+      theta=0.0;
+    }
+
+  this->AngleAxisTransform->RotateWXYZ(theta,axis[0],axis[1],axis[2]);
+  this->AngleAxisTransform->Translate(origin);
+}
+// -----------------------------------------------------------------------------------
+double vtkpxArticulatedJointTransform::AdjustForZBlending(const double point[3],vtkpxSimilarityTransform* trans,float max)
+{
+  float* origin=trans->GetOrigin();
+  float*   axis=trans->GetRotationAxis();
+
+  double sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+    sum+=(point[ia]-origin[ia])*axis[ia];
+
+  double r=fabs(sum/max);
+  if (r>1.0)
+    r=1.0;
+
+  if (this->CubicBlending==0)
+    return r;
+  
+  return 3.0*pow(r,2.0)-2.0*pow(r,3.0);
+}
+
+// -----------------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::InternalTransformPoint(const double point[3], 
+							    double output[3])
+{
+  if (this->BlendedMode==0)
+    {
+      if (this->SeparateZRotation)
+	{
+	  this->ZSimilarityTransform->TransformPoint(point,output);
+	  this->SimilarityTransform->TransformPoint(output,output);
+	}
+      else
+	{
+	  this->SimilarityTransform->TransformPoint(point,output);
+	}
+      if (this->AlignmentTransform!=NULL)
+	this->AlignmentTransform->TransformPoint(output,output);
+      if (this->DetailMode)
+	fprintf(stderr,"Bl 0 ");
+
+      return;
+    }
+
+  int mode=this->IsInsideRegion(point);
+
+  if (mode==-1)
+    {
+      if (this->SeparateZRotation)
+	{
+	  this->ZSimilarityTransform->TransformPoint(point,output);
+	  this->SimilarityTransform->TransformPoint(output,output);
+	}
+      else
+	{
+	  this->SimilarityTransform->TransformPoint(point,output);
+	}
+      if (this->AlignmentTransform!=NULL)
+	this->AlignmentTransform->TransformPoint(output,output);
+      if (this->DetailMode)
+	fprintf(stderr,"Bl -1");
+      return;
+    }
+  else if (mode==0)
+    {
+      for (int ia=0;ia<=2;ia++)
+	output[ia]=point[ia];
+      if (this->AlignmentTransform!=NULL)
+	this->AlignmentTransform->TransformPoint(output,output);
+      if (this->DetailMode)
+	fprintf(stderr,"Bl 0");
+      return;
+    }
+
+  // Fun part begins here
+
+  // First Apply Z-Transform
+  double newpoint[3];
+  if (this->SeparateZRotation)
+    {
+      double phi=this->GetSmoothRotationAngle(point,this->ZSimilarityTransform);
+      // Scale phi somewhat
+      phi=phi*this->AdjustForZBlending(point,this->ZSimilarityTransform,this->ZBlendingSize*this->ZSimilarityTransform->GetTranslationScale());
+
+
+      this->CreateAngleAxisTransformation(phi,this->ZSimilarityTransform);
+      this->AngleAxisTransform->TransformPoint(point,newpoint);
+      if (this->DetailMode)
+	fprintf(stderr,"bl phi* =%.2f",phi);
+
+
+    }
+  else
+    {
+      for (int i=0;i<=2;i++)
+	newpoint[i]=point[i];
+    }
+
+  double theta=this->GetSmoothRotationAngle(newpoint,this->SimilarityTransform);
+  this->CreateAngleAxisTransformation(theta,this->SimilarityTransform);
+  this->AngleAxisTransform->TransformPoint(newpoint,output);
+  if (this->DetailMode)
+    fprintf(stderr,", theta=%.2f\n",theta);
+     
+  if (this->AlignmentTransform!=NULL)
+    this->AlignmentTransform->TransformPoint(output,output);
+}
+//------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::InternalTransformDerivative(const double point[3],
+								 double output[3],
+								 double derivative[3][3])
+{
+  for (int ia=0;ia<=2;ia++)
+    for (int ja=0;ja<=2;ja++)
+      derivative[ia][ja]=double(ia==ja);
+	
+  this->InternalTransformPoint(point,output);
+  return;
+}
+ // -----------------------------------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::InternalTransformPoint(const float point[3],float output[3])
+{
+  double p1[3],p2[3]; 
+  for (int i=0;i<=2;i++) 
+    p1[i]=point[i];
+  this->InternalTransformPoint(p1,p2);
+  for (int i=0;i<=2;i++) 
+    output[i]=p2[i];
+}
+// -----------------------------------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::InternalTransformDerivative(const float point[3],
+								 float output[3],
+								 float derivative[3][3])
+{
+  double p1[3],p2[3],der[3][3];
+  for (int i=0;i<=2;i++) 
+    p1[i]=point[i];
+
+  this->InternalTransformDerivative(p1,p2,der);
+  for (int i=0;i<=2;i++) 
+    {
+      output[i]=p2[i];
+      for (int j=0;j<=2;j++)
+	derivative[i][j]=der[i][j];
+    }
+}
+//----------------------------------------------------------------------------
+double vtkpxArticulatedJointTransform::SearchForInterface(const double x[3],double maxtheta,double stepsize,vtkpxSimilarityTransform* trans)
+{
+  double tx[3];
+  double dtheta=stepsize;
+  double theta=0.0;
+  int found=0;
+  
+  while (found==0 && fabs(theta)<fabs(maxtheta))
+    {
+      theta+=dtheta;
+      this->CreateAngleAxisTransformation(theta,trans);
+      this->AngleAxisTransform->TransformPoint(x,tx);
+      if (this->DetailMode==1)
+	fprintf(stderr," *** %.2f ",theta);
+      if (this->IsInsideRegion(tx)==0)
+	found=1;
+    }
+  return theta;
+
+}
+//----------------------------------------------------------------------------
+//
+//   Implement Causal Blending, Assume Convex Interface
+//
+//----------------------------------------------------------------------------
+double vtkpxArticulatedJointTransform::GetActualRotationAngle(const double x[3],vtkpxSimilarityTransform* trans)
+{
+
+  // Step 1:
+  // Check if we need to blend at all by rotating by (2*theta), 
+
+  double tx[3];
+  
+  double RotationAngle=trans->GetRotationAngle();
+
+  if (RotationAngle==0.0)
+    return 0.0;
+
+  double threshold[2] = { 1.0+this->BlendingWindow,this->BlendingWindow };
+
+  int    dobisection[2]={ 1, 1 };
+  double upperangle[2]= { threshold[0]*RotationAngle, -threshold[1]*RotationAngle };
+  
+  int maxside=this->BlendedMode; // i.e. 1 or 2
+  
+  if (this->DetailMode)
+    fprintf(stderr,"\n\nInit x=(%.1f,%.1f,%.1f) thr=(%.1f,%.1f) dobis=%d,%d, upperangle=%.2f %.2f (Angle=%.2f)\n",
+	    x[0],x[1],x[2],
+	    threshold[0],threshold[1],
+	    dobisection[0],dobisection[1],
+	    upperangle[0],upperangle[1],
+	    RotationAngle);
+
+  for (int side=0;side<maxside;side++)
+    {
+      if (this->MinimumSectorAngle>fabs(upperangle[side]))
+	{
+	  if (this->DetailMode)
+	    fprintf(stderr,"Fast Search: side=%d upper=%.2f\n",side,upperangle[side]);
+
+	  this->CreateAngleAxisTransformation(upperangle[side],trans);
+	  this->AngleAxisTransform->TransformPoint(x,tx);
+
+	  if (this->IsInsideRegion(tx)!=0)
+	    dobisection[side]=0;
+	}
+      else
+	{
+	  double step=this->MinimumSectorAngle;
+	  if (upperangle[side]<0.0)
+	    {
+	      step=-this->MinimumSectorAngle;
+	      if (step>-1.0)
+		step=-1.0;
+	    }
+	  else
+	    {
+	      if (step<1.0)
+		step=1.0;
+	    }
+	  if (this->DetailMode)
+	    fprintf(stderr,"Slow Search side=%d upper=%.2f step=%.2f\n",side,upperangle[side],step);
+
+	  double th=this->SearchForInterface(x,upperangle[side],step,trans);
+	  if (fabs(th)>fabs(upperangle[side]))
+	    dobisection[side]=0;
+	  else
+	    upperangle[side]=th;
+	}
+    }
+
+  if (this->DetailMode)
+    fprintf(stderr," dobis=%d,%d, upperangle=%.2f %.2f (Angle=%.2f)\n",
+	    dobisection[0],dobisection[1],
+	    upperangle[0],upperangle[1],
+	    RotationAngle);
+
+
+  if (( dobisection[0]+dobisection[1] == 0 ) ||
+      ( dobisection[0] == 0 && this->BlendedMode !=2 ))
+      return RotationAngle;
+
+  double ratio[2] = { threshold[0]+0.01,threshold[1]+0.01};
+
+  for (int side=0;side<maxside;side++)
+    {
+      if (dobisection[side])
+	{
+	  // Do Bisection to establish angle of change 
+	  float outsidetheta=upperangle[side];
+	  float insidetheta=0.0;
+	  
+	  float thr=fabs(0.01);// *RotationAngle);
+	  float theta=0.5*(outsidetheta+insidetheta);
+	  
+	  while (fabs(outsidetheta-insidetheta)>thr)
+	    {
+	      this->CreateAngleAxisTransformation(theta,trans);
+	      this->AngleAxisTransform->TransformPoint(x,tx);
+	      if (this->DetailMode)
+		fprintf(stderr,"Bisection Side=%d, in=%.2f out=%.2f theta=%.2f \t",side,insidetheta,outsidetheta,theta);
+	      
+	      int isinside=this->IsInsideRegion(tx);
+	      
+	      if (isinside!=0)
+		insidetheta=theta;
+	      else
+		outsidetheta=theta;
+	      
+	      theta=0.5*(outsidetheta+insidetheta);
+	      
+	    }
+	  ratio[side]=fabs(theta/RotationAngle);
+	  if (this->DetailMode)
+	    fprintf(stderr,"Bisection Side=%d, theta=%.2f ratio=%.4f\n\n",side,theta,ratio[side]);
+	}
+    }
+
+  // Three cases
+  // Case 1 -- folding issue, no smoothing
+  double newangle=RotationAngle;
+  double sumratio=fabs(ratio[1])+fabs(ratio[0]);
+
+  if (this->DetailMode)
+    fprintf(stderr,"Blending, ratios=%.2f,%.2f  thresholds=%.2f,%.2f sumratio=%.2f\n",
+	    ratio[0],ratio[1],threshold[0],threshold[1],sumratio);
+
+  if  (ratio[0]<threshold[0] && ratio[1]>threshold[1])
+    {
+      // Fold No Blend
+      double x=fabs(ratio[0]);
+      double w=fabs(threshold[0]);
+
+      if (CubicBlending)
+	{
+	  newangle=(x-(2.0*pow(x,3.0)/pow(w,3.0)-3.0*pow(x,2.0)/pow(w,2.0)+x))*RotationAngle;
+	}
+      else
+	{
+	  newangle=fabs(ratio[0]/threshold[0])*RotationAngle;
+	}
+      if (this->DetailMode)
+	fprintf(stderr,"Fold cubic=%d, newangle=%.2f\n",this->CubicBlending,newangle);
+    }
+  else if (ratio[1] < threshold[1] && ratio[0]>threshold[0])
+    {
+      // Blend No Fold
+      double x=fabs(ratio[1]);
+      double w=fabs(threshold[1]);
+      if (CubicBlending)
+	{
+	  newangle=(x-(2.0*pow(x,3.0)/pow(w,3.0)-3.0*pow(x,2.0)/pow(w,2.0)+x))*RotationAngle;
+	}
+      else
+	{
+	  newangle=(ratio[1]/threshold[1])*RotationAngle;
+	}
+      if (this->DetailMode)
+	fprintf(stderr,"Smooth cubic=%d, newangle=%.2f\n",this->CubicBlending,newangle);
+	
+    }
+  else
+    {
+      double midpoint=(threshold[1]*sumratio)/(threshold[0]+threshold[1]);
+      int double0=-1;
+
+      if (CubicBlending)
+	{
+	  newangle=fabs(ratio[0]/threshold[0])*RotationAngle;
+	}
+      else 
+	{
+	  if (midpoint<ratio[1])
+	    {
+	      newangle=fabs(ratio[0]/threshold[0])*RotationAngle;
+	      double0=0;
+	    }
+	  else
+	    {
+	      newangle=(ratio[1]/threshold[1])*RotationAngle;
+	      double0=1;
+	    }
+	}
+
+      if (this->DetailMode)
+	fprintf(stderr,"Double Blend  midpoint=%.2f double0=%d newangle=%.2f\n",
+		midpoint,double0,newangle);
+  
+    }
+
+
+  return newangle;
+
+}
+
+// ----------------------------------------------------------------------------------------------
+vtkImageData* vtkpxArticulatedJointTransform::ComputeAllAngles()
+{
+  if (this->RegionLabelImage==NULL)
+    return NULL;
+
+  vtkImageData* output=vtkImageData::New();
+  output->CopyStructure(this->RegionLabelImage);
+  output->SetScalarTypeToFloat();
+  output->SetNumberOfScalarComponents(1);
+  output->AllocateScalars();
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  out->FillComponent(0,0.0);
+  int np=out->GetNumberOfTuples();
+
+
+  for (int i=0;i<np;i++)
+    {
+      double x[3]; output->GetPoint(i,x);
+      
+      if (this->IsInsideRegion(x)==1)
+	{
+	  double theta=this->GetSmoothRotationAngle(x,this->SimilarityTransform);
+	  out->SetComponent(i,0,theta);
+	}
+    }
+
+  return output;
+}
+// ----------------------------------------------------------------------------------------------      
+double vtkpxArticulatedJointTransform::GetSmoothRotationAngle(const double x[3],vtkpxSimilarityTransform* trans)
+{
+  double RotationAngle=trans->GetRotationAngle();
+  //  if (this->BlendedMode==0)
+  //return RotationAngle;
+
+  double theta=this->GetActualRotationAngle(x,trans);
+  if (!this->SmoothingMode)
+    return theta;
+
+  float origin[3]; trans->GetOrigin(origin);
+  float axis[3];   trans->GetRotationAxis(axis);
+  double r[3],sum=0.0;
+  for (int i=0;i<=2;i++)
+    {
+      r[i]=x[i]-origin[i];
+      sum+=r[i]*axis[i];
+    }
+
+  if (this->DetailMode) fprintf(stderr,"axis=%.2f,%.2f,%.2f\n",axis[0],axis[1],axis[2]);
+  if (this->DetailMode) fprintf(stderr,"r   =%.2f,%.2f,%.2f\n",r[0],r[1],r[2]);
+
+  
+  double magn=0.0;
+  for (int i=0;i<=2;i++)
+    {
+      r[i]-=sum*axis[i];
+      magn+=r[i]*r[i];
+    }
+
+  if (this->DetailMode) fprintf(stderr,"r   =%.2f,%.2f,%.2f\n",r[0],r[1],r[2]);
+
+  for (int i=0;i<=2;i++)
+    r[i]/=sqrt(magn);
+  
+  if (this->DetailMode) fprintf(stderr,"r   =%.2f,%.2f,%.2f\n",r[0],r[1],r[2]);
+
+  double thetasum=0.0;
+  for (int i=0;i<4;i++)
+    {
+      double newx[3] = { x[0],x[1],x[2] };
+      switch(i)
+	{
+	case 0:
+	  for (int j=0;j<=2;j++)
+	    newx[j]=x[j]-this->SmoothingRadius*axis[j];
+	  break;
+	case 1:
+	  for (int j=0;j<=2;j++)
+	    newx[j]=x[j]+this->SmoothingRadius*axis[j];
+	  break;
+	case 3:
+	  for (int j=0;j<=2;j++)
+	    newx[j]=x[j]-this->SmoothingRadius*r[j];
+	  break;
+	case 4:
+	  for (int j=0;j<=2;j++)
+	    newx[j]=x[j]+this->SmoothingRadius*r[j];
+	  break;
+	}
+      thetasum+=0.25*this->GetActualRotationAngle(newx,trans);
+    }
+      
+  return 0.5*(theta+thetasum);
+}
+// ----------------------------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::AdjustOriginToBeOutside(double gap)
+{
+  
+  float origin[3]; this->SimilarityTransform->GetOrigin(origin);
+  float zaxis[3];  this->SimilarityTransform->GetLocalZAxis(zaxis);
+  double px[3];
+
+  // do bisection assume we are < 20.0 from boundary and go
+  // ------------------------------------------------------
+
+
+  int dim[3]; this->RegionLabelImage->GetDimensions(dim);
+  double sp[3]; this->RegionLabelImage->GetSpacing(sp);
+  double ori[3]; this->RegionLabelImage->GetOrigin(ori);
+  // fprintf(stderr,"Dimensions =%dx%dx%d spacing=%.2fx%.2fx%.2f\n",dim[0],dim[1],dim[2],sp[0],sp[1],sp[2]);
+
+
+  for (int k=0;k<=2;k++)
+    px[k]=origin[k];
+
+  int p=this->RegionLabelImage->FindPoint(px[0],px[1],px[2]);
+  int pv=(int)this->RegionLabelImage->GetPointData()->GetScalars()->GetComponent(p,0);
+
+  this->RegionLabelImage->GetPoint(p,px);
+  for (int i=0;i<=2;i++)
+    px[i]=(px[i]-ori[i])/sp[i];
+
+  int newp=int(px[2]*(dim[0]*dim[1])+px[1]*dim[0]+px[0]);
+  int p2=(int)this->RegionLabelImage->GetScalarComponentAsDouble(int(0.5+px[0]),int(0.5+px[1]),int(0.5+px[2]),0);
+
+  /*  fprintf(stderr,"Testing %.2f %.2f %.2f (%d,%d,%d)  p=%d(%d)  newp=%d p2=%d    (ind=%d, children=%d,%d)\n",
+	  origin[0],origin[1],origin[2],
+	  int(0.5+px[0]),int(0.5+px[1]),int(0.5+px[2]),
+	  p,pv,
+	  newp,p2,
+	  this->RegionLabelIndex,
+	  this->ChildRegionLabelIndex,this->ChildRegionLabelIndex2);*/
+
+
+  //  this->SetDetailMode(1);
+
+  for (int k=0;k<=2;k++)
+    px[k]=origin[k];
+  
+  int isinside=this->IsInsideRegion(px);
+
+  //  fprintf(stderr,"Ininside (%.2f,%.2f,%.2f) = %d\n",px[0],px[1],px[2],isinside);
+
+
+  float inside =30.0;
+  float outside=-30.0;
+
+  float thr=0.2;
+  float location=0.5*(outside+inside);
+	  
+  while (fabs(outside-inside)>thr)
+    {
+      fprintf(stderr,"Bisection %.2f : %.2f  testing %.2f ",inside,outside,location);
+      for (int i=0;i<=2;i++)
+	px[i]=origin[i]+location*zaxis[i];
+      int isinside=this->IsInsideRegion(px);
+
+      int p=this->RegionLabelImage->FindPoint(px[0],px[1],px[2]);
+      int pv=(int)this->RegionLabelImage->GetPointData()->GetScalars()->GetComponent(p,0);
+
+      fprintf(stderr,"px=(%.2f %.2f %.2f) isinside=%d (p=%d pv=%d)\n",px[0],px[1],px[2],isinside,p,pv);
+	      
+      if (isinside!=0)
+	inside=location;
+      else
+	outside=location;
+      
+      location=0.5*(outside+inside);
+	      
+    }
+
+  for (int i=0;i<=2;i++)
+    px[i]=origin[i]+location*zaxis[i];
+
+  /*  fprintf(stderr,"Distance of (%.2f,%.2f,%.2f) from boundary = %.2f (%.2f,%.2f,%.2f) \t new origin (%.2f) = ",
+      origin[0],origin[1],origin[2],location,px[0],px[1],px[2],gap);*/
+
+  // New z-axis
+  this->SetFreezeUpdates(1);
+  
+  for (int i=0;i<=2;i++)
+    {
+      origin[i]=px[i]-fabs(gap)*zaxis[i];
+      if (i==2)
+	this->SetFreezeUpdates(0);
+      this->Put(3+i,origin[i]);
+    }
+  this->SimilarityTransform->GetOrigin(origin);
+  fprintf(stderr,"%.2f %.2f %.2f\n",origin[0],origin[1],origin[2]);
+    
+}
+
+// ----------------------------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::SetOriginLocalAxis(double ori[3],double p1[3],double p2[3])
+{
+  fprintf(stderr,"\n------------------------------------------------------\norigin=%.2f,%.2f,%.2f\n",ori[0],ori[1],ori[2]);
+  fprintf(stderr,"p1=%.2f,%.2f,%.2f\n",p1[0],p1[1],p1[2]);
+  fprintf(stderr,"p2=%.2f,%.2f,%.2f\n",p2[0],p2[1],p2[2]);
+
+  for (int j=0;j<=2;j++)
+    {
+      p1[j]=p1[j]-ori[j];
+      p2[j]=p2[j]-ori[j];
+    }
+  
+  vtkMath::Normalize(p1);
+  vtkMath::Normalize(p2);
+
+  double a=vtkMath::Dot(p1,p2);
+  for (int ia=0;ia<=2;ia++)
+    p2[ia]=p2[ia]-a*p1[ia];
+  
+  double p3[3];
+  vtkMath::Cross(p1,p2,p3);
+
+
+  fprintf(stderr,"p1=%.2f,%.2f,%.2f\n",p1[0],p1[1],p1[2]);
+  fprintf(stderr,"p2=%.2f,%.2f,%.2f\n",p2[0],p2[1],p2[2]);
+  fprintf(stderr,"p3=%.2f,%.2f,%.2f\n",p3[0],p3[1],p3[2]);
+
+
+  int isorigininside=this->IsInsideRegion(ori);
+  fprintf(stderr,"Origin isinside=%d\n",isorigininside);
+
+  if (this->BlendedMode!=0)
+    {
+      // Check which way to go ....
+      
+      double inside=-5.0,outside=5.0;
+      
+      double tp[3];
+      double test=inside;
+      
+      for (int ia=0;ia<=2;ia++)
+	tp[ia]=ori[ia]+test*p3[ia];
+      
+      
+      int isinside=this->IsInsideRegion(tp);
+
+      if (!isinside)
+	{
+	  outside=-5.0;
+	  inside=5.0;
+	}
+
+      fprintf(stderr,"ins=%.2f outs=%.2f tp=%.2f %.2f %.2f test=%.2f insid=%d\n",
+	      inside,outside,0.5*tp[0],0.5*tp[1],0.5*tp[2],test,isinside);
+
+      test=0.0;
+      while ( fabs(outside-inside)>0.1)
+	{
+	  for (int ia=0;ia<=2;ia++)
+	    tp[ia]=ori[ia]+test*p3[ia];
+
+	  isinside=this->IsInsideRegion(tp);
+	  fprintf(stderr,"ins=%.2f outs=%.2f tp=%.2f %.2f %.2f test=%.2f insid=%d\n",
+		  inside,outside,0.5*tp[0],0.5*tp[1],0.5*tp[2],test,isinside);
+	  
+	  if (!isinside)
+	    outside=test;
+	  else
+	    inside=test;
+	  test=0.5*(outside+inside);
+
+	}
+      
+      double shift=0.0;
+      if (isorigininside)
+	{
+	  shift=fabs(test)+3.0;
+	  if (test<0.0)
+	    shift=-shift;
+	}
+      else
+	{
+	  if (fabs(test)<3.0)
+	    {
+	      shift=-(3.0-fabs(test));
+	      if (test<0.0)
+		shift=-shift;
+	    }
+	}
+
+      fprintf(stderr,"\t Test=%.2f shift=%.2f \n",test,shift);
+      
+      for (int ia=0;ia<=2;ia++)
+	ori[ia]=ori[ia]+shift*p3[ia];
+    }
+
+  this->SetFreezeUpdates(1);
+  for (int i=0;i<=2;i++)
+    {
+      if (i==2)
+	this->SetFreezeUpdates(0);
+      this->Put(3+i,ori[i]);
+    }
+       
+  int flag=this->IsInsideRegion(ori);
+  fprintf(stderr,"Origin=%.2f,%.2f,%.2f (%.2f,%.2f,%.2f) inside=%d (***)\n",ori[0],ori[1],ori[2],0.5*ori[0],0.5*ori[1],0.5*ori[2],flag);
+  fprintf(stderr,"X- Axis=%.2f,%.2f,%.2f\n\n",p1[0],p1[1],p1[2]);
+  fprintf(stderr,"Z- Axis=%.2f,%.2f,%.2f\n\n",p3[0],p3[1],p3[2]);
+
+  float x[3],z[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      x[ia]=p1[ia];
+      z[ia]=p3[ia];
+    }
+  this->SetLocalXZAxis(x,z);
+}
+
+
+// ----------------------------------------------------------------------------------------------
+int vtkpxArticulatedJointTransform::GetNumberOfParameters()
+{
+  int nt=this->SimilarityTransform->GetNumberOfParameters();
+  if (this->SeparateZRotation==1)
+    nt+=this->ZSimilarityTransform->GetNumberOfParameters();
+  return nt;
+}
+// ----------------------------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::SetParameters(vtkDoubleArray *parameters,int InputOffset)
+{
+  this->SimilarityTransform->SetParameters(parameters,InputOffset);
+  if (this->SeparateZRotation==1)
+    {
+      int nt=this->SimilarityTransform->GetNumberOfParameters();
+      this->ZSimilarityTransform->SetParameters(parameters,InputOffset+nt);
+    }
+  return;
+}
+// ----------------------------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::GetParameters(vtkDoubleArray *parameters,int InputOffset)
+{
+  this->SimilarityTransform->GetParameters(parameters,InputOffset);
+  if (this->SeparateZRotation==1)
+    {
+      int nt=this->SimilarityTransform->GetNumberOfParameters();
+      this->ZSimilarityTransform->GetParameters(parameters,InputOffset+nt);
+    }
+}
+// ----------------------------------------------------------------------------------------------
+void vtkpxArticulatedJointTransform::SetLocalXZAxis(float x[3],float z[3])
+{
+  this->SimilarityTransform->SetLocalXZAxis(x,z);
+  this->ZSimilarityTransform->SetLocalXZAxis(x,z);
+}
+// ----------------------------------------------------------------------------------------------
+int vtkpxArticulatedJointTransform::GetMode()
+{
+  if (this->SeparateZRotation==1)
+    return this->SimilarityTransform->GetMode();
+  else
+    return 1;
+}
+// ----------------------------------------------------------------------------------------------
+// Description:
+// Puts a transformation parameter (transformation matrix is updated)
+void  vtkpxArticulatedJointTransform::Put(int a, float v)
+{
+  if (this->SeparateZRotation==0)
+    {
+      this->SimilarityTransform->Put(a,v); 
+      return;
+    }
+
+  if (a<6 || a>8)
+    {
+      this->SimilarityTransform->Put(a,v);  
+      this->ZSimilarityTransform->Put(a,v);  
+    }
+  else if (a==8)
+    {
+      this->ZSimilarityTransform->Put(6,v);  
+    }
+  else
+    {
+      this->SimilarityTransform->Put(a,v);  
+    }
+}
+
+void  vtkpxArticulatedJointTransform::Set(int a, float v)
+{
+  this->Put(a,v);
+}
+
+
+float vtkpxArticulatedJointTransform::Get(int a)
+{
+  if (this->SeparateZRotation==0 || a!=8)
+    return this->SimilarityTransform->Get(a); 
+  
+  return this->ZSimilarityTransform->Get(6);  
+}
+
+
+void vtkpxArticulatedJointTransform::SetFreezeUpdates(int a)
+{
+  this->ZSimilarityTransform->SetFreezeUpdates(a); 
+  this->SimilarityTransform->SetFreezeUpdates(a); 
+}
+
+int  vtkpxArticulatedJointTransform::GetFreezeUpdates()
+{
+  return this->SimilarityTransform->GetFreezeUpdates();
+}
+
+// ------------------------------------------------------------------------------------
+
+int vtkpxArticulatedJointTransform::InitializeAngles(double source0[3],double target0[3])
+{
+  vtkMath::Normalize(source0);
+  vtkMath::Normalize(target0);
+
+  double source[3],target[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      source[ia]=source0[ia];
+      target[ia]=target0[ia];
+    }
+
+  vtkMath::Normalize(target);
+
+  float z1[3]; this->GetLocalZAxis(z1);
+  double z[3]; 
+  for (int ia=0;ia<=2;ia++)
+    z[ia]=z1[ia];
+
+  vtkMath::Normalize(z);
+
+  double temp[3];
+
+  if (this->SeparateZRotation)
+    {
+      double p1[3],p2[3];
+  
+      double a1=vtkMath::Dot(z,source);
+      double a2=vtkMath::Dot(z,target);
+
+      fprintf(stderr,"\t\t --------------- Beginning Z Rotation -----------------------------\n");
+      fprintf(stderr,"\t\t Source = (%.2f,%.2f,%.2f) %.2f \n",source[0],source[1],source[2],a1);
+      fprintf(stderr,"\t\t Target = (%.2f,%.2f,%.2f) %.2f \n",target[0],target[1],target[2],a2);
+      
+      for (int ia=0;ia<=2;ia++)
+	{
+	  source[ia]=source[ia]-a1*z[ia];
+	  target[ia]=target[ia]-a2*z[ia];
+	}
+      vtkMath::Normalize(source);
+      vtkMath::Normalize(target);
+      double cosangle=vtkMath::Dot(source,target);
+
+      fprintf(stderr,"\t\t Source' = (%.2f,%.2f,%.2f) \n",source[0],source[1],source[2]);
+      fprintf(stderr,"\t\t Target' = (%.2f,%.2f,%.2f) \n",target[0],target[1],target[2]);
+      fprintf(stderr,"\t\t Z-axis  = (%.2f,%.2f,%.2f) \n",z[0],z[1],z[2]);
+      
+      vtkMath::Cross(source,target,temp);
+      double sign=1.0;
+      if (vtkMath::Dot(temp,z)<0.0)
+	sign=-1.0;
+      
+      double phi=sign*acos(cosangle)*180.0/vtkMath::Pi();
+      fprintf(stderr,"\t\t cosangle=%.3f phi=%.2f\n",cosangle,phi);
+
+      // Now Find Residual
+      this->ZSimilarityTransform->Put(6,phi);
+
+      vtkTransform* tr=vtkTransform::New();
+      tr->RotateWXYZ(phi,z[0],z[1],z[2]);
+      tr->TransformPoint(source0,source);
+    }
+  else
+    {
+      for (int ia=0;ia<=2;ia++)
+	source[ia]=source0[ia];
+    }
+
+  for (int ia=0;ia<=2;ia++)
+    target[ia]=target0[ia];
+  
+  fprintf(stderr,"\t\t --------------- Beginning XY Rotation -----------------------------\n");
+  fprintf(stderr,"\t\t  source=(%.2f,%.2f,%.2f)\n",source[0],source[1],source[2]);
+  fprintf(stderr,"\t\t  target=(%.2f,%.2f,%.2f)\n",target[0],target[1],target[2]);
+  
+  float x1[3]; this->GetLocalXAxis(x1);
+  double x[3]; 
+  for (int ia=0;ia<=2;ia++)
+    x[ia]=x1[ia];
+
+  vtkMath::Normalize(x);
+
+  double newaxis[3];
+  vtkMath::Cross(source,target,newaxis);
+  vtkMath::Normalize(newaxis);
+  fprintf(stderr,"\t\t Newaxis = (%.2f,%.2f,%.2f)\n\t\t zaxis=(%.2f,%.2f,%.2f)\n",newaxis[0],newaxis[1],newaxis[2],z[0],z[1],z[2]);
+
+  double dt=vtkMath::Dot(newaxis,z);
+  for (int ia=0;ia<=2;ia++)
+    newaxis[ia]=newaxis[ia]-dt*z[ia];
+  vtkMath::Normalize(newaxis);
+  
+  fprintf(stderr,"\t\t Newaxis' = (%.2f,%.2f,%.2f) %.2f \n",newaxis[0],newaxis[1],newaxis[2],dt);
+  double a1=vtkMath::Dot(source,newaxis);
+  double a2=vtkMath::Dot(target,newaxis);
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      source[ia]=source[ia]-a1*newaxis[ia];
+      target[ia]=target[ia]-a2*newaxis[ia];
+    }
+
+  vtkMath::Normalize(source);
+  vtkMath::Normalize(target);
+  double cosangle=vtkMath::Dot(source,target);
+
+  vtkMath::Cross(source,target,temp);
+  double sign=1.0;
+  if (vtkMath::Dot(temp,newaxis)<0.0)
+    sign=-1.0;
+  
+  double theta=sign*acos(cosangle)*180.0/vtkMath::Pi();
+
+
+  fprintf(stderr,"\t\t Source' = (%.2f,%.2f,%.2f) %.2f \n",source[0],source[1],source[2],a1);
+  fprintf(stderr,"\t\t Target' = (%.2f,%.2f,%.2f) %.2f \n",target[0],target[1],target[2],a2);
+  fprintf(stderr,"\t\t Cosangle=%.2f theta=%.2f\n",cosangle,theta);
+
+  double theta2=0.0,cosangle2=1.0;
+
+  if (fabs(theta)>2.0)
+    {
+      vtkMath::Cross(x,newaxis,temp);
+      double sign=1.0;
+      if (vtkMath::Dot(temp,z)<0.0)
+	sign=-1.0;
+      
+      fprintf(stderr,"\t\t X-axis = (%.2f,%.2f,%.2f)  \n",x[0],x[1],x[2]);
+      cosangle2=vtkMath::Dot(x,newaxis);
+      theta2=sign*acos(cosangle2)*180.0/vtkMath::Pi();
+    }
+
+  fprintf(stderr,"\t\t Cosangle2=%.2f theta2=%.2f\n",cosangle2,theta2);
+
+  this->SimilarityTransform->Put(7,theta2);
+  this->SimilarityTransform->Put(6,theta);
+
+
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Registration/vtkpxArticulatedJointTransform.h b/bioimagesuite30_src/Registration/vtkpxArticulatedJointTransform.h
new file mode 100644
index 0000000..4b9acbc
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxArticulatedJointTransform.h
@@ -0,0 +1,327 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkpxArticulatedJointTransform - describes linear transformations via a 4x4 matrix
+// .SECTION Description
+// This generates a similarity/rigid transform based on
+// (a) center of rotation (3 params)
+// (b) scaling parameter (1 param)
+// (c) roation angles (3 params)
+// (d) translation (3 params)
+// (e) additional transformation (vtkMatrixToLinearTransform)
+//
+// 
+
+#ifndef __vtkpxArticulatedJointTransform_h
+#define __vtkpxArticulatedJointTransform_h
+
+#include "vtkpxSimilarityTransform.h"
+#include "vtkImageData.h"
+#include "vtkTransform.h"
+#include "vtkAbstractTransform.h"
+
+class vtkpxArticulatedJointTransform : public vtkAbstractTransform
+{
+ public:
+  static vtkpxArticulatedJointTransform *New();
+  vtkTypeMacro(vtkpxArticulatedJointTransform,vtkAbstractTransform);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Set the parameters from array
+  // This is key for Optimization Classes 
+  void SetParameters(vtkDoubleArray *parameters,int InputOffset=0);
+  // { this->SimilarityTransform->SetParameters(parameters,InputOffset);}
+  void GetParameters(vtkDoubleArray *parameters,int InputOffset=0);
+  // { this->SimilarityTransform->GetParameters(parameters,InputOffset);}
+
+  // Description:
+  // Detail Mode , lots of fprintf statements
+  vtkGetMacro(DetailMode,int);
+  vtkSetClampMacro(DetailMode,int,0,1);
+
+  // Description:
+  // Smooth Rotation Angle across r,z
+  vtkGetMacro(SmoothingMode,int);
+  vtkSetClampMacro(SmoothingMode,int,0,1);
+
+  // Description:
+  // Smooth Rotation Angle across r,z
+  vtkGetMacro(SmoothingRadius,float);
+  vtkSetClampMacro(SmoothingRadius,float,0.1,15.0);
+
+  // Description:
+  // Smooth Rotation Angle across r,z
+  vtkGetMacro(ZBlendingSize,float);
+  vtkSetClampMacro(ZBlendingSize,float,0.1,40.0);
+
+  // Description:  
+  // 0 = No Blending
+  // 1 = Avoid Folding
+  // 2 = Smooth Wake + Avoid Folding
+  vtkGetMacro(BlendedMode,int);
+  vtkSetClampMacro(BlendedMode,int,0,2);
+
+  // Description:  
+  // SeparateZRotation
+  vtkGetMacro(SeparateZRotation,int);
+  vtkSetClampMacro(SeparateZRotation,int,0,1);
+
+
+
+  // Description:  
+  // 0 = No Blending
+  // 1 = Avoid Folding
+  // 2 = Smooth Wake + Avoid Folding
+  vtkGetMacro(BlendingWindow,float);
+  vtkSetClampMacro(BlendingWindow,float,0.05,3.0);
+
+
+  // Description:
+  // Cubic Blending fits cubic polynomial for $C^1$ continuity, otherwise linear
+  vtkGetMacro(CubicBlending,int);
+  vtkSetClampMacro(CubicBlending,int,0,1);
+
+
+  // Description:
+  // Active = 0 is fixed parameters, 1 = enabled
+  vtkGetMacro(Active,int);
+  virtual void SetActive(int active);
+
+
+  // Description:
+  // Fast Interface Search
+  vtkGetMacro(MinimumSectorAngle,float);
+  vtkSetClampMacro(MinimumSectorAngle,float,0.0,180.0);
+
+  // Description:
+  // RegionLabelImage
+  vtkGetObjectMacro(RegionLabelImage,vtkImageData);
+  virtual void ExternalSetRegionLabelImage(vtkImageData* img);
+
+
+
+  // Description:
+  // Index in Region
+  vtkGetMacro(RegionLabelIndex,int);
+  vtkSetMacro(RegionLabelIndex,int);
+
+  // Description:
+  // Child Index in Region
+  // If ChildRegionLabelIndex == 1000 then all regions > RegionLabelIndex are children by default, in this case ChildRegionLabelIndex2 is ignored!
+  vtkGetMacro(ChildRegionLabelIndex,int);
+  vtkSetMacro(ChildRegionLabelIndex,int);
+
+  // Description:
+  // Index in Region
+  vtkGetMacro(ChildRegionLabelIndex2,int);
+  vtkSetMacro(ChildRegionLabelIndex2,int);
+ 
+  // Descrpition:
+  // Get Similarity Transform
+  vtkGetObjectMacro(SimilarityTransform,vtkpxSimilarityTransform);
+  vtkGetObjectMacro(ZSimilarityTransform,vtkpxSimilarityTransform);
+
+  // Description:
+  // Copy
+  virtual void Copy(vtkpxArticulatedJointTransform* other);
+
+
+  // Description:
+  // Limit Modes to only applicable ones (Nothing, 
+  
+  virtual  void SetModeToRotationXYOnly()  { this->SetMode(0); }
+  virtual  void SetModeToRotationOnly()  { this->SetMode(1); }
+  virtual  void SetModeToRotationScale() { this->SetMode(2); }
+  virtual  void SetModeToRotationTranslation() { this->SetMode(3); }
+  virtual  void SetModeToRotationScaleTranslation() { this->SetMode(4); }
+  virtual  void SetModeToRotationOrigin() { this->SetMode(5); }
+  virtual  void SetModeToFixedParameters() { this->SetMode(-1); }
+  virtual  void SetMode(int m);
+  virtual  int  GetMode();
+  //{ return this->SimilarityTransform->GetMode(); }
+
+
+
+  // Description:
+  // Puts a transformation parameter (transformation matrix is updated)
+  void   Put(int a, float v);
+  void   Set(int a, float v);
+  // Gets a transformation parameter
+  float Get(int a);
+
+
+  // Description:
+  // Stop Auto Updates
+  virtual void SetFreezeUpdates(int a);
+  virtual int  GetFreezeUpdates();
+
+
+  // Description:
+  // Load / Save Transformation
+  virtual int Load(const char* fname);
+  virtual int Load(gzFile fin);
+
+  virtual int Save(const char* fname);
+  virtual int Save(FILE* fout);
+
+  // Description:
+  // Number Of Parameters
+  virtual int GetNumberOfParameters();
+
+  // Description:
+  // Set/Get Alignment Transform
+  vtkGetObjectMacro(AlignmentTransform,vtkAbstractTransform);
+  vtkSetObjectMacro(AlignmentTransform,vtkAbstractTransform);
+
+  // Description:
+  // Index in Region
+  vtkGetMacro(AlignmentTransformIndex,int);
+  vtkSetMacro(AlignmentTransformIndex,int);
+
+  // Description:
+  // Internal Transform Point -- OK
+  void InternalTransformPoint(const float in[3], float out[3]);
+  void InternalTransformPoint(const double in[3], double out[3]);
+
+  // Description:
+  // Internal Transform Derivative (Not done yet) -- OK
+  void InternalTransformDerivative(const float in[3], float out[3],
+				  float derivative[3][3]);
+  void InternalTransformDerivative(const double in[3], double out[3],
+				  double derivative[3][3]);
+
+
+  // Description:
+  // Inverse
+  virtual void Inverse() { vtkErrorMacro(<<"Not Implemented\n");}
+  
+  // Description:
+  // Make another transform of the same type.
+  vtkAbstractTransform *MakeTransform();
+
+  // Description:
+  // Compute All Angles 
+  vtkImageData* ComputeAllAngles();
+  
+  // Description:
+  // Adjust Origin to be outside 
+  virtual void AdjustOriginToBeOutside(double gap);
+
+  // Description:
+  // Set Origin and LocalZAxis via cross-product of three co-planar points
+  virtual void SetOriginLocalAxis(double ori[3],double p1[3],double p2[3]);
+
+
+  // Description:
+  // Local Z Axis
+
+  virtual void SetLocalXZAxis(float x[3],float z[3]);
+  virtual float* GetOrigin() { return this->SimilarityTransform->GetOrigin(); }
+  virtual void GetOrigin(float x[3]) {  this->SimilarityTransform->GetOrigin(x); }
+  virtual float* GetLocalXAxis() { return this->SimilarityTransform->GetLocalXAxis(); }
+  virtual float* GetLocalZAxis() { return this->SimilarityTransform->GetLocalZAxis(); }
+  virtual void GetLocalZAxis(float z[3]) {  this->SimilarityTransform->GetLocalZAxis(z); }
+  virtual void GetLocalXAxis(float x[3]) {  this->SimilarityTransform->GetLocalXAxis(x); }
+
+
+  // Description:
+  // Initialize Angles from Points
+  virtual int InitializeAngles(double source[3],double target[3]);
+
+
+  // Description:
+  // Identity
+  virtual void Identity();
+
+  // Description:
+  // Specify name of the joint
+  vtkSetStringMacro(JointName);
+  vtkGetStringMacro(JointName);
+
+
+
+protected:
+  vtkpxArticulatedJointTransform ();
+  virtual ~vtkpxArticulatedJointTransform ();
+
+ 
+
+//BTX
+  vtkImageData* RegionLabelImage;
+  int           RegionLabelIndex;
+  int           ChildRegionLabelIndex;
+  int           ChildRegionLabelIndex2;
+  int           BlendedMode;
+  int           CubicBlending;
+  float         MinimumSectorAngle;
+  int           DetailMode;
+  float         BlendingWindow;
+  float         ZBlendingSize;
+  int           SmoothingMode;
+  int           SeparateZRotation;
+  int           Active;
+  int           OldSimilarityMode;
+  int           OldZSimilarityMode;
+  int           OldBlendedMode;
+  int           OldSeparateZRotation;
+  float         SmoothingRadius;
+  char          *JointName;
+  vtkTransform* AngleAxisTransform;
+  vtkpxSimilarityTransform* SimilarityTransform;
+  vtkpxSimilarityTransform* ZSimilarityTransform;
+  vtkAbstractTransform* AlignmentTransform;
+  int           AlignmentTransformIndex;
+//ETX
+  
+  // Description:
+  // Return -1 if no region label image (re-route to vtkpxSimilarityTransform) or no Blending
+  // Return  0 if in static region      (do nothing)
+  // Return  1 if in moving region      (do something)
+  virtual int    IsInsideRegion(const double x[3]);
+  virtual void   CreateAngleAxisTransformation(double theta,vtkpxSimilarityTransform* trans);
+
+  virtual double SearchForInterface(const double x[3],double maxtheta,double stepsize,vtkpxSimilarityTransform* trans);
+  virtual double GetActualRotationAngle(const double x[3],vtkpxSimilarityTransform* trans);
+  virtual double GetSmoothRotationAngle(const double x[3],vtkpxSimilarityTransform* trans);
+
+  virtual double AdjustForZBlending(const double point[3],vtkpxSimilarityTransform* trans,float max);
+
+  // Make This Protected
+  // -------------------
+  vtkSetObjectMacro(RegionLabelImage,vtkImageData);
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxBSplinePriorRPMRegistration.cpp b/bioimagesuite30_src/Registration/vtkpxBSplinePriorRPMRegistration.cpp
new file mode 100644
index 0000000..fcf8b44
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxBSplinePriorRPMRegistration.cpp
@@ -0,0 +1,434 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxBSplineRPMRegistration.cpp,v $
+  Language:  C++
+  Date:      $Date: 2003/03/06 16:34:24 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "pxutil.h"
+#include "vtkOldStyleCallbackCommand.h"
+#include "vtkpxGridTransform.h"
+#include "vtkpxMath.h"
+#include "vtkMatrix4x4.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxBSplinePriorRPMRegistration.h"
+#include "vtkpxMatrix.h"
+#include "vtkpxUtil.h"
+#include "vtkIdList.h"
+#include "vtkCollection.h"
+#include "vtkDoubleArray.h"
+#include "vtkPolyData.h"
+#include "vtkPointLocator.h"
+#include "vtkLinearTransform.h"
+//-----------------------------------------------------------------------------------
+
+vtkpxBSplinePriorRPMRegistration* vtkpxBSplinePriorRPMRegistration::New()
+{
+  // First try to create the object from the vtkObjectFactory
+
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxBSplinePriorRPMRegistration");
+  if(ret)
+    {
+      return (vtkpxBSplinePriorRPMRegistration*)ret;
+    }
+
+  // If the factory was unable to create the object, then create it here.
+
+  return new vtkpxBSplinePriorRPMRegistration;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxBSplinePriorRPMRegistration::vtkpxBSplinePriorRPMRegistration()
+{
+  this->CurrentPriorTransform=vtkpxGridTransform::New();
+  this->PriorTransform=NULL;
+  this->PriorWeights=NULL;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxBSplinePriorRPMRegistration::~vtkpxBSplinePriorRPMRegistration()
+{
+  this->SetPriorTransform(NULL);
+  this->SetPriorWeights(NULL);
+  this->CurrentPriorTransform->Delete();
+}
+
+//----------------------------------------------------------------------------
+// Transformation Stuff
+//----------------------------------------------------------------------------
+void vtkpxBSplinePriorRPMRegistration::GenerateTransformation(vtkpxGridTransform* gridxform,
+							      vtkpxMatrix* points1,vtkpxMatrix* points2,
+							      vtkpxMatrix* labels,
+							      float controlpointspacing,
+							      double bounds[6],
+							      float lambda,
+							      vtkCollection* W,vtkpxMatrix* OutlierWeights,
+							      vtkpxComboTransform* priorTransform,
+							      vtkpxGridTransform* currentPriorTransform,
+							      vtkDoubleArray* priorWeights,
+							      int finalmode)
+{
+  if (points1->GetSize()[0]!=points2->GetSize()[0])
+    {
+      vtkErrorMacro(<<"Unequal Number of points specified cannot fit bspline transform!");
+      return;
+    }
+
+  int newgrid=0;
+  float gap=fabs(this->InitialControlPointSpacing-this->FinalControlPointSpacing)*0.1;
+
+
+  fprintf(stderr,"Controlpointspacing=%f current=%f\n",controlpointspacing,this->CurrentControlPointSpacing);
+  if (fabs(controlpointspacing-this->CurrentControlPointSpacing)>gap)
+    { 
+      fprintf(stderr,".... Previous Transformation to new spacing\n");
+      gridxform->InitializeDisplacementGridTransform(bounds,controlpointspacing,0.1,NULL);
+      fprintf(stderr,"Tranformation Spacing = %.2f %.2f %.2f, Origin = %.2f %.2f %.2f, Dimensions=%d %d %d\n",
+	      gridxform->GetGridSpacing()[0],
+	      gridxform->GetGridSpacing()[1],
+	      gridxform->GetGridSpacing()[2],
+	      gridxform->GetGridOrigin()[0],
+	      gridxform->GetGridOrigin()[1],
+	      gridxform->GetGridOrigin()[2],
+	      gridxform->GetGridDimensions()[0],
+	      gridxform->GetGridDimensions()[1],
+	      gridxform->GetGridDimensions()[2]);
+      this->CurrentControlPointSpacing=controlpointspacing;
+      newgrid=1;
+
+      this->CurrentPriorTransform->InitializeDisplacementGridTransform(bounds,controlpointspacing,0.1,NULL);
+      fprintf(stderr,"++++ Approximating Prior Transformation to same space\n");
+      this->CurrentPriorTransform->ApproximateTransformation(this->PriorTransform->GetGridTransform(),1.0,12,1,0.05,0.001);
+    }
+
+  newgrid=0;
+  int np=points1->GetSize()[0];
+
+  int useoutliers=0;
+  float lab[50][2],sumlab[50];
+  int numlab[50];
+  for (int cnt=0;cnt<50;cnt++)
+    {
+      lab[cnt][0]=1000.0;
+      lab[cnt][1]=0.0;
+      sumlab[cnt]=0.0;
+      numlab[cnt]=0;
+    }
+
+
+  int dolabels=0;
+  if (labels!=NULL && this->UseLabels>0)
+    dolabels=1;
+
+
+  if (OutlierWeights!=NULL)
+    {
+      if (OutlierWeights->GetSize()[0]==np)
+	{
+	  useoutliers=1;
+	}
+    }
+
+  vtkPoints* p1=vtkPoints::New();
+  p1->SetNumberOfPoints(np);
+  vtkPoints* p2=vtkPoints::New();
+  p2->SetNumberOfPoints(np);
+  
+
+  float sum=0.0;
+  for (int i=0;i<np;i++)
+    {
+      float x[3],y[3];
+      for (int ia=0;ia<=2;ia++)
+	{
+	  x[ia]=points1->GetDirectElement(i,ia);
+	  y[ia]=points2->GetDirectElement(i,ia);
+	}
+
+      p1->SetPoint(i,x);
+      p2->SetPoint(i,y);
+      float dsum=0.0;
+      for (int j=0;j<=2;j++)
+	{
+	  float v=y[j]-x[j];
+	  dsum+=pow(v,float(2.0));
+	}
+      sum+=sqrt(dsum);
+    }
+  sum/=np;
+
+  int numc=gridxform->GetNumberOfControlPoints();
+
+  if (W->GetNumberOfItems()!=numc)
+    {
+      fprintf(stderr,"Forming Collection Structure\n");
+      gridxform->FormCollectionStructure(p1,W,0.001);
+    }
+
+  float threshold=sum*0.01;
+  fprintf(stderr,"Lambda=%10.7f average component=%10.5f approximating mode=%d threshold=%.5f\n",
+	  lambda,sum,finalmode,
+	  threshold*0.01);
+  gridxform->SetApproximationMode(0);
+
+  float sc2=0.25; // was 0.05
+
+  switch (finalmode)
+    {
+    case 1:
+      gridxform->ApproximatePoints(p1,p2,W,
+				   sum*sc2,
+				   20,1,
+				   threshold,0.001,
+				   newgrid,OutlierWeights,
+				   this->CurrentPriorTransform,this->PriorWeights);
+      break;
+    case 2:
+      gridxform->ApproximatePoints(p1,p2,W,
+				   sum*sc2,
+				   20,3,
+				   threshold,0.001,
+				   newgrid,OutlierWeights,
+				   this->CurrentPriorTransform,this->PriorWeights);
+      break;
+    default:
+      gridxform->ApproximatePoints(p1,p2,W,
+				   sum*sc2,
+				   40,1,
+				   threshold,lambda,
+				   newgrid,OutlierWeights,
+				   this->CurrentPriorTransform,this->PriorWeights);
+      break;
+    }
+  double e2=0.0;
+  double e=gridxform->TestWeightedApproximation(p1,p2,OutlierWeights,e2);
+  fprintf(stderr,"Weighted Displacement approximation=%8.6f\n---------------------------------\n",e);
+  p2->Delete();
+  p1->Delete();
+  return;
+
+}
+//----------------------------------------------------------------------------
+// Description:
+// Annealing Procedure
+//----------------------------------------------------------------------------
+void vtkpxBSplinePriorRPMRegistration::Anneal()
+{
+  if (this->PriorTransform==NULL)
+    {
+      fprintf(stderr,"\n\n No Prior Specified for vtkpxBSplinePriorRegistration ... dropping back to vtkpxBSplineRPMRegistration\n");
+      vtkpxBSplineRPMRegistration::Anneal();
+      return;
+    }
+
+  fprintf(stderr,"\n\n\n\n --------------------------------\n Beginning Anneal \n ---------------------------- \n");
+
+  int perT_maxit=2;
+  //int relax_maxit=1;
+  float anneal_rate=this->AnnealRate;
+ 
+  // Initialize Temperature Stuff 
+  float T      =Frange(this->InitialTemperature,0.1,500);
+  float T_final=Frange(this->FinalTemperature,0.01,T);
+
+
+  int   totaliter=int(fabs(log(T/T_final)/log(anneal_rate))+1.0);
+
+  vtkpxMatrix* X=vtkpxMatrix::New();
+  vtkpxMatrix* Y=vtkpxMatrix::New();
+  vtkpxMatrix* LX=vtkpxMatrix::New();
+  vtkpxMatrix* LY=vtkpxMatrix::New();
+
+
+  if (this->MaximumNumberOfLandmarks<-1)
+    {
+      this->MaximumNumberOfLandmarks=abs(this->MaximumNumberOfLandmarks);
+      this->PreferentialSampling=1;
+    }
+
+  this->SamplePoints(X,Y,LX,LY,this->MaximumNumberOfLandmarks,this->PreferentialSampling);
+
+
+  double bounds[6];   this->Source->GetPoints()->GetBounds(bounds);
+
+
+  int sz[2],nump_x,nump_y;
+  X->GetSize(sz);   nump_x=sz[0];
+  Y->GetSize(sz);   nump_y=sz[0];
+  vtkDebugMacro(<< "Anneal: Using " << nump_x << " , " << nump_y << "Landmarks UseLabels="<< this->UseLabels << "\n");
+
+  vtkpxAbstractMatrix* M=this->AllocateMatchMatrix(this->MatchMatrixType);
+  vtkpxMatrix* M_Outliers_Row=vtkpxMatrix::New();
+  vtkpxMatrix* M_Outliers_Column=vtkpxMatrix::New();
+  this->InitMatchMatrices(M,M_Outliers_Row,M_Outliers_Column,nump_x,nump_y);
+  
+  vtkPointLocator* locator=this->CreateLocator(Y);
+
+  // Initialize Transformed X and Y stuff 
+  vtkpxMatrix* VX=vtkpxMatrix::New();   VX->Copy(X);
+  vtkpxMatrix* VY=vtkpxMatrix::New();  VY->Copy(X);
+
+  vtkCollection* collection=vtkCollection::New();
+
+  if (this->FinalSmoothnessFactor>this->InitialSmoothnessFactor)
+    {
+      float a=this->FinalSmoothnessFactor;
+      this->FinalSmoothnessFactor=this->InitialSmoothnessFactor;
+      this->InitialSmoothnessFactor=a;
+    }
+
+  float bsmooth=this->InitialSmoothnessFactor;
+  float bsmooth_final=this->FinalSmoothnessFactor;
+  float bsmooth_annealrate=exp(-fabs(log(bsmooth/bsmooth_final)/float(totaliter-1.0)));
+  fprintf(stderr,"Bsmooth = %f Bsmoothfinal=%f totaliter=%d annealrate=%f\n",bsmooth,bsmooth_final,totaliter,bsmooth_annealrate);
+
+  float cps=Frange(this->InitialControlPointSpacing,0.1,500);
+  float cps_final=Frange(this->FinalControlPointSpacing,0.01,cps);
+  this->InitialControlPointSpacing=cps;
+  this->FinalControlPointSpacing=cps_final;
+
+  float cps_annealrate=exp(-fabs(log(cps/cps_final)/float(totaliter-1.0)));
+  float controlpointspacing=cps;
+
+  // Annealing Procedure 
+  int flag_stop=0;
+  int iter=1;
+
+  this->InitializeUsingInitialComboTransform(X,Y,VX,this->PriorTransform);
+  M_Outliers_Column->Fill(1.0);
+  vtkpxBSplineRPMRegistration::GenerateTransformation(this->GridTransform,X,VX,LX,
+						      controlpointspacing,bounds,0.01,
+						      collection,M_Outliers_Column);
+
+  float moutlier=0.0;
+  while (flag_stop == 0 )
+    {
+      for (int i=1;i<=perT_maxit;i++)
+	{
+	  if (this->AbortExecute>0)
+	    {
+	      i=perT_maxit+1;
+	    }
+	  else
+	    {
+	      //moutlier=this->SetOutliers(M_Outliers_Row,M_Outliers_Column,this->InitialTemperature);
+	      this->UpdateCorrespondence(M,M_Outliers_Row,M_Outliers_Column,
+					 VX,Y,VY,T,locator,LX,LY);
+	      this->GenerateTransformation(this->GridTransform,X,VY,LX,
+					   controlpointspacing,bounds,bsmooth,
+					   collection,M_Outliers_Column,
+					   this->PriorTransform,
+					   this->CurrentPriorTransform,
+					   this->PriorWeights);
+	      this->TransformPoints(this->GridTransform,X,VX);
+	    }
+	}
+
+      vtkImageData* grid=this->GridTransform->GetDisplacementGrid();
+      vtkDebugMacro(<<"\n\n----------------------------------------------------------\nIteration " << iter << "/" << totaliter << " T = " << T << "Cps= " << controlpointspacing << ", abort= " << this->AbortExecute << "\n\t" << "Grid Dimensions"<< grid->GetDimensions()[0] << " x " <<  grid->GetDimensions()[1] << " x " << grid->GetDimensions()[2] << " Num DOFs = " << this->GridTransform->GetNumberOfControlPoints() << " Bsmooth= " << bsmooth << ",Outlier weight=" << moutlier);
+          
+      this->UpdateProgress(float(iter)/totaliter);
+      iter++;
+      T=T*anneal_rate;
+      controlpointspacing*=cps_annealrate;
+      bsmooth*=bsmooth_annealrate;
+      if (T<T_final || this->AbortExecute>0)
+	flag_stop=1;
+    }
+  
+  vtkDebugMacro(<<"Creating Final Transformation");
+  this->InvokeEvent(vtkCommand::EndEvent,NULL);
+
+
+  // Generate Final Weights and normalize them to have mean 1
+  // --------------------------------------------------------
+  if (this->PreferentialSampling==1 &&   M_Outliers_Column!=NULL && ( this->MatchMode==2 || this->MatchMode==4) )
+    {
+      int dolabels=0;
+      if (LX!=NULL && LY!=NULL && this->UseLabels>0)
+	dolabels=1;
+      if (dolabels==1)
+	{
+	  int nt=0;
+	  for (int i=0;i<nump_x;i++)
+	    {
+	      if (LX->GetDirectElement(i,0)==1)
+		{
+		  M_Outliers_Column->SetDirectElement(i,0,0.0);
+		  ++nt;
+		}
+	    }
+	  fprintf(stderr," %d / %d outlier weights set to 0 \n",nt,nump_x);
+	  float s=float(M_Outliers_Column->GetSize()[0])/M_Outliers_Column->Sum();
+	  M_Outliers_Column->Scale(s);
+	}
+    }
+
+  this->GridTransform->FormOutputWeights(collection,M_Outliers_Column,this->FinalWeights);
+
+
+  // Onto Cleanup Stuff 
+  // -------------------------------------------
+  if (locator!=NULL)    locator->Delete();
+  VX->Delete();         VY->Delete();
+  M->Delete();          M_Outliers_Row->Delete();
+  X->Delete();          M_Outliers_Column->Delete();
+  Y->Delete();          
+  LX->Delete();         LY->Delete();
+  collection->Delete();
+  this->CurrentControlPointSpacing=-1.0;
+
+}
+//----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Registration/vtkpxBSplinePriorRPMRegistration.h b/bioimagesuite30_src/Registration/vtkpxBSplinePriorRPMRegistration.h
new file mode 100644
index 0000000..bfa568d
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxBSplinePriorRPMRegistration.h
@@ -0,0 +1,113 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxBSplinePriorRPMRegistration.h,v $
+  Language:  C++
+  Date:      $Date: 2003/03/06 16:34:31 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#ifndef __vtkpxBSplinePriorRPMRegistration_h
+#define __vtkpxBSplinePriorRPMRegistration_h
+
+#include "vtkpxBSplineRPMRegistration.h"
+#include "vtkDoubleArray.h"
+#include "vtkpxComboTransform.h"
+
+class vtkpxBSplinePriorRPMRegistration : public vtkpxBSplineRPMRegistration
+{
+public:
+  static vtkpxBSplinePriorRPMRegistration *New();
+  vtkTypeMacro(vtkpxBSplinePriorRPMRegistration,vtkpxBSplineRPMRegistration);
+
+  // Description:
+  // Get/Set Prior Weights
+  vtkSetObjectMacro(PriorWeights,vtkDoubleArray);
+  vtkGetObjectMacro(PriorWeights,vtkDoubleArray);
+
+  // Description:
+  // Get/Set Prior Transform -- needs to be a combo transform
+  vtkSetObjectMacro(PriorTransform,vtkpxComboTransform);
+  vtkGetObjectMacro(PriorTransform,vtkpxComboTransform);
+
+
+protected:
+  // Description:
+  
+  vtkpxBSplinePriorRPMRegistration();
+  ~vtkpxBSplinePriorRPMRegistration();
+  vtkpxBSplinePriorRPMRegistration(const vtkpxBSplinePriorRPMRegistration&) {};
+  void operator=(const vtkpxBSplinePriorRPMRegistration&) {};
+
+  vtkpxComboTransform *PriorTransform;
+  vtkDoubleArray       *PriorWeights;
+  vtkpxGridTransform*CurrentPriorTransform;
+
+  // Description
+  // Master Optimization Routine
+  virtual void Anneal();
+
+  // Description:
+  // Generate Transformation Details 
+  virtual void GenerateTransformation(vtkpxGridTransform* gridxform,
+				      vtkpxMatrix* x,vtkpxMatrix* vy, vtkpxMatrix* lx,
+				      float cps, double bounds[6],float sm,
+				      vtkCollection* W,vtkpxMatrix* OutlierColumn,
+				      vtkpxComboTransform* priorTransform,
+				      vtkpxGridTransform*  currentPriorTransform,
+				      vtkDoubleArray*       priorWeights,
+				      int finalmode=0);
+
+
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxBSplineRPMRegistration.cpp b/bioimagesuite30_src/Registration/vtkpxBSplineRPMRegistration.cpp
new file mode 100644
index 0000000..6921c9b
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxBSplineRPMRegistration.cpp
@@ -0,0 +1,556 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxBSplineRPMRegistration.cpp,v $
+  Language:  C++
+  Date:      $Date: 2005/10/25 00:45:36 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "pxutil.h"
+#include "vtkOldStyleCallbackCommand.h"
+#include "vtkpxGridTransform.h"
+#include "vtkpxMath.h"
+#include "vtkMatrix4x4.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxBSplineRPMRegistration.h"
+#include "vtkpxMatrix.h"
+#include "vtkpxUtil.h"
+#include "vtkIdList.h"
+#include "vtkCollection.h"
+#include "vtkDoubleArray.h"
+#include "vtkPolyData.h"
+#include "vtkPointLocator.h"
+#include "vtkLinearTransform.h"
+//-----------------------------------------------------------------------------------
+
+vtkpxBSplineRPMRegistration* vtkpxBSplineRPMRegistration::New()
+{
+  // First try to create the object from the vtkObjectFactory
+
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxBSplineRPMRegistration");
+  if(ret)
+    {
+      return (vtkpxBSplineRPMRegistration*)ret;
+    }
+
+  // If the factory was unable to create the object, then create it here.
+
+  return new vtkpxBSplineRPMRegistration;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxBSplineRPMRegistration::vtkpxBSplineRPMRegistration()
+{
+  this->ComboTransform=vtkpxComboTransform::New();
+  this->ComboTransform->SetNonLinearFirst(1);
+  this->GridTransform = this->ComboTransform->GetGridTransform();
+  this->InitialControlPointSpacing=0.2;
+  this->FinalControlPointSpacing=0.2;
+  this->CurrentControlPointSpacing=-1.0;
+  this->FinalWeights=vtkDoubleArray::New();
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxBSplineRPMRegistration::~vtkpxBSplineRPMRegistration()
+{
+  this->ComboTransform->Delete();
+  this->GridTransform=NULL;
+  this->FinalWeights->Delete();
+}
+
+//----------------------------------------------------------------------------
+void vtkpxBSplineRPMRegistration::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkpxAbstractRPMRegistration::PrintSelf(os,indent);
+  os << indent << "InitialControlPointSpacing:  " << this->InitialControlPointSpacing << "\n";
+  os << indent << "FinalControlPointSpacing:  " << this->FinalControlPointSpacing << "\n";
+  os << indent << "CurrentControlPointSpacing:  " << this->CurrentControlPointSpacing << "\n";
+  os << indent << "Transformation: " << this->ComboTransform << "\n";
+}
+
+//----------------------------------------------------------------------------
+vtkAbstractTransform* vtkpxBSplineRPMRegistration::GetCurrentTransformation()
+{
+  return this->ComboTransform;
+}
+//----------------------------------------------------------------------------
+// Transformation Stuff
+//----------------------------------------------------------------------------
+void vtkpxBSplineRPMRegistration::GenerateTransformation(vtkpxGridTransform* gridxform,
+							 vtkpxMatrix* points1,vtkpxMatrix* points2,
+							 vtkpxMatrix* labels,
+							 float controlpointspacing,
+							 double bounds[6],
+							 float lambda,
+							 vtkCollection* W,vtkpxMatrix* OutlierWeights,
+							 int finalmode)
+{
+  if (points1->GetSize()[0]!=points2->GetSize()[0])
+    {
+      vtkErrorMacro(<<"Unequal Number of points specified cannot fit bspline transform!");
+      return;
+    }
+
+  float gap=fabs(this->InitialControlPointSpacing-this->FinalControlPointSpacing)*0.1;
+
+  fprintf(stderr,"Controlpointspacing=%f current=%f\n",controlpointspacing,this->CurrentControlPointSpacing);
+  int newgrid=0;
+  if (fabs(controlpointspacing-this->CurrentControlPointSpacing)>gap)
+    { 
+      gridxform->InitializeDisplacementGridTransform(bounds,controlpointspacing,0.05,NULL);
+      fprintf(stderr,"Tranformation Spacing = %.2f %.2f %.2f, Origin = %.2f %.2f %.2f, Dimensions=%d %d %d\n",
+	      gridxform->GetGridSpacing()[0],
+	      gridxform->GetGridSpacing()[1],
+	      gridxform->GetGridSpacing()[2],
+	      gridxform->GetGridOrigin()[0],
+	      gridxform->GetGridOrigin()[1],
+	      gridxform->GetGridOrigin()[2],
+	      gridxform->GetGridDimensions()[0],
+	      gridxform->GetGridDimensions()[1],
+	      gridxform->GetGridDimensions()[2]);
+      this->CurrentControlPointSpacing=controlpointspacing;
+      newgrid=1;
+    }
+
+  int np=points1->GetSize()[0];
+
+  int useoutliers=0;
+  int dolabels=0;
+  if (labels!=NULL && this->UseLabels>0)
+    dolabels=1;
+
+
+  if (OutlierWeights!=NULL)
+    {
+      if (OutlierWeights->GetSize()[0]==np)
+	{
+	  useoutliers=1;
+	}
+    }
+
+  /*  if (initial_xform!=NULL)
+    {
+      if (initial_xform->IsA("vtkpxPolySimilarityTransform")==1)
+	this->ComboTransform->InitializeFromPolySimilarityTransform((vtkpxPolySimilarityTransform*)initial_xform);
+	}*/
+
+  //  this->ComboTransform->Save("approx1.grd");
+
+  vtkPoints* p1=vtkPoints::New();
+  p1->SetNumberOfPoints(np);
+  vtkPoints* p2=vtkPoints::New();
+  p2->SetNumberOfPoints(np);
+  
+  double sum=0.0;
+  for (int i=0;i<np;i++)
+    {
+      float x[3],y[3];
+      for (int ia=0;ia<=2;ia++)
+	{
+	  x[ia]=points1->GetDirectElement(i,ia);
+	  y[ia]=points2->GetDirectElement(i,ia);
+	}
+
+      p1->SetPoint(i,x);
+      p2->SetPoint(i,y);
+      float dsum=0.0;
+      for (int j=0;j<=2;j++)
+	{
+	  float v=y[j]-x[j];
+	  dsum+=pow(v,float(2.0));
+	}
+      sum+=sqrt(dsum);
+    }
+  sum/=np;
+
+  int numc=gridxform->GetNumberOfControlPoints();
+
+  if (W->GetNumberOfItems()!=numc)
+    {
+      fprintf(stderr,"Forming Collection Structure\n");
+      gridxform->FormCollectionStructure(p1,W,0.001);
+      fprintf(stderr,"Done\n");
+    }
+
+  float threshold=sum*0.01;
+  fprintf(stderr,"Lambda=%10.7f average component=%10.5f approximating mode=%d threshold=%.5f\n",
+	  lambda,sum,finalmode,
+	  threshold*0.01);
+  gridxform->SetApproximationMode(0);
+  
+  //  sum=20.0;
+  sum*=2.5;
+
+  switch (finalmode)
+    {
+    case 1:
+      gridxform->ApproximatePoints(p1,p2,W,
+				   sum*0.05,
+				   20,1,
+				   threshold,0.001,
+				   newgrid,OutlierWeights);
+      break;
+    case 2:
+      gridxform->ApproximatePoints(p1,p2,W,
+				   sum*0.05,
+				   20,3,
+				   threshold,0.001,
+				   newgrid,OutlierWeights);
+      break;
+    default:
+      gridxform->ApproximatePoints(p1,p2,W,
+				   sum*0.05,
+				   40,1,
+				   threshold,lambda,
+				   newgrid,OutlierWeights);
+      break;
+    }
+  double e2=0.0;
+  float e=gridxform->TestWeightedApproximation(p1,p2,OutlierWeights,e2);
+  fprintf(stderr,"Weighted Displacement approximation=%8.6f\n---------------------------------\n",e);
+  p2->Delete();
+  p1->Delete();
+
+
+
+  return;
+
+}
+//----------------------------------------------------------------------------
+//
+//          Initial Transformation Stuff
+//
+//----------------------------------------------------------------------------
+void vtkpxBSplineRPMRegistration::InitializeUsingInitialComboTransform(vtkpxMatrix* X,vtkpxMatrix* Y,
+								  vtkpxMatrix* VX,
+								  vtkpxComboTransform* usethiscombotransformation)
+{
+  vtkTransform* tr=vtkTransform::New();
+  tr->GetMatrix()->DeepCopy(usethiscombotransformation->GetLinearTransform()->GetMatrix());
+  this->ComboTransform->GetLinearTransform()->GetMatrix()->DeepCopy(tr->GetMatrix());
+  this->ComboTransform->SetNonLinearFirst(usethiscombotransformation->GetNonLinearFirst());
+
+  if (this->ComboTransform->GetNonLinearFirst()==0)
+    {
+      int nump_x=X->GetSize()[0];
+      float x[3],tx[3],tx2[3];
+      for (int i=0;i<nump_x;i++)
+	{
+	  for (int ia=0;ia<3;ia++)
+	    x[ia]=X->GetDirectElement(i,ia);
+	  usethiscombotransformation->GetLinearTransform()->TransformPoint(x,tx);
+	  usethiscombotransformation->GetGridTransform()->TransformPoint(tx,tx2);
+	  
+	  for (int ib=0;ib<3;ib++)
+	    {
+	      X->SetDirectElement(i,ib,tx[ib]);
+	      VX->SetDirectElement(i,ib,tx2[ib]);
+	    }
+	}
+    }
+  else
+    {
+      fprintf(stderr,"In Non Linear First = 1\n\n\n");
+      int nump_x=X->GetSize()[0];
+      float x[3],tx[3];
+      for (int i=0;i<nump_x;i++)
+	{
+	  for (int ia=0;ia<3;ia++)
+	    x[ia]=X->GetDirectElement(i,ia);
+	  usethiscombotransformation->GetGridTransform()->TransformPoint(x,tx);
+	  for (int ib=0;ib<3;ib++)
+	    VX->SetDirectElement(i,ib,tx[ib]);
+	}
+      
+      float y[3],ty[3];
+      int nump_y=Y->GetSize()[0];
+      for (int j=0;j<nump_y;j++)
+	{
+	  for (int ia=0;ia<3;ia++)
+	    y[ia]=Y->GetDirectElement(j,ia);
+	  usethiscombotransformation->GetLinearTransform()->GetLinearInverse()->TransformPoint(y,ty);
+	  for (int ib=0;ib<3;ib++)
+	      Y->SetDirectElement(j,ib,tx[ib]);
+	}
+    }
+
+  
+
+}
+//----------------------------------------------------------------------------
+void vtkpxBSplineRPMRegistration::InitializeUsingInitialTransform(vtkpxMatrix* X,vtkpxMatrix* Y,
+								  vtkpxMatrix* VX,
+								  vtkAbstractTransform* usethistransformation)
+{
+  
+  /*  if (usethistransformation->IsA("vtkpxComboTransform"))
+    {
+      this->InitializeUsingInitialComboTransform(X,Y,VX,(vtkpxComboTransform*)usethistransformation);
+      return;
+      }*/
+
+  this->ComboTransform->SetNonLinearFirst(1);
+  if (usethistransformation->IsA("vtkLinearTransform")==1)
+    {
+      vtkLinearTransform* tr=(vtkLinearTransform*)usethistransformation;
+      
+      float y[3],ty[3];
+      int nump_y=Y->GetSize()[0];
+      for (int i=0;i<nump_y;i++)
+	{
+	  for (int ia=0;ia<3;ia++)
+	    y[ia]=Y->GetDirectElement(i,ia);
+	  
+	  tr->GetLinearInverse()->TransformPoint(y,ty);
+	  for (int ib=0;ib<3;ib++)
+	    Y->SetDirectElement(i,ib,ty[ib]);
+	}
+      fprintf(stderr,"Used Linear Initial Transform inside vtkpxBSplineRPMRegistration");
+      this->ComboTransform->GetLinearTransform()->GetMatrix()->DeepCopy(((vtkLinearTransform*)usethistransformation)->GetMatrix());
+      this->ComboTransform->SetNonLinearFirst(1);
+    }
+  else
+    {
+      fprintf(stderr,"Using Non-Linear Initial Transform inside vtkpxBSplineRPMRegistration %s %d\n",
+	      usethistransformation->GetClassName(),usethistransformation->IsA("vtkTransform"));
+      float x[3],tx[3];
+      int nump_x=X->GetSize()[0];
+      for (int i=0;i<nump_x;i++)
+	{
+	  for (int ia=0;ia<3;ia++)
+	    x[ia]=X->GetDirectElement(i,ia);
+	  
+	  usethistransformation->TransformPoint(x,tx);
+
+	  for (int ib=0;ib<3;ib++)
+	    VX->SetDirectElement(i,ib,tx[ib]);
+	}
+    }
+}
+//----------------------------------------------------------------------------
+// Description:
+// Annealing Procedure
+//----------------------------------------------------------------------------
+void vtkpxBSplineRPMRegistration::Anneal()
+{
+  fprintf(stderr,"\n\n\n\n --------------------------------\n Beginning Anneal \n ---------------------------- \n");
+
+  int perT_maxit=2;
+  //int relax_maxit=1;
+  float anneal_rate=this->AnnealRate;
+ 
+  // Initialize Temperature Stuff 
+  float T      =Frange(this->InitialTemperature,0.1,500);
+  float T_final=Frange(this->FinalTemperature,0.01,T);
+
+  int   totaliter=int(fabs(log(T/T_final)/log(anneal_rate))+1.0);
+  fprintf(stderr,"T=%f, T_final=%f totaliter=%d anneal_rate=%.3f\n",T,T_final,totaliter,anneal_rate);
+
+
+  vtkpxMatrix* X=vtkpxMatrix::New();
+  vtkpxMatrix* Y=vtkpxMatrix::New();
+  vtkpxMatrix* LX=vtkpxMatrix::New();
+  vtkpxMatrix* LY=vtkpxMatrix::New();
+
+  double bounds[6]; this->Source->GetPoints()->GetBounds(bounds);
+  
+  if (this->MaximumNumberOfLandmarks<-1)
+    {
+      this->MaximumNumberOfLandmarks=abs(this->MaximumNumberOfLandmarks);
+      this->PreferentialSampling=1;
+    }
+
+  if (this->UseAttributes==1)
+    {
+      this->PreferentialSampling=0;
+      this->UseLabels=0;
+    }
+
+
+  this->SamplePoints(X,Y,LX,LY,this->MaximumNumberOfLandmarks,this->PreferentialSampling);
+
+
+  int sz[2],nump_x,nump_y;
+  X->GetSize(sz);   nump_x=sz[0];
+  Y->GetSize(sz);   nump_y=sz[0];
+  vtkDebugMacro(<< "Anneal: Using " << nump_x << " , " << nump_y << "Landmarks UseLabels="<< this->UseLabels << " PrefSampling=" << this->PreferentialSampling << "\n");
+
+  vtkpxAbstractMatrix* M=this->AllocateMatchMatrix(this->MatchMatrixType);
+  vtkpxMatrix* M_Outliers_Row=vtkpxMatrix::New();
+  vtkpxMatrix* M_Outliers_Column=vtkpxMatrix::New();
+  this->InitMatchMatrices(M,M_Outliers_Row,M_Outliers_Column,nump_x,nump_y);
+  
+
+  // Initialize Transformed X and Y stuff 
+  vtkpxMatrix* VX=vtkpxMatrix::New();   VX->Copy(X);
+  vtkpxMatrix* VY=vtkpxMatrix::New();   VY->Copy(X);
+
+  vtkCollection* collection=vtkCollection::New();
+
+  if (this->FinalSmoothnessFactor>this->InitialSmoothnessFactor)
+    {
+      float a=this->FinalSmoothnessFactor;
+      this->FinalSmoothnessFactor=this->InitialSmoothnessFactor;
+      this->InitialSmoothnessFactor=a;
+    }
+
+  float bsmooth=this->InitialSmoothnessFactor;
+  float bsmooth_final=this->FinalSmoothnessFactor;
+  float bsmooth_annealrate=exp(-fabs(log(bsmooth/bsmooth_final)/float(totaliter-1.0)));
+  fprintf(stderr,"Bsmooth = %f Bsmoothfinal=%f totaliter=%d annealrate=%f\n",bsmooth,bsmooth_final,totaliter,bsmooth_annealrate);
+
+  float cps=Frange(this->InitialControlPointSpacing,0.1,500);
+  float cps_final=Frange(this->FinalControlPointSpacing,0.01,cps);
+
+  this->InitialControlPointSpacing=cps;
+  this->FinalControlPointSpacing=cps_final;
+
+  float cps_annealrate=exp(-fabs(log(cps/cps_final)/float(totaliter-1.0)));
+  float controlpointspacing=cps;
+
+  // Annealing Procedure 
+  int flag_stop=0;
+  int iter=1;
+
+
+  if (this->InitialTransform!=NULL && this->UseInitialTransform>0 )
+    {
+      this->InitializeUsingInitialTransform(X,Y,VX,this->InitialTransform);
+      fprintf(stderr,"Initialized Using Initial Transform Done\n");
+
+      /*      if (this->InitialTransform->IsA("vtkLinearTransform")==0)
+	{
+	  M_Outliers_Column->Fill(1.0);
+	  fprintf(stderr,"Fitting Initial Transformation\n\n\n ****");
+	  this->GenerateTransformation(this->GridTransform,X,VX,LX,
+				       controlpointspacing,bounds,2.0,
+				       collection,NULL,0);
+				       }*/
+    }
+  else
+    fprintf(stderr,"Not Using Initial Transform inside vtkpxBSplineRPMRegistration");
+
+  vtkPointLocator* locator=this->CreateLocator(Y);
+
+
+  while (flag_stop == 0 )
+    {
+      for (int i=1;i<=perT_maxit;i++)
+	{
+	  if (this->AbortExecute>0)
+	    {
+	      i=perT_maxit+1;
+	    }
+	  else
+	    {
+	      this->UpdateCorrespondence(M,M_Outliers_Row,M_Outliers_Column,
+					 VX,Y,VY,T,locator,LX,LY);
+	      this->GenerateTransformation(this->GridTransform,X,VY,LX,
+					   controlpointspacing,bounds,bsmooth,
+					   collection,M_Outliers_Column);
+	      this->TransformPoints(this->GridTransform,X,VX);
+	    }
+	}
+
+      vtkImageData* grid=this->GridTransform->GetDisplacementGrid();
+      vtkDebugMacro(<<"\n\n----------------------------------------------------------\nIteration " << iter << "/" << totaliter << " T = " << T << "Cps= " << controlpointspacing << ", abort= " << this->AbortExecute << "\n\t" << "Grid Dimensions"<< grid->GetDimensions()[0] << " x " <<  grid->GetDimensions()[1] << " x " << grid->GetDimensions()[2] << " Num DOFs = " << this->GridTransform->GetNumberOfControlPoints() << " Bsmooth= " << bsmooth);
+          
+      this->UpdateProgress(float(iter)/totaliter);
+      iter++;
+      T=T*anneal_rate;
+      controlpointspacing*=cps_annealrate;
+      bsmooth*=bsmooth_annealrate;
+      if (T<T_final || this->AbortExecute>0)
+	flag_stop=1;
+    }
+  
+  if (this->PreferentialSampling==1 &&   M_Outliers_Column!=NULL && ( this->MatchMode==2 || this->MatchMode==4) )
+    {
+      int dolabels=0;
+      if (LX!=NULL && LY!=NULL && this->UseLabels>0)
+	dolabels=1;
+      if (dolabels==1)
+	{
+	  int nt=0;
+	  for (int i=0;i<nump_x;i++)
+	    {
+	      if (LX->GetDirectElement(i,0)==1)
+		{
+		  M_Outliers_Column->SetDirectElement(i,0,0.0);
+		  ++nt;
+		}
+	    }
+	  fprintf(stderr," %d / %d outlier weights set to 0 \n",nt,nump_x);
+	  float s=float(M_Outliers_Column->GetSize()[0])/M_Outliers_Column->Sum();
+	  M_Outliers_Column->Scale(s);
+	}
+    }
+
+  this->GridTransform->FormOutputWeights(collection,M_Outliers_Column,this->FinalWeights);
+
+  vtkDebugMacro(<<"Creating Final Transformation");
+  this->InvokeEvent(vtkCommand::EndEvent,NULL);
+
+  // Cleanup Stuff 
+  if (locator!=NULL)    locator->Delete();
+  VX->Delete();         VY->Delete();
+  M->Delete();          M_Outliers_Row->Delete();
+  X->Delete();          M_Outliers_Column->Delete();
+  Y->Delete();          
+  LX->Delete();         LY->Delete();
+  collection->Delete();
+  this->CurrentControlPointSpacing=-1.0;
+
+}
+//----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Registration/vtkpxBSplineRPMRegistration.h b/bioimagesuite30_src/Registration/vtkpxBSplineRPMRegistration.h
new file mode 100644
index 0000000..8e95955
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxBSplineRPMRegistration.h
@@ -0,0 +1,136 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxBSplineRPMRegistration.h,v $
+  Language:  C++
+  Date:      $Date: 2004/11/19 01:06:39 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#ifndef __vtkpxBSplineRPMRegistration_h
+#define __vtkpxBSplineRPMRegistration_h
+
+#include "vtkpxComboTransform.h"
+#include "vtkpxAbstractRPMRegistration.h"
+
+class vtkpxBSplineRPMRegistration : public vtkpxAbstractRPMRegistration
+{
+public:
+  static vtkpxBSplineRPMRegistration *New();
+  vtkTypeMacro(vtkpxBSplineRPMRegistration,vtkpxAbstractRPMRegistration);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Get Current Transformation -- needed for displaying updates 
+  virtual vtkAbstractTransform* GetCurrentTransformation();
+
+  // Description:
+  // Initial ControlPointSpacing for deterministic annealing and bspline grid
+  vtkSetClampMacro(InitialControlPointSpacing,float,0.01,1000);
+  vtkGetMacro(InitialControlPointSpacing,float);
+
+  // Description:
+  // Final ControlPointSpacing for deterministic annealing and bspline grid
+  vtkSetClampMacro(FinalControlPointSpacing,float,0.01,900);
+  vtkGetMacro(FinalControlPointSpacing,float);
+
+  // Description:
+  // Current Control Point Spacing
+  vtkGetMacro(CurrentControlPointSpacing,float);
+
+  // Description:
+  // Get/Set Prior Weights
+  vtkGetObjectMacro(FinalWeights,vtkDoubleArray);
+
+protected:
+  // Description:
+  
+  vtkpxBSplineRPMRegistration();
+  ~vtkpxBSplineRPMRegistration();
+  vtkpxBSplineRPMRegistration(const vtkpxBSplineRPMRegistration&) {};
+  void operator=(const vtkpxBSplineRPMRegistration&) {};
+
+  vtkpxGridTransform  *GridTransform;
+  vtkpxComboTransform *ComboTransform;
+  float InitialControlPointSpacing;
+  float FinalControlPointSpacing;
+  float CurrentControlPointSpacing;
+  vtkDoubleArray       *FinalWeights;
+
+  // Description
+  // Master Optimization Routine
+  virtual void Anneal();
+
+
+
+
+  // Description:
+  // Generate Transformation Details 
+  virtual void GenerateTransformation(vtkpxGridTransform* gridxform,
+				      vtkpxMatrix* x,vtkpxMatrix* vy, vtkpxMatrix* lx,
+				      float cps,double bounds[6],float sm,
+				      vtkCollection* W,vtkpxMatrix* OutlierColumn=NULL,
+				      int finalmode=0);
+
+
+  virtual void InitializeUsingInitialTransform(vtkpxMatrix* X,vtkpxMatrix* Y,
+					       vtkpxMatrix* VX,
+					       vtkAbstractTransform* usethistransformation);
+
+  virtual void InitializeUsingInitialComboTransform(vtkpxMatrix* X,vtkpxMatrix* Y,
+						    vtkpxMatrix* VX,
+						    vtkpxComboTransform* usethiscombotransformation);
+
+
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxBaseGridTransform.cpp b/bioimagesuite30_src/Registration/vtkpxBaseGridTransform.cpp
new file mode 100644
index 0000000..7ae4496
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxBaseGridTransform.cpp
@@ -0,0 +1,802 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+
+#include "vtkpxBaseGridTransform.h"
+#include "vtkObjectFactory.h"
+#include "vtkMath.h"
+#include "vtkDoubleArray.h"
+#include "pxutil.h"
+#include "math.h"
+#include "vtkOutlineFilter.h"
+#include "vtkTransformPolyDataFilter.h"
+
+/// Size of lookup table for B-spline basis function values
+
+/// Memory for lookup table for B-spline basis function values
+int   vtkpxBaseGridTransform::LookupTableInitialized=0;
+double vtkpxBaseGridTransform::LutSize=0.0;
+double vtkpxBaseGridTransform::LookupTable[LookupTableSize+1][4];
+double vtkpxBaseGridTransform::dLookupTable[LookupTableSize+1][4];
+
+/*
+#define ULT 1
+*/
+
+//----------------------------------------------------------------------------
+inline int dround(double x)
+{
+  return x > 0 ? int(x + 0.5) : int(x - 0.5);
+}
+
+//----------------------------------------------------------------------------
+vtkpxBaseGridTransform* vtkpxBaseGridTransform::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxBaseGridTransform");
+  if(ret)
+    {
+    return (vtkpxBaseGridTransform*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxBaseGridTransform;
+}
+//----------------------------------------------------------------------------
+const char *vtkpxBaseGridTransform::GetInterpolationModeAsString()
+{
+  switch (this->InterpolationMode)
+    {
+    case VTK_GRID_NEAREST:
+      return "NearestNeighbor";
+    case VTK_GRID_LINEAR:
+      return "Linear";
+    case VTK_GRID_CUBIC:
+      return "Cubic";
+    case VTK_GRID_BSPLINE:
+      return "B-Spline";
+    default:
+      return "";
+    }
+}  
+//----------------------------------------------------------------------------
+double vtkpxBaseGridTransform::B(int i, double t)
+{
+  switch (i) 
+    {
+    case 0:
+      return (1-t)*(1-t)*(1-t)/6.0;
+      break;
+      
+    case 1:
+      return (3*t*t*t - 6*t*t + 4)/6.0;
+    case 2:
+      return (-3*t*t*t + 3*t*t + 3*t + 1)/6.0;
+      
+    case 3:
+      return (t*t*t)/6.0;
+    }
+  return 0;
+}
+//----------------------------------------------------------------------------
+inline double vtkpxBaseGridTransform::B0(double t)
+{
+  return (1-t)*(1-t)*(1-t)/6.0;
+}
+//----------------------------------------------------------------------------
+inline double vtkpxBaseGridTransform::B1(double t)
+{
+  return (3*t*t*t - 6*t*t + 4)/6.0;
+}
+//----------------------------------------------------------------------------
+inline double vtkpxBaseGridTransform::B2(double t)
+{
+  return (-3*t*t*t + 3*t*t + 3*t + 1)/6.0;
+}
+//----------------------------------------------------------------------------
+inline double vtkpxBaseGridTransform::B3(double t)
+{
+  return (t*t*t)/6.0;
+}
+//----------------------------------------------------------------------------
+double vtkpxBaseGridTransform::dB(int i, double t)
+{
+  switch (i) 
+    {
+    case 0:
+      return dB0(t);
+    case 1:
+      return dB1(t);
+    case 2:
+      return dB3(t);
+    case 3:
+      return dB3(t);
+    }
+  return 0;
+}
+//----------------------------------------------------------------------------
+inline double vtkpxBaseGridTransform::dB0(double t)
+{
+  return -(1-t)*(1-t)/2.0;
+}
+//----------------------------------------------------------------------------
+inline double vtkpxBaseGridTransform::dB1(double t)
+{
+  return (9*t*t - 12*t)/6.0;
+}
+//----------------------------------------------------------------------------
+inline double vtkpxBaseGridTransform::dB2(double t)
+{
+  return (-9*t*t + 6*t + 3)/6.0;
+}
+//----------------------------------------------------------------------------
+inline double vtkpxBaseGridTransform::dB3(double t)
+{
+  return (t*t)/2.0;
+}
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// Do B-Spline interpolation of the input data 'gridPtr' of extent 'gridExt' 
+// at the 'point'.  The result is placed at 'outPtr'.  
+// The number of scalar components in the data is 'numscalars'
+
+// The tricubic interpolation ensures that both the intensity and
+// the first derivative of the intensity are smooth across the
+// image.  The first derivative is estimated using a 
+// centered-difference calculation.
+
+
+// helper function: set up the lookup indices and the interpolation 
+// coefficients
+
+// tricubic interpolation of a warp grid with derivatives
+// (set derivatives to NULL to avoid computing them).
+
+static inline int GridIrange(int a,int minv,int   maxv)
+{
+  if (a<minv) 
+    return minv;
+  if (a>maxv) 
+    return maxv;
+  return a;
+}
+
+
+template <class Type>
+static inline void vtkBSplineHelper(double displacement[3], 
+				    double derivatives[3][3],
+				    int l,int m,int n,
+				    int S,int T,int U,
+				    double s,double t,double u,
+				    Type *gridPtr, vtkIdType gridInc[3],int ext[6])
+{
+  int i, j, k,K,J,I,offset;
+  double B_K, B_J, B_I;
+  double v, dx,dy,dz;
+
+
+
+  displacement[0]=0;
+  displacement[1]=0;
+  displacement[2]=0;
+
+  if (!derivatives) 
+    {
+       for (k = 0; k < 4; k++)
+	{
+	  K = GridIrange(k + n - 1,ext[4],ext[5]);
+	  B_K   = vtkpxBaseGridTransform::LookupTable[U][k];
+	  for (j = 0; j < 4; j++)
+	    {
+	      J = GridIrange(j + m - 1,ext[2],ext[3]);
+	      B_J   = vtkpxBaseGridTransform::LookupTable[T][j];
+	      for (i = 0; i < 4; i++)
+		{
+		  I = GridIrange(i + l - 1,ext[0],ext[1]);
+
+		  B_I   = vtkpxBaseGridTransform::LookupTable[S][i];
+		  
+		  offset=I*gridInc[0]+J*gridInc[1]+K*gridInc[2];
+		  dx=((double) gridPtr[offset  ]);
+		  dy=((double) gridPtr[offset+1]);
+		  dz=((double) gridPtr[offset+2]);
+
+		  v = B_I * B_J * B_K;
+		  displacement[0] += dx * v;
+		  displacement[1] += dy * v;
+		  displacement[2] += dz * v;
+		  
+		} 
+	    }
+	}
+    } 
+  else 
+    {
+      double dB_K, dB_J, dB_I;
+      for (i=0; i<3; i++) 
+	for (j=0; j<3; j++) 
+	  derivatives[i][j]=0.0;
+    
+      for (k = 0; k < 4; k++)
+	{
+	  K = GridIrange(k + n - 1,ext[4],ext[5]);
+	  B_K   = vtkpxBaseGridTransform::LookupTable[U][k];
+	  dB_K = vtkpxBaseGridTransform::dLookupTable[U][k];
+	  for (j = 0; j < 4; j++)
+	    {
+	      J = GridIrange(j + m - 1,ext[2],ext[3]);
+	      B_J   = vtkpxBaseGridTransform::LookupTable[T][j];
+	      dB_J = vtkpxBaseGridTransform::dLookupTable[T][j];
+	      for (i = 0; i < 4; i++)
+		{
+		I = GridIrange(i + l - 1,ext[0],ext[1]);
+		B_I   = vtkpxBaseGridTransform::LookupTable[S][i];
+		dB_I = vtkpxBaseGridTransform::dLookupTable[S][i];
+		
+		offset=I*gridInc[0]+J*gridInc[1]+K*gridInc[2];
+		dx=((double) gridPtr[offset  ]);
+		dy=((double) gridPtr[offset+1]);
+		dz=((double) gridPtr[offset+2]);
+		
+		v = B_I * B_J * B_K;
+		displacement[0] += dx * v;
+		displacement[1] += dy * v;
+		displacement[2] += dz * v;
+
+		v = B_I * B_J * dB_K;
+		derivatives[0][2] += dx * v;
+		derivatives[1][2] += dy * v;
+		derivatives[2][2] += dz * v;
+
+		v = B_I * dB_J * B_K;
+		derivatives[0][1] += dx * v;
+		derivatives[1][1] += dy * v;
+		derivatives[2][1] += dz * v;
+
+		v = dB_I * B_J * B_K;
+		derivatives[0][0] += dx * v;
+		derivatives[1][0] += dy * v;
+		derivatives[2][0] += dz * v;
+		} 
+	    }
+	} 
+    }
+}
+
+
+// point: point position in the coordinate system of the grid
+// displacement: result of this function
+// derivatives: in the first step NULL
+// gridPtr: pointer to the displacement vectors of the grid
+// gridType: Type of the grid, e.g. VTK_CHAR, VTK_DOUBLE
+// gridExt: min and max index of the control points (can be negative)
+// gridInc: grid increments
+static void vtkBSplineInterpolation(double point[3],
+				    double displacement[3], 
+				    double derivatives[3][3],
+				    void *gridPtr, int gridType, 
+				    int gridExt[6], vtkIdType gridInc[3])
+{
+
+  double s, t, u;
+  // double v, B_K, B_J, B_I;
+  int l, m, n, S, T, U;
+
+  double LUTSIZE=vtkpxBaseGridTransform::LutSize;
+
+  // Xenios Papademetris
+  // Fix floor BUG on Linux
+  l = int(floor(point[0]+0.00001));
+  m = int(floor(point[1]+0.00001));
+  n = int(floor(point[2]+0.00001));
+
+  // End of Fix
+  s = point[0] - l;
+  t = point[1] - m;
+  u = point[2] - n;
+  l -= gridExt[0];
+  m -= gridExt[2];
+  n -= gridExt[4];
+  S = dround(LUTSIZE*s);
+  T = dround(LUTSIZE*t);
+  U = dround(LUTSIZE*u);
+
+  int ext[6];
+
+    
+  ext[0] = -gridExt[0];
+  ext[1] = gridExt[1];
+  ext[2] = -gridExt[2];
+  ext[3] = gridExt[3];
+  ext[4] = -gridExt[4];
+  ext[5] = gridExt[5];
+
+  switch (gridType) 
+    {
+    case VTK_CHAR:
+      vtkBSplineHelper(displacement, derivatives, 
+		       l,m,n,S,T,U,s,t,u,
+		       (char *)gridPtr,gridInc,ext);
+      break;
+    case VTK_UNSIGNED_CHAR:
+      vtkBSplineHelper(displacement, derivatives, 
+		       l,m,n,S,T,U,s,t,u,
+		       (unsigned char *)gridPtr,gridInc,ext);
+      break;
+    case VTK_SHORT:
+      vtkBSplineHelper(displacement, derivatives, 
+		       l,m,n,S,T,U,s,t,u,
+		       (short *)gridPtr,gridInc,ext);
+      break;
+    case VTK_UNSIGNED_SHORT:
+      vtkBSplineHelper(displacement, derivatives, 
+		       l,m,n,S,T,U,s,t,u, 
+		     (unsigned short *)gridPtr,gridInc,ext);
+      break;
+    case VTK_DOUBLE:
+      vtkBSplineHelper(displacement, derivatives, 
+		       l,m,n,S,T,U,s,t,u,
+		       (double *)gridPtr,gridInc,ext);
+      break;
+    }
+
+}		  
+
+//----------------------------------------------------------------------------
+vtkpxBaseGridTransform::vtkpxBaseGridTransform()
+{
+  if (vtkpxBaseGridTransform::LookupTableInitialized==0)
+    {
+      vtkpxBaseGridTransform::LutSize=double(LookupTableSize);
+      double LUTSIZE=vtkpxBaseGridTransform::LutSize;
+      // Initialize lookup table
+      // Arrays are of size LookupTableSize+1
+      for (int i = 0; i <= LookupTableSize; i++)
+	{
+	  double s=double(i)/LUTSIZE;
+	  vtkpxBaseGridTransform::LookupTable[i][0] = this->B0(s);
+	  vtkpxBaseGridTransform::LookupTable[i][1] = this->B1(s);
+	  vtkpxBaseGridTransform::LookupTable[i][2] = this->B2(s);
+	  vtkpxBaseGridTransform::LookupTable[i][3] = this->B3(s);
+	  vtkpxBaseGridTransform::dLookupTable[i][0] = this->dB0(s);
+	  vtkpxBaseGridTransform::dLookupTable[i][1] = this->dB1(s);
+	  vtkpxBaseGridTransform::dLookupTable[i][2] = this->dB2(s);
+	  vtkpxBaseGridTransform::dLookupTable[i][3] = this->dB3(s);
+	}
+      vtkpxBaseGridTransform::LookupTableInitialized=1;
+    }
+  this->SetInterpolationModeToBSpline();
+
+
+}
+
+//----------------------------------------------------------------------------
+void vtkpxBaseGridTransform::SetInterpolationMode(int mode)
+{
+  if (mode == this->InterpolationMode)
+    {
+      return;
+    }
+  this->InterpolationMode = mode;
+  switch(mode)
+    {
+    case VTK_GRID_BSPLINE:
+      this->InterpolationFunction = &vtkBSplineInterpolation;
+      break;
+    default:
+      this->vtkGridTransform::SetInterpolationMode(mode);
+    }
+  this->Modified();
+}
+//----------------------------------------------------------------------------
+vtkAbstractTransform *vtkpxBaseGridTransform::MakeTransform()
+{
+  return vtkpxBaseGridTransform::New();
+}
+//----------------------------------------------------------------------------
+int vtkpxBaseGridTransform::Load(const char* fname)
+{  
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  int ok=Load(fin);
+  gzclose(fin);
+
+  return ok;
+}
+
+int vtkpxBaseGridTransform::Load(gzFile fin,int skipheader,const char* header)
+{
+  char pxtk_buffer[255];
+  
+  //  printf("hirohito:  int vtkpxBaseGridTransform::Load\n");
+  if (skipheader==0)
+    gzgets(fin,pxtk_buffer,100);
+  else
+    strncpy(pxtk_buffer,header,255);
+
+  //  fprintf(stderr,"Header Line =%s\n",pxtk_buffer);
+
+  int interpmode=0;
+  if (gzfindstringinstring(pxtk_buffer,"#vtkpxBaseGridTransform File")==0)
+    {
+      if (gzfindstringinstring(pxtk_buffer,"#vtkpxBaseGridTransform2 File")==0)
+	return 0;
+      else
+	interpmode=1;
+    }
+
+  double ori[3],spa[3];
+  int   dim[3];
+  gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+  sscanf(pxtk_buffer,"%lf %lf %lf",&ori[0],&ori[1],&ori[2]);
+  gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+  sscanf(pxtk_buffer,"%lf %lf %lf",&spa[0],&spa[1],&spa[2]);
+  gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+  sscanf(pxtk_buffer,"%d %d %d",&dim[0],&dim[1],&dim[2]);
+  
+  if (interpmode)
+    {
+      gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+      int tmp;
+      sscanf(pxtk_buffer,"%d",&tmp);
+      this->SetInterpolationMode(tmp);
+    }
+  else
+    this->SetInterpolationModeToBSpline();
+
+  //  printf("hirohito:  int vtkpxBaseGridTransform::Load setting grid\n");
+  vtkImageData *grid = vtkImageData::New();
+  grid->SetScalarType(VTK_DOUBLE);
+  grid->SetSpacing(spa);
+  grid->SetOrigin(ori);
+  grid->SetNumberOfScalarComponents(3);
+  grid->SetExtent(0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1);
+  grid->SetWholeExtent(grid->GetExtent());
+  grid->SetUpdateExtent(grid->GetWholeExtent());
+  grid->AllocateScalars();
+  
+  // pointer to the start address of the whole image
+
+  gzgets(fin,pxtk_buffer,100);  
+  vtkDoubleArray* scalars=(vtkDoubleArray*)grid->GetPointData()->GetScalars();
+
+  for (int ia=0;ia<=2;ia++)
+    scalars->FillComponent(ia,0.0);
+
+  int np=scalars->GetNumberOfTuples();
+  int tmp=0;
+  double dx[3];
+  for (int i=0;i<np;i++)
+    {
+      gzgets(fin,pxtk_buffer,100);
+      sscanf(pxtk_buffer,"%d %lf %lf %lf",&tmp,&dx[0],&dx[1],&dx[2]);
+      scalars->SetTuple(i,dx);
+    }
+
+
+  this->SetDisplacementGrid(grid);
+  return 1;
+}
+//----------------------------------------------------------------------------
+int vtkpxBaseGridTransform::Save(const char* fname)
+{
+  return this->Save(fname,0);
+}
+
+int vtkpxBaseGridTransform::Save(const char* fname,int compression)
+{
+  if (compression==0)
+    {
+      FILE* fout=fopen(fname,"w");
+      if (!fout)
+	return 0;
+      
+      int ok=Save(fout);
+      fclose(fout);
+      return ok;
+    } 
+
+  gzFile fout=gzsuffixopen(fname,"wb",compression);
+  if (!fout)
+    return 0;
+  int ok=Save(fout);
+  gzclose(fout);
+  return ok;
+  
+}
+
+int vtkpxBaseGridTransform::Save(FILE* fout)
+{
+
+  vtkImageData *grid=this->GetDisplacementGrid();
+  if (grid==NULL)
+    return 0;
+  double ori[3],spa[3];
+  int   dim[3];
+
+  grid->GetOrigin(ori);
+  grid->GetSpacing(spa);
+  grid->GetDimensions(dim);
+  vtkDoubleArray* scalars=(vtkDoubleArray*)grid->GetPointData()->GetScalars();
+
+  if (scalars==NULL)
+    return 0;
+
+  int np=scalars->GetNumberOfTuples();
+
+
+  fprintf(fout,"#vtkpxBaseGridTransform2 File\n");
+  fprintf(fout,"#Origin\n %.4f %.4f %.4f\n",ori[0],ori[1],ori[2]);
+  fprintf(fout,"#Spacing\n %.4f %.4f %.4f\n",spa[0],spa[1],spa[2]);
+  fprintf(fout,"#Dimensions\n %d %d %d\n",dim[0],dim[1],dim[2]);
+  fprintf(fout,"#Interpolation Mode\n%d\n",this->InterpolationMode);
+  fprintf(fout,"#Displacements\n");
+
+  for (int i = 0; i < np;i++)
+    fprintf(fout,"%d %.4f %.4f %.4f\n",i,
+	     scalars->GetComponent(i,0),
+	     scalars->GetComponent(i,1),
+	     scalars->GetComponent(i,2));
+
+  return 1;
+}
+//----------------------------------------------------------------------------
+int vtkpxBaseGridTransform::Save(gzFile fout)
+{
+
+  vtkImageData *grid=this->GetDisplacementGrid();
+  if (grid==NULL)
+    return 0;
+  double ori[3],spa[3];
+  int   dim[3];
+
+  grid->GetOrigin(ori);
+  grid->GetSpacing(spa);
+  grid->GetDimensions(dim);
+  vtkDoubleArray* scalars=(vtkDoubleArray*)grid->GetPointData()->GetScalars();
+
+  if (scalars==NULL)
+    return 0;
+
+  int np=scalars->GetNumberOfTuples();
+
+
+  gzprintf(fout,"#vtkpxBaseGridTransform2 File\n");
+  gzprintf(fout,"#Origin\n %.4f %.4f %.4f\n",ori[0],ori[1],ori[2]);
+  gzprintf(fout,"#Spacing\n %.4f %.4f %.4f\n",spa[0],spa[1],spa[2]);
+  gzprintf(fout,"#Dimensions\n %d %d %d\n",dim[0],dim[1],dim[2]);
+  gzprintf(fout,"#Interpolation Mode\n%d\n",this->InterpolationMode);
+  gzprintf(fout,"#Displacements\n");
+
+  for (int i = 0; i < np;i++)
+    gzprintf(fout,"%d %.4f %.4f %.4f\n",i,
+	     scalars->GetComponent(i,0),
+	     scalars->GetComponent(i,1),
+	     scalars->GetComponent(i,2));
+
+  return 1;
+}
+//----------------------------------------------------------------------------
+void vtkpxBaseGridTransform::InitializeDisplacementGridTransform(double in_bounds[6],double spacing,double offset,
+								 vtkAbstractTransform* tr)
+{
+  double bounds[6];
+
+  if ( tr == NULL ) 
+    {
+      for (int ib=0;ib<=5;ib++)
+	bounds[ib]=in_bounds[ib];
+    }
+  else
+    {
+      vtkImageData* img=vtkImageData::New();
+      img->SetDimensions(2,2,2);
+      img->SetOrigin(in_bounds[0],in_bounds[2],in_bounds[4]);
+      img->SetSpacing(in_bounds[1],in_bounds[3],in_bounds[5]);
+      img->AllocateScalars();
+
+      vtkOutlineFilter* outline=vtkOutlineFilter::New();
+      outline->SetInput(img);
+      
+      vtkTransformPolyDataFilter* transformFilter=vtkTransformPolyDataFilter::New();
+      transformFilter->SetInput(outline->GetOutput());
+      transformFilter->SetTransform(tr);
+      transformFilter->Update();
+      transformFilter->GetOutput()->GetBounds(bounds);
+      transformFilter->Delete();
+      outline->Delete();
+      img->Delete();
+    }
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      double diff=(bounds[2*ia+1]-bounds[2*ia]);
+      bounds[2*ia]=bounds[2*ia]-offset*diff;
+      bounds[2*ia+1]=bounds[2*ia]+(diff*(1.0+2.0*offset));
+    }
+
+  this->InitializeDisplacementGridBounds(bounds,spacing,spacing,spacing);
+}
+//----------------------------------------------------------------------------
+void vtkpxBaseGridTransform::InitializeDisplacementGridBounds(double bounds[6],double dx, double dy, double dz)
+{
+
+  double _x1=bounds[0];  
+  double _y1=bounds[2];  
+  double _z1=bounds[4];
+  double _x2=bounds[1];
+  double _y2=bounds[3];
+  double _z2=bounds[5];
+
+  //fprintf(stderr,"\t ** Bounds %.1f:%.1f %.1f:%.1f %.1f:%.1f\n",_x1,_x2,_y1,_y2,_z1,_z2);
+
+  // Intialize control point dimensions
+  int _x = int((_x2 - _x1)/dx+1.5);
+  int _y = int((_y2 - _y1)/dy+1.5);
+  int _z = int((_z2 - _z1)/dz+1.5);
+
+  if (_x<4) _x=4;
+  if (_y<4) _y=4;
+  if (_z<4) _z=4;
+  
+  //  fprintf(stderr,"\t ** Dim %d x %d x %d (dx=%.1f,dy=%.1f,dz=%.1f)\n",_x,_y,_z,dx,dy,dz);
+  
+  // Intialize control point spacing
+  double _dx =  double(_x2 - _x1) / double(_x-1);
+  double _dy =  double(_y2 - _y1) / double(_y-1) ;
+  double _dz =  double(_z2 - _z1) / double(_z-1) ;
+
+  /*  fprintf(stderr,"\t ** Spacing  (%.1f,%.1f,%.1f)\n",_dx,_dy,_dz);
+      fprintf(stderr,"\t ** Origin  (%.1f,%.1f,%.1f)\n",_x1,_y1,_z1);*/
+
+  vtkImageData *grid = vtkImageData::New();
+  grid->SetScalarType(VTK_DOUBLE);
+  grid->SetSpacing(_dx,_dy,_dz);
+  grid->SetOrigin(_x1 , _y1 , _z1 );
+  grid->SetNumberOfScalarComponents(3);
+  grid->SetExtent(0, _x-1, 0, _y-1, 0, _z-1); 
+  grid->SetUpdateExtent(grid->GetWholeExtent());
+  grid->AllocateScalars();
+  this->SetDisplacementGrid(grid);
+
+  vtkDataArray* scal=(this->DisplacementGrid->GetPointData()->GetScalars());
+  for (int i=0;i<=2;i++)
+    scal->FillComponent(i,0.0);
+
+}
+
+int vtkpxBaseGridTransform::Export(const char* fname,const char* vname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+    return 0;
+  
+    vtkImageData *grid=this->GetDisplacementGrid();
+  if (grid==NULL)
+    return 0;
+  double ori[3],spa[3];
+  int   dim[3];
+
+  grid->GetOrigin(ori);
+  grid->GetSpacing(spa);
+  grid->GetDimensions(dim);
+  vtkDoubleArray* scalars=(vtkDoubleArray*)grid->GetPointData()->GetScalars();
+
+  if (scalars==NULL)
+    return 0;
+
+  int np=scalars->GetNumberOfTuples();
+
+
+  fprintf(fout,"#vtkpxBaseGridTransform2 File\n");
+  fprintf(fout,"# name: %s\n# type: matrix\n",vname);
+  fprintf(fout,"# rows: %d\n# columns: 1\n",np*3);
+
+  for (int i = 0; i < np;i++)
+    fprintf(fout,"%.4f\n%.4f\n%.4f\n",
+	     scalars->GetComponent(i,0),
+	     scalars->GetComponent(i,1),
+	     scalars->GetComponent(i,2));
+
+ 
+  fclose(fout);
+  return 1;
+}
+
+int vtkpxBaseGridTransform::Import(const char* fname)
+{
+  vtkImageData *grid=this->GetDisplacementGrid();
+  if (grid==NULL)
+    return 0;
+  
+  int dim[3]; grid->GetDimensions(dim);
+  vtkDoubleArray* scalars=(vtkDoubleArray*)grid->GetPointData()->GetScalars();
+
+  if (scalars==NULL)
+    return 0;
+
+
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  
+  int np=scalars->GetNumberOfTuples();
+  char pxtk_buffer[255];
+  gzgets(fin,pxtk_buffer,100);
+  gzgets(fin,pxtk_buffer,100);
+  gzgets(fin,pxtk_buffer,100);
+  gzgets(fin,pxtk_buffer,100);
+  gzgets(fin,pxtk_buffer,100);
+
+  for (int i = 0; i < np;i++)
+    for (int j = 0 ; j <=2;j++)
+      {
+	  gzgets(fin,pxtk_buffer,100);
+	  double v;
+	  sscanf(pxtk_buffer,"%lf",&v);
+	  scalars->SetComponent(i,j,v);
+      }
+
+  gzclose(fin);
+  return 1;
+}
+
+
+#ifdef ULT 
+#undef ULT 
+#endif
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxBaseGridTransform.h b/bioimagesuite30_src/Registration/vtkpxBaseGridTransform.h
new file mode 100644
index 0000000..b01660c
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxBaseGridTransform.h
@@ -0,0 +1,149 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+
+
+#ifndef __vtkpxBaseGridTransform_h
+#define __vtkpxBaseGridTransform_h
+
+#include "vtkGridTransform.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "pxutil.h"
+#include "vtkDoubleArray.h"
+
+#define VTK_GRID_BSPLINE 4
+#define LookupTableSize 1000
+
+class vtkpxBaseGridTransform : public vtkGridTransform
+{
+ public:
+  static vtkpxBaseGridTransform *New();
+  vtkTypeMacro(vtkpxBaseGridTransform,vtkGridTransform);
+
+
+  // Description:
+  // Set interpolation mode for sampling the grid.  Higher-order
+  // interpolation allows you to use a sparser grid.
+  // Default: Linear.
+  void SetInterpolationMode(int mode);
+  void SetInterpolationModeToBSpline()
+    { this->SetInterpolationMode(VTK_GRID_BSPLINE); };
+  const char *GetInterpolationModeAsString();
+
+  // Description:
+  // Initialize Displacement Grid
+  void InitializeDisplacementGridTransform(double bounds[6],double spacing,double offset,vtkAbstractTransform* tr=NULL);
+  void InitializeDisplacementGridBounds(double bounds[6],double dx, double dy, double dz);
+
+//BTX
+
+  // Description:
+  // Make another transform of the same type.
+  vtkAbstractTransform *MakeTransform();
+
+  /// Size of lookup table for B-spline basis function values
+  /// Memory for lookup table for B-spline basis function values
+  static    double LookupTable[LookupTableSize+1][4];
+  static    double dLookupTable[LookupTableSize+1][4];
+  static    int    LookupTableInitialized;
+  static    double  LutSize;
+//ETX
+
+
+  // Description:
+  // Return Result of B-sline basis functions 
+  static double B (int, double);
+  static double dB (int, double);
+
+  // Description:
+  // Load/Save Transformation
+  virtual int Load(const char* fname);
+  virtual int Save(const char* fname);
+  virtual int Save(const char* fname,int compression);
+
+  virtual int Load(gzFile fin,int skipheader=0,const char* header=NULL);
+  virtual int Save(FILE* fout);
+  virtual int Save(gzFile fout);
+
+  // Description:
+  // Export/Import to Octave Format
+  virtual int Export(const char* fname,const char* vname);
+  virtual int Import(const char* fname);
+
+ protected:
+  vtkpxBaseGridTransform();
+
+//BTX
+
+  /// Returns the value of the i-th B-spline basis function
+
+  static double B0(double);
+  static double B1(double);
+  static double B2(double);
+  static double B3(double);
+
+  /// Returns the derivative of the i-th B-spline basis functio
+
+  static double dB0(double);
+  static double dB1(double);
+  static double dB2(double);
+  static double dB3(double);
+
+//ETX
+
+};
+
+
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxComboTransform.cpp b/bioimagesuite30_src/Registration/vtkpxComboTransform.cpp
new file mode 100644
index 0000000..684f389
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxComboTransform.cpp
@@ -0,0 +1,580 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkpxComboTransform.h"
+#include "vtkCollection.h"
+#include "vtkTransformToGrid.h"
+#include "vtkStructuredPointsReader.h"
+#include "vtkStructuredPoints.h"
+#include "vtkImageCast.h"
+//----------------------------------------------------------------------------
+vtkpxComboTransform *vtkpxComboTransform::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxComboTransform");
+  if(ret)
+    {
+      return (vtkpxComboTransform*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxComboTransform;
+}
+
+//----------------------------------------------------------------------------
+vtkpxComboTransform::vtkpxComboTransform()
+{
+  this->LinearTransform=NULL;
+  this->NonLinearFirst=1;
+  this->GridTransformationsCollection=vtkCollection::New();
+  this->InitializeTransformations();
+}
+
+//----------------------------------------------------------------------------
+vtkpxComboTransform::~vtkpxComboTransform()
+{
+  this->SetLinearTransform(NULL);
+  this->GridTransformationsCollection->RemoveAllItems();
+  this->GridTransformationsCollection->Delete();
+}
+//----------------------------------------------------------------------------
+int vtkpxComboTransform::Save(const char* fname)
+{
+  return this->Save(fname,0);
+}
+
+int vtkpxComboTransform::Save(const char* fname,int compression)
+{
+  if (compression==0)
+    {
+      FILE* fout=fopen(fname,"w");
+      if (!fout)
+	return 0;
+      
+      int ok=Save(fout);
+      fclose(fout);
+      return ok;
+    } 
+
+  gzFile fout=gzsuffixopen(fname,"wb",compression);
+  if (!fout)
+    return 0;
+  int ok=Save(fout);
+  gzclose(fout);
+  return ok;
+  
+}
+
+
+int vtkpxComboTransform::Save(FILE* fout)
+{
+  if (this->LinearTransform==NULL || this->GridTransformationsCollection==NULL)
+    return 0;
+
+  int nt=this->GridTransformationsCollection->GetNumberOfItems();
+
+  if (nt==1)
+    {
+      fprintf(fout,"#vtkpxNewComboTransform File\n");
+    }
+  else
+    {
+      fprintf(fout,"#vtkpxMultiComboTransform File\n");
+      fprintf(fout,"#Number of Non Linear Transformations\n%d\n",
+	      this->GridTransformationsCollection->GetNumberOfItems());
+    }
+  fprintf(fout,"#NonLinearFirst\n%d\n",this->NonLinearFirst);
+  fprintf(fout,"#Linear Component\n");
+  for(int i=0;i<=3;i++)
+    {
+      for (int j=0;j<=3;j++)
+	fprintf(fout,"%7.3f ",this->LinearTransform->GetMatrix()->GetElement(i,j));
+      fprintf(fout,"\n");
+    }
+  int ok=1;
+  for (int i=0;i<nt;i++)
+    {
+      vtkpxGridTransform* obj=(vtkpxGridTransform*)this->GridTransformationsCollection->GetItemAsObject(i);  
+      ok=ok*obj->Save(fout);
+    }
+  return ok;
+}
+
+int vtkpxComboTransform::Save(gzFile fout)
+{
+  if (this->LinearTransform==NULL || this->GridTransformationsCollection==NULL)
+    return 0;
+
+  int nt=this->GridTransformationsCollection->GetNumberOfItems();
+
+  if (nt==1)
+    {
+      gzprintf(fout,"#vtkpxNewComboTransform File\n");
+    }
+  else
+    {
+      gzprintf(fout,"#vtkMultiComboTransform File\n");
+      gzprintf(fout,"#Number of Non Linear Transformations\n%d\n",
+	       this->GridTransformationsCollection->GetNumberOfItems());
+    }
+  gzprintf(fout,"#NonLinearFirst\n%d\n",this->NonLinearFirst);
+  gzprintf(fout,"#Linear Component\n");
+  for(int i=0;i<=3;i++)
+    {
+      for (int j=0;j<=3;j++)
+	gzprintf(fout,"%7.3f ",this->LinearTransform->GetMatrix()->GetElement(i,j));
+      gzprintf(fout,"\n");
+    }
+
+  int ok=1;
+  for (int i=0;i<nt;i++)
+    {
+      vtkpxGridTransform* obj=(vtkpxGridTransform*)this->GridTransformationsCollection->GetItemAsObject(i);  
+      ok=ok*obj->Save(fout);
+    }
+  return ok;
+}
+
+//----------------------------------------------------------------------------
+int vtkpxComboTransform::Load(const char* fname)
+{  
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  int ok=Load(fin);
+  gzclose(fin);
+
+  if (ok==-1)
+    {
+      // Load this as .vtk file
+      ok=0;
+      vtkStructuredPointsReader* rd=vtkStructuredPointsReader::New();
+      rd->SetFileName(fname);
+      rd->Update();
+
+      int nc=rd->GetOutput()->GetNumberOfScalarComponents();
+      if (nc==3)
+	{
+	  vtkImageCast* cst=vtkImageCast::New();
+	  cst->SetInput(rd->GetOutput());
+	  cst->SetOutputScalarTypeToDouble();
+	  cst->Update();
+	  this->ClearGridTransformationsCollection();
+	  this->LinearTransform->Identity();
+	  this->SetNonLinearFirst(1);
+	  vtkpxGridTransform* gr=vtkpxGridTransform::New();
+	  gr->SetDisplacementGrid(cst->GetOutput());
+	  gr->SetInterpolationModeToLinear();
+	  this->AddGridTransform(gr);
+	  gr->Delete();
+	  cst->Delete();
+
+	  //	  fprintf(stderr,"Transformation Loaded from %s (vtk format)\n",fname);
+	  ok=1;
+	}
+      rd->Delete();
+    }
+      
+
+  return ok;
+}
+
+int vtkpxComboTransform::Load(gzFile fin)
+{
+  this->InitializeTransformations();
+  char pxtk_buffer[255];
+  gzgets(fin,pxtk_buffer,100);
+  //  fprintf(stderr,"Header = %s\n",pxtk_buffer);
+  int isvtk=gzfindstringinstring(pxtk_buffer,"# vtk DataFile Version 3.0");
+  if (isvtk)
+    return -1;
+
+  int iscombo=gzfindstringinstring(pxtk_buffer,"#vtkpxComboTransform File");
+  int isnewcombo=gzfindstringinstring(pxtk_buffer,"#vtkpxNewComboTransform File");
+  int ismulticombo=gzfindstringinstring(pxtk_buffer,"#vtkpxMultiComboTransform File");
+  int isgrid=gzfindstringinstring(pxtk_buffer,"#vtkpxBaseGridTransform2 File");
+
+
+
+  //  fprintf(stderr,"iscombo=%d isnewcombo=%d ismulticombo=%d isgrid=%d\n",
+  //	  iscombo,isnewcombo,ismulticombo,isgrid);
+
+  if (iscombo==0 && isnewcombo==0 && ismulticombo==0 && isgrid==0)
+    return 0;
+
+
+  this->ClearGridTransformationsCollection();
+
+  if (isgrid==1)
+    {
+      this->LinearTransform->Identity();
+      this->SetNonLinearFirst(1);
+    }
+
+  int numgrid=1;
+
+  if (iscombo || isgrid)
+    {
+      this->SetNonLinearFirst(0);
+    }
+  else if (isnewcombo)
+    {
+      gzgets(fin,pxtk_buffer,100);
+      gzgets(fin,pxtk_buffer,200);
+      int a;      sscanf(pxtk_buffer,"%d",&a);
+      this->SetNonLinearFirst(a);
+    } 
+  else if (ismulticombo)
+    {
+      gzgets(fin,pxtk_buffer,100);
+      gzgets(fin,pxtk_buffer,200);
+      sscanf(pxtk_buffer,"%d",&numgrid);
+      gzgets(fin,pxtk_buffer,100);
+      gzgets(fin,pxtk_buffer,200);
+      int a;      sscanf(pxtk_buffer,"%d",&a);
+      this->SetNonLinearFirst(a);
+    }
+  
+  // Now Load Identity
+  if (!isgrid)
+    {
+      gzgets(fin,pxtk_buffer,100);
+      vtkMatrix4x4* mat=vtkMatrix4x4::New();
+      mat->Identity();
+      
+      float m1,m2,m3,m4;
+      for (int i=0;i<=3;i++)
+	{
+	  gzgets(fin,pxtk_buffer,200);
+	  sscanf(pxtk_buffer,"%f %f %f %f",&m1,&m2,&m3,&m4);
+	  mat->SetElement(i,0,m1);
+	  mat->SetElement(i,1,m2);
+	  mat->SetElement(i,2,m3);
+	  mat->SetElement(i,3,m4);
+	}
+      
+      this->LinearTransform->Identity();
+      this->LinearTransform->PostMultiply();
+      this->LinearTransform->Concatenate(mat);
+      mat->Delete();
+    } 
+  
+  int ok=1;
+  if (!isgrid)
+    {
+      for (int i=0;i<numgrid;i++)
+	{
+	  vtkpxGridTransform* gr=vtkpxGridTransform::New();
+	  int ok2=gr->Load(fin);
+	  if (ok2)
+	    {
+	      this->AddGridTransform(gr);
+	    }
+	  else
+	    {
+	      fprintf(stderr,"Failed to read Grid Transform %d of %d\n",i+1,numgrid);
+	    }
+	  gr->Delete();
+	  ok=ok*ok2;
+	}
+    }
+  else
+    {
+      numgrid=1;
+      vtkpxGridTransform* gr=vtkpxGridTransform::New();
+      ok=gr->Load(fin,1,"#vtkpxBaseGridTransform2 File");
+      if (ok)
+	this->AddGridTransform(gr);
+      else
+	fprintf(stderr,"Failed to Load Single Grid Transform\n");
+
+      gr->Delete();
+    }
+  return ok;
+  
+}
+//----------------------------------------------------------------------------
+void vtkpxComboTransform::UpdateStack()
+{
+  this->Identity();
+  this->PostMultiply();
+  if (this->NonLinearFirst==0)
+      this->Concatenate(this->LinearTransform);
+
+  int nt=this->GridTransformationsCollection->GetNumberOfItems();
+  for (int i=nt-1;i>=0;i=i-1)
+    {
+      vtkpxGridTransform* obj=(vtkpxGridTransform*)this->GridTransformationsCollection->GetItemAsObject(i);  
+      this->Concatenate(obj);
+    }
+  
+  if (this->NonLinearFirst==1)
+    this->Concatenate(this->LinearTransform);
+  this->Modified();
+}
+
+// --------------------------------------------------------------------------------
+
+void vtkpxComboTransform::SetNonLinearFirst(int s)
+{
+  int old=this->NonLinearFirst;
+  this->NonLinearFirst=(s>0);
+  //  if (old!=this->NonLinearFirst)
+  this->UpdateStack();
+}
+
+void vtkpxComboTransform::ChangeLinearTransform(vtkTransform* LinearTransformIn)
+{
+  this->SetLinearTransform(LinearTransformIn);
+  this->UpdateStack();
+}
+
+
+int vtkpxComboTransform::GetNumberOfGridTransformations()
+{
+  return this->GridTransformationsCollection->GetNumberOfItems();
+}
+
+// --------------------------------------------------------------------------------
+vtkpxGridTransform* vtkpxComboTransform::GetGridTransform()
+{
+  return this->GetGridTransformByIndex(-1);
+}
+
+vtkpxGridTransform* vtkpxComboTransform::GetGridTransformByIndex(int index)
+{
+  int nt=this->GridTransformationsCollection->GetNumberOfItems();
+  if (index<0 || index>=nt)
+    index=nt-1;
+  vtkpxGridTransform* obj=(vtkpxGridTransform*)this->GridTransformationsCollection->GetItemAsObject(index);  
+  return obj;
+}
+
+void vtkpxComboTransform::ChangeGridTransform(vtkpxGridTransform* GridTransform)
+{
+  return this->ChangeGridTransformByIndex(GridTransform,-1);
+}
+ 
+void vtkpxComboTransform::ChangeGridTransformByIndex(vtkpxGridTransform* GridTransform,int index)
+{
+  int nt=this->GridTransformationsCollection->GetNumberOfItems();
+  if (index<0 || index>=nt)
+    index=nt-1;
+  
+  this->GridTransformationsCollection->ReplaceItem(index,GridTransform);
+  this->UpdateStack();
+}
+
+
+void vtkpxComboTransform::SetGridTransform(vtkpxGridTransform* GridTransform)
+{
+  int nt=this->GridTransformationsCollection->GetNumberOfItems();
+  if (nt>0)
+    {
+      this->ChangeGridTransformByIndex(GridTransform,-1);
+      return;
+    }
+
+  this->GridTransformationsCollection->AddItem(GridTransform);
+  this->UpdateStack();
+}
+
+
+int vtkpxComboTransform::ClearGridTransformationsCollection()
+{
+  this->GridTransformationsCollection->RemoveAllItems();
+  this->UpdateStack();
+  return 0;
+}
+
+int vtkpxComboTransform::AddGridTransform(vtkpxGridTransform* GridTransform)
+{
+  this->GridTransformationsCollection->AddItem(GridTransform);
+  this->UpdateStack();
+  return 0;
+}
+
+
+void vtkpxComboTransform::SetTransformations(vtkTransform* LinearTransformIn,vtkpxGridTransform* GridTransformIn)
+{
+  this->SetLinearTransform(LinearTransformIn);
+  this->SetGridTransform(GridTransformIn);
+  this->UpdateStack();
+}
+
+
+void vtkpxComboTransform::InitializeTransformations()
+{
+  if (this->LinearTransform==NULL || this->GetNumberOfGridTransformations()==0 )
+    {
+      vtkTransform* tr=vtkTransform::New();
+      vtkpxGridTransform* gr=vtkpxGridTransform::New();
+      this->SetTransformations(tr,gr);
+      tr->Delete();
+      gr->Delete();
+    }
+}
+
+// Copy will be a pain
+// --------------------
+void vtkpxComboTransform::InternalDeepCopy(vtkAbstractTransform *gtrans)
+{
+  vtkGeneralTransform::InternalDeepCopy(gtrans);
+  vtkpxComboTransform *transform =(vtkpxComboTransform *)gtrans;
+  
+  vtkTransform* tr=vtkTransform::New();
+  tr->Identity();
+  tr->Concatenate(transform->GetLinearTransform());
+  
+  this->SetNonLinearFirst(transform->GetNonLinearFirst());
+  this->SetLinearTransform(tr);
+  tr->Delete();
+
+  int nt=transform->GetNumberOfGridTransformations();
+  this->ClearGridTransformationsCollection();
+
+  for (int i=0;i<nt;i++)
+    {
+      vtkpxGridTransform* newgridxform=vtkpxGridTransform::New();
+      newgridxform->DeepCopy(transform->GetGridTransformByIndex(i));
+      this->AddGridTransform(newgridxform);
+      newgridxform->Delete();
+    }
+}
+
+void vtkpxComboTransform::Copy(vtkpxComboTransform *ComboTransform)
+{
+  this->InternalDeepCopy(ComboTransform);
+}
+// --------------------
+void vtkpxComboTransform::Inverse()
+{
+  fprintf(stderr,"Inverting Transform");
+  this->GetLinearTransform()->Inverse();
+
+  int nt=this->GridTransformationsCollection->GetNumberOfItems();
+  if (nt==1)
+    {
+      this->GetGridTransform()->Inverse();
+    }
+  else
+    {
+      vtkCollection* temp=vtkCollection::New();
+      for (int i=0;i<nt;i++)
+	temp->AddItem(this->GridTransformationsCollection->GetItemAsObject(i));
+
+      this->GridTransformationsCollection->RemoveAllItems();
+
+      for (int i=nt-1;i>=0;i=i-1)
+	{
+	  vtkpxGridTransform* tr=(vtkpxGridTransform*)temp->GetItemAsObject(i);
+	  tr->Inverse();
+      	  this->GridTransformationsCollection->AddItem(tr);
+	}
+      temp->Delete();
+    }
+  this->SetNonLinearFirst(1-this->NonLinearFirst);
+}
+
+
+
+
+int vtkpxComboTransform::CollapseTransormationsCollection()
+{
+  int nt=this->GridTransformationsCollection->GetNumberOfItems();
+
+  // No point in this if we only have zero or 1 transformation !!!!
+  if (nt<2)
+    return 1;
+
+  double spacing[3],origin[3],outer[3];
+
+  vtkGeneralTransform* gen=vtkGeneralTransform::New();
+  gen->PostMultiply();
+
+
+  for (int i=0;i<nt;i++)
+    {
+      vtkpxGridTransform* tr=(vtkpxGridTransform*)this->GridTransformationsCollection->GetItemAsObject(i);  
+      vtkImageData* img=tr->GetDisplacementGrid();
+      double spa[3];img->GetSpacing();
+      double ori[3];img->GetOrigin();
+      int    dim[3];img->GetDimensions(dim);
+
+      for (int ia=0;ia<=2;ia++)
+	{
+	  if (i==0 || spa[ia]<spacing[ia])
+	    spacing[ia]=spa[ia];
+	  if (i==0 || ori[ia]<origin[ia])
+	    origin[ia]=ori[ia];
+
+	  double maxv=ori[ia]+spacing[ia]*double(dim[ia]-1);
+	  if (i==0 || outer[ia]<maxv)
+	    outer[ia]=maxv;
+	}
+      gen->Concatenate(tr);
+    }
+
+  int extent[6];
+  for (int ia=0;ia<=2;ia++)
+    {
+      extent[ia*2]=0;
+      extent[ia*2+1]=int(outer[ia]/spacing[ia])+1;
+    }
+
+  
+  vtkTransformToGrid* tgrid=vtkTransformToGrid::New();
+  tgrid->SetGridExtent(extent);
+  tgrid->SetGridOrigin(origin);
+  tgrid->SetGridSpacing(spacing);
+  tgrid->SetInput(gen);
+  tgrid->Update();
+
+  vtkpxGridTransform* newgr=vtkpxGridTransform::New();
+  newgr->SetInterpolationModeToLinear();
+  newgr->SetDisplacementGrid(tgrid->GetOutput());
+	
+  this->ClearGridTransformationsCollection();
+  this->AddGridTransform(newgr);
+
+  tgrid->Delete();
+  newgr->Delete();
+  gen->Delete();
+
+  return 1;
+
+
+}
+
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxComboTransform.h b/bioimagesuite30_src/Registration/vtkpxComboTransform.h
new file mode 100644
index 0000000..a37ad49
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxComboTransform.h
@@ -0,0 +1,227 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxComboTransform.h,v $
+  Language:  C++
+  Date:      $Date: 2003/01/03 16:42:27 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#ifndef __vtkpxComboTransform_h
+#define __vtkpxComboTransform_h
+
+#include "vtkGeneralTransform.h"
+#include "vtkpxGridTransform.h"
+#include "vtkTransform.h"
+#include "pxutil.h"
+
+class vtkCollection;
+
+class vtkpxComboTransform : public vtkGeneralTransform
+{
+ public:
+  static vtkpxComboTransform *New();
+  vtkTypeMacro(vtkpxComboTransform,vtkGeneralTransform);
+  
+  // Description:
+  // Manipulate the Linear Transformation 
+  vtkGetObjectMacro(LinearTransform,vtkTransform);
+  virtual void ChangeLinearTransform(vtkTransform* LinearTransform);
+
+
+  // Description:
+  // Change The Grid Transformations 
+  virtual int GetNumberOfGridTransformations();
+  virtual vtkpxGridTransform* GetGridTransform();
+  virtual vtkpxGridTransform* GetGridTransformByIndex(int index);
+
+  virtual void ChangeGridTransform(vtkpxGridTransform* GridTransform);
+  virtual void ChangeGridTransformByIndex(vtkpxGridTransform* GridTransform,int index);
+
+  virtual void SetGridTransform(vtkpxGridTransform* GridTransform);
+  virtual int  AddGridTransform(vtkpxGridTransform* GridTransform);
+
+  // Description:
+  // Change The Internal Transformations -- if more than one grid manipulate the last Grid Transform
+  virtual void SetTransformations(vtkTransform* LinearTransform,vtkpxGridTransform* GridTransform);
+
+  // Description:
+  virtual int ClearGridTransformationsCollection();
+  virtual int CollapseTransormationsCollection();
+  
+  // Description:
+  // Load and Save Functionality 
+  virtual int Load(const char* fname);
+  virtual int Save(const char* fname);
+  virtual int Save(const char* fname,int compression);
+  
+  //BTX
+  virtual int Load(gzFile fin);
+  virtual int Save(FILE* fout);
+  virtual int Save(gzFile fout);
+  //ETX
+  
+  // Description:
+  // Virtual Do Copy (Shallow)
+  virtual void Copy(vtkpxComboTransform *transform);
+
+  // Description:
+  // NonLinear First
+  vtkGetMacro(NonLinearFirst,int);
+  virtual void SetNonLinearFirst(int s);
+
+  // Description:
+  // Invert Transformation
+  void Inverse();
+
+
+ protected:
+  // Description:
+  // Update Stack
+  virtual void UpdateStack();
+
+  // Description:
+  // Constructors and Destructors
+  vtkpxComboTransform();
+  virtual ~vtkpxComboTransform();
+
+  // Description:
+  // Set the Internal Transformations
+  vtkSetObjectMacro(LinearTransform,vtkTransform);
+
+
+  vtkpxComboTransform(const vtkpxComboTransform&);  
+  void operator=(const vtkpxComboTransform&);  
+
+  // Description:
+  // Copy Transformation
+  void InternalDeepCopy(vtkAbstractTransform *t);
+
+  // Description:
+  // Call this to initialize default mode
+  virtual void InitializeTransformations();
+
+
+  // Description:
+  // These are the two Grid Transformations 
+  vtkTransform*       LinearTransform;
+  int                 NonLinearFirst;
+  vtkCollection*      GridTransformationsCollection;
+
+
+  //BTX
+  // Description:
+  // Most of the following simply protects methods from outside use ...
+  // see vtkGeneralTransform.h for comments
+  //  void Inverse() { vtkGeneralTransform::Inverse();}
+  void Translate(double x, double y, double z) {  vtkGeneralTransform::Translate(x,y,z);}
+  void RotateWXYZ(double angle, double x, double y, double z) { vtkGeneralTransform::RotateWXYZ(angle,x,y,z);}
+
+
+  // Description:
+  // Create a rotation matrix about the X, Y, or Z axis and concatenate
+  // it with the current transformation according to PreMultiply or
+  // PostMultiply semantics.  The angle is expressed in degrees.
+  void RotateX(double angle) { vtkGeneralTransform::RotateWXYZ(angle, 1, 0, 0); }
+  void RotateY(double angle) { vtkGeneralTransform::RotateWXYZ(angle, 0, 1, 0); }
+  void RotateZ(double angle) { vtkGeneralTransform::RotateWXYZ(angle, 0, 0, 1); }
+
+  // Description:
+  // Create a scale matrix (i.e. set the diagonal elements to x, y, z)
+  // and concatenate it with the current transformation according to
+  // PreMultiply or PostMultiply semantics.
+  void Scale(double x, double y, double z) { vtkGeneralTransform::Scale(x,y,z); }
+  void Scale(const double s[3]) { vtkGeneralTransform::Scale(s[0], s[1], s[2]); }
+  void Scale(const float s[3])  { vtkGeneralTransform::Scale(s[0], s[1], s[2]); }
+
+  // Description:
+  // Concatenates the matrix with the current transformation according
+  // to PreMultiply or PostMultiply semantics.
+  void Concatenate(vtkMatrix4x4 *matrix) { vtkGeneralTransform::Concatenate(matrix); }
+  void Concatenate(const double elements[16]) { vtkGeneralTransform::Concatenate(elements); }
+
+
+  // Description:
+  // Concatenate the specified transform with the current transformation
+  // according to PreMultiply or PostMultiply semantics.
+  // The concatenation is pipelined, meaning that if any of the
+  // transformations are changed, even after Concatenate() is called,
+  // those changes will be reflected when you call TransformPoint().
+  void Concatenate(vtkAbstractTransform *transform) { vtkGeneralTransform::Concatenate(transform);}
+
+  // Description:
+  // Sets the internal state of the transform to PreMultiply. All subsequent
+  // operations will occur before those already represented in the
+  // current transformation.  In homogeneous matrix notation, M = M*A where
+  // M is the current transformation matrix and A is the applied matrix.
+  // The default is PreMultiply.
+  void PreMultiply()  { vtkGeneralTransform::PreMultiply(); }
+  void PostMultiply() { vtkGeneralTransform::PostMultiply(); }
+
+  // Description:
+  void SetInput(vtkAbstractTransform *input) { vtkGeneralTransform::SetInput(input); }
+
+  // Description:
+  // Pushes the current transformation onto the transformation stack.
+  void Push() { vtkGeneralTransform::Push();}
+
+  // Description:
+  // Deletes the transformation on the top of the stack and sets the top 
+  // to the next transformation on the stack.
+  void Pop() { vtkGeneralTransform::Pop(); }
+  //ETX
+};
+
+
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxDistortionCorrection.cpp b/bioimagesuite30_src/Registration/vtkpxDistortionCorrection.cpp
new file mode 100644
index 0000000..8550194
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxDistortionCorrection.cpp
@@ -0,0 +1,428 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxNonLinearRegistration.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/04/16 17:51:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxDistortionCorrection.h"
+#include "vtkObjectFactory.h"
+#include "pxutil.h"
+#include "vtkbisImageReslice.h"
+#include "vtkpxUtil.h"
+#include "vtkImageMathematics.h"
+#include "vtkMath.h"
+#include "vtkpxRegistration.h"
+
+vtkpxDistortionCorrection* vtkpxDistortionCorrection::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxDistortionCorrection");
+  if(ret)
+    {
+    return (vtkpxDistortionCorrection*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxDistortionCorrection;
+  
+}
+//-------------------------------------------------------------------------
+vtkpxDistortionCorrection::vtkpxDistortionCorrection()
+{
+  this->LastImageJacobian=NULL;
+  this->LastSignalLossImage=NULL;
+  this->UseJacobian=0;
+  this->UseSignalLossCorrection=0;
+  this->KeepSameNumberOfSlices=1;
+  this->UpdateTransform->SetNonLinearFirst(0);
+  this->PhaseEncodeAxis=1;
+}
+//-------------------------------------------------------------------------
+vtkpxDistortionCorrection::~vtkpxDistortionCorrection() 
+{
+  if (this->LastImageJacobian!=NULL)
+    this->LastImageJacobian->Delete();
+  if (this->LastSignalLossImage!=NULL)
+    this->LastSignalLossImage->Delete();
+}
+//-------------------------------------------------------------------------
+int vtkpxDistortionCorrection::Initialize(int level) 
+{
+  this->WarpX=0;
+  this->WarpY=0;
+  this->WarpZ=0;
+
+  switch (this->PhaseEncodeAxis)
+    {
+    case 0:
+      this->WarpX=1;
+      break;
+    case 1:
+      this->WarpY=1;
+      break;
+    case 2:
+      this->WarpZ=1;
+      break;
+    }
+
+  vtkpxNonLinearRegistration::Initialize(level);
+  if (this->InitialTransform!=NULL)
+    {
+      if (this->InitialTransform->IsA("vtkLinearTransform")==1)
+	this->ComboTransform->SetNonLinearFirst(0);
+    }
+
+  
+  if (this->LastImageJacobian!=NULL)
+    this->LastImageJacobian->Delete();
+  this->LastImageJacobian=vtkImageData::New();
+
+  if (this->LastSignalLossImage!=NULL)
+    this->LastSignalLossImage->Delete();
+  this->LastSignalLossImage=vtkImageData::New();
+  
+  return 1;
+}
+//-------------------------------------------------------------------------
+double vtkpxDistortionCorrection::Evaluate()
+{
+  if (this->LastTargetImage==NULL)
+    this->LastTargetImage=vtkImageData::New();
+  vtkpxRegistration::ResliceImage(this->LastTargetImage,this->SampledTransformImage,
+				  this->SampledReferenceImage,this->ComboTransform,this->InterpolationMode);
+
+  if (this->UseJacobian==1)
+    this->ScaleIntensitiesUsingJacobian(this->LastTargetImage);
+  this->Histogram->WeightedFillHistogram(this->SampledReferenceImage,this->LastTargetImage,this->SampledReferenceWeightImage,1);  
+  
+  this->LastSimilarity=this->Similarity(this->Histogram);
+  if (this->Lambda>0.0001)
+    this->LastSmoothness=this->ComputeInternalEnergy(this->GridTransform);
+  else
+    this->LastSmoothness=0.0;
+  return this->LastSimilarity-this->LastSmoothness*this->Lambda;
+}
+//-------------------------------------------------------------------------
+double vtkpxDistortionCorrection::EvaluatePiece(vtkImageData* reference,
+						vtkImageData* target,
+						vtkImageData* previoustarget,
+						vtkImageData* weightimage,
+						int cpoint)
+{
+  this->Histogram->BackupHistogram();
+
+  // Reslice And Scale 
+  vtkImageData* tmp=vtkImageData::New();
+  vtkpxRegistration::ResliceImage(tmp,target,reference,this->ComboTransform,this->InterpolationMode);
+  if (this->UseJacobian==1)
+    this->ScaleIntensitiesUsingJacobian(tmp);
+  
+  // Remove Last Target Value
+  this->Histogram->WeightedRemoveFromHistogram(reference,previoustarget,weightimage);
+  this->Histogram->WeightedFillHistogram(reference,tmp,weightimage,0);
+  tmp->Delete();
+
+  double e1=this->Similarity(this->Histogram);
+  this->Histogram->ResetHistogram();
+
+  double l1=0.0;
+  if (this->Lambda>0.000001)
+    l1 = this->ComputeInternalEnergy(this->GridTransform,cpoint)*double(NumberOfControlPoints);
+  double s1=e1-this->Lambda*l1;
+  
+  return s1;
+}
+//-------------------------------------------------------------------------
+int vtkpxDistortionCorrection::ComputeSimpleJacobianAndSignalLoss(vtkImageData* ref,vtkImageData* jacobian,vtkImageData* signalloss,
+								  vtkAbstractTransform* tr)
+{
+  if (ref==NULL || jacobian==NULL || tr==NULL)
+    return 0;
+
+  int dim[3];  ref->GetDimensions(dim);
+  int dim2[3]; jacobian->GetDimensions(dim2);
+
+  if (dim[0]!=dim2[0] || dim[1]!=dim2[1] || dim[2]!=dim2[2] || 
+      jacobian->GetScalarType()!=VTK_DOUBLE || 
+      jacobian->GetNumberOfScalarComponents()!=1)
+    {
+      jacobian->CopyStructure(ref);
+      jacobian->SetNumberOfScalarComponents(1);
+      jacobian->SetScalarTypeToDouble();
+      jacobian->AllocateScalars();
+    }
+
+  int sigmode=0;
+  if (signalloss!=NULL)
+    {
+      sigmode=1;
+      signalloss->GetDimensions(dim2);
+      
+      if (dim[0]!=dim2[0] || dim[1]!=dim2[1] || dim[2]!=dim2[2] || 
+	  signalloss->GetScalarType()!=VTK_DOUBLE || 
+	  signalloss->GetNumberOfScalarComponents()!=1)
+	{
+	  signalloss->CopyStructure(ref);
+	  signalloss->SetNumberOfScalarComponents(1);
+	  signalloss->SetScalarTypeToDouble();
+	  signalloss->AllocateScalars();
+	}
+    }
+  
+  double sp[3];  ref->GetSpacing(sp);
+  double ori[3]; ref->GetOrigin(ori);
+  double der[3][3],x[3],x2[3];
+  
+  vtkDataArray* dat=jacobian->GetPointData()->GetScalars();
+  vtkDataArray* sig=NULL;
+  if (sigmode)
+    sig=signalloss->GetPointData()->GetScalars();
+  int index=0;
+
+  for (int k=0;k<dim[2];k++)
+    {
+      x[2]=k*sp[2]+ori[2];
+      for (int j=0;j<dim[1];j++)
+	{
+	  x[1]=j*sp[1]+ori[1];
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      x[0]=i*sp[0]+ori[0];
+	      tr->InternalTransformDerivative(x,x2,der);
+	      double det=der[1][1];//vtkMath::Determinant3x3(der);
+	      dat->SetComponent(index,0,det);
+	      if (sigmode)
+		{
+		  double v=1.0+sqrt(der[1][0]*der[1][0]*sp[0]*sp[0]+
+				   der[1][1]*der[1][1]*sp[1]*sp[1]+
+				   der[1][2]*der[1][2]*sp[2]*sp[2]);
+		  sig->SetComponent(index,0,v);
+		}
+	      ++index;
+	    }
+	}
+    }
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxDistortionCorrection::ScaleIntensitiesUsingJacobian(vtkImageData* inout)
+{
+  if (this->UseSignalLossCorrection)
+    return vtkpxDistortionCorrection::ScaleIntensitiesUsingJacobianAndSignalLoss(inout,this->GridTransform,
+										 this->LastImageJacobian,
+										 this->LastSignalLossImage,
+										 this->LogarithmMode);
+								  
+
+  return vtkpxDistortionCorrection::ScaleIntensitiesUsingJacobian(inout,this->GridTransform,
+								  this->LastImageJacobian,
+								  this->LogarithmMode);
+								  
+}
+//-------------------------------------------------------------------------
+int vtkpxDistortionCorrection::ScaleIntensitiesUsingJacobian(vtkImageData* inout,vtkAbstractTransform* tr,vtkImageData* jac,
+							     int logmode)
+{
+  int ok=vtkpxDistortionCorrection::ComputeSimpleJacobianAndSignalLoss(inout,jac,NULL,tr);
+  // int ok=vtkpxRegistration::ComputeSimpleJacobianImage(inout,jac,tr,1,0.0);
+  if (ok==0)
+    {
+      fprintf(stderr,"Bad Jacobian Calculation\n");
+      return 0;
+    }
+
+  int np1= inout->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int np2= jac->GetPointData()->GetScalars()->GetNumberOfTuples();
+
+  if (np1!=np2)
+    {
+      fprintf(stderr,"Bad Jacobian Image\n");
+      return 0;
+    }
+
+  vtkDataArray* scal=inout->GetPointData()->GetScalars();
+  double *img2 = (double*) jac->GetPointData()->GetScalars()->GetVoidPointer(0);  
+  
+  for (int i=0;i<np1;i++)
+    {
+      double a=scal->GetComponent(i,0);
+      double b=( *img2);
+      if (b<0.33)
+	b=0.33;
+      else if (b>3.0)
+	b=3.0;
+      if (logmode)
+	scal->SetComponent(i,0,a+log(b));
+      else
+	scal->SetComponent(i,0,a*b);
+      ++img2;
+    }
+  return 1;
+}
+//------------------------------------------------------------------------- 
+int vtkpxDistortionCorrection::ScaleIntensitiesUsingJacobianAndSignalLoss(vtkImageData* inout,vtkAbstractTransform* tr,
+									  vtkImageData* jac,vtkImageData* sig,
+									  int logmode)
+{
+  int ok=vtkpxDistortionCorrection::ComputeSimpleJacobianAndSignalLoss(inout,jac,sig,tr);
+  if (ok==0)
+    {
+      fprintf(stderr,"Bad Jacobian/Signal Loss Calculation\n");
+      return 0;
+    }
+
+  int np1= inout->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int np2= jac->GetPointData()->GetScalars()->GetNumberOfTuples();
+
+  if (np1!=np2)
+    {
+      fprintf(stderr,"Bad Jacobian Image\n");
+      return 0;
+    }
+
+  vtkDataArray* scal=inout->GetPointData()->GetScalars();
+  double *img2 = (double*) jac->GetPointData()->GetScalars()->GetVoidPointer(0);  
+  double *loss = (double*) sig->GetPointData()->GetScalars()->GetVoidPointer(0);  
+  
+  for (int i=0;i<np1;i++)
+    {
+      double a=scal->GetComponent(i,0);
+      double b=( *img2);
+      double l=( *loss);
+
+      if (b<0.33)
+	b=0.33;
+      else if (b>3.0)
+	b=3.0;
+      if (logmode)
+	scal->SetComponent(i,0,a+log(b)+log(l));
+      else
+	scal->SetComponent(i,0,a*b*l);
+      ++img2;
+      ++loss;
+    }
+  return 1;
+}
+//-------------------------------------------------------------------------
+
+int vtkpxDistortionCorrection::Finalize(int level)
+{
+  if (this->LastImageJacobian!=NULL && this->UseJacobian==1)
+    {
+      double range[2];
+      this->LastImageJacobian->GetPointData()->GetScalars()->GetRange(range);
+      fprintf(stderr,"Jacobian Range =%.4f:%.4f\n",range[0],range[1]);
+    }
+  return vtkpxNonLinearRegistration::Finalize(level);
+}
+//-------------------------------------------------------------------------
+
+double vtkpxDistortionCorrection::ComputeSimilarityBetweenImages(vtkImageData* img1,vtkImageData* img2,
+								vtkAbstractTransform* tr,
+								double resolution[3],double sigma,
+								int metric,int logarithmmode,
+								int interpolation,int numbins)
+{
+  vtkImageData* ref=vtkImageData::New();
+  vtkImageData* trn=vtkImageData::New();
+  
+  vtkpxRegistration::ResampleAndSmoothImage(ref,img1,
+					    resolution,sigma,1.0);
+  
+  vtkpxRegistration::ResampleAndSmoothImage(trn,img2,
+					    resolution,sigma,1.0);
+  
+  short minr=0,maxr=1,mint=0,maxt=1;
+  int num_ref=vtkpxRegistration::CalculateNumberOfBinsAndAdjustImage(ref,numbins,minr,maxr,logarithmmode);
+  int num_tar=vtkpxRegistration::CalculateNumberOfBinsAndAdjustImage(trn,numbins,mint,maxt,logarithmmode);
+
+  vtkpxJointHistogram* Histogram=vtkpxJointHistogram::New();
+  Histogram->Allocate(num_ref,num_tar);
+
+  vtkbisImageReslice* resl=vtkbisImageReslice::New();    resl->OptimizationOff();
+
+  resl->SetInput(trn);
+  resl->SetInformationInput(ref);
+  resl->SetResliceTransform(tr);
+  resl->SetInterpolationMode(interpolation);
+  resl->Update();
+
+  vtkImageData* target=vtkImageData::New();
+  target->ShallowCopy(resl->GetOutput());
+  resl->Delete();
+
+
+  metric=Irange(metric,0,2);
+
+  if (metric>0)
+    {
+      vtkImageData* jac=vtkImageData::New();
+      vtkImageData* loss=vtkImageData::New();
+
+      vtkpxDistortionCorrection::ComputeSimpleJacobianAndSignalLoss(target,jac,loss,tr);
+      if (metric==2)
+	vtkpxDistortionCorrection::ScaleIntensitiesUsingJacobianAndSignalLoss(target,tr,jac,loss,logarithmmode);
+      else
+	vtkpxDistortionCorrection::ScaleIntensitiesUsingJacobian(target,tr,jac,logarithmmode);
+      jac->Delete();
+      loss->Delete();
+    }
+								  
+  Histogram->FillHistogram(ref,target,1);
+  double val= +Histogram->NormalizedMutualInformation();
+
+  target->Delete();
+  Histogram->Delete();
+  ref->Delete();
+  trn->Delete();
+  return val;
+}
+
diff --git a/bioimagesuite30_src/Registration/vtkpxDistortionCorrection.h b/bioimagesuite30_src/Registration/vtkpxDistortionCorrection.h
new file mode 100644
index 0000000..46f8aa0
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxDistortionCorrection.h
@@ -0,0 +1,184 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxDistortionCorrection.h,v $
+  Language:  C++
+  Date:      $Date: 2002/04/16 13:19:58 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxDistortionCorrection - Filter for ffd registration based on voxel similarity measures.
+
+// .SECTION Description
+// This class implements a registration filter for the non-rigid registration
+// of images.
+
+
+#ifndef _VTKPXDISTORTIONCORRECTION_H
+#define _VTKPXDISTORTIONCORRECTION_H
+
+#include "vtkpxNonLinearRegistration.h"
+#include "vtkImageData.h"
+#include "vtkpxComboTransform.h"
+#include "vtkDoubleArray.h"
+
+
+class vtkpxDistortionCorrection : public vtkpxNonLinearRegistration {
+
+public:
+  static vtkpxDistortionCorrection* New();
+  vtkTypeMacro(vtkpxDistortionCorrection,vtkpxNonLinearRegistration);
+
+  // Description:
+  // Use Jacobian Correction
+  vtkSetClampMacro(UseJacobian,int,0,1);
+  vtkGetMacro(UseJacobian,int);
+  vtkBooleanMacro(UseJacobian,int);
+
+  // Description:
+  // Use Jacobian Correction
+  vtkSetClampMacro(UseSignalLossCorrection,int,0,1);
+  vtkGetMacro(UseSignalLossCorrection,int);
+  vtkBooleanMacro(UseSignalLossCorrection,int);
+
+  // Description:
+  // Set Phase Encode Axis
+  vtkSetClampMacro(PhaseEncodeAxis,int,0,2);
+  vtkGetMacro(PhaseEncodeAxis,int);
+  void SetPhaseEncodeAxisToX() { this->SetPhaseEncodeAxis(0); }
+  void SetPhaseEncodeAxisToY() { this->SetPhaseEncodeAxis(1); }
+  void SetPhaseEncodeAxisToZ() { this->SetPhaseEncodeAxis(2); }
+  
+  // Description:
+  // Scale Intensities by Computing the Jacobian of the Transformation
+  static  int ScaleIntensitiesUsingJacobian(vtkImageData* inout,vtkAbstractTransform* tr,vtkImageData* jac,int logmode=0);
+  static  int ScaleIntensitiesUsingJacobianAndSignalLoss(vtkImageData* inout,vtkAbstractTransform* tr,
+							 vtkImageData* jac,vtkImageData* signalloss,
+							 int logmode=0);
+  static int ComputeSimpleJacobianAndSignalLoss(vtkImageData* ref,vtkImageData* jacobian,vtkImageData* signalloss,
+						vtkAbstractTransform* tr);
+
+  // Description:
+  // Compute Similarity between images allowing for distortion and signalloss (metric=0 nmi 1=jac nmi,2=jac & loss nmi)
+  static double ComputeSimilarityBetweenImages(vtkImageData* img1,vtkImageData* img2,
+					      vtkAbstractTransform* tr,
+					      double resolution[3],double sigma,
+					      int metric,int logarithmmode,
+					      int interpolation,int numbins);
+    
+protected:
+
+  // Make all these protected 
+  // Constructor
+  vtkpxDistortionCorrection();
+  virtual ~vtkpxDistortionCorrection();
+  vtkpxDistortionCorrection(const vtkpxDistortionCorrection&) {};
+  void operator=(const vtkpxDistortionCorrection&) {};
+
+  // Description:
+  // Image Data to store last match (for removing bins from histogram)
+  vtkImageData* LastImageJacobian;
+  vtkImageData* LastSignalLossImage;
+  
+  // Description:
+  // Flag to store use Jacobian
+  int UseJacobian;
+  int UseSignalLossCorrection;
+  int PhaseEncodeAxis;
+
+  // Description:
+  // Initialize for level level
+  virtual int Initialize(int level);
+
+
+  // Description:
+  // Evaluates the registration. This function evaluates the registration by
+  // looping over the target image and interpolating the transformed source 
+  // image while filling the joint histogram. This function returns the value
+  // of the similarity measure using Similarity().
+  virtual double Evaluate();
+
+  // Description:
+  // Evaluates the registration. This function evaluates the registration by
+  // looping over the target image and interpolating the transformed source 
+  // image while filling the joint histogram. This function returns the value
+  // of the similarity measure using Similarity().
+  virtual double EvaluatePiece(vtkImageData* reference,
+			      vtkImageData* target,
+			      vtkImageData* previoustarget,
+			       vtkImageData* weightimage,
+			      int cpoint=-1);
+
+
+  // Make these protected in this case 
+  // Description:
+  // Enable control point displacements in X,Y and Z directions (defaults=1)
+  vtkSetClampMacro(WarpX,int,0,1);
+  vtkSetClampMacro(WarpY,int,0,1);
+  vtkSetClampMacro(WarpZ,int,0,1);
+
+  vtkGetMacro(WarpX,int);
+  vtkGetMacro(WarpY,int);
+  vtkGetMacro(WarpZ,int);
+
+  vtkBooleanMacro(WarpX,int);
+  vtkBooleanMacro(WarpY,int);
+  vtkBooleanMacro(WarpZ,int);
+
+  // Description:
+  // Scale Image with Jacobian 
+  virtual int ScaleIntensitiesUsingJacobian(vtkImageData* inout);
+
+  virtual int Finalize(int level);
+
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxGridTransform.cpp b/bioimagesuite30_src/Registration/vtkpxGridTransform.cpp
new file mode 100644
index 0000000..9970e37
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxGridTransform.cpp
@@ -0,0 +1,1791 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "pxutil.h"
+#include "vtkDoubleArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPoints.h"
+#include "vtkDataArray.h"
+#include "vtkStructuredPoints.h"
+#include "vtkpxGridTransform.h"
+#include "vtkLinearTransform.h"
+#include "vtkpxUtil.h"
+#include "vtkpxMatrix.h"
+#include "vtkpxWeightedLandmarkTransform.h"
+#include "vtkCollection.h"
+#include "vtkpxOptimizer.h"
+#include "vtkbisImageReslice.h"
+#include "pxisinf.h"
+#include "bioimagesuite_settings.h"
+#include "vtkTimerLog.h"
+
+//-----------------------------------------------------------------------------------
+vtkpxGridTransform* vtkpxGridTransform::New()
+{
+  // First try to create the object from the vtkObjectFactory
+
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxGridTransform");
+  if(ret)
+    {
+    return (vtkpxGridTransform*)ret;
+    }
+
+  // If the factory was unable to create the object, then create it here.
+
+  return new vtkpxGridTransform;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxGridTransform::vtkpxGridTransform()
+{
+  for (int ia=0;ia<=2;ia++)
+    {
+      this->GridDimensions[ia]=0;
+      this->GridOrigin[ia]=0.0;
+      this->GridSpacing[ia]=1.0;
+    }
+  this->GridSliceDimensions=1;
+  this->NumberOfControlPoints=1;
+  this->Displacements=NULL;
+
+  this->InverseTolerance = 0.1;
+  this->InverseIterations = 10;
+  this->ApproximationMode=0;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxGridTransform::~vtkpxGridTransform()
+{
+}
+
+//----------------------------------------------------------------------------
+void vtkpxGridTransform::InitializeDisplacementGrid(double bounds[6],double dx, double dy, double dz)
+{
+  this->InitializeDisplacementGridBounds(bounds,dx,dy,dz);
+}
+void vtkpxGridTransform::InitializeDisplacementGrid(vtkImageData *image, double spacing,double offset,vtkAbstractTransform* tr)
+{
+  double bounds[6];  image->GetBounds(bounds);
+  this->InitializeDisplacementGridTransform(bounds,spacing,offset,tr);
+  fprintf(stderr,"Dimensions=%d,%d,%d Spacing=%.2f,%.2f,%.2f Origin=%.2f,%.2f,%.2f\n",
+	  this->GridDimensions[0],	  this->GridDimensions[1],	  this->GridDimensions[2],
+	  this->GridSpacing[0],	  this->GridSpacing[1],	  this->GridSpacing[2],
+	  this->GridOrigin[0],	  this->GridOrigin[1],	  this->GridOrigin[2]);
+ 
+}
+//----------------------------------------------------------------------------
+void vtkpxGridTransform::SetDisplacementGrid(vtkImageData *grid)
+{
+  if (grid==NULL)
+    return;
+
+  vtkpxBaseGridTransform::SetDisplacementGrid(grid);
+
+  this->DisplacementGrid->GetDimensions(this->GridDimensions);
+  this->DisplacementGrid->GetOrigin(this->GridOrigin);
+  this->DisplacementGrid->GetSpacing(this->GridSpacing);
+
+  this->Displacements=(vtkDoubleArray*)this->DisplacementGrid->GetPointData()->GetScalars();
+  this->NumberOfControlPoints=1;
+  this->NumberOfControlPoints=this->Displacements->GetNumberOfTuples();
+  this->GridSliceDimensions=this->GridDimensions[1]*this->GridDimensions[0]; 
+}
+//----------------------------------------------------------------------------
+// Index Manipulation
+//----------------------------------------------------------------------------
+inline int  vtkpxGridTransform::GetControlPointIndex(int i,int j,int k)
+{
+  i=Irange(i,0,this->GridDimensions[0]-1);
+  j=Irange(j,0,this->GridDimensions[1]-1);
+  k=Irange(k,0,this->GridDimensions[2]-1);
+
+  return i+j*this->GridDimensions[0]+k*this->GridSliceDimensions;
+}
+
+inline void vtkpxGridTransform::GetControlPointIndices(int index,int ind[3])
+{
+  index=Irange(index,0,this->NumberOfControlPoints-1);
+  ind[2]=index/this->GridSliceDimensions;
+  int t=index%this->GridSliceDimensions;
+  ind[1]=t/this->GridDimensions[0];
+  ind[0]=t%this->GridDimensions[0];
+}
+//----------------------------------------------------------------------------
+//  Get double* pointer to the displacement of control point index (0..numcontrolpoints-1)
+//----------------------------------------------------------------------------
+inline double* vtkpxGridTransform::GetControlPointPointer(int index)
+{
+  index=Irange(index,0,this->NumberOfControlPoints-1);
+  return this->Displacements->GetPointer(index*3);
+}
+//-------------------------------------------------------------------------
+// Get/Set Displacement of control point index 
+//----------------------------------------------------------------------------
+inline double vtkpxGridTransform::GetControlPointDisplacement(int index,int comp)
+{
+  comp=Irange(comp,0,2);
+  double* ptr=this->GetControlPointPointer(index);
+  return ptr[comp];
+}
+//-------------------------------------------------------------------------
+inline void vtkpxGridTransform::GetControlPointDisplacement(int index,double val[3])
+{
+  double* ptr=this->GetControlPointPointer(index);
+  for (int ia=0;ia<=2;ia++)
+    val[ia]=ptr[ia];
+}
+//-------------------------------------------------------------------------
+inline void vtkpxGridTransform::SetControlPointDisplacement(int index,int comp,double val)
+{
+  comp=Irange(comp,0,2);
+  double* ptr=this->GetControlPointPointer(index);
+  ptr[comp]=val;
+}
+
+inline void vtkpxGridTransform::SetControlPointDisplacement(int index,double val[3])
+{
+  double* ptr=this->GetControlPointPointer(index);
+  for (int i=0;i<=2;i++)
+    ptr[i]=val[i];
+}
+//----------------------------------------------------------------------------
+// Move Control Point index
+//----------------------------------------------------------------------------
+inline void vtkpxGridTransform::ShiftControlPoint(int index,int comp,double val)
+{
+  comp=Irange(comp,0,2);
+  double* ptr=this->GetControlPointPointer(index);
+  if (ptr!=NULL)
+    ptr[comp]+=val;
+  else
+    vtkErrorMacro(<<"NULL Pointer\n");
+}
+//-------------------------------------------------------------------------
+inline void vtkpxGridTransform::ShiftControlPoint(int index,double val[3])
+{
+  double* ptr=this->GetControlPointPointer(index);
+  for (int i=0;i<=2;i++)
+    ptr[i]+=val[i];
+}
+//-------------------------------------------------------------------------
+// Get the Location of control point index
+//-------------------------------------------------------------------------
+inline void vtkpxGridTransform::GetControlPointLocation(int index,double p[3])
+{
+  int ind[3];  this->GetControlPointIndices(index,ind);
+  for (int ia=0;ia<=2;ia++)
+    {
+      p[ia]=this->GridOrigin[ia]+this->GridSpacing[ia]*double(ind[ia]);
+    }
+}
+//----------------------------------------------------------------------------
+inline double vtkpxGridTransform::GetControlPointLocation(int index,int comp)
+{
+  double p[3];
+  this->GetControlPointLocation(index,p);
+  comp=Irange(comp,0,2);
+  return p[comp];
+}
+//----------------------------------------------------------------------------
+// Get Internal Coordinates both lattice and arclengths
+//----------------------------------------------------------------------------
+void vtkpxGridTransform::GetCoordinatesInGrid(double p[3],int lat[3],double s[3])
+{
+  for (int ia=0;ia<=2;ia++)
+    {
+      double x=(p[ia]-this->GridOrigin[ia])/this->GridSpacing[ia]; 
+      lat[ia]=int(floor(x+0.0001));
+      s[ia]=x-lat[ia];
+    }
+}
+//----------------------------------------------------------------------------
+// Compute Derivative Matrix for Point x1,x2,x3 and store in vtkpxMatrix
+//----------------------------------------------------------------------------
+double vtkpxGridTransform::ComputeDerivativeMatrix(double x1,double x2,double x3,vtkpxMatrix* matr)
+{
+  double der[3][3];
+  double x[3]; x[0]=x1; x[1]=x2; x[2]=x3;
+  double det=this->ComputeDerivativeMatrix(x,der);
+  matr->Zeros(3,3);
+  for (int ia=0;ia<=2;ia++)
+    for (int ib=0;ib<=2;ib++)
+      matr->SetElement(ia,ib,der[ia][ib]);
+  return det;
+}
+
+double vtkpxGridTransform::ComputeDerivativeMatrix(double x[3],double der[3][3])
+{
+  double x2[3];
+  this->InternalTransformDerivative(x,x2,der);
+  return vtkMath::Determinant3x3(der);
+}
+
+//----------------------------------------------------------------------------
+// Compute Derivative at location of control point index
+//----------------------------------------------------------------------------
+double vtkpxGridTransform::ComputeDerivativeMatrix(int index,vtkpxMatrix* matr)
+{
+  double der[3][3];
+  double x[3]; this->GetControlPointLocation(index,x);
+  double det=this->ComputeDerivativeMatrix(x,der);
+  matr->Zeros(3,3);
+  for (int ia=0;ia<=2;ia++)
+    for (int ib=0;ib<=2;ib++)
+      matr->SetElement(ia,ib,der[ia][ib]);
+  return det;
+}
+
+double vtkpxGridTransform::ComputeDerivativeMatrix(int index,double der[3][3])
+{
+  double x[3]; this->GetControlPointLocation(index,x);
+  return this->ComputeDerivativeMatrix(x,der);
+}
+
+//----------------------------------------------------------------------------
+double vtkpxGridTransform::ComputeDerivative(int index,int comp1,int comp2)
+{
+  double x[3];
+  this->GetControlPointLocation(index,x);
+  return this->ComputeDerivative(x,comp1,comp2);
+}
+
+double vtkpxGridTransform::ComputeDerivative(double x1,double x2,double x3,int comp1,int comp2)
+{
+  double x[3];
+  x[0]=x1; x[1]=x2; x[2]=x3;
+  return this->ComputeDerivative(x,comp1,comp2);
+
+}
+//----------------------------------------------------------------------------
+// Single Component of Derivative
+//----------------------------------------------------------------------------
+double vtkpxGridTransform::ComputeDerivative(double x[3],int comp1,int comp2)
+{
+  comp1=Irange(comp1,0,2);
+  comp2=Irange(comp1,0,2);
+  double x2[3],der[3][3];
+  this->ForwardTransformDerivative(x,x2,der);
+  return der[comp1][comp2];
+}
+//----------------------------------------------------------------------------
+// Stuff Needed to fit transformation to set of points 
+//----------------------------------------------------------------------------
+void vtkpxGridTransform::FormWeightMatrix(vtkPoints* points,vtkpxMatrix* W)
+{
+  int nump=points->GetNumberOfPoints();
+
+  if (nump<1)
+    return;
+
+  int numc=this->NumberOfControlPoints;
+  if (numc<1)
+    return;
+  
+  W->Zeros(nump,numc);
+
+  for (int node = 0; node < nump; node++)
+    {
+      double p1[3],s[3];
+      int  lat[3];
+      points->GetPoint(node,p1);
+      this->GetCoordinatesInGrid(p1,lat,s);
+      
+      for (int k = 0; k < 4; k++)
+	{
+	  int K = Irange(k + lat[2] - 1,0,this->GridDimensions[2]-1);
+	  for (int j = 0; j < 4; j++)
+	    {
+	      int J = Irange(j + lat[1] - 1,0,this->GridDimensions[1]-1);
+	      for (int i = 0; i < 4; i++)
+		{
+		  int I = Irange(i + lat[0] - 1,0,this->GridDimensions[0]-1);
+		  int   cpoint=I+J*this->GridDimensions[0]+K*this->GridSliceDimensions;
+		  double wgt= B(i, s[0]) * B(j, s[1]) * B(k, s[2]);
+		  W->AddToElement(node,cpoint,wgt);
+		}
+	    }
+	}
+    }
+}
+
+
+double vtkpxGridTransform::TestTransformPoint(double p1[3],double p2[3])
+{
+  double p2a[3];
+  fprintf(stderr,"****\n");
+  this->TransformPoint(p1,p2a);
+  fprintf(stderr,"****\n");
+
+  double s[3];
+  int  lat[3];
+
+  double pp[3]; 
+  for (int ia=0;ia<=2;ia++)
+    pp[ia]=p1[ia];
+
+  this->GetCoordinatesInGrid(pp,lat,s);
+ 
+  fprintf(stderr,"p1 = (%.2f,%.2f,%.2f) lat=(%d,%d,%d), s=(%.2f,%.2f,%.2f)\n",
+	  p1[0],p1[1],p1[2],lat[0],lat[1],lat[2],s[0],s[1],s[2]);
+
+  /*  if (p1[2]>94.79 && p1[2]<94.81)
+    {
+      lat[2]-=1;
+      s[2]+=1.0;
+      fprintf(stderr,"\t\t\t p1 = (%.2f,%.2f,%.2f) lat=(%d,%d,%d), s=(%.2f,%.2f,%.2f)\n",
+	      p1[0],p1[1],p1[2],lat[0],lat[1],lat[2],s[0],s[1],s[2]);
+	      }*/
+
+  {
+    for (int ia=0;ia<=2;ia++)
+      p2[ia]=p1[ia];
+  }
+     
+  for (int k = 0; k < 4; k++)
+    {
+      int K = Irange(k + lat[2] - 1,0,this->GridDimensions[2]-1);
+      for (int j = 0; j < 4; j++)
+	{
+	  int J = Irange(j + lat[1] - 1,0,this->GridDimensions[1]-1);
+	  for (int i = 0; i < 4; i++)
+	    {
+	      int I = Irange(i + lat[0] - 1,0,this->GridDimensions[0]-1);
+	      int   cpoint=I+J*this->GridDimensions[0]+K*this->GridSliceDimensions;
+	      double wgt= B(i, s[0]) * B(j, s[1]) * B(k, s[2]);
+
+	      double c[3],d[3];
+	      this->GetControlPointLocation(cpoint,c);
+	      this->GetControlPointDisplacement(cpoint,d);
+	      for (int ia=0;ia<=2;ia++)
+		p2[ia]+=wgt*d[ia];
+	      if (wgt>0.005)
+		fprintf(stderr,"\t\t (%d %d %d) wgt=%.2f c=(%.1f,%.1f,%.1f) \t p2=(%.1f,%.1f,%.1f) \n",I,J,K,wgt,c[0],c[1],c[2],p2[0],p2[1],p2[2]);
+
+	    }
+	}
+    }
+
+  double d=sqrt(vtkMath::Distance2BetweenPoints(p2a,p2));
+  
+  fprintf(stderr,"p1 (%.1f,%.1f,%.1f) ---> \t (%.1f,%.1f,%.1f)\n\t\t\t (%.1f,%.1f,%.1f)  d=%.2f\n",
+	  p1[0],p1[1],p1[2],
+	  p2a[0],p2a[1],p2a[2],
+	  p2[0],p2[1],p2[2],d);
+  return d;
+}
+
+double vtkpxGridTransform::TestTransformPoint(double x,double y,double z)
+{
+  double p1[3],p2[3];
+  p1[0]=x;p1[1]=y;p1[2]=z;
+  p2[0]=0;p2[1]=0;p2[2]=0;
+  
+  return this->TestTransformPoint(p1,p2);
+}
+
+//----------------------------------------------------------------------------
+// Form Cached Collections between points and control points 
+//----------------------------------------------------------------------------
+int vtkpxGridTransform::FormCollectionStructure(vtkPoints* points,vtkCollection* ControlsCollection)
+{
+  return this->FormCollectionStructure(points,ControlsCollection,0.0);
+}
+
+int vtkpxGridTransform::FormCollectionStructure(vtkPoints* points,vtkCollection* ControlsCollection,double thr)
+{
+  if (points==NULL || ControlsCollection==NULL)
+    return 0;
+  
+  thr=Frange(thr,0.0,0.2);
+
+  ControlsCollection->RemoveAllItems();
+  int np=points->GetNumberOfPoints();
+  int nc=this->NumberOfControlPoints;
+
+  vtkDoubleArray** arrlist=new vtkDoubleArray*[nc];
+
+  for (int cp=0;cp<nc;cp++)
+    {
+      vtkDoubleArray* fl=vtkDoubleArray::New();
+      fl->SetNumberOfComponents(2);
+      fl->Allocate(10,10);
+      ControlsCollection->AddItem(fl);
+      arrlist[cp]=fl;
+    }
+
+  for (int node=0;node<np;node++)
+    {
+      double p1[3],s[3];
+      int  lat[3];
+      points->GetPoint(node,p1);
+      this->GetCoordinatesInGrid(p1,lat,s);
+      //      double sum=0.0;
+
+      for (int k = 0; k < 4; k++)
+	{
+	  int K = Irange(k + lat[2] - 1,0,this->GridDimensions[2]-1);
+	  for (int j = 0; j < 4; j++)
+	    {
+	      int J = Irange(j + lat[1] - 1,0,this->GridDimensions[1]-1);
+	      for (int i = 0; i < 4; i++)
+		{
+		  int I = Irange(i + lat[0] - 1,0,this->GridDimensions[0]-1);
+		  int   cpoint=I+J*this->GridDimensions[0]+K*this->GridSliceDimensions;
+		  double wgt= B(i, s[0]) * B(j, s[1]) * B(k, s[2]);
+		  //sum+=wgt;
+		  if (wgt>=thr)
+		    {
+		      //vtkDoubleArray* fl=(vtkDoubleArray*)ControlsCollection->GetItemAsObject(cpoint);
+		      vtkDoubleArray* fl=arrlist[cpoint];
+		      int numt=fl->GetNumberOfTuples();
+		      int found=0,l=0;
+		      
+		      while (l<numt && found==0)
+			{
+			  int cand=(int)fl->GetComponent(l,0);
+			  if (cand==node)
+			    {
+			      fl->SetComponent(l,1,fl->GetComponent(l,1)+wgt);
+			      found=1;
+			    }
+			  l++;
+			}
+		      
+		      if (found==0)
+			fl->InsertNextTuple2(double(node),wgt);
+		    }
+		}
+	    }
+	}
+      //      fprintf(stderr,"node=%d sum=%f\n",node,sum);
+    }
+
+  delete [] arrlist;
+
+
+  int sum=0;
+  ControlsCollection->InitTraversal();
+  for (int p=0;p<nc;p++)
+    {
+      vtkDoubleArray* fl=(vtkDoubleArray*)ControlsCollection->GetNextItemAsObject();
+      sum+=fl->GetNumberOfTuples();
+    }
+  int m=int(sum/nc);
+  //fprintf(stderr,"Mean Number of Points=%d\n",m);
+  return m;
+
+}
+//----------------------------------------------------------------------------
+int vtkpxGridTransform::InitialApproximateTransformation(vtkAbstractTransform* tr)
+{
+  if (tr==NULL)
+    return 0;
+
+  double tp[3],tq[3];
+  tr->Update();
+  vtkImageData *grid=this->DisplacementGrid;
+  for (int k=0;k<this->GridDimensions[2];k++)
+    {
+      tp[2]=this->GridOrigin[2]+this->GridSpacing[2]*double(k);
+      for (int j=0;j<this->GridDimensions[1];j++)
+	{
+	  tp[1]=this->GridOrigin[1]+this->GridSpacing[1]*double(j);
+	  for (int i=0;i<this->GridDimensions[0];i++)
+	    {
+	      tp[0]=this->GridOrigin[0]+this->GridSpacing[0]*double(i);
+	      tr->InternalTransformPoint(tp,tq);
+	      double *v=(double*)grid->GetScalarPointer(i,j,k);
+	      for (int ia=0;ia<=2;ia++)
+		v[ia]=tq[ia]-tp[ia];
+	    }
+	}
+    }
+
+  this->Update();
+  return 1;
+}
+//-------------------------------------------------------------------------
+void vtkpxGridTransform::GenerateTestPoints(vtkPoints* points,double incr)
+{
+  int nc=this->NumberOfControlPoints;
+
+  incr=Frange(incr,0.2,3.0);
+
+  //  fprintf(stderr,"Incr=%f\n",incr);
+  double max=nc/(incr*incr*incr)+10;
+  //  fprintf(stderr,"Max=%f\n",max);
+  points->Allocate((int)max,20);
+  double p[3];
+
+  //  int index=0;
+  for (double k=0;k<this->GridDimensions[2];k+=incr)
+    {
+      p[2]=this->GridOrigin[2]+this->GridSpacing[2]*(k);
+      for (double j=0;j<this->GridDimensions[1];j+=incr)
+	{
+	  p[1]=this->GridOrigin[1]+this->GridSpacing[1]*(j);
+	  for (double i=0;i<this->GridDimensions[0];i+=incr)
+	    {
+	      p[0]=this->GridOrigin[0]+this->GridSpacing[0]*(i);
+	      points->InsertNextPoint(p);
+	      //	      if (index==50)
+		//		fprintf(stderr,"Point index=%d x= %f,%f,%f \n",index,p[0],p[1],p[2]);
+	      //	      ++index;
+	    }
+	}
+    }
+
+}
+//-------------------------------------------------------------------------
+void vtkpxGridTransform::FillMatrices(vtkAbstractTransform* tr,vtkpxMatrix* A,vtkpxMatrix* BB)
+{
+  int nc=this->NumberOfControlPoints;
+  vtkPoints* points=vtkPoints::New();
+  points->SetNumberOfPoints(nc);
+  A->Zeros(nc,nc);
+  BB->Zeros(nc,3);
+  double x[3],tx[3];
+  tr->Update();
+  for (int index=0;index<nc;index++)
+    {
+      this->GetControlPointLocation(index,x);
+      points->SetPoint(index,(double*)x);
+      tr->InternalTransformPoint((double*)x,tx);
+      for (int ib=0;ib<=2;ib++)
+	tx[ib]-=x[ib];
+      BB->SetRow(index,3,(double*)tx);
+    }
+
+  this->FormWeightMatrix(points,A);
+  points->Delete();
+}
+//-------------------------------------------------------------------------
+double vtkpxGridTransform::TestApproximation(vtkAbstractTransform* tr,vtkPoints* points)
+{
+  double error=0.0;
+  int nc=points->GetNumberOfPoints();
+  if (nc<1)
+    return -1.0;
+
+  tr->Update();
+  this->Update();
+
+  double x[3],t1[3],t2[3];
+  for (int i=0;i<nc;i++)
+    {
+      points->GetPoint(i,x);
+      tr->InternalTransformPoint(x,t1);
+      this->InternalTransformPoint(x,t2);
+      error+=sqrt(vtkMath::Distance2BetweenPoints(t1,t2));
+    }
+
+  return error/double(nc);
+}
+//-------------------------------------------------------------------------
+double vtkpxGridTransform::TestInverseApproximation(vtkAbstractTransform* tr,vtkPoints* points)
+{
+  double error=0.0;
+  int nc=points->GetNumberOfPoints();
+  if (nc<1)
+    return -1.0;
+
+  tr->Update();
+  this->Update();
+
+  double x[3],t1[3],t2[3];
+  for (int i=0;i<nc;i++)
+    {
+      points->GetPoint(i,x);
+      tr->InternalTransformPoint(x,t1);
+      this->InternalTransformPoint(t1,t2);
+      double d=sqrt(vtkMath::Distance2BetweenPoints(x,t2));
+      /*fprintf(stderr,
+	      "i=%d\t x=(%5.2f %5.2f %5.2f) -->\t t1=(%5.2f %5.2f %5.2f) -->\t (%5.2f %5.2f %5.2f) \t dist=%5.2f\n",
+	      i,x[0],x[1],x[2],t1[0],t1[1],t1[2],t2[0],t2[1],t2[2],d);*/
+      error+=d;
+    }
+  return error/double(nc);
+}
+
+//-------------------------------------------------------------------------
+double vtkpxGridTransform::TestApproximation(vtkPoints* points,vtkPoints* points2)
+{
+  double error=0.0;
+  int nc=points->GetNumberOfPoints();
+  
+  if (nc<1)
+    return -1.0;
+
+  this->Update();
+
+  double x[3],tx[3],x2[3];
+  for (int i=0;i<nc;i++)
+    {
+      points->GetPoint(i,x);
+      points2->GetPoint(i,tx);
+      this->InternalTransformPoint(x,x2);
+      error+=sqrt(vtkMath::Distance2BetweenPoints(x2,tx));
+    }
+  return error/double(nc);
+}
+//-------------------------------------------------------------------------
+double vtkpxGridTransform::TestWeightedApproximation(vtkPoints* points,vtkPoints* points2,
+						     vtkpxMatrix* lsqweights,
+						     double& sum2error)
+{
+  double error=0.0;
+  sum2error=0.0;
+  int nc=points->GetNumberOfPoints();
+  
+  int useweights=0;
+  if (lsqweights!=NULL)
+    {
+      if (lsqweights->GetSize()[0]>=points->GetNumberOfPoints())
+	useweights=1;
+    }
+
+
+  if (nc<1)
+    {
+      fprintf(stderr,"*** nc<1");
+      return 0.0;
+    }
+
+  this->Update();
+  double x[3],x2[3],tx[3];
+  for (int i=0;i<nc;i++)
+    {
+      points->GetPoint(i,x);
+      points2->GetPoint(i,tx);
+      this->InternalTransformPoint(x,x2);
+      //this->TransformPoint(x,x2);
+      // This is the key **** point **********
+      double d=vtkMath::Distance2BetweenPoints(x2,tx);
+      if (isinf(d))
+	{
+	  fprintf(stderr,"-- i=%d %.2f %.2f %.2f,  %.2f %.2f %.2f\n",i,
+		  x[0],x[1],x[2],
+		  x2[0],x2[1],x2[2]);
+	  d=0.0;
+	}
+      double w=1.0;
+      if (useweights)
+	{
+	  w=lsqweights->GetDirectElement(i,0);
+	  if (isinf(w))
+	    {
+	      w=1.0;
+	      fprintf(stderr,"Weight=inf i=%d\n",i);
+	    }
+	}
+      error+=w*sqrt(d);
+      sum2error+=w*d;
+    }
+  sum2error/=double(nc);
+  return error/double(nc);
+}
+//-------------------------------------------------------------------------
+int vtkpxGridTransform::ApproximateTransformation(vtkAbstractTransform* tr)
+{
+  return this->ApproximateTransformation(tr,0.05,20,1,0.0005,0.0);
+}
+
+int vtkpxGridTransform::ApproximateTransformation(vtkAbstractTransform* tr,
+						  double step,
+						  int numiter,
+						  int numlevels,double threshold,double lambda)
+{
+  this->InitialApproximateTransformation(tr);
+
+  if (tr->IsA("vtkLinearTransform")==1)
+    return 1;
+    
+  //  timer->StartTimer();
+  vtkCollection* collection=vtkCollection::New();
+  vtkPoints* points=vtkPoints::New();
+  this->GenerateTestPoints(points,0.5);
+  
+  int np=points->GetNumberOfPoints();
+
+
+
+  vtkPoints* points2=vtkPoints::New();
+  points2->SetNumberOfPoints(np);
+  tr->Update();
+  for (int ia=0;ia<np;ia++)
+    {
+      double x[3],tx[3];
+      points->GetPoint(ia,x);
+      tr->InternalTransformPoint(x,tx);
+      points2->SetPoint(ia,tx);
+    }
+  fprintf(stderr,"\t GridTransform::Approximate  Transform %d points (error=%.4f)\n",np  , this->TestApproximation(points,points2));
+  this->FormCollectionStructure(points,collection,0.01);
+
+  vtkTimerLog* timer=vtkTimerLog::New();
+  timer->StartTimer();
+  this->ApproximatePoints(points,points2,collection,step,numiter,numlevels,threshold,lambda,0);
+  timer->StopTimer();  fprintf(stderr,"\t GridTransform::Approximate  Finished Approximation %d TestPoints = %.5fs\n",np,timer->GetElapsedTime());
+  points->Delete();
+  points2->Delete();
+  collection->Delete();
+  timer->Delete();
+  return 1;
+}
+//------------------------------------------------------------------------- 
+// Compute Approximation to Set of Displacements
+//-------------------------------------------------------------------------
+double vtkpxGridTransform::ErrorAtControlPoint(int cp,vtkPoints* points,vtkPoints* points2,
+					      vtkDoubleArray* indices,double lambda,vtkpxMatrix* lsqweight,
+					      vtkpxGridTransform* priorTransform,vtkDoubleArray* priorWeights)
+{
+  int np=indices->GetNumberOfTuples();
+  double nump=double(points->GetNumberOfPoints());
+  double x[3],tx[3],sum=0.0;
+  this->Update();
+  if (np>0)
+    {
+      for (int ki=0;ki<np;ki++)
+	{
+	  int i=(int)indices->GetComponent(ki,0);
+	  double w=indices->GetComponent(ki,1);
+	  points->GetPoint(i,x);
+	  points2->GetPoint(i,tx);
+	  this->InternalTransformPoint(x,x);
+	  double dist= (vtkMath::Distance2BetweenPoints(x, tx));
+
+	  double w2=1.0;
+	  if (lsqweight!=NULL)
+	    w2=lsqweight->GetDirectElement(i,0);
+	  sum+=w*w2*dist;
+	}
+    }
+
+  if (priorTransform==NULL)
+    return (sum/nump)+lambda*this->ComputeBendingEnergyAroundControlPoint(cp);
+
+  return (sum/nump)+lambda*this->ComputeWeightedDistance(OptimizationStructure.priorTransform,cp,OptimizationStructure.priorWeights);
+}
+//------------------------------------------------------------------------- 
+double vtkpxGridTransform::GradientAtControlPoint(int cp,double grad[3],
+						 vtkPoints* points,vtkPoints* points2,
+						 vtkDoubleArray* indices,double step,
+						 double lambda,vtkpxMatrix* lsqweight,
+						 vtkpxGridTransform* priorTransform,
+						 vtkDoubleArray* priorWeights)
+{
+  for (int dim=0;dim<=2;dim++)
+    {
+      grad[dim]=0.0;
+      this->ShiftControlPoint(cp,dim,-step);
+      double s1 = this->ErrorAtControlPoint(cp,points,points2,indices,lambda,lsqweight,priorTransform,priorWeights);
+      this->ShiftControlPoint(cp,dim,+2.0*step);
+      double s2 = this->ErrorAtControlPoint(cp,points,points2,indices,lambda,lsqweight,priorTransform,priorWeights);
+      this->ShiftControlPoint(cp,dim,-step);
+      double s0=this->ErrorAtControlPoint(cp,points,points2,indices,lambda,lsqweight,priorTransform,priorWeights);
+
+      /*if (cp==99)
+	fprintf(stderr,"s0=%.5f s1=%.5f s2=%.5f dim=%d\n",s0,s1,s2,dim);*/
+
+      if (s0 < s1 && s0 < s2)
+	{
+	  grad[dim]=0.0;
+	}
+      else 
+	{
+	  grad[dim]=s2-s1;
+	}
+    }
+
+  return ( pow(grad[0],2.0)+pow(grad[1],2.0)+pow(grad[2],2.0));
+}
+
+
+// ---------------------------------------------------------------------------------------
+// Key Procedures for approximation of points via optimization
+// ---------------------------------------------------------------------------------------
+void vtkpxGridTransform::ShiftControlPoints(vtkDoubleArray* grad,double step)
+{
+  int nc=this->NumberOfControlPoints;
+  for (int j=0;j<=2;j++)
+    for (int i = 0; i < nc; i++)
+      this->ShiftControlPoint(i,j,step*grad->GetComponent(i,j));
+}
+// ---------------------------------------------------------------------------------------
+void vtkpxGridTransform::ScaleGradients(vtkDoubleArray* grad,double scale)
+{
+  int nt=grad->GetNumberOfTuples();
+  int nc=grad->GetNumberOfComponents();
+  for (int t=0;t<nt;t++)
+    for (int c=0;c<nc;c++)
+      grad->SetComponent(t,c,grad->GetComponent(t,c) * scale);
+
+}
+// ---------------------------------------------------------------------------------------
+void vtkpxGridTransform::InitializeApproximatePoints(vtkPoints* points,
+						     vtkPoints* points2,
+						     vtkpxMatrix* weights)
+
+{
+  vtkpxWeightedLandmarkTransform* tr=vtkpxWeightedLandmarkTransform::New();
+  tr->SetSourceLandmarks(points);
+  tr->SetTargetLandmarks(points2);
+  tr->SetWeights(weights);
+  tr->SetModeToAffine();
+  tr->Modified();
+  tr->Update();
+
+  this->InitialApproximateTransformation(tr);
+  double e=this->TestApproximation(points,points2);
+  OptimizationStructure.bend=0.0;
+  OptimizationStructure.error=0.0;
+  vtkpxGridTransform::OptimizerFeedback(this,"Initial Approximation Error ",e);
+  tr->Delete();
+}
+// ---------------------------------------------------------------------------------------
+void vtkpxGridTransform::ApproximatePoints(vtkPoints* points,
+					   vtkPoints* points2,
+					   vtkCollection* ControlsCollection,
+					   double step,
+					   int numiter,int numlevels,
+					   double in_threshold,
+					   double lambda,int initialize,
+					   vtkpxMatrix* controlweights,
+					   vtkpxGridTransform* priorTransform0,
+					   vtkDoubleArray* priorWeights0)
+{
+  // Test for Parameters
+  // --------------------
+
+  if (ControlsCollection==NULL || points2==NULL)
+    {
+      vtkErrorMacro(<<"Collection or Points = NULL");
+      return;
+    }
+
+  int nc=this->NumberOfControlPoints;
+  if (ControlsCollection->GetNumberOfItems()!=nc)
+    {
+      vtkErrorMacro(<<"Bad Controls Collection\n");
+      return ;
+    }
+
+
+  // Initial Step
+  // -------------
+
+  if (initialize)
+    {
+      vtkDebugMacro(<<"Step 1  Optimization\n");
+      this->InitializeApproximatePoints(points,points2,controlweights);
+      if (numlevels==0)
+	{
+	  vtkDebugMacro(<<"No Further Optimization\n");
+	  return;
+	}
+    }
+
+  vtkpxOptimizer* optimizer=vtkpxOptimizer::New();
+  vtkDoubleArray* position=vtkDoubleArray::New();
+  vtkDoubleArray* temp=vtkDoubleArray::New();
+  
+  this->GetCurrentParameters(position);
+  optimizer->SetMasterObject(this);
+  optimizer->SetEvaluateFunctionMethod(&vtkpxGridTransform::CalculateFunction);
+  optimizer->SetEvaluateGradientMethod(&vtkpxGridTransform::CalculateGradient);
+  optimizer->SetFeedbackMethod(&vtkpxGridTransform::OptimizerFeedback);
+  
+  double v=0.0;
+  numlevels=Irange(numlevels,1,3);
+
+  vtkpxGridTransform* priorTransform=priorTransform0;
+  vtkDoubleArray* priorWeights=priorWeights0;
+
+  // Make Sure that all is fine before using prior Stuff 
+  if (priorTransform!=NULL)
+    {
+      int np=this->GetNumberOfControlPoints();
+      int np1=priorTransform->GetNumberOfControlPoints();
+      if (np!=np1)
+	{
+	  priorTransform=NULL;
+	}
+      else
+	{
+	  if (priorWeights!=NULL)
+	    {
+	      int np2=priorWeights->GetNumberOfTuples();
+	      if (np!=np2)
+		priorWeights=NULL;
+	    }
+	}
+    }
+  else
+    {
+      priorWeights=NULL;
+      priorTransform=NULL;
+    }
+
+  fprintf(stderr,"\n Approximating  %d points lambda=%f step=%.2f\n",points->GetNumberOfPoints(),lambda,step);
+  for (int level=1;level<=numlevels;level++)
+    {
+      this->OptimizationStructure.SetValues(ControlsCollection,points,points2,step,lambda,controlweights,
+					    priorTransform,priorWeights);
+      
+      switch (this->ApproximationMode)
+	{
+	case 1:
+	  v=optimizer->ComputeGradientDescent(position,numiter,0.01*in_threshold);
+	  break;
+	  
+	default:
+	  v=optimizer->ComputeConjugateGradient(position,numiter,0.01*in_threshold);
+	  break;
+	}
+      step*=0.5;
+      in_threshold*=0.5;
+    }
+  optimizer->Delete();
+  position->Delete();
+  temp->Delete();
+  return;
+}
+// ---------------------------------------------------------------------------------------
+void vtkpxGridTransform::CombineWithLinearTransform(vtkLinearTransform* tr,int premultiply)
+{
+  int nc=this->NumberOfControlPoints;
+
+  vtkLinearTransform* inverse=tr->GetLinearInverse();
+  
+
+  double x[3],tx[3],dx[3];
+  for (int cpoint=0;cpoint<nc;cpoint++)
+    {
+      this->GetControlPointLocation(cpoint,x);
+      this->GetControlPointDisplacement(cpoint,dx);
+      
+      if (premultiply)
+	{
+	  inverse->InternalTransformPoint(x,tx);
+	  for (int ia=0;ia<=2;ia++)
+	    dx[ia]+=x[ia]-tx[ia];
+	}
+      else
+	{
+	  for (int ia=0;ia<=2;ia++)
+	    dx[ia]+=x[ia];
+	  tr->InternalTransformPoint(dx,tx);
+	  for (int ib=0;ib<=2;ib++)
+	    dx[ib]=tx[ib]-x[ib];
+	}
+      this->SetControlPointDisplacement(cpoint,dx);
+    }
+}
+
+// -----------------------------------------------------------------------------------------
+//                                     Perform Inversion
+// -----------------------------------------------------------------------------------------
+
+void vtkpxGridTransform::Inverse()
+{
+  if (this->InterpolationMode!=VTK_GRID_BSPLINE)
+    {
+      vtkGridTransform::Inverse();
+      return;
+    }
+
+  this->InverseFlag=0;
+
+  int nc=this->NumberOfControlPoints;
+  if (nc<1)
+    return;
+  
+  vtkPoints* points=vtkPoints::New();
+  vtkPoints* points2=vtkPoints::New();
+
+
+  double factor=2.0;
+  double ffact=1.0/factor;
+
+  double p[3],tp[3];
+  this->Update();
+  for (int k=0;k<this->GridDimensions[2]*factor;k++)
+    {
+      p[2]=this->GridOrigin[2]+this->GridSpacing[2]*double(k)*ffact;
+      for (int j=0;j<this->GridDimensions[1]*factor;j++)
+	{
+	  p[1]=this->GridOrigin[1]+this->GridSpacing[1]*double(j*ffact);
+	  for (int i=0;i<this->GridDimensions[0]*factor;i++)
+	    {
+	      p[0]=this->GridOrigin[0]+this->GridSpacing[0]*double(i*ffact);
+	      this->InternalTransformPoint(p,tp);
+	      points->InsertNextPoint(tp);
+	      points2->InsertNextPoint(p);
+	    }
+	}
+    }
+
+  double bounds[6];
+  points->GetBounds(bounds);
+
+  double newsp[3];
+  double offset=0.05;
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      double d=bounds[2*ia+1]-bounds[2*ia];
+      double w=(1.0+2.0*offset)*d;
+      bounds[2*ia]=bounds[2*ia]-offset*d;
+      bounds[2*ia+1]=bounds[2*ia]+w;
+      newsp[ia]=0.667*this->GridSpacing[ia];
+    }
+
+
+  fprintf(stderr,"#Original\n");
+  fprintf(stderr,"#Origin\n %.4f %.4f %.4f\n",this->GridOrigin[0],this->GridOrigin[1],this->GridOrigin[2]);
+  fprintf(stderr,"#Spacing\n %.4f %.4f %.4f\n",this->GridSpacing[0],this->GridSpacing[1],this->GridSpacing[2]);
+  fprintf(stderr,"#Dimensions\n %d %d %d\n",this->GridDimensions[0],this->GridDimensions[1],this->GridDimensions[2]);
+
+
+  this->InitializeDisplacementGrid(bounds,newsp[0],newsp[1],newsp[2]);
+
+  
+  fprintf(stderr,"#Inverse\n");
+  fprintf(stderr,"#Origin\n %.4f %.4f %.4f\n",this->GridOrigin[0],this->GridOrigin[1],this->GridOrigin[2]);
+  fprintf(stderr,"#Spacing\n %.4f %.4f %.4f\n",this->GridSpacing[0],this->GridSpacing[1],this->GridSpacing[2]);
+  fprintf(stderr,"#Dimensions\n %d %d %d\n",this->GridDimensions[0],this->GridDimensions[1],this->GridDimensions[2]);
+
+
+  vtkCollection* collection=vtkCollection::New();
+  this->FormCollectionStructure(points,collection,0.01);
+  this->ApproximatePoints(points,points2,
+			  collection,
+			  this->InverseTolerance*2,
+			  this->InverseIterations,
+			  3,
+			  this->InverseTolerance,
+			  0.0,1);
+  
+
+  points->Delete();
+  points2->Delete();
+}
+
+// -----------------------------------------------------------------------------------------
+// New Stuff for Optimization
+// -----------------------------------------------------------------------------------------
+double vtkpxGridTransform::CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output)
+{
+  return ((vtkpxGridTransform*)self)->OptimizerGradient(position,output);
+}
+
+double vtkpxGridTransform::CalculateFunction(vtkObject* self,vtkDoubleArray* position)
+{
+  return ((vtkpxGridTransform*)self)->OptimizerValue(position);
+}
+
+void vtkpxGridTransform::OptimizerFeedback(vtkObject* slf,const char* line,double val)
+{
+  vtkpxGridTransform* self=(vtkpxGridTransform*)slf;
+  fprintf(stderr,"%s (%.5f) [ dist=%.5f tbend=%.5f]\n",line,val,
+	  self->OptimizationStructure.error,
+	  self->OptimizationStructure.bend);
+}
+// -----------------------------------------------------------------------------------------
+// Get/Set Parameters, also used by NonLinearRegistration 
+// -----------------------------------------------------------------------------------------
+void  vtkpxGridTransform::SetCurrentParameters(vtkDoubleArray* param)
+{
+  int numt=this->GetNumberOfControlPoints();
+  int numc=3;
+  int num=param->GetNumberOfTuples();
+
+  if (num!=numt*numc)
+    {
+      vtkErrorMacro(<<"Bad Data for Optimization");
+      return;
+    }
+
+  int index=0;
+
+  for (int i=0;i<numt;i++)
+    {
+      double p[3];
+      for (int j=0;j<numc;j++)
+	{
+	  p[j]=param->GetComponent(index,0);
+	  ++index;
+	}
+      
+      this->SetControlPointDisplacement(i,p);
+    }
+}
+
+
+void  vtkpxGridTransform::GetCurrentParameters(vtkDoubleArray* param)
+{
+  int numt=this->GetNumberOfControlPoints();
+  int numc=3;
+  int num=numt*numc;
+  
+  if (param->GetNumberOfComponents()!=1 || param->GetNumberOfTuples()!=num)
+    {
+      param->SetNumberOfComponents(1);
+      param->SetNumberOfTuples(num);
+    }
+
+
+  int index=0;
+  for (int i=0;i<numt;i++)
+    {
+      double p[3];
+      this->GetControlPointDisplacement(i,p);
+      for (int j=0;j<=2;j++)
+	{
+	  param->SetComponent(index,0,p[j]);
+	  ++index;
+	}
+    }
+}
+// -----------------------------------------------------------------------------------------
+// Gradient and Value Stuff 
+// -----------------------------------------------------------------------------------------
+double vtkpxGridTransform::OptimizerValue(vtkDoubleArray* params)
+{
+  this->SetCurrentParameters(params);
+  double sqerr=0.0;
+  this->OptimizationStructure.error=this->TestWeightedApproximation(this->OptimizationStructure.points,
+								    this->OptimizationStructure.points2,
+								    OptimizationStructure.weights,
+								    sqerr);
+  
+  this->OptimizationStructure.bend =0.0;
+  OptimizationStructure.ControlsCollection->InitTraversal();
+  int nc=this->NumberOfControlPoints;
+
+  
+  if (OptimizationStructure.priorTransform==NULL)
+    {
+      double sum=0.0;
+      for (int cpoint=0;cpoint<nc;cpoint++)
+	sum+=this->ComputeBendingEnergyAtControlPoint(cpoint);
+      OptimizationStructure.bend=sum;
+    }
+  else
+    {
+      fprintf(stderr,"+");
+      OptimizationStructure.bend=this->ComputeWeightedDistance(OptimizationStructure.priorTransform,-1,OptimizationStructure.priorWeights);
+    }
+     
+  /*  fprintf(stderr,"Optimizer Value: error=%.2f\t sqerror=%.2f\t bend=%.2f\t total=%.2f\n",
+	  this->OptimizationStructure.error,
+	  sqerr,
+	  OptimizationStructure.bend,
+	  sqerr+OptimizationStructure.bend*OptimizationStructure.lambda);*/
+  
+  return sqerr+OptimizationStructure.bend*OptimizationStructure.lambda;
+}
+// -----------------------------------------------------------------------------------------
+double vtkpxGridTransform::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+{
+  if (grad->GetNumberOfComponents()!=1 || grad->GetNumberOfTuples()!=this->NumberOfControlPoints*3)
+    {
+      grad->SetNumberOfComponents(1);
+      grad->SetNumberOfTuples(this->NumberOfControlPoints*3);
+    }
+
+  this->SetCurrentParameters(params);
+
+  double sum=0.0;
+  OptimizationStructure.ControlsCollection->InitTraversal();
+  int nc=this->NumberOfControlPoints;
+  double g[3];
+
+
+
+  for (int cpoint=0;cpoint<nc;cpoint++)
+    {      
+      vtkDoubleArray* indices=(vtkDoubleArray*)OptimizationStructure.ControlsCollection->GetNextItemAsObject();
+      
+      double v=this->GradientAtControlPoint(cpoint,g,
+					   OptimizationStructure.points,
+					   OptimizationStructure.points2,
+					   indices,
+					   OptimizationStructure.step,
+					   OptimizationStructure.lambda,
+					   OptimizationStructure.weights,
+					   OptimizationStructure.priorTransform,
+					   OptimizationStructure.priorWeights);
+
+      sum+=v;
+      grad->SetComponent(cpoint*3,0,g[0]);
+      grad->SetComponent(cpoint*3+1,0,g[1]);
+      grad->SetComponent(cpoint*3+2,0,g[2]);
+    }
+	  
+  sum=sqrt(sum);
+
+  if (sum>0.0)
+    {
+      double scale=OptimizationStructure.step/sum;
+      //      fprintf(stderr,"\tGradient Norm=%f scale=%.5f\n",sum,scale);
+      this->ScaleGradients(grad,scale);
+    }
+  return sum;
+}
+
+// -----------------------------------------------------------------------------------------
+void vtkpxGridTransform::InitializeDisplacementGrid(vtkpxGridTransform* other)
+{
+  vtkImageData* oldgrid=other->GetDisplacementGrid();
+  vtkImageData *grid = vtkImageData::New();
+  grid->SetScalarType(VTK_DOUBLE);
+  grid->SetNumberOfScalarComponents(3);
+  grid->SetSpacing(oldgrid->GetSpacing());
+  grid->SetOrigin(oldgrid->GetOrigin());
+  grid->SetExtent(oldgrid->GetExtent());
+
+  grid->SetUpdateExtent(grid->GetWholeExtent());
+  grid->AllocateScalars();
+  for (int i=0;i<=2;i++)
+    grid->GetPointData()->GetScalars()->FillComponent(i,0.0);
+  this->SetDisplacementGrid(grid);
+}
+// -----------------------------------------------------------------------------------------
+void vtkpxGridTransform::InverseApproximateTransformation(vtkpxGridTransform* output,int initialize)
+{
+  if (initialize)
+    output->InitializeDisplacementGrid(this);
+
+  vtkCollection* collection=vtkCollection::New();
+  vtkPoints* points=vtkPoints::New();
+
+  output->GenerateTestPoints(points,0.5);
+  int np=points->GetNumberOfPoints();
+
+  vtkPoints* points2=vtkPoints::New();
+  points2->SetNumberOfPoints(np);
+
+  for (int ia=0;ia<np;ia++)
+    {
+      double x[3],tx[3];
+      points->GetPoint(ia,x);
+      this->InverseTransformPoint(x,tx);
+      points2->SetPoint(ia,tx);
+    }
+
+
+  output->FormCollectionStructure(points,collection,0.01);
+  output->ApproximatePoints(points,points2,collection,
+			    this->InverseTolerance*2,
+			    this->InverseIterations,
+			    3,
+			    this->InverseTolerance,
+			    0.0,1);
+  points->Delete();
+  points2->Delete();
+  collection->Delete();
+  return;
+}
+
+
+// -----------------------------------------------------------------------------------------
+double vtkpxGridTransform::ComputeTotalBendingEnergy()
+{
+  double sum=0.0;
+  int nc=this->NumberOfControlPoints;
+  if (nc==0)
+    return 0.0;
+
+  for (int i=0;i<nc;i++)
+    sum+=this->ComputeBendingEnergyAtControlPoint(i);
+
+
+  return sum;
+}
+// ---------------------------------------------------------------------------------------
+double vtkpxGridTransform::ComputeBendingEnergyAroundControlPoint(int cpoint)
+{
+  int ind[3];
+  this->GetControlPointIndices(cpoint,ind);
+
+  int ip=ind[0]+1; if (ip>=this->GridDimensions[0]-1) ip=this->GridDimensions[0]-1;
+  int jp=ind[1]+1; if (jp>=this->GridDimensions[1]-1) jp=this->GridDimensions[1]-1;
+  int kp=ind[2]+1; if (kp>=this->GridDimensions[2]-1) kp=this->GridDimensions[2]-1;
+
+  int im=ind[0]-1; if (im<0) im=0;
+  int jm=ind[1]-1; if (jm<0) jm=0;
+  int km=ind[2]-1; if (km<0) km=0;
+
+  double sum=0.0;
+  for (int i=im;i<=ip;i++)
+    for (int j=jm;j<=jp;j++)
+      for (int k=km;k<=kp;k++)
+	sum+=this->ComputeBendingEnergyAtControlPoint(i,j,k);
+
+  return sum;
+}
+
+double vtkpxGridTransform::ComputeBendingEnergyAtControlPoint(int cpoint)
+{
+  int ind[3];  this->GetControlPointIndices(cpoint,ind);
+  return this->ComputeBendingEnergyAtControlPoint(ind[0],ind[1],ind[2]);
+}
+
+
+double vtkpxGridTransform::ComputeBendingEnergyAtControlPoint(int i,int j,int k)
+{
+  vtkImageData *grid=this->DisplacementGrid;
+  double *gridPtr1,*gridPtr2,*gridPtr4,*gridPtr3;
+
+  //double sp=(this->GridSpacing[0]+this->GridSpacing[1]+this->GridSpacing[2])/3.0;
+  double scale=0.01*(1.0/(double(this->NumberOfControlPoints)));
+  
+  double sum=0.0;
+
+  int ip=i+1; if (ip>=this->GridDimensions[0]-1) ip=this->GridDimensions[0]-1;
+  int jp=j+1; if (jp>=this->GridDimensions[1]-1) jp=this->GridDimensions[1]-1;
+  int kp=k+1; if (kp>=this->GridDimensions[2]-1) kp=this->GridDimensions[2]-1;
+
+  int im=i-1; if (im<0) im=0;
+  int jm=j-1; if (jm<0) jm=0;
+  int km=k-1; if (km<0) km=0;
+
+
+  gridPtr1 = (double *)grid->GetScalarPointer(ip,j,k);
+  gridPtr2 = (double *)grid->GetScalarPointer(i,j,k);
+  gridPtr3 = (double *)grid->GetScalarPointer(im,j,k);
+  sum += pow(*(gridPtr1)  - 2 * *(gridPtr2)   + *(gridPtr3)   , 2.0);
+  sum += pow(*(gridPtr1+1)- 2 * *(gridPtr2+1) + *(gridPtr3+1) , 2.0);
+  sum += pow(*(gridPtr1+2)- 2 * *(gridPtr2+2) + *(gridPtr3+2) , 2.0);
+  
+  gridPtr1 = (double *)grid->GetScalarPointer(i,jp,k);
+  gridPtr2 = (double *)grid->GetScalarPointer(i,j,k);
+  gridPtr3 = (double *)grid->GetScalarPointer(i,jm,k);
+  sum += pow(*(gridPtr1)  - 2 * *(gridPtr2)   + *(gridPtr3)   , 2.0);
+  sum += pow(*(gridPtr1+1)- 2 * *(gridPtr2+1) + *(gridPtr3+1) , 2.0);
+  sum += pow(*(gridPtr1+2)- 2 * *(gridPtr2+2) + *(gridPtr3+2) , 2.0);
+  
+  gridPtr1 = (double *)grid->GetScalarPointer(i,j,kp);
+  gridPtr2 = (double *)grid->GetScalarPointer(i,j,k);
+  gridPtr3 = (double *)grid->GetScalarPointer(i,j,km);
+  sum += pow(*(gridPtr1)  - 2 * *(gridPtr2)   + *(gridPtr3)   , 2.0);
+  sum += pow(*(gridPtr1+1)- 2 * *(gridPtr2+1) + *(gridPtr3+1) , 2.0);
+  sum += pow(*(gridPtr1+2)- 2 * *(gridPtr2+2) + *(gridPtr3+2) , 2.0);
+  
+  gridPtr1 = (double *)grid->GetScalarPointer(ip,jp,k);
+  gridPtr2 = (double *)grid->GetScalarPointer(im,jp,k);
+  gridPtr3 = (double *)grid->GetScalarPointer(ip,jm,k);
+  gridPtr4 = (double *)grid->GetScalarPointer(im,jm,k);
+  sum += pow((*(gridPtr1  )-*(gridPtr2  )-*(gridPtr3  )+*(gridPtr4  ))/4.0, 2.0)*2;
+  sum += pow((*(gridPtr1+1)-*(gridPtr2+1)-*(gridPtr3+1)+*(gridPtr4+1))/4.0, 2.0)*2;
+  sum += pow((*(gridPtr1+2)-*(gridPtr2+2)-*(gridPtr3+2)+*(gridPtr4+2))/4.0, 2.0)*2;
+  
+  gridPtr1 = (double *)grid->GetScalarPointer(ip,j,kp);
+  gridPtr2 = (double *)grid->GetScalarPointer(im,j,kp);
+  gridPtr3 = (double *)grid->GetScalarPointer(ip,j,km);
+  gridPtr4 = (double *)grid->GetScalarPointer(im,j,km);
+  sum += pow((*(gridPtr1  )-*(gridPtr2  )-*(gridPtr3  )+*(gridPtr4  ))/4.0, 2.0)*2;
+  sum += pow((*(gridPtr1+1)-*(gridPtr2+1)-*(gridPtr3+1)+*(gridPtr4+1))/4.0, 2.0)*2;
+  sum += pow((*(gridPtr1+2)-*(gridPtr2+2)-*(gridPtr3+2)+*(gridPtr4+2))/4.0, 2.0)*2;
+  
+  gridPtr1 = (double *)grid->GetScalarPointer(i,jp,kp);
+  gridPtr2 = (double *)grid->GetScalarPointer(i,jm,kp);
+  gridPtr3 = (double *)grid->GetScalarPointer(i,jp,km);
+  gridPtr4 = (double *)grid->GetScalarPointer(i,jm,km);
+  sum += pow((*(gridPtr1  )-*(gridPtr2  )-*(gridPtr3  )+*(gridPtr4  ))/4.0, 2.0)*2;
+  sum += pow((*(gridPtr1+1)-*(gridPtr2+1)-*(gridPtr3+1)+*(gridPtr4+1))/4.0, 2.0)*2;
+  sum += pow((*(gridPtr1+2)-*(gridPtr2+2)-*(gridPtr3+2)+*(gridPtr4+2))/4.0, 2.0)*2;
+  
+  return (sum)*scale;
+
+}
+//-------------------------------------------------------------------------
+double vtkpxGridTransform::ComputeJacobianConstraint(float gamma)
+{
+
+  fprintf(stdout,"\n\n\n\n-------------------------\n\n\n\nDoing jacobian constraint\n\n\n\n-------------------------\n\n\n\n");
+	double sum=0.0;
+	int nc=this->NumberOfControlPoints;
+	if (nc==0)
+		return 0.0;
+
+	for (int i=0;i<nc;i++)
+	{
+		int ind[3];
+		float p[3],p2[3],der[3][3];
+		this->GetControlPointIndices(i,ind);
+		p[0]=ind[0];p[1]=ind[1];p[2]=ind[2];
+		this->InternalTransformDerivative(p,p2,der);
+
+		double v1=vtkMath::Determinant3x3(der);
+
+		if ( v1<=gamma )
+			sum+=(gamma*gamma)/(v1*v1)-2;
+		else
+			sum+=0.0;
+	}
+	return sum;
+}
+// ---------------------------------------------------------------------------------------
+double vtkpxGridTransform::ComputeTotalStrainEnergy(double v)
+{
+  double sum=0.0;
+  int nc=this->NumberOfControlPoints;
+  if (nc==0)
+    return 0.0;
+
+  for (int i=0;i<nc;i++)
+    sum+=this->ComputeStrainEnergyAtControlPoint(i,v);
+  return sum;
+
+}
+// ---------------------------------------------------------------------------------------
+double vtkpxGridTransform::ComputeStrainEnergyAtControlPoint(int cpoint,double v)
+{
+  /*  double p1[3];
+      this->GetControlPointLocation(cpoint,p1);
+      return this->ComputeStrainEnergyAtPoint(p1,v);*/
+
+  int ind[3];  this->GetControlPointIndices(cpoint,ind);
+  vtkImageData *grid=this->DisplacementGrid;
+  double *gridPtr1,*gridPtr2,*gridPtr3;
+
+  //double sp=(this->GridSpacing[0]+this->GridSpacing[1]+this->GridSpacing[2])/3.0;
+  double scale=0.01*(1.0/(double(this->NumberOfControlPoints)));
+
+  int i=ind[0];
+  int j=ind[1];
+  int k=ind[2];
+  
+
+  int ip=i+1; if (ip>=this->GridDimensions[0]-1) ip=this->GridDimensions[0]-2;
+  int jp=j+1; if (jp>=this->GridDimensions[1]-1) jp=this->GridDimensions[1]-2;
+  int kp=k+1; if (kp>=this->GridDimensions[2]-1) kp=this->GridDimensions[2]-2;
+  
+  int im=i-1; if (im<1) im=1;
+  int jm=j-1; if (jm<1) jm=1;
+  int km=k-1; if (km<1) km=1;
+
+  double det[3][3];
+  
+  gridPtr1 = (double *)grid->GetScalarPointer(ip,j,k);
+  gridPtr2 = (double *)grid->GetScalarPointer(i,j,k);
+  gridPtr3 = (double *)grid->GetScalarPointer(im,j,k);
+   
+  // du/dx
+  det[0][0]= *(gridPtr1)  - 2 * *(gridPtr2)   + *(gridPtr3);
+  // dv/dx
+  det[1][0]= *(gridPtr1+1)- 2 * *(gridPtr2+1) + *(gridPtr3+1);
+  // dw/dx
+  det[2][0]= *(gridPtr1+2)- 2 * *(gridPtr2+2) + *(gridPtr3+2);
+  
+  
+  gridPtr1 = (double *)grid->GetScalarPointer(i,jp,k);
+  gridPtr2 = (double *)grid->GetScalarPointer(i,j,k);
+  gridPtr3 = (double *)grid->GetScalarPointer(i,jm,k);
+  
+  // du/dy
+  det[0][1]= *(gridPtr1)  - 2 * *(gridPtr2)   + *(gridPtr3)  ;
+  // dv/dy
+  det[1][1]= *(gridPtr1+1)- 2 * *(gridPtr2+1) + *(gridPtr3+1);
+  // dw/dy
+  det[2][1]= *(gridPtr1+2)- 2 * *(gridPtr2+2) + *(gridPtr3+2);
+  
+  
+  gridPtr1 = (double *)grid->GetScalarPointer(i,j,kp);
+  gridPtr2 = (double *)grid->GetScalarPointer(i,j,k);
+  gridPtr3 = (double *)grid->GetScalarPointer(i,j,km);
+  
+  // du/dz
+  det[0][2]= *(gridPtr1)  - 2 * *(gridPtr2)   + *(gridPtr3)  ;
+  // dv/dz
+  det[1][2]= *(gridPtr1+1)- 2 * *(gridPtr2+1) + *(gridPtr3+1);
+  // dw/dz
+  det[2][2]= *(gridPtr1+2)- 2 * *(gridPtr2+2) + *(gridPtr3+2);
+  
+  
+  double shear[3];
+  shear[0]=0.5*(det[0][1]+det[1][0]);
+  shear[1]=0.5*(det[0][2]+det[2][0]);
+  shear[2]=0.5*(det[1][2]+det[2][1]);
+  
+  double sum=0.0;
+  sum+= det[0][0]*((1.0-v)*det[0][0]+v*(det[1][1]+det[2][2]));
+  sum+= det[1][1]*((1.0-v)*det[1][1]+v*(det[0][0]+det[2][2]));
+  sum+= det[2][2]*((1.0-v)*det[2][2]+v*(det[0][0]+det[1][1]));
+  for (i=0;i<=2;i++)
+    sum+=(0.5-v)*pow(shear[i],2.0);
+  
+  return scale*sum/( (1.0+v)*(1.0-2.0*v));
+}
+// --------------------------------------------------------------------------------------- 
+double vtkpxGridTransform::ComputeStrainEnergyAtPoint(double p1[3],double v)
+{
+  if (v<0.0)
+    v=0.0;
+  else if (v>=0.5)
+    v=0.49;
+
+  // Linear Elastic Stuff 
+  double det[3][3],p2[3];
+  this->InternalTransformDerivative(p1,p2,det);
+
+  for (int ia=0;ia<=2;ia++)
+    det[ia][ia]-=1.0;
+
+  double shear[3];
+  shear[0]=0.5*(det[0][1]+det[1][0]);
+  shear[1]=0.5*(det[0][2]+det[2][0]);
+  shear[2]=0.5*(det[1][2]+det[2][1]);
+
+  double sum=0.0;
+  sum+= det[0][0]*((1.0-v)*det[0][0]+v*(det[1][1]+det[2][2]));
+  sum+= det[1][1]*((1.0-v)*det[1][1]+v*(det[0][0]+det[2][2]));
+  sum+= det[2][2]*((1.0-v)*det[2][2]+v*(det[0][0]+det[1][1]));
+  for (int i=0;i<=2;i++)
+    sum+=(0.5-v)*pow(shear[i],2.0);
+  
+  return sum/( (1.0+v)*(1.0-2.0*v));
+}
+// ---------------------------------------------------------------------------------------
+double vtkpxGridTransform::ComputeWeightedDistance(vtkpxGridTransform* other,int cpindex,vtkDoubleArray* weights0)
+{
+  if (other==NULL)
+    {
+      vtkErrorMacro(<<"Really Bad Prior\n");
+      return 0;
+    }
+
+  int np=other->GetNumberOfControlPoints();
+  if (np!=this->GetNumberOfControlPoints())
+    {
+      vtkErrorMacro(<<"Bad Prior\n");
+      return 0;
+    }
+  
+  vtkDoubleArray* weights=weights0;
+
+  double weight=1.0;
+  if (weights0!=NULL)
+    {
+      if (weights->GetNumberOfTuples()!=np)
+	weights=NULL;
+    }
+  int mincpindex=0;
+  int maxcpindex=np-1;
+  
+  if (cpindex>=0)
+    {
+      mincpindex=Irange(cpindex,0,maxcpindex);
+      maxcpindex=mincpindex;
+    }
+  
+  double v=0;
+  double scale=1.0/double(np);
+  for (int cp=mincpindex;cp<=maxcpindex;cp++)
+    {
+      double d1[3],d2[3];
+      other->GetControlPointDisplacement(cp,d1);
+      this->GetControlPointDisplacement(cp,d2);
+      double d=(vtkMath::Distance2BetweenPoints(d1,d2));
+      if (weights!=NULL)
+	weight=weights->GetComponent(cp,0);
+      v+=d*weight;
+    }
+  return v*scale;
+}
+// ---------------------------------------------------------------------------------------
+int vtkpxGridTransform::FormOutputWeights(vtkCollection* collection,vtkpxMatrix* PointWeights,vtkDoubleArray* FinalWeights)
+{
+  if (collection==NULL || PointWeights==NULL || FinalWeights==NULL)
+    return 0;
+ 
+  int numc=collection->GetNumberOfItems();
+  if (FinalWeights->GetNumberOfTuples()!=numc)
+    FinalWeights->SetNumberOfTuples(numc);
+
+  collection->InitTraversal();
+  double sum=1.0;
+  for (int p=0;p<=1;p++)
+    {
+      for (int i=0;i<numc;i++)
+	{
+	  if (p==0)
+
+	    {
+	      vtkDoubleArray* indices=(vtkDoubleArray*)collection->GetNextItemAsObject();
+	      int n=indices->GetNumberOfTuples();
+	      double total=0.0;
+	      for (int j=0;j<n;j++)
+		{
+		  int point=(int)indices->GetComponent(j,0);
+		  double wgt=indices->GetComponent(j,1);
+		  double wpt=PointWeights->GetDirectElement(point,0);
+		  total+=wgt*wpt;
+		}
+	      FinalWeights->SetComponent(i,0,total);
+	      sum+=total;
+	    }
+	  else
+	    {
+	      FinalWeights->SetComponent(i,0,FinalWeights->GetComponent(i,0)/sum);
+	    }
+	}
+
+      if(p==0)
+	sum/=double(numc);
+
+    }
+  return 1;
+}
+
+// ---------------------------------------------------------------------------------------
+// Optimization Structure
+// ---------------------------------------------------------------------------------------
+
+vtkpxGridTransformOptimizationStructure::vtkpxGridTransformOptimizationStructure() {
+  this->SetValues(NULL,NULL,NULL,0,1.0,NULL);
+}
+
+void vtkpxGridTransformOptimizationStructure::SetValues(vtkCollection* ControlsCollection0,
+							vtkPoints* points0,
+							vtkPoints* points2_0,
+							double step0,
+							double lambda0,
+							vtkpxMatrix* weights0,		 
+							vtkpxGridTransform* prior0,
+							vtkDoubleArray* priorweights0)
+{
+  this->ControlsCollection=ControlsCollection0;
+  this->points=points0;
+  this->points2=points2_0;
+  this->step=step0;
+  this->lambda=lambda0;
+  this->error=0.0;
+  this->bend=0.0;
+  this->weights=weights0;
+  this->priorTransform=prior0;
+  this->priorWeights=priorweights0;
+}
+
+// ---------------------------------------------------------------------------------------
+int vtkpxGridTransform::SmoothCollection(vtkCollection* TransformationCollection,int periodic,double sigma)
+{
+  if (TransformationCollection==NULL)
+    return 0;
+
+  int nt=  TransformationCollection->GetNumberOfItems();
+  
+  TransformationCollection->InitTraversal();
+  // First Make sure there all vtkpxGridTransforms, then get number of control points ....
+  int numberofcontrolpoints=0;
+
+  double** arr=new double*[nt];
+  int flag=0;
+
+  for (int i=0;i<nt;i++)
+    {
+      vtkObject* tr= TransformationCollection->GetNextItemAsObject();
+      if (tr->IsA("vtkpxGridTransform")==1)
+	{
+	  if (i==0)
+	    {
+	      numberofcontrolpoints=((vtkpxGridTransform*)tr)->GetNumberOfControlPoints();
+	    }
+	  else
+	    {
+	      int nc=((vtkpxGridTransform*)tr)->GetNumberOfControlPoints();
+	      if (numberofcontrolpoints!=nc)
+		{
+		  fprintf(stderr,"Bad Grid Transform nc=%d vs %d\n",nc,numberofcontrolpoints);
+		  flag=1;
+		  i=nt+1;
+		}
+	    }
+	  if (flag==0)
+	    arr[i]=((vtkpxGridTransform*)tr)->GetControlPointPointer(0);
+	}
+    }
+
+  if (flag==0)
+    {
+      delete [] arr;
+      return 0;
+    }
+
+
+  double weights[5] = { 0.05,0.25,0.4,0.25,0.04 };
+  double* values=new double[nt];
+  int    index[5];
+
+  int numberofvalues=numberofcontrolpoints*3;
+  for (int i=0;i<numberofvalues;i++)
+    {
+      // Copy into small array first 
+      for (int j=0;j<nt;j++)
+	values[j]=arr[j][i];
+      
+      for (int j=0;j<nt;j++)
+	{
+	  for (int ia=0;ia<=4;ia++)
+	    {
+	      index[ia]=j+(ia-2);
+	      if (periodic)
+		{
+		  if (index[ia]<0)
+		    index[ia]+=nt;
+		  else if (index[ia]>=nt)
+		    index[ia]-=nt;
+		}
+	      if (index[ia]<0)
+		index[ia]=0;
+	      else if (index[ia]>=nt)
+		index[ia]=nt-1;
+	    }
+	  double newv=0.0;
+	  for (int ia=0;ia<=4;ia++)
+	    newv+=weights[ia]*values[index[ia]];
+	
+	  arr[j][i]=newv;
+	}
+    }
+  
+  delete [] values;
+  delete [] arr;
+
+  return 1;
+}
+// ---------------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Registration/vtkpxGridTransform.h b/bioimagesuite30_src/Registration/vtkpxGridTransform.h
new file mode 100644
index 0000000..976509f
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxGridTransform.h
@@ -0,0 +1,337 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkpxGridTransform_h
+#define __vtkpxGridTransform_h
+
+class vtkProbeFilter;
+class vtkPolyData;
+class vtkDataArray;
+class vtkpxMatrix;
+class vtkLinearTransform;
+class vtkDoubleArray;
+
+#include "vtkPoints.h"
+#include "vtkCollection.h"
+#include "vtkpxBaseGridTransform.h"
+
+//BTX
+class vtkpxGridTransform;
+class vtkpxGridTransformOptimizationStructure {
+public:
+  vtkCollection* ControlsCollection;
+  vtkPoints* points;
+  vtkPoints* points2;
+  double step;
+  double lambda;
+  double bend;
+  double error;
+  vtkpxMatrix* weights;
+  vtkpxGridTransform* priorTransform;
+  vtkDoubleArray*    priorWeights;
+
+  vtkpxGridTransformOptimizationStructure();
+  void SetValues(vtkCollection* ControlsCollection0,
+		 vtkPoints* points0,
+		 vtkPoints* points2_0,
+		 double step0,
+		 double lambda0,
+		 vtkpxMatrix* weights0,
+		 vtkpxGridTransform* prior0=NULL,
+		 vtkDoubleArray* priorweights0=NULL);
+};
+
+//ETX
+
+
+class vtkpxGridTransform : public vtkpxBaseGridTransform
+{
+public:
+  static vtkpxGridTransform *New();
+  vtkTypeMacro(vtkpxGridTransform,vtkpxBaseGridTransform);
+
+  // Description:
+  // Initialize Displacement Grid Given Image
+  virtual void InitializeDisplacementGrid(vtkImageData *image, double spacing,double offset,vtkAbstractTransform* tr=NULL);
+  
+  
+  // Description:
+  // Set Displacement Grid -- used to create cached structures
+  virtual void SetDisplacementGrid(vtkImageData *grid);
+
+
+  // -------------------------------------------------------------------
+  // Symmetric RPM Stuff
+  // -------------------------------------------------------------------
+
+  // Description:
+  // Initialize the Displacement Grid to be the same as the other
+  virtual void InitializeDisplacementGrid(vtkpxGridTransform* other);
+  virtual void InitializeDisplacementGrid(double bounds[6],double dx, double dy, double dz);
+  virtual void InverseApproximateTransformation(vtkpxGridTransform* output,int initialize=0);
+
+
+  // -----------------------------------------------------------------------------
+  // Utility Functions to Set Invididual Control Points
+  // -----------------------------------------------------------------------------
+
+  // Description:
+  // Access to Internal Structures for Information
+  vtkGetVector3Macro(GridDimensions,int);
+  vtkGetVector3Macro(GridSpacing,double);
+  vtkGetVector3Macro(GridOrigin,double);
+
+
+  // Description:
+  // NumberOfControlPoints
+  vtkGetMacro(NumberOfControlPoints,int);
+
+
+  // Description:
+  // NumberOfControlPoints
+  vtkGetMacro(ApproximationMode,int);
+  vtkSetMacro(ApproximationMode,int);
+
+  // Description:
+  // Get Index From Indices
+  virtual int GetControlPointIndex(int i,int j,int k);
+
+  // Description:
+  // Shift Control Point and get control point location stuff
+  virtual void  GetControlPointLocation(int index, double p[3]);
+  virtual double GetControlPointLocation(int index, int comp);
+
+
+  // Description:
+  // Modify individual displacements
+  virtual double GetControlPointDisplacement(int index,int comp);
+  virtual void  GetControlPointDisplacement(int index,double val[3]);
+  virtual void  SetControlPointDisplacement(int index,int comp,double val);
+  virtual void  SetControlPointDisplacement(int index,double val[3]);
+
+  // Description:
+  // Shift Control Point
+  virtual void  ShiftControlPoint(int index,int comp,double val);
+  virtual void  ShiftControlPoint(int index,double val[3]);
+
+
+  // Description:
+  // Compute Derivatives at a point, returns determinat (Jacobian)
+  virtual double ComputeDerivativeMatrix(double x1,double x2,double x3,vtkpxMatrix* matr);
+  virtual double ComputeDerivativeMatrix(int index,vtkpxMatrix* matr);
+  virtual double ComputeDerivativeMatrix(int index,double der[3][3]);
+  virtual double ComputeDerivativeMatrix(double x[3],double der[3][3]);
+
+
+  virtual double ComputeDerivative(int index,int comp1,int comp2);
+  virtual double ComputeDerivative(double x1,double x2,double x3,int comp1,int comp2);
+  virtual double ComputeDerivative(double x[3],int comp1,int comp2);
+
+  // ----------------------------------------------------------------------
+  // General Registration Stuff
+  // ----------------------------------------------------------------------
+
+  // Description:
+  // Initialize Transformation using an arbitrary input transform
+  virtual int   ApproximateTransformation(vtkAbstractTransform* tr);
+  virtual int   ApproximateTransformation(vtkAbstractTransform* tr,double step,
+					  int numiter,int numlevels,
+					  double threshold,double lambda);
+  virtual int   InitialApproximateTransformation(vtkAbstractTransform* tr);
+
+
+
+  // Description:
+  // Approximation Helper Routines
+  virtual void   GenerateTestPoints(vtkPoints* points,double inc=1.0);
+  virtual void   FillMatrices(vtkAbstractTransform* tr,vtkpxMatrix* A,vtkpxMatrix* B);
+  virtual double  TestApproximation(vtkAbstractTransform* tr,vtkPoints* points);
+  virtual double  TestInverseApproximation(vtkAbstractTransform* tr,vtkPoints* points);
+  virtual double  TestApproximation(vtkPoints* points,vtkPoints* points2);
+  virtual double  TestWeightedApproximation(vtkPoints* points,vtkPoints* points2,vtkpxMatrix* lsqweight,double& sum2error);
+
+  // Description:
+  // Test of B-Spline
+  virtual double TestTransformPoint(double p1[3],double p2[3]);
+  virtual double TestTransformPoint(double x,double y,double z);
+
+  // Description:
+  // Compute Bending Energy (this is the one used internally)
+  virtual double ComputeTotalBendingEnergy();
+  virtual double ComputeBendingEnergyAroundControlPoint(int cpoint);
+  virtual double ComputeBendingEnergyAtControlPoint(int cpoint);
+  virtual double ComputeBendingEnergyAtControlPoint(int i,int j,int k);
+
+  // Description:
+  // Compute Strain Energy (Linear Elasticity)
+  virtual double ComputeTotalStrainEnergy(double v=0.45);
+  virtual double ComputeStrainEnergyAtControlPoint(int cpoint,double v=0.45);
+  virtual double ComputeStrainEnergyAtPoint(double p1[3],double v=0.45);
+
+  // Description:
+  // CombineWithLinear Transform
+  virtual void CombineWithLinearTransform(vtkLinearTransform* tr,int premultiply=1);
+
+  // Description:
+  // Invert the transformation.  This is done by point fitting
+  void Inverse();
+
+  // -----------------------------------------------------------------------------
+  // Description
+  // The Following Routines are need to support point matching stuff
+  // -----------------------------------------------------------------------------
+
+  // Description:
+  // Form Weight Matrix 
+  virtual void FormWeightMatrix(vtkPoints* points,vtkpxMatrix* W);
+
+  // Description:
+  // Form Weight Structures
+  virtual int  FormCollectionStructure(vtkPoints* points,vtkCollection* ControlsCollection,double thr);
+  virtual int  FormCollectionStructure(vtkPoints* points,vtkCollection* ControlsCollection);
+  virtual void ApproximatePoints(vtkPoints* points,vtkPoints* points2,
+				 vtkCollection* ControlsCollection,
+				 double step,
+				 int numiter,int numlevels,double threshold,
+				 double lambda,int initialize,vtkpxMatrix* controlweights=NULL,
+				 vtkpxGridTransform* priorTransform=NULL,
+				 vtkDoubleArray* priorWeights=NULL);
+
+  virtual double ErrorAtControlPoint(int cp,vtkPoints* points,vtkPoints* points2,
+				    vtkDoubleArray* indices,double lambda,
+				    vtkpxMatrix* lsqweight=NULL,
+				    vtkpxGridTransform* priorTransform=NULL,
+				    vtkDoubleArray* priorWeights=NULL);
+
+
+
+
+  // Description:
+  // Compute Weighted Distance
+  // -------------------------
+  virtual double ComputeWeightedDistance(vtkpxGridTransform* other,int cp,vtkDoubleArray* weights=NULL);
+  virtual int   FormOutputWeights(vtkCollection* collection,vtkpxMatrix* PointWeights,vtkDoubleArray* OutputWeights);
+  // Description:
+  // Approximate Points with Prior 
+  /*  virtual void ApproximatePoints(vtkPoints* points,vtkPoints* points2,
+				 vtkCollection* ControlsCollection,
+				 double step,
+				 int numiter,int numlevels,double threshold,
+				 double lambda,int initialize,vtkpxMatrix* controlweights=NULL,
+				 vtkpxGridTransform* priorTransform,vtkDoubleArray* priorweights);*/
+
+  // Description:
+  // Shift Control Points by step*values in grad
+  virtual void  ShiftControlPoints(vtkDoubleArray* grad,double step);
+  virtual void  ScaleGradients(vtkDoubleArray* grad,double scale);
+  // -----------------------------------------------------------------------------
+
+  // Description:
+  // Stuff Needed for Using vtkpxOptimizer to improve approximation of new points
+  // -----------------------------------------------------------------------------
+  static void   OptimizerFeedback(vtkObject* self,const char* line,double val);
+  static double  CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output);
+  static double  CalculateFunction(vtkObject* self,vtkDoubleArray* position);
+
+  virtual void  SetCurrentParameters(vtkDoubleArray* par);
+  virtual void  GetCurrentParameters(vtkDoubleArray* par);
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+
+  // Description:
+  // Smoothing of Collections to yield new transformations
+  // -----------------------------------------------------------------------------
+  static int SmoothCollection(vtkCollection* TransformationCollection,int periodic=0,double sigma=1.0);
+
+  virtual double ComputeJacobianConstraint(float gamma);
+  //BTX
+  // Description:
+  // Pointer to Control Point
+  virtual double* GetControlPointPointer(int index);
+  virtual void   GetControlPointIndices(int index,int ind[3]);
+  //ETX
+
+protected:
+  vtkpxGridTransform();
+  virtual ~vtkpxGridTransform();
+  vtkpxGridTransform(const vtkpxGridTransform&) {};
+  void operator=(const vtkpxGridTransform&) {};
+
+
+
+  // Description:
+  // Get the inverse flag of the transformation.  This flag is
+  // set to zero when the transformation is first created, and
+  // is flipped each time Inverse() is called.
+  // Protected so it is not accesible from outside 
+  vtkGetMacro(InverseFlag,int);
+
+  
+  // Description:
+  // Cached Grid Dimensions, NumberOfControlPoints etc.
+  int    GridDimensions[3];
+  int   NumberOfControlPoints;
+  int   GridSliceDimensions;
+  double GridSpacing[3];
+  double GridOrigin[3];
+  vtkDoubleArray* Displacements;
+  int   ApproximationMode;
+  
+  //BTX
+  // Description:
+  // Get Lattice And Arclength Coordinates
+  virtual void GetCoordinatesInGrid(double point[3],int lattice[3],double s[3]);
+
+  vtkpxGridTransformOptimizationStructure OptimizationStructure;
+  //ETX
+
+public:
+  // --------------------------------------------------------------------------------------------------
+  // Description:
+  // Approximation Stuff
+  virtual double GradientAtControlPoint(int cp,double grad[3],
+				       vtkPoints* points,vtkPoints* points2,vtkDoubleArray* indices,
+				       double step,double lambda=0.0,vtkpxMatrix* lsqweights=NULL,
+				       vtkpxGridTransform* priorTransform=NULL,
+				       vtkDoubleArray* priorWeights=NULL);
+  
+protected:
+  // Description:
+  // Helper Routines for Approximate Displacements
+  // Shift Control Points by step * grad
+  virtual void  InitializeApproximatePoints(vtkPoints* points,vtkPoints* points2,vtkpxMatrix* lsqweights=NULL);
+
+};
+
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxJointHistogram.cpp b/bioimagesuite30_src/Registration/vtkpxJointHistogram.cpp
new file mode 100644
index 0000000..e0bb5e9
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxJointHistogram.cpp
@@ -0,0 +1,1714 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+
+/*=========================================================================*/
+#include "vtkpxJointHistogram.h"
+#include "vtkObjectFactory.h"
+#include "vtkShortArray.h"
+#include "vtkImageData.h"
+#include "vtkpxRegistration.h"
+#include "vtkImageCast.h"
+#include "pxutil.h"
+// ----------------------------------------------------------------------------------
+
+int** NewIntMatrix(int x[2]) 
+{
+  int** m = new int*[x[0]];
+  for(int i = 0; i < x[0]; i++) 
+    m[i] = new int[x[1]];
+  return m;
+}
+
+void DeleteIntMatrix(int** m, int x[2] ) 
+{
+  for(int i = 0; i < x[0]; i++) 
+    delete [] m[i]; // OK, we don't actually need y
+  delete [] m;
+}
+// ----------------------------------------------------------------------------------
+
+
+vtkpxJointHistogram* vtkpxJointHistogram::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxJointHistogram");
+  if(ret)
+    {
+      return (vtkpxJointHistogram*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxJointHistogram;
+}
+// ----------------------------------------------------------------------------------
+vtkpxJointHistogram::vtkpxJointHistogram()
+{
+
+  this->NumberOfBins[0]=64;
+  this->NumberOfBins[1]=64;
+  this->NumberOfSamples   = 0;
+
+  this->Bins=NULL;
+  this->OldBins=NULL;
+}
+// ----------------------------------------------------------------------------------
+vtkpxJointHistogram::~vtkpxJointHistogram()
+{
+  if (this->Bins!=NULL)
+    {
+      DeleteIntMatrix(this->Bins,this->NumberOfBins);
+      DeleteIntMatrix(this->OldBins,this->NumberOfBins);
+    }
+}
+// ----------------------------------------------------------------------------------
+void vtkpxJointHistogram::Reset()
+{
+  if (this->Bins==NULL)
+    return;
+
+  for (int ia=0;ia<this->NumberOfBins[0];ia++)
+    for (int ib=0;ib<this->NumberOfBins[1];ib++)
+      this->Bins[ia][ib]=0;
+  this->NumberOfSamples=0;
+
+}
+// ----------------------------------------------------------------------------------
+void vtkpxJointHistogram::Allocate(int numx,int numy)
+{
+  int flag=0;
+
+  int oldx[2];
+  oldx[0]=this->NumberOfBins[0];
+  oldx[1]=this->NumberOfBins[1];
+
+  if (this->Bins!=NULL)
+    {
+      if (numx!=NumberOfBins[0])
+	{
+	  this->NumberOfBins[0]=Irange(numx,1,1024);
+	  flag=1;
+	}
+      
+      if (numy!=NumberOfBins[1])
+	{
+	  this->NumberOfBins[1]=Irange(numy,1,1024);
+	  flag=1;
+	}
+
+      if (flag==1)
+	{
+	  DeleteIntMatrix(this->Bins,oldx);
+	  DeleteIntMatrix(this->OldBins,oldx);
+	}
+
+    }
+  else
+    {
+      flag=1;
+      this->NumberOfBins[0]=Irange(numx,1,1024);
+      this->NumberOfBins[1]=Irange(numy,1,1024);
+    }
+ 
+  if (flag==1)
+    {
+      this->Bins=NewIntMatrix(this->NumberOfBins);
+      this->OldBins=NewIntMatrix(this->NumberOfBins);
+    }
+  
+  this->Reset();
+  this->BackupHistogram();
+
+  
+}
+// ----------------------------------------------------------------------------------
+int vtkpxJointHistogram::CheckHistogram()
+{
+  if (this->NumberOfSamples == 0 || this->Bins==NULL)
+    {
+      vtkErrorMacro(<<"No Samples In Histogram");
+      return 0;
+    }
+  
+  return 1;
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::MeanX()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  
+  float val=0.0;
+  for (int i = 0; i < NumberOfBins[0]; i++)
+    {
+      float tmp=float(i);
+      for (int j = 0; j < NumberOfBins[1]; j++)
+	val += this->Bins[i][j] * tmp;
+    }
+  
+  return val / (float)this->NumberOfSamples;
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::MeanY()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+
+  float val = 0.0;
+  for (int j = 0; j < NumberOfBins[1]; j++)
+    {
+      float tmp = float(j);
+      for (int i = 0; i < NumberOfBins[0]; i++)
+	val += this->Bins[i][j] * tmp;
+    }
+
+  return val / (float)this->NumberOfSamples;
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::VarianceX()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  float val  = 0.0;
+  for (int i = 0; i < NumberOfBins[0]; i++)
+    val += this->MarginalProbabilityX(i) * pow(float(i),float(2.0));
+
+  return val - pow(this->MeanX(), 2);
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::VarianceY()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  float val  = 0;
+  for (int i = 0; i < NumberOfBins[1]; i++)
+    val += this->MarginalProbabilityY(i) * pow(float(i),float(2.0));
+
+  return val - pow(this->MeanY(), 2);
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::StandardDeviationX()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+  return sqrt(this->VarianceX());
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::StandardDeviationY()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+  
+  return sqrt(this->VarianceY());
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::Covariance()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+  
+  float val  = 0.0;
+  float mean_x = this->MeanX(); 
+  float mean_y = this->MeanY(); 
+  for (int j = 0; j < NumberOfBins[1]; j++)
+    for (int i = 0; i < NumberOfBins[0]; i++)
+      val += this->Bins[i][j] * float (i-mean_x)*float(j-mean_y);
+
+  return val / (float)NumberOfSamples;
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::EntropyX()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  // Calculate entropy
+  float val = 0;
+  for (int i = 0; i < NumberOfBins[0]; i++)
+    {
+      float tmp=0.0;
+      for (int j = 0; j < NumberOfBins[1]; j++)
+	  tmp +=this->Bins[i][j];
+
+      if (tmp > 0) 
+	val += tmp * log(tmp);
+    }
+
+
+
+  float v= - val / (float)NumberOfSamples + log(float(NumberOfSamples));
+  //  fprintf(stdout,"Entropy X=%f\n",v);
+  return v;
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::EntropyY()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  // Calculate entropy
+  float val = 0;
+  
+  for (int j = 0; j < NumberOfBins[1]; j++)
+    {
+      float tmp = 0;
+      for (int i = 0; i < NumberOfBins[0]; i++)
+	tmp += this->Bins[i][j];
+
+      if (tmp > 0) 
+	val += tmp * log(tmp);
+    }
+  float v= - val / (float)NumberOfSamples + log(float(NumberOfSamples));
+  //  fprintf(stdout,"Entropy Y=%f\n",v);
+  return v;
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::JointEntropy()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  // Calculate joint entropy
+  float val = 0;
+  
+  for (int j = 0; j < NumberOfBins[1]; j++)
+    for (int i = 0; i < NumberOfBins[0]; i++)
+      {
+	float v=this->Bins[i][j];
+	if (v > 0.0)
+	  val += v * log(v);
+
+      }
+
+  float v= - val / (float)NumberOfSamples + log(float(NumberOfSamples));
+  //  fprintf(stdout,"Joint Entropy = %f\n",v);
+  return v;
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::ConditionalMeanXY(int i)
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  if ((i < 0) || (i > NumberOfBins[1]-1))
+    {
+      cerr << "vtkpxJointHistogram::ConditionalMeanXY: No such bin " << i << endl;
+      return 0;
+    }
+  
+  float m = 0;
+  float p = 0;
+  for (int j = 0; j < NumberOfBins[0]; j++)
+    {
+      m += this->JointProbability(j, i) * float(j);
+      p += this->JointProbability(j, i);
+    }
+
+  if (p > 0.0)
+    return m / p;
+
+  return 0;
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::ConditionalMeanYX(int i)
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  if ((i < 0) || (i > NumberOfBins[0]-1)){
+    cerr << "vtkpxJointHistogram::ConditionalMeanYX: No such bin " << i << endl;
+    return 0;
+  }
+  float m = 0;
+  float p = 0;
+  for (int j = 0; j < NumberOfBins[1]; j++)
+    {
+      m += this->JointProbability(i, j) * float(j);
+      p += this->JointProbability(i, j);
+    }
+
+  if (p > 0)
+    return m / p;
+
+  return 0;
+  
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::CorrelationRatioXY()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  float c = 0;
+  float m = this->MeanX();
+  for (int i = 0; i < NumberOfBins[1]; i++)
+    c += this->MarginalProbabilityY(i) * pow(this->ConditionalMeanXY(i)-m, float(2.0));
+  
+  return (c / this->VarianceX());
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::CorrelationRatioYX()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  float c = 0;
+  float m = this->MeanY();
+  for (int i = 0; i < NumberOfBins[0]; i++)
+    c += this->MarginalProbabilityX(i) * pow(this->ConditionalMeanYX(i)-m, float(2.0));
+  return (c / this->VarianceY());
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::MutualInformation()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+
+  return this->EntropyX() + this->EntropyY() - this->JointEntropy();
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::NormalizedMutualInformation()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  return (this->EntropyX() + this->EntropyY()) / this->JointEntropy()-1.0;
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::CrossCorrelation()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  return this->Covariance() / (sqrt(this->VarianceX()) * sqrt(this->VarianceY()));
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::SumsOfSquaredDifferences()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+  float ssd   = 0;
+  for (int j = 0; j < NumberOfBins[1]; j++)
+    for (int i = 0; i < NumberOfBins[0]; i++)
+      ssd   += this->Bins[i][j]*pow(float(i-j),float(2.0));
+  
+  return ssd/float(this->GetNumberOfSamples());
+
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::ComputeProduct()
+{
+  if (this->CheckHistogram()==0)
+    return 0.0;
+
+
+  if (this->NumberOfSamples<1)
+    return 0.0;
+
+  float prod   = 0;
+  for (int j = 0; j < NumberOfBins[1]; j++)
+    for (int i = 0; i < NumberOfBins[0]; i++)
+      prod   += this->Bins[i][j]*i*j;
+  
+  if (this->NumberOfSamples<1)
+    return 0;
+
+  return prod/float(this->GetNumberOfSamples());
+}
+// ----------------------------------------------------------------------------------
+int vtkpxJointHistogram::GetNumberOfBinsX()
+{
+  return NumberOfBins[0];
+}
+// ----------------------------------------------------------------------------------
+ int vtkpxJointHistogram::GetNumberOfBinsY()
+{
+  return NumberOfBins[1];
+}
+// ----------------------------------------------------------------------------------
+int vtkpxJointHistogram::GetBinCount(int i,int j)
+{
+  i=Irange(i,0,this->NumberOfBins[0]-1);
+  j=Irange(j,0,this->NumberOfBins[1]-1);
+  return this->Bins[i][j];
+}
+
+void vtkpxJointHistogram::SetBinCount(int i,int j,int v)
+{
+  int ia=Irange(i,0,this->NumberOfBins[0]-1);
+  int ib=Irange(j,0,this->NumberOfBins[1]-1);
+  if (i!=ia || ib!=j)
+    fprintf(stdout,"Mapping %d %d --> %d %d\n",i,j,ia,ib);
+  this->NumberOfSamples=this->NumberOfSamples+v-this->Bins[ia][ib];
+  this->Bins[ia][ib]=v;
+}
+
+ float vtkpxJointHistogram::JointProbability(int i, int j)
+{
+  i=Irange(i,0,this->NumberOfBins[0]-1);
+  j=Irange(j,0,this->NumberOfBins[1]-1);
+  return this->Bins[i][j] / (float) NumberOfSamples;
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::MarginalProbabilityX(int i)
+{
+  i=Irange(i,0,this->NumberOfBins[0]-1);
+  float n = 0;
+  for (int j = 0; j < NumberOfBins[1]; j++)
+    n += this->Bins[i][j];
+  return n / (float) NumberOfSamples;
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::MarginalProbabilityY(int j)
+{
+  j=Irange(j,0,this->NumberOfBins[1]-1);
+  float n = 0;
+  for (int i = 0; i < NumberOfBins[0]; i++)
+    n += this->Bins[i][j];
+
+  return n / (float) NumberOfSamples;
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::ConditionalProbabilityXY(int i, int j)
+{
+  float p = this->MarginalProbabilityY(j);
+  if (p > 0)
+    return this->JointProbability(i, j) / p;
+    
+  return 0;
+
+}
+// ----------------------------------------------------------------------------------
+float vtkpxJointHistogram::ConditionalProbabilityYX(int i, int j)
+{
+  float p = this->MarginalProbabilityX(j);
+  if (p > 0)
+    return this->JointProbability(j, i) / p;
+
+  return 0;
+}
+// ----------------------------------------------------------------------------------
+int vtkpxJointHistogram::AddToBin(short a,short b,short count)
+{
+  if (this->Bins==NULL)
+      return 0;
+
+
+  if (a>=0 && a<this->NumberOfBins[0] && b>=0 && b<this->NumberOfBins[1])
+    {
+      this->Bins[a][b] +=count;
+      this->NumberOfSamples+=count;
+      return 1;
+
+    }
+  
+  return 0;
+
+}
+
+
+// ----------------------------------------------------------------------------------
+int vtkpxJointHistogram::DelToBin(short a,short b,short count)
+{
+  if (this->Bins==NULL)
+    return 0;
+
+  if (a>=0 && a<this->NumberOfBins[0] && b>=0 && b<this->NumberOfBins[1])
+    {
+      this->Bins[a][b] -=count;
+      this->NumberOfSamples-=count;
+      return 1;
+    }
+  return 0;
+
+}
+// --------------------------------------------------------------------------------
+int vtkpxJointHistogram::AddToBin(unsigned char a,unsigned char b,unsigned char count)
+{
+  if (this->Bins==NULL)
+    return 0;
+
+  if (a<this->NumberOfBins[0] &&  b<this->NumberOfBins[1])
+    {
+      this->Bins[a][b] +=count;
+      this->NumberOfSamples+=count;
+      return 1;
+    }
+  
+  return 0;
+
+}
+
+
+// ----------------------------------------------------------------------------------
+int vtkpxJointHistogram::DelToBin(unsigned char a,unsigned char b,unsigned char count)
+{
+  if (this->Bins==NULL)
+    return 0;
+
+  if (a<this->NumberOfBins[0] && b<this->NumberOfBins[1])
+    {
+      this->Bins[a][b] -=count;
+      this->NumberOfSamples-=count;
+      return 1;
+    }
+  return 0;
+
+}
+// ----------------------------------------------------------------------------------
+void vtkpxJointHistogram::ResetHistogram()
+{
+  if (this->Bins!=NULL && this->OldBins!=NULL)
+    {
+      for (int i=0;i<this->NumberOfBins[0];i++)
+	for (int j=0;j<this->NumberOfBins[1];j++)
+	  this->Bins[i][j]=this->OldBins[i][j];
+      this->NumberOfSamples=this->OldNumberOfSamples;
+    }
+}
+
+void vtkpxJointHistogram::BackupHistogram()
+{
+  if (this->Bins!=NULL && this->OldBins!=NULL)
+    {
+      for (int i=0;i<this->NumberOfBins[0];i++)
+	for (int j=0;j<this->NumberOfBins[1];j++)
+	  this->OldBins[i][j]=this->Bins[i][j];
+      this->OldNumberOfSamples=this->NumberOfSamples;
+    }
+}
+
+//-------------------------------------------------------------------------
+int vtkpxJointHistogram::AreBothImagesShort(vtkImageData* img1,vtkImageData* img2)
+{
+  if (img1->GetScalarType()==VTK_SHORT && img2->GetScalarType()==VTK_SHORT )
+    return 1;
+  return 0;
+}
+//-------------------------------------------------------------------------
+int vtkpxJointHistogram::AreBothImagesUnsignedChar(vtkImageData* img1,vtkImageData* img2)
+{
+  if (img1->GetScalarType()==VTK_UNSIGNED_CHAR && img2->GetScalarType()==VTK_UNSIGNED_CHAR )
+    return 1;
+  return 0;
+}
+//-------------------------------------------------------------------------
+int vtkpxJointHistogram::FillHistogram(vtkImageData* ref,vtkImageData* targ,int reset)
+{
+  
+  int np1= ref->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc1= ref->GetNumberOfScalarComponents();
+  int np2=targ->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc2=targ->GetNumberOfScalarComponents();
+
+  if (np1!=np2)
+    return 0;
+
+  if (this->AreBothImagesShort(ref,targ)==1)
+    {
+      short *img1 = (short*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *img2 = (short*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+
+      
+      if (reset)
+	this->Reset();
+
+      if (nc1 ==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;++i)
+	    {
+	      this->AddToBin(*img1,*img2);
+	      ++img1;
+	      ++img2;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+		  this->AddToBin(img1[c1],img2[c2]);
+	      img1+=nc1;
+	      img2+=nc2;
+	    }
+	}
+    }
+  else if (this->AreBothImagesUnsignedChar(ref,targ)==1)
+    {
+      unsigned char *img1 = (unsigned char*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      unsigned char *img2 = (unsigned char*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+
+      if (reset)
+	this->Reset();
+
+      if (nc1 ==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;++i)
+	    {
+	      this->AddToBin(*img1,*img2);
+	      ++img1;
+	      ++img2;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+		  this->AddToBin(img1[c1],img2[c2]);
+	      img1+=nc1;
+	      img2+=nc2;
+	    }
+	}
+    }
+  else
+    {
+      vtkDataArray* img1 =  ref->GetPointData()->GetScalars();
+      vtkDataArray* img2 =  targ->GetPointData()->GetScalars();
+      
+      if (reset)
+	this->Reset();
+
+      for (int i=0;i<np1;i++)
+	{
+	  for (int c1=0;c1<nc1;c1++)
+	    {
+	      short a1=(short)img1->GetComponent(i,c1);
+	      for (int c2=0;c2<nc2;c2++)
+		{
+		  short a2=(short)img2->GetComponent(i,c2);
+		  this->AddToBin(a1,a2);
+		}
+	    }
+	}
+    }
+
+  return 1;
+}
+//-------------------------------------------------------------------------
+//
+//  Weighted Fill Histogram
+//
+//-------------------------------------------------------------------------
+int vtkpxJointHistogram::WeightedFillHistogram(vtkImageData* ref,vtkImageData* targ,vtkImageData* weights,int reset)
+{
+  static int count=0;
+  ++count;
+
+  if (weights==NULL)
+    return this->FillHistogram(ref,targ,reset);
+  
+  int np1= ref->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc1= ref->GetNumberOfScalarComponents();
+  int np2=targ->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc2=targ->GetNumberOfScalarComponents();
+  int np3=weights->GetPointData()->GetScalars()->GetNumberOfTuples();
+
+  if (count==1)
+    fprintf(stderr,"Weighted Fill Histogram np1=%d, npc1=%d, np2=%d nc2=%d np3=%d\n",
+	    np1,nc1,np2,nc2,np3);
+
+  if (np1!=np2 || np1!=np3)
+    return 0;
+
+  if (this->AreBothImagesShort(ref,targ)==1 && this->AreBothImagesShort(ref,weights))
+    {
+      if (count==1)
+	fprintf(stderr,"In Short Paradise ..... \n");
+      short *img1 = (short*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *img2 = (short*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *wgt  = (short*) weights->GetPointData()->GetScalars()->GetVoidPointer(0);
+      if (reset)
+	this->Reset();
+
+      if (nc1 ==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;++i)
+	    {
+	      this->AddToBin(*img1,*img2,*wgt);
+	      ++img1;
+	      ++img2;
+	      ++wgt;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+	      this->AddToBin(img1[c1],img2[c2],*wgt);
+	      img1+=nc1;
+	      img2+=nc2;
+	      ++wgt;
+	    }	  
+	}
+    }
+  else if (this->AreBothImagesUnsignedChar(ref,targ)==1 && this->AreBothImagesUnsignedChar(ref,weights))
+      {
+      unsigned char *img1 = (unsigned char*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      unsigned char *img2 = (unsigned char*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+      unsigned char *wgt  = (unsigned char*) weights->GetPointData()->GetScalars()->GetVoidPointer(0);
+
+      if (reset)
+	this->Reset();
+
+      if (nc1 ==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;++i)
+	    {
+	      this->AddToBin(*img1,*img2,*wgt);
+	      ++img1;
+	      ++img2;
+	      ++wgt;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+		  this->AddToBin(img1[c1],img2[c2],*wgt);
+	      img1+=nc1;
+	      img2+=nc2;
+	      ++wgt;
+	    }
+	}
+    }
+  else
+    {
+      vtkDataArray* img1 =  ref->GetPointData()->GetScalars();
+      vtkDataArray* img2 =  targ->GetPointData()->GetScalars();
+      vtkDataArray* wgt  =  weights->GetPointData()->GetScalars();
+      
+      if (reset)
+	this->Reset();
+
+      for (int i=0;i<np1;i++)
+	{
+	  for (int c1=0;c1<nc1;c1++)
+	    {
+	      short a1=(short)img1->GetComponent(i,c1);
+	      for (int c2=0;c2<nc2;c2++)
+		{
+		  short a2=(short)img2->GetComponent(i,c2);
+		  this->AddToBin(a1,a2,(short)wgt->GetComponent(i,0));
+		}
+	    }
+	}
+    }
+
+  return 1;
+}
+//-------------------------------------------------------------------------
+//
+//  Dual Weighted Fill Histogram
+//
+//-------------------------------------------------------------------------
+int vtkpxJointHistogram::DualWeightedFillHistogram(vtkImageData* ref,vtkImageData* targ,vtkImageData* weights,vtkImageData* weights2,int reset)
+{
+  static int count=0;
+  ++count;
+
+  if (weights==NULL)
+    return this->FillHistogram(ref,targ,reset);
+
+  if (weights2==NULL)
+    return this->WeightedFillHistogram(ref,targ,weights,reset);
+  
+  int np1= ref->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc1= ref->GetNumberOfScalarComponents();
+  int np2=targ->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc2=targ->GetNumberOfScalarComponents();
+  int np3=weights->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int np4=weights2->GetPointData()->GetScalars()->GetNumberOfTuples();
+
+  if (count==1)
+    fprintf(stderr,"Dual Weighted Fill Histogram np1=%d, npc1=%d, np2=%d nc2=%d np3=%d np4=%d\n",
+	    np1,nc1,np2,nc2,np3,np4);
+
+  if (np1!=np2 || np1!=np3 || np1!=np4 )
+    return 0;
+
+  if (this->AreBothImagesShort(ref,targ)==1 && this->AreBothImagesShort(weights,weights2))
+    {
+      if (count==1)
+	fprintf(stderr,"In Short Paradise ..... \n");
+      short *img1 = (short*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *img2 = (short*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *wgt  = (short*) weights->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *wgt2 = (short*) weights2->GetPointData()->GetScalars()->GetVoidPointer(0);
+      if (reset)
+	this->Reset();
+
+      if (nc1 ==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;++i)
+	    {
+	      this->AddToBin(*img1,*img2,(*wgt)+(*wgt2));
+	      ++img1;
+	      ++img2;
+	      ++wgt;
+	      ++wgt2;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+		  this->AddToBin(img1[c1],img2[c2],(*wgt)+(*wgt2));
+	      img1+=nc1;
+	      img2+=nc2;
+	      ++wgt;
+	      ++wgt2;
+	    }	  
+	}
+    }
+  else if (this->AreBothImagesUnsignedChar(ref,targ)==1 && this->AreBothImagesUnsignedChar(weights,weights2))
+      {
+      unsigned char *img1 = (unsigned char*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      unsigned char *img2 = (unsigned char*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+      unsigned char *wgt  = (unsigned char*) weights->GetPointData()->GetScalars()->GetVoidPointer(0);
+      unsigned char *wgt2 = (unsigned char*) weights2->GetPointData()->GetScalars()->GetVoidPointer(0);
+
+      if (reset)
+	this->Reset();
+
+      if (nc1 ==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;++i)
+	    {
+	      this->AddToBin(*img1,*img2,(*wgt)+(*wgt2));
+	      ++img1;
+	      ++img2;
+	      ++wgt;
+	      ++wgt2;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+		  this->AddToBin(img1[c1],img2[c2],(*wgt)+(*wgt2));
+	      img1+=nc1;
+	      img2+=nc2;
+	      ++wgt;
+	      ++wgt2;
+	    }
+	}
+    }
+  else
+    {
+      vtkDataArray* img1 =  ref->GetPointData()->GetScalars();
+      vtkDataArray* img2 =  targ->GetPointData()->GetScalars();
+      vtkDataArray* wgt  =  weights->GetPointData()->GetScalars();
+      vtkDataArray* wgt2 =  weights2->GetPointData()->GetScalars();
+      
+      if (reset)
+	this->Reset();
+
+      for (int i=0;i<np1;i++)
+	{
+	  for (int c1=0;c1<nc1;c1++)
+	    {
+	      short a1=(short)img1->GetComponent(i,c1);
+	      for (int c2=0;c2<nc2;c2++)
+		{
+		  short a2=(short)img2->GetComponent(i,c2);
+		  this->AddToBin(a1,a2,(short)(wgt->GetComponent(i,0)+wgt2->GetComponent(i,0)));
+		}
+	    }
+	}
+    }
+
+  return 1;
+}
+//-------------------------------------------------------------------------
+//
+//  Use Intensity Gradient to compute histogram
+//
+//-------------------------------------------------------------------------
+int vtkpxJointHistogram::FillGradientHistogram(vtkImageData* ref,vtkImageData* targ,vtkImageData* grad,
+					       double step,int component,int reset)
+{
+  if (grad==NULL)
+    return this->FillHistogram(ref,targ,reset);
+
+  int np1= ref->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc1= ref->GetNumberOfScalarComponents();
+
+  int np2=targ->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc2=targ->GetNumberOfScalarComponents();
+
+  int np3=grad->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc3=grad->GetNumberOfScalarComponents();
+
+  if (np1!=np2 || np1!=np3)
+    return 0;
+
+  if (component<0 || component>2)
+    component=0;
+
+  if (this->AreBothImagesShort(ref,targ)==1 && grad->GetScalarType()==VTK_DOUBLE)
+    {
+      short *img1 = (short*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *img2 = (short*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+      double *grd =  (double*) grad->GetPointData()->GetScalars()->GetVoidPointer(0);
+      for (int c=0;c<component;c++)
+	++grd;
+      
+      if (reset)
+	this->Reset();
+      
+      if (nc1 ==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;++i)
+	    {
+	      this->AddToBin(*img1,short(*img2+(*grd)*step));
+	      ++img1;
+	      ++img2;
+	      ++grd;
+	      ++grd;
+	      ++grd;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+		  this->AddToBin(img1[c1],short(img2[c2]+(*grd)*step));
+	      img1+=nc1;
+	      img2+=nc2;
+	      ++grd;
+	      ++grd;
+	      ++grd;
+  	    }
+	}
+    }
+  else
+    {
+      vtkDataArray* img1 =  ref->GetPointData()->GetScalars();
+      vtkDataArray* img2 =  targ->GetPointData()->GetScalars();
+      vtkDataArray* grd =   grad->GetPointData()->GetScalars();
+      
+      if (reset)
+	this->Reset();
+
+      for (int i=0;i<np1;i++)
+	{
+	  for (int c1=0;c1<nc1;c1++)
+	    {
+	      short a1=(short)img1->GetComponent(i,c1);
+	      for (int c2=0;c2<nc2;c2++)
+		{
+		  short a2=(short)img2->GetComponent(i,c2);
+		  double g2=grd->GetComponent(i,component);
+		  this->AddToBin(a1,short(a2+g2*step));
+		}
+	    }
+	}
+    }
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxJointHistogram::RemoveFromHistogram(vtkImageData* ref,vtkImageData* targ)
+{
+  int np1= ref->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc1= ref->GetNumberOfScalarComponents();
+  int np2= targ->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc2= targ->GetNumberOfScalarComponents();
+
+  if (np1!=np2)
+    return 0;
+
+  if (this->AreBothImagesShort(ref,targ)==1)
+    {
+      short *img1 = (short*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *img2 = (short*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+      
+      if (nc1==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      this->DelToBin(*img1,*img2);
+	      ++img1;
+	      ++img2;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+		  this->DelToBin(img1[c1],img2[c2]);
+	      img1+=nc1;
+	      img2+=nc2;
+	    }
+	}
+    }
+  else if (this->AreBothImagesUnsignedChar(ref,targ)==1)
+    {
+      unsigned char *img1 = (unsigned char*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      unsigned char *img2 = (unsigned char*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+      
+      if (nc1==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      this->DelToBin(*img1,*img2);
+	      ++img1;
+	      ++img2;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+		  this->DelToBin(img1[c1],img2[c2]);
+	      img1+=nc1;
+	      img2+=nc2;
+	    }
+	}
+    }
+  else
+    {
+      vtkDataArray* img1 =  ref->GetPointData()->GetScalars();
+      vtkDataArray* img2 =  targ->GetPointData()->GetScalars();
+      
+      for (int i=0;i<np1;i++)
+	{
+	  for (int c1=0;c1<nc1;c1++)
+	    {
+	      short a1=(short)img1->GetComponent(i,c1);
+	      for (int c2=0;c2<nc2;c2++)
+		{
+		  short a2=(short)img2->GetComponent(i,c2);
+		  this->DelToBin(a1,a2);
+		}
+	    }
+	}
+    }
+
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxJointHistogram::WeightedRemoveFromHistogram(vtkImageData* ref,vtkImageData* targ,vtkImageData* weights)
+{
+  if (weights==NULL)
+    return this->RemoveFromHistogram(ref,targ);
+
+
+  int np1= ref->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc1= ref->GetNumberOfScalarComponents();
+  int np2= targ->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc2= targ->GetNumberOfScalarComponents();
+  int np3=weights->GetPointData()->GetScalars()->GetNumberOfTuples();
+  if (np1!=np2 || np1!=np3)
+    return 0;
+
+  if (this->AreBothImagesShort(ref,targ)==1 && this->AreBothImagesShort(ref,weights)==1)
+    {
+      short *img1 = (short*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *img2 = (short*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *wgt  = (short*) weights->GetPointData()->GetScalars()->GetVoidPointer(0);
+      
+      if (nc1==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      this->DelToBin(*img1,*img2,*wgt);
+	      ++img1;
+	      ++img2;
+	      ++wgt;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+		  this->DelToBin(img1[c1],img2[c2],*wgt);
+	      img1+=nc1;
+	      img2+=nc2;
+	      ++wgt;
+	    }
+	}
+    }
+  else if (this->AreBothImagesUnsignedChar(ref,targ)==1 && this->AreBothImagesUnsignedChar(ref,weights)==1)
+    {
+      unsigned char *img1 = (unsigned char*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      unsigned char *img2 = (unsigned char*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+      unsigned char *wgt  = (unsigned char*) weights->GetPointData()->GetScalars()->GetVoidPointer(0);
+	    
+      if (nc1==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      this->DelToBin(*img1,*img2,*wgt);
+	      ++img1;
+	      ++img2;
+	      ++wgt;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+		  this->DelToBin(img1[c1],img2[c2],*wgt);
+	      img1+=nc1;
+	      img2+=nc2;
+	      ++wgt;
+	    }
+	}
+    }
+  else
+    {
+      vtkDataArray* img1 =  ref->GetPointData()->GetScalars();
+      vtkDataArray* img2 =  targ->GetPointData()->GetScalars();
+      vtkDataArray* wgt  =  weights->GetPointData()->GetScalars();
+      
+      for (int i=0;i<np1;i++)
+	{
+	  short w=(short)wgt->GetComponent(i,0);
+	  for (int c1=0;c1<nc1;c1++)
+	    {
+	      short a1=(short)img1->GetComponent(i,c1);
+	      for (int c2=0;c2<nc2;c2++)
+		{
+		  short a2=(short)img2->GetComponent(i,c2);
+		  this->DelToBin(a1,a2,w);
+		}
+	    }
+	}
+    }
+
+  return 1;
+}
+// -------------------------------------------------------------------------------
+int vtkpxJointHistogram::DualWeightedRemoveFromHistogram(vtkImageData* ref,vtkImageData* targ,vtkImageData* weights,vtkImageData* weights2)
+{
+  if (weights==NULL)
+    return this->RemoveFromHistogram(ref,targ);
+
+  if (weights2==NULL)
+    return this->WeightedRemoveFromHistogram(ref,targ,weights);
+
+
+  int np1= ref->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc1= ref->GetNumberOfScalarComponents();
+  int np2= targ->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc2= targ->GetNumberOfScalarComponents();
+  int np3=weights->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int np4=weights2->GetPointData()->GetScalars()->GetNumberOfTuples();
+
+  if (np1!=np2 || np1!=np3 || np1!=np4 )
+    return 0;
+
+  if (this->AreBothImagesShort(ref,targ)==1 && this->AreBothImagesShort(weights,weights2)==1)
+    {
+      short *img1 = (short*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *img2 = (short*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *wgt  = (short*) weights->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *wgt2  = (short*) weights2->GetPointData()->GetScalars()->GetVoidPointer(0);
+      
+      if (nc1==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      this->DelToBin(*img1,*img2,((*wgt)+(*wgt2)));
+	      ++img1;
+	      ++img2;
+	      ++wgt;
+	      ++wgt2;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+		  this->DelToBin(img1[c1],img2[c2],((*wgt)+(*wgt2)));
+	      img1+=nc1;
+	      img2+=nc2;
+	      ++wgt;
+	      ++wgt2;
+	    }
+	}
+    }
+  else if (this->AreBothImagesUnsignedChar(ref,targ)==1 && this->AreBothImagesUnsignedChar(ref,weights)==1)
+    {
+      unsigned char *img1 = (unsigned char*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      unsigned char *img2 = (unsigned char*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+      unsigned char *wgt  = (unsigned char*) weights->GetPointData()->GetScalars()->GetVoidPointer(0);
+      unsigned char *wgt2 = (unsigned char*) weights2->GetPointData()->GetScalars()->GetVoidPointer(0);
+	    
+      if (nc1==1 && nc2==1)
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      this->DelToBin(*img1,*img2,((*wgt)+(*wgt2)));
+	      ++img1;
+	      ++img2;
+	      ++wgt;
+	      ++wgt2;
+	    }
+	}
+      else
+	{
+	  for (int i=0;i<np1;i++)
+	    {
+	      for (int c1=0;c1<nc1;c1++)
+		for (int c2=0;c2<nc2;c2++)
+		  this->DelToBin(img1[c1],img2[c2],((*wgt)+(*wgt2)));
+	      img1+=nc1;
+	      img2+=nc2;
+	      ++wgt;
+	      ++wgt2;
+	    }
+	}
+    }
+  else
+    {
+      vtkDataArray* img1 =  ref->GetPointData()->GetScalars();
+      vtkDataArray* img2 =  targ->GetPointData()->GetScalars();
+      vtkDataArray* wgt  =  weights->GetPointData()->GetScalars();
+      vtkDataArray* wgt2 =  weights2->GetPointData()->GetScalars();
+      
+      for (int i=0;i<np1;i++)
+	{
+	  short w=(short)wgt->GetComponent(i,0);
+	  w=w+(short)wgt2->GetComponent(i,0);
+	  for (int c1=0;c1<nc1;c1++)
+	    {
+	      short a1=(short)img1->GetComponent(i,c1);
+	      for (int c2=0;c2<nc2;c2++)
+		{
+		  short a2=(short)img2->GetComponent(i,c2);
+		  this->DelToBin(a1,a2,w);
+		}
+	    }
+	}
+    }
+
+  return 1;
+}
+// -------------------------------------------------------------------------------
+float vtkpxJointHistogram::ComputeEntropyOfDifference()
+{
+  static float newhist[2048];
+
+  int ncommon=this->NumberOfBins[0]+this->NumberOfBins[1]-1;
+  if (ncommon>2048)
+    {
+      fprintf(stderr,"Difference Histogram is too big\n");
+      return 0.0;
+    }
+
+  for (int ia=0;ia<ncommon;ia++)
+    newhist[ia]=0.0;
+
+  for (int j = 0; j < NumberOfBins[1]; j++)
+    for (int i = 0; i < NumberOfBins[0]; i++)
+      {
+	int index=(j-i)+NumberOfBins[0]-1;
+	newhist[index]+=this->Bins[i][j];
+      }
+
+  float total=0.0;
+  for (int k=0;k<ncommon;k++)
+    total+=newhist[k];
+
+  float val = 0;
+  for (int ic=0;ic<ncommon;ic++)
+    {
+      float a=newhist[ic]/total;
+      if (a>0)
+	val+=a*log(a);
+    }
+
+  return -val;
+}
+
+// -------------------------------------------------------------------------------------
+
+const char* vtkpxJointHistogram::NameOfMeasure(int measureno)
+{
+  // Return the name of similarity measure
+  switch (measureno) 
+    {
+    case 1:
+      return "JointEntropy";
+      break;
+    case 2:
+      return "Correlation";
+      break;
+    case 3:
+      return "Gradient Correlation";
+      break;
+    case 4:
+      return "Mutual Information";
+      break;
+    case 5:
+      return "Normalized Mutual Information";
+      break;
+    case 6:
+      return "Sums of Squared Differences";
+      break;
+    case 7:
+      return "Correlation ratio C(X|Y)";
+      break;
+    case 8:
+      return "Correlation ratio C(Y|X)";
+    case 9:
+      return "Product Y*x";
+      break;
+    case 10:
+      return "Entropy of Difference";
+      break;
+    }
+  return "Undefined!";
+
+}
+// -------------------------------------------------------------------------------------
+float vtkpxJointHistogram::Similarity(int measureno)
+{
+  switch (measureno) 
+    {
+    case 1:
+      return -this->JointEntropy();
+      break;
+    case 2:
+      return +this->CrossCorrelation();
+      break;
+    case 3:
+      return fabs(this->CrossCorrelation());
+      break;
+    case 4:
+      return +this->MutualInformation();
+      break;
+    case 5:
+      return +this->NormalizedMutualInformation();
+      break;
+    case 6:
+      return -this->SumsOfSquaredDifferences();
+      break;
+    case 7:
+      return +this->CorrelationRatioXY();
+      break;
+    case 8:
+      return +this->CorrelationRatioYX();
+      break;
+    case 9:
+      return this->ComputeProduct();
+      break;
+    case 10:
+      return -this->ComputeEntropyOfDifference();
+      break;
+    default:
+      return 0;
+      break;
+    }
+}
+
+
+// -------------------------------------------------------------------------------------
+vtkImageData* vtkpxJointHistogram::GetHistogramAsImage()
+{
+  vtkImageData* img=vtkImageData::New();
+  img->SetDimensions(this->NumberOfBins[0],this->NumberOfBins[1],1);
+  img->SetScalarTypeToFloat();
+  img->AllocateScalars();
+
+  for (int ia=0;ia<this->NumberOfBins[0];ia++)
+    for (int ib=0;ib<this->NumberOfBins[1];ib++)
+      img->SetScalarComponentFromDouble(ia,ib,0,0,this->Bins[ia][ib]);
+  return img;
+}
+
+int  vtkpxJointHistogram::SetHistogramFromImage(vtkImageData* img)
+{
+  if (img==NULL)
+    return 0;
+
+  int dim[3];
+  img->GetDimensions(dim);
+  if (dim[2]!=1)
+    {
+      fprintf(stderr,"Error 3D Image Specified in SetHistogramFromImage\n");
+      return 0;
+    }
+
+  this->Allocate(dim[0],dim[1]);
+  for (int ia=0;ia<dim[0];ia++)
+    for (int ib=0;ib<dim[1];ib++)
+      {
+	double v=img->GetScalarComponentAsDouble(ia,ib,0,0);
+	this->Bins[ia][ib]=int(v);
+      }
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------------
+int vtkpxJointHistogram::FillHistogramComponent(vtkImageData* ref,vtkImageData* targ,int component1,int component2,int reset)
+{
+  
+  int np1= ref->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc1= ref->GetNumberOfScalarComponents();
+  int np2=targ->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc2=targ->GetNumberOfScalarComponents();
+
+  if (np1!=np2)
+    return 0;
+  
+  if (component1<0 || component1>=nc1)
+    component1=0;
+
+  if (component2<0 || component2>=nc2)
+    component2=0;
+
+  if (this->AreBothImagesShort(ref,targ)==1)
+    {
+      short *img1 = (short*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *img2 = (short*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+
+      if (reset)
+	this->Reset();
+
+      img1+=component1;
+      img2+=component2;
+
+      for (int i=0;i<np1;i++)
+	{
+	  this->AddToBin(*img1,*img2);
+	  img1+=nc1;
+	  img2+=nc2;
+	}
+    }
+  else
+    {
+      vtkDataArray* img1 =  ref->GetPointData()->GetScalars();
+      vtkDataArray* img2 =  targ->GetPointData()->GetScalars();
+      
+      if (reset)
+	this->Reset();
+
+      for (int i=0;i<np1;i++)
+	{
+	  short a1=(short)img1->GetComponent(i,component1);
+	  short a2=(short)img2->GetComponent(i,component2);
+	  this->AddToBin(a1,a2);
+	}
+    }
+
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxJointHistogram::RemoveFromHistogramComponent(vtkImageData* ref,vtkImageData* targ,int component1,int component2)
+{
+  int np1= ref->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc1= ref->GetNumberOfScalarComponents();
+  int np2= targ->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nc2= targ->GetNumberOfScalarComponents();
+
+  if (np1!=np2)
+    return 0;
+
+  if (component1<0 || component1>=nc1)
+    component1=0;
+
+  if (component2<0 || component2>=nc2)
+    component2=0;
+
+
+  if (this->AreBothImagesShort(ref,targ)==1)
+    {
+      short *img1 = (short*)  ref->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *img2 = (short*) targ->GetPointData()->GetScalars()->GetVoidPointer(0);
+
+      img1+=component1;
+      img2+=component2;
+      
+      for (int i=0;i<np1;i++)
+	{
+	  this->DelToBin(*img1,*img2);
+	  img1+=nc1;
+	  img2+=nc2;
+	}
+    }
+  else
+    {
+      vtkDataArray* img1 =  ref->GetPointData()->GetScalars();
+      vtkDataArray* img2 =  targ->GetPointData()->GetScalars();
+      
+      for (int i=0;i<np1;i++)
+	{
+	      short a1=(short)img1->GetComponent(i,component1);
+	      short a2=(short)img2->GetComponent(i,component2);
+	      this->DelToBin(a1,a2);
+	}
+    }
+
+  return 1;
+}
+// -------------------------------------------------------------------------------------------------------------
+void vtkpxJointHistogram::CreateHistogram(vtkImageData* ref, int numbinsref,vtkImageData* trg, int numbinstrg)
+{
+  short minr=0,maxr=1;
+  vtkImageData* img1=vtkImageData::New();
+  vtkImageData* img2=vtkImageData::New();
+
+  for (int ia=0;ia<=1;ia++)
+    {
+      vtkImageCast* cst=vtkImageCast::New();
+      cst->SetOutputScalarTypeToShort();
+      if (ia==0)
+	cst->SetInput(ref);
+      else
+	cst->SetInput(trg);
+      cst->Update();
+      
+      if (ia==0)
+	img1->ShallowCopy(cst->GetOutput());
+      else
+	img2->ShallowCopy(cst->GetOutput());
+      cst->Delete();
+    }
+
+
+  int num_ref=vtkpxRegistration::CalculateNumberOfBinsAndAdjustImage(img1,numbinsref,
+								     minr,maxr,
+								     0,1,0);
+  int num_tar=vtkpxRegistration::CalculateNumberOfBinsAndAdjustImage(img2,numbinstrg,
+								     minr,maxr,
+								     0,1,0);
+
+  fprintf(stdout,"Computing Histogram num_ref=%d, num_tar=%d\n",num_ref,num_tar);
+  this->Allocate(num_ref,num_tar);
+  this->FillHistogram(img1,img2,1);
+  img1->Delete();
+  img2->Delete();
+
+}
+
+
+void vtkpxJointHistogram::CreateDualWeightedHistogram(vtkImageData* ref, int numbinsref,vtkImageData* trg, int numbinstrg,
+							   vtkImageData* refw,vtkImageData* trgw)
+{
+  short minr=0,maxr=1;
+
+
+  vtkImageData* img[4];
+
+  for (int ia=0;ia<=3;ia++)
+    {
+      img[ia]=vtkImageData::New();
+      vtkImageCast* cst=vtkImageCast::New();
+      cst->SetOutputScalarTypeToShort();
+      if (ia==0)
+	cst->SetInput(ref);
+      else if (ia==1)
+	cst->SetInput(trg);
+      else if (ia==2)
+	cst->SetInput(refw);
+      else if (ia==3)
+	cst->SetInput(trgw);
+      cst->Update();
+      
+      img[ia]->ShallowCopy(cst->GetOutput());
+      cst->Delete();
+    }
+
+
+  int num_ref=vtkpxRegistration::CalculateNumberOfBinsAndAdjustImage(img[0],numbinsref,
+								     minr,maxr,
+								     0,1,0);
+  int num_tar=vtkpxRegistration::CalculateNumberOfBinsAndAdjustImage(img[1],numbinstrg,
+								     minr,maxr,
+								     0,1,0);
+  
+  vtkpxRegistration::ScaleWeightImage(img[2],img[0],100.0);
+  vtkpxRegistration::ScaleWeightImage(img[3],img[1],100.0);
+
+  fprintf(stdout,"Computing Weighted Histogram num_ref=%d, num_tar=%d\n",num_ref,num_tar);
+  this->Allocate(num_ref,num_tar);
+  this->DualWeightedFillHistogram(img[0],img[1],img[2],img[3],1);
+
+
+  img[0]->Delete();
+  img[1]->Delete();
+  img[2]->Delete();
+  img[3]->Delete();
+
+}
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxJointHistogram.h b/bioimagesuite30_src/Registration/vtkpxJointHistogram.h
new file mode 100644
index 0000000..2cfc139
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxJointHistogram.h
@@ -0,0 +1,282 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+
+
+
+
+#ifndef _VTKPXJOINTHISTOGRAM_2D_H
+
+#define _VTKPXJOINTHISTOGRAM_2D_H
+
+#include "vtkObject.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkpxJointHistogram : public vtkObject 
+{
+public:
+  static vtkpxJointHistogram *New();
+  vtkTypeMacro(vtkpxJointHistogram,vtkObject);
+  
+  // Description:
+  // Backup and Reset Histogram
+  virtual void ResetHistogram();
+  virtual void BackupHistogram();
+
+  // Description:
+  // Get/Set number of bins
+  vtkGetVector2Macro(NumberOfBins,int);
+  virtual int  GetNumberOfBinsX();
+  virtual int  GetNumberOfBinsY();
+
+  // Description:
+  // Clear histogram
+  virtual void Reset();
+
+  // Description:
+  // Allocate Histogram
+  virtual void Allocate(int numx,int numy);
+
+  // Description:
+  // Get number of samples in histogram
+  vtkGetMacro(NumberOfSamples,int);
+
+  // Description:
+  // Add counts to bins
+  int AddToBin(short x,short y,short count=1);
+  int AddToBin(unsigned char x,unsigned char y,unsigned char count=1);
+
+  // Description:
+  // Delete counts from bins
+  int DelToBin(short x,short y,short count=1);
+  int DelToBin(unsigned char x,unsigned char y,unsigned char count=1);
+
+
+  // Description:
+  // Fill Histogram From Images 
+  int FillHistogram(vtkImageData* ref,vtkImageData* targ,int reset);
+  int WeightedFillHistogram(vtkImageData* ref,vtkImageData* targ,vtkImageData* weights,int reset);
+  int DualWeightedFillHistogram(vtkImageData* ref,vtkImageData* targ,vtkImageData* weight1,vtkImageData* weights2,int reset);
+  int FillHistogramComponent(vtkImageData* ref,vtkImageData* targ,int component1,int component2,int reset);
+
+  // Description:
+  // Fill Histogram from Combination of Image and Intensity Gradient for Optimization
+  int FillGradientHistogram(vtkImageData* ref,vtkImageData* targ,vtkImageData* grad,double step,int component,int reset);
+
+  // This removes an original image
+  int RemoveFromHistogram(vtkImageData* ref,vtkImageData* targ);
+  int RemoveFromHistogramComponent(vtkImageData* ref,vtkImageData* targ,int component1,int component2);
+  int WeightedRemoveFromHistogram(vtkImageData* ref,vtkImageData* targ,vtkImageData* weights);
+  int DualWeightedRemoveFromHistogram(vtkImageData* ref,vtkImageData* targ,vtkImageData* weight1,vtkImageData* weights2);
+
+
+  // Description:
+  // Get Bin Count
+  int GetBinCount(int,int);
+  void SetBinCount(int a,int b,int val);
+
+  // Description:
+  // Statistics Stuff 
+  // Description:
+  // Calculate joint probability p(x, y)
+  float JointProbability(int, int);
+
+  // Description:
+  // Calculate marginal probability p(x)
+  float MarginalProbabilityX(int);
+
+  // Description:
+  // Calculate marginal probability p(y)
+  float MarginalProbabilityY(int);
+
+  // Description:
+  // Calculate conditional probability p(x|y)
+  float ConditionalProbabilityXY(int, int);
+
+  // Description:
+  // Calculate conditional probability p(y|x)
+  float ConditionalProbabilityYX(int, int);
+
+  // Description:
+  // Calculate mean
+  float MeanX();
+
+  // Description:
+  // Calculate mean
+  float MeanY();
+
+  // Description:
+  // Calculate conditional mean
+  float ConditionalMeanXY(int);
+
+  // Description:
+  // Calculate conditional mean
+  float ConditionalMeanYX(int);
+
+  // Description:
+  // Calculate variance
+  float VarianceX();
+
+  // Description:
+  // Calculate variance
+  float VarianceY();
+
+  // Description:
+  // Calculate covariance
+  float Covariance();
+
+  // Description:
+  // Calculate standard deviation
+  float StandardDeviationX();
+
+  // Description:
+  // Calculate standard deviation
+  float StandardDeviationY();
+
+  // Description:
+  // Calculate marginal entropy
+  float EntropyX();
+
+  // Description:
+  // Calculate marginal entropy
+  float EntropyY();
+
+  // Description:
+  // Calculate joint entropy
+  float JointEntropy();
+
+  // Description:
+  // Calculate mutual information
+  float MutualInformation();
+
+  // Description:
+  // Calculate normalized mutual information
+  float NormalizedMutualInformation();
+
+  // Description:
+  // Calculate cross correlation
+  float CrossCorrelation();
+
+  // Description:
+  // Calculate correlation ratio
+  float CorrelationRatioXY();
+
+  // Description:
+  // Calculate correlation ratio
+  float CorrelationRatioYX();
+
+  // Description:
+  // Calculate sums of squared differences
+  float SumsOfSquaredDifferences();
+
+  // Description:
+  // Compute Product (ala Convolution)
+  float ComputeProduct();
+
+  // Description:
+  // Compute Entropy of (y-x)
+  float ComputeEntropyOfDifference();
+
+  // Description:
+  // Compute Similarity
+  static  const char *NameOfMeasure(int measureno);
+  virtual float Similarity(int measureno);
+
+  // Description:
+  // Image Input/Output
+  virtual vtkImageData* GetHistogramAsImage();
+  virtual int   SetHistogramFromImage(vtkImageData* img);
+  
+  // Description:
+  // One Stop Shop
+  virtual void CreateHistogram(vtkImageData* ref, int numbinsref,vtkImageData* trg, int numbinstrg);
+  virtual void CreateDualWeightedHistogram(vtkImageData* ref, int numbinsref,vtkImageData* trg, int numbinstrg,
+					   vtkImageData* refw,vtkImageData* trgw);
+
+			       
+
+protected:
+  
+  // Description:
+  // Number of bins 
+  int NumberOfBins[2];
+  
+  // Description:
+  // Number of samples
+  int NumberOfSamples;
+  int OldNumberOfSamples;
+  
+  //BTX
+  // Description:
+  // Dynamic memory for bins
+  int**  Bins;
+  int**  OldBins;
+  //ETX
+
+  // Description:
+  // Copy contructor.
+  vtkpxJointHistogram();
+  vtkpxJointHistogram(const vtkpxJointHistogram &) { }
+  virtual ~vtkpxJointHistogram();
+
+
+  // Description:
+  // Check and Return
+  virtual int CheckHistogram();
+
+  // Description:
+  // Check for single frame short
+  virtual int AreBothImagesShort(vtkImageData* img1,vtkImageData* img2);
+  virtual int AreBothImagesUnsignedChar(vtkImageData* img1,vtkImageData* img2);
+  
+
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxLinearMotionCorrect.cpp b/bioimagesuite30_src/Registration/vtkpxLinearMotionCorrect.cpp
new file mode 100644
index 0000000..0da85e9
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxLinearMotionCorrect.cpp
@@ -0,0 +1,628 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxLinearMotionCorrect.cpp,v $
+  Language:  C++
+  Date:      $Date: 2003/10/16 19:43:04 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkObjectFactory.h"
+#include "vtkTransform.h"
+#include "vtkpxLinearTransform.h"
+#include "vtkpxUtil.h"
+#include "vtkpxRegistration.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkbisImageReslice.h"
+#include "vtkpxMath.h"
+#include "vtkIdentityTransform.h"
+#include "vtkpxLinearMotionCorrect.h"
+
+#ifdef BIOIMAGESUITE_EXPERIMENTAL
+#include "vtkpxImageBSplineReslice.h"
+#endif
+
+vtkpxLinearMotionCorrect* vtkpxLinearMotionCorrect::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxLinearMotionCorrect");
+  if(ret)
+    {
+      return (vtkpxLinearMotionCorrect*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxLinearMotionCorrect;
+  
+}
+
+vtkpxLinearMotionCorrect::vtkpxLinearMotionCorrect()
+{
+  this->BeginFrame=-1;
+  this->EndFrame=-1;
+  this->ReferenceFrame=-1;
+  this->RegistrationParameters=vtkDoubleArray::New();
+  this->SimilarityResults=vtkDoubleArray::New();
+  this->ReferenceMotionImage=NULL;
+  this->MotionSequence=NULL;
+  this->InitialParameters=NULL;
+  this->UseLastFrameForInitialization=1;
+  this->InterpolationMode=3;
+  this->LinearRegistration=vtkpxLinearRegistration::New();
+
+}
+//-------------------------------------------------------------------------
+vtkpxLinearMotionCorrect::~vtkpxLinearMotionCorrect()
+{
+  this->RegistrationParameters->Delete();
+  this->SimilarityResults->Delete();
+  this->SetReferenceMotionImage(NULL);
+  this->SetMotionSequence(NULL);
+  this->SetInitialParameters(NULL);
+
+  if (this->LinearRegistration)
+    this->LinearRegistration->Delete();
+}
+
+//-------------------------------------------------------------------------
+int vtkpxLinearMotionCorrect::SaveMotionParameters(vtkDoubleArray* scalars,char* fname)
+{
+  return vtkpxLinearMotionCorrect::SaveMotionParameters(scalars,fname,-1);
+}
+
+int vtkpxLinearMotionCorrect::SaveMotionParameters(vtkDoubleArray* scalars,char* fname,int nparam)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+    return 0;
+
+  fprintf(fout,"#Motion Correct Parameters\n");
+  int nt=scalars->GetNumberOfTuples();
+  int nc=scalars->GetNumberOfComponents();
+  if (nparam>0 && nparam<nc)
+    nc=nparam;
+  fprintf(fout,"#Frames\n#%d\n#Components\n#%d\n",nt,nc);
+  fprintf(fout,"#Actual Parameters\n");
+
+  for (int i=0;i<nt;i++)
+    {
+      int count=0;
+      fprintf(fout,"%d\t",i);
+      for (int j=0;j<nc;j++)
+	{
+	  fprintf(fout,"%.4f ",scalars->GetComponent(i,j));
+	  ++count;
+	  if (count>=6 && j!=nc-1)
+	    {
+	      fprintf(fout,"\n\t");
+	      count=0;
+	    }
+	}
+      fprintf(fout,"\n");
+    }
+  fclose(fout);
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxLinearMotionCorrect::InitializeMotionParameters(vtkDoubleArray* scalars,int numframes)
+{
+  if (numframes<0 || numframes>2000 || scalars==NULL)
+    return 0;
+
+  vtkpxLinearTransform* InitialTransform=vtkpxLinearTransform::New();
+  InitialTransform->Identity();
+  scalars->SetNumberOfComponents(InitialTransform->GetNumberOfParameters());
+  scalars->SetNumberOfTuples(numframes);
+
+  for (int i=0;i<numframes;i++)
+    InitialTransform->GetParameters(scalars,i);
+
+  InitialTransform->Delete();
+  return 1;
+}
+
+//-------------------------------------------------------------------------
+int vtkpxLinearMotionCorrect::LoadMotionParameters(vtkDoubleArray* scalars,char* fname)
+{
+  char pxtk_buffer[500];
+
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  gzgets(fin,pxtk_buffer,100);
+ 
+  if (gzfindstringinstring(pxtk_buffer,"#Motion Correct Parameters")==0)
+    {
+      gzclose(fin);
+      return 0;
+    }
+
+  int nc,nt;
+  gzgets(fin,pxtk_buffer,200);   gzgets(fin,pxtk_buffer,200);  sscanf(pxtk_buffer,"#%d",&nt);
+  gzgets(fin,pxtk_buffer,200);  gzgets(fin,pxtk_buffer,200);   sscanf(pxtk_buffer,"#%d",&nc);
+  scalars->SetNumberOfComponents(nc);
+  scalars->SetNumberOfTuples(nt);
+  gzgets(fin,pxtk_buffer,200);
+
+  for (int i=0;i<nt;i++)
+    {
+      int tmp,index=0;
+      float ftmp[6];
+      while (index<nc)
+	{
+	  gzgets(fin,pxtk_buffer,200);
+	  int n=0;
+	  if (index==0)
+	    n=sscanf(pxtk_buffer,"%d %f %f %f %f %f %f",&tmp,
+		     &ftmp[0],&ftmp[1],&ftmp[2],
+		     &ftmp[3],&ftmp[4],&ftmp[5])-1;
+	  else
+	    n=sscanf(pxtk_buffer,"%f %f %f %f %f %f",
+		     &ftmp[0],&ftmp[1],&ftmp[2],
+		     &ftmp[3],&ftmp[4],&ftmp[5]);
+
+	  for (int j=index;j<index+n;j++)
+	    scalars->SetComponent(i,j,ftmp[j-index]);
+	  index+=n;
+	}
+    }
+  gzclose(fin);
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxLinearMotionCorrect::MotionCorrectSequence(vtkImageData* Reference,
+						    vtkImageData* Output,vtkImageData* Input,
+						    vtkDoubleArray* Parameters,int interp_mode)
+{
+  return vtkpxLinearMotionCorrect::MotionCorrectSequence(Reference,Output,Input,Parameters,interp_mode,1);
+}
+
+
+int vtkpxLinearMotionCorrect::MotionCorrectSequenceMask(vtkImageData* Reference,
+							vtkImageData* Output,vtkImageData* Input,
+							vtkDoubleArray* Parameters,int interp_mode)
+{
+  return vtkpxLinearMotionCorrect::MotionCorrectSequence(Reference,Output,Input,Parameters,interp_mode,1,-300,1);
+}
+
+
+int vtkpxLinearMotionCorrect::MotionCorrectSequence(vtkImageData* Reference,
+						    vtkImageData*  Output,vtkImageData* Input,
+						    vtkDoubleArray* Parameters,int interp_mode,int center,short background,short final)
+{
+  if (Input==NULL || Output==NULL || Parameters==NULL || Reference==NULL)
+    return 0;
+
+  if (interp_mode>=0)
+    {
+      if (interp_mode==2)
+	interp_mode=1;
+      if (interp_mode>3)
+	interp_mode=3;
+    }
+  else
+    {
+      if (interp_mode==-1)
+	interp_mode=-2;
+      else if (interp_mode<-5)
+	interp_mode=-5;
+    }
+
+  int nf=Input->GetNumberOfScalarComponents();
+  if (Parameters->GetNumberOfTuples()<nf)
+    {
+      fprintf(stderr,"Insufficient Number Of Parameters nframes=%d ntuples=%d\n",nf,Parameters->GetNumberOfTuples());
+      return 0;
+    }
+
+  if (center>0)
+    {
+      vtkpxRegistration::CenterImageOrigin(Reference);
+      vtkpxRegistration::CenterImageOrigin(Input);
+    }
+
+  Output->SetSpacing(Reference->GetSpacing());
+  Output->SetDimensions(Reference->GetDimensions());
+  Output->SetOrigin(Reference->GetOrigin());
+  Output->SetScalarType(Reference->GetScalarType());
+  Output->SetExtent(Reference->GetExtent());
+  Output->SetWholeExtent(Reference->GetWholeExtent());
+  Output->SetNumberOfScalarComponents(nf);
+  Output->AllocateScalars();
+
+  vtkDataArray* outarr=Output->GetPointData()->GetScalars();
+  int nt=outarr->GetNumberOfTuples();
+
+  vtkpxLinearTransform* tr=vtkpxLinearTransform::New();
+
+  fprintf(stderr,"\t\t Reslicing frame: %d",interp_mode);
+
+  vtkbisImageReslice* resl=NULL;
+#ifdef BIOIMAGESUITE_EXPERIMENTAL
+  vtkpxImageBSplineReslice* bresl=NULL;
+#endif
+  int max_count=nf/10;
+  int count=0;
+
+  for (int frame=0;frame<nf;frame++)
+    {
+      ++count;
+      if (count==max_count)
+	{
+	  fprintf(stderr," %d",frame+1);
+	  count=0;
+	}
+      tr->SetParameters(Parameters,frame);
+      vtkDataArray* inarr=NULL;
+
+#ifdef BIOIMAGESUITE_EXPERIMENTAL
+      if (interp_mode>=0)
+	{
+#endif
+	  if (interp_mode<0 || interp_mode>1)
+	    interp_mode=3;
+
+
+	  vtkImageExtractComponents* extr=vtkImageExtractComponents::New();
+	  extr->SetInput(Input);
+	  extr->SetComponents(frame);
+	  
+	  resl=vtkbisImageReslice::New();    resl->OptimizationOff();
+	  resl->SetInput(extr->GetOutput());
+	  resl->SetInformationInput(Reference);
+	  resl->SetResliceTransform(tr);
+	  resl->SetInterpolationMode(interp_mode);
+	  resl->SetBackgroundLevel(background);
+	  resl->Update();
+	  inarr=resl->GetOutput()->GetPointData()->GetScalars();
+	  extr->Delete();
+#ifdef BIOIMAGESUITE_EXPERIMENTAL
+	}
+      else 
+	{
+	  bresl=vtkpxImageBSplineReslice::New();
+
+	  bresl->SetInput(Input);
+	  bresl->SetInformationInput(Reference);
+	  bresl->SetComponent(frame);
+	  bresl->SetResliceTransform(tr);
+	  bresl->SetSplineDegree(abs(interp_mode));
+	  //bresl->SetBackgroundLevel(-1);
+	  bresl->Update();
+	  inarr=bresl->GetOutput()->GetPointData()->GetScalars();
+	}
+#endif
+
+      outarr->CopyComponent(frame,inarr,0);
+      double range[2]; outarr->GetRange(range,frame);
+      //      fprintf(stderr,"(%.2f %.2f)",range[0],range[1]);
+
+#ifdef BIOIMAGESUITE_EXPERIMENTAL
+      if (resl!=NULL)
+	{
+#endif
+	  resl->Delete();
+	  resl=NULL;
+#ifdef BIOIMAGESUITE_EXPERIMENTAL
+	}
+      else
+	{
+
+	  bresl->Delete();
+	  bresl=NULL;
+	}
+#endif
+    }
+
+  if (final==1)
+    {
+      fprintf(stderr,"Clearing Image %d\n",background);
+      int nt=outarr->GetNumberOfTuples();
+      int nc=outarr->GetNumberOfComponents();
+
+      for (int voxel=0;voxel<nt;voxel++)
+	{
+	  int ok=1;
+	  int frame=0;
+	  while (frame<nc && ok==1)
+	    {
+	      if (outarr->GetComponent(voxel,frame)==background)
+		ok=0;
+	      ++frame;
+	    }
+	  
+	  if (ok==0)
+	    for (int i=0;i<nc;i++)
+	      outarr->SetComponent(voxel,i,0);
+	}
+    }
+
+  fprintf(stderr,"\n");
+  tr->Delete();
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxLinearMotionCorrect::CheckInputs()
+{
+  if (this->ReferenceMotionImage==NULL || this->MotionSequence==NULL)
+    {
+      vtkErrorMacro(<<"No Reference Image or Motion Sequence Specified\n");
+      return 0;
+    }
+
+  int nf=this->MotionSequence->GetNumberOfScalarComponents();
+  int rf=this->ReferenceMotionImage->GetNumberOfScalarComponents();
+
+  this->BeginFrame=Irange(this->BeginFrame,0,nf-1);
+
+  if (this->EndFrame==-1)
+    this->EndFrame=nf-1;
+  else
+    this->EndFrame=Irange(this->EndFrame,this->BeginFrame,nf-1);
+
+  this->ReferenceFrame=Irange(this->ReferenceFrame,0,rf-1);
+  
+  return nf;
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearMotionCorrect::RunSingleFrame(vtkImageData* ref,vtkImageData* sequence,int frame,vtkpxLinearTransform* initial)
+{
+
+  //  this->LinearRegistration->DebugOn();
+  this->LinearRegistration->SetReferenceImage(ref,0);
+  this->LinearRegistration->SetReferenceOrientation(this->ReferenceOrientation);
+  this->LinearRegistration->SetTransformImage(sequence,frame);
+  this->LinearRegistration->SetTransformOrientation(this->TransformOrientation);
+  this->LinearRegistration->SetInitialTransform(initial);
+  this->LinearRegistration->SetReferenceWeightImage(this->ReferenceWeightImage);
+  this->LinearRegistration->SetTransformWeightImage(this->TransformWeightImage);
+
+  this->LinearRegistration->SetInterpolationMode(this->InterpolationMode);
+  this->LinearRegistration->SetPositiveIntensitiesOnly(this->PositiveIntensitiesOnly);
+  this->LinearRegistration->SetAutoNormalizeIntensities(this->AutoNormalizeIntensities);
+  this->LinearRegistration->SetJointlyNormalizeIntensities(this->JointlyNormalizeIntensities);
+
+  this->LinearRegistration->SetNumberOfLevels(this->NumberOfLevels);
+  this->LinearRegistration->SetNumberOfBins(this->NumberOfBins);
+  this->LinearRegistration->SetNumberOfIterations(this->NumberOfIterations);
+  this->LinearRegistration->SetNumberOfSteps(this->NumberOfSteps);
+  this->LinearRegistration->SetResolution(this->Resolution);
+  this->LinearRegistration->SetBlurFactor(this->BlurFactor);
+  this->LinearRegistration->SetStepSize(this->StepSize);
+  this->LinearRegistration->SetSimilarityMeasure(this->SimilarityMeasure);
+  this->LinearRegistration->SetOptimizationMethod(this->OptimizationMethod);
+  this->LinearRegistration->SetAutoCenterOrigin(this->AutoCenterOrigin);
+  this->LinearRegistration->SetTransformModeToRigid();
+
+  this->LinearRegistration->Run();
+  //  this->LinearRegistration->DebugOff();
+  this->SimilarityResults->SetComponent(frame,0,this->LinearRegistration->GetLastSimilarity());
+  this->LinearRegistration->GetLinearTransform()->GetParameters(this->RegistrationParameters,frame);
+
+  if (this->UseLastFrameForInitialization)
+    initial->Copy(this->LinearRegistration->GetLinearTransform());
+
+  fprintf(stderr,"Done With Frame %d\n",frame);
+
+  return;
+
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearMotionCorrect::Run()
+{
+  int nf=this->CheckInputs();
+  if (nf==0)
+    {
+      vtkErrorMacro(<<"Bad Inputs");
+      return;
+    }
+
+  this->AutoCenterOriginOff();
+  vtkpxRegistration::CenterImageOrigin(this->ReferenceMotionImage);
+  vtkpxRegistration::CenterImageOrigin(this->MotionSequence);
+
+  this->InitialTransform=vtkpxLinearTransform::New();
+  this->InitialTransform->Identity();
+  if (this->InitialParameters!=NULL)
+    this->InitialTransform->SetParameters(this->InitialParameters,0);
+    
+  int   lv=this->GetNumberOfLevels();
+  this->RegistrationParameters->SetNumberOfComponents(this->InitialTransform->GetNumberOfParameters());
+  this->RegistrationParameters->SetNumberOfTuples(nf);
+
+  this->SimilarityResults->SetNumberOfComponents(1);
+  this->SimilarityResults->SetNumberOfTuples(nf);
+  this->SimilarityResults->FillComponent(0,0.0);
+
+  for (int i=0;i<nf;i++)
+    this->InitialTransform->GetParameters(this->RegistrationParameters,i);
+
+  vtkDebugMacro(<< "\n Using Previous frame = " << this->UseLastFrameForInitialization );
+
+  vtkImageData* refimg=vtkImageData::New();
+  vtkImageExtractComponents* extr=vtkImageExtractComponents::New();
+
+  extr->SetInput(this->ReferenceMotionImage);
+  extr->SetComponents(this->ReferenceFrame);
+  extr->Update();
+  refimg->ShallowCopy(extr->GetOutput());
+  extr->Delete();
+
+  for (int frame=this->BeginFrame;frame<=this->EndFrame;frame++)
+    {
+      vtkDebugMacro(<<"----------------------------------------------------------------");
+      vtkDebugMacro(<<"Beginning Frame "<< frame);
+
+      fprintf(stderr,"----------------------------------------------------------------\n");
+      fprintf(stderr," Beginning Frame  %d\n",frame);
+
+      
+      if (this->UseLastFrameForInitialization)
+	{
+	  fprintf(stderr,"Using Last Frame\n");
+	  if (frame!=this->BeginFrame && this->UseLastFrameForInitialization==1)
+	    {
+	      if (this->NumberOfLevels>2)
+		this->SetNumberOfLevels(2);
+	    }
+	} 
+      else if (this->InitialParameters!=NULL)
+	{
+	  if (this->InitialParameters->GetNumberOfTuples()>=this->RegistrationParameters->GetNumberOfTuples())
+	    {
+	      fprintf(stderr,"\n\n*** Using True Initial Parameters -*-*\n\n");
+	      this->InitialTransform->SetParameters(this->InitialParameters,frame);
+	    }
+	  else
+	    fprintf(stderr,"Using Nothing\n");
+	}
+	  
+      this->RunSingleFrame(refimg,this->MotionSequence,frame,this->InitialTransform);
+    }
+  vtkDebugMacro(<<"Done All");
+  this->SetNumberOfLevels(lv);
+
+  refimg->Delete();
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearMotionCorrect::ComputeAllSimilarityMetricsBetweenImages(vtkImageData* reference,int frame,
+									vtkImageData* series,
+									vtkDoubleArray* results)
+{
+  if (results==NULL || reference == NULL || series==NULL)
+    return;
+
+  int numframes=series->GetNumberOfScalarComponents();
+
+  results->SetNumberOfComponents(5);
+  results->SetNumberOfTuples(numframes);
+
+  double resolution[3];
+  reference->GetSpacing(resolution);
+  
+  float sigma=0.0;
+  
+  int interpolation=1;
+  int numbins=64;
+
+  // Generate Reference Image 
+  vtkImageData* ref=vtkImageData::New();
+  vtkImageExtractComponents* extr1=vtkImageExtractComponents::New();
+
+  extr1->SetInput(reference);
+  extr1->SetComponents(frame);
+  extr1->Update();
+  vtkpxRegistration::ResampleAndSmoothImage(ref,extr1->GetOutput(),resolution,sigma,1.0);
+  extr1->Delete();
+  short minr=0,maxr=1; 
+  int num_ref=vtkpxRegistration::CalculateNumberOfBinsAndAdjustImage(ref,numbins,minr,maxr,0);
+
+  // On to Series 
+  vtkImageData* trn=vtkImageData::New();
+  vtkImageExtractComponents* extr2=vtkImageExtractComponents::New();
+
+  extr2->SetInput(series);
+
+  vtkIdentityTransform* tr=vtkIdentityTransform::New();
+
+  for (int fr=0;fr<numframes;fr++)
+    {
+      fprintf(stderr,"Computing for frame %d\n",fr);
+      extr2->SetComponents(fr);
+      extr2->Update();
+      vtkpxRegistration::ResampleAndSmoothImage(trn,extr2->GetOutput(),
+						resolution,sigma,1.0);
+      short mint=0,maxt=1;
+      int num_tar=vtkpxRegistration::CalculateNumberOfBinsAndAdjustImage(trn,numbins,mint,maxt,0);
+      vtkpxJointHistogram* Histogram=vtkpxJointHistogram::New();
+      Histogram->Allocate(num_ref,num_tar);
+
+      vtkImageData* tmp=vtkImageData::New();
+      vtkpxRegistration::ResliceImage(tmp,trn,ref,tr,interpolation);
+
+      Histogram->FillHistogram(ref,tmp,1);
+      
+      for (int metric=1;metric<=5;metric++)
+	{
+	  double val=0.0;
+	  switch (metric) 
+	    {
+	    case 1:
+	      val= +Histogram->CrossCorrelation();
+	      break;
+	    case 2:
+	      val= +Histogram->MutualInformation();
+	      break;
+	    case 3:
+	      val= +Histogram->NormalizedMutualInformation();
+	      break;
+	    case 4:
+	      val= -Histogram->SumsOfSquaredDifferences() / 
+		(double)Histogram->GetNumberOfSamples();
+	      break;
+	    case 5:
+	      val= Histogram->ComputeEntropyOfDifference();
+	      break;
+	    }
+	  results->SetComponent(fr,metric-1,val);
+	}
+      tmp->Delete();
+      Histogram->Delete();
+
+    }
+  tr->Delete();
+  trn->Delete();
+  extr2->Delete();
+  ref->Delete();
+  return;
+}
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxLinearMotionCorrect.h b/bioimagesuite30_src/Registration/vtkpxLinearMotionCorrect.h
new file mode 100644
index 0000000..c0a948e
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxLinearMotionCorrect.h
@@ -0,0 +1,203 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSurfaceUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+// .NAME vtkpxLinearMotionCorrect - Filter for affine registration based on voxel similarity measures
+// .SECTION Description
+// This class implements a registration filter for the affine registration
+// of images. The basic algorithm is described in Studholme, Medical Image
+// Analysis, Vol. 1, No. 2, 1996.
+//
+// developed by the Computational Imaging Science Group, KCL <www-ipg.umds.ac.uk>
+//
+
+#ifndef _VTKPXLINEARMOTIONCORRECT_H
+#define _VTKPXLINEARMOTIONCORRECT_H
+
+#include "vtkpxLinearRegistration.h"
+#include "vtkpxLinearTransform.h"
+
+
+class vtkpxLinearMotionCorrect : public vtkpxLinearRegistration {
+
+public:
+  static vtkpxLinearMotionCorrect* New();
+  vtkTypeMacro(vtkpxLinearMotionCorrect,vtkpxLinearRegistration);
+
+  // Description:
+  // Return Final Set of Registration Parameters
+  vtkGetObjectMacro(RegistrationParameters,vtkDoubleArray);
+  vtkGetObjectMacro(SimilarityResults,vtkDoubleArray);
+
+  // Description:
+  // Return Final Set of Registration Parameters
+  vtkGetObjectMacro(InitialParameters,vtkDoubleArray);
+  vtkSetObjectMacro(InitialParameters,vtkDoubleArray);
+
+  // Description:
+  // Sets referenceimage for the registration filter
+  vtkSetObjectMacro(ReferenceMotionImage,vtkImageData);
+  vtkGetObjectMacro(ReferenceMotionImage,vtkImageData);
+  
+  // Description:
+  // Set Transform Image Sequence
+  vtkSetObjectMacro(MotionSequence,vtkImageData);
+  vtkGetObjectMacro(MotionSequence,vtkImageData);
+
+  // Description:
+  // Get Linear Registration 
+  vtkGetObjectMacro(LinearRegistration,vtkpxLinearRegistration);
+  
+
+  // Description:
+  // Begin Frame, End Frame, Reference Frame
+  vtkSetMacro(BeginFrame,int);
+  vtkGetMacro(BeginFrame,int);
+  vtkGetMacro(EndFrame,int);
+  vtkSetMacro(EndFrame,int);
+  vtkGetMacro(ReferenceFrame,int);
+  vtkSetMacro(ReferenceFrame,int);
+
+  // Description:
+  // UseLastFrameForInitialization
+  vtkSetClampMacro(UseLastFrameForInitialization,int,0,1);
+  vtkGetMacro(UseLastFrameForInitialization,int);
+  vtkBooleanMacro(UseLastFrameForInitialization,int);
+
+
+
+  // Description:
+  // Warp Output Image
+  static int MotionCorrectSequence(vtkImageData* Reference,
+				   vtkImageData* Output,vtkImageData* Input,
+				   vtkDoubleArray* Parameters,int interp_mode);
+
+  static int MotionCorrectSequenceMask(vtkImageData* Reference,
+				       vtkImageData* Output,vtkImageData* Input,
+				       vtkDoubleArray* Parameters,int interp_mode);
+
+
+  static int MotionCorrectSequence(vtkImageData* Reference,
+				   vtkImageData* Output,vtkImageData* Input,
+				   vtkDoubleArray* Parameters,int interp_mode,int center,short background=-100,short final=0);
+
+
+  // Description:
+  // Save/Load Motion Parameters (Scalars)
+  static int SaveMotionParameters(vtkDoubleArray* scalars,char* fname);
+  static int SaveMotionParameters(vtkDoubleArray* scalars,char* fname,int nparam);
+  static int LoadMotionParameters(vtkDoubleArray* scalars,char* fname);
+  static int InitializeMotionParameters(vtkDoubleArray* scalars,int numframes);
+
+  // Description:
+  // Run Motion Correction
+  virtual void Run();
+
+  
+  // Description:
+  // Compute All Similarity Metrics Between Images After Reslicing
+  static void ComputeAllSimilarityMetricsBetweenImages(vtkImageData* reference,int frame,
+						       vtkImageData* series,
+						       vtkDoubleArray* results);
+
+
+
+protected:
+  // Make all these protected 
+  // Constructor
+  vtkpxLinearMotionCorrect();
+  virtual ~vtkpxLinearMotionCorrect();
+  vtkpxLinearMotionCorrect(const vtkpxLinearMotionCorrect&) {};
+  void operator=(const vtkpxLinearMotionCorrect&) {};
+
+  // Description:
+  // Reference Image
+  vtkImageData*                ReferenceMotionImage;
+  vtkImageData*                MotionSequence;
+
+  // Description:
+  // Registration Parameters
+  vtkDoubleArray*               RegistrationParameters;
+  vtkDoubleArray*               SimilarityResults;
+
+  // Description:
+  // Initial Parameters
+  vtkDoubleArray*               InitialParameters;
+
+  // Description:
+  // Use this to do actual registration
+  vtkpxLinearRegistration*      LinearRegistration;
+
+  // Descriptions:
+  // Various Flags
+  int BeginFrame;
+  int EndFrame;
+  int ReferenceFrame;
+  int UseLastFrameForInitialization;
+  int ComputeRegistrationExtra;
+
+
+  // Description:
+  // Check Inputs
+  virtual int  CheckInputs();
+
+  // Description:
+  // Run Single Frame
+  virtual void RunSingleFrame(vtkImageData* ref,vtkImageData* sequence,int frame,vtkpxLinearTransform* initial);
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxLinearRPMRegistration.cpp b/bioimagesuite30_src/Registration/vtkpxLinearRPMRegistration.cpp
new file mode 100644
index 0000000..1a81cfc
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxLinearRPMRegistration.cpp
@@ -0,0 +1,241 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxRPMTransform.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/03/12 16:49:59 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "pxutil.h"
+#include "vtkOldStyleCallbackCommand.h"
+#include "vtkDataSet.h"
+#include "vtkpxWeightedLandmarkTransform.h"
+#include "vtkTransform.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxLinearRPMRegistration.h"
+#include "vtkpxMatrix.h"
+#include "vtkpxUtil.h"
+#include "vtkIdList.h"
+#include "vtkFloatArray.h"
+#include "vtkPointLocator.h"
+//-----------------------------------------------------------------------------------
+
+vtkpxLinearRPMRegistration* vtkpxLinearRPMRegistration::New()
+{
+  // First try to create the object from the vtkObjectFactory
+
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxLinearRPMRegistration");
+  if(ret)
+    {
+    return (vtkpxLinearRPMRegistration*)ret;
+    }
+
+  // If the factory was unable to create the object, then create it here.
+
+  return new vtkpxLinearRPMRegistration;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxLinearRPMRegistration::vtkpxLinearRPMRegistration()
+{
+  this->ForwardTransform = vtkTransform::New();
+  this->ForwardTransform->Identity();
+  this->TransformMode=2;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxLinearRPMRegistration::~vtkpxLinearRPMRegistration()
+{
+  this->ForwardTransform->Delete();
+}
+
+//----------------------------------------------------------------------------
+void vtkpxLinearRPMRegistration::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkpxAbstractRPMRegistration::PrintSelf(os,indent);
+  os << indent << "TransformMode:  " << this->TransformMode << "\n";
+  os << indent << "Transformation: " << this->ForwardTransform << "\n";
+}
+
+//----------------------------------------------------------------------------
+vtkAbstractTransform* vtkpxLinearRPMRegistration::GetCurrentTransformation()
+{
+  return this->ForwardTransform;
+}
+//----------------------------------------------------------------------------
+// Transformation Stuff
+//----------------------------------------------------------------------------
+void vtkpxLinearRPMRegistration::GenerateTransformation(vtkTransform* transform,
+							vtkpxMatrix* x,vtkpxMatrix* vy,int mode,vtkpxMatrix* weights,
+							vtkpxMatrix* labels)
+{
+  vtkPoints* ptx=this->CreatePointsFromMatrix(x);
+  vtkPoints* pty=this->CreatePointsFromMatrix(vy);
+
+  vtkpxWeightedLandmarkTransform* tr=vtkpxWeightedLandmarkTransform::New();
+  tr->SetSourceLandmarks(ptx);
+  tr->SetTargetLandmarks(pty);
+  tr->SetWeights(weights);
+  if (mode==0)
+    tr->SetModeToRigidBody();
+  else if (mode==1)
+    tr->SetModeToSimilarity(); 
+  else
+    tr->SetModeToAffine();
+
+  tr->Modified();
+  tr->Update();
+    
+  transform->Identity();
+  transform->PostMultiply();
+  transform->Concatenate(tr);
+
+  tr->Delete();
+  ptx->Delete();
+  pty->Delete();
+}
+
+//----------------------------------------------------------------------------
+// Description:
+// Annealing Procedure
+//----------------------------------------------------------------------------
+void vtkpxLinearRPMRegistration::Anneal()
+{
+  int perT_maxit=5;
+  float anneal_rate=this->AnnealRate;
+
+  float T,T_final;
+  // Initialize Temperature Stuff 
+  T      =Frange(this->InitialTemperature,0.1,500);
+  T_final=Frange(this->FinalTemperature,0.01,T);
+  
+
+  float totaliter=fabs(log(T/T_final)/log(anneal_rate))+1.0;
+
+  fprintf(stderr,"T=%f, T_final=%f totaliter=%.0f anneal_rate=%.3f (orig=%.2f:%.2f)\n",T,T_final,totaliter,anneal_rate,
+	  this->InitialTemperature,this->FinalTemperature);
+
+  this->Initialize(NULL);
+
+  // Centroid Initialization:
+  double sumx[3] = { 0.0,0.0,0.0};
+  double sumy[3] = { 0.0,0.0,0.0};
+  int sz[2],nump_x,nump_y;
+  VX->GetSize(sz);   nump_x=sz[0];
+  Y->GetSize(sz);   nump_y=sz[0];
+  for (int i=0;i<nump_x;i++)
+    for (int ia=0;ia<3;ia++)
+      sumx[ia]+=VX->GetDirectElement(i,ia);
+  
+  for (int i=0;i<nump_y;i++)
+    for (int ia=0;ia<3;ia++)
+      sumy[ia]+=Y->GetDirectElement(i,ia);
+
+  double shift[3];
+  for (int ia=0;ia<3;ia++)
+    {
+      sumx[ia]/=double(nump_x);
+      sumy[ia]/=double(nump_y);
+      shift[ia]=sumy[ia]-sumx[ia];
+    }
+
+  fprintf(stderr,"\t\t Linear Initialization ::: Initial Shifts = (%.1f,%.1f,%.1f)\n",shift[0],shift[1],shift[2]);
+
+  for (int i=0;i<nump_x;i++)
+    for (int ia=0;ia<3;ia++)
+      VX->SetDirectElement(i,ia,VX->GetDirectElement(i,ia)+shift[ia]);
+
+  // Annealing Procedure 
+  int flag_stop=0;
+  int iter=1;
+
+  perT_maxit=1;
+
+  while (flag_stop == 0 )
+    {
+      for (int i=1;i<=perT_maxit;i++)
+	{
+	  if (this->AbortExecute>0)
+	    {
+	      i=perT_maxit+1;
+	    }
+	  else
+	    {
+	      this->UpdateCorrespondence(M,M_Outliers_Row,M_Outliers_Column,
+					 VX,Y,VY,T,this->Locator,LX,LY);
+	      this->GenerateTransformation(this->ForwardTransform,X,VY,this->TransformMode,M_Outliers_Column,LX);
+	      this->TransformPoints(this->ForwardTransform,X,VX);
+	    }
+	}
+
+      vtkDebugMacro(<<"\n----------------------------------------------------------\nIteration " << iter << "/" << totaliter << " T = " << T << ", abort= " << this->AbortExecute << "\n");
+
+
+      this->UpdateProgress(float(iter)/totaliter);
+      iter++;
+      T=T*anneal_rate;
+      if (T<T_final || this->AbortExecute>0)
+	flag_stop=1;
+    }
+  
+  this->InvokeEvent(vtkCommand::EndEvent,NULL);
+  this->UpdateVYPoints();
+
+  
+}
+//----------------------------------------------------------------------------
+
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxLinearRPMRegistration.h b/bioimagesuite30_src/Registration/vtkpxLinearRPMRegistration.h
new file mode 100644
index 0000000..809bdc9
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxLinearRPMRegistration.h
@@ -0,0 +1,107 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxLinearRPMRegistration.h,v $
+  Language:  C++
+  Date:      $Date: 2002/03/12 16:50:35 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#ifndef __vtkpxLinearRPMRegistration_h
+#define __vtkpxLinearRPMRegistration_h
+
+#include "vtkTransform.h"
+#include "vtkpxAbstractRPMRegistration.h"
+
+class vtkpxLinearRPMRegistration : public vtkpxAbstractRPMRegistration
+{
+public:
+  static vtkpxLinearRPMRegistration *New();
+  vtkTypeMacro(vtkpxLinearRPMRegistration,vtkpxAbstractRPMRegistration);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Get Current Transformation -- needed for displaying updates 
+  virtual vtkAbstractTransform* GetCurrentTransformation();
+
+  // Description:
+  // Set the current mode 0=Rigid, 1=Similarity 2=Affine 
+  vtkSetClampMacro(TransformMode,int,0,2);
+  vtkGetMacro(TransformMode,int);
+
+  // Description:
+  // Dedicated Set/Get TransformMode stuff 
+  virtual void SetTransformModeToRigid()      { this->SetTransformMode(0);}
+  virtual void SetTransformModeToSimilarity() { this->SetTransformMode(1);}
+  virtual void SetTransformModeToAffine()     { this->SetTransformMode(2);}
+
+protected:
+  // Description:
+  
+  vtkpxLinearRPMRegistration();
+  ~vtkpxLinearRPMRegistration();
+  vtkpxLinearRPMRegistration(const vtkpxLinearRPMRegistration&) {};
+  void operator=(const vtkpxLinearRPMRegistration&) {};
+
+  vtkTransform *ForwardTransform;
+  int TransformMode;
+
+  // Description:
+  // Annealing Routines both one-way and symmetric
+  virtual void Anneal();
+
+  // Description:
+  // Generate Transformation Details 
+  virtual void GenerateTransformation(vtkTransform* transform,vtkpxMatrix* x,vtkpxMatrix* vy,int mode,vtkpxMatrix* weights=NULL,vtkpxMatrix* labels=NULL);
+  
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxLinearRegistration.cpp b/bioimagesuite30_src/Registration/vtkpxLinearRegistration.cpp
new file mode 100644
index 0000000..411ceaf
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxLinearRegistration.cpp
@@ -0,0 +1,686 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+
+/*=========================================================================*/
+#include "vtkpxLinearRegistration.h"
+#include "vtkpxRegistration.h"
+#include "vtkObjectFactory.h"
+#include "vtkTransform.h"
+#include "vtkpxUtil.h"
+#include "vtkpxOptimizer.h"
+#include "vtkShortArray.h"
+
+vtkpxLinearRegistration* vtkpxLinearRegistration::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxLinearRegistration");
+  if(ret)
+    {
+      return (vtkpxLinearRegistration*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxLinearRegistration;
+  
+}
+
+vtkpxLinearRegistration::vtkpxLinearRegistration()
+{
+
+  DofStatus=vtkShortArray::New();
+  DofStatus->SetNumberOfTuples(15);
+  for (int i=0; i<15; i++) 
+    {
+      DofStatus->SetComponent(i,0,1);
+      DofWeight[i]=0.0;
+    }
+  
+  this->SetTransformModeToAffine();
+  this->LinearTransform=NULL;
+  this->UpdateTransform=vtkTransform::New();
+  this->InitialTransform=NULL;
+  this->AutoCenterOrigin=1;
+  this->TransformOutputMode=0;
+  this->DistortionMode=0;
+  this->OptimizationAutoScale=1;
+  this->OptimizationScaleFactor=1.0;
+
+}
+//-------------------------------------------------------------------------
+vtkpxLinearRegistration::~vtkpxLinearRegistration()
+{
+  if (this->LinearTransform!=NULL)
+    {
+      this->LinearTransform->Delete();
+      this->LinearTransform=NULL;
+    }
+  if (this->UpdateTransform!=NULL)
+    {
+      this->UpdateTransform->Delete();
+      this->UpdateTransform=NULL;
+    }
+
+  this->SetInitialTransform(NULL);
+  this->DofStatus->Delete();
+}
+
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::SetTransformModeToRigid()
+{
+  TranslationX=1;	TranslationY=1; 	TranslationZ=1;
+  RotationX=1;	RotationZ=1; 	RotationY=1;
+  ScalingX=0; 	ScalingY=0;	ScalingZ=0;
+  ShearingXY=0;	ShearingYX=0;	ShearingYZ=0;
+  ShearingZY=0;	ShearingZX=0;	ShearingXZ=0;
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::SetTransformModeToDistortion()
+{
+  TranslationX=1;	TranslationY=1; 	TranslationZ=1;
+  RotationX=1;	RotationZ=1; 	RotationY=1;
+  ScalingX=0; 	ScalingY=1;	ScalingZ=0;
+  ShearingXY=0;	ShearingYX=0;	ShearingYZ=0;
+  ShearingZY=0;	ShearingZX=0;	ShearingXZ=0;
+  this->DistortionMode=1;
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::SetTransformModeToSimilarity()
+{
+  TranslationX=1;	TranslationY=1; 	TranslationZ=1;
+  RotationX=1;	RotationZ=1; 	RotationY=1;
+  ScalingX=1; 	ScalingY=1;	ScalingZ=1;
+  ShearingXY=0;	ShearingYX=0;	ShearingYZ=0;
+  ShearingZY=0;	ShearingZX=0;	ShearingXZ=0;
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::SetTransformModeToAffine()
+{
+  TranslationX=1;	TranslationY=1; 	TranslationZ=1;
+  RotationX=1;	RotationZ=1; 	RotationY=1;
+  ScalingX=1; 	ScalingY=1;	ScalingZ=1;
+  ShearingXY=1;	ShearingYX=1;	ShearingYZ=1;
+  ShearingZY=1;	ShearingZX=1;	ShearingXZ=1;
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::SetTransformModeToRigid2D()
+{
+  TranslationX=1;	TranslationY=1; 	TranslationZ=0;
+  RotationX=0;	RotationZ=1; 	RotationY=0;
+  ScalingX=0; 	ScalingY=0;	ScalingZ=0;
+  ShearingXY=0;	ShearingYX=0;	ShearingYZ=0;
+  ShearingZY=0;	ShearingZX=0;	ShearingXZ=0;
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::SetTransformModeToSimilarity2D()
+{
+  TranslationX=1;	TranslationY=1; 	TranslationZ=0;
+  RotationX=0;	RotationZ=1; 	RotationY=0;
+  ScalingX=1; 	ScalingY=1;	ScalingZ=0;
+  ShearingXY=0;	ShearingYX=0;	ShearingYZ=0;
+  ShearingZY=0;	ShearingZX=0;	ShearingXZ=0;
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::SetTransformModeToAffine2D()
+{
+  TranslationX=1;	TranslationY=1; 	TranslationZ=0;
+  RotationX=0;	RotationZ=1; 	RotationY=0;
+  ScalingX=1; 	ScalingY=1;	ScalingZ=0;
+  ShearingXY=1;	ShearingYX=1;	ShearingYZ=0;
+  ShearingZY=0;	ShearingZX=0;	ShearingXZ=0;
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::UpdateDofLabels()
+{
+  this->DofStatus->SetComponent(0,0,TranslationX);
+  this->DofStatus->SetComponent(1,0,TranslationY); 
+  this->DofStatus->SetComponent(2,0,TranslationZ); 
+  this->DofStatus->SetComponent(3,0,RotationX); 
+  this->DofStatus->SetComponent(4,0,RotationY); 
+  this->DofStatus->SetComponent(5,0,RotationZ); 
+  this->DofStatus->SetComponent(6,0,ScalingX); 
+  this->DofStatus->SetComponent(7,0,ScalingY); 
+  this->DofStatus->SetComponent(8,0,ScalingZ); 
+  this->DofStatus->SetComponent(9,0,ShearingXY); 
+  this->DofStatus->SetComponent(10,0,ShearingYX); 
+  this->DofStatus->SetComponent(11,0,ShearingYZ); 
+  this->DofStatus->SetComponent(12,0,ShearingZY); 
+  this->DofStatus->SetComponent(13,0,ShearingZX); 
+  this->DofStatus->SetComponent(14,0,ShearingXZ); 
+}
+
+int vtkpxLinearRegistration::GetDofStatus(int dof)
+{
+  return (int)DofStatus->GetComponent(dof,0);
+}
+
+int vtkpxLinearRegistration::InitializeAll() 
+{
+  vtkpxAbstractIntensityRegistration::InitializeAll();
+  UpdateDofLabels();
+
+  if (this->OptimizationAutoScale)
+    {
+      this->OptimizationScaleFactor=this->MeanResolution;
+    }
+  else 
+    {
+      if (this->OptimizationScaleFactor<0.001)
+	this->OptimizationScaleFactor=0.001;
+    }
+
+  fprintf(stdout,"\t\t\t OptScaleFactor=%.5f (auto=%d)\n",this->OptimizationScaleFactor,this->OptimizationAutoScale);
+
+
+  if (this->LinearTransform==NULL)
+    this->LinearTransform=vtkpxLinearTransform::New();
+  this->LinearTransform->Identity();
+
+  if (this->InitialTransform!=NULL)
+    {
+      this->LinearTransform->Copy(this->InitialTransform);
+      this->GenerateOutput(-1,-1,-1,-1,-1,-1,-1);
+    }
+  else
+    fprintf(stdout,"Not Copying any initial transform\n");
+
+  this->LinearTransform->SetDistortionMode(this->DistortionMode);  
+
+  this->GenerateOutput(-1,-1,-1,-1,-1,-1,-1);
+
+  this->TransformOutputMode=0;
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxLinearRegistration::Initialize(int level)
+{
+  vtkpxAbstractIntensityRegistration::Initialize(level); 
+
+  if (this->AutoCenterOrigin)
+    {
+      double sp1[3],sp2[3];
+      int   dim1[3],dim2[3];
+      this->SampledReferenceImage->GetSpacing(sp1);
+      this->SampledReferenceImage->GetDimensions(dim1);
+      this->SampledTransformImage->GetSpacing(sp2);
+      this->SampledTransformImage->GetDimensions(dim2);
+      
+      double or1[3],or2[3];
+      for (int ia=0;ia<=2;ia++)
+	{
+	  or1[ia]=-0.5*sp1[ia]*dim1[ia];
+	  or2[ia]=-0.5*sp2[ia]*dim2[ia];
+	}
+      
+      this->SampledReferenceImage->SetOrigin(or1);
+      this->SampledTransformImage->SetOrigin(or2);
+      
+
+      vtkpxRegistration::FixPipelineSpacingAndOrigin(this->SampledReferenceImage);
+      vtkpxRegistration::FixPipelineSpacingAndOrigin(this->SampledTransformImage);
+    }
+
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxLinearRegistration::ComputeRegistration(int level)
+{  
+  double step=this->CurrentStepSize;
+  int maxdofs=15;
+  if (level>1)
+    maxdofs=6;
+
+  int v=0;
+  for (int i=0;i<maxdofs;i++)
+    {
+      if (this->DofStatus->GetComponent(i,0)==1)
+	v=i+1;
+    }
+
+  maxdofs=v;
+  //fprintf(stderr,"vtkpxLinearRegistration:: Level = %d maxdofs=%d\n",level,maxdofs);
+      
+  for (int st=1;st<=this->NumberOfSteps;st++)
+    {
+      double old_similarity = this->Evaluate();
+      double new_similarity=this->Optimize(maxdofs,step,old_similarity,level,st);
+      old_similarity=this->Evaluate();
+      this->GenerateOutput(level,st,this->NumberOfIterations,step,new_similarity,
+			   this->LastSimilarity,this->LastSmoothness);
+      step*=0.5;
+    }
+  
+  return 1;
+}
+
+//-------------------------------------------------------------------------
+double vtkpxLinearRegistration::Optimize(int maxdofs,double step,double old_similarity,int level,int st)
+{
+
+  if (this->OptimizationMethod==-1)
+    {
+      return this->OldOptimize(maxdofs,step,old_similarity,level,st);
+    }
+
+
+  OptimizationStructure.SetValues(maxdofs,step,old_similarity,level,st);
+
+  vtkpxOptimizer* optimizer=vtkpxOptimizer::New();
+  vtkDoubleArray* position=vtkDoubleArray::New();
+  vtkDoubleArray* temp=vtkDoubleArray::New();
+  this->GetCurrentParameters(position);
+  optimizer->SetMasterObject(this);
+  optimizer->SetEvaluateFunctionMethod(&vtkpxAbstractIntensityRegistration::CalculateFunction);
+  optimizer->SetEvaluateGradientMethod(&vtkpxAbstractIntensityRegistration::CalculateGradient);
+  optimizer->SetBeginIterationMethod(&vtkpxAbstractIntensityRegistration::OnBeginIteration);
+  optimizer->SetFeedbackMethod(&vtkpxAbstractIntensityRegistration::OptimizerFeedback);
+
+
+  double v=0.0;
+  fprintf(stderr,"Optimization Method=%d\n\n",this->OptimizationMethod);
+
+  switch (this->OptimizationMethod)
+    {
+    case 1:
+      v=optimizer->ComputeSlowClimb(position,step,this->NumberOfIterations,this->DofStatus);
+      break;
+
+    case 2:
+      v=optimizer->ComputePowell(position,temp,this->NumberOfIterations,0.0001);
+      break;
+
+    case 3:
+      v=optimizer->ComputeGradientDescent(position,this->NumberOfIterations,0.0001);
+      break;
+
+    case 4:
+      v=optimizer->ComputeConjugateGradient(position,this->NumberOfIterations,0.0001);
+      break;
+
+    case 5:
+      v=optimizer->ComputeSlowClimb(position,step,this->NumberOfIterations,this->DofStatus);
+      if (level==1 && st==this->NumberOfSteps)
+	v=optimizer->ComputeConjugateGradient(position,this->NumberOfIterations,0.0001);
+      break;
+
+    default:
+      if (this->MeanResolution>1.0)
+	v=optimizer->ComputeConjugateGradient(position,this->NumberOfIterations,0.0001);
+      else
+	v=optimizer->ComputeGradientDescent(position,this->NumberOfIterations,0.0001);
+    }
+
+  optimizer->Delete();
+  position->Delete();
+  temp->Delete();
+  return v;
+}
+//-------------------------------------------------------------------------
+int vtkpxLinearRegistration::FinalizeAll()
+{
+  // Shift Origin back to 0,0,0 as opposed to center of image
+  this->GenerateUpdateTransform();
+  this->TransformOutputMode=1;
+  //  this->LastSimilarity=Evaluate();
+  return vtkpxAbstractIntensityRegistration::FinalizeAll();
+}
+
+vtkAbstractTransform* vtkpxLinearRegistration::GetTransformation()
+{
+  if (this->TransformOutputMode==0 || this->UpdateTransform==NULL)
+    return this->LinearTransform;
+
+  return this->UpdateTransform;
+}
+
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::GenerateUpdateTransform()
+{
+  this->UpdateTransform->Identity();
+
+  if (!this->AutoCenterOrigin)
+    {
+      this->UpdateTransform->Concatenate(this->LinearTransform->GetMatrix());
+      return;
+    }
+
+  /*  fprintf(stderr,"\n\n ------------------------------------------------\nIn Generate Update Transformation %d %d\n",this->ReferenceOrientation,this->TransformOrientation);
+   */
+
+  if (this->ReferenceOrientation==this->TransformOrientation)
+    {
+      this->LinearTransform->GenerateUpdateTransform(this->UpdateTransform,
+						     this->ReferenceImage,this->ReferenceOrientation,
+						     this->TransformImage,this->TransformOrientation);
+    }
+  else
+    {
+
+      int   rdim[3],tdim[3],dim2[3];
+      double rsp[3],tsp[3],sp2[3];
+
+      this->ReferenceImage->GetSpacing(rsp); this->ReferenceImage->GetDimensions(rdim);
+      this->TransformImage->GetSpacing(sp2); this->TransformImage->GetDimensions(dim2);
+
+      vtkpxUtil::ReOrientDimensions(sp2,dim2,
+				    this->ReferenceOrientation,
+				    this->TransformOrientation,
+				    tsp,tdim);
+      
+      float shift[3],minusshift[3];
+      for (int i=0;i<=2;i++)
+	{
+	  shift[i]=0.5*tsp[i]*double(tdim[i]-1);
+	  minusshift[i]=-0.5*rsp[i]*double(rdim[i]-1);
+	}
+
+      /*fprintf(stderr,"tdim=%d %d %d dim2=(%d,%d,%d)\n",tdim[0],tdim[1],tdim[2],
+	dim2[0],dim2[1],dim2[2]);*/
+      this->LinearTransform->GenerateUpdateTransform(this->UpdateTransform,
+						     minusshift,this->ReferenceOrientation,
+						     shift,this->TransformOrientation);
+    }
+
+  //this->PrintInformation();
+ 
+  return;
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::PrintInformation()
+{
+  int i;
+  vtkpxLinearTransform *t=this->LinearTransform;
+  if (t!=NULL)
+    {
+      for (i=0; i<12; i++) 
+	fprintf(stdout,"%7.5f ",t->Get(i));
+      fprintf(stdout,"%5.2f\n",this->Similarity());
+    }
+}
+
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::GenerateOutput(int level, int step,int iter,double stepsize,double actualSimilarity,
+					     double last_image,double last_smooth)
+{
+  if (iter>=100)
+    iter=99;
+
+  sprintf(this->OutputStatus,"%2d %2d %2d %6.3f:",level,step,iter,stepsize);
+  for (int ii=0; ii<15; ii++) 
+    {
+      if (this->DofStatus->GetComponent(ii,0)>0)
+	sprintf(this->OutputStatus,"%s %-.3f ",this->OutputStatus,this->LinearTransform->Get(ii));
+    }
+
+  
+
+  sprintf(this->OutputStatus,"%s\t%.3f (%.6f,%.6f) %d\n",this->OutputStatus,actualSimilarity,last_image,last_smooth,this->InterpolationMode);
+
+
+  if (this->ProvideFeedback) 
+    this->GenerateUpdateTransform();
+  
+  vtkpxAbstractIntensityRegistration::GenerateOutput(level,step,iter,stepsize,actualSimilarity);
+  return;
+}
+//-------------------------------------------------------------------------
+double vtkpxLinearRegistration::Evaluate()
+{
+  this->LastSmoothness=0.0;
+  //  fprintf(stderr,"Not Here .........................\n");
+
+  if (this->SampledReferenceWeightImage!=NULL && this->SampledTransformWeightImage!=NULL)
+    {
+      this->LastSimilarity=vtkpxRegistration::WeightedHistogramEvaluate(this->SampledReferenceImage,this->SampledReferenceWeightImage,
+									    this->SampledTransformImage,this->SampledTransformWeightImage,
+									    this->LinearTransform,
+									    this->Histogram,this->SimilarityMeasure,this->InterpolationMode);
+    }
+  else if (this->SampledReferenceWeightImage!=NULL)
+    {
+      this->LastSimilarity=vtkpxRegistration::WeightedHistogramEvaluate(this->SampledReferenceImage,this->SampledReferenceWeightImage,
+									this->SampledTransformImage,NULL,
+									this->LinearTransform,
+									this->Histogram,this->SimilarityMeasure,this->InterpolationMode);
+    }
+  else
+    {
+      this->LastSimilarity=vtkpxRegistration::HistogramEvaluate(this->SampledReferenceImage,this->SampledTransformImage,
+								this->LinearTransform,
+								this->Histogram,this->SimilarityMeasure,this->InterpolationMode);
+    }
+  return this->LastSimilarity;
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::SetCurrentParameters(vtkDoubleArray* param)
+{
+  int numt=OptimizationStructure.maxdofs;
+  int num=param->GetNumberOfTuples();
+
+  if (num!=numt)
+    {
+      vtkErrorMacro(<<"Bad Data for Optimization");
+      return;
+    }
+  
+  this->LinearTransform->SetFreezeUpdates(1);
+  int i=0;
+  for (i=0;i<3;i++)
+    this->LinearTransform->Put(i,param->GetComponent(i,0));
+  for (i=3;i<numt;i++)
+    this->LinearTransform->Put(i,param->GetComponent(i,0)/this->OptimizationScaleFactor);
+
+
+  this->LinearTransform->SetFreezeUpdates(0);
+  
+  this->LinearTransform->UpdateParameters();
+}
+//-------------------------------------------------------------------------
+void vtkpxLinearRegistration::GetCurrentParameters(vtkDoubleArray* param) 
+{
+  int numt=OptimizationStructure.maxdofs;
+  if (param->GetNumberOfComponents()!=2 || param->GetNumberOfTuples()!=numt)
+    {
+      param->SetNumberOfComponents(2);
+      param->SetNumberOfTuples(numt);
+    }
+
+  for (int j=0;j<=2;j++)
+    {
+      param->SetComponent(j,0,this->LinearTransform->Get(j));
+      param->SetComponent(j,1,1.0);
+    }
+  
+  for (int i=3;i<numt;i++)
+    {
+      param->SetComponent(i,0,this->LinearTransform->Get(i)*this->OptimizationScaleFactor);
+      param->SetComponent(i,1,this->OptimizationScaleFactor);
+    }
+  
+}
+//-------------------------------------------------------------------------
+double vtkpxLinearRegistration::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad) 
+{
+  if (grad->GetNumberOfComponents()!=1 || grad->GetNumberOfTuples()!=OptimizationStructure.maxdofs)
+    {
+      grad->SetNumberOfComponents(1);
+      grad->SetNumberOfTuples(OptimizationStructure.maxdofs);
+    }
+
+  grad->FillComponent(0,0.0);
+  this->OptimizationStructure.old_similarity=this->OptimizerValue(params);
+  double GradientNorm = 0;
+  fprintf(stderr,",Grad Step=%.4f (optsc=%.4f),",OptimizationStructure.step,this->OptimizationScaleFactor);
+
+  for (int i=0;i<OptimizationStructure.maxdofs;i++)
+    {
+      if (DofStatus->GetComponent(i,0)>0) 
+	{
+	  double orig=params->GetComponent(i,0);
+	  params->SetComponent(i, 0, orig + this->OptimizationStructure.step);
+	  this->SetCurrentParameters(params);
+	  double a=this->Evaluate();
+
+	  params->SetComponent(i, 0, orig - this->OptimizationStructure.step);
+	  this->SetCurrentParameters(params);
+	  double b=this->Evaluate();
+
+	  params->SetComponent(i, 0, orig);
+	  this->SetCurrentParameters(params);
+
+	  double g=-0.5*(b-a)/this->OptimizationStructure.step;
+	  grad->SetComponent(i,0,g);
+	  GradientNorm+=pow(g,2.0);
+	}
+    }
+  GradientNorm = (sqrt(GradientNorm));
+
+
+  // -------------------------
+  // Hirohito Found this One!!
+  // -------------------------
+  for (int j=0;j<OptimizationStructure.maxdofs;j++)
+    grad->SetComponent(j,0,grad->GetComponent(j,0)/GradientNorm);
+      
+  return GradientNorm;
+}
+//-------------------------------------------------------------------------
+double vtkpxLinearRegistration::OptimizerValue(vtkDoubleArray* params) 
+{
+  this->SetCurrentParameters(params);
+  return -this->Evaluate();
+}
+//-------------------------------------------------------------------------
+//
+//
+//          OLD STUFF --- IGNORE
+//
+//
+//-------------------------------------------------------------------------
+
+double vtkpxLinearRegistration::OldOptimize(int maxdofs,double step,double old_similarity,int level,int st)
+{
+
+  double similarity=0.0,new_similarity=0.0;
+  double last_smooth=0.0,last_image=0.0;
+
+  double actstep=step;
+  double actstep2=step*(1.0/this->MeanResolution);
+
+  //fprintf(stderr,"Step=%f  actstep=%f actstep2=%f\n",step,actstep,actstep2);
+  
+  for (int iter=1;iter<this->NumberOfIterations;iter++)
+    {
+      int j = 0,k = 0;
+      old_similarity = new_similarity = this->Evaluate();
+      
+      last_image=this->LastSimilarity;
+      last_smooth=this->LastSmoothness;
+
+
+      
+      for (int i = 0; i < maxdofs; i++)
+	{
+	  if (i>=6 && i<=8)
+	    step=actstep2;
+	  else
+	    step=actstep;
+
+	  /*	  if (iter==1)
+		  fprintf(stderr,"Param = %d step=%f\n",i,step);*/
+
+	  if (DofStatus->GetComponent(i,0)>0)
+	    {
+	      double orig=this->LinearTransform->Get(i);
+	      this->LinearTransform->Put(i, orig + step);
+	      similarity = this->Evaluate();
+	      
+	      if (similarity > new_similarity)
+		{
+		  new_similarity = similarity;
+		  j =  i;
+		  k =  1;
+		}
+	      
+	      this->LinearTransform->Put(i, orig - step);
+	      similarity = this->Evaluate();
+	      if (similarity > new_similarity)
+		{
+		  new_similarity = similarity;
+		  j =  i;
+		  k = -1; 
+		  last_image=this->LastSimilarity;
+		  last_smooth=this->LastSmoothness;
+		}
+	      this->LinearTransform->Put(i, orig);
+	    }
+	}
+      
+      if (new_similarity > old_similarity)
+	{
+	  if (j>=6 && j<=8)
+	    step=actstep2;
+	  else
+	    step=actstep;
+
+
+	  this->LinearTransform->Put(j, this->LinearTransform->Get(j) + k * step);
+	  this->GenerateOutput(level,st,iter,step,new_similarity,last_image,last_smooth);
+	  old_similarity=new_similarity;
+	}
+      else
+	iter=this->NumberOfIterations+1; // Break Out
+    }
+  return old_similarity;
+}
+//-------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Registration/vtkpxLinearRegistration.h b/bioimagesuite30_src/Registration/vtkpxLinearRegistration.h
new file mode 100644
index 0000000..daa6b9a
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxLinearRegistration.h
@@ -0,0 +1,314 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+
+#ifndef _VTKPXRIGIDREGISTRATION_H
+#define _VTKPXRIGIDREGISTRATION_H
+
+#include "vtkpxAbstractIntensityRegistration.h"
+#include "vtkpxLinearTransform.h"
+#include "vtkTransform.h"
+#include "vtkShortArray.h"
+
+//BTX
+class vtkpxLinearRegistrationOptimizationStructure {
+public:
+  double old_similarity;
+  double step;
+  int   maxdofs;
+  int   level;
+  int   st;
+
+  void SetValues(int maxdofs0,double step0,
+		 double old_similarity0,int level0,int st0)
+  {
+    this->old_similarity=old_similarity0;
+    this->step=step0;
+    this->maxdofs=maxdofs0;
+    this->level=level0;
+    this->st=st0;
+  }
+};
+//ETX
+
+class vtkpxLinearRegistration : public vtkpxAbstractIntensityRegistration {
+
+public:
+  static vtkpxLinearRegistration* New();
+  vtkTypeMacro(vtkpxLinearRegistration,vtkpxAbstractIntensityRegistration);
+
+  // Description:
+  // Print information about the progress of the registration
+  void PrintInformation();
+
+  // Description:
+  // Run Optimization for Level level
+  virtual int ComputeRegistration(int level);
+
+  // Description:
+  // Internal Optimization
+  virtual double Optimize(int maxdofs,double step,double old_similarity,int level,int st);
+  virtual double OldOptimize(int maxdofs,double step,double old_similarity,int level,int st);
+
+
+  // Description:
+  // Auto Center Origin
+  vtkSetClampMacro(AutoCenterOrigin,int,0,1);
+  vtkGetMacro(AutoCenterOrigin,int);
+  vtkBooleanMacro(AutoCenterOrigin,int);
+
+
+  // Description:
+  // Auto Center Origin
+  vtkSetClampMacro(OptimizationAutoScale,int,0,1);
+  vtkGetMacro(OptimizationAutoScale,int);
+  vtkBooleanMacro(OptimizationAutoScale,int);
+
+  // Description:
+  // Auto Center Origin
+  vtkSetMacro(OptimizationScaleFactor,double);
+  vtkGetMacro(OptimizationScaleFactor,double);
+
+
+
+  // Description:
+  // Set Different Modes
+  virtual void SetTransformModeToRigid();
+  virtual void SetTransformModeToSimilarity();
+  virtual void SetTransformModeToAffine();
+  virtual void SetTransformModeToRigid2D();
+  virtual void SetTransformModeToSimilarity2D();
+  virtual void SetTransformModeToAffine2D();
+  virtual void SetTransformModeToDistortion();
+
+  // Description:
+  // Distortion Mode;
+  vtkSetClampMacro(DistortionMode,int,0,1);
+  vtkGetMacro(DistortionMode,int);
+  vtkBooleanMacro(DistortionMode,int);
+  
+
+
+  // Description:
+  // Set Active/Passive Degrees of Freedom
+  vtkSetClampMacro(TranslationX,int,0,1);
+  vtkSetClampMacro(TranslationY,int,0,1);
+  vtkSetClampMacro(TranslationZ,int,0,1);
+  vtkSetClampMacro(RotationX,int,0,1);
+  vtkSetClampMacro(RotationY,int,0,1);
+  vtkSetClampMacro(RotationZ,int,0,1);
+  vtkSetClampMacro(ScalingX,int,0,1);
+  vtkSetClampMacro(ScalingY,int,0,1);
+  vtkSetClampMacro(ScalingZ,int,0,1);
+  vtkSetClampMacro(ShearingXY,int,0,1);
+  vtkSetClampMacro(ShearingYX,int,0,1);
+  vtkSetClampMacro(ShearingYZ,int,0,1);
+  vtkSetClampMacro(ShearingZY,int,0,1);
+  vtkSetClampMacro(ShearingZX,int,0,1);
+  vtkSetClampMacro(ShearingXZ,int,0,1);
+
+  vtkGetMacro(TranslationX,int);
+  vtkGetMacro(TranslationY,int);
+  vtkGetMacro(TranslationZ,int);
+  vtkGetMacro(RotationX,int);
+  vtkGetMacro(RotationY,int);
+  vtkGetMacro(RotationZ,int);
+  vtkGetMacro(ScalingX,int);
+  vtkGetMacro(ScalingY,int);
+  vtkGetMacro(ScalingZ,int);
+  vtkGetMacro(ShearingXY,int);
+  vtkGetMacro(ShearingYX,int);
+  vtkGetMacro(ShearingYZ,int);
+  vtkGetMacro(ShearingZY,int);
+  vtkGetMacro(ShearingZX,int);
+  vtkGetMacro(ShearingXZ,int);
+
+  vtkBooleanMacro(TranslationX,int);
+  vtkBooleanMacro(TranslationY,int);
+  vtkBooleanMacro(TranslationZ,int);
+  vtkBooleanMacro(RotationX,int);
+  vtkBooleanMacro(RotationY,int);
+  vtkBooleanMacro(RotationZ,int);
+  vtkBooleanMacro(ScalingX,int);
+  vtkBooleanMacro(ScalingY,int);
+  vtkBooleanMacro(ScalingZ,int);
+  vtkBooleanMacro(ShearingXY,int);
+  vtkBooleanMacro(ShearingYX,int);
+  vtkBooleanMacro(ShearingYZ,int);
+  vtkBooleanMacro(ShearingZY,int);
+  vtkBooleanMacro(ShearingZX,int);
+  vtkBooleanMacro(ShearingXZ,int);
+
+
+  // Description:
+  // Return Internal Transform Structure
+  vtkGetObjectMacro(LinearTransform,vtkpxLinearTransform);
+
+  // Description:
+  // Return Update Transformation
+  virtual vtkAbstractTransform* GetUpdateTransform() { return this->UpdateTransform; } 
+
+  // Description:
+  // Get Transformation
+  virtual vtkAbstractTransform* GetTransformation();
+
+  // Description:
+  // Initial Transform
+  vtkGetObjectMacro(InitialTransform,vtkpxLinearTransform);
+  vtkSetObjectMacro(InitialTransform,vtkpxLinearTransform);
+
+
+  // Description:
+  // Dof Status
+  virtual int   GetDofStatus(int dof);
+  virtual void  UpdateDofLabels();
+
+
+protected:
+  // Make all these protected 
+  // Constructor
+  vtkpxLinearRegistration();
+  virtual ~vtkpxLinearRegistration();
+  vtkpxLinearRegistration(const vtkpxLinearRegistration&) {};
+  void operator=(const vtkpxLinearRegistration&) {};
+
+  // Description:
+  // Initial set up for the registration at all levels
+  virtual int InitializeAll();
+
+  // Description:
+  // Initial set up for the registration at a multiresolution level
+  virtual int Initialize(int Level);
+
+  // Description:
+  // Final set up for the registration at all levels
+  virtual int FinalizeAll();
+
+  // Description:
+  // Evaluates the registration. This function evaluates the registration by
+  // looping over the target image and interpolating the transformed source 
+  // image while filling the joint histogram. This function returns the value
+  // of the similarity measure using Similarity().
+  virtual double Evaluate();
+
+
+  // Description:
+  // Pointer To  Transform Used for Evaluation
+  vtkpxLinearTransform* LinearTransform;
+  vtkTransform*     UpdateTransform;
+
+  // Description:
+  // Auto Center Origin
+  int AutoCenterOrigin;
+
+  // Description:
+  // Optimization Auto Scale -- what to scale the non-translation parameters
+  // relative to translation if OptimizationAutoScale=0 default (meanresolution) is used
+  // if 1 value in OptimizationScaleFactor is used
+  int OptimizationAutoScale;
+  double OptimizationScaleFactor;
+  
+
+  // Description:
+  // Initial Transform
+  vtkpxLinearTransform*     InitialTransform;
+
+  // Description:
+  // Genereate Output
+  virtual void GenerateUpdateTransform();
+  virtual void GenerateOutput(int level, int step,int iter,double stepsize,double simil,double last_sim,double last_sm);
+
+  // Description:
+  // Transform Output Mode
+  int TransformOutputMode;
+
+  // Description:
+  // Set Distortion Mode on Linear Xform
+  int DistortionMode;
+
+
+  // Description:
+  // Optimizer Interface
+  virtual void SetCurrentParameters(vtkDoubleArray* par);
+  virtual void GetCurrentParameters(vtkDoubleArray* par);
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+
+  // Description:
+  // This controls the optimization method 0=default,1=Cong Gradient
+  vtkpxLinearRegistrationOptimizationStructure OptimizationStructure;
+
+
+  // Description:
+  // Enable/Disable DOF
+  vtkShortArray* DofStatus;
+
+
+protected:
+
+//BTX
+  int TranslationX, TranslationY, TranslationZ;
+  int RotationX, RotationZ, RotationY;
+  int ScalingX, ScalingY, ScalingZ;
+  int ShearingXY, ShearingYX, ShearingYZ, ShearingZY, ShearingZX, ShearingXZ;
+  double DofWeight[15];
+
+//ETX
+
+
+
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxLinearTransform.cpp b/bioimagesuite30_src/Registration/vtkpxLinearTransform.cpp
new file mode 100644
index 0000000..c88cb2e
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxLinearTransform.cpp
@@ -0,0 +1,866 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+
+
+#include <stdlib.h>
+#include "vtkpxLinearTransform.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "pxutil.h"
+#include "vtkImageData.h"
+#include "pxutil.h"
+#include "vtkpxUtil.h"
+#include "vtkLandmarkTransform.h"
+#include "vtkPoints.h"
+#include "vtkLinearTransform.h"
+//----------------------------------------------------------------------------
+vtkpxLinearTransform* vtkpxLinearTransform::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxLinearTransform");
+  if(ret)
+    {
+    return (vtkpxLinearTransform*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxLinearTransform;
+}
+
+//----------------------------------------------------------------------------
+vtkpxLinearTransform::vtkpxLinearTransform()
+{
+  /// Scaling along the x-axis, y-axis, z-axis
+  _sx=100.0;
+  _sy=100.0;
+  _sz=100.0;
+  /// Skew angle in the x-y ...  plane (in degrees)
+  _sxy=0.0;
+  _syx=0.0;
+  _syz=0.0;
+  _szy=0.0;
+  _szx=0.0;
+  _sxz=0.0;
+  /// Translation along the x-axis (in mm)
+  _tx=0.0;
+  _ty=0.0;
+  _tz=0.0;
+  /// Rotation around the x-axis (in degrees)
+  _rx=0.0;
+  _ry=0.0;
+  _rz=0.0;
+
+  FlipX=0;
+  FlipY=0;
+  FlipZ=0;
+
+  this->DistortionMode=0;
+  this->FreezeUpdates=0;
+}
+
+//----------------------------------------------------------------------------
+vtkpxLinearTransform::~vtkpxLinearTransform()
+{
+}
+
+//----------------------------------------------------------------------------
+void vtkpxLinearTransform::PrintSelf(ostream& os, vtkIndent indent)
+{
+  os << indent << "### " << this->GetClassName() << " ### \n";
+  os  << indent << "Transformation Parameters: \n";
+  os << indent << "Translation: " << _tx << " " << _ty  << " " << _tz << " "  << "\n";
+  os << indent << "Rotation: " << _rx  << " " << _ry  << " " << _rz << "\n";
+  os << indent << "Scaling: " << _sx  << " " << _sy  << " " << _sz << "\n";
+  os << indent << "Shearing 1: " << _sxy  << " " << _syx  << " " << _syz << "\n";
+  os << indent << "Shearing 2: " << _szy  << " " << _szx  << " " << _sxz << "\n";
+  os << indent << "Flip: " << FlipX << " " << FlipY  << " " << FlipZ << "\n";
+  os << indent << "DistotionMode: " << DistortionMode << "\n";
+  
+  this->vtkTransform::PrintSelf(os, indent.GetNextIndent());
+}
+
+
+//----------------------------------------------------------------------------
+void vtkpxLinearTransform::UpdateParameters()
+{
+  if (this->FreezeUpdates)
+    return;
+
+  float pi = vtkMath::Pi();
+
+  /*  float cosrx = cos(_rx*pi/180.0);
+      float cosry = cos(_ry*pi/180.0);
+      float cosrz = cos(_rz*pi/180.0);
+      float sinrx = sin(_rx*pi/180.0);
+      float sinry = sin(_ry*pi/180.0);
+      float sinrz = sin(_rz*pi/180.0);*/
+
+
+
+  // Update affine transformation: Add shearing
+  vtkMatrix4x4 *skewx= vtkMatrix4x4::New();
+  skewx->Identity();
+  skewx->SetElement(2, 1,tan(_szy*(pi/180.0)));
+  skewx->SetElement(1, 2,tan(_syz*(pi/180.0))); 
+  vtkMatrix4x4 *skewy= vtkMatrix4x4::New();
+  skewy->Identity();
+  skewy->SetElement(2, 0,tan(_szx*(pi/180.0)));
+  skewy->SetElement(0, 2,tan(_sxz*(pi/180.0)));
+  vtkMatrix4x4 *skewz= vtkMatrix4x4::New();
+  skewz->Identity();
+  skewz->SetElement(1, 0,tan(_sxy*(pi/180.0)));  
+  skewz->SetElement(0, 1,tan(_syx*(pi/180.0))); 
+
+  float sx=_sx*0.01; if (this->FlipX) sx=-1.0*sx;
+  float sy=_sy*0.01; if (this->FlipY) sy=-1.0*sy;
+  float sz=_sz*0.01; if (this->FlipZ) sz=-1.0*sz;
+
+  vtkTransform* tr=vtkTransform::New();
+
+  tr->Identity();
+  tr->PostMultiply();
+  if (this->DistortionMode==0)
+    {
+      tr->Concatenate(skewx);
+      tr->Concatenate(skewy);
+      tr->Concatenate(skewz);
+      tr->Scale(sx,sy,sz);
+      tr->RotateX(_rx);
+      tr->RotateY(_ry);
+      tr->RotateZ(_rz);
+      tr->Translate(_tx,_ty,_tz);
+    }
+  else
+    {
+      tr->RotateX(_rx);
+      tr->RotateY(_ry);
+      tr->RotateZ(_rz);
+      tr->Translate(_tx,_ty,_tz);
+      tr->Concatenate(skewx);
+      tr->Concatenate(skewy);
+      tr->Concatenate(skewz);
+      tr->Scale(sx,sy,sz);
+    }
+
+  skewx->Delete();
+  skewy->Delete();
+  skewz->Delete();
+
+
+  vtkTransform::Identity();
+  this->Concatenate(tr->GetMatrix());
+  tr->Delete();
+  this->vtkTransform::InternalUpdate();
+
+}
+
+
+//----------------------------------------------------------------------------
+void vtkpxLinearTransform::GetParameters(vtkDoubleArray *parameters)
+{
+  this->GetParameters(parameters,0);
+}
+
+void vtkpxLinearTransform::SetParameters(vtkDoubleArray *scalars)
+{
+  this->SetParameters(scalars,0);
+}
+//----------------------------------------------------------------------------
+void vtkpxLinearTransform::GetParameters(vtkDoubleArray *parameters,int frame)
+{
+  if (parameters->GetNumberOfComponents()>=this->GetNumberOfParameters() && parameters->GetNumberOfTuples()>frame)
+    {
+      for (int i=0;i<this->GetNumberOfParameters();i++)
+	parameters->SetComponent(frame,i,this->Get(i));
+    }
+}
+
+void vtkpxLinearTransform::SetParameters(vtkDoubleArray *scalars,int frame)
+{
+  if (scalars->GetNumberOfComponents()<this->GetNumberOfParameters() || frame>=scalars->GetNumberOfTuples())
+    {
+      fprintf(stderr,"Wrong Input in comp=%d,nump=%d in frame=%d tuples=%d\n",
+	      scalars->GetNumberOfComponents(),this->GetNumberOfParameters(),
+	      frame,scalars->GetNumberOfTuples());
+      return;
+    }
+
+  for (int i=0;i<this->GetNumberOfParameters();i++)
+    this->Put(i,scalars->GetComponent(frame,i));
+  this->UpdateParameters();
+}
+
+//----------------------------------------------------------------------------
+float vtkpxLinearTransform::Get(int i) const
+{
+  switch (i) 
+    {
+    case 0:
+      return _tx;
+      break;
+    case 1:
+      return _ty;
+      break;
+    case 2:
+      return _tz;
+      break;
+    case 3:
+      return _rx;
+      break;
+    case 4:
+      return _ry;
+      break;
+    case 5:
+      return _rz;
+      break;
+    case 6:
+      return _sx;
+      break;
+    case 7:
+      return _sy;
+      break;
+    case 8:
+      return _sz;
+      break;
+    case 9:
+      return _sxy; 
+      break;
+    case 10:
+      return _syx;
+      break;
+    case 11:
+      return _syz;
+      break;
+    case 12:
+      return _szy;
+      break;
+    case 13:
+      return _szx;
+      break;
+    case 14:
+      return _sxz;
+      break;
+    case 15:
+      return FlipX;
+      break;
+    case 16:
+      return FlipY;
+      break;
+    case 17:
+      return FlipZ;
+      break;
+    case 18:
+      return DistortionMode;
+      break;
+    default:
+      cerr << "No such dof" << i << endl;
+    return 0;
+    }
+}
+//----------------------------------------------------------------------------
+void vtkpxLinearTransform::Put(int i, float x)
+{
+  switch (i) 
+    {
+    case 0:
+      _tx = x;
+      break;
+    case 1:
+      _ty = x;
+      break;
+    case 2:
+      _tz = x;
+      break;
+    case 3:
+      _rx = x;
+      break;
+    case 4:
+      _ry = x;
+      break;
+    case 5:
+      _rz = x;
+      break;
+    case 6:
+      _sx = x;
+      if (_sx<1.01)
+	_sx=100.0;
+      break;
+    case 7:
+      _sy = x;
+      if (_sy<1.01)
+	_sy=100.0;
+      break;
+    case 8:
+      _sz = x;
+      if (_sz<1.01)
+	_sz=100.0;
+      break;
+    case 9:
+      _sxy = x; 
+      break;
+    case 10:
+      _syx = x;
+      break;
+    case 11:
+      _syz = x;
+      break;
+    case 12:
+      _szy = x;
+      break;
+    case 13:
+      _szx = x;
+      break;
+    case 14:
+      _sxz = x;
+    break;
+    case 15:
+      FlipX = ((int) x) %2;
+      break;
+    case 16:
+      FlipY = ((int) x) %2;
+      break;
+    case 17:
+      FlipZ = ((int) x) %2;
+      break;
+    case 18:
+      DistortionMode=int(x>0);
+      break;
+    default:
+      cerr << "Put(): No such dof" << i << endl;
+      return;
+    }
+  // Update transformation matrix
+  this->UpdateParameters();
+}
+//----------------------------------------------------------------------------
+void vtkpxLinearTransform::SetFlipX(int f)
+{
+  this->FlipX=f;
+  this->UpdateParameters();
+}
+//----------------------------------------------------------------------------
+void vtkpxLinearTransform::SetFlipY(int f)
+{
+  this->FlipY=f;
+  this->UpdateParameters();
+}
+//----------------------------------------------------------------------------
+void vtkpxLinearTransform::SetFlipZ(int f)
+{
+  this->FlipZ=f;
+  this->UpdateParameters();
+}
+
+//----------------------------------------------------------------------------
+void vtkpxLinearTransform::SetDistortionMode(int f)
+{
+  this->DistortionMode=(f>0);
+  this->UpdateParameters();
+}
+//----------------------------------------------------------------------------
+
+
+void vtkpxLinearTransform::Inverse() 
+{
+    /// Scaling along the x-axis, y-axis, z-axis
+  _sx=10000.0/_sx; _sy=10000.0/_sy; _sz=10000.0/_sz;
+  /// Skew angle in the x-y ...  plane (in degrees)
+  _sxy=-_sxy;
+  _syx=-_syx;
+  _syz=-_syz;
+  _szy=-_szy;
+  _szx=-_szx;
+  _sxz=-_sxz;
+
+  /// Translation along the x-axis (in mm)
+  _tx *= -1;
+  _ty *= -1;
+  _tz *= -1;
+  /// Rotation around the x-axis (in degrees)
+  _rx *= -1;
+  _ry *= -1;
+  _rz *= -1;
+
+  this->GetMatrix()->Invert();
+  this->Update();
+  
+  this->Concatenation->Inverse();
+  this->Modified();
+}
+//----------------------------------------------------------------------------
+int vtkpxLinearTransform::Load(char* fname)
+{
+  char pxtk_buffer[255];
+
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  gzgets(fin,pxtk_buffer,100);
+  
+  if (gzfindstringinstring(pxtk_buffer,"#vtkpxLinearTransform File")==0)
+    {
+      gzclose(fin);
+      return 0;
+    }
+
+  gzgets(fin,pxtk_buffer,100);
+  float dx[4];
+
+  vtkMatrix4x4* matrix=this->GetMatrix();
+  
+  for (int ia=0;ia<=3;ia++)
+    {
+      gzgets(fin,pxtk_buffer,200);
+      sscanf(pxtk_buffer,"%f %f %f %f",&dx[0],&dx[1],&dx[2],&dx[3]);
+      for (int j=0;j<=3;j++)
+	matrix->SetElement(ia,j,dx[j]);
+    }
+
+  gzgets(fin,pxtk_buffer,200); 
+  int tmp;
+  float v;
+  for (int i=0;i<this->GetNumberOfParameters();i++)
+    {
+      gzgets(fin,pxtk_buffer,200);
+      sscanf(pxtk_buffer,"%d %f",&tmp,&v);
+      this->Put(i,v);
+    }
+  gzclose(fin);
+  return 1;
+}
+//----------------------------------------------------------------------------
+int vtkpxLinearTransform::Save(char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+    return 0;
+
+  fprintf(fout,"#vtkpxLinearTransform File\n");
+  fprintf(fout,"#4x4 Matrix\n");
+
+  vtkMatrix4x4* matrix=this->GetMatrix();
+
+  for(int ia=0;ia<=3;ia++)
+    {
+      for (int j=0;j<=3;j++)
+	fprintf(fout,"%.4f ",matrix->GetElement(ia,j));
+      fprintf(fout,"\n");
+    }
+
+  fprintf(fout,"#Actual Parameters\n");
+  for (int i=0;i<this->GetNumberOfParameters();i++)
+    fprintf(fout,"%d %.4f\n",i+1,this->Get(i));
+  
+  fclose(fout);
+  return 1;
+}
+//----------------------------------------------------------------------------
+void vtkpxLinearTransform::Identity()
+{
+  /// Scaling along the x-axis, y-axis, z-axis
+  _sx=100.0;
+  _sy=100.0;
+  _sz=100.0;
+  /// Skew angle in the x-y ...  plane (in degrees)
+  _sxy=0.0;
+  _syx=0.0;
+  _syz=0.0;
+  _szy=0.0;
+  _szx=0.0;
+  _sxz=0.0;
+  /// Translation along the x-axis (in mm)
+  _tx=0.0;
+  _ty=0.0;
+  _tz=0.0;
+  /// Rotation around the x-axis (in degrees)
+  _rx=0.0;
+  _ry=0.0;
+  _rz=0.0;
+
+  FlipX=0;
+  FlipY=0;
+  FlipZ=0;
+  this->UpdateParameters();
+}
+//----------------------------------------------------------------------------
+void vtkpxLinearTransform::Copy(vtkpxLinearTransform* other)
+{
+  if (other==NULL)
+    return;
+
+  for (int i=0;i<this->GetNumberOfParameters();i++)
+    {
+      this->Put(i,other->Get(i));
+    }
+  this->UpdateParameters();
+}
+
+//----------------------------------------------------------------------------
+void LinPrint(vtkMatrix4x4* matrix,char* name)
+{
+  fprintf(stdout,"\n Printing %s\n",name);
+  for(int i=0;i<=3;i++)
+    {
+      for (int j=0;j<=3;j++)
+	fprintf(stdout,"%7.3f ",matrix->GetElement(i,j));
+      fprintf(stdout,"\n");
+    }
+}
+
+
+//----------------------------------------------------------------------------
+/*
+
+Let C : be centered coordinate frame to centered coordinate frame transformation
+Let G : be transformation that changes orientation from reference to transform
+Let Z : be actual VTK Transformation 
+
+Let r be the centered coordinate space on the Reference Image
+Let t be the centered coordinate space on the Transform Image
+
+Let r' be the non-centered (default) coordinate space on Reference
+Let t' be the non-centered (default) coordinate space on Transform
+
+
+Transformation we are interested in is
+
+     r --> t i.e.   t= Ar
+     
+What we need for practical application is
+
+     r' --> t' i.e.  t'=Br'
+
+     
+Let R,T be shift operations such that : r'=Rr, t'=Tt
+
+If no orientation change then
+
+          
+   t=Ar
+   T(-1)t'=AR(-1)r'
+   t'=[ TAR(-1) ] r'
+
+Hence B=[ TAR(-1) ] 
+
+This would be true if the orientations of B and A where the same. 
+
+If not we need to transform B such that it accounts for the orientation dependence.
+
+Hence we need B' = G*B
+
+
+B'=G * [ TAR(-1) ] 
+
+TAR(-1) = G(-1)*B'
+TA      =  G(-1)*B'*R
+A       = T(-1)*G(-1)*B'*R
+
+
+
+*/
+//----------------------------------------------------------------------------
+int vtkpxLinearTransform::ManualSetParameters(float tx,float ty,float tz,
+					      float rx,float ry,float rz,
+					      float sx,float sy,float sz,
+					      vtkImageData* reference,int ref_orientation,
+					      vtkImageData* transform,int trn_orientation,
+					      vtkTransform* combined)
+{
+  
+  // This Function Generates the A Matrix Above
+
+  if (reference==NULL || transform==NULL || combined==NULL)
+    return 0;
+
+  // Ensure No Individual Updates
+  this->FreezeUpdates=1;
+  this->Identity();
+  this->Put(0,tx);   this->Put(1,ty);   this->Put(2,tz);
+  this->Put(3,rx);   this->Put(4,ry);   this->Put(5,rz);
+  this->Put(6,sx);   this->Put(7,sy);   this->Put(8,sz);
+  this->SetDistortionMode(0);
+  this->FreezeUpdates=0;
+  // Creates Transformation from parameters 
+  this->UpdateParameters();
+
+  
+
+  // This call modifes A to yield B'
+  return this->GenerateUpdateTransform(combined,reference,ref_orientation,
+				       transform,trn_orientation);
+  
+}
+//----------------------------------------------------------------------------
+int vtkpxLinearTransform::ExtractParameters(vtkAbstractTransform* tr,int nparam,
+					    vtkImageData* reference,int ref_orientation,
+					    vtkImageData* transform,int trn_orientation)
+{
+  if (tr==NULL || reference==NULL || transform ==NULL)
+    {
+      vtkErrorMacro(<< "Bad  Inputs to Extract Parameters\n");
+      return 0;
+    }
+
+  vtkTransform *estimatedMatrix=vtkTransform::New();
+  estimatedMatrix->Identity();
+  
+  if (tr->IsA("vtkLinearTransform")!=1)
+    {
+      // Step 1 : Generate B' Matrix
+      // ---------------------------
+      vtkPoints* p1=vtkPoints::New();
+      vtkPoints* p2=vtkPoints::New();
+      
+      p1->SetNumberOfPoints(8);
+      
+      double bounds[6]; reference->GetBounds(bounds);
+      int index=0;
+      for (int i=0;i<2;i++)
+	for (int j=0;j<2;j++)
+	  for (int k=0;k<2;k++)
+	    {
+	      p1->SetPoint(index,bounds[i],bounds[2+j],bounds[4+k]);
+	      ++index;
+	    }
+      
+      tr->TransformPoints(p1,p2);
+      
+      vtkLandmarkTransform* land=vtkLandmarkTransform::New();
+      land->SetSourceLandmarks(p1);
+      land->SetTargetLandmarks(p2);
+      land->SetModeToAffine();
+      
+      if (nparam<7)
+	land->SetModeToRigidBody();
+      else if (nparam<8)
+	land->SetModeToSimilarity();
+      land->Update();
+      
+      p1->Delete();
+      p2->Delete();
+
+      estimatedMatrix->Concatenate(land->GetMatrix());
+      land->Delete();
+    }
+  else
+    {
+      vtkLinearTransform* t=(vtkLinearTransform*) tr;
+      estimatedMatrix->Concatenate(t->GetMatrix());
+    }
+  
+
+  // ---------------------------------------------------------
+  //  Transformation = Orient * Shift * Linear * MinusShift
+  //  Linear = Shift(-1) *   ( Orient(-1) * Transformation ) * MinusShift(-1)
+  // ---------------------------------------------------------
+  
+  // Not needed vtkpxUtil takes care of this
+  //  ref_orientation=Irange(ref_orientation,0,2);
+  //  trn_orientation=Irange(trn_orientation,0,2);
+  
+  
+  // Orient = G(-1)
+  vtkTransform* Orient=vtkTransform::New();
+  vtkMatrix4x4* mat=vtkMatrix4x4::New();
+  vtkpxUtil::ReOrientMatrix(transform,ref_orientation,trn_orientation,mat,1);
+  //  vtkpxUtil::ReOrientMatrix(transform,trn_orientation,ref_orientation,mat);
+  Orient->Identity();
+  Orient->Concatenate(mat);
+  mat->Delete();
+  //  Orient->Inverse();
+
+  int   rdim[3],tdim[3];
+  double rsp[3],tsp[3];
+
+  reference->GetSpacing(rsp); reference->GetDimensions(rdim);
+  transform->GetSpacing(tsp); transform->GetDimensions(tdim);
+  float shift[3],minusshift[3];
+  for (int ib=0;ib<=2;ib++)
+    {
+      shift[ib]=0.5*tsp[ib]*float(tdim[ib]-1.0);
+      minusshift[ib]=-0.5*rsp[ib]*float(rdim[ib]-1.0);
+    }
+
+  vtkTransform* MinusShift=vtkTransform::New();
+  MinusShift->Translate(minusshift);
+  MinusShift->Inverse();
+
+  vtkTransform* Shift=vtkTransform::New();
+  Shift->Translate(shift);
+  Shift->Inverse();
+ 
+  vtkTransform* combo=vtkTransform::New();
+  combo->Identity();
+  combo->PostMultiply();
+  combo->Concatenate(MinusShift);
+  combo->Concatenate(estimatedMatrix);
+  combo->Concatenate(Shift);
+  combo->Concatenate(Orient);
+
+  //  fprintf(stderr,"Extracting Stuff");
+  //LinPrint(MinusShift->GetMatrix(),"MinusShift");
+  //LinPrint(land->GetMatrix(),"Landmark");
+  //LinPrint(Orient->GetMatrix(),"Orientation");
+  //LinPrint(Shift->GetMatrix(),"Shift");
+  //LinPrint(combo->GetMatrix(),"Combo");
+
+
+
+  estimatedMatrix->Delete();
+  Shift->Delete();
+  Orient->Delete();
+  MinusShift->Delete();
+
+
+  float rot[3]; combo->GetOrientation(rot);
+  float pos[3]; combo->GetPosition(pos);
+  float sc[3];  combo->GetScale(sc);
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (fabs(rot[ia])<0.001)
+	rot[ia]=0.0;
+      if (fabs(pos[ia])<0.001)
+	pos[ia]=0.0;
+    }
+
+
+
+  // Ensure No Individual Updates
+  this->FreezeUpdates=1;
+  this->Identity();
+  this->Put(0,pos[0]);   this->Put(1,pos[1]);   this->Put(2,pos[2]);
+  this->Put(3,rot[0]);   this->Put(4,rot[1]);   this->Put(5,rot[2]);
+  this->Put(6,sc[0]*100.0);   this->Put(7,sc[1]*100.0);   this->Put(8,sc[2]*100.0);
+  this->SetDistortionMode(0);
+  this->FreezeUpdates=0;
+  this->UpdateParameters();
+ 
+  return 0;
+}
+//---------------------------------------------------------------------------------------------
+int vtkpxLinearTransform::GenerateUpdateTransform(vtkTransform* combined,
+						  vtkImageData* reference,int ref_orientation,
+						  vtkImageData* transform,int trn_orientation)
+{
+  if (reference==NULL || transform==NULL || combined==NULL)
+    {
+      combined->Identity();
+      fprintf(stderr,"Here\n");
+      combined->Concatenate(this->GetMatrix());
+      return 0;
+    }
+
+  combined->Identity();
+
+  //  ref_orientation=Irange(ref_orientation,0,2);
+  //  trn_orientation=Irange(trn_orientation,0,2);
+  
+  int   rdim[3],tdim[3];
+  double rsp[3],tsp[3];
+
+  reference->GetSpacing(rsp); reference->GetDimensions(rdim);
+  transform->GetSpacing(tsp); transform->GetDimensions(tdim);
+
+  float shift[3],minusshift[3];
+  for (int i=0;i<=2;i++)
+    {
+      shift[i]=0.5*tsp[i]*float(tdim[i]-1);
+      minusshift[i]=-0.5*rsp[i]*float(rdim[i]-1);
+    }
+
+  return this->GenerateUpdateTransform(combined,minusshift,ref_orientation,shift,trn_orientation);
+
+}
+//---------------------------------------------------------------------------------------------
+int vtkpxLinearTransform::GenerateUpdateTransform(vtkTransform* combined,
+						  float minusshift[3],int ref_orientation,
+						  float shift[3],int trn_orientation)
+{
+  if (combined==NULL)
+    return 0;
+
+  vtkMatrix4x4* mat=vtkMatrix4x4::New();
+  double ori[3],sp[3];int d[3];
+  vtkpxUtil::ReOrientMatrix(ori,sp,d,ref_orientation,trn_orientation,mat,1);
+
+  vtkTransform* Orient=vtkTransform::New();
+  Orient->Identity();
+  Orient->PostMultiply();
+  Orient->Concatenate(mat);
+  Orient->Inverse();
+  
+
+  /*  fprintf(stderr,"Reference Orientation=%d Transform=%d\n",ref_orientation,trn_orientation);
+      fprintf(stderr,"Shift = %.2f %.2f %.2f\n mShift=%.2f %.2f %.2f\n",
+      shift[0],shift[1],shift[2],minusshift[0],minusshift[1],minusshift[2]);*/
+
+  combined->Identity();
+  combined->PostMultiply();
+  combined->Translate(minusshift);
+  combined->Concatenate(this->GetMatrix());
+  combined->Concatenate(Orient);
+  combined->Translate(shift);
+
+  /*  fprintf(stdout,"\n Printing Combined\n");
+      LinPrint(this->GetMatrix(),"Input Matrix");
+      LinPrint(mat,"Reorient Matrix");
+      LinPrint(combined->GetMatrix(),"Combined Matrix");*/
+  mat->Delete();
+  Orient->Delete();
+  return 1;
+}
+			      
+//---------------------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Registration/vtkpxLinearTransform.h b/bioimagesuite30_src/Registration/vtkpxLinearTransform.h
new file mode 100644
index 0000000..36bdbda
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxLinearTransform.h
@@ -0,0 +1,182 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+
+
+#ifndef __vtkpxLinearTransform_h
+#define __vtkpxLinearTransform_h
+
+#include "vtkTransform.h"
+#include "vtkMatrix4x4.h"
+#include "vtkDoubleArray.h"
+
+class vtkImageData;
+
+class vtkpxLinearTransform : public vtkTransform
+{
+ public:
+  static vtkpxLinearTransform *New();
+  vtkTypeMacro(vtkpxLinearTransform,vtkTransform);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Set the parameters
+  void SetParameters(vtkDoubleArray *parameters);
+  void SetParameters(vtkDoubleArray *parameters,int frame);
+  void GetParameters(vtkDoubleArray *parameters);
+  void GetParameters(vtkDoubleArray *parameters,int frame);
+
+  // Description:
+  // Puts a transformation parameter (transformation matrix is updated)
+  void   Put(int, float);
+  void   Set(int a, float v) {  Put(a,v);}
+  /// Gets a transformation parameter
+  float Get(int) const;
+
+  void SetFlipX(int f);
+  void SetFlipY(int f);
+  void SetFlipZ(int f);
+  vtkGetMacro(FlipX, int);
+  vtkGetMacro(FlipY, int);
+  vtkGetMacro(FlipZ, int);
+  
+  // Description:
+  // Stop Auto Updates
+  vtkSetClampMacro(FreezeUpdates,int,0,1);
+  vtkGetMacro(FreezeUpdates,int);
+
+  void SetDistortionMode(int m);
+  vtkGetMacro(DistortionMode, int);
+
+  // Description:
+  // Load / Save Transformation
+  virtual int Save(char* fname);
+  virtual int Load(char* fname);
+
+  // Description:
+  // Invert the transformation.  This will also set a flag so that
+  // the transformation will use the inverse of its Input, if an Input
+  // has been set.
+  void Inverse();
+  void UpdateParameters();
+
+  // Description:
+  // Number Of Parameters
+  virtual int GetNumberOfParameters() { return 19;}
+
+  // Description:
+  // Set Identity
+  virtual void Identity();
+
+  // Description:
+  // Copy
+  virtual void Copy(vtkpxLinearTransform* other);
+
+
+  // Description:
+  // This is key code for setting/exporting transformation given an input
+  // and images of different orientations
+
+  int ManualSetParameters(float tx,float ty,float tz,
+			  float rx,float ry,float rz,
+			  float sx,float sy,float sz,
+			  vtkImageData* reference,int ref_orientation,
+			  vtkImageData* transform,int trn_orientation,
+			  vtkTransform* combined);
+  
+  int ExtractParameters(vtkAbstractTransform* tr,int nparam,
+			vtkImageData* reference,int ref_orientation,
+			vtkImageData* transform,int trn_orientation);
+
+
+  int GenerateUpdateTransform(vtkTransform* output,
+			      vtkImageData* reference,int ref_orientation,
+			      vtkImageData* transform,int trn_orientation);
+			      
+
+
+  int GenerateUpdateTransform(vtkTransform* output,
+			      float minusshift[3],int ref_orientation,
+			      float shift[3],int trn_orientation);
+			      
+
+
+  
+protected:
+  vtkpxLinearTransform ();
+  ~vtkpxLinearTransform ();
+
+//BTX
+  /// Scaling along the x-axis, y-axis, z-axis
+  float _sx,_sy,_sz;
+  /// Skew angle in the x-y ...  plane (in degrees)
+  float _sxy, _syx,_syz,_szy,_szx,_sxz;
+  /// Translation along the x-axis (in mm)
+  float _tx,_ty, _tz;
+  /// Rotation around the x-axis (in degrees)
+  float _rx,_ry,_rz ;
+
+  int FlipX;
+  int FlipY;
+  int FlipZ;
+
+  int DistortionMode;
+  int FreezeUpdates;
+//ETX
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxMidlineSymmetricRegistration.cpp b/bioimagesuite30_src/Registration/vtkpxMidlineSymmetricRegistration.cpp
new file mode 100644
index 0000000..870f618
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxMidlineSymmetricRegistration.cpp
@@ -0,0 +1,118 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+/*=========================================================================*/
+#include "vtkpxMidlineSymmetricRegistration.h"
+#include "vtkpxRegistration.h"
+#include "vtkbisImageReslice.h"
+#include "vtkImageFlip.h"
+#include "vtkpxUtil.h"
+#include "vtkObjectFactory.h"
+
+
+vtkpxMidlineSymmetricRegistration* vtkpxMidlineSymmetricRegistration::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxMidlineSymmetricRegistration");
+  if(ret)
+    {
+      return (vtkpxMidlineSymmetricRegistration*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxMidlineSymmetricRegistration;
+}
+
+vtkpxMidlineSymmetricRegistration::vtkpxMidlineSymmetricRegistration() 
+{
+  this->MidlineSymmetricMode=1;
+}
+
+int vtkpxMidlineSymmetricRegistration::InitializeAll() 
+{
+  this->TranslationY=0;
+  this->TranslationZ=0;
+  this->RotationX=0;
+  return vtkpxLinearRegistration::InitializeAll();
+}
+
+double vtkpxMidlineSymmetricRegistration::Evaluate()
+{
+  this->LastSmoothness=0.0;
+  static int count=0;
+  vtkImageData* ref=this->SampledReferenceImage;
+  vtkImageData* targ=this->SampledTransformImage;
+  vtkTransform* trans=this->LinearTransform;
+  vtkpxJointHistogram* histo=this->Histogram;
+  int similaritymeasure=this->SimilarityMeasure;
+  int interp=this->InterpolationMode;
+  int reset=1;
+
+  // The magic is here ... create a composite image and add it up ...
+  // ----------------------------------------------------------------
+
+  if (ref==NULL || targ==NULL || trans==NULL || histo==NULL)
+    return 0.0;
+
+  if (interp<0)
+    interp=-interp;
+
+  if (interp<0 || interp>1)
+    interp=3;
+  
+  vtkbisImageReslice* resl=vtkbisImageReslice::New(); resl->OptimizationOff();
+  resl->SetInput(targ);
+  resl->SetInformationInput(ref);
+  resl->SetResliceTransform(trans);
+  resl->SetInterpolationMode(interp);
+  resl->Update();
+  
+  vtkImageFlip* flip=vtkImageFlip::New();
+  flip->SetInput(resl->GetOutput());
+  flip->SetFilteredAxis(0);
+  flip->PreserveImageExtentOn();
+  flip->Update();
+
+  /*  if (count==1)
+    {
+      vtkpxUtil::SaveAnalyze("flip.nii.gz",flip->GetOutput(),9);
+      vtkpxUtil::SaveAnalyze("resl.nii.gz",resl->GetOutput(),9);
+    }
+    ++count;*/
+
+
+  histo->FillHistogram(flip->GetOutput(),resl->GetOutput(),reset);
+  float val=histo->Similarity(similaritymeasure);
+  
+  resl->Delete();
+  this->LastSimilarity=val;
+  return this->LastSimilarity;
+
+}
+
diff --git a/bioimagesuite30_src/Registration/vtkpxMidlineSymmetricRegistration.h b/bioimagesuite30_src/Registration/vtkpxMidlineSymmetricRegistration.h
new file mode 100644
index 0000000..843d958
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxMidlineSymmetricRegistration.h
@@ -0,0 +1,88 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+
+#ifndef _VTKPXMIDLINEREGISTRATION_H
+#define _VTKPXMIDLINEREGISTRATION_H
+
+#include "vtkpxLinearRegistration.h"
+
+class vtkpxMidlineSymmetricRegistration : public vtkpxLinearRegistration {
+
+public:
+  static vtkpxMidlineSymmetricRegistration* New();
+  vtkTypeMacro(vtkpxMidlineSymmetricRegistration,vtkpxLinearRegistration);
+
+protected:
+  // Make all these protected 
+  // Constructor
+  vtkpxMidlineSymmetricRegistration();
+  vtkpxMidlineSymmetricRegistration(const vtkpxMidlineSymmetricRegistration&) {};
+  void operator=(const vtkpxMidlineSymmetricRegistration&) {};
+
+  // Description:
+  // Evaluates the registration. This function evaluates the registration by
+  // looping over the target image and interpolating the transformed source 
+  // image while filling the joint histogram. This function returns the value
+  // of the similarity measure using Similarity().
+  virtual double Evaluate();
+
+  virtual int InitializeAll();
+
+
+
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxNonLinearIntegratedRegistration.cpp b/bioimagesuite30_src/Registration/vtkpxNonLinearIntegratedRegistration.cpp
new file mode 100644
index 0000000..c628059
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxNonLinearIntegratedRegistration.cpp
@@ -0,0 +1,553 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxNonLinearIntegratedRegistration.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/04/16 17:51:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxNonLinearIntegratedRegistration.h"
+#include "vtkObjectFactory.h"
+#include "pxutil.h"
+#include "vtkbisImageReslice.h"
+#include "vtkpxUtil.h"
+#include "vtkpxImageExtractVOI.h"
+#include "vtkpxOptimizer.h"
+#include "vtkMath.h"
+
+vtkpxNonLinearIntegratedRegistration* vtkpxNonLinearIntegratedRegistration::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxNonLinearIntegratedRegistration");
+  if(ret)
+    {
+    return (vtkpxNonLinearIntegratedRegistration*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxNonLinearIntegratedRegistration;
+  
+}
+
+
+vtkpxNonLinearIntegratedRegistration::vtkpxNonLinearIntegratedRegistration()
+{
+  this->RPMEstimator=vtkpxRPMCorrespondenceFinder::New();
+  this->PointsWeight=0.01;
+  this->WholeImage=1;
+  this->MarginSize=0.1;
+  this->FixedCorrespondences=1;
+}
+
+vtkpxNonLinearIntegratedRegistration::~vtkpxNonLinearIntegratedRegistration() 
+{
+  if (this->RPMEstimator!=NULL)
+    this->RPMEstimator->Delete();
+}
+
+//-------------------------------------------------------------------------
+
+int vtkpxNonLinearIntegratedRegistration::InitializeAll() 
+{
+  vtkpxNonLinearRegistration::InitializeAll();
+  if (this->WholeImage==1)
+    {
+      fprintf(stderr,"Using Whole Image\n");
+      return 1;
+    }
+
+  
+  double bounds[6];
+  vtkPolyData* source=this->RPMEstimator->GetSource();
+  if (source!=NULL)
+    source->GetPoints()->GetBounds(bounds);
+
+  fprintf(stderr,"Source Bounds = %.1f:%.1f %.1f:%.1f %.1f:%.1f\n",
+	  bounds[0],bounds[1],
+	  bounds[2],bounds[3],
+	  bounds[4],bounds[5]);
+
+  vtkImageData* tmp=vtkImageData::New();
+  tmp->CopyStructure(this->ReferenceImage);
+  tmp->SetScalarTypeToUnsignedChar();
+  tmp->AllocateScalars();
+
+  bounds[0]=bounds[0]-this->MarginSize*(bounds[1]-bounds[0]);
+  bounds[1]=bounds[1]+this->MarginSize*(bounds[1]-bounds[0]);
+  bounds[2]=bounds[2]-this->MarginSize*(bounds[3]-bounds[2]);
+  bounds[3]=bounds[3]+this->MarginSize*(bounds[3]-bounds[2]);
+  bounds[4]=bounds[4]-this->MarginSize*(bounds[5]-bounds[4]);
+  bounds[5]=bounds[5]+this->MarginSize*(bounds[5]-bounds[4]);
+
+  fprintf(stderr,"Enlarged Bounds (%.2f) = %.1f:%.1f %.1f:%.1f %.1f:%.1f\n",
+	  this->MarginSize,
+	  bounds[0],bounds[1],
+	  bounds[2],bounds[3],
+	  bounds[4],bounds[5]);
+
+  double ori[3]; tmp->GetOrigin(ori);
+  double sp[3];  tmp->GetSpacing(sp);
+
+
+  bounds[0]=(bounds[0]-ori[0])/sp[0];
+  bounds[1]=(bounds[1]-ori[0])/sp[0];
+  bounds[2]=(bounds[2]-ori[1])/sp[1];
+  bounds[3]=(bounds[3]-ori[1])/sp[1];
+  bounds[4]=(bounds[4]-ori[2])/sp[2];
+  bounds[5]=(bounds[5]-ori[2])/sp[2];
+
+  fprintf(stderr,"Voxel Bounds (%.2f) = %.1f:%.1f %.1f:%.1f %.1f:%.1f\n",
+	  this->MarginSize,
+	  bounds[0],bounds[1],
+	  bounds[2],bounds[3],
+	  bounds[4],bounds[5]);
+
+
+  int   dim[3]; tmp->GetDimensions(dim);
+
+  vtkDataArray* scal=tmp->GetPointData()->GetScalars();
+  int index=0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  if (i>bounds[0] && i<bounds[1] && j>bounds[2] && j<bounds[3] && k>bounds[4] && k<bounds[5])
+	    scal->SetComponent(index,0,1);
+	  else
+	    scal->SetComponent(index,0,0);
+	  ++index;
+	}
+
+  this->SetImageMask(tmp);
+
+  tmp->Delete();
+  return 1;
+
+}
+//-------------------------------------------------------------------------
+int vtkpxNonLinearIntegratedRegistration::Initialize(int level) 
+{
+  // Different Procedure for toplevel and remaining levels
+  // In top level initialize using InitialTransform
+  // in other levels initialize using previous grid transform
+
+  vtkpxNonLinearRegistration::Initialize(level);
+
+  if (level==this->NumberOfLevels)
+    RPMEstimator->Initialize(NULL);
+  this->GridTransform->FormCollectionStructure(RPMEstimator->GetPointsX(),RPMEstimator->GetCollection(),0.001);
+  return 1;
+}
+//-------------------------------------------------------------------------
+double vtkpxNonLinearIntegratedRegistration::Evaluate()
+{
+  if (this->LastTargetImage==NULL)
+    this->LastTargetImage=vtkImageData::New();
+
+  vtkpxRegistration::ResliceImage(this->LastTargetImage,this->SampledTransformImage,
+				  this->SampledReferenceImage,this->ComboTransform,1);
+  this->Histogram->FillHistogram(this->SampledReferenceImage,this->LastTargetImage,1);  
+  this->LastSimilarity=this->Similarity(this->Histogram);
+
+  if (this->Lambda>0.000001)
+    this->LastSmoothness=this->ComputeInternalEnergy(this->GridTransform);
+  else
+    this->LastSmoothness=0.0;
+  //  fprintf(stderr,"Last sim=%.4f lastsmo=%.4f \t",this->LastSimilarity,this->LastSmoothness);
+  
+  this->LastFitError=this->ComputeTotalApproximationError(this->LastFitAbsError,0);
+  /*double v2=0.0;
+    double v1=this->GridTransform->TestWeightedApproximation(RPMEstimator->GetPointsX(),
+							   RPMEstimator->GetPointsVY(),
+							   RPMEstimator->GetM_Outliers_Column(),
+							   v2);
+  
+    fprintf(stderr,"Comparing errors direct (%.3f,%.3f)  new (%.3f,%.3f)\n",
+    v1,v2,this->LastFitAbsError,this->LastFitError);*/
+
+
+  return this->LastSimilarity-this->LastSmoothness*this->Lambda-this->PointsWeight*this->LastFitError;
+}
+//-------------------------------------------------------------------------
+
+void vtkpxNonLinearIntegratedRegistration::GenerateOutput(int level, int step,int iter,double stepsize,
+							  double actualSimilarity)
+{
+  if (iter>=100)
+    iter=99;
+
+  sprintf(this->OutputStatus,"Level=%2d Step=%2d iter=%2d stepsize=%.3f: sim=%8.6f (int=%8.6f pt2=%8.6f, l*sm=%8.6f (sm=%9.6f, ptd=%8.6f))\n",
+	  level,step,iter,stepsize,actualSimilarity,
+	  this->LastSimilarity,this->LastFitError,this->LastSmoothness*this->Lambda,
+	  this->LastSmoothness,this->LastFitAbsError);
+  this->UpdateProgress(this->LastProgress);
+  //  vtkpxAbstractIntensityRegistration::GenerateOutput(level,step,iter,stepsize,actualSimilarity);
+  return;
+}
+
+
+//-------------------------------------------------------------------------
+// Optimizer Stuff 
+//-------------------------------------------------------------------------
+double vtkpxNonLinearIntegratedRegistration::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+
+{
+
+  if (grad->GetNumberOfComponents()!=1 || grad->GetNumberOfTuples()!=this->NumberOfControlPoints*3)
+    {
+      grad->SetNumberOfComponents(1);
+      grad->SetNumberOfTuples(this->NumberOfControlPoints*3);
+    }
+
+  OptimizationStructure.old_similarity=this->OptimizerValue(params);
+
+  // Calculate gradient 
+  double GradientNorm = 0;
+
+  int per=this->NumberOfControlPoints/10;
+  int count=0;
+  int count2=0;
+  
+  grad->FillComponent(0,0.0);
+
+  
+  //  this->GenerateOutput(OptimizationStructure.level,
+  //		       -1,-1,OptimizationStructure.step,
+  //		       OptimizationStructure.old_similarity);
+  fprintf(stderr,"\nOptimizer Computing Gradients : (%5.3f)",OptimizationStructure.step);
+
+  //int mid=this->NumberOfControlPoints;
+
+  RPMEstimator->GetCollection()->InitTraversal();
+
+  int debug=0;
+  for (int i = 0; i < this->NumberOfControlPoints; i++)
+    {
+      vtkFloatArray* indices=(vtkFloatArray*)RPMEstimator->GetCollection()->GetNextItemAsObject();
+
+      ++count;
+      if (count==per)
+	{
+	  fprintf(stderr,"%.1f ",double(count2)*10.0);
+	  count=0;
+	  ++count2;
+	  if (count2==10)
+	    fprintf(stderr,"\n");
+	}
+
+      if (this->Status->GetComponent(i,0)+
+	  this->Status->GetComponent(i,1)+
+	  this->Status->GetComponent(i,2) > 0 )
+	{
+	  double p[3]; this->GridTransform->GetControlPointLocation(i,p);
+	  // Determine the area in which we have to update our similarity measure
+	  // p1 = upper left , p2=lower right
+
+	  // Extract Relevant Portion of the Image
+	  vtkpxImageExtractVOI* voi=vtkpxImageExtractVOI::New();
+	  voi->SetInput(this->SampledReferenceImage);
+	  voi->SetRegion(p,OptimizationStructure.gridspacing,this->WindowSize);
+	  voi->Update();
+
+	  vtkpxImageExtractVOI* voi2=vtkpxImageExtractVOI::New();
+	  voi2->SetInput(this->LastTargetImage);
+	  voi2->SetRegion(p,OptimizationStructure.gridspacing,this->WindowSize);
+	  voi2->Update();
+
+	  for (int j=0;j<=2;j++)
+	    {
+	      if (this->Status->GetComponent(i,j)>0)
+		{
+		  this->GridTransform->ShiftControlPoint(i,j,-OptimizationStructure.step);
+		  
+		  double e1 = this->EvaluatePiece(voi->GetOutput(),
+						  this->SampledTransformImage,
+						  voi2->GetOutput(),NULL,NULL,i);
+		  double pe1_2=0.0;
+		  if (this->PointsWeight>0.00001)
+		    pe1_2=this->ComputeApproximationErrorAtControlPoint(indices,debug);
+
+		  
+		  double l1=0.0;
+		  if (this->Lambda>0.0001)
+		    l1 = this->ComputeInternalEnergy(this->GridTransform,i);
+		  double s1=e1-this->Lambda*l1-this->PointsWeight*pe1_2;
+		  
+		  this->GridTransform->ShiftControlPoint(i,j,+2.0*OptimizationStructure.step);
+		  double e2 =this->EvaluatePiece(voi->GetOutput(),
+						 this->SampledTransformImage,
+						 voi2->GetOutput(),NULL,NULL,i);
+		  double pe2_2=0.0;
+		  if (this->PointsWeight>0.00001)
+		    if (this->PointsWeight>0.00001)
+		      pe2_2=this->ComputeApproximationErrorAtControlPoint(indices,debug);
+		  
+		  double l2=0.0;
+		  if (this->Lambda>0.0001)
+		    l2 = this->ComputeInternalEnergy(this->GridTransform,i);
+		  double s2=e2-l2*this->Lambda-this->PointsWeight*pe2_2;
+
+		  this->GridTransform->ShiftControlPoint(i,j,-OptimizationStructure.step);
+		  grad->SetComponent(i*3+j,0,-(s2-s1));
+		  GradientNorm+=pow(s2-s1,2.0);
+		}
+	    }
+	  voi->Delete();
+	  voi2->Delete();
+	}
+    }
+
+  GradientNorm = (sqrt(GradientNorm));
+  double sc=OptimizationStructure.step/GradientNorm;
+
+  // Normalize vector
+  if (GradientNorm > 0)
+    this->GridTransform->ScaleGradients(grad,sc);
+  else 
+    grad->FillComponent(0,0.0);
+  fprintf(stderr,"Gradient Norm=%.5f scale=%.5f\n",GradientNorm,sc);
+  return GradientNorm;
+
+}
+//-------------------------------------------------------------------------
+int vtkpxNonLinearIntegratedRegistration::ComputeRegistration(int level)
+{  
+  /*  this->RPMEstimator->WarpAndUpdateCorrespondence(this->GridTransform,this->RPMEstimator->GetTemperature());  
+  vtkpxNonLinearRegistration::ComputeRegistration(level);
+  return 1;*/
+
+  fprintf(stderr,"Computing Registration level=%d\n",level);
+  fprintf(stderr,"Updating RPM Estimator Correspondence stuff\n");
+  this->RPMEstimator->WarpAndUpdateCorrespondence(this->GridTransform,this->RPMEstimator->GetTemperature());  
+
+  fprintf(stderr,"On to estimation\n");
+  double step=this->CurrentStepSize;
+  double origin[3],spacing[3],gridspacing[3];
+  int   dimensions[3];
+  this->GridTransform->GetDisplacementGrid()->GetSpacing(gridspacing);
+  this->SampledReferenceImage->GetOrigin(origin);
+  this->SampledReferenceImage->GetSpacing(spacing);
+  this->SampledReferenceImage->GetDimensions(dimensions);
+  
+  vtkDoubleArray* grad=vtkDoubleArray::New();
+  grad->SetNumberOfComponents(3);
+  grad->SetNumberOfTuples(this->NumberOfControlPoints);
+
+
+
+
+  double origptsweights=this->PointsWeight;
+
+  for (int st=1;st<=this->NumberOfSteps;st++)
+    {
+      double old_similarity = this->Evaluate();
+      this->PointsWeight=origptsweights*double(st)/double(this->NumberOfSteps);
+      fprintf(stderr,"\n ---------------------------------------------------- \n Points Weight=%.5f\n\n",this->PointsWeight);
+      double new_similarity=this->Optimize(grad,old_similarity,step,level,
+					  origin,spacing,dimensions,gridspacing);
+      this->GenerateOutput(level,st,this->NumberOfIterations,step,new_similarity);
+    }
+
+  grad->Delete();
+  return 1;
+}
+//-------------------------------------------------------------------------
+double vtkpxNonLinearIntegratedRegistration::OnBeginIteration(vtkDoubleArray* )
+{
+  if (this->FixedCorrespondences==0)
+    {
+      fprintf(stderr,"Updating Corresspondences!");
+      this->RPMEstimator->WarpAndUpdateCorrespondence(this->GridTransform,this->RPMEstimator->GetTemperature());
+    }
+  return 1.0;
+}
+
+int vtkpxNonLinearIntegratedRegistration::FinalizeAll()
+{
+  return vtkpxNonLinearRegistration::FinalizeAll();
+}
+
+//-------------------------------------------------------------------------
+double vtkpxNonLinearIntegratedRegistration::ComputeApproximationErrorAtControlPoint(vtkFloatArray* indices,int debug)
+{
+  
+  /*  double other=0.0;
+  this->GridTransform->TestWeightedApproximation(RPMEstimator->GetPointsX(),
+						 RPMEstimator->GetPointsVY(),
+						 RPMEstimator->GetM_Outliers_Column(),
+						 other);*/
+
+  vtkPoints* points=RPMEstimator->GetPointsX();
+  vtkPoints* points2=RPMEstimator->GetPointsVY();
+  vtkpxMatrix* lsqweights=RPMEstimator->GetM_Outliers_Column();
+  int useweights=0;
+  if (lsqweights!=NULL)
+    {
+      if (lsqweights->GetSize()[0]>=points->GetNumberOfPoints())
+	useweights=1;
+    }
+
+  int np=indices->GetNumberOfTuples();
+  double nump=double(points->GetNumberOfPoints());
+  double x[3],tx[3],sum2=0.0;
+
+  if (debug>0)
+    fprintf(stderr,"\nApproximation error debug=%d, np=%d\t",debug,np);
+
+  if (np>0)
+    {
+      for (int ki=0;ki<np;ki++)
+	{
+	  int i=(int)indices->GetComponent(ki,0);
+	  double w=indices->GetComponent(ki,1);
+	  points->GetPoint(i,x);
+	  points2->GetPoint(i,tx);
+	  this->GridTransform->TransformPoint(x,x);
+	  double dist= (vtkMath::Distance2BetweenPoints(x, tx));
+	  double w2=1.0;
+	  if (useweights)
+	    w2=lsqweights->GetDirectElement(i,0);
+	  sum2+=w*w2*dist;
+	}
+      sum2/=(nump);
+      if (debug>0)
+	fprintf(stderr,"Error=%.8f\n",sum2);
+      return sum2;
+    }
+  return 0.0;
+}
+
+double vtkpxNonLinearIntegratedRegistration::ComputeTotalApproximationError(double& lastfiterror,int debug)
+{
+  vtkPoints* points=RPMEstimator->GetPointsX();
+  vtkPoints* points2=RPMEstimator->GetPointsVY();
+  int nc=points->GetNumberOfPoints();
+
+  vtkpxMatrix* lsqweights=RPMEstimator->GetM_Outliers_Column();    
+  int useweights=0;
+  if (lsqweights!=NULL)
+    {
+      if (lsqweights->GetSize()[0]>=points->GetNumberOfPoints())
+	useweights=1;
+    }
+
+  lastfiterror=0.0;
+  double sum2error=0.0;
+
+  if (nc<1)
+    return 0.0;
+
+  double x[3],tx[3];
+  for (int i=0;i<nc;i++)
+    {
+      points->GetPoint(i,x);
+      points2->GetPoint(i,tx);
+      this->GridTransform->TransformPoint(x,x);
+      double d=vtkMath::Distance2BetweenPoints(x,tx);
+      double w=1.0;
+      if (useweights)
+	w=lsqweights->GetDirectElement(i,0);
+      lastfiterror+=w*sqrt(d);
+      sum2error+=w*d;
+    }
+  lastfiterror/=double(nc);
+  sum2error/=double(nc);
+
+  if (debug)
+    fprintf(stderr,"Total Error =%.6f (%.6f) \n",lastfiterror,sum2error);
+
+  return sum2error;
+ 
+}
+//-------------------------------------------------------------------------
+int vtkpxNonLinearIntegratedRegistration::InitializeTransformation(int level) 
+{
+  int proceed=0;
+
+
+  if (level==1 && this->NumberOfLevels==1)
+    {
+      if (this->InitialTransform!=NULL)
+	{
+	  if (this->InitialTransform->IsA("vtkpxComboTransform")==1)
+	    {
+	      proceed=1;
+	    }
+	}
+    }
+
+  if (proceed==0)
+    {
+      return vtkpxNonLinearRegistration::InitializeTransformation(level);
+    }
+
+  fprintf(stderr,"In vtkpxNonLinearIntegratedRegistration::InitializeTransform\n");
+
+  this->LinearTransform=vtkTransform::New();
+  this->GridTransform=vtkpxGridTransform::New();
+  this->ComboTransform=vtkpxComboTransform::New();
+  
+  vtkpxComboTransform* x=(vtkpxComboTransform*)(this->InitialTransform);
+  this->LinearTransform->Identity();
+  this->LinearTransform->Concatenate(x->GetLinearTransform()->GetMatrix());
+  this->ComboTransform->SetNonLinearFirst(x->GetNonLinearFirst());
+  
+  vtkImageData* tmp=vtkImageData::New();
+  tmp->DeepCopy(x->GetGridTransform()->GetDisplacementGrid());
+  
+  this->GridTransform->SetInterpolationMode(x->GetGridTransform()->GetInterpolationMode());
+  this->GridTransform->SetDisplacementGrid(tmp);
+  tmp->Delete();
+  
+  this->ComboTransform->SetTransformations(this->LinearTransform,this->GridTransform);
+  this->NumberOfControlPoints=this->GridTransform->GetNumberOfControlPoints();
+  fprintf(stderr,"In vtkpxNonIntegratedLinearRegistration::InitializeTransform Done\n");
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Registration/vtkpxNonLinearIntegratedRegistration.h b/bioimagesuite30_src/Registration/vtkpxNonLinearIntegratedRegistration.h
new file mode 100644
index 0000000..2161557
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxNonLinearIntegratedRegistration.h
@@ -0,0 +1,186 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxNonLinearRegistration.h,v $
+  Language:  C++
+  Date:      $Date: 2002/04/16 13:19:58 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxNonLinearRegistration - Filter for ffd registration based on voxel similarity measures.
+
+// .SECTION Description
+// This class implements a registration filter for the non-rigid registration
+// of images.
+
+
+#ifndef _VTKPXNONLINEARINTREGISTRATION_H
+#define _VTKPXNONLINEARINTREGISTRATION_H
+
+#include "vtkpxNonLinearRegistration.h"
+#include "vtkImageData.h"
+#include "vtkpxGridTransform.h"
+#include "vtkpxComboTransform.h"
+#include "vtkDoubleArray.h"
+#include "vtkGeneralTransform.h"
+#include "vtkPointLocator.h"
+#include "vtkpxRPMCorrespondenceFinder.h"
+#include "vtkPoints.h"
+#include "vtkCollection.h"
+
+class  vtkpxNonLinearIntegratedRegistration : public vtkpxNonLinearRegistration {
+
+public:
+  static vtkpxNonLinearIntegratedRegistration* New();
+  vtkTypeMacro(vtkpxNonLinearIntegratedRegistration,vtkpxNonLinearRegistration);
+
+  // Description:
+  // Get Internal Transformation Stuff
+  vtkGetObjectMacro(RPMEstimator,vtkpxRPMCorrespondenceFinder);
+
+  
+  // Description:
+  // Relative Weight of Intensity to Points 
+  vtkGetMacro(PointsWeight,float);
+  vtkSetClampMacro(PointsWeight,float,0.0,1.0);
+
+  // Run Optimization for Level level
+  virtual int ComputeRegistration(int level);
+
+  // Description:
+  // Whole Image -- if set to 0 only register on part of the image covered by points 
+  vtkSetMacro(WholeImage,int);
+  vtkGetMacro(WholeImage,int);
+  vtkBooleanMacro(WholeImage,int);
+
+  // Description:
+  // If WholeImage==0 use this to bound the region to be registered on
+  vtkSetMacro(MarginSize,double);
+  vtkGetMacro(MarginSize,double);
+
+  // Description:
+  // FixedCorrespondencesk -- if 1 run RPM only once at the startof the registration
+  vtkSetMacro(FixedCorrespondences,int);
+  vtkGetMacro(FixedCorrespondences,int);
+  vtkBooleanMacro(FixedCorrespondences,int);
+
+protected:
+
+  // Make all these protected 
+  // Constructor
+  vtkpxNonLinearIntegratedRegistration();
+  virtual ~vtkpxNonLinearIntegratedRegistration();
+  vtkpxNonLinearIntegratedRegistration(const vtkpxNonLinearIntegratedRegistration&) {};
+  void operator=(const vtkpxNonLinearIntegratedRegistration&) {};
+
+  // Description:
+  // RPM Registration
+  vtkpxRPMCorrespondenceFinder* RPMEstimator;
+
+  // Description:
+  // PointsWeight
+  double PointsWeight;
+
+  // Description:
+  // Last Fitting Error
+  double LastFitError;
+  double LastFitAbsError;
+
+  // Description:
+  // Whole Image Stuff
+  int WholeImage;
+  double MarginSize;
+
+  // Description:
+  // Correspondence Stuff
+  int FixedCorrespondences;
+
+  // Description:
+  // Initial set up for the registration at a multiresolution level
+  virtual int InitializeAll();
+  virtual int Initialize(int);
+
+
+  // Description:
+  // Initial set up for the registration at a multiresolution level
+  virtual int FinalizeAll();
+
+  // Description:
+  // Generate Output
+  virtual void GenerateOutput(int level, int step,int iter,double stepsize,double simil);
+
+  // Description:
+  // Needed for Optimizer
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+
+  // Description:
+  // Evaluates the registration. This function evaluates the registration by
+  // looping over the target image and interpolating the transformed source 
+  // image while filling the joint histogram. This function returns the value
+  // of the similarity measure using Similarity().
+  virtual double Evaluate();
+
+  // Description:
+  // Needed for RPM Optimizer
+  virtual double OnBeginIteration(vtkDoubleArray* params);
+
+  // Description:
+  // Compute Distance Sub Error
+  virtual double ComputeApproximationErrorAtControlPoint(vtkFloatArray* indices,int debug=0);
+  virtual double ComputeTotalApproximationError(double& lastabsfiterror,int debug=0);
+					  
+  // Description:
+  // Called from Initialize to Initialize the Transformation
+  virtual int InitializeTransformation(int);
+  
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxNonLinearLabelRegistration.cpp b/bioimagesuite30_src/Registration/vtkpxNonLinearLabelRegistration.cpp
new file mode 100644
index 0000000..f588325
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxNonLinearLabelRegistration.cpp
@@ -0,0 +1,846 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+#include "vtkpxNonLinearLabelRegistration.h"
+#include "vtkObjectFactory.h"
+#include "pxutil.h"
+#include "vtkpxUtil.h"
+#include "vtkpxImageExtractVOI.h"
+#include "vtkpxOptimizer.h"
+#include "vtkTimerLog.h"
+#include "vtkCollection.h"
+#include "vtkImageCast.h"
+#include <vtkstd/algorithm>
+#include "vtkpxMath.h"
+
+vtkpxNonLinearLabelRegistration* vtkpxNonLinearLabelRegistration::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxNonLinearLabelRegistration");
+  if(ret)
+    {
+    return (vtkpxNonLinearLabelRegistration*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxNonLinearLabelRegistration;
+  
+}
+
+
+vtkpxNonLinearLabelRegistration::vtkpxNonLinearLabelRegistration()
+{
+  this->LastTargetImage=NULL;
+  this->ControlPointSpacing=20.0;
+  this->ControlPointSpacingRate=1.0;
+  this->GridTransform=NULL;
+  this->AppendTransformations=0;
+  this->InitialTransform=NULL;
+
+  this->ComboTransform=NULL;
+  this->LinearTransform=NULL;
+
+  this->Lambda=0.0;
+  this->Epsilon=0.003;
+  this->WindowSize=1.0;
+  this->UpdateTransform=vtkpxComboTransform::New();
+  this->UpdateTransform->SetNonLinearFirst(1);
+  this->InternalEnergyMode=0;
+  this->GradientScale=1.0;
+  this->CombinationMetric=1;
+  this->similarityarray=NULL;
+}
+
+vtkpxNonLinearLabelRegistration::~vtkpxNonLinearLabelRegistration() 
+{
+  if (this->GridTransform!=NULL)
+    this->GridTransform->Delete();
+
+
+  if (this->LinearTransform!=NULL)
+    this->LinearTransform->Delete();
+
+  if (this->ComboTransform!=NULL)
+    this->ComboTransform->Delete();
+
+
+
+  if (this->LastTargetImage!=NULL)
+    this->LastTargetImage->Delete();
+
+
+  if (this->similarityarray!=NULL)
+    delete [] this->similarityarray;
+
+  this->UpdateTransform->Delete();
+  this->SetInitialTransform(NULL);
+
+}
+//-------------------------------------------------------------------------
+void vtkpxNonLinearLabelRegistration::SetReferenceImage(vtkImageData* ref,int frame)
+{
+
+  // Ignoring frame here ...
+  if (ref==NULL)
+    return;
+
+  int nc=ref->GetNumberOfScalarComponents();
+  if (nc<1)
+    return;
+
+  if (this->ReferenceImage==NULL)
+    this->ReferenceImage=vtkImageData::New();
+
+  vtkImageCast* cst=vtkImageCast::New();
+  cst->SetInput(ref);
+  cst->SetOutputScalarTypeToShort();
+  cst->Update();
+
+  this->ReferenceImage->ShallowCopy(cst->GetOutput());
+  cst->Delete();
+
+  if (this->similarityarray!=NULL)
+    delete [] this->similarityarray;
+  this->similarityarray=new float[nc];
+}
+
+
+void vtkpxNonLinearLabelRegistration::SetTransformImage(vtkImageData* img,int frame)
+{
+  if (img==NULL)
+    return;
+
+  if (this->TransformImage==NULL)
+    this->TransformImage=vtkImageData::New();
+
+  vtkpxRegistration::ExtractComponentAndCastImageToShort(this->TransformImage,img,frame,0);
+}
+//-------------------------------------------------------------------------
+int vtkpxNonLinearLabelRegistration::InitializeAll() 
+{
+  vtkpxAbstractIntensityRegistration::InitializeAll();
+  this->ControlPointSpacing=Frange(this->ControlPointSpacing,
+				   this->MinimumResolution,
+				   50.0*this->MinimumResolution);
+  this->ControlPointSpacingRate=Frange(this->ControlPointSpacingRate,1.0,2.0);
+
+  if (this->NumberOfExtraLevels>0)
+    this->AppendTransformations=1;
+
+  this->NumberOfLevels=1;
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxNonLinearLabelRegistration::InitializeTransformation(int level) 
+{
+  fprintf(stderr,"In vtkpxNonLinearLabelRegistration::InitializeTransform level=%d\n",level);
+  double reduction=pow(this->ControlPointSpacingRate,double(level-1.0));
+
+  if (level==this->NumberOfLevels)
+    {
+      this->LinearTransform=vtkTransform::New();
+      this->GridTransform=vtkpxGridTransform::New();
+      this->ComboTransform=vtkpxComboTransform::New();
+      this->ComboTransform->SetNonLinearFirst(1);
+      this->LinearTransform->Identity();
+
+      if (this->InitialTransform==NULL)
+	{
+	 	  fprintf(stderr,"No initial transformation -- nothing special create grid");
+	  this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+							  this->ControlPointSpacing*reduction,0.0,
+							  NULL);
+	}
+      else if (this->InitialTransform->IsA("vtkLinearTransform")==1)
+	{
+	  // Just Linear Absorb
+	  fprintf(stderr,"Linear initial transformation");
+	  vtkLinearTransform* x=(vtkLinearTransform*)(this->InitialTransform);
+	  this->LinearTransform->Identity();
+	  this->LinearTransform->Concatenate(x->GetMatrix());
+	  this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+							  this->ControlPointSpacing*reduction,0.0);
+	}
+      else if (this->InitialTransform->IsA("vtkpxComboTransform")==1 || (this->InitialTransform->IsA("vtkpxGridTransform")==1))
+	{
+	  // Either a Grid or a combo
+	  // If Combo get linear component else set linear to identity
+	  fprintf(stderr,"Combo/Grid initial transformation");
+	  this->LinearTransform->Identity();
+	  vtkpxGridTransform* ingrid=NULL;
+	  if  (this->InitialTransform->IsA("vtkpxComboTransform")==1)
+	    {
+	      vtkpxComboTransform* x=(vtkpxComboTransform*)(this->InitialTransform);
+	      this->LinearTransform->Concatenate(x->GetLinearTransform()->GetMatrix());
+	      this->ComboTransform->SetNonLinearFirst(x->GetNonLinearFirst());
+	      ingrid=x->GetGridTransform();
+	    } 
+	  else
+	    {
+	      ingrid=(vtkpxGridTransform*)(this->InitialTransform);
+	    }
+	  
+	  if (this->ComboTransform->GetNonLinearFirst()==1)
+	    this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+							    this->ControlPointSpacing*reduction,0.0);
+	  else
+	    this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+							    this->ControlPointSpacing*reduction,0.0,
+							    this->LinearTransform);
+	  this->ComboTransform->SetTransformations(this->LinearTransform,ingrid);
+	  
+	  if (this->AppendTransformations)
+	    this->ComboTransform->AddGridTransform(this->GridTransform);
+	  else
+	    this->GridTransform->ApproximateTransformation(ingrid,1.0,12,1,0.05*this->MinimumResolution,0.01);
+	}
+      else
+	{
+	  fprintf(stderr,"Other initial transformation .. brute force approximate this and hope for the best");
+	  this->GridTransform=vtkpxGridTransform::New();
+	  this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+							  this->ControlPointSpacing*reduction,0.0,NULL);
+	  fprintf(stderr,"\n -------------------- Approximating Grid Transformation ---------------\n");
+	  this->GridTransform->ApproximateTransformation(this->InitialTransform,1.0,12,1,0.05*this->MinimumResolution,0.01);
+	  fprintf(stderr,"\n -------------------- Approximating Grid Transformation Done-----------\n");
+	}
+
+      this->ComboTransform->SetTransformations(this->LinearTransform,this->GridTransform);
+    }
+ else if (this->ControlPointSpacingRate>1)
+   {
+     vtkpxGridTransform* prevTransform=this->GridTransform;
+      this->GridTransform=vtkpxGridTransform::New();
+      this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+						      this->ControlPointSpacing*reduction,0.0,
+						      NULL);
+      
+      if (this->AppendTransformations)
+	{
+	  this->ComboTransform->AddGridTransform(this->GridTransform);
+	  
+	}
+      else
+	{
+	  if (prevTransform!=NULL)
+	    {
+	      fprintf(stderr,"\n -------------------- Approximating Grid Transformation ---------------\n");
+	      this->GridTransform->ApproximateTransformation(prevTransform);
+	      fprintf(stderr,"\n -------------------- Approximating Grid Transformation Done-----------\n");
+	    }
+	  
+	  this->ComboTransform->SetTransformations(this->LinearTransform,this->GridTransform);
+	}
+      prevTransform->Delete();
+    }
+  else
+    {
+      if (this->AppendTransformations)
+	{
+	  this->GridTransform=vtkpxGridTransform::New();
+	  this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+							  this->ControlPointSpacing*reduction,0.0,
+							  NULL);
+	  this->ComboTransform->AddGridTransform(this->GridTransform);
+	}
+      else
+	{
+	  fprintf(stderr,"Keeping the same transformation and refining");
+	}
+    }
+
+  this->NumberOfControlPoints=this->GridTransform->GetNumberOfControlPoints();
+  fprintf(stderr,"In vtkpxNonLinearLabelRegistration::InitializeTransform Done numnonlinear=%d\n",
+	  this->ComboTransform->GetNumberOfGridTransformations());
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxNonLinearLabelRegistration::Initialize(int level) 
+{
+  // Different Procedure for toplevel and remaining levels
+  // In top level initialize using InitialTransform
+  // in other levels initialize using previous grid transform
+
+  double reduction=pow(this->ResolutionRate,double(level-1.0));
+  this->CurrentStepSize=this->InternalStepSize*reduction;
+  this->CurrentResolution=this->InternalResolution*reduction;
+  this->InternalBlurFactor=0.0;
+
+  if (this->SampledReferenceImage==NULL)
+    this->SampledReferenceImage=vtkImageData::New();
+  if (this->SampledTransformImage==NULL)
+    this->SampledTransformImage=vtkImageData::New();
+
+  // -resolution = Nearest Neighbor!
+  this->SampledReferenceImage->DeepCopy(this->ReferenceImage);
+  this->SampledTransformImage->DeepCopy(this->TransformImage);
+  /*  vtkpxRegistration::ResampleAndSmoothImage(this->SampledReferenceImage,this->ReferenceImage,
+					    this->BaseResolution,
+					    0.0,
+					    -this->CurrentResolution,0);
+
+   
+  //  vtkpxRegistration::PrintImageInfo(this->SampledReferenceImage,"ResandSmooth");
+
+  vtkpxRegistration::ResampleAndSmoothImage(this->SampledTransformImage,this->TransformImage,
+					    this->BaseResolution,
+					    0.0,
+					    -this->CurrentResolution,0);*/
+
+  short minr=0,maxr=1,mint=0,maxt=1;
+  int num_ref,num_tar;
+
+  sprintf(this->OutputStatus,"Label Registration --- Going to Calc Range and Adjust \n\n");
+  this->UpdateProgress(this->LastProgress);
+
+  
+  if (this->Histogram!=NULL)
+    this->Histogram->Delete();
+  this->Histogram=NULL;
+
+  this->HistogramCollection=vtkCollection::New();
+  int nframes=this->SampledReferenceImage->GetNumberOfScalarComponents();
+
+  double r1[2]; this->SampledTransformImage->GetPointData()->GetScalars()->GetRange(r1);
+
+  double r2[2];
+  for (int ia=0;ia<nframes;ia++)
+    {
+      this->SampledReferenceImage->GetPointData()->GetScalars()->GetRange(r2,ia);
+      vtkpxJointHistogram* hist=vtkpxJointHistogram::New();
+      int r_bins=int(r2[1]);
+      int t_bins=int(r1[1]);
+
+      hist->Allocate(r_bins,t_bins);
+      fprintf(stderr,"------------------------- Label Reg -- Allocating Histogram ia=%d  (%d x %d)\n",ia,r_bins,t_bins);
+      this->HistogramCollection->AddItem(hist);
+      //      hist->Delete();
+    }
+
+  double sp1[3],sp2[3],or1[3],or2[3];
+  int   dim1[3],dim2[3];
+
+  this->SampledReferenceImage->GetSpacing(sp1);
+  this->SampledReferenceImage->GetDimensions(dim1);
+  this->SampledReferenceImage->GetOrigin(or1);
+  this->SampledTransformImage->GetSpacing(sp2);
+  this->SampledTransformImage->GetDimensions(dim2);
+  this->SampledTransformImage->GetOrigin(or2);
+
+  sprintf(this->OutputStatus,"\nEnd Of Initialization Of Level =%d,%d",level,this->NumberOfLevels);
+  sprintf(this->OutputStatus,
+	  "%s\n Reference = %d x %d x %d (%.2f %.2f %.2f) (or=%.1f,%.1f,%.1f), Range=%.0f:%.0f frames=%d\n",
+	  this->OutputStatus,dim1[0],dim1[1],dim1[2],sp1[0],sp1[1],sp1[2],or1[0],or1[1],or1[2],
+	  r2[0],r2[1],nframes);
+  sprintf(this->OutputStatus, 
+	  "%s\nTransform  = %d x %d x %d (%.2f %.2f %.2f) (or=%.1f,%.1f,%.1f), Range=%.0f:%.0f\n",
+	  this->OutputStatus,dim2[0],dim2[1],dim2[2],sp2[0],sp2[1],sp2[2],or2[0],or2[1],or2[2],
+	  r1[0],r1[1]);
+
+  
+  vtkDebugMacro(<<this->OutputStatus);
+  //fprintf(stderr,"%s\n",this->OutputStatus);
+  this->UpdateProgress(this->LastProgress);
+
+
+  fprintf(stderr,"Going to initialize transformation ...........\n");
+  this->InitializeTransformation(level);
+  fprintf(stderr,"Done with initialize transformation ...........\n");
+
+  if (this->LastTargetImage!=NULL)
+    this->LastTargetImage->Delete();
+  this->LastTargetImage=vtkImageData::New();
+
+
+  double sp[3]; this->GridTransform->GetGridSpacing(sp);
+  int    d[3]; this->GridTransform->GetGridDimensions(d);
+  sprintf(this->OutputStatus,"\n Transformation Spacing %.2f %.2f %.2f dimensions=%d x %d x %d\n",sp[0],sp[1],sp[2],d[0],d[1],d[2]);
+
+  sprintf(this->OutputStatus,"\n Combination Metric=%d",this->CombinationMetric);
+
+  this->UpdateProgress(this->LastProgress);
+
+
+
+
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxNonLinearLabelRegistration::FinalizeAll()
+{
+  this->LastTargetImage->Delete();
+  this->LastTargetImage=NULL;
+
+  return vtkpxAbstractIntensityRegistration::FinalizeAll();
+}
+//-------------------------------------------------------------------------
+// Compute Registration
+int vtkpxNonLinearLabelRegistration::ComputeRegistration(int level)
+{  
+
+  double step=this->CurrentStepSize;
+
+  double origin[3],spacing[3],gridspacing[3];
+  int   dimensions[3];
+  this->GridTransform->GetDisplacementGrid()->GetSpacing(gridspacing);
+  this->SampledReferenceImage->GetOrigin(origin);
+  this->SampledReferenceImage->GetSpacing(spacing);
+  this->SampledReferenceImage->GetDimensions(dimensions);
+  
+  vtkDoubleArray* grad=vtkDoubleArray::New();
+  grad->SetNumberOfComponents(3);
+  grad->SetNumberOfTuples(this->NumberOfControlPoints);
+
+
+  for (int st=1;st<=this->NumberOfSteps;st++)
+    {
+      fprintf(stderr,"Computing Optimization for Step %d/%d\n",st,this->NumberOfSteps);
+      double old_similarity = this->Evaluate();
+      double new_similarity=this->Optimize(grad,old_similarity,step,level,
+					  origin,spacing,dimensions,gridspacing);
+      this->GenerateOutput(level,st,this->NumberOfIterations,step,new_similarity);
+      step*=0.5;
+    }
+
+  grad->Delete();
+  return 1;
+}
+//-------------------------------------------------------------------------
+
+double vtkpxNonLinearLabelRegistration::Optimize(vtkDoubleArray* grad,double old_similarity,
+					   double step,int level,
+					   double origin[3],double spacing[3],
+					   int dimensions[3],double gridspacing[3])
+{
+  OptimizationStructure.SetValues(old_similarity,step,level,origin,spacing,dimensions,gridspacing);
+     
+  vtkpxOptimizer* optimizer=vtkpxOptimizer::New();
+  vtkDoubleArray* position=vtkDoubleArray::New();
+  vtkDoubleArray* temp=vtkDoubleArray::New();
+
+  this->GetCurrentParameters(position);
+  optimizer->SetMasterObject(this);
+  optimizer->SetTempArray(grad);
+  optimizer->SetEvaluateFunctionMethod(&vtkpxNonLinearLabelRegistration::CalculateFunction);
+  optimizer->SetEvaluateGradientMethod(&vtkpxNonLinearLabelRegistration::CalculateGradient);
+  optimizer->SetFeedbackMethod(&vtkpxNonLinearLabelRegistration::OptimizerFeedback);
+  optimizer->SetBeginIterationMethod(&vtkpxAbstractIntensityRegistration::OnBeginIteration);
+
+  double v=0.0;
+
+
+  fprintf(stderr,"In Non Label Linear Reg :: Optimize :: %d\n",this->OptimizationMethod);
+
+  switch (this->OptimizationMethod)
+    {
+    case 2:
+      v=optimizer->ComputePowell(position,temp,this->NumberOfIterations,0.001);
+      break;
+
+    case 3:
+      v=optimizer->ComputeGradientDescent(position,this->NumberOfIterations,0.001);
+      break;
+
+    case 4:
+      v=optimizer->ComputeConjugateGradient(position,this->NumberOfIterations,0.001);
+      break;
+
+    case 5:
+      v=optimizer->ComputeGradientDescent(position,this->NumberOfIterations,0.001);
+      if (level==1)
+	v=optimizer->ComputeConjugateGradient(position,this->NumberOfIterations,0.001);
+      break;
+
+    default:
+	v=optimizer->ComputeConjugateGradient(position,this->NumberOfIterations,0.001);
+    }
+
+  optimizer->Delete();
+  position->Delete();
+  temp->Delete();
+  return v;
+}
+//-------------------------------------------------------------------------
+double vtkpxNonLinearLabelRegistration::Evaluate()
+{
+  if (this->LastTargetImage==NULL)
+    this->LastTargetImage=vtkImageData::New();
+  
+  fprintf(stderr,"Optimizing Value\n");
+
+  vtkpxRegistration::ResliceImage(this->LastTargetImage,this->SampledTransformImage,
+				  this->SampledReferenceImage,this->ComboTransform,0);
+  
+
+  int nframes=this->SampledReferenceImage->GetNumberOfScalarComponents();
+  double sum=0.0;
+  for (int ia=0;ia<nframes;ia++)
+    {
+      vtkpxJointHistogram* hist=(vtkpxJointHistogram*)(this->HistogramCollection->GetItemAsObject(ia));
+      hist->FillHistogramComponent(this->SampledReferenceImage,this->LastTargetImage,ia,0,1);  
+      double v=this->Similarity(hist);
+      this->similarityarray[ia]=v;
+    }
+
+  this->LastSimilarity=this->ComputeCombinedValue(this->similarityarray,nframes);
+  if (this->Lambda>0.000001)
+    this->LastSmoothness=this->ComputeInternalEnergy(this->GridTransform);
+  else
+    this->LastSmoothness=0.0;
+  return this->LastSimilarity-this->LastSmoothness*this->Lambda;
+}
+//-------------------------------------------------------------------------
+double vtkpxNonLinearLabelRegistration::EvaluatePiece(vtkImageData* reference,
+						 vtkImageData* target,
+						 vtkImageData* previoustarget,
+						 int cpoint)
+
+{
+  //  fprintf(stderr,"Going to evaluete piece\n");
+
+  vtkImageData* tmp=vtkImageData::New();
+  vtkpxRegistration::ResliceImage(tmp,target,reference,this->ComboTransform,0);
+
+  // Remove Last Target Value
+
+  // Add New Value
+
+  int nframes=this->SampledReferenceImage->GetNumberOfScalarComponents();
+  double sume1=0.0;
+  double minvalue=0.0;
+  for (int ia=0;ia<nframes;ia++)
+    {
+      vtkpxJointHistogram* hist=(vtkpxJointHistogram*)(this->HistogramCollection->GetItemAsObject(ia));
+      hist->BackupHistogram();
+      hist->RemoveFromHistogramComponent(reference,previoustarget,ia,0);
+      hist->FillHistogramComponent(reference,tmp,ia,0,0);
+      this->similarityarray[ia]=this->Similarity(hist);
+      hist->ResetHistogram();
+    }
+
+  double e1=this->ComputeCombinedValue(this->similarityarray,nframes);
+
+  // Clean Up
+  tmp->Delete();
+  double l1=0.0;
+  if (this->Lambda>0.000001)
+    l1 = this->ComputeInternalEnergy(this->GridTransform,cpoint)*double(NumberOfControlPoints);
+  double s1=e1-this->Lambda*l1;
+ 
+  //  fprintf(stderr,"done with evaluate piece\n");
+  return s1;
+}
+
+//-------------------------------------------------------------------------
+void vtkpxNonLinearLabelRegistration::PrintInformation() 
+{
+  
+}
+//-------------------------------------------------------------------------
+
+void vtkpxNonLinearLabelRegistration::GenerateOutput(int level, int step,int iter,double stepsize,double actualSimilarity)
+{
+  if (iter>=100)
+    iter=99;
+
+  sprintf(this->OutputStatus,"Level=%2d Step=%2d iter=%2d stepsize=%.3f: tot=%8.6f (sim=%8.6f sm=%8.6f (dist=%.2f))",
+	  level,step,iter,stepsize,actualSimilarity,
+	  this->LastSimilarity,this->LastSmoothness*this->Lambda,
+	  this->LastSmoothness);
+  this->UpdateProgress(this->LastProgress);
+  vtkpxAbstractIntensityRegistration::GenerateOutput(level,step,iter,stepsize,actualSimilarity);
+  return;
+}
+
+//-------------------------------------------------------------------------
+vtkAbstractTransform* vtkpxNonLinearLabelRegistration::GetUpdateTransform()
+{
+  if (this->SampledReferenceImage==NULL || this->GridTransform==NULL)
+    return this->UpdateTransform;
+
+  return this->ComboTransform;
+}
+
+//-------------------------------------------------------------------------
+// Optimizer Stuff 
+//-------------------------------------------------------------------------
+void vtkpxNonLinearLabelRegistration::SetCurrentParameters(vtkDoubleArray* param)
+{
+  this->GridTransform->SetCurrentParameters(param);
+}
+//-------------------------------------------------------------------------
+void vtkpxNonLinearLabelRegistration::GetCurrentParameters(vtkDoubleArray* param)
+{
+  this->GridTransform->GetCurrentParameters(param);
+}
+//-------------------------------------------------------------------------
+double vtkpxNonLinearLabelRegistration::OptimizerValue(vtkDoubleArray* params)
+{
+  this->SetCurrentParameters(params);
+  return -this->Evaluate();
+}
+//-------------------------------------------------------------------------
+double vtkpxNonLinearLabelRegistration::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+
+{
+  if (grad->GetNumberOfComponents()!=1 || grad->GetNumberOfTuples()!=this->NumberOfControlPoints*3)
+    {
+      grad->SetNumberOfComponents(1);
+      grad->SetNumberOfTuples(this->NumberOfControlPoints*3);
+    }
+
+  OptimizationStructure.old_similarity=this->OptimizerValue(params);
+
+  // Calculate gradient 
+  double GradientNorm = 0;
+
+  int per=this->NumberOfControlPoints/10;
+  int count=0;
+  int count2=0;
+  
+  grad->FillComponent(0,0.0);
+
+  
+  this->GenerateOutput(OptimizationStructure.level,
+		       -1,-1,OptimizationStructure.step,
+		       OptimizationStructure.old_similarity);
+  fprintf(stderr,"\n\n%s NonLinear Label nOptimizer Computing Gradients : (%5.3f)",OutputStatus,OptimizationStructure.step);
+
+  //int mid=this->NumberOfControlPoints;
+
+  double tvoi=0.0,tpiece=0.0;
+  vtkTimerLog* timer=vtkTimerLog::New();
+
+  for (int i = 0; i < this->NumberOfControlPoints; i++)
+    {
+      ++count;
+
+      if (count==per)
+	{
+	  fprintf(stderr,"%.1f ",double(count2)*10.0);
+	  count=0;
+	  ++count2;
+	  if (count2==10)
+	    fprintf(stderr,"\n");
+	}
+
+      double p[3]; this->GridTransform->GetControlPointLocation(i,p);
+      
+      // Extract Relevant Portion of the Image
+      timer->StartTimer();
+      
+      vtkpxImageExtractVOI* voi=vtkpxImageExtractVOI::New();
+      voi->SetInput(this->SampledReferenceImage);
+      voi->SetRegion(p,OptimizationStructure.gridspacing,this->WindowSize);
+      voi->Update();
+      
+      
+      vtkpxImageExtractVOI* voi2=vtkpxImageExtractVOI::New();
+      voi2->SetInput(this->LastTargetImage);
+      voi2->SetRegion(p,OptimizationStructure.gridspacing,this->WindowSize);
+      voi2->Update();
+      
+      
+      timer->StopTimer();
+      tvoi+=timer->GetElapsedTime();
+      timer->StartTimer();
+      
+      for (int j=0;j<=2;j++)
+	{
+	  this->GridTransform->ShiftControlPoint(i,j,-OptimizationStructure.step);
+	  double s1 = this->EvaluatePiece(voi->GetOutput(),
+					  this->SampledTransformImage,
+					  voi2->GetOutput(),
+					  i);
+	  this->GridTransform->ShiftControlPoint(i,j,+2.0*OptimizationStructure.step);
+	  double s2 = this->EvaluatePiece(voi->GetOutput(),
+					  this->SampledTransformImage,
+					  voi2->GetOutput(),
+					  i);
+	  this->GridTransform->ShiftControlPoint(i,j,-OptimizationStructure.step);
+	  
+	  // Minus sign for ascent 
+	  grad->SetComponent(i*3+j,0,-(s2-s1));
+	  GradientNorm+=pow(s2-s1,2.0);
+	  
+	}
+      timer->StopTimer();
+      tpiece+=timer->GetElapsedTime();
+      
+      voi->Delete();
+      voi2->Delete();
+    }
+
+  timer->Delete();
+  GradientNorm = (sqrt(GradientNorm));
+  // Changing this one 
+  //  double sc=OptimizationStructure.step/GradientNorm;
+  double sc=this->GradientScale*OptimizationStructure.step/GradientNorm;
+
+  // Normalize vector
+  if (GradientNorm > 0)
+    this->GridTransform->ScaleGradients(grad,sc);
+  else 
+    grad->FillComponent(0,0.0);
+  fprintf(stderr,"Gradient Norm=%.5f scale=%.5f (tvoi=%f tpiece=%f)\n",GradientNorm,sc,tvoi,tpiece);
+  return GradientNorm;
+
+}
+//-------------------------------------------------------------------------
+double vtkpxNonLinearLabelRegistration::ComputeInternalEnergy(vtkpxGridTransform* tr,int cpindex)
+{
+  double v1=0.0;
+
+  if (this->InternalEnergyMode==0)
+    {
+      // Bending Energy
+      if (cpindex==-1)
+	{
+	  v1=tr->ComputeTotalBendingEnergy();
+	}
+      else
+	{
+	  v1=tr->ComputeBendingEnergyAtControlPoint(cpindex);
+	}
+    }
+  else
+    { 
+      if (cpindex==-1)
+	{
+	  v1=tr->ComputeTotalStrainEnergy(0.45);
+	}
+      else
+	{
+	  v1=tr->ComputeStrainEnergyAtControlPoint(cpindex,0.45);
+	}
+    }
+
+  return v1;
+}
+
+
+//-------------------------------------------------------------------------
+double vtkpxNonLinearLabelRegistration::OptimizerGradientGlobal(vtkDoubleArray* params,vtkDoubleArray* grad)
+{
+  if (grad->GetNumberOfComponents()!=1 || grad->GetNumberOfTuples()!=this->NumberOfControlPoints*3)
+    {
+      grad->SetNumberOfComponents(1);
+      grad->SetNumberOfTuples(this->NumberOfControlPoints*3);
+    }
+
+  OptimizationStructure.old_similarity=this->OptimizerValue(params);
+
+  // Calculate gradient 
+  double GradientNorm = 0;
+
+  grad->FillComponent(0,0.0);
+
+  this->GenerateOutput(OptimizationStructure.level,
+		       -1,-1,OptimizationStructure.step,
+		       OptimizationStructure.old_similarity);
+  fprintf(stderr,"\n\n%s\nOptimizer Computing Gradients : (%5.3f)",OutputStatus,OptimizationStructure.step);
+
+  //int mid=this->NumberOfControlPoints;
+
+  int nparam=params->GetNumberOfTuples();
+  double stepsize=OptimizationStructure.step;
+
+  for (int i = 0; i < nparam; i++)
+    {
+      params->SetComponent(i,0,params->GetComponent(i,0)-stepsize);
+      double s1 = this->OptimizerValue(params);
+      
+      params->SetComponent(i,0,params->GetComponent(i,0)+2*stepsize);
+      double s2 = this->OptimizerValue(params);
+
+      params->SetComponent(i,0,params->GetComponent(i,0)-stepsize);
+
+      grad->SetComponent(i,0,-(s2-s1));
+      GradientNorm+=pow(s2-s1,2.0);
+    }
+
+  GradientNorm = (sqrt(GradientNorm));
+  double sc=OptimizationStructure.step/GradientNorm;
+
+  if (GradientNorm > 0)
+    this->GridTransform->ScaleGradients(grad,sc);
+  else 
+    grad->FillComponent(0,0.0);
+  fprintf(stderr,"Gradient Norm=%.5f scale=%.5f\n",GradientNorm,sc);
+  return GradientNorm;
+
+}
+
+double vtkpxNonLinearLabelRegistration::ComputeCombinedValue(float* tv,int num)
+{
+  if (this->CombinationMetric==0)
+    {
+      double sum=0.0;
+      for (int ia=0;ia<num;ia++)
+	sum+=tv[ia];
+      return sum/double(num);
+    }
+  else if (this->CombinationMetric==1)
+    {
+      return vtkpxMath::GetMedian(num,tv);
+    }
+
+  double minval=tv[0];
+  for (int ia=1;ia<num;ia++)
+    {
+      if (minval>tv[ia])
+	minval=tv[ia];
+    }
+
+  return minval;
+}
+
diff --git a/bioimagesuite30_src/Registration/vtkpxNonLinearLabelRegistration.h b/bioimagesuite30_src/Registration/vtkpxNonLinearLabelRegistration.h
new file mode 100644
index 0000000..071e1d2
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxNonLinearLabelRegistration.h
@@ -0,0 +1,344 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+
+
+
+#ifndef _VTKPXNONLINEARLABELREGISTRATION_H
+#define _VTKPXNONLINEARLABELREGISTRATION_H
+
+#include "vtkpxRegistration.h"
+#include "vtkpxAbstractIntensityRegistration.h"
+#include "vtkImageData.h"
+#include "vtkpxGridTransform.h"
+#include "vtkpxComboTransform.h"
+#include "vtkDoubleArray.h"
+#include "vtkGeneralTransform.h"
+
+//BTX
+class vtkpxNonLinearLabelRegistrationOptimizationStructure {
+public:
+  double old_similarity;
+  double step;
+  int   level;
+  double origin[3];
+  double spacing[3];
+  int   dimensions[3];
+  double gridspacing[3];
+
+  void SetValues(double old_similarity0,
+		 double step0,
+		 int level0,
+		 double origin0[3],double spacing0[3],
+		 int dimensions0[3],double gridspacing0[3])
+  {
+    this->old_similarity=old_similarity0;
+    this->step=step0;
+    this->level=level0;
+    for (int ia=0;ia<=2;ia++)
+      {
+	this->origin[ia]=origin0[ia];
+	this->spacing[ia]=spacing0[ia];
+	this->dimensions[ia]=dimensions0[ia];
+	this->gridspacing[ia]=gridspacing0[ia];
+      }
+  }
+};
+//ETX
+
+
+class  vtkpxNonLinearLabelRegistration : public vtkpxAbstractIntensityRegistration {
+
+public:
+  static vtkpxNonLinearLabelRegistration* New();
+  vtkTypeMacro(vtkpxNonLinearLabelRegistration,vtkpxAbstractIntensityRegistration);
+
+  // Description:
+  // Print information about the progress of the registration
+  void PrintInformation();
+
+
+  // Description:
+  // Set Grid Spacing at highest resolution
+  vtkSetMacro(ControlPointSpacing,double);
+  vtkGetMacro(ControlPointSpacing,double);
+
+  // Desription:
+  // Set Rate of increase of spacing with resolution level (std=2.0)
+  vtkSetClampMacro(ControlPointSpacingRate,double,1.0,2.0);
+  vtkGetMacro(ControlPointSpacingRate,double);
+
+  // Run Optimization for Level level
+  virtual int ComputeRegistration(int level);
+
+
+  // Description:
+  // Sets input for the registration filter -- frame is ignored in ref image, all frames are used
+  virtual void SetReferenceImage(vtkImageData* ref,int frame);
+  virtual void SetTransformImage(vtkImageData* ref,int frame);
+  
+  // Description:
+  // Get Internal Transformation Stuff
+  vtkGetObjectMacro(ComboTransform,vtkpxComboTransform);
+
+  // Description:
+  // Get/Set Initial Transform -- typically an affine estimate
+  vtkSetObjectMacro(InitialTransform,vtkAbstractTransform);
+  vtkGetObjectMacro(InitialTransform,vtkAbstractTransform);
+
+
+  // Description:
+  // Epsilon is the convergence limit (default=0.0001);
+  vtkGetMacro(Epsilon,double);
+  vtkSetClampMacro(Epsilon,double,0.0001,0.1);
+
+  // Description:
+  // WindowSize is the window size for updating the transformation (full=2.0)
+  vtkGetMacro(WindowSize,double);
+  vtkSetClampMacro(WindowSize,double,1.0,2.0);
+
+  // Description:
+  // WindowSize is the window size for updating the transformation (full=2.0)
+  vtkGetMacro(GradientScale,double);
+  vtkSetClampMacro(GradientScale,double,0.1,100.0);
+
+  // Description:
+  // 0 = Mean, 1=Median, 2 = Minimum
+  vtkGetMacro(CombinationMetric,int);
+  vtkSetClampMacro(CombinationMetric,int,0,2);
+
+  // Description:
+  // Get Update Transformation
+  virtual vtkAbstractTransform* GetUpdateTransform();
+
+
+  // Description:
+  // GetTransformation
+  virtual vtkAbstractTransform* GetTransformation() { return this->ComboTransform;}
+
+
+  // -----------------------------------------------------------------------------------------------
+  // Smoothness Constraint 
+  // -----------------------------------------------------------------------------------------------
+  
+
+  // Description:
+  // Lambda is smoothness constant (default=0.0)
+  vtkGetMacro(Lambda,double);
+  vtkSetMacro(Lambda,double);
+
+  // Description:
+  // Prior Mode
+  vtkSetClampMacro(InternalEnergyMode,int,0,1);
+  vtkGetMacro(InternalEnergyMode,int);
+
+
+  // Description:
+  // Utility Functions for Setting the Smoothness Mode
+  virtual void SetInternalEnergyModeToBendingEnergy()     { this->SetInternalEnergyMode(0);} // Default
+  virtual void SetInternalEnergyModeToLinearElastic()     { this->SetInternalEnergyMode(1);}
+
+  // Description:
+  // Append Transformations or Fit to Single
+  vtkSetClampMacro(AppendTransformations,int,0,1);
+  vtkGetMacro(AppendTransformations,int);
+
+
+protected:
+
+  // Make all these protected 
+  // Constructor
+  vtkpxNonLinearLabelRegistration();
+  virtual ~vtkpxNonLinearLabelRegistration();
+  vtkpxNonLinearLabelRegistration(const vtkpxNonLinearLabelRegistration&) {};
+  void operator=(const vtkpxNonLinearLabelRegistration&) {};
+
+  // Description:
+  // Image Data to store last match (for removing bins from histogram)
+  vtkImageData* LastTargetImage;
+
+
+
+
+  // Description:
+  // Spacing of control points and rate of increase of spacing with resolution level (std=2.0)
+  double ControlPointSpacing;
+  double ControlPointSpacingRate;
+
+  // Description:
+  // This controls the optimization method 0=default,1=Cong Gradient
+  vtkpxNonLinearLabelRegistrationOptimizationStructure OptimizationStructure;
+
+  // Description:
+  // Actual Transformation
+  vtkpxGridTransform*   GridTransform;
+  vtkpxComboTransform*  ComboTransform;
+  vtkTransform*         LinearTransform;
+  vtkCollection*        HistogramCollection;
+
+  // Description:
+  // Initial Transformation (to initialize Grid values)
+  vtkAbstractTransform* InitialTransform;
+
+  // Description:
+  // Update Transform
+  vtkpxComboTransform* UpdateTransform;
+
+  // Description:
+  // Set Convergence Limit
+  double Epsilon;
+
+  // Description:
+  // If one use "fluid like" registration
+  int AppendTransformations;
+
+  // Description:
+  // Set Window Size (def=2.0);
+  double WindowSize;
+
+  // Description:
+  // Scaling of Gradient before Calling Gradient Descent etc
+  double GradientScale;
+  
+
+  // Description:
+  // Lambda is smoothness constant (default=0.0)
+  double Lambda;
+
+  // Description:
+  // InternalEnergyMode determines the type of smoothness constraint used
+  // UsePrior determines whether the prior transform is used 
+  int InternalEnergyMode;
+
+
+  // Description:
+  // Cached Grid Dimensions, NumberOfControlPoints etc.
+  int NumberOfControlPoints;
+  int ExperimentalMode;
+  int CombinationMetric;
+  float* similarityarray;
+
+  // Description:
+  // Initial set up for the registration at all levels
+  virtual int InitializeAll();
+
+  // Description:
+  // Optimize for step size = step
+  virtual double Optimize(vtkDoubleArray* grad,double old_similarity,double step,int level,
+			 double origin[3],double spacing[3],int dimensions[3],
+			 double gridspacing[3]);
+
+  // Description:
+  // Evaluates the registration. This function evaluates the registration by
+  // looping over the target image and interpolating the transformed source 
+  // image while filling the joint histogram. This function returns the value
+  // of the similarity measure using Similarity().
+  virtual double Evaluate();
+
+  // Description:
+  // Evaluates the registration. This function evaluates the registration by
+  // looping over the target image and interpolating the transformed source 
+  // image while filling the joint histogram. This function returns the value
+  // of the similarity measure using Similarity().
+  virtual double EvaluatePiece(vtkImageData* reference,
+			       vtkImageData* target,
+			       vtkImageData* previoustarget,
+			       int cpointno=-1);
+  
+
+  // Description:
+  // Compute the combined similarity metric from individual ones
+  virtual double ComputeCombinedValue(float* tv,int num);
+
+  //BTX
+  // Description:
+  // Fast access to the parameters of the grid
+  //ETX
+
+  // Description:
+  // Initial set up for the registration at a multiresolution level
+  virtual int Initialize(int);
+
+  // Description:
+  // Called from Initialize to Initialize the Transformation
+  virtual int InitializeTransformation(int);
+
+  // Description:
+  // Final set up for the registration at a multiresolution level
+  virtual int FinalizeAll();
+
+
+  // Description:
+  // Generate Output
+  virtual void GenerateOutput(int level, int step,int iter,double stepsize,double simil);
+
+
+  // Description:
+  // Needed for Optimizer
+  virtual void SetCurrentParameters(vtkDoubleArray* par);
+  virtual void GetCurrentParameters(vtkDoubleArray* par);
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerGradientGlobal(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+
+  // Description:
+  // SmoothnessMeasure
+  virtual double ComputeInternalEnergy(vtkpxGridTransform* tr,int cp=-1);
+
+
+
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxNonLinearRegistration.cpp b/bioimagesuite30_src/Registration/vtkpxNonLinearRegistration.cpp
new file mode 100644
index 0000000..a99f607
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxNonLinearRegistration.cpp
@@ -0,0 +1,873 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+#include "vtkpxNonLinearRegistration.h"
+#include "vtkObjectFactory.h"
+#include "pxutil.h"
+#include "vtkpxUtil.h"
+#include "vtkpxImageExtractVOI.h"
+#include "vtkpxOptimizer.h"
+#include "vtkTimerLog.h"
+#include "vtkMath.h"
+
+vtkpxNonLinearRegistration* vtkpxNonLinearRegistration::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxNonLinearRegistration");
+  if(ret)
+    {
+    return (vtkpxNonLinearRegistration*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxNonLinearRegistration;
+  
+}
+
+
+vtkpxNonLinearRegistration::vtkpxNonLinearRegistration()
+{
+  this->LastTargetImage=NULL;
+  this->LastTargetWeightImage=NULL;
+  this->ImageMask=NULL;
+  this->Status=NULL;
+  this->ControlPointSpacing=20.0;
+  this->ControlPointSpacingRate=1.0;
+  this->GridTransform=NULL;
+  this->AppendTransformations=0;
+  this->InitialTransform=NULL;
+  this->DoDiffeomorphic=0;
+
+  this->ComboTransform=NULL;
+  this->LinearTransform=NULL;
+  this->WarpX=1;
+  this->WarpY=1;
+  this->WarpZ=1;
+  this->Lambda=0.0;
+  this->Epsilon=0.003;
+  this->WindowSize=1.0;
+  this->UpdateTransform=vtkpxComboTransform::New();
+  this->UpdateTransform->SetNonLinearFirst(1);
+  this->InternalEnergyMode=0;
+  this->GradientScale=1.0;
+}
+
+vtkpxNonLinearRegistration::~vtkpxNonLinearRegistration() 
+{
+  if (this->GridTransform!=NULL)
+    this->GridTransform->Delete();
+
+
+  if (this->LinearTransform!=NULL)
+    this->LinearTransform->Delete();
+
+  if (this->ComboTransform!=NULL)
+    this->ComboTransform->Delete();
+
+
+  if (this->Status!=NULL)
+    this->Status->Delete();
+
+  if (this->LastTargetImage!=NULL)
+    this->LastTargetImage->Delete();
+
+  if (this->LastTargetWeightImage!=NULL)
+    this->LastTargetWeightImage->Delete();
+
+  this->UpdateTransform->Delete();
+  this->SetInitialTransform(NULL);
+  this->SetImageMask(NULL);
+}
+
+//-------------------------------------------------------------------------
+int vtkpxNonLinearRegistration::InitializeAll() 
+{
+  vtkpxAbstractIntensityRegistration::InitializeAll();
+  this->ControlPointSpacing=Frange(this->ControlPointSpacing,
+				   this->MinimumResolution,
+				   50.0*this->MinimumResolution);
+  this->ControlPointSpacingRate=Frange(this->ControlPointSpacingRate,1.0,2.0);
+
+  if (this->NumberOfExtraLevels>0)
+    this->AppendTransformations=1;
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxNonLinearRegistration::InitializeTransformation(int level) 
+{
+  fprintf(stderr,"In vtkpxNonLinearRegistration::InitializeTransform\n");
+  double reduction=pow(this->ControlPointSpacingRate,double(level-1.0));
+
+  vtkTimerLog* timer=vtkTimerLog::New();
+  timer->StartTimer();
+
+  if (level==this->NumberOfLevels)
+    {
+      this->LinearTransform=vtkTransform::New();
+      this->GridTransform=vtkpxGridTransform::New();
+      this->ComboTransform=vtkpxComboTransform::New();
+      this->ComboTransform->SetNonLinearFirst(1);
+      this->LinearTransform->Identity();
+
+      if (this->InitialTransform==NULL)
+	{
+	 	  fprintf(stderr,"No initial transformation -- nothing special create grid");
+	  this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+							  this->ControlPointSpacing*reduction,0.0,
+							  NULL);
+	}
+      else if (this->InitialTransform->IsA("vtkLinearTransform")==1)
+	{
+	  // Just Linear Absorb
+	  fprintf(stderr,"Linear initial transformation");
+	  vtkLinearTransform* x=(vtkLinearTransform*)(this->InitialTransform);
+	  this->LinearTransform->Identity();
+	  this->LinearTransform->Concatenate(x->GetMatrix());
+	  this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+							  this->ControlPointSpacing*reduction,0.0);
+	}
+      else if (this->InitialTransform->IsA("vtkpxComboTransform")==1 || (this->InitialTransform->IsA("vtkpxGridTransform")==1))
+	{
+	  // Either a Grid or a combo
+	  // If Combo get linear component else set linear to identity
+	  fprintf(stderr,"Combo/Grid initial transformation");
+	  this->LinearTransform->Identity();
+	  vtkpxGridTransform* ingrid=NULL;
+	  if  (this->InitialTransform->IsA("vtkpxComboTransform")==1)
+	    {
+	      vtkpxComboTransform* x=(vtkpxComboTransform*)(this->InitialTransform);
+	      this->LinearTransform->Concatenate(x->GetLinearTransform()->GetMatrix());
+	      this->ComboTransform->SetNonLinearFirst(x->GetNonLinearFirst());
+	      ingrid=x->GetGridTransform();
+	    } 
+	  else
+	    {
+	      ingrid=(vtkpxGridTransform*)(this->InitialTransform);
+	    }
+	  
+	  if (this->ComboTransform->GetNonLinearFirst()==1)
+	    this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+							    this->ControlPointSpacing*reduction,0.0);
+	  else
+	    this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+							    this->ControlPointSpacing*reduction,0.0,
+							    this->LinearTransform);
+	  this->ComboTransform->SetTransformations(this->LinearTransform,ingrid);
+	  
+	  if (this->AppendTransformations)
+	    this->ComboTransform->AddGridTransform(this->GridTransform);
+	  else
+	    this->ApproximateTransformationToGrid(this->GridTransform,ingrid,1.0,12,1,0.05*this->MinimumResolution,0.01);
+	}
+      else
+	{
+	  fprintf(stderr,"Other initial transformation .. brute force approximate this and hope for the best");
+	  this->GridTransform=vtkpxGridTransform::New();
+	  this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+							  this->ControlPointSpacing*reduction,0.0,NULL);
+	  fprintf(stderr,"\n -------------------- Approximating Grid Transformation ---------------\n");
+	  this->ApproximateTransformationToGrid(this->GridTransform,this->InitialTransform,1.0,12,1,0.05*this->MinimumResolution,0.01);
+	  fprintf(stderr,"\n -------------------- Approximating Grid Transformation Done-----------\n");
+	}
+
+      this->ComboTransform->SetTransformations(this->LinearTransform,this->GridTransform);
+    }
+ else if (this->ControlPointSpacingRate>1)
+   {
+     vtkpxGridTransform* prevTransform=this->GridTransform;
+      this->GridTransform=vtkpxGridTransform::New();
+      this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+						      this->ControlPointSpacing*reduction,0.0,
+						      NULL);
+      
+      if (this->AppendTransformations)
+	{
+	  this->ComboTransform->AddGridTransform(this->GridTransform);
+	  
+	}
+      else
+	{
+	  if (prevTransform!=NULL)
+	    {
+	      fprintf(stderr,"\n -------------------- Approximating Grid Transformation ---------------\n");
+	      this->ApproximateTransformationToGrid(this->GridTransform,prevTransform);
+	      fprintf(stderr,"\n -------------------- Approximating Grid Transformation Done-----------\n");
+	    }
+	  
+	  this->ComboTransform->SetTransformations(this->LinearTransform,this->GridTransform);
+	}
+      prevTransform->Delete();
+    }
+  else
+    {
+      if (this->AppendTransformations)
+	{
+	  this->GridTransform=vtkpxGridTransform::New();
+	  this->GridTransform->InitializeDisplacementGrid(this->SampledReferenceImage,
+							  this->ControlPointSpacing*reduction,0.0,
+							  NULL);
+	  this->ComboTransform->AddGridTransform(this->GridTransform);
+	}
+      else
+	{
+	  fprintf(stderr,"Keeping the same transformation and refining");
+	}
+    }
+
+  this->NumberOfControlPoints=this->GridTransform->GetNumberOfControlPoints();
+  timer->StopTimer();
+  fprintf(stderr,"In vtkpxNonLinearRegistration::InitializeTransform Done numnonlinear=%d time=%f\n",
+	  this->ComboTransform->GetNumberOfGridTransformations(),timer->GetElapsedTime());
+  timer->Delete();
+
+  return 1;
+}
+//-------------------------------------------------------------------------
+void vtkpxNonLinearRegistration::ApproximateTransformationToGrid(vtkpxGridTransform* grid,vtkAbstractTransform* tr)
+{
+  this->ApproximateTransformationToGrid(grid,tr,0.05,20,1,0.0005,0.0);
+}
+
+void vtkpxNonLinearRegistration::ApproximateTransformationToGrid(vtkpxGridTransform* grid,vtkAbstractTransform* tr,double step,
+								 int numiter,int numlevels,
+								 double threshold,double lambda)
+{
+  grid->ApproximateTransformation(tr,step,numiter,numlevels,threshold,lambda);
+}
+
+//-------------------------------------------------------------------------
+int vtkpxNonLinearRegistration::Initialize(int level) 
+{
+  // Different Procedure for toplevel and remaining levels
+  // In top level initialize using InitialTransform
+  // in other levels initialize using previous grid transform
+
+  vtkpxAbstractIntensityRegistration::Initialize(level);
+  this->InitializeTransformation(level);
+
+  if (this->Status!=NULL)
+    this->Status->Delete();
+
+  this->Status=vtkDataArray::CreateDataArray(VTK_UNSIGNED_CHAR);
+  this->Status->SetNumberOfComponents(3);
+  this->Status->SetNumberOfTuples(this->NumberOfControlPoints);
+
+  if (this->WarpX)
+    this->Status->FillComponent(0,1);
+  else
+    this->Status->FillComponent(0,0);
+  
+  if (this->WarpY)
+    this->Status->FillComponent(1,1);
+  else
+    this->Status->FillComponent(1,0);
+
+  if (this->WarpZ)
+    this->Status->FillComponent(2,1);
+  else
+    this->Status->FillComponent(2,0);
+  
+
+  // If Mask == 1 Do not warp
+  if (this->ImageMask!=NULL)
+    {
+      vtkTransform* tr3=vtkTransform::New();
+      tr3->Concatenate(this->LinearTransform);
+      tr3->Inverse();
+
+      int numactive=0,numtotal=0;
+
+      int dim[3];
+      this->ImageMask->GetDimensions(dim);
+
+      double ori[3],sp[3];
+      this->ImageMask->GetOrigin(ori);
+      this->ImageMask->GetSpacing(sp);
+      for (int i=0;i<this->NumberOfControlPoints;i++)
+	{
+	  double p[3];
+	  int   q[3];
+	  this->GridTransform->GetControlPointLocation(i,p);
+	  tr3->TransformPoint(p,p);
+	  for (int ia=0;ia<=2;ia++)
+	    q[ia]=int((p[ia]-ori[ia])/sp[ia]);
+
+	  ++numtotal;
+	  if (q[0]>=0 && q[0]<dim[0] && q[1]>=0 && q[1]<dim[1] && q[2]>=0 && q[2]<dim[2])
+	    {
+	      if (this->ImageMask->GetScalarComponentAsDouble(q[0],q[1],q[2],0)==0)
+		{
+		  for (int ib=0;ib<=2;ib++)
+		    this->Status->SetComponent(i,ib,0);
+		  ++numactive;
+		}
+	    }
+	  else
+	    {
+	      for (int ib=0;ib<=2;ib++)
+		this->Status->SetComponent(i,ib,0);
+	      ++numactive;
+	    }
+	}
+      tr3->Delete();
+      numactive=numtotal-numactive;
+      fprintf(stderr,"Total Control Points = %d Active = %d (%5.2f)\n",
+	      numtotal,numactive,double(numactive*100.0)/double(numtotal));
+    }
+
+
+  if (this->LastTargetImage!=NULL)
+    this->LastTargetImage->Delete();
+  this->LastTargetImage=vtkImageData::New();
+
+  if (this->LastTargetWeightImage!=NULL)
+    this->LastTargetWeightImage->Delete();
+  this->LastTargetWeightImage=vtkImageData::New();
+
+  double sp[3]; this->GridTransform->GetGridSpacing(sp);
+  int    d[3]; this->GridTransform->GetGridDimensions(d);
+  sprintf(this->OutputStatus,"\n Transformation Spacing %.2f %.2f %.2f dimensions=%d x %d x %d\n",sp[0],sp[1],sp[2],d[0],d[1],d[2]);
+  this->UpdateProgress(this->LastProgress);
+
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxNonLinearRegistration::FinalizeAll()
+{
+  this->LastTargetImage->Delete();
+  this->LastTargetWeightImage->Delete();
+  this->LastTargetImage=NULL;
+  this->LastTargetWeightImage=NULL;
+  this->Status->Delete();
+  this->Status=NULL;
+  return vtkpxAbstractIntensityRegistration::FinalizeAll();
+}
+//-------------------------------------------------------------------------
+// Compute Registration
+int vtkpxNonLinearRegistration::ComputeRegistration(int level)
+{  
+
+  double step=this->CurrentStepSize;
+
+  double origin[3],spacing[3],gridspacing[3];
+  int   dimensions[3];
+  this->GridTransform->GetDisplacementGrid()->GetSpacing(gridspacing);
+  this->SampledReferenceImage->GetOrigin(origin);
+  this->SampledReferenceImage->GetSpacing(spacing);
+  this->SampledReferenceImage->GetDimensions(dimensions);
+  
+  vtkDoubleArray* grad=vtkDoubleArray::New();
+  grad->SetNumberOfComponents(3);
+  grad->SetNumberOfTuples(this->NumberOfControlPoints);
+
+
+  for (int st=1;st<=this->NumberOfSteps;st++)
+    {
+      double old_similarity = this->Evaluate();
+      double new_similarity=this->Optimize(grad,old_similarity,step,level,
+					  origin,spacing,dimensions,gridspacing);
+      this->GenerateOutput(level,st,this->NumberOfIterations,step,new_similarity);
+      step*=0.5;
+    }
+
+  grad->Delete();
+  return 1;
+}
+//-------------------------------------------------------------------------
+
+double vtkpxNonLinearRegistration::Optimize(vtkDoubleArray* grad,double old_similarity,
+					   double step,int level,
+					   double origin[3],double spacing[3],
+					   int dimensions[3],double gridspacing[3])
+{
+  OptimizationStructure.SetValues(old_similarity,step,level,origin,spacing,dimensions,gridspacing);
+     
+  vtkpxOptimizer* optimizer=vtkpxOptimizer::New();
+  vtkDoubleArray* position=vtkDoubleArray::New();
+  vtkDoubleArray* temp=vtkDoubleArray::New();
+
+  this->GetCurrentParameters(position);
+  optimizer->SetMasterObject(this);
+  optimizer->SetTempArray(grad);
+  optimizer->SetEvaluateFunctionMethod(&vtkpxNonLinearRegistration::CalculateFunction);
+  optimizer->SetEvaluateGradientMethod(&vtkpxNonLinearRegistration::CalculateGradient);
+  optimizer->SetFeedbackMethod(&vtkpxNonLinearRegistration::OptimizerFeedback);
+  optimizer->SetBeginIterationMethod(&vtkpxAbstractIntensityRegistration::OnBeginIteration);
+
+  double v=0.0;
+
+
+  fprintf(stderr,"In Non Linear Reg :: Optimize :: %d\n",this->OptimizationMethod);
+
+  switch (this->OptimizationMethod)
+    {
+    case 2:
+      v=optimizer->ComputePowell(position,temp,this->NumberOfIterations,0.001);
+      break;
+
+    case 3:
+      v=optimizer->ComputeGradientDescent(position,this->NumberOfIterations,0.001);
+      break;
+
+    case 4:
+      v=optimizer->ComputeConjugateGradient(position,this->NumberOfIterations,0.001);
+      break;
+
+    case 5:
+      v=optimizer->ComputeGradientDescent(position,this->NumberOfIterations,0.001);
+      if (level==1)
+	v=optimizer->ComputeConjugateGradient(position,this->NumberOfIterations,0.001);
+      break;
+
+    default:
+	v=optimizer->ComputeConjugateGradient(position,this->NumberOfIterations,0.001);
+    }
+
+  optimizer->Delete();
+  position->Delete();
+  temp->Delete();
+  return v;
+}
+//-------------------------------------------------------------------------
+double vtkpxNonLinearRegistration::Evaluate()
+{
+  if (this->LastTargetImage==NULL)
+    this->LastTargetImage=vtkImageData::New();
+  
+  vtkpxRegistration::ResliceImage(this->LastTargetImage,this->SampledTransformImage,
+				  this->SampledReferenceImage,this->ComboTransform,this->InterpolationMode);
+  
+  if (this->SampledReferenceWeightImage!=NULL && this->SampledTransformWeightImage!=NULL)
+    {
+      if (this->LastTargetWeightImage==NULL)
+	this->LastTargetWeightImage=vtkImageData::New();
+
+      vtkpxRegistration::ResliceImage(this->LastTargetWeightImage,this->SampledTransformWeightImage,
+				      this->SampledReferenceImage,this->ComboTransform,this->InterpolationMode);
+
+      //      fprintf(stderr,"Calling Dual Weighted Fill Histogram\n");
+      this->Histogram->DualWeightedFillHistogram(this->SampledReferenceImage,this->LastTargetImage,
+					     this->SampledReferenceWeightImage,this->LastTargetWeightImage,1);  
+    }
+  else   if (this->SampledReferenceWeightImage!=NULL)
+    {
+      //      fprintf(stderr,"Calling Weighted Fill Histogram\n");
+      this->Histogram->WeightedFillHistogram(this->SampledReferenceImage,this->LastTargetImage,
+					     this->SampledReferenceWeightImage,1);  
+      
+    }
+  else
+    {
+      this->Histogram->FillHistogram(this->SampledReferenceImage,this->LastTargetImage,1);  
+    }
+  this->LastSimilarity=this->Similarity(this->Histogram);
+
+  if (this->DoDiffeomorphic>0)
+    this->LastSmoothness=this->GridTransform->ComputeJacobianConstraint(0.3);
+  else if (this->Lambda>0.000001)
+    this->LastSmoothness=this->ComputeInternalEnergy(this->GridTransform);
+  else
+    this->LastSmoothness=0.0;
+  return this->LastSimilarity-this->LastSmoothness*this->Lambda;
+}
+//-------------------------------------------------------------------------
+double vtkpxNonLinearRegistration::EvaluatePiece(vtkImageData* reference,
+						 vtkImageData* target,
+						 vtkImageData* previoustarget,
+						 vtkImageData* weights,
+						 vtkImageData* weights2,
+						 int cpoint)
+
+{
+  this->Histogram->BackupHistogram();
+
+  vtkImageData* tmp=vtkImageData::New();
+  vtkpxRegistration::ResliceImage(tmp,target,reference,this->ComboTransform,this->InterpolationMode);
+
+  // Remove Last Target Value
+
+  // Add New Value
+
+  if (weights!=NULL && weights2!=NULL)
+    {
+      //      fprintf(stderr,"Calling Dual Weighted Remove and Weighted Fill Histogram weights=%d, weights2=%d\n",weights,weights2);
+      this->Histogram->DualWeightedRemoveFromHistogram(reference,previoustarget,weights,weights2);
+      this->Histogram->DualWeightedFillHistogram(reference,tmp,weights,weights2,0);
+    }
+  else if (weights!=NULL)
+    {
+      //      fprintf(stderr,"Calling Weighted Remove and Weighted Fill Histogram\n");
+      this->Histogram->WeightedRemoveFromHistogram(reference,previoustarget,weights);
+      this->Histogram->WeightedFillHistogram(reference,tmp,weights,0);
+    }
+  else
+    {
+      this->Histogram->RemoveFromHistogram(reference,previoustarget);
+      this->Histogram->FillHistogram(reference,tmp,0);
+    }
+  // Clean Up
+  tmp->Delete();
+
+  // Return Value
+  double e1=this->Similarity(this->Histogram);
+
+  this->Histogram->ResetHistogram();
+
+  double l1=0.0;
+  if (this->Lambda>0.000001)
+    l1 = this->ComputeInternalEnergy(this->GridTransform,cpoint)*double(NumberOfControlPoints);
+  double s1=e1-this->Lambda*l1;
+  
+  return s1;
+}
+
+//-------------------------------------------------------------------------
+void vtkpxNonLinearRegistration::PrintInformation() 
+{
+  
+}
+//-------------------------------------------------------------------------
+
+void vtkpxNonLinearRegistration::GenerateOutput(int level, int step,int iter,double stepsize,double actualSimilarity)
+{
+  if (iter>=100)
+    iter=99;
+
+  sprintf(this->OutputStatus,"Level=%2d Step=%2d iter=%2d stepsize=%.3f: tot=%8.6f (sim=%8.6f sm=%8.6f (dist=%.2f))\n",
+	  level,step,iter,stepsize,actualSimilarity,
+	  this->LastSimilarity,this->LastSmoothness*this->Lambda,
+	  this->LastSmoothness);
+  this->UpdateProgress(this->LastProgress);
+
+  return;
+}
+
+//-------------------------------------------------------------------------
+vtkAbstractTransform* vtkpxNonLinearRegistration::GetUpdateTransform()
+{
+  if (this->SampledReferenceImage==NULL || this->GridTransform==NULL)
+    return this->UpdateTransform;
+
+  return this->ComboTransform;
+}
+
+//-------------------------------------------------------------------------
+// Optimizer Stuff 
+//-------------------------------------------------------------------------
+void vtkpxNonLinearRegistration::SetCurrentParameters(vtkDoubleArray* param)
+{
+  this->GridTransform->SetCurrentParameters(param);
+}
+//-------------------------------------------------------------------------
+void vtkpxNonLinearRegistration::GetCurrentParameters(vtkDoubleArray* param)
+{
+  this->GridTransform->GetCurrentParameters(param);
+}
+//-------------------------------------------------------------------------
+double vtkpxNonLinearRegistration::OptimizerValue(vtkDoubleArray* params)
+{
+  /*  double sum=0.0;
+  int nt=params->GetNumberOfTuples();
+  for (int i=0;i<nt;i++)
+    sum+=params->GetComponent(i,0);
+    fprintf(stdout,"Params sum=%f\n",sum);*/
+  this->SetCurrentParameters(params);
+  
+  return -this->Evaluate();
+}
+//-------------------------------------------------------------------------
+double vtkpxNonLinearRegistration::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+
+{
+  if (grad->GetNumberOfComponents()!=1 || grad->GetNumberOfTuples()!=this->NumberOfControlPoints*3)
+    {
+      grad->SetNumberOfComponents(1);
+      grad->SetNumberOfTuples(this->NumberOfControlPoints*3);
+    }
+
+  OptimizationStructure.old_similarity=this->OptimizerValue(params);
+
+  // Calculate gradient 
+  double GradientNorm = 0;
+
+  int per=this->NumberOfControlPoints/10;
+  int count=0;
+  int count2=0;
+  
+  grad->FillComponent(0,0.0);
+
+  sprintf(this->OutputStatus,"");
+  fprintf(stderr,"\n");
+  this->GenerateOutput(OptimizationStructure.level,
+  		       -1,-1,OptimizationStructure.step,
+  		       OptimizationStructure.old_similarity);
+  fprintf(stderr,"Optimizer Computing Gradients : (%5.3f)",OptimizationStructure.step);
+
+  //int mid=this->NumberOfControlPoints;
+
+  double tvoi=0.0,tpiece=0.0;
+  vtkTimerLog* timer=vtkTimerLog::New();
+
+  for (int i = 0; i < this->NumberOfControlPoints; i++)
+    {
+      ++count;
+
+      if (count==per)
+	{
+	  fprintf(stderr,"%.1f ",double(count2)*10.0);
+	  count=0;
+	  ++count2;
+	  if (count2==10)
+	    fprintf(stderr,"\n");
+	}
+
+      if (this->Status->GetComponent(i,0)+this->Status->GetComponent(i,1)+this->Status->GetComponent(i,2) > 0 )
+	{
+	  double p[3]; this->GridTransform->GetControlPointLocation(i,p);
+	  
+	  // Extract Relevant Portion of the Image
+	  timer->StartTimer();
+
+	  vtkpxImageExtractVOI* voi=vtkpxImageExtractVOI::New();
+	  voi->SetInput(this->SampledReferenceImage);
+	  voi->SetRegion(p,OptimizationStructure.gridspacing,this->WindowSize);
+	  voi->Update();
+
+	  /*	  if (i ==33)
+	    {
+	      int bounds[6]; voi->GetVOI(bounds);
+	      fprintf(stderr,"Control Point %d bounds=%d:%d %d;%d, %d:%d p=%f,%f,%f sp=%f,%f,%f w=%d\n",i,bounds[0],bounds[1],bounds[2],bounds[3],bounds[4],bounds[5],
+		      p[0],p[1],p[2],
+		      OptimizationStructure.gridspacing[0],		      
+		      OptimizationStructure.gridspacing[1],		      
+		      OptimizationStructure.gridspacing[2],
+		      this->WindowSize);
+		      }*/
+
+
+	  vtkpxImageExtractVOI* voi2=vtkpxImageExtractVOI::New();
+	  voi2->SetInput(this->LastTargetImage);
+	  voi2->SetRegion(p,OptimizationStructure.gridspacing,this->WindowSize);
+	  voi2->Update();
+
+	  vtkpxImageExtractVOI* voi3=NULL;
+	  vtkImageData* roi3image=NULL;
+
+	  vtkpxImageExtractVOI* voi4=NULL;
+	  vtkImageData* roi4image=NULL;
+	  if (this->SampledReferenceWeightImage!=NULL)
+	    {
+	      voi3=vtkpxImageExtractVOI::New();
+	      voi3->SetInput(this->SampledReferenceWeightImage);
+	      voi3->SetRegion(p,OptimizationStructure.gridspacing,this->WindowSize);
+	      voi3->Update();
+	      roi3image=voi3->GetOutput();
+	    }
+
+	  // Approximation here, do not mess with estimate of weight image ....
+	  if (this->SampledTransformWeightImage!=NULL)
+	    {
+	      //	      fprintf(stderr,"*********** Creating voi4\n");
+	      voi4=vtkpxImageExtractVOI::New();
+	      voi4->SetInput(this->LastTargetWeightImage);
+	      voi4->SetRegion(p,OptimizationStructure.gridspacing,this->WindowSize);
+	      voi4->Update();
+	      roi4image=voi4->GetOutput();
+	    }
+
+	  timer->StopTimer();
+	  tvoi+=timer->GetElapsedTime();
+	  timer->StartTimer();
+
+	  for (int j=0;j<=2;j++)
+	    {
+	      if (this->Status->GetComponent(i,j)>0)
+		{
+		  this->GridTransform->ShiftControlPoint(i,j,-OptimizationStructure.step);
+		  //		  if (i==0)   fprintf(stdout,"Shifted Control Point %i comp %d-> %f\n",i,j,this->GridTransform->GetControlPointDisplacement(i,j));
+		  double s1 = this->EvaluatePiece(voi->GetOutput(),
+						  this->SampledTransformImage,
+						  voi2->GetOutput(),
+						  roi3image,roi4image,
+						 i);
+		  this->GridTransform->ShiftControlPoint(i,j,+2.0*OptimizationStructure.step);
+		  //		  if (i==0)   fprintf(stdout,"Shifted Control Point %i comp %d-> %f\n",i,j,this->GridTransform->GetControlPointDisplacement(i,j));
+		  double s2 = this->EvaluatePiece(voi->GetOutput(),
+						  this->SampledTransformImage,
+						  voi2->GetOutput(),
+						  roi3image,roi4image,
+						 i);
+		  this->GridTransform->ShiftControlPoint(i,j,-OptimizationStructure.step);
+		  //		  if (i==0)   fprintf(stdout,"Shifted Control Point %i comp %d-> %f\n",i,j,this->GridTransform->GetControlPointDisplacement(i,j));
+		  
+		  // Minus sign for ascent 
+		  grad->SetComponent(i*3+j,0,-(s2-s1));
+		  /*		  if (i==33)
+				  fprintf(stdout,"Grad Component i=%d j=%d -->%f (s1=%f s2=%f)\n",i,j,grad->GetComponent(i*3+j,0),s1,s2);*/
+		  GradientNorm+=pow(s2-s1,2.0);
+		  //}
+		}
+	    }
+	  timer->StopTimer();
+	  tpiece+=timer->GetElapsedTime();
+
+	  voi->Delete();
+	  voi2->Delete();
+	  if (voi3!=NULL)
+	    voi3->Delete();
+	  if (voi4!=NULL)
+	    voi4->Delete();
+	}
+    }
+
+  timer->Delete();
+  GradientNorm = (sqrt(GradientNorm));
+  // Changing this one 
+  //  double sc=OptimizationStructure.step/GradientNorm;
+  double sc=this->GradientScale*OptimizationStructure.step/GradientNorm;
+
+  // Normalize vector
+  if (GradientNorm > 0)
+    this->GridTransform->ScaleGradients(grad,sc);
+  else 
+    grad->FillComponent(0,0.0);
+  fprintf(stderr,"\tGradient Norm=%.5f scale=%.5f (tvoi=%f tpiece=%f)\n",GradientNorm,sc,tvoi,tpiece);
+  return GradientNorm;
+
+}
+
+//-------------------------------------------------------------------------
+
+double vtkpxNonLinearRegistration::ComputeInternalEnergy(vtkpxGridTransform* tr,int cpindex)
+{
+  double v1=0.0;
+
+  if (this->InternalEnergyMode==0)
+    {
+      // Bending Energy
+      if (cpindex==-1)
+	{
+	  v1=tr->ComputeTotalBendingEnergy();
+	}
+      else
+	{
+	  v1=tr->ComputeBendingEnergyAtControlPoint(cpindex);
+	}
+    }
+  else
+    { 
+      if (cpindex==-1)
+	{
+	  v1=tr->ComputeTotalStrainEnergy(0.45);
+	}
+      else
+	{
+	  v1=tr->ComputeStrainEnergyAtControlPoint(cpindex,0.45);
+	}
+    }
+
+  return v1;
+}
+
+
+//-------------------------------------------------------------------------
+double vtkpxNonLinearRegistration::OptimizerGradientGlobal(vtkDoubleArray* params,vtkDoubleArray* grad)
+{
+  if (grad->GetNumberOfComponents()!=1 || grad->GetNumberOfTuples()!=this->NumberOfControlPoints*3)
+    {
+      grad->SetNumberOfComponents(1);
+      grad->SetNumberOfTuples(this->NumberOfControlPoints*3);
+    }
+
+  OptimizationStructure.old_similarity=this->OptimizerValue(params);
+
+  // Calculate gradient 
+  double GradientNorm = 0;
+
+  grad->FillComponent(0,0.0);
+
+  //  this->GenerateOutput(OptimizationStructure.level,
+  //		       -1,-1,OptimizationStructure.step,
+  //		       OptimizationStructure.old_similarity);
+  fprintf(stderr,"\n\n%s\nOptimizer Computing Gradients : (%5.3f)",OutputStatus,OptimizationStructure.step);
+
+  //int mid=this->NumberOfControlPoints;
+
+  int nparam=params->GetNumberOfTuples();
+  double stepsize=OptimizationStructure.step;
+
+  for (int i = 0; i < nparam; i++)
+    {
+      params->SetComponent(i,0,params->GetComponent(i,0)-stepsize);
+      double s1 = this->OptimizerValue(params);
+      
+      params->SetComponent(i,0,params->GetComponent(i,0)+2*stepsize);
+      double s2 = this->OptimizerValue(params);
+
+      params->SetComponent(i,0,params->GetComponent(i,0)-stepsize);
+
+      grad->SetComponent(i,0,-(s2-s1));
+      GradientNorm+=pow(s2-s1,2.0);
+    }
+
+  GradientNorm = (sqrt(GradientNorm));
+  double sc=OptimizationStructure.step/GradientNorm;
+
+  if (GradientNorm > 0)
+    this->GridTransform->ScaleGradients(grad,sc);
+  else 
+    grad->FillComponent(0,0.0);
+  fprintf(stderr,"Gradient Norm=%.5f scale=%.5f\n",GradientNorm,sc);
+  return GradientNorm;
+
+}
+
diff --git a/bioimagesuite30_src/Registration/vtkpxNonLinearRegistration.h b/bioimagesuite30_src/Registration/vtkpxNonLinearRegistration.h
new file mode 100644
index 0000000..57aea5d
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxNonLinearRegistration.h
@@ -0,0 +1,371 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+
+
+
+#ifndef _VTKPXNONLINEARREGISTRATION_H
+#define _VTKPXNONLINEARREGISTRATION_H
+
+#include "vtkpxRegistration.h"
+#include "vtkpxAbstractIntensityRegistration.h"
+#include "vtkImageData.h"
+#include "vtkpxGridTransform.h"
+#include "vtkpxComboTransform.h"
+#include "vtkDoubleArray.h"
+#include "vtkGeneralTransform.h"
+
+//BTX
+class vtkpxNonLinearRegistrationOptimizationStructure {
+public:
+  double old_similarity;
+  double step;
+  int   level;
+  double origin[3];
+  double spacing[3];
+  int   dimensions[3];
+  double gridspacing[3];
+
+  void SetValues(double old_similarity0,
+		 double step0,
+		 int level0,
+		 double origin0[3],double spacing0[3],
+		 int dimensions0[3],double gridspacing0[3])
+  {
+    this->old_similarity=old_similarity0;
+    this->step=step0;
+    this->level=level0;
+    for (int ia=0;ia<=2;ia++)
+      {
+	this->origin[ia]=origin0[ia];
+	this->spacing[ia]=spacing0[ia];
+	this->dimensions[ia]=dimensions0[ia];
+	this->gridspacing[ia]=gridspacing0[ia];
+      }
+  }
+};
+//ETX
+
+
+class  vtkpxNonLinearRegistration : public vtkpxAbstractIntensityRegistration {
+
+public:
+  static vtkpxNonLinearRegistration* New();
+  vtkTypeMacro(vtkpxNonLinearRegistration,vtkpxAbstractIntensityRegistration);
+
+  // Description:
+  // Print information about the progress of the registration
+  void PrintInformation();
+
+
+  // Description:
+  // Set Grid Spacing at highest resolution
+  vtkSetMacro(ControlPointSpacing,double);
+  vtkGetMacro(ControlPointSpacing,double);
+
+  // Description:
+  // Set to 1 to produce diffeomorphic transformation using jacobian constraint
+  vtkSetMacro(DoDiffeomorphic,int);
+  vtkGetMacro(DoDiffeomorphic,int);
+
+  // Desription:
+  // Set Rate of increase of spacing with resolution level (std=2.0)
+  vtkSetClampMacro(ControlPointSpacingRate,double,1.0,2.0);
+  vtkGetMacro(ControlPointSpacingRate,double);
+
+  // Run Optimization for Level level
+  virtual int ComputeRegistration(int level);
+
+  
+  // Description:
+  // Get Internal Transformation Stuff
+  vtkGetObjectMacro(ComboTransform,vtkpxComboTransform);
+
+  // Description:
+  // Get/Set Initial Transform -- typically an affine estimate
+  vtkSetObjectMacro(InitialTransform,vtkAbstractTransform);
+  vtkGetObjectMacro(InitialTransform,vtkAbstractTransform);
+
+
+  // Description:
+  // Image Mask -- only allow warp in regions where image mask > 0.0
+  vtkSetObjectMacro(ImageMask,vtkImageData);
+  vtkGetObjectMacro(ImageMask,vtkImageData);
+
+  // Description:
+  // Enable control point displacements in X,Y and Z directions (defaults=1)
+  vtkSetClampMacro(WarpX,int,0,1);
+  vtkSetClampMacro(WarpY,int,0,1);
+  vtkSetClampMacro(WarpZ,int,0,1);
+
+  vtkGetMacro(WarpX,int);
+  vtkGetMacro(WarpY,int);
+  vtkGetMacro(WarpZ,int);
+
+  vtkBooleanMacro(WarpX,int);
+  vtkBooleanMacro(WarpY,int);
+  vtkBooleanMacro(WarpZ,int);
+
+
+  // Description:
+  // Epsilon is the convergence limit (default=0.0001);
+  vtkGetMacro(Epsilon,double);
+  vtkSetClampMacro(Epsilon,double,0.0001,0.1);
+
+  // Description:
+  // WindowSize is the window size for updating the transformation (full=2.0)
+  vtkGetMacro(WindowSize,double);
+  vtkSetClampMacro(WindowSize,double,1.0,2.0);
+
+  // Description:
+  // WindowSize is the window size for updating the transformation (full=2.0)
+  vtkGetMacro(GradientScale,double);
+  vtkSetClampMacro(GradientScale,double,0.1,100.0);
+
+  // Description:
+  // Get Update Transformation
+  virtual vtkAbstractTransform* GetUpdateTransform();
+
+
+  // Description:
+  // GetTransformation
+  virtual vtkAbstractTransform* GetTransformation() { return this->ComboTransform;}
+
+
+  // -----------------------------------------------------------------------------------------------
+  // Smoothness Constraint 
+  // -----------------------------------------------------------------------------------------------
+  
+
+  // Description:
+  // Lambda is smoothness constant (default=0.0)
+  vtkGetMacro(Lambda,double);
+  vtkSetMacro(Lambda,double);
+
+  // Description:
+  // Prior Mode
+  vtkSetClampMacro(InternalEnergyMode,int,0,1);
+  vtkGetMacro(InternalEnergyMode,int);
+
+
+  // Description:
+  // Utility Functions for Setting the Smoothness Mode
+  virtual void SetInternalEnergyModeToBendingEnergy()     { this->SetInternalEnergyMode(0);} // Default
+  virtual void SetInternalEnergyModeToLinearElastic()     { this->SetInternalEnergyMode(1);}
+
+  // Description:
+  // Append Transformations or Fit to Single
+  vtkSetClampMacro(AppendTransformations,int,0,1);
+  vtkGetMacro(AppendTransformations,int);
+
+
+protected:
+
+  // Make all these protected 
+  // Constructor
+  vtkpxNonLinearRegistration();
+  virtual ~vtkpxNonLinearRegistration();
+  vtkpxNonLinearRegistration(const vtkpxNonLinearRegistration&) {};
+  void operator=(const vtkpxNonLinearRegistration&) {};
+
+  // Description:
+  // Image Data to store last match (for removing bins from histogram)
+  vtkImageData* LastTargetImage;
+  vtkImageData* LastTargetWeightImage;
+
+  // Description:
+  // Image Mask is image which defines region where warping is allowed
+  vtkImageData* ImageMask;
+
+  // Description:
+  // Control Point Status
+  vtkDataArray* Status;
+
+  // Description:
+  // Spacing of control points and rate of increase of spacing with resolution level (std=2.0)
+  double ControlPointSpacing;
+  double ControlPointSpacingRate;
+  int DoDiffeomorphic;
+  
+  // Description:
+  // This controls the optimization method 0=default,1=Cong Gradient
+  vtkpxNonLinearRegistrationOptimizationStructure OptimizationStructure;
+
+  // Description:
+  // Actual Transformation
+  vtkpxGridTransform*   GridTransform;
+  vtkpxComboTransform*  ComboTransform;
+  vtkTransform*         LinearTransform;
+
+  // Description:
+  // Initial Transformation (to initialize Grid values)
+  vtkAbstractTransform* InitialTransform;
+
+  // Description:
+  // Update Transform
+  vtkpxComboTransform* UpdateTransform;
+
+  // Description:
+  // Flgas to Enable/Disable Translations along x,y,z axis (for distortion correction)
+  int WarpX;
+  int WarpY;
+  int WarpZ;
+
+  // Description:
+  // Set Convergence Limit
+  double Epsilon;
+
+  // Description:
+  // If one use "fluid like" registration
+  int AppendTransformations;
+
+  // Description:
+  // Set Window Size (def=2.0);
+  double WindowSize;
+
+  // Description:
+  // Scaling of Gradient before Calling Gradient Descent etc
+  double GradientScale;
+  
+
+  // Description:
+  // Lambda is smoothness constant (default=0.0)
+  double Lambda;
+
+  // Description:
+  // InternalEnergyMode determines the type of smoothness constraint used
+  // UsePrior determines whether the prior transform is used 
+  int InternalEnergyMode;
+
+
+  // Description:
+  // Cached Grid Dimensions, NumberOfControlPoints etc.
+  int NumberOfControlPoints;
+  int ExperimentalMode;
+
+  // Description:
+  // Initial set up for the registration at all levels
+  virtual int InitializeAll();
+
+  // Description:
+  // Optimize for step size = step
+  virtual double Optimize(vtkDoubleArray* grad,double old_similarity,double step,int level,
+			 double origin[3],double spacing[3],int dimensions[3],
+			 double gridspacing[3]);
+
+  // Description:
+  // Evaluates the registration. This function evaluates the registration by
+  // looping over the target image and interpolating the transformed source 
+  // image while filling the joint histogram. This function returns the value
+  // of the similarity measure using Similarity().
+  virtual double Evaluate();
+
+  // Description:
+  // Evaluates the registration. This function evaluates the registration by
+  // looping over the target image and interpolating the transformed source 
+  // image while filling the joint histogram. This function returns the value
+  // of the similarity measure using Similarity().
+  virtual double EvaluatePiece(vtkImageData* reference,
+			       vtkImageData* target,
+			       vtkImageData* previoustarget,
+			       vtkImageData* weight=NULL,
+			       vtkImageData* weights2=NULL,
+			       int cpointno=-1);
+  
+  //BTX
+  // Description:
+  // Fast access to the parameters of the grid
+  //ETX
+
+  // Description:
+  // Initial set up for the registration at a multiresolution level
+  virtual int Initialize(int);
+
+  // Description:
+  // Called from Initialize to Initialize the Transformation
+  virtual int InitializeTransformation(int);
+
+  // Description:
+  // Final set up for the registration at a multiresolution level
+  virtual int FinalizeAll();
+
+
+  // Description:
+  // Generate Output
+  virtual void GenerateOutput(int level, int step,int iter,double stepsize,double simil);
+
+
+  // Description:
+  // Needed for Optimizer
+  virtual void SetCurrentParameters(vtkDoubleArray* par);
+  virtual void GetCurrentParameters(vtkDoubleArray* par);
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerGradientGlobal(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+
+  // Description:
+  // SmoothnessMeasure
+  virtual double ComputeInternalEnergy(vtkpxGridTransform* tr,int cp=-1);
+
+
+  // Description:
+  virtual void    ApproximateTransformationToGrid(vtkpxGridTransform* grid,vtkAbstractTransform* tr,double step,
+						  int numiter,int numlevels,
+						  double threshold,double lambda);
+
+  virtual void ApproximateTransformationToGrid(vtkpxGridTransform* grid,vtkAbstractTransform* tr);
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxPolyAbstractTransform.cpp b/bioimagesuite30_src/Registration/vtkpxPolyAbstractTransform.cpp
new file mode 100644
index 0000000..821353e
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxPolyAbstractTransform.cpp
@@ -0,0 +1,516 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxPolyAbstractTransform.cpp,v $
+  Language:  C++
+  Date:      $Date: 2003/04/11 20:00:25 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxPolyAbstractTransform.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+#include "vtkpxAnalyzeImageWriter.h"
+#include "vtkpxAnalyzeImageSource.h"
+#include "vtkpxUtil.h"
+#include "vtkpxTransformationUtil.h"
+#include "vtkpxComboTransform.h"
+#include "vtkpxBaseGridTransform.h"
+#include "vtkpxSimilarityTransform.h"
+//----------------------------------------------------------------------------
+vtkpxPolyAbstractTransform* vtkpxPolyAbstractTransform::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxPolyAbstractTransform");
+  if(ret)
+    {
+      return (vtkpxPolyAbstractTransform*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxPolyAbstractTransform;
+}
+
+//------------------------------------------------------------------------
+vtkpxPolyAbstractTransform::vtkpxPolyAbstractTransform()
+{
+  this->RegionLabel=NULL;
+  this->TransformationCollection=vtkCollection::New();
+  this->ThinPlateSplineTransform=NULL;
+}
+
+//------------------------------------------------------------------------
+vtkpxPolyAbstractTransform::~vtkpxPolyAbstractTransform()
+{
+  if (this->RegionLabel)
+    this->SetRegionLabel(NULL);
+
+  if (this->TransformationCollection)
+    this->TransformationCollection->Delete();
+
+  if (this->ThinPlateSplineTransform!=NULL)
+    this->ThinPlateSplineTransform->Delete();
+}
+
+//------------------------------------------------------------------------
+int vtkpxPolyAbstractTransform::IsValid()
+{
+  if (this->RegionLabel==NULL || this->TransformationCollection->GetNumberOfItems()==0)
+    return 0;
+
+  int nc=this->RegionLabel->GetNumberOfScalarComponents();
+  if (nc!=1 && nc!=4)
+    return 0;
+
+  return 1;
+}
+//------------------------------------------------------------------------
+unsigned long vtkpxPolyAbstractTransform::GetMTime()
+{
+  if (this->IsValid()==0)
+    return 0;
+
+  unsigned long result = this->RegionLabel->GetMTime();
+
+  int np=this->TransformationCollection->GetNumberOfItems();
+  for (int i=0;i<np;i++)
+    {
+      vtkObject* obj=this->TransformationCollection->GetItemAsObject(i);  
+      unsigned long mtime = obj->GetMTime(); 
+      if (mtime > result)
+	result = mtime;
+    }
+
+  return result;
+}
+//------------------------------------------------------------------------
+void vtkpxPolyAbstractTransform::PrintSelf(ostream& os, vtkIndent indent)
+{
+  if (this->IsValid()==0)
+    {
+      os << indent << " Not Initialized \n";
+      return;
+    }
+
+  vtkAbstractTransform::PrintSelf(os,indent);
+  
+  os << indent << "RegionLabel: " << this->RegionLabel << "\n";
+  this->RegionLabel->PrintSelf(os,indent.GetNextIndent());
+
+  os << indent << "TransformationCollection: " << this->TransformationCollection << "\n";
+  this->TransformationCollection->PrintSelf(os,indent.GetNextIndent());
+ 
+  os << indent << "ThinPlateSplineTransform: " << this->ThinPlateSplineTransform << "\n";
+
+}
+
+//----------------------------------------------------------------------------
+vtkAbstractTransform *vtkpxPolyAbstractTransform::MakeTransform()
+{
+  return vtkpxPolyAbstractTransform::New(); 
+}
+
+//----------------------------------------------------------------------------
+void vtkpxPolyAbstractTransform::InternalDeepCopy(vtkAbstractTransform *transform)
+{
+  vtkpxPolyAbstractTransform *t = (vtkpxPolyAbstractTransform *)transform;
+  this->SetRegionLabel(t->GetRegionLabel());
+  
+  this->TransformationCollection->RemoveAllItems();
+
+  vtkCollection* tcol=t->GetTransformationCollection();
+  for (int i=0;i<tcol->GetNumberOfItems();i++)
+    {
+      vtkObject* obj=tcol->GetItemAsObject(i);
+      this->TransformationCollection->AddItem(obj);
+    }
+
+  if (t->GetThinPlateSplineTransform()==NULL)
+    {
+      if (this->ThinPlateSplineTransform!=NULL)
+	this->ThinPlateSplineTransform->Delete();
+      this->ThinPlateSplineTransform=NULL;
+    }
+  else
+    {
+      if (this->ThinPlateSplineTransform==NULL)
+	this->ThinPlateSplineTransform=vtkThinPlateSplineTransform::New();
+      this->ThinPlateSplineTransform->DeepCopy(t->GetThinPlateSplineTransform());
+    }
+  this->Modified();
+}
+//------------------------------------------------------------------------
+void vtkpxPolyAbstractTransform::InternalUpdate()
+{
+  return;
+}
+//------------------------------------------------------------------------
+void vtkpxPolyAbstractTransform::InternalTransformPoint(const double point[3], 
+							double output[3])
+{
+  vtkAbstractTransform* tr0=(vtkAbstractTransform*)(this->TransformationCollection->GetItemAsObject(0));
+
+  if (tr0==NULL || this->RegionLabel==NULL)
+    {
+      vtkErrorMacro(<<"Bad tr0\n");
+      return;
+    }
+
+      
+  if (this->TransformationCollection->GetNumberOfItems()==1)
+    {
+      tr0->InternalTransformPoint(point,output);
+      return;
+    }
+ 
+  int p=this->RegionLabel->FindPoint(point[0],point[1],point[2]);
+  if (p==-1)
+    {
+      if (this->ThinPlateSplineTransform!=NULL)
+	{
+	  //	  fprintf(stderr,"+");
+	  this->ThinPlateSplineTransform->TransformPoint(point,output);
+	}
+      else
+	tr0->TransformPoint(point,output);
+      return;
+    }
+
+  int l=(int)this->RegionLabel->GetPointData()->GetScalars()->GetComponent(p,0);
+  if (l==-1)
+    {
+      if (this->ThinPlateSplineTransform!=NULL)
+	{
+	  //	  fprintf(stderr,"+");
+	  this->ThinPlateSplineTransform->TransformPoint(point,output);
+	}
+      else
+	tr0->TransformPoint(point,output);
+      return;
+    }
+
+  vtkAbstractTransform* tr=(vtkAbstractTransform*)(this->TransformationCollection->GetItemAsObject(l));
+  tr->InternalTransformPoint(point,output);
+
+
+}
+// ---------------------------------------------------------------------------------------
+void vtkpxPolyAbstractTransform::InternalTransformPoint(const float point[3], 
+							float output[3])
+{
+  double x[3]= { point[0],point[1],point[2]};
+  double y[3];
+  this->InternalTransformPoint(x,y);
+  for (int ia=0;ia<=2;ia++)
+    output[ia]=y[ia];
+}
+
+//------------------------------------------------------------------------
+void vtkpxPolyAbstractTransform::InternalTransformDerivative(const double point[3],
+							 double output[3],
+							 double derivative[3][3])
+{
+
+  vtkAbstractTransform* tr0=(vtkAbstractTransform*)(this->TransformationCollection->GetItemAsObject(0));
+  if (this->TransformationCollection->GetNumberOfItems()==1)
+    {
+      tr0->InternalTransformDerivative(point,output,derivative);
+      return;
+    }
+
+  int p=this->RegionLabel->FindPoint(point[0],point[1],point[2]);
+  if (p==-1)
+    {
+      if (this->ThinPlateSplineTransform!=NULL)
+	{
+	  //	  fprintf(stderr,"*");
+	  this->ThinPlateSplineTransform->InternalTransformDerivative(point,output,derivative);
+	}
+      else
+	tr0->InternalTransformDerivative(point,output,derivative);
+      return;
+    }
+
+  int l=(int)this->RegionLabel->GetPointData()->GetScalars()->GetComponent(p,0);
+  if (l==-1)
+    {
+      if (this->ThinPlateSplineTransform!=NULL)
+	{
+	  //	  fprintf(stderr,"*");
+	  this->ThinPlateSplineTransform->InternalTransformDerivative(point,output,derivative);
+	}
+      else
+	tr0->InternalTransformDerivative(point,output,derivative);
+      return;
+    }
+
+
+  vtkAbstractTransform* tr=(vtkAbstractTransform*)(this->TransformationCollection->GetItemAsObject(l));
+
+  if (this->RegionLabel->GetNumberOfScalarComponents()==1)
+    {
+      tr->InternalTransformDerivative(point,output,derivative);
+    }
+  else
+    {
+
+      int l2=(int)this->RegionLabel->GetPointData()->GetScalars()->GetComponent(p,2);
+      vtkAbstractTransform* tr2=(vtkAbstractTransform*)(this->TransformationCollection->GetItemAsObject(l2));
+
+      double w1=this->RegionLabel->GetPointData()->GetScalars()->GetComponent(p,1);
+      double w2=this->RegionLabel->GetPointData()->GetScalars()->GetComponent(p,3);
+      
+      double wsum=w1+w2; if (wsum<0.001) wsum=1.0;
+      w1/=wsum; w2/=wsum;
+
+      double p1[3],p2[3],d1[3][3],d2[3][3];
+      tr->InternalTransformDerivative(point,p1,d1);
+      tr2->InternalTransformDerivative(point,p2,d2);
+      
+      for (int ia=0;ia<=2;ia++)
+	{
+	  output[ia]=(w1*p1[ia]+w2*p2[ia]);
+	  for (int ib=0;ib<=2;ib++)
+	    derivative[ia][ib]=w1*d1[ia][ib]+w2*d2[ia][ib];
+	}
+    }
+}
+// ---------------------------------------------------------------------------------------
+void vtkpxPolyAbstractTransform::InternalTransformDerivative(const float point[3],
+							 float output[3],
+							 float derivative[3][3])
+{
+  double x[3]= { point[0],point[1],point[2]};
+  double y[3];
+  double d[3][3];
+  this->InternalTransformDerivative(x,y,d);
+  for (int ia=0;ia<=2;ia++)
+    {
+      output[ia]=y[ia];
+      for (int ib=0;ib<=2;ib++)
+	derivative[ia][ib]=d[ia][ib];
+    }
+}
+// ---------------------------------------------------------------------------------------
+int vtkpxPolyAbstractTransform::Load(const char* fname)
+{
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+
+  char pxtk_buffer[255];
+  gzgets(fin,pxtk_buffer,100);
+  if (gzfindstringinstring(pxtk_buffer,"#vtkpxPolyAbstractTransform")==0)
+    {
+      gzclose(fin);
+      return 0;
+    }
+
+  gzgets(fin,pxtk_buffer,100);
+  gzgets(fin,pxtk_buffer,200);
+  int numtransforms;      
+  sscanf(pxtk_buffer,"%d",&numtransforms);
+  if (numtransforms<1)
+    {
+      gzclose(fin);
+      return 0;
+    }
+
+  //  fprintf(stderr,"Numtransforms=%d\n",numtransforms);
+  
+  this->TransformationCollection->RemoveAllItems();
+
+  for (int i=0;i<numtransforms;i++)
+    {
+      gzgets(fin,pxtk_buffer,200);
+      gzgets(fin,pxtk_buffer,200);
+      //      fprintf(stderr,"Header: %s\n",pxtk_buffer);
+      gzgets(fin,pxtk_buffer,200);
+      //      fprintf(stderr,"Type : %s\n",pxtk_buffer);
+
+      if (gzfindstringinstring(pxtk_buffer,"Combo Transform")==1)
+	{
+	  vtkpxComboTransform* tr=vtkpxComboTransform::New();
+	  tr->Load(fin);
+	  this->TransformationCollection->AddItem(tr);
+	  tr->Delete();
+	}
+      else if (gzfindstringinstring(pxtk_buffer,"Grid Transform")==1)
+	{
+	  vtkpxGridTransform* tr=vtkpxGridTransform::New();
+	  tr->Load(fin);
+	  this->TransformationCollection->AddItem(tr);
+	  tr->Delete();
+	}
+      else if (gzfindstringinstring(pxtk_buffer,"Similarity Transform")==1)
+	{
+	  vtkpxSimilarityTransform* tr=vtkpxSimilarityTransform::New();
+	  tr->Load(fin);
+	  this->TransformationCollection->AddItem(tr);
+	  tr->Delete();
+	}
+      else if (gzfindstringinstring(pxtk_buffer,"Linear Transform")==1)
+	{
+	  vtkTransform* tr=vtkTransform::New();
+	  vtkMatrix4x4* mat_in=vtkMatrix4x4::New();
+	  mat_in->Identity();
+	  float mat[3];
+	  for (int ia=0;ia<=3;ia++)
+	    {
+	      gzgets(fin,pxtk_buffer,200);
+	      sscanf(pxtk_buffer,"%f %f %f %f",&mat[0],&mat[1],&mat[2],&mat[3]);
+	      for (int j=0;j<=3;j++)
+		mat_in->SetElement(ia,j,mat[j]);
+	    }
+	  tr->Concatenate(mat_in);
+	  mat_in->Delete();
+	  this->TransformationCollection->AddItem(tr);
+	  tr->Delete();
+	}
+    }
+
+  if (this->ThinPlateSplineTransform==NULL)
+    this->ThinPlateSplineTransform=vtkThinPlateSplineTransform::New();
+     
+  int ok=vtkpxTransformationUtil::LoadThinPlateSplineTransform(this->ThinPlateSplineTransform,fin);
+  if (ok==0)
+    {
+      this->ThinPlateSplineTransform->Delete();
+      this->ThinPlateSplineTransform=NULL;
+    }
+        
+
+  gzclose(fin);
+
+  vtkpxAnalyzeImageSource* w=vtkpxAnalyzeImageSource::New();
+  w->Load(fname);
+
+  this->SetRegionLabel(w->GetOutput());
+  w->Delete();
+  
+  return 1;
+}
+
+void vtkpxPolyAbstractTransform::Identity()
+{
+  int np=this->TransformationCollection->GetNumberOfItems();
+  for (int i=0;i<np;i++)
+    {
+      vtkObject* obj=this->TransformationCollection->GetItemAsObject(i);  
+      if (obj->IsA("vtkAbstractTransform"))
+	((vtkAbstractTransform*)obj)->Identity();
+    }
+}
+
+int vtkpxPolyAbstractTransform::Save(const char* fname)
+{
+  if (this->IsValid()==0)
+    return 0;
+
+  vtkpxAnalyzeImageWriter* w=vtkpxAnalyzeImageWriter::New();
+  w->SetInput(this->RegionLabel);
+  w->Save(fname);
+  
+  int np=this->TransformationCollection->GetNumberOfItems();
+
+
+  FILE* fout=fopen(fname,"w");
+  fprintf(fout,"#vtkpxPolyAbstractTransform\n");
+  fprintf(fout,"#Number Of Transformations\n");
+  fprintf(fout,"%d\n",np);
+
+  for (int i=0;i<np;i++)
+    {
+      fprintf(fout,"#*****************************\n#Transformation %d\n",i+1);
+      vtkObject* obj=this->TransformationCollection->GetItemAsObject(i);  
+      if (obj->IsA("vtkpxComboTransform"))
+	{
+	  fprintf(fout,"# Combo Transform\n");
+	  ((vtkpxComboTransform*)(obj))->Save(fout);
+	}
+      else if (obj->IsA("vtkpxBaseGridTransform"))
+	{
+	  fprintf(fout,"# Grid Transform\n");
+	  ((vtkpxBaseGridTransform*)(obj))->Save(fout);
+	}
+      else if (obj->IsA("vtkpxSimilarityTransform"))
+	{
+	  fprintf(fout,"# Similarity Transform\n");
+	  ((vtkpxSimilarityTransform*)(obj))->Save(fout);
+	}
+      else if (obj->IsA("vtkLinearTransform"))
+	{
+	  vtkLinearTransform* tr=(vtkLinearTransform*)obj;
+	  fprintf(fout,"# Linear Transform\n");
+	  for(int row=0;row<=3;row++)
+	    {
+	      for (int j=0;j<=3;j++)
+		fprintf(fout,"%7.3f ",tr->GetMatrix()->GetElement(row,j));
+	      fprintf(fout,"\n");
+	    }
+	}
+    }
+
+  if (this->ThinPlateSplineTransform==NULL)
+    fprintf(fout,"No Thin Plate Spline Transform\n");
+  else
+    vtkpxTransformationUtil::SaveThinPlateSplineTransform(this->ThinPlateSplineTransform,fout);
+    
+  fclose(fout);
+  return 1;
+}
+
+
+void vtkpxPolyAbstractTransform::Inverse()
+{
+  vtkErrorMacro(<<"Inverse Not Implemented Yet\n");
+}
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxPolyAbstractTransform.h b/bioimagesuite30_src/Registration/vtkpxPolyAbstractTransform.h
new file mode 100644
index 0000000..e51e5ce
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxPolyAbstractTransform.h
@@ -0,0 +1,163 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxPolyAbstractTransform.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+ ========================================================================*/
+
+#ifndef __vtkpxPolyAbstractTransform_h
+#define __vtkpxPolyAbstractTransform_h
+
+#include "vtkWarpTransform.h"
+#include "vtkCollection.h"
+#include "vtkImageData.h"
+#include "vtkAbstractTransform.h"
+#include "vtkTransform.h"
+#include "vtkThinPlateSplineTransform.h"
+
+class vtkpxPolyAbstractTransform : public vtkAbstractTransform
+{
+public:
+  vtkTypeMacro(vtkpxPolyAbstractTransform,vtkAbstractTransform);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  static vtkpxPolyAbstractTransform *New();
+
+  // Description:
+  // Set Image that functions as a lookup table 
+  // 1-component == no blending
+  // 4-component == (1=id1,2=wgt1 (x100),3=id2,4=wgt2(x100))
+  vtkGetObjectMacro(RegionLabel,vtkImageData);
+  vtkSetObjectMacro(RegionLabel,vtkImageData);
+
+  // Description:
+  // Get Thin Plate Spline Transform
+  vtkGetObjectMacro(ThinPlateSplineTransform,vtkThinPlateSplineTransform);
+
+
+  
+  // Description:
+  // Get Transformation Collection
+  vtkGetObjectMacro(TransformationCollection,vtkCollection);
+
+  // Description:
+  // Make another transform of the same type.
+  vtkAbstractTransform *MakeTransform();
+  
+  // Description:
+  // Get Linear Transform
+  //  virtual vtkAbstractTransform* GetTransform(int i) ;
+  //  virtual void SetTransform(int i,vtkAbstractTransform* i);
+
+  // Description:
+  // Save & Load Transform into .tal file
+  int Load(const char* fname);
+  int Save(const char* fname);
+
+  // Description:
+  // Get MTime
+  unsigned long GetMTime();
+
+
+  // Description:
+  // Inverse
+  virtual void Inverse();
+
+  // Description:
+  // Identity
+  virtual void Identity();
+
+
+protected:
+  vtkpxPolyAbstractTransform();
+  virtual ~vtkpxPolyAbstractTransform();
+  vtkpxPolyAbstractTransform(const vtkpxPolyAbstractTransform&) {};
+  void operator=(const vtkpxPolyAbstractTransform&) {};
+
+  vtkCollection* TransformationCollection;
+  vtkImageData*  RegionLabel;
+  vtkThinPlateSplineTransform* ThinPlateSplineTransform;
+
+  // Description:
+  virtual int IsValid();
+
+  // Description:
+  // Prepare the transformation for application.
+  void InternalUpdate();
+
+  // Description:
+  // This method does no type checking, use DeepCopy instead.
+  void InternalDeepCopy(vtkAbstractTransform *transform);
+
+  // Description:
+  // Internal Transform Point -- OK
+  void InternalTransformPoint(const float in[3], float out[3]);
+  void InternalTransformPoint(const double in[3], double out[3]);
+
+  // Description:
+  // Internal Transform Derivative (Not done yet) -- OK
+  void InternalTransformDerivative(const float in[3], float out[3],
+				  float derivative[3][3]);
+  void InternalTransformDerivative(const double in[3], double out[3],
+				  double derivative[3][3]);
+
+
+
+
+};
+
+#endif
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxPolySimilarityTransform.cpp b/bioimagesuite30_src/Registration/vtkpxPolySimilarityTransform.cpp
new file mode 100644
index 0000000..c290edd
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxPolySimilarityTransform.cpp
@@ -0,0 +1,1279 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxPolySimilarityTransform.cpp,v $
+  Language:  C++
+  Date:      $Date: 2003/04/11 20:00:25 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkAppendPolyData.h"
+#include "vtkContourFilter.h"
+#include "vtkDataArray.h"
+#include "vtkDecimatePro.h"
+#include "vtkGlyph3D.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageMathematics.h"
+#include "vtkLinearTransform.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkSphereSource.h"
+#include "vtkpxAnalyzeImageSource.h"
+#include "vtkpxAnalyzeImageWriter.h"
+#include "vtkpxArticulatedJointTransform.h"
+#include "vtkpxAppendComponents.h"
+#include "vtkpxOptimizer.h"
+#include "vtkpxPolySimilarityTransform.h"
+#include "vtkpxUtil.h"
+#include "vtkpxTransformationUtil.h"
+#include "vtkImageDataGeometryFilter.h"
+#include "vtkThresholdPoints.h"
+#include "vtkGridTransform.h"
+#include "vtkImageThreshold.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkCleanPolyData.h"
+#include "vtkPolyDataWriter.h"
+#include "vtkThinPlateSplineTransform.h"
+#include "vtkPolyDataConnectivityFilter.h"
+//----------------------------------------------------------------------------
+vtkpxPolySimilarityTransform* vtkpxPolySimilarityTransform::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxPolySimilarityTransform");
+  if(ret)
+    {
+      return (vtkpxPolySimilarityTransform*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxPolySimilarityTransform;
+}
+
+//------------------------------------------------------------------------
+vtkpxPolySimilarityTransform::vtkpxPolySimilarityTransform()
+{
+  vtkpxArticulatedJointTransform* tr=vtkpxArticulatedJointTransform::New();
+  tr->SetModeToRotationScaleTranslation();
+  this->SetTransform(0,tr);
+  tr->Delete();
+  this->RegionLabelImageName=NULL; this->SetRegionLabelImageName("Joint");
+
+}
+//------------------------------------------------------------------------
+vtkpxPolySimilarityTransform::~vtkpxPolySimilarityTransform()
+{
+  if (this->RegionLabelImageName!=NULL)
+    delete [] RegionLabelImageName;
+
+}
+//------------------------------------------------------------------------
+void vtkpxPolySimilarityTransform::SetCylinderPreset(int numparts)
+{
+  if (numparts<2)
+    numparts=2;
+  else if (numparts>3)
+    numparts=3;
+
+  char line[40];
+
+  this->TransformationCollection->RemoveAllItems();
+  vtkpxArticulatedJointTransform* tr[2];
+
+  for (int i=0;i<numparts;i++)
+    {
+      tr[i]=vtkpxArticulatedJointTransform::New();
+      if (i==0)
+	{
+	  tr[i]->SetModeToRotationTranslation();
+	  tr[i]->SetBlendedMode(0);
+	}
+      else 
+	{
+	  tr[i]->SetModeToRotationOnly();
+	  fprintf(stderr,"Setting Mode to Rotation Only\n");
+	  tr[i]->SetBlendedMode(1);
+	  tr[i]->SetAlignmentTransform(tr[i-1]);
+	  tr[i]->SetAlignmentTransformIndex(i-1);
+	}
+
+      tr[i]->SetChildRegionLabelIndex(i+1);
+      tr[i]->SetChildRegionLabelIndex2(numparts-1);
+      tr[i]->ExternalSetRegionLabelImage(this->RegionLabel);
+      tr[i]->SetRegionLabelIndex(i);
+      sprintf(line,"Joint_%d",i+1);
+      tr[i]->SetJointName(line);
+    }
+
+  for (int i=0;i<numparts;i++)
+    {
+      this->SetTransform(i,tr[i]);
+      tr[i]->Delete();
+    }
+
+}
+
+
+//------------------------------------------------------------------------
+void vtkpxPolySimilarityTransform::SetWholeBodyPreset(int doscale,int hasfeet,
+						      int hashindlimbs,int hasforelimbs,int hashead, int taildivisions,
+						      int spinedivisions)
+{
+  this->TransformationCollection->RemoveAllItems();
+
+  if (spinedivisions>10)
+    spinedivisions=10;
+  else if (spinedivisions<1)
+    spinedivisions=0;
+
+  hasfeet=(hasfeet>0);
+  hashead=(hashead>0);
+  hashindlimbs=(hashindlimbs>0);
+  hasforelimbs=(hasforelimbs>0);
+  hashead=(hashead>0);
+
+  char line[100],partname[50];
+  
+  if (taildivisions<1)
+    taildivisions=0;
+  else if (taildivisions>5)
+    taildivisions=5;
+
+  int legparts=2+hasfeet;
+  
+  int totalparts=
+    1 + 2*legparts*(hashindlimbs+hasforelimbs) +
+    hashead +
+    spinedivisions +
+    taildivisions;
+
+
+  // Create Defaults
+  vtkpxArticulatedJointTransform* tr[30];
+  for (int i=0;i<totalparts;i++)
+    {
+      tr[i]=vtkpxArticulatedJointTransform::New();
+      tr[i]->SetModeToRotationOnly();
+      tr[i]->SetBlendedMode(2);
+      tr[i]->SetRegionLabelIndex(i);
+      tr[i]->ExternalSetRegionLabelImage(this->RegionLabel);
+      tr[i]->SetRegionLabelIndex(i);
+      this->SetTransform(i,tr[i]);
+      tr[i]->Delete();
+    }
+
+  for (int i=0;i<totalparts;i++)
+    tr[i]=this->GetTransform(i);
+
+  // One part at a time --- first the abdomen core part
+  tr[0]->SetBlendedMode(0);
+  if (doscale)
+    tr[0]->SetModeToRotationScaleTranslation();
+  else
+    tr[0]->SetModeToRotationTranslation();
+  tr[0]->SetChildRegionLabelIndex(1);
+  tr[0]->SetChildRegionLabelIndex2(totalparts);
+  tr[0]->SetJointName("Global_0");
+
+  int shoulderjoint = totalparts-(1+hashead);
+
+  if (hashindlimbs == 1 || hasforelimbs == 1 ) 
+    {
+      int minleg=0;
+      int maxleg=3;
+      if (hashindlimbs==0)
+	minleg=2;
+      if (hasforelimbs ==0)
+	maxleg=1;
+    
+      for (int leg=minleg;leg<=maxleg;leg++)
+	{
+	  if (leg==0 || leg==2)
+	    sprintf(partname,"Left");
+	  else
+	    sprintf(partname,"Right");
+	  
+	  int baseindex=leg*legparts+1;
+	  int maxindex =baseindex+legparts-1;
+	  int index=baseindex;
+	  
+	  for (int part=0;part<legparts;part++)
+	    {
+	      if (part==0)
+		{
+		  tr[index]->SetModeToRotationOnly();
+		  if (leg<2)
+		    {
+		      tr[index]->SetAlignmentTransform(tr[0]);
+		      tr[index]->SetAlignmentTransformIndex(0);
+		    }
+		  else
+		    {
+		      tr[index]->SetAlignmentTransform(tr[shoulderjoint]);
+		      tr[index]->SetAlignmentTransformIndex(shoulderjoint);
+		    }
+
+		  if (leg<2)
+		    sprintf(line,"%s-Hipp_%d",partname,index);
+		  else
+		    sprintf(line,"%s-Shoulder_%d",partname,index);
+		  tr[index]->SetJointName(line);
+
+		}
+	      else // either abdomen parts or knee/ankle
+		{
+		  tr[index]->SetModeToRotationXYOnly();
+		  tr[index]->SetAlignmentTransform(tr[index-1]);
+		  tr[index]->SetAlignmentTransformIndex(index-1);
+		  
+		  if (leg<2)
+		    {
+		      if (part==1)
+			sprintf(line,"%s-Knee_%d",partname,index);
+		      else
+			sprintf(line,"%s-Ankle_%d",partname,index);
+		    }
+		  else
+		    {
+		      if (part==1)
+			sprintf(line,"%s-Elbow_%d",partname,index);
+		      else
+			sprintf(line,"%s-Wrist_%d",partname,index);
+		    }
+		  tr[index]->SetJointName(line);
+		}
+	      tr[index]->SetChildRegionLabelIndex(index+1);
+	      tr[index]->SetChildRegionLabelIndex2(maxindex);
+	      ++index;
+	    }
+	}
+    }
+
+  if ((spinedivisions+hashead)> 0 || taildivisions > 0 ) 
+    {
+      int cut[3];
+      cut[0]=legparts*2*(hashindlimbs+hasforelimbs)+1;
+      cut[1]=cut[0]+taildivisions;
+      cut[2]=totalparts;
+
+      int minregion=0,maxregion=1;
+      if (taildivisions==0)
+	minregion=1;
+      if( (spinedivisions+hashead)==0)
+	maxregion=0;
+
+      for (int region=minregion;region<=maxregion;region++)
+	{
+	  int baseindex=cut[region];
+	  int maxindex=cut[region+1]-1;
+	  int index=baseindex;
+	  int numparts=maxindex-baseindex+1;
+
+	  for (int part=0;part<numparts;part++)
+	    {
+	      if (region==1)
+		tr[index]->SetModeToRotationOnly(); // Abdomen is fully flexed
+	      else
+		tr[index]->SetModeToRotationXYOnly(); // Tail is mostly circular anyway
+
+	      if (part==0)
+		{
+		  tr[index]->SetAlignmentTransform(tr[0]);
+		  tr[index]->SetAlignmentTransformIndex(0);
+		}
+	      else
+		{
+		  tr[index]->SetAlignmentTransform(tr[index-1]);
+		  tr[index]->SetAlignmentTransformIndex(index-1);
+		}
+	      tr[index]->SetChildRegionLabelIndex(index+1);
+	      tr[index]->SetChildRegionLabelIndex2(maxindex);
+
+
+	      if (region==0)
+		sprintf(line,"Tail_%d",index);
+	      else if (hashead==1 && index==maxindex)
+		sprintf(line,"Neck_%d",index);
+	      else
+		sprintf(line,"Spine_%d",index);
+
+	      tr[index]->SetJointName(line);
+	      ++index;
+	    }
+	}
+    }
+}
+
+//------------------------------------------------------------------------
+void vtkpxPolySimilarityTransform::SetRegionLabel(vtkImageData* h)
+{
+  vtkpxPolyAbstractTransform::SetRegionLabel(h);
+  int np=this->TransformationCollection->GetNumberOfItems();
+  for (int i=0;i<np;i++)
+    {
+      vtkpxArticulatedJointTransform* tr=this->GetTransform(i);
+      tr->ExternalSetRegionLabelImage(this->RegionLabel);
+      tr->SetRegionLabelIndex(i);
+      tr->Modified();
+    }
+
+}
+
+//------------------------------------------------------------------------
+void vtkpxPolySimilarityTransform::SetTransform(int i,vtkpxArticulatedJointTransform* tr)
+{
+  int np=this->TransformationCollection->GetNumberOfItems();
+  if (i>=np)
+    {
+      this->TransformationCollection->AddItem(tr);
+    }
+  else
+    {
+      this->TransformationCollection->ReplaceItem(i,tr);
+    }
+
+}
+vtkpxArticulatedJointTransform* vtkpxPolySimilarityTransform::GetTransform(int i)
+{
+  int np=this->TransformationCollection->GetNumberOfItems();
+  if (np==0 || i>=np || i<0)
+    return NULL;
+
+  return (vtkpxArticulatedJointTransform*)this->TransformationCollection->GetItemAsObject(i);
+}
+// ---------------------------------------------------------------------------
+int vtkpxPolySimilarityTransform::GetNumberOfTransformations()
+{
+  return this->TransformationCollection->GetNumberOfItems();
+ 
+}
+// ---------------------------------------------------------------------------
+int vtkpxPolySimilarityTransform::Load(const char* fname)
+{
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+
+  char pxtk_buffer[255];
+  gzgets(fin,pxtk_buffer,100);
+  if (gzfindstringinstring(pxtk_buffer,"#vtkpxPolySimilarityTransform2")==0)
+    {
+      gzclose(fin);
+      return 0;
+    }
+
+  gzgets(fin,pxtk_buffer,100);
+  gzgets(fin,pxtk_buffer,200);
+  int numtransforms;      
+  sscanf(pxtk_buffer,"%d",&numtransforms);
+  if (numtransforms<1)
+    {
+      gzclose(fin);
+      return 0;
+    }
+  
+  gzgets(fin,pxtk_buffer,200);
+  gzgets(fin,pxtk_buffer,200);
+  int a=strlen(pxtk_buffer);  pxtk_buffer[a-1]=(char)0;
+  this->SetRegionLabelImageName(pxtk_buffer);
+
+  this->TransformationCollection->RemoveAllItems();
+
+  for (int i=0;i<numtransforms;i++)
+    {
+      gzgets(fin,pxtk_buffer,200);
+      gzgets(fin,pxtk_buffer,200);
+      vtkpxArticulatedJointTransform* tr=vtkpxArticulatedJointTransform::New();
+      tr->Load(fin);
+      this->SetTransform(i,tr);
+      tr->Delete();
+    }
+
+  if (this->ThinPlateSplineTransform==NULL)
+    this->ThinPlateSplineTransform=vtkThinPlateSplineTransform::New();
+  
+  int ok=vtkpxTransformationUtil::LoadThinPlateSplineTransform(this->ThinPlateSplineTransform,fin);
+  if (ok==0)
+    {
+      this->ThinPlateSplineTransform->Delete();
+      this->ThinPlateSplineTransform=NULL;
+    }
+
+  gzclose(fin);
+
+  // Fix Alignment Transform Stuff -- i.e. re-establish hierarchy
+  for (int i=0;i<numtransforms;i++)
+    {
+      vtkpxArticulatedJointTransform* tr=this->GetTransform(i);
+      int ind=tr->GetAlignmentTransformIndex();
+      if (ind>=0 && ind<numtransforms && ind!=i)
+	tr->SetAlignmentTransform(this->GetTransform(ind));
+    }
+
+
+
+  vtkpxAnalyzeImageSource* w=vtkpxAnalyzeImageSource::New();
+  w->Load(this->RegionLabelImageName);
+
+  this->SetRegionLabel(w->GetOutput());
+  w->Delete();
+  
+  return 1;
+}
+// ---------------------------------------------------------------------------
+int vtkpxPolySimilarityTransform::Save(const char* fname)
+{
+  if (this->IsValid()==0)
+    return 0;
+
+  /*  vtkpxAnalyzeImageWriter* w=vtkpxAnalyzeImageWriter::New();
+  w->SetInput(this->RegionLabel);
+  w->SetCompression(9);
+  w->Save(fname);*/
+  
+  int np=this->TransformationCollection->GetNumberOfItems();
+
+
+  FILE* fout=fopen(fname,"w");
+  fprintf(fout,"#vtkpxPolySimilarityTransform2\n");
+  fprintf(fout,"#Number Of Transformations\n");
+  fprintf(fout,"%d\n",np);
+  fprintf(fout,"#RegionLabelImageName\n%s\n",this->RegionLabelImageName);
+  for (int i=0;i<np;i++)
+    {
+      fprintf(fout,"#*****************************\n#Transformation %d\n",i+1);
+      vtkpxArticulatedJointTransform* tr=this->GetTransform(i);
+      tr->Save(fout);
+    }
+
+  if (this->ThinPlateSplineTransform==NULL)
+    fprintf(fout,"No Thin Plate Spline Transform\n");
+  else
+    vtkpxTransformationUtil::SaveThinPlateSplineTransform(this->ThinPlateSplineTransform,fout);
+
+  fclose(fout);
+  return 1;
+}
+// ---------------------------------------------------------------------------
+int  vtkpxPolySimilarityTransform::GetNumberOfParameters()
+{
+  int n=0;
+  int np=this->TransformationCollection->GetNumberOfItems();
+  for (int i=0;i<np;i++)
+    n+= this->GetTransform(i)->GetNumberOfParameters();
+
+  return n;
+}
+// ---------------------------------------------------------------------------
+void vtkpxPolySimilarityTransform::SetCurrentParameters(vtkDoubleArray* params)
+{
+  int nt=params->GetNumberOfTuples();
+  int np=this->GetNumberOfParameters();
+  
+  if (nt<np)
+    {
+      vtkErrorMacro(<<"Insufficient number of parameters " << nt << "," << np);
+      return;
+    }
+
+  int nc=this->TransformationCollection->GetNumberOfItems();
+  int offset=0;
+  for (int j=0;j<nc;j++)
+    {
+      vtkpxArticulatedJointTransform* tr=this->GetTransform(j);
+      int nump=tr->GetNumberOfParameters();
+	if (nump>0)
+	  {
+	    tr->SetParameters(params,offset);
+	    offset+= nump;
+	  }
+    }
+}
+// ---------------------------------------------------------------------------
+void vtkpxPolySimilarityTransform::GetCurrentParameters(vtkDoubleArray* params)
+{
+ int nt=params->GetNumberOfTuples();
+ int np=this->GetNumberOfParameters();
+  
+  if (nt<np)
+    {
+      vtkErrorMacro(<<"Insufficient number of parameters " << nt << "," << np);
+      return;
+    }
+
+  int nc=this->TransformationCollection->GetNumberOfItems();
+  int offset=0;
+  for (int j=0;j<nc;j++)
+    {
+      vtkpxArticulatedJointTransform* tr=this->GetTransform(j);
+      int nump=tr->GetNumberOfParameters();
+	if (nump>0)
+	  {
+	    tr->GetParameters(params,offset);
+	    offset+= nump;
+	  }
+    }
+}
+
+
+// ---------------------------------------------------------------------------
+// Optimization Stuff
+// ---------------------------------------------------------------------------
+// Description:
+// These are needed for the Optimizer 
+void vtkpxPolySimilarityTransform::OptimizerFeedback(vtkObject* self,const char* line,double val)
+{
+  
+  fprintf(stderr,"%s %f\n",line,val);
+}
+
+double vtkpxPolySimilarityTransform::CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output)
+{
+  return ((vtkpxPolySimilarityTransform*)self)->OptimizerGradient(position,output);
+}
+
+double vtkpxPolySimilarityTransform::CalculateFunction(vtkObject* self,vtkDoubleArray* position)
+{
+  return ((vtkpxPolySimilarityTransform*)self)->OptimizerValue(position);
+}
+
+// ---------------------------------------------------------------------------
+double vtkpxPolySimilarityTransform::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+{
+  if (grad->GetNumberOfComponents()!=1 || grad->GetNumberOfTuples()!=OptimizationStructure.maxdofs)
+    {
+      grad->SetNumberOfComponents(1);
+      grad->SetNumberOfTuples(OptimizationStructure.maxdofs);
+    }
+
+  grad->FillComponent(0,0.0);
+  //double old_similarity=this->OptimizerValue(params);
+  double GradientNorm = 0;
+
+  for (int i=0;i<OptimizationStructure.maxdofs;i++)
+    {
+      double orig=params->GetComponent(i,0);
+      params->SetComponent(i, 0, orig + this->OptimizationStructure.step);
+      double a=this->OptimizerValue(params);
+      
+      params->SetComponent(i, 0, orig - this->OptimizationStructure.step);
+      double b=this->OptimizerValue(params);
+
+      params->SetComponent(i, 0, orig);
+      this->SetCurrentParameters(params);
+      
+      double g=-0.5*(b-a)/this->OptimizationStructure.step;
+      grad->SetComponent(i,0,g);
+      GradientNorm+=pow(g,2.0);
+    }
+  GradientNorm = (sqrt(GradientNorm));
+
+
+  // -------------------------
+  // Hirohito Found this One!!
+  // -------------------------
+  for (int j=0;j<OptimizationStructure.maxdofs;j++)
+    grad->SetComponent(j,0,grad->GetComponent(j,0)/GradientNorm);
+      
+  return GradientNorm;
+}
+// ---------------------------------------------------------------------------
+double vtkpxPolySimilarityTransform::OptimizerValue(vtkDoubleArray* params)
+{
+  this->SetCurrentParameters(params);
+  return this->Evaluate();
+}
+// ---------------------------------------------------------------------------
+
+double vtkpxPolySimilarityTransform::Evaluate()
+{
+  
+  vtkPoints* p1=OptimizationStructure.sourcePoints;
+  vtkPoints* p2=OptimizationStructure.targetPoints;
+
+  int useweights=0;
+  int np=p1->GetNumberOfPoints();
+  if (OptimizationStructure.weights!=NULL)
+    {
+      if (OptimizationStructure.weights->GetSize()[0]==np)
+	useweights=1;
+    }
+
+  double p[3],q[3];
+  double sum=0.0,nsum=0.00001;
+  for (int i=0;i<np;i++)
+    {
+      p1->GetPoint(i,p);
+      p2->GetPoint(i,q);
+      this->TransformPoint(p,p);
+
+      double w=1.0;
+      if (useweights)
+	w=OptimizationStructure.weights->GetElement(i,0);
+      
+      sum+=w*vtkMath::Distance2BetweenPoints(p,q);
+      nsum+=w;
+    }
+
+  return sum/nsum;
+}
+// ---------------------------------------------------------------------------
+double vtkpxPolySimilarityTransform::ApproximatePoints(vtkPoints* SourceLandmarks,vtkPoints* TargetLandmarks,vtkpxMatrix* Weights,
+						       int numsteps,float stepsize,float tolerance)
+{
+  if (SourceLandmarks==NULL || TargetLandmarks==NULL)
+    {
+      vtkErrorMacro(<<"One or more Point Sets=NULL in input to ApproximatePoints\n");
+      return 0.0;
+    }
+  
+  int np1=SourceLandmarks->GetNumberOfPoints();
+  int np2=TargetLandmarks->GetNumberOfPoints();
+
+  if (np1!=np2)
+    {
+      vtkErrorMacro(<<"Bad point sets " << np1 << " vs " << np2 << " in input to ApproximatePoints\n");
+      return 0.0;
+    } 
+
+  vtkpxMatrix* optweights=NULL;
+  if (Weights!=NULL)
+    {
+      if (Weights->GetSize()[0]==np1)
+	optweights=Weights;
+    }
+
+  int nparam=this->GetNumberOfParameters();
+
+  vtkpxOptimizer* optimizer=vtkpxOptimizer::New();
+  vtkDoubleArray* position=vtkDoubleArray::New();
+  position->SetNumberOfTuples(nparam);
+  vtkDoubleArray* temp=vtkDoubleArray::New();
+  temp->SetNumberOfTuples(nparam);
+  
+  this->GetCurrentParameters(position);
+
+  optimizer->SetMasterObject(this);
+  optimizer->SetEvaluateFunctionMethod(&vtkpxPolySimilarityTransform::CalculateFunction);
+  optimizer->SetEvaluateGradientMethod(&vtkpxPolySimilarityTransform::CalculateGradient);
+  optimizer->SetFeedbackMethod(&vtkpxPolySimilarityTransform::OptimizerFeedback);
+  
+  double v=0.0;
+  numsteps=Irange(numsteps,1,3);
+
+  fprintf(stderr,"\n Approximating Transformation using %d points numsteps=%d step=%.3f tolerance=%.3f\n",np1,
+	  numsteps,stepsize,tolerance);
+
+  this->OptimizationStructure.SetLandmarksAndWeights(SourceLandmarks,TargetLandmarks,optweights);
+
+  for (int step=1;step<=numsteps;step++)
+    {
+      this->OptimizationStructure.SetValues(nparam,stepsize,step);
+      v=optimizer->ComputeConjugateGradient(position,20,tolerance);
+      stepsize*=0.5;
+      tolerance*=0.5;
+    }
+
+  //  temp->Delete();
+  //  position->Delete();
+  //  optimizer->Delete();
+  
+  return v;
+}
+
+// ----------------------------------------------------------------------
+// ----------------------------------------------------------------------
+void vtkpxPolySimilarityTransform::FixOrigins(double gap)
+{
+  int nt=this->GetNumberOfTransformations();
+  if (nt<2)
+    return;
+
+  for (int i=1;i<nt;i++)
+    {
+      vtkpxArticulatedJointTransform* tr=this->GetTransform(i);
+      tr->AdjustOriginToBeOutside(gap);
+    }
+}
+
+
+void vtkpxPolySimilarityTransform::SetOriginAxes(vtkPoints* points)
+{
+  if (points==NULL)
+    {
+      vtkErrorMacro(<<"Bad Points (NULL)\n");
+      return;
+    }
+
+  int nt=this->GetNumberOfTransformations();
+  if (points->GetNumberOfPoints()<nt*3 || nt==0)
+    {
+      vtkErrorMacro(<<"Bad Points (Not Enough or not enough transformations)\n");
+      return;
+    }
+  
+  for (int i=0;i<nt;i++)
+    {
+      double ori[3],p1[3],p2[3];
+      points->GetPoint(i*3,ori);
+      points->GetPoint(i*3+1,p1);
+      points->GetPoint(i*3+2,p2);
+      vtkpxArticulatedJointTransform* tr=this->GetTransform(i);
+      tr->SetOriginLocalAxis(ori,p1,p2);
+    }
+}
+
+vtkPolyData* vtkpxPolySimilarityTransform::DrawAxis(float scale,float length)
+{
+  // Combination of
+  // a sphere at origin and p1 and a line from -p1 to p2
+
+  int nt=this->GetNumberOfTransformations();
+  if (nt<1)
+    return NULL;
+
+  vtkPoints    *c_points    = vtkPoints::New();
+  vtkPoints    *o_points    = vtkPoints::New();
+  vtkCellArray *c_lines     = vtkCellArray::New();
+  
+  o_points->Allocate(nt);
+  c_points->Allocate(nt*3);
+  c_lines->Allocate(nt*2,5);
+  
+  vtkIdType index=0,pt[2];
+  float x[3],x2[3],x3[3],n[3];
+
+  for (int i=1;i<nt;i++)
+    {
+      vtkpxSimilarityTransform* tr=this->GetTransform(i)->GetSimilarityTransform();
+      tr->GetOrigin(x);
+      tr->GetRotationAxis(n);
+
+      for (int ia=0;ia<=2;ia++)
+	{
+	  x2[ia]=x[ia]-n[ia]*length;
+	  x3[ia]=x[ia]+n[ia]*length;
+	}
+      /*      vtkAbstractTransform* align=this->GetTransform(i)->GetAlignmentTransform();
+      if (align!=NULL)
+	{
+	  align->TransformPoint(x,x);
+	  align->TransformPoint(x2,x2);
+	  align->TransformPoint(x3,x3);
+	  }*/
+      
+      c_points->InsertNextPoint(x2);
+      c_points->InsertNextPoint(x);
+      c_points->InsertNextPoint(x3);
+
+      o_points->InsertNextPoint(x);
+      o_points->InsertNextPoint(x3);
+      pt[0]=index;  pt[1]=index+1;
+      c_lines->InsertNextCell(2,pt);
+      pt[0]=index+1;  pt[1]=index+2;
+      c_lines->InsertNextCell(2,pt);
+      index+=3;
+    }
+  
+  vtkPolyData* curve=vtkPolyData::New();
+  curve->SetPoints(c_points);
+  curve->SetLines(c_lines);
+  c_points->Delete();
+  c_lines->Delete();
+
+  vtkPolyData* centers=vtkPolyData::New();
+  centers->SetPoints(o_points);
+  o_points->Delete();
+
+  vtkTubeFilter* tube=vtkTubeFilter::New();
+  tube->SetInput(curve);
+  tube->SetRadius(scale*0.5);
+  tube->SetNumberOfSides(8);
+  tube->SetVaryRadiusToVaryRadiusOff();
+  tube->Update();
+
+  curve->Delete();
+
+  vtkGlyph3D* glyph=vtkGlyph3D::New();
+  vtkSphereSource* sphere=vtkSphereSource::New();
+  sphere->SetRadius(scale);
+  sphere->Update();
+  glyph->SetSource(sphere->GetOutput());
+  glyph->SetInput(centers);
+  glyph->Update();
+
+  centers->Delete();
+  sphere->Delete();
+  
+  vtkAppendPolyData* append=vtkAppendPolyData::New();
+  append->AddInput(glyph->GetOutput());
+  append->AddInput(tube->GetOutput());
+  append->Update();
+
+  vtkDecimatePro* deciFilter=vtkDecimatePro::New();
+  deciFilter->SetInput(append->GetOutput());
+  deciFilter->SetTargetReduction(0.9);
+  deciFilter->PreserveTopologyOn();
+  deciFilter->Update();
+  
+
+  vtkPolyData* output=vtkPolyData::New();
+  output->ShallowCopy(deciFilter->GetOutput());
+  tube->Delete();
+  glyph->Delete();
+  deciFilter->Delete();
+  return output;
+}
+// ----------------------------------------------------------------------
+int vtkpxPolySimilarityTransform::InitializeRearLimbPresetRotations(vtkPoints* points)
+{
+  return this->InitializeRearLimbPresetRotations(points,NULL);
+}
+// ----------------------------------------------------------------------
+int vtkpxPolySimilarityTransform::InitializeRearLimbPresetRotations(vtkPoints* orig_points,
+								    vtkLinearTransform* lin_tr)
+{
+  if (orig_points==NULL)
+    return 0;
+
+  // Somehow use tr->Inverse to move the points back so that we can compute angles
+  // -----------------------------------------------------------------------------
+
+
+  int nt=this->TransformationCollection->GetNumberOfItems();
+  int np=orig_points->GetNumberOfPoints();
+  
+  if (np< nt-1)
+    {
+      fprintf(stderr,"Not Enough Points\n");
+      return 0;
+    }
+
+  vtkPoints* points=vtkPoints::New();
+  points->DeepCopy(orig_points);
+
+  if (lin_tr!=NULL)
+    {
+      for (int i=0;i<np;i++)
+	{
+	  double x[3]; points->GetPoint(i,x);
+	  lin_tr->GetLinearInverse()->TransformPoint(x,x);
+	  points->SetPoint(i,x);
+	}
+    }
+	
+  vtkTransform* concat=vtkTransform::New();
+  
+  for (int i=1;i<nt;i++)
+    {
+      vtkpxArticulatedJointTransform* tr=this->GetTransform(i);
+      int ch=tr->GetChildRegionLabelIndex();
+      if (ch >=0)
+	{
+	  vtkpxArticulatedJointTransform* trchild=this->GetTransform(ch);
+	  float x1[3]; tr->GetOrigin(x1);
+	  float x2[3]; trchild->GetOrigin(x2);
+	  double x[3];
+
+	  double p1[3]; points->GetPoint(i-1,p1);
+	  double p2[3]; points->GetPoint(ch-1,p2);
+
+	  // Back Shift p1 and p2 ......
+	  concat->Identity();
+	  concat->PostMultiply();
+	  
+	  vtkpxArticulatedJointTransform* current=tr;
+
+	  int done=0,numt=0;
+	  while (done==0)
+	    {
+	      vtkAbstractTransform* trparent0=current->GetAlignmentTransform();
+	      done=1;
+
+	      if (trparent0!=NULL)
+		{
+		  if (trparent0->IsA("vtkpxArticulatedJointTransform")==1)
+		    {
+		      vtkpxArticulatedJointTransform* joint=(vtkpxArticulatedJointTransform*)trparent0;
+
+		      if (joint->GetSeparateZRotation()>0)
+			concat->Concatenate(joint->GetZSimilarityTransform());
+		      concat->Concatenate(joint->GetSimilarityTransform());
+		      current=joint;
+		      done=0;
+		      ++numt;
+		    }
+		}
+	    }
+
+	  fprintf(stderr,"\n\n\n +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ \n");
+	  fprintf(stderr,"Tr=%d ch=%d  origins=(%.2f,%.2f,%.2f),(%.2f,%.2f,%.2f) ----> (%.2f,%.2f,%.2f), (%.2f,%.2f,%.2f)\n",
+		  i,ch,
+		  x1[0],x1[1],x1[2],x2[0],x2[1],x2[2],
+		  p1[0],p1[1],p1[2],p2[0],p2[1],p2[2]);
+		
+
+	  concat->Inverse();
+	  concat->TransformPoint(p1,p1);
+	  concat->TransformPoint(p2,p2);
+
+	  fprintf(stderr,"\t\t Transform points numt=%d  ----> (%.2f,%.2f,%.2f), (%.2f,%.2f,%.2f)\n",
+		  numt,p1[0],p1[1],p1[2],p2[0],p2[1],p2[2]);
+		  
+	  for (int ia=0;ia<=2;ia++)
+	    {
+	      p2[ia]=p2[ia]-p1[ia];
+	      x[ia]=x2[ia]-x1[ia];
+	    }
+
+	  fprintf(stderr,"\t\t\t vectors (%.2f,%.2f,%.2f)  and (%.2f,%.2f,%.2f)\n\n\n\n",
+		  x[0],x[1],x[2],p2[0],p2[1],p2[2]);
+
+	  tr->InitializeAngles(x,p2);
+	}
+    }
+
+  points->Delete();
+  return 1;
+}
+      
+
+vtkPoints* vtkpxPolySimilarityTransform::CreateTestPoints()
+{
+  vtkPoints* pt=vtkPoints::New();
+  int nt=this->TransformationCollection->GetNumberOfItems();
+
+  pt->SetNumberOfPoints(nt-1);
+  for (int i=1;i<nt;i++)
+    {
+      vtkpxArticulatedJointTransform* tr=this->GetTransform(i);
+      float x1[3]; tr->GetOrigin(x1);
+      float x2[3];
+      this->TransformPoint(x1,x2);
+      fprintf(stderr,"x1=(%.2f,%.2f,%.2f) --> (%.2f,%.2f,%.2f)\n",
+	      x1[0],x1[1],x1[2],
+	      x2[0],x2[1],x2[2]);
+      pt->SetPoint(i-1,x2[0],x2[1],x2[2]);
+    }
+
+  return pt;
+}
+
+void vtkpxPolySimilarityTransform::Identity()
+{
+  int np=this->TransformationCollection->GetNumberOfItems();
+  for (int i=0;i<np;i++)
+    this->GetTransform(i)->Identity();
+}
+// ----------------------------------------------------------------------
+int vtkpxPolySimilarityTransform::UpdateThinPlateSplineTransform()
+{
+  return this->CreateThinPlateSplineTransform(-150);
+}
+// ----------------------------------------------------------------------
+vtkPoints* vtkpxPolySimilarityTransform::CreateSamplePoints(int numberofpoints,float smooth,float ratio,float startsample)
+{
+  if (this->RegionLabel==NULL)
+    {
+      vtkErrorMacro(<<"No Region Label , Cannot create Sample Points\n");
+      return NULL;
+    }
+
+
+  vtkPoints* sourcePoints=vtkPoints::New();
+
+
+  if (numberofpoints<40)
+    numberofpoints=40;
+  else if (numberofpoints>10000)
+    numberofpoints=10000;
+  
+  if (smooth<0.5)
+    smooth=0.5;
+  else if (smooth>4.0)
+    smooth=4.0;
+  
+  if (ratio<1.1)
+    ratio=1.1;
+  else if (ratio>3.0)
+    ratio=3.0;
+  
+  if (startsample<2.0)
+    startsample=2.0;
+  else if (startsample>10.0)
+    startsample=10.0;
+  
+  fprintf(stderr,"SamplePoints :: Thresholding nc=%d smooth=%.2f ratio=%.2f startsample=%.2f\n",
+	  numberofpoints,smooth,ratio,startsample);
+  
+  vtkImageThreshold* thr=vtkImageThreshold::New();
+  thr->SetInput(this->RegionLabel);
+  thr->ThresholdBetween(0.0,100);
+  thr->SetInValue(100);
+  thr->SetOutValue(0);
+  thr->ReplaceInOn();
+  thr->ReplaceOutOn();
+      
+  fprintf(stderr,"SamplePoints :: Smoothing\n");
+  vtkImageGaussianSmooth* smoothFilter=vtkImageGaussianSmooth::New();
+  smoothFilter->SetInput(thr->GetOutput());
+  smoothFilter->SetStandardDeviations(smooth,smooth,smooth);
+  smoothFilter->Update();
+  thr->Delete();
+      
+      
+  fprintf(stderr,"SamplePoints :: Extracting\n");
+  vtkContourFilter* skinExtractor=vtkContourFilter::New();
+  skinExtractor->SetInput(smoothFilter->GetOutput());
+  skinExtractor->SetNumberOfContours(1);
+  skinExtractor->SetValue(0,99.0);
+  skinExtractor->ComputeScalarsOff();
+  skinExtractor->ComputeGradientsOff();
+  skinExtractor->ComputeNormalsOff();
+  skinExtractor->Update();
+  
+  vtkPolyData* poly=vtkPolyData::New();
+  poly->ShallowCopy(skinExtractor->GetOutput());
+  skinExtractor->Delete();
+  
+  fprintf(stderr,"SamplePoints:: Resampling\n");
+  
+  
+  double sampling=startsample*this->RegionLabel->GetSpacing()[0];
+  
+  vtkCleanPolyData* cleanerFilter=vtkCleanPolyData::New();
+  cleanerFilter->SetInput(poly);
+  cleanerFilter->SetToleranceIsAbsolute(1);
+  
+  int np1=poly->GetNumberOfPoints();
+  fprintf(stderr,"SamplePoints:: Original Number of Points =%d sampling=%.2f\n",np1,sampling);
+  
+  int totalnp=np1,iter=1;
+  
+  while (totalnp>numberofpoints*1.1 && iter<20)
+    {
+      cleanerFilter->SetAbsoluteTolerance(sampling);
+      cleanerFilter->Modified();
+      cleanerFilter->Update();
+      
+      totalnp=cleanerFilter->GetOutput()->GetNumberOfPoints();
+      fprintf(stderr,"\t\t\t SamplePoints: iter=%d \t Sampling %.2f \t  np=%d\n",iter,sampling,totalnp);
+      sampling*=ratio;
+      ++iter;
+    }
+  
+  
+  poly->ShallowCopy(cleanerFilter->GetOutput());
+  
+  int finalnp=poly->GetNumberOfPoints();
+  fprintf(stderr,"\t\t\t SamplePoints: Final reduction = %d (%.2f)\n",finalnp,sampling);
+  cleanerFilter->Delete();
+  sourcePoints->DeepCopy(poly->GetPoints());
+  poly->Delete();
+  return sourcePoints;
+}
+// ----------------------------------------------------------------------
+int vtkpxPolySimilarityTransform::CreateThinPlateSplineTransform(int numberofcontrolpoints,float smooth,float ratio,float startsample)
+{
+  if (this->RegionLabel==NULL)
+    {
+      vtkErrorMacro(<<"No Region Label , Cannot create TPS Transform\n");
+      return 0;
+    }
+
+  int reinitialize=1;
+
+  if (numberofcontrolpoints<0)
+    {
+      if (this->ThinPlateSplineTransform!=NULL)
+	{
+	  if (this->ThinPlateSplineTransform->GetSourceLandmarks()->GetNumberOfPoints()>5)
+	    {
+	      reinitialize=0;
+	    }
+	}
+
+      if (reinitialize==1)
+	numberofcontrolpoints=abs(numberofcontrolpoints);
+    }
+
+  vtkPoints* sourcePoints=NULL;
+
+
+  if (reinitialize == 1 )
+    {
+      if (numberofcontrolpoints>400)
+	numberofcontrolpoints=400;
+      sourcePoints=CreateSamplePoints(numberofcontrolpoints,smooth,ratio,startsample);
+    }
+  else
+    {
+      sourcePoints=vtkPoints::New();
+      sourcePoints->DeepCopy(this->ThinPlateSplineTransform->GetSourceLandmarks());
+      fprintf(stderr,"Not Reinitializing, just recomputing displacements nc=%d\n",
+	      sourcePoints->GetNumberOfPoints());
+
+    }
+  
+  int totalnp=sourcePoints->GetNumberOfPoints();
+
+  fprintf(stderr,"Transforming Points\n");
+  vtkPoints* targetPoints=vtkPoints::New();
+  targetPoints->DeepCopy(sourcePoints);
+  for (int i=0;i<totalnp;i++)
+    {
+      double px[3],py[3];
+      sourcePoints->GetPoint(i,px);
+      
+      this->TransformPoint(px,py);
+      // This needs to be checked
+      // int p=this->RegionLabel->FindPoint(px);
+      targetPoints->SetPoint(i,py);
+    }
+  
+  fprintf(stderr,"Creating TPS\n");
+
+  if (this->ThinPlateSplineTransform==NULL)
+    this->ThinPlateSplineTransform = vtkThinPlateSplineTransform::New();
+  this->ThinPlateSplineTransform->SetSourceLandmarks(sourcePoints);
+  this->ThinPlateSplineTransform->SetTargetLandmarks(targetPoints);
+  this->ThinPlateSplineTransform->SetBasisToR();
+  this->ThinPlateSplineTransform->Update();
+
+  sourcePoints->Delete();
+  targetPoints->Delete();
+
+  return totalnp;
+}
+
+// ----------------------------------------------------------------------
+void vtkpxPolySimilarityTransform::InitializeComboTransform(vtkpxComboTransform* combotransform,
+						   int numpoints,int numsteps,double smoothness)
+{
+  if (combotransform->GetGridTransform()->GetNumberOfControlPoints()<50)
+    {
+      fprintf(stderr,"Bad Combo Transform, cannot initialize\n");
+      return;
+    }
+
+  // First the linear part
+  
+  if (combotransform->GetNonLinearFirst()!=1)
+    combotransform->SetNonLinearFirst(1);
+  
+  vtkpxSimilarityTransform* sim=vtkpxSimilarityTransform::New();
+  sim->Copy(this->GetTransform(0)->GetSimilarityTransform());
+  combotransform->GetLinearTransform()->Identity();
+  combotransform->GetLinearTransform()->Concatenate(sim);
+
+
+  // For now set global part to identity this is covered by the linear
+  // part of vtkpxComboTransform
+  this->GetTransform(0)->GetSimilarityTransform()->Identity();
+
+  // Next Create a thin plate spline transformation ....
+  vtkPoints* sourcePoints=this->CreateSamplePoints(numpoints);
+
+  if (sourcePoints==NULL)
+    {
+      fprintf(stderr,"Bad Poly Similarity Transformation");
+      return;
+    }
+
+  double sp[3]; this->GetRegionLabel()->GetSpacing(sp);
+  double voxelsize=sp[0];
+
+  // Now approximate points in multiple steps
+  vtkPoints* tmpPoints=vtkPoints::New();
+
+  int np=sourcePoints->GetNumberOfPoints();
+  tmpPoints->SetNumberOfPoints(np);
+
+  fprintf(stderr,"Number of Sampled Points=%d\n",np);
+
+  vtkDataArray* disp=combotransform->GetGridTransform()->GetDisplacementGrid()->GetPointData()->GetScalars();
+  for (int i=0;i<=2;i++)
+    disp->FillComponent(i,0.0);
+
+  if (numsteps<1)
+    numsteps=1;
+  else if (numsteps>50)
+    numsteps=50;
+    
+  vtkCollection* collection=vtkCollection::New();
+  combotransform->GetGridTransform()->FormCollectionStructure(sourcePoints,collection,0.01);
+  
+
+  
+
+  for (int i=1;i<=numsteps;i++)
+    {
+      fprintf(stderr,"Approximation, step %d/%d\n",i,numsteps);
+      double fraction=double(i)/double(numsteps);
+      for (int j=0;j<np;j++)
+	{
+	  double x[3]; sourcePoints->GetPoint(j,x);
+	  double y[3]; this->TransformPoint(x,y);
+	  double t[3];
+	  for (int ia=0;ia<=2;ia++)
+	    t[ia]=fraction*(y[ia]-x[ia])+x[ia];
+	  tmpPoints->SetPoint(j,t);
+	}
+      combotransform->GetGridTransform()->ApproximatePoints(sourcePoints,tmpPoints,collection,voxelsize*0.1,
+							    20,1,voxelsize*0.2,smoothness,0);
+    }
+  collection->Delete();
+  tmpPoints->Delete();
+
+  // Restore polysimilarity transform to initial stage
+  this->GetTransform(0)->GetSimilarityTransform()->Copy(sim);
+  sim->Delete();
+}
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxPolySimilarityTransform.h b/bioimagesuite30_src/Registration/vtkpxPolySimilarityTransform.h
new file mode 100644
index 0000000..6fefb3d
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxPolySimilarityTransform.h
@@ -0,0 +1,227 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxPolySimilarityTransform.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+ ========================================================================*/
+
+#ifndef __vtkpxPolySimilarityTransform_h
+#define __vtkpxPolySimilarityTransform_h
+
+#include "vtkWarpTransform.h"
+#include "vtkCollection.h"
+#include "vtkImageData.h"
+#include "vtkpxPolyAbstractTransform.h"
+#include "vtkpxArticulatedJointTransform.h"
+#include "vtkPoints.h"
+#include "vtkCellArray.h"
+#include "vtkTubeFilter.h"
+#include "vtkpxMatrix.h"
+#include "vtkpxGridTransform.h"
+#include "vtkpxComboTransform.h"
+#include "vtkpxTransformationUtil.h"
+#include "vtkThinPlateSplineTransform.h"
+
+//BTX
+class vtkpxPolySimilarityOptimizationStructure {
+public:
+  double step;
+  int   st;
+  int   maxdofs;
+
+  vtkPoints *sourcePoints,*targetPoints;
+  vtkpxMatrix* weights;
+
+  vtkpxPolySimilarityOptimizationStructure() {
+    sourcePoints=NULL;
+    targetPoints=NULL;
+    weights=NULL;
+  }
+
+  void SetValues(int maxdofs0,double step0,
+		 int st0)
+  {
+    this->step=step0;
+    this->maxdofs=maxdofs0;
+    this->st=st0;
+  }
+
+  void SetLandmarksAndWeights(vtkPoints* p1,vtkPoints* p2,vtkpxMatrix* w)
+  {
+    sourcePoints=p1;
+    targetPoints=p2;
+    weights=w;
+  }
+};
+//ETX
+
+class vtkpxPolySimilarityTransform : public vtkpxPolyAbstractTransform
+{
+public:
+  vtkTypeMacro(vtkpxPolySimilarityTransform,vtkpxPolyAbstractTransform);
+  static vtkpxPolySimilarityTransform *New();
+
+
+  // Description:
+  // Set Label Image
+  virtual void SetRegionLabel(vtkImageData* h);
+
+  // Description:
+  // Get Linear Transform
+  virtual void SetTransform(int i,vtkpxArticulatedJointTransform* tr);
+  virtual vtkpxArticulatedJointTransform* GetTransform(int i);
+  virtual int GetNumberOfTransformations();
+
+  // Description:
+  // This is a preset
+  virtual void SetWholeBodyPreset(int doscale,int hasfeet,
+				 int hashindlimbs,int hasforelimbs,
+				 int hashead, int taildivisions,
+					 int spinedivisions);
+
+  virtual void SetCylinderPreset(int numparts=2);
+
+
+  // Description:
+  // Save & Load Transform into .tal file
+  int Load(const char* fname);
+  int Save(const char* fname);
+
+  // Description:
+  // Optimization Parameters
+  virtual int  GetNumberOfParameters();
+  virtual void SetCurrentParameters(vtkDoubleArray* param);
+  virtual void GetCurrentParameters(vtkDoubleArray* param);
+
+  // Description:
+  // These are needed for the Optimizer 
+  static void   OptimizerFeedback(vtkObject* self,const char* line,double val);
+  static double CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output);
+  static double CalculateFunction(vtkObject* self,vtkDoubleArray* position);
+
+  // Description:
+  // Compute Gradients etc
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+
+  // Description:
+  // Fix Origins
+  virtual void FixOrigins(double gap=2.0);
+  virtual void SetOriginAxes(vtkPoints* points);
+  vtkPolyData* DrawAxis(float scale=2.0,float length=100.0);
+
+  // Description:
+  // Approximate Points
+  virtual double ApproximatePoints(vtkPoints* SourceLandmarks,vtkPoints* TargetLandmarks,vtkpxMatrix* Weights,
+				   int numsteps=1,float beginstepsize=1.0,float tolerance=0.01);
+
+
+
+  
+  // Description:
+  // Initialize Rotations
+  virtual int InitializeRearLimbPresetRotations(vtkPoints* points);
+  virtual int InitializeRearLimbPresetRotations(vtkPoints* points,vtkLinearTransform* tr);
+  virtual vtkPoints* CreateTestPoints();
+
+
+  // Description:
+  // Identity
+  virtual void Identity();
+
+  // Description:
+  // Specify name of the region label image
+  vtkSetStringMacro(RegionLabelImageName);
+  vtkGetStringMacro(RegionLabelImageName);
+
+  // Description:
+  // Create Displacement Field
+  virtual int UpdateThinPlateSplineTransform();
+  virtual int CreateThinPlateSplineTransform(int numberofcontrolpoints=150,float smooth=2.0,float ratio=1.25,float startsample=-1.0);
+  virtual vtkPoints* CreateSamplePoints(int numberofpoints=1500,float smooth=1.5,float ratio=1.25,float startsample=-1.0);
+
+  // Description:
+  // Initialize from a Poly Similarity Transform
+  virtual void InitializeComboTransform(vtkpxComboTransform* combo,int numpoints,int numsteps,double smoothness=0.0001);
+
+
+protected:
+  vtkpxPolySimilarityTransform();
+
+  vtkpxPolySimilarityTransform(const vtkpxPolySimilarityTransform&) {};
+  virtual ~vtkpxPolySimilarityTransform();
+
+  void operator=(const vtkpxPolySimilarityTransform&) {};
+
+  // Get Transformation Collection
+  vtkGetObjectMacro(TransformationCollection,vtkCollection);
+
+  vtkpxPolySimilarityOptimizationStructure OptimizationStructure;
+
+  // Description:
+  // File Name for RegionLabelImage
+  char          *RegionLabelImageName;
+
+
+  // Description:
+  // Evaluate
+  virtual double Evaluate();
+
+};
+
+#endif
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxRPMCorrespondenceFinder.cpp b/bioimagesuite30_src/Registration/vtkpxRPMCorrespondenceFinder.cpp
new file mode 100644
index 0000000..8033b33
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxRPMCorrespondenceFinder.cpp
@@ -0,0 +1,1319 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxRPMTransform.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/03/12 16:49:59 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkDataSet.h"
+#include "vtkFloatArray.h"
+#include "vtkIdList.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkOldStyleCallbackCommand.h"
+#include "vtkPointLocator.h"
+#include "vtkTransform.h"
+#include "vtkTriangleFilter.h"
+#include "vtkpxMath.h"
+#include "vtkpxMatrix.h"
+#include "vtkpxRPMCorrespondenceFinder.h"
+#include "vtkpxSparseMatrix.h"
+#include "vtkpxUtil.h"
+#include "vtkpxWeightedLandmarkTransform.h"
+#include "pxutil.h"
+//-----------------------------------------------------------------------------------
+
+vtkpxRPMCorrespondenceFinder* vtkpxRPMCorrespondenceFinder::New()
+{
+  // First try to create the object from the vtkObjectFactory
+
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxRPMCorrespondenceFinder");
+  if(ret)
+    {
+    return (vtkpxRPMCorrespondenceFinder*)ret;
+    }
+
+  // If the factory was unable to create the object, then create it here.
+
+  return new vtkpxRPMCorrespondenceFinder;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxRPMCorrespondenceFinder::vtkpxRPMCorrespondenceFinder()
+{
+  M=NULL; M_Outliers_Row=NULL; M_Outliers_Column=NULL;   
+  X=NULL; VX=NULL; Y=NULL; VY=NULL; LX=NULL; LY=NULL;                  
+  Locator=NULL; PointsX=NULL;  PointsVY=NULL;
+  Temperature=0.02;
+
+  this->Source = NULL;
+  this->Target = NULL;
+
+
+  this->EnableFeedback=0;
+
+  this->MaximumNumberOfLandmarks = 2000;
+
+  this->MatchMode=1;
+ 
+  this->UseLabels=1;
+  this->UseAttributes=0;
+  this->FastThreshold=2.0;
+  this->ExtraDebug=0;
+
+  this->InitialTransform=NULL;
+  this->UseInitialTransform=0;
+
+  this->UseWeightedLeastSquares=1;
+  this->MatchMatrixType=-1;
+  this->PreferentialSampling=0;
+  this->AttributesWeight=0.1;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxRPMCorrespondenceFinder::~vtkpxRPMCorrespondenceFinder()
+{
+  this->CleanUp();
+
+  ReleaseSource();
+  ReleaseTarget();
+  this->SetInitialTransform(NULL);
+
+}
+
+void vtkpxRPMCorrespondenceFinder::CleanUp()
+{
+  cleanobject(M);    cleanobject(M_Outliers_Row);    cleanobject(M_Outliers_Column);
+  cleanobject(X);    cleanobject(VX);    cleanobject(Y);    cleanobject(VY);
+  cleanobject(LX);   cleanobject(LY);    cleanobject(Locator);
+  cleanobject(PointsX);   
+  cleanobject(PointsVY);
+
+
+  M=NULL; M_Outliers_Row=NULL; M_Outliers_Column=NULL;   
+  X=NULL; VX=NULL; Y=NULL; VY=NULL; LX=NULL; LY=NULL;                  
+  Locator=NULL; PointsX=NULL;  PointsVY=NULL;
+}
+
+void vtkpxRPMCorrespondenceFinder::SetSource(vtkPolyData *source)
+{
+  if (this->Source == source)
+      return;
+  
+  if (this->Source)
+    this->ReleaseSource();
+  
+  if (source)
+    source->Register(this);
+  
+  this->Source = source;
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+
+void vtkpxRPMCorrespondenceFinder::ReleaseSource(void) 
+{
+  if (this->Source) 
+    {
+      this->Source->UnRegister(this);
+      this->Source = NULL;
+    }
+}
+
+//----------------------------------------------------------------------------
+
+void vtkpxRPMCorrespondenceFinder::SetTarget(vtkPolyData *target)
+{
+  if (this->Target == target)
+    return;
+  
+  if (this->Target)
+    this->ReleaseTarget();
+  
+  if (target)
+    target->Register(this);
+  
+  this->Target = target;
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+
+void vtkpxRPMCorrespondenceFinder::ReleaseTarget(void) 
+{
+  if (this->Target) 
+    {
+      this->Target->UnRegister(this);
+      this->Target = NULL;
+    }
+}
+
+//----------------------------------------------------------------------------
+void vtkpxRPMCorrespondenceFinder::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkProcessObject::PrintSelf(os,indent);
+
+  if ( this->Source ) 
+    {
+      os << indent << "Source: " << this->Source << "\n";
+    }
+  else 
+    {
+      os << indent << "Source: (none)\n";
+    }
+  
+  if ( this->Target ) 
+    {
+      os << indent << "Target: " << this->Target << "\n";
+    }
+  else 
+    {
+      os << indent << "Target: (none)\n";
+    }
+  
+  os << indent << "MaximumNumberOfLandmarks: " << this->MaximumNumberOfLandmarks << "\n";
+  os << indent << "MatchMode: " << this->MatchMode << "\n";
+}
+
+
+//----------------------------------------------------------------------------
+void vtkpxRPMCorrespondenceFinder::Initialize(vtkAbstractTransform* OffsetTransform)
+{
+  this->CleanUp();
+  fprintf(stderr,"\n\n\n\n --------------------------------\n External Initialization \n ----------------------- \n");
+
+  // Sample Points 
+  X=vtkpxMatrix::New(); LX=vtkpxMatrix::New();
+  Y=vtkpxMatrix::New(); LY=vtkpxMatrix::New();
+  this->SamplePoints(X,Y,LX,LY,this->MaximumNumberOfLandmarks,this->PreferentialSampling);
+
+  int sz[2],nump_x,nump_y;
+  X->GetSize(sz);   nump_x=sz[0];
+  Y->GetSize(sz);   nump_y=sz[0];
+  vtkDebugMacro(<< "Initialization: Using " << nump_x << " , " << nump_y << "Landmarks UseLabels="<< this->UseLabels << "or Attributes " << this->UseAttributes << "\n");
+
+  // Initialize Match Matrices 
+  this->M=this->AllocateMatchMatrix();
+  M_Outliers_Row=vtkpxMatrix::New();
+  M_Outliers_Column=vtkpxMatrix::New();
+  this->InitMatchMatrices(M,M_Outliers_Row,M_Outliers_Column,nump_x,nump_y);
+  
+  // Initialize Transformed X and Y stuff 
+  VX=vtkpxMatrix::New();   VX->Copy(X);
+  VY=vtkpxMatrix::New();   VY->Copy(X);
+
+
+  int useinit=(this->UseInitialTransform>0);
+  if (useinit ==1 && this->InitialTransform==NULL)
+    useinit=0;
+
+  int useoffset=0;
+  if (OffsetTransform!=NULL)
+    useoffset=1;
+
+  if ( useoffset > 0 || useinit > 0 )
+    {
+      float ox[3],x[3],tx[3];
+      for (int i=0;i<nump_x;i++)
+	{
+	  for (int ia=0;ia<3;ia++)
+	    ox[ia]=VX->GetDirectElement(i,ia);
+	
+	  if (useoffset)
+	    {
+	      OffsetTransform->TransformPoint(ox,ox);
+	      for (int ib=0;ib<3;ib++)
+		X->SetDirectElement(i,ib,ox[ib]);
+	    }
+
+	  if (useinit > 0 ) 
+	    {
+	      this->InitialTransform->TransformPoint(x,tx);
+	      for (int ib=0;ib<3;ib++)
+		VX->SetDirectElement(i,ib,tx[ib]);
+	    }
+	  else 
+	    {
+	      for (int ib=0;ib<3;ib++)
+		VX->SetDirectElement(i,ib,ox[ib]);
+	    }
+	}
+      
+      M_Outliers_Column->Fill(1.0);
+    }
+
+  this->Locator=this->CreateLocator(this->Y);
+  this->Collection=vtkCollection::New();
+  
+  int np=this->X->GetSize()[0];
+  
+  this->PointsX=vtkPoints::New();
+  this->PointsX->SetNumberOfPoints(np);
+  this->PointsVY=vtkPoints::New();
+  this->PointsVY->SetNumberOfPoints(np);
+  
+  
+  for (int i=0;i<np;i++)
+    {
+      float x[3];
+      for (int ia=0;ia<=2;ia++)
+	x[ia]=this->X->GetDirectElement(i,ia);
+      
+      this->PointsX->SetPoint(i,x);
+      this->PointsVY->SetPoint(i,x);
+    }
+}
+
+//----------------------------------------------------------------------------
+void vtkpxRPMCorrespondenceFinder::WarpAndUpdateCorrespondence(vtkAbstractTransform* warpTransform,
+							       float temperature)
+
+{
+  this->TransformPoints(warpTransform,this->X,this->VX);
+  
+  this->SetTemperature(temperature);
+  
+  // Somewhere here do annealing etc
+
+  this->UpdateCorrespondence(this->M,
+			     this->M_Outliers_Row,
+			     this->M_Outliers_Column,
+			     this->VX,
+			     this->Y,
+			     this->VY,
+			     this->Temperature,
+			     this->Locator,
+			     this->LX,
+			     this->LY);
+
+  /*  this->X->Print("X");
+  this->Y->Print("Y");
+  this->VX->Print("VX");
+  this->VY->Print("VY");
+  this->M->Print("M");
+  this->M_Outliers_Column->Print("OC");
+  this->M_Outliers_Row->Print("OR");
+  */
+
+  this->UpdateVYPoints();
+
+  /*  if (this->M_Outliers_Column!=NULL)
+    {
+      int np=this->M_Outliers_Column->GetSize()[0];
+      float sum=0.0,sum2=0.0,vmin=1.0e+30,vmax=-1.0e+30;
+      int numlow=0,nummed=0,numhigh=0;
+      for (int i=0;i<np;i++)
+	{
+	  float v=M_Outliers_Column->GetElement(i,0);
+	  vmin=Fmin(v,vmin);
+	  vmax=Fmax(v,vmax);
+	  if (v<0.75)
+	    ++numlow;
+	  else if (v>1.25)
+	    ++numhigh;
+	  else
+	    ++nummed;
+	  sum+=v;
+	  sum2+=v*v;
+	}
+
+      float mean=sum/float(np);
+      float std= sqrt(sum2/float(np) - mean*mean);
+      fprintf(stderr,"Outlier Range=%.2f:%.2f mean=%.2f std=%.2f (low=%.2f,med=%.2f high=%.2f)\n",
+	      vmin,vmax,mean,std,
+	      100.0*float(numlow)/float(np),
+	      100.0*float(nummed)/float(np),
+	      100.0*float(numhigh)/float(np));
+	      }*/
+}
+//----------------------------------------------------------------------------
+void vtkpxRPMCorrespondenceFinder::UpdateVYPoints()
+{
+  int np=this->VY->GetSize()[0];
+
+  for (int i=0;i<np;i++)
+    {
+      float y[3];
+      for (int ia=0;ia<=2;ia++)
+	y[ia]=this->VY->GetDirectElement(i,ia);
+      
+
+      this->PointsVY->SetPoint(i,y);
+    }
+}
+//----------------------------------------------------------------------------
+
+void vtkpxRPMCorrespondenceFinder::MapPointsICP(vtkpxMatrix* VX,vtkpxMatrix* Y,
+						vtkpxMatrix* VY,vtkPointLocator* locator)
+					
+{
+  int size[2];
+  VX->GetSize(size);
+
+  if (this->ExtraDebug) 
+    fprintf(stderr,"Forming ICP Map and Warp %d ...",size[0]);
+
+
+  double x[3];
+  for (int k=0;k<=2;k++)
+    x[k]=0.0;
+
+  // Find Closest point and use binary correspondece!
+  for (int i=0;i<size[0];i++)
+    {
+      VX->GetRow(i,3,x);
+      int id=locator->FindClosestPoint(x);
+      Y->GetRow(id,3,x);
+      VY->SetRow(i,3,x);
+    }
+
+  if (this->ExtraDebug) 
+    fprintf(stderr,"Done\n");
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+void vtkpxRPMCorrespondenceFinder::MapPointsICPPlus(vtkpxMatrix* VX,vtkpxMatrix* Y,vtkpxMatrix* VY,
+						    float T,vtkPointLocator* locator)
+					       
+{
+  int size[2];
+  VX->GetSize(size);
+
+  //float minvalue=0.1/float(size[1]);
+
+  if (this->ExtraDebug) 
+    fprintf(stderr,"Forming Fast Distance and Map %d ...",size[0]);
+
+  int total=0;
+
+
+
+  double p1[3],p2[3],p1h[3];
+  this->ZeroArray(3,p1);
+  this->ZeroArray(3,p2);
+      
+  vtkIdList* idlist=vtkIdList::New();
+
+  float T2=2.0*T*T;
+
+  for (int row=0;row<size[0];row++)
+    {
+      float sum=0.0;
+      VX->GetRow(row,3,p1);
+      this->ZeroArray(3,p1h);
+           
+      locator->FindPointsWithinRadius(T*this->FastThreshold,p1,idlist);
+      int np=idlist->GetNumberOfIds();
+
+      if (np<5)
+	{
+	  locator->FindClosestNPoints(5,p1,idlist);
+	  np=idlist->GetNumberOfIds();
+	}
+
+      total+=np;
+
+      for (int j=0;j<np;j++)
+	{
+	  int column=idlist->GetId(j);
+	  if (column>=0)
+	    {
+	      Y->GetRow(column,3,p2);
+	      float dist= vtkMath::Distance2BetweenPoints(p1, p2);
+	      float m=exp(-dist/T2);//+(vtkpxMath::GaussianRandom()*0.001/float(size[0]));
+	      /*if (m<minvalue)
+		m=minvalue;*/
+	      for (int ic=0;ic<3;ic++)
+		p1h[ic]+=m*p2[ic];
+	      sum+=m;
+	    }
+	}
+      for (int ic=0;ic<3;ic++)
+	VY->SetDirectElement(row,ic,p1h[ic]/sum);
+
+    }
+  if (this->ExtraDebug) 
+    fprintf(stderr,"%d done \n",total/size[0]);
+}
+
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+void vtkpxRPMCorrespondenceFinder::FormDistanceMatrix(vtkpxAbstractMatrix* M,vtkpxMatrix* VX,vtkpxMatrix* Y,float T,
+							 vtkpxMatrix* LX,vtkpxMatrix* LY)
+{
+  int size[2];
+  M->GetSize(size);
+  M->Zero();
+
+  //  float minvalue=0.00000001;
+
+
+
+
+  int dolabels=0;
+  int numattributes=1;
+  float* labelx=NULL;
+  float* labely=NULL;
+
+  if (LX!=NULL && LY!=NULL)
+    {
+      if (this->UseLabels>0)
+	{
+	  dolabels=1;
+	}
+      else if (this->UseAttributes>0)
+	{
+	  dolabels=2;
+	  numattributes=LX->GetSize()[1];
+	}
+    }
+  else
+    {
+      numattributes=0;
+    }
+
+  if (this->ExtraDebug) 
+    fprintf(stderr,"Forming Distance Matrix %dx%d ... uselabels=%d  (numattr=%d)",size[0],size[1],dolabels,numattributes);
+  
+
+  if (dolabels>0)
+    {
+      labelx=new float[numattributes];
+      labely=new float[numattributes];
+    }
+
+  double p1[3],p2[3];
+  for (int k=0;k<=2;k++)
+    {
+      p1[k]=0.0;
+      p2[k]=0.0;
+    }
+
+  float T2=2.0*T*T;
+
+  for (int row=0;row<size[0];row++)
+    {
+      for (int ia=0;ia<3;ia++)
+	p1[ia]=VX->GetDirectElement(row,ia);
+
+      if (dolabels==1)
+	{
+	  labelx[0]=(int)LX->GetDirectElement(row,0);
+	}
+      else if (dolabels==2)
+	{
+	  for (int j=0;j<numattributes;j++)
+	    labelx[j]=LX->GetDirectElement(row,j);
+	}
+
+      for (int column=0;column<size[1];column++)
+	{
+	  float adddist=0.0;
+	  if (dolabels==1)
+	    {
+	      labely[0]=(int)LY->GetDirectElement(column,0);
+	    }
+	  else if (dolabels==2)
+	    {
+	      for (int j=0;j<numattributes;j++)
+		{
+		  labely[j]=LY->GetDirectElement(column,j);
+		  adddist+=pow(labelx[j]-labely[j],float(2.0));
+		}
+	      adddist=this->AttributesWeight * adddist;
+	    }
+	  
+	  if (dolabels!=1 || labelx[0]==labely[0])
+	    {
+	      p2[2]=0.0;
+	      for (int ib=0;ib<3;ib++)
+		p2[ib]=Y->GetDirectElement(column,ib);
+	      
+	      float dist= vtkMath::Distance2BetweenPoints(p1, p2) + adddist;
+	      float m=exp(-dist/T2);
+	      if (m>0.0000)
+		M->SetDirectElement(row,column,m);
+	      else
+		M->SetDirectElement(row,column,0.00000);
+	    }
+	}
+    }
+
+  if (labelx!=NULL)
+    delete [] labelx;
+  
+  if (labely!=NULL)
+    delete [] labely;
+
+  if (this->ExtraDebug) 
+    fprintf(stderr,"done \n");
+}
+
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+void vtkpxRPMCorrespondenceFinder::FormDistanceMatrixFast(vtkpxAbstractMatrix* M,vtkpxMatrix* VX,vtkpxMatrix* Y,
+							  float T,vtkPointLocator* locator,
+							  vtkpxMatrix* LX,vtkpxMatrix* LY)
+{
+  int size[2];
+  M->GetSize(size);
+  M->Zero();
+
+  int total=0;
+  //  float minvalue=0.00000001;
+
+  float trueThreshold=T*this->FastThreshold;
+  if (trueThreshold<0.15)
+    trueThreshold=0.15;
+
+
+
+  int dolabels=0;
+  int numattributes=1;
+
+  float* labelx=NULL;
+  float* labely=NULL;
+
+
+  if (LX!=NULL && LY!=NULL)
+    {
+      if (this->UseLabels>0)
+	{
+	  dolabels=1;
+	}
+      else if (this->UseAttributes>0)
+	{
+	  dolabels=2;
+	  numattributes=LX->GetSize()[1];
+	}
+    }
+
+
+
+  if (dolabels>0)
+    {
+      labelx=new float[numattributes+5];
+      labely=new float[numattributes+5];
+    }
+  else
+    {
+      numattributes=0;
+    }
+	
+
+  double p1[3],p2[3];
+  for (int k=0;k<=2;k++)
+    {
+      p1[k]=0.0;
+      p2[k]=0.0;
+    }
+      
+
+  if (this->ExtraDebug) 
+    fprintf(stderr,"Forming Fast Distance Matrix %dx%d %.3f (%.3f) ... labels=%d (numattr=%d)\n",size[0],size[1],
+	    trueThreshold,T*this->FastThreshold,dolabels,numattributes);
+  
+  vtkIdList* idlist=vtkIdList::New();
+  //int count1=0,count2=0;
+  float T2=2.0*T*T;
+  for (int row=0;row<size[0];row++)
+    {
+      for (int ia=0;ia<3;ia++)
+	p1[ia]=VX->GetDirectElement(row,ia);
+      
+      if (dolabels==1)
+	{
+	  labelx[0]=(int)LX->GetDirectElement(row,0);
+	}
+      else if (dolabels==2)
+	{
+	  for (int j=0;j<numattributes;j++)
+	    labelx[j]=LX->GetDirectElement(row,j);
+	}
+      locator->FindPointsWithinRadius(trueThreshold,p1,idlist);
+      int np=idlist->GetNumberOfIds();
+
+      if (np<3)
+	{
+	  locator->FindClosestNPoints(3,p1,idlist);
+	  np=idlist->GetNumberOfIds();
+
+	}
+      
+      total+=np;
+      double sum=0.0;
+
+      for (int j=0;j<np;j++)
+	{
+	  int column=idlist->GetId(j);
+	  float adddist=0.0;
+
+	  if (dolabels==1)
+	    {
+	      labely[0]=(int)LY->GetDirectElement(column,0);
+	    }
+	  else if (dolabels==2)
+	    {
+	      for (int j=0;j<numattributes;j++)
+		{
+		  labely[j]=LY->GetDirectElement(column,j);
+		  adddist+=pow(labelx[j]-labely[j],float(2.0));
+		}
+	      adddist=this->AttributesWeight * adddist;
+	    }
+
+	  if (dolabels!=1 || labelx[0]==labely[0])
+	    {
+	      p2[2]=0.0;
+	      for (int ib=0;ib<3;ib++)
+		p2[ib]=Y->GetDirectElement(column,ib);
+	      
+	      float dist= vtkMath::Distance2BetweenPoints(p1, p2) + adddist;
+	      float m=exp(-dist/T2);//+(vtkpxMath::GaussianRandom()*0.001/float(size[0]));
+	      sum+=m;
+	      if (m>0.0)
+		M->SetDirectElement(row,column,m);
+	      else
+		M->SetDirectElement(row,column,0.0);
+	    }
+	}
+
+      if (sum<0.0001)
+	{
+	  int id=locator->FindClosestPoint(p1);
+	  //	  fprintf(stderr,"Adding 0.001 at %d %d\n",row,id);
+	  M->SetDirectElement(row,id,0.0001);
+	}
+    }
+
+
+  if (labelx!=NULL)
+    delete [] labelx;
+  if (labely!=NULL)
+    delete [] labely;
+
+  if (this->ExtraDebug) 
+    fprintf(stderr,"%d done \n",total/size[0]);
+}
+
+
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+vtkPoints* vtkpxRPMCorrespondenceFinder::CreatePointsFromMatrix(vtkpxMatrix* Y,int sample)
+{
+  int size[2];
+  Y->GetSize(size);
+  
+  sample=Irange(sample,1,10);
+
+  int nump=size[0]/sample;
+
+  vtkPoints* pt=vtkPoints::New();
+  pt->SetNumberOfPoints(nump);
+
+  int i;
+
+  for (i=0;i<nump;i++)
+    {
+      int index=i*sample;
+      pt->SetPoint(i,Y->GetDirectElement(index,0),Y->GetDirectElement(index,1),Y->GetDirectElement(index,2));
+    }
+
+  
+  return pt;
+
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+vtkpxMatrix* vtkpxRPMCorrespondenceFinder::CreateMatrixFromPoints(vtkPoints* pts)
+{
+  int nump=pts->GetNumberOfPoints();
+
+  vtkpxMatrix* Y=vtkpxMatrix::New();
+  Y->Zeros(nump,4);
+  double p[3];
+
+  for (int i=0;i<nump;i++)
+    {
+      pts->GetPoint(i,p);
+      for (int ia=0;ia<=2;ia++)
+	Y->SetDirectElement(i,ia,p[ia]);
+      Y->SetElement(i,3,1);
+    }
+
+  return Y;
+
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+vtkPointLocator* vtkpxRPMCorrespondenceFinder::CreateLocator(vtkpxMatrix* Y,int pointsperbucket)
+{
+  vtkPointLocator* locator=vtkPointLocator::New();
+  locator->SetNumberOfPointsPerBucket(1);
+  vtkPoints* pt=this->CreatePointsFromMatrix(Y);
+  double bounds[6];
+  pt->GetBounds(bounds);
+
+  vtkPolyData* poly=vtkPolyData::New();
+  poly->SetPoints(pt);
+
+  locator->SetDataSet(poly);
+  locator->BuildLocator();
+  pt->Delete();
+  poly->Delete();
+
+  int dat[3];
+  locator->GetDivisions(dat);
+  if (this->ExtraDebug) 
+    fprintf(stderr,"Locator number of buckets = %d (%d,%d,%d)\n",locator->GetNumberOfPointsPerBucket(),dat[0],dat[1],dat[2]);
+	  
+
+  return locator;
+}
+
+void vtkpxRPMCorrespondenceFinder::ZeroArray(int num,float *x)
+{
+  for (int i=0;i<num;i++)
+    x[i]=0.0;
+}
+
+void vtkpxRPMCorrespondenceFinder::ZeroArray(int num,double *x)
+{
+  for (int i=0;i<num;i++)
+    x[i]=0.0;
+}
+
+//----------------------------------------------------------------------------
+// Higher Level Procedures 
+//----------------------------------------------------------------------------
+void vtkpxRPMCorrespondenceFinder::UpdateCorrespondence(vtkpxAbstractMatrix* m,
+							vtkpxMatrix* m_outliers_row,vtkpxMatrix* m_outliers_column,
+							vtkpxMatrix* vx,vtkpxMatrix* y,vtkpxMatrix* vy,
+							float T,vtkPointLocator* locator,
+							vtkpxMatrix* lx,vtkpxMatrix* ly)
+{
+  if (this->ExtraDebug)
+    m->DebugOn();
+
+  char line[30];
+
+  this->SetOutliers(m_outliers_row,m_outliers_column,T);
+
+
+  switch (MatchMode)
+    {
+    case 0:
+      this->MapPointsICP(vx,y,vy, locator);
+      sprintf(line,"ICP");
+      break;
+    case 1:
+      this->FormDistanceMatrix(m,vx,y,T,lx,ly);
+      sprintf(line,"Dense");
+      m->NormalizeMixtureMatrix(m_outliers_row);
+      m->MapPoints(y,vy);
+      break;
+    case 2:
+      this->FormDistanceMatrix(m,vx,y,T,lx,ly);
+      sprintf(line,"Dense");
+      m->NormalizeRPMMatrix(m_outliers_row,m_outliers_column);
+      m->MapPoints(y,vy);
+      break;
+    case 3:
+      this->FormDistanceMatrixFast(m,vx,y,T,locator,lx,ly);
+      sprintf(line,"Fast");
+      m->NormalizeMixtureMatrix(m_outliers_row);
+      m->MapPoints(y,vy);
+      break;
+    case 4:
+      this->FormDistanceMatrixFast(m,vx,y,T,locator,lx,ly);
+      sprintf(line,"Fast");
+      m->NormalizeRPMMatrix(m_outliers_row,m_outliers_column);
+      m->MapPoints(y,vy);
+      break;
+    case 5:
+      this->MapPointsICPPlus(vx,y,vy,T, locator);
+      sprintf(line,"ICPP");
+      break;
+    }
+
+  vtkDebugMacro(<<line << " Match Matrix Formed : Density = " << m->Density());
+
+  this->TransformOutlierColumnToWeights(m_outliers_column,this->MatchMode,this->UseWeightedLeastSquares);
+
+  if (m_outliers_column!=NULL && ( this->MatchMode==2 || this->MatchMode==4) )
+    {
+      int dolabels=0;
+      if (lx!=NULL && this->UseLabels>0)
+	dolabels=1;
+
+      float lab[50][2],sumlab[50];
+      int numlab[50];
+      for (int cnt=0;cnt<50;cnt++)
+	{
+	  lab[cnt][0]=1000.0;
+	  lab[cnt][1]=0.0;
+	  sumlab[cnt]=0.0;
+	  numlab[cnt]=0;
+	}
+      
+      float range[2];
+      float v=m_outliers_column->GetDirectElement(0,0);
+      range[0]=range[1]=v;
+      int np=m_outliers_column->GetSize()[0];
+      for (int i=0;i<np;i++)
+	{
+	  float v=m_outliers_column->GetElement(i,0);
+	  range[0]=Fmin(range[0],v);
+	  range[1]=Fmax(range[1],v);
+	  if (dolabels)
+	    {
+	      int lv=(int)lx->GetElement(i,0);
+	      if (lv<50 && lv>=0)
+		{		      
+		  sumlab[lv]+=v;
+		  numlab[lv]+=1;
+		  lab[lv][0]=Fmin(v,lab[lv][0]);
+		  lab[lv][1]=Fmax(v,lab[lv][1]);
+		}
+	    }
+	}
+      fprintf(stderr,"Outlier Range=%.2f %.2f\n",range[0],range[1]);
+      {   
+	for (int cnt=0;cnt<50;cnt++)
+	  {
+	    if (lab[cnt][0]!=1000.0 || lab[cnt][1]!=0.0)
+	      {
+		fprintf(stderr,"Label %d range = %.2f:%.2f  num=%d mean=%.2f\n",cnt,
+			lab[cnt][0],lab[cnt][1],
+			numlab[cnt],sumlab[cnt]/float(numlab[cnt]));
+	      }
+	  }
+      }
+      fprintf(stderr,"\n");
+    }
+  
+  if (this->ExtraDebug)
+    m->DebugOff();
+
+}
+//----------------------------------------------------------------------------
+// Description:
+// Annealing Helper Procedures
+//----------------------------------------------------------------------------
+void vtkpxRPMCorrespondenceFinder::SamplePoints(vtkpxMatrix* X,vtkpxMatrix* Y,vtkpxMatrix* LX,vtkpxMatrix* LY,int numlandmarks,
+						     int preferentialsampling)
+{
+  if (numlandmarks==-1)
+    numlandmarks=this->MaximumNumberOfLandmarks;
+
+  if (this->ExtraDebug)
+    fprintf(stderr,"Sample Only numlandmarks=%d %d Preferential=%d, Use Attributes=%d UseLabels=%d\n",numlandmarks,this->MaximumNumberOfLandmarks,
+	    preferentialsampling,this->UseAttributes,this->UseLabels);
+
+  if (this->UseAttributes==1)
+    this->UseLabels=0;
+
+  int stepx = 1,stepy=1;
+  int nump_x,nump_y;
+
+  int numattributes=0;
+
+  if ( (this->UseLabels>0 || this->UseAttributes>0) && LX!=NULL && LY!=NULL)
+    {
+      if (Source->GetPointData()!=NULL && Target->GetPointData()!=NULL)
+	{
+	  if (Source->GetPointData()->GetScalars()!=NULL  && Target->GetPointData()->GetScalars()!=NULL)
+	    {
+	      if ( (Source->GetPointData()->GetScalars()->GetNumberOfTuples()==Source->GetNumberOfPoints()) &&
+		   (Target->GetPointData()->GetScalars()->GetNumberOfTuples()==Target->GetNumberOfPoints()) )
+		numattributes=1;
+	      else
+		this->UseLabels=0;
+	      
+	      if (numattributes>0 && this->UseAttributes==1)
+		{
+		  numattributes=Source->GetPointData()->GetScalars()->GetNumberOfComponents();
+		  if (numattributes>Target->GetPointData()->GetScalars()->GetNumberOfComponents())
+		    numattributes=Target->GetPointData()->GetScalars()->GetNumberOfComponents();
+		}
+	    }
+	}
+      else
+	{
+	  this->UseLabels=0;
+	}
+    }
+  else
+    {
+      this->UseLabels=0;
+    }
+
+      
+
+  int maxlan=Imax(Source->GetNumberOfPoints(),Target->GetNumberOfPoints());
+
+  if (maxlan > numlandmarks)
+    {
+      stepx = this->Source->GetNumberOfPoints() / numlandmarks;
+      if (stepx<1)
+	stepx=1;
+      nump_x=this->Source->GetNumberOfPoints()/stepx;
+
+      stepy = this->Target->GetNumberOfPoints() / numlandmarks;
+      if (stepy<1)
+	stepy=1;
+      nump_y=this->Target->GetNumberOfPoints()/stepy;
+    }
+  else 
+    {
+      stepx=1;
+      stepy=1;
+      nump_x=this->Source->GetNumberOfPoints();
+      nump_y=this->Target->GetNumberOfPoints();
+    }
+
+
+  X->Zeros(nump_x,4);
+  Y->Zeros(nump_y,4);
+
+  if (numattributes>0)
+    {
+      LX->Zeros(nump_x,numattributes);
+      LY->Zeros(nump_y,numattributes);
+    }
+  else
+    this->UseLabels=0;
+
+  int done=0;
+
+  if (numattributes==1  && this->UseLabels==1 && preferentialsampling==1)
+    {
+      done=DoPreferentialSampling(this->Source,X,LX,nump_x);
+      if (done>0)
+	done=DoPreferentialSampling(this->Target,Y,LY,nump_y);
+    }
+
+  if (done==0)
+    {
+      if (this->ExtraDebug)
+	fprintf(stderr,"Doing Straight Sampling\n");
+      DoStraightSampling(this->Source,X,LX,nump_x,stepx,(numattributes>0));
+      DoStraightSampling(this->Target,Y,LY,nump_y,stepy,(numattributes>0));
+    }
+}
+
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+// Sampling Stats
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+
+void vtkpxRPMCorrespondenceFinder::DoStraightSampling(vtkPolyData* surface,vtkpxMatrix* X,vtkpxMatrix* LX,int nump,int step,int dolabels)
+{
+  double tpt[3];
+  int numattributes=LX->GetSize()[1];
+
+  for (int i=0;i<nump;i++)
+    {
+      surface->GetPoint(i*step,tpt);
+
+      for (int ia=0;ia<3;ia++)
+	X->SetElement(i,ia,tpt[ia]);
+      X->SetElement(i,3,1.0);
+      if (dolabels)
+	{
+	  for (int j=0;j<numattributes;j++)
+	    LX->SetElement(i,j,surface->GetPointData()->GetScalars()->GetComponent(i*step,j));
+	}
+    }
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+int vtkpxRPMCorrespondenceFinder::DoPreferentialSampling(vtkPolyData* surface,vtkpxMatrix* X,vtkpxMatrix* LX,int nump)
+{
+  if (this->ExtraDebug)
+    fprintf(stderr,"In Do Preferential Sampling nump=%d\n",nump);
+
+
+  vtkDataArray* in_labels=surface->GetPointData()->GetScalars();
+  int numlab=in_labels->GetNumberOfTuples();
+  double range[2]; in_labels->GetRange(range);
+
+  int upper=0,flag=0;
+  while (upper<numlab && flag==0)
+    {
+      if ( fabs(in_labels->GetComponent(upper,0)-range[0])<0.01)
+	++upper;
+      else
+	flag=1;
+    }
+
+  if (flag==0)
+    {
+      if (this->ExtraDebug)
+	fprintf(stderr,"No Second Labels Found in Preferential Sampling\n");
+      return 0;
+    }
+
+
+  int numupper=numlab-upper;
+  int numlower=nump-numupper;
+
+
+  if (numlower<0)
+    {
+      if (this->ExtraDebug)
+	fprintf(stderr,"Not enough points found for Preferential Sampling upper=%d numlab=%d numlower=%d numupper=%d nump=%d\n",
+		upper,numlab,numlower,numupper,nump);
+      return 0;
+    }
+
+  
+  int step=int(upper/numlower);
+  if (step<1)
+    step=1;
+  numlower=upper/step;
+
+  int newnump=numlower+numupper;
+  if (newnump!=nump)
+    {
+      nump=newnump;
+      X->Zeros(nump,4);
+      LX->Zeros(nump,1);
+    }
+
+  double tpt[3];
+  int numcomp=LX->GetSize()[1];
+  for (int i=0;i<numlower;i++)
+    {
+      surface->GetPoint(i*step,tpt);
+      for (int ia=0;ia<3;ia++)
+	X->SetElement(i,ia,tpt[ia]);
+      X->SetElement(i,3,1.0);
+      for (int j=0;j<numcomp;j++)
+	LX->SetElement(i,j,surface->GetPointData()->GetScalars()->GetComponent(i*step,j));
+    }
+  for (int j=numlower;j<nump;j++)
+    {
+      surface->GetPoint(upper+(j-numlower),tpt);
+      for (int ia=0;ia<3;ia++)
+	X->SetElement(j,ia,tpt[ia]);
+      X->SetElement(j,3,1.0);
+      for (int jj=0;jj<numcomp;jj++)
+	LX->SetElement(j,jj,surface->GetPointData()->GetScalars()->GetComponent(upper+(j-numlower),jj));
+    }
+
+  if (this->ExtraDebug)
+    fprintf(stderr,"Preferential Sampling : Input: out=%d tot=%d per=%.1f \t  Output: out=%d tot=%d per=%.1f\n",
+	    upper,numlab,float(100.0*upper)/float(numlab),
+	    numlower,nump,float(100.0*numlower)/float(nump));
+
+  return 1;
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+void vtkpxRPMCorrespondenceFinder::InitMatchMatrices(vtkpxAbstractMatrix* M,vtkpxMatrix* M_Outliers_Row,
+						     vtkpxMatrix* M_Outliers_Column,
+						     int nump_x,int nump_y)
+{
+  M->Zeros(nump_x,nump_y);
+  M_Outliers_Row->Zeros(1,nump_y);
+  M_Outliers_Column->Zeros(nump_x,1);
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+float vtkpxRPMCorrespondenceFinder::SetOutliers(vtkpxMatrix* M_Outliers_Row,vtkpxMatrix* M_Outliers_Column,float T)
+{
+  int size[2];  M_Outliers_Column->GetSize(size);
+  float moutlier=0.01;
+  M_Outliers_Row->Fill(moutlier);
+  if (this->MatchMode==2 || this->MatchMode==4 || this->MatchMode==7)
+    M_Outliers_Column->Fill(moutlier);
+  if (this->ExtraDebug)
+    fprintf(stderr,"Moutlier=%f (Temperature=%.5f)\n",moutlier,T);
+  
+  return moutlier;
+}
+
+vtkpxAbstractMatrix* vtkpxRPMCorrespondenceFinder::AllocateMatchMatrix(int dense)
+{
+  if (dense==1 || (dense==-1 &&  (this->MatchMode==1 || this->MatchMode==2)))
+    {
+      return vtkpxMatrix::New();
+    }
+
+  return vtkpxSparseMatrix::New();
+}
+
+void vtkpxRPMCorrespondenceFinder::TransformOutlierColumnToWeights(vtkpxMatrix* M_Outliers_Column,int Mode,int UseWLS)
+{
+  if ( UseWLS>0 && (Mode==2 || Mode==4 || Mode==6 || Mode==7) )
+    {
+      M_Outliers_Column->ScaleAdd(-1.0,1.0);
+
+      float med=M_Outliers_Column->Median();
+      if (med<0.001)
+	{
+	  float s=float(M_Outliers_Column->GetSize()[0])/M_Outliers_Column->Sum();
+	  M_Outliers_Column->Scale(s);
+	}
+      else
+	{
+	  fprintf(stderr,"Median Scaling median=%.3f\n",med);
+	  M_Outliers_Column->Scale(1.0/med);
+	}
+    }
+  else
+    {
+      M_Outliers_Column->Fill(1.0);
+    }
+  
+}
+
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+void vtkpxRPMCorrespondenceFinder::TransformPoints(vtkAbstractTransform* xform,vtkpxMatrix* X,vtkpxMatrix* VX)
+{
+  int size[2];
+  X->GetSize(size);
+  
+  double tx[3],ty[3];
+  for (int k=0;k<=2;k++)
+    tx[k]=0.0;
+  
+  for (int i=0;i<size[0];i++)
+    {
+      for (int ia=0;ia<3;ia++)
+	tx[ia]=X->GetDirectElement(i,ia);
+      
+      xform->TransformPoint(tx,ty);
+      for (int ib=0;ib<3;ib++)
+	VX->SetDirectElement(i,ib,ty[ib]);
+    }
+  
+}
+//----------------------------------------------------------------------------
+float vtkpxRPMCorrespondenceFinder::ComputeDistance()
+{
+ return this->ComputeDistance("");
+}
+
+float vtkpxRPMCorrespondenceFinder::ComputeDistance(const char* label)
+{
+  int dooutliers=0;
+  if  (this->M_Outliers_Column!=NULL && ( this->MatchMode==2 || this->MatchMode==4) )
+    dooutliers=1;
+
+  int dolabels=0;
+  if (this->LX!=NULL && this->UseLabels>0)
+    dolabels=1;
+
+  char line[150];
+  if (label!=NULL)
+    strncpy(line,label,150);
+  else
+    strcpy(line,"");
+  
+  vtkPointLocator* locator=vtkPointLocator::New();
+  locator->SetNumberOfPointsPerBucket(1);
+  locator->SetDataSet(this->Target);
+  locator->BuildLocator();
+  
+  float sumlab[50],numlab[50];
+  float sum=0,totaln=0.0;
+  
+  for (int cnt=0;cnt<50;cnt++)
+    {
+      sumlab[cnt]=0.0;
+      numlab[cnt]=0.0;
+    }
+  
+  int np=this->VX->GetSize()[0];
+  for (int i=0;i<np;i++)
+    {
+      double p4[5],p5[3];
+      this->VX->GetRow(i,3,&p4[0]);
+      int id=locator->FindClosestPoint(p4);
+      this->Target->GetPoints()->GetPoint(id,p5);
+      
+      float w=1.0;
+      if (dooutliers==1)
+	w=M_Outliers_Column->GetDirectElement(i,0);
+      float d=sqrt(vtkMath::Distance2BetweenPoints(p4,p5));
+
+      sum+=d*w;
+      totaln+=w;
+      if (dolabels)
+	{
+	  int lv=(int)this->LX->GetElement(i,0);
+	  if (lv<50 && lv>=0)
+	    {		      
+	      sumlab[lv]+=d*w;
+	      numlab[lv]+=w;
+	    }
+	  
+	}
+    }
+
+  {  for (int cnt=0;cnt<50;cnt++)
+    {
+      if (numlab[cnt]>0.01)
+	{
+	  fprintf(stdout,"EX \t %s \t Label %d  \t %8.5f \t %8.2f \n",line,cnt,
+		  sumlab[cnt]/(numlab[cnt]),numlab[cnt]);
+	}
+  }}
+  fprintf(stdout,"EX \t %s \t Overall \t %8.5f \t %8.2f \n",line,sum/(totaln),totaln);
+  fprintf(stdout,"\n");
+
+  this->AverageDistance = sum/(totaln);
+  fprintf(stdout,"Transformation = %s ",line);
+  fprintf(stdout,"Average distance between corresponding  points = %8.5f ",this->AverageDistance);
+  fprintf(stdout,"Number of points used to compute distance  = %8.2f \n", totaln);
+
+  locator->Delete();
+  return sum/totaln;
+
+      
+}
+
diff --git a/bioimagesuite30_src/Registration/vtkpxRPMCorrespondenceFinder.h b/bioimagesuite30_src/Registration/vtkpxRPMCorrespondenceFinder.h
new file mode 100644
index 0000000..4fcd25c
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxRPMCorrespondenceFinder.h
@@ -0,0 +1,346 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxRPMCorrespondenceFinder.h,v $
+  Language:  C++
+  Date:      $Date: 2003/11/13 20:02:03 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#ifndef __vtkpxRPMCorrespondenceFinder_h
+#define __vtkpxRPMCorrespondenceFinder_h
+
+#include "vtkTransform.h"
+#include "vtkProcessObject.h"
+#include "vtkCollection.h"
+#include "vtkpxMatrix.h"
+#include "vtkPoints.h"
+#include "vtkPointLocator.h"
+#include "vtkPolyData.h"
+
+class vtkpxRPMCorrespondenceFinder : public vtkProcessObject
+{
+public:
+  static vtkpxRPMCorrespondenceFinder *New();
+  vtkTypeMacro(vtkpxRPMCorrespondenceFinder,vtkProcessObject);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Set the current Temperature
+  vtkSetClampMacro(Temperature,float,0.0,2000.0);
+  vtkGetMacro(Temperature,float);
+
+  // Description:
+  // Initialize by allocating Memory etc
+  virtual void Initialize(vtkAbstractTransform* OffsetTransform);
+  virtual void Initialize() { this->Initialize(NULL); }
+
+  // Description:
+  // Warp and Update Correspondence
+  virtual void WarpAndUpdateCorrespondence(vtkAbstractTransform* warpTransform,
+					   float temperature);
+  virtual float ComputeDistance(const char* label);
+  virtual float ComputeDistance();
+
+  // Description:
+  // Access Certain Internal Stuff
+  vtkGetObjectMacro(PointsX, vtkPoints);
+  vtkGetObjectMacro(PointsVY, vtkPoints);
+  vtkGetObjectMacro(M_Outliers_Column, vtkpxMatrix);
+  vtkGetObjectMacro(Collection,vtkCollection);
+  
+
+  // Description:
+  // Specify the source and target data sets.
+  void SetSource(vtkPolyData *source);
+  void SetTarget(vtkPolyData *target);
+  vtkGetObjectMacro(Source, vtkPolyData);
+  vtkGetObjectMacro(Target, vtkPolyData);
+
+  // Description:
+  // Specify the initial transformation
+  vtkSetObjectMacro(InitialTransform,vtkAbstractTransform);
+  vtkGetObjectMacro(InitialTransform,vtkAbstractTransform);
+
+  // Description: 
+  // Set/Get vertex step
+  vtkSetMacro(MaximumNumberOfLandmarks, int);
+  vtkGetMacro(MaximumNumberOfLandmarks, int);
+
+  // Description:
+  // Extra Debug
+  vtkSetClampMacro(ExtraDebug,int,0,1);
+  vtkGetMacro(ExtraDebug,int);
+
+  // Description:
+  // Set the current mode 0=ICP, 1=RPM-Mixture 2=RPM 3=RPM-Mixture-Fast 4=RPM Fast 5=ICP-Plus
+  // 6=RPM-Mixture-Hybrid 7-RPM Hybrid
+  vtkSetClampMacro(MatchMode,int,0,5);
+  vtkGetMacro(MatchMode,int);
+
+  // Description:
+  // Dedicated Set/Get MatchMode stuff 
+  virtual void SetMatchModeToICP()          { this->SetMatchMode(0);}
+  virtual void SetMatchModeToMixture()      { this->SetMatchMode(1);}
+  virtual void SetMatchModeToRPM()          { this->SetMatchMode(2);}
+  virtual void SetMatchModeToMixtureFast()  { this->SetMatchMode(3);}
+  virtual void SetMatchModeToRPMFast()      { this->SetMatchMode(4);}
+  virtual void SetMatchModeToICPPlus()      { this->SetMatchMode(5);}
+
+  // Description: 
+  // UseLabels
+  vtkSetClampMacro(UseLabels, int,0,1);
+  vtkGetMacro(UseLabels, int);
+  vtkBooleanMacro(UseLabels, int);
+
+  // Description: 
+  // Use Attributes 
+  vtkSetClampMacro(UseAttributes, int,0,1);
+  vtkGetMacro(UseAttributes, int);
+  vtkBooleanMacro(UseAttributes, int);
+
+
+  // Description:
+  // Threshold for fast search
+  vtkSetMacro(AttributesWeight,float);
+  vtkGetMacro(AttributesWeight,float);
+
+  // Description: 
+  // UseLabels
+  vtkSetClampMacro(PreferentialSampling, int,0,1);
+  vtkGetMacro(PreferentialSampling, int);
+  vtkBooleanMacro(PreferentialSampling, int);
+
+  // Description: 
+  // UseWeightedLeastSquares
+  vtkSetClampMacro(UseWeightedLeastSquares, int,0,1);
+  vtkGetMacro(UseWeightedLeastSquares, int);
+  vtkBooleanMacro(UseWeightedLeastSquares, int);
+
+  // Description: 
+  // UseInitialTransform
+  vtkSetClampMacro(UseInitialTransform, int,0,1);
+  vtkGetMacro(UseInitialTransform, int);
+  vtkBooleanMacro(UseInitialTransform, int);
+
+  // Description: 
+  // MatchMatrixType
+  vtkSetClampMacro(MatchMatrixType, int,-1,1);
+  vtkGetMacro(MatchMatrixType, int);
+  vtkBooleanMacro(MatchMatrixType, int);
+  virtual void SetMatchMatrixTypeToAuto()          { this->SetMatchMatrixType(-1);}
+  virtual void SetMatchMatrixTypeToSparse()        { this->SetMatchMatrixType(0);}
+  virtual void SetMatchMatrixTypeToDense()         { this->SetMatchMatrixType(1);}
+
+  // Description:
+  // Threshold for fast search
+  vtkSetMacro(FastThreshold,float);
+  vtkGetMacro(FastThreshold,float);
+
+  // Description:
+  // Enable/Disable Update of Transformation in conjuction with UpdateProgress
+  vtkSetMacro(EnableFeedback,int);
+  vtkGetMacro(EnableFeedback,int);
+  vtkBooleanMacro(EnableFeedback, int);
+
+  // Description:
+  // Threshold for fast search
+  vtkGetMacro(AverageDistance,float);
+
+protected:
+  // Description:
+  
+  vtkpxRPMCorrespondenceFinder();
+  ~vtkpxRPMCorrespondenceFinder();
+  vtkpxRPMCorrespondenceFinder(const vtkpxRPMCorrespondenceFinder&) {};
+  void operator=(const vtkpxRPMCorrespondenceFinder&) {};
+
+  // Description:
+  // Current Temperature
+  float Temperature;
+
+  // Description:
+  // Internal Storage 
+  vtkpxAbstractMatrix* M;
+  vtkpxMatrix* M_Outliers_Row;
+  vtkpxMatrix* M_Outliers_Column;
+  vtkpxMatrix* X;
+  vtkpxMatrix* VX;
+  vtkpxMatrix* Y;
+  vtkpxMatrix* VY;
+  vtkpxMatrix* LX;
+  vtkpxMatrix* LY;                  
+  vtkPointLocator* Locator;
+  vtkCollection* Collection;
+  vtkPoints* PointsX;
+  vtkPoints* PointsVY;
+
+  // Description:
+  // Clean Up Stuff 
+  void cleanobject(vtkObject* f) {
+    if (f!=NULL)
+      f->Delete();
+  }
+
+  // Description:
+  // Clean Up Procedure
+  virtual void CleanUp();
+
+  // Description:
+  // Update pointsVY
+  virtual void UpdateVYPoints();
+
+  // Description:
+  // Release source and target
+  void ReleaseSource(void);
+  void ReleaseTarget(void);
+
+  vtkPolyData* Source;
+  vtkPolyData* Target;
+
+  int EnableFeedback;
+  int MaximumNumberOfIterations;
+  int MaximumNumberOfLandmarks;
+
+  // Progress/Update handling
+  vtkAbstractTransform* InitialTransform;
+
+  // Description:
+  // Parameters for Various Things
+
+  float FastThreshold;
+  int   UseLabels;
+  int   PreferentialSampling;
+  int   UseInitialTransform;
+  int   MatchMode;
+  int   ExtraDebug;
+  int   UseWeightedLeastSquares;
+  int   MatchMatrixType;
+  int   UseAttributes;
+  float AttributesWeight;
+  float AverageDistance;
+
+  // -----------------------------------------------------------
+  // Setup Routines, utility stuff
+  // -----------------------------------------------------------
+  // Description:
+  // Sample and Scale points appropriately 
+  virtual void  SamplePoints(vtkpxMatrix* X,vtkpxMatrix* Y,
+			     vtkpxMatrix* LX=NULL,vtkpxMatrix* LY=NULL,int numlandmarks=-1,int sampleonlyfirstlabel=0);
+  virtual void  DoStraightSampling(vtkPolyData* surface,vtkpxMatrix* X,vtkpxMatrix* LX,int nump,int step,int dolabels);
+  virtual int   DoPreferentialSampling(vtkPolyData* surface,vtkpxMatrix* X,vtkpxMatrix* LX,int nump);
+
+
+  void ZeroArray(int num,float *x);
+  void ZeroArray(int num,double *x);
+
+  // Create Points from Matrix and vice-versa
+  virtual vtkPoints*   CreatePointsFromMatrix(vtkpxMatrix* X,int sample=1);
+  virtual vtkpxMatrix* CreateMatrixFromPoints(vtkPoints* pts);
+
+  // Description:
+  // Initialize Labels and Match Matrices 
+  void InitMatchMatrices(vtkpxAbstractMatrix* M,vtkpxMatrix* M_Outlier_Row,vtkpxMatrix* M_Outlier_Column,
+			 int rows,int cols);
+
+
+  // -------------------------------------------------------------
+  // Correspondence Stuff
+  // -------------------------------------------------------------
+
+  // Description:
+  // Update Correspondence
+  virtual void UpdateCorrespondence(vtkpxAbstractMatrix* m,
+				    vtkpxMatrix* m_outliers_row,vtkpxMatrix* m_outliers_column,
+				    vtkpxMatrix* vx,vtkpxMatrix* y,vtkpxMatrix* vy,
+				    float T,vtkPointLocator* locator,
+				    vtkpxMatrix* lx,vtkpxMatrix* ly);
+
+
+  // Description:
+  // Routines for Estimating correspondence in one-shot, no distance matrix involved
+  virtual void MapPointsICP(vtkpxMatrix* vx,vtkpxMatrix* y,vtkpxMatrix* vy,vtkPointLocator* locator);
+  virtual void MapPointsICPPlus(vtkpxMatrix* vx,vtkpxMatrix* y,vtkpxMatrix* vy,float T,vtkPointLocator* locator);
+  
+  // Description:
+  // Routines to estimate distance matrices 
+  
+  virtual void FormDistanceMatrix(vtkpxAbstractMatrix* M,vtkpxMatrix* vx,vtkpxMatrix* y,float T,
+				  vtkpxMatrix* LX,vtkpxMatrix* LY);
+  virtual void FormDistanceMatrixFast(vtkpxAbstractMatrix* M,vtkpxMatrix* vx,vtkpxMatrix* y,
+				      float T,vtkPointLocator* locator,
+				      vtkpxMatrix* LX,vtkpxMatrix* LY);
+
+  // Description:
+  // Allocate the Match Matrix
+  virtual vtkpxAbstractMatrix* AllocateMatchMatrix(int dense=-1);
+  
+
+  // Description:
+  // Create Point Locator
+  virtual vtkPointLocator* CreateLocator(vtkpxMatrix* Y,int pointsperbucket=2);
+  
+
+  // Description:
+  // Routine for warping  points using the transformation 
+  virtual void TransformPoints(vtkAbstractTransform* xform,
+			       vtkpxMatrix* x,vtkpxMatrix* vx);
+
+
+  // Description:
+  // Outlier Initialization and Transformation To Weights
+  float SetOutliers(vtkpxMatrix* M_Outlier_Row,vtkpxMatrix* M_Outlier_Column,float T);
+  void  TransformOutlierColumnToWeights(vtkpxMatrix* M_Outliers_Column,int Mode,int UseWLS);
+
+  
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxRegistration.cpp b/bioimagesuite30_src/Registration/vtkpxRegistration.cpp
new file mode 100644
index 0000000..4f98200
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxRegistration.cpp
@@ -0,0 +1,2134 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+
+// vtk includes
+#include "pxutil.h"
+#include "vtkImageData.h"
+#include "vtkImageCast.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkbisImageResample.h"
+#include "vtkbisImageReslice.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxRegistration.h"
+#include "vtkMath.h"
+#include "vtkpxMath.h"
+#include "vtkLandmarkTransform.h"
+#include "vtkpxUtil.h"
+#include "vtkTransform.h"
+#include "vtkImageShiftScale.h"
+#include "vtkPoints.h"
+#include "vtkpxComboTransform.h"
+#include "vtkpxUtil.h"
+#include "vtkpxImageNormalizeIntensityToReference.h"
+#include "vtkpxLinearTransform.h"
+#include "vtkpxLinearRegistration.h"
+#include "vtkImageGaussianSource.h"
+#include "vtkPolyData.h"
+#include "vtkTransformPolyDataFilter.h"
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkTriangleFilter.h"
+#include "vtkFloatArray.h"
+//#include "vtkIdType.h"
+#include "vtkCellDataToPointData.h"
+#include "vtkpxSurfaceUtil.h"
+#include "vtkInformation.h"
+
+
+
+vtkpxRegistration* vtkpxRegistration::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxRegistration");
+  if(ret)
+    {
+      return (vtkpxRegistration*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxRegistration;
+}
+
+
+vtkpxRegistration::vtkpxRegistration()
+{
+}
+
+vtkpxRegistration::~vtkpxRegistration()
+{
+}
+
+
+//----------------------------------------------------------------------------
+int vtkpxRegistration::ExtractComponentAndCastImageToShort(vtkImageData* destination,vtkImageData* source,
+							   int frame,int doscale)
+{
+  if (destination==NULL || source==NULL)
+    return 0;
+
+  double range[2];
+
+  vtkImageData* newsource=NULL;
+  int donewsource=1;
+
+  if (source->GetNumberOfScalarComponents()>1)
+    {
+      int fr=Irange(frame,0,source->GetNumberOfScalarComponents()-1);
+      vtkImageExtractComponents* extr=vtkImageExtractComponents::New();
+      
+      extr->SetInput(source);
+      extr->SetComponents(fr);
+      fprintf(stderr," ************ Extracting frame %d\n",fr);
+      extr->Update();
+      newsource=vtkImageData::New();
+      newsource->ShallowCopy(extr->GetOutput());
+      donewsource=1;
+      extr->Delete();
+    }
+  else
+    {
+      newsource=source;
+      donewsource=0;
+    }
+  
+  newsource->GetPointData()->GetScalars()->GetRange(range);
+  //  fprintf(stderr,"extracting component %d scale=%d range=%.2f:%.2f\n",frame,doscale,range[0],range[1]);
+  
+  if (  (range[1]-range[0]<32.0) ||  source->GetScalarType() != VTK_SHORT || range[1]>32767.0 || range[2]<-32767.0)
+    {
+      double scale=1.0,shift=0.0;
+      vtkImageCast* cast2=vtkImageCast::New();
+
+      if ((range[1]-range[0]<32.0) && doscale==1)
+	{
+	  scale=100.0;
+	}
+      else if ((range[1]>32760.0 || range[0]<-32767.0))
+	{
+	  shift=-range[0];
+	  scale=30000.0/(range[1]-range[0]);
+	}
+	
+      //      fprintf(stderr,"Here shift=%.5f, scale=%.5f\n",shift,scale);
+
+      if (scale!=1.0 || shift!=0.0)
+	{
+	  fprintf(stderr,"\t Scaling Intensity=%.4f,%.4f\n",scale,shift);
+	  vtkImageShiftScale* cast=vtkImageShiftScale::New();
+	  cast->SetInput(newsource);
+	  cast->SetShift(shift);
+	  cast->SetScale(scale);
+	  cast->SetOutputScalarTypeToFloat();
+	  cast->Update();
+	  cast2->SetInput(cast->GetOutput());
+	  cast->Delete();
+	}
+      else
+	{
+	  //  fprintf(stderr,"Simply Casting\n");
+	  cast2->SetInput(source);
+	}
+      cast2->SetOutputScalarTypeToShort();
+      cast2->Update();
+      destination->ShallowCopy(cast2->GetOutput());
+      cast2->Delete();
+    }
+  else
+    {
+      destination->ShallowCopy(newsource);
+    }
+  
+  if (donewsource!=0)
+    newsource->Delete();
+
+  destination->GetPointData()->GetScalars()->GetRange(range);
+  
+
+  if (destination->GetScalarType() !=VTK_SHORT) 
+    {
+      cerr << "Trouble in casting ::: vtkpxRegistration supports SHORT images only! \n";
+    }
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+//-------------------------------------------------------------------------
+int vtkpxRegistration::CalculateNumberOfBinsAndAdjustImage(vtkImageData *image, int maxbin,
+							   short& minv,short& maxv,int logmode,
+							   int posmode,int autonorm)
+{
+  if (image->GetScalarType() != VTK_SHORT && image->GetScalarType() != VTK_UNSIGNED_CHAR) 
+    {
+      cerr << "vtkpxRegistration supports SHORT or UNSIGNED CHAR images only! \n";
+      return 0;
+    }
+
+  
+
+  vtkpxRegistration::CalculateRange(image,minv,maxv,autonorm);
+  return vtkpxRegistration::AdjustImage(image,maxbin,minv,maxv,logmode,posmode,autonorm);
+
+}
+//------------------------------------------------------------------------- 
+int vtkpxRegistration::CalculateNumberOfBinsAndAdjustImages(vtkImageData *image1,vtkImageData* image2, 
+							    int maxbin,
+							    short& minv,short& maxv,
+							    int logmode,int posmode,int autonorm)
+{
+  int ok=0;
+
+  if ( (image1->GetScalarType() != image2->GetScalarType() ) ||
+       (image1->GetScalarType() != VTK_UNSIGNED_CHAR && image2->GetScalarType() != VTK_SHORT ) )
+    {
+      cerr << "vtkpxRegistration supports SHORT or UNSIGNED_CHAR images only! \n";
+      return 0;
+    }
+
+  short min_val1,min_val2,max_val1,max_val2;
+  vtkpxRegistration::CalculateRange(image1,min_val1,max_val1,autonorm);
+  vtkpxRegistration::CalculateRange(image2,min_val2,max_val2,autonorm);
+
+  minv=Imin(min_val1,min_val2);
+  maxv=Imax(max_val1,max_val2);
+
+  vtkpxRegistration::AdjustImage(image1,maxbin,minv,maxv,
+				 logmode,posmode,autonorm);
+
+  vtkpxRegistration::AdjustImage(image2,maxbin,minv,maxv,
+				 logmode,posmode,autonorm);
+
+  return 1;
+
+}
+
+
+int vtkpxRegistration::CalculateRange(vtkImageData* image, short& minv,short& maxv,int autonorm)
+{
+  if (autonorm)
+    {
+      float perlow=0.01,perhigh=0.99,tlow,thigh;
+      vtkpxUtil::ImageRobustRange(image,perlow,perhigh,tlow,thigh,256);
+      minv=int(tlow+0.5);
+      maxv=int(thigh+0.5);
+      return 1;
+    }
+
+  double r[2];
+  image->GetPointData()->GetScalars()->GetRange(r,0);
+
+  if (image->GetNumberOfScalarComponents()>0)
+    {
+      double t[2];
+      int nf=image->GetNumberOfScalarComponents();
+      for (int i=1;i<nf;i++)
+	{
+	  image->GetPointData()->GetScalars()->GetRange(t,i);
+	  if (t[0]<r[0])
+	    r[0]=t[0];
+	  if (t[1]>r[1])
+	    r[1]=t[1];
+	}
+    }
+     
+  minv=int(r[0]);
+  maxv=int(r[1]);
+      
+  return 1;
+}
+
+
+int vtkpxRegistration::AdjustImage(vtkImageData* image,int maxbin,
+				   short minv,short maxv,
+				   int logmode,int posmode,int autonorm)
+{
+  //  vtkpxRegistration::PrintImageInfo(image,"In Adjust Image");
+  // --------------------------------------------------------------------------
+  // Not Logarithm Mode
+  // --------------------------------------------------------------------------
+  
+  if (!logmode)
+    {
+      if (posmode && maxv>2 && minv<=0)
+	{
+	  minv=1;
+	}
+
+      int range = int(maxv - minv + 1);
+      int nbins = range;
+      int width = 1;
+      
+      // Calculate number of bins to use
+      if (maxbin > 0)
+	{
+	  while ((int)(ceil(range / (double)width)) > maxbin)
+	    width++;
+	  nbins = (int)(ceil(range/(double)width));    
+	}
+      
+
+      float scale=float(range)/float(nbins);
+      int  ns=image->GetPointData()->GetScalars()->GetNumberOfTuples()*image->GetPointData()->GetScalars()->GetNumberOfComponents();
+
+      if (image->GetScalarType()==VTK_SHORT)
+	{
+	  short *img = (short*) image->GetPointData()->GetScalars()->GetVoidPointer(0);
+	  
+	  for (int i=0;i<ns;i++)
+	    {
+	      float a=float(*img);
+	      int b=int((a-minv)/scale+0.5);
+	      if (b<0)
+		b=0;
+	      else if (b>=nbins)
+		b=nbins-1;
+	      *img=b;
+	      ++img;
+	    }
+	}
+      else
+	{
+	  unsigned char *img = (unsigned char*) image->GetPointData()->GetScalars()->GetVoidPointer(0);
+	  
+	  for (int i=0;i<ns;i++)
+	    {
+	      float a=float(*img);
+	      int b=int((a-minv)/scale+0.5);
+	      if (b<0)
+		b=0;
+	      else if (b>=nbins)
+		b=nbins-1;
+	      *img=b;
+	      ++img;
+	    }
+
+	}
+
+      //      vtkpxRegistration::PrintImageInfo(image,"Done Adjust Image");
+      return nbins;
+    }
+
+  // --------------------------------------------------------------------------
+  // Logarithm Mode
+  // --------------------------------------------------------------------------
+
+  float logrange=log(float(maxv-minv+1));
+  float scale=1.0;
+  if (logrange>0.01)
+    scale = float(maxbin-1)/logrange;
+      
+  minv=0;
+  maxv=(maxbin-1);
+
+  int  ns=image->GetPointData()->GetScalars()->GetNumberOfTuples()*image->GetPointData()->GetScalars()->GetNumberOfComponents();
+
+  if (image->GetScalarType()==VTK_SHORT)
+    {
+      short *img = (short*) image->GetPointData()->GetScalars()->GetVoidPointer(0);
+      float truemin=2000,truemax=-2000;
+      
+      for (int i=0;i<ns;i++)
+	{
+	  float inval=float(*img);
+	  float outval = log(inval-minv+1)*scale;
+	  *img=short(outval);
+	  truemin=Fmin(truemin,outval);
+	  truemax=Fmax(truemax,outval);
+	  ++img;
+	}
+    }
+  else
+    {
+      unsigned char* img = (unsigned char*) image->GetPointData()->GetScalars()->GetVoidPointer(0);
+      float truemin=2000,truemax=-2000;
+      
+      for (int i=0;i<ns;i++)
+	{
+	  float inval=float(*img);
+	  float outval = log(inval-minv+1)*scale;
+	  *img=short(outval);
+	  truemin=Fmin(truemin,outval);
+	  truemax=Fmax(truemax,outval);
+	  ++img;
+	}
+    }
+
+
+  return maxbin;
+
+}
+
+
+int vtkpxRegistration::ScaleWeightImage(vtkImageData* weightimage,vtkImageData* sampledimage,double maxvalue)
+{
+  if (weightimage==NULL || sampledimage==NULL)
+    return 0;
+
+  vtkImageExtractComponents* extr=vtkImageExtractComponents::New();
+  extr->SetInput(weightimage);
+  extr->SetComponents(0);
+  extr->Update();
+  
+  double range[2]; extr->GetOutput()->GetPointData()->GetScalars()->GetRange(range);
+  
+  if (maxvalue<10.0)
+    maxvalue=10.0;
+  if (maxvalue>100.0)
+    maxvalue=100.0;
+
+  if (range[1]<1.0)
+    range[1]=1.0;
+
+  double scalefactor=maxvalue/range[1];
+
+  vtkImageShiftScale* cast=vtkImageShiftScale::New();
+  cast->SetInput(extr->GetOutput());
+  extr->Delete();
+  cast->SetShift(0.0);
+  cast->SetScale(scalefactor);
+  cast->SetOutputScalarType(sampledimage->GetScalarType());
+  cast->Update();
+
+  weightimage->ShallowCopy(cast->GetOutput());
+  cast->Delete();
+  return 1;
+
+
+}
+//-------------------------------------------------------------------------
+int vtkpxRegistration::ResampleAndSmoothImage(vtkImageData* destination,
+					      vtkImageData* source,
+					      double baseresolution[3],
+					      float sigma,
+					      float res,int sameslices)
+{
+
+  if (source==NULL || destination==NULL)
+      return 0;
+
+  double sp[3];  source->GetSpacing(sp);
+  double ori[3]; source->GetOrigin(ori);
+  int dim[3];   source->GetDimensions(dim);
+
+
+
+  double gaussian[3],resolution[3];
+  for (int j=0;j<=2;j++)
+    {
+      gaussian[j]=sigma*baseresolution[j];
+      resolution[j]=baseresolution[j]*fabs(res);
+    }
+
+  // Step 1 Smooth 
+  double gp[3],sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+    {
+      gp[ia]=(gaussian[ia]/sp[ia]);
+      if (gp[ia]>2.0) 
+	gp[ia]=2.0;
+      sum+=gp[ia];
+    }
+
+  if (sameslices)
+    {
+      gp[2]=0.0;
+      resolution[2]=sp[2];
+    }
+
+  vtkbisImageResample* resamp=vtkbisImageResample::New();
+
+  int largeimage=0;
+ #ifdef _WIN32
+  if (dim[0]>256 || dim[1]>256 || dim[2]>256)
+    {
+      largeimage=1;
+      fprintf(stderr,"\t\t Large Image (windows) not smoothing\n");
+    }
+#endif
+  
+  if (sum>0.5 && largeimage==0)
+    {
+      vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+      smooth->SetInput(source);
+      smooth->SetStandardDeviations(gp);
+      smooth->Update();
+      resamp->SetInput(smooth->GetOutput());
+      smooth->Delete();
+    }
+  else
+    {
+      resamp->SetInput(source);
+    }
+
+  // Speed things up this is a hack anyway bspline will take over for <1
+  if (res<1.0)
+    resamp->InterpolateOff();
+  else
+    resamp->InterpolateOn();
+  resamp->SetDimensionality(3);
+  for (int ib=0;ib<=2;ib++)
+    resamp->SetAxisOutputSpacing(ib,resolution[ib]);
+  resamp->Update();
+
+  destination->ShallowCopy(resamp->GetOutput());
+  resamp->Delete();
+
+  return 1;
+}
+
+//-------------------------------------------------------------------------
+int vtkpxRegistration::ResliceImage(vtkImageData* destination,vtkImageData* source,vtkImageData* ref,
+				    vtkAbstractTransform* transform,
+				    int interp)
+{
+  if (destination==NULL || source==NULL || ref==NULL || transform==NULL)
+    return 0;
+
+  if (interp<0)
+    interp=-interp;
+
+  if (interp>=0)
+    {
+      if (interp<0 || interp>1)
+	interp=3;
+      vtkbisImageReslice* resl=vtkbisImageReslice::New(); resl->OptimizationOff();
+      
+      resl->SetInput(source);
+      resl->SetInformationInput(ref);
+      resl->SetResliceTransform(transform);
+      resl->SetInterpolationMode(interp);
+      resl->SetBackgroundLevel(-10.0);
+      resl->Update();
+      destination->ShallowCopy(resl->GetOutput());
+      resl->Delete();
+    }
+
+  return 1;
+}
+
+//-------------------------------------------------------------------------
+//-------------------------------------------------------------------------
+int vtkpxRegistration::MultiplyAndOverWriteImage(vtkImageData* inout,vtkImageData* scale)
+{
+  
+  int np1= inout->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int np2= scale->GetPointData()->GetScalars()->GetNumberOfTuples();
+
+  if (np1!=np2)
+    return 0;
+  
+  if (inout->GetScalarType()==VTK_SHORT && scale->GetScalarType()==VTK_SHORT)
+    {
+      short *img1 = (short*) inout->GetPointData()->GetScalars()->GetVoidPointer(0);
+      short *img2 = (short*) scale->GetPointData()->GetScalars()->GetVoidPointer(0);
+      for (int i=0;i<np1;i++)
+	{
+	  *img1 = ( *img1) * (*img2);
+	  ++img1;
+	  ++img2;
+	}
+    }
+  else
+    {
+      vtkDataArray* in1=inout->GetPointData()->GetScalars();
+      vtkDataArray* in2=scale->GetPointData()->GetScalars();
+      for (int i=0;i<np1;i++)
+	in1->SetComponent(i,0,in1->GetComponent(i,0)*in2->GetComponent(i,0));
+    }
+  return 1;
+}
+//-------------------------------------------------------------------------
+// Jacobian Stuff for visualization
+//-------------------------------------------------------------------------
+int vtkpxRegistration::ComputeJacobianImage(vtkImageData* ref,vtkImageData* jacobian,
+					    vtkAbstractTransform* tr)
+{
+  return vtkpxRegistration::ComputeJacobianImage(ref,jacobian,tr,1.0);
+}
+
+//-------------------------------------------------------------------------
+int vtkpxRegistration::ComputeSimpleJacobianImage(vtkImageData* ref,vtkImageData* jacobian,vtkAbstractTransform* tr,
+						  float scale,float offset)
+{
+  return vtkpxRegistration::ComputeSimpleJacobianImage(ref,jacobian,tr,scale,offset,0.0);
+}
+
+int vtkpxRegistration::ComputeSimpleJacobianImage(vtkImageData* ref,vtkImageData* jacobian,vtkAbstractTransform* tr,
+						  float scale,float offset,float threshold)
+{
+ if (ref==NULL || jacobian==NULL || tr==NULL)
+    return 0;
+
+  tr->Update();
+
+  int dim[3];  ref->GetDimensions(dim);
+  int dim2[3]; jacobian->GetDimensions(dim2);
+
+  double r[2]; ref->GetPointData()->GetScalars()->GetRange(r);
+
+  if (threshold<0.0)
+    threshold=0.0;
+  else if (threshold>1.0)
+    threshold=1.0;
+  double cutoff=r[0]+threshold*(r[1]-r[0]);
+  
+
+  if (dim[0]!=dim2[0] || dim[1]!=dim2[1] || dim[2]!=dim2[2] || 
+      jacobian->GetScalarType()!=VTK_FLOAT || 
+      jacobian->GetNumberOfScalarComponents()!=1)
+    {
+      jacobian->CopyStructure(ref);
+      jacobian->SetNumberOfScalarComponents(1);
+      jacobian->SetScalarTypeToFloat();
+      jacobian->AllocateScalars();
+    }
+
+  double sp[3];  ref->GetSpacing(sp);
+  double ori[3]; ref->GetOrigin(ori);
+  double der[3][3],x[3],x2[3];
+  
+  vtkDataArray* dat=jacobian->GetPointData()->GetScalars();
+  int index=0;
+
+  for (int k=0;k<dim[2];k++)
+    {
+      x[2]=k*sp[2]+ori[2];
+      for (int j=0;j<dim[1];j++)
+	{
+	  x[1]=j*sp[1]+ori[1];
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      x[0]=i*sp[0]+ori[0];
+
+	      double v=ref->GetScalarComponentAsDouble(i,j,k,0);
+	      if (v>=cutoff)
+		{
+		  tr->InternalTransformDerivative(x,x2,der);
+		  double det=vtkMath::Determinant3x3(der);
+		  dat->SetComponent(index,0,(det-offset)*scale);
+		}
+	      else
+		{
+		  dat->SetComponent(index,0,0.0);
+		}
+	      ++index;
+	    }
+	}
+    }
+  fprintf(stderr,"\t\t Offset = %.2f scale=%.2f cutoff=%.4f\n",offset,scale,cutoff);
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxRegistration::ComputeJacobianImage(vtkImageData* ref,vtkImageData* jacobian,
+					    vtkAbstractTransform* tr,float scale,float affine)
+{
+  return vtkpxRegistration::ComputeJacobianImage(ref,jacobian,tr,scale,affine,0.0);
+}
+
+int vtkpxRegistration::ComputeJacobianImage(vtkImageData* ref,vtkImageData* jacobian,
+					    vtkAbstractTransform* tr,float scale,float affine,float threshold)
+{
+  if (ref==NULL || jacobian==NULL || tr==NULL)
+    return 0;
+
+  tr->Update();
+
+  int dim[3];  ref->GetDimensions(dim);
+  int dim2[3]; jacobian->GetDimensions(dim2);
+
+
+  vtkpxGridTransform* grid=NULL;
+  vtkTransform* linear=NULL;
+  int numcomponents=2;
+  int minpass=0;
+
+  if ( tr->IsA("vtkpxComboTransform")==1)
+    {
+      linear=((vtkpxComboTransform*)tr)->GetLinearTransform();
+      float sum=0.0;
+      for (int i=0;i<=3;i++)
+	for (int j=0;j<=3;j++)
+	  {
+	    float a=linear->GetMatrix()->GetElement(i,j);
+	    float b=float(i==j);
+	    sum+=fabs(a-b);
+	  }
+
+      grid=((vtkpxComboTransform*)tr)->GetGridTransform();
+	  
+      if (sum>0.0)
+	{
+	  numcomponents=18;
+	  minpass=0;
+	}
+      else
+	{
+	  numcomponents=9;
+	  minpass=1;
+	}
+    }
+
+  if (dim[0]!=dim2[0] || dim[1]!=dim2[1] || dim[2]!=dim2[2] || 
+      jacobian->GetScalarType()!=VTK_FLOAT || 
+      jacobian->GetNumberOfScalarComponents()!=numcomponents)
+    {
+      jacobian->CopyStructure(ref);
+      jacobian->SetNumberOfScalarComponents(numcomponents);
+      jacobian->SetScalarTypeToFloat();
+      jacobian->AllocateScalars();
+    }
+
+  double sp[3];  ref->GetSpacing(sp);
+  double ori[3]; ref->GetOrigin(ori);
+  double der[3][3];
+  double x[3],x2[3],x3[3];
+  
+  vtkDataArray* dat=jacobian->GetPointData()->GetScalars();
+  int index=0;
+
+  for (int k=0;k<dim[2];k++)
+    {
+      x[2]=k*sp[2]+ori[2];
+      for (int j=0;j<dim[1];j++)
+	{
+	  x[1]=j*sp[1]+ori[1];
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      x[0]=i*sp[0]+ori[0];
+
+	      if (grid==NULL)
+		{
+		  tr->InternalTransformDerivative(x,x2,der);
+		  double det=vtkMath::Determinant3x3(der);
+		  double val=det/fabs(affine);
+		  dat->SetComponent(index,0,(det-1.0)*scale);
+		  dat->SetComponent(index,1,(val-1.0)*scale);
+		}
+	      else
+		{
+		  tr->InternalTransformDerivative(x,x2,der);
+		  int ind=0;
+		  for (int pass=minpass;pass<=1;pass++)
+		    {
+		      for (int ia=0;ia<=2;ia++)
+			for (int ib=0;ib<=2;ib++)
+			  {
+			    dat->SetComponent(index,ind,der[ia][ib]);
+			    ++ind;
+			  }
+		      
+		      if (pass<1)
+			{
+			  linear->TransformPoint(x,x2);
+			  grid->InternalTransformDerivative(x2,x3,der);
+			}
+		    }
+		}
+	      ++index;
+	    }
+	}
+    }
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxRegistration::ComputeCompleteJacobianImage(vtkImageData* ref,vtkImageData* jacobian,vtkpxComboTransform* tr,
+						    int nonlinearonly)
+{
+  if (ref==NULL || jacobian==NULL || tr==NULL)
+    return 0;
+
+  int dim[3];  ref->GetDimensions(dim);
+  int dim2[3]; jacobian->GetDimensions(dim2);
+
+  tr->Update();
+
+  vtkpxGridTransform* grid=tr->GetGridTransform();
+  vtkTransform* linear=tr->GetLinearTransform();
+  int nlfirst=tr->GetNonLinearFirst();
+  int numcomponents=6;
+  
+  if (dim[0]!=dim2[0] || dim[1]!=dim2[1] || dim[2]!=dim2[2] || 
+      jacobian->GetScalarType()!=VTK_FLOAT || 
+      jacobian->GetNumberOfScalarComponents()!=numcomponents)
+    {
+      jacobian->CopyStructure(ref);
+      jacobian->SetNumberOfScalarComponents(numcomponents);
+      jacobian->SetScalarTypeToFloat();
+      jacobian->AllocateScalars();
+    }
+
+  double sp[3];  ref->GetSpacing(sp);
+  double ori[3]; ref->GetOrigin(ori);
+  double der[3][3];
+  double x[3],x2[3],x3[3];
+  
+  vtkDataArray* dat=jacobian->GetPointData()->GetScalars();
+  int index=0;
+
+  for (int k=0;k<dim[2];k++)
+    {
+      x[2]=k*sp[2]+ori[2];
+      for (int j=0;j<dim[1];j++)
+	{
+	  x[1]=j*sp[1]+ori[1];
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      x[0]=i*sp[0]+ori[0];
+
+	      if (nonlinearonly==0)
+		{
+		  tr->InternalTransformDerivative(x,x2,der);
+		}
+	      else
+		{
+		  if (nlfirst==1)
+		    {
+		      grid->InternalTransformDerivative(x,x2,der);
+		    }
+		  else
+		    {
+		      linear->TransformPoint(x,x2);
+		      grid->InternalTransformDerivative(x2,x3,der);
+		    }
+		}
+	      dat->SetComponent(index,0,der[0][0]);
+	      dat->SetComponent(index,1,der[0][1]);
+	      dat->SetComponent(index,2,der[0][2]);
+	      dat->SetComponent(index,3,der[1][1]);
+	      dat->SetComponent(index,4,der[1][2]);
+	      dat->SetComponent(index,5,der[2][2]);
+	      ++index;
+	    }
+	}
+      
+    }
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxRegistration::ComputePrincipalStrains(vtkImageData* ref,vtkImageData* jacobian,
+					       vtkAbstractTransform* tr,float threshold)
+{
+  if (ref==NULL || jacobian==NULL || tr==NULL)
+    return 0;
+
+  tr->Update();
+
+  double range[2]; ref->GetPointData()->GetScalars()->GetRange(range);
+
+  if (threshold<0.0)
+    threshold=range[0]-10.0;
+  else
+    threshold=Frange(threshold,0.0,0.5)*(range[1]-range[0])+range[0];
+
+
+  int dim[3];  ref->GetDimensions(dim);
+  int dim2[3]; jacobian->GetDimensions(dim2);
+
+
+  if (dim[0]!=dim2[0] || dim[1]!=dim2[1] || dim[2]!=dim2[2] || 
+      jacobian->GetScalarType()!=VTK_FLOAT || 
+      jacobian->GetNumberOfScalarComponents()!=3)
+    {
+      jacobian->CopyStructure(ref);
+      jacobian->SetNumberOfScalarComponents(3);
+      jacobian->SetScalarTypeToFloat();
+      jacobian->AllocateScalars();
+    }
+
+  double sp[3];  ref->GetSpacing(sp);
+  double ori[3]; ref->GetOrigin(ori);
+  double der[3][3], x[3],x2[3];
+  
+  vtkDataArray* dat=jacobian->GetPointData()->GetScalars();
+  int index=0;
+
+  dat->FillComponent(0,0.0);
+  dat->FillComponent(1,0.0);
+  dat->FillComponent(2,0.0);
+
+  fprintf(stderr,"Computing Strains: ");
+  for (int k=0;k<dim[2];k++)
+    {
+      x[2]=k*sp[2]+ori[2];
+      for (int j=0;j<dim[1];j++)
+	{
+	  x[1]=j*sp[1]+ori[1];
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      x[0]=i*sp[0]+ori[0];
+	      double v=ref->GetScalarComponentAsDouble(i,j,k,0);
+	      if (v>=threshold)
+		{
+		  tr->InternalTransformDerivative(x,x2,der);
+		  for (int ia=0;ia<=2;ia++)
+		    {
+		      der[ia][ia]-=1.0;
+		      for (int ib=ia+1;ib<=2;ib++)
+			{
+			  der[ia][ib]=0.5*(der[ia][ib]+der[ib][ia]);
+			  der[ib][ia]=der[ia][ib];
+			}
+		    }
+		  
+		  //float det=vtkMath::Determinant3x3(der);
+		  //  if (det>1e-4)
+		  //		    {
+		      double w[3],V[3][3];
+		      vtkMath::Diagonalize3x3(der,w,V);
+		      float w2[3]; for (int ia=0;ia<=2;ia++) w2[ia]=w[ia];
+		      vtkpxMath::Heapsort(3,&w2[0]);
+		      
+		      dat->SetComponent(index,0,(w2[2])*100.0);
+		      dat->SetComponent(index,1,(w2[1])*100.0);
+		      dat->SetComponent(index,2,(w2[0])*100.0);
+		      /*}
+		  else
+		    {
+		      dat->SetComponent(index,0,0.01);
+		      dat->SetComponent(index,1,0.01);
+		      dat->SetComponent(index,2,0.01);
+		      }*/
+		}
+	      else
+		{
+		  dat->SetComponent(index,0,-0.01);
+		  dat->SetComponent(index,1,-0.01);
+		  dat->SetComponent(index,2,-0.01);
+		}
+	      ++index;
+	    }
+	}
+      if ( 10*int(k/10)==k)
+	fprintf(stderr,"%d/%d ",k+1,dim[2]);
+    }
+  fprintf(stderr,"\n");
+  return 1;
+}
+//-------------------------------------------------------------------------
+// Description:
+// Compute Average Jacobian for image
+//-------------------------------------------------------------------------
+float vtkpxRegistration::ComputeAverageJacobian(vtkImageData* ref,vtkAbstractTransform* tr)
+{
+  return vtkpxRegistration::ComputeAverageJacobian(ref,tr,0.05);
+}
+
+float vtkpxRegistration::ComputeAverageJacobian(vtkImageData* ref,vtkAbstractTransform* tr,float srate)
+{
+  if (ref==NULL || tr==NULL)
+    {
+      fprintf(stderr,"Bad Inputs to Compute Average Jacobian\n");
+      return 1.0;
+    }
+
+  if ( tr->IsA("vtkHomogeneousTransform")==1) 
+    return ((vtkHomogeneousTransform*)tr)->GetMatrix()->Determinant();
+
+  if ( tr->IsA("vtkpxComboTransform")==1)
+    {
+      vtkTransform* linear=((vtkpxComboTransform*)tr)->GetLinearTransform();
+      float sum=0.0;
+      for (int i=0;i<=3;i++)
+	for (int j=0;j<=3;j++)
+	  {
+	    float a=linear->GetMatrix()->GetElement(i,j);
+	    float b=float(i==j);
+	    sum+=fabs(a-b);
+	  }
+      
+      if (sum>0.0)
+	{
+	  return linear->GetMatrix()->Determinant();
+	}
+    }
+  fprintf(stderr,"Computing determinant from landmark transform\n");
+  srate=Frange(srate,0.01,0.5);
+  float offset=srate*0.5;
+
+  double ori[3],spa[3];
+  int   dim[3];
+
+  ref->GetDimensions(dim);
+  ref->GetSpacing(spa);
+  ref->GetOrigin(ori);
+
+  // Use Middle 60% of images
+  float wd[3];
+  for (int ia=0;ia<=2;ia++)
+    wd[ia]=float(dim[ia])*spa[ia];
+
+
+  int np=int(1.0/srate);
+  int nptot=np*np*np;
+
+  vtkPoints* p1=vtkPoints::New();
+  vtkPoints* p2=vtkPoints::New();
+  p1->SetNumberOfPoints(nptot);
+  p2->SetNumberOfPoints(nptot);
+  
+    
+  float x[3],tx[3];
+  int index=0;
+  for (int k=0;k<np;k++)
+    {
+      x[2]=(offset+float(k)*srate)*wd[2]+ori[2];
+      for (int j=0;j<np;j++)
+	{
+	  x[1]=(offset+float(j)*srate)*wd[1]+ori[1];
+	  for (int i=0;i<np;i++)
+	    {
+	      x[0]=(offset+float(i)*srate)*wd[0]+ori[0];
+	      tr->TransformPoint(x,tx);
+	      p1->SetPoint(index,x);
+	      p2->SetPoint(index,tx);
+	      ++index;
+	    }
+	}
+    }
+
+  vtkLandmarkTransform* land=vtkLandmarkTransform::New();
+  land->SetSourceLandmarks(p1);
+  land->SetTargetLandmarks(p2);
+  land->SetModeToAffine();
+  land->Modified();
+  land->Update();
+  float det=land->GetMatrix()->Determinant();
+
+  p1->Delete();
+  p2->Delete();
+  land->Delete();
+
+
+  return det;
+}
+
+//-------------------------------------------------------------------------
+int vtkpxRegistration::ReOrientImage(vtkImageData* destination,vtkImageData* source,int inputorient,int outputorient)
+{
+  if (source==NULL || destination==NULL)
+      return 0;
+
+
+  return vtkpxUtil::ReOrientImage(destination,source,inputorient,outputorient);
+
+  /*  inputorient=Irange(inputorient,0,2);
+  outputorient=Irange(outputorient,0,2);
+
+  if (inputorient==outputorient)
+    {
+      destination->DeepCopy(source);
+      return 0;
+    }
+  
+  vtkMatrix4x4* tmat=vtkMatrix4x4::New();
+  int ok2=vtkpxUtil::ReOrientMatrix(source,inputorient,outputorient,tmat);
+  if (ok2==0)
+    return ok2;
+
+  vtkTransform* trans=vtkTransform::New();
+  trans->SetMatrix(tmat);
+		
+  float sp[3],spout[3];
+  int dim[3],dimout[3];
+
+  source->GetSpacing(sp);
+  source->GetDimensions(dim);
+  vtkpxUtil::ReOrientDimensions(sp,dim,inputorient,outputorient,spout,dimout);
+
+  vtkbisImageReslice* reslice=vtkbisImageReslice::New();    resl->OptimizationOff();
+  reslice->SetInput(source);
+  reslice->SetOutputOrigin(0.0,0.0,0.0);
+  reslice->SetOutputExtent(0,dimout[0]-1,0,dimout[1]-1,0,dimout[2]-1);
+  reslice->SetOutputSpacing(spout[0],spout[1],spout[2]);
+  reslice->SetInterpolationMode(0);
+  reslice->SetResliceTransform(trans);
+  reslice->SetBackgroundLevel(0);
+  reslice->Update();
+
+  destination->ShallowCopy(reslice->GetOutput());
+  reslice->Delete();
+  trans->Delete();
+  tmat->Delete();
+  return 1;*/
+}
+
+
+//-------------------------------------------------------------------------
+void vtkpxRegistration::CenterImageOrigin(vtkImageData* img)
+{
+  double sp[3];   img->GetSpacing(sp);
+  int dm[3]; img->GetDimensions(dm);
+  double ori[3];
+
+  for (int ia=0;ia<=2;ia++)
+    ori[ia]=-0.5*(sp[ia]*float(dm[ia]));
+
+  img->SetOrigin(ori);
+}
+//-------------------------------------------------------------------------
+float vtkpxRegistration::ComputeSimpleSimilarityBetweenImages(vtkImageData* img1,vtkImageData* img2,
+							      vtkAbstractTransform* tr)
+{
+  return vtkpxRegistration::ComputeSimilarityBetweenImages(img1,img2,tr,img1->GetSpacing(),0.0,
+							   5,1,64);
+}
+
+
+
+float vtkpxRegistration::ComputeSimilarityBetweenImages(vtkImageData* img1,vtkImageData* img2,
+							vtkAbstractTransform* tr,
+							double resolution[3],float sigma,
+							int metric,int interpolation,int numbins)
+{
+  vtkImageData* ref=vtkImageData::New();
+  vtkImageData* trn=vtkImageData::New();
+  
+  vtkpxRegistration::ResampleAndSmoothImage(ref,img1,
+					    resolution,sigma,1.0);
+  
+  vtkpxRegistration::ResampleAndSmoothImage(trn,img2,
+					    resolution,sigma,1.0);
+  
+  short minr=0,maxr=1,mint=0,maxt=1;
+  int num_ref=CalculateNumberOfBinsAndAdjustImage(ref,numbins,minr,maxr,0);
+  int num_tar=CalculateNumberOfBinsAndAdjustImage(trn,numbins,mint,maxt,0);
+
+
+  vtkpxJointHistogram* Histogram=vtkpxJointHistogram::New();
+  Histogram->Allocate(num_ref,num_tar);
+
+  vtkbisImageReslice* resl=vtkbisImageReslice::New();   resl->OptimizationOff();
+  
+  resl->SetInput(trn);
+  resl->SetInformationInput(ref);
+  resl->SetResliceTransform(tr);
+  resl->SetInterpolationMode(interpolation);
+  resl->Update();
+
+  Histogram->FillHistogram(ref,resl->GetOutput(),1);
+  float val=0.0;
+
+  switch (metric) 
+    {
+    case 1:
+      val= -Histogram->JointEntropy();
+      break;
+    case 2:
+    case 3:
+      val= +Histogram->CrossCorrelation();
+      break;
+    case 4:
+      val= +Histogram->MutualInformation();
+      break;
+    case 5:
+      val= +Histogram->NormalizedMutualInformation();
+      break;
+    case 6:
+      val= -Histogram->SumsOfSquaredDifferences() / 
+	(double)Histogram->GetNumberOfSamples();
+      break;
+    case 7:
+      val= +Histogram->CorrelationRatioXY();
+      break;
+    case 8:
+      val= +Histogram->CorrelationRatioYX();
+      break;
+    case 9:
+      val= Histogram->ComputeProduct();
+      break;
+    case 10:
+      val= Histogram->ComputeEntropyOfDifference();
+      break;
+
+    default:
+      val= +Histogram->NormalizedMutualInformation();
+      break;
+    }
+
+
+  resl->Delete();
+  Histogram->Delete();
+  ref->Delete();
+  trn->Delete();
+  return val;
+}
+
+
+void vtkpxRegistration::ComputeAllSimilarityMetricsBetweenImages(vtkImageData* img1,vtkImageData* img2,
+								 vtkAbstractTransform* tr,vtkFloatArray* results)
+{
+  vtkpxRegistration::ComputeAllSimilarityMetricsBetweenImages(img1,img2,tr,results,64);
+}
+
+void vtkpxRegistration::ComputeAllSimilarityMetricsBetweenImages(vtkImageData* img1,vtkImageData* img2,
+								 vtkAbstractTransform* tr,vtkFloatArray* results,int numbins)
+{
+
+  if (results==NULL)
+    return;
+
+  results->SetNumberOfComponents(1);
+  results->SetNumberOfTuples(10);
+
+  double resolution[3];
+  img1->GetSpacing(resolution);
+  
+  float sigma=0.0;
+  
+  int interpolation=1;
+  if (numbins<2)
+    numbins=2;
+  else if (numbins>1024)
+    numbins=1024;
+ 
+
+  vtkImageData* ref=vtkImageData::New();
+  vtkImageData* trn=vtkImageData::New();
+  
+  vtkpxRegistration::ResampleAndSmoothImage(ref,img1,
+					    resolution,sigma,1.0);
+  
+  vtkpxRegistration::ResampleAndSmoothImage(trn,img2,
+					    resolution,sigma,1.0);
+  
+  short minr=0,maxr=1,mint=0,maxt=1;
+  int num_ref=CalculateNumberOfBinsAndAdjustImage(ref,numbins,minr,maxr,0);
+  int num_tar=CalculateNumberOfBinsAndAdjustImage(trn,numbins,mint,maxt,0);
+
+
+  vtkpxJointHistogram* Histogram=vtkpxJointHistogram::New();
+  Histogram->Allocate(num_ref,num_tar);
+
+  vtkbisImageReslice* resl=vtkbisImageReslice::New(); resl->OptimizationOff();
+  
+  resl->SetInput(trn);
+  resl->SetInformationInput(ref);
+  resl->SetResliceTransform(tr);
+  resl->SetInterpolationMode(interpolation);
+  resl->Update();
+
+  Histogram->FillHistogram(ref,resl->GetOutput(),1);
+
+
+  for (int metric=1;metric<=10;metric++)
+    {
+      float val=0.0;
+      switch (metric) 
+	{
+	case 1:
+	  val= -Histogram->JointEntropy();
+	  break;
+	case 2:
+	case 3:
+	  val= +Histogram->CrossCorrelation();
+	  break;
+	case 4:
+	  val= +Histogram->MutualInformation();
+	  break;
+	case 5:
+	  val= +Histogram->NormalizedMutualInformation();
+	  break;
+	case 6:
+	  val= -Histogram->SumsOfSquaredDifferences() / 
+	    (double)Histogram->GetNumberOfSamples();
+	  break;
+	case 7:
+	  val= +Histogram->CorrelationRatioXY();
+	  break;
+	case 8:
+	  val= +Histogram->CorrelationRatioYX();
+	  break;
+	case 9:
+	  val= Histogram->ComputeProduct();
+	  break;
+	case 10:
+	  val= Histogram->ComputeEntropyOfDifference();
+	  break;
+	}
+      results->SetComponent(metric-1,0,val);
+    }
+
+  resl->Delete();
+  Histogram->Delete();
+  ref->Delete();
+  trn->Delete();
+  return;
+}
+
+
+//-------------------------------------------------------------------------
+float vtkpxRegistration::HistogramEvaluate(vtkImageData* ref,vtkImageData* targ,vtkAbstractTransform* trans,
+					   vtkpxJointHistogram* histo,int similaritymeasure,
+					   int interp,int reset)
+{
+  if (ref==NULL || targ==NULL || trans==NULL || histo==NULL)
+    return 0.0;
+
+  if (interp<0)
+    interp=-interp;
+
+  if (interp<0 || interp>1)
+    interp=3;
+  
+  vtkbisImageReslice* resl=vtkbisImageReslice::New(); resl->OptimizationOff();
+  
+  resl->SetInput(targ);
+  resl->SetInformationInput(ref);
+  resl->SetResliceTransform(trans);
+  resl->SetInterpolationMode(interp);
+  resl->Update();
+  
+  histo->FillHistogram(ref,resl->GetOutput(),reset);
+  float val=histo->Similarity(similaritymeasure);
+  
+  resl->Delete();
+  return val;
+}
+//-------------------------------------------------------------------------
+float vtkpxRegistration::WeightedHistogramEvaluate(vtkImageData* ref,vtkImageData* wgt,vtkImageData* targ,vtkImageData* wgt2,
+						   vtkAbstractTransform* trans,
+						   vtkpxJointHistogram* histo,int similaritymeasure,
+						   int interp,int reset)
+{
+  if (ref==NULL || targ==NULL || trans==NULL || histo==NULL)
+    return 0.0;
+  
+  if (interp<0 || interp>1)
+    interp=3;
+  
+  vtkbisImageReslice* resl=vtkbisImageReslice::New(); resl->OptimizationOff();
+  resl->SetInput(targ);
+  resl->SetInformationInput(ref);
+  resl->SetResliceTransform(trans);
+  resl->SetInterpolationMode(interp);
+  resl->Update();
+
+  vtkImageData* reslweight=NULL;
+
+  if (wgt2!=NULL)
+    {
+      vtkbisImageReslice* resl2=vtkbisImageReslice::New();
+      resl2->OptimizationOff();
+      resl2->SetInput(wgt2);
+      resl2->SetInformationInput(ref);
+      resl2->SetResliceTransform(trans);
+      resl2->SetInterpolationMode(interp);
+      resl2->Update();
+      histo->DualWeightedFillHistogram(ref,resl->GetOutput(),wgt,resl2->GetOutput(),reset);
+      resl2->Delete();
+    }
+  else
+    {
+      histo->WeightedFillHistogram(ref,resl->GetOutput(),wgt,reset);
+    }
+  float val=histo->Similarity(similaritymeasure);
+  
+  resl->Delete();
+  return val;
+}
+//-------------------------------------------------------------------------
+
+int vtkpxRegistration::SeamImages(vtkImageData* ref,vtkImageData* targ,vtkLinearTransform* tr,vtkImageData* output,int intensitymap)
+{
+  {
+    double r1[2],r2[2];
+    ref->GetPointData()->GetScalars()->GetRange(r1);
+    targ->GetPointData()->GetScalars()->GetRange(r2);
+    fprintf(stderr,"Input Ranges=%.1f:%.1f and %.1f:%.1f\n",r1[0],r1[1],r2[0],r2[1]);
+  }
+
+  double bounds[6],bounds2[6];
+  ref->GetBounds(bounds);
+  targ->GetBounds(bounds2);
+
+  double p1[3],p2[3],pc1[3],pc2[3];
+  int ia=0;
+
+  for (ia=0;ia<=2;ia++)
+    {
+      p1[ia]=bounds2[ia*2];
+      p2[ia]=bounds2[ia*2+1];
+      pc1[ia]=0.5*(bounds[ia*2]+bounds[ia*2+1]);
+      pc2[ia]=0.5*(p2[ia]+p1[ia]);
+      
+    }
+
+  tr->GetLinearInverse()->TransformPoint(p1,p1);
+  tr->GetLinearInverse()->TransformPoint(p2,p2);
+  tr->GetLinearInverse()->TransformPoint(pc2,pc2);
+  
+  fprintf(stderr,"Reference Bounds=%.4f:%.4f %.4f:%.4f %.4f:%.4f\n",
+	  bounds[0],bounds[1],bounds[2],bounds[3],bounds[4],bounds[5]);
+
+  for (ia=0;ia<=2;ia++)
+    {
+      if (bounds[ia*2]>p1[ia])
+	bounds[ia*2]=p1[ia];
+      if (bounds[ia*2]>p2[ia])
+	bounds[ia*2]=p2[ia];
+
+      if (bounds[ia*2+1]<p1[ia])
+	bounds[ia*2+1]=p1[ia];
+      if (bounds[ia*2+1]<p2[ia])
+	bounds[ia*2+1]=p2[ia];
+    }
+  
+  fprintf(stderr,"Outlining Bounds=%.4f:%.4f %.4f:%.4f %.4f:%.4f\n",
+	  bounds[0],bounds[1],bounds[2],bounds[3],bounds[4],bounds[5]);
+
+  
+  double ori[3],spa[3]; ref->GetOrigin(ori); ref->GetSpacing(spa);
+  double outorigin[3];
+  int   outdim[3];
+  
+  for (ia=0;ia<=2;ia++)
+    {
+      if (bounds[2*ia]<ori[ia])
+	{
+	  int v=int(fabs(bounds[2*ia]-ori[ia])/spa[ia]+0.99);
+	  outorigin[ia]=ori[ia]-v*spa[ia];
+	}
+      else
+	{
+	  outorigin[ia]=ori[ia];
+	}
+
+      outdim[ia]=int(fabs(bounds[2*ia+1]-outorigin[ia])/spa[ia]+0.99);
+    }
+
+  fprintf(stderr,"Outputs ... Origin=(%.4f %.4f %.4f) Spacing=(%.4f,%.4f,%.4f) Dimensions(%d,%d,%d)\n",
+	  outorigin[0],	  outorigin[1],	  outorigin[2],
+	  spa[0],	  spa[1],	  spa[2],
+	  outdim[0],	  outdim[1],	  outdim[2]);
+
+  
+  vtkbisImageReslice* resl[2];
+
+  for (int img=0;img<=1;img++)
+    {
+      resl[img]=vtkbisImageReslice::New(); resl[img]->OptimizationOff();
+      resl[img]->SetOutputSpacing(spa);
+      resl[img]->SetOutputOrigin(outorigin);
+      resl[img]->SetOutputExtent(0,outdim[0]-1,0,outdim[1]-1,0,outdim[2]-1);
+      if (img==0)
+	{
+	  resl[img]->SetInput(ref);
+	  resl[img]->SetInterpolationMode(0);
+	  resl[img]->SetBackgroundLevel(-1);
+	}
+      else
+	{
+	  resl[img]->SetInput(targ);
+	  resl[img]->SetResliceTransform(tr);
+	  resl[img]->SetInterpolationMode(1);
+	  resl[img]->SetBackgroundLevel(-1);
+	}
+      resl[img]->Update();
+    }
+
+  vtkpxImageNormalizeIntensityToReference* norm=vtkpxImageNormalizeIntensityToReference::New();
+  norm->SetInput(resl[1]->GetOutput());
+  norm->SetReference(resl[0]->GetOutput());
+  norm->SetThreshold(0.03);
+  norm->SetOrder(1);
+  norm->Update();
+
+  output->ShallowCopy(resl[0]->GetOutput());
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* dat=norm->GetOutput()->GetPointData()->GetScalars();
+  vtkDataArray* dat2=resl[1]->GetOutput()->GetPointData()->GetScalars();
+
+  double r1[2],r2[2];
+  out->GetRange(r1);
+  dat->GetRange(r2);
+  fprintf(stderr,"Range=%.1f:%.1f and %.1f:%.1f\n",r1[0],r1[1],r2[0],r2[1]);
+
+  int index=0;
+  double tp[3];
+  for (int k=0;k<outdim[2];k++)
+    {
+      tp[2]=outorigin[2]+float(k)*spa[2];
+      for (int j=0;j<outdim[1];j++)
+	{
+	  tp[1]=outorigin[1]+float(j)*spa[1];
+	  for (int i=0;i<outdim[0];i++)
+	    {
+	      tp[0]=outorigin[0]+float(i)*spa[0];
+	      float y2=dat2->GetComponent(index,0);
+	      if (y2!=-1)
+		{
+		  float d1=vtkMath::Distance2BetweenPoints(tp,pc1);
+		  float d2=vtkMath::Distance2BetweenPoints(tp,pc2);
+		  
+		  if (d2<d1)
+		    {
+		      for (int c=0;c<output->GetNumberOfScalarComponents();c++)
+			out->SetComponent(index,c,dat->GetComponent(index,c));
+		    }
+		}
+	      ++index;
+	    }
+	}
+    }
+
+
+
+  resl[0]->Delete();
+  resl[1]->Delete();
+  norm->Delete();
+
+  return 1;
+}
+
+
+int vtkpxRegistration::AutoReorientImages(vtkImageData* orig_ref,int ref_orient,
+					  vtkImageData* targ,int trg_orient,
+					  vtkImageData* output)
+{
+
+  vtkImageData* ref=vtkImageData::New();
+  
+  if (ref_orient==trg_orient)
+    ref->ShallowCopy(orig_ref);
+  else
+    vtkpxUtil::ReOrientImage(ref,orig_ref,ref_orient,trg_orient);
+
+  vtkpxLinearRegistration* areg=vtkpxLinearRegistration::New();
+  areg->SetTransformModeToAffine();
+  areg->SetSimilarityMeasureToNormalizedMutualInformation();
+  areg->SetReferenceImage(ref);
+  areg->SetTransformImage(targ);
+  areg->SetReferenceOrientation(0);
+  areg->SetTransformOrientation(0);
+  areg->SetResolution(2.0);
+  areg->SetNumberOfLevels(3);
+  areg->SetNumberOfSteps(4);
+  areg->SetStepSize(2.0);
+  areg->SetOptimizationMethodToHybrid();
+  areg->SetNumberOfIterations(25);
+  areg->SetPositiveIntensitiesOnly(0);
+  areg->SetLogarithmMode(0);
+  areg->SetJointlyNormalizeIntensities(0);
+  areg->SetAutoNormalizeIntensities(1);
+  areg->SetInterpolationMode(1);
+  areg->Run();
+    
+  vtkAbstractTransform* tr=areg->GetTransformation();
+
+  double bounds2[6];
+  targ->GetBounds(bounds2);
+
+  vtkpxLinearTransform* lin=vtkpxLinearTransform::New();
+  lin->ExtractParameters(tr,9,ref,0,targ,0);
+  lin->Put(6,100);
+  lin->Put(7,100);
+  lin->Put(8,100);
+
+  vtkTransform* tr2=vtkTransform::New();
+  lin->GenerateUpdateTransform(tr2,ref,0,targ,0);
+  lin->Delete();
+  
+  float p1[3],p2[3];
+  int ia=0;
+
+  for (ia=0;ia<=2;ia++)
+    {
+      p1[ia]=bounds2[ia*2];
+      p2[ia]=bounds2[ia*2+1];
+    }
+
+  tr2->GetLinearInverse()->TransformPoint(p1,p1);
+  tr2->GetLinearInverse()->TransformPoint(p2,p2);
+  
+
+  double bounds[6],spa[3],outorigin[3];
+  int   outdim[3];
+
+  targ->GetSpacing(spa);  
+  float outspacing=spa[0];
+  if (outspacing>spa[1])
+    outspacing=spa[1];
+  
+  if (outspacing>spa[2])
+    outspacing=spa[2];
+  
+ 
+  for (ia=0;ia<=2;ia++)
+    {
+      bounds[ia*2]  =Fmin(p1[0],p2[0])-3.0*outspacing;
+      bounds[ia*2+1]=Fmax(p1[0],p2[0])+3.0*outspacing;
+      outorigin[ia]=bounds[ia*2];
+      outdim[ia]=int( (bounds[ia*2+1]-bounds[ia*2])/outspacing + 0.5);
+    }
+
+  fprintf(stderr,"Outlining Bounds=%.4f:%.4f %.4f:%.4f %.4f:%.4f\n",
+	  bounds[0],bounds[1],bounds[2],bounds[3],bounds[4],bounds[5]);
+  
+  
+  
+  fprintf(stderr,"Outputs ... Origin=(%.4f %.4f %.4f) Spacing=(%.4f,%.4f,%.4f) Dimensions(%d,%d,%d)\n",
+	  outorigin[0],	  outorigin[1],	  outorigin[2],
+	  outspacing,	  outspacing,	  outspacing,
+	  outdim[0],	  outdim[1],	  outdim[2]);
+
+  
+  vtkbisImageReslice* resl=vtkbisImageReslice::New(); resl->OptimizationOff();
+  resl->SetOutputSpacing(outspacing,outspacing,outspacing);
+  resl->SetOutputOrigin(outorigin);
+  resl->SetOutputExtent(0,outdim[0]-1,0,outdim[1]-1,0,outdim[2]-1);
+  resl->SetInput(targ);
+  resl->SetResliceTransform(tr2);
+  resl->SetInterpolationMode(1);
+  resl->SetBackgroundLevel(0);
+  resl->Update();
+  
+  output->ShallowCopy(resl->GetOutput());
+  
+  resl->Delete();
+  ref->Delete();
+  areg->Delete();
+  return 1;
+}
+//-------------------------------------------------------------------------
+// Vasicek Estimator
+//
+//
+double vtkpxRegistration::ComputeEntropy(unsigned long n,short* data,double drift,short ignore)
+{
+  if (n<2)
+    return 0.0;
+
+  if (n<21)
+    {
+      fprintf(stderr,"Inp = ");
+      for (unsigned long j=0;j<n;j++)
+	fprintf(stderr,"%d ",data[j]);
+      fprintf(stderr,"\n");
+    }
+
+  if (fabs(drift)>0.000001)
+    {
+      for (unsigned long j=0;j<n;j++)
+	data[j]=short(double(data[j])/(1.0+drift*j));
+    }
+  
+  if (n<21)
+    {
+      fprintf(stderr,"Scale = ");
+      for (unsigned long j=0;j<n;j++)
+	fprintf(stderr,"%d ",data[j]);
+    }
+
+  vtkpxMath::Heapsort_Short(n,data);
+
+  if (n<21)
+    {
+      fprintf(stderr,"\nSort = ");
+      for (unsigned long j=0;j<n;j++)
+	fprintf(stderr,"%d ",data[j]);
+      fprintf(stderr,"\n");
+    }
+  
+  //  fprintf(stderr,"data[0]=%d ignore=%d\n",data[0],ignore);
+  if (data[0]==ignore)
+    return -1.0;
+
+  double h=0.0;
+  unsigned long m=(int)floor(sqrt(double(n)));
+  if (m<1)
+    m=1;
+  else if (m>=n)
+    m=n-1;
+  double factor=double(n)/double(m);
+  for (int i=0;i<n-m;i++)
+    h+=log(1.0+factor*(data[i+m]-data[i]));
+  return h/factor;
+}
+//-------------------------------------------------------------------------
+double vtkpxRegistration::ComputeWeightedTotalGroupEntropy(vtkImageData* img,vtkImageData* weights,double drift,short ignore)
+{
+  vtkDataArray* arr=img->GetPointData()->GetScalars();
+  int nt=arr->GetNumberOfTuples();
+  int nc=arr->GetNumberOfComponents();
+
+  short* data=new short[nc];
+  
+  vtkDataArray* wgt=NULL;
+  if (weights!=NULL)
+    wgt=weights->GetPointData()->GetScalars();
+
+
+  double entropy=0.0;
+  double sum=0.0;
+  //  int bad=0;
+  for (int i=0;i<nt;i++)
+    {
+      for (int j=0;j<nc;j++)
+	data[j]=(short)arr->GetComponent(i,j);
+
+      double w=1.0;
+      if (wgt!=NULL)
+	w=wgt->GetComponent(i,0);
+
+      double ent=vtkpxRegistration::ComputeEntropy(nc,data,drift);
+      if (ent>0.0)
+	{
+	  entropy+=w*ent;
+	  sum+=w;
+	}
+      /*  else
+	  bad+=1;*/
+    }
+  //  fprintf(stderr,"Bad=%.2f ent=%.3f\n",double(bad)/double(nt)*100.0,entropy/sum);
+  return entropy/sum;
+}
+//-------------------------------------------------------------------------
+double vtkpxRegistration::ComputeTotalGroupEntropy(vtkImageData* img,double drift,short ignore)
+{
+  return vtkpxRegistration::ComputeWeightedTotalGroupEntropy(img,NULL,drift,ignore);
+}
+//-------------------------------------------------------------------------
+vtkImageData* vtkpxRegistration::ComputeVoxelwiseEntropyImage(vtkImageData* img,double drift,short ignore)
+{
+  vtkImageData* output=vtkImageData::New();
+  output->CopyStructure(img);
+  output->SetNumberOfScalarComponents(3);
+  output->SetScalarTypeToFloat();
+  output->AllocateScalars();
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  out->FillComponent(0,-1.0);
+  out->FillComponent(1,-1.0);
+  out->FillComponent(2,-1.0);
+
+  vtkDataArray* arr=img->GetPointData()->GetScalars();
+  int nt=arr->GetNumberOfTuples();
+  int nc=arr->GetNumberOfComponents();
+
+  short* data=new short[nc];
+  
+  double entropy=0.0;
+  double sum=0.0;
+  int bad=0;
+  for (int i=0;i<nt;i++)
+    {
+      for (int j=0;j<nc;j++)
+	data[j]=(short)arr->GetComponent(i,j);
+
+  
+      double ent=vtkpxRegistration::ComputeEntropy(nc,data,drift,ignore);
+      double med=double(data[nc/2]);
+      out->SetComponent(i,1,med);
+      if (ent>0.0)
+	{
+	  out->SetComponent(i,0,ent);
+	  entropy+=ent;
+	  sum+=1.0;
+	}
+      else
+	bad+=1;
+    }
+
+  double r1[2]; out->GetRange(r1,0);
+  double r2[2]; out->GetRange(r2,1);
+  double scale1=200.0;
+  double scale2=1000.0/r2[1];
+
+  fprintf(stderr,"Range entr = %.2f :%.2f sc=%.2f\n",r1[0],r1[1],scale1);
+  fprintf(stderr,"Range grsc = %.2f :%.2f sc=%.2f\n",r2[0],r2[1],scale2);
+  for (int i=0;i<nt;i++)
+    {
+      double a=out->GetComponent(i,0);
+      if (a>0.0)
+	{
+	  double b=out->GetComponent(i,1);
+	  out->SetComponent(i,0,scale1*a);
+	  out->SetComponent(i,1,b*scale2);
+	  out->SetComponent(i,2,pow(r1[1]-a,2.0)*b);
+	}
+    }
+
+  double r3[2]; out->GetRange(r3,2);
+  double scale3=1000.0/r3[1];
+  fprintf(stderr,"Range prod = %.2f :%.2f sc=%.2f\n",r3[0],r3[1],scale3);
+  for (int i=0;i<nt;i++)
+    {
+      double a=out->GetComponent(i,2);
+      if (a>0.0)
+	out->SetComponent(i,2,scale3*a);
+    }
+
+
+
+  fprintf(stderr,"Bad=%.2f ent=%.3f\n",double(bad)/double(nt)*100.0,entropy/sum);
+  return output;
+}
+
+// --------------------------------------------------------------------------------------------------------------------
+//
+//
+//  Area Expansion Methods for Surface Deformation Morphometry
+//
+//
+// --------------------------------------------------------------------------------------------------------------------
+
+
+float vtkpxRegistration::ComputeAreaExpansionSurface(vtkPolyData* surface,vtkAbstractTransform* tr,float scale,float offset)
+{
+  if (surface==NULL || tr==NULL)
+    return -1.0;
+
+  vtkTriangleFilter* triFilter=vtkTriangleFilter::New();
+  triFilter->SetInput(surface);
+  triFilter->Update();
+
+  vtkTransformPolyDataFilter* filt= vtkTransformPolyDataFilter::New();
+  filt->SetInput(triFilter->GetOutput());
+  filt->SetTransform(tr);
+  filt->Update();
+
+  vtkPolyData* tmpsurface=vtkPolyData::New();
+  tmpsurface->DeepCopy(triFilter->GetOutput());
+  triFilter->Delete();
+  
+  surface->ShallowCopy(tmpsurface);
+  tmpsurface->Delete();
+
+  vtkCellArray* triangles=surface->GetPolys();
+  vtkPoints*    p1=surface->GetPoints();
+  vtkPoints*    p2=filt->GetOutput()->GetPoints();
+
+  int nt=surface->GetNumberOfPolys();
+  int np=p1->GetNumberOfPoints();
+
+  //  fprintf(stderr,"NumberOf Triangles=%d, points=%d\n",nt,np);
+
+
+  vtkFloatArray* areas=vtkFloatArray::New();
+  areas->SetNumberOfComponents(1);
+  areas->SetNumberOfTuples(nt);
+  areas->FillComponent(0,0.0);
+  float sumarea[2] = { 0.000001,0.000001};
+  triangles->InitTraversal();
+  vtkIdType  iad[10];
+  vtkIdType* id=&iad[0];
+
+  for (int ia=0;ia<nt;ia++)
+    {
+      vtkIdType ncell;
+
+      triangles->GetNextCell(ncell,id);
+      if (ncell!=3)
+	{
+	  fprintf(stderr,"Error Triangle but npoints!=3 (%d)\n",ncell);
+	}
+
+      for (int i=0;i<=2;i++)
+	{
+	  if (id[i]>=np)
+	    {
+	      fprintf(stderr,"Bad Point %d (Triangle %d) max=%d\n",
+		      id[i],ia,np);
+	    }
+	}
+      
+      double v0[3],v1[3],v2[3],q0[3],q1[3],q2[3];
+      p1->GetPoint(id[0],v0);      p1->GetPoint(id[1],v1);      p1->GetPoint(id[2],v2);
+      p2->GetPoint(id[0],q0);      p2->GetPoint(id[1],q1);      p2->GetPoint(id[2],q2);
+
+      if (ia==nt/2)
+	{
+	  fprintf(stderr,"Triangle1= [ %.2f %.2f %.2f ; %.2f %.2f %.2f ; %.2f %.2f %.2f ]\n",
+		  v0[0],v0[1],v0[2],
+		  v1[0],v1[1],v1[2],		  
+		  v2[0],v2[1],v2[2]);
+	  fprintf(stderr,"Triangle2= [ %.2f %.2f %.2f ; %.2f %.2f %.2f ; %.2f %.2f %.2f ]\n",
+		  q0[0],q0[1],q0[2],
+		  q1[0],q1[1],q1[2],		  
+		  q2[0],q2[1],q2[2]);
+	}
+
+      for (int ib=0;ib<=2;ib++)
+	{
+	  v1[ib]=v1[ib]-v0[ib];	  v2[ib]=v2[ib]-v0[ib];
+	  q1[ib]=q1[ib]-q0[ib];	  q2[ib]=q2[ib]-q0[ib];
+	}
+
+      vtkMath::Cross(v1,v2,v0);       vtkMath::Cross(q1,q2,q0); 
+      double v=0.5*vtkMath::Norm(v0);
+      double q=0.5*vtkMath::Norm(q0);
+
+      if (ia==nt/2)
+	fprintf(stderr,"Areas = %.4f %.4f\n",v,q);
+
+      sumarea[0]+=v;
+      sumarea[1]+=q;
+      double ratio=1.0;
+      if (q>0.0)
+	ratio=v/q;
+      areas->SetComponent(ia,0,(ratio-offset)*scale);
+    }
+  
+  surface->GetCellData()->SetScalars(areas);
+  areas->Delete();
+  filt->Delete();
+  
+  vtkCellDataToPointData* pt=vtkCellDataToPointData::New();
+  pt->SetInput(surface);
+  pt->Update();
+
+  surface->ShallowCopy(pt->GetOutput());
+  pt->Delete();
+
+  //  delete [] id;
+    
+  return  sumarea[1]/sumarea[0];
+
+}
+// -----------------------------------------------------------------------------------------------------------
+int vtkpxRegistration::SmoothAreaExpansionSurface(vtkPolyData* surface,int iterations,float lambda)
+{
+  if (surface==NULL)
+    return 0;
+  
+  if (surface->GetPointData()->GetScalars()==NULL)
+  return 0;
+
+  PXIntegerList* neighbours=vtkpxSurfaceUtil::GenerateNeighbors(surface,0);
+
+  vtkDataArray* data=surface->GetPointData()->GetScalars();
+  int nt=data->GetNumberOfTuples();
+  vtkFloatArray* temp=vtkFloatArray::New();
+  temp->SetNumberOfComponents(1);
+  temp->SetNumberOfTuples(nt);
+  
+  fprintf(stderr,"Smoothing point data , iterations (lambda=%5.3f,iter=%d)\n ",lambda,iterations);
+
+  for (int iter=1;iter<=iterations;iter++)
+    {
+      temp->CopyComponent(0,data,0);
+      for(int i=0;i<nt;i++)
+	{
+	  double oldx=temp->GetComponent(i,0),newx=0.0;
+	
+	  /*	  if (i==nt/2)
+	    fprintf(stderr,"i=%d oldx=%.2f\n",i,oldx);*/
+	  
+	  neighbours[i].Rewind();
+	  int n=(neighbours[i].getnumnodes());
+	  double scalefactor=0.0001;
+	  if (n>0)
+	    scalefactor=1.0/double(n);
+	  for(int j=0;j<n;j++)
+	    {
+	      int p=neighbours[i].getcurrent();
+	      double v=temp->GetComponent(p,0);
+	      newx+=v*scalefactor;
+	      neighbours[i].Next();
+
+	      /*	      if (i==nt/2)
+		fprintf(stderr,"\tj=%d \t p=%d \t v=%.2f\t newx=%f\n",j,p,v,newx);*/
+	    }
+	
+	  double final=oldx;
+	  if (n>0)
+	    final=(1.0-lambda)*oldx+lambda*newx;
+	  /*	  if (i==nt/2)
+	    fprintf(stderr,"\tnewx=%f\t oldx=%f \t final=%f\n\n\n",oldx,newx,final);*/
+	  
+	  data->SetComponent(i,0,final);
+	}
+	
+    }
+  temp->Delete();
+  delete [] neighbours;
+
+  return 1;
+}
+
+// -----------------------------------------------------------------------------------------------------------
+
+vtkImageData* vtkpxRegistration::ComputeAreaExpansionImage(vtkPolyData* surface)
+{
+  if (surface==NULL)
+    return NULL;
+
+  vtkDataArray* dat=surface->GetPointData()->GetScalars();
+  if (dat==NULL)
+    return NULL;
+
+  int nt=dat->GetNumberOfTuples();
+  if (nt==0)
+    return NULL;
+
+  double v=sqrt(double(nt));
+  int width=int(v+1);
+  int height=int(v+1);
+
+  fprintf(stderr,"Input cell data=%d output image = %d x %d = %d\n",
+	  nt,width,height,width*height);
+
+  vtkImageData* img=vtkImageData::New();
+  img->SetDimensions(width,height,1);
+  img->SetScalarTypeToFloat();
+  img->AllocateScalars();
+
+  vtkDataArray* out=img->GetPointData()->GetScalars();
+  out->FillComponent(0,0.0);
+  for (int ia=0;ia<nt;ia++)
+    out->SetComponent(ia,0,dat->GetComponent(ia,0));
+
+  //  fprintf(stderr,"Done Copying Data\n");
+  return img;
+		
+}
+
+int vtkpxRegistration::ConvertAreaExpansionImageToSurface(vtkImageData* img, vtkPolyData* surface)
+{
+  if (surface==NULL || img==NULL)
+    return -1;
+
+  vtkTriangleFilter* triFilter=vtkTriangleFilter::New();
+  triFilter->SetInput(surface);
+  triFilter->Update();
+
+  vtkCellArray* triangles=triFilter->GetOutput()->GetPolys();
+  int nt=triFilter->GetOutput()->GetNumberOfPoints();
+  vtkDataArray* dat=img->GetPointData()->GetScalars();
+  int np=dat->GetNumberOfTuples();
+
+  if (np<nt)
+    {
+      fprintf(stderr,"Bad Image\n");
+      triFilter->Delete();
+      return -1;
+    }
+
+  vtkFloatArray* areas=vtkFloatArray::New();
+  areas->SetNumberOfComponents(1);
+  areas->SetNumberOfTuples(nt);
+  areas->FillComponent(0,0.0);
+  for (int ia=0;ia<nt;ia++)
+    areas->SetComponent(ia,0,dat->GetComponent(ia,0));
+
+  surface->ShallowCopy(triFilter->GetOutput());
+  surface->GetPointData()->SetScalars(areas);
+  
+  areas->Delete();
+  triFilter->Delete();
+  return 1;
+}
+
+void vtkpxRegistration::PrintImageInfo(vtkImageData* tmp,const char* comment)
+{
+  double sp1[3],or1[3];
+  int   dim1[3];
+
+  if (tmp==NULL)
+    {
+      fprintf(stderr,"\n +++++++++++ Image is NULL %s\n",comment);
+      return;
+    }
+
+  tmp->GetSpacing(sp1);
+  tmp->GetDimensions(dim1);
+  tmp->GetOrigin(or1);
+
+  
+
+  fprintf(stderr,"\n ************* Image (%s) dim=(%dx%dx%d) spa=(%.2f,%.2f,%.2f) ori=(%.2f,%.2f,%.2f) \t\t",comment,dim1[0],dim1[1],dim1[2],sp1[0],sp1[1],sp1[2],or1[0],or1[1],or1[2]);
+
+  for (int i=0;i<=1;i++)
+    {
+      vtkInformation* info;
+      if (i==0)
+	info=tmp->GetInformation();
+      else
+	info=tmp->GetPipelineInformation();
+      
+      if (info!=NULL)
+	{
+	  if (info->Has(vtkDataObject::SPACING()))
+	    {
+	      double sp[3];  info->Get(vtkDataObject::SPACING(), sp);
+	      fprintf(stderr," PIPELINE i=%d (%.2f,%.2f,%.2f)\n\n\n\n",i,sp[0],sp[1],sp[2]);
+	    }
+	}
+    }
+
+
+  fprintf(stderr,"\n");
+}
+
+
+void vtkpxRegistration::FixPipelineSpacingAndOrigin(vtkImageData* img)
+{
+  double Origin[3]; img->GetOrigin(Origin);
+  double Spacing[3]; img->GetSpacing(Spacing);
+
+  if (img->GetInformation()->Has(vtkDataObject::SPACING()))
+    img->GetInformation()->Set(vtkDataObject::SPACING(),Spacing[0],Spacing[1],Spacing[2]);
+
+  if (img->GetPipelineInformation()->Has(vtkDataObject::SPACING()))
+    img->GetPipelineInformation()->Set(vtkDataObject::SPACING(),Spacing[0],Spacing[1],Spacing[2]);
+
+
+  if (img->GetInformation()->Has(vtkDataObject::ORIGIN()))
+    img->GetInformation()->Set(vtkDataObject::ORIGIN(),Origin[0],Origin[1],Origin[2]);
+
+  if (img->GetPipelineInformation()->Has(vtkDataObject::ORIGIN()))
+    img->GetPipelineInformation()->Set(vtkDataObject::ORIGIN(),Origin[0],Origin[1],Origin[2]);
+
+}
+
diff --git a/bioimagesuite30_src/Registration/vtkpxRegistration.h b/bioimagesuite30_src/Registration/vtkpxRegistration.h
new file mode 100644
index 0000000..f68b674
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxRegistration.h
@@ -0,0 +1,224 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// ------------------------------------------------------------------------
+//
+// This file derives from original work
+// in the vtkCISG Toolkit
+// that was released under the terms of 
+// the GNU General Public License (either version 2,
+// of the License, or any later version.)
+// 
+// The code has been modified for inclusion in BioImage Suite
+//
+// It may consist of work derived from more than one source
+// file in the vtkCISG Toolkit. The original copyright notice
+// was:
+//
+//  Authors   : Thomas Hartkens <thomas at hartkens.de>
+//              Daniel Rueckert <d.rueckert at doc.ic.ac.uk>
+//	        Julia Schnabel  <julia.schnabel at kcl.ac.uk>
+//	        under the supervision of Dave Hawkes and Derek Hill
+//  Web       : http://www.image-registration.com
+//  Copyright : King's College London
+//              Div. of Radiological Sciences, 
+//              Computational Imaging Science Group, 1997 - 2000
+//	        http://www-ipg.umds.ac.uk/cisg
+//
+// ------------------------------------------------------------------------
+
+#ifndef __VTKPXREGISTRATION_H
+#define __VTKPXREGISTRATION_H
+
+#include "vtkObject.h"
+#include "vtkAbstractTransform.h"
+#include "vtkpxJointHistogram.h"
+#include "vtkProcessObject.h"
+#include "vtkLinearTransform.h"
+#include "vtkFloatArray.h"
+
+class vtkpxComboTransform;
+class vtkPolyData;
+
+class vtkpxRegistration : public vtkProcessObject {
+
+public:
+
+  vtkTypeMacro(vtkpxRegistration,vtkProcessObject);
+
+
+  // Description:
+  // This one also 
+  static vtkpxRegistration* New();
+  
+
+  // Description:
+  // Generate Jacobian Image using transformation tr and reference ref and transform tr
+  static int ComputeJacobianImage(vtkImageData* ref,vtkImageData* jacobian,vtkAbstractTransform* tr);
+  static int ComputeSimpleJacobianImage(vtkImageData* ref,vtkImageData* jacobian,vtkAbstractTransform* tr,float scale=100,float offset=1);
+  static int ComputeSimpleJacobianImage(vtkImageData* ref,vtkImageData* jacobian,vtkAbstractTransform* tr,float scale,float offset,float threshold);
+
+  // Surface Area Expansions (Jacobians)
+  static int   ConvertAreaExpansionImageToSurface(vtkImageData* img, vtkPolyData* surface);
+  static float ComputeAreaExpansionSurface(vtkPolyData* surface,vtkAbstractTransform* tr,float scale=100.0,float offset=1.0);
+  static int   SmoothAreaExpansionSurface(vtkPolyData* surface,int iterations=10,float lambda=0.5);
+  static vtkImageData* ComputeAreaExpansionImage(vtkPolyData* surface);
+
+
+
+  static int ComputePrincipalStrains(vtkImageData* ref,vtkImageData* jacobian,vtkAbstractTransform* tr,float threshold=0.05);
+
+  static int ComputeJacobianImage(vtkImageData* ref,vtkImageData* jacobian,vtkAbstractTransform* tr,float scale,float shift=0.0);
+  static int ComputeJacobianImage(vtkImageData* ref,vtkImageData* jacobian,vtkAbstractTransform* tr,float scale,float shift,float threshold);
+  static int ComputeCompleteJacobianImage(vtkImageData* ref,vtkImageData* jacobian,vtkpxComboTransform* tr,int nonlinearonly);
+
+  // Description:
+  // Compute Average Jacobian for image
+  static float ComputeAverageJacobian(vtkImageData* ref,vtkAbstractTransform* tr);
+  static float ComputeAverageJacobian(vtkImageData* ref,vtkAbstractTransform* tr,float srate);
+
+  // Description:
+  // Center Image Origin
+  static void CenterImageOrigin(vtkImageData* img);
+
+
+  // Description:
+  // Voxel Wise Estimation of Group Entropy from Miller et al 
+  // Intensity Correction   y(t)=x*(a*t+b) -- defaults a=0 b=1;
+  static double ComputeEntropy(unsigned long n,short* data,double drift=1.0,short ignore=-20000);
+  static double ComputeTotalGroupEntropy(vtkImageData* img,double drift=1.0,short ignore=-20000);
+  static double ComputeWeightedTotalGroupEntropy(vtkImageData* img,vtkImageData* wgt,double drift=1.0,short ignore=-20000);
+  static vtkImageData* ComputeVoxelwiseEntropyImage(vtkImageData* img,double drift=1.0,short ignore=-20000);
+
+
+  // Description:
+  // Compute Similarity given two images and a resolution
+  static float ComputeSimilarityBetweenImages(vtkImageData* img1,vtkImageData* img2,
+					      vtkAbstractTransform* tr,
+					      double sp[3],float sigma,int metric,int interpolation,int numbins);
+
+  static float ComputeSimpleSimilarityBetweenImages(vtkImageData* img1,vtkImageData* img2,
+						    vtkAbstractTransform* tr);
+
+
+  static void ComputeAllSimilarityMetricsBetweenImages(vtkImageData* img1,vtkImageData* img2,
+						       vtkAbstractTransform* tr,vtkFloatArray* results);
+
+  static void ComputeAllSimilarityMetricsBetweenImages(vtkImageData* img1,vtkImageData* img2,
+						       vtkAbstractTransform* tr,vtkFloatArray* results,int numbins);
+
+
+  // Description:
+  // This function adjusts the image and computes appropriate number of bins to use
+  static int CalculateNumberOfBinsAndAdjustImage(vtkImageData *image, int maxbin,
+						 short& minv,short& maxv,
+						 int logmode,int posmode=0,int autonorm=0);  
+
+  static int CalculateNumberOfBinsAndAdjustImages(vtkImageData *image1,vtkImageData* image2, 
+						  int maxbin,
+						  short& minv,short& maxv,
+						  int logmode,int posmode=0,int autonorm=0);  
+
+  static int CalculateRange(vtkImageData* image, short& minv,short& maxv,int autonorm=0);  
+  static int AdjustImage(vtkImageData* image,int maxbins,short minv,short maxv,int logmode,int posmode=0,int autonorm=0);
+
+  static int ScaleWeightImage(vtkImageData* weightimage,vtkImageData* sampledimage,double maxvalue=100.0);
+  
+
+  // Description:
+  // Create A Level in the Multi-scale pyramid
+  static int ResampleAndSmoothImage(vtkImageData* destination,
+				    vtkImageData* source,
+				    double baseresolution[3],
+				    float gaussian,
+				    float resolution,int sameslices=0);
+  static int ExtractComponentAndCastImageToShort(vtkImageData* destination,vtkImageData* source,int frame,int doscale=1);
+
+  // Description:
+  // Reslice Image using transformation and fill in histogram
+  static int ResliceImage(vtkImageData* destination,vtkImageData* source,vtkImageData* ref,
+			  vtkAbstractTransform* transform,
+			  int interp);
+
+  static int MultiplyAndOverWriteImage(vtkImageData* inout,vtkImageData* scale);
+
+  // Description:
+  // Re-orient Image
+  static int ReOrientImage(vtkImageData* destination,vtkImageData* source,int inputorient,int outputorient);
+
+  // Description::
+  // Evaluate Histogram Based Similarity
+  static float HistogramEvaluate(vtkImageData* ref,vtkImageData* targ,vtkAbstractTransform* trans,
+				 vtkpxJointHistogram* histo,int similaritymeasure,int interp=1,int reset=1);
+
+  static float WeightedHistogramEvaluate(vtkImageData* ref,vtkImageData* wgt,vtkImageData* targ,vtkImageData* wgt2,
+					 vtkAbstractTransform* trans,
+					 vtkpxJointHistogram* histo,int similaritymeasure,int interp=1,int reset=1);
+
+
+
+  
+  // Description::
+  // Seam Images 
+  static int SeamImages(vtkImageData* ref,vtkImageData* targ,vtkLinearTransform* tr,vtkImageData* output,int intensitymap);
+
+  
+  // Description:
+  // Auto Reorient Image
+  static int AutoReorientImages(vtkImageData* orig_ref,int ref_orient,
+				vtkImageData* targ,int trg_orient,
+				vtkImageData* output);
+
+
+
+  // Description:
+  // Debugging Aid 
+  static void PrintImageInfo(vtkImageData* tmp,const char* comment);
+
+  // Description:
+  // Fix Pipeline Spacing and Origin
+  static void FixPipelineSpacingAndOrigin(vtkImageData* img);
+  
+
+protected:
+
+  // Description:
+  // Make all these protected 
+  // Constructor
+  vtkpxRegistration();
+  virtual ~vtkpxRegistration();
+  vtkpxRegistration(const vtkpxRegistration&) {};
+  void operator=(const vtkpxRegistration&) {};
+
+
+};
+
+
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxSimilarityTransform.cpp b/bioimagesuite30_src/Registration/vtkpxSimilarityTransform.cpp
new file mode 100644
index 0000000..891cf95
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxSimilarityTransform.cpp
@@ -0,0 +1,1061 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include <stdlib.h>
+#include "vtkpxSimilarityTransform.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxUtil.h"
+#include "vtkTransform.h"
+//----------------------------------------------------------------------------
+vtkpxSimilarityTransform* vtkpxSimilarityTransform::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxSimilarityTransform");
+  if(ret)
+    {
+      return (vtkpxSimilarityTransform*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxSimilarityTransform;
+}
+
+//----------------------------------------------------------------------------
+vtkpxSimilarityTransform::vtkpxSimilarityTransform()
+{
+  this->Mode=0;
+  this->Initialize();
+  this->LocalZAxis[0] = 0.0;
+  this->LocalZAxis[1] = 0.0;
+  this->LocalZAxis[2] = 1.0;
+  this->LocalXAxis[0] = 1.0;
+  this->LocalXAxis[1] = 0.0;
+  this->LocalXAxis[2] = 0.0;
+  this->TranslationScale=1.0;
+  this->LocalAxisTransform=vtkMatrixToLinearTransform::New();
+
+}
+
+//----------------------------------------------------------------------------
+vtkpxSimilarityTransform::~vtkpxSimilarityTransform()
+{
+  this->LocalAxisTransform->Delete();
+}
+
+//----------------------------------------------------------------------------
+void vtkpxSimilarityTransform::PrintSelf(ostream& os, vtkIndent indent)
+{
+  os << indent << "### " << this->GetClassName() << " ### \n";
+  os  << indent << "Transformation Parameters: \n";
+  os << indent << "Mode: " << this->Mode << "\n";
+  os << indent << "Origin:      " << this->Origin[0] << " " << this->Origin[1]  << " " << this->Origin[2] << " "  << "\n";
+  os << indent << "Angle:      " << this->Angle[0] << " " << this->Angle[1]  << " " << this->Angle[2] << " "  << "\n";
+  os << indent << "Translation: " << this->Translation[0] << " " << this->Translation[1]  << " " << this->Translation[2] << " "  << "\n";
+  os << indent << "Scaling: " << this->ScaleFactor << "\n";
+  os << indent << "FreezeUpdates: " << this->FreezeUpdates << "\n";
+  os << indent << "RotationAxis:      " << this->RotationAxis[0] << " " << this->RotationAxis[1]  << " " << this->RotationAxis[2] << " "  << "\n";
+  os << indent << "RotationAngle: " << this->RotationAngle << "\n";
+  os << indent << "LocalXAxis:      " << this->LocalXAxis[0] << " " << this->LocalXAxis[1]  << " " << this->LocalXAxis[2] << " "  << "\n";
+  os << indent << "LocalZAxis:      " << this->LocalZAxis[0] << " " << this->LocalZAxis[1]  << " " << this->LocalZAxis[2] << " "  << "\n";
+  os << indent << "LocalAxisTransform: " << this->LocalAxisTransform << "\n";
+  os << indent << "TranslationScale: " << this->TranslationScale << "\n";
+  this->vtkMatrixToLinearTransform::PrintSelf(os, indent.GetNextIndent());
+}
+
+
+//----------------------------------------------------------------------------
+void vtkpxSimilarityTransform::SetLocalXZAxis(float x[3],float z[3])
+{
+  vtkMath::Normalize(x);
+  vtkMath::Normalize(z);
+
+  for (int i=0;i<=2;i++)
+    {
+      this->LocalZAxis[i]=z[i];
+      this->LocalXAxis[i]=x[i];
+    }
+
+  // Construct LocalAxisTransform and we are done.
+  float y[3];  vtkMath::Cross(z,x,y);
+
+  vtkMatrix4x4* mat=vtkMatrix4x4::New();
+  mat->Identity();
+  for (int i=0;i<=2;i++)
+    {
+      mat->SetElement(i,0,x[i]);
+      mat->SetElement(i,1,y[i]);
+      mat->SetElement(i,2,z[i]);
+    }
+  mat->Invert();
+
+  this->LocalAxisTransform->SetInput(mat);
+  this->LocalAxisTransform->Update();
+  mat->Delete();
+
+}
+//----------------------------------------------------------------------------
+/*void vtkpxSimilarityTransform::UpdateMatrix()
+{
+  if (this->FreezeUpdates)
+    return;
+
+
+  // Generate Rotation Transformation
+
+  vtkTransform* rot=vtkTransform::New();
+  rot->Identity();
+  rot->PostMultiply();
+
+  // Explicit Angle Axis Representation
+  // In Local Coordinate System
+  // First Take Local x-axis --> rotate it via Z
+  // 
+  double p1[3]= { 1,0,0} ;
+  if (this->Mode==9)
+    {
+      p1[0]=0.0;
+      p1[1]=0.0;
+      p1[2]=1.0;
+    }
+  else
+    {
+      rot->RotateY(this->Angle[2]);
+      rot->TransformVector(p1,p1);
+      
+      //  fprintf(stderr,"Post Angle 2 (Y-Rotate %.2f) New X Axis = %.2f %.2f %.2f\n",this->Angle[2],p1[0],p1[1],p1[2]);
+      
+      rot->Identity();
+      rot->RotateZ(this->Angle[1]);
+      rot->TransformVector(p1,p1);
+      //  fprintf(stderr,"Post Angle 1 (Z-Rotate %.2f) New X Axis = %.2f %.2f %.2f\n",this->Angle[1],p1[0],p1[1],p1[2]);
+      rot->Delete();
+    }
+
+  float scale=this->ScaleFactor*0.01;
+
+  vtkTransform* tr=vtkTransform::New();
+
+  int maxpass=2;
+  if (this->Angle[0]!=0.0)
+    maxpass=1;
+  
+  for (int pass=0;pass<maxpass;pass++)
+    {
+      tr->Identity();
+      tr->PostMultiply();
+      
+      // First Get it to a Local Coordinate System
+      tr->Translate(-this->Origin[0],-this->Origin[1],-this->Origin[2]);
+      tr->Concatenate(this->LocalAxisTransform);
+      
+      // Now Apply Scale, Rotations
+      tr->Scale(scale,scale,scale);
+      
+      if (maxpass==2 && pass==0)
+	tr->RotateWXYZ(1.0,p1[0],p1[1],p1[2]);
+      else
+	tr->RotateWXYZ(this->Angle[0],p1[0],p1[1],p1[2]);
+
+      // Back to Global Coordinate System
+      tr->Concatenate(this->LocalAxisTransform->GetLinearInverse());
+      tr->Translate(this->Origin);
+      
+      // Add Translation 
+      tr->Translate(this->Translation);
+      tr->Update();
+
+      double wxyz[4];  
+      tr->GetOrientationWXYZ(wxyz);
+
+      if (pass==0)
+	{
+	  for (int i=0;i<=2;i++)
+	    this->RotationAxis[i]=wxyz[i+1];
+	}
+
+      if (pass==maxpass-1)
+	{
+	  this->RotationAngle=wxyz[0];
+	  if (this->RotationAngle*this->Angle[0] < 0 )
+	    {
+	      this->RotationAngle=-wxyz[0];
+	      for (int i=0;i<=2;i++)
+		this->RotationAxis[i]=-wxyz[i+1];
+	    }
+	  while (this->RotationAngle<-180.0)
+	    this->RotationAngle+=360.0;
+	  while (this->RotationAngle>180.0)
+	    this->RotationAngle-=360.0;
+	}
+    }
+
+
+  this->SetInput(tr->GetMatrix());
+  this->Update();
+  tr->Delete();
+}*/
+//----------------------------------------------------------------------------
+void vtkpxSimilarityTransform::UpdateMatrix()
+{
+  if (this->FreezeUpdates)
+    return;
+
+
+  // Generate Rotation Transformation
+
+  float scale=this->ScaleFactor*0.01;
+
+  vtkTransform* tr=vtkTransform::New();
+  tr->Identity();
+  tr->PostMultiply();
+  
+  // First Get it to a Local Coordinate System
+  tr->Translate(-this->Origin[0],-this->Origin[1],-this->Origin[2]);
+  tr->Concatenate(this->LocalAxisTransform);
+  
+  // Now Apply Scale, Rotations
+  tr->Scale(scale,scale,scale);
+  
+  if (this->Mode==9)
+    {
+      tr->RotateZ(this->Angle[0]);
+    }
+  else
+    {
+      tr->RotateZ(this->Angle[2]);
+      tr->RotateY(this->Angle[1]);
+      tr->RotateX(this->Angle[0]);
+    }
+  
+  // Back to Global Coordinate System
+  tr->Concatenate(this->LocalAxisTransform->GetLinearInverse());
+  tr->Translate(this->Origin);
+  
+  // Add Translation 
+  tr->Translate(this->Translation);
+  tr->Update();
+
+  double wxyz[4];  
+  tr->GetOrientationWXYZ(wxyz);
+
+  for (int i=0;i<=2;i++)
+    this->RotationAxis[i]=wxyz[i+1];
+
+  this->RotationAngle=wxyz[0];
+  if (this->RotationAngle*this->Angle[0] < 0 )
+    {
+      this->RotationAngle=-wxyz[0];
+      for (int i=0;i<=2;i++)
+	this->RotationAxis[i]=-wxyz[i+1];
+    }
+
+  while (this->RotationAngle<-180.0)
+    this->RotationAngle+=360.0;
+  while (this->RotationAngle>180.0)
+    this->RotationAngle-=360.0;
+
+
+  this->SetInput(tr->GetMatrix());
+  this->Update();
+  tr->Delete();
+}
+//----------------------------------------------------------------------------
+void vtkpxSimilarityTransform::SetMode(int m)
+{
+  if (m<-1)
+    this->Mode=-1;
+  else if (m>9)
+    this->Mode=9;
+  else 
+    this->Mode=m;
+}
+//----------------------------------------------------------------------------
+int vtkpxSimilarityTransform::GetNumberOfParameters()
+{
+  switch (this->Mode)
+    {
+    case -1: // Fixed Parameters
+      return 0;
+      break;
+    case 0:  // XY Rotation Only
+      return 2;
+      break;
+    case 1:  // Rotation Only
+      return 3;
+      break;
+    case 2: // Rotation+Scale Only
+      return 4;
+      break;
+    case 3: // Rotation + Translation
+      return 6;
+      break;
+    case 4: // Rotation + Scale + Translation
+      return 7;
+      break;
+    case 5: // Rotation + Origin
+      return 6;
+      break;
+    case 6: // Rotation + Scale + Origin
+      return 7;
+      break;
+    case 7: // Rotation + Translation + Origin
+      return 9;
+    case 8: // All of them 
+      return 10;
+      break;
+    case 9: // Z-Rot Only
+      return 1;
+      break;
+    }
+  return 0;
+}
+
+//----------------------------------------------------------------------------
+void vtkpxSimilarityTransform::GetParameters(vtkDoubleArray *parameters,int InputOffset)
+{
+  int np=this->GetNumberOfParameters();
+  if (np==-1)
+    return;
+  
+  if (parameters->GetNumberOfTuples()-InputOffset<np)
+    return;
+
+  if (this->Mode==8)
+    {
+      for (int i=0;i<np;i++)
+	parameters->SetComponent(InputOffset+i,0,this->Get(i));
+    }
+  else 
+    {
+      int offset=3;
+      if (this->Mode==0)
+	offset=2;
+      else if (this->Mode==9)
+	offset=1;
+      
+      for (int i=0;i<offset;i++)
+	parameters->SetComponent(InputOffset+i,0,this->Angle[i]);
+            
+      if (this->Mode == 2 || this->Mode == 4 || this->Mode == 6)
+	{
+	  parameters->SetComponent(InputOffset+offset,0,this->ScaleFactor);
+	  ++offset;
+	}
+      
+      if (this->Mode == 3 || this->Mode == 4 || this->Mode == 7)
+	{
+	  for (int i=0;i<=2;i++)
+	    parameters->SetComponent(InputOffset+offset+i,0,this->Translation[i]*this->TranslationScale);
+	  offset+=3;
+	}
+      
+      if (this->Mode == 5 || this->Mode == 6 || this->Mode == 7 )
+	{
+	  for (int i=0;i<=2;i++)
+	    parameters->SetComponent(InputOffset+offset+i,0,this->Origin[i]);
+	}
+    }
+  return;
+}
+
+void vtkpxSimilarityTransform::SetParameters(vtkDoubleArray *parameters,int InputOffset)
+{
+  int np=this->GetNumberOfParameters();
+  if (np==-1)
+    return;
+
+  if (parameters->GetNumberOfTuples()-InputOffset<np)
+    return;
+  
+  this->FreezeUpdates=1;
+  if (this->Mode==8)
+    {
+      for (int i=0;i<np;i++)
+	this->Put(i,parameters->GetComponent(InputOffset+i,0));
+    }
+  else 
+    {
+      int offset=3;
+      if (this->Mode==0)
+	offset=2;
+      else if (this->Mode==9)
+	offset=1;
+
+      for (int i=0;i<offset;i++)
+	this->Angle[i]=parameters->GetComponent(InputOffset+i,0);
+      
+      if (this->Mode == 2 || this->Mode == 4 || this->Mode == 6)
+	{
+	  this->ScaleFactor=parameters->GetComponent(InputOffset+offset,0);
+	  ++offset;
+	}
+      
+      if (this->Mode == 3 || this->Mode == 4 || this->Mode == 7)
+	{
+	  for (int i=0;i<=2;i++)
+	    this->Translation[i]=parameters->GetComponent(InputOffset+offset+i,0)/this->TranslationScale;
+	  offset+=3;
+	}
+      
+      if (this->Mode == 5 || this->Mode == 6 || this->Mode == 7 )
+	{
+	  for (int i=0;i<=2;i++)
+	    this->Origin[i]=parameters->GetComponent(InputOffset+offset+i,0);
+	}
+    }
+  this->FreezeUpdates=0;
+  this->UpdateMatrix();
+}
+//----------------------------------------------------------------------------
+float vtkpxSimilarityTransform::Get(int i) const
+{
+  switch (i) 
+    {
+    case 0:
+      return this->Translation[0];
+      break;
+    case 1:
+      return this->Translation[1];
+      break;
+    case 2:
+      return this->Translation[2];
+      break;
+    case 3:
+      return this->Origin[0];
+      break;
+    case 4:
+      return this->Origin[1];
+      break;
+    case 5:
+      return this->Origin[2];
+      break;
+    case 6:
+      return this->Angle[0];
+      break;
+    case 7:
+      return this->Angle[1];
+      break;
+    case 8:
+      return this->Angle[2];
+      break;
+    case 9:
+      return this->ScaleFactor;
+      break;
+    default:
+      cerr << "No such dof" << i << endl;
+      return 0;
+    }
+}
+//----------------------------------------------------------------------------
+void vtkpxSimilarityTransform::Put(int i, float x)
+{
+  switch (i) 
+    {
+    case 0:
+      this->Translation[0] = x;
+      break;
+    case 1:
+      this->Translation[1] = x;
+      break;
+    case 2:
+      this->Translation[2] = x;
+      break;
+    case 3:
+      this->Origin[0] = x;
+      break;
+    case 4:
+      this->Origin[1] = x;
+      break;
+    case 5:
+      this->Origin[2] = x;
+      break;
+    case 6:
+      this->Angle[0]=x;
+      break;
+    case 7:
+      this->Angle[1]=x;
+      break;
+    case 8:
+      this->Angle[2]=x;
+      break;
+    case 9:
+      this->ScaleFactor=x;
+      if (this->ScaleFactor<1.01)
+	this->ScaleFactor=100.0;
+      break;
+    default:
+      cerr << "Put(): No such dof" << i << endl;
+      return;
+    }
+  this->UpdateMatrix();
+}
+//----------------------------------------------------------------------------
+int vtkpxSimilarityTransform::Load(const char* fname)
+{
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  int ok=this->Load(fin);
+  gzclose(fin);
+  return ok;
+}
+
+int vtkpxSimilarityTransform::Load(gzFile fin)
+{
+  char pxtk_buffer[101];
+  gzgets(fin,pxtk_buffer,100);
+  
+  if (gzfindstringinstring(pxtk_buffer,"#vtkpxSimilarityTransform")==0)
+    return 0;
+
+  gzgets(fin,pxtk_buffer,100);
+
+  int tmp;
+  float v;
+  this->FreezeUpdates=1;
+
+  gzgets(fin,pxtk_buffer,200);   gzgets(fin,pxtk_buffer,200); 
+  sscanf(pxtk_buffer,"%f %f %f",&this->Angle[0],&this->Angle[1],&this->Angle[2]);
+
+  gzgets(fin,pxtk_buffer,200);   gzgets(fin,pxtk_buffer,200); 
+  sscanf(pxtk_buffer,"%f %f %f",&this->Translation[0],&this->Translation[1],&this->Translation[2]);
+
+  gzgets(fin,pxtk_buffer,200);   gzgets(fin,pxtk_buffer,200); 
+  sscanf(pxtk_buffer,"%f %f %f",&this->Origin[0],&this->Origin[1],&this->Origin[2]);
+
+  float x[3],z[3];   
+  gzgets(fin,pxtk_buffer,200);   gzgets(fin,pxtk_buffer,200);   sscanf(pxtk_buffer,"%f %f %f",&x[0],&x[1],&x[2]);
+  gzgets(fin,pxtk_buffer,200);   gzgets(fin,pxtk_buffer,200);   sscanf(pxtk_buffer,"%f %f %f",&z[0],&z[1],&z[2]);
+  this->SetLocalXZAxis(x,z);
+
+  gzgets(fin,pxtk_buffer,200);   gzgets(fin,pxtk_buffer,200); 
+  sscanf(pxtk_buffer,"%f",&this->ScaleFactor);
+
+  gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+  sscanf(pxtk_buffer,"%d",&tmp);
+  this->SetMode(tmp);
+  this->FreezeUpdates=0;
+
+  this->UpdateMatrix();
+
+  return 1;
+}
+//----------------------------------------------------------------------------
+int vtkpxSimilarityTransform::Save(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+    return 0;
+  
+  int ok=this->Save(fout);
+  fclose(fout);
+  return ok;
+}
+
+int vtkpxSimilarityTransform::Save(FILE* fout)
+{
+  fprintf(fout,"#vtkpxSimilarityTransform2\n");
+  fprintf(fout,"#Actual Parameters\n");
+  fprintf(fout,"#Rotation\n %.4f %.4f %.4f\n",this->Angle[0],this->Angle[1],this->Angle[2]);
+  fprintf(fout,"#Translation\n %.4f %.4f %.4f\n",this->Translation[0],this->Translation[1],this->Translation[2]);
+  fprintf(fout,"#Origin\n %.4f %.4f %.4f\n",this->Origin[0],this->Origin[1],this->Origin[2]);
+  fprintf(fout,"#LocalXAxis\n %.4f %.4f %.4f\n",this->LocalXAxis[0],this->LocalXAxis[1],this->LocalXAxis[2]);
+  fprintf(fout,"#LocalZAxis\n %.4f %.4f %.4f\n",this->LocalZAxis[0],this->LocalZAxis[1],this->LocalZAxis[2]);
+  fprintf(fout,"#Scale\n %.4f\n",this->ScaleFactor);
+  fprintf(fout,"#Mode\n%d\n",this->Mode);
+  return 1;
+}
+//----------------------------------------------------------------------------
+void vtkpxSimilarityTransform::Initialize()
+{
+  this->FreezeUpdates=1;
+  this->ScaleFactor=100.0;
+  for (int i=0;i<=2;i++)
+    {
+      this->Origin[i]=0.0; 
+      this->Angle[i]=0.0;
+      this->Translation[i]=0.0;
+    }
+  this->FreezeUpdates=0;
+}
+//----------------------------------------------------------------------------
+void vtkpxSimilarityTransform::Identity()
+{
+  this->ScaleFactor=100.0;
+  for (int i=0;i<=2;i++)
+    {
+      this->Angle[i]=0.0;
+      this->Translation[i]=0.0;
+    }
+  this->UpdateMatrix();
+}
+//----------------------------------------------------------------------------
+void vtkpxSimilarityTransform::Copy(vtkpxSimilarityTransform* other)
+{
+  if (other==NULL)
+    return;
+
+  this->FreezeUpdates=1;
+  for (int i=3;i<=5;i++)
+    this->Put(i,other->Get(i));
+  
+  this->SetLocalXZAxis(other->GetLocalXAxis(),other->GetLocalZAxis());
+  this->CopyParameters(other);
+}
+
+void vtkpxSimilarityTransform::CopyParameters(vtkpxSimilarityTransform* other)
+{
+  if (other==NULL)
+    return;
+
+  this->FreezeUpdates=1;
+  for (int i=0;i<10;i++)
+    if (i<3 || i > 5)
+      this->Put(i,other->Get(i));
+
+  this->SetTranslationScale(this->GetTranslationScale());
+
+  this->FreezeUpdates=0;
+  this->UpdateMatrix();
+}
+
+//----------------------------------------------------------------------------
+void vtkpxSimilarityTransform::ApproximatePoints(vtkPoints* SourceLandmarks,vtkPoints* TargetLandmarks,vtkpxMatrix* Weights)
+{
+  int j;
+
+  if (SourceLandmarks == NULL || TargetLandmarks == NULL)
+    return;
+
+  // --- compute the necessary transform to match the two sets of landmarks ---
+
+  /*
+    The solution is based on
+    Berthold K. P. Horn (1987),
+    "Closed-form solution of absolute orientation using unit quaternions,"
+    Journal of the Optical Society of America A, 4:629-642
+  */
+
+  // Original python implementation by David G. Gobbi
+  // Weight Stuff added by Xenios Papademetris
+  // Moved out of vtkpxWeightedLandamarkTransform to Support Offsets etc.
+  // Center of Rotation is now the the Origin[3] not the centroid of the points
+  // No alignment by matching centroids etc
+
+  const vtkIdType N_PTS = SourceLandmarks->GetNumberOfPoints();
+  if (N_PTS < 3)
+    return;
+
+  if(N_PTS != TargetLandmarks->GetNumberOfPoints())
+    {
+      vtkErrorMacro(<<"Update: Source and Target Landmarks contain a different number of points");
+      return;
+    }
+
+  if (Weights!=NULL)
+    {
+      if(N_PTS != Weights->GetSize()[0] || Weights->GetSize()[1]!=1)
+	{
+	  vtkDebugMacro(<<"Update: Source Landmarks and Weight Matrix contain a different number of points");
+	  Weights=NULL;
+	}
+    }
+
+
+  // -- if no points, stop here
+
+
+  vtkDebugMacro(<<"Using Weighted Least Squares Landmark Fitting\n");
+  
+  // -- find the centroid of each set --
+
+  // No more centroid stuff, rotation is about a fixed point i.e. Origin[3]
+  float source_centroid[3]={0,0,0};
+  float target_centroid[3]={0,0,0};
+
+
+  for(int i=0;i<N_PTS;i++)
+    {
+      double* p;
+      p = SourceLandmarks->GetPoint(i);
+      source_centroid[0] += p[0];
+      source_centroid[1] += p[1];
+      source_centroid[2] += p[2];
+      p = TargetLandmarks->GetPoint(i);
+
+      target_centroid[0] += p[0];
+      target_centroid[1] += p[1];
+      target_centroid[2] += p[2];
+    }
+  source_centroid[0] /= float(N_PTS);
+  source_centroid[1] /= float(N_PTS);
+  source_centroid[2] /= float(N_PTS);
+  target_centroid[0] /= float(N_PTS);
+  target_centroid[1] /= float(N_PTS);
+  target_centroid[2] /= float(N_PTS);
+
+
+  // -- build the 3x3 matrix M --
+  float M[3][3];
+  float AAT[3][3];
+  for(int i=0;i<3;i++) 
+    {
+      AAT[i][0] = M[i][0]=0.0F; // fill M with zeros
+      AAT[i][1] = M[i][1]=0.0F; 
+      AAT[i][2] = M[i][2]=0.0F; 
+    }
+
+  vtkIdType pt;
+  double a[3],b[3];
+  float sa=0.0F,sb=0.0F;
+  for(pt=0;pt<N_PTS;pt++)
+    {
+      float wgt=1.0;
+      if (Weights!=NULL)
+	wgt=Weights->GetDirectElement(pt,0);
+
+
+      // get the origin-centred point (a) in the source set
+      SourceLandmarks->GetPoint(pt,a);
+      TargetLandmarks->GetPoint(pt,b);
+
+      for (int ia=0;ia<=2;ia++)
+	{
+	  if (this->Mode < 5 )
+	    {
+	      a[ia]-=this->Origin[ia];
+	      b[ia]-=this->Origin[ia];
+	    }
+	  else
+	    {
+	      a[ia]-=source_centroid[ia];
+	      b[ia]-=target_centroid[ia];
+	      this->Origin[ia]=0.0;
+	    }
+	}
+      // accumulate the products a*T(b) into the matrix M
+      for(int i=0;i<3;i++) 
+	{
+	  M[i][0] += wgt*a[i]*b[0];
+	  M[i][1] += wgt*a[i]*b[1];
+	  M[i][2] += wgt*a[i]*b[2];
+	}
+      // accumulate scale factors (if desired)
+      sa += wgt*(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
+      sb += wgt*(b[0]*b[0]+b[1]*b[1]+b[2]*b[2]);
+    }
+  
+  // compute required scaling factor (if desired)
+  float scale = (float)sqrt(sb/sa);
+  
+  // -- build the 4x4 matrix N --
+  
+  float Ndata[4][4];
+  float *N[4];
+  for(int i=0;i<4;i++)
+    {
+      N[i] = Ndata[i];
+      N[i][0]=0.0F; // fill N with zeros
+      N[i][1]=0.0F;
+      N[i][2]=0.0F;
+      N[i][3]=0.0F;
+    }
+  // on-diagonal elements
+  N[0][0] = M[0][0]+M[1][1]+M[2][2];
+  N[1][1] = M[0][0]-M[1][1]-M[2][2];
+  N[2][2] = -M[0][0]+M[1][1]-M[2][2];
+  N[3][3] = -M[0][0]-M[1][1]+M[2][2];
+  // off-diagonal elements
+  N[0][1] = N[1][0] = M[1][2]-M[2][1];
+  N[0][2] = N[2][0] = M[2][0]-M[0][2];
+  N[0][3] = N[3][0] = M[0][1]-M[1][0];
+  
+  N[1][2] = N[2][1] = M[0][1]+M[1][0];
+  N[1][3] = N[3][1] = M[2][0]+M[0][2];
+  N[2][3] = N[3][2] = M[1][2]+M[2][1];
+  
+  // -- eigen-decompose N (is symmetric) --
+  
+  float eigenvectorData[4][4];
+  float *eigenvectors[4],eigenvalues[4];
+  
+  eigenvectors[0] = eigenvectorData[0];
+  eigenvectors[1] = eigenvectorData[1];
+  eigenvectors[2] = eigenvectorData[2];
+  eigenvectors[3] = eigenvectorData[3];
+  
+  vtkMath::JacobiN(N,4,eigenvalues,eigenvectors);
+  
+  // the eigenvector with the largest eigenvalue is the quaternion we want
+  // (they are sorted in decreasing order for us by JacobiN)
+  double w,x,y,z;
+  
+  // first: if points are collinear, choose the quaternion that 
+  // results in the smallest rotation.
+  if (eigenvalues[0] == eigenvalues[1])
+    {
+      double s0[3],t0[3],s1[3],t1[3];
+      SourceLandmarks->GetPoint(0,s0);
+      TargetLandmarks->GetPoint(0,t0);
+
+      SourceLandmarks->GetPoint(1,s1);
+      TargetLandmarks->GetPoint(1,t1);
+
+      double ds[3],dt[3];
+      double rs = 0, rt = 0;
+      for (int i = 0; i < 3; i++)
+	{
+	  ds[i] = s1[i] - s0[i];      // vector between points
+	  rs += ds[i]*ds[i];
+	  dt[i] = t1[i] - t0[i];
+	  rt += dt[i]*dt[i];
+	}
+      
+      // normalize the two vectors
+      rs = sqrt(rs);
+      ds[0] /= rs; ds[1] /= rs; ds[2] /= rs; 
+      rt = sqrt(rt);
+      dt[0] /= rt; dt[1] /= rt; dt[2] /= rt; 
+      
+      // take dot & cross product
+      w = ds[0]*dt[0] + ds[1]*dt[1] + ds[2]*dt[2];
+      x = ds[1]*dt[2] - ds[2]*dt[1];
+      y = ds[2]*dt[0] - ds[0]*dt[2];
+      z = ds[0]*dt[1] - ds[1]*dt[0];
+      
+      double r = sqrt(x*x + y*y + z*z);
+      double theta = atan2(r,w);
+      
+      // construct quaternion
+      w = cos(theta/2);
+      if (r != 0)
+	{
+	  r = sin(theta/2)/r;
+	  x = x*r;
+	  y = y*r;
+	  z = z*r;
+	}
+      else // rotation by 180 degrees: special case
+	{
+	  // rotate around a vector perpendicular to ds
+	  vtkMath::Perpendiculars(ds,dt,0,0);
+	  r = sin(theta/2);
+	  x = dt[0]*r;
+	  y = dt[1]*r;
+	  z = dt[2]*r;
+	}
+    }
+  else // points are not collinear
+    {
+      w = eigenvectors[0][0];
+      x = eigenvectors[1][0];
+      y = eigenvectors[2][0];
+      z = eigenvectors[3][0];
+    }
+      
+  // convert quaternion to a rotation matrix
+  
+  double ww = w*w;
+  double wx = w*x;
+  double wy = w*y;
+  double wz = w*z;
+  
+  double xx = x*x;
+  double yy = y*y;
+  double zz = z*z;
+  
+  double xy = x*y;
+  double xz = x*z;
+  double yz = y*z;
+
+
+  // Step 1 Get Rotation 
+  // -------------------
+  vtkMatrix4x4* fitMatrix=vtkMatrix4x4::New();
+  fitMatrix->Identity();
+  fitMatrix->Element[0][0] = ww + xx - yy - zz; 
+  fitMatrix->Element[1][0] = 2.0*(wz + xy);
+  fitMatrix->Element[2][0] = 2.0*(-wy + xz);
+  
+  fitMatrix->Element[0][1] = 2.0*(-wz + xy);  
+  fitMatrix->Element[1][1] = ww - xx + yy - zz;
+  fitMatrix->Element[2][1] = 2.0*(wx + yz);
+  
+  fitMatrix->Element[0][2] = 2.0*(wy + xz);
+  fitMatrix->Element[1][2] = 2.0*(-wx + yz);
+  fitMatrix->Element[2][2] = ww - xx - yy + zz;
+  
+  
+  // First Get Angles 
+  vtkTransform* tr=vtkTransform::New();
+  tr->SetMatrix(fitMatrix);
+  tr->GetOrientation(this->Angle);
+  tr->Delete();
+  
+  if (this->Mode ==2 || this->Mode == 4 || this->Mode == 7)
+    { 
+      this->ScaleFactor=scale*100.0;
+      for(int i=0;i<3;i++) 
+	{
+	  fitMatrix->Element[i][0] *= scale;
+	  fitMatrix->Element[i][1] *= scale;
+	  fitMatrix->Element[i][2] *= scale;
+	}
+    }
+  
+  // the translation is given by the difference in the transformed source
+  // centroid and the target centroid
+  double sx, sy, sz;
+  
+  sx = fitMatrix->Element[0][0] * source_centroid[0] +
+    fitMatrix->Element[0][1] * source_centroid[1] +
+    fitMatrix->Element[0][2] * source_centroid[2];
+  sy = fitMatrix->Element[1][0] * source_centroid[0] +
+    fitMatrix->Element[1][1] * source_centroid[1] +
+    fitMatrix->Element[1][2] * source_centroid[2];
+  sz = fitMatrix->Element[2][0] * source_centroid[0] +
+    fitMatrix->Element[2][1] * source_centroid[1] +
+    fitMatrix->Element[2][2] * source_centroid[2];
+  
+  this->Translation[0] = target_centroid[0] - sx;
+  this->Translation[1] = target_centroid[1] - sy;
+  this->Translation[2] = target_centroid[2] - sz;
+
+  fitMatrix->Delete();
+  this->UpdateMatrix();
+}
+
+// -------------------------------------------------------------------------------------
+vtkPolyData* vtkpxSimilarityTransform::CreateBlendedCylinder(vtkPolyData* input,float angle,int mode)
+{
+  if (input==NULL)
+    return NULL;
+
+  double radcon=180.0/vtkMath::Pi();
+
+  for (float a=-1.0;a<=1.0;a+=2.0)
+    for (float b=-1.0;b<=1.0;b+=2.0)
+      {
+	fprintf(stderr,"a=%.1f b=%.1f angle=%.2f\n",a,b,
+		radcon*atan2(b,a));
+      }
+
+
+
+  double bounds[6]; input->GetBounds(bounds);
+
+  if (mode<0)
+    mode=0;
+  else if (mode>2)
+    mode=2;
+
+  double radangle=fabs(angle)/radcon;
+
+  double centroid[3];
+  for (int i=0;i<=2;i++)
+    centroid[i]=0.5*(bounds[i*2]+bounds[i*2+1]);
+
+  fprintf(stderr,"Centroid =%.2f %.2f %.2f\n",centroid[0],centroid[1],centroid[2]);
+
+  vtkPolyData* output=vtkPolyData::New();
+  output->DeepCopy(input);
+  
+
+  double c1= 0.25/pow(radangle,2.0);
+  double c2=-0.75/radangle;
+
+  int np=output->GetNumberOfPoints();
+
+  if (radangle==0.0)
+    np=0;
+
+  for (int i=0;i<np;i++)
+    {
+      double x[3]; output->GetPoint(i,x);
+      
+      // First subtract centroid
+      for (int ia=0;ia<=2;ia++)
+	x[ia]=x[ia]-centroid[ia];
+
+      if (i==np/2)
+	fprintf(stderr,"x=(%.2f,%.2f,%.2f) \t ",x[0],x[1],x[2]);
+
+      double r=sqrt(x[0]*x[0]+x[2]*x[2]);
+      double theta=atan2(x[2],x[0]);
+
+
+      if (i==np/2)
+	fprintf(stderr,"x=(r=%.2f,theta=%.2f) \t ",r,theta*radcon);
+
+      // 3 Cases
+      
+
+      if (mode==0)
+	{
+	  if (x[2]>0)
+	    theta-=radangle;
+	}
+      else if (mode==1)
+	{
+	  if (theta>radangle)
+	    theta-=radangle;
+	  else if (theta<-radangle)
+	    theta=theta;
+	  else
+	    theta= c1*pow(theta,3.0)+0.25*theta-0.5*radangle;
+	}
+      else if (mode ==2 )
+	{
+	  if (theta>2.0*radangle)
+	    theta-=radangle;
+	  else if (theta<=0.0)
+	    theta=theta;
+	  else
+	    theta= c1*pow(theta,3.0)+c2*pow(theta,2.0)+theta;
+	}
+    
+      x[0]=r*cos(theta);
+      x[2]=r*sin(theta);
+
+      if (i==np/2)
+	fprintf(stderr,"(r=%.2f,theta=%.2f) (%.1f,%.1f,%.1f)\n",r,theta*radcon,x[0],x[1],x[2]);
+
+      
+      for (int ia=0;ia<=2;ia++)
+	x[ia]=x[ia]+centroid[ia];
+      
+      output->GetPoints()->SetPoint(i,x);
+    }
+
+  return output;
+}
+
diff --git a/bioimagesuite30_src/Registration/vtkpxSimilarityTransform.h b/bioimagesuite30_src/Registration/vtkpxSimilarityTransform.h
new file mode 100644
index 0000000..ed67f34
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxSimilarityTransform.h
@@ -0,0 +1,185 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkpxSimilarityTransform - describes linear transformations via a 4x4 matrix
+// .SECTION Description
+// This generates a similarity/rigid transform based on
+// (a) center of rotation (3 params)
+// (b) scaling parameter (1 param)
+// (c) roation angles (3 params)
+// (d) translation (3 params)
+// (e) additional transformation (vtkMatrixToLinearTransform)
+//
+// 
+
+#ifndef __vtkpxSimilarityTransform_h
+#define __vtkpxSimilarityTransform_h
+
+#include "vtkMatrixToLinearTransform.h"
+#include "vtkMatrix4x4.h"
+#include "vtkDoubleArray.h"
+#include "vtkLinearTransform.h"
+#include "vtkpxMatrix.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "pxutil.h"
+
+
+class vtkpxSimilarityTransform : public vtkMatrixToLinearTransform
+{
+ public:
+  static vtkpxSimilarityTransform *New();
+  vtkTypeMacro(vtkpxSimilarityTransform,vtkMatrixToLinearTransform);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Set the parameters from array
+  // This is key for Optimization Classes 
+  void SetParameters(vtkDoubleArray *parameters,int InputOffset=0);
+  void GetParameters(vtkDoubleArray *parameters,int InputOffset=0);
+  
+  // Description:  
+  // Mode determines how Set/Get Parameters Operate, all other elements are active but fixed
+  // i.e. fixed scale DOES not mean no scaling
+  virtual  void SetModeToRotationXYOnly()  { this->SetMode(0); }
+  virtual  void SetModeToRotationOnly()  { this->SetMode(1); }
+  virtual  void SetModeToRotationScale() { this->SetMode(2); }
+  virtual  void SetModeToRotationTranslation() { this->SetMode(3); }
+  virtual  void SetModeToRotationScaleTranslation() { this->SetMode(4); }
+  virtual  void SetModeToRotationOrigin() { this->SetMode(5); }
+  virtual  void SetModeToRotationScaleOrigin() { this->SetMode(6); }
+  virtual  void SetModeToRotationTranlationOrigin() { this->SetMode(7); }
+  virtual  void SetModeToAll() { this->SetMode(8); }
+  virtual  void SetModeToZRotationOnly() { this->SetMode(9); }
+  virtual  void SetModeToFixedParameters() { this->SetMode(-1); }
+  vtkGetMacro(Mode,int);
+  virtual void SetMode(int m);
+
+  // Description:
+  // Puts a transformation parameter (transformation matrix is updated)
+  void   Put(int, float);
+  void   Set(int a, float v) {  Put(a,v);}
+  /// Gets a transformation parameter
+  float Get(int) const;
+
+  // Description:
+  // Stop Auto Updates
+  vtkSetClampMacro(FreezeUpdates,int,0,1);
+  vtkGetMacro(FreezeUpdates,int);
+
+  // Description:
+  // Load / Save Transformation
+  virtual int Load(const char* fname);
+  virtual int Load(gzFile fin);
+
+  virtual int Save(const char* fname);
+  virtual int Save(FILE* fout);
+
+  // Description:
+  // Set To Identity
+  virtual void Identity();
+
+
+  // Description:
+  // Number Of Parameters
+  virtual int GetNumberOfParameters();
+
+  // Description:
+  // Set Initialize
+  virtual void Initialize();
+
+  // Description:
+  // Copy
+  virtual void Copy(vtkpxSimilarityTransform* other);
+  virtual void CopyParameters(vtkpxSimilarityTransform* other);
+
+  // Description:
+  // Point Fitting
+  void ApproximatePoints(vtkPoints* SourceLandmarks,vtkPoints* TargetLandmarks,vtkpxMatrix* Weights);
+		
+  // Description:
+  // Forces Parameter Updates
+  virtual void UpdateMatrix();
+
+
+  // Description:
+  // BlendedCylinder
+  // mode=0 no-blend, 1=symmetric blend, 2=causal blend
+  static vtkPolyData* CreateBlendedCylinder(vtkPolyData* input,float angle,int mode);
+
+  // Description:
+  // Z-Axis : can 
+  vtkGetVectorMacro(LocalZAxis,float,3);
+  vtkGetVectorMacro(LocalXAxis,float,3);
+  virtual void SetLocalXZAxis(float x[3],float z[3]);
+
+  // Description:
+  // Access Internal Numbers
+  vtkGetVectorMacro(Origin,float,3);
+  vtkGetVectorMacro(RotationAxis,float,3);
+  vtkGetMacro(RotationAngle,float);
+
+
+  // Description:
+  // Translation Scale == size of voxel in mm
+  vtkGetMacro(TranslationScale,float);
+  vtkSetClampMacro(TranslationScale,float,0.001,10.0);
+  
+protected:
+  vtkpxSimilarityTransform ();
+  virtual ~vtkpxSimilarityTransform ();
+
+//BTX
+  /// Scaling along the x-axis, y-axis, z-axis
+  float ScaleFactor;
+  float Origin[3];
+  float Angle[3];
+  float Translation[3];
+  float LocalZAxis[3];
+  float LocalXAxis[3];
+  int   FreezeUpdates;
+  int   Mode;
+  float TranslationScale;
+  vtkMatrixToLinearTransform* LocalAxisTransform;
+
+  // Keep this also
+  // --------------
+  float RotationAngle;
+  float RotationAxis[3];
+
+//ETX
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxSparseMatrix.cpp b/bioimagesuite30_src/Registration/vtkpxSparseMatrix.cpp
new file mode 100644
index 0000000..c8a0337
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxSparseMatrix.cpp
@@ -0,0 +1,466 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSparseMatrix.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/10/29 19:34:42 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxSparseMatrix.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxUtil.h"
+#include "pxutil.h"
+
+// -----------------------------------------------------------------------------------
+
+vtkpxSparseMatrix* vtkpxSparseMatrix::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxSparseMatrix");
+  if(ret)
+      {
+	return (vtkpxSparseMatrix*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxSparseMatrix;
+}
+
+// -----------------------------------------------------------------------------------
+vtkpxSparseMatrix::vtkpxSparseMatrix()
+{
+  this->Size[0]=0;
+  this->Size[1]=0;
+}
+// -----------------------------------------------------------------------------------
+vtkpxSparseMatrix::~vtkpxSparseMatrix()
+{
+  this->Matrix.cleanup();
+}
+// -----------------------------------------------------------------------------------
+// Some in-line stuff 
+
+void vtkpxSparseMatrix::Zeros(int rows,int cols) 
+{
+  Allocate(rows,cols); 
+  Fill(0.0);
+}
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::Ones(int rows,int cols)  
+{ 
+  Allocate(rows,cols); 
+  Fill(1.0); 
+}
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::Eye(int rowcol)
+{
+  Allocate(rowcol,rowcol) ; 
+  Identity(); 
+}
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::Allocate(int rows,int columns)
+{
+  this->Matrix.cleanup();
+  this->Size[0]=rows;
+  this->Size[1]=columns;
+
+}
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::Identity()
+{
+  if (this->Size[0]!=this->Size[1])
+    return;
+
+  this->Zero();
+  for (int i=0;i<this->Size[0];i++)
+    this->SetDirectElement(i,i,1.0);
+}
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::Zero()
+{ 
+  this->Matrix.cleanup();
+}
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::Fill(float v)
+{
+  for (int i=0;i<this->Size[0];i++)
+    for (int j=0;j<this->Size[1];j++)
+      this->SetDirectElement(i,j,v);
+}
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::Print(const char* message)
+{
+  fprintf(stdout,"\n %s =\n",message);
+  this->Matrix.setindices(this->Size);
+  this->Matrix.print(0);
+  fprintf(stdout,"\n");
+}
+
+// -----------------------------------------------------------------------------------
+float vtkpxSparseMatrix::Density()
+{
+  int total=this->Size[0]*this->Size[1];
+  if (total<1)
+    return 0.0;
+  
+  return float(this->Matrix.totalsize())/float(total);
+}
+
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::InternalPrint()
+{
+  if (this->Size[0]>0 && this->Size[1]>0)
+    {
+      this->Matrix.setindices(this->Size);
+      this->Matrix.print(0);
+    }
+}
+
+void vtkpxSparseMatrix::PrintBW()
+{
+  if (this->Size[0]>0 && this->Size[1]>0)
+    {
+      this->Matrix.setindices(this->Size);
+      this->Matrix.printbw(0);
+    }
+}
+// -----------------------------------------------------------------------------------
+float vtkpxSparseMatrix::GetElement(int i,int j)
+{
+  if (this->Size[0]>0 && this->Size[1]>0)
+    {
+      i=Irange(i,0,this->Size[0]-1);
+      j=Irange(j,0,this->Size[1]-1);
+      return (this->Matrix)[i][j];
+    }
+  return 0.0;
+}
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::SetElement(int i,int j,float v)
+{
+  if (this->Size[0]>0 && this->Size[1]>0)
+    {
+      i=Irange(i,0,this->Size[0]-1);
+      j=Irange(j,0,this->Size[1]-1);
+      (this->Matrix)[i][j]=v;
+    }
+}
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::AddToElement(int i,int j,float v)
+{
+  if (this->Size[0]>0 && this->Size[1]>0)
+    {
+      i=Irange(i,0,this->Size[0]-1);
+      j=Irange(j,0,this->Size[1]-1);
+      float v1=(this->Matrix)[i][j];
+      (this->Matrix)[i][j]=v1+v;
+    }
+}
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::Add(vtkpxSparseMatrix* a,vtkpxSparseMatrix* b,vtkpxSparseMatrix* c)
+{
+  vtkpxSparseMatrix::Add(1.0,a,1.0,b,c);
+}
+
+void vtkpxSparseMatrix::Scale(float s)
+{
+  this->Matrix.scale(s);
+
+}
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::Add(float wa,vtkpxSparseMatrix* a,float wb,vtkpxSparseMatrix* b,vtkpxSparseMatrix* c)
+{
+
+  int s1[2],s2[2];
+  a->GetSize(s1);
+  b->GetSize(s2);
+
+  if (s1[1]!=s2[1] || s1[0]!=s2[0])
+    {
+      fprintf(stderr,"Cannot add matrices bad size %f*a=%dx%d, %f*b=%dx%d!\n",wa,s1[0],s1[1],wb,s2[0],s2[1]);
+      return;
+    }
+  
+  c->Allocate(s1[0],s1[1]);
+
+  /*  dvSparseMatrix<float> A=*(a->GetMatrixPointer());
+  dvSparseMatrix<float> B=*(b->GetMatrixPointer());
+  dvSparseMatrix<float> C=*(c->GetMatrixPointer());*/
+  
+  dvSparseMatrix A=*(a->GetMatrixPointer());
+  dvSparseMatrix B=*(b->GetMatrixPointer());
+  dvSparseMatrix C=*(c->GetMatrixPointer());
+  
+  for(int i=0;i<s1[0];i++)
+    for(int j=0;j<s2[0];j++)
+	A[i][j]=wa*B[i][j]+wb*B[i][j];
+
+}
+
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::Multiply(vtkpxSparseMatrix* a,vtkpxMatrix* b,vtkpxMatrix* c)
+{
+  int s1[2],s2[2],s3[2];
+  a->GetSize(s1);
+  b->GetSize(s2);
+
+  if (s1[1]!=s2[0])
+    {
+      fprintf(stderr,"Cannot multiply matrices bad size! a=%dx%d, b=%dx%d\n",s1[0],s1[1],s2[0],s2[1]);
+      return;
+    }
+
+  c->Allocate(s1[0],s2[1]);
+  c->GetSize(s3);
+
+  //  dvSparseMatrix<float> A=*(a->GetMatrixPointer());
+  dvSparseMatrix A=*(a->GetMatrixPointer());
+  float* b_pointer=b->GetMatrixPointer();
+  float* c_pointer=c->GetMatrixPointer();
+  float* C=&c_pointer[0];
+
+  for(int col = 0; col < s3[1]; col++) 
+    {
+      for(int row = 0; row < s3[0]; row++) 
+	{
+	  float* B=&b_pointer[col*s2[0]];
+	  *C=0;
+	  for(int i = 0; i < s1[1]; i++)
+	    {
+	      (*C)+=A[row][i]*(*B);
+	      ++B;
+	    }
+	  ++C;
+	}
+    }
+}
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::MultiplyThisWith(vtkpxMatrix* b,vtkpxMatrix* c)
+{
+  int s1[2];
+  this->GetSize(s1);
+
+  
+  int s2[2],s3[2];
+  b->GetSize(s2);
+    
+  if (s1[1]!=s2[0])
+    {
+      fprintf(stderr,"Cannot multiply matrices bad size! a=%dx%d, b=%dx%d\n",s1[0],s1[1],s2[0],s2[1]);
+      return;
+    }
+    
+  c->Allocate(s1[0],s2[1]);
+  c->GetSize(s3);
+
+
+  float* sum=new float[s3[1]];
+  for (int j=0;j<s3[1];j++)
+    sum[j]=0.0;
+
+  std::map<unsigned long,dvSparseRow>::iterator iter = this->Matrix.rows_.begin();    
+  
+  
+
+  while (iter!=this->Matrix.rows_.end())
+    {
+      std::map<unsigned long,float>::iterator i = (*iter).second.columns_.begin();    
+      while (i != (*iter).second.columns_.end())                    
+	{
+	  for(int col = 0; col < s3[1]; col++) 
+	    sum[col]+=(*i).second*b->GetDirectElement((*i).first,col);
+	  ++i;
+	}
+      for(int col = 0; col < s3[1]; col++) 
+	c->SetDirectElement((*iter).first,col,sum[col]);
+      ++iter;
+    }
+
+  delete [] sum;
+}
+
+// -----------------------------------------------------------------------------------
+// RPM Code
+// -----------------------------------------------------------------------------------
+void vtkpxSparseMatrix::MapPoints(vtkpxMatrix* Y,vtkpxMatrix* VY)
+{
+  int size[2];  this->GetSize(size);
+
+  if (Y->GetSize()[0] != size[1] || Y->GetSize()[1]!=4)
+    {
+      vtkErrorMacro(<<"Bad Matrices to Map Points");
+      return;
+    }
+
+  if (VY->GetSize()[0]!=size[0] || VY->GetSize()[1]!=4)
+    VY->Zeros(size[0],4);
+
+  if (this->Debug) 
+    fprintf(stderr,"Mapping Points %dx%d ...",size[0],size[1]);
+  
+  for (int row=0;row<size[0];row++)
+    {
+      float sum=this->Matrix[row].getsum();
+      if (sum<0.0001)
+	sum=0.0001;
+      float scale=1.0/sum;
+      this->Matrix[row].multiplywith3vector(row,Y,VY,scale);
+      VY->SetDirectElement(row,3,1.0);
+    }
+  if (this->Debug) 
+    fprintf(stderr,"done\n");
+}
+
+
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+void vtkpxSparseMatrix::NormalizeMixtureMatrix(vtkpxMatrix* M_Outliers_Row)
+{
+  int size[2];
+  this->GetSize(size);
+  if (this->Debug) 
+    fprintf(stderr,"Normalizing Distance Matrix %dx%d ...",size[0],size[1]);
+
+  float* sum=new float[size[1]];
+  for (int i=0;i<size[1];i++)
+    sum[i]=0.0;
+
+  for (int row=0;row<size[0];row++)
+    this->Matrix[row].addtosum(sum);
+
+  for (int column=0;column<size[1];column++)
+    {
+      sum[column]+=M_Outliers_Row->GetElement(0,column);
+      if (sum[column]<0.0001)
+	sum[column]=0.0001;
+      sum[column]=1.0/sum[column];
+    }
+  
+  for (int r=0;r<size[0];r++)
+    this->Matrix[r].scalebyarray(sum);
+
+  delete [] sum;
+
+  if (this->Debug) 
+    fprintf(stderr,"done\n");
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+void vtkpxSparseMatrix::NormalizeRPMMatrix(vtkpxMatrix* M_Outliers_Row,vtkpxMatrix* M_Outliers_Column)
+{
+  int size[2];
+  this->GetSize(size);
+
+  if (this->Debug) 
+    fprintf(stderr,"RPM Normalizing Distance Matrix %dx%d ...",size[0],size[1]);
+
+
+  int   norm_maxit     = 10;
+  int   row,column;
+  float* sumcols=new float[size[1]];
+
+
+  /*  this->Print("Original");
+      M_Outliers_Row->Print("Original Row");
+      M_Outliers_Column->Print("Original Column");*/
+
+  int norm_it = 1;
+  while (norm_it <= norm_maxit)
+    {
+      //fprintf(stderr,"\n --------------- Iteration %d --------------------\n",norm_it);
+      // --- Row normalization --------------------------------------------
+      for (row=0;row<size[0];row++)
+	{
+	  float sumrow=this->Matrix[row].getsum();
+	  sumrow+=M_Outliers_Column->GetElement(row,0);
+
+	  if (sumrow<0.0001)
+	    sumrow=0.0001;
+	  sumrow=1.0/sumrow;
+	  
+	  this->Matrix[row].scale(sumrow);
+	  M_Outliers_Column->SetElement(row,0,M_Outliers_Column->GetElement(row,0)*sumrow);
+	}
+
+      /*this->Print("Normalized");
+	M_Outliers_Column->Print("Column");*/
+
+      
+      // --- Column normalization -----------------------------------------
+      for (column=0;column<size[1];column++)
+	sumcols[column]=0.0;
+      
+      for (row=0;row<size[0];row++)
+	this->Matrix[row].addtosum(sumcols);
+            
+      for (column=0;column<size[1];column++)
+	{
+	  sumcols[column]+=M_Outliers_Row->GetElement(0,column);
+	  if (sumcols[column]<0.0001)
+	    sumcols[column]=0.0001;
+	  sumcols[column]=1.0/sumcols[column];
+	  M_Outliers_Row->SetElement(0,column,M_Outliers_Row->GetElement(0,column)*sumcols[column]);
+	}
+  
+      for (row=0;row<size[0];row++)
+	this->Matrix[row].scalebyarray(sumcols);
+    
+
+      /*this->Print("Normalized");
+	M_Outliers_Row->Print("Row");*/
+
+      norm_it = norm_it + 1;
+    }
+
+  delete [] sumcols;
+
+  if (this->Debug) 
+    fprintf(stderr,"done\n");
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+
diff --git a/bioimagesuite30_src/Registration/vtkpxSparseMatrix.h b/bioimagesuite30_src/Registration/vtkpxSparseMatrix.h
new file mode 100644
index 0000000..af7904d
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxSparseMatrix.h
@@ -0,0 +1,172 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSparseMatrix.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxSparseMatrix - stores and manipulates a 2D Sparse Matrix (float) using STL map
+// .SECTION Description
+// .SECTION See Also
+//  vtkpxMatrix
+//
+#ifndef __vtkpxSparseMatrix_h
+#define __vtkpxSparseMatrix_h
+
+#include "vtkObject.h"
+#include "dvSparseMatrix.h"
+#include "vtkpxAbstractMatrix.h"
+
+class vtkpxSparseMatrix : public vtkpxAbstractMatrix
+{
+public:
+  static vtkpxSparseMatrix *New();
+  vtkTypeMacro(vtkpxSparseMatrix,vtkpxAbstractMatrix);
+
+  // Description:
+  // Matrix Density
+  virtual float Density();
+  
+  // Description:
+  // Routine to allocate memory and set equal to zero (alias for allocate ala matlab)
+  virtual void Zeros(int rows,int cols);
+
+  // Description:
+  // Routine to allocate memory 
+  virtual void Allocate(int rows,int columns);
+
+  // Description:
+  // Routines to allocate memory and set equal to one
+  virtual void Ones(int rows,int cols);
+
+  // Description:
+  // Routines to allocate memory for square matrix and initialize accordingly and set to identity
+  virtual void Eye(int rowcol);
+
+  // Description:
+  // Sets current matrix=identity matrix (if it is square)
+  virtual void Identity();
+
+  // Description:
+  // Set all elements = zero
+  virtual void Zero();
+
+
+  // Description:
+  // Set all elements = a
+  virtual void Fill(float a);
+
+  // Description:
+  // Print Matrix to stderr
+  virtual void InternalPrint();
+  virtual void PrintBW();
+  virtual void Print(const char* message);
+  
+  //BTX
+  // Description:
+  // Get/Set Element in row=i column=j without range checking UNSAFE
+  inline virtual float  GetDirectElement(const int i,const int j)               { return this->Matrix[i][j]; }
+  inline virtual void   SetDirectElement(const int i,const int j,const float v) { this->Matrix[i][j]=v;}
+  //ETX
+
+  // Description:
+  // Get/Set Element in row=i column=j with range checking SAFE
+  virtual float   GetElement(int i,int j);
+  virtual void    SetElement(int i,int j,float v);
+  virtual void    AddToElement(int i,int j,float v);
+
+  // Description:
+  // Multiply All elements in matrix by s
+  virtual void  Scale(float s);
+
+
+  // Description:
+  // Static methods: a+b=results, a*b=results 
+  static  void Add(vtkpxSparseMatrix* a,vtkpxSparseMatrix* b,vtkpxSparseMatrix* result);
+  static  void Add(float wa,vtkpxSparseMatrix* a,float wb,vtkpxSparseMatrix* b,vtkpxSparseMatrix* result);
+  static  void Multiply(vtkpxSparseMatrix* a,vtkpxMatrix* b,vtkpxMatrix* result);
+
+  // Description:
+  // this*b=c
+  virtual void MultiplyThisWith(vtkpxMatrix* b,vtkpxMatrix* c);
+
+  //BTX
+  // Description:
+  //  dvSparseMatrix<float>* GetMatrixPointer() { return &Matrix; }
+  dvSparseMatrix* GetMatrixPointer() { return &Matrix; }
+  //ETX
+
+
+  // Description:
+  // Stuff Needed for RPM
+  virtual void MapPoints(vtkpxMatrix* Y,vtkpxMatrix* VY);
+  virtual void NormalizeMixtureMatrix(vtkpxMatrix* M_Outliers_Row);
+  virtual void NormalizeRPMMatrix(vtkpxMatrix* M_Outliers_Row,vtkpxMatrix* M_Outliers_Column);
+
+
+protected:
+
+  //BTX
+  vtkpxSparseMatrix();
+  virtual ~vtkpxSparseMatrix();
+
+  vtkpxSparseMatrix(const vtkpxSparseMatrix&) {};
+  void operator=(const vtkpxSparseMatrix&) {};
+
+  //  int Index(int i,int j) { return j*Size[0]+i; }
+  //dvSparseMatrix<float> Matrix; 
+  dvSparseMatrix Matrix; 
+  //ETX
+
+  
+};
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxTPSRPMRegistration.cpp b/bioimagesuite30_src/Registration/vtkpxTPSRPMRegistration.cpp
new file mode 100644
index 0000000..e2301dd
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxTPSRPMRegistration.cpp
@@ -0,0 +1,388 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxTPSRPMRegistration.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/03/12 16:49:59 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "pxutil.h"
+#include "vtkOldStyleCallbackCommand.h"
+#include "vtkDataSet.h"
+#include "vtkLandmarkTransform.h"
+#include "vtkMath.h"
+#include "vtkpxMath.h"
+#include "vtkMatrix4x4.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxTPSRPMRegistration.h"
+#include "vtkpxMatrix.h"
+#include "vtkpxUtil.h"
+#include "vtkIdList.h"
+#include "vtkTransformPolyDataFilter.h"
+#include "vtkCollection.h"
+#include "vtkFloatArray.h"
+//-----------------------------------------------------------------------------------
+
+vtkpxTPSRPMRegistration* vtkpxTPSRPMRegistration::New()
+{
+  // First try to create the object from the vtkObjectFactory
+
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxTPSRPMRegistration");
+  if(ret)
+    {
+    return (vtkpxTPSRPMRegistration*)ret;
+    }
+
+  // If the factory was unable to create the object, then create it here.
+
+  return new vtkpxTPSRPMRegistration;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxTPSRPMRegistration::vtkpxTPSRPMRegistration()
+{
+  this->ThinPlateSplineTransform = vtkThinPlateSplineTransform::New();
+  for (int i=0;i<12;i++)
+    temp_mat[i]=vtkpxMatrix::New();
+
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxTPSRPMRegistration::~vtkpxTPSRPMRegistration()
+{
+  this->ThinPlateSplineTransform->Delete();
+  for (int i=0;i<12;i++)
+    temp_mat[i]->Delete();
+}
+
+//----------------------------------------------------------------------------
+void vtkpxTPSRPMRegistration::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkpxAbstractRPMRegistration::PrintSelf(os,indent);
+  os << indent << "Transformation: " << this->ThinPlateSplineTransform << "\n";
+}
+
+//----------------------------------------------------------------------------
+vtkAbstractTransform* vtkpxTPSRPMRegistration::GetCurrentTransformation()
+{
+  return this->ThinPlateSplineTransform;
+}
+//----------------------------------------------------------------------------
+// Transformation Stuff
+//----------------------------------------------------------------------------
+void vtkpxTPSRPMRegistration::WarpControlPoints(vtkpxMatrix* X,vtkpxMatrix* VX,vtkpxMatrix* C,vtkpxMatrix* D)
+{
+  this->Gen_TPS_K(X,temp_mat[10]); 
+  vtkpxMatrix::Multiply(X,D,VX);
+  vtkpxMatrix::Multiply(temp_mat[10],C,temp_mat[11]);
+  vtkpxMatrix::Add(VX,temp_mat[11],VX);
+  return;
+}
+
+
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+// Helper Routines for Thin-Plate Spline 
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - - 
+void vtkpxTPSRPMRegistration::Gen_TPS_K(vtkpxMatrix* X,vtkpxMatrix* K)
+{
+  int sx[2];
+  X->GetSize(sx);
+  K->Zeros(sx[0],sx[0]);
+
+  float p1[3],p2[3];
+  for (int k=0;k<=2;k++)
+    {
+      p1[k]=0.0;
+      p2[k]=0.0;
+    }
+
+
+  for (int row=0;row<sx[0];row++)
+    {
+      for (int ia=0;ia<3;ia++)
+	p1[ia]=X->GetDirectElement(row,ia);
+
+      for (int column=row+1;column<sx[0];column++)
+	{
+	  if (row!=column)
+	    {
+	      for (int ib=0;ib<3;ib++)
+		p2[ib]=X->GetDirectElement(column,ib);
+	      
+	      float dist2= vtkMath::Distance2BetweenPoints(p1, p2);
+	      K->SetElement(row,column,-sqrt(dist2));
+	      K->SetElement(column,row,K->GetDirectElement(row,column));
+	    }
+	}
+    }
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - -  
+void vtkpxTPSRPMRegistration::Gen_TPS_CD_Regularized(float lambda1,float lambda2,
+					       vtkpxMatrix* q1,vtkpxMatrix* q2,
+					       vtkpxMatrix* R,vtkpxMatrix* K,vtkpxMatrix* Y,
+					       vtkpxMatrix* C,vtkpxMatrix* D)
+{
+  int sy[2];
+  Y->GetSize(sy);
+  int n=sy[0];
+  int M=sy[1];
+
+  this->temp_mat[5]->Copy(q2);
+  this->temp_mat[5]->Transpose();
+  vtkpxMatrix::Multiply(this->temp_mat[5],Y,this->temp_mat[6]);
+  
+  // this->temp_mat[0]=q2'*K*q2
+  // Speed this up 
+  vtkpxMatrix::MultiplyTripleProduct(q2,K,this->temp_mat[0]);
+  // this->temp_mat[1]=lambda1*eye(n-M)
+  this->temp_mat[1]->Eye(n-M);
+  this->temp_mat[1]->Scale(lambda1);
+  
+  // this->temp_mat[0]=this->temp_mat[0]+this->temp_mat[1];
+  vtkpxMatrix::Add(this->temp_mat[0],this->temp_mat[1],this->temp_mat[0]);
+  
+  // Invert this->temp_mat[0]
+  this->temp_mat[0]->Invert();
+  
+  // C= q2 * inv (this->temp_mat[0]) * this->temp_mat[6]
+  vtkpxMatrix::Multiply3(q2,this->temp_mat[0],this->temp_mat[6],C);
+  
+
+  // Then Calculate D 
+  //   A = inv(R'*R + lamda2 * eye(length(R),length(R))) * ( R'*q1'*(y-K*q2*gamma) - R'*R);
+  //   d = A + eye(dim+1,dim+1);
+  
+
+  this->temp_mat[3]->Copy(R);
+  this->temp_mat[3]->Transpose();
+  
+  // this->temp_mat[1]= R'*R
+  vtkpxMatrix::Multiply(this->temp_mat[3],R,this->temp_mat[4]);
+  
+  // this->temp_mat[0] = eye(length(R,R))
+  int lr[2]; 
+  R->GetSize(lr);
+  this->temp_mat[0]->Eye(lr[0]);
+  this->temp_mat[0]->Scale(lambda2);
+
+  // Find R'*R + lambda2*eye(length(R)
+  vtkpxMatrix::Add(this->temp_mat[0],this->temp_mat[4],this->temp_mat[0]);
+
+  // Invert this->temp_mat[0]
+  this->temp_mat[0]->Invert();
+
+  // Work on ( R'*q1'*(y-K*C) - R'*R);    (q2*gamma=C)
+  
+  // this->temp_mat[1]=y-KC 
+  vtkpxMatrix::Multiply(K,C,this->temp_mat[1]);
+  this->temp_mat[1]->Scale(-1.0);
+  vtkpxMatrix::Add(Y,this->temp_mat[1],this->temp_mat[1]);
+
+  // Find this->temp_mat[2]=R'*q1'*(y-KC)-R'R
+  q1->Transpose();
+  vtkpxMatrix::Multiply3(this->temp_mat[3],q1,this->temp_mat[1],this->temp_mat[2]);
+  this->temp_mat[4]->Scale(-1.0);
+  vtkpxMatrix::Add(this->temp_mat[2],this->temp_mat[4],this->temp_mat[2]);
+  
+  // Find this->temp_mat[1] = A  = inv(R'*R + lamda2 * eye(length(R),length(R))) * ( R'*q1'*(y-K*q2*gamma) - R'*R)
+  vtkpxMatrix::Multiply(this->temp_mat[0],this->temp_mat[2],this->temp_mat[1]);
+  
+  // Find D = A + eye(4,4);
+  D->Eye(4);
+  vtkpxMatrix::Add(D,this->temp_mat[1],D);
+
+
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - -  
+void vtkpxTPSRPMRegistration::GenerateTransformation(vtkpxMatrix* X,vtkpxMatrix* VY,
+						     float lambda1,float lambda2,vtkpxMatrix* C,vtkpxMatrix* D)
+{
+  X->Q1Q2RDecomposition(temp_mat[7],temp_mat[8],temp_mat[9]);  // q1,q2,R
+  this->Gen_TPS_K(X,temp_mat[10]);                             // K
+  this->Gen_TPS_CD_Regularized(lambda1,lambda2,temp_mat[7],temp_mat[8],temp_mat[9],temp_mat[10],VY,C,D);
+}
+// - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - -  - - - - - - - -  
+void vtkpxTPSRPMRegistration::CreateFinalTransformation(vtkpxMatrix* X,vtkpxMatrix* VX)
+  
+{
+  vtkPoints* p1_a=this->CreatePointsFromMatrix(X);
+  vtkPoints* p2_a=this->CreatePointsFromMatrix(VX);
+
+
+  this->ThinPlateSplineTransform->SetSourceLandmarks(p1_a);
+  this->ThinPlateSplineTransform->SetTargetLandmarks(p2_a);
+  this->ThinPlateSplineTransform->SetBasisToR();
+  this->ThinPlateSplineTransform->Update();
+
+  p1_a->Delete();
+  p2_a->Delete();
+
+
+}
+//----------------------------------------------------------------------------
+void vtkpxTPSRPMRegistration::Anneal()
+{
+  int perT_maxit=5;
+  //int relax_maxit=1;
+  float anneal_rate=this->AnnealRate;
+  float lambda1_init=this->InitialSmoothnessFactor;
+  float lambda2_init=0.01*lambda1_init;
+
+  // Initialize Temperature Stuff 
+  float T      =Frange(this->InitialTemperature,0.01,0.5);
+  float T_final=Frange(this->FinalTemperature,0.00001,T);
+  float totaliter=fabs(log(T/T_final)/log(anneal_rate))+1.0;
+
+  vtkpxMatrix* X=vtkpxMatrix::New();
+  vtkpxMatrix* Y=vtkpxMatrix::New();
+  vtkpxMatrix* LX=vtkpxMatrix::New();
+  vtkpxMatrix* LY=vtkpxMatrix::New();
+
+  this->SamplePoints(X,Y,LX,LY,this->MaximumNumberOfLandmarks);
+
+
+  int sz[2],nump_x,nump_y;
+  X->GetSize(sz);   nump_x=sz[0];
+  Y->GetSize(sz);   nump_y=sz[0];
+  vtkDebugMacro(<< "Anneal: Using " << nump_x << " , " << nump_y << "Landmarks UseLabels="<< this->UseLabels << "\n");
+
+  vtkpxAbstractMatrix* M=this->AllocateMatchMatrix(this->MatchMatrixType);
+  vtkpxMatrix* M_Outliers_Row=vtkpxMatrix::New();
+  vtkpxMatrix* M_Outliers_Column=vtkpxMatrix::New();
+  this->InitMatchMatrices(M,M_Outliers_Row,M_Outliers_Column,nump_x,nump_y);
+  
+  vtkPointLocator* locator=this->CreateLocator(Y);
+
+  // Initialize Transformed X and Y stuff 
+  vtkpxMatrix* VX=vtkpxMatrix::New();   VX->Copy(X);
+
+
+  if (this->InitialTransform!=NULL && this->UseInitialTransform>0 )
+    {
+      fprintf(stderr,"Initializing using current transform!\n\n");
+      float x[3],tx[3];
+      for (int i=0;i<nump_x;i++)
+	{
+	  for (int ia=0;ia<3;ia++)
+	    x[ia]=VX->GetDirectElement(i,ia);
+
+	  this->InitialTransform->TransformPoint(x,tx);
+	  for (int ib=0;ib<3;ib++)
+	    VX->SetDirectElement(i,ib,tx[ib]);
+	}
+    }
+  
+  // THis is a BUG in Haili's Code, VY has same size as X!!! 
+  vtkpxMatrix* VY=vtkpxMatrix::New();  VY->Copy(X);
+
+  vtkpxMatrix* C=vtkpxMatrix::New();
+  vtkpxMatrix* D=vtkpxMatrix::New();
+  C->Zeros(nump_x,4);
+  D->Zeros(4,4);
+  
+  // Annealing Procedure 
+  int flag_stop=0;
+  int iter=1;
+
+  perT_maxit=1;
+
+  while (flag_stop == 0 )
+    {
+      float lambda1=lambda1_init*float(nump_x)*T;
+      float lambda2=lambda2_init*float(nump_x)*T;
+
+      for (int i=1;i<=perT_maxit;i++)
+	{
+	  if (this->AbortExecute>0)
+	    {
+	      i=perT_maxit+1;
+	    }
+	  else
+	    {
+	      this->SetOutliers(M_Outliers_Row,M_Outliers_Column,T);
+	      this->UpdateCorrespondence(M,M_Outliers_Row,M_Outliers_Column,
+					 VX,Y,VY,T,locator,LX,LY);
+	      this->GenerateTransformation(X,VY,
+					   lambda1,lambda2,C,D);
+	      this->WarpControlPoints(X,VX,C,D);
+	    }
+	}
+
+      vtkDebugMacro(<<"\n----------------------------------------------------------\nIteration " << iter << "/" << totaliter << " T = " << T << " Lambda1=" << lambda1 << "Lambda2 = "<< lambda2 << ", abort= " << this->AbortExecute << "\n");
+
+      if (this->EnableFeedback)
+	this->CreateFinalTransformation(X,VX);
+
+
+      this->UpdateProgress(float(iter)/totaliter);
+      iter++;
+      T=T*anneal_rate;
+      if (T<T_final || this->AbortExecute>0)
+	flag_stop=1;
+    }
+  
+  vtkDebugMacro(<<"Creating Final Transformation");
+  this->CreateFinalTransformation(X,VX);
+  this->InvokeEvent(vtkCommand::EndEvent,NULL);
+
+  // Cleanup Stuff 
+  if (locator!=NULL)    locator->Delete();
+  if (C!=NULL)          C->Delete();
+  if (D!=NULL)          D->Delete();
+  VX->Delete();         VY->Delete();
+  M->Delete();          M_Outliers_Row->Delete();
+  X->Delete();          M_Outliers_Column->Delete();
+  Y->Delete();          
+  LX->Delete();         LY->Delete();
+}
+
diff --git a/bioimagesuite30_src/Registration/vtkpxTPSRPMRegistration.h b/bioimagesuite30_src/Registration/vtkpxTPSRPMRegistration.h
new file mode 100644
index 0000000..32f1827
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxTPSRPMRegistration.h
@@ -0,0 +1,110 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxTPSRPMRegistration.h,v $
+  Language:  C++
+  Date:      $Date: 2002/03/12 16:50:35 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#ifndef __vtkpxTPSRPMRegistration_h
+#define __vtkpxTPSRPMRegistration_h
+
+#include "vtkThinPlateSplineTransform.h"
+#include "vtkpxAbstractRPMRegistration.h"
+
+class vtkpxTPSRPMRegistration : public vtkpxAbstractRPMRegistration
+{
+public:
+  static vtkpxTPSRPMRegistration *New();
+  vtkTypeMacro(vtkpxTPSRPMRegistration,vtkpxAbstractRPMRegistration);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Get Current Transformation -- needed for displaying updates 
+  virtual vtkAbstractTransform* GetCurrentTransformation();
+
+protected:
+  // Description:
+  
+  vtkpxTPSRPMRegistration();
+  ~vtkpxTPSRPMRegistration();
+  vtkpxTPSRPMRegistration(const vtkpxTPSRPMRegistration&) {};
+  void operator=(const vtkpxTPSRPMRegistration&) {};
+
+  vtkThinPlateSplineTransform* ThinPlateSplineTransform;
+  vtkpxMatrix* temp_mat[12];
+
+  virtual void Anneal();
+
+  // Description:
+  // Routine for warping control points for thin-plate spline 
+  virtual void WarpControlPoints(vtkpxMatrix* x,vtkpxMatrix* vx,vtkpxMatrix*C ,vtkpxMatrix* D);
+
+  // Description:
+  // Generate Transformation
+  virtual void GenerateTransformation(vtkpxMatrix* x,vtkpxMatrix* vy,
+				      float lambda1,float lambda2,vtkpxMatrix* C,vtkpxMatrix* D);
+  virtual void CreateFinalTransformation(vtkpxMatrix* x,vtkpxMatrix* vx);
+
+  // Description:
+  // Helper Routines for Transformation 
+  virtual void Gen_TPS_K(vtkpxMatrix* x,vtkpxMatrix* K);
+  virtual void Gen_TPS_CD_Regularized (float lamda1,float lamda2,
+				       vtkpxMatrix* q1,vtkpxMatrix* q2,
+				       vtkpxMatrix* R,vtkpxMatrix* K,vtkpxMatrix* y,
+				       vtkpxMatrix* c,vtkpxMatrix* d);
+
+
+  
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxTransformationUtil.cpp b/bioimagesuite30_src/Registration/vtkpxTransformationUtil.cpp
new file mode 100644
index 0000000..0c0df56
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxTransformationUtil.cpp
@@ -0,0 +1,1169 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxTransformationUtil.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "pxutil.h"
+#include "vtkAbstractTransform.h"
+#include "vtkDataArray.h"
+#include "vtkFloatArray.h"
+#include "vtkGridTransform.h"
+#include "vtkHomogeneousTransform.h"
+#include "vtkIdentityTransform.h"
+#include "vtkImageCast.h"
+#include "vtkImageData.h"
+#include "vtkImageData.h"
+#include "vtkMath.h"
+#include "vtkMatrix4x4.h"
+#include "vtkObjectFactory.h"
+#include "vtkStructuredPoints.h"
+#include "vtkStructuredPointsReader.h"
+#include "vtkStructuredPointsWriter.h"
+#include "vtkThinPlateSplineTransform.h"
+#include "vtkTransform.h"
+#include "vtkpxComboTransform.h"
+#include "vtkpxGridTransform.h"
+#include "vtkpxMatrix.h"
+#include "vtkpxTransformationUtil.h"
+#include "vtkMatrixToHomogeneousTransform.h"
+#include "vtkAppendPolyData.h"
+#include "vtkImageExtractComponents.h"
+#include "bioimagesuite_settings.h"
+#include "vtkpxAppendComponents.h"
+#include "vtkContourFilter.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageMathematics.h"
+#include "vtkImageDataGeometryFilter.h"
+#include "vtkThresholdPoints.h"
+#include "vtkPolyDataConnectivityFilter.h"
+
+
+#ifdef BIOIMAGESUITE_EXPERIMENTAL
+#include "vtkpxPolySimilarityTransform.h"
+#include "vtkpxSimilarityTransform.h"
+#endif
+// ---------------------------
+
+vtkpxTransformationUtil* vtkpxTransformationUtil::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxTransformationUtil");
+  if(ret)
+      {
+	return (vtkpxTransformationUtil*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxTransformationUtil;
+}
+
+
+/*=========================================================================
+
+
+     T R A N S F O R M      C O D E
+
+
+=========================================================================*/
+
+
+//------------------------------------------------------------------------
+// Some Matrix Code --- genrate rotation matrix from 2 or 3 points 
+//------------------------------------------------------------------------
+int vtkpxTransformationUtil::GenerateTransform(vtkTransform* tr,vtkPoints* points,int npoints)
+{
+  if (tr==NULL || points==NULL)
+    return 0;
+
+  tr->Identity();
+
+  if (npoints==-1)
+    {
+      if (points->GetNumberOfPoints()<2)
+	  return 0;
+      
+      if (points->GetNumberOfPoints()>3)
+	npoints=4;
+      else
+	npoints=2;
+    }
+  else
+    {
+      if (points->GetNumberOfPoints()<2)
+	{
+	  return 0;
+	}
+      else 
+	npoints=Irange(npoints,2,4);
+    }
+
+  // fprintf(stderr,"Generating transform npoints=%d\n",npoints);
+
+  double x1[3],x2[3],x3[3];
+  
+  if (npoints==3)
+    {
+      points->GetPoint(0,x1);
+      points->GetPoint(1,x2);
+      points->GetPoint(2,x3);
+
+      // Pick x1 as origin 
+      for (int ia=0;ia<=2;ia++)
+	{
+	  x2[ia]=x2[ia]-x1[ia];
+	  x3[ia]=x3[ia]-x1[ia];
+	  x1[ia]=0.0;
+	}
+
+      /*      fprintf(stderr,"Differences:\n");
+	      for (int ia=0;ia<=2;ia++)
+	      fprintf(stderr,"Vectors x1[%d]=%5.2f x2[%d]=%5.2f x3[%d]=%5.2f\n", ia,x1[ia],ia,x2[ia],ia,x3[ia]);*/
+
+      vtkMath::Normalize(x2);
+      vtkMath::Normalize(x3);
+      vtkMath::Cross(x2,x3,x1);
+      /*fprintf(stderr,"Perpendiculars:\n");
+	for (int ia=0;ia<=2;ia++)
+	fprintf(stderr,"Vectors x1[%d]=%5.2f x2[%d]=%5.2f x3[%d]=%5.2f\n", ia,x1[ia],ia,x2[ia],ia,x3[ia]);*/
+
+    }
+  else
+    { 
+      points->GetPoint(0,x1);
+      points->GetPoint(1,x2);
+
+      // Pick x1 as origin 
+      for (int ia=0;ia<=2;ia++)
+	x2[ia]=x2[ia]-x1[ia];
+
+      /*fprintf(stderr,"Differences:\n");
+	for (int ia=0;ia<=2;ia++)
+	fprintf(stderr,"Vectors x1[%d]=%5.2f x2[%d]=%5.2f x3[%d]=%5.2f\n", ia,x1[ia],ia,x2[ia],ia,x3[ia]);*/
+
+      vtkMath::Normalize(x2);
+      vtkMath::Perpendiculars(x2,x3,x1,0.0);
+      /*fprintf(stderr,"Perpendiculars:");
+	for (int ia=0;ia<=2;ia++)
+	fprintf(stderr,"Vectors x1[%d]=%5.2f x2[%d]=%5.2f x3[%d]=%5.2f\n", ia,x1[ia],ia,x2[ia],ia,x3[ia]);*/
+    }
+
+
+  // Set the 3x3 Section with the vectors x2,x3,x1 ::: Done 
+  vtkMatrix4x4* mat=tr->GetMatrix();
+  for (int i=0;i<=2;i++)
+    {
+      mat->SetElement(0,i,x1[i]);
+      mat->SetElement(1,i,x2[i]);
+      mat->SetElement(2,i,x3[i]);
+    }
+
+  //  PrintMatrix(mat->Element,4,4);
+  return 1;
+}
+
+
+
+//------------------------------------------------------------------------
+// Fix Mmvreg Output to central coordinates 
+//------------------------------------------------------------------------
+void vtkpxTransformationUtil::FixMmvregOutput(vtkMatrix4x4* matrix,int permute)
+{
+  if (matrix==NULL)
+    return;
+
+  double mat[4][4];
+
+  for (int i=0;i<=3;i++)
+    for (int j=0;j<=3;j++)
+      mat[i][j]=matrix->GetElement(i,j);
+
+  permute=Irange(permute,0,2);
+  
+  for (int ia=0;ia<=3;ia++)
+    for (int ib=0;ib<=3;ib++)
+      {
+	int newi=Icyclic(ia+permute,3);
+	int newj=Icyclic(ib+permute,3);
+	matrix->SetElement(ia,ib,mat[newi][newj]);
+      }
+}
+
+//------------------------------------------------------------------------
+// Transformation I/O
+//------------------------------------------------------------------------
+
+int vtkpxTransformationUtil::SaveAbstractTransform(vtkAbstractTransform* tr,const char* fname)
+{
+
+  if ( tr->IsA("vtkHomogeneousTransform")==1) 
+    return vtkpxTransformationUtil::SaveMatrix(((vtkHomogeneousTransform*)tr)->GetMatrix(),fname);
+  else if ( tr->IsA("vtkThinPlateSplineTransform")==1)
+    return vtkpxTransformationUtil::SaveThinPlateSplineTransform((vtkThinPlateSplineTransform*)tr,fname);
+  else if ( tr->IsA("vtkpxGridTransform")==1) 
+    return ((vtkpxGridTransform*)tr)->Save(fname);
+  else if ( tr->IsA("vtkpxComboTransform")==1) 
+    return ((vtkpxComboTransform*)tr)->Save(fname);
+
+#ifdef BIOIMAGESUITE_EXPERIMENTAL
+  else if ( tr->IsA("vtkpxSimilarityTransform")==1)
+    return ((vtkpxSimilarityTransform*)tr)->Save(fname); 
+  else if ( tr->IsA("vtkpxPolySimilarityTransform")==1)
+    return ((vtkpxPolySimilarityTransform*)tr)->Save(fname); 
+#endif
+  return 0;
+}
+
+vtkAbstractTransform* vtkpxTransformationUtil::LoadAbstractTransform(const char* fname)
+{
+  // Check Grid, then ThinPlate then Matrix
+
+  vtkpxComboTransform* tg=vtkpxComboTransform::New();
+  int ok=tg->Load(fname);
+  if (ok)
+    return tg;
+
+  tg->Delete();
+
+#ifdef BIOIMAGESUITE_EXPERIMENTAL
+  vtkpxSimilarityTransform* stg=vtkpxSimilarityTransform::New();
+  ok=stg->Load(fname);
+  if (ok)
+    return stg;
+  stg->Delete();
+
+  vtkpxPolySimilarityTransform* pstg=vtkpxPolySimilarityTransform::New();
+  ok=pstg->Load(fname);
+  if (ok)
+    return pstg;
+  pstg->Delete();
+#endif
+
+  vtkThinPlateSplineTransform* tr=vtkThinPlateSplineTransform::New();
+  ok=vtkpxTransformationUtil::LoadThinPlateSplineTransform(tr,fname);
+  if (ok)
+    return tr;
+
+  tr->Delete();
+  
+  vtkTransform* tm=vtkTransform::New();
+  ok=LoadMatrixTransform(tm,fname);
+  
+  if (ok)
+    return tm;
+
+  tm->Delete();
+  return NULL;
+}
+//------------------------------------------------------------------------
+int vtkpxTransformationUtil::LoadMatrixTransform(vtkTransform* tr,const char* fname)
+{
+  vtkMatrix4x4* mat=vtkMatrix4x4::New();
+  int ok=vtkpxTransformationUtil::LoadMatrix(mat,fname);
+  if (ok)
+    {
+      tr->Identity();
+      tr->Concatenate(mat);
+    }
+  mat->Delete();
+
+  return ok;
+}
+
+int vtkpxTransformationUtil::SaveMatrixTransform(vtkTransform* tr,const char* fname)
+{
+  return vtkpxTransformationUtil::SaveMatrix(tr->GetMatrix(),fname);
+}
+
+
+int vtkpxTransformationUtil::LoadMatrix(vtkMatrix4x4* matrix,const char* fname)
+{
+  FILE* fin=fopen(fname,"r");
+  if (fin==NULL)
+    return 0;
+
+  vtkMatrix4x4* mat_in=vtkMatrix4x4::New();
+  mat_in->Identity();
+
+
+  float mat;
+  for (int i=0;i<=3;i++)
+    for (int j=0;j<=3;j++)
+      {
+	fscanf(fin,"%f ",&mat);
+	mat_in->SetElement(i,j,mat);
+      }
+  fclose(fin);
+
+  matrix->DeepCopy(mat_in);
+  mat_in->Delete();
+  return 1;
+
+}
+
+int vtkpxTransformationUtil::SaveMatrix(vtkMatrix4x4* matrix,const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout==NULL)
+    return 0;
+  
+  for(int i=0;i<=3;i++)
+    {
+      for (int j=0;j<=3;j++)
+	fprintf(fout,"%7.3f ",matrix->GetElement(i,j));
+      fprintf(fout,"\n");
+    }
+  fclose(fout);
+  return 1;
+}
+
+
+
+
+int vtkpxTransformationUtil::LoadThinPlateSplineTransform(vtkThinPlateSplineTransform* tps,const char* fname)
+{
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  int ok=vtkpxTransformationUtil::LoadThinPlateSplineTransform(tps,fin);
+
+  gzclose(fin);
+  return ok;
+}
+
+
+
+int vtkpxTransformationUtil::LoadThinPlateSplineTransform(vtkThinPlateSplineTransform* tps,gzFile fin)
+{
+  char pxtk_buffer[100];
+  gzgets(fin,pxtk_buffer,100);
+ 
+  if (gzfindstringinstring(pxtk_buffer,"#Thin-Plate Spline Transform File")==0)
+    return 0;
+
+  gzgets(fin,pxtk_buffer,100); 
+  gzgets(fin,pxtk_buffer,100);
+  int np;
+  sscanf(pxtk_buffer,"%d",&np);
+  vtkPoints* points[2];
+  
+  for (int j=0;j<=1;j++)
+    {
+      gzgets(fin,pxtk_buffer,100);
+      points[j]=vtkPoints::New();
+      points[j]->SetNumberOfPoints(np);
+
+      for (int i=0;i<np;i++)
+	{
+	  float x[3];
+	  gzgets(fin,pxtk_buffer,100);
+	  sscanf(pxtk_buffer,"%f %f %f",&x[0],&x[1],&x[2]);
+	  points[j]->SetPoint(i,x);
+	}
+    }
+
+  
+  tps->SetSourceLandmarks(points[0]);
+  tps->SetTargetLandmarks(points[1]);
+  tps->SetBasisToR();
+  tps->Update();
+  points[0]->Delete();
+  points[1]->Delete();
+
+  return 1;
+}
+
+int vtkpxTransformationUtil::SaveThinPlateSplineTransform(vtkThinPlateSplineTransform* tps,const char* fname)
+{
+  vtkPoints* points[2];
+  
+  points[0]=tps->GetSourceLandmarks();
+  points[1]=tps->GetTargetLandmarks();
+
+  if (points[0]==NULL || points[1]==NULL)
+    return 0;
+  
+  //int np=points[0]->GetNumberOfPoints();
+  
+  FILE* fout=fopen(fname,"w");
+  if (fout==NULL)
+    return 0;
+
+  int ok=vtkpxTransformationUtil::SaveThinPlateSplineTransform(tps,fout);
+  fclose(fout);
+  return ok;
+}
+// --------------------------------------------------------------------------------------
+int vtkpxTransformationUtil::SaveThinPlateSplineTransform(vtkThinPlateSplineTransform* tps,FILE* fout)
+{
+
+  vtkPoints* points[2];
+  
+  points[0]=tps->GetSourceLandmarks();
+  points[1]=tps->GetTargetLandmarks();
+
+  if (points[0]==NULL || points[1]==NULL)
+    return 0;
+  
+  int np=points[0]->GetNumberOfPoints();
+    
+  fprintf(fout,"#Thin-Plate Spline Transform File\n");
+  fprintf(fout,"#Number of Points\n%d\n",np);
+  for (int j=0;j<=1;j++)
+    {
+      if (j==0)
+	fprintf(fout,"#Source Points\n");
+      else
+	fprintf(fout,"#Target Points\n");
+      for (int i=0;i<np;i++)
+	{
+	  double x[3];
+	  points[j]->GetPoint(i,x);
+	  fprintf(fout,"%.2f %.2f %.2f\n",x[0],x[1],x[2]);
+	}
+    }
+  return 1;
+}
+// --------------------------------------------------------------------------------------
+
+int vtkpxTransformationUtil::SaveGridTransform(vtkpxGridTransform* mat,const char* fname)
+{
+  return mat->Save(fname);
+}
+
+int vtkpxTransformationUtil::LoadGridTransform(vtkpxGridTransform* tr,const char* fname)
+{
+  char pxtk_buffer[400];
+  gzFile fin=gzsuffixopen(fname,"rb");
+  if (!fin)
+    return 0;
+  
+  gzgets(fin,pxtk_buffer,100);
+  
+  if (gzfindstringinstring(pxtk_buffer,"#Grid Transform File")==1)
+    {
+      float scale,shift;
+      int interp;
+      gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+      sscanf(pxtk_buffer,"%f",&scale);
+      gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+      sscanf(pxtk_buffer,"%f",&shift);
+      gzgets(fin,pxtk_buffer,100);  gzgets(fin,pxtk_buffer,100);
+      sscanf(pxtk_buffer,"%d",&interp);
+      gzclose(fin);
+      sprintf(pxtk_buffer,"%s.cntrl",fname);
+      vtkStructuredPointsReader* rd=vtkStructuredPointsReader::New();
+      rd->SetFileName(pxtk_buffer);
+      rd->Update();
+      tr->SetDisplacementScale(scale);
+      tr->SetDisplacementShift(shift);
+      tr->SetInterpolationMode(interp);
+      tr->SetDisplacementGrid(rd->GetOutput());
+      rd->Delete();
+      return 1;
+    }
+  gzclose(fin);
+  int ok=tr->Load(fname);
+  return ok;
+}
+
+float vtkpxTransformationUtil::GetJacobian(vtkAbstractTransform* tr,vtkpxMatrix* jac,float x,float y,float z)
+{
+  tr->Update();
+
+  if (tr==NULL || jac==NULL)
+    return 0.0;
+  jac->Zeros(3,3);
+
+  float p[3],p2[3],der[3][3];
+  p[0]=x;p[1]=y;p[2]=z;
+  tr->InternalTransformDerivative(p,p2,der);
+  for (int i=0;i<=2;i++)
+    for (int j=0;j<=2;j++)
+      jac->SetElement(i,j,der[i][j]);
+  return vtkMath::Determinant3x3(der);
+}
+// ----------------------------------------------------------------------
+// Mouse Model Stuff originally in vtkpxPolySimilarityTransform
+// ----------------------------------------------------------------------
+
+vtkImageData* vtkpxTransformationUtil::GetMaskImage(vtkImageData* input,vtkFloatArray* planes,int offset)
+{
+  return vtkpxTransformationUtil::GetMaskImage(input,planes,offset,0);
+}
+
+vtkImageData* vtkpxTransformationUtil::GetMaskImage(vtkImageData* input,vtkFloatArray* planes,int offset,int flip)
+{
+  double n1[3],c1[3];
+  
+  for (int ia=0;ia<=2;ia++)
+    {
+      n1[ia]=planes->GetComponent(offset,ia);
+      c1[ia]=planes->GetComponent(offset,ia+4);
+    }
+  double dist1=planes->GetComponent(offset,3);
+  int above1=(int)planes->GetComponent(offset,7);
+  if (flip)
+    above1=-above1;
+
+  return vtkpxTransformationUtil::GetMaskImage(input,above1,n1,c1,dist1);
+
+}
+// ----------------------------------------------------------------------
+vtkImageData* vtkpxTransformationUtil::GetMaskImage(vtkImageData* image,int abv,double n[3],double c[3],double offset)
+{
+  if (abv!=1)
+    abv=-1;
+
+  //  fprintf(stderr,"\nCenter = %.2f,%.2f,%.2f Normal=%.2f,%.2f,%.2f offset=%.2f\t abd=%d\n",c[0],c[1],c[2],n[0],n[1],n[2],offset,abv);
+  
+
+
+
+  vtkImageData* img=vtkImageData::New();
+  img->CopyStructure(image);
+  img->SetNumberOfScalarComponents(1);
+  img->SetScalarTypeToShort();
+  img->AllocateScalars();
+
+  int np=img->GetNumberOfPoints();
+  vtkDataArray* data=img->GetPointData()->GetScalars();
+  vtkDataArray* inp=image->GetPointData()->GetScalars();
+  
+  data->CopyComponent(0,inp,0);
+    
+
+  int dim[3];  img->GetDimensions(dim);
+  double spa[3]; img->GetSpacing(spa);
+  double ori[3]; img->GetOrigin(ori);
+
+  double x[3];
+  
+  for (int k=0;k<dim[2];k++)
+    {
+      x[2]=double(k)*spa[2]+ori[2];
+      for (int j=0;j<dim[1];j++)
+	{
+	  x[1]=double(j)*spa[1]+ori[1];
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      x[0]=double(i)*spa[0]+ori[0];
+	      double sum=0.0;
+	      for (int ia=0;ia<=2;ia++)
+		sum+=(x[ia]-c[ia])*n[ia];
+
+	      if (sum*abv<0)	      
+		img->SetScalarComponentFromDouble(i,j,k,0,0);
+	    }
+	}
+    }
+  return img;
+}
+// ----------------------------------------------------------------------
+vtkImageData* vtkpxTransformationUtil::CreateRegionLabelImage(vtkImageData* input,float sigma)
+{
+  return vtkpxTransformationUtil::CreateRegionLabelImage(input,sigma,NULL);
+}
+// ----------------------------------------------------------------------
+int vtkpxTransformationUtil::CreatePolygonalModel(vtkImageData* multiframeinput,vtkPolyData* surface,float threshold)
+{
+  fprintf(stderr,"\n\n Now Creating Surface Model thr=%.2f\n",threshold);
+       
+  int nc=multiframeinput->GetNumberOfScalarComponents();
+  vtkAppendPolyData* append=vtkAppendPolyData::New();
+  
+  for (int i=0;i<nc;i++)
+    {
+      fprintf(stderr,"Part %d\n",i+1);
+      vtkImageExtractComponents* frame=vtkImageExtractComponents::New();
+      frame->SetInput(multiframeinput);
+      frame->SetComponents(i);
+      frame->Modified();
+	  
+      vtkContourFilter* skinExtractor=vtkContourFilter::New();
+      skinExtractor->SetInput(frame->GetOutput());
+      skinExtractor->SetUseScalarTree(0);
+      skinExtractor->SetNumberOfContours(1);
+      skinExtractor->SetValue(0,threshold);
+      skinExtractor->ComputeScalarsOff();
+      skinExtractor->ComputeGradientsOff();
+      skinExtractor->ComputeNormalsOff();
+      skinExtractor->Update();
+      
+      vtkPolyData* tmp=vtkPolyData::New();
+      tmp->ShallowCopy(skinExtractor->GetOutput());
+      
+      vtkDataArray* ptScalars=vtkDataArray::CreateDataArray(VTK_SHORT);
+      ptScalars->SetNumberOfComponents(1);
+      ptScalars->SetNumberOfTuples(tmp->GetPoints()->GetNumberOfPoints());
+      ptScalars->FillComponent(0,i);
+	  
+      tmp->GetPointData()->SetScalars(ptScalars);
+      ptScalars->Delete();
+      
+      append->AddInput(tmp);
+      tmp->Delete();
+      
+      skinExtractor->Delete();
+      frame->Delete();
+    }
+      
+  fprintf(stderr,"Concatenating\n");
+  append->Update();
+      
+  surface->ShallowCopy(append->GetOutput());
+  append->Delete();
+  return 1;
+}
+// ----------------------------------------------------------------------
+vtkImageData* vtkpxTransformationUtil::CreateRegionLabelImage(vtkImageData* input,float sigma,vtkPolyData* surface)
+{
+  double r[2]; input->GetPointData()->GetScalars()->GetRange(r);
+  double threshold=(r[0]+r[1])*0.5;
+
+  fprintf(stderr,"Creating Model Input nc=%d range=%.1f:%.1f threshold=%.2f sigma=%.2f\n",
+	  input->GetNumberOfScalarComponents(),r[0],r[1],threshold,sigma);
+
+
+  vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+  smooth->SetInput(input);
+  smooth->SetStandardDeviations(sigma,sigma,sigma);
+  smooth->SetRadiusFactors(3.0,3.0,3.0);
+  smooth->Update();
+
+  vtkImageData* output=vtkImageData::New();
+  output->CopyStructure(input);
+  output->SetNumberOfScalarComponents(1);
+  output->SetScalarTypeToShort();
+  output->AllocateScalars();
+
+  vtkDataArray* inp=smooth->GetOutput()->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  int np=out->GetNumberOfTuples();
+  int nc=input->GetNumberOfScalarComponents();
+
+  out->FillComponent(0,0);
+
+  fprintf(stderr,"Here Starting np=%d nc=%d :",np,nc);
+
+  int count=0;
+  int per=0;
+  int tenth=np/10;
+
+  for (int i=0;i<np;i++)
+    {
+      int best=-1;
+      double bestv=0;
+
+      for (int j=0;j<nc;j++)
+	{
+	  double v=inp->GetComponent(i,j);
+	  if (v>bestv)
+	    {
+	      bestv=v;
+	      best=j;
+	    }
+	}
+
+      out->SetComponent(i,0,best);
+      ++count;
+      if (count==tenth)
+	{
+	  per+=10;
+	  fprintf(stderr,"%d \%",per);
+	  count=0;
+	}
+    }
+
+
+  if (surface != NULL)
+    {
+      vtkImageData* smoothed=smooth->GetOutput();
+      vtkpxTransformationUtil::CreatePolygonalModel(smoothed,surface,threshold);
+    }
+  
+  smooth->Delete();
+  return output;
+
+}
+
+// ----------------------------------------------------------------------
+//
+//            Whole body atlas  .... .............
+//
+// ----------------------------------------------------------------------
+vtkImageData* vtkpxTransformationUtil::ChopLeg(vtkImageData* Leg,vtkFloatArray* planes,int offset,int numcuts,int legmode)
+{
+  legmode=(legmode>0);
+
+  vtkpxAppendComponents* append=vtkpxAppendComponents::New();
+
+  for (int piece=0;piece<numcuts;piece++)
+    {
+      double n[3],c[3],dist;
+      for (int ia=0;ia<=2;ia++)
+	{
+	  n[ia]=planes->GetComponent(offset+piece,ia);
+	  c[ia]=planes->GetComponent(offset+piece,ia+4);
+	}
+      dist=planes->GetComponent(offset+piece,3);
+      int above=(int)planes->GetComponent(offset+piece,7);
+      int oldabove=above;
+      if (above<=0)
+	above=-1;
+      else
+	above=1;
+     
+      if (piece==0)
+	above=-above;
+
+      fprintf(stderr,"Piece=%d offset+piece=%d n=%.2f,%.2f,%.2f  dist=%.2f above=%d --> %d\n",
+	      piece,offset+piece,
+	      n[0],n[1],n[2],dist,oldabove,above);
+
+      vtkImageData* tmp=vtkpxTransformationUtil::GetMaskImage(Leg,above,n,c,dist);
+
+      vtkImageMathematics* m2=vtkImageMathematics::New();
+      m2->SetInput1(Leg);
+      m2->SetInput2(tmp);
+      m2->SetOperationToSubtract();
+      m2->Update();
+
+      
+      Leg->ShallowCopy(m2->GetOutput());
+      m2->Delete();
+
+      if (piece==numcuts-1 && legmode==1)
+	append->AddInput(Leg);	
+      append->AddInput(tmp);
+
+      tmp->Delete();
+    }
+  
+  if (legmode==0)
+    append->AddInput(Leg);	
+
+  append->Update();
+
+  vtkImageData* pieces=vtkImageData::New();
+  pieces->ShallowCopy(append->GetOutput());
+  append->Delete();
+  return pieces;
+}
+// ----------------------------------------------------------------------
+vtkImageData* vtkpxTransformationUtil::CreateWholeBodyRegionLabelImage(vtkImageData* input,vtkFloatArray* planes,
+									    int hasfeet,int hashindlimbs,int hasforelimbs,
+									    int hashead,int taildivisions, int spinedivisions)
+{
+  // Plane order
+  // Left  Hipp 1+2, Left Knee ,Left Foot               0..3 
+  // Right Hipp 1+2, Right Knee ,Right Foot             4..7
+  // Left  Shoulder 1+2, Left Elbow ,Left Wrist         8..11
+  // Right Shoulder 1+2, Right Elbow ,Right Wrist       12..15
+  // Tail from hipp down                                16..20
+  // Abdomen from hipp up                               21..25
+  // Neck                                               26
+  
+  // Strategy
+  // 1. Chop off all legs first (1..4)
+  // 2. Chop off tail
+  // 3. Chop up legs, tail
+  // 4. Chop up abdomen and head
+
+  //  int abdomenoffset=0;
+
+  if (input==NULL || planes == NULL)
+    {
+      fprintf(stderr,"Bad Inputs to Create Region Label Image\n");
+      return NULL;
+    }
+	
+  hasfeet=(hasfeet>0);
+  hashead=(hashead>0);
+  hashindlimbs=(hashindlimbs>0);
+  hasforelimbs=(hasforelimbs>0);
+
+  if (spinedivisions>10)
+    spinedivisions=10;
+  else if (spinedivisions<1)
+    spinedivisions=0;
+
+  if (taildivisions<1)
+    taildivisions=0;
+  else if (taildivisions>5)
+    taildivisions=5;
+
+  int legparts=3+hasfeet;  // (hip needs two planes)
+
+  int totalplanes=
+    hashead + // head
+    2*(hashindlimbs+hasforelimbs)*legparts + // 4 limbs
+    spinedivisions + //
+    taildivisions;
+	
+  int numberofplanes=planes->GetNumberOfTuples();
+  if (numberofplanes!=totalplanes || planes->GetNumberOfComponents()!=8)
+    {
+      fprintf(stderr,"Bad Number of Planes %d (vs %d needed) or components (%d vs 8) to Create Region Label Image\n",numberofplanes,totalplanes,
+	      planes->GetNumberOfComponents());
+      return NULL;
+    }
+
+
+  vtkpxAppendComponents* append=vtkpxAppendComponents::New();
+  
+  // --------------------------------------------------------------------------------
+  // [A]  Chop off Four Legs to leave MainTrunk -- further subdivide legs into pieces
+  // --------------------------------------------------------------------------------
+
+  int minleg=-1,maxleg=-2;
+
+  vtkImageData* MainTrunk=vtkImageData::New();
+  vtkImageData* LegPieces[4];
+  for (int i=0;i<=3;i++)
+    LegPieces[i]=NULL;
+
+
+  if (hasforelimbs ==1 || hashindlimbs ==1 )
+    {
+      minleg=0;
+      maxleg=3;
+      if (hashindlimbs==0)
+	minleg=2;
+      if (hasforelimbs==0)
+	maxleg=1;
+
+      vtkImageData* Leg[4];
+      
+      for (int leg=minleg;leg<=maxleg;leg++)
+	{
+	  int offset=legparts*leg;
+	  vtkImageData* tmp=vtkpxTransformationUtil::GetMaskImage(input,planes,offset);
+	  Leg[leg]=vtkpxTransformationUtil::GetMaskImage(tmp,planes,offset+1);
+
+	  tmp->Delete();
+	}
+      
+      vtkImageMathematics* m2=vtkImageMathematics::New();
+      m2->SetInput1(input);
+      m2->SetOperationToSubtract();
+  
+      if (hasforelimbs ==1 && hashindlimbs ==1 )
+	{
+	  vtkImageMathematics* m1[3]; 
+	  for (int p=0;p<=2;p++)
+	    {
+	      m1[p]=vtkImageMathematics::New();
+	      if (p<2)
+		{
+		  m1[p]->SetInput1(Leg[2*p+1]);
+		  m1[p]->SetInput2(Leg[2*p]);
+		}
+	      else
+		{
+		  m1[2]->SetInput1(m1[0]->GetOutput());
+		  m1[2]->SetInput2(m1[1]->GetOutput());
+		}
+	      m1[p]->SetOperationToAdd();
+	      m1[p]->Update();
+	    }
+	  m2->SetInput2(m1[2]->GetOutput());
+
+	  //	  vtkpxUtil::SaveAnalyze("Legs",m1[2]->GetOutput(),0);
+
+
+	  for (int p=0;p<=2;p++)
+	    m1[p]->Delete();
+	}
+      else
+	{
+	  vtkImageMathematics* m1=vtkImageMathematics::New();
+	  m1->SetInput1(Leg[minleg]);
+	  m1->SetInput2(Leg[maxleg]);
+	  m1->SetOperationToAdd();
+	  m1->Update();
+	  m2->SetInput2(m1->GetOutput());
+	  //	  vtkpxUtil::SaveAnalyze("Legs",m1->GetOutput(),0);
+	  m1->Delete();
+	}
+      m2->Update();
+      MainTrunk->ShallowCopy(m2->GetOutput());
+      m2->Delete();
+
+      for (int i=minleg;i<=maxleg;i++)
+	{
+	  LegPieces[i]=vtkpxTransformationUtil::ChopLeg(Leg[i],planes,legparts*i+2,1+hasfeet,1);
+	  Leg[i]->Delete();
+	}
+    }
+  else
+    {
+      MainTrunk->ShallowCopy(input);
+    }
+
+  //  vtkpxUtil::SaveAnalyze("MainTrunk",MainTrunk,0);
+
+  // --------------------------------------------------------------------------------
+  // [B] Chop off Tail and Spine
+  // --------------------------------------------------------------------------------
+
+  // Next do tail -- and abdomen top -- two cuts 
+
+  vtkImageData* SpineTailParts[2];
+  for (int ia=0;ia<=1;ia++)
+    SpineTailParts[ia]=NULL;
+
+
+  if ((spinedivisions+hashead)> 0 || taildivisions > 0 ) 
+    {
+      fprintf(stderr,"In Spine or Tail Divisions\n");
+
+      vtkImageData* SpineTail[2];
+
+      int cut[3]; 
+      cut[0]=legparts*2*(hashindlimbs+hasforelimbs);
+      cut[1]=cut[0]+taildivisions;
+      cut[2]=totalplanes;
+      
+      int minpart=0,maxpart=1;
+      if (taildivisions==0)
+	minpart=1;
+      if( (spinedivisions+hashead)==0)
+	maxpart=0;
+
+      for (int part=minpart;part<=maxpart;part++)
+	{
+	  int offset=cut[part];
+	  SpineTail[part]=vtkpxTransformationUtil::GetMaskImage(MainTrunk,planes,offset);
+	}
+
+      vtkImageMathematics* m2a=vtkImageMathematics::New();
+      m2a->SetInput1(MainTrunk);
+      m2a->SetOperationToSubtract();
+      
+      if (maxpart==1 && minpart==0)
+	{
+	  vtkImageMathematics* m1a=vtkImageMathematics::New();
+	  m1a->SetInput1(SpineTail[0]);
+	  m1a->SetInput2(SpineTail[1]);
+	  m1a->SetOperationToAdd();
+	  m1a->Update();
+	  m2a->SetInput2(m1a->GetOutput());
+	  m1a->Delete();
+	}
+      else if (maxpart==0)
+	{
+	  m2a->SetInput2(SpineTail[0]);
+	}
+      else
+	{
+	  m2a->SetInput2(SpineTail[1]);
+	}
+      m2a->Update();
+      MainTrunk->ShallowCopy(m2a->GetOutput());
+      m2a->Delete();
+      
+      for (int p=minpart;p<=maxpart;p++)
+	{
+	  int numcuts=cut[p+1]-cut[p]-1;
+	  fprintf(stderr,"Tail part=%d, numcuts=%d\n",p,numcuts);
+
+	  if (numcuts>0)
+	    {
+	      SpineTailParts[p]=vtkpxTransformationUtil::ChopLeg(SpineTail[p],planes,1+cut[p],numcuts,0);
+	      SpineTail[p]->Delete();
+	    }
+	  else
+	    {
+	      SpineTailParts[p]=SpineTail[p];
+	    }
+	}
+    }
+  
+  append->AddInput(MainTrunk); 
+  MainTrunk->Delete();
+  for (int ia=0;ia<=3;ia++)
+    {
+      if (LegPieces[ia]!=NULL)
+	{
+	  fprintf(stderr,"Adding LegPiece %d\n",ia);
+	  append->AddInput(LegPieces[ia]); 
+	  LegPieces[ia]->Delete();
+	}
+    }
+
+  for (int ia=0;ia<=1;ia++)
+    {
+      if (SpineTailParts[ia]!=NULL)
+	{
+	  append->AddInput(SpineTailParts[ia]); 
+	  SpineTailParts[ia]->Delete();
+	}
+    }
+  append->Update();
+  vtkImageData* model=vtkImageData::New();
+  model->ShallowCopy(append->GetOutput()); 
+  append->Delete();
+  
+  return model;
+}
+// ----------------------------------------------------------------------
+int vtkpxTransformationUtil::GetPlaneNumber(int jointno,int hasfeet,
+						 int hashindlimbs,int hasforelimbs,int hashead, int taildivisions,
+						 int spinedivisions)
+{
+  if ( jointno < 1 ) {   return -1; }
+
+  int legparts=2+(hasfeet>0);
+  int offset=0;
+  int totalhips=0;
+
+  int numpass=(hashindlimbs>0) + (hasforelimbs>0);
+  
+  for (int pass=0; pass< numpass; pass++)
+    {
+      int legpartp = offset+legparts;
+      if (jointno<=legpartp)
+	{
+	  return jointno+totalhips;
+	}
+      totalhips+=2;
+    }
+
+  return jointno + totalhips -1;
+}
+
+vtkPoints* vtkpxTransformationUtil::GetCentroids(vtkImageData* img,double axislength)
+{
+
+  int dim[3]; img->GetDimensions(dim);
+
+  int numjoints=dim[2];
+
+  vtkPoints* jointpoints=vtkPoints::New();
+  jointpoints->SetNumberOfPoints(numjoints*3);
+
+
+  //  vtkpxUtil::SaveAnalyze("tt_joint.hdr",img);
+
+  for (int joint=0;joint<numjoints;joint++)
+    {
+      vtkImageDataGeometryFilter* filt=vtkImageDataGeometryFilter::New();
+      filt->SetInput(img);
+      filt->SetExtent(0,dim[0]-1,
+		      0,dim[1]-1,
+		      joint,joint);
+      filt->Update();
+
+     
+      vtkThresholdPoints* thrPoints=vtkThresholdPoints::New();
+      thrPoints->SetInput(filt->GetOutput());
+      thrPoints->ThresholdBetween(1,250);
+      thrPoints->Update();
+
+      vtkPoints* points=points=vtkPoints::New();
+
+      if (thrPoints->GetOutput()->GetNumberOfPoints()>0)
+	{
+	  vtkPolyDataConnectivityFilter* connectFilter=vtkPolyDataConnectivityFilter::New();
+	  connectFilter->SetInput(thrPoints->GetOutput());
+	  connectFilter->SetExtractionModeToLargestRegion();
+	  connectFilter->Update();
+	  
+	  fprintf(stderr,"Extracted %d Connected %d --> Number of Regions=%d\n",
+		  thrPoints->GetOutput()->GetNumberOfPoints(),
+		  connectFilter->GetOutput()->GetNumberOfPoints(),
+		  connectFilter->GetNumberOfExtractedRegions());
+	  
+	  
+	  points->ShallowCopy(connectFilter->GetOutput()->GetPoints());	  
+	  connectFilter->Delete();
+	} 
+      else
+	{
+	  points->SetNumberOfPoints(1);
+	  points->SetPoint(0,0,0,0);
+	}
+      
+      thrPoints->Delete();
+      filt->Delete();
+      
+      int nump=points->GetNumberOfPoints();
+
+      double centroid[3] = { 0.0,0.0,0.0};
+      for (int i=0;i<nump;i++)
+	{
+	  double p[3]; points->GetPoint(i,p);
+	  for (int ia=0;ia<=2;ia++)
+	    centroid[ia]+=p[ia];
+	}
+
+      if (nump>1)
+	{
+	  for (int ia=0;ia<=2;ia++)
+	    centroid[ia]/=double(nump);
+	}
+
+      jointpoints->SetPoint(joint*3,centroid);
+      jointpoints->SetPoint(joint*3+1,centroid[0]+axislength,centroid[1],centroid[2]);
+      jointpoints->SetPoint(joint*3+2,centroid[0],axislength+centroid[1],centroid[2]);
+
+
+      
+    }
+
+  
+  return jointpoints;
+}
+
diff --git a/bioimagesuite30_src/Registration/vtkpxTransformationUtil.h b/bioimagesuite30_src/Registration/vtkpxTransformationUtil.h
new file mode 100644
index 0000000..cf773b2
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxTransformationUtil.h
@@ -0,0 +1,170 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxTransformationUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxTransformationUtil - a collection of static utility functions
+// .SECTION Description
+// This class contains a collection of <EM>static</EM> utility functions for use elsewhere ala vtkMath
+// These deal with images and transformations.
+// <br> <br> <EM>Copyright (c) 1995-2002 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// This requires pxutil 
+
+#ifndef __vtkpxTransformationUtil_h
+#define __vtkpxTransformationUtil_h
+
+#include "vtkObject.h"
+#include "vtkObjectFactory.h"
+#include "pxutil.h"
+
+class vtkMatrix4x4;
+class vtkThinPlateSplineTransform;
+class vtkpxGridTransform;
+class vtkHomogeneousTransform;
+class vtkAbstractTransform;
+class vtkDataArray;
+class vtkPoints;
+class vtkTransform;
+class vtkpxMatrix;
+class vtkImageData;
+class vtkPolyData;
+class vtkFloatArray;
+
+
+
+class vtkpxTransformationUtil : public vtkObject
+{
+public:
+  static vtkpxTransformationUtil *New();
+  vtkTypeMacro(vtkpxTransformationUtil,vtkObject);
+  
+
+  // -----------------------------------------------------
+  // Transformation Stuff
+  // -----------------------------------------------------
+
+  // Description:
+  // Save And Load Abstract Transformation as matrix/grid/thin-plate-spline
+  static int SaveAbstractTransform(vtkAbstractTransform* tr,const char* fname);
+  static vtkAbstractTransform* LoadAbstractTransform(const char* fname);
+
+
+  // Description:
+  // Matrix I/O
+  static int LoadMatrix(vtkMatrix4x4* mat,const char* fname);
+  static int SaveMatrix(vtkMatrix4x4* mat,const char* fname);
+
+  static int LoadMatrixTransform(vtkTransform* tr,const char* fname);
+  static int SaveMatrixTransform(vtkTransform* tr,const char* fname);
+
+  // Description:
+  // Thin-Plate-Spline I/O
+  static int LoadThinPlateSplineTransform(vtkThinPlateSplineTransform* mat,const char* fname);
+  static int SaveThinPlateSplineTransform(vtkThinPlateSplineTransform* mat,const char* fname);
+
+  // Description:
+  // Thin-Plate-Spline I/O from stream
+  static int LoadThinPlateSplineTransform(vtkThinPlateSplineTransform* mat,gzFile fin);
+  static int SaveThinPlateSplineTransform(vtkThinPlateSplineTransform* mat,FILE* fout);
+
+
+  // Description:
+  // Grid Transform  I/O
+  static int LoadGridTransform(vtkpxGridTransform* mat,const char* fname);
+  static int SaveGridTransform(vtkpxGridTransform* mat,const char* fname);
+
+
+  // Description:
+  // Creates reslice transform given 2 or 3 points (specified by npoints ) stored in vtkPoints 
+  static int     GenerateTransform(vtkTransform* tr,vtkPoints* pt,int npoints=-1);
+
+  // Description:
+  // Fixes mmvreg output to standard coordinate space
+  static void FixMmvregOutput(vtkMatrix4x4* matrix,int permute);
+
+  // Description:
+  // GetJacobian
+  static float GetJacobian(vtkAbstractTransform* tr,vtkpxMatrix* jac,float x,float y,float z);
+
+  // Description:
+  // Mouse Model Stuff
+    // Description:
+  // Create Basis Image
+  static int CreatePolygonalModel(vtkImageData* multiframeinput,vtkPolyData* surface,float threshold=50.0);
+  static vtkImageData* CreateRegionLabelImage(vtkImageData* input,float sigma);
+  static vtkImageData* CreateRegionLabelImage(vtkImageData* input,float sigma,vtkPolyData* surface);
+  static vtkImageData* ChopLeg(vtkImageData* Leg,vtkFloatArray* planes,int offset,int numcuts,int legmode=1);
+
+  static vtkImageData* GetMaskImage(vtkImageData* input,int above,double n[3],double c[3],double offset);
+  static vtkImageData* GetMaskImage(vtkImageData* input,vtkFloatArray* planes,int offset);
+  static vtkImageData* GetMaskImage(vtkImageData* input,vtkFloatArray* planes,int offset,int flip);
+  static vtkImageData* CreateWholeBodyRegionLabelImage(vtkImageData* input,vtkFloatArray* planes,int hasfeet,
+						       int hashindlimbs,int hasforelimbs,int hashead, int taildivisions,
+						       int spinedivisions);
+
+
+  // Joint Locations
+  // ----------------------------------------
+  static vtkPoints* GetCentroids(vtkImageData* img,double axislength=10.0);
+  static int        GetPlaneNumber(int jointno,int hasfeet,
+				   int hashindlimbs,int hasforelimbs,int hashead, int taildivisions,
+				   int spinedivisions);
+    
+
+
+
+ 
+};
+#endif
+
diff --git a/bioimagesuite30_src/Registration/vtkpxWeightedLandmarkTransform.cpp b/bioimagesuite30_src/Registration/vtkpxWeightedLandmarkTransform.cpp
new file mode 100644
index 0000000..5d52100
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxWeightedLandmarkTransform.cpp
@@ -0,0 +1,399 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkpxWeightedLandmarkTransform.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+
+//----------------------------------------------------------------------------
+vtkpxWeightedLandmarkTransform* vtkpxWeightedLandmarkTransform::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxWeightedLandmarkTransform");
+  if(ret)
+    {
+    return (vtkpxWeightedLandmarkTransform*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxWeightedLandmarkTransform;
+}
+
+//----------------------------------------------------------------------------
+vtkpxWeightedLandmarkTransform::vtkpxWeightedLandmarkTransform()
+{
+  this->Weights=NULL;
+}
+
+//----------------------------------------------------------------------------
+vtkpxWeightedLandmarkTransform::~vtkpxWeightedLandmarkTransform()
+{
+  this->SetWeights(NULL);
+}
+
+//----------------------------------------------------------------------------
+// Update the 4x4 matrix. Updates are only done as necessary.
+ 
+void vtkpxWeightedLandmarkTransform::InternalUpdate()
+{
+  if (this->Weights==NULL)
+    {
+      vtkDebugMacro(<<"No Weights Specified! Using vtkLandmarkTransform::InternalUpdate() Instead");
+      vtkLandmarkTransform::InternalUpdate();
+      return;
+    }
+
+  
+  vtkIdType i;
+  int j;
+
+  if (this->SourceLandmarks == NULL || this->TargetLandmarks == NULL)
+    {
+      this->Matrix->Identity();
+      return;
+    }
+
+  // --- compute the necessary transform to match the two sets of landmarks ---
+
+  /*
+    The solution is based on
+    Berthold K. P. Horn (1987),
+    "Closed-form solution of absolute orientation using unit quaternions,"
+    Journal of the Optical Society of America A, 4:629-642
+  */
+
+  // Original python implementation by David G. Gobbi
+  // Weight Stuff added by Xenios Papademetris
+
+  const vtkIdType N_PTS = this->SourceLandmarks->GetNumberOfPoints();
+  if(N_PTS != this->TargetLandmarks->GetNumberOfPoints())
+    {
+      vtkErrorMacro(<<"Update: Source and Target Landmarks contain a different number of points");
+      return;
+    }
+
+  if(N_PTS != this->Weights->GetSize()[0] || this->Weights->GetSize()[1]!=1)
+    {
+      vtkDebugMacro(<<"Update: Source Landmarks and Weight Matrix contain a different number of points");
+      vtkDebugMacro(<<"Using vtkLandmarkTransform::InternalUpdate() Instead");
+      vtkLandmarkTransform::InternalUpdate();
+      return;
+    }
+
+
+  // -- if no points, stop here
+
+  if (N_PTS == 0)
+    {
+      this->Matrix->Identity();
+      return;
+    }
+  
+  vtkDebugMacro(<<"Using Weighted Least Squares Landmark Fitting\n");
+
+  // -- find the centroid of each set --
+
+  float source_centroid[3]={0,0,0};
+  float target_centroid[3]={0,0,0};
+  double *p;
+
+  for(i=0;i<N_PTS;i++)
+    {
+      p = this->SourceLandmarks->GetPoint(i);
+      source_centroid[0] += p[0];
+      source_centroid[1] += p[1];
+      source_centroid[2] += p[2];
+      p = this->TargetLandmarks->GetPoint(i);
+      target_centroid[0] += p[0];
+      target_centroid[1] += p[1];
+      target_centroid[2] += p[2];
+    }
+  source_centroid[0] /= float(N_PTS);
+  source_centroid[1] /= float(N_PTS);
+  source_centroid[2] /= float(N_PTS);
+  target_centroid[0] /= float(N_PTS);
+  target_centroid[1] /= float(N_PTS);
+  target_centroid[2] /= float(N_PTS);
+
+  // -- if only one point, stop right here
+
+  if (N_PTS == 1)
+    {
+      this->Matrix->Identity();
+      this->Matrix->Element[0][3] = target_centroid[0] - source_centroid[0];
+      this->Matrix->Element[1][3] = target_centroid[1] - source_centroid[1];
+      this->Matrix->Element[2][3] = target_centroid[2] - source_centroid[2];
+      return;
+    }
+  
+  // -- build the 3x3 matrix M --
+
+  float M[3][3];
+  float AAT[3][3];
+  for(i=0;i<3;i++) 
+    {
+      AAT[i][0] = M[i][0]=0.0F; // fill M with zeros
+      AAT[i][1] = M[i][1]=0.0F; 
+      AAT[i][2] = M[i][2]=0.0F; 
+    }
+  vtkIdType pt;
+  double a[3],b[3];
+  float sa=0.0F,sb=0.0F;
+  for(pt=0;pt<N_PTS;pt++)
+    {
+      float wgt=this->Weights->GetDirectElement(pt,0);
+
+
+      // get the origin-centred point (a) in the source set
+      this->SourceLandmarks->GetPoint(pt,a);
+      a[0] -= source_centroid[0];
+      a[1] -= source_centroid[1];
+      a[2] -= source_centroid[2];
+      // get the origin-centred point (b) in the target set
+      this->TargetLandmarks->GetPoint(pt,b);
+      b[0] -= target_centroid[0];
+      b[1] -= target_centroid[1];
+      b[2] -= target_centroid[2];
+      // accumulate the products a*T(b) into the matrix M
+      for(i=0;i<3;i++) 
+	{
+	  M[i][0] += wgt*a[i]*b[0];
+	  M[i][1] += wgt*a[i]*b[1];
+	  M[i][2] += wgt*a[i]*b[2];
+	  
+	  // for the affine transform, compute ((a.a^t)^-1 . a.b^t)^t.
+	  // a.b^t is already in M.  here we put a.a^t in AAT.
+	  if (this->Mode == VTK_LANDMARK_AFFINE)
+	    {
+	      AAT[i][0] += wgt*a[i]*a[0];
+	      AAT[i][1] += wgt*a[i]*a[1];
+	      AAT[i][2] += wgt*a[i]*a[2];
+	    }
+	}
+      // accumulate scale factors (if desired)
+      sa += wgt*(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
+      sb += wgt*(b[0]*b[0]+b[1]*b[1]+b[2]*b[2]);
+    }
+  
+  if(this->Mode == VTK_LANDMARK_AFFINE)
+    {
+      // AAT = (a.a^t)^-1
+      vtkMath::Invert3x3(AAT,AAT);
+      
+      // M = (a.a^t)^-1 . a.b^t
+      vtkMath::Multiply3x3(AAT,M,M);
+      
+      // this->Matrix = M^t
+      for(i=0;i<3;++i) 
+	{
+	  for(j=0;j<3;++j)
+	    {
+	      this->Matrix->Element[i][j] = M[j][i];
+	    }
+	}
+    }
+  else //AFFINE
+    {
+      // compute required scaling factor (if desired)
+      float scale = (float)sqrt(sb/sa);
+      
+      // -- build the 4x4 matrix N --
+      
+      float Ndata[4][4];
+      float *N[4];
+      for(i=0;i<4;i++)
+	{
+	  N[i] = Ndata[i];
+	  N[i][0]=0.0F; // fill N with zeros
+	  N[i][1]=0.0F;
+	  N[i][2]=0.0F;
+	  N[i][3]=0.0F;
+	}
+      // on-diagonal elements
+      N[0][0] = M[0][0]+M[1][1]+M[2][2];
+      N[1][1] = M[0][0]-M[1][1]-M[2][2];
+      N[2][2] = -M[0][0]+M[1][1]-M[2][2];
+      N[3][3] = -M[0][0]-M[1][1]+M[2][2];
+      // off-diagonal elements
+      N[0][1] = N[1][0] = M[1][2]-M[2][1];
+      N[0][2] = N[2][0] = M[2][0]-M[0][2];
+      N[0][3] = N[3][0] = M[0][1]-M[1][0];
+      
+      N[1][2] = N[2][1] = M[0][1]+M[1][0];
+      N[1][3] = N[3][1] = M[2][0]+M[0][2];
+      N[2][3] = N[3][2] = M[1][2]+M[2][1];
+      
+      // -- eigen-decompose N (is symmetric) --
+      
+      float eigenvectorData[4][4];
+      float *eigenvectors[4],eigenvalues[4];
+      
+      eigenvectors[0] = eigenvectorData[0];
+      eigenvectors[1] = eigenvectorData[1];
+      eigenvectors[2] = eigenvectorData[2];
+      eigenvectors[3] = eigenvectorData[3];
+      
+      vtkMath::JacobiN(N,4,eigenvalues,eigenvectors);
+      
+      // the eigenvector with the largest eigenvalue is the quaternion we want
+      // (they are sorted in decreasing order for us by JacobiN)
+      double w,x,y,z;
+      
+      // first: if points are collinear, choose the quaternion that 
+      // results in the smallest rotation.
+      if (eigenvalues[0] == eigenvalues[1] || N_PTS == 2)
+	{
+	  double s0[3],t0[3],s1[3],t1[3];
+	  this->SourceLandmarks->GetPoint(0,s0);
+	  this->TargetLandmarks->GetPoint(0,t0);
+	  this->SourceLandmarks->GetPoint(1,s1);
+	  this->TargetLandmarks->GetPoint(1,t1);
+	  
+	  double ds[3],dt[3];
+	  double rs = 0, rt = 0;
+	  for (i = 0; i < 3; i++)
+	    {
+	      ds[i] = s1[i] - s0[i];      // vector between points
+	      rs += ds[i]*ds[i];
+	      dt[i] = t1[i] - t0[i];
+	      rt += dt[i]*dt[i];
+	    }
+	  
+	  // normalize the two vectors
+	  rs = sqrt(rs);
+	  ds[0] /= rs; ds[1] /= rs; ds[2] /= rs; 
+	  rt = sqrt(rt);
+	  dt[0] /= rt; dt[1] /= rt; dt[2] /= rt; 
+	  
+	  // take dot & cross product
+	  w = ds[0]*dt[0] + ds[1]*dt[1] + ds[2]*dt[2];
+	  x = ds[1]*dt[2] - ds[2]*dt[1];
+	  y = ds[2]*dt[0] - ds[0]*dt[2];
+	  z = ds[0]*dt[1] - ds[1]*dt[0];
+	  
+	  double r = sqrt(x*x + y*y + z*z);
+	  double theta = atan2(r,w);
+	  
+	  // construct quaternion
+	  w = cos(theta/2);
+	  if (r != 0)
+	    {
+	      r = sin(theta/2)/r;
+	      x = x*r;
+	      y = y*r;
+	      z = z*r;
+	    }
+	  else // rotation by 180 degrees: special case
+	    {
+	      // rotate around a vector perpendicular to ds
+	      vtkMath::Perpendiculars(ds,dt,0,0);
+	      r = sin(theta/2);
+	      x = dt[0]*r;
+	      y = dt[1]*r;
+	      z = dt[2]*r;
+	    }
+	}
+      else // points are not collinear
+	{
+	  w = eigenvectors[0][0];
+	  x = eigenvectors[1][0];
+	  y = eigenvectors[2][0];
+	  z = eigenvectors[3][0];
+	}
+      
+      // convert quaternion to a rotation matrix
+      
+      double ww = w*w;
+      double wx = w*x;
+      double wy = w*y;
+      double wz = w*z;
+      
+      double xx = x*x;
+      double yy = y*y;
+      double zz = z*z;
+      
+      double xy = x*y;
+      double xz = x*z;
+      double yz = y*z;
+      
+      this->Matrix->Element[0][0] = ww + xx - yy - zz; 
+      this->Matrix->Element[1][0] = 2.0*(wz + xy);
+      this->Matrix->Element[2][0] = 2.0*(-wy + xz);
+      
+      this->Matrix->Element[0][1] = 2.0*(-wz + xy);  
+      this->Matrix->Element[1][1] = ww - xx + yy - zz;
+      this->Matrix->Element[2][1] = 2.0*(wx + yz);
+      
+      this->Matrix->Element[0][2] = 2.0*(wy + xz);
+      this->Matrix->Element[1][2] = 2.0*(-wx + yz);
+      this->Matrix->Element[2][2] = ww - xx - yy + zz;
+      
+      if (this->Mode != VTK_LANDMARK_RIGIDBODY)
+	{ // add in the scale factor (if desired)
+	  for(i=0;i<3;i++) 
+	    {
+	      this->Matrix->Element[i][0] *= scale;
+	      this->Matrix->Element[i][1] *= scale;
+	      this->Matrix->Element[i][2] *= scale;
+	    }
+	}
+    }
+  
+  // the translation is given by the difference in the transformed source
+  // centroid and the target centroid
+  double sx, sy, sz;
+  
+  sx = this->Matrix->Element[0][0] * source_centroid[0] +
+    this->Matrix->Element[0][1] * source_centroid[1] +
+    this->Matrix->Element[0][2] * source_centroid[2];
+  sy = this->Matrix->Element[1][0] * source_centroid[0] +
+    this->Matrix->Element[1][1] * source_centroid[1] +
+    this->Matrix->Element[1][2] * source_centroid[2];
+  sz = this->Matrix->Element[2][0] * source_centroid[0] +
+    this->Matrix->Element[2][1] * source_centroid[1] +
+    this->Matrix->Element[2][2] * source_centroid[2];
+  
+  this->Matrix->Element[0][3] = target_centroid[0] - sx;
+  this->Matrix->Element[1][3] = target_centroid[1] - sy;
+  this->Matrix->Element[2][3] = target_centroid[2] - sz;
+  
+  // fill the bottom row of the 4x4 matrix
+  this->Matrix->Element[3][0] = 0.0;
+  this->Matrix->Element[3][1] = 0.0;
+  this->Matrix->Element[3][2] = 0.0;
+  this->Matrix->Element[3][3] = 1.0;
+  
+  this->Matrix->Modified();
+}
+
+
+
+
diff --git a/bioimagesuite30_src/Registration/vtkpxWeightedLandmarkTransform.h b/bioimagesuite30_src/Registration/vtkpxWeightedLandmarkTransform.h
new file mode 100644
index 0000000..dc87c9a
--- /dev/null
+++ b/bioimagesuite30_src/Registration/vtkpxWeightedLandmarkTransform.h
@@ -0,0 +1,78 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkpxWeightedLandmarkTransform - a linear transform specified by two corresponding point sets
+// .SECTION Description
+// A vtkpxWeightedLandmarkTransform is defined by two sets of landmarks, the 
+// transform computed gives the best fit mapping one onto the other, in a 
+// least squares sense. The indices are taken to correspond, so point 1 
+// in the first set will get mapped close to point 1 in the second set, 
+// etc. Call SetSourceLandmarks and SetTargetLandmarks to specify the two
+// sets of landmarks, ensure they have the same number of points.
+// .SECTION Caveats
+// Whenever you add, subtract, or set points you must call Modified()
+// on the vtkPoints object, or the transformation might not update.
+// .SECTION Modification
+// Added Weight Parameter to Establish a weighted Least Squares instead
+// Xenios Papademetris November 2002
+// .SECTION see also
+// vtkLinearTransform
+
+#ifndef __vtkpxWeightedLandmarkTransform_h
+#define __vtkpxWeightedLandmarkTransform_h
+
+#include "vtkLandmarkTransform.h"
+#include "vtkMatrix4x4.h"
+#include "vtkPoints.h"
+#include "vtkpxMatrix.h"
+
+class vtkpxWeightedLandmarkTransform : public vtkLandmarkTransform
+{
+public:
+  static vtkpxWeightedLandmarkTransform *New();
+  vtkTypeMacro(vtkpxWeightedLandmarkTransform,vtkLandmarkTransform);
+
+  vtkSetObjectMacro(Weights,vtkpxMatrix);
+  vtkGetObjectMacro(Weights, vtkpxMatrix);
+
+
+protected:
+
+  vtkpxWeightedLandmarkTransform();
+  virtual ~vtkpxWeightedLandmarkTransform();
+
+  // Update the matrix from the quaternion.
+  void InternalUpdate();
+
+  vtkpxMatrix* Weights;
+};
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/CMakeLists.txt b/bioimagesuite30_src/Segmentation/CMakeLists.txt
new file mode 100644
index 0000000..7688f45
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/CMakeLists.txt
@@ -0,0 +1,169 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+SET(KITBASE Segmentation)
+SET(KIT vtkpx${KITBASE})
+
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/${KITBASE})
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Imaging)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Legacy)
+INCLUDE_DIRECTORIES(${ITK_INCLUDE_DIRS})
+
+SET (KITSRCS
+#
+#
+vtkpxLogExponentialFit.cpp
+vtkpxImageRobustHistogram.cpp
+vtkpxHistogramSegmentation.cpp
+vtkpxMRFSegmentation.cpp
+#
+vtkpxBrainPreSegment.cpp
+#
+#
+vtkpxAbstractBiasFieldCorrection.cpp
+vtkpxSliceBiasFieldCorrection.cpp
+vtkpxPolynomialBiasFieldCorrection.cpp
+#
+vtkpxImageTensorSpline.cpp
+#
+# Old Levelset stuff
+#
+vtkpxLevelSetUtil.cpp
+vtkpxBaseLevelSetFilter.cpp
+vtkpxTissueLevelSetFilter.cpp
+vtkpxCoupledTissueLevelSetFilter.cpp
+itkpxLevelSetCallback.h
+itkImageToVTKImageFilter.txx  
+itkVTKImageToImageFilter.txx
+vtkjwsSignedDanielssonDistanceMapImageFilter.cpp
+vtkbisBinaryThinningFilter.cpp
+#
+# John's Skull Stripping Stuff
+#
+vtkjoBETHistogram.cpp
+#vtkjoBETSurface.cpp
+vtkjoBETImageFilter.cpp
+#vtkjoRobustBETImageFilter.cpp
+vtkjoPolyDataRobustBETTraining.cpp
+vtkjoScalePolyData.cpp
+#
+vtkpxExponentialFitT1.cpp
+)
+
+IF (BIOIMAGESUITE3_EXPERIMENTAL)
+  SET (KITSRCS
+    ${KITSRCS}
+    vtkpxApproximateRayleigh.cpp
+    vtkpxExponentialFit.cpp
+    vtkpxFuzzyCMeansSegmentation.cpp	
+    vtkpxMultiEchoSegmentation.cpp
+    #vtkpxMonoExponentialFatSegmentation
+    #vtkpxBiExponentialFatSegmentation
+    #vtkpxSplineFitBiasFieldCorrection
+    vtkpxRegionSegmentation.cpp
+    #vtkpxCreateFatMap.cpp
+    vtkpxBrainStripUtil.cpp
+    vtkpxNonLinearFit.cpp
+    #
+    vtkpxDualResolutionCoupledLevelSetFilter.cpp)
+ENDIF (BIOIMAGESUITE3_EXPERIMENTAL)
+
+
+SET_SOURCE_FILES_PROPERTIES(
+vtkpxBaseLevelSetFilter.cpp
+ABSTRACT
+)
+
+SET_SOURCE_FILES_PROPERTIES(
+itkpxLevelSetCallback.h
+itkImageToVTKImageFilter.txx
+itkVTKImageToImageFilter.txx
+ WRAP_EXCLUDE
+)
+
+SET(KITLIBS
+  vtkpxImagingTCL
+  vtkpxImaging
+  vtkpxLegacyTCL
+  vtkpxLegacy
+  vtkpxCommon
+  vtkpxCommonTCL
+  numerics
+  vtkCommonTCL
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+)
+
+SET(KITJAVALIBS
+  vtkpxImagingJava
+  vtkpxImaging
+  vtkpxLegacyJava
+  vtkpxLegacy
+  vtkpxCommon
+  vtkpxCommonJava
+  numerics
+  ${BIOIMAGESUITE3_COMMON_JAVALIBS}
+)
+
+
+SET (KITEXTRAFILES
+  Segmentation/itkpxSaturateImageFilter.h
+  Segmentation/itkpxSaturateImageFilter.txx  
+  Segmentation/itkpxTissueSegmentationCoupledLevelSetFunction.h
+  Segmentation/itkpxTissueSegmentationCoupledLevelSetFunction.txx
+  Segmentation/itkpxTissueSegmentationCoupledLevelSetImageFilter.h
+  Segmentation/itkpxTissueSegmentationCoupledLevelSetImageFilter.txx
+  Segmentation/itkpxTissueSegmentationLevelSetFunction.h
+  Segmentation/itkpxTissueSegmentationLevelSetFunction.txx
+  Segmentation/itkpxTissueSegmentationLevelSetImageFilter.h
+  Segmentation/itkpxTissueSegmentationLevelSetImageFilter.txx
+  Segmentation/itkBinaryThinningImageFilter3D.h
+  Segmentation/itkBinaryThinningImageFilter3D.txx
+  Segmentation/vtkITKMyUtility.h
+  Segmentation/vtkITKUtility.h
+  )
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+
+SET (KITTCLSRCS )
+bis_complex("Segmentation" ${KIT} ${FILELIST})
+
+
+IF(BIOIMAGESUITE3_HAVE_COUPLEDLEVELSET_SOURCE)
+ADD_EXECUTABLE (TestXiaolanSegmentation TestXiaolanSegmentation.cpp)
+ENDIF(BIOIMAGESUITE3_HAVE_COUPLEDLEVELSET_SOURCE)
+
diff --git a/bioimagesuite30_src/Segmentation/itkBinaryThinningImageFilter3D.h b/bioimagesuite30_src/Segmentation/itkBinaryThinningImageFilter3D.h
new file mode 100644
index 0000000..ef33ef4
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkBinaryThinningImageFilter3D.h
@@ -0,0 +1,185 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef __itkBinaryThinningImageFilter3D_h
+#define __itkBinaryThinningImageFilter3D_h
+
+#include <itkNeighborhoodIterator.h>
+#include <itkImageToImageFilter.h>
+#include <itkImageRegionIteratorWithIndex.h>
+#include <itkConstantBoundaryCondition.h>
+
+namespace itk
+{
+/** \class BinaryThinningImageFilter3D
+*
+* \brief This filter computes one-pixel-wide skeleton of a 3D input image.
+*
+* This class is parametrized over the type of the input image
+* and the type of the output image.
+* 
+* The input is assumed to be a binary image. All non-zero valued voxels
+* are set to 1 internally to simplify the computation. The filter will
+* produce a skeleton of the object.  The output background values are 0,
+* and the foreground values are 1.
+* 
+* A 26-neighbourhood configuration is used for the foreground and a
+* 6-neighbourhood configuration for the background. Thinning is performed
+* symmetrically in order to guarantee that the skeleton lies medial within
+* the object.
+*
+* This filter is a parallel thinning algorithm and is an implementation
+* of the algorithm described in:
+* 
+* T.C. Lee, R.L. Kashyap, and C.N. Chu.
+* Building skeleton models via 3-D medial surface/axis thinning algorithms.
+* Computer Vision, Graphics, and Image Processing, 56(6):462--478, 1994.
+* 
+* To do: Make use of multi-threading.
+*
+* \author Hanno Homann, Oxford University, Wolfson Medical Vision Lab, UK.
+* 
+* \sa MorphologyImageFilter
+* \ingroup ImageEnhancement MathematicalMorphologyImageFilters
+*/
+
+template <class TInputImage,class TOutputImage>
+class BinaryThinningImageFilter3D :
+    public ImageToImageFilter<TInputImage,TOutputImage>
+{
+public:
+  /** Standard class typedefs. */
+  typedef BinaryThinningImageFilter3D    Self;
+  typedef ImageToImageFilter<TInputImage,TOutputImage> Superclass;
+  typedef SmartPointer<Self> Pointer;
+  typedef SmartPointer<const Self> ConstPointer;
+
+  /** Method for creation through the object factory */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro( BinaryThinningImageFilter3D, ImageToImageFilter );
+
+  /** Type for input image. */
+  typedef   TInputImage       InputImageType;
+
+  /** Type for output image: Skelenton of the object.  */
+  typedef   TOutputImage      OutputImageType;
+
+  /** Type for the region of the input image. */
+  typedef typename InputImageType::RegionType RegionType;
+
+  /** Type for the index of the input image. */
+  typedef typename RegionType::IndexType  IndexType;
+
+  /** Type for the pixel type of the input image. */
+  typedef typename InputImageType::PixelType InputImagePixelType ;
+
+  /** Type for the pixel type of the input image. */
+  typedef typename OutputImageType::PixelType OutputImagePixelType ;
+
+  /** Type for the size of the input image. */
+  typedef typename RegionType::SizeType SizeType;
+
+  /** Pointer Type for input image. */
+  typedef typename InputImageType::ConstPointer InputImagePointer;
+
+  /** Pointer Type for the output image. */
+  typedef typename OutputImageType::Pointer OutputImagePointer;
+  
+  /** Boundary condition type for the neighborhood iterator */
+  typedef ConstantBoundaryCondition< TInputImage > ConstBoundaryConditionType;
+  
+  /** Neighborhood iterator type */
+  typedef NeighborhoodIterator<TInputImage, ConstBoundaryConditionType> NeighborhoodIteratorType;
+  
+  /** Neighborhood type */
+  typedef typename NeighborhoodIteratorType::NeighborhoodType NeighborhoodType;
+
+  /** Get Skelenton by thinning image. */
+  OutputImageType * GetThinning(void);
+
+  /** ImageDimension enumeration   */
+  itkStaticConstMacro(InputImageDimension, unsigned int,
+                      TInputImage::ImageDimension );
+  itkStaticConstMacro(OutputImageDimension, unsigned int,
+                      TOutputImage::ImageDimension );
+
+#ifdef ITK_USE_CONCEPT_CHECKING
+  /** Begin concept checking */
+  itkConceptMacro(SameDimensionCheck,
+    (Concept::SameDimension<InputImageDimension, 3>));
+  itkConceptMacro(SameTypeCheck,
+    (Concept::SameType<InputImagePixelType, OutputImagePixelType>));
+  itkConceptMacro(InputAdditiveOperatorsCheck,
+    (Concept::AdditiveOperators<InputImagePixelType>));
+  itkConceptMacro(InputConvertibleToIntCheck,
+    (Concept::Convertible<InputImagePixelType, int>));
+  itkConceptMacro(IntConvertibleToInputCheck,
+    (Concept::Convertible<int, InputImagePixelType>));
+  itkConceptMacro(InputIntComparableCheck,
+    (Concept::Comparable<InputImagePixelType, int>));
+  /** End concept checking */
+#endif
+
+protected:
+  BinaryThinningImageFilter3D();
+  virtual ~BinaryThinningImageFilter3D() {};
+  void PrintSelf(std::ostream& os, Indent indent) const;
+
+  /** Compute thinning Image. */
+  void GenerateData();
+
+  /** Prepare data. */
+  void PrepareData();
+
+  /**  Compute thinning Image. */
+  void ComputeThinImage();
+  
+  /**  isEulerInvariant [Lee94] */
+  bool isEulerInvariant(NeighborhoodType neighbors, int *LUT);
+  void fillEulerLUT(int *LUT);  
+  /**  isSimplePoint [Lee94] */
+  bool isSimplePoint(NeighborhoodType neighbors);
+  /**  Octree_labeling [Lee94] */
+  void Octree_labeling(int octant, int label, int *cube);
+
+
+private:   
+  BinaryThinningImageFilter3D(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+}; // end of BinaryThinningImageFilter3D class
+
+} //end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkBinaryThinningImageFilter3D.txx"
+#endif
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/itkBinaryThinningImageFilter3D.txx b/bioimagesuite30_src/Segmentation/itkBinaryThinningImageFilter3D.txx
new file mode 100644
index 0000000..4c1b2a9
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkBinaryThinningImageFilter3D.txx
@@ -0,0 +1,1000 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef _itkBinaryThinningImageFilter3D_txx
+#define _itkBinaryThinningImageFilter3D_txx
+
+#include <iostream>
+
+#include "itkBinaryThinningImageFilter3D.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkImageRegionIterator.h"
+#include "itkNeighborhoodIterator.h"
+#include <vector>
+
+namespace itk
+{
+
+/**
+ *    Constructor
+ */
+template <class TInputImage,class TOutputImage>
+BinaryThinningImageFilter3D<TInputImage,TOutputImage>
+::BinaryThinningImageFilter3D()
+{
+
+  this->SetNumberOfRequiredOutputs( 1 );
+
+  OutputImagePointer thinImage = OutputImageType::New();
+  this->SetNthOutput( 0, thinImage.GetPointer() );
+
+}
+
+/**
+ *  Return the thinning Image pointer
+ */
+template <class TInputImage,class TOutputImage>
+typename BinaryThinningImageFilter3D<
+  TInputImage,TOutputImage>::OutputImageType * 
+BinaryThinningImageFilter3D<TInputImage,TOutputImage>
+::GetThinning(void)
+{
+  return  dynamic_cast< OutputImageType * >(
+    this->ProcessObject::GetOutput(0) );
+}
+
+
+/**
+ *  Prepare data for computation
+ *  Copy the input image to the output image, changing from the input
+ *  type to the output type.
+ */
+template <class TInputImage,class TOutputImage>
+void 
+BinaryThinningImageFilter3D<TInputImage,TOutputImage>
+::PrepareData(void) 
+{
+  
+  itkDebugMacro(<< "PrepareData Start");
+  OutputImagePointer thinImage = GetThinning();
+
+  InputImagePointer  inputImage  = 
+    dynamic_cast<const TInputImage  *>( ProcessObject::GetInput(0) );
+
+  thinImage->SetBufferedRegion( thinImage->GetRequestedRegion() );
+  thinImage->Allocate();
+
+  typename OutputImageType::RegionType region  = thinImage->GetRequestedRegion();
+
+
+  ImageRegionConstIterator< TInputImage >  it( inputImage,  region );
+  ImageRegionIterator< TOutputImage > ot( thinImage,  region );
+
+  it.GoToBegin();
+  ot.GoToBegin();
+
+  itkDebugMacro(<< "PrepareData: Copy input to output");
+ 
+  // Copy the input to the output, changing all foreground pixels to
+  // have value 1 in the process.
+  while( !ot.IsAtEnd() )
+      {
+      if ( it.Get() )
+        {
+        ot.Set( NumericTraits<OutputImagePixelType>::One );
+        }
+      else
+        {
+        ot.Set( NumericTraits<OutputImagePixelType>::Zero );
+        }
+      ++it;
+      ++ot;
+      }
+  itkDebugMacro(<< "PrepareData End");    
+}
+
+/**
+ *  Post processing for computing thinning
+ */
+template <class TInputImage,class TOutputImage>
+void 
+BinaryThinningImageFilter3D<TInputImage,TOutputImage>
+::ComputeThinImage() 
+{
+  itkDebugMacro( << "ComputeThinImage Start");
+  OutputImagePointer thinImage = GetThinning();
+
+  typename OutputImageType::RegionType region = thinImage->GetRequestedRegion();
+  
+  ConstBoundaryConditionType boundaryCondition;
+  boundaryCondition.SetConstant( 0 );
+
+  typename NeighborhoodIteratorType::RadiusType radius;
+  radius.Fill(1);
+  NeighborhoodIteratorType ot( radius, thinImage, region );
+  ot.SetBoundaryCondition( boundaryCondition );
+
+  std::vector < IndexType > simpleBorderPoints;
+  typename std::vector < IndexType >::iterator simpleBorderPointsIt;
+
+  // Define offsets
+  typedef typename NeighborhoodIteratorType::OffsetType OffsetType;
+  OffsetType N   = {{ 0,-1, 0}};  // north
+  OffsetType S   = {{ 0, 1, 0}};  // south
+  OffsetType E   = {{ 1, 0, 0}};  // east
+  OffsetType W   = {{-1, 0, 0}};  // west
+  OffsetType U   = {{ 0, 0, 1}};  // up
+  OffsetType B   = {{ 0, 0,-1}};  // bottom
+
+  // prepare Euler LUT [Lee94]
+  int eulerLUT[256]; 
+  fillEulerLUT( eulerLUT );
+  // Loop through the image several times until there is no change.
+  int unchangedBorders = 0;
+  while( unchangedBorders < 6 )  // loop until no change for all the six border types
+  {
+    unchangedBorders = 0;
+    for( int currentBorder = 1; currentBorder <= 6; currentBorder++)
+    {
+      // Loop through the image.
+      for ( ot.GoToBegin(); !ot.IsAtEnd(); ++ot )
+      { 
+        // check if point is foreground
+        if ( ot.GetCenterPixel() != 1 )
+        {
+          continue;         // current point is already background 
+        }
+        // check 6-neighbors if point is a border point of type currentBorder
+        bool isBorderPoint = false;
+        if( currentBorder == 1 && ot.GetPixel(N)<=0 )
+          isBorderPoint = true;
+        if( currentBorder == 2 && ot.GetPixel(S)<=0 )
+          isBorderPoint = true;
+        if( currentBorder == 3 && ot.GetPixel(E)<=0 )
+          isBorderPoint = true;
+        if( currentBorder == 4 && ot.GetPixel(W)<=0 )
+          isBorderPoint = true;
+        if( currentBorder == 5 && ot.GetPixel(U)<=0 )
+          isBorderPoint = true;
+        if( currentBorder == 6 && ot.GetPixel(B)<=0 )
+          isBorderPoint = true;
+        if( !isBorderPoint )
+        {
+          continue;         // current point is not deletable
+        }        
+        // check if point is the end of an arc
+        int numberOfNeighbors = -1;   // -1 and not 0 because the center pixel will be counted as well  
+        for( int i = 0; i < 27; i++ ) // i =  0..26
+          if( ot.GetPixel(i)==1 )
+            numberOfNeighbors++;
+
+        if( numberOfNeighbors == 1 )
+        {
+          continue;         // current point is not deletable
+        }
+
+        // check if point is Euler invariant
+        if( !isEulerInvariant( ot.GetNeighborhood(), eulerLUT ) )
+        {
+          continue;         // current point is not deletable
+        }
+
+        // check if point is simple (deletion does not change connectivity in the 3x3x3 neighborhood)
+        if( !isSimplePoint( ot.GetNeighborhood() ) )
+        {
+          continue;         // current point is not deletable
+        }
+
+        // add all simple border points to a list for sequential re-checking
+        simpleBorderPoints.push_back( ot.GetIndex() );
+      } // end image iteration loop
+
+      // sequential re-checking to preserve connectivity when
+      // deleting in a parallel way
+      bool noChange = true;
+      for( simpleBorderPointsIt=simpleBorderPoints.begin(); simpleBorderPointsIt!=simpleBorderPoints.end(); simpleBorderPointsIt++)
+      {
+      	// 1. Set simple border point to 0
+        thinImage->SetPixel( *simpleBorderPointsIt, NumericTraits<OutputImagePixelType>::Zero);
+        // 2. Check if neighborhood is still connected
+        ot.SetLocation( *simpleBorderPointsIt );
+        if( !isSimplePoint( ot.GetNeighborhood() ) )
+        {
+          // we cannot delete current point, so reset
+          thinImage->SetPixel( *simpleBorderPointsIt, NumericTraits<OutputImagePixelType>::One );
+        }
+        else
+        {
+          noChange = false;
+        }
+      }
+      if( noChange )
+        unchangedBorders++;
+
+      simpleBorderPoints.clear();
+    } // end currentBorder for loop
+  } // end unchangedBorders while loop
+
+  itkDebugMacro( << "ComputeThinImage End");
+}
+
+/**
+ *  Generate ThinImage
+ */
+template <class TInputImage,class TOutputImage>
+void 
+BinaryThinningImageFilter3D<TInputImage,TOutputImage>
+::GenerateData() 
+{
+
+  this->PrepareData();
+
+  itkDebugMacro(<< "GenerateData: Computing Thinning Image");
+  this->ComputeThinImage();
+} // end GenerateData()
+
+/** 
+ * Fill the Euler look-up table (LUT) for later check of the Euler invariance. (see [Lee94])
+ */
+template <class TInputImage,class TOutputImage>
+void 
+BinaryThinningImageFilter3D<TInputImage,TOutputImage>
+::fillEulerLUT(int *LUT)
+{
+  LUT[1]  =  1;
+  LUT[3]  = -1;
+  LUT[5]  = -1;
+  LUT[7]  =  1;
+  LUT[9]  = -3;
+  LUT[11] = -1;
+  LUT[13] = -1;
+  LUT[15] =  1;
+  LUT[17] = -1;
+  LUT[19] =  1;
+  LUT[21] =  1;
+  LUT[23] = -1;
+  LUT[25] =  3;
+  LUT[27] =  1;
+  LUT[29] =  1;
+  LUT[31] = -1;
+  LUT[33] = -3;
+  LUT[35] = -1;
+  LUT[37] =  3;
+  LUT[39] =  1;
+  LUT[41] =  1;
+  LUT[43] = -1;
+  LUT[45] =  3;
+  LUT[47] =  1;
+  LUT[49] = -1;
+  LUT[51] =  1;
+
+  LUT[53] =  1;
+  LUT[55] = -1;
+  LUT[57] =  3;
+  LUT[59] =  1;
+  LUT[61] =  1;
+  LUT[63] = -1;
+  LUT[65] = -3;
+  LUT[67] =  3;
+  LUT[69] = -1;
+  LUT[71] =  1;
+  LUT[73] =  1;
+  LUT[75] =  3;
+  LUT[77] = -1;
+  LUT[79] =  1;
+  LUT[81] = -1;
+  LUT[83] =  1;
+  LUT[85] =  1;
+  LUT[87] = -1;
+  LUT[89] =  3;
+  LUT[91] =  1;
+  LUT[93] =  1;
+  LUT[95] = -1;
+  LUT[97] =  1;
+  LUT[99] =  3;
+  LUT[101] =  3;
+  LUT[103] =  1;
+
+  LUT[105] =  5;
+  LUT[107] =  3;
+  LUT[109] =  3;
+  LUT[111] =  1;
+  LUT[113] = -1;
+  LUT[115] =  1;
+  LUT[117] =  1;
+  LUT[119] = -1;
+  LUT[121] =  3;
+  LUT[123] =  1;
+  LUT[125] =  1;
+  LUT[127] = -1;
+  LUT[129] = -7;
+  LUT[131] = -1;
+  LUT[133] = -1;
+  LUT[135] =  1;
+  LUT[137] = -3;
+  LUT[139] = -1;
+  LUT[141] = -1;
+  LUT[143] =  1;
+  LUT[145] = -1;
+  LUT[147] =  1;
+  LUT[149] =  1;
+  LUT[151] = -1;
+  LUT[153] =  3;
+  LUT[155] =  1;
+
+  LUT[157] =  1;
+  LUT[159] = -1;
+  LUT[161] = -3;
+  LUT[163] = -1;
+  LUT[165] =  3;
+  LUT[167] =  1;
+  LUT[169] =  1;
+  LUT[171] = -1;
+  LUT[173] =  3;
+  LUT[175] =  1;
+  LUT[177] = -1;
+  LUT[179] =  1;
+  LUT[181] =  1;
+  LUT[183] = -1;
+  LUT[185] =  3;
+  LUT[187] =  1;
+  LUT[189] =  1;
+  LUT[191] = -1;
+  LUT[193] = -3;
+  LUT[195] =  3;
+  LUT[197] = -1;
+  LUT[199] =  1;
+  LUT[201] =  1;
+  LUT[203] =  3;
+  LUT[205] = -1;
+  LUT[207] =  1;
+
+  LUT[209] = -1;
+  LUT[211] =  1;
+  LUT[213] =  1;
+  LUT[215] = -1;
+  LUT[217] =  3;
+  LUT[219] =  1;
+  LUT[221] =  1;
+  LUT[223] = -1;
+  LUT[225] =  1;
+  LUT[227] =  3;
+  LUT[229] =  3;
+  LUT[231] =  1;
+  LUT[233] =  5;
+  LUT[235] =  3;
+  LUT[237] =  3;
+  LUT[239] =  1;
+  LUT[241] = -1;
+  LUT[243] =  1;
+  LUT[245] =  1;
+  LUT[247] = -1;
+  LUT[249] =  3;
+  LUT[251] =  1;
+  LUT[253] =  1;
+  LUT[255] = -1;
+}
+
+/** 
+ * Check for Euler invariance. (see [Lee94])
+ */
+template <class TInputImage,class TOutputImage>
+bool 
+BinaryThinningImageFilter3D<TInputImage,TOutputImage>
+::isEulerInvariant(NeighborhoodType neighbors, int *LUT)
+{
+  // calculate Euler characteristic for each octant and sum up
+  int EulerChar = 0;
+  unsigned char n;
+  // Octant SWU
+  n = 1;
+  if( neighbors[24]==1 )
+    n |= 128;
+  if( neighbors[25]==1 )
+    n |=  64;
+  if( neighbors[15]==1 )
+    n |=  32;
+  if( neighbors[16]==1 )
+    n |=  16;
+  if( neighbors[21]==1 )
+    n |=   8;
+  if( neighbors[22]==1 )
+    n |=   4;
+  if( neighbors[12]==1 )
+    n |=   2;
+  EulerChar += LUT[n];
+  // Octant SEU
+  n = 1;
+  if( neighbors[26]==1 )
+    n |= 128;
+  if( neighbors[23]==1 )
+    n |=  64;
+  if( neighbors[17]==1 )
+    n |=  32;
+  if( neighbors[14]==1 )
+    n |=  16;
+  if( neighbors[25]==1 )
+    n |=   8;
+  if( neighbors[22]==1 )
+    n |=   4;
+  if( neighbors[16]==1 )
+    n |=   2;
+  EulerChar += LUT[n];
+  // Octant NWU
+  n = 1;
+  if( neighbors[18]==1 )
+    n |= 128;
+  if( neighbors[21]==1 )
+    n |=  64;
+  if( neighbors[9]==1 )
+    n |=  32;
+  if( neighbors[12]==1 )
+    n |=  16;
+  if( neighbors[19]==1 )
+    n |=   8;
+  if( neighbors[22]==1 )
+    n |=   4;
+  if( neighbors[10]==1 )
+    n |=   2;
+  EulerChar += LUT[n];
+  // Octant NEU
+  n = 1;
+  if( neighbors[20]==1 )
+    n |= 128;
+  if( neighbors[23]==1 )
+    n |=  64;
+  if( neighbors[19]==1 )
+    n |=  32;
+  if( neighbors[22]==1 )
+    n |=  16;
+  if( neighbors[11]==1 )
+    n |=   8;
+  if( neighbors[14]==1 )
+    n |=   4;
+  if( neighbors[10]==1 )
+    n |=   2;
+  EulerChar += LUT[n];
+  // Octant SWB
+  n = 1;
+  if( neighbors[6]==1 )
+    n |= 128;
+  if( neighbors[15]==1 )
+    n |=  64;
+  if( neighbors[7]==1 )
+    n |=  32;
+  if( neighbors[16]==1 )
+    n |=  16;
+  if( neighbors[3]==1 )
+    n |=   8;
+  if( neighbors[12]==1 )
+    n |=   4;
+  if( neighbors[4]==1 )
+    n |=   2;
+  EulerChar += LUT[n];
+  // Octant SEB
+  n = 1;
+  if( neighbors[8]==1 )
+    n |= 128;
+  if( neighbors[7]==1 )
+    n |=  64;
+  if( neighbors[17]==1 )
+    n |=  32;
+  if( neighbors[16]==1 )
+    n |=  16;
+  if( neighbors[5]==1 )
+    n |=   8;
+  if( neighbors[4]==1 )
+    n |=   4;
+  if( neighbors[14]==1 )
+    n |=   2;
+  EulerChar += LUT[n];
+  // Octant NWB
+  n = 1;
+  if( neighbors[0]==1 )
+    n |= 128;
+  if( neighbors[9]==1 )
+    n |=  64;
+  if( neighbors[3]==1 )
+    n |=  32;
+  if( neighbors[12]==1 )
+    n |=  16;
+  if( neighbors[1]==1 )
+    n |=   8;
+  if( neighbors[10]==1 )
+    n |=   4;
+  if( neighbors[4]==1 )
+    n |=   2;
+  EulerChar += LUT[n];
+  // Octant NEB
+  n = 1;
+  if( neighbors[2]==1 )
+    n |= 128;
+  if( neighbors[1]==1 )
+    n |=  64;
+  if( neighbors[11]==1 )
+    n |=  32;
+  if( neighbors[10]==1 )
+    n |=  16;
+  if( neighbors[5]==1 )
+    n |=   8;
+  if( neighbors[4]==1 )
+    n |=   4;
+  if( neighbors[14]==1 )
+    n |=   2;
+  EulerChar += LUT[n];
+  if( EulerChar == 0 )
+    return true;
+  else
+    return false;
+}
+
+/** 
+ * Check if current point is a Simple Point.
+ * This method is named 'N(v)_labeling' in [Lee94].
+ * Outputs the number of connected objects in a neighborhood of a point
+ * after this point would have been removed.
+ */
+template <class TInputImage,class TOutputImage>
+bool 
+BinaryThinningImageFilter3D<TInputImage,TOutputImage>
+::isSimplePoint(NeighborhoodType neighbors)
+{
+  // copy neighbors for labeling
+  int cube[26];
+  int i;
+  for( i = 0; i < 13; i++ )  // i =  0..12 -> cube[0..12]
+    cube[i] = neighbors[i];
+  // i != 13 : ignore center pixel when counting (see [Lee94])
+  for( i = 14; i < 27; i++ ) // i = 14..26 -> cube[13..25]
+    cube[i-1] = neighbors[i];
+  // set initial label
+  int label = 2;
+  // for all points in the neighborhood
+  for( int i = 0; i < 26; i++ )
+  {
+    if( cube[i]==1 )     // voxel has not been labelled yet
+    {
+      // start recursion with any octant that contains the point i
+      switch( i )
+      {
+      case 0:
+      case 1:
+      case 3:
+      case 4:
+      case 9:
+      case 10:
+      case 12:
+        Octree_labeling(1, label, cube );
+        break;
+      case 2:
+      case 5:
+      case 11:
+      case 13:
+        Octree_labeling(2, label, cube );
+        break;
+      case 6:
+      case 7:
+      case 14:
+      case 15:
+        Octree_labeling(3, label, cube );
+        break;
+      case 8:
+      case 16:
+        Octree_labeling(4, label, cube );
+        break;
+      case 17:
+      case 18:
+      case 20:
+      case 21:
+        Octree_labeling(5, label, cube );
+        break;
+      case 19:
+      case 22:
+        Octree_labeling(6, label, cube );
+        break;
+      case 23:
+      case 24:
+        Octree_labeling(7, label, cube );
+        break;
+      case 25:
+        Octree_labeling(8, label, cube );
+        break;
+      }
+      label++;
+      if( label-2 >= 2 )
+      {
+        return false;
+      }
+    }
+  }
+  //return label-2; in [Lee94] if the number of connected compontents would be needed
+  return true;
+}
+
+/** 
+ * Octree_labeling [Lee94]
+ * This is a recursive method that calulates the number of connected
+ * components in the 3D neighbourhood after the center pixel would
+ * have been removed.
+ */
+template <class TInputImage,class TOutputImage>
+void 
+BinaryThinningImageFilter3D<TInputImage,TOutputImage>
+::Octree_labeling(int octant, int label, int *cube)
+{
+  // check if there are points in the octant with value 1
+  if( octant==1 )
+  {
+  	// set points in this octant to current label
+  	// and recurseive labeling of adjacent octants
+    if( cube[0] == 1 )
+      cube[0] = label;
+    if( cube[1] == 1 )
+    {
+      cube[1] = label;        
+      Octree_labeling( 2, label, cube);
+    }
+    if( cube[3] == 1 )
+    {
+      cube[3] = label;        
+      Octree_labeling( 3, label, cube);
+    }
+    if( cube[4] == 1 )
+    {
+      cube[4] = label;        
+      Octree_labeling( 2, label, cube);
+      Octree_labeling( 3, label, cube);
+      Octree_labeling( 4, label, cube);
+    }
+    if( cube[9] == 1 )
+    {
+      cube[9] = label;        
+      Octree_labeling( 5, label, cube);
+    }
+    if( cube[10] == 1 )
+    {
+      cube[10] = label;        
+      Octree_labeling( 2, label, cube);
+      Octree_labeling( 5, label, cube);
+      Octree_labeling( 6, label, cube);
+    }
+    if( cube[12] == 1 )
+    {
+      cube[12] = label;        
+      Octree_labeling( 3, label, cube);
+      Octree_labeling( 5, label, cube);
+      Octree_labeling( 7, label, cube);
+    }
+  }
+  if( octant==2 )
+  {
+    if( cube[1] == 1 )
+    {
+      cube[1] = label;
+      Octree_labeling( 1, label, cube);
+    }
+    if( cube[4] == 1 )
+    {
+      cube[4] = label;        
+      Octree_labeling( 1, label, cube);
+      Octree_labeling( 3, label, cube);
+      Octree_labeling( 4, label, cube);
+    }
+    if( cube[10] == 1 )
+    {
+      cube[10] = label;        
+      Octree_labeling( 1, label, cube);
+      Octree_labeling( 5, label, cube);
+      Octree_labeling( 6, label, cube);
+    }
+    if( cube[2] == 1 )
+      cube[2] = label;        
+    if( cube[5] == 1 )
+    {
+      cube[5] = label;        
+      Octree_labeling( 4, label, cube);
+    }
+    if( cube[11] == 1 )
+    {
+      cube[11] = label;        
+      Octree_labeling( 6, label, cube);
+    }
+    if( cube[13] == 1 )
+    {
+      cube[13] = label;        
+      Octree_labeling( 4, label, cube);
+      Octree_labeling( 6, label, cube);
+      Octree_labeling( 8, label, cube);
+    }
+  }
+  if( octant==3 )
+  {
+    if( cube[3] == 1 )
+    {
+      cube[3] = label;        
+      Octree_labeling( 1, label, cube);
+    }
+    if( cube[4] == 1 )
+    {
+      cube[4] = label;        
+      Octree_labeling( 1, label, cube);
+      Octree_labeling( 2, label, cube);
+      Octree_labeling( 4, label, cube);
+    }
+    if( cube[12] == 1 )
+    {
+      cube[12] = label;        
+      Octree_labeling( 1, label, cube);
+      Octree_labeling( 5, label, cube);
+      Octree_labeling( 7, label, cube);
+    }
+    if( cube[6] == 1 )
+      cube[6] = label;        
+    if( cube[7] == 1 )
+    {
+      cube[7] = label;        
+      Octree_labeling( 4, label, cube);
+    }
+    if( cube[14] == 1 )
+    {
+      cube[14] = label;        
+      Octree_labeling( 7, label, cube);
+    }
+    if( cube[15] == 1 )
+    {
+      cube[15] = label;        
+      Octree_labeling( 4, label, cube);
+      Octree_labeling( 7, label, cube);
+      Octree_labeling( 8, label, cube);
+    }
+  }
+  if( octant==4 )
+  {
+  	if( cube[4] == 1 )
+    {
+      cube[4] = label;        
+      Octree_labeling( 1, label, cube);
+      Octree_labeling( 2, label, cube);
+      Octree_labeling( 3, label, cube);
+    }
+  	if( cube[5] == 1 )
+    {
+      cube[5] = label;        
+      Octree_labeling( 2, label, cube);
+    }
+    if( cube[13] == 1 )
+    {
+      cube[13] = label;        
+      Octree_labeling( 2, label, cube);
+      Octree_labeling( 6, label, cube);
+      Octree_labeling( 8, label, cube);
+    }
+    if( cube[7] == 1 )
+    {
+      cube[7] = label;        
+      Octree_labeling( 3, label, cube);
+    }
+    if( cube[15] == 1 )
+    {
+      cube[15] = label;        
+      Octree_labeling( 3, label, cube);
+      Octree_labeling( 7, label, cube);
+      Octree_labeling( 8, label, cube);
+    }
+    if( cube[8] == 1 )
+      cube[8] = label;        
+    if( cube[16] == 1 )
+    {
+      cube[16] = label;        
+      Octree_labeling( 8, label, cube);
+    }
+  }
+  if( octant==5 )
+  {
+  	if( cube[9] == 1 )
+    {
+      cube[9] = label;        
+      Octree_labeling( 1, label, cube);
+    }
+    if( cube[10] == 1 )
+    {
+      cube[10] = label;        
+      Octree_labeling( 1, label, cube);
+      Octree_labeling( 2, label, cube);
+      Octree_labeling( 6, label, cube);
+    }
+    if( cube[12] == 1 )
+    {
+      cube[12] = label;        
+      Octree_labeling( 1, label, cube);
+      Octree_labeling( 3, label, cube);
+      Octree_labeling( 7, label, cube);
+    }
+    if( cube[17] == 1 )
+      cube[17] = label;        
+    if( cube[18] == 1 )
+    {
+      cube[18] = label;        
+      Octree_labeling( 6, label, cube);
+    }
+    if( cube[20] == 1 )
+    {
+      cube[20] = label;        
+      Octree_labeling( 7, label, cube);
+    }
+    if( cube[21] == 1 )
+    {
+      cube[21] = label;        
+      Octree_labeling( 6, label, cube);
+      Octree_labeling( 7, label, cube);
+      Octree_labeling( 8, label, cube);
+    }
+  }
+  if( octant==6 )
+  {
+  	if( cube[10] == 1 )
+    {
+      cube[10] = label;        
+      Octree_labeling( 1, label, cube);
+      Octree_labeling( 2, label, cube);
+      Octree_labeling( 5, label, cube);
+    }
+    if( cube[11] == 1 )
+    {
+      cube[11] = label;        
+      Octree_labeling( 2, label, cube);
+    }
+    if( cube[13] == 1 )
+    {
+      cube[13] = label;        
+      Octree_labeling( 2, label, cube);
+      Octree_labeling( 4, label, cube);
+      Octree_labeling( 8, label, cube);
+    }
+    if( cube[18] == 1 )
+    {
+      cube[18] = label;        
+      Octree_labeling( 5, label, cube);
+    }
+    if( cube[21] == 1 )
+    {
+      cube[21] = label;        
+      Octree_labeling( 5, label, cube);
+      Octree_labeling( 7, label, cube);
+      Octree_labeling( 8, label, cube);
+    }
+    if( cube[19] == 1 )
+      cube[19] = label;        
+    if( cube[22] == 1 )
+    {
+      cube[22] = label;        
+      Octree_labeling( 8, label, cube);
+    }
+  }
+  if( octant==7 )
+  {
+  	if( cube[12] == 1 )
+    {
+      cube[12] = label;        
+      Octree_labeling( 1, label, cube);
+      Octree_labeling( 3, label, cube);
+      Octree_labeling( 5, label, cube);
+    }
+  	if( cube[14] == 1 )
+    {
+      cube[14] = label;        
+      Octree_labeling( 3, label, cube);
+    }
+    if( cube[15] == 1 )
+    {
+      cube[15] = label;        
+      Octree_labeling( 3, label, cube);
+      Octree_labeling( 4, label, cube);
+      Octree_labeling( 8, label, cube);
+    }
+    if( cube[20] == 1 )
+    {
+      cube[20] = label;        
+      Octree_labeling( 5, label, cube);
+    }
+    if( cube[21] == 1 )
+    {
+      cube[21] = label;        
+      Octree_labeling( 5, label, cube);
+      Octree_labeling( 6, label, cube);
+      Octree_labeling( 8, label, cube);
+    }
+    if( cube[23] == 1 )
+      cube[23] = label;        
+    if( cube[24] == 1 )
+    {
+      cube[24] = label;        
+      Octree_labeling( 8, label, cube);
+    }
+  }
+  if( octant==8 )
+  {
+  	if( cube[13] == 1 )
+    {
+      cube[13] = label;        
+      Octree_labeling( 2, label, cube);
+      Octree_labeling( 4, label, cube);
+      Octree_labeling( 6, label, cube);
+    }
+  	if( cube[15] == 1 )
+    {
+      cube[15] = label;        
+      Octree_labeling( 3, label, cube);
+      Octree_labeling( 4, label, cube);
+      Octree_labeling( 7, label, cube);
+    }
+  	if( cube[16] == 1 )
+    {
+      cube[16] = label;        
+      Octree_labeling( 4, label, cube);
+    }
+  	if( cube[21] == 1 )
+    {
+      cube[21] = label;        
+      Octree_labeling( 5, label, cube);
+      Octree_labeling( 6, label, cube);
+      Octree_labeling( 7, label, cube);
+    }
+  	if( cube[22] == 1 )
+    {
+      cube[22] = label;        
+      Octree_labeling( 6, label, cube);
+    }
+  	if( cube[24] == 1 )
+    {
+      cube[24] = label;        
+      Octree_labeling( 7, label, cube);
+    }
+  	if( cube[25] == 1 )
+      cube[25] = label;        
+  } 
+}
+
+
+/**
+ *  Print Self
+ */
+template <class TInputImage,class TOutputImage>
+void 
+BinaryThinningImageFilter3D<TInputImage,TOutputImage>
+::PrintSelf(std::ostream& os, Indent indent) const
+{
+  Superclass::PrintSelf(os,indent);
+  
+  os << indent << "Thinning image: " << std::endl;
+
+}
+
+} // end namespace itk
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/itkImageToVTKImageFilter.h b/bioimagesuite30_src/Segmentation/itkImageToVTKImageFilter.h
new file mode 100644
index 0000000..c13fc10
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkImageToVTKImageFilter.h
@@ -0,0 +1,131 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkImageToVTKImageFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2004/02/19 03:47:59 $
+  Version:   $Revision: 1.6 $
+
+  Copyright (c) 2002 Insight Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkImageToVTKImageFilter_h
+#define __itkImageToVTKImageFilter_h
+
+#include "itkVTKImageExport.h"
+#include "vtkImageImport.h"
+#include "vtkImageData.h"
+
+namespace itk
+{
+  
+/** \class ImageToVTKImageFilter
+ * \brief Converts an ITK image into a VTK image and plugs a 
+ *  itk data pipeline to a VTK datapipeline.   
+ *
+ *  This class puts together an itkVTKImageExporter and a vtkImageImporter.
+ *  It takes care of the details related to the connection of ITK and VTK
+ *  pipelines. The User will perceive this filter as an adaptor to which
+ *  an itk::Image can be plugged as input and a vtkImage is produced as 
+ *  output.
+ * 
+ * \ingroup   ImageFilters     
+ */
+template <class TInputImage >
+class  ImageToVTKImageFilter : public ProcessObject
+{
+public:
+  /** Standard class typedefs. */
+  typedef ImageToVTKImageFilter       Self;
+  typedef ProcessObject             Superclass;
+  typedef SmartPointer<Self>        Pointer;
+  typedef SmartPointer<const Self>  ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+  
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(ImageToVTKImageFilter, ProcessObject);
+
+  /** Some typedefs. */
+  typedef TInputImage InputImageType;
+  typedef typename    InputImageType::ConstPointer    InputImagePointer;
+  typedef VTKImageExport< InputImageType>            ExporterFilterType; 
+  typedef typename ExporterFilterType::Pointer        ExporterFilterPointer;
+ 
+  /** Get the output in the form of a vtkImage. 
+      This call is delegated to the internal vtkImageImporter filter  */
+  vtkImageData *  GetOutput() const;
+
+  /** Set the input in the form of an itk::Image */
+  void SetInput( const InputImageType * );
+
+  /** Return the internal VTK image importer filter.
+      This is intended to facilitate users the access 
+      to methods in the importer */
+  vtkImageImport * GetImporter() const;
+
+  /** Return the internal ITK image exporter filter.
+      This is intended to facilitate users the access 
+      to methods in the exporter */
+  ExporterFilterType * GetExporter() const;
+  
+  /** This call delegate the update to the importer */
+  void Update();
+  
+protected:
+  ImageToVTKImageFilter(); 
+  virtual ~ImageToVTKImageFilter(); 
+
+private:
+  ImageToVTKImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+  ExporterFilterPointer       m_Exporter;
+  vtkImageImport            * m_Importer;
+
+};
+
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkImageToVTKImageFilter.txx"
+#endif
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Segmentation/itkImageToVTKImageFilter.txx b/bioimagesuite30_src/Segmentation/itkImageToVTKImageFilter.txx
new file mode 100644
index 0000000..0b4ea0c
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkImageToVTKImageFilter.txx
@@ -0,0 +1,172 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkImageToVTKImageFilter.txx,v $
+  Language:  C++
+  Date:      $Date: 2005/06/12 01:23:44 $
+  Version:   $Revision: 1.7 $
+
+  Copyright (c) 2002 Insight Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkImageToVTKImageFilter_txx
+#define _itkImageToVTKImageFilter_txx
+
+#include "itkImageToVTKImageFilter.h"
+
+namespace itk
+{
+
+
+
+/**
+ * Constructor
+ */
+template <class TInputImage>
+ImageToVTKImageFilter<TInputImage>
+::ImageToVTKImageFilter()
+{
+
+  m_Importer = vtkImageImport::New();
+
+  m_Exporter = ExporterFilterType::New();
+
+  m_Importer->SetUpdateInformationCallback(m_Exporter->GetUpdateInformationCallback());
+  m_Importer->SetPipelineModifiedCallback(m_Exporter->GetPipelineModifiedCallback());
+  m_Importer->SetWholeExtentCallback(m_Exporter->GetWholeExtentCallback());
+  m_Importer->SetSpacingCallback(m_Exporter->GetSpacingCallback());
+  m_Importer->SetOriginCallback(m_Exporter->GetOriginCallback());
+  m_Importer->SetScalarTypeCallback(m_Exporter->GetScalarTypeCallback());
+  m_Importer->SetNumberOfComponentsCallback(m_Exporter->GetNumberOfComponentsCallback());
+  m_Importer->SetPropagateUpdateExtentCallback(m_Exporter->GetPropagateUpdateExtentCallback());
+  m_Importer->SetUpdateDataCallback(m_Exporter->GetUpdateDataCallback());
+  m_Importer->SetDataExtentCallback(m_Exporter->GetDataExtentCallback());
+  m_Importer->SetBufferPointerCallback(m_Exporter->GetBufferPointerCallback());
+  m_Importer->SetCallbackUserData(m_Exporter->GetCallbackUserData());
+
+}
+
+
+
+
+/**
+ * Destructor
+ */
+template <class TInputImage>
+ImageToVTKImageFilter<TInputImage>
+::~ImageToVTKImageFilter()
+{
+  if( m_Importer )
+    {
+    m_Importer->Delete();
+    m_Importer = 0;
+    }
+}
+
+
+
+/**
+ * Set an itk::Image as input 
+ */
+template <class TInputImage>
+void
+ImageToVTKImageFilter<TInputImage>
+::SetInput( const InputImageType * inputImage )
+{
+  m_Exporter->SetInput( inputImage );
+}
+
+
+
+/**
+ * Get a vtkImage as output
+ */
+template <class TInputImage>
+vtkImageData *
+ImageToVTKImageFilter<TInputImage>
+::GetOutput() const
+{
+  return m_Importer->GetOutput();
+}
+
+
+
+
+/**
+ * Get the importer filter
+ */
+template <class TInputImage>
+vtkImageImport *
+ImageToVTKImageFilter<TInputImage>
+::GetImporter() const
+{
+  return m_Importer;
+}
+
+
+
+/**
+ * Get the exporter filter
+ */
+template <class TInputImage>
+typename ImageToVTKImageFilter<TInputImage>::ExporterFilterType *
+ImageToVTKImageFilter<TInputImage>
+::GetExporter() const
+{
+  return m_Exporter.GetPointer();
+}
+
+
+
+/**
+ * Delegate the Update to the importer
+ */
+template <class TInputImage>
+void
+ImageToVTKImageFilter<TInputImage>
+::Update()
+{
+  m_Importer->Update();
+}
+
+
+
+
+
+} // end namespace itk
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Segmentation/itkVTKImageToImageFilter.h b/bioimagesuite30_src/Segmentation/itkVTKImageToImageFilter.h
new file mode 100644
index 0000000..b832b21
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkVTKImageToImageFilter.h
@@ -0,0 +1,133 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkVTKImageToImageFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2004/04/25 21:35:10 $
+  Version:   $Revision: 1.5 $
+
+  Copyright (c) 2002 Insight Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkVTKImageToImageFilter_h
+#define __itkVTKImageToImageFilter_h
+
+#include "itkVTKImageImport.h"
+#include "vtkImageExport.h"
+#include "vtkImageData.h"
+
+
+namespace itk
+{
+  
+/** \class VTKImageToImageFilter
+ * \brief Converts a VTK image into an ITK image and plugs a 
+ *  vtk data pipeline to an ITK datapipeline.   
+ *
+ *  This class puts together an itkVTKImageImporter and a vtkImageExporter.
+ *  It takes care of the details related to the connection of ITK and VTK
+ *  pipelines. The User will perceive this filter as an adaptor to which
+ *  a vtkImage can be plugged as input and an itk::Image is produced as 
+ *  output.
+ * 
+ * \ingroup   ImageFilters     
+ */
+
+template <class TOutputImage >
+class  VTKImageToImageFilter : public ProcessObject
+{
+public:
+  /** Standard class typedefs. */
+  typedef VTKImageToImageFilter       Self;
+  typedef ProcessObject             Superclass;
+  typedef SmartPointer<Self>        Pointer;
+  typedef SmartPointer<const Self>  ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+  
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(VTKImageToImageFilter, ProcessObject);
+
+  /** Some typedefs. */
+  typedef TOutputImage OutputImageType;
+  typedef typename    OutputImageType::ConstPointer    OutputImagePointer;
+  typedef VTKImageImport< OutputImageType >   ImporterFilterType; 
+  typedef typename ImporterFilterType::Pointer         ImporterFilterPointer;
+ 
+  /** Get the output in the form of a vtkImage. 
+      This call is delegated to the internal vtkImageImporter filter  */
+  const OutputImageType *  GetOutput() const;
+
+  /** Set the input in the form of a vtkImageData */
+  void SetInput( vtkImageData * );
+
+  /** Return the internal VTK image exporter filter.
+      This is intended to facilitate users the access 
+      to methods in the exporter */
+  vtkImageExport * GetExporter() const;
+
+  /** Return the internal ITK image importer filter.
+      This is intended to facilitate users the access 
+      to methods in the importer */
+  ImporterFilterType * GetImporter() const;
+  
+  /** This call delegate the update to the importer */
+  void Update();
+  
+protected:
+  VTKImageToImageFilter(); 
+  virtual ~VTKImageToImageFilter(); 
+
+private:
+  VTKImageToImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+  ImporterFilterPointer       m_Importer;
+  vtkImageExport            * m_Exporter;
+
+};
+
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkVTKImageToImageFilter.txx"
+#endif
+
+#endif
+
+
+
+
diff --git a/bioimagesuite30_src/Segmentation/itkVTKImageToImageFilter.txx b/bioimagesuite30_src/Segmentation/itkVTKImageToImageFilter.txx
new file mode 100644
index 0000000..f5b0a7b
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkVTKImageToImageFilter.txx
@@ -0,0 +1,172 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkVTKImageToImageFilter.txx,v $
+  Language:  C++
+  Date:      $Date: 2005/06/12 01:23:44 $
+  Version:   $Revision: 1.4 $
+
+  Copyright (c) 2002 Insight Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _itkVTKImageToImageFilter_txx
+#define _itkVTKImageToImageFilter_txx
+
+#include "itkVTKImageToImageFilter.h"
+
+namespace itk
+{
+
+
+
+/**
+ * Constructor
+ */
+template <class TOutputImage>
+VTKImageToImageFilter<TOutputImage>
+::VTKImageToImageFilter()
+{
+
+  m_Exporter = vtkImageExport::New();
+
+  m_Importer = ImporterFilterType::New();
+
+  m_Importer->SetUpdateInformationCallback( m_Exporter->GetUpdateInformationCallback());
+  m_Importer->SetPipelineModifiedCallback( m_Exporter->GetPipelineModifiedCallback());
+  m_Importer->SetWholeExtentCallback( m_Exporter->GetWholeExtentCallback());
+  m_Importer->SetSpacingCallback( m_Exporter->GetSpacingCallback());
+  m_Importer->SetOriginCallback( m_Exporter->GetOriginCallback());
+  m_Importer->SetScalarTypeCallback( m_Exporter->GetScalarTypeCallback());
+  m_Importer->SetNumberOfComponentsCallback( m_Exporter->GetNumberOfComponentsCallback());
+  m_Importer->SetPropagateUpdateExtentCallback( m_Exporter->GetPropagateUpdateExtentCallback());
+  m_Importer->SetUpdateDataCallback( m_Exporter->GetUpdateDataCallback());
+  m_Importer->SetDataExtentCallback( m_Exporter->GetDataExtentCallback());
+  m_Importer->SetBufferPointerCallback( m_Exporter->GetBufferPointerCallback());
+  m_Importer->SetCallbackUserData( m_Exporter->GetCallbackUserData());
+
+}
+
+
+
+
+/**
+ * Destructor
+ */
+template <class TOutputImage>
+VTKImageToImageFilter<TOutputImage>
+::~VTKImageToImageFilter()
+{
+  if( m_Exporter )
+    {
+    m_Exporter->Delete();
+    m_Exporter = 0;
+    }
+}
+
+
+
+/**
+ * Set a vtkImageData as input 
+ */
+template <class TOutputImage>
+void
+VTKImageToImageFilter<TOutputImage>
+::SetInput( vtkImageData * inputImage )
+{
+  m_Exporter->SetInput( inputImage );
+}
+
+
+
+/**
+ * Get an itk::Image as output
+ */
+template <class TOutputImage>
+const typename VTKImageToImageFilter<TOutputImage>::OutputImageType *
+VTKImageToImageFilter<TOutputImage>
+::GetOutput() const
+{
+  return m_Importer->GetOutput();
+}
+
+
+
+
+/**
+ * Get the exporter filter
+ */
+template <class TOutputImage>
+vtkImageExport *
+VTKImageToImageFilter<TOutputImage>
+::GetExporter() const
+{
+  return m_Exporter;
+}
+
+
+
+/**
+ * Get the importer filter
+ */
+template <class TOutputImage>
+typename VTKImageToImageFilter<TOutputImage>::ImporterFilterType *
+VTKImageToImageFilter<TOutputImage>
+::GetImporter() const
+{
+  return m_Importer;
+}
+
+
+
+
+/**
+ * Delegate the Update to the importer
+ */
+template <class TOutputImage>
+void
+VTKImageToImageFilter<TOutputImage>
+::Update()
+{
+  m_Importer->Update();
+}
+
+
+
+
+} // end namespace itk
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Segmentation/itkpxLevelSetCallback.h b/bioimagesuite30_src/Segmentation/itkpxLevelSetCallback.h
new file mode 100644
index 0000000..f5d0a59
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkpxLevelSetCallback.h
@@ -0,0 +1,133 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __itkLevelSetCallback_h_
+#define __itkLevelSetCallback_h_
+#include "itkCommand.h"
+#include "vtkpxAnalyzeImageWriter.h"
+#include "itkVTKImageExport.h"
+#include "itkVTKImageImport.h"
+#include "vtkITKUtility.h"
+#include "itkImage.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+#include "vtkImageData.h"
+
+template<class TFilter,class RFilter,class ImageType>
+class CommandIterationUpdate : public itk::Command
+{
+public:
+
+  // Some ITK Definitions
+  typedef CommandIterationUpdate   Self;
+  typedef itk::Command             Superclass;
+  typedef itk::SmartPointer<Self>  Pointer;
+  itkNewMacro( Self );
+
+  RFilter* actual_filter;
+
+  virtual int SetSaveOptions(char* fname,int orientation,int frequency)
+  {
+    strncpy(this->SavePrefix,fname,199);
+    this->SaveOrientation=orientation;
+    this->SaveFrequency=frequency;
+    this->DoSave=1;
+	return 1;
+  };
+
+protected:
+  CommandIterationUpdate() 
+  {
+    this->DoSave=0;
+    this->SaveOrientation=0;
+    this->SaveFrequency=50;
+    strcpy(this->SavePrefix,"iterations");
+  };
+  int    DoSave;
+  char  SavePrefix[200];
+  int   SaveOrientation;
+  int   SaveFrequency;
+  
+
+public:
+
+  void Execute(itk::Object *caller, const itk::EventObject & event)
+    { 
+      Execute( (const itk::Object *) caller, event); 
+    }
+
+  void Execute(const itk::Object * object, const itk::EventObject & event)
+    {
+      const TFilter * filter = dynamic_cast< const TFilter * >( object );
+      if( typeid( event ) != typeid( itk::IterationEvent ) )
+        { 
+	  return; 
+	}
+      
+      
+      std::cerr << filter->GetElapsedIterations() << ": ";
+      std::cerr << filter->GetRMSChange() << std::endl;
+      int iterations=filter->GetElapsedIterations();
+
+      if (this->DoSave==1 && this->SaveFrequency*int(iterations/this->SaveFrequency)==iterations &&
+	  actual_filter->GetOutput()!=NULL)
+	{
+	  typename itk::VTKImageExport<ImageType>::Pointer itkExporter = itk::VTKImageExport<ImageType>::New();
+
+	  /*typename ImageType::SizeType size=actual_filter->GetOutput()->GetLargestPossibleRegion().GetSize();
+	    std::cerr << "actual_filter_output_size " << size[0] << "," << size[1] << std::endl;*/
+	  itkExporter->SetInput(actual_filter->GetOutput());
+	  itkExporter->Update();
+
+	  vtkImageImport* vtkImporter=vtkImageImport::New();
+	  ConnectPipelines(itkExporter, vtkImporter);
+	  vtkImporter->Update();
+
+	  if (vtkImporter->GetOutput()!=NULL)
+	    {
+	      char line[220];
+	      sprintf(line,"%s_%03d",this->SavePrefix,iterations);
+	      vtkpxAnalyzeImageWriter* anaw=vtkpxAnalyzeImageWriter::New();
+	      anaw->SetInput(vtkImporter->GetOutput());
+	      anaw->SetOrientation(this->SaveOrientation);
+	      anaw->Save(line);
+	      
+	      std::cerr << " ***** Saving in " << line  << std::endl;
+	      anaw->Delete();
+	    }
+	  vtkImporter->Delete();
+	}
+    }
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/itkpxSaturateImageFilter.h b/bioimagesuite30_src/Segmentation/itkpxSaturateImageFilter.h
new file mode 100644
index 0000000..639e073
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkpxSaturateImageFilter.h
@@ -0,0 +1,166 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkpxSaturateImageFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2004/10/26 13:59:18 $
+  Version:   $Revision: 1.1 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkSaturateImageFilter_h
+#define __itkSaturateImageFilter_h
+
+#include "itkImageToImageFilter.h"
+#include "itkArray.h"
+
+namespace itk
+{
+
+/** \class SaturateImageFilter
+ * \brief Shift and scale the pixels in an image.
+ *
+ * SaturateImageFilter shifts the input pixel by Shift (default 0.0)
+ * and then scales the pixel by Scale (default 1.0). All computattions
+ * are performed in the precison of the input pixel's RealType. Before
+ * assigning the computed value to the output pixel, the value is clamped
+ * at the NonpositiveMin and max of the pixel type.
+ * \ingroup IntensityImageFilters
+ *
+ */
+template <class TInputImage, class TOutputImage>
+class SaturateImageFilter:
+    public ImageToImageFilter<TInputImage,TOutputImage>
+{
+public:
+  /** Standard class typedefs. */
+  typedef SaturateImageFilter         Self;
+  typedef ImageToImageFilter<TInputImage,TOutputImage>  Superclass;
+  typedef SmartPointer<Self>  Pointer;
+  typedef SmartPointer<const Self>  ConstPointer;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);  
+
+  /** Typedef to describe the output and input image region types. */
+  typedef typename TInputImage::RegionType InputImageRegionType;
+  typedef typename TOutputImage::RegionType OutputImageRegionType;
+
+  /** Typedef to describe the pointer to the input/output. */  
+  typedef typename TInputImage::Pointer InputImagePointer;
+  typedef typename TOutputImage::Pointer OutputImagePointer;
+
+  /** Typedef to describe the type of pixel. */
+  typedef typename TInputImage::PixelType InputImagePixelType;
+  typedef typename TOutputImage::PixelType OutputImagePixelType;
+
+  /** Typedef to describe the output and input image index and size types. */
+  typedef typename TInputImage::IndexType InputImageIndexType;
+  typedef typename TInputImage::SizeType InputImageSizeType;
+  typedef typename TInputImage::OffsetType InputImageOffsetType;
+  typedef typename TOutputImage::IndexType OutputImageIndexType;
+  typedef typename TOutputImage::SizeType OutputImageSizeType;
+  typedef typename TOutputImage::OffsetType OutputImageOffsetType;
+
+  /** Type to use form computations. */
+  typedef typename NumericTraits<OutputImagePixelType>::RealType RealType;
+      
+  /** Image related typedefs. */
+  itkStaticConstMacro(ImageDimension, unsigned int,
+                      TInputImage::ImageDimension ) ;
+
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(SaturateImageFilter, ImageToImageFilter);
+
+  /** Set/Get the amount to Shift each Pixel. The shift is followed by a Scale. */
+  itkSetMacro(LowerBound,RealType);
+  itkGetMacro(LowerBound,RealType);
+
+  /** Set/Get the amount to Shift each Pixel. The shift is followed by a Scale. */
+  itkSetMacro(UpperBound,RealType);
+  itkGetMacro(UpperBound,RealType);
+
+  /** Set/Get the amount to Scale each Pixel. The Scale is applied after the Shift. */
+  itkSetMacro(Scale,RealType);
+  itkGetMacro(Scale,RealType);
+
+  /** Get the number of pixels that underflowed and overflowed. */
+  itkGetMacro(UnderflowCount,long);
+  itkGetMacro(OverflowCount,long);
+
+
+protected:
+  SaturateImageFilter();
+  ~SaturateImageFilter();
+  void PrintSelf(std::ostream& os, Indent indent) const;
+
+  /** Initialize some accumulators before the threads run. */
+  void BeforeThreadedGenerateData ();
+  
+  /** Tally accumulated in threads. */
+  void AfterThreadedGenerateData ();
+  
+  /** Multi-thread version GenerateData. */
+  void  ThreadedGenerateData (const OutputImageRegionType& 
+                              outputRegionForThread,
+                              int threadId) ;
+private:
+  SaturateImageFilter(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+
+  RealType m_LowerBound;
+  RealType m_UpperBound;
+  RealType m_Scale;
+
+  long m_UnderflowCount;
+  long m_OverflowCount;
+  Array<long> m_ThreadUnderflow;
+  Array<long> m_ThreadOverflow;
+};
+
+  
+} // end namespace itk
+  
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkpxSaturateImageFilter.txx"
+#endif
+  
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/itkpxSaturateImageFilter.txx b/bioimagesuite30_src/Segmentation/itkpxSaturateImageFilter.txx
new file mode 100644
index 0000000..2c1a444
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkpxSaturateImageFilter.txx
@@ -0,0 +1,161 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+#ifndef _itkSaturateImageFilter_txx
+#define _itkSaturateImageFilter_txx
+#include "itkpxSaturateImageFilter.h"
+
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkNumericTraits.h"
+#include "itkProgressReporter.h"
+
+namespace itk {
+
+template<class TInputImage, class TOutputImage>
+SaturateImageFilter<TInputImage, TOutputImage>
+::SaturateImageFilter()
+{
+  m_LowerBound= NumericTraits<OutputImagePixelType>::NonpositiveMin();
+  m_UpperBound= NumericTraits<OutputImagePixelType>::max();
+  m_Scale = NumericTraits<RealType>::One;
+  m_ThreadUnderflow.SetSize(1);
+  m_ThreadOverflow.SetSize(1);
+}
+
+template<class TInputImage, class TOutputImage>
+SaturateImageFilter<TInputImage, TOutputImage>
+::~SaturateImageFilter()
+{
+}
+
+template<class TInputImage, class TOutputImage>
+void
+SaturateImageFilter<TInputImage, TOutputImage>
+::BeforeThreadedGenerateData ()
+{
+  int numberOfThreads = this->GetNumberOfThreads();
+
+  //  Allocate and initialize the thread temporaries
+  m_ThreadUnderflow.SetSize(numberOfThreads);
+  m_ThreadUnderflow.Fill(0);
+  m_ThreadOverflow.SetSize(numberOfThreads);
+  m_ThreadOverflow.Fill(0);
+}
+
+template<class TInputImage, class TOutputImage>
+void
+SaturateImageFilter<TInputImage, TOutputImage>
+::AfterThreadedGenerateData ()
+{
+  int numberOfThreads = this->GetNumberOfThreads();
+
+  m_UnderflowCount = 0;
+  m_OverflowCount = 0;
+
+  // Accumulate counts for each thread
+  for( int i = 0; i < numberOfThreads; i++)
+    {
+    m_UnderflowCount += m_ThreadUnderflow[i];
+    m_OverflowCount += m_ThreadOverflow[i];
+    }
+}
+
+template<class TInputImage, class TOutputImage>
+void
+SaturateImageFilter<TInputImage, TOutputImage>
+::ThreadedGenerateData(const OutputImageRegionType& outputRegionForThread,
+                       int threadId) 
+{
+  //  std::cerr << "Updating Saturate .....";
+  RealType value;
+  ImageRegionConstIterator<TInputImage>  it (this->GetInput(), outputRegionForThread);
+  ImageRegionIterator<TOutputImage> ot (this->GetOutput(), outputRegionForThread);
+  
+  // support progress methods/callbacks
+  ProgressReporter progress(this, threadId, outputRegionForThread.GetNumberOfPixels());
+          
+  // shift and scale the input pixels
+  while (!it.IsAtEnd())
+    {
+      value = (static_cast<RealType>(it.Get()));
+      if (value<m_LowerBound)
+	{
+	  value=(m_LowerBound*m_Scale);
+	}
+      else if (value > m_UpperBound)
+	{
+	  value=(m_UpperBound*m_Scale);
+	}
+      else
+	{
+	  value=(value*m_Scale);
+	}
+	       
+    if (value < NumericTraits<OutputImagePixelType>::NonpositiveMin())
+      {
+      ot.Set (NumericTraits<OutputImagePixelType>::NonpositiveMin());
+      m_ThreadUnderflow[threadId]++;
+      }
+    else if (value > NumericTraits<OutputImagePixelType>::max())
+      {
+      ot.Set (NumericTraits<OutputImagePixelType>::max());      
+      m_ThreadOverflow[threadId]++;
+      }
+    else
+      {
+	ot.Set( static_cast<OutputImagePixelType>( value ) );
+      }
+    ++it;
+    ++ot;
+    
+    progress.CompletedPixel();
+    }
+  //std::cerr << "Updating Saturate Done " << std::endl;
+}
+
+template <class TInputImage, class TOutputImage>
+void 
+SaturateImageFilter<TInputImage, TOutputImage>
+::PrintSelf(std::ostream& os, Indent indent) const
+{
+  Superclass::PrintSelf(os,indent);
+
+  os << indent << "Bounds: "  << m_LowerBound << ": " << m_UpperBound << std::endl;
+  os << indent << "Scale: "  << m_Scale << std::endl;
+  os << indent << "Computed values follow:" << std::endl;
+  os << indent << "UnderflowCount: "  << m_UnderflowCount << std::endl;
+  os << indent << "OverflowCount: "  << m_OverflowCount << std::endl;
+}
+
+
+}// end namespace itk
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationCoupledLevelSetFunction.h b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationCoupledLevelSetFunction.h
new file mode 100644
index 0000000..4c2472f
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationCoupledLevelSetFunction.h
@@ -0,0 +1,356 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkTissueSegmentationCoupledLevelSetFunction.h,v $
+  Language:  C++
+  Date:      $Date: 2003/09/10 14:28:39 $
+  Version:   $Revision: 1.12 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkTissueSegmentationCoupledLevelSetFunction_h_
+#define __itkTissueSegmentationCoupledLevelSetFunction_h_
+
+#include "itkSegmentationLevelSetFunction.h"
+#include "itkConstNeighborhoodIterator.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkImageRegionConstIteratorWithIndex.h"
+#include "itkNumericTraits.h"
+
+#ifndef M_PI
+#define M_PI 3.14159
+#endif
+
+namespace itk {
+
+/** \class TissueSegmentationCoupledLevelSetFunction
+ *    
+ * \brief This function is used in TissueSegmentationCoupledLevelSetImageFilter to
+ * segment structures in images based on intensity values.
+ *
+ * \par  SegmentationLevelSetFunction is a subclass of the generic LevelSetFunction.
+ * It useful for segmentations based on intensity values in an image.  It works
+ * by constructing a speed term (feature image) with positive values inside an
+ * intensity window (between a low and high threshold) and negative values
+ * outside that intensity window.  The evolving level set front will lock onto
+ * regions that are at the edges of the intensity window.
+ *
+ *  You may optionally add a Laplacian calculation on the image to the
+ *  threshold-based speed term by setting the EdgeWeight parameter to a
+ *  non-zero value.  The Laplacian term will cause the evolving surface to
+ *  be more strongly attracted to image edges.   Several parameters control a
+ *  preprocessing FeatureImage smoothing stage applied only to the Laplacian
+ *  calculation.
+ *
+ *  \par
+ *  Image $f$ is thresholded pixel by pixel using upper threshold
+ *  $U$ and lower threshold $L$ according to the following formula.
+ *
+ * \par
+ *  \f$  f(x) = \left\{ \begin{array}{ll} g(x) - L & \mbox{if $(g)x < (U-L)/2 + L$} \\ U - g(x) & \mbox{otherwise} \end{array} \right. \f$ 
+ *
+ * \sa SegmentationLevelSetImageFunction
+ *  \sa TissueSegmentationCoupledLevelSetImageFilter */
+template <class TImageType, class TFeatureImageType = TImageType>
+class TissueSegmentationCoupledLevelSetFunction
+  : public SegmentationLevelSetFunction<TImageType, TFeatureImageType>
+{
+public:
+  /** Standard class typedefs. */
+  typedef TissueSegmentationCoupledLevelSetFunction Self;
+  typedef SegmentationLevelSetFunction<TImageType, TFeatureImageType> Superclass;
+  typedef SmartPointer<Self> Pointer;
+  typedef SmartPointer<const Self> ConstPointer;
+  typedef TFeatureImageType FeatureImageType;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods) */
+  itkTypeMacro( TissueSegmentationCoupledLevelSetFunction, SegmentationLevelSetFunction );
+
+  /** Extract some parameters from the superclass. */
+  typedef typename Superclass::ImageType ImageType;
+  typedef typename Superclass::ScalarValueType ScalarValueType;
+  typedef typename Superclass::FeatureScalarType FeatureScalarType;
+  typedef typename Superclass::RadiusType RadiusType;
+  typedef typename Superclass::FloatOffsetType FloatOffsetType;
+  typedef typename Superclass::VectorImageType VectorImageType;
+  typedef typename Superclass::VectorType VectorType;
+  typedef typename Superclass::PixelType PixelType;
+  typedef typename Superclass::TimeStepType TimeStepType;
+  typedef typename Superclass::IndexType IndexType;
+  typedef typename Superclass::ContinuousIndexType ContinuousIndexType;
+  typedef typename Superclass::NeighborhoodType NeighborhoodType;
+  
+
+  /** Extract some parameters from the superclass. */
+  itkStaticConstMacro(ImageDimension, unsigned int,Superclass::ImageDimension);
+
+
+  // ** Image and Image Iterator definition */
+  typedef ImageRegionIterator<ImageType>                    ImageIterator;
+  typedef ImageRegionConstIterator<ImageType>               ConstImageIterator;
+  typedef ImageRegionConstIteratorWithIndex<ImageType>      ConstImageIteratorWithIndex;
+  typedef ConstNeighborhoodIterator<ImageType>              NeighborhoodIterator;
+
+  typedef itk::CovariantVector<float,3>                     GradientOutputPixel;
+  typedef itk::Image<GradientOutputPixel,pxImageDimension>  GradientOutputType;
+  typedef ImageRegionConstIterator<GradientOutputType>      GradientImageIterator;
+
+  /* ------------------------------------------------------
+     Use Chen/ Vesse \delta(x) instead of |\nabla \phi| term
+  ------------------------------------------------------ */
+  void SetUseNonMorphometricTerm(int m) { 
+    m_UseNonMorphometricTerm=(m>0);
+  }
+  
+  int GetUseNonMorphometricTerm() {
+    return m_UseNonMorphometricTerm;
+  }
+
+  // ------------------------------------------------------
+  // Epsilon Term for Heavy Side Function
+  // ------------------------------------------------------
+  void SetHeavySideEpsilon(double d) {
+    m_HeavySideEpsilon=d;
+  }
+
+  double GetHeavySideEpsilon() {
+    return m_HeavySideEpsilon;
+  }
+
+
+  /** Set/Get the sigma for the Gaussian kernel used to compute the gradient
+   * of the feature image needed for the advection term of the equation. */
+  void SetDerivativeSigma( const double v )
+  { m_DerivativeSigma = v; }
+  double GetDerivativeSigma()
+  { return m_DerivativeSigma; };
+
+
+  /** Set/Get threshold values */
+  void SetWhiteMatterTissue(FeatureScalarType m,FeatureScalarType s)  {
+    m_WhiteMatterMean  = m;
+    m_WhiteMatterSigma = s;
+    if (m_WhiteMatterSigma<1.0)
+      m_WhiteMatterSigma=1.0;
+  }
+  FeatureScalarType GetWhiteMatterMean() const  { return m_WhiteMatterMean; }
+  FeatureScalarType GetWhiteMatterSigma() const  { return m_WhiteMatterSigma; }
+
+
+  void SetGrayMatterTissue(FeatureScalarType m,FeatureScalarType s)  {
+    m_GrayMatterMean  = m;
+    m_GrayMatterSigma = s;
+    if (m_GrayMatterSigma<1.0)
+      m_GrayMatterSigma=1.0;
+
+  }
+  FeatureScalarType GetGrayMatterMean() const  { return m_GrayMatterMean; }
+  FeatureScalarType GetGrayMatterSigma() const  { return m_GrayMatterSigma; }
+
+  void SetCSFTissue(FeatureScalarType m,FeatureScalarType s)  {
+    m_CSFMean  = m;
+    m_CSFSigma = s;
+    if (m_CSFSigma<1.0)
+      m_CSFSigma=1.0;
+
+  }
+  FeatureScalarType GetCSFMean() const  { return m_CSFMean; }
+  FeatureScalarType GetCSFSigma() const  { return m_CSFSigma; }
+
+
+  // Get/Set the boundaries of the two images 
+  void SetCoupledLevelSetBoundaries(int innerboundary,int outerboundary)
+  {
+    m_InnerBoundary=innerboundary;
+    m_OuterBoundary=outerboundary;
+  }
+
+  int GetInnerBoundary() const
+  {
+    return m_InnerBoundary;
+  }
+
+  int GetOuterBoundary() const
+  {
+    return m_OuterBoundary;
+  }
+
+
+
+  virtual void CalculateSpeedImage();
+  virtual void CalculateAdvectionImage();
+
+  virtual void Initialize(const RadiusType &r)
+  {
+    Superclass::Initialize(r);
+    //    this->SetAdvectionWeight( NumericTraits<ScalarValueType>::Zero);
+    this->SetPropagationWeight(-1.0 * NumericTraits<ScalarValueType>::One);
+    this->SetCurvatureWeight(NumericTraits<ScalarValueType>::One);
+    this->SetAdvectionWeight( NumericTraits<ScalarValueType>::One );
+    m_DerivativeSigma = 1.0;
+  }
+
+  /** Set/Get the weight applied to the edge (Laplacian) attractor in the speed
+   *  term function. Zero will turn this term off. */
+  void SetEdgeWeight(const ScalarValueType p)
+  {
+    m_EdgeWeight = p;
+  }
+  ScalarValueType GetEdgeWeight() const
+  {
+    return m_EdgeWeight;
+  }
+  
+
+  void  SetLowerWhiteGrayBound(const float p)  {    m_LowerWhiteGrayBound = p;  }
+  float GetLowerWhiteGrayBound() const         {    return m_LowerWhiteGrayBound;  }
+
+  void  SetUpperWhiteGrayBound(const float p)  {    m_UpperWhiteGrayBound = p;  }
+  float GetUpperWhiteGrayBound() const         {    return m_UpperWhiteGrayBound;  }
+
+  void  SetLowerGrayCSFBound(const float p)  {    m_LowerGrayCSFBound = p;  }
+  float GetLowerGrayCSFBound() const         {    return m_LowerGrayCSFBound;  }
+
+  void  SetUpperGrayCSFBound(const float p)  {    m_UpperGrayCSFBound = p;  }
+  float GetUpperGrayCSFBound() const         {    return m_UpperGrayCSFBound;  }
+
+  void  SetConstraintOffset(const float p)  {    m_ConstraintOffset = p;  }
+  float GetConstraintOffset() const         {    return m_ConstraintOffset;  }
+
+  
+  FeatureScalarType WhiteMatterTissueFunction(FeatureScalarType v) {
+    return ( (v-m_WhiteMatterMean)*(v-m_WhiteMatterMean)/(m_WhiteMatterSigma*m_WhiteMatterSigma )) + 0.5*log(2.0*M_PI)+log(m_WhiteMatterSigma);
+  }
+
+  FeatureScalarType GrayMatterTissueFunction(FeatureScalarType v) {
+    return ( (v-m_GrayMatterMean)*(v-m_GrayMatterMean)/(m_GrayMatterSigma*m_GrayMatterSigma )) + 0.5*log(2.0*M_PI)+log(m_GrayMatterSigma);
+  }
+
+  FeatureScalarType CSFTissueFunction(FeatureScalarType v) {
+    return ( (v-m_CSFMean)*(v-m_CSFMean)/(m_CSFSigma*m_CSFSigma )) + 0.5*log(2.0*M_PI)+log(m_CSFSigma);
+  }
+
+
+  /** Get/Set the image used as the speed function in the level set equation */
+  typedef typename Superclass::GlobalDataStruct GlobalDataStruct;
+
+  virtual PixelType ComputeUpdate(const NeighborhoodType &neighborhood,
+                                  void *globalData,
+                                  const FloatOffsetType& = FloatOffsetType(0.0));
+
+
+
+protected:
+  TissueSegmentationCoupledLevelSetFunction()
+  {
+    this->SetAdvectionWeight(0.0);
+    this->SetPropagationWeight(1.0);
+    this->SetCurvatureWeight(1.0);
+    this->SetEdgeWeight(0.0);
+    this->SetWhiteMatterTissue(100.0,10.0);
+    this->SetGrayMatterTissue(0.0,10.0);
+    this->SetCSFTissue(0.0,-1.0);
+    m_LowerWhiteGrayBound=-3.0;
+    m_UpperWhiteGrayBound=-8.0;
+    m_LowerGrayCSFBound=3.0;
+    m_UpperGrayCSFBound=8.0;
+
+    m_UseNonMorphometricTerm=0;
+    m_HeavySideEpsilon=1.0;
+    m_ConstraintOffset=1.0;
+  }
+
+  virtual ~TissueSegmentationCoupledLevelSetFunction() {
+  }
+
+  TissueSegmentationCoupledLevelSetFunction(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+  void PrintSelf(std::ostream& os, Indent indent) const
+  {
+    Superclass::PrintSelf(os, indent );
+    os << indent << "Use NonMorphometric Speed Multiplier " << m_UseNonMorphometricTerm << std::endl;
+    os << indent << "Heavy Side Epsilon " << m_HeavySideEpsilon << std::endl;
+    os << indent << "WhiteMatter Tissue: " << m_WhiteMatterMean << " + " << m_WhiteMatterSigma << std::endl;
+    os << indent << "GrayMatter Tissue: " << m_GrayMatterMean << " + " << m_GrayMatterSigma << std::endl;
+    os << indent << "CSF Tissue: " << m_CSFMean << " + " << m_CSFSigma << std::endl;
+    os << indent << "Boundaries: " << m_InnerBoundary << " + " << m_OuterBoundary << std::endl;
+    os << indent << "EdgeWeight: " << m_EdgeWeight << std::endl;
+
+    os << indent << "WhiteGray  Bounds :" <<  m_LowerWhiteGrayBound << " to " << m_UpperWhiteGrayBound << std::endl;
+    os << indent << "GrayCSF    Bounds :" <<  m_LowerGrayCSFBound << " to " << m_UpperGrayCSFBound << std::endl;
+    os << indent << "Constraint Weight :" <<  m_ConstraintOffset << std::endl;
+    os << indent << "DerivativeSigma: " << m_DerivativeSigma << std::endl;
+  }
+  
+  FeatureScalarType m_WhiteMatterMean;
+  FeatureScalarType m_WhiteMatterSigma;
+  FeatureScalarType m_GrayMatterMean;
+  FeatureScalarType m_GrayMatterSigma;
+  FeatureScalarType m_CSFMean;
+  FeatureScalarType m_CSFSigma;
+  ScalarValueType   m_EdgeWeight;
+  float             m_LowerWhiteGrayBound;
+  float             m_UpperWhiteGrayBound;
+  float             m_LowerGrayCSFBound;
+  float             m_UpperGrayCSFBound;
+
+  float             m_ConstraintOffset;
+  double m_DerivativeSigma;
+  double m_HeavySideEpsilon;
+  int  m_UseNonMorphometricTerm;
+  int  m_InnerBoundary;
+  int  m_OuterBoundary;
+  /** The image holding the speed values for front propagation */
+
+};
+  
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkpxTissueSegmentationCoupledLevelSetFunction.txx"
+#endif
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationCoupledLevelSetFunction.txx b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationCoupledLevelSetFunction.txx
new file mode 100644
index 0000000..5b3a600
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationCoupledLevelSetFunction.txx
@@ -0,0 +1,420 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkTissueSegmentationCoupledLevelSetFunction.txx,v $
+  Language:  C++
+  Date:      $Date: 2003/09/10 14:28:39 $
+  Version:   $Revision: 1.5 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkTissueSegmentationCoupledLevelSetFunction_txx_
+#define __itkTissueSegmentationCoupledLevelSetFunction_txx_
+
+#include "itkpxTissueSegmentationCoupledLevelSetFunction.h"
+#include "vtkpxLevelSetUtil.h"
+#include "itkGradientRecursiveGaussianImageFilter.h"
+#include "itkImageRegionIterator.h"
+
+namespace itk {
+
+template <class TImageType, class TFeatureImageType>
+void TissueSegmentationCoupledLevelSetFunction<TImageType, TFeatureImageType>
+::CalculateSpeedImage()
+{
+  //  ImageRegionIterator<FeatureImageType> lit;
+  ImageRegionConstIterator<FeatureImageType>  fit(this->GetFeatureImage(), this->GetFeatureImage()->GetRequestedRegion());
+  ImageRegionIterator<ImageType>              sit(this->GetSpeedImage(), this->GetFeatureImage()->GetRequestedRegion());
+
+  for ( fit.GoToBegin(), sit.GoToBegin(); ! fit.IsAtEnd(); ++sit, ++fit)
+    sit.Set( static_cast<ScalarValueType>(fit.Get()));
+}
+
+
+template <class TImageType, class TFeatureImageType>
+void TissueSegmentationCoupledLevelSetFunction<TImageType, TFeatureImageType>
+::CalculateAdvectionImage()
+{
+  /* compoute the gradient of the feature image. */
+  typedef GradientRecursiveGaussianImageFilter<FeatureImageType,VectorImageType>
+    DerivativeFilterType;
+
+  typename DerivativeFilterType::Pointer derivative = DerivativeFilterType::New();
+  derivative->SetInput( this->GetFeatureImage() );
+  derivative->SetSigma( m_DerivativeSigma );
+  derivative->Update();
+  
+  /* copy negative gradient into the advection image. */
+  ImageRegionIterator<VectorImageType>
+    dit( derivative->GetOutput(), this->GetFeatureImage()->GetRequestedRegion() );
+  ImageRegionIterator<VectorImageType>
+    ait( this->GetAdvectionImage(), this->GetFeatureImage()->GetRequestedRegion() );
+
+  for( dit.GoToBegin(), ait.GoToBegin(); !dit.IsAtEnd(); ++dit, ++ait )
+    {
+      typename VectorImageType::PixelType v = dit.Get();
+      for ( unsigned int j = 0; j < ImageDimension; j++ )
+	  v[j] *= -1.0L;
+
+      ait.Set( v);
+    }
+}
+
+
+template <class TImageType, class TFeatureImageType>
+typename TissueSegmentationCoupledLevelSetFunction<TImageType, TFeatureImageType>::PixelType
+TissueSegmentationCoupledLevelSetFunction<TImageType, TFeatureImageType>::ComputeUpdate(
+										 const NeighborhoodType &it,
+										 void *globalData,
+										 const FloatOffsetType& offset )
+{
+  unsigned int i, j;  
+  const ScalarValueType ZERO = NumericTraits<ScalarValueType>::Zero;
+  const ScalarValueType center_value  = it.GetCenterPixel();
+  
+  
+
+
+  ScalarValueType laplacian, x_energy, laplacian_term, propagation_term,
+    curvature_term, advection_term, propagation_gradient;
+  VectorType advection_field;
+
+  ScalarValueType mean1  = static_cast<ScalarValueType>(m_WhiteMatterMean);
+  ScalarValueType sigma1 = static_cast<ScalarValueType>(m_WhiteMatterSigma);
+
+
+  //  ScalarValueType mean2  = static_cast<ScalarValueType>(m_GrayMatterMean);
+  //  ScalarValueType sigma2 = static_cast<ScalarValueType>(m_GrayMatterSigma);
+
+
+  // Global data structure
+  GlobalDataStruct *gd = (GlobalDataStruct *)globalData;
+
+  // ----------------------------------------------------------------------------
+  // 
+  // Step -1: Where are we?
+  //
+  // ---------------------------------------------------------------------------
+
+  typename ImageType::IndexType idx=it.GetIndex();
+
+  
+  int BoundaryMode=0; // 0 = None , 1 = White/Gray ... 2= Gray/CS
+  if (idx[0] < m_InnerBoundary)
+    BoundaryMode=1;
+  else if (idx[0] >= m_OuterBoundary)
+    BoundaryMode=2;
+  
+  gd->m_GradMagSqr = 1.0e-6;
+
+
+  //  std::cerr << m_InnerBoundary << " m_outer= " << m_OuterBoundary << "\n";
+
+
+  // ----------------------------------------------------------------------------
+  // 
+  // Step 0 Compute Derivatives etc
+  //
+  // ---------------------------------------------------------------------------
+
+  for( i = 0 ; i < ImageDimension; i++)
+    {
+      const unsigned int positionA = 
+	static_cast<unsigned int>( this->m_Center + this->m_xStride[i]);    
+      const unsigned int positionB = 
+	static_cast<unsigned int>( this->m_Center - this->m_xStride[i]);    
+
+      
+      gd->m_dx[i] = 0.5 * (it.GetPixel( positionA ) - 
+			   it.GetPixel( positionB )    );
+      
+      gd->m_dxy[i][i] = it.GetPixel( positionA )
+	+ it.GetPixel( positionB ) - 2.0 * center_value;
+      
+      gd->m_dx_forward[i]  = it.GetPixel( positionA ) - center_value;
+      gd->m_dx_backward[i] = center_value - it.GetPixel( positionB );
+      gd->m_GradMagSqr += gd->m_dx[i] * gd->m_dx[i];
+      
+      for( j = i+1; j < ImageDimension; j++ )
+	{
+	  const unsigned int positionAa = static_cast<unsigned int>( 
+								    this->m_Center - this->m_xStride[i] - this->m_xStride[j] );
+	  const unsigned int positionBa = static_cast<unsigned int>( 
+								    this->m_Center - this->m_xStride[i] + this->m_xStride[j] );
+	  const unsigned int positionCa = static_cast<unsigned int>( 
+								    this->m_Center + this->m_xStride[i] - this->m_xStride[j] );
+	  const unsigned int positionDa = static_cast<unsigned int>( 
+								    this->m_Center + this->m_xStride[i] + this->m_xStride[j] );
+	  
+	  gd->m_dxy[i][j] = gd->m_dxy[j][i] = 0.25 *( it.GetPixel( positionAa )
+						      - it.GetPixel( positionBa )
+						      - it.GetPixel( positionCa )
+						      + it.GetPixel( positionDa )
+						      );
+	}
+    }
+  
+  
+  // ----------------------------------------------------------------------------
+  // 
+  // Step 1 Compute Curvature Term 
+  //
+  // ---------------------------------------------------------------------------
+
+
+  curvature_term = ZERO;
+  if ( this->m_CurvatureWeight != ZERO && BoundaryMode!=0 )
+    {
+      curvature_term = this->ComputeCurvatureTerm(it, offset, gd) * this->m_CurvatureWeight * this->CurvatureSpeed(it, offset);
+      gd->m_MaxCurvatureChange = vnl_math_max(gd->m_MaxCurvatureChange, vnl_math_abs(curvature_term));
+    }
+
+  
+
+  // ----------------------------------------------------------------------------
+  // 
+  // Step 2 Compute Advection Term 
+  //
+  // ---------------------------------------------------------------------------
+
+  advection_term = ZERO;
+  if (this->m_AdvectionWeight != ZERO && BoundaryMode!= 0 )
+    {
+      advection_field = this->AdvectionField(it, offset, gd);
+      advection_term = ZERO;
+      for(i = 0; i < ImageDimension; i++)
+	{
+	  x_energy = this->m_AdvectionWeight * advection_field[i];
+	  if (x_energy > ZERO)
+	    {
+	      advection_term += advection_field[i] * gd->m_dx_backward[i];
+	    }
+	  else
+	    {
+	      advection_term += advection_field[i] * gd->m_dx_forward[i];
+	    }
+	  
+	  gd->m_MaxAdvectionChange = vnl_math_max(gd->m_MaxAdvectionChange, vnl_math_abs(x_energy)); 
+	}
+      advection_term *= this->m_AdvectionWeight;
+    }
+  
+
+  // ----------------------------------------------------------------------------
+  // 
+  // Step 3 Compute Propagation Term 
+  //
+  // ---------------------------------------------------------------------------
+
+
+
+	  /*	  typename NeighborhoodIterator<FeatureImageType>::IndexType loc;
+	    loc[0]=layerIt->m_Value[0]/2;
+	    loc[1]=layerIt->m_Value[1];
+	    loc[2]=layerIt->m_Value[2];
+	    outputIt.SetLocation(loc);
+	    outputIt.SetCenterPixel(phi);*/
+
+
+  propagation_term = ZERO;
+
+  if (BoundaryMode!=0)
+    {
+      if (this->m_PropagationWeight > 0 ) 
+	{
+	  ScalarValueType intensity=this->PropagationSpeed(it, offset, gd);
+	  ScalarValueType t1,t2;
+	  if (BoundaryMode==1)
+	    {
+	      t1=this->WhiteMatterTissueFunction(intensity);
+	      t2=this->GrayMatterTissueFunction(intensity);
+	    } 
+	  else
+	    {
+	      t1=this->GrayMatterTissueFunction(intensity);	      
+	      t2=this->CSFTissueFunction(intensity);
+	    }
+	  
+	  ScalarValueType sp=t2-t1;
+	  
+	  // if (intensity < (mean1-3.0*sigma1 ) || intensity < (mean1+5.5*sigma1)  )
+	  // sp=0.0;
+
+	  propagation_term = this->m_PropagationWeight * sp;
+	  //	  std::cerr << "\nPoint " << idx[0] << "," << idx[1] << "," << idx[2] << "\t";
+	  //	  std::cerr << "Intensity = " << intensity << ", t1= " << t1 << " t2 = " << t2 << " mode= " << BoundaryMode << "\n";
+
+	}
+      
+      
+      if (this->m_ConstraintOffset > 0.0)
+	{
+	  // Now get other level set and constrain to it 
+
+	  unsigned int positionOffset = 0;
+
+	  typename ImageType::IndexType idx2;
+	  // All coordinates other than x are fixed!
+	  for ( unsigned int j = 1; j < ImageDimension; j++ )
+	    idx2[j]=idx[j];
+
+	  float lower_bound,upper_bound;
+	  if (BoundaryMode==1)
+	    {
+	      // Look over to the right 
+	      idx2[0]=idx[0]+m_OuterBoundary;
+	      lower_bound=m_LowerWhiteGrayBound;
+	      upper_bound=m_UpperWhiteGrayBound;
+	    }
+	  else 
+	    {
+	      // Look to the left
+	      idx2[0]=idx[0]-m_OuterBoundary;
+	      lower_bound=m_LowerGrayCSFBound;
+	      upper_bound=m_UpperGrayCSFBound;
+	    }
+
+	  
+
+	  ScalarValueType phi_other=it.GetImagePointer()->GetPixel(idx2);
+	  ScalarValueType phi_diff=(center_value-phi_other);
+
+
+	  ScalarValueType factor=1.0;
+
+
+	  if (phi_diff < lower_bound )
+	    factor=1.0-fabs(phi_diff-lower_bound)/m_ConstraintOffset;
+	  else if (phi_diff > upper_bound)
+	    factor=1.0-fabs(phi_diff-upper_bound)/m_ConstraintOffset;
+	  
+	  if (factor<0.0)
+	    factor=0.0;
+	  
+	  propagation_term=propagation_term*factor;
+	}
+      
+      //
+      // Construct upwind gradient values for use in the propagation speed term:
+      //  $\beta G(\mathbf{x})\mid\nabla\phi\mid$
+      //
+      // The following scheme for ``upwinding'' in the normal direction is taken
+      // from Sethian, Ch. 6 as referenced above.
+      //
+      propagation_gradient = ZERO;
+      
+      if (this->m_UseNonMorphometricTerm == 0 ) 
+	{
+	  if ( propagation_term > ZERO )
+	    {
+	      for(i = 0; i< ImageDimension; i++)
+		{
+		  propagation_gradient += vnl_math_sqr( vnl_math_max(gd->m_dx_backward[i], ZERO) )
+		    + vnl_math_sqr( vnl_math_min(gd->m_dx_forward[i],  ZERO) );
+		}
+	    }
+	  else
+	    {
+	      for(i = 0; i< ImageDimension; i++)
+		{
+		  propagation_gradient += vnl_math_sqr( vnl_math_min(gd->m_dx_backward[i], ZERO) )
+		    + vnl_math_sqr( vnl_math_max(gd->m_dx_forward[i],  ZERO) );
+		}        
+	    }
+	}
+      else
+	{
+	  propagation_gradient=m_HeavySideEpsilon/(3.1415927* (m_HeavySideEpsilon*m_HeavySideEpsilon+center_value*center_value));
+	}
+      
+      // Collect energy change from propagation term.  This will be used in
+      // calculating the maximum time step that can be taken for this iteration.
+      gd->m_MaxPropagationChange =	vnl_math_max(gd->m_MaxPropagationChange,  vnl_math_abs(propagation_term));
+      
+      propagation_term *= vcl_sqrt( propagation_gradient );
+    }
+
+
+
+  // ----------------------------------------------------------------------------
+  // 
+  // Step 4  Compute Laplacian Term 
+  //
+  // ---------------------------------------------------------------------------
+
+  laplacian_term = ZERO;  
+  if(this->m_LaplacianSmoothingWeight != ZERO && BoundaryMode!=0)
+    {
+      laplacian = ZERO;
+      for(i = 0;i < ImageDimension; i++)
+	  laplacian += gd->m_dxy[i][i];
+        laplacian_term = laplacian * this->m_LaplacianSmoothingWeight * LaplacianSmoothingSpeed(it,offset, gd);
+    }
+
+  
+  // ----------------------------------------------------------------------------
+  // 
+  // Step 5  Add it Up
+  //
+  // ---------------------------------------------------------------------------
+
+
+  /*  std::cerr << "\n Pixel("<<idx[0]<<","<<idx[1]<<")\n";
+  std::cerr << "Curvature   =" << curvature_term     << "(" << m_CurvatureWeight          << ")"   << std::endl;
+  std::cerr << "Propagation =" << propagation_term   << "(" << m_PropagationWeight        <<")"    << std::endl;
+  std::cerr << "Advection   =" << advection_term     << "(" << m_AdvectionWeight          << ")"   << std::endl;
+  std::cerr << "Laplacian   =" << laplacian_term     << "(" << m_LaplacianSmoothingWeight << ")" << std::endl;
+  PixelType a=( curvature_term - propagation_term 
+		- advection_term - laplacian_term );
+		std::cerr << "Overall     =" << a << "\n\n";*/
+  
+  // Return the combination of all the terms.
+  return ( PixelType ) ( curvature_term - propagation_term - advection_term - laplacian_term );
+}
+
+
+
+
+} // end namespace itk
+
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationCoupledLevelSetImageFilter.h b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationCoupledLevelSetImageFilter.h
new file mode 100644
index 0000000..c5ea787
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationCoupledLevelSetImageFilter.h
@@ -0,0 +1,281 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkpxTissueSegmentationCoupledLevelSetImageFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2004/06/01 18:33:45 $
+  Version:   $Revision: 1.19 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkpxTissueSegmentationCoupledLevelSetImageFilter_h_
+#define __itkpxTissueSegmentationCoupledLevelSetImageFilter_h_
+
+#include "itkSegmentationLevelSetImageFilter.h"
+#include "itkpxTissueSegmentationCoupledLevelSetFunction.h"
+
+namespace itk {
+
+/** \class TissueSegmentationCoupledLevelSetImageFilter
+ *    \brief Segments structures in images based on intensity values.
+ *
+ *   \par IMPORTANT
+ *   The SegmentationLevelSetImageFilter class and the
+ *   TissueSegmentationCoupledLevelSetFunction class contain additional information necessary
+ *   to the full understanding of how to use this filter.
+ *
+ *    \par OVERVIEW
+ *    This class is a level set method segmentation filter.  It constructs a
+ *    speed function which is close to zero at the upper and lower bounds of an
+ *    intensity window, effectively locking the propagating front onto those
+ *    edges.  Elsewhere, the front will propagate quickly.
+ *
+ *    \par INPUTS
+ *    This filter requires two inputs.  The first input is a seed
+ *    image.  This seed image must contain an isosurface that you want to use as the
+ *    seed for your segmentation.  It can be a binary, graylevel, or floating
+ *    point image.  The only requirement is that it contain a closed isosurface
+ *    that you will identify as the seed by setting the IsosurfaceValue parameter
+ *    of the filter.  For a binary image you will want to set your isosurface
+ *    value halfway between your on and off values (i.e. for 0's and 1's, use an
+ *    isosurface value of 0.5).
+ *
+ *    \par
+ *    The second input is the feature image.  This is the image from which the
+ *    speed function will be calculated.  For most applications, this is the
+ *    image that you want to segment. The desired isosurface in your seed image
+ *    should lie within the region of your feature image that you are trying to
+ *    segment. Note that this filter does no preprocessing of the feature image
+ *    before thresholding.
+ *
+ *    \par
+ *    See SegmentationLevelSetImageFilter for more information on Inputs.
+ *
+ *    \par OUTPUTS
+ *    The filter outputs a single, scalar, real-valued image.
+ *    Positive values in the output image are inside the segmentated region
+ *    and negative values in the image are outside of the inside region.  The
+ *    zero crossings of the image correspond to the position of the level set
+ *    front.
+ *
+ *   \par
+ *   See SparseFieldLevelSetImageFilter and
+ *   SegmentationLevelSetImageFilter for more information.
+ *
+ *   \par PARAMETERS
+ *   In addition to parameters described in SegmentationLevelSetImageFilter,
+ *   this filter adds the UpperTissue and LowerTissue.  See
+ *   TissueSegmentationCoupledLevelSetFunction for a description of how these values
+ *   affect the segmentation.
+ *
+ *   \sa SegmentationLevelSetImageFilter
+ *   \sa TissueSegmentationCoupledLevelSetFunction,
+ *   \sa SparseFieldLevelSetImageFilter */
+template <class TInputImage,
+          class TFeatureImage,
+          class TOutputPixelType = float >
+class TissueSegmentationCoupledLevelSetImageFilter : public SegmentationLevelSetImageFilter<TInputImage, TFeatureImage, TOutputPixelType >
+{
+public:
+  /** Standard class typedefs */
+  typedef TissueSegmentationCoupledLevelSetImageFilter Self;
+  typedef  SegmentationLevelSetImageFilter<TInputImage, TFeatureImage, TOutputPixelType > Superclass;
+  typedef SmartPointer<Self>  Pointer;
+  typedef SmartPointer<const Self>  ConstPointer;
+
+  /** Inherited typedef from the superclass. */
+  typedef typename Superclass::ValueType ValueType;
+  typedef typename Superclass::OutputImageType OutputImageType;
+  typedef typename Superclass::FeatureImageType FeatureImageType;
+  typedef typename Superclass::IndexType IndexType;
+
+  
+  /** Type of the segmentation function */
+  typedef TissueSegmentationCoupledLevelSetFunction<OutputImageType,
+                                                FeatureImageType> TissueFunctionType;
+  typedef typename TissueFunctionType::Pointer TissueFunctionPointer;
+  
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(TissueSegmentationCoupledLevelSetImageFilter, SegmentationLevelSetImageFilter);
+
+  /** Method for creation through the object factory */
+  itkNewMacro(Self);
+
+  /** Get/Set the boundaries of the two images */
+  void SetCoupledLevelSetBoundaries(int innerboundary,int outerboundary)
+  {
+    this->m_TissueFunction->SetCoupledLevelSetBoundaries(innerboundary,outerboundary);
+    this->Modified();
+  }
+
+  int GetInnerBoundary() const
+  {
+    return m_TissueFunction->GetInnerBoundary();
+  }
+
+  int GetOuterBoundary() const
+  {
+    return m_TissueFunction->GetOuterBoundary();
+  }
+
+ 
+  /** Get/Set the threshold values that will be used to calculate the speed function. */
+  void SetWhiteMatterTissue(ValueType m,ValueType f)
+  {
+    this->m_TissueFunction->SetWhiteMatterTissue(m,f);
+    this->Modified();
+  }
+  void SetGrayMatterTissue(ValueType m,ValueType f)
+  {
+    this->m_TissueFunction->SetGrayMatterTissue(m,f);
+    this->Modified();
+  }
+
+  void SetCSFTissue(ValueType m,ValueType f)
+  {
+    this->m_TissueFunction->SetCSFTissue(m,f);
+    this->Modified();
+  }
+
+
+  ValueType GetWhiteMatterMean() const
+  {
+    return m_TissueFunction->GetWhiteMatterMean();
+  }
+
+  ValueType GetWhiteMatterSigma() const
+  {
+    return m_TissueFunction->GetWhiteMatterSigma();
+  }
+
+  ValueType GetGrayMatterMean() const
+  {
+    return m_TissueFunction->GetGrayMatterMean();
+  }
+
+  ValueType GetGrayMatterSigma() const
+  {
+    return m_TissueFunction->GetGrayMatterSigma();
+  }
+
+
+
+  ValueType GetCSFMean() const
+  {
+    return m_TissueFunction->GetCSFMean();
+  }
+
+  ValueType GetCSFSigma() const
+  {
+    return m_TissueFunction->GetCSFSigma();
+  }
+
+
+  /** Set/Get the weight applied to the edge (Laplacian) attractor in the speed
+   *  term function. Zero will turn this term off. */
+  void SetEdgeWeight(ValueType v)
+  {
+    this->m_TissueFunction->SetEdgeWeight(v);
+    this->Modified();
+  }
+
+  ValueType GetEdgeWeight() const
+  {
+    return m_TissueFunction->GetEdgeWeight();
+  }
+
+
+  void SetHeavySideEpsilon(double v)
+  {
+    this->m_TissueFunction->SetHeavySideEpsilon(v);
+  }
+
+  double GetHeavySideEpsilon() const
+  {
+    return m_TissueFunction->GetHeavySideEpsilon();
+  }
+
+
+  // Coupling of Levelsets Stuff
+  // ---------------------------
+  void  SetLowerWhiteGrayBound(const float p)  {    m_TissueFunction->SetLowerWhiteGrayBound(p);       }
+  float GetLowerWhiteGrayBound() const         {    return m_TissueFunction->GetLowerWhiteGrayBound(); }
+  
+  void  SetUpperWhiteGrayBound(const float p)  {    m_TissueFunction->SetUpperWhiteGrayBound(p);       }
+  float GetUpperWhiteGrayBound() const         {    return m_TissueFunction->GetUpperWhiteGrayBound(); }
+
+  void  SetLowerGrayCSFBound(const float p)  {    m_TissueFunction->SetLowerGrayCSFBound(p);       }
+  float GetLowerGrayCSFBound() const         {    return m_TissueFunction->GetLowerGrayCSFBound(); }
+  
+  void  SetUpperGrayCSFBound(const float p)  {    m_TissueFunction->SetUpperGrayCSFBound(p);       }
+  float GetUpperGrayCSFBound() const         {    return m_TissueFunction->GetUpperGrayCSFBound(); }
+
+  void  SetConstraintOffset(const float p)  {    m_TissueFunction->SetConstraintOffset(p);       }
+  float GetConstraintOffset() const         {    return m_TissueFunction->GetConstraintOffset(); }
+
+  
+protected:
+  ~TissueSegmentationCoupledLevelSetImageFilter() {}
+  TissueSegmentationCoupledLevelSetImageFilter();
+
+  virtual void PrintSelf(std::ostream &os, Indent indent) const; 
+
+  TissueSegmentationCoupledLevelSetImageFilter(const Self &); // purposely not impl.
+  void operator=(const Self&); //purposely not implemented
+
+  /** Overrides parent implementation. Allows for Chen and Vesse like term computation */
+  //  virtual void InitializeIteration();
+
+
+
+private:
+  TissueFunctionPointer m_TissueFunction;
+};
+
+} // end namespace itk
+
+
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkpxTissueSegmentationCoupledLevelSetImageFilter.txx"
+#endif
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationCoupledLevelSetImageFilter.txx b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationCoupledLevelSetImageFilter.txx
new file mode 100644
index 0000000..d0586e6
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationCoupledLevelSetImageFilter.txx
@@ -0,0 +1,80 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkpxTissueSegmentationCoupledLevelSetImageFilter.txx,v $
+  Language:  C++
+  Date:      $Date: 2003/09/10 14:28:39 $
+  Version:   $Revision: 1.11 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkpxTissueSegmentationCoupledLevelSetImageFilter_txx_
+#define __itkpxTissueSegmentationCoupledLevelSetImageFilter_txx_
+
+#include "itkpxTissueSegmentationCoupledLevelSetImageFilter.h"
+#include <math.h>
+#include "pxisinf.h"
+
+namespace itk {
+
+template <class TInputImage, class TFeatureImage, class TOutputType>
+TissueSegmentationCoupledLevelSetImageFilter<TInputImage, TFeatureImage, TOutputType>
+::TissueSegmentationCoupledLevelSetImageFilter()
+{
+  m_TissueFunction = TissueFunctionType::New();
+  this->SetSegmentationFunction(m_TissueFunction);
+}
+ 
+template <class TInputImage, class TFeatureImage, class TOutputType>
+void TissueSegmentationCoupledLevelSetImageFilter<TInputImage, TFeatureImage, TOutputType>
+::PrintSelf(std::ostream &os, Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+  os << "TissueFunction: " << m_TissueFunction;
+}
+
+
+}// end namespace itk
+
+
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationLevelSetFunction.h b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationLevelSetFunction.h
new file mode 100644
index 0000000..dff7315
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationLevelSetFunction.h
@@ -0,0 +1,385 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkTissueSegmentationLevelSetFunction.h,v $
+  Language:  C++
+  Date:      $Date: 2003/09/10 14:28:39 $
+  Version:   $Revision: 1.12 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkTissueSegmentationLevelSetFunction_h_
+#define __itkTissueSegmentationLevelSetFunction_h_
+
+#include "itkSegmentationLevelSetFunction.h"
+#include "itkConstNeighborhoodIterator.h"
+#include "itkImageRegionIterator.h"
+#include "itkImageRegionConstIterator.h"
+#include "itkImageRegionConstIteratorWithIndex.h"
+#include "itkNumericTraits.h"
+
+#ifndef M_PI
+#define M_PI 3.14159
+#endif
+
+namespace itk {
+
+/** \class TissueSegmentationLevelSetFunction
+ *    
+ * \brief This function is used in TissueSegmentationLevelSetImageFilter to
+ * segment structures in images based on intensity values.
+ *
+ * \par  SegmentationLevelSetFunction is a subclass of the generic LevelSetFunction.
+ * It useful for segmentations based on intensity values in an image.  It works
+ * by constructing a speed term (feature image) with positive values inside an
+ * intensity window (between a low and high threshold) and negative values
+ * outside that intensity window.  The evolving level set front will lock onto
+ * regions that are at the edges of the intensity window.
+ *
+ *  You may optionally add a Laplacian calculation on the image to the
+ *  threshold-based speed term by setting the EdgeWeight parameter to a
+ *  non-zero value.  The Laplacian term will cause the evolving surface to
+ *  be more strongly attracted to image edges.   Several parameters control a
+ *  preprocessing FeatureImage smoothing stage applied only to the Laplacian
+ *  calculation.
+ *
+ *  \par
+ *  Image $f$ is thresholded pixel by pixel using upper threshold
+ *  $U$ and lower threshold $L$ according to the following formula.
+ *
+ * \par
+ *  \f$  f(x) = \left\{ \begin{array}{ll} g(x) - L & \mbox{if $(g)x < (U-L)/2 + L$} \\ U - g(x) & \mbox{otherwise} \end{array} \right. \f$ 
+ *
+ * \sa SegmentationLevelSetImageFunction
+ *  \sa TissueSegmentationLevelSetImageFilter */
+template <class TImageType, class TFeatureImageType = TImageType>
+class TissueSegmentationLevelSetFunction
+  : public SegmentationLevelSetFunction<TImageType, TFeatureImageType>
+{
+public:
+  /** Standard class typedefs. */
+  typedef TissueSegmentationLevelSetFunction Self;
+  typedef SegmentationLevelSetFunction<TImageType, TFeatureImageType> Superclass;
+  typedef SmartPointer<Self> Pointer;
+  typedef SmartPointer<const Self> ConstPointer;
+  typedef TFeatureImageType FeatureImageType;
+
+  /** Method for creation through the object factory. */
+  itkNewMacro(Self);
+
+  /** Run-time type information (and related methods) */
+  itkTypeMacro( TissueSegmentationLevelSetFunction, SegmentationLevelSetFunction );
+
+  /** Extract some parameters from the superclass. */
+  typedef typename Superclass::ImageType ImageType;
+  typedef typename Superclass::ScalarValueType ScalarValueType;
+  typedef typename Superclass::FeatureScalarType FeatureScalarType;
+  typedef typename Superclass::RadiusType RadiusType;
+  typedef typename Superclass::FloatOffsetType FloatOffsetType;
+  typedef typename Superclass::VectorImageType VectorImageType;
+  typedef typename Superclass::VectorType VectorType;
+  typedef typename Superclass::PixelType PixelType;
+  typedef typename Superclass::TimeStepType TimeStepType;
+  typedef typename Superclass::IndexType IndexType;
+  typedef typename Superclass::ContinuousIndexType ContinuousIndexType;
+  typedef typename Superclass::NeighborhoodType NeighborhoodType;
+  
+
+  /** Extract some parameters from the superclass. */
+  itkStaticConstMacro(ImageDimension, unsigned int,Superclass::ImageDimension);
+
+
+  // ** Image and Image Iterator definition */
+  typedef ImageRegionIterator<ImageType>                    ImageIterator;
+  typedef ImageRegionConstIterator<ImageType>               ConstImageIterator;
+  typedef ImageRegionConstIteratorWithIndex<ImageType>      ConstImageIteratorWithIndex;
+  typedef ConstNeighborhoodIterator<ImageType>              NeighborhoodIterator;
+
+  typedef itk::CovariantVector<float,3>                     GradientOutputPixel;
+  typedef itk::Image<GradientOutputPixel,pxImageDimension>  GradientOutputType;
+  typedef ImageRegionConstIterator<GradientOutputType>      GradientImageIterator;
+
+
+  // -------------------------------------
+  // Stuff for Using Tissue Specific Speed
+  // -------------------------------------
+  void SetUseTissueSpecificSpeedMode(int m) {
+    if (m<0 || m>2)  m=0;
+    m_UseTissueSpecificSpeedMode=m;
+    
+  }
+  
+  int GetUseTissueSpecificSpeedMode() { 
+    return m_UseTissueSpecificSpeedMode;
+  }
+
+  // ------------------------------------------------------
+  // Use Chen/Vesse \delta(x) instead of |\nabla \phi| term
+  // ------------------------------------------------------
+  void SetUseNonMorphometricTerm(int m) { 
+    m_UseNonMorphometricTerm=(m>0);
+  }
+  
+  int GetUseNonMorphometricTerm() {
+    return m_UseNonMorphometricTerm;
+  }
+
+  // ------------------------------------------------------
+  // Epsilon Term for Heavy Side Function
+  // ------------------------------------------------------
+  void SetHeavySideEpsilon(double d) {
+    m_HeavySideEpsilon=d;
+  }
+
+  double GetHeavySideEpsilon() {
+    return m_HeavySideEpsilon;
+  }
+
+
+  /** Set/Get the sigma for the Gaussian kernel used to compute the gradient
+   * of the feature image needed for the advection term of the equation. */
+  void SetDerivativeSigma( const double v )
+  { m_DerivativeSigma = v; }
+  double GetDerivativeSigma()
+  { return m_DerivativeSigma; };
+
+
+  /** Set/Get threshold values */
+  void SetInsideTissue(FeatureScalarType m,FeatureScalarType s)  {
+    m_InsideMean  = m;
+    m_InsideSigma = s;
+    if (m_InsideSigma<1.0)
+      m_InsideSigma=1.0;
+  }
+  FeatureScalarType GetInsideMean() const  { return m_InsideMean; }
+  FeatureScalarType GetInsideSigma() const  { return m_InsideSigma; }
+
+
+  void SetOutsideTissue(FeatureScalarType m,FeatureScalarType s)  {
+    m_OutsideMean  = m;
+    m_OutsideSigma = s;
+    if (m_OutsideSigma<1.0)
+      m_OutsideSigma=1.0;
+
+  }
+  FeatureScalarType GetOutsideMean() const  { return m_OutsideMean; }
+  FeatureScalarType GetOutsideSigma() const  { return m_OutsideSigma; }
+
+
+  // Second Outside Class
+  void SetBiExponentialOutside(int m) { 
+    m_BiExponentialOutside=(m>0);
+  }
+  
+  int GetUseBiExponentialOutside() {
+    return m_BiExponentialOutside;
+  }
+
+
+  void SetOutside2Tissue(FeatureScalarType m,FeatureScalarType s)  {
+    m_Outside2Mean  = m;
+    m_Outside2Sigma = s;
+    if (m_Outside2Sigma<1.0)
+      m_Outside2Sigma=1.0;
+
+  }
+  FeatureScalarType GetOutside2Mean() const  { return m_Outside2Mean; }
+  FeatureScalarType GetOutside2Sigma() const  { return m_Outside2Sigma; }
+
+
+  // 
+  //  This is from Yun Zhu et al Cardiac Segmentation Volume Constraint
+  //
+  // ApproximateVolume  is volume that the body should be approximately
+  // ApproximateVolumeConstraintWeight is the weight of this constraint
+  void SetApproximateVolume(double v)
+  {
+    m_ApproximateVolume=v;
+  }
+
+  double GetApproximateVolume() const
+  {
+    return m_ApproximateVolume;
+  }
+
+  void SetMyVolume(double v)
+  {
+    m_MyVolume=v;
+  }
+
+  double GetMyVolume() const
+  {
+    return m_MyVolume;
+  }
+
+
+  void SetApproximateVolumeConstraintWeight(double v)
+  {
+    m_ApproximateVolumeConstraintWeight=v;
+  }
+
+  double GetApproximateVolumeConstraintWeight() const
+  {
+    return m_ApproximateVolumeConstraintWeight;
+  }
+
+
+
+
+
+  virtual void CalculateSpeedImage();
+  virtual void CalculateAdvectionImage();
+
+  virtual void Initialize(const RadiusType &r)
+  {
+    Superclass::Initialize(r);
+    //    this->SetAdvectionWeight( NumericTraits<ScalarValueType>::Zero);
+    this->SetPropagationWeight(-1.0 * NumericTraits<ScalarValueType>::One);
+    this->SetCurvatureWeight(NumericTraits<ScalarValueType>::One);
+    this->SetAdvectionWeight( NumericTraits<ScalarValueType>::One );
+    m_DerivativeSigma = 1.0;
+  }
+
+  /** Set/Get the weight applied to the edge (Laplacian) attractor in the speed
+   *  term function. Zero will turn this term off. */
+  void SetEdgeWeight(const ScalarValueType p)
+  {
+    m_EdgeWeight = p;
+  }
+  ScalarValueType GetEdgeWeight() const
+  {
+    return m_EdgeWeight;
+  }
+  
+  
+  FeatureScalarType InsideTissueFunction(FeatureScalarType v) {
+    return ( (v-m_InsideMean)*(v-m_InsideMean)/(m_InsideSigma*m_InsideSigma )) + 0.5*log(2.0*M_PI)+log(m_InsideSigma);
+  }
+
+  FeatureScalarType OutsideTissueFunction(FeatureScalarType v) {
+    return ( (v-m_OutsideMean)*(v-m_OutsideMean)/(m_OutsideSigma*m_OutsideSigma )) + 0.5*log(2.0*M_PI)+log(m_OutsideSigma);
+  }
+
+  FeatureScalarType Outside2TissueFunction(FeatureScalarType v) {
+    return ( (v-m_Outside2Mean)*(v-m_Outside2Mean)/(m_Outside2Sigma*m_Outside2Sigma )) + 0.5*log(2.0*M_PI)+log(m_Outside2Sigma);
+  }
+
+
+  /** Get/Set the image used as the speed function in the level set equation */
+  typedef typename Superclass::GlobalDataStruct GlobalDataStruct;
+
+  virtual PixelType ComputeUpdate(const NeighborhoodType &neighborhood,
+                                  void *globalData,
+                                  const FloatOffsetType& = FloatOffsetType(0.0));
+
+
+
+
+protected:
+  TissueSegmentationLevelSetFunction()
+  {
+    this->SetAdvectionWeight(0.0);
+    this->SetPropagationWeight(1.0);
+    this->SetCurvatureWeight(1.0);
+    this->SetEdgeWeight(0.0);
+    this->SetInsideTissue(100.0,10.0);
+    this->SetOutsideTissue(0.0,10.0);
+    this->SetOutside2Tissue(0.0,-1.0);
+    m_UseTissueSpecificSpeedMode=1;
+    m_UseNonMorphometricTerm=0;
+    m_BiExponentialOutside=0;
+    m_HeavySideEpsilon=1.0;
+
+    m_ApproximateVolume=100.0;
+    m_MyVolume=100.0;
+    m_ApproximateVolumeConstraintWeight=0.0;
+  }
+
+  virtual ~TissueSegmentationLevelSetFunction() {
+
+    
+  }
+
+  TissueSegmentationLevelSetFunction(const Self&); //purposely not implemented
+  void operator=(const Self&); //purposely not implemented
+  
+  void PrintSelf(std::ostream& os, Indent indent) const
+  {
+    Superclass::PrintSelf(os, indent );
+    os << indent << "Use Tissue Specific Speed Mode (0=none,1=Chen & Vesse,2=Xiaolan)" << m_UseTissueSpecificSpeedMode << std::endl;
+    os << indent << "Use NonMorphometric Speed Multiplier " << m_UseNonMorphometricTerm << std::endl;
+    os << indent << "Heavy Side Epsilon " << m_HeavySideEpsilon << std::endl;
+    os << indent << "Inside Tissue: " << m_InsideMean << " + " << m_InsideSigma << std::endl;
+    os << indent << "Outside Tissue: " << m_OutsideMean << " + " << m_OutsideSigma << std::endl;
+    os << indent << "Outside2 Tissue: " << m_Outside2Mean << " + " << m_Outside2Sigma << std::endl;
+    os << indent << "BiExponenital Outside: " << m_BiExponentialOutside << std::endl;
+    os << indent << "EdgeWeight: " << m_EdgeWeight << std::endl;
+    os << indent << "DerivativeSigma: " << m_DerivativeSigma << std::endl;
+  }
+  
+  FeatureScalarType m_InsideMean;
+  FeatureScalarType m_InsideSigma;
+  FeatureScalarType m_OutsideMean;
+  FeatureScalarType m_OutsideSigma;
+  FeatureScalarType m_Outside2Mean;
+  FeatureScalarType m_Outside2Sigma;
+  ScalarValueType   m_EdgeWeight;
+  double            m_ApproximateVolume;
+  double            m_MyVolume;
+  double            m_ApproximateVolumeConstraintWeight;
+
+  double m_DerivativeSigma;
+  double m_HeavySideEpsilon;
+  int  m_UseNonMorphometricTerm;
+  int  m_UseTissueSpecificSpeedMode;
+  int  m_BiExponentialOutside;
+
+    /** The image holding the speed values for front propagation */
+
+};
+  
+} // end namespace itk
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkpxTissueSegmentationLevelSetFunction.txx"
+#endif
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationLevelSetFunction.txx b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationLevelSetFunction.txx
new file mode 100644
index 0000000..ddcfdd3
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationLevelSetFunction.txx
@@ -0,0 +1,378 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkTissueSegmentationLevelSetFunction.txx,v $
+  Language:  C++
+  Date:      $Date: 2003/09/10 14:28:39 $
+  Version:   $Revision: 1.5 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkTissueSegmentationLevelSetFunction_txx_
+#define __itkTissueSegmentationLevelSetFunction_txx_
+
+#include "itkpxTissueSegmentationLevelSetFunction.h"
+#include "vtkpxLevelSetUtil.h"
+#include "itkGradientRecursiveGaussianImageFilter.h"
+#include "itkImageRegionIterator.h"
+
+namespace itk {
+
+template <class TImageType, class TFeatureImageType>
+void TissueSegmentationLevelSetFunction<TImageType, TFeatureImageType>
+::CalculateSpeedImage()
+{
+  //  ImageRegionIterator<FeatureImageType> lit;
+  ImageRegionConstIterator<FeatureImageType>  fit(this->GetFeatureImage(), this->GetFeatureImage()->GetRequestedRegion());
+  ImageRegionIterator<ImageType>              sit(this->GetSpeedImage(), this->GetFeatureImage()->GetRequestedRegion());
+
+  for ( fit.GoToBegin(), sit.GoToBegin(); ! fit.IsAtEnd(); ++sit, ++fit)
+    sit.Set( static_cast<ScalarValueType>(fit.Get()));
+}
+
+
+template <class TImageType, class TFeatureImageType>
+void TissueSegmentationLevelSetFunction<TImageType, TFeatureImageType>
+::CalculateAdvectionImage()
+{
+  /* compoute the gradient of the feature image. */
+  typedef GradientRecursiveGaussianImageFilter<FeatureImageType,VectorImageType>
+    DerivativeFilterType;
+
+  typename DerivativeFilterType::Pointer derivative = DerivativeFilterType::New();
+  derivative->SetInput( this->GetFeatureImage() );
+  derivative->SetSigma( m_DerivativeSigma );
+  derivative->Update();
+  
+  /* copy negative gradient into the advection image. */
+  ImageRegionIterator<VectorImageType>
+    dit( derivative->GetOutput(), this->GetFeatureImage()->GetRequestedRegion() );
+  ImageRegionIterator<VectorImageType>
+    ait( this->GetAdvectionImage(), this->GetFeatureImage()->GetRequestedRegion() );
+
+  for( dit.GoToBegin(), ait.GoToBegin(); !dit.IsAtEnd(); ++dit, ++ait )
+    {
+      typename VectorImageType::PixelType v = dit.Get();
+      for ( unsigned int j = 0; j < ImageDimension; j++ )
+	  v[j] *= -1.0L;
+
+      ait.Set( v);
+    }
+}
+
+
+template <class TImageType, class TFeatureImageType>
+typename TissueSegmentationLevelSetFunction<TImageType, TFeatureImageType>::PixelType
+TissueSegmentationLevelSetFunction<TImageType, TFeatureImageType>::ComputeUpdate(
+										 const NeighborhoodType &it,
+										 void *globalData,
+										 const FloatOffsetType& offset )
+{
+  static int count=0;
+  ++count;
+  unsigned int i, j;  
+  const ScalarValueType ZERO = NumericTraits<ScalarValueType>::Zero;
+  const ScalarValueType center_value  = it.GetCenterPixel();
+  
+  
+
+
+  ScalarValueType laplacian, x_energy, laplacian_term, propagation_term,
+    curvature_term, advection_term, propagation_gradient;
+  VectorType advection_field;
+
+  ScalarValueType mean1  = static_cast<ScalarValueType>(m_InsideMean);
+  ScalarValueType sigma1 = static_cast<ScalarValueType>(m_InsideSigma);
+
+
+  //  ScalarValueType mean2  = static_cast<ScalarValueType>(m_OutsideMean);
+  //  ScalarValueType sigma2 = static_cast<ScalarValueType>(m_OutsideSigma);
+
+
+  // Global data structure
+  GlobalDataStruct *gd = (GlobalDataStruct *)globalData;
+
+
+  // ----------------------------------------------------------------------------
+  // 
+  // Step 0 Compute Derivatives etc
+  //
+  // ---------------------------------------------------------------------------
+
+  gd->m_GradMagSqr = 1.0e-6;
+  for( i = 0 ; i < ImageDimension; i++)
+    {
+      const unsigned int positionA = 
+	static_cast<unsigned int>( this->m_Center + this->m_xStride[i]);    
+      const unsigned int positionB = 
+	static_cast<unsigned int>( this->m_Center - this->m_xStride[i]);    
+      
+      gd->m_dx[i] = 0.5 * (it.GetPixel( positionA ) - 
+			   it.GetPixel( positionB )    );
+      
+      gd->m_dxy[i][i] = it.GetPixel( positionA )
+	+ it.GetPixel( positionB ) - 2.0 * center_value;
+      
+      gd->m_dx_forward[i]  = it.GetPixel( positionA ) - center_value;
+      gd->m_dx_backward[i] = center_value - it.GetPixel( positionB );
+      gd->m_GradMagSqr += gd->m_dx[i] * gd->m_dx[i];
+      
+      for( j = i+1; j < ImageDimension; j++ )
+	{
+	  const unsigned int positionAa = static_cast<unsigned int>( 
+								    this->m_Center - this->m_xStride[i] - this->m_xStride[j] );
+	  const unsigned int positionBa = static_cast<unsigned int>( 
+								    this->m_Center - this->m_xStride[i] + this->m_xStride[j] );
+	  const unsigned int positionCa = static_cast<unsigned int>( 
+								    this->m_Center + this->m_xStride[i] - this->m_xStride[j] );
+	  const unsigned int positionDa = static_cast<unsigned int>( 
+								    this->m_Center + this->m_xStride[i] + this->m_xStride[j] );
+	  
+	  gd->m_dxy[i][j] = gd->m_dxy[j][i] = 0.25 *( it.GetPixel( positionAa )
+						      - it.GetPixel( positionBa )
+						      - it.GetPixel( positionCa )
+						      + it.GetPixel( positionDa )
+						      );
+	}
+    }
+  
+
+  // ----------------------------------------------------------------------------
+  // 
+  // Step 1 Compute Curvature Term 
+  //
+  // ---------------------------------------------------------------------------
+
+
+  if ( this->m_CurvatureWeight != ZERO )
+    {
+      curvature_term = this->ComputeCurvatureTerm(it, offset, gd) * this->m_CurvatureWeight * this->CurvatureSpeed(it, offset);
+      gd->m_MaxCurvatureChange = vnl_math_max(gd->m_MaxCurvatureChange, vnl_math_abs(curvature_term));
+    }
+  else
+    {
+      curvature_term = ZERO;
+    }
+  
+
+  // ----------------------------------------------------------------------------
+  // 
+  // Step 2 Compute Advection Term 
+  //
+  // ---------------------------------------------------------------------------
+
+  if (this->m_AdvectionWeight != ZERO)
+    {
+      advection_field = this->AdvectionField(it, offset, gd);
+      advection_term = ZERO;
+      for(i = 0; i < ImageDimension; i++)
+	{
+	  x_energy = this->m_AdvectionWeight * advection_field[i];
+	  if (x_energy > ZERO)
+	    {
+	      advection_term += advection_field[i] * gd->m_dx_backward[i];
+	    }
+	  else
+	    {
+	      advection_term += advection_field[i] * gd->m_dx_forward[i];
+	    }
+	  
+	  gd->m_MaxAdvectionChange = vnl_math_max(gd->m_MaxAdvectionChange, vnl_math_abs(x_energy)); 
+	}
+      advection_term *= this->m_AdvectionWeight;
+    }
+  else
+    {
+      advection_term = ZERO;
+    }
+  
+
+  // ----------------------------------------------------------------------------
+  // 
+  // Step 3 Compute Propagation Term 
+  //
+  // ---------------------------------------------------------------------------
+
+  typename ImageType::IndexType idx=it.GetIndex();
+
+
+  if (this->m_PropagationWeight > 0 ) 
+    {
+      
+      if (this->m_UseTissueSpecificSpeedMode==0)
+	{
+	  //	  std::cerr << "Tissue SPECIFIC MODE is ZERO .................... \n";
+	  propagation_term = this->m_PropagationWeight * this->PropagationSpeed(it, offset, gd);
+	}
+      else
+	{
+	  ScalarValueType intensity=this->PropagationSpeed(it, offset, gd);
+	  
+	  ScalarValueType t1=this->InsideTissueFunction(intensity);
+	  ScalarValueType t2=this->OutsideTissueFunction(intensity);
+	  if (this->m_BiExponentialOutside==1)
+	    {
+	      ScalarValueType t3=this->Outside2TissueFunction(intensity);
+	      if (t3<t2)
+		t2=t3;
+	    }
+	  
+	  ScalarValueType sp=t2-t1;
+	  
+	  if (this->m_UseTissueSpecificSpeedMode==2)
+	    {
+	      if (intensity < (mean1-3.0*sigma1 ) || intensity < (mean1+5.5*sigma1)  )
+		sp=0.0;
+	    }
+	  propagation_term = this->m_PropagationWeight * sp;
+	}
+    
+  
+      if (    m_ApproximateVolumeConstraintWeight > 0.0)
+	{
+	  //	  std::cerr << "Tissue ON to Approxumate Volume Constraint .................... \n";
+	  //2*lamda*vc
+	  double addp=m_ApproximateVolumeConstraintWeight*(m_ApproximateVolume-m_MyVolume)/(m_ApproximateVolume);
+	  propagation_term = propagation_term + addp;
+
+	  /*	  if (count==1000)
+	    {
+	      std::cerr << "Volume   =" << m_MyVolume     << ", target_volume = " << m_ApproximateVolume << ", (add = " << addp  << ")" << std::endl; 
+	      }*/
+	}
+      
+      
+      //
+      // Construct upwind gradient values for use in the propagation speed term:
+      //  $\beta G(\mathbf{x})\mid\nabla\phi\mid$
+      //
+      // The following scheme for ``upwinding'' in the normal direction is taken
+      // from Sethian, Ch. 6 as referenced above.
+      //
+      propagation_gradient = ZERO;
+      
+      if (this->m_UseNonMorphometricTerm == 0 ) 
+	{
+	  if ( propagation_term > ZERO )
+	    {
+	      for(i = 0; i< ImageDimension; i++)
+		{
+		  propagation_gradient += vnl_math_sqr( vnl_math_max(gd->m_dx_backward[i], ZERO) )
+		    + vnl_math_sqr( vnl_math_min(gd->m_dx_forward[i],  ZERO) );
+		}
+	    }
+	  else
+	    {
+	      for(i = 0; i< ImageDimension; i++)
+		{
+		  propagation_gradient += vnl_math_sqr( vnl_math_min(gd->m_dx_backward[i], ZERO) )
+		    + vnl_math_sqr( vnl_math_max(gd->m_dx_forward[i],  ZERO) );
+		}        
+	    }
+	}
+      else
+	{
+	  propagation_gradient=m_HeavySideEpsilon/(3.1415927* (m_HeavySideEpsilon*m_HeavySideEpsilon+center_value*center_value));
+	}
+      
+      // Collect energy change from propagation term.  This will be used in
+      // calculating the maximum time step that can be taken for this iteration.
+      gd->m_MaxPropagationChange =	vnl_math_max(gd->m_MaxPropagationChange,  vnl_math_abs(propagation_term));
+      
+      propagation_term *= vcl_sqrt( propagation_gradient );
+      
+      //      propagation_term = ZERO;
+    }
+  /*  else
+    {
+      std::cerr << "Propagation Weight is ZERO .................... \n";
+      }*/
+
+  // ----------------------------------------------------------------------------
+  // 
+  // Step 4  Compute Laplacian Term 
+  //
+  // ---------------------------------------------------------------------------
+  
+  if(this->m_LaplacianSmoothingWeight != ZERO)
+    {
+      laplacian = ZERO;
+        for(i = 0;i < ImageDimension; i++)
+	  laplacian += gd->m_dxy[i][i];
+        laplacian_term = laplacian * this->m_LaplacianSmoothingWeight * LaplacianSmoothingSpeed(it,offset, gd);
+    }
+  else 
+    laplacian_term = ZERO;
+  
+  // ----------------------------------------------------------------------------
+  // 
+  // Step 5  Add it Up
+  //
+  // ---------------------------------------------------------------------------
+
+  /*  if (count==1000)
+    {
+      std::cerr << "\n Pixel("<<idx[0]<<","<<idx[1]<<"," << idx[2]<< ")\n";
+      std::cerr << "Curvature   =" << curvature_term     << "(" << this->m_CurvatureWeight          << ")"   << std::endl;
+      std::cerr << "Propagation =" << propagation_term   << "(" << this->m_PropagationWeight        <<")"    << std::endl;
+      std::cerr << "Advection   =" << advection_term     << "(" << this->m_AdvectionWeight          << ")"   << std::endl;
+      std::cerr << "Laplacian   =" << laplacian_term     << "(" << this->m_LaplacianSmoothingWeight << ")" << std::endl;
+
+
+
+      PixelType a=( curvature_term - propagation_term 
+                         - advection_term - laplacian_term );
+      std::cerr << "Overall     =" << a << "\n\n";
+      count=0;
+      }*/
+  
+  // Return the combination of all the terms.
+  return ( PixelType ) ( curvature_term - propagation_term - advection_term - laplacian_term );
+}
+
+
+
+
+} // end namespace itk
+
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationLevelSetImageFilter.h b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationLevelSetImageFilter.h
new file mode 100644
index 0000000..3111544
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationLevelSetImageFilter.h
@@ -0,0 +1,278 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkpxTissueSegmentationLevelSetImageFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2004/06/01 18:33:45 $
+  Version:   $Revision: 1.19 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkpxTissueSegmentationLevelSetImageFilter_h_
+#define __itkpxTissueSegmentationLevelSetImageFilter_h_
+
+#include "itkSegmentationLevelSetImageFilter.h"
+#include "itkpxTissueSegmentationLevelSetFunction.h"
+
+namespace itk {
+
+/** \class TissueSegmentationLevelSetImageFilter
+ *    \brief Segments structures in images based on intensity values.
+ *
+ *   \par IMPORTANT
+ *   The SegmentationLevelSetImageFilter class and the
+ *   TissueSegmentationLevelSetFunction class contain additional information necessary
+ *   to the full understanding of how to use this filter.
+ *
+ *    \par OVERVIEW
+ *    This class is a level set method segmentation filter.  It constructs a
+ *    speed function which is close to zero at the upper and lower bounds of an
+ *    intensity window, effectively locking the propagating front onto those
+ *    edges.  Elsewhere, the front will propagate quickly.
+ *
+ *    \par INPUTS
+ *    This filter requires two inputs.  The first input is a seed
+ *    image.  This seed image must contain an isosurface that you want to use as the
+ *    seed for your segmentation.  It can be a binary, graylevel, or floating
+ *    point image.  The only requirement is that it contain a closed isosurface
+ *    that you will identify as the seed by setting the IsosurfaceValue parameter
+ *    of the filter.  For a binary image you will want to set your isosurface
+ *    value halfway between your on and off values (i.e. for 0's and 1's, use an
+ *    isosurface value of 0.5).
+ *
+ *    \par
+ *    The second input is the feature image.  This is the image from which the
+ *    speed function will be calculated.  For most applications, this is the
+ *    image that you want to segment. The desired isosurface in your seed image
+ *    should lie within the region of your feature image that you are trying to
+ *    segment. Note that this filter does no preprocessing of the feature image
+ *    before thresholding.
+ *
+ *    \par
+ *    See SegmentationLevelSetImageFilter for more information on Inputs.
+ *
+ *    \par OUTPUTS
+ *    The filter outputs a single, scalar, real-valued image.
+ *    Positive values in the output image are inside the segmentated region
+ *    and negative values in the image are outside of the inside region.  The
+ *    zero crossings of the image correspond to the position of the level set
+ *    front.
+ *
+ *   \par
+ *   See SparseFieldLevelSetImageFilter and
+ *   SegmentationLevelSetImageFilter for more information.
+ *
+ *   \par PARAMETERS
+ *   In addition to parameters described in SegmentationLevelSetImageFilter,
+ *   this filter adds the UpperTissue and LowerTissue.  See
+ *   TissueSegmentationLevelSetFunction for a description of how these values
+ *   affect the segmentation.
+ *
+ *   \sa SegmentationLevelSetImageFilter
+ *   \sa TissueSegmentationLevelSetFunction,
+ *   \sa SparseFieldLevelSetImageFilter */
+template <class TInputImage,
+          class TFeatureImage,
+          class TOutputPixelType = float >
+class TissueSegmentationLevelSetImageFilter : public SegmentationLevelSetImageFilter<TInputImage, TFeatureImage, TOutputPixelType >
+{
+public:
+  /** Standard class typedefs */
+  typedef TissueSegmentationLevelSetImageFilter Self;
+  typedef  SegmentationLevelSetImageFilter<TInputImage, TFeatureImage, TOutputPixelType > Superclass;
+  typedef SmartPointer<Self>  Pointer;
+  typedef SmartPointer<const Self>  ConstPointer;
+
+  /** Inherited typedef from the superclass. */
+  typedef typename Superclass::ValueType ValueType;
+  typedef typename Superclass::OutputImageType OutputImageType;
+  typedef typename Superclass::FeatureImageType FeatureImageType;
+  typedef typename Superclass::IndexType IndexType;
+
+  
+  /** Type of the segmentation function */
+  typedef TissueSegmentationLevelSetFunction<OutputImageType,
+                                                FeatureImageType> TissueFunctionType;
+  typedef typename TissueFunctionType::Pointer TissueFunctionPointer;
+  
+  /** Run-time type information (and related methods). */
+  itkTypeMacro(TissueSegmentationLevelSetImageFilter, SegmentationLevelSetImageFilter);
+
+  /** Method for creation through the object factory */
+  itkNewMacro(Self);
+  
+  /** Get/Set the threshold values that will be used to calculate the speed function. **/
+  void SetInsideTissue(ValueType m,ValueType f)
+  {
+    this->m_TissueFunction->SetInsideTissue(m,f);
+    this->Modified();
+  }
+  void SetOutsideTissue(ValueType m,ValueType f)
+  {
+    this->m_TissueFunction->SetOutsideTissue(m,f);
+    this->Modified();
+  }
+
+  void SetOutside2Tissue(ValueType m,ValueType f)
+  {
+    this->m_TissueFunction->SetOutside2Tissue(m,f);
+    this->Modified();
+  }
+
+
+  ValueType GetInsideMean() const
+  {
+    return m_TissueFunction->GetInsideMean();
+  }
+
+  ValueType GetInsideSigma() const
+  {
+    return m_TissueFunction->GetInsideSigma();
+  }
+
+  ValueType GetOutsideMean() const
+  {
+    return m_TissueFunction->GetOutsideMean();
+  }
+
+  ValueType GetOutsideSigma() const
+  {
+    return m_TissueFunction->GetOutsideSigma();
+  }
+
+
+
+  ValueType GetOutside2Mean() const
+  {
+    return m_TissueFunction->GetOutside2Mean();
+  }
+
+  ValueType GetOutside2Sigma() const
+  {
+    return m_TissueFunction->GetOutside2Sigma();
+  }
+
+
+  /** Set/Get the weight applied to the edge (Laplacian) attractor in the speed
+   *  term function. Zero will turn this term off. */
+  void SetEdgeWeight(ValueType v)
+  {
+    this->m_TissueFunction->SetEdgeWeight(v);
+    this->Modified();
+  }
+
+  ValueType GetEdgeWeight() const
+  {
+    return m_TissueFunction->GetEdgeWeight();
+  }
+
+
+  void SetHeavySideEpsilon(double v)
+  {
+    this->m_TissueFunction->SetHeavySideEpsilon(v);
+  }
+
+  double GetHeavySideEpsilon() const
+  {
+    return m_TissueFunction->GetHeavySideEpsilon();
+  }
+
+  // 
+  //  This is from Yun Zhu et al Cardiac Segmentation Volume Constraint
+  //
+  // ApproximateVolume  is volume that the body should be approximately
+  // ApproximateVolumeConstraintWeight is the weight of this constraint
+  void SetApproximateVolume(double v)
+  {
+    this->m_TissueFunction->SetApproximateVolume(v);
+  }
+
+  double GetApproximateVolume() const
+  {
+    return m_TissueFunction->GetApproximateVolume();
+  }
+
+  void SetApproximateVolumeConstraintWeight(double v)
+  {
+    this->m_TissueFunction->SetApproximateVolumeConstraintWeight(v);
+  }
+
+  double GetApproximateVolumeConstraintWeight() const
+  {
+    return m_TissueFunction->GetApproximateVolumeConstraintWeight();
+  }
+
+
+  void  SetBiExponentialOutside(const int p)  {    m_TissueFunction->SetBiExponentialOutside(p);       }
+  int   GetBiExponentialOutside() const       {    return m_TissueFunction->GetBiExponentialOutside(); }
+
+
+  itkSetMacro(DynamicUpdateParameters,int);
+  itkGetMacro(DynamicUpdateParameters,int);
+  
+protected:
+  ~TissueSegmentationLevelSetImageFilter() {}
+  TissueSegmentationLevelSetImageFilter();
+
+  virtual void PrintSelf(std::ostream &os, Indent indent) const; 
+
+  TissueSegmentationLevelSetImageFilter(const Self &); // purposely not impl.
+  void operator=(const Self&); //purposely not implemented
+
+  /** Overrides parent implementation. Allows for Chen and Vesse like term computation */
+  virtual void InitializeIteration();
+
+
+
+private:
+  TissueFunctionPointer m_TissueFunction;
+  int m_DynamicUpdateParameters;
+};
+
+} // end namespace itk
+
+
+
+#ifndef ITK_MANUAL_INSTANTIATION
+#include "itkpxTissueSegmentationLevelSetImageFilter.txx"
+#endif
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationLevelSetImageFilter.txx b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationLevelSetImageFilter.txx
new file mode 100644
index 0000000..119fc60
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/itkpxTissueSegmentationLevelSetImageFilter.txx
@@ -0,0 +1,179 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkpxTissueSegmentationLevelSetImageFilter.txx,v $
+  Language:  C++
+  Date:      $Date: 2003/09/10 14:28:39 $
+  Version:   $Revision: 1.11 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef __itkpxTissueSegmentationLevelSetImageFilter_txx_
+#define __itkpxTissueSegmentationLevelSetImageFilter_txx_
+
+#include "itkpxTissueSegmentationLevelSetImageFilter.h"
+#include <math.h>
+#include "pxisinf.h"
+
+namespace itk {
+
+template <class TInputImage, class TFeatureImage, class TOutputType>
+TissueSegmentationLevelSetImageFilter<TInputImage, TFeatureImage, TOutputType>
+::TissueSegmentationLevelSetImageFilter()
+{
+  m_TissueFunction = TissueFunctionType::New();
+  m_DynamicUpdateParameters=1;
+  this->SetSegmentationFunction(m_TissueFunction);
+}
+ 
+template <class TInputImage, class TFeatureImage, class TOutputType>
+void TissueSegmentationLevelSetImageFilter<TInputImage, TFeatureImage, TOutputType>
+::PrintSelf(std::ostream &os, Indent indent) const
+{
+  Superclass::PrintSelf(os, indent);
+  os << "TissueFunction: " << m_TissueFunction;
+}
+
+
+template <class TInputImage, class TFeatureImage, class TOutputType>
+void TissueSegmentationLevelSetImageFilter<TInputImage, TFeatureImage, TOutputType>
+::InitializeIteration()
+{
+
+  if (this->m_DynamicUpdateParameters==0 && m_TissueFunction->GetApproximateVolumeConstraintWeight()<0.0001)
+    return;
+
+  double epsilon=m_TissueFunction->GetHeavySideEpsilon();
+
+  typename Superclass::LayerType::ConstIterator layerIt;
+  const typename Superclass::FiniteDifferenceFunctionType::Pointer df  = this->GetDifferenceFunction();
+  NeighborhoodIterator<OutputImageType> outputIt(df->GetRadius(), this->GetOutput(), this->GetOutput()->GetRequestedRegion());
+  NeighborhoodIterator<FeatureImageType> featureIt(df->GetRadius(), this->GetFeatureImage(), this->GetFeatureImage()->GetRequestedRegion());
+
+
+  double volume=0.0;
+  
+  double sum[2],sum2[2],counter[2];
+  for (int i=0;i<=1;i++)
+    {
+      counter[i]=0.0;
+      sum[i]=0.0;
+      sum2[i]=0.0;
+    }
+  
+  for ( unsigned int k = 0; k < this->GetNumberOfLayers(); k++ )
+    {
+      for (layerIt = this->m_Layers[k]->Begin(); layerIt != this->m_Layers[k]->End(); ++layerIt)
+	{
+	  featureIt.SetLocation(layerIt->m_Value);
+	  outputIt.SetLocation(layerIt->m_Value);
+	  ValueType phi=outputIt.GetCenterPixel();
+
+	  if (phi<0.0)
+	    volume+=1.0;
+	  
+	  ValueType v=featureIt.GetCenterPixel();
+
+
+	  for (int region=0;region<=1;region++)
+	    {
+	      double m=(1.0+0.63662*atan(phi/epsilon));
+	      if (region==1)
+		m=2.0-m;
+	      //	      std::cerr << "Layer = " << k << ", region = " << region << ", m=" << m << " (" << phi << ") location=" << layerIt->m_Value[0] << " " << layerIt->m_Value[1] << ", value = " << v << "\n";
+
+	      
+	      sum[region]+=v*m;
+	      sum2[region]+=v*v*m;
+	      counter[region]+=m;
+	    }
+	}
+    }
+
+  if (this->m_DynamicUpdateParameters>0)
+    {
+      double mean[2],sigma[2];
+      std::cerr << "Chan Vese Update:: Region Properties ( " << epsilon << "\t";
+      for (int ia=0;ia<=1;ia++)
+	{
+	  if (counter[ia]>0)
+	    mean[ia]=sum[ia]/(counter[ia]);
+	  else
+	    mean[ia]=0.0;
+	  
+	  if (counter[ia]>1)
+	    sigma[ia]=sqrt(sum2[ia]/(counter[ia])-mean[ia]*mean[ia]);
+	  else
+	    sigma[ia]=1.0;
+	  
+	  
+	  if (isnan(sigma[ia]))	sigma[ia]=1.0;
+	  if (isnan(mean[ia]))	mean[ia]=0.0;
+	  
+	  
+	  std::cerr << 
+	    "ia=" << ia << 
+	    " mean=" << mean[ia] << 
+	    " + " << sigma[ia] << "( " << 
+	    sum[ia] << "," << 
+	    sum2[ia] << "," << 
+	    counter[ia] << ")\t";
+	}
+      this->SetInsideTissue(mean[1],sigma[1]);
+      this->SetOutsideTissue(mean[0],sigma[0]);
+    }
+
+  //  if(m_TissueFunction->GetApproximateVolumeConstraintWeight()>0.0) 
+  //    {
+  std::cerr << "Volume = " << volume << "\n";
+  m_TissueFunction->SetMyVolume(volume);
+      //    }
+
+  std::cerr << "\n";
+}
+
+
+}// end namespace itk
+
+
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkITKMyUtility.h b/bioimagesuite30_src/Segmentation/vtkITKMyUtility.h
new file mode 100644
index 0000000..212055d
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkITKMyUtility.h
@@ -0,0 +1,54 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef __vtkITKMyUtility_h
+#define __vtkITKMyUtility_h
+
+#include <vtkObject.h>
+
+class vtkImageData;
+
+
+class vtkITKMyUtility : public vtkObject
+{
+public:
+  static vtkITKMyUtility *New();
+  vtkTypeMacro(vtkITKMyUtility,vtkObject);
+  
+
+  static vtkImageData* CurvatureAnisotropicDiffusionFilter(vtkImageData* input,double Conductance=1.0,double TimeStep=0.15,int NumberOfIterations=8);
+  static vtkImageData* LoadImage(char* fname);
+  static int           SaveImage(vtkImageData* input,char* filename);
+
+protected:
+  vtkITKMyUtility() {};
+  virtual ~vtkITKMyUtility() {};
+
+
+};
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkITKUtility.h b/bioimagesuite30_src/Segmentation/vtkITKUtility.h
new file mode 100644
index 0000000..f777b50
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkITKUtility.h
@@ -0,0 +1,137 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkITKUtility_h
+#define __vtkITKUtility_h
+
+
+#include "vtkObjectFactory.h"
+#include "vtkSetGet.h"
+
+/**
+ * This function will connect the given itk::VTKImageExport filter to
+ * the given vtkImageImport filter.
+ */
+template <typename ITK_Exporter, typename VTK_Importer>
+void ConnectPipelines(ITK_Exporter exporter, VTK_Importer* importer)
+{
+  importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
+  importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
+  importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
+  importer->SetSpacingCallback(exporter->GetSpacingCallback());
+  importer->SetOriginCallback(exporter->GetOriginCallback());
+  importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
+  importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
+  importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
+  importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
+  importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
+  importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
+  importer->SetCallbackUserData(exporter->GetCallbackUserData());
+}
+
+/**
+ * This function will connect the given vtkImageExport filter to
+ * the given itk::VTKImageImport filter.
+ */
+template <typename VTK_Exporter, typename ITK_Importer>
+void ConnectPipelines(VTK_Exporter* exporter, ITK_Importer importer)
+{
+  importer->SetUpdateInformationCallback(exporter->GetUpdateInformationCallback());
+  importer->SetPipelineModifiedCallback(exporter->GetPipelineModifiedCallback());
+  importer->SetWholeExtentCallback(exporter->GetWholeExtentCallback());
+  importer->SetSpacingCallback(exporter->GetSpacingCallback());
+  importer->SetOriginCallback(exporter->GetOriginCallback());
+  importer->SetScalarTypeCallback(exporter->GetScalarTypeCallback());
+  importer->SetNumberOfComponentsCallback(exporter->GetNumberOfComponentsCallback());
+  importer->SetPropagateUpdateExtentCallback(exporter->GetPropagateUpdateExtentCallback());
+  importer->SetUpdateDataCallback(exporter->GetUpdateDataCallback());
+  importer->SetDataExtentCallback(exporter->GetDataExtentCallback());
+  importer->SetBufferPointerCallback(exporter->GetBufferPointerCallback());
+  importer->SetCallbackUserData(exporter->GetCallbackUserData());
+}
+
+
+#define DelegateSetMacro(name,arg) DelegateITKInputMacro(Set##name,arg)
+#define DelegateITKInputMacro(name,arg) \
+if ( 1 ) { \
+  vtkDebugMacro( << this->GetClassName() << " (" << this << "): setting " #name " to " << #arg ); \
+  ImageFilterType* tempFilter = dynamic_cast<ImageFilterType*> ( this->m_Filter.GetPointer() ); \
+  if ( tempFilter ) \
+    { \
+    tempFilter->name ( arg ); \
+    this->Modified(); \
+    } \
+  }
+
+#define DelegateGetMacro(name) DelegateITKOutputMacro (Get##name)
+#define DelegateITKOutputMacro(name) \
+if ( 1 ) { \
+  vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " #name ); \
+  ImageFilterType* tempFilter = dynamic_cast<ImageFilterType*> ( this->m_Filter.GetPointer() ); \
+  if ( tempFilter ) \
+    { \
+    return tempFilter->name (); \
+    } \
+    else \
+    { \
+    vtkErrorMacro ( << this->GetClassName() << " Error getting " #name " Dynamic cast returned 0" ); \
+    return 0; \
+    } \
+  }
+
+
+// struct vtkITKProgressDisplay
+// {
+//   ProgressDisplay(vtkObject* obj, itk::ProcessObject* process): m_Process(process), m_Object(obj) {}
+  
+//   void Display()
+//   {
+//     m_Object->SetProgress ( m_Process->GetProgress() );
+//     }
+  
+//   itk::ProcessObject::Pointer m_Process;
+//   vtkObject* m_Object();
+// };
+
+//   // Add a progress observer for the itk::CurvatureFlowImageFilter.
+//   // This will make it clear when this part of the ITK pipeline
+//   // executes.
+//   ProgressDisplay progressDisplay(denoiser);
+//   itk::SimpleMemberCommand<ProgressDisplay>::Pointer progressEvent =
+//     itk::SimpleMemberCommand<ProgressDisplay>::New();
+//   progressEvent->SetCallbackFunction(&progressDisplay,
+//                                      &ProgressDisplay::Display);
+//   denoiser->AddObserver(itk::ProgressEvent(), progressEvent);
+
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkbisBinaryThinningFilter.cpp b/bioimagesuite30_src/Segmentation/vtkbisBinaryThinningFilter.cpp
new file mode 100644
index 0000000..ce078ef
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkbisBinaryThinningFilter.cpp
@@ -0,0 +1,168 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkbisBinaryThinningFilter.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkImageData.h"
+#include "vtkImageImport.h"
+#include "vtkImageExport.h"
+#include "vtkbisBinaryThinningFilter.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkInformation.h"
+#include "itkImage.h"
+#include "itkVTKImageExport.h"
+#include "itkVTKImageImport.h"
+#include "vtkITKUtility.h"
+#include "itkBinaryThinningImageFilter3D.h"
+#include "vtkImageThreshold.h"
+
+//------------------------------------------------------------------------------
+// First a Helper Class
+// -----------------------------------------------------------------------------
+vtkbisBinaryThinningFilter* vtkbisBinaryThinningFilter::New()
+{
+  return new vtkbisBinaryThinningFilter;
+}
+
+
+
+vtkbisBinaryThinningFilter::vtkbisBinaryThinningFilter()
+{
+
+}
+// ----------------------------------------------------------------------------
+vtkbisBinaryThinningFilter::~vtkbisBinaryThinningFilter()
+{
+}
+// ---------------------------------------------------------------------------------------------
+void vtkbisBinaryThinningFilter::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkbisBinaryThinningFilter");
+      return;
+    }
+
+  typedef short  PixelType;
+  typedef itk::Image<PixelType,3>    ImageType;
+  typedef itk::VTKImageImport<ImageType> ImportType;
+  typedef itk::VTKImageExport<ImageType> ExportType;
+  
+  typedef itk::BinaryThinningImageFilter3D< ImageType, ImageType > ThinningFilterType;
+
+
+  // Step 1: Take VTK Image and make it float
+  vtkImageThreshold* thresholder=vtkImageThreshold::New();
+  thresholder->SetInput(input);
+  thresholder->SetOutputScalarTypeToShort();
+  thresholder->SetOutValue(0);
+  thresholder->SetInValue(100);
+  thresholder->ThresholdByUpper(1.0);
+  thresholder->SetOutputScalarTypeToShort();
+  thresholder->ReplaceInOn();
+  thresholder->ReplaceOutOn();
+
+  // Step 2: Convert VTK Image to ITK
+  vtkImageExport *vtkInputExporter = vtkImageExport::New();
+  vtkInputExporter->SetInput(thresholder->GetOutput());
+  
+  ImportType::Pointer itkInputImporter =  ImportType::New();
+  ConnectPipelines(vtkInputExporter, itkInputImporter);
+  itkInputImporter->Update();
+  
+  ThinningFilterType::Pointer thinningFilter = ThinningFilterType::New();
+  thinningFilter->SetInput(  itkInputImporter->GetOutput() );
+  thinningFilter->Update();
+
+
+  // Step 4:
+  // Push it out to VTK
+  ExportType::Pointer itkExporter = ExportType::New();
+  itkExporter->SetInput(thinningFilter->GetOutput());
+  itkExporter->Update();
+
+  vtkImageImport* vtkImporter=vtkImageImport::New();
+  ConnectPipelines(itkExporter, vtkImporter);
+  vtkImporter->Update();
+
+  output->DeepCopy(vtkImporter->GetOutput());
+  
+  vtkImporter->Delete();
+  thresholder->Delete();
+  vtkInputExporter->Delete();
+  
+  
+}
+
+
+// Tell the pipeline that the output has same dimensions as input but force SHORT one component
+// --------------------------------------------------------------------------------------------
+int vtkbisBinaryThinningFilter::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+								     vtkInformationVector *outputVector)
+{
+  vtkInformation *inInfo =  inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  int wholeExtent[6]; inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
+  double sp[3];  inInfo->Get(vtkDataObject::SPACING(), sp);
+  double origin[3];  inInfo->Get(vtkDataObject::ORIGIN(),  origin);
+
+  outInfo->Set(vtkDataObject::ORIGIN(),  origin, 3);
+  outInfo->Set(vtkDataObject::SPACING(),sp , 3);
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6);
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), VTK_SHORT, 1);
+
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Segmentation/vtkbisBinaryThinningFilter.h b/bioimagesuite30_src/Segmentation/vtkbisBinaryThinningFilter.h
new file mode 100644
index 0000000..36679fc
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkbisBinaryThinningFilter.h
@@ -0,0 +1,92 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkbisBinaryThinningFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkbisBinaryThinningFilter -- corrects for B0 inhomogeneity in 1-H CSI Data for fat quantification
+
+#ifndef __vtkbisBinaryThinningFilter_h
+#define __vtkbisBinaryThinningFilter_h
+
+#include "vtkSimpleImageToImageFilter.h"
+
+
+class vtkbisBinaryThinningFilter : public vtkSimpleImageToImageFilter
+{
+public:
+  static vtkbisBinaryThinningFilter *New();
+  vtkTypeMacro(vtkbisBinaryThinningFilter,vtkSimpleImageToImageFilter);
+
+
+protected:
+
+  vtkbisBinaryThinningFilter();
+  virtual ~vtkbisBinaryThinningFilter();
+  vtkbisBinaryThinningFilter(const vtkbisBinaryThinningFilter&) {};
+  void operator=(const vtkbisBinaryThinningFilter&) {};
+
+  // Description:
+  // Specify Output Stuff
+  virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+  // Description
+  // Run algorithm
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+
+
+  
+};
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkjoBETHistogram.cpp b/bioimagesuite30_src/Segmentation/vtkjoBETHistogram.cpp
new file mode 100644
index 0000000..f45eb0f
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkjoBETHistogram.cpp
@@ -0,0 +1,336 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <math.h>
+#include "vtkjoBETHistogram.h"
+#include "vtkDataArray.h"
+#include "vtkDataObject.h"
+#include "vtkFloatArray.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageAccumulate.h"
+#include "vtkImageData.h"
+#include "vtkImageMask.h"
+#include "vtkImageMedian3D.h"
+#include "vtkImageThreshold.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkMath.h"
+#include "vtkPointData.h"
+#include "vtkRenderWindowInteractor.h"
+#include "vtkSmartPointer.h"
+#include "vtkSortDataArray.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+
+
+vtkjoBETHistogram* vtkjoBETHistogram::New()
+{
+	// First try to create the object from the vtkObjectFactory
+	vtkObject* ret = vtkObjectFactory::CreateInstance("vtkjoBETHistogram");
+	if (ret)
+	{
+		return (vtkjoBETHistogram*) ret;
+	}
+	// If the factory was unable to create the object, then create it here.
+	return new vtkjoBETHistogram;
+}
+
+
+void vtkjoBETHistogram::PrintSelf(ostream& os, vtkIndent indent)
+{
+	vtkSimpleImageToImageFilter::PrintSelf(os, indent);
+
+	os << indent << "  MinIntensityPercent " << this->MinIntensityPercent << "\n";
+	os << indent << "  MaxIntensityPercent " << this->MaxIntensityPercent << "\n";
+	os << indent << "  Bins " << this->Bins << "\n";
+	os << indent << "  MinIntensity " << this->MinIntensity << "\n";
+	os << indent << "  MaxIntensity " << this->MaxIntensity << "\n";
+	os << indent << "  Threshold " << this->Threshold << "\n";
+	os << indent << "  COG.x " << this->CenterOfGravity[0] << "\n";
+	os << indent << "  COG.y " << this->CenterOfGravity[1] << "\n";
+	os << indent << "  COG.z " << this->CenterOfGravity[2] << "\n";
+	os << indent << "  Radius " << this->Radius << "\n";
+	os << indent << "  MeanIntensity " << this->MeanIntensity << "\n";
+	os << indent << "  MedianIntensity " << this->MedianIntensity << "\n";
+}
+
+
+vtkjoBETHistogram::vtkjoBETHistogram()
+{
+	this->MinIntensityPercent = 0.02;
+	this->MaxIntensityPercent = 0.98;
+
+	this->Bins = 1000;
+
+	this->MinIntensity = 0.0;
+	this->MaxIntensity = 0.0;
+	this->Threshold = 0.0;
+
+	// TODO: Is this the proper initialization?
+	this->CenterOfGravity[0] = 0.0;
+	this->CenterOfGravity[1] = 0.0;
+	this->CenterOfGravity[2] = 0.0;
+
+	this->Radius = 0.0;
+	this->MeanIntensity = 0.0;
+	this->MedianIntensity = 0.0;
+}
+
+
+vtkjoBETHistogram::~vtkjoBETHistogram()
+{
+}
+
+
+void vtkjoBETHistogram::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+	vtkDebugMacro(<<"Entering SimpleExecute");
+
+	if (input == NULL)
+	{
+		vtkErrorMacro(<<"Input is NULL");
+		return;
+	}
+
+	// Get the input image's range in order to determine spacing of the
+	// histogram
+	double range[2];
+	input->GetPointData()->GetScalars()->GetRange(range);
+
+	double spacing = (range[1] - range[0])/float(this->Bins-1);
+
+	// Create the histogram
+	vtkSmartPointer<vtkImageAccumulate> accumulator =
+		vtkSmartPointer<vtkImageAccumulate>::New();
+	accumulator->SetInput(input);
+	accumulator->SetComponentExtent(0, this->Bins-1, 0, 0, 0, 0);
+	accumulator->SetComponentOrigin(range[0], 0, 0);
+	accumulator->SetComponentSpacing(spacing, 1, 1);
+	accumulator->Update();
+
+	vtkDataArray* data = accumulator->GetOutput()->GetPointData()->GetScalars();
+	vtkSmartPointer<vtkFloatArray> cum =
+		vtkSmartPointer<vtkFloatArray>::New();
+	cum->SetNumberOfTuples(this->Bins);
+
+	// Compute the cumulative distribution of the histogram
+	cum->SetComponent(0, 0, data->GetComponent(0,0));
+	for (int i=1; i<this->Bins; i++)
+		cum->SetComponent(i, 0, data->GetComponent(i,0) + cum->GetComponent(i-1,0));
+
+	// Get the total number of voxels
+	double total = cum->GetComponent(this->Bins-1, 0);
+
+	// Compute the "robust" thresholds
+	bool foundMinThresh = false;
+	bool foundMaxThresh = false;
+	double value = 0.0;
+
+	for (int i=0; i<this->Bins; i++)
+	{
+		value = cum->GetComponent(i, 0);
+		if (!foundMinThresh && value/total > this->MinIntensityPercent)
+		{
+			foundMinThresh = true;
+			this->MinIntensity = range[0] + i*spacing;
+		}
+
+		if (!foundMaxThresh && value/total > this->MaxIntensityPercent)
+		{
+			foundMaxThresh = true;
+			this->MaxIntensity = range[0] + i*spacing;
+		}
+	}
+	vtkDebugMacro(<<"MinIntensity="<<this->MinIntensity<<" MaxIntensity="<<this->MaxIntensity);
+
+	// Find threshold 10% of the way between the min and max thresholds
+//    this->Threshold = (this->MaxIntensity - this->MinIntensity)*0.10;
+    this->Threshold = (this->MaxIntensity - this->MinIntensity)*0.10 + this->MinIntensity;
+	vtkDebugMacro(<<"Threshold="<<this->Threshold);
+
+	// Compute the CoG and the mean radius
+	ComputeCoGandRadius(input, output);
+}
+
+
+// TODO: remove the output image from here...
+/**
+ * Computes the COG, the "mean" radius and the median intensity.  Voxels with
+ * intensity greater than Theshold and less than MaxIntensity are used to compute
+ * the COG.  All voxels with intensity greater than Threshold are used to find
+ * the radius.  The median intensity is found for all points within a sphere
+ * of the radius centered on the COG.
+ */
+void vtkjoBETHistogram::ComputeCoGandRadius(vtkImageData* image, vtkImageData* output)
+{
+	vtkDebugMacro(<<"Computing the CoG and Radius...");
+
+	int dim[3];
+	image->GetDimensions(dim);
+	double spacing[3];
+	image->GetSpacing(spacing);
+
+	int slicesize = dim[0]*dim[1];
+
+	vtkDataArray* data = image->GetPointData()->GetScalars();
+
+	double range[2];
+	data->GetRange(range);
+
+	int countIn = 0;
+	double totalMass = 0.0;
+
+	double value = 0.0;
+	double tempThresh = this->Threshold - this->MinIntensity;
+	for (int z=0; z<dim[2]; z++)
+		for (int y=0; y<dim[1]; y++)
+			for (int x=0; x<dim[0]; x++)
+			{
+			    // TODO: BET uses the MinIntensity as a zero basis, so
+			    // we added tempThresh here
+//                value = data->GetComponent(x+y*dim[0]+z*slicesize, 0);
+                value = data->GetComponent(x+y*dim[0]+z*slicesize, 0) - this->MinIntensity;
+
+//                if (value > this->Threshold)
+                if (value > tempThresh)
+				{
+					countIn++;
+					// NOTE: BET does not use this upper limit even though
+					// it is reported in the literature
+					// TODO: probably add this back into our alg.
+//					if (value <= this->MaxIntensity)
+					{
+						this->CenterOfGravity[0] += x*value;
+						this->CenterOfGravity[1] += y*value;
+						this->CenterOfGravity[2] += z*value;
+						totalMass += value;
+					}
+				}
+			}
+
+	// Check to make sure the total mass is > 0 in order to avoid dividing by zero
+	if (totalMass > 0.0)
+	{
+		this->CenterOfGravity[0] /= totalMass;
+		this->CenterOfGravity[1] /= totalMass;
+		this->CenterOfGravity[2] /= totalMass;
+	}
+	else
+	{
+		this->CenterOfGravity[0] = 0;
+		this->CenterOfGravity[1] = 0;
+		this->CenterOfGravity[2] = 0;
+	}
+
+	// use V=4/3*pi*r^3 to find the mean radius
+	const double PI = vtkMath::DoublePi();
+	// TODO: incorporate spacing information into the final calc?
+	this->Radius = pow((0.75*double(countIn))/PI, 1.0/3.0);
+
+	vtkDebugMacro(<<"COG.x="<<this->CenterOfGravity[0]<<" COG.y="<<this->CenterOfGravity[1]<<" COG.z="<<this->CenterOfGravity[2]);
+	vtkDebugMacro(<<"Mean Radius="<<this->Radius);
+
+	// Finally compute the median intensity within the mean radius
+	// from the COG
+
+	// TODO: remove me
+	vtkDataArray* outData = output->GetPointData()->GetScalars();
+
+	// Note, rather than using r > ((x-x0)^2+(y-y0)^2+...)^0.5
+	// Use: r^2 > (x-x0)^2 + (y-y0)^2 in order to save on calculating the
+	// square root every time
+	double radiusThresh = this->Radius*this->Radius;
+	double dist = 0.0;
+	int spherePoints = 0;
+	double sphereIntensity = 0.0;
+
+	vtkDataArray* intensityArray = vtkDataArray::CreateDataArray(data->GetDataType());
+
+	for (int z=0; z<dim[2]; z++)
+		for (int y=0; y<dim[1]; y++)
+			for (int x=0; x<dim[0]; x++)
+			{
+				dist = (x - this->CenterOfGravity[0])*(x - this->CenterOfGravity[0]) +
+					   (y - this->CenterOfGravity[1])*(y - this->CenterOfGravity[1]) +
+					   (z - this->CenterOfGravity[2])*(z - this->CenterOfGravity[2]);
+				if (dist < radiusThresh)
+				{
+					value = data->GetComponent(x+y*dim[0]+z*slicesize, 0);
+
+					// BET also performs a check for the intensity to be between
+					// the min and max intensity thresholds.  NOTE, this is note
+					// reported in the literature.
+					if (value > this->MinIntensity && value < this->MaxIntensity)
+					{
+	                    intensityArray->InsertNextTuple1(value);
+	                    sphereIntensity += value;
+	                    spherePoints++;
+					}
+					outData->SetComponent(x+y*dim[0]+z*slicesize, 0, 1.0);
+				}
+				else
+				{
+					outData->SetComponent(x+y*dim[0]+z*slicesize, 0, 0.0);
+				}
+			}
+
+	this->MeanIntensity = sphereIntensity/double(spherePoints);
+	vtkDebugMacro(<<"MeanIntensity="<<this->MeanIntensity);
+
+	vtkSortDataArray::Sort(intensityArray);
+
+	// If we have an odd number of points take the middle tuple, else take the
+	// average of the two middle tuples.
+	int numElements = intensityArray->GetNumberOfTuples();
+	if (numElements%2 != 0)
+	{
+		this->MedianIntensity = intensityArray->GetTuple1((numElements-1)/2);
+	}
+	else
+	{
+		int medianIndex = (numElements-1)/2;
+		this->MedianIntensity = (intensityArray->GetTuple1(medianIndex-1) +
+				intensityArray->GetTuple1(medianIndex))/2.0;
+	}
+	vtkDebugMacro(<<"MedianIntensity="<<this->MedianIntensity);
+
+
+	double sum=0.0;
+	for (int i=0;i<=2;i++)
+	  {
+	    this->CenterOfGravity[i]*=spacing[i];
+	    sum+=spacing[i];
+	  }
+	sum=sum/3.0;
+	this->Radius*=sum;
+	vtkDebugMacro(<<"COG.x="<<this->CenterOfGravity[0]<<" COG.y="<<this->CenterOfGravity[1]<<" COG.z="<<this->CenterOfGravity[2]);
+	vtkDebugMacro(<<"Mean Radius="<<this->Radius);
+
+}
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkjoBETHistogram.h b/bioimagesuite30_src/Segmentation/vtkjoBETHistogram.h
new file mode 100644
index 0000000..02b57e6
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkjoBETHistogram.h
@@ -0,0 +1,126 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef __vtkjoBETHistogram_h
+#define __vtkjoBETHistogram_h
+
+#include "vtkSimpleImageToImageFilter.h"
+
+
+class vtkjoBETHistogram : public vtkSimpleImageToImageFilter
+{
+public:
+	static vtkjoBETHistogram *New();
+	vtkTypeMacro(vtkjoBETHistogram, vtkSimpleImageToImageFilter);
+
+	void PrintSelf(ostream& os, vtkIndent indent);
+
+	// Description:
+	// MinIntensityPercent - the lower percentage of the cumulative histogram
+	// used to determine MinIntensity.  We limit the minimum intensity
+	// percentage to be between 0.0 and 1.0.  The default is 0.02.
+	vtkSetClampMacro(MinIntensityPercent, double, 0.0, 1.0);
+	vtkGetMacro(MinIntensityPercent, double);
+
+	// Description:
+	// MaxIntensityPercent - the upper percentage of the cumulative histogram
+	// used to determine MaxIntensity.  We limit the maximum intensity
+	// percentage to be between 0.0 and 1.0.  The default is 0.98.
+	vtkSetClampMacro(MaxIntensityPercent, double, 0.0, 1.0);
+	vtkGetMacro(MaxIntensityPercent, double);
+
+	// Description:
+	// MinIntensity - the robust minimum intensity below which lies
+	// MinIntensityPercent percent of the cumulative histogram.
+	vtkGetMacro(MinIntensity, double);
+	// Description:
+	// MaxIntensity - the robust maximum intensity above which lies
+	// MaxIntensityPercent percent of the cumulative histogram.
+	vtkGetMacro(MaxIntensity, double);
+	// Description:
+	// Threshold - set to be 10% of the way between MinIntensity
+	// and MaxIntensity.
+	vtkGetMacro(Threshold, double);
+
+	// Description:
+	// Bins - the number of histogram bins.  We limit the number of bins to be
+	// between 1 and 512.
+	vtkSetClampMacro(Bins, int, 1, 1024);
+	vtkGetMacro(Bins, int);
+
+	// Description:
+	// Center Of Gravity - the center of gravity (COG) of the brain/head in the
+	// image.  Only voxels with intensity greater than Threshold and less than
+	// MaxIntensity are used to compute this.
+	vtkGetVectorMacro(CenterOfGravity, double, 3);
+
+	// Description:
+	// Radius - the estimated "mean' radius of the brain/head volume.  All voxels
+	// with intensity greater than Threshold are counted.
+	vtkGetMacro(Radius, double);
+
+	// Description:
+	// MeanIntensity - the mean intensity within a sphere of the estimated
+	// radius and centered on the COG.
+	vtkGetMacro(MeanIntensity, double);
+	// Description:
+	// MedianIntensity - the median intensity within a sphere of the estimated
+	// radius and centered on the COG.
+	vtkGetMacro(MedianIntensity, double);
+
+protected:
+
+	double MinIntensityPercent;
+	double MaxIntensityPercent;
+
+	double Threshold;
+	double MinIntensity;
+	double MaxIntensity;
+
+	int Bins;
+
+	double Radius;
+	double CenterOfGravity[3];
+	double MeanIntensity;
+	double MedianIntensity;
+
+	vtkjoBETHistogram();
+	virtual ~vtkjoBETHistogram();
+
+	virtual void SimpleExecute(vtkImageData* input, vtkImageData *output);
+
+//	virtual int RequestInformation(vtkInformation *vtkNotUsed(request),
+//			vtkInformationVector **inputVector,
+//			vtkInformationVector *outputVector);
+
+//	void ComputeCenterOfGravity(vtkImageData* input);
+	void ComputeCoGandRadius(vtkImageData* image, vtkImageData* output);
+};
+
+#endif
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkjoBETImageFilter.cpp b/bioimagesuite30_src/Segmentation/vtkjoBETImageFilter.cpp
new file mode 100644
index 0000000..36a647d
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkjoBETImageFilter.cpp
@@ -0,0 +1,773 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkjoBETImageFilter.cpp
+ *
+ *  Created on: Sep 12, 2008
+ *      Author: jonofrey
+ */
+
+#include "vtkCellArray.h"
+#include "vtkDoubleArray.h"
+#include "vtkIdList.h"
+#include "vtkImageReslice.h"
+#include "vtkImageThreshold.h"
+#include "vtkjoBETImageFilter.h"
+#include "vtkjoSphereSource.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyDataToImageStencil.h"
+
+//-------------------------------------------------------------------------------
+
+vtkjoBETImageFilter* vtkjoBETImageFilter::New()
+{
+    // First try to create the object from the vtkObjectFactory
+    vtkObject* ret = vtkObjectFactory::CreateInstance("vtkjoBETImageFilter");
+    if (ret)
+    {
+        return (vtkjoBETImageFilter*) ret;
+    }
+    // If the factory was unable to create the object, then create it here.
+    return new vtkjoBETImageFilter;
+}
+
+//-------------------------------------------------------------------------------
+
+vtkjoBETImageFilter::vtkjoBETImageFilter()
+{
+    this->BETHistogram = vtkjoBETHistogram::New();
+
+    // Get initial values from the vtkjoBETHistogram instance
+    this->MinIntensityPercent = this->BETHistogram->GetMinIntensityPercent();
+    this->MaxIntensityPercent = this->BETHistogram->GetMaxIntensityPercent();
+    this->Bins = this->BETHistogram->GetBins();
+    this->MinIntensityThresh = this->BETHistogram->GetMinIntensity();
+    this->MaxIntensityThresh = this->BETHistogram->GetMaxIntensity();
+    this->Threshold = this->BETHistogram->GetThreshold();
+    this->BETHistogram->GetCenterOfGravity(this->CenterOfGravity);
+    this->Radius = this->BETHistogram->GetRadius();
+    this->MedianIntensity = this->BETHistogram->GetMedianIntensity();
+
+    this->ManualRadiusAndCOGOff();
+
+    this->RadiusScaleFactor = 0.5;
+    this->SurfaceResolution = 4;
+    this->MaxIterations = 1000;
+    this->MaxPasses = 10;
+    this->MinChangeTolerance = 0.01;
+    this->MinIntensitySearchDist = 7.0;
+    this->MaxIntensitySearchDist = this->MinIntensitySearchDist*0.5;
+    this->LocalThresholdConst = 0.5;
+    this->RMin = 3.33333;
+    this->RMax = 10.0;
+    this->IncreasedSmoothing = 0;
+    this->SelfIntersectionThreshold = 4000;
+
+    this->Surface = NULL;
+    this->SurfaceInput = NULL;
+    this->EdgeTable = NULL;
+}
+
+//-------------------------------------------------------------------------------
+
+vtkjoBETImageFilter::~vtkjoBETImageFilter()
+{
+    if (this->BETHistogram != NULL)
+        this->BETHistogram->Delete();
+}
+
+//-------------------------------------------------------------------------------
+
+void vtkjoBETImageFilter::PrintSelf(ostream& os, vtkIndent indent)
+{
+    vtkSimpleImageToImageFilter::PrintSelf(os, indent);
+
+    os << indent << "  MinIntensityPercent " << this->MinIntensityPercent << "\n";
+    os << indent << "  MaxIntensityPercent " << this->MaxIntensityPercent << "\n";
+    os << indent << "  Bins " << this->Bins << "\n";
+    os << indent << "  MinIntensityThresh " << this->MinIntensityThresh << "\n";
+    os << indent << "  MaxIntensityThresh " << this->MaxIntensityThresh << "\n";
+    os << indent << "  Threshold " << this->Threshold << "\n";
+    os << indent << "  COG.x " << this->CenterOfGravity[0] << "\n";
+    os << indent << "  COG.y " << this->CenterOfGravity[1] << "\n";
+    os << indent << "  COG.z " << this->CenterOfGravity[2] << "\n";
+    os << indent << "  Radius " << this->Radius << "\n";
+    os << indent << "  MedianIntensity " << this->MedianIntensity << "\n";
+    os << indent << "  ManualRadiusAndCOG  " << this->ManualRadiusAndCOG << "\n";
+
+    os << indent << "  RadiusScaleFactor " << this->RadiusScaleFactor << "\n";
+    os << indent << "  SurfaceResolution " << this->SurfaceResolution << "\n";
+    os << indent << "  MaxIterations " << this->MaxIterations << "\n";
+    os << indent << "  MaxPasses " << this->MaxPasses << "\n";
+    os << indent << "  MinChangeTolerance " << this->MinChangeTolerance << "\n";
+    os << indent << "  MinIntensitySearchDist " << this->MinIntensitySearchDist << "\n";
+    os << indent << "  MaxIntensitySearchDist " << this->MaxIntensitySearchDist << "\n";
+    os << indent << "  LocalThresholdConst " << this->LocalThresholdConst << "\n";
+    os << indent << "  RMin " << this->RMin<< "\n";
+    os << indent << "  RMax " << this->RMax << "\n";
+    os << indent << "  IncreasedSmoothing " << this->IncreasedSmoothing << "\n";
+    os << indent << "  SelfIntersectionThreshold " << this->SelfIntersectionThreshold << "\n";
+
+}
+
+//-------------------------------------------------------------------------------
+
+vtkImageData* vtkjoBETImageFilter::GetOutputMask()
+{
+    vtkDebugMacro(<<"Creating binary mask...");
+
+    vtkImageData* input = this->GetImageDataInput(0);
+
+    if (this->Surface == NULL || input == NULL)
+        vtkErrorMacro(<<"Either surface points or source image (or both) is NULL.");
+
+    vtkImageData* output = vtkImageData::New();
+
+    vtkPolyDataToImageStencil* stencil = vtkPolyDataToImageStencil::New();
+    stencil->SetInput(this->Surface);
+    stencil->SetInformationInput(input);
+    stencil->Update();
+
+    vtkImageReslice* reslice = vtkImageReslice::New();
+    reslice->SetInput(input);
+    reslice->SetStencil(stencil->GetOutput());
+    reslice->SetBackgroundColor(0.0, 0.0, 0.0, 1.0);
+
+    vtkImageThreshold* threshold = vtkImageThreshold::New();
+    threshold->SetInputConnection(reslice->GetOutputPort());
+    threshold->SetOutputScalarTypeToShort();
+    threshold->ThresholdByLower(0.0);
+    threshold->SetInValue(0.0);
+    threshold->SetOutValue(1.0);
+    threshold->Update();
+
+    output->ShallowCopy(threshold->GetOutput());
+
+    stencil->Delete();
+    reslice->Delete();
+    threshold->Delete();
+
+    return output;
+}
+
+//-------------------------------------------------------------------------------
+
+vtkPolyData* vtkjoBETImageFilter::CreateInitialSurface()
+{
+    vtkDebugMacro(<<"Creating initial surface as a sphere...");
+
+    vtkPolyData* surface = vtkPolyData::New();
+
+    // Create the initial sphere source based on the radius and COG
+    vtkjoSphereSource* sphereSrc = vtkjoSphereSource::New();
+    sphereSrc->SetRadius(this->Radius*this->RadiusScaleFactor);
+    sphereSrc->SetCenter(this->CenterOfGravity[0],
+            this->CenterOfGravity[1],
+            this->CenterOfGravity[2]);
+    sphereSrc->IcosahedralTessellationOn();
+    sphereSrc->SetSubdivisionLevels(this->SurfaceResolution);
+    sphereSrc->Update();
+    surface->ShallowCopy(sphereSrc->GetOutput());
+    sphereSrc->Delete();
+
+    vtkDebugMacro(<<"Finished creating sphere.");
+
+    return surface;
+}
+
+//-------------------------------------------------------------------------------
+
+void vtkjoBETImageFilter::FindNeighbors()
+{
+    // Get the neighbors for each vertex
+    vtkDebugMacro(<<"Computing neighbor list...");
+
+    if (this->Surface == NULL) {
+        vtkErrorMacro(<<"Surface is NULL!");
+        return;
+    }
+
+    int numPoints = this->Surface->GetNumberOfPoints();
+    this->NeighborList = new vtkIdList*[numPoints];
+    for (int i=0; i<numPoints; i++) {
+        this->NeighborList[i] = vtkIdList::New();
+    }
+
+    int numCells = this->Surface->GetNumberOfCells();
+    vtkCellArray* polys = this->Surface->GetPolys();
+    polys->InitTraversal();
+
+    vtkIdType nPts;
+    // Each point can have either 5 or 6 neighbors
+    vtkIdType  pts0[6];
+    vtkIdType* pts = &pts[0];
+
+    vtkIdType p1 = 0;
+    vtkIdType p2 = 0;
+
+    for (int i=0; i<numCells; i++) {
+        polys->GetNextCell(nPts, pts);
+        // Fill the unique neighbor list
+        for (int j=0; j<nPts-1; j++) {
+            p1 = pts[j];
+            for (int k=j+1; k<nPts; k++) {
+                p2 = pts[k];
+                this->NeighborList[p1]->InsertUniqueId(p2);
+                this->NeighborList[p2]->InsertUniqueId(p1);
+            }
+        }
+    }
+
+    vtkDebugMacro(<<"Finished computing neighbor list.");
+}
+
+//-------------------------------------------------------------------------------
+
+vtkIdType vtkjoBETImageFilter::CreateEdgeTable()
+{
+    // Get the neighbors for each vertex
+    vtkDebugMacro(<<"Creating edge table...");
+
+    if (this->Surface == NULL) {
+        vtkErrorMacro(<<"Cannot create edge table, surface is NULL!");
+        return 0;
+    }
+
+    if (this->EdgeTable != NULL) {
+        vtkDebugMacro(<<"Edge table is not empty - deleting old table.");
+        this->EdgeTable->Delete();
+    }
+
+    vtkIdType numCells = this->Surface->GetNumberOfCells();
+
+    vtkCellArray* polys = this->Surface->GetPolys();
+    polys->InitTraversal();
+
+    this->EdgeTable = vtkEdgeTable::New();
+    this->EdgeTable->InitEdgeInsertion(this->Surface->GetNumberOfPoints(), 0);
+
+    vtkIdType nPts;
+    // Each point can have either 5 or 6 neighbors
+    vtkIdType  pts0[3];
+    vtkIdType* pts = &pts[0];
+
+    vtkIdType p1 = 0;
+    vtkIdType p2 = 0;
+
+    for (int i=0; i<numCells; i++) {
+        polys->GetNextCell(nPts, pts);
+        for (int idx=0; idx<nPts; idx++) {
+            int next = (idx+1)%nPts;
+            vtkIdType id = this->EdgeTable->IsEdge(pts[idx], pts[next]);
+            // Add the edge to the table if it does not already exist
+            if (id == -1)
+                this->EdgeTable->InsertEdge(pts[idx], pts[next]);
+        }
+    }
+
+    vtkDebugMacro(<<"Finished creating edge table.");
+
+    return this->EdgeTable->GetNumberOfEdges();
+}
+
+//-------------------------------------------------------------------------------
+
+double vtkjoBETImageFilter::ComputeMeanVertexSpacing(vtkPolyData* surface)
+{
+    vtkDebugMacro(<<"Computing mean vertex spacing for the surface.");
+
+    if (surface == NULL || this->EdgeTable == NULL) {
+        vtkErrorMacro(<<"Surface points are NULL");
+        return 0.0;
+    }
+
+    vtkDoubleArray* pointsDA = static_cast<vtkDoubleArray*>(surface->GetPoints()->GetData());
+    double* points = pointsDA->GetPointer(0);
+
+    int numComps = pointsDA->GetNumberOfComponents();
+
+    vtkIdType numEdges = this->EdgeTable->GetNumberOfEdges();
+    this->EdgeTable->InitTraversal();
+
+    double meanSpacing = 0.0;
+
+    vtkIdType p1, p2;
+
+    for (int i=0; i<numEdges; i++) {
+        this->EdgeTable->GetNextEdge(p1, p2);
+        meanSpacing += sqrt(vtkMath::Distance2BetweenPoints(&points[p1*numComps], &points[p2*numComps]));
+    }
+
+    return meanSpacing/numEdges;
+}
+
+//-------------------------------------------------------------------------------
+/*
+double vtkjoBETImageFilter::ComputeMeanVertexSpacing()
+{
+    return this->ComputeMeanVertexSpacing(this->Surface);
+}
+*/
+// -------------------------------------------------------------------------------------------
+
+void vtkjoBETImageFilter::ComputeMeanPosition(
+        const double* points,
+        vtkIdList* neighbors,
+        double mean[3])
+{
+    for (int ia=0; ia<=2; ia++)
+        mean[ia] = 0.0;
+
+    int numNeighbors = neighbors->GetNumberOfIds();
+    double scale = 1.0/(double(numNeighbors));
+
+    int offset=0;
+    for (int j=0; j<numNeighbors; j++)
+    {
+        offset = neighbors->GetId(j)*3;
+        for (int idx=0; idx<=2; idx++)
+            mean[idx] += points[offset+idx];
+    }
+
+    for (int idx=0; idx<=2; idx++)
+        mean[idx] = mean[idx]*scale;
+}
+
+// -------------------------------------------------------------------------------------------
+/*
+void vtkjoBETImageFilter::ComputeMeanPositionOfNeighbors(vtkIdType id, double mean[3])
+{
+    for (int i=0; i<3; i++)
+        mean[i] = 0.0;
+
+    vtkIdList* neighbors = this->NeighborList[id];
+    int n = neighbors->GetNumberOfIds();
+    double scale = 1.0/(double(n));
+
+    vtkDoubleArray* points = static_cast<vtkDoubleArray*>(
+            this->Surface->GetPoints()->GetData());
+
+    vtkIdType nb;
+    for (int j=0; j<n; j++)
+    {
+        nb = neighbors->GetId(j);
+        for (int i=0; i<3; i++)
+            mean[i] += points->GetComponent(nb, i);
+    }
+
+    for (int i=0; i<3; i++)
+        mean[i] = mean[i]*scale;
+}
+*/
+// -------------------------------------------------------------------------------------------
+
+double vtkjoBETImageFilter::ComputeSefIntersection(vtkPolyData* originalSurface)
+{
+    if (this->Surface == NULL || originalSurface == NULL)
+        vtkErrorMacro(<<"Surface points or original points or both are NULL");
+
+    double intersection = 0.0;
+
+    // Get the points
+    vtkPoints* currentPts = this->Surface->GetPoints();
+    vtkPoints* originalPts = originalSurface->GetPoints();
+    if (currentPts->GetNumberOfPoints() != originalPts->GetNumberOfPoints())
+    {
+        vtkErrorMacro(<<"Original surface points do not correspond the those of the current points");
+        return 0.0;
+    }
+
+    // Compute the mean neighbor distance for each vertex
+    double ml= this->ComputeMeanVertexSpacing(this->Surface);
+    double mlo = this->ComputeMeanVertexSpacing(originalSurface);
+    double ml2 = ml*ml;
+
+    vtkIdType nPts = currentPts->GetNumberOfPoints();
+    for (int i=0; i<nPts; i++) {
+        for (int j=0; j<nPts; j++) {
+            if (i != j && this->EdgeTable->IsEdge(i, j) == -1) {
+                double currPt[3], currNPt[3];
+                currentPts->GetPoint(i, currPt);
+                currentPts->GetPoint(j, currNPt);
+
+                if (vtkMath::Distance2BetweenPoints(currPt, currNPt) < ml2) {
+                    double origPt[3], origNPt[3];
+                    originalPts->GetPoint(i, origPt);
+                    originalPts->GetPoint(j, origNPt);
+
+                    double currDist = sqrt(vtkMath::Distance2BetweenPoints(currPt, currNPt))/ml;
+                    double origDist = sqrt(vtkMath::Distance2BetweenPoints(origPt, origNPt))/mlo;
+                    intersection += (currDist - origDist)*(currDist - origDist);
+                }
+            }
+        }
+    }
+
+    return intersection;
+}
+
+// -------------------------------------------------------------------------------------------
+
+void vtkjoBETImageFilter::CreateStrippedImage(
+        vtkPolyData* surface,
+        vtkImageData* input,
+        vtkImageData* output)
+{
+    vtkDebugMacro(<<"Creating extracted image...");
+
+    if (surface == NULL || input == NULL)
+        vtkErrorMacro(<<"Either surface points or source image (or both) is NULL.");
+
+    vtkPolyDataToImageStencil* stencil = vtkPolyDataToImageStencil::New();
+    stencil->SetInput(surface);
+    stencil->SetInformationInput(input);
+    stencil->Update();
+
+    vtkImageReslice* reslice = vtkImageReslice::New();
+    reslice->SetInput(input);
+    reslice->SetStencil(stencil->GetOutput());
+    reslice->SetBackgroundColor(0.0, 0.0, 0.0, 1.0);
+    reslice->Update();
+
+    output->ShallowCopy(reslice->GetOutput());
+
+    stencil->Delete();
+    reslice->Delete();
+}
+
+// -------------------------------------------------------------------------------------------
+
+double vtkjoBETImageFilter::SingleIteration(
+        const int iter,
+        const int pass,
+        vtkImageData* input,
+        const double* spacing,
+        const double* extent,
+        double* points,
+        float* normals,
+        double* updatedPoints,
+        const vtkIdType nPts,
+        const double localThreshold,
+        const double E,
+        const double F,
+        const double L,
+        const double L2,
+        double smoothingFactor)
+{
+    vtkDebugMacro(<<"Updating the surface: iteration: "<<iter);
+
+    vtkDataArray* imgData = input->GetPointData()->GetScalars();
+
+    double* point, *updatedPoint;
+    float* normal;
+    double mean[3], s[3], sn[3], st[3], probePt[3];
+    double dot=0.0, abs_dot=0.0, r_inv=0.0, f_2=0.0, f_3=0.0,
+		   Imin=0.0, Imax=0.0, intensity=0.0, t_l=0.0,
+		   dist=0.0, maxDist=0.0;
+    int offset = 0;
+    vtkIdType index;
+
+    // Update each point
+    for (int i=0; i<nPts; i++) {
+        offset = i*3;
+    	point = &points[offset];
+    	updatedPoint = &updatedPoints[offset];
+        normal = &normals[offset];
+
+        this->ComputeMeanPosition(points, this->NeighborList[i], mean);
+//        this->ComputeMeanPositionOfNeighbors(i, mean);
+
+        for (int j=0; j<3; j++)
+            s[j] = mean[j] - point[j];
+
+        dot = s[0]*normal[0] + s[1]*normal[1] + s[2]*normal[2];
+        for (int j=0; j<3; j++)
+        {
+        	sn[j] = dot*normal[j];
+        	st[j] = s[j] - sn[j];
+        }
+
+        // Compute component update 2
+        abs_dot = dot;
+        if (abs_dot < 0.0)
+        	abs_dot *= -1.0;
+
+        r_inv = (2.0*abs_dot)/L2;
+        f_2 = 0.5*(1.0 + tanh(F*(r_inv - E)));
+
+        if (pass > 0 && dot > 0.0)
+        {
+        	f_2 *= smoothingFactor;
+        	// f_2 = MIN(f_2, 1.0);
+        	if (f_2 > 1.0)
+        		f_2 = 1.0;
+        }
+
+        // Compute component update 3
+        Imin = this->MedianIntensity;
+        Imax = this->Threshold;
+
+        for (int d=1; double(d)<this->MinIntensitySearchDist; d++)
+        {
+            for (int j=0; j<3; j++)
+                probePt[j] = point[j] - double(d)*normal[j];
+
+            index = input->FindPoint(probePt);
+            if (index != -1) {
+                intensity = imgData->GetComponent(index, 0);
+
+                if (intensity < Imin)
+                    Imin = intensity;
+
+                if (double(d)<this->MaxIntensitySearchDist && intensity > Imax)
+                        Imax = intensity;
+            }
+        }
+
+        if (this->MinIntensityThresh > Imin)
+        	Imin = this->MinIntensityThresh;
+        if (this->MedianIntensity < Imax)
+        	Imax = this->MedianIntensity;
+
+        t_l = (Imax - this->MinIntensityThresh)*localThreshold + this->MinIntensityThresh;
+        if ((Imax - this->MinIntensityThresh) > 0.0)
+        	f_3 = 2.0*(Imin - t_l)/(Imax - this->MinIntensityThresh);
+        else
+         	f_3 = 2.0*(Imin - t_l);
+
+        // Perform update
+        for (int j=0; j<3; j++)
+        {
+            updatedPoint[j] = point[j] + 0.5*st[j] + f_2*sn[j] + 0.05*f_3*L*normal[j];
+            if (updatedPoint[j] <= extent[2*j])
+                updatedPoint[j] = extent[2*j] + 2;
+            else if (updatedPoint[j] >= extent[2*j+1])
+                updatedPoint[j] = extent[2*j+1] - 2;
+        }
+
+        dist = vtkMath::Distance2BetweenPoints(point, updatedPoint);
+        if (dist > maxDist)
+            maxDist = dist;
+    }
+
+    for (int i=0; i<nPts; i++)
+    {
+        offset = i*3;
+        for (int j=0; j<3; j++)
+        {
+            points[offset+j] = updatedPoints[offset+j];
+        }
+    }
+
+    return maxDist;
+}
+
+// -------------------------------------------------------------------------------------------
+
+void vtkjoBETImageFilter::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+    vtkDebugMacro(<<"Executing BET image filter");
+
+    if (input == NULL)
+    {
+        vtkErrorMacro(<<"Input is NULL");
+        return;
+    }
+
+    this->UpdateProgress(0.0);
+
+    // Setup and perform image preprocessing
+
+    this->BETHistogram->SetInput(input);
+    this->BETHistogram->SetMinIntensityPercent(this->GetMinIntensityPercent());
+    this->BETHistogram->SetMaxIntensityPercent(this->GetMaxIntensityPercent());
+    this->BETHistogram->SetBins(this->GetBins());
+    this->BETHistogram->Update();
+
+    this->Threshold = this->BETHistogram->GetThreshold();
+    this->MinIntensityThresh = this->BETHistogram->GetMinIntensity();
+    this->MaxIntensityThresh = this->BETHistogram->GetMaxIntensity();
+    this->MedianIntensity = this->BETHistogram->GetMedianIntensity();
+
+    if (this->GetManualRadiusAndCOG() == 0)
+    {
+        this->Radius = this->BETHistogram->GetRadius();
+        this->SetCenterOfGravity(this->BETHistogram->GetCenterOfGravity());
+    }
+
+    this->PrintSelf(cout, vtkIndent());
+
+    // Initialize the surface.  Use a sphere based on calculations
+    // from the histogram if no other surface is provided by the user.
+    if (this->SurfaceInput == NULL)
+    {
+        this->SurfaceInput = this->CreateInitialSurface();
+    }
+
+    // Copy the initial/input surface so we are working with a local copy
+    this->Surface = vtkPolyData::New();
+    this->Surface->DeepCopy(this->SurfaceInput);
+
+    this->FindNeighbors();
+    vtkIdType numEdges = this->CreateEdgeTable();
+
+    double localThresholdConst = pow(this->LocalThresholdConst, 0.275);
+
+    // Stuff for increased smoothing
+    vtkPolyData* originalSurface;
+    if (this->IncreasedSmoothing) {
+        // Make a copy of the original surface for use later
+        // in calculating "spherecity"
+        originalSurface = this->CreateInitialSurface();
+    }
+    else
+        this->MaxPasses = 1;
+
+    // Do a bunch of setup for optimal performance
+    double spacing[3]; input->GetSpacing(spacing);
+    int inExtent[6]; input->GetWholeExtent(inExtent);
+
+    double extent[6];
+    for (int i=0; i<3; i++)
+    {
+        extent[2*i] = double(inExtent[2*i])*spacing[i];
+        extent[2*i+1] = double(inExtent[2*i+1])*spacing[i];
+    }
+
+    // Precompute E and F for the second update component
+    double E = 0.5*((1/this->RMin) + (1/this->RMax));
+    double F = 6.0/((1/this->RMin) - (1/this->RMax));
+    double L = 0.0, L2 = 0.0;
+    double smoothingFactor = 1.0;
+
+    // Get the set of surface points and a copy of them and convert to pointer arrays
+    vtkDoubleArray* pointsArray = (vtkDoubleArray*) this->Surface->GetPoints()->GetData();
+    double* points_ptr = pointsArray->GetPointer(0);
+    vtkIdType nPts = pointsArray->GetNumberOfTuples();
+
+    vtkPoints* updatedPoints = vtkPoints::New();
+    updatedPoints->SetDataTypeToDouble();
+    updatedPoints->SetNumberOfPoints(nPts);
+    double* updatedPoints_ptr = (double*) updatedPoints->GetData()->GetVoidPointer(0);
+
+    // Create a single normal filter
+    vtkPolyDataNormals* normalFilter = vtkPolyDataNormals::New();
+    normalFilter->SplittingOff();
+    normalFilter->FlipNormalsOn();
+    normalFilter->ComputePointNormalsOn();
+
+    // Record the maximum distance changed
+    double maxDist=0.0;
+
+
+    for (int j=0; j<this->MaxPasses; j++)
+    {
+        double scale = 1.0/double(this->MaxIterations);
+
+        for (int i=0; i<this->MaxIterations; i++)
+        {
+            // Find the mean connection length, occasionally
+            if (i == 50 || i%100 == 0)
+            {
+                L = this->ComputeMeanVertexSpacing(this->Surface);
+                fprintf(stderr, "%d: Mean Vertex Spacing = %f\n", i, L);
+                L2 = L*L;
+            }
+
+            if (j > 0)
+            {
+                double tempFactor = pow(10.0, double(j+1));
+                if (i > double(this->MaxIterations)*0.75)
+                    smoothingFactor = 4.0*(1.0 - double(i)*scale)*(tempFactor - 1.0) + 1.0;
+                else
+                    smoothingFactor = tempFactor;
+            }
+
+            // Compute the surface normals
+            normalFilter->SetInput(this->Surface);
+            normalFilter->Update();
+
+            // TODO: probably make this a template to handle the case when normals
+            // switch over to doubles in future VTK releases
+            vtkDataArray* normalsArray = normalFilter->GetOutput()->GetPointData()->GetNormals();
+            float* normals_ptr = (float*) (normalsArray->GetVoidPointer(0));
+
+            maxDist = this->SingleIteration(
+                    i, j,
+                    input,
+                    spacing,
+                    extent,
+                    points_ptr,
+                    normals_ptr,
+                    updatedPoints_ptr,
+                    nPts,
+                    localThresholdConst,
+                    E, F, L, L2,
+                    smoothingFactor);
+
+            this->UpdateProgress(double(i+1)/double(this->MaxIterations));
+        }
+
+        if (this->IncreasedSmoothing)
+        {
+            double self_intersection = this->ComputeSefIntersection(originalSurface);
+            fprintf(stderr, "self_intersection=%f\n", self_intersection);
+
+            if (self_intersection <= this->SelfIntersectionThreshold)
+                j = this->MaxPasses;
+            else {
+                vtkDebugMacro(<<"Rerunning with higher smoothness constraint");
+                fprintf(stderr, "Rerunning with higher smoothness constraint\n");
+
+//                double* origPts_ptr = (double*) originalPts->GetData()->GetVoidPointer(0);
+//                int offset = 0;
+//                for (int k=0; k<nPts; k++) {
+//                    offset = k*3;
+//                    for (int m=0; m<3; m++) {
+//                        points_ptr[offset+m] = origPts_ptr[offset+m];
+//                    }
+//                }
+            }
+        }
+    }
+
+    this->UpdateProgress(1.0);
+
+    this->CreateStrippedImage(this->Surface, input, output);
+
+    // Cleanup...
+    normalFilter->Delete();
+    updatedPoints->Delete();
+    if (this->IncreasedSmoothing)
+        originalSurface->Delete();
+}
+
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkjoBETImageFilter.h b/bioimagesuite30_src/Segmentation/vtkjoBETImageFilter.h
new file mode 100644
index 0000000..ae02da2
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkjoBETImageFilter.h
@@ -0,0 +1,272 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkjoBETImageFilter.h
+ *
+ *  Created on: Sep 12, 2008
+ *      Author: jonofrey
+ */
+
+#ifndef VTKJOBETIMAGEFILTER_H_
+#define VTKJOBETIMAGEFILTER_H_
+
+#include "vtkEdgeTable.h"
+#include "vtkImageData.h"
+#include "vtkjoBETHistogram.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataNormals.h"
+#include "vtkSimpleImageToImageFilter.h"
+
+class vtkjoBETImageFilter : public vtkSimpleImageToImageFilter
+{
+public:
+    static vtkjoBETImageFilter *New();
+    vtkTypeMacro(vtkjoBETImageFilter, vtkSimpleImageToImageFilter);
+
+    void PrintSelf(ostream& os, vtkIndent indent);
+
+    // Description:
+    // Set the initial surface geometry from which the BET
+    // algorithm will start running.  If no surface is provided here
+    // BET proceeds as normally by creating an initial sphere surface
+    // based on parameters found creating the histogram.
+    vtkSetObjectMacro(SurfaceInput, vtkPolyData);
+
+    // Description:
+    // Returns the BET brain surface geometry mesh.
+    vtkGetObjectMacro(Surface, vtkPolyData);
+
+    // Description:
+    // Returns the binary image mask of the extracted brain.
+    vtkImageData* GetOutputMask();
+
+    // Description:
+    // MinIntensityPercent - the lower percentage of the cumulative histogram
+    // used to determine MinIntensity.  We limit the minimum intensity
+    // percentage to be between 0.0 and 1.0.  The default is 0.02.
+    vtkSetClampMacro(MinIntensityPercent, double, 0.0, 1.0);
+    vtkGetMacro(MinIntensityPercent, double);
+
+    // Description:
+    // MaxIntensityPercent - the upper percentage of the cumulative histogram
+    // used to determine MaxIntensity.  We limit the maximum intensity
+    // percentage to be between 0.0 and 1.0.  The default is 0.98.
+    vtkSetClampMacro(MaxIntensityPercent, double, 0.0, 1.0);
+    vtkGetMacro(MaxIntensityPercent, double);
+
+    // Description:
+    // MinIntensityThresh - the robust minimum intensity threshold below which
+    // lies MinIntensityPercent percent of the cumulative histogram.
+    vtkGetMacro(MinIntensityThresh, double);
+    // Description:
+    // MaxIntensityThresh - the robust maximum intensity threshold above which
+    // lies MaxIntensityPercent percent of the cumulative histogram.
+    vtkGetMacro(MaxIntensityThresh, double);
+    // Description:
+    // Threshold - set to be 10% of the way between MinIntensityThresh
+    // and MaxIntensityThresh.
+    vtkGetMacro(Threshold, double);
+
+    // Description:
+    // Bins - the number of histogram bins.  We limit the number of bins to be
+    // between 1 and 1024.
+    vtkSetClampMacro(Bins, int, 1, 1024);
+    vtkGetMacro(Bins, int);
+
+    // Description:
+    // Center Of Gravity - the center of gravity (COG) of the brain/head in the
+    // image.  Only voxels with intensity greater than Threshold and less than
+    // MaxIntensityThresh are used to compute this.
+    vtkGetVectorMacro(CenterOfGravity, double, 3);
+    vtkSetVector3Macro(CenterOfGravity, double);
+
+    // Description:
+    // Radius - the estimated "mean' radius of the brain/head volume.  All voxels
+    // with intensity greater than Threshold are counted.
+    vtkSetMacro(Radius, double);
+    vtkGetMacro(Radius, double);
+
+    // Description:
+    // MedianIntensity - the median intensity within a sphere of the estimated
+    // radius and centered on the COG.
+    vtkGetMacro(MedianIntensity, double);
+
+    // Description:
+    // ManualRadiusAndCOG - the filter uses the radius and center of gravity
+    // manually specified by the user instead of those automatically found
+    // during image preprocessing.
+    vtkSetClampMacro(ManualRadiusAndCOG, int, 0, 1);
+    vtkGetMacro(ManualRadiusAndCOG, int);
+    vtkBooleanMacro(ManualRadiusAndCOG, int);
+
+    // Description:
+    // RadiusScaleFactor - constant factor to scale the InitialRadius by.  Default
+    // value set to 0.5;
+    vtkSetMacro(RadiusScaleFactor, double);
+
+    // Description:
+    // SurfaceResolution - sets the number of surface points to use.  This value
+    // represents the number of times an icosahedron's faces are subdivided into
+    // 4 triangles.
+    vtkSetClampMacro(SurfaceResolution, int, 0, 8);
+
+    // Description:
+    // MaxIterations - the maximum number of iterations for the algorithm
+    // to run.
+    vtkSetMacro(MaxIterations, int);
+
+    // Description:
+    // MaxPasses - the maximum number of passes for the algorithm
+    // to run.
+    vtkSetMacro(MaxPasses, int);
+
+    // Description:
+    // MinChangeTolerance - the minimum allowable maximum change in point distance
+    // shift before the algorithm stops.
+    vtkSetMacro(MinChangeTolerance, double);
+
+    // Description:
+    // MinSearchDist - the distance searched for the minimum intensity
+    // from a surface point (d1 in the BET paper).  Default d1 = 7mm.
+    vtkSetMacro(MinIntensitySearchDist, double);
+    vtkGetMacro(MinIntensitySearchDist, double);
+    // Description:
+    // MaxSearchDist - the distance searched for the maximum intensity
+    // from a surface point (d2 in the BET paper).  Default d2 = 0.5*d1.
+    vtkSetMacro(MaxIntensitySearchDist, double);
+    vtkGetMacro(MaxIntensitySearchDist, double);
+
+    // Description:
+    // LocalThresholdConst - fractional constant (b_t in the BET paper)
+    // used when computing the locally appropriate intensity threshold t_l.
+    // Default b_t = 0.5;
+    vtkSetClampMacro(LocalThresholdConst, double, 0.0, 1.0);
+    vtkGetMacro(LocalThresholdConst, double);
+
+    // Description:
+    // RMin - the minimum local radius used for smoothing (default 3.33mm).
+    vtkSetMacro(RMin, double);
+    // Description:
+    // RMax - the maximum local radius used for smoothing (default 10mm).
+    vtkSetMacro(RMax, double);
+
+    // Description:
+    // IncreasedSmoothing - tells the algorithm to used increased smoothing.
+    vtkSetMacro(IncreasedSmoothing, int);
+    vtkGetMacro(IncreasedSmoothing, int);
+    vtkBooleanMacro(IncreasedSmoothing, int);
+
+    // Description:
+    // SelfIntersectionThreshold - threshold for the surface self intersections.
+    vtkSetMacro(SelfIntersectionThreshold, double);
+
+//    virtual double ComputeMeanVertexSpacing();
+//    virtual void ComputeMeanPositionOfNeighbors(vtkIdType id, double mean[3]);
+
+protected:
+
+    // Stuff from vtkjoBETHistogram...
+    // ======================================================
+    double MinIntensityPercent;
+    double MaxIntensityPercent;
+    double Threshold;
+    double MinIntensityThresh;
+    double MaxIntensityThresh;
+    int Bins;
+    double Radius;
+    double CenterOfGravity[3];
+    double MedianIntensity;
+
+    int ManualRadiusAndCOG;
+    vtkjoBETHistogram* BETHistogram;
+
+    // Stuff from vtkjoBETSurface...
+    // ======================================================
+    double RadiusScaleFactor;
+    int SurfaceResolution;
+    vtkPolyData* SurfaceInput;
+    vtkPolyData* Surface;
+    vtkIdList** NeighborList;
+    vtkEdgeTable* EdgeTable;
+
+    int MaxIterations;
+    int MaxPasses;
+    double MinChangeTolerance;
+
+    double MaxIntensitySearchDist;
+    double MinIntensitySearchDist;
+    double LocalThresholdConst;
+
+    double RMin;
+    double RMax;
+
+    int IncreasedSmoothing;
+    double SelfIntersectionThreshold;
+
+    vtkjoBETImageFilter();
+    virtual ~vtkjoBETImageFilter();
+
+    // Setup methods
+    virtual vtkPolyData* CreateInitialSurface();
+    virtual void FindNeighbors();
+    virtual vtkIdType CreateEdgeTable();
+
+    // BET-related methods
+    virtual double ComputeMeanVertexSpacing(vtkPolyData* surface);
+    virtual void ComputeMeanPosition(
+            const double* points,
+            vtkIdList* neighbors,
+            double mean[3]);
+    virtual double ComputeSefIntersection(
+            vtkPolyData* originalSurface);
+    virtual void CreateStrippedImage(
+            vtkPolyData* surface,
+            vtkImageData* input,
+            vtkImageData* output);
+    virtual double SingleIteration(
+            const int iter,
+            const int pass,
+            vtkImageData* input,
+            const double* spacing,
+            const double* extent,
+            double* points,
+            float* normals,
+            double* updatedPoints,
+            const vtkIdType nPts,
+            const double localThreshold,
+            const double E,
+            const double F,
+            const double L,
+            const double L2,
+            double smoothingFactor);
+
+    virtual void SimpleExecute(vtkImageData* input, vtkImageData *output);
+};
+
+#endif /* VTKJOBETIMAGEFILTER_H_ */
+
diff --git a/bioimagesuite30_src/Segmentation/vtkjoPolyDataRobustBETTraining.cpp b/bioimagesuite30_src/Segmentation/vtkjoPolyDataRobustBETTraining.cpp
new file mode 100644
index 0000000..8b13381
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkjoPolyDataRobustBETTraining.cpp
@@ -0,0 +1,629 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkjoPolyDataRobustBETTraining.cpp
+ *
+ *  Created on: Feb 6, 2009
+ *      Author: jonofrey
+ */
+
+#include <vtkjoPolyDataRobustBETTraining.h>
+
+#include "vtkCellData.h"
+#include "vtkDataArray.h"
+#include "vtkDoubleArray.h"
+#include "vtkImageAppendComponents.h"
+#include "vtkImageContinuousDilate3D.h"
+#include "vtkImageContinuousErode3D.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkImageReslice.h"
+#include "vtkImageThreshold.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkjoBETHistogram.h"
+#include "vtkjoBETImageFilter.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+#include "vtkPolyDataNormals.h"
+#include "vtkPolyDataToImageStencil.h"
+#include "vtkpxImageAlgebra.h"
+#include "vtkpxUtil.h"
+#include "vtkShortArray.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+vtkjoPolyDataRobustBETTraining* vtkjoPolyDataRobustBETTraining::New()
+{
+    // First try to create the object from the vtkObjectFactory
+    vtkObject* ret = vtkObjectFactory::CreateInstance("vtkjoRobustBETTraining");
+    if (ret)
+    {
+        return (vtkjoPolyDataRobustBETTraining*) ret;
+    }
+    // If the factory was unable to create the object, then create it here.
+    return new vtkjoPolyDataRobustBETTraining;
+}
+
+void vtkjoPolyDataRobustBETTraining::PrintSelf(ostream &os, vtkIndent indent)
+{
+    vtkPolyDataAlgorithm::PrintSelf(os, indent);
+}
+
+
+vtkjoPolyDataRobustBETTraining::vtkjoPolyDataRobustBETTraining()
+{
+    this->SrcImage = NULL;
+    this->Appender = vtkImageAppendComponents::New();
+
+    this->MinIntensitySearchDist = 7.0;
+    this->MaxIntensitySearchDist = 3.5;
+    this->LocalThresholdConst = 0.5;
+
+    this->NormalizeInputsOn();
+    this->SearchOutwardsOff();
+}
+
+vtkjoPolyDataRobustBETTraining::~vtkjoPolyDataRobustBETTraining()
+{
+    if (this->Appender != NULL)
+        this->Appender->Delete();
+}
+
+void vtkjoPolyDataRobustBETTraining::SetSrcImage(vtkImageData* image)
+{
+    this->SrcImage = image;
+    this->Modified();
+}
+
+//=========================================================================
+
+void vtkjoPolyDataRobustBETTraining::AddInput(vtkImageData* image)
+{
+    if (image == NULL) {
+        vtkErrorMacro("Unable to add NULL image");
+        return;
+    }
+
+    if (this->NormalizeInputs) {
+        // First, normalize the input image
+        double range[2];
+        image->GetPointData()->GetScalars()->GetRange(range);
+
+        float auto_min, auto_max;
+        vtkpxUtil::ImageRobustRange(image, 0.01, 0.99, auto_min, auto_max);
+
+        // Create a new map
+        vtkDoubleArray* map = vtkDoubleArray::New();
+        map->SetNumberOfComponents(3);
+
+        // add to the map x,a,b triples
+        map->InsertNextTuple3(auto_min, 0.0, 0.0);
+        map->InsertNextTuple3(auto_max, 0.0, 100.0/(auto_max-auto_min));
+        map->InsertNextTuple3(range[1], 100.0, 0.0);
+
+        vtkpxImageAlgebra* filter = vtkpxImageAlgebra::New();
+        filter->SetInput(image);
+        filter->SetMap(map);
+        filter->Update();
+
+        // Now, append the normalized image
+        this->Appender->AddInput(filter->GetOutput());
+        this->Appender->Update();
+
+        map->Delete();
+        filter->Delete();
+    } else {
+        // Append the image
+        this->Appender->AddInput(image);
+        this->Appender->Update();
+    }
+
+    this->Modified();
+}
+
+//=========================================================================
+
+vtkImageData* vtkjoPolyDataRobustBETTraining::GetInputImage()
+{
+    vtkImageData* output = vtkImageData::New();
+    output->ShallowCopy(this->SrcImage);
+    return output;
+}
+
+//=========================================================================
+
+double vtkjoPolyDataRobustBETTraining::GetMin(const char *arrayName)
+{
+    if (!arrayName) {
+        return 0.0;
+    }
+
+    vtkPolyData* output = this->GetOutput();
+
+    vtkDataArray* data = output->GetPointData()->GetArray(arrayName);
+    // Make sure the array with the given name exists
+    if (data) {
+        double range[2];
+        data->GetRange(range, 0);
+        return range[0];
+    }
+
+    return 0.0;
+}
+
+double vtkjoPolyDataRobustBETTraining::GetMax(const char *arrayName)
+{
+    if (!arrayName) {
+        return 0.0;
+    }
+
+    vtkPolyData* output = this->GetOutput();
+
+    vtkDataArray* data = output->GetPointData()->GetArray(arrayName);
+    // Make sure the array with the given name exists
+    if (data) {
+        double range[2];
+        data->GetRange(range, 0);
+        return range[1];
+    }
+
+    return 0.0;
+}
+
+//=========================================================================
+
+void vtkjoPolyDataRobustBETTraining::ComputeStatistics(vtkDataArray* data,
+        vtkDataArray* means,
+        vtkDataArray* vars)
+{
+    vtkIdType nPts = data->GetNumberOfTuples();
+    if (nPts != means->GetNumberOfTuples() || nPts != vars->GetNumberOfTuples())
+    {
+        vtkErrorMacro("Data arrays do not have the same size.");
+        return;
+    }
+
+    int numComps = data->GetNumberOfComponents();
+    double sum=0.0, sumSqrs=0.0;
+    double value, mean, var;
+    double tol = 1E-05;
+
+    for (int i=0; i<nPts; i++)
+    {
+        sum = 0.0, sumSqrs = 0.0;
+        for (int n=0; n<numComps; n++)
+        {
+            value = data->GetComponent(i, n);
+            sum += value;
+            sumSqrs += value*value;
+        }
+        mean = sum/double(numComps);
+        means->SetComponent(i, 0, mean);
+
+        var = mean*mean + (sumSqrs - 2.0*mean*sum)/double(numComps);
+        // Check for very small variances and just set these to zero
+        if (var < tol) {
+            var = 0.0;
+        }
+//        vars->SetComponent(i, 0, sqrt(var));
+        vars->SetComponent(i, 0, var);
+    }
+}
+
+//=========================================================================
+
+vtkImageData* vtkjoPolyDataRobustBETTraining::GetOutputAsImage()
+{
+    // Check to make sure we have all the object we need to work with.
+    if (this->SrcImage == NULL) {
+        vtkErrorMacro("SrcImage cannot be null.");
+        return NULL;
+    }
+
+    vtkIdType nPts = this->SrcImage->GetNumberOfPoints();
+
+    vtkImageData* ones = vtkImageData::New();
+    ones->CopyStructure(this->SrcImage);
+    ones->SetNumberOfScalarComponents(1);
+    ones->SetScalarTypeToFloat();
+    ones->AllocateScalars();
+    ones->GetPointData()->GetScalars()->FillComponent(0, 1.0);
+
+    vtkPolyDataToImageStencil* stencil = vtkPolyDataToImageStencil::New();
+    stencil->SetInput(this->GetOutput());
+    stencil->SetInformationInput(ones);
+    stencil->Update();
+
+    vtkImageReslice* reslice = vtkImageReslice::New();
+    reslice->SetInput(ones);
+    reslice->SetStencil(stencil->GetOutput());
+    reslice->SetBackgroundColor(0.0, 0.0, 0.0, 1.0);
+    reslice->Update();
+
+    stencil->Delete();
+    ones->Delete();
+
+    vtkImageContinuousDilate3D* dilate = vtkImageContinuousDilate3D::New();
+    dilate->SetInputConnection(reslice->GetOutputPort());
+    dilate->SetKernelSize(3,3,3);
+    dilate->Update();
+
+    vtkImageContinuousErode3D* erode = vtkImageContinuousErode3D::New();
+    erode->SetInputConnection(reslice->GetOutputPort());
+    erode->SetKernelSize(3,3,3);
+    erode->Update();
+
+    reslice->Delete();
+
+    vtkImageData* outline = vtkImageData::New();
+    outline->ShallowCopy(dilate->GetOutput());
+
+    vtkDataArray* outlineDA = outline->GetPointData()->GetScalars();
+    vtkDataArray* eroded = erode->GetOutput()->GetPointData()->GetScalars();
+
+    // Subtract the eroded brain mask from the dilated mask
+    for (int i = 0; i < nPts; i++) {
+        if (eroded->GetComponent(i, 0) > 0.0) {
+            outlineDA->SetComponent(i, 0, 0.0);
+        }
+    }
+
+    erode->Delete();
+    dilate->Delete();
+
+    // Update the remaining surface pixels to reflect values from
+    // the field data at the closest point
+    vtkPolyData* surface = this->GetOutput();
+
+    // Create a new image with the correct number of components
+    int numArrays = surface->GetPointData()->GetNumberOfArrays();
+    vtkImageAppendComponents* appender = vtkImageAppendComponents::New();
+    for (int i=0; i<numArrays; i++) {
+        appender->AddInput(outline);
+        appender->Update();
+    }
+
+    outline->Delete();
+
+    vtkImageData* output = vtkImageData::New();
+    output->ShallowCopy(appender->GetOutput());
+    vtkDataArray* outDA = output->GetPointData()->GetScalars();
+
+    appender->Delete();
+
+    // Now fill in the output frames with the field data values
+    vtkDataArray* fieldData;
+    double point[3];
+    double value = 0.0;
+
+    for (int n=0; n < numArrays; n++) {
+        fieldData = surface->GetPointData()->GetArray(n);
+
+        for (int i=0; i < nPts; i++) {
+            if (outDA->GetComponent(i, n) > 0.0) {
+                output->GetPoint(i, point);
+                vtkIdType id = surface->FindPoint(point);
+                if (id != -1) {
+                    value = fieldData->GetComponent(id, 0);
+                    outDA->SetComponent(i, n, value);
+                }
+            }
+        }
+    }
+
+    // Cleanup...
+    return output;
+}
+
+//=========================================================================
+/*
+vtkDoubleArray* vtkjoPolyDataRobustBETTraining::ComputeF2(vtkPolyData* surface) {
+
+    // Check to make sure we have a surface
+    if (surface == NULL) {
+        vtkErrorMacro("surface cannot be null.");
+        return NULL;
+    }
+
+    vtkIdType nPts = surface->GetNumberOfPoints();
+
+    vtkDoubleArray* f2s = vtkDoubleArray::New();
+    f2s->SetNumberOfComponents(1);
+    f2s->SetNumberOfTuples(nPts);
+
+    vtkPolyDataNormals* normalFilter = vtkPolyDataNormals::New();
+    normalFilter->SplittingOff();
+    normalFilter->FlipNormalsOn();
+    normalFilter->ComputePointNormalsOn();
+    normalFilter->SetInput(surface);
+    normalFilter->Update();
+
+    vtkjoBETImageFilter* bet = vtkjoBETImageFilter::New();
+    bet->SetSurface(surface);
+
+    vtkDataArray* normals = normalFilter->GetOutput()->GetPointData()->GetNormals();
+
+    vtkDataArray* points = surface->GetPoints()->GetData();
+
+    double const RMin = 3.33333;
+    double const RMax = 10.0;
+    double E = 0.5*((1/RMin) + (1/RMax));
+    double F = 6.0/((1/RMin) - (1/RMax));
+    double abs_dot, dot, r_inv, f_2;
+
+//    double L = this->ComputeMeanVertexSpacing(surface);
+    double L = bet->ComputeMeanVertexSpacing();
+    double L2 = L*L;
+
+    double point[3], normal[3], mean[3], s[3], st[3], sn[3];
+
+    for (int i=0; i<nPts; i++) {
+
+        points->GetTuple(i, point);
+        normals->GetTuple(i, normal);
+
+//        this->ComputeMeanPosition(surface, points, this->NeighborList[i], mean);
+        bet->ComputeMeanPositionOfNeighbors(i, mean);
+
+        for (int j=0; j<3; j++)
+            s[j] = mean[j] - point[j];
+
+        dot = s[0]*normal[0] + s[1]*normal[1] + s[2]*normal[2];
+        for (int j=0; j<3; j++)
+        {
+            sn[j] = dot*normal[j];
+            st[j] = s[j] - sn[j];
+        }
+
+        // Compute component update 2
+        abs_dot = dot;
+        if (abs_dot < 0.0)
+            abs_dot *= -1.0;
+
+        r_inv = (2.0*abs_dot)/L2;
+        f_2 = 0.5*(1.0 + tanh(F*(r_inv - E)));
+
+        f2s->SetComponent(i, 0, f_2);
+    }
+
+    normalFilter->Delete();
+    bet->Delete();
+
+    return f2s;
+}
+*/
+//=========================================================================
+
+int vtkjoPolyDataRobustBETTraining::RequestData(
+        vtkInformation* vtkNotUsed(request),
+        vtkInformationVector** inputVector,
+        vtkInformationVector* outputVector)
+{
+    // TODO: this is bad to do this here, but it will do for now...
+    fprintf(stderr, "getting data from the appender...\n");
+    this->SrcImage = this->Appender->GetOutput();
+    fprintf(stderr, "SrcImage has num comps = %d\n",
+            this->SrcImage->GetNumberOfScalarComponents());
+
+    // Get the info objects
+    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
+    vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+    // Get the input and output
+    vtkPolyData *input = vtkPolyData::SafeDownCast(
+            inInfo->Get(vtkDataObject::DATA_OBJECT()));
+    vtkPolyData *output = vtkPolyData::SafeDownCast(
+            outInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+    vtkDataArray* points = input->GetPoints()->GetData();
+    vtkIdType nPts = points->GetNumberOfTuples();
+
+    // Copy the data through
+    output->DeepCopy(input);
+
+    vtkPolyDataNormals* normalFilter = vtkPolyDataNormals::New();
+    normalFilter->SetInput(input);
+    normalFilter->SplittingOff();
+    normalFilter->FlipNormalsOn();
+    normalFilter->ComputePointNormalsOn();
+    normalFilter->Update();
+    vtkDataArray* normals = normalFilter->GetOutput()->GetPointData()->GetNormals();
+
+    // Get the source image
+    int numComps = this->SrcImage->GetNumberOfScalarComponents();
+
+    // Create a temporary storage array for calculating the mean
+    // and variance of f3
+    vtkDoubleArray* f3StatsArray = vtkDoubleArray::New();
+    f3StatsArray->SetNumberOfComponents(numComps);
+    f3StatsArray->SetNumberOfTuples(nPts);
+
+    vtkFloatArray* meanBETVal = vtkFloatArray::New();
+    meanBETVal->SetName("BET_mean");
+    meanBETVal->SetNumberOfComponents(1);
+    meanBETVal->SetNumberOfTuples(nPts);
+
+    vtkFloatArray* varBETVal = vtkFloatArray::New();
+    varBETVal->SetName("BET_var");
+    varBETVal->SetNumberOfComponents(1);
+    varBETVal->SetNumberOfTuples(nPts);
+
+    // Create a temporary storage array for calculating the mean
+    // and variance of bt
+    vtkDoubleArray* btStatsArray = vtkDoubleArray::New();
+    btStatsArray->SetNumberOfComponents(numComps);
+    btStatsArray->SetNumberOfTuples(nPts);
+
+    vtkFloatArray* meanBtVal = vtkFloatArray::New();
+    meanBtVal->SetName("bt_mean");
+    meanBtVal->SetNumberOfComponents(1);
+    meanBtVal->SetNumberOfTuples(nPts);
+
+    vtkFloatArray* varBtVal = vtkFloatArray::New();
+    varBtVal->SetName("bt_var");
+    varBtVal->SetNumberOfComponents(1);
+    varBtVal->SetNumberOfTuples(nPts);
+
+    // Create a temporary storage array for calculating the mean and
+    // variance of bt with compensation for f2 update term
+//    vtkFloatArray* meanBt2Val = vtkFloatArray::New();
+//    meanBt2Val->SetName("bt2_mean");
+//    meanBt2Val->SetNumberOfComponents(1);
+//    meanBt2Val->SetNumberOfTuples(nPts);
+//
+//    vtkFloatArray* varBt2Val = vtkFloatArray::New();
+//    varBt2Val->SetName("bt2_var");
+//    varBt2Val->SetNumberOfComponents(1);
+//    varBt2Val->SetNumberOfTuples(nPts);
+
+
+    vtkImageExtractComponents* extractor = vtkImageExtractComponents::New();
+    extractor->SetInput(this->SrcImage);
+    vtkImageData* currentImage;
+
+    vtkjoBETHistogram* bet = vtkjoBETHistogram::New();
+
+    double maxDist =
+        (this->MinIntensitySearchDist > this->MaxIntensitySearchDist)?
+                this->MinIntensitySearchDist : this->MaxIntensitySearchDist;
+    double localThreshold = pow(this->LocalThresholdConst, 0.275);
+
+    for (int n=0; n<numComps; n++) {
+        fprintf(stderr, "processing image %d...\n", n);
+        extractor->SetComponents(n);
+        extractor->Update();
+
+        vtkDataArray* imgData = extractor->GetOutput()->GetPointData()->GetScalars();
+        double range[2];
+        imgData->GetRange(range);
+        fprintf(stderr, "  img %d range: [%f, %f]\n", n, range[0], range[1]);
+
+        bet->SetInputConnection(extractor->GetOutputPort());
+        bet->Update();
+        double Threshold = bet->GetThreshold();
+        double MinIntensityThresh = bet->GetMinIntensity();
+        double MaxIntensityThresh = bet->GetMaxIntensity();
+        double MedianIntensity = bet->GetMedianIntensity();
+
+        // Loop through all the surface points and write the BET update
+        // coefficient value to the statistics array at the corresponding
+        // location
+        vtkIdType index;
+        double intensity=0.0, Imin=0.0, Imax=0.0, t_l=0.0, f_3=0.0;
+        double f_2 = 0.0;
+        double b_t=0.0;
+        double point[3], normal[3], probePt[3];
+        for (int i=0; i<nPts; i++)
+        {
+            points->GetTuple(i, point);
+            normals->GetTuple(i, normal);
+
+            // Compute the update component according to BET
+            Imin = MedianIntensity;
+            Imax = Threshold;
+
+            for (double d=1.0; d<maxDist; d = d + 1.0)
+            {
+                if (!this->SearchOutwards) {
+                    for (int j=0; j<3; j++)
+                        probePt[j] = point[j] - d*normal[j];
+                } else {
+                    for (int j=0; j<3; j++)
+                        probePt[j] = point[j] + d*normal[j];
+                }
+
+                index = this->SrcImage->FindPoint(probePt);
+                if (index != -1) {
+                    intensity = imgData->GetComponent(index, 0);
+                    if (d<this->MinIntensitySearchDist && intensity < Imin)
+                        Imin = intensity;
+                    if (d<this->MaxIntensitySearchDist && intensity > Imax)
+                        Imax = intensity;
+                }
+            }
+
+            if (MinIntensityThresh > Imin)
+                Imin = MinIntensityThresh;
+            if (MedianIntensity < Imax)
+                Imax = MedianIntensity;
+
+            t_l = (Imax - MinIntensityThresh)*localThreshold + MinIntensityThresh;
+            if ((Imax - MinIntensityThresh) > 0.0)
+                f_3 = 2.0*(Imin - t_l)/(Imax - MinIntensityThresh);
+            else
+                f_3 = 2.0*(Imin - t_l);
+
+            // Store the value in our temporary array
+            f3StatsArray->SetComponent(i, n, f_3);
+
+            // Store the analytical value of bt in our surface
+//            b_t = (Imin - MinIntensityThresh)/(Imax - MinIntensityThresh);
+            // Store the normalized analytical value of bt in our surface
+            b_t = (Imin - MinIntensityThresh)/(Imax - MinIntensityThresh);
+            b_t /= localThreshold;
+            btStatsArray->SetComponent(i, n, b_t);
+
+        }
+    }
+
+    this->ComputeStatistics(f3StatsArray, meanBETVal, varBETVal);
+    this->ComputeStatistics(btStatsArray, meanBtVal, varBtVal);
+//    this->ComputeStatistics(bt2StatsArray, meanBt2Val, varBt2Val);
+
+    // Compute the value of bt2
+//    vtkFloatArray* f2 = this->ComputeF2(input);
+//    for (int i=0; i<nPts; i++) {
+//        meanBt2Val->SetComponent(i, 0,
+//                meanBtVal->GetComponent(i, 0) + 0.5*f2->GetComponent(i, 0));
+//    }
+//    varBt2Val->DeepCopy(varBtVal);
+
+    // Get the point data, this is what we'll be setting.
+    vtkPointData* outPD = output->GetPointData();
+    outPD->AddArray(meanBETVal);
+    outPD->AddArray(varBETVal);
+    outPD->AddArray(meanBtVal);
+    outPD->AddArray(varBtVal);
+//    outPD->AddArray(meanBt2Val);
+//    outPD->AddArray(varBt2Val);
+
+    meanBETVal->Delete();
+    varBETVal->Delete();
+    meanBtVal->Delete();
+    varBtVal->Delete();
+//    meanBt2Val->Delete();
+//    varBt2Val->Delete();
+    f3StatsArray->Delete();
+    btStatsArray->Delete();
+    bet->Delete();
+    extractor->Delete();
+
+    return 1;
+}
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkjoPolyDataRobustBETTraining.h b/bioimagesuite30_src/Segmentation/vtkjoPolyDataRobustBETTraining.h
new file mode 100644
index 0000000..cda41b4
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkjoPolyDataRobustBETTraining.h
@@ -0,0 +1,138 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkjoPolyDataRobustBETTraining.h
+ *
+ *  Created on: Feb 6, 2009
+ *      Author: jonofrey
+ */
+
+#ifndef VTKJOPOLYDATAROBUSTBETTRAINING_H_
+#define VTKJOPOLYDATAROBUSTBETTRAINING_H_
+
+#include "vtkFloatArray.h"
+#include "vtkImageAppendComponents.h"
+#include "vtkImageData.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataAlgorithm.h"
+
+class vtkjoPolyDataRobustBETTraining : public vtkPolyDataAlgorithm {
+public:
+    static vtkjoPolyDataRobustBETTraining *New();
+    vtkTypeMacro(vtkjoPolyDataRobustBETTraining, vtkPolyDataAlgorithm);
+
+    void PrintSelf(ostream &os, vtkIndent indent);
+
+    // Description:
+    // Get/Set the source image.
+    virtual void SetSrcImage(vtkImageData* image);
+
+    // Description:
+    // Add source image to the stack of training images.  The added
+    // image will be appended as a component to the end of the
+    // current image stack.  Use the NormalizeInputs flag to turn
+    // normalization on/off.
+    virtual void AddInput(vtkImageData* image);
+
+    virtual vtkImageData* GetInputImage();
+
+    // Description:
+    // Get the calculated information as an image.
+    virtual vtkImageData* GetOutputAsImage();
+
+    virtual double GetMin(const char* arrayName);
+    virtual double GetMax(const char* arrayName);
+
+    // Description:
+    // MinSearchDist - the distance searched for the minimum intensity
+    // from a surface point (d1 in the BET paper).  Default d1 = 7mm.
+    vtkSetMacro(MinIntensitySearchDist, double);
+    vtkGetMacro(MinIntensitySearchDist, double);
+    // Description:
+    // MaxSearchDist - the distance searched for the maximum intensity
+    // from a surface point (d2 in the BET paper).  Default d2 = 0.5*d1.
+    vtkSetMacro(MaxIntensitySearchDist, double);
+    vtkGetMacro(MaxIntensitySearchDist, double);
+    // Description:
+    // MinSearchDist - the distance searched for the minimum intensity
+    // from a surface point (d1 in the BET paper).  Default d1 = 7mm.
+    vtkSetMacro(OutMinIntensitySearchDist, double);
+    vtkGetMacro(OutMinIntensitySearchDist, double);
+    // Description:
+    // MaxSearchDist - the distance searched for the maximum intensity
+    // from a surface point (d2 in the BET paper).  Default d2 = 0.5*d1.
+    vtkSetMacro(OutMaxIntensitySearchDist, double);
+    vtkGetMacro(OutMaxIntensitySearchDist, double);
+    // Description:
+    // LocalThresholdConst - fractional constant (b_t in the BET paper)
+    // used when computing the locally appropriate intensity threshold t_l.
+    // Default b_t = 0.5;
+    vtkSetClampMacro(LocalThresholdConst, double, 0.0, 1.0);
+    vtkGetMacro(LocalThresholdConst, double);
+
+    // Description:
+    // Normalize the input images as they are added to the input image
+    // stack (default is On).
+    vtkSetClampMacro(NormalizeInputs, int, 0, 1);
+    vtkGetMacro(NormalizeInputs, int);
+    vtkBooleanMacro(NormalizeInputs, int);
+
+    // Description:
+    // Normalize the input images as they are added to the input image
+    // stack (default is On).
+    vtkSetClampMacro(SearchOutwards, int, 0, 1);
+    vtkGetMacro(SearchOutwards, int);
+    vtkBooleanMacro(SearchOutwards, int);
+
+protected:
+    vtkImageData* SrcImage;
+    vtkImageAppendComponents* Appender;
+
+    double MinIntensitySearchDist;
+    double MaxIntensitySearchDist;
+    double OutMinIntensitySearchDist;
+    double OutMaxIntensitySearchDist;
+    double LocalThresholdConst;
+
+    int NormalizeInputs;
+    int SearchOutwards;
+
+    virtual void ComputeStatistics(vtkDataArray* data,
+            vtkDataArray* means,
+            vtkDataArray* vars);
+
+//    virtual vtkFloatArray* ComputeF2(vtkPolyData* surface);
+
+    vtkjoPolyDataRobustBETTraining();
+    virtual ~vtkjoPolyDataRobustBETTraining();
+
+    virtual int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*);
+};
+
+#endif /* VTKJOPOLYDATAROBUSTBETTRAINING_H_ */
+
diff --git a/bioimagesuite30_src/Segmentation/vtkjoScalePolyData.cpp b/bioimagesuite30_src/Segmentation/vtkjoScalePolyData.cpp
new file mode 100644
index 0000000..7a82860
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkjoScalePolyData.cpp
@@ -0,0 +1,196 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkjoScalePolyData.cpp
+ *
+ *  Created on: Mar 13, 2009
+ *      Author: jonofrey
+ */
+
+#include "vtkjoScalePolyData.h"
+
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkPolyDataNormals.h"
+
+vtkjoScalePolyData* vtkjoScalePolyData::New()
+{
+    // First try to create the object from the vtkObjectFactory
+    vtkObject* ret = vtkObjectFactory::CreateInstance("vtkjoScalePolyData");
+    if (ret)
+    {
+        return (vtkjoScalePolyData*) ret;
+    }
+    // If the factory was unable to create the object, then create it here.
+    return new vtkjoScalePolyData;
+}
+
+
+vtkjoScalePolyData::vtkjoScalePolyData()
+{
+    this->ScaleFactor = 0.0;
+    this->SetScalingModeToUseCOG();
+}
+
+
+vtkjoScalePolyData::~vtkjoScalePolyData()
+{
+}
+
+
+void vtkjoScalePolyData::PrintSelf(ostream& os, vtkIndent indent)
+{
+    this->Superclass::PrintSelf(os, indent);
+    os << indent << "ScaleFactor: " << this->ScaleFactor << "\n";
+}
+
+
+void vtkjoScalePolyData::ScaleUsingNormals(vtkPolyData* input,
+        vtkPolyData* output, double scalar)
+{
+    vtkDebugMacro("Scaling the geometry along the surface normals...")
+
+    // Get the surface normals normal filter
+    vtkPolyDataNormals* normalFilter = vtkPolyDataNormals::New();
+    normalFilter->SplittingOff();
+    normalFilter->ComputePointNormalsOn();
+    normalFilter->SetInput(input);
+    normalFilter->Update();
+
+    vtkDataArray* inPoints = input->GetPoints()->GetData();
+    vtkDataArray* outPoints = output->GetPoints()->GetData();
+    vtkDataArray* normals = normalFilter->GetOutput()->GetPointData()->GetNormals();
+
+    vtkIdType nPts = input->GetNumberOfPoints();
+    double point[3], normal[3];
+    for (int i=0; i<nPts; i++)
+    {
+        inPoints->GetTuple(i, point);
+        normals->GetTuple(i, normal);
+
+        // Update the point along its normal
+        for (int j=0; j<3; j++)
+            point[j] = point[j] + normal[j]*scalar;
+
+        outPoints->SetTuple(i, point);
+    }
+
+    // Cleanup
+    normalFilter->Delete();
+}
+
+
+void vtkjoScalePolyData::ScaleUsingCOG(vtkPolyData* output,
+        double scalar)
+{
+    vtkDebugMacro("Scaling the geometry about the COG...");
+
+    vtkDataArray* points = output->GetPoints()->GetData();
+    vtkIdType nPts = output->GetNumberOfPoints();
+
+    // First, find the center of gravity (COG)
+    double cog[3], point[3];
+    for (int i=0; i<3; i++)
+        cog[i] = 0.0;
+
+    for (int i=0; i<nPts; i++)
+    {
+        points->GetTuple(i, point);
+        for (int j=0; j<3; j++)
+            cog[j] += point[j];
+    }
+
+    for (int i=0; i<3; i++)
+        cog[i] /= double(nPts);
+
+    vtkDebugMacro("COG = ("<<cog[0]<<","<<cog[1]<<","<<cog[2]<<")");
+
+    // Scale along the normalized vector direction from each point
+    // to the COG
+    double direction[3];
+    for (int i=0; i<nPts; i++)
+    {
+        points->GetTuple(i, point);
+
+        for (int j=0; j<3; j++)
+            direction[j] = cog[j] - point[j];
+        // Normalize the direction vector
+        vtkMath::Normalize(direction);
+
+        // Update the point along its normal
+        for (int j=0; j<3; j++)
+            point[j] = point[j] + direction[j]*scalar;
+
+        points->SetTuple(i, point);
+    }
+}
+
+
+int vtkjoScalePolyData::RequestData(vtkInformation* vtkNotUsed(request),
+        vtkInformationVector** inputVector,
+        vtkInformationVector* outputVector)
+{
+    vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
+    vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+    vtkPolyData *input = vtkPolyData::SafeDownCast(
+            inInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+    vtkDebugMacro(<<"Scaling poly data");
+
+    if (input == NULL || input->GetPoints() == NULL)
+    {
+        return 1;
+    }
+
+    vtkPolyData *output = vtkPolyData::SafeDownCast(
+            outInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+    // Copy the poly data to the output
+    output->DeepCopy(input);
+
+    switch (this->ScalingMode)
+    {
+    case VTK_SCALE_POLY_COG:
+        this->ScaleUsingCOG(output, this->ScaleFactor);
+        break;
+    case VTK_SCALE_POLY_NORMALS:
+        this->ScaleUsingNormals(input, output, this->ScaleFactor);
+        break;
+    default:
+        break;
+    }
+
+    return 1;
+}
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkjoScalePolyData.h b/bioimagesuite30_src/Segmentation/vtkjoScalePolyData.h
new file mode 100644
index 0000000..738eb91
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkjoScalePolyData.h
@@ -0,0 +1,100 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkjoScalePolyData.h
+ *
+ *  Created on: Mar 13, 2009
+ *      Author: jonofrey
+ */
+// .NAME vtkjoScalePolyData - Scales a vtkPolyData using the data set's
+// points.
+// .SECTION Description
+// vtkjoScalePolyData scales a given vtkPolyData input using the data set's
+// points.  This filter can scale the geometry in two ways:
+// <p>1) Scale the points in the direction of the geometry's center of
+// gravity (COG).  Positive scaling factor values shrink the geometry in
+// towards the COG.  This is the default scaling mode.
+// <p>2) Scale the points in the direction of the geometry's inward facing
+// surface normals.
+// Using negative ScalingFactor values causes the geometry to expand
+// outwards.
+// .SECTION Caveats
+// This filter can result in inverting surface meshes if the scaling factor
+// is too large.  Also, when using the surface normals scaling mode, concave
+// parts of the surface can expand outwards causing the geometry to
+// self-intersect.
+
+#ifndef VTKJOSCALEPOLYDATA_H_
+#define VTKJOSCALEPOLYDATA_H_
+
+#include "vtkPolyDataAlgorithm.h"
+
+#define VTK_SCALE_POLY_COG 0
+#define VTK_SCALE_POLY_NORMALS 1
+
+class vtkjoScalePolyData : public vtkPolyDataAlgorithm
+{
+public:
+    static vtkjoScalePolyData *New();
+    vtkTypeMacro(vtkjoScalePolyData,vtkPolyDataAlgorithm);
+
+    void PrintSelf(ostream& os, vtkIndent indent);
+
+    // Description:
+    // ScaleFactor - the scalar value to shrink the surface by.
+    vtkGetMacro(ScaleFactor, double);
+    vtkSetMacro(ScaleFactor, double);
+
+    // Description:
+    // Set the scaling mode (default: COG)
+    vtkSetClampMacro(ScalingMode, int,
+            VTK_SCALE_POLY_COG, VTK_SCALE_POLY_NORMALS)
+    vtkGetMacro(ScalingMode, int);
+    void SetScalingModeToUseCOG() {
+        this->SetScalingMode(VTK_SCALE_POLY_COG); };
+    void SetScalingModeToUseNormals() {
+        this->SetScalingMode(VTK_SCALE_POLY_NORMALS); };
+
+protected:
+
+    double ScaleFactor;
+    int ScalingMode;
+
+    void ScaleUsingCOG(vtkPolyData* output, double scalar);
+    void ScaleUsingNormals(vtkPolyData* input, vtkPolyData* output, double scalar);
+
+    int RequestData(vtkInformation* request,
+            vtkInformationVector** inputVector,
+            vtkInformationVector* outputVector);
+
+    vtkjoScalePolyData();
+    virtual ~vtkjoScalePolyData();
+};
+
+#endif /* VTKJOSCALEPOLYDATA_H_ */
+
diff --git a/bioimagesuite30_src/Segmentation/vtkjwsSignedDanielssonDistanceMapImageFilter.cpp b/bioimagesuite30_src/Segmentation/vtkjwsSignedDanielssonDistanceMapImageFilter.cpp
new file mode 100644
index 0000000..cbba663
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkjwsSignedDanielssonDistanceMapImageFilter.cpp
@@ -0,0 +1,204 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkjwsSignedDanielssonDistanceMapImageFilter.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkImageImport.h"
+#include "vtkImageExport.h"
+#include "vtkjwsSignedDanielssonDistanceMapImageFilter.h"
+#include "itkSignedDanielssonDistanceMapImageFilter.h"
+#include "itkGrayscaleMorphologicalClosingImageFilter.h"
+#include "itkBinaryBallStructuringElement.h" 
+#include "vtkImageThreshold.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkInformation.h"
+#include "itkImage.h"
+#include "itkVTKImageExport.h"
+#include "itkVTKImageImport.h"
+#include "vtkITKUtility.h"
+
+
+
+//------------------------------------------------------------------------------
+// First a Helper Class
+// -----------------------------------------------------------------------------
+vtkjwsSignedDanielssonDistanceMapImageFilter* vtkjwsSignedDanielssonDistanceMapImageFilter::New()
+{
+  return new vtkjwsSignedDanielssonDistanceMapImageFilter;
+}
+
+
+
+vtkjwsSignedDanielssonDistanceMapImageFilter::vtkjwsSignedDanielssonDistanceMapImageFilter()
+{
+  this->LowerThreshold=100;
+  this->UpperThreshold=2000;
+  this->InValue=3000;
+  this->OutValue=0;
+  this->Radius=1;
+}
+// ----------------------------------------------------------------------------
+vtkjwsSignedDanielssonDistanceMapImageFilter::~vtkjwsSignedDanielssonDistanceMapImageFilter()
+{
+}
+// ---------------------------------------------------------------------------------------------
+template <int ImageDimension>
+int vtkjwsSignedDanielssonDistanceMapImageFilter_RunFilter(vtkImageData* input,vtkImageData* output,vtkjwsSignedDanielssonDistanceMapImageFilter* self)
+{
+  typedef float  PixelType;
+  typedef itk::Image<PixelType,ImageDimension>    ImageType;
+  typedef itk::VTKImageImport<ImageType> ImportType;
+  typedef itk::VTKImageExport<ImageType> ExportType;
+  
+  typedef itk::SignedDanielssonDistanceMapImageFilter<ImageType,ImageType>  DMapFilterType; 
+  typedef itk::BinaryBallStructuringElement<PixelType,ImageDimension>  StructuringElementType;
+  typedef itk::GrayscaleMorphologicalClosingImageFilter<ImageType,ImageType,StructuringElementType >  ClosingFilterType; 
+
+
+  // Step 1: Take VTK Image and make it float
+  vtkImageThreshold* thresholder=vtkImageThreshold::New();
+  thresholder->SetInput(input);
+  thresholder->SetOutputScalarTypeToShort();
+  thresholder->SetOutValue(self->GetOutValue());
+  thresholder->SetInValue(self->GetInValue());
+  thresholder->ThresholdBetween(self->GetLowerThreshold(),self->GetUpperThreshold());
+  thresholder->SetOutputScalarTypeToFloat();
+  thresholder->ReplaceInOn();
+  thresholder->ReplaceOutOn();
+
+  // Step 2: Convert VTK Image to ITK
+  vtkImageExport *vtkInputExporter = vtkImageExport::New();
+  vtkInputExporter->SetInput(thresholder->GetOutput());
+  typename ImportType::Pointer itkInputImporter =  ImportType::New();
+  ConnectPipelines(vtkInputExporter, itkInputImporter);
+  itkInputImporter->Update();
+  
+  // Step 3:
+  // Run Pipeline 
+  StructuringElementType  structuringElement;
+  structuringElement.SetRadius( self->GetRadius() );  // 3x3 structuring element
+  structuringElement.CreateStructuringElement();
+
+  typename ClosingFilterType::Pointer binaryClosing = ClosingFilterType::New();  
+  binaryClosing->SetKernel( structuringElement );
+  binaryClosing->SetInput( itkInputImporter->GetOutput() );
+
+  typename  DMapFilterType::Pointer dmap =    DMapFilterType::New();
+  dmap->SetInput(binaryClosing->GetOutput());
+  dmap->Update();
+
+
+  // Step 4:
+  // Push it out to VTK
+  typename ExportType::Pointer itkExporter = ExportType::New();
+  itkExporter->SetInput(dmap->GetOutput());
+  itkExporter->Update();
+
+  vtkImageImport* vtkImporter=vtkImageImport::New();
+  ConnectPipelines(itkExporter, vtkImporter);
+  vtkImporter->Update();
+
+  output->DeepCopy(vtkImporter->GetOutput());
+  
+  vtkImporter->Delete();
+  thresholder->Delete();
+  vtkInputExporter->Delete();
+  return 1;
+}
+
+
+int vtkjwsSignedDanielssonDistanceMapImageFilter::RunFilter(vtkImageData* input,vtkImageData* output)
+{
+  int dim[3]; input->GetDimensions(dim);
+
+
+  if (dim[2]==1)
+    return vtkjwsSignedDanielssonDistanceMapImageFilter_RunFilter<2>(input,output,this);
+
+  return vtkjwsSignedDanielssonDistanceMapImageFilter_RunFilter<3>(input,output,this);
+}
+// ----------------------------------------------------------------------------
+void vtkjwsSignedDanielssonDistanceMapImageFilter::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkjwsSignedDanielssonDistanceMapImageFilter");
+      return;
+    }
+
+  this->RunFilter(input,output);
+}
+
+
+// Tell the pipeline that the output has same dimensions as input but force SHORT one component
+// --------------------------------------------------------------------------------------------
+int vtkjwsSignedDanielssonDistanceMapImageFilter::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+								     vtkInformationVector *outputVector)
+{
+  vtkInformation *inInfo =  inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  int wholeExtent[6]; inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
+  double sp[3];  inInfo->Get(vtkDataObject::SPACING(), sp);
+  double origin[3];  inInfo->Get(vtkDataObject::ORIGIN(),  origin);
+
+  outInfo->Set(vtkDataObject::ORIGIN(),  origin, 3);
+  outInfo->Set(vtkDataObject::SPACING(),sp , 3);
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6);
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), VTK_SHORT, 1);
+
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Segmentation/vtkjwsSignedDanielssonDistanceMapImageFilter.h b/bioimagesuite30_src/Segmentation/vtkjwsSignedDanielssonDistanceMapImageFilter.h
new file mode 100644
index 0000000..00a5975
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkjwsSignedDanielssonDistanceMapImageFilter.h
@@ -0,0 +1,122 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkjwsSignedDanielssonDistanceMapImageFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkjwsSignedDanielssonDistanceMapImageFilter -- corrects for B0 inhomogeneity in 1-H CSI Data for fat quantification
+
+#ifndef __vtkjwsSignedDanielssonDistanceMapImageFilter_h
+#define __vtkjwsSignedDanielssonDistanceMapImageFilter_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkpxLevelSetUtil.h"
+
+class vtkjwsSignedDanielssonDistanceMapImageFilter : public vtkSimpleImageToImageFilter
+{
+public:
+  static vtkjwsSignedDanielssonDistanceMapImageFilter *New();
+  vtkTypeMacro(vtkjwsSignedDanielssonDistanceMapImageFilter,vtkSimpleImageToImageFilter);
+
+
+  // Description:
+  // Threshold Value
+  vtkSetMacro(LowerThreshold,double);
+  vtkGetMacro(LowerThreshold,double);
+
+  vtkSetMacro(UpperThreshold,double);
+  vtkGetMacro(UpperThreshold,double);
+  
+
+  vtkSetMacro(InValue,double);
+  vtkGetMacro(InValue,double);
+
+
+  vtkSetMacro(OutValue,double);
+  vtkGetMacro(OutValue,double);
+
+
+  vtkSetMacro(Radius,int);
+  vtkGetMacro(Radius,int);
+
+
+protected:
+
+  vtkjwsSignedDanielssonDistanceMapImageFilter();
+  virtual ~vtkjwsSignedDanielssonDistanceMapImageFilter();
+  vtkjwsSignedDanielssonDistanceMapImageFilter(const vtkjwsSignedDanielssonDistanceMapImageFilter&) {};
+  void operator=(const vtkjwsSignedDanielssonDistanceMapImageFilter&) {};
+
+  // Description:
+  // Specify Output Stuff
+  virtual int RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+  // Description
+  // Boilerplate code from filter
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  // Description:
+  // Basic Methods
+  virtual int  RunFilter(vtkImageData* input,vtkImageData* output);
+
+  // Description:
+  // If DoClosing = 1 do closing before Distance Filter
+  double        LowerThreshold;
+  double        UpperThreshold;
+  double        InValue;
+  double        OutValue;
+  int           Radius;
+  
+};
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxAbstractBiasFieldCorrection.cpp b/bioimagesuite30_src/Segmentation/vtkpxAbstractBiasFieldCorrection.cpp
new file mode 100644
index 0000000..dbec442
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxAbstractBiasFieldCorrection.cpp
@@ -0,0 +1,1042 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxNonLinearRegistration.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/01/21 22:35:22 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxAbstractBiasFieldCorrection.h"
+#include "vtkObjectFactory.h"
+#include "pxutil.h"
+#include "vtkpxUtil.h"
+#include "vtkExtractVOI.h"
+#include "vtkpxOptimizer.h"
+#include "vtkbisImageResample.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageGradientMagnitude.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+#include "vtkpxMath.h"
+#include "vtkImageCast.h"
+#include "vtkpxHistogramSegmentation.h"
+#include "vtkpxImageRobustHistogram.h"
+#include "vtkImageExtractComponents.h"
+
+vtkpxAbstractBiasFieldCorrection* vtkpxAbstractBiasFieldCorrection::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxAbstractBiasFieldCorrection");
+  if(ret)
+    {
+    return (vtkpxAbstractBiasFieldCorrection*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxAbstractBiasFieldCorrection;
+  
+}
+
+
+vtkpxAbstractBiasFieldCorrection::vtkpxAbstractBiasFieldCorrection()
+{
+
+  this->StepSize=2.0;
+  this->InternalStepSize=2.0;
+  this->CurrentStepSize=2.0;
+  this->CurrentResolution=2.0;
+  this->LastProgress=0;
+
+  this->ProvideFeedback=1;
+  this->NumberOfIterations=25;
+
+  this->Epsilon=0.003;
+  this->NumberOfLevels=3;
+  this->NumberOfSteps=1;
+  this->Resolution=1.0;
+
+  this->ReferenceImage=NULL;
+  this->SampledReferenceImage=NULL;
+  this->WeightImage=NULL;
+
+  this->BiasField=NULL;
+  this->SampledWeightImage=NULL;
+  this->ClassParameters=NULL;
+  this->Lambda=0.0;
+  this->FixedNumberOfSlices=0;
+
+  this->Histo_NumberOfClasses=3;
+  this->Histo_Iterations=30;
+  this->Histo_Convergence=0.5;
+  this->Histo_NumberOfBins=128;
+  this->Histo_Sigma=1.0;
+  this->Histo_OutlierDetection=0;
+  this->Histo_OutlierProbability=0.0005;
+  this->Histo_PreprocessingMode=2;
+  this->Histo_MaxSigmaRatio=0.05;
+
+  this->MaskImage=NULL;
+  this->Metric=0;
+
+  this->Frame=0;
+
+  strcpy(this->OutputStatus,"");
+}
+
+vtkpxAbstractBiasFieldCorrection::~vtkpxAbstractBiasFieldCorrection() 
+{
+
+
+  if (this->SampledReferenceImage!=NULL)
+    this->SampledReferenceImage->Delete();
+
+  if (this->ReferenceImage!=NULL)
+    this->ReferenceImage->Delete();
+  
+  if (this->SampledWeightImage!=NULL)
+    this->SampledWeightImage->Delete();
+
+  if (this->WeightImage!=NULL)
+    this->WeightImage->Delete();
+
+  if (this->BiasField!=NULL)
+    this->BiasField->Delete();
+
+
+
+
+  this->SetMaskImage(NULL);
+}
+
+const char *vtkpxAbstractBiasFieldCorrection::GetOutputStatus()
+{
+  return this->OutputStatus;
+}
+
+//-------------------------------------------------------------------------
+int vtkpxAbstractBiasFieldCorrection::InitializeAll() 
+{
+  this->NumberOfLevels=Irange(this->NumberOfLevels,1,8);
+  this->NumberOfIterations=Irange(this->NumberOfIterations,1,100);
+  this->NumberOfSteps=Irange(this->NumberOfSteps,1,8);
+
+  double sp[3]; this->ReferenceImage->GetSpacing(sp);
+  this->MinimumResolution=sp[0];
+  
+  if (this->Resolution<0.0)
+    this->InternalResolution=1.0;
+  else
+    this->InternalResolution=Frange(this->Resolution,0.25,50.0);
+
+  this->CurrentResolution=this->InternalResolution;
+
+  this->InternalStepSize=Frange(this->StepSize,0.01,40.0);
+  this->CurrentStepSize=this->InternalStepSize;
+  this->CreateWeightImage(this->ReferenceImage);
+
+
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxAbstractBiasFieldCorrection::CreateWeightImage(vtkImageData* ref) 
+{
+  if (this->WeightImage!=NULL)
+    this->WeightImage->Delete();
+
+  this->WeightImage=vtkImageData::New();
+  this->WeightImage->CopyStructure(ref);
+  this->WeightImage->SetScalarTypeToFloat();
+  this->WeightImage->SetNumberOfScalarComponents(1);
+  this->WeightImage->AllocateScalars();
+
+  vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+  smooth->SetInput(ref);
+  smooth->SetStandardDeviations(1.0,1.0,1.0);
+
+  vtkImageGradientMagnitude* grad=vtkImageGradientMagnitude::New();
+  grad->HandleBoundariesOn();
+  grad->SetInput(smooth->GetOutput());
+  grad->Update();
+
+  vtkImageData* tmp=grad->GetOutput();
+
+  vtkDataArray* magn=tmp->GetPointData()->GetScalars();
+  double r[2]; magn->GetRange(r);
+  double sigma2=pow(r[1]*0.1,2.0);
+
+
+  vtkDataArray* in=ref->GetPointData()->GetScalars();
+  vtkDataArray* wgt=this->WeightImage->GetPointData()->GetScalars();
+  int nt=wgt->GetNumberOfTuples();
+
+  if (this->MaskImage==NULL)
+    {
+      double range[2]; in->GetRange(range);
+      for (int i=0;i<nt;i++)
+	{
+	  float m=in->GetComponent(i,0);
+	  if (m>range[0])
+	    wgt->SetComponent(i,0,1000*(1.0-vtkpxAbstractBiasFieldCorrection::Valley2(magn->GetComponent(i,0),sigma2)));
+	  else
+	    wgt->SetComponent(i,0,0.0);
+	}
+    }
+  else
+    {
+      vtkDataArray* msk=this->MaskImage->GetPointData()->GetScalars();
+      double mrange[2]; msk->GetRange(mrange);
+      double range[2];  in->GetRange(range);
+
+      for (int i=0;i<nt;i++)
+	{
+	  float m=msk->GetComponent(i,0);
+	  float w=in->GetComponent(i,0);
+	  if (m>mrange[0] && w>range[0])
+	    wgt->SetComponent(i,0,1000*(1.0-vtkpxAbstractBiasFieldCorrection::Valley2(magn->GetComponent(i,0),sigma2)));
+	  else
+	    wgt->SetComponent(i,0,0.0);
+	}
+    }
+  grad->Delete();
+  smooth->Delete();
+    //  vtkpxUtil::SaveAnalyze("ap_weight",this->WeightImage,0);
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxAbstractBiasFieldCorrection::InitializeTransformation(int level) 
+{
+  fprintf(stderr,"In vtkpxAbstractBiasFieldCorrection::InitializeTransform\n");
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxAbstractBiasFieldCorrection::Initialize(int level) 
+{
+  double reduction=pow(2.0,double(level-1.0));
+  this->CurrentStepSize=this->InternalStepSize*reduction;
+  this->CurrentResolution=this->InternalResolution*reduction;
+
+
+  double sp[3];  this->ReferenceImage->GetSpacing(sp);
+  int    dim[3]; this->ReferenceImage->GetDimensions(dim);
+
+  /*  if (sp[2]>(sp[1]+sp[0]))
+      this->FixedNumberOfSlices=1;*/
+
+  fprintf(stderr,"Input sp = %.1f,%.1f,%.1f dim=%d,%d,%d fixed_slices=%d\n",sp[0],sp[1],sp[2],dim[0],dim[1],dim[2],
+	  this->FixedNumberOfSlices);
+
+
+
+  vtkbisImageResample* resamp=vtkbisImageResample::New();
+  resamp->SetInput(this->ReferenceImage);
+
+  double outspa[3];
+
+  for (int ia=0;ia<=2;ia++)
+    outspa[ia]=sp[ia]*this->CurrentResolution;
+
+  double minspa=outspa[0];
+  for (int ia=1;ia<=2;ia++)
+    {
+      if (outspa[ia]<minspa)
+	minspa=outspa[ia];
+    }
+
+  for (int ia=0;ia<=2;ia++)
+    {
+      if (outspa[ia]>1.2*minspa)
+	outspa[ia]=1.2*minspa;
+    }
+
+  if (this->FixedNumberOfSlices>0)
+    outspa[2]=sp[2];
+
+  for (int ia=0;ia<=2;ia++)
+    resamp->SetAxisOutputSpacing(ia,outspa[ia]);
+  // Check this!
+  resamp->InterpolateOn();
+  resamp->DebugOff();
+  resamp->Update();
+
+  
+  if (this->SampledReferenceImage!=NULL)
+    this->SampledReferenceImage->Delete();
+  this->SampledReferenceImage=vtkImageData::New();
+  this->SampledReferenceImage->DeepCopy(resamp->GetOutput());
+
+  resamp->SetInput(this->WeightImage);
+  resamp->Modified();
+  resamp->Update();
+
+
+  if (this->SampledWeightImage!=NULL)
+    this->SampledWeightImage->Delete();
+  this->SampledWeightImage=vtkImageData::New();
+  
+  this->SampledWeightImage->ShallowCopy(resamp->GetOutput());
+  resamp->Delete();
+
+  double sp1[3],or1[3],range[2];
+  int   dim1[3];
+
+  this->SampledReferenceImage->GetSpacing(sp1);
+  this->SampledReferenceImage->GetDimensions(dim1);
+  this->SampledReferenceImage->GetOrigin(or1);
+  this->SampledReferenceImage->GetPointData()->GetScalars()->GetRange(range);
+
+  sprintf(this->OutputStatus,"\nEnd Of Initialization Of Level =%d,%d",level,this->NumberOfLevels);
+  sprintf(this->OutputStatus,
+	  "%s\n Reference = %d x %d x %d (%.2f %.2f %.2f) (or=%.1f,%.1f,%.1f) range=%.1f:%.1f\n",
+	  this->OutputStatus,dim1[0],dim1[1],dim1[2],sp1[0],sp1[1],sp1[2],or1[0],or1[1],or1[2],range[0],range[1]);
+
+  vtkDebugMacro(<<this->OutputStatus);
+  fprintf(stderr,"%s\n",this->OutputStatus);
+  this->UpdateProgress(this->LastProgress);
+  this->InitializeTransformation(level);
+  return 1;
+
+}
+//-------------------------------------------------------------------------
+int vtkpxAbstractBiasFieldCorrection::FinalizeAll()
+{
+  return 1;
+}
+//-------------------------------------------------------------------------
+// Compute Registration
+int vtkpxAbstractBiasFieldCorrection::ComputeBiasFit(int level)
+{  
+  return 1;
+}
+//-------------------------------------------------------------------------
+
+double vtkpxAbstractBiasFieldCorrection::Optimize(vtkDoubleArray* grad,double old_similarity,
+						   double step,int level,
+						   double origin[3],double spacing[3],
+						   int dimensions[3],double gridspacing[3])
+{
+  return 0.0;
+}
+//-------------------------------------------------------------------------
+vtkImageData* vtkpxAbstractBiasFieldCorrection::ComputeBiasFieldImage(vtkImageData* ref)
+{
+  return NULL;
+}
+//-------------------------------------------------------------------------
+vtkImageData* vtkpxAbstractBiasFieldCorrection::ComputeMeanPreservingCorrectedImage(vtkImageData* ref,vtkImageData* biasfield)
+{
+  return vtkpxAbstractBiasFieldCorrection::ComputeCorrectedImage(ref,biasfield,1);
+}
+
+vtkImageData* vtkpxAbstractBiasFieldCorrection::ComputeCorrectedImage(vtkImageData* ref,vtkImageData* biasfield)
+{
+  return vtkpxAbstractBiasFieldCorrection::ComputeCorrectedImage(ref,biasfield,0);
+}
+//-------------------------------------------------------------------------
+double  vtkpxAbstractBiasFieldCorrection::ComputeScaleFactor(vtkImageData* ref,vtkImageData* biasfield)
+{
+  if (ref==NULL || biasfield==NULL)
+    {
+      fprintf(stderr,"NULL Inputs to ComputeScaleFactor\n");
+      return 0.0;
+    }
+
+  double typeMax =  ref->GetScalarTypeMax();
+  double range[2];  ref->GetPointData()->GetScalars()->GetRange(range);
+  double brange[2]; biasfield->GetPointData()->GetScalars()->GetRange(brange);
+
+
+  // Find Max Intensity
+  double maximg=range[1];
+  if (fabs(range[0])>range[1])
+    maximg=fabs(range[0]);
+
+  double minb=brange[0];
+  if (minb<0.0001)
+    minb=0.0001;
+
+  double scale_in=1.0;
+  double maxinten=maximg/minb;
+  if (maxinten > typeMax)
+    {
+      scale_in= (typeMax)/(maxinten);
+      fprintf(stderr,"Intensity Scaling = %.2f   (maximg=%.1f,minb=%.2f,maxinten=%.1f,typeMax=%.2f\n",
+	      scale_in,maximg,minb,maxinten,typeMax);
+    }
+  return scale_in;
+
+
+}
+//-------------------------------------------------------------------------
+vtkImageData* vtkpxAbstractBiasFieldCorrection::ComputeCorrectedImage(vtkImageData* ref,vtkImageData* biasfield,int meanpreserving)
+{
+  vtkImageData* output=vtkImageData::New();
+  output->CopyStructure(ref);
+  output->SetNumberOfScalarComponents(ref->GetNumberOfScalarComponents());
+  output->AllocateScalars();
+
+  int ok=vtkpxAbstractBiasFieldCorrection::ComputeCorrectedImage(ref,biasfield,output,meanpreserving);
+  if (ok==0)
+    {
+      fprintf(stderr,"Correction Failed\n");
+      output->Delete();
+      output=NULL;
+    }
+  else
+    {
+      fprintf(stderr,"Correction Succeeded\n");
+    }
+
+  return output;
+}
+// -------------------------------------------------------------------------
+int vtkpxAbstractBiasFieldCorrection::ComputeCorrectedImage(vtkImageData* ref,vtkImageData* biasfield,vtkImageData* output,int meanpreserving)
+{
+  if (ref==NULL || biasfield==NULL || output==NULL)
+    {
+      fprintf(stderr,"NULL Inputs to ComputeCorrectedImage\n");
+      return 0;
+    }
+
+  
+  vtkDataArray* img=ref->GetPointData()->GetScalars();
+  vtkDataArray* bf =biasfield->GetPointData()->GetScalars();
+  vtkDataArray* out =output->GetPointData()->GetScalars();
+
+  int nt=img->GetNumberOfTuples();
+  int nc=img->GetNumberOfComponents();
+
+  if (nt!=bf->GetNumberOfTuples())
+    {
+      fprintf(stderr,"Mismatched ref image and bias field inputs to ComputeCorrectedImage\n");
+      return 0;
+    }
+
+  if (nt!=out->GetNumberOfTuples() || nc!=out->GetNumberOfComponents())
+    {
+      output->CopyStructure(ref);
+      output->SetNumberOfScalarComponents(ref->GetNumberOfScalarComponents());
+      output->AllocateScalars();
+      fprintf(stderr,"Compute Corrected, fixing output ******************************\n");
+      out =output->GetPointData()->GetScalars();
+    }
+   
+
+
+  double sum_in=0.00001;
+  double sum_out=0.00001;
+  double scale_in=vtkpxAbstractBiasFieldCorrection::ComputeScaleFactor(ref,biasfield);
+
+  for (int i=0;i<nt;i++)
+    {
+      double b=bf->GetComponent(i,0);
+      for (int c=0;c<nc;c++)
+	{
+	  double v=img->GetComponent(i,c)*scale_in;
+	  sum_in+=v;
+	  
+	  if (b>0.000)
+	    v=v/b;
+	  sum_out+=v;
+	  out->SetComponent(i,c,v);
+	}
+    }
+
+  if (meanpreserving>0)
+    {
+      double scale=sum_in/sum_out;
+      //      fprintf(stderr,"Mean Preserving Scale =%f (sum_in=%f sum_out=%f)\n",scale,sum_in,sum_out);
+      for (int i=0;i<nt;i++)
+	for (int c=0;c<nc;c++)
+	  out->SetComponent(i,c,out->GetComponent(i,c)*scale);
+    }
+
+  return 1;
+  
+  
+}
+// --------------------------------------------------------------------------------------------------------------------------------------------
+vtkImageData* vtkpxAbstractBiasFieldCorrection::ComputeMaskCorrectedImage(vtkImageData* ref,vtkImageData* biasfield,vtkImageData* mask,
+									  int meanpreserving)
+{
+  if (ref==NULL || biasfield==NULL || mask==NULL)
+    {
+      fprintf(stderr,"NULL Inputs to ComputeCorrectedImage\n");
+      return NULL;
+    }
+
+  vtkDataArray* img=ref->GetPointData()->GetScalars();
+  vtkDataArray* bf =biasfield->GetPointData()->GetScalars();
+  vtkDataArray* msk =mask->GetPointData()->GetScalars();
+
+  int nt=img->GetNumberOfTuples();
+  int nc=img->GetNumberOfComponents();
+
+  if (nt!=bf->GetNumberOfTuples() || nt!=msk->GetNumberOfTuples())
+    {
+      fprintf(stderr,"Mismatched ref image and bias field/mask inputs to ComputeMaskCorrectedImage\n");
+      return NULL;
+    }
+
+  vtkImageData* output=vtkImageData::New();
+  output->CopyStructure(ref);
+  //  output->SetScalarTypeToFloat();
+  output->AllocateScalars();
+  
+  vtkDataArray* out =output->GetPointData()->GetScalars();
+
+  double sum_in=0.00001;
+  double sum_out=0.00001;
+  double scale_in=vtkpxAbstractBiasFieldCorrection::ComputeScaleFactor(ref,biasfield);
+
+  for (int i=0;i<nt;i++)
+    {
+      double m=msk->GetComponent(i,0);
+      if (m>0)
+	{
+	  double b=bf->GetComponent(i,0);
+	  for (int c=0;c<nc;c++)
+	    {
+	      double v=img->GetComponent(i,c)*scale_in;
+	      sum_in+=v;
+	      
+	      if (b>0.000)
+		v=v/b;
+	      sum_out+=v;
+	      
+	      out->SetComponent(i,c,v);
+	    }
+	}
+      else
+	{
+	  for (int c=0;c<nc;c++)
+	    {
+	      double v=img->GetComponent(i,c);
+	      sum_in+=v;
+	      sum_out+=v;
+	      out->SetComponent(i,c,v);
+	    }
+	}
+    }
+
+  if (meanpreserving>0)
+    {
+      double scale=sum_in/sum_out;
+      //      fprintf(stderr,"Mean Preserving Scale =%f (sum_in=%f sum_out=%f)\n",scale,sum_in,sum_out);
+      for (int i=0;i<nt;i++)
+	{
+	  double m=msk->GetComponent(i,0);
+	  if (m>0)
+	    {
+	      for (int c=0;c<nc;c++)
+		out->SetComponent(i,c,out->GetComponent(i,c)*scale);
+	    }
+	}
+    }
+
+  return output;
+  
+  
+}
+//-------------------------------------------------------------------------
+// Log Image
+//-------------------------------------------------------------------------
+vtkImageData* vtkpxAbstractBiasFieldCorrection::ComputeMeanPreservingCorrectedLogarithmImage(vtkImageData* logref,vtkImageData* logbiasfield)
+{
+  return vtkpxAbstractBiasFieldCorrection::ComputeCorrectedLogarithmImage(logref,logbiasfield,1);
+}
+
+vtkImageData* vtkpxAbstractBiasFieldCorrection::ComputeCorrectedLogarithmImage(vtkImageData* logref,vtkImageData* logbiasfield)
+{
+  return vtkpxAbstractBiasFieldCorrection::ComputeCorrectedLogarithmImage(logref,logbiasfield,0);
+}
+
+vtkImageData* vtkpxAbstractBiasFieldCorrection::ComputeCorrectedLogarithmImage(vtkImageData* logref,vtkImageData* logbiasfield,int meanpreserving)
+{
+  if (logref==NULL || logbiasfield==NULL)
+    {
+      fprintf(stderr,"NULL Inputs to ComputeCorrectedLogImage\n");
+      return NULL;
+    }
+
+  vtkDataArray* img=logref->GetPointData()->GetScalars();
+  vtkDataArray* bf =logbiasfield->GetPointData()->GetScalars();
+
+  int nt=img->GetNumberOfTuples();
+  int nc=img->GetNumberOfComponents();
+
+  if (nt!=bf->GetNumberOfTuples())
+    {
+      fprintf(stderr,"Mismatched logref image and bias field inputs to ComputeCorrectedImage\n");
+      return NULL;
+    }
+
+  vtkImageData* output=vtkImageData::New();
+  output->CopyStructure(logref);
+  //  output->SetScalarTypeToFloat();
+  output->AllocateScalars();
+  
+  vtkDataArray* out =output->GetPointData()->GetScalars();
+
+  double sum_in=0.00001;
+  double sum_out=0.00001;
+  for (int i=0;i<nt;i++)
+    {
+      double b=bf->GetComponent(i,0);
+      for (int c=0;c<nc;c++)
+	{
+	  double v=img->GetComponent(i,c);
+	  sum_in+=v;
+	  
+	  v=v-b;
+	  sum_out+=v;
+	  out->SetComponent(i,c,v);
+	}
+    }
+
+  if (meanpreserving>0)
+    {
+      double scale=sum_in/sum_out;
+      //      fprintf(stderr,"Mean Preserving Scale =%f (sum_in=%f sum_out=%f)\n",scale,sum_in,sum_out);
+      for (int i=0;i<nt;i++)
+	for (int c=0;c<nc;c++)
+	  out->SetComponent(i,c,out->GetComponent(i,c)*scale);
+    }
+
+  return output;
+  
+  
+}
+//-------------------------------------------------------------------------
+int vtkpxAbstractBiasFieldCorrection::ExponentiateBiasField(vtkImageData* logbiasfield)
+{
+  if (logbiasfield==NULL)
+    {
+      fprintf(stderr,"NULL Inputs to ExponentiateBiasField\n");
+      return 0;
+    }
+
+  vtkDataArray* bf =logbiasfield->GetPointData()->GetScalars();
+  int nt=bf->GetNumberOfTuples();
+  for (int i=0;i<nt;i++)
+    bf->SetComponent(i,0,exp(bf->GetComponent(i,0)));
+  
+  return 1;
+}
+//-------------------------------------------------------------------------
+vtkFloatArray* vtkpxAbstractBiasFieldCorrection::ComputeLogClassParameters(vtkFloatArray* initial)
+{
+  if (initial==NULL)
+    return NULL;
+
+
+  vtkFloatArray* initiallog=vtkFloatArray::New();
+  initiallog->DeepCopy(initial);
+  int nt=initiallog->GetNumberOfTuples();
+  for (int i=0;i<nt;i++)
+    {
+      double m=initiallog->GetComponent(i,0);
+      double s=initiallog->GetComponent(i,1);
+      
+      fprintf(stderr," Class %d %.2f + %.2f ---> ",i+1,m,s);
+
+      if (m>1.0)
+	m=log(m);
+      else
+	m=0.0;
+      
+      /*      if (s>1.0)
+	s=log(s);
+	else*/
+	s=1.0;
+      
+      initiallog->SetComponent(i,0,m);
+      initiallog->SetComponent(i,1,s);
+
+      fprintf(stderr,"  %.2f + %.2f \n",m,s);
+    }
+  return initiallog;
+}
+//-------------------------------------------------------------------------
+vtkFloatArray* vtkpxAbstractBiasFieldCorrection::ComputeClassParameters(vtkImageData* input,vtkFloatArray *initial)
+{
+  if (input==NULL)
+    return NULL;
+
+  vtkpxHistogramSegmentation* histo=vtkpxHistogramSegmentation::New();
+  histo->SetInput(input);
+  histo->SetInitialParameters(initial);
+  histo->SetNumberOfClasses(this->Histo_NumberOfClasses);
+  histo->SetIterations(this->Histo_Iterations);
+  histo->SetSigma(this->Histo_Sigma);
+  histo->SetConvergence(this->Histo_Convergence);
+  histo->SetNumberOfBins(this->Histo_NumberOfBins);
+  histo->SetOutlierProbability(this->Histo_OutlierProbability);
+  histo->SetOutlierDetection(this->Histo_OutlierDetection);
+  histo->SetPreprocessingMode(this->Histo_PreprocessingMode);
+  //  histo->SetMaskImage(this->WeightImage);
+  histo->GenerateLabelsOff();
+  histo->SetMaxSigmaRatio(this->Histo_MaxSigmaRatio);
+  histo->Update();
+
+  vtkFloatArray* p=vtkFloatArray::New();
+  p->DeepCopy(histo->GetParameters());
+  
+  histo->Delete();
+  return p;
+}
+
+int vtkpxAbstractBiasFieldCorrection::ComputeAndSetClassParameters(vtkImageData* input,vtkFloatArray* initial)
+{
+  vtkFloatArray* p=this->ComputeClassParameters(input,initial);
+  if (p==NULL)
+    return 0;
+
+  if (this->Histo_OutlierDetection==0)
+    {
+      this->SetClassParameters(p);
+    }
+  else
+    {
+      vtkFloatArray* phat=vtkFloatArray::New();
+      int nt=p->GetNumberOfTuples();
+      phat->SetNumberOfComponents(p->GetNumberOfComponents());
+      phat->SetNumberOfTuples(nt-1);
+
+      for (int i=0;i<nt-1;i++)
+	for (int j=0;j<p->GetNumberOfComponents();j++)
+	  phat->SetComponent(i,j,p->GetComponent(i,j));
+
+      this->SetClassParameters(phat);
+      phat->Delete();
+    }
+  p->Delete();
+  return 1;
+}
+//-------------------------------------------------------------------------
+double vtkpxAbstractBiasFieldCorrection::Evaluate()
+{
+  this->LastSimilarity=0.0;
+  this->LastSmoothness=0.0;
+  return 0.0;
+}
+
+//-------------------------------------------------------------------------
+void vtkpxAbstractBiasFieldCorrection::PrintInformation() 
+{
+  
+}
+//-------------------------------------------------------------------------
+
+void vtkpxAbstractBiasFieldCorrection::GenerateOutput(int level, int step,int iter,double stepsize,double actualSimilarity)
+{
+  if (iter>=100)
+    iter=99;
+
+  sprintf(this->OutputStatus,"Level=%2d Step=%2d iter=%2d stepsize=%.3f: tot=%8.6f (sim=%8.6f sm=%8.6f (dist=%.2f))",
+	  level,step,iter,stepsize,actualSimilarity,
+	  this->LastSimilarity,this->LastSmoothness*this->Lambda,
+	  this->LastSmoothness);
+  //  this->UpdateProgress(this->LastProgress);
+
+  double sc=1.0/double(this->NumberOfLevels);
+  double pog=(double(step)/double(this->NumberOfSteps+1) + double(this->NumberOfLevels-level))*sc;
+  this->LastProgress=pog;
+  this->UpdateProgress(pog);
+  vtkDebugMacro(<<this->OutputStatus);
+  return;
+}
+
+//-------------------------------------------------------------------------
+// Optimizer Stuff 
+//-------------------------------------------------------------------------
+void vtkpxAbstractBiasFieldCorrection::SetCurrentParameters(vtkDoubleArray* param)
+{
+  return;
+}
+//-------------------------------------------------------------------------
+void vtkpxAbstractBiasFieldCorrection::GetCurrentParameters(vtkDoubleArray* param)
+{
+  return;
+}
+//-------------------------------------------------------------------------
+double vtkpxAbstractBiasFieldCorrection::OptimizerValue(vtkDoubleArray* params)
+{
+  this->SetCurrentParameters(params);
+  return -this->Evaluate();
+}
+//-------------------------------------------------------------------------
+double vtkpxAbstractBiasFieldCorrection::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+
+{
+  return 0.0;
+}
+
+
+double vtkpxAbstractBiasFieldCorrection::OnBeginIteration(vtkDoubleArray* params)
+{
+  return 0.0;
+}
+
+//-------------------------------------------------------------------------
+// Static Function Stuff
+//-------------------------------------------------------------------------
+double vtkpxAbstractBiasFieldCorrection::CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output)
+{
+  return ((vtkpxAbstractBiasFieldCorrection*)self)->OptimizerGradient(position,output);
+}
+
+double vtkpxAbstractBiasFieldCorrection::CalculateFunction(vtkObject* self,vtkDoubleArray* position)
+{
+  return ((vtkpxAbstractBiasFieldCorrection*)self)->OptimizerValue(position);
+}
+
+double vtkpxAbstractBiasFieldCorrection::OnBeginIteration(vtkObject* self,vtkDoubleArray* position)
+{
+  return ((vtkpxAbstractBiasFieldCorrection*)self)->OnBeginIteration(position);
+}
+
+void vtkpxAbstractBiasFieldCorrection::OptimizerFeedback(vtkObject* self,const char* line,double val)
+{
+  ((vtkpxAbstractBiasFieldCorrection*)self)->SetOutputStatus(line,val);
+}
+//-------------------------------------------------------------------------
+
+void vtkpxAbstractBiasFieldCorrection::SetOutputStatus(const char* line,double v)
+{
+  sprintf(this->OutputStatus,"**Opt=%s (%.5f)\n",line,v);
+  vtkDebugMacro(<<this->OutputStatus);    
+  this->UpdateProgress(this->LastProgress);
+}
+//-------------------------------------------------------------------------
+int vtkpxAbstractBiasFieldCorrection::CheckInputsAndCreateReferenceImage(vtkImageData* input)
+{
+  if (input==NULL)
+    return -1;
+
+  int nc=input->GetNumberOfScalarComponents();
+  fprintf(stderr,"Input had %d frames",nc);
+
+  if (this->Frame<0)
+    this->Frame=0;
+  else if (this->Frame>=nc)
+    this->Frame=nc-1;
+
+  if (this->ReferenceImage!=NULL)
+    this->ReferenceImage->Delete();
+  this->ReferenceImage=vtkImageData::New();
+
+  if (nc==1)
+    {
+      this->ReferenceImage->ShallowCopy(input);
+    }
+  else
+    {
+      // Check this code -- it was giving a freeze on Windows XP Home if there was
+      // only one component!
+      vtkImageExtractComponents* extr=vtkImageExtractComponents::New();
+      extr->SetInput(input);
+      extr->SetComponents(this->Frame);
+      extr->Update();
+      this->ReferenceImage->ShallowCopy(extr->GetOutput());
+      fprintf(stderr,"Extracting Frame %d for Bias Field Correction\n",this->Frame);
+    }
+
+  if (this->MaskImage==NULL)
+    return 0;
+
+
+  int dim[3]; this->MaskImage->GetDimensions(dim);
+  int dam[3]; this->ReferenceImage->GetDimensions(dam);
+
+  int sum=0;
+  for (int i=0;i<=2;i++)
+    sum+=abs(dim[i]-dam[i]);
+
+  if (sum==0)
+    return 1;
+
+  this->SetMaskImage(NULL);
+  return 0;
+}
+//-------------------------------------------------------------------------
+void vtkpxAbstractBiasFieldCorrection::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  this->CheckInputsAndCreateReferenceImage(input);
+  return;
+}
+//-------------------------------------------------------------------------
+vtkImageData* vtkpxAbstractBiasFieldCorrection::GenerateSynthetic(int width,double factor)
+{
+  if (width<16)
+    width=16;
+  else if (width>256)
+    width=256;
+
+  if (factor < 0.000001)
+    factor=0.000001;
+  else if (factor>0.1)
+    factor=0.1;
+
+  int offset=width/7;
+
+  vtkImageData* tmp=vtkImageData::New();
+  tmp->SetDimensions(width,width,width);
+  tmp->SetScalarTypeToShort();
+  tmp->AllocateScalars();
+
+  int mid=width/2;
+
+  for (int slice=0;slice<width;slice++)
+    for (int j=0;j<width;j++)
+      {
+	int count=0;
+	int mode=0;
+	for (int i=0;i<width;i++)
+	  {
+	    float v=0.0;
+	    if (mode==0)
+	      v=vtkpxMath::GaussianRandom()*5.0+100.0;
+	    else
+	      v=vtkpxMath::GaussianRandom()*5.0+50.0;
+	    
+
+	    float dist2=pow(float(i-mid),float(2.0))+pow(float(j-mid),float(2.0))+pow(float(slice-mid),float(2.0));
+	    float dist=sqrt(dist2);
+	    
+	    double newv=v*(1.0-(factor*dist)*(factor*dist));
+
+	    if (newv<0.0)
+	      newv=0.0;
+	    
+	    tmp->SetScalarComponentFromDouble(i,j,slice,0,newv);
+	    ++count;
+	    if (count==offset)
+	      {
+		mode=1-mode;
+		count=0;
+	      }
+	  }
+      }
+  return tmp;
+}
+// -----------------------------------------------------------------------------------
+vtkImageData* vtkpxAbstractBiasFieldCorrection::CreateLogReferenceImage(vtkImageData* input)
+{
+  if (input==NULL)
+    {
+      fprintf(stderr,"Error NULL input in Log Reference Input\n");
+      return NULL;
+    }
+
+  vtkImageData* refimage=vtkImageData::New();
+  refimage->CopyStructure(input);
+  refimage->AllocateScalars();
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* ref=refimage->GetPointData()->GetScalars();
+
+  int nt=inp->GetNumberOfTuples();
+  int nc=inp->GetNumberOfComponents();
+
+  for (int i=0;i<nt;i++)
+    for (int j=0;j<nc;j++)
+      {
+	double v=inp->GetComponent(i,j);
+	if (v>1.0)
+	  ref->SetComponent(i,j,log(v));
+	else
+	  ref->SetComponent(i,j,0.0);
+      }
+  return refimage;
+}
+
+// -----------------------------------------------------------------------------------
+vtkImageData* vtkpxAbstractBiasFieldCorrection::ComputeRatioBiasFieldImage(vtkImageData* original,vtkImageData* corrected)
+{
+  if (original==NULL || corrected==NULL)
+    {
+      fprintf(stderr,"Error NULL input ComputeRatioBiasFieldImage\n");
+      return NULL;
+    }
+
+  int np1=original->GetNumberOfPoints();
+  int np2=corrected->GetNumberOfPoints();
+  
+  if (np1!=np2)
+    {
+      fprintf(stderr,"Unqueal Size Images in ComputeRatioBiasFieldImage\n");
+      return NULL;
+
+    }
+
+  vtkImageData* bfield=vtkImageData::New();
+  bfield->CopyStructure(corrected);
+  bfield->SetNumberOfScalarComponents(1);
+  bfield->SetScalarTypeToFloat();
+  bfield->AllocateScalars();
+
+  vtkDataArray* orig =original->GetPointData()->GetScalars();
+  vtkDataArray* corr =corrected->GetPointData()->GetScalars();
+  vtkDataArray* bfld =bfield->GetPointData()->GetScalars();
+
+  bfld->FillComponent(0,1.0);
+
+  for (int i=0;i<np1;i++)
+    {
+      double x=orig->GetComponent(i,0);
+      double y=corr->GetComponent(i,0);
+      // y=x/b --> b=x/y
+
+      if (fabs(y)>1.0)
+	bfld->SetComponent(i,0,x/y);
+    }
+
+  return bfield;
+}
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxAbstractBiasFieldCorrection.h b/bioimagesuite30_src/Segmentation/vtkpxAbstractBiasFieldCorrection.h
new file mode 100644
index 0000000..d4e6dc2
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxAbstractBiasFieldCorrection.h
@@ -0,0 +1,381 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxAbstractBiasFieldCorrection.h,v $
+  Language:  C++
+  Date:      $Date: 2002/04/16 13:19:58 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxAbstractBiasFieldCorrection - Filter for ffd registration based on voxel similarity measures.
+
+// .SECTION Description
+// This class implements a registration filter for the non-rigid registration
+// of images.
+
+
+#ifndef _VTKPXAbstractBiasFieldCorrection_H
+#define _VTKPXAbstractBiasFieldCorrection_H
+
+#include "vtkImageData.h"
+#include "vtkDoubleArray.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkFloatArray.h"
+
+
+class  vtkpxAbstractBiasFieldCorrection : public vtkpxSimpleImageToImageFilter {
+
+public:
+  static vtkpxAbstractBiasFieldCorrection* New();
+  vtkTypeMacro(vtkpxAbstractBiasFieldCorrection,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Print information about the progress of the registration
+  void PrintInformation();
+
+  // Description:
+  // Feedback Stuff
+  vtkSetMacro(ProvideFeedback,int);
+  vtkGetMacro(ProvideFeedback,int);
+  vtkBooleanMacro(ProvideFeedback,int);
+
+
+  // Description:
+  // Feedback Stuff
+  vtkSetMacro(FixedNumberOfSlices,int);
+  vtkGetMacro(FixedNumberOfSlices,int);
+  vtkBooleanMacro(FixedNumberOfSlices,int);
+
+
+  // Description:
+  // NumberOfLevels, NumberOfSteps, Resolution
+  vtkSetMacro(NumberOfLevels,int);
+  vtkGetMacro(NumberOfLevels,int);
+  vtkSetMacro(NumberOfIterations,int);
+  vtkGetMacro(NumberOfIterations,int);
+  vtkSetMacro(NumberOfSteps,int);
+  vtkGetMacro(NumberOfSteps,int);
+  vtkSetMacro(Resolution,double);
+  vtkGetMacro(Resolution,double);
+  vtkSetMacro(StepSize,double);
+  vtkGetMacro(StepSize,double);
+
+  // Description:
+  // Frame
+  // Selects the frame to use for correction in 4D images (3D + t)
+  vtkSetMacro(Frame,int);
+  vtkGetMacro(Frame,int);
+
+
+  // Description:
+  // These are needed for the Optimizer 
+  static void  OptimizerFeedback(vtkObject* self,const char* line,double val);
+  static double CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output);
+  static double CalculateFunction(vtkObject* self,vtkDoubleArray* position);
+  static double OnBeginIteration(vtkObject* self,vtkDoubleArray* position);
+  
+
+  // Run Optimization for Level level
+  virtual int ComputeBiasFit(int level);
+  
+  // Description:
+  // Get The Weight Image
+  vtkGetObjectMacro(WeightImage,vtkImageData);
+  vtkGetObjectMacro(BiasField,vtkImageData);
+
+  // Description:
+  // Get/Set the Mask Image
+  vtkSetObjectMacro(MaskImage,vtkImageData);
+  vtkGetObjectMacro(MaskImage,vtkImageData);
+
+  // Description:
+  // Get Internal Transformation Stuff
+  vtkGetObjectMacro(ClassParameters,vtkFloatArray);
+  vtkSetObjectMacro(ClassParameters,vtkFloatArray);
+
+  // Description:
+  // Epsilon is the convergence limit (default=0.0001);
+  vtkGetMacro(Epsilon,double);
+  vtkSetClampMacro(Epsilon,double,0.0001,0.1);
+
+  // Description:
+  // Lambda is the smoothness weight
+  vtkGetMacro(Lambda,double);
+  vtkSetClampMacro(Lambda,double,0.0,1.0);
+
+  // Description:
+  // Metric
+  // 0 -- pabic multi-valley stuff
+  // 1 -- entropy
+  // 2 -- input itself is bias field
+  vtkGetMacro(Metric,int);
+  vtkSetClampMacro(Metric,int,0,2);
+  virtual void SetMetricToPABIC()           { this->SetMetric(0);}
+  virtual void SetMetricToEntropy()         { this->SetMetric(1);}
+  virtual void SetMetricToMinimumVariance() { this->SetMetric(2);}
+
+
+  // Description:
+  // Valley Function
+  static double Valley(double x,double sigma) { double x2=x*x; return x2/(x2+sigma*sigma+0.001);}
+  static double Valley2(double x,double sigma2) { double x2=x*x; return x2/(x2+sigma2+0.001);}
+
+  // GetOutputStatus 
+  virtual void SetOutputStatus(const char* line,double v);
+  const char *GetOutputStatus();
+
+  // Description:
+  // Synthetic Data
+  vtkImageData* GenerateSynthetic(int width,double factor);
+
+
+    // Description:
+  // Outlier Class
+  vtkSetClampMacro(Histo_OutlierDetection,int,0,1);
+  vtkGetMacro(Histo_OutlierDetection,int);
+  vtkBooleanMacro(Histo_OutlierDetection,int);
+
+
+  // Description:
+  // Outlier Probability
+  vtkSetMacro(Histo_OutlierProbability,float);
+  vtkGetMacro(Histo_OutlierProbability,float);
+
+
+  // Description:
+  // Outlier Probability
+  vtkSetClampMacro(Histo_MaxSigmaRatio,float,0.1,1.0);
+  vtkGetMacro(Histo_MaxSigmaRatio,float);
+
+  // Description:
+  // Number Of Classes
+  vtkGetMacro(Histo_NumberOfClasses,int);
+  vtkSetClampMacro(Histo_NumberOfClasses,int,2,10);
+
+
+  // Description:
+  // Number Of Iterations
+  vtkGetMacro(Histo_NumberOfBins,int);
+  vtkSetClampMacro(Histo_NumberOfBins,int,4,1024);
+
+  // Description:
+  // Convergence for CMeans Values (<1.0)
+  vtkGetMacro(Histo_Convergence,float);
+  vtkSetClampMacro(Histo_Convergence,float,0.05,100);
+
+  // Description:
+  // Histogram Sigma
+  vtkGetMacro(Histo_Sigma,float);
+  vtkSetClampMacro(Histo_Sigma,float,0.05,5.0);
+
+  // Description:
+  // Number Of Iterations
+  vtkGetMacro(Histo_Iterations,int);
+  vtkSetClampMacro(Histo_Iterations,int,0,200);
+
+  // Description:
+  // Number Of Iterations
+  vtkGetMacro(Histo_PreprocessingMode,int);
+  vtkSetClampMacro(Histo_PreprocessingMode,int,0,2);
+
+  // Description:
+  // Compute Corrected Image 
+  static double        ComputeScaleFactor(vtkImageData* ref,vtkImageData* biasfield);  
+  static vtkImageData* ComputeCorrectedImage(vtkImageData* ref,vtkImageData* biasfield);
+  static vtkImageData* ComputeMeanPreservingCorrectedImage(vtkImageData* ref,vtkImageData* biasfield);
+  static vtkImageData* ComputeCorrectedImage(vtkImageData* ref,vtkImageData* biasfield,int meanpreserving);
+
+  static int ComputeCorrectedImage(vtkImageData* ref,vtkImageData* biasfield,vtkImageData* fixedimage,int meanpreserving);
+
+
+  // Separate
+  static vtkImageData* ComputeMaskCorrectedImage(vtkImageData* ref,vtkImageData* biasfield,vtkImageData* Mask,int meanpreserving);
+
+  // Description:
+  // Compute Corrected Log Image 
+  static vtkImageData* ComputeCorrectedLogarithmImage(vtkImageData* logref,vtkImageData* logbiasfield);
+  static vtkImageData* ComputeMeanPreservingCorrectedLogarithmImage(vtkImageData* logref,vtkImageData* logbiasfield);
+  static vtkImageData* ComputeCorrectedLogarithmImage(vtkImageData* logref,vtkImageData* logbiasfield,int meanpreserving);
+
+  // Description:
+  // Exponentiate Bias Field
+  static int ExponentiateBiasField(vtkImageData* biasfield);
+
+  // Description:
+  static vtkImageData* CreateLogReferenceImage(vtkImageData* input);
+
+  // Description:
+  // Compute Bias Field From Two Images
+  static vtkImageData* ComputeRatioBiasFieldImage(vtkImageData* original,vtkImageData* corrected);
+  
+
+protected:
+
+  // Make all these protected 
+  // Constructor
+  vtkpxAbstractBiasFieldCorrection();
+  virtual ~vtkpxAbstractBiasFieldCorrection();
+  vtkpxAbstractBiasFieldCorrection(const vtkpxAbstractBiasFieldCorrection&) {};
+  void operator=(const vtkpxAbstractBiasFieldCorrection&) {};
+
+  // Description:
+  // Execute Stuff 
+  virtual void SimpleExecute(vtkImageData* in,vtkImageData* out);
+
+  // Description:
+  // Set Convergence Limit
+  double Epsilon;
+
+  // Description:
+  // Initial set up for the registration at all levels
+  virtual int InitializeAll();
+
+  // Description:
+  // Optimize for step size = step
+  virtual double Optimize(vtkDoubleArray* grad,double old_similarity,double step,int level,
+			  double origin[3],double spacing[3],int dimensions[3],
+			  double gridspacing[3]);
+
+  // Description:
+  virtual double Evaluate();
+
+  // Description:
+  // Create Bias Field Image
+  virtual vtkImageData* ComputeBiasFieldImage(vtkImageData* ref);
+
+
+  // Description:
+  // Compute Class Parameters
+  virtual vtkFloatArray* ComputeLogClassParameters(vtkFloatArray* parameters);
+  virtual vtkFloatArray* ComputeClassParameters(vtkImageData* input,vtkFloatArray* initial=NULL);
+  virtual int ComputeAndSetClassParameters(vtkImageData* input,vtkFloatArray* initial=NULL);
+
+  // Description:
+  // Check Mask Image
+  virtual int CheckInputsAndCreateReferenceImage(vtkImageData* input);
+
+  // Description:
+  // Initial set up for the registration at a multiresolution level
+  virtual int Initialize(int);
+  
+  // Description:
+  // Called from Initialize to Initialize the Transformation
+  virtual int InitializeTransformation(int);
+
+  // Description:
+  // Create Weight Image based on partial voluming
+  virtual int CreateWeightImage(vtkImageData* ref);
+
+  // Description:
+  // Final set up for the registration at a multiresolution level
+  virtual int FinalizeAll();
+
+
+  // Description:
+  // Generate Output
+  virtual void GenerateOutput(int level, int step,int iter,double stepsize,double simil);
+
+
+  // Description:
+  // Needed for Optimizer
+  virtual void   SetCurrentParameters(vtkDoubleArray* par);
+  virtual void   GetCurrentParameters(vtkDoubleArray* par);
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+  virtual double OnBeginIteration(vtkDoubleArray* params);
+
+  // Description:
+  // More Variables
+  int ProvideFeedback;
+  int NumberOfLevels;
+  int NumberOfIterations;
+  int NumberOfSteps;
+  int FixedNumberOfSlices;
+  double Resolution;
+  double MinimumResolution;
+  double InternalResolution;
+  double InternalStepSize;
+  double LastSmoothness;
+  double LastSimilarity;
+  double CurrentResolution;
+  double CurrentStepSize;
+  double StepSize;
+  double Lambda;
+  int  Metric;
+
+  vtkImageData* SampledReferenceImage;
+  vtkImageData* ReferenceImage;
+  vtkImageData* SampledWeightImage;
+  vtkImageData* WeightImage;
+  vtkImageData* BiasField;
+  vtkImageData* MaskImage;
+  vtkFloatArray* ClassParameters;
+
+  char  OutputStatus[500];
+  double LastProgress;
+
+
+  int   Histo_OutlierDetection;
+  float Histo_OutlierProbability;
+  int   Histo_NumberOfClasses;
+  int   Histo_NumberOfBins;
+  float Histo_Convergence;
+  float Histo_MaxSigmaRatio;
+  float Histo_Sigma;
+  int   Histo_Iterations;
+  int   Histo_PreprocessingMode;
+  int   Frame;
+
+
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxBaseLevelSetFilter.cpp b/bioimagesuite30_src/Segmentation/vtkpxBaseLevelSetFilter.cpp
new file mode 100644
index 0000000..6193af3
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxBaseLevelSetFilter.cpp
@@ -0,0 +1,143 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxGeodesicLevelSetFilter.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxBaseLevelSetFilter.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+
+vtkpxBaseLevelSetFilter::vtkpxBaseLevelSetFilter()
+{
+  this->InitialLevelSet=NULL;
+  this->InitialPoints=NULL;
+  this->InitialDistance=2.0;
+  this->RMSError=0.01;
+  this->LevelsetIterations=400;
+  this->InputLevelSet=NULL;
+  this->IterationSaveOrientation=0;
+  this->IterationSaveFrequency=50;
+  this->IterationSave=0;
+  this->IterationName=NULL; this->SetIterationName("patient");
+  this->PropagationWeight=0.1;
+  this->CurvatureWeight=1.0;
+  this->AdvectionWeight=0.0;
+  this->UpdatePercentage=1.01;
+  this->OutputStatus=NULL; this->SetOutputStatus("waiting");
+  this->RealIteration=1;
+}
+// ----------------------------------------------------------------------------
+vtkpxBaseLevelSetFilter::~vtkpxBaseLevelSetFilter()
+{
+  this->SetInitialLevelSet(NULL);
+  this->SetInitialPoints(NULL);
+
+  if (this->InputLevelSet!=NULL)
+    {
+      this->InputLevelSet->Delete();
+      this->InputLevelSet=NULL;
+    }
+
+  if (this->IterationName!=NULL)
+    delete [] IterationName;
+
+  if (this->OutputStatus!=NULL)
+    delete [] OutputStatus;
+
+}
+// ---------------------------------------------------------------------------------------------
+int vtkpxBaseLevelSetFilter::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+						vtkInformationVector *outputVector)
+{
+  vtkInformation *inInfo =  inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  int wholeExtent[6]; inInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), wholeExtent);
+  double sp[3];  inInfo->Get(vtkDataObject::SPACING(), sp);
+  double origin[3];  inInfo->Get(vtkDataObject::ORIGIN(),  origin);
+
+  outInfo->Set(vtkDataObject::ORIGIN(),  origin, 3);
+  outInfo->Set(vtkDataObject::SPACING(),sp , 3);
+  outInfo->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),wholeExtent,6);
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), VTK_FLOAT, 1);
+
+  return 1;
+}
+// ----------------------------------------------------------------------------
+int vtkpxBaseLevelSetFilter::GenerateInputLevelSet(vtkImageData* input,float factor)
+{
+  if (this->InputLevelSet!=NULL)
+    this->InputLevelSet->Delete();
+  this->InputLevelSet=NULL;
+
+  // If Initial Level Set Exists just copy it 
+
+  if (this->InitialLevelSet!=NULL)
+    {
+      this->InputLevelSet=vtkImageData::New();
+      vtkpxLevelSetUtil::ResliceDistanceMap(this->InputLevelSet,this->InitialLevelSet,input);
+      return 1;
+    }
+
+  if (this->InitialPoints==NULL)
+    return 0;
+
+  if (this->InitialPoints->GetNumberOfPoints()<1)
+    return 0;
+
+  this->InputLevelSet=vtkpxLevelSetUtil::GenerateInputLevelSet(input,this->InitialPoints,this->InitialDistance,factor);
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxBaseLevelSetFilter.h b/bioimagesuite30_src/Segmentation/vtkpxBaseLevelSetFilter.h
new file mode 100644
index 0000000..5a62481
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxBaseLevelSetFilter.h
@@ -0,0 +1,188 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxBaseLevelSetFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxBaseLevelSetFilter -- corrects for B0 inhomogeneity in 1-H CSI Data for fat quantification
+
+#ifndef __vtkpxBaseLevelSetFilter_h
+#define __vtkpxBaseLevelSetFilter_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkpxLevelSetUtil.h"
+
+class vtkpxBaseLevelSetFilter : public vtkSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkpxBaseLevelSetFilter,vtkSimpleImageToImageFilter);
+
+  // Part 1 -- Input Seeds or Levelset (if the later is not NULL use it first)
+  vtkSetObjectMacro(InitialLevelSet,vtkImageData);
+  vtkGetObjectMacro(InitialLevelSet,vtkImageData);
+
+  vtkSetObjectMacro(InitialPoints,vtkPoints);
+  vtkGetObjectMacro(InitialPoints,vtkPoints);
+
+  // Gradient Scale
+  vtkSetClampMacro(InitialDistance,float,1.0,10.0);
+  vtkGetMacro(InitialDistance,float);
+  
+
+  // Part 2 -- Actual Levelset Stuff
+
+  // RMS Errors
+  vtkSetClampMacro(RMSError,float,0.0,1.0);
+  vtkGetMacro(RMSError,float);
+
+  // LevelsetIterations
+  vtkSetClampMacro(LevelsetIterations,int,1,1000);
+  vtkGetMacro(LevelsetIterations,int);
+
+  // Description::
+  // Internal Stuff
+  vtkGetObjectMacro(InputLevelSet,vtkImageData);
+
+
+  // Description:
+  // Debug Output 
+  vtkSetStringMacro(IterationName);
+  vtkGetStringMacro(IterationName);
+
+  // Description:
+  // Last Output
+  vtkSetStringMacro(OutputStatus);
+  vtkGetStringMacro(OutputStatus);
+
+
+  // Description:
+  // Debug Save On
+  vtkSetClampMacro(IterationSave,int,0,1);
+  vtkGetMacro(IterationSave,int);
+  vtkBooleanMacro(IterationSave,int);
+
+  vtkSetClampMacro(IterationSaveFrequency,int,1,1000000);
+  vtkGetMacro(IterationSaveFrequency,int);
+  vtkBooleanMacro(IterationSaveFrequency,int);
+
+  vtkSetClampMacro(IterationSaveOrientation,int,0,2);
+  vtkGetMacro(IterationSaveOrientation,int);
+  vtkBooleanMacro(IterationSaveOrientation,int);
+ 
+  // Part 3 -- Actual Levelset Stuff
+  // Inflation Strength
+  vtkSetClampMacro(PropagationWeight,float,0.0,1.0);
+  vtkGetMacro(PropagationWeight,float);
+
+  // CurvatureWeight
+  vtkSetClampMacro(CurvatureWeight,float,0.0,1.0);
+  vtkGetMacro(CurvatureWeight,float);
+
+  // AdvectionWeight
+  vtkSetClampMacro(AdvectionWeight,float,0.0,1.0);
+  vtkGetMacro(AdvectionWeight,float);
+
+
+  // AdvectionWeight
+  vtkSetClampMacro(UpdatePercentage,float,0.05,1.01);
+  vtkGetMacro(UpdatePercentage,float);
+
+
+  // RealIteration
+  vtkSetMacro(RealIteration,int);
+  vtkGetMacro(RealIteration,int);
+  
+  
+protected:
+
+  vtkpxBaseLevelSetFilter();
+  virtual ~vtkpxBaseLevelSetFilter();
+  vtkpxBaseLevelSetFilter(const vtkpxBaseLevelSetFilter&) {};
+  void operator=(const vtkpxBaseLevelSetFilter&) {};
+
+
+  // Description
+  // Execute Information Replacements
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+  // Description:
+  // Basic Methods
+  virtual int  GenerateInputLevelSet(vtkImageData* input,float factor=1.0);
+
+  vtkImageData* InitialLevelSet;
+  vtkPoints*    InitialPoints;
+  float         InitialDistance;
+  float         RMSError;
+  int           LevelsetIterations;
+  int           OffsetIteration;
+  vtkImageData* InputLevelSet;
+
+
+
+  //BTX
+  // Some ITK Definitions
+  char* IterationName,*OutputStatus;
+  int IterationSave,IterationSaveFrequency,IterationSaveOrientation;
+  float         PropagationWeight;
+  float         CurvatureWeight;
+  float         AdvectionWeight;
+  float         UpdatePercentage;
+  int           RealIteration;
+   //ETX
+
+};
+
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxBrainPreSegment.cpp b/bioimagesuite30_src/Segmentation/vtkpxBrainPreSegment.cpp
new file mode 100644
index 0000000..6937a20
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxBrainPreSegment.cpp
@@ -0,0 +1,557 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*
+ * File: OmsVoxelStack.cpp
+ * Author: Skrinjar Oskar
+ * Date: October 19, 1998
+ * Project: Surgical Navigation System
+ * -----------------------------------------------
+ * This file is the implementation of the OmsVoxelStack class.
+ */
+
+#include "vtkpxBrainPreSegment.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkDataArray.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkPointData.h"
+
+// INCLUDE FILES
+#include <stdio.h>
+#include <stdlib.h>
+
+//***********************************************************************
+//   This came via Oskar's Code 
+//***********************************************************************
+/*
+ * File: OmsVoxelStack.h
+ * Author: Skrinjar Oskar
+ * Date: October 19, 1998
+ * Project: Surgical Navigation System
+ * ------------------------------------------------------------
+ * This file is the declaration of the OmsVoxelStack class.
+ * It is a stack of voxel positions.
+ */
+
+// new data types
+struct OmsVoxelStackEntry {
+  int x, y, z;
+  struct OmsVoxelStackEntry *previous;
+  struct OmsVoxelStackEntry *next;
+};
+
+
+/*
+ * CLASS: OmsVoxelStack
+ */
+
+class OmsVoxelStack {
+
+private:
+
+  OmsVoxelStackEntry *first, *last;
+
+  void EmptyStack(void);
+
+public:
+
+  OmsVoxelStack(void); // constructor
+  ~OmsVoxelStack();  // destructor
+
+  void Push(int x, int y, int z);
+  int Pop(int &x, int &y, int &z);
+  int IsEmpty(void) { if (first == NULL) return 1;  return 0; }
+  void SetEmpty(void);
+
+};
+
+//***********************************************************************
+/*
+ * Public method: OmsVoxelStack
+ * Usage: OmsVoxelStack stack;
+ * -----------------------------------------------------
+ * This method is a constructor of the OmsVoxelStack class.
+ */
+
+OmsVoxelStack::OmsVoxelStack(void)
+{
+  first = NULL;
+  last = NULL;
+}
+
+
+/*
+ * Public method: ~OmsVoxelStack
+ * -------------------------------------------------------
+ * This method is the destructor of the OmsVoxelStack class.
+ */
+
+OmsVoxelStack::~OmsVoxelStack()
+{
+  EmptyStack();
+}
+
+
+/*
+ * Public method: Push
+ * Usage: stack.Push(x, y, z);
+ * ------------------------------------------------------
+ * This method pushes an element to the stack.
+ */
+
+void OmsVoxelStack::Push(int x, int y, int z)
+{
+  OmsVoxelStackEntry *tmp = new OmsVoxelStackEntry;
+  if (tmp == 0)
+      {
+	printf("OmsVoxelStack::Puch:  Not enough memory !\n");
+	exit(0);
+      }
+  //  printf("Pusing %d %d %d\n",x,y,z);
+  // set the entry elements
+  tmp->x = x;
+  tmp->y = y;
+  tmp->z = z;
+  tmp->next = NULL;
+  tmp->previous = last;
+
+  // link it to the stack
+  if (first == NULL)
+      {
+	first = tmp;
+	last = tmp;
+      }
+  else
+      {
+	last->next = tmp;
+	last = tmp;
+      }
+}
+
+
+/*
+ * Public method: Pop
+ * Usage: if (stack.Pop(x,y,z) == 1) ...
+ * -----------------------------------------------------------------
+ * This method pops the last element from the stack and returns 1.
+ * If there are no elements 0 is returned.
+ */
+
+int OmsVoxelStack::Pop(int &x, int &y, int &z)
+{
+  if (first == NULL) return 0;
+
+  x = last->x;
+  y = last->y;
+  z = last->z;
+
+  if (last->previous == NULL)
+      {
+	delete last;
+	first = NULL;
+	last = NULL;
+      }
+  else
+      {
+	last = last->previous;
+	delete last->next;
+	last->next = NULL;
+      }
+
+  return 1;
+}
+
+
+/*
+ * Public method: SetEmpty
+ * Usage: Stack.SetEmpty();
+ * -----------------------------------------------------
+ * This method reinitializes the stack to its initial state, i.e.,
+ * deletes all the elements in the stack.
+ */
+
+void OmsVoxelStack::SetEmpty(void)
+{
+  EmptyStack();
+  first = NULL;
+  last = NULL;
+}
+
+
+/*
+ * Private method: EmptyStack
+ * Usage: EmptyStack();
+ * --------------------------------------------------------------
+ * This method deletes all of the stack elements.
+ */
+
+void OmsVoxelStack::EmptyStack(void)
+{
+  OmsVoxelStackEntry *tmp = first, *tmp_del;
+
+  // delete entry by entry
+  while (tmp != NULL)
+      {
+	tmp_del = tmp;
+	tmp = tmp->next;
+	delete tmp_del;
+      }
+}
+
+
+//***********************************************************************
+//   This also came via Oskar's Code 
+//***********************************************************************
+/*
+ * Private method: BrainTissueAlgorithm
+ * Usage: BrainTissueAlgorithm(x_seed, y_seed, z_seed)
+ * ---------------------------------------------------------------------------
+ * This algorithm performs the brain tissue segmentation.
+ */
+
+void   BrainTissueAlgorithm(vtkpxBrainPreSegment* self,
+			    int seed[3],
+			    float LowThreshold,
+			    float HighThreshold,
+			    vtkImageData* input,
+			    vtkImageData* output,
+			    int erode,
+			    int regrow,
+			    int geodilate,
+			    int numerode)
+		  
+{
+  /*printf("\nBrain tissue segmentation:  seed=(%d,%d,%d), levels=%f:%f\n",
+    seed[0],seed[1],seed[2],LowThreshold,HighThreshold);*/
+  
+  // sizes of the bounding box
+
+  int dim[3];
+  input->GetDimensions(dim);
+
+  int xsize = dim[0];
+  int ysize = dim[1];
+  int zsize = dim[2];
+
+  int slicesize=xsize*ysize;
+  int volsize=slicesize*zsize;
+
+  unsigned char *data1 = NULL;
+  data1 = new unsigned char [volsize];
+  if (data1 == 0)
+      {
+	printf("BrainTissueAlgorithm:  Not enough memory !\n");
+	return;
+      }
+
+  vtkDataArray* outScalars=output->GetPointData()->GetScalars();
+  unsigned char* data2=((vtkUnsignedCharArray *)outScalars)->WritePointer(0, volsize);
+  
+  // THRESHOLDING
+  //printf("Double thresholding ... ");
+  vtkDataArray* inScalars=input->GetPointData()->GetScalars();
+  int x, y, z;
+  
+  for (int ia = 0; ia < volsize; ia++) 
+    {
+      float v=inScalars->GetComponent(ia,0);
+      if (v>=LowThreshold && v<=HighThreshold)
+	{
+	  data1[ia] = 1;
+	  data2[ia] = 1;
+	}
+      else
+	{
+	  data1[ia] = 0;
+	  data2[ia] = 0;
+	}
+    }
+
+  //  printf(" Done !\n");
+  self->UpdateProgress(0.2);
+
+  int n;
+
+  if (erode==1)
+    {
+      // Erosion
+      //      printf("Erosion: ");
+      for (n = 0; n < numerode; n++)
+	{
+	  //	  printf(" %d ", n);
+	  for (x = 1; x < xsize-1; x++) 
+	    for (y = 1; y < ysize-1; y++) 
+	      for (z = 1; z < zsize-1; z++) 
+		{
+		  int index=x+y*xsize+z*slicesize;
+		  if (data1[index] == 1)
+		    {
+		      if ( (data1[index-1] == 0) || 
+			   (data1[index+1] == 0) || 
+			   (data1[index+xsize] == 0) || 
+			   (data1[index-xsize] == 0) || 
+			   (data1[index+slicesize] == 0) || 
+			   (data1[index-slicesize] == 0) ) 
+			data2[index] = 0;
+		    }
+		}
+	  for (int i=0;i<volsize;i++)
+	    data1[i]=data2[i];
+	  if (numerode>1)
+	    self->UpdateProgress(float(n+1)/float(numerode-1)*0.3+0.1);
+	}
+      //printf("Done\n");
+      
+    }
+  
+
+  if (regrow==1)
+    {
+      // REGROW
+      //      printf("Regrow .... ");
+      
+      int xc = seed[0];
+      int yc = seed[1];
+      int zc = seed[2];
+      
+      OmsVoxelStack stack;
+      stack.Push(xc,yc,zc);
+      int index=xc+yc*xsize+zc*slicesize;
+      data2[index] = 2;
+
+      int iter=0;
+      
+      while ( stack.Pop(xc, yc, zc) == 1 )
+	{
+	  iter++;
+	  int index=xc+yc*xsize+zc*slicesize;
+	  if (xc > 0)
+	    {
+	      if ( data2[index-1] == 1 )
+		{
+		  data2[index-1] = 2;
+		  stack.Push(xc-1, yc, zc);
+		}
+	    }
+	  
+	  if (xc < xsize-1)
+	    {
+	      if ( data2[index+1] == 1 )
+		{
+		  data2[index+1] = 2;
+		  stack.Push(xc+1, yc, zc);
+		}
+	    }
+	  
+	  if (yc > 0)
+	    {
+	      if ( data2[index-xsize] == 1 )
+		{
+		  data2[index-xsize] = 2;
+		  stack.Push(xc, yc-1, zc);
+		}
+	    }
+	  
+	  if (yc < ysize-1)
+	    {
+	      if ( data2[index+xsize] == 1 )
+		{
+		  data2[index+xsize] = 2;
+		  stack.Push(xc, yc+1, zc);
+		}
+	    }
+	  
+	  if (zc > 0)
+	    {
+	      if ( data2[index-slicesize] == 1 )
+		{
+		  data2[index-slicesize] = 2;
+		  stack.Push(xc, yc, zc-1);
+		}
+	    }
+	  
+	  if (zc < zsize-1)
+	    {
+	      if ( data2[index+slicesize] == 1 )
+		{
+		  data2[index+slicesize] = 2;
+		  stack.Push(xc, yc, zc+1);
+		}
+	    }
+	}
+      
+      //      printf("Done Regrow iter=%d\n",iter);
+
+      if (iter>2)
+	{
+	  //printf("Reset ... ");
+	  for (int index = 0; index < volsize; index++) 
+	    {
+	      if ( data2[index] == 2) 
+		data2[index] = 1;
+	      else 
+		data2[index] = 0;
+	    }
+	  //printf(" Done !\n");
+	}
+      else
+	{
+	  printf("****** Bad Seed No Regrow  will be attempted! ***** \n");
+	}
+
+      self->UpdateProgress(0.6);
+    }
+
+  // GEODILATE
+  if (geodilate)
+    {
+      //printf("Geodilate in process ...");
+      for (n = 0; n < numerode+1; n++)
+	{
+	  //printf(" %d", n);
+	  
+	  for (x = 1; x < xsize-1; x++) 
+	    for (y = 1; y < ysize-1; y++) 
+	      for (z = 1; z < zsize-1; z++) 
+		{
+		  int index=x+y*xsize+z*slicesize;
+		  if ( data2[index] == 1 )
+		    {
+		      if ( (data2[index-1]==0) && (data1[index-1]==1) ) 
+			data2[index-1] = 2;
+		      //index = INDEX(x+1,y,z);
+		      if ( (data2[index+1]==0) && (data1[index+1]==1) ) 
+			data2[index+1] = 2;
+		      //index = INDEX(x,y-1,z);
+		      if ( (data2[index-xsize]==0) && (data1[index-xsize]==1) ) 
+			data2[index-xsize] = 2;
+		      //index = INDEX(x,y+1,z);
+		      if ( (data2[index+xsize]==0) && (data1[index+xsize]==1) ) 
+			data2[index+xsize] = 2;
+		      //index = INDEX(x,y,z-1);
+		      if ( (data2[index-slicesize]==0) && (data1[index-slicesize]==1) ) 
+			data2[index-slicesize] = 2;
+		      //index = INDEX(x,y,z+1);
+		      if ( (data2[index+slicesize]==0) && (data1[index+slicesize]==1) ) 
+			data2[index+slicesize] = 2;
+		    }
+		}
+	  
+	  for (int i=0;i<volsize;i++)
+	    {
+	      if ( data2[i] == 2 ) 
+		data2[i] = 1;
+	    }
+
+	  self->UpdateProgress(0.6+float(n+1)/float(numerode)*0.4);
+	}
+      //printf("\n");
+    }
+  
+  // free the occupied memory
+  if (data1 != NULL) 
+    delete [] data1;
+  
+
+      self->UpdateProgress(1.0);
+  //  printf("Brain segmentation algorithm completed !\n");
+
+}
+
+
+
+vtkpxBrainPreSegment* vtkpxBrainPreSegment::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxBrainPreSegment");
+  if(ret)
+      {
+	return (vtkpxBrainPreSegment*)ret;
+      }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxBrainPreSegment;
+}
+
+
+// Construct object to extract all of the input data.
+vtkpxBrainPreSegment::vtkpxBrainPreSegment()
+{
+  this->LowThreshold=0.0;
+  this->HighThreshold=255.0;
+  this->Erode=1;
+  this->Regrow=1;
+  this->Geodilate=1;
+  this->NumErosions=2;
+  for (int i=0;i<=2;i++)
+    this->Seed[i]=0;
+}
+
+void vtkpxBrainPreSegment::SimpleExecute(vtkImageData *input,vtkImageData *output)
+{  
+  vtkDebugMacro(<< "Extracting Slice");
+
+  int dim[3];   input->GetDimensions(dim);
+  double ori[3]; input->GetOrigin(ori);
+  double sp[3];  input->GetSpacing(sp);
+
+  output->SetSpacing(sp);
+  output->SetScalarType(VTK_UNSIGNED_CHAR);
+  output->SetNumberOfScalarComponents(1);
+  output->SetOrigin(ori);
+  output->SetDimensions(dim);
+  output->SetWholeExtent(0,dim[0]-1,
+			 0,dim[1]-1,
+			 0,dim[2]-1);
+  output->AllocateScalars();
+  BrainTissueAlgorithm(this,
+		       this->Seed,
+		       this->LowThreshold,
+		       this->HighThreshold,
+		       input,output,
+		       this->Erode,
+		       this->Regrow,
+		       this->Geodilate,
+		       this->NumErosions);
+}
+
+
+void vtkpxBrainPreSegment::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkpxSimpleImageToImageFilter::PrintSelf(os,indent);
+
+  os << indent << "  Seed " << this->Seed[0] << ", "<< this->Seed[1] << ", " << this->Seed[2]  << "\n";
+  os << indent << "  Thresholds " << this->LowThreshold << ", " << this->HighThreshold << "\n";
+}
+
+
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxBrainPreSegment.h b/bioimagesuite30_src/Segmentation/vtkpxBrainPreSegment.h
new file mode 100644
index 0000000..dec082d
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxBrainPreSegment.h
@@ -0,0 +1,138 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxBrainPreSegment.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:53:08 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxBrainPreSegment - simple brain segmentation algorithm
+// .SECTION Description
+// This is an implementation of a simple brain segmentation algorithm
+// (originally from the work of Rik Stokking and Oskar Skrinjar)
+// which consists of four steps <OL>
+// <LI> Threshold Image  between <TT>LowThreshold</TT> and <TT>HighThreshold</TT>
+// <LI> Erode  (if <TT>Erode</TT> >0) (<TT>NumErosions</TT> iterations)
+// <LI> Apply Connectivity (if <TT>Regrow</TT>>0) based on (<TT>Seed</TT>[] coordinates)
+// <LI> Apply a modified Dilation (if <TT>Geodilate</TT>>0) (<TT>NumErosions</TT>+1 iterations)
+// </UL>
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxBrainPreSegment_h
+#define __vtkpxBrainPreSegment_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+
+class vtkpxBrainPreSegment : public vtkpxSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkpxBrainPreSegment,vtkpxSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Construct object to extract all of the input data.
+
+  static vtkpxBrainPreSegment *New();
+
+  // Description:
+  // Description: Get/Set Thresholds for step 1
+  vtkSetMacro(LowThreshold,float);
+  vtkGetMacro(LowThreshold,float);
+  vtkSetMacro(HighThreshold,float);
+  vtkGetMacro(HighThreshold,float);
+
+  // Description:
+  // Description: Get/Set Seed position (in voxels) for connectivity
+  vtkSetVectorMacro(Seed,int,3);
+  vtkGetVectorMacro(Seed,int,3);
+
+  // Description:
+  // Flag to determine whether to erode or not
+  vtkGetMacro(Erode,int);
+  vtkSetMacro(Erode,int);
+
+  // Description:
+  // Flag to determine whether to run connectivity or not
+  vtkGetMacro(Regrow,int);
+  vtkSetMacro(Regrow,int);
+
+  // Description:
+  // Flag to determine whether to dilate or not
+  vtkGetMacro(Geodilate,int);
+  vtkSetMacro(Geodilate,int);
+
+  // Description:
+  // Number of Erosions/Dilations if enabled
+  vtkGetMacro(NumErosions,int);
+  vtkSetMacro(NumErosions,int);
+
+protected:
+  //BTX
+  vtkpxBrainPreSegment();
+  ~vtkpxBrainPreSegment() {};
+  vtkpxBrainPreSegment(const vtkpxBrainPreSegment&) {};
+  void operator=(const vtkpxBrainPreSegment&) {};
+
+  virtual void SimpleExecute(vtkImageData *in,vtkImageData *op);
+
+  int   Erode;
+  int   Regrow;
+  int   Geodilate;
+  int   NumErosions;
+  float LowThreshold;
+  float HighThreshold;
+  int Seed[3];
+  //ETX
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxCoupledTissueLevelSetFilter.cpp b/bioimagesuite30_src/Segmentation/vtkpxCoupledTissueLevelSetFilter.cpp
new file mode 100644
index 0000000..bfec4e6
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxCoupledTissueLevelSetFilter.cpp
@@ -0,0 +1,421 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCoupledTissueLevelSetFilter.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxLevelSetUtil.h"
+#include "vtkImageImport.h"
+#include "vtkImageExport.h"
+#include "itkpxLevelSetCallback.h"
+#include "itkpxTissueSegmentationCoupledLevelSetImageFilter.h"
+#include "vtkImageCast.h"
+#include "itkReinitializeLevelSetImageFilter.h"
+#include "itkpxSaturateImageFilter.h"
+#include "vtkpxCoupledTissueLevelSetFilter.h"
+#include "vtkpxImageExtractVOI.h"
+#include "vtkpxAnalyzeImageWriter.h"
+#include "vtkImageChangeInformation.h"
+//------------------------------------------------------------------------------
+// First a Helper Class
+// -----------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+vtkpxCoupledTissueLevelSetFilter* vtkpxCoupledTissueLevelSetFilter::New()
+{
+  return new vtkpxCoupledTissueLevelSetFilter;
+}
+
+
+
+vtkpxCoupledTissueLevelSetFilter::vtkpxCoupledTissueLevelSetFilter()
+{
+  this->CouplingOffset=1.0;
+  this->SetPresetMode(0);
+  this->Output2=NULL;
+  this->MinThickness=2.0;
+  this->MaxThickness=5.0;
+  this->Padding=10;
+  this->SetIterationName("joined");
+}
+// ----------------------------------------------------------------------------
+vtkpxCoupledTissueLevelSetFilter::~vtkpxCoupledTissueLevelSetFilter()
+{
+  if (this->Output2!=NULL)
+    this->Output2->Delete();
+  this->Output2=NULL;
+
+}
+// ---------------------------------------------------------------------------------------------
+void vtkpxCoupledTissueLevelSetFilter::SetPresetMode(int m)
+{
+  if (m<0 || m>2) 
+    m=0;
+
+  switch (m)
+    {
+    case 0:
+      this->WhiteMatterMean= 275;   
+      this->WhiteMatterSigma=13; 
+      this->GrayMatterMean= 200; 
+      this->GrayMatterSigma= 21;
+      this->CSFMean= 80;  
+      this->CSFSigma= 20;
+      break;
+    case 1: 
+      this->WhiteMatterMean= 285; 
+      this->WhiteMatterSigma=14; 
+      this->GrayMatterMean= 200; 
+      this->GrayMatterSigma= 21;
+      this->CSFMean= 80;
+      this->CSFSigma= 20;
+      break;
+    case 2:
+      this->WhiteMatterMean= 300; 
+      this->WhiteMatterSigma=18; 
+      this->GrayMatterMean= 200; 
+      this->GrayMatterSigma= 21;
+      this->CSFMean= 80;  
+      this->CSFSigma= 20;
+      break;
+    }
+}
+
+int vtkpxCoupledTissueLevelSetFilter::CheckInputs()
+{
+  return 1;
+}
+// ---------------------------------------------------------------------------
+template <int ImageDimension>
+int vtkpxCoupledTissueLevelSetFilter_RunCoupledActiveContour(vtkImageData* input,vtkImageData* output,vtkImageData* output2,
+							     vtkpxCoupledTissueLevelSetFilter* self)
+{
+  typedef  float  PixelType;
+  typedef itk::Image<PixelType,ImageDimension>    ImageType;
+  typedef itk::VTKImageImport<ImageType> ImportType;
+  typedef itk::VTKImageExport<ImageType> ExportType;
+  typedef itk::TissueSegmentationCoupledLevelSetImageFilter< ImageType, ImageType > LevelSetFilterType;
+  typedef itk::ReinitializeLevelSetImageFilter<ImageType> Reinitializer;
+  typedef itk::SaturateImageFilter<ImageType,ImageType> SaturateFilterType;
+  typedef CommandIterationUpdate<LevelSetFilterType,SaturateFilterType,ImageType> CommandType;
+  //typedef CommandIterationUpdate<LevelSetFilterType,Reinitializer,ImageType> CommandType;
+
+
+  int original_dimx=input->GetDimensions()[0];
+  double meanthickness=0.5*(self->GetMinThickness()+self->GetMaxThickness());
+  vtkImageData* paddedimage=vtkpxCoupledTissueLevelSetFilter::CreatePaddedImage(input,
+										self->GetPadding(),
+										0.0);
+
+  vtkImageData* paddedinput=vtkpxCoupledTissueLevelSetFilter::CreatePaddedImage(self->GetInputLevelSet(),
+										self->GetPadding(),
+										meanthickness);
+										
+
+  /*  vtkpxAnalyzeImageWriter* w=vtkpxAnalyzeImageWriter::New();
+  w->SetInput(paddedimage);
+  w->Save("00_padimage.nii.gz");
+
+  
+  w->SetInput(paddedinput);
+  w->Save("00_padinput.nii.gz");
+  w->Delete();*/
+
+  // Export original image
+  vtkImageExport *vtkInputExporter = vtkImageExport::New();
+  vtkInputExporter->SetInput(paddedimage);
+  typename ImportType::Pointer itkInputImporter =  ImportType::New();
+  ConnectPipelines(vtkInputExporter, itkInputImporter);
+  itkInputImporter->Update();
+  
+  // Export Initial Levelset
+  vtkImageExport *vtkInputLevelSetExporter = vtkImageExport::New();
+  vtkInputLevelSetExporter->SetInput(paddedinput);
+  typename ImportType::Pointer itkInputLevelSetImporter =  ImportType::New();
+  ConnectPipelines(vtkInputLevelSetExporter, itkInputLevelSetImporter);
+  itkInputLevelSetImporter->Update();
+
+
+  typename LevelSetFilterType::Pointer levelSet;
+  typename Reinitializer::Pointer reinit;
+  typename SaturateFilterType::Pointer sat;
+  typename CommandType::Pointer observer;
+
+  levelSet=    LevelSetFilterType::New();
+  levelSet->SetPropagationScaling( self->GetPropagationWeight() );
+  levelSet->SetCurvatureScaling(   self->GetCurvatureWeight() );
+  levelSet->SetAdvectionScaling(self->GetAdvectionWeight());
+  levelSet->SetInput(  itkInputLevelSetImporter->GetOutput() );
+  levelSet->SetFeatureImage(itkInputImporter->GetOutput());
+  levelSet->SetCoupledLevelSetBoundaries(original_dimx,original_dimx+self->GetPadding());
+  levelSet->SetConstraintOffset(self->GetCouplingOffset());
+
+  levelSet->SetWhiteMatterTissue(self->GetWhiteMatterMean(),self->GetWhiteMatterSigma());
+  levelSet->SetGrayMatterTissue(self->GetGrayMatterMean(),self->GetGrayMatterSigma());
+  levelSet->SetCSFTissue(self->GetCSFMean(),self->GetCSFSigma());
+  levelSet->SetIsoSurfaceValue(0.0);
+  levelSet->SetLowerWhiteGrayBound(self->GetMinThickness());
+  levelSet->SetUpperWhiteGrayBound(self->GetMaxThickness());
+  levelSet->SetLowerGrayCSFBound(-self->GetMaxThickness());
+  levelSet->SetUpperGrayCSFBound(-self->GetMinThickness());
+  levelSet->SetMaximumRMSError(0.0);
+  levelSet->SetNumberOfIterations(1);
+  levelSet->SetNumberOfLayers(int(2*self->GetMaxThickness()));
+  levelSet->Update();
+
+  self->SetRealIteration(self->GetRealIteration()+1);
+
+  typename ExportType::Pointer itkExporter = ExportType::New();
+  itkExporter->SetInput(levelSet->GetOutput());
+
+  vtkImageImport* vtkImporter=vtkImageImport::New();
+  ConnectPipelines(itkExporter, vtkImporter);
+
+  int maxiter=int(self->GetLevelsetIterations());
+  int iter=1;
+  int count=1;
+  int fraction=int(self->GetUpdatePercentage()*float(maxiter));
+  float maxerror=self->GetRMSError()+1.0;
+
+  char line[220];
+  sprintf(line,"Begining level set evolution, updating every %d iterations", fraction);
+  self->SetOutputStatus(line);
+  //  fprintf(stderr,"%s\n",line);
+
+  while( iter <= maxiter && maxerror > self->GetRMSError() )
+    {
+      levelSet->SetStateToInitialized();
+      levelSet->SetNumberOfIterations(levelSet->GetElapsedIterations()+1);
+      levelSet->Modified();
+      levelSet->Update();
+      maxerror=levelSet->GetRMSChange();
+      self->SetRealIteration(self->GetRealIteration()+1);
+      
+      sprintf(line,"Completed  %d (%d) /%d error=%6.4f",iter,self->GetRealIteration(),maxiter,maxerror);
+      self->SetOutputStatus(line);
+      int doupdate=0;
+      if (count==fraction)
+	{
+	  doupdate=1;
+	  count=0;
+	  itkExporter->Update();
+	  vtkImporter->Update();
+
+	  vtkImageData* tmp_out=vtkpxCoupledTissueLevelSetFilter::CreateInnerOutputImage(vtkImporter->GetOutput(),original_dimx);
+	  output2->ShallowCopy(tmp_out);
+	  tmp_out->Delete();
+
+	  
+	  vtkImageData* tmp_out2=vtkpxCoupledTissueLevelSetFilter::CreateOuterOutputImage(vtkImporter->GetOutput(),
+											  self->GetPadding(),original_dimx);
+	  output->ShallowCopy(tmp_out2);
+	  tmp_out2->Delete();
+	  self->UpdateProgress(self->GetProgress()+float(iter)/float(maxiter));
+	}
+
+      ++iter;
+      ++count;
+    }
+
+  
+  reinit=Reinitializer::New();
+  reinit->SetInput(levelSet->GetOutput());
+  reinit->NarrowBandingOn();
+  reinit->SetNarrowBandwidth(4.0*meanthickness);
+      
+  sat=SaturateFilterType::New();
+  sat->SetInput(reinit->GetOutput());
+  sat->SetLowerBound(-3.0*meanthickness);
+  sat->SetUpperBound( 3.0*meanthickness);
+  sat->Update();
+
+  itkExporter->SetInput(sat->GetOutput());
+  itkExporter->Update();
+  ConnectPipelines(itkExporter, vtkImporter);
+  vtkImporter->Update();
+  
+  vtkImageData* tmp_out=vtkpxCoupledTissueLevelSetFilter::CreateInnerOutputImage(vtkImporter->GetOutput(),original_dimx);
+  output2->ShallowCopy(tmp_out);
+  tmp_out->Delete();
+
+
+  vtkImageData* tmp_out2=vtkpxCoupledTissueLevelSetFilter::CreateOuterOutputImage(vtkImporter->GetOutput(),
+										 self->GetPadding(),original_dimx);
+  output->ShallowCopy(tmp_out2);
+  tmp_out2->Delete();
+  
+  vtkInputLevelSetExporter->Delete();
+  vtkInputExporter->Delete();
+  vtkImporter->Delete();
+
+  paddedimage->Delete();
+  paddedinput->Delete();
+
+  return 1;
+}
+
+
+int vtkpxCoupledTissueLevelSetFilter::RunCoupledActiveContour(vtkImageData* input,vtkImageData* output,vtkImageData* output2)
+{
+  int dim[3]; input->GetDimensions(dim);
+
+  if (dim[2]==1)
+    return vtkpxCoupledTissueLevelSetFilter_RunCoupledActiveContour<2>(input,output,output2,this);
+
+  return vtkpxCoupledTissueLevelSetFilter_RunCoupledActiveContour<3>(input,output,output2,this);
+
+
+
+
+}
+
+// ----------------------------------------------------------------------------
+void vtkpxCoupledTissueLevelSetFilter::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxCoupledTissueLevelSetFilter");
+      return;
+    }
+
+  fprintf(stderr,"Creating Input Level Set\n");
+  this->GenerateInputLevelSet(input);
+  fprintf(stderr,"Running Level Set\n");
+
+  if (this->Output2!=NULL)
+    this->Output2->Delete();
+  this->Output2=vtkImageData::New();
+
+  this->RunCoupledActiveContour(input,output,Output2);
+
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+vtkImageData* vtkpxCoupledTissueLevelSetFilter::CreatePaddedImage(vtkImageData* input,int padding,double offset)
+{
+  if (input==NULL)
+    return NULL;
+  int dim[3];  input->GetDimensions(dim);
+  int odim[3]; input->GetDimensions(odim);
+  odim[0]=odim[0]*2+padding;
+
+  vtkImageData* output=vtkImageData::New();
+  output->CopyStructure(input);
+  output->SetNumberOfScalarComponents(1);
+  output->SetDimensions(odim);
+  output->SetScalarTypeToFloat();
+  output->AllocateScalars();
+
+  int shift=dim[0]+padding;
+
+  int index=0;
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  if (fabs(offset)<0.01)
+    out->FillComponent(0,0.0);
+  else
+    out->FillComponent(0,100.0);
+
+  for (int ic=0;ic<dim[2];ic++)
+    for (int ib=0;ib<dim[1];ib++)
+      for (int ia=0;ia<dim[0];ia++)
+	{
+	  double v=inp->GetComponent(index,0);
+	  output->SetScalarComponentFromDouble(ia,ib,ic,0,v);
+	  output->SetScalarComponentFromDouble(ia+shift,ib,ic,0,v-offset);
+	  ++index;
+	}
+  return output;
+}
+
+vtkImageData* vtkpxCoupledTissueLevelSetFilter::CreateInnerOutputImage(vtkImageData* result,int dimx)
+{
+  if (result==NULL)
+    return NULL;
+
+  int dim[3]; result->GetDimensions(dim);
+
+  vtkpxImageExtractVOI* voi=vtkpxImageExtractVOI::New();
+  voi->SetInput(result);
+  voi->SetVOI(0,dimx-1,0,dim[1]-1,0,dim[2]-1);
+  voi->Update();
+  
+  vtkImageData* out=vtkImageData::New();
+  out->ShallowCopy(voi->GetOutput());
+  voi->Delete();
+  return out;
+}
+
+vtkImageData* vtkpxCoupledTissueLevelSetFilter::CreateOuterOutputImage(vtkImageData* result,int padding,int dimx)
+{
+  if (result==NULL)
+    return NULL;
+
+  int dim[3]; result->GetDimensions(dim);
+
+  vtkpxImageExtractVOI* voi=vtkpxImageExtractVOI::New();
+  voi->SetInput(result);
+  voi->SetVOI(dimx+padding,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  voi->Update();
+
+  vtkImageChangeInformation* info=vtkImageChangeInformation::New();
+  info->SetInput(voi->GetOutput());
+  info->SetOutputOrigin(result->GetOrigin());
+  info->Update();
+  
+  vtkImageData* out=vtkImageData::New();
+  out->ShallowCopy(info->GetOutput());
+  voi->Delete();
+  return out;
+}
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxCoupledTissueLevelSetFilter.h b/bioimagesuite30_src/Segmentation/vtkpxCoupledTissueLevelSetFilter.h
new file mode 100644
index 0000000..abdb1af
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxCoupledTissueLevelSetFilter.h
@@ -0,0 +1,154 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxCoupledTissueLevelSetFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxCoupledTissueLevelSetFilter -- corrects for B0 inhomogeneity in 1-H CSI Data for fat quantification
+
+#ifndef __vtkpxCoupledTissueLevelSetFilter_h
+#define __vtkpxCoupledTissueLevelSetFilter_h
+
+#include "vtkpxBaseLevelSetFilter.h"
+#include "vtkpxLevelSetUtil.h"
+
+class vtkpxCoupledTissueLevelSetFilter : public vtkpxBaseLevelSetFilter
+{
+public:
+  static vtkpxCoupledTissueLevelSetFilter *New();
+  vtkTypeMacro(vtkpxCoupledTissueLevelSetFilter,vtkpxBaseLevelSetFilter);
+
+
+  // Description:
+  // Part 1 Coupled Description
+  // Inside Mean and Sigma
+  vtkSetMacro(GrayMatterMean,float);
+  vtkGetMacro(GrayMatterMean,float);
+  vtkSetMacro(GrayMatterSigma,float);
+  vtkGetMacro(GrayMatterSigma,float);
+
+  vtkSetMacro(WhiteMatterMean,float);
+  vtkGetMacro(WhiteMatterMean,float);
+  vtkSetMacro(WhiteMatterSigma,float);
+  vtkGetMacro(WhiteMatterSigma,float);
+
+  vtkSetMacro(CSFMean,float);
+  vtkGetMacro(CSFMean,float);
+  vtkSetMacro(CSFSigma,float);
+  vtkGetMacro(CSFSigma,float);
+
+  // Mode (0 = Wm = 275, 1=285 2=300)
+  virtual void SetPresetMode(int mode);
+
+  // Part 1 -- Input Seeds or Levelset (if the later is not NULL use it first)
+  vtkGetObjectMacro(Output2,vtkImageData);
+
+  // LengthPenalty
+  vtkSetClampMacro(MinThickness,float,0.0,10.0);
+  vtkGetMacro(MinThickness,float);
+
+  vtkSetClampMacro(MaxThickness,float,0.0,10.0);
+  vtkGetMacro(MaxThickness,float);
+
+  vtkSetClampMacro(Padding,int,1,20);
+  vtkGetMacro(Padding,int);
+
+  // Coupling Weight
+  vtkSetClampMacro(CouplingOffset,float,0.0,100.0);
+  vtkGetMacro(CouplingOffset,float);
+
+
+  // Description:
+  // Operations for creating and splitting padded images
+  static vtkImageData* CreatePaddedImage(vtkImageData* input,int padding,double offset);
+  static vtkImageData* CreateInnerOutputImage(vtkImageData* result,int dimx);
+  static vtkImageData* CreateOuterOutputImage(vtkImageData* result,int padding,int dimx);
+
+protected:
+
+
+  vtkpxCoupledTissueLevelSetFilter();
+  virtual ~vtkpxCoupledTissueLevelSetFilter();
+  vtkpxCoupledTissueLevelSetFilter(const vtkpxCoupledTissueLevelSetFilter&) {};
+  void operator=(const vtkpxCoupledTissueLevelSetFilter&) {};
+
+
+  // Description
+  // Boilerplate code from filter
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  // Description:
+  // Basic Methods
+  virtual int  CheckInputs();
+  virtual int  RunCoupledActiveContour(vtkImageData* input,vtkImageData* output,vtkImageData* output2);
+
+
+  float         GrayMatterMean;
+  float         GrayMatterSigma;
+  float         WhiteMatterMean;
+  float         WhiteMatterSigma;
+  float         CSFMean;
+  float         CSFSigma;
+  float         MaxThickness;
+  float         MinThickness;
+  float         CouplingOffset;
+  int           Padding;
+
+  //BTX
+  vtkImageData* Output2;
+  //ETX
+};
+
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxExponentialFitT1.cpp b/bioimagesuite30_src/Segmentation/vtkpxExponentialFitT1.cpp
new file mode 100644
index 0000000..73ceb91
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxExponentialFitT1.cpp
@@ -0,0 +1,676 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxExponentialFitT1.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+
+#include "vtkpxExponentialFitT1.h"
+#include "vtkpxOptimizer.h"
+#include "vtkpxUtil.h"
+#include "vtkpxMath.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+#include "pxutil.h"
+#include "pxisinf.h"
+#include "math.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+//#include "vnl/vnl_gamma.h"
+
+//extern double vnl_gamma_q(double a, double x);
+
+//------------------------------------------------------------------------------
+vtkpxExponentialFitT1* vtkpxExponentialFitT1::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxExponentialFitT1");
+  if(ret)
+    {
+      return (vtkpxExponentialFitT1*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxExponentialFitT1;
+}
+
+// Construct object with no children.
+vtkpxExponentialFitT1::vtkpxExponentialFitT1()
+{
+  this->RelaxationTimes=NULL;
+  this->R1Map=vtkImageData::New();
+  this->DensityMap=vtkImageData::New();
+  this->AlphaMap=vtkImageData::New();
+  this->MaxT1Value=2000.0;
+  this->IntensityThreshold=0.0;
+  this->DebugOpt=0;
+  this->ThreeParameterFit=1;
+  this->alphascale=10.0;
+  this->r1scale=100.0;
+}
+// ----------------------------------------------------------------------------
+vtkpxExponentialFitT1::~vtkpxExponentialFitT1()
+{
+  if (this->R1Map!=NULL)
+    this->R1Map->Delete();
+
+  if (this->DensityMap!=NULL)
+    this->DensityMap->Delete();
+
+  if (this->AlphaMap!=NULL)
+    this->AlphaMap->Delete();
+
+  if (this->RelaxationTimes!=NULL)
+    this->SetRelaxationTimes(NULL);
+}
+// ----------------------------------------------------------------------------
+int vtkpxExponentialFitT1::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+					       vtkInformationVector *outputVector)
+{
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), VTK_FLOAT, 1);
+  return 1;
+}
+// ----------------------------------------------------------------------------
+int vtkpxExponentialFitT1::CreateRelaxationTimes(float FirstRelaxationTime,float  RelaxationSpacing,int numechos)
+{
+  if (numechos==-1 && this->GetImageDataInput(0)==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image Specified, specify number of echos explicitly\n");
+      return 0;
+    }
+
+  if (numechos<1)
+    numechos=this->GetImageDataInput(0)->GetNumberOfScalarComponents();
+
+  vtkFloatArray* ar=vtkFloatArray::New();
+  ar->SetNumberOfTuples(numechos);
+  
+  for (int i=0;i<numechos;i++)
+    ar->SetComponent(i,0,FirstRelaxationTime+float(i)*RelaxationSpacing);
+
+  this->SetRelaxationTimes(ar);
+  ar->Delete();
+  return 1;
+}
+
+
+
+void vtkpxExponentialFitT1::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"No Input for vtkpxExponentialFitT1 Specified\n");
+      return;
+    }
+
+  if (input->GetNumberOfScalarComponents() < 3)
+    {
+      vtkErrorMacro(<<"Not enough components in input for vtkpxExponentialFitT1 to perform fit\n");
+      return;
+    }
+
+  if (this->RelaxationTimes==NULL)
+    {
+      this->CreateRelaxationTimes(15.0,15.0,-1);
+    }
+
+  if (this->RelaxationTimes->GetNumberOfTuples()<input->GetNumberOfScalarComponents())
+    {
+      vtkErrorMacro(<<"Bad Relaxation Train Specified\n");
+      return;
+    }
+  
+  if (this->DensityMap!=NULL)
+    this->DensityMap->Delete();
+
+  this->DensityMap=vtkImageData::New();
+  this->DensityMap->CopyStructure(output);
+  this->DensityMap->SetNumberOfScalarComponents(1);
+  this->DensityMap->AllocateScalars();
+
+  if (this->R1Map!=NULL)
+    this->R1Map->Delete();
+
+  this->R1Map=vtkImageData::New();
+  this->R1Map->CopyStructure(this->DensityMap);
+  this->R1Map->SetScalarTypeToFloat();
+  this->R1Map->SetNumberOfScalarComponents(1);
+  this->R1Map->AllocateScalars();
+
+  if (this->AlphaMap!=NULL)
+    this->AlphaMap->Delete();
+
+  this->AlphaMap=vtkImageData::New();
+  this->AlphaMap->CopyStructure(this->DensityMap);
+  this->AlphaMap->SetScalarTypeToFloat();
+  this->AlphaMap->SetNumberOfScalarComponents(1);
+  this->AlphaMap->AllocateScalars();
+
+
+  vtkDataArray* inp_v=input->GetPointData()->GetScalars();
+  vtkDataArray* den_v=this->DensityMap->GetPointData()->GetScalars();
+  vtkDataArray* alpha_v=this->AlphaMap->GetPointData()->GetScalars();
+
+  den_v->FillComponent(0,0);
+  alpha_v->FillComponent(0,1.0);
+
+  vtkDataArray* r1_v=this->R1Map->GetPointData()->GetScalars();
+  r1_v->FillComponent(0,0);
+  vtkDataArray* t1_v=output->GetPointData()->GetScalars();
+  t1_v->FillComponent(0,0);
+
+  /*  fprintf(stderr,"output %d,%d\n",
+	  t1_v->GetNumberOfTuples(),
+	  t1_v->GetNumberOfComponents());*/
+
+  double range[2]; inp_v->GetRange(range);
+
+  double threshold=  this->IntensityThreshold*(range[1]-range[0])+range[0];
+  fprintf(stderr,"Intensity Threshold=%f threshold=%f\n",this->IntensityThreshold,threshold);
+
+  int nt=inp_v->GetNumberOfTuples();
+  int nc=inp_v->GetNumberOfComponents();
+
+  this->xvalues=new double[nc];
+  int* ind=new int[nc];
+  this->yvalues=new double[nc];
+
+  fprintf(stderr,"nc=%d\n\n");
+  this->numgoodvalues=-1;
+  for (int j=0;j<nc;j++)
+    {
+      float t=this->RelaxationTimes->GetComponent(j,0);
+      fprintf(stderr,"Testing %d %f\n",j,t);
+      if (t>0.0)
+	{
+	  ++numgoodvalues;
+	  this->xvalues[numgoodvalues]=t;
+	  ind[numgoodvalues]=j;
+	}
+    }
+  ++numgoodvalues;
+
+  fprintf(stdout,"Numgood=%d:",numgoodvalues);
+  for (int j=0;j<numgoodvalues;j++)
+    fprintf(stdout,"j=%d  xvalues[j]=%.2f indvalues[j]=%d\t",j,xvalues[j],ind[j]);
+  fprintf(stdout,"\n");
+
+  if (numgoodvalues<1)
+    return;
+  int tenth=int(nt/10);
+  int count=0;
+
+
+  this->UpdateProgress(0.0);
+
+
+  vtkpxOptimizer* optimizer=vtkpxOptimizer::New();
+  vtkDoubleArray* position=vtkDoubleArray::New();
+  vtkDoubleArray* temp=vtkDoubleArray::New();
+  this->GetCurrentParameters(position);
+  optimizer->SetMasterObject(this);
+
+  optimizer->SetEvaluateFunctionMethod(&vtkpxExponentialFitT1::CalculateFunction);
+  optimizer->SetEvaluateGradientMethod(&vtkpxExponentialFitT1::CalculateGradient);
+  optimizer->SetFeedbackMethod(&vtkpxExponentialFitT1::OptimizerFeedback);
+  optimizer->SetTempArray(temp);
+
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      if (inp_v->GetComponent(voxel,0)>=threshold)
+	{
+	  /*	  if (voxel==0)
+	    this->DebugOpt=1;
+	  else
+	  this->DebugOpt=0;*/
+
+
+	  for (int j=0;j<numgoodvalues;j++)
+	    {
+	      yvalues[j]=inp_v->GetComponent(voxel,ind[j]);
+	      if (this->DebugOpt)
+		fprintf(stderr,"j=%d xvalues=%f yvalues=%f\n",j,xvalues[j],yvalues[j]);
+	    }
+	  
+
+	  this->InitializeFit(position);
+	  optimizer->ComputeConjugateGradient(position,10,0.001);
+	  double density=position->GetComponent(0,0);
+	  double r1=position->GetComponent(1,0)/this->r1scale;
+	  double alpha=1.0;
+	  if (this->ThreeParameterFit)
+	    alpha=position->GetComponent(2,0)/this->alphascale;
+
+
+	  if (this->DebugOpt)
+	    fprintf(stderr,"First Estimate d=%.1f, r1=%.5f (%.2f), alpha=%.2f",
+		    density,r1,1.0/r1,alpha);
+	  
+
+	  /*	  this->InitializeFit2(position,position->GetComponent(0,0));
+	  	  optimizer->ComputeConjugateGradient(position,10,0.001);
+
+
+	  	  density=position->GetComponent(0,0);
+	  r1=position->GetComponent(1,0)/this->r1scale;
+	  alpha=1.0;
+	  if (this->ThreeParameterFit)
+	  alpha=position->GetComponent(2,0)/this->alphascale;*/
+
+	  if (this->DebugOpt)
+	    fprintf(stderr,"Final Estimate d=%.1f, r1=%.5f (%.2f), alpha=%.2f",
+		    density,r1,1.0/r1,alpha);
+	  
+	  if (r1<1.0/this->MaxT1Value)
+	    r1=1.0/this->MaxT1Value;
+	  
+	  if (r1>10000.0)
+	    r1=10000.0;
+	  
+	  if (r1>0.0)
+	    t1_v->SetComponent(voxel,0,1.0/r1);
+	  else
+	    t1_v->SetComponent(voxel,0,0.0);
+	  
+	  if (isnan(density) || isinf(density))
+	    density=0.0;
+	
+	  r1_v->SetComponent(voxel,0,1000.0*r1);
+	  den_v->SetComponent(voxel,0,density);
+	  alpha_v->SetComponent(voxel,0,alpha);
+	}
+      ++count;
+      if (count==tenth)
+	{
+	  this->UpdateProgress(0.1+this->GetProgress());
+	  count=0;
+	}
+    }
+  this->UpdateProgress(1.0);
+  
+
+  delete [] this->xvalues;
+  delete [] this->yvalues;
+  delete [] ind;
+
+  optimizer->Delete();
+  position->Delete();
+  temp->Delete();
+}
+
+
+//-------------------------------------------------------------------------
+double vtkpxExponentialFitT1::CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output)
+{
+  return ((vtkpxExponentialFitT1*)self)->OptimizerGradient(position,output);
+}
+
+double vtkpxExponentialFitT1::CalculateFunction(vtkObject* self,vtkDoubleArray* position)
+{
+  return ((vtkpxExponentialFitT1*)self)->OptimizerValue(position);
+}
+
+void vtkpxExponentialFitT1::OptimizerFeedback(vtkObject* self,const char* line,double val)
+{
+  ((vtkpxExponentialFitT1*)self)->SetOutputStatus(line,val);
+}
+//-------------------------------------------------------------------------
+void vtkpxExponentialFitT1::SetOutputStatus(const char* line,double v)
+{
+  if (this->DebugOpt)
+    fprintf(stderr,"**Opt=%s (%.8f)\n",line,v);
+}
+
+//-------------------------------------------------------------------------
+
+void vtkpxExponentialFitT1::SetCurrentParameters(vtkDoubleArray* par)
+{
+  this->currentdensity=par->GetComponent(0,0);
+  this->currentr1=par->GetComponent(1,0)/this->r1scale;
+  if (this->currentr1<0.0)
+    this->currentr1=0.0;
+  if (this->ThreeParameterFit)
+    this->currentalpha=par->GetComponent(2,0)/this->alphascale;
+}
+ 
+void vtkpxExponentialFitT1::GetCurrentParameters(vtkDoubleArray* par)
+{
+  if (par->GetNumberOfTuples()!= 2+this->ThreeParameterFit)
+    par->SetNumberOfTuples(2+this->ThreeParameterFit);
+  par->SetComponent(0,0,this->currentdensity);
+  par->SetComponent(1,0,this->currentr1*this->r1scale);
+  if (this->ThreeParameterFit)
+    par->SetComponent(2,0,this->currentalpha*this->alphascale);
+
+}
+
+double vtkpxExponentialFitT1::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+{
+  if (grad->GetNumberOfTuples()!= 2+this->ThreeParameterFit)
+    grad->SetNumberOfTuples(2+this->ThreeParameterFit);
+
+  double den=params->GetComponent(0,0);
+  double r1=params->GetComponent(1,0)/this->r1scale;
+  if (r1<0.000001)
+    r1=0.000001;
+  double alpha=1.0;
+  if (den<0.0)
+    den=0.0;
+  if (this->ThreeParameterFit)
+    {
+      alpha=params->GetComponent(2,0)/this->alphascale;
+      if (alpha<0.0)
+	alpha=0.0;
+    }
+
+  if (this->DebugOpt)
+    fprintf(stderr,"Opt Gradient Current Values =%f , %f (t1=%f), %f\n",
+  	    den,r1,1.0/r1,alpha);
+
+
+  int np=this->ThreeParameterFit+2;
+
+  double sum[3];
+  for (int ia=0;ia<=2;ia++)
+    sum[ia]=0.0;
+
+  for (int ia=0;ia<this->numgoodvalues;ia++)
+    {
+      double tx=this->xvalues[ia]*r1;
+      double exponent=exp(-tx);
+      double v=den*(1.0-alpha*exponent);
+	
+      //      if (this->DebugOpt)
+      //fprintf(stderr,"\t\t grad ia=%d xvalues=%f yalues=%f tx=%f exp=%f v=%f\n",ia,xvalues[ia],yvalues[ia],tx,exponent,v);
+
+
+      double err=(this->yvalues[ia]-v);
+      // grad w.r.t to density
+      // 
+      sum[0]+= 2.0*err*(alpha*exponent-1.0);
+      sum[1]+= -2.0*err*(den*alpha*exponent*this->xvalues[ia]);
+      if (this->ThreeParameterFit)
+	sum[2]+= 2.0*err*(den*exponent);
+    }
+  
+  double magn=0.0;
+  for (int ia=0;ia<np;ia++)
+    magn+=sum[ia]*sum[ia];
+  magn=sqrt(sqrt(magn));
+
+  if (magn>0.0) 
+    {
+      for (int ia=0;ia<np;ia++)
+	{
+	  sum[ia]=(sum[ia]/magn);
+	  //  if (this->DebugOpt)
+	  //fprintf(stderr,"Normalized Gradient %d = %f\n",ia,sum[ia]);
+	}
+    }
+
+  grad->SetComponent(0,0,sum[0]);
+  grad->SetComponent(1,0,sum[1]);
+  if (this->ThreeParameterFit)
+    grad->SetComponent(2,0,sum[2]);
+
+  //  if (this->DebugOpt)
+  //    fprintf(stderr,"magn=%f\n\n\n",magn);
+
+  return magn;
+}
+ 
+double vtkpxExponentialFitT1::OptimizerValue(vtkDoubleArray* params)
+{
+  double den=params->GetComponent(0,0);
+  double r1=params->GetComponent(1,0)/this->r1scale;
+  double alpha=1.0;
+
+  if (den<0.0)
+    den=0.0;
+  if (r1<0.000001)
+    r1=0.000001;
+
+
+  if (this->ThreeParameterFit)
+    {
+      alpha=params->GetComponent(2,0)/this->alphascale;
+      if (alpha<0.0)
+	alpha=0.0;
+    }
+
+
+  if (this->DebugOpt)
+    fprintf(stderr,"Opt Value Current Values =%f , %f (t1=%f) %f \t",
+	    den,r1,1.0/r1,alpha);
+
+  double sum=0.0;
+  for (int ia=0;ia<this->numgoodvalues;ia++)
+    {
+      double v=den*(1.0-alpha*exp(-this->xvalues[ia]*r1));
+      //      if (this->DebugOpt)
+      //	fprintf(stderr,"\t\t ia=%d \t x=%f \t y=%f \t est=%f\n",ia,this->xvalues[ia],this->yvalues[ia],v);
+      sum+=pow(v-this->yvalues[ia],2.0);
+    }
+  sum=sum*0.001;
+  if (this->DebugOpt)
+    fprintf(stderr," sum=%f\n\n",sum);
+  return sum;
+}
+
+void vtkpxExponentialFitT1::InitializeFit2(vtkDoubleArray* position,double den) 
+{
+  double denestimate=den;
+
+  double maxy=this->yvalues[0];
+  double secondy=0.0;
+  int opt=0;
+  int opt2=0;
+  for (int ia=1;ia<this->numgoodvalues;ia++) 
+    {
+      if (maxy<this->yvalues[ia])
+	{
+	  opt2=opt;
+	  secondy=maxy;
+	  
+	  maxy=this->yvalues[ia];
+	  opt=ia;
+	}
+    }
+  
+  double r1estimate=0.1;
+  double alphaestimate=1.0;
+  
+  for (int it=0;it<1;it++)
+    {
+      double y1=this->yvalues[opt2];
+      double y2=this->yvalues[opt];
+      
+      double x1=this->xvalues[opt2];
+      double x2=this->xvalues[opt];
+      
+      double rhs1=(1.0-y1/denestimate);
+      double rhs2=(1.0-y2/denestimate);
+      double ratio=rhs2/(rhs1*alphaestimate);
+      double logratio=log(ratio);
+      r1estimate=-logratio/fabs(x2-x1);
+      if (r1estimate<0.000001)
+	r1estimate=0.000001;
+      
+      if (this->ThreeParameterFit)
+	{
+	  alphaestimate=(y1-y2)/(y1*exp(-x2*r1estimate)-y2*exp(-x1*r1estimate));
+	  if (alphaestimate<0.00001)
+	    alphaestimate=0.00001;
+	}
+
+      if (this->DebugOpt)
+	fprintf(stderr,"\t\t Initializing ..(%d).. x1=%f, x2=%f , y1=%f y2=%f  logratio=%f t1estimate=%f (%f) denestimate=%f alpha=%f\n",
+		it,x1,x2,y1,y2,logratio,1.0/r1estimate,r1estimate,denestimate,alphaestimate);
+    }
+  
+  position->SetComponent(0,0,denestimate);
+  position->SetComponent(1,0,r1estimate*this->r1scale);
+  position->SetComponent(2,0,alphaestimate*this->alphascale);
+
+
+
+}
+
+void vtkpxExponentialFitT1::InitializeFit(vtkDoubleArray* position) 
+{
+  double denestimate=this->yvalues[0];
+  int opt=0;
+  for (int ia=1;ia<this->numgoodvalues;ia++)
+    if (denestimate<this->yvalues[ia])
+      {
+	denestimate=this->yvalues[ia];
+	opt=ia;
+      }
+  
+  if (denestimate<0.00001)
+    denestimate=0.00001;
+  
+  int minx1=0,minx2=0;
+  double miny1=this->yvalues[opt];
+  double miny2=this->yvalues[opt];
+  for (int ia=0;ia<this->numgoodvalues;ia++)
+    {
+      if (miny1>this->yvalues[ia])
+	{
+	  miny2=miny1;
+	  minx2=minx1;
+	  minx1=ia;
+	  miny1=this->yvalues[ia];
+	}
+      else if (miny2>this->yvalues[ia])
+	{
+	  minx2=ia;
+	  miny2=this->yvalues[ia];
+	}
+      /*      fprintf(stderr,"ia=%d, yvalues[ia]=%f \t\t minx1=%d minx2=%d miny1=%f miny2=%f\n",
+	      ia,yvalues[ia],minx1,minx2,miny1,miny2);*/
+    }
+
+
+  double y1=this->yvalues[minx2];
+  double y2=this->yvalues[minx1];
+
+  double x1=this->xvalues[minx2];
+  double x2=this->xvalues[minx1];
+
+  double rhs1=(1.0-y1/denestimate);
+  double rhs2=(1.0-y2/denestimate);
+
+  double logratio=log(rhs2/rhs1);
+  double r1estimate=logratio/fabs(x2-x1);
+
+  if (r1estimate<0.000001)
+    r1estimate=0.000001;
+
+  //  denestimate=yvalues[opt]/(1.0-exp(-xvalues[opt]*r1estimate));
+
+  double alphaestimate=1.0;
+  /*  if (this->ThreeParameterFit)
+    {
+      alphaestimate=(1.0-this->yvalues[opt]/denestimate)/exp(-this->xvalues[opt]*r1estimate);
+      if (alphaestimate<0.00001)
+	alphaestimate=0.00001;
+	}*/
+  
+  if (this->ThreeParameterFit)
+    {
+      alphaestimate=(y1-y2)/(y1*exp(-x2*r1estimate)-y2*exp(-x1*r1estimate));
+      if (alphaestimate<0.00001)
+	alphaestimate=0.00001;
+    }
+
+  denestimate=yvalues[opt]/(1.0-alphaestimate*exp(-xvalues[opt]*r1estimate));
+
+  if (this->DebugOpt)
+    {
+      fprintf(stderr,"\t\t Initializing ..(%d, %d,%d).. x1=%f, x2=%f , y1=%f y2=%f  logratio=%f t1estimate=%f (%f) denestimate=%f alpha=%f\n",
+	      opt,minx1,minx2,x1,x2,y1,y2,logratio,1.0/r1estimate,r1estimate,denestimate,alphaestimate);
+    }
+
+
+
+  int it=1;
+  int opt2=minx1;
+  if (this->ThreeParameterFit)
+    {
+      alphaestimate=(1.0-this->yvalues[opt2]/denestimate)/exp(-this->xvalues[opt2]*r1estimate);
+      if (alphaestimate<0.00001)
+	alphaestimate=0.00001;
+    }
+  
+  r1estimate=log((1.0-this->yvalues[opt2]/denestimate)/alphaestimate)/(-this->xvalues[opt2]);
+  
+  if (r1estimate<0.000001)
+    r1estimate=0.000001;
+  
+  
+  if (this->DebugOpt)
+    fprintf(stderr,"\t\t Initializing ..(%d).%d/%d. x=%f, , y=%f t1estimate=%f (%f) denestimate=%f alpha=%f\n",
+	    it,opt,opt2,xvalues[opt2],yvalues[opt2],1.0/r1estimate,r1estimate,denestimate,alphaestimate);
+
+
+  position->SetComponent(0,0,denestimate);
+  position->SetComponent(1,0,r1estimate*this->r1scale);
+  position->SetComponent(2,0,alphaestimate*this->alphascale);
+
+
+  
+
+}
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxExponentialFitT1.h b/bioimagesuite30_src/Segmentation/vtkpxExponentialFitT1.h
new file mode 100644
index 0000000..bf4548c
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxExponentialFitT1.h
@@ -0,0 +1,169 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxExponentialFitT1.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxExponentialFitT1 -- compute phase/magnitude from raw reconstruction image on Bruker
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxExponentialFitT1_h
+#define __vtkpxExponentialFitT1_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkIntArray.h"
+#include "vtkpxMatrix.h"
+#include "vtkFloatArray.h"
+
+class vtkpxExponentialFitT1 : public vtkSimpleImageToImageFilter
+{
+public:
+  static vtkpxExponentialFitT1 *New();
+  vtkTypeMacro(vtkpxExponentialFitT1,vtkSimpleImageToImageFilter);
+
+  // Description: 
+  // Create Relaxation Train
+  virtual int CreateRelaxationTimes(float FirstRelaxationTime,float  RelaxationSpacing,int numechos=-1);
+
+  // Description:
+  // Get Outputs
+  vtkGetObjectMacro(RelaxationTimes,vtkFloatArray);
+  vtkSetObjectMacro(RelaxationTimes,vtkFloatArray);
+
+  // Description: 
+  // Thresholds 
+  vtkGetMacro(MaxT1Value,float);
+  vtkSetMacro(MaxT1Value,float);
+
+  // Description: 
+  // Thresholds 
+  vtkSetClampMacro(IntensityThreshold,float,0.0,0.5);
+  vtkGetMacro(IntensityThreshold,float);
+
+  // Description;
+  // density-map (i.e. magnitude of intensity as opposed to relaxation time)
+  vtkGetObjectMacro(DensityMap, vtkImageData);
+
+  // Description;
+  // r1-map (i.e. 1000.0/T1)
+  vtkGetObjectMacro(R1Map, vtkImageData);
+
+  // Description;
+  // Alpha-map (in case of three parameter fit)
+  vtkGetObjectMacro(AlphaMap, vtkImageData);
+
+
+  // Description:
+  // Enable or Disable Fitting for alpha parameter
+  vtkSetClampMacro(ThreeParameterFit,int,0,1);
+  vtkGetMacro(ThreeParameterFit,int);
+  vtkBooleanMacro(ThreeParameterFit,int);
+
+
+  // Description:
+  // These are needed for the Optimizer 
+  static void  OptimizerFeedback(vtkObject* self,const char* line,double val);
+  static double CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output);
+  static double CalculateFunction(vtkObject* self,vtkDoubleArray* position);
+
+protected:
+
+  vtkpxExponentialFitT1();
+  virtual ~vtkpxExponentialFitT1();
+  vtkpxExponentialFitT1(const vtkpxExponentialFitT1&) {};
+  void operator=(const vtkpxExponentialFitT1&) {};
+
+
+  virtual void SimpleExecute(vtkImageData*,vtkImageData*);
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+
+  //BTX
+  float IntensityThreshold;
+  vtkImageData *R1Map,*DensityMap,*AlphaMap;
+  float MaxT1Value;
+  vtkFloatArray* RelaxationTimes;
+  int ThreeParameterFit;
+  double* xvalues;
+  double* yvalues;
+  double currentalpha,currentdensity,currentr1;
+  int numgoodvalues;
+  int DebugOpt;
+  double alphascale;
+  double r1scale;
+  //ETX
+
+  
+
+  // Description:
+  // Needed for Optimizer -- set,get,optimizer,optimizervalue
+  virtual void SetCurrentParameters(vtkDoubleArray* par);
+  virtual void GetCurrentParameters(vtkDoubleArray* par);
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+  virtual void  SetOutputStatus(const char* line,double v);
+
+  // Get Initial Estimates
+  virtual void InitializeFit(vtkDoubleArray* position);
+  virtual void InitializeFit2(vtkDoubleArray* position,double initialden);
+
+
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxHistogramSegmentation.cpp b/bioimagesuite30_src/Segmentation/vtkpxHistogramSegmentation.cpp
new file mode 100644
index 0000000..bfac7a5
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxHistogramSegmentation.cpp
@@ -0,0 +1,910 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxHistogramSegmentation.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxHistogramSegmentation.h"
+#include "vtkpxUtil.h"
+#include "vtkFloatArray.h"
+#include "vtkDoubleArray.h"
+#include "vtkpxUtil.h"
+#include "vtkImageAccumulate.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkpxMath.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkpxImageAlgebra.h"
+#include "vtkImageThreshold.h"
+#include "vtkpxImageRobustHistogram.h"
+#include "vtkImageSeedConnectivity.h"
+#include "vtkImageMedian3D.h"
+#include "pxisinf.h"
+#include "vtkpxSplineStackSource.h"
+//------------------------------------------------------------------------------
+
+
+vtkpxHistogramSegmentation* vtkpxHistogramSegmentation::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxHistogramSegmentation");
+  if(ret)
+    {
+      return (vtkpxHistogramSegmentation*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxHistogramSegmentation;
+}
+
+// Construct object with no children.
+vtkpxHistogramSegmentation::vtkpxHistogramSegmentation()
+{
+  this->NumberOfClasses=3;
+  this->Iterations=30;
+  this->Parameters=NULL;
+  this->InitialParameters=NULL;
+  this->Histogram=NULL;
+  this->Convergence=0.5;
+  this->NumberOfBins=128;
+  this->HistogramOrigin=0.0;
+  this->HistogramSpacing=1.0;
+  this->Sigma=1.0;
+  this->GenerateLabels=0;
+  this->OutlierDetection=0;
+  this->OutlierProbability=0.0;
+  this->PreprocessingMode=2;
+  this->MaskImage=NULL;
+  this->DistributionModel=0;
+  this->MaxSigmaRatio=0.2;
+  this->RobustScaleFactor=4.0;
+  this->KeyChannel=0;
+}
+// ----------------------------------------------------------------------------
+vtkpxHistogramSegmentation::~vtkpxHistogramSegmentation()
+{
+  
+  if (this->Parameters!=NULL)
+    this->Parameters->Delete();
+  this->Parameters=NULL;
+
+  if (this->Histogram!=NULL)
+    this->Histogram->Delete();
+  this->Histogram=NULL;
+
+  this->SetMaskImage(NULL);
+
+  this->SetInitialParameters(NULL);
+
+}
+// ----------------------------------------------------------------------------
+float vtkpxHistogramSegmentation::Metric(float x,float m,float sigma2)
+{
+  if (this->DistributionModel==0)
+    return vtkpxMath::Gaussian(x,m,sigma2);
+  else if (this->DistributionModel==1)
+    return exp(-fabs(x-m)/sqrt(sigma2))/(2.0*sqrt(sigma2));
+
+  return 0.5*(vtkpxMath::Gaussian(x,m,sigma2)+vtkpxMath::Gaussian(x,m,this->RobustScaleFactor*this->RobustScaleFactor*sigma2));
+}
+
+float vtkpxHistogramSegmentation::GetGaussianDifference(float x,float mean1,float mean2,float var1,float var2)
+{
+  return vtkpxMath::Gaussian(x,mean1,var1)-vtkpxMath::Gaussian(x,mean2,var2);
+}
+
+float vtkpxHistogramSegmentation::GetThreshold(float mean1,float mean2,float sigma1,float sigma2)
+{
+  float thr=0.01;
+
+  if (fabs(mean1-mean2)<thr)
+    return 0.5*(mean1+mean2);
+
+  float var1=sigma1*sigma1;
+  float var2=sigma2*sigma2;
+
+  float upperbound=mean1;
+  float lowerbound=mean2;
+	  
+  float test=0.5*(upperbound+lowerbound);
+  float v=0.0;
+
+  while (fabs(upperbound-lowerbound)>thr)
+    {
+      v=vtkpxHistogramSegmentation::GetGaussianDifference(test,mean1,mean2,var1,var2);
+      //      fprintf(stderr,"Testing %.2f (%.2f : %.2f)\n",test,lowerbound,upperbound);
+
+      if (v>0.0)
+	upperbound=test;
+      else
+	lowerbound=test;
+      test=0.5*(upperbound+lowerbound);
+    }
+  //  fprintf(stderr,"Found Threshold %.2f v=%.6f\n",v,test);
+
+  return test;
+}
+// ----------------------------------------------------------------------------
+int vtkpxHistogramSegmentation::CreateHistogram(vtkImageData* input,int NumBins)
+{
+  if (input==NULL)
+    return 0;
+  
+  if (NumBins<4)
+    NumBins=4;
+
+  int UseMask=0;
+  if (this->MaskImage!=NULL)
+    {
+      int nt=this->MaskImage->GetPointData()->GetScalars()->GetNumberOfTuples();
+      int nt2=input->GetPointData()->GetScalars()->GetNumberOfTuples();
+      if (nt==nt2)
+	UseMask=1;
+    }
+
+
+  double range[2]; input->GetPointData()->GetScalars()->GetRange(range);
+  float minv=range[0];
+  float maxv=range[1];
+
+  if (this->PreprocessingMode==2)
+    vtkpxUtil::ImageRobustRange(input,0.002,0.998,minv,maxv);
+  else if (this->PreprocessingMode==1 && minv<1.0)
+    minv=1.0;
+
+  this->HistogramOrigin=minv;
+  this->HistogramSpacing=1.0;
+
+  this->NumberOfBins=NumBins;
+  int drange=int(maxv-minv+1);
+  
+  if (drange< this->NumberOfBins)
+    this->NumberOfBins=drange;
+  
+  while(drange> this->NumberOfBins*this->HistogramSpacing)
+    this->HistogramSpacing+=1.0;
+  
+
+  fprintf(stderr,"\t Input range = %.0f:%.0f   robust=%.0f:%.0f \n",range[0],range[1],minv,maxv);
+  fprintf(stderr,"\t Input bins  = %d          output=%d (drange=%d)\n",NumBins,this->NumberOfBins,drange);
+  fprintf(stderr,"\t Histogram origin=%.0f spacing=%.0f\n",this->HistogramOrigin,this->HistogramSpacing);
+
+  this->NumberOfBins=int(drange/this->HistogramSpacing+0.5);
+
+  vtkpxImageRobustHistogram* accumulate=vtkpxImageRobustHistogram::New();
+  accumulate->SetInput(input);
+  accumulate->InterpolationOff();
+  accumulate->RobustModeOff();
+  accumulate->SaturationModeOff();
+  accumulate->SetLowerThreshold(range[0]);
+  accumulate->SetUpperThreshold(range[1]);
+  accumulate->SetNumberOfBins(this->NumberOfBins);
+  if (UseMask)
+    {
+      accumulate->SetWeightImage(this->MaskImage);
+      accumulate->SetIgnoreMaskedVoxels(0);
+    }
+  accumulate->Update();
+
+  vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+  smooth->SetInput(accumulate->GetOutput());
+  smooth->SetStandardDeviations(this->Sigma,0.0,0.0);
+  smooth->Update();
+
+  if (this->Histogram!=NULL)
+    this->Histogram->Delete();
+
+  this->Histogram=vtkImageData::New();
+  this->Histogram->ShallowCopy(smooth->GetOutput());
+  accumulate->Delete();
+  smooth->Delete();
+  return 1;
+}
+
+
+int vtkpxHistogramSegmentation::InitializeParameters(vtkImageData* histogram,int NumClasses,vtkFloatArray* params)
+{
+  if (histogram==NULL)
+    return 0;
+
+  this->NumberOfClasses=NumClasses;
+  if (this->NumberOfClasses<1)
+    this->NumberOfClasses=1;
+  
+  params->SetNumberOfComponents(3);
+  params->SetNumberOfTuples(this->NumberOfClasses+this->OutlierDetection);
+  params->FillComponent(0,1.0);
+
+  int dim[3]; this->Histogram->GetDimensions(dim);
+
+  double range[2];
+  range[0]=this->HistogramOrigin;
+  range[1]=this->HistogramSpacing*float(dim[0]-1);
+
+  fprintf(stderr,"Beginning range = %.0f:%.0f\n Initial Means:\n",range[0],range[1]);
+
+  int numtuples=this->Parameters->GetNumberOfTuples();
+  float s=(range[1]-range[0])/float(this->NumberOfClasses);
+
+  if (this->InitialParameters!=NULL)
+    {
+
+      int nc=this->InitialParameters->GetNumberOfComponents();
+      int docopy=1;
+      if (nc==0)
+	docopy=0;
+
+      if (numtuples==this->InitialParameters->GetNumberOfTuples())
+	docopy=1;
+
+      if (numtuples==this->InitialParameters->GetNumberOfTuples()+1 && this->OutlierDetection==1)
+	docopy=1;
+
+      int offset=0;
+      if (nc>2)
+	offset=1;
+
+      if (docopy)
+	{
+	  fprintf(stderr,"\n\n ****** Using Initial Parameters ************ \n");
+	  for (int j=0;j<numtuples-this->OutlierDetection;j++)
+	    {
+	      params->SetComponent(j,1,this->InitialParameters->GetComponent(j,0+offset));
+	      if (nc>1)
+		params->SetComponent(j,2,this->InitialParameters->GetComponent(j,1+offset));
+	      else
+		params->SetComponent(j,2,s);
+
+	    }
+	  return 1;
+	}
+    }
+  for (int j=0;j<numtuples;j++)
+    {
+      float s=(range[1]-range[0])/float(this->NumberOfClasses);
+      float m =range[0]+ float(j+0.5)/float(this->NumberOfClasses)*(range[1]-range[0]);
+      // fprintf(stderr,"\t c=%d   mean=%.1f   sigma=%.1f\n",j+1,m,s);
+      params->SetComponent(j,1,m);
+      params->SetComponent(j,2,s);
+      params->SetComponent(j,0,1.0);
+    }
+ 
+
+  return 1;
+}
+
+
+// ---------------------------------------------------------------------------------------------
+//
+//     Execute Segmentation 
+//
+// ----------------------------------------------------------------------------
+void vtkpxHistogramSegmentation::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+  output->SetScalarTypeToFloat();
+  output->SetNumberOfScalarComponents(1);
+}
+
+void vtkpxHistogramSegmentation::SimpleExecute(vtkImageData* input,vtkImageData* output )
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxHistogramSegmentation");
+      return;
+    }
+
+  int nc=input->GetNumberOfScalarComponents();
+
+  if (this->KeyChannel<0)
+    this->KeyChannel=0;
+  if (this->KeyChannel>=nc)
+    this->KeyChannel=nc-1;
+
+  // Restrict input to single frame and float
+  vtkImageExtractComponents* extr=vtkImageExtractComponents::New();
+  extr->SetInput(input);
+  extr->SetComponents(this->KeyChannel);
+  extr->Update();
+  this->UpdateProgress(0.1);
+
+  if (this->Parameters==NULL)
+    this->Parameters=vtkFloatArray::New();
+
+  this->HistogramSegmentation(extr->GetOutput(),output,this->Parameters,0);
+  this->UpdateProgress(1.0);
+  extr->Delete();
+
+}
+
+void vtkpxHistogramSegmentation::HistogramSegmentation(vtkImageData* single_channel,vtkImageData* labels,vtkFloatArray* parameters,
+						       int useparams,int usevar)
+{
+  this->CreateHistogram(single_channel,this->NumberOfBins);
+  if (useparams==0)
+    this->InitializeParameters(this->Histogram,this->NumberOfClasses,parameters);
+
+  this->UpdateProgress(0.05);
+
+  int dim[3]; this->Histogram->GetDimensions(dim);
+  vtkDataArray* data=this->Histogram->GetPointData()->GetScalars();
+
+  // ----------------- EM Estimation -------------------------------------
+  int numclasses=this->Parameters->GetNumberOfTuples();
+  float* mean =new float[numclasses];
+  float* sigma2=new float[numclasses];
+  float* sum  =new float[numclasses];
+  float* sum2 =new float[numclasses];
+  float*  num =new float[numclasses];
+
+  fprintf(stderr,"\n**** Initial Parameters (maxsigmaratio=%.3f, Dist Model=%d, RobustScaleFactor=%.2f) \n --------------------------\n",
+	  this->MaxSigmaRatio,this->DistributionModel,this->RobustScaleFactor);
+  for (int j=0;j<numclasses;j++)
+    {
+      sigma2[j]=parameters->GetComponent(j,2);      sigma2[j]*=sigma2[j];
+      mean[j] =parameters->GetComponent(j,1);
+      fprintf(stderr,"\t c=%d   mean=%.1f   sigma=%.1f\n",j+1,mean[j],sqrt(sigma2[j]));
+    }
+
+  // ----------------------------------------------------------------------------------
+  //            Iterations
+  // ----------------------------------------------------------------------------------
+  int iter=1;
+  float error=this->Convergence+1.0;
+  
+  while (iter <= this->Iterations && error > this->Convergence)
+    {
+      error=0.0;
+      float totalnum=0.0;
+      
+      for (int i=0;i<numclasses;i++)	{ sum[i]=0.0; sum2[i]=0.0; num[i]=0.0; }
+      
+      for (int bin=0;bin<dim[0];bin++)
+	{
+	  float v=this->HistogramOrigin+float(bin)*this->HistogramSpacing;
+	  float numv=data->GetComponent(bin,0);
+	  if (isnan(numv))
+	    numv=0.0;
+	  float bestp=0.0;
+	  int   bestc=0;
+
+	  for (int c=0;c<numclasses;c++)
+	    {
+	      float t=this->OutlierProbability;
+	      if (c<this->NumberOfClasses)
+		{
+		  if (usevar)
+		    t=this->Metric(v,mean[c],sigma2[c]);
+		  else
+		    t=this->Metric(v,mean[c],sigma2[0]);
+		}
+	      if (t>bestp)  {  bestp=t;  bestc=c;  }
+	    }
+	  num[bestc]+=numv;  sum[bestc]+=v*numv;  sum2[bestc]+=v*v*numv;  totalnum+=numv;
+	}
+      
+     fprintf(stderr,"It=%03d : \t",iter);
+     
+     // Compute Parameters
+     // ------------------
+     float maxsigma=0.0;
+     for (int c=0;c<numclasses;c++)
+       {
+	 //	 fprintf(stderr,"c=%d num[c]=%.1f  sum[c]=%.1f sum2[c]=%.1f\t",c,num[c],sum[c],sum2[c]);
+	 if (num[c]<1.0)  num[c]=1.0;
+
+	 //	 fprintf(stderr,"num[c]=%.1f  sum[c]=%.1f sum2[c]=%.1f\n",num[c],sum[c],sum2[c]);
+
+	 float m=sum[c]/num[c];
+	 if (c<this->NumberOfClasses)
+	   error=Fmax(fabs(m-mean[c]),error);
+	 
+	 mean[c]=m;
+	 sigma2[c]=(sum2[c]/num[c]-mean[c]*mean[c]);
+	 if (this->DistributionModel==1)
+	   sigma2[c]=0.5*sigma2[c];
+	 
+	 if (isnan(sigma2[c]) || sigma2[c]<2.0)
+	   sigma2[c]=2.0;
+
+	 float s=sqrt(sigma2[c]);
+	 if (isnan(s))
+	   s=2.0;
+	 if (s>maxsigma)
+	   maxsigma=s;
+       }
+
+     // Enforce MaxSigmaRatio (0.1)
+     // ---------------------------
+     for (int c=0;c<numclasses;c++)
+       {
+	 float s=sqrt(sigma2[c]);
+	 if (s<this->MaxSigmaRatio*maxsigma)
+	   sigma2[c]=pow(this->MaxSigmaRatio*maxsigma,float(2.0));
+	 if (isnan(sigma2[c]))
+	   sigma2[c]=2.0;
+	 parameters->SetComponent(c,1,mean[c]);
+	 parameters->SetComponent(c,2,sqrt(sigma2[c]));
+	 parameters->SetComponent(c,0,num[c]);
+	 fprintf(stderr,"%.1f + %.1f (%5.2f)\t",mean[c],sqrt(sigma2[c]),100.0*num[c]/totalnum);
+       }
+      fprintf(stderr,"usevar=%d error=%.2f\n",usevar,error);
+      ++iter;
+    }
+
+  // At this point sort via mean[c]
+  // ------------------------------
+  fprintf(stderr,"\n\nSorting \n-----------------\n");
+  for (int c=0;c<this->NumberOfClasses;c++)
+    {
+      int best=c;
+      float bestm=mean[c];
+
+      fprintf(stderr,"Orig: class %d :  mean=%.2f sigma=%.2f number=%.2f\n\t Means:",best,
+	      parameters->GetComponent(best,1),
+	      parameters->GetComponent(best,2),parameters->GetComponent(best,0));
+      
+      for (int c1=0;c1<this->NumberOfClasses;c1++)
+	fprintf(stderr,"%.2f ",mean[c1]);
+      fprintf(stderr,"\n");
+
+      for (int c1=0;c1<this->NumberOfClasses;c1++)
+	{
+	  if (mean[c1]<bestm)
+	    {
+	      bestm=mean[c1];
+	      best=c1;
+	    }
+	}
+      
+      parameters->SetComponent(c,1,mean[best]);
+      parameters->SetComponent(c,2,sqrt(sigma2[best]));
+      parameters->SetComponent(c,0,num[best]);
+      mean[best]=1e+10;
+      //      sigma2[best]=sigma2[c];
+      //      num[best]=num[c];
+
+      fprintf(stderr,"\t\t Final class %d : orig=%d mean=%.2f sigma=%.2f number=%.2f\n",c,best,
+	      parameters->GetComponent(c,1),
+	      parameters->GetComponent(c,2),parameters->GetComponent(c,0));
+
+
+
+    }
+
+  //  vtkDataArray* outdata=labels->GetPointData()->GetScalars();
+  //  outdata->FillComponent(0,0.0);
+  if (this->GenerateLabels)
+    {
+      float *thresholds=new float[numclasses];
+      for (int j=0;j<(numclasses-1);j++)
+	thresholds[j]=this->GetThreshold(parameters->GetComponent(j,1),parameters->GetComponent(j+1,1),
+					 parameters->GetComponent(j,2),parameters->GetComponent(j+1,2));
+      thresholds[numclasses-1]=1e+10;
+      
+      vtkDoubleArray* map=vtkDoubleArray::New();
+      map->SetNumberOfComponents(3);
+      map->SetNumberOfTuples(numclasses);
+      
+      for (int j=0;j<numclasses;j++)
+	{
+	  map->SetComponent(j,0,thresholds[j]);
+	  map->SetComponent(j,1,float(j));
+	  map->SetComponent(j,2,0.0);
+	  //	  fprintf(stderr,"If x < %.3f --> x=%.2f\n",thresholds[j],float(j));
+	}
+
+      vtkpxImageAlgebra* algebra=vtkpxImageAlgebra::New();
+      algebra->SetInput(single_channel);
+      algebra->SetMap(map);
+      algebra->SetOutputScalarTypeToShort();
+      algebra->Update();
+      labels->ShallowCopy(algebra->GetOutput());
+      algebra->Delete();
+
+      delete [] thresholds;
+    }
+  delete [] mean;  delete [] sigma2;  delete [] sum;  delete [] sum2;  delete [] num;
+}
+
+// -------------------------------------------------------------------------------------------------------------------------------------------
+int vtkpxHistogramSegmentation::HistogramNormalizeImage(vtkImageData* image,float pmin,float pmax)
+{
+  if (image==NULL)
+    {
+      fprintf(stderr,"Bad Input to Histogram Normalize Image\n");
+      return 0;
+    }
+
+  pmin=Frange(pmin,0.0,0.95);
+  pmax=Frange(pmax,pmin+0.05,1.0);
+
+  float tlow,thigh;
+  vtkpxUtil::ImageRobustRange(image,pmin,pmax,tlow,thigh);
+  double range[2]; image->GetPointData()->GetScalars()->GetRange(range);
+  fprintf(stderr,"Histogram Image Normalization (%.2f:%.2f) r=(%.1f:%.1f) --> ",pmin,pmax,range[0],range[1]);
+
+  vtkDoubleArray* map=vtkDoubleArray::New();
+  map->SetNumberOfComponents(3);
+  map->SetNumberOfTuples(3);
+  map->SetComponent(0,0,tlow);   map->SetComponent(0,1,tlow);   map->SetComponent(0,2,0.0);
+  map->SetComponent(1,0,thigh);  map->SetComponent(1,1,0.0);    map->SetComponent(1,2,1.0);
+  map->SetComponent(2,0,range[1]+10.0);   map->SetComponent(2,1,thigh);   map->SetComponent(2,2,0.0);
+  vtkpxImageAlgebra* algebra=vtkpxImageAlgebra::New();
+
+  algebra->SetInput(image);
+  algebra->SetMap(map);
+  algebra->Update();
+  image->ShallowCopy(algebra->GetOutput());
+  algebra->Delete();
+  map->Delete();
+  image->GetPointData()->GetScalars()->GetRange(range);
+  fprintf(stderr,"(%.1f : %.1f)\n",range[0],range[1]);
+
+  return 1;
+}
+
+// -------------------------------------------------------------------------------------------------------------------------------------------
+vtkImageData* vtkpxHistogramSegmentation::ComputeFatValues(vtkImageData* orig_image,vtkImageData* orig_map,vtkpxSplineStackSource* surface,
+							   int abd_fat_value,int artifact_value,int subq_fat_value,int numclasses)
+{
+  vtkImageData* output=vtkImageData::New();
+  output->CopyStructure(orig_map);
+  output->AllocateScalars();
+
+  fprintf(stderr,"\n\n+++++ Creating Surface Object Map\n");
+  surface->CreateObjectMap(output);
+
+  vtkImageData* artifactfree=vtkImageData::New();
+  artifactfree->DeepCopy(orig_image);
+
+  fprintf(stderr,"+++++ Eliminating Artifacts = %d\n",artifact_value);
+  vtkDataArray* inp=artifactfree->GetPointData()->GetScalars();
+  vtkDataArray* map=orig_map->GetPointData()->GetScalars();
+  int np=map->GetNumberOfTuples();
+  for (int i=0;i<np;i++)
+    {
+      if (map->GetComponent(i,0)==artifact_value)
+	inp->SetComponent(i,0,0.0);
+    }
+
+
+  fprintf(stderr,"+++++ Histogram Segmentation\n");
+
+  vtkpxHistogramSegmentation* hist=vtkpxHistogramSegmentation::New();
+  hist->DebugOn();
+  hist->SetInput(artifactfree);
+  hist->SetNumberOfClasses(numclasses);
+  hist->SetGenerateLabels(1);
+  hist->DebugOff();
+  hist->Update();
+
+  //  vtkpxUtil::SaveAnalyze("hist.hdr",hist->GetOutput(),0);
+
+
+  fprintf(stderr,"+++++ Final Objectmap Output\n");
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* back=hist->GetOutput()->GetPointData()->GetScalars();
+
+  for (int j=0;j<np;j++)
+    {
+      float bk  =  back->GetComponent(j,0);
+      float abd =   out->GetComponent(j,0);
+      float visc=   map->GetComponent(j,0);
+      
+      if (visc!=artifact_value)
+	{
+	  if (abd>0)
+	    {
+	      if (visc==abd_fat_value && abd ==2 )
+		out->SetComponent(j,0,3);
+	      else if (abd==1 && bk>2 )
+		out->SetComponent(j,0,2);
+	      else
+		out->SetComponent(j,0,0);
+	    }
+	 
+	} 
+      else
+	{
+	  out->SetComponent(j,0,artifact_value);
+	}
+    }
+
+  hist->Delete();
+  artifactfree->Delete();
+  return output;
+}
+
+vtkImageData* vtkpxHistogramSegmentation::CreateRayleighSynthetic(float beta,float m1,float sigma1,float m2,float sigma2)
+{
+  vtkImageData* tmp=vtkImageData::New();
+  int dim=128;
+  tmp->SetDimensions(dim,dim,dim);
+  tmp->SetScalarTypeToShort();
+  tmp->AllocateScalars();
+
+  int mid=dim/2;
+
+  float sum=0.0,sumn=0.0,sum2=0.0;
+
+  for (int k=0;k<dim;k++)
+    for (int j=0;j<dim;j++)
+      for (int i=0;i<dim;i++)
+	{
+	  float signal=vtkpxMath::GaussianRandom();
+	  float noise=vtkpxMath::GaussianRandom();
+	  float noise2=vtkpxMath::GaussianRandom();
+	  noise=beta*sqrt(noise*noise+noise2*noise2);	
+
+	  if ( i<dim/3)
+	    {
+	      signal=sigma1*signal+m1;
+
+	    }
+	  else if (i<2*dim/3)
+	    {
+	      signal=sigma2*signal+m2;
+
+	    }
+	  else
+	    {
+	      signal=noise;
+	      
+	    }
+	  tmp->SetScalarComponentFromDouble(i,j,k,0,signal);
+	  sum+=noise;
+	  sum2+=noise*noise;
+	  sumn+=1.0;
+	}
+
+  double mean=sum/sumn;
+  double sigma=sqrt(sum2/sumn-mean*mean);
+  double sig2 =sqrt(sum2/sumn-beta*beta);
+  fprintf(stderr,"Gaussian Fit=%.2f,%.2f or %.2f\n",mean,sigma,sig2);
+
+  return tmp;
+}
+	    
+
+// -------------------------------------------------------------------------------------------------------------------------------------------
+vtkImageData* vtkpxHistogramSegmentation::ComputeCaprioFatValues(vtkImageData* orig_map,
+								 vtkpxSplineStackSource* visceral_surface,
+								 vtkpxSplineStackSource* abdomen_surface,
+								 vtkpxSplineStackSource* fascia_surface,
+								 vtkpxSplineStackSource* skin_surface,
+								 float minv,float maxv)
+{
+  vtkImageData* output=vtkImageData::New();
+  output->CopyStructure(orig_map);
+  output->AllocateScalars();
+
+  // inside =2 , outside =1 offslice =0
+  vtkImageData* internal=vtkImageData::New(); internal->CopyStructure(orig_map); internal->AllocateScalars(); 
+  visceral_surface->CreateObjectMap(internal);
+  
+  vtkImageData* abdomen=vtkImageData::New();  abdomen->CopyStructure(orig_map); abdomen->AllocateScalars(); 
+  abdomen_surface->CreateObjectMap(abdomen);
+  
+  vtkImageData* deepsub=vtkImageData::New();    deepsub->CopyStructure(orig_map); deepsub->AllocateScalars(); 
+  fascia_surface->CreateObjectMap(deepsub);
+  
+  vtkImageData* superficial=vtkImageData::New(); superficial->CopyStructure(orig_map); superficial->AllocateScalars(); 
+  skin_surface->CreateBoundedObjectMap(fascia_surface,superficial);
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* inner=internal->GetPointData()->GetScalars();
+  vtkDataArray*   abd=abdomen->GetPointData()->GetScalars();
+  vtkDataArray*  deep=deepsub->GetPointData()->GetScalars();
+  vtkDataArray* super=superficial->GetPointData()->GetScalars();
+  
+  vtkDataArray* inp=orig_map->GetPointData()->GetScalars();
+  out->FillComponent(0,0.0);
+
+  if (maxv==-1.0 || minv==-1.0)
+    {
+      double range[2]; inp->GetRange(range);
+      minv=range[1]-0.2;
+      maxv=range[1]+0.2;
+    }
+
+  int np=out->GetNumberOfTuples();
+
+  for (int index=0;index<np;index++)
+    {
+      double fat=inp->GetComponent(index,0);
+      
+      if (inner->GetComponent(index,0)==2)
+	{
+	  if (fat>=minv && fat <=maxv)
+	    out->SetComponent(index,0,3.0);
+	}
+      else if (abd->GetComponent(index,0)==1)
+	{
+	  // outside the abdomen
+	  if (fat>=minv && fat <=maxv)
+	    {
+	      if (deep->GetComponent(index,0)==2)
+		out->SetComponent(index,0,1.0);
+	      else if (super->GetComponent(index,0)==2)
+		out->SetComponent(index,0,2.0);
+	      else if (super->GetComponent(index,0)==3)
+		out->SetComponent(index,0,4.0);
+	    }
+	}
+    }
+
+  internal->Delete();
+  abdomen->Delete();
+  deepsub->Delete();
+  superficial->Delete();
+  return output;
+}
+  
+// -------------------------------------------------------------------------------------------------------------------------------------------
+int vtkpxHistogramSegmentation::ComputeSegmentedMapStatistics(vtkImageData* image,vtkImageData* map,vtkFloatArray* output_values)
+{
+  if (image==NULL || map==NULL || output_values==NULL)
+    return 0;
+
+
+  double range[2]; 
+  vtkDataArray* labels=map->GetPointData()->GetScalars();
+  vtkDataArray* values=image->GetPointData()->GetScalars();
+
+  if (labels->GetNumberOfTuples()!=values->GetNumberOfTuples())
+    {
+      fprintf(stderr,"Bad Match between labels and image\n");
+      return 0;
+    }
+
+  labels->GetRange(range,0);
+
+  int pbmap=0,numclasses=1;
+  if (map->GetNumberOfScalarComponents()==1)
+    {
+      
+      numclasses=int(range[1]-range[0]+1);
+      if (numclasses>20)
+	{
+	  fprintf(stderr,"Too many classes for meaningful statistics\n");
+	  return 0;
+	}
+    }
+  else
+    {
+      pbmap=1;
+      numclasses=map->GetNumberOfScalarComponents()-1;
+    }
+
+  fprintf(stderr,"Numclasses=%d numcomponents=%d pbmap=%d\n",numclasses,
+	  map->GetNumberOfScalarComponents(),pbmap);
+
+  int numcomponents=image->GetNumberOfScalarComponents();
+  
+  output_values->SetNumberOfComponents(4*numcomponents); // volume , numpix, mean, std   for each component
+  output_values->SetNumberOfTuples(numclasses);
+  
+  for (int j=0;j<4*numcomponents;j++)
+    output_values->FillComponent(j,0);
+  
+  int nt=labels->GetNumberOfTuples();
+  
+  for (int i=0;i<nt;i++)
+    {
+      if (pbmap==0)
+	{
+	  int l=(int)(labels->GetComponent(i,0)-range[0]);
+	  for (int c=0;c<numcomponents;c++)
+	    {
+	      float v=values->GetComponent(i,c);
+	      int index=c*4;
+	      
+	      // Count Pixels
+	      output_values->SetComponent(l,index+1,output_values->GetComponent(l,index+1)+1.0);
+	      output_values->SetComponent(l,index+2,output_values->GetComponent(l,index+2)+v);
+	      output_values->SetComponent(l,index+3,output_values->GetComponent(l,index+3)+v*v);
+	    }
+	}
+      else
+	{
+	  for (int c=0;c<numcomponents;c++)
+	    {
+	      float v=values->GetComponent(i,c);
+	      int index=c*4;
+	      for (int cl=0;cl<numclasses;cl++)
+		{
+		  float prob=labels->GetComponent(i,cl+1);
+		  output_values->SetComponent(cl,index+1,output_values->GetComponent(cl,index+1)+prob);
+		  output_values->SetComponent(cl,index+2,output_values->GetComponent(cl,index+2)+v*prob);
+		  output_values->SetComponent(cl,index+3,output_values->GetComponent(cl,index+3)+v*v*prob);
+		}
+	    }
+	}
+    }
+  
+  double sp[3]; image->GetSpacing(sp);
+  float volpix=sp[0]*sp[1]*sp[2];
+  
+  for (int l=0;l<numclasses;l++)
+    for (int c=0;c<numcomponents;c++)
+      {
+	int index=c*4;
+	
+	// First Volume
+	float numvox=output_values->GetComponent(l,index+1);
+	output_values->SetComponent(l,index,numvox*volpix);
+	
+	// Then Mean
+	float mean=output_values->GetComponent(l,index+2);
+	float mean2=output_values->GetComponent(l,index+3);
+	
+	mean=mean/numvox;
+	mean2=mean2/numvox-mean*mean;
+	
+	output_values->SetComponent(l,index+2,mean);
+	output_values->SetComponent(l,index+3,sqrt(mean2));
+	
+	/*	fprintf(stderr,"Label =%d  Component=%d (index=%d (nt=%d,nc=%d))  Volume=%.2f (%.0f)\t Mean=%.2f std=%.2f\n",
+		l+1,c+1,index,
+		output_values->GetNumberOfTuples(),
+		output_values->GetNumberOfComponents(),
+		output_values->GetComponent(l,index),
+		output_values->GetComponent(l,index+1),
+		output_values->GetComponent(l,index+2),
+		output_values->GetComponent(l,index+3));*/
+      }
+
+
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxHistogramSegmentation.h b/bioimagesuite30_src/Segmentation/vtkpxHistogramSegmentation.h
new file mode 100644
index 0000000..3ff3b03
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxHistogramSegmentation.h
@@ -0,0 +1,257 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxHistogramSegmentation.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxHistogramSegmentation -- compute segmentation betwenn images using a simplified mono-exponential model
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+//
+//
+//  Best Approximation to Rayleigh Beta for Right hand side tail of peak
+// x~R(beta), x~N(1.14*beta,0.744*beta)
+//
+//   
+//  Useful Gnuplot Code
+//
+//   r(x,b)=x/(b*b)*exp(-(0.5*x*x)/(b*b));
+//   g(x,m,s)=1.0/sqrt(2.0*pi*s*s)*exp(-0.5*(x-m)*(x-m)/(s*s));
+//
+// plot r(x,1000) w l, g(x,1140,760),0.56*g(x,1120,653)+0.44*g(x,1283,841)
+//
+//
+
+#ifndef __vtkpxHistogramSegmentation_h
+#define __vtkpxHistogramSegmentation_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkFloatArray.h"
+
+class vtkpxSplineStackSource;
+
+
+class vtkpxHistogramSegmentation : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkpxHistogramSegmentation *New();
+  vtkTypeMacro(vtkpxHistogramSegmentation,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Number Of Classes
+  vtkGetMacro(DistributionModel,int);
+  vtkSetClampMacro(DistributionModel,int,0,1);
+
+  // Description:
+  // Sigma Scale for Robust Distribution Model (i.e. Sum of Gaussians)
+  vtkSetClampMacro(RobustScaleFactor,float,1.0,20.0);
+  vtkGetMacro(RobustScaleFactor,float);
+
+  // Description:
+  // Number Of Classes
+  vtkGetMacro(MaxSigmaRatio,float);
+  vtkSetClampMacro(MaxSigmaRatio,float,0.0001,0.9);
+
+  // Description:
+  // Number Of Classes
+  vtkGetMacro(NumberOfClasses,int);
+  vtkSetClampMacro(NumberOfClasses,int,1,10);
+
+  // Description:
+  // Number Of Iterations
+  vtkGetMacro(Iterations,int);
+  vtkSetClampMacro(Iterations,int,0,200);
+
+  // Description:
+  // Key Channel i.e. channel to perform initial clustering on
+  vtkGetMacro(KeyChannel,int);
+  vtkSetMacro(KeyChannel,int);
+
+  // Description:
+  // Number Of Iterations
+  vtkGetMacro(NumberOfBins,int);
+  vtkSetClampMacro(NumberOfBins,int,4,1024);
+
+  // Description:
+  // Convergence for CMeans Values (<1.0)
+  vtkGetMacro(Convergence,float);
+  vtkSetClampMacro(Convergence,float,0.05,100);
+
+  // Description:
+  // Histogram Sigma
+  vtkGetMacro(Sigma,float);
+  vtkSetClampMacro(Sigma,float,0.05,5.0);
+
+  // Description:
+  // Number Of Iterations
+  vtkGetMacro(GenerateLabels,int);
+  vtkSetClampMacro(GenerateLabels,int,0,1);
+  vtkBooleanMacro(GenerateLabels,int);
+
+
+  // Description:
+  // Get Outputs
+  vtkGetObjectMacro(InitialParameters,vtkFloatArray);
+  vtkSetObjectMacro(InitialParameters,vtkFloatArray);
+
+  // Description:
+  // Get Outputs
+  vtkGetObjectMacro(MaskImage,vtkImageData);
+  vtkSetObjectMacro(MaskImage,vtkImageData);
+
+
+  // Description:
+  // Get Outputs
+  vtkGetObjectMacro(Parameters,vtkFloatArray);
+  vtkGetObjectMacro(Histogram,vtkImageData);
+
+
+  // Description:
+  // Outlier Class
+  vtkSetClampMacro(OutlierDetection,int,0,1);
+  vtkGetMacro(OutlierDetection,int);
+  vtkBooleanMacro(OutlierDetection,int);
+
+
+  // Description:
+  // Outlier Probability
+  vtkSetMacro(OutlierProbability,float);
+  vtkGetMacro(OutlierProbability,float);
+
+  // Description:
+  // Outlier Class
+  vtkSetClampMacro(PreprocessingMode,int,0,2);
+  vtkGetMacro(PreprocessingMode,int);
+
+  /*  // Description:
+  // Outlier Class
+  vtkSetClampMacro(RayleighDistributedBackground,int,0,1);
+  vtkGetMacro(RayleighDistributedBackground,int);*/
+
+
+  // Description:
+  // Normalize Image Using Histogram
+  static int HistogramNormalizeImage(vtkImageData* image,float pmin,float pmax);
+
+  // Description:
+  // Fat Computation Stuff
+  static vtkImageData* ComputeFatValues(vtkImageData* orig_image,vtkImageData* orig_map,vtkpxSplineStackSource* surface,
+					int abd_fat_value,int artifact_value,int subq_fat_value,int numclasses);
+
+  static vtkImageData* ComputeCaprioFatValues(vtkImageData* orig_map,
+					      vtkpxSplineStackSource* abdomen_surface,
+					      vtkpxSplineStackSource* visceral_surface,
+					      vtkpxSplineStackSource* fascia_surface,
+					      vtkpxSplineStackSource* skin_surface,
+					      float minv,float maxv);
+
+  // Description:
+  // ROI Analysis Stuff
+  static int ComputeSegmentedMapStatistics(vtkImageData* image,vtkImageData* map,vtkFloatArray* output_values);
+
+  // Description:
+  // Create Synthetic Two Channel Image (Three concentric circles) with Rayleigh Noise
+  static vtkImageData*   CreateRayleighSynthetic(float beta,float m1,float sigma1,float m2,float sigma2);
+
+  // Description:
+  // Get Threshold
+  static float GetThreshold(float mean1,float mean2,float sigma1,float sigma2);
+  static float GetGaussianDifference(float x,float m1,float m2,float var1,float var2);
+protected:
+
+  vtkpxHistogramSegmentation();
+  virtual ~vtkpxHistogramSegmentation();
+  vtkpxHistogramSegmentation(const vtkpxHistogramSegmentation&) {};
+  void operator=(const vtkpxHistogramSegmentation&) {};
+
+  virtual void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData* in,vtkImageData* out);
+
+  virtual void HistogramSegmentation(vtkImageData* singlechanngel,vtkImageData* labels,vtkFloatArray* initial_parameters,int useinitial=1,int usevar=1);
+
+
+  // Description:
+  // Metric
+  virtual float Metric(float x,float m,float sigma2);
+
+
+  // Description:
+  // Components 
+  virtual int CreateHistogram(vtkImageData* input,int NumBins);
+  virtual int InitializeParameters(vtkImageData* histogram,int numclasses,vtkFloatArray* params);
+
+  int           NumberOfClasses;
+  //  int           RayleighDistributedBackground;
+  int           Iterations;
+  float         Convergence;
+  float         HistogramOrigin;
+  float         HistogramSpacing;
+  float         Sigma;
+  vtkFloatArray* Parameters;
+  vtkFloatArray* InitialParameters;
+  vtkImageData* Histogram;
+  vtkImageData* MaskImage;
+  int           NumberOfBins;
+  int           GenerateLabels;
+  int           OutlierDetection;
+  int           PreprocessingMode;
+  float         OutlierProbability;
+  int           DistributionModel;
+  float         MaxSigmaRatio;
+  float         RobustScaleFactor;
+  int           KeyChannel;
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxImageRobustHistogram.cpp b/bioimagesuite30_src/Segmentation/vtkpxImageRobustHistogram.cpp
new file mode 100644
index 0000000..4546825
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxImageRobustHistogram.cpp
@@ -0,0 +1,453 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkpxImageRobustHistogram.h"
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkpxUtil.h"
+#include <stdio.h>
+#include "pxutil.h"
+#include "pxisinf.h"
+#include <math.h>
+
+vtkpxImageRobustHistogram* vtkpxImageRobustHistogram::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageRobustHistogram");
+  if(ret)
+    {
+      return (vtkpxImageRobustHistogram*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxImageRobustHistogram;
+}
+
+
+// Construct object to extract all of the input data.
+vtkpxImageRobustHistogram::vtkpxImageRobustHistogram()
+{
+  this->NumberOfBins=128;
+  this->Interpolation=0;
+  this->LowerBound=0.0;
+  this->UpperBound=1.0;
+  this->LowerThreshold=0.0;
+  this->UpperThreshold=0.0;
+  this->Entropy=0.0;
+  this->Initialized=0;
+  this->RobustMode=0;
+  this->SaturationMode=0;
+  this->LastOutput=NULL;
+  this->WeightImage=NULL;
+  this->IgnoreMaskedVoxels=1;
+}
+
+vtkpxImageRobustHistogram::~vtkpxImageRobustHistogram()
+{
+  if (this->LastOutput!=NULL)
+    this->LastOutput->Delete();
+  this->SetWeightImage(NULL);
+}
+// ---------------------------------------------------------------------------
+void vtkpxImageRobustHistogram::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkpxSimpleImageToImageFilter::PrintSelf(os,indent);
+
+  os << indent << "  WeightImage " << this->WeightImage << "\n";
+  os << indent << "  NumberOfBins " << this->NumberOfBins << "\n";
+  os << indent << "  Interpolation " << this->Interpolation << "\n";
+  os << indent << "  RobustMode " << this->RobustMode << "\n";
+  os << indent << "  SaturationMode " << this->SaturationMode << "\n";
+  os << indent << "  Bounds " << this->LowerBound << ":" << this->UpperBound << "\n";
+  os << indent << "  Thresholds " << this->LowerThreshold << ":" << this->UpperThreshold << "\n";
+  os << indent << "  Entropy " << this->Entropy << "\n";
+  os << indent << "  Initialized " << this->Initialized << "\n";
+}
+// ---------------------------------------------------------------------------
+void vtkpxImageRobustHistogram::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+
+  if (input==NULL)
+    return;
+
+  double sp[3]; sp[1]=1.0; sp[2]=1.0;
+
+  this->UpdateThresholds();
+  sp[0]=(this->UpperThreshold-this->LowerThreshold)/double(this->NumberOfBins);
+
+  int wholeExtent[6];
+  int dims[3];    dims[1]=1; dims[2]=1; dims[0]=this->NumberOfBins;
+
+  wholeExtent[0]=0;
+  wholeExtent[1]=dims[0]-1;
+  wholeExtent[2]=0;
+  wholeExtent[3]=0;
+  wholeExtent[4]=0;
+  wholeExtent[5]=0;
+
+  output->SetSpacing(sp[0],sp[1],sp[2]);
+  output->SetOrigin(this->LowerThreshold,0.0,0.0);
+  output->SetWholeExtent( wholeExtent );
+  output->SetUpdateExtent( wholeExtent );
+  output->SetScalarTypeToDouble();
+  output->SetNumberOfScalarComponents(1);
+
+}
+// ---------------------------------------------------------------------------
+void vtkpxImageRobustHistogram::BackupHistogram()
+{
+  if (this->Initialized==0)
+    return;
+
+  if (this->LastOutput==NULL)
+    this->LastOutput=vtkImageData::New();
+  this->LastOutput->DeepCopy(this->GetOutput());
+}
+// ---------------------------------------------------------------------------
+void vtkpxImageRobustHistogram::SetPlainHistogram()
+{
+  this->RobustMode=0;
+  this->Interpolation=0;
+  this->SaturationMode=0;
+}
+// ---------------------------------------------------------------------------
+void vtkpxImageRobustHistogram::UpdateThresholds()
+{
+  vtkImageData* input=this->GetInput();
+  if (input==NULL)
+    return;
+
+  //  fprintf(stderr,"Frame=%d\n",this->Frame);
+
+  double range[2]; input->GetPointData()->GetScalars()->GetRange(range,this->Frame);
+  float minv=range[0];
+  float maxv=range[1];
+
+  if (this->RobustMode==1)
+  {
+      vtkpxUtil::ImageRobustRange(input,this->LowerBound,this->UpperBound,minv,maxv);
+
+      if (this->LowerBound>0.0)
+	this->LowerThreshold=minv;
+      else
+	this->LowerThreshold=range[0];
+
+      if (this->UpperBound<1.0)
+	this->UpperThreshold=maxv;
+      else
+	this->UpperThreshold=range[1];
+  }
+  else if (this->UpperThreshold==this->LowerThreshold)
+  {
+
+      this->UpperThreshold=maxv;
+      this->LowerThreshold=minv;
+  }
+    //std::cout<<"frame:"<<this->Frame<<"max:"<<this->UpperThreshold<<" min:"<<this->LowerThreshold<<endl;
+}
+
+
+void vtkpxImageRobustHistogram::AddDataArray(vtkDataArray* data,float factor,int frame,vtkDataArray* weights)
+{
+  if (this->Initialized==0)
+    return;
+
+  vtkDataArray* out=this->GetOutput()->GetPointData()->GetScalars();
+  int nt=data->GetNumberOfTuples();
+
+  double maxbin=double(this->NumberOfBins-1);
+  double maxrange=this->UpperThreshold-this->LowerThreshold;
+  double numbins=maxbin+1.0;
+
+  for (int i=0;i<nt;i++)
+  {
+      double v=data->GetComponent(i,frame);
+      if (!isnan(v))
+      {
+    	  double bin=-1.0;
+    	  double wgt=1.0;
+    	  if (weights!=NULL)
+    		  wgt=weights->GetComponent(i,0);
+
+    	  if (wgt==0)
+    	  {
+    		  if (this->IgnoreMaskedVoxels==0)
+    			  out->SetComponent(0,0,out->GetComponent(0,0)+1.0);
+    	  }
+    	  else
+    	  {
+    		  if (this->SaturationMode==0)
+    		  {
+    			  if (v<this->LowerThreshold || v>this->UpperThreshold)
+    				  bin=-1;
+    			  else
+    				  bin=maxbin*(v-this->LowerThreshold)/maxrange;
+					  //bin=this->NumberOfBins*(v-this->LowerThreshold)/maxrange;
+					  //		  std::cout<<"v:"<<v<<"bin:"<<bin;
+    		  }
+    		  else
+    		  {
+    			  if (v<=this->LowerThreshold)
+    				  bin=0.0;
+    			  else if (v>=this->UpperThreshold)
+    				  bin=maxbin;
+    			  else
+    				  bin=maxbin*(v-this->LowerThreshold)/maxrange;
+    		  }
+
+    		  if (bin!=-1 && !isnan(bin) && !isinf(bin))
+    		  {
+    			  if (this->Interpolation==0)
+    			  {
+    				  int b=int(bin+0.5);
+    				  out->SetComponent(b,0,out->GetComponent(b,0)+factor*wgt);
+    				  //  std::cout<<"b:"<<b<<"number:"<<out->GetComponent(b,0)<<endl;
+    			  }
+    			  else
+    			  {
+    				  int b0=(int)(bin);
+    				  int b1=(int)(bin+1.0);
+
+    				  if (b1==this->NumberOfBins)
+    					  b1=b0;
+
+    				  double w1=bin-double(b0);
+    				  double w0=1.0-w1;
+
+    				  out->SetComponent(b0,0,out->GetComponent(b0,0)+w0*factor*wgt);
+    				  out->SetComponent(b1,0,out->GetComponent(b1,0)+w1*factor*wgt);
+    			  }
+    		  }
+	    }
+	}
+  }
+}
+// ---------------------------------------------------------------------------
+vtkDataArray* vtkpxImageRobustHistogram::GetWeightArray(vtkImageData* image,vtkImageData* weightimage)
+{
+  if (weightimage==NULL || image==NULL)
+    return NULL;
+
+  vtkDataArray* weights=weightimage->GetPointData()->GetScalars();
+  if (weights->GetNumberOfTuples()!=image->GetPointData()->GetScalars()->GetNumberOfTuples())
+    return NULL;
+
+  return weights;
+}
+// ---------------------------------------------------------------------------
+int vtkpxImageRobustHistogram::RemoveImage(vtkImageData* newimage,vtkImageData* weights)
+{
+  if (newimage==NULL)
+    return 0;
+
+  if (this->Initialized==0)
+    return 0;
+
+  this->AddDataArray(newimage->GetPointData()->GetScalars(),-1.0,this->Frame,this->GetWeightArray(newimage,weights));
+  return 1;
+}
+// ---------------------------------------------------------------------------
+int vtkpxImageRobustHistogram::UndoLastChange()
+{
+  if (this->Initialized==0 || this->LastOutput==NULL)
+    return 0;
+
+  vtkImageData* output=this->GetOutput();
+  output->DeepCopy(this->LastOutput);
+  return 1;
+}
+// ---------------------------------------------------------------------------
+double vtkpxImageRobustHistogram::ComputeEntropy()
+{
+  vtkDataArray* arr=this->GetOutput()->GetPointData()->GetScalars();
+
+  int nt=arr->GetNumberOfTuples();
+  double sum=0.0;
+  for (int i=0;i<nt;i++)
+    sum+=arr->GetComponent(i,0);
+
+  this->Entropy=0.0;
+
+  if (sum>1.0 && nt>1)
+    {
+      for (int i=0;i<nt;i++)
+	{
+	  double p=arr->GetComponent(i,0)/sum;
+	  if (p>0.0)
+	    this->Entropy+= (-p*log(p));
+	}
+      this->Entropy/=log(double(nt));
+    }
+
+  return this->Entropy;
+}
+// ---------------------------------------------------------------------------
+int vtkpxImageRobustHistogram::AddImage(vtkImageData* newimage,vtkImageData* weights)
+{
+  if (newimage==NULL)
+    return 0;
+
+  if (this->GetInput()==NULL)
+    {
+      this->SetInput(newimage);
+      this->Update();
+    }
+  else
+    {
+      this->Update();
+      this->AddDataArray(newimage->GetPointData()->GetScalars(),1.0,this->Frame,this->GetWeightArray(newimage,weights));
+    }
+  return 1;
+}
+// ---------------------------------------------------------------------------
+void vtkpxImageRobustHistogram::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+  if (input==NULL)
+    return;
+
+  int nc=input->GetNumberOfScalarComponents();
+
+
+  if (this->Frame<0)
+    this->Frame=0;
+  if (this->Frame>=nc)
+    this->Frame=nc-1;
+
+
+  vtkDataArray* data=output->GetPointData()->GetScalars();
+  vtkDataArray* weights=this->GetWeightArray(input,this->WeightImage);
+  if (weights==NULL)
+    this->SetWeightImage(NULL);
+
+  data->FillComponent(0,0.0);
+  this->Initialized=1;
+  this->AddDataArray(input->GetPointData()->GetScalars(),1.0,this->Frame,weights);
+
+
+}
+// ---------------------------------------------------------------------------
+int vtkpxImageRobustHistogram::SaveGnuplot(char* fname)
+{
+  if (this->Initialized==0)
+    return 0;
+
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+    return 0;
+
+  vtkImageData* output=this->GetOutput();
+  vtkDataArray* data=output->GetPointData()->GetScalars();
+  int nt=data->GetNumberOfTuples();
+  double  sp[3]; output->GetSpacing(sp);
+  double ori[3]; output->GetOrigin(ori);
+
+  fprintf(fout,"#Bin Minimum\t Bin Maximum\t  Value\t Cumulative \n");
+
+  double sum=0.0;
+  for (int i=0;i<nt;i++)
+    {
+      //      double x=double(i+0.5)*sp[0]+ori[0];
+      double x0=double(i)*sp[0]+ori[0];
+      double x1=double(i+1.0)*sp[0]+ori[0];
+      double y=data->GetComponent(i,0);
+      sum+=y;
+      fprintf(fout,"%f \t %f \t %f \t %f  \n",x0,x1,y,sum);
+
+    }
+
+  fclose(fout);
+  return 1;
+}
+
+// ---------------------------------------------------------------------------
+int vtkpxImageRobustHistogram::GetObjectmapStatistics(vtkImageData* img,vtkDoubleArray* array)
+{
+
+  if (img==NULL || array==NULL)
+    {
+      fprintf(stderr,"Bad Inputs to GetObjectmapStatistics \n");
+      return 0;
+    }
+  img->GetPointData()->GetScalars()->Modified();
+  double* nonused_dummy = img->GetPointData()->GetScalars()->GetRange(0);  
+  double range[2]; img->GetPointData()->GetScalars()->GetRange(range);
+
+  int minv=int(range[0]);
+  int maxv=int(range[1]);
+
+
+  int nt=maxv-minv+1;
+
+  array->SetNumberOfComponents(4);
+  array->SetNumberOfTuples(nt);
+
+  for (int ia=0;ia<=3;ia++)
+    array->FillComponent(ia,0.0);
+
+  int    dim[3]; img->GetDimensions(dim);
+
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  int v=(int)img->GetScalarComponentAsDouble(i,j,k,0)-minv;
+	  if (v>=0 && v<nt)
+	    {
+	      array->SetComponent(v,0,array->GetComponent(v,0)+i);
+	      array->SetComponent(v,1,array->GetComponent(v,1)+j);
+	      array->SetComponent(v,2,array->GetComponent(v,2)+k);
+	      array->SetComponent(v,3,array->GetComponent(v,3)+1);
+	    }
+	  else
+	    {
+	      fprintf(stderr,"Bad Voxel %d,%d,%d = %d\n",i,j,k,v);
+	    }
+	}
+
+
+
+  for (int i=0;i<nt;i++)
+    {
+      double nvoxel=array->GetComponent(i,3);
+      if (nvoxel>0.0)
+	{
+	  for (int j=0;j<=2;j++)
+	    array->SetComponent(i,j,array->GetComponent(i,j)/nvoxel);
+	}
+    }
+
+  return nt;
+}
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxImageRobustHistogram.h b/bioimagesuite30_src/Segmentation/vtkpxImageRobustHistogram.h
new file mode 100644
index 0000000..746910d
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxImageRobustHistogram.h
@@ -0,0 +1,200 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+  
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageRobustHistogram.h,v $
+  Language:  C++
+  Date:      $Date: 2003/05/13 15:37:02 $
+  Version:   $Revision: 1.2 $
+  
+  
+  Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+  All rights reserved.
+  
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+  
+=========================================================================*/
+// .NAME vtkpxImageRobustHistogram - extracts slices from 3D Images
+// .SECTION Description
+// Extracts single 2D slice from 3D Images determined by slice number, CurrentPlane and flip 
+// CurrentPlane = 0=YZ, 1=XZ, 2=XY
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION See Also
+//  vtkExtractVOI
+
+#ifndef __vtkpxImageRobustHistogram_h
+#define __vtkpxImageRobustHistogram_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkDataArray.h"
+#include "vtkDoubleArray.h"
+
+class vtkpxImageRobustHistogram : public vtkpxSimpleImageToImageFilter
+{
+public:
+  vtkTypeMacro(vtkpxImageRobustHistogram,vtkpxSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+  
+  // Description:
+  // Construct object to extract all of the input data.
+  static vtkpxImageRobustHistogram *New();
+  
+  // Description:
+  // Polar Mode used for ultrasound images
+  vtkSetClampMacro(NumberOfBins,int,2,1024);
+  vtkGetMacro(NumberOfBins,int);
+
+
+  // Description:
+  // Get/Set the Mask Image
+  vtkSetObjectMacro(WeightImage,vtkImageData);
+  vtkGetObjectMacro(WeightImage,vtkImageData);
+
+  // Description:
+  // Flag Igored Mask Voxels
+  vtkSetClampMacro(IgnoreMaskedVoxels,int,0,1);
+  vtkGetMacro(IgnoreMaskedVoxels,int);
+  vtkBooleanMacro(IgnoreMaskedVoxels,int);
+
+
+  // Description:
+  // Use this to set sliceno,numslices and currentplane
+  // for extracting frames
+  vtkSetClampMacro(Interpolation,int,0,1);
+  vtkGetMacro(Interpolation,int);
+  vtkBooleanMacro(Interpolation,int);
+
+  // Description:
+  // Use this to set sliceno,numslices and currentplane
+  // for extracting frames
+  vtkSetMacro(Frame,int);
+  vtkGetMacro(Frame,int);
+
+
+  // Description:
+  // Robust Mode Automatically Determines Bounds from Lower and UpperBound
+  vtkSetClampMacro(RobustMode,int,0,1);
+  vtkGetMacro(RobustMode,int);
+  vtkBooleanMacro(RobustMode,int);
+
+  // Description:
+  // Saturation Mode (if v<Saturate Ignore if saturation is off)
+  vtkSetClampMacro(SaturationMode,int,0,1);
+  vtkGetMacro(SaturationMode,int);
+  vtkBooleanMacro(SaturationMode,int);
+
+  // Description:
+  // Plain Histogram i.e. no tricks
+  virtual void SetPlainHistogram();
+
+  // Description:
+  // Upper and Lower Bounds of Cumulative Histogram 
+  vtkSetClampMacro(LowerBound,double,0.0,0.5);
+  vtkGetMacro(LowerBound,double);
+  vtkSetClampMacro(UpperBound,double,0.5,1.0);
+  vtkGetMacro(UpperBound,double);
+  
+  
+  // Description:
+  // Key Outputs
+  vtkGetMacro(LowerThreshold,double);
+  vtkGetMacro(UpperThreshold,double);
+  vtkSetMacro(LowerThreshold,double);
+  vtkSetMacro(UpperThreshold,double);
+
+  vtkGetMacro(Entropy,double);
+
+
+
+
+  // Description:
+  // Modify Current Histogram
+  virtual void  BackupHistogram();
+  virtual int AddImage(vtkImageData* newimage,vtkImageData* weight=NULL);
+  virtual int RemoveImage(vtkImageData* newimage,vtkImageData* weight=NULL);
+  virtual int UndoLastChange();
+  virtual double ComputeEntropy();
+
+  // Description
+  // Save Gnuplot
+  virtual int SaveGnuplot(char* fname);
+
+  // Description:
+  // Get Centroids
+  static int GetObjectmapStatistics(vtkImageData* img,vtkDoubleArray* array);
+
+protected:
+  vtkpxImageRobustHistogram();
+  ~vtkpxImageRobustHistogram();
+  vtkpxImageRobustHistogram(const vtkpxImageRobustHistogram&) {};
+  void operator=(const vtkpxImageRobustHistogram&) {};
+
+  virtual void SimpleExecute(vtkImageData* input, vtkImageData* output);
+  virtual void  ExecuteInformation();
+
+  virtual void  UpdateThresholds();
+  virtual void  AddDataArray(vtkDataArray* data,float factor=1.0,int Frame=0,vtkDataArray* weights=NULL);
+
+  virtual vtkDataArray* GetWeightArray(vtkImageData* image,vtkImageData* weights);
+
+  int NumberOfBins;
+  int Interpolation;
+  int RobustMode;
+  int SaturationMode;
+  double UpperBound;
+  double LowerBound;
+  double LowerThreshold;
+  double UpperThreshold;
+  double Entropy;
+  int  Initialized;
+  int  IgnoreMaskedVoxels;
+  int  Frame;
+
+  vtkImageData* LastOutput;
+  vtkImageData* WeightImage;
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxImageTensorSpline.cpp b/bioimagesuite30_src/Segmentation/vtkpxImageTensorSpline.cpp
new file mode 100644
index 0000000..f69e42c
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxImageTensorSpline.cpp
@@ -0,0 +1,879 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageTensorSpline.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/12/15 14:20:06 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkImageData.h"
+#include "vtkpxImageTensorSpline.h"
+#include "vtkbisImageResample.h"
+#include "vtkImageThreshold.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkObjectFactory.h"
+#include "vtkpxOptimizer.h"
+#include "vtkpxUtil.h"
+#include "vtkpxImageExtractVOI.h"
+#include "vtkImageContinuousDilate3D.h"
+#include "vtkImageMedian3D.h"
+//-----------------------------------------------------------------------------------
+vtkpxImageTensorSpline* vtkpxImageTensorSpline::New()
+{
+  // First try to create the object from the vtkObjectFactory
+
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxImageTensorSpline");
+  if(ret)
+    {
+      return (vtkpxImageTensorSpline*)ret;
+    }
+  
+  // If the factory was unable to create the object, then create it here.
+  
+  return new vtkpxImageTensorSpline;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxImageTensorSpline::vtkpxImageTensorSpline()
+{
+  this->Output=NULL;
+  this->Input=NULL;
+  this->WeightImage=NULL;
+  this->SampledInputImage=NULL;
+  this->SampledWeightImage=NULL;
+  this->MaskImage=NULL;
+
+  this->Sigma=0.0;
+  this->Lambda=0.001;
+  this->StepSize=5.0;
+  this->Resolution=2.0;
+  this->PreSmoothIterations=8;
+  this->AutoInitialize=1;
+  this->Mode=0;
+  this->ControlPointSpacing=20.0;
+  this->Iterations=10;
+  this->Epsilon=0.1;
+}
+
+//----------------------------------------------------------------------------
+
+vtkpxImageTensorSpline::~vtkpxImageTensorSpline()
+{
+  if (this->Output!=NULL)
+    this->Output->Delete();
+
+  if (this->SampledInputImage!=NULL)
+    this->SampledInputImage->Delete();
+
+  if (this->SampledWeightImage!=NULL)
+    this->SampledWeightImage->Delete();
+
+  this->SetInput(NULL);
+  this->SetWeightImage(NULL);
+  this->SetMaskImage(NULL);
+}
+//----------------------------------------------------------------------------
+vtkImageData* vtkpxImageTensorSpline::ResampleAndSmoothImage(vtkImageData* source,double res,double sigma)
+{
+
+  if (sigma<0.0)    
+    sigma=0.0;
+  else if (sigma>20.0)
+    sigma=20.0;
+
+  if (res<1.0)    
+    res=1.0;
+  else if (res>10.0)
+    res=10.0;
+
+  if (source==NULL)
+      return 0;
+  
+  double sp[3];  source->GetSpacing(sp);
+  double ori[3]; source->GetOrigin(ori);
+  int dim[3];   source->GetDimensions(dim);
+
+  double gp[3],sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+    {
+      gp[ia]=(sigma/sp[ia]);
+      if (gp[ia]>25.0) 
+	gp[ia]=25.0;
+    }
+  
+  vtkbisImageResample* resamp=vtkbisImageResample::New();
+
+
+  if (sigma>0.001)
+    {
+      vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+      smooth->SetInput(source);
+      smooth->SetStandardDeviations(gp);
+      resamp->SetInput(smooth->GetOutput());
+      smooth->Delete();
+      resamp->InterpolateOn();
+    }
+  else 
+    {
+      resamp->SetInput(source);
+      resamp->InterpolateOff();
+    }
+
+  resamp->SetDimensionality(3);
+  for (int ib=0;ib<=2;ib++)
+    resamp->SetAxisOutputSpacing(ib,res*sp[0]);
+  if (sp[2]>res*sp[0])
+    resamp->SetAxisOutputSpacing(2,sp[2]);
+
+  resamp->Update();
+
+
+  vtkImageData* destination=vtkImageData::New();
+  destination->ShallowCopy(resamp->GetOutput());
+  resamp->Delete();
+
+  return destination;
+}
+
+// --------------------------------------------------------------------------------------------------
+int vtkpxImageTensorSpline::GenerateLaplacianExtentedFieldWeight(vtkImageData* field,vtkImageData* weight,double res,int maxiter)
+{
+  if (field==NULL || weight==NULL)
+    return 0;
+  
+  vtkImageData* tmp=vtkImageData::New();
+  vtkImageData* tmpw=vtkImageData::New();
+
+  int dim[3];   field->GetDimensions(dim);
+  double sp[3]; field->GetSpacing(sp);
+
+  int incr[6];
+  double wincr[6];
+  int slicesize=dim[0]*dim[1];
+
+  double gp[3];
+  for (int ia=0;ia<=2;ia++)
+    gp[ia]=1.0/sp[ia];
+
+  incr[5]=-slicesize;  wincr[5]=gp[2];
+  incr[4]=slicesize;   wincr[4]=gp[2];
+  incr[3]=-dim[0];     wincr[3]=gp[1];
+  incr[2]=dim[0];      wincr[2]=gp[1];
+  incr[1]=-1;          wincr[1]=gp[0];
+  incr[0]=1;           wincr[0]=gp[0];
+
+  int nt=dim[0]*dim[1]*dim[2];
+
+  int iter=1;
+
+  for (int pass=1;pass<=1;pass++)
+    {
+      double maxchange=100.0;
+      if (pass==2)
+	{
+	  iter=20;
+	  maxiter=400+iter;
+	}
+
+      while (iter<=maxiter)
+	{
+	  maxchange=0.0;
+	  tmp->DeepCopy(field);
+	  tmpw->DeepCopy(weight);
+	  
+	  vtkDataArray* tmp_arr=tmp->GetPointData()->GetScalars();
+	  vtkDataArray* tmpw_arr=tmpw->GetPointData()->GetScalars();
+
+	  vtkDataArray* fld=field->GetPointData()->GetScalars();
+	  vtkDataArray* wgt=weight->GetPointData()->GetScalars();
+	  
+	  int iincr=1;
+	  int i=0;
+	  /*if (2*int(iter/2)==iter)
+	    {
+	      iincr=-1;
+	      i=nt-1;
+	      }*/
+	  
+	  fprintf(stderr,"iter = %d , (iincr=%d i=%d) ",iter,iincr,i);
+	  
+	  while (i>=0 && i<=nt-1)
+	    {
+	      int z=i/slicesize;
+	      int y=(i-z*slicesize)/dim[1];
+	      int x=(i-z*slicesize-y*dim[1]);
+
+	      int proceed=1;
+	      if (x==0 || y==0 || x==(dim[0]-1) || y==(dim[1]-1))
+		proceed=0;
+
+	      double thisweight=tmpw_arr->GetComponent(i,0);
+	      
+	      if (  ( (thisweight==100 && pass==1 ) || (thisweight<100 && pass==2)) && proceed==1)
+		{
+		  double sum=0.0,nsum=0.0,sumw=0.0,nsumw=0.0;
+		  
+		  for (int sh=0;sh<4;sh++)
+		    {
+		      int newindex=i+incr[sh];
+		      if (newindex<0 || newindex>=nt)
+			newindex=i;
+		      double w=tmpw_arr->GetComponent(newindex,0);
+		      if (w>=thisweight)
+			{
+			  sum+=tmp_arr->GetComponent(newindex,0)*wincr[sh];
+			  nsum+=wincr[sh];
+			  sumw+=w;
+			  nsumw+=1.0;
+			}
+		    }
+		  
+		  if (nsum>0.0)
+		    {
+		      double tmpx=sum/nsum;
+		      double oldx=tmp_arr->GetComponent(i,0);
+
+		      double neww=1.0;
+		      if (nsumw>0.0)
+			neww=Frange(sumw/nsumw,1.0,50.0);
+
+		      double w1=0.95;
+		      if (thisweight>=100.0)
+			{
+			  w1=0.1;
+			}
+
+		      double newx=w1*tmpx+(1.0-w1)*oldx;
+		      if ( fabs(newx-oldx)>maxchange)
+			maxchange=fabs(newx-oldx);
+		      fld->SetComponent(i,0,newx);
+		      tmp_arr->SetComponent(i,0,newx);
+		      
+		      if (wgt->GetComponent(i,0)<100)
+			{
+			  wgt->SetComponent(i,0,neww);
+			  tmpw_arr->SetComponent(i,0,neww);
+			}
+		    }
+		}
+	      i=i+iincr;
+	    }
+	  
+	  if (maxchange<0.2)
+	    iter=maxiter;
+
+	  ++iter;
+	}
+    }
+
+  tmp->Delete();
+  tmpw->Delete();
+
+  this->SetWeightImage(weight);
+  this->SampledInputImage=this->ResampleAndSmoothImage(field,res,0.00);
+  this->SampledWeightImage=this->ResampleAndSmoothImage(this->WeightImage,res,0.00);
+  
+
+  return 1;
+}
+
+// --------------------------------------------------------------------------------------------------
+int vtkpxImageTensorSpline::SetInputForBiasFieldApproximation(vtkImageData* ref,double res)
+{
+  if (ref==NULL)
+      return 0;
+
+  if (res<1.0)    
+    res=1.0;
+  else if (res>10.0)
+    res=10.0;
+  
+  double sp[3];  ref->GetSpacing(sp);
+  double ori[3]; ref->GetOrigin(ori);
+  int dim[3];   ref->GetDimensions(dim);
+
+
+  double mean=0.0,sum=0.0,max=0.0;
+  int domask=0;
+  vtkDataArray* orig=ref->GetPointData()->GetScalars();
+  int nt=orig->GetNumberOfTuples();
+ 
+  vtkImageData* cleanref=vtkImageData::New();
+  cleanref->CopyStructure(ref);
+  cleanref->AllocateScalars();
+
+  if (this->MaskImage!=NULL)
+    {
+      vtkDataArray* mask=this->MaskImage->GetPointData()->GetScalars();
+      int nt2=mask->GetNumberOfTuples();
+
+      if (nt2==nt)
+	{
+	  domask=1;
+	  
+	  vtkDataArray* tmp=cleanref->GetPointData()->GetScalars();
+	  vtkDataArray* mask=this->MaskImage->GetPointData()->GetScalars();
+      
+	  int nt=tmp->GetNumberOfTuples();
+	  int nt2=mask->GetNumberOfTuples();
+	  int nc=tmp->GetNumberOfComponents();
+	  double r[2]; mask->GetRange(r);
+	  for (int ia=0;ia<nt;ia++)
+	    {
+	      if (mask->GetComponent(ia,0)>r[0])
+		{
+		  for (int ib=0;ib<nc;ib++)
+		    tmp->SetComponent(ia,ib,orig->GetComponent(ia,ib));
+		  if (orig->GetComponent(ia,0) > 0)
+		    {
+		      mean+=orig->GetComponent(ia,0);
+		      if (orig->GetComponent(ia,0)>max)
+			max=orig->GetComponent(ia,0);
+		      sum+=1.0;
+		    }
+		} 
+	      else
+		{
+		  for (int ib=0;ib<nc;ib++)
+		    tmp->SetComponent(ia,ib,0.0);
+		}
+	    }
+	}
+      else
+	{
+	  cleanref->ShallowCopy(ref);
+	  domask=0;
+	  for (int voxel=0;voxel<nt;voxel++)
+	    {
+	      double v=orig->GetComponent(voxel,0);
+	      if (v>0.0)
+		{
+		  mean+=v;
+		  if (v>max)
+		    max=v;
+		  sum+=1.0;
+		}
+	    }
+	}
+    }
+
+  mean/=sum;
+
+  fprintf(stderr,"In ImageTensorSpline domask=%d mean=%f max=%f\n",domask,mean,max);
+
+  vtkImageThreshold* thr=vtkImageThreshold::New();
+  thr->SetInput(cleanref);
+  thr->ThresholdByLower(0.5);
+  thr->ReplaceInOn();
+  thr->ReplaceOutOn();
+  thr->SetInValue(0.0);
+  thr->SetOutValue(100.0);
+  thr->Update();
+
+  vtkImageData* field=vtkImageData::New();
+  field->CopyStructure(cleanref);
+  field->SetNumberOfScalarComponents(1);
+  field->AllocateScalars();
+
+  vtkDataArray* top=cleanref->GetPointData()->GetScalars();
+  vtkDataArray* bot=thr->GetOutput()->GetPointData()->GetScalars();
+  vtkDataArray* fld=field->GetPointData()->GetScalars();
+
+  double range[2]; bot->GetRange(range);
+  double threshold=0.99*range[0]+0.01*range[1];
+  fprintf(stderr,"Auto Range range=%f:%f thr=%f mean=%f\n",range[0],range[1],threshold,mean);
+
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      float b=bot->GetComponent(voxel,0);
+      float r=100.0;
+      if (b>threshold)
+	{
+	  float t=top->GetComponent(voxel,0);
+	  if (t>0.0)
+	    r=10000.0*t/(b*mean);
+	  if (r<25.0)
+	    r=25.0;
+	  else if (r>400.0)
+	    r=400.0;
+	}
+      fld->SetComponent(voxel,0,r);
+    }
+
+  this->GenerateLaplacianExtentedFieldWeight(field,thr->GetOutput(),res,this->PreSmoothIterations);
+  field->Delete();
+  thr->Delete();
+  cleanref->Delete();
+
+
+  return 1;
+}
+//-------------------------------------------------------------------------
+vtkImageData* vtkpxImageTensorSpline::GenerateOutput(vtkImageData* ref)
+{
+  if (ref==NULL)
+    return NULL;
+
+  vtkImageData* output=vtkImageData::New();
+  output->CopyStructure(ref);
+  output->SetNumberOfScalarComponents(1);
+  output->AllocateScalars();
+
+  double ori[3];   output->GetOrigin(ori); 
+  double sp[3];    output->GetSpacing(sp); 
+  int   dim[3];   output->GetDimensions(dim); 
+
+  vtkDataArray* fits=output->GetPointData()->GetScalars();
+  
+  int index=0;
+  double x[3],tx[3];
+  for (int ka=0;ka<dim[2];ka++)
+    {
+      x[2]=ka*sp[2]+ori[2];
+      for (int ja=0;ja<dim[1];ja++)
+	{
+	  x[1]=ja*sp[1]+ori[1];
+	  for (int ia=0;ia<dim[0];ia++)
+	    {
+	      x[0]=ia*sp[0]+ori[0];
+
+	      this->TransformPoint(x,tx);
+	      double d=tx[0]-x[0];
+	      fits->SetComponent(index,0,d);
+	      ++index;
+	    }
+	}
+    }
+  return output;
+}
+
+// --------------------------------------------------------------------------------------------------------------
+double vtkpxImageTensorSpline::ComputeAverageSquaredDifference(vtkImageData* x,vtkImageData* y,vtkImageData* weight)
+{
+  vtkDataArray* ref=x->GetPointData()->GetScalars();
+  vtkDataArray* fit=y->GetPointData()->GetScalars();
+  vtkDataArray* wgt=NULL;
+  if (weight!=NULL)
+    wgt=weight->GetPointData()->GetScalars();
+
+  int nt=ref->GetNumberOfTuples();
+  double sum=0.0001;
+  double sqerr=0.0;
+  for (int ia=0;ia<nt;ia++)
+    {
+      double v1=ref->GetComponent(ia,0);
+      double v2=fit->GetComponent(ia,0);
+      double w=1.0;
+      if (wgt!=NULL)
+	w=wgt->GetComponent(ia,0);
+      sqerr+=w*pow(v1-v2,2.0);
+      sum+=w;
+    }
+  sqerr/=sum;
+  return sqerr;
+}
+// -----------------------------------------------------------------------------------------
+double vtkpxImageTensorSpline::ComputeAverageSquaredFittingError(vtkImageData* refimg,vtkImageData* weight)
+{
+  vtkDataArray* ref=refimg->GetPointData()->GetScalars();
+  vtkDataArray* wgt=NULL;
+  if (weight!=NULL)    wgt=weight->GetPointData()->GetScalars();
+
+  double ori[3];   refimg->GetOrigin(ori); 
+  double sp[3];    refimg->GetSpacing(sp); 
+  int   dim[3];   refimg->GetDimensions(dim); 
+
+  double sqerr=0.0;
+  double sum=0.0001;
+  int index=0;
+  double x[3],tx[3];
+  for (int ka=0;ka<dim[2];ka++)
+    {
+      x[2]=ka*sp[2]+ori[2];
+      for (int ja=0;ja<dim[1];ja++)
+	{
+	  x[1]=ja*sp[1]+ori[1];
+	  for (int ia=0;ia<dim[0];ia++)
+	    {
+	      x[0]=ia*sp[0]+ori[0];
+	      
+	      this->TransformPoint(x,tx);
+	      /*	      if (ka==dim[2]/2 && ja==dim[1]/2 && ia==dim[0]/2)
+			      fprintf(stderr,"x=%.2f,%.2f,%.2f \t tx=%.2f,%.2f,%.2f\n",x[0],x[1],x[2],tx[0],tx[1],tx[2]);*/
+
+	      double v2=tx[0]-x[0];
+	      double v1=ref->GetComponent(index,0);
+	      double w=1.0;
+	      if (wgt!=NULL)
+		w=wgt->GetComponent(index,0);
+	      sqerr+=w*(pow(v1-v2,2.0));
+	      sum+=w;
+	      ++index;
+	    }
+	}
+    }
+  sqerr/=sum;
+  return sqerr;
+}
+// --------------------------------------------------------------------------------------------------------------
+// Optimization Stuff
+// --------------------------------------------------------------------------------------------------------------
+double vtkpxImageTensorSpline::OptimizerValue(vtkDoubleArray* params)
+{
+  this->SetCurrentParameters(params);
+  double sqerr=this->ComputeAverageSquaredFittingError(this->SampledInputImage,this->SampledWeightImage);
+
+  this->LastError=sqrt(sqerr);
+
+  double sum=0.0;
+  
+  if (this->Lambda>0.0)
+    sum=this->ComputeTotalBendingEnergy();
+    this->LastSmoothness =sum;
+
+  return sqerr+sum*Lambda;
+}
+// -----------------------------------------------------------------------------------------
+double vtkpxImageTensorSpline::EvaluatePiece(vtkImageData* reference,vtkImageData* weights,int cpoint)
+{
+  double e1=this->ComputeAverageSquaredFittingError(reference,weights);
+  double l1 =this->ComputeBendingEnergyAroundControlPoint(cpoint);
+  double s1=-(e1+this->Lambda*l1);
+  return s1;
+}
+
+//-------------------------------------------------------------------------
+double vtkpxImageTensorSpline::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+{
+  if (grad->GetNumberOfComponents()!=1 || grad->GetNumberOfTuples()!=this->NumberOfControlPoints)
+    {
+      grad->SetNumberOfComponents(1);
+      grad->SetNumberOfTuples(this->NumberOfControlPoints);
+    }
+
+  this->OptimizerValue(params);
+  int count=0;
+  int per=this->NumberOfControlPoints/10;
+  int count2=0;
+  
+  grad->FillComponent(0,0.0);
+
+  fprintf(stderr,"Computing Gradient: ");
+
+  double GradientNorm=0.0;
+  for (int i = 0; i < this->NumberOfControlPoints; i++)
+    {
+      ++count;
+
+      if (count==per)
+	{
+	  fprintf(stderr,"%.1f ",double(count2)*10.0);
+	  count=0;
+	  ++count2;
+	  if (count2==10)
+	    fprintf(stderr,"\n");
+	}
+
+      double p[3]; this->GetControlPointLocation(i,p);
+      
+      vtkpxImageExtractVOI* voi=vtkpxImageExtractVOI::New();
+      voi->SetInput(this->SampledInputImage);
+      voi->SetRegion(p,this->Spacing,1.1);
+      voi->Update();
+
+      vtkImageData* weight=NULL;
+
+      if (this->SampledWeightImage!=NULL)
+	{
+	  vtkpxImageExtractVOI* m_voi=vtkpxImageExtractVOI::New();
+	  m_voi->SetInput(this->SampledWeightImage);
+	  m_voi->SetRegion(p,this->Spacing,1.1);
+	  m_voi->Update();
+	  weight=vtkImageData::New();
+	  weight->ShallowCopy(m_voi->GetOutput());
+	  m_voi->Delete();
+	}
+      
+      this->ShiftControlPoint(i,0,-this->StepSize);
+      double s1 = this->EvaluatePiece(voi->GetOutput(),weight,i);
+
+      this->ShiftControlPoint(i,0,+2.0*this->StepSize);
+      double s2 = this->EvaluatePiece(voi->GetOutput(),weight,i);
+
+      this->ShiftControlPoint(i,0,-this->StepSize);
+
+      grad->SetComponent(i,0,-(s2-s1));
+      GradientNorm+=pow(s2-s1,2.0);
+      voi->Delete();
+      if (weight!=NULL)
+	weight->Delete();
+
+    }
+  if (GradientNorm<0.001)
+    GradientNorm=0.001;
+
+  GradientNorm = (sqrt(GradientNorm));
+  double sc=this->StepSize/GradientNorm;
+
+  // Normalize vector
+  if (GradientNorm > 0)
+    {
+      int nt=grad->GetNumberOfTuples();
+      int nc=grad->GetNumberOfComponents();
+      for (int t=0;t<nt;t++)
+	for (int c=0;c<nc;c++)
+	  grad->SetComponent(t,c,grad->GetComponent(t,c) * sc);
+    }
+  else 
+    grad->FillComponent(0,0.0);
+
+  fprintf(stderr,"Gradient Norm=%.5f scale=%f\n",GradientNorm,sc);
+  return GradientNorm;
+}
+
+// -----------------------------------------------------------------------------------------
+void  vtkpxImageTensorSpline::SetCurrentParameters(vtkDoubleArray* param)
+{
+  int numt=this->NumberOfControlPoints;
+  int num=param->GetNumberOfTuples();
+
+  if (num!=numt)
+    {
+      vtkErrorMacro(<<"Bad Data for Optimization");
+      return;
+    }
+
+  for (int i=0;i<numt;i++)
+    {
+      double p[3];
+      p[0]=param->GetComponent(i,0);
+      p[1]=0.0;
+      p[2]=0.0;
+      this->Displacements->SetTuple(i,p);
+    }
+}
+// -----------------------------------------------------------------------------------------
+void  vtkpxImageTensorSpline::GetCurrentParameters(vtkDoubleArray* param)
+{
+  int num=this->NumberOfControlPoints;
+  
+  if (param->GetNumberOfComponents()!=1 || param->GetNumberOfTuples()!=num)
+    {
+      param->SetNumberOfComponents(1);
+      param->SetNumberOfTuples(num);
+    }
+
+  for (int i=0;i<num;i++)
+    {
+      double* p=this->Displacements->GetTuple(i);
+      param->SetComponent(i,0,p[0]);
+    }
+}
+
+// -----------------------------------------------------------------------------------------
+int vtkpxImageTensorSpline::ApproximateImage(vtkImageData* img,float resolution,float spacing,float offset,float smoothness,float initial)
+{
+  this->SetInput(img);
+  this->SetResolution(resolution);
+  if (spacing>0.0)
+    {
+      this->SetControlPointSpacing(spacing);
+      this->SetAutoInitialize(1);
+    }
+  else
+    this->SetAutoInitialize(0);
+  //this->SetSigma(smoothness);
+  this->Run();
+  return 1;
+}
+// -----------------------------------------------------------------------------------------
+int  vtkpxImageTensorSpline::ApproximateFieldMap(double scalefactor,int phasedirection)
+{
+  int ok=this->Run();
+  if (ok==0)
+    return 0;
+
+  phasedirection=Irange(phasedirection,0,2);
+
+  vtkDataArray* out=this->Output->GetPointData()->GetScalars();
+  int nt=out->GetNumberOfTuples();
+
+  for (int i=0;i<nt;i++)
+    {
+      double v=out->GetComponent(i,0)*scalefactor;
+      out->SetComponent(i,phasedirection,v);
+    }
+
+  if (phasedirection!=0)
+    out->FillComponent(0,0.0);
+  
+  return 1;
+}
+
+int vtkpxImageTensorSpline::Run()
+{
+  if (this->Input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Input Image\n");
+      return 0;
+    }
+
+  if (this->AutoInitialize==1 || this->Displacements==NULL)
+    {
+      fprintf(stderr,"Auto Initialize ...\n");
+      this->Initialize(this->Input,this->ControlPointSpacing,0.05);
+    }
+  
+  if (this->SampledInputImage!=NULL)
+    this->SampledInputImage->Delete();
+  
+  if (this->SampledWeightImage!=NULL)
+    this->SampledWeightImage->Delete();
+  this->SampledWeightImage=NULL;
+
+  if (this->Mode==0)
+    {
+      this->SampledInputImage=this->ResampleAndSmoothImage(this->Input,this->Resolution,this->Sigma);
+      if (this->WeightImage!=NULL)
+	{
+	  this->SampledWeightImage=this->ResampleAndSmoothImage(this->WeightImage,this->Resolution,this->Sigma);
+	}
+    }
+  else
+    {
+      this->SetInputForBiasFieldApproximation(this->Input,this->Resolution);
+    }
+
+  // Initialize B-Spline with value at closest point
+  // Crude but OK
+  int    dim[3]; this->SampledInputImage->GetDimensions(dim);
+  double  sp[3]; this->SampledInputImage->GetSpacing(sp);
+  double ori[3]; this->SampledInputImage->GetOrigin(ori);
+
+  fprintf(stderr,"Approximating dim=%d x %d x %d (%.1f,%.1f,%.1f) Mode=%d\n",
+	  dim[0],dim[1],dim[2],sp[0],sp[1],sp[2],this->Mode);
+  
+  for (int ia=0;ia<this->NumberOfControlPoints;ia++)
+    {
+      double x[3];
+      double p[3]={0.0,0.0,0.0};
+      this->GetControlPointLocation(ia,x);
+      int voxel[3];
+      for (int ib=0;ib<=2;ib++)
+	voxel[ib]=Irange(int((x[ib]-ori[ib])/sp[ib]),0,dim[ib]-1);
+
+      //      if (this->Mode>0)
+      p[0]=this->SampledInputImage->GetScalarComponentAsDouble(voxel[0],voxel[1],voxel[2],0);
+
+      this->ShiftControlPoint(ia,p);
+    }
+
+
+  {
+    vtkImageData* out=this->GenerateOutput(this->Input);
+    int ok=vtkpxUtil::SaveAnalyze("initial_fit",out,0);
+    fprintf(stderr,"Initial_fit saved... %d",ok);
+    out->Delete();
+  }
+  
+
+
+  vtkpxOptimizer* optimizer=vtkpxOptimizer::New();
+  vtkDoubleArray* position=vtkDoubleArray::New();
+  vtkDoubleArray* temp=vtkDoubleArray::New();
+  
+  this->LastError=0.0;
+  this->LastSmoothness=0.0;
+
+  this->GetCurrentParameters(position);
+  optimizer->SetMasterObject(this);
+  optimizer->SetEvaluateFunctionMethod(&vtkpxImageTensorSpline::CalculateFunction);
+  optimizer->SetEvaluateGradientMethod(&vtkpxImageTensorSpline::CalculateGradient);
+  optimizer->SetFeedbackMethod(&vtkpxImageTensorSpline::OptimizerFeedback);
+  
+  double v1=this->OptimizerValue(position);
+  fprintf(stderr,"Value=%f\n",v1);
+  double tol=this->Epsilon*0.01*fabs(v1);
+  fprintf(stderr,"Tolerance=%.5f\n",tol);
+
+  double v=optimizer->ComputeConjugateGradient(position,this->Iterations,tol);
+  optimizer->Delete();
+  position->Delete();
+  temp->Delete();
+
+  if (this->Output!=NULL)
+    this->Output->Delete();
+  this->Output=this->GenerateOutput(this->Input);
+  
+  return 1;
+}
+
+// -----------------------------------------------------------------------------------------
+// New Stuff for Optimization
+// -----------------------------------------------------------------------------------------
+double vtkpxImageTensorSpline::CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output)
+{
+  return ((vtkpxImageTensorSpline*)self)->OptimizerGradient(position,output);
+}
+
+double vtkpxImageTensorSpline::CalculateFunction(vtkObject* self,vtkDoubleArray* position)
+{
+  return ((vtkpxImageTensorSpline*)self)->OptimizerValue(position);
+}
+
+void vtkpxImageTensorSpline::OptimizerFeedback(vtkObject* slf,const char* line,double val)
+{
+  vtkpxImageTensorSpline* self=(vtkpxImageTensorSpline*)slf;
+  fprintf(stderr,"%s (%.5f) [ dist=%.5f tbend=%.5f]\n",line,val,
+	  self->LastError,
+	  self->LastSmoothness);
+}
+// -----------------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxImageTensorSpline.h b/bioimagesuite30_src/Segmentation/vtkpxImageTensorSpline.h
new file mode 100644
index 0000000..a200115
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxImageTensorSpline.h
@@ -0,0 +1,218 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxImageTensorSpline.h,v $
+  Language:  C++
+  Date:      $Date: 2002/03/12 16:50:25 $
+  Version:   $Revision: 1.2 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#ifndef __vtkpxImageTensorSpline_h
+#define __vtkpxImageTensorSpline_h
+
+#include "vtkpxTensorBSplineTransform.h"
+#include "vtkImageData.h"
+
+class vtkpxImageTensorSpline : public vtkpxTensorBSplineTransform
+{
+public:
+  static vtkpxImageTensorSpline *New();
+  vtkTypeMacro(vtkpxImageTensorSpline,vtkpxTensorBSplineTransform);
+
+  // Description:
+  // Approximate Image Value
+  virtual int  Run();
+  virtual int  ApproximateImage(vtkImageData* img,float resolution,float spacing,float offest,float smoothness,float initial);
+  virtual int  ApproximateFieldMap(double scalefactor,int phasedirection=1);
+
+  // Description:
+  // Output Image
+  vtkGetObjectMacro(Output,vtkImageData);
+
+  // Description:
+  // Image To be Approximated
+  vtkGetObjectMacro(Input,vtkImageData);
+  vtkSetObjectMacro(Input,vtkImageData);
+
+  // Description:
+  // Weight Image -- auto generate if Mode = 1
+  vtkGetObjectMacro(WeightImage,vtkImageData);
+  vtkSetObjectMacro(WeightImage,vtkImageData);
+
+
+  // Description:
+  // Mask Image
+  vtkGetObjectMacro(MaskImage,vtkImageData);
+  vtkSetObjectMacro(MaskImage,vtkImageData);
+
+  // Description:
+  // Lambda is smoothness constant (default=0.0)
+  vtkGetMacro(Lambda,double);
+  vtkSetMacro(Lambda,double);
+
+  // Description:
+  // Sigma is image space smoothness (default =0.0)
+  vtkGetMacro(Sigma,double);
+  vtkSetMacro(Sigma,double);
+
+  // Description:
+  // Step Size for Gradient Computation
+  vtkSetMacro(StepSize,double);
+  vtkGetMacro(StepSize,double);
+
+
+  // Description:
+  // Control Point Spacing
+  vtkSetMacro(ControlPointSpacing,double);
+  vtkGetMacro(ControlPointSpacing,double);
+
+
+  // Description:
+  // Control Point Spacing
+  vtkSetMacro(Resolution,double);
+  vtkGetMacro(Resolution,double);
+
+
+  // Description:
+  // Control Point Spacing
+  vtkSetMacro(PreSmoothIterations,int);
+  vtkGetMacro(PreSmoothIterations,int);
+  
+
+  // Description:
+  // Control Point Spacing
+  vtkSetClampMacro(Mode,int,0,1);
+  vtkGetMacro(Mode,int);
+
+
+  // Description:
+  // Control Point Spacing
+  vtkSetClampMacro(AutoInitialize,int,0,1);
+  vtkGetMacro(AutoInitialize,int);
+
+
+  // Description:
+  // Control Point Spacing
+  vtkSetClampMacro(Iterations,int,1,100);
+  vtkGetMacro(Iterations,int);
+
+
+  // Description:
+  // Control Point Spacing
+  vtkSetClampMacro(Epsilon,double,0.0,100.0);
+  vtkGetMacro(Epsilon,double);
+
+
+  // Description:
+  // Needed for Optimization
+  virtual void  SetCurrentParameters(vtkDoubleArray* par);
+  virtual void  GetCurrentParameters(vtkDoubleArray* par);
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+
+  // Description:
+  // Needed for Optimization
+  static void   OptimizerFeedback(vtkObject* self,const char* line,double val);
+  static double  CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output);
+  static double  CalculateFunction(vtkObject* self,vtkDoubleArray* position);
+
+  // Description:
+  // Optimization Output
+  double   LastError;
+  double   LastSmoothness;
+
+
+protected:
+  vtkpxImageTensorSpline();
+  virtual ~vtkpxImageTensorSpline();
+  vtkpxImageTensorSpline(const vtkpxImageTensorSpline&) {};
+  void operator=(const vtkpxImageTensorSpline&) {};
+
+
+  // Description:
+  // Members 
+  vtkImageData* Output;
+  vtkImageData* Input;
+  vtkImageData* WeightImage;
+
+  vtkImageData* SampledInputImage;
+  vtkImageData* SampledWeightImage;
+  vtkImageData* MaskImage;
+
+  double   Lambda;
+  double   StepSize;
+  double   ControlPointSpacing;
+  double   Resolution;
+  int      PreSmoothIterations;
+  int      Mode;
+  int      AutoInitialize;
+  int      Iterations;
+  double   Epsilon;
+  double   Sigma;
+
+  // Description:
+  // Helper Routines 
+  virtual vtkImageData* ResampleAndSmoothImage(vtkImageData* source,double res,double sigma);
+  virtual vtkImageData* GenerateOutput(vtkImageData* img);
+
+  virtual double ComputeAverageSquaredDifference(vtkImageData* x,vtkImageData* y,vtkImageData* w=NULL);
+  virtual double ComputeAverageSquaredFittingError(vtkImageData* x,vtkImageData* w=NULL);
+  virtual double EvaluatePiece(vtkImageData* reference,vtkImageData* weights,int cpoint);
+
+
+  virtual int SetInputForBiasFieldApproximation(vtkImageData* ref,double res);
+  virtual int GenerateLaplacianExtentedFieldWeight(vtkImageData* field,vtkImageData* weight,double res,int iter);
+  
+};
+
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxLevelSetUtil.cpp b/bioimagesuite30_src/Segmentation/vtkpxLevelSetUtil.cpp
new file mode 100644
index 0000000..e4e1d2d
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxLevelSetUtil.cpp
@@ -0,0 +1,382 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxLevelSetUtil.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/07/15 12:58:44 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+
+#include "vtkpxLevelSetUtil.h"
+#include "vtkImageCast.h"
+#include "vtkImageImport.h"
+#include "vtkImageExport.h"
+
+#include "itkGradientAnisotropicDiffusionImageFilter.h"
+#include "itkGradientMagnitudeRecursiveGaussianImageFilter.h"
+#include "itkFastMarchingImageFilter.h"
+#include "itkSigmoidImageFilter.h"
+
+#include  "itkMRIBiasFieldCorrectionFilter.h"
+#include "itkMultivariateLegendrePolynomial.h"
+
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageResample.h"
+#include "vtkbisImageReslice.h"
+#include "vtkImageShiftScale.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+
+vtkpxLevelSetUtil* vtkpxLevelSetUtil::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxLevelSetUtil");
+  if(ret)
+    {
+      return (vtkpxLevelSetUtil*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxLevelSetUtil;
+}
+
+
+// --------------------------------------------------------------------------------------
+//                      LevelSet Stuff
+// --------------------------------------------------------------------------------------
+
+vtkImageData* vtkpxLevelSetUtil::SigmoidFilter(vtkImageData* input,
+					       float SigmoidAlpha,float SigmoidBeta,
+					       float SigmoidMin,float SigmoidMax)
+{
+  if (input==NULL)
+    return NULL;
+
+  double range[2]; input->GetPointData()->GetScalars()->GetRange(range);
+
+  SigmoidAlpha*=(range[1]-range[0]);
+  SigmoidBeta*=0.5*(range[1]+range[0]);
+  
+  vtkImageCast* cast=vtkImageCast::New();
+  cast->SetInput(input);
+  cast->SetOutputScalarTypeToFloat();
+
+  vtkImageExport *vtkExporter = vtkImageExport::New();
+  vtkExporter->SetInput(cast->GetOutput());
+
+  pxImportType::Pointer itkImporter =  pxImportType::New();
+  ConnectPipelines(vtkExporter, itkImporter);
+  itkImporter->Update();
+
+  typedef   itk::SigmoidImageFilter<pxImageType,pxImageType >  SigmoidFilterType;
+  SigmoidFilterType::Pointer sigmoid = SigmoidFilterType::New();
+  sigmoid->SetOutputMinimum( SigmoidMin  );
+  sigmoid->SetOutputMaximum( SigmoidMax  );
+  sigmoid->SetInput( itkImporter->GetOutput() );
+  sigmoid->SetAlpha(SigmoidAlpha);
+  sigmoid->SetBeta(SigmoidBeta);
+  sigmoid->Update();
+  
+  pxExportType::Pointer itkExporter = pxExportType::New();
+  itkExporter->SetInput(sigmoid->GetOutput());
+  itkExporter->Update();
+
+  vtkImageImport* vtkImporter=vtkImageImport::New();
+  ConnectPipelines(itkExporter, vtkImporter);
+  vtkImporter->Update();
+
+  vtkImageData* EdgeMap=vtkImageData::New();
+  EdgeMap->DeepCopy(vtkImporter->GetOutput());
+  vtkExporter->Delete();
+  vtkImporter->Delete();
+  cast->Delete();
+
+  return EdgeMap;
+}
+
+
+vtkImageData* vtkpxLevelSetUtil::GenerateGradientMagnitudeSpeedImage(vtkImageData* input,int SmoothingIterations,float Conductance,
+								     float GradientSigma,
+								     float SigmoidAlpha,float SigmoidBeta,
+								     float SigmoidMin,float SigmoidMax)
+{
+  if (input==NULL)
+    return NULL;
+
+  double range[2]; input->GetPointData()->GetScalars()->GetRange(range);
+  SigmoidAlpha*=(range[1]-range[0]);
+  SigmoidBeta*=0.5*(range[1]+range[0]);
+
+  vtkImageCast* cast=vtkImageCast::New();
+  cast->SetInput(input);
+  cast->SetOutputScalarTypeToFloat();
+
+  vtkImageExport *vtkExporter = vtkImageExport::New();
+  vtkExporter->SetInput(cast->GetOutput());
+
+  pxImportType::Pointer itkImporter =  pxImportType::New();
+  ConnectPipelines(vtkExporter, itkImporter);
+  itkImporter->Update();
+
+  typedef   itk::GradientMagnitudeRecursiveGaussianImageFilter<pxImageType,pxImageType >  GradientFilterType;
+  GradientFilterType::Pointer  gradientMagnitude = GradientFilterType::New();
+
+  typedef   itk::GradientAnisotropicDiffusionImageFilter<pxImageType,pxImageType >  SmoothingFilterType;
+  SmoothingFilterType::Pointer smoothing = SmoothingFilterType::New();
+  
+  if (SmoothingIterations>0)
+    {
+      smoothing->SetInput( itkImporter->GetOutput() );
+      smoothing->SetTimeStep( 0.05 );
+      smoothing->SetNumberOfIterations(SmoothingIterations);
+      smoothing->SetConductanceParameter( Conductance );
+      gradientMagnitude->SetInput( smoothing->GetOutput() );
+    }
+  else
+    {
+      gradientMagnitude->SetInput(itkImporter->GetOutput());
+      gradientMagnitude->SetSigma( GradientSigma  );
+    }
+
+  typedef   itk::SigmoidImageFilter<pxImageType,pxImageType >  SigmoidFilterType;
+  SigmoidFilterType::Pointer sigmoid = SigmoidFilterType::New();
+  sigmoid->SetOutputMinimum( SigmoidMin  );
+  sigmoid->SetOutputMaximum( SigmoidMax  );
+  sigmoid->SetInput( gradientMagnitude->GetOutput() );
+  sigmoid->SetAlpha(SigmoidAlpha);
+  sigmoid->SetBeta(SigmoidBeta);
+  sigmoid->Update();
+
+  pxExportType::Pointer itkExporter = pxExportType::New();
+  itkExporter->SetInput(sigmoid->GetOutput());
+  itkExporter->Update();
+
+  vtkImageImport* vtkImporter=vtkImageImport::New();
+  ConnectPipelines(itkExporter, vtkImporter);
+  vtkImporter->Update();
+
+  vtkImageData* EdgeMap=vtkImageData::New();
+  EdgeMap->DeepCopy(vtkImporter->GetOutput());
+
+  vtkExporter->Delete();
+  vtkImporter->Delete();
+  cast->Delete();
+
+  return EdgeMap;
+}
+
+// -------------------------------------------------------------------------------------------------------------------
+template <int ImageDimension>
+vtkImageData* vtkpxLevelSetUtil_GenerateInputLevelSet(vtkImageData* input,vtkPoints* points,float offset,float factor)
+{
+  typedef float PixelType;
+  typedef itk::Image<PixelType,ImageDimension>    ImageType;
+
+  typedef  itk::FastMarchingImageFilter<ImageType,ImageType>   FastMarchingFilterType;
+  typename FastMarchingFilterType::NodeContainer::Pointer seeds;
+  seeds= FastMarchingFilterType::NodeContainer::New();
+  
+  seeds->Initialize();
+
+  typename ImageType::IndexType   seedPosition;
+  for (int i=0 ; i< points->GetNumberOfPoints();i++)
+    {
+      double p[3]; points->GetPoint(i,p);
+
+      std::cerr << "Seed Position " << i << "(";
+      for (int ia=0;ia<ImageDimension;ia++)
+	{
+	  seedPosition[ia] = long(p[ia]/factor+0.5);
+	  std::cerr << seedPosition[ia] << " ";
+	}
+      std::cerr << ")" << std::endl;
+
+      typename FastMarchingFilterType::NodeType  node;
+      node.SetValue( -fabs(offset*factor));
+      node.SetIndex( seedPosition );
+      seeds->InsertElement( i, node );
+    }
+
+
+  typename ImageType::SizeType size;
+  int dim[3]; input->GetDimensions(dim);
+  for (int i=0;i<ImageDimension;i++)
+    size[i]=dim[i];
+
+  typename FastMarchingFilterType::Pointer fastMarching = FastMarchingFilterType::New();
+  fastMarching->SetTrialPoints(  seeds  );
+  fastMarching->SetSpeedConstant( 1.0 );
+  fastMarching->SetOutputSize(size);
+  fastMarching->Update();
+
+  typedef itk::VTKImageExport<ImageType> ExportType;
+  typename ExportType::Pointer itkExporter = ExportType::New();
+  itkExporter->SetInput(fastMarching->GetOutput());
+  itkExporter->Update();
+
+  vtkImageImport* vtkImporter=vtkImageImport::New();
+  ConnectPipelines(itkExporter, vtkImporter);
+  vtkImporter->Update();
+
+  vtkImageData* InputLevelSet=vtkImageData::New();
+  InputLevelSet->DeepCopy(vtkImporter->GetOutput());
+  InputLevelSet->SetOrigin(input->GetOrigin());
+  InputLevelSet->SetSpacing(input->GetSpacing());
+  vtkImporter->Delete();
+
+  return InputLevelSet;
+
+
+}
+// -------------------------------------------------------------------------------------------------------------------
+
+vtkImageData* vtkpxLevelSetUtil::GenerateInputLevelSet(vtkImageData* input,vtkPoints* points,float offset,float factor)
+{
+  if (input==NULL || points==NULL)
+    return NULL;
+
+  if (points->GetNumberOfPoints()<1)
+    return NULL;
+
+  int dim[3]; input->GetDimensions(dim);
+
+  if (dim[2]==1)
+    return vtkpxLevelSetUtil_GenerateInputLevelSet<2>(input,points,offset,factor);
+
+  return vtkpxLevelSetUtil_GenerateInputLevelSet<3>(input,points,offset,factor);
+}
+
+// -------------------------------------------------------------------------------------------------------------------
+int vtkpxLevelSetUtil::ResliceDistanceMap(vtkImageData* destination,vtkImageData* source,vtkImageData* ref)
+{
+  int nt1=source->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nt2=ref->GetPointData()->GetScalars()->GetNumberOfTuples();
+  if (nt1==nt2)
+    {
+      destination->ShallowCopy(source);
+    }
+  else
+    {
+      vtkImageShiftScale* sc=vtkImageShiftScale::New();
+      sc->SetInput(source);
+      sc->SetShift(0.0);
+      sc->SetScale(ref->GetSpacing()[0]/source->GetSpacing()[0]);
+
+      vtkbisImageReslice* resl=vtkbisImageReslice::New();
+      resl->OptimizationOff();
+      resl->SetInput(sc->GetOutput());
+      resl->SetInformationInput(ref);
+      resl->SetInterpolationMode(3);
+      resl->Update();
+      destination->ShallowCopy(resl->GetOutput());
+      resl->Delete();
+      sc->Delete();
+    }
+  return 1;
+}
+// -------------------------------------------------------------------------------------------------------------------
+int vtkpxLevelSetUtil::ResampleAndSmoothImage(vtkImageData* destination,vtkImageData* source,float factor)
+{
+
+  if (source==NULL || destination==NULL)
+      return 0;
+
+
+  float blurfactor=0.4247;
+
+
+  double sp[3];  source->GetSpacing(sp);
+  int    dim[3];   source->GetDimensions(dim);
+  double gp[3],resolution[3];
+  for (int j=0;j<=2;j++)
+    {
+      gp[j]=factor*blurfactor;
+      resolution[j]=sp[j]*factor;
+    }
+
+  if (dim[2]==1 || sp[2] > 2.0*sp[0])
+    {
+      gp[2]=0.0;
+      resolution[2]=sp[2];
+    }
+
+  fprintf(stderr,"In Reample and smooth Image\n");
+
+  vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+  smooth->SetInput(source);
+  smooth->SetStandardDeviations(gp);
+  smooth->Update();
+  
+  vtkImageResample* resamp=vtkImageResample::New();
+  resamp->SetInput(smooth->GetOutput());
+  resamp->InterpolateOn();
+  resamp->SetDimensionality(3);
+
+  for (int ib=0;ib<=2;ib++)
+    resamp->SetAxisOutputSpacing(ib,resolution[ib]);
+  resamp->Update();
+
+  
+  destination->ShallowCopy(resamp->GetOutput());
+  destination->GetSpacing(resolution);
+
+  fprintf(stderr,"Smoothed (%.2f,%.2f,%.2f)  (sp=%.2f,%.2f,%.2f) --> (%.2f,%.2f,%.2f)\n",
+	  gp[0],gp[1],gp[2],sp[0],sp[1],sp[2],resolution[0],resolution[1],resolution[2]);
+
+  resamp->Delete();
+  smooth->Delete();
+
+  return 1;
+}
+
+// -------------------------------------------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxLevelSetUtil.h b/bioimagesuite30_src/Segmentation/vtkpxLevelSetUtil.h
new file mode 100644
index 0000000..51e6746
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxLevelSetUtil.h
@@ -0,0 +1,104 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxLevelSetUtil.h,v $
+  Language:  C++
+  Date:      $Date: 2002/07/15 12:58:30 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxLevelSetUtil - a collection of static utility functions
+// .SECTION Description
+// This class contains a collection of <EM>static</EM> utility functions for use elsewhere ala vtkMath
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// .SECTION Caveats
+// This requires pxutil 
+
+#ifndef __vtkpxLevelSetUtil_h
+#define __vtkpxLevelSetUtil_h
+
+
+#include "vtkImageData.h"
+#include "vtkPoints.h"
+#include "itkImage.h"
+#include "vtkFloatArray.h"
+#include "itkVTKImageExport.h"
+#include "itkVTKImageImport.h"
+#include "vtkITKUtility.h"
+
+enum { pxImageDimension = 3 };
+typedef  float  pxPixelType;
+typedef itk::Image<pxPixelType,pxImageDimension>    pxImageType;
+typedef itk::VTKImageImport<pxImageType> pxImportType;
+typedef itk::VTKImageExport<pxImageType> pxExportType;
+
+
+class vtkpxLevelSetUtil : public vtkObject
+{
+public:
+  static vtkpxLevelSetUtil *New();
+  vtkTypeMacro(vtkpxLevelSetUtil,vtkObject);
+
+  static vtkImageData* SigmoidFilter(vtkImageData* input,
+				     float SigmoidAlpha=0.5,float SigmoidBeta=0.0,
+				     float SigmoidMin=-1.0,float SigmoidMax=1.0);
+
+  static vtkImageData* GenerateGradientMagnitudeSpeedImage(vtkImageData* input,int SmoothingIterations=5,float Conductance=9.0,
+							   float GradientSigma=0.5,
+							   float SigmoidAlpha=0.5,float SigmoidBeta=0.0,
+							   float SigmoidMin=-1.0,float SigmoidMax=1.0);
+  static vtkImageData* GenerateInputLevelSet(vtkImageData* input,vtkPoints* points,float offset=5.0,float factor=1.0);
+
+  static int ResampleAndSmoothImage(vtkImageData* destination,vtkImageData* source,float factor);
+  static int ResliceDistanceMap(vtkImageData* destination,vtkImageData* source,vtkImageData* ref);
+
+  
+};
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxLogExponentialFit.cpp b/bioimagesuite30_src/Segmentation/vtkpxLogExponentialFit.cpp
new file mode 100644
index 0000000..a79cbee
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxLogExponentialFit.cpp
@@ -0,0 +1,313 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxLogExponentialFit.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+
+#include "vtkpxLogExponentialFit.h"
+#include "vtkpxUtil.h"
+#include "vtkpxMath.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+#include "pxutil.h"
+#include "pxisinf.h"
+#include "math.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+//#include "vnl/vnl_gamma.h"
+
+//extern double vnl_gamma_q(double a, double x);
+
+//------------------------------------------------------------------------------
+vtkpxLogExponentialFit* vtkpxLogExponentialFit::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxLogExponentialFit");
+  if(ret)
+    {
+      return (vtkpxLogExponentialFit*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxLogExponentialFit;
+}
+
+// Construct object with no children.
+vtkpxLogExponentialFit::vtkpxLogExponentialFit()
+{
+  this->EchoTrain=NULL;
+  this->R2Map=vtkImageData::New();
+  this->DensityMap=vtkImageData::New();
+  this->MaxT2Value=200.0;
+  this->IntensityThreshold=0.0;
+
+}
+// ----------------------------------------------------------------------------
+vtkpxLogExponentialFit::~vtkpxLogExponentialFit()
+{
+  if (this->R2Map!=NULL)
+    this->R2Map->Delete();
+
+  if (this->DensityMap!=NULL)
+    this->DensityMap->Delete();
+
+  if (this->EchoTrain!=NULL)
+    this->SetEchoTrain(NULL);
+}
+// ----------------------------------------------------------------------------
+int vtkpxLogExponentialFit::RequestInformation(vtkInformation *request,  vtkInformationVector **inputVector, 
+					       vtkInformationVector *outputVector)
+{
+  vtkDataObject::SetPointDataActiveScalarInfo(outputVector->GetInformationObject(0), VTK_FLOAT, 1);
+  return 1;
+}
+// ----------------------------------------------------------------------------
+int vtkpxLogExponentialFit::CreateEchoTrain(float FirstEchoTime,float  EchoSpacing,int numechos)
+{
+  if (numechos==-1 && this->GetImageDataInput(0)==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image Specified, specify number of echos explicitly\n");
+      return 0;
+    }
+
+  if (numechos<1)
+    numechos=this->GetImageDataInput(0)->GetNumberOfScalarComponents();
+
+  vtkFloatArray* ar=vtkFloatArray::New();
+  ar->SetNumberOfTuples(numechos);
+  
+  for (int i=0;i<numechos;i++)
+    ar->SetComponent(i,0,FirstEchoTime+float(i)*EchoSpacing);
+
+  this->SetEchoTrain(ar);
+  ar->Delete();
+  return 1;
+}
+
+
+
+void vtkpxLogExponentialFit::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"No Input for vtkpxLogExponentialFit Specified\n");
+      return;
+    }
+
+  if (input->GetNumberOfScalarComponents() < 3)
+    {
+      vtkErrorMacro(<<"Not enough components in input for vtkpxLogExponentialFit to perform fit\n");
+      return;
+    }
+
+  if (this->EchoTrain==NULL)
+    {
+      this->CreateEchoTrain(15.0,15.0,-1);
+    }
+
+  if (this->EchoTrain->GetNumberOfTuples()<input->GetNumberOfScalarComponents())
+    {
+      vtkErrorMacro(<<"Bad Echo Train Specified\n");
+      return;
+    }
+  
+  if (this->DensityMap!=NULL)
+    this->DensityMap->Delete();
+
+  this->DensityMap=vtkImageData::New();
+  this->DensityMap->CopyStructure(output);
+  this->DensityMap->SetNumberOfScalarComponents(1);
+  this->DensityMap->AllocateScalars();
+
+  if (this->R2Map!=NULL)
+    this->R2Map->Delete();
+
+  this->R2Map=vtkImageData::New();
+  this->R2Map->CopyStructure(this->DensityMap);
+  this->R2Map->SetScalarTypeToFloat();
+  this->R2Map->SetNumberOfScalarComponents(1);
+  this->R2Map->AllocateScalars();
+
+
+  vtkDataArray* inp_v=input->GetPointData()->GetScalars();
+  vtkDataArray* den_v=this->DensityMap->GetPointData()->GetScalars();
+  den_v->FillComponent(0,0);
+  vtkDataArray* r2_v=this->R2Map->GetPointData()->GetScalars();
+  r2_v->FillComponent(0,0);
+  vtkDataArray* t2_v=output->GetPointData()->GetScalars();
+  t2_v->FillComponent(0,0);
+
+  /*  fprintf(stderr,"output %d,%d\n",
+	  t2_v->GetNumberOfTuples(),
+	  t2_v->GetNumberOfComponents());*/
+
+  double range[2]; inp_v->GetRange(range);
+
+  double threshold=  this->IntensityThreshold*(range[1]-range[0])+range[0];
+  //  fprintf(stderr,"Intensity Threshold=%f threshold=%f\n",this->IntensityThreshold,threshold);
+
+  int nt=inp_v->GetNumberOfTuples();
+  int nc=inp_v->GetNumberOfComponents();
+
+  float* temp=new float[nc];
+  float*    x=new float[nc];
+
+
+  int*     ind=new int[nc];
+
+  int numgood=-1;
+  for (int j=0;j<nc;j++)
+    {
+      float t=-this->EchoTrain->GetComponent(j,0);
+      if (t<0.0)
+	{
+	  ++numgood;
+	  x[numgood]=t;
+	  ind[numgood]=j;
+	}
+    }
+  ++numgood;
+
+  fprintf(stdout,"Numgood=%d:",numgood);
+  for (int j=0;j<numgood;j++)
+    fprintf(stdout,"j=%d  x[j]=%.2f ind[j]=%d\t",j+1,-x[j],ind[j]);
+  fprintf(stdout,"\n");
+
+  int tenth=int(nt/10);
+  int count=0;
+
+  double ndata=double(numgood);
+
+  this->UpdateProgress(0.0);
+  for (int voxel=0;voxel<nt;voxel++)
+    {
+      double density=0.0,r2=0.0;
+      if (inp_v->GetComponent(voxel,0)>=threshold)
+	{
+	  double sx=0.0,sy=0.0,sxy=0.0,sxx=0.0;
+	  for (int j=0;j<numgood;j++)
+	    {
+	      double iv=inp_v->GetComponent(voxel,ind[j]);
+	      double y=0.0;
+	      double t=x[j];
+
+
+	      if (iv>1.0)
+		y=log(iv);
+	      else
+		y=0.0;
+
+	      if (voxel==75952)
+		fprintf(stderr,"voxel=%d \t j=%d ind[j]=%d x[j]=%.2f iv=%.2f t=%.2f y=%.2f \n",
+		voxel,j,ind[j],x[j],iv,t,y);
+
+	      
+	      sx += t;
+	      sy += y;
+	      sxy += t*y;
+	      sxx += t*t;
+	    }
+	      
+	  double del=ndata*sxx-sx*sx;
+	      
+	  if (fabs(del)>1e-12)
+	    {
+	      density=(sxx*sy-sx*sxy)/del;
+	      r2=(ndata*sxy-sx*sy)/del;
+	      //	      fprintf(stderr,"Density=%.2f r2=%.2f del=%.2f\n");
+	    }
+	  else
+	    {
+	      density=0.0;
+	      r2=1.0/this->MaxT2Value;
+	    }
+
+	  
+	  if (r2<1.0/this->MaxT2Value)
+	    r2=1.0/this->MaxT2Value;
+	  
+	  if (r2>10000.0)
+	    r2=10000.0;
+	  
+	  if (r2>0.0)
+	    t2_v->SetComponent(voxel,0,1.0/r2);
+	  else
+	    t2_v->SetComponent(voxel,0,0.0);
+	  
+	  if (isnan(density) || isinf(density))
+	    density=0.0;
+
+	  /*	  if (voxel==2184)
+	    fprintf(stderr,"r2=%f den=%f t2=%f\n",r2,exp(density),t2_v->GetComponent(voxel,0));*/
+	}
+      r2_v->SetComponent(voxel,0,1000.0*r2);
+      den_v->SetComponent(voxel,0,exp(density));
+      
+      ++count;
+      if (count==tenth)
+	{
+	  this->UpdateProgress(0.1+this->GetProgress());
+	  count=0;
+	}
+    }
+  this->UpdateProgress(1.0);
+  
+
+  delete [] x;
+  delete [] ind;
+  delete [] temp;
+}
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxLogExponentialFit.h b/bioimagesuite30_src/Segmentation/vtkpxLogExponentialFit.h
new file mode 100644
index 0000000..8b2d862
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxLogExponentialFit.h
@@ -0,0 +1,135 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxLogExponentialFit.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:02:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxLogExponentialFit -- compute phase/magnitude from raw reconstruction image on Bruker
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxLogExponentialFit_h
+#define __vtkpxLogExponentialFit_h
+
+#include "vtkSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkIntArray.h"
+#include "vtkpxMatrix.h"
+#include "vtkFloatArray.h"
+
+class vtkpxLogExponentialFit : public vtkSimpleImageToImageFilter
+{
+public:
+  static vtkpxLogExponentialFit *New();
+  vtkTypeMacro(vtkpxLogExponentialFit,vtkSimpleImageToImageFilter);
+
+  // Description: 
+  // Create Echo Train
+  virtual int CreateEchoTrain(float FirstEchoTime,float  EchoSpacing,int numechos=-1);
+
+  // Description:
+  // Get Outputs
+  vtkGetObjectMacro(EchoTrain,vtkFloatArray);
+  vtkSetObjectMacro(EchoTrain,vtkFloatArray);
+
+  // Description: 
+  // Thresholds 
+  vtkGetMacro(MaxT2Value,float);
+  vtkSetMacro(MaxT2Value,float);
+
+  // Description: 
+  // Thresholds 
+  vtkSetClampMacro(IntensityThreshold,float,0.0,0.5);
+  vtkGetMacro(IntensityThreshold,float);
+
+  // Description;
+  // density-map (i.e. magnitude of intensity as opposed to relaxation time)
+  vtkGetObjectMacro(DensityMap, vtkImageData);
+
+  // Description;
+  // r2-map (i.e. 1000.0/T2)
+  vtkGetObjectMacro(R2Map, vtkImageData);
+
+
+
+
+protected:
+
+  vtkpxLogExponentialFit();
+  virtual ~vtkpxLogExponentialFit();
+  vtkpxLogExponentialFit(const vtkpxLogExponentialFit&) {};
+  void operator=(const vtkpxLogExponentialFit&) {};
+
+
+  virtual void SimpleExecute(vtkImageData*,vtkImageData*);
+  virtual int RequestInformation(vtkInformation *vtkNotUsed(request),  vtkInformationVector **inputVector, 
+				 vtkInformationVector *outputVector);
+
+
+  //BTX
+  float IntensityThreshold;
+  vtkImageData *R2Map,*DensityMap;
+  float MaxT2Value;
+  vtkFloatArray* EchoTrain;
+  //ETX
+
+  
+
+
+
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxMRFSegmentation.cpp b/bioimagesuite30_src/Segmentation/vtkpxMRFSegmentation.cpp
new file mode 100644
index 0000000..fc5635b
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxMRFSegmentation.cpp
@@ -0,0 +1,1521 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxMRFSegmentation.cpp,v $
+  Language:  C++
+  Date:      $Date: 2005/08/19 18:34:53 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkObjectFactory.h"
+#include "vtkpxMRFSegmentation.h"
+#include "vtkpxUtil.h"
+#include "vtkFloatArray.h"
+#include "vtkpxMath.h"
+#include "vtkImageShiftScale.h"
+#include "vtkMath.h"
+#include "vtkImageExtractComponents.h"
+#include "vtkbisImageReslice.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageCast.h"
+#include "vtkImageShiftScale.h"
+#include "vtkpxAbstractBiasFieldCorrection.h"
+#include "pxisinf.h"
+
+
+vtkpxMRFSegmentation* vtkpxMRFSegmentation::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxMRFSegmentation");
+  if(ret)
+    {
+    return (vtkpxMRFSegmentation*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxMRFSegmentation;
+}
+
+// Construct object with no children.
+vtkpxMRFSegmentation::vtkpxMRFSegmentation()
+{
+  this->Smoothness=0.3;
+  this->MRFIterations=8;
+  this->DebugVoxel=0;
+
+  this->MRFConvergencePercentage=0.2;
+  this->PartialStep=0.125;
+  this->FuzzyClassification=0;
+
+  this->FitQualityMap=NULL;
+  this->MultiFrameOutput=NULL;
+  this->BiasField=NULL;
+  this->BiasFieldWeights=NULL;
+  this->HistogramNormalization=0;
+  this->NumberOfChannels=1;
+  this->SingleChannel=1;
+  this->ImageNoiseSigma=1.0;
+  this->MRFBasedFitQuality=1;
+  this->MRFThreshold=0.1;
+  this->ComputeBiasField=0;
+  this->TensorSpline=vtkpxImageTensorSpline::New();
+  this->PerformingFuzzyClassification=0;
+  this->BiasFieldFactor=6.0;
+  this->BiasFieldSigma=0.25;
+}
+// ----------------------------------------------------------------------------
+vtkpxMRFSegmentation::~vtkpxMRFSegmentation()
+{
+  if (this->MultiFrameOutput!=NULL)
+    this->MultiFrameOutput->Delete();
+
+  if (this->BiasField!=NULL)
+    this->BiasField->Delete();
+  
+  if (this->BiasFieldWeights!=NULL)
+    this->BiasFieldWeights->Delete();
+
+  this->SetFitQualityMap(NULL);
+
+  if (this->TensorSpline!=NULL)
+    this->TensorSpline->Delete();
+}
+// ----------------------------------------------------------------------------
+//
+//       M - Step 
+//
+// ----------------------------------------------------------------------------
+
+void vtkpxMRFSegmentation::CombineMeansAndStandardDeviations(vtkFloatArray* params,int class1,int class2,float fraction1,float* theta,int debug)
+{
+  fraction1=Frange(fraction1,0.0,1.0);
+
+  for (int channel=0;channel<this->NumberOfChannels;channel++)
+    {
+
+      int b0=this->ChannelMean(channel);
+      int b1=this->ChannelSigma(channel);
+
+      if (class1==class2)
+	{
+	  for (int k=b0;k<=b1;k++)
+	    theta[k]=params->GetComponent(class1,k);
+	  
+	  if ( debug)
+	    {
+	      fprintf(stderr,"Combining channel=%d\n",channel);
+	      fprintf(stderr,"\t class=%d =%.2f+%.2f \n",class1+1,theta[b0],theta[b1]);
+	    }
+	}
+      else
+	{
+	  theta[b0]=fraction1*params->GetComponent(class1,b0)+(1.0-fraction1)*params->GetComponent(class2,b0);
+	  theta[b1]=sqrt(pow(fraction1*params->GetComponent(class1,b1),2.0)+pow((1.0-fraction1)*params->GetComponent(class2,b1),2.0));
+	  
+	  
+	  if ( debug)
+	    {
+	      fprintf(stderr,"\t channel =%d\n",channel+1);
+	      fprintf(stderr,"\t class1=%d (%.2f)\t  %.2f+%.2f \n",class1+1,fraction1,
+		      params->GetComponent(class1,b0),
+		      params->GetComponent(class1,b1));
+	      
+	      fprintf(stderr,"\t class2=%d (%.2f)\t  %.2f+%.2f \n",class2+1,1-fraction1,
+		      params->GetComponent(class2,b0),
+		      params->GetComponent(class2,b1));
+	      
+	      fprintf(stderr,"\t combined  \t \t %.2f+%.2f \n\n",
+		      theta[b0],theta[b1]);
+	    }
+	}
+    }
+  return;
+  
+}
+
+// -------------------------------------------------------------------------------------------------------------------------------
+//
+//      Expectation Step Stuff 
+//
+// -------------------------------------------------------------------------------------------------------------------------------
+void vtkpxMRFSegmentation::UpdateFitQualityMapFromMRF(vtkImageData* label_image,vtkImageData* fit_quality,float threshold)
+{
+  
+  vtkDataArray* fitq=fit_quality->GetPointData()->GetScalars();
+  vtkDataArray* labels=label_image->GetPointData()->GetScalars();
+
+  int dim[3]; label_image->GetDimensions(dim);
+  int incr[6]; float wgth[6]; this->ComputeMRFIncrementsAndWeights(label_image,incr,wgth);
+
+  int mink=1,maxk=dim[2]-1;
+  if (dim[2]==1)
+    {
+      mink=0;
+      maxk=1;
+    }
+
+  int slicesize=dim[0]*dim[1];
+  fitq->FillComponent(0,0.0);
+
+  int numclasses=labels->GetNumberOfComponents();
+
+
+  int numgood=0;
+  int numtotal=fitq->GetNumberOfTuples();
+
+  float ratio=0.0;
+
+  while (ratio<25.0)
+    {
+      numgood=0;
+      for (int k=mink;k<maxk;k++)
+	for (int j=1;j<dim[1]-1;j++)
+	  for (int i=1;i<dim[0]-1;i++)
+	    {
+	      int vox=i+j*dim[0]+k*slicesize;
+	      double sum=0.0;
+	      
+	      for (int c=0;c<numclasses;c++)
+		{
+		  float g=0.0;
+		  for (int ia=0;ia<=5;ia++)
+		    {
+		      if (wgth[ia]>0.0001)
+			g+=wgth[ia]*labels->GetComponent(vox+incr[ia],c);
+		    }
+		  sum+=(pow(labels->GetComponent(vox,c)-g,2.0));
+		}
+	      
+	      if (sum<threshold)
+		{
+		  fitq->SetComponent(vox,0,1.0);
+		  numgood+=1;
+		}
+	    }
+      
+      ratio=100.0*float(numgood)/float(numtotal);
+      fprintf(stderr,"\t\t ********* Fit Quality  %.2f  voxels good\n",ratio);
+      threshold*=2.0;
+    }
+}
+// -------------------------------------------------------------------------------------------------------------------------------
+void vtkpxMRFSegmentation::ComputeClassSums(vtkImageData* label_image,
+					    vtkImageData* fitted_image,
+					    vtkImageData* fit_quality,
+					    vtkImageData* bias_field,
+					    float partial_threshold,
+					    vtkFloatArray* params,int numclasses)
+{
+  vtkDataArray* fitted=fitted_image->GetPointData()->GetScalars();
+  vtkDataArray* labels=label_image->GetPointData()->GetScalars();
+
+  vtkDataArray* quality=NULL;
+  if (fit_quality!=NULL)
+    quality=fit_quality->GetPointData()->GetScalars();
+
+  vtkDataArray* bfield=NULL;
+  if (bias_field!=NULL)
+    bfield=bias_field->GetPointData()->GetScalars();
+  
+  int nt=fitted->GetNumberOfTuples();
+
+  int nparam=params->GetNumberOfComponents();
+  for (int ia=0;ia<nparam;ia++)
+    params->FillComponent(ia,0.0);
+
+  /*  fprintf(stderr,"Number Of Components param=%d label=%d fitted=%d number of channels=%d ImageNoise=%.2f\n",
+      nparam,labels->GetNumberOfComponents(),fitted->GetNumberOfComponents(),this->NumberOfChannels,this->ImageNoiseSigma);*/
+  
+  // Compute Sums
+  // ------------
+  //  partial_threshold=0.0;
+
+  // Step 1 ------- Compute Sums and Sum Of Squares 
+
+  for (int vox=0;vox<nt;vox++)
+    {
+      float w=1.0;
+      if (quality!=NULL)
+	w=quality->GetComponent(vox,0);
+
+      float biasfieldvalue=1.0;
+      if (bfield!=NULL)
+	biasfieldvalue=bfield->GetComponent(vox,0);
+      
+      for (int c=0;c<numclasses;c++)
+	{
+	  float partial=labels->GetComponent(vox,c);
+	  if (partial> partial_threshold)
+	    {
+	      partial=partial*w;
+	      params->SetComponent(c,0,params->GetComponent(c,0)+partial);
+	      
+	      for (int channel=0;channel<this->NumberOfChannels;channel++)
+		{
+		  int b0=this->ChannelMean(channel);
+		  int b1=this->ChannelSigma(channel);
+		  float d_value=fitted->GetComponent(vox,channel)/biasfieldvalue;
+		  
+		  params->SetComponent(c,b0,params->GetComponent(c,b0)+partial*d_value);
+		  params->SetComponent(c,b1,params->GetComponent(c,b1)+partial*d_value*d_value);
+		}
+	    }
+	}
+    }
+
+  for (int c=0;c<numclasses;c++)
+    {
+      if (params->GetComponent(c,0)<1e-6)
+	params->SetComponent(c,0,1e-6);
+    }
+
+}
+// -------------------------------------------------------------------------------------------------------------------------------
+int vtkpxMRFSegmentation::FitModelToSums(vtkFloatArray* ,int )
+{
+  return 0;
+}
+// -------------------------------------------------------------------------------------------------------------------------------
+  
+void vtkpxMRFSegmentation::ComputeClassMeansAndStandardDeviations(vtkFloatArray* params,int numclasses,int domeans,int doprint)
+{
+  int nc=this->NumberOfChannels;
+  float* maxsigma =new float[nc];
+  float totalnp=0.0;
+  
+  for (int cl2=0;cl2<numclasses;cl2++)
+    totalnp+=params->GetComponent(cl2,0);
+
+  for (int channel=0;channel<this->NumberOfChannels;channel++)
+    {
+      int b0=this->ChannelMean(channel);
+      int b1=this->ChannelSigma(channel);
+      
+      maxsigma[channel]=0.0;
+      for (int cl=0;cl<numclasses;cl++)
+	{
+	  float np=params->GetComponent(cl,0);
+
+	  float meanden =params->GetComponent(cl,b0);
+	  if (isnan(meanden))
+	    meanden=1.0;
+
+	  if (domeans)
+	    meanden=meanden/np;
+
+	  float mean2den =params->GetComponent(cl,b1)/np;
+	  if (isnan(mean2den))
+	    mean2den=2.0;
+	  
+	  float sigmaden= sqrt( mean2den-meanden*meanden);
+	  if (isnan(sigmaden))
+	    sigmaden=0.1*meanden;
+
+	  params->SetComponent(cl,b0,meanden);
+	  params->SetComponent(cl,b1,sigmaden);
+      
+	  if (sigmaden>maxsigma[channel])
+	    maxsigma[channel]=sigmaden;
+	}
+      maxsigma[channel]=maxsigma[channel]*this->MaxSigmaRatio;
+    }
+
+  if (doprint)
+    {
+      fprintf(stderr,"\t\t Composition\n");
+      for (int cl=0;cl<numclasses;cl++)
+	{
+	  if (cl==numclasses-1 && this->OutlierDetection==1)
+	    fprintf(stderr,"+++++++++++++++++++++++++++++ Outlier\t %8.0f \t %5.2f  \n",params->GetComponent(cl,0),100.0*params->GetComponent(cl,0)/float(totalnp));
+	  else
+	    fprintf(stderr,"+++++++++++++++++++++++++++++ %d\t %8.0f \t %5.2f  \n",cl+1,params->GetComponent(cl,0),100.0*params->GetComponent(cl,0)/float(totalnp));
+	}
+    }
+
+  if (doprint)
+    fprintf(stderr,"\n\n# Data Printing\n Channel \t  Mean, Sigma      \t Mean, Sigma     \t Mean, Sigma     \n");
+
+  for (int channel=0;channel<this->NumberOfChannels;channel++)
+    {
+      fprintf(stderr,"%6.2f \t ",this->GetChannelEchoTime(channel));
+      for (int cl=0;cl<numclasses;cl++)
+	{
+      	  int b0=this->ChannelMean(channel);
+	  int b1=this->ChannelSigma(channel);
+	  
+	  if (params->GetComponent(cl,b1)<maxsigma[channel])
+	    {
+	      float old=params->GetComponent(cl,b1);
+	      params->SetComponent(cl,b1,maxsigma[channel]);
+	    }
+
+	  if (doprint)
+	    fprintf(stderr,"%6.2f, %6.2f \t ",params->GetComponent(cl,b0),params->GetComponent(cl,b1));
+	}
+      
+      if (doprint)
+	fprintf(stderr,"%.2f \n",maxsigma[channel]);
+    }
+
+  return;
+}
+// -------------------------------------------------------------------------------------------------------------------------------
+void vtkpxMRFSegmentation::DoExpectationStep(vtkImageData* label_image,
+					     vtkImageData* fitted_image,
+					     vtkImageData* fit_quality,
+					     vtkImageData* bias_field,
+					     float partial_threshold,
+					     vtkFloatArray* params,
+					     int numclasses)
+{
+
+  if (this->MRFBasedFitQuality)
+    this->UpdateFitQualityMapFromMRF(label_image,fit_quality,this->MRFThreshold);
+
+  this->ComputeClassSums(label_image,fitted_image,fit_quality,bias_field,partial_threshold,params,numclasses);
+
+  int domeans=1;
+  if (this->FitModelToSums(params,numclasses)==1)
+    domeans=0;
+  this->ComputeClassMeansAndStandardDeviations(params,numclasses,domeans,1);
+}
+
+// ----------------------------------------------------------------------------
+//
+// M - Step
+//
+// ---------------------------------------------------------------------------
+void vtkpxMRFSegmentation::ComputeInitialBiasField(vtkImageData* clean_image,vtkImageData* cleanLabels,vtkImageData* fit_quality,
+						   vtkImageData* bias_field_image,vtkImageData* weight_image,
+						   vtkFloatArray* params)
+{
+  fprintf(stderr,"\t\t ******* Computing Initial Bias Field .... \n");
+  vtkDataArray* image_data=clean_image->GetPointData()->GetScalars();
+  vtkDataArray* label_data=cleanLabels->GetPointData()->GetScalars();
+  vtkDataArray* fitq_data =fit_quality->GetPointData()->GetScalars();
+  vtkDataArray* bfield=bias_field_image->GetPointData()->GetScalars();
+  vtkDataArray* weights=weight_image->GetPointData()->GetScalars();
+
+  bfield->FillComponent(0,0.0);
+  weights->FillComponent(0,0.0);
+  
+
+  int nt=image_data->GetNumberOfTuples();
+  int numc=this->NumberOfClasses;
+  for (int voxel_index=0;voxel_index<nt;voxel_index++)
+    {
+      if (fitq_data->GetComponent(voxel_index,0)>0)
+	{
+	  int   bestcl=0;
+	  float bestprob=label_data->GetComponent(voxel_index,0);
+	  for (int i=1;i<numc;i++)
+	    {
+	      float newl=label_data->GetComponent(voxel_index,i);
+	      if (newl>bestprob)
+		{
+		  bestprob=newl;
+		  bestcl=i;
+		}
+	    }
+	  
+	  if (bestcl>0)
+	    {
+	      float sxx=0.0,sxy=0.0;
+	      for (int channel=0;channel<this->NumberOfChannels;channel++)
+		{
+		  int b0=this->ChannelMean(channel);
+		  float v1=params->GetComponent(bestcl,b0);
+		  float v2=image_data->GetComponent(voxel_index,channel);
+		  
+		  sxx+=v1*v1;
+		  sxy+=v2*v1;
+		}
+	      float r=sxy/sxx;
+	      if (r<0.5)
+		r=0.5;
+	      else if (r>2.0)
+		r=2.0;
+	      bfield->SetComponent(voxel_index,0,r*1.0);
+	      weights->SetComponent(voxel_index,0,1.0);
+	    }
+	}
+    }
+}
+
+void vtkpxMRFSegmentation::ComputeSmoothBiasField(vtkImageData* bias_field,vtkImageData* fit_quality,float Sigma)
+{
+  Sigma=fabs(Sigma);
+  if (Sigma<1.0)
+    Sigma=1.0;
+  else if (Sigma>5.0)
+    Sigma=5.0;
+
+  fprintf(stderr,"\t\t ******* Computing Smooth Bias Field .... %.2f",Sigma);
+
+  int offset=1;//int(Sigma/2);
+
+  double sp[3],sigma[3]; bias_field->GetSpacing(sp);
+  Sigma=Sigma*sp[0];
+
+
+
+  for (int i=0;i<=2;i++)
+    sigma[i]=Sigma/sp[i];
+
+  vtkImageGaussianSmooth* sm[2];
+  int nvox[2];
+
+  for (int i=0;i<=1;i++)
+    {
+      sm[i]=vtkImageGaussianSmooth::New();
+      if (i==0)
+	sm[i]->SetInput(bias_field);
+      else
+	sm[i]->SetInput(fit_quality);
+      sm[i]->SetStandardDeviations(sigma);
+      sm[i]->Update();
+      nvox[i]=sm[i]->GetOutput()->GetPointData()->GetScalars()->GetNumberOfTuples();
+    }
+
+
+
+  int nt=bias_field->GetPointData()->GetScalars()->GetNumberOfTuples();
+
+
+  if (nvox[0]==nt && nvox[1]==nt)
+    {
+      vtkDataArray* numerator=sm[0]->GetOutput()->GetPointData()->GetScalars();
+      vtkDataArray* denominator=sm[1]->GetOutput()->GetPointData()->GetScalars();
+      vtkDataArray* bfield=bias_field->GetPointData()->GetScalars();
+
+      bfield->FillComponent(0,1.0);
+
+      int dim[3]; bias_field->GetDimensions(dim);
+      int slicesize=dim[0]*dim[1];
+      float sum=0.0,nsum=0.0;
+
+
+      for (int k=offset;k<dim[2]-offset;k++)
+	for (int j=offset;j<dim[1]-offset;j++)
+	  for (int i=offset;i<dim[0]-offset;i++)
+	    {
+	      int indx=i+j*dim[0]+k*slicesize;
+	      double y=numerator->GetComponent(indx,0);
+	      double x=denominator->GetComponent(indx,0);
+	      
+	      if (x>0.1)
+		{
+		  float r=y/x;
+		  if (r<0.667)
+		    r=0.667;
+		  else if (r>1.5)
+		    r=1.5;
+		  bfield->SetComponent(indx,0,r);
+		}
+	      
+	      sum+=bfield->GetComponent(indx,0);
+	      nsum+=1.0;
+	    }
+      
+      float factor=nsum/sum;
+      fprintf(stderr,"Factor=%.2f\n",factor);
+      /*	      for (int i=0;i<nt;i++)
+	      {
+	      double b=bfield->GetComponent(i,0)*factor;
+	      bfield->SetComponent(i,0,b);
+	      }*/
+      
+      fprintf(stderr,"\t\t  Done Computing Smooth Bias Field\n");
+    }
+  else
+    {
+      fprintf(stderr,"Error Not Computing Smooth Bias Field %d,%d,%d\n",nt,nvox[0],nvox[1]);
+    }
+
+  sm[1]->Delete();
+  sm[0]->Delete();
+
+
+
+
+}
+// ----------------------------------------------------------------------------
+
+void vtkpxMRFSegmentation::TensorFitBiasFieldImage(vtkImageData* bias_field,vtkImageData* weight_image)
+{
+  fprintf(stderr,"\t\t ****** Fitting Tensor Spline .... \n");
+  if (this->TensorSpline!=NULL)
+    this->TensorSpline->Delete();
+  this->TensorSpline=vtkpxImageTensorSpline::New();
+  this->TensorSpline->SetInput(bias_field);
+  this->TensorSpline->SetWeightImage(weight_image);
+
+  double sp[3]; bias_field->GetSpacing(sp);
+  int   dim[3]; bias_field->GetDimensions(dim);
+
+  float spacing=dim[0]*sp[0]/this->BiasFieldFactor;
+  
+  this->TensorSpline->SetControlPointSpacing(spacing);
+  this->TensorSpline->SetResolution(2.0);
+  this->TensorSpline->SetAutoInitialize(1);
+  this->TensorSpline->Run();
+  bias_field->ShallowCopy(this->TensorSpline->GetOutput());
+
+  vtkDataArray* bfield=bias_field->GetPointData()->GetScalars();
+  int nt=bfield->GetNumberOfTuples();
+  for (int i=0;i<nt;i++)
+    {
+      float v=bfield->GetComponent(i,0);
+      if (v<0.667)
+	bfield->SetComponent(i,0,0.667);
+      else if (v>1.5)
+	bfield->SetComponent(i,0,1.5);
+    }
+
+  fprintf(stderr,"\t\t ****** Fitting Tensor Spline .... Done\n");
+
+}
+// ----------------------------------------------------------------------------
+// Compute Individual Probability Components 
+// ----------------------------------------------------------------------------
+
+int vtkpxMRFSegmentation::DebugPrint(int vox)
+{
+  if (vox==0)
+    return 1;
+
+
+  if (this->DebugVoxel==0 || vox==0)
+    return 0;
+
+  if (vox - this->DebugVoxel == 0)
+    return 1;
+
+  return 0;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+double vtkpxMRFSegmentation::ComputeLogLikelihoodProbability(vtkDataArray* image_data,int vox,float* theta,float noise_sigma,float bfield,float& newbfield,
+							     int debug)
+{
+  double totalprob=0.0;
+  float r=1.0;
+  /*  if (this->ComputeBiasField)
+    {
+      float sxx=0.0,sxy=0.0;
+      for (int channel=0;channel<this->NumberOfChannels;channel++)
+	{
+	  int b0=this->ChannelMean(channel);
+	  float v1=theta[b0];
+	  float v2=image_data->GetComponent(vox,channel);
+	  
+	  sxx+=v1*v1;
+	  sxy+=v2*v1;
+	}
+      r=sxy/sxx;
+      
+      float r1=(r-bfield);
+
+      if (r1<-this->BiasFieldSigma)
+	r1=bfield+this->BiasFieldSigma;
+      else if (r1>this->BiasFieldSigma)
+	r1=bfield-this->BiasFieldSigma;
+      newbfield=r1;
+    }
+    else*/
+  newbfield=bfield;
+	
+  for (int channel=0;channel<this->NumberOfChannels;channel++)
+    {
+      int b0=this->ChannelMean(channel);
+      int b1=this->ChannelSigma(channel);
+            
+      float mean=theta[b0];
+      float variance=theta[b1]*theta[b1]+pow(noise_sigma/newbfield,float(2.0));
+      totalprob+=log(vtkpxHistogramSegmentation::Metric(image_data->GetComponent(vox,channel)/newbfield,mean,variance));
+    }
+
+  if (debug)
+    fprintf(stderr,"\n\t PROB(%d)::   -logp=%f\n",    vox,-(totalprob));
+  
+  return totalprob;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+double vtkpxMRFSegmentation::ComputeMRFPrior(vtkDataArray* labels,int vox,float* current_labels,int incr[6],float wgth[6],int debug)
+{
+  if (debug)
+    fprintf(stderr,"\t MRF [ g=");
+
+  double sum=0.0;
+  int numclasses=labels->GetNumberOfComponents();
+  for (int c=0;c<numclasses;c++)
+    {
+      float g=0.0;
+      for (int i=0;i<=5;i++)
+	{
+	  if (wgth[i]>0.0001)
+	    g+=wgth[i]*labels->GetComponent(vox+incr[i],c);
+	}
+
+      if (debug)
+	fprintf(stderr,"%d(%5.3f - %5.3f),",c+1,current_labels[c],g);
+      
+      sum+=(pow(current_labels[c]-g,float(2.0)));
+    }
+
+  if (debug)
+    fprintf(stderr,"] sum=%.2f\n ",sum);
+
+  return sum;
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+double vtkpxMRFSegmentation::ComputeTotalMinusLogProbability(vtkDataArray* image_data,
+							    vtkDataArray* labels,
+							     int voxel_index,
+							     float *currentlab,
+							     float* theta,
+							     float noise_sigma,
+							     float bfield,
+							     int incr[6],float wgth[6],
+							     float smoothness,
+							     int debug)
+{
+  float newbfield=0.0;
+  double mlterm=this->ComputeLogLikelihoodProbability(image_data,voxel_index,theta,noise_sigma,bfield,newbfield,debug);
+  double pmrf  =0.0;
+  if (smoothness>0.001)
+    pmrf=smoothness*this->ComputeMRFPrior(labels,voxel_index,currentlab,incr,wgth,debug);
+  /*  double bterm =0.0;
+  if (this->ComputeBiasField)
+  bterm=log(vtkpxHistogramSegmentation::Metric(newbfield,bfield,this->BiasFieldSigma));*/
+  double t=-mlterm+pmrf;
+
+  if (debug)
+    fprintf(stderr,"\t Total Minus Log Probability=%.2f\n ",t);
+
+  return t;
+}
+
+
+double vtkpxMRFSegmentation::ComputeTotalMinusLogProbabilityOutlier(vtkDataArray* labels,
+								   int voxel_index,
+								   float *currentlab,
+								   float* theta,
+								   int incr[6],float wgth[6],float smoothness,int debug)
+{
+  double mlterm=this->OutlierProbability;
+  double pmrf  =this->ComputeMRFPrior(labels,voxel_index,currentlab,incr,wgth,debug);
+  double t=-log(mlterm)+smoothness*pmrf;
+
+  if (debug)
+    fprintf(stderr,"\t Total Minus Log Probability=%.2f\n ",t);
+
+  return t;
+
+}
+// --------------------------------------------------------------------------------------------
+int vtkpxMRFSegmentation::DoHardClassification(int voxel_index,int actual_num_classes,float prob[20],float& bestprob,
+						 float new_labels[20])
+						 
+{
+  int bestclass=0;
+  bestprob=0.0;
+
+  float biasfieldvalue=1.0;
+  if (OptimizationStructure.biasfield!=NULL)
+    biasfieldvalue=OptimizationStructure.biasfield->GetComponent(voxel_index,0);
+
+  for (int cl=0;cl< actual_num_classes;cl++)
+    {
+      for (int cl2=0;cl2< actual_num_classes;cl2++)
+	new_labels[cl2]=0.0;
+
+
+      float theta[200];
+      if ( this->DebugPrint(voxel_index))
+	fprintf(stderr,"\n\n ------------ Beginning Class %d\n++++ Prior(%d):",
+		cl+1,OptimizationStructure.voxel_index);
+      
+      this->CombineMeansAndStandardDeviations(OptimizationStructure.params,cl,cl,1.0,theta,this->DebugPrint(voxel_index));
+      OptimizationStructure.SetIndex(voxel_index,this->DebugPrint(voxel_index));
+
+      OptimizationStructure.currentclass[0]=cl;
+      OptimizationStructure.currentclass[1]=cl;
+      OptimizationStructure.currentfraction=1.0;
+      OptimizationStructure.numberofcomponentclasses=1;
+      new_labels[cl]=1.0;
+      
+      if (this->OutlierDetection==1 && cl==actual_num_classes-1)
+	prob[cl]=this->ComputeTotalMinusLogProbabilityOutlier(OptimizationStructure.labels,
+							      OptimizationStructure.voxel_index,
+							      &new_labels[0],
+							      &theta[0],
+							      OptimizationStructure.incr,
+							      OptimizationStructure.wgth,
+							      OptimizationStructure.smoothness,
+							      OptimizationStructure.debug);
+      else
+	prob[cl]=this->ComputeTotalMinusLogProbability(OptimizationStructure.image_data,
+						       OptimizationStructure.labels,
+						       OptimizationStructure.voxel_index,
+						       &new_labels[0],
+						       &theta[0],
+						       OptimizationStructure.noisesigma,
+						       biasfieldvalue,
+						       OptimizationStructure.incr,
+						       OptimizationStructure.wgth,
+						       OptimizationStructure.smoothness,
+						       OptimizationStructure.debug);
+      if (cl==0 || prob[cl]<bestprob)
+	{
+	  bestprob=prob[cl];
+	  bestclass=cl;
+  	}
+      
+    }
+
+
+
+
+  return bestclass;
+}
+// --------------------------------------------------------------------------------------------
+int vtkpxMRFSegmentation::DoFuzzyClassification(int voxel_index,int actual_num_classes,float prob[20],float& bestprob,
+						float new_labels[20])
+{
+  
+  if (this->DebugPrint(voxel_index))
+    fprintf(stderr,"\n\n ffff Fuzzy Classification \n");
+  
+  float biasfieldvalue=1.0;
+  if (OptimizationStructure.biasfield!=NULL)
+    biasfieldvalue=OptimizationStructure.biasfield->GetComponent(voxel_index,0);
+
+  // 1. Sort and find best 2 classes for this voxel
+  // ----------------------------------------------
+  int ignore=-1,rank[2],bestindex=0;
+  float best=prob[0];
+  
+  for (int outer=0;outer<=1;outer++)
+    {
+      for (int cl=0;cl< this->NumberOfClasses;cl++)
+	{
+	  if (prob[cl]<best && cl!=ignore)
+	    {
+	      best=prob[cl];
+	      bestindex=cl;
+	      
+	    }
+	}
+      rank[outer]=bestindex;
+      
+      if (outer==0)
+	{
+	  ignore=bestindex;
+	  if (bestindex==0)
+	    bestindex=1;
+	  else
+	    bestindex=0;
+	  best=prob[bestindex];
+	}
+    }
+  
+  
+  // 2. Optimize Partial
+  // -------------------
+  bestprob=prob[rank[0]];
+  float secondbestprob=prob[rank[1]];
+  float bestpartial=0.0;
+  float secondbestpartial=1.0;
+  
+  if (this->DebugPrint(voxel_index))
+    fprintf(stderr,"\t\t BestClasses %d (%.2f) and  %d (%.2f) optimal=(%.2f,%.2f)\n",rank[0]+1,prob[rank[0]],rank[1]+1,prob[rank[1]],bestpartial,bestprob);
+  
+  OptimizationStructure.SetIndex(voxel_index,this->DebugPrint(voxel_index));
+  
+  int maxattempts=4;
+  
+  for (int attempt=0;attempt<maxattempts;attempt++)
+    {
+      float partial=0.5*(bestpartial+secondbestpartial);
+      
+      float fraction[2];
+      float theta[200];
+      fraction[0]=1.0-partial;
+      fraction[1]=partial;
+      
+      for (int cl2=0;cl2< this->NumberOfClasses;cl2++)
+	new_labels[cl2]=0.0;
+      new_labels[rank[0]]=fraction[0];
+      new_labels[rank[1]]=fraction[1];
+      
+      if (this->DebugPrint(voxel_index))
+	{
+	  fprintf(stderr,"\n\t\t Partial Prob %.3f of %d and %.3f of %d\n",fraction[0],rank[0]+1,fraction[1],rank[1]+1);
+	  fprintf(stderr,"\t\t\t bestpartial %.3f (%.3f) secondbest %.3f (%.3f) \n",bestpartial,bestprob,secondbestpartial,secondbestprob);
+	}
+      
+      this->CombineMeansAndStandardDeviations(OptimizationStructure.params,rank[0],rank[1],fraction[0],theta,
+					      this->DebugPrint(voxel_index));
+      float partial_prob=this->ComputeTotalMinusLogProbability(OptimizationStructure.image_data,
+							       OptimizationStructure.labels,
+							       OptimizationStructure.voxel_index,
+							       &new_labels[0],
+							       &theta[0],
+							       OptimizationStructure.noisesigma,
+							       biasfieldvalue,
+							       OptimizationStructure.incr,
+							       OptimizationStructure.wgth,
+							       OptimizationStructure.smoothness,
+							       OptimizationStructure.debug);
+      
+      if (partial_prob < secondbestprob && partial_prob > bestprob)
+	{
+	  secondbestprob=partial_prob;
+	  secondbestpartial=partial;
+	}
+      else if (partial_prob < bestprob )
+	{
+	  secondbestprob=bestprob;
+	  secondbestpartial=bestpartial;
+	  bestprob=partial_prob;
+	  bestpartial=partial;
+	}
+      else
+	{
+	  attempt=maxattempts;
+	}
+    }
+  
+  new_labels[rank[0]]=1.0-bestpartial;
+  new_labels[rank[1]]=bestpartial;
+  
+  if ( this->DebugPrint(voxel_index))
+    fprintf(stderr,"\n **** Best Fraction =%.3f , bestprob=%.2f (%.3f,%.3f)\n",bestpartial,bestprob,new_labels[rank[0]],new_labels[rank[1]]);
+
+  return rank[1];
+  
+}
+// --------------------------------------------------------------------------------------------
+float  vtkpxMRFSegmentation::DoVoxelFit(int voxel_index)
+{
+  int actual_num_classes=this->NumberOfClasses+this->OutlierDetection;
+
+  // 1. Examine probability for all pure voxels   (use meanr2,mean density for each class i.e. do not reoptimize here)
+  // ----------------------------------------------
+
+  float current_labels[20],new_labels[20];
+  for (int c=0;c<actual_num_classes;c++)
+    current_labels[c]=OptimizationStructure.labels->GetComponent(voxel_index,c);
+
+  float prob[20],bestprob=0.0;
+  int bestclass=this->DoHardClassification(voxel_index,actual_num_classes,prob,bestprob,new_labels);
+
+
+  
+  if ( this->DebugPrint(voxel_index))
+    fprintf(stderr,"\n **** New_Labels:");
+
+  for (int cl=0;cl< actual_num_classes;cl++)
+    {
+      if (cl!=bestclass)
+	new_labels[cl]=0.0;
+      else
+	new_labels[cl]=1.0;
+      
+      if ( this->DebugPrint(voxel_index))
+	fprintf(stderr,"\t [%d]=%.2f (%.2f)",cl+1,new_labels[cl],prob[cl]);
+    }
+  
+  if ( this->DebugPrint(voxel_index))
+    fprintf(stderr,"\n");
+
+  if (this->PerformingFuzzyClassification==1 && this->OutlierDetection==0)
+    {
+      this->DoFuzzyClassification(voxel_index,actual_num_classes,prob,bestprob,new_labels);
+    }
+  
+  float changeinlab=0.0;
+  if ( this->DebugPrint(voxel_index))
+    fprintf(stderr," **** New_Fuzzy_Labels:");
+
+  for (int cl=0;cl< this->NumberOfClasses;cl++)
+    {
+      changeinlab+=fabs(new_labels[cl]-current_labels[cl]);
+      OptimizationStructure.labels->SetComponent(voxel_index,cl,new_labels[cl]);
+      if ( this->DebugPrint(voxel_index))
+	fprintf(stderr,"\t [%d]=%.2f, ",cl+1,new_labels[cl]);
+    }
+
+  if ( this->DebugPrint(voxel_index))
+    fprintf(stderr,"change =%.2f\n",changeinlab);
+  return changeinlab;
+
+}
+// ----------------------------------------------------------------------------------------------------
+//  High Level Routines
+// ----------------------------------------------------------------------------------------------------
+int  vtkpxMRFSegmentation::UpdateVoxel(int eveni,int evenj,int evenk,int pass)
+{
+  int update_voxel=0;
+  if (eveni == evenj) update_voxel=1;
+  if (evenk>=0)
+    {
+      if (evenk)   	  
+	update_voxel=1-update_voxel;
+    }
+  if (pass==1) 	  update_voxel=1-update_voxel;
+  
+  return update_voxel;
+}
+// ----------------------------------------------------------------------------
+int  vtkpxMRFSegmentation::ComputeMRFIncrementsAndWeights(vtkImageData* img,int incr[6],float wgt[6])
+{
+  int dim[3]; img->GetDimensions(dim);
+  double sp[3];img->GetSpacing(sp);
+
+  if (dim[2]>1)
+    {
+      incr[5]=dim[0]*dim[1];   wgt[5]=1.0/sp[2];
+      incr[4]=-incr[5];        wgt[4]=1.0/sp[2];
+    }
+  else
+    {
+      incr[5]=0;  incr[4]=0;
+      wgt[5]=0.0; wgt[4]=0.0;
+    }
+
+  incr[3]=dim[0];          wgt[3]=1.0/sp[1];
+  incr[2]=-incr[3];        wgt[2]=1.0/sp[1];
+  incr[1]=1;               wgt[1]=1.0/sp[0];
+  incr[0]=-incr[1];        wgt[0]=1.0/sp[0];
+
+
+
+  float sum=0.0;
+  for (int l=0;l<=5;l++)
+    sum+=wgt[l];
+
+  for (int k=0;k<=5;k++)
+    wgt[k]/=sum;
+  
+    
+  return 1;
+}
+// ----------------------------------------------------------------------------
+float vtkpxMRFSegmentation::DoMaximizationStep(vtkImageData* label_image,vtkImageData* intensity_image,vtkImageData* bias_field,
+					       float noise_sigma,
+					       vtkFloatArray* params,int numclasses,
+					       float smoothness,int maxiter)
+{
+  vtkDataArray* intensities=intensity_image->GetPointData()->GetScalars();
+  vtkDataArray* labels=label_image->GetPointData()->GetScalars();
+  vtkDataArray* bfield=bias_field->GetPointData()->GetScalars();
+
+  fprintf(stderr,"M-Step Number of Components intensity=%d labels=%d channels=%d\n",intensities->GetNumberOfComponents(),labels->GetNumberOfComponents(),
+	  this->NumberOfChannels);
+
+  int nt=intensities->GetNumberOfTuples();
+
+  int dim[3]; intensity_image->GetDimensions(dim);
+
+  int incr[6]; float weights[6]; this->ComputeMRFIncrementsAndWeights(intensity_image,incr,weights);
+
+  int done=0,iter=0;
+
+  int tenth=nt/11;
+
+
+  OptimizationStructure.SetBaseValues(intensities,
+				      labels,
+				      bfield,
+				      params,
+				      &incr[0],
+				      &weights[0],
+				      smoothness,
+				      noise_sigma);
+  
+  int mink=1,maxk=dim[2]-1;
+  if (dim[2]==1)
+    {
+      mink=0;
+      maxk=1;
+    }
+
+  float sumchanged=0.0;
+  if (smoothness<0.001)
+    maxiter=1;
+
+  while (done==0 && iter<maxiter)
+    {
+      float total=0.0;
+      float changed=0.0;
+      
+      int order=(vtkMath::Random()>0.5);
+  
+      fprintf(stderr,"\t **** MRF Fuzzy=%d Regularization (%.2f) iter=%d :",this->PerformingFuzzyClassification,smoothness,iter+1);
+      int count=0;
+
+      for (int pass=0;pass<=1;pass++)
+	{
+	  int realpass=pass;
+	  if (order==1)
+	    realpass=1-pass;
+
+	  for (int k=mink;k<maxk;k++)
+	    {
+	      int evenk= ( ( k % 2 )  == 0);
+	      if (maxk==1)
+		evenk=-1;
+
+	      for (int j=1;j<dim[1]-1;j++)
+		{
+		  int evenj= ( ( j % 2 ) == 0 );
+		  int vox=k*incr[5]+j*incr[3]+1;
+		  for (int i=1;i<dim[0]-1;i++)
+		    {
+		      int eveni= ( ( i % 2 ) == 0 );
+		      ++count;
+		      if (count==tenth)
+			{
+			  fprintf(stderr,".");
+			  count=0;
+			}
+
+		      // ----------------------------
+		      // Updating Voxel
+		      // ----------------------------
+		      
+		      if ( this->UpdateVoxel(eveni,evenj,evenk,pass)==1)
+			{
+			  changed+=this->DoVoxelFit(vox);
+
+			  for (int cl=0;cl<numclasses;cl++)
+			    {
+			      labels->SetComponent(vox,cl,OptimizationStructure.labels->GetComponent(vox,cl));
+			      total+=1.0;
+			    }
+			  
+
+			}
+		      ++vox;
+		    }
+		}
+	    }
+	}
+         
+      changed=100.0*changed/total;
+
+      sumchanged+=changed;
+
+      fprintf(stderr,"changed=%.2f\n\n",changed);
+      if (changed<this->MRFConvergencePercentage)
+	done=1;
+      ++iter;
+
+
+    }
+  return sumchanged;
+}
+// ----------------------------------------------------------------------------
+//
+//     Execute Segmentation 
+//
+// ----------------------------------------------------------------------------
+void vtkpxMRFSegmentation::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *input=this->GetImageDataInput(0);
+  vtkImageData *output=this->GetOutput();
+
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxMRFSegmentation");
+      return;
+    }
+
+  output->SetScalarTypeToShort();
+  output->SetNumberOfScalarComponents(1);
+}
+// ----------------------------------------------------------------------------
+//
+//         Helper Routines
+//
+// ----------------------------------------------------------------------------
+void vtkpxMRFSegmentation::GenerateLabelOutputs(vtkImageData* cleanLabels,vtkImageData* output)
+{
+  vtkImageShiftScale* sc=vtkImageShiftScale::New();
+  sc->SetScale(100.0);
+  sc->SetOutputScalarTypeToShort();
+  sc->SetShift(0.0);
+  sc->SetInput(cleanLabels);
+  sc->Update();
+  
+  if (this->MultiFrameOutput!=NULL)
+    this->MultiFrameOutput->Delete();
+  this->MultiFrameOutput=vtkImageData::New();
+  this->MultiFrameOutput->ShallowCopy(sc->GetOutput());
+  sc->Delete();
+  
+  vtkDataArray* complex=this->MultiFrameOutput->GetPointData()->GetScalars();
+  vtkDataArray*     out=output->GetPointData()->GetScalars();
+
+  int np=out->GetNumberOfTuples();
+  int np2=complex->GetNumberOfComponents();
+  for (int i=0;i<np;i++)
+    {
+      int best=0;
+      float maxv=complex->GetComponent(i,0);
+      for (int j=1;j<np2;j++)
+	{
+	  float v=complex->GetComponent(i,j);
+	  if (v>maxv)
+	    {
+	      maxv=v;
+	      best=j;
+	    }
+	}
+      out->SetComponent(i,0,best);
+    }
+}
+// ----------------------------------------------------------------------------
+void vtkpxMRFSegmentation::Optimization(vtkImageData* cleanLabels,vtkImageData* cleanInput,
+					vtkImageData* fitted_image,vtkImageData* fit_quality,
+					vtkImageData* bias_field,
+					float noise_sigma)
+{
+  int iter=1,done=0,countsmooth=1;
+  this->PerformingFuzzyClassification=0;
+  while (iter<=this->MRFIterations && done==0)
+    {
+      float smooth=this->Smoothness;//float(iter)*this->Smoothness/(0.5*float(this->MRFIterations));
+      fprintf(stderr,"\n\n---------------------------------------------------------------------------------------------------\n Beginning Global Iteration %d/%d  \n\n",iter,this->MRFIterations);
+      if (smooth>=this->Smoothness)
+	smooth=this->Smoothness;
+      
+      if (this->ComputeBiasField)
+	this->BiasField->GetPointData()->GetScalars()->FillComponent(0,1.0);
+	  
+      float changed=this->DoMaximizationStep(cleanLabels,cleanInput,bias_field,
+					     noise_sigma,
+						 this->Parameters,this->NumberOfClasses+this->OutlierDetection,smooth,5);
+      
+      
+      if (this->ComputeBiasField && countsmooth==4 )
+	{
+	  this->ComputeInitialBiasField(cleanInput,cleanLabels,fit_quality,bias_field,this->BiasFieldWeights,this->Parameters);
+	  
+	  vtkpxUtil::SaveAnalyze("initial_field.hdr",this->BiasField,0);
+	  
+	  if (this->BiasFieldFactor>0.0)
+	    this->TensorFitBiasFieldImage(bias_field,this->BiasFieldWeights);
+	  else
+	    this->ComputeSmoothBiasField(bias_field,this->BiasFieldWeights,this->BiasFieldFactor);
+	  
+	  vtkpxUtil::SaveAnalyze("smooth_field.hdr",this->BiasField,0);
+	  changed=100.0;
+	  countsmooth=0;
+	}
+      
+      this->DoExpectationStep(cleanLabels,
+			      fitted_image,fit_quality,bias_field,
+			      0.75,this->Parameters,this->NumberOfClasses+this->OutlierDetection);
+      
+      ++iter;
+      ++countsmooth;
+      this->UpdateProgress(float(iter)/float(this->MRFIterations));
+      
+      if (changed<this->MRFConvergencePercentage)
+	done=1;
+    }
+
+  // Fuzzy Classification if needed .. no additional bias field or expectation steps from here on
+  // --------------------------------------------------------------------------------------------
+  if (this->FuzzyClassification)
+    {
+      fprintf(stderr,"On to Fuzzy Classification Optimization %.2f\n",this->ImageNoiseSigma);
+      this->FuzzyClassificationOptimization(cleanLabels,cleanInput,fitted_image,fit_quality,bias_field,noise_sigma);
+    }
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxMRFSegmentation::FuzzyClassificationOptimization(vtkImageData* cleanLabels,vtkImageData* cleanInput,
+							   vtkImageData* fitted_image,vtkImageData* fit_quality,
+							   vtkImageData* bias_field,
+							   float noise_sigma)
+{
+  int iter=1,done=0;
+  this->PerformingFuzzyClassification=1;
+  while (iter<=this->MRFIterations && done==0)
+    {
+      float smooth=float(iter)*this->Smoothness/(float(this->MRFIterations));
+      fprintf(stderr,"\n\n---------------------------------------------------------------------------------------------------\n Beginning Fuzzy Iteration %d/%d  \n\n",iter,this->MRFIterations);
+      if (smooth>=this->Smoothness)
+	smooth=this->Smoothness;
+
+      float changed=this->DoMaximizationStep(cleanLabels,cleanInput,bias_field,noise_sigma,
+					     this->Parameters,this->NumberOfClasses+this->OutlierDetection,smooth,5);
+
+      ++iter;
+      this->UpdateProgress(float(iter)/float(this->MRFIterations));
+      if (changed<0.50*this->MRFConvergencePercentage)
+	done=1;
+    }
+
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxMRFSegmentation::GenerateInitialCleanLabelImageFromFirstFrame(vtkImageData* tmpLabels,vtkImageData* cleanLabels)
+{
+  vtkDataArray* lab=cleanLabels->GetPointData()->GetScalars();
+  vtkDataArray* tmp=tmpLabels->GetPointData()->GetScalars();
+  int  nt=lab->GetNumberOfTuples();
+  int  nc=lab->GetNumberOfComponents();
+
+  
+  for (int i=0;i<nt;i++)
+    {
+      int c=(int)tmp->GetComponent(i,0);
+      for (int j=0;j<nc;j++)
+	{
+	  if (j==c)
+	    lab->SetComponent(i,j,1.0);
+	  else
+	    lab->SetComponent(i,j,0.0);
+	}
+    }
+
+}
+
+// ----------------------------------------------------------------------------
+void vtkpxMRFSegmentation::GenerateFittedParametersAndCleanInput(vtkImageData* input,vtkImageData* cleanInput,
+								 vtkImageData* fitted_image,vtkImageData* fit_quality)
+{
+
+  cleanInput->ShallowCopy(input);
+  fitted_image->ShallowCopy(cleanInput);
+
+  if (this->FitQualityMap!=NULL &&   this->MRFBasedFitQuality==0)
+    fit_quality->ShallowCopy(this->FitQualityMap);
+  else
+    {
+      fit_quality->CopyStructure(cleanInput);
+      fit_quality->SetNumberOfScalarComponents(1);
+      fit_quality->SetScalarTypeToUnsignedChar();
+      fit_quality->AllocateScalars();
+      fit_quality->GetPointData()->GetScalars()->FillComponent(0,1.0);
+    }
+
+
+}
+// ----------------------------------------------------------------------------
+vtkImageData* vtkpxMRFSegmentation::CreateInitialLabels(vtkImageData* output)
+{
+  vtkImageData* cleanLabels=vtkImageData::New();
+  cleanLabels->CopyStructure(output);
+  cleanLabels->SetScalarTypeToFloat();
+  cleanLabels->SetNumberOfScalarComponents(this->NumberOfClasses+this->OutlierDetection);
+  cleanLabels->AllocateScalars();
+  
+  vtkDataArray* dat=cleanLabels->GetPointData()->GetScalars();
+  int nc=dat->GetNumberOfComponents();
+  float v=1.0/nc;
+  for (int i=0;i<nc;i++)
+    dat->FillComponent(i,v);
+  return cleanLabels;
+
+}
+// ----------------------------------------------------------------------------
+int vtkpxMRFSegmentation::CheckInitialParameters(vtkImageData* input)
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxMRFSegmentation");
+      return -1;
+    }
+
+  fprintf(stderr,"Number Of Classes = %d\n",this->NumberOfClasses);
+  if (this->Parameters==NULL)
+    this->Parameters=vtkFloatArray::New();
+
+  if (this->OutlierDetection)
+    this->FuzzyClassification=0;
+
+  return 1;
+}
+// ----------------------------------------------------------------------------
+vtkImageData* vtkpxMRFSegmentation::CreateSingleChannel(vtkImageData* input)
+{
+  vtkImageData* single=vtkImageData::New();
+  int nt=input->GetNumberOfScalarComponents();
+
+  if (nt==1)
+    {
+      single->DeepCopy(input);
+      this->SingleChannel=1;
+    }
+  else
+    {
+      if (this->KeyChannel<0)
+	this->KeyChannel=0;
+      else if (this->KeyChannel>=nt)
+	this->KeyChannel=nt-1;
+ 
+      fprintf(stderr,"Creating Single Channel: Using Key Channel=%d\n",this->KeyChannel);
+     
+      vtkImageExtractComponents* extr=vtkImageExtractComponents::New();
+      extr->SetInput(input);
+      extr->SetComponents(this->KeyChannel);
+      extr->Update();
+      
+      single->ShallowCopy(extr->GetOutput());
+      extr->Delete();
+    }
+
+  if (this->HistogramNormalization)
+    HistogramNormalizeImage(single,0.01,0.99);
+  
+  return single;
+}
+// ----------------------------------------------------------------------------
+void vtkpxMRFSegmentation::InitializeSegmentation(vtkImageData* singleChannel,vtkImageData* fitImage,
+						  vtkImageData* fitQuality,vtkImageData* cleanLabels)
+{
+  this->GenerateLabels=1;
+  
+  vtkImageData* tmp_labels=vtkImageData::New();
+  this->HistogramSegmentation(singleChannel,tmp_labels,this->Parameters,0,0);
+  this->GenerateInitialCleanLabelImageFromFirstFrame(tmp_labels,cleanLabels);
+
+
+  if (this->SingleChannel!=1)
+    {
+      // Force an Expectation Step at this Point
+      int nt=this->Parameters->GetNumberOfTuples();
+      int nc=2*fitImage->GetNumberOfScalarComponents()+1;
+      this->Parameters->SetNumberOfComponents(nc);
+      this->Parameters->SetNumberOfTuples(nt);
+      fprintf(stderr,"Doing Expectation Step\n\n");
+      this->DoExpectationStep(cleanLabels,
+			      fitImage,fitQuality,NULL,
+			      0.75,this->Parameters,this->NumberOfClasses+this->OutlierDetection);
+    }
+
+}
+// ----------------------------------------------------------------------------
+void vtkpxMRFSegmentation::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  int ok=this->CheckInitialParameters(input);
+  if (ok==-1)
+    return;
+
+  vtkImageData* cleanLabels=this->CreateInitialLabels(output);
+  vtkImageData* singleChannel=this->CreateSingleChannel(input);
+
+  vtkImageData* cleanInput=vtkImageData::New();
+  vtkImageData* fittedImage=vtkImageData::New();
+  vtkImageData* fitQuality =vtkImageData::New();
+
+  if (this->SingleChannel)
+    this->GenerateFittedParametersAndCleanInput(singleChannel,cleanInput,fittedImage,fitQuality);
+  else
+    this->GenerateFittedParametersAndCleanInput(input,cleanInput,fittedImage,fitQuality);
+
+  this->NumberOfChannels=fittedImage->GetNumberOfScalarComponents();
+
+  this->BiasField=vtkImageData::New();
+  this->BiasField->CopyStructure(input);
+  this->BiasField->SetNumberOfScalarComponents(1);
+  this->BiasField->SetScalarTypeToFloat();
+  this->BiasField->AllocateScalars();
+  this->BiasField->GetPointData()->GetScalars()->FillComponent(0,1.0);
+
+  if (this->ComputeBiasField)
+    {
+      this->BiasFieldWeights=vtkImageData::New();
+      this->BiasFieldWeights->CopyStructure(this->BiasField);
+      this->BiasFieldWeights->SetScalarTypeToFloat();
+      this->BiasFieldWeights->AllocateScalars();
+    }
+  
+  // Initialization Stuff 
+  // --------------------
+  fprintf(stderr,"Initializing Segmentation\n");
+  this->InitializeSegmentation(singleChannel,fittedImage,fitQuality,cleanLabels);
+
+  
+  fprintf(stderr,"On to Update Progress %d\n",this->MRFIterations);
+  this->UpdateProgress(float(0.2)/float(this->MRFIterations+1));
+
+  // EM Iterations (or ME) 
+  // ---------------------
+  fprintf(stderr,"On to Optimization %.2f\n",this->ImageNoiseSigma);
+  this->Optimization(cleanLabels,cleanInput,fittedImage,fitQuality,this->BiasField,this->ImageNoiseSigma);
+
+
+  // Generate Proper Label Output
+  // ----------------------------
+  this->GenerateLabelOutputs(cleanLabels,output);
+
+  if (this->FitQualityMap==NULL)
+    this->SetFitQualityMap(fitQuality);
+
+  cleanInput->Delete();
+  cleanLabels->Delete();
+  singleChannel->Delete();
+  fittedImage->Delete();
+  fitQuality->Delete();
+
+  this->UpdateProgress(1.0);
+}
+
+
+
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxMRFSegmentation.h b/bioimagesuite30_src/Segmentation/vtkpxMRFSegmentation.h
new file mode 100644
index 0000000..bfe24dd
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxMRFSegmentation.h
@@ -0,0 +1,351 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxMRFSegmentation.h,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxMRFSegmentation -- compute segmentation betwenn images using a simplified mono-exponential model
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+
+#ifndef __vtkpxMRFSegmentation_h
+#define __vtkpxMRFSegmentation_h
+
+#include "vtkpxHistogramSegmentation.h"
+#include "vtkImageData.h"
+#include "vtkFloatArray.h"
+#include "vtkAbstractTransform.h"
+#include "vtkpxImageTensorSpline.h"
+//BTX
+class vtkpxMRFSegmentationOptimizationStructure {
+
+public:
+  vtkDataArray* image_data;
+  vtkDataArray* labels;
+  vtkDataArray* biasfield;
+  vtkFloatArray* params;
+  int   voxel_index;
+  int   incr[6];
+  float wgth[6];
+  float smoothness;
+  float noisesigma;
+  float currentfraction;
+  int   currentclass[2];
+  int   numberofcomponentclasses;
+  int   debug;
+
+  void SetBaseValues(vtkDataArray* image_data0,
+		     vtkDataArray* labels0,
+		     vtkDataArray* biasfield0,
+		     vtkFloatArray* params0,
+		     int* incr0,
+		     float* wght0,
+		     float smoothness0,
+		     float noisesigma0)
+  {
+    this->image_data=image_data0;
+    this->labels=labels0;
+    this->params=params0;
+    this->biasfield=biasfield0;
+    for (int i=0;i<=5;i++)
+      {
+	this->incr[i]=incr0[i];
+	this->wgth[i]=wght0[i];
+      }
+    this->smoothness=smoothness0;
+    this->noisesigma=noisesigma0;
+
+  }
+  
+  void SetIndex(int voxel_index0,int debug0=0)
+  {
+    this->voxel_index=voxel_index0;
+    this->debug=debug0;
+  }
+  
+
+
+};
+//ETX
+
+class vtkpxMRFSegmentation : public vtkpxHistogramSegmentation
+{
+public:
+  static vtkpxMRFSegmentation *New();
+  vtkTypeMacro(vtkpxMRFSegmentation,vtkpxHistogramSegmentation);
+
+  // Description:
+  // Single Channel i.e. force Single Channel Mode
+  vtkGetMacro(SingleChannel,int);
+  vtkSetClampMacro(SingleChannel,int,0,1);
+  vtkBooleanMacro(SingleChannel,int);
+
+  // Description:
+  // Compute Bias Field
+  vtkGetMacro(ComputeBiasField,int);
+  vtkSetClampMacro(ComputeBiasField,int,0,1);
+  vtkBooleanMacro(ComputeBiasField,int);
+
+
+  // Description:
+  // Number Of Iterations
+  vtkGetMacro(MRFIterations,int);
+  vtkSetClampMacro(MRFIterations,int,0,20);
+
+  // Description:
+  // Weight of MRF
+  vtkGetMacro(Smoothness,float);
+  vtkSetClampMacro(Smoothness,float,0,100.0);
+
+
+  // Description:
+  // Weight of MRF
+  vtkGetMacro(BiasFieldFactor,float);
+  vtkSetClampMacro(BiasFieldFactor,float,-20.0,20.0);
+
+  // Description:
+  // Weight of MRF
+  vtkGetMacro(MRFThreshold,float);
+  vtkSetClampMacro(MRFThreshold,float,0,100.0);
+
+  // Description:
+  // Weight of MRF
+  vtkGetMacro(ImageNoiseSigma,float);
+  vtkSetClampMacro(ImageNoiseSigma,float,0,10000.0);
+
+  // Description:
+  // Partial Step
+  vtkGetMacro(PartialStep,float);
+  vtkSetClampMacro(PartialStep,float,0.05,0.5);
+
+  // Description:
+  // Do Histogram Normalization 0.01:0.99
+  vtkSetClampMacro(HistogramNormalization,int,0,1);
+  vtkGetMacro(HistogramNormalization,int);
+
+  // Description:
+  // Max Percentage of Voxels changing needed for iteration to converge (0 == all voxels)
+  vtkGetMacro(MRFConvergencePercentage,float);
+  vtkSetClampMacro(MRFConvergencePercentage,float,0,0.1);
+
+  // Description:
+  // Debug Voxel
+  vtkGetMacro(DebugVoxel,int);
+  vtkSetMacro(DebugVoxel,int);
+
+  // Description:
+  // Fuzzy Classification
+  vtkSetClampMacro(FuzzyClassification,int,0,1);
+  vtkGetMacro(FuzzyClassification,int);
+
+  // Description:
+  // MultiFrameOutput
+  vtkGetObjectMacro(MultiFrameOutput,vtkImageData);
+
+  // Description:
+  // BiasField
+  vtkGetObjectMacro(BiasField,vtkImageData);
+
+  // Description:
+  // BiasFieldWeights
+  vtkGetObjectMacro(BiasFieldWeights,vtkImageData);
+
+  // Description:
+  // Fit Quality Map
+  vtkSetObjectMacro(FitQualityMap,vtkImageData);
+  vtkGetObjectMacro(FitQualityMap,vtkImageData);
+  
+
+
+  
+protected:
+
+  vtkpxMRFSegmentation();
+  virtual ~vtkpxMRFSegmentation();
+  vtkpxMRFSegmentation(const vtkpxMRFSegmentation&) {};
+  void operator=(const vtkpxMRFSegmentation&) {};
+
+  virtual void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData* in,vtkImageData* out);
+
+
+  // Description:
+  // Master Optimization
+  // ----------------------------------------------------------------------------------------------------------
+  virtual void FuzzyClassificationOptimization(vtkImageData* cleanLabels,vtkImageData* cleanInput,
+					       vtkImageData* fittedImage,vtkImageData* fitQuality,
+					       vtkImageData* biasField,float noise_sigma);
+
+  virtual void Optimization(vtkImageData* cleanLabels,vtkImageData* cleanInput,vtkImageData* fitted_image,
+			    vtkImageData* fit_quality,vtkImageData* biasField,
+			    float noise_sigma);
+			      
+
+  // Initialization and Final Cleaning Stuff
+  // ----------------------------------------------------------------------------------------------------------
+  virtual int CheckInitialParameters(vtkImageData* input);
+  virtual vtkImageData* CreateInitialLabels(vtkImageData* output);
+  virtual vtkImageData* CreateSingleChannel(vtkImageData* input);
+
+  virtual void GenerateInitialCleanLabelImageFromFirstFrame(vtkImageData* tmpLabels,vtkImageData* cleanLabels);
+  virtual void GenerateLabelOutputs(vtkImageData* cleanLabels,vtkImageData* output);
+  virtual void InitializeSegmentation(vtkImageData* single_channel,vtkImageData* fitted_image,vtkImageData* fit_quality,vtkImageData* cleanLabels);
+
+  virtual void GenerateFittedParametersAndCleanInput(vtkImageData* input,vtkImageData* cleanInput,vtkImageData* fitted_image,vtkImageData* fit_quality);
+
+
+  // M-Step Is Easy for the most_part
+  // Compute Parameter Estimates Given Classication and r2,density estimates
+  // -----------------------------------------------------------------------
+  virtual void UpdateFitQualityMapFromMRF(vtkImageData* label_image,vtkImageData* fit_quality,float threshold=1.0);
+  virtual void ComputeClassSums(vtkImageData* label_image,
+				vtkImageData* fitted_image,
+				vtkImageData* fit_quality,
+				vtkImageData* bias_field,
+				float partial_threshold,
+				vtkFloatArray* params,int numclasses);
+  virtual int FitModelToSums(vtkFloatArray* params,int numclasses);
+  virtual float GetChannelEchoTime(int i) { return float(i+1);}
+  virtual void ComputeClassMeansAndStandardDeviations(vtkFloatArray* params,int numclasses,int domeans=1,int doprint=1);
+  virtual void DoExpectationStep(vtkImageData* label_image,
+				 vtkImageData* intensity_image,
+				 vtkImageData* fit_quality,
+				 vtkImageData* bias_field,
+				 float partial_threshold,
+				 vtkFloatArray* params,int numclasses);
+
+  
+  // E-Step
+  // -----------------------------------
+  // Description:
+  // Compute Invididual Probability Functions
+  virtual void CombineMeansAndStandardDeviations(vtkFloatArray* params,int class1,int class2,float fraction1,float* theta,int debug=0);
+  virtual double ComputeLogLikelihoodProbability(vtkDataArray* image_data,int vox,float* theta,float noise_sigma,float bfield,float& newbfield,int debug=0);
+  virtual double ComputeMRFPrior(vtkDataArray* labels,int vox,float currentlab[20],int incr[6],float wgth[6],int debug=0);
+  virtual double ComputeTotalMinusLogProbability(vtkDataArray* image_data,
+						 vtkDataArray* labels,
+						 int voxel_index,
+						 float *currentlab,
+						 float* theta,
+						 float noise_sigma,
+						 float bfield,
+						 int incr[6],float wgth[6],float smoothness,int debug=0);
+
+  virtual double ComputeTotalMinusLogProbabilityOutlier(vtkDataArray* labels,
+						       int voxel_index,
+						       float *currentlab,
+						       float* theta,
+						       int incr[6],float wgth[6],float smoothness,int debug=0);
+  
+  // Description:
+  // Optimize For Each Voxel
+  virtual float DoVoxelFit(int voxel_index);
+  virtual int   DoHardClassification(int voxel_index,int actual_num_classes,float prob[20],float& bestprob,
+				     float new_labels[20]);
+  virtual int   DoFuzzyClassification(int voxel_index,int actual_num_classes,float prob[20],float& bestprob,
+				      float new_labels[20]);
+  
+  // M-Step
+  // -----------------------------------------
+  virtual int  UpdateVoxel(int eveni,int evenj,int evenk,int pass);
+  virtual int  ComputeMRFIncrementsAndWeights(vtkImageData* img,int incr[6],float wgt[6]);
+  virtual int  DebugPrint(int vox);
+  virtual float DoMaximizationStep(vtkImageData* label_image,vtkImageData* intensity_image,vtkImageData* biasfield,
+				   float noise_sigma,
+				   vtkFloatArray* params,int numclasses,
+				   float smoothness,int maxiter);
+
+
+  // Bias Field Stuff
+  // ------------------------------------------
+  virtual void   ComputeInitialBiasField(vtkImageData* image_data,vtkImageData* clean_labels,vtkImageData* fit_quality,
+					 vtkImageData* bias_field_image,vtkImageData* weight_image,
+					 vtkFloatArray* params);
+  virtual void   TensorFitBiasFieldImage(vtkImageData* bias_field,vtkImageData* weight_image);
+  virtual void   ComputeSmoothBiasField(vtkImageData* bias_field,vtkImageData* fit_quality,float Sigma);
+
+
+
+  
+  float       Smoothness;
+  float       PartialStep;
+  float       MRFConvergencePercentage;
+  float       ImageNoiseSigma;
+  float       MRFThreshold;
+  int         MRFIterations;
+  int         FuzzyClassification;
+  int         DebugVoxel;
+  int         HistogramNormalization;
+  int         NumberOfChannels; 
+  int         SingleChannel;
+  int         MRFBasedFitQuality;
+  float       BiasFieldFactor;
+  float       BiasFieldSigma;
+  int         ComputeBiasField;
+  int         PerformingFuzzyClassification;
+
+  //BTX
+  vtkpxMRFSegmentationOptimizationStructure OptimizationStructure;
+  vtkImageData* MultiFrameOutput;
+  vtkImageData*  FitQualityMap;
+  vtkImageData*  BiasField;
+  vtkImageData*  BiasFieldWeights;
+  vtkpxImageTensorSpline* TensorSpline;
+  //ETX
+
+  static int ChannelMean(int ch) { return ch*2+1; }
+  static int ChannelSigma(int ch) { return ch*2+2; }
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxPolynomialBiasFieldCorrection.cpp b/bioimagesuite30_src/Segmentation/vtkpxPolynomialBiasFieldCorrection.cpp
new file mode 100644
index 0000000..3359636
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxPolynomialBiasFieldCorrection.cpp
@@ -0,0 +1,855 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxPolynomialBiasFieldCorrection.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/12/13 19:46:32 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxPolynomialBiasFieldCorrection.h"
+#include "vtkObjectFactory.h"
+#include "pxutil.h"
+#include "vtkpxUtil.h"
+#include "vtkbisImageReslice.h"
+#include "vtkpxOptimizer.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+#include "vtkImageThreshold.h"
+#include "vtkImageSeedConnectivity.h"
+#include "vtkpxMath.h"
+#include "vtkpxImageExtractVOI.h"
+#include "vtkDoubleArray.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageMedian3D.h"
+#include "vtkImageMathematics.h"
+#include "pxisinf.h"
+
+
+vtkpxPolynomialBiasFieldCorrection* vtkpxPolynomialBiasFieldCorrection::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxPolynomialBiasFieldCorrection");
+  if(ret)
+    {
+    return (vtkpxPolynomialBiasFieldCorrection*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxPolynomialBiasFieldCorrection;
+  
+}
+
+
+vtkpxPolynomialBiasFieldCorrection::vtkpxPolynomialBiasFieldCorrection()
+{
+  this->FixedNumberOfSlices=0;
+  this->NumberOfIterations=10;
+  this->Coefficients=vtkDoubleArray::New();
+  this->Epsilon=0.003;
+  this->RecomputeParameters=0;
+  this->Degree=2;
+  this->Metric=0;
+  this->InitialCoefficients=NULL;
+  this->OptimizationMethod=0;
+  this->MinValue=0.5;
+  this->MaxValue=2.5;
+  strcpy(this->OutputStatus,"");
+  this->TempBiasField=NULL;
+  this->TempFixedImage=NULL;
+}
+
+vtkpxPolynomialBiasFieldCorrection::~vtkpxPolynomialBiasFieldCorrection() 
+{
+  if (this->Coefficients!=NULL)
+    this->Coefficients->Delete();
+
+  this->SetInitialCoefficients(NULL);
+
+  if (this->TempBiasField!=NULL)
+    this->TempBiasField->Delete();
+
+  if (this->TempFixedImage!=NULL)
+    this->TempFixedImage->Delete();
+}
+
+//-------------------------------------------------------------------------
+int vtkpxPolynomialBiasFieldCorrection::InitializeAll() 
+{
+  strcpy(this->OutputStatus,"Initializing");
+  if (this->StepSize>0.5)
+    this->StepSize=0.5;
+  this->InternalStepSize=Frange(this->StepSize,0.01,0.5);
+
+  vtkpxAbstractBiasFieldCorrection::InitializeAll();
+  switch (this->Degree)
+    {
+    case 3:
+      this->Coefficients->SetNumberOfTuples(19);
+      break;
+    case 2:
+      this->Coefficients->SetNumberOfTuples(9);
+      break;
+    default:
+      this->Coefficients->SetNumberOfTuples(3);
+      break;
+    }
+
+
+  this->Coefficients->FillComponent(0,0.0);
+
+  if (this->InitialCoefficients!=NULL)
+    {
+      int nt=this->InitialCoefficients->GetNumberOfTuples();
+      if (nt>this->Coefficients->GetNumberOfTuples())
+	nt=this->Coefficients->GetNumberOfTuples();
+      
+      for (int i=0;i<nt;i++)
+	this->Coefficients->SetComponent(i,0,this->InitialCoefficients->GetComponent(i,0));
+    }
+
+
+  return 1;
+}
+//-------------------------------------------------------------------------
+int vtkpxPolynomialBiasFieldCorrection::FinalizeAll()
+{
+  this->Evaluate();
+  this->GenerateOutput(-1,-1,-1,-1,this->LastSimilarity);
+  return 1;
+}
+//-------------------------------------------------------------------------
+// Compute Registration
+int vtkpxPolynomialBiasFieldCorrection::ComputeBiasFit(int level)
+{  
+  
+  double step=this->CurrentStepSize;
+
+  vtkDoubleArray* grad=vtkDoubleArray::New();
+  grad->SetNumberOfComponents(1);
+  grad->SetNumberOfTuples(this->Coefficients->GetNumberOfTuples());
+
+  for (int st=1;st<=this->NumberOfSteps;st++)
+    {
+      double old_similarity = this->Evaluate();
+      double new_similarity=this->Optimize(grad,old_similarity,step,level,st);
+      this->GenerateOutput(level,st,this->NumberOfIterations,step,new_similarity);
+      step*=0.5;
+    }
+
+  grad->Delete();
+  return 1;
+}
+//-------------------------------------------------------------------------
+
+double vtkpxPolynomialBiasFieldCorrection::Optimize(vtkDoubleArray* grad,double old_similarity,
+						    double step,int level,int numstep)
+
+{
+  OptimizationStructure.SetValues(old_similarity,step,level);
+     
+  vtkpxOptimizer* optimizer=vtkpxOptimizer::New();
+  vtkDoubleArray* position=vtkDoubleArray::New();
+  vtkDoubleArray* temp=vtkDoubleArray::New();
+
+  this->GetCurrentParameters(position);
+  optimizer->SetMasterObject(this);
+  optimizer->SetTempArray(grad);
+  optimizer->SetEvaluateFunctionMethod(&vtkpxPolynomialBiasFieldCorrection::CalculateFunction);
+  optimizer->SetEvaluateGradientMethod(&vtkpxPolynomialBiasFieldCorrection::CalculateGradient);
+  optimizer->SetBeginIterationMethod(&vtkpxAbstractBiasFieldCorrection::OnBeginIteration);
+  optimizer->SetFeedbackMethod(&vtkpxPolynomialBiasFieldCorrection::OptimizerFeedback);
+  
+  double v1=this->Evaluate();
+  double tol=this->Epsilon*0.01*fabs(v1);
+  
+  int olddegree=this->Degree;
+  /*  this->Degree=1;
+  if (level==1 && st==this->NumberOfSteps)
+  this->Degree=olddegree;*/
+
+  double v;
+
+  switch (this->OptimizationMethod)
+    {
+    case 2:
+      v=optimizer->ComputePowell(position,temp,this->NumberOfIterations,tol);
+      break;
+      
+    case 3:
+      v=optimizer->ComputeGradientDescent(position,this->NumberOfIterations,tol);
+      break;
+
+    case 4:
+      v=optimizer->ComputeConjugateGradient(position,this->NumberOfIterations,tol);
+      break;
+
+    default:
+      v=optimizer->ComputeConjugateGradient(position,this->NumberOfIterations,tol);
+    }
+
+
+  optimizer->Delete();
+  position->Delete();
+  temp->Delete();
+  return v;
+}
+
+
+//-------------------------------------------------------------------------
+double vtkpxPolynomialBiasFieldCorrection::ComputePolynomialValue(double x,double x2,double x3,
+								  double y,double y2,double y3,
+								  double z,double z2,double z3,
+								  vtkDoubleArray* coefficients,int degree)
+{
+  double value= 
+    coefficients->GetComponent(0,0)*x+
+    coefficients->GetComponent(1,0)*y+
+    coefficients->GetComponent(2,0)*z;
+
+  if (degree==1)
+    return value;
+
+  value+= 
+    0.5*coefficients->GetComponent(3,0)*(3*x2-1.0)+
+    0.5*coefficients->GetComponent(4,0)*(3*y2-1.0)+
+    0.5*coefficients->GetComponent(5,0)*(3*z2-1.0)+
+    coefficients->GetComponent(6,0)*x*y+
+    coefficients->GetComponent(7,0)*x*z+
+    coefficients->GetComponent(8,0)*y*z;
+  
+  if (degree==2)
+    return value;
+
+  value+=
+    0.5*(
+	 coefficients->GetComponent( 9,0)*(5.0*x3-3.0*x)+
+	 coefficients->GetComponent(10,0)*(5.0*y3-3.0*y)+
+	 coefficients->GetComponent(11,0)*(5.0*z3-3.0*z)+
+	 coefficients->GetComponent(12,0)*(3*x2-1.0)*y+
+	 coefficients->GetComponent(13,0)*(3*x2-1.0)*z+
+	 coefficients->GetComponent(14,0)*(3*y2-1.0)*x+
+	 coefficients->GetComponent(15,0)*(3*y2-1.0)*z+
+	 coefficients->GetComponent(16,0)*(3*z2-1.0)*x+
+	 coefficients->GetComponent(17,0)*(3*z2-1.0)*y
+	 )+
+    coefficients->GetComponent(18,0)*x*y*z;
+
+  return value;
+
+}
+//-------------------------------------------------------------------------
+double vtkpxPolynomialBiasFieldCorrection::ComputePolynomialValue(double x,double x2,double x3,
+								  double y,double y2,double y3,
+								  double z,double z2,double z3,
+								  double* coefficients,int degree)
+{
+  double value= 
+    coefficients[0]*x+
+    coefficients[1]*y+
+    coefficients[2]*z;
+
+  if (degree==1)
+    return value;
+
+  value+= 
+    0.5*coefficients[3]*(3*x2-1.0)+
+    0.5*coefficients[4]*(3*y2-1.0)+
+    0.5*coefficients[5]*(3*z2-1.0)+
+    coefficients[6]*x*y+
+    coefficients[7]*x*z+
+    coefficients[8]*y*z;
+  
+  if (degree==2)
+    return value;
+
+  value+=
+    0.5*(
+	 coefficients[ 9]*(5.0*x3-3.0*x)+
+	 coefficients[10]*(5.0*y3-3.0*y)+
+	 coefficients[11]*(5.0*z3-3.0*z)+
+	 coefficients[12]*(3*x2-1.0)*y+
+	 coefficients[13]*(3*x2-1.0)*z+
+	 coefficients[14]*(3*y2-1.0)*x+
+	 coefficients[15]*(3*y2-1.0)*z+
+	 coefficients[16]*(3*z2-1.0)*x+
+	 coefficients[17]*(3*z2-1.0)*y
+	 )+
+    coefficients[18]*x*y*z;
+
+  return value;
+
+}
+
+//-------------------------------------------------------------------------
+
+vtkImageData* vtkpxPolynomialBiasFieldCorrection::ComputeBiasFieldImage(vtkImageData* ref,vtkDoubleArray* tr,int degree,double minvalue,double maxvalue)
+{
+  if (ref==NULL || tr==NULL)
+    return NULL;
+
+ if (tr->GetNumberOfTuples()<3)
+	return NULL;
+
+  vtkImageData* bfield=vtkImageData::New();
+  bfield->CopyStructure(ref);
+  bfield->SetNumberOfScalarComponents(1);
+  bfield->SetScalarTypeToFloat();
+  bfield->AllocateScalars();
+
+  int ok=vtkpxPolynomialBiasFieldCorrection::ComputeBiasFieldImage(ref,bfield,tr,degree,minvalue,maxvalue);
+  //  fprintf(stderr,"ok=%d\n",ok);
+  return bfield;
+}
+
+
+// --------------------------------------------------------------------------------------------------------------------------------------------
+
+int vtkpxPolynomialBiasFieldCorrection::ComputeBiasFieldImage(vtkImageData* ref,vtkImageData* bfield,vtkDoubleArray* tr,int degree,double minvalue,double maxvalue)
+{
+  double ori[3],spa[3];
+  int    dim[3];
+
+  ref->GetSpacing(spa);
+  ref->GetOrigin(ori);
+  ref->GetDimensions(dim);
+
+  if (bfield==NULL)
+    {
+      fprintf(stderr, " ************************** Big Problem No Bias Field ***************************\n");
+      return 0;
+    }
+
+  int nt1=ref->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int nt2=bfield->GetPointData()->GetScalars()->GetNumberOfTuples();
+
+  if (nt1!=nt2)
+    {
+      fprintf(stderr, " ************************** Allocating Bias Field ***************************\n");
+      bfield->CopyStructure(ref);
+      bfield->SetNumberOfScalarComponents(1);
+      bfield->SetScalarTypeToFloat();
+      bfield->AllocateScalars();
+    }
+  //  else
+    //      fprintf(stderr,"nt1=nt2=%d\n",nt1);
+
+  if (degree==-1)
+    {
+      if (tr->GetNumberOfTuples()==9)
+	degree=2;
+      else if (tr->GetNumberOfTuples()==19)
+	degree=3;
+      else
+	degree=1;
+    }
+  else
+    {
+      if (degree==3 && tr->GetNumberOfTuples()<19)
+	degree=2;
+
+      if (degree ==2 && tr->GetNumberOfTuples()<9)
+	degree=1;
+    }
+
+  double center[3],radius[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      radius[ia]=0.5*double(dim[ia])*spa[ia];
+      center[ia]=radius[ia];
+      if (radius[ia]<0.001)
+	radius[ia]=1.0;
+    }
+
+  vtkDataArray* bfield_dat=bfield->GetPointData()->GetScalars();
+  int index=0;
+
+  //  fprintf(stderr,"This far nt=%d vs %d x %d x %d\n",bfield_dat->GetNumberOfTuples(),dim[0],dim[1],dim[2]);
+
+  double *coeff = (double*) tr->GetVoidPointer(0);
+  int count=0;
+  for (int k=0;k<dim[2];k++)
+    {
+      double z=(double(k)*spa[2]-center[2])/radius[2];
+      double z2=z*z;
+      double z3=z2*z;
+      for (int j=0;j<dim[1];j++)
+	{
+	  double y=(double(j)*spa[1]-center[1])/radius[1];
+	  double y2=y*y;
+	  double y3=y2*y;
+
+	  for (int i=0;i<dim[0];i++)
+	    {
+	      double x=(double(i)*spa[0]-center[0])/radius[0];
+	      double x2=x*x;
+	      double x3=x2*x;
+	      
+	      double s=vtkpxPolynomialBiasFieldCorrection::ComputePolynomialValue(x,x2,x3,y,y2,y3,z,z2,z3,coeff,degree)+1.0;
+	      if (s<minvalue)
+		s=minvalue;
+	      else if (s>maxvalue)
+		s=maxvalue;
+	      bfield_dat->SetComponent(index,0,s);
+	      ++index;
+	    }
+	}
+      ++count;
+      if (count==20)
+	{
+	  //	  fprintf(stderr,"Done with slice %d\n",k);
+	  count=0;
+	}
+    }
+	
+  //  fprintf(stderr,"Done\n");
+  
+  return 1;
+
+}
+//-------------------------------------------------------------------------
+double vtkpxPolynomialBiasFieldCorrection::ComputeErrorFunction(vtkImageData* image,vtkImageData* weights,
+								vtkDoubleArray* coefficients,vtkFloatArray* params)
+{
+  if (this->TempBiasField==NULL)
+    {
+      this->TempBiasField=vtkImageData::New();
+      this->TempBiasField->CopyStructure(image);
+      this->TempBiasField->SetNumberOfScalarComponents(1);
+      this->TempBiasField->AllocateScalars();
+    }
+
+  if (this->TempFixedImage==NULL)
+    {
+      this->TempFixedImage=vtkImageData::New();
+      this->TempFixedImage->CopyStructure(image);
+      this->TempFixedImage->SetNumberOfScalarComponents(image->GetNumberOfScalarComponents());
+      this->TempFixedImage->AllocateScalars();
+    }
+
+
+  this->ComputeBiasFieldImage(image,this->TempBiasField,coefficients,this->Degree,this->MinValue,this->MaxValue);
+  vtkpxAbstractBiasFieldCorrection::ComputeCorrectedImage(image,this->TempBiasField,this->TempFixedImage,1);
+
+
+
+  double metric=0;
+  vtkDataArray* wg=NULL;
+  if (weights!=NULL)
+    wg=weights->GetPointData()->GetScalars();
+
+  if (this->Metric==0)
+    {
+      vtkDataArray* img=this->TempFixedImage->GetPointData()->GetScalars();
+      int nt=img->GetNumberOfTuples();
+      int nc=params->GetNumberOfTuples();
+      
+      double sum=0.0,nsum=0.0001;
+      double scale_in=vtkpxAbstractBiasFieldCorrection::ComputeScaleFactor(image,this->TempBiasField);
+
+      for (int i=0;i<nt;i++)
+	{
+	  double v=img->GetComponent(i,0)/scale_in;
+	  double p=1.0;
+
+	  for (int c=0;c<nc;c++)
+	    {
+	      double q=Valley(v-params->GetComponent(c,1),params->GetComponent(c,2));
+	      if (!isnan(q))
+		p=p*q;
+	    }
+	  
+	  if (wg!=NULL)
+	    {
+	      sum+=wg->GetComponent(i,0)*p;
+	      nsum+=wg->GetComponent(i,0);
+	    }
+	  else
+	    {
+	      sum+=p;
+	      nsum+=1.0;
+	    }
+	}
+      metric=sum/nsum;
+    }
+  else if (this->Metric==1)
+    {
+      double range[2]; this->TempFixedImage->GetPointData()->GetScalars()->GetRange(range);
+      double lower=range[0];
+      double upper=range[1];
+
+      vtkpxImageRobustHistogram* hist=vtkpxImageRobustHistogram::New();
+      hist->InterpolationOff();
+      hist->DebugOff();
+      hist->SetNumberOfBins(1024);
+      hist->RobustModeOff();
+      if (weights!=NULL)
+	hist->SetWeightImage(weights);
+      hist->SetInput(this->TempFixedImage);
+      hist->Update();
+      metric=-hist->ComputeEntropy();
+      hist->Delete();
+    }
+  else if (this->Metric==2)
+    {
+      vtkImageMedian3D* smooth=vtkImageMedian3D::New();
+      smooth->SetInput(this->TempFixedImage);
+      smooth->SetKernelSize(3,3,3);
+      smooth->Update();
+
+
+      vtkImageMathematics* math=vtkImageMathematics::New();
+      math->AddInput(smooth->GetOutput());
+      math->AddInput(this->TempFixedImage);
+      math->SetOperationToSubtract();
+      math->Update();
+
+      vtkDataArray* img=math->GetOutput()->GetPointData()->GetScalars();
+      int nt=img->GetNumberOfTuples();
+      int nc=img->GetNumberOfComponents();
+      double range[2]; img->GetRange(range);
+
+      double sum=0.0,sum2=0.0,nsum=0.0001;
+      for (int i=0;i<nt;i++)
+	{
+	  double w=1.0;
+	  if (wg!=NULL)
+	    w=wg->GetComponent(i,0);
+
+	  for (int j=0;j<nc;j++)
+	    {
+	      double p=fabs(img->GetComponent(i,j));
+	      sum+=p*w;
+	      nsum+=w;
+	    }
+	}
+      metric=-sum/nsum;
+      math->Delete();
+      smooth->Delete();
+    }
+  return metric;
+
+}
+//-------------------------------------------------------------------------
+float vtkpxPolynomialBiasFieldCorrection::ComputeEntropy(vtkImageData* img)
+{
+  double range[2]; img->GetPointData()->GetScalars()->GetRange(range);
+  double lower=range[0];//0.99*range[0]+0.01*range[1];
+  double upper=range[1];//0.01*range[0]+0.99*range[1];
+
+  vtkpxImageRobustHistogram* hist=vtkpxImageRobustHistogram::New();
+  hist->SetInput(img);
+  hist->SaturationModeOff();
+  hist->InterpolationOn();
+  hist->RobustModeOff();
+  hist->SetNumberOfBins(512);
+  hist->Update();
+  double metric=hist->ComputeEntropy();
+  hist->Delete();
+  return metric;
+}
+
+//-------------------------------------------------------------------------
+double vtkpxPolynomialBiasFieldCorrection::Evaluate()
+{
+  this->LastSimilarity=this->ComputeErrorFunction(this->SampledReferenceImage,this->SampledWeightImage,
+						  this->Coefficients,this->ClassParameters);
+  return (this->LastSimilarity);
+}
+//-------------------------------------------------------------------------
+void vtkpxPolynomialBiasFieldCorrection::GenerateOutput(int level, int step,int iter,double stepsize,double actualSimilarity)
+{
+  if (iter>=100)
+    iter=99;
+
+  sprintf(this->OutputStatus,"Level=%2d Step=%2d iter=%2d stepsize=%.3f:\t",
+	  level,step,iter,stepsize);
+
+  for (int i=0;i<this->Coefficients->GetNumberOfTuples();i++)
+    sprintf(this->OutputStatus,"%s %.5f ", this->OutputStatus,this->Coefficients->GetComponent(i,0));
+
+  sprintf(this->OutputStatus,"%s \t sim=%8.6f",this->OutputStatus, actualSimilarity);
+  //  this->UpdateProgress(this->LastProgress);
+  
+  double sc=1.0/double(this->NumberOfLevels);
+  double pog=(double(step)/double(this->NumberOfSteps+1) + double(this->NumberOfLevels-level))*sc;
+  this->LastProgress=pog;
+  //  this->UpdateProgress(pog);
+  //  fprintf(stderr,"%s\n",this->OutputStatus);
+  return;
+}
+
+//-------------------------------------------------------------------------
+// Optimizer Stuff 
+//-------------------------------------------------------------------------
+double vtkpxPolynomialBiasFieldCorrection::OnBeginIteration(vtkDoubleArray* params)
+{
+  if (this->Metric==0 && this->RecomputeParameters==1)
+    {
+      sprintf(this->OutputStatus,"On Begin Iteration ... Computing Parameters ...\n");
+      this->UpdateProgress(this->LastProgress);
+      
+      vtkImageData* bfield=this->ComputeBiasFieldImage(this->SampledReferenceImage,this->Coefficients);
+      vtkImageData* tmp=ComputeCorrectedImage(this->SampledReferenceImage,bfield,1);
+      this->ComputeAndSetClassParameters(tmp,this->ClassParameters);
+      tmp->Delete();
+      bfield->Delete();
+      
+      
+      this->LastProgress+=0.001;
+      sprintf(this->OutputStatus,"On Begin Iteration ... Computing Parameters Done\n");
+      this->UpdateProgress(this->LastProgress);
+    }
+  return 0.0;
+}
+// -----------------------------------------------------------------------------------------------
+void vtkpxPolynomialBiasFieldCorrection::SetCurrentParameters(vtkDoubleArray* param)
+{
+  int numt=this->Coefficients->GetNumberOfTuples();
+  int num=param->GetNumberOfTuples();
+
+  if (num!=numt)
+    {
+      vtkErrorMacro(<<"Bad Data for Optimization");
+      fprintf(stderr,"Bad Data for Optimization\n");
+      return;
+    }
+
+  for (int i=0;i<numt;i++)
+    {
+      double v=param->GetComponent(i,0);
+      if (v<-2.0)
+	v=2.0;
+      else if (v>2.0)
+	v=2.0;
+      this->Coefficients->SetComponent(i,0,v);
+    }
+}
+//-------------------------------------------------------------------------
+void vtkpxPolynomialBiasFieldCorrection::GetCurrentParameters(vtkDoubleArray* param)
+{
+  param->DeepCopy(this->Coefficients);
+}
+//-------------------------------------------------------------------------
+double vtkpxPolynomialBiasFieldCorrection::OptimizerValue(vtkDoubleArray* params)
+{
+  this->SetCurrentParameters(params);
+  return -this->Evaluate();
+}
+//-------------------------------------------------------------------------
+double vtkpxPolynomialBiasFieldCorrection::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+
+{
+  if (grad->GetNumberOfComponents()!=1 || grad->GetNumberOfTuples()!=this->Coefficients->GetNumberOfTuples())
+    {
+      grad->SetNumberOfComponents(1);
+      grad->SetNumberOfTuples(this->Coefficients->GetNumberOfTuples());
+    }
+
+  OptimizationStructure.old_similarity=this->OptimizerValue(params);
+  this->GenerateOutput(OptimizationStructure.level,-1,-1,OptimizationStructure.step,OptimizationStructure.old_similarity);
+
+  // Calculate gradient 
+  double GradientNorm = 0;
+
+  grad->FillComponent(0,0.0);
+
+  
+  this->GenerateOutput(OptimizationStructure.level,
+		       -1,-1,OptimizationStructure.step,
+		       OptimizationStructure.old_similarity);
+  fprintf(stderr,"\n\n%s\nOptimizer Computing Gradients : (%5.3f,%d) ... ",
+	  OutputStatus,OptimizationStructure.step,
+	  this->Coefficients->GetNumberOfTuples());
+
+
+  int nt=this->Coefficients->GetNumberOfTuples();
+  for (int i = 0; i < nt ; i++)
+    {
+      double p=this->Coefficients->GetComponent(i,0);
+
+      this->Coefficients->SetComponent(i,0,p-OptimizationStructure.step);
+      double s1 = this->Evaluate();
+
+      this->Coefficients->SetComponent(i,0,p+OptimizationStructure.step);
+      double s2 = this->Evaluate();
+
+      this->Coefficients->SetComponent(i,0,p);
+
+      // Minus sign for ascent 
+      grad->SetComponent(i,0,-(s2-s1));
+      GradientNorm+=pow(s2-s1,2.0);
+
+    }
+  GradientNorm = (sqrt(GradientNorm));
+  double sc=OptimizationStructure.step/GradientNorm;
+
+  // Normalize vector
+  if (GradientNorm > 0)
+    {
+      for (int t=0;t<nt;t++)
+	grad->SetComponent(t,0,grad->GetComponent(t,0) * sc);
+    }
+  else 
+    grad->FillComponent(0,0.0);
+
+  fprintf(stderr,"... Gradient Norm=%.5f scale=%f\n",GradientNorm,sc);
+  return GradientNorm;
+}
+//-------------------------------------------------------------------------
+int vtkpxPolynomialBiasFieldCorrection::CreateWeightImage(vtkImageData* ref) 
+{
+  if (this->WeightImage!=NULL)
+    this->WeightImage->Delete();
+
+  this->WeightImage=vtkImageData::New();
+  this->WeightImage->CopyStructure(ref);
+  this->WeightImage->SetScalarTypeToShort();
+  this->WeightImage->SetNumberOfScalarComponents(1);
+  this->WeightImage->AllocateScalars();
+
+  vtkDataArray* wgt=this->WeightImage->GetPointData()->GetScalars();
+  int nt=wgt->GetNumberOfTuples();
+
+  if (this->MaskImage==NULL)
+    {
+      wgt->FillComponent(0,1);
+    }
+  else
+    {
+      vtkDataArray* msk=this->MaskImage->GetPointData()->GetScalars();
+      double mrange[2]; msk->GetRange(mrange);
+      double thr=0.5*(mrange[0]+mrange[1]);
+      for (int i=0;i<nt;i++)
+	{
+	  float m=msk->GetComponent(i,0);
+	  if (m>thr)
+	    wgt->SetComponent(i,0,1.0);
+	  else
+	    wgt->SetComponent(i,0,0.0);
+	}
+    }
+  //  vtkpxUtil::SaveAnalyze("poly_weight",this->WeightImage,0);
+	return 1;
+}
+//-------------------------------------------------------------------------
+void vtkpxPolynomialBiasFieldCorrection::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Input to vtkpxPolynomialBiasFieldCorrection");
+      return;
+    }
+
+  this->CheckInputsAndCreateReferenceImage(input);
+
+  fprintf(stderr,"Beginning Degree=%d\n",this->Degree);
+
+
+
+  vtkDebugMacro(<<"Initializing All");
+  int ok=this->InitializeAll();
+
+  if (this->ClassParameters==NULL && this->Metric==0)
+    {
+      fprintf(stderr,"\n\t\tComputing Class Parameters from Original Image\n");
+      this->ComputeAndSetClassParameters(this->ReferenceImage);
+    } 
+  else
+    {
+      fprintf(stderr,"\n\t\tNot Computing Class Parameters from Original Image Metric=%d\n",this->Metric);
+    }
+
+  if (this->ClassParameters!=NULL)
+    {
+      int nc=this->ClassParameters->GetNumberOfTuples();
+      fprintf(stderr,"Initial Parameters : %d\n",nc);
+      for (int c=0;c<nc;c++)
+	fprintf(stderr,"Class %d \t Mean = %.1f , Sigma=%.1f\n",c,
+		this->ClassParameters->GetComponent(c,1),
+		this->ClassParameters->GetComponent(c,2));
+      fprintf(stderr,"\n");
+    }
+
+
+
+  fprintf(stderr," -------------------- Done Setting Parameters ------------- \n");
+
+  if (ok==0)
+    {
+      vtkErrorMacro(<<"Initialization Failed\n");
+      fprintf(stderr,"Initialization Failed\n");
+      return;
+    }
+
+
+  for (int level=this->NumberOfLevels;level>=1;level=level-1)
+    {
+      vtkDebugMacro(<<"Initializing Level="<<level);
+      this->Initialize(level);
+      vtkDebugMacro(<<"Compute Bias Fit Level="<<level);
+      this->ComputeBiasFit(level);
+      vtkDebugMacro(<<"Finalizing Level="<<level);
+    }
+  vtkDebugMacro(<<"Finalizing All");
+  this->FinalizeAll();
+
+  // Generate Output
+  if (this->BiasField=NULL)
+    this->BiasField->Delete();
+  
+  this->BiasField=vtkpxPolynomialBiasFieldCorrection::ComputeBiasFieldImage(input,this->Coefficients,this->Degree,this->MinValue,this->MaxValue);
+  vtkImageData* tmp=vtkpxAbstractBiasFieldCorrection::ComputeMeanPreservingCorrectedImage(input,this->BiasField);
+
+  output->ShallowCopy(tmp);
+  tmp->Delete();
+
+  fprintf(stderr,"Done Degree=%d\n",this->Degree);
+ 
+}
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxPolynomialBiasFieldCorrection.h b/bioimagesuite30_src/Segmentation/vtkpxPolynomialBiasFieldCorrection.h
new file mode 100644
index 0000000..bd278f6
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxPolynomialBiasFieldCorrection.h
@@ -0,0 +1,246 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxPolynomialBiasFieldCorrection.h,v $
+  Language:  C++
+  Date:      $Date: 2004/12/13 19:46:39 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxPolynomialBiasFieldCorrection - Filter for ffd registration based on voxel similarity measures.
+
+// .SECTION Description
+// This class implements a registration filter for the non-rigid registration
+// of images.
+
+
+#ifndef _VTKPXPolynomialBiasFieldCorrection_H
+#define _VTKPXPolynomialBiasFieldCorrection_H
+
+#include "vtkImageData.h"
+#include "vtkDoubleArray.h"
+#include "vtkDoubleArray.h"
+#include "vtkpxAbstractBiasFieldCorrection.h"
+#include "vtkImageData.h"
+#include "vtkpxImageRobustHistogram.h"
+//BTX
+class vtkpxPolynomialBiasFieldCorrectionOptimizationStructure {
+public:
+  double old_similarity;
+  double step;
+  int    level;
+
+  void SetValues(double old_similarity0,
+		 double step0,
+		 int level0)
+  {
+    this->old_similarity=old_similarity0;
+    this->step=step0;
+    this->level=level0;
+  }
+};
+//ETX
+
+
+class  vtkpxPolynomialBiasFieldCorrection : public vtkpxAbstractBiasFieldCorrection {
+
+public:
+  static vtkpxPolynomialBiasFieldCorrection* New();
+  vtkTypeMacro(vtkpxPolynomialBiasFieldCorrection,vtkpxAbstractBiasFieldCorrection);
+
+  // Description:
+  // Get Last Output Measures
+  vtkGetMacro(LastSimilarity,double);
+
+  // Run Optimization for Level level
+  virtual int ComputeBiasFit(int level);
+  
+  // Description:
+  // Get The Transformation
+  vtkGetObjectMacro(Coefficients,vtkDoubleArray);
+
+  // Description:
+  // Initial Parameters
+  vtkGetObjectMacro(InitialCoefficients,vtkDoubleArray);
+  vtkSetObjectMacro(InitialCoefficients,vtkDoubleArray);
+
+  // Description:
+  // RecomputeParameters
+  // 1 == update parameters & pabic
+  vtkSetClampMacro(RecomputeParameters,int,0,1);
+  vtkGetMacro(RecomputeParameters,int);
+
+  // Description:
+  // MinValue/MaxValue
+  // Minimum/Maximum Value of the Bias Field =0.2,5.0
+  vtkSetClampMacro(MinValue,double,0.1,0.8);
+  vtkGetMacro(MinValue,double);
+  vtkSetClampMacro(MaxValue,double,1.25,10.0);
+  vtkGetMacro(MaxValue,double);
+
+  // Description:
+  // Degre Linear or Quadratic
+  vtkSetClampMacro(Degree,int,1,3);
+  vtkGetMacro(Degree,int);
+
+  // Description:
+  // Create Bias Field Image
+  static vtkImageData* ComputeBiasFieldImage(vtkImageData* ref,vtkDoubleArray* tr,int degree=-1,double minvalue=0.5,double maxvalue=2.5);
+  static int ComputeBiasFieldImage(vtkImageData* ref,vtkImageData* bf,vtkDoubleArray* tr,int degree=1,double minvalue=0.5,double maxvalue=2.5);
+
+  // Description:
+  // Compute Entropy
+  static float ComputeEntropy(vtkImageData* tmp);
+
+  // Description:
+  // Optimization Method
+  vtkSetMacro(OptimizationMethod,int);
+  vtkGetMacro(OptimizationMethod,int);
+
+  // Description:
+  // Shorthand for different optimization methods 
+  virtual void SetOptimizationMethodToPowell() { this->SetOptimizationMethod(2); }
+  virtual void SetOptimizationMethodToGradientDescent() { this->SetOptimizationMethod(3); }
+  virtual void SetOptimizationMethodToConjugateGradient() { this->SetOptimizationMethod(4); }
+
+
+protected:
+
+  // Make all these protected 
+  // Constructor
+  vtkpxPolynomialBiasFieldCorrection();
+  virtual ~vtkpxPolynomialBiasFieldCorrection();
+  vtkpxPolynomialBiasFieldCorrection(const vtkpxPolynomialBiasFieldCorrection&) {};
+  void operator=(const vtkpxPolynomialBiasFieldCorrection&) {};
+
+  // Description:
+  // Execute Stuff 
+  virtual void SimpleExecute(vtkImageData* in,vtkImageData* out);
+
+  // Description:
+  // This controls the optimization method 0=default,1=Cong Gradient
+  vtkpxPolynomialBiasFieldCorrectionOptimizationStructure OptimizationStructure;
+
+  // Description:
+  // Actual Transformation
+  vtkDoubleArray*   Coefficients;
+  vtkDoubleArray*   InitialCoefficients;
+  vtkImageData*     TempBiasField;
+  vtkImageData*     TempFixedImage;
+  double            MinValue;
+  double            MaxValue;
+
+  // Description:
+  // Degree of Polynomial 1:3
+  int               Degree;
+
+  // Description:
+  // Mode See Set Mode above
+  int RecomputeParameters;
+
+  // Initial set up for the registration at all levels
+  virtual int InitializeAll();
+
+  // Description:
+  // Optimize for step size = step
+  virtual double Optimize(vtkDoubleArray* grad,double old_similarity,double step,int level,int numstep);
+
+
+  // Description:
+  // Evaluate the metric
+  virtual double Evaluate();
+
+  // Description:
+  // Create Weight Image based on partial voluming
+  virtual int CreateWeightImage(vtkImageData* ref);
+
+  // Description:
+  // Compute Error Function
+  virtual double ComputeErrorFunction(vtkImageData* image,vtkImageData* weights,vtkDoubleArray* coefficients,vtkFloatArray* params);
+
+  // Description:
+  // Final set up for the registration at a multiresolution level
+  virtual int FinalizeAll();
+
+
+  // Description:
+  // Compute Polynomial Value
+  static double ComputePolynomialValue(double x,double x2,double x3,
+				       double y,double y2,double y3,
+				       double z,double z2,double z3,
+				       vtkDoubleArray* coefficients,int degree);
+
+  static double ComputePolynomialValue(double x,double x2,double x3,
+				       double y,double y2,double y3,
+				       double z,double z2,double z3,
+				       double* coefficients,int degree);
+
+
+  // Description:
+  // Generate Output
+  virtual void GenerateOutput(int level, int step,int iter,double stepsize,double simil);
+
+
+  // Description:
+  // Needed for Optimizer
+  virtual void SetCurrentParameters(vtkDoubleArray* par);
+  virtual void GetCurrentParameters(vtkDoubleArray* par);
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+  virtual double OnBeginIteration(vtkDoubleArray* params);
+
+  // Description:
+  int OptimizationMethod;
+
+
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxSliceBiasFieldCorrection.cpp b/bioimagesuite30_src/Segmentation/vtkpxSliceBiasFieldCorrection.cpp
new file mode 100644
index 0000000..412e25b
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxSliceBiasFieldCorrection.cpp
@@ -0,0 +1,659 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSliceBiasFieldCorrection.cpp,v $
+  Language:  C++
+  Date:      $Date: 2004/11/23 18:19:05 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxSliceBiasFieldCorrection.h"
+#include "vtkObjectFactory.h"
+#include "pxutil.h"
+#include "vtkpxUtil.h"
+#include "vtkExtractVOI.h"
+#include "vtkpxOptimizer.h"
+#include "vtkbisImageResample.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageGradientMagnitude.h"
+#include "vtkPointData.h"
+#include "vtkDataArray.h"
+#include "vtkpxMath.h"
+#include "vtkpxImageExtract.h"
+#include "vtkpxHistogramSegmentation.h"
+#include "pxisinf.h"
+#include "vtkpxMatrix.h"
+
+vtkpxSliceBiasFieldCorrection* vtkpxSliceBiasFieldCorrection::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkpxSliceBiasFieldCorrection");
+  if(ret)
+    {
+    return (vtkpxSliceBiasFieldCorrection*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkpxSliceBiasFieldCorrection;
+  
+}
+
+
+vtkpxSliceBiasFieldCorrection::vtkpxSliceBiasFieldCorrection()
+{
+  this->SliceParameters=vtkDoubleArray::New();
+  this->RobustMode=0;
+  this->Threshold=0.02;
+  this->Axis=2;
+  this->PureScaling=0;
+}
+
+vtkpxSliceBiasFieldCorrection::~vtkpxSliceBiasFieldCorrection() 
+{
+  this->SliceParameters->Delete();
+}
+//-------------------------------------------------------------------------
+int vtkpxSliceBiasFieldCorrection::CreateWeightImage(vtkImageData* ref) 
+{
+  if (this->WeightImage!=NULL)
+    this->WeightImage->Delete();
+
+  this->WeightImage=vtkImageData::New();
+  this->WeightImage->CopyStructure(ref);
+  this->WeightImage->SetScalarTypeToFloat();
+  this->WeightImage->SetNumberOfScalarComponents(1);
+  this->WeightImage->AllocateScalars();
+
+  vtkImageGaussianSmooth* smooth=vtkImageGaussianSmooth::New();
+  smooth->SetInput(ref);
+  smooth->SetStandardDeviations(1.0,1.0,0.0);
+
+  vtkImageGradientMagnitude* grad=vtkImageGradientMagnitude::New();
+  grad->HandleBoundariesOn();
+  grad->SetInput(smooth->GetOutput());
+  grad->SetDimensionality(2);
+  grad->Update();
+
+  vtkImageData* tmp=grad->GetOutput();
+
+  vtkDataArray* magn=tmp->GetPointData()->GetScalars();
+  double r[2]; magn->GetRange(r);
+  double sigma2=pow(r[1]*0.1,2.0);
+
+
+  vtkDataArray* in=ref->GetPointData()->GetScalars();
+  vtkDataArray* wgt=this->WeightImage->GetPointData()->GetScalars();
+  int nt=wgt->GetNumberOfTuples();
+
+  double range[2];in->GetRange(range);
+  double m_range[2];
+  vtkDataArray* mask=NULL;
+  if (this->MaskImage!=NULL)
+    {
+      mask=this->MaskImage->GetPointData()->GetScalars();
+      mask->GetRange(m_range);
+    }
+
+  for (int i=0;i<nt;i++)
+    {
+      double v=in->GetComponent(i,0);
+     
+      double w=0.0;
+      if (v>range[0])
+	w=1000.0;
+
+      if (this->MaskImage!=NULL)
+	{
+	  if (mask->GetComponent(i,0)>m_range[0])
+	    w=1000.0;
+	  else
+	    w=0.0;
+	}
+      
+      wgt->SetComponent(i,0,w*(1.0-vtkpxAbstractBiasFieldCorrection::Valley2(magn->GetComponent(i,0),sigma2)));
+    }
+
+  grad->Delete();
+  smooth->Delete();
+  return 1;
+}
+// ---------------------------------------------------------------------------------------------------
+void vtkpxSliceBiasFieldCorrection::PrintInformation() 
+{
+  
+}
+//-------------------------------------------------------------------------
+vtkImageData* vtkpxSliceBiasFieldCorrection::GenerateSynthetic(int width,double factor)
+{
+  if (width<16)
+    width=16;
+  else if (width>256)
+    width=256;
+
+  if (factor < 0.000001)
+    factor=0.000001;
+  else if (factor>0.1)
+    factor=0.1;
+
+  int offset=width/7;
+
+  vtkImageData* tmp=vtkImageData::New();
+  tmp->SetDimensions(width,width,width);
+  tmp->SetScalarTypeToShort();
+  tmp->AllocateScalars();
+
+  int mid=width/2;
+
+  for (int slice=0;slice<width;slice++)
+    {
+      float bias=vtkpxMath::GaussianRandom()*0.1+1.0;
+      for (int j=0;j<width;j++)
+	{
+	  int count=0;
+	  int mode=0;
+	  for (int i=0;i<width;i++)
+	    {
+	      float v=0.0;
+	      if (mode==0)
+		v=vtkpxMath::GaussianRandom()*5.0+100.0;
+	      else
+		v=vtkpxMath::GaussianRandom()*5.0+50.0;
+	      
+	      double newv=bias*v;
+
+	      if (newv<0.0)
+		newv=0.0;
+	      
+	      tmp->SetScalarComponentFromDouble(i,j,slice,0,newv);
+	      ++count;
+	      if (count==offset)
+		{
+		  mode=1-mode;
+		  count=0;
+		}
+	    }
+	}
+    }
+  return tmp;
+}
+//-------------------------------------------------------------------------
+int vtkpxSliceBiasFieldCorrection::ComputeWeightedImageRatio(vtkImageData* img1,vtkImageData* img2,vtkImageData* weight1,vtkImageData* weight2,
+							     float threshold, 
+							     float *x,float* y,float* t,float& a,float& b)
+{
+ vtkDataArray* data1=img1->GetPointData()->GetScalars();
+ vtkDataArray* data2=img2->GetPointData()->GetScalars();
+  
+ vtkDataArray* wgt1=weight1->GetPointData()->GetScalars();
+ vtkDataArray* wgt2=weight2->GetPointData()->GetScalars();
+
+  int nt1=data1->GetNumberOfTuples();
+  if (nt1!=data2->GetNumberOfTuples() || nt1!=wgt1->GetNumberOfTuples() || nt1!=wgt2->GetNumberOfTuples())
+    {
+      fprintf(stderr,"**** Bad Images for Ratio\n");
+      a=0.0;
+      b=0.0;
+      return 0;
+    }
+
+  int index=0;
+  int numgood=0;
+  for (int pixel=0;pixel<nt1;pixel++)
+    {
+      double xin=data1->GetComponent(pixel,0);
+      double yin=data2->GetComponent(pixel,0);
+      
+      if (xin>threshold && yin>threshold)
+	++numgood;
+
+      if (wgt1->GetComponent(pixel,0)>750.0 && wgt2->GetComponent(pixel,0)> 750.0)
+	{
+	  x[index]=xin;
+	  y[index]=yin;
+	  ++index;
+	}
+    }
+
+  float abdev=0.0;
+
+  if (index > nt1/20)
+    {
+      int maxpass=1;
+      if (this->PureScaling==0)
+	maxpass=0;
+      for (int pass=0;pass<=maxpass;pass++)
+	{
+	  if (this->RobustMode==1)
+	    vtkpxMath::Medfit(x,y,index,a,b,abdev,t);
+	  else
+	    vtkpxMath::Meanfit(x,y,index,a,b,abdev);
+	  if (pass==0 && maxpass>0)
+	    {
+	      for (int i=0;i<index;i++)
+		y[i]=y[i]-a;
+	    }
+	}
+    }
+  else
+    {
+      a=0.0;
+      b=1.0;
+    }
+
+  if (this->PureScaling==1)
+    a=0.0;
+
+  return numgood;
+}
+//-------------------------------------------------------------------------
+void vtkpxSliceBiasFieldCorrection::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxSliceBiasFieldCorrection");
+      return;
+    }
+
+  this->CheckInputsAndCreateReferenceImage(input);
+
+  if (this->BiasField!=NULL)
+    {
+      this->BiasField->Delete();
+      this->BiasField=NULL;
+    }
+  
+
+  vtkDebugMacro(<<"Initializing All");
+  int ok=this->InitializeAll();
+  if (ok==0)
+    {
+      vtkErrorMacro(<<"Initialization Failed\n");
+      return;
+    }
+
+  int dim[3]; this->ReferenceImage->GetDimensions(dim);
+
+  if (dim[this->Axis]<2)
+    {
+      output->ShallowCopy(input);
+      return;
+    }
+  
+
+  double int_range[2]; this->ReferenceImage->GetPointData()->GetScalars()->GetRange(int_range);
+  int nonnegative=0;
+  if (int_range[0]>=0.0)
+    nonnegative=1;
+
+  float threshold=this->Threshold*int_range[1]+(1.0-this->Threshold)*int_range[0];
+
+  int perdim[3];
+  perdim[2]=dim[this->Axis];
+  for (int k=1;k<=2;k++)
+    {
+      int taxis=this->Axis+k;
+      if (taxis>2)
+	taxis-=3;
+      perdim[k-1]=dim[taxis];
+    }
+
+  fprintf(stderr,"Axis=%d dim=%d,%d,%d perdim=%d,%d,%d\n",
+	  this->Axis,
+	  dim[0],dim[1],dim[2],
+	  perdim[0],perdim[1],perdim[2]);
+
+  int slicesize=perdim[0]*perdim[1];
+  float* xa=new float[slicesize];
+  float* ya=new float[slicesize];
+  float* ta=new float[slicesize];
+
+  this->SliceParameters->SetNumberOfComponents(3);
+  this->SliceParameters->SetNumberOfTuples(perdim[2]);
+  this->SliceParameters->FillComponent(0,0.0);
+  this->SliceParameters->FillComponent(1,1.0);
+  this->SliceParameters->FillComponent(2,1.0);
+
+  this->CreateWeightImage(this->ReferenceImage);
+  
+  vtkpxImageExtract* slice_voi=vtkpxImageExtract::New(); 
+  slice_voi->SetInput(this->ReferenceImage);   slice_voi->SetCurrentPlane(this->Axis);
+  
+  vtkpxImageExtract* slice_voi2=vtkpxImageExtract::New(); 
+  slice_voi2->SetInput(this->ReferenceImage);   slice_voi2->SetCurrentPlane(this->Axis);
+  
+  vtkpxImageExtract* weight_voi=vtkpxImageExtract::New(); 
+  weight_voi->SetInput(this->WeightImage);   weight_voi->SetCurrentPlane(this->Axis);
+  
+  vtkpxImageExtract* weight_voi2=vtkpxImageExtract::New(); 
+  weight_voi2->SetInput(this->WeightImage);   weight_voi2->SetCurrentPlane(this->Axis);
+  
+
+  for (int pass=0;pass<=1;pass++)
+    {
+      double current_a=0.0;
+      double current_b=1.0;
+
+      int slice=perdim[2]/2+1; 
+      int endslice=perdim[2];
+      int increment=1;
+
+      
+      if (pass==1)
+	{
+	  slice=perdim[2]/2-1;   
+	  endslice=-1;
+	  increment=-1;
+	}
+
+      int maxcount=abs(endslice-slice);
+      if (slice>=perdim[2] || slice<0)
+	maxcount=-1;
+
+      fprintf(stderr,"Slice=%d endslice=%d increment=%d maxcount=%d\n",
+	      slice,endslice,increment,maxcount);
+
+      for (int count=0;count<maxcount;count++)
+	{
+	  slice_voi->SetSliceNo(slice);	    slice_voi->Update();
+	  slice_voi2->SetSliceNo(slice-increment);  slice_voi2->Update();
+	  weight_voi->SetSliceNo(slice);    weight_voi->Update();
+	  weight_voi2->SetSliceNo(slice-increment); weight_voi2->Update();
+	  
+	  
+	  float a1,b1;
+	  int nv1=this->ComputeWeightedImageRatio(slice_voi2->GetOutput(),slice_voi->GetOutput(),weight_voi2->GetOutput(),weight_voi->GetOutput(),
+						  threshold,xa,ya,ta,a1,b1);
+	  float ah1,bh1;
+	  
+	  int nv2=this->ComputeWeightedImageRatio(slice_voi->GetOutput(),slice_voi2->GetOutput(),weight_voi->GetOutput(),weight_voi2->GetOutput(),
+						  threshold,xa,ya,ta,ah1,bh1);
+	  
+	  double a0=current_a;
+	  double b0=current_b;
+
+	  
+
+	  //	  fprintf(stderr,"Orig Pairs nv1=%d (%.2f,%.2f) vs nv2=%d (%.2f,%.2f)\t",nv1,a1,b1,nv2,ah1,bh1);
+	  
+	  if (nv1>0 && nv2>0 && (b1*bh1)>0.5)
+	    {
+	      float olda1=a1,oldb1=b1;
+
+	      a1=0.5*(a1-ah1/bh1);
+	      b1=0.5*(b1+1.0/bh1);
+
+	      if (b1>1.5 || b1 <0.666)
+		{
+		  b1=Frange(b1,0.666,1.5);
+		  a1=0.0;
+		}
+
+	      if ( !isnan(a1) && !isnan(b1) )
+		{
+		  current_a=a1+b1*a0;
+		  current_b=b1*b0;
+		}
+	      else
+		{
+		  a1=0.0;
+		  b1=0.0;
+		}
+	    }
+	  else
+	    {
+	      a1=0.0;
+	      b1=0.0;
+	    }
+	  
+	  /*	  fprintf(stderr,"Slice = %02d to %02d \t ",slice-increment,slice);
+	  fprintf(stderr,"y=%.4f + %.4f * x (%.2f,%.2f), \n***********************\t overall \t  %.2f + %.2f * x --> \t %.2f + %.2f * x\n\n",
+		  a1,b1,
+		  100.0*nv1/double(perdim[0]*perdim[1]),
+		  100.0*nv2/double(perdim[0]*perdim[1]),
+		  a0,b0,
+		  current_a,current_b);*/
+	  this->SliceParameters->SetComponent(slice,0,current_a);
+	  this->SliceParameters->SetComponent(slice,1,current_b);
+	  this->SliceParameters->SetComponent(slice,2,double(nv1)/double(slicesize));
+	  slice+=increment;
+	}
+    }
+
+  if (perdim[2]>3)
+    {
+      double a1=this->SliceParameters->GetComponent(perdim[2]/2-1,2);
+      double a2=this->SliceParameters->GetComponent(perdim[2]/2+1,2);
+      this->SliceParameters->SetComponent(perdim[2]/2,2,0.5*(a1+a2));
+    }
+
+  slice_voi->Delete();
+  slice_voi2->Delete();
+  weight_voi->Delete();
+  weight_voi2->Delete();
+  delete [] xa;
+  delete [] ya;
+  delete [] ta;
+
+  vtkDataArray* inp=input->GetPointData()->GetScalars();
+  vtkDataArray* dat=output->GetPointData()->GetScalars();
+  
+  double sum_in=0.0,sum_out=0.0;
+  int nc=dat->GetNumberOfComponents();
+
+  double drange[2]; dat->GetDataTypeRange(drange);
+  if (nonnegative==1)
+    drange[0]=0.0;
+
+  int index=0;
+  for (int k=0;k<dim[2];k++)
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  double a=0.0,b=1.0;
+	  switch (this->Axis)
+	    {
+	    case 0:
+	      a=this->SliceParameters->GetComponent(i,0);
+	      b=this->SliceParameters->GetComponent(i,1);
+	      break;
+	    case 1:
+	      a=this->SliceParameters->GetComponent(j,0);
+	      b=this->SliceParameters->GetComponent(j,1);
+	      break;
+	    case 2:
+	      a=this->SliceParameters->GetComponent(k,0);
+	      b=this->SliceParameters->GetComponent(k,1);
+	      break;
+	    }
+
+	  for (int c=0;c<nc;c++)
+	    {
+	      double y=inp->GetComponent(index,c);
+	      if (y>threshold)
+		{
+		  double x=(y-a)/b;
+		  
+		  if (x<drange[0])
+		    x=drange[0];
+		  else if (x>drange[1])
+		    x=drange[1];
+		  
+		  if (c==0)
+		    {
+		      sum_in+=y;
+		      sum_out+=x;
+		    }
+		  dat->SetComponent(index,c,x);
+		}
+	      else
+		{
+		  dat->SetComponent(index,c,y);		  
+		}
+	    }
+	  ++index;
+	}
+
+  this->BiasField=vtkImageData::New();  
+  this->BiasField->CopyStructure(output);
+  this->BiasField->SetNumberOfScalarComponents(1);
+  this->BiasField->SetScalarTypeToFloat();
+  this->BiasField->AllocateScalars();
+  vtkDataArray* bias=this->BiasField->GetPointData()->GetScalars();
+
+  double scale=sum_in/sum_out;
+  fprintf(stderr,"Overall scale=%.2f\n",scale);
+  int    nt=dat->GetNumberOfTuples();
+  for (int vx=0;vx<nt;vx++)
+    for (int c=0;c<nc;c++)
+      {
+	dat->SetComponent(vx,c,dat->GetComponent(vx,c)*scale);
+	if (c==0)
+	  {
+	    double y=inp->GetComponent(vx,0);
+	    double x=dat->GetComponent(vx,0);
+	    double b=0.0;
+	    if (x>0.0)
+	      b=100.0*y/x;
+	    else 
+	      b=100.0;
+	    bias->SetComponent(vx,0,b);
+	  }
+      }
+}
+
+
+int vtkpxSliceBiasFieldCorrection::PolynomialFitToParameters(int order,vtkFloatArray* params)
+{
+  if (params==NULL || this->SliceParameters->GetNumberOfTuples()<2)
+    {
+      vtkErrorMacro(<<"Either Bad Output Array or no SliceParameters\n");
+      return 0;
+    }
+  
+  if (order<1)
+    order=1;
+  else if (order>3)
+    order=3;
+
+  params->SetNumberOfComponents(1);
+  params->SetNumberOfTuples(order);
+
+  int rows=this->SliceParameters->GetNumberOfTuples();
+
+  double* y=new double[rows];
+
+  double sum=0.0;
+  for (int i=0;i<rows;i++)
+    sum+=this->SliceParameters->GetComponent(i,1);
+  double mean=sum/double(rows);
+
+  for (int i=0;i<rows;i++)
+    y[i]=this->SliceParameters->GetComponent(i,1)-mean;
+
+
+  vtkpxMatrix* A=vtkpxMatrix::New();
+  vtkpxMatrix* B=vtkpxMatrix::New();
+  vtkpxMatrix* W=vtkpxMatrix::New();
+  vtkpxMatrix* D=vtkpxMatrix::New();
+  A->Zeros(rows,order+1);
+  B->Zeros(rows,1);
+  D->Zeros(rows,1);
+  W->Eye(rows);
+
+  double half=0.5*double(rows);
+
+  for (int i=0;i<rows;i++)
+    {
+      double w=this->SliceParameters->GetComponent(i,2)+0.01;
+      B->SetDirectElement(i,0,y[i]);
+      W->SetDirectElement(i,i,w);
+      D->SetDirectElement(i,0,w);
+      double x=(double(i)-half)/half;
+      
+      for (int j=0;j<=order;j++)
+	{
+	  switch (j)
+	    {
+	    case 0:
+	      A->SetDirectElement(i,0,1.0);
+	    case 1:
+	      A->SetDirectElement(i,1,x);
+	      break;
+	    case 2:
+	      A->SetDirectElement(i,2,0.5*(3.0*x*x-1.0));
+	      break;
+	    case 3:
+	      A->SetDirectElement(i,3,0.5*(5.0*x*x*x-3.0*x));
+	      break;
+	    }
+	}
+    }
+
+  vtkpxMatrix* Wa=vtkpxMatrix::New();
+  vtkpxMatrix::Multiply(W,A,Wa);
+
+  vtkpxMatrix* Wb=vtkpxMatrix::New();
+  vtkpxMatrix::Multiply(W,B,Wb);
+
+  vtkpxMatrix* X=vtkpxMatrix::New();
+  X->Zeros(order+1,1);
+
+  A->SolveLeastSquares(B,X);
+  X->Print("Ordinary Params");
+
+  for (int i=0;i<order;i++)
+    params->SetComponent(i,0,X->GetDirectElement(i+1,0));
+
+  A->Delete();
+  B->Delete();
+  X->Delete();
+  Wa->Delete();
+  Wb->Delete();
+
+  delete [] y;
+  return order;
+}
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxSliceBiasFieldCorrection.h b/bioimagesuite30_src/Segmentation/vtkpxSliceBiasFieldCorrection.h
new file mode 100644
index 0000000..ccbf7e3
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxSliceBiasFieldCorrection.h
@@ -0,0 +1,151 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxSliceBiasFieldCorrection.h,v $
+  Language:  C++
+  Date:      $Date: 2002/04/16 13:19:58 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxSliceBiasFieldCorrection - Filter for ffd registration based on voxel similarity measures.
+
+// .SECTION Description
+// This class implements a registration filter for the non-rigid registration
+// of images.
+
+
+#ifndef _VTKPXSliceBiasFieldCorrection_H
+#define _VTKPXSliceBiasFieldCorrection_H
+
+#include "vtkImageData.h"
+#include "vtkDoubleArray.h"
+#include "vtkpxAbstractBiasFieldCorrection.h"
+#include "vtkImageData.h"
+#include "vtkFloatArray.h"
+
+class  vtkpxSliceBiasFieldCorrection : public vtkpxAbstractBiasFieldCorrection {
+
+public:
+  static vtkpxSliceBiasFieldCorrection* New();
+  vtkTypeMacro(vtkpxSliceBiasFieldCorrection,vtkpxAbstractBiasFieldCorrection);
+
+  // Description:
+  // Print information about the progress of the registration
+  void PrintInformation();
+
+  // Description:
+  // Synthetic Data
+  vtkImageData* GenerateSynthetic(int width,double factor);
+
+  // Description:
+  // Get Internal Transformation Stuff
+  vtkGetObjectMacro(SliceParameters,vtkDoubleArray);
+
+  // Description:
+  // RobustMode
+  // 0 == correlation
+  vtkSetClampMacro(RobustMode,int,0,1);
+  vtkGetMacro(RobustMode,int);
+
+
+  // Description:
+  // Threshold
+  // Values below this are ignored in image ratio computation (Image Range 0..1)
+  vtkSetClampMacro(Threshold,float,0.0,0.25);
+  vtkGetMacro(Threshold,float);
+
+  // Description:
+  // Axis 0=X, 1=Y, 2=Z
+  vtkSetClampMacro(Axis,int,0,2);
+  vtkGetMacro(Axis,int);
+
+  // Description:
+  // Pure Scaling i.e. no Offset Computed
+  vtkSetClampMacro(PureScaling,int,0,1);
+  vtkGetMacro(PureScaling,int);
+
+
+  // Description:
+  // ComputePolynomial Fit 
+  virtual int PolynomialFitToParameters(int order,vtkFloatArray* params);
+
+  // Description:
+  // Image Ratio
+  virtual int ComputeWeightedImageRatio(vtkImageData* img1,vtkImageData* img2,vtkImageData* weight1,vtkImageData* weight2,float threshold,
+					float* x,float* y,float *temp,float& a,float& b);
+
+protected:
+
+  // Make all these protected 
+  // Constructor
+  vtkpxSliceBiasFieldCorrection();
+  virtual ~vtkpxSliceBiasFieldCorrection();
+  vtkpxSliceBiasFieldCorrection(const vtkpxSliceBiasFieldCorrection&) {};
+  void operator=(const vtkpxSliceBiasFieldCorrection&) {};
+
+  // Description:
+  // Execute Stuff 
+  virtual void SimpleExecute(vtkImageData* in,vtkImageData* out);
+
+  // Description:
+  // Create Weight Image
+  virtual int CreateWeightImage(vtkImageData* ref);
+
+  // Description:
+  // More Variables
+  vtkDoubleArray* SliceParameters;
+  int             RobustMode;
+  int             Axis;
+  float           Threshold;
+  int             PureScaling;
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxTissueLevelSetFilter.cpp b/bioimagesuite30_src/Segmentation/vtkpxTissueLevelSetFilter.cpp
new file mode 100644
index 0000000..94dfe52
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxTissueLevelSetFilter.cpp
@@ -0,0 +1,362 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxTissueLevelSetFilter.cpp,v $
+  Language:  C++
+  Date:      $Date: 2002/02/20 18:06:52 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+#include "vtkpxLevelSetUtil.h"
+#include "vtkImageImport.h"
+#include "vtkImageExport.h"
+#include "vtkpxTissueLevelSetFilter.h"
+#include "itkpxTissueSegmentationLevelSetImageFilter.h"
+#include "itkThresholdSegmentationLevelSetImageFilter.h"
+#include "vtkImageCast.h"
+#include "itkReinitializeLevelSetImageFilter.h"
+#include "itkpxSaturateImageFilter.h"
+#include "vtkpxAnalyzeImageWriter.h"
+//------------------------------------------------------------------------------
+// First a Helper Class
+// -----------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+vtkpxTissueLevelSetFilter* vtkpxTissueLevelSetFilter::New()
+{
+  return new vtkpxTissueLevelSetFilter;
+}
+
+
+
+vtkpxTissueLevelSetFilter::vtkpxTissueLevelSetFilter()
+{
+  this->InsideMean=100.0;
+  this->InsideSigma=10.0;
+  this->OutsideMean=0.0;
+  this->OutsideSigma=10.0;
+  this->Outside2Mean=0.0;
+  this->Outside2Sigma=10.0;
+  this->DynamicParameterUpdate=1;
+  this->BeginLevel=1;
+  this->EndLevel=1;
+  this->NumberOfLevels=2;
+  this->BiExponentialOutside=0;
+  this->VolumeWeight=0.0;
+  this->ApproximateVolume=0.0;
+}
+// ----------------------------------------------------------------------------
+vtkpxTissueLevelSetFilter::~vtkpxTissueLevelSetFilter()
+{
+}
+// ---------------------------------------------------------------------------------------------
+int vtkpxTissueLevelSetFilter::CheckInputs()
+{
+  return 1;
+}
+// ----------------------------------------------------------------------------
+template <int ImageDimension>
+int vtkpxTissueLevelSetFilter_RunActiveContour(vtkImageData* input,vtkImageData* initial,vtkImageData* output,vtkpxTissueLevelSetFilter* self)
+{
+  typedef  float  PixelType;
+  typedef itk::Image<PixelType,ImageDimension>    ImageType;
+  typedef itk::VTKImageImport<ImageType> ImportType;
+  typedef itk::VTKImageExport<ImageType> ExportType;
+  typedef itk::TissueSegmentationLevelSetImageFilter< ImageType, ImageType > LevelSetFilterType;
+  typedef itk::SaturateImageFilter<ImageType,ImageType> SaturateFilterType;
+  typedef itk::ReinitializeLevelSetImageFilter<ImageType> Reinitializer;
+  
+
+  vtkImageCast* cast=vtkImageCast::New();
+  cast->SetInput(input);
+  cast->SetOutputScalarTypeToFloat();
+  // Export original image
+  vtkImageExport *vtkInputExporter = vtkImageExport::New();
+  vtkInputExporter->SetInput(cast->GetOutput());
+  typename ImportType::Pointer itkInputImporter =  ImportType::New();
+  ConnectPipelines(vtkInputExporter, itkInputImporter);
+  itkInputImporter->Update();
+  
+  //  fprintf(stderr,"Importer Done\n");
+
+  // Export Initial Levelset
+  vtkImageExport *vtkInputLevelSetExporter = vtkImageExport::New();
+  vtkInputLevelSetExporter->SetInput(initial);
+  typename ImportType::Pointer itkInputLevelSetImporter =  ImportType::New();
+  ConnectPipelines(vtkInputLevelSetExporter, itkInputLevelSetImporter);
+  itkInputLevelSetImporter->Update();
+
+  //  fprintf(stderr,"Input Level Importer Done\n");
+
+  typename  LevelSetFilterType::Pointer levelSet =    LevelSetFilterType::New();
+  levelSet->SetInsideTissue(self->GetInsideMean(),self->GetInsideSigma());
+  levelSet->SetOutsideTissue(self->GetOutsideMean(),self->GetOutsideSigma());
+  if (self->GetBiExponentialOutside())
+    {
+      levelSet->SetOutside2Tissue(self->GetOutside2Mean(),self->GetOutside2Sigma());
+      levelSet->SetBiExponentialOutside(1);
+    }
+  else
+    levelSet->SetBiExponentialOutside(0);
+
+  levelSet->SetDynamicUpdateParameters(self->GetDynamicParameterUpdate());
+  levelSet->SetPropagationScaling( self->GetPropagationWeight() );
+  levelSet->SetCurvatureScaling(   self->GetCurvatureWeight() );
+  levelSet->SetAdvectionScaling(self->GetAdvectionWeight());
+
+  if (self->GetVolumeWeight()>0.0)
+    {
+      levelSet->SetApproximateVolumeConstraintWeight(self->GetVolumeWeight());
+      levelSet->SetApproximateVolume(self->GetApproximateVolume());
+      fprintf(stderr,"VolumeWeight=%.5f, ApproximateVolume=%.5f\n",
+	      self->GetVolumeWeight(),
+	      self->GetApproximateVolume());
+    }
+
+  levelSet->SetMaximumRMSError(0.0);//self->GetRMSError());
+  levelSet->SetNumberOfIterations(1);
+  levelSet->SetInput(  itkInputLevelSetImporter->GetOutput() );
+  levelSet->SetIsoSurfaceValue(0.0);
+  levelSet->SetFeatureImage(itkInputImporter->GetOutput());
+  levelSet->SetNumberOfIterations(1);
+
+
+
+  //  fprintf(stderr,"Just Before Update\n");
+
+  levelSet->Update();
+  self->SetRealIteration(self->GetRealIteration()+1);
+  
+  typename ExportType::Pointer itkExporter = ExportType::New();
+  itkExporter->SetInput(levelSet->GetOutput());
+
+  vtkImageImport* vtkImporter=vtkImageImport::New();
+  ConnectPipelines(itkExporter, vtkImporter);
+
+
+  int maxiter=int(self->GetLevelsetIterations());
+  int iter=1;
+  int count=1;
+  int fraction=int(self->GetUpdatePercentage()*float(maxiter));
+  float maxerror=self->GetRMSError()+1.0;
+
+  char line[220];
+  sprintf(line,"Begining level set evolution, updating every %d iterations", fraction);
+  self->SetOutputStatus(line);
+
+
+  while( iter <= maxiter && maxerror > self->GetRMSError() )
+    {
+      //      fprintf(stderr,"maxiter=%d iter=%d maxerror=%.2f (<%.5f)\n",maxiter,iter,maxerror,self->GetRMSError());
+      levelSet->SetStateToInitialized();
+      levelSet->SetNumberOfIterations(levelSet->GetElapsedIterations()+1);
+      levelSet->Modified();
+      levelSet->Update();
+      maxerror=levelSet->GetRMSChange();
+      self->SetRealIteration(self->GetRealIteration()+1);
+
+      sprintf(line,"Completed  %d (%d) /%d error=%6.4f",iter,self->GetRealIteration(),maxiter,maxerror);
+      self->SetOutputStatus(line);
+      //      fprintf(stderr,"%s\n",line);
+
+      int doupdate=0,dosave=0;
+      if (self->GetIterationSave() && 
+	  self->GetIterationSaveFrequency()*int(self->GetRealIteration()/self->GetIterationSaveFrequency())==self->GetRealIteration())
+	{
+	  doupdate=1;
+	  dosave=1;
+	}
+      
+      if (count==fraction)
+	{
+	  doupdate=1;
+	  count=0;
+	}
+
+      if (doupdate)
+	{
+	  itkExporter->Update();
+	  vtkImporter->Update();
+	  output->ShallowCopy(vtkImporter->GetOutput());
+	  self->UpdateProgress(float(iter)/float(maxiter*self->GetNumberOfLevels()));
+
+	  if (dosave)
+	    {
+
+	      sprintf(line,"%s_%03d",self->GetIterationName(),self->GetRealIteration());
+	      vtkpxAnalyzeImageWriter* anaw=vtkpxAnalyzeImageWriter::New();
+	      anaw->SetInput(output);
+	      anaw->SetOrientation(self->GetIterationSaveOrientation());
+	      anaw->Save(line);
+	      std::cerr << "\t\t ***** Saving levelset " << line  << std::endl;
+	      anaw->Delete();
+	    }
+	}
+
+      ++iter;
+      ++count;
+    }
+
+  typename Reinitializer::Pointer reinit=Reinitializer::New();
+  reinit->SetInput(levelSet->GetOutput());
+  reinit->NarrowBandingOn();
+  reinit->SetNarrowBandwidth(12);
+
+  typename SaturateFilterType::Pointer sat=SaturateFilterType::New();
+  sat->SetInput(reinit->GetOutput());
+  sat->SetLowerBound(-20.0);
+  sat->SetUpperBound(20.0);
+
+
+  itkExporter->SetInput(sat->GetOutput());
+  itkExporter->Modified();
+
+  reinit->Update();
+  sat->Update();
+  itkExporter->Update();
+  vtkImporter->Update();
+
+  output->DeepCopy(vtkImporter->GetOutput());
+  
+  vtkImporter->Delete();
+  vtkInputLevelSetExporter->Delete();
+  cast->Delete();
+  vtkInputExporter->Delete();
+
+  return 1;
+}
+
+
+int vtkpxTissueLevelSetFilter::RunActiveContour(vtkImageData* input,vtkImageData* initial,vtkImageData* output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int   t[3]; initial->GetDimensions(t);
+  int   q[3]; output->GetDimensions(q);
+
+  /*    fprintf(stderr,"\n\n Dimensions input (%d x %d x%d)\n",dim[0],dim[1],dim[2]);
+    fprintf(stderr,"\n\n Dimensions intal (%d x %d x%d)\n",t[0],t[1],t[2]);
+    fprintf(stderr,"\n\n Dimensions outpt (%d x %d x%d)\n",q[0],q[1],q[2]);*/
+
+
+  if (dim[2]==1)
+    return vtkpxTissueLevelSetFilter_RunActiveContour<2>(input,initial,output,this);
+
+  return vtkpxTissueLevelSetFilter_RunActiveContour<3>(input,initial,output,this);
+}
+// ----------------------------------------------------------------------------
+void vtkpxTissueLevelSetFilter::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"Bad Inputs to vtkpxTissueLevelSetFilter");
+      return;
+    }
+
+  //  fprintf(stderr,"Beginning Simple Execute\n");
+
+  if (this->EndLevel>this->BeginLevel)
+    this->BeginLevel=this->EndLevel;
+
+  this->NumberOfLevels=this->EndLevel-this->BeginLevel+1;
+  
+  vtkImageData* internal_input=vtkImageData::New();
+  internal_input->ShallowCopy(input);
+
+
+  vtkImageData* internal_output=vtkImageData::New();
+  internal_output->CopyStructure(output);
+  internal_output->AllocateScalars();
+
+  vtkImageData* lv_input=vtkImageData::New();
+  vtkImageData* lv_initial=vtkImageData::New();
+
+
+  for (int level=this->BeginLevel;level>=this->EndLevel;level=level-1)
+    {
+      float factor=pow(2.0,level-1);
+
+      char line[150];   
+      sprintf(line,"********* Beginning Level %d of %d\n",this->NumberOfLevels-level+1,this->NumberOfLevels);
+      this->SetOutputStatus(line);
+      //      fprintf(stderr,"%s\n",line);
+      this->UpdateProgress(0.01);
+
+      if (level>1)
+	vtkpxLevelSetUtil::ResampleAndSmoothImage(lv_input,internal_input,factor);
+      else
+	lv_input->ShallowCopy(internal_input);
+
+      if (level==this->BeginLevel)
+	{
+	  this->SetOutputStatus("********* Creating Input Level Set");
+	  this->GenerateInputLevelSet(lv_input,factor);
+	  lv_initial->ShallowCopy(this->InputLevelSet);
+	  this->UpdateProgress(0.01);
+	}
+      else
+	vtkpxLevelSetUtil::ResliceDistanceMap(lv_initial,internal_output,lv_input);
+
+      //      fprintf(stderr,"\n*********  On to Running Active Contour for Level=%d (End=%d)\n-----------------------------------------\n",level,this->EndLevel);
+
+      this->RunActiveContour(lv_input,lv_initial,internal_output);
+      //      fprintf(stderr,"********* Done Running Active Contour for Level=%d (End=%d)\n\n",level,this->EndLevel);
+    }
+
+  if (this->EndLevel!=1)
+    vtkpxLevelSetUtil::ResliceDistanceMap(output,internal_output,input);
+  else
+    output->ShallowCopy(internal_output);
+  
+  internal_output->Delete();
+  internal_input->Delete();
+  lv_input->Delete();
+  lv_initial->Delete();
+
+}
+
diff --git a/bioimagesuite30_src/Segmentation/vtkpxTissueLevelSetFilter.h b/bioimagesuite30_src/Segmentation/vtkpxTissueLevelSetFilter.h
new file mode 100644
index 0000000..66fbede
--- /dev/null
+++ b/bioimagesuite30_src/Segmentation/vtkpxTissueLevelSetFilter.h
@@ -0,0 +1,156 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkpxTissueLevelSetFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/18 20:22:27 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkpxTissueLevelSetFilter -- corrects for B0 inhomogeneity in 1-H CSI Data for fat quantification
+
+#ifndef __vtkpxTissueLevelSetFilter_h
+#define __vtkpxTissueLevelSetFilter_h
+
+#include "vtkpxBaseLevelSetFilter.h"
+#include "vtkpxLevelSetUtil.h"
+
+class vtkpxTissueLevelSetFilter : public vtkpxBaseLevelSetFilter
+{
+public:
+  static vtkpxTissueLevelSetFilter *New();
+  vtkTypeMacro(vtkpxTissueLevelSetFilter,vtkpxBaseLevelSetFilter);
+
+  // Description:
+  // Part 1 Tissue Description
+  // Inside Mean and Sigma
+  vtkSetMacro(InsideMean,float);
+  vtkGetMacro(InsideMean,float);
+  vtkSetMacro(InsideSigma,float);
+  vtkGetMacro(InsideSigma,float);
+
+  vtkSetMacro(OutsideMean,float);
+  vtkGetMacro(OutsideMean,float);
+  vtkSetMacro(OutsideSigma,float);
+  vtkGetMacro(OutsideSigma,float);
+
+  vtkSetMacro(Outside2Mean,float);
+  vtkGetMacro(Outside2Mean,float);
+  vtkSetMacro(Outside2Sigma,float);
+  vtkGetMacro(Outside2Sigma,float);
+
+  // Bi-exponential outside
+  vtkSetClampMacro(BiExponentialOutside,int,0,1);
+  vtkGetMacro(BiExponentialOutside,int);
+  vtkBooleanMacro(BiExponentialOutside,int);
+  
+  
+  // Dynamic Update
+  vtkSetClampMacro(DynamicParameterUpdate,int,0,1);
+  vtkGetMacro(DynamicParameterUpdate,int);
+  vtkBooleanMacro(DynamicParameterUpdate,int);
+
+  // Multiresolution
+  vtkSetClampMacro(BeginLevel,int,1,4);
+  vtkGetMacro(BeginLevel,int);
+
+  vtkSetClampMacro(EndLevel,int,1,4);
+  vtkGetMacro(EndLevel,int);
+
+  virtual void SetNumberOfLevels(int n) {
+    this->SetEndLevel(1);
+    this->SetBeginLevel(n);
+  }
+
+  vtkGetMacro(NumberOfLevels,int);
+
+// Multiresolution
+  vtkSetMacro(VolumeWeight,float);
+  vtkGetMacro(VolumeWeight,float);
+
+  vtkSetMacro(ApproximateVolume,float);
+  vtkGetMacro(ApproximateVolume,float);
+
+
+protected:
+
+  vtkpxTissueLevelSetFilter();
+  virtual ~vtkpxTissueLevelSetFilter();
+  vtkpxTissueLevelSetFilter(const vtkpxTissueLevelSetFilter&) {};
+  void operator=(const vtkpxTissueLevelSetFilter&) {};
+
+
+  // Description
+  // Boilerplate code from filter
+  virtual void SimpleExecute(vtkImageData* inp,vtkImageData* out);
+
+  // Description:
+  // Basic Methods
+  virtual int  CheckInputs();
+  virtual int  RunActiveContour(vtkImageData* input,vtkImageData* initial,vtkImageData* output);
+
+  float         InsideMean;
+  float         InsideSigma;
+  float         OutsideMean;
+  float         OutsideSigma;
+  float         Outside2Mean;
+  float         Outside2Sigma;
+  float         VolumeWeight;
+  float         ApproximateVolume;
+  int           DynamicParameterUpdate;
+  int           EndLevel;
+  int           BeginLevel;
+  int           NumberOfLevels;
+  int           BiExponentialOutside;
+};
+
+
+
+#endif
+
diff --git a/bioimagesuite30_src/Testing/CMakeLists.txt b/bioimagesuite30_src/Testing/CMakeLists.txt
new file mode 100644
index 0000000..d789001
--- /dev/null
+++ b/bioimagesuite30_src/Testing/CMakeLists.txt
@@ -0,0 +1,131 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+INCLUDE_DIRECTORIES(${ITK_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/numerics)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/igtlutil)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Registration)
+INCLUDE_DIRECTORIES (${BIOIMAGESUITE3_SOURCE_DIR}/Imaging)
+
+
+SET (KITSRCS 
+bisVersionTest.cpp
+)
+
+SET (KITSRCS
+${KITSRCS}
+Test_vtkpxMatrix.cpp
+Test_vnlmatrix.cpp
+Test_vtkpxOptimizer.cpp
+)
+
+IF (BIOIMAGESUITE3_USE_CUDA)
+SET (KITSRCS
+${KITSRCS}
+cudainfo.cpp
+conjGrad.cpp
+Test_vtkbisCUDAOptimizer.cpp
+Test_vtkbisCUDASparseMatrix.cpp
+)
+ENDIF (BIOIMAGESUITE3_USE_CUDA)
+
+
+
+
+SET(KIT Testing)
+
+
+SET(KITLIBS
+  vtkpxCommon
+  vtkpxImaging
+  vtkpxRegistration
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+  numerics
+)
+
+IF (BIOIMAGESUITE3_USE_CUDA)
+SET(KITLIBS
+  vtkpxRegistration_Cuda
+  vtkpxImaging_Cuda
+  ${KITLIBS})
+ENDIF (BIOIMAGESUITE3_USE_CUDA)
+
+IF (APPLE)
+SET(KITLIBS
+${KITLIBS}
+SystemStubs
+)
+ENDIF (APPLE)
+
+
+SET (KITEXTRAFILES
+Testing/test.h
+Testing/bisruntests.bat.in
+Testing/bisruntests.sh.in
+)
+
+# Macro 
+bis_executable_list(installtools)
+
+FOREACH(item ${KITSRCS})
+  GET_FILENAME_COMPONENT(TAIL ${item} NAME_WE )        
+  IF (UNIX)
+    ADD_TEST(C-${TAIL} ${BIOIMAGESUITE3_BINARY_DIR}/biscppexec ${EXECUTABLE_OUTPUT_PATH}/${TAIL})
+  ELSE (UNIX)
+    ADD_TEST(C-${TAIL} ${BIOIMAGESUITE3_BINARY_DIR}/biscppexec.bat ${EXECUTABLE_OUTPUT_PATH}/${TAIL})
+  ENDIF (UNIX)
+ENDFOREACH(item $KITSRCS)
+
+
+SET (DOSH 0)
+IF (UNIX)
+  SET (DOSH 1)
+ELSEIF (BIOIMAGESUITE_USING_MINGW)
+  SET (DOSH 1)
+ENDIF (UNIX)
+      
+#message("Creating unix style .sh build = ${DOSH}")
+
+
+IF (WIN32)
+  STRING(REGEX REPLACE "/" "\\\\"  CMAKE_CTEST_COMMAND_BAT ${CMAKE_CTEST_COMMAND})
+  STRING(REGEX REPLACE "/" "\\\\"  SVNCOMMAND_BAT ${SVNCOMMAND})
+  configure_file( ${BIOIMAGESUITE3_SOURCE_DIR}/Testing/bisruntests.bat.in
+    ${BIOIMAGESUITE3_BINARY_DIR}/bisruntests.bat @ONLY )
+   install(FILES bisruntests.bat.in DESTINATION  ${BIOIMAGESUITE_INSTALL_EXTRAPATH}/testing)
+ENDIF(WIN32)
+
+IF (DOSH)
+  configure_file( ${BIOIMAGESUITE3_SOURCE_DIR}/Testing/bisruntests.sh.in
+    ${BIOIMAGESUITE3_BINARY_DIR}/bisruntests.sh @ONLY )
+   EXECUTE_PROCESS (COMMAND chmod +x  ${BIOIMAGESUITE3_BINARY_DIR}/bisruntests.sh)
+   install(FILES bisruntests.sh.in DESTINATION  ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/testing)
+ENDIF (DOSH)
+
+bis_sourcelist("Testing" ${KIT} ${FILELIST})
+
diff --git a/bioimagesuite30_src/Testing/Test_vnlmatrix.cpp b/bioimagesuite30_src/Testing/Test_vnlmatrix.cpp
new file mode 100644
index 0000000..599493e
--- /dev/null
+++ b/bioimagesuite30_src/Testing/Test_vnlmatrix.cpp
@@ -0,0 +1,126 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//
+// .Description
+//  Test program for vtkpxMatrix Class
+// .SETCTION Autor 
+//  Hirohito Okuda <hirohito.okuda at yale.edu>
+//
+
+#include "bioimagesuite_settings.h"
+#include "vtkpxMatrix.h"
+#include "test.h"
+#include "vnl/vnl_matrix.h"
+#include "vnl/algo/vnl_matrix_inverse.h"
+
+//---------------------------------------
+// test class
+//---------------------------------------
+class test_vnlMatrix{
+  public :
+  int Invert();            
+};
+
+
+//---------------------------------------
+// test vtkpxMatrix::Invert
+//---------------------------------------
+int test_vnlMatrix::Invert()
+{
+  int ret;
+
+  ret = 0;
+
+  vtkpxMatrix *matrix_operator = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix1            = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix1_expect      = (vtkpxMatrix *) vtkpxMatrix::New();
+
+
+  //Set matrix1
+  matrix1->Zeros(3,3);
+  matrix1->SetDirectElement (0,0, 1.20);  matrix1->SetDirectElement (0,1,-5.1);  matrix1->SetDirectElement (0,2, 0.4);
+  matrix1->SetDirectElement (1,0, 16.7);  matrix1->SetDirectElement (1,1, 0.6);  matrix1->SetDirectElement (1,2,-6.9);
+  matrix1->SetDirectElement (2,0, -0.4);  matrix1->SetDirectElement (2,1, 2.4);  matrix1->SetDirectElement (2,2,-4.1);
+
+  //Set expect
+  matrix1_expect->Zeros(3,3);
+  matrix1_expect->SetDirectElement (0,0, -0.0426982);  matrix1_expect->SetDirectElement (0,1,0.0604134);  matrix1_expect->SetDirectElement (0,2,-0.1058369);
+  matrix1_expect->SetDirectElement (1,0, -0.2157014);  matrix1_expect->SetDirectElement (1,1,0.0144144);  matrix1_expect->SetDirectElement (1,2,-0.0453024);
+  matrix1_expect->SetDirectElement (2,0, -0.1220986);  matrix1_expect->SetDirectElement (2,1,0.0025437);  matrix1_expect->SetDirectElement (2,2,-0.2600954);
+
+
+  int sz[2]; matrix1->GetSize(sz);
+  vnl_matrix<double> M(sz[0],sz[1]);
+  for (unsigned i=0; i<M.rows(); ++i)
+    for (unsigned j=0; j<M.cols(); ++j)
+      M(i,j)=matrix1->GetDirectElement(i,j);
+
+  vnl_matrix<double> IN=vnl_matrix_inverse<double>(M);
+
+  for (unsigned i=0; i< sz[0]; ++i)
+    for (unsigned j=0; j< sz[1]; ++j)
+	matrix1->SetDirectElement(i,j,IN(i,j));
+
+  //Output
+  std::cout << "Test_Inverse()-------------------------------------\n";
+  std::cout << "[expect]\n";
+  matrix1_expect->InternalPrint();
+  std::cout << "\n";
+  std::cout << "[result]\n";
+  matrix1->InternalPrint();
+
+  //Validate
+  ret = matrix_operator->IsEqual(matrix1,matrix1_expect,tolerance); if(ret !=0 ){ return ret;}
+
+  matrix_operator->Delete();
+  matrix1->Delete();
+  matrix1_expect->Delete();
+
+  return ret;
+}
+
+
+//--------------------------------------------
+// main part for testing vtkpxMatrix class
+//--------------------------------------------
+int main(int argc,char* argv[])
+{
+  int ret;
+  ret = 0;
+
+  test_vnlMatrix test;
+
+  ret = test.Invert();             if (ret!=0) {std::cout << "est_Invert() returns error "; return ret;}
+
+  if (ret==0)
+    std::cout << "All Tests Passed\n";
+  
+  return ret;
+}
+
+
diff --git a/bioimagesuite30_src/Testing/Test_vtkpxMatrix.cpp b/bioimagesuite30_src/Testing/Test_vtkpxMatrix.cpp
new file mode 100644
index 0000000..c84534f
--- /dev/null
+++ b/bioimagesuite30_src/Testing/Test_vtkpxMatrix.cpp
@@ -0,0 +1,645 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//
+// .Description
+//  Test program for vtkpxMatrix Class
+// .SETCTION Autor 
+//  Hirohito Okuda <hirohito.okuda at yale.edu>
+//
+
+#include "bioimagesuite_settings.h"
+#include "vtkpxMatrix.h"
+#include "test.h"
+
+//---------------------------------------
+// test class
+//---------------------------------------
+class test_vtkpxMatrix{
+  public :
+  int Add();
+  int QRDecomposition();
+  int Q1Q2RDecomposition();
+  int Invert();            
+
+  int SolveLeastSquares();//for SGELS of LAPACK
+
+
+  int SolveLinearSystem();//for SGESV of LAPACK
+
+  int SolveUpperSymmetricLinearSystem();//for SPOSV of LAPACK
+  int SolveLowerSymmetricLinearSystem();//for SPOSV of LAPACK
+
+  int InternalSolveSymmetricLinearSystem(int mode);
+
+};
+
+//---------------------------------------
+// test vtkpxMatrix::Add
+//---------------------------------------
+int  test_vtkpxMatrix::Add()
+{
+  int ret;
+  ret = 0;
+
+  vtkpxMatrix *matrix_operator = (vtkpxMatrix *) vtkpxMatrix::New();
+
+  vtkpxMatrix *matrix1       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix2       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix_result = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix_expect = (vtkpxMatrix *) vtkpxMatrix::New();
+
+  //Set matrix1
+  matrix1->Zeros(3,3);
+  matrix1->SetDirectElement (0,0, 1.0);  matrix1->SetDirectElement (0,1,2.0);  matrix1->SetDirectElement (0,2,  3.0);
+  matrix1->SetDirectElement (1,0, 4.0);  matrix1->SetDirectElement (1,1,5.0);  matrix1->SetDirectElement (1,2,  6.0);
+  matrix1->SetDirectElement (2,0, 7.0);  matrix1->SetDirectElement (2,1,8.0);  matrix1->SetDirectElement (2,2,  9.0);
+
+  //Set matrix2
+  matrix2->Zeros(3,3);
+  matrix2->SetDirectElement (0,0, 9.0);  matrix2->SetDirectElement (0,1,8.0);  matrix2->SetDirectElement (0,2,  7.0);
+  matrix2->SetDirectElement (1,0, 6.0);  matrix2->SetDirectElement (1,1,5.0);  matrix2->SetDirectElement (1,2,  4.0);
+  matrix2->SetDirectElement (2,0, 3.0);  matrix2->SetDirectElement (2,1,2.0);  matrix2->SetDirectElement (2,2,  1.0);
+
+  //Initialize
+  matrix_result->Zeros(3,3);
+
+  //Add
+  matrix_operator->Add(matrix1,matrix2,matrix_result);
+
+  //Set expect data
+  matrix_expect->Ones(3,3);
+  matrix_expect->Scale(10.0);
+
+  //Validate
+  ret = matrix_operator->IsEqual(matrix_expect,matrix_result,tolerance);
+
+  //Output
+  std::cout << "Test_Add()-------------------------------------";
+  std::cout << "[expect]\n";
+  matrix_expect->InternalPrint();
+  std::cout << "[result]\n";
+  matrix_result->InternalPrint();
+
+  matrix_operator->Delete();
+  matrix1->Delete();
+  matrix2->Delete();
+  matrix_result->Delete();
+  matrix_expect->Delete();
+
+  return ret;
+}
+
+//---------------------------------------
+// test vtkpxMatrix::QRDecomposition
+//---------------------------------------
+int test_vtkpxMatrix::QRDecomposition()
+{
+  int ret;
+
+  ret = 0;
+
+  vtkpxMatrix *matrix_operator = (vtkpxMatrix *) vtkpxMatrix::New();
+
+  vtkpxMatrix *matrix1       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix_Q      = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix_R      = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix_Q_expect      = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix_R_expect      = (vtkpxMatrix *) vtkpxMatrix::New();
+
+  //Set matrix1
+  matrix1->Zeros(3,3);
+  matrix1->SetDirectElement (0,0, 12.0);  matrix1->SetDirectElement (0,1,-51.0);  matrix1->SetDirectElement (0,2,  4.0);
+  matrix1->SetDirectElement (1,0,  6.0);  matrix1->SetDirectElement (1,1,167.0);  matrix1->SetDirectElement (1,2,-69.0);
+  matrix1->SetDirectElement (2,0, -4.0);  matrix1->SetDirectElement (2,1, 24.0);  matrix1->SetDirectElement (2,2,-41.0);
+
+  //Initialize
+  matrix_Q->Zeros(3,3);
+  matrix_R->Zeros(3,3);
+
+  //QRDecomposition
+  matrix1->QRDecomposition(matrix_Q,matrix_R);
+
+  //Set expect data calculated by Octave version 2.1.57 (i686-pc-linux-gnu)
+  //Set matrix_Q_expect
+  matrix_Q_expect->Zeros(3,3);
+  matrix_Q_expect->SetDirectElement (0,0, -0.857143);  matrix_Q_expect->SetDirectElement (0,1, 0.394286);  matrix_Q_expect->SetDirectElement (0,2,  0.331429);
+  matrix_Q_expect->SetDirectElement (1,0, -0.428571);  matrix_Q_expect->SetDirectElement (1,1,-0.902857);  matrix_Q_expect->SetDirectElement (1,2, -0.034286);
+  matrix_Q_expect->SetDirectElement (2,0,  0.285714);  matrix_Q_expect->SetDirectElement (2,1,-0.171429);  matrix_Q_expect->SetDirectElement (2,2,  0.942857);
+
+  //Set matrix_R_expect
+  matrix_R_expect->Zeros(3,3);
+  matrix_R_expect->SetDirectElement (0,0,-14.0);  matrix_R_expect->SetDirectElement (0,1, -21.0);  matrix_R_expect->SetDirectElement (0,2, 14.42857);
+  matrix_R_expect->SetDirectElement (1,0,  0.0);  matrix_R_expect->SetDirectElement (1,1,-175.0);  matrix_R_expect->SetDirectElement (1,2, 70.90286);
+  matrix_R_expect->SetDirectElement (2,0,  0.0);  matrix_R_expect->SetDirectElement (2,1,   0.0);  matrix_R_expect->SetDirectElement (2,2,-34.96571);
+  
+  //Output
+  std::cout << "Test_QRDecomposition()-------------------------------------";
+  std::cout << "[expect]\n";
+  std::cout << "Q\n";
+  matrix_Q_expect->InternalPrint();
+  std::cout << "R\n";
+  matrix_R_expect->InternalPrint();
+  std::cout << "[result]\n";
+  std::cout << "Q\n";
+  matrix_Q->InternalPrint();
+  std::cout << "R\n";
+  matrix_R->InternalPrint();
+
+  //Validate
+  ret = matrix_operator->IsEqual(matrix_Q,matrix_Q_expect,tolerance); if(ret !=0 ){ return ret;}
+  ret = matrix_operator->IsEqual(matrix_R,matrix_R_expect,tolerance); if(ret !=0 ){ return ret;}
+
+  matrix1->Delete();
+  matrix_Q->Delete();
+  matrix_R->Delete();
+  matrix_Q_expect->Delete();
+  matrix_R_expect->Delete();
+  matrix_operator->Delete();
+  return ret;
+}
+
+//---------------------------------------
+// test vtkpxMatrix::Q1Q2RDecomposition
+//---------------------------------------
+int test_vtkpxMatrix::Q1Q2RDecomposition()
+{
+  int ret;
+
+  ret = 0;
+  std::cout <<  "Q1Q2RDecomposition start\n";
+
+  vtkpxMatrix *matrix_operator = (vtkpxMatrix *) vtkpxMatrix::New();
+
+  vtkpxMatrix *matrix1       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix_Q1      = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix_Q2      = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix_R      = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix_Q1_expect      = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix_Q2_expect      = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix_R_expect      = (vtkpxMatrix *) vtkpxMatrix::New();
+
+  //Set matrix1
+  matrix1->Zeros(5,3);
+  matrix1->SetDirectElement (0,0, 12.0);  matrix1->SetDirectElement (0,1,-51.0);  matrix1->SetDirectElement (0,2,  4.0);
+  matrix1->SetDirectElement (1,0,  6.0);  matrix1->SetDirectElement (1,1,167.0);  matrix1->SetDirectElement (1,2,-69.0);
+  matrix1->SetDirectElement (2,0, -4.0);  matrix1->SetDirectElement (2,1, 24.0);  matrix1->SetDirectElement (2,2,-41.0);
+  matrix1->SetDirectElement (3,0,  10);   matrix1->SetDirectElement (3,1,    1);  matrix1->SetDirectElement (3,2,  7.0);  
+  matrix1->SetDirectElement (4,0,  -4);   matrix1->SetDirectElement (4,1,-21.0);  matrix1->SetDirectElement (4,2,  6.0);
+
+
+  //Initialize
+  matrix_Q1->Zeros(5,3);
+  matrix_Q2->Zeros(5,2);
+  matrix_R->Zeros(3,3);
+
+  //Q1Q2RDecomposition
+  matrix1->Q1Q2RDecomposition(matrix_Q1,matrix_Q2,matrix_R);
+
+
+  //Set expect data calculated by Octave version 2.1.57 (i686-pc-linux-gnu)
+  matrix_Q1_expect->Zeros(5,3);
+  matrix_Q1_expect->SetDirectElement (0,0, -0.679366);  matrix_Q1_expect->SetDirectElement (0,1, 0.374264);  matrix_Q1_expect->SetDirectElement (0,2,-0.463994);
+  matrix_Q1_expect->SetDirectElement (1,0, -0.339683);  matrix_Q1_expect->SetDirectElement (1,1,-0.905745);  matrix_Q1_expect->SetDirectElement (1,2,-0.028185);
+  matrix_Q1_expect->SetDirectElement (2,0,  0.226455);  matrix_Q1_expect->SetDirectElement (2,1,-0.164496);  matrix_Q1_expect->SetDirectElement (2,2,-0.859179);
+  matrix_Q1_expect->SetDirectElement (3,0, -0.566139);  matrix_Q1_expect->SetDirectElement (3,1, 0.064925);  matrix_Q1_expect->SetDirectElement (3,2, 0.202198);  
+  matrix_Q1_expect->SetDirectElement (4,0,  0.226455);  matrix_Q1_expect->SetDirectElement (4,1, 0.090982);  matrix_Q1_expect->SetDirectElement (4,2,-0.069586);
+
+  //Set matrix_Q2_expect
+  matrix_Q2_expect->Zeros(5,2);
+  matrix_Q2_expect->SetDirectElement (0,0, -0.408598);  matrix_Q2_expect->SetDirectElement (0,1, 0.127062); 
+  matrix_Q2_expect->SetDirectElement (1,0, -0.177169);  matrix_Q2_expect->SetDirectElement (1,1, 0.179046); 
+  matrix_Q2_expect->SetDirectElement (2,0,  0.406245);  matrix_Q2_expect->SetDirectElement (2,1,-0.135775); 
+  matrix_Q2_expect->SetDirectElement (3,0,  0.793298);  matrix_Q2_expect->SetDirectElement (3,1, 0.071180); 
+  matrix_Q2_expect->SetDirectElement (4,0,  0.085451);  matrix_Q2_expect->SetDirectElement (4,1, 0.963481); 
+
+  //Set matrix_R_expect
+  matrix_R_expect->Zeros(3,3);
+  matrix_R_expect->SetDirectElement (0,0,-17.66352);  matrix_R_expect->SetDirectElement (0,1, -21.96617);  matrix_R_expect->SetDirectElement (0,2,  8.83176);
+  matrix_R_expect->SetDirectElement (1,0,      0.0);  matrix_R_expect->SetDirectElement (1,1,-176.14053);  matrix_R_expect->SetDirectElement (1,2, 71.73817);
+  matrix_R_expect->SetDirectElement (2,0,      0.0);  matrix_R_expect->SetDirectElement (2,1,       0.0);  matrix_R_expect->SetDirectElement (2,2, 36.31301);
+  
+
+  //Output
+  std::cout << "Test_Q1Q2RDecomposition()-------------------------------------\n";
+  std::cout << "[expect]\n";
+  std::cout << "Q1\n";
+  matrix_Q1_expect->InternalPrint();
+  std::cout << "Q2\n";
+  matrix_Q2_expect->InternalPrint();
+  std::cout << "R\n";
+  matrix_R_expect->InternalPrint();
+
+  std::cout << "[result]\n";
+  std::cout << "Q1\n";
+  matrix_Q1->InternalPrint();
+  std::cout << "Q2\n";
+  matrix_Q2->InternalPrint();
+  std::cout << "R\n";
+  matrix_R->InternalPrint();
+
+  //Validate
+  ret = matrix_operator->IsEqual(matrix_Q1,matrix_Q1_expect,tolerance); if(ret !=0 ){ return ret;}
+  ret = matrix_operator->IsEqual(matrix_Q2,matrix_Q2_expect,tolerance); if(ret !=0 ){ return ret;}
+  ret = matrix_operator->IsEqual(matrix_R,matrix_R_expect,tolerance); if(ret !=0 ){ return ret;}
+
+
+  matrix_operator->Delete();
+
+
+  matrix1->Delete();
+  matrix_Q1->Delete();
+  matrix_Q2->Delete();
+  matrix_R->Delete();
+  matrix_Q1_expect->Delete();
+  matrix_Q2_expect->Delete();
+  matrix_R_expect->Delete();
+
+  return ret;
+}
+
+//---------------------------------------
+// test vtkpxMatrix::Invert
+//---------------------------------------
+int test_vtkpxMatrix::Invert()
+{
+  int ret;
+
+  ret = 0;
+
+  vtkpxMatrix *matrix_operator = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix1            = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix1_expect      = (vtkpxMatrix *) vtkpxMatrix::New();
+
+
+  //Set matrix1
+  matrix1->Zeros(3,3);
+  matrix1->SetDirectElement (0,0, 1.20);  matrix1->SetDirectElement (0,1,-5.1);  matrix1->SetDirectElement (0,2, 0.4);
+  matrix1->SetDirectElement (1,0, 16.7);  matrix1->SetDirectElement (1,1, 0.6);  matrix1->SetDirectElement (1,2,-6.9);
+  matrix1->SetDirectElement (2,0, -0.4);  matrix1->SetDirectElement (2,1, 2.4);  matrix1->SetDirectElement (2,2,-4.1);
+
+  matrix1->Invert();
+
+  //Set expect
+  matrix1_expect->Zeros(3,3);
+  matrix1_expect->SetDirectElement (0,0, -0.0426982);  matrix1_expect->SetDirectElement (0,1,0.0604134);  matrix1_expect->SetDirectElement (0,2,-0.1058369);
+  matrix1_expect->SetDirectElement (1,0, -0.2157014);  matrix1_expect->SetDirectElement (1,1,0.0144144);  matrix1_expect->SetDirectElement (1,2,-0.0453024);
+  matrix1_expect->SetDirectElement (2,0, -0.1220986);  matrix1_expect->SetDirectElement (2,1,0.0025437);  matrix1_expect->SetDirectElement (2,2,-0.2600954);
+
+
+  //Output
+  std::cout << "Test_Inverse()-------------------------------------\n";
+  std::cout << "[expect]\n";
+  matrix1_expect->InternalPrint();
+  std::cout << "\n";
+  std::cout << "[result]\n";
+  matrix1->InternalPrint();
+
+  //Validate
+  ret = matrix_operator->IsEqual(matrix1,matrix1_expect,tolerance); if(ret !=0 ){ return ret;}
+
+  matrix_operator->Delete();
+  matrix1->Delete();
+  matrix1_expect->Delete();
+
+  return ret;
+}
+
+//---------------------------------------
+// test vtkpxMatrix::SolveLeastSquares
+//---------------------------------------
+int test_vtkpxMatrix::SolveLeastSquares()
+{
+  int ret;
+  ret = 0;
+  vtkpxMatrix *matrix_operator = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix1       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix2       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix3       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix3_expect= (vtkpxMatrix *) vtkpxMatrix::New();
+
+  //Overdetermined
+  //Set matrix1
+  matrix1->Zeros(5,3);
+  matrix1->SetDirectElement (0,0, 12.0);  matrix1->SetDirectElement (0,1,-51.0);  matrix1->SetDirectElement (0,2,  4.0);
+  matrix1->SetDirectElement (1,0,  6.0);  matrix1->SetDirectElement (1,1,167.0);  matrix1->SetDirectElement (1,2,-69.0);
+  matrix1->SetDirectElement (2,0, -4.0);  matrix1->SetDirectElement (2,1, 24.0);  matrix1->SetDirectElement (2,2,-41.0);
+  matrix1->SetDirectElement (3,0,  10);   matrix1->SetDirectElement (3,1,    1);  matrix1->SetDirectElement (3,2,  7.0);  
+  matrix1->SetDirectElement (4,0,  -4);   matrix1->SetDirectElement (4,1,-21.0);  matrix1->SetDirectElement (4,2,  6.0);
+  //Set matrix2
+  matrix2->Zeros(5,1);
+  matrix2->SetDirectElement(0,0,2.0);
+  matrix2->SetDirectElement(1,0,2.0);
+  matrix2->SetDirectElement(2,0,2.0);
+  matrix2->SetDirectElement(3,0,2.0);
+  matrix2->SetDirectElement(4,0,2.0);
+  //Initialize matrix3
+  matrix3->Zeros(3,1);
+
+  //
+  matrix1->SolveLeastSquares(matrix2,matrix3);
+
+  //Set expect
+  //Calculated by pinv(matrix1)*matrix2 of Octave
+  matrix3_expect->Zeros(3,1);
+  matrix3_expect->SetDirectElement(0,0,0.121015);
+  matrix3_expect->SetDirectElement(1,0,-0.021206);
+  matrix3_expect->SetDirectElement(2,0,-0.067125);
+
+  //Validate
+  ret = matrix_operator->IsEqual(matrix3_expect,matrix3,tolerance);
+
+  std::cout << "test_SolveLeastSquares()-------------------------------------------\n";
+  std::cout << "Overdetermined\n";
+  std::cout << "[expect]\n";
+  matrix3_expect->InternalPrint();
+  std::cout << "[result]\n";
+  matrix3->InternalPrint();
+
+
+  matrix1->Delete();
+  matrix2->Delete();
+  matrix3->Delete();
+  matrix3_expect->Delete();
+
+  //Welldetermined
+
+ matrix1       = (vtkpxMatrix *) vtkpxMatrix::New();
+ matrix2       = (vtkpxMatrix *) vtkpxMatrix::New();
+ matrix3       = (vtkpxMatrix *) vtkpxMatrix::New();
+ matrix3_expect= (vtkpxMatrix *) vtkpxMatrix::New();
+
+  //Set matrix1
+  matrix1->Zeros(3,3);
+  matrix1->SetDirectElement (0,0, 12.0);  matrix1->SetDirectElement (0,1,-51.0);  matrix1->SetDirectElement (0,2,  4.0);
+  matrix1->SetDirectElement (1,0,  6.0);  matrix1->SetDirectElement (1,1,167.0);  matrix1->SetDirectElement (1,2,-69.0);
+  matrix1->SetDirectElement (2,0, -4.0);  matrix1->SetDirectElement (2,1, 24.0);  matrix1->SetDirectElement (2,2,-41.0);
+  //Set matrix2
+  matrix2->Zeros(3,1);
+  matrix2->SetDirectElement(0,0,2.0);
+  matrix2->SetDirectElement(1,0,2.0);
+  matrix2->SetDirectElement(2,0,2.0);
+  //Initialize matrix3
+  matrix3->Zeros(3,1);
+
+  //
+  matrix1->SolveLeastSquares(matrix2,matrix3);
+
+  //Set expect
+  //Calculated by simple "division(=\)" operation of Octave
+  matrix3_expect->Zeros(3,1);
+  matrix3_expect->SetDirectElement(0,0,0.101207);
+  matrix3_expect->SetDirectElement(1,0,-0.020965);
+  matrix3_expect->SetDirectElement(2,0,-0.070927);
+
+  //Validate
+  ret = matrix_operator->IsEqual(matrix3_expect,matrix3,tolerance);
+
+
+  std::cout << "Welldetermined\n";
+  std::cout << "[expect]\n";
+  matrix3_expect->InternalPrint();
+  std::cout << "[result]\n";
+  matrix3->InternalPrint();
+
+  matrix1->Delete();
+  matrix2->Delete();
+  matrix3->Delete();
+  matrix3_expect->Delete();
+  
+  //Underdetermined
+  matrix1       = (vtkpxMatrix *) vtkpxMatrix::New();
+  matrix2       = (vtkpxMatrix *) vtkpxMatrix::New();
+  matrix3       = (vtkpxMatrix *) vtkpxMatrix::New();
+  matrix3_expect= (vtkpxMatrix *) vtkpxMatrix::New();
+
+  //Set matrix1
+  matrix1->Zeros(5,5);
+  matrix1->SetDirectElement (0,0, 12.0);  matrix1->SetDirectElement (0,1,-51.0);  matrix1->SetDirectElement (0,2,  4.0);  
+  matrix1->SetDirectElement (0,3,  7.0);matrix1->SetDirectElement   (0,4,-3.0);
+  matrix1->SetDirectElement (1,0,  6.0);  matrix1->SetDirectElement (1,1,167.0);  matrix1->SetDirectElement (1,2,-69.0);
+  matrix1->SetDirectElement (1,3,  10.0);matrix1->SetDirectElement  (1,4,-1.5);
+  matrix1->SetDirectElement (2,0, -4.0);  matrix1->SetDirectElement (2,1, 24.0);  matrix1->SetDirectElement (2,2,-41.0);
+  matrix1->SetDirectElement (2,3,  2.0);matrix1->SetDirectElement   (2,4,-3.0);
+
+  //Set matrix2
+  matrix2->Zeros(5,1);
+  matrix2->SetDirectElement(0,0,2.0);
+  matrix2->SetDirectElement(1,0,2.0);
+  matrix2->SetDirectElement(2,0,2.0);
+  matrix2->SetDirectElement(3,0,0.0);
+  matrix2->SetDirectElement(4,0,0.0);
+  //Initialize matrix3
+  matrix3->Zeros(5,1);
+
+  //
+   matrix1->SolveLeastSquares(matrix2,matrix3);
+
+  //Set expect
+  matrix3_expect->Zeros(5,1);
+  matrix3_expect->SetDirectElement(0,0,0.101207);
+  matrix3_expect->SetDirectElement(1,0,-0.020965);
+  matrix3_expect->SetDirectElement(2,0,-0.070927);
+  matrix3_expect->SetDirectElement(3,0,0);
+  matrix3_expect->SetDirectElement(4,0,0);
+
+  std::cout << "Underdetermined\n";
+  std::cout << "[expect]\n";
+  matrix3_expect->InternalPrint();
+  std::cout << "[result]\n";
+  matrix3->InternalPrint();
+
+  matrix1->Delete();
+  matrix2->Delete();
+  matrix3->Delete();
+  matrix3_expect->Delete();
+
+  return ret;
+}
+
+//---------------------------------------
+// test vtkpxMatrix::SolveLinearSystem
+//---------------------------------------
+int test_vtkpxMatrix::SolveLinearSystem()
+{
+  int ret;
+  ret = 0;
+
+  vtkpxMatrix *matrix_operator = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix1       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix2       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix3       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix3_expect= (vtkpxMatrix *) vtkpxMatrix::New();
+
+  matrix1->Zeros(3,3);
+  matrix1->SetDirectElement (0,0, 12.0);  matrix1->SetDirectElement (0,1,-51.0);  matrix1->SetDirectElement (0,2,  4.0);
+  matrix1->SetDirectElement (1,0,  6.0);  matrix1->SetDirectElement (1,1,167.0);  matrix1->SetDirectElement (1,2,-69.0);
+  matrix1->SetDirectElement (2,0, -4.0);  matrix1->SetDirectElement (2,1, 24.0);  matrix1->SetDirectElement (2,2,-41.0);
+  //Set matrix2
+  matrix2->Zeros(3,1);
+  matrix2->SetDirectElement(0,0,2.0);
+  matrix2->SetDirectElement(1,0,2.0);
+  matrix2->SetDirectElement(2,0,2.0);
+  //Initialize matrix3
+  matrix3->Zeros(3,1);
+
+  //
+  matrix1->SolveLinearSystem(matrix2,matrix3);
+
+  //Set expect
+  //Calculated by simple "division(=\)" operation of Octave
+  matrix3_expect->Zeros(3,1);
+  matrix3_expect->SetDirectElement(0,0,0.101207);
+  matrix3_expect->SetDirectElement(1,0,-0.020965);
+  matrix3_expect->SetDirectElement(2,0,-0.070927);
+
+  //Validate
+  ret = matrix_operator->IsEqual(matrix3_expect,matrix3,tolerance);
+
+
+  std::cout << "test_SolveLinearSystem---------------------------\n";
+  std::cout << "[expect]\n";
+  matrix3_expect->InternalPrint();
+  std::cout << "[result]\n";
+  matrix3->InternalPrint();
+
+  matrix1->Delete();
+  matrix2->Delete();
+  matrix3->Delete();
+  matrix3_expect->Delete();
+  matrix_operator->Delete();
+
+  return ret;
+}
+
+//---------------------------------------
+// Helper functions
+//---------------------------------------
+int test_vtkpxMatrix::InternalSolveSymmetricLinearSystem(int mode)
+{
+  int ret;
+  ret = 0;
+  vtkpxMatrix *matrix_operator = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix1       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix2       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix3       = (vtkpxMatrix *) vtkpxMatrix::New();
+  vtkpxMatrix *matrix3_expect= (vtkpxMatrix *) vtkpxMatrix::New();
+
+  matrix1->Zeros(3,3);
+  matrix1->SetDirectElement (0,0,  3.0);  matrix1->SetDirectElement (0,1,2.0);  matrix1->SetDirectElement (0,2,1.0);
+  matrix1->SetDirectElement (1,0,  2.0);  matrix1->SetDirectElement (1,1,2.0);  matrix1->SetDirectElement (1,2,1.0);
+  matrix1->SetDirectElement (2,0,  1.0);  matrix1->SetDirectElement (2,1,1.0);  matrix1->SetDirectElement (2,2,1.0);
+  //Set matrix2
+  matrix2->Zeros(3,1);
+  matrix2->SetDirectElement(0,0,2.4);
+  matrix2->SetDirectElement(1,0,0.2);
+  matrix2->SetDirectElement(2,0,1.2);
+  //Initialize matrix3
+  matrix3->Zeros(3,1);
+
+  //
+  char *tmp;
+  switch (mode){
+  case 0 :  matrix1->SolveLowerSymmetricLinearSystem(matrix2,matrix3);tmp = "Lower";break;
+  case 1 :  matrix1->SolveUpperSymmetricLinearSystem(matrix2,matrix3);tmp = "Upper";break;
+  default :  break;
+  }
+
+  //Set expect
+  //Calculated by simple "division(=\)" operation of Octave
+  matrix3_expect->Zeros(3,1);
+  matrix3_expect->SetDirectElement(0,0,2.2);
+  matrix3_expect->SetDirectElement(1,0,-3.2);
+  matrix3_expect->SetDirectElement(2,0,2.2);
+
+  //Validate
+  //  ret = matrix_operator->IsEqual(matrix3_expect,matrix3,tolerance);
+
+  std::cout << "test_" << tmp << "SymmetricLinearSystem---------------------------\n";
+  std::cout << "[expect]\n";
+  matrix3_expect->InternalPrint();
+  std::cout << "[result]\n";
+  matrix3->InternalPrint();
+
+  matrix1->Delete();
+  matrix2->Delete();
+  matrix3->Delete();
+  matrix3_expect->Delete();
+
+  return ret;
+}
+
+//---------------------------------------
+// Helper functions
+//---------------------------------------
+
+int test_vtkpxMatrix::SolveUpperSymmetricLinearSystem()
+{
+  int ret;
+  ret = 0;
+  ret = this->InternalSolveSymmetricLinearSystem(0);
+  return ret;
+}
+
+
+//---------------------------------------
+// Helper functions
+//---------------------------------------
+int test_vtkpxMatrix::SolveLowerSymmetricLinearSystem()
+{
+  int ret;
+  ret = 0;
+  ret = this->InternalSolveSymmetricLinearSystem(1);
+  return ret;
+}
+
+//--------------------------------------------
+// main part for testing vtkpxMatrix class
+//--------------------------------------------
+int main(int argc,char* argv[])
+{
+  int ret;
+  ret = 0;
+
+  test_vtkpxMatrix test;
+
+  ret = test.Add();                if (ret!=0) {std::cout << "test_Add() returns error "; return ret;}
+  ret = test.QRDecomposition();    if (ret!=0) {std::cout << "test_QRDecomposition() returns error "; return ret;}
+  ret = test.Q1Q2RDecomposition(); if (ret!=0) {std::cout << "test_Q1R2Decomposition() returns error "; return ret;}
+  ret = test.Invert();             if (ret!=0) {std::cout << "est_Invert() returns error "; return ret;}
+  ret = test.SolveLeastSquares();                           if (ret!=0) {std::cout << "test_SolveLeastSquares() returns error "; return ret;}
+  ret = test.SolveLinearSystem();                           if (ret!=0) {std::cout << "test_SolveLinearSystem() returns error "; return ret;}
+  ret = test.SolveUpperSymmetricLinearSystem();             if (ret!=0) {std::cout << "test_SolveUpperSymmetricLinearSystem() returns error "; return ret;}
+  ret = test.SolveLowerSymmetricLinearSystem();             if (ret!=0) {std::cout << "test_SolveLowerSymmetricLinearSystem() returns error "; return ret;}
+
+  if (ret==0)
+    std::cout << "All Tests Passed\n";
+
+  return ret;
+}
+
+
diff --git a/bioimagesuite30_src/Testing/Test_vtkpxOptimizer.cpp b/bioimagesuite30_src/Testing/Test_vtkpxOptimizer.cpp
new file mode 100644
index 0000000..9260322
--- /dev/null
+++ b/bioimagesuite30_src/Testing/Test_vtkpxOptimizer.cpp
@@ -0,0 +1,67 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//
+// .Description
+//  Test program for vtkpxOptimizer Class
+
+
+#include "bioimagesuite_settings.h"
+#include "vtkpxTestOptimizer.h"
+#include "test.h"
+
+
+int main(int argc,char* argv[])
+{
+  int ret;
+  ret = 0;
+
+  
+  vtkpxTestOptimizer* opt=vtkpxTestOptimizer::New();
+  opt->SetDimension(2);
+
+  opt->SetOptimizationMethodToConjugateGradient();
+  int ok=opt->Run();
+
+  fprintf(stdout,"Test 1 --> ok=%d\n",ok);
+
+  opt->SetOptimizationMethodToGradientDescent();
+  int ok1=opt->Run();
+
+  fprintf(stdout,"Test 2 --> ok=%d\n",ok);
+
+  if (ok && ok1)
+    {
+      std::cout << "All Tests Passed\n";
+      return 0;
+    }
+
+  return 1;
+
+}
+
+
diff --git a/bioimagesuite30_src/Testing/bisVersionTest.cpp b/bioimagesuite30_src/Testing/bisVersionTest.cpp
new file mode 100644
index 0000000..68df086
--- /dev/null
+++ b/bioimagesuite30_src/Testing/bisVersionTest.cpp
@@ -0,0 +1,128 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "bioimagesuite_settings.h"
+#include <itkVersion.h>
+#include <vtkVersion.h>
+#include <gdcmVersion.h>
+#include <tcl.h>
+#include <tk.h>
+
+
+int main(int argc, char* argv[])
+{
+  // Tcl
+  //
+  std::cout << std::endl;
+  std::cout << "-----------------------------------------------" << std::endl;
+  std::cout << "Tcl Version    = "
+            << TK_PATCH_LEVEL << std::endl;
+  std::cout << "Major Version  = "
+            << TK_MAJOR_VERSION << std::endl;
+  std::cout << "Minor Version  = "
+            << TK_MINOR_VERSION << std::endl;
+  std::cout << "Patch Version  = "
+            << TK_RELEASE_SERIAL << std::endl;
+
+
+  // Tk
+  //
+  std::cout << std::endl;
+  std::cout << "-----------------------------------------------" << std::endl;
+  std::cout << "Tk Version     = "
+            << TCL_PATCH_LEVEL << std::endl;
+  std::cout << "Major Version  = "
+            << TCL_MAJOR_VERSION << std::endl;
+  std::cout << "Minor Version  = "
+            << TCL_MINOR_VERSION << std::endl;
+  std::cout << "Patch Version  = "
+            << TCL_RELEASE_SERIAL << std::endl;
+
+
+  // GDCM
+  //
+  std::cout << std::endl;
+  std::cout << "-----------------------------------------------" << std::endl;
+  std::cout << "GDCM Version   = "
+            << gdcm::Version::GetVersion() << std::endl;
+  std::cout << "Major Version  = "
+            << gdcm::Version::GetMajorVersion()  << std::endl;
+  std::cout << "Minor Version  = "
+            << gdcm::Version::GetMinorVersion()  << std::endl;
+  std::cout << "Patch Version  = "
+            << gdcm::Version::GetBuildVersion()  << std::endl;
+
+
+  // ITK
+  // 
+  std::cout << std::endl;
+  std::cout << "-----------------------------------------------" << std::endl;
+  std::cout << "ITK Version    = " 
+            << itk::Version::GetITKVersion()       << std::endl;
+  std::cout << "Major Version  = " 
+            << itk::Version::GetITKMajorVersion()  << std::endl;
+  std::cout << "Minor Version  = " 
+            << itk::Version::GetITKMinorVersion()  << std::endl;
+  std::cout << "Patch Version  = " 
+            << itk::Version::GetITKBuildVersion()  << std::endl;
+  std::cout << "Source Version = " 
+            << itk::Version::GetITKSourceVersion() << std::endl;
+
+
+  // VTK
+  // 
+  std::cout << std::endl;
+  std::cout << "-----------------------------------------------" << std::endl;
+  std::cout << "VTK Version    = " 
+            << vtkVersion::GetVTKVersion()       << std::endl;
+  std::cout << "Major Version  = " 
+            << vtkVersion::GetVTKMajorVersion()  << std::endl;
+  std::cout << "Minor Version  = " 
+            << vtkVersion::GetVTKMinorVersion()  << std::endl;
+  std::cout << "Patch Version  = " 
+            << vtkVersion::GetVTKBuildVersion()  << std::endl;
+  std::cout << "Source Version = " 
+            << vtkVersion::GetVTKSourceVersion() << std::endl;
+  std::cout << std::endl;
+
+  std::cout << std::endl;
+  std::cout << "-----------------------------------------------" << std::endl;
+#ifdef BIOIMAGESUITE3_USE_CUDA
+  std::cout << "CUDA Version    = " << BIOIMAGESUITE3_CUDA_VERSION << std::endl;
+#else
+  std::cout << "CUDA Version    = NONE " << std::endl; 
+#endif
+
+
+  // BIOIMAGESUITE
+  std::cout << std::endl;
+  std::cout << "-----------------------------------------------" << std::endl;
+  std::cout << "BioImage Suite Package Version    = " << BIOIMAGESUITE_PACK_VERSION  << std::endl;
+
+  return 0;
+}
+
diff --git a/bioimagesuite30_src/Testing/bisruntests.bat.in b/bioimagesuite30_src/Testing/bisruntests.bat.in
new file mode 100644
index 0000000..df93c00
--- /dev/null
+++ b/bioimagesuite30_src/Testing/bisruntests.bat.in
@@ -0,0 +1,87 @@
+ at echo off
+REM  --------------------------------------------------------------------------------------
+REM  This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+REM  --------------------------------------------------------------------------------------
+REM  Arguments (all optional)
+REM  First = Type either Experiemental or Nightly
+REM  Second = DISPLAY setting
+REM  Third = Options on tests (e.g. 1-2)
+
+
+
+REM bis_fix_script_begin
+SET TST_BINARY_DIR=@BIOIMAGESUITE3_BINARY_DIR_BAT@
+SET TST_SOURCE_DIR=@BIOIMAGESUITE3_SOURCE_DIR_BAT@
+SET TST_TEST_DIR=@BIOIMAGESUITE3_TEST_DIR_BAT@
+SET TST_TMP_DIR=@BIOIMAGESUITE3_TESTING_TEMPDIR_BAT@
+SET BINPATH=@EXECUTABLE_OUTPUT_PATH_BAT@
+SET SVNUPDATE=@BIOIMAGESUITE3_TESTING_DOSVNUPDATE@
+SET CLEAN=@BIOIMAGESUITE3_TESTING_DOCLEANBUILD@
+SET CTEST=@CMAKE_CTEST_COMMAND_BAT@
+SET SVN=@SVNCOMMAND_BAT@
+REM bis_fixscript_end
+
+SET TESTMODE=Experimental
+SET TESTSTORUN=""
+IF NOT (%1)==() SET TESTMODE=%1
+IF NOT (%2)==() SET TESTSTORUN=-I %2 
+IF NOT (%TST_TMP_DIR%) == (BIOIMAGESUITE3_TESTING_TEMPDIR-NOTFOUND) GOTO TAG0
+
+SET TST_TMP_DIR=""
+
+:TAG0
+
+SET BISTEMP=%TST_TMP_DIR%
+
+echo ---------------------------------------------------------------------------
+echo Beginning tests 
+echo --
+
+IF NOT %SVNUPDATE% == ON GOTO STEP1
+    echo Updating Test Data at %TST_TEST_DIR%
+    echo --
+
+    cd %TST_TEST_DIR%
+    %SVN% cleanup
+    %SVN% update
+
+    echo Updating Source Tree at %TST_SOURCE_DIR% 
+    echo --
+    cd %TST_SOURCE_DIR%
+    %SVN% cleanup
+    %SVN% update
+
+:STEP1
+
+cd %TST_BINARY_DIR%
+
+if NOT (%TESTMODE%) == (Nightly)  SET TESTMODE=Experimental
+
+
+echo ---------------------------------------------------------------------------
+echo Beginning %CTEST% Testing as *%TESTMODE%* 
+echo Flags=*%TESTSTORUN%* at %TST_BINARY_DIR%
+echo ---------------------------------------------------------------------------
+echo on
+
+%CTEST% -D %TESTMODE%Start
+echo --------------------
+%CTEST% -D %TESTMODE%Configure -VV
+echo --------------------
+%CTEST% -D %TESTMODE%Build -VV
+echo --------------------
+%CTEST% -D %TESTMODE%Test %TESTSTORUN%
+echo --------------------
+%CTEST% -D %TESTMODE%Submit
+
+echo ---------------------------------------------------------------------------
+echo Done
+echo ---------------------------------------------------------------------------
+
+IF  (%BISTEMP%) == () GOTO END
+IF  (%BISTEMP%) == ("") GOTO END
+
+echo Should be Deleting %BISTEMP%
+echo Calling something like del /f /s  %BISTEMP%
+
+:END
\ No newline at end of file
diff --git a/bioimagesuite30_src/Testing/bisruntests.sh.in b/bioimagesuite30_src/Testing/bisruntests.sh.in
new file mode 100644
index 0000000..9ebefa6
--- /dev/null
+++ b/bioimagesuite30_src/Testing/bisruntests.sh.in
@@ -0,0 +1,89 @@
+#!/bin/bash
+# --------------------------------------------------------------------------------------
+# This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+# --------------------------------------------------------------------------------------
+# Arguments (all optional)
+# First = Type either Experiemental or Nightly
+# Second = DISPLAY setting
+# Third = Options on tests (e.g. 1-2)
+
+#bis_fix_script_begin
+TST_BINARY_DIR=@BIOIMAGESUITE3_BINARY_DIR@
+TST_SOURCE_DIR=@BIOIMAGESUITE3_SOURCE_DIR@
+TST_TEST_DIR=@BIOIMAGESUITE3_TEST_DIR@
+TST_TMP_DIR=@BIOIMAGESUITE3_TESTING_TEMPDIR@
+BINPATH=@EXECUTABLE_OUTPUT_PATH@
+DISP=@BIOIMAGESUITE3_TESTING_DISPLAY@
+SVNUPDATE=@BIOIMAGESUITE3_TESTING_DOSVNUPDATE@
+CLEAN=@BIOIMAGESUITE3_TESTING_DOCLEANBUILD@
+CTEST=@CMAKE_CTEST_COMMAND@
+SVN=@SVNCOMMAND@
+#bis_fixscript_end
+
+TESTMODE=Experimental
+TESTSTORUN=""
+
+TESTMODE=$1
+TESTSTORUN=$3
+
+
+export BISTEMP=$TST_TMP_DIR
+
+if [ -n "$2" ]; then
+    DISP=$2
+fi
+
+
+if [ -n "$DISP" ]; then
+    export DISPLAY=$DISP
+fi
+
+echo "---------------------------------------------------------------------------"
+echo "Beginning tests DISPLAY=${DISPLAY} TEMP=$BISTEMP `date`"
+echo ""
+
+if [ $SVNUPDATE == "ON" ]; then
+
+    echo "Updating Test Data at ${TST_TEST_DIR}"; 
+    echo "";
+
+    cd ${TST_TEST_DIR}
+    ${SVN} cleanup
+    ${SVN} update
+
+    echo "Updating Source Tree at ${TST_SOURCE_DIR}"; echo "";
+    cd ${TST_SOURCE_DIR}
+    ${SVN} cleanup; 
+    ${SVN} update
+fi
+
+cd ${TST_BINARY_DIR}
+
+if [ "$TESTMODE" != "Nightly" ]; then
+    TESTMODE="Experimental"
+fi
+
+if [ "$TESTSTORUN" != "" ]; then
+    TESTSTORUN="-I $TESTSTORUN"
+fi 
+
+echo "---------------------------------------------------------------------------"
+echo "Beginning ${CTEST} Testing as *${TESTMODE}* "
+echo "Flags=*${TESTSTORUN}* at ${TST_BINARY_DIR}"; 
+echo "---------------------------------------------------------------------------"
+
+
+if [ "$CLEAN" == "ON" ]; then
+    make clean
+fi
+
+
+${CTEST} -D ${TESTMODE}Start
+${CTEST} -D ${TESTMODE}Configure -VV
+${CTEST} -D ${TESTMODE}Build -VV
+${CTEST} -D ${TESTMODE}Test ${TESTSTORUN}
+${CTEST} -D ${TESTMODE}Submit
+
+echo "---------------------------------------------------------------------------"
+echo "Done"
+
diff --git a/bioimagesuite30_src/Testing/test.h b/bioimagesuite30_src/Testing/test.h
new file mode 100644
index 0000000..74fa5f9
--- /dev/null
+++ b/bioimagesuite30_src/Testing/test.h
@@ -0,0 +1,34 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#define tolerance 0.01
+int MAIN__()
+{
+  return 0;
+}
+
+
diff --git a/bioimagesuite30_src/Utilities/CMakeLists.txt b/bioimagesuite30_src/Utilities/CMakeLists.txt
new file mode 100644
index 0000000..be7c123
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/CMakeLists.txt
@@ -0,0 +1,53 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+SUBDIRS(Doxygen)
+
+SET(KIT Doxygen)
+
+SET(KITLIBS )
+SET (KITSRCS )
+SET (KITEXTRAFILES)
+SET (KITSRCS 
+Doxygen/CMakeLists.txt
+Doxygen/doc_class2example.pl
+Doxygen/doc_cleanhtml.pl
+Doxygen/doc_codematch.pl
+Doxygen/doc_contributors.pl
+Doxygen/doc_header2doxygen.pl
+Doxygen/doc_index.pl
+Doxygen/doc_makeall.in
+Doxygen/doc_readme.txt
+Doxygen/doc_rmpath.pl
+Doxygen/doc_version.pl
+Doxygen/doxyfile.in
+Doxygen/doxygen.css
+Doxygen/footer.html
+Doxygen/header.html
+)
+
+bis_sourcelist("Utilities" ${KIT} ${FILELIST})
diff --git a/bioimagesuite30_src/Utilities/Doxygen/CMakeLists.txt b/bioimagesuite30_src/Utilities/Doxygen/CMakeLists.txt
new file mode 100644
index 0000000..7ea9113
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/CMakeLists.txt
@@ -0,0 +1,62 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#
+# Build the documentation
+#
+INCLUDE (${CMAKE_ROOT}/Modules/Documentation.cmake OPTIONAL)
+
+IF (BUILD_DOCUMENTATION)
+
+  #
+  # Configure the script and the doxyfile, then add target
+  #
+
+  CONFIGURE_FILE(
+    ${BIOIMAGESUITE3_SOURCE_DIR}/Utilities/Doxygen/doc_makeall.in
+    ${BIOIMAGESUITE3_SOURCE_DIR}/Utilities/Doxygen/doc_makeall.sh)
+
+  CONFIGURE_FILE(
+    ${BIOIMAGESUITE3_SOURCE_DIR}/Utilities/Doxygen/doxyfile.in
+    ${BIOIMAGESUITE3_SOURCE_DIR}/Utilities/Doxygen/doxyfile)
+
+  ADD_CUSTOM_TARGET(DoxygenDoc
+    ${BASH}
+    ${BIOIMAGESUITE3_SOURCE_DIR}/Utilities/Doxygen/doc_makeall.sh
+    )
+
+ENDIF (BUILD_DOCUMENTATION)
+
+#INCLUDE (${BIOIMAGESUITE3_SOURCE_DIR}/Utilities/Doxygen/LocalUserOptions.cmake OPTIONAL)
+
+#INSTALL_FILES(/lib/vtk/doxygen "\\.css$")
+#INSTALL_FILES(/lib/vtk/doxygen "\\.gif$")
+#INSTALL_FILES(/lib/vtk/doxygen "\\.html$")
+#INSTALL_FILES(/lib/vtk/doxygen "\\.pl$")
+#INSTALL_FILES(/lib/vtk/doxygen "\\.stop$")
+#INSTALL_FILES(/lib/vtk/doxygen .txt authors doc_readme)
+
diff --git a/bioimagesuite30_src/Utilities/Doxygen/doc_class2example.pl b/bioimagesuite30_src/Utilities/Doxygen/doc_class2example.pl
new file mode 100644
index 0000000..4aa57dd
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/doc_class2example.pl
@@ -0,0 +1,846 @@
+#!/usr/bin/env perl
+# Time-stamp: <2002-01-15 11:10:15 barre>
+#
+# Build cross-references between classes and examples
+#
+# barre : Sebastien Barre <sebastien at barre.nom.fr>
+#
+# 0.81 (barre) :
+#   - add --baselinedir d : use 'd' as baseline directory
+#   - add --baselineicon f: use 'f' as icon file to report that file has 
+#     baseline picture
+#   - add --baselinelink l: use 'l' as baseline link to picture
+#   - add --baselinelinksuffix s : suffix string to append
+#     to --baselinelink + filename
+#   - add --datamatch s : use string s to match any usage of data files
+#
+# 0.8 (barre) :
+#   - more robust code: comments are removed from files before parsing
+#     and several identifier per lines are now supported (at last).
+#   - add --datamatch s : use string s to match any usage of data files
+#   - add --dataicon f : use f as icon file to report that file makes use 
+#     of data files
+#
+# 0.74 (barre) :
+#   - use common build_page_doc proc
+#
+# 0.73 (barre) :
+#   - add --linksuffix s : suffix string to append to --link + filename
+#
+# 0.72 (barre) :
+#   - add --project name : project name, used to uniquify
+#   - add slightly changed the way --link are created
+#
+# 0.71 (barre) :
+#   - add .cpp and .cc extension to the C++ parser regexp
+#
+# 0.7 (barre) :
+#   - update to match the new VTK 4.0 tree
+#   - change default --dirs so that it can be launched from Utilities/Doxygen
+#   - change default --to so that it can be launched from Utilities/Doxygen
+#   - add Java support
+#   - add --label str : use string as label in class page
+#   - add --title str : use string as title in "Related Pages"
+#   - add --dirmatch str : use string to match the directory name holding files
+#   - add --unique str : use string as a unique page identifier (otherwise MD5)
+#
+# 0.6 (barre) :
+#   - the "class to example" page is now split in different pages
+#   - use --weight to increase or decrease the maximum weight of a page
+#
+# 0.55 (barre) :
+#   - change default --to to '../vtk-doxygen' to comply with Kitware's doxyfile
+#
+# 0.54 (barre) :
+#   - change doxygen command style from \ to @ to match javadoc, autodoc, etc.
+#
+# 0.53 (barre) :
+#   - change default --to to '../vtk-dox'
+#
+# 0.52 (barre) :
+#   - rename -l option to --link, add a parameter to preprend in front of
+#     the example location/filename.
+#
+# 0.51 (barre) :
+#   - fix O_TEXT flag problem
+#   - switch to Unix CR/LF format
+#
+# 0.5 (barre) :
+#   - removed version extraction feature (moved to another script)
+#
+# 0.4 (barre) :
+#   - change (warning) default --to to '../vtk2' because I ruined my own
+#     VTK distrib too many times :(
+#   - change (warning) --to is now a path to a destination directory, and
+#     no more a path to the destination doxygen file. The headers to update
+#     will logically be searched here, while the examples to process are
+#     searched in the directory where the script is launched
+#
+# 0.3 (barre)
+#   - add '--parser' option to use specific parser only
+#
+# 0.2 (barre)
+#   - use vtkVersion.h to fill the main page (@mainpage) with version/revision
+#     => comment/remove PROJECT_NUMBER from your doxygen config file (doxyfile)
+#   - add web URL to main page
+#   - fix small "uninitialized variable" warning
+#
+# 0.1 (barre)
+#   - first release (-l does not work for the moment)
+
+use Carp;
+use Data::Dumper;
+use Digest::MD5  qw(md5 md5_hex md5_base64);
+use Getopt::Long;
+use Fcntl;
+use File::Basename;
+use File::Find;
+use strict;
+
+my ($VERSION, $PROGNAME, $AUTHOR) = (0.81, $0, "Sebastien Barre");
+$PROGNAME =~ s/^.*[\\\/]//;
+print "$PROGNAME $VERSION, by $AUTHOR\n";
+
+# -------------------------------------------------------------------------
+# Defaults (add options as you want : "verbose" => 1 for default verbose mode)
+
+my %default = 
+  (
+   baselineicon => "pic.gif",
+   baselinelinksuffix => "",
+   dataicon => "paper-clip.gif",
+   dirmatch => "^Examples\$",
+   dirs => ["../.."],
+   label => "Examples",
+   limit => 20,
+   linksuffix => "",
+   project => "VTK",
+   store => "doc_VTK_class2examples.dox",
+   title => "Class To Examples",
+   to => "../../../VTK-doxygen",
+   unique => "e",
+   weight => 90000
+  );
+
+# -------------------------------------------------------------------------
+# Matchers and parsers :
+#
+# $eliminate_matcher : regexp matching the names of the 'fake' classes 
+#                      that shall be eliminated/ignored,
+# %parsers           : hash defining each parser by associating
+#                      parser_name => [filename_matcher, func1, func2].
+#  $parser_name      : language identifier (Tcl, C++, Python, etc.),
+#  $filename_matcher : regexp matching the filenames belonging to the language,
+# @$func1            : function called when a filename is matched,
+#                      - receives the contents of the file as a reference to a
+#                        string,
+#                      - modifies this contents by removing the comments.
+# @$func2            : function called when a filename is matched,
+#                      - receives the contents of the file as a reference to a
+#                        string (or the result of func1 if exists),
+#                      - returns an array of unique class names that have been 
+#                        recognized/matched in the file contents.
+
+my $eliminate_matcher = '^vtkCommand$';
+
+my %parsers = (
+               "Tcl" => ['\.tcl$', \&rm_tcl_comments, \&parse],
+               "C++" => ['\.c(xx|pp|c)$', \&rm_cpp_comments, \&parse],
+               "Java" => ['\.java$', \&rm_cpp_comments, \&parse],
+               "Python" => ['\.py$', \&rm_tcl_comments, \&parse]
+              );
+
+sub rm_tcl_comments {
+    my $ref = shift;
+    $$ref =~ s/#.*?$//gms;
+}
+
+sub rm_cpp_comments {
+    my $ref = shift;
+    $$ref =~ s/\/\*.*?\*\/|\/\/.*?$|#(include|define|if).*?$//gms;
+}
+
+sub rm_no_comments {
+    my $ref = shift;
+}
+
+# Parser (seems to work with all languages for the moment)
+
+sub unique {
+    my ($ref, %uniques) = (shift, ());
+    foreach my $item (@$ref) {
+        $uniques{$item}++;
+    }
+    return keys %uniques;
+}
+
+sub parse {
+    my $ref = shift;
+    my @matches = $$ref =~ /\b(vtk[A-Z0-9][A-Za-z0-9]+)[^"]/gms;
+    return unique(\@matches);
+}
+
+# -------------------------------------------------------------------------
+# Parse options
+
+my %args;
+# Getopt::Long::Configure("bundling");
+GetOptions (\%args, "help", "verbose|v", "baselinedir=s", "baselineicon=s", "datamatch=s", "baselinelink=s", "baselinelinksuffix=s", "dataicon=s", "dirmatch=s", "label=s", "limit=i", "link=s", "linksuffix=s", "project=s", "store=s", "title=s", "to=s", "unique=s", "weight=i", "parser=s@");
+
+my $available_parser = join(", ", keys %parsers);
+
+if (exists $args{"help"}) {
+    print <<"EOT";
+by $AUTHOR
+Usage : $PROGNAME [--help] [--verbose|-v] [--baselinedir path] [--baselineicon filename] [--baselinelink url] [--baselinelinksuffix url] [--datamatch string] [--dataicon filename] [--dirmatch string] [--label string] [--limit n] [--link url] [--linksuffix string] [--parser name] [--store file] [--title string] [--to path] [--weight n] [directories...]
+  --help          : this message
+  --verbose|-v    : verbose (display filenames/classes while processing)
+  --baselinedir d : use 'd' as baseline directory
+  --baselineicon f: use 'f' as icon file to report that file has baseline picture
+  --baselinelink l: use 'l' as baseline link to picture
+  --baselinelinksuffix s : suffix string to append to --baselinelink + filename
+  --datamatch s   : use string s to match any usage of data files
+  --dataicon f    : use 'f  as icon file to report that file makes use of data files
+  --dirmatch str  : use string to match the directory name holding files (default: $default{dirmatch})
+  --label str     : use string as label in class page (default: $default{label})
+  --limit n       : limit the number of examples per parser type (default: $default{limit})
+  --link path     : link to example files (and prepend path)
+  --linksuffix s  : suffix string to append to --link + filename
+  --title str     : use string as title in "Related Pages" (default: $default{title})
+  --parser name   : use specific parser only (available : $available_parser)
+  --project name  : project name, used to uniquify (default: $default{project})
+  --store file    : use 'file' to store xrefs (default: $default{store})
+  --to path       : use 'path' as destination directory (default : $default{to})
+  --unique str    : use string as a unique page identifier among "Class To..." pages (otherwise MD5) (default : $default{unique})
+  --weight n      : use 'n' as an approximation of the maximum page weight (default : $default{weight})
+
+Example:
+  $PROGNAME --verbose
+  $PROGNAME --dirmatch "^Testing$" --label "Tests" --title "Class To Tests" --store "doc_class2tests.dox" --unique "t"
+EOT
+    exit;
+}
+
+$args{"verbose"} = 1 if exists $default{"verbose"};
+$args{"baselinedir"} =~ s/[\\\/]*$// if exists $args{"baselinedir"};
+$args{"baselineicon"} = $default{"baselineicon"} 
+  if ! exists $args{"baselineicon"};
+$args{"baselinelink"} = $default{"baselinelink"} 
+  if ! exists $args{"baselinelink"} && exists $default{"baselinelink"};
+$args{"baselinelink"} =~ s/[\\\/]*$// if exists $args{"baselinelink"};
+$args{"baselinelinksuffix"} = $default{"baselinelinksuffix"} 
+  if ! exists $args{"baselinelinksuffix"};
+$args{"dataicon"} = $default{"dataicon"} if ! exists $args{"dataicon"};
+$args{"dirmatch"} = $default{"dirmatch"} if ! exists $args{"dirmatch"};
+$args{"label"} = $default{"label"} if ! exists $args{"label"};
+$args{"limit"} = $default{"limit"} if ! exists $args{"limit"};
+$args{"link"} = $default{"link"} if ! exists $args{"link"} && exists $default{"link"};
+$args{"link"} =~ s/[\\\/]*$// if exists $args{"link"};
+$args{"linksuffix"} = $default{"linksuffix"} if ! exists $args{"linksuffix"};
+$args{"project"} = $default{"project"} if ! exists $args{"project"};
+$args{"store"} = $default{"store"} if ! exists $args{"store"};
+$args{"title"} = $default{"title"} if ! exists $args{"title"};
+$args{"to"} = $default{"to"} if ! exists $args{"to"};
+$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"};
+$args{"unique"} = $default{"unique"} if ! exists $args{"unique"};
+$args{"weight"} = $default{"weight"} if ! exists $args{"weight"};
+
+# Select parsers
+
+my @parsers;
+if (exists $args{"parser"}) {
+    foreach my $parser (@{$args{"parser"}}) {
+        if (exists $parsers{$parser}) {
+            push @parsers, $parser;
+        } else {
+            carp "$PROGNAME: unknown parser : $parser\n";
+        }
+    }
+} else {
+    @parsers = keys %parsers;
+}
+    
+my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i);
+my $open_file_as_text = $os_is_win ? O_TEXT : 0;
+my $start_time = time();
+
+# -------------------------------------------------------------------------
+# Collect unique non-intersecting (top) examples' directories recursively
+# Save current path (pwd) to avoid the ::prune bug
+
+print "Collecting files...\n";
+
+push @ARGV, @{$default{"dirs"}} if !@ARGV;
+my (%seen, @dirs);
+
+my $cwd = Cwd::cwd();
+
+foreach my $file (@ARGV) {
+    find sub { 
+        if (-d $_ && 
+            $_ ne "CVS" && 
+            basename($File::Find::name) =~ m/$args{"dirmatch"}/i) {
+            # my ($dev, $ino) = stat $_;
+            push @dirs, $File::Find::name;
+            # if ! $seen{$dev, $ino}++;
+            # once we are in a "examples directory", don't descend anymore
+            $File::Find::prune = 1;
+        }
+    }, $file;
+}
+
+chdir($cwd);
+
+# -------------------------------------------------------------------------
+# Collect files within directories recursively
+
+my @files;
+foreach my $dir (@dirs) {
+    find sub {
+        push @files, $File::Find::name if -f $_;
+    }, $dir;
+}
+
+# -------------------------------------------------------------------------
+# Select unique files matching available parsers
+
+my @parsable;
+foreach my $parser (@parsers) {
+    foreach my $file (@files) {
+        if ($file =~ m/$parsers{$parser}->[0]/) {
+            # my ($dev, $ino) = stat $file;
+            push @parsable, $file;
+            # if ! $seen{$dev, $ino}++;
+        }
+    }
+}
+
+ at parsable = sort @parsable;
+
+print " => ", scalar @parsable, " file(s) collected in ", time() - $start_time, " s.\n";
+
+# -------------------------------------------------------------------------
+# Parse files and build xref
+
+# %xref is a hash : xref{$class}{$parser}{$file}
+# Ex: xref{"vtkPoints"}{"Tcl"}{"examplesTcl/foo.tcl"}
+#     xref{"vtkPoints"}{"Tcl"}{"graphics/examplesTcl/bar.tcl"}
+#     xref{"vtkNormals"}{"C++"}{"test.cxx"}
+
+my %xref;
+
+# %shorter_filename is a hash associating a filename to its shorter 
+# counterpart where any leading component matching the name of a directory
+# being browsed have been removed.
+
+my %shorter_filename;
+
+# %use_data is a hash associating a filename to a flag (1) when the
+# file makes use of data files (i.e. the contents of the file matches
+# $args{"datamatch"}). 
+
+my %use_data;
+
+# %baseline_picture is a hash associating a filename to the relative path
+# to its baseline picture (relative to --baselinedir). 
+
+my %baseline_picture;
+
+print "Parsing files...\n";
+
+my $intermediate_time = time();
+
+# slurp mode
+
+my $oldslurp = $/;
+undef $/;
+
+foreach my $filename (@parsable) {
+
+    # Read entire file into an array of lines
+
+    sysopen(FILE, $filename, O_RDONLY|$open_file_as_text)
+      or croak "$PROGNAME: unable to open $filename\n";
+    my $file = <FILE>;
+    close(FILE);
+
+    # Submit the contents of the file to the corresponding parser
+
+    foreach my $parser (@parsers) {
+        if ($filename =~ m/$parsers{$parser}->[0]/) {
+            $parsers{$parser}->[1]->(\$file);
+            my @classes = $parsers{$parser}->[2]->(\$file);
+            printf("%7s: %2d | ", $parser, scalar @classes)
+              if exists $args{"verbose"};
+            #print "[", join(", ", @classes), "]"  if exists $args{"verbose"};
+            if (@classes) {
+                $shorter_filename{$filename} = $filename;
+                # print "(", join(", ", sort @classes), ") " if @classes;
+                foreach my $class (@classes) {
+                    $xref{$class}{$parser}{$filename}++;
+                }
+            }
+        }
+    }
+    print "=> ", $filename, "\n" if exists $args{"verbose"};
+
+    # Shorten filename if it has been added
+
+    if (exists $shorter_filename{$filename}) {
+        foreach my $dir (@ARGV) {
+            last if $shorter_filename{$filename} =~ s/$dir//;
+        }
+
+        # Check for baseline picture
+
+        if (exists $args{"baselinedir"}) {
+            my ($name, $dir, $ext) = 
+              fileparse($shorter_filename{$filename}, '\..*');
+            my @dirs = split('/', $dir);
+            my $pic = $dirs[1] . "/$name.png";
+            $baseline_picture{$filename} = $pic 
+              if -e $args{"baselinedir"} . "/$pic";
+        }
+    }
+    
+    # Check for data
+    
+    $use_data{$filename} = 1 
+      if exists $args{"datamatch"} && $file =~ m/$args{"datamatch"}/ms;
+}
+
+$/ = $oldslurp;
+
+print " => ", scalar @parsable, " file(s) parsed in ", time() - $intermediate_time, " s.\n";
+
+# -------------------------------------------------------------------------
+# Eliminate some 'fake' classes
+
+print "Eliminating some classes...\n";
+
+$intermediate_time = time();
+my @eliminated = ();
+
+foreach my $class (keys %xref) {
+    if ($class =~ m/$eliminate_matcher/) {
+        print "   $class\n" if exists $args{"verbose"};
+        delete($xref{$class});
+        push @eliminated, $class;
+    }
+}
+
+print " => ", scalar @eliminated, " class(es) eliminated (", join(", ", @eliminated), ") in ", time() - $intermediate_time, " s.\n";
+
+# -------------------------------------------------------------------------
+# We need to locate the C++ header of each class to add a link from
+# that header to the example page. We also remove orphan classes with
+# no headers.
+
+# %headers is a hash associating a class name to the location of its header.
+#   ex: $headers{"vtkPoints"} = "Common/vtkPoints.h"
+# %headers_not_found is a hash associating a class name to a flag that is
+#   true (1) if the location of its header has not been found.
+
+print "Locating headers to update...\n";
+
+$intermediate_time = time();
+my (%headers, %headers_not_found);
+
+# Let's state that no headers have been found at the moment
+
+foreach (keys %xref) {
+    $headers_not_found{$_} = 1;
+}
+my $headers_not_found_nb = scalar keys %headers_not_found;
+
+$cwd = Cwd::cwd();
+
+find sub { 
+    if ($headers_not_found_nb == 0) {
+        # All headers have been found, let's stop descending the tree
+        $File::Find::prune = 1;
+
+    } elsif (-f $_ && $_ =~ /^(vtk[A-Z0-9][A-Za-z0-9]+)\.h$/) {
+        # A class header has been found, let's check if it matches one pf
+        # the class in xref
+        my $class = $1;
+        if (exists $headers_not_found{$class}) {
+            print "   $class : $File::Find::name\n" if exists $args{"verbose"};
+            $headers{$class} = $File::Find::name;
+            $headers_not_found_nb--;
+            delete($headers_not_found{$class});
+        }
+    }
+}, $args{"to"};
+
+chdir($cwd);
+
+# Collect these classes that have not been associated to a header and
+# remove them from xref.
+
+my @still_not_found = keys %headers_not_found;
+foreach my $not_found (@still_not_found) {
+    print "   $not_found : not found (removed)\n" if exists $args{"verbose"};
+    delete($xref{$not_found});
+}
+
+print " => ", scalar keys %headers, " found, ", scalar @still_not_found, " orphan class(es) removed (", join(", ", @still_not_found), ") in ", time() - $intermediate_time, " s.\n";
+
+# -------------------------------------------------------------------------
+# Build the page summary documentation
+
+# $indent is the indentation string
+
+my $indent = "    ";
+
+# @words is the array of words to document
+
+my @words = sort keys %xref;
+
+# $header is the Doxygen string summarizing what has been documented as well
+# as the credits.
+
+my $header;
+my (@summary, @credits, @legend);
+
+push @summary, 
+  "  - " . scalar @words . " class(es) in " . 
+  scalar @parsable . " file(s) from directories matching \@c " . $args{"dirmatch"} . " on " . localtime();
+
+push @summary,
+  "  - " . scalar @parsers . " parser(s) : [" . join(", ", @parsers) . "]";
+
+push @summary, 
+  "  - at most " . $args{"limit"} . " file(s) per parser";
+
+push @credits, 
+  "\@version $VERSION",
+  "\@author \@c $PROGNAME, by $AUTHOR";
+
+$header = $indent . join("\n$indent", @summary) . "\n\n" .
+  $indent . join("\n$indent", @credits) . "\n\n";
+
+my $footer;
+
+if (exists $args{"datamatch"}) {
+    push @legend,
+    "- <img src='" . $args{"dataicon"} . "' align='top'> : the corresponding file uses data files.";
+    # hack so that the image is automatically copied to the doc dir
+    $footer .= " \@image html " . $args{"dataicon"} . "\n";
+}
+
+if (exists $args{"baselinedir"}) {
+    push @legend,
+    "- <img src='" . $args{"baselineicon"} . "' align='top'> : the corresponding file has a baseline picture (click to display)";
+    # hack so that the image is automatically copied to the doc dir
+    $footer .= " \@image html " . $args{"baselineicon"} . "\n";
+}
+
+if (scalar @legend) {
+    unshift @legend, "\@par Legend:";
+    $header .= $indent . join("\n$indent", @legend) . "\n\n";
+}
+
+# -------------------------------------------------------------------------
+# Index to class
+
+print "Building page doc...\n";
+
+# $prefix is a unique prefix that is appended to each link
+
+my $prefix = "c2_" . $args{"project"} . "_";
+if (exists $args{"unique"}) {
+    $prefix .= $args{"unique"};
+} else {
+    $prefix .= md5_hex($args{"label"} . $args{"title"});
+}
+$prefix = lc($prefix);
+
+# word_section_name returns the short string describing a word section
+
+sub word_section_name {
+    my ($word) = @_;
+    return "\@anchor ${prefix}_$word\n$indent$word";
+}
+    
+# word_section_doc returns the doxygen doc for a word
+
+sub word_section_doc {
+    my ($word) = @_;
+    my @temp;
+    foreach my $parser (sort keys %{$xref{$word}}) {
+        push @temp, "  - $parser";
+        my $count = 0;
+        # @files if the set of files found for that class by that parser
+        my @files = sort keys %{$xref{$word}{$parser}};
+        foreach my $file (@files) {
+            my $has_data;
+            $has_data = ' @htmlonly <img src="' . $args{"dataicon"} . '" align="top"> @endhtmlonly' if exists $use_data{$file};
+            my $has_baseline_picture;
+            $has_baseline_picture = ' @htmlonly <a href="' . $args{"baselinelink"} . '/' . $baseline_picture{$file} . $args{"baselinelinksuffix"} . '"><img src="' . $args{"baselineicon"} . '" align="top" border="0"></a> @endhtmlonly' if exists $baseline_picture{$file};
+            last if ++$count > $args{"limit"};
+            if (exists $args{"link"}) {
+                push @temp, 
+                '    - @htmlonly <TT><A href="' . $args{"link"} .  
+                  $shorter_filename{$file} . $args{"linksuffix"} . '">@endhtmlonly ' . $shorter_filename{$file} . 
+                    '@htmlonly</A></TT> @endhtmlonly ' . 
+                      $has_data . $has_baseline_picture;
+            } else {
+                push @temp, "    - \@c $shorter_filename{$file} $has_data $has_baseline_picture";
+            }
+        }
+    }
+    return join("\n$indent", @temp) . "\n";
+}
+
+# word_section_alpha returns the single alpha char corresponding to that
+# word's section.
+
+sub word_section_alpha {
+    my ($word) = @_;
+    $word =~ /^vtk(\w)/;
+    return $1;
+}
+
+my $page_doc = build_page_doc($indent,
+                              $args{"title"},
+                              \@words, 
+                              $prefix, 
+                              \&word_section_name, 
+                              \&word_section_doc,
+                              \&word_section_alpha,
+                              $header,
+                              $footer,
+                              $args{"to"} . "/" . $args{"store"});
+
+print join("\n", @summary), "\n => in ", time() - $intermediate_time, " s.\n";
+
+# -------------------------------------------------------------------------
+# Update class headers (add a link from the class header to the example page).
+# Do not update if the section is already there.
+
+print "Updating headers...\n";
+
+$intermediate_time = time();
+my $updated_nb = 0;
+
+foreach my $class (@words) {
+
+    print "   $class => " . $headers{$class} . "\n" if exists $args{"verbose"};
+
+    sysopen(HEADER, $headers{$class}, O_RDONLY|$open_file_as_text)
+      or croak "$PROGNAME: unable to open " . $headers{$class} . "\n";
+    
+    # Search for the documentation block (@class ...)
+
+    my @dest = ();
+    my $line;
+    while ($line = <HEADER>) {
+        push @dest, $line;
+        last if $line =~ /\s\@class\s+$class/;
+    }
+
+    # Search for the end of the block (*/), and check if the xref is not
+    # already there (@par      $args{"label"})
+
+    if (defined $line) {
+        while ($line = <HEADER>) {
+            last if $line =~ /^\*\// || $line =~ /^\s*\@par\s+$args{"label"}:\s*$/;
+            push @dest, $line;
+        }
+
+        # If the example section was not found, insert the xref to the
+        # example page, read the rest of the file, and overwrite the
+        # header
+
+        if (defined $line && $line =~ /^\*\//) {
+            push @dest, "\n    \@par      " . $args{"label"} . ":\n",
+                    "              \@ref ${prefix}_$class \"$class (" . $args{"label"} . ")\"\n",
+                        $line;
+            while ($line = <HEADER>) {
+                push @dest, $line;
+            }
+            close(HEADER);
+            sysopen(HEADER, $headers{$class}, 
+                    O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+              or croak "$PROGNAME: unable to open " . $headers{$class} . "\n";
+            print HEADER @dest;
+            $updated_nb++;
+        } 
+    }
+    close(HEADER);
+}
+
+print " => $updated_nb header(s) updated in ", time() - $intermediate_time, " s.\n";
+
+print "Finished in ", time() - $start_time, " s.\n";
+
+
+# -------------------------------------------------------------------------
+
+sub build_page_doc {
+
+    # $indent is the indentation string
+    # $rwords is a reference to the array of words to document
+    # $prefix is a unique prefix that is appended to each link
+    # word_section_name returns the short string describing a word section
+    # word_section_doc returns the doxygen doc for a word
+    # word_section_alpha returns the single alpha char corresponding to that
+    # word's section.
+    # $header is the Doxygen string summarizing what has been documented as 
+    # well as the credits.
+    # $footer is a Doxygen string appended to each the resulting page
+    # $destination_file is the name of the file where this page should be
+    # written to.
+
+    my ($ident, $title, $rwords, $prefix, $rword_section_name, $rword_section_doc, $rword_section_alpha, $header, $footer, $destination_file) = @_;
+
+    # %words_doc is a hash associating a word to its Doxygen doc (string)
+
+    my %words_doc;
+
+    # %sections_words is a hash associating a section (alphabetical letter) to
+    # an array of words belonging to that section.
+    #   Ex: $sections_words{"C"} => ("contour", "cut")
+    # %sections_weight is a hash associating a section to its weight (the sum 
+    # of the weights of each word belonging to that section).
+    # @sections is the array holding the name of all sections
+
+    my (%sections_words, %sections_weight, @sections);
+
+    # $navbar is the Doxygen string describing the sections' navigation bar
+    
+    my $navbar;
+    
+    my $intermediate_time = time();
+    
+    # Browse each word
+
+    foreach my $word (@$rwords) {
+
+        my @temp;
+        push @temp, &$rword_section_name($word), &$rword_section_doc($word);
+        $words_doc{$word} = $indent . join("\n$indent", @temp) . "\n";
+
+        # Update section(s) and section(s) weight(s)
+
+        my $section = &$rword_section_alpha($word);
+        push @{$sections_words{$section}}, $word;
+        $sections_weight{$section} += length($words_doc{$word});
+        
+        print " => ", $word, "\n" if exists $args{"verbose"};
+    }
+
+    print " => ", scalar @$rwords, " words(s) documented in ", time() - $intermediate_time, " s.\n";
+    
+    @sections = sort keys %sections_words;
+
+    # Build the navbar
+    
+    my @temp;
+    foreach my $section (@sections) {
+        push @temp, "\@ref ${prefix}_section_$section \"$section\"";
+    }
+    $navbar = "$indent\@par Navigation: \n$indent\[" . 
+      join(" | ", @temp) . "]\n";
+
+    # Add the (approximate) weight of the (header + navbar) to each section
+
+    my $total_weight = 0;
+    my $header_weight = length($indent) + 24 + length($navbar);
+
+    foreach my $section (@sections) {
+        $sections_weight{$section} += $header_weight;
+        $total_weight += $sections_weight{$section};
+    }
+
+    if (exists $args{"verbose"}) {
+        foreach my $section (@sections) {
+            printf("\t- %s : %6d\n", $section, $sections_weight{$section});
+        }
+    }
+
+    print " => total weight is $total_weight in ", scalar @sections, " section(s)\n";
+
+    print " => mean is ", int($total_weight / scalar @sections), ")\n"
+      if scalar @sections;
+
+    # Compute the alphabetical groups by joining sections depending on weights
+
+    print "Computing alphabetical group(s)/page(s)...\n";
+
+    # %groups is a hash associating a group id (int) to an array of sections 
+    # namesbelonging to that group.
+    #   Ex: $groups{"0"} => ("A", "B", "C")
+    # %groups_weight is a hash associating a group id to its weight (the sum
+    # of the weights of each section belonging to that group).
+
+    my (%groups, %groups_weight);
+
+    my $groupid = 0;
+
+    # Remove a section one by one, and put it in a group until the group if 
+    # full,then create a next group, etc., until the sections are exhausted.
+
+    my @sections_temp = @sections;
+    while (@sections_temp) {
+        $groups_weight{$groupid} = $sections_weight{$sections_temp[0]};
+        push @{$groups{$groupid}}, shift @sections_temp;
+        while (@sections_temp && 
+               ($groups_weight{$groupid} +$sections_weight{$sections_temp[0]}) 
+               <= $args{"weight"}) {
+            $groups_weight{$groupid} += $sections_weight{$sections_temp[0]};
+            push @{$groups{$groupid}}, shift @sections_temp;
+        }
+        $groupid++;
+    }
+
+    if (exists $args{"verbose"}) {
+        foreach my $groupid (sort {$a <=> $b} keys %groups) {
+            printf("\t- %02d (weight: %7d) : %s\n", $groupid, 
+                   $groups_weight{$groupid}, join(", ", @{$groups{$groupid}}));
+        }
+    }
+
+    print " => max weight is ", $args{"weight"}, " per group/page, but a section can not be divided\n";
+    print " => ", scalar  keys %groups, " group(s) for ", scalar @sections, " section(s)\n";
+
+    # Build documentation page
+    # Browse each group, each section in this group, each word in this section
+
+    my $page_doc;
+
+    foreach my $groupid (sort {$a <=> $b} keys %groups) {
+
+        my $fromto = $groups{$groupid}[0];
+        $fromto .= ".." . $groups{$groupid}[scalar @{$groups{$groupid}} - 1]
+          if scalar @{$groups{$groupid}} > 1;
+
+        $page_doc .= 
+          "/*! \@page ${prefix}_$groupid $title ($fromto)\n\n$header"; 
+
+        foreach my $section (@{$groups{$groupid}}) {
+            $page_doc .=
+              "\n$indent\@section ${prefix}_section_$section $section\n\n$navbar\n";
+            foreach my $word (@{$sections_words{$section}}) {
+                $page_doc .= $words_doc{$word}, "\n";
+            }
+            print "\t- $section\n" if exists $args{"verbose"};
+        }
+        $page_doc .= "$footer\n*/\n\n";
+    }
+
+    print "Writing documentation to ", $destination_file, "...\n";
+
+    $intermediate_time = time();
+
+    sysopen(DEST_FILE, 
+            $destination_file, 
+            O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+     or croak "$PROGNAME: unable to open destination file $destination_file\n";
+    print DEST_FILE $page_doc;
+    close(DEST_FILE);
+
+    print " => written in ", time() - $intermediate_time, " s.\n";
+}
+
diff --git a/bioimagesuite30_src/Utilities/Doxygen/doc_cleanhtml.pl b/bioimagesuite30_src/Utilities/Doxygen/doc_cleanhtml.pl
new file mode 100644
index 0000000..5872064
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/doc_cleanhtml.pl
@@ -0,0 +1,113 @@
+#!/usr/bin/env perl
+# Time-stamp: <2002-10-25 20:17:59 barre>
+#
+# Clean the HTML generated by Doxygen to remove some layout quicks
+#
+# barre : Sebastien Barre <sebastien at barre.nom.fr>
+#
+# 0.1 (barre)
+#   - first release
+
+use Carp;
+use Getopt::Long;
+use Fcntl;
+use File::Find;
+use strict;
+
+my ($VERSION, $PROGNAME, $AUTHOR) = (0.1, $0, "Sebastien Barre");
+$PROGNAME =~ s/^.*[\\\/]//;
+print "$PROGNAME $VERSION, by $AUTHOR\n";
+
+# -------------------------------------------------------------------------
+# Defaults (add options as you want : "verbose" => 1 for default verbose mode)
+
+my %default = 
+  (
+   html => "../../../doc/html",
+  );
+
+# -------------------------------------------------------------------------
+# Parse options
+
+my %args;
+Getopt::Long::Configure("bundling");
+GetOptions (\%args, "help", "verbose|v", "html=s");
+
+if (exists $args{"help"}) {
+    print <<"EOT";
+Usage : $PROGNAME [--help] [--verbose|-v] [--html path]
+  --help       : this message
+  --verbose|-v : verbose (display filenames while processing)
+  --html path  : 'path' the Doxygen generated HTML doc (default : $default{html})
+
+Example:
+  $PROGNAME
+EOT
+    exit;
+}
+
+$args{"html"} = $default{"html"} if ! exists $args{"html"};
+$args{"html"} =~ s/[\\\/]*$// if exists $args{"html"};
+
+my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i);
+my $open_file_as_text = $os_is_win ? O_TEXT : 0;
+my $start_time = time();
+
+# -------------------------------------------------------------------------
+# Collect all HTML files
+
+print "Collecting HTML files in ", $args{"html"}, "\n";
+
+my @files;
+find sub { 
+    push @files, $File::Find::name
+      if -f $_ && $_ =~ /\.html$/;
+}, $args{"html"};
+
+print " => ", scalar @files, " file(s) collected in ", time() - $start_time, " s.\n";
+
+# -------------------------------------------------------------------------
+# Remove path 
+
+my $nb_files = 0;
+undef $/;  # slurp mode
+
+print "Cleaning and writing...\n";
+my $intermediate_time = time();
+
+foreach my $filename (@files) {
+
+    print "  $filename\n" if exists $args{"verbose"};
+
+    # Open the file, read it entirely
+
+    sysopen(HTMLFILE, 
+            $filename, 
+            O_RDONLY|$open_file_as_text)
+      or croak "$PROGNAME: unable to open $filename\n";
+    my $html = <HTMLFILE>;
+    close(HTMLFILE);
+    
+    # Clean
+
+    my $has_been_cleaned = 0;
+    if ($html =~ s/<table width="100%" cellpadding="2" cellspacing="0" border="0">/<table class="table-md-params" cellpadding="2" cellspacing="0" border="0">/gms) {
+        $has_been_cleaned = 1;
+    }
+
+    # Write
+   
+    if ($has_been_cleaned) {
+        ++$nb_files;
+        sysopen(HTMLFILE, 
+                $filename, 
+                O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+          or croak "$PROGNAME: unable to open destination file $filename\n";
+        print HTMLFILE $html;
+        close(HTMLFILE);
+    }
+}
+
+print " => $nb_files file(s) processed and written in ", time() - $intermediate_time, " s.\n";
+print "Finished in ", time() - $start_time, " s.\n";
+
diff --git a/bioimagesuite30_src/Utilities/Doxygen/doc_codematch.pl b/bioimagesuite30_src/Utilities/Doxygen/doc_codematch.pl
new file mode 100644
index 0000000..d63e59d
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/doc_codematch.pl
@@ -0,0 +1,565 @@
+#!/usr/bin/env perl
+# Time-stamp: <2002-01-18 16:17:26 barre>
+#
+# Summary ?
+#
+# barre : Sebastien Barre <sebastien.barre at kitware.com>
+#
+# 0.2 (barre)
+#   - add --headerext s : expected header file extension
+#   - add --headernewext s : new header file extension
+#   - add --headernewsuffix s : new header file suffix
+#
+# 0.1 (barre)
+#   - first release
+
+use Carp;
+use Cwd 'abs_path';
+use Getopt::Long;
+use Fcntl;
+use File::Basename;
+use File::Find;
+use File::Path;
+use strict;
+
+my ($VERSION, $PROGNAME, $AUTHOR) = (0.2, $0, "Sebastien Barre");
+$PROGNAME =~ s/^.*[\\\/]//;
+print "$PROGNAME $VERSION, by $AUTHOR\n";
+
+# -------------------------------------------------------------------------
+# Defaults (add options as you want : "verbose" => 1 for default verbose mode)
+
+my %default = 
+  (
+   codematch => "\w(?:->|\.)InvokeEvent\s*\(\s*(vtkCommand::\w+)[\s,]",
+   dirs => ["../../Common", 
+            "../../Filtering", 
+            "../../Graphics", 
+            "../../Hybrid", 
+            "../../Imaging", 
+            "../../IO", 
+            "../../Parallel", 
+            "../../Patented", 
+            "../../Rendering"],
+   headerext => "h",
+   headernewext => "h",
+   headernewsuffix => "",
+   label => "Events",
+   project => "VTK",
+   relativeto => "",
+   sectionmatch => "^vtkCommand::(\w)",
+   sectionmatch2 => "^vtk(\w)",
+   store => "doc_VTK_events.dox",
+   store2 => "doc_VTK_events2.dox",
+   title => "Event To Classes",
+   title2 => "Class to Events",
+   to => "../../../VTK-doxygen",
+   unique => "v",
+   weight => 90000
+  );
+
+# -------------------------------------------------------------------------
+# Parse options
+
+my %args;
+Getopt::Long::Configure("bundling");
+GetOptions (\%args, "help", "verbose|v", "debug", "label=s", "codematch=s", "headerext=s", "headernewext=s", "headernewsuffix=s", "project=s", "relativeto=s", "sectionmatch=s", "sectionmatch2=s", "store=s", "store2=s", "title=s", "title2=s", "to=s", "unique=s", "weight=i");
+
+if (exists $args{"help"}) {
+    print <<"EOT";
+Usage : $PROGNAME [--help] [--verbose|-v] [--limit n] [--stop file] [--sectionmatch str] [--sectionmatch2 file] [--store file] [--store2 file] [--title string] [--title2 string] [--to path] [--relativeto path] [--weight n] [files|directories...]
+  --help            : this message
+  --verbose|-v      : verbose (display filenames while processing)
+  --codematch str   : codematch used to generate matches against code (default: $default{codematch})
+  --headerext s     : expected header file extension (default: $default{headerext})
+  --headernewext s  : new header file extension (default: $default{headernewext})
+  --headernewsuffix s : new header file suffix (default: $default{headernewsuffix})
+  --project name    : project name, used to uniquify (default: $default{project})
+  --label str       : use string as label in class page (default: $default{label})
+  --sectionmatch s  : use string against match to get unique alpha section (default: $default{sectionmatch})
+  --sectionmatch2 s : use string against class to get unique alpha section (default: $default{sectionmatch2})
+  --store file      : use 'file' to store 'match to classes' (default: $default{store})
+  --store2 file     : use 'file' to store 'classes to matches' (default: $default{store2})
+  --title str       : use string as title in 'match to classes' (default: $default{title})
+  --title2 str      : use string as title in 'class to matches' (default: $default{title2})
+  --to path         : use 'path' as destination directory (default : $default{to})
+  --unique str      : use string as a unique page identifier among "Class To..." pages generated by this script (otherwise MD5) (default : $default{unique})
+  --relativeto path : each file/directory to document is considered relative to 'path', where --to and --relativeto should be absolute (default: $default{relativeto})
+  --weight n     : use 'n' as an approximation of the maximum page weight (default : $default{weight})
+
+Example:
+  $PROGNAME
+EOT
+    exit;
+}
+
+$args{"debug"} = $default{"debug"} if exists $default{"debug"};
+$args{"verbose"} = 1 if exists $default{"verbose"};
+$args{"codematch"} = $default{"codematch"} if ! exists $args{"codematch"};
+$args{"headerext"} = $default{"headerext"} if ! exists $args{"headerext"};
+$args{"headernewext"} = $default{"headernewext"} if ! exists $args{"headernewext"};
+$args{"headernewsuffix"} = $default{"headernewsuffix"} 
+if ! exists $args{"headernewsuffix"};
+$args{"project"} = $default{"project"} if ! exists $args{"project"};
+$args{"label"} = $default{"label"} if ! exists $args{"label"};
+$args{"sectionmatch"} = $default{"sectionmatch"} if ! exists $args{"sectionmatch"};
+$args{"store"} = $default{"store"} if ! exists $args{"store"};
+$args{"title"} = $default{"title"} if ! exists $args{"title"};
+$args{"sectionmatch2"} = $default{"sectionmatch2"} if ! exists $args{"sectionmatch2"};
+$args{"store2"} = $default{"store2"} if ! exists $args{"store2"};
+$args{"title2"} = $default{"title2"} if ! exists $args{"title2"};
+$args{"to"} = $default{"to"} if ! exists $args{"to"};
+$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"};
+$args{"relativeto"} = $default{"relativeto"} if ! exists $args{"relativeto"};
+$args{"relativeto"} =~ s/[\\\/]*$// if exists $args{"relativeto"};
+$args{"unique"} = $default{"unique"} if ! exists $args{"unique"};
+$args{"weight"} = $default{"weight"} if ! exists $args{"weight"};
+
+my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i);
+my $open_file_as_text = $os_is_win ? O_TEXT : 0;
+my $start_time = time();
+
+# -------------------------------------------------------------------------
+# Collect all files and directories
+
+print "Collecting files...\n";
+
+push @ARGV, @{$default{dirs}} if !@ARGV;
+
+my @files;
+foreach my $file (@ARGV) {
+    if (-f $file) {
+        push @files, $file;
+    } elsif (-d $file) {
+        find sub { push @files, $File::Find::name; }, $file;
+    }
+}
+
+# -------------------------------------------------------------------------
+# Parse implementation files corresponding to headers
+
+print "Parsing implementation files and updating headers...\n";
+my $intermediate_time = time();
+
+# %allclasses reports all class that have been parsed.
+# %allmatches reports all matches that have been found.
+# %match2classes associates a match to a class name and reports how many 
+# times that association was found.
+# Example: $match2classes{"vtkCommand::Event"}{"vtkMarchingCubes"} = 2
+# %class2matches associates a class name to a match
+
+my %allclasses;
+my %allmatches;
+my %class2matches;
+my %match2classes;
+
+my ($nb_files, $nb_replaced_files, $nb_classes_matching) = (0, 0);
+undef $/;  # slurp mode
+
+foreach my $source (@files) {
+
+    # Skip if not a VTK header file or has no implementation file
+
+    next if $source !~ /(\w?vtk[^\\\/]*)\.$args{"headerext"}\Z/;
+    my ($class, $implem) = ($1, $source);
+    $implem =~ s/\.$args{"headerext"}\Z/\.cxx/;
+    next if ! -e $implem;
+
+    ++$nb_files;
+
+    # Open the implementation file, read it entirely
+
+    sysopen(IMPLEMFILE, $implem, O_RDONLY|$open_file_as_text)
+      or croak "$PROGNAME: unable to open $implem\n";
+    my $implemfile = <IMPLEMFILE>;
+    close(IMPLEMFILE);
+    
+    # Remove all comments
+   
+    $implemfile =~ s/\/\*.*?\*\/|\/\/.*?$//gms;
+
+    # Grab matches, skip to next file if none found
+
+    my @matches = $implemfile =~ m/$args{"codematch"}/gms;
+
+    next if ! @matches;
+    $allclasses{$class} = 1;
+
+    # Setup match <-> class relationships
+
+    foreach my $match (@matches) {
+        $allmatches{$match}++;
+        $class2matches{$class}{$match}++;
+        $match2classes{$match}{$class}++;
+    }
+
+    # Figure out the name of the already-converted-to-doxygen header
+    # file using --to and --relativeto destination file now
+
+    my $header;
+
+    # If source has absolute path, just use the basename (unless a
+    # relativeto path has been set) otherwise remove the ../ component
+    # before the source filename, so that it might be appended to the
+    # "to" directory.
+
+    if ($source =~ m/^(\/|[a-zA-W]\:[\/\\])/) {
+        if ($args{"relativeto"}) {
+            my ($dir, $absrel) = (abs_path(dirname($source)), 
+                                  abs_path($args{"relativeto"}));
+            $dir =~ s/$absrel//;
+            $header = $args{"to"} . $dir . '/' . basename($source);
+        } else {
+            $header = $args{"to"} . '/' . basename($source);
+        }
+    } else {
+        $source =~ s/^(\.\.[\/\\])*//;
+        $header = $args{"to"} . '/' . $source;
+    }
+    $header =~ s/\.$args{"headerext"}\Z/$args{"headernewsuffix"}\.$args{"headernewext"}/;
+
+    next if ! -e $header;
+
+    # Read that header
+
+    sysopen(HEADERFILE, $header, O_RDONLY|$open_file_as_text)
+      or croak "$PROGNAME: unable to open $header\n";
+    my $headerfile = <HEADERFILE>;
+    close(HEADERFILE);
+    
+    # Search for the documentation block (@class ...)
+
+    if ($headerfile !~ /(.*\/\*\!\s+)(\@class\s.+?)(\*\/.*)/gms) {
+        carp  "$PROGNAME: no documentation block in $header ! (skipping)\n";
+        next;
+    }
+    my ($pre, $block, $post) = ($1, $2, $3);
+
+    # Create new doc section, insert it into block
+    
+    my $preamble = "    \@par      " . $args{"label"} . ":\n";
+    my $doc = $preamble . 
+      "              " . join(" ", keys %{$class2matches{$class}}) . "\n";
+
+    if ($block !~ s/($preamble.+?)(\s*\@par|\z)/$doc$2/gms) {
+        $block .= "\n$doc";
+    }
+
+    # Write new header
+
+    sysopen(HEADERFILE, $header, 
+            O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+      or croak "$PROGNAME: unable to open $header\n";
+    print HEADERFILE $pre . $block . $post;
+    close(HEADERFILE);
+
+    ++$nb_replaced_files;
+}
+
+print " => parsed in ", time() - $intermediate_time, " s.\n";
+
+# -------------------------------------------------------------------------
+# Build the page summary documentation
+
+# $indent is the indentation string
+
+my $indent = "    ";
+
+# $header is the Doxygen string summarizing what has been documented as well
+# as the credits.
+
+my $header;
+my (@summary, @credits);
+
+push @summary, 
+  "  - $nb_files implementation file(s) returning " . scalar (keys %allmatches) . " word(s) for " . scalar (keys %allclasses) . " classe(es) on " . localtime(),
+  "  - $nb_replaced_files file(s) updated";
+
+push @credits, 
+  "\@version $VERSION",
+  "\@author \@c $PROGNAME, by $AUTHOR";
+
+$header = $indent . join("\n$indent", @summary) . 
+  "\n\n$indent" . join("\n$indent", @credits) . "\n\n";
+
+# -------------------------------------------------------------------------
+# (first part - match 2 classes)
+
+if ($args{"store"}) {
+
+    print "Building page doc (match 2 classes)...\n";
+
+    # @words is the array of words to document
+
+    my @words = sort keys %allmatches;
+
+    # $prefix is a unique prefix that is appended to each link
+
+    my $prefix = "mc_" . $args{"project"} . "_";
+    if (exists $args{"unique"}) {
+        $prefix .= $args{"unique"};
+    } else {
+        $prefix .= md5_hex($args{"label"} . $args{"title"});
+    }
+    $prefix = lc($prefix);
+
+    # word_section_name returns the short string describing a word section
+
+    sub word_section_name {
+        my ($word) = @_;
+        return $word;
+    }
+    
+    # word_section_doc returns the doxygen doc for a word
+
+    sub word_section_doc {
+        my ($word) = @_;
+        return "  - " . join(", ", sort keys %{$match2classes{$word}}) . "\n";
+    }
+
+    # word_section_alpha returns the single alpha char corresponding to that
+    # word's section.
+
+    sub word_section_alpha {
+        my ($word) = @_;
+        $word =~ /$args{"sectionmatch"}/;
+        return $1;
+    }
+
+    my $page_doc = build_page_doc($indent,
+                                  $args{"title"},
+                                  \@words, 
+                                  $prefix, 
+                                  \&word_section_name, 
+                                  \&word_section_doc,
+                                  \&word_section_alpha,
+                                  $header,
+                                  "",
+                                  $args{"to"} . "/" . $args{"store"});
+}
+
+
+# -------------------------------------------------------------------------
+# (second part - class to matches)
+
+if ($args{"store2"}) {
+
+    print "Building page doc (classes to matches)...\n";
+
+    # @words is the array of words to document
+
+    my @words = sort keys %allclasses;
+
+    # $prefix is a unique prefix that is appended to each link
+
+    my $prefix = "mc2_" . $args{"project"} . "_";
+    if (exists $args{"unique"}) {
+        $prefix .= $args{"unique"};
+    } else {
+        $prefix .= md5_hex($args{"label"} . $args{"title"});
+    }
+    $prefix = lc($prefix);
+
+    # word_section_name returns the short string describing a word section
+
+    sub word_section_name2 {
+        my ($word) = @_;
+        return $word;
+    }
+    
+    # word_section_doc returns the doxygen doc for a word
+
+    sub word_section_doc2 {
+        my ($word) = @_;
+        return "  - " . join(", ", sort keys %{$class2matches{$word}}) . "\n";
+    }
+
+    # word_section_alpha returns the single alpha char corresponding to that
+    # word's section.
+
+    sub word_section_alpha2 {
+        my ($word) = @_;
+        $word =~ /$args{"sectionmatch2"}/;
+        return $1;
+    }
+
+    my $page_doc = build_page_doc($indent,
+                                  $args{"title2"},
+                                  \@words, 
+                                  $prefix, 
+                                  \&word_section_name2, 
+                                  \&word_section_doc2,
+                                  \&word_section_alpha2,
+                                  $header,
+                                  "",
+                                  $args{"to"} . "/" . $args{"store2"});
+}
+
+print join("\n", @summary), "\n";
+print "Finished in ", time() - $start_time, " s.\n";
+
+# -------------------------------------------------------------------------
+
+sub build_page_doc {
+
+    # $indent is the indentation string
+    # $rwords is a reference to the array of words to document
+    # $prefix is a unique prefix that is appended to each link
+    # word_section_name returns the short string describing a word section
+    # word_section_doc returns the doxygen doc for a word
+    # word_section_alpha returns the single alpha char corresponding to that
+    # word's section.
+    # $header is the Doxygen string summarizing what has been documented as 
+    # well as the credits.
+    # $footer is a Doxygen string appended to each the resulting page
+    # $destination_file is the name of the file where this page should be
+    # written to.
+
+    my ($ident, $title, $rwords, $prefix, $rword_section_name, $rword_section_doc, $rword_section_alpha, $header, $footer, $destination_file) = @_;
+
+    # %words_doc is a hash associating a word to its Doxygen doc (string)
+
+    my %words_doc;
+
+    # %sections_words is a hash associating a section (alphabetical letter) to
+    # an array of words belonging to that section.
+    #   Ex: $sections_words{"C"} => ("contour", "cut")
+    # %sections_weight is a hash associating a section to its weight (the sum 
+    # of the weights of each word belonging to that section).
+    # @sections is the array holding the name of all sections
+
+    my (%sections_words, %sections_weight, @sections);
+
+    # $navbar is the Doxygen string describing the sections' navigation bar
+    
+    my $navbar;
+    
+    my $intermediate_time = time();
+    
+    # Browse each word
+
+    foreach my $word (@$rwords) {
+
+        my @temp;
+        push @temp, &$rword_section_name($word), &$rword_section_doc($word);
+        $words_doc{$word} = $indent . join("\n$indent", @temp) . "\n";
+
+        # Update section(s) and section(s) weight(s)
+
+        my $section = &$rword_section_alpha($word);
+        push @{$sections_words{$section}}, $word;
+        $sections_weight{$section} += length($words_doc{$word});
+        
+        print " => ", $word, "\n" if exists $args{"verbose"};
+    }
+
+    print " => ", scalar @$rwords, " words(s) documented in ", time() - $intermediate_time, " s.\n";
+    
+    @sections = sort keys %sections_words;
+
+    # Build the navbar
+    
+    my @temp;
+    foreach my $section (@sections) {
+        push @temp, "\@ref ${prefix}_section_$section \"$section\"";
+    }
+    $navbar = "$indent\@par Navigation: \n$indent\[" . 
+      join(" | ", @temp) . "]\n";
+
+    # Add the (approximate) weight of the (header + navbar) to each section
+
+    my $total_weight = 0;
+    my $header_weight = length($indent) + 24 + length($navbar);
+
+    foreach my $section (@sections) {
+        $sections_weight{$section} += $header_weight;
+        $total_weight += $sections_weight{$section};
+    }
+
+    if (exists $args{"verbose"}) {
+        foreach my $section (@sections) {
+            printf("\t- %s : %6d\n", $section, $sections_weight{$section});
+        }
+    }
+
+    print " => total weight is $total_weight in ", scalar @sections, " section(s) (mean is ", int($total_weight / scalar @sections), ")\n";
+
+    # Compute the alphabetical groups by joining sections depending on weights
+
+    print "Computing alphabetical group(s)/page(s)...\n";
+
+    # %groups is a hash associating a group id (int) to an array of sections 
+    # namesbelonging to that group.
+    #   Ex: $groups{"0"} => ("A", "B", "C")
+    # %groups_weight is a hash associating a group id to its weight (the sum
+    # of the weights of each section belonging to that group).
+
+    my (%groups, %groups_weight);
+
+    my $groupid = 0;
+
+    # Remove a section one by one, and put it in a group until the group if 
+    # full,then create a next group, etc., until the sections are exhausted.
+
+    my @sections_temp = @sections;
+    while (@sections_temp) {
+        $groups_weight{$groupid} = $sections_weight{$sections_temp[0]};
+        push @{$groups{$groupid}}, shift @sections_temp;
+        while (@sections_temp && 
+               ($groups_weight{$groupid} +$sections_weight{$sections_temp[0]}) 
+               <= $args{"weight"}) {
+            $groups_weight{$groupid} += $sections_weight{$sections_temp[0]};
+            push @{$groups{$groupid}}, shift @sections_temp;
+        }
+        $groupid++;
+    }
+
+    if (exists $args{"verbose"}) {
+        foreach my $groupid (sort {$a <=> $b} keys %groups) {
+            printf("\t- %02d (weight: %7d) : %s\n", $groupid, 
+                   $groups_weight{$groupid}, join(", ", @{$groups{$groupid}}));
+        }
+    }
+
+    print " => max weight is ", $args{"weight"}, " per group/page, but a section can not be divided\n";
+    print " => ", scalar  keys %groups, " group(s) for ", scalar @sections, " section(s)\n";
+
+    # Build documentation page
+    # Browse each group, each section in this group, each word in this section
+
+    my $page_doc;
+
+    foreach my $groupid (sort {$a <=> $b} keys %groups) {
+
+        my $fromto = $groups{$groupid}[0];
+        $fromto .= ".." . $groups{$groupid}[scalar @{$groups{$groupid}} - 1]
+          if scalar @{$groups{$groupid}} > 1;
+
+        $page_doc .= 
+          "/*! \@page ${prefix}_$groupid $title ($fromto)\n\n$header"; 
+
+        foreach my $section (@{$groups{$groupid}}) {
+            $page_doc .=
+              "\n$indent\@section ${prefix}_section_$section $section\n\n$navbar\n";
+            foreach my $word (@{$sections_words{$section}}) {
+                $page_doc .= $words_doc{$word}, "\n";
+            }
+            print "\t- $section\n" if exists $args{"verbose"};
+        }
+        $page_doc .= "$footer\n*/\n\n";
+    }
+
+    print "Writing documentation to ", $destination_file, "...\n";
+
+    $intermediate_time = time();
+
+    sysopen(DEST_FILE, 
+            $destination_file, 
+            O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+     or croak "$PROGNAME: unable to open destination file $destination_file\n";
+    print DEST_FILE $page_doc;
+    close(DEST_FILE);
+
+    print " => written in ", time() - $intermediate_time, " s.\n";
+}
+
diff --git a/bioimagesuite30_src/Utilities/Doxygen/doc_contributors.pl b/bioimagesuite30_src/Utilities/Doxygen/doc_contributors.pl
new file mode 100644
index 0000000..6c9e04b
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/doc_contributors.pl
@@ -0,0 +1,1052 @@
+#!/usr/bin/env perl
+# Time-stamp: <2002-11-01 15:33:04 barre>
+#
+# Get author and contributors.
+#
+# barre : Sebastien Barre <sebastien at barre.nom.fr>
+#
+# 0.8 (barre) :
+#   - Add --cvsweb and --cvsweb_suffix to report links to CVSweb logs
+#
+# 0.7 (barre) :
+#   - Fix empty cached log file pb (regenerated)
+#   - Add link from name to detailed description of contribution
+#
+# 0.6 (barre) :
+#   - Change --history_img in order to create any contribution graph(s)
+#
+# 0.5 (barre) :
+#   - Contribution graphs for the whole period (back to 1994).
+#
+# 0.4 (barre) :
+#   - D'oh ! Month returned by localtime start with 0 (=january).
+#
+# 0.3 (barre) :
+#   - add history feature + gnuplot fig
+#
+# 0.2 (barre) :
+#   - now handles most files
+#
+# 0.1 (barre) :
+#   - first release
+
+use Carp;
+use Cwd 'abs_path', 'cwd';
+use Getopt::Long;
+use Fcntl;
+use File::Basename;
+use File::Find;
+use File::Path;
+use POSIX;
+use strict;
+use FileHandle;
+use Time::Local;
+
+my ($VERSION, $PROGNAME, $AUTHOR) = (0.8, $0, "Sebastien Barre");
+$PROGNAME =~ s/^.*[\\\/]//;
+
+# -------------------------------------------------------------------------
+# Defaults  (add options as you want: "verbose" => 1 for default verbose mode)
+
+my %default = 
+  (
+   dirs => ["../.."],
+   cachedir => $ENV{TMP} . "/cache",
+   class_group => '^(vtk[A-Z0-9][A-Za-z0-9]+)\.(?:c|cpp|cxx|h|mm)$',
+   files_in => '(?:^hints|^README|\.(?:c|cmake|cpp|cxx|doc|h|html|in|java|mm|pl|py|tcl|txt))$',
+   files_out => '(?:^vtkVersion\.\w+|^pkgIndex\.tcl|^vtkParse\.tab\.c|\.yy\.c)$',
+   gnuplot_file => '../../../VTK-doxygen/contrib/history.plt',
+   history_dir => '../../../VTK-doxygen/contrib',
+   history_img => ['|lines|../../../VTK-doxygen/contrib/history.png',
+                   '730|lines|../../../VTK-doxygen/contrib/history2y.png',
+                   '180|linespoints|../../../VTK-doxygen/contrib/history6m.png'],
+   history_max_nb => 12,
+   lines_add => 1.0,
+   lines_rem => 0.5,
+   massive => 200,
+   max_class_nb => 10,
+   max_file_nb => 5,
+   min_class => 0.02,
+   min_file => 0.01,
+   min_contrib => 0.05,
+   min_gcontrib => 0.0001,
+   relativeto => "../..",
+   store => "doc_VTK_contributors.dox",
+   to => "../../../VTK-doxygen"
+  );
+
+# -------------------------------------------------------------------------
+# Parse options
+
+my %args;
+Getopt::Long::Configure("bundling");
+GetOptions (\%args, "help", "verbose|v", "authors=s", "cachedir=s", "class_group=s", "cvsweb=s", "cvsweb_suffix=s", "files_in=s", "files_out=s", "gnuplot_file=s", "history_dir=s", "history_img=s@", "history_max_nb=i", "lines_add=f", "lines_rem=f", "massive=i", "max_class_nb=i", "max_file_nb=i", "min_class=f", "min_file=f", "min_contrib=f", "min_gcontrib=f", "relativeto=s", "store=s", "to=s");
+
+print "$PROGNAME $VERSION, by $AUTHOR\n";
+
+if (exists $args{"help"}) {
+    print <<"EOT";
+Usage : $PROGNAME [--help] [--verbose|-v] [--authors file] [--cachedir path] [--files_in string] [--files_out string] [--gnuplot_file string] [--history_dir string] [--history_img string] [--history_max_nb number] [--lines_add number] [--lines_rem number] [--massive number] [--max_class_nb number] [--max_file_nb number] [--min_class number] [--min_file number] [--min_contrib number] [--min_gcontrib number] [--store file] [--relativeto path] [--to path] [files|directories...]
+  --help           : this message
+  --verbose|-v     : verbose (display filenames while processing)
+  --authors file   : use 'file' to read authors list
+  --cachedir path  : use 'path' as cache directory for CVS logs (default: $default{cachedir})
+  --files_in s     : accept only file names (without path) matching 's' (default: $default{files_in})
+  --files_out s    : (then) reject file names (without path) matching 's' (default: $default{files_out})
+  --gnuplot_file s : use 's' to store gnuplot command file (default: $default{gnuplot_file})
+  --history_dir s  : history dir (default: $default{history_dir})
+  --history_img d|s : create history image 's' graphing contribs up to 'd' ago (default: $default{history_img})
+  --history_max_nb n : use at most 'n' authors in history pic (default: $default{history_max_nb})
+  --lines_add n           : use 'n' as weight for added lines (default: $default{lines_add})
+  --lines_rem n          : use 'n' as weight for removed lines (default: $default{lines_rem})
+  --massive n      : use 'n' as minimum threshold for massive commits removal (default: $default{massive})
+  --max_class_nb n : do not display more than 'n' classes by contributor (default: $default{max_class_nb})
+  --max_file_nb n : do not display more than 'n' files by contributor (default: $default{max_file_nb})
+  --min_class n    : display classes that represent more than 'n' % of author's contribution (default: $default{min_class})
+  --min_file n    : display files that represent more than 'n' % of author's contribution (default: $default{min_file})
+x  --min_contrib n  : display authors who represent more than 'n' % of classe's contribution (default: $default{min_contrib})
+  --min_gcontrib n : display authors who represent more than 'n' % of total contribution (default: $default{min_gcontrib})
+  --cvsweb s : use 's' as a base link to the CVSweb site
+  --cvsweb_suffix s : use 's' as a suffix to the link to the CVSweb site
+  --store file     : use 'file' to store doc (default: $default{store})
+  --relativeto path: each file/directory to document is considered relative to 'path', where --to and --relativeto should be absolute (default: $default{relativeto})
+  --to path        : use 'path' as destination directory (default: $default{to})
+
+Example:
+  $PROGNAME --to ../vtk-doxygen
+  $PROGNAME contrib
+EOT
+    exit;
+}
+
+foreach my $option (
+                    "cachedir",
+                    "class_group",
+                    "files_in",
+                    "files_out",
+                    "gnuplot_file",
+                    "history_dir",
+                    "history_img",
+                    "history_max_nb",
+                    "lines_add",
+                    "lines_rem",
+                    "massive",
+                    "min_contrib",
+                    "min_gcontrib",
+                    "min_class",
+                    "min_file",
+                    "max_class_nb",
+                    "max_file_nb",
+                    "relativeto",
+                    "store",
+                    "to") {
+    $args{$option} = $default{$option} 
+      if ! exists $args{$option} && exists $default{$option};
+}
+                    
+$args{"verbose"} = 1 if exists $default{"verbose"};
+
+$args{"cachedir"} =~ s/[\\\/]*$// if exists $args{"cachedir"};
+$args{"history_dir"} =~ s/[\\\/]*$// if exists $args{"history_dir"};
+$args{"relativeto"} =~ s/[\\\/]*$// if exists $args{"relativeto"};
+$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"};
+
+my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i);
+my $open_file_as_text = $os_is_win ? O_TEXT : 0;
+
+STDOUT->autoflush;
+STDERR->autoflush;
+
+my $start_time = time();
+    
+# -------------------------------------------------------------------------
+# Read the authors list
+
+# %authors is indexed by login name (i.e. $authors{$name})
+# {'name'}: full name of the user
+# {'email'}: email of the user
+#
+# %authors_aliases is indexed by aliased login name
+# $authors_aliases{$name} is the real login name for $name
+
+my %authors;
+my %authors_aliases;
+
+sub trim_spaces {
+    my @out = @_;
+    for (@out) {
+        s/^\s*//;
+        s/\s*$//;
+    }
+    return wantarray ? @out : $out[0];
+}
+
+# Grab each author, line by line, setup aliases
+# Example:
+# will, schroede: Schroeder, Will (will.schroeder at kitware.com)
+
+my $authors_file_loaded = 0;
+
+if (exists $args{"authors"}) {
+    if (!sysopen(AUTHORS_FILE, 
+                 $args{"authors"}, 
+                 O_RDONLY|$open_file_as_text)) {
+        carp "$PROGNAME: unable to open authors list ". $args{"authors"}. "\n";
+    } else {
+        print "Reading the authors list from ". $args{"authors"} . "...\n";
+        
+        my @authors_file = <AUTHORS_FILE>;
+        close(AUTHORS_FILE);
+
+        $authors_file_loaded = 1;
+
+        foreach my $line (@authors_file) {
+            if ($line && $line =~ m/^\s*(.+?)\s*:\s*(.+?)\s*\(\s*(.*?)\s*\)/) {
+                my @aliases = split(',', $1);
+                my $author = trim_spaces(shift @aliases);
+                $authors{$author}{'name'} = $2;
+                $authors{$author}{'email'} = $3;
+                foreach my $alias (@aliases) {
+                    $authors_aliases{trim_spaces($alias)} = $author;
+                }
+                print " >> $author: ", $authors{$author}{'name'}, 
+                " (", $authors{$author}{'email'}, ")\n" 
+                  if  exists $args{"verbose"};
+            }
+        }
+        
+        print " => ", scalar keys %authors, " authors(s) read from ", basename($args{"authors"}), ".\n";
+    }
+}
+
+# -------------------------------------------------------------------------
+# Parse a revision
+#
+# Example:
+# 1.2
+# date: 2001/06/05 15:34:17;  author: barre;  state: Exp;  lines: +10 -3
+# fix PrintSelf defects
+
+sub parse_revision {
+    my $ref = shift;
+
+    $$ref =~ /([\d\.]*)\n(.*)\n(.*)/;
+
+    my ($revision, $fields_line, $message) = ($1, $2, $3);
+    my ($author, $date, $time, $lines_add, $lines_rem) = 
+      (undef, undef, undef, undef, undef);
+    
+    my @fields = split (';', $fields_line);
+
+    if ($fields[0] =~ m/date:\s+(\d+\/\d+\/\d+)\s+(\d+:\d+:\d+)$/) {
+        ($date, $time) = ($1, $2);
+    } else {
+        carp "Unable to find date of revision!\n";
+    }
+        
+    if ($fields[1] =~ m/author:\s+(.+)$/) {
+        $author = $1;
+    } else {
+        carp "Unable to find author of revision!\n";
+    }
+        
+    if (exists $fields[3] && $fields[3] =~ m/lines:\s+\+(\d+)\s+\-(\d+)$/) {
+        ($lines_add, $lines_rem) = ($1, $2);
+    }
+
+    return ($revision, $date, $time, $author, $lines_add, $lines_rem, $message);
+}
+
+# -------------------------------------------------------------------------
+# Collect all files and directories
+
+# Avoid all CVS/ directories and third-party libs directories (identified
+# by a .NoDartCoverage file)
+
+push @ARGV, @{$default{dirs}} if !@ARGV;
+
+print "Collecting...\n";
+my %files;
+foreach my $file (@ARGV) {
+    if (-f $file) {
+        $files{$file} = 1;
+    } elsif (-d $file) {
+        find sub { 
+            if ($File::Find::dir =~ /\bCVS$/ || 
+                -e '.NoDartCoverage') {
+                $File::Find::prune = 1;
+            } else {
+                $files{$File::Find::name} = 1 if -f $_;
+            }
+        }, $file;
+    }
+}
+
+# -------------------------------------------------------------------------
+# Process files and get logs
+
+print "Processing files and getting logs...\n";
+
+my $intermediate_time = time();
+my $nb_revisions = 0;
+
+# %log_by_file_revision is indexed by file and revision 
+# (i.e. $log_by_file_revision{$file_name}{$revision_number})
+# {'date'}: revision's date
+# {'author'}: revision's author
+# {'lines_add'}: number of lines added for that revision
+# {'lines_rem'}: number of lines removed for that revision
+
+my %log_by_file_revision;
+
+# %log_revision_by_signature_file is indexed by signature and file
+# (i.e. $log_revision_by_signature_file{$signature}{$file_name})
+# (hash) all revisions matching this signature and that file.
+# The signature is made of the rev date, author and message.
+
+my %log_revision_by_signature_file;
+
+my @files_submitted = sort keys %files;
+my $nb_file_submitted = scalar @files_submitted;
+my $nb_file_fraction = ceil($nb_file_submitted / 10.0);
+
+my %files_visited;
+
+sub get_short_relative_name {
+    my ($file_name, $relative_to) = @_;
+    $file_name =~ s/^$relative_to//;
+    return $file_name;
+}
+
+foreach my $file_name (@files_submitted) {
+
+    # print "   ? $file_name\n" if exists $args{"verbose"};
+
+    # Progress meter
+
+    if ($nb_file_submitted % $nb_file_fraction == 0) {
+        print " - Remaining files: $nb_file_submitted\n";
+    }
+    --$nb_file_submitted;
+        
+    # Reject file if not matching pattern or already visited
+
+    my $file_name_basename = basename($file_name);
+
+    next if ($file_name_basename !~ m/$args{"files_in"}/ ||
+             $file_name_basename =~ m/$args{"files_out"}/ ||
+             exists $files_visited{$file_name});
+
+    print "     $file_name\n" if exists $args{"verbose"};
+
+    # Get the CVS log for that file or grab it from the cache
+        
+    my $cache_name = $args{"cachedir"} . 
+      get_short_relative_name($file_name, $args{"relativeto"}) . '.log';
+    my $output;
+
+    my $old_slurp = $/;
+    undef $/;                           # slurp mode  
+    
+    # Use the cache if it exists, is not older than file, and not empty
+
+    if (-e $cache_name && 
+        (stat $cache_name)[9] >= (stat $file_name)[9] &&
+        (stat $cache_name)[7]) {
+        sysopen(CACHE_FILE, 
+                $cache_name, 
+                O_RDONLY|$open_file_as_text)
+          or croak "$PROGNAME: unable to open cache file $cache_name\n";
+        $output = <CACHE_FILE>;
+        close(CACHE_FILE);
+    } else {
+        my $file_name_dir = dirname($file_name);
+        print " >>  $file_name_dir: cvs log -b $file_name_basename\n" 
+          if exists $args{"verbose"};
+        my $current = cwd;
+        chdir($file_name_dir);
+        $output = qx/cvs log -b $file_name_basename/;
+        chdir($current);
+        mkpath(dirname($cache_name));
+        sysopen(CACHE_FILE, 
+                $cache_name, 
+                O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+          or croak "$PROGNAME: unable to open cache file $cache_name\n";
+        print CACHE_FILE $output;
+        close(CACHE_FILE);
+    }
+
+    $/ = $old_slurp;
+
+    if (! $output) {
+        carp " >> Empty output from CVS log -b $file_name\n";
+        next;
+    }
+
+    $files_visited{$file_name} = 1;
+    
+    # Process revisions
+    
+    my @file_revisions = 
+      split('----------------------------\nrevision ', $output);
+    shift @file_revisions;
+
+    # Store each revision
+
+    my $lines_added = 0;
+
+    foreach my $revision (@file_revisions) {
+        
+        my ($revision, $date, $time, $author, 
+            $lines_add, $lines_rem, $message) = parse_revision(\$revision);
+
+        # Resolve author aliases and use full name
+        
+        $author = $authors_aliases{$author} 
+          if exists $authors_aliases{$author};
+        
+        $nb_revisions++;
+        
+        # Store date/author
+        
+        $log_by_file_revision{$file_name}{$revision}{'date'} = $date;
+        $log_by_file_revision{$file_name}{$revision}{'author'} = $author;
+
+        # Store lines added and removed. Load the file and count the
+        # lines for rev 1.1
+        
+        if ($revision ne '1.1') {
+            $log_by_file_revision{$file_name}{$revision}{'lines_add'} 
+              = $lines_add;
+            $log_by_file_revision{$file_name}{$revision}{'lines_rem'} 
+              = $lines_rem;
+            
+            $lines_added += $lines_add - $lines_rem;
+
+            $log_revision_by_signature_file
+              {"$date: $author: $message"}{$file_name}{$revision} = 1;
+        }
+    }
+
+    # Now get the number of lines for 1.1 (not stored in the log)
+    # Read the current file, add all changes
+
+    sysopen(FILE, 
+            $file_name, 
+            O_RDONLY|$open_file_as_text)
+      or croak "$PROGNAME: unable to open file $file_name\n";
+
+    my @lines = <FILE>;
+    close(FILE);
+    
+    $log_by_file_revision{$file_name}{'1.1'}{'lines_add'} 
+      = (scalar @lines) - $lines_added;
+    if ($log_by_file_revision{$file_name}{'1.1'}{'lines_add'} < 0) {
+        print " >> $file_name: ", $log_by_file_revision{$file_name}{'1.1'}{'lines_add'}, " lines !\n";
+    }
+    $log_by_file_revision{$file_name}{'1.1'}{'lines_rem'} = 0;
+}
+
+print " => $nb_revisions revision(s) stored from ", scalar keys %files_visited, " file(s) in ", time() - $intermediate_time, " s. \n";
+
+# -------------------------------------------------------------------------
+# Remove massive commits (copyright changes for example)
+
+print "Removing massive commits (> " . $args{"massive"} . ") ...\n";
+
+$intermediate_time = time();
+my $nb_removed = 0;
+
+# Remove these changes that have been commited to more than 'n' files
+# in the same day by the same author with same log message (= signature)
+
+foreach my $signature (sort { (scalar keys %{$log_revision_by_signature_file{$b}}) <=> (scalar keys %{$log_revision_by_signature_file{$a}}) } 
+                       keys %log_revision_by_signature_file) {
+    my @files = keys %{$log_revision_by_signature_file{$signature}};
+
+    if (scalar @files > $args{"massive"}) {
+        print " >> Removed: (" . scalar @files . ")\n     " . 
+          substr($signature, 0, 130) . "...\n\n" if exists $args{"verbose"};
+
+        foreach my $name (@files) {
+            foreach my $revision 
+              (keys %{$log_revision_by_signature_file{$signature}{$name}}) {
+                ++$nb_removed;
+                delete $log_by_file_revision{$name}{$revision};
+            }
+        }
+    }
+}
+
+print " => ", $nb_revisions - $nb_removed, " revision(s) kept ($nb_removed revision(s) removed) in ", time() - $intermediate_time, " s. \n";
+
+# -------------------------------------------------------------------------
+# Compute the contributions
+
+print "Contributing contributions (sum(added * ", $args{"lines_add"}, " + removed * ", $args{"lines_rem"}, "))...\n";
+
+# %contribution_by_author_file is indexed by author and file name
+# (i.e $contribution_by_author_file{$author}{$file_name})
+# stores the total contribution of this author for that specific file.
+
+my %contribution_by_author_file;
+
+# %contribution_by_author_date is indexed by author and date
+# (i.e $contribution_by_author_date{$author}{$date})
+# stores the total *accumulative* contribution of this author up to that date.
+# (computed it 2 steps)
+
+my %contribution_by_author_date;
+
+# %contribution_by_author_class is indexed by author and class name
+# (i.e $contribution_by_author_class{$author}{$class_name})
+# stores the total contribution of this author for that specific class.
+
+my %contribution_by_author_class;
+
+# %classes is indexed by class name (i.e. $classes{$class_name})
+# {'files'}: (hash) all files describing that class (header, implem, etc.)
+# {'creators'}: (hash) all creators (authors of rev 1.1) for that class
+# {'contributors'}: (hash) all contributors for that class
+
+my %classes;
+
+# %not_class_file_by_author is indexed by author
+# (i.e $not_class_file_by_author{$author})
+# (hash) files contributed by author but not part of a class group.
+
+my %not_class_file_by_author;
+
+$intermediate_time = time();
+
+# Browse each file, each revision and use contribution
+ 
+foreach my $file_name (keys %files_visited) {
+
+    # Check if file is part of a class group
+    
+    my $class_name = undef;
+    if (basename($file_name) =~ m/$args{"class_group"}/) {
+        $class_name = $1;
+        print " >> $class_name: $file_name\n" if exists $args{"verbose"};
+        $classes{$class_name}{'files'}{$file_name} = 1;
+        $classes{$class_name}{'creators'}{$log_by_file_revision{$file_name}{'1.1'}{'author'}} = 1;
+    }
+
+    foreach my $revision (keys %{$log_by_file_revision{$file_name}}) {
+
+        my $author = $log_by_file_revision{$file_name}{$revision}{'author'};
+
+        # Store contribution
+
+        my $revision_contribution = 
+          $log_by_file_revision{$file_name}{$revision}{'lines_add'} * 
+            $args{"lines_add"} + 
+              $log_by_file_revision{$file_name}{$revision}{'lines_rem'} * 
+                $args{"lines_rem"};
+
+        $contribution_by_author_file{$author}{$file_name} += 
+          $revision_contribution;
+
+        $contribution_by_author_date{$author}{$log_by_file_revision{$file_name}{$revision}{'date'}} += 
+          $revision_contribution;
+
+        # File is part of a class, store the whole class contributors
+        # and contributions
+
+        if (defined($class_name)) {
+
+            $classes{$class_name}{'contributors'}{$author} = 1;
+
+            $contribution_by_author_class{$author}{$class_name} += 
+              $revision_contribution;
+        } else {
+            $not_class_file_by_author{$author}{$file_name} = 1;
+        }
+    }
+}
+
+print " => computed in ", time() - $intermediate_time, " s. \n";
+
+# -------------------------------------------------------------------------
+# Find contributors for each class, update header
+
+print "Finding contributors > ", int($args{"min_contrib"} * 100.0), " and updating class headers...\n";
+
+mkpath($args{"to"});
+
+$intermediate_time = time();
+my $nb_updated = 0;
+
+my $class_name;
+my @classes_names = sort { $b cmp $a } keys %classes;
+
+while (@classes_names) {
+    $class_name = pop @classes_names;
+
+    # Sort the contributors for that class according to their
+    # respective contributions. 
+
+    my @class_contributors_sorted = 
+      sort {$contribution_by_author_class{$b}{$class_name} <=> 
+              $contribution_by_author_class{$a}{$class_name}}
+        keys %{$classes{$class_name}{'contributors'}};
+
+    # Compute the total contribution for that class
+
+    my $total_class_contribution;
+    foreach my $class_contributor (@class_contributors_sorted) {
+        $total_class_contribution += 
+          $contribution_by_author_class{$class_contributor}{$class_name};
+    }
+
+    # Find the class header name
+
+    my $source_header_name = undef;
+    foreach my $file_name (keys %{$classes{$class_name}{'files'}}) {
+        if ($file_name =~ m/\.h$/) {
+            $source_header_name = $file_name;
+            last;
+        }
+    }
+    next if ! defined $source_header_name;
+
+    # Figure out the name of the already-converted-to-doxygen header
+    # file using --to and --relativeto destination file now
+
+    my $header;
+
+    # If source has absolute path, just use the basename (unless a
+    # relativeto path has been set) otherwise remove the ../ component
+    # before the source filename, so that it might be appended to the
+    # "to" directory.
+
+    if ($source_header_name =~ m/^(\/|[a-zA-W]\:[\/\\])/) {
+        if ($args{"relativeto"}) {
+            my ($dir, $absrel) = (abs_path(dirname($source_header_name)), 
+                                  abs_path($args{"relativeto"}));
+            $dir =~ s/$absrel//;
+            $header = $args{"to"} . $dir . '/' . basename($source_header_name);
+        } else {
+            $header = $args{"to"} . '/' . basename($source_header_name);
+        }
+    } else {
+        $source_header_name =~ s/^(\.\.[\/\\])*//;
+        $header = $args{"to"} . '/' . $source_header_name;
+    }
+
+    next if ! -e $header;
+
+    # Read that header
+
+    my $old_slurp = $/;
+    undef $/; # slurp mode  
+
+    if (!sysopen(HEADERFILE, 
+                 $header, 
+                 O_RDONLY|$open_file_as_text)) {
+        carp "$PROGNAME: unable to open $header\n";
+        next;
+    }
+
+    my $headerfile = <HEADERFILE>;
+    close(HEADERFILE);
+    
+    $/ = $old_slurp;
+
+    # Search for the documentation block (@class ...)
+
+    if ($headerfile !~ /(.*\/\*\!\s+)(\@class\s.+?)(\*\/.*)/gms) {
+        carp  "$PROGNAME: no documentation block in $header ! (skipping)\n";
+        next;
+    }
+    my ($pre, $block, $post) = ($1, $2, $3);
+
+    # Create new doc section, insert it into block
+    
+    my $preamble = "    \@par      Created by:\n";
+
+    my $doc = $preamble . "                - " . 
+      join("\n                - ", 
+           sort map(exists $authors{$_}{'name'} ? $authors{$_}{'name'} : $_, keys %{$classes{$class_name}{'creators'}})) . "\n";
+
+    $doc .= "\n    \@par      CVS contributions (if > " . int(100.0 * $args{"min_contrib"}) . "%):\n";
+
+    foreach my $class_contributor (@class_contributors_sorted) {
+        my $ratio = 
+          $contribution_by_author_class{$class_contributor}{$class_name} / 
+            $total_class_contribution;
+        last if $ratio < $args{"min_contrib"};
+        $doc .= "                - " . (exists $authors{$class_contributor}{'name'} ? $authors{$class_contributor}{'name'} : $class_contributor) . " (" . int($ratio * 100.0) . "%)\n";
+    }
+
+    if (exists $args{"cvsweb"}) {
+        $doc .= "\n    \@par      CVS logs (CVSweb):\n";
+        foreach my $file (keys %{$classes{$class_name}{'files'}}) {
+            my $shortname = get_short_relative_name($file, $args{"relativeto"});
+            my ($base, $dir, $ext) = fileparse($shortname, '\..*');
+            $doc .= '                - @htmlonly<A href="' . $args{"cvsweb"} 
+              . $shortname;
+            $doc .= $args{"cvsweb_suffix"} if exists $args{"cvsweb_suffix"};
+            $doc .= '">@endhtmlonly @c ' .  $ext 
+              . ' @htmlonly</A>@endhtmlonly (@c ' . $shortname . ")\n";
+        }
+    }
+
+    if ($block !~ s/($preamble.+?)(\s*\@par|\z)/$doc$2/gms) {
+        $block .= "\n$doc";
+    }
+
+    # Write new header
+
+    if (!sysopen(HEADERFILE, $header, 
+                 O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)) {
+        carp "$PROGNAME: unable to open $header\n";
+        next;
+    }
+
+    print HEADERFILE $pre . $block . $post;
+    close(HEADERFILE);
+
+    print " >> Updating $header\n" if exists $args{"verbose"};
+
+    $nb_updated++;
+}
+
+print " => $nb_updated header(s) updated in ", time() - $intermediate_time, " s. \n";
+
+# -------------------------------------------------------------------------
+# Build the page summary documentation
+
+# $indent is the indentation string
+
+my $indent = "    ";
+
+# $header is the Doxygen string summarizing what has been documented as well
+# as the credits.
+
+my $header;
+my (@summary, @credits);
+
+push @summary, 
+  "  - " . (scalar keys %contribution_by_author_file) . " authors(s) reported";
+
+push @summary, 
+  "  - Files matching \@c " . $args{"files_in"} . " and not matching \@c ". $args{"files_out"} . " are taken into account";
+
+push @summary,
+  "  - $nb_revisions CVS revision(s) processed from " . (scalar keys %files_visited) . " matching file(s)";
+
+push @summary, 
+  "  - " . ($nb_revisions - $nb_removed) . " revision(s) kept ($nb_removed revision(s) removed from 'massive commits' > " . $args{"massive"} . " changes per date/author/message)";
+
+push @summary, 
+  "  - revision's contribution is " . $args{"lines_add"} . " * (number of lines added) + " . $args{"lines_rem"} . " * (number of lines removed)";
+
+push @summary,
+  "  - " . (scalar keys %classes) . " class(es) found (matching \@c " . $args{"class_group"} . ")";
+
+push @credits, 
+  "\@version $VERSION",
+  "\@author \@c $PROGNAME, by $AUTHOR";
+
+$header = $indent . join("\n$indent", @summary) . "\n\n" .
+  $indent . join("\n$indent", @credits) . "\n\n";
+
+# -------------------------------------------------------------------------
+# Update contributions stats
+
+# %contribution_by_author is indexed by author
+# (i.e $contribution_by_author{$author})
+# stores the total contribution of this author for all files processed so far.
+
+my %contribution_by_author;
+
+# %contribution_by_date is indexed by date
+# (i.e $contribution_by_date{$date})
+# stores the total *accumulative* contribution up to that date 
+# for all files processed so far.
+
+my %contribution_by_date;
+
+foreach my $contributor (keys %contribution_by_author_file) {
+    
+    foreach my $file_name 
+      (keys %{$contribution_by_author_file{$contributor}}) {
+        $contribution_by_author{$contributor} += 
+          $contribution_by_author_file{$contributor}{$file_name};
+    }
+
+    my $accumulate = 0;
+
+    foreach my $date 
+      (sort {$a cmp $b} keys %{$contribution_by_author_date{$contributor}}) {
+          $contribution_by_date{$date} += 
+            $contribution_by_author_date{$contributor}{$date};
+          $accumulate += $contribution_by_author_date{$contributor}{$date};
+          $contribution_by_author_date{$contributor}{$date} = $accumulate;
+      }
+}
+
+my $accumulate = 0;
+
+foreach my $date 
+  (sort {$a cmp $b} keys %contribution_by_date) {
+      $accumulate += $contribution_by_date{$date};
+      $contribution_by_date{$date} = $accumulate;
+  }
+
+my @all_contribution_dates = sort {$a cmp $b} keys %contribution_by_date;
+
+my $last_contribution_date = $all_contribution_dates[$#all_contribution_dates];
+my $first_contribution_date = $all_contribution_dates[0];
+my $total_contribution = $contribution_by_date{$last_contribution_date};
+
+# -------------------------------------------------------------------------
+# Build documentation
+
+my $destination_file = $args{"to"} . "/" . $args{"store"};
+print "Building documentation to ", $destination_file, "\n";
+
+sysopen(DEST_FILE, 
+        $destination_file, 
+        O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+  or croak "$PROGNAME: unable to open destination file $destination_file\n";
+
+print DEST_FILE 
+  "/*! \@page contributors Contributors\n\n$header"; 
+
+print DEST_FILE 
+  "\n$indent\@section contributors_alphabetical Contributors (by alphabetical order)\n\n";
+
+sub compare_by_author_name {
+    my $a_name = exists $authors{$a}{'name'} ? $authors{$a}{'name'} : $a;
+    my $b_name = exists $authors{$b}{'name'} ? $authors{$b}{'name'} : $b;
+    return lc $a_name cmp lc $b_name;
+}
+
+foreach my $contributor (sort compare_by_author_name 
+                         keys %contribution_by_author_file) {
+
+    my $c_ratio = $contribution_by_author{$contributor} / $total_contribution;
+
+    my $name = exists $authors{$contributor}{'name'} 
+      ? $authors{$contributor}{'name'} : $contributor;
+
+    if ($c_ratio < $args{"min_gcontrib"}) {
+        print DEST_FILE "$indent - $name\n";
+    } else {
+        print DEST_FILE "$indent - \@ref $contributor \"$name\"\n";
+    }
+}
+
+print DEST_FILE 
+  "\n$indent\@section contributors_decreasing Contributors (by decreasing order of global contribution)\n";
+
+print DEST_FILE 
+  "\n$indent\@note Contributions lower than " . int($args{"min_gcontrib"} * 10000.0) / 100.0 . "% are not listed\n\n";
+
+my @contributors_sorted = 
+  sort {$contribution_by_author{$b} <=> $contribution_by_author{$a}} 
+  keys %contribution_by_author;
+
+foreach my $contributor (@contributors_sorted) {
+
+    my $c_ratio = $contribution_by_author{$contributor} / $total_contribution;
+    last if $c_ratio < $args{"min_gcontrib"};
+
+    my $name = exists $authors{$contributor}{'name'} 
+      ? $authors{$contributor}{'name'} : $contributor;
+
+    print DEST_FILE "$indent -# \@ref $contributor \"$name\"\n";
+}
+
+foreach my $history (@{$args{"history_img"}}) {
+    my ($delta, $style, $filename) = split(/\|/, $history);
+    print DEST_FILE 
+      "\n$indent\@image html " . basename($filename) . "\n";
+}
+
+print DEST_FILE 
+  "\n$indent\@section contributors_detailed Detailed contributions (by decreasing order)\n";
+
+print DEST_FILE 
+  "\n$indent\@note Contributions lower than " . int($args{"min_gcontrib"} * 10000.0) / 100.0 . "% are not listed\n";
+
+print DEST_FILE 
+  "\n$indent\@note Details are:",
+  "\n$indent       - % of global contribution at $last_contribution_date, % at date of last contribution, % at date of first contribution",
+  "\n$indent       - first ", $args{"max_class_nb"}, " contributed classes > ", int($args{"min_class"} * 100.0), "% of author's total contribution",
+  "\n$indent       - first ", $args{"max_file_nb"}, " contributed (non-class) files > ", int($args{"min_file"} * 100.0), "% of author's total contribution",
+  "\n\n";
+
+foreach my $contributor (@contributors_sorted) {
+
+    # Yes, you can have 0 contrib:
+    # vtkPiecewiseFunction.cxx:date: 1999/11/03 18:11:39;  
+    # author: tpan;  state: Exp; lines: +0 -0
+
+    next if $contribution_by_author{$contributor} == 0;
+
+    my $c_ratio = $contribution_by_author{$contributor} / $total_contribution;
+    last if $c_ratio < $args{"min_gcontrib"};
+
+    # Classes
+
+    my @ok_classes; 
+
+    my @classes_sorted = 
+      sort {$contribution_by_author_class{$contributor}{$b} <=> 
+              $contribution_by_author_class{$contributor}{$a}}
+        keys %{$contribution_by_author_class{$contributor}};
+    
+    foreach my $class_name (@classes_sorted) {
+        last if scalar @ok_classes > $args{"max_class_nb"};
+        my $ratio = 
+          $contribution_by_author_class{$contributor}{$class_name} / 
+            $contribution_by_author{$contributor};
+        last if $ratio < $args{"min_class"};
+        push @ok_classes, "$class_name (" . int($ratio * 100.0) . "%)";
+    }
+    
+    # Files
+
+    my @ok_files; 
+
+    my @files_sorted = 
+      sort {$contribution_by_author_file{$contributor}{$b} <=> 
+              $contribution_by_author_file{$contributor}{$a}}
+        keys %{$not_class_file_by_author{$contributor}};
+    
+    foreach my $file_name (@files_sorted) {
+        next if basename($file_name) =~ m/$args{"class_group"}/;
+        last if scalar @ok_files > $args{"max_file_nb"};
+        my $ratio = 
+          $contribution_by_author_file{$contributor}{$file_name} / 
+            $contribution_by_author{$contributor};
+        last if $ratio < $args{"min_file"};
+        push @ok_files, get_short_relative_name($file_name, $args{"relativeto"}) . " (" . int($ratio * 100.0) . "%)";
+    }
+
+    my $name = exists $authors{$contributor}{'name'} 
+      ? $authors{$contributor}{'name'} . " ($contributor)" : $contributor;
+
+    print DEST_FILE "$indent -# \@anchor $contributor \@b $name:\n";
+
+    my @contribution_dates = sort { $a cmp $b } 
+      keys %{$contribution_by_author_date{$contributor}};
+
+    my $last_contrib_date = $contribution_dates[$#contribution_dates];
+    my $first_contrib_date = $contribution_dates[0];
+
+    print DEST_FILE 
+      "$indent   - \@b ", int(10000.0 * $c_ratio) / 100, "% ($last_contribution_date), ", int(10000.0 * ($contribution_by_author_date{$contributor}{$last_contrib_date} / $contribution_by_date{$last_contrib_date})) / 100, "% ($last_contrib_date), ", int(10000.0 * ($contribution_by_author_date{$contributor}{$first_contrib_date} / $contribution_by_date{$first_contrib_date})) / 100, "% ($first_contrib_date)\n";
+
+    print DEST_FILE 
+      "$indent   - ", (scalar @classes_sorted), " class(es): ", join(", ", @ok_classes), "...\n" if @classes_sorted;
+
+    print DEST_FILE 
+      "$indent   - ", (scalar @files_sorted), " file(s): ", join(", ", @ok_files), "...\n" if @files_sorted;
+}
+
+print DEST_FILE "\n*/\n\n";
+
+# -------------------------------------------------------------------------
+# Create history files
+
+print "Creating history files in ", $args{"history_dir"}, "\n";
+
+mkpath($args{"history_dir"});
+
+foreach my $contributor (@contributors_sorted) {
+    my $history_name = $args{"history_dir"} . "/$contributor.dat";
+
+    sysopen(HISTORY_FILE, 
+            $history_name, 
+            O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+      or croak "$PROGNAME: unable to open history file $history_name\n";
+
+    foreach my $date 
+      (sort {$a cmp $b} keys %{$contribution_by_author_date{$contributor}}) {
+          print HISTORY_FILE $date . ' ' . ($contribution_by_author_date{$contributor}{$date} / $contribution_by_date{$date}) * 100.0 . "\n";
+      }
+
+    close(HISTORY_FILE);
+}
+
+# -------------------------------------------------------------------------
+# Create gnuplot file
+
+print "Creating gnuplot command file\n", $args{"gnuplot_file"}, "\n";
+
+my ($year, $month, $mday) = split('/', $last_contribution_date);
+
+my $last_contribution_sec = timelocal(0, 0, 0, $mday, $month - 1, $year-1900); 
+
+my $history_dir_abs = abs_path($args{"history_dir"});
+
+my @plots;
+foreach my $contributor (@contributors_sorted) {
+    last if scalar @plots >= $args{"history_max_nb"};
+    my $history_filename = $history_dir_abs . "/$contributor.dat";
+    push @plots, "\"$history_filename\" using 1:2 title \"" . (exists $authors{$contributor}{'name'} ? $authors{$contributor}{'name'} : $contributor) . "\"" if -e $history_filename;
+}
+
+my $plot = 'plot ' . join(', ', @plots);
+
+sysopen(GNUPLOT_FILE, 
+        $args{"gnuplot_file"}, 
+        O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+  or croak "$PROGNAME: unable to open gnuplot command file " . $args{"gnuplot_file"} . "\n";
+
+print GNUPLOT_FILE <<EOT;
+set grid
+
+set xdata time
+set timefmt "%Y/%m/%d"
+set format x "%Y/%m"
+set xlabel "Time (Year/Month)"
+
+set ylabel "Contribution (%)"
+
+set key bottom outside below Left title 'Legend:' nobox
+
+set mytics 5
+
+set size 1.2,1.4
+
+set terminal png color small
+
+set timestamp top
+
+EOT
+
+my $date_from;
+foreach my $history (@{$args{"history_img"}}) {
+    my ($delta, $style, $filename) = split(/\|/, $history);
+    if ($delta eq '') {
+        print GNUPLOT_FILE "# Whole period\n\n";
+        $date_from = $first_contribution_date;
+        print GNUPLOT_FILE "set title \"Contributions over time (whole period: $date_from to $last_contribution_date)\"\n\n";
+    } else {
+        print GNUPLOT_FILE "# Back $delta days\n\n";
+        ($mday, $month, $year) = 
+          (localtime($last_contribution_sec - $delta * 24 * 60 * 60))[3, 4, 5];
+        $date_from = sprintf("%04d/%02d/%02d", $year+1900, $month + 1, $mday);
+        print GNUPLOT_FILE "set title \"Contributions over time ($delta days ago: $date_from to $last_contribution_date)\"\n\n";
+    }
+    print GNUPLOT_FILE "set xrange [\"$date_from\":]\n\n";
+    print GNUPLOT_FILE "set output \"" . 
+      abs_path(dirname($filename)) . '/' . basename($filename) . "\"\n\n";
+    print GNUPLOT_FILE "set data style $style\n\n";
+    print GNUPLOT_FILE "$plot\n\n";
+    if ($plot ne 'replot') {
+        $plot = 'replot';
+    }
+}
+
+close(GNUPLOT_FILE);
+
+# -------------------------------------------------------------------------
+
+print "Finished in ", time() - $start_time, " s.\n";
diff --git a/bioimagesuite30_src/Utilities/Doxygen/doc_header2doxygen.pl b/bioimagesuite30_src/Utilities/Doxygen/doc_header2doxygen.pl
new file mode 100644
index 0000000..54a6cb9
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/doc_header2doxygen.pl
@@ -0,0 +1,555 @@
+#!/usr/bin/env perl
+# Time-stamp: <2002-01-28 11:56:19 barre>
+#
+# Convert VTK headers to doxygen format
+#
+# roeim : Vetle Roeim <vetler at ifi.uio.no>
+# barre : Sebastien Barre <sebastien at barre.nom.fr>
+#
+# 0.83 (barre) :
+#   - add --stdout          : print converted file to standard output
+#
+# 0.82 (barre) :
+#   - add --relativeto path : each file/directory to document is considered
+#     relative to 'path', where --to and --relativeto should be absolute
+#
+# 0.81 (barre) :
+#   - fix pb if both --to and path to the file to document were absolute
+#   - remove warning when date or revision not found
+#
+# 0.8 (barre) :
+#   - update to match the new VTK 4.0 tree
+#   - change default --dirs so that it can be launched from Utilities/Doxygen
+#   - change default --to so that it can be launched from Utilities/Doxygen
+#   - handle more .SECTION syntax
+#   - add group support (at last)
+#
+# 0.76 (barre) :
+#   - add 'parallel' to the default set of directories
+#
+# 0.75 (barre) :
+#   - change default --to to '../vtk-doxygen' to comply with Kitware's doxyfile
+#
+# 0.74 (barre) :
+#   - as doxygen now handles RCS/CVS tags of the form $word:text$, use them 
+#
+# 0.73 (barre) :
+#   - change doxygen command style from \ to @ to match javadoc, autodoc, etc.
+#
+# 0.72 (barre) :
+#   - change default --to to '../vtk-dox'
+#
+# 0.71 (barre) :
+#   - fix O_TEXT flag problem
+#   - switch to Unix CR/LF format
+#
+# 0.7 (barre) :
+#   - change name
+#   - remove -c option
+#
+# 0.6 (barre) :
+#   - change (warning) default --to to '../vtk2' because I ruined my own
+#     VTK distrib too many times :(
+#   - add automatic creation of missing directory trees
+#   - add check for current OS (if Windows, do not perform tests based 
+#     on stat()/idev/ino features)
+#
+# 0.5 (barre) :
+#   - better .SECTION handling
+#   - add support for empty lines in documentation block
+#   - fix problem with headers not corresponding to classes
+#   - change name to doc_header2doxygen (removed vtk_)
+#   - change '-s' (silent) to '-v' (verbose)
+#   - add function description reformatting
+#
+# 0.4 (barre) :
+#   - change /*! ... */ position upon request
+#   - add 'Date:' support as @date
+#   - add 'Version:' support as @version
+#   - add 'Thanks:' support as @par Thanks
+#
+# 0.3 (barre) :
+#   - fix various " // Description" spelling problems :)
+#
+# 0.2 (barre) :
+#   - fix problem with classes with no brief documentation
+#
+# 0.1 (barre) :
+#   - add Perl syntactic sugar, options...
+#   - add standard output (filter) mode (-c)
+#   - add silent mode (-s)
+#   - add update mode, convert only if newer (-u)
+#   - add conversion to another directory (--to)
+#   - add '.SECTION Caveats' support as @warning
+#   - add/fix '.SECTION whatever' support as @par
+#   - add default directories to process
+#
+# 0.0 (roeim)
+#   - first release (thanks to V. Roeim !)
+
+
+use Carp;
+use Cwd 'abs_path';
+use Getopt::Long;
+use Fcntl;
+use File::Basename;
+use File::Find;
+use File::Path;
+use Text::Wrap;
+use strict;
+
+my ($VERSION, $PROGNAME, $AUTHOR) = (0.83, $0, "Sebastien Barre et al.");
+$PROGNAME =~ s/^.*[\\\/]//;
+
+# -------------------------------------------------------------------------
+# Defaults  (add options as you want: "verbose" => 1 for default verbose mode)
+
+my %default = 
+  (
+   dirs => ["../../Common", 
+            "../../Filtering", 
+            "../../Graphics", 
+            "../../Hybrid", 
+            "../../Imaging", 
+            "../../IO", 
+            "../../Parallel", 
+            "../../Patented", 
+            "../../Rendering"],
+   relativeto => "",
+   temp => "doc_header2doxygen.tmp",
+   to => "../../../VTK-doxygen"
+  );
+
+# -------------------------------------------------------------------------
+# Parse options
+
+my %args;
+Getopt::Long::Configure("bundling");
+GetOptions (\%args, "help", "verbose|v", "update|u", "force|f", "temp=s", "to=s", "stdout", "relativeto=s");
+
+print "$PROGNAME $VERSION, by $AUTHOR\n" if ! exists $args{"stdout"};
+
+if (exists $args{"help"}) {
+    print <<"EOT";
+Usage : $PROGNAME [--help] [--verbose|-v] [--update|-u] [--force|-f] [--temp file] [--to path] [--relativeto path] [files|directories...]
+  --help            : this message
+  --verbose|-v      : verbose (display filenames while processing)
+  --update|-u       : update (convert only if newer, requires --to)
+  --force|-f        : force conversion for all files (overrides --update)
+  --stdout          : print converted file to standard output
+  --temp file       : use 'file' as temporary file (default: $default{temp})
+  --to path         : use 'path' as destination directory (default: $default{to})
+  --relativeto path : each file/directory to document is considered relative to 'path', where --to and --relativeto should be absolute (default: $default{relativeto})
+
+Example:
+  $PROGNAME --to ../vtk-doxygen
+  $PROGNAME contrib
+EOT
+    exit;
+}
+
+$args{"verbose"} = 1 if exists $default{"verbose"};
+$args{"update"} = 1 if exists $default{"update"};
+$args{"force"} = 1 if exists $default{"force"};
+$args{"temp"} = $default{temp} if ! exists $args{"temp"};
+$args{"to"} = $default{"to"} if ! exists $args{"to"};
+$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"};
+$args{"relativeto"} = $default{"relativeto"} if ! exists $args{"relativeto"};
+$args{"relativeto"} =~ s/[\\\/]*$// if exists $args{"relativeto"};
+
+croak "$PROGNAME: --update requires --to\n" 
+  if exists $args{"update"} && ! exists $args{"to"};
+
+my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i);
+my $open_file_as_text = $os_is_win ? O_TEXT : 0;
+my $start_time = time();
+    
+# -------------------------------------------------------------------------
+# Collect all files and directories
+
+push @ARGV, @{$default{dirs}} if !@ARGV;
+
+print "Collecting...\n" if ! exists $args{"stdout"};
+my @files;
+foreach my $file (@ARGV) {
+    if (-f $file) {
+        push @files, $file;
+    } elsif (-d $file) {
+        find sub { push @files, $File::Find::name; }, $file;
+    }
+}
+
+# -------------------------------------------------------------------------
+# Process files corresponding to headers
+
+print "Converting...\n" if ! exists $args{"stdout"};
+my $intermediate_time = time();
+my $nb_file = 0;
+
+foreach my $source (@files) {
+    
+    next if $source !~ /vtk[^\\\/]*\.h\Z/;
+
+    # Figure out destination file now
+
+    my $dest;
+    if (! exists $args{"to"}) {
+        $dest = $args{"temp"};
+    } else {
+        # if source has absolute path, just use the basename, unless a
+        # relativeto path has been set
+        if ($source =~ m/^(\/|[a-zA-W]\:[\/\\])/) {
+            if ($args{"relativeto"}) {
+                my ($dir, $absrel) = (abs_path(dirname($source)), 
+                                      abs_path($args{"relativeto"}));
+                $dir =~ s/$absrel//;
+                $dest = $args{"to"} . $dir . '/' . basename($source);
+            } else {
+                $dest = $args{"to"} . '/' . basename($source);
+            }
+        } else {
+            my $source2 = $source;
+            # let's remove the ../ component before the source filename, so 
+            # that it might be appended to the "to" directory
+            $source2 =~ s/^(\.\.[\/\\])*//;
+            $dest = $args{"to"} . '/' . $source2;
+        }
+        # Ensure both source and target are different
+        if (!$os_is_win) {
+            my ($i_dev, $i_ino) = stat $source;
+            my ($o_dev, $o_ino) = stat $dest;
+            croak "$PROGNAME: sorry, $source and $dest are the same file\n"
+              if ($i_dev == $o_dev && $i_ino == $o_ino);
+        }
+    }
+
+    # Update mode : skip the file if it is not newer than the 
+    # previously converted target
+    
+    if (exists $args{"update"} && ! exists $args{"force"}) {
+        next if -e $dest && (stat $source)[9] < (stat $dest)[9];
+    }
+    
+    ++$nb_file;
+    print "  $source\n" if exists $args{"verbose"};
+
+    # Open file, feed it entirely to an array
+
+    sysopen(HEADERFILE, $source, O_RDONLY|$open_file_as_text)
+      or croak "$PROGNAME: unable to open $source\n";
+    my @headerfile = <HEADERFILE>;
+    close(HEADERFILE);
+    
+    my ($date, $revision) = ("", "");
+    my @converted = ();
+    my @thanks = ();
+    
+    # Parse the file until the beginning of the documentation block
+    # is found. The copyright and disclaimer sections are parsed to 
+    # extract the 'Date', 'Version' and 'Thanks' values.
+    
+    my $line;
+    while ($line = shift @headerfile) {
+
+        # Quit if the beginning of the documentation block has been reached. 
+        # It is supposed to start with:
+        # // .NAME vtkFooBar - foo bar class
+
+        last if $line =~ /\/\/ \.NAME/;
+
+        # Date. Example:
+        # Date:      $Date: 2002/01/29 23:29:28 $
+
+        if ($line =~ /^\s*Date:\s*(.*)$/) {
+            $date = $1;
+
+        # Version. Example:
+        # Version:   $Revision: 1.7 $
+
+        } elsif ($line =~ /^\s*Version:\s*(.*)$/) {
+            $revision = $1;
+
+        # Thanks (maybe multi-lines). Example:
+        # Thanks:    Thanks to Sebastien Barre who developed this class.
+         
+        } elsif ($line =~ /^\s*Thanks:\s*(.*)$/) {
+            push @thanks, "             ", $1, "\n";
+            # Handle multi-line thanks
+            while ($line = shift @headerfile) {
+                last if $line =~ /^\s*$/;
+                $line =~ s/^(\s*)//;
+                push @thanks, "             ", $line;
+            }
+            push @converted, $line;
+
+        # Everything else goes to the converted file
+
+        } else {
+            push @converted, $line;
+        }
+    }
+    
+    # Process the documentation block
+    # Extract the name of the class and its short description
+    # // .NAME vtkFooBar - foo bar class
+    
+    if (defined($line) && $line =~ /\/\/ \.NAME (\w*)( \- (.*))?/) {
+        
+        my ($class_name, $class_short_description) = ($1, $3);
+        $class_name =~ s/\.h//;
+        
+        # Insert class description, date, revision, thanks
+        
+        push @converted, "/*! \@class   $class_name\n";
+        push @converted, "    \@brief   $class_short_description\n"
+          if $class_short_description;
+
+        if ($date) {
+            push @converted, "\n    $date\n";
+        }
+
+        # WARNING : need a blank line between RCS tags and previous dox tag
+
+        if ($revision) {
+            push @converted, "\n" if (!$date);
+            push @converted, "    $revision\n";
+        }
+
+        # Do not add thanks anymore. Will be done externally.
+        # push @converted, "    \@par     Thanks:\n", @thanks if @thanks;
+        
+        # Read until the end of the documentation block is reached
+        # Translate 'See Also', 'Caveats' and whatever .SECTION
+        # As of 24 sep 2001, there are:
+        #      137	// .SECTION Caveats
+        #        1	// .SECTION Credits
+        #      702	// .SECTION Description
+        #        3	// .SECTION Note
+        #        1	// .SECTION note
+        #      329	// .SECTION See Also
+        #        4	// .SECTION See also
+        #       70	// .SECTION see also
+        #        1	// .SECTION Warning
+        # find . -name vtk\*.h -exec grep "\.SECTION" {} \; | sort | uniq -c
+        # Let's provide support for bugs too:
+        #         	// .SECTION Bug
+        #         	// .SECTION Bugs
+        #         	// .SECTION Todo
+
+        my ($tag, $inblock) = ("", 0);
+        while ($line = shift @headerfile) {
+            
+            # Quit if the end of the documentation block has been reached. 
+            # Let'say that it is supposed to end as soon as the usual
+            # inclusion directives are found, for example:
+            # #ifndef __vtkAbstractTransform_h
+            # #define __vtkAbstractTransform_h
+            
+            last if $line =~ /^\#/;
+            
+            # Process and recognize a .SECTION command and convert it to
+            # the corresponding doxygen tag ($tag)
+
+            if ($line =~ /^\/\/\s+\.SECTION\s+(.+)\s*$/i) {
+                
+                my $type = $1;
+
+                # Bugs (@bugs). Starts with:
+                # // .SECTION Bug
+                # // .SECTION Bugs
+            
+                if ($type =~ /Bugs?/i) {
+                    $tag = "\@bug";
+                }
+
+                # Caveats or Warnings (@warning). Starts with:
+                # // .SECTION Caveats
+                # // .SECTION Warning
+                # // .SECTION Warnings
+            
+                elsif ($type =~ /(Caveats|Warnings?)/i) {
+                    $tag = "\@warning";
+                }
+
+                # Description. Starts with:
+                # // .SECTION Description
+            
+                elsif ($type =~ /Description/i) {
+                    $tag = "";
+                    push @converted, "\n";
+                }
+
+                # Note (@attention). Starts with:
+                # // .SECTION Note
+
+                elsif ($type =~ /Note/i) {
+                    $tag = "\@attention";
+                }
+
+                # See also (@sa). Starts with:
+                # // .SECTION See Also
+                
+                elsif ($type =~ /See Also/i) {
+                    $tag = "\@sa";
+                }
+
+                # Todo (@todo). Starts with:
+                # // .SECTION Todo
+
+                elsif ($type =~ /Todo/i) {
+                    $tag = "\@todo";
+                }
+
+                # Any other .SECTION (@par). Starts with:
+                # // .SECTION whatever
+                
+                else {
+                    $tag =  "\@par " . $type . ":";
+                }
+
+                $inblock = 0;
+            }
+            
+            # If the line starts with '//', we are still within the tag block.
+            # Remove '//' for non empty lines, eventually put or duplicate 
+            # the tag name if an empty comment is found (meaning that a new 
+            # 'paragraph' is requested but with the same tag type)
+            # Example:
+            #  // .SECTION Caveats
+            #  // blabla1q
+            #  // blabla1b
+            #  //
+            #  // blabla2
+            # Gets translated into:
+            #      @warning
+            #   blabla1q
+            #   blabla1b
+            #
+            #      @warning
+            #   blabla2
+            
+            elsif ($line =~ /^\/\/(.*)/) {
+                my $remaining = $1;
+                if ($remaining =~ /\S/) {
+                    push @converted, "    $tag\n" 
+                      if $tag ne "" && ! $inblock;
+                    push @converted, $remaining, "\n";
+                    $inblock = 1;
+                } else {
+                    push @converted, "\n";
+                    $inblock = 0;
+                }    
+            } else {
+                # Does not starts with // but still within block or just
+                # before the end (#). Probably an empty line.
+                # Hack : let's have a look at the next line... if it begins
+                # with // then the current line is included (was a space).
+                
+                if (my $next_line = shift @headerfile) {
+                    push @converted, $line if $next_line =~ /^\/\//;
+                    unshift @headerfile, $next_line;
+                }
+            }
+        }
+        
+        # Close the doxygen documentation block describing the class
+        
+        push @converted, "*/\n\n", $line;
+    }
+    
+    # Read until the end of the header and translate the description of
+    # each function provided that it is located in a C++ comment
+    # containing the 'Description:' keyword.
+    # Example:
+    #  // Description:
+    #  // Construct with automatic computation of divisions, averaging
+    #  // 25 points per bucket.
+    #  static vtkPointLocator2D *New();
+    
+    while ($line = shift @headerfile) {
+        
+        if ($line =~ /^(\s*)\/\/\s*De(s|c)(s|c)?ription/) {
+            
+            my $indent = $1;
+            $Text::Wrap::columns = 76;
+            
+            # While there are still lines beginning with '//' append them to
+            # the function's description and trim spaces.
+            
+            my @description = ();
+            while ($line = shift @headerfile) {
+                last if $line !~ /^\s*\/\//;
+                chop $line;
+                $line =~ s/^\s*\/\/\s*//;
+                $line =~ s/\s*$//;
+                push @description, $line;
+            }
+
+            # While there are non-empty lines add these lines to the
+            # list of declarations (and/or inline definitions)
+            # pertaining to the same description.
+
+            my @declarations = ();
+            while ($line && $line =~ /\s+\S/) {
+                push @declarations, $line;
+                $line = shift @headerfile
+            }
+
+            # If there is more than one declaration or at least a macro,
+            # enclose in a group (actually a single multiline declaration will
+            # be enclosed too, but who cares :)...
+
+            my $enclose =
+              (scalar @declarations > 1 || $declarations[0] =~ /vtk.+Macro/);
+            
+            push @converted, "$indent//@\{\n" if $enclose;
+            push @converted, 
+            wrap("$indent/*! ", "$indent    ", @description), " */\n"
+              if @description;
+            push @converted, @declarations;
+            push @converted, "$indent//@\}\n" if $enclose;
+        }
+        
+        push @converted, $line;
+    }
+    
+    # Write the converted header to its destination
+    # or to standard output.
+
+    if (exists $args{"stdout"}) {
+
+        print  @converted;
+
+    } else {
+
+        # Open the target and create the missing directory if any
+
+        if (!sysopen(DEST_FILE, 
+                     $dest, 
+                     O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)) {
+            my $dir = dirname($dest);
+            mkpath($dir);
+            sysopen(DEST_FILE, 
+                    $dest, 
+                    O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+              or croak "$PROGNAME: unable to open destination file $dest\n";
+        }
+        print DEST_FILE @converted;
+        close(DEST_FILE);
+        
+        # If in-place conversion was requested, remove source and rename target
+        # (or temp file) to source
+
+        if (! exists $args{"to"}) {
+            unlink($source)
+              or carp "$PROGNAME: unable to delete original file $source\n";
+            rename($args{"temp"}, $source)
+              or carp "$PROGNAME: unable to rename ", $args{"temp"}, " to $source\n";
+        }
+    }
+}
+
+if (! exists $args{"stdout"}) {
+    print " => $nb_file files converted in ", time() - $intermediate_time, " s. \n";
+    print "Finished in ", time() - $start_time, " s.\n";
+}
diff --git a/bioimagesuite30_src/Utilities/Doxygen/doc_index.pl b/bioimagesuite30_src/Utilities/Doxygen/doc_index.pl
new file mode 100644
index 0000000..3aa3eb9
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/doc_index.pl
@@ -0,0 +1,670 @@
+#!/usr/bin/env perl
+# Time-stamp: <2001-11-21 17:40:48 barre>
+#
+# Build full-text index 
+#
+# barre : Sebastien Barre <sebastien at barre.nom.fr>
+#
+# 0.22 (barre) :
+#   - use common build_page_doc proc
+#
+# 0.21 (barre) :
+#   - add --project name : project name, used to uniquify
+#
+# 0.2 (barre) :
+#   - update to match the new VTK 4.0 tree
+#   - change default --dirs so that it can be launched from Utilities/Doxygen
+#   - change default --stop so that it can be launched from Utilities/Doxygen
+#   - change default --to so that it can be launched from Utilities/Doxygen
+#   - the "class to example" page is now split in different pages
+#   - use --weight to increase or decrease the maximum weight of a page
+#
+# 0.16 (barre) :
+#   - added 'parallel' to the default set of directories
+#
+# 0.15 (barre) :
+#   - change default --to to '../vtk-doxygen' to comply with Kitware's doxyfile
+#   - change default --stop to 'wrap/doc_index.stop' to comply with the source
+#     tree structure.
+#
+# 0.14 (barre) :
+#   - change doxygen command style from \ to @ to match javadoc, autodoc, etc.
+#
+# 0.13 (barre) :
+#   - change default --to to '../vtk-dox'
+#
+# 0.12 (barre)
+#   - change relevancy sorting : for each word, classes are sorted by presence
+#     of the word in the class name, *then* by occurence of the word in the
+#     class documentation, *then* by alphabetical order
+#
+# 0.11 (barre)
+#   - fix O_TEXT flag problem
+#   - switch to Unix CR/LF format
+#
+# 0.1 (barre)
+#   - first release
+
+use Carp;
+use Getopt::Long;
+use Fcntl;
+use File::Find;
+use strict;
+
+my ($VERSION, $PROGNAME, $AUTHOR) = (0.22, $0, "Sebastien Barre");
+$PROGNAME =~ s/^.*[\\\/]//;
+print "$PROGNAME $VERSION, by $AUTHOR\n";
+
+# -------------------------------------------------------------------------
+# Defaults (add options as you want : "verbose" => 1 for default verbose mode)
+
+my %default = 
+  (
+   limit => 10,
+   dirs => ["../../Common", 
+            "../../Filtering", 
+            "../../Graphics", 
+            "../../Hybrid", 
+            "../../Imaging", 
+            "../../IO", 
+            "../../Parallel", 
+            "../../Patented", 
+            "../../Rendering"],
+   project => "VTK",
+   stop => "doc_index.stop",
+   store => "doc_VTK_index.dox",
+   to => "../../../VTK-doxygen",
+   weight => 90000
+  );
+
+# -------------------------------------------------------------------------
+# Parse options
+
+my %args;
+Getopt::Long::Configure("bundling");
+GetOptions (\%args, "help", "verbose|v", "debug", "limit=i", "project=s", "stop=s", "store=s", "to=s", "weight=i");
+
+if (exists $args{"help"}) {
+    print <<"EOT";
+Usage : $PROGNAME [--help] [--verbose|-v] [--limit n] [--stop file] [--store file] [--to path] [--weight n] [files|directories...]
+  --help         : this message
+  --verbose|-v   : verbose (display filenames while processing)
+  --limit n      : limit the number of xrefs per word (default: $default{limit})
+  --project name : project name, used to uniquify (default: $default{project})
+  --stop file    : use 'file' to read stop-words (default: $default{stop})
+  --store file   : use 'file' to store index (default: $default{store})
+  --to path      : use 'path' as destination directory (default : $default{to})
+  --weight n     : use 'n' as an approximation of the maximum page weight (default : $default{weight})
+
+Example:
+  $PROGNAME
+EOT
+    exit;
+}
+
+$args{"debug"} = $default{"debug"} if exists $default{"debug"};
+$args{"verbose"} = 1 if exists $default{"verbose"};
+$args{"limit"} = $default{"limit"} if ! exists $args{"limit"};
+$args{"project"} = $default{"project"} if ! exists $args{"project"};
+$args{"stop"} = $default{"stop"} if ! exists $args{"stop"};
+$args{"store"} = $default{"store"} if ! exists $args{"store"};
+$args{"to"} = $default{"to"} if ! exists $args{"to"};
+$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"};
+$args{"weight"} = $default{"weight"} if ! exists $args{"weight"};
+
+my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i);
+my $open_file_as_text = $os_is_win ? O_TEXT : 0;
+my $start_time = time();
+
+# -------------------------------------------------------------------------
+# Read the stop-words
+
+print "Reading stop-words from $args{stop}...\n";
+
+sysopen(STOPFILE, $args{"stop"}, O_RDONLY|$open_file_as_text)
+  or die "$PROGNAME: unable to open stop words list $args{stop}\n";
+my @stop_file = <STOPFILE>;
+close(HEADERFILE);
+
+my %stop_words;
+foreach my $stop_word (@stop_file) {
+    if ($stop_word && $stop_word !~ m/^\s*#/) {
+        chop $stop_word;
+        $stop_words{$stop_word} = 1;
+    }
+}
+
+print " => ", scalar keys %stop_words, " stop-word(s) read.\n";
+
+# -------------------------------------------------------------------------
+# Collect all files and directories
+
+print "Collecting files...\n";
+
+push @ARGV, @{$default{dirs}} if !@ARGV;
+
+my @files;
+foreach my $file (@ARGV) {
+    if (-f $file) {
+        push @files, $file;
+    } elsif (-d $file) {
+        find sub { push @files, $File::Find::name; }, $file;
+    }
+}
+
+# -------------------------------------------------------------------------
+# Index files corresponding to headers
+
+print "Indexing...\n";
+my $intermediate_time = time();
+
+# %index associates a word with a class name and reports how many times that
+# word was found in that comment.
+# Example: $index{"contour"}{"vtkMarchingCubes"} = 2
+
+my %index;
+keys(%index) = 7000;
+my %group;
+
+my $nb_files = 0;
+undef $/;  # slurp mode
+
+foreach my $source (@files) {
+
+    # Skip what is not a vtk header
+
+    next if $source !~ /(vtk[^\\\/]*)\.h\Z/;
+    my $class = $1;
+    
+    ++$nb_files;
+    print "  $source\n" if exists $args{"verbose"};
+
+    # Open the file, read it entirely
+
+    sysopen(HEADERFILE, $source, O_RDONLY|$open_file_as_text)
+      or croak "$PROGNAME: unable to open $source\n";
+    my $headerfile = <HEADERFILE>;
+    close(HEADERFILE);
+    
+    # Grab all comments then skip the first one (preamble and copyright stuff)
+   
+    my @comments = $headerfile =~ m/(?:\/\*(.+?)\*\/|\/\/(.+?)$)/gms;
+    shift @comments;
+
+    # Grab (and count) each word in each comment and associate it with
+    # the class name
+
+    foreach my $comment (@comments) {
+        next if ! $comment;
+        my @words = $comment =~ m/\b([A-Za-z][A-Za-z-]*[A-Za-z]+)\b/gms;
+        foreach my $word (@words) {
+            $index{$word}{$class}++ if $word;
+        }
+    }
+}
+
+my @words = keys %index;
+print " => ", scalar @words, " word(s) grabbed in $nb_files file(s) in ", time() - $intermediate_time, " s.\n";
+
+# -------------------------------------------------------------------------
+# Remove some words
+
+print "Removing...\n";
+
+my $nb_removed = 0;
+foreach my $word (@words) {
+    my ($len, $lcw, $ucw) = (length($word), lc($word), uc($word));
+    if ($len <= 2 ||                         # too small
+        ($len == 3 && $ucw ne $word) ||      # small and not an accronym
+        (ucfirst($word) ne ucfirst($lcw) && $ucw ne $word) || # mixed case
+        $word =~ m/^vtk/ ||                  # VTK function/class
+        exists $stop_words{lc($word)}) {     # found in stop-words
+        delete $index{$word};
+        ++$nb_removed;
+    }
+}
+
+print " => $nb_removed word(s) removed.\n";
+
+# -------------------------------------------------------------------------
+# Group some words
+
+print "Grouping...\n";
+
+sub transfer_keys {
+    my ($rfrom, $rto) = @_;
+    foreach my $key (keys %$rfrom) {
+        $rto->{$key} += $rfrom->{$key};
+    }
+}
+
+ at words = sort keys %index;
+my $nb_grouped = 0;
+
+foreach my $word (@words) {
+
+    my ($len, $lcw, $similar) = (length($word), lc($word));
+    my (@similars, %verbs, %exts) = ((), (), ());
+
+    # Now first try to get a list of words similar to the current one
+
+    # Lowercase form ?
+
+    if ($word ne $lcw) {
+        push @similars, $lcw;
+    }
+    
+    # Singular form ?
+
+    if ($word =~ m/s$/i) {
+        $similar = substr($word, 0, $len - 1);
+        push @similars, lc($similar), $similar;
+    }
+
+    # Singular form ? (dashes -> dash)
+
+    if ($word =~ m/[hsx]es$/i) {
+        $similar = substr($word, 0, $len - 2);
+        push @similars, lc($similar), $similar;
+
+    # Singular form ? (leaves -> leaf)
+
+    } elsif ($word =~ m/ves$/i) {
+        $similar = substr($word, 0, $len - 3) . 'f';
+        push @similars, lc($similar), $similar;
+    }
+
+    # Colour -> color
+
+    if ($word =~ m/our$/i) {
+        $similar = substr($word, 0, $len - 2) . 'r';
+        push @similars, lc($similar), $similar;
+    }
+
+    # Thick -> thickness
+
+    if ($word =~ m/ness$/i) {
+        $similar = substr($word, 0, $len - 4);
+        push @similars, lc($similar), $similar;
+    }
+
+    # Explicitly -> explicit
+
+    if ($word =~ m/ly$/i) {
+        $similar = substr($word, 0, $len - 2);
+        push @similars, lc($similar), $similar;
+    }
+
+    # Accuracy -> accurate
+
+    if ($word =~ m/acy$/i) {
+        ($similar = $word) =~ s/cy$/te/i;
+        push @similars, lc($similar), $similar;
+    }
+
+    # Rounded, rounding -> round
+
+    if ($word =~ m/.{4,}(ed|ing|ten)$/i) {
+        $exts{$1} = 1;
+        ($similar = $word) =~ s/(ed|ing|ten)$//i;
+        $verbs{$similar} = 1;
+    }
+
+    # Not try to see if it's not a verb (and keep its "extension")
+
+    # Mapped, mapping -> map
+
+    if ($word =~ m/.{3,}[bglmnpt](ed|ing)$/i) {
+        $exts{$1} = 1;
+        ($similar = $word) =~ s/[bglmnpt](ed|ing)$//i;
+        $verbs{$similar} = 1;
+    }
+
+    # Applied -> apply
+
+    if ($word =~ m/.{3,}(ied)$/i) {
+        $exts{$1} = 1;
+        ($similar = $word) =~ s/ied$/y/i;
+        $verbs{$similar} = 1;
+    }
+
+    # Description -> descript
+
+    if ($word =~ m/.{4,}[ts](ion)s?$/i) {
+        $exts{$1} = 1;
+        ($similar = $word) =~ s/ions?$//i;
+        $verbs{$similar} = 1;
+    }
+
+    # Now we have a list of verb and extension, try to associate each verb
+    # with these extensions that were not found and build a list of similar
+    # "words" by concatenating both.
+
+    my @verbs = keys %verbs;
+    if (@verbs) {
+        my %try = ("" => 1, 
+                   "e" => 1, 
+                   "ed" => 1, "ied" => 1, 
+                   "es" => 1, 
+                   "ing" => 1, 
+                   "ion" => 1,
+                   "s" => 1,
+                   "ten" => 1);
+        foreach my $ext (sort keys %exts) {
+            delete $try{$ext};
+        }
+        foreach my $verb (@verbs) {
+            my $lcverb = lc $verb;
+            print " -> ", $lcverb, "\n" if exists $args{"debug"};
+            foreach my $ext (sort keys %try) {
+                print "    +> ", $lcverb . $ext, "\n" if exists $args{"debug"};
+                push @similars, $lcverb . $ext, $verb . $ext;
+            }
+        }
+    }
+
+    # Browse each similar word. It it already exists in the index then group
+    # the current word with it and remove the word from the index.
+
+    foreach $similar (@similars) {
+        if (exists $index{$similar}) {
+            print "- grouping $word with $similar\n" if exists $args{"debug"};
+            transfer_keys(\%{$index{$word}}, \%{$index{$similar}});
+            delete $index{$word};
+            $group{$similar}{$word}++;
+            transfer_keys(\%{$group{$word}}, \%{$group{$similar}});
+            delete $group{$word};
+            ++$nb_grouped;
+            last;
+        }
+    }
+}
+
+print " => $nb_grouped word(s) grouped.\n";
+
+# -------------------------------------------------------------------------
+# Normalize to lowercase except if all uppercase
+
+print "Normalizing...\n";
+
+ at words = keys %index;
+foreach my $word (@words) {
+    my $lcw = lc $word;
+
+    # Normalize word to lowercase
+
+    if ($word ne uc($word) && $word ne $lcw) {
+        transfer_keys(\%{$index{$word}}, \%{$index{$lcw}});
+        delete $index{$word};
+        transfer_keys(\%{$group{$word}}, \%{$group{$lcw}});
+        delete $group{$word};
+    }
+
+    # Normalize group to lowercase
+
+    if (exists $group{$word}) {
+        foreach my $gword (keys %{$group{$word}}) {
+            my $lcgw = lc $gword;
+            if ($gword ne uc($gword) && $gword ne $lcgw) {
+                $group{$word}{$lcgw} = $group{$word}{$gword};
+                delete $group{$word}{$gword};
+            }
+        }
+        delete $group{$word}{$word};
+    }
+}
+
+print " => normalized to lowercase.\n";
+
+# -------------------------------------------------------------------------
+# Build the page summary documentation
+
+# $indent is the indentation string
+
+my $indent = "    ";
+
+# $header is the Doxygen string summarizing what has been documented as well
+# as the credits.
+
+my $header;
+my (@summary, @credits);
+
+push @summary, 
+  "  - $nb_files file(s) indexed by " . scalar @words . " word(s) on " . 
+  localtime(),
+  "  - max limit is " . $args{"limit"} . " xref(s) per word";
+
+push @credits, 
+  "\@version $VERSION",
+  "\@author \@c $PROGNAME, by $AUTHOR";
+
+$header = $indent . join("\n$indent", @summary) . 
+  "\n\n$indent" . join("\n$indent", @credits) . "\n\n";
+
+# -------------------------------------------------------------------------
+# Index to class
+
+print "Building page doc...\n";
+
+# @words is the array of words to document
+
+my @words = sort keys %index;
+
+# $prefix is a unique prefix that is appended to each link
+
+my $prefix = "idx_" . $args{"project"};
+$prefix = lc($prefix);
+
+# word_section_name returns the short string describing a word section
+
+sub word_section_name {
+    my ($word) = @_;
+    my @group = sort keys %{$group{$word}};
+    $word .= " (" . join(", ", @group) . ")" if @group;
+    return $word;
+}
+    
+# word_section_doc returns the doxygen doc for a word
+
+sub word_section_doc {
+    my ($word) = @_;
+    my @xrefs = sort { (($b =~ m/$word/i) <=> ($a =~ m/$word/i)) || ($index{$word}{$b} <=> $index{$word}{$a}) || ($a cmp $b)} (keys %{$index{$word}});
+    my @xrefs_lim;
+    my $count = 0;
+    foreach my $xref (@xrefs) {
+        last if ++$count > $args{"limit"};
+        push @xrefs_lim, $xref . " (" . $index{$word}{$xref} . ")";
+    }
+    my $string = "  - " . join(", ", @xrefs_lim);
+    $string .= ", [...]" if scalar keys %{$index{$word}} > $args{"limit"};
+    return $string . "\n";
+}
+
+# word_section_alpha returns the single alpha char corresponding to that
+# word's section.
+
+sub word_section_alpha {
+    my ($word) = @_;
+    $word =~ /^(\w)/;
+    return $1;
+}
+
+my $page_doc = build_page_doc($indent,
+                              "Full-text Index",
+                              \@words, 
+                              $prefix, 
+                              \&word_section_name, 
+                              \&word_section_doc,
+                              \&word_section_alpha,
+                              $header,
+                              "",
+                              $args{"to"} . "/" . $args{"store"});
+
+print join("\n", @summary), "\n";
+print "Finished in ", time() - $start_time, " s.\n";
+
+# -------------------------------------------------------------------------
+
+sub build_page_doc {
+
+    # $indent is the indentation string
+    # $rwords is a reference to the array of words to document
+    # $prefix is a unique prefix that is appended to each link
+    # word_section_name returns the short string describing a word section
+    # word_section_doc returns the doxygen doc for a word
+    # word_section_alpha returns the single alpha char corresponding to that
+    # word's section.
+    # $header is the Doxygen string summarizing what has been documented as 
+    # well as the credits.
+    # $footer is a Doxygen string appended to each the resulting page
+    # $destination_file is the name of the file where this page should be
+    # written to.
+
+    my ($ident, $title, $rwords, $prefix, $rword_section_name, $rword_section_doc, $rword_section_alpha, $header, $footer, $destination_file) = @_;
+
+    # %words_doc is a hash associating a word to its Doxygen doc (string)
+
+    my %words_doc;
+
+    # %sections_words is a hash associating a section (alphabetical letter) to
+    # an array of words belonging to that section.
+    #   Ex: $sections_words{"C"} => ("contour", "cut")
+    # %sections_weight is a hash associating a section to its weight (the sum 
+    # of the weights of each word belonging to that section).
+    # @sections is the array holding the name of all sections
+
+    my (%sections_words, %sections_weight, @sections);
+
+    # $navbar is the Doxygen string describing the sections' navigation bar
+    
+    my $navbar;
+    
+    my $intermediate_time = time();
+    
+    # Browse each word
+
+    foreach my $word (@$rwords) {
+
+        my @temp;
+        push @temp, &$rword_section_name($word), &$rword_section_doc($word);
+        $words_doc{$word} = $indent . join("\n$indent", @temp) . "\n";
+
+        # Update section(s) and section(s) weight(s)
+
+        my $section = &$rword_section_alpha($word);
+        push @{$sections_words{$section}}, $word;
+        $sections_weight{$section} += length($words_doc{$word});
+        
+        print " => ", $word, "\n" if exists $args{"verbose"};
+    }
+
+    print " => ", scalar @$rwords, " words(s) documented in ", time() - $intermediate_time, " s.\n";
+    
+    @sections = sort keys %sections_words;
+
+    # Build the navbar
+    
+    my @temp;
+    foreach my $section (@sections) {
+        push @temp, "\@ref ${prefix}_section_$section \"$section\"";
+    }
+    $navbar = "$indent\@par Navigation: \n$indent\[" . 
+      join(" | ", @temp) . "]\n";
+
+    # Add the (approximate) weight of the (header + navbar) to each section
+
+    my $total_weight = 0;
+    my $header_weight = length($indent) + 24 + length($navbar);
+
+    foreach my $section (@sections) {
+        $sections_weight{$section} += $header_weight;
+        $total_weight += $sections_weight{$section};
+    }
+
+    if (exists $args{"verbose"}) {
+        foreach my $section (@sections) {
+            printf("\t- %s : %6d\n", $section, $sections_weight{$section});
+        }
+    }
+
+    print " => total weight is $total_weight in ", scalar @sections, " section(s) (mean is ", int($total_weight / scalar @sections), ")\n";
+
+    # Compute the alphabetical groups by joining sections depending on weights
+
+    print "Computing alphabetical group(s)/page(s)...\n";
+
+    # %groups is a hash associating a group id (int) to an array of sections 
+    # namesbelonging to that group.
+    #   Ex: $groups{"0"} => ("A", "B", "C")
+    # %groups_weight is a hash associating a group id to its weight (the sum
+    # of the weights of each section belonging to that group).
+
+    my (%groups, %groups_weight);
+
+    my $groupid = 0;
+
+    # Remove a section one by one, and put it in a group until the group if 
+    # full,then create a next group, etc., until the sections are exhausted.
+
+    my @sections_temp = @sections;
+    while (@sections_temp) {
+        $groups_weight{$groupid} = $sections_weight{$sections_temp[0]};
+        push @{$groups{$groupid}}, shift @sections_temp;
+        while (@sections_temp && 
+               ($groups_weight{$groupid} +$sections_weight{$sections_temp[0]}) 
+               <= $args{"weight"}) {
+            $groups_weight{$groupid} += $sections_weight{$sections_temp[0]};
+            push @{$groups{$groupid}}, shift @sections_temp;
+        }
+        $groupid++;
+    }
+
+    if (exists $args{"verbose"}) {
+        foreach my $groupid (sort {$a <=> $b} keys %groups) {
+            printf("\t- %02d (weight: %7d) : %s\n", $groupid, 
+                   $groups_weight{$groupid}, join(", ", @{$groups{$groupid}}));
+        }
+    }
+
+    print " => max weight is ", $args{"weight"}, " per group/page, but a section can not be divided\n";
+    print " => ", scalar  keys %groups, " group(s) for ", scalar @sections, " section(s)\n";
+
+    # Build documentation page
+    # Browse each group, each section in this group, each word in this section
+
+    my $page_doc;
+
+    foreach my $groupid (sort {$a <=> $b} keys %groups) {
+
+        my $fromto = $groups{$groupid}[0];
+        $fromto .= ".." . $groups{$groupid}[scalar @{$groups{$groupid}} - 1]
+          if scalar @{$groups{$groupid}} > 1;
+
+        $page_doc .= 
+          "/*! \@page ${prefix}_$groupid $title ($fromto)\n\n$header"; 
+
+        foreach my $section (@{$groups{$groupid}}) {
+            $page_doc .=
+              "\n$indent\@section ${prefix}_section_$section $section\n\n$navbar\n";
+            foreach my $word (@{$sections_words{$section}}) {
+                $page_doc .= $words_doc{$word}, "\n";
+            }
+            print "\t- $section\n" if exists $args{"verbose"};
+        }
+        $page_doc .= "$footer\n*/\n\n";
+    }
+
+    print "Writing documentation to ", $destination_file, "...\n";
+
+    $intermediate_time = time();
+
+    sysopen(DEST_FILE, 
+            $destination_file, 
+            O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+     or croak "$PROGNAME: unable to open destination file $destination_file\n";
+    print DEST_FILE $page_doc;
+    close(DEST_FILE);
+
+    print " => written in ", time() - $intermediate_time, " s.\n";
+}
+
diff --git a/bioimagesuite30_src/Utilities/Doxygen/doc_makeall.in b/bioimagesuite30_src/Utilities/Doxygen/doc_makeall.in
new file mode 100644
index 0000000..42c463f
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/doc_makeall.in
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+DOXYGEN_PROG="doxygen"
+DOXYGEN_ARGS="${BIOIMAGESUITE3_SOURCE_DIR}/Utilities/Doxygen/doxyfile"
+
+$DOXYGEN_PROG $DOXYGEN_ARGS
diff --git a/bioimagesuite30_src/Utilities/Doxygen/doc_readme.txt b/bioimagesuite30_src/Utilities/Doxygen/doc_readme.txt
new file mode 100644
index 0000000..e314ac7
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/doc_readme.txt
@@ -0,0 +1,358 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+Documenting VTK with doxygen
+----------------------------
+
+Sebastien BARRE (Time-stamp: <2001-10-24 22:38:42 barre>)
+
+This file describes how to generate a Doxygen-compliant documentation
+featuring cross-references between classes and examples, a full-text index
+and an accurate VTK version. 
+
+Note that this file describes how to run the scripts manually, which
+can be tedious (to say the least). A batch file doc_makeall.sh is now
+used to automate this process. It is part of the CMake/Build process
+and is configured both though CMake and through its own parameter. It
+should be pretty straightforward to understand and adapt.
+
+Warning
+-------
+
+These scripts are now part of the VTK source distribution.
+
+Think twice before letting Doxygen eat your CPU cycles: Kitware is
+now using these scripts to build an up-to-date Doxygen-compliant
+documentation every night as part of the "nightly build"
+process. Thus, you might browse or download a pre-built documentation here:
+
+         http://public.kitware.com/doc/
+
+Nevertheless, Doxygen might still be useful to generate additional
+PDF, Postscript or plain LaTeX output.
+
+This package is made of he following Perl scripts:
+
+- doc_header2doxygen.pl: convert the VTK headers to the Doxygen format
+- doc_version.pl: extract the VTK version and add it to the documentation set
+- doc_class2example.pl: build cross-references between classes and examples
+- doc_index.pl: build the full-text index 
+
+Use the --help option to display the parameters that are allowed for each
+script.
+
+Thanks to Vetle Roeim and Jan Stifter who started the project :)
+
+
+A. Preamble
+   --------
+
+I assume that your VTK distribution is in a 'VTK' directory and that
+you do NOT want to modify it in any ways. You would rather create a
+modified copy of the VTK files in a different location (here, the
+'../VTK-doxygen' directory, assuming that you are in the 'VTK'
+directory now). Hence, you might use this main 'VTK' directory for CVS
+and development purposes (updating it from time to time) and rerun
+the process described below to update your documentation (a
+straightforward process once you get used to it).
+
+The Perl scripts described in that document are stored in the
+'VTK/Utilities/Doxygen' directory. You will also find a couple of
+additional files like a VTK logo and a batch script automating the
+whole conversion process. Thus, the directories that are of some
+interest in that README are:
+
+   VTK/ : the VTK repository
+   VTK/Utilities/Doxygen : the Doxygen scripts and configuration files
+   VTK-Doxygen/ : the intermediate VTK repository
+
+The doxygen configuration script, i.e. the script controlling how this
+VTK documentation is created, is named 'doxyfile'; it is also stored
+in the 'VTK/Utilities/Doxygen' directory. It is read by doxygen and
+lists option/value pairs like:
+
+    PARAMETER = VALUE
+ 
+Comment lines are allowed and start with '#'. Commenting a directive
+is a simple way to hide it to doxygen:
+
+#   PARAMETER = VALUE
+
+Do not forget to set the OUTPUT_DIRECTORY directive specifying the
+location where the whole documentation is to be stored. Example:
+
+    OUTPUT_DIRECTORY     = ../../../doc
+
+The crucial INPUT directive controls which directory or files are
+processed by doxygen to produce the documentation. Each directory/file
+is separated by a space. Whenever you will be requested to add a
+filename to INPUT, just add it to the end of the list. Example:
+
+    INPUT = ../../../VTK-doxygen/Common ../../../VTK-doxygen/Filtering ../../../VTK-doxygen/Graphics ../../../VTK-doxygen/Hybrid ../../../VTK-doxygen/Imaging ../../../VTK-doxygen/IO ../../../VTK-doxygen/Parallel ../../../VTK-doxygen/Patented ../../../VTK-doxygen/Rendering ../../../VTK-doxygen/doc_version.dox ../../../VTK-doxygen/doc_class2examples.dox ../../../VTK-doxygen/doc_class2tests.dox ../../../VTK-doxygen/doc_index.dox
+
+WARNING: disable the HAVE_DOT directive if you have not installed graphviz
+(http://www.research.att.com/~north/graphviz/download.html).
+
+
+B.  Download doxygen, make sure it runs 
+    -----------------------------------
+
+    http://www.doxygen.org
+
+
+C0. Go to the VTK/Utilities/Doxygen directory
+    -----------------------------------------
+ 
+    You are supposed to run all scripts as well as Doxygen from this
+    directory.
+
+For example:
+
+    D:\src\kitware\vtk\VTK> cd Utilities\Doxygen
+    D:\src\kitware\vtk\VTK\Utilities\Doxygen>
+
+
+C1. Convert the VTK headers to Doxygen format
+    -----------------------------------------
+
+    Use the conversion script: doc_header2doxygen.pl 
+
+For example: 
+
+    D:\src\kitware\vtk\VTK\Utilities\Doxygen> perl doc_header2doxygen.pl --to ../../../VTK-doxygen
+    doc_header2doxygen.pl 0.8, by Sebastien Barre et al.
+    Collecting...
+    Converting...
+     => 729 files converted in 6 s.
+    Finished in 7 s.
+
+Meaning that:
+
+    The optional '--to ../../../VTK-doxygen' parameter specifies that the
+    script stores the modified C++ *headers* (*.h files)  in the
+    '../../../VTK-doxygen' directory (here: 'D:\src\kitware\vtk\VTK-doxygen',
+    as I issued the command from 'D:\src\kitware\vtk\VTK\Utilities\Doxygen').
+    The files located in 'VTK' remain untouched. The script browses
+    the directories located two levels up (i.e. ../../) automatically.
+
+    Use --help to display the default value associated to --to.
+     
+    Note that you might restrict the conversion to a set of particuliar
+    directories or files if you want to document a specific VTK part only:
+    just add these parts as parameters. Example:
+
+    D:\src\kitware\vtk\VTK\Utilities\Doxygen> perl doc_header2doxygen.pl --to ../../../VTK-doxygen ../../Hybrid
+
+Update the Doxygen configuration file ('doxyfile'):
+
+    Depending on the location from where you are going to run Doxygen
+    (here: 'D:\src\kitware\vtk\VTK\Utilities\Doxygen') update or add
+    the paths to the VTK components/directories that you want to
+    document. Since the headers have been created in
+    '../../../VTK-doxygen', the following values will be fine:
+
+    INPUT = ../../../VTK-doxygen/Common ../../../VTK-doxygen/Filtering ../../../VTK-doxygen/Graphics ../../../VTK-doxygen/Hybrid ../../../VTK-doxygen/Imaging ../../../VTK-doxygen/IO ../../../VTK-doxygen/Parallel ../../../VTK-doxygen/Patented ../../../VTK-doxygen/Rendering
+
+
+C2. Extract VTK version
+    -------------------
+
+    Use the extraction script: doc_version.pl 
+
+For example: 
+
+    D:\src\kitware\vtk\VTK\Utilities\Doxygen> perl doc_version.pl --logo "vtk-logo.gif" --to ../../../VTK-doxygen
+    doc_version.pl 0.22, by Sebastien Barre
+     => 4.0.0
+     => $Revision: 1.4 $ $Date: 2001/10/25 02:48:20 $
+    Building version documentation to ../../../VTK-doxygen/doc_version.dox
+    Finished in 0 s.
+
+Meaning that:
+
+    The optional '--to ../../../VTK-doxygen' parameter specifies that
+    the script stores the related documentation part in the
+    '../../../VTK-doxygen' directory (more precisely in the
+    '../../../VTK-doxygen/doc_version.dox' file). The VTK logo is
+    incorporated by using the --logo option. The script searchs for
+    the VTK version in the '../../Common/vtkVersion.h'. Use --help to
+    check how to override these default values.
+
+Update the Doxygen configuration file ('doxyfile'):
+
+    Comment the PROJECT_NUMBER directive: you do not need it anymore
+    as you have just created a more accurate description based on the
+    current vtkVersion.h.
+
+    # PROJECT_NUMBER       =
+
+
+C3. Generate the 'class to examples' pages 
+    --------------------------------------
+
+    Use the referencing script: doc_class2example.pl 
+
+For example: 
+    
+    D:\src\kitware\vtk\VTK\Utilities\Doxygen> perl doc_class2example.pl --link http://public.kitware.com/cgi-bin/cvsweb.cgi/~checkout~/VTK/Utilities/Doxygen --to ../../../VTK-doxygen
+    doc_class2example.pl 0.7, by Sebastien Barre
+    Collecting files...
+     => 17 file(s) collected in 2 s.
+    Parsing files...
+     => 17 file(s) parsed in 0 s.
+    Eliminating some classes...
+     => 1 class(es) eliminated (vtkCommand) in 0 s.
+    Locating headers to update...
+     => 33 found, 8 orphan class(es) removed (vtkIOJava, vtkRenderingJava, vtkCommonJava, vtkImagingJava, vtkGraphicsJava, vtkInteract, vtkTkWidget, vtkFilteringJava) in 0 s.
+    Building classes doc and alphabetical section(s) weight(s)...
+     => 33 classes(s) documented in 0 s.
+     => total weight is 38604 in 13 section(s) (mean is 2969)
+    Computing alphabetical group(s)/page(s)...
+     => max weight is 90000 per group/page, but a section can not be divided
+     => 1 group(s) for 13 section(s)
+    Building pages header...
+    Writing documentation to ../../../VTK-doxygen/doc_class2examples.dox...
+      - 33 class(es) in 17 file(s) from directories matching @c ^Examples$ on Mon Oct  1 10:53:04 2001
+      - 4 parser(s) : [Java, Python, C++, Tcl]
+      - at most 20 file(s) per parser (0% over)
+     => in 0 s.
+    Updating headers...
+     => 32 header(s) updated in 0 s.
+Finished in 2 s.
+
+Meaning that :
+
+    The optional '--to ../../../VTK-doxygen' parameter specifies that
+    the script searches (and parses) the Python, Tcl, Java or C++
+    *examples* (17 here) in the directories two level up (i.e. ../../
+    and below) but updates the C++ class *headers* (32 here) stored in
+    the '../../../VTK-doxygen' directory (which is good because they
+    have just been created in step C1). These headers are updated to
+    include cross-links between the class and the examples using
+    it. The script stores the documentation file listing all examples
+    in the '../../../VTK-doxygen/doc_class2example.dox' file. Once
+    again, the files located in 'VTK' remain untouched. The --link
+    option is a path or a URL that is prepended to each example's name
+    to provide a physical link to that example (here, the CVSweb).
+
+    Use --help to check how to override these default values. More
+    specifically you can override the --dirmatch option (a regexp) so
+    that the parsers will only look into specific directories. The
+    default value "^Examples\$" constrains the script to any
+    directory which name is 'Example'; --dirmatch "^Testing$" will
+    actually make the script parse all examples found in the 'Testing'
+    directories (the --label, --title and --unique option should be changed
+    appropriately, check 'doc_makeall.bat' for example).
+
+Update the Doxygen configuration file ('doxyfile'):
+
+    Add the relative path to 'doc_class2example.dox' (here :
+    '../../../VTK-doxygen/doc_class2example.dox') to the INPUT
+    directive, so that Doxygen might process it (see also section D).
+
+
+C4. Build full-text index 
+    ---------------------
+
+    Use the indexing script: doc_index.pl 
+
+For example: 
+
+    D:\src\kitware\vtk\VTK\Utilities\Doxygen> perl doc_index.pl --to ../../../VTK-doxygen
+    doc_index.pl 0.2, by Sebastien Barre
+    Reading stop-words from doc_index.stop...
+     => 724 stop-word(s) read.
+    Collecting files...
+    Indexing...
+     => 8174 word(s) grabbed in 729 file(s) in 2 s.
+    Removing...
+     => 3126 word(s) removed.
+    Grouping...
+     => 2075 word(s) grouped.
+    Normalizing...
+     => normalized to lowercase.
+    Building indexes doc and alphabetical section(s) weight(s)...
+     => 2973 words(s) documented in 2 s.
+     => total weight is 400800 in 47 section(s) (mean is 8527)
+    Computing alphabetical group(s)/page(s)...
+     => max weight is 90000 per group/page, but a section can not be divided
+     => 6 group(s) for 47 section(s)
+    Building pages header...
+    Writing documentation to ../../../VTK-doxygen/doc_index.dox...
+      - 729 file(s) indexed by 2973 word(s) on Mon Oct  1 11:13:44 2001
+      - max limit is 10 xref(s) per word
+    Finished in 5 s.
+
+Meaning that:
+
+    The optional '--to ../../../VTK-doxygen' parameter specifies that
+    the script stores the full-text index in the
+    '../../../VTK-doxygen' directory (more precisely in the
+    '../../../VTK-doxygen/doc_index.dox' file).
+
+    The optional --stop parameter can be used to specify that the
+    script should read its stop-words from a different file (default
+    is 'doc_index.stop').  This file is a list of trivial words (one
+    per line) that won't be indexed.
+
+Update the Doxygen configuration file ('doxyfile'):
+
+    Add the relative path to 'doc_index.dox' (here :
+    '../../../VTK-doxygen/doc_index.dox') to the INPUT directive, so that
+    Doxygen might process it (see also section D)
+
+
+D.  Run doxygen 
+    -----------
+
+    Check that your Doxygen configuration file is OK
+    ('doxyfile'). The important directives are:
+
+    PROJECT_NAME         = VTK
+    # PROJECT_NUMBER     =
+    OUTPUT_DIRECTORY     = ../../../doc
+    INPUT = ../../../VTK-doxygen/Common ../../../VTK-doxygen/Filtering ../../../VTK-doxygen/Graphics ../../../VTK-doxygen/Hybrid ../../../VTK-doxygen/Imaging ../../../VTK-doxygen/IO ../../../VTK-doxygen/Parallel ../../../VTK-doxygen/Patented ../../../VTK-doxygen/Rendering ../../../VTK-doxygen/doc_version.dox ../../../VTK-doxygen/doc_class2examples.dox ../../../VTK-doxygen/doc_class2tests.dox ../../../VTK-doxygen/doc_index.dox
+
+    Then run doxygen. Be *patient* :)
+
+For example: 
+
+    D:\src\kitware\vtk\VTK\Utilities\Doxygen> doxygen
+
+    The documentation will be located in the '../../../doc'
+    directory. If that directory does not exist, doxygen will create it,
+    *unless* the its parent directory does not exist either.
+
+    You are done.
+    Browse the HTML documentation starting from:
+    doc/html/index.html
+
+
+Just my 2 cents.
+
+Sebastien BARRE
+
diff --git a/bioimagesuite30_src/Utilities/Doxygen/doc_rmpath.pl b/bioimagesuite30_src/Utilities/Doxygen/doc_rmpath.pl
new file mode 100644
index 0000000..bdffe39
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/doc_rmpath.pl
@@ -0,0 +1,111 @@
+#!/usr/bin/env perl
+# Time-stamp: <2001-10-05 11:49:40 barre>
+#
+# Remove path to intermediate Doxygen dir from html doc
+#
+# barre : Sebastien Barre <sebastien at barre.nom.fr>
+#
+# 0.1 (barre)
+#   - first release
+
+use Carp;
+use Cwd 'abs_path';
+use Getopt::Long;
+use Fcntl;
+use File::Find;
+use strict;
+
+my ($VERSION, $PROGNAME, $AUTHOR) = (0.1, $0, "Sebastien Barre");
+$PROGNAME =~ s/^.*[\\\/]//;
+print "$PROGNAME $VERSION, by $AUTHOR\n";
+
+# -------------------------------------------------------------------------
+# Defaults (add options as you want : "verbose" => 1 for default verbose mode)
+
+my %default = 
+  (
+   html => "../../../doc/html",
+   to => "../../../VTK-doxygen"
+  );
+
+# -------------------------------------------------------------------------
+# Parse options
+
+my %args;
+Getopt::Long::Configure("bundling");
+GetOptions (\%args, "help", "verbose|v", "html=s", "to=s");
+
+if (exists $args{"help"}) {
+    print <<"EOT";
+Usage : $PROGNAME [--help] [--verbose|-v] [--html path] [--to path]
+  --help       : this message
+  --verbose|-v : verbose (display filenames while processing)
+  --html path  : 'path' the Doxygen generated HTML doc (default : $default{html})
+  --to path    : 'path' to intermediate Doxygen dir (default : $default{to})
+
+Example:
+  $PROGNAME
+EOT
+    exit;
+}
+
+$args{"to"} = $default{"to"} if ! exists $args{"to"};
+$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"};
+$args{"html"} = $default{"html"} if ! exists $args{"html"};
+$args{"html"} =~ s/[\\\/]*$// if exists $args{"html"};
+
+my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i);
+my $open_file_as_text = $os_is_win ? O_TEXT : 0;
+my $start_time = time();
+
+# -------------------------------------------------------------------------
+# Collect all HTML files
+
+print "Collecting HTML files in ", $args{"html"}, "\n";
+
+my @files;
+find sub { 
+    push @files, $File::Find::name
+      if -f $_ && $_ =~ /\.html$/;
+}, $args{"html"};
+
+print " => ", scalar @files, " file(s) collected in ", time() - $start_time, " s.\n";
+
+# -------------------------------------------------------------------------
+# Remove path 
+
+my ($nb_files, $htmlpath) = (0, abs_path($args{"to"}) . '/');
+undef $/;  # slurp mode
+
+print "Removing $htmlpath and writing...\n";
+my $intermediate_time = time();
+
+foreach my $filename (@files) {
+
+    print "  $filename\n" if exists $args{"verbose"};
+
+    # Open the file, read it entirely
+
+    sysopen(HTMLFILE, 
+            $filename, 
+            O_RDONLY|$open_file_as_text)
+      or croak "$PROGNAME: unable to open $filename\n";
+    my $html = <HTMLFILE>;
+    close(HTMLFILE);
+    
+    # Remove all paths
+   
+    if ($html =~ s/$htmlpath//gms) {
+        ++$nb_files;
+        sysopen(HTMLFILE, 
+                $filename, 
+                O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+          or croak "$PROGNAME: unable to open destination file $filename\n";
+        print HTMLFILE $html;
+        close(HTMLFILE);
+    }
+}
+
+print " => $nb_files file(s) processed and written in ", time() - $intermediate_time, " s.\n";
+print "Finished in ", time() - $start_time, " s.\n";
+
diff --git a/bioimagesuite30_src/Utilities/Doxygen/doc_version.pl b/bioimagesuite30_src/Utilities/Doxygen/doc_version.pl
new file mode 100644
index 0000000..6157a59
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/doc_version.pl
@@ -0,0 +1,192 @@
+#!/usr/bin/env perl
+# Time-stamp: <2002-11-22 16:23:16 barre>
+#
+# Extract VTK version and add it to documentation
+#
+# barre : Sebastien Barre <sebastien at barre.nom.fr>
+#
+# 0.3 (barre) :
+#   - update to search for the version infos in a different file
+#     (i.e. top CMakeLists.txt file instead of vtkVersion.h)
+#   - --header becomes --revision_file and --version_file
+#
+# 0.25 (barre) :
+#   - update useful links for Dart
+#
+# 0.24 (barre) :
+#   - update useful links for new public.kitware.com structure
+#
+# 0.23 (barre) :
+#   - update useful links
+#
+# 0.22 (barre) :
+#   - add more (useful) links to various VTK documentation ressources
+#
+# 0.21 (barre) :
+#   - no more --logo defaults
+#
+# 0.2 (barre) :
+#   - update to match the new VTK 4.0 tree
+#   - change default --header so that it can be launched from Utilities/Doxygen
+#   - change default --to so that it can be launched from Utilities/Doxygen
+#   - add --logo file : use 'file' as logo
+#
+# 0.16 (barre) :
+#   - change default --to to '../vtk-doxygen' to comply with Kitware
+#   - update VTK home page URL.
+#
+# 0.15 (barre) :
+#   - fix RCS/CVS tags problem (regexp replacement when this file is in a CVS)
+#
+# 0.14 (barre) :
+#   - as doxygen now handles RCS/CVS tags of the form $word:text$, use them 
+#
+# 0.13 (barre) :
+#   - change doxygen command style from \ to @ to match javadoc, autodoc, etc.
+#
+# 0.12 (barre) :
+#   - change default --to to '../vtk-dox'
+#
+# 0.11 (barre)
+#   - fix O_TEXT flag problem
+#   - switch to Unix CR/LF format
+#
+# 0.1 (barre)
+#   - initial release
+
+use Carp;
+use Fcntl;
+use File::Basename;
+use Getopt::Long;
+use strict;
+
+my ($VERSION, $PROGNAME, $AUTHOR) = (0.3, $0, "Sebastien Barre");
+$PROGNAME =~ s/^.*[\\\/]//;
+print "$PROGNAME $VERSION, by $AUTHOR\n";
+
+# -------------------------------------------------------------------------
+# Defaults (add options as you want: "verbose" => 1 for default verbose mode)
+
+my %default = 
+  (
+   version_file => "../../CMakeLists.txt",
+   revison_file => "../../Common/vtkVersion.h",
+   store => "doc_VTK_version.dox",
+   to => "../../../VTK-doxygen"
+  );
+
+# -------------------------------------------------------------------------
+# Parse options
+
+my %args;
+Getopt::Long::Configure("bundling");
+GetOptions (\%args, "help", "revision_file=s", "version_file=s", "logo=s", "store=s", "to=s");
+
+if (exists $args{"help"}) {
+    print <<"EOT";
+by $AUTHOR
+Usage : $PROGNAME [--help] [--revision_file file] [--store file] [--to path]
+  --help        : this message
+  --revision_file file : use 'file' to find revision (default: $default{revision_file})
+  --version_file file : use 'file' to find version info (default: $default{version_file})
+  --logo file   : use 'file' as logo (default: $default{logo})
+  --store file  : use 'file' to store version (default: $default{store})
+  --to path     : use 'path' as destination directory (default: $default{to})
+
+Example:
+  $PROGNAME
+EOT
+    exit;
+}
+
+$args{"revision_file"} = $default{"revision_file"} if ! exists $args{"revision_file"};
+$args{"version_file"} = $default{"version_file"} if ! exists $args{"version_file"};
+$args{"logo"} = $default{"logo"} if ! exists $args{"logo"};
+$args{"store"} = $default{"store"} if ! exists $args{"store"};
+$args{"to"} = $default{"to"} if ! exists $args{"to"};
+$args{"to"} =~ s/[\\\/]*$// if exists $args{"to"};
+
+my $os_is_win = ($^O =~ m/(MSWin32|Cygwin)/i);
+my $open_file_as_text = $os_is_win ? O_TEXT : 0;
+my $start_time = time();
+
+# -------------------------------------------------------------------------
+# Try to get VTK version and revision
+
+my ($major_version, $minor_version, $build_version, $revision, $date) = (undef, undef, undef);
+
+sysopen(FILE, $args{"version_file"}, O_RDONLY|$open_file_as_text)
+  or croak "$PROGNAME: unable to open $args{version_file}\n";
+
+while (<FILE>) {
+    if ($_ =~ /VTK_MAJOR_VERSION\s+(\d+)/) {
+        $major_version = $1;
+        print " major => $major_version\n";
+    } elsif ($_ =~ /VTK_MINOR_VERSION\s+(\d+)/) {
+        $minor_version = $1;
+        print " minor => $minor_version\n";
+    } elsif ($_ =~ /VTK_BUILD_VERSION\s+(\d+)/) {
+        $build_version = $1;
+        print " build => $build_version\n";
+    }
+}
+
+close(FILE);
+
+croak "$PROGNAME: unable to find version in " . $args{"version_file"} . "\n"
+  if (!defined $major_version || !defined $minor_version || !defined $build_version);
+
+sysopen(FILE, $args{"revision_file"}, O_RDONLY|$open_file_as_text)
+  or croak "$PROGNAME: unable to open $args{revision_file}\n";
+
+while (<FILE>) {
+    if ($_ =~ /define\s+VTK_SOURCE_VERSION.*(.Revision:.*.?\$).*(.Date:.*?\$).*\"/) {
+        $revision = $1;
+        $date = $2;
+        print " revision => $revision $date\n";
+        last;
+    }
+}
+
+close(FILE);
+
+croak "$PROGNAME: unable to find revision/date in " . $args{"revision_file"} . "\n"
+  if (!defined $revision || !defined $date);
+
+# -------------------------------------------------------------------------
+# Build documentation
+
+my $destination_file = $args{"to"} . "/" . $args{"store"};
+print "Building version documentation to ", $destination_file, "\n";
+
+sysopen(DEST_FILE, 
+        $destination_file, 
+        O_WRONLY|O_TRUNC|O_CREAT|$open_file_as_text)
+  or croak "$PROGNAME: unable to open destination file " . $destination_file . "\n";
+
+print DEST_FILE 
+  "/*! \@mainpage VTK $major_version.$minor_version.$build_version Documentation\n\n";
+
+print DEST_FILE 
+  "  \@image html " . basename($args{"logo"}) . "\n"
+  if exists $args{"logo"} && -f $args{"logo"};
+
+print DEST_FILE 
+  "  $revision\n",
+  "  $date\n",
+  "  \@par Useful links:\n",
+  "  \@li VTK Home: http://www.vtk.org\n",
+  "  \@li VTK Mailing-list: http://public.kitware.com/mailman/listinfo/vtkusers\n",
+  "  \@li VTK FAQ: http://public.kitware.com/cgi-bin/vtkfaq\n",
+  "  \@li VTK Search: http://www.kitware.com/search.html\n",
+  "  \@li VTK Dashboard: http://www.vtk.org/Testing/Dashboard/MostRecentResults-Nightly/Dashboard.html",
+  "  \@li VTK-Doxygen scripts (Sebastien Barre): http://www.barre.nom.fr/vtk/doc/README\n",
+  "  \@li Kitware Home: http://www.kitware.com\n",
+  "  \@li Sebastien's VTK Links: http://www.barre.nom.fr/vtk/links.html\n",
+  "  \@li Other Links: http://www.vtk.org/links.php\n",
+  " ",
+  "*/\n\n";
+
+close(DEST_FILE);
+
+print "Finished in ", time() - $start_time, " s.\n";
diff --git a/bioimagesuite30_src/Utilities/Doxygen/doxyfile.in b/bioimagesuite30_src/Utilities/Doxygen/doxyfile.in
new file mode 100644
index 0000000..56dd6fb
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/doxyfile.in
@@ -0,0 +1,165 @@
+# -------------------------------------------------------------------------
+# doxyfile for BIOIMAGESUITE
+# modified by H. Okuda (Time-stamp: <2006-12-14 00:00:00 Okuda>
+# -------------------------------------------------------------------------
+
+############################################
+
+PROJECT_NAME         = BIOIMAGESUITE3
+IMAGE_PATH           = "${BIOIMAGESUITE3_SOURCE_DIR}/Utilities/Doxygen" 
+OUTPUT_DIRECTORY     = "${BIOIMAGESUITE3_BINARY_DIR}/doc"
+INPUT                = \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/Common"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/Connectivity"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/database"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/DemonsRegistration"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/GUI"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/igtlutil"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/Graphics"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/Imaging"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/Legacy"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/Registration"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/Segmentation"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/mpjCommon"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/mpjDiffusion"  \
+                       "${BIOIMAGESUITE3_SOURCE_DIR}/mpjLevelset"  
+EXCLUDE_PATTERNS     =
+
+############################################
+
+FULL_PATH_NAMES      = YES
+WARN_IF_UNDOCUMENTED = NO
+
+GENERATE_TREEVIEW    = NO
+GENERATE_TODOLIST    = YES
+GENERATE_BUGLIST     = YES
+GENERATE_HTML        = YES
+GENERATE_HTMLHELP    = YES
+GENERATE_LATEX       = NO
+GENERATE_MAN         = NO
+GENERATE_RTF         = NO
+
+PDF_HYPERLINKS       = YES
+
+HAVE_DOT             = YES
+DOT_PATH             = "@DOT_PATH@"
+CLASS_GRAPH          = YES
+COLLABORATION_GRAPH  = YES
+TEMPLATE_RELATIONS   = YES
+INCLUDE_GRAPH        = YES
+INCLUDED_BY_GRAPH    = YES
+CLASS_DIAGRAMS       = YES
+GENERATE_LEGEND      = YES
+GRAPHICAL_HIERARCHY  = NO        # would be too large for vtkObject
+
+ALLEXTERNALS         = NO
+
+
+#EXCLUDE              = \
+EXTRACT_ALL          = YES
+EXTRACT_PRIVATE      = NO
+EXTRACT_STATIC       = YES
+EXTRACT_LOCAL_CLASSES = NO
+HIDE_UNDOC_MEMBERS   = NO
+HIDE_UNDOC_CLASSES   = YES
+ALWAYS_DETAILED_SEC  = NO
+SOURCE_BROWSER       = YES
+INLINE_SOURCES       = NO
+CASE_SENSE_NAMES     = YES
+VERBATIM_HEADERS     = NO
+SHOW_INCLUDE_FILES   = YES
+JAVADOC_AUTOBRIEF    = YES
+SORT_MEMBER_DOCS     = NO
+DISTRIBUTE_GROUP_DOC = YES
+TAB_SIZE             = 3
+DETAILS_AT_TOP       = YES
+# PAPER_TYPE           = letter
+
+FILE_PATTERNS        = *.h
+RECURSIVE            = NO
+
+HTML_ALIGN_MEMBERS   = YES
+
+ALPHABETICAL_INDEX   = YES
+COLS_IN_ALPHA_INDEX  = 3
+IGNORE_PREFIX        = vtk
+
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION      = YES
+SEARCH_INCLUDES      = YES
+INCLUDE_PATH         =
+EXPAND_ONLY_PREDEF   = YES
+PREDEFINED  = "vtkSetMacro(name,type)= \
+                 virtual void Set##name (type);" \
+              "vtkGetMacro(name,type)= \
+                 virtual type Get##name ();" \
+              "vtkSetStringMacro(name)= \
+                 virtual void Set##name (const char*);" \
+              "vtkGetStringMacro(name)= \
+                 virtual char* Get##name ();" \
+              "vtkSetClampMacro(name,type,min,max)= \
+                 virtual void Set##name (type);" \
+              "vtkSetObjectMacro(name,type)= \
+                 virtual void Set##name (type*);" \
+              "vtkGetObjectMacro(name,type)= \
+                 virtual type *Get##name ();" \
+              "vtkBooleanMacro(name,type)= \
+                 virtual void name##On (); \
+                 virtual void name##Off ();" \
+              "vtkSetVector2Macro(name,type)= \
+                 virtual void Set##name (type, type); \
+                 void Set##name (type [2]);" \
+              "vtkGetVector2Macro(name,type)= \
+                 virtual type *Get##name (); \
+                 virtual void Get##name (type &, type &); \
+                 virtual void Get##name (type [2]);" \
+              "vtkSetVector3Macro(name,type)= \
+                 virtual void Set##name (type, type, type); \
+                 virtual void Set##name (type [3]);" \
+              "vtkGetVector3Macro(name,type)= \
+                 virtual type *Get##name (); \
+                 virtual void Get##name (type &, type &, type &); \
+                 virtual void Get##name (type [3]);" \
+              "vtkSetVector4Macro(name,type)= \
+                 virtual void Set##name (type, type, type, type); \
+                 virtual void Set##name (type [4]);" \
+              "vtkGetVector4Macro(name,type)= \
+                 virtual type *Get##name (); \
+                 virtual void Get##name (type &, type &, type &, type &); \
+                 virtual void Get##name (type [4]);" \
+               "vtkSetVector6Macro(name,type)= \
+                 virtual void Set##name (type, type, type, type, \
+                                         type, type); \
+                 virtual void Set##name (type [6]);" \
+               "vtkGetVector6Macro(name,type)= \
+                  virtual type *Get##name (); \
+                  virtual void Get##name (type &, type &, type &, \
+                                          type &, type &, type &); \
+                  virtual void Get##name (type [6]);" \
+               "vtkSetVectorMacro(name,type,count)= \
+                  virtual void Set##name(type data[]);" \
+               "vtkGetVectorMacro(name,type,count)= \
+                   virtual type *Get##name (); \
+                   virtual void Get##name(type data[##count]);" \
+               "vtkWorldCoordinateMacro(name)= \
+                   virtual vtkCoordinate *Get##name##Coordinate (); \
+                   virtual void Set##name(float x[3]); \
+                   virtual void Set##name(float x, float y, float z); \
+                   virtual float *Get##name();" \
+               "vtkViewportCoordinateMacro(name)= \
+                   virtual vtkCoordinate *Get##name##Coordinate (); \
+                   virtual void Set##name(float x[2]); \
+                   virtual void Set##name(float x, float y); \
+                   virtual float *Get##name();" \
+               "vtkTypeMacro(thisClass,superclass)= \
+                   typedef superclass Superclass; \
+                   virtual const char *GetClassName(); \
+                   static int IsTypeOf(const char *type); \
+                   virtual int IsA(const char *type); \
+                   static thisClass* SafeDownCast(vtkObject *o);" \
+               "vtkTypeRevisionMacro(thisClass,superclass)= \
+                   typedef superclass Superclass; \
+                   virtual const char *GetClassName(); \
+                   static int IsTypeOf(const char *type); \
+                   virtual int IsA(const char *type); \
+                   static thisClass* SafeDownCast(vtkObject *o);"
diff --git a/bioimagesuite30_src/Utilities/Doxygen/doxygen.css b/bioimagesuite30_src/Utilities/Doxygen/doxygen.css
new file mode 100644
index 0000000..d148db5
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/doxygen.css
@@ -0,0 +1,196 @@
+body {
+  background-color: #97A8C9;
+  color: #000000;
+}
+
+div.div-page { 
+  background-color: #FFFFFF; 
+  margin-left: 1em;
+  margin-right: 1em;
+  margin-top: 1em;
+  margin-bottom: 0.1em;
+
+  padding-left: 1em;
+  padding-right: 1em;
+  padding-top: 0.5em;
+  padding-bottom: 0.5em;
+
+  border: 2px solid #0D299A; 
+  border-width: 2px;
+  border-color: #0D299A; 
+}
+
+div.div-footer { 
+  margin-left: 1em;
+  margin-right: 1em;
+  margin-bottom: 0.2em;
+  text-align: right; 
+  font-size: 9pt; 
+}
+
+div.div-title { 
+  text-align: left; 
+  font-weight: bold;
+  color: #FFFFFF;
+}
+
+h1, h2, h3, h4, h5, h6, body, caption, td, p, ul, ol, dd, dt {
+  font-family: Arial, Helvetica, sans-serif;
+}
+
+code, tt {
+  font-family: "Courier New", Courier, monospace;
+}
+
+H1 { 
+  text-align: center; 
+}
+
+CAPTION { 
+  font-weight: bold 
+}
+
+/* Link in the top navbar */
+
+A.qindex {
+  font-size: 9pt; 
+}
+
+A.qindexRef {
+}
+
+/* Link to any cross-referenced Doxygen element */
+
+A.el { 
+  text-decoration: none; 
+  font-weight: bold 
+}
+
+A.elRef { 
+  font-weight: bold 
+}
+
+/* Link to any cross-referenced Doxygen element inside a code section 
+   (ex: header)
+*/
+
+A.code { 
+  text-decoration: none; 
+  font-weight: normal; 
+  color: #4444ee 
+}
+
+A.codeRef { 
+  font-weight: normal; 
+  color: #4444ee 
+}
+
+A:hover { 
+  text-decoration: none; 
+  background-color: #f2f2ff 
+}
+
+DL.el { 
+  margin-left: -1cm 
+}
+
+/* A code fragment (ex: header) */
+
+DIV.fragment { 
+  width: 100%; 
+  border: none; 
+  background-color: #eeeeee 
+}
+
+/* In the alpha list (coumpound index), style of an alphabetical index letter */
+
+DIV.ah { 
+  background-color: black; 
+  font-weight: bold; 
+  color: #ffffff; 
+  margin-bottom: 3px; 
+  margin-top: 3px 
+}
+
+/* Method name (+ type) */
+
+TD.md { 
+  background-color: #f2f2ff; 
+  font-weight: bold; 
+}
+
+/* Method parameter (some of them) */
+
+TD.mdname1 { 
+  background-color: #f2f2ff; 
+  font-weight: bold; 
+  color: #602020; 
+}
+
+/* Method parameter (some of them) */
+
+TD.mdname { 
+  background-color: #f2f2ff; 
+  font-weight: bold; 
+  color: #602020; 
+/*  width: 600px; */
+}
+
+/* Table surrounding the method name + params */
+
+table.table-md-params { 
+  width: 90%; 
+}
+
+/* Separator between methods group (usually empty, seems not supported by IE) */
+
+DIV.groupHeader { 
+  margin-left: 16px;
+  margin-top: 12px; 
+  margin-bottom: 6px; 
+  font-weight: bold 
+}
+
+DIV.groupText { 
+  margin-left: 16px; 
+  font-style: italic; 
+  font-size: smaller 
+}
+
+/* In File List, Coumpound List, etc, 1st column of the index */
+
+TD.indexkey { 
+   background-color: #eeeeff; 
+   font-weight: bold; 
+   padding-right  : 10px; 
+   padding-top    : 2px; 
+   padding-left   : 10px; 
+   padding-bottom : 2px; 
+   margin-left    : 0px; 
+   margin-right   : 0px; 
+   margin-top     : 2px; 
+   margin-bottom  : 2px  
+}
+
+/* In File List, Coumpound List, etc, 2nd column of the index */
+
+TD.indexvalue { 
+   background-color: #eeeeff; 
+   font-style: italic; 
+   padding-right  : 10px; 
+   padding-top    : 2px; 
+   padding-left   : 10px; 
+   padding-bottom : 2px; 
+   margin-left    : 0px; 
+   margin-right   : 0px; 
+   margin-top     : 2px; 
+   margin-bottom  : 2px  
+}
+
+span.keyword       { color: #008000 }
+span.keywordtype   { color: #604020 }
+span.keywordflow   { color: #e08000 }
+span.comment       { color: #800000 }
+span.preprocessor  { color: #806020 }
+span.stringliteral { color: #002080 }
+span.charliteral   { color: #008080 }
diff --git a/bioimagesuite30_src/Utilities/Doxygen/footer.html b/bioimagesuite30_src/Utilities/Doxygen/footer.html
new file mode 100644
index 0000000..663ba19
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/footer.html
@@ -0,0 +1,5 @@
+</DIV>
+<DIV class="div-footer">
+Generated on $datetime for <A href="http://www.vtk.org">$projectname</A> by <A href="http://www.doxygen.org/index.html">Doxygen</A> $doxygenversion</DIV>
+</BODY>
+</HTML>
diff --git a/bioimagesuite30_src/Utilities/Doxygen/header.html b/bioimagesuite30_src/Utilities/Doxygen/header.html
new file mode 100644
index 0000000..4f82b53
--- /dev/null
+++ b/bioimagesuite30_src/Utilities/Doxygen/header.html
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+<META http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<TITLE>$title</TITLE>
+<LINK href="doxygen.css" rel="stylesheet" type="text/css">
+</HEAD>
+<BODY>
+<DIV class="div-page">
diff --git a/bioimagesuite30_src/bioimagesuite/CMakeLists.txt b/bioimagesuite30_src/bioimagesuite/CMakeLists.txt
new file mode 100644
index 0000000..27f9392
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/CMakeLists.txt
@@ -0,0 +1,55 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+
+
+SUBDIRS(
+apps
+base
+images
+main
+mjack
+datatree
+bis_algorithm
+origscripts
+)
+
+
+SET(KITAPPS )
+SET(KITSRCS VERSION.txt)
+bis_complex_tcl3src(bioimagesuite "." ${FILELIST})
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/CMakeLists.txt b/bioimagesuite30_src/bioimagesuite/apps/CMakeLists.txt
new file mode 100644
index 0000000..8e32e17
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/CMakeLists.txt
@@ -0,0 +1,85 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+
+SET(KITSCRIPTS
+    pkgIndex.tcl
+    pxappscommon.tcl
+)
+
+SET(KITAPPS
+    pxtonifti.tcl
+    pxroitoroi.tcl
+    pxmat_headerinfo.tcl
+    pxmat_surfaceinfo.tcl
+    pxmat_flip.tcl
+    pxmat_reorientimage.tcl
+    pxmat_smoothimage.tcl
+    pxmat_thresholdimage.tcl
+    pxmat_resampleimage.tcl
+    pxmat_create4dimage.tcl
+    pxmat_split4dimage.tcl
+    pxmat_resliceimage.tcl
+    pxmat_reorient_tensor.tcl
+    pxmat_inverttransform.tcl
+    pxmat_displacementfield.tcl
+    pxmultijacobian.tcl
+    pxsinglejacobian.tcl
+    pxcomputeaverage.tcl
+    pxmultiregister_int.tcl
+    pxpairwiseregister.tcl
+    pxmat_register.tcl
+    pxmat_distortioncorrection.tcl
+    pxmat_pointregister.tcl
+    pxmat_integratedregistration.tcl
+    pxmat_computedistance.tcl
+    pxmat_computeoverlap.tcl
+    pxmat_computesimilarity.tcl
+    pxmat_computestrains.tcl
+    pxmat_computeaveragebrain.tcl
+    pxmultisegment.tcl
+    pxmat_fastpostprocess.tcl
+    pxmat_segment.tcl
+    pxmat_biasfield.tcl
+    pxmat_reslicect.tcl
+    bisserver.tcl
+    bisclient.tcl
+    biscomputecorrelations.tcl
+)
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+bis_complex_tcl(bioimagesuite/apps ${FILELIST2} ${FILELIST})
diff --git a/bioimagesuite30_src/bioimagesuite/apps/bisclient.tcl b/bioimagesuite30_src/bioimagesuite/apps/bisclient.tcl
new file mode 100755
index 0000000..4c2d9d7
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/bisclient.tcl
@@ -0,0 +1,81 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+if { [ llength $argv ] < 1 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a test OpenIGTLink test client sends points\n"
+    puts stdout "Syntax: $scriptname server port"
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+
+set server [ lindex $argv 0 ]
+set port   [ lindex $argv 1 ]
+
+set client [ vtkpxOpenIGTLinkClient [ pxvtable::vnewobj ]]
+
+puts stderr "$client, [ $client GetClassName ]"
+set ok [ $client InitializeConnection $server $port ]
+
+if { $ok == 0 } {
+    puts stderr "Connection failed\n"
+    exit
+}
+
+puts stdout "Connection Done"
+    
+set pts [ vtkPoints [ pxvtable::vnewobj ]]
+$pts SetNumberOfPoints 1
+
+set line "           "
+    
+while { [ string length $line ] > 1 } {
+    set x 5 
+    set y 5
+    set z 5
+    puts stderr "Enter next point then press enter:"
+    gets stdin line
+    scan $line "%f %f %f" x y z
+    puts stderr "Sending $x $y $z"
+    $pts SetPoint 0 $x $y $z
+    $client SendToolLocation $pts
+}
+$client CloseConnection
+
+
+exit 0
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/biscomputecorrelations.tcl b/bioimagesuite30_src/bioimagesuite/apps/biscomputecorrelations.tcl
new file mode 100755
index 0000000..eda784a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/biscomputecorrelations.tcl
@@ -0,0 +1,226 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+puts stdout "This is obsolete"
+puts stdout "Use bis_computecorrelations.tcl instead"
+exit
+
+set num $argc 
+
+if { $num < 2 } {
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "Usage: $scriptname 4DImage measuresfile"
+
+    puts stdout "Measures File Example\n------------------------"
+    puts stdout "\#Individual Subject Measures"
+    puts stdout "\#Number of Subjects\n4"
+    puts stdout "\#Number of Measures\n2"
+    puts stdout "\#Data (either , or tab-delimited)"
+    puts stdout "Subject IQ Weight"
+    puts stdout "1314	100 100"
+    puts stdout "1361	110 200"
+    puts stdout "1518	120 200"
+    puts stdout "2205	130 121"
+    puts stdout "------------------------"
+    exit 0
+}
+
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+package require bis_seedcorrelation 1.0
+
+
+proc TextFileToImage { textfile } {
+
+    set fileid [open $textfile r]
+	
+    gets $fileid line
+    set line [ string trim $line ]
+    
+    if { [ string compare $line "#Individual Subject Measures" ] != 0 } {
+	puts stderr "Bad Data File\n"
+	close $fileid
+	exit
+    }
+    
+    set numsubjects 1
+    set nummeasures 1
+    gets $fileid line;     gets $fileid numsubjects
+    gets $fileid line;     gets $fileid nummeasures
+    
+    puts stdout "Reading textfile = $textfile, numsubjects=$numsubjects, nummeasures=$nummeasures"
+
+    gets $fileid line
+
+    set img [ vtkImageData New ]
+    $img SetDimensions $nummeasures 1 1
+    $img SetNumberOfScalarComponents $numsubjects
+    $img SetScalarTypeToFloat
+    $img AllocateScalars
+    
+    set numcols [ expr $nummeasures +1 ]
+    gets $fileid line
+
+    set subjectlist ""
+    set measurelist ""
+
+    set ln [ string trim $line ]
+    regsub -all " +" $ln "\t" ln
+    regsub -all "\t" $ln "|" ln
+    regsub -all ","  $ln "|" ln
+    set tmp  [ split $ln | ]	
+    if { [ llength $tmp ] != $numcols } {
+	puts stderr "Not Engough Measure names specified (numcols=$numcols) ($ln,$tmp)"
+	close $fileid
+	exit
+    }
+    for { set i 1 } { $i < $numcols } { incr i } {
+	lappend measurelist [ lindex $tmp $i ]
+    }
+
+
+    for { set i 0 } { $i < $numsubjects } { incr i } {
+	gets $fileid line
+	set ln [ string trim $line ]
+	regsub -all " +" $ln "\t" ln
+	regsub -all "\t" $ln "|" ln
+	regsub -all ","  $ln "|" ln
+	set tmp  [ split $ln | ]	
+	#	puts stdout "ln=$ln, tmp=$tmp"
+	if { [ llength $tmp ] != $numcols } {
+	    puts stderr "Bad Line for subject [ expr $i +1 ], number of columns = [ llength $tmp ] != $numcols "
+	    close $fileid
+	    exit
+	}
+	for { set j 1 } { $j < $numcols } { incr j } {
+	    $img SetScalarComponentFromDouble [ expr $j -1 ] 0 0 $i [ expr double([ lindex $tmp $j ]) ]
+	}
+	lappend subjectlist [ lindex $tmp 0 ]
+    }
+    close $fileid
+
+    puts stdout "Verifying ...."
+
+    puts -nonewline stdout " \t :"
+    for { set j 0 } { $j < $nummeasures } { incr j } {
+	puts -nonewline stdout " [ lindex $measurelist $j ]\t"
+    }
+    puts stdout ""
+
+    for { set i 0 } { $i < $numsubjects } { incr i } {
+	puts -nonewline stdout "Subject [ lindex $subjectlist $i ] \t"
+	for { set j 0 } { $j < $nummeasures } { incr j } {
+	    puts -nonewline stdout "[ $img GetScalarComponentAsDouble $j 0 0 $i ]\t"
+	}
+	puts stdout ""
+    }
+
+
+    set ref [ pxitclimage \#auto ]
+    $ref ShallowCopyImage $img
+    $img Delete
+    return [ list $ref $measurelist ]
+}
+
+# ---------------------------------------------------------------------------------------------------------
+
+set rlist [ TextFileToImage [ lindex $argv 1 ] ]
+if { $rlist == 0 } {
+    exit
+}
+
+set roimean [ lindex $rlist 0 ]
+set measurelist [ lindex $rlist 1 ]
+
+
+
+set ref [ pxitclimage \#auto ]
+$ref Load [ lindex $argv 0 ]
+puts stdout "\n\n4D Image loaded = [ $ref GetDescription ]\n"
+
+if { [ llength $argv ] > 2 } {
+    set threshold [ lindex $argv 2 ]
+} else {
+    set threshold 0.05
+}
+
+
+set corr [ bis_seedcorrelation \#auto ]
+$corr InitializeFromContainer 0 
+$corr SetInput $ref
+$corr SetSecondInput $roimean
+$corr SetOptionValue usemask 0
+$corr Execute
+
+
+set outname [ lindex $argv 0 ]
+set ext [ file extension $outname ]
+set outname [ file rootname $outname ]
+if { $ext == ".gz" } {
+    set outname [ file rootname $outname ]
+}
+
+set tmp [ pxitclimage \#auto ]
+
+set outimage [ $corr GetOutput ]
+
+for { set i 0 } { $i < [ [ $outimage GetImage ] GetNumberOfScalarComponents ] } { incr i } {
+
+    set extr [ vtkImageExtractComponents New ]
+    $extr SetInput [ $outimage GetImage ]
+    $extr SetComponents $i
+    $extr Update
+
+    $tmp ShallowCopyImage [ $extr GetOutput ]
+    $tmp CopyImageHeader  [ $outimage GetImageHeader ]
+    set name "${outname}_[ lindex $measurelist $i ].nii.gz"
+    set ok [ $tmp Save $name ]
+    if { $ok > 0 } {
+	puts stdout "\t\t Correlation with [ lindex $measurelist $i ] saved in $name"
+    }
+    $extr Delete
+}
+
+
+itcl::delete obj $corr
+itcl::delete obj $roimean
+itcl::delete obj $ref
+itcl::delete obj $tmp
+
+exit
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/bisserver.tcl b/bioimagesuite30_src/bioimagesuite/apps/bisserver.tcl
new file mode 100755
index 0000000..df923a2
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/bisserver.tcl
@@ -0,0 +1,184 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+if { [ llength $argv ] < 1 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a test OpenIGTLink test client that receives points\n"
+    puts stdout "Syntax: $scriptname port"
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+set cursor_xform [ vtkTransform [ pxvtable::vnewobj ]]
+set current_image [ vtkImageData [ pxvtable::vnewobj ]]
+set port   [ lindex $argv 0 ]
+set igtlserver 0
+set igtllasttransformtime 0
+set igtllastimagetime 0
+
+
+# -------------------------------------------------------------------------------------
+proc ServerCallbackHandleData { mode } {
+
+    global igtlserver
+    global igtllasttransformtime
+    global igtllastimagetime
+    global cursor_xform
+    global current_image
+
+    set status 0
+
+    if { $mode == 0 } {
+	set tr [ $igtlserver GetLastReceivedTransform ]
+
+	$cursor_xform Identity;
+	$cursor_xform Concatenate $tr
+
+	set tx [ $tr GetPosition ]
+
+	set cursor_x [ expr double([ lindex $tx 0 ])]
+	set cursor_y [ expr double([ lindex $tx 1 ])]
+	set cursor_z [ expr double([ lindex $tx 2 ])]
+	set pointstatus  [ format "(%.2f %.2f %.2f)" $cursor_x $cursor_y $cursor_z ]
+	set status 1
+	set igtllasttransformtime  [ $igtlserver GetLastReceivedTransformTime ] 
+	puts stdout "Received point $pointstatus"
+    } elseif { $mode ==1 } {
+	$current_image ShallowCopy  [ $igtlserver GetLastReceivedImage ]
+	set imagestatus  "[ $current_image GetDimensions ], [ $current_image GetSpacing ]"
+	puts stdout "Received image $imagestatus"
+	set igtllastimagetime  [ $igtlserver GetLastReceivedImageTime ]
+	set status 1
+    }
+
+    return $status
+    
+}
+# ---------------------------------------------------------------------
+proc ServerCallback { } {
+    
+    global igtlserver
+    global igtllasttransformtime
+    global igtllastimagetime
+
+
+    if { $igtllastimagetime < [ $igtlserver GetLastReceivedImageTime ] } {
+	 ServerCallbackHandleData 1
+    }
+    
+    if { $igtllasttransformtime < [ $igtlserver GetLastReceivedTransformTime ] } {
+	 ServerCallbackHandleData 0
+    }
+}
+
+
+
+# ---------------------------------------------------------------------
+proc ServerEventLoop { } {
+
+    global igtlserver
+    global igtllasttransformtime
+    global igtllastimagetime
+    global port
+
+
+    set con [ $igtlserver GetIsServerConnected ]
+    set act [ $igtlserver GetIsServerActive    ]
+
+    if { $con == 1 } {
+	set st " **** STATUS: Server connected"
+    } elseif { $act ==1 } {
+	set st "**** STATUS: Server listening Port=$port"
+    } else {
+	if { [ $igtlserver GetThreadActive ] == 0 } {
+	    puts stderr "Connection closed ... exiting\n"
+	    exit
+	}
+    }
+    
+    if { $st != "" } {
+	set serverstatus "$st (img=$igtllastimagetime, tr=$igtllasttransformtime)"
+	#	puts stdout "$serverstatus"
+    }
+
+    set dl 1
+    # If needed start this ....
+    if { $con == 1 && $act == 1 } {
+	$igtlserver BeginReceivingDataInThread
+	ServerCallback
+    }
+
+    after $dl ServerEventLoop
+    return     
+}
+
+# ---------------------------------------------------------------------
+
+proc CreateServer { } { 
+
+    global igtlserver
+    global igtllasttransformtime
+    global igtllastimagetime
+    global port
+    
+
+    set igtlserver [ vtkpxOpenIGTLinkServer [ pxvtable::vnewobj ]]
+    set ok [ $igtlserver InitializeConnection $port ]
+
+    if { $ok == 0 } {
+	puts stderr "Failed to Create OpenIGTLink Server on port $port"
+	exit
+    } else {
+	puts stdout "Server Initialized on $port" 
+    }
+
+    while { [ $igtlserver GetThreadActive ] == 0 } { 
+	puts stderr "Waiting for thread to become active"
+    }
+
+
+    set igtllasttransformtime      [ $igtlserver GetLastReceivedTransformTime ] 
+    set igtllastimagetime          [ $igtlserver GetLastReceivedImageTime ]
+    ServerEventLoop
+}
+
+
+CreateServer
+
+
+vwait forever
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pkgIndex.tcl b/bioimagesuite30_src/bioimagesuite/apps/pkgIndex.tcl
new file mode 100644
index 0000000..7afb682
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pkgIndex.tcl
@@ -0,0 +1,46 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# Tcl package index file, version 1.1
+# This file is generated by the "pkg_mkIndex" command
+# and sourced either when an application starts up or
+
+
+
+
+# by a "package unknown" script.  It invokes the
+# "package ifneeded" command to set up package-related
+# information so that packages will be loaded automatically
+# in response to "package require" commands.  When this
+# script is sourced, the variable $dir must contain the
+# full path name of this file's directory.
+
+# 	$Id: pkgIndex.tcl,v 1.1 2003/05/07 18:50:18 papad Exp papad $	
+
+
+package ifneeded pxappscommon         1.0 [list source [file join $dir pxappscommon.tcl]] 
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxappscommon.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxappscommon.tcl
new file mode 100644
index 0000000..336b6da
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxappscommon.tcl
@@ -0,0 +1,204 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# --------------------------------------------------------------------------------------------------------
+# 	$Id: pxappscommon.tcl,v 1.2 2004/01/15 15:01:11 xenios Exp xenios $	
+
+
+
+
+
+
+package provide pxappscommon 1.0
+
+catch { wm withdraw . }
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] main ]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] mjack ]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] bis_algorithm ]
+
+package require pxtclutil 1.0
+package require pxtcluserprefs 1.0
+package require Itcl 3.2
+package require pxitclimage  
+
+
+set no_gui 1
+catch {  if { $vtkpxcontrib_no_gui == 0 } {
+    set no_gui 0 }
+}
+
+if { $no_gui == 1 } {
+    set vtkpxcontrib_no_gui 1
+}
+unset no_gui
+package require vtkpxcontrib  1.1
+unset vtkpxcontrib_no_gui 
+
+package require vtkmpjcontrib 
+
+package require pxvtable 1.0
+
+namespace eval ::pxappscommon {
+    
+    proc GenOutputName { input tag { outsuffix .hdr } { insuffix .hdr } } {
+
+	if { [ file extension $input ] == ".gz" } {
+	    set input [ file rootname $input ]
+	}
+
+	if { [ file extension $input ] == ".nii" } {
+	    set outsuffix .nii.gz
+	    set insuffix  .nii
+	}
+
+	if { [ file extension $input ] == $insuffix } {
+	    set fname "[ file rootname $input ]"
+	} else {
+	    set fname $input
+	}
+
+
+	if { [ string length $tag ] > 0 } {
+	    set fname "${fname}_${tag}$outsuffix"
+	} else {
+	    set fname "${fname}$outsuffix"
+	}
+	return $fname
+    }
+
+    proc RestrictRange { input minv maxv } {
+	if { $input < $minv } {
+	    return $minv
+	}
+	
+	if { $input > $maxv } {
+	    return $maxv
+	}
+
+	return $input
+    }
+
+    proc RestrictIntRange { input minv maxv } {
+	return [ expr round([RestrictRange $input $minv $maxv ])]
+    }
+
+    proc CheckAnalyzeSource { ana imagename filename vtkobjs } {
+	set ok 0
+	catch {
+	    set img [ $ana GetOutput ]
+	    set dim [ $img GetDimensions ]
+	    set spa [ $img GetSpacing    ]
+	    set pt  [ $img GetNumberOfPoints ]
+	    set ok 1
+	}
+	
+	if { $ok ==0 } {
+	    puts stderr "Failed to load $imagename from $filename\n exiting"
+	    cleanup $vtkobjs
+	    exit
+	} 
+
+	puts stdout "Loaded $imagename from $filename ([ lindex $dim 0 ] x [ lindex $dim 1 ] x [ lindex $dim 2 ]), ([ lindex $spa 0 ] x [ lindex $spa 1 ] x [ lindex $spa 2 ])"
+    }
+
+    proc Cleanup { vtkobjs } {
+	for { set i 0 } { $i < [ llength $vtkobjs ] } {incr i } {
+	    catch { [ lindex $vtkobjs $i ] Delete }
+	}
+    }
+
+
+    # Check whether file exists and 
+    proc CompressedFileExists { fname } {
+	
+	set ext [ file extension $fname ]
+	if { $ext == ".gz" } {
+	    set fname [ file rootname $fname ]
+	}
+
+	if { [ file exists $fname ] > 0 } {
+	    return [ file size $fname ]
+	}
+
+	if { [ file exists "${fname}.gz" ] > 0 } {
+	    return [ expr -[ file size ${fname}.gz ] ]
+	}
+	return 0
+    }
+
+    proc EnsureImageExists { fname }  {
+
+	if { $fname == "" } {
+	    return 0
+	}
+
+	set ext [ file extension $fname ]
+	if { $ext == ".gz" } {
+	    set fname [ file rootname $fname ]
+	    set ext   [ file extension $fname ]
+	}
+
+	if { $ext == ".hdr" } {
+	    set fname [ file rootname $fname ]
+	    set ok1 [ ::pxappscommon::CompressedFileExists ${fname}.hdr ]
+	    set ok2 [ ::pxappscommon::CompressedFileExists ${fname}.img ]
+	    
+	    if { $ok1 != 0 && $ok2 != 0 } {
+		set ext1 ""
+		set ext2 ""
+		if { $ok1 < 0 } {   set ext1 ".gz"; set ok1 [ expr - $ok1 ] }
+		if { $ok2 < 0 } {   set ext2 ".gz"; set ok2 [ expr - $ok2 ] }
+
+
+		return [ list ${fname}.hdr${ext1} "($ok1)" ${fname}.img${ext2} "($ok2)" ]
+	    }
+	}
+
+	set ok [ ::pxappscommon::CompressedFileExists $fname ] 
+	if { $ok !=0 } {
+	    set ext1 ""
+	    if { $ok < 0 } {   set ext1 ".gz"; set ok [ expr - $ok ] }
+	    return [ list $fname${ext1} "($ok)" ]
+	}
+    }
+
+}
+
+
+set tmp  [  [ pxitclimage \#auto ] GetThisPointer ]
+if {   $pxtcl_pref_array(ForceOutputFormat) == "Analyze" } {
+    $tmp SetOutputFormat 1
+} elseif { $pxtcl_pref_array(ForceOutputFormat) == "NIFTI" } {
+    $tmp SetOutputFormat 2
+} else {
+    $tmp SetOutputFormat 0
+}
+itcl::delete object $tmp 
+unset tmp
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxcomputeaverage.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxcomputeaverage.tcl
new file mode 100755
index 0000000..7098236
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxcomputeaverage.tcl
@@ -0,0 +1,127 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+set imglist ""
+set output  ""
+
+
+set argc [llength $argv]
+if { $argc < 3 } {
+    set scriptname [ file tail $argv0 ]
+    puts stderr "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stderr "$scriptname is a script that computes the mean and standard deviation of a set of images"
+    puts stderr "Syntax: $scriptname output_stem image1 image2 .... \n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+    
+
+set outputstem [ file root [ lindex $argv 0 ]]
+
+# --------------------------------------------------------------------------------------------------------
+
+proc TestImages {  } {
+
+    global argv
+
+    for { set i 1 } { $i < [ llength $argv ] } { incr i } {
+
+	set refimgname [ lindex $argv $i ]
+	set a "[ file root $refimgname ].hdr"
+	set b "[ file root $refimgname ].img"
+	set ok1 [ file exists $a ] ;   set sz1 -1 ; catch { set sz1 [ file size $a ] }
+	set ok2 [ file exists $b ] ;   set sz2 -1 ; catch { set sz2 [ file size $b ] }
+	if { $ok2 ==0 } {
+	    set b "[ file root $refimgname ].img.gz"
+	    set ok2 [ file exists $b ] ;   set sz2 -1 ; catch { set sz2 [ file size $b ] }
+	}
+
+	if { $ok1 > 0 && $ok2 > 0 } {
+	    puts stderr "+++++ Image $i  $a,[file tail $b ] ($sz1,$sz2)  ok"
+	} else {
+	    puts stderr "\n*********** Missing Image $a,$b ($sz1,$sz2)"
+	    exit
+	}
+    }
+}
+
+TestImages 
+
+
+
+set combo [  vtkpxAverageImages [ pxvtable::vnewobj ]]
+$combo SetMedian 0
+$combo ComputeStandardDeviationOn
+$combo IgnoreFlagOff
+
+set imageheader [ vtkbisImageHeader [ pxvtable::vnewobj ]]
+
+for { set i 1 } { $i < [ llength $argv ] } { incr i } {
+
+    set ana [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+    set fname [ lindex $argv $i ]
+    $ana Load $fname
+    puts stderr "++++ Image $i Loaded from $fname ( [ [ $ana GetOutput ] GetDimensions ])"
+
+    if { $i == 1 } {
+	set orientation [ $ana GetOrientation ]
+	$imageheader CopyHeader [ $ana GetHeader ]
+    }
+
+
+    $combo AddInput [ $ana GetOutput ]
+
+    $ana Delete
+}
+
+$combo  Update
+set outname  ${outputstem}_mean.hdr
+set outnames  ${outputstem}_stdev.hdr
+
+set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]    
+$anaw SetCompression 0
+$anaw SetInput [ $combo GetOutput ]
+$anaw SetImageHeader $imageheader
+$anaw Save $outname
+
+puts stderr "\n++++ Mean saved in $outname"
+    
+$anaw SetInput [ $combo GetOutputStandardDeviation ]
+$anaw Save $outnames
+
+puts stderr "++++ Standard Deviation saved in $outnames\n"
+$anaw Delete
+$combo Delete
+$imageheader Delete
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_biasfield.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_biasfield.tcl
new file mode 100755
index 0000000..e1293b8
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_biasfield.tcl
@@ -0,0 +1,263 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxflipslices.tcl,v 1.1 2004/01/15 15:11:59 xenios Exp xenios $	
+
+set num $argc 
+
+if { $num < 1 } {
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "Syntax: $scriptname input \[ mode = 3 \] \[ threshold =0.05 \] \[ numclasses = 4 \] \[ res=3 \] \[ maxsigmaratio = 0.2 \] \[ minb1 =0.2 \] \[ maxb1=5.0 \]"
+    puts stdout "\t\t mode = 0 (slice homogeneity) 1 (triple slice homogeneity) 2 (quadratic polynomial) 3 (cubic polynomial)"
+    puts stdout "\t\t\t      4 = triple slice + quadratic, 5=triple slice + cubic."
+    puts stdout "\t\tThreshold = 0.05, normalized threshold (0..1) to exclude voxels from bias field estimation -- to eliminate background"
+    puts stdout "\t\tNumber of classes = number of tissue labels (background is a tissue label so add this) for polynomial"
+    puts stdout "\t\tResolution = 3, resolution sampling for polynomial estimation"
+    puts stdout "\t\tMaxSigmaRatio  = this constrains the ratio of the max standard deviation to the min standard deviation"
+    puts stdout "\t\tMin B1 and Max B1 specify the range of B1 field allowed"
+    puts stdout "\n"
+    exit 0
+}
+
+# ---------------------------------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+
+set name [ lindex $argv 0 ]
+set argc [ llength $argv ]
+
+set mode 3;         if { $argc > 1 } { set mode       [ ::pxappscommon::RestrictIntRange [ lindex $argv 1 ] 0 5 ] }
+set threshold 0.05; if { $argc > 2 } { set threshold  [ ::pxappscommon::RestrictRange [ lindex $argv 2 ] 0.0 0.2 ] }
+set numclasses 3;   if { $argc > 3 } { set numclasses [ ::pxappscommon::RestrictIntRange [ lindex $argv 3 ] 2 10 ] }
+set resolution 3;   if { $argc > 4 } { set resolution [ ::pxappscommon::RestrictIntRange [ lindex $argv 4 ] 1 5 ] }
+set sigmaratio 0.2; if { $argc > 5 } { set sigmaratio [ ::pxappscommon::RestrictRange [ lindex $argv 5 ] 0.0 1.0 ] }
+set minb1 0.2      ;if { $argc > 6 } { set minb1      [ ::pxappscommon::RestrictRange [ lindex $argv 6 ] 0.1 0.95 ] }
+set maxb1 5.0      ;if { $argc > 7 } { set maxb1      [ ::pxappscommon::RestrictRange [ lindex $argv 7 ] 1.1 10.0 ] }
+
+# ---------------------------------------------------------------------------------------------------------
+
+proc RunSliceHomogeneity   { inputimage } { 
+
+    set fit [ vtkpxSliceBiasFieldCorrection  [ pxvtable::vnewobj ]]
+    $fit SetRobustMode  1
+    $fit SetPureScaling 0
+    $fit SetInput       $inputimage
+    $fit Update
+
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+    $img ShallowCopy [ $fit GetOutput ]
+    $fit Delete
+    return $img
+}
+# ----------------------------------------------------------------------------------------------------
+proc RunTripleSliceHomogeneity   { inputimage } { 
+
+    set axislist { x y z }
+
+    set output [ vtkImageData [ pxvtable::vnewobj ]]
+    $output ShallowCopy $inputimage
+
+    
+    for { set axis 0 } { $axis <=2 } { incr axis } {
+	puts stderr ".... Slice Inhomogeneity Correction orientation  axis= [ lindex $axislist $axis ]\n"
+	set fit [ vtkpxSliceBiasFieldCorrection  [ pxvtable::vnewobj ]]
+	$fit SetAxis $axis
+	$fit SetRobustMode  1
+	$fit SetPureScaling 0
+	$fit SetInput       $output
+	$fit Update
+	$output ShallowCopy [ $fit GetOutput ]
+	$fit Delete
+    }
+    return $output
+}
+# ----------------------------------------------------------------------------------------------------
+proc RunTripleSliceHomogeneityFit   { inputimage minb1 maxb1 } { 
+
+    
+    for { set axis 0 } { $axis <=2 } { incr axis } {
+	puts stderr ".... Slice Inhomogeneity Correction orientation  axis= $axis /2\n"
+	set fit [ vtkpxSliceBiasFieldCorrection  [ pxvtable::vnewobj ]]
+	$fit SetAxis $axis
+	$fit SetRobustMode  1
+	$fit SetPureScaling 0
+	$fit SetInput       $inputimage
+	$fit Update
+
+	set p [ vtkFloatArray [ pxvtable::vnewobj ]]
+	$fit PolynomialFitToParameters 2 $p
+	if { $axis == 0 } {
+	    set thisparam(pabic_shimval_0) [ $p GetComponent 0 0 ]
+	    set thisparam(pabic_shimval_3) [ $p GetComponent 1 0 ]
+	} elseif { $axis == 1 } {
+	    set thisparam(pabic_shimval_1) [ $p GetComponent 0 0 ]
+	    set thisparam(pabic_shimval_4) [ $p GetComponent 1 0 ]
+	} else { 
+	    set thisparam(pabic_shimval_2) [ $p GetComponent 0 0 ]
+	    set thisparam(pabic_shimval_5) [ $p GetComponent 1 0 ]
+	}
+	$fit Delete
+	$p Delete
+    }
+
+
+    set fit [ vtkpxPolynomialBiasFieldCorrection  [ pxvtable::vnewobj ]]
+    set db [ vtkDoubleArray [ pxvtable::vnewobj ]]
+    $db SetNumberOfTuples 18
+    $db FillComponent 0 0.0
+    for { set i 0 } { $i <= 5 } { incr i } {
+	$db SetComponent $i 0 $thisparam(pabic_shimval_$i) 
+    }
+    set tmp [ $fit ComputeBiasFieldImage [ $currentimage GetImage ] $db  2 $minb1 $maxb1 ]
+    set outimage [ $fit ComputeCorrectedImage $inputimage $tmp  ]
+
+    $db Delete
+    $fit Delete
+    $tmp Delete
+    return $outimage
+}
+
+# ----------------------------------------------------------------------------------------------------
+
+proc RunPolynomial { inputimage degree threshold numclasses resolution sigmaratio minb1 maxb1 } {
+
+
+    set fit [ vtkpxPolynomialBiasFieldCorrection  [ pxvtable::vnewobj ]]
+
+    set tFilter  [ vtkImageThreshold [ pxvtable::vnewobj ]  ]
+
+    if { $threshold > 0.0 } { 
+
+	set range  [ [ [ $inputimage GetPointData ] GetScalars ] GetRange ]
+	set tvalue [ expr [ lindex $range 0 ] + $threshold * ( [ lindex $range 1] - [ lindex $range 0 ]) ]
+	puts stdout "\t\t Thresholding at $tvalue (range = $range) to generate mask for bias field correction"
+
+	$tFilter SetInput $inputimage
+	$tFilter SetInValue  100.0
+	$tFilter SetOutValue   0.0
+	$tFilter ReplaceInOn
+	$tFilter ReplaceOutOn
+	$tFilter ThresholdBetween $tvalue [ expr 0.001 + [ lindex $range 1 ] ]
+	$tFilter SetOutputScalarTypeToShort
+	$tFilter Update
+
+	$fit SetMaskImage [ $tFilter GetOutput ]
+    }
+
+    $fit SetInput                $inputimage
+    $fit SetMetric               0
+    $fit SetNumberOfLevels       1
+    $fit SetNumberOfSteps        1
+    $fit SetResolution           $resolution
+    $fit SetStepSize             0.05
+    $fit SetNumberOfIterations   15
+    $fit SetEpsilon              0.1
+    $fit SetDegree               $degree
+    $fit SetOptimizationMethodToConjugateGradient
+    $fit SetFrame               0
+    $fit SetMinValue            $minb1
+    $fit SetMaxValue            $maxb1
+    $fit SetHisto_NumberOfClasses  $numclasses
+    $fit SetHisto_Iterations       50
+    $fit SetHisto_NumberOfBins    128
+    $fit SetHisto_Convergence     0.05
+    $fit SetHisto_Sigma           0.05
+    $fit SetHisto_MaxSigmaRatio     $sigmaratio
+    $fit SetHisto_OutlierDetection 0 
+    $fit SetHisto_PreprocessingMode 0
+    $fit Update
+
+    set outimage [ vtkImageData [ pxvtable::vnewobj ]]
+    $outimage ShallowCopy [ $fit GetOutput ]
+    $fit Delete
+    $tFilter Delete
+    return $outimage
+}
+
+# ----------------------------------------------------------------------------------------------------
+
+
+set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+$ana Load $name
+set or [ $ana GetOrientation ]
+puts stdout "\nRead $name [ [ $ana GetOutput ] GetDimensions ] ori=$or "
+
+set outimage 0
+set input [ $ana GetOutput ]
+set modename ""
+
+if { $mode == 0  } {
+    set outimage [ RunSliceHomogeneity $input ]
+    set modename "slicehom"
+} elseif { $mode ==  1 || $mode >= 4 } {
+    set outimage [ RunTripleSliceHomogeneity $input ]
+    set modename "triplehom"
+} else {
+    set outimage [ vtkImageData [ pxvtable::vnewobj ]]
+    $outimage ShallowCopy $input
+}
+
+set degree 0
+if { $mode == 2 || $mode == 4 } {
+    set degree 2
+} elseif { $mode == 3 || $mode == 5 } {
+    set degree 3
+}
+
+if { $degree > 0 } {
+    set tmp $outimage
+    set outimage [ RunPolynomial $tmp $degree $threshold $numclasses $resolution $sigmaratio $minb1 $maxb1 ]
+    set modename "pabic$degree"
+    $tmp Delete
+}
+
+set fname [ ::pxappscommon::GenOutputName $name $modename ]
+
+set ana2 [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+$ana2 SetInput $outimage
+$ana2 SetImageHeader [ $ana GetImageHeader ]
+
+$ana2 Save $fname
+
+puts stderr "Segmentation saved to $fname"
+
+$ana2 Delete
+$ana Delete
+$outimage Delete
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_computeaveragebrain.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_computeaveragebrain.tcl
new file mode 100755
index 0000000..ebae569
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_computeaveragebrain.tcl
@@ -0,0 +1,482 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+# ------------------------------------------------------------------------------------------
+
+proc MakeDirectory { } {
+    global outputdirectory
+
+    if { [ file exists $outputdirectory ] == 0 } {
+	file mkdir $outputdirectory
+    }
+
+}
+
+# ------------------------------------------------------------------------------------------
+
+proc ComputeAverageTransformations { xformlist refimg namestem debugmode } {
+
+    set numxforms [ llength $xformlist ]
+    puts stdout "$numxforms transformations"
+    
+    set ana [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+    $ana Load $refimg
+
+    scan [ [ $ana GetOutput ] GetDimensions ] "%d %d %d" dim(0) dim(1) dim(2)
+    scan [ [ $ana GetOutput ] GetSpacing ] "%f %f %f" spa(0) spa(1) spa(2)
+    scan [ [ $ana GetOutput ] GetOrigin ] "%f %f %f" ori(0) ori(1) ori(2)
+
+    puts stdout "Loaded Image $refimg (dim = $dim(0)x$dim(1)x$dim(2), sp=$spa(0)x$spa(1)x$spa(2), origin=$ori(0),$ori(1),$ori(2))"
+
+
+    set average     [ vtkpxAverageImages [ pxvtable::vnewobj ]]
+    set averagejac  [ vtkpxAverageImages [ pxvtable::vnewobj ]]
+
+
+    $average SetMedian 0;     $average SetSumOnly 0
+    $averagejac SetMedian 0;  $averagejac SetSumOnly 0
+
+
+    set reg [ vtkpxRegistration  [ pxvtable::vnewobj ]]
+    set factor 2.0
+
+    for { set i 0 } { $i < $numxforms } { incr i } {
+	
+	set m [ lindex $xformlist $i ]
+	set combo [ vtkpxComboTransform  [ pxvtable::vnewobj ]]
+	$combo Load $m
+	[ $combo GetLinearTransform  ] Identity
+	puts stdout "\n ********* Loaded [ expr $i+1 ] $m [ file size $m ]"
+
+	set jac_1($i) [ vtkImageData [ pxvtable::vnewobj ] ]
+	    
+	if { $debugmode > 0 } {
+	    puts stdout "Computing Grid and Jacobian for [ file tail $m ] \t [ file size $m ]"
+	    $reg ComputeJacobianImage [ $ana GetOutput ] $jac_1($i) $combo 0.01 100.0
+	} else {
+	    puts stdout "Computing Grid Only for [ file tail $m ] \t [ file size $m ]"
+	}
+
+	set tgrid [ vtkTransformToGrid  [ pxvtable::vnewobj ]]
+	$tgrid SetGridExtent 0 [ expr round($dim(0)/$factor) - 1 ] 0 [ expr round($dim(1)/$factor) -1 ] 0 [ expr round($dim(2)/$factor) -1 ]
+	$tgrid SetGridOrigin  $ori(0) $ori(1) $ori(2)
+	$tgrid SetGridSpacing [ expr $factor*$spa(0)] [ expr $factor*$spa(1)] [ expr $factor*$spa(2) ]
+	$tgrid SetInput $combo
+	$tgrid Update
+	
+	set img($i) [ vtkImageData [ pxvtable::vnewobj ] ]
+	$img($i) ShallowCopy [ $tgrid GetOutput ]
+	
+	
+	$average AddInput $img($i)
+	if { $debugmode > 0 } {
+	    $averagejac AddInput $jac_1($i)
+	}
+	
+	$tgrid Delete
+	$combo Delete
+    }
+	
+    $average Update
+    if { $debugmode > 0 } {
+	$averagejac Update
+    }
+
+    set cast [ vtkImageCast [ pxvtable::vnewobj ]]
+    $cast SetInput [ $average GetOutput ]
+    $cast SetOutputScalarTypeToDouble
+    $cast Update
+
+    if { $debugmode > 0 } {
+	set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+	$anaw SetInput [ $averagejac GetOutput ]
+	$anaw SetOrientation [ $ana GetOrientation ]
+	$anaw Save "${namestem}_averagejacobian1"
+	puts stderr "Average Jacobian Map Saved in ${namestem}_averagejacobian1.hdr"
+	$anaw Delete
+    }
+
+    set tr [ vtkpxGridTransform [ pxvtable::vnewobj ]]
+    $tr SetDisplacementGrid [ $average GetOutput ]
+    $tr SetInterpolationModeToLinear
+
+    if { $debugmode > 0 } {
+	$tr Save "${namestem}_average.grd" 9
+	puts stderr "Average Transformation Saved in ${namestem}_average.grd.gz"
+    }
+
+    puts stderr "Computing Inverse Transformation ... this will take a while\n"
+    set trg [ vtkGridTransform [ pxvtable::vnewobj ] ]
+    $trg SetDisplacementGrid [ $cast GetOutput ]
+    $trg SetInterpolationModeToLinear
+    $trg Inverse
+    $cast Delete
+
+    set tgrid [ vtkTransformToGrid  [ pxvtable::vnewobj ]]
+    $tgrid SetGridExtent 0 [ expr round($dim(0)/$factor) - 1 ] 0 [ expr round($dim(1)/$factor) -1 ] 0 [ expr round($dim(2)/$factor) -1 ]
+    $tgrid SetGridOrigin  $ori(0) $ori(1) $ori(2)
+    $tgrid SetGridSpacing [ expr $factor*$spa(0)] [ expr $factor*$spa(1)] [ expr $factor*$spa(2) ]
+    $tgrid SetInput $trg
+    $tgrid Update
+    
+    set tr2 [ vtkpxGridTransform [ pxvtable::vnewobj ]]
+    $tr2 SetDisplacementGrid [ $tgrid GetOutput ]
+    $tr2 SetInterpolationModeToLinear
+    $tr2 Save "${namestem}_averageinverse.grd" 9
+
+    puts stderr "Average Inverse Transformation Saved in ${namestem}_averageinverse.grd.gz"
+    $tgrid Delete
+
+
+    if { $debugmode > 0 } {
+	set gen [ vtkGeneralTransform [ pxvtable::vnewobj ]]    
+	$gen PostMultiply
+	$gen Concatenate $tr
+	$gen Concatenate $tr2
+	
+	set tgrid [ vtkTransformToGrid [ pxvtable::vnewobj ]]
+	$tgrid SetGridExtent 0 [ expr round($dim(0)/$factor) - 1 ] 0 [ expr round($dim(1)/$factor) -1 ] 0 [ expr round($dim(2)/$factor) -1 ]
+	$tgrid SetGridOrigin  $ori(0) $ori(1) $ori(2)
+	$tgrid SetGridSpacing [ expr $factor*$spa(0)] [ expr $factor*$spa(1)] [ expr $factor*$spa(2) ]
+	$tgrid SetInput $gen
+	$tgrid DebugOn
+	$tgrid Update
+	
+	set tr3 [ vtkpxGridTransform [ pxvtable::vnewobj ] ]
+	$tr3 SetDisplacementGrid [ $tgrid GetOutput ]
+	$tr3 SetInterpolationModeToLinear
+	$tr3 Save "${namestem}_concat_averageinverse.grd" 9
+
+	puts stderr "Concat Average Inverse+Average Transformation Saved in ${namestem}_concat_averageinverse.grd.gz"
+	
+	$gen Delete
+	$tr3 Delete
+	$tgrid Delete
+    }
+	
+    for { set i 0 } { $i < $numxforms } { incr i } {
+	$img($i) Delete
+	$jac_1($i) Delete
+    }
+
+    $ana Delete
+    $average Delete
+    $averagejac Delete
+    $reg Delete
+    $tr Delete
+    $trg Delete
+    $tr2 Delete
+}
+
+# ------------------------------------------------------------------------------------------
+
+proc TestAverageTransformation { xformlist refimg namestem } {
+
+    set numxforms [ llength $xformlist ]
+    puts stdout "$numxforms transformations"
+    
+    set ana [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+    $ana Load $refimg
+
+    scan [ [ $ana GetOutput ] GetDimensions ] "%d %d %d" dim(0) dim(1) dim(2)
+    scan [ [ $ana GetOutput ] GetSpacing ] "%f %f %f" spa(0) spa(1) spa(2)
+    scan [ [ $ana GetOutput ] GetOrigin ] "%f %f %f" ori(0) ori(1) ori(2)
+
+    puts stdout "Loaded Image $refimg (dim = $dim(0)x$dim(1)x$dim(2), sp=$spa(0)x$spa(1)x$spa(2), origin=$ori(0),$ori(1),$ori(2))"
+
+    set tr2 [ vtkpxGridTransform [ pxvtable::vnewobj ]]
+    set ok [ $tr2 Load "${namestem}_averageinverse.grd" ]
+    puts stderr "Average Inverse Transform Loaded from ${namestem}_averageinverse.grd (status = $ok) "
+    if { $ok == 0 } {
+	$ana Delete
+	$tr2 Delete
+	puts stderr "Bad Transformation filename exiting\n"
+	exit
+    }
+
+    set averagejac2 [ vtkpxAverageImages [ pxvtable::vnewobj ]]
+    $averagejac2 SetMedian 0; $averagejac2 SetSumOnly 0
+
+    for { set i 0 } { $i < $numxforms } { incr i } {
+	
+	set m [ lindex $xformlist $i ]
+	set combo [ vtkpxComboTransform [ pxvtable::vnewobj ]]
+	puts stdout "Computing Combo Jacobian for [ file tail $m ] \t [ file size $m ]"
+	$combo Load $m
+	
+	set jac_2($i) [ vtkImageData [ pxvtable::vnewobj ]] 
+
+	set gen [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+	$gen PostMultiply
+	$gen Concatenate $combo
+	$gen Concatenate $tr2
+	$reg ComputeJacobianImage [ $ana GetOutput ] $jac_2($i) gen 0.01 100.0
+	$gen Delete
+
+	$averagejac2 AddInput $jac_2($i)
+	$combo Delete
+    }
+
+    $averagejac2 Update
+
+    set anaw2 [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+    $anaw2 SetInput [ $averagejac2 GetOutput ]
+    $anaw2 SetOrientation [ $ana GetOrientation ]
+    $anaw2 Save "averagejacobian2"
+    $anaw2 Delete
+
+
+    for { set i 0 } { $i < $numxforms } { incr i } { 
+	$jac_2($i) Delete
+    }
+    $averagejac2 Delete
+    $tr2 Delete
+    $ana Delete
+}
+# --------------------------------------------------------------------------------------------------------
+proc TestImages {  } {
+
+    global refimg
+    global transformlist
+    
+    puts stdout "Testing for existence of images/transformations"
+
+    
+    for { set i 0 } { $i < [ llength $transformlist ] } { incr i } {
+	
+	set a [ lindex $transformlist $i ]
+	set index [ format "%3d" [ expr $i +1 ] ]
+	set ok1 [ file exists $a ] ;   set sz1 -1 ; catch { set sz1 [ file size $a ] }
+	
+	if { $ok1 > 0 } {
+	    puts stdout "\t$index  $a ($sz1)  ok"
+	} else {
+	    puts stdout "\n*********** Missing Transform $a ($sz1)"
+	    exit
+	}
+
+	set refimgname [ lindex $refimg 0 ]
+	set a $refimgname
+	set b "[ file root $refimgname ].img"
+	set ok1 [ file exists $a ] ;   set sz1 -1 ; catch { set sz1 [ file size $a ] }
+	set ok2 [ file exists $b ] ;   set sz2 -1 ; catch { set sz2 [ file size $b ] }
+	
+	if { $ok1 > 0 && $ok2 > 0 } {
+	    puts stdout "\tSingle Ref image  $a,[file tail $b ] ($sz1,$sz2)  ok"
+	} else {
+	    puts stdout "\n*********** Missing Image $a,$b ($sz1,$sz2)"
+	    exit
+	}
+    }
+}
+
+
+
+
+# ------------------------------------------------------------------------------------------
+
+proc ComputeAverageBrain { refimg namestem forcemni } {
+
+    set linear 0
+    set ana2   0
+
+    set ana [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+    $ana Load $refimg
+
+    scan [ [ $ana GetOutput ] GetDimensions ] "%d %d %d" dim(0) dim(1) dim(2)
+    scan [ [ $ana GetOutput ] GetSpacing ] "%f %f %f" spa(0) spa(1) spa(2)
+    scan [ [ $ana GetOutput ] GetOrigin ] "%f %f %f" ori(0) ori(1) ori(2)
+
+    puts stdout "Loaded Image $refimg (dim = $dim(0)x$dim(1)x$dim(2), sp=$spa(0)x$spa(1)x$spa(2), origin=$ori(0),$ori(1),$ori(2))"
+
+    set tr2 [ vtkpxGridTransform [ pxvtable::vnewobj ]]
+    set ok [ $tr2 Load "${namestem}_averageinverse.grd" ]
+    puts stderr "Average Inverse Transform Loaded from ${namestem}_averageinverse.grd (status = $ok) "
+    if { $ok == 0 } {
+	$ana Delete
+	$tr2 Delete
+	puts stderr "Bad Transformation filename exiting\n"
+	exit
+    }
+
+
+    if { $forcemni } {
+	# Register the refimg to mni and get a transformation .....
+	# set 
+	set dirname [ file dirname [ info script ] ]
+	set mnifilename [ file join $dirname [ file join ".." [ file join images "mni_305.hdr" ] ] ]
+	puts stderr "mnifilename = $mnifilename "
+	puts stderr "target = $refimg "
+	
+	puts stderr "exec  pxmat_register.tcl $mnifilename $refimg ${namestem}_tomni.matr 1 1.25 > ${namestem}_tomni.log 2>&1"
+	exec  pxmat_register.tcl $mnifilename $refimg ${namestem}_tomni.matr 1 1.25 > ${namestem}_tomni.log 2>&1
+	set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ] ]
+
+	set linear [ $ut LoadAbstractTransform  ${namestem}_tomni.matr ]
+	$ut Delete
+
+	set ana2 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+	$ana2 Load $mnifilename
+
+	scan [ [ $ana2 GetOutput ] GetDimensions ] "%d %d %d" dim(0) dim(1) dim(2)
+	scan [ [ $ana2 GetOutput ] GetSpacing ] "%f %f %f" spa(0) spa(1) spa(2)
+	scan [ [ $ana2 GetOutput ] GetOrigin ] "%f %f %f" ori(0) ori(1) ori(2)
+
+	puts stdout "Loaded Image $mnifilename (dim = $dim(0)x$dim(1)x$dim(2), sp=$spa(0)x$spa(1)x$spa(2), origin=$ori(0),$ori(1),$ori(2))"
+    }
+
+    set gen [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+    $gen PostMultiply
+    if { $linear !=0 } {
+	puts stderr "Concatenating linear to map to mni space"
+	$gen Concatenate $linear
+    }
+    $gen Concatenate $tr2
+
+    set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+    $resl SetInput [ $ana GetOutput ]
+    if { $ana2 != 0 } {
+	$resl SetInformationInput [ $ana2 GetOutput ]
+    } else {
+	$resl SetInformationInput [ $ana GetOutput ]
+    }
+    $resl SetInterpolationMode 1
+    $resl SetBackgroundLevel 0.0
+    $resl OptimizationOff
+    $resl SetResliceTransform $gen
+    $resl Update
+    
+    set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+    $anaw SetInput [ $resl GetOutput ]
+    if { $ana2 !=0 } {
+	$anaw SetImageHeader [ $ana2 GetImageHeader ]
+    } else {
+	$anaw SetImageHeader [ $ana1 GetImageHeader ]
+    }
+
+    set outname "${namestem}_averagebrain"
+    $anaw Save $outname
+    
+    puts stdout "Average Saved in $outname, dimensions [ [ $resl GetOutput ] GetDimensions ]"
+ 
+
+    $resl Delete
+    $ana  Delete
+    $anaw Delete
+    $gen  Delete
+    $tr2  Delete
+
+    if { $linear !=0 } {
+	$linear Delete
+	$ana2 Delete
+    }
+    
+}
+
+# ------------------------------------------------------------------------------------------
+#  Main Program is Here
+# ------------------------------------------------------------------------------------------
+set argc [llength $argv]
+if { $argc < 2 } {
+    puts stderr "Usage  pxmat_computeaveragebrain.tcl setup_file output_directory \[ go\]"
+    puts stderr " if the word go is missing the program simply tests for the presence of all the images"
+    puts stderr "\n type pxmat_computeaveragebrain.tcl > sample.setup "
+    puts stderr " \t to generate a sample setup file\n"
+
+    puts stdout "\#Example Setup File\n\# all lines beginning with \# are ignored \n\#"
+    puts stdout "\#\n\#\n\# List all subjects here\n\#"
+    puts stdout "set transformlist \{"
+    puts stdout "   /usr/home/schultz/brain_reg/brains/1001/sag.cihte.grd"
+    puts stdout "   /usr/home/schultz/brain_reg/brains/1002/sag.cihte.lw.grd"
+    puts stdout "\}\n\#"
+    puts stdout "\#\n\#\n\# Put reference brain here\n\#"
+    puts stdout "set refimg  /home/papad/normalized/1115_normalized.hdr\n\#"
+    puts stdout "\#\n\#\n\# Put the name stem\n\#"
+    puts stdout "set namestem normals"
+    puts stdout "\#\n\#\n\# Set this to 1 to do some checking via computing jacobians"
+    puts stdout "set debugmode 0"
+    puts stdout "\#\n\#\n\# Set this to 1 to skip recomputing the average inverse transform"
+    puts stdout "set haveaverageinversetransform 0"
+    puts stdout "\#\n\#\n\# Set this to 0 to skip computing  an average brain image"
+    puts stdout "set computenewaveragebrain 1"
+    puts stdout "\#\n\#\n\# Set this to 1 to force the new average brain image to be in MNI space (recommended)\n\#"
+    puts stdout "set maptomni 1"
+    exit
+}
+
+# --------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+set outputdirectory [ lindex $argv 1 ]
+set inputfile [ file tail [ file root [ lindex $argv 0 ]]]
+
+set transformlist ""
+set refimg  ""
+set namestem "normals"
+set debugmode 0
+set haveaverageinversetransform 1
+set computenewaveragebrain 1
+set maptomni 1
+
+source [ lindex $argv 0 ]
+
+# --------------------------------------------------------------------------
+
+TestImages 
+
+if { [ llength $argv ] < 3 } {
+    exit
+}
+
+set namestem [ file join $outputdirectory $namestem ]
+
+MakeDirectory
+
+if { $haveaverageinversetransform < 1 }  {
+    ComputeAverageTransformations $transformlist $refimg $namestem $debugmode
+    
+    if { $debugmode == 1 } {
+	TestAverageTransformation     $transformlist $refimg $namestem 
+    }
+} else {
+    puts stderr "\n\n Not Recomputing Average Transformation\n"
+}
+
+if { $computenewaveragebrain > 0 } {
+    ComputeAverageBrain $refimg $namestem $maptomni
+}
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_computedistance.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_computedistance.tcl
new file mode 100755
index 0000000..62de7a3
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_computedistance.tcl
@@ -0,0 +1,98 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxmat_computedistance.tcl,v 1.1 2004/01/15 15:11:37 xenios Exp xenios $	
+
+
+
+
+
+if { [ llength $argv ] < 6 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a script that prints the distance between two surfaces after a transformation"
+    puts stdout "Syntax: $scriptname  pointset1.vtk  pointset2.vtk transform.grd matchmode temperature numpoints"
+    puts stdout "\t\t matchmode = 0 = ICP, 1=Mixture, 2=RPM (Use 0 for nearest neighbor), temperature is used if matchmode !=0, number of points = number of points to use for distance computation"
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+vtkPolyDataReader p1
+p1 SetFileName [ lindex $argv 0 ]
+p1 Update
+
+vtkPolyDataReader p2
+p2 SetFileName [ lindex $argv 1 ]
+p2 Update
+
+set sur(0) [ p1 GetOutput ]
+set nam(0) [ lindex $argv 0 ]
+set sur(1) [ p2 GetOutput ]
+set nam(1) [ lindex $argv 1 ]
+
+vtkpxTransformationUtil ut
+set trn [ ut LoadAbstractTransform [ lindex $argv 2 ]]
+
+set matchmode [ lindex $argv 3 ]
+set temperature [ lindex $argv 4 ]
+set numpoints [ lindex $argv 5 ]
+
+
+puts stdout "Surface 1  [ file tail $nam(0) ] pts = [ $sur(0) GetNumberOfPoints ]"
+puts stdout "Surface 2  [ file tail $nam(1) ] pts = [ $sur(1) GetNumberOfPoints ]"
+puts stdout "Transformation loaded from [ lindex $argv 2 ],  [ $trn GetClassName ]"
+puts stdout "MatchMode= $matchmode, Temperature = $temperature, numpoints=$numpoints"
+
+vtkpxRPMCorrespondenceFinder rpm
+
+rpm SetSource $sur(0)
+rpm SetTarget $sur(1)
+rpm DebugOn
+rpm SetMaximumNumberOfLandmarks $numpoints
+rpm SetMatchMode $matchmode
+rpm SetUseLabels 1
+rpm SetFastThreshold 3.0
+#rpm SetNoScaling 1
+rpm Initialize
+
+rpm WarpAndUpdateCorrespondence $trn $temperature
+rpm ComputeDistance "[ file tail [ lindex $argv 2 ] ] \t $matchmode"
+
+exit 0
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_computeoverlap.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_computeoverlap.tcl
new file mode 100755
index 0000000..024dc7e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_computeoverlap.tcl
@@ -0,0 +1,380 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+# 	$Id: pxmat_computeoverlap.tcl,v 1.1 2004/01/15 15:07:53 xenios Exp xenios $	
+
+if { [ llength $argv ] < 2 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+
+    puts stdout "$scriptname computes overlap metrics. overlap1 = 100*(V1 ^ V2)/(V1 U V2),overlap2 = 100* V2/Avarage(V1,V2)"
+    puts stdout "Syntax: $scriptname reference_image target_image \[ sigma=1.0 \] \[ transformation \]"
+    puts stdout "\t\t sigma=gaussian st. deviation for smoothing binary image, and transformation is optional mapping"
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+
+proc ComputeOverlap { img1 img2 comment sigma xform } {
+
+    puts stdout "Comment=$comment, $sigma, [ $xform GetClassName ]"
+
+    set image(1) $img1
+    set image(2) $img2
+
+    scan [ $image(1) GetDimensions ] "%f %f %f" x1 y1 z1
+    scan [ $image(2) GetDimensions ] "%f %f %f" x2 y2 z2
+
+    if { $x1 < 2 || $x2  < 2 } { 
+	puts stderr  "No Reference or Transform Image in Memory\n Cannot Compute Overlap!"
+	return  0
+    }
+
+
+
+
+    # Step One Threshold both 
+    
+    for { set k 1 } { $k <= 2 } { incr k } {
+
+	set spa [ $image($k)  GetSpacing ]
+	
+	for { set i 0 } { $i <= 2 } { incr i } {
+	    set smsigma($i) [ expr $sigma / [ lindex $spa $i ]]
+	}
+
+	set smooth($k)  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+	$smooth($k) SetStandardDeviations $smsigma(0) $smsigma(1) $smsigma(2)
+	$smooth($k) SetInput $image($k)
+	$smooth($k) SetRadiusFactors 1.5 1.5 1.5
+	$smooth($k) Update
+
+	if { $k == 1 } {
+	    set r  [ [ [ [ $smooth($k) GetOutput ] GetPointData ] GetScalars ] GetRange ]
+	    set low($k) [ expr  0.5*( [ lindex $r 0 ] + [ lindex $r 1 ]) ]
+	    set high($k) [ expr  1 + [ lindex $r 1 ]]
+	    puts stderr "Thresholding Image $k ($r) $low($k):$high($k)"
+	    set threshold($k)  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+	}
+
+	if { $k == 2 } {
+	    set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+	    $resl SetInput [ $smooth($k)  GetOutput ]
+	    $resl SetInformationInput [ $smooth(1) GetOutput ]
+	    $resl SetInterpolationMode 1
+	    $resl SetBackgroundLevel 0.0
+	    $resl SetResliceTransform $xform
+	    $resl Update
+
+	    set r  [ [ [ [ $resl GetOutput ]  GetPointData ] GetScalars ] GetRange ]
+	    set low($k) [ expr  0.5*( [ lindex $r 0 ] + [ lindex $r 1 ]) ]
+	    set high($k) [ expr  1 + [ lindex $r 1 ]]
+	    puts stderr "Thresholding Image $k ($r) $low($k):$high($k)"
+	    set threshold($k)  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+	    $threshold($k) SetInput [ $resl GetOutput ]
+	    $resl Delete
+	} else {
+	    $threshold($k) SetInput [ $smooth($k) GetOutput ]
+	}
+
+	$threshold($k) ThresholdBetween  $low($k) $high($k)
+	$threshold($k) SetInValue    1
+	$threshold($k) SetOutValue   0
+	$threshold($k) ReplaceInOn
+	$threshold($k) ReplaceOutOn
+	$threshold($k) SetOutputScalarTypeToUnsignedChar
+	$threshold($k) Update
+
+	set image($k) [ $threshold($k) GetOutput ]
+	
+	set accum($k)  [  vtkImageAccumulate [ pxvtable::vnewobj ] ]
+
+	$accum($k) SetInput $image($k)
+	$accum($k) SetComponentExtent 0 1 0 0 0 0
+	$accum($k) SetComponentOrigin 0 0 0 
+	$accum($k) SetComponentSpacing 1.0 1.0 1.0
+	$accum($k) Update
+	
+	if { $k == 1 } {
+	    set ve [ [ [ [ $accum($k) GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+	} else {
+	    set va [ [ [ [ $accum($k) GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+	}
+    }
+    
+    set compare1 [ vtkImageMathematics [ pxvtable::vnewobj ]]
+    $compare1 SetInput1 $image(1)
+    $compare1 SetInput2 $image(2)
+    $compare1 SetOperationToMultiply
+    $compare1 Update
+
+    set accumcompare1  [  vtkImageAccumulate [ pxvtable::vnewobj ] ]
+    $accumcompare1 SetInput [ $compare1 GetOutput ]
+    $accumcompare1 SetComponentExtent 0 1 0 0 0 0
+    $accumcompare1 SetComponentOrigin 0 0 0 
+    $accumcompare1 SetComponentSpacing 1.0 1.0 1.0
+    $accumcompare1 Update
+
+    # vae == intesection 
+    set vae [ [ [ [ $accumcompare1 GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+
+    set overlap [ expr 100.0 * $vae / ( $va + $ve - $vae ) ]
+    set overlap2 [ expr 100.0* $vae / ( 0.5 * ( $va + $ve )  ) ]
+
+    set line1 [ format "Va:\t %d \t Ve:\t %d \t Vae:\t %d \t Overlap:\t %.2f \t Overlap2\t %.2f \t Sigma:\t %.3f " $va $ve $vae $overlap $overlap2 $sigma ]
+
+    puts stdout  "$comment:OV\t  $line1"
+    
+    for { set k 1 } { $k <= 2 } { incr k } {
+	$threshold($k) Delete
+	$accum($k) Delete
+    }
+    
+    ${compare1} Delete
+    ${accumcompare1} Delete
+    
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------------------------
+
+proc ComputeMultiOverlap { img1 img2 comment sigma xform } {
+
+    puts stdout "Comment=$comment, $sigma, [ $xform GetClassName ]"
+
+    set image(1) $img1
+    set image(2) $img2
+
+    vtkpxTransformationUtil ut
+
+    scan [ $image(1) GetDimensions ] "%f %f %f" x1 y1 z1
+    scan [ $image(2) GetDimensions ] "%f %f %f" x2 y2 z2
+
+    if { $x1 < 2 || $x2  < 2 } { 
+	puts stderr  "No Reference or Transform Image in Memory\n Cannot Compute Overlap!"
+	return  0
+    }
+
+
+    set range [ [ [ $image(1) GetPointData ] GetScalars ] GetRange ]
+
+    set low_thr [ expr [ lindex $range 0 ] + 1 ]
+    set high_thr  [ lindex $range 1 ]
+
+    # Step One Threshold both 
+    
+    for { set thr $low_thr } { $thr <=$high_thr } { set thr [ expr $thr +1.0 ] } {
+
+	for { set k 1 } { $k <= 2 } { incr k } {
+	
+	    set cast($k)  [  vtkImageCast [ pxvtable::vnewobj ] ]
+	    $cast($k) SetInput $image($k)
+	    $cast($k) SetOutputScalarTypeToFloat
+	    $cast($k) Update
+
+	    set prethreshold($k)  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+	    
+	    set low  [ expr $thr - 0.1 ]
+	    set high [ expr $thr + 0.1 ]
+
+	    $prethreshold($k) SetInput [$cast($k)  GetOutput ]
+	    $prethreshold($k) ThresholdBetween  $low $high
+	    $prethreshold($k) SetInValue    100
+	    $prethreshold($k) SetOutValue   0
+	    $prethreshold($k) ReplaceInOn
+	    $prethreshold($k) ReplaceOutOn
+	    $prethreshold($k) SetOutputScalarTypeToUnsignedChar
+	    $prethreshold($k) Update
+
+	    $cast($k) Delete
+
+	    set spa [ $image($k)  GetSpacing ]
+	    
+	    for { set i 0 } { $i <= 2 } { incr i } {
+		set smsigma($i) [ expr $sigma / [ lindex $spa $i ]]
+	    }
+	    
+	    set smooth($k)  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+	    $smooth($k) SetStandardDeviations $smsigma(0) $smsigma(1) $smsigma(2)
+	    $smooth($k) SetInput [ $prethreshold($k) GetOutput ] 
+	    $smooth($k) SetRadiusFactors 1.5 1.5 1.5
+	    $smooth($k) Update
+	    $prethreshold($k) Delete
+	    
+	    set threshold($k)  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+
+	    if { $k == 2 } {
+		set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+		$resl SetInput [ $smooth($k)  GetOutput ]
+		$resl SetInformationInput [ $smooth(1) GetOutput ]
+		$resl SetInterpolationMode 1
+		$resl SetBackgroundLevel 0.0
+		$resl SetResliceTransform $xform
+		$resl Update
+		$threshold($k) SetInput [ $resl GetOutput ]		
+		$resl Delete
+	    } else {
+		$threshold($k) SetInput [ $smooth($k) GetOutput ]
+	    }
+	    
+
+	    set r [ [ [ [ $threshold($k) GetInput ] GetPointData ] GetScalars ] GetRange ]
+	    set lowr [ expr 0.5* ([lindex $r 0 ] + [ lindex $r 1 ]) ]
+	    set highr [ lindex $r 1 ]
+	    $threshold($k) ThresholdBetween  $lowr $highr
+	    $threshold($k) SetInValue    1
+	    $threshold($k) SetOutValue   0
+	    $threshold($k) ReplaceInOn
+	    $threshold($k) ReplaceOutOn
+	    $threshold($k) SetOutputScalarTypeToUnsignedChar
+	    $threshold($k) Update
+	    
+	    set finalimage($k) [ $threshold($k) GetOutput ]
+	
+	    set accum($k)  [  vtkImageAccumulate [ pxvtable::vnewobj ] ]
+	    
+	    $accum($k) SetInput $finalimage($k)
+	    $accum($k) SetComponentExtent 0 1 0 0 0 0
+	    $accum($k) SetComponentOrigin 0 0 0 
+	    $accum($k) SetComponentSpacing 1.0 1.0 1.0
+	    $accum($k) Update
+	    
+	    if { $k == 1 } {
+		set ve [ [ [ [ $accum($k) GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+	    } else {
+		set va [ [ [ [ $accum($k) GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+	    }
+	}
+	
+	set compare1 [ vtkImageMathematics [ pxvtable::vnewobj ]]
+	$compare1 SetInput1 $finalimage(1)
+	$compare1 SetInput2 $finalimage(2)
+	$compare1 SetOperationToMultiply
+	$compare1 Update
+	
+	set accumcompare1  [  vtkImageAccumulate [ pxvtable::vnewobj ] ]
+	$accumcompare1 SetInput [ $compare1 GetOutput ]
+	$accumcompare1 SetComponentExtent 0 1 0 0 0 0
+	$accumcompare1 SetComponentOrigin 0 0 0 
+	$accumcompare1 SetComponentSpacing 1.0 1.0 1.0
+	$accumcompare1 Update
+	
+	# vae == intesection 
+	set vae [ [ [ [ $accumcompare1 GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+	
+	set overlap [ expr 100.0 * $vae / ( $va + $ve - $vae ) ]
+	set overlap2 [ expr 100.0* $vae / ( 0.5 * ( $va + $ve )  ) ]
+
+	set line1 "thr=$thr overlap=$overlap\n"
+	catch { set line1 [ format "thr:%.1f\t Va:\t %d \t Ve:\t %d \t Vae:\t %d \t Overlap:\t %.2f \t Overlap2:\t %.2f \t Sigma:\t %.3f " $thr $va $ve $vae $overlap $overlap2 $sigma ] }
+	
+	puts stdout  "$comment:OV\t  $line1"
+	
+	for { set k 1 } { $k <= 2 } { incr k } {
+	    $threshold($k) Delete
+	    $accum($k) Delete
+	    $smooth($k) Delete
+
+	}
+	
+	${compare1} Delete
+	${accumcompare1} Delete
+
+	    
+	
+    }
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------------------------
+
+
+#puts stdout " Number of Arguments = [ llength $argv ] "
+
+set reference     [ lindex $argv 0 ]
+set target        [ lindex $argv 1 ]
+set sigma   1.0
+
+if { [ llength $argv ]  > 2 } {
+    set sigma [ lindex $argv 2 ]
+}
+
+set ana1 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana1 Load $reference
+
+set ana2 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana2 Load $target
+
+puts stdout "\nComputing Overlap"
+puts stdout "\tLoaded image [ $ana1 GetFilePrefix ] dim [ [ $ana1 GetOutput ] GetDimensions ]"
+puts stdout "\tLoaded image [ $ana2 GetFilePrefix ] dim [ [ $ana2 GetOutput ] GetDimensions ]"
+
+set comment "[ file tail [ file rootname [ $ana1 GetFilePrefix ] ]]\t[ file tail [ file rootname [ $ana2 GetFilePrefix ] ]]"
+
+if { [ llength $argv ] > 3 } {
+
+    set fname [ lindex $argv 3 ]
+    set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+    set xform [ $ut LoadAbstractTransform $fname ]
+    puts stderr "Transformation Loaded from $fname [ $xform GetClassName ]"
+    set comment "[ file dirname $fname] \t [ file tail $fname ] \t ${comment}"
+} else {
+    set xform [ vtkIdentityTransform [ pxvtable::vnewobj ]]
+    set comment "${comment}:identity"
+}
+
+
+set ref [ $ana1 GetOutput ]
+set trg [ $ana2 GetOutput ]
+
+if { $sigma > 0.0 } {
+    ComputeOverlap $ref $trg $comment $sigma $xform
+} else {
+    ComputeMultiOverlap $ref $trg $comment [ expr abs($sigma) ] $xform
+}
+
+
+$ana1 Delete
+$ana2 Delete
+$xform Delete
+catch { $ut Delete }
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_computesimilarity.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_computesimilarity.tcl
new file mode 100755
index 0000000..72c4a33
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_computesimilarity.tcl
@@ -0,0 +1,157 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxmat_computesimilarity.tcl,v 1.1 2004/01/15 15:11:23 xenios Exp xenios $	
+
+
+
+set argc [ llength $argv ]
+
+if { $argc != 3 && $argc != 8 } {
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+
+    puts stdout "$scriptname is a script that prints the image similarity after a transform and optionally point distances"
+    puts stdout "Syntax: $scriptname image1 image2 transformation \[ pointset1.vtk \] \[ pointset2.vtk \] \[ temperature \] \[ numpoints \] \[ matchmode  \]"
+    puts stdout "\t\t matchmode = 0 = ICP, 1=Mixture, 2=RPM (Use 0 for nearest neighbor), temperature is used if matchmode !=0, number of points = number of points to use for distance computation"
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+
+
+vtkpxAnalyzeImageSource ana1
+ana1 Load [ lindex $argv 0 ]
+
+vtkpxAnalyzeImageSource ana2
+ana2 Load [ lindex $argv 1 ]
+
+
+vtkpxTransformationUtil ut
+set trn [ ut LoadAbstractTransform [ lindex $argv 2 ]]
+
+
+puts stderr "Image 1 Loaded from [ lindex $argv 0 ] dim = [ [ ana1 GetOutput ] GetDimensions ] vox = [ [ ana1 GetOutput ] GetSpacing ]"
+puts stderr "Image 2 Loaded from [ lindex $argv 1 ] dim = [ [ ana2 GetOutput ] GetDimensions ] vox = [ [ ana2 GetOutput ] GetSpacing ]"
+puts stderr "Transformation loaded from [ lindex $argv 2 ],  [ $trn GetClassName ]"
+
+
+if { $argc == 8 } {
+    vtkPolyDataReader p1
+    p1 SetFileName [ lindex $argv 3 ]
+    p1 Update
+
+    vtkPolyDataReader p2
+    p2 SetFileName [ lindex $argv 4 ]
+    p2 Update
+
+    set sur(0) [ p1 GetOutput ]
+    set nam(0) [ lindex $argv 0 ]
+    set sur(1) [ p2 GetOutput ]
+    set nam(1) [ lindex $argv 1 ]
+
+    set temperature [ lindex $argv 5 ]
+    set numpoints [ lindex $argv 6 ]
+    set matchmode [ lindex $argv 7 ]
+
+    puts stderr "Surface 1  [ file tail $nam(0) ] pts = [ $sur(0) GetNumberOfPoints ]"
+    puts stderr "Surface 2  [ file tail $nam(1) ] pts = [ $sur(1) GetNumberOfPoints ]"
+    puts stderr "Temperature = $temperature, numpoints=$numpoints"
+}
+
+
+set reg [ vtkpxRegistration [ pxvtable::vnewobj ]]
+set current_transform $trn
+set image_ref [ ana1 GetOutput ]
+set image_trn [ ana2 GetOutput ]
+
+
+set image_ref_short [vtkImageData [pxvtable::vnewobj]]
+set image_trn_short [vtkImageData [pxvtable::vnewobj]]
+
+ 
+set reg_measures [ list "Joint Entropy" "CR" "Gradient Correlation" "Mutual Information" "NMI" "Sum of Sq Diff" "Correlation ratio C(X|Y)" "Correlation ratio C(Y|X)" "Product" "DifferenceEntropy" ]
+
+   
+set arr [ vtkFloatArray [ pxvtable::vnewobj ]]
+$reg ExtractComponentAndCastImageToShort $image_ref_short $image_ref 0
+$reg ExtractComponentAndCastImageToShort $image_trn_short $image_trn 0
+$reg ComputeAllSimilarityMetricsBetweenImages $image_ref_short $image_trn_short $current_transform $arr
+puts stderr "Similarity between ref and resliced transform using \t [ lindex $argv 2 ]"
+for { set i 0 } { $i < [ $arr GetNumberOfTuples ] } { incr i } {
+#    if { $i ==1 || $i==4 } {
+	puts -nonewline stdout [ format "EX \t %s \t %s \t %8.5f \n" [ lindex $argv 2 ] [ lindex $reg_measures $i ] [ $arr GetComponent $i 0 ] ]
+#    }
+}
+
+if { [ $current_transform IsA vtkpxComboTransform  ] ==1 } {
+    set sm [ [ $current_transform GetGridTransform ] ComputeTotalBendingEnergy ]
+    puts stdout [ format "EX \t %s \t BEN \t %8.5f \n" [ lindex $argv 2 ] $sm ]
+}
+
+puts stdout ""
+$arr Delete
+$reg Delete
+
+if { $argc == 8 } {
+    vtkpxRPMCorrespondenceFinder rpm
+
+    puts stdout "Point Distances temp=$temperature, numpoints=$numpoints matchmode=$matchmode)"
+    rpm SetSource $sur(0)
+    rpm SetTarget $sur(1)
+    rpm SetMaximumNumberOfLandmarks $numpoints
+    rpm SetMatchMode $matchmode
+    rpm SetUseLabels 1
+    rpm SetFastThreshold 3.0
+    rpm Initialize
+    
+    rpm WarpAndUpdateCorrespondence $trn $temperature
+    set d [ rpm ComputeDistance [ lindex $argv 2 ] ]
+
+    #puts stdout [ format "EX \t %s \t RPM \t %8.5f \n" [ lindex $argv 2 ] $d ]
+    rpm Delete
+    p1 Delete
+    p2 Delete
+}
+
+ana1 Delete
+ana2 Delete
+$trn Delete
+
+exit
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_computestrains.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_computestrains.tcl
new file mode 100755
index 0000000..1d42973
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_computestrains.tcl
@@ -0,0 +1,86 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+# 	$Id: pxmat_computestrains.tcl,v 1.1 2004/01/15 15:07:53 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+
+if { [ llength $argv ] < 3 } { 
+    puts stdout "pxmat_computestrains is a script that reslices an image using one or more transformations"
+    puts stdout "\npxmat_computestrains.tcl reference_image output_jacobian xform \[ threshold \]"
+    exit
+}
+
+#puts stdout " Number of Arguments = [ llength $argv ] "
+
+set reference     [ lindex $argv 0 ]
+set outname       [ lindex $argv 1 ]
+set xform         [ lindex $argv 2 ]
+if { [ llength $argv ] > 3  } {
+    set threshold [ lindex $argv 3 ]
+} else {
+    set threshold -1.0
+}
+
+
+set ana1 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana1 Load $reference
+puts stdout "Loaded image [ $ana1 GetFilePrefix ] dim [ [ $ana1 GetOutput ] GetDimensions ]"
+
+set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+set trans [ $ut LoadAbstractTransform $xform ]
+puts stdout "Loading transformation from $xform [ $trans GetClassName ]"
+$ut Delete
+
+set reg [ vtkpxRegistration [ pxvtable::vnewobj ]]
+set img [ vtkImageData [ pxvtable::vnewobj ]]
+$reg ComputePrincipalStrains [ $ana1 GetOutput ] $img $trans $threshold
+$reg Delete
+
+set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+$anaw SetInput  $img 
+$anaw SetImageHeader [ $ana1 GetImageHeader ]
+$anaw Save $outname
+
+puts stdout "Saved in [ $anaw GetFileName ] dimensions [ $img GetDimensions ], threshold=$threshold"
+ 
+$anaw  Delete
+$ana1  Delete
+$trans Delete
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_create4dimage.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_create4dimage.tcl
new file mode 100755
index 0000000..c063082
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_create4dimage.tcl
@@ -0,0 +1,81 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+if { [ llength $argv ] < 2 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+
+    puts stdout "$scriptname is a script that combines a number of 3D volumes into 4D image (all images in analyze.hdr .img format)"
+    puts stdout "Syntax: $scriptname image1 image2 ... imagen"
+    puts stdout "\t\t output = image1_4D.hdr"
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+set appnd [ vtkImageAppendComponents [ pxvtable::vnewobj ]]
+
+for { set i 0 } { $i < [ llength $argv ] } { incr  i } {
+
+    set ana($i) [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+    $ana($i) Load [ lindex $argv $i ]
+    puts stdout "Loaded image [ expr $i +1 ] :  [ $ana($i) GetFilePrefix ] dim [ [ $ana($i) GetOutput ] GetDimensions ] [ [ $ana($i) GetOutput ] GetNumberOfScalarComponents ]"
+    $appnd AddInput [ $ana($i) GetOutput ]
+}
+
+$appnd Update
+
+set outname [ ::pxappscommon::GenOutputName [ lindex $argv 0 ] "4D" ]
+
+set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+$anaw SetInput [ $appnd GetOutput ]
+$anaw SetImageHeader [ $ana(0) GetImageHeader ]
+$anaw Save $outname
+
+set img [ $appnd GetOutput ]
+
+puts stdout "\n Output [ [ $anaw GetImageHeader ] GetHeaderDescription 0 ]"
+
+$anaw Delete
+$appnd Delete
+for { set i 0 } { $i < [ llength $argv ] } { incr  i } {
+    $ana($i) Delete
+}
+
+exit
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_displacementfield.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_displacementfield.tcl
new file mode 100755
index 0000000..462629b
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_displacementfield.tcl
@@ -0,0 +1,119 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxmat_displacementfield.tcl,v 1.1 2004/01/15 15:11:06 xenios Exp xenios $	
+
+
+
+
+
+if { [ llength $argv ] < 3 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+
+    puts stdout "$scriptname is a script that computes the displacement field from  an image using one or more transformations"
+    puts stdout "Syntax: $scriptname  reference_image output_field  xform1 \[ xform2 \] \[ xform3 \]"
+    puts stdout "\t\t e.g. xform1 = Ref -> 3D, xform2 = 3D -> Conv , xform3 = Conv->Echo"
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+set reference     [ lindex $argv 0 ]
+set outname       [ lindex $argv 1 ]
+
+set xform(1)        [ lindex $argv 2 ]
+set xform(2) ""
+set xform(3) ""
+if { [ llength $argv ] >= 4 } {
+    set xform(2)    [ lindex $argv 3 ] 
+    if { [ llength $argv ] >= 5 } {
+	set xform(3)    [ lindex $argv 4 ] 
+    }
+}
+
+set ana1 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana1 Load $reference
+
+puts stdout "Loaded image [ $ana1 GetFilePrefix ] dim [ [ $ana1 GetOutput ] GetDimensions ]"
+
+set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+
+for { set i 1 } { $i <= 3 } { incr i } {
+    if { $xform($i) != "" } {
+	set tr($i) [ $ut LoadAbstractTransform $xform($i) ]
+	puts stdout "Loading transformation $i from $xform($i)"
+    } else {
+	set tr($i) [ vtkIdentityTransform [ pxvtable::vnewobj ]]
+	puts stdout "Setting transformation $i to identity"
+    }
+}
+
+set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+$trans Identity
+$trans PostMultiply
+$trans Concatenate $tr(1)
+$trans Concatenate $tr(2)
+$trans Concatenate $tr(3)
+
+set dim [ [ $ana1 GetOutput ] GetDimensions ]
+set spa [ [ $ana1 GetOutput ] GetSpacing ]
+
+set tgrid [ vtkTransformToGrid [ pxvtable::vnewobj ]]
+$tgrid SetGridExtent 0 [ expr [ lindex $dim  0 ] -1 ] 0 [ expr [ lindex $dim  1 ] -1 ] 0 [ expr [ lindex $dim  2 ] -1 ]
+$tgrid SetGridOrigin  0 0 0
+$tgrid SetGridSpacing [ lindex $spa 0 ] [ lindex $spa 1 ] [ lindex $spa 2 ] 
+$tgrid SetInput $trans
+$tgrid Update
+
+set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+$anaw SetInput [ $tgrid GetOutput ]
+$anaw SetImageHeader [ $ana1 GetImageHeader ]
+$anaw Save $outname
+
+puts stdout "Saved in [ $anaw GetFileName ] dimensions [ [ $tgrid GetOutput ] GetDimensions ]"
+ 
+$anaw Delete
+$tgrid Delete
+$ana1 Delete
+$tr(1) Delete
+$tr(2) Delete
+$tr(3) Delete
+$trans Delete
+$ut Delete
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_distortioncorrection.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_distortioncorrection.tcl
new file mode 100755
index 0000000..d16f815
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_distortioncorrection.tcl
@@ -0,0 +1,218 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# --------------------------------------------------------------------------------------------------------
+# 	$Id: pxmat_distortioncorrection.tcl,v 1.1 2004/01/15 15:10:50 xenios Exp xenios $	
+
+
+
+
+set argc [llength $argv]
+if { $argc < 2 } {
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a script that computes non-linear distortion corrections for echoplanar images"
+
+    puts stdout "Syntax: $scriptname ref_image trg_image output_transformation \[phaseencodedirection=1\] \[resolution=2.0\] \[spacing=15\] \[iterations=12\] \[ step_size=3.0\] \[ smoothness=0.0005\]"
+    puts stdout "\n"
+    exit 0
+}
+   
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+set filenametype 0
+
+# --------------------------------------------------------------------------------------------------------
+proc DoNMIDistortion { image1 image2 output_xform xform_mode initialxform { resolution 1.5 } { spacing 15.0 } { iterations 15 } { stepsize 1 } { smoothness 0 } {phaseencode 1 } } {
+
+    if { $xform_mode == "linear" } {
+	set areg [ vtkpxLinearRegistration [ pxvtable::vnewobj ]]
+	$areg SetTransformModeToRigid
+	$areg SetSimilarityMeasure 5
+	$areg SetReferenceImage $image1
+	$areg SetTransformImage $image2
+	$areg SetReferenceOrientation 0
+	$areg SetTransformOrientation 0
+	$areg SetResolution $resolution
+	$areg SetNumberOfLevels 2
+	$areg SetNumberOfSteps  1
+	$areg SetStepSize       1.0
+	$areg SetOptimizationMethodToConjugateGradient
+	$areg SetNumberOfIterations $iterations 
+	eval "$areg AddObserver ProgressEvent { puts stdout  \[ $areg GetOutputStatus \] }"
+	$areg Run
+	
+	$output_xform DeepCopy  [ $areg GetTransformation ]
+	$areg Delete
+    } else {
+	set nreg [ vtkpxDistortionCorrection [ pxvtable::vnewobj ]]
+	$nreg SetSimilarityMeasure 5
+	
+	if { $initialxform !=0 } { 
+	    $nreg SetInitialTransform $initialxform 
+	    puts stdout "Using Initial Transformation"
+	}
+    
+	$nreg SetUseJacobian 0
+	$nreg SetUseSignalLossCorrection 0
+	$nreg SetReferenceImage $image1
+	$nreg SetTransformImage $image2 
+	$nreg SetNumberOfSteps  1
+	$nreg SetNumberOfLevels 3
+	$nreg SetStepSize       $stepsize 
+	$nreg SetLambda [ expr 0.01 * $smoothness ]
+	$nreg SetResolution     $resolution 
+	$nreg SetControlPointSpacing $spacing
+	$nreg SetControlPointSpacingRate 2.0
+	$nreg SetOptimizationMethodToDefault
+	$nreg SetNumberOfIterations $iterations
+	$nreg SetPhaseEncodeAxis $phaseencode
+	
+	eval "$nreg AddObserver ProgressEvent { puts stdout  \[ $nreg GetOutputStatus \] }"
+	$nreg Run
+	$output_xform DeepCopy  [ $nreg GetTransformation ]
+	$nreg Delete
+    }
+
+}
+# --------------------------------------------------------------------------------------------------------
+#   Main Program 
+# ----------------------------------------------------------------------------------------------------
+
+proc DoNMIDistortionAll { refimagename trnimagename output phaseencode resolution spacing iterations stepsize smoothness } {
+    
+    set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+    
+    puts stdout "\n----------------- Loading Reference Image ---------------------------\n"
+    set ana [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+    $ana Load $refimagename
+    set img_ref [ $ana GetOutput ]
+    puts stdout "Reference Image Read from $refimagename dimensions = [ $img_ref GetDimensions ]"
+    
+    set ana2 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+    $ana2 Load $trnimagename
+    set img_trn [ $ana2 GetOutput ]
+    puts stdout "Target Image Read from $trnimagename dimensions = [ $img_trn GetDimensions ]"
+    
+    		  
+    puts stdout "\n----------------- Running Linear  ---------------------------\n"
+
+    set xform [ vtkTransform [ pxvtable::vnewobj ]]
+    $xform Identity 
+    DoNMIDistortion  $img_ref $img_trn $xform linear 0 $resolution $spacing $iterations 1 0
+
+    puts stdout "\n----------------- Running Non-Linear  ---------------------------\n"
+    set xform2 [ vtkpxComboTransform [ pxvtable::vnewobj ] ]
+    DoNMIDistortion $img_ref $img_trn $xform2 nonlinear  $xform $resolution $spacing $iterations $stepsize $smoothness $phaseencode
+    set fname "${output}.grd"
+    set ok [ $xform2 Save $fname  ]
+    puts stdout "Non Linear Transformation saved in $fname ($ok) [ file size $fname ]"
+    $xform2 Delete
+
+    puts stdout "\n----------------- Done  ---------------------------\n"
+    
+    $ana Delete
+    $ana2 Delete
+    $xform Delete
+    $ut Delete
+    return 1
+}
+
+# --------------------------------------------------------------------------------------------------------
+
+
+set argc [ llength $argv ]
+set refimg [ lindex $argv 0 ]
+set tarimg [ lindex $argv 1 ]
+
+if { $argc > 2 } {
+    set output [ file root [ lindex $argv 2 ] ]
+} else {
+    set output "[ file root [ lindex $argv 0 ] ]_[ file root [ file tail [ lindex $argv 1 ]]]_distortion"
+    puts stderr "Output set to $output"
+}
+
+set phaseencodedirection 1
+if { $argc > 3 } {
+    if {  [ lindex $argv 3 ] < 1 } {
+	set phaseencodedirection 0
+    } else {
+	if {  [ lindex $argv 3 ] < 1 } {
+	    set phaseencodedirection 2
+	}
+    } 
+}
+
+# 1 2.0 15.0 12.1 3.0 0.0005
+
+if { $argc > 4 } {
+    set resolution [ lindex $argv 4 ]
+} else {
+    set resolution 2.0
+}
+
+if { $argc > 5 } {
+    set spacing [ lindex $argv 5 ]
+} else {
+    set spacing 15.0
+}
+
+if { $argc > 6 } {
+    set iterations [ expr round([ lindex $argv 6 ]) ]
+} else {
+    set iterations 12
+}
+
+
+if { $argc > 7 } {
+    set stepsize [ lindex $argv 7 ]
+} else {
+    set stepsize 3.0
+}
+
+
+if { $argc > 8 } {
+    set smoothness [ lindex $argv 8 ]
+} else {
+    set smoothness 0.0005
+}
+
+
+
+puts stdout "Beginning ref=$refimg -> tar=$tarimg output=$output phase encode direction (0=X,1=Y,2=Z)=$phaseencodedirection res=$resolution spa=$spacing it=$iterations stepsize=$stepsize smoothness=$smoothness numargs=[ llength $argv ]"
+
+DoNMIDistortionAll $refimg $tarimg  $output  $phaseencodedirection $resolution $spacing $iterations $stepsize $smoothness
+
+exit 0
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_fastpostprocess.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_fastpostprocess.tcl
new file mode 100755
index 0000000..0e39fc3
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_fastpostprocess.tcl
@@ -0,0 +1,125 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# --------------------------------------------------------------------------------------------------------
+# 	$Id: pxmultiregister_int.tcl,v 1.1 2004/01/15 15:06:06 xenios Exp xenios $	
+
+
+set imglist ""
+set numclasses 3
+set imgtype 1
+set identifier "segm"
+
+set argc [llength $argv]
+if { $argc <3 } {
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a script that converts fsl/fast output into a format suitable for use by BioImage Suite"
+    puts stdout "Syntax: $scriptname basename outname numclasses"
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+package require  pxitclimage            1.0
+package require  pxitcltransform        1.0
+package require  pxitclsubjectentry     1.0
+    
+set basename [ lindex $argv 0 ]
+set nc [ lindex $argv 2 ]
+set out  [ lindex $argv 1 ] 
+set outb ${out}_restore
+set outo ${out}_seg
+
+set anabase [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ] ]
+$anabase Load $basename
+set baseimg [ $anabase GetOutput ]
+puts stdout "Dim/Comp: [ $baseimg GetDimensions ] [ $baseimg GetNumberOfScalarComponents ] $basename\n-----------------------------\n"
+
+set anasource [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ] ]
+$anasource Load ${outo}.hdr
+set newimg [ $anasource GetOutput ]
+puts stdout "Read Output File $outo [ $newimg GetDimensions ]"
+
+#catch { file delete ${outo}.img }
+#catch { file delete ${outo}.hdr }
+
+puts stdout "Dim/Comp: [ $newimg GetDimensions ] [ $newimg GetNumberOfScalarComponents ] $outo"
+
+set cast [ vtkImageShiftScale [ pxvtable::vnewobj ]]
+$cast SetInput $newimg
+$cast SetScale [ expr 1.0 / $nc ]
+$cast SetOutputScalarTypeToFloat
+$cast Update
+
+puts stdout "Cast to float [ [ $cast GetOutput ] GetDimensions ] [ [ $cast GetOutput ] GetNumberOfScalarComponents ]"
+
+set merg [ vtkImageAppendComponents [ pxvtable::vnewobj ]]
+$merg AddInput [ $cast GetOutput ]
+
+for { set i 0 } { $i < $nc } { incr i } {
+    set pimg($i) [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ] ]
+    set tname ${out}_pbmap_$i
+    $pimg($i) Load $tname
+    puts stdout "Loaded $tname [ [ $pimg($i) GetOutput ] GetDimensions ] [ [ $pimg($i) GetOutput ] GetNumberOfScalarComponents ]"
+    
+    $merg AddInput [ $pimg($i) GetOutput ]
+    $pimg($i) Delete
+    
+    #catch { file delete ${tname}.img }
+    #catch { file delete ${tname}.hdr }
+}
+
+$merg Update
+set newimage [ vtkImageData [ pxvtable::vnewobj ]]
+$newimage ShallowCopy [ $merg GetOutput ]
+
+set t [ $merg GetOutput ]
+puts stdout "Dim/Comp: [ $t GetDimensions ] [ $t GetNumberOfScalarComponents ]"
+puts stdout "Dim/Comp: [ $newimage GetDimensions ] [ $newimage GetNumberOfScalarComponents ]"
+
+$merg Delete
+$cast Delete
+
+
+set anaw  [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ] ]
+$anaw SetInput $newimage
+$anaw SetImageHeader [ $anabase GetImageHeader ]
+$anaw Save ${out}_classification.hdr
+
+exit
+
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_flip.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_flip.tcl
new file mode 100755
index 0000000..94f0b07
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_flip.tcl
@@ -0,0 +1,113 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxflipslices.tcl,v 1.1 2004/01/15 15:11:59 xenios Exp xenios $	
+
+set num $argc 
+
+if { $num < 2 } {
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "Syntax: $scriptname direction file1 file2 file3 ..."
+    puts stdout "\t\tDirection 0=x, 1=y, 2=z"
+    puts stdout "\t\tOutput filenames are generated from input filenames with the addition of \"_flip\" "
+    puts stdout "\n"
+    exit 0
+}
+
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+
+set direction [ lindex $argv 0 ]
+if { $direction < 0 } {
+    set direction 0
+} elseif { $direction > 2 } {
+    set direction 2
+}
+
+
+
+proc ResliceImage { imagein imageout } {
+    		
+    global direction
+
+    set flip [ vtkImageFlip [ pxvtable::vnewobj ]]
+    $flip SetFilteredAxis $direction
+    $flip SetInput $imagein
+    $flip PreserveImageExtentOn
+    $flip Update
+    $imageout ShallowCopy [ $flip GetOutput ]
+    puts stdout "Dim=[$imageout GetDimensions], Vox size=[ $imageout GetSpacing ]"
+
+    catch { $flip   Delete }
+}
+
+
+set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+
+set axislist [ list x y z ]
+set outsuffix  "flip[lindex $axislist $direction ]"
+
+for { set i 1 } { $i < $num } { incr i } {
+    
+    puts stdout "----------------------------------------------"
+    set name [ lindex $argv $i ]
+
+    $ana Load $name
+    set or [ $ana GetOrientation ]
+
+    puts stdout "\nRead $name [ [ $ana GetOutput ] GetDimensions ] ori=$or "
+
+    set outp [ vtkImageData [ pxvtable::vnewobj ]]
+    ResliceImage [ $ana GetOutput ] $outp
+
+    set ana2 [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+
+    $ana2 SetInput $outp
+    $ana2 SetImageHeader [ $ana GetImageHeader ]
+
+    set fname [ ::pxappscommon::GenOutputName $name $outsuffix ]
+    $ana2 Save $fname
+
+    puts stdout "Resliced $name to $fname\n"
+    $ana2 Delete
+    $outp Delete
+}
+
+$ana Delete
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_headerinfo.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_headerinfo.tcl
new file mode 100755
index 0000000..c720e80
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_headerinfo.tcl
@@ -0,0 +1,80 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxmat_headerinfo.tcl,v 1.1 2004/01/15 15:10:15 xenios Exp xenios $	
+
+if { [ llength $argv ] < 1 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a script that prints  an analyze image header"
+    puts stdout "Syntax: $scriptname \[-short (default), -long or -full \] \[ image1 \] \[ image2 \] ..."
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+set begin 0
+set fullmode 0
+
+if { [ lindex $argv 0 ] == "-short" } {
+    set begin 1
+}
+
+if { [ lindex $argv 0 ] == "-min" } {
+    set begin 1
+    set fullmode -1
+}
+
+if { [ lindex $argv 0 ] == "-full" } {
+    set begin 1
+    set fullmode 2
+}
+if { [ lindex $argv 0 ] == "-long" } {
+    set begin 1
+    set fullmode 1
+}
+
+set num [  llength $argv ]
+set ana [ vtkbisImageHeader [ pxvtable::vnewobj ]]
+puts stdout "**** Printing Headers for [ expr $num -$begin ] images (mode=$fullmode)\n"
+for { set i $begin } { $i < $num } { incr i } {
+    $ana ReadHeader [ lindex $argv $i ]
+    puts stderr "\nImage : [ $ana GetHeaderDescription $fullmode  ]"
+}
+
+$ana Delete
+exit
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_integratedregistration.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_integratedregistration.tcl
new file mode 100755
index 0000000..5efc6cb
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_integratedregistration.tcl
@@ -0,0 +1,218 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# --------------------------------------------------------------------------------------------------------
+# 	$Id: pxmat_integratedregistration.tcl,v 1.1 2004/01/15 15:10:03 xenios Exp xenios $	
+
+
+
+
+
+# ----------------------------------------------------------------------------
+set argc   [ llength $argv ]
+
+
+set resolution 1.5
+set iterations 25
+set smoothness 0.0
+
+set temperature 1.5
+set numpoints 2000
+set pointsweight 1.0
+set preferentialsampling 0
+set fixed_correspondences 0
+set use_rpm 1
+set threshold_low  -100.0
+set threshold_high +100.0
+set spacing 15.0
+set numsteps 1
+
+set argc [llength $argv]
+if { $argc <6 } {
+    set scriptname [ file tail $argv0 ]
+
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a script that computes non-linear intensity + point-based registrations"
+
+    puts stdout "Syntax: $scriptname ref_image trg_image ref_surface trg_surface output_transformation input_transformation \[ spacing = 15 \] \[resolution=1.5\] \[iterations=15\] \[ smoothness=0.0\] \[ pts_weight=0.1 \] \[ numpoints 2000 \]  \[ temperature 1.5 \] \[ fixed_correspondences 0 \] \[ use_rpm 1 \] \[ numsteps =1 \] \[ surface_threshold_low -100 \] \[ surface_threshold_high 100.0 \] \[ autonormalize_intensities = 1 \]"
+    puts stdout "\n"
+    exit 1
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+set refimg  [ lindex $argv 0 ]
+set trnimg  [ lindex $argv 1 ]
+set refsur  [ lindex $argv 2 ]
+set trnsur  [ lindex $argv 3 ]
+set output  [ lindex $argv 4 ] 
+set initial [ lindex $argv 5 ]
+set autonormalize 1
+
+
+if { $argc > 6 }  {  set spacing  [ lindex $argv  6 ] }
+if { $argc > 7 }  {  set resolution  [ lindex $argv  7 ] }
+if { $argc > 8 }  {  set iterations  [ lindex $argv  8 ] }
+if { $argc > 9 }  {  set smoothness  [ lindex $argv  9 ] }
+if { $argc > 10 }  {  set pointsweight  [ lindex $argv  10 ] }
+if { $argc > 11 } {  set numpoints   [ lindex $argv 11 ] }
+if { $argc > 12 } {  set temperature [ lindex $argv 12 ] }
+if { $argc > 13 } {  set fixed_correspondences [ lindex $argv 13 ] }
+if { $argc > 14 } {  set use_rpm [ lindex $argv 14 ] }
+if { $argc > 15 } {  set numsteps    [ lindex $argv 15 ] }
+if { $argc > 16 } {  set threshold_low   [ lindex $argv 16 ] }
+if { $argc > 17 } {  set threshold_high  [ lindex $argv 17 ] }
+if { $argc > 18 } {  set autonormalize  [ expr  [ lindex $argv 18 ] > 0 ] }
+
+
+
+set comment "Beginning ref=$refimg ($refsur) -> tar=$trnimg ($trnsur) output=$output initial=$initial\n\t"
+set comment "${comment} spacing=$spacing resolution=$resolution, iterations=$iterations (x steps=$numsteps) smoothness=$smoothness pointsweight=$pointsweight numpoints=$numpoints surface_thresholds=$threshold_low : $threshold_high temperature=$temperature fixed_correspondences=$fixed_correspondences use_rpm=$use_rpm"
+
+puts stdout $comment
+
+set fout [ open ${output}.log w ]
+puts $fout $comment
+puts -nonewline $fout "commandline : \n\npxmat_intergratedregistration.tcl "
+for { set i 0 } { $i < [ llength $argv ] } { incr i } {
+    puts -nonewline $fout "[ lindex $argv $i] "
+}
+puts $fout " "
+close $fout
+
+puts stdout "\n----------------- Loading Images ---------------------------\n"
+set ana [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana Load $refimg
+set img_ref [ $ana GetOutput ]
+puts stdout "Reference Image Read from $refimg dimensions = [ $img_ref GetDimensions ]"
+
+set ana2 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana2 Load $trnimg
+set img_trn [ $ana2 GetOutput ]
+puts stdout "Target Image Read from $trnimg dimensions = [ $img_trn GetDimensions ]"
+
+puts stdout "\n----------------- Loading Surfaces ---------------------------\n"
+
+set pana [ vtkPolyDataReader [ pxvtable::vnewobj ]]
+$pana SetFileName $refsur; $pana Update
+if { $threshold_low != $threshold_high } {
+    set filt1 [ vtkThresholdPoints [ pxvtable::vnewobj ]]
+    $filt1 SetInput [ $pana GetOutput ]
+    $filt1 ThresholdBetween $threshold_low $threshold_high
+    $filt1 Update
+    set sur_ref [ $filt1 GetOutput ]
+} else {
+    set sur_ref [ $pana GetOutput ]
+}
+
+puts stdout "Reference Surface Read from $refsur thresholded points = [ $sur_ref GetNumberOfPoints ], bbox = [ $sur_ref GetBounds ] (orig = [ [ $pana GetOutput ] GetNumberOfPoints ])"
+    
+set pana2 [ vtkPolyDataReader [ pxvtable::vnewobj ]]
+$pana2 SetFileName $trnsur; $pana2 Update
+if { $threshold_low != $threshold_high } {
+    set filt2 [ vtkThresholdPoints [ pxvtable::vnewobj ]]
+    $filt2 SetInput [ $pana2 GetOutput ]
+    $filt2 ThresholdBetween $threshold_low $threshold_high
+    $filt2 Update
+    set sur_trn [ $filt2 GetOutput ]
+} else {
+    set sur_trn [ $pana2 GetOutput ]
+}
+puts stdout "Target Surface Read from $trnsur thresholded points = [ $sur_trn GetNumberOfPoints ], bbox = [ $sur_trn GetBounds ] (orig = [ [ $pana2 GetOutput ] GetNumberOfPoints ])"
+
+puts stdout "\n----------------- Load Initial  Registration  ---------------------------\n"
+
+set xform 0
+set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+set xform [ $ut LoadAbstractTransform $initial ]
+puts stdout "Initial Transform Loaded from $initial"
+
+puts stdout "\n----------------- Non-linear Integrated Registration ---------------------------\n"
+
+set nreg [ vtkpxNonLinearIntegratedRegistration [ pxvtable::vnewobj ]]
+$nreg SetAutoNormalizeIntensities $autonormalize
+$nreg SetSimilarityMeasure 5
+$nreg SetInitialTransform $xform 
+$nreg SetReferenceImage $img_ref
+$nreg SetTransformImage $img_trn
+$nreg SetNumberOfSteps  $numsteps
+$nreg SetNumberOfLevels 1
+$nreg SetStepSize       1.0
+$nreg SetFixedCorrespondences $fixed_correspondences
+$nreg SetLambda [ expr 0.01 * $smoothness ]
+$nreg SetPointsWeight [ expr 0.01 * $pointsweight ]
+$nreg SetResolution     $resolution
+$nreg SetNumberOfIterations [ expr round($iterations) ]
+$nreg SetControlPointSpacing $spacing
+$nreg SetControlPointSpacingRate 2.0
+$nreg SetOptimizationMethodToDefault
+
+
+set rpm [ $nreg GetRPMEstimator ]
+$rpm SetSource $sur_ref
+$rpm SetTarget $sur_trn
+$rpm SetMaximumNumberOfLandmarks $numpoints
+$rpm SetExtraDebug 0
+$rpm SetMatchModeToRPMFast
+if { $use_rpm == 0 } {
+    $rpm SetMatchModeToICP
+}
+$rpm SetUseLabels 1
+$rpm SetFastThreshold 3.0
+$rpm SetEnableFeedback 1
+$rpm SetTemperature $temperature
+
+eval "$nreg AddObserver ProgressEvent { puts stdout \[ $nreg GetOutputStatus \] }"
+$nreg Run
+
+set fname $output
+set ok [ [ $nreg GetTransformation ] Save $fname  ]
+puts stdout "Non Linear Transformation saved in $fname ($ok) [ file size $fname ]"
+$nreg Delete
+	
+puts stdout "\n----------------- Done  ---------------------------\n"
+
+$ana Delete
+$ana2 Delete
+$pana Delete
+$pana2 Delete
+
+exit 0
+
+# --------------------------------------------------------------------------------------------------------
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_inverttransform.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_inverttransform.tcl
new file mode 100755
index 0000000..e69eb2f
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_inverttransform.tcl
@@ -0,0 +1,165 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxmat_inverttransform.tcl,v 1.1 2004/01/15 15:09:49 xenios Exp xenios $	
+
+if { [ llength $argv ] == 0 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+
+    puts stdout "$scriptname is a script that computes the inverse transformation for one or more transformations"
+    puts stdout "Syntax: $scriptname reference_image output_transformation  xform1 \[ xform2 \] \[ xform3 \]\n"
+    puts stdout "\t\t The Image is only used if there are multiple transformations to define the space for the displacement field."
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+
+proc InvertSingle { xformname outname } {
+
+    set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]    
+    puts stdout "exists $xformname [ file exists $xformname ]"
+    set trans [ $ut LoadAbstractTransform $xformname ]
+    puts stdout "Loaded single transformation  from $xformname [ $trans GetClassName ]"
+    $trans Inverse
+    $ut SaveAbstractTransform $trans $outname
+    puts stdout "Inverse Transform Saved in $outname [ file size $outname ]"
+    $ut Delete
+}
+
+# ---------------------------------
+
+
+puts stdout " Number of Arguments = [ llength $argv ] "
+
+if { [ llength $argv ]  < 3  } {
+    set name [ lindex $argv 0 ]
+    set pname [ file dirname $name ]
+    set tname [ file tail $name ]
+    set out  [ file join $pname "Inverse_${tname}" ]
+    InvertSingle $name $out
+    exit
+}
+
+set reference     [ lindex $argv 0 ]
+set outname       [ lindex $argv 1 ]
+
+
+set xform(1)        [ lindex $argv 2 ]
+set xform(2) ""
+set xform(3) ""
+if { [ llength $argv ] >= 4 } {
+    set xform(2)    [ lindex $argv 3 ] 
+    if { [ llength $argv ] >= 5 } {
+	set xform(3)    [ lindex $argv 4 ] 
+    }
+}
+
+set numxforms [ expr [ llength $argv ] - 2 ]
+
+if { $numxforms == 1 } {
+    InvertSingle $xform(1) $outname 
+    exit
+}
+
+set ana1 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana1 Load $reference
+
+puts stdout "Loaded image [ $ana1 GetFilePrefix ] dim [ [ $ana1 GetOutput ] GetDimensions ]"
+
+set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+
+for { set i 1 } { $i <= 3 } { incr i } {
+    if { $xform($i) != "" } {
+	set tr($i) [ $ut LoadAbstractTransform $xform($i) ]
+	puts stdout "Loading transformation $i from $xform($i)"
+    } else {
+	set tr($i) [ vtkIdentityTransform [ pxvtable::vnewobj ]]
+	puts stdout "Setting transformation $i to identity"
+    }
+}
+
+set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+$trans Identity
+$trans PostMultiply
+$trans Concatenate $tr(1)
+$trans Concatenate $tr(2)
+$trans Concatenate $tr(3)
+
+set dim [ [ $ana1 GetOutput ] GetDimensions ]
+set spa [ [ $ana1 GetOutput ] GetSpacing ]
+
+set tgrid [ vtkTransformToGrid [ pxvtable::vnewobj ]]
+$tgrid SetGridExtent 0 [ expr [ lindex $dim  0 ] -1 ] 0 [ expr [ lindex $dim  1 ] -1 ] 0 [ expr [ lindex $dim  2 ] -1 ]
+$tgrid SetGridOrigin  0 0 0
+$tgrid SetGridSpacing [ lindex $spa 0 ] [ lindex $spa 1 ] [ lindex $spa 2 ] 
+$tgrid SetInput $trans
+$tgrid Update
+
+
+set trg [ vtkGridTransform [ pxvtable::vnewobj ]]
+$trg SetDisplacementGrid [ $tgrid GetOutput ]
+$trg SetInterpolationModeToLinear
+$trg Inverse
+
+set tgrid2 [ vtkTransformToGrid [ pxvtable::vnewobj ]]
+$tgrid2 SetGridExtent 0 [ expr [ lindex $dim  0 ] -1 ] 0 [ expr [ lindex $dim  1 ] -1 ] 0 [ expr [ lindex $dim  2 ] -1 ]
+$tgrid2 SetGridOrigin  0 0 0
+$tgrid2 SetGridSpacing [ lindex $spa 0 ] [ lindex $spa 1 ] [ lindex $spa 2 ] 
+$tgrid2 SetInput $trg
+$tgrid2 Update
+
+set tr2 [ vtkpxGridTransform [ pxvtable::vnewobj ]]
+$tr2 SetDisplacementGrid [ $tgrid2 GetOutput ]
+$tr2 SetInterpolationModeToLinear
+$tr2 Save $outname 
+ 
+
+puts stdout "Saved in $outname"
+ 
+$tgrid Delete
+$tgrid2 Delete
+$trg Delete
+$tr2 Delete
+$tr(1) Delete
+$tr(2) Delete
+$tr(3) Delete
+$trans Delete
+$ut Delete
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_pointregister.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_pointregister.tcl
new file mode 100755
index 0000000..b6e8f7a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_pointregister.tcl
@@ -0,0 +1,386 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# --------------------------------------------------------------------------------------------------------
+# 	$Id: pxmat_pointregister.tcl,v 1.1 2004/01/15 15:09:08 xenios Exp xenios $	
+
+
+
+set argc [llength $argv]
+if { $argc <3 } {
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a script that computes either linear or linear+non-linear point-based registrations"
+
+    puts stdout "Syntax: $scriptname ref_surface trg_surface output_transformation \[transformmode=0\] \[ userpm =1 \] \[points=3000\] \[tstart=5.0\] \[ tend=2.0\] \[ smoothstart=5.0\] \[ smooth_end=1.0 \] \[ cps_start=30.0 \] \[ cps_end =15.0 \]  \[ prior_xform = none \] \[ prior_weights = none \] "
+    puts stdout "\t\ttransformmode: rigid=3, similarity=2, affine=1, nonlinear=0"
+    puts stdout "\t\tuserpm = 0,1 if 1 use RPM algorithm, if 0 use ICP"
+    puts stdout "\n"
+    exit 1
+}
+   
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+# --------------------------------------------------------------------------------------------------------
+proc DoRPM { surface1 surface2 output_xform xform_mode initialxform numpoints tstart tend smoothstart smoothend cpsstart cpsend priorxform priorxformweights  outputweights  } {
+
+    global transformmode
+    global userpm
+
+    puts stderr "Use RPM = $userpm\n"
+
+    if { [ string length $initialxform] == 0 } {
+	set initialxform 0
+    }
+
+    if { $xform_mode == "linear" } {
+	set rpmxform [ vtkpxLinearRPMRegistration  [ pxvtable::vnewobj ]]
+	$rpmxform DebugOn
+	
+	if { $transformmode == 3 } {
+	    $rpmxform SetTransformModeToRigid
+	} elseif { $transformmode == 2 } {
+	    $rpmxform SetTransformModeToSimilarity
+	} else {
+	    $rpmxform SetTransformModeToAffine
+	}
+	
+
+	$rpmxform SetAnnealRate 0.93
+	$rpmxform SetInitialTemperature $tstart
+	$rpmxform SetFinalTemperature   $tend
+
+	if { $userpm == 1 } {
+	    $rpmxform SetMatchModeToRPMFast
+	} else {
+	    $rpmxform SetMatchModeToICP
+	}
+	
+	$rpmxform SetUseLabels  1
+	$rpmxform SetUseWeightedLeastSquares 1
+	$rpmxform SetFastThreshold 3.0
+
+	if { $initialxform != 0 } {
+	    puts stdout "Using Initial Transformation [ $initialxform GetClassName ]"
+	    $rpmxform SetUseInitialTransform  1
+	    $rpmxform SetInitialTransform     $initialxform 
+	}
+    } else {
+	set rpmxform [ vtkpxBSplinePriorRPMRegistration  [ pxvtable::vnewobj ]]
+	$rpmxform SetAnnealRate 0.93
+	$rpmxform SetFastThreshold 3.0
+
+	$rpmxform SetInitialControlPointSpacing  $cpsstart
+	$rpmxform SetFinalControlPointSpacing   $cpsend
+
+	$rpmxform SetInitialSmoothnessFactor $smoothstart
+	$rpmxform SetFinalSmoothnessFactor $smoothend
+
+	$rpmxform SetInitialTemperature $tstart
+	$rpmxform SetFinalTemperature   $tend
+
+	if { $userpm == 1 } {
+	    $rpmxform SetMatchModeToRPMFast
+	} else {
+	    $rpmxform SetMatchModeToICP
+	}
+
+	$rpmxform SetUseLabels 1
+	$rpmxform SetUseWeightedLeastSquares 1
+	
+	if { $priorxform != 0 } {
+	    $rpmxform SetPriorTransform $priorxform
+	    if { $priorxformweights !=0 } {
+		$rpmxform SetPriorWeights $priorweights
+	    }
+	} elseif { $initialxform != 0 } {
+	    puts stdout "Using Initial Transformation [ $initialxform GetClassName ]"
+	    $rpmxform SetUseInitialTransform  1
+	    $rpmxform SetInitialTransform     $initialxform 
+	}
+	
+    }
+    $rpmxform DebugOn    
+    if { $numpoints < -1  } {
+	if { $xform_mode != "linear" } {
+	    $rpmxform SetPreferentialSampling 1
+	}
+	$rpmxform SetMaximumNumberOfLandmarks [ expr abs($numpoints) ]
+    } else {
+	$rpmxform SetMaximumNumberOfLandmarks $numpoints
+    }
+    $rpmxform DebugOff
+
+    $rpmxform EnableFeedbackOn
+    $rpmxform SetExtraDebug 1
+
+    $rpmxform SetSource $surface1
+    $rpmxform SetTarget $surface2
+
+    $rpmxform DebugOn
+    $rpmxform Run
+    
+    puts stdout "Copying a [ $output_xform GetClassName ] from [ [ $rpmxform GetCurrentTransformation ] GetClassName ]"
+    $output_xform DeepCopy [ $rpmxform GetCurrentTransformation ]
+
+    if { $xform_mode != "linear" && $outputweights !=0 } {
+	$outputweights DeepCopy [ $rpmxform GetFinalWeights ]
+    }
+	
+    $rpmxform Delete
+}
+# --------------------------------------------------------------------------------------------------------
+#   Main Program 
+# ----------------------------------------------------------------------------------------------------
+
+proc DoRPMALL { refsurfacename trnsurfacename output transformmode numpoints tstart tend smoothstart smoothend cpsstart cpsend priorxformname priorweightsname  } {
+    
+    puts stdout "\n----------------- Loading Reference Surface ---------------------------\n"
+    set ana [ vtkPolyDataReader [ pxvtable::vnewobj ]]
+    $ana SetFileName $refsurfacename; $ana Update
+    set sur_ref [ $ana GetOutput ]
+    puts stdout "Reference Surface Read from $refsurfacename points = [ $sur_ref GetNumberOfPoints ], bbox = [ $sur_ref GetBounds ]"
+    
+    set ana2 [ vtkPolyDataReader [ pxvtable::vnewobj ]]
+    $ana2 SetFileName $trnsurfacename; $ana2 Update
+    set sur_trn [ $ana2 GetOutput ]
+    puts stdout "Target Surface Read from $trnsurfacename points = [ $sur_trn GetNumberOfPoints ], bbox = [ $sur_trn GetBounds ]"
+    
+    set nfactor 1.0
+    set tfactor 1.0
+    if { $transformmode == 0 } {
+	set nfactor 0.5
+	set tfactor 3.0
+    }
+    set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+    		
+    set usepriorreg 0
+    if { $priorxformname != "none" } {
+	if { [ file extension $priorxformname ] == ".grd" } {
+	    set usepriorreg 1
+	}
+    }
+
+    set prior 0
+    if { $priorxformname != "none" } {
+	set prior  [ $ut LoadAbstractTransform $priorxformname ]
+    }
+
+    set xform [ vtkTransform [ pxvtable::vnewobj ]]
+    $xform Identity 
+      
+    if { $usepriorreg == 0 } {
+
+	set runlinear 1
+	
+	if { $prior !=0 && $prior !="" } {
+	    puts stdout "Prior=$prior"
+	    if { [ $prior IsA vtkTransform ] == 1 && $transformmode == 0 } {
+		$xform DeepCopy $prior
+		puts stdout "Copying initial transfor from $priorxformname"
+		set runlinear 0
+	    }
+	}
+
+	if { $runlinear == 1} {
+	    puts stdout "\n----------------- Running Linear  ---------------------------\n"
+	    DoRPM $sur_ref $sur_trn  $xform linear $prior [ expr round($nfactor*$numpoints) ] [ expr $tfactor*$tstart]  $tend $smoothstart $smoothend $cpsstart $cpsend 0 0 0 
+	    catch { $prior Delete }
+	}
+
+	if { $runlinear == 1 } {
+	    set fname "${output}.matr"
+	    
+	    set ok [ $ut SaveAbstractTransform $xform $fname ]
+	    if { $transformmode == 1 } {
+		puts stdout "Affine Transformation saved in $fname ($ok) [ file size $fname ]"
+	    } elseif { $transformmode == 2 } {
+		puts stdout "Similarity Transformation saved in $fname ($ok) [ file size $fname ]"
+	    } else {
+		puts stdout "Rigid Transformation saved in $fname ($ok) [ file size $fname ]"
+	    }
+	}
+
+	if { $transformmode == 0 } {
+	    puts stdout "\n----------------- Running Non-Linear  ---------------------------\n"
+	    set xform2 [ vtkpxComboTransform [ pxvtable::vnewobj ] ]
+	    set outputweights [ vtkFloatArray [ pxvtable::vnewobj ]]
+	    
+	    DoRPM $sur_ref $sur_trn  $xform2 nonlinear $xform $numpoints $tstart $tend $smoothstart $smoothend $cpsstart $cpsend 0 0 $outputweights 
+	    set fname "${output}.grd"
+	    set ok [ $xform2 Save $fname  ]
+	    puts stdout "Non Linear Transformation saved in $fname ($ok) [ file size $fname ]"
+	    
+	    $xform2 Delete
+	    $outputweights Delete
+	}
+	$xform Delete
+    } else {
+	
+	if { $priorweightsname !="none" } {
+	    set priorweights [ vtkFloatArray [ pxvtable::vnewobj]]
+	    set mot [ vtkpxLinearMotionCorrect  [ pxvtable::vnewobj ]]    
+	    set ok [ $mot LoadMotionParameters $priorweights $priorweightsname ]
+	    puts stdout "Prior Weights read from $priorweightsname (ok=$ok)\n"
+	    $mot Delete
+	} else {
+	    set priorweights 0
+	}
+
+	set xform2 [ vtkpxComboTransform [ pxvtable::vnewobj ] ]
+	set outputweights [ vtkFloatArray [ pxvtable::vnewobj ]]
+	
+	DoRPM $sur_ref $sur_trn  $xform2 nonlinear 0 $numpoints $tstart $tend $smoothstart $smoothend $cpsstart $cpsend $prior $priorweights $outputweights
+
+	set fname "${output}.grd"
+	set ok [ $xform2 Save $fname  ]
+
+	$xform2 Delete
+	$outputweights Delete
+    }
+	
+
+    puts stdout "\n----------------- Done  ---------------------------\n"
+
+    $ut Delete
+    $ana Delete
+    $ana2 Delete
+    return 1
+}
+
+# --------------------------------------------------------------------------------------------------------
+
+
+set argc [ llength $argv ]
+set refsur [ lindex $argv 0 ]
+set tarsur [ lindex $argv 1 ]
+set output [ file root [ lindex $argv 2 ] ]
+set prior_xform 0
+
+set transformmode 0
+if { $argc > 3 } {
+    if {  [ lindex $argv 3 ] == 1 } {
+	set transformmode 1 
+    } elseif { [ lindex $argv 3 ] == 2 } {
+	set transformmode 2
+    } elseif { [ lindex $argv 3 ] == 3 } {
+	set transformmode 3
+    }
+} 
+
+set userpm 1
+if { $argc > 4 } {
+    if {  [ lindex $argv 4 ] == 0 } {
+	set userpm 0
+    }
+} 
+
+
+if { $argc > 5 } {
+    set numpoints [ lindex $argv 5 ]
+} else {
+    set numpoints 3000
+}
+
+if { $argc > 6 } {
+    set tstart [ lindex $argv 6 ]
+} else {
+    set tstart 5
+}
+
+if { $argc > 7 } {
+    set tend [ lindex $argv 7 ]
+} else {
+    set tend 2
+}
+
+
+if { $argc > 8 } {
+    set smoothstart [ lindex $argv 8 ]
+} else {
+    set smoothstart 5.0
+}
+
+
+if { $argc > 9 } {
+    set smoothend [ lindex $argv 9 ]
+} else {
+    set smoothend 1.0
+}
+
+if { $argc > 10 } {
+    set cpsstart [ lindex $argv 10 ]
+} else {
+    set cpsstart 30
+}
+
+
+if { $argc > 11 } {
+    set cpsend [ lindex $argv 11 ]
+} else {
+    set cpsend 15
+}
+
+if { $argc > 12 } {
+    set priorxform [ lindex $argv 12 ]
+} else {
+    set priorxform "none"
+}
+
+if { $argc > 13 } {
+    set priorweights [ lindex $argv 13 ]
+} else {
+    set priorweights "none"
+}
+
+
+set comment "Beginning ref=$refsur -> tar=$tarsur output=$output transformmode=$transformmode userpm=$userpm points=$numpoints temp=$tstart : $tend smooth=$smoothstart : $smoothend cps=$cpsstart : $cpsend priorxform=$priorxform priorweights=$priorweights numargs=[ llength $argv ]"
+puts stdout $comment
+set comment "$comment\n\ncommandline = pxmat_pointregister" 
+for { set c 0 } { $c < $argc } { incr c } {
+    set comment "$comment [ lindex $argv $c ]"
+}
+
+set fout [ open ${output}.log w ]
+puts $fout $comment
+close $fout
+
+
+DoRPMALL $refsur $tarsur  $output  $transformmode $numpoints $tstart $tend $smoothstart $smoothend $cpsstart $cpsend $priorxform $priorweights"
+
+puts stderr "Done OK"
+
+exit 0
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_register.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_register.tcl
new file mode 100755
index 0000000..1e035f4
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_register.tcl
@@ -0,0 +1,377 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# --------------------------------------------------------------------------------------------------------
+# 	$Id: pxmat_register.tcl,v 1.1 2004/01/15 15:08:41 xenios Exp xenios $	
+set argc [llength $argv]
+if { $argc <3 } {
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a script that computes either linear or linear+non-linear intensity based registrations"
+
+    puts stdout "Syntax: $scriptname ref_image trg_image output_transformation \[transformmode=2\] \[resolution=1.5\] \[spacing=15\] \[iterations=15\] \[ step_size=1.0\] \[ smoothness=0.0\] \[ linearmode = 1 \] \[ autonormalize_intensities =1 \] \[ prior_xform = none \] \[ prior_weights = none \] \[minimum_spacing_ratio=4\]"
+    puts stdout "\t\ttransformmode: rigid=3 similarity=2, affine=1, nonlinear=0, linearmode = 3,2,1 if transformmode=0"
+    puts stdout "\n"
+    exit 0
+}
+   
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+set filenametype 0
+set linearmode   1
+set autonormalize 1
+# --------------------------------------------------------------------------------------------------------
+proc DoNMI { image1 orient1 image2 orient2 output_xform xform_mode initialxform { resolution 1.5 } { spacing 15.0 } { iterations 15 } { stepsize 1 } { smoothness 0 } } {
+
+    global transformmode
+    global linearmode
+    global autonormalize
+
+
+    if { $xform_mode == "linear" } {
+	set areg [ vtkpxLinearRegistration [ pxvtable::vnewobj ]]
+	$areg DebugOn
+
+	if { $linearmode == 3 } {
+	    $areg SetTransformModeToRigid
+	    puts stdout "Transform Mode = Rigid"
+	} elseif { $linearmode == 2 }  {
+	    $areg SetTransformModeToSimilarity
+	    puts stdout "Transform Mode = Similarity"
+	} else {
+	    $areg SetTransformModeToAffine
+	    puts stdout "Transform Mode = Affine"
+	}
+
+	$areg SetAutoNormalizeIntensities $autonormalize
+	$areg SetSimilarityMeasure 5
+	puts stderr "On To Setting Ref/Trg"
+	$areg SetReferenceImage $image1
+	$areg SetTransformImage $image2
+	$areg SetReferenceOrientation $orient1
+	$areg SetTransformOrientation $orient2
+	$areg SetResolution $resolution
+	$areg SetNumberOfLevels 3
+	$areg SetNumberOfSteps  1
+	$areg SetStepSize       $stepsize
+	$areg SetOptimizationMethodToConjugateGradient
+	$areg SetNumberOfIterations [ expr round(2 * $iterations) ]
+	$areg DebugOff
+	eval "$areg AddObserver ProgressEvent { set a   \[ $areg GetOutputStatus \]; if \{ \[ string length  \$a \] > 0  \} \{ puts -nonewline stdout \$a \} }"
+	$areg Run
+        puts stdout "DoNMI 1111111111111111111111111111111111111111111111111111111111111111111111"	
+	$output_xform DeepCopy  [ $areg GetTransformation ]
+        puts stdout "DoNMI 2222222222222222222222222222222222222222222222222222222222222222222222"
+	$areg Delete
+        puts stdout "DoNMI 3333333333333333333333333333333333333333333333333333333333333333333333"
+    } else {
+	set nreg [ vtkpxNonLinearRegistration [ pxvtable::vnewobj ]]
+
+	$nreg SetSimilarityMeasure 5
+	
+	if { $initialxform !=0 } { 
+	    $nreg SetInitialTransform $initialxform 
+	    puts stdout "Using Initial Transformation"
+	}
+	$nreg DebugOn
+	$nreg SetAutoNormalizeIntensities $autonormalize
+	$nreg SetReferenceImage $image1
+	$nreg SetTransformImage $image2 
+	$nreg SetNumberOfSteps  1
+	$nreg SetNumberOfLevels 3
+	$nreg SetStepSize       $stepsize 
+	$nreg SetLambda [ expr 0.01 * $smoothness ]
+	$nreg SetResolution     $resolution
+	$nreg SetControlPointSpacing $spacing
+	$nreg SetControlPointSpacingRate 2.0
+	$nreg SetOptimizationMethodToDefault
+	$nreg SetNumberOfIterations [ expr round($iterations) ]
+	$nreg DebugOff
+	eval "$nreg AddObserver ProgressEvent { puts stdout  \[ $nreg GetOutputStatus \] }"
+	
+	$nreg Run
+	$output_xform DeepCopy  [ $nreg GetTransformation ]
+	$nreg Delete
+    }
+
+}
+# --------------------------------------------------------------------------------------------------------
+# Do Prior NMI
+# --------------------------------------------------------------------------------------------------------
+
+proc DoPriorNMI { image1 image2 output_xform priorxform priorweights { resolution 1.5 } { spacing 15.0 } { iterations 15 } { stepsize 1 } { smoothness 0 } } {
+
+    global autonormalize
+
+    set nreg [ vtkpxNonLinearPriorRegistration [ pxvtable::vnewobj ]]
+
+    $nreg SetSimilarityMeasure 5
+    $nreg SetPriorTransform $priorxform
+    if { $priorweights !=0 } {
+	$nreg SetPriorWeights $priorweights
+    }
+
+    $nreg SetAutoNormalizeIntensities $autonormalize   
+    $nreg SetReferenceImage $image1
+    $nreg SetTransformImage $image2 
+    $nreg SetNumberOfSteps  1
+    $nreg SetNumberOfLevels 1
+    $nreg SetStepSize       $stepsize 
+    $nreg SetLambda [ expr 0.01 * $smoothness ]
+    $nreg SetResolution     $resolution
+    $nreg SetControlPointSpacing $spacing
+    $nreg SetControlPointSpacingRate 2.0
+    $nreg SetOptimizationMethodToDefault
+    $nreg SetNumberOfIterations $iterations
+
+    eval "$nreg AddObserver ProgressEvent { puts stdout  \[ $nreg GetOutputStatus \] }"
+    $nreg Run
+    $output_xform DeepCopy  [ $nreg GetTransformation ]
+    $nreg Delete
+}
+
+# --------------------------------------------------------------------------------------------------------
+#   Main Program 
+# ----------------------------------------------------------------------------------------------------
+
+proc DoNMIAll { refimagename trnimagename output transformmode resolution spacing iterations stepsize smoothness priorxformname priorweightsname minimum_spacing_ratio} {
+    
+    set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+    global linearmode
+
+    puts stdout "\n----------------- Loading Reference Image ---------------------------\n"
+    set ana [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+    $ana Load $refimagename
+    set img_ref [ $ana GetOutput ]
+    puts stdout "Reference Image Read from $refimagename dimensions = [ $img_ref GetDimensions ]"
+
+   #exception handling from here
+    scan [$img_ref  GetSpacing] "%f %f %f" sp(0) sp(1) sp(2)
+    set spacing_ratio_too_small 0
+    for { set i 0 } { $i < 3} { incr i} {
+	set spacing_ratio [ expr $spacing /$sp($i)] 
+	puts stderr "spacing_ratio = $spacing_ratio, spacing = $sp($i)"
+        if { $spacing_ratio < $minimum_spacing_ratio } {
+	    set spacing_ratio_too_small 1
+	}
+    }
+#    if { $spacing_ratio_too_small == 1 } {
+#	puts stderr "Control point spacing is too small. Control point spacing must be at least 
+#$minimum_spacing_ratio times as large as voxel spacing."
+#       return 0
+#    }
+   #exception handling to here
+
+    set ana2 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+    $ana2 Load $trnimagename
+    set img_trn [ $ana2 GetOutput ]
+    puts stdout "Target Image Read from $trnimagename dimensions = [ $img_trn GetDimensions ]"
+    
+
+    set orient1 [ $ana  GetOrientation ]
+    set orient2 [ $ana2 GetOrientation ]
+
+    if { $orient1 != $orient2  && $transformmode == 0 } {
+	puts stderr "Cannot Register Different Orientation $orient1 $orient2"
+    }
+    
+    if { $priorxformname == "none" } {
+
+	puts stdout "\n----------------- Running Linear  ---------------------------\n"
+	
+	set xform [ vtkTransform [ pxvtable::vnewobj ]]
+	$xform Identity 
+	DoNMI  $img_ref $orient1 $img_trn $orient2  $xform  linear 0 $resolution $spacing $iterations 1 0
+        puts stdout "DoNMIAll 22222222222" 	
+	if { $transformmode > 0 } {
+	    set fname "${output}.matr"
+	    set ok [ $ut SaveAbstractTransform $xform $fname ]
+	    if { $linearmode == 1 } {
+		puts stdout "Affine Transformation saved in $fname ($ok) [ file size $fname ]"
+	    } elseif { $linearmode == 2 } { 
+		puts stdout "Similarity Transformation saved in $fname ($ok) [ file size $fname ]"
+	    } else {
+		puts stdout "Rigid Transformation saved in $fname ($ok) [ file size $fname ]"
+	    }
+	} else  {
+	    puts stdout "\n----------------- Running Non-Linear  ---------------------------\n"
+	    set xform2 [ vtkpxComboTransform [ pxvtable::vnewobj ] ]
+	    DoNMI $img_ref $orient1 $img_trn $orient2 $xform2 nonlinear  $xform $resolution $spacing $iterations $stepsize $smoothness 
+	    set fname "${output}.grd"
+	    set ok [ $xform2 Save $fname  ]
+	    puts stdout "Non Linear Transformation saved in $fname ($ok) [ file size $fname ]"
+	    $xform2 Delete
+	}
+	$xform Delete
+    } else {
+	set prior [ vtkpxComboTransform [ pxvtable::vnewobj ] ]
+	set ok [ $prior Load $priorxformname ]
+	puts stdout "Prior Transform read from $priorxformname (ok=$ok)\n"
+
+	if { $priorweightsname !="none" } {
+	    set mot [ vtkpxLinearMotionCorrect  [ pxvtable::vnewobj ]]    
+	    set priorweights [ vtkFloatArray [ pxvtable::vnewobj]]
+	    set ok [ $mot LoadMotionParameters $priorweights $priorweightsname ]
+	    puts stdout "Prior Weights read from $priorweightsname (ok=$ok)\n"
+	    $mot Delete
+	} else {
+	    set priorweights 0
+	}
+
+	set xform2 [ vtkpxComboTransform [ pxvtable::vnewobj ] ]
+	DoPriorNMI $img_ref $img_trn $xform2 $prior $priorweights  $resolution $spacing $iterations $stepsize $smoothness 
+	set fname "${output}.grd"
+	set ok [ $xform2 Save $fname  ]
+	puts stdout "Non Linear Transformation (Prior) saved in $fname ($ok) [ file size $fname ]"
+	$xform2 Delete
+    }
+	
+
+    puts stdout "\n----------------- Done  ---------------------------\n"
+   
+    $ana Delete
+    $ana2 Delete
+    $ut Delete
+    return 1
+}
+
+# --------------------------------------------------------------------------------------------------------
+
+set argc [ llength $argv ]
+
+#for { set i 0 } { $i < $argc } { incr i } {
+#    puts stderr "\t\t $i / $argc \t\t [ lindex $argv $i ]"
+#}
+
+set refimg [ lindex $argv 0 ]
+set tarimg [ lindex $argv 1 ]
+set output [ file root [ lindex $argv 2 ] ]
+set prior_xform 0
+
+set transformmode 0
+if { $argc > 3 } {
+#    puts stderr "argv(3) = [ lindex $argv 3 ]"
+    if {  [ lindex $argv 3 ] == 1 } {
+	set transformmode 1 
+    } elseif { [ lindex $argv 3 ] == 2 } {
+	set transformmode 2
+    } elseif { [ lindex $argv 3 ] == 3 } {
+	set transformmode 3
+    }
+}
+#puts stderr "Transform Mode = $transformmode \n\n"
+
+if { $argc > 4 } {
+    set resolution [ lindex $argv 4 ]
+} else {
+    set resolution 1.5
+}
+
+if { $argc > 5 } {
+    set spacing [ lindex $argv 5 ]
+} else {
+    set spacing 15.0
+}
+
+if { $argc > 6 } {
+    set iterations [ lindex $argv 6 ]
+} else {
+    set iterations 15
+}
+
+
+if { $argc > 7 } {
+    set stepsize [ lindex $argv 7 ]
+} else {
+    set stepsize 1.0
+}
+
+
+if { $argc > 8 } {
+    set smoothness [ lindex $argv 8 ]
+} else {
+    set smoothness 0.0
+}
+
+if { $transformmode == 0 } {
+    if { $argc > 9 } {
+	set linearmode [ lindex $argv 9 ]
+    } else {
+	set linearmode 1
+    }
+} else {
+    set linearmode $transformmode
+}
+
+if { $argc > 10 } {
+    set autonormalize [ expr [ lindex $argv 10 ] > 0 ]
+}
+
+#puts stderr "Linear Mode = $linearmode argc=$argc\n\n"
+
+if { $argc > 11 } {
+    set priorxform [ lindex $argv 11 ]
+} else {
+    set priorxform "none"
+}
+
+if { $argc > 12 } {
+    set priorweights [ lindex $argv 12 ]
+} else {
+    set priorweights "none"
+}
+
+if { $argc > 13 } {
+    set minimum_spacing_ratio [ lindex $argv 13 ]
+} else {
+    set minimum_spacing_ratio 4
+}
+
+
+set comment "Beginning ref=$refimg -> tar=$tarimg output=$output transformmode=$transformmode (linearmode=$linearmode) res=$resolution spa=$spacing it=$iterations stepsize=$stepsize smoothness=$smoothness priorxform=$priorxform priorweights=$priorweights numargs=[ llength $argv ]"
+puts stdout $comment
+set comment "$comment\n\ncommandline = pxmat_register" 
+for { set c 0 } { $c < $argc } { incr c } {
+    set comment "$comment [ lindex $argv $c ]"
+}
+
+set fout [ open ${output}.log w ]
+puts $fout $comment
+close $fout
+
+
+DoNMIAll $refimg $tarimg  $output  $transformmode $resolution $spacing $iterations $stepsize $smoothness  $priorxform $priorweights $minimum_spacing_ratio
+
+exit 0
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_reorient_tensor.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_reorient_tensor.tcl
new file mode 100755
index 0000000..c7e948c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_reorient_tensor.tcl
@@ -0,0 +1,168 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+# 	$Id: pxmat_reorient_tensor.tcl,v 1.1 2004/01/15 15:07:53 xenios Exp xenios $	
+
+
+
+
+if { [ llength $argv ] < 5 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a script that reorients a tensor using one or more transformations"
+    puts stdout "Syntax: $scriptname reference_image target_image output_image interpolation_mode flip_mode xform1 \[ xform2 \] \[ xform3 \]\n"
+    puts stdout "interpolation_mode = 0,1,3 nearest neighbor,linear,cubic"
+    puts stdout "flip_mode = 0 (none) 1 (flip x) 2 (flip y) 3 (flip x+y) 4 (flip z) 5 (flip x+z) 6 (flip y+z) 7 (flip x+y+z)"
+    puts stdout "xform1 = Ref -> 3D, xform2 = 3D -> Conv , xform3 = Conv->Echo"
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+set reference     [ lindex $argv 0 ]
+set target        [ lindex $argv 1 ]
+set outname       [ lindex $argv 2 ]
+set intmode       [ lindex $argv 3 ]
+set flipmode      [ lindex $argv 4 ]
+set xform(1)        [ lindex $argv 5 ]
+set xform(2) ""
+set xform(3) ""
+if { [ llength $argv ] >= 7 } {
+    set xform(2)    [ lindex $argv 6 ] 
+    if { [ llength $argv ] >= 8 } {
+	set xform(3)    [ lindex $argv 7 ] 
+    }
+}
+
+if { $intmode <= 0 } { 
+    set intmode 0
+} elseif { $intmode <2 } {
+    set intmode 1
+} else {
+    set intmode 3
+}
+
+if { $flipmode <=0 || $flipmode >7 } {
+    set flipmode 0
+}
+
+
+set ana1 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana1 Load $reference
+
+set ana2 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana2 Load $target
+
+puts stdout "Loaded image [ $ana1 GetFilePrefix ] dim [ [ $ana1 GetOutput ] GetDimensions ]"
+puts stdout "Loaded image [ $ana2 GetFilePrefix ] dim [ [ $ana2 GetOutput ] GetDimensions ]"
+
+set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+
+set counttr 0
+
+for { set i 1 } { $i <= 3 } { incr i } {
+    if { $xform($i) != "" } {
+	set tr($i) [ $ut LoadAbstractTransform $xform($i) ]
+	incr counttr
+	puts stdout "Loading transformation $i from $xform($i)"
+    } else {
+	set tr($i) [ vtkIdentityTransform [ pxvtable::vnewobj ]]
+	puts stdout "Setting transformation $i to identity"
+    }
+}
+
+if { $counttr>1 } {
+    set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+    $trans Identity
+    $trans PostMultiply
+    $trans Concatenate $tr(1)
+    $trans Concatenate $tr(2)
+    $trans Concatenate $tr(3)
+} else {
+    set trans $tr(1)
+    puts stdout "Only using One Transformation"
+}
+
+puts stdout "Reslicing Image First"
+
+set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+$resl SetInput [ $ana2 GetOutput ]
+$resl SetInformationInput [ $ana1 GetOutput ]
+$resl SetInterpolationMode $intmode
+$resl SetBackgroundLevel 0.0
+$resl OptimizationOff
+$resl SetResliceTransform $trans
+$resl Update
+
+puts stdout "Reorienting Tensor or Vector"
+
+set reor [  vtkpxImageReorientTensorOrVector [ pxvtable::vnewobj ]]
+$reor SetInput [ $resl GetOutput ]
+$reor SetTransformation $trans
+$reor DebugOn
+if { $flipmode == 1 || $flipmode ==3 || $flipmode == 5 || $flipmode == 7 } {
+    $reor FlipXOn
+}
+if { $flipmode == 2 || $flipmode ==3 || $flipmode == 6 || $flipmode == 7 } {
+    $reor FlipYOn
+}
+if { $flipmode >=4 } {
+    $reor FlipZOn
+}
+$reor Use7PointsOn
+$reor Update
+
+puts stdout "Done Reorienting Tensor or Vector"
+
+set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+$anaw SetInput [ $reor GetOutput ]
+$anaw SetImageHeader [ $ana1 GetImageHeader ]
+$anaw Save $outname
+
+puts stdout "Saved in [ $anaw GetFileName ] dimensions [ [ $resl GetOutput ] GetDimensions ]"
+ 
+$anaw Delete
+$resl Delete
+$ana1 Delete
+$ana2 Delete
+$tr(1) Delete
+$tr(2) Delete
+$tr(3) Delete
+$ut Delete
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_reorientimage.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_reorientimage.tcl
new file mode 100755
index 0000000..0ac22c8
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_reorientimage.tcl
@@ -0,0 +1,105 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+# 	$Id: pxmat_reorientimage.tcl,v 1.1 2004/01/15 15:08:25 xenios Exp xenios $	
+
+
+
+
+
+if { [ llength $argv ] < 3 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname  is a script that reorients an image to a given orientation"
+    puts stdout "Syntax : $scriptname input_image  output_image output_orientation"
+    puts stdout "\t\t output_orientation = 0 axial 1 coronal 2 sagittal"
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+set orientlist [ list "axial" "coronal" "sagittal" "other" ]
+
+set reference     [ lindex $argv 0 ]
+set outname       [ lindex $argv 1 ]
+set output_orientation  [ lindex $argv 2 ]
+
+if { $output_orientation < 1 } {
+    set output_orientation 0 
+} elseif { $output_orientation >= 2 } {
+    set output_orientation 2 
+} else { 
+    set output_orientation 1
+}
+
+set ana1 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ] ]
+$ana1 Load $reference
+
+set inori [ $ana1 GetOrientation ]
+if { $inori <= 0 } { 
+    set inori 0 
+} elseif { $inori >= 2 } {
+    set inori 2
+} else {
+    set inori 1
+}
+
+puts stdout "Loaded image [ [ $ana1 GetImageHeader ] GetHeaderDescription 0 ]"
+
+set img [ vtkImageData [ pxvtable::vnewobj ]]
+
+set ut [ vtkpxUtil [ pxvtable::vnewobj ]]
+$ut ReOrientImage $img [ $ana1 GetOutput ] [ $ana1 GetOrientation ] $output_orientation
+
+set head [ $ana1 GetImageHeader ]
+$head SetOrientation $output_orientation
+
+
+set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+$anaw SetInput $img
+$anaw SetImageHeader $head
+$anaw Save $outname
+
+set head [ $anaw GetImageHeader ]
+
+puts stdout "\nOutput saved  [ $head GetHeaderDescription 0 ]"
+ 
+$anaw Delete
+$ana1 Delete
+$ut Delete
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_resampleimage.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_resampleimage.tcl
new file mode 100755
index 0000000..7f9dd96
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_resampleimage.tcl
@@ -0,0 +1,117 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+# 	$Id: pxmat_resampleimage.tcl,v 1.1 2004/01/15 15:08:09 xenios Exp xenios $	
+
+
+
+
+if { [ llength $argv ] < 4 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stderr "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+
+    puts stdout "$scriptname is a script that resamples an image to a specific resolution"
+    puts stdout "Syntax: $scriptname input_image  output_image blur_mode  voxelsize1 \[ voxelsize2 \] \[ voxelsize3 \]"
+    puts stdout "\t\tblurmode = 0 or 1 to blur with appropriate FHWM filter"
+    puts stdout "\t\tvoxelsize1 = voxel size x, voxelsize2=voxel size y, voxelsize3=voxel size z"
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+set reference     [ lindex $argv 0 ]
+set outname       [ lindex $argv 1 ]
+set blurmode       [ lindex $argv 2 ]
+set spacing(0)        [ lindex $argv 3 ]
+set spacing(1) $spacing(0)
+set spacing(2) $spacing(0)
+if { [ llength $argv ] >= 5 } {
+    set spacing(1)    [ lindex $argv 4 ] 
+    if { [ llength $argv ] >= 6 } {
+	set spacing(2)    [ lindex $argv 5 ] 
+    }
+}
+
+if { $blurmode != 0 } { 
+    set blurmode 1
+} 
+
+set ana1 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ] ]
+$ana1 Load $reference
+
+puts stdout "Loaded image [ [ $ana1 GetImageHeader ] GetHeaderDescription 0 ]"
+
+
+set smooth  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+    
+set resl [ vtkbisImageResample [ pxvtable::vnewobj ]]
+for { set i 0 } { $i <=2 } { incr i } {
+    $resl SetAxisOutputSpacing $i $spacing($i)
+}
+
+if { $blurmode == 1 } {
+    set spa   [ [ $ana1 GetOutput ] GetSpacing ]
+    for { set i 0 } { $i <=2 } { incr i } {
+	set sigma($i) [ expr $spacing($i) *0.4247 / [ lindex $spa $i ]]
+    }
+    $smooth SetStandardDeviations $sigma(0) $sigma(1) $sigma(2)
+    $smooth SetRadiusFactors 1.5 1.5 1.5
+    $smooth SetInput [ $ana1 GetOutput ]
+    $smooth Update
+    $resl SetInput [ $smooth GetOutput ]
+} else {
+    $resl SetInput [ $ana1 GetOutput ]
+}
+
+$resl InterpolateOn
+$resl SetDimensionality 3
+$resl Update
+
+set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+$anaw SetInput [ $resl GetOutput ]
+$anaw SetImageHeader [ $ana1 GetImageHeader ]
+$anaw Save $outname
+
+puts stdout "Saved in [ [  $anaw GetImageHeader ] GetHeaderDescription 0 ]"
+ 
+$anaw Delete
+$resl Delete
+$ana1 Delete
+$smooth Delete
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_reslicect.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_reslicect.tcl
new file mode 100755
index 0000000..5ebdece
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_reslicect.tcl
@@ -0,0 +1,108 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+# 	$Id: pxmat_reslicect.tcl,v 1.1 2004/01/15 15:07:53 xenios Exp xenios $	
+
+if { [ llength $argv ] < 3 } { 
+    puts stdout "pxmat_reslicect is a script that reslices an image (typically ct) to have proper uniformly thick slices"
+    puts stdout "\npxmat_reslicect.tcl reference_image zlevels spacing\n"
+    puts stdout "\nNote: zlevels is the name of a text file that contains the z-coordinates of each slice one number per line"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+set inputname       [ lindex $argv 0 ]
+set outname         "[ file root $inputname  ]_fixed"
+set zlevels         [ lindex $argv 1 ]
+set spacing         [ lindex $argv 2 ]
+
+set ana1 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana1 Load $inputname
+
+set d [ lindex [ [ $ana1 GetOutput ] GetDimensions ] 2 ]
+set zlev [ vtkFloatArray [ pxvtable::vnewobj ]]
+$zlev SetNumberOfTuples $d
+
+set fileid [open $zlevels r]
+
+set zlist ""
+
+for { set i 0 } { $i < $d } { incr i } {
+    gets $fileid line
+    lappend zlist $line
+}
+close $fileid
+
+set sortlist [ lsort -real $zlist ]
+
+puts stderr "Sorting from ( $zlist) to ($sortlist)"
+
+set nt [ llength $sortlist ]
+
+for { set i 0 } { $i < $nt } { incr i } {
+    
+    set line [ lindex $sortlist $i ]
+    if { $i == 0 } {
+	set offset $line
+    }
+    $zlev SetComponent $i 0 [ expr ($line-$offset) ]
+    puts stdout "Z-coordinate for slice $i = [ $zlev GetComponent $i 0 ]  ($line)"
+}
+
+
+set recon [ vtkpxImageCorrectNonUniformZ [ pxvtable::vnewobj ]]
+$recon SetInput [ $ana1 GetOutput ]
+$recon SetSpacing $spacing
+$recon SetZLevels $zlev
+$recon Update
+
+set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+$anaw SetInput [ $recon GetOutput ]
+$anaw SetImageHeader [ $ana1 GetImageHeader ]
+$anaw Save $outname
+
+puts stdout "Saved in [ $anaw GetFileName ] dimensions [ [ $recon GetOutput ] GetDimensions ]"
+ 
+$anaw Delete
+$recon Delete
+$ana1 Delete
+$zlev Delete
+
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_resliceimage.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_resliceimage.tcl
new file mode 100755
index 0000000..6a61fef
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_resliceimage.tcl
@@ -0,0 +1,145 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+# 	$Id: pxmat_resliceimage.tcl,v 1.1 2004/01/15 15:07:53 xenios Exp xenios $	
+
+
+
+
+if { [ llength $argv ] < 5 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a script that reslices an image using one or more transformations"
+    puts stdout "Syntax: $scriptname reference_image target_image output_image interpolation_mode xform1 \[ xform2 \] \[ xform3 \]\n"
+    puts stdout "interpolation_mode = 0,1,3 nearest neighbor,linear,cubic"
+    puts stdout "xform1 = Ref -> 3D, xform2 = 3D -> Conv , xform3 = Conv->Echo"
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+set reference     [ lindex $argv 0 ]
+set target        [ lindex $argv 1 ]
+set outname       [ lindex $argv 2 ]
+set intmode       [ lindex $argv 3 ]
+set xform(1)        [ lindex $argv 4 ]
+set xform(2) ""
+set xform(3) ""
+if { [ llength $argv ] >= 6 } {
+    set xform(2)    [ lindex $argv 5 ] 
+    if { [ llength $argv ] >= 7 } {
+	set xform(3)    [ lindex $argv 6 ] 
+    }
+}
+
+if { $intmode <= 0 } { 
+    set intmode 0
+} elseif { $intmode <2 } {
+    set intmode 1
+} else {
+    set intmode 3
+}
+
+
+set ana1 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana1 Load $reference
+
+set ana2 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana2 Load $target
+
+puts stdout "Loaded image [ $ana1 GetFilePrefix ] dim [ [ $ana1 GetOutput ] GetDimensions ]"
+puts stdout "Loaded image [ $ana2 GetFilePrefix ] dim [ [ $ana2 GetOutput ] GetDimensions ]"
+
+set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+
+set counttr 0
+
+for { set i 1 } { $i <= 3 } { incr i } {
+    if { $xform($i) != "" } {
+	set tr($i) [ $ut LoadAbstractTransform $xform($i) ]
+	incr counttr
+	puts stdout "Loading transformation $i from $xform($i)"
+    } else {
+	set tr($i) [ vtkIdentityTransform [ pxvtable::vnewobj ]]
+	puts stdout "Setting transformation $i to identity"
+    }
+}
+
+if { $counttr>1 } {
+    set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+    $trans Identity
+    $trans PostMultiply
+    $trans Concatenate $tr(1)
+    $trans Concatenate $tr(2)
+    $trans Concatenate $tr(3)
+} else {
+    set trans $tr(1)
+    puts stdout "Only using One Transformation"
+}
+
+set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+$resl SetInput [ $ana2 GetOutput ]
+$resl SetInformationInput [ $ana1 GetOutput ]
+$resl SetInterpolationMode $intmode
+$resl SetBackgroundLevel 0.0
+$resl OptimizationOff
+$resl SetResliceTransform $trans
+$resl Update
+
+set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+$anaw SetInput [ $resl GetOutput ]
+$anaw SetImageHeader [ $ana1 GetImageHeader ]
+
+# Test this  -- extensions addition
+# ---------------------------------
+[ $anaw  GetImageHeader ] CopyExtensionsOnly [ $ana2 GetImageHeader ]
+# -----------------------------------
+$anaw Save $outname
+
+puts stdout "Saved in [ $anaw GetFileName ] dimensions [ [ $resl GetOutput ] GetDimensions ]"
+ 
+$anaw Delete
+$resl Delete
+$ana1 Delete
+$ana2 Delete
+$tr(1) Delete
+$tr(2) Delete
+$tr(3) Delete
+$ut Delete
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_segment.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_segment.tcl
new file mode 100755
index 0000000..8d2226e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_segment.tcl
@@ -0,0 +1,173 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxflipslices.tcl,v 1.1 2004/01/15 15:11:59 xenios Exp xenios $	
+
+set num $argc 
+
+if { $num < 2 } {
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "Syntax: $scriptname input numclasses \[ smoothness = 1.0 \] \[ maxsigmaratio = 0.05 \] \[ mrfiterations = 20 \] \[ outputname = \"\" \] "
+    puts stdout "\t\tNumber of classes = number of tissue labels (background is a tissue label so add this)"
+    puts stdout "\t\tSmoothness = spatial smoothness, is set to zero -- a faster algorithm is used"
+    puts stdout "\t\tMaxSigmaRatio  = this constrains the ratio of the max standard deviation to the min standard deviation"
+    puts stdout "\t\tIf Output Name is blank defaults are either input_quicksegm (smoothness=0.0) or input_segm "
+    puts stdout "\n"
+    exit 0
+}
+
+# ---------------------------------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+
+set name [ lindex $argv 0 ]
+set numclasses [ ::pxappscommon::RestrictRange [ lindex $argv 1 ] 2 10 ]
+
+set smoothness 1.0
+if { [ llength $argv ] > 2 } {
+    set smoothness [ ::pxappscommon::RestrictRange [ lindex $argv 2 ] 0.0 10.0 ]
+}
+
+set sigmaratio 0.05
+if { [ llength $argv ] > 3 } {
+    set sigmaratio [ ::pxappscommon::RestrictRange [ lindex $argv 3 ] 0.0 1.0 ]
+}
+
+set mrfiterations 20
+if { [ llength $argv ] > 4 } {
+    set mrfiterations [ ::pxappscommon::RestrictIntRange [ lindex $argv 4 ] 2 40 ]
+}
+
+set outputname ""
+if { [ llength $argv ] > 4 } {
+    set outputname [ lindex $argv 5 ]
+}
+
+
+# ---------------------------------------------------------------------------------------------------------
+
+proc HistogramSegmentation { img numcl sigmaratio } {
+
+    set segm [ vtkpxHistogramSegmentation [ pxvtable::vnewobj ]]
+    $segm SetInput $img
+    $segm SetNumberOfClasses $numcl
+    $segm SetIterations 50
+    $segm SetNumberOfBins 256
+    $segm SetConvergence 0.05
+    $segm SetSigma 0.05
+    $segm GenerateLabelsOn
+    $segm SetOutlierDetection 0
+    $segm SetPreprocessingMode 0
+    $segm SetDistributionModel 0
+    $segm SetOutlierProbability 0
+    $segm SetMaxSigmaRatio     $sigmaratio
+    $segm Update
+
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+    $img ShallowCopy [ $segm GetOutput ]
+    $segm Delete
+    return $img
+}
+
+# ------------------------------------------------------------------------------------
+
+proc MRFSegmentation { img numcl sigmaratio smoothness mrfiterations } {
+
+    set segm [ vtkpxMRFSegmentation [ pxvtable::vnewobj ]]
+    $segm SetInput $img
+    $segm SetNumberOfClasses $numcl
+    $segm SetIterations 50
+    $segm SetNumberOfBins 256
+    $segm SetConvergence 0.05
+    $segm SetSigma 0.05
+    $segm GenerateLabelsOn
+    $segm SetOutlierDetection 0
+    $segm SetPreprocessingMode 0
+    $segm SetDistributionModel 0
+    $segm SetOutlierProbability 0
+    $segm SetMaxSigmaRatio     $sigmaratio
+    $segm SetComputeBiasField 0
+    $segm SetMRFIterations $mrfiterations
+    $segm SetSmoothness $smoothness
+    $segm Update
+
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+    $img ShallowCopy [ $segm GetOutput ]
+    $segm Delete
+    return $img
+}
+
+
+
+
+
+set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+$ana Load $name
+set or [ $ana GetOrientation ]
+puts stdout "\nRead $name [ [ $ana GetOutput ] GetDimensions ] ori=$or "
+
+set outimage 0
+
+set fname $outputname
+
+if { $smoothness == 0.0 } {
+    set outimage [ HistogramSegmentation [ $ana GetOutput ]  $numclasses $sigmaratio ]
+    if { $fname == "" } {
+	set fname [ ::pxappscommon::GenOutputName $name quicksegm ]
+    }
+} else {
+    set outimage [  MRFSegmentation [ $ana GetOutput ]  $numclasses $sigmaratio $smoothness $mrfiterations ]
+    if { $fname == "" } {
+	set fname [ ::pxappscommon::GenOutputName $name segm ]
+    }
+}
+
+
+set ana2 [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+$ana2 SetInput $outimage
+$ana2 SetImageHeader [ $ana GetImageHeader ]
+
+$ana2 Save $fname
+
+puts stderr "Segmentation saved to $fname"
+
+$ana2 Delete
+$ana Delete
+$outimage Delete
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_smoothimage.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_smoothimage.tcl
new file mode 100755
index 0000000..d8611f1
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_smoothimage.tcl
@@ -0,0 +1,98 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+# 	$Id: pxmat_smoothimage.tcl,v 1.2 2004/01/15 15:04:47 xenios Exp xenios $	
+
+
+
+if { [ llength $argv ] < 2 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a script that smooths an image using a specific gaussian smoothing kernel"
+    puts stdout "Syntax: pxmat_smoothimage.tcl kernel_size  input_image1 input_image2 ..... "
+    puts stdout "\t\tsmoothing kernel_size in mm represents FWHM filter size"
+    puts stdout "\n"
+    exit 0
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+set numc [ llength $argv ]
+set blursigma       [ lindex $argv 0 ]
+
+
+for { set i 1 } { $i < $numc } { incr i } {
+
+    set ana1 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ] ]
+
+
+    set reference [ lindex $argv $i ]
+    $ana1 Load $reference
+
+    set spa [ [ $ana1 GetOutput ] GetSpacing ]
+    puts stdout "\nLoaded image $i [ [ $ana1 GetImageHeader ] GetHeaderDescription 0 ]"
+
+    for { set j 0 } { $j <=2 } { incr j } {
+	set sigma($j) [ expr $blursigma * 0.4247 / [ lindex $spa $j ]]
+    }
+    puts stdout "\n\tSmoothing kernel size  [ format "%.2fx%.2fx%.2f voxels from input %.2f mm" $sigma(0) $sigma(1) $sigma(2) $blursigma ]"
+
+    set header [ $ana1 GetImageHeader ]
+
+    set smooth  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+    $smooth SetStandardDeviations $sigma(0) $sigma(1) $sigma(2)
+    $smooth SetRadiusFactors 1.5 1.5 1.5
+    $smooth SetInput [ $ana1 GetOutput ]
+    $smooth Update
+
+    $header AddComment [ format "BIS::pxmat_smoothimage.tcl blursigma=%.2f in voxels (%.2f,%.2f,%.2f)" $blursigma $sigma(0) $sigma(1) $sigma(2) $blursigma ] 0
+
+    set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ] ]
+    $anaw SetImageHeader $header
+    $anaw SetInput [ $smooth GetOutput ]
+    set outfname [ ::pxappscommon::GenOutputName $reference sm${blursigma} ]
+    $anaw Save $outfname
+    
+    puts stdout "\nSmoothed image saved  [ [ $anaw GetImageHeader ] GetHeaderDescription 0 ]\n"
+    exit
+
+    $smooth Delete
+    $anaw Delete
+    $ana1 Delete
+
+}
+
+exit 0
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_split4dimage.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_split4dimage.tcl
new file mode 100755
index 0000000..894db79
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_split4dimage.tcl
@@ -0,0 +1,114 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+if { [ llength $argv ] < 1 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+
+    puts stdout "$scriptname is a script that extracts all 3D volumes from a  4D image"
+    puts stdout "Syntax: $scriptname image \[ begin =1 \] \[ end = maximum number of frames \]"
+    puts stdout "\t\t output = image_001.hdr .. image_002.hdr etc."
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+# set outname  [ ::pxappscommon::GenOutputName [ lindex $argv 0 ] "" ] 
+# puts "outname==$outname"
+# set outname [ file root $outname ]
+# puts "outnameroot==$outname"
+# set extension .nii.gz
+
+# exit
+
+set ana [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$ana Load [ lindex $argv 0 ]
+
+set img [ $ana GetOutput ]
+set nf  [ $img GetNumberOfScalarComponents ]
+set orient [ $ana GetOrientation ]
+
+set beginframe 1
+set endframe   $nf
+
+if { [ llength $argv ] >1 } {
+    set beginframe [ lindex $argv 1 ]
+    if { $beginframe < 1 } { 
+	set beginframe 1 
+    } elseif { $beginframe > $nf } {
+	set beginframe $nf
+    }
+}       
+
+if { [ llength $argv ] >2 } {
+    set endframe [ lindex $argv 2 ]
+    if { $endframe < $beginframe } { 
+	set endframe $beginframe 
+    } elseif { $endframe > $nf } {
+	set endframe $nf
+    }
+}       
+
+puts stdout "\nOriginal Image Read [ [ $ana GetImageHeader ] GetHeaderDescription 0 ]\n\t frames=$nf, extracting $beginframe:$endframe\n"
+
+set w [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+set extr [ vtkImageExtractComponents [ pxvtable::vnewobj ]]
+$extr SetInput $img
+
+set bg [ expr $beginframe -1 ]
+
+for { set i $bg } { $i < $endframe } { incr i } {
+    set j [ expr $i +1 ]
+    $extr SetComponents $i
+    $extr Modified
+    $extr Update
+
+    $w SetInput [ $extr GetOutput ]
+    $w SetImageHeader [ $ana GetImageHeader ]
+    $w Modified
+
+    set numout [ format "%03d" [ expr $i +1 ] ]
+    set fname  [ ::pxappscommon::GenOutputName [ lindex $argv 0 ] $numout  ]
+    $w Save $fname
+    puts stdout "\t Frame [ expr $i+1 ] saved in $fname [ [ $w GetImageHeader ] GetHeaderDescription -1 ]\n"
+}
+
+$w Delete
+$extr Delete
+$ana Delete
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_surfaceinfo.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_surfaceinfo.tcl
new file mode 100755
index 0000000..133f287
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_surfaceinfo.tcl
@@ -0,0 +1,107 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxmat_surfaceinfo.tcl,v 1.2 2004/01/15 15:07:37 xenios Exp xenios $	
+
+
+
+
+if { [ llength $argv ] < 1 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a script that prints information about .vtk surface files"
+    puts stdout "Syntax: $scriptname \[ surface1 \] \[ surface2 \] ..."
+    puts stdout "\n"
+    exit
+}
+
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+set num [  llength $argv ]
+
+set ana [ vtkPolyDataReader [ pxvtable::vnewobj ]]
+
+for { set i 0 } { $i < $num } { incr i } {
+    $ana SetFileName [ lindex $argv $i ]
+    $ana Modified
+    $ana Update
+
+    set sur [ $ana GetOutput ]
+
+    set np [ $sur GetNumberOfPoints ]
+    set nc [ $sur GetNumberOfCells  ]
+    set bd [ $sur GetBounds ]
+
+    set scalardata "no point scalars"
+    set celldata   "no cell  scalars"
+    set testscal 0
+
+    catch {
+	set scal [ [  $sur GetPointData ] GetScalars ]
+	set ns [ $scal GetNumberOfTuples ]
+	set nc [ $scal GetNumberOfComponents ]
+	set range [ $scal GetRange ]
+	set scalardata  "$ns point-scalars ($nc components) range=[lindex $range 0 ]:[lindex $range 1 ]"
+	set testscal 1
+    }
+
+    catch {
+	set scal [ [  $sur GetCellData ] GetScalars ]
+	set ns [ $scal GetNumberOfTuples ]
+	set nc [ $scal GetNumberOfComponents ]
+	set range [ $scal GetRange ]
+	set celldata  "$ns cell-scalars ($nc components) range=[lindex $range 0 ]:[lindex $range 1 ]"
+	set testscal 0
+    }
+
+    puts stdout "[ lindex $argv $i ] : $np points $nc cells (bounds=$bd) ($scalardata,$celldata)"
+
+    set histline ""
+    if { $testscal > 0 } {
+	set thrFilter [ vtkThresholdPoints [ pxvtable::vnewobj ]]
+	for { set j [ lindex $range 0 ] } { $j <= [ lindex $range 1 ]} { incr j } {
+	    $thrFilter SetInput $sur
+	    $thrFilter ThresholdBetween [ expr $j-0.1 ] [ expr $j+0.1 ]
+	    $thrFilter Update
+	    set histline "$histline \t $j \t [ [ $thrFilter GetOutput ] GetNumberOfPoints ]\n"
+	}
+	$thrFilter Delete 
+	puts stdout $histline
+    }
+}
+
+$ana Delete
+exit 0
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmat_thresholdimage.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmat_thresholdimage.tcl
new file mode 100755
index 0000000..86f8787
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmat_thresholdimage.tcl
@@ -0,0 +1,94 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+# 	$Id: pxmat_thresholdimage.tcl,v 1.1 2004/01/15 15:07:18 xenios Exp xenios $	
+
+
+
+
+
+if { [ llength $argv ] < 2 } { 
+    set scriptname [ file tail $argv0 ]
+    puts stdout "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stdout "$scriptname is a script that thresholds an image to generate a binary output using a specific threshold"
+    puts stdout "Syntax: $scriptname threshold  input_image1 input_image2 ..... "
+    puts stdout "\t\t Output: 100=above threshold, 0=below"
+    puts stdout "\t\t Output filenames are generated from input filenames with the addition of \"_binary\" "
+    puts stdout "\n"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+set numc [ llength $argv ]
+set value       [ lindex $argv 0 ]
+
+
+puts stdout "numc = $numc value=$value"
+
+for { set i 1 } { $i < $numc } { incr i } {
+
+    set ana1 [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ] ]
+    set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ] ]
+
+    set reference [ lindex $argv $i ]
+    $ana1 Load $reference
+    set spa   [ [ $ana1 GetOutput ] GetSpacing ]
+
+    set range [ [ [ [ $ana1 GetOutput ] GetPointData ] GetScalars ] GetRange ]
+
+    puts stdout "Loaded image $i [ $ana1 GetFilePrefix ] dim [ [ $ana1 GetOutput ] GetDimensions ]  [ format "%.2fx%.2fx%.2f mm" [ lindex $spa 0 ] [ lindex $spa 1 ] [ lindex $spa 2  ]] range = $range"
+
+    set threshold  [ vtkImageThreshold [ pxvtable::vnewobj ]  ]
+    $threshold SetInput [ $ana1 GetOutput ]
+    $threshold SetInValue  100.0
+    $threshold SetOutValue   0.0
+    $threshold ReplaceInOn
+    $threshold ReplaceOutOn
+    $threshold ThresholdBetween $value [ expr 0.001 + [ lindex $range 1 ] ]
+    $threshold SetOutputScalarTypeToShort
+    $threshold Update
+
+    $anaw SetInput [ $threshold GetOutput ]
+    $anaw SetImageHeader [ $ana1 GetImageHeader ]
+    
+    set outfname [ ::pxappscommon::GenOutputName $reference "binary" ]
+    $anaw Save $outfname
+    puts stdout "\t Thresholded image saved in [ $anaw GetFileName ] dimensions [ [ $threshold GetOutput ] GetDimensions ]\n"
+    $threshold Delete
+ 
+    $anaw Delete
+    $ana1 Delete
+}
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmultijacobian.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmultijacobian.tcl
new file mode 100755
index 0000000..b34b3e5
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmultijacobian.tcl
@@ -0,0 +1,258 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+set transformlist ""
+set refimg  ""
+set resolution -1.0
+set blursize 0.0
+set outputstem "jac"
+set rawjacobians 0
+set threshold 0.01
+set computeaverage 0
+
+set argc [llength $argv]
+if { $argc <2 } {
+    set scriptname [ file tail $argv0 ]
+    puts stderr "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stderr "$scriptname is a script that computes either the determinant of the jacobian or the full tensor for a set of transformations"
+    puts stderr "Syntax: $scriptname setup_file output_directory \[ go\]"
+    puts stderr " if the word go is missing the program simply tests for the presence of all the images/transformations"
+    puts stderr "\n type $scriptname sample > sample.setup "
+    puts stderr " \t to generate a sample setup file\n"
+
+    if { [ lindex $argv 0 ] != "sample" } {
+	exit
+    }
+
+    puts stdout "\#Example Setup File\n\# all lines beginning with \# are ignored \n\#"
+    puts stdout "\#\n\#\n\# List all subjects here\n\#"
+    puts stdout "set transformlist \{"
+    puts stdout "   /usr/home/schultz/brain_reg/brains/1001/sag.cihte.grd"
+    puts stdout "   /usr/home/schultz/brain_reg/brains/1002/sag.cihte.lw.grd"
+    puts stdout "\}\n\#"
+    puts stdout "\#\n\#\n\# Put reference brain here\n\#"
+    puts stdout "set refimg  /home/papad/normalized/1115_normalized.hdr\n\#"
+    puts stdout "\#\n\#\n\# Put output stem and resolution here\n\#"
+    puts stdout "set outputstem jac"
+    puts stdout "set resolution -1.0\n"
+    puts stdout "set blursize 0\n"
+    puts stdout "\# Set this to 1 to get the full tensor as opposed to just the determinant"
+    puts stdout "set rawjacobians 0"
+    puts stdout "\# Set this to 0.05 to eliminate computation of jacobian in low intensity regions"
+    puts stdout "set threshold   0.0"
+    puts stdout "\# Set this to 1 to compute the mean and standard deviation of the output"
+    puts stdout "set computeaverage 0"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+    
+source [ lindex $argv 0 ]
+set outputdirectory [ lindex $argv 1 ]
+set inputfile [ file tail [ file root [ lindex $argv 0 ]]]
+
+# --------------------------------------------------------------------------------------------------------
+
+proc TestImages {  } {
+
+    global refimg
+    global transformlist
+    global singlereference
+
+    puts stderr "Testing for existence of images"
+
+    
+    for { set i 0 } { $i < [ llength $transformlist ] } { incr i } {
+	
+	set a [ lindex $transformlist $i ]
+	set index [ format "%3d" [ expr $i +1 ] ]
+	set ok1 [ file exists $a ] ;   set sz1 -1 ; catch { set sz1 [ file size $a ] }
+	
+	if { $ok1 > 0 } {
+	    puts stderr "\t$index  $a ($sz1)  ok"
+	} else {
+	    puts stderr "\n*********** Missing Transform $a ($sz1)"
+	    exit
+	}
+
+	if { $singlereference == 0 } {
+
+	    set refimgname [ lindex $refimg $i ]
+	    set b "[ file root $refimgname ].img"
+	    set ok1 [ file exists $a ] ;   set sz1 -1 ; catch { set sz1 [ file size $a ] }
+	    set ok2 [ file exists $b ] ;   set sz2 -1 ; catch { set sz2 [ file size $b ] }
+	    
+	    if { $ok1 > 0 && $ok2 > 0 } {
+		puts stderr "\tRef image $index  $a,[file tail $b ] ($sz1,$sz2)  ok"
+	    } else {
+		puts stderr "\n*********** Missing Image $a,$b ($sz1,$sz2)"
+		exit
+	    }
+	}
+
+
+    }
+
+    if { $singlereference == 1 } {
+	set refimgname [ lindex $refimg 0 ]
+	set a $refimgname
+	set b "[ file root $refimgname ].img"
+	set ok1 [ file exists $a ] ;   set sz1 -1 ; catch { set sz1 [ file size $a ] }
+	set ok2 [ file exists $b ] ;   set sz2 -1 ; catch { set sz2 [ file size $b ] }
+	
+	if { $ok1 > 0 && $ok2 > 0 } {
+	    puts stderr "\tSingle Ref image  $a,[file tail $b ] ($sz1,$sz2)  ok"
+	} else {
+	    puts stderr "\n*********** Missing Image $a,$b ($sz1,$sz2)"
+	    exit
+	}
+    }
+}
+
+# --------------------------------------------------------------------------------------------------------
+
+proc MakeDirectory { } {
+    global outputdirectory
+
+    if { [ file exists $outputdirectory ] == 0 } {
+	file mkdir $outputdirectory
+    }
+
+}
+
+proc GenAbsolute { fname } {
+
+    if { [ file pathtype $fname ] == "relative" } {
+	set out [ file join [ pwd ] $fname ]
+	regsub -all  "/./" $out "/" out
+    } else {
+	set out $fname
+    }
+
+    puts stderr "$fname -> $out"
+    return $out
+}
+
+# --------------------------------------------------------------------------------------------------------
+# Main Program
+# --------------------------------------------------------------------------------------------------------
+
+set singlereference 1
+
+if { [ llength $transformlist ] == [ llength $refimg ] } {
+    set singlereference 0
+}
+
+
+TestImages 
+
+
+if { [ llength $argv ] < 3 } {
+    exit
+}
+
+MakeDirectory
+
+puts stdout "\# Makefile Output\n"
+puts stdout "all : computeall\n"
+
+set nlist ""
+set blist ""
+set rlist ""
+
+for { set i 0 } { $i < [ llength $transformlist ] } { incr i } {
+
+    if { $singlereference == 0 } {
+	set ref_image [ lindex $refimg $i ]
+    } else {
+	set ref_image $refimg
+    }
+
+    set trfname [ lindex $transformlist $i ]
+    # $rawjacobians 
+    # $threshold
+    # $sigma
+    
+    set fname  [ file join $outputdirectory "[ file tail [ file root $trfname ]]_${outputstem}_${blursize}" ]
+    if { $rawjacobians == 0 } {
+	set a "${fname}_combined"
+	set b "${fname}_nonlinear"
+	lappend rlist $a.hdr
+	lappend rlist $a.img.gz
+	lappend rlist $b.hdr 
+	lappend rlist $b.img.gz
+	lappend blist ${b}.hdr
+    } else {
+	set a "${fname}_raw"
+	lappend rlist $a.hdr
+	lappend rlist $a.img.gz
+
+    }
+    puts stdout "${a}.hdr : $trfname"
+    lappend nlist ${a}.hdr
+
+    puts stdout "\tpxsinglejacobian.tcl $ref_image $trfname ${fname}.hdr $resolution $blursize $threshold $rawjacobians\n"
+}
+
+set nlist2 ""
+
+if { $computeaverage == 1 } {
+
+    set maxv 2
+    if { $rawjacobians == 1 } {
+	set maxv 1 
+    }
+    for { set i 0 } { $i < $maxv } { incr i } {
+	if { $rawjacobians == 1 } {
+	    set mstem [ file join $outputdirectory ${outputstem}_${blursize}_raw ]
+	    puts stdout "${mstem}_mean.hdr : $nlist\n\tpxcomputeaverage.tcl $mstem $nlist\n"
+	} elseif { $i == 0 } {
+	    set mstem [ file join $outputdirectory ${outputstem}_${blursize}_combined ]
+	    puts stdout "${mstem}_mean.hdr : $nlist\n\tpxcomputeaverage.tcl $mstem $nlist\n"
+	} else {
+	    set mstem [ file join $outputdirectory ${outputstem}_${blursize}_nonlinear ]
+	    puts stdout "${mstem}_mean.hdr : $nlist\n\tpxcomputeaverage.tcl $mstem $blist\n"
+	}
+	
+	lappend rlist "${mstem}_mean.hdr"
+	lappend rlist "${mstem}_mean.img"
+	lappend nlist2 "${mstem}_mean.hdr"
+    }
+}
+puts stdout "\ncomputeall : $nlist $nlist2\n"
+puts stdout "\nclean : \n\trm $rlist "
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmultiregister_int.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmultiregister_int.tcl
new file mode 100755
index 0000000..18fd89f
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmultiregister_int.tcl
@@ -0,0 +1,838 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# --------------------------------------------------------------------------------------------------------
+# 	$Id: pxmultiregister_int.tcl,v 1.1 2004/01/15 15:06:06 xenios Exp xenios $	
+
+
+set argc [llength $argv]
+if { $argc <2 } {
+    set scriptname [ file tail $argv0 ]
+    puts stderr "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stderr "$scriptname is a script that generates a makefile to compute batch mode registrations to a single reference"
+
+    puts stderr "Syntax: $scriptname setup_file output_directory \[ go,setup\]  \[ > makefile  \]"
+    puts stderr " if the word go is missing the program simply tests for the presence of all the images"
+    puts stderr " if the word setup is present the program simply generates a multi-subject setup file (.msb) and stops"
+    puts stderr " if the word go is present then the program outputs a makefile to stdout. Use the make (gmake) command to execute the batch job!"
+    
+    puts stderr "\n type $scriptname sample > sample.setup "
+    puts stderr " \t to generate a sample setup file\n"
+    puts stderr "\n"
+
+    if { [ lindex $argv 0 ] != "sample" } {
+	exit
+    }
+
+    puts stdout "\#Example Setup File\n\# all lines beginning with \# are ignored \n\#"
+    puts stdout "\#\tif imglist is missing this defaults to standard rpm registration"
+    puts stdout "\#\tif surfacelist is missing this defaults to standard intensity registration"
+
+    puts stdout "\#\txformlist   is ignored unless both imglist and surfacelist are present"
+    puts stdout "\#\t\t if no initial transformations are specified, these are computed via rpm and then the integrated algorithm is executed!"
+
+    puts stdout "\#\n\# Mode of Operation"
+    puts stdout "set intensities_only 0"
+    puts stdout "set points_only 0"
+    puts stdout "set ignore_initial_transformations 0\n\#\n\#"
+    puts stdout "\#\n\#\n\# List all images here\n\#"
+    puts stdout "set imglist \{"
+    puts stdout "   /data/brains/1001/sag.cihte.hdr"
+    puts stdout "   /data/brains/1002/sag.cihte.lw.hdr"
+    puts stdout "\}\n\#\n\#\n"
+
+    puts stdout "\#\n\#\n\# List all surface objectmaps (same number as the images here)\n\#"
+    puts stdout "set surfacelist \{"
+    puts stdout "   /data/brains/1001/1001_objectmap.vtk"
+    puts stdout "   /data/brains/1002/1002_objectmap.vtk"
+    puts stdout "\}\n\#\n\#\n"
+
+    puts stdout "\#\n\#\n\# List all initial transforms (if they exist -- same number as images else do not include ) here\n\#"
+    puts stdout "set xformlist \{"
+    puts stdout "   /data/brains/1001/1115_normalized_objectmap_1001_objectmap.grd"
+    puts stdout "   /data/brains/1002/1115_normalized_objectmap_1002_objectmap.grd"
+    puts stdout "\}\n\#\n\#\n"
+
+    puts stdout "\#\n\# If Binary map to test alignment -- put it here"
+    puts stdout "set objectmaplist \{"
+    puts stdout "   /data/brains/1001/1115_gray.hdr"
+    puts stdout "   /data/brains/1002/1115_gray.hdr"
+    puts stdout "\}\n\#\n\#\n"
+    
+
+    puts stdout "\#\n\#\n\# Put reference brain here\n\#"
+    puts stdout "set refimg  /home/papad/normalized/1115_normalized.hdr"
+    puts stdout "set refsurface  /home/papad/normalized/1115_normalized_objectmap.vtk\n\#"
+    puts stdout "\# If using objectmaps put reference objectmap here"
+    puts stdout "\nset refobjectmap /data/brains/1002/1115__normalized_gray.hdr\n\#"
+    puts stdout "\# Leave objectmap sigma as negative number unless it is a single roi"
+    puts stdout "\nset objectmapsigma -2.0"
+    puts stdout "\#\n\# beginsubject determines which would the first subject to be processed"
+    puts stdout "\# -1 = default automatically determines whether this is a new job or a restarting of a crashed job"
+    puts stdout "set beginsubject -1"
+    puts stdout "\# Initial Transform Mode = one of ( affine,similarity,rigid )"
+    puts stdout "set linearmode  \"affine\"\n\n"
+    puts stdout "\#\n\#\n\# Tweak parameters for intensity based part"
+    puts stdout "\# Regarding filetype: filetype = 1 includes directory name in output filename 0 does not"
+    puts stdout "set resolution 1.5\nset spacing   15.0\nset iterations 15\nset filenametype 0\nset smoothness 0.001"
+    puts stdout "set linearonly 0\nset autonormalize 1\n"
+    puts stdout "\#\n\#\n\# Tweak parameters for point-based part, userpm=0 then use icp instead"
+    puts stdout "set userpm 1"
+    puts stdout "set numpoints 1000\nset initial_spacing  30\nset final_spacing 15\n"
+    puts stdout "set initial_smoothness 5.0\nset final_smoothness 1.0\n"
+    puts stdout "set initial_linear_temperature 15\nset final_linear_temperature  3"
+    puts stdout "set initial_spline_temperature 3\nset final_spline_temperature 1.5"
+    puts stdout "\#\n\#\n\# Tweak parameters for integrated part"
+    puts stdout "\nset pointsweight 0.1"
+    puts stdout "set fixedcorrespondences    0"
+    puts stdout "set numsteps 1"
+    puts stdout "set surface_threshold_low      -100"
+    puts stdout "set surface_threshold_high     +100"
+    puts stdout "set identifier \"\""
+
+    puts stdout "\#\n\#\n\# Parameters for jacobian computation for the final registration\n"
+    puts stdout "set dojacobians 0"
+    puts stdout "set jacobians_stem \"jacobians\""
+    puts stdout "set jacobians_resolution 2.0"
+    puts stdout "set jacobians_blursize   2.0"
+    puts stdout "set jacobians_raw 0"
+    puts stdout "set jacobians_threshold 0.0"
+
+
+    exit
+}
+# ------------------------------------------------------------------------------------------------------
+
+set imglist ""
+set refimg  ""
+set objectmaplist ""
+set refobjectmap ""
+set beginsubject -1
+set resolution 1.5
+set spacing   15.0
+set iterations 15
+set filenametype 0
+set smoothness 0.001
+set linearonly 0
+set autonormalize 1
+set linearmode "affine"
+
+set surfacelist ""
+set xformlist ""
+set refsurface ""
+set userpm 1
+
+set numpoints 3000
+set initial_spacing 30
+set final_spacing 15
+set initial_smoothness 5.0
+set final_smoothness 1.0
+
+set initial_linear_temperature 15
+set final_linear_temperature   3
+
+set initial_spline_temperature 3
+set final_spline_temperature   1
+
+set anneal_rate 0.93
+
+
+set identifier ""
+set pointsweight 0.1
+
+set fixedcorrespondences    0
+set weightedcorrespondences 1
+set surface_threshold_low       -100
+set surface_threshold_high      +100
+
+set intensities_only          0
+set points_only             0
+set ignore_initial_transformations 0
+set ignore_objectmaps 0
+set objectmapsigma   -2.0
+set numsteps 1
+set userpm 1
+
+set jacobians_stem "jacobians"
+set jacobians_resolution 2.0
+set jacobians_blursize   2.0
+set jacobians_raw 0
+set jacobians_threshold 0.0
+set dojacobians 0
+
+    
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+package require  pxitclimage            1.0
+package require  pxitcltransform        1.0
+package require  pxitclsubjectentry     1.0
+
+
+set usesurfaces 1
+set useimgages  1
+set useinitialxforms 1
+set usesurfacesforchecking 0
+set useimagesforchecking   0
+set useobjectmaps 1
+
+set inputfile [ file tail [ file root [ lindex $argv 0 ]]]
+source [ lindex $argv 0 ]
+
+
+if { $imglist != "" } {
+    set endsubject [ llength $imglist ]
+} else {
+    set endsubject [ llength $surfacelist ]
+}
+
+
+# --------------------------------------------------------------------------------------------------------
+
+proc TestImages { argv } {
+
+    global resolution
+    global spacing
+    global beginsubject
+    global iterations
+    global endsubject
+    global refimg
+    global refsurface
+    global imglist
+    global outputdirectory
+    global identifier
+    global filenametype
+    global surfacelist
+    global xformlist
+    global useinitialxforms
+    global pointsweight
+    global usesurfaces
+    global useimages
+    global numpoints
+    global initial_smoothness
+    global final_smoothness
+    global initial_spacing
+    global final_spacing
+    global initial_spline_temperature
+    global final_spline_temperature
+    global usesurfacesforchecking 
+    global useimagesforchecking   
+    global useobjectmaps 
+    global objectmaplist 
+    global refobjectmap
+    
+
+    puts stderr "Testing for existence of images,surfaces and initial transforms (useimages=$useimages,usesurfaces=$usesurfaces,usexforms=$useinitialxforms)"
+    set outputdirectory [ lindex $argv 1 ]
+
+    if { $identifier == "" } {
+	if { $usesurfaces == 1 && $useimages == 1 } {
+	    set identifier  "integr"
+	} elseif { $usesurfaces == 1 } {
+	    set identifier "np${numpoints}_sm${initial_smoothness}_${final_smoothness}_cp${initial_spacing}_${final_spacing}"
+#_te_${initial_spline_temperature}_${final_spline_temperature}"
+	} else {
+	    set identifier  "nmi_${spacing}_${resolution}"
+	}
+    }
+
+    for { set i $beginsubject } { $i <= $endsubject } { incr i } {
+	
+	if { $i != $endsubject } {
+	    
+	    if { $useimages == 1 || $useimagesforchecking == 1 } {
+		set a [ lindex $imglist $i ]
+	    } else {
+		set a ""
+	    }
+
+
+	    if { $usesurfaces == 1 || $usesurfacesforchecking == 1 } {
+		set b [ lindex $surfacelist $i ]
+	    } else {
+		set b ""
+	    }
+	    
+	    if { $useinitialxforms == 1 } {
+		set c [ lindex $xformlist $i ]
+	    } else {
+		set c ""
+	    }
+	    set index [ format "%3d" $i ]
+
+	    if { $useobjectmaps == 1 } {
+		set d [ lindex $objectmaplist $i ]
+	    } else {
+		set d ""
+	    }
+	} else {
+	    if { $useimages == 1 || $useimagesforchecking == 1} {
+		set a $refimg
+	    } else {
+		set a ""
+	    }
+	    
+	    if { $usesurfaces == 1 || $usesurfacesforchecking == 1 } {
+		set b $refsurface
+	    } else {
+		set b ""
+	    }
+	    set c ""
+	    set index "REF"
+
+	    set d $refobjectmap
+	}
+
+	if { $a != "" } {
+	    set ok1 [ pxappscommon::EnsureImageExists $a ]
+	} else {
+	    set ok1 "(none)"
+	}
+
+	if { $b != "" } {
+	    set ok3 [ file exists $b  ] ;   set sz3 -1 ; catch { set sz3 [ file size $b ] }
+	} else {
+	    set ok3 1 
+	    set sz3 none
+	}
+
+	if { $c != "" } {
+	    set ok4 [ file exists $c ] ;   set sz4 -1 ; catch { set sz4 [ file size $c ] }
+	} else {
+	    set ok4 1
+	    set sz4 "(none)"
+	}
+
+
+	if { $d != "" } {
+	    set okd1 [ pxappscommon::EnsureImageExists $d ]
+	} else {
+	    set okd1 "(none)"
+	}
+
+	
+	if { $ok1 !=0    && $ok3 > 0 && $ok4 > 0 && $okd1 !=0   } {
+	    set f "--> [ pxtclutil::GenerateFilename $refimg $a $identifier [ pxtclutil::GetNonLinearSuffix ] $outputdirectory $filenametype ]"
+	    if { $index == "REF" } {
+		set f ""
+	    }
+	    puts stderr "\n\t$index  $ok1\n\t surface=$b ($sz3)\n\t initxform = $c ($sz4) $f  objectmap=$okd1 ok"
+	} else {
+	    puts stderr "\n*********** Missing Image $ok1 surface  $b ($sz3)  or initxform $c ($sz4) or ojectmap $okd1"
+	}
+    }
+}
+
+# --------------------------------------------------------------------------------------------------------
+
+proc MakeDirectory { } {
+    global outputdirectory
+
+    if { [ file exists $outputdirectory ] == 0 } {
+	file mkdir $outputdirectory
+    }
+
+}
+# --------------------------------------------------------------------------------------------------------
+proc GenAbsolute { fname } {
+
+    if { [ file pathtype $fname ] == "relative" } {
+	set out [ file join [ pwd ] $fname ]
+	regsub -all  "/./" $out "/" out
+    } else {
+	set out $fname
+    }
+
+    return $out
+}
+
+# --------------------------------------------------------------------------------------------------------
+proc GenerateSetupFile {  }  {
+
+    global outputdirectory
+    global identifier
+    global beginsubject
+    global endsubject
+    global refimg
+    global imglist
+    global filenametype
+    global inputfile
+    global useimages
+    global usesurfaces
+    global surfacelist
+    global refsurface
+
+    set fname [ file join $outputdirectory "${inputfile}_${identifier}.msb" ]
+
+    set fileid [open $fname w]
+    puts $fileid "#Multisubject Description File v2"
+    
+    set task [ pxitcltask \#auto ]
+    $task configure -task_name "First Task"
+    $task configure -task_suffix "_task1"
+
+    puts $fileid "Tasks\n1"
+    puts $fileid "- - - - - - - - - - - - - - - - - - - -"
+    $task SaveToSetupFile $fileid
+    
+    set subject [ pxitclsubject \#auto ]
+
+    puts $fileid "Subjects\n[llength $imglist]"
+    puts $fileid "- - - - - - - - - - - - - - - - - - - -"
+    for { set i $beginsubject } { $i < $endsubject } { incr i } {
+	[ $subject cget -anatomical_image ] configure -filename [ GenAbsolute [ lindex $imglist $i ] ]
+	if { $useimages == 1 } {
+	    set f "[ pxtclutil::GenerateFilename $refimg [ lindex $imglist $i ] $identifier [ pxtclutil::GetNonLinearSuffix ] $outputdirectory $filenametype ]"
+	} else {
+	    set f [ pxtclutil::GenerateFilename $refsurface [ lindex $surfacelist $i ] $identifier [ pxtclutil::GetNonLinearRPMSuffix ] $outputdirectory $filenametype ] 
+	}
+	[ $subject cget -reference_transform ] configure -filename [ GenAbsolute $f ]
+	$subject SaveToSetupFile $fileid
+    }
+
+    puts $fileid "Reference/Output Images"
+    puts $fileid "--------------------------------------"
+
+    puts $fileid " Reference Image : [ GenAbsolute $refimg]"
+
+    set output_list [ list "Average Anatomical" "Std Anatomical" "Average Functional" "Std Functional" "TofT Functional" "Thresholded Composite" "Average Jacobian" "Std Jacobian" ]
+    set name_list [ list "average_anatomical" "std_anatomical" "average_functional" "std_functional" "toft_functional" "thresholded_composite" "average_jacobian" "std_jacobian" ]
+
+    for { set i 0 } { $i < [ llength $output_list ] } { incr i } {
+	if { $i >=2 && $i <= 5 } {
+	    puts $fileid "[ lindex $output_list $i ] : [ GenAbsolute [ file root $fname]_[ lindex $name_list $i ]_task1.hdr]"
+	} else {
+	    puts $fileid "[ lindex $output_list $i ] : [ GenAbsolute [ file root $fname]_[ lindex $name_list $i ].hdr]"
+	}
+    }
+    
+    close $fileid
+}
+# --------------------------------------------------------------------------------------------------------
+#    Jacobian Stuff
+# --------------------------------------------------------------------------------------------------------
+
+proc   GenerateJacobianTarget { finalxformlist ptsweight numweights } {
+
+    global jacobians_stem 
+    global jacobians_resolution 
+    global jacobians_blursize   
+    global jacobians_raw 0
+    global jacobians_threshold 
+    global argv
+
+    global identifier
+    global refimg
+    global inputfile
+    global outputdirectory
+
+    set suffix ${jacobians_stem}
+    if { $numweights > 1 } {
+	set suffix "${jacobians_stem}_${ptsweight}"
+    }
+
+    set fname [ file join $outputdirectory "${inputfile}_${identifier}_${suffix}.txt" ]
+    
+    set fileid [open $fname w]
+
+    puts $fileid "\#Jacobian Definition File\n"
+    puts $fileid "set transformlist \{"
+    for { set i 0 } { $i < [ llength $finalxformlist ] } { incr i } {
+	puts $fileid "\t [ lindex $finalxformlist $i ]"
+    }
+    puts $fileid "\}\n\#"
+    puts $fileid "\#\n\#\n\# Put reference brain here\n\#"
+    puts $fileid "set refimg  $refimg"
+    puts $fileid "\n\#\n\#\n\# Put output stem and resolution here\n\#"
+    puts $fileid "set outputstem $suffix"
+    puts $fileid "set resolution ${jacobians_resolution}"
+    puts $fileid "set blursize   ${jacobians_blursize}"
+    puts $fileid "\n\# Set this to 1 to get the full tensor as opposed to just the determinant"
+    puts $fileid "set rawjacobians ${jacobians_raw}"
+    puts $fileid "\n\# Set this to 0.05 to eliminate computation of jacobian in low intensity regions"
+    puts $fileid "set threshold  ${jacobians_threshold}"
+
+    close $fileid
+
+    set jobname "jacobians_${suffix}"
+
+    set dname [ file join $outputdirectory $jobname ]
+
+    file mkdir $dname
+
+    puts stdout "$jobname : $finalxformlist"
+    puts stdout "\t pxmultijacobian.tcl $fname $dname go\n"
+
+    return $jobname
+}
+
+
+# --------------------------------------------------------------------------------------------------------
+# Main Program
+# --------------------------------------------------------------------------------------------------------
+
+set totalnumber 0
+
+if { $beginsubject == -1 } {
+    set auto_flag 1
+    set beginsubject 0
+} else {
+    set auto_flag 0
+}
+
+
+if { [ llength $imglist ] > 0 } {
+    if { [ llength $surfacelist ] > 0 } {
+	if { [ llength $surfacelist ] != [ llength $imglist ] } {
+	    puts stderr "Error different numbers of images ([llength $imglist]) and surfaces ([ llength $surfacelist ]) specified"
+	    exit 0
+	}
+	set usesurfaces 1
+    } else {
+	set usesurfaces 0
+    }
+    
+    if { [ llength $xformlist ] > 0 && $ignore_initial_transformations == 0 } {
+	if { [ llength $xformlist ] != [ llength $imglist ] } {
+	    puts stderr "Error different numbers of images ([llength $imglist]) and surfaces ([ llength $xformlist ]) specified"
+	    exit 0
+	}
+	set useinitialxforms 1
+    } else {
+	set useinitialxforms 0
+    }
+    set useimages 1
+    set totalnumber [ llength $imglist ]
+} else {
+    set usesurfaces 1
+    set useinitialxforms 0
+    set useimages 0
+    set totalnumber [ llength $surfacelist ]
+}
+    
+
+if { $intensities_only == 1 && $useimages == 1 } {
+    
+    if  { $usesurfaces == 1 } {
+	set usesurfaces 0
+	set usesurfacesforchecking 1
+    }
+} elseif { $points_only == 1 && $usesurfaces == 1 } {
+    
+    if { $useimages == 1 } {
+	set useimages 0
+	set useimagesforchecking 1
+    }
+}
+
+if { [ llength $objectmaplist ] == $totalnumber } {
+    set usetobjectmaps 1
+} else  {
+    set useobjectmaps 0
+}
+
+
+TestImages $argv
+puts stderr "Using identifier $identifier, output directory is $outputdirectory"
+
+puts stdout "\# Global Settings\n\#"
+puts stdout "\# Number of Inputs"
+puts stdout "\# Images = [ llength $imglist ], Surfaces = [ llength $surfacelist ], Transforms = [ llength $xformlist ]"
+puts stdout "\# Input Specs: intensities_only = $intensities_only,   points_only=$points_only ignore_initial_xforms=$ignore_initial_transformations\n\#"
+puts stdout "\# Actual Use:"
+puts stdout "\#\t Use Images = $useimages (for checing only $useimagesforchecking)"
+puts stdout "\#\t Use Surfaces = $usesurfaces (for checing only $usesurfacesforchecking)"
+puts stdout "\#\t Use Initial Transformations = $useinitialxforms, and Objectmaps=$useobjectmaps\n\#\n\#-------------------------------------------------------"
+
+if { [ llength $argv ] < 3 } {
+    exit
+}
+
+if { [ lindex $argv 2 ] != "go" } {
+    if { [ lindex $argv 2 ] == "setup" } {
+	GenerateSetupFile
+    }
+    exit
+}
+
+
+
+# Stop the program and fix up the button
+MakeDirectory
+GenerateSetupFile
+
+
+puts stdout "\#\n\# Makefile for batch job\n\#\n\#\n"
+puts stdout "all : computeall\n"
+set all ""
+set linearall ""
+set realcleanall ""
+set results ""
+set rpmresults ""
+set overlaps ""
+
+set jacobianlist ""
+set lmode 1
+if { $linearmode == "similarity" } {
+    set lmode 2 
+} elseif { $linearmode == "rigid" } {
+    set lmode 3
+}
+
+if { $usesurfaces == 0 || $useimages == 0 } {
+    set pointsweight "\#"
+}
+
+if { $userpm != 0 } {
+    set rpmname "rpm"
+    set userpm  1
+} else {
+    set rpmname "icp"
+    set userpm 0
+}
+
+for { set j  0 } { $j < [ llength $pointsweight ] } { incr j } {
+
+    set finalxformlist ""
+
+    set weight [ lindex $pointsweight $j ]
+
+    if { $usesurfaces == 0 || $useimages == 0 } {
+	set identifierw $identifier
+    } else {
+	set wg [ format "%5.3f" $weight ]
+	if { $usesurfaces == 0 } {
+	    set identifierw ${identifier}_${wg}
+	} else {
+	    set identifierw ${identifier}_${rpmname}_${wg}_${numsteps}
+	}
+    }
+
+
+    for { set i $beginsubject } { $i < $endsubject } { incr i } {
+	
+	puts stdout "\#-------------------------------------------------------\n\# Individual Subject [ expr $i + 1 ] w=$weight\n\#-------------------------------------------------------\n"
+	
+	
+	if { $usesurfaces ==1 } {
+	    set f1 [ pxtclutil::GenerateFilename $refsurface [ lindex $surfacelist $i ]  $rpmname [ pxtclutil::GetLinearSuffix ] $outputdirectory $filenametype ]
+	    set f2 [ pxtclutil::GenerateFilename $refsurface [ lindex $surfacelist $i ]  $rpmname [ pxtclutil::GetNonLinearRPMSuffix ] $outputdirectory $filenametype ]
+	}
+	
+	# -------------------------------------------------------
+	#
+	# Case A :  use images or not
+	#
+	# -------------------------------------------------------
+	
+	
+	if { $useimages == 1 } {
+	    set f3 [ pxtclutil::GenerateFilename $refimg [ lindex $imglist $i ]  "${identifierw}" [ pxtclutil::GetNonLinearSuffix ] $outputdirectory $filenametype ]
+	} else {
+	    set f2 [ pxtclutil::GenerateFilename $refsurface [ lindex $surfacelist $i ] "${identifierw}" [ pxtclutil::GetNonLinearRPMSuffix ] $outputdirectory $filenametype ]
+	}
+
+	# -------------------------------------------------------
+	#
+	# Case B : use surfaces  =0
+	#
+	# -------------------------------------------------------
+	
+	if { $usesurfaces == 0 } {
+	    
+	    # -------------------------------------------------------
+	    #
+	    # Do not use Surfaces use only images
+	    #
+	    # -------------------------------------------------------
+
+	    if { $linearonly == 1 } {
+		set f3 [ pxtclutil::GenerateFilename $refimg [ lindex $imglist $i ]  "${identifierw}" [ pxtclutil::GetLinearSuffix ] $outputdirectory $filenametype ]
+		set command "pxmat_register.tcl $refimg [ lindex $imglist $i ] $f3 $lmode $resolution $spacing $iterations 1.0 $smoothness $lmode $autonormalize"	    
+		set command "$command > $f3.intlog 2>&1"
+		puts stdout "$f3 :\n\t$command"
+		set all "$all $f3"
+	    } else {
+		set command "pxmat_register.tcl $refimg [ lindex $imglist $i ] $f3 0 $resolution $spacing $iterations 1.0 $smoothness $lmode $autonormalize"
+		if { $useinitialxforms == 1 } {
+		    set command "$command [ lindex $xformlist $i ]"
+		}
+		set command "$command > $f3.intlog 2>&1"
+		puts stdout "$f3 :\n\t$command"
+		set all "$all $f3"
+		
+		if { $usesurfacesforchecking == 0 } {
+		    set command2 "pxmat_computesimilarity.tcl $refimg [ lindex $imglist $i ] $f3 > $f3.results 2>&1"
+		} else {
+		    set command2 "pxmat_computesimilarity.tcl $refimg [ lindex $imglist $i ] $f3 $refsurface [ lindex $surfacelist $i ] $final_spline_temperature [ expr $numpoints /3 ]  0  > $f3.results 2>&1"
+		}
+
+		if { $useobjectmaps > 0 } {
+		    set command3 "pxmat_computeoverlap.tcl $refobjectmap [ lindex $objectmaplist $i ] $objectmapsigma $f3 > $f3.overlap 2>&1"
+		    set overlaps "$overlaps $f3.overlap"
+		    puts stdout "\n$f3.overlap : $f3\n\t$command3\n"
+		} else {
+		    puts stderr "objectmaps = $useobjectmaps"
+		}
+		
+		puts stdout "$f3.results : $f3\n\t$command2"
+		set realcleanall "$realcleanall $f3"
+		set results      "$results $f3.results"
+
+		lappend finalxformlist $f3
+
+	    }
+	} else {
+	    
+	    # -------------------------------------------------------
+	    #
+	    # Use Surfaces  =1
+	    #
+	    # -------------------------------------------------------
+	    
+	    if { $useinitialxforms == 0 } {
+		
+		# -------------------------------------------------------
+		#
+		# Compute Straight RPM for initialization
+		#
+		# -------------------------------------------------------
+		
+		
+		set command "pxmat_pointregister.tcl $refsurface [ lindex $surfacelist $i ] $f1 $lmode $userpm [ expr $numpoints / 3 ] $initial_linear_temperature $final_linear_temperature 5.0 1.0 20 10  > $f1.intlog 2>&1"
+		puts stdout "$f1 :\n\t $command\n"
+		set linearall "$linearall $f1"
+		
+		set command "pxmat_pointregister.tcl $refsurface [ lindex $surfacelist $i ] $f2 0 $userpm [ expr $numpoints  ] $initial_spline_temperature $final_spline_temperature $initial_smoothness $final_smoothness $initial_spacing $final_spacing $f1 > $f2.intlog 2>&1"
+		puts stdout "$f2 : $f1\n\t $command\n"
+		
+		
+		set realcleanall "$realcleanall $f1 $f2 ${f1}.intlog ${f2}.intlog"
+	    } else {
+		
+		# -------------------------------------------------------
+		#
+		# Else Use Initial Transform 
+		#
+		# -------------------------------------------------------
+		
+		set f2 [ lindex $xformlist $i ]
+	    }
+	    
+	    if { $useimages == 1 } {
+		
+		# -------------------------------------------------------
+		#
+		#  Use Images + Surfaces 
+		#
+		# -------------------------------------------------------
+		
+		set command "pxmat_integratedregistration.tcl $refimg [ lindex $imglist $i ] $refsurface [ lindex $surfacelist $i ] $f3 $f2 $spacing $resolution $iterations $smoothness $weight $numpoints  $final_spline_temperature $fixedcorrespondences $userpm $numsteps $surface_threshold_low $surface_threshold_high > $f3.intlog 2>&1 "
+		puts stdout "$f3 : $f2\n\t $command\n"
+		
+		set all "$all $f3"
+		set realcleanall "$realcleanall $f3"
+		lappend finalxformlist $f3
+
+		set command2 "pxmat_computesimilarity.tcl $refimg [ lindex $imglist $i ] $f3 $refsurface [ lindex $surfacelist $i ] $final_spline_temperature [ expr $numpoints /3 ]  0  > $f3.results 2>&1"
+		puts stdout "$f3.results : $f3\n\t$command2\n"
+		set results "$results $f3.results"
+		
+		if { $j == 0 } {
+		    set outcommand2 [ file join $outputdirectory [ file tail $f2 ]]
+		    set command2b "pxmat_computesimilarity.tcl $refimg [ lindex $imglist $i ] $f2 $refsurface [ lindex $surfacelist $i ] $final_spline_temperature [ expr $numpoints /3 ]  0  > $outcommand2.results 2>&1"
+		    puts stdout "$outcommand2.results : $f2\n\t$command2b\n"
+		    set rpmresults "$rpmresults $outcommand2.results"
+		}
+		
+		if { $useobjectmaps > 0 } {
+		    set command3 "pxmat_computeoverlap.tcl $refobjectmap [ lindex $objectmaplist $i ] $objectmapsigma $f3 > $f3.overlap 2>&1"
+		    set overlaps "$overlaps $f3.overlap"
+		    puts stdout "$f3.overlap : $f3\n\t$command3\n"
+		}
+	    } else {
+		
+		# -------------------------------------------------------
+		#
+		#  Do not Use Images + Surfaces  i.e. surface only
+		#
+		# -------------------------------------------------------
+		
+		set all "$all $f2"
+		if { $useimagesforchecking == 0 } {
+		    set command2 "pxmat_computedistance.tcl $refsurface [ lindex $surfacelist $i ] $f2 0 $final_spline_temperature [ expr $numpoints /3 ]  > $f2.results 2>&1"
+		} else {
+		    set command2 "pxmat_computesimilarity.tcl $refimg [ lindex $imglist $i ] $f2 $refsurface [ lindex $surfacelist $i ] $final_spline_temperature [ expr $numpoints /3 ]  0  > $f2.results 2>&1"
+		}
+		puts stdout "$f2.results : $f2\n\t$command2\n"
+		set results "$results $f2.results"
+		
+		if { $useobjectmaps > 0 } {
+		    set command3 "pxmat_computeoverlap.tcl $refobjectmap [ lindex $objectmaplist $i ] $objectmapsigma $f2 > $f2.overlap 2>&1"
+		    set overlaps "$overlaps $f2.overlap"
+		    puts stdout "$f2.overlap : $f2\n\t$command3\n"
+		}
+		lappend finalxformlist $f2
+	    }
+	}
+	puts stdout " "
+    }
+    
+    if { $dojacobians > 0 } {
+	puts stdout "\#-------------------------------------------------------\n\# Jacobian Target for w=$weight\n\#-------------------------------------------------------\n"
+	lappend jacobianlist [ GenerateJacobianTarget $finalxformlist [ lindex $pointsweight $j ] [ llength $pointsweight ] ]
+    }
+}
+puts stdout "\# -------------------------------------------------------"
+puts stdout "\#                     Global Targets                     "
+puts stdout "\# -------------------------------------------------------"
+
+puts stdout "computeall : $all evaluate\n\n"
+if { $dojacobians > 0 } {
+    puts stdout "jacobians : $jacobianlist\n\n"
+}
+puts stdout "evaluate   : $results\n"
+puts stdout "linear     : $linearall\n"
+if { $useobjectmaps > 0 } {
+    puts stdout "overlap   : $overlaps\n"
+    puts stdout "evaluaterpm : $rpmresults\n"
+}
+
+puts stdout "clean :\n\t rm $all\n\n"
+puts stdout "realclean : cleanresults \n\t rm $realcleanall\n\t rm $rpmresults\n"
+puts stdout "cleanresults :\n\t rm $results \n"
+
+
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxmultisegment.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxmultisegment.tcl
new file mode 100755
index 0000000..03310f6
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxmultisegment.tcl
@@ -0,0 +1,225 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# --------------------------------------------------------------------------------------------------------
+# 	$Id: pxmultiregister_int.tcl,v 1.1 2004/01/15 15:06:06 xenios Exp xenios $	
+
+
+set imglist ""
+set numclasses 3
+set imgtype 1
+set identifier "segm"
+set usefsl 0
+set mrfiterations 20
+set smoothness 1.0
+set maxsigmaratio 0.05
+set mrfiterations 20
+
+set argc [llength $argv]
+if { $argc <2 } {
+    set scriptname [ file tail $argv0 ]
+    puts stderr "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stderr "$scriptname is a script that generates a makefile to compute batch mode tissue segmentation using\n\t\teither FSL/fast or native BioImage Suite segmentation tools (pxmat_segment.tcl)"
+
+    puts stderr "Syntax: $scriptname setup_file output_directory \[ go\]  \[ > makefile  \]"
+    puts stderr "\t\t if the word go is missing the program simply tests for the presence of all the images"
+    puts stderr "\t\t if the word go is present then the program outputs a makefile to stdout. Use the make (gmake) command to execute the batch job!"
+    
+    puts stderr "\n type $scriptname sample > sample.setup "
+    puts stderr " \t to generate a sample setup file\n"
+
+    if { [ lindex $argv 0 ] != "sample" } {
+	exit
+    }
+
+    puts stdout "\#Example Setup File\n\# all lines beginning with \# are ignored \n\#"
+    puts stdout "\#\n\# Mode of Operation"
+    puts stdout "\#\n\#\n\# List all images here\n\#"
+    puts stdout "set imglist \{"
+    puts stdout "   /data/brains/1001/sag.cihte.hdr"
+    puts stdout "   /data/brains/1002/sag.cihte.lw.hdr"
+    puts stdout "\}\n"
+    puts stdout "\#\n\#\n\# Mode"
+    puts stdout "\# Set this to 0 to use native BioImage Suite tools"
+    puts stdout "set usefsl 1"
+    puts stdout "\nset numclasses 3\n\n"
+    puts stdout "set identifier $identifier"
+    puts stdout "\#\n\#\n\# FSL parameters"
+    puts stdout "set imgtype 1"
+    puts stdout "\#\n\#\n\# BioImage Suite parameters"
+    puts stdout "set smoothness 1.0"
+    puts stdout "set maxsigmaratio 0.05"
+    puts stdout "set mrfiterations 20"
+    exit
+}
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+package require  pxitclimage            1.0
+package require  pxitcltransform        1.0
+package require  pxitclsubjectentry     1.0
+    
+source [ lindex $argv 0 ]
+
+# --------------------------------------------------------------------------------------------------------
+
+proc TestImages { argv } {
+
+    global imglist
+    global identifier
+
+    puts stderr "Testing for existence of images"
+
+    set outputdirectory [ lindex $argv 1 ]
+    set endsubject [ llength $imglist ]
+
+    for { set i 0 } { $i < $endsubject } { incr i } {
+	
+	set fname   [ file root [ lindex $imglist $i ] ]
+	set outname ${fname}_${identifier}
+	
+	set a "${fname}.hdr"
+	set a1 "${fname}.img"
+	set ok1 [ file exists $a ] ;   set sz1 -1 ; catch { set sz1 [ file size $a ] }
+	set ok2 [ file exists $a1 ] ;   set sz2 -1 ; catch { set sz2 [ file size $a1 ] }
+	
+	set index [ expr $i + 1 ]
+	if { $ok1 > 0 && $ok2 > 0  }  {
+	    puts stderr "\n\t$index  $a,[file tail $a1 ] ($sz1,$sz2)\n\t output -> $outname"
+	} else {
+	    puts stderr "\n*********** Missing Image $a,$a1 ($sz1,$sz2)"
+	    exit
+	}
+    }
+}
+
+# --------------------------------------------------------------------------------------------------------
+
+proc MakeDirectory { } {
+    global outputdirectory
+
+    if { [ file exists $outputdirectory ] == 0 } {
+	file mkdir $outputdirectory
+    }
+
+}
+# --------------------------------------------------------------------------------------------------------
+proc GenAbsolute { fname } {
+
+    if { [ file pathtype $fname ] == "relative" } {
+	set out [ file join [ pwd ] $fname ]
+	regsub -all  "/./" $out "/" out
+    } else {
+	set out $fname
+    }
+
+    return $out
+}
+
+# --------------------------------------------------------------------------------------------------------
+# Main Program
+# --------------------------------------------------------------------------------------------------------
+
+set outputdirectory [ lindex $argv 1 ]
+
+TestImages $argv
+puts stderr "Using identifier $identifier, output directory is $outputdirectory"
+
+puts stdout "\# Global Settings\n\#"
+puts stdout "\# Use FSL = $usefsl"
+puts stdout "\# Number of Inputs"
+puts stdout "\# Images = [ llength $imglist ]"
+puts stdout "\# classes = $numclasses , imgtype=$imgtype"
+if { $usefsl } {
+    puts stdout "\# identifier=$identifier"
+} else {
+    puts stdout "\# mrfiterations=$mrfiterations, smoothness=$smoothness, maxsigmaratio=$maxsigmaratio"
+}
+
+if { [ llength $argv ] < 3 } {
+    exit
+}
+
+if { [ lindex $argv 2 ] != "go" } {
+    exit
+}
+
+
+
+
+MakeDirectory
+
+puts stdout "\#\n\# Makefile for batch job\n\#\n\#\n"
+puts stdout "all : computeall\n"
+set all ""
+set results ""
+
+for { set i 0 } { $i < [ llength $imglist ] } { incr i } {
+
+    set fname [ lindex $imglist $i ]
+    set base  [ file root [ file tail $fname ]]
+    set outname [ file join $outputdirectory "${base}_${identifier}" ]
+
+    if { $usefsl == 1 } {
+	set command "fast -c $numclasses -t$imgtype -v 5 -op -or -od $outname $fname"
+	set command "$command > ${outname}.fsllog 2>&1"
+	puts stdout "${outname}_restore.hdr :\n\t$command"
+	
+	set command2 "pxmat_fastpostprocess $fname $outname $numclasses"
+	set command2 "$command2 > ${outname}_2.fsllog 2>&1"
+	puts stdout "${outname}_classification.hdr :\n\t$command2"
+
+	set all "$all ${outname}_restore.hdr"
+	set results "$results ${outname}_classification.hdr"
+	set results "$results ${outname}.fsllog ${outname}_2.fsllog"
+    } else {
+	
+	set command "pxmat_segment.tcl $fname $numclasses $smoothness $maxsigmaratio $mrfiterations $outname  > ${outname}.segmlog 2>&1"
+	puts stdout "${outname}.hdr :\n\t$command"
+	set all "$all ${outname}.hdr"
+	set results "$results ${outname}.segmlog"
+    }
+}
+puts stdout "\# -------------------------------------------------------"
+puts stdout "\#                     Global Targets                     "
+puts stdout "\# -------------------------------------------------------"
+
+puts stdout "computeall : $all\n\n"
+puts stdout "clean :\n\t rm $all\n\n"
+puts stdout "cleanresults :\n\t rm $results\n"
+
+
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxpairwiseregister.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxpairwiseregister.tcl
new file mode 100755
index 0000000..aa0cf79
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxpairwiseregister.tcl
@@ -0,0 +1,290 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+set argc [llength $argv]
+if { $argc <2 } {
+    set scriptname [ file tail $argv0 ]
+    puts stderr "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stderr "$scriptname is a script that generates a makefile to compute batch mode registrations between pairs of images"
+
+    puts stderr "Syntax: $scriptname setup_file output_directory \[ go\]"
+    puts stderr " if the word go is missing the program simply tests for the presence of all the images"
+    puts stderr "\n type $scriptname sample > sample.setup "
+    puts stderr " \t to generate a sample setup file\n"
+    puts stderr "\n"
+
+    if { [ lindex $argv 0 ] != "sample" } {
+	exit
+    }
+
+
+    puts stdout "\#Example Setup File\n\# all lines beginning with \# are ignored \n\#"
+    puts stdout "\#\n\#\n\# List all subjects here\n\#"
+    puts stdout "\#\n\#\n\# Put reference brain here\n\#"
+    puts stdout "set reflist \{"
+    puts stdout "   /data1/brains/1001/sag2.cihte.hdr"
+    puts stdout "   /data1/brains/1002/sag2.cihte.lw.hdr"
+    puts stdout "\}\n\#"
+    puts stdout "set trglist \{"
+    puts stdout "   /data1/brains/1001/sag.cihte.hdr"
+    puts stdout "   /data1/brains/1002/sag.cihte.lw.hdr"
+    puts stdout "\}\n\#"
+    puts stdout "\#\n\# beginsubject determines which would the first subject to be processed"
+    puts stdout "\# -1 = default automatically determines whether this is a new job or a restarting of a crashed job"
+    puts stdout "set beginsubject -1"
+    puts stdout "\# Initial Transform Mode = one of ( affine,similarity,rigid), only used if transformation is nonlinear or distortion"
+    puts stdout "set linearmode  \"affine\"\n\n"
+    puts stdout "\# mode = linear,nonlinear,distortion"
+    puts stdout "set mode  \"nonlinear\""
+    puts stdout "\#set mode \"rigid\""
+    puts stdout "\#set mode \"affine\""
+    puts stdout "\#set mode \"distortion\""
+    puts stdout "\#\n\#\n\# Tweak parameters"
+    puts stdout "\# filetype = 1 includes directory name in output filename 0 does not"
+    puts stdout "\# defaults are for rigid/affine/nonlinear"
+    puts stdout "set resolution 1.5\nset spacing   15.0\nset iterations 15\nset stepsize 1\nset smoothness auto\n"
+    puts stdout "set autonormalize 1\n"
+    puts stdout "\#For Distortion Correction use\n\#set resolution 2.0\n\#set spacing   12.0\n\#set iterations 15\n\#set stepsize 4\n\#set smoothness 0.0001\nset phaseencode 1\n"
+
+    puts stdout "\# If in Child Study center set this to 1 otherwise leave alone"
+    puts stdout "set filenametype 0\n"
+    exit
+}
+
+
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+set trglist ""
+set reflist  ""
+set beginsubject -1
+set resolution 1.5
+set spacing   15.0
+set phaseencode 1
+set iterations 15
+set filenametype 0
+set mode "nonlinear"
+set stepsize 1.0
+set smoothness auto
+set dummy 0
+set autonormalize 1
+set linearmode "affine"
+
+    
+source [ lindex $argv 0 ]
+set inputfile [ file tail [ file root [ lindex $argv 0 ]]]
+set endsubject [ llength $trglist ]
+
+# --------------------------------------------------------------------------------------------------------
+
+proc TestImages { argv } {
+
+    global resolution
+    global spacing
+    global beginsubject
+    global iterations
+    global endsubject
+    global reflist
+    global trglist
+    global outputdirectory
+    global identifier
+    global filenametype
+    global mode
+    global suffix
+
+    puts stderr "Testing for existence of images"
+    set outputdirectory [ lindex $argv 1 ]
+    set identifier "nmi_r${resolution}_s${spacing}_i${iterations}"
+    
+    set tname(0) "REF"
+    set tname(1) "TRG"
+
+
+    for { set i $beginsubject } { $i < $endsubject } { incr i } {
+
+	set name(0) [ lindex $reflist $i ]
+	set name(1) [ lindex $trglist $i ]
+	set index [ format "%3d" [ expr 1 + $i ] ]
+	
+	for { set j 0 } { $j < 2 } { incr j } {
+	    set a($j) $name($j)
+	    set ok($j) [ pxappscommon::EnsureImageExists $a($j) ]
+	}
+
+	if { $ok(1) !=0 && $ok(0) !=0 } {
+	    set f "--> [ pxtclutil::GenerateFilename $name(0) $name(1) $identifier $suffix $outputdirectory $filenametype ]"
+	    for { set j 0 } { $j <=1 } { incr j } {
+		puts stderr "$index $tname($j)  $ok($j) ok"
+	    }
+	    puts stderr "\t\t Output Transform in $f"
+	} else {
+	    puts stderr "\n*********** Missing Image $ok(0)\n"
+	    puts stderr "\n*********** Missing Image $ok(1)\n"
+	    exit
+	}
+	puts stderr "\n"
+    }
+}
+
+# --------------------------------------------------------------------------------------------------------
+
+proc MakeDirectory { } {
+    global outputdirectory
+
+    if { [ file exists $outputdirectory ] == 0 } {
+	file mkdir $outputdirectory
+    }
+
+}
+
+proc Log { args } {
+	
+    global inputpipe
+    global donext
+    if { $inputpipe == 0 } {
+	return
+    }
+    
+    if [eof $inputpipe] {
+	catch { close $inputpipe  }
+	set donext 1
+    } else {
+	gets $inputpipe line
+	if { $line !="" } {
+	    puts stderr "$args $line"
+	}
+    }
+}
+
+# --------------------------------------------------------------------------------------------------------
+proc GenAbsolute { fname } {
+
+    if { [ file pathtype $fname ] == "relative" } {
+	set out [ file join [ pwd ] $fname ]
+	regsub -all  "/./" $out "/" out
+    } else {
+	set out $fname
+    }
+
+    puts stderr "$fname -> $out"
+    return $out
+}
+
+# --------------------------------------------------------------------------------------------------------
+# Main Program
+# --------------------------------------------------------------------------------------------------------
+
+if { $beginsubject == -1 } {
+    set auto_flag 1
+    set beginsubject 0
+} else {
+    set auto_flag 0
+}
+
+if { [ llength $reflist ] != [ llength $trglist ] } {
+    puts stderr "Different Number Of Target and Source Images exiting\n"
+    exit
+}
+
+set suffix [ pxtclutil::GetNonLinearSuffix ]
+if { $mode == "rigid" || $mode == "affine" } {
+    set suffix [ pxtclutil::GetLinearSuffix ]
+}
+
+TestImages $argv
+
+puts stderr "Using identifier $identifier, output directory is $outputdirectory"
+
+if { [ llength $argv ] < 3 } {
+    exit
+}
+
+if { [ lindex $argv 2 ] != "go" } {
+    exit
+}
+
+
+# Stop the program and fix up the button
+
+MakeDirectory
+
+set inputpipe 0
+set donext 0
+
+if { $smoothness == "auto" } {
+    if { $mode == "nonlinear" } {
+	set smoothness 0.0
+    } else {
+	set smoothness 1.0
+    }
+}
+
+
+set lmode 1
+if { $linearmode == "similarity" } {
+    set lmode 2 
+} elseif { $linearmode == "rigid" } {
+    set lmode 3
+}
+
+
+puts stdout "\# Makefile for pxpairwiseregister.tcl"
+puts stdout "\#\n\# Computing [ expr $endsubject - $beginsubject ] $mode registration(s)\n\#\n\#"
+puts stdout "\# Example usage:\n\#\t nohup gmake -k -j2 -f makefile >& log.txt &\n\# to execute\n\#\n\n"
+puts stdout "all : computeall\n\n"
+
+set allreg ""
+
+for { set i $beginsubject } { $i < $endsubject } { incr i } {
+    
+    set name(0) [ lindex $reflist $i ]
+    set name(1) [ lindex $trglist $i ]
+    set outname [ pxtclutil::GenerateFilename $name(0) $name(1) $identifier $suffix $outputdirectory $filenametype ]
+    
+    if { $mode == "rigid" } {
+	    set command "pxmat_register.tcl $name(0) $name(1) $outname 2 $resolution $spacing $iterations $stepsize 0 $lmode $autonormalize"
+    } elseif { $mode == "affine" } {
+	set command "pxmat_register.tcl $name(0) $name(1) $outname 1 $resolution $spacing $iterations $stepsize 0 $lmode $autonormalize"
+    } elseif { $mode == "distortion" } {
+	set command "pxmat_distortioncorrection.tcl $name(0) $name(1) $outname $phaseencode $resolution $spacing $iterations $stepsize $smoothness $lmode $autonormalize"
+    } else {
+	set command "pxmat_register.tcl $name(0) $name(1) $outname 0 $resolution $spacing $iterations $stepsize $smoothness $lmode $autonormalize"
+    }
+    set allreg "$allreg $outname "
+    puts stdout "$outname : \n\t $command > $outname.intlog 2>&1\n"
+}
+
+puts stdout "\n\n\# All Results\n\n computeall : $allreg"
+
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxroitoroi.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxroitoroi.tcl
new file mode 100755
index 0000000..fa3938e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxroitoroi.tcl
@@ -0,0 +1,161 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+set argc [llength $argv]
+if { $argc != 2 } {
+    puts stderr "Usage  pxroitoroi.tcl  descript.txt outdirectory\n"
+    exit
+}
+
+set textfile [ lindex $argv 0 ]
+set outdir [ lindex $argv 1 ]
+
+set outlist ""
+
+if { [ file exists $textfile ] ==0 || [ file readable $textfile ] == 0 } {
+    puts stderr "Bad Input File $textfile"
+    exit
+}
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+wm withdraw .
+
+catch { file mkdir  $outdir }
+
+
+# ---------------------------------------------------------------------------------
+
+proc SaveSingle { img name value outdir } {
+    set thresholdF  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+    $thresholdF ThresholdBetween  [ expr $value -0.1 ] [ expr  $value  +0.1 ]
+    $thresholdF SetInValue    68
+    $thresholdF SetOutValue 0
+    $thresholdF ReplaceOutOn
+    $thresholdF ReplaceInOn
+    $thresholdF SetInput $img
+    $thresholdF Update
+
+    if { [ string length $name ] > 17 } {
+	set name2 [ string range $name 0 16 ]
+    } else {
+	set name2 $name
+    }
+
+    set done 0
+    while { $done == 0 } {
+	set ind [ string first " " $name2 ]
+	if { $ind == - 1 } {
+	    set ind [ string first "\t" $name2 ]
+	}
+	if { $ind >= 0 } {
+	    set name2 [ string replace $name2 $ind $ind "_" ]
+	} else {
+	    set done 1
+	}
+    }
+
+    set head [ vtkbisImageHeader [ pxvtable::vnewobj ]]
+    $head CreateHeader [ $thresholdF GetOutput ] 0
+    $head SetVOIValue 68
+    $head SetDBName   $name2
+
+    set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+    $anaw SetInput [ $thresholdF GetOutput ]
+    $anaw SetImageHeader $head
+
+    set fname [ file join $outdir $name2 ].hdr
+
+    $anaw Save $fname
+
+    puts stderr "Thresholding for $name between  [ expr $value -0.1 ] and [ expr  $value  +0.1 ] --> $fname"
+    $anaw Delete
+    $head Delete
+    $thresholdF Delete
+    return [ file tail [ file rootname $fname ]]
+}
+
+# ---------------------------------------------------------------------------------
+
+set fileid [open $textfile r]
+set inlist ""
+while { [ gets $fileid line ] >=0 } {
+    lappend inlist $line
+}
+close $fileid
+
+
+set ananame [ file rootname $textfile].hdr
+
+set anar [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+$anar Load $ananame
+
+set inpimg [ $anar GetOutput ]
+puts stderr "Loaded [ [ $anar GetImageHeader ] GetHeaderDescription 0 ]"
+puts stderr "inlist = $inlist"
+
+for { set i 0 } { $i < [ llength $inlist ] } { incr i } {
+
+    set name [ lindex $inlist $i ]
+#    puts stderr "Examining $name"
+    if { [ string first "\[" $name ] == -1 } {
+	# Not a comment
+	set ind [ string first " " $name ]
+	if { $ind == -1 } {
+	    set ind [ string first "\t" $name ]
+	}
+	set len [ string length $line ]
+#	puts stderr "ind = $ind"
+	if { $ind > 0 } {
+	    set val [ string range $name 0 [ expr $ind -1 ] ]
+	    set name2 [ string trim [ string range $name $ind end ] ]
+#	    puts stderr "Value = $val, name = $name2"
+	    set newname [ SaveSingle $inpimg $name2 $val $outdir ]
+	    lappend outlist $newname
+	}
+    }
+}
+
+puts stderr "outlist = $outlist"
+
+set name [ file join $outdir [ file rootname [ file tail $textfile ] ].vois ]
+set fout [ open $name w ]
+for { set i 0 } { $i < [ llength $outlist ] } { incr i } {
+    puts $fout [ lindex $outlist $i ]
+}
+close $fout
+puts stderr "Saved output in $name "
+
+exit
+    
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxsinglejacobian.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxsinglejacobian.tcl
new file mode 100755
index 0000000..b9889bb
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxsinglejacobian.tcl
@@ -0,0 +1,254 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+set refimg  ""
+set resolution -1.0
+set blursize 0.0
+set threshold 0.01
+set raw 0
+
+set argc [llength $argv]
+if { $argc <3 } {
+    set scriptname [ file tail $argv0 ]
+    puts stderr "\n$scriptname is part of BioImage Suite (www.bioimagesuite.org)\n"
+    puts stderr "$scriptname is a script that computes either the determinant of the jacobian or the full tensor for a transformation"
+    puts stderr "Syntax: $scriptname refimage transformation output \[ resolution = -1.0 \] \[ blursize = 0.0 \] \[ threshold 0.0 \] \[ raw_values = 0 \]"
+    exit
+}
+
+
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+
+    
+set imagename           [ lindex $argv 0 ]
+set xformname           [ lindex $argv 1 ]
+set outputname          [ lindex $argv 2 ]
+
+if { $argc > 3 } { set resolution   [ ::pxappscommon::RestrictRange [ lindex $argv 3 ] -1 10.0 ] }
+if { $argc > 4 } { set blursize     [ ::pxappscommon::RestrictRange [ lindex $argv 4 ] 0.0  10.0 ] }
+if { $argc > 5 } { set threshold    [ ::pxappscommon::RestrictRange [ lindex $argv 5 ] 0.0 1.0 ] }
+if { $argc > 6 } { set raw          [ ::pxappscommon::RestrictIntRange [ lindex $argv 6 ] 0 1 ] }
+
+
+# ------------------------------------------------------------------------------------------------
+proc J_ThresholdSmoothImage { img threshold sigma } {
+
+    set r [ [ [ $img GetPointData ] GetScalars ] GetRange ]
+    set cutoff [ expr [ lindex $r 0 ] + $threshold * ( [ lindex $r 1 ] - [ lindex $r 0 ] ) ]
+    puts stderr "++++ Thresholding r=$r , thr=$threshold sigma=$sigma Cutoff for Thresholding = $cutoff"
+
+    set threshold  [ vtkImageThreshold [ pxvtable::vnewobj ]  ]
+    $threshold SetInput $img 
+    $threshold SetInValue    1.0
+    $threshold SetOutValue   0.0
+    $threshold ReplaceInOn
+    $threshold ReplaceOutOn
+    $threshold ThresholdBetween $cutoff [ lindex $r 1 ]
+    $threshold SetOutputScalarTypeToFloat
+    $threshold Update
+
+    set smooth2 [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]]
+    $smooth2 SetInput [ $threshold GetOutput ]
+    $smooth2 SetStandardDeviations $sigma $sigma $sigma
+    $smooth2 SetRadiusFactors 3.0 3.0 3.0
+    $smooth2 Update
+
+
+
+    set out  [ vtkImageData [ pxvtable::vnewobj ]]
+    $out ShallowCopy [ $smooth2 GetOutput ]
+
+    set out2 [ vtkImageData [ pxvtable::vnewobj ]]
+    $out2 ShallowCopy [ $threshold GetOutput ]
+
+    $threshold Delete
+    $smooth2 Delete
+    return [ list $out2 $out ]
+}
+
+proc J_MaskedSmoothImage { input smoothmask sigma } {
+
+
+    set smooth [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]]
+    $smooth SetInput $input
+    $smooth SetStandardDeviations $sigma $sigma $sigma
+    $smooth Update
+
+    set math [ vtkImageMathematics [ pxvtable::vnewobj ]]
+    $math SetInput1 [ $smooth GetOutput ]
+    $math SetInput2 $smoothmask
+    $math SetOperationToDivide
+    $math SetConstantC 0.0
+    $math SetDivideByZeroToC 1
+    $math Update
+
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+    $img ShallowCopy [ $math GetOutput ]
+    $smooth Delete
+    $math Delete
+    return $img
+}
+
+
+proc J_ResampleImage { img sp } {
+
+    set resl [ vtkImageResample [ pxvtable::vnewobj ] ]
+    $resl SetAxisOutputSpacing 0 $sp
+    $resl SetAxisOutputSpacing 1 $sp
+    $resl SetAxisOutputSpacing 2 $sp
+    $resl InterpolateOff
+    $resl SetDimensionality 3
+    $resl SetInput $img
+    $resl Update
+    
+    set ref_image [ vtkImageData [ pxvtable::vnewobj ]]
+    $ref_image ShallowCopy [ $resl GetOutput ]
+    $resl Delete
+
+    puts stdout "++++ Dimensions [ $ref_image GetDimensions ]"
+    return $ref_image
+}
+
+proc J_ComputeSimpleJacobian { ref_imgmask tr  } {
+
+    set jac [ vtkImageData [ pxvtable::vnewobj ]]
+    set jac2 [ vtkImageData [ pxvtable::vnewobj ]]
+    set reg [ vtkpxRegistration [ pxvtable::vnewobj ]]
+    set affine [ $reg ComputeAverageJacobian $ref_imgmask $tr ]
+    $reg ComputeSimpleJacobianImage $ref_imgmask $jac  $tr 100.0 $affine 0.01
+    $reg ComputeSimpleJacobianImage $ref_imgmask $jac2 $tr 100.0 1.0     0.01
+    $reg Delete
+
+    return [ list $jac2 $jac ]
+}
+
+proc J_ComputeCompleteJacobian { ref_imgmask tr } {
+
+    set jac [ vtkImageData [ pxvtable::vnewobj ]]
+    set reg [ vtkpxRegistration [ pxvtable::vnewobj ]]
+    $reg ComputeJacobianImage $ref_imgmask $jac  $tr 1 1.0 0
+    $reg Delete
+    return $jac
+}
+
+# --------------------------------------------------------------------------------------------------------
+
+#set ut [ vtkpxUtil [ pxvtable::vnewobj ]]
+
+set ana [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ] ]
+$ana Load $imagename
+
+set imageheader [ $ana GetImageHeader ]
+puts stderr "\n++++ Image $imagename [ [ $ana GetOutput ] GetDimensions ]"
+
+set util [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]	
+set tr [ $util LoadAbstractTransform  $xformname ]
+$util Delete
+puts stdout "++++ Transform [ file tail $xformname ], [ file size $xformname ]\n++++ Transform Type = [ $tr GetClassName ]"
+
+
+set spa  [ lindex [ [ $ana GetOutput ] GetSpacing ] 0 ]
+set sigma [ expr $blursize/ $spa ]
+
+puts stderr "++++ Using blur = $blursize mm or $sigma (voxels) and threshold=$threshold \%"
+
+# Step 0 -- resample image
+if { $resolution > 0.5 } {
+    set ref [ J_ResampleImage [ $ana GetOutput ] $resolution ]
+} else {
+    set ref [ vtkImageData [ pxvtable::vnewobj ]]
+    $ref ShallowCopy [ $ana GetOutput ]
+}
+
+
+#$ut SaveAnalyze jacobians/0_ref $ref  0
+puts stderr "++++ Using ref image resolution [ $ref GetSpacing ]"
+
+# Step 1 -- create mask
+set tmp [ J_ThresholdSmoothImage $ref $threshold $sigma ]
+set regimgmask [ lindex $tmp 0 ]
+set sregimgmask [ lindex $tmp 1 ]
+
+#$ut SaveAnalyze jacobians/1_smask  $sregimgmask  0
+
+# Step 2 -- Compute Jacobian
+if { $raw == 0 } {
+    set jaclist [ J_ComputeSimpleJacobian $regimgmask $tr ]
+} else {
+    set jaclist [ J_ComputeCompleteJacobian $regimgmask $tr ]
+}
+
+#$ut SaveAnalyze jacobians/2_jac [ lindex $jaclist 0 ] 0
+
+# Step 3 -- Smooth Jacobians
+set outlist ""
+for { set i 0 } { $i < [ llength $jaclist ] } { incr i } {
+    lappend outlist [ J_MaskedSmoothImage [ lindex $jaclist $i ] $sregimgmask $sigma ]
+}
+
+#$ut SaveAnalyze jacobians/3_sjac [ lindex $outlist 0 ] 0
+
+# Step 4 -- Save
+
+if { $raw ==0 } {
+    set suffixlist [ list "_combined" "_nonlinear" ]
+} else {
+    set suffixlist "_raw"
+}
+
+set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+$anaw SetImageHeader $imageheader
+$anaw SetCompression 9
+
+for { set i 0 } { $i < [ llength $outlist ] } { incr i } {
+    $anaw SetInput [ lindex $outlist $i ]
+    set name "[file root $outputname ][ lindex $suffixlist $i ].hdr"
+    $anaw Save $name
+    puts stderr "Output $i saved in $name"
+}
+    
+# Step 5 -- Cleanup
+for { set i 0 } { $i < [ llength $outlist ] } { incr i } {
+    [ lindex $outlist $i ] Delete
+    [ lindex $jaclist $i ] Delete
+}
+
+puts stderr "\n"
+
+$regimgmask Delete
+$sregimgmask Delete
+$ref Delete
+$tr  Delete
+$ana Delete
+exit
+
diff --git a/bioimagesuite30_src/bioimagesuite/apps/pxtonifti.tcl b/bioimagesuite30_src/bioimagesuite/apps/pxtonifti.tcl
new file mode 100755
index 0000000..93f4a99
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/apps/pxtonifti.tcl
@@ -0,0 +1,74 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+set argc [llength $argv]
+if { $argc < 1 } {
+    puts stderr "Usage  pxtonifti.tcl  image1  image2 image 3  ...\n"
+    exit
+}
+
+
+
+lappend auto_path /usr/local/bioimagesuite30/apps
+lappend auto_path [ file dirname [ info script ]]; package require pxappscommon
+wm withdraw .
+
+
+for { set i 0 } { $i < $argc } { incr i } {
+
+    set anar [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+    set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+
+    set fname [ lindex $argv $i ]
+    $anar Load $fname
+
+    set head [ $anar GetImageHeader ]
+    # SetModeToAnalyze() 
+    # SetModeToNIFTI_HDRIMG
+    $head SetModeToNIFTI_NII
+
+    set outname [ file rootname $fname ].nii.gz
+
+    $anaw SetInput [ $anar GetOutput ]
+    $anaw SetImageHeader $head
+    $anaw Save $outname
+    
+    puts stderr "From $fname --> $outname"
+    $anaw Delete
+    $anar Delete
+}
+
+exit
+
+    
diff --git a/bioimagesuite30_src/bioimagesuite/base/CMakeLists.txt b/bioimagesuite30_src/bioimagesuite/base/CMakeLists.txt
new file mode 100644
index 0000000..7fea99f
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/CMakeLists.txt
@@ -0,0 +1,68 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+
+SET(KITSCRIPTS
+    pkgIndex.tcl
+    feedbackplus.tcl
+    labelframe.tcl
+    pxtclreadsprheader.tcl
+    pxtclruncommand.tcl
+    pxtcluserprefs.tcl
+    pxtclutil.tcl
+    pxtclhelp.tcl
+    pxvtable.tcl
+    vtkImageInclude.tcl
+    vtkpxcontrib.tcl
+    vtknrcontrib.tcl
+    pxitclcamera.tcl
+    pxitclelectrodemultigrid.tcl
+    pxitclimage.tcl
+    pxitclmesh.tcl
+    pxitcllandmarks.tcl
+    pxitclobject.tcl
+    pxitclsurface.tcl
+    pxitcltransform.tcl
+    biscmdline.tcl
+    VisTree3.tcl
+    pxtclreadvarianheader.tcl
+)
+
+SET(KITAPPS
+
+)
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+bis_complex_tcl(bioimagesuite/base ${FILELIST2} ${FILELIST})
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/VisTree3.tcl b/bioimagesuite30_src/bioimagesuite/base/VisTree3.tcl
new file mode 100644
index 0000000..c0a35ac
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/VisTree3.tcl
@@ -0,0 +1,901 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+########################################################################################
+########################################################################################
+#				File Tree Widget Definition			       #
+#			     based on Widget by D. Richard Hipp			       #
+#			Modified July 2005 by Marcello DiStasio	to Version 2.0         #
+#			Modified July 2009 by Xenios Papademetris to Version 3.0       #
+########################################################################################
+########################################################################################
+
+
+
+package provide VisTree 3.0
+
+#A Couple preliminary formatting options for the file tree
+
+option add *highlightThickness 0
+
+
+namespace eval Tree { 
+
+    namespace export create dfltconfig config newitem delitem setselection getselection build buildlayer open close drawselection buildwhenidle labelat
+
+    #main Tree variable
+    variable Tree
+
+    #icon data variables
+    variable fileicon
+    variable diricon
+    variable brainiconbw
+    variable brainicongrey
+    variable purplebrainicon
+    variable redbrainicon
+    variable orangebrainicon 
+    variable yellowbrainicon 
+    variable greenbrainicon 
+    variable bluebrainicon 
+    variable lightbluebrainicon 
+    variable rainbowbrainicon 
+    variable arrowicon2 
+    variable arrowicon 
+    variable arrowbrain
+    variable cactusicon
+
+
+
+    global tcl_platform
+    switch $tcl_platform(platform) {
+	unix {
+	    set Tree(font) \
+		-adobe-helvetica-medium-r-normal-*-12-80-100-100-p-56-iso8859-1
+	}
+	windows {
+	    set Tree(font) \
+		-adobe-helvetica-medium-r-normal-*-14-100-100-100-p-76-iso8859-1
+	}
+    }
+
+    #
+    # Create a new tree widget.  $args become the configuration arguments to
+    # the canvas widget from which the tree is constructed.
+    #
+    proc create {w args} {
+
+	variable Tree
+	variable diricon
+	variable brainiconbw
+	variable brainicongrey
+	variable purplebrainicon
+	variable redbrainicon
+	variable orangebrainicon 
+	variable yellowbrainicon 
+	variable greenbrainicon 
+	variable bluebrainicon 
+	variable lightbluebrainicon 
+	variable rainbowbrainicon 
+	variable arrowicon2 
+	variable arrowicon 
+	variable arrowbrain
+	variable cactusicon
+
+
+	eval canvas $w $args
+	bind $w <Destroy> "::Tree::delitem $w /"
+	Tree::dfltconfig $w /
+	Tree::buildwhenidle $w
+	set Tree($w:selection) {}
+	set Tree($w:current) {}
+	set Tree($w:selidx) {}
+	set Tree($w:selidcurrent) {}
+	#------------------------------------------------------------------------------------------
+	# These are all the icon image definitions
+	#------------------------------------------------------------------------------------------
+
+	set diricon [image create photo idir -data {
+	    R0lGODdhEAAQAPIAAAAAAHh4eLi4uPj4APj4+P///wAAAAAAACwAAAAAEAAQAAADPVi63P4w
+	    LkKCtTTnUsXwQqBtAfh910UU4ugGAEucpgnLNY3Gop7folwNOBOeiEYQ0acDpp6pGAFArVqt
+	    hQQAO///}
+		    ]
+	#lots of for loops to clean up the transparency of the folder image
+	for {set i1 0} {$i1 < 3} {incr i1} {
+	    for {set i2 0} {$i2 < 16} {incr i2} {
+		$diricon transparency set $i2 $i1 1
+	    }
+	}
+	for {set i3 0} {$i3 < 16} {incr i3} {
+	    $diricon transparency set 15 $i3 1
+	}
+	for {set i4 15} {$i4 > 6} {incr i4 -1} {
+	    $diricon transparency set $i4 3 1
+	}
+	for {set i4 15} {$i4 > 7} {incr i4 -1} {
+	    $diricon transparency set $i4 4 1
+	}
+	#A couple more spots
+	$diricon transparency set 14 5 1
+	$diricon transparency set 0 15 1
+	$diricon transparency set 0 3 1
+	$diricon transparency set 0 4 1
+	$diricon transparency set 1 3 1
+	
+	#Now I'll correct the file image to have a transparent bg with for loops as above
+	set fileicon [image create photo ifile -data {
+	    R0lGODdhEAAQAPIAAAAAAHh4eLi4uPj4+P///wAAAAAAAAAAACwAAAAAEAAQAAADPkixzPOD
+	    yADrWE8qC8WN0+BZAmBq1GMOqwigXFXCrGk/cxjjr27fLtout6n9eMIYMTXsFZsogXRKJf6u
+	    P0kCADv/}
+		     ]
+	for {set i5 0} {$i5 < 16} {incr i5} {
+	    $fileicon transparency set 0 $i5 1
+	    $fileicon transparency set 14 $i5 1
+	    $fileicon transparency set 15 $i5 1
+	}
+	#And a couple more pixels in the corner...
+	$fileicon transparency set 11 0 1
+	$fileicon transparency set 12 0 1
+	$fileicon transparency set 12 1 1
+	$fileicon transparency set 13 0 1
+	$fileicon transparency set 13 1 1
+	$fileicon transparency set 13 2 1
+	
+	#Define a brain icon with hexadecimal values
+	set brainiconbw [image create bitmap ibrainbw -data {
+	    
+	    #define smallbrain2_width 18
+	    #define smallbrain2_height 16
+	    static char smallbrain2_bits[] = {
+		0xff,0xff,0x03,0x3f,0xf0,0x03,0x0f,0xc0,0x03,0x97,0xa4,0x03,0x07,0x11,0x03,
+		0x53,0x88,0x03,0xa5,0x45,0x02,0x0b,0x94,0x02,0x93,0x88,0x02,0x2f,0x92,0x02,
+		0x4f,0x24,0x03,0x57,0xd1,0x03,0x27,0xfd,0x03,0x9f,0xff,0x03,0xff,0xff,0x03,
+		0xff,0xff,0x03,0x00,0x88,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x66,0x61,0x6c,
+		0x73,0x65,0x00,0x67 };
+	    
+	} ]
+
+	set brainicongrey [image create photo ibraingrey -data {
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtu6WkpNvS0vT59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+IeHh/f/9v77/f3+9/r88sK6yvX69Pr+/P39\
+		/vf596Ojo7qxwvz9+9PB2CcrJVtfWYOEhpyRo/789jo4O4+NiI2KioOBimdn\
+		YOfd5tnMxIGAhnd1d2pna5WTlYKChmRoZZeXl25te5WPkXBycmVlZVRUVNXO\
+		1oGDgnd3dMrLyrvAvbatwPz8+dfJ0ZCFlrCytNfT1szMzL6+vqGfoaOeosrQ\
+		yIKAhf78/vr+/fv++eLc37apuMHDwuLi4s/Pz76/vq6vsL61voB9hPj7+rCx\
+		sdnZ2aysrL+/v6urq2lnaubZ6vj8/Ozn8qusr8vLy83NzZqampKSkn9/f8PD\
+		wvz59/77+f/8+f38//j7+fj9+Pz7+fj6+dHNz7y8vMnJyZiYmPb29v3/+/v/\
+		///9+v36///7/Pr+/vz8+rCwsM7OzqampvHx8f/////+/f/+/MTExK6uruTk\
+		5Onp6cLCwt7e3v//////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		/////////////////////ywAAAAAEgASAAAI9QABBBAwgEABAwcQHFiYQMEC\
+		Bg0iOngAIYJCBBgxLpQwISKFCgk1ZhRp4UJEDAlTXhypMUMDDRlDRtgQciSH\
+		Dh5YIojwAUQIESMPjLBYk8SBEiZOoKCZMcVFFQhWsDjQwsULGDFGRlCZUcYM\
+		GjVsMM14Q+PCnThyRIigYwePjD18xETwA0gQIUOIFDFyBCOSJEqWjGTSxMkT\
+		KFGkTFEYsQGVmhGqWHlyBUsWLQe2NObS5ewBL1/AhBEzhkwZM43PoEmjZg2b\
+		Nm7ebIATp4Gcxg3m0EFSx84dPHn07OHToI+fP7iTNwAEJpCgPn2UKx9EyE0h\
+		3AEBADs=
+	} ]
+
+	set purplebrainicon [image create photo ibrainpurple -data {
+	    R0lGODlhEgASAOcAACIiKnZ6dpqamsK6ymZmYs7OzmIqisrSymZWct7e3q5m\
+		yo4+ulZKYmZGiuLi4opSpjYyNqZ6vopiqoYqvurq6lYidqKeokJGQo5SsmIy\
+		ir62vpKGmvLy8jo6OppSwn5iko6KiqKiom5GitLC1p6Govb29mYyinIioop2\
+		jmZqZlo2erqWyrKawsrKyqpW4nY+mn5Okn42oq6urnIymvr+8tbS1p5CzlZW\
+		VoZ2hl5CZnpWhoZCro5GtnIinqKOqn5KmnJ2cnI6lrJW4oo2utK22o5uomom\
+		kr6+vv7+9o6CnoKChnYqqvr6+rauwloqepJ2ptrO4uLW5qqqqrpq4oZenpaK\
+		omI+dsbGxq6SuppKytLK1noymrKyspp+qno6rqZe0v7++opOqooyrloiho6O\
+		imouinpejmpudpJiqm4yjraqun5+fu7m8sKu0rrCvtbO1pZCwiYqJq5q0q6C\
+		wn5qitra2qJKzlpeWoo+vqJS0nIqmvb+9noypq5i2q5e2sLCwpZSwn46spZq\
+		snp2fpaOkpJGvnoqtnY2ov769v7+/oYyuiomJube5no6omIugp6KrnJyfpp6\
+		tvr++v76/vb69oKGhl4mho5Cwoo6tnouqm5ycno2ppKSkmZmZvby+oJ+hubm\
+		5oZWno5mrp5WwqamplY6cn46qp6Sorqywuba6qqurpZmrrauum4umqpm1pJK\
+		vtLOzmoykraayopCtrZW6l4qgmYuipJGsl4iimpmavr+/mYqjuLe3pI+uno+\
+		nnZ2dpZ2qtbK0n5eim5uenIykooyupaSlv76+q6usnIynoKCirKyttLC2p6G\
+		ppp+ropOrnoyqpJGtv//////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		/////////////////////yH5BAEKAP8ALAAAAAASABIAAAj+ABMJRHKMAysf\
+		kYAlGUHp2CRdAgXq8sQCzbM0s774cqVDy55JAmnQiBKhFqYpYTYNWSIkz4MB\
+		lCRCcQSnlx8jFUxNyMRDjwcnjwRSWgVogalWKuh0eSIhSBYFW1yhAsPMRTFL\
+		m8wMuxDnTqVTInyNsVEEEQtMXxzNQtBhERkQygig4IOrlwlGguyk8TLjDAQA\
+		uTgpIcBgE49Yr9pEonXiS6YxVoYRGkbgBiRhGQwswfImSJ9bMxTNwhEAyK8A\
+		Bdyo+eFhzrFgzhok41MqCZcaBY5YsHDg048ViXQhSRXDVA4Dav44yM1FwydR\
+		RASCoUSlxxBFj2TUOSDliJRcwlJFRWTChkoZDBtktGghwNiaP0wQRUTEZA8N\
+		MExgHWkRQkAJMGBEFFwikzDx0CQyFEAKBwI22OAfBcgAioMUJkLBHxokIGBA\
+		ADs=
+	}]
+
+	set redbrainicon [image create photo ibrainred -data {
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtu8kAAOgSC/T59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+LKawvQHB/f/9v77/f3+9/r88sK6yvX69Pr+\
+		/P39/vf597qxwvz9+9PB2Id9dkBEQScrJVtfWYOEhuhMJ/789mRXcTo4Oykm\
+		JY+NiI2KioOBimdnYOfd5mtsdDQwNCIiKmpna5WTlYKChmRoZVRIYsOu0G5t\
+		e5WPkW9xcWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8fMrLyrvAvbat\
+		wPz8+dfJ0ZOFmrCytNfT1szMzL6+vqGfoaOeosrQyIKAhf78/vr+/fv++eLc\
+		37apuMHDwuLi4s/Pz76/vq6vsL61voB9hPj7+p6Ho7CxsdnZ2aysrL+/v6ur\
+		q2lnaubZ6vj8/Ozn8qusr8vLy83NzZqampKSkn9/f8PDwvz59/77+f/8+f38\
+		//j7+fj9+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb29v3/+/v////9+v36///7\
+		/Pr+/vz8+rCwsM7OzqampvHx8f/////+/f/+/MTExK6uruTk5Onp6cLCwt7e\
+		3skAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAACH5BAEKAP8ALAAAAAASABIAAAj3AAEEEDCAQAED\
+		BxAcWJhAwQIGDSI6eAAhggQEGDNinEAhYgULCTWKRHABQ8QMCxOGDIlRpYYG\
+		GzKqTLlQJocOHmQe+AAihIgRKxGQKNFSoYkTKFKoWMEiJcYWLRe6eAEjhowZ\
+		NGqwtFE05Q0cOXTs4NGDpQ+FK38ACSJkCJEiRloeQTITQRIlS5g0cfIEShSM\
+		UqZQqcLSyhUsWbRs4dJlYcQGXlh+ARMmi5gxZMpIMPP4DJqaB9KoWcOmjZs3\
+		cOI8ljOHTh07d/Dk0bOHT58Gfh43+ANISiBBgwgVMnQIUYNEihbpXt6A0ZpG\
+		jhIlYs78EaQ8kXQHBAA7
+	}]
+	
+	set orangebrainicon [image create photo ibrainorange -data {
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtu85/JeuqQb9lEfT5\
+		9/z5+v77/vv+/v7+/vz+/P3+/vbz+LKawv+yQf/DZeOlQf+6Wff/9v77/f3+\
+		9/r88vmuQcK6yvX69Pr+/P39/vf59/S5bH5oipyFp8SQd7qxwvz9+9PB2OWo\
+		Y4d9dkBEQScrJVtfWYOEhpyRo+mlU/789rWayOGuXmRXcTo4OykmJY+NiI2K\
+		ioOBimdnYIp1jufd5tGaQeGgQWtsdDQwNCIiKmpna5WTlYKChmRoZVRIYsOu\
+		0NaheuGqaG5te5WPkW9xcWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8\
+		fMrLyrvAvbatwOmrdfz8+dfJ0ey2cpOFmrCytNfT1szMzL6+vqGfoaOeosrQ\
+		yIKAhf78/vr+/fv++eLc37apuMHDwuLi4s/Pz76/vq6vsL61voB9hPj7+p6H\
+		o7CxsdnZ2aysrL+/v6urq2lnaubZ6vj8/Ozn8qusr8vLy83NzZqampKSkn9/\
+		f8PDwvz59/77+f/8+f38//j7+fj9+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb2\
+		9v3/+/v////9+v36///7/Pr+/vz8+rCwsM7OzqampvHx8f/////+/f/+/MTE\
+		xK6uruTk5Onp6cLCwt7e3m03BW03BW03BW03BW03BW03BW03BW03BW03BW03\
+		BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03\
+		BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03\
+		BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03\
+		BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03\
+		BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03\
+		BW03BW03BW03BW03BW03BSH5BAEKAP8ALAAAAAASABIAAAj+AAEEEDCAQAED\
+		BxAkWKhgAYMGDiI+gBBBwoQEFCpMmGBh4QUMETNoSGChJEYEGzhi5NAhogeM\
+		JA90PJASpsIPDkCEoKCwpIgRJDhS4JmghIkTQxFYQJFCxQoWLVwMTTDhBYwY\
+		MhJOmEGjho0bOHLoSIBg446OMnj08PEDSBAhQ4gU4bnRyBEKZDkiSaJkCZMm\
+		Tp6U5Qhl6kIKUaRMoVLFyhUsHLNo2cKl7AEKXbx8ARNGzBgyZUqaOYMmjVAE\
+		atawaePmDZw4HSM6kEOS5xw6ddrYuYMnTwI9svfwWaiwj58/gAIJGkSokGxD\
+		hxAlUrSIUSNHjyBFciBJtoNJlMwhVLJ0CVMmTZs4Oejk6ZP39w5A/QklqlMn\
+		+PBHkWpUyntAADs=
+	}]
+
+	set yellowbrainicon [image create photo ibrainyellow -data {
+	    
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtuxuZFv/yAPT59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+LKawvf/9v77/f3+9/r88sK6yvX69Pr+/P39\
+		/vf59wf0I7qxwvz9+9PB2Id9dkBEQScrJVtfWYOEhv789mRXcTo4OykmJY+N\
+		iI2KioOBimdnYOfd5mtsdDQwNCIiKmpna5WTlYKChmRoZVRIYsOu0G5te5WP\
+		kW9xcWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8fMrLyrvAvbatwPz8\
+		+dfJ0ZOFmrCytNfT1szMzL6+vqGfoaOeosrQyIKAhf78/vr+/fv++eLc37ap\
+		uMHDwuLi4s/Pz76/vq6vsL61voB9hPj7+p6Ho7CxsdnZ2aysrL+/v6urq2ln\
+		aubZ6vj8/Ozn8qusr8vLy83NzZqampKSkn9/f8PDwvz59/77+f/8+f38//j7\
+		+fj9+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb29v3/+/v////9+v36///7/Pr+\
+		/vz8+rCwsM7OzqampvHx8f/////+/f/+/MTExK6uruTk5Onp6cLCwt7e3gOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqESH5BAEKAP8ALAAAAAASABIAAAjuAAEEEDCAQIED\
+		BxAgPJBAwQIGDSI6eABhIYKLGA9ImBCRQgWEGENitHAhIoaEIlFeTHggQwMN\
+		IDNazMihg0qEH0CEEDECJUoSKhGUMHECRQoVK2ayuNnCxQsYMWTMoKGyBkuf\
+		Nm7gyKFjBw+VPYIi8PEDSBAhQ4gUWWkEJEgkSZQsYdLEyRMoF6NImUIlZBUr\
+		V7Bk0bKFC8KIDbqo9PIFDJYwYsaQ2VAGsZkzbtGkUbOGTRs3b+AgjiNnDp06\
+		du7gyaNnD58GfRA38PMnCqBAggYRKmToUANEiRTJHt5gkRpGjRAhIk7c0SM8\
+		kGQHBAA7
+	}]
+
+	set greenbrainicon [image create photo ibraingreen -data {
+
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtuxuZFgf0I/T59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+LKawvf/9v77/f3+9/r88sK6yvX69Pr+/P39\
+		/vf597qxwvz9+9PB2Id9dkBEQScrJVtfWYOEhv789mRXcTo4OykmJY+NiI2K\
+		ioOBimdnYOfd5mtsdDQwNCIiKmpna5WTlYKChmRoZVRIYsOu0G5te5WPkW9x\
+		cWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8fMrLyrvAvbatwPz8+dfJ\
+		0ZOFmrCytNfT1szMzL6+vqGfoaOeosrQyIKAhf78/vr+/fv++eLc37apuMHD\
+		wuLi4s/Pz76/vq6vsL61voB9hPj7+p6Ho7CxsdnZ2aysrL+/v6urq2lnaubZ\
+		6vj8/Ozn8qusr8vLy83NzZqampKSkn9/f8PDwvz59/77+f/8+f38//j7+fj9\
+		+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb29v3/+/v////9+v36///7/Pr+/vz8\
+		+rCwsM7OzqampvHx8f/////+/f/+/MTExK6uruTk5Onp6cLCwt7e3gf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0IyH5BAEKAP8ALAAAAAASABIAAAj1AAEEEDCAQAED\
+		BxAcWJhAwQIGDSI6eAAhAoKLGDFKmBCRQoWEGUMisHAhIoaFCUGCvJgyQwMN\
+		GFOiXBhzA4cOMQ94+AAihAiVF0ewVEiihIkTKFKoQHlxBcuFLFq4eAEjhowZ\
+		K2kMRVnDxg0cOXTsWMlDocoePn4ACSJkCBGWRYzIRHAESRIlS5g0cfLkIpQo\
+		UqaspFLFyhUsWbRsWRixAZeVXbx8uQImjJgxCMg0LmOG5oEzaNKoWcOmjZs3\
+		jeHEkTOHTh07d/Dk0bOnAZ/GDfr4gfIHUCBBgwgVMtTgEKJEuJM3UJRmEaND\
+		h5Qrb+ToziPcAQEAOw==
+	}]
+	set bluebrainicon [image create photo ibrainblue -data {
+	    
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtu/97AAAq//T59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+LKawvf/9v77/f3+9/r88sK6yvX69Pr+/P39\
+		/vf597qxwvz9+9PB2Id9dkBEQScrJVtfWYOEhv789mRXcTo4OykmJY+NiI2K\
+		ioOBimdnYOfd5mtsdDQwNCIiKmpna5WTlYKChmRoZVRIYsOu0G5te5WPkW9x\
+		cWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8fMrLyrvAvbatwPz8+dfJ\
+		0ZOFmrCytNfT1szMzL6+vqGfoaOeosrQyIKAhf78/vr+/fv++eLc37apuMHD\
+		wuLi4s/Pz76/vq6vsL61voB9hPj7+p6Ho7CxsdnZ2aysrL+/v6urq2lnaubZ\
+		6vj8/Ozn8qusr8vLy83NzZqampKSkn9/f8PDwvz59/77+f/8+f38//j7+fj9\
+		+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb29v3/+/v////9+v36///7/Pr+/vz8\
+		+rCwsM7OzqampvHx8f/////+/f/+/MTExK6uruTk5Onp6cLCwt7e3gf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0IyH5BAEKAP8ALAAAAAASABIAAAj1AAEEEDCAQAED\
+		BxAcWJhAwQIGDSI6eAAhAoKLGDFKmBCRQoWEGUMisHAhIoaFCUGCvJgyQwMN\
+		GFOiXBhzA4cOMQ94+AAihAiVF0ewVEiihIkTKFKoQHlxBcuFLFq4eAEjhowZ\
+		K2kMRVnDxg0cOXTsWMlDocoePn4ACSJkCBGWRYzIRHAESRIlS5g0cfLkIpQo\
+		UqaspFLFyhUsWbRsWRixAZeVXbx8uQImjJgxCMg0LmOG5oEzaNKoWcOmjZs3\
+		jeHEkTOHTh07d/Dk0bOnAZ/GDfr4gfIHUCBBgwgVMtTgEKJEuJM3UJRmEaND\
+		h5Qrb+ToziPcAQEAOw==
+	}]
+	set lightbluebrainicon [image create photo ibrainlightblue -data {
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtuxj06QAq//T59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+LKawvf/9v77/f3+9/r88sK6yvX69Pr+/P39\
+		/vf597qxwvz9+9PB2Id9dkBEQScrJVtfWYOEhv789mRXcTo4OykmJY+NiI2K\
+		ioOBimdnYOfd5mtsdDQwNCIiKmpna5WTlYKChmRoZVRIYsOu0G5te5WPkW9x\
+		cWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8fMrLyrvAvbatwPz8+dfJ\
+		0ZOFmrCytNfT1szMzL6+vqGfoaOeosrQyIKAhf78/vr+/fv++eLc37apuMHD\
+		wuLi4s/Pz76/vq6vsL61voB9hPj7+p6Ho7CxsdnZ2aysrL+/v6urq2lnaubZ\
+		6vj8/Ozn8qusr8vLy83NzZqampKSkn9/f8PDwvz59/77+f/8+f38//j7+fj9\
+		+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb29v3/+/v////9+v36///7/Pr+/vz8\
+		+rCwsM7OzqampvHx8f/////+/f/+/MTExK6uruTk5Onp6cLCwt7e3v/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yACH5BAEKAP8ALAAAAAASABIAAAj2AAEEEDCAQAED\
+		BxAcWJhAwQIGDSI6eAAhAoKLGDFKmBCRQoWEGTGCtHAhIoaFCUGmvJgyQwMN\
+		IhWiXChyA4cOIg94+AAihAiVF0ewVEiihIkTKFKoQHlxBcuFLFq4eAEjhowZ\
+		IBHQGIqyho0bOHLo2JGVh0yWPXz8ABJEyBAiLIsYSZnwCJIkSpYwaeLkyUUo\
+		UaRMyUqlipUrWLJo2bIwYgMuWbt4+XIFTBgxYxCQcVzGDM0DZ9CkUbOGTRs3\
+		bxzDiSNnDp06du7gyaNnTwM+jhv08QPlD6BAggYRKmSowSFEiXIrb6AozSJG\
+		hw4tX97I0Z1HuQMCADs=
+	    
+	}]
+	set rainbowbrainicon [image create photo ibrainrainbow -data {
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtu4wA//8IAPT59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+LKawgB3//f/9v77/f3+9/r88sK6yvX69Pr+\
+		/AD/CP9lAP39/vf597qxwvz9+9PB2EBEQScrJVtfWYOEhv789jo4OykmJY+N\
+		iI2KioOBimdnYP/2AOfd5v/uADQwNCIiKmpna5WTlYKChmRoZVRIYsOu0P+M\
+		AG5te5WPkW9xcWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8fMrLyrvA\
+		vbatwBH/APz8+dfJ0ZOFmrCytNfT1szMzL6+vqGfoaOeosrQyIKAhf78/vr+\
+		/fv++eLc3/QfGLapuMHDwuLi4s/Pz76/vq6vsL61voB9hAAM//j7+p6Ho7Cx\
+		sdnZ2aysrL+/v6urq2lnagAq/+bZ6vj8/Ozn8qusr8vLy83NzZqampKSkn9/\
+		f8PDwvz59/77+f/8+f38//j7+fj9+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb2\
+		9v3/+/v////9+v36///7/Pr+/vz8+rCwsM7OzqampvHx8f/////+/f/+/MTE\
+		xK6uruTk5Onp6cLCwt7e3hH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ACH5BAEKAP8ALAAAAAASABIAAAj+AAEEEDCAQAED\
+		BxIeQJBAwQIGDSI6eAAhggSFCRFonEAhYgULEkKGVKhR4wUMETNo0CByZEaN\
+		GzZwaNBhJUuRJBHE3ODhAwibN0OIGEEC5s4SQFeaOIEihYoVOmOyaOGiqtUX\
+		MGLImEGjhlQWNqxWvXEDRw4dO3j08MGiLYsfVsneABJEyBAiRYwcQcI3iRIX\
+		cm8sYdLEyRMoUaRM4UulipUrZLFgyaJlC5cuXr6ACRMmYgMxNyRjGUOmDBcz\
+		Z9CkUbPGM5s2bUS7eQMnjpw5dOrY8XwHTx49e/j08fMHUCBBDQZ5bkCoEBVD\
+		hxAlUrSIUaMGjh5BWs69QSQ4kiYMOXLUvTulSn4sLQ8IADs=
+	    
+	}]
+	
+	#A person icon for "Subject" nodes
+	set personicon [image create photo ipersonicon -data {
+	    R0lGODlhEgASAKEAAAAAAP8AAP///wAAACH+FUNyZWF0ZWQgd2l0aCBUaGUg\
+		R0lNUAAsAAAAABIAEgAAAi6UL6CAjZqgeyzKmc6qmG9sSB8YWaS2nNS5AUHQ\
+		NpcLo+SljmyFd0/+YwVBuF4BADs=
+	}]
+
+
+	#Here are a couple arrows
+	#This one has a bend in it
+	set arrowicon2 [image create bitmap iarrow2 -data {          
+	    
+	    #define arrow2_width 16
+	    #define arrow2_height 16
+	    static unsigned char arrow2_bits[] = {
+		0x10, 0x00, 0x18, 0x00, 0xfc, 0x1f, 0xfe, 0x3f, 0xff, 0x3f, 0xfe, 0x3f,
+		0xfc, 0x3f, 0x18, 0x3e, 0x10, 0x3e, 0x00, 0x3e, 0x00, 0x3e, 0x80, 0xff,
+		0x00, 0x7f, 0x00, 0x3e, 0x00, 0x1c, 0x00, 0x08};
+	    
+	    
+    	}]
+	
+	#This one is diagonal
+	set arrowicon [image create bitmap iarrow -data { 
+
+	    #define arrow_width 17
+	    #define arrow_height 17
+	    static char arrow_bits[] = {
+		0x1f,0x00,0x00,0x0f,0x00,0x00,0xcf,0x07,0x00,0x3f,0x08,0x00,0x99,0x13,0x00,
+		0x68,0x24,0x00,0xe4,0x4b,0x00,0xd4,0x57,0x00,0xd4,0x57,0x00,0xd4,0x57,0x00,
+		0xa4,0x4f,0x00,0x48,0x2c,0x00,0x90,0x33,0x01,0x20,0xf8,0x01,0xc0,0xe7,0x01,
+		0x00,0xe0,0x01,0x00,0xf0,0x01,0x00,0x90,0x00,0x00,0x00,0x11,0x00,0x00,0x00,
+		0x48,0x79,0x15,0x08,0x98,0xd8,0x24,0x08 };
+	}]
+
+	#This one is in color and over a green brain
+	set arrowbrain [image create photo iarrowbrain -data {
+	    
+	    R0lGODlhEgASAMYAAAcP8v7+/huZFgf0I/T59/z5+v77/vv+/vf/9v77/cK6\
+		yvX69P39/rqxwvz9+0BEQScrJVtfWYOEhv789o+NiI2KioOBimdnYOfd5mts\
+		dJWTlYKChmRoZVRIYsOu0GVlZVRUVHp2fXxgktXO1oV1hXx8fMrLyrvAvbat\
+		wPz8+dfJ0ZOFmrCytKGfoaOeosrQyIKAhf78/vr+/fv++eLc37apuMHDwq6v\
+		sL61voB9hPj7+p6Ho7CxsdnZ2aurq2lnavj8/Ozn8qusr8vLy83NzcPDwv/8\
+		+f38//j7+fj9+Pz7+fj6+dHNz7y8vMnJyaOjo/v////9+v36///7/Pr+/vz8\
+		+rCwsM7OzqampvHx8cTExK6urunp6cLCwv//////////////////////////\
+		////////////////////////////////////////////////////////////\
+		/////////////////////////////////////////////////ywAAAAAEgAS\
+		AAAHvoAAgoMBAgMCiAQFBgcBAYOCA5KTkwgJjpCUmgMKC5iQhoeUhgIMjwAD\
+		g4iroYcNDqiSgw8QERKhoROSpIMUFRYXq5IYu4gZgxobHB2tHruHiIMfICEi\
+		rSPQuySDJSYnKLspKqSGKyyDLS4vMJIxMjM0rTU2gzc4OQKOjjqtOzw9g3z8\
+		SKUPSBBEh4QMITKoiCB9Ro4gSaJkCZMmTp5AAqAPSpQYUqZQqWLlCpYskPSp\
+		1KeFyJaNK1dy6bIRQCAAOw==
+	} ]
+	
+	set cactusicon [image create photo icactus -data { 
+
+	    R0lGODlhEQARAPcAMf///wR8HAR8JASELASENAyEPASERCSMJCSMLCyUHCSM
+	    NCyUNByMPBSMTByMTFykFFykHEScLFykJEScRDycXEScXDScZESkdFykPFys
+	    VEykbGysJHSsHIy0FHS0NIS0HHy0THy8hJS8FKTEDJTETJzETKTETKzEDKTM
+	    TLTMTJzEVKTMbKTMhKzMVLzMBLzMLMTUJPz89P9oLAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAACH5BAEAADIALAAAAAARABEAAAiWAGUIHEiwoEGB
+	    HhJiMHFw4AsKEgwYEKHgRUMZGBhENMBgQwSLDAm+iHAggkQDGwSYMCAgg0MZ
+	    BxSYlJhyJUqBKRpsSLBgpoEIAjZIBCFQhIEJPH2mbCBxoFGkPU8ubTrwaFKp
+	    Jy0iZLogKk0BHgy+YGDAK0oDDV8IMItBgFaDA2Se5CDg4lqlBt6KjPBgg4K/
+	    Hi8KHhgQADs=
+	    
+	}]
+
+
+
+
+
+	#------------------------------------------------------------------------------------------
+	# End of icon image definitions
+	#------------------------------------------------------------------------------------------
+		
+    };#End of the "create" procedure
+    
+    
+    # Initialize an element of the tree.
+    # Internal use only
+    #
+    proc dfltconfig {w v} {
+	variable Tree
+	set Tree($w:$v:children) {}
+	set Tree($w:$v:open) 0
+	set Tree($w:$v:icon) {}
+	set Tree($w:$v:tags) {}
+	set Tree($w:$v:linecolor) gray50
+    }
+    
+    #
+    # Pass configuration options to the tree widget
+    #
+    proc config {w args} {
+	eval $w config $args
+
+    }
+
+    #Configure a single node of the tree
+    proc nodeconfig {w v args} {
+	foreach {op arg} $args {
+	    switch -exact -- $op {
+		-linecolor {set Tree($w:$v:linecolor) $arg}
+		-image {set Tree($w:$v:icon) $arg}
+		-tags {set Tree($w:$v:tags) $arg}
+	    }
+	}
+    }
+    
+    proc itemexists {w v} {
+	
+	variable Tree
+	
+	if {[info exists Tree($w:$v:open)]} {
+	    return 1
+	} else {return 0}
+
+    }
+
+
+    proc gettreeobjects {w} {
+    	variable Tree
+    	foreach t [array names Tree $w:*] {
+    		lappend n $t
+    	}
+	return $n
+    }
+
+    #
+    # Insert a new element $v into the tree $w.
+    #
+    proc newitem {w v args} {
+	variable Tree
+	set dir [file dirname $v]
+	set n [file tail $v]
+	if {![info exists Tree($w:$dir:open)]} {
+	    error "parent item \"$dir\" is missing"
+	}
+	set i [lsearch -exact $Tree($w:$dir:children) $n]
+	if {$i>=0} {
+	    error "item \"$v\" already exists"
+	}
+	lappend Tree($w:$dir:children) $n
+	set Tree($w:$dir:children) [lsort $Tree($w:$dir:children)]
+	Tree::dfltconfig $w $v
+	foreach {op arg} $args {
+	    switch -exact -- $op {
+		-linecolor {set Tree($w:$v:linecolor) $arg}
+		-image {set Tree($w:$v:icon) $arg}
+		-tags {set Tree($w:$v:tags) $arg}
+	    }
+	}
+	Tree::buildwhenidle $w
+}
+
+#
+# Delete element $v from the tree $w.  If $v is /, then the widget is
+# deleted.
+#
+proc delitem {w v} {
+    variable Tree
+    if {![info exists Tree($w:$v:open)]} return
+    if {[string compare $v /]==0} {
+	# delete the whole widget
+	catch {destroy $w}
+	foreach t [array names Tree $w:*] {
+	    unset Tree($t)
+	}
+    }
+    foreach c $Tree($w:$v:children) {
+	catch {Tree::delitem $w $v/$c}
+    }
+    unset Tree($w:$v:open)
+    unset Tree($w:$v:children)
+    unset Tree($w:$v:icon)
+    set dir [file dirname $v]
+    set n [file tail $v]
+    set i [lsearch -exact $Tree($w:$dir:children) $n]
+    if {$i>=0} {
+	set Tree($w:$dir:children) [lreplace $Tree($w:$dir:children) $i $i]
+    }
+    Tree::buildwhenidle $w
+}
+
+#
+# Change the selection to the indicated item
+#
+proc setselection {w v} {
+    variable Tree
+    set Tree($w:selection) [list $v]
+    Tree::drawselection $w
+}
+
+proc setCurrent {w v} {
+    
+    variable Tree
+    set Tree($w:current) [ list $v ] 
+    Tree::drawCurrent $w 
+}
+
+proc addselection {w v} {
+    variable Tree
+    lappend Tree($w:selection) $v
+    set Tree($w:selection) [ linsert $Tree($w:selection) 0 $v ]
+    Tree::drawselection $w
+}
+
+
+#Accessor method for the name of the element currently selected
+proc getselection {w {option_list 0}} {
+    variable Tree
+    if {[llength $Tree($w:selection)]} {
+	foreach p $Tree($w:selection) {
+	    set q [string last / $p]
+	    if {$q == -1} {lappend result $p} else {
+		lappend result [string range $p [expr $q + 1] end]
+	    }	
+	}
+	if {$option_list == 0} {
+	    return [lindex $result 0]
+	}
+	return $result
+    }
+}
+
+
+#
+# Retrieve the current selection (with fully qualified path name)
+#
+proc getCurrentPath w {
+    variable Tree
+    if {[llength $Tree($w:current)]} {
+	return $Tree($w:current)
+    }
+}
+
+proc getselectionpath w {
+    variable Tree
+    if {[llength $Tree($w:selection)]} {
+	return $Tree($w:selection)
+    }
+}
+
+#
+# Bitmaps used to show which parts of the tree can be opened.
+#
+set maskdata "#define solid_width 9\n#define solid_height 9"
+append maskdata {
+    static unsigned char solid_bits[] = { 
+	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
+	0xff, 0x01, 0xff, 0x01, 0xff, 0x01
+    };
+}
+set data "#define open_width 9\n#define open_height 9"
+append data {
+    static unsigned char open_bits[] = {
+	0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7d, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0xff, 0x01
+    };
+}
+image create bitmap Tree::openbm -data $data -maskdata $maskdata \
+    -foreground black -background white
+set data "#define closed_width 9\n#define closed_height 9"
+append data {
+    static unsigned char closed_bits[] = {
+	0xff, 0x01, 0x01, 0x01, 0x11, 0x01, 0x11, 0x01, 0x7d, 0x01, 0x11, 0x01,
+	0x11, 0x01, 0x01, 0x01, 0xff, 0x01
+    };
+}
+image create bitmap Tree::closedbm -data $data -maskdata $maskdata \
+    -foreground black -background white
+
+# Internal use only.
+# Draw the tree on the canvas
+proc build w {
+    variable Tree
+    $w delete all
+    catch {unset Tree($w:buildpending)}
+    set Tree($w:y) 30
+    Tree::buildlayer $w / 20
+    $w config -scrollregion [$w bbox all]
+    Tree::drawselection $w
+}
+
+# Internal use only.
+# Build a single layer of the tree on the canvas.  Indent by $in pixels
+proc buildlayer {w v in} {
+    variable Tree
+    
+    incr in 5  
+    if {$v=="/"} {
+	set vx {}
+    } else {
+	set vx $v
+    }
+
+    set start [expr $Tree($w:y)-10]
+    foreach c $Tree($w:$v:children) {
+	set y $Tree($w:y)
+	incr Tree($w:y) 19
+	set li($y) [$w create line $in $y [expr $in+15] $y -fill $Tree($w:$vx/$c:linecolor) -width 3]
+	set icon $Tree($w:$vx/$c:icon)
+	set taglist x
+	foreach tag $Tree($w:$vx/$c:tags) {
+	    lappend taglist $tag
+	}
+	set x [expr $in+16]
+	if {[string length $icon]>0} {
+	    set k [$w create image $x $y -image $icon -anchor w -tags $taglist]
+	    incr x 20
+	    set Tree($w:tag:$k) $vx/$c
+	}
+	set j [$w create text $x $y -text $c -font $Tree(font) \
+		   -anchor w -tags $taglist]
+	set Tree($w:tag:$j) $vx/$c
+	set Tree($w:$vx/$c:tag) $j
+	if {[string length $Tree($w:$vx/$c:children)]} {
+	    if {$Tree($w:$vx/$c:open)} {
+		set j [$w create image $in $y -image Tree::openbm]
+		$w bind $j <1> "set {::Tree::Tree($w:$vx/$c:open)} 0; ::Tree::build $w"
+		Tree::buildlayer $w $vx/$c [expr $in+18]
+	    } else {
+		set j [$w create image $in $y -image Tree::closedbm]
+		$w bind $j <1> "set {::Tree::Tree($w:$vx/$c:open)} 1; ::Tree::build $w"
+	    }
+	}
+    }
+
+    set j [$w create line $in $start $in [expr $y+2] -fill gray50 -width 3]
+    $w lower $j
+    foreach index [array names li] {
+	$w lower $li($index) $j
+    }
+}
+
+# Open a branch of a tree
+#
+proc open {w v} {
+  variable Tree
+  if {[info exists Tree($w:$v:open)] && $Tree($w:$v:open)==0
+      && [info exists Tree($w:$v:children)]
+      && [string length $Tree($w:$v:children)]>0} {
+    set Tree($w:$v:open) 1
+    Tree::build $w
+  }
+}
+
+proc close {w v} {
+  variable Tree
+  if {[info exists Tree($w:$v:open)] && $Tree($w:$v:open)==1} {
+    set Tree($w:$v:open) 0
+    Tree::build $w
+  }
+}
+
+proc eraseCurrentBox w {
+    
+    variable Tree
+    
+    if {[llength $Tree($w:selidcurrent)] > 0} {
+	foreach x $Tree($w:selidcurrent) {
+	    $w delete $x
+	}
+    }
+    
+    #unset $Tree($w:selidcurrent)
+    #unset $Tree($w:current)
+}
+
+proc drawCurrent w {
+    
+    variable Tree
+    
+    if {[llength $Tree($w:selidcurrent)] > 0} {
+	foreach x $Tree($w:selidcurrent) {
+	   $w delete $x
+	}
+    }
+
+    foreach v $Tree($w:current) {
+	if {[string length $v]==0} return
+	if {![info exists Tree($w:$v:tag)]} return
+	set bbox [$w bbox $Tree($w:$v:tag)]
+	if {[llength $bbox]==4} {
+	    set i [eval $w create rectangle $bbox -outline black]
+	lappend Tree($w:selidcurrent) $i
+	    $w lower $i
+	} else {
+	    set Tree($w:selidcurrent) {}
+	}
+    }
+ }
+
+
+# Internal use only.
+# Draw the selection highlight
+proc drawselection w {
+    variable Tree
+
+    if {[llength $Tree($w:selidx)] > 0} {
+	foreach x $Tree($w:selidx) {
+	$w delete $x
+	}
+	
+    }
+    
+    foreach v $Tree($w:selection) {
+	if {[string length $v]==0} return
+	if {![info exists Tree($w:$v:tag)]} return
+	set bbox [$w bbox $Tree($w:$v:tag)]
+	if {[llength $bbox]==4} {
+	    set i [eval $w create rectangle $bbox -fill skyblue -outline {{}} ] 
+	    lappend Tree($w:selidx) $i
+	    $w lower $i
+	} else {
+	    set Tree($w:selidx) {}
+	}
+    }
+}
+
+
+
+
+# Internal use only
+# Call Tree::build then next time we're idle
+proc buildwhenidle w {
+  variable Tree
+  if {![info exists Tree($w:buildpending)]} {
+    set Tree($w:buildpending) 1
+    after idle "Tree::build $w"
+  }
+}
+
+#
+# Return the full pathname of the label for widget $w that is located
+# at real coordinates $x, $y
+#
+proc labelat {w x y} {
+  set x [$w canvasx $x]
+  set y [$w canvasy $y]
+  variable Tree
+  foreach m [$w find overlapping $x $y $x $y] {
+    if {[info exists Tree($w:tag:$m)]} {
+      return $Tree($w:tag:$m)
+    }
+  }
+  return ""
+}
+
+}
+########################################################################################
+#				End of Tree Widget Definition			       #
+########################################################################################
+########################################################################################
+########################################################################################
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/biscmdline.tcl b/bioimagesuite30_src/bioimagesuite/base/biscmdline.tcl
new file mode 100644
index 0000000..302cf31
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/biscmdline.tcl
@@ -0,0 +1,950 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# cmdline.tcl --
+#
+#	This package provides a utility for parsing command line
+#	arguments that are processed by our various applications.
+#	It also includes a utility routine to determine the
+#	application name for use in command line errors.
+#
+# Copyright (c) 1998-2000 by Ajuba Solutions.
+# Copyright (c) 2001-2006 by Andreas Kupries <andreas_kupries at users.sf.net>.
+# Copyright (c) 2003      by David N. Welton  <davidw at dedasys.com>
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# 
+# RCS: @(#) $Id: cmdline.tcl,v 1.24 2006/09/28 02:19:20 andreas_kupries Exp $
+# Modified Xenios Papademetris for BioImage Suite Jul 29, 2009
+
+package require Tcl 8.2
+package provide biscmdline 1.3
+
+# ---------------------------------------------------------------------------
+# Added Xenios Papademetris for biscmdline
+# ---------------------------------------------------------------------------
+
+set error_found 0
+proc biserror { argv } {
+    global error_found
+    global vtkpxcontrib_no_load
+    set vtkpxcontrib_no_load 1
+    package require vtkpxcontrib
+    
+
+    set first [ lindex $argv 0 ]
+    set second [ lindex $argv 1 ]
+
+    set line "[ lindex $second 0 ] \#auto"
+    set ok  0
+    catch {
+	set alg [ eval $line ]
+	set ok [$alg GetCmdLineOptionsList]
+	$alg PrintUsage
+	set ok 1
+    }
+    if { $ok > 0 } {
+	if { $first != "help" } {
+	    puts stderr "\n\n------------------------------------------------------\nTHE FOLLOWING ERROR HAS OCCURRED:\n\t Bad flag \"$first\" Specified\n"  
+	}
+	set error_found 1
+	itcl::delete obj $alg
+    }
+
+    puts stderr $argv
+
+    exit
+}
+
+#-----------------------------------------------------
+
+
+
+namespace eval ::biscmdline {
+    namespace export getArgv0 getopt getKnownOpt getfiles getoptions \
+	    getKnownOptions usage
+}
+
+# ::biscmdline::getopt --
+#
+#	The cmdline::getopt works in a fashion like the standard
+#	C based getopt function.  Given an option string and a 
+#	pointer to an array or args this command will process the
+#	first argument and return info on how to proceed.
+#
+# Arguments:
+#	argvVar		Name of the argv list that you
+#			want to process.  If options are found the
+#			arg list is modified and the processed arguments
+#			are removed from the start of the list.
+#	optstring	A list of command options that the application
+#			will accept.  If the option ends in ".arg" the
+#			getopt routine will use the next argument as 
+#			an argument to the option.  Otherwise the option	
+#			is a boolean that is set to 1 if present.
+#	optVar		The variable pointed to by optVar
+#			contains the option that was found (without the
+#			leading '-' and without the .arg extension).
+#	valVar		Upon success, the variable pointed to by valVar
+#			contains the value for the specified option.
+#			This value comes from the command line for .arg
+#			options, otherwise the value is 1.
+#			If getopt fails, the valVar is filled with an
+#			error message.
+#
+# Results:
+# 	The getopt function returns 1 if an option was found, 0 if no more
+# 	options were found, and -1 if an error occurred.
+
+proc ::biscmdline::getopt {argvVar optstring optVar valVar} {
+    upvar 1 $argvVar argsList
+    upvar 1 $optVar option
+    upvar 1 $valVar value
+
+    set result [getKnownOpt argsList $optstring option value]
+
+    if {$result < 0} {
+        # Collapse unknown-option error into any-other-error result.
+        set result -1
+    }
+    return  $result 
+}
+
+# ::biscmdline::getKnownOpt --
+#
+#	The cmdline::getKnownOpt works in a fashion like the standard
+#	C based getopt function.  Given an option string and a 
+#	pointer to an array or args this command will process the
+#	first argument and return info on how to proceed.
+#
+# Arguments:
+#	argvVar		Name of the argv list that you
+#			want to process.  If options are found the
+#			arg list is modified and the processed arguments
+#			are removed from the start of the list.  Note that
+#			unknown options and the args that follow them are
+#			left in this list.
+#	optstring	A list of command options that the application
+#			will accept.  If the option ends in ".arg" the
+#			getopt routine will use the next argument as 
+#			an argument to the option.  Otherwise the option	
+#			is a boolean that is set to 1 if present.
+#	optVar		The variable pointed to by optVar
+#			contains the option that was found (without the
+#			leading '-' and without the .arg extension).
+#	valVar		Upon success, the variable pointed to by valVar
+#			contains the value for the specified option.
+#			This value comes from the command line for .arg
+#			options, otherwise the value is 1.
+#			If getopt fails, the valVar is filled with an
+#			error message.
+#
+# Results:
+# 	The getKnownOpt function returns 1 if an option was found,
+#	0 if no more options were found, -1 if an unknown option was
+#	encountered, and -2 if any other error occurred. 
+
+proc ::biscmdline::getKnownOpt {argvVar optstring optVar valVar} {
+    upvar 1 $argvVar argsList
+    upvar 1 $optVar  option
+    upvar 1 $valVar  value
+
+    # default settings for a normal return
+    set value ""
+    set option ""
+    set result 0
+
+    # check if we're past the end of the args list
+    if {[llength $argsList] != 0} {
+
+	# if we got -- or an option that doesn't begin with -, return (skipping
+	# the --).  otherwise process the option arg.
+	switch -glob -- [set arg [lindex $argsList 0]] {
+	    "--" {
+		set argsList [lrange $argsList 1 end]
+	    }
+
+	    "-*" {
+		set option [string range $arg 1 end]
+
+		if {[lsearch -exact $optstring $option] != -1} {
+		    # Booleans are set to 1 when present
+		    set value 1
+		    set result 1
+		    set argsList [lrange $argsList 1 end]
+		} elseif {[lsearch -exact $optstring "$option.arg"] != -1} {
+		    set result 1
+		    set argsList [lrange $argsList 1 end]
+		    if {[llength $argsList] != 0} {
+			set value [lindex $argsList 0]
+			set argsList [lrange $argsList 1 end]
+		    } else {
+			set value "Option \"$option\" requires an argument"
+			set result -2
+		    }
+		} else {
+		    # Unknown option.
+		    set value "Illegal option \"-$option\""
+		    set result -1
+		}
+	    }
+	    default {
+		# Skip ahead
+	    }
+	}
+    }
+
+    return $result
+}
+
+# ::biscmdline::getoptions --
+#
+#	Process a set of command line options, filling in defaults
+#	for those not specified.  This also generates an error message
+#	that lists the allowed flags if an incorrect flag is specified.
+#
+# Arguments:
+#	arglistVar	The name of the argument list, typically argv.
+#			We remove all known options and their args from it.
+#	optlist		A list-of-lists where each element specifies an option
+#			in the form:
+#				(where flag takes no argument) 
+#					flag comment 
+#
+#				(or where flag takes an argument) 
+#					flag default comment
+#
+#			If flag ends in ".arg" then the value is taken from the
+#			command line. Otherwise it is a boolean and appears in
+#			the result if present on the command line. If flag ends
+#			in ".secret", it will not be displayed in the usage.
+#	usage		Text to include in the usage display. Defaults to
+#			"options:"
+#
+# Results
+#	Name value pairs suitable for using with array set.
+
+proc ::biscmdline::getoptions {arglistVar optlist {usage options:}} {
+    upvar 1 $arglistVar argv
+
+    set opts [GetOptionDefaults $optlist result]
+
+    set argc [llength $argv]
+    while {[set err [getopt argv $opts opt arg]]} {
+	if {$err < 0} {
+            set result(?) ""
+            break
+	}
+	set result($opt) $arg
+    }
+    if {[info exist result(?)] || [info exists result(help)]} {
+	error "\"$opt\" [usage $optlist $usage]"
+    }
+    return [array get result]
+}
+
+# ::biscmdline::getKnownOptions --
+#
+#	Process a set of command line options, filling in defaults
+#	for those not specified.  This ignores unknown flags, but generates
+#	an error message that lists the correct usage if a known option
+#	is used incorrectly.
+#
+# Arguments:
+#	arglistVar	The name of the argument list, typically argv.  This
+#			We remove all known options and their args from it.
+#	optlist		A list-of-lists where each element specifies an option
+#			in the form:
+#				flag default comment
+#			If flag ends in ".arg" then the value is taken from the
+#			command line. Otherwise it is a boolean and appears in
+#			the result if present on the command line. If flag ends
+#			in ".secret", it will not be displayed in the usage.
+#	usage		Text to include in the usage display. Defaults to
+#			"options:"
+#
+# Results
+#	Name value pairs suitable for using with array set.
+
+proc ::biscmdline::getKnownOptions {arglistVar optlist {usage options:}} {
+    upvar 1 $arglistVar argv
+
+    set opts [GetOptionDefaults $optlist result]
+
+    # As we encounter them, keep the unknown options and their
+    # arguments in this list.  Before we return from this procedure,
+    # we'll prepend these args to the argList so that the application
+    # doesn't lose them.
+
+    set unknownOptions [list]
+
+    set argc [llength $argv]
+    while {[set err [getKnownOpt argv $opts opt arg]]} {
+	if {$err == -1} {
+            # Unknown option.
+
+            # Skip over any non-option items that follow it.
+            # For now, add them to the list of unknownOptions.
+            lappend unknownOptions [lindex $argv 0]
+            set argv [lrange $argv 1 end]
+            while {([llength $argv] != 0) \
+                    && ![string match "-*" [lindex $argv 0]]} {
+                lappend unknownOptions [lindex $argv 0]
+                set argv [lrange $argv 1 end]
+            }
+	} elseif {$err == -2} {
+            set result(?) ""
+            break
+        } else {
+            set result($opt) $arg
+        }
+    }
+
+    # Before returning, prepend the any unknown args back onto the
+    # argList so that the application doesn't lose them.
+    set argv [concat $unknownOptions $argv]
+
+    if {[info exist result(?)] || [info exists result(help)]} {
+	error [usage $optlist $usage]
+    }
+    return [array get result]
+}
+
+# ::biscmdline::GetOptionDefaults --
+#
+#	This internal procedure processes the option list (that was passed to
+#	the getopt or getKnownOpt procedure).  The defaultArray gets an index
+#	for each option in the option list, the value of which is the option's
+#	default value.
+#
+# Arguments:
+#	optlist		A list-of-lists where each element specifies an option
+#			in the form:
+#				flag default comment
+#			If flag ends in ".arg" then the value is taken from the
+#			command line. Otherwise it is a boolean and appears in
+#			the result if present on the command line. If flag ends
+#			in ".secret", it will not be displayed in the usage.
+#	defaultArrayVar	The name of the array in which to put argument defaults.
+#
+# Results
+#	Name value pairs suitable for using with array set.
+
+proc ::biscmdline::GetOptionDefaults {optlist defaultArrayVar} {
+    upvar 1 $defaultArrayVar result
+
+    set opts { }
+    foreach opt $optlist {
+	set name [lindex $opt 0]
+	if {[regsub -- .secret$ $name {} name] == 1} {
+	    # Need to hide this from the usage display and getopt
+	}   
+	lappend opts $name
+	if {[regsub -- .arg$ $name {} name] == 1} {
+
+	    # Set defaults for those that take values.
+
+	    set default [lindex $opt 1]
+	    set result($name) $default
+	} else {
+	    # The default for booleans is false
+	    set result($name) 0
+	}
+    }
+    return $opts
+}
+
+# ::biscmdline::usage --
+#
+#	Generate an error message that lists the allowed flags.
+#
+# Arguments:
+#	optlist		As for cmdline::getoptions
+#	usage		Text to include in the usage display. Defaults to
+#			"options:"
+#
+# Results
+#	A formatted usage message
+
+proc ::biscmdline::usage {optlist {usage {options:}}} {
+    set str "[getArgv0] $usage\n"
+    foreach opt [concat $optlist \
+	    {{help "Print this message"} {? "Print this message"}}] {
+	set name [lindex $opt 0]
+	if {[regsub -- .secret$ $name {} name] == 1} {
+	    # Hidden option
+	    continue
+	}
+	if {[regsub -- .arg$ $name {} name] == 1} {
+	    set default [lindex $opt 1]
+	    set comment [lindex $opt 2]
+	    append str [format " %-20s %s <%s>\n" "-$name value" \
+		    $comment $default]
+	} else {
+	    set comment [lindex $opt 1]
+	    append str [format " %-20s %s\n" "-$name" $comment]
+	}
+    }
+    return $str
+}
+
+# ::biscmdline::getfiles --
+#
+#	Given a list of file arguments from the command line, compute
+#	the set of valid files.  On windows, file globbing is performed
+#	on each argument.  On Unix, only file existence is tested.  If
+#	a file argument produces no valid files, a warning is optionally
+#	generated.
+#
+#	This code also uses the full path for each file.  If not
+#	given it prepends [pwd] to the filename.  This ensures that
+#	these files will never conflict with files in our zip file.
+#
+# Arguments:
+#	patterns	The file patterns specified by the user.
+#	quiet		If this flag is set, no warnings will be generated.
+#
+# Results:
+#	Returns the list of files that match the input patterns.
+
+proc ::biscmdline::getfiles {patterns quiet} {
+    set result {}
+    if {$::tcl_platform(platform) == "windows"} {
+	foreach pattern $patterns {
+	    set pat [file join $pattern]
+	    set files [glob -nocomplain -- $pat]
+	    if {$files == {}} {
+		if {! $quiet} {
+		    puts stdout "warning: no files match \"$pattern\""
+		}
+	    } else {
+		foreach file $files {
+		    lappend result $file
+		}
+	    }
+	}
+    } else {
+	set result $patterns
+    }
+    set files {}
+    foreach file $result {
+	# Make file an absolute path so that we will never conflict
+	# with files that might be contained in our zip file.
+	set fullPath [file join [pwd] $file]
+	
+	if {[file isfile $fullPath]} {
+	    lappend files $fullPath
+	} elseif {! $quiet} {
+	    puts stdout "warning: no files match \"$file\""
+	}
+    }
+    return $files
+}
+
+# ::biscmdline::getArgv0 --
+#
+#	This command returns the "sanitized" version of argv0.  It will strip
+#	off the leading path and remove the ".bin" extensions that our apps
+#	use because they must be wrapped by a shell script.
+#
+# Arguments:
+#	None.
+#
+# Results:
+#	The application name that can be used in error messages.
+
+proc ::biscmdline::getArgv0 {} {
+    global argv0
+
+    set name [file tail $argv0]
+    return [file rootname $name]
+}
+
+##
+# ### ### ### ######### ######### #########
+##
+# Now the typed versions of the above commands.
+##
+# ### ### ### ######### ######### #########
+##
+
+# typedCmdline.tcl --
+#
+#    This package provides a utility for parsing typed command
+#    line arguments that may be processed by various applications.
+#
+# Copyright (c) 2000 by Ross Palmer Mohn.
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# 
+# RCS: @(#) $Id: cmdline.tcl,v 1.24 2006/09/28 02:19:20 andreas_kupries Exp $
+
+namespace eval ::biscmdline {
+    namespace export typedGetopt typedGetoptions typedUsage
+
+    # variable cmdline::charclasses --
+    #
+    #    Create regexp list of allowable character classes
+    #    from "string is" error message.
+    #
+    # Results:
+    #    String of character class names separated by "|" characters.
+
+    variable charclasses
+    catch {string is . .} charclasses
+    regexp -- {must be (.+)$} $charclasses dummy charclasses
+    regsub -all -- {, (or )?} $charclasses {|} charclasses
+
+}
+
+# ::biscmdline::typedGetopt --
+#
+#	The cmdline::typedGetopt works in a fashion like the standard
+#	C based getopt function.  Given an option string and a
+#	pointer to a list of args this command will process the
+#	first argument and return info on how to proceed. In addition,
+#	you may specify a type for the argument to each option.
+#
+# Arguments:
+#	argvVar		Name of the argv list that you want to process.
+#			If options are found, the arg list is modified
+#			and the processed arguments are removed from the
+#			start of the list.
+#
+#	optstring	A list of command options that the application
+#			will accept.  If the option ends in ".xxx", where
+#			xxx is any valid character class to the tcl
+#			command "string is", then typedGetopt routine will
+#			use the next argument as a typed argument to the
+#			option. The argument must match the specified
+#			character classes (e.g. integer, double, boolean,
+#			xdigit, etc.). Alternatively, you may specify
+#			".arg" for an untyped argument.
+#
+#	optVar		Upon success, the variable pointed to by optVar
+#			contains the option that was found (without the
+#			leading '-' and without the .xxx extension).  If
+#			typedGetopt fails the variable is set to the empty
+#			string. SOMETIMES! Different for each -value!
+#
+#	argVar		Upon success, the variable pointed to by argVar
+#			contains the argument for the specified option.
+#			If typedGetopt fails, the variable is filled with
+#			an error message.
+#
+# Argument type syntax:
+#	Option that takes no argument.
+#		foo
+#
+#	Option that takes a typeless argument.
+#		foo.arg
+#
+#	Option that takes a typed argument. Allowable types are all
+#	valid character classes to the tcl command "string is".
+#	Currently must be one of alnum, alpha, ascii, control,
+#	boolean, digit, double, false, graph, integer, lower, print,
+#	punct, space, true, upper, wordchar, or xdigit.
+#		foo.double
+#
+#	Option that takes an argument from a list.
+#		foo.(bar|blat)
+#
+# Argument quantifier syntax:
+#	Option that takes an optional argument.
+#		foo.arg?
+#
+#	Option that takes a list of arguments terminated by "--".
+#		foo.arg+
+#
+#	Option that takes an optional list of arguments terminated by "--".
+#		foo.arg*
+#
+#	Argument quantifiers work on all argument types, so, for
+#	example, the following is a valid option specification.
+#		foo.(bar|blat|blah)?
+#
+# Argument syntax miscellany:
+#	Options may be specified on the command line using a unique,
+#	shortened version of the option name. Given that program foo
+#	has an option list of {bar.alpha blah.arg blat.double},
+#	"foo -b fob" returns an error, but "foo -ba fob"
+#	successfully returns {bar fob}
+#
+# Results:
+#	The typedGetopt function returns one of the following:
+#	 1	a valid option was found
+#	 0	no more options found to process
+#	-1	invalid option
+#	-2	missing argument to a valid option
+#	-3	argument to a valid option does not match type
+#
+# Known Bugs:
+#	When using options which include special glob characters,
+#	you must use the exact option. Abbreviating it can cause
+#	an error in the "cmdline::prefixSearch" procedure.
+
+proc ::biscmdline::typedGetopt {argvVar optstring optVar argVar} {
+    variable charclasses
+
+    upvar $argvVar argsList
+
+    upvar $optVar retvar
+    upvar $argVar optarg
+
+    # default settings for a normal return
+    set optarg ""
+    set retvar ""
+    set retval 0
+
+    # check if we're past the end of the args list
+    if {[llength $argsList] != 0} {
+
+        # if we got -- or an option that doesn't begin with -, return (skipping
+        # the --).  otherwise process the option arg.
+        switch -glob -- [set arg [lindex $argsList 0]] {
+            "--" {
+                set argsList [lrange $argsList 1 end]
+            }
+
+            "-*" {
+                # Create list of options without their argument extensions
+
+                set optstr ""
+                foreach str $optstring {
+                    lappend optstr [file rootname $str]
+                }
+
+                set _opt [string range $arg 1 end]
+
+                set i [prefixSearch $optstr [file rootname $_opt]]
+                if {$i != -1} {
+                    set opt [lindex $optstring $i]
+
+                    set quantifier "none"
+                    if {[regexp -- {\.[^.]+([?+*])$} $opt dummy quantifier]} {
+                        set opt [string range $opt 0 end-1]
+                    }
+
+                    if {[string first . $opt] == -1} {
+                        set retval 1
+                        set retvar $opt
+                        set argsList [lrange $argsList 1 end]
+
+                    } elseif {[regexp -- "\\.(arg|$charclasses)\$" $opt dummy charclass]
+                            || [regexp -- {\.\(([^)]+)\)} $opt dummy charclass]} {
+				if {[string equal arg $charclass]} {
+                            set type arg
+			} elseif {[regexp -- "^($charclasses)\$" $charclass]} {
+                            set type class
+                        } else {
+                            set type oneof
+                        }
+
+                        set argsList [lrange $argsList 1 end]
+                        set opt [file rootname $opt]
+
+                        while {1} {
+                            if {[llength $argsList] == 0
+                                    || [string equal "--" [lindex $argsList 0]]} {
+                                if {[string equal "--" [lindex $argsList 0]]} {
+                                    set argsList [lrange $argsList 1 end]
+                                }
+
+                                set oneof ""
+                                if {$type == "arg"} {
+                                    set charclass an
+                                } elseif {$type == "oneof"} {
+                                    set oneof ", one of $charclass"
+                                    set charclass an
+                                }
+    
+                                if {$quantifier == "?"} {
+                                    set retval 1
+                                    set retvar $opt
+                                    set optarg ""
+                                } elseif {$quantifier == "+"} {
+                                    set retvar $opt
+                                    if {[llength $optarg] < 1} {
+                                        set retval -2
+                                        set optarg "Option requires at least one $charclass argument$oneof -- $opt"
+                                    } else {
+                                        set retval 1
+                                    }
+                                } elseif {$quantifier == "*"} {
+                                    set retval 1
+                                    set retvar $opt
+                                } else {
+                                    set optarg "Option requires $charclass argument$oneof -- $opt"
+                                    set retvar $opt
+                                    set retval -2
+                                }
+                                set quantifier ""
+                            } elseif {($type == "arg")
+                                    || (($type == "oneof")
+                                    && [string first "|[lindex $argsList 0]|" "|$charclass|"] != -1)
+                                    || (($type == "class")
+                                    && [string is $charclass [lindex $argsList 0]])} {
+                                set retval 1
+                                set retvar $opt
+                                lappend optarg [lindex $argsList 0]
+                                set argsList [lrange $argsList 1 end]
+                            } else {
+                                set oneof ""
+                                if {$type == "arg"} {
+                                    set charclass an
+                                } elseif {$type == "oneof"} {
+                                    set oneof ", one of $charclass"
+                                    set charclass an
+                                }
+                                set optarg "Option requires $charclass argument$oneof -- $opt"
+                                set retvar $opt
+                                set retval -3
+    
+                                if {$quantifier == "?"} {
+                                    set retval 1
+                                    set optarg ""
+                                }
+                                set quantifier ""
+                            }
+                             if {![regexp -- {[+*]} $quantifier]} {
+                                break;
+                            }
+                        }
+                    } else {
+                        error "Illegal option type specification:\
+                                must be one of $charclasses"
+                    }
+                } else {
+                    set optarg "Illegal option -- $_opt"
+                    set retvar $_opt
+                    set retval -1
+                }
+            }
+	    default {
+		# Skip ahead
+	    }
+        }
+    }
+
+    return $retval
+}
+
+# ::biscmdline::typedGetoptions --
+#
+#	Process a set of command line options, filling in defaults
+#	for those not specified. This also generates an error message
+#	that lists the allowed options if an incorrect option is
+#	specified.
+#
+# Arguments:
+#	arglistVar	The name of the argument list, typically argv
+#	optlist		A list-of-lists where each element specifies an option
+#			in the form:
+#
+#				option default comment
+#
+#			Options formatting is as described for the optstring
+#			argument of typedGetopt. Default is for optionally
+#			specifying a default value. Comment is for optionally
+#			specifying a comment for the usage display. The
+#			options "-help" and "-?" are automatically included
+#			in optlist.
+#
+# Argument syntax miscellany:
+#	Options formatting and syntax is as described in typedGetopt.
+#	There are two additional suffixes that may be applied when
+#	passing options to typedGetoptions.
+#
+#	You may add ".multi" as a suffix to any option. For options
+#	that take an argument, this means that the option may be used
+#	more than once on the command line and that each additional
+#	argument will be appended to a list, which is then returned
+#	to the application.
+#		foo.double.multi
+#
+#	If a non-argument option is specified as ".multi", it is
+#	toggled on and off for each time it is used on the command
+#	line.
+#		foo.multi
+#
+#	If an option specification does not contain the ".multi"
+#	suffix, it is not an error to use an option more than once.
+#	In this case, the behavior for options with arguments is that
+#	the last argument is the one that will be returned. For
+#	options that do not take arguments, using them more than once
+#	has no additional effect.
+#
+#	Options may also be hidden from the usage display by
+#	appending the suffix ".secret" to any option specification.
+#	Please note that the ".secret" suffix must be the last suffix,
+#	after any argument type specification and ".multi" suffix.
+#		foo.xdigit.multi.secret
+#
+# Results
+#	Name value pairs suitable for using with array set.
+
+proc ::biscmdline::typedGetoptions {arglistVar optlist {usage options:}} {
+    variable charclasses
+
+    upvar 1 $arglistVar argv
+
+    set opts {? help}
+    foreach opt $optlist {
+        set name [lindex $opt 0]
+        if {[regsub -- {\.secret$} $name {} name] == 1} {
+            # Remove this extension before passing to typedGetopt.
+        }
+        if {[regsub -- {\.multi$} $name {} name] == 1} {
+            # Remove this extension before passing to typedGetopt.
+
+            regsub -- {\..*$} $name {} temp
+            set multi($temp) 1
+        }
+        lappend opts $name
+        if {[regsub -- "\\.(arg|$charclasses|\\(.+).?\$" $name {} name] == 1} {
+            # Set defaults for those that take values.
+            # Booleans are set just by being present, or not
+
+            set dflt [lindex $opt 1]
+            if {$dflt != {}} {
+                set defaults($name) $dflt
+            }
+        }
+    }
+    set argc [llength $argv]
+    while {[set err [typedGetopt argv $opts opt arg]]} {
+        if {$err == 1} {
+            if {[info exists result($opt)]
+                    && [info exists multi($opt)]} {
+                # Toggle boolean options or append new arguments
+
+                if {$arg == ""} {
+                    unset result($opt)
+                } else {
+                    set result($opt) "$result($opt) $arg"
+                }
+            } else {
+                set result($opt) "$arg"
+            }
+        } elseif {($err == -1) || ($err == -3)} {
+            error [typedUsage $optlist $usage]
+        } elseif {$err == -2 && ![info exists defaults($opt)]} {
+            error [typedUsage $optlist $usage]
+        }
+    }
+    if {[info exists result(?)] || [info exists result(help)]} {
+        error [typedUsage $optlist $usage]
+    }
+    foreach {opt dflt} [array get defaults] {
+        if {![info exists result($opt)]} {
+            set result($opt) $dflt
+        }
+    }
+    return [array get result]
+}
+
+# ::biscmdline::typedUsage --
+#
+#	Generate an error message that lists the allowed flags,
+#	type of argument taken (if any), default value (if any),
+#	and an optional description.
+#
+# Arguments:
+#	optlist		As for cmdline::typedGetoptions
+#
+# Results
+#	A formatted usage message
+
+proc ::biscmdline::typedUsage {optlist {usage {options:}}} {
+    variable charclasses
+
+    set str "[getArgv0] $usage\n"
+    foreach opt [concat $optlist \
+            {{help "Print this message"} {? "Print this message"}}] {
+        set name [lindex $opt 0]
+        if {[regsub -- {\.secret$} $name {} name] == 1} {
+            # Hidden option
+
+        } else {
+            if {[regsub -- {\.multi$} $name {} name] == 1} {
+                # Display something about multiple options
+            }
+
+            if {[regexp -- "\\.(arg|$charclasses)\$" $name dummy charclass]
+                    || [regexp -- {\.\(([^)]+)\)} $opt dummy charclass]} {
+                   regsub -- "\\..+\$" $name {} name
+                set comment [lindex $opt 2]
+                set default "<[lindex $opt 1]>"
+                if {$default == "<>"} {
+                    set default ""
+                }
+                append str [format " %-20s %s %s\n" "-$name $charclass" \
+                        $comment $default]
+            } else {
+                set comment [lindex $opt 1]
+		append str [format " %-20s %s\n" "-$name" $comment]
+            }
+        }
+    }
+    return $str
+}
+
+# ::biscmdline::prefixSearch --
+#
+#	Search a Tcl list for a pattern; searches first for an exact match,
+#	and if that fails, for a unique prefix that matches the pattern 
+#	(i.e, first "lsearch -exact", then "lsearch -glob $pattern*"
+#
+# Arguments:
+#	list		list of words
+#	pattern		word to search for
+#
+# Results:
+#	Index of found word is returned. If no exact match or
+#	unique short version is found then -1 is returned.
+
+proc ::biscmdline::prefixSearch {list pattern} {
+    # Check for an exact match
+
+    if {[set pos [::lsearch -exact $list $pattern]] > -1} {
+        return $pos
+    }
+
+    # Check for a unique short version
+
+    set slist [lsort $list]
+    if {[set pos [::lsearch -glob $slist $pattern*]] > -1} {
+        # What if there is nothing for the check variable?
+
+        set check [lindex $slist [expr {$pos + 1}]]
+        if {[string first $pattern $check] != 0} {
+            return [::lsearch -exact $list [lindex $slist $pos]]
+        }
+    }
+    return -1
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/feedbackplus.tcl b/bioimagesuite30_src/bioimagesuite/base/feedbackplus.tcl
new file mode 100644
index 0000000..69b36ee
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/feedbackplus.tcl
@@ -0,0 +1,128 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide feedbackplus 1.0
+package require Iwidgets
+
+# Derives from iwidgets::feedback
+
+# ------------------------------------------------------------------
+#                          FEEDBACKPLUS
+# ------------------------------------------------------------------
+option add *Feedbackplus.borderWidth	2		widgetDefault
+option add *Feedbackplus.labelPos		n		widgetDefault
+option add *Feedbackplus.barHeight		20		widgetDefault
+option add *Feedbackplus.troughColor	White		widgetDefault
+option add *Feedbackplus.barColor		Blue	        widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Feedbackplus {
+    keep -background -cursor -foreground
+}
+
+# ------------------------------------------------------------------
+#                          FEEDBACKPLUS
+# ------------------------------------------------------------------
+itcl::class iwidgets::Feedbackplus {
+    inherit iwidgets::Feedback
+
+    constructor {args} {}
+    destructor {}
+
+    public {
+	method setval { val }
+    }
+
+    private {
+	method _display
+	variable _barwidth 0
+	variable _stepval 0
+    }
+
+}
+
+#
+# Provide a lowercased access method for the Dialogshell class.
+# 
+proc ::iwidgets::feedbackplus {pathName args} {
+    uplevel ::iwidgets::Feedbackplus $pathName $args
+}
+
+# ------------------------------------------------------------------
+#                        CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Feedbackplus::constructor {args} {
+
+    pack $itk_component(bar) -side left -padx 2 -pady 0
+    pack $itk_component(percentage) -side right -padx 2 -pady 0
+    pack $itk_component(trough) -side left -fill both -expand true  -pady 0
+    bind $itk_component(hull) <Configure> [itcl::code $this _display]
+    eval itk_initialize $args
+}
+
+# -----------------------------------------------------------------------------
+# PROTECTED METHOD: _display 
+#
+# Displays the bar in the trough with the width set using the current number
+# of steps.
+# -----------------------------------------------------------------------------
+itcl::body iwidgets::Feedbackplus::_display {} {
+    update idletasks
+    set troughwidth [winfo width $itk_component(trough)]
+    set _barwidth [expr {
+      (1.0*$troughwidth-(2.0*[$itk_component(trough) cget -borderwidth])) /
+      $itk_option(-steps)}]
+    set fraction [expr {int((1.0*$_stepval)/$itk_option(-steps)*100.0)}]
+
+    $itk_component(percentage) config -text "$fraction%"
+    $itk_component(bar) config -width [expr {$_barwidth*$_stepval}]
+
+    update
+}
+
+# ------------------------------------------------------------------
+
+# ------------------------------------------------------------------
+#                          DESTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Feedbackplus::destructor {} {
+}
+
+
+itcl::body iwidgets::Feedbackplus::setval { val } {
+
+    set _stepval $val
+    if { $_stepval < 0 } {
+	set _stepval 0
+    } elseif {$_stepval >= $itk_option(-steps)} {
+	set _stepval $itk_option(-steps)
+    }
+    _display 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/labelframe.tcl b/bioimagesuite30_src/bioimagesuite/base/labelframe.tcl
new file mode 100644
index 0000000..9b2a77c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/labelframe.tcl
@@ -0,0 +1,51 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# A Labeled Frame widget for Tcl/Tk
+# $Revision: 1.1 $
+#
+
+
+package provide labelframe 1.0
+
+
+package require Tk 8.0
+package require Itcl
+package require Iwidgets
+
+ proc LabelFrame:create { w args } {
+ 
+     iwidgets::Labeledframe $w -labelpos nw
+     foreach { tag value } $args {
+	 switch -- $tag {
+	     -text { $w configure -labeltext "$value" }
+	     -width { [ $w childsite ] configure -width $value }
+	 }
+     }
+     return [ $w childsite ]
+ }
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pkgIndex.tcl b/bioimagesuite30_src/bioimagesuite/base/pkgIndex.tcl
new file mode 100644
index 0000000..4c4a1ea
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pkgIndex.tcl
@@ -0,0 +1,73 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# Tcl package index file, version 1.1
+# This file is generated by the "pkg_mkIndex" command
+# and sourced either when an application starts up or
+
+
+
+
+# by a "package unknown" script.  It invokes the
+# "package ifneeded" command to set up package-related
+# information so that packages will be loaded automatically
+# in response to "package require" commands.  When this
+# script is sourced, the variable $dir must contain the
+# full path name of this file's directory.
+
+package ifneeded labelframe 1.0 [list source [file join $dir labelframe.tcl]]
+package ifneeded feedbackplus 1.0 [list source [file join $dir feedbackplus.tcl]]
+package ifneeded pxtclbrukerheader 1.0 [list source [file join $dir pxtclbrukerheader.tcl]]
+package ifneeded pxtclhelp 1.0 [list source [file join $dir pxtclhelp.tcl]]
+package ifneeded pxtclreadsprheader 1.0 [list source [file join $dir pxtclreadsprheader.tcl]]
+package ifneeded pxtclreadvarianheader 1.0 [list source [file join $dir pxtclreadvarianheader.tcl]]
+
+package ifneeded pxtcluserprefs 1.0 [list source [file join $dir pxtcluserprefs.tcl]]
+package ifneeded pxtclutil 1.0 [list source [file join $dir pxtclutil.tcl]]
+package ifneeded pxvtable 1.0 [list source [file join $dir pxvtable.tcl]]
+package ifneeded pxtclruncommand 1.0 [list source [file join $dir pxtclruncommand.tcl]]
+package ifneeded vtkImageInclude 1.0 [list source [file join $dir vtkImageInclude.tcl]]
+package ifneeded vtkpxcontrib 1.2 [list source [file join $dir vtkpxcontrib.tcl]]
+package ifneeded biscmdline 1.0 [list source [file join $dir biscmdline.tcl]]
+package ifneeded vtknrcontrib 1.1 [list source [file join $dir vtknrcontrib.tcl]]
+package ifneeded vtkfemlib 1.0 [list source [file join $dir vtkfemlib.tcl]]
+package ifneeded VisTree 3.0   [list source [file join $dir VisTree3.tcl]]
+
+
+# Core Objects moved here from main
+# ----------------------------------
+package ifneeded pxitclobject         1.0 [list source [file join $dir pxitclobject.tcl]] 
+package ifneeded pxitclimage         1.0 [list source [file join $dir pxitclimage.tcl]] 
+package ifneeded pxitclsurface         1.0 [list source [file join $dir pxitclsurface.tcl]] 
+package ifneeded pxitcllandmarks         1.0 [list source [file join $dir pxitcllandmarks.tcl]] 
+package ifneeded pxitclelectrodemultigrid         1.0 [list source [file join $dir pxitclelectrodemultigrid.tcl]] 
+package ifneeded pxitcltransform     1.0 [list source [file join $dir pxitcltransform.tcl]] 
+package ifneeded pxitclmesh         1.0 [list source [file join $dir pxitclmesh.tcl]] 
+package ifneeded pxitclcamera     1.0 [list source [file join $dir pxitclcamera.tcl]] 
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxitclcamera.tcl b/bioimagesuite30_src/bioimagesuite/base/pxitclcamera.tcl
new file mode 100644
index 0000000..666950e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxitclcamera.tcl
@@ -0,0 +1,448 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclcamera 1.0
+
+# 	$Id: pxitclcamera.tcl,v 1.1 2002/07/19 22:17:02 papad Exp papad $	
+
+
+
+
+
+package require pxitclobject 1.0
+# -------------------------------------------------------------------
+# Definition of pxitclcamera
+#
+#    a class that encapsulates a camera and its filename
+# -------------------------------------------------------------------
+
+itcl::class pxitclcamera {
+
+    inherit pxitclobject
+
+    public variable camera 0 
+    public variable delay 1.0
+    public variable volclipvalues { -1 -1 -1 -1 -1 -1 }
+    public variable polyclipvalues { -1 -1 -1 -1 -1 -1 }
+    constructor { } {
+	pxitclobject::constructor 
+    } {
+	set camera [ vtkCamera [ pxvtable::vnewobj ]]
+	$camera ParallelProjectionOn
+	set filename "None"
+    }
+
+    destructor  { $camera Delete  }
+
+
+    # --- begin method def -----
+
+
+    
+    public method GetObject { } { return $camera }
+    public method GetType { } { return [ $camera GetClassName ]} 
+    public method GetDescriptionPiece { lst fmt } 
+    public method GetDescription { } 
+    public method UpdateStatus { } 
+    public method Copy    { obj }
+    public method Clear   { }
+    public method Load { args }
+    public method LoadStream { fout { mode "new" } }
+    public method Save { args }
+    public method SaveStream { fout }
+
+    # Methods additional to pxitclobject
+    public method GetCamera { } { return $camera }
+    public method CopyCamera { obj }
+    # --- end method def -----
+}
+
+# ------------------- End of Header ---------------------------------
+itcl::body pxitclcamera::Copy   { obj  } {
+
+    if { [ $obj isa pxitclcamera ] == 0 } {
+	return 0
+    }
+    
+    CopyCamera  [ $obj GetCamera ]  
+    set filename [ $obj cget -filename ] 
+    set delay    [ $obj cget -delay ]
+    set volclipvalues [ $obj cget -volclipvalues ]
+    set polyclipvalues [ $obj cget -polyclipvalues ]
+    return 1
+}
+# ----------------------------------------------------------
+itcl::body pxitclcamera::CopyCamera { oldcamera  } {
+    
+    set thistype "[ $camera GetClassName ]"
+    if { [ $oldcamera IsA $thistype ] == 0 } {
+	return
+    }
+
+    set ren [ vtkpxGUIRenderer [ pxvtable::vnewobj ] ]
+    $ren CopyCamera $camera $oldcamera
+    $ren Delete
+}
+# ----------------------------------------------------------
+itcl::body pxitclcamera::GetDescriptionPiece { lst fmt } {
+
+    set a ""
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	set a [ format "%s $fmt" $a [ lindex $lst $i ] ]
+    }
+    return $a
+}
+
+
+itcl::body pxitclcamera::GetDescription { } {
+    
+    set line ""
+    set line "Position : [ $this GetDescriptionPiece [ $camera GetPosition ] "%.0f" ] , FP = [ $this GetDescriptionPiece [ $camera GetFocalPoint ] "%.0f" ]"
+    set line "$line\nScale : [ $camera GetParallelScale ] (Parallel = [ $camera GetParallelProjection ])"
+    set line "$line\nView Up : [ $this GetDescriptionPiece [ $camera GetViewUp ] "%.2f" ]"
+    set line "$line ClipRange : [ $this GetDescriptionPiece [ $camera GetClippingRange ] "%.1f" ]\nDuration = $delay"
+    set line "$line\nVolClip  : [ $this GetDescriptionPiece $volclipvalues  "%.0f" ]"
+    set line "$line\nPolyClip : [ $this GetDescriptionPiece $polyclipvalues "%.0f" ]"
+    return $line 
+}
+# ----------------------------------------------------------
+itcl::body pxitclcamera::Load { args } {
+    
+    set len [ llength $args ]
+    if { [ string length $filename ] == 0 && $len == 0 } { return    }
+
+
+    if { $len > 0 } {
+	set f [ lindex $args 0 ]
+    }  else {
+	set f $filename
+    }
+
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    } else {
+	set desc "Camera"
+    }
+
+    if { [ string length $f ] < 1 } { 
+	set typelist { 
+	    {"Camera File" {.cmf}} 
+	    {"All Files" {*}}}
+	
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set f [tk_getOpenFile -title "Load $desc" -initialfile $f2tail -filetypes $typelist -initialdir $f2path]
+    }
+
+    if { [string length $f ] < 2 || $f=="identity" } {
+	return 0;
+    }
+    
+    set filename  $f
+    set fin [ open $filename r ]
+    gets $fin line
+    if { [ string trim $line  ] == "\#Camera File"  } {
+	set ok [ LoadStream $fin old ]
+    }
+    close $fin
+    return $ok
+
+}
+# ----------------------------------------------------------
+itcl::body pxitclcamera::LoadStream { fin { mode "new" } } {
+
+    if { $mode == "old" } {
+	gets $fin line
+	scan $line "%f %f %f %f %f %f %f %f %f %f %f %f %f %f " fx fy fz px py pz nx ny nz cf cb pp parscale dl
+	set volclipvalues { -1 -1 -1 -1 -1 -1 }
+	set polyclipvalues { -1 -1 -1 -1 -1 -1 }
+	set dl 1.0
+    } else {
+	gets $fin line
+
+        scan $line "%f %f %f %f %f %f %f %f %f %f %f %f %f %f" \
+	    fx fy fz px py pz nx ny nz cf cb pp parscale dl
+
+	gets $fin line
+
+	scan $line " %f %f %f %f %f %f %f %f %f %f %f %f" \
+	    c1 c2 c3 c4 c5 c6 p1 p2 p3 p4 p5 p6
+
+
+
+	set volclipvalues  [ list $c1 $c2 $c3 $c4 $c5 $c6 ]
+	set polyclipvalues [ list $p1 $p2 $p3 $p4 $p5 $p6 ]
+    }
+    $camera SetFocalPoint $fx $fy $fz
+    $camera SetPosition   $px $py $pz
+    $camera SetViewUp     $nx $ny $nz
+    $camera ComputeViewPlaneNormal
+    $camera SetClippingRange     $cf $cb
+    $camera SetParallelProjection [ expr round($pp) ]
+    $camera SetParallelScale $parscale
+    set delay $dl
+    return 1
+}
+# ----------------------------------------------------------
+itcl::body pxitclcamera::Save { args } {
+
+    set f     ""
+    set desc "Camera"
+    
+    
+    if { [ llength $args ] > 0 } {
+	set f [ lindex $args 0 ]
+    } 
+    if { [ llength $args ] > 1 } { 
+	set desc [ lindex $args 1 ]
+    }
+
+    if { [ string length $f ] < 1 } { 
+	set f1 $filename  
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set f  [tk_getSaveFile -title "Saving $desc" -initialfile $f1tail -initialdir $f1path -filetypes { {"Camera Files" {.cml}} } ]
+    }
+
+    if { [string length $f ] < 0 } {
+	return 0
+    }
+    set filename  $f
+    set fout [ open $filename $w ]
+    puts $fout "\#Camera File"
+    $this SaveStream $fout
+    close $fout
+    return 1
+}
+
+itcl::body pxitclcamera::SaveStream { fout } {
+
+    scan  "[ $camera GetFocalPoint ]" "%f %f %f" fx fy fz
+    scan  "[ $camera GetPosition   ]" "%f %f %f" px py pz
+    scan  "[ $camera GetViewUp ]"     "%f %f %f" nx ny nz
+    scan  "[ $camera GetClippingRange ]" "%f %f" cf cb
+    scan  "[ $camera GetParallelProjection ]" "%f" pp
+    scan  "[ $camera GetParallelScale ]" "%f" parscale
+    set a [ format "%.1f %.1f %.1f %.1f %.1f %.1f" [ lindex $volclipvalues 0 ] \
+		[ lindex $volclipvalues 1 ] [ lindex $volclipvalues 2 ] \
+		[ lindex $volclipvalues 3 ] [ lindex $volclipvalues 4 ] [ lindex $volclipvalues 5 ] ]
+
+    set b [ format "%.1f %.1f %.1f %.1f %.1f %.1f" [ lindex $polyclipvalues 0 ] \
+		[ lindex $polyclipvalues 1 ] [ lindex $polyclipvalues 2 ] \
+		[ lindex $polyclipvalues 3 ] [ lindex $polyclipvalues 4 ] [ lindex $polyclipvalues 5 ] ]
+
+    
+    puts $fout [ format "%.1f %.1f %.1f \t %.1f %.1f %.1f \t %.3f %.3f %.3f \t %.1f %.1f \t %.0f %.1f \t %.1f\n\t $a\t $b" \
+		     $fx $fy $fz $px $py $pz $nx $ny $nz $cf $cb $pp $parscale $delay ]
+
+#    puts -nonewline $fout "[ $camera GetFocalPoint ]"
+#    puts -nonewline $fout "\t[ $camera GetPosition   ]"
+#    puts -nonewline $fout "\t[ $camera GetViewUp ]"
+#    puts -nonewline $fout "\t[ $camera GetClippingRange ]"
+#    puts -nonewline $fout "\t[ $camera GetParallelProjection ]"
+#    puts -nonewline $fout "\t[ $camera GetParallelScale ]"
+#    puts $fout "\t$delay"
+}
+# ----------------------------------------------------------
+itcl::body pxitclcamera::Clear { } {
+
+    $camera SetFocalPoint 0 0 0 
+    $camera SetPosition  0 0 0 
+    $camera SetViewUp   0 1 0
+    $camera ComputeViewPlaneNormal
+    $camera SetParallelProjection 1
+    $camera SetParallelScale 1.0
+    $camera SetClippingRange 0 1
+    set     volclipvalues { -1 -1 -1 -1 -1 -1 }
+    set     polyclipvalues { -1 -1 -1 -1 -1 -1 }
+    set filename "identity"
+}
+
+# ----------------------------------------------------------
+#  GUI for pxitclcamera
+# ----------------------------------------------------------
+
+itcl::class pxitclcameraGUI {
+
+    inherit pxitclobjectGUI
+
+
+    constructor { } {
+	pxitclobjectGUI::constructor
+    } { 
+	set thisparam($this,status) "vtkCamera"
+	set thisparam($this,shortfilename) None
+	set thisparam($this,delaytime) 0
+	set  description "Camera"
+	set  filename "identity.cml"
+	set  numlines 8
+	Reset
+    }
+
+    destructor { }
+
+    public    method Initialize { basewidg } 
+    public    method GetCamera { } { return $itclobject  }
+    public    method SetCamera { tr } 
+    public    method Update { }
+    public    method UpdateDelay { }
+    protected method CreateNewObject { } 
+    public method SetObject { tr } { return [ $this SetCamera $tr ] }
+
+}
+# ----------------------------------------------------------
+itcl::body pxitclcameraGUI::CreateNewObject { } {
+
+    set itclobject  [ [  pxitclcamera \#auto ] GetThisPointer ]
+}
+
+
+
+itcl::body pxitclcameraGUI::SetCamera { trn } {
+    
+    set continue 0
+    
+    catch { 
+	if { [ $trn isa pxitclcamera ] == 1 } {
+	set  continue 1
+	}
+    }
+
+    if { $continue == 0 } {
+	return 0 
+    }
+	
+	
+    if { $owns_object == 1} {
+	catch { itcl::delete object $itclobject }
+    }
+
+    set itclobject $trn
+    
+    set owns_object 0
+    Update
+}
+
+itcl::body pxitclcameraGUI::Initialize { basewidg } {
+
+    if { $initialized == 1 } { return $basewidget }
+    
+    pxitclobjectGUI::Initialize $basewidg
+    set thisparam($this,delaytime) 2.0
+    iwidgets::entryfield $buttonbar.del -labeltext Duration:  -width 7 -validate real -textvariable [ itcl::scope thisparam($this,delaytime) ] -relief sunken
+    eval "button $buttonbar.in -text \"Update\" -command {  $this UpdateDelay }"
+    pack $buttonbar.del  $buttonbar.in  -side left -fill x -expand f
+    pack forget $statusbar
+    $thisparam($this,descriptionbox) configure -width 45
+    Update
+    return $basewidget
+}
+
+itcl::body pxitclcameraGUI::UpdateDelay {  } {
+
+    set d $thisparam($this,delaytime)
+    if { $d < 0.1 } { set d 0.1 } 
+    if { $d > 20.0 } { set d 20.0 }
+    set thisparam($this,delaytime) $d
+
+    $itclobject configure -delay $thisparam($this,delaytime)
+    $this Update
+}
+
+itcl::body pxitclcameraGUI::Update { } {
+    set thisparam($this,delaytime) [ $itclobject cget -delay ]
+    pxitclobjectGUI::Update
+}
+# ----------------------------------------------------------
+#  GUI for multiple camera object
+# ----------------------------------------------------------
+itcl::class pxitclmultiCameraGUI {
+
+    inherit pxitclmultiObjectGUI
+
+    constructor { } {
+	pxitclmultiObjectGUI::constructor
+    } {
+	set description "Camera Control"
+	set enableupdown 1
+    }
+    
+    destructor { }
+    
+    public    method Initialize { basewidg } 
+
+    public    method AddCamera { descr }
+    public    method SetCamera { index } 
+    public    method GetCamera { index } { return [ GetObject $index ] }
+    public    method DeleteCamera { index } { DeleteObject $index }
+
+    protected method CreateNewObject { }
+    protected method CreateNewObjectGUI { widget }
+
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclmultiCameraGUI::CreateNewObject { } {
+    
+    return [ [  pxitclcamera \#auto ] GetThisPointer ]
+}
+
+itcl::body pxitclmultiCameraGUI::CreateNewObjectGUI { widget } {
+    set itclcameraGUI [ [ pxitclcameraGUI \#auto ] GetThisPointer ]
+    pack [ $itclcameraGUI Initialize $widget.[ pxvtable::vnewobj ] ] -side left -fill x
+    return $itclcameraGUI
+}
+
+itcl::body pxitclmultiCameraGUI::AddCamera { descr } {
+    
+    set newobj [ $this AddObject $descr ]
+    set index [ expr [ llength $itclobjectlist ] -1 ]
+    $this SetCamera $index
+    return $newobj
+}
+
+itcl::body pxitclmultiCameraGUI::SetCamera { index } {
+
+    $this SetObject $index
+    $objectGUI Update
+}
+
+itcl::body pxitclmultiCameraGUI::Initialize { basewidg } {
+    
+    if { $initialized == 1 } { 
+	return $basewidget 
+    }
+    
+    pxitclmultiObjectGUI::Initialize $basewidg
+
+    $listbox configure -selectmode single -exportselection 0
+    set initialized 1
+    
+    return $basewidget
+}
+ 
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxitclelectrodemultigrid.tcl b/bioimagesuite30_src/bioimagesuite/base/pxitclelectrodemultigrid.tcl
new file mode 100644
index 0000000..52bedbc
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxitclelectrodemultigrid.tcl
@@ -0,0 +1,378 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclelectrodemultigrid 1.0
+
+# 	$Id: pxitclelectrodemultigrid.tcl,v 1.2 2003/08/14 17:49:42 xenios Exp xenios $	
+
+
+
+
+package require  pxitclobject  1.0
+
+
+# -------------------------------------------------------------------
+# Definition of pxitclelectrodemultigrid
+#
+#    a class that encapsulates an image (vtkImageData)
+#            its orientation , filename and status
+# -------------------------------------------------------------------
+
+itcl::class pxitclelectrodemultigrid {
+
+    inherit pxitclobject
+
+    # --- begin variable def -----
+
+    public variable status 
+    protected variable multigrid 
+
+    # --- end of variable def -----
+
+    constructor { } {
+	pxitclobject::constructor 
+    } {
+	CreateNewElectrodeMultiGrid
+	UpdateStatus    
+    }
+
+    destructor  { $multigrid Delete     }
+
+
+    # --- begin method def -----
+    public method GetObject { } { return $multigrid }
+    public method GetType { } { return [ $multigrid GetNumberOfGrids ] }
+    public method GetDescription { } 
+    public method UpdateStatus { } { set status [ $multigrid GetNumberOfGrids ]  }
+    public method Copy   { obj args }
+    public method CopyElectrodeMultiGrid   { obj }
+    public method Clear { } 
+    public method UnLoad { } { return [ Clear ] }
+
+    public method Load   { args }
+    public method Save   { args }
+
+    # Methods additional to pxitclobject
+    
+    public method GetElectrodeMultiGrid { } { return $multigrid }
+
+    public method GetLongDescription { } 
+    public method GetShortDescription { } 
+    public method GetElectrodeMultiGridSize { } 
+    public method GetSize { } { return [ $this GetElectrodeMultiGridSize ] }
+
+
+    # Extra Stuff for Display
+    public method GetGridNamesList { } 
+    public method GetDisplayedGridNamesList { }
+    public method SetGridNamesToDisplay { lst }
+    public method SetLabelGap { gap }
+    public method SetJustShowElectrodes { justshow }
+
+
+    public method CreateNewElectrodeMultiGrid { } 
+
+    # Procedures to Just Set Filename
+    public method Browse { description }
+
+
+    # Procedures to Ship To Viewer and Transform
+    public method Display { electrodecontrol }
+    public method Transform { gen }
+
+
+
+    # --- end method def -----
+}
+
+# ------------------- End of Header ---------------------------------
+itcl::body pxitclelectrodemultigrid::CreateNewElectrodeMultiGrid { } {
+
+    set multigrid [ vtkpxElectrodeMultiGridSource [ pxvtable::vnewobj ]]
+}
+
+
+itcl::body pxitclelectrodemultigrid::Copy   { obj args } {
+
+    if { [ $obj isa pxitclelectrodemultigrid ] == 0 } {
+#	puts stderr "not copying ..."
+	return 0
+    }
+
+    
+
+    set oldimg [ $obj GetElectrodeMultiGrid ] 
+    CopyElectrodeMultiGrid $oldimg 
+    set filename    [ $obj cget -filename ]
+    UpdateStatus
+}
+# ----------------------------------------------------------
+itcl::body pxitclelectrodemultigrid::CopyElectrodeMultiGrid { newimg  } {
+
+    if { [ $newimg IsA "vtkpxElectrodeMultiGridSource" ] == 0 } {
+	puts stdout "Bad Input"
+	return
+    }
+
+    $multigrid Delete
+    set multigrid [ vtkpxElectrodeMultiGridSource [ pxvtable::vnewobj ]]
+    $multigrid Copy $newimg
+    UpdateStatus
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclelectrodemultigrid::Clear { } {
+    catch { $multigrid Delete }
+    CreateNewElectrodeMultiGrid
+    set orientation 0
+    set filename    ""
+    UpdateStatus
+}
+# ----------------------------------------------------------
+itcl::body pxitclelectrodemultigrid::GetElectrodeMultiGridSize { } {
+
+    return [ $multigrid GetNumberOfGrids ]
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclelectrodemultigrid::GetGridNamesList { }  {
+    
+    set ng [ $multigrid GetNumberOfGrids ]
+    set lst ""
+
+    for { set i 0 } { $i < $ng } { incr i } {
+	set grid [ $multigrid GetElectrodeGrid $i ]
+	set nm [ $grid GetGridName ]
+	set p [ expr $i + 1 ]
+	lappend lst "${nm}.${p}"
+    }
+ #   puts stderr "names list=$lst"
+    return $lst
+}
+# ----------------------------------------------------------
+itcl::body pxitclelectrodemultigrid::GetDisplayedGridNamesList { } {
+    set ng [ $multigrid GetNumberOfGrids ]
+    set lst ""
+    for { set i 0 } { $i < $ng } { incr i } {
+	set grid [ $multigrid GetElectrodeGrid $i ]
+	set nm [ $grid GetGridName ]
+	set v [ $grid GetVisible ]
+	set p [ expr $i + 1 ]
+	if { $v > 0 } {
+	    lappend lst "${nm}.${p}"
+	}
+    }
+#    puts stderr "display names list=$lst"
+    return $lst
+}
+
+itcl::body pxitclelectrodemultigrid::SetGridNamesToDisplay { lst } {
+
+#    puts stderr "lst=$lst"
+ 
+    set ng [ $multigrid GetNumberOfGrids ]
+    for { set i 0 } { $i < $ng } { incr i } {
+	set vis($i) 0
+    }
+
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	set lname [ lindex $lst $i ]
+	set v [ file extension $lname ]
+	if { [ string length $v ] > 1 } {
+	    set ind [ expr  [ string range $v 1 end ] -1 ]
+	    if { $ind >= 0 && $ind < $ng } {
+		set vis($ind) 1
+	    }
+	}
+    }
+
+    set sum 0
+
+    for { set i 0 } { $i < $ng } { incr i } {
+	set grid [ $multigrid GetElectrodeGrid $i ]
+	$grid SetVisible $vis($i)
+	if { $vis($i) > 0 } {
+	    $grid Modified
+	    incr sum
+	}
+    }
+
+ #   puts stderr "Numbers of visible = $sum"
+    if { $sum > 0 } {
+	$multigrid Modified
+    }
+
+}
+
+itcl::body pxitclelectrodemultigrid::SetJustShowElectrodes { justshow } {
+    
+    set ng [ $multigrid GetNumberOfGrids ]
+    for { set i 0 } { $i < $ng } { incr i } {
+	set grid [ $multigrid GetElectrodeGrid $i ]
+	$grid SetJustShowElectrodes [ expr $justshow > 0 ]
+	$grid Modified
+    }
+
+}
+
+
+
+itcl::body pxitclelectrodemultigrid::SetLabelGap { gap } {
+    if { $gap <0 } {
+	return 
+    }
+    $multigrid ShowLabelsGap $gap
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclelectrodemultigrid::GetLongDescription { } {
+    
+    set x1 [ $multigrid GetNumberOfGrids ] 
+    
+    set line [ format "Number Of Grids %d " $x1 ]
+
+    set line  "name=$this\n\t$line\n\tFilename= $filename"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitclelectrodemultigrid::GetDescription { } {
+    
+    set x1 [ $multigrid GetNumberOfGrids ] 
+    set line [ format "Number Of Grids %d" $x1 ]
+    set line  "$line\nFilename=$filename\n"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitclelectrodemultigrid::GetShortDescription { } {
+    
+    set x1 [ $multigrid GetNumberOfGrids ] 
+    set line [ format "Number Of Grids %d" $x1  ]
+    set line  "[ file tail $filename]  $line"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitclelectrodemultigrid::Browse { description } {
+
+    set f2path [ file dirname $filename ]
+    set f2tail [ file tail    $filename ]
+	
+    set fname  [tk_getOpenFile -title "Get Filename for $description" -filetypes { {"Electrode Grid Files" {.mgrid}}} -initialfile $f2tail -initialdir $f2path ]   
+    if { [ string length $fname ] > 0 } {
+	set filename $fname
+	return 1
+    }
+    return 0
+}
+# ----------------------------------------------------------
+itcl::body pxitclelectrodemultigrid::Load { args } {
+
+    set len [ llength $args ]
+    if { [ string length $filename ] == 0 && $len == 0 } { return  }
+
+
+    if { $len < 1 } {
+	set fname $filename
+    } else  { 
+	set fname [ lindex $args 0 ] 
+    }
+
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    } else {
+	set desc "Electrode Grids"
+    }
+
+
+    if { [ string length $fname ] == 0 } {
+
+
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getOpenFile -title "Load $desc" -filetypes { {"ElectrodeMultiGrid Files" {.mgrid}}} -initialfile $f2tail -initialdir $f2path ]   
+    }
+    
+
+    if { [ string length $fname ] <1 } {
+	return 0
+    }
+
+    set ok [ $multigrid Load $fname ]
+    if { $ok > 0 } {
+	$this configure -filename $fname
+    }
+}
+# ----------------------------------------------------------
+itcl::body pxitclelectrodemultigrid::Save { args } {
+
+    set len [ llength $args ]
+    if { $len < 1 } {
+	set fname $filename
+    } else  { 
+	set fname [ lindex $args 0 ] 
+    }
+
+    set desc "Electrode Grid"
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    }
+
+
+    if { [ string length $fname ] == 0 } {
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getSaveFile -title "Saving $desc" -filetypes { {"ElectrodeMultiGrid Files" {.mgrid}}} -initialfile $f2tail -initialdir $f2path ]   
+    }
+    
+    if { [ string length $fname ] > 0 } {
+	$multigrid Save $fname
+	set filename $fname
+    }
+}
+# ----------------------------------------------------------
+itcl::body pxitclelectrodemultigrid::Display { electrodecontrol } {
+
+    if { [ $electrodecontrol isa pxitclElectrodeMultiControl ] == 0 } {
+	::pxtclutil::Warning "Bad electrodecontrol ($electrodecontrol) Specified. Cannot display landmarks\n"
+	return 0
+    }
+    [ $electrodecontrol GetMultiGrid ] Copy $multigrid
+    $electrodecontrol SetLastFilename $filename
+    $electrodecontrol DisableElectrodePropertySheet
+    $electrodecontrol UpdateInterface
+    $electrodecontrol SelectElectrodeGrid 0
+
+    return 1
+
+}
+
+itcl::body pxitclelectrodemultigrid::Transform { gen } {
+    
+    set ok [ $multigrid ApplyTransformation $gen 1 ]
+    return $ok
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxitclimage.tcl b/bioimagesuite30_src/bioimagesuite/base/pxitclimage.tcl
new file mode 100644
index 0000000..975b524
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxitclimage.tcl
@@ -0,0 +1,1847 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclimage 1.0
+
+# 	$Id: pxitclimage.tcl,v 1.2 2003/08/14 17:49:42 xenios Exp xenios $	
+
+
+
+
+package require  pxitclobject  1.0
+package require  pxtcluserprefs 1.0
+package require pxtclreadvarianheader
+
+# -------------------------------------------------------------------
+# Definition of pxitclimage
+#
+#    a class that encapsulates an image (vtkImageData)
+#            its imageheader (vtkbisImageHeader) , filename and status
+# -------------------------------------------------------------------
+
+itcl::class pxitclimage {
+
+    inherit pxitclobject
+
+    # --- begin variable def -----
+
+    public variable status 
+    protected variable img  0
+    protected variable lookuptable 0
+    protected  variable imageheader 0
+    protected  common forceoutputformat 0
+    public     variable lastdicomlist ""
+    public     common forcebioimagesuitecoordinates 1
+    
+    # --- end of variable def -----
+
+    constructor { } {
+	pxitclobject::constructor 
+    } {
+	CreateNewImage
+	UpdateStatus    
+    }
+
+    destructor  { $img Delete     }
+
+
+    # --- begin method def -----
+    public method GetObject { } { return $img }
+    public method GetType { } { return [ $img GetDimensions ] }
+    public method GetDescription { } 
+    public method UpdateStatus { } { set status [ $img GetDimensions ]  }
+    public method Copy   { obj args }
+    public method Clear { } 
+    public method UnLoad { } { return [ Clear ] }
+
+    # args  1=filename 2=description 3=parent object (save 4=force analyze)
+    public method Load      { args }
+    public method LoadDICOM { fname { petcenter 1 } { parobj 0 } }
+    public method LoadVarian { fname  { parobj 0 } { flipdti 0 } }
+    public method ISPETDICOM { fname }
+    public method Save      { args }
+
+
+    # mode = 0 auto, 1= force analyze, 2 = force nifti (.hdr/.img)
+    public method SetOutputFormat { mode }
+
+    public method LoadLookupTable { cname }
+    public method SaveLookupTable { cname }
+    public method CreateLookupTable { }
+
+    # Methods additional to pxitclobject
+    
+    public method GetImage { } { return $img }
+    public method GetImageHeader { } { return $imageheader }
+    public method GetLookupTable { } { return $lookuptable }
+    public method SetLookupTable { cmap } 
+
+    public method AddComment { cmt } { [ $this GetImageHeader ] AddComment $cmt 0 }
+
+    public method GetLongDescription { } 
+    public method GetShortDescription { } 
+    public method GetSize { } { return [ $this GetImageSize ] }
+    public method GetImageSize { } 
+    public method IsSameDisplaySize { other } 
+
+
+    public method DeepCopyImage    { newimg } { CopyImage $newimg 1    }
+    public method ShallowCopyImage { newimg } { CopyImage $newimg 0    }
+    public method CopyImage   { newimg mode }
+    public method CopyImageHeader  { newheader }
+    public method CopyImageHeaderAndFixImage  { newheader }
+
+    public method GetOrientation { }
+    public method GetIntensityScale { }
+    public method GetIntensityOffset { }
+    public method SetOrientationDirect { ori } 
+    public method GetOrientationName { }
+    public method SetFromAnalyzeSource { ana }
+    public method SetFromAnalyzeSourceOld { ana }
+    public method CreateNewImage { } 
+
+    # Procedures to Just Set Filename
+    public method Browse { description }
+
+    # Common Complex Image Processing Routines
+    public method FlipImage { mode }
+
+    # Static Method to Get Image List types
+    public proc GetImageTypeList { mode } 
+
+    # Does Image Exist on Disk
+    public method DoesImageExistOnDisk { } 
+    public method SplitFileName { } 
+
+    # Compare with FileName
+    public method CompareTo  { fname { thr 0.001 } }
+    public method CorrelateWith  { fname { thr 0.9 } }
+
+    # --- end method def -----
+}
+
+# ------------------- End of Header ---------------------------------
+
+itcl::body pxitclimage::SplitFileName { } {
+
+    if { $filename == "" } {
+	return 0
+    }
+
+    set ext [ file extension $fname ]
+    set ext2 ""
+    if { $ext == ".gz" } {
+	set fname [ file rootname $fname ]
+	set ext   [ file extension $fname ]
+	set ext2 ".gz"
+    }
+
+    return [ list $fname ${ext}${ext2} ]
+}
+
+# ---------------------------------------------------------------------
+
+itcl::body pxitclimage::DoesImageExistOnDisk { } {
+
+    if { $filename == "" } {
+	return 0
+    }
+
+    set fname $filename
+
+    set ext [ file extension $fname ]
+    if { $ext == ".gz" } {
+	set fname [ file rootname $fname ]
+	set ext   [ file extension $fname ]
+    }
+
+    if { $ext == ".nii"  || $ext == ".vt" || $ext == ".vtk" } {
+	if { [ file exists $fname ] == 1 || [ file exists ${fname}.gz ] ==1 } {
+	    return 1
+	}
+    }
+    
+    set f1 $fname
+    set f2 [ file rootname $fname].img
+
+    set a1 0;
+    set s2 0;
+    if { [ file exists $f1 ] || [ file exists ${f1}.gz ] } {
+	set a1 1
+    }
+
+    if { [ file exists $f2 ] || [ file exists ${f2}.gz ] } {
+	set a2 1
+    }
+
+    if { $a1 == 1 && $a2 ==1 } {
+	return 1
+    }
+    return 0
+}
+
+
+
+itcl::body pxitclimage::GetImageTypeList { mode } {
+
+    global pxtcl_pref_array
+    
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+
+    if { $mode == "save" } {
+	return $typelist
+    }
+
+    set r 0
+    catch { 
+	set r [ vtkbisDICOMReader New ]
+	lappend typelist {"DICOM Files" {.dcm *.DCM}}
+	$r Delete
+    }
+    
+    lappend typelist {"Varian Files" {.fdf *.FDF}}
+	
+    if { $pxtcl_pref_array(MincImageFormat) == "Enabled" } {
+	lappend typelist {"MINC Files" {.mnc}}
+    }
+    
+    lappend typelist {"VTK Files" {.vt*}}
+    lappend typelist {"All Files" {*}}
+    return $typelist
+}
+
+itcl::body pxitclimage::CreateNewImage { } {
+
+    catch { $img Delete }
+
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+    $img SetDimensions 1 1 1
+    $img SetWholeExtent 0 0 0 0 0 0
+    $img SetExtent 0 0 0 0 0 0
+    $img AllocateScalars
+
+    catch { $imageheader Delete }
+    set imageheader [ vtkbisImageHeader [ pxvtable::vnewobj ]]
+    $imageheader  CreateHeader $img 0
+
+}
+
+# mode = 0 auto, 1= force analyze, 2 = force nifti (.hdr/.img)
+itcl::body pxitclimage::SetOutputFormat { mode } {
+    if { $mode < 0 || $mode > 2 } {
+	return $fourceoutputformat
+    }
+    set forceoutputformat $mode
+    set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+    $anaw SetForceOutputFileFormat $forceoutputformat
+    $anaw Delete
+
+    return $forceoutputformat
+}
+
+itcl::body pxitclimage::Copy   { obj args } {
+
+    set ispxitclimage 0
+    catch { if { [ $obj isa pxitclimage ] == 1 } {set ispxitclimage 1  } }
+    if { $ispxitclimage  == 0 } { return }
+
+    set mode 0
+    if { [ llength $args ] > 0 } {
+	set mode [ expr [ lindex $args 0 ] > 0 ]
+    }
+
+    set oldimg [ $obj GetImage ] 
+    CopyImage $oldimg $mode
+    SetLookupTable [ $obj GetLookupTable ]
+    set filename    [ $obj cget -filename ]
+    $this CopyImageHeader [ $obj GetImageHeader ]
+    
+    UpdateStatus
+}
+# ----------------------------------------------------------
+itcl::body pxitclimage::CopyImage { newimg mode } {
+
+    set isimagedata 0
+    catch {
+	if { [ $newimg IsA "vtkImageData" ] == 1 } {
+	    set isimagedata 1
+	}
+    }
+    if { $isimagedata == 0 } {return  }
+
+    set mode [ expr $mode > 0 ]
+
+
+    catch { $img Delete }
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+
+    scan [ $newimg GetDimensions ] "%d %d %d" x1 y1 z1
+    set x1 [ expr $x1 - 1]
+    set y1 [ expr $y1 - 1]
+    set z1 [ expr $z1 - 1]
+
+    if { $mode == 0 } {
+	$img ShallowCopy $newimg
+    } else {
+	$img DeepCopy $newimg
+    }
+    $imageheader ReconcileHeader $img 0
+    UpdateStatus
+}
+
+
+itcl::body pxitclimage::CopyImageHeader { newheader } {
+
+    set isimageheader 0
+    catch {
+	if { [ $newheader IsA "vtkbisImageHeader" ] == 1 } {
+	    set isimageheader 1
+	}
+    }
+    if { $isimageheader == 0 } { return }
+
+    $imageheader CopyHeader $newheader 
+    $imageheader ReconcileHeader $img 0
+    $this UpdateStatus
+}
+
+itcl::body pxitclimage::CopyImageHeaderAndFixImage { newheader } {
+
+    set isimageheader 0
+    catch {
+	if { [ $newheader IsA "vtkbisImageHeader" ] == 1 } {
+	    set isimageheader 1
+	}
+    }
+    if { $isimageheader == 0 } { return }
+
+    $imageheader CopyHeader $newheader 
+    $imageheader ReconcileImage $img 0
+    $imageheader ReconcileHeader $img 0
+    $this UpdateStatus
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclimage::Clear { } {
+    catch { $img Delete }
+    CreateNewImage
+    set filename    ""
+    UpdateStatus
+}
+# ----------------------------------------------------------
+itcl::body pxitclimage::SetOrientationDirect { ori } {
+    if { $ori <0 || $ori > 3 } {
+	return
+    }
+    
+    $imageheader SetOrientation $ori
+    return
+
+}
+itcl::body pxitclimage::GetOrientation { } {
+    
+    return [ $imageheader GetOrientation ]
+}
+
+itcl::body pxitclimage::GetIntensityScale { } {
+    
+    return [ $imageheader GetIntensityScale ]
+}
+
+itcl::body pxitclimage::GetIntensityOffset { } {
+    
+    return [ $imageheader GetIntensityOffset ]
+}
+
+
+
+itcl::body pxitclimage::GetOrientationName { } {
+    
+    set raw [ $imageheader GetOrientation ]
+    set orientation [ $imageheader MapOrientationToOldStyle $raw ]
+    set name [ $imageheader GetOrientationCode ]
+
+    switch -exact $orientation {
+	"1" { return "Coronal $name" }
+	"2" { return "Sagittal $name" } 
+	"3" { return "Polar" } 
+    }
+    
+    return "Axial $name" 
+}
+# ----------------------------------------------------------
+itcl::body pxitclimage::GetImageSize { } {
+    scan [ $img GetDimensions ] "%d %d %d" x1 y1 z1
+    return [ expr $x1 * $y1 * $z1 ]
+}
+
+itcl::body pxitclimage::IsSameDisplaySize { other } {
+    if { $other == $img } {
+	return 1
+    }
+    if { $other == 0 } {
+	return 0
+    }
+
+    set otherimg [ $other GetImage ]
+
+    scan [ $img GetDimensions ] "%d %d %d" x1 y1 z1
+    scan [ $otherimg GetDimensions ] "%d %d %d" x2 y2 z2
+
+    scan [ $img GetSpacing ] "%f %f %f" a1 b1 c1
+    scan [ $otherimg GetSpacing ] "%f %f %f" a2 b2 c2
+
+    set l1 [ list $x1 $y1 $z1 $a1 $b1 $c1 ]
+    set l2 [ list $x2 $y2 $z2 $a2 $b2 $c2 ]
+    
+    set sum 0
+    for { set i 0 } { $i < [ llength $l1 ]  } { incr i } {
+	set d [ expr abs([lindex $l1 $i]-[ lindex $l2 $i ] )]
+	if { $d > 0.00001 } {
+	    incr sum
+	}
+    }
+
+    if { $sum ==0 } {
+	return 1
+    }
+    return 0
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclimage::GetLongDescription { } {
+
+    if { $imageheader !=0 } {	
+	set l [ $imageheader GetHeaderDescription -1 ]
+	regsub -all "\t" $l " " l
+	return "$l\n*${filename}*"
+    }
+
+    scan [ $img GetDimensions ] "%d %d %d" x1 y1 z1
+    scan [ $img GetSpacing    ] "%f %f %f" s1 s2 s3
+    scan [ $img GetOrigin     ] "%f %f %f" o1 o2 o3
+    set t1 [ $img GetNumberOfScalarComponents ] 
+    
+    set line [ format "Dimensions %dx%dx%d Comp=%d Orientation = [ GetOrientationName]\nSpacing=%.3fx%.3fx%.3f origin=(%.1f %.1f %.1f)" $x1 $y1 $z1 $t1 $s1 $s2 $s3 $o1 $o2 $o3 ]
+    set line  "name=$this\n\t$line\n\tFilename= *${filename}*"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitclimage::GetDescription { } {
+     
+    if { $imageheader !=0 } {
+
+	
+	set l [ $imageheader GetHeaderDescription -1 ]
+	regsub -all "\t" $l " " l
+	set l2 "${l}\n*${filename}*"
+	return $l2
+    }
+
+    scan [ $img GetDimensions ] "%d %d %d" x1 y1 z1
+    scan [ $img GetSpacing    ] "%f %f %f" s1 s2 s3
+    scan [ $img GetOrigin     ] "%f %f %f" o1 o2 o3
+    set t1 [ $img GetNumberOfScalarComponents ] 
+    
+    set line [ format "Dimensions %dx%dx%d fr=%d,Orientation = [ GetOrientationName]\nSpacing=%.3fx%.3fx%.3f origin=(%.1f %.1f %.1f)" $x1 $y1 $z1 $t1 $s1 $s2 $s3 $o1 $o2 $o3 ]
+    set line  "$line\nFilename=*${filename}*\n"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitclimage::GetShortDescription { } {
+    
+    scan [ $img GetDimensions ] "%d %d %d" x1 y1 z1
+    set t1 [ $img GetNumberOfScalarComponents ] 
+   
+    set line [ format "%dx%dx%d,%d"  $x1 $y1 $z1 $t1 ]
+
+    set line  "[ file tail $filename] [ GetOrientationName ] $line"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitclimage::SetFromAnalyzeSource { ana } {
+
+    #puts stderr "In Set From Analyze Source"
+
+    if { [ $ana IsA vtkpxAnalyzeImageSourceOld ] == 1 } {
+	return [ $this SetFromAnalyzeSourceOld $ana ]
+    }
+
+    global pxtcl_pref_array
+    if { [ $ana IsA vtkpxAnalyzeImageSource ] == 0 } {
+	return 0
+    }
+
+    ShallowCopyImage [ $ana GetOutput ]
+    CopyImageHeader  [ $ana GetImageHeader ]
+    $imageheader ReconcileImageIntensityRange $img
+
+    if { [ GetImageSize ] < 1 } {
+	Clear
+    }
+
+    #    #puts stderr "In setfromana [ $imageheader GetHeaderDescription 0 ]"
+    set filename     [ pxtclutil::GetAbsoluteFileName [ $imageheader GetFileName ] ]
+
+
+    set ok 1
+
+    if { $pxtcl_pref_array(ImageColormaps) == 1 } {
+	set cname "[ file root $filename ].cmap"
+
+	if { [ file exists $cname ] } {
+	    LoadLookupTable $cname
+	    set ok 2
+	}
+    }
+    UpdateStatus
+    return  $ok
+}
+# ----------------------------------------------------------
+itcl::body pxitclimage::SetFromAnalyzeSourceOld { ana } {
+
+    global pxtcl_pref_array
+    #puts stderr "In Set From Analyze Source Old"
+
+    if { [ $ana IsA vtkpxAnalyzeImageSourceOld ] == 0 } {
+	return 0
+    }
+
+    ShallowCopyImage [ $ana GetOutput ]
+    if { [ GetImageSize ] < 1 } {
+	Clear
+    }
+
+    catch { set orientation  [ $ana GetOrientation ] }
+    if { $orientation !=0 && $orientation !=1  && $orientation !=2  && $orientation !=3  } {
+	#puts stderr "Input Orientation = $orientation"
+	set orientation 0
+    }
+    set imageheader [ vtkbisImageHeader [ pxvtable::vnewobj ]]
+    $imageheader  CreateHeader $img 0
+    $imageheader  SetOrientation $orientation
+
+    set filename     [ pxtclutil::GetAbsoluteFileName [ $ana GetFilePrefix ] ]
+    #puts stderr "In Set From Analyze Source Old $filename"
+    set ok 1
+
+    if { $pxtcl_pref_array(ImageColormaps) == 1 } {
+	set cname "[ file root $filename ].cmap"
+
+	if { [ file exists $cname ] } {
+	    LoadLookupTable $cname
+	    set ok 2
+	}
+    }
+    UpdateStatus
+    #puts stderr "In Set From Analyze Source Old $filename $ok"
+    return  $ok
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclimage::Browse { description } {
+
+    set f2path [ file dirname $filename ]
+    set f2tail [ file tail    $filename ]
+	
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Get Filename for $description" -filetypes $typelist -initialfile $f2tail -initialdir $f2path ]   
+    if { [ string length $fname ] > 0 } {
+	set filename $fname
+	return 1
+    }
+    return 0
+}
+# ----------------------------------------------------------
+itcl::body pxitclimage::Load { args } {
+
+    global pxtcl_pref_array
+
+    set len [ llength $args ]
+    if { [ string length $filename ] == 0 && $len == 0 } { return  }
+
+
+    if { $len < 1 } {
+	set fname $filename
+    } else  { 
+	set fname [ lindex $args 0 ] 
+    }
+
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    } else {
+	set desc "Image"
+    }
+
+    set parobj 0;  if { $len > 2 } {	set parobj [ lindex $args 2 ]    }
+
+    if { [ string length $fname ] == 0 } {
+	set typelist  [ ::pxitclimage::GetImageTypeList load ]
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getOpenFile -title "Load $desc" -filetypes $typelist -initialfile $f2tail -initialdir $f2path ]   
+    }
+    
+
+    if { [ string length $fname ] <1 } {
+	return 0
+    }
+
+    set ext [ file extension $fname ]
+    set haslookuptable 0
+
+    set f $fname
+
+    set ext [ file extension $f ]
+    set allok 1
+
+    if { $ext == ".gz" } {
+	set ext [ file extension [ file root $f ]]
+    }
+
+    set ext2 [ string range $ext 1 end ]
+
+    set alldone 0
+
+    if { $ext == ".png" || $ext == ".PNG" || $ext == ".jpg" || $ext == ".jpeg" || $ext == ".JPG" || $ext == ".JPEG" } {
+	
+	if { $ext == ".png" || $ext == ".PNG" } {
+	    set ana [ vtkPNGReader New ]
+	} else {
+	    set ana [ vtkJPEGReader New ]
+	}
+	$ana SetFileName $f
+	if { $parobj !=0 } { $parobj SetFilterCallbacks $ana "Reading $ext Image" ; $parobj	WatchOn }
+	$ana Update
+	$this ShallowCopyImage [ $ana GetOutput ]
+	$this configure -filename $f
+	if { $parobj !=0 } {  $parobj  WatchOff }
+	set alldone 1
+	$ana Delete
+    } elseif { $ext == ".vt" || $ext == ".vtk" } {
+	set ana [ vtkStructuredPointsReader [ pxvtable::vnewobj ]]
+	$ana SetFileName $f
+	if { $parobj !=0 } { $parobj SetFilterCallbacks $ana "Reading Image" ; $parobj	WatchOn }
+	$ana Update
+	$this ShallowCopyImage [ $ana GetOutput ]
+	$this configure -filename $f
+	if { $parobj !=0 } {  $parobj  WatchOff }
+	set alldone 1
+	$ana Delete
+    } elseif { $ext == ".vtc" } {
+	set ana [ vtkafBVImageReader [ pxvtable::vnewobj ]]
+	if { $parobj !=0 } { $parobj SetFilterCallbacks $ana "Reading Image" ; $parobj WatchOn }
+	$ana Load $f
+	$this ShallowCopyImage [ $ana GetOutput ]
+	$this configure -filename $f
+	$imageheader SetOrientation [ $ana GetOrientation ]
+	if { $parobj !=0 } {  $parobj  WatchOff }
+	$ana Delete
+	set alldone 1
+    } elseif { $ext == ".fdf" } { 
+    # Varian Reader
+	set ok [ $this LoadVarian $fname  $parobj ]
+	if { $ok == 0 } {
+	    ::pxtclutil::Warning "Failed to Load Image $fname as Varian fdf"
+	}
+	set allok $ok
+	set alldone 1
+    } elseif { $ext == ".mnc" } {
+	set ana [ vtkpxMINC2ImageReader [ pxvtable::vnewobj ]]
+	if { $parobj !=0 } { $parobj SetFilterCallbacks $ana "Reading Image" ; $parobj WatchOn }
+	set ok [ $ana Load $f ]
+	set alldone 1
+	if { $ok > 0 } {
+	    $this ShallowCopyImage [ $ana GetOutput ]
+	    $this configure -filename $f
+	    $imageheader SetOrientation [ $ana GetOrientation ]
+	    [ $this  GetImage ] SetOrigin 0 0 0
+	} else {
+	    ::pxtclutil::Warning "Failed to Load Image $f -- maybe it is not in MINC2 format."
+	    set allok 0
+	}
+	if { $parobj !=0 } {  $parobj  WatchOff }
+	$ana Delete
+    } elseif { $ext != ".nii" && $ext !=".hdr" && $ext!=".img" } {
+	set r [ vtkbisDICOMReader New ]
+	$r CreateNIFTIHeaderOff
+	set ok [ $r CanReadFile $f ]
+	$r Delete
+	if { $r > 0 } {
+	    set ok [ $this LoadDICOM $fname 1  $parobj ]
+	    if { $ok == 0 } {
+		::pxtclutil::Warning "Failed to Load Image $fname as DICOM"
+	    }
+
+	    set allok $ok
+	    set alldone 1
+	}
+    }
+
+
+    if { $alldone == 0 } {
+	set ana [vtkpxAnalyzeImageSource [ pxvtable::vnewobj ] ]
+	if { $parobj !=0 } { $parobj SetFilterCallbacks $ana "Reading Image" ; $parobj WatchOn }
+	$ana   SetForceStandardOrientation $forcebioimagesuitecoordinates 
+	set ok [ $ana Load $f ]
+
+	if { $ok > 0 } {
+	    $this SetFromAnalyzeSource $ana
+	} else {
+	    ::pxtclutil::Warning "Failed to Load Image $f"
+	    set allok 0
+	}
+	if { $parobj !=0 } {  $parobj  WatchOff }
+	$ana Delete
+    }
+
+    if { $allok == 0 } {
+	return $allok
+    }
+    
+    if { $haslookuptable != 2 } {
+	catch { $lookuptable Delete } 
+	set lookuptable 0
+    }
+
+    return 1
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclimage::LoadDICOM { fname { petcenter 1 } { parobj 0 } } {
+
+
+#    puts stdout "Starting $fname $petcenter $parobj\n\n"
+
+    set lastdicomlist ""
+    set dodicom 0
+    catch { 
+	set r [ vtkbisDICOMReader New ]
+	set dodicom 1
+	$r Delete
+    }
+
+    if { $dodicom == 0 } {
+	puts stderr "This version of BioImage Suite can not read DICOM"
+	return 0
+    }
+
+    # --  Jeetu's notes on 4D
+    #
+    #  (0020,0012) IS [1 ]                                               # 2,1 Acquisition Number
+    #  (0020,0013) IS [2 ]                                               # 2,1 Instance Number
+
+    # For anatomical images the acquisition number stays same and instance number is effectively frame
+    # For fMRI images the acquisition number increases per time and instance number stays constant
+    #
+    # 0020,0012 -- fmri Acquis
+    
+    set fnamelist 0
+
+    if { $petcenter > 0  } {
+	# Use special rules to create filename list 
+	set fnamelist [ $this ISPETDICOM $fname ] 
+    }
+
+    if { $fnamelist == 0 } {
+	set dname [ file normalize [ file dirname $fname ] ]
+	set fnamelist ""
+	catch { set fnamelist [ lsort [ glob [ file join $dname * ]] ] }
+	if  { $fnamelist == "" } {
+	    return 0
+	}
+	set fnamelist [ lsort -unique [ concat [ file normalize $fname ] $fnamelist ] ]
+    }
+
+
+    #    puts stdout "fnamelist = $fnamelist"
+
+
+    set sortimglist ""
+    set studyid ""
+    set seriesid ""
+    set seriestime ""
+
+    set imglist  ""
+    set found 0
+    set mosaic 0
+    set dwimode 0
+    set dwidirlist ""
+    set dwizlist ""
+
+    set mos_w 0
+    set mos_h 0
+    set mos_d 0
+    set mos_spa 0
+    set r [ vtkbisDICOMReader New ]
+    $r CreateNIFTIHeaderOff
+    set ok [ $r CanReadFile $fname ]
+    if { $ok == 3 } {
+	$r SetFileName $fname
+	$r Update
+	    
+	set studyid  [ $r GetStudyUID ]
+	set seriesid [ $r GetSeriesUID ]
+	set found 1
+
+	if { [ $r GetIsMosaic  ] > 0 } {
+	    set mosaic 1
+	    set mos_w [ $r GetMosaicWidth ]
+	    set mos_h [ $r GetMosaicHeight ]
+	    set mos_d [ $r GetMosaicDepth ]
+	    set seriestime [ $r GetTimeFrame ]
+	    set mos_spa [ [ $r GetOutput ] GetSpacing ]
+	} elseif { [ $r GetDWIMode ] > 0 } {
+	    set dwimode 1
+	    set dwi_spa [ [ $r GetOutput ] GetSpacing ]
+	}
+    }
+    $r Delete
+    
+    if { $found == 0 } {
+	return 0
+    }
+    
+    set n [ llength $fnamelist ]
+
+    for { set i 0 } { $i < $n  } { incr i } {
+	set r [ vtkbisDICOMReader New ]
+	$r CreateNIFTIHeaderOff
+
+	set testname [ lindex $fnamelist $i ]
+	set ok [ $r CanReadFile $testname ]
+	
+	if { $ok == 3 } {
+	    #	    puts stdout "Setting Filename $testname"
+	    $r SetFileName $testname
+	    $r Update
+	    set sid [ $r GetStudyUID ]
+	    set sno [ $r GetSeriesUID ]
+
+	    if { $sid == $studyid && $seriesid == $sno } {
+		#puts stdout "Appending  $testname z=[ $r GetZPosition ]"
+		set rt [ $r GetReferenceTime ]
+		if { $rt =="" } {
+		    # FMRI Hack
+		    set rt [ $r GetTimeFrame ]
+		}
+		
+		set toadd 1
+		if { $mosaic == 1 } {
+		    if { $mos_w != [ $r GetMosaicWidth ] || $mos_h != [ $r GetMosaicHeight ] } {
+			set toadd 0
+		    }
+		}  elseif { $dwimode == 1 } {
+		    set dw [ $r GetDWIMode ]
+		    set dr [ $r GetDWIDirections ]
+		    set bv [ $r GetDWIBValue ]
+		    set v "$dw,[ lindex $dr 0],[lindex $dr 1 ],[lindex $dr 2],$bv"
+		    set ind [ lsearch -exact $dwidirlist $v ]
+		    if { $ind == - 1 } {
+			lappend dwidirlist $v
+		    }
+		    
+		    lappend dwizlist [ $r GetZPosition ]
+		    lappend imglist [ list $testname [ $r GetZPosition ] [$r GetX0 ] [ $r GetY0 ] [ $r GetZ0 ] $v $sid $sno ]
+		    set toadd 0
+		}
+		
+		if { $toadd > 0  } {
+		    lappend imglist [ list $testname [ $r GetZPosition ] [$r GetX0 ] [ $r GetY0 ] [ $r GetZ0 ] $rt $sid $sno ]
+
+		}
+	    }
+	}
+	$r Delete
+    }
+
+    if { $dwimode > 0 } {
+	set alldirections  $dwidirlist 
+	set dwizlist [ lsort -unique  -real -increasing $dwizlist ]
+	set n [ llength $imglist ]
+	set tmp $imglist
+	set imglist ""
+	for { set i 0 } { $i < $n } { incr i } {
+	    set elem [ lindex $tmp $i ] 
+	    set d [ lindex $elem 2  ]
+	    set ind [ lsearch  $alldirections $d ]
+	    if { $ind == - 1 } {
+		puts stdout "Bad Element $elem"
+	    }
+	    set newelem [ list [ lindex $elem 0 ] [ lindex $elem 1 ] $ind [ lindex $elem 3 ] [ lindex $elem 4 ] $d ]
+	    lappend imglist $newelem
+	}
+    }
+
+    if { [ llength $imglist ] == 0 } {
+	return 0
+    }
+
+
+    # Double sort for time purposes
+    # First sort in space
+    if { $mosaic != 0 } {
+	set sortimglist  [ lsort -real -increasing -index 5 $imglist ]
+    } elseif { $dwimode !=0 } {
+	set sortimglist  [ lsort -ascii -increasing -index 5  $imglist ]
+	set sortimglist  [ lsort -real -increasing -index 1  $sortimglist ]
+    } else  {
+	set sortimglist [ lsort -real -increasing -index 1 $imglist ]
+    }
+
+    
+
+
+#    pxtkprint "\n ------------------------------- \n Beginning to read $studyid, $seriesid\n"
+    set sar [ vtkStringArray New ]
+    set n [ llength $sortimglist ]
+
+    set lastdicomlist $sortimglist
+
+    for { set i 0 } { $i < $n } { incr i } {
+	$sar InsertNextValue  [ lindex [ lindex $sortimglist $i ] 0 ]
+    }
+    
+    set zflip 0
+
+    if { $mosaic != 0 } {
+	set zsp [ lindex $mos_spa 2 ]
+	set zflip 0
+    } elseif { $dwimode !=0 } { 
+	set zsp 1.0
+	set zflip 0
+	if { [ llength $dwizlist ] > 1 } {
+	    set zsp [ expr [ lindex $dwizlist 1 ] - [ lindex $dwizlist 0 ]]
+	}
+    } elseif { [ llength $sortimglist ] > 1 } {
+	set z [ expr [ lindex [ lindex $sortimglist 1 ] 4 ] -  [ lindex [ lindex $sortimglist 0 ] 4 ] ]
+	set x [ expr [ lindex [ lindex $sortimglist 1 ] 2 ] -  [ lindex [ lindex $sortimglist 0 ] 2 ] ]
+	set y [ expr [ lindex [ lindex $sortimglist 1 ] 3 ] -  [ lindex [ lindex $sortimglist 0 ] 3 ] ]
+	set zsp [ expr sqrt($x*$x+$y*$y+$z*$z) ]
+	#	puts stderr "1=[ lindex $sortimglist 1 ]"
+	#	puts stderr "0=[ lindex $sortimglist 0 ]"
+	#	puts stderr "x=$x, y=$y, z=$z zsp=$zsp"
+	
+	if { $zsp < 0.0 } {
+	    set zsp [ expr abs($zsp)  ]
+	    set zflip 1
+	}
+    } else {
+	set zsp 0.0
+	set zflip 0
+    }
+    
+    set ana [ vtkbisDICOMReader New ]
+    if { $parobj !=0 } { $parobj SetFilterCallbacks $ana "Reading DICOM Image" ; $parobj	WatchOn }
+    
+    $ana SetForceZSpacing  $zsp
+    $ana SetFlipZ $zflip
+    $ana SetFileNames $sar
+    $ana Update
+
+
+    if { $mosaic > 0 } {
+	set flt [ vtkbisSiemensMosaicConverter New ]
+	#	$flt DebugOn
+	$flt SetInput [ $ana GetOutput ]
+	$flt SetMosaicWidth  $mos_w
+	$flt SetMosaicHeight $mos_h
+	$flt SetMosaicDepth  $mos_d
+	$flt Update
+	$this ShallowCopyImage [ $flt GetOutput ]
+	$flt Delete
+    } elseif { $dwimode > 0 } {
+	set flt [ vtkbisSiemensDWIArrange New ]
+	$flt SetInput [ $ana GetOutput ]
+	$flt SetNumberOfSlices  [ llength $dwizlist ] 
+	$flt Update
+	$this ShallowCopyImage [ $flt GetOutput ]
+	$flt Delete
+    } else {
+	$this ShallowCopyImage [ $ana GetOutput ]
+    }
+    $this CopyImageHeader  [ $ana GetImageHeader ]
+    $imageheader ReconcileImageIntensityRange $img
+
+    if { $forcebioimagesuitecoordinates  > 0 }  {
+    	$imageheader ForceHeaderToBioImageSuiteCoordinatesAndFlipImage $img 
+    }
+
+
+    set txt "Original DICOM Series (num dicom images=[ llength $sortimglist ])\n"
+    for { set i 0 } { $i < [ llength $sortimglist ] } { incr i } {
+	#	puts stdout "$i [ lindex $sortimglist $i ]"
+	append txt "[ file tail [ lindex [ lindex $sortimglist $i ] 0 ]] \t pos=[ lindex [ lindex $sortimglist $i ] 1 ], ori = [ lindex [ lindex $sortimglist $i ] 2 ] [ lindex [ lindex $sortimglist $i ] 3 ] [ lindex [ lindex $sortimglist $i ] 4 ] \t t= [ lindex [ lindex $sortimglist $i ] 4 ]\n"
+    }
+
+    if { $dwimode > 0 } {
+	append txt "DWI Directions\n"
+	append txt "[ expr [ llength $alldirections ] -1 ]\n"
+	for { set i 1 } { $i < [ llength $alldirections ] } { incr i } {
+	    set el [ split [ lindex $alldirections $i ] "," ]
+	    append txt "[ lindex $el 1 ] [ lindex $el 2 ] [ lindex $el 3 ]\n"
+	}
+	append txt "DWI B-Values\n"
+	for { set i 0 } { $i < [ llength $alldirections ] } { incr i } {
+	    set el [ split [ lindex $alldirections $i ] "," ]
+	    if { $i !=0 } { append txt ", " }
+	    append txt "[ lindex $el 4 ]"
+	}
+	append txt "\n"
+    }
+    $imageheader AddComment $txt
+
+    $sar Delete
+    set pid [ $ana GetPatientID ]
+    set pst [ $ana GetStudy]
+    set pse [ $ana GetSeries ]
+    set pdt [ $ana GetDate ]
+    if { $pse == "" } {
+	set pse 0
+    }
+    $ana Delete
+    
+    if { $pst != "1" } {
+	set outname2 [ format "%s_s%03d_s_%s" $pid $pse $pst  $pdt  ]
+    } else {
+	set outname2 [ format "%s_s%03d_%s" $pid $pse $pdt  ]
+    }
+    
+    if { [ GetImageSize ] < 1 } {
+	Clear
+	return 0
+    }
+    
+    if { $mosaic != 0 } {
+	append outname2 "_fmri"
+    } elseif { $dwimode !=0 }  {
+	append outname2 "_dwi"
+    }
+    
+    set filename  "${outname2}.nii.gz"
+
+
+    return 1
+}
+# ----------------------------------------------------------
+itcl::body pxitclimage::ISPETDICOM { fname } { 
+
+    set tname [ file tail $fname ]
+    set dname [ file dirname $fname ]
+    
+    set nameparts [ split $tname . ]
+    if { [ llength $nameparts ] != 3  } {
+	return 0
+    }
+    set first [ lindex $nameparts 0 ]
+    set last  [ lindex $nameparts 2 ]
+    
+    if { $first != "Image" || $last != "dcm" } {
+	return 0
+    }
+    
+    set midlist [ split [ lindex $nameparts 1 ] _ ]
+    
+    set tmplist [ glob [ file join $dname  "${first}.*_[lindex $midlist 1 ].${last}" ] ]
+    return $tmplist 
+}
+# ----------------------------------------------------------
+itcl::body pxitclimage::CreateLookupTable { } {
+
+    global pxtcl_pref_array
+
+    set robust 0
+    catch { 
+	if { $pxtcl_pref_array(NormalizeAnatomical) > 0 } {
+	    set robust 1
+	}
+    }
+
+    if { $lookuptable == 0 } {
+	set lookuptable [ vtkLookupTable [ pxvtable::vnewobj ]]
+    }
+    
+    set cutil [ vtkpxColorMapUtil [ pxvtable::vnewobj ] ]
+#    puts stderr "Creating robust =$robust Lookup Table"
+    $cutil SetAutoStepColorMap $img $lookuptable $robust 256 0
+    $cutil Delete
+}
+
+
+itcl::body pxitclimage::LoadLookupTable { name } {
+
+    if { $lookuptable == 0 } {
+	set lookuptable [ vtkLookupTable [ pxvtable::vnewobj ]]
+    }
+
+    set cutil [ vtkpxColorMapUtil [ pxvtable::vnewobj ] ]
+    set ok [ $cutil LoadColormap $lookuptable $name ]
+    if { $ok == 0 } {
+	catch { $lookuptable Delete }
+	set lookuptable 0
+    }
+    $cutil Delete
+
+#    puts stderr "Loading Lookup Table from $name $ok"
+
+}
+# ----------------------------------------------------------
+itcl::body pxitclimage::SetLookupTable { cmap }  {
+
+    if { $cmap == 0 } {
+	if { $lookuptable != 0 } {
+	    catch { $lookuptable Delete }
+	    set lookuptable 0
+	}
+	return
+    }
+    
+    if { $lookuptable == 0 } {
+	set lookuptable [ vtkLookupTable [ pxvtable::vnewobj ]]
+    }
+
+    #    puts -nonewline stderr "pxitclimage copying lookuptable ..."
+    $lookuptable DeepCopy $cmap 
+    #puts stderr "done\n"
+}
+
+itcl::body pxitclimage::SaveLookupTable { name } {
+
+    if { $lookuptable == 0 } {
+	return
+    }
+
+    set cutil [ vtkpxColorMapUtil [ pxvtable::vnewobj ] ]
+    set ok [ $cutil SaveColormap $lookuptable $name ]
+    $cutil Delete
+    #    puts stderr "Saviing Lookup Table to $name $ok"
+}
+# ----------------------------------------------------------
+
+itcl::body pxitclimage::Save { args } {
+
+    global pxtcl_pref_array
+
+    set len [ llength $args ]
+    if { $len < 1 } {
+	set fname $filename
+    } else  { 
+	set fname [ lindex $args 0 ] 
+    }
+
+    set desc "Image"
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    }
+
+    set parobj 0;   if { $len > 2 } {	set parobj   [ lindex $args 2 ]  }
+    set forceimageformat 0; 
+    if { $len > 3 } {  
+	set forceimageformat [ lindex $args 3 ]  
+    } else {
+	set forceimageformat $forceoutputformat 
+    }
+    #    puts stderr "Forceoutput =  $forceoutputformat (pxitclimage)"
+
+    if { [ string length $fname ] == 0 } {
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set typelist  [ ::pxitclimage::GetImageTypeList save ]
+
+	set d [ [ $this GetImage ] GetDimensions ]
+
+	if { [ lindex $d 2 ] == 1 } {
+	    lappend typelist {"PNG Files" {.png}}
+	}
+	set fname  [tk_getSaveFile -title "Saving $desc" -filetypes $typelist -initialfile $f2tail -initialdir $f2path ]   
+    }
+
+    if { [ string length $fname ] <1 } { return 0   }
+
+    set f $fname
+    set ext [ file extension $f ]
+    set line ""
+
+    set status 1
+
+    if { $ext == ".mnc" } {
+	$this configure -filename $f
+	set vtkwriter [ vtkMINC2ImageWriter [ pxvtable::vnewobj ] ]
+	$vtkwriter SetFileName    $f
+	$vtkwriter SetInput       [ $this GetImage ] 
+    } elseif { $ext == ".png" } {
+	$this configure -filename $f
+	set vtkwriter [ vtkPNGWriter [ pxvtable::vnewobj ] ]
+	$vtkwriter SetFileName    $f
+	$vtkwriter SetInput       [ $this GetImage ] 
+    } else {
+	$this configure -filename $f
+	set vtkwriter [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ] ]
+	$vtkwriter SetByteSwap    0
+	$vtkwriter SetInput       [ $this GetImage ] 
+	$vtkwriter SetImageHeader $imageheader
+
+	set md [ $vtkwriter GetForceOutputFileFormat ]
+	#puts stderr "Getting Force Format $md"
+	$vtkwriter SetForceOutputFileFormat 0
+
+	#	puts stderr "What is forceoutputformat ?  $forceimageformat"
+	if { $forceimageformat == 1 } {
+	    [ $vtkwriter GetImageHeader ] SetModeToAnalyze
+	    if { $ext == ".gz" } {
+		set f [ file root $f ]
+	    }
+	    if { $ext == ".nii" } {
+		set f [ file root $f ]_nii
+	    }
+	    #puts stderr "Making Header to Analyze .... $f"
+	    $vtkwriter SetForceOutputFileFormat 1
+	} elseif { $forceimageformat == 2 && [ $imageheader GetMode ] == 0 } {
+	    [ $vtkwriter GetImageHeader ]  SetModeToNIFTI_NII
+	    $vtkwriter SetForceOutputFileFormat 2
+	    #puts stderr "Making Header to NIFTI (HDR/IMG) .... $f"
+	} else {
+	    #puts stderr "No Force\n"
+	}
+		  
+
+	$vtkwriter SetFileName    $f
+
+	if { $ext == ".gz" } {
+	    $vtkwriter SetCompression 9
+	    set line "Compressed"
+	} 	    
+	if {  $pxtcl_pref_array(ImageColormaps) == 1 } {
+	    set cname "[ file root $fname ].cmap"
+	    $this SaveLookupTable $cname
+	}
+    }
+    if { $parobj !=0 } {
+	$parobj SetFilterCallbacks $vtkwriter "Saving ${line} Image"
+	$parobj WatchOn 
+    }
+    $vtkwriter Write
+    
+    if { [ $vtkwriter IsA "vtkpxAnalyzeImageWriter"  ] == 1 } {
+	$vtkwriter SetForceOutputFileFormat $md
+    }
+
+    catch { set status [ $vtkwriter GetSaveStatus ] }
+
+    if { $parobj !=0 } { $parobj WatchOff  }
+    
+    if { $status == 0 } {
+	::pxtclutil::Warning "Failed to save image $f"
+    } else {
+	#	puts stderr "Copying Header"
+	if { [ $vtkwriter IsA "vtkpxAnalyzeImageWriter"  ] == 1 } {
+	    $imageheader CopyHeader [ $vtkwriter GetImageHeader ]
+	    $this configure -filename [ $imageheader GetFileName ]
+	}
+    }
+
+    catch { $vtkwriter Delete }
+
+    return $status
+}
+# ----------------------------------------------------------
+itcl::body pxitclimage::FlipImage { mode } {
+    
+    if { $mode == "None" } { 
+	return 1  
+    }
+    
+    if { [ GetImageSize ] < 2 } {  
+	return 0 
+    }
+
+    set reslice  [  vtkbisImageReslice [ pxvtable::vnewobj ] ]
+   
+    $reslice SetInput  [ $this GetImage ] 
+
+    set trans  [  vtkTransform [ pxvtable::vnewobj ] ]
+    $trans Identity
+    $trans PostMultiply
+    set tmat  [  vtkMatrix4x4 [ pxvtable::vnewobj ]  ]
+    $tmat Identity
+    
+    set spa [ [ $this GetImage ] GetSpacing ]
+    set ori [ [ $this GetImage ] GetOrigin ]
+    set dim [ [ $this GetImage ] GetDimensions ]
+    set perm(0) 0 ;  set perm(1) 1 ;  set perm(2) 2 	
+    
+
+    # Compute Transformation
+    # ----------------------
+    switch -exact $mode {
+	"Slice Order(Z)" {
+	    $tmat SetElement 2 2 -1
+	    $trans SetMatrix $tmat
+	}
+
+	"Z" {
+	    $tmat SetElement 2 2 -1
+	    $trans SetMatrix $tmat
+	}
+	
+	"Y" {
+	    $tmat SetElement 1 1 -1
+	    $trans SetMatrix $tmat
+	}
+
+	"YZ" {
+	    $tmat SetElement 1 1 -1
+	    $tmat SetElement 2 2 -1
+	    $trans SetMatrix $tmat
+	}
+	
+	"X" {
+	    $tmat SetElement 0 0 -1
+	    $trans SetMatrix $tmat
+	}
+	
+	"Transpose" {
+	    $tmat SetElement 0 0 0 ; $tmat SetElement 0 1 1 ;
+	    $tmat SetElement 1 0 1 ; $tmat SetElement 1 1 0;
+	    set perm(0) 1 ; set perm(1) 0 ; set perm(2) 2
+	    $trans SetMatrix $tmat
+	}
+	
+	"FlipTranspose" {
+	    $tmat SetElement 0 0 0 ;  $tmat SetElement 0 1 -1 ;
+	    $tmat SetElement 1 0 -1 ; $tmat SetElement 1 1 0;
+	    $trans SetMatrix $tmat
+	    set perm(0) 1 ; set perm(1) 0 ; set perm(2) 2
+	}
+	
+    }
+    catch {$tmat Delete }
+    
+    $reslice SetResliceTransform $trans
+    $reslice AutoCropOutputOn
+
+    for { set k 0 } { $k <=2 } { incr k } {
+	set outsp($k)  [ lindex $spa $perm($k) ]
+    }
+    $reslice SetOutputSpacing $outsp(0) $outsp(1) $outsp(2)
+
+    set wd [ expr int( [ lindex $dim 0 ]*[lindex $spa 0 ]/ $outsp(0)) - 1]
+    set ht [ expr int( [ lindex $dim 1 ]*[lindex $spa 1 ]/ $outsp(1)) - 1]
+    set dp [ expr int( [ lindex $dim 2 ]*[lindex $spa 2 ]/ $outsp(2)) - 1]
+    $reslice SetOutputExtent 0 $wd 0 $ht 0 $dp
+
+    catch { unset outsp }
+    $reslice SetInterpolationMode 0
+    $reslice SetBackgroundLevel 0
+    $reslice Update
+    [ $reslice GetOutput ] SetOrigin 0 0 0 
+    $this ShallowCopyImage [ $reslice GetOutput ]
+    catch { $reslice Delete }
+}
+
+# --------------------------------------------------------------------------------------------------
+itcl::body pxitclimage::LoadVarian { fname { parobj 0 } { flipdti 0 } } {
+
+
+    set lastdicomlist ""
+    set baseelement [ ::pxtclreadvarianheader::ReadVarianHeader $fname ]
+    if { $baseelement ==0 } {
+	return 0
+    }
+
+    
+    set tmpname  [ file root [ file tail [ file dirname [ file normalize $fname ] ] ] ]
+    puts stdout "Filename = $tmpname"
+
+    set studyid [ $baseelement GetAttribute "studyid"  ]
+
+    # Single Image ..........
+    if { $studyid == "__none__" } {
+	set tmpname2  [ file tail $fname ] 
+	[ $this GetImageHeader ] CreateVarianHeader $baseelement
+	set tmpimg [ ::pxtclreadvarianheader::ReadVarianImage $baseelement $parobj ]
+	$this ShallowCopyImage $tmpimg
+	$tmpimg Delete
+	$this configure -filename ${tmpname}_${tmpname2}
+	$baseelement Delete
+	set lastdicomlist $fname
+	return 1
+    }
+
+
+    set dname [ file normalize [ file dirname $fname ] ]
+    set fnamelist ""
+    catch { set fnamelist [ lsort [ glob [ file join $dname *.fdf ]] ] }
+    if  { $fnamelist == "" } {
+	return 0
+    }
+    set fnamelist [ lsort -unique [ concat [ file normalize $fname ] $fnamelist ] ]
+
+
+    set imglist  ""
+    set found 0
+    set mosaic 0
+    set dwimode 0
+    set numslices [ $baseelement GetAttribute "slices" ]
+    set numframes [ $baseelement GetAttribute "array_dim" ]
+    set numechos [ $baseelement GetAttribute "echoes" ]
+    set dointerleave 0
+    set dwidirlist ""
+
+    set gd [ $baseelement GetAttribute "Gdiff1" ]
+    if { $gd != "" } {
+	set dwimode 1
+	set dwidirlist "[ $baseelement GetAttribute "Gdiff1" ],[ $baseelement GetAttribute "Gdiff2" ],[ $baseelement GetAttribute "Gdiff3" ]"
+    }
+    
+    
+    set n [ llength $fnamelist ]
+
+    for { set i 0 } { $i < $n  } { incr i } {
+	set testname [ lindex $fnamelist $i ]
+	set r [ ::pxtclreadvarianheader::ReadVarianHeader $testname ]
+	if { $r !=0 } {
+	    set sid [ $r GetAttribute "studyid" ]
+	    if { $sid == $studyid } {
+		if { $dwimode == 1 } {
+		    set lst "[ $r GetAttribute "Gdiff1" ],[ $r GetAttribute "Gdiff2" ],[ $r GetAttribute "Gdiff3" ]"
+		} else {
+		    set lst "0,0,0"
+		}
+		set sliceno [ $r GetAttribute "slice_no" ]
+		set frameno [ $r GetAttribute "array_index" ]
+		set location [ $r GetAttribute "location" ]
+
+		for { set j 0 } { $j <=2 } { incr j } {
+		    set spa($j) [ $r GetAttribute "bis_Spacing$j" ]
+		    set dim($j) [ $r GetAttribute "bis_Dimension$j" ]
+		    set bits    [ $r GetAttribute "bits" ]
+		    set hd      [ $r GetAttribute "bis_HeaderSize" ]
+		}
+		lappend imglist [ list $testname "[ $r GetAttribute "display_order" ]" "$sliceno" "$frameno" "$lst" [ list $dim(0) $dim(1) $dim(2)  $spa(0) $spa(1) $spa(2) $bits $hd ] "$location" ]
+	    }
+	    $r Delete
+	}
+    }
+
+    if { [ llength $imglist ] == 0 } {
+	return 0
+    }
+
+    set sortimglist [ lsort -real -increasing -index 1 $imglist ]
+
+    set dwidirlist ""
+    for { set i 0 } { $i < [ llength $sortimglist ] } { incr i } {
+	set el [ lindex $sortimglist $i ]
+	if { $dwimode > 0 } {
+	    set slno [ lindex $el  2]
+	    if { $slno == 1 } {
+		lappend dwidirlist [ lindex $el 4 ]
+	    }
+	}
+    }
+	
+    if { $dwimode > 0 } {
+	for { set i 0 } { $i < [ llength $dwidirlist ] } { incr i } {
+	    puts stdout "dwi $i = [ lindex $dwidirlist $i ]"
+	}
+    }
+
+    if { [ llength $sortimglist ] > 1 && $numslices > 1 } {
+	set upper 0
+	set el1 [ lindex $sortimglist 0 ]
+	set loc1 [ lindex $el1 6 ]
+	set zdim 0.0
+
+	while { $upper < [ llength $sortimglist ] && $zdim == 0.0 } {
+	    incr upper
+	    set el2 [ lindex $sortimglist $upper ]
+	    set loc2 [ lindex $el2 6 ]
+	    set sum 0.0
+	    for { set i 0 } { $i<=2 } { incr i } {
+		set x1 [ lindex $loc1 $i ]
+		set x2 [ lindex $loc2 $i ]
+		set sum [ expr $sum+($x1-$x2)*($x1-$x2) ]
+	    }
+	    set sum [ expr sqrt($sum) ]
+	    set zdim $sum
+	    #	    puts stdout "zdim=$zdim, upper=$upper slices=$numslices, $numechos"
+	}
+	set units [ $baseelement GetAttribute "abscissa" ]
+	if { $upper >= 2 } {
+	    set numslices $numechos
+	    set dointerleave 1
+	}
+
+
+	#	puts stderr "units=$units\n\n\n\n"
+	if { [ llength $units ] > 0 } {
+	    if { [ lindex $units 0 ] == "cm" } {
+		set zdim [ expr 10.0*$zdim ]
+	    }
+	}
+    } else {
+	set zdim -1.0
+    }
+
+    #    puts stderr "zdim=$zdim"
+    if { $zdim > 0.0 } {
+	$baseelement SetAttribute "bis_Spacing2" $zdim 
+    }
+
+    set appnd [ vtkImageAppend New ]
+    $appnd  SetAppendAxis 2
+    for { set i 0 } { $i < [ llength $sortimglist ] } { incr i } {
+	set anar [ vtkpxAnalyzeImageSourceOld New ]
+	set el [ lindex $sortimglist $i ]
+	set dt [ lindex $el 5 ]
+	set fn [ lindex $el 0 ]
+	set loc [ lindex $el 6 ]
+
+	if { $zdim < 0.0 } {
+	    $anar SetVoxelDimensions [ lindex $dt 3 ] [ lindex $dt 4 ] [ lindex $dt 5 ]
+	} else {
+	    $anar SetVoxelDimensions [ lindex $dt 3 ] [ lindex $dt 4 ] $zdim
+	}
+	$anar SetHeaderInfo [ lindex $dt 0 ] [ lindex $dt 1 ] [ lindex $dt 2 ] 1 0 [ expr [ lindex $dt 6 ] / 8 ]
+	$anar SetHeaderSize [ lindex $dt 7 ]
+	$anar SetFilePrefix $fn
+	lappend lastdicomlist $fn
+	if { $parobj !=0 } { $parobj SetFilterCallbacks $anar "Reading Varian Image [ lindex $el 2]/[lindex $el 3]" }
+	#	puts stdout "Reading Varian Image slice:[ lindex $el 2] frame:[lindex $el 3] ($loc, $zdim) from $fn"
+	$anar Update
+	$appnd AddInput [ $anar GetOutput ]
+	$anar Delete
+    }
+    $appnd Update
+
+    set co [ vtkpxImageComponentsToFrames [ pxvtable::vnewobj ]]
+    $co SetSlicesPerFrame $numslices
+    $co SetInverse 1
+    $co SetInput [ $appnd GetOutput ] 
+    $co Update
+
+    set tmpimage 0
+
+
+    if { $dointerleave } {
+	set tmpimage [ vtkImageData New ]
+	set ut [ vtkpxUtil New ]
+	$ut ReorderImage $tmpimage [ $co GetOutput ] 
+	set imgtocopy $tmpimage
+	puts stdout "Auto interleaving image"
+	$ut Delete
+    } else {
+	set imgtocopy [ $co GetOutput ]
+    }
+
+    if { $flipdti > 0 && $dwimode > 0 } {
+	set flipx [ vtkImageFlip New ]
+	$flipx SetInput $imgtocopy
+	$flipx SetFilteredAxis 0
+	$flipx Update
+
+	if { $tmpimage == 0 } {
+	    set tmpimage [ vtkImageData New ]
+	}
+	$tmpimage ShallowCopy [ $flipx GetOutput ]
+	set imgtocopy $tmpimage
+	$flipx Delete
+	puts stdout "Flipping DWI Image along x-axis to correct for bug"
+    }
+	
+
+    set vl [ ::pxtclreadvarianheader::GetVarianScaleFactor [ $co GetOutput ] ]
+    if {  $vl > 1.0 } {
+	set sscale [ vtkImageShiftScale New ]
+	puts stdout "Scaling 4D Varian Image by $vl"
+	$sscale SetShift 0.0
+	$sscale SetScale $vl
+	$sscale SetInput $imgtocopy
+	$sscale Update
+	$this ShallowCopyImage [ $sscale GetOutput ]
+	$sscale Delete
+    } else {
+	$this ShallowCopyImage $imgtocopy
+    }
+
+
+
+
+    [ $this GetImageHeader ] CreateVarianHeader $baseelement
+
+    $this configure -filename "${studyid}.nii.gz"
+
+    $co Delete
+    $appnd Delete
+
+    if { $tmpimage !=0 } {
+	$tmpimage Delete
+    }
+
+    set txt "\#Original Header Info"
+    set n [ $baseelement GetNumberOfAttributes ]
+    for { set  i 0 } { $i < $n } { incr i } {
+	set a [ $baseelement GetAttributeName $i ]
+	set b [ $baseelement GetAttributeValue $i ]
+	if { [ string first "bis_" $a ] !=0 } {
+	    append txt "$a = $b\n"
+	}
+    }
+
+    append txt "--------------------------------------\nOriginal Image Info\n"
+    for { set i 0 } { $i < [ llength $sortimglist ] } { incr i } {
+	append txt "Image [ expr $i+1]: [ lindex $sortimglist $i ]\n"
+    }
+
+    if { $dwimode > 0 } {
+	append txt "--------------------------------------\nDWI Directions\n"
+	append txt "[ expr [ llength $dwidirlist ] -1 ]\n"
+	for { set i 1 } { $i < [ llength $dwidirlist ] } { incr i } {
+	    append txt "[ lindex $dwidirlist $i ] \n"
+	}
+	append txt "\n"
+    }
+    $imageheader AddComment $txt
+    #    puts stdout "txt=$txt\n[ $this GetOrientation ], [ $this GetDescription]"
+    $baseelement Delete
+    $this configure -filename $tmpname
+
+
+    
+
+    return 1
+}
+# ----------------------------------------------------------------------------------
+
+
+itcl::body pxitclimage::CompareTo  { fname { thr 0.001 } } {
+
+    set tmp [ pxitclimage \#auto ]
+    set ok [$tmp Load $fname  ]
+    if { $ok == 0 } {
+	itcl::delete object $tmp
+	return 0
+    }
+
+    set ut [ vtkbisTestUtil New ]
+    $ut ClearStatus
+    set ok [ $ut CompareImages [ $this GetImage ] [ $tmp GetImage ] $thr ]
+    itcl::delete object $tmp
+    set a [ $ut ReturnStatus ]
+    $ut Delete
+    return [ list $ok $a ]
+}
+
+itcl::body pxitclimage::CompareTo  { fname { thr 0.001 } } {
+
+    set tmp [ pxitclimage \#auto ]
+    set ok [$tmp Load $fname  ]
+    if { $ok == 0 } {
+	itcl::delete object $tmp
+	return 0
+    }
+
+    set ut [ vtkbisTestUtil New ]
+    $ut ClearStatus
+    set ok [ $ut CompareImages [ $this GetImage ] [ $tmp GetImage ] $thr ]
+    set a [ $ut ReturnStatus ]
+    itcl::delete object $tmp
+    $ut Delete
+    return [ list $ok $a ]
+}
+
+itcl::body pxitclimage::CorrelateWith  { fname { thr 0.9 } } {
+
+    set tmp [ pxitclimage \#auto ]
+    set ok [$tmp Load $fname  ]
+    if { $ok == 0 } {
+	itcl::delete object $tmp
+	return 0
+    }
+
+    if { $thr < 0.05 } {
+	set thr [ expr 1.0 - $thr ]
+	if { $thr > 1.0 } {
+	    set thr 1.0
+	}
+    }
+
+    set ut [ vtkbisTestUtil New ]
+    $ut ClearStatus
+    set ok [ $ut CorrelateImages [ $this GetImage ] [ $tmp GetImage ] $thr ]
+    set a [ $ut ReturnStatus ]
+    itcl::delete object $tmp
+    $ut Delete
+    return [ list $ok $a ]
+}
+
+# ----------------------------------------------------------
+#  GUI for pxitclimage
+# ----------------------------------------------------------
+itcl::class pxitclimageGUI {
+
+    inherit pxitclobjectGUI
+
+    public variable browsebutton
+
+    constructor { } {
+	pxitclobjectGUI::constructor
+    } { 
+	set thisparam($this,status) "vtkImageData"
+	set thisparam($this,shortfilename) "none"
+	set thisparam($this,descriptionbox) 0
+	Reset
+    }
+
+    destructor { }
+
+
+    public method SetObject { tr } { return [ SetImage $tr ] }
+    public    method GetImage { } { return $itclobject  }
+
+    protected method CreateNewObject { } 
+    public    method Initialize { basewidg } 
+    public    method SetImage { img }
+    public    method BrowseImage { } h
+
+
+}
+# ----------------------------------------------------------
+itcl::body pxitclimageGUI::CreateNewObject { } {
+    set itclobject  [ [  pxitclimage \#auto ] GetThisPointer ]
+}
+
+itcl::body pxitclimageGUI::BrowseImage { } {
+    $itclobject Browse $description
+    Update
+}
+
+itcl::body pxitclimageGUI::SetImage { trn } {
+    
+    if { [ $trn isa pxitclimage ] == 0 } {
+	return 0
+    }
+	
+    if { $owns_object == 1} {
+	catch { itcl::delete object $itclobject }
+    }
+
+    set itclobject $trn
+    set owns_object 0
+    Update
+}
+
+itcl::body pxitclimageGUI::BrowseImage { } {
+    $itclobject Browse $description
+    Update
+}
+
+itcl::body pxitclimageGUI::Initialize { basewidg } {
+
+    if { $initialized == 1 } { return $basewidget }
+    pxitclobjectGUI::Initialize $basewidg
+    
+    set browsebutton [ eval "button $buttonbar.b -text Browse -command { $this BrowseImage }" ]
+    pack  $buttonbar.b   -side left -fill x -expand f
+
+    Update
+    return $basewidget
+}
+
+# ----------------------------------------------------------
+#  GUI for multiple image object
+# ----------------------------------------------------------
+itcl::class pxitclmultiImageGUI {
+
+    inherit pxitclmultiObjectGUI
+
+    constructor { } {
+	pxitclmultiObjectGUI::constructor
+    } {
+    }
+    
+    destructor { }
+    
+    public    method Initialize { basewidg } 
+
+    public    method AddImage { descr }
+    public    method SetImage { index } 
+    public    method GetImage { index } { return [ GetObject $index ] }
+    public    method DeleteImage { index } { DeleteObject $index }
+
+    protected method CreateNewObject { }
+    protected method CreateNewObjectGUI { widget }
+
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclmultiImageGUI::CreateNewObject { } {
+
+    return  [ [  pxitclimage \#auto ] GetThisPointer ]
+}
+
+itcl::body pxitclmultiImageGUI::CreateNewObjectGUI { widget } {
+    set itclimageGUI [ [ pxitclimageGUI \#auto ] GetThisPointer ]
+    set w  [ $itclimageGUI InitializeLite $widget.[ pxvtable::vnewobj ] 2 ] 
+    pack $w -side left -fill x
+    return $itclimageGUI
+}
+
+itcl::body pxitclmultiImageGUI::AddImage { descr } {
+    
+    set newobj [ $this AddObject $descr ]
+    $this SetImage [ expr [ llength $itclobjectlist ] -1 ]    
+    return $newobj
+}
+
+itcl::body pxitclmultiImageGUI::SetImage { index } {
+
+    $this SetObject $index
+    $objectGUI configure -description [ $listbox get $currentobject ]
+    $objectGUI Update
+}
+
+itcl::body pxitclmultiImageGUI::Initialize { basewidg } {
+    
+    if { $initialized == 1 } { 
+	return $basewidget 
+    }
+    
+    pxitclmultiObjectGUI::Initialize $basewidg
+
+    $listbox configure -selectmode single -exportselection 0
+    eval "$listbox configure -selectioncommand { $this SetImage -1 }"
+    
+    set initialized 1
+    
+    return $basewidget
+}
+ 
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxitcllandmarks.tcl b/bioimagesuite30_src/bioimagesuite/base/pxitcllandmarks.tcl
new file mode 100644
index 0000000..2d8f81f
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxitcllandmarks.tcl
@@ -0,0 +1,414 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitcllandmarks 1.0
+
+# 	$Id: pxitcllandmarks.tcl,v 1.2 2003/08/14 17:49:42 xenios Exp xenios $	
+
+
+
+
+package require  pxitclobject  1.0
+
+
+# -------------------------------------------------------------------
+# Definition of pxitcllandmarks
+#
+#    a class that encapsulates an image (vtkImageData)
+#            its orientation , filename and status
+# -------------------------------------------------------------------
+
+itcl::class pxitcllandmarks {
+
+    inherit pxitclobject
+
+    # --- begin variable def -----
+
+    public variable status 
+    protected variable landmarkset 
+
+    # --- end of variable def -----
+
+    constructor { } {
+	pxitclobject::constructor 
+    } {
+	CreateNewLandmarks
+	UpdateStatus    
+    }
+
+    destructor  { $landmarkset Delete     }
+
+
+    # --- begin method def -----
+    public method GetObject { } { return $landmarkset }
+    public method GetType { } { return [ [ $landmarkset GetPoints ] GetNumberOfPoints ] }
+    public method GetDescription { } 
+    public method UpdateStatus { } { set status [ [ $landmarkset GetPoints ] GetNumberOfPoints ]  }
+    public method Copy   { obj args }
+    public method Clear { } 
+    public method UnLoad { } { return [ Clear ] }
+
+    public method Load   { args }
+    public method Save   { args }
+
+    # Methods additional to pxitclobject
+    
+    public method GetLandmarks { } { return $landmarkset }
+
+    public method GetLongDescription { } 
+    public method GetShortDescription { } 
+    public method GetSize { } { return [ $this GetLandmarksSize ] }
+    public method GetLandmarksSize { } 
+
+    public method CopyLandmarks   { newlandmarkset args }
+
+    public method CreateNewLandmarks { } 
+
+    # Procedures to Just Set Filename
+    public method Browse { description }
+
+
+    # Procedures to Ship To Viewer
+    public method Display { baseviewer }
+    public method Transform { transformation } 
+
+
+    # Testing Stuff
+    public method CompareTo  { fname { thr 0.001 } } 
+    # --- end method def -----
+}
+
+# ------------------- End of Header ---------------------------------
+itcl::body pxitcllandmarks::CreateNewLandmarks { } {
+
+    set landmarkset [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+}
+
+
+itcl::body pxitcllandmarks::Copy  { obj  } {
+
+    if { [ $obj isa pxitcllandmarks ] == 0 } {
+	return 0
+    }
+
+    set oldimg [ $obj GetLandmarks ] 
+    CopyLandmarks $oldimg 
+    set filename    [ $obj cget -filename ]
+    UpdateStatus
+}
+# ----------------------------------------------------------
+itcl::body pxitcllandmarks::CopyLandmarks { newimg  } {
+
+    if { [ $newimg IsA "vtkpxBaseCurve" ] == 0 } {
+	puts stdout "Bad Input"
+	return
+    }
+
+    $landmarkset Delete
+    set landmarkset [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+
+    $landmarkset Copy $newimg
+    UpdateStatus
+}
+
+# ----------------------------------------------------------
+itcl::body pxitcllandmarks::Clear { } {
+    catch { $landmarkset Delete }
+    CreateNewLandmarks
+    set orientation 0
+    set filename    ""
+    UpdateStatus
+}
+# ----------------------------------------------------------
+itcl::body pxitcllandmarks::GetLandmarksSize { } {
+
+    return [ $landmarkset GetNumPoints ]
+}
+
+# ----------------------------------------------------------
+itcl::body pxitcllandmarks::GetLongDescription { } {
+    
+    set x1 [ $landmarkset GetNumPoints ] 
+    
+    set line [ format "Number Of Points %d " $x1 ]
+
+    set line  "name=$this\n\t$line\n\tFilename= $filename"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitcllandmarks::GetDescription { } {
+    
+    set x1 [ $landmarkset GetNumPoints ] 
+    set line [ format "Number Of Points %d" $x1 ]
+    set line  "$line\nFilename=$filename\n"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitcllandmarks::GetShortDescription { } {
+    
+    set x1 [ $landmarkset GetNumPoints ] 
+    set line [ format "Number Of Points %d" $x1  ]
+    set line  "[ file tail $filename]  $line"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitcllandmarks::Browse { description } {
+
+    set f2path [ file dirname $filename ]
+    set f2tail [ file tail    $filename ]
+	
+    set fname  [tk_getOpenFile -title "Get Filename for $description" -filetypes { {"Landmark Files" {.land .vtk}}} -initialfile $f2tail -initialdir $f2path ]   
+    if { [ string length $fname ] > 0 } {
+	set filename $fname
+	return 1
+    }
+    return 0
+}
+# ----------------------------------------------------------
+itcl::body pxitcllandmarks::Load { args } {
+
+    set len [ llength $args ]
+    if { [ string length $filename ] == 0 && $len == 0 } { return  }
+
+
+    if { $len < 1 } {
+	set fname $filename
+    } else  { 
+	set fname [ lindex $args 0 ] 
+    }
+
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    } else {
+	set desc "Landmark Set"
+    }
+
+
+    if { [ string length $fname ] == 0 } {
+
+
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getOpenFile -title "Load $desc" -filetypes { {"Landmarks Files" {.land .vtk .vtp}}} -initialfile $f2tail -initialdir $f2path ]   
+    }
+    
+
+    if { [ string length $fname ] <1 } {
+	return 0
+    }
+
+    if { [ file extension $fname ] == ".vtk" || [ file extension $fname ] == ".vtp" } {
+	if { [ file extension $fname ]  == ".vtp"  } {
+	    set ana [ vtkXMLPolyDataReader [ pxvtable::vnewobj ]]
+	} else {
+	    set ana [ vtkPolyDataReader [ pxvtable::vnewobj ]]
+	}
+	$ana SetFileName $fname
+	$ana Update
+	$landmarkset SetFromPoints [ [ $ana GetOutput ] GetPoints ]
+	$this configure -filename $fname
+	$ana Delete
+    } else {
+	$landmarkset Load $fname
+	$this configure -filename $fname
+    }
+    
+
+    return 1
+
+}
+# ----------------------------------------------------------
+itcl::body pxitcllandmarks::Save { args } {
+
+    set len [ llength $args ]
+    if { $len < 1 } {
+	set fname $filename
+    } else  { 
+	set fname [ lindex $args 0 ] 
+    }
+
+    set desc "Landmark Set"
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    }
+
+
+    if { [ string length $fname ] == 0 } {
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getSaveFile -title "Saving $desc" -filetypes { {"Landmarks Files" {.land}}} -initialfile $f2tail -initialdir $f2path ]   
+    }
+    
+
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+    
+    $landmarkset Save $fname
+    set filename $fname
+    return 1
+}
+# ----------------------------------------------------------
+
+itcl::body pxitcllandmarks::Display { baseviewer } {
+    
+    set landmarkcontrol 0
+    catch {     set  landmarkcontrol [ [ $baseviewer GetLandmarkControl ] GetLandmarkControl ] }
+
+    if { $landmarkcontrol == 0 } {
+	::pxtclutil::Warning "Bad baseviewer ($baseviewer) Specified. Cannot display landmarks\n"
+	return 0
+    }
+    
+    #    $landmarkset Save "temp.land"
+    $landmarkcontrol SetClipboardCollection $landmarkset 0
+    ::pxtclutil::Info "Placed landmarks $filename in the clipboard of the landmarks control"
+    
+    [ $baseviewer GetLandmarkControl ] ShowWindow
+    return 1
+} 
+# ----------------------------------------------------------
+itcl::body pxitcllandmarks::Transform { transformation } {
+
+    set pt [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    $pt Copy $landmarkset
+    $pt Compact
+
+
+    
+    set poly [ vtkPolyData [ pxvtable::vnewobj ]]
+    $poly SetPoints [ $pt GetPoints ]
+
+    set vt [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ]]
+    $vt SetInput $poly
+    $vt SetTransform $transformation
+    $vt Update
+
+    $landmarkset SetFromPoints [ [ $vt GetOutput ] GetPoints ]
+    $vt Delete
+    $poly Delete
+    $pt Delete
+
+    UpdateStatus
+    return 1
+} 
+
+
+itcl::body pxitcllandmarks::CompareTo  { fname { thr 0.001 } }  {
+
+    set pt [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    $pt Copy [ $this GetLandmarks ]
+    $pt Compact
+
+    set pt2 [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    $pt2 Load $fname
+    $pt2 Compact
+
+    set ut [ vtkbisTestUtil New ]
+    $ut ClearStatus
+    puts stderr "Comparing [ $this GetDescription ] to $fname, threshold=$thr"
+    set ok [ $ut ComparePoints [ $pt GetPoints ] [ $pt2 GetPoints ] $thr ]
+    set a [ $ut ReturnStatus ]
+    $ut Delete
+    $pt Delete
+    $pt2 Delete
+    return [ list $ok $a ]
+}
+# ---------------------------------------------------------------------------------------------
+
+
+itcl::class pxitcllandmarksGUI {
+
+    inherit pxitclobjectGUI
+
+    public variable browsebutton
+
+    constructor { } {
+	pxitclobjectGUI::constructor
+    } { 
+	set thisparam($this,status) "vtkpxBaseCurve"
+	set thisparam($this,shortfilename) "none"
+	set thisparam($this,descriptionbox) 0
+	Reset
+    }
+
+    destructor { }
+
+    public method SetObject { tr } { return [ SetLandmarks $tr ] }
+    public    method GetLandmarks { } { return $itclobject  }
+
+    protected method CreateNewObject { } 
+    public    method Initialize { basewidg } 
+    public    method SetLandmarks { isur }
+    public    method BrowseLandmarks { } 
+
+
+}
+# ----------------------------------------------------------
+itcl::body pxitcllandmarksGUI::CreateNewObject { } {
+    set itclobject  [ [  pxitcllandmarks \#auto ] GetThisPointer ]
+}
+
+itcl::body pxitcllandmarksGUI::BrowseLandmarks { } {
+    $itclobject Browse $description
+    Update
+}
+
+itcl::body pxitcllandmarksGUI::SetLandmarks { trn } {
+    
+    if { [ $trn isa pxitcllandmarks ] == 0 } {
+	return 0
+    }
+	
+    if { $owns_object == 1} {
+	catch { itcl::delete object $itclobject }
+    }
+
+    set itclobject $trn
+    set owns_object 0
+    Update
+}
+
+itcl::body pxitcllandmarksGUI::BrowseLandmarks { } {
+    $itclobject Browse $description
+    Update
+}
+
+itcl::body pxitcllandmarksGUI::Initialize { basewidg } {
+
+    if { $initialized == 1 } { return $basewidget }
+    pxitclobjectGUI::Initialize $basewidg
+
+    set browsebutton [ eval "button $buttonbar.b -text Browse -command { $this BrowseLandmarks }" ]
+    pack  $buttonbar.b   -side left -fill x -expand f
+    update idletasks
+
+    Update
+    return $basewidget
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxitclmesh.tcl b/bioimagesuite30_src/bioimagesuite/base/pxitclmesh.tcl
new file mode 100644
index 0000000..cea0322
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxitclmesh.tcl
@@ -0,0 +1,565 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclmesh 1.0
+
+# 	$Id: pxitclmesh.tcl,v 1.2 2003/08/14 17:49:42 xenios Exp xenios $	
+
+
+
+
+package require  pxitclobject  1.0
+package provide pxitclmesh 1.0
+
+# -------------------------------------------------------------------
+# Definition of pxitclmesh
+#
+#    a class that encapsulates a mesh (vtkUnstructureGrid)
+#            its orientation , filename and status
+# -------------------------------------------------------------------
+
+itcl::class pxitclmesh {
+
+    inherit pxitclobject
+
+    # --- begin variable def -----
+
+    public variable status 
+    protected variable mesh 
+
+    # --- end of variable def -----
+
+    constructor { } {
+	pxitclobject::constructor 
+    } {
+	CreateNewMesh
+	UpdateStatus    
+    }
+
+    destructor  { $mesh Delete     }
+
+
+    # --- begin method def -----sur
+    public method GetObject { } { return $mesh }
+    public method GetType { } { return [ $mesh GetNumberOfPoints ] }
+    public method GetDescription { } 
+    public method UpdateStatus { } { set status [ $mesh GetNumberOfPoints ]  }
+    public method Copy   { obj args }
+    public method Clear { } 
+    public method UnLoad { } { return [ Clear ] }
+
+    public method Load   { args }
+    public method Save   { args }
+
+    # Methods additional to pxitclobject
+    
+    public method GetMesh { } { return $mesh }
+    public method GetSurfaceRepresentation { }
+
+    public method GetLongDescription { } 
+    public method GetShortDescription { } 
+    public method GetMeshSize { } 
+    public method GetSize { } { return [ $this GetMeshSize ] }
+
+    public method DeepCopy    { obj } { Copy $obj 1    }
+    public method ShallowCopy { obj } { Copy $obj 0    }
+
+    public method DeepCopyMesh    { newmesh } { CopyMesh $newmesh 1    }
+    public method ShallowCopyMesh { newmesh } { CopyMesh $newmesh 0    }
+    public method CopyMesh   { newmesh mode }
+
+    public method CreateNewMesh { } 
+
+    # Procedures to Just Set Filename
+    public method Browse { description }
+
+    # Procedures to Ship To Viewer
+    public method Display { baseviewer }
+    public method Transform { gen }
+
+
+    # Compare with FileName
+    public method CompareTo  { fname } 
+
+
+    # --- end method def -----
+}
+
+# ------------------- End of Header ---------------------------------
+itcl::body pxitclmesh::CreateNewMesh { } {
+
+    set mesh [ vtkUnstructuredGrid [ pxvtable::vnewobj ]]
+}
+
+
+itcl::body pxitclmesh::Copy   { obj args } {
+
+    set mode 0
+    if { [ llength $args ] > 0 } {
+	set mode [ expr [ lindex $args 0 ] > 0 ]
+    }
+
+    if { [ $obj isa pxitclmesh ] == 0 } {
+	return 0
+    }
+
+    set oldimg [ $obj GetMesh ] 
+    CopyMesh $oldimg $mode
+    set filename    [ $obj cget -filename ]
+    UpdateStatus
+}
+
+
+itcl::body pxitclmesh::GetSurfaceRepresentation { } {
+
+    set sur [ vtkPolyData [ pxvtable::vnewobj ]]
+
+    # This works, but is very slow compared to the C++ version
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary vtkjoStereoVisionTCL vtkjoConvertUnstructuredGridToPolyDataFilter ]
+    if { $ok != 0 } {
+        set convert [ vtkjoConvertUnstructuredGridToPolyDataFilter New ]
+        $convert SetGridInput $mesh
+        $convert Update
+        $sur ShallowCopy [ $convert GetOutput ]
+        $convert Delete
+    } else {
+    
+        # Procedure taken from vtkpxAbaqusUtil::CreateSurfaceFromGrid
+        $sur SetPoints [ $mesh GetPoints ]
+        [ $sur GetPointData ] SetScalars [[ $mesh GetPointData ] GetScalars ]
+
+        set ntetra [[ $mesh GetCells ] GetNumberOfCells ]
+
+        set polys [ vtkCellArray [ pxvtable::vnewobj ]]
+        $polys Allocate [ expr $ntetra * 4 ] 1000
+
+        set npts [ vtkIdList [ pxvtable::vnewobj ]]
+        for { set j 0 } { $j < $ntetra } { incr j } {
+            set cell [ $mesh GetCell $j ]
+            set numpts [ $cell GetNumberOfPoints ]
+            set pts [ vtkIdList [ pxvtable::vnewobj ]]
+        
+            for { set i 0 } { $i < $numpts } { incr i } {
+                $pts InsertNextId [ $cell GetPointId $i ]
+            }
+        
+            $npts InsertId 0 [ $pts GetId 0 ]
+            $npts InsertId 1 [ $pts GetId 1 ]
+            $npts InsertId 2 [ $pts GetId 2 ]
+            $polys InsertNextCell $npts
+
+            $npts InsertId 0 [ $pts GetId 1 ]
+            $npts InsertId 1 [ $pts GetId 2 ]
+            $npts InsertId 2 [ $pts GetId 3 ]
+            $polys InsertNextCell $npts
+
+            $npts InsertId 0 [ $pts GetId 2 ]
+            $npts InsertId 1 [ $pts GetId 3 ]
+            $npts InsertId 2 [ $pts GetId 0 ]
+            $polys InsertNextCell $npts
+
+            $npts InsertId 0 [ $pts GetId 3 ]
+            $npts InsertId 1 [ $pts GetId 0 ]
+            $npts InsertId 2 [ $pts GetId 1 ]
+            $polys InsertNextCell $npts
+
+            $pts Delete
+        }
+        $npts Delete
+    
+        $sur SetPolys $polys
+        $polys Delete
+    }
+    # puts stderr "Done creating surface"
+    
+    return $sur
+}
+
+
+# ----------------------------------------------------------
+itcl::body pxitclmesh::CopyMesh { newimg mode } {
+
+    set mode [ expr $mode > 0 ]
+
+    if { [ $newimg IsA "vtkUnstructuredGrid" ] == 0 } {
+	puts stdout "Bad Input"
+	return
+    }
+
+    $mesh Delete
+    set mesh [ vtkUnstructuredGrid [ pxvtable::vnewobj ]]
+
+    #    puts stderr "In Copy Mesh mode=$mode, mesh = $mesh [ $mesh GetClassName ], newimg=$newimg [ $newimg GetClassName ]"
+
+    if { $mode == 0 } {
+	$mesh ShallowCopy $newimg
+    } else {
+	$mesh DeepCopy $newimg
+    }
+
+    UpdateStatus
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclmesh::Clear { } {
+    catch { $mesh Delete }
+    CreateNewMesh
+    set orientation 0
+    set filename    ""
+    UpdateStatus
+}
+# ----------------------------------------------------------
+itcl::body pxitclmesh::GetMeshSize { } {
+
+    return [ $mesh GetNumberOfPoints ]
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclmesh::GetLongDescription { } {
+    
+    set x1 [ $mesh GetNumberOfPoints ] 
+    set s1 [ $mesh GetNumberOfCells  ]
+    set bd [ $mesh GetBounds ]
+    set t1 [ $mesh GetNumberOfScalarComponents ] 
+    
+    set line [ format "Number Of Points %d Cells=%d Bounds= $bd" $x1 $s1 ]
+
+    set line  "name=$this\n\t$line\n\tFilename= $filename"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitclmesh::GetDescription { } {
+    
+    set x1 [ $mesh GetNumberOfPoints ] 
+    set s1 [ $mesh GetNumberOfCells  ]
+    set line [ format "Number Of Points %d Cells=%d" $x1 $s1 ]
+    set line  "$line\nFilename=$filename\n"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitclmesh::GetShortDescription { } {
+    
+    set x1 [ $mesh GetNumberOfPoints ] 
+    set s1 [ $mesh GetNumberOfCells  ]
+    set line [ format "Number Of Points %d Cells=%d" $x1 $s1 ]
+    set line  "[ file tail $filename]  $line"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitclmesh::Browse { description } {
+
+    set f2path [ file dirname $filename ]
+    set f2tail [ file tail    $filename ]
+	
+    set fname  [tk_getOpenFile -title "Get Filename for $description" -filetypes { {"Mesh Files" {.ugrid .ugridx}}} -initialfile $f2tail -initialdir $f2path ]   
+    if { [ string length $fname ] > 0 } {
+	set filename $fname
+	return 1
+    }
+    return 0
+}
+# ----------------------------------------------------------
+itcl::body pxitclmesh::Load { args } {
+
+    set len [ llength $args ]
+    if { [ string length $filename ] == 0 && $len == 0 } { return  }
+
+
+    if { $len < 1 } {
+	set fname $filename
+    } else  { 
+	set fname [ lindex $args 0 ] 
+    }
+
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    } else {
+	set desc "Mesh"
+    }
+
+
+    if { [ string length $fname ] == 0 } {
+
+
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getOpenFile -title "Load $desc" -filetypes { {"Mesh Files" {.ugrid .ugridx}}} -initialfile $f2tail -initialdir $f2path ]   
+    }
+    
+
+    if { [ string length $fname ] <1 } {
+	return 0
+    }
+
+    catch {
+	if { [ file extension $fname ]  == ".ugridx"  } {
+	    set ana [ vtkXMLUnstructuredGridReader [ pxvtable::vnewobj ]]
+	} else {
+	    set ana [ vtkUnstructuredGridReader [ pxvtable::vnewobj ]]
+	}
+	$ana SetFileName $fname
+	$ana Update
+	$this ShallowCopyMesh [ $ana GetOutput ]
+	$this configure -filename $fname
+	$ana Delete
+    }
+    return 1
+}
+# ----------------------------------------------------------
+itcl::body pxitclmesh::Save { args } {
+
+    set len [ llength $args ]
+    if { $len < 1 } {
+	set fname $filename
+    } else  { 
+	set fname [ lindex $args 0 ] 
+    }
+
+    set desc "Image"
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    }
+
+
+    if { [ string length $fname ] == 0 } {
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getSaveFile -title "Saving $desc" -filetypes { {"Mesh Files" {.ugrid}}} -initialfile $f2tail -initialdir $f2path ]   
+    }
+    
+    if { [ string length $fname ] < 0 } {
+	return 0
+    }
+    
+    set ana [ vtkUnstructuredGridWriter  [ pxvtable::vnewobj ]]
+    $ana SetInput $mesh
+    $ana SetFileName $fname
+    $ana Update
+    set filename $fname
+#$this configure -filename $fnamea
+    $ana Delete 
+    return 1
+}
+# ----------------------------------------------------------
+itcl::body pxitclmesh::Display { baseviewer } {
+    
+    # Create a surface and send to polydatacontrol as per pxitclsurface
+    set polydatacontrol 0
+    catch { set polydatacontrol [ [ $baseviewer GetPolyDataControl ] GetPolyDataControl ] }
+
+    if { $polydatacontrol == 0 } {
+        ::pxtclutil::Warning "Bad baseviewer ($baseviewer) specified. Cannot display mesh surface\n"
+        return 0
+    }
+
+    # Create surface representation by calling this oject's GetSurfaceRepresentation method
+    $polydatacontrol SetClipboardSurface [ $this GetSurfaceRepresentation ] $filename
+    ::pxtclutil::Info "Placed mesh surface $filename in the clipboard of the surface control"
+
+    [ $baseviewer GetPolyDataControl ] ShowWindow
+    return 1
+} 
+# ----------------------------------------------------------
+itcl::body pxitclmesh::Transform { transformation } {
+
+    # Transform Points and then copy back
+    # Actually, maybe this can just be done using vtkTransformFilter,
+    # which takes a vtkPointSet as input
+    # TODO: Test
+    set xform [ vtkTransformFilter [ pxvtable::vnewobj ]]
+    $xform SetInput $mesh 
+    $xform SetTransform $transformation
+    $xform Update
+    $this ShallowCopyMesh [ $xform GetOutput ]
+    $xform Delete
+    return 1
+} 
+
+
+itcl::body pxitclmesh::CompareTo  { fname } {
+
+    # TODO: Test
+    set tmp [ pxitclmesh \#auto ]
+    set ok [ $tmp Load $fname ]
+    if { $ok == 0 } {
+        itcl::delete object $tmp
+        return 0
+    }
+
+    set ut [ vtkbisTestUtil New ]
+    # Just compare the surface representations!
+    set ok [ $ut CompareSurfaces [[ $this GetMesh ] GetSurfaceRepresentation ] [[ $tmp GetMesh ] GetSurfaceRepresentation ]
+    itcl::delete object $tmp
+    $ut Delete
+    return $ok
+}
+
+
+# ----------------------------------------------------------
+#  GUI for pxitclmesh
+# ----------------------------------------------------------
+itcl::class pxitclmeshGUI {
+
+    inherit pxitclobjectGUI
+
+    public variable browsebutton
+
+    constructor { } {
+	pxitclobjectGUI::constructor
+    } { 
+	set thisparam($this,status) "vtkUnstructuredGrid"
+	set thisparam($this,shortfilename) "none"
+	set thisparam($this,descriptionbox) 0
+	Reset
+    }
+
+    destructor { }
+
+    public method SetObject { tr } { return [ SetMesh $tr ] }
+    public    method GetMesh { } { return $itclobject  }
+
+    protected method CreateNewObject { } 
+    public    method Initialize { basewidg } 
+    public    method SetMesh { imesh }
+    public    method BrowseMesh { } 
+
+
+}
+# ----------------------------------------------------------
+itcl::body pxitclmeshGUI::CreateNewObject { } {
+    set itclobject  [ [  pxitclmesh \#auto ] GetThisPointer ]
+}
+
+itcl::body pxitclmeshGUI::BrowseMesh { } {
+    $itclobject Browse $description
+    Update
+}
+
+itcl::body pxitclmeshGUI::SetMesh { trn } {
+    
+    if { [ $trn isa pxitclmesh ] == 0 } {
+	return 0
+    }
+	
+    if { $owns_object == 1} {
+	catch { itcl::delete object $itclobject }
+    }
+
+    set itclobject $trn
+    set owns_object 0
+    Update
+}
+
+itcl::body pxitclmeshGUI::BrowseMesh { } {
+    $itclobject Browse $description
+    Update
+}
+
+itcl::body pxitclmeshGUI::Initialize { basewidg } {
+
+    if { $initialized == 1 } { return $basewidget }
+    pxitclobjectGUI::Initialize $basewidg
+
+    set browsebutton [ eval "button $buttonbar.b -text Browse -command { $this BrowseMesh }" ]
+    pack  $buttonbar.b   -side left -fill x -expand f
+    update idletasks
+
+    Update
+    return $basewidget
+}
+
+# ----------------------------------------------------------
+#  GUI for multiple image object
+# ----------------------------------------------------------
+itcl::class pxitclmultiMeshGUI {
+
+    inherit pxitclmultiObjectGUI
+
+    constructor { } {
+	pxitclmultiObjectGUI::constructor
+	set description "Mesh"
+    } {
+    }
+    
+    destructor { }
+    
+    public    method Initialize { basewidg } 
+
+    public    method AddMesh { descr }
+    public    method SetMesh { index } 
+    public    method GetMesh { index } { return [ GetObject $index ] }
+    public    method DeleteMesh { index } { DeleteObject $index }
+
+    protected method CreateNewObject { }
+    protected method CreateNewObjectGUI { widget }
+
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclmultiMeshGUI::CreateNewObject { } {
+
+    return  [ [  pxitclmesh \#auto ] GetThisPointer ]
+}
+
+itcl::body pxitclmultiMeshGUI::CreateNewObjectGUI { widget } {
+    set itclimageGUI [ [ pxitclmeshGUI \#auto ] GetThisPointer ]
+    pack [ $itclimageGUI Initialize $widget.[ pxvtable::vnewobj ] ] -side left -fill x
+    return $itclimageGUI
+}
+
+itcl::body pxitclmultiMeshGUI::AddMesh { descr } {
+    
+    set newobj [ $this AddObject $descr ]
+    $this SetMesh [ expr [ llength $itclobjectlist ] -1 ]    
+    return $newobj
+}
+
+itcl::body pxitclmultiMeshGUI::SetMesh { index } {
+
+    $this SetObject $index
+    $objectGUI configure -description [ $listbox get $currentobject ]
+    $objectGUI Update
+}
+
+itcl::body pxitclmultiMeshGUI::Initialize { basewidg } {
+    
+    if { $initialized == 1 } { 
+	return $basewidget 
+    }
+    
+    pxitclmultiObjectGUI::Initialize $basewidg
+
+    $listbox configure -selectmode single -exportselection 0
+    eval "$listbox configure -selectioncommand { $this SetMesh -1 }"
+    
+    set initialized 1
+
+    
+    return $basewidget
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxitclobject.tcl b/bioimagesuite30_src/bioimagesuite/base/pxitclobject.tcl
new file mode 100644
index 0000000..3afd581
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxitclobject.tcl
@@ -0,0 +1,731 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclobject 1.0
+
+# 	$Id: pxitclobjectGUI.tcl,v 1.1 2002/08/03 13:36:49 papad Exp papad $	
+
+
+
+
+package require  pxtclutil  1.0
+package require Itcl 3.2
+package require pxvtable 1.0
+
+# --------------------------------------------------------------
+#  abstract base GUI Class for pxitcltransform, pxitclimage etc.
+# --------------------------------------------------------------
+itcl::class pxitclobject {
+
+    # --- begin variable def -----
+
+    public variable filename  ""
+
+    # --- end of variable def -----
+
+    constructor { } {  }
+    destructor  { } 
+
+
+    # --- begin method def -----
+    public method GetThisPointer { } { return $this }
+
+    # Things that must be over-ridden by derived classes
+    # --------------------------------------------------
+    public method GetObject { } { return 0 }
+    public method GetType { } { return "vtkObject" }
+    public method GetFileName { } { return $filename }
+    public method SetFileName { f } { $this configure -filename $f }
+    public method GetDescription { } { return [ $this GetType ]}
+    public method GetShortDescription { } { return [ $this GetType ]}
+    public method UpdateStatus { }  { }
+    public method Copy    { obj args } { }
+    public method DeepCopy    { obj } { Copy $obj 1    }
+    public method ShallowCopy { obj } { Copy $obj 0    }
+
+    public method GetSize { } { return 0}
+
+    # Essentially Release Memory
+    public method Clear   { } { } 
+
+    # Procedures to Load/Save 
+    public method Load { args } { }
+    public method Save { args } { }
+
+    # Procedures to Add/Get comment
+    public method AddComment { cmt } { } 
+    public method GetComment {     } { return "no comment" } 
+    public method CompareTo  { fname { thr 0.001 } } { 
+	puts stdout "No test for this type of object -- $this to object from $fname ($thr)"
+	return 0
+    }
+}
+
+
+# --------------------------------------------------------------
+#  abstract base GUI Class for pxitcltransformGUI pxitclimageGUI
+# --------------------------------------------------------------
+
+itcl::class pxitclobjectGUI {
+
+    public    variable  itclobject 0
+    protected variable  basewidget  0
+    protected variable  initialized 0
+    protected common    thisparam
+    protected variable  owns_object 1
+    public    variable  description Object
+    public    variable  callback 0 
+    public variable     buttonbar 0
+    protected variable  numlines 3
+
+    public variable  loadbutton 0
+    public variable  savebutton 0
+    public variable  clearbutton 0
+    public variable  statusbar 0
+    
+
+    constructor { } {
+	set thisparam($this,status) "vtkObject"
+	set thisparam($this,shortfilename) "identity"
+	set thisparam($this,descriptionbox) 0
+    }
+
+    destructor {	if { $owns_object == 1} {
+	    catch { itcl::delete object $itclobject }
+	}
+    }
+
+    public    method GetThisPointer { } { return $this }
+    public    method GetObject { } { return $itclobject  }
+    public    method Reset { } 
+    public    method Initialize { basewidg } 
+    public    method InitializeLite { basewidg args } 
+    public    method Update { }
+    public    method Info { }
+    public    method LoadObject { } 
+    public    method SaveObject { } 
+    public    method ClearObject { } 
+
+    public    method AddFunction { command name post }
+    # -----------------------------------------
+    # Function that must be overriden
+    protected method CreateNewObject { } { puts stdout "Error!"}
+    public    method SetObject { tr } { puts stdout "Error!" }
+
+}
+# ----------------------------------------------------------
+itcl::body pxitclobjectGUI::Reset { } {
+
+    if { $itclobject !=0 && $owns_transformation == 1} {
+	itcl::delete object $itclobject
+    }
+    
+    CreateNewObject
+    set thisparam($this,shortfilename) [ $itclobject cget -filename ]
+    set owns_object 1
+    Update
+}
+
+itcl::body pxitclobjectGUI::Info { } {
+
+    tk_messageBox -type ok -title "Object Info" -message  [ $itclobject GetDescription ] -parent $basewidget
+}
+
+itcl::body pxitclobjectGUI::Update { } {
+    
+    if { $thisparam($this,descriptionbox) !=0 } {
+
+	set tbox $thisparam($this,descriptionbox)
+	$tbox delete 1.0 end
+	$tbox insert end [ $itclobject GetDescription ]
+	$tbox see 1.0
+    }
+    set thisparam($this,shortfilename) [ file tail [ $itclobject cget -filename ]]
+    set thisparam($this,classname) [ $itclobject GetType ]
+    if { $basewidget !=0 } {
+	set a [ $basewidget cget -labeltext ]
+	if { $a != $description } {
+	    $basewidget configure -labeltext  $description
+	}
+	if { $callback !=0 } {
+	    eval $callback
+	}
+    }
+}
+
+itcl::body pxitclobjectGUI::LoadObject { } {
+    $itclobject Load "" $description
+    Update
+}
+
+itcl::body pxitclobjectGUI::SaveObject { } {
+    $itclobject Save "" $description
+    Update
+}
+
+itcl::body pxitclobjectGUI::ClearObject { } {
+    $itclobject Clear
+    Update
+}
+
+
+itcl::body pxitclobjectGUI::Initialize { basewidg } {
+
+    if { $initialized == 1 } { 
+	return $basewidget 
+    }
+    global tcl_platform
+
+    set basewidget [  iwidgets::Labeledframe $basewidg -labelpos n -labeltext $description ]
+    set base [ $basewidget childsite ]
+
+    frame $base.mid
+
+    if { $tcl_platform(platform) == "windows" } {
+	set thisparam($this,descriptionbox) [ text $base.top -width 35 -height $numlines -borderwidth 2 -relief raised -font { fixed 8 }]
+    } else {
+	set thisparam($this,descriptionbox) [ text $base.top -width 35 -height $numlines -borderwidth 2 -relief raised -font { fixed 10 }]
+    }
+    
+    $base.top configure -bg white -fg black
+
+    iwidgets::entryfield $base.mid.1 -textvariable [ itcl::scope thisparam($this,shortfilename) ] -width 50 -labeltext "Nm:"
+    iwidgets::entryfield $base.mid.2 -textvariable [ itcl::scope thisparam($this,classname) ] -width 10 -labeltext "St: "
+
+    [ $base.mid.2 component entry  ] configure -bg white -fg black
+    [ $base.mid.1 component entry  ] configure -bg white -fg black
+
+    set statusbar $base.mid.2
+    [ $base.mid.2  component entry ] configure -state disabled
+    pack $base.mid.2 -side right -expand false 
+    pack $base.mid.1 -side left -expand true -fill x
+    
+    set buttonbar [ frame $base.bot ]
+    eval "button $buttonbar.0l -text Load -command { $this LoadObject }"
+    set loadbutton $buttonbar.0l
+    eval "button $buttonbar.0s -text Save -command { $this SaveObject }"
+    set savebutton $buttonbar.0s
+    eval "button $buttonbar.0cl -text Clear -command { $this ClearObject }"
+    set clearbutton $buttonbar.0cl    
+    pack  $buttonbar.0l $buttonbar.0s    -side left -fill x -expand f
+    pack  $buttonbar.0cl   -side right -fill x -expand f
+
+    pack  $base.mid $base.top $base.bot -side top -expand f -fill x -padx 5 -pady 2
+    set initialized 1
+    return $basewidget
+}
+
+itcl::body pxitclobjectGUI::InitializeLite { basewidg args } {
+
+    if { $initialized == 1 } { 
+	return $basewidget 
+    }
+
+    set packmode 0
+    if { [ llength $args ] > 0 } {
+	set packmode [ lindex $args 0 ] 
+    }
+
+    set basewidget [  iwidgets::Labeledframe $basewidg -labelpos n -labeltext $description ]
+    set base [ $basewidget childsite ]
+    pack $basewidg -side top -expand true -fill x
+
+    frame $base.top; pack $base.top
+    set buttonbar [ frame $base.bottom ]
+
+    iwidgets::entryfield $base.top.1 -textvariable [ itcl::scope thisparam($this,shortfilename) ] -width 30 -labeltext ""
+    [ $base.top.1 component entry ] configure -bg white -fg black
+    
+    if { $packmode > 2 } {
+	iwidgets::entryfield $base.top.2 -textvariable [ itcl::scope thisparam($this,classname) ] -width 6 -labeltext "St: "
+	[ $base.top.2  component entry ] configure -state disabled
+	set packmode 2
+	pack $base.top.2  -side right -expand false
+    }
+    pack $base.top.1  -side left -expand true -fill x 
+
+    if { $packmode == 0 } {
+	pack $buttonbar -side right -expand f -padx 0
+	pack $base.top -side left -expand f -fill x
+	eval "button $buttonbar.3 -text Load -command { $this LoadObject }"
+	set loadbutton $buttonbar.3
+	eval "button $buttonbar.4 -text Save -command { $this SaveObject }"
+	set savebutton $buttonbar.4
+	eval "button $buttonbar.45 -text Clear -command { $this ClearObject }"
+	set clearbutton $buttonbar.45    
+
+	eval "button $buttonbar.5 -text \"I\" -command { $this Info }"
+	pack $buttonbar.3 $buttonbar.4 $buttonbar.45 $buttonbar.5 -side left -expand f 
+    } elseif { $packmode == 1 } {
+	pack $base.top $buttonbar -side top -expand true -fill x 
+	eval "button $buttonbar.3 -text Load -command { $this LoadObject }"
+	set loadbutton $buttonbar.3
+	eval "button $buttonbar.4 -text Save -command { $this SaveObject }"
+	set savebutton $buttonbar.4
+	eval "button $buttonbar.5 -text Clear -command { $this ClearObject }"
+	set clearbutton  $buttonbar.5
+	eval "button $buttonbar.6 -text Info -command { $this Info }"
+	pack $buttonbar.3 $buttonbar.4 $buttonbar.5 $buttonbar.6 -side top -expand f 
+    } else {
+	pack $base.top $buttonbar -side top -expand true -fill x 
+	eval "button $buttonbar.3 -text Load -command { $this LoadObject } -padx 1"
+	set loadbutton $buttonbar.3
+	eval "button $buttonbar.4 -text Save -command { $this SaveObject } -padx 1"
+	set savebutton $buttonbar.4
+	eval "button $buttonbar.45 -text Clear -command { $this ClearObject } -padx 1"
+	set clearbutton $buttonbar.45    
+
+	eval "button $buttonbar.5 -text \"Info\" -command { $this Info }"
+	pack $buttonbar.3 $buttonbar.4 $buttonbar.45 $buttonbar.5 -side left -expand false
+    }
+
+
+    set initialized 1
+
+    return $basewidget
+}
+
+
+itcl::body pxitclobjectGUI::AddFunction { command name post } {
+
+    if { $initialized == 0  } {
+	return 0
+    }
+    set a $buttonbar.[pxvtable::vnewobj ]
+    eval  "button $a -text \"$name\" -command { $command \[ $this GetObject \] $post } -padx 1 "
+    pack $a -side left -fill x -expand f -padx 0
+}
+
+
+# --------------------------------------------------------------
+#  abstract base GUI Class for pxitclmutltitransformGUI pxitclmutltiimageGUI
+# --------------------------------------------------------------
+
+itcl::class pxitclmultiObjectGUI {
+
+    public    variable  itclobjectlist "" 
+    public    variable  currentobject 0
+    protected variable  objectGUI 0
+    protected variable  basewidget  0
+    protected variable  initialized 0
+    protected common    thisparam
+    public    variable  description "Object"
+    public    variable  callback  ""
+    public    variable  listbox 0
+    public    variable  enableadd 1
+    public    variable  enabledelete 1
+    public    variable  enabledeleteall 0
+    public    variable  enableupdown 0
+    protected variable  objectindex 0
+
+    constructor { } {
+    }
+    
+    destructor {
+	set l [ llength $itclobjectlist ]
+	for { set a 0 } { $a < $l } { incr a } {
+	    catch { itcl::delete object [ lindex $itclobjectlist $a ] }
+	}
+    }
+    
+    public    method GetThisPointer { } { return $this }
+
+    public    method Initialize { basewidg } 
+    public    method InitializeLite { basewidg } 
+    public    method Update { } { $objectGUI Update } 
+  
+    public    method AddObject { descr }    
+    public    method SetObject { { index -1 } }
+    public    method GetObject { {  index -1 } }     
+    public    method DeleteObject { index }
+    public    method DeleteAllObjects { { force 0 } { addone 1 } }
+    public    method AddFunction { command name post } { $objectGUI AddFunction $command $name $post }
+    public    method CallbackFunction { }
+    public    method GetCurrentObject { }
+    public    method CurrentObjectModified { }
+    public    method GetNumberOfObjects { } { return [ llength $itclobjectlist ] }
+    public    method GetNextObjectIndex { } { return $objectindex }
+    public    method MoveCurrentObject { direction }
+    public    method SingleObjectGUIUpdate { args } { $this CallbackFunction }
+
+    # -----------------------------------------
+    # Function that must be overriden
+    protected method CreateNewObject { } { puts stdout "Error!"}
+    protected method CreateNewObjectGUI { widget } { puts stdout "Error!"}
+    public    method AddInternalObject {  }    
+    public    method DeleteInternalObject {  }    
+    public    method GetObjectGUI { } { return $objectGUI }
+    
+}
+
+itcl::body  pxitclmultiObjectGUI::GetObject { {  index -1 } } {
+
+    if { $initialized == 0 } { 	return 0  }
+    
+    if { $index == - 1} {
+	set index [ $listbox index [ $listbox getcurselection ]  ]
+    }
+
+    return [ [ lindex $itclobjectlist $index ] GetThisPointer ]
+}
+
+itcl::body pxitclmultiObjectGUI::SetObject { { index -1 } } {
+    
+    if { $initialized == 0 } { 	return 0  }
+
+    set ln [ llength $itclobjectlist  ]
+
+    if { $index == - 1 } { set index [ $listbox curselection ]    }
+    if { $index < 0 || $index >= $ln } { set index $currentobject } 
+
+
+    # Disable callback now
+    $objectGUI configure -callback 0
+
+    set currentobject $index    
+    $objectGUI configure -description [ $listbox get $currentobject ]
+    $listbox selection clear 0 [ expr $ln -1 ]
+    $listbox selection set $index $index
+    $objectGUI SetObject [ lindex $itclobjectlist $index ]
+
+    $this CallbackFunction
+
+    # renable callback
+    eval "$objectGUI configure -callback   { $this SingleObjectGUIUpdate }"
+    return $index 
+}
+
+itcl::body pxitclmultiObjectGUI::AddInternalObject { } {
+
+    set a  [ GetNextObjectIndex ] 
+    set b  [ string range $description 0 4 ]
+    set desc "${b}.${a}"
+    return [ [ AddObject $desc ] GetThisPointer ]
+}
+
+
+
+
+itcl::body pxitclmultiObjectGUI::DeleteInternalObject { } {
+
+    set name [ $listbox get $currentobject ]
+    set a  [ llength $itclobjectlist ]
+    if { $a == 1 } {
+	::pxtclutil::Warning "Cannot delete $name. This is the only object available!"
+	return 0
+    }
+
+    set ok [ ::pxtclutil::Question "Are you sure you want to delete $name?" ]
+    if { $ok == 0 } {
+	return 0
+    }
+
+    DeleteObject $currentobject
+}
+
+itcl::body pxitclmultiObjectGUI::AddObject { descr } {
+
+    if { $initialized == 0 } { return 0 }
+
+    incr objectindex
+    set new_obj [ $this CreateNewObject ]    
+    $listbox insert end $descr
+    lappend itclobjectlist $new_obj
+    set index [ expr [ llength $itclobjectlist ]  -1 ]
+    SetObject $index
+    return [ $new_obj GetThisPointer ]
+}
+
+
+
+
+itcl::body pxitclmultiObjectGUI::DeleteAllObjects { { force 0 } { addone 1 } } {
+
+    if { $force == 0 } {
+	set ok [ ::pxtclutil::Question "Are you sure you want to delete all objects?" ]
+	if { $ok == 0 } {
+	    return 0
+	}
+    }
+    
+    if { $initialized == 0 } { return 0 }
+    set ln [ llength $itclobjectlist  ]
+    for { set i 0 } { $i < $ln } { incr i } {
+	catch { itcl::delete object [ lindex $itclobjectlist $index ] }
+    }
+    set itclobjectlist ""
+    $listbox delete 0 end
+    if { $addone ==1 } {
+	$this AddInternalObject
+    }
+}
+
+itcl::body pxitclmultiObjectGUI::DeleteObject { index } {
+    
+    if { $initialized == 0 } { return 0 }
+    
+    set ln [ llength $itclobjectlist  ]
+    
+    if { $index < 0 || $index >= $ln } { return 0 } 
+
+    catch { itcl::delete object [ lindex $itclobjectlist $index ] }
+    set itclobjectlist [ lreplace $itclobjectlist $index $index ]
+
+    $listbox delete $index $index
+
+    if { $index == $currentobject } {
+	SetObject 0
+    } else {
+	SetObject $currentobject
+    }
+}
+
+itcl::body pxitclmultiObjectGUI::Initialize { basewidg } {
+    
+    if { $initialized == 1 } { 
+	return $basewidget 
+    }
+    
+    set basewidget [ iwidgets::Labeledframe $basewidg -labelpos n -labeltext $description ]
+    set base [ $basewidget childsite ]
+    
+    frame $base.left; 
+    frame $base.right;
+    pack $base.left -side left -expand false -fill y
+    pack $base.right -side right -expand true  -fill both
+
+    set objectGUI [ $this CreateNewObjectGUI $base.right ]
+    eval "$objectGUI configure -callback   { $this SingleObjectGUIUpdate }"
+
+    set listbox [ iwidgets::scrolledlistbox $base.left.slb -vscrollmode dynamic -hscrollmode none -selectmode single -labelpos nw -visibleitems 10x8 ]
+    eval "$listbox configure -selectioncommand { $this SetObject -1 }"
+    $listbox configure -selectmode single
+    $listbox configure -exportselection 0
+
+
+    if { $enableadd == 1 || $enabledelete == 1 || $enabledeleteall == 1} {
+	frame $base.left.bot; pack $base.left.bot -side bottom -fill x -expand f -pady 0
+
+	if { $enableadd == 1 } {
+	    eval "button $base.left.bot.add -text Add -command { $this AddInternalObject }"
+	    pack $base.left.bot.add  -side left -expand f -fill x -padx 1
+	}
+
+	if { $enabledelete == 1 } {
+	    eval "button $base.left.bot.delete -text Delete -command { $this DeleteInternalObject }"
+	    pack $base.left.bot.delete  -side left -expand f -fill x -padx 1
+	}
+
+	if { $enabledeleteall == 1 } {
+	    eval "button $base.left.bot.deleteall -text \"Del All\" -command { $this DeleteAllObjects }"
+	    pack $base.left.bot.deleteall  -side left -expand f -fill x -padx 1
+	}
+
+
+    }
+
+    if { $enableupdown == 1 } {
+	set w [ frame $base.left.bot2 ] ; pack $w -side bottom -fill x -expand f -pady 0
+	eval "button $w.1 -text Up -command { $this MoveCurrentObject -1 }"
+	eval "button $w.2 -text Down -command { $this MoveCurrentObject 1 }"
+	pack $w.1 $w.2 -side left -expand t -fill x -padx 1
+    }
+
+
+    eval "bind $listbox <ButtonRelease-1> { $this CallbackFunction }"
+    pack $listbox -side top -fill x -padx 5 -pady 0
+
+
+
+    set initialized 1
+    return $basewidget
+}
+
+itcl::body pxitclmultiObjectGUI::CallbackFunction { } {    
+    if { [ $this GetNumberOfObjects ] > 0  } {
+	if { $callback !="" } {
+	    return [ eval $callback ] 
+	}
+    }
+    return 0
+}
+	
+itcl::body pxitclmultiObjectGUI::GetCurrentObject { } {
+    
+ 
+    return [ lindex $itclobjectlist $currentobject ]
+}
+		
+    
+itcl::body pxitclmultiObjectGUI::CurrentObjectModified { } {
+    if { [ $this GetNumberOfObjects ] > 0 }  {
+	$objectGUI Update
+    }
+}
+
+
+itcl::body pxitclmultiObjectGUI::MoveCurrentObject { direction } {
+
+    if { $direction !=1 } {
+	set direction -1
+    }
+
+    set myindex $currentobject
+    set numelements [ expr [ llength $itclobjectlist ] -1 ]
+
+
+    # Can't go up
+    if { $direction == -1 && $myindex == 0 } {	return  0 }
+    # Can't go down
+    if { $direction == 1 && $myindex == $numelements } {	return  0  }
+
+    set newindex [ expr $myindex + $direction ]
+
+    #puts stderr "myindex=$myindex , numelements = $numelements newindex = $newindex , itclobjectlist = $itclobjectlist\n\n"
+
+    set newobject   [ lindex $itclobjectlist $newindex ]
+    set curobject [  lindex $itclobjectlist $myindex ]
+
+    #puts stderr "curobject=$curobject , newobject = $newobject\n\n"
+
+
+
+    if { $direction == -1 } {
+	set min $newindex
+	set max [ expr $myindex +1 ]
+    } else {
+	set min $myindex
+	set max [ expr $newindex +1 ]
+    }
+
+    set oldlist $itclobjectlist
+    set oldtaglist ""
+    for { set i 0 } { $i < [ llength $oldlist ] } { incr i } {
+	lappend oldtaglist [ $listbox get $i $i  ]
+    }
+    
+    $listbox delete 0 end
+
+    set itclobjectlist ""
+    
+    for { set i 0 } { $i < $min  } { incr i } {
+	#puts stderr "Adding $i (0:$min) [ lindex $oldlist $i ]\n"
+	lappend itclobjectlist [ lindex $oldlist $i ]
+	$listbox insert end [ lindex $oldtaglist $i ]
+    }
+
+    if { $direction == 1 } {
+	lappend itclobjectlist  $newobject
+	lappend itclobjectlist  $curobject
+	$listbox insert end [ lindex $oldtaglist $newindex ]
+	$listbox insert end [ lindex $oldtaglist $myindex ]
+	#puts stderr "Adding dir= 1 $newobject $curobject"
+    } else {
+	lappend itclobjectlist  $curobject
+	lappend itclobjectlist  $newobject
+	$listbox insert end [ lindex $oldtaglist $myindex ]
+	$listbox insert end [ lindex $oldtaglist $newindex ]
+	#puts stderr "Adding dir= -1  $curobject $newobject"
+    }
+
+    for { set i $max } { $i <= $numelements   } { incr i } {
+#	puts stderr "Adding $i ($max:$numelements) [ lindex $oldlist $i ]\n"
+	lappend itclobjectlist [ lindex $oldlist $i ]
+	$listbox insert end [ lindex $oldtaglist $i ]
+    }
+
+    set oldlist ""
+    set oldtaglist ""
+    
+    $this SetObject $newindex
+    return 1
+}
+    
+# -------------------------------------------------------------------------
+
+itcl::body pxitclmultiObjectGUI::InitializeLite { basewidg } {
+    
+    if { $initialized == 1 } { 
+	return $basewidget 
+    }
+    
+    set basewidget [ iwidgets::Labeledframe $basewidg -labelpos n -labeltext $description ]
+    set base [ $basewidget childsite ]
+    
+    set w1 [ frame $base.top ]
+    set w2 [ frame $base.right ]
+    pack $w2 -side bottom -expand true  -fill x
+    pack $w1 -side top -expand true -fill x
+
+    set objectGUI [ $this CreateNewObjectGUI $w2 ]
+    eval "$objectGUI configure -callback   { $this SingleObjectGUIUpdate }"
+
+
+    frame $w1.right; pack $w1.right -side right -expand false 
+    frame $w1.left;  pack $w1.left  -side left  -expand true -fill both
+
+    set listbox [ iwidgets::scrolledlistbox $w1.left.slb -vscrollmode dynamic -hscrollmode dynamic -selectmode single -labelpos nw -visibleitems 10x8 ] 
+    [ $listbox component listbox ] configure -bg white -fg black
+    eval "$listbox configure -selectioncommand { $this SetObject -1 }"
+    $listbox configure -selectmode single
+    $listbox configure -exportselection 0
+
+    if { $enableadd == 1 || $enabledelete == 1 || $enabledeleteall == 1} {
+
+	if { $enableadd == 1 } {
+	    eval "button $w1.right.add -text Add -command { $this AddInternalObject }"
+	    pack $w1.right.add  -side top -expand f -fill x -padx 1
+	}
+
+	if { $enabledelete == 1 } {
+	    eval "button $w1.right.delete -text Delete -command { $this DeleteInternalObject }"
+	    pack $w1.right.delete  -side top -expand f -fill x -padx 1
+	}
+
+	if { $enabledeleteall == 1 } {
+	    eval "button $w1.right.deleteall -text \"Del All\" -command { $this DeleteAllObjects }"
+	    pack $w1.right.deleteall  -side top -expand f -fill x -padx 1
+	}
+
+
+    }
+
+    if { $enableupdown == 1 } {
+	eval "button $w1.right.1 -text Up -command { $this MoveCurrentObject -1 }"
+	eval "button $w1.right.2 -text Down -command { $this MoveCurrentObject 1 }"
+	pack $w1.right.1 $w1.right.2 -side top -expand t -fill x -padx 1
+    }
+
+
+    eval "bind $listbox <ButtonRelease-1> { $this CallbackFunction }"
+    pack $listbox -side top -fill x -padx 5 -pady 2 -expand true
+
+
+    set initialized 1
+    return $basewidget
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxitclsurface.tcl b/bioimagesuite30_src/bioimagesuite/base/pxitclsurface.tcl
new file mode 100644
index 0000000..ba7a10c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxitclsurface.tcl
@@ -0,0 +1,515 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclsurface 1.0
+
+# 	$Id: pxitclsurface.tcl,v 1.2 2003/08/14 17:49:42 xenios Exp xenios $	
+
+
+
+
+package require  pxitclobject  1.0
+package provide pxitclsurface 1.0
+
+# -------------------------------------------------------------------
+# Definition of pxitclsurface
+#
+#    a class that encapsulates an image (vtkImageData)
+#            its orientation , filename and status
+# -------------------------------------------------------------------
+
+itcl::class pxitclsurface {
+
+    inherit pxitclobject
+
+    # --- begin variable def -----
+
+    public variable status 
+    protected variable sur 
+
+    # --- end of variable def -----
+
+    constructor { } {
+	pxitclobject::constructor 
+    } {
+	CreateNewSurface
+	UpdateStatus    
+    }
+
+    destructor  { $sur Delete     }
+
+
+    # --- begin method def -----
+    public method GetObject { } { return $sur }
+    public method GetType { } { return [ $sur GetNumberOfPoints ] }
+    public method GetDescription { } 
+    public method UpdateStatus { } { set status [ $sur GetNumberOfPoints ]  }
+    public method Copy   { obj args }
+    public method Clear { } 
+    public method UnLoad { } { return [ Clear ] }
+
+    public method Load   { args }
+    public method Save   { args }
+
+    # Methods additional to pxitclobject
+    
+    public method GetSurface { } { return $sur }
+
+    public method GetLongDescription { } 
+    public method GetShortDescription { } 
+    public method GetSurfaceSize { } 
+    public method GetSize { } { return [ $this GetSurfaceSize ] }
+
+    public method DeepCopy    { obj } { Copy $obj 1    }
+    public method ShallowCopy { obj } { Copy $obj 0    }
+
+    public method DeepCopySurface    { newsur } { CopySurface $newsur 1    }
+    public method ShallowCopySurface { newsur } { CopySurface $newsur 0    }
+    public method CopySurface   { newsur mode }
+
+    public method CreateNewSurface { } 
+
+    # Procedures to Just Set Filename
+    public method Browse { description }
+
+    # Procedures to Ship To Viewer
+    public method Display { baseviewer }
+    public method Transform { gen }
+
+
+    # Compare with FileName
+    public method CompareTo  { fname { thr 0.001 } } 
+    # This is misnomer it really is a correspondence check
+    public method CorrelateWith  { fname { thr 1.0 } }
+
+    # --- end method def -----
+}
+
+# ------------------- End of Header ---------------------------------
+itcl::body pxitclsurface::CreateNewSurface { } {
+
+#    set sphere [ vtkSphereSource [ pxvtable::vnewobj ]]
+#    $sphere SetRadius 1
+#    $sphere Update
+
+    set sur [ vtkPolyData [ pxvtable::vnewobj ]]
+#    $sur ShallowCopy [ $sphere GetOutput ]
+#    $sphere Delete
+}
+
+
+itcl::body pxitclsurface::Copy   { obj args } {
+
+    set mode 0
+    if { [ llength $args ] > 0 } {
+	set mode [ expr [ lindex $args 0 ] > 0 ]
+    }
+
+    if { [ $obj isa pxitclsurface ] == 0 } {
+	return 0
+    }
+
+    set oldimg [ $obj GetSurface ] 
+    CopySurface $oldimg $mode
+    set filename    [ $obj cget -filename ]
+    UpdateStatus
+}
+# ----------------------------------------------------------
+itcl::body pxitclsurface::CopySurface { newimg mode } {
+
+    set mode [ expr $mode > 0 ]
+
+    if { [ $newimg IsA "vtkPolyData" ] == 0 } {
+	puts stdout "Bad Input"
+	return
+    }
+
+    $sur Delete
+    set sur [ vtkPolyData [ pxvtable::vnewobj ]]
+
+    #    puts stderr "In Copy Surface mode=$mode, sur = $sur [ $sur GetClassName ], newimg=$newimg [ $newimg GetClassName ]"
+
+    if { $mode == 0 } {
+	$sur ShallowCopy $newimg
+    } else {
+	$sur DeepCopy $newimg
+    }
+
+    UpdateStatus
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclsurface::Clear { } {
+    catch { $sur Delete }
+    CreateNewSurface
+    set orientation 0
+    set filename    ""
+    UpdateStatus
+}
+# ----------------------------------------------------------
+itcl::body pxitclsurface::GetSurfaceSize { } {
+
+    return [ $sur GetNumberOfPoints ]
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclsurface::GetLongDescription { } {
+    
+    set x1 [ $sur GetNumberOfPoints ] 
+    set s1 [ $sur GetNumberOfCells  ]
+    set bd [ $sur GetBounds ]
+    set t1 [ $sur GetNumberOfScalarComponents ] 
+    
+    set line [ format "Number Of Points %d Cells=%d Bounds= $bd" $x1 $s1 ]
+
+    set line  "name=$this\n\t$line\n\tFilename= $filename"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitclsurface::GetDescription { } {
+    
+    set x1 [ $sur GetNumberOfPoints ] 
+    set s1 [ $sur GetNumberOfCells  ]
+    set line [ format "Number Of Points %d Cells=%d" $x1 $s1 ]
+    set line  "$line\nFilename=$filename\n"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitclsurface::GetShortDescription { } {
+    
+    set x1 [ $sur GetNumberOfPoints ] 
+    set s1 [ $sur GetNumberOfCells  ]
+    set line [ format "Number Of Points %d Cells=%d" $x1 $s1 ]
+    set line  "[ file tail $filename]  $line"
+    return $line
+}
+# ----------------------------------------------------------
+itcl::body pxitclsurface::Browse { description } {
+
+    set f2path [ file dirname $filename ]
+    set f2tail [ file tail    $filename ]
+	
+    set fname  [tk_getOpenFile -title "Get Filename for $description" -filetypes { {"Surface Files" {.vtk .vtp}}} -initialfile $f2tail -initialdir $f2path ]   
+    if { [ string length $fname ] > 0 } {
+	set filename $fname
+	return 1
+    }
+    return 0
+}
+# ----------------------------------------------------------
+itcl::body pxitclsurface::Load { args } {
+
+    set len [ llength $args ]
+    if { [ string length $filename ] == 0 && $len == 0 } { return  }
+
+
+    if { $len < 1 } {
+	set fname $filename
+    } else  { 
+	set fname [ lindex $args 0 ] 
+    }
+
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    } else {
+	set desc "Surface"
+    }
+
+
+    if { [ string length $fname ] == 0 } {
+
+
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getOpenFile -title "Load $desc" -filetypes { {"Surface Files" {.vtk .vtp}}} -initialfile $f2tail -initialdir $f2path ]   
+    }
+    
+
+    if { [ string length $fname ] <1 } {
+	return 0
+    }
+
+    catch {
+	if { [ file extension $fname ]  == ".vtp"  } {
+	    set ana [ vtkXMLPolyDataReader [ pxvtable::vnewobj ]]
+	} else {
+	    set ana [ vtkPolyDataReader [ pxvtable::vnewobj ]]
+	}
+	$ana SetFileName $fname
+	$ana Update
+	$this ShallowCopySurface [ $ana GetOutput ]
+	$this configure -filename $fname
+	$ana Delete
+    }
+    return 1
+}
+# ----------------------------------------------------------
+itcl::body pxitclsurface::Save { args } {
+
+    set len [ llength $args ]
+    if { $len < 1 } {
+	set fname $filename
+    } else  { 
+	set fname [ lindex $args 0 ] 
+    }
+
+    set desc "Image"
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    }
+
+
+    if { [ string length $fname ] == 0 } {
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getSaveFile -title "Saving $desc" -filetypes { {"Surface Files" {.vtk}}} -initialfile $f2tail -initialdir $f2path ]   
+    }
+    
+    if { [ string length $fname ] < 0 } {
+	return 0
+    }
+    
+    set ana [ vtkPolyDataWriter  [ pxvtable::vnewobj ]]
+    $ana SetInput $sur
+    $ana SetFileName $fname
+    $ana Update
+    set filename $fname
+#$this configure -filename $fnamea
+    $ana Delete 
+    return 1
+}
+# ----------------------------------------------------------
+itcl::body pxitclsurface::Display { baseviewer } {
+    
+    set polydatacontrol 0
+    catch {     set  polydatacontrol [ [ $baseviewer GetPolyDataControl ] GetPolyDataControl ] }
+
+    if { $polydatacontrol == 0 } {
+	::pxtclutil::Warning "Bad baseviewer ($baseviewer) Specified. Cannot display surface\n"
+	return 0
+    }
+
+    $polydatacontrol SetClipboardSurface $sur $filename
+    ::pxtclutil::Info "Placed surface $filename in the clipboard of the surface control"
+    
+    [ $baseviewer GetPolyDataControl ] ShowWindow
+    return 1
+} 
+# ----------------------------------------------------------
+itcl::body pxitclsurface::Transform { transformation } {
+    
+    set vt [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ]]
+    $vt SetInput $sur
+    $vt SetTransform $transformation
+    $vt Update
+    $this ShallowCopySurface [ $vt GetOutput ]
+    $vt Delete
+    return 1
+} 
+
+
+itcl::body pxitclsurface::CompareTo  { fname { thr 0.001 } } {
+
+    set tmp [ pxitclsurface \#auto ]
+    set ok [$tmp Load $fname  ]
+    if { $ok == 0 } {
+	itcl::delete object $tmp
+	return 0
+    }
+
+    set ut [ vtkbisTestUtil New ]
+    $ut ClearStatus
+    set ok [ $ut CompareSurfaces [ $this GetSurface ] [ $tmp GetSurface ] $thr ]
+    set a [ $ut ReturnStatus ]
+    itcl::delete object $tmp
+    $ut Delete
+    return [ list $ok $a ]
+}
+
+
+itcl::body pxitclsurface::CorrelateWith  { fname { thr 1.0 } } {
+
+    set tmp [ pxitclsurface \#auto ]
+    set ok [$tmp Load $fname  ]
+    if { $ok == 0 } {
+	itcl::delete object $tmp
+	return 0
+    }
+
+    set ut [ vtkbisTestUtil New ]
+    $ut ClearStatus
+    set ok [ $ut CompareSurfacesByCorrespondence [ $this GetSurface ] [ $tmp GetSurface ] $thr ]
+    itcl::delete object $tmp
+    set a [ $ut ReturnStatus ]
+    $ut Delete
+    return [ list $ok $a ]
+
+}
+# ----------------------------------------------------------
+#  GUI for pxitclsurface
+# ----------------------------------------------------------
+itcl::class pxitclsurfaceGUI {
+
+    inherit pxitclobjectGUI
+
+    public variable browsebutton
+
+    constructor { } {
+	pxitclobjectGUI::constructor
+    } { 
+	set thisparam($this,status) "vtkPolyData"
+	set thisparam($this,shortfilename) "none"
+	set thisparam($this,descriptionbox) 0
+	Reset
+    }
+
+    destructor { }
+
+    public method SetObject { tr } { return [ SetSurface $tr ] }
+    public    method GetSurface { } { return $itclobject  }
+
+    protected method CreateNewObject { } 
+    public    method Initialize { basewidg } 
+    public    method SetSurface { isur }
+    public    method BrowseSurface { } 
+
+
+}
+# ----------------------------------------------------------
+itcl::body pxitclsurfaceGUI::CreateNewObject { } {
+    set itclobject  [ [  pxitclsurface \#auto ] GetThisPointer ]
+}
+
+itcl::body pxitclsurfaceGUI::BrowseSurface { } {
+    $itclobject Browse $description
+    Update
+}
+
+itcl::body pxitclsurfaceGUI::SetSurface { trn } {
+    
+    if { [ $trn isa pxitclsurface ] == 0 } {
+	return 0
+    }
+	
+    if { $owns_object == 1} {
+	catch { itcl::delete object $itclobject }
+    }
+
+    set itclobject $trn
+    set owns_object 0
+    Update
+}
+
+itcl::body pxitclsurfaceGUI::BrowseSurface { } {
+    $itclobject Browse $description
+    Update
+}
+
+itcl::body pxitclsurfaceGUI::Initialize { basewidg } {
+
+    if { $initialized == 1 } { return $basewidget }
+    pxitclobjectGUI::Initialize $basewidg
+
+    set browsebutton [ eval "button $buttonbar.b -text Browse -command { $this BrowseSurface }" ]
+    pack  $buttonbar.b   -side left -fill x -expand f
+    update idletasks
+
+    Update
+    return $basewidget
+}
+
+# ----------------------------------------------------------
+#  GUI for multiple image object
+# ----------------------------------------------------------
+itcl::class pxitclmultiSurfaceGUI {
+
+    inherit pxitclmultiObjectGUI
+
+    constructor { } {
+	pxitclmultiObjectGUI::constructor
+	set description "Surface"
+    } {
+    }
+    
+    destructor { }
+    
+    public    method Initialize { basewidg } 
+
+    public    method AddSurface { descr }
+    public    method SetSurface { index } 
+    public    method GetSurface { index } { return [ GetObject $index ] }
+    public    method DeleteSurface { index } { DeleteObject $index }
+
+    protected method CreateNewObject { }
+    protected method CreateNewObjectGUI { widget }
+
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclmultiSurfaceGUI::CreateNewObject { } {
+
+    return  [ [  pxitclsurface \#auto ] GetThisPointer ]
+}
+
+itcl::body pxitclmultiSurfaceGUI::CreateNewObjectGUI { widget } {
+    set itclimageGUI [ [ pxitclsurfaceGUI \#auto ] GetThisPointer ]
+    pack [ $itclimageGUI Initialize $widget.[ pxvtable::vnewobj ] ] -side left -fill x
+    return $itclimageGUI
+}
+
+itcl::body pxitclmultiSurfaceGUI::AddSurface { descr } {
+    
+    set newobj [ $this AddObject $descr ]
+    $this SetSurface [ expr [ llength $itclobjectlist ] -1 ]    
+    return $newobj
+}
+
+itcl::body pxitclmultiSurfaceGUI::SetSurface { index } {
+
+    $this SetObject $index
+    $objectGUI configure -description [ $listbox get $currentobject ]
+    $objectGUI Update
+}
+
+itcl::body pxitclmultiSurfaceGUI::Initialize { basewidg } {
+    
+    if { $initialized == 1 } { 
+	return $basewidget 
+    }
+    
+    pxitclmultiObjectGUI::Initialize $basewidg
+
+    $listbox configure -selectmode single -exportselection 0
+    eval "$listbox configure -selectioncommand { $this SetSurface -1 }"
+    
+    set initialized 1
+
+    
+    return $basewidget
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxitcltransform.tcl b/bioimagesuite30_src/bioimagesuite/base/pxitcltransform.tcl
new file mode 100644
index 0000000..df8bae2
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxitcltransform.tcl
@@ -0,0 +1,539 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitcltransform 1.0
+
+# 	$Id: pxitcltransform.tcl,v 1.1 2002/07/19 22:17:02 papad Exp papad $	
+
+
+
+
+
+package require pxitclobject 1.0
+# -------------------------------------------------------------------
+# Definition of pxitcltransform
+#
+#    a class that encapsulates a transformation and its filename
+# -------------------------------------------------------------------
+
+itcl::class pxitcltransform {
+
+    inherit pxitclobject
+
+    public variable transformation
+
+    constructor { } {
+	pxitclobject::constructor 
+    } {
+	set transformation [ vtkTransform [ pxvtable::vnewobj ]]
+	$transformation Identity
+    }
+
+    destructor  { $transformation Delete  }
+
+
+    # --- begin method def -----
+
+
+    
+    public method GetObject { } { return $transformation }
+    public method GetType { } { return [ $transformation GetClassName ]} 
+    public method GetDescription { } 
+    public method GetShortDescription { } 
+    public method UpdateStatus { } 
+    public method Copy    { obj args }
+    public method Clear   { }
+    public method IsIdentity   { }
+    public method GetSize { } { return [ expr 1 -[ $this IsIdentity ] ]}
+    public method IsLinear   { }
+    public method Load { args }
+    public method Browse { description }
+    public method Save { args }
+
+    # Methods additional to pxitclobject
+    public method GetTransformation { } { return $transformation }
+    public method Invert  { } 
+    public method CopyTransformation { obj }
+    
+    public method CompareTo  { fname { thr 0.001 } }
+
+    # --- end method def -----
+}
+
+# ------------------- End of Header ---------------------------------
+itcl::body pxitcltransform::Copy   { obj args  } {
+
+    if { $obj == 0 } {
+	return 0
+    }
+
+
+    if { [ $obj isa pxitcltransform ] == 0 } {
+	return 0
+    }
+
+    CopyTransformation  [ $obj GetTransformation ]  
+    set filename [ $obj cget -filename ] 
+    return 1
+}
+# ----------------------------------------------------------
+
+
+itcl::body pxitcltransform::CopyTransformation { oldxform  } {
+    
+    set thistype "[ $transformation GetClassName ]"
+    $transformation Delete
+    set transformation [ [ $oldxform GetClassName ] [ pxvtable::vnewobj ] ]
+    #    puts stdout "executing set transformation [ $oldxform GetClassName ] [ pxvtable::vnewobj ] "
+
+    if { [ $oldxform GetClassName ] == "vtkTransform" } {
+	$transformation Identity
+	$transformation Concatenate $oldxform
+    } else {
+	$transformation DeepCopy $oldxform
+    }   
+
+}
+# ----------------------------------------------------------
+itcl::body pxitcltransform::GetShortDescription { } {
+    return  "[ file tail $filename] [ $transformation GetClassName ]"
+}
+
+itcl::body pxitcltransform::GetDescription { } {
+    
+    set line ""
+    
+
+
+    if { [ $transformation IsA "vtkHomogeneousTransform" ] ==1 } {
+	set matr [ $transformation GetMatrix ] 
+	for { set row 0 } { $row <= 3 } { incr row } {
+	    set line "$line\[ "
+	    for { set col 0 } { $col <= 3 } { incr col } {
+		set key [ $matr GetElement $row $col ]
+		set line "$line [format "%-7.3f" $key ]"
+	    }
+	    set line "$line\]\n"
+	}
+    } elseif { [ $transformation IsA "vtkGridTransform" ] == 1 } {
+	set grd [ $transformation GetDisplacementGrid ]
+	set dim [ $grd GetDimensions ]
+	set sp [ $grd GetSpacing ]
+	set or [ $grd GetOrigin ]
+	set line "Dimensions = $dim"
+	set line "$line\nSpacing = $sp\n"
+	set line "$line\nOrigin = $or\n"
+    } elseif { [ $transformation IsA "vtkpxComboTransform" ] == 1 } {
+	set grd [ [ $transformation GetGridTransform ] GetDisplacementGrid ]
+	set dim [ $grd GetDimensions ]
+	set sp [ $grd GetSpacing ]
+	set or [ $grd GetOrigin ]
+	set line "Combo Transform:  (NonLinearFirst: [ $transformation GetNonLinearFirst])"
+	set line "$line\n Num_Grids [ $transformation GetNumberOfGridTransformations ]"
+	set line "$line\n Dimensions = $dim"
+	set line "$line\n Spacing = $sp"
+	set line "$line\n Origin = $or"
+    } elseif { [ $transformation IsA "vtkpxPolySimilarityTransform" ] } {
+	set nt [ $transformation GetNumberOfTransformations ]
+	set np [ $transformation GetNumberOfParameters ]
+	set lp "No TPS transform"
+	catch {
+	    set np2 [ [ [ $transformation GetThinPlateSplineTransform ] GetSourceLandmarks ] GetNumberOfPoints ]
+	    set lp "TPS present: $np2 control points"
+	}
+	set line "PolySimilarityTransform :\n $nt transformations\n $np pararameters\n$lp"
+    } elseif { [ $transformation IsA "vtkThinPlateSplineTransform" ] } {
+	set line "ThinPlateSplineTransform :\n Number of Control Points = [ [ $transformation GetSourceLandmarks ] GetNumberOfPoints ]" 
+    } else {
+	set line "Transformation Type:\n [ $transformation GetClassName ]"
+    }
+
+    set line "$line\n Filename = $filename"
+
+    return $line 
+}
+# ----------------------------------------------------------
+itcl::body pxitcltransform::Browse { description } {
+
+    set f2path [ file dirname $filename ]
+    set f2tail [ file tail    $filename ]
+	
+	set typelist { 
+	    {"Matrix/Grid Files" {".matr" ".grd" ".grd.gz" } }
+	    {"Grid/Combo Transform Files"  {".grd" ".grd.gz" ".vtk" }}
+	    {"VTK Displacement Fields" {.vtk}} 
+	    {"Matrix Files" {.matr}} 
+	    {"All Files" {*}}}
+    
+    set fname  [tk_getOpenFile -title "Get Filename for $description" -filetypes $typelist -initialfile $f2tail -initialdir $f2path ]   
+    if { [ string length $fname ] > 0 } {
+	set filename $fname
+	return 1
+    }
+    return 0
+}
+# ------------------------------------------------------------------------
+itcl::body pxitcltransform::Load { args } {
+    
+    set len [ llength $args ]
+    if { [ string length $filename ] == 0 && $len == 0 } { return    }
+
+
+    if { $len > 0 } {
+	set f [ lindex $args 0 ]
+    }  else {
+	set f $filename
+    }
+
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    } else {
+	set desc "Transformation"
+    }
+
+    if { [ string length $f ] < 1 } { 
+	set typelist { 
+	    {"Matrix/Grid Files" {".matr" ".grd" ".grd.gz" } }
+	    {"Grid/Combo Transform Files"  {".grd" ".grd.gz" }}
+	    {"VTK Displacement Fields" {.vtk}} 
+	    {"PolySimilarity Transforms" {.psim}} 
+	    {"Matrix Files" {.matr}} 
+	    {"Thin Plate Spline Transforms" {.tps}} 
+	    {"All Files" {*}}}
+	
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set f [tk_getOpenFile -title "Load $desc" -initialfile $f2tail -filetypes $typelist -initialdir $f2path]
+    }
+
+    if { [string length $f ] < 2 || $f=="identity" } {
+	return 0;
+    }
+    
+    set filename  $f
+    set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+    set newtr [ $ut LoadAbstractTransform $f ]
+    $ut Delete
+    
+    if { [ string length $newtr ] ==0 } {
+	::pxtclutil::Warning "Failed to Load transformation from $f!"
+	return 0;
+    } 
+	
+    
+    CopyTransformation $newtr
+
+    $newtr Delete
+    return 1;
+
+}
+# ----------------------------------------------------------
+itcl::body pxitcltransform::Save { args } {
+
+    set f    $filename
+    set desc "Transformation"
+    
+    
+    if { [ llength $args ] > 0 } {
+	set f [ lindex $args 0 ]
+    } 
+    if { [ llength $args ] > 1 } { 
+	set desc [ lindex $args 1 ]
+    }
+
+    set dovtk 0
+
+    if { [ string length $f ] < 1 } { 
+	set f1 $filename  
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+
+	if { [ $transformation IsA "vtkHomogeneousTransform" ] ==1 } {		
+	    set f  [tk_getSaveFile -title "Saving $desc" -initialfile $f1tail -initialdir $f1path -filetypes { {"Matrix Files" {.matr}} } ]
+	} elseif { [ $transformation IsA "vtkGridTransform" ] ==1 } {		
+	    set f  [tk_getSaveFile -title "Saving $desc" -initialfile $f1tail -initialdir $f1path -filetypes { {"Grid Transform Files" {.grd .vtk}} } ]
+	    set dovtk 1
+	} elseif { [ $transformation IsA "vtkpxComboTransform" ] ==1 } {		
+	    set f  [tk_getSaveFile -title "Saving $desc" -initialfile $f1tail -initialdir $f1path -filetypes { {"Combo Transform Files" {.grd}} } ]
+	} elseif {[ $transformation IsA "vtkThinPlateSplineTransform" ] ==1 } {		
+	    set f  [tk_getSaveFile -title "Saving $desc" -initialfile $f1tail -initialdir $f1path -filetypes { {"ThinPlateSpline Transform Files" {.tps}} } ]
+	} elseif {[ $transformation IsA "vtkpxPolySimilarityTransform" ] ==1 } {		
+	    set f  [tk_getSaveFile -title "Saving $desc" -initialfile $f1tail -initialdir $f1path -filetypes { {"PolySimilarity Transform Files" {.psim}} } ]
+	}
+    }
+
+    if { [string length $f ] > 0 } {
+	set filename  $f
+
+	if { $dovtk ==1 && [ file extension $f ] == ".vtk"  } {
+	    set w [ vtkStructuredPointsWriter New ]
+	    $w SetFileName $f
+	    $w SetFileTypeToBinary
+	    $w SetInput [ $transformation GetDisplacementGrid ]
+	    $w Write
+	    $w Delete
+	    set ok 0
+	    if { [ file exists $f ] } { set ok 1 }
+	} else {
+	    set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+	    set ok [ $ut SaveAbstractTransform $transformation $f ]
+	    $ut Delete
+	}
+	if { $ok == 0 } {
+	    ::pxtclutil::Warning "Failed to Save Transformation in $f!"
+	    return 0;
+	} 
+    }
+    return 1;
+}
+# ----------------------------------------------------------
+itcl::body pxitcltransform::Clear { } {
+    
+    if { [ $transformation IsA "vtkHomogeneousTransform" ] !=1 } { 
+	$transformation Delete
+	set transformation [ vtkTransform [ pxvtable::vnewobj ] ]
+    }
+    $transformation Identity
+    set filename "identity"
+}
+
+itcl::body pxitcltransform::IsLinear   { } {
+
+    if { [ $transformation IsA "vtkHomogeneousTransform" ] } {
+	return 1
+    } 
+    return 0
+}
+
+
+
+itcl::body pxitcltransform::IsIdentity   { } {
+
+    if { [ $transformation IsA "vtkTransform" ] !=1 } { 
+	return 0
+    }
+
+    set sum 0.0
+
+    set matr [ $transformation GetMatrix ] 
+    for { set row 0 } { $row <= 3 } { incr row } {
+	for { set col 0 } { $col <= 3 } { incr col } {
+	    set v [ $matr GetElement $row $col ]
+
+	    if { $row == $col } {
+		set sum [ expr $sum + abs ($v-1.0) ]
+	    } else {
+		set sum [ expr $sum + abs ($v) ]
+	    }
+	}
+    }
+
+    if { $sum > 0.0001 } {
+	return 0
+    }
+
+    
+    return 1
+}
+# ----------------------------------------------------------
+    
+itcl::body pxitcltransform::Invert { } {
+    $transformation Inverse
+    set dname [ file dirname $filename ]
+    set tname [ file tail    $filename ]
+    set filename [ file join $dname "Inverse_${tname}" ]
+}
+
+itcl::body pxitcltransform::CompareTo  { fname { thr 0.001 } } {
+
+    if { [ file tail $fname ] == "do_not_use" } {	return 1    }
+
+    set tmp [ pxitcltransform \#auto ]
+    set ok [$tmp Load $fname  ]
+    if { $ok == 0 } {
+	itcl::delete object $tmp
+	return 0
+    }
+
+    set ut [ vtkbisTransformationTestUtil New ]
+    $ut ClearStatus
+    set ok [ $ut CompareTransformations [ $this GetTransformation ] [ $tmp GetTransformation ] $thr ]
+    set a [ $ut ReturnStatus ]
+    itcl::delete object $tmp
+    $ut Delete
+    return [ list $ok $a ]
+}
+
+
+# ----------------------------------------------------------
+#  GUI for pxitcltransform
+# ----------------------------------------------------------
+
+itcl::class pxitcltransformGUI {
+
+    inherit pxitclobjectGUI
+
+
+    constructor { } {
+	pxitclobjectGUI::constructor
+    } { 
+	set thisparam($this,status) "vtkTransform"
+	set thisparam($this,shortfilename) "identity"
+	set  description "Transformation"
+	set  filename "identity.matr"
+	set  numlines 4
+	Reset
+    }
+
+    destructor { }
+
+    public    method GetTransformation { } { return $itclobject  }
+    public    method Initialize { basewidg } 
+    public    method SetTransformation { tr } 
+    public    method InvertTransformation { }
+
+    protected method CreateNewObject { } 
+    public method SetObject { tr } { return [ $this SetTransformation $tr ] }
+
+}
+# ----------------------------------------------------------
+itcl::body pxitcltransformGUI::CreateNewObject { } {
+
+    set itclobject  [ [  pxitcltransform \#auto ] GetThisPointer ]
+}
+
+
+itcl::body pxitcltransformGUI::InvertTransformation { } {
+    $itclobject Invert 
+    Update
+}
+
+itcl::body pxitcltransformGUI::SetTransformation { trn } {
+    
+    set continue 0
+    
+    catch { 
+	if { [ $trn isa pxitcltransform ] == 1 } {
+	set  continue 1
+	}
+    }
+
+    if { $continue == 0 } {
+	return 0 
+    }
+	
+	
+    if { $owns_object == 1} {
+	catch { itcl::delete object $itclobject }
+    }
+
+    set itclobject $trn
+    
+    set owns_object 0
+    Update
+}
+
+itcl::body pxitcltransformGUI::Initialize { basewidg } {
+
+    if { $initialized == 1 } { return $basewidget }
+    
+    pxitclobjectGUI::Initialize $basewidg
+
+    eval "button $buttonbar.in -text Invert -command {  $this InvertTransformation }"
+    pack  $buttonbar.in  -side left -fill x -expand f
+    Update
+    return $basewidget
+}
+
+# ----------------------------------------------------------
+#  GUI for multiple transform object
+# ----------------------------------------------------------
+itcl::class pxitclmultiTransformGUI {
+
+    inherit pxitclmultiObjectGUI
+
+    constructor { } {
+	pxitclmultiObjectGUI::constructor
+	set description "Transformation"
+    } {
+    }
+    
+    destructor { }
+    
+    public    method Initialize { basewidg } 
+
+    public    method AddTransformation { descr }
+    public    method SetTransformation { index } 
+    public    method GetTransformation { index } { return [ GetObject $index ] }
+    public    method DeleteTransformation { index } { DeleteObject $index }
+
+    protected method CreateNewObject { }
+    protected method CreateNewObjectGUI { widget }
+
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclmultiTransformGUI::CreateNewObject { } {
+    
+    return [ [  pxitcltransform \#auto ] GetThisPointer ]
+}
+
+itcl::body pxitclmultiTransformGUI::CreateNewObjectGUI { widget } {
+    set itcltransformGUI [ [ pxitcltransformGUI \#auto ] GetThisPointer ]
+    pack [ $itcltransformGUI Initialize $widget.[ pxvtable::vnewobj ] ] -side left -fill x
+    return $itcltransformGUI
+}
+
+itcl::body pxitclmultiTransformGUI::AddTransformation { descr } {
+    
+    set newobj [ $this AddObject $descr ]
+    set index [ expr [ llength $itclobjectlist ] -1 ]
+    $this SetTransformation $index
+    return $newobj
+}
+
+itcl::body pxitclmultiTransformGUI::SetTransformation { index } {
+
+    $this SetObject $index
+    $objectGUI Update
+}
+
+itcl::body pxitclmultiTransformGUI::Initialize { basewidg } {
+    
+    if { $initialized == 1 } { 
+	return $basewidget 
+    }
+    
+    pxitclmultiObjectGUI::Initialize $basewidg
+
+    $listbox configure -selectmode single -exportselection 0
+    set initialized 1
+    
+    return $basewidget
+}
+ 
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxtclhelp.tcl b/bioimagesuite30_src/bioimagesuite/base/pxtclhelp.tcl
new file mode 100644
index 0000000..7d80b73
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxtclhelp.tcl
@@ -0,0 +1,102 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxtclhelp 1.0
+
+
+
+
+catch { package require labelframe 1.0 }
+package require pxvtable 1.0
+package require pxtclutil 1.0
+
+
+# ---------------------------------------------------------------------
+# pxtclhelp namespace -- create dialog boxes with scrolled text
+# ---------------------------------------------------------------------
+
+namespace eval ::pxtclhelp {
+
+    proc HelpDialog { widgetname } {
+	
+	frame $widgetname.logoframe  -width 450 
+	frame $widgetname.topframe    -width 450 -height 400
+
+	set textbox $widgetname.topframe.textbox 
+	set ybar    $widgetname.topframe.ybar 
+	set xbar    $widgetname.xbar 
+
+	eval "scrollbar $ybar  -command { $textbox yview } -orient vertical"
+	eval "scrollbar $xbar  -command { $textbox xview } -orient horizontal"
+	eval "text $textbox  -width 60 -height 10  -wrap word -relief ridge -yscrollcommand { $ybar set} -xscrollcommand {$xbar set}"
+
+	pack $widgetname.logoframe   -side top    -expand false -fill x -padx 0 -pady 0
+
+	pack $xbar -side bottom -expand f -fill x 
+	pack $widgetname.topframe -side top -expand true -fill both -padx 0 -pady 5
+	pack $ybar -side right -expand false -fill y
+	pack $textbox -side left -expand true -fill both
+
+
+	$textbox configure -state disabled
+
+	wm deiconify $widgetname
+	eval "wm protocol $widgetname WM_DELETE_WINDOW { grab release $widgetname ; wm withdraw $widgetname } "
+    }
+
+    proc HelpDialogAddText { widgetname texttoadd } {
+
+	set textbox $widgetname.topframe.textbox
+
+	$textbox configure -state normal
+	$textbox insert end $texttoadd
+	$textbox configure -state disabled
+
+    }
+
+    proc HelpDialogClearText { widgetname } {
+
+	set textbox $widgetname.topframe.textbox
+	$textbox configure -state normal
+	$textbox delete 1.0 end
+	$textbox configure -state disabled
+    }
+
+    proc GetLogoFrame { widgetname } {
+	return $widgetname.logoframe
+    }
+
+    proc GetTextBox { widgetname } {
+	return $widgetname.topframe.textbox
+    }
+
+
+}
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxtclreadsprheader.tcl b/bioimagesuite30_src/bioimagesuite/base/pxtclreadsprheader.tcl
new file mode 100644
index 0000000..9f71abe
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxtclreadsprheader.tcl
@@ -0,0 +1,201 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxtclreadsprheader 1.0
+
+# 	$Id: pxtclreadsprheader.tcl,v 1.1 2002/02/20 18:07:50 Xenios Exp Xenios $	
+
+
+
+
+
+
+
+package require pxvtable 1.0
+
+namespace eval ::pxtclreadsprheader {
+
+    #initialize vtable
+    pxvtable::initvlist 
+
+    #variable header
+    namespace export ReadHeader PrintHeader SetAnalyzeImageSource
+
+    # Procedure to Load Spr File -- Static no $this variable involved 
+    # --------------------------
+    proc LoadFile { ana fname } {
+
+	set this [ pxvtable::vnewobj ]
+	::pxtclreadsprheader::ReadHeader $this $fname
+	::pxtclreadsprheader::SetAnalyzeImageSource $this $ana
+	$ana Update
+    }
+
+    # Helper Procedure to Load Spr File 
+    # ----------------------------------
+    pxvtable::vproc SetAnalyzeImageSource { this ana } {
+
+	$ana SetHeaderInfo $thisparam(width) $thisparam(height) $thisparam(numslices) $thisparam(numframes) $thisparam(swapbytes) $thisparam(bytes)
+	$ana SetDataOrigin $thisparam(originx) $thisparam(originy) $thisparam(originz)
+	$ana SetDataSpacing $thisparam(spacingx) $thisparam(spacingy) $thisparam(spacingz)
+
+	set or [ string index $thisparam(orient) 0 ]
+	set or [ string toupper $or ]
+
+	if { $or == "S" } {
+	    $ana SetOrientation 2
+	} else {
+	    if { $or == "C"} {
+		$ana SetOrientation 1 
+	    } else {
+		$ana SetOrientation 0
+	    }
+	}
+	    
+	set f [file rootname $thisparam(filename)]
+	$ana SetFilePrefix "$f.sdt"
+    }
+
+    # Print Header Array
+    # ------------------
+    pxvtable::vproc PrintHeader { this } {
+
+	puts stdout "Header Values:"
+	foreach { key value } [array get thisparam] {
+	    puts stdout "$key  : $value"
+	}
+    }
+
+    # Initialize Header
+    # ------------------
+
+    pxvtable::vproc InitHeader { this } {
+	global tcl_platform
+
+	set thisparam(filename) ""
+	set thisparam(numDim) 0
+	set thisparam(width) 0
+	set thisparam(height) 1
+	set thisparam(numslices) 1
+	set thisparam(numframes) 0
+	set thisparam(originx) 0.0
+	set thisparam(originy) 0.0
+	set thisparam(originz) 0.0
+	set thisparam(origint) 0.0
+	set thisparam(spacingx) 0.0
+	set thisparam(spacingy) 0.0
+	set thisparam(spacingz) 0.0
+	set thisparam(spacingt) 0.0
+	set thisparam(fovx) 0.0
+	set thisparam(fovy) 0.0
+	set thisparam(fovz) 0.0
+	set thisparam(fovt) 0.0
+	set thisparam(bytes) 2
+	set thisparam(swapbytes) 0
+	set thisparam(orient) "COR"
+
+	if { $tcl_platform(byteOrder) == "littleEndian" } { 
+	    set thisparam(swapbytes) 1
+	}
+    }    
+
+    # Read spr Header
+    # ---------------
+    pxvtable::vproc ReadHeader { this fname } {
+	
+	::pxtclreadsprheader::InitHeader $this
+	
+	if { [string length $fname] < 1 } {
+	    set fname [tk_getOpenFile -title "Filename" -filetypes { {"spr files" {.spr}}}]
+	}
+	
+	if { [string length  $fname] < 1 } {
+	    return 0
+	}
+
+	set thisparam(filename) $fname
+	
+
+	if { [ file exists $fname ] == 0 } {
+	    return 0
+	}
+	set fileid [open $fname r]
+	
+	# Parse file one-line at a time
+	while { [gets $fileid line] >=0 } {
+	    set index [string first ":" $line]
+	    
+	    if { $index > 0 }  {
+		set len   [string length $line]
+		
+		set key [string trim   [string range $line 0 [expr $index - 1]]]
+		set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		
+		switch $key {
+		    numDim {
+			scan $value "%d" thisparam(numDim)
+		    }
+		    
+		    dim {
+			scan $value "%d %d %d %d" thisparam(width) thisparam(height) thisparam(numslices) thisparam(numframes) 
+		    }
+		    
+		    origin {
+			scan $value "%f %f %f %f" thisparam(originx) thisparam(originy) thisparam(originz) thisparam(origint) 
+		    }
+		    
+		    fov {
+			scan $value "%f %f %f %f" thisparam(fovx) thisparam(fovy) thisparam(fovz) thisparam(fovt) 
+		    }
+		    
+		    interval {
+			scan $value "%f %f %f %f" thisparam(spacingx) thisparam(spacingy) thisparam(spacingz) thisparam(spacingt) 
+			
+		    }
+		    
+		    dataType {
+			if { $value == "WORD"} { 
+			    set thisparam(bytes) 2 
+			} else {
+			    set thisparam(bytes) 1
+			}
+		    }
+		    
+		    sdtOrient {
+			set thisparam(orient) $value
+		    }
+		}
+	    }
+	}
+	
+
+	close $fileid
+	return 1
+    }
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxtclreadvarianheader.tcl b/bioimagesuite30_src/bioimagesuite/base/pxtclreadvarianheader.tcl
new file mode 100644
index 0000000..8bf771c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxtclreadvarianheader.tcl
@@ -0,0 +1,239 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxtclreadvarianheader 1.0
+
+# 	$Id: pxtclreadvarianheader.tcl,v 1.1 2002/02/20 18:07:50 Xenios Exp Xenios $	
+
+
+
+
+
+
+
+package require pxvtable 1.0
+package require vtkpxcontrib 1.0
+
+namespace eval ::pxtclreadvarianheader {
+
+    proc ReadVarianHeader { fname } {
+	
+	if { [string length $fname] < 1 } {
+	    return 0
+	}
+	
+	if { [ file exists $fname ]  == 0 } {
+	    return 0
+	}
+	
+	set element [ vtkXMLDataElement New ]
+	$element SetAttribute "studyid" "__none__"
+	$element SetAttribute "array_index" 1
+	$element SetAttribute "array_dimension" 1
+	$element SetAttribute "slice_no" 1
+	$element SetAttribute "slices" 1
+	$element SetAttribute "matrix" "0"
+	
+	set fileid [open $fname r ]
+	set foundend 0
+	while { [ gets $fileid line ] >=0 && $foundend ==0 } {
+	    if { [ string length $line ] == 1 } {
+		set foundend 1
+	    } else {
+		set index [string first "\#" $line]
+		if { $index != 0 } {
+		    set index [string first "=" $line]
+		    set len   [string length $line]
+		    set key   [string trim   [string range $line 0 [expr $index - 1]]]
+		    set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		    
+		    regsub -all " +" $key " " key
+		    regsub -all "\\\[" $key "" key
+		    regsub -all "\\\]" $key "" key
+		    regsub -all "\\\*" $key "" key
+		    
+		    regsub -all "," $value " " value
+		    regsub -all "\{" $value "" value
+		    regsub -all "\}" $value "" value
+		    regsub -all "\\\;" $value "" value
+		    regsub -all " +" $value " " value
+		    regsub -all "\"" $value "" value
+		    
+		    set key2 [ lindex [  split $key " "   ]  1 ]
+		    
+		    $element SetAttribute $key2 $value
+		}
+	    }
+	}
+	close $fileid
+	
+	set fz [ file size $fname ]
+	set val [ $element GetAttribute "matrix" ]
+	
+	set n 1
+	for { set i 0 } { $i < [ llength $val ] } { incr i } {
+	    set n [ expr $n * [ lindex $val $i ] ]
+	}
+	
+	set bits [ expr [ $element GetAttribute "bits" ] / 8 ]
+	
+	$element SetAttribute bis_HeaderSize [ expr $fz - $n*$bits ]
+	$element SetAttribute bis_OriginalFileName $fname
+	
+	set mat [ $element GetAttribute "matrix" ]
+	if { [ llength $mat  ] < 3 } {
+	    lappend mat 1
+	}
+	set fov  [ $element GetAttribute "roi" ]
+	set units [ $element GetAttribute "abscissa" ]
+	if { $units == "" } {
+	    set units "mm mm mm"
+	}
+
+	for { set i 0 } { $i <=2 } { incr i } {
+	    set spa($i) [ expr [ lindex $fov $i ]/ (0.000+ [ lindex $mat $i ] ) ]
+	    set ut [ lindex $units $i ]
+	    if { $ut == "cm" } {
+		set spa($i) [ expr $spa($i) * 10.0 ]
+	    }
+	    set dim($i) [ lindex $mat $i ]
+	    $element SetAttribute "bis_Dimension$i" $dim($i)
+	    $element SetAttribute "bis_Spacing$i"   $spa($i)
+	}
+
+	set orient [ $element GetAttribute orientation ]
+	for { set i 0 } { $i < [ llength $orient ] } { incr i } {
+	    $element SetAttribute "bis_Orient$i" [ lindex $orient $i ]
+	}
+
+	return $element
+	
+    }
+    
+    proc PrintHeaderList { element } {
+	
+	set n [ $element GetNumberOfAttributes ]
+	for { set  i 0 } { $i < $n } { incr i } {
+	    set a [ $element GetAttributeName $i ]
+	    set b [ $element GetAttributeValue $i ]
+	    puts stdout "$a-->$b"
+	}
+    }
+    
+    proc GetVarianScaleFactor { img } {
+
+	set r [ [ [ $img GetPointData ] GetScalars ] GetRange ]
+	set dt [ $img GetScalarType ]
+	if { $dt !=11 && $dt!=10 } {
+	    #puts stdout "dt=$dt"
+	    return 1.0
+	}
+	
+	set r1 [ lindex $r 1 ]
+	set r0 [ lindex $r 0 ]
+	#	puts stdout "R1=$r1, ro=$r0"
+	if {  ($r1 > $r0 ) && [ expr ($r1 - $r0) ] < 1.0 } {
+	    set vl 10000.0
+	    return $vl
+	} 
+	return 1.0
+    }
+
+    proc ReadVarianImage { element { parobj 0 } } {
+	
+	set hd [ $element GetAttribute "bis_HeaderSize" ]
+	set bits [ $element GetAttribute "bits" ]
+
+	for { set i 0 } { $i <=2 } { incr i } {
+	    set spa($i) [ $element GetAttribute bis_Spacing$i ]
+	    set dim($i) [ $element GetAttribute bis_Dimension$i ]
+	}
+
+
+	set fname [ $element GetAttribute bis_OriginalFileName ]
+	set anar [ vtkpxAnalyzeImageSourceOld New ]
+	
+	$anar SetVoxelDimensions $spa(0) $spa(1) $spa(2)
+	$anar SetHeaderInfo $dim(0) $dim(1) $dim(2) 1 0 [ expr $bits / 8 ]
+	$anar SetHeaderSize $hd
+	$anar SetFilePrefix $fname
+	if { $parobj !=0 } { $parobj SetFilterCallbacks $anar "Reading Varian Image" }
+	$anar Update
+
+
+	set img [ vtkImageData New ]
+
+	set vl [ GetVarianScaleFactor [ $anar GetOutput ] ]
+	if { $vl > 1.0 } {
+	    puts stdout "Scaling Varian image by $vl"
+	    set shift [ vtkImageShiftScale New ]
+	    $shift SetInput [ $anar GetOutput ]
+	    $shift SetScale $vl
+	    $shift SetShift 0.0
+	    $shift Update
+	    $img ShallowCopy [ $shift GetOutput ]
+	    $shift Delete
+	} else {
+	    $img ShallowCopy [ $anar GetOutput ]
+	}
+	$anar Delete
+	return $img
+    }
+    
+    proc WriteNIIImage { img outname } {
+
+	set anaw [ vtkpxAnalyzeImageWriter New ]
+	$anaw SetInput $img
+	$anaw Save $outname 
+	$anaw Delete
+    }
+
+
+    proc Test { argv } {
+	set fname [ lindex $argv 0 ]
+	
+	set element [ ReadVarianHeader $fname ]
+	if { $element ==0 } {
+	    exit
+	}
+	
+
+	
+	if { [ llength $argv ] > 1 } {
+	    set outname [ lindex $argv 1 ]
+	} else {
+	    set outname "[ file rootname $fname].nii.gz"
+	}
+	
+	set img [ ReadImage $element ]
+		PrintHeaderList $element
+	#	WriteImage $img $outname 
+	$element Delete
+	$img Delete
+    }
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxtclruncommand.tcl b/bioimagesuite30_src/bioimagesuite/base/pxtclruncommand.tcl
new file mode 100644
index 0000000..8377b14
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxtclruncommand.tcl
@@ -0,0 +1,200 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxtclruncommand.tcl,v 1.1 2004/03/12 14:49:02 xenios Exp xenios $	
+
+package provide pxtclruncommand 1.0
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxvtable   1.0
+package require  Itcl       3.2
+
+
+itcl::class pxtclruncommand {
+
+    protected variable basewidget 0
+    public variable callback 0
+    public variable progresscallback 0
+    public variable message "Algorithm Completed"
+    protected variable lasttitle ""
+
+    protected common thisparam
+
+    constructor { } { 
+	set thisparam($this,command) "ls -l"
+    }
+
+    public method GetThisPointer { } { return $this }
+    public method Initialize { widget inside standalone }
+    public method Run  { args } 
+    public method Log  { } 
+    public method Stop { } 
+    public method List { }
+    public method Hide { } {wm withdraw $basewidget}
+    public method Show { } {wm deiconify $basewidget}
+    public method SetCallback { func } { set callback $func }
+    public method SetProgressCallback { func } { set progresscallback $func }
+
+    public method SetCommand { cmd } {
+	set thisparam($this,command) $cmd 
+    }
+}
+
+itcl::body pxtclruncommand::Initialize { widget inside standalone } {
+
+    set basewidget $widget
+
+    if { $inside == 0 } {
+	toplevel $basewidget
+	if { $standalone == 0 } {
+	    wm withdraw $basewidget
+	}
+    } else {
+	frame $basewidget 
+    }
+
+    set w $basewidget
+
+    frame $w.c; frame $w.exec
+    pack $w.c    -side top -fill x -expand f
+    pack $w.exec -side top -fill x -expand f
+
+    entry $w.c.command -textvariable [ itcl::scope thisparam($this,command) ] -width 50 -relief sunken 
+    pack $w.c.command  -side top -fill x -expand t -padx 5
+
+    set w [LabelFrame:create $basewidget.log -text "Log" -expand true -fill both]
+    pack $basewidget.log -side top -fill both -expand t
+
+    set cmd "text $w.log -width 80 -height 10  -borderwidth 2 -relief raised -setgrid true  -yscrollcommand {$w.scroll set}"
+    eval $cmd
+    set thisparam($this,gui_log) $w.log
+    
+    set cmd "scrollbar $w.scroll -command { $w.log yview} "
+    eval $cmd
+
+    pack $w.scroll -side right -fill y
+    pack $w.log -side left -fill both -expand true
+    
+    frame $basewidget.buttonbar  -bg white -bd 4
+    pack $basewidget.buttonbar -side bottom -fill x -expand f
+    set w  $basewidget.buttonbar 
+
+    set thisparam($this,gui_runbutton) [ button $w.run   -text "Run!" ]
+    eval "$thisparam($this,gui_runbutton) configure  -command { $this Run  } "
+    set thisparam($this,gui_stopbutton) [ button $w.stop  -text "Stop!" -state disabled ]
+    eval "$thisparam($this,gui_stopbutton) configure -command { $this Stop  } "
+
+    if { $standalone == 0 } {
+	set cmd "button $w.close -text Close -command { wm withdraw $basewidget }";  eval $cmd
+    } else {
+	set cmd "button $w.close -text Close -command { wm withdraw $basewidget }";  eval $cmd
+	#set cmd "button $w.close -text Exit -command { pxtkexit }";  eval $cmd
+    }
+
+
+    
+    pack $w.run $w.stop  $w.close -fill x -side left -expand t -padx 20
+    
+    set thisparam($this,gui_closebutton) $w.close 
+
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    wm title $basewidget "External Command Console"
+    return $basewidget
+}
+
+
+itcl::body pxtclruncommand::Run { args } {
+	
+
+    if [catch {  set thisparam($this,gui_input) [ open "| $thisparam($this,command) 2>@1 " ] } ] {
+	pxtclutil::Warning "Error, please check all the parameters.\n"
+	$thisparam($this,gui_log) insert end "thisparam($this,gui_input)\n"
+    } else {
+	$thisparam($this,gui_log) delete 1.0 end
+	fileevent $thisparam($this,gui_input) readable [ list $this Log ]
+    }
+    $thisparam($this,gui_stopbutton) configure -state normal
+    $thisparam($this,gui_runbutton) configure -state disabled
+
+
+
+    if { [ llength $args ] > 0 } {
+	set lasttitle [ lindex $args 0 ]
+    } else {
+	set lasttitle $thisparam($this,command)
+	if { [ string length $lasttitle ] > 25 } {
+	    set lasttitle "[ string range $lasttitle 0 25 ]..."
+	}   
+    }
+    wm title $basewidget "Console :: $lasttitle "
+    
+}
+
+itcl::body pxtclruncommand::Log {  } {
+	
+
+    if [eof $thisparam($this,gui_input)] {
+	Stop
+	wm title $basewidget "Console :: $lasttitle COMPLETED"
+ 	if { $callback !=0  } { 
+	    eval $callback
+	    set progresscallback 0
+	} else {
+	    ::pxtclutil::Info $message
+	}
+    } else {
+	gets $thisparam($this,gui_input) line
+	$thisparam($this,gui_log) insert end "$line\n"
+	$thisparam($this,gui_log) see end
+ 	if { $progresscallback !=0  } { 
+	    eval "$progresscallback $line"
+	} 
+    }
+}
+
+# Stop the program and fix up the button
+
+itcl::body pxtclruncommand::Stop {  } {
+	
+    catch {close $thisparam($this,gui_input)}
+    $thisparam($this,gui_stopbutton) configure -state disabled
+    $thisparam($this,gui_runbutton) configure -state normal
+    wm title $basewidget "Console :: $lasttitle STOPPED"
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxtcluserprefs.tcl b/bioimagesuite30_src/bioimagesuite/base/pxtcluserprefs.tcl
new file mode 100644
index 0000000..7ab6d49
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxtcluserprefs.tcl
@@ -0,0 +1,483 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxtcluserprefs 1.0
+
+# 	$Id: pxtcluserprefs.tcl,v 1.1 2002/04/29 18:05:15 papad Exp papad $	
+
+
+
+
+
+package require pxtclutil    1.0
+package require pxvtable     1.0
+package require vtkpxcontrib 1.0
+
+
+namespace eval ::pxtcluserprefs {
+
+    proc LoadUserPrefs { } {
+	
+	global pxtcl_pref_array
+	global pxtcl_pref_array_names
+	global pxtcl_pref_array_list
+	global env
+
+
+	global env
+	set fn ".bioimagesuite3"; catch { set fn $env(BIODBASE) }
+	set fn [ file join $env(HOME) $fn ]
+	
+	set connector [ vtkbisDatabase New ]
+	$connector InitializeSQLite "$fn" 
+	set dbase_ok [ $connector Connect ]
+	
+	set usingdbase 0
+
+	if { $dbase_ok > 0 } {
+	    set dbase [ vtkbisFilenameTable New ]
+	    $dbase SetConnector $connector
+	    $dbase CreateTable
+	    set lst [ split [ $dbase QueryAll "User_Preferences" ] "|" ]
+	    
+
+	    if { [ llength $lst ] > 0 } {
+		set usingdbase 1
+		for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+		    set line [ lindex $lst $i ]
+		    set lst2 [  split $line "," ]
+		    if { [ llength $lst2 ] == 3 } {
+			set key   [string trim   [ lindex $lst2 1 ] ]
+			set value [string trim   [ lindex $lst2 2 ] ]
+			set pxtcl_pref_array($key) $value
+		    }
+		}
+	    }
+	    $dbase Delete
+	}
+	$connector Delete
+	
+	# -----------------------------------------------------------------------
+
+	if { $usingdbase == 0 } {
+	    # Read from file as before
+	    set f [ GetUserPrefName ]
+	    if { [ file  exists $f ] !=0 } {
+		::pxtclutil::ReadArray $f pxtcl_pref_array "#BioImageSuite_Preferences"
+	    }
+	}
+
+	set remove_list ""
+	foreach { key value } [array get pxtcl_pref_array] {
+	    set l2   [ array get pxtcl_pref_array_list $key ]
+	    if { [ llength $l2 ] != 2 } {
+		set remove_list [ lappend $remove_list  $key ]
+	    }
+	}
+	for { set k 0 } { $k < [ llength $remove_list ] } { incr k } {
+	    array unset pxtcl_pref_array [ lindex $remove_list $k ]
+	}
+
+	    
+	if { $pxtcl_pref_array(FmriMode) == "64" } {
+	    set pxtcl_pref_array(FmriMode) F1
+	} elseif { $pxtcl_pref_array(FmriMode) == "256" } {
+	    set pxtcl_pref_array(FmriMode) F2
+	}
+	
+	if { $pxtcl_pref_array(VolumeTextureMode) == 1 } {
+	    set pxtcl_pref_array(VolumeTextureMode) 2
+	}
+
+	if { $usingdbase == 0 && $dbase_ok > 0 } {
+	    SaveUserPrefs
+	}
+
+
+	# ---------------------------------------------
+	#	::pxtclutil::PrintArray pxtcl_pref_array
+    }
+
+    # ---------------------------------------------------------------------------------
+
+    proc SaveUserPrefs { } {
+
+	global env
+	set fn ".bioimagesuite3"; catch { set fn $env(BIODBASE) }
+	set fn [ file join $env(HOME) $fn ]
+	global pxtcl_pref_array	
+
+	set connector [ vtkbisDatabase New ]
+	$connector InitializeSQLite "$fn" 
+	set ok [ $connector Connect ]
+	
+	set usingdbase 0
+
+	if { $ok > 0 } {
+	    set dbase [ vtkbisFilenameTable New ]
+	    $dbase SetConnector $connector
+	    $dbase DeleteAll "User_Preferences"
+	    
+	    foreach { key value } [ array get pxtcl_pref_array ] {
+		$dbase AddItem "User_Preferences" $key $value 
+	    }
+	    $dbase Delete
+	    set usingdbase 1
+	}
+	$connector Delete
+	
+	if { $usingdbase == 0 } {
+	    set f [ GetUserPrefName ]
+	    ::pxtclutil::SaveArray $f pxtcl_pref_array "#BioImageSuite_Preferences"
+	}
+    }
+
+
+    proc GetUserPrefName { } {
+
+	global env
+	set fn ".bioimagesuite3"; catch { set fn $env(BIODBASE) }
+	set fn [ file join $env(HOME) $fn ]
+	
+	set a ".bioimagesuite"
+	catch { set a $env(BIOIMAGESUITECONF) }
+	return [ file join $env(HOME) $a ]
+    }
+
+    proc EnsureUserPrefs { } {
+	global pxtcl_pref_array
+	global pxtcl_pref_array_names
+
+	if { $pxtcl_pref_array(VectorVisionLink) == "Enabled" } {
+	    set vvl 0
+	    catch { 
+		set vvl [ vtkpxVVLinkConnectorNew [ pxvtable::vnewobj ] ]
+		$vvl Delete
+		set vvl 1
+	    }
+
+	    if { $vvl == 0 } {
+		 set pxtcl_pref_array(VectorVisionLink)  "Disabled"
+	     }
+	 }
+
+	if { $pxtcl_pref_array(MincImageFormat) == "Enabled" } {
+	    set minc 0
+	     catch { 
+		 set minc [ vtkMINC2ImageReader [ pxvtable::vnewobj ] ]
+		 $minc Delete
+		 set minc 1
+	     }
+	     if { $minc == 0 } {
+		 set pxtcl_pref_array(MincImageFormat)  "Disabled"
+	     } 
+	} 
+
+	if { $pxtcl_pref_array(MincImageFormat) == "Disabled" } {	    
+	    set pxtcl_pref_array(MincImageFormatDefault) 0
+	}
+    }
+
+    proc Init { }  {
+	global pxtcl_pref_array
+	global pxtcl_pref_array_list
+	global pxtcl_pref_array_names
+	global tcl_platform
+
+	catch { array  unset pxtcl_pref_array }
+
+	# Set Default Values 
+	# ------------------
+
+	# -----------------   Set 1 ---------- Look and Feel
+
+	set pxtcl_pref_array(ColorScheme) "System Default"
+	set pxtcl_pref_array_list(ColorScheme) [ list "System Default" "BioImage Suite Blue" "Bisque" "High Contrast" ]
+	set pxtcl_pref_array(FontSelection) "System Default"
+	set pxtcl_pref_array_list(FontSelection) [ list "System Default" "Small" "Medium" "Large" "Extra Large" ]
+	set pxtcl_pref_array(MirrorConsole) 0
+	set pxtcl_pref_array_list(MirrorConsole) [ list "0" "1" ]
+
+	lappend pxtcl_pref_array_names [ list "Look & Feel" "ColorScheme" "FontSelection" "MirrorConsole" ]
+
+	# -----------------   Set 2 ---------- File Formats etc
+
+	set pxtcl_pref_array(ForceOutputFormat) "Auto" 
+	set pxtcl_pref_array_list(ForceOutputFormat) [ list "Auto" "Analyze" "NIFTI" ]
+
+	set pxtcl_pref_array(DefaultImportMode) "Binary"
+	set pxtcl_pref_array_list(DefaultImportMode) [ list "Signa LX" "Binary" "Raw MR" "Analyze" "Prism (SPECT)" "DICOM" "Signa Spr" "Nmr47" "TIFF" "PNM" "BMP"  ]
+
+	set pxtcl_pref_array(MincImageFormat) "Enabled"
+	set pxtcl_pref_array_list(MincImageFormat) [ list  "Disabled" "Enabled" ]
+
+	lappend pxtcl_pref_array_names [ list "File Formats" "ForceOutputFormat" "DefaultImportMode" "MincImageFormat"  ]
+
+	# ----------------- Set 2.5 ------------ Coordinates
+
+	set pxtcl_pref_array(ManualTalairach) "Off"
+	set pxtcl_pref_array_list(ManualTalairach)  [ list "On" "Off" ]
+
+	set pxtcl_pref_array(WFUAtlasAutoInitialize) "Disabled" 
+	set pxtcl_pref_array_list(WFUAtlasAutoInitialize) [ list  "Disabled" "Enabled"  ]
+
+	set pxtcl_pref_array(YaleAtlasAutoInitialize) "Disabled" 
+	set pxtcl_pref_array_list(YaleAtlasAutoInitialize) [ list  "Disabled" "Enabled" ]
+
+	lappend pxtcl_pref_array_names [ list "Coordinates"  "WFUAtlasAutoInitialize" "YaleAtlasAutoInitialize"  "ManualTalairach" ]
+
+
+	# -----------------   Set 3 ---------- Image Display
+	set pxtcl_pref_array(VolumeTextureMode) 2
+	set pxtcl_pref_array_list(VolumeTextureMode) [ list "0" "2" "3" ]
+
+	set pxtcl_pref_array(FmriMode) F2
+	set pxtcl_pref_array_list(FmriMode) [ list "F1" "F2" "F4" ]
+	
+	set pxtcl_pref_array(NormalizeAnatomical) 1
+	set pxtcl_pref_array_list(NormalizeAnatomical) [ list "0" "1" ]
+
+	set pxtcl_pref_array(ImageColormaps) "0"
+	set pxtcl_pref_array_list(ImageColormaps) [ list "0" "1" ]
+
+	set pxtcl_pref_array(Interpolation) "Linear"
+	set pxtcl_pref_array_list(Interpolation) [ list "NearestNeighbor" "Linear" "Cubic" ]
+
+	lappend pxtcl_pref_array_names [ list "Image Display" "NormalizeAnatomical" "ImageColormaps" "Interpolation" "VolumeTextureMode" "FmriMode"  ]
+
+	# -----------------   Set 4 ---------- Surface Editor
+
+	set pxtcl_pref_array(SurfaceEditorMaxSurfaces) "4"
+	set pxtcl_pref_array_list(SurfaceEditorMaxSurfaces) [ list "2" "4" "8" "12" "20" "30" "45" ]
+
+	set pxtcl_pref_array(SplineEditorControlPointScale) "4"
+	set pxtcl_pref_array_list(SplineEditorControlPointScale) [ list "1" "2" "3" "4" "5" "6" "7" "8" ]
+
+	set pxtcl_pref_array(ObjectMapVOIMode) "Normal"
+	set pxtcl_pref_array_list(ObjectMapVOIMode) [ list "Normal" "Fat1" "Fat2" "Custom" ]
+	
+	lappend pxtcl_pref_array_names [ list "Surface Editing" "SurfaceEditorMaxSurfaces" "SplineEditorControlPointScale" "ObjectMapVOIMode" ]
+
+
+	# -----------------   Set 5 ---------- Advanced Misc
+
+	set pxtcl_pref_array(FSLVersion) "4.0 (or older)"
+	set pxtcl_pref_array_list(FSLVersion) [ list "4.0 (or older)" "4.1" ]
+
+	set pxtcl_pref_array(RigidRegistration) "Normal"
+	set pxtcl_pref_array_list(RigidRegistration) [ list "Normal" "Stitch" ]
+
+	set pxtcl_pref_array(VectorVisionLink) "Disabled"
+	set pxtcl_pref_array_list(VectorVisionLink) [ list "Disabled" "Enabled" ]
+
+	set pxtcl_pref_array(OpenIGTLink) "Disabled"
+	set pxtcl_pref_array_list(OpenIGTLink) [ list "Disabled" "Enabled" ]
+
+	set pxtcl_pref_array(EnableBetaFeatures) "Disabled"
+	set pxtcl_pref_array_list(EnableBetaFeatures)  [ list "Disabled" "Enabled" ]
+
+	lappend pxtcl_pref_array_names [ list "Advanced/Miscelleneous" "FSLVersion" "RigidRegistration" "VectorVisionLink" "OpenIGTLink" "EnableBetaFeatures" ]
+
+	# Modify for each platform
+	# ------------------------
+# 	if { $tcl_platform(byteOrder) == "littleEndian" } { 
+# 	    set pxtcl_pref_array(SwapOnSave) 1
+# 	}
+
+# 	if { $tcl_platform(platform) == "windows" } {
+# 	    set pxtcl_pref_array(TextureMode) 0
+# 	}
+	
+    }
+
+
+    proc CreatePreferenceEditor  { } {
+
+	global pxtcl_pref_array
+	global pxtcl_pref_array_list
+	global pxtcl_pref_array_names
+
+	set comment "Global Preferences for Ipag BioImageSuite"
+	set comment2 "([::pxtcluserprefs::GetUserPrefName])"  
+	set comment3 "Changes will take effect when the application is restarted!"
+	set loadcommand "::pxtcluserprefs::LoadUserPrefs" 
+	set savecommand "::pxtcluserprefs::SaveUserPrefs" 
+	set resetcommand "::pxtcluserprefs::Init" 
+
+	set top [ pxvtable::vnewobj]
+	set dlg [ toplevel .$top ]
+	wm geometry .$top 600x280
+	wm withdraw $dlg
+	wm title $dlg "BioImage Suite User Preferences"
+
+	label $dlg.o -bg black -fg white -text $comment
+	#	label $dlg.o2 -bg black -fg white -text $comment2
+	label $dlg.o3 -bg black -fg white -text $comment3
+	pack $dlg.o $dlg.o3 -side top -expand f -fill x -pady 0
+
+	frame $dlg.bot  
+	pack $dlg.bot -side bottom -pady 5 -expand t -fill x
+
+	frame $dlg.o4 -height 4 -bg black
+	pack $dlg.o4 -side bottom -expand t -fill x -pady 2
+
+	set notebook [ iwidgets::tabnotebook $dlg.mid  -tabpos w -gap 2 -margin 2 -raiseselect true]
+	pack $notebook -side top -expand t -fill both -pady 2
+
+	set listlen [ llength $pxtcl_pref_array_names ]
+
+	set c 0
+
+	set defname ""
+
+	for { set i 0 } { $i < $listlen } { incr i } {
+
+	    set keylist [ lindex $pxtcl_pref_array_names $i ]
+	    set len     [ llength $keylist ]
+	    set nname   [ lindex $keylist 0 ]
+
+	    set fr [ $notebook add -label $nname ]
+
+	    if { $i == 0 } {
+		set defname $nname 
+	    }
+
+	    for { set k 1 } { $k < $len } { incr k } {
+		set name [ lindex $keylist  $k ] 
+		frame $fr.$c
+		pack $fr.$c -side top -expand t -fill x
+		
+		label $fr.$c.l -text $name -width 25
+		eval "tk_optionMenu $fr.$c.e  pxtcl_pref_array($name) $pxtcl_pref_array_list($name)"
+		pack $fr.$c.l $fr.$c.e -side left -expand f -padx 2 -fill x -pady 0
+		incr c
+	    }
+	}
+	
+	eval "button $dlg.bot.close -text Close -command { wm withdraw $dlg }"
+        eval "button $dlg.bot.load -text ReLoad -command { $loadcommand }"
+        eval "button $dlg.bot.save -text Save   -command { $savecommand }"
+        eval "button $dlg.bot.def -text Defaults   -command { $resetcommand }"
+	
+	pack $dlg.bot.load $dlg.bot.save $dlg.bot.def $dlg.bot.close -side left -expand t -padx 20 -fill x
+	eval "wm protocol $dlg WM_DELETE_WINDOW { wm withdraw $dlg }"
+
+	$notebook view $defname
+	return $dlg
+
+
+    }
+
+    # -------------------------------------------------------------------------
+    # Initialize Color Schemes 
+    # -------------------------------------------------------------------------
+    
+    proc InitializeBioImageSuiteColorAndFontScheme { } {
+
+	global pxtcl_pref_array
+	option clear
+
+
+
+	switch -exact  $pxtcl_pref_array(ColorScheme) {
+	    "BioImage Suite Blue"  {
+		option add *foreground  "\#400000"
+		option add *selectColor  "\#d00000"
+		option add *disabledForeground  black
+		option add *activeForeground   "\#d00000"
+
+		option add *background  "\#cccdf8"
+		option add *textBackground  "\#cccdf8"
+		option add *scaleBackground  "\#cccdf8"
+		option add *backdrop    "\#cccdf8"
+		option add *activeBackground "\#cccdf8"
+		option add *highlightBackground "\#cccdf7"
+
+		option add *disabledBackground  "\#bbbce7"
+		option add *highlightColor  "\#bbbce7"
+		option add *selectBackground  "\#bbbce7"
+		
+		option add *readonlybackground  "\#8197c5"
+		option add *tabBackground  "\#8197c5"
+		option add *troughColor  "\#8197c5"
+		option add *highlightColor      "\#8197c5"
+		
+	    } "Bisque" {
+	    
+		tk_bisque
+		option add *background  "#ffe4c4"
+		option add *tabBackground  "#ccb4a4"
+		option add *textBackground "#ffe4c4"
+		option add *scaleBackground "#ffe4c4"
+		option add *backdrop "#ffe4c4"
+		option add *activeBackground "#ffe4c4"
+		option add *highlightBackground "#ffe4c4"
+		
+		option add *disabledBackground  "\#eed4b4"
+		option add *disabledForeground  darkgray
+
+	    } "High Contrast" { 
+	    
+		option add *background  "#ffffff"
+		option add *tabBackgrod  "#ffffff"
+		option add *textBackground "#ffffff"
+		option add *scaleBackground "#ffffff"
+		option add *backdrop "#ffffff"
+		option add *activeBackground "#ffffff"
+		option add *highlightBackground "#ffffff"
+		
+		option add *selectColor  "\#d00000"
+		option add *disabledForeground  "\#505050"
+		option add *activeForeground   "\#202020"
+		
+		option add *disabledBackground  "\#bbbbbb"
+		option add *highlightColor  "\#bbbbbb"
+		option add *selectBackground  "\#bbbbbb"
+		
+		option add *readonlybackground  "\#cccccc"
+		option add *tabBackground       "\#cccccc"
+		option add *troughColor         "\#cccccc"
+		option add *highlightColor      "\#cccccc"
+	    } 
+	}
+	
+	switch -exact $pxtcl_pref_array(FontSelection) {
+	    "Small"  {  option add *font { Helvetica 8 bold } }
+	    "Medium" {  option add *font { Helvetica 9 bold } }
+	    "Large"  {  option add *font { Helvetica 10 bold } }
+	    "Extra Large" { option add *font { Helvetica 12 bold } }
+	}
+    }
+}
+
+::pxtcluserprefs::Init
+::pxtcluserprefs::LoadUserPrefs
+::pxtcluserprefs::EnsureUserPrefs
+::pxtcluserprefs::InitializeBioImageSuiteColorAndFontScheme
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxtclutil.tcl b/bioimagesuite30_src/bioimagesuite/base/pxtclutil.tcl
new file mode 100644
index 0000000..f8674de
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxtclutil.tcl
@@ -0,0 +1,720 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxtclutil 1.0
+
+
+
+
+package require pxvtable 1.0
+
+# 	$Id: pxtclutil.tcl,v 1.2 2002/02/22 23:18:07 Xenios Exp $	
+
+
+namespace eval ::pxtclutil {
+    
+    namespace export  ReadArray SaveArray PrintArray CreateTriple CreateInputFile LoadParameters SaveParameters ShowWindow HideWindow  ExportJPEGImage ColorBox FindCommandInPath
+
+    # Some Quick Dialog Boxes
+    # ------------------------
+
+    proc GetAbsoluteFileName { fname } {
+	if { [ file pathtype $fname ] == "relative" } {
+	    set out [ file join [ pwd ] $fname ]
+	    regsub -all  "/./" $out "/" out
+	} else {
+	    set out $fname
+	}
+	
+	return $out
+    }
+
+    proc Info    { message } { 
+	set a 0
+	catch { set a [ llength [ winfo children . ] ] }
+	if { $a > 1 } {
+	    tk_messageBox -type ok -message $message -title "For your information ..." -icon info
+	} else {
+	    puts stdout "Info -- $message"
+	}
+    }
+
+    proc Warning { message } {
+	set a 0
+	catch { set a [ llength [ winfo children . ] ] }
+	if { $a > 1 } {
+	    tk_messageBox -type ok -message $message -title "Error!" -icon error
+	} else {
+	    puts stderr "Error -- $message"
+	}
+    }
+
+    proc Question { message } {
+	set ok [ tk_messageBox -type yesno -default no -title "Think again ..." -message $message -icon question  ]
+	if { $ok == "yes" } {
+	    return 1
+	}  else {
+	    return 0
+	}
+    }
+
+
+    proc Question2 { message } {
+	set ok [ tk_messageBox -type yesnocancel -default no -title "Think again ..." -message $message -icon question  ]
+	if { $ok == "yes" } {
+	    return 1
+	}  elseif { $ok=="no" } {
+	    return 0
+	} else {
+	    return -1
+	}
+    }
+
+    proc GetLinearSuffix { } { return "affine.matr" } 
+    proc GetNonLinearSuffix { } { return "grid.grd" } 
+    proc GetNonLinearRPMSuffix { } { return "rpm.grd" } 
+
+    proc GenerateFilename { name1 name2 identifier suffix { basedir "" } { filenametype 0 } } {
+
+	set f1a [ file tail [ file dirname $name1 ]]
+	set f1b [ file root [ file tail $name1 ]]
+	set f2a [ file tail [ file dirname $name2 ]]
+	set f2b [ file root [ file tail $name2 ]]
+	if { $filenametype > 0 } {
+	    set newname "${f1a}${f1b}_${f2a}${f2b}_${identifier}_${suffix}"
+	} else {
+	    set newname "${f1b}_${f2b}_${identifier}_${suffix}"
+	}
+	if { $basedir != "" } {
+	    set newname [ file join $basedir $newname ]
+	}
+	return $newname
+    }
+
+    # Show/Hide Window Stuff
+    proc ShowWindow { w } { 
+	wm deiconify $w ; raise $w ;
+	set geom ""
+	catch { set geom [ winfo geometry [ winfo parent $w ]] }
+	if { [ string length $geom ] > 2 } {
+	    
+	    set offset [ lsearch [ winfo children [ winfo parent $w ]] $w ]
+	    
+	    scan $geom "%dx%d+%d+%d" w0 h0 x0 y0
+	    set x0 [ expr $x0+$w0/2+20*$offset]
+	    set y0 [ expr $y0+5+10*$offset ]
+	    wm geometry $w "+$x0+$y0"
+	}
+    }
+    
+    proc HideWindow { w } {
+	set len [ llength [ winfo children $w ]]
+	if { $len > 0 } {
+	    for { set k 0 } { $k < $len } { incr k } { 
+		set a [ lindex [ winfo children $w ] $k ]
+		if { [ winfo class $a ] == "Toplevel"} {
+		    HideWindow $a
+		}
+	    }
+	}
+	wm withdraw $w
+    }
+
+
+    # A Complex GUI Element
+    # ---------------------
+    proc CreateTriple {base2 name variable range1 range2 resol interv length } {
+	
+	set base [ LabelFrame:create $base2 -text $name ]
+	pack $base2 -side left -padx 3 -pady 1 -expand t -fill both
+
+	entry  $base.en -width 5 -textvariable $variable -relief sunken
+	scale  $base.sc -orient horizontal  -from $range1 -to $range2 -resolution $resol -bigincrement $interv -showvalue 0 -length $length -variable $variable
+	pack $base.sc $base.en -side left -expand true -fill x
+	
+	return $base.sc
+    }
+
+    proc CreateInputFile { f name tvar } {
+
+	frame  $f -relief raised
+	pack $f -side top -expand true -fill x -padx 2 -pady 2
+
+	label  $f.name -text $name
+	set cmd " entry  $f.entry -width 35 -textvariable $tvar "
+	eval $cmd
+	button $f.but -text "Browse"
+
+	pack $f.name $f.entry  -side left -fill x -pady 5 -expand true
+	pack $f.but -side left -pady 5 
+	return $f.but
+    }
+
+    # --------------------------------------------------
+    # --------------------------------------------------
+    # Save Array from file including possible headerline
+    # --------------------------------------------------
+
+    proc printArrays {args} {
+	foreach array $args {
+	    upvar $array data
+	    foreach name [lsort [array names data]] {
+		puts "$array\($name\) = $data($name)"
+	    }
+	}
+    }
+    # --------------------------------------------------
+    proc PrintArray { varname } {
+	::pxtclutil::SaveArray "" $varname "Debug Info"
+    }
+
+    proc SaveArray { fname varname2 headerline } {
+	SaveArrayComplex $fname $varname2 $headerline "" 
+    }
+
+    # --------------------------------------------------
+    proc SaveArrayComplex { fname varname2 headerline exclude } {
+	
+	upvar #0 $varname2 varname
+
+	set len [ string length $exclude ]
+	set keylist { }
+	foreach { key value } [array get varname] {
+	    if { $len > 0 } {
+		if { [ string equal -length $len $key $exclude ] == 0 } {
+		    set keylist [concat $keylist $key]
+		}
+	    } else {
+		set keylist [concat $keylist $key]
+	    }
+	}
+	set keylist [lsort -ascii $keylist]
+	
+	if { [string length $fname] > 0 } {
+	    set fileid [open $fname w]
+	} else {
+	    set fileid stdout
+	}
+	
+	if { [ string length $headerline  ] > 0 } {
+	    puts $fileid "$headerline"
+	    puts $fileid "--------------------"
+	}
+	
+	for { set k 0 } { $k < [llength $keylist] } { incr k } {
+	    set key [lindex $keylist $k]
+	    puts $fileid "$key  : $varname($key)"
+	}
+	
+	if {$fileid != "stdout" } {
+	    close $fileid
+	}
+    }
+
+    # --------------------------------------------------
+    proc SaveArrayList { fname varname2 headerline paramlist } {
+	
+	upvar #0 $varname2 varname
+
+	set keylist [ array names varname ]
+	
+	if { [string length $fname] > 0 } {
+	    set fileid [open $fname w]
+	} else {
+	    set fileid stdout
+	}
+	
+	if { [ string length $headerline  ] > 0 } {
+	    puts $fileid "$headerline"
+	    puts $fileid "--------------------"
+	}
+	
+	for { set k 0 } { $k < [llength $paramlist] } { incr k } {
+
+	    set key [lindex $paramlist $k]
+	    set value ""
+	    set ind [ lsearch  -exact $keylist $key ]
+	    if { $ind >=0 } {
+		set value $varname($key)
+	    }
+	    if { [ string length $value] > 0 } {
+		puts $fileid "$key  : $value"
+	    }
+	}
+	
+	if {$fileid != "stdout" } {
+	    close $fileid
+	}
+    }
+    # --------------------------------------------------
+
+    proc SaveParameters { param headerline  } {
+	SaveParametersComplex $param $headerline ""
+    }
+
+    proc SaveParametersComplex { param headerline exclude } {
+	set fname [tk_getSaveFile -title "Filename" -defaultextension .log  -filetypes { {"Log files" {.log}}}]
+	if { [string length  $fname] < 1 } { return}
+	::pxtclutil::SaveArrayComplex $fname $param $headerline $exclude
+	return $fname
+    }
+    
+    proc SaveParametersList { param headerline paramlist } {
+	set fname [tk_getSaveFile -title "Filename" -defaultextension .log  -filetypes { {"Log files" {.log}}}]
+	if { [string length  $fname] < 1 } { return}
+	::pxtclutil::SaveArrayList $fname $param $headerline $paramlist
+	return $fname
+    }
+
+    # --------------------------------------------------
+    # Read Array from file including possible headerline
+    # --------------------------------------------------
+    proc ReadArray { fname varname2 headerline } {
+	
+	upvar #0 $varname2 varname
+	
+	
+	if { [string length $fname] < 1 } {
+	    return 0
+	}
+	
+	if { [ file exists $fname ]  == 0 } {
+	    return 0
+	}
+	
+	set fileid [open $fname r]
+	
+	# Eliminate Header 
+	
+	if { [ string length $headerline ] > 0 } {
+	    gets $fileid line
+	    if { [string compare $line $headerline] !=0 } {
+		::pxtclutil::Warning "Cannot read parameter file\n Desired = $headerline \n Actual = $line"
+		close $fileid
+		return 0 
+	    } else {
+		gets $fileid line
+	    }
+	}
+	
+	while { [ gets $fileid line ] >=0 } {
+	    set index [string first ":" $line]
+	    
+	    if { $index > 0 }  {
+		set len   [string length $line]
+		
+		set key   [string trim   [string range $line 0 [expr $index - 1]]]
+		set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		set varname($key)  $value 
+	    }
+	}  
+	close $fileid
+	return 1
+    }
+	
+    # --------------------------------------------------
+    proc ReadArrayList { fname varname2 headerline paramlist } {
+	
+	upvar #0 $varname2 varname
+	
+	
+	if { [string length $fname] < 1 } {
+	    return 0
+	}
+	
+	if { [ file exists $fname ]  == 0 } {
+	    return 0
+	}
+	
+	set fileid [open $fname r]
+	
+	# Eliminate Header 
+	
+	if { [ string length $headerline ] > 0 } {
+	    gets $fileid line
+	    if { [string compare $line $headerline] !=0 } {
+		::pxtclutil::Warning "Cannot read parameter file\n Desired = $headerline \n Actual = $line"
+		close $fileid
+		return  0
+	    } else {
+		gets $fileid line
+	    }
+	}
+	
+	while { [ gets $fileid line ] >=0 } {
+
+	    if { [ string  first "#" $line ] != 0 } {
+		set index [string first ":" $line]
+		
+		if { $index > 0 }  {
+		    set len   [string length $line]
+		    set key   [string trim   [string range $line 0 [expr $index - 1]]]
+		    set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		    
+		    if { [ lsearch -exact $paramlist $key ] >=0 } {
+			set varname($key)  $value 
+		    }
+		}
+	    } else {
+		puts stdout "Comment Line $line"
+	    }
+	}  
+	close $fileid
+	return 1
+    }
+	
+    # ---------------------------------------------------------------------------------
+    
+    proc LoadParameters { param headerline} {
+
+	set fname [tk_getOpenFile -title "Filename" -filetypes { {"Log files" {.log}}}]
+	if { [string length  $fname] < 1 } { return  }
+	
+	return [ ::pxtclutil::ReadArray $fname $param $headerline ]
+    }
+
+    proc LoadParametersList { param headerline paramlist} {
+
+	set fname [tk_getOpenFile -title "Filename" -filetypes { {"Log files" {.log}}}]
+	if { [string length  $fname] < 1 } { return  }
+	
+	::pxtclutil::ReadArrayList $fname $param $headerline $paramlist
+	return $fname
+    }
+
+
+    # ---------------------------------------------------------------------------------
+    #   Matrix Stuff
+    # ---------------------------------------------------------------------------------
+    proc SaveMatrix { matr { fname "" } } {
+
+	if { [string length  $fname] > 0 } {
+	    if [ catch { set fileid [open $fname w] } ] {
+		return 0
+	    }
+	} else {
+	    set fileid stdout
+	    puts stdout "Matrix Elements\n-------------\n"
+	}
+	    
+	for { set i 0 } { $i < 4 } { incr i } {
+	    for { set j 0 } { $j < 4 } { incr j } {
+		set key [$matr GetElement $i $j]
+		set line [ format "%6.3f " $key ]
+		puts -nonewline $fileid  "$line"
+	    }
+	    puts $fileid ""
+	}
+
+	if { $fileid != "stdout" } {
+	    close $fileid
+	}
+	return 1
+    }
+
+    proc LoadMatrix { matr fname } {
+	
+	if { [string length  $fname] < 1 } {  return 0 }
+	
+	if { [ file exists $fname ] == 0 } {
+	    return 0
+	}
+	set fileid [open $fname r]
+	
+	for { set i 0 } { $i < 4} { incr i } {
+	    set a [ gets $fileid line ]
+	    if { $a > 0 } { 
+		set row $line
+		if { [llength $row] == 4 } {
+		    for { set j 0 } {$j < 4} { incr j } {
+			$matr SetElement $i $j [lindex $row $j ]
+		    }
+		}
+	    }
+	}
+	close $fileid
+	return 1
+    }
+
+    # ---------------------------------------------------------------------------------
+    #   Export as JPEG Stuff
+    # ---------------------------------------------------------------------------------
+
+    proc ExportJPEGImage { fname img } {
+
+	set f $fname
+
+	if { $f == "" } { return }
+
+	set ok 0
+
+	set data [ [ $img  GetPointData ] GetScalars ]
+	$data Modified
+	set r0 [lindex [$data GetRange] 0]
+	set r1 [lindex [$data GetRange] 1]
+
+	set sc [ vtkImageShiftScale [ pxvtable::vnewobj ]]
+	$sc SetInput $img
+	$sc SetOutputScalarTypeToUnsignedChar 
+	$sc SetScale [ expr 255.0 / ($r1 - $r0 )]
+	$sc SetShift [ expr -1.0* $r0 ]
+	$sc Update
+
+	set data [ [ [ $sc GetOutput ]  GetPointData ] GetScalars ]
+	set r0 [lindex [$data GetRange] 0]
+	set r1 [lindex [$data GetRange] 1]
+
+	set tiffwriter [ vtkJPEGWriter [ pxvtable::vnewobj  ] ]
+	$tiffwriter DebugOn
+	$tiffwriter SetFileDimensionality 2
+	puts stderr "File Prefix [ file rootname $fname ]"
+	$tiffwriter SetFilePrefix [ file rootname $fname ]
+	$tiffwriter SetFilePattern "%s_%d.jpg"
+	$tiffwriter SetInput [ $sc GetOutput] 
+	$tiffwriter Write
+	catch { $tiffwriter Delete }
+	catch { $sc Delete }
+    }
+
+
+    #  ArrayEditor Stuff 
+    # ------------------------------------------
+
+        
+    proc CreateGlobalArrayEditor { arrayname comment loadcommand savecommand resetcommand } {
+
+	upvar #0 $arrayname varname
+
+	set top [ pxvtable::vnewobj]
+	set dlg [ toplevel .$top ]
+	wm withdraw $dlg
+
+	label $dlg.o -bg black -fg white -text $comment
+	pack $dlg.o -side top -expand t -fill x -pady 5
+	frame $dlg.bot  
+	pack $dlg.bot -side bottom -pady 15 -expand t -fill x
+
+
+	set keylist ""
+	foreach { key value } [array get varname] {
+	    set keylist [concat $keylist $key]
+	}
+	set keylist [lsort -ascii $keylist]
+	set len [  llength $keylist  ]
+	
+	for { set k 0 } { $k < $len } { incr k } {
+	    frame $dlg.$k ;
+	    pack $dlg.$k -side top -expand t -fill x
+	    set name [ lindex $keylist  $k ] 
+
+	    label $dlg.$k.l -text $name -width 20
+	    eval "entry $dlg.$k.e -textvariable ${arrayname}($name) -width 50"
+	    pack $dlg.$k.l $dlg.$k.e -side left -expand f -padx 10
+	}
+	
+	eval "button $dlg.bot.close -text Close -command { wm withdraw $dlg }"
+        eval "button $dlg.bot.load -text ReLoad -command { $loadcommand }"
+        eval "button $dlg.bot.save -text Save   -command { $savecommand }"
+        eval "button $dlg.bot.def -text Defaults   -command { $resetcommand }"
+	
+	pack $dlg.bot.load $dlg.bot.save $dlg.bot.def $dlg.bot.close -side left -expand t -padx 20 -fill x
+	return $dlg
+    }
+
+    proc GetIpAddress {} {
+	set ip 255.255.255.0
+        catch { set me [socket -server garbage_word -myaddr [info hostname] 0];set ip [lindex [fconfigure $me -sockname] 0];close $me; }
+	return $ip
+    }
+
+    proc GetAllInfo {} {
+	global tcl_platform
+	global tcl_version
+	global auto_path 
+
+	set m0 $tcl_platform(user)
+	set m1 $tcl_platform(os)
+	set m2 $tcl_platform(osVersion)
+	set m3 $tcl_version
+	set m24 [ info nameofexecutable ]
+
+	set m5 [ file normalize [ file join $::pxtclvtkpxcontrib::baselibrarypath  $::pxtclvtkpxcontrib::librarypath ] ]
+	set m5 "$m5, $::pxtclvtkpxcontrib::osmode "
+
+       	#puts stderr "m5=$m5"
+	set m4 ""
+    
+	catch { 
+	    set m4 "([ GetIpAddress ])"
+	}
+	return "User $m0 on [ info hostname ] $m4\n OS=$m1 ($m2)\n using $m24 $m3\nLibrary Directory=$m5"
+    }
+
+    proc ColorBox { inp_title inp_color inp_parent } {
+
+	for { set i 0 } { $i <=2 } { incr i } {
+	    set c($i) [ lindex $inp_color $i ]
+	    if { $c($i) < 0 } {
+		set c($i) 0.0
+	    } elseif { $c($i) > 1.0 } {
+		set c($i) 1.0
+	    }
+
+	    set c($i) [ expr round($c($i) *255.0) ]
+	}
+	
+	set line [ format "\#%02x%02x%02x"  $c(0) $c(1) $c(2) ]
+
+	set out [ tk_chooseColor -title $inp_title -initialcolor $line -parent $inp_parent ]
+	#	puts stdout "out color = $out"
+
+	if { [ string length $out ] > 0 } {
+	    set out_list ""
+
+	    for { set i 0 } { $i <=2 } { incr i } {
+		set m [ expr 2*$i +1  ]
+		set n [ expr $m + 1 ]
+		set t [ string range $out $m $n ]
+		scan $t "%x" t1
+		lappend out_list [ expr $t1/255.0 ]
+	    }
+	    return $out_list
+	} else {
+	    return $inp_color
+	}
+    }
+
+    proc FindCommandInPath { cmd } {
+
+	global tcl_platform
+	global env
+
+	set exename [ info nameofexecutable ]
+	if { [ string first cygwin $exename ] > 0 } {
+	    set cygwin 1
+	} else {
+	    set cygwin 0
+	}
+
+
+	if { $tcl_platform(platform) == "windows" && $cygwin == 0 } {
+	    set divider ";"
+	} else {
+	    set divider ":"
+	}
+	
+
+	set plist [ split $env(PATH) $divider ]
+	set ppath ""
+	set flag 0
+	set len [ llength $plist ]
+	set i 0
+	while { $i < $len && $flag == 0 } {
+	    set ppath [ lindex $plist $i ]
+	    set out   [ file join $ppath ${cmd} ]
+	    if { [ file exists $out ] == 1 } {
+		set flag 1
+		set i $len
+	    } else {
+		incr i
+	    }
+	}
+
+	if { $flag == 0 } {
+	    return 0
+	}
+	
+	return $out
+    }
+
+
+    proc GenerateVOIFileNameFromImageName { objectmapname } { 
+
+	set tname [ file rootname $objectmapname ]
+	set ff [ file extension $objectmapname ]
+	if { $ff == ".gz" } {
+	    set tname [ file rootname $tname ]
+	}
+	set tname "${tname}.txt"
+	return $tname
+    }
+
+    proc LoadVOINamesList { tname numc } {
+
+	if { $numc < 2 } {
+	    set numc 2 
+	} elseif { $numc > 255 } {
+	    set numc 255
+	}
+	
+	set tmpname(0) "Background"
+	for { set i 1 } { $i < $numc } { incr i } {
+	    set tmpname($i) "Region $i"
+	}
+	
+	puts stderr "Reading Names from $tname"
+
+	# Read Objectmap Colors
+	if { [ file exists $tname ] == 0 } {
+	    return  [ array get tmpname ]
+	}
+
+
+	set fileid [open $tname r]
+
+	# Eliminate Header 
+	set found 0
+	while { [ gets $fileid line ] >=0 } {
+	    #puts stderr "Testing line \"$line\""
+	    if { [  string range $line 0 0 ] == "\#" || [ string range $line 0 0 ] == "\[" } {
+		
+	    } else {
+		set index [string first ":" $line]
+		set lst ""
+		if { $index > 0 } {
+		    set lst [ split $line ":" ]
+		} else {
+		    set index [string first "\t" $line]
+		    if { $index > 0 } {
+			set lst [ split $line "\t" ]
+		    }
+		}
+		if { $lst != "" } {
+		    set index   [ string trim [ lindex $lst 0 ] ]
+		    set value   [ string trim [ lindex $lst 1 ] ]
+		    set tmpname($index) $value
+		}
+	    }
+	}
+	close $fileid
+    
+	return  [ array get tmpname ]
+    }
+
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/pxvtable.tcl b/bioimagesuite30_src/bioimagesuite/base/pxvtable.tcl
new file mode 100644
index 0000000..59c6094
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/pxvtable.tcl
@@ -0,0 +1,228 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# --------------------------------------------------------------------------------------
+# vtable packages a simple oop extension for tcl
+# 
+
+
+
+
+
+
+# provides commands
+#
+# to define a new class
+#
+#
+#
+#  namespace eval classname {
+#    
+#      pxvtable::initvlist
+#      ... this also defines a procedure called init which returns a unique object name
+#
+#      ... then define all procedures using pxvtable::vproc instead of proc
+#      ... in all procedures
+#      ... classname = package name
+#      ... if first argument == this then non static else static
+#      ...    thisparam is a special array of class parameters
+#      ...    thisname  is the reference to array for -variable, -textvariable situations
+#      ...                   i.e. entry -textvariable ${thisname}(text)
+#      ...
+#      ... at end if this is a derived class
+#      ...
+#      ...  pxvtable::appendvlist parentclassname
+#  }
+#
+#  Xenios Papademetris papad at noodle.med.yale.edu August  2001
+#
+# --------------------------------------------------------------------------------------
+package provide pxvtable 1.0
+
+# 	$Id: pxvtable.tcl,v 1.1 2002/02/20 18:07:50 Xenios Exp $	
+
+
+namespace eval pxvtable {
+
+
+    namespace export listvpackage getvariable getvariablename setvariable vproc vnewobj
+
+    variable counter
+
+    set counter 0
+
+
+    proc vnewobj { } {
+	variable counter
+	incr counter
+	return "pxtclobj$counter"
+    }
+
+    
+    proc vproc  { name arguments  args } {
+
+	set classname [ uplevel namespace current ]
+	uplevel lappend vlist $name
+	uplevel lappend vlist $classname
+	uplevel lappend vlist [ llength $arguments ]
+
+
+	if { [ lindex $arguments 0 ] == "this" } {
+	    set addition " set thisname \[::pxvtable::getthisname \$this pxtclobj \]; upvar #0 \$thisname thisparam; set classname $classname \n"
+	} else {
+	    set addition " set classname $classname\n"
+	}
+	set len [ string length $args ]
+	set oldbody  [ string range $args 1 [ expr $len -2 ] ]
+	set newbody "$addition  $oldbody"
+
+	uplevel proc $name [ list $arguments ] [ list $newbody ]
+    }
+
+    proc getthisname {widget varName} {
+	regsub -all {\.} $widget "_" base
+	
+	return "$varName$base"
+    }
+
+    proc initvlist {  } {
+	uplevel set vlist [ list "" ]
+	set realclassname [ uplevel namespace current ]
+	set realobj       [ uplevel pxvtable::vnewobj  ]
+	
+	#uplevel pxvtable::vproc init [ list [] ] [ list "return \[ pxvtable::vnewobj \]" ]
+
+	set add2 " set this \[ pxvtable::vnewobj \];"
+	set add3 " set thisname \[::pxvtable::getthisname \$this pxtclobj \]; upvar #0 \$thisname thisparam; set thisparam(realclassname) $realclassname;"
+	set add4 ""
+	#" puts stdout \" New \$thisparam(realclassname) object \$this \"; "
+	set add5 " return \$this "
+	set addition "$add2 $add3 $add4 $add5"
+	#puts stdout "Addition for $realclassname\n\t $addition\n"
+	uplevel pxvtable::vproc init [ list [] ] [ list $addition ]
+    }
+
+    proc listvpackage { packname } {
+	
+	upvar #0 ${packname}::vlist vlist
+	printvlist $vlist $packname
+    }
+
+    proc printvtable { } {
+	set basename [ uplevel namespace current ]
+	upvar  ${basename}::vlist vlist
+	printvlist $vlist $basename
+    }
+
+    proc printvlist { vlist basename } {
+
+	puts stdout "\nVirtual Table List for $basename "
+	puts stdout "-----------------------------------"
+	
+	set len [ llength $vlist ]
+	for { set k 0 } { $k < $len } { set k [ expr $k +3 ]} {
+	    set name [ lindex $vlist [ expr $k  ] ]
+	    set par  [  lindex $vlist [ expr $k + 1 ] ]
+	    set num  [  lindex $vlist [ expr $k + 2 ] ]
+	    puts stdout "${par}::${name} num=$num"
+	}
+	puts stdout "-----------------------------------\n";
+    }
+
+    proc appendvlist { other } {
+	
+	set basename [ uplevel namespace current ]
+	upvar  ${basename}::vlist vlist
+	upvar  ${other}::vlist otherlist
+
+	set len [ llength $otherlist ]
+	for {set k 0 } { $k < $len } { set k [ expr $k +3 ] } {
+	    set name [ lindex $otherlist $k ] 
+	    set index [ lsearch -exact $vlist $name ]
+	    if { $index == -1 } {
+		set par  [ lindex $otherlist [expr 1+$k]  ]
+		set num  [ lindex $otherlist [expr 2+$k] ]
+		lappend vlist $name
+		lappend vlist $par
+		lappend vlist $num
+		set oldarg [ oldarglist $num ]
+		set newarg [ newbody $name $par $num ]
+		uplevel proc $name [ list $oldarg ]   [list $newarg ]
+	    }
+	}
+    }
+    
+    proc oldarglist {  numargs } {
+	
+	set oldlist " "
+
+	for { set k 0 } { $k < $numargs } { incr k } {
+	    set oldlist "${oldlist}a$k "
+	}
+	
+	return  $oldlist 
+    }
+
+    proc newbody { name par numargs } {
+	
+	set oldlist " "
+
+	for { set k 0 } { $k < $numargs } { incr k } {
+	    set oldlist "${oldlist}\$a$k "
+	}
+	
+	return "return \[ ${par}::${name} $oldlist \] "
+    }
+
+    proc setvariable { object name value } {
+	set thisname [::pxvtable::getthisname $object pxtclobj ]; 
+	upvar #0 $thisname thisparam;
+	set thisparam($name) $value
+    }
+
+    proc getvariable { object name } {
+	set thisname [::pxvtable::getthisname $object pxtclobj ]; 
+	upvar #0 $thisname thisparam;
+	return $thisparam($name)
+	
+    }
+
+    proc getvariablename { object name } {
+	set thisname [::pxvtable::getthisname $object pxtclobj ]; 
+	return ${thisname}($name)
+	
+    }
+
+    proc vdeleteobj { object } {
+	
+	set thisname [::pxvtable::getthisname $object pxtclobj ]; 
+	upvar #0 $thisname thisparam;
+	array unset thisparam 
+    }
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/vtkImageInclude.tcl b/bioimagesuite30_src/bioimagesuite/base/vtkImageInclude.tcl
new file mode 100644
index 0000000..7d1f99c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/vtkImageInclude.tcl
@@ -0,0 +1,65 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide vtkImageInclude 1.0
+
+# 	$Id: vtkImageInclude.tcl,v 1.1 2002/02/20 18:07:50 Xenios Exp $	
+
+
+
+# This file derives from vthe VTK Source Tree
+
+
+set VTK_VOID            0
+set VTK_BIT             1 
+set VTK_CHAR            2
+set VTK_UNSIGNED_CHAR   3
+set VTK_SHORT           4
+set VTK_UNSIGNED_SHORT  5
+set VTK_INT             6
+set VTK_UNSIGNED_INT    7
+set VTK_LONG            8
+set VTK_UNSIGNED_LONG   9
+set VTK_FLOAT          10
+set VTK_DOUBLE         11 
+
+set VTK_IMAGE_X_AXIS             0
+set VTK_IMAGE_Y_AXIS             1
+set VTK_IMAGE_Z_AXIS             2
+
+set VTK_CLAW_NEAREST_NETWORK      0
+set VTK_CLAW_NEAREST_MINIMUM      1
+set VTK_CLAW_NEAREST_GLOBAL       2
+set VTK_CLAW_PIONEER_LOCAL        3
+set VTK_CLAW_PIONEER_GLOBAL       4
+set VTK_CLAW_WELL_NOISE           6
+set VTK_CLAW_WELL_DIRECTED_NOISE  7
+set VTK_CLAW_MINIMUM_WELL         8
+set VTK_CLAW_INSERT               9
+set VTK_CLAW_NARROW_WEL           10
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/vtknrcontrib.tcl b/bioimagesuite30_src/bioimagesuite/base/vtknrcontrib.tcl
new file mode 100644
index 0000000..538a213
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/vtknrcontrib.tcl
@@ -0,0 +1,41 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide vtknrcontrib 1.2
+
+# 	$Id: vtknrcontrib.tcl,v 1.1 2005/12/01 16:42:26 xenios Exp xenios $	
+
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [ file join [ file join [ file join  [ file dirname [ info script ]] .. ] extensions ] lib ]
+
+package require vtkpxcontrib 1.2
+
+# These libraries are loaded by default by vtkpxcontrib above
+#::pxtclvtkpxcontrib::LoadLibraries { vtknrCommonTCL  vtknrGraphicsTCL vtknrImagingTCL vtknrNmrlibTCL } 
+
diff --git a/bioimagesuite30_src/bioimagesuite/base/vtkpxcontrib.tcl b/bioimagesuite30_src/bioimagesuite/base/vtkpxcontrib.tcl
new file mode 100644
index 0000000..00043e3
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/base/vtkpxcontrib.tcl
@@ -0,0 +1,537 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide vtkpxcontrib 1.2
+package provide vtknrcontrib 1.2
+
+# 	$Id: vtkpxcontrib.tcl,v 1.2 2005/12/01 16:42:14 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [ file join [ file join [ file join  [ file dirname [ info script ]] .. ] extensions ] lib ]
+
+package require pxtclutil
+
+namespace eval ::pxtclvtkpxcontrib {
+
+    variable osmode       unix
+    variable libraryprefix     lib
+    variable librarysuffix     .so
+    variable librarypath       ""
+    variable staticsuffix      .a
+    variable execsuffix        ""
+    variable baselibrarypath [ file normalize [  file join [ file join [ file dirname [ info script ]] .. ] lib ] ]
+    variable  imagedir [ file normalize [ file join [ file join [ file dirname [ info script ]] .. ] images ] ]
+
+    variable vtkpxlibrarylist {   vtkpxCommonTCL vtkbisDatabaseTCL vtkpxGraphicsTCL  vtkpxLegacyTCL  vtkpxImagingTCL  vtkpxRegistrationTCL  vtkpxSegmentationTCL  }
+    variable vtkpxguilibrarylist { vtkpxGUITCL  vtkpxtklib Vtkpxtklib   }
+    variable debugmode 0
+
+
+
+    variable versionno   "3.01"
+    variable versiontag  "30"
+    variable versiondate "Mar 17th, 2011"
+    variable version  "BioImage Suite ${versionno} $versiondate"
+
+
+    variable yalelogo  0
+    variable logo      0  
+    variable smalllogo 0
+    variable fontname  0
+    variable betamode  0
+    variable bioimagesuiteicon ""
+
+    # -------------------------------------------------------------------------
+    # Initialize Logos
+    # -------------------------------------------------------------------------
+
+
+    proc CheckForUpdates { } {
+
+	variable betamode 
+
+	if { $betamode == 0 } {
+
+	    set ok "yes"
+	    catch { 	set ok [ tk_messageBox -title "Checking for Updates" -type yesno  -message "May BioImage Suite phone home (connect to www.bioimagesuite.org) to check for updates?\n(This involves downloading the file http://www.bioimagesuite.org/VERSION.txt)"  ] }
+	    if { $ok == "no" } {
+		return -1 
+	    }
+	    
+	    set ver 0
+	    catch {
+		set ver [http::data [http::geturl "http://www.bioimagesuite.org/VERSION.txt" ]]
+	    }
+	    if { $ver == 0 } {
+		catch { tk_messageBox -type ok -message "Connection to www.bioimagesuite.org failed\n" -title "Connection Error!" }
+		return -1
+	    }
+	    
+	    if { $ver != $::pxtclvtkpxcontrib::version } {
+		catch { tk_messageBox -type ok -title "For your information ..." -icon info -message "A Newer version is available:\n$ver\nYour current version is\n$::pxtclvtkpxcontrib::version" }
+		return 0
+	    } 
+	    catch { tk_messageBox -type ok -title "For your information ..." -icon info -message "Your Version of BioImage Suite is up to date\n($::pxtclvtkpxcontrib::version)" }
+	    return 1
+	} else {
+	    catch { tk_messageBox -type ok -title "For your information ..." -icon info -message "You are using a beta version of BioImage Suite (no updates available)\n($::pxtclvtkpxcontrib::version)" }
+	    return 1
+	}
+
+    }
+
+
+    
+    proc InitializeBioImageSuiteLogos { } {
+	variable yalelogo  
+	variable logo      
+	variable smalllogo 
+	variable fontname  
+	variable imagedir
+	variable betamode
+	variable bioimagesuiteicon 
+	global tcl_platform
+
+	catch {
+	    variable logo [ image create photo -file [ file join $imagedir  bioimagesuite_logo_www.gif ] ]
+	    variable smalllogo [ image create photo -file [ file join $imagedir bioimagesuite_logo_small_www.gif ] ]
+	    variable fontname { Helvetica 10 bold }
+	}
+
+	if { $tcl_platform(platform) == "windows" } { 
+	    set bioimagesuiteicon  [ file join $imagedir bioimagesuite.ico ]
+	} else {
+	    set bioimagesuiteicon  [ file join $imagedir bioimagesuite.xbm ]
+	}
+
+	if { $tcl_platform(platform) == "windows" } { 
+	    wm iconbitmap . -default $::pxtclvtkpxcontrib::bioimagesuiteicon 
+	} 
+
+    }
+
+    # -------------------------------------------------------------------------
+
+    proc CheckVisualStudioVersion { } {
+
+	variable libraryprefix
+	variable librarysuffix
+	variable baselibrarypath
+	variable librarypath
+	variable debugmode
+	variable osmode
+	variable vtkpxlibrarylist
+
+	set path3    [ file normalize $baselibrarypath ]
+	set libraryname [ lindex $vtkpxlibrarylist 0 ]
+	set libname1 [ file join $path3 "Release/${libraryprefix}${libraryname}${librarysuffix}" ]
+	set libname2 [ file join $path3 "Debug/${libraryprefix}${libraryname}${librarysuffix}" ]
+	set libname3 [ file join $path3 "${libraryprefix}${libraryname}${librarysuffix}" ]
+	set libname4 [ file join $path3 "lib${libraryname}${librarysuffix}" ]
+
+	set tm1 -2; catch { set tm1 [ file mtime $libname1 ] }
+	set tm2 -3; catch { set tm2 [ file mtime $libname2 ] }
+	set tm3 -1; catch { set tm3 [ file mtime $libname3 ] }
+	set tm4 -1; catch { set tm4 [ file mtime $libname4 ] }
+
+	if { $debugmode > 0 } {
+	    puts stderr "File Times:\n\t $libname1 ($tm1), $libname2 ($tm2), $libname3 ($tm3)\n\t $libname4 ($tm4)\n"
+	}
+
+	set domsys 0
+
+	if { $tm1 < 0 && $tm2 < 0 && $tm3 < 0 && $tm4 >= 0 } {
+	    set domsys 1
+	} elseif { $tm4 == -1 && ($tm1 >= 0 || $tm2 >= 0 || $tm3 >= 0 ) } {
+	    set domsys 0
+	}  else {
+	    global env
+	    set a ""
+	    catch { set a $env(MSYSTEM) }
+	    if { $a == "MINGW32" } {
+		set domsys 1
+	    }
+	}
+	 
+	# Returning ....
+	
+	set extra ""
+
+	if { $domsys == 1 } {
+	    # msys
+	    set libraryprefix "lib"
+	} elseif { $tm3 > $tm2 && $tm3 > $tm1 } {
+	    set extra ""
+	} elseif { $tm2 > $tm1 } {
+	    set extra "Debug"
+	} else {
+	    set extra "Release"
+	}
+	    
+		
+	if { $debugmode > 0 } {
+	    puts stdout "msys=$domsys, libraryprefix=*$libraryprefix*, extra=$extra"
+	}
+	return $extra
+    }
+
+
+    proc InitializePlatform { } {
+
+	global tcl_platform
+	variable osmode
+	variable libraryprefix
+	variable librarypath
+	variable librarysuffix
+	variable debugmode
+	variable staticsuffix
+	variable baselibrarypath
+	variable execsuffix
+
+	global env
+	catch {
+	    set bpath $env(BIOIMAGESUITE3_BINARY_DIR)
+	    if { $bpath != "" } {
+		set baselibrarypath [ file normalize [ file join $bpath "lib" ]]
+		eval { after 2000 puts stdout \"BioImage Suite::using baselibrarypath =$bpath\" }
+	    }
+	}
+
+
+	if { $tcl_platform(os) == "Darwin" } {
+	    if { [ file dirname [ info nameofexecutable ] ] == "/usr/local/vtk44_carbon_yale/bin" } {
+		set extraname "carbon"
+		set osmode  macos
+	    } else {
+		set osmode macosx11
+	    }
+	} elseif { $tcl_platform(platform) == "windows" } { 
+	    catch {
+		set exename [ info nameofexecutable ]
+		
+		if { [ string first cygwin $exename ] > 0 } {
+		    set osmode windowscygwin
+		}
+	    }
+	    
+	    if { $osmode != "windowscygwin" } {
+		set osmode windows
+	    }
+	    set execsuffix ".exe"
+	}
+
+	switch -exact -- $osmode { 
+	    "unix" {
+		set libraryprefix "lib"
+		set librarysuffix ".so"
+		set librarypath    ""
+	    }
+	    "windowscygwin" {
+		set libraryprefix "lib"
+		set librarysuffix ".dll" 
+		set librarypath "cygwin"
+	    }
+	    "windows" {
+		set libraryprefix ""
+		set librarysuffix ".dll" 
+		set staticsuffix  ".lib"
+		set librarypath [ CheckVisualStudioVersion ] 
+		# test release vs debug
+	    }
+	    "macos" {
+		set libraryprefix "lib"
+		set librarysuffix ".dylib"
+		set librarypath   "carbon"
+	    } 
+	    "macosx11" {
+		set libraryprefix "lib"
+		set librarysuffix ".dylib"
+		set librarypath   ""
+	    }
+	}
+
+    }
+
+
+    # -------------------------------------------------------------------------
+
+    proc LoadVTKLibraries { } {
+
+
+	global env
+	global tcl_platform	
+	global auto_path
+	variable debugmode
+
+	set fname [ string range [ file root [ file tail [ info nameofexecutable] ]] 0 2]
+	
+	if { $fname != "vtk"} {
+	    if { $tcl_platform(platform) == "windows"} {
+		set suffix ".exe"
+		set divider ";"
+	    } else {
+		set suffix ""
+		set divider ":"
+	    }
+	
+	    set newpath "[ file dirname [ info nameofexecutable ]]${divider}$env(PATH)"
+
+	    set plist [ split $newpath $divider ]
+	    set ppath ""
+	    set flag 0
+	    set len [ llength $plist ]
+	    set i 0
+	    while { $i < $len && $flag == 0 } {
+		set ppath [ lindex $plist $i ]
+		
+		if { [ file exists [ file join $ppath vtk$suffix ]] == 1 } {
+		    set flag 1
+		}
+		incr i
+	    }
+	    
+	    
+	    if { $flag == 1 } {
+		if { $tcl_platform(platform) == "windows"} {
+		    lappend auto_path [ file join $ppath "../Wrapping/Tcl" ]
+		}
+		lappend auto_path [ file join $ppath "../lib/vtk/tcl" ]
+
+		if { $fname == "tcl" } {
+		    catch {		   
+			package require vtkbase
+			package require vtkcommon
+			package require vtkfiltering
+			package require vtkgraphics
+			package require vtkhybrid
+			package require vtkimaging
+			package require vtkio
+			package require vtkparallel
+			package require vtkpatented
+			package require vtkrendering
+			package require infovis
+			package require volumerendering
+		    }
+		} else {
+		    package require vtk 
+		}
+	    } else {
+		tk_messageBox -type ok -message "Cannot find vtk.exe in your path!     [ info nameofexecutable ]" -title "Error!" -icon error
+		exit
+	    }
+	}
+    }
+
+    # -------------------------------------------------------------------------
+    proc LoadLibrary { libraryname initialcommand { dbmode 0 } } { 
+
+	variable libraryprefix
+	variable librarysuffix
+	variable baselibrarypath
+	variable librarypath
+	variable osmode
+
+	
+	set path    [ file join $baselibrarypath $librarypath ]
+	set libname [ file join $path "${libraryprefix}${libraryname}${librarysuffix}" ]
+
+	if { [ file exists $libname ] } {
+	    global env
+	    global tcl_platform	
+	    if { $tcl_platform(platform) == "windows"} {
+		if { [ lsearch -exact [ split $env(PATH) ";" ] [ file normalize $path ] ] == -1 } {
+		    set env(PATH) "$env(PATH);[ file normalize $path ]"
+		    set dbmode 1
+		    #		    puts stdout "Adding $path to PATH"
+		}
+	    } else { 
+		set envname "LD_LIBRARY_PATH"
+		if { $tcl_platform(os) != "Darwin" } {
+		    set envname DYLD_LIBRARY_PATH
+		}
+		
+		set ld ""
+		set ind -1
+		catch { 
+		    set ld $env($envname) 
+		    set ind [ lsearch -exact [ split $ld ":" ] [ file normalize $path ] ]
+		}
+
+		#		puts stdout "\n ++++++++++ ind=$ind ld=$ld"
+
+		if { $ld == "" } {
+		    set env($envname) [ file normalize $path ]
+		    set dbmode 1
+		    #  puts stdout "***************** Setting  $envname to $path, $env($envname)"
+		} elseif { $ind == -1 } {
+		    set env($envname) "$env($envname):[ file normalize $path ]"
+		    set dbmode 1
+		    #  puts stdout "Adding $path to $envname"
+		} 
+	    }
+
+
+	    if { $dbmode > 0 } {
+		eval { after 2000 puts stderr \"BioImage Suite::loading $osmode $libname\" }
+	    }
+	    
+	    if { $initialcommand == "" } {
+		return [ load $libname  ]
+	    } else {
+		return [ load $libname $initialcommand  ]
+	    }
+	} else {
+	    eval { after 2000 puts stderr \"$libname does not exist\" }
+	}
+	return 0
+    }
+
+    # -------------------------------------------------------------------------
+    proc ConditionalLoadLibrary { libraryname classname { dbmode 0 } } { 
+
+	variable libraryprefix
+	variable librarysuffix
+	variable baselibrarypath
+	variable librarypath
+	variable osmode
+	set dbmode 0
+	
+	set cl 0
+	catch { 
+	    set cl [ eval "$classname New" ]; 
+	    $cl Delete
+	    puts stdout "Library $libraryname exists"
+	    set cl 1
+	}
+
+	if { $cl == 1 } {
+	    if { $dbmode > 0 } {
+		puts stdout "Library $libraryname already loaded, class=$classname exists"
+	    }
+	    return 1
+	}
+
+	set path    [ file join $baselibrarypath $librarypath ]
+	set libname [ file join $path "${libraryprefix}${libraryname}${librarysuffix}" ]
+
+	if { [ file exists $libname ] } {
+	    
+	    if { $dbmode > 0 } {
+		puts  stdout "Loading $osmode $libname $dbmode"
+	    }
+	    return [ load $libname  ]
+	} else {
+	    puts stderr "$libname does not exist"
+	}
+	return 0
+    }
+    # -------------------------------------------------------------------------
+    proc LoadGUILibraries { librarylist } {
+
+	LoadLibrary [ lindex $librarylist 0 ] [ lindex $librarylist 1 ]
+    }
+
+    # -------------------------------------------------------------------------
+    proc LoadLibraries { librarylist } {
+
+	for { set i 0 } { $i < [ llength $librarylist ] } { incr i  } {
+	    LoadLibrary [ lindex $librarylist $i ] "" 0
+	}
+    }
+    # -------------------------------------------------------------------------
+    proc LoadAll { } {
+
+	variable vtkpxlibrarylist
+	variable vtkpxguilibrarylist
+	
+	global vtkpxcontrib_no_gui
+	LoadLibraries $vtkpxlibrarylist
+
+	set dogui 1
+
+	catch { 
+	    if { $vtkpxcontrib_no_gui == 1 } {
+		set dogui 0
+	    }
+	}
+
+	if { $dogui == 1 } {
+	    LoadGUILibraries $vtkpxguilibrarylist
+	}
+    }
+    # -------------------------------------------------------------------------
+}
+
+catch {
+    rename toplevel tk_toplevel
+}
+ 
+# A Safer toplevel command with icons and DELETE_WINDOW protocol by default
+
+proc toplevel { args } {
+    global tcl_platform
+    set ok [ eval "tk_toplevel $args" ]
+    if { $tcl_platform(platform) != "windows" } { 
+	wm iconbitmap $ok  @$::pxtclvtkpxcontrib::bioimagesuiteicon 
+    }
+    eval "wm protocol $ok WM_DELETE_WINDOW {  wm withdraw $ok }"
+    return $ok
+}
+
+#proc pxtkexit { } {
+#
+#    update idletasks
+#    destroy .
+#    exit
+#}
+
+
+
+set doload 1
+catch { 
+    if { $vtkpxcontrib_no_load == 1 } {
+	set doload 0
+    }
+}
+
+if { $doload == 1 } {
+    ::pxtclvtkpxcontrib::LoadVTKLibraries
+}
+
+::pxtclvtkpxcontrib::InitializePlatform
+::pxtclvtkpxcontrib::InitializeBioImageSuiteLogos
+ 
+if { $doload == 1 } {
+    ::pxtclvtkpxcontrib::LoadAll
+}
+
+
+
+
+unset doload
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/CMakeLists.txt b/bioimagesuite30_src/bioimagesuite/bis_algorithm/CMakeLists.txt
new file mode 100644
index 0000000..b85b7e8
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/CMakeLists.txt
@@ -0,0 +1,335 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+
+SET(KITSCRIPTS
+    pkgIndex.tcl
+    bis_common.tcl
+    bis_util.tcl
+    bis_object.tcl
+    bis_option.tcl
+    bis_optiondialog.tcl
+    bis_optiondialog.tcl
+    bis_algorithmdbaseinterface.tcl
+    bis_basealgorithm.tcl
+    bis_algorithm.tcl
+    bis_imagetoimagealgorithm.tcl
+    bis_imagetosurfacealgorithm.tcl
+    bis_basethresholdimage.tcl
+    bis_dualimagealgorithm.tcl
+    bis_dualimagetransformationalgorithm.tcl
+    bis_dualimagereslicetransformationalgorithm.tcl
+    bis_imageandsurfacetosurfacealgorithm.tcl
+    bis_surfacetosurfacealgorithm.tcl
+    bis_landmarkstolandmarksalgorithm.tcl
+    bis_baseintensityregistration.tcl
+    bis_basepointbasedregistration.tcl
+    bis_pointbasedregistrationviewer.tcl
+    bis_spectbase.tcl
+    bis_baselevelset.tcl
+    bis_graphvis.tcl
+    bis_guicontainer.tcl
+    bis_guiimageutility.tcl
+    bis_guisurfacecontrol.tcl
+    bis_guisurfaceutility.tcl
+    bis_guioverlayutility.tcl 
+    bis_guicompareutility.tcl 
+    bis_guirpmcontainer.tcl 
+    bis_guitreeimageutility.tcl
+    bis_guitreecreate4d.tcl
+    bis_datamanager.tcl
+    bis_treewidget.tcl
+    bis_viewer.tcl
+    bis_polygonaldisplaymanager.tcl
+    bis_xmlalgorithm.tcl
+    bis_electrodeeditor.tcl
+    bis_landmarkeditor.tcl
+    bis_imagelisttoimagealgorithm.tcl
+    bis_displayroimean.tcl
+    bis_basecontrolhelper.tcl
+)
+
+# These are the scripts that are to be tested
+
+SET(KITAPPSTEST
+#
+# fMRI Test Stuff
+#
+bis_multisubjectfmri.tcl
+bis_computetensor.tcl
+bis_tensoranalysis.tcl
+#
+bis_blendimage.tcl
+bis_castimage.tcl
+bis_csfwmmotioncorr.tcl
+bis_createoverlayimage.tcl
+bis_checkerboardimage.tcl
+bis_cleansurface.tcl
+bis_clipsurface.tcl
+bis_clusterthresholdimage.tcl
+bis_colorblendimage.tcl
+bis_combineframes.tcl
+bis_combineimages.tcl
+bis_combinetransformations.tcl
+bis_computedisplacementfield.tcl
+bis_computejointhistogram.tcl
+bis_computeglm.tcl
+bis_computenormals.tcl
+bis_computeoverlap.tcl
+bis_computesimilarity.tcl
+bis_connect.tcl
+bis_convolveimage.tcl
+bis_create4dimage.tcl
+bis_cropimage.tcl
+bis_curvatures.tcl
+bis_cylindricalcropimage.tcl
+bis_decimate.tcl
+bis_delaunay3D.tcl
+bis_distancemapimage.tcl
+bis_skeletonizeimage.tcl
+bis_edgedetectimage.tcl
+bis_extractobjectmap.tcl 
+bis_extractsurface.tcl
+bis_fdr.tcl
+bis_fftimage.tcl
+bis_flipimage.tcl
+bis_imagecompare.tcl
+bis_imagedilate.tcl
+bis_imagemathoperations.tcl
+bis_imagemedian.tcl
+bis_imageremoveframes.tcl
+bis_intsegment.tcl
+bis_linearintensityregister.tcl
+bis_linearpointregister.tcl
+bis_listthresholdimage.tcl
+bis_logimage.tcl
+bis_manualregistration.tcl
+bis_manualreslice.tcl
+bis_maskimage.tcl
+bis_matrixcorrelation.tcl
+bis_mediantemporalsmoothimage.tcl
+bis_nonlineardistortioncorrection.tcl
+bis_nonlinearintensityregister.tcl
+bis_nonlinearpointregister.tcl
+bis_nonlinearsmoothimage.tcl
+bis_piecewiseimagemap.tcl
+bis_preprocessimage.tcl
+bis_proportionalscale.tcl
+bis_qianvesselness.tcl
+bis_regularizeobjectmap.tcl
+bis_relabelimage.tcl
+bis_removeslicemean.tcl     
+bis_removetemporaldrift.tcl 
+bis_reorientimage.tcl
+bis_newreorientimage.tcl
+bis_resampleimage.tcl
+bis_resamplelandmarks.tcl
+bis_resliceimage.tcl
+bis_rfftimage.tcl
+bis_roimean.tcl
+bis_rtopvalue.tcl
+bis_rtotmap.tcl
+bis_seedcorrelation.tcl
+bis_shiftscaleimage.tcl
+bis_singlejacobian.tcl
+bis_singleimagemathoperations.tcl
+bis_sliceinhomogeneity.tcl
+bis_smoothimage.tcl
+bis_exponentialfitimage.tcl
+bis_exponentialfitt1.tcl
+bis_smoothlandmarks.tcl
+bis_smoothsurface.tcl
+bis_spectrf.tcl
+bis_stitchimage.tcl
+bis_stripskull.tcl
+bis_subdivide.tcl
+bis_temporalsmoothimage.tcl
+bis_thresholdimage.tcl
+bis_thresholdpoints.tcl
+bis_tmaptopvalue.tcl
+bis_tmaptozscore.tcl
+bis_transformsurface.tcl
+bis_triangulate.tcl
+bis_ttest.tcl
+bis_visualizetransformation.tcl
+bis_zscoretopvalue.tcl
+bis_ISAS.tcl
+bis_ISASHN.tcl
+#
+bis_singlesubjectfmri.tcl
+bis_frangivesselness.tcl
+bis_computecorrelations.tcl
+bis_biasfield.tcl
+bis_levelset.tcl
+bis_interleave.tcl
+bis_reslicetensor.tcl
+#
+bis_intrinsicconnectivity.tcl
+bis_fmritoolbox.tcl
+
+)
+
+SET(KITLIBS
+  vtkpxCommon
+  vtkpxCommonTCL
+  numerics
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+)
+
+# Excluded TCL Code 
+
+IF(BIOIMAGESUITE3_MOUSEREG)
+SET(KITAPPSTEST
+${KITAPPSTEST}
+bis_serialdemonmousereg.tcl
+)
+ENDIF(BIOIMAGESUITE3_MOUSEREG)
+
+
+
+SET (KITAPPS
+${KITAPPSTEST}
+bis_testviewer.tcl
+bis_testmatrix.tcl
+bis_testdatabase.tcl
+# Add applications that have no tests
+bis_treeapp.tcl
+bis_headerinfo.tcl
+bis_makebatch.tcl
+bis_split4dimage.tcl
+bis_help.tcl
+bis_surfaceinfo.tcl
+bis_dicom2nifti.tcl
+bis_varian2nifti.tcl
+#
+# These ought to have tests but do not
+#
+# bis_serialdemonmousereg.tcl
+#
+)
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+bis_complex_tcl(bioimagesuite/bis_algorithm ${FILELIST2} ${FILELIST})
+
+
+
+# ---------------------------------------------------------------------------------------------------------------------
+# Create scripts and help files
+# ---------------------------------------------------------------------------------------------------------------------
+# --------------------------------------------------------------------------------------
+# Create Wrapper Scripts 
+# --------------------------------------------------------------------------------------
+
+SET (BASEDIR ${CMAKE_INSTALL_PREFIX}/${BIOIMAGESUITE3_INSTALL_EXTRAPATH})
+SET (TMPBINDIR ${BIOIMAGESUITE3_BINARY_DIR}/bioimagesuite/bis_algorithm)
+SET (DOSH 0)
+SET (SHSUFFIX "")
+
+IF (UNIX)
+  SET (DOSH 1)
+ 
+ELSEIF (BIOIMAGESUITE_USING_MINGW)
+  SET (DOSH 1)
+  SET (SHSUFFIX ".sh")
+ENDIF (UNIX)
+
+
+# ---------------------------------------------------------
+# Create a list of scripts
+SET (F33 ${BIOIMAGESUITE3_BINARY_DIR}/bisalgorithmscriptlist.txt)
+FILE (WRITE ${F33} "#List of scripts\n")
+FOREACH (item ${KITAPPS})
+  GET_FILENAME_COMPONENT(TAIL ${item} NAME_WE)
+  FILE (APPEND ${F33} "${TAIL}\n")
+ENDFOREACH (item ${KITAPPS})
+install(FILES ${F33} DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/lib)
+
+# ---------------------------------------------------------
+#MESSAGE("USING DOSH=${DOSH}")
+
+IF (DOSH)
+  FOREACH (item2 ${KITAPPS})
+
+    GET_FILENAME_COMPONENT(item ${item2} NAME_WE)
+    set(item3 ${item}${SHSUFFIX})
+    
+    configure_file( ${BIOIMAGESUITE3_SOURCE_DIR}/bioimagesuite/origscripts/runscript.in
+      ${EXECUTABLE_OUTPUT_PATH}/${item3} @ONLY )
+
+    EXECUTE_PROCESS (COMMAND chmod +x  ${EXECUTABLE_OUTPUT_PATH}/${item3})
+    
+    install(FILES ${EXECUTABLE_OUTPUT_PATH}/${item3}  DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/bin
+      PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE WORLD_READ WORLD_EXECUTE )
+    FILE(APPEND ${SCRIPTFILELIST} "bin/${item}\n")
+  ENDFOREACH (item2 ${KITAPPS})
+ENDIF (DOSH)
+  
+IF (WIN32)
+  FOREACH (item2 ${KITAPPS})
+
+    GET_FILENAME_COMPONENT(item ${item2} NAME_WE)
+    set(item3 ${item}.bat)
+
+    configure_file( ${BIOIMAGESUITE3_SOURCE_DIR}/bioimagesuite/origscripts/runscript.bat.in
+         ${EXECUTABLE_OUTPUT_PATH}/${item3} @ONLY )
+  
+    install(FILES ${EXECUTABLE_OUTPUT_PATH}/${item3}  DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/bin
+      PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE WORLD_READ WORLD_EXECUTE )
+    FILE(APPEND ${SCRIPTFILELIST} "bin/${item3}\n")
+  ENDFOREACH (item2 ${KITAPPS})
+ENDIF(WIN32)
+
+add_custom_command(OUTPUT
+  ${BIOIMAGESUITE3_BINARY_DIR}/html/index.html
+  DEPENDS ${KITAPPSTEST} vtkbisConnectivityTCL vtkpxGUITCL
+  POST_BUILD
+  COMMENT     "Creating HTML Help Pages"
+  COMMAND 
+  ${BIOIMAGESUITE3_BINARY_DIR}/bisexec ${BIOIMAGESUITE3_SOURCE_DIR}/bioimagesuite/bis_algorithm/bis_help.tcl ${BIOIMAGESUITE3_BINARY_DIR}/bisalgorithmscriptlist.txt ${BIOIMAGESUITE3_BINARY_DIR}/html)
+
+
+add_custom_target(bis_help 
+  DEPENDS  ${BIOIMAGESUITE3_BINARY_DIR}/html/index.html 
+)
+
+install (DIRECTORY ${BIOIMAGESUITE3_BINARY_DIR}/html DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH})
+
+
+# ---------------------------------------------------------------------------------------------------------------------
+# Testing Stuff -- exclude from release
+# ---------------------------------------------------------------------------------------------------------------------
+# Excluded TCL Code 
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_ISAS.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_ISAS.tcl
new file mode 100755
index 0000000..4a31b00
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_ISAS.tcl
@@ -0,0 +1,136 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_ISAS 1.0
+package require bis_spectbase 1.0
+
+
+itcl::class bis_ISAS {
+
+    inherit bis_spectbase
+
+    constructor { } {	 
+	
+	set inputs { 
+	    { meanimage  "Mean Spect Image (Optional)"                  pxitclimage  "" 400 } 
+	}
+
+	set description2 "The basic idea of ISAS is to compute the difference between an ictal and interictal SPECT scan for a single patient. The differences of the ictal/inter-ictal comparison are checked against a healthy normal database to determine the normal expected variation. Significant increases and decreases in CBF (cerebral blood flow) between the interictal and ictal SPECT can then be detected to predict seizure localization. All inputs to this algorithm are expected to be registre [...]
+	
+	$this InitializeBaseSpect 
+    }
+
+    public method Execute    { }
+    public method GetGUIName { } { return "ISAS" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_ISAS::Execute {  } {
+
+    PrintDebug "bis_ISAS::Execute"
+        
+    set inp1  [ GetInput ]
+    set inp2  [ GetSecondInput ]
+    set doMask [ $OptionsArray(usemask)   GetValue ]
+
+    set std 0
+    if { [ $InputsArray(stdimage) IsFileNameTheDefault ] } { 
+	set std [ $this loadImage ISAS_Standard_Deviation.nii.gz ] 
+    } else { 
+	catch { set std [ $InputsArray(stdimage) GetObject ] }
+    } 
+    if { $std == 0 } { return 0 }
+
+    set mean 0
+    if { [ $InputsArray(meanimage) IsFileNameTheDefault ] } { 
+	set mean  [ $this loadImage ISAS_Mean_Diff_SPECT.nii.gz ] 
+    } else { 
+	catch { set mean [ $InputsArray(meanimage) GetObject ] }
+    } 
+    if { $mean == 0 } { return 0 }
+
+    set inter [ $this cast $inp1 Float ]
+    set ictal [ $this cast $inp2 Float ]
+    
+    if { $doMask } { 
+
+	set mask 0
+	if { [ $InputsArray(maskimage) IsFileNameTheDefault ] } { 
+	    set mask  [ $this loadImage ISAS_SPECT_Mask.nii.gz ]
+	} else { 
+	    catch { set mask [ $InputsArray(maskimage) GetObject ] }
+	} 
+	if { $mask == 0 } { return 0 }
+    
+	set inter [ $this mathops $inter $mask Multiply ]
+	set ictal [ $this mathops $ictal $mask Multiply ]
+    }
+
+    set inter_sm [ $this smooth $inter ]
+    set ictal_sm [ $this smooth $ictal ]
+
+    set inter_pr [ $this propScale $inter_sm ]
+    set ictal_pr [ $this propScale $ictal_sm ]
+
+    set mask2 [ createBrainMask $inter_pr $ictal_pr $std ]
+
+    set inter_pre [ $this mathops $inter_pr $mask2 Multiply ]
+    set ictal_pre [ $this mathops $ictal_pr $mask2 Multiply ]
+    set mean_msk  [ $this mathops $mean     $mask2 Multiply ]
+    set std_msk   [ $this mathops $std      $mask2 Multiply ]
+
+    set tmap [ createTmap $ictal_pre $inter_pre $std_msk $mean_msk ]    
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $tmap GetObject ]
+    $outimage CopyImageHeader [ $std GetImageHeader ]
+
+    delete $inter_sm $ictal_sm $inter_pre $ictal_pre $inter_pr $ictal_pr $mean $mean_msk $std $std_msk
+    if { $doMask } { itcl::delete object $mask } 
+
+    return 1
+}
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_ISAS [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_ISASHN.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_ISASHN.tcl
new file mode 100755
index 0000000..8a2a470
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_ISASHN.tcl
@@ -0,0 +1,130 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_ISASHN 1.0
+package require bis_spectbase 1.0
+
+
+itcl::class bis_ISASHN {
+
+    inherit bis_spectbase
+
+    constructor { } { set inputs [ list ] ;
+	
+	set description2 "The basic idea of ISASHN is to compute the difference between an ictal and interictal \
+SPECT scan for a single patient. The differences of the ictal/inter-ictal comparison are checked against a \
+healthy normal database to determine the normal expected variation. Significant increases and decreases in CBF \
+(cerebral blood flow) between the interictal and ictal SPECT can then be detected to predict seizure localization. \
+    All inputs to this algorithm are expected to be registred to the 2mm MNI brain. The user specify the interictal \
+    spect as input one and the ictal spect as input two. If the user want to use a custom healthy control poplation, \
+    the user can optionally specify a standard deviation spect, and/or a brain mask. Otherwise these image are \
+    automaically set to the ISAS health normal database. The user can also specifiy the smoothing kernal use in the \
+    algorithm. The default value is 16mm FWHM. See Scheinost et. al 2009 ISBI "
+
+	$this InitializeBaseSpect  }
+
+    public method Execute    { }
+    public method GetGUIName { } { return "Diff SPECT with ISASHN" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_ISASHN::Execute {  } {
+
+    PrintDebug "bis_ISASHN::Execute"
+
+    set inp1  [ GetInput ]
+    set inp2  [ GetSecondInput ]
+    set doMask [ $OptionsArray(usemask)   GetValue ]
+
+    set std 0
+    if { [ $InputsArray(stdimage) IsFileNameTheDefault ] } { 
+	set std [ $this loadImage ISAS_Standard_Deviation.nii.gz ] 
+    } else { 
+	catch { set std [ $InputsArray(stdimage) GetObject ] }
+    } 
+    if { $std == 0 } { return 0 }
+
+    set inter [ $this cast $inp1 Float ]
+    set ictal [ $this cast $inp2 Float ]
+
+    if { $doMask } { 
+
+	set mask 0
+	if { [ $InputsArray(maskimage) IsFileNameTheDefault ] } { 
+	    set mask  [ $this loadImage ISAS_SPECT_Mask.nii.gz ]
+	} else { 
+	    catch { set mask [ $InputsArray(maskimage) GetObject ] }
+	} 
+	if { $mask == 0 } { return 0 }
+
+	set inter [ $this mathops $inter $mask Multiply ]
+	set ictal [ $this mathops $ictal $mask Multiply ]
+    }
+
+    set inter_sm [ smooth $inter ]
+    set ictal_sm [ smooth $ictal ]
+
+    set inter_pr [ propScale $inter_sm ]
+    set ictal_pr [ propScale $ictal_sm ]
+
+    set mask2 [ createBrainMask $inter_pr $ictal_pr $std ] 
+
+    set inter_pre [ $this mathops $inter_pr $mask2 Multiply ]
+    set ictal_pre [ $this mathops $ictal_pr $mask2 Multiply ]
+    set std_msk   [ $this mathops $std      $mask2 Multiply ]
+
+    set tmap [ createTmap $ictal_pre $inter_pre $std_msk ] 
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $tmap GetObject ]
+    $outimage CopyImageHeader  [ $std GetImageHeader ]
+
+    delete $inter_sm $ictal_sm $inter_pre $ictal_pre $inter_pr $ictal_pr $std $std_msk
+    if { $doMask } { itcl::delete object $mask } 
+
+    return 1
+}
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [ bis_ISASHN [ pxvtable::vnewobj ] ]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_algorithm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_algorithm.tcl
new file mode 100644
index 0000000..96f44f4
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_algorithm.tcl
@@ -0,0 +1,2877 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_algorithm 1.0
+
+#
+# bis_algorithm.tcl
+# 
+#  Do we want to add
+#
+#  bis_optionslist class
+#  bis_objectlist  class
+#
+#
+
+package require  Itcl 3.2
+#package require  biscmdline
+
+package require bis_option 1.0
+package require bis_object 1.0
+package require bis_common 1.0
+
+package require bis_basealgorithm 1.0
+package require bis_algorithmdbaseinterface 1.0
+
+package require Iwidgets 
+package require feedbackplus 1.0
+package require pxitclobject 1.0
+package require pxtclhelp 1.0
+package require  labelframe 1.0
+package require bis_viewer 1.0
+#
+# bis_algorithm class
+#
+
+itcl::class bis_algorithm {
+
+    inherit bis_basealgorithm
+
+    #
+    #public
+    #
+    constructor { } { set progressbar($this)  0 }
+
+    # --------------------------------------------------------------------
+    #  Methods to ovverride 
+    # --------------------------------------------------------------------
+
+    # This is the entry point method where the algorithm execution is
+    # --------------------------------------------------------------------
+    public method  Execute { } {
+	puts stdout "Nothing to run .. .this is bis_algorithm "
+    }
+
+    # ------------------------------------------------------------------
+    # This method is used to create dialog title bars etc.
+    public method GetGUIName    { } { return $scriptname }
+
+    # This needs to be redefined by those algorithms  (e.g. surfacetosurface)
+    # which need a data control in standalone mode
+    public method NeedsCustomDataControl { } { return 0 }
+    public method CreateCustomDataControl { w } { return 0 }
+
+
+    # Check Input Objects before execution -- i.e. ensure images exist etc
+    # -------------------------------------------------------------------
+    public method CheckInputObjects { } { return 1 }
+
+
+    # -------------------------------------------------------------------
+    # This methods is called by UpdateProgress events on filters properly
+    # configured -- using the SetFilterCallbacks method
+    # -------------------------------------------------------------------
+    public method ProgressCallback   { filter lab } 
+
+
+    # -------------------------------------------------------------------
+    # GUI Stuff -- pack options is probably the first one to look at 
+    # -------------------------------------------------------------------
+
+    # Create Input/Output GUI Controls for Objects in standalone mode
+    public method CreateGUI { parent { callafter 0 } { callbefore 0 } { testingmode 0 } }
+    public method SetMainTabNotebook { nt  } {  set maintabnotebook $nt }
+    public method SetMainTabScrollMode { md  } {  set maintabscrollmode $md }
+
+
+    public method GetBaseWidget { } { return $basewidget }
+    public method GetViewerBaseWidget { } { return $viewerbasewidget }
+    public method GetGUIBaseWidget { } { return $guibasewidget }
+    public method GetParameterBar { } { return $parameterbar }
+
+    protected method CreateStandaloneGUI { { testingmode 0  } }
+    protected method CreateManagedGUI { }
+    protected method CreateDataTreeGUI { }
+
+    
+    # Componet GUIs
+    protected method CreateInputGUIInterface { fr }
+    protected method CreateOutputGUIInterface { fr }
+    protected method CreateOptionsGUIInterface { fr }
+    protected method PackOptionsGUIInterface { lst }
+    protected method ConfigureOptionsGUICallbacks { } { return 0 }
+
+
+
+    # Create applet superstructure -- perhaps this needs to move out
+    # --------------------------------------------------------------
+    protected method CreateMenuBar { fr }
+    protected method CreateViewer { fr }
+    public method SetViewer { vtk_vr }
+    public method SetBisViewer { bis_vr }
+
+
+
+    # This method is used to initialize from the GUI from a container
+    public method InitializeFromContainer { container { eventcontainer 0 } }
+
+    # This method is used to initialize for a standalone GUI Application
+    public method InitializeStandalone { }
+    public method InitializeTesting    { { dogui 0 } }
+
+    # This is called from each derived class's main function
+    public method  RunCommandLine { parameterlist commandline }
+
+    # This is function for running ctest with associated help functions
+    public method RunRegressionTests { fname args }
+    # This reads the custom filename containing all tests
+    protected method LoadTestFileName { fname { lineno -1 } }
+    protected method DualPrint { line { fout 0 } { usescriptname 1 } }
+    protected method ReformatTestLine { line { extra "" } }
+    protected method DoTestComparison { alg comparenames { fout 0  }  { ctestcreategold 0 } }
+    protected method DoTestGUIComparison { alg comparenames { fout 0  }  { ctestcreategold 0 } }
+    protected method RunTest { testline basedir { fout 0  } { extra ""} { ctestcreategold 0 } }
+    protected method CreateTempOutputDirectory { inp }
+    protected method RemoveTempOutputDirectory { tmp }
+
+
+    # This method is used to pass arguments as strings
+    public method  SetParameterList { parameterlist }
+
+    # This is the Main Function for all scripts
+    public method MainFunction {  }
+
+    # Command line processing
+    protected method StripDashes { ln }
+    protected method ProcessCommandline { argv { debug 0 } }
+
+    #Internal flags as to whether some gui element objects exist
+    protected variable hasinputguis  0 
+    protected variable hasoutputguis 0 
+
+    
+    #Add Default Options -- these are for GUI related issues
+    protected method AddDefaultOptions { {addgui 1 } }
+
+
+    # GUI Stuff
+    # 
+    # GUI Mode should be one of managed, standalone, commandline (other maps to commandline)
+    public method  SetGUIMode { md }
+    public method  GetGUIMode { } { return  $guimode   }
+    public method  GetViewer  { } 
+    public method  GetBisViewer  { } 
+    public method  GetBisViewerImage  { { magnification 1 } } 
+
+
+
+    # Show Outputs in GUI even if managed
+    protected variable showoutputsmode 0
+    public method  SetShowOutputsMode { md } { set showoutputsmode [ expr $md > 0 ]}
+    public method  GetShowOutputsMode { } { return  $showoutputsmode   }
+
+    # Get Info about Algorithm for use in GUI Container
+    public method IsImageToImage { }
+    public method SetContainer { cont }  { set containerobject $cont }
+    public method GetContainer { }  { return $containerobject }
+    public method SetDataTree { cont }  { set datatree $cont ; $this SetGUIMode datatree }
+    public method GetDataTree { }  { return $datatree }
+    public method UpdateInputsFromContainer { } { return 0 }
+    public method UpdateContainerWithOutput { } { return 0 }
+
+
+
+    # These methods may not to be changed in derived classes
+    public method GetFirstInputObject  { }
+    public method GetSecondInputObject  { }
+    public method GetThirdInputObject { }
+    public method GetFourthInputObject { } 
+
+    public method GetFirstOutputObject { }
+    public method GetOutputObjectByIndex { { index 0 } }
+    public method GetOutputObjectNameByIndex { { index 0 }}
+
+    
+    # Invokation Stuff
+    public method InvokeAlgorithmFromGUI { }
+    public method ShowCommandLine { }
+    public method GetCommandLine { { mode short } }
+    public method GetSlicerXMLDescription { }
+    public method GetJSONDescription { }
+    public method GetJSONParameters { mode }
+    public method GetJSONInputs { }
+    public method GetJSONOutputs { }
+
+    public method GetLONIXMLDescription { { mode 1 } }
+    public method ShowLongDescription { }
+
+    
+
+    protected variable executename "Run Algorithm"
+    protected variable callbackafter 0
+    protected variable callbackbefore 0
+    protected common thisparam
+    protected variable aboutdialog 0
+    protected variable helpdialog 0
+    protected variable basewidget 0
+    protected variable viewerbasewidget 0
+    protected variable guibasewidget 0
+    protected variable parameterbar 0
+    protected variable vtk_viewer 0
+    protected variable bis_viewer 0
+    protected variable bis_viewer_type ortho
+    protected variable bis_viewer_edit 1
+    protected variable maintabnotebook 0
+    protected variable createviewermode 1
+    protected common   dbaseinterface 0
+    protected variable datatree 0
+    protected variable forceguimode 0
+    protected variable maintabscrollmode 1
+
+    # More GUI Stuff -- Progress Bar
+    public method CreateProgressBar { w } 
+    public method ShowProgress       { filter lab } 
+    public method ShowProgressVal    { name   val }
+    public method SetFilterCallbacks { filter comment } 
+
+    # Dbase Module
+    protected method PrintMessage { msg } 
+    protected method ErrorMessage { msg { titlemessage "Error Message" } }
+    public    method SetParametersFromString { line }
+    protected method HandleParameterSetArgument { plist } 
+
+    public method ResetParameters { }
+    public method LoadParameters { {fname "" }}
+    public method SaveParameters { {fname "" }}
+    public method QueryParameters { psetname }
+    protected method CreateDatabaseConnector {  }
+    public method ShowDatabaseGUI { mode }
+
+
+
+    # Method to add logo label to something 
+    public proc   AddLogoLabel { w }
+    public method ExitCommand { }
+    public method AboutCommand { }
+    public method HelpCommand { }
+    public method SetCurrentDirectory { { newdir ""  } }
+    public method WatchOn { } 
+    public method WatchOff { } 
+
+    # Enable/Disable pieces of the User Interface
+    public proc   DisableWidget { widget  }
+    public proc   DisableUI     { widgetlist }
+    public proc   EnableWidget { widget }
+    public proc   EnableUI     { widgetlist  }
+    public proc   SetStateOfWidget { widget mode }
+    public proc   SetStateOfUI     { widgetlist mode  }
+
+    # Configure Whole Trees
+    public proc   ConfigureWidgetTree { widget optionlist }
+    public proc   SetWidgetTreeColors { widget backc forec }
+
+
+
+    # Common Variables
+    public    variable version 3.0a
+    public    variable aboutstring "(c) X. Papademetris, M. Jackowski, D. Scheinost, A.Joshi, H.Okuda, R.T. Constable, L.H. Staib 1995-2011\nSection of Bioimaging Sciences, Department of Diagnostic Radiology, Yale University School of Medicine\n\n\nThis application is intended for research applications only! Use at your OWN RISK. If used for publication please acknowledge, see the webpage for more details. For additional support please visit the BioImage Suite forum at:\n\thttp://researc [...]
+
+    
+    # Variables attached to progress bar
+    private common progressbar 
+    private common progress_lab 
+    private common progress_val 
+    protected variable progress_status -1
+
+    # --- end method def -----
+    protected common ignoreflag { dogui pset ctest ctestgui ctestline ctestcreategold ctestexact ctestthr ctestsave ctestdebug ctesttmpdir slicermode }
+    protected common ignoreflagslicer { pset ctest ctestgui ctestline ctestcreategold ctestexact ctestthr ctestsave ctestdebug ctesttmpdir loni }
+    protected common ctestextraflags {  ctestexact ctestthr ctestsave ctesttmpdir }
+
+
+}
+
+
+#----------------------------------------------------
+# GUI Stuff
+#----------------------------------------------------
+itcl::body bis_algorithm::AddDefaultOptions { { addgui 1 } } {
+
+    if { $addgui == 1 } {
+
+	lappend options [ list dogui "Enable the creation of a graphical user interface" "dogui"   boolean     0 { 0 1 }  -10002 ]
+	lappend options [ list pset  "Use Parameter set to set parameters" "pset"   string  "" "" -10000 ]
+	lappend options [ list slicermode "This signifies that the algorithm is being invoked by Slicer. It affects default save formats."  "slicermode" boolean 0 { 0 1 }  -10020 ]
+	if { $forceguimode == 0 } {
+	    lappend options [ list loni "Create xml output  for loni pipeline and exit (1=module group,2=module)"  "loni" integer 0 { 0 2 }  -10021 ]
+	    lappend options [ list ctest "Enable the running of ctest automated testing. If argument is specified then the script is invoked in test mode and using the argument as the text file containing the test definitions"  "ctest" { filename readfile } 0 { }  -10003 ]
+
+	    lappend options [ list ctestline "(Use only in software testing mode) If set to a positive integer then the only test that is run corresponds to the appropriate line in the testfile"  "Test LineNo:" integer -1 { -1 9999} -11001 ]
+	    lappend options [ list ctestsave "(Use only in software testing mode) If enabled then save results of computation otherwise discard after testing is performed"  "Save Test Results" boolean 0 { 0 1 }  -11002 ]
+	    lappend options [ list ctesttmpdir "(Use only in software testing mode) Output directory to save temporary output testing files, if not set default filenames are generated from the input filenames"  "Debug Directory" { filename directory } "" {  } -11003 ]
+	    lappend options [ list ctestexact "(Use only in software testing mode) If enabled then comparison is done via subtraction else correlation (images) or correspondence error (surfaces) is used"  "Exact Test" boolean 1 { 0 1 }  -11004 ]
+	    lappend options [ list ctestthr   "(Use only in software testing mode) Threshold for subtraction or correlation" "Test Threshold" real 0.002 { 0 100000 }  -11005 ]
+	    lappend options [ list ctestdebug "(Use only in software testing mode) If set to non empty then a textfile is created with debug output"  "Debug Filename" { filename writefile } "" { text { .txt } } -11006 ]
+
+	    lappend options [ list ctestcreategold "(Use only in software testing mode) If set to 9999 then the test saves its result as a gold standard. Use with extreme care"  "Test LineNo:" integer 0 { 0 9999} -11007 ]
+	    lappend options [ list ctestgui "(Use only in software testing mode) If set to 1 then the testing is done in GUI mode and the comparison is based on the viewer output"  "Test GUI:" integer 0 { 0 1} -11008 ]
+	}
+    }
+    $this CreateOptionsArray
+}
+
+# --------------------------------------------------
+# Set GUI Mode
+# --------------------------------------------------
+
+itcl::body bis_algorithm::SetGUIMode { md } {
+
+    set guimode "commandline"
+
+    switch $md { 
+	"managed"        { set guimode "managed" }
+	"standalone"     { set guimode "standalone" }
+	"datatree"       {  set guimode "datatree" }
+    }
+}
+
+
+
+#----------------------------------------------------
+# This is called from each derived class's main function
+#----------------------------------------------------
+itcl::body bis_algorithm::RunCommandLine { parameterlist commandline } {
+    
+    $this SetGUIMode commandline
+    set ret [ $this CreateVTKObjects ]
+    set ret [ $this SetArguments $parameterlist $commandline ]
+
+    if { $ret == 1 } {	set ret [ $this LoadObjects ] }
+    if { $ret == 1 } {  set ret [ $this CheckInputObjects ] }
+    if { $ret == 1 } {	set ret [ $this Execute ]     }
+    if { $ret == 1 } {  set ret [ $this SaveObjects ] } 
+    if { $ret == 0 }  {  
+	PrintUsage; puts stderr "\n\n------------------------------------------------------\nTHE FOLLOWING ERROR HAS OCCURRED:\n\t $errormessage\n"  
+    }  else {
+	puts stdout "\n $resultmessage"
+    }
+    $this CleanAll
+}
+
+
+# -------------------------------------------------------------------------------------------
+#  
+#    Application level GUI Functionality
+#
+# -------------------------------------------------------------------------------------------
+
+::itcl::body bis_algorithm::SetStateOfWidget { widget state } {
+    
+    set children [ winfo children $widget ]
+    set a [ llength $children ]
+    if { $a == 0 } {
+	catch { $widget configure -state $state  }
+	return 0
+    } else {
+	for { set i 0 } { $i < $a } { incr i } {
+	    SetStateOfWidget [ lindex $children $i ] $state
+	}
+    }
+}
+# ----------------------------------------------------------
+
+::itcl::body bis_algorithm::ConfigureWidgetTree { widget optionlist } {
+
+    catch { eval "$widget configure $optionlist" }
+
+    set children [ winfo children $widget ]
+    set a [ llength $children ]
+    if { $a == 0 } {
+	catch { eval " $widget configure $optionlist" }
+	return 0
+    } else {
+	for { set i 0 } { $i < $a } { incr i } {
+	    ConfigureWidgetTree [ lindex $children $i ] $optionlist
+	}
+    }
+
+}
+# ----------------------------------------------------------
+itcl::body bis_algorithm::SetWidgetTreeColors { widget backc forec } {
+
+    ::bis_algorithm::ConfigureWidgetTree $widget "-bg $backc"
+    ::bis_algorithm::ConfigureWidgetTree $widget "-fg $forec"
+    ::bis_algorithm::ConfigureWidgetTree $widget "-highlightbackground $backc"
+    ::bis_algorithm::ConfigureWidgetTree $widget "-highlightcolor $forec"
+}
+# ----------------------------------------------------------
+::itcl::body bis_algorithm::SetStateOfUI { disablelist state } {
+	
+    set a [ llength $disablelist ]
+    for { set i 0 } { $i < $a } { incr i } {
+	SetStateOfWidget [ lindex $disablelist $i ] $state
+    }
+}
+# ----------------------------------------------------------	
+::itcl::body bis_algorithm::DisableWidget { widget  }    { ::bis_algorithm::SetStateOfWidget $widget disabled }
+::itcl::body bis_algorithm::DisableUI     { widgetlist } { ::bis_algorithm::SetStateOfUI $widgetlist disabled }
+::itcl::body bis_algorithm::EnableWidget  { widget }     { ::bis_algorithm::SetStateOfWidget $widget normal   }
+::itcl::body bis_algorithm::EnableUI      { widgetlist } { ::bis_algorithm::SetStateOfUI $widgetlist normal   }
+
+# ----------------------------------------------------------
+::itcl::body bis_algorithm::WatchOn { } {
+
+    $basewidget config -cursor watch; 
+    
+    if { $containerobject != 0 } {
+	catch { $containerobject WatchOn }
+    }
+}
+# ----------------------------------------------------------
+::itcl::body bis_algorithm::WatchOff { } {
+
+    $basewidget config -cursor ""
+    ShowProgressVal "Done" 0.0
+    if { $containerobject !=0 } {
+	catch { 
+	    $containerobject WatchOff
+	    $containerobject ShowProgressVal "Done" 0.0
+	}
+    }
+}
+
+# -------------------------------------------------------------------------------------------
+# Dbase Module
+# -------------------------------------------------------------------------------------------
+itcl::body bis_algorithm::PrintMessage { msg }  {
+
+    if { $guimode ==  "commandline" } {
+	puts -nonewline stdout $msg
+    } else {
+	pxtkprint $msg
+    }
+
+    return 1
+}
+
+# -------------------------------------------------------------------------------------------
+
+itcl::body bis_algorithm::ErrorMessage { msg { titlemessage "Error Message" } } {
+
+    
+    if { $guimode ==  "commandline" } {
+	set errormessage "$msg"
+	return 0
+    }
+    tk_messageBox -type ok -message $msg -title $titlemessage -icon error
+    return 1
+}
+
+# ------------------------------------------------------------------------------------------
+itcl::body bis_algorithm::ResetParameters {  } {
+
+    set names [array names OptionsArray]
+    foreach name $names {
+	$OptionsArray($name) SetValue [ $OptionsArray($name) GetDefaultValue ]
+    }
+    return [ $this UpdateInputsFromContainer ]
+}
+
+# ------------------------------------------------------------------------------------------
+itcl::body bis_algorithm::SetParametersFromString { line } {
+
+    set cmd $scriptname
+    if { [ file extension $cmd ] != ".tcl"  } {
+	set cmd "${cmd}.tcl"
+    }
+
+    if {  [ lindex $line 0 ] != $cmd  } {
+	return [ $this ErrorMessage "Bad Parameter String for algorithm $cmd != [ lindex $line 0 ]"  "Bad Parameter File!" ]
+    }
+
+    set n [ expr [ llength $line ] -1 ]
+    if { [ expr 2*int($n/2) != $n ] } {
+	return [ $this ErrorMessage "Need even number of parameters ... ignoring $line" "Bad Parameter File!" ]
+    }
+
+
+
+    for { set i 1 } { $i < $n } { incr i } {
+	set option  [ string range [ lindex $line $i ] 1 end ]
+
+	for { set j 0 } { $j <=1 } { incr j } {
+	    set t [ string first "-"  $option  ]
+	    if { $t >=0 } {
+		set option [ string range $option 1 end ]
+	    } 
+	}
+	
+
+	incr i
+	set val    [ lindex $line $i ] 
+
+	set opt [ string range $option 0 2 ]
+	if { $opt != "inp" && $opt != "out" } {
+	    $this SetOptionValue $option $val
+#	    puts stderr "Setting $option =$val"    
+	} else {	
+#	    puts stderr "Ignoring $option =$val"    
+	}    }
+    return 1
+
+}
+# --------------------------------------------------------------------
+itcl::body bis_algorithm::HandleParameterSetArgument { plist }  {
+
+    set found [ lsearch $plist pset ]
+    
+    if { $found == -1 } {
+	puts stderr "pset not found"
+	return 0
+    }
+
+    set indx [ expr $found +1 ]
+    if { $indx < [ llength $plist ] } {
+	set pname  [ lindex $plist $indx ]
+	if { $pname == "" } {
+	    return 1
+	}
+    }
+
+    if { [ file exists $pname ] == 1 } {
+	return [ $this LoadParameters $pname ]
+    }  
+
+    set out [ $this QueryParameters $pname ]
+
+    if { [ string length $out ] > 0 } { 
+	if { $guimode ==  "commandline" } {
+	    puts stdout "Setting Parameters from database, preset=\"$pname\" ($out)"
+	}
+
+	return [ $this SetParametersFromString $out ]
+    }
+    
+    return [ $this ErrorMessage "Parameter set $pname (either as file or as database entry) does not exist" ]
+}
+
+# --------------------------------------------------------------------
+
+itcl::body bis_algorithm::LoadParameters { {fname "" }} {
+
+    if { $fname == "" || [ file exists $fname ] ==0 } {
+	set valuerange { 
+	    {"Parameter Files" {.param}} 
+	    {"All Files" {*}}}
+	
+	set fname  [tk_getOpenFile -title "Select Parameter File" -filetypes $valuerange ]
+    }
+
+    if { $fname == "" } {
+	return 0
+    }
+
+    if { [ file readable $fname ] == 0 } {
+	return 0
+    }
+
+
+    set fileid [open $fname r]
+    gets $fileid line
+    if { [string compare $line "#bis_algorithm parameter file" ] !=0 } {
+	close $fileid
+	return [ $this ErrorMessage "Bad Parameter File $fname"  "Bad Parameter File!" ]
+    }
+    gets $fileid line
+    close $fileid
+
+
+    if { $guimode ==  "commandline" } {
+	puts stdout "Setting Parameters from file=$fname ($line)"
+    }
+
+    return [ $this SetParametersFromString $line ]
+}
+
+itcl::body bis_algorithm::SaveParameters { {fname "" }} {
+
+    if { $fname == "" || [ file exists $fname ] ==0 } {
+	set valuerange { 
+	    {"Parameter Files" {.param}} 
+	    {"All Files" {*}}}
+	
+	set fname  [tk_getSaveFile -title "Select Parameter File" -filetypes $valuerange ]
+    }
+
+    if { $fname == "" } {
+	return 0
+    }
+
+    set fout [ open $fname w ]
+    puts $fout "#bis_algorithm parameter file"
+    puts $fout [ $this GetCommandLine paramset ]
+    close $fout
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+itcl::body bis_algorithm::QueryParameters { psetname } {
+
+    $this CreateDatabaseConnector
+    return [ $dbaseinterface FindPreset $psetname ]
+}
+
+
+itcl::body bis_algorithm::CreateDatabaseConnector { } {
+
+    if { $dbaseinterface ==0 } {
+	set dbaseinterface  [ [ bis_algorithmdbaseinterface \#auto ] GetThisPointer ]
+    }
+    if { [ $dbaseinterface GetAlgorithm ]  != $this  } {
+	$dbaseinterface SetAlgorithm $this
+    }
+    return $dbaseinterface
+}
+
+itcl::body bis_algorithm::ShowDatabaseGUI { mode } {
+
+    $this CreateDatabaseConnector 
+    $dbaseinterface CreateGUI $basewidget 1
+    $dbaseinterface ShowWindow $mode
+    $dbaseinterface UpdateFromAlgorithm
+    
+
+}
+
+
+# -------------------------------------------------------------------------------------------
+#  
+#    Progress Bar Stuff  and other common application level GUI Functionality
+#
+# -------------------------------------------------------------------------------------------
+
+itcl::body bis_algorithm::AboutCommand { } {
+
+    if { $aboutdialog == 0 } {
+	
+	set w .
+	if { [ string length $basewidget ] > 2 } { set w $basewidget }
+    
+	set aboutdialog  [ toplevel $w.[ pxvtable::vnewobj ]] 
+	wm geometry $aboutdialog 600x300
+    
+	::pxtclhelp::HelpDialog $aboutdialog
+	wm title $aboutdialog "About This Application"
+    
+
+	set extra "Open Source Edition\n"
+
+	set opt [ vtkpxOptimizer [ pxvtable::vnewobj ]]
+	if { [ $opt UsesNumericalRecipes ] == 1 } {
+	    set extra "Uses a small amount of code from Numerical Recipes in C\n"
+	}
+	$opt Delete
+
+	set line "[ $this GetSynopsis text ]\n\nVersion: $version\n$aboutstring \n$extra\n------------------------------------\n System Information\n------------------------------------\n[ ::pxtclutil::GetAllInfo ]"
+	                                                
+	::pxtclhelp::HelpDialogAddText $aboutdialog $line
+
+	set logoframe [ ::pxtclhelp::GetLogoFrame  $aboutdialog ]
+	set imgname [ file join $::pxtclvtkpxcontrib::imagedir  bioimagesuite_logo.gif ]
+
+	label $logoframe.b -image $::pxtclvtkpxcontrib::logo -width 581
+	pack  $logoframe.b -side left -expand t -fill x 
+
+ 	set textbox [  ::pxtclhelp::GetTextBox  $aboutdialog ]
+
+	$textbox configure -font "$::pxtclvtkpxcontrib::fontname"
+	::bis_algorithm::SetWidgetTreeColors $aboutdialog "\#8197c5" white
+    } 
+
+    ::pxtclutil::ShowWindow $aboutdialog
+
+    #    option clear
+    #    global pxtcl_pref_array
+    #    set pxtcl_pref_array(ColorScheme)  "Suite Blue"
+    #    ::pxtcluserprefs::InitializeBioImageSuiteColorScheme
+
+}
+
+
+itcl::body bis_algorithm::HelpCommand { } {
+
+    if { $helpdialog == 0 } {
+	
+	set w .
+	if { [ string length $basewidget ] > 2 } { set w $basewidget }
+    
+	set helpdialog  [ toplevel $w.[ pxvtable::vnewobj ]] 
+	wm geometry $helpdialog 800x600
+    
+	wm title $helpdialog "BioImage Suite Tool Manual Page"
+    
+	set scr [ iwidgets::scrolledhtml $helpdialog.t  -labeltext "" \
+		      -width 6i -height 3i \
+		      -wrap word -padx 2 ]
+
+	$scr configure -fontsize large
+
+	pack $scr -side top -expand true -fill both
+
+	
+	::bis_algorithm::SetWidgetTreeColors $scr "\#8197c5" white	
+	set alg $this
+	set ok [$alg GetCmdLineOptionsList]	
+	set tool [ $this GetGUIName ]
+
+	set fname ${scriptname}.tcl
+	$scr render "<HTML><HEAD><TITLE>BioImage Suite - ${tool} </TITLE></HEAD><BODY><font size=\"2\" face=\"Verdana\"><H3>NAME</H3>${fname} --[$alg GetDescription]<br> <br><H3>SYNOPSIS</H3></font><font size=\"3\" face=\"Verdana\">[$alg GetSynopsis html]</font><font size=\"2\" face=\"Verdana\"><br> <br><H3>DESCRIPTION</H3>${tool}.tcl [$alg GetDetailDescription html] <br> <br><H3>BACKWARD COMPATIBILITY ISSUES</H3>[$alg GetBackwardCompatibility]<br> <br><H3>Authors</H3>[$alg GetAuthors]<br></fon [...]
+
+
+    } 
+
+    ::pxtclutil::ShowWindow $helpdialog
+
+
+}
+
+
+itcl::body bis_algorithm::ExitCommand { } {
+    set ok [ tk_messageBox -title "Exiting this Application" -type yesno  -message "Are you sure you want to close $scriptname. Any unsaved work will be lost."  ]
+    if { $ok == "yes" } {
+	pxtkexit
+    }
+    return 0
+}
+
+itcl::body bis_algorithm::SetCurrentDirectory { { dirname "" } } {
+
+    if { [ string length $dirname ] == 0 } {
+	set dirname  [tk_chooseDirectory -title "Select Current Directory" ]
+    }
+
+    if { [ string length $dirname ] < 1 } {
+	return 0
+    }
+
+    cd $dirname
+    set dirname [ pwd ]
+    #    pxtkprint "Switched directory to $dirname"
+}
+
+
+::itcl::body bis_algorithm::AddLogoLabel { w } {
+
+    set l [ label $w.[ pxvtable::vnewobj ] -image  $::pxtclvtkpxcontrib::smalllogo ]
+    return $l
+}
+
+::itcl::body bis_algorithm::CreateProgressBar { w } {
+    
+    set l [ AddLogoLabel $w  ]
+    pack $l -side left -expand f -padx 1
+
+    set progressbar($this) $w.pbar
+    set progress_lab($this)  0.0
+    iwidgets::feedbackplus $w.pbar -steps 100  -barheight 10  -labelpos w -labeltext $progress_lab($this)  
+    pack $w.pbar -side left -expand true -fill x
+
+    #    [ $w.pbar component trough ] configure  -bg  "gra"
+    [ $w.pbar component bar ] configure  -bg  "blue"
+
+
+
+}
+# ----------------------------------------------------------
+::itcl::body bis_algorithm::ProgressCallback { filter label } {
+
+    if { $progressbar($this) != 0 } {
+	$this ShowProgress $filter $label
+    }
+
+    if { [ $OptionsArray(slicermode) GetValue ] > 0 } {
+	set p 0.5
+	catch { set p  [$filter GetProgress] }
+	if { $p==0 && $progress_status == -1 } {
+	    puts stdout "<filter-start>"
+	    puts stdout "<filter-name>[ $this GetGUIName]</filter-name>"
+	    puts stdout "<filter-comment>$label</filter-comment>"
+	    puts stdout "</filter-start>"
+	    set progress_status 0
+	} elseif { $p < 1.0 && $progress_status == 0 } { 
+	    puts stdout "<filter-progress>$p</filter-progress>"
+	} elseif { $progress_status == 0 } {
+	    puts stdout "<filter-end>"
+	    puts stdout "<filter-name>[ $this GetGUIName]</filter-name>"
+	    puts stdout "</filter-end>"
+	    set progress_status -1
+	} else {
+	    set progress_status -1
+	}
+	flush stdout
+    }
+
+    return 0
+
+}
+# ----------------------------------------------------------
+::itcl::body bis_algorithm::ShowProgress { filter lab } {
+	
+    if { $progressbar($this) == 0 } {
+	return
+    }
+
+    set progress_val($this) 50
+    catch { set progress_val($this)  [expr [$filter GetProgress]*100] }
+    set progress_lab($this) $lab
+    
+    if {$lab == "Done" } { 
+	set progress_val($this) 0
+    }
+    
+    $progressbar($this) configure  -labeltext $progress_lab($this)
+    $progressbar($this) setval [ expr round($progress_val($this)) ]
+
+    update idletasks
+}
+# ----------------------------------------------------------
+::itcl::body bis_algorithm::ShowProgressVal { name val } {
+	
+    if { $progressbar($this) == 0 } {
+	return
+    }
+	
+    set progress_val($this) [expr $val*100.0]
+    set progress_lab($this) "$name"
+	
+    if {$name == "Done" } { 
+	set progress_val($this) 0
+    }
+
+    $progressbar($this) configure  -labeltext $progress_lab($this)
+    $progressbar($this) setval [ expr round($progress_val($this)) ]
+
+    #    update idletasks
+}
+# ----------------------------------------------------------
+itcl::body bis_algorithm::GetViewer  { }  {
+
+    if { $containerobject == 0 } {
+	return $vtk_viewer
+    }
+
+    return [ $containerobject GetViewer ]
+}
+# ----------------------------------------------------------
+itcl::body bis_algorithm::GetBisViewer  { }  {
+
+    if { $bis_viewer !=0 ||  $containerobject == 0 } {
+	return $bis_viewer
+    }
+
+    set bv 0
+    catch { set bv  [ $containerobject GetBisViewer ] }
+    return $bv
+}
+# ----------------------------------------------------------
+itcl::body bis_algorithm::GetBisViewerImage  { { magn 1 }}  {
+
+    set bv [ $this GetBisViewer ]
+    if { $bv == 0 } {
+	return 0
+    }
+
+    set vr [ $bv GetViewer ]
+    set rw [ $vr GetRenderWidgetName ]
+    set renwin [ $rw GetRenderWindow ]
+
+    set renSrc [ vtkWindowToImageFilter New ]
+    $renSrc SetInput $renwin
+    $renSrc SetMagnification $magn
+    $renSrc Update
+
+    set img [ vtkImageData New ]
+    $img ShallowCopy [ $renSrc GetOutput ]
+    $renSrc Delete
+
+    return $img
+}
+
+
+# ----------------------------------------------------------
+itcl::body bis_algorithm::SetFilterCallbacks { filter comment } {
+    
+    set t [ itcl::scope $this ]
+
+    eval "$filter AddObserver ProgressEvent { $t ProgressCallback $filter \"$comment\"}"
+    eval "$filter AddObserver EndEvent      { $t ProgressCallback $filter Done}"
+
+    # Also notify container ...
+    if { $containerobject != 0 } { 
+	$containerobject SetFilterCallbacks $filter $comment
+    }
+
+    if { $eventcontainerobject !=0 } { 
+	$eventcontainerobject SetFilterCallbacks $filter $comment
+    }
+}
+
+
+
+# ----------------------------------------------------------
+itcl::body bis_algorithm::IsImageToImage { } {
+
+    set n [ array names InputsArray ]
+    if { [ llength $n ] != 1  } {
+	return 0
+    }
+    set obj $InputsArray([lindex $n 0 ])
+    if { [ $obj GetObjectType ] != "pxitclimage" } {
+	return 0
+    }
+
+    set count 0
+    foreach  n [ array names OutputsArray ] {
+	set obj $OutputsArray($n) 
+	if { [ $obj GetObjectType ] == "pxitclimage" } {
+	    incr count
+	}
+    }
+    
+    return $count
+}
+
+# ----------------------------------------------------------
+#
+#  Inputs and Outputs
+#
+# ----------------------------------------------------------
+itcl::body bis_algorithm::GetFirstInputObject  { } {
+
+    set n [ lindex [ lindex $inputs 0 ] 0 ]
+    set obj [ $InputsArray($n) GetObject ]
+    return $obj
+
+}
+
+itcl::body bis_algorithm::GetSecondInputObject  { } {
+
+    set n [ lindex [ lindex $inputs 1 ] 0 ]
+    set obj [ $InputsArray($n) GetObject ]
+    return $obj
+
+}
+
+itcl::body bis_algorithm::GetThirdInputObject  { } {
+
+    set n [ lindex [ lindex $inputs 2 ] 0 ]
+    set obj [ $InputsArray($n) GetObject ]
+    return $obj
+
+}
+
+itcl::body bis_algorithm::GetFourthInputObject  { } {
+
+    set n [ lindex [ lindex $inputs 3 ] 0 ]
+    set obj [ $InputsArray($n) GetObject ]
+    return $obj
+
+}
+
+
+itcl::body bis_algorithm::GetFirstOutputObject { } {
+    set n [ lindex [ lindex $outputs 0 ] 0 ]
+    set obj [ $OutputsArray($n) GetObject ]
+    return $obj
+}
+
+# index starts at zero !!!!
+itcl::body bis_algorithm::GetOutputObjectByIndex { { index 0 } } {
+    
+#    puts stderr "Names = [ array names OutputsArray]"
+    set n [ lindex [ lindex $outputs $index ] 0 ]
+    set obj [ $OutputsArray($n) GetObject ]
+    return $obj
+}
+
+itcl::body bis_algorithm::GetOutputObjectNameByIndex { { index 0 } } {
+    set n [ lindex [ lindex $outputs $index ] 0 ]
+    return $n
+}
+
+#----------------------------------------------------
+# GUI Construction
+#----------------------------------------------------
+
+
+
+
+itcl::body bis_algorithm::CreateGUI { basew { callafter 0 } { callbefore 0 } { testingmode 0 } } {
+
+
+    set basewidget $basew
+
+    # First Store the Callbacks
+    set callbackbefore $callbefore
+    set callbackafter  $callafter
+    set progressbar($this) 0
+    set progress_lab($this) "Status"
+    set progress_val($this) 0
+
+
+    if { $guimode == "standalone" } {
+	return [ $this CreateStandaloneGUI $testingmode ]
+    } elseif { $guimode == "datatree" && $datatree !=0 } {
+	return [ $this CreateDataTreeGUI ]
+    }
+
+    return [ $this CreateManagedGUI ]
+}
+
+
+#----------------------------------------------------
+itcl::body bis_algorithm::CreateStandaloneGUI { { testingmode 0 } } {
+
+
+    # Now Create Main GUI View
+    # If main application then menubase, viewbase, guibase and pbar all created
+    # Else only viewbase
+
+    set viewbase 0
+    set noviewer 0
+    set showoutputsmode 1
+
+    set doviewer 1
+    if { [ llength $inputs ] == 0 && [ llength $outputs ] == 0 } {
+	set showoutputsmode 0
+	set noviewer 1
+    } elseif { $createviewermode  == 0 } {
+	set noviewer 1
+    }
+
+    set buttonbar 0
+
+    set menubase     [ menu $basewidget.top -tearoff 0  ]
+    $basewidget configure -menu $menubase
+    set pbar         [ frame $basewidget.pbar    -width 500 -height 20 ]
+    
+    CreateProgressBar  $pbar
+    
+    pack $pbar -side bottom -expand false -fill x
+    
+    eval "bind all <Control-d>  { $this ExitCommand }"
+    eval "wm protocol . WM_DELETE_WINDOW { $this ExitCommand } "
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { $this ExitCommand  }"
+    bind all <F1>  { pxtkconsole }
+    
+    set w $basewidget.v
+    
+    if { $noviewer == 0 } {
+	if { $testingmode == 0 } {
+	    set nt [ panedwindow $w -orient horizontal -showhandle 1 \
+			 -borderwidth 10 -relief raised -sashwidth 4 -sashpad 4 \
+			 -handlesize 5 -handlepad 50  ]
+	    set guibase  [ frame $nt.c  -width 500 -bg red ]
+	    set viewbase  [ frame $nt.v -width 450 ]
+	    
+	    $nt add $guibase -minsize  300 -sticky nse
+	    $nt add $viewbase -minsize 400 -sticky nsew
+	} else {
+	    set nt [ frame $w ]
+	    set guibase  [ frame $nt.c  -width 500 ]
+	    set viewbase  [ frame $nt.v -width 450 ]
+	    pack $viewbase -side right -expand false -fill y
+	}
+	set guibasewidget $guibase
+	CreateViewer  $viewbase
+	if { $testingmode > 0 } {
+	    $vtk_viewer SetShowControls 0
+	}
+    } else {
+	set nt [ frame $w ]
+	set guibase $nt
+    }
+
+    set buttonbar [ frame $guibase.bot ]
+    pack $buttonbar -side bottom -expand false -fill x
+    CreateMenuBar $menubase
+    pack $nt -side top -expand true -fill both 
+    
+    set inbase 0
+    set outbase 0
+    set numout [ llength $outputs ]
+    set numint [ llength $inputs  ]
+    set needsdc 0
+    if { $noviewer == 0 } {
+	set needsdc [ $this NeedsCustomDataControl ]
+    }
+
+    if { [ expr $numout + $numint + $needsdc ] > 0 } {
+	set w $guibase
+	set guibase [  iwidgets::tabnotebook $guibase.0 -tabpos n  -angle 45 -margin 2 -backdrop gray -raiseselect true  ]
+	pack $guibase -side top -expand true -fill both
+
+	if { $needsdc } {
+	    $this CreateCustomDataControl  $guibase 
+	}
+	
+	if { [ llength $inputs ] > 0 } {
+	    set inbase  [ $guibase add -label Inputs ]
+	}
+	set optbase [ $guibase add -label Options ]
+	$optbase configure -bg red
+	if { [ llength $outputs ] > 0 } {
+	    set outbase [ $guibase add -label Outputs ]
+	}
+	$guibase view "Options"
+	update idletasks
+    } else {
+	set optbase $guibase
+    }
+
+    if { $inbase !=0 } { 
+	CreateInputGUIInterface $inbase 
+    }
+
+    CreateOptionsGUIInterface $optbase
+    
+    if { $buttonbar == 0 } {
+	set buttonbar     [ frame $optbase.2    -width 500 -height 20 ]
+	pack $buttonbar -side bottom -expand true -fill x
+    }
+
+
+    eval "button $buttonbar.a -text \"$executename\" -command { $this InvokeAlgorithmFromGUI } -padx 5"
+    eval "button $buttonbar.b -text \"Show Command\" -command { $this ShowCommandLine } -padx 5"
+    pack $buttonbar.b -side right -expand false
+    pack $buttonbar.a -side left -expand true -fill x
+
+
+    if { $outbase !=0 &&  $showoutputsmode == 1 } {
+	$this CreateOutputGUIInterface $outbase 
+    }
+    return $basewidget
+}
+#----------------------------------------------------
+itcl::body bis_algorithm::CreateDataTreeGUI { } {
+
+    #    puts stderr "Creating Data tree GUI"
+
+    if { [ llength $inputs ] == 0 && [ llength $outputs ] == 0 } {
+	set showoutputsmode 0
+    }
+    set buttonbar 0
+#    set n [ $this GetGUIName ]
+#    label $basewidget.o -text "$n" -bg black -fg white
+#    pack $basewidget.o -side top -expand false -fill x
+
+    set buttonbar [ frame  $basewidget.bot2 ]
+    pack $buttonbar -side bottom -expand false -fill x
+
+    set nt [ panedwindow $basewidget.top -orient vertical -showhandle 1 \
+		 -borderwidth 10 -relief raised -sashwidth 4 -sashpad 4 \
+		 -handlesize 5 -handlepad 50  ]
+    pack $nt -side top -expand true -fill both 
+    set base $nt
+
+    set top [ [ iwidgets::labeledframe $base.top  -labeltext "Parameters" ] childsite ]
+    set bot [ [ iwidgets::labeledframe $base.bot  -labeltext "Inputs+Outputs" ] childsite ]
+
+    $nt add $base.top -minsize 200 -height 350
+    $nt add $base.bot -minsize 200 -height 350
+
+    set guibase [  iwidgets::tabnotebook $bot.0 -tabpos n  -angle 45 -margin 2 -backdrop gray -raiseselect true ]
+    pack $guibase -side top -expand true -fill both
+    
+    if { [ llength $inputs ] > 0 } {
+	set inbase  [ $guibase add -label Inputs ]
+	CreateInputGUIInterface $inbase
+	$guibase view "Inputs"
+    }
+    if { [ llength $outputs ] > 0 } {
+	set outbase [ $guibase add -label Outputs ]
+	$this CreateOutputGUIInterface $outbase 
+	if { [ llength $inputs ] == 0 } {
+	    $guibase view "Outputs"
+	}
+    }
+
+    CreateOptionsGUIInterface $top
+    
+    eval "button $buttonbar.a -text \"$executename\" -command { $this InvokeAlgorithmFromGUI } -padx 5"
+    eval "button $buttonbar.b -text \"Show Command\" -command { $this ShowCommandLine } -padx 5"
+    pack $buttonbar.b -side right -expand false
+    pack $buttonbar.a -side left -expand true -fill x
+
+
+    return $basewidget
+}
+#----------------------------------------------------
+
+itcl::body bis_algorithm::CreateManagedGUI { } {
+
+
+    if { [ llength $inputs ] == 0 && [ llength $outputs ] == 0 } {
+	set showoutputsmode 0
+	set noviewer 1
+    }
+
+    set inbase 0
+    set outbase 0
+    set numout [ llength $outputs ]
+    set numint [ llength $inputs  ]
+
+
+
+    if { [ expr $numout + $numint ] > 0 && ( $showoutputsmode == 1 ) } {
+	set guibase [  iwidgets::tabnotebook $basewidget.1 -tabpos w  -angle 45 -margin 2 -backdrop gray -raiseselect true ]
+	pack $guibase -side top -expand true -fill both
+
+	if { [ llength $inputs ] > 0 } {
+	    set inbase  [ $guibase add -label Inputs ]
+	}
+	set optbase [ $guibase add -label Options ]
+	if { [ llength $outputs ] > 0 } {
+	    set outbase [ $guibase add -label Outputs ]
+	}
+	$guibase view "Options"
+    } else {
+	set optbase $basewidget
+    }
+
+    
+    set buttonbar     [ frame $optbase.2    -width 500 -height 20 ]
+    pack $buttonbar -side bottom -expand false -fill x
+    frame $optbase.1; pack $optbase.1 -side top -expand true -fill both
+    
+    frame $buttonbar.1 
+    frame $buttonbar.2 -bg black -height 2
+    frame $buttonbar.3 
+    pack $buttonbar.1 $buttonbar.2 $buttonbar.3 -side top -expand false -fill x
+
+    set parameterbar $buttonbar.1
+
+    label $buttonbar.1.0 -text "Parameters:" 
+    eval "button $buttonbar.1.a -text \"Load\" -command { $this LoadParameters }"
+    eval "button $buttonbar.1.b -text \"Save\" -command { $this SaveParameters }"
+    eval "button $buttonbar.1.c -text \"Query\" -command { $this ShowDatabaseGUI query }"
+    eval "button $buttonbar.1.d -text \"Store\" -command { $this ShowDatabaseGUI store }"
+    eval "button $buttonbar.1.e -text \"Reset\" -command { $this ResetParameters }"
+    pack $buttonbar.1.0 $buttonbar.1.a $buttonbar.1.b $buttonbar.1.c $buttonbar.1.d $buttonbar.1.e -side left -expand false -padx 1
+    
+    eval "button $buttonbar.3.a -text \"$executename\" -command { $this InvokeAlgorithmFromGUI } -padx 5"
+    eval "button $buttonbar.3.b -text \"Show Command\" -command { $this ShowCommandLine } -padx 5"
+    pack $buttonbar.3.b -side right -expand false
+    pack $buttonbar.3.a -side left -expand true -fill x
+
+
+    if { $outbase !=0 } {
+	if { $showoutputsmode == 1 } {
+	    iwidgets::scrolledframe $outbase.sf  -labeltext ""  -hscrollmode dynamic -vscrollmode dynamic
+	    pack $outbase.sf -side top -expand true -fill both
+	    $this CreateOutputGUIInterface [ $outbase.sf childsite ]
+	}
+    }
+
+
+    CreateOptionsGUIInterface $optbase.1
+
+    return $basewidget
+}
+
+
+
+#----------------------------------------------------
+#  Create Input GUIInterface
+#----------------------------------------------------
+itcl::body bis_algorithm::CreateInputGUIInterface { bar } {
+
+    if { $hasinputguis == 1 } {
+	return
+    }
+
+    set c [ iwidgets::scrolledframe $bar.[pxvtable::vnewobj ] -width 12i -height 12i -hscrollmode dynamic -vscrollmode dynamic  -labelpos nw -labeltext "" -relief ridge ]
+    pack $c -side top -expand true -fill both
+    set bar [ $c childsite ]
+
+    set count 0
+    set nlist ""
+    foreach name [ array names InputsArray ] {
+	lappend nlist [ list $name [ expr abs([  $InputsArray($name) GetPriority ]) ] ]
+    }
+    set nlist [ lsort -integer  -index 1 $nlist ]
+
+    set dograb 1
+    for { set i 0 } { $i < [ llength $nlist ] } { incr i } {
+	if { [ $InputsArray($name) GetObjectType ] != "pxitcltransform" } {
+	    set dograb 2
+	}
+    }
+
+    for { set i 0 } { $i < [ llength $nlist ] } { incr i } {
+
+	set name [ lindex [ lindex $nlist $i ] 0 ]
+	if { [ $InputsArray($name) GetDescription ] != "" } { 
+	    set n $bar.$name$count
+	    if { $guimode == "datatree" } {
+		$InputsArray($name) CreateDataTreeObjectGUI $n $dograb 0 $this $datatree
+		pack $n -side top -expand false -fill x -pady 0
+	    } else {
+		$InputsArray($name) CreateObjectGUI $n 0 "" $this
+		pack $n -side top -expand false -fill x 
+	    }
+
+	}
+	incr count
+    }
+    set hasinputguis 1
+    PrintDebug "Done Creating Inputs"
+}
+
+
+itcl::body bis_algorithm::CreateOutputGUIInterface { bar } {
+
+    if { $hasoutputguis == 1 } {
+	return
+    }
+
+    set c [ iwidgets::scrolledframe $bar.[pxvtable::vnewobj ] -width 12i -height 12i -hscrollmode dynamic -vscrollmode dynamic  -labelpos nw -labeltext "" -relief ridge ]
+    pack $c -side top -expand true -fill both
+    set bar [ $c childsite ]
+
+    set count 0
+    set nlist ""
+    foreach name [ array names OutputsArray ] {
+	lappend nlist [ list $name [ expr abs([  $OutputsArray($name) GetPriority ]) ] ]
+    }
+    set nlist [ lsort -integer  -index 1 $nlist ]
+
+    for { set i 0 } { $i < [ llength $nlist ] } { incr i } {
+
+	set name [ lindex [ lindex $nlist $i ] 0 ]
+	set ln "Creating a GUI for output $name"
+
+	set n $bar.$name$count
+	if { $guimode == "datatree" } {
+	    $OutputsArray($name) CreateDataTreeObjectGUI $n 0 1 $this $datatree
+	} else {
+	    $OutputsArray($name) CreateObjectGUI $n 1 "" $this
+	}
+	pack $n -side top -expand false -fill x
+	incr count
+    }
+    set hasoutputguis 1
+}
+
+itcl::body bis_algorithm::CreateOptionsGUIInterface { optbase } { 
+
+    # Step 1 number -- determine number of experimental parameters
+    # Priority < 0 experimental
+    # Priority >=0 normal
+    # Priority = -1000 do not show (-dogui)
+    set numexp 0
+   set names [array names OptionsArray]
+    foreach name $names {
+	set opt $OptionsArray($name)
+
+	set pr [ $opt GetPriority ]
+	if { $pr < 0 && $pr > -1000 } {
+	    incr numexp
+	}
+    }
+
+    # If we have experimental then create tabbed notebook
+    # Else simple frame
+    if { $numexp > 0 } {
+	set nt [ iwidgets::tabnotebook $optbase.nt -tabpos n -angle 45 -margin 2 -backdrop gray -raiseselect true   ]
+	pack $nt -side top -expand true  -fill both
+	set t(0)  [ $nt add -label Standard   ]
+	set t(1)  [ $nt add -label Advanced ]
+
+	for { set i 0 } { $i <=1 } { incr i } {
+	    if { $maintabscrollmode > 0 } {
+		set c [ iwidgets::scrolledframe $t($i).[pxvtable::vnewobj ] -width 12i -height 12i -hscrollmode dynamic -vscrollmode dynamic  -labelpos nw -labeltext "" -relief ridge ]
+		pack $c -side top -expand true -fill both
+		set topbar($i)  [ $c childsite ]
+	    } else {
+		set topbar($i) $t($i)
+	    }
+	}
+
+	$nt view "Standard"
+
+	for { set i 0 } { $i <=1 } { incr i } {
+	    set w [ frame $topbar($i).sf  ]
+	    set topbar($i) $w
+	    pack $w -side top -expand true -fill both
+
+	}
+    } else {
+	if { $maintabscrollmode > 0 } {
+	    set c [ iwidgets::scrolledframe $optbase.[pxvtable::vnewobj ] -width 12i -height 12i -hscrollmode dynamic -vscrollmode dynamic  -labelpos nw -labeltext "" -relief ridge ]
+	    pack $c -side top -expand true -fill both
+	    set w [ $c childsite ]
+	} else {
+	    set w [ frame $optbase.sf ]
+	    pack $w -side top -expand true -fill both 
+	}
+	set topbar(0) $w
+	set topbar(1) $w
+
+    }
+
+
+    # For each element in options create GUI element
+
+    set nlist [ concat $StandardOptionsList $AdvancedOptionsList ]
+    set elemlist ""
+
+    for { set i 0 } { $i < [ llength $nlist ] } { incr i } {
+
+	set name  [ lindex $nlist $i ]
+	set opt $OptionsArray($name)
+	set ind 0
+	set pr [ $opt GetPriority ]
+	if { $pr > -1000 } {
+	    if { $pr < 0 } {
+		set ind 1
+	    }
+	    set w  $topbar($ind).[pxvtable::vnewobj ] 
+	    $opt CreateGUIElement $w ""
+	    lappend elemlist [ list [ expr abs($pr)] $ind $name $w ]
+	}
+    }
+
+    if { [ llength $elemlist ] > 0 } {
+	$this PackOptionsGUIInterface $elemlist
+	$this ConfigureOptionsGUICallbacks
+    }
+
+}
+
+# lst is a list of lists !, each sublist has two elements, the name and the widget
+itcl::body bis_algorithm::PackOptionsGUIInterface { lst } {
+
+    set n [ llength $lst ]
+    PrintDebug "\n\n Length of list = $n"
+
+    for { set tab 0 } { $tab <= 1 } { incr tab } {
+	set wlist ""
+	for { set i 0 } { $i < $n } { incr i } {
+	    
+		set pair [ lindex $lst $i ]
+		set ind  [ lindex $pair 1 ]
+		if { $ind == $tab } {
+		    lappend wlist $pair
+		}
+	    }
+
+	set wlist [ lsort -integer  -index 0 $wlist ]
+
+	set nlist ""
+	for { set j 0 } { $j < [ llength $wlist ] } { incr j } {
+
+	    set pair [ lindex $wlist $j ]
+	    set name [ lindex $pair 2 ]
+	    set widg [ lindex $pair 3 ]
+
+	    #PrintDebug "Packing $name"
+	    #puts stderr "Packing $name ---> $widg, [ lindex $pair 0 ]"
+	    pack $widg -side top -expand false -fill x -padx 1
+	    lappend nlist  $widg.lab
+	}
+	update idletasks
+	eval "iwidgets::Labeledwidget::alignlabels $nlist"
+    }
+
+}
+
+
+# ----------------------------------------------------------------------
+
+
+itcl::body bis_algorithm::CreateMenuBar { menubase } {
+
+    set filem [ menu $menubase.file -tearoff 0  ]
+    $menubase add cascade -underline 0  -label "File" -menu $filem
+
+    eval "$filem add command -label \"Load Parameters\" -command { $this LoadParameters }"
+    eval "$filem add command -label \"Save Parameters\" -command { $this SaveParameters }"
+    $filem add separator
+    eval "$filem add command -label \"Query Parameters from Database\" -command { $this ShowDatabaseGUI query } "
+    eval "$filem add command -label \"Store Parameters in Database\" -command { $this ShowDatabaseGUI store } "
+    $filem add separator
+    eval "$filem add command -label \"Reset Parameters\" -command { $this ResetParameters }"
+
+    $filem add separator
+    eval "$filem add command -label \"Switch Directory\" -command { $this SetCurrentDirectory } "
+    $filem add separator
+    eval "$filem add command -label Exit -command {  $this ExitCommand } -underline 1"
+
+    set runm [ menu $menubase.run -tearoff 0  ]
+    $menubase add cascade -underline 0  -label "Run" -menu $runm
+    eval "$runm add command -label \"$executename\" -command {$this InvokeAlgorithmFromGUI }"
+
+
+    set viewm [ menu $menubase.viewm -tearoff 0  ]
+    $menubase add cascade -underline 0  -label "Viewer" -menu $viewm
+    if { $bis_viewer !=0 } {
+	$bis_viewer AddToMenu $viewm
+    }
+
+    
+    set helpm [ menu $menubase.help -tearoff 0  ]
+    $menubase add cascade -underline 0  -label "Help" -menu $helpm 
+
+    eval "$helpm add command -label \"Tool Manual Page\" -command { $this HelpCommand }"
+    eval "$helpm add separator"
+    eval "$helpm add command -label \"Show Command Line\" -command {$this ShowCommandLine }"    
+    eval "$helpm add command -label \"Show Long  Description\" -command {$this ShowLongDescription }"    
+    $helpm add separator
+    $helpm add command -label "Show Console" -command { pxtkconsole }
+    eval "$helpm add separator"
+    eval "$helpm add command -label About -command { $this AboutCommand }"
+}
+
+# --------------------------------------------------------------------
+
+itcl::body bis_algorithm::CreateViewer { fr } {
+
+    set viewerbasewidget $fr
+    set bis_viewer [ [ bis_viewer \#auto ] GetThisPointer ]
+    $bis_viewer configure -enable_toolbar  0
+    $bis_viewer SetViewerType $bis_viewer_type $bis_viewer_edit 
+    $bis_viewer CreateGUI $fr 
+    set vtk_viewer [ $bis_viewer GetViewer ]
+
+
+}
+# --------------------------------------------------------------------
+itcl::body bis_algorithm::SetViewer { vr } {
+    set vtk_viewer $vr
+}
+
+itcl::body bis_algorithm::SetBisViewer { vr } {
+    set bis_viewer $vr
+    set vtk_viewer [ $bis_viewer GetViewer ]
+}
+
+#----------------------------------------------------
+# Invoke algorithm from GUI
+#----------------------------------------------------
+
+itcl::body bis_algorithm::GetCommandLine { { mode short } } {
+
+    set cmd $scriptname
+    if { [ file extension $cmd ] != ".tcl"  } {
+	set cmd "${cmd}.tcl"
+    }
+
+    set nlist [ concat $StandardOptionsList $AdvancedOptionsList ]
+    for { set i 0 } { $i < [ llength $nlist ] } { incr i } {
+	set name [ lindex $nlist $i ]
+	if {  [ lsearch -exact $ignoreflag $name  ] == -1 } {
+	    if { [ string compare -length 3 $name "gui" ] != 0 && 
+		 $name != "loni" } {
+		
+		set opt $OptionsArray($name)
+		$opt UpdateFromGUI
+		set v [ string trim [ $opt GetValue ] ]
+
+		
+		if { [ string first " " $v ] > 0 || [ string first ";" $v ] > 0   || [ string first "\t" $v ] > 0 } {
+		    set v "\"$v\""
+		}
+
+		if { [ string length $v ] > 0 } {
+		    if { $mode == "short" } {
+			if { $v != [ $opt GetDefaultValue ] } {
+			    set cmd "$cmd --[ $opt GetCommandSwitch ] $v"
+			}
+		    } else {
+			set cmd "$cmd --[ $opt GetCommandSwitch ] $v"
+		    }
+		}
+	    }
+	}
+    }
+
+    if { $mode != "paramset" } {
+	
+	for { set i 0 } { $i < [ llength $outputs ] } { incr i } {
+	    set elem [ lindex $outputs $i ]
+	    set name  [ lindex $elem  0 ]
+	    set fname [ $OutputsArray($name) GetFileName ]
+	    set v [ $OutputsArray($name) IsFileNameTheDefault ]
+	    if { [ string length $fname ] > 0 } {
+		if { $v==0 || $mode !="short" } {
+		    set cmd "$cmd --[ $OutputsArray($name) GetCommandSwitch ] $fname"
+		}
+	    }
+	}
+	
+	for { set i 0 } { $i < [ llength $inputs ] } { incr i } {
+	    set elem [ lindex $inputs $i ]
+	    set name  [ lindex $elem  0 ]
+	    if { $name != $directinputs } {
+		set fname [ $InputsArray($name) GetFileName ]
+		set v [ $InputsArray($name) IsFileNameTheDefault ]
+		if { [ string length $fname ] > 0 } {
+		    if { $v==0 || $mode !="short" } {
+			set cmd "$cmd --[ $InputsArray($name) GetCommandSwitch ] $fname"
+		    }
+		}
+	    }
+	}
+
+	if { $directinputs != "" } {
+	    set v " [ $InputsArray($directinputs) GetFileName ] [ $InputsArray($directinputs) GetFileNameList ]"
+	    #	    puts stdout "directs = $v"
+	    append cmd $v
+	}
+    }
+
+    return $cmd
+}
+# ----------------------------------------------------------------------------------------------------------------
+itcl::body bis_algorithm::GetSlicerXMLDescription {  } {
+
+    set cmd $scriptname
+    if { [ file extension $cmd ] != ".tcl"  } {
+	set cmd "${cmd}.tcl"
+    }
+
+    set names [ concat $StandardOptionsList $AdvancedOptionsList ]
+
+    set normal "<parameters>\n<label>Standard</label>\n<description>Standard Parameters</description>"
+    set advanced "<parameters advanced=\"true\">\n<label>Advanced</label>\n<description>Advanced Parameters</description>"
+    set debug "<parameters advanced=\"true\">\n<label>Debug</label>\n<description>Debug Parameters</description>"
+    set inp "<parameters>\n<label>Inputs</label>\n<description>Input Objects</description>"
+    set outp "<parameters>\n<label>Outputs</label>\n<description>Output Objects</description>"
+    set numnormal 0
+    set numadvanced 0
+    set numinp 0
+    set numout 0
+
+
+
+    for { set i 0 } { $i < [ llength $names ] } { incr i } {
+	set name [ lindex $names $i ]
+	if {  [ lsearch -exact $ignoreflagslicer $name  ] == -1 &&  [ string compare -length 3 $name "gui" ] !=0 } {
+	    
+	    #	    puts stderr "Using $name"
+	    set opt $OptionsArray($name)
+
+	    set desc [ $opt GetSlicerXMLDescription ]
+	    set pri  [ $opt GetPriority ]
+
+	    if { $name == "dogui" || $name =="slicermode" } {
+		if { $name == "slicermode" } {
+		    $opt SetDefaultValue 1
+		    $opt SetValue 1
+		}
+		set desc [ $opt GetSlicerXMLDescription ]
+
+		if { $forceguimode == 0 || $name !="dogui" } {
+		    set debug "$debug\n$desc"
+		}
+	    } elseif { $pri >= 0 } {
+		set normal "$normal\n$desc"
+		set numnormal 1
+	    } else {
+		set advanced "$advanced\n$desc"
+		set numadvanced 1
+	    }
+	}
+    }
+ 
+     for { set i 0 } { $i < [ llength $inputs ] } { incr i } {
+	 set n [ lindex [ lindex $inputs $i ] 0 ]
+	 if { $n != $directinputs } {
+	     set desc [ bis_object::GetSlicerListXMLDescription [ lindex $inputs $i ] 1 [expr $i +1 ]  ]
+	     if { $desc != "" } {
+		 set inp "$inp\n$desc"
+		 incr numinp
+	     }
+	 }
+     }
+
+    if { $directinputs != "" } {
+	set j 0; set found -1
+	while { $j < [ llength $inputs ] } {
+	    if { [ lindex [ lindex $inputs $j ] 0 ] == $directinputs } {
+		set found $j
+		set j 10000
+	    }  
+	    incr j
+	}
+	if { $found != -1 } {
+	    for { set i 0 } { $i <= 8 } { incr i } {
+		set desc [ bis_object::GetSlicerListXMLDescription [ lindex $inputs $found ] 1 [expr $i +1 ] $i ]
+		if { $desc != "" } {
+		    set inp "$inp\n$desc"
+		incr numinp
+		}
+	    }
+	}
+    }
+
+     for { set i 0 } { $i < [ llength $outputs ] } { incr i } {
+	 set desc [ bis_object::GetSlicerListXMLDescription [ lindex $outputs $i ]  0 [ expr $i +1 ] ]
+	 if { $desc != "" } {
+	     set outp "$outp\n$desc"
+	     incr numout
+	 }
+
+     }
+
+    set cmdline "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+    set cmdline "$cmdline\n<executable>"
+    set cmdline "$cmdline\n<category>Yale BioImage Suite-${category}</category>"
+    set cmdline "$cmdline\n<title>BioImage Suite-[ $this GetGUIName]</title>"
+    set cmdline "$cmdline\n<description>$description\n$description2</description>"
+    set cmdline "$cmdline\n<version>$::pxtclvtkpxcontrib::versionno</version>"
+    set cmdline "$cmdline\n<documentation-url>www.bioimagesuite.org</documentation-url>"
+    set cmdline "$cmdline\n<license>GPL v2</license>"
+    set cmdline "$cmdline\n<contributor>$authors</contributor>\n"
+
+     if { $numnormal > 0 } { set cmdline "$cmdline\n$normal\n</parameters>\n" }
+     if { $numadvanced > 0 } { set cmdline "$cmdline\n$advanced\n</parameters>\n" }
+     set cmdline "$cmdline\n$debug\n</parameters>\n" 
+     if { $numinp > 0 } { set cmdline "$cmdline\n$inp\n</parameters>\n" }
+     if { $numout > 0 } { set cmdline "$cmdline\n$outp\n</parameters>\n" }
+
+    set cmdline "$cmdline\n</executable>\n"
+
+    return $cmdline
+}
+# ---------------------------------------------------------------------
+# mode 0 = normal, 1 =advanced 2 =debug
+itcl::body bis_algorithm::GetJSONParameters { mode } {
+
+    set num 0
+    set out ""
+    set names [ concat $StandardOptionsList $AdvancedOptionsList ]
+    for { set i 0 } { $i < [ llength $names ] } { incr i } {
+	set name [ lindex $names $i ]
+	set opt $OptionsArray($name)
+	set desc [ $opt GetJSONString ]
+	set pri  [ $opt GetPriority ]
+	if { ( ($pri >= 0 && $mode==0) || ($pri > -9999 && $pri < 0 && $mode == 1) || ($pri < -9999 && $mode == 2 ) ) } {
+	    if { $num > 0 } {
+		append out ","
+	    }
+	    append out "\n$desc"
+	    incr num
+	}
+    }
+    return $out
+}
+
+itcl::body bis_algorithm::GetJSONInputs { } {
+
+    set inp ""
+    set numinp 0
+    for { set i 0 } { $i < [ llength $inputs ] } { incr i } {
+	set n [ lindex [ lindex $inputs $i ] 0 ]
+	if { $n != $directinputs } {
+	    set desc [ bis_object::GetJSONString [ lindex $inputs $i ] 1 [expr $i +1 ]  ]
+	    if { $desc != "" } {
+		if { $numinp > 0 } {
+		    append inp ","
+		}
+		append inp "\n$desc"
+		incr numinp
+	    }
+	}
+    }
+    return $inp
+
+}
+
+itcl::body bis_algorithm::GetJSONOutputs { } {
+    set outp ""
+    set numout 0
+    for { set i 0 } { $i < [ llength $outputs ] } { incr i } {
+	set desc [ bis_object::GetJSONString [ lindex $outputs $i ]  0 [ expr $i +1 ] ]
+	if { $desc != "" } {
+	    if { $numout > 0 } {
+		append outp ","
+	    }
+	    append outp "\n$desc"
+	    incr numout
+	}
+    }
+    return $outp
+
+}
+
+itcl::body bis_algorithm::GetJSONDescription {  } {
+
+    set cmd $scriptname
+    if { [ file extension $cmd ] != ".tcl"  } {
+	set cmd "${cmd}.tcl"
+    }
+
+
+    set names [ concat $StandardOptionsList $AdvancedOptionsList ]
+
+    set numnormal 0
+    set numadvanced 0
+    set numdebug 0
+    set numinp 0
+    set numout 0
+    set normal   " \"Standard\": \{"
+    set advanced   " \"Advanced\": \{"
+    set debug   " \"Debug\": \{"
+    set inp   " \"Inputs\": \{"
+    set outp   " \"Outputs\": \{"
+
+
+    
+
+    set    outtxt  "\{\n"
+    append outtxt  " \"Header\": \{"
+    append outtxt "\t\"commandname\": [ ::bis_common::CleanString $cmd],\n"
+    append outtxt "\t\"category\": [ ::bis_common::CleanString ${category}],\n"
+    append outtxt "\t\"title\":  [ ::bis_common::CleanString [ $this GetGUIName]],\n"
+    append outtxt "\t\"description\": [ ::bis_common::CleanString $description],\n"
+    append outtxt "\t\"description2\": [ ::bis_common::CleanString $description2],\n"
+    append outtxt "\t\"authors\": [ ::bis_common::CleanString $authors]"
+    append outtxt "\n\t\},\n"
+
+    append normal [ $this GetJSONParameters 0 ]
+    append advanced [ $this GetJSONParameters 1 ]
+    append debug  [ $this GetJSONParameters 2 ]
+    append inp [ $this GetJSONInputs ]
+    append outp [ $this GetJSONOutputs ]
+ 
+    
+
+    append outtxt "$normal\n\t\},\n"
+    append outtxt "$advanced\n\t\},\n"
+    append outtxt "$debug\n\t\},\n"
+    append outtxt "$inp\n\t\},\n"
+    append outtxt "$outp\n\t\}\n"
+    append outtxt "\}\n"
+    
+    return $outtxt
+}
+# ----------------------------------------------------------------------------------------------------------------
+itcl::body bis_algorithm::GetLONIXMLDescription { { mode 1 } } {
+
+    set cmd $scriptname
+    if { [ file extension $cmd ] != ".tcl"  } {
+	set cmd "${cmd}.tcl"
+    }
+
+    set names [ concat $StandardOptionsList $AdvancedOptionsList ]
+    if { [ llength $names ] > 0 } {
+	set parameters "\n"
+	set inp ""
+	set outp ""
+	set numparam [ llength $names ]
+	
+	for { set i 0 } { $i < [ llength $names ] } { incr i } {
+	    set name [ lindex $names $i ]
+	    if { $name != "testlog"  && $name !="pset" && [ string compare -length 3 $name "gui" ] !=0 } {
+		
+		set opt $OptionsArray($name)
+		
+		set desc [ $opt GetLONIXMLDescription ]
+		set pri  [ $opt GetPriority ]
+		
+		if { $pri > -1000 } {
+		    append parameters "$desc\n"
+		}
+	    }
+	}
+    }
+ 
+    set numinp 0
+    set names [ array names InputsArray ]
+    if { [ llength $names ] > 0 } {
+	foreach name $names {
+	    lappend nlist [ list $name [ expr abs([  $InputsArray($name) GetPriority ]) ] ]
+	}
+	set nlist [ lsort -integer  -index 1 $nlist ]
+	
+	for { set i 0 } { $i < [ llength $nlist ] } { incr i } {
+	    set name [ lindex [ lindex $nlist $i ] 0 ]
+	    set desc [ $InputsArray($name) GetLONIXMLDescription  1  ]
+	    if { $desc != "" } {
+		append inp "$desc\n"
+		incr numinp
+	    }
+	}
+    }
+
+    set numout 0
+    set nlist ""
+    set names [ array names OutputsArray ]
+    if { [ llength $names ] > 0 } {
+	foreach name $names {
+	    lappend nlist [ list $name [ expr abs([  $OutputsArray($name) GetPriority ]) ] ]
+	}
+	set nlist [ lsort -integer  -index 1 $nlist ]
+	for { set i 0 } { $i < [ llength $nlist ] } { incr i } {
+	    set name [ lindex [ lindex $nlist $i ] 0 ]
+	    set desc [ $OutputsArray($name) GetLONIXMLDescription 0 ]
+	    if { $desc != "" } {
+		append outp "$desc\n"
+		incr numout
+	    }
+	}
+    }
+
+    
+    set fname [ info script ]
+    set tname [ file tail $fname ]
+    set fname2 [ file dirname [ file dirname $fname ] ]
+    set ftail [ file rootname [ file tail $fname ] ]
+    set newname "${fname2}/bin/${ftail}"
+
+    set cmdline "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+    if { $mode <2 } {
+	append cmdline "<pipeline version=\".1\">\n"
+	append cmdline "\t<moduleGroup id=\"id_$tname\" name=\"$tname\">\n"
+    }
+    append cmdline "\t\t<module name=\"[ $this GetGUIName]\" "
+    append cmdline "description=\"$description$description2\" "
+    append cmdline "location=\"pipeline://localhost/$newname\" "
+    append cmdline "package=\"BioImage Suite\" "
+    append cmdline "icon=\"/9j/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAx&#xA;NDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy&#xA;MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAAUCAAwADAEASIAAhEBAxEBBCIA/8QAHwAAAQUB&#xA;AQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEG&#xA;E1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVW&#xA;V1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ip [...]
+    append cmdline "version=\"$::pxtclvtkpxcontrib::versionno\">"
+
+    append cmdline "executableVersion=\"$::pxtclvtkpxcontrib::versionno\">\n"
+    append cmdline "\t\t\t<executableAuthors>\n"
+    append cmdline "\t\t\t\t<author fullName=\"BioImage Suite Team\" email=\"\" website=\"www.bioimagesuite.org\" />\n"
+    append cmdline "\t\t\t</executableAuthors>\n"
+    append cmdline "\t\t\t<tag />\n"
+    append cmdline "\t\t\t<uri>www.bioimagesuite.org</uri>"
+
+
+    set endcmdline "\t\t</module>\n"
+    if { $mode <2 } {
+	append endcmdline "\t</moduleGroup>\n"
+	append endcmdline "</pipeline>\n"
+    }
+
+
+    if { $numparam > 0 } { append cmdline "$parameters\n" }
+    if { $numinp > 0 } { append cmdline "$inp\n" }
+    if { $numout > 0 } { append cmdline "$outp\n" }
+
+    append cmdline $endcmdline
+
+    return $cmdline
+}
+# ----------------------------------------------------------------------------------------------------------------
+itcl::body bis_algorithm::ShowCommandLine { } {
+
+    pxtkconsole
+
+    pxtkprint "\n--------------------------------------------\n\nCOMMAND LINE PROCEDURE\n---------------------- \n"
+    pxtkprint "To perform this procedure on the command line type:\n\n"
+
+    set cmdlong [ $this GetCommandLine full ]
+    set cmdshort [ $this GetCommandLine short ]
+
+    pxtkprint "\nFull Version\n\t $cmdlong\n\n"
+
+    pxtkprint "\nShort Version (not setting default arguments)\n\t $cmdshort\n\n"
+
+    pxtkprint "\n\n"
+
+}
+
+itcl::body bis_algorithm::ShowLongDescription { } {
+
+    pxtkconsole
+
+    pxtkprint "\n--------------------------------------------\n\n\n\nLONG Description\n---------------------- \n"
+
+    pxtkprint "[ $this GetSynopsis 0]\n\n "
+    pxtkprint "[ $this GetDetailDescription 0 ]\n "
+    pxtkprint "\n"
+
+}
+
+
+itcl::body bis_algorithm::InvokeAlgorithmFromGUI { } {
+
+    if { $callbackbefore !=0 } {
+	# this is a hook from master object to set filenames  if needed
+	eval $callbackbefore
+    }
+
+    # Update Values from GUI
+    set names [array names OptionsArray]
+    foreach name $names {
+	set opt $OptionsArray($name)
+	$opt UpdateFromGUI
+    }
+
+    $this UpdateOutputFilenames
+    if { $directinputs != "" } {
+	$InputsArray($directinputs) UpdateObjectListFromGUI
+    }
+
+
+    set ret [ $this CheckInputObjects ] 
+    if { $ret == 0 } {
+	tk_messageBox -type ok -message "Failed to execute [ $this GetGUIName ] ... bad inputs" -title "Error!" -icon error
+	return 0
+    }
+    
+    $this WatchOn
+    set ret [ $this Execute ]
+    $this WatchOff
+    if { $ret == 0 } {
+	tk_messageBox -type ok -message "Failed to execute [ $this GetGUIName ] ... something is wrong with the options" -title "Error!" -icon error
+	return 0
+    }
+
+    $this UpdateContainerWithOutput
+    if { $callbackafter !=0 } {
+	eval $callbackafter 
+    }
+
+    if { [ $OptionsArray(slicermode) GetValue ] > 0 } {
+	puts stderr "Slicermode is not zero ... [ $OptionsArray(slicermode) GetValue ] saving\n"
+	$this SaveObjects 
+    }
+
+    PrintDebug "\n\n\n\n Done Callback After $this"
+
+    if { $hasoutputguis == 1 } {
+	PrintDebug "Updating Outputs" 
+
+	foreach name [ array names OutputsArray ] {
+	    
+	    $OutputsArray($name) UpdateInternalGUI 
+#	    set gui [ $OutputsArray($name) GetObjectGUI ]
+#	    if { $gui !=0  } {
+#		set obj [ $OutputsArray($name) GetObject ]
+#		$gui SetObject $obj
+#		$gui Update
+#	    } else 
+	}
+    }
+    PrintDebug "\n\n\n\n Done Invoke Algorithm From GUI $this"
+    return 1
+}
+
+itcl::body bis_algorithm::InitializeFromContainer { cont { eventcont 0 } } {
+
+    $this SetGUIMode managed
+    $this SetContainer $cont
+
+    set ok [ $this CreateVTKObjects  ]
+    #    puts stderr "[ $this info class ] Initializing from Container $cont, $ok"
+
+    PrintDebug "Outputs Ok=$ok"
+
+    set eventcontainerobject $eventcont
+    PrintDebug "Inputs Ok=$ok"
+
+
+
+}
+
+itcl::body bis_algorithm::InitializeStandalone { } {
+
+    $this SetGUIMode standalone
+    set ok [ $this CreateVTKObjects  ]    
+    PrintDebug "Inputs Ok=$ok ($ok)"
+    return $ok
+}
+
+itcl::body bis_algorithm::InitializeTesting { { dogui 0 }  } {
+
+    if { $dogui == 0 } {
+	$this SetGUIMode commandline
+	set ok [ $this CreateVTKObjects  ]    
+	return $ok
+    } 
+
+    set ok [ $this InitializeStandalone ]
+    return $ok
+}
+
+#-------------------------------------------------------------------------
+# Stuff for testing
+#-------------------------------------------------------------------------
+
+itcl::body bis_algorithm::LoadTestFileName { fname { lineno -1 } } {
+
+    if { [ file  exists $fname ] ==0 } {
+	puts stderr "$fname not found"
+	return 0
+    }
+
+    set myclassname [ string range  [ $this info class ] 2 end ]
+    #    puts stderr "Myclassname is $myclassname "
+
+    set outlist ""
+
+    set fileid [open $fname r]
+    set lcount 0
+    while { [ gets $fileid line ] >=0 } {
+	if { [ string first "#" $line ] !=0 } {
+	    
+	    set lst  [ split $line : ]
+	    set n    [ llength $lst ]
+	    if { $n == 4 } {
+		set nlist [ list  [ string trim [ lindex $lst 1 ]] [ string trim [ lindex $lst 2 ]] [ string trim [ lindex $lst 3 ] ] "([file tail $fname]:L$lcount)" ]
+		set algname [ string trim [ lindex $lst 0 ] ]
+
+		if { ( $lineno < 0 ) || ( $lineno == $lcount ) } {
+		    if { $algname ==  $myclassname } {
+			lappend outlist $nlist
+		    } elseif { [ file rootname $algname ]  ==  $myclassname } {
+			lappend outlist $nlist
+		    }
+		}
+	    } else {
+		puts stderr "Bad Line *$line*, $n !=4 parts, line number=$lcount"
+	    }
+	}
+	incr lcount
+    }
+    close $fileid
+    return $outlist
+}
+
+# ---------------------------------------------------
+itcl::body bis_algorithm::DualPrint { line { fout 0 } { usescriptname 1 } } {
+
+    if { $usescriptname > 0 } {
+	puts stdout "${scriptname}:$line"
+    } else {
+	puts stdout "$line"
+    }
+    if { $fout !=0 } {
+	puts $fout $line
+    }
+}
+# ---------------------------------------------------
+itcl::body bis_algorithm::ReformatTestLine { line { extra "" } } {
+    set ttline ""
+    for { set i 0 } { $i < [ llength $line ] }  { incr i } {
+	append ttline [ lindex $line $i ]
+	if { $i == 0 && [ string length $extra ] > 1 } {
+	    append ttline "($extra)"
+	}
+	if { $i < [ expr [ llength $line ] -2 ] } {
+	    append ttline " : "
+	} else {
+	    append ttline " "
+	}
+    }
+    return $ttline
+}
+
+# ---------------------------------------------------------------------------------------------------------------
+itcl::body bis_algorithm::DoTestComparison { alg comparenames { fout 0  }  { ctestcreategold 0 } } {
+
+    set finalstatus 1
+
+    for { set i 0 } { $i < [ llength $comparenames ] } { incr i } {
+	
+	set obj [ $alg GetOutputObjectByIndex $i ]
+	set n   [ $alg GetOutputObjectNameByIndex $i ]
+	set outputobj [ lindex $comparenames $i ]
+	if { [ $obj isa pxitclimage ] || [ $obj isa pxitclsurface ] } {
+	    if { [ $alg GetOptionValue ctestexact ] ==1 } {
+		set ok [ $obj  CompareTo $outputobj  [ $alg GetOptionValue ctestthr ] ]
+	    } else {
+		set ok [ $obj  CorrelateWith $outputobj  [ $alg GetOptionValue ctestthr ] ]
+	    }
+	} else {
+	    set ok [ $obj  CompareTo $outputobj [ $alg GetOptionValue ctestthr ] ]
+	}
+	
+	set textst ""
+	if { [ llength $ok ] > 1 } {
+	    set textst [ lindex $ok 1 ]
+	    set ok [ lindex $ok 0 ]
+	}
+	
+	if { $ok == 0 } {
+	    $this DualPrint "-\t Failed comparison of output $n with  [ lindex $comparenames $i ] ($textst)" $fout
+	    if { $ctestcreategold > 0 } {
+		$this DualPrint "\t\t ****************** Overwriting [ lindex $comparenames $i ] with output"
+		$obj SetFileName  [ lindex $comparenames $i ] 
+		set okk [ $obj Save "" "Saving Fixed Result" ]
+		$this DualPrint "\t\t ****************** Overwriting [ lindex $comparenames $i ] with output done=$okk"
+	    }
+	    set i [ llength $comparenames ]
+	    set finalstatus 0
+	} else {
+	    if { [ file tail [ lindex $comparenames $i ] ] != "do_not_use" } {
+		$this DualPrint "+\t Succesful comparison of output $n with  [ lindex $comparenames $i ] ($textst)" $fout
+	    }
+	}
+
+	if { [ $alg GetOptionValue ctestsave  ] > 0 } {
+           $this DualPrint "+ Saving outputs ....." $fout
+           set ok [ $alg SaveObjects [ $alg GetOptionValue ctesttmpdir ] ]
+           if { $ok == 1 } {
+               $this DualPrint "+ [ $alg GetResultsMessage ]"
+           } else {
+               $this DualPrint "+ [ $alg GetErrorMessage ]"
+           }
+	}
+    }
+    
+    $this DualPrint "+"
+    return $finalstatus
+}
+# ---------------------------------------------------------------------------------------------------------------
+itcl::body bis_algorithm::DoTestGUIComparison { alg comparenames { fout 0  }  { ctestcreategold 0 } } {
+
+    set finalstatus 1
+
+    set img [ $alg GetBisViewerImage ]
+    if { $img == "0" } {
+	return 0
+    }
+
+    set obj [ [ pxitclimage \#auto ] GetThisPointer ]
+    $obj ShallowCopyImage $img
+    $img Delete
+    set compimagename [ lindex $comparenames 0 ]
+	
+    if { [ $alg GetOptionValue ctestexact ] ==1 } {
+	set ok [ $obj  CompareTo $compimagename  [ $alg GetOptionValue ctestthr ] ]
+    } else {
+	set ok [ $obj  CorrelateWith $compimagename  [ $alg GetOptionValue ctestthr ] ]
+    }
+
+    set textst ""
+    if { [ llength $ok ] > 1 } {
+	set textst [ lindex $ok 1 ]
+	set ok [ lindex $ok 0 ]
+    }
+    
+    if { $ok == 0 } {
+	$this DualPrint "-\t Failed comparison of viewer image with  $compimagename ($textst)" $fout
+	if { $ctestcreategold > 0 } {
+	    $this DualPrint "\t\t ****************** Overwriting $compimagename with viewer image"
+	    set tplist { {"PNG Images" { .png }} }
+	    set fname  [tk_getSaveFile -title "Saving $compimagename " -filetypes $tplist -initialfile [ file tail $compimagename ]  -initialdir [ file dirname $compimagename  ]  ]
+	    if { [ string length $fname ] > 0 } {
+		set w [ vtkPNGWriter New ]
+		$w SetInput [ $obj GetImage ]
+		$w SetFileName $compimagename
+		$w Write
+		$w Delete
+	    } 
+	    $this DualPrint "\t\t ****************** Overwriting $compimagename with viewer image done=[ file size $compimagename ]"
+	}
+	set finalstatus 0
+    } else {
+	$this DualPrint "+\t Succesful comparison of viewer output with  [ lindex $comparenames 0 ] ($textst)" $fout
+    }
+    
+    if { [ $alg GetOptionValue ctestsave  ] > 0 } {
+	set dr  [ $alg GetOptionValue ctesttmpdir ] 
+	set fn  [ file join $dr [ pid ].png ]
+	set w [ vtkPNGWriter New ]
+	$w SetInput [ $obj GetImage ]
+	$w SetFileName $fn
+	$w Write
+	$w Delete
+	$this DualPrint "\t\t ****************** Saving Viewer Output in $fn done=[ file size $compimagename ]"
+    }
+
+    itcl::delete obj $obj
+    return $finalstatus
+}
+
+# ---------------------------------------------------------------------------------------------------------------
+itcl::body bis_algorithm::RemoveTempOutputDirectory { odir } {
+
+    set ok 0
+    catch { 
+	file delete -force $odir 
+	set ok 1
+    }
+    return $ok
+
+}
+
+# ---------------------------------------------------------------------------------------------------------------
+
+itcl::body bis_algorithm::CreateTempOutputDirectory { odir } {
+
+    set tmpdir $odir
+
+    if { [ file tail $tmpdir ] == "BIOIMAGESUITE3_TESTING_TEMPDIR-NOTFOUND" } {
+	set tmpdir ""
+    }
+    
+    set processid [ pid ]
+    if { [ string length $tmpdir ] > 1 } {
+	if { [ file exists $tmpdir ] == 0 } {
+	    set tmpdir ""
+	} elseif { [ file writable [ file join $tmpdir $processid ] ] == 0 } { 
+	    set tmpdir ""
+	}
+    }
+
+    #    puts stdout "sofar =  $tmpdir"
+
+    if { [ string length $tmpdir ] <  1 } {
+	global env
+	catch { set tmpdir $env(BISTEMP) }
+	set ot [ file tail $tmpdir ]
+
+	#puts stdout "sofar tmpdir=*${tmpdir}* ot=*${ot}*"
+	if { $ot == "" || $ot == "\"\"" } {
+	    global tcl_platform
+	    puts stdout "Using default output directory ..... as *$ot* *$tmpdir*"
+	    if { $tcl_platform(platform) == "windows" } { 
+		set tmpdir c:/temp
+	    } else {
+		set tmpdir /tmp
+	    }
+	}
+    }
+
+    set tmpdir [ file normalize [ file join $tmpdir tmp_$processid ] ]
+    catch { file mkdir $tmpdir }
+    puts stdout "Using temp tmpdir=$tmpdir\n\n\n"
+    return $tmpdir
+}
+
+# ------------------------------------------------------------------------------------------------------------------------
+
+itcl::body bis_algorithm::RunTest { testline basedir { fout 0 } { extra "" } { ctestcreategold 0 } } {
+
+    cd $basedir
+
+    $this DualPrint  "\#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n+" $fout
+
+    global tcl_platform
+    
+    set m0 $tcl_platform(user)
+    set m1 $tcl_platform(os)
+    set m2 $tcl_platform(osVersion)
+    set m3 [ file normalize  [ info nameofexecutable ] ]
+
+    $this DualPrint "+" $fout
+    $this DualPrint  "+ $m0 on [ info hostname ] $m1, $m2 using $m3" $fout
+    $this DualPrint "+" $fout
+    $this DualPrint "+ I n v o k i n g   T e s t = [ $this ReformatTestLine $testline $extra]"  $fout
+    $this DualPrint "+" $fout
+    set myclassname [ string range  [ $this info class ] 2 end ]
+    set alg [ $myclassname \#auto ]
+    #    $this DualPrint "+Created $alg of type [ $alg info class  ]" $fout
+
+    set paramnames [ lindex $testline 0 ]
+    set inputnames ""
+    set tmp [  lindex $testline 1 ]
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend inputnames [ file normalize [ file join $basedir [ lindex $tmp $i ] ] ]
+    }
+    set tmp [  lindex $testline 2 ]
+    set comparenames ""
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend comparenames [ file normalize [ file join $basedir [ lindex $tmp $i ] ] ]
+#	puts stdout "Adding   $basedir, [ lindex $tmp $i ] "
+    }
+    
+    set paramnames [ concat $paramnames $extra ]
+    $this DualPrint "+Inputs=*$inputnames*\tCompare=*$comparenames*\t+params=*$paramnames* (extra=$extra)" $fout
+    $this DualPrint "+" $fout
+    set fnd [ lsearch -regexp $paramnames "-*ctestgui" ]
+    set dogui 0
+    if { $fnd > -1 } {
+	set dogui [ expr [ lindex $paramnames [ expr $fnd +1 ] ] > 0 ]
+	#	puts stdout "Testing in GUI Mode! $dogui, $fnd"
+	if { $dogui > 0 } {
+	    $this SetOptionValue ctestgui 1
+	}
+    }
+
+    
+
+    $alg InitializeTesting $dogui
+    set tp 0
+
+    for { set i 0 } { $i < [ llength $paramnames ] } { incr i } {
+	
+	set pn [ lindex $paramnames $i ]
+	if { [ string first "--"  $pn  ] == 0 } {
+	    set pn [ string range $pn 2 end ]
+	} elseif { [ string first "-"  $pn  ] == 0 } {
+	    set pn [ string range $pn 1 end ]
+	}
+
+	set optionname $pn
+	incr i 
+	set optionvalue [ lindex $paramnames $i ]
+	set tp [ lindex [ $alg GetOptionType $optionname ] 0 ]
+	if { $tp == "filename" } {
+	    set optionvalue [ file normalize [ file join $basedir $optionvalue ]]
+	}
+	$alg SetOptionValue $optionname $optionvalue
+    }
+    $alg SetInputArrayFilenames  $inputnames
+
+    
+
+
+    $alg LoadObjects
+    set temptoplevel 0 
+    if { $dogui == 1 } {
+	set temptoplevel [ toplevel .[ pxvtable::vnewobj ] ]
+	$alg CreateGUI $temptoplevel 0 0 1
+	wm geometry $temptoplevel 600x600
+	wm title $temptoplevel "BioImage Suite::[ $alg GetGUIName ] Applet Running in Testing Mode"
+    }
+
+    $this DualPrint "+ [ $alg GetCommandLine full ]" $fout
+    $this DualPrint "+" $fout
+
+    set tstart [ clock clicks -milliseconds ]
+
+    if { $dogui == 1 } {
+	set ok [ $alg InvokeAlgorithmFromGUI ]
+    } else {
+	set ok [ $alg Execute ]
+    }
+    set tend [ clock clicks -milliseconds ]
+
+    $this DualPrint "+ Algorithm execution = $ok ([ expr 0.001*($tend-$tstart) ]s)" $fout
+    $this DualPrint "+" $fout
+
+    if { $dogui == 1 } {
+	update idletasks
+	after 1000
+    }
+
+    # Modify this to compare multiple outputs if need be
+    set finalstatus 1
+
+    if { $ok == 1 } {
+	if { $dogui == 0 } {
+	    set finalstatus [ $this DoTestComparison $alg $comparenames $fout $ctestcreategold ]
+	} else {
+	    set finalstatus [ $this DoTestGUIComparison $alg $comparenames $fout $ctestcreategold ]
+	}
+    } else {
+	set finalstatus 0
+    }
+
+    
+    if { $temptoplevel > 0 } {
+	wm withdraw $temptoplevel
+	destroy $temptoplevel
+    }
+    itcl::delete object $alg 
+    
+    return [ list $finalstatus [ expr $tend-$tstart ]]
+
+}
+# ---------------------------------------------------
+
+itcl::body bis_algorithm::RunRegressionTests { messyfname args } {
+
+    set extraparams ""
+    set debug 0
+    set debugname ""
+    set ctestline -1
+    set ctestcreategold 0
+
+    if { $args != "" } {
+	set tmp [ lindex $args 0 ]
+#	puts stdout "Scanning $tmp"
+	set l [ expr [ llength $tmp ] -1 ]
+	for { set i 0 } { $i < $l } { set i [ expr $i+2 ] } {
+	    set pn [ lindex $tmp $i ]
+	    set v  [ lindex $tmp [ expr $i +1 ] ]
+
+	    if { [ string first "--"  $pn  ] == 0 } {
+		set pn [ string range $pn 2 end ]
+	    } elseif { [ string first "-"  $pn  ] == 0 } {
+		set pn [ string range $pn 1 end ]
+	    }
+	    
+	    set ind  [ lsearch -exact $ctestextraflags $pn ] 
+	#    puts stdout "Looking for $pn in $ctestextraflags, ind=$ind"
+	    if { $ind > -1 } {
+		if { [ $OptionsArray($pn) GetDefaultValue ] != $v  } {
+		    lappend extraparams $pn
+		    lappend extraparams $v
+		    #puts stdout "Appending $pn $v"
+		}
+	    } elseif { $pn == "ctestdebug" } {
+		if { [ string length $v ] > 1 } {
+		    set debug 1
+		    set debugname $v
+		}
+	    } elseif { $pn == "ctestline" } {
+		if { [ string length $v ] > 0 } {
+		    set ctestline $v
+		}
+	    } elseif { $pn == "ctestcreategold" } {
+		if { [ string length $v ] > 0 } {
+		    if { $v == "9999" } {
+			set ctestcreategold 1
+		    }
+		}
+	    }
+	}
+    }
+
+    if { $ctestline ==-1 } {
+	set ctestcreategold 0
+    }
+#    puts stdout "CtestLine = $ctestline "
+
+    # Keep this 0
+
+
+    set fname [ file rootname $messyfname ]
+    set ext   [ file extension $messyfname ]
+
+    if { $ext == "." } {
+	set ext ".OFF"
+    } elseif { $ext != ".ON" && $ext != ".OFF" } {
+	set fname $messyfname
+	set ext ".OFF"
+    }
+
+    set tlist [ $this LoadTestFileName $fname $ctestline ]
+    if { $tlist == 0 } {
+	return 0
+    } 
+
+    # Switch to the directory of the tests to allow for more non-absolute paths
+    set basedirectory [ file normalize  [ file dirname $fname ] ]
+#    puts stdout "Tests loaded from $fname, base=$basedirectory"
+  
+
+    set oklist ""
+    if { $debug == 1 } {
+	set fout [ open $debugname a ]
+	$this DualPrint "*\n*\n*\n\#-------------------------------------------------------------------------------------------\n\#" $fout
+	$this DualPrint "\# S T A R T I N G    N E W   M O D U L E    T E S T : $scriptname\n\#" $fout
+	set f  [ clock format [ clock seconds ] -format "%d %b %Y at %H:%M:%S" ]
+	$this DualPrint  "\#Debug output from  [ string range  [ $this info class ] 2 end ], [  info script ] ($f) ctestline=$ctestline" $fout
+    } else {
+	set fout 0
+    }
+
+    set allok 1
+
+    set statuslist ""
+
+    if { [ llength $tlist ] == 0 } {
+	$this DualPrint "No tests for me" $fout
+	if { $ext == ".ON" } {
+	    set allok 0
+	}
+    } else  {
+	for { set i 0 } { $i < [ llength $tlist ] } { incr i } {
+
+	    set passlist [ $this RunTest [ lindex $tlist $i ] $basedirectory $fout $extraparams $ctestcreategold ]
+	    set pass [ lindex $passlist 0 ]
+	    set passtime [ lindex $passlist 1 ]
+	    if { $pass > 0 } {
+		append statuslist "++ [ $this ReformatTestLine [ lindex $tlist $i ] $extraparams ]  ... status = passed ($passtime ms)\n"
+	    } else {
+		append statuslist "-- [ $this ReformatTestLine [ lindex $tlist $i ] $extraparams ]  ... status = failed ($passtime ms)\n"
+	    }
+		
+	    if { $pass == 0 } {
+		set allok 0
+	    }
+	}
+    }
+
+
+    if { $ctestline == -1 } {
+	if { $allok == 1 } {
+	    $this DualPrint "+\n+\n+++++++++++++++++++++++++++++++ All Tests for $scriptname Passed +++++++++++++++++++++++++++++++ " $fout
+	} else {
+	    $this DualPrint "-\n-\n------------------------------- Some Tests for $scriptname Failed ------------------------------- " $fout
+	}
+	
+	$this DualPrint "$statuslist*" $fout 0
+    }
+    if { $fout !=0 } {
+	close $fout 
+    }
+    
+
+    return $allok
+
+}
+
+#-------------------------------------------------------------------------
+# Main Function
+#-------------------------------------------------------------------------
+itcl::body bis_algorithm::StripDashes { val } {
+
+    if { [ string first "--"  $val  ] == 0 } {
+	return [ string range $val 2 end ]
+    }
+
+    if { [ string first "-"  $val  ] == 0 } {
+	return [ string range $val 1 end ]
+    }
+
+    return 0
+}
+
+itcl::body bis_algorithm::ProcessCommandline { argv { debug 0 } } {
+
+    set lst [$this GetCmdLineOptionsList]
+
+    set knownlist ""
+    set errormessage ""
+    foreach it $lst { 
+	set sw [ file rootname [ lindex $it 0 ] ]
+	set value($sw) [ lindex $it 1 ]
+	set default($sw) [ lindex $it 1 ]
+	lappend knownlist $sw
+    }
+
+
+    set len [ llength $argv ] 
+    set lenm [ expr $len -1 ]
+    set i 0
+    set done 0 
+    while { $i < $lenm && $done == 0 } {
+	set opt [ $this StripDashes [ lindex $argv $i ] ]
+	set found -1
+	if { $opt !=0 } {
+	    set found [ lsearch $knownlist $opt ]
+	    if { $found > -1 } {
+		
+		# Increase i and get argument
+		incr i
+		set val [ lindex $argv $i ]
+		set value($opt) $val
+
+		if { $debug > 0 } {
+		    puts stdout "\t\t value($opt) = $val"
+		}
+		
+		# Increase i again and see if there is anything to be found (multi length args)
+		incr i
+	    } else {
+		set errormessage "unknown option $opt"
+		set done -1
+	    }
+	} else {
+	    set done 1
+	}
+    }
+
+
+    if { $done !=- 1 } {
+	if { $debug > 0 } {
+	    foreach q $knownlist {
+		puts stdout "option $q, val= ( $value($q) ), default=( $default($q) )"
+	    }
+	}
+	set extra [ lrange $argv $i end ]
+	set f [ list [ array get value ] $extra ]
+	if { $debug > 0 } {
+	    puts stdout "f(0) = [ lindex $f 0 ]"
+	    puts stdout "f(1) = [ lindex $f 1 ]"
+	}
+	return $f
+    }
+
+    return [ list 0 $errormessage ]
+}
+
+#-------------------------------------------------------------------------
+# Define the error function
+#----------------------------------------------------
+
+itcl::body bis_algorithm::MainFunction { } {
+
+    global argv
+    package require vtkpxcontrib
+
+    set n [ llength $argv ]
+    if { $argv == "-help" || $argv == "--help" || $argv == "-h" || $argv == "--h" } {
+	set n 0
+	set forceguimode 0
+    }
+    if { $n == 0 && $forceguimode == 0 } {
+	set ok [$this GetCmdLineOptionsList]
+	$this PrintUsage
+	exit
+    }
+
+    if {  [ lsearch $argv --xml ] > -1 } {
+	set a "[ $this GetSlicerXMLDescription ]"
+	puts stdout $a
+	exit
+    }
+    
+
+    if {  [ lsearch $argv --logo ] > -1 } {
+	puts stdout [ ::bis_common::GetSlicerXMLLogo ]
+	exit
+    }
+
+    if {  [ lsearch $argv --json ] > -1 } {
+	set a "[ $this GetJSONDescription ]"
+	puts stdout "$a"
+	exit
+    }
+    
+
+    set lst [ $this ProcessCommandline $argv ]
+    set v [ lindex $lst 0 ]
+    if { $v == 0 } {
+	$this PrintUsage
+	puts stderr "\n parameter parsing error = [ lindex $lst 1 ]"
+	exit
+    }
+    set parameterlist [ lindex $lst 0 ]
+    set extrafilenames [ lindex $lst 1 ]
+
+    set dogui 0;    set doctest 0 ;    set doloni 0
+
+    if { $forceguimode > 0 } {
+	set dogui 1
+    } else {
+        set found [ lsearch $parameterlist dogui ]
+	if { $found > -1 } {
+	    set indx [ expr $found +1 ]
+	    if { $indx < [ llength $parameterlist ] } {
+		set dogui [ expr [ lindex $parameterlist $indx ] > 0 ]
+	    }
+	} 
+    }
+
+
+    if { $dogui == 0 } {
+	set found [ lsearch $parameterlist loni ]
+	if { $found > -1 } {
+	    set indx [ expr $found +1 ]
+	    if { $indx < [ llength $parameterlist ] } {
+		set doloni [ lindex $parameterlist $indx ] 
+		if { $doloni != 1 && $doloni !=2 } {
+		    set doloni 0
+		}
+	    }
+	}
+    }
+    
+    if { $dogui == 0 && $doloni == 0 } {
+	set found [ lsearch -exact $parameterlist ctest ]
+	if { $found > -1 } {
+	    set indx [ expr $found +1 ]
+	    if { $indx < [ llength $parameterlist ] } {
+		set ctestfname [  lindex $parameterlist $indx ]
+		if { $ctestfname != 0 } {
+		    set doctest 1
+		}
+	    }
+	}
+    }
+
+
+    package require pxtcluserprefs 1.0
+    set version $::pxtclvtkpxcontrib::version
+
+
+    
+    if { $dogui == 0 && $doctest == 0 && $doloni == 0 } {
+	if { [ $OptionsArray(slicermode) GetValue ] > 0 } {
+	    puts stdout "Called from slicer [ $this GetCommandLine full ]"
+	}
+	wm withdraw .
+	$this RunCommandLine $parameterlist  $extrafilenames
+	pxtkexit
+    } elseif { $doloni > 0 } {
+	puts stdout "[ $this GetLONIXMLDescription $doloni ]"
+	pxtkexit
+    } elseif { $doctest == 1 }  {
+	wm withdraw .
+	set ok [ $this RunRegressionTests $ctestfname $parameterlist ]
+	# our codes and unix codes are inverted!
+	set ctestgui [ $this GetOptionValue ctestgui ]
+	puts stdout "${scriptname}:+\n${scriptname}:+ Test finished ok=$ok ctestgui=$ctestgui"
+
+	if { $ok == 0 } {
+	    if { $ctestgui == 0 } {
+		exit 1
+	    } else {
+		update idletasks
+		destroy .
+		after idle exit 1
+	    }
+	} elseif { $ctestgui == 0 } {
+	    exit 0
+	} else {
+	    update idletasks
+	    destroy .
+	    after idle exit 0
+	}
+    } else {
+	package require pxappscommon 
+	set tp [ toplevel .[ pxvtable::vnewobj ] ]
+	$this InitializeStandalone 
+	set ret [ $this SetParameters $parameterlist ]
+	if { $ret == 0 } {
+	    $this PrintUsage; 
+	    puts stderr "\n\n The following error has occurred: $errormessage\n"  
+	    exit 1
+	}
+
+	set ret [ $this SetInputArrayFilenames  $extrafilenames ] 
+
+	$this LoadObjects 
+	$this CreateGUI $tp
+	$this UpdateInputsFromContainer 
+
+
+	if { [ $OptionsArray(slicermode) GetValue ] == 0 } {
+	    wm title $tp "BioImage Suite::[ $this GetGUIName ] Applet"
+	} else {
+	    wm title $tp "BioImage Suite::[ $this GetGUIName ] Applet -- called from Slicer"
+	}
+
+	if { [ $this GetViewer ] ==0 } {
+	    wm geometry $tp 500x600
+	} elseif { $forceguimode == 0 } { 
+	    wm geometry $tp 1024x600
+	}
+	update idletasks
+    }
+}
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_algorithmdbaseinterface.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_algorithmdbaseinterface.tcl
new file mode 100644
index 0000000..97fce14
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_algorithmdbaseinterface.tcl
@@ -0,0 +1,500 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_algorithmdbaseinterface 1.0
+
+package require Itcl 3.2
+package require Iwidgets 
+package require vtkpxcontrib  1.1
+
+# This loads the database library
+pxtclvtkpxcontrib::LoadLibraries { vtkbisDatabaseTCL }
+
+
+itcl::class bis_algorithmdbaseinterface {
+    private common    thisparam
+    protected variable basewidget 0
+    protected variable dbase      0
+    protected variable connector  0
+    protected variable algorithm  0
+    protected variable algorithmname ""
+    protected variable querybox   0
+    protected variable dialogmode 0
+    protected variable notebook   0
+
+    
+    constructor { } { $this Initialize }
+    destructor  { }
+
+    # This pointer
+    public method GetThisPointer { } { return $this }
+
+    # Algorithm Stuff
+    public method SetAlgorithm { a } { }
+    public method GetAlgorithm { } { return $algorithm }
+    public method UpdateFromAlgorithm { } 
+
+    # GUI Stuff
+    public method Reset { { ask 0 } }
+    public method CreateGUI { base { dlg 0 } }
+    public method QueryEntryGUI { mode }
+    public method AddEntryGUI { }
+    public method HandleSelect { mode }
+    public method ShowWindow { md }
+    public method HideWindow { }
+    public method PrintTable { }
+    public method SetSQLDebugMode { }
+    public method ClearTable { }
+
+    # Initialize Code
+    protected method Initialize { }
+    
+    # Public Methods for handling dbase
+    public method Connect    { { sqlitefile "" } }
+    public method Disconnect { }
+    public method AddEntry { name description }
+    public method FindPreset { psetname }
+
+};
+
+# -------------------------------------------------------------------------------------------
+# Initialize 
+# -------------------------------------------------------------------------------------------
+itcl::body bis_algorithmdbaseinterface::Initialize { } {
+
+    $this Reset 0
+    set thisparam($this,algorithname) "Alg: None"
+    set thisparam($this,dbasefilename) "Dbase: Not Connected"
+    set thisparam($this,debugdbase)    0
+    set thisparam($this,connected)     0
+    $this Connect 
+}
+# -------------------------------------------------------------------------------------------
+
+itcl::body bis_algorithmdbaseinterface::Reset { {  ask 0 } } {
+    if { $ask == 1 } {
+	set ok [ tk_messageBox -type yesno -message "Reseting filenames" -icon question ]
+	if { $ok == "no" } { return }
+    }
+
+    if { $ask !=2 } {
+	set thisparam($this,addname) ""
+	set thisparam($this,adddesc) ""
+    }
+
+    set thisparam($this,queryname) ""
+    set thisparam($this,querydesc) ""
+    set thisparam($this,querydate) ""
+    set thisparam($this,queryparam) ""
+
+}
+
+itcl::body bis_algorithmdbaseinterface::SetAlgorithm { a } { 
+
+    set algorithm $a
+
+    set tmp [ string range  [ $algorithm info class ] 2 end ]
+    set algorithmname  $tmp
+    set thisparam($this,algorithmname)  "Alg: [ $algorithm GetGUIName ] ($algorithmname)"
+
+
+    if { $basewidget !=0 } {
+	return [ $this QueryEntryGUI all ]
+    }
+    return 1
+
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_algorithmdbaseinterface::UpdateFromAlgorithm { }  {
+
+    set v [ $algorithm GetOptionValue "pset" ] 
+    set thisparam($this,addname) ""
+    set thisparam($this,adddesc) ""
+
+    if { [ string length $v ] < 1 } {
+	return
+    }
+    
+    set l [ split $v "," ]
+
+    set thisparam($this,addname) [ lindex $l 0 ]
+    if { [ llength $v ] > 1 } {
+	set thisparam($this,adddesc) [ lindex $l 1 ]
+    }
+
+}
+
+# -------------------------------------------------------------------------------------------
+#   GUI Stuff
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_algorithmdbaseinterface::ShowWindow { md } {
+
+    if { $dialogmode == 0 || $basewidget == 0 } {
+	return 
+    }
+
+
+#    puts stderr "md=$md"
+    if { $md == "store" } {
+	set md 1
+    } else {
+	set md 0
+    }
+    $notebook view $md
+    
+    
+
+    if { [ winfo ismapped $basewidget ] == 1 } {
+	wm withdraw $basewidget
+    }
+    wm deiconify $basewidget
+    return $basewidget
+}
+# ----------------------------------------------------------
+::itcl::body bis_algorithmdbaseinterface::HideWindow { } {
+
+    if { $dialogmode == 0 || $basewidget == 0 } { return }
+    catch { wm withdraw $basewidget }
+}
+# ----------------------------------------------------------
+itcl::body bis_algorithmdbaseinterface::CreateGUI { base { dlg 0 } } {
+
+    if { $basewidget !=0 } {
+	return $basewidget
+    }
+
+
+    if { $dlg == 1 } {
+	set basewidget [ toplevel $base.[pxvtable::vnewobj ] ]
+	wm withdraw $basewidget
+	wm title $basewidget "Parameter Query Tool"
+	wm geometry $basewidget 500x400
+	set dialogmode 1
+    } else {
+	set basewidget $base
+	set dialogmode 0
+    }
+
+
+    set nt [ iwidgets::tabnotebook $basewidget.[ pxvtable::vnewobj ]  -tabpos n ]
+    set notebook $nt
+    pack $nt -side top -expand true -fill both -pady 1
+    # Page Query
+    # ----------------------------------------------------------------------
+    set page [ $nt add -label "Query Database"]
+    
+    iwidgets::entryfield $page.1 -labeltext "Preset Name:" -textvariable [ itcl::scope thisparam($this,queryname) ]
+    iwidgets::entryfield $page.2 -labeltext "Description:" -textvariable [ itcl::scope thisparam($this,querydesc) ]
+    iwidgets::entryfield $page.3 -labeltext "Date:" -textvariable [ itcl::scope thisparam($this,querydate) ]
+    iwidgets::entryfield $page.4 -labeltext "Parameters:" -textvariable [ itcl::scope thisparam($this,queryparam) ]
+    pack $page.1  $page.2 $page.3 $page.4 -side top -expand false -fill x
+    iwidgets::Labeledwidget::alignlabels $page.1 $page.2 $page.3 $page.4
+    
+    iwidgets::buttonbox $page.btop 
+    eval "$page.btop add querybtn -text \"Search for Param. Set\" -command { $this QueryEntryGUI search }"
+    eval "$page.btop add showbtn  -text \"Show All\" -command { $this QueryEntryGUI all }"
+    eval "$page.btop add clearbtn  -text \"Clear Entries\" -command { $this Reset 2 }"
+    pack $page.btop -expand false -fill x -side top
+
+    iwidgets::buttonbox $page.bb2
+    pack $page.bb2 -side bottom -expand false -fill x -padx 10 -pady 2
+
+    eval "$page.bb2 add 1 -text \" Select\"        -command  { $this HandleSelect 0 }"
+    eval "$page.bb2 add 2 -text \" Set Algorithm\" -command  { $this HandleSelect 1 }"
+
+    
+    iwidgets::scrolledlistbox $page.slb -vscrollmode dynamic -selectmode single 
+    pack $page.slb -expand yes -fill x -side top
+    $page.slb insert 0 ""
+    set querybox $page.slb
+
+   
+    $nt view "Query Database"
+
+
+    # -------------------------------------------------------------------
+    set page [ $nt add -label "Store Current Parameters"]
+        
+    
+    label $page.0   -text "Please do not use commas \",\" as part of the name or the description" -bg black -fg white
+    pack $page.0 -side top -expand false -fill x
+    iwidgets::entryfield $page.name -labeltext "Preset Name:"  -textvariable [ itcl::scope thisparam($this,addname) ]
+    iwidgets::entryfield $page.addr -labeltext "Description:" -textvariable [ itcl::scope thisparam($this,adddesc) ]
+    pack $page.name $page.addr -side top -expand false -fill x
+    iwidgets::Labeledwidget::alignlabels $page.name $page.addr
+    iwidgets::buttonbox $page.bb 
+    eval "$page.bb add OK -text \"Store Current Param. Set\" -command { $this AddEntryGUI }"
+    pack $page.bb -expand false -fill x -side bottom
+
+
+    # -------------------------------------------------------------------
+    set bot [ $nt add -label "Debug"]
+
+    frame $bot.1
+    frame $bot.3
+    entry $bot.1.1 -width 30  -textvariable [ itcl::scope thisparam($this,algorithmname) ] -relief sunken  -bg black -fg white 
+    entry $bot.1.2 -width 30  -textvariable [ itcl::scope thisparam($this,dbasefilename) ] -relief sunken  -bg black -fg white 
+    pack $bot.1 $bot.3 -side top -expand false -fill x
+    pack $bot.1.1 $bot.1.2 -side top -expand true -fill x -padx 0
+
+    eval "checkbutton $bot.3.1 -variable [ itcl::scope thisparam($this,debugdbase)  ] -text \"Debug SQL\" -command { $this SetSQLDebugMode }" 
+    eval "button $bot.3.2 -text \"Show Table\" -command { $this PrintTable } -padx 5"
+    eval "button $bot.3.3 -text \"Clear Table\" -command { $this ClearTable } -padx 5"
+    pack $bot.3.1 $bot.3.2 $bot.3.3 -side left -expand false -fill x
+    
+
+    if { $algorithm !=0 } {
+	 $this QueryEntryGUI all 
+    }
+
+    return $basewidget
+}
+# ------------------------- GUI Callbacks ---------------------------------
+itcl::body bis_algorithmdbaseinterface::QueryEntryGUI { mode } {
+    if { $basewidget == 0 } {	return 0  }
+    if { $thisparam($this,connected) == 0 } {	return 0    }
+
+    if { $mode == "all" } {
+	set out [ $dbase QueryAll $algorithmname ]
+	$this Reset 2
+    } else {
+
+	set p1 "%$thisparam($this,queryname)%"
+	set p2 "%$thisparam($this,querydesc)%" 
+	set p3 "%$thisparam($this,querydate)%"
+	set p4 "%$thisparam($this,queryparam)%"
+
+	set out [ $dbase SearchItem $algorithmname $p1 $p2 $p3 $p4 0 ]
+    }
+
+    $querybox delete 0 end 
+    if { $out == "" } {
+	return
+    }
+
+    set lst [ split $out "\n" ]
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	if { $thisparam($this,debugdbase) > 0 } {
+	    puts stdout "Item $i = *[lindex $lst $i ]*"
+	}
+	if { [ string length [ lindex $lst $i ] ] > 2 } {
+	    $querybox insert end [ lindex $lst $i ]
+	}
+    }
+}
+
+itcl::body bis_algorithmdbaseinterface::AddEntryGUI { } {
+    if { $basewidget == 0 } {	return 0  }
+
+    if { $thisparam($this,addname) == "" } {
+	tk_messageBox -type ok -message "Empty name" -title "Failed to Store Preset" -icon error
+	return 0
+    }
+
+    if { $thisparam($this,adddesc) == "" } {
+	set thisparam($this,adddesc) "none" 
+    }
+
+    return [ $this AddEntry  $thisparam($this,addname) $thisparam($this,adddesc) ]
+}
+
+itcl::body bis_algorithmdbaseinterface::HandleSelect { mode } {
+    if { $basewidget == 0 } {	return 0  }
+
+    set test [ $querybox getcurselection]
+
+    set lst [ split $test "," ]
+    set thisparam($this,queryname)  [ lindex $lst 1 ]
+    set thisparam($this,querydesc)  [ lindex $lst 2 ]
+    set thisparam($this,querydate)  [ lindex $lst 3 ]
+    set thisparam($this,queryparam) [ lindex $lst 4 ]
+
+
+    if { $mode == 1 } {
+	$algorithm SetParametersFromString "[ lindex $lst 4 ]"
+	$algorithm SetOptionValue "pset" "[ lindex $lst 1 ],[ lindex $lst 2 ]"
+	$this UpdateFromAlgorithm
+    }
+
+}
+
+# ------------------------- Non GUI Callbacks ---------------------------------
+itcl::body bis_algorithmdbaseinterface::Connect    { { sqlitefile "" } } {
+
+    if { $thisparam($this,connected) == 1 } {	return 0    }
+
+    if { $sqlitefile == "" } {
+	global env
+	set fn ".bioimagesuite3"
+	catch { set fn $env(BIODBASE) }
+	set fn [ file join $env(HOME) $fn ]
+    } else {
+	set fn $sqlitefile
+    }
+    set connector [ vtkbisDatabase New ]
+    $connector InitializeSQLite "$fn" 
+    set ok [ $connector Connect ]
+
+    if { $ok < 1 } {
+	$connector Delete
+	return 0
+    }
+
+    set thisparam($this,dbasefilename) "Dbase: $fn"
+    if { $thisparam($this,debugdbase) > 0 } {
+	$connector DebugOn
+    } else {
+	$connector DebugOff
+    }
+    set thisparam($this,connected) 1
+
+    set dbase [ vtkbisAlgorithmTable New ]
+    $dbase SetConnector $connector
+    $dbase CreateTable
+    return 1
+}
+
+itcl::body bis_algorithmdbaseinterface::Disconnect { } {
+
+    if { $thisparam($this,connected) == 1 } {
+	return 0
+    }
+    
+    catch { $connector Disconnect }
+    set thisparam($this,connected) 0
+    set thisparam($this,dbasefilename) "Dbase: Not Connected"
+}
+
+itcl::body bis_algorithmdbaseinterface::AddEntry { name description } { 
+
+    if { $thisparam($this,connected)  == 0 } {
+	puts stderr "Not Connected to base"
+	return 0
+    }
+
+    set p(1) $algorithmname
+    set p(2) $name
+    set p(3) $description
+    set p(4) [  clock format [ clock seconds ] ]
+    set p(5) [ $algorithm GetCommandLine paramset ]
+
+    set txt [ $dbase SearchItem $p(1) $p(2) "" "" "" 1 ]
+    if { [ string length $txt ] > 0 } {
+	set ok [ tk_messageBox -type yesno -message "There is an existing preset with the same name ($name). Would you like to ovverride this?\n (Full text=$txt) " -icon question ]
+	if { $ok == "no" } {
+	    return 0
+	} else {
+	    $dbase DeleteItem $p(1) $p(2)
+	}
+    }
+
+    for { set i 1 } { $i < 5 } { incr i } {
+	#puts -nonewline stdout "$i\tMapping $p($i) to "
+	regsub -all "," $p($i)  ";" p($i)
+	#	puts stdout "to $p($i)"
+    }
+
+    $dbase AddItem $p(1) $p(2) $p(3) $p(4) $p(5)
+    return [ $this QueryEntryGUI all  ]
+
+}
+
+itcl::body bis_algorithmdbaseinterface::FindPreset { psetname } {
+
+    if { $thisparam($this,connected)  == 0 } {
+	return 0
+    }
+
+    set out [ $dbase SearchItem $algorithmname $psetname "" "" ""   1 ]
+    if { $out == "" } {
+	return ""
+    } 
+    if { $thisparam($this,debugdbase) > 0 } {
+	puts stderr "Search output = *$out*"
+    }
+
+    set lst [ split $out "\n" ]
+    if { $thisparam($this,debugdbase) > 0 } {
+	puts stdout "Returning $lst"
+    }
+
+    set elem [ split [ lindex $lst 0 ] "," ]
+    if { $thisparam($this,debugdbase) > 0 } {
+	puts stderr "Search elem = *$elem*"
+    }
+    
+    set out [ lindex $elem 4 ]
+
+    return $out
+}
+
+# --------------------------------------------------------------------
+
+itcl::body bis_algorithmdbaseinterface::SetSQLDebugMode { } {
+
+    if { $thisparam($this,connected)  == 0 } {
+	return
+    }
+    
+    if { $thisparam($this,debugdbase) > 0 } {
+	$connector DebugOn
+    } else {
+	$connector DebugOff
+    }
+}
+# --------------------------------------------------------------------
+itcl::body bis_algorithmdbaseinterface::PrintTable { } {
+
+    if { $thisparam($this,connected) == 0 } {	return 0    }
+
+    set out [ $dbase QueryAll $algorithmname ]
+
+    set lst [ split $out "\n" ]
+
+    puts stdout "\n\n\n         Whole Table for $algorithmname \n"
+    
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	if { [ string length [ lindex $lst $i ] ] > 1 } {
+	    puts stdout "$i \t *[ lindex $lst $i ]*"
+	}
+    }
+    puts stdout "\n\n"
+}
+
+itcl::body bis_algorithmdbaseinterface::ClearTable { } {
+
+    if { $thisparam($this,connected) == 0 } {	return 0    }
+
+    set ok [ tk_messageBox -type yesno -message "Are you sure you want to delete all parameters for algorithm $algorithmname?" -icon question ]
+    if { $ok == "no" } {
+	return
+    }
+
+    $dbase DeleteAll $algorithmname
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_basealgorithm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_basealgorithm.tcl
new file mode 100644
index 0000000..324391d
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_basealgorithm.tcl
@@ -0,0 +1,1389 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_basealgorithm 1.0
+
+#
+# bis_basealgorithm.tcl
+# 
+#  Do we want to add
+#
+#  bis_optionslist class
+#  bis_objectlist  class
+#
+#
+
+package require  Itcl 3.2
+package require  cmdline
+
+package require bis_option 1.0
+package require bis_object 1.0
+package require bis_common 1.0
+
+package require Iwidgets 
+
+package require pxitclobject 1.0
+#package require pxtcluserprefs 1.0
+
+#
+# bis_basealgorithm class
+#
+
+itcl::class bis_basealgorithm {
+
+    #
+    #public
+    #
+
+    constructor { } { }
+    destructor { $this CleanAll }
+
+
+    # This Pointer
+    public method GetThisPointer { } { return $this }
+
+    # Some Methods you mant to override
+    # ----------------------------------
+    public method  UpdateOutputFilenames { } { return 1 }
+
+    # The rest is pretty fixed at this point
+    # --------------------------------------
+    #Get command line options list
+    public method  GetCmdLineOptionsList { }
+
+    #Get list from interenal arrays
+    public method  GetOptionsList { }
+    public method  GetInputsList { }
+    public method  GetOutputsList { }
+
+    # -----------------------------------------------------------
+    # vtk-like interface to Modify/access invidual option and inputs outputs
+    # -----------------------------------------------------------
+    public method SetOptionValue  { optionname value }
+    public method GetOptionValue  { optionname }
+    public method GetOptionType  { optionname }
+    public method SetInputObject  { inputname obj }
+    public method GetInputObject  { inputname }
+    public method GetOutputObject { outputname }
+
+    public method GetOutputBisObject { outputname }
+    public method GetInputBisObject  { inputname }
+
+    public method RenameInput     { id newname { newpriority -1 } }
+    public method RenameOutput    { id newname { newpriority -1 } }
+    public method GetInputName    { id }
+    
+    #Set parameter values and file names to internal arrays
+    protected method  SetArguments { parameterlist filelist }
+
+    #Set parameter values to internal bis_option arrays
+    public method  SetParameters   { plist } 
+
+    #This handle parameter set stuff
+    protected method HandleParameterSetArgument { plist } { }
+
+    #Clean List and Make Sure Priorities are Sorted
+    protected method CleanAndSortPriorities { inplist fld } 
+
+    # Set bis_object of InputsArray from a bis_object list Why do we nee this ?
+    public method  SetInputObjects { objectlist }
+
+    # Prints InputsArray
+    public method  PrintObjectList { } 
+
+    # Clean InputsArray and OutputsArray
+    public method  CleanAll {  }
+    public method  CleanInputsArray {  }
+    public method  CleanOutputsArray {  }
+    public method  AddLog { comment } { lappend Log $comment }
+
+    #print usage
+    public method  PrintUsage {  } 
+
+    #Get help related information 
+    public method  GetUsage         {  } { return $Usage }
+    public method  GetDescription   {  } { return  $description}
+    public method  GetDescription2  {  } { return  $description2}
+    public method  GetCategory      {  } { return  $category}
+    public method  SetCategory      { c } { set  category $c}
+    public method  GetAuthors       {  } { return  $authors }
+    public method  GetBackwardCompatibility { } { return $backwardcompatibility }
+    public method  GetSeeAlso       {  } {reurn $seealso }
+
+   # Get formatted help information (mode = stdout or html or tex )
+    public method  GetDetailDescription   { mode } 
+    public method  GetSynopsis            { mode } 
+
+    # Load bis_object to InputsArray from files
+    public method  LoadObjects { }
+
+    # Save bis_object of OutputsArray
+    public method  SaveObjects { { forcedir "" } }
+
+    # Memory preservation stuff
+    public method ClearInputs { }
+    public method ClearOutputs { }
+
+
+    # Get Name of Script
+    public method GetScriptName { } { return $scriptname }
+    public method GetCompletionStatus { } { return $completionstatus }
+
+
+
+
+    #Debug switch
+    public method  DebugOn   { } {   set debug 1 }
+    public method  DebugOff  { } {   set debug 0 }
+
+    #print debug message only when DebugON
+    public method  PrintDebug { msg } { 
+	if {$debug == 1 } {
+	    if { [ catch { pxtkprint "$msg\n" } ] } { puts stdout "$msg" }
+	}
+    }
+
+    # Set Log from arguments specified (=argv_org) and filelist
+    public method   SetLog { str  } { 	
+	set  scr  [info script]
+	set  Log [concat  $scr $str ]    
+    }
+
+    #Save log files if "testlog" or "log" option is specified
+    #If testlog specified,information for testing saved in  bis_common::bis_testlog
+    #If log specified,additional log file will be saved
+    public method   SaveTestLog {  }
+
+    #
+    #protected
+    #
+    protected variable containerobject 0
+    protected variable eventcontainerobject 0
+
+    # Mode
+    # managed, standalone, commandline
+    protected variable guimode "managed"
+    protected variable errormessage ""
+    protected variable resultmessage ""
+
+    public method GetResultsMessage { } { return $resultmessage }
+    public method GetErrorMessage { } { return $errormessage }
+
+    #Help related information 
+    protected variable category ""
+    protected variable description ""
+    protected variable description2 ""
+    protected variable Synopsis ""
+    protected variable Usage ""
+    protected variable scriptname ""
+    protected variable completionstatus "Not specified"
+    protected variable backwardcompatibility  ""
+    protected variable seealso  ""
+    protected variable authors  ""
+
+    #Internal tcl array for input files 
+    #output files and options. See bis_option.tcl 
+    #bis_object.tcl
+    protected variable InputsArray
+    protected variable OutputsArray
+    protected variable OptionsArray
+    protected variable StandardOptionsList ""
+    protected variable AdvancedOptionsList ""
+
+    #Log related
+    protected variable debug 0
+    protected variable Log ""
+    protected variable PreserveHistory 0
+
+    #
+    #Inputs, Outputs and Options
+    #
+    protected variable inputs    ""
+    protected variable outputs   ""
+    protected variable options ""
+    protected variable extrafilenames ""
+    protected variable directinputs  ""
+
+
+
+    # Create Default Output File list based on specific rules
+    protected method CreateDefaultOutputFileList  { filelist { numoutputs -1 } }
+
+    #output file name default is input filename + default suffix
+    protected variable defaultsuffix ""
+
+    #Generate internal tcl array (InputsArray,OutputsArray, and OptionsArray)
+    #from tcl lists (inputs outputs,options). Values and objects  won't be
+    #set until execution
+    protected method   CreateOptionsArray { }
+
+    # Set InputsArray,OutputsArray
+    protected method CreateInputArray  { }
+    protected method CreateOutputArray { }
+    protected method CreateVTKObjects  { }
+    protected method CreateInputArrayElement { newlist  { cmdline "" }}
+    protected method CreateOutputArrayElement { newlist { cmdline "" }} 
+
+    # set the filenames from a list for those objects not initialized from the command line (-inp, -out) style switches
+    public method SetInputArrayFilenames  { inplist }
+
+    #under construction
+    protected method   AddHistoryToLog {  }
+
+}
+
+
+#----------------------------------------------------
+# under construction
+#----------------------------------------------------
+itcl::body bis_basealgorithm::AddHistoryToLog {  } {
+
+    PrintDebug "bis_basealgorithm::AddHistoryToLog"
+
+    set history ""
+
+    #history is a list which contains history from all the input file
+    if { $PreserveHistory != 0 } {
+	foreach input [ array names InputsArray ] {
+	    set object      [$InputsArray($name) GetObject ] 
+	    set object_type [$InputsArray($name) GetObjectType ] 
+	    switch object_type {
+		pxitclimage {
+		    set comment [ $object GetImageHeader GetComment ]
+		}
+		pxitcltransform {
+		}
+		pxitclsurface {
+		}
+		pxitcllandmarks {
+		}
+		pxitclelectrodemultigrid {
+		}
+		default {
+		}
+		lappend history $comment
+	    }
+	}
+	lappend Log $history
+    }
+    PrintDebug "Log =$Log" 
+}
+
+#----------------------------------------------------
+#Get command line options list
+#----------------------------------------------------
+itcl::body bis_basealgorithm::GetCmdLineOptionsList {  } {
+    #    PrintDebug "bis_basealgorithm::GetCmdLineOptionsList"
+
+    $this CreateInputArray
+    $this CreateOutputArray
+
+    set optionslist ""
+
+    for { set i 0 } { $i < [ llength $inputs ] } { incr i } { 
+	set name [ lindex [ lindex $inputs $i ] 0 ]
+	set cmdoption [ $InputsArray($name) GetCommandSwitch ]
+	if { $cmdoption != "" } {
+	    lappend optionslist [  $InputsArray($name) GetCmdLineString ]
+	}
+    }
+
+    for { set i 0 } { $i < [ llength $outputs ] } { incr i } { 
+	set name [ lindex [ lindex $outputs $i ] 0 ]
+	set cmdoption [ $OutputsArray($name) GetCommandSwitch ]
+	if { $cmdoption != "" } {
+	    lappend optionslist [  $OutputsArray($name) GetCmdLineString ]
+	}
+    }
+
+    set nlist [ concat $StandardOptionsList $AdvancedOptionsList ]
+    for { set i 0 } { $i < [ llength $nlist ] } { incr i } {
+	set name [ lindex $nlist $i ]
+	set opt $OptionsArray($name)
+ 	if { [ string compare -length 3 $name "gui" ] != 0 } {
+ 	    lappend optionslist [  $OptionsArray($name) GetCmdLineString ]
+ 	}
+     }
+    
+
+    PrintDebug "\n\n\[CmdLineOptionsList\]"
+    PrintDebug "$optionslist"
+    return $optionslist
+}
+
+
+#----------------------------------------------------
+#Get list from interenal arrays
+#----------------------------------------------------
+itcl::body bis_basealgorithm::GetInputsList  {  } {    return  [array names InputsArray]  }
+itcl::body bis_basealgorithm::GetOutputsList {  } {    return  [array names OutputsArray] }
+itcl::body bis_basealgorithm::GetOptionsList {  } {    return  [array names OptionsArray] }
+
+
+# -----------------------------------------------------------
+#  VTK Like interface to options and outputs
+# -----------------------------------------------------------
+
+itcl::body bis_basealgorithm::SetOptionValue { optionname value } {
+
+    $OptionsArray($optionname) SetValue $value
+}
+
+itcl::body bis_basealgorithm::GetOptionValue { optionname } {
+
+    return [ $OptionsArray($optionname) GetValue ]
+}
+
+itcl::body bis_basealgorithm::GetOptionType { optionname } {
+
+    return [ $OptionsArray($optionname) GetOptionType ]
+}
+
+
+itcl::body bis_basealgorithm::SetInputObject { inputname obj } {
+
+    catch {
+	if { [ $obj IsA "vtkObject"  ] == 1 } {
+	    puts stderr "You are doing something wrong in SetInputObject $inputname, you are using a vtkObject instead of a pxitcl object"
+	    exit
+	}
+    }
+    [ $InputsArray($inputname) GetObject ] Copy $obj
+}
+
+itcl::body bis_basealgorithm::GetInputObject { inputname } {
+    return [  $InputsArray($inputname) GetObject ]
+}
+ 
+itcl::body bis_basealgorithm::GetOutputObject { outputname }  {
+    return [ $OutputsArray($outputname) GetObject ]
+}
+
+itcl::body bis_basealgorithm::GetInputBisObject { inputname } {
+    return   $InputsArray($inputname) 
+}
+ 
+itcl::body bis_basealgorithm::GetOutputBisObject { outputname }  {
+    return  $OutputsArray($outputname) 
+}
+
+itcl::body bis_basealgorithm::GetInputName { id } {
+
+    return [ lindex [ lindex $inputs $id ] 1 ]
+}
+
+itcl::body bis_basealgorithm::RenameInput { id newname { newpriority -1 } } {
+
+    set n [ llength $inputs ]
+    if { $id >= $n } {
+	return 0
+    }
+
+    set tmp $inputs
+    set inputs ""
+    for { set i 0 } { $i < $n } { incr i } {
+	if { $id != $i } {
+	    lappend inputs [ lindex $tmp $i ]
+	} else {
+	    set tmplist [ lindex $tmp $i ]
+
+
+	    lset tmplist 1 "$newname"
+
+	    if { $newpriority != -1 } {
+		lset tmplist 4 $newpriority
+	    }
+
+	    lappend inputs $tmplist
+	}
+    }
+    set tmp ""
+
+}
+
+itcl::body bis_basealgorithm::RenameOutput { id newname { newpriority -1 } } {
+
+    set n [ llength $outputs ]
+    if { $id >= $n } {
+	return 0
+    }
+
+    set tmp $outputs
+    set outputs ""
+    for { set i 0 } { $i < $n } { incr i } {
+	if { $id != $i } {
+	    lappend outputs [ lindex $tmp $i ]
+	} else {
+	    set tmplist [ lindex $tmp $i ]
+
+
+	    lset tmplist 1 "$newname"
+
+	    if { $newpriority != -1 } {
+		lset tmplist 4 $newpriority
+	    }
+
+	    lappend outputs $tmplist
+	}
+    }
+    set tmp ""
+
+}
+
+#----------------------------------------------------
+#Generate InputsArray,OutputsArray, and OptionsArray
+#----------------------------------------------------
+itcl::body bis_basealgorithm::CreateOptionsArray { } {
+
+    PrintDebug  "bis_basealgorithm::CreateOptionsArray"
+
+    PrintDebug "Creating Options Array "
+    array set OptionsArray {}
+    set nlist ""
+    for { set i 0 } { $i < [llength $options  ] } { incr i } {
+	set lst [ lindex $options $i]
+	set name [ lindex $lst  0]
+
+	if { $name == "out" || $name == "inp" || $name == "i" || $name =="o" } {
+	    puts stderr "Bad Option Name \"out\" -- this is reserved"
+	    exit
+	}
+
+	if { [ regexp "^out\[0-9\]+" $name  ] > 0 } {
+	    puts stderr "Bad Option Name $name -- this matches a  reserved name"
+	    exit
+	}
+
+	if { [ regexp "^inp\[0-9\]+" $name  ] > 0 } {
+	    puts stderr "Bad Option Name $name -- this matches a  reserved name"
+	    exit
+	}
+
+	if { [ llength $lst ] ==7 } {
+	    set p [ lindex $lst 6 ]
+	    if { $p < 0 } {
+		set p [ expr abs($p) + 1000000 ]
+	    }
+	    lappend nlist [ list $i $p $name ]
+	}
+    }
+
+    set pluspr    0
+    set minuspr -1
+
+    set StandardOptionsList ""
+    set AdvancedOptionsList ""
+
+ #   puts stderr "nlist = $nlist"
+
+    set nlist [ lsort -integer  -index 1 $nlist ]
+ #   puts stderr "sorted nlist = $nlist"
+    for { set i 0 } { $i < [ llength $nlist ] } { incr i } {
+	
+	set ind [ lindex [ lindex $nlist $i ] 0 ]
+	set lst [ lindex $options $ind ]
+	set p   [ lindex $lst 6 ]
+#	puts stderr "Reading lst item $i, p=$p lst=$lst"
+
+
+	set name [ lindex $lst 0 ]
+#	puts stderr "Item $i, ind=$i, lst=$lst, p=$p"
+	if { $p >= 0 } {
+	    lset lst 6 $pluspr; incr pluspr
+	    lappend StandardOptionsList $name
+	} else {
+	    lappend AdvancedOptionsList $name
+	    if { $p > -10000 } {
+		lset lst 6 $minuspr; set minuspr [ expr $minuspr -1 ]
+	    }
+	}
+
+	set elem [ [ bis_option \#auto ] GetThisPointer ]
+	set OptionsArray($name) $elem
+	$OptionsArray($name) SetAllPropertiesAsList $lst
+
+#	puts stderr "\t\t adding Option $name  $p --> [ lindex $lst 6 ] \t\t: $lst"
+    }
+}
+
+#----------------------------------------------------
+# Get usage information including input,output
+# and option description.Stdout by default
+# or html format if specified
+#----------------------------------------------------
+itcl::body bis_basealgorithm::GetDetailDescription { mode  } {
+
+    set description_all "$description $description2 \n"
+    #
+    if {[string compare $mode "html" ] == 0 } { 
+	set cr  "<br>"
+	set cr2  "<BR>"
+	set bos "<b>"
+	set boe "</b>"
+	set bh4 " <BR><B><span style=\"color: red;\">"
+	set eh4 "</span></B>"
+	set eeh4 ""
+    } elseif {[string compare $mode "tex" ] == 0 } { 
+	set cr "\n"
+	set cr2 "\n\n"
+	set bos "\\item{"
+	set boe "}"
+	set bh4 "\n\\paragraph*{"
+	set eh4 "}\n\\begin{compactitem}"
+	set eeh4 "\n\\end{compactitem}"
+    } else {
+	set cr "\n"
+	set cr2 "\n\n"
+	set bos ""
+	set boe ""
+	set bh4 ""
+	set eh4 ""
+	set eeh4 ""
+
+    }
+
+    #
+    #Inputs
+    #
+    set desc_in ""
+    if { [llength $inputs ]  > 0 } {
+	set desc_in  "$cr2$bh4\[Inputs\]$eh4"
+
+	if { [ llength $inputs ] > 0 } {
+
+	    for { set i 0 } { $i < [ llength $inputs ] } { incr i } {
+		set name [lindex [ lindex $inputs $i ]  0 ]
+		if { $name != $directinputs } {
+		    set cmdoption [ $InputsArray($name) GetCommandSwitch ]
+		    set comment1  "${bos}$name${boe} (command line option --$cmdoption) : [lindex [ lindex $inputs $i ] 1 ]"
+		} else {
+		    set comment1  "${bos}$name${boe} list --  specify the list of names for this at the end of the command line"
+		}
+		append desc_in "$cr $comment1 "
+	    }
+	}
+	append desc_in $eeh4
+    }
+
+    
+
+    #
+    #Outputs
+    #
+    set desc_out ""
+    if { [llength $outputs ]  > 0 } {
+
+	set desc_out "$cr2$bh4\[Outputs\]$eh4"
+	
+	if { [ llength $outputs ] > 0 } {
+	    for { set i 0 } { $i < [ llength $outputs ] } { incr i } {
+		set name [lindex [ lindex $outputs $i ]  0 ]
+		set cmdoption [ $OutputsArray($name) GetCommandSwitch ]
+		set comment1  "${bos}$name${boe} (command line option --$cmdoption) : [lindex [ lindex $outputs $i ] 1 ]"
+		append desc_out " $cr $comment1 "
+	    }
+	}
+
+	append desc_out $eeh4
+    }
+
+    #
+    #Options
+    #
+
+    for { set pass 0 } { $pass <=2 } { incr pass } {
+	set cnt($pass) 0
+#	puts stdout "\n\n"
+	if { $pass == 0 } {
+	    set desc_opt($pass) "$cr2$bh4\[Options\]$eh4"
+	} elseif { $pass ==1 } {
+	    set desc_opt($pass) "$cr2$bh4\[Common Options\]$eh4"
+	} else {
+	    set desc_opt($pass) "$cr2$bh4\[Software Testing Options\]$eh4"
+	}
+
+	foreach elem $options {
+	    set nm [ lindex $elem 0 ]
+	    if { $nm != "testlog" && [ string compare -length 3 $nm "gui" ] != 0 } {
+	
+		set pri [ lindex $elem 6 ]
+		set includethis 0
+		
+		if { $pass == 0 && $pri > -10000 } {
+		    set includethis 1
+		} elseif { $pass == 1 && ( $pri <= -10000 && $pri > -11000 ) } {
+		    set includethis 1
+		} elseif { $pass == 2 && $pri < -11000 } {
+		    set includethis 1
+		}
+
+#		puts stdout "nm=$nm pri=$pri pass=$pass includethis=$includethis"
+
+		if { $includethis > 0 } {
+		    #description for each option. name, description, default value
+		    set comment1 "${bos}[lindex $elem 0]${boe}  : [lindex $elem 1]. Default value is \"[lindex $elem 4]\"."
+		    set etype [ lindex [ lindex $elem 3 ] 0 ]
+		    if { $etype != "string" && $etype != "filename" && $etype != "comment"  } {
+			if { $etype == "listofvalues" } {
+			    set comment2 "Allowed values = \["
+			    set l [ llength [ lindex $elem 5 ] ]
+			    for { set i 0 } { $i < $l } { incr i } {
+				set comment2 "${comment2} [ lindex [ lindex $elem 5 ] $i ]"
+				if { $i != [ expr $l -1 ] } {
+				    set comment2 "${comment2},"
+				}
+			    }
+			    set comment2 "${comment2} \]"
+			} elseif { $etype == "boolean" } {
+			    set comment2  "Allowed values are either 0 (Off) or 1 (On)"
+			} else {
+			    set comment2  "Allowed range is from [lindex [lindex $elem 5] 0 ] to [lindex [lindex $elem 5] 1 ] "
+			}
+		    } else {
+			set comment2 ""
+		    }
+		    
+		    set tmp "$desc_opt($pass) $cr $comment1 $comment2"
+		    set desc_opt($pass) $tmp
+		    incr cnt($pass)
+		}
+	    }
+	}
+	if { $cnt($pass) < 1 } {
+	    set desc_opt($pass) "$cr"
+	} else {
+	    append desc_opt($pass) $eeh4
+	}
+    }
+    
+
+
+    return "$description_all $desc_in $desc_out $desc_opt(0) $desc_opt(1) $desc_opt(2)"
+}
+
+#----------------------------------------------------
+#print usage
+#----------------------------------------------------
+itcl::body bis_basealgorithm::PrintUsage {  } {
+
+    puts stdout "---------------------- BioImage Suite Command Line Tools (www.bioimagesuite.org)--------------"
+    puts stdout "\n\[NAME\]"
+    puts stdout "${scriptname}.tcl [GetDescription]"
+    puts stdout "\n\[SYNOPSIS\]"
+    puts stdout "[GetSynopsis text]"
+    puts stdout "\n\[DESCRIPTION\]"
+    puts stdout "[GetDetailDescription text ]"
+    puts stdout "\n\[BACKWARD COMPATIBILITY\]"
+    puts stdout "[GetBackwardCompatibility]"
+    puts stdout "\n\[NOTE\]"
+    puts stdout "BioImage Suite accepts both single dash and double dash specs, e.g. you may use --dogui instead of -dogui or vice-versa."
+}
+
+#----------------------------------------------------
+# Create Default Output File list based on specific rules
+# rule 1 : "the first input file name" + "suffix".
+#          If the input filename is "image" and the 
+#          default suffix is "_smooth","_bin", output
+#          will be "image_smooth" and "image_bin"
+# rule2 :"the first input file name" and index.
+#          If the input filename is "image" ,
+#          output will be "image_001",image"002",,,
+#----------------------------------------------------
+itcl::body bis_basealgorithm::CreateDefaultOutputFileList  { filelist { numoutputs -1 } } {
+#    DebugOn
+#    puts stdout "bis_basealgorithm::CreateDefaulteDefaultOutputFileList"
+#    puts stdout "filelist = $filelist"
+#    puts stdout "defaultsuffix = $defaultsuffix"
+
+
+    # First setting up the suffix rules
+    # ---------------------------------
+
+    if { $numoutputs == -1 } {
+	set numoutputs  [ llength $outputs ]
+    }
+    set numsuffixes [ llength $defaultsuffix ]
+
+    if { $numsuffixes == 0 } {
+	set firstsuffix "_out"
+    } else {
+	set firstsuffix [ lindex $defaultsuffix 0 ]
+    }
+
+    if { $numsuffixes < $numoutputs } {
+
+	set str "%d"
+        if { $numoutputs >=100 && $numoutputs < 1000 } {
+	    set str "%03d"
+	} elseif { $numoutputs >=10 }  {
+	    set str "%02d"
+	}
+
+	for { set i  $numsuffixes  } { $i < $numoutputs } { incr i } {
+	    set num [ format $str [ expr $i +1 ] ]
+	    lappend defaultsuffix "${firstsuffix}_$num"
+	    #	    puts stdout "Adding to $defaultsuffix"
+	}
+    }
+
+#    puts stderr "Suffixes = $defaultsuffix"
+
+    # Second setup the main file stem and suffix and directory name
+    # -------------------------------------------------------------
+    set inname [ lindex $filelist 0 ]
+
+    set l [ ::bis_common::SplitFileNameGZ $inname ]
+    set inname [ lindex $l 0 ]
+    set extension [ lindex $l 1 ]
+    set tmp ""; catch { set tmp [ $this GetOptionValue outputstem ] }
+    if { [ string length $tmp ] > 0 } { set inname $tmp }
+
+    set ext [ file extension $inname ]    
+    if { [ string length $ext ] > 0 } {
+	set extension $ext 
+    }
+    set inname    [ file rootname  $inname ]
+    set l [ ::bis_common::SplitFileNameGZ $inname ]
+    set inname [ lindex $l 0 ]
+    set extension [ lindex $l 1 ]
+
+
+    # Ovveride dirname from outputpath
+    set dirname [ file normalize [ file dirname $inname ] ]
+    set rootname [ file tail $inname ]
+
+    
+    set output_filelist ""
+    
+    foreach suffix $defaultsuffix  {
+	if { $suffix == "_nosuffix_" } {
+	    set suffix ""
+	}
+	PrintDebug "************************* root=$rootname, suffix=$suffix, $extension"
+	lappend output_filelist [ file join $dirname "$rootname$suffix$extension" ]
+    }
+    
+    
+    PrintDebug "output_filelist = $output_filelist"
+    #    puts stderr "Outputs = $output_filelist"
+    #puts $output_filelist
+    return $output_filelist
+}
+
+#----------------------------------------------------
+# CreateInputArrayElement 
+#----------------------------------------------------
+itcl::body bis_basealgorithm::CreateInputArrayElement { newlist { cmdline "" } } {
+
+    PrintDebug "bis_basealgorithm::CreateInputArrayElement"
+    set name  [ lindex $newlist  0 ]
+    set elem  [ [ bis_object \#auto ] GetThisPointer ]
+    set InputsArray($name) $elem
+    PrintDebug "$scriptname Created Input Array $name == $elem"
+
+    $InputsArray($name) SetValueAsList $newlist
+    $InputsArray($name) SetUpdateCallback "$this UpdateInputsFromContainer"
+    $InputsArray($name) SetCommandSwitch $cmdline
+    #    $InputsArray($name) CreateVTKObject     
+    if { $debug ==1 } { $InputsArray($name) PrintSelf }
+}
+
+
+
+
+#----------------------------------------------------
+# CreateOutputArrayElement 
+#----------------------------------------------------
+itcl::body bis_basealgorithm::CreateOutputArrayElement { newlist { cmdline "" }} {
+    set name  [ lindex $newlist  0 ]
+    set elem  [ [ bis_object \#auto ] GetThisPointer ]
+    set OutputsArray($name) $elem
+    PrintDebug "$scriptname: Created Output Array $name == $elem"
+    $OutputsArray($name) SetValueAsList $newlist
+    $OutputsArray($name) SetCommandSwitch $cmdline
+    if { $debug ==1 } { $OutputsArray($name) PrintSelf }
+    
+    
+}
+
+
+#-----------------------------------------------------------------------
+#  Utility Function to sort priorities
+#-----------------------------------------------------------------------
+itcl::body bis_basealgorithm::CleanAndSortPriorities { elemlist fld } {
+
+    #puts stderr "\n\n ------------------------------------------------------------------\n"
+    set indlist ""
+    for { set idx 0 } { $idx < [llength $elemlist] } { incr idx } {
+	set elem [ lindex $elemlist $idx ]
+	while { [ llength $elem ] <= $fld } {
+	    lappend elem 0
+	}
+	set tmp [ list $idx [ lindex $elem $fld ] ]
+	lappend indlist $tmp
+	#puts stderr "Adding unsorted element $tmp "
+    }
+    
+    set newlist [ lsort -integer  -index 1 $indlist ]
+
+
+    set sortedelemlist ""
+    set offset 0
+    for { set idx 0 } { $idx < [llength $elemlist] } { incr idx } {
+	set ind [ lindex $newlist $idx ] 
+
+
+	if {  [ lindex $ind 1 ] < 100 } { 
+	    set offset 0
+	} else {
+	    set offset 100
+	}
+	set index [ lindex $ind 0 ]
+	set elem [ lindex $elemlist $index ]
+	while { [ llength $elem ] <= $fld } {
+	    lappend elem ""
+	}
+	set elem2 [ lreplace $elem $fld $fld [ expr $offset + $idx ] ]
+	lappend sortedelemlist $elem2
+	#puts stderr "Adding $elem2"
+    }
+
+
+    return $sortedelemlist
+}
+#-----------------------------------------------------------------------
+# Set InputArray
+#-----------------------------------------------------------------------
+itcl::body bis_basealgorithm::CreateInputArray {  } {
+
+
+    # Clean Priorities and Sort
+
+    set inputs [ CleanAndSortPriorities $inputs 4 ]
+
+    set maxpr [ expr [ llength $inputs ] +1 ]
+
+    # set fixed and optional input files
+    for { set idx 0 } { $idx < [llength $inputs] } { incr idx } {
+	set ilist         [ lindex $inputs $idx ]
+	set line "inp"
+	if { $idx > 0 } {
+	    set j [ expr $idx +1 ]
+	    set line "inp$j"
+	}
+
+	CreateInputArrayElement $ilist $line
+    }
+
+}
+
+itcl::body bis_basealgorithm::SetInputArrayFilenames  { inplist } {
+
+    if { $directinputs != "" } {
+	if { [ llength $inplist ] > 0 } {
+	    puts stdout "Setting $directinputs  filenames= ( $inplist ) \n"
+	    $InputsArray($directinputs) SetFileName [ lindex $inplist 0 ] 1
+	    if { [ llength $inplist ] > 1 } {
+		set extrafilenames  [ lrange $inplist 1 [ expr [ llength $inplist ] -1 ] ]
+		$InputsArray($directinputs) AddFileNames $extrafilenames
+	    }
+	}
+	return
+    }
+
+    set index 0
+    for { set idx 0 } { $idx < [llength $inputs] } { incr idx } {
+	set elem [ lindex $inputs $idx ]
+	set name  [ lindex $elem  0 ]
+	if { [ $InputsArray($name) IsFileNameTheDefault ] == 1 }  {
+	    if { $index < [ llength $inplist ] } {
+		$InputsArray($name) SetFileName [ lindex $inplist $index ] 1
+		#puts stderr "\t\t\t Setting $name [ lindex $inplist $index ]"
+		incr index
+	    } else {
+		#puts stderr "\t\t\t index $index  is too big compared to [ llength $inplist ]"
+	    }
+	} else {
+	    #puts stderr "\t\t\t Image $name not default ignoring"
+	}
+    }
+    
+    return 1
+}
+
+#-----------------------------------------------------------------------
+# Set OutputArray
+#-----------------------------------------------------------------------
+itcl::body bis_basealgorithm::CreateOutputArray {  } {
+
+    set outputs [ CleanAndSortPriorities $outputs 4 ]
+    set maxpr [ expr [ llength $inputs ] +1 ]
+
+    PrintDebug "bis_basealgorithm::CreateOutputArray"
+    # set fixed and optional input files
+    for { set i 0 } { $i < [llength $outputs] } { incr i } {
+	set ilist         [ lindex $outputs $i ]
+	set line "out"
+	if { $i > 0 } {
+	    set j [ expr $i +1 ]
+	    set line "out$j"
+	}
+	#puts stderr "Creating outputelement $ilist, $line"
+	CreateOutputArrayElement $ilist $line
+    }
+
+}
+
+itcl::body bis_basealgorithm::CreateVTKObjects  { } {
+    
+
+#    puts stderr "Creating VTK Objects \n\n\n\n\n"
+
+    if { [ llength [ array names OutputsArray ] ] <1  } {
+	$this CreateOutputArray
+    }
+    foreach name [ array names OutputsArray ] {
+	set ok [ $OutputsArray($name) CreateVTKObject $guimode ]
+	if { $ok ==0 } {
+	    return 0
+	}
+    }
+
+    if { [ llength [ array names InputsArray ] ] < 1 } {
+	$this CreateInputArray
+    }
+
+    foreach name [ array names InputsArray ] {
+	set ok [ $InputsArray($name) CreateVTKObject $guimode ]
+	if { $ok ==0 } {
+	    return 0
+	}
+    }
+    return 1
+}
+#----------------------------------------------------
+#Set parameter values and file names to internal arrays
+#----------------------------------------------------
+itcl::body bis_basealgorithm::SetArguments { parameterlist filelist } {
+
+    set ret 1
+
+    PrintDebug "bis_basealgorithm::SetArguments"
+    PrintDebug "parameterlist = $parameterlist"
+    PrintDebug "filelist = $filelist"
+
+    set ret [ $this SetParameters $parameterlist ]
+    if { $ret == 0 } {
+	return 0 
+    }
+
+    $this SetInputArrayFilenames  $filelist  
+    AddHistoryToLog 
+
+    return 1
+}
+
+#----------------------------------------------------
+# Prints InputsArray
+#----------------------------------------------------
+
+itcl::body bis_basealgorithm::PrintObjectList {   } {
+
+    set names [array names InputsArray]
+    foreach name $names {
+	$InputsArray($name) PrintSelf
+  }
+}
+
+#----------------------------------------------------
+#Set parameter values (given as list) to internal bis_option arrays
+#----------------------------------------------------
+itcl::body bis_basealgorithm::SetParameters { params_list } {
+    
+    PrintDebug "bis_basealgorithm::SetParameters"
+    set ret 1
+
+
+    set ret [ $this HandleParameterSetArgument $params_list ]
+    if { $ret == 0 } {
+	return 0
+    }
+
+    array set params $params_list
+    # Parameters should be an array of bis_options not a list
+    foreach { key value } [array get params] {
+	# input checking will be done automatically in SetValue
+
+	set found 0
+	if { [string first "-" $key ] !=-1 } {
+	    set key [ string range $key 1 end ]
+	}
+	
+	foreach name [ array names OutputsArray ] {
+	    if { $found == 0 } {
+		set cmdoption [ $OutputsArray($name) GetCommandSwitch ]
+		if { $cmdoption == $key } {
+		    $OutputsArray($name) SetFileName $value 1
+		    set found 1
+		}
+	    }
+	}
+
+	if { $found == 0 } {
+	    foreach name [ array names InputsArray ] {
+		if { $found == 0 } {
+		    set cmdoption [ $InputsArray($name) GetCommandSwitch ]
+		    if { $cmdoption == $key } { 
+			if { $name != $directinputs } {
+			    $InputsArray($name) SetFileName $value 1
+			}
+			set found 1
+		    }
+		}
+	    }
+	}
+
+	if { $found == 0 } {
+	    set tmp [$OptionsArray($key) SetValueIfCurrentIsTheDefault $value ]
+	}
+    }
+    return $ret
+}
+
+#----------------------------------------------------
+# Clean InputsArray
+#----------------------------------------------------
+itcl::body bis_basealgorithm::CleanInputsArray {  } {
+    foreach name [array names InputsArray] {
+	set obj [ $InputsArray($name) GetObject ]
+
+	# this deltes a vtkObject
+	catch { $obj Delete }
+
+	# this deltes a Itcl object
+	catch { itcl::delete object $obj }
+    }
+}
+
+#----------------------------------------------------
+# Clean OutputsArray
+#----------------------------------------------------
+itcl::body bis_basealgorithm::CleanOutputsArray {  } {
+    foreach name [array names OutputsArray] {
+	set obj [ $OutputsArray($name) GetObject ]
+
+	# this deltes a vtkObject
+	catch { $obj Delete }
+
+	# this deltes a Itcl object
+	catch { itcl::delete object $obj }
+
+    }
+}
+itcl::body bis_basealgorithm::CleanAll {  } {
+    PrintDebug "bis_basealgorithm::CleanAll"
+    $this CleanInputsArray
+    $this CleanOutputsArray
+}
+
+
+
+#----------------------------------------------------
+# Load bis_object to InputsArray from files
+#----------------------------------------------------
+itcl::body bis_basealgorithm::LoadObjects {  } {
+
+    PrintDebug "bis_basealgorithm::LoadObjects"
+    if { $guimode  == "managed" } {
+	return 0
+    }
+
+    foreach input [ array names InputsArray ] {
+
+	#load pxitcl object
+	set filename [ $InputsArray($input) GetFileName ]
+	set type     [ $InputsArray($input) GetObjectType]
+	set priority [ $InputsArray($input) GetPriority ]
+
+
+	set ok 0
+	if { $filename != "" && $filename != "\"\"" } {
+	    set ok       [ $InputsArray($input) LoadObject $filename ]
+	} elseif { $priority >= 100 } {
+	    set ok -1
+	}
+    	
+	if { $ok == 0 } {
+	    set errormessage "Failed to load \"$filename\" for input object [  $InputsArray($input) GetDescription ]. Specify this using the --[ $InputsArray($input) GetCommandSwitch ] flag"
+	    return 0
+	}
+    }
+
+    if { $directinputs != "" } {
+	set objectlist [ $InputsArray($directinputs) GetObjectList ]
+	for { set i 0 } { $i < [ llength $objectlist ] } { incr i } {
+	    set obj [ lindex $objectlist $i ]
+	    set fn  [ $obj cget -filename ]
+	    set ok [ $obj Load $fn ]
+	    if { $ok == 0 } {
+		set errormessage "Failed to load \"$fn\" for input object [  $InputsArray($input) GetDescription ] (extra [ expr $i+1 ]). "
+		return 0
+	    }
+	}
+	$InputsArray($directinputs) UpdateInternalGUI
+    }
+    return 1
+}
+
+#----------------------------------------------------
+# Set bis_object of InputsArray from a bis_object list Why do we nee this ?
+#----------------------------------------------------
+itcl::body bis_basealgorithm::SetInputObjects { objectlist  } {
+    PrintDebug "bis_basealgorithm::LoadObjects"
+    if { [ llength $objectlist ] != [ llength $inputs ] } {
+	puts stderr "Bad Input $objectlist, wrong number of elements "
+	return 
+    }
+
+    foreach input [ array names InputsArray ] {
+	 $InputsArray($input) Copy [ lindex $objectlist $i ] 
+    }
+    return 1
+
+}
+
+#------------------------------------------------------------------------------------
+# Save filenames for validation. This information is used from bis_test::SaveExpectData
+#------------------------------------------------------------------------------------
+itcl::body bis_basealgorithm::SaveTestLog {  } {
+
+    PrintDebug "bis_basealgorithm::SaveTestLog"
+
+    #testlog file
+    set flag 0
+    catch { set flag [ $OptionsArray(testlog)    GetValue ]  }
+
+    if {$flag  == 1} {
+	set tmp ${bis_common::bis_testlog}
+	puts stdout "$tmp"
+	set chan [ open $tmp  w]
+	foreach output [ array names OutputsArray ] {
+	    set filename [ $OutputsArray($output) GetFileName ]
+	    if  { $filename != "" } {
+		puts $chan  "$filename"
+	    }
+	}
+
+	set found [lsearch [array names OptionsArray ] log]
+	if { $found  > 0 } {
+	    set  additional_log [ $OptionsArray(log)    GetValue ] 
+	    if {$additional_log  != ""} {
+		if  { $additional_log != "" } {
+		    puts $chan  "$additional_log"
+		}
+	    }
+	}
+	close $chan 
+    }
+
+
+    return 1
+}
+
+#----------------------------------------------------
+# Save bis_object of OutputsArray
+#----------------------------------------------------
+itcl::body bis_basealgorithm::SaveObjects { { forcedir "" } } {
+    PrintDebug "bis_basealgorithm::SaveObjects"
+
+    $this UpdateOutputFilenames
+
+    set tmp  [ array names OutputsArray ]
+    set namelist [lsort $tmp]
+    set resultmessage ""
+
+    foreach output $namelist {
+	#save each pxitcl object
+	set filename [ $OutputsArray($output) GetFileName ]
+	set object   [ $OutputsArray($output) GetObject  ]
+	set type     [ $OutputsArray($output) GetObjectType]
+
+	set ok 0
+	if { $filename != "" } {
+	    if { [ string length $forcedir ] > 1 } {
+		set filename [ file join $forcedir [ file tail $filename ]]
+	    }
+
+	    set tok [ file writable [ file dirname $filename ] ]
+	    if { [ file exists $filename ] } {
+		set tok [ file writable $filename ]
+	    }
+
+	    if { $tok !=0 } {
+		catch { set ok [ $object Save $filename ] }
+	    }
+
+	    if { $ok == 0 } {
+		set errormessage "Failed to save object [ $OutputsArray($output) GetDescription ] in \"$filename\""
+		return 0
+	    } else {
+		set resultmessage "${resultmessage}\t Saved object [ $OutputsArray($output) GetDescription ] in $filename\n"
+	    }
+	}
+    }
+
+    #Save log for test if specified
+    $this SaveTestLog
+
+    return 1
+}
+
+
+#--------------------------------------------------------------
+# GetSynopsis
+#--------------------------------------------------------------
+itcl::body bis_basealgorithm::GetSynopsis { mode  } {
+
+    set html 0
+    set latex 0
+    set linebreak ""
+
+    if { [string compare $mode "html" ] == 0 } { 
+	set html 1
+	set linebreak "<br>\t"    
+    } elseif { [string compare $mode "tex" ] == 0 } { 
+	set latex 1
+	set linebreak  "|\\linebreak\n\\verb|     "    
+    }
+
+    if { $html } {
+	set Synopsis "<PRE><B>"    
+	append Synopsis ${scriptname}.tcl
+	append Synopsis "</B>" 
+    } elseif { $latex } {
+	set Synopsis "\\verb| ${scriptname}.tcl "
+    } else {
+	set Synopsis "${scriptname}.tcl "
+    }
+
+    set numouts [ llength $outputs ]
+
+    set cnt 1
+
+    set badlist [ list  outputpath outputstem outputsuffix ]
+
+    for { set i 0 } { $i < [ llength $inputs ] } { incr i } { 
+	set name [ lindex [ lindex $inputs $i ] 0 ]
+	if { $name != $directinputs } {
+	    set cmdoption [ $InputsArray($name) GetCommandSwitch ]
+	    if { $cmdoption != "" } {
+		if { [expr ${cnt} % 5 ] == 0 } {
+		    append Synopsis  $linebreak
+		}
+		
+		set tmp [  $InputsArray($name) GetCommandSwitch ]
+		append Synopsis  "\[--$tmp \] "
+		incr cnt
+	    }
+	}
+    }
+    
+    for { set i 0 } { $i < [ llength $outputs ] } { incr i } { 
+	set name [ lindex [ lindex $outputs $i ] 0 ]
+	set cmdoption [ $OutputsArray($name) GetCommandSwitch ]
+	if { $cmdoption != "" } {
+	    if { [expr ${cnt} % 5 ] == 0 } {
+		append Synopsis  $linebreak
+	    }
+
+	    set tmp [  $OutputsArray($name) GetCommandSwitch ]
+	    append Synopsis    "\[--$tmp \] "
+	    incr cnt
+	}
+    }
+
+    foreach elem $options {
+
+	set elemname [ lindex $elem 0 ]
+	set found [ lsearch -exact $badlist $elemname ]
+
+
+	if { $numouts > 0 || $found  ==-1  } {
+
+	    if { [expr ${cnt} % 5 ] == 0 } {
+		append Synopsis  $linebreak
+	    }
+
+	    set option    "\[--[ lindex $elem 0] \] "
+	    
+	    if { [string compare "[lindex $elem 0]" "testlog" ] !=0 } {
+		append Synopsis   $option 
+	    }
+	    incr cnt
+	}
+    }
+
+
+    if { $directinputs != "" } { 
+	append Synopsis "$linebreak ${directinputs}1 ${directinputs}2  ... ${directinputs}N "
+    }
+
+#    foreach elem $inputs {
+#	append Synopsis "\[ [lindex $elem 0] \]"
+#    }
+    
+
+    if { $html > 0 } {
+	append Synopsis "</PRE>"    
+    } elseif { $latex > 0 } {
+	append Synopsis "|\n"    
+    }
+
+    return $Synopsis 
+}
+
+# ------------------------------------------------------------------
+itcl::body bis_basealgorithm::ClearInputs { } {
+    foreach name [ array names InputsArray ] {
+	set bisobj $InputsArray($name)
+	set obj [ $bisobj GetObject ]
+	$obj Clear
+	$bisobj UpdateInternalGUI
+    }
+
+}
+# -----------------------------------------------------------------
+itcl::body bis_basealgorithm::ClearOutputs { } {
+
+    foreach name [ array names OutputsArray ] {
+	set bisobj $OutputsArray($name)
+	set obj [ $bisobj GetObject ]
+	$obj Clear
+	$bisobj UpdateInternalGUI
+    }
+}
+# -----------------------------------------------------------------
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_basecontrolhelper.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_basecontrolhelper.tcl
new file mode 100644
index 0000000..473c04e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_basecontrolhelper.tcl
@@ -0,0 +1,67 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main ]
+
+package require pxitclbasecontrol
+package provide bis_basecontrolhelper 1.0
+
+# -------------------------------
+# Helper Class for Wrapping Calls
+# -------------------------------
+itcl::class bis_basecontrolhelper { 
+
+    inherit pxitclbasecontrol
+
+    constructor { bis_algo } {
+	::pxitclbasecontrol::constructor $bis_algo
+    } {
+	set parent $bis_algo
+	set currentpoint [ list -1 -1 -1 ]
+	set basewidget [ $bis_algo GetBaseWidget ]
+	if { $basewidget == 0 } {
+	    set basewidget .
+	}
+
+    }
+
+    public variable currentpoint 
+
+    public method GetThisPointer { } { return $this }
+    public method SetResultsFromObject { img alg }  {  return 0 } 
+    public method GetViewer { } { return [ $parent GetViewer ] }
+    public method ShowWindow { } { return 1 }
+    public method SetImageFromObject { img alg } { return 0 }
+    public method WatchOn { } { return 0 }
+    public method WatchOff { } { return 0 }
+}
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_baseintensityregistration.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_baseintensityregistration.tcl
new file mode 100644
index 0000000..da6f61e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_baseintensityregistration.tcl
@@ -0,0 +1,500 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_baseintensityregistration 1.0
+package require bis_algorithm 1.0
+package require bis_common 1.0
+package require bis_resliceimage 1.0
+package require bis_colorblendimage 1.0
+
+
+itcl::class bis_baseintensityregistration {
+
+    inherit bis_algorithm
+
+    constructor { } { }
+    public method InitializeBaseIntensityRegistration { }
+
+    # Get Info about Algorithm for use in GUI Container
+    public method IsImageToImage { } { return 0 }
+    public method SetContainer { cont }  { set containerobject $cont }
+    public method GetContainer { }  { return $containerobject }
+    public method UpdateInputsFromContainer { }
+    public method UpdateContainerWithOutput { } 
+    public method ProgressCallback   { filter lab }  
+
+    # Input and Output Methods
+    public method GetReferenceImage { }
+    public method GetTransformImage { }
+    public method GetOutputTransformation { }
+    public method GetOutputImage { }
+    public method GetInitialTransformation { }
+    public method SetReferenceImage { img }
+    public method SetTransformImage { img }
+    public method SetInitialTransformation { img }
+
+    # Set Filenames etc
+    public method  UpdateOutputFilenames { } 
+    public method CheckInputObjects { } 
+    protected method SetCommonIntensityRegistrationOptions { regobj }
+
+
+    # Generate Resliced Image
+    public method GenerateReslicedTransformImage { }
+    public method CreateWarpedImage { } 
+    # Generate Method 
+    public method GetExtension { } { return ".matr" }
+
+
+    protected variable current_registration 0
+    protected variable has_weights 1
+    protected variable single_input 0
+
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_baseintensityregistration::InitializeBaseIntensityRegistration { } {
+
+
+    # This assumes that a derived class has done some work here already
+
+    PrintDebug "bis_baseintensityregistration::Initialize" 
+
+    set tmp $inputs
+    set ismidline 0
+
+
+    if { $single_input > 0 } {
+	set inputs { 
+	    { reference_image   "Input Image" pxitclimage  ""  0}    
+	    { initial_transform "Initial Transformation" pxitcltransform  "" 100  }
+	}
+    } else {
+	set inputs { 
+	    { reference_image   "Reference Image" pxitclimage  ""  0}    
+	    { transform_image   "Transform Image" pxitclimage  ""  1}     
+	    { initial_transform "Initial Transformation" pxitcltransform  "" 100  }
+	}
+	
+	if { $has_weights == 1 } {
+	    set inputs {
+		{ reference_image   "Reference Image" pxitclimage  ""  0}    
+		{ transform_image   "Transform Image" pxitclimage  ""  1}     
+		{ initial_transform "Initial Transformation" pxitcltransform  "" 100  }
+		{ weight_image "Reference Weight Image" pxitclimage  "" 101  }
+		{ weight_image2 "Transform Weight Image" pxitclimage  "" 102  }
+	    }
+	}
+    }
+
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend inputs [ lindex $tmp $i ]
+    }
+    
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set tmp $outputs
+    
+    set outputs { 
+	{ output_transform "Output Transformation"  pxitcltransform  "" }
+	{ output_image   "Transformed Image" pxitclimage  ""  200 }
+    }
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+    	lappend outputs [ lindex $tmp $i ]
+    }
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    #    lappend options [ list outname  "output filename root" "Output" string ""     { "" }  -1000 ]
+    set myclassname [ string range  [ $this info class ] 2 end ]
+    if {  $myclassname != "bis_nonlineardistortioncorrection"  } {
+	lappend options [ list resolution      "resolution "                                   "Resolution (x Native)"     real  1.5   { 0.5 10.0 }  20 ]
+	lappend options [ list stepsize       "step size "                                    "Step Size"       real  1.0   { 0.1 5.0 }  -151 ]
+    } else {
+	lappend options [ list resolution      "resolution "                                   "Resolution (x Native)"     real  2.0   { 0.5 10.0 }  20 ]
+	lappend options [ list stepsize       "step size "                                    "Step Size"       real  3.0   { 0.1 5.0 }  -151 ]
+    }
+
+    lappend options [ list numberoflevels  "number of multiresolution levels"          "Number of Levels"     int   3    { 1  5 } 2 ]
+    lappend options [ list metric  "Similarity Metric"   "Metric"  listofvalues  "NMI"    { SSD CC MI NMI JE }  -10  ]
+    lappend options [ list iterations      "Number of iterations "                                   "Number of Iterations"     int   15    { 1     50 }  -100 ]
+    lappend options [ list resolutionrate  "Rate at which to decrease the resolution"   "Resolution Rate"  real   2    { 1.05 3.0 } -101 ]
+    lappend options [ list  autonormalize   "Autonormalize Intensities (i.e. staturate between 1% and 99% of intensity range)"                                 "Auto Normalize"  boolean   1     { 0 1  }  -102  ]
+    lappend options [ list optimization    "Optimization Method"          "OptMethod"   listofvalues   default { default "SlowClimb" "GradientDescent" "ConjugateGradient" "Hybrid" }  -103 ]
+    lappend options [ list numberofbins    "Number of bins for the joint histogram"          "Number of Bins"     int   64    { 32  1024 } -104 ]
+
+    lappend options [ list numberofsteps    "Number of steps/level for the optimization"          "Number Of Steps"     int   1    { 1 5 } -150 ]
+    lappend options [ list guiautosave       "AutoSave Result" "Autosave"  boolean  1 { 0 1 }  99 ]
+    lappend options [ list reslimage   "Output a resliced image, or  a red-green blend image, or no  resliced image" "Resliced Image"  listofvalues Resliced  { Resliced ColorBlend }  200 ]
+    lappend options [ list usegpu   "Use GPU Implementation (if available)"  "Use GPU"  boolean   0  { 0 1  }  -500  ]
+    lappend options [ list threadmode "GPU Thread Mode " "GPU ThreadMode" int 3 { 0 4 }  -501 ]
+
+    if { $has_weights == 1 } {
+	lappend options [ list  useweightimage  "Weighted Registrations (0=none,1=ref only,2=both ref and target weights)"  "Num Weight Images:"  listofvalues  0     { 0 1 2  }  -10  ]
+    }
+
+    
+    if { $defaultsuffix == "" } {
+	set defaultsuffix { "_xform" }
+    }
+
+
+    set category    "Registration"
+    
+    if { $authors == "" } {
+	set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+    }
+
+    $this AddDefaultOptions
+}
+
+
+
+# ----------------------------------------------------------
+#
+#  Input/Output Utility Stuff
+#
+# ----------------------------------------------------------
+
+itcl::body bis_baseintensityregistration::SetReferenceImage  { img } {
+    #    puts stderr "I am here $img"
+    $this SetInputObject reference_image $img
+}
+
+itcl::body bis_baseintensityregistration::SetTransformImage  { img } {
+    if { $single_input == 0 } {
+	$this SetInputObject transform_image $img
+    }
+}
+
+itcl::body bis_baseintensityregistration::SetInitialTransformation  { tr } {
+    $this SetInputObject initial_transform $tr
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+itcl::body bis_baseintensityregistration::GetReferenceImage  { } {
+    return [ $this GetInputObject reference_image ]
+}
+
+itcl::body bis_baseintensityregistration::GetTransformImage  { } {
+
+    if { $single_input == 0 } {
+	return [ $this GetInputObject transform_image ]
+    } 
+    return 0
+}
+
+itcl::body bis_baseintensityregistration::GetOutputTransformation  { } {
+    return [ $this GetOutputObject output_transform ]
+}
+
+itcl::body bis_baseintensityregistration::GetOutputImage  { } {
+    return [ $this GetOutputObject output_image ]
+}
+
+itcl::body bis_baseintensityregistration::GetInitialTransformation  {  } {
+    return [ $this GetInputObject initial_transform ]
+}
+
+# ------------------------------------------------------------------------------------
+#        Container Stuff 
+# ------------------------------------------------------------------------------------
+
+itcl::body bis_baseintensityregistration::ProgressCallback   { filter lab }  {
+
+    if { $current_registration == 0 } {
+	return 0
+    }
+
+    ::bis_algorithm::ProgressCallback $filter $lab
+
+    set t [ string trim [ $current_registration GetOutputStatus ] ]
+    puts  stderr "$t"
+
+}
+
+itcl::body bis_baseintensityregistration::UpdateInputsFromContainer { } {
+
+    if { $containerobject == 0 } {    
+	return
+    }
+
+#    puts stderr "Updating Base Intensity Reg"
+
+    $this SetTransformImage [ $containerobject GetTargetImage ] 
+    $this SetReferenceImage [ $containerobject GetReferenceImage ] 
+    $this SetInitialTransformation [ $containerobject GetTransformation ] 
+    [ $this GetOutputTransformation ] configure -filename ""
+
+#    puts stderr "\n\n --------------------------------------\n Updating $this"
+#    puts stderr "[ [ $this GetReferenceImage  ] GetDescription ]"
+#    puts stderr "[ [ $this GetTransformImage  ] GetDescription ]"
+#    puts stderr "[ [ $this GetInitialTransformation  ] GetDescription ]"
+
+    $this UpdateOutputFilenames
+#    puts stderr "\n"
+
+    return
+
+}
+
+itcl::body bis_baseintensityregistration::UpdateContainerWithOutput { } {
+
+    # Reslice on the fly and update viewer ......................
+
+    if { $current_registration != 0 } {
+	return 0
+    }
+
+
+    set img  [ $this GenerateReslicedTransformImage ] 
+    if { $img == 0 } {
+	return 0
+    }
+
+    PrintDebug "In Update Container With Output $this, $img [ $img GetDescription ]\n"
+    puts stderr "In Update Container With Output $this, $img [ $img GetDescription ]\n"
+
+    set autosave [ $this GetOptionValue guiautosave ]
+
+    if { $autosave > 0 } {
+	$OutputsArray(output_transform) SaveObject
+    }
+    
+    if { $containerobject == 0 } {
+	if { $bis_viewer !=0 } {
+	    $bis_viewer SetImage $img
+	}  elseif { $vtk_viewer !=0 } {
+	    $vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+	} 
+    } else {
+	PrintDebug "Calling Container ($this, $containerobject) SetResultsFromObject" 
+	$containerobject SetResultsFromObject $img $this
+	$containerobject SetTransformationFromObject [ $this GetOutputTransformation ] $this
+    }
+
+    itcl::delete obj $img
+
+}
+
+# --------------------------------------------------------------------------------------------
+
+itcl::body bis_baseintensityregistration::UpdateOutputFilenames { } {
+
+
+    set f1 [ [ $this GetOutputTransformation ] cget -filename ]
+
+    if { [ string length $f1 ] > 1 } {
+	return 1
+    }
+
+    set f(0) [ $InputsArray(reference_image) GetFileName ]
+    if { $single_input == 0 } {
+	set f(1) [ $InputsArray(transform_image) GetFileName ]
+    } else {
+	set f(1) "self"
+    }
+    
+    for { set i 0 } { $i <= 1 } { incr i } {
+	set l($i) [ ::bis_common::SplitFileNameGZ $f($i) ]
+	set f($i) [ file tail [ lindex $l($i) 0 ] ]
+    }
+    
+    set fname [ file join [ file dirname $f(0) ] "$f(0)_$f(1)" ]
+    
+#    puts stdout "\n suffixlist = $defaultsuffix"
+    set outlist [ $this CreateDefaultOutputFileList $fname ]
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+
+#    puts stdout "\n suffixlist = $defaultsuffix"
+#    puts stdout "\nxformname = [ lindex $outlist 0 ][ $this GetExtension ]" 
+ 
+    $OutputsArray(output_transform) SetFileName "[ lindex $outlist 0 ][ $this GetExtension ]" $force
+
+    return 1
+}
+
+
+itcl::body bis_baseintensityregistration::CheckInputObjects { } {
+
+
+    set image_in    [ $this GetReferenceImage ]
+    set d [ $image_in GetImageSize ]
+
+    if { $d < 2 } {
+	return 0
+    }
+
+    if { $single_input == 0 } {
+	set image_in    [ $this GetTransformImage ]
+	set d [ $image_in GetImageSize ]
+	
+	if { $d < 2 } {
+	    return 0
+	}
+    }
+
+    return 1
+
+}
+
+itcl::body bis_baseintensityregistration::CreateWarpedImage { } {
+
+    set reslice_alg [bis_resliceimage [pxvtable::vnewobj]]
+    $reslice_alg InitializeFromContainer 0
+    $reslice_alg SetInput [ $this GetReferenceImage ] 
+    if { $single_input == 1 } {
+	$reslice_alg SetSecondInput [ $this GetReferenceImage ] 
+    } else {
+	$reslice_alg SetSecondInput [ $this GetTransformImage ] 
+    }
+    $reslice_alg SetTransformation [ $this GetOutputTransformation ] 
+    $reslice_alg Execute
+
+    [ $this GetOutputImage ] ShallowCopy [ $reslice_alg GetOutput ]
+    itcl::delete obj $reslice_alg
+}
+
+itcl::body bis_baseintensityregistration::GenerateReslicedTransformImage { } {
+
+    set d [ $this CheckInputObjects ]
+    if { $d == 0 } {
+	return 0
+    }
+
+    if { [ $OptionsArray(reslimage) GetValue ] == "Resliced" } {
+	set reslice_alg [bis_resliceimage [pxvtable::vnewobj]]
+    } else {
+	set reslice_alg [bis_colorblendimage [pxvtable::vnewobj]]
+    }
+    $reslice_alg InitializeFromContainer 0
+    $reslice_alg SetInput [ $this GetReferenceImage ] 
+    if { $single_input == 1 } {
+	$reslice_alg SetSecondInput [ $this GetReferenceImage ] 
+    } else {
+	$reslice_alg SetSecondInput [ $this GetTransformImage ] 
+    }
+    $reslice_alg SetTransformation [ $this GetOutputTransformation ] 
+    $reslice_alg Execute
+
+    set img [ [ pxitclimage \#auto ] GetThisPointer ]
+    $img ShallowCopy [ $reslice_alg GetOutputObject output_image ]
+
+    itcl::delete obj $reslice_alg 
+    return $img
+}
+
+itcl::body bis_baseintensityregistration::SetCommonIntensityRegistrationOptions { regobj } {
+
+    set image1    [ $this GetReferenceImage  ]
+    if { $single_input == 0 } {
+	set image2    [ $this GetTransformImage ]
+    }
+
+    set resolution     [ $OptionsArray(resolution) GetValue ]
+    set iterations     [ $OptionsArray(iterations) GetValue ]
+    set numlevels     [ $OptionsArray(numberoflevels) GetValue ]
+
+    set numbins        [ $OptionsArray(numberofbins) GetValue ]
+    set numsteps       [ $OptionsArray(numberofsteps) GetValue ]
+    set optmethod      [ $OptionsArray(optimization) GetValue ]
+    set resolrate      [ $OptionsArray(resolutionrate) GetValue ]
+    set metric         [ $OptionsArray(metric) GetValue ]
+    set stepsize       [ $OptionsArray(stepsize) GetValue ]
+    set autonormalize  [ $OptionsArray(autonormalize) GetValue ]
+
+
+    if { $has_weights == 1 } {
+	set useweights     [ $OptionsArray(useweightimage) GetValue ]
+	puts stdout "UseWeights=$useweights"
+
+	
+	if { $useweights > 0 } {
+	    #	puts stderr "Using Weight Image"
+	    $regobj SetReferenceWeightImage [ [ $this GetInputObject weight_image  ] GetImage ]
+	    if { $useweights > 1 } {
+		$regobj SetTransformWeightImage [ [ $this GetInputObject weight_image2  ] GetImage ]
+	    }
+	}
+    }
+
+    $regobj SetResolution $resolution 
+    $regobj SetNumberOfIterations $iterations 
+    $regobj SetNumberOfLevels $numlevels
+    $regobj SetNumberOfBins  $numbins
+    $regobj SetNumberOfSteps  $numsteps
+
+
+    
+
+    $regobj SetOptimizationMethodToDefault
+    
+    puts stdout "Optmethod $optmethod [ $regobj GetClassName ]"
+
+    switch -exact $optmethod {
+	"SlowClimb" {  $regobj SetOptimizationMethodToSlowClimb }
+	"GradientDescent" {  $regobj SetOptimizationMethodToGradientDescent }
+	"ConjugateGradient" {  $regobj SetOptimizationMethodToConjugateGradient }
+	"Hybrid" {  $regobj SetOptimizationMethodToHybrid }
+    }
+
+    $regobj SetResolutionRate $resolrate
+
+    $regobj SetSimilarityMeasureToNormalizedMutualInformation 
+    switch -exact $metric { 
+	"SSD" { $regobj SetSimilarityMeasureToSumofSquaredDifferences } 
+	"CC" { $regobj SetSimilarityMeasureToCorrelation } 
+	"MI" { $regobj SetSimilarityMeasureToMutualInformation } 
+	"JE" { $regobj SetSimilarityMeasureToJointEntropy } 
+
+    }
+
+    puts stdout "Metric set to [ $regobj GetSimilarityMeasure ], $metric "
+
+    $regobj SetStepSize       $stepsize
+    $regobj SetAutoNormalizeIntensities $autonormalize
+
+    if { $single_input == 1 } {
+	puts stdout "MIDLINE\n\n"
+	$regobj SetReferenceImage [ $image1 GetObject ]
+	$regobj SetTransformImage [ $image1 GetObject ]
+	$regobj SetReferenceOrientation [$image1 GetOrientation]
+	$regobj SetTransformOrientation [$image1 GetOrientation]
+    } else {
+	$regobj SetReferenceImage [ $image1 GetObject ]
+	$regobj SetTransformImage [ $image2 GetObject ]
+	$regobj SetReferenceOrientation [$image1 GetOrientation]
+	$regobj SetTransformOrientation [$image2 GetOrientation]
+    }
+
+    return 1
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_baselevelset.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_baselevelset.tcl
new file mode 100644
index 0000000..cc289bb
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_baselevelset.tcl
@@ -0,0 +1,259 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_baselevelset 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+#
+# strip skull
+#
+
+itcl::class bis_baselevelset {
+
+    inherit bis_imagetoimagealgorithm
+
+    constructor { } {  }
+    public method InitializeBaseLevelset { }
+    protected method SetLevelsetParameters { filter }
+
+    # This is the update callback
+    public method ProgressCallback   { filter lab }  
+
+    # add some "global" variables
+    protected variable levelset    0
+    protected variable surf_actor     
+    protected variable has_surface_actors 0
+    protected variable original_x 0
+    protected variable padding_x  0
+    protected variable dual_mode  0
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_baselevelset::InitializeBaseLevelset { } {
+
+    PrintDebug "bis_baselevelset::InitializeBaseLevelset" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set inputs { 
+	{ initial_levelset "Initial Levelset" pxitclimage  ""  101 }   
+	{ seed_points      "Seed Points" pxitcllandmarks  ""  102 }   
+    }
+
+    lappend options [ list initial_mode "Initialization Mode" "Init Mode"  listofvalues seedpoint { seedpoint landmarks levelset  }  0 ]
+    lappend options [ list edgestrength "Strength of Edge" "Edge Weight"  real 0.0 { 0.0 10.0  }  1 ]
+    lappend options [ list propagationstrength "Strength of Propagation" "Propagation Weight"  real 1.0 { 0.0 10.0  }  2 ]
+    lappend options [ list smoothnessstrength " Smoothness Factor" "Smoothness Weight"  real 0.2 { 0.0 10.0  }    3 ]
+    lappend options [ list iterations "Number of Iterations for Updates" "Iterations"  { integer }  50 { 1 2000 }  4 ]
+    lappend options [ list radius "Radius of Initial Ball" "Radius"  { real }  3.0 { 1.0 10.0 }  5 ]
+
+    lappend options [ list seedx "Seed position x" "Seedx"  { integer }  91 { 0 255 }  -2 ]
+    lappend options [ list seedy "Seed position y" "Seedy"  { integer }  91 { 0 255 }  -3 ]
+    lappend options [ list seedz "Seed position z" "Seedz"  { integer }  91 { 0 255 }  -4 ]
+    lappend options [ list updatepercentage "Update Percentage" "Update Rate"  real 0.1 { 0.0 1.0  } -5 ]
+    lappend options [ list tolerance "Tolerance for Convergenece in mm" "Tolerance"  { real }  0.00001 { 0.0 1.0 }   -6 ]
+    
+    set defaultsuffix { "_levelset" }
+
+    set category "Segmentation"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Update Progress
+# ----------------------------------------------------------------------------------------
+
+
+itcl::body bis_baselevelset::ProgressCallback   { filter lab }  {
+
+    if { $levelset == 0 } {  return 0    }
+    ::bis_algorithm::ProgressCallback $filter $lab
+
+    set ortho [ $this GetViewer ]
+    if { $ortho == 0 } {
+	return 0
+    }
+
+
+    if { [ $ortho IsA "vtkpxGUIOrthogonalViewer"  ] == 0 } {
+	return 0
+    }
+
+    set maxj 1
+    if { $dual_mode == 0 } {
+	set maxj 0
+    }
+
+    # Initialization Phase
+    if { $has_surface_actors == 0 } {
+	for { set i 0 } { $i <=3 } { incr i } {
+	    for { set j 0 } { $j <= $maxj } { incr j } {
+		set map [ vtkPolyDataMapper New ]
+		set surf_actor($i,$j) [ vtkActor New ]
+		$surf_actor($i,$j) SetMapper $map
+		$map Delete
+		
+		[ [ $ortho GetRenderer $i ] GetRenderer ] AddActor $surf_actor($i,$j)
+		#		puts stderr "Creating Actor $i $j $surf_actor($i,$j)"
+		set prop [ $surf_actor($i,$j) GetProperty ]
+		if { $j == 1 } {
+		    $prop SetColor 1.0 0.0 0.0
+		} else {
+		    $prop SetColor 0.0 1.0 0.0
+		    if { $i == 3 } {
+			$prop SetOpacity 0.8
+		    }
+		}
+		
+		if { $i !=3 } {
+		    $prop SetRepresentationToWireframe
+		    $prop SetAmbient 1.0
+		    $prop SetDiffuse 0.0
+		    $prop SetSpecular 0.0
+		    $prop SetLineWidth 2.0
+		}
+	    }
+	}
+	set has_surface_actors 1
+	return 0
+    }
+
+
+    puts stderr "Status = [ $levelset GetOutputStatus ]\n"
+
+    for { set j 0 } { $j <= $maxj } { incr j } {
+	
+	set pd [ vtkImageData New ] 
+	
+	if { $j ==  1 } {
+	    $pd ShallowCopy [  $levelset GetOutput2 ]  
+	} else {
+	    $pd ShallowCopy [  $levelset GetOutput ]  
+	}
+
+	puts stderr "Extracting $j dims = [ $pd GetDimensions ]"
+	    
+	set skinExtractor [ vtkContourFilter [ pxvtable::vnewobj ] ]
+	$skinExtractor SetUseScalarTree 0
+	$skinExtractor ComputeScalarsOff
+	$skinExtractor ComputeGradientsOff
+	$skinExtractor SetInput $pd
+	$skinExtractor SetValue 0 0.0
+	$skinExtractor Update
+		
+	puts stderr "this far updating $j"
+	for { set i 0 } { $i <=3 } { incr i } {
+	    [ $surf_actor($i,$j) GetMapper ] SetInput [ $skinExtractor GetOutput ]
+	}
+	$skinExtractor Delete
+	$pd Delete
+    }
+    $ortho UpdateDisplay
+    update idletasks
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_baselevelset::SetLevelsetParameters { filter  } {
+
+    set edge         [ $OptionsArray(edgestrength)    GetValue ]
+    set smoothness   [ $OptionsArray(smoothnessstrength)    GetValue ]
+    set propagation    [ $OptionsArray(propagationstrength) GetValue ]
+    set iterations  [ $OptionsArray(iterations) GetValue ]
+    set tolerance  [ $OptionsArray(tolerance) GetValue ]
+    set radius      [ $OptionsArray(radius) GetValue ]
+    set updateper   [ $OptionsArray(updatepercentage) GetValue ]
+    set initmode    [ $OptionsArray(initial_mode) GetValue ]
+    set image_in      [ $this GetInput ]
+
+    
+    $filter SetInput [ $image_in GetImage]
+    $filter SetPropagationWeight $propagation
+    $filter SetCurvatureWeight $smoothness
+    $filter SetAdvectionWeight   $edge
+    $filter SetInitialDistance $radius
+    $filter SetRMSError $tolerance
+    $filter SetLevelsetIterations $iterations
+    $filter SetUpdatePercentage $updateper
+
+
+    if { $initmode == "seedpoint" } {
+	set seedx      [ $OptionsArray(seedx) GetValue ]
+	set seedy      [ $OptionsArray(seedy) GetValue ]
+	set seedz      [ $OptionsArray(seedz) GetValue ]
+	set pt [ vtkPoints New ]
+	$pt SetNumberOfPoints 1
+	$pt SetPoint 0 $seedx $seedy $seedz
+	$filter SetInitialPoints $pt
+	$pt Delete
+    } elseif { $initmode == "landmarks" } {
+
+	set land [ [ $this GetInputObject seed_points ] GetLandmarks ]
+	if { [ [ $land GetPoints ] GetNumberOfPoints ] < 1 } {
+	    return 0
+	}
+
+	set baseCurve [ vtkpxBaseCurve New ]
+	$baseCurve Copy $land 
+	$baseCurve SetSpacing 1.0 1.0 1.0
+	$baseCurve SetOrigin 0.0 0.0 0.0
+	$baseCurve Compact
+	
+	$filter SetInitialPoints [ $baseCurve GetPoints ]
+	$baseCurve Delete
+    } else {
+	set img1 [ $image_in GetImage]
+	set img2 [ $this GetInputObject initial_levelset ] 
+	set d1 [ $img1 GetImageSize ]
+	set d2 [ $img2 GetImageSize ]
+	if { $d1 != $d2 } {
+	    return 0
+	}
+
+	$filter SetInitialLevelSet [ $img2 GetImage ]
+    }
+
+    return 1
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_basepointbasedregistration.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_basepointbasedregistration.tcl
new file mode 100644
index 0000000..5c70a7c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_basepointbasedregistration.tcl
@@ -0,0 +1,415 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_basepointbasedregistration 1.0
+package require bis_algorithm 1.0
+package require bis_common 1.0
+package require bis_pointbasedregistrationviewer 1.0
+
+
+itcl::class bis_basepointbasedregistration {
+
+    inherit bis_algorithm
+
+    constructor { } { }
+    public method InitializeBasePointBasedRegistration { }
+
+    # Get Info about Algorithm for use in GUI Container
+    public method IsImageToImage { } { return 0 }
+    public method SetContainer { cont }  { set containerobject $cont }
+    public method GetContainer { }  { return $containerobject }
+    public method UpdateInputsFromContainer { }
+    public method UpdateContainerWithOutput { } 
+    public method ProgressCallback   { filter lab }  
+
+    # Input and Output Methods
+    public method GetReferenceSurface { }
+    public method GetTransformSurface { }
+    public method GetOutputTransformation { }
+    public method GetOutputSurface { }
+    public method GetInitialTransformation { }
+    public method SetReferenceSurface { sur }
+    public method SetTransformSurface { sur }
+    public method SetInitialTransformation { xform }
+
+    # Set Filenames etc
+    public method    UpdateOutputFilenames { } 
+    public method    CheckInputObjects { } 
+    protected method SetCommonPointBasedRegistrationOptions { regobj }
+
+    # Generate Resliced Image
+    public method CreateWarpedSurface { }
+
+    # Generate Method 
+    public method GetExtension { } { return ".matr" }
+
+
+    # Custom Viewer for RPM
+    protected method CreateViewer { fr }
+    public method UpdateRPMViewer { visib alg currentregistration }
+    public method HasRPMGUI { } { }
+
+    protected variable currentregistration 0
+    protected variable registrationviewer  0
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_basepointbasedregistration::InitializeBasePointBasedRegistration { } {
+
+
+    # This assumes that a derived class has done some work here already
+
+    PrintDebug "bis_basepointbasedregistration::Initialize" 
+
+    set tmp $inputs
+    set inputs { 
+	{ reference_surface   "Reference Surface" pxitclsurface  ""  0}    
+	{ transform_surface   "Transform Surface" pxitclsurface  ""  1}     
+	{ initial_transform "Initial Transformation" pxitcltransform  "" 100  }
+    }
+
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend inputs [ lindex $tmp $i ]
+    }
+    
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set tmp $outputs
+    
+    set outputs { 
+	{ output_transform "Output Transformation"  pxitcltransform  "" }
+	{ output_surface   "Transformed Surface" pxitclsurface  ""  200 }
+    }
+
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+    	lappend outputs [ lindex $tmp $i ]
+    }
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    #    lappend options [ list outname  "output filename root" "Output" string ""     { "" }  -1000 ]
+    lappend options [ list matchmode   "Match Mode either RPM or ICP" "Match Mode" { listofvalues } rpm { rpm icp } 0 ]
+    lappend options [ list numpoints     "number of points "                                        "numpoints"      int  800 { 0 10000 }    1 ]
+    lappend options [ list tstart "Initial temparature "                                "tstart"         real 5.0  { 0.0 100.0 }  2 ]
+    lappend options [ list tstop  "Final temparature "                                  "tend"           real 2.0  { 0.0 100.0}    3 ]
+    lappend options [ list useinitial "Use Initial Transformation" "Use Initial Xform"  boolean   0     { 0 1 } 25 ]
+    lappend options [ list guiautosave       "AutoSave Result" "Autosave"  boolean  1 { 0 1 }  99 ]
+
+    if { $defaultsuffix == "" } {
+	set defaultsuffix { "_xform" }
+    }
+
+
+    set category    "Registration"
+    
+    if { $authors == "" } {
+	set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+    }
+
+    $this AddDefaultOptions
+}
+
+
+
+# ----------------------------------------------------------
+#
+#  Input/Output Utility Stuff
+#
+# ----------------------------------------------------------
+
+itcl::body bis_basepointbasedregistration::SetReferenceSurface  { sur } {
+    $this SetInputObject reference_surface $sur
+}
+
+itcl::body bis_basepointbasedregistration::SetTransformSurface  { sur } {
+    $this SetInputObject transform_surface $sur
+}
+
+itcl::body bis_basepointbasedregistration::SetInitialTransformation  { tr } {
+    $this SetInputObject initial_transform $tr
+}
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+itcl::body bis_basepointbasedregistration::GetReferenceSurface  { } {
+    return [ $this GetInputObject reference_surface ]
+}
+
+itcl::body bis_basepointbasedregistration::GetTransformSurface  { } {
+    return [ $this GetInputObject transform_surface ]
+}
+
+itcl::body bis_basepointbasedregistration::GetOutputTransformation  { } {
+    return [ $this GetOutputObject output_transform ]
+}
+
+itcl::body bis_basepointbasedregistration::GetOutputSurface  { } {
+    return [ $this GetOutputObject output_surface ]
+}
+
+itcl::body bis_basepointbasedregistration::GetInitialTransformation  {  } {
+    return [ $this GetInputObject initial_transform ]
+}
+
+# ------------------------------------------------------------------------------------
+#        Container Stuff 
+# ------------------------------------------------------------------------------------
+
+itcl::body bis_basepointbasedregistration::ProgressCallback   { filter lab }  {
+
+    if { $containerobject == 0 } {
+	if { $currentregistration != 0 } {
+	    $this UpdateRPMViewer 0 $this $currentregistration
+	}
+	return [ ::bis_algorithm::ProgressCallback $filter $lab ]
+    }
+
+    
+
+    set ok 0
+    catch { set ok [ $containerobject HasRPMGUI ]  }
+
+    if { $ok > 0 } {
+	$containerobject UpdateRPMViewer 0 $this $currentregistration
+    }
+    return [ ::bis_algorithm::ProgressCallback $filter $lab ]
+}
+
+# ---------------------------------------------------------------------------------------
+
+itcl::body bis_basepointbasedregistration::UpdateRPMViewer { visib alg currentreg } {
+
+
+    if { $containerobject == 0 } {
+	if {  $currentreg == 0 || $bis_viewer == 0 } {
+	    return 0
+	}
+	set dat_trn  [ $currentreg GetCurrentTransformation ]
+	set filt2m [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+	$filt2m SetInput [ [ $this GetReferenceSurface ] GetSurface ]
+	$filt2m SetTransform $dat_trn
+	$filt2m Update
+	
+	[ $this GetOutputSurface ] ShallowCopySurface [ $filt2m GetOutput ]
+	$filt2m Delete 
+
+	$bis_viewer UpdatePolygonalObject [ $this GetReferenceSurface ]   {  visible 0 } 0
+	$bis_viewer UpdatePolygonalObject [ $this GetTransformSurface ]   {  opacity 1.0 visible 1 } 0
+	$bis_viewer UpdatePolygonalObject [ $this GetOutputSurface ]     { color "1.0 1.0 0.0" opacity 0.5 visible 1 dispmode Wireframe }   1
+	return 1
+    }
+
+    set ok 0
+    catch { set ok [ $containerobject HasRPMGUI ]  }
+    if { $ok !=0 } {
+	$containerobject UpdateRPMViewer $visib $alg $currentreg
+    }
+}
+
+# ---------------------------------------------------------------------------------------
+itcl::body bis_basepointbasedregistration::UpdateInputsFromContainer { } {
+
+
+
+    if { $containerobject == 0 } {    
+	return
+    }
+
+    $this SetTransformSurface [ $containerobject GetTransformSurface ] 
+    $this SetReferenceSurface [ $containerobject GetReferenceSurface ] 
+    $this SetInitialTransformation [ $containerobject GetInitialTransformation ] 
+    [ $this GetOutputTransformation ] configure -filename ""
+    $this UpdateOutputFilenames
+
+#    puts stderr "*************************** Updating Inputs From Container ************************************"
+#    puts stderr " [ [ $this GetTransformSurface ] GetDescription ]"
+#    puts stderr " [ [ $this GetOutputTransformation ] GetDescription ]"
+    return
+
+}
+# --------------------------------------------------------------------------------------
+itcl::body bis_basepointbasedregistration::UpdateContainerWithOutput { } {
+
+    # Reslice on the fly and update viewer ......................
+
+    if { $currentregistration != 0 } {
+	return 0
+    }
+
+    set autosave [ $this GetOptionValue guiautosave ]
+
+    if { $autosave > 0 } {
+	$OutputsArray(output_transform) SaveObject
+    }
+    
+    if { $containerobject == 0 } {
+
+    } else {
+	PrintDebug "Calling Container ($this, $containerobject) SetResultsFromObject" 
+	#	puts stderr "Calling Container ($this, $containerobject) SetResultsFromObject" 
+	$containerobject SetTransformationFromObject [ $this GetOutputTransformation ] $this
+    }
+
+}
+
+# --------------------------------------------------------------------------------------------
+
+itcl::body bis_basepointbasedregistration::UpdateOutputFilenames { } {
+
+
+    set f1 [ [ $this GetOutputTransformation ] cget -filename ]
+
+    if { [ string length $f1 ] > 1 } {
+	return 1
+    }
+
+    set fname ""; 
+
+
+    if { $fname == "" } {
+	set f(0) [ $InputsArray(reference_surface) GetFileName ]
+	set f(1) [ $InputsArray(transform_surface) GetFileName ]
+
+	for { set i 0 } { $i <= 1 } { incr i } {
+	    set l($i) [ ::bis_common::SplitFileNameGZ $f($i) ]
+	    set f($i) [ file tail [ lindex $l($i) 0 ] ]
+	}
+	
+	set fname [ file join [ file dirname $f(0) ] "$f(0)_$f(1)" ]
+    }
+
+    
+    set outlist [ $this CreateDefaultOutputFileList $fname ]
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+    
+    $OutputsArray(output_transform) SetFileName "[ lindex $outlist 0 ][ $this GetExtension ]" $force
+
+    return 1
+}
+
+
+itcl::body bis_basepointbasedregistration::CheckInputObjects { } {
+
+
+    set Surface_in    [ $this GetReferenceSurface ]
+    set d [ $Surface_in GetSurfaceSize ]
+
+    if { $d < 2 } {
+	return 0
+    }
+
+    set Surface_in    [ $this GetTransformSurface ]
+    set d [ $Surface_in GetSurfaceSize ]
+
+    if { $d < 2 } {
+	return 0
+    }
+
+    return 1
+
+}
+
+itcl::body bis_basepointbasedregistration::SetCommonPointBasedRegistrationOptions { rpmxform } {
+
+    set userpm          [ $OptionsArray(matchmode)        GetValue ]
+    set numpoints       [ $OptionsArray(numpoints)     GetValue ]
+    set tstart          [ $OptionsArray(tstart)        GetValue ]
+    set tend            [ $OptionsArray(tstop)          GetValue ]
+
+    $rpmxform SetAnnealRate 0.93
+    $rpmxform SetInitialTemperature $tstart
+    $rpmxform SetFinalTemperature   $tend
+    if { $userpm == "rpm" } {
+	$rpmxform SetMatchModeToRPMFast
+    } else {
+	$rpmxform SetMatchModeToICP
+    }
+    
+    $rpmxform SetUseLabels  1
+    $rpmxform SetUseWeightedLeastSquares 1
+    $rpmxform SetFastThreshold 3.0
+    $rpmxform SetMaximumNumberOfLandmarks $numpoints
+
+
+
+    return 1
+}
+
+
+# --------------------------------------------------------------------------------------------------
+#
+#
+#
+#         Custom GUI Stuff from pxitclrpm
+#
+#
+# --------------------------------------------------------------------------------------------------
+
+itcl::body  bis_basepointbasedregistration::CreateWarpedSurface { } {
+
+    set filt2m [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $filt2m SetInput [ [ $this GetReferenceSurface ] GetSurface ]
+    $filt2m SetTransform [ [ $this GetOutputTransformation ] GetTransformation ]
+    $filt2m Update
+
+    [ $this GetOutputSurface ] ShallowCopySurface [ $filt2m GetOutput ]
+    $filt2m Delete
+
+    if { $bis_viewer != 0 } {
+	$bis_viewer UpdatePolygonalObject [ $this GetReferenceSurface ]   {  visible 0 } 0
+	$bis_viewer UpdatePolygonalObject [ $this GetTransformSurface ]   {  opacity 1.0 visible 1 } 0
+	$bis_viewer UpdatePolygonalObject [ $this GetOutputSurface ]   { color "1.0 0.8 0.0" opacity 0.9 visible 1 }  1
+    }
+}
+
+
+# -----------------------------------------------------------------------------------------------------
+
+itcl::body  bis_basepointbasedregistration::CreateViewer { par  } {
+
+    set bis_viewer [ [ bis_viewer \#auto ] GetThisPointer ]
+    $bis_viewer CreateGUI $par
+    set vtk_viewer [ $bis_viewer GetViewer ]
+    $bis_viewer AddOrReplacePolygonalObject [ $this GetReferenceSurface ]  1 { color "1.0 0.0 0.0" opacity 0.5 visible 1} 
+    $bis_viewer AddOrReplacePolygonalObject [ $this GetTransformSurface ]  1 { color "0.0 1.0 0.0" opacity 1.0 visible 1} 
+    $bis_viewer AddOrReplacePolygonalObject [ $this GetOutputSurface ]  1 { color "1.0 1.0 0.0" opacity 0.5 visible 0 dispmode Wireframe }  
+    return 1
+}
+
+itcl::body  bis_basepointbasedregistration::HasRPMGUI { } {
+
+    if { $containerobject == 0 } {
+	if { $bis_viewer > 0 } {
+	    return 1
+	}
+    }
+
+    return [ $containerobject HasRPMGUI ]
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_basethresholdimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_basethresholdimage.tcl
new file mode 100644
index 0000000..9064fe9
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_basethresholdimage.tcl
@@ -0,0 +1,166 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+package require bis_imagetoimagealgorithm 1.0
+package provide bis_basethresholdimage 1.0
+
+# -----------------------------------------------------------------------------------------
+# threshold image
+#
+
+itcl::class bis_basethresholdimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {     }
+
+    public method InitializeBaseThresholdImage { }
+    public method UpdateInputsFromContainer { }
+
+    # returns invalue outvalue replaceinvalue replaceoutvalue dobinary
+    protected method ParseArgs { }
+}
+
+# -----------------------------------------------------------------------------------------
+# InitializeBaseThresholdImage
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_basethresholdimage::InitializeBaseThresholdImage { } {
+
+    PrintDebug "bis_basethresholdimage::InitializeBaseThresholdImage" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    lappend options [ list  minth "Lower Threshold value" "Low Threshold"   real   0.0 { -100000000.0 100000000.0 }  1 ]
+    lappend options [ list  maxth "Upper Threshold value" "High Threshold"  real 100.0 { -100000000.0 100000000.0 }  2 ]
+    lappend options [ list  inverse "Inverse Threshold"  "Inverse" { listofvalues radiobuttons } Off  { On Off }  -10  ]
+    lappend options [ list binary "Binary Output" "Binary Output"   { listofvalues radiobuttons } Off  { Off On x100 }  6 ]
+
+    set defaultsuffix { "_thr" }
+    
+
+
+    #document
+    #
+    if { $description == "" } {
+	set description "thresholds an image to generate a binary output using a specific threshold."
+    }
+    if { $description2 == "" } { 
+	set description2 "The output is a binary image with value = 100 where the original image had values above the threshold and zero elsewhere."
+    }
+    set backwardcompatibility "Reimplemented from pxmat_basethresholdimage.tcl"
+    
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Update GUI
+# -----------------------------------------------------------------------------------------
+itcl::body bis_basethresholdimage::UpdateInputsFromContainer { } {
+
+#    puts stderr "In Update Inputs from Container"
+
+    bis_imagetoimagealgorithm::UpdateInputsFromContainer 
+
+
+
+    # This happens when image has changed 
+    set currentimage  [ $InputsArray(input_image) GetObject ]
+
+#    puts stderr "upd inputs :: Current Image = [ $currentimage GetDescription ]"
+
+    set r [ [ $currentimage GetImage ] GetScalarRange ]
+    set rmin [ lindex $r 0 ]
+    set rmax [ lindex $r 1 ]
+    if { $rmax == $rmin } {
+	set rmax [ expr $rmin +1 ]
+    }
+
+    $OptionsArray(minth) SetValueRange [ list $rmin $rmax ]
+    $OptionsArray(maxth) SetValueRange [ list $rmin $rmax ]
+    if { [ $OptionsArray(minth) GetValue ] == [ $OptionsArray(minth) GetDefaultValue ] } {
+	$OptionsArray(minth) SetValue $rmin
+    }
+
+    if { [ $OptionsArray(maxth) GetValue ] == [ $OptionsArray(maxth) GetDefaultValue ] } {
+	$OptionsArray(maxth) SetValue $rmax
+    }
+
+
+}
+
+
+# --------------------------------------------------------------------------------------------
+
+itcl::body bis_basethresholdimage::ParseArgs {  } {
+    
+#    puts stderr "In Parse Args"
+    
+    set bm          [ $OptionsArray(binary) GetValue ]
+    set scalef 1
+
+    set binarymask 1
+    if { $bm == "Off" } {
+	set binarymask 0
+    } elseif { $bm == "x100" } {
+	set scalef 100
+    }
+
+
+    set replaceout 1
+    set replacein  0
+
+    if { $binarymask ==1 } {
+	set replacein 1
+    } 
+
+    set invalue $scalef
+    set outvalue 0
+
+    
+    if { [ $OptionsArray(inverse) GetValue ] == "On"  } {
+
+	set outvalue $invalue
+	set invalue  0
+	set tmp $replacein
+	set replacein $replaceout
+	set replaceout $replacein
+	if { $binarymask == 0 } {
+	    set replaceout 0
+	}
+    }
+    
+    return [ list $invalue $outvalue $replacein $replaceout $binarymask ]
+}
+
+ 
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_biasfield.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_biasfield.tcl
new file mode 100755
index 0000000..6553559
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_biasfield.tcl
@@ -0,0 +1,375 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagealgorithm 1.0
+
+package provide bis_biasfield 1.0
+
+#
+# bias field correction
+#
+
+itcl::class bis_biasfield {
+
+    inherit bis_dualimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Bias Field" }
+
+    #
+    #protected
+    #
+
+    protected variable pabic_shimval ""
+
+    protected method RunSliceHomogeneity   { inputimage } 
+    protected method RunTripleSliceHomogeneity   { inputimage } 
+    protected method RunTripleSliceHomogeneityFit   { inputimage minb1 maxb1 } 
+    protected method RunPolynomial { inputimage maskimage degree numclasses resolution sigmaratio minb1 maxb1 }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_biasfield::Initialize { } {
+
+    PrintDebug "bis_biasfield::Initialize" 
+    #name,description,type,object,filename(if applicable),priority (optional)
+
+    set outputs {
+	{ bias_field_image "Bias Field Estimate"  pxitclimage  "" 120 }
+    }
+
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ initmode "Preprocessing mode, none, slice or triple slice" "Initialization Moode" listofvalues None { None Slice TripleSlice } 0 }
+	{ mode "Fitting Mode either None, Quadratic or Cubic" "Mode" listofvalues Quadratic { None Quadratic Cubic } 1 }
+	{ numclasses    "Number of classes = number of tissue labels (background is a tissue label so add this) for polynomial" "Number Of Classes" int  3   { 2 10 }  2 }
+	{ resolution    "resolution sampling for polynomial estimation " "Resolution" int  3   { 1 5 }  3 }
+	{ maxsigmaratio    "The program assumes this as the ratio of the max standard deviation to the min standard deviation. This helps the program to prevent from detecting false peak from the histogram." "Max Sigma Ratio" real  0.2   { 0.1 1.0 }  -100 }
+	{ minb1    "The program assumes this as the minimum value of the field B1 " "Min B1" real  0.2   { 0.1 0.95 }  -101 }
+	{ maxb1    "The program assumes this as the maximum value of the filed B1 " "Max B1" real  5.0   { 1.1 10.0 }  -102 }
+	{ usemask  "Use Mask Image" "Use Mask" boolean   0  { 0 1 } 25 }
+    }
+    
+    set defaultsuffix { "restored" "biasfield" }
+    
+    set scriptname bis_biasfield
+
+    #
+    #document
+    #
+
+    set category "Image Processing Dual"
+    set description "corrects bias field"
+    set description2 "uses either simple linear inhomogeneity model algrotihm or PABIC's algorithm"
+    set backwardcompatibility "Reimplemented from pxmat_biasfieled.tcl.The default output filename was ****_pabic etc, Now you need to specify output filename explicitly. "
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this InitializeDualImageAlgorithm
+
+    $this RenameInput 1 "Mask Image" 102
+
+}
+# ---------------------------------------------------------------------------------------------------------
+
+itcl::body bis_biasfield::RunSliceHomogeneity   { inputimage } { 
+
+    set fit [ vtkpxSliceBiasFieldCorrection  [ pxvtable::vnewobj ]]
+    $fit SetRobustMode  1
+    $fit SetPureScaling 0
+    $fit SetInput       $inputimage
+
+	
+    $fit Update
+
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+    $img ShallowCopy [ $fit GetOutput ]
+
+    set bfield [ vtkImageData [ pxvtable::vnewobj ]]
+    $bfield ShallowCopy [ $fit GetBiasField ]
+    $fit Delete
+    return [ list $img $bfield ] 
+}
+# ----------------------------------------------------------------------------------------------------
+itcl::body bis_biasfield::RunTripleSliceHomogeneity   { inputimage } { 
+
+    set axislist { x y z }
+
+    set output [ vtkImageData [ pxvtable::vnewobj ]]
+    set bfield [ vtkImageData [ pxvtable::vnewobj ]]
+    $output ShallowCopy $inputimage
+    
+    for { set axis 0 } { $axis <=2 } { incr axis } {
+	puts stderr ".... Slice Inhomogeneity Correction orientation  axis= [ lindex $axislist $axis ]\n"
+	set fit [ vtkpxSliceBiasFieldCorrection  [ pxvtable::vnewobj ]]
+	$fit SetAxis $axis
+	$fit SetRobustMode  1
+	$fit SetPureScaling 0
+	$fit SetInput       $output
+	$fit Update
+	$output ShallowCopy [ $fit GetOutput ]
+	$bfield ShallowCopy [ $fit GetBiasField ]
+	$fit Delete
+    }
+    return [ list $output $bfield ]
+}
+# ----------------------------------------------------------------------------------------------------
+itcl::body bis_biasfield::RunTripleSliceHomogeneityFit   { inputimage minb1 maxb1 } { 
+
+    
+    for { set axis 0 } { $axis <=2 } { incr axis } {
+	puts stderr ".... Slice Inhomogeneity Correction orientation  axis= $axis /2\n"
+	set fit [ vtkpxSliceBiasFieldCorrection  [ pxvtable::vnewobj ]]
+	$fit SetAxis $axis
+	$fit SetRobustMode  1
+	$fit SetPureScaling 0
+	$fit SetInput       $inputimage
+	$fit Update
+
+	set p [ vtkFloatArray [ pxvtable::vnewobj ]]
+	$fit PolynomialFitToParameters 2 $p
+	if { $axis == 0 } {
+	    set pabic_shimval(0) [ $p GetComponent 0 0 ]
+	    set pabic_shimval(3) [ $p GetComponent 1 0 ]
+	} elseif { $axis == 1 } {
+	    set pabic_shimval(1) [ $p GetComponent 0 0 ]
+	    set pabic_shimval(4) [ $p GetComponent 1 0 ]
+	} else { 
+	    set pabic_shimval(2) [ $p GetComponent 0 0 ]
+	    set pabic_shimval(5) [ $p GetComponent 1 0 ]
+	}
+	$fit Delete
+	$p Delete
+    }
+
+
+    set fit [ vtkpxPolynomialBiasFieldCorrection  [ pxvtable::vnewobj ]]
+    set db [ vtkDoubleArray [ pxvtable::vnewobj ]]
+    $db SetNumberOfTuples 18
+    $db FillComponent 0 0.0
+    for { set i 0 } { $i <= 5 } { incr i } {
+	$db SetComponent $i 0 $pabic_shimval($i) 
+    }
+    set tmp [ $fit ComputeBiasFieldImage [ $currentimage GetImage ] $db  2 $minb1 $maxb1 ]
+    set outimage [ $fit ComputeCorrectedImage $inputimage $tmp  ]
+
+
+    $db Delete
+    $fit Delete
+
+    return [ list  $outimage $tmp ]
+}
+
+# ----------------------------------------------------------------------------------------------------
+
+itcl::body bis_biasfield::RunPolynomial { inputimage maskimage degree numclasses resolution sigmaratio minb1 maxb1 } {
+
+    puts stdout "input=$inputimage mask=$maskimage"
+
+    set fit [ vtkpxPolynomialBiasFieldCorrection  [ pxvtable::vnewobj ]]
+
+    if { $maskimage !=0 } {
+	$fit SetMaskImage $maskimage
+    } 
+    $fit SetInput                $inputimage
+    $fit SetMetric               0
+    $fit SetNumberOfLevels       1
+    $fit SetNumberOfSteps        1
+    $fit SetResolution           $resolution
+    $fit SetStepSize             0.05
+    $fit SetNumberOfIterations   10
+    $fit SetEpsilon              0.1
+    $fit SetDegree               $degree
+    $fit SetOptimizationMethodToConjugateGradient
+    $fit SetFrame               0
+    $fit SetMinValue            $minb1
+    $fit SetMaxValue            $maxb1
+    $fit SetHisto_NumberOfClasses  $numclasses
+    $fit SetHisto_Iterations       50
+    $fit SetHisto_NumberOfBins    256
+    $fit SetHisto_Convergence     0.05
+    $fit SetHisto_Sigma           0.05
+    $fit SetHisto_MaxSigmaRatio     $sigmaratio
+    $fit SetHisto_OutlierDetection 0 
+    $fit SetHisto_PreprocessingMode 2
+    $fit Update
+
+    set outimage [ vtkImageData [ pxvtable::vnewobj ]]
+    $outimage ShallowCopy [ $fit GetOutput ]
+
+    set bfield [ vtkImageData [ pxvtable::vnewobj ]]
+    $bfield ShallowCopy [ $fit GetBiasField ]
+
+    $fit Delete
+    return [ list $outimage $bfield ]
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_biasfield::Execute {  } {
+
+    DebugOn
+    PrintDebug "bis_biasfield::Execute"
+
+    set initmode    [ $OptionsArray(initmode)      GetValue ]
+    set mode        [ $OptionsArray(mode)      GetValue ]
+
+    if { $initmode == "None" && $mode=="None" } {
+	set errormessage "Nothing to do both mode and initmode are set to None"
+	return 0
+    }
+
+    set usemask      [ $OptionsArray(usemask)      GetValue ]
+    set mode        [ $OptionsArray(mode)      GetValue ]
+    set numclasses  [ $OptionsArray(numclasses)      GetValue ]
+    set resolution  [ $OptionsArray(resolution)      GetValue ]
+    set sigmaratio  [ $OptionsArray(maxsigmaratio)      GetValue ]
+    set minb1        [ $OptionsArray(minb1)      GetValue ]
+    set maxb1        [ $OptionsArray(maxb1)      GetValue ]
+    set image_in    [ $InputsArray(input_image) GetObject ]
+    set mask_in 0
+
+
+    set outimage 0
+
+    set tmplist ""
+
+    
+    set degree 3
+    if { $mode == "None" } { 
+	set degree 0
+    } elseif { $mode == "Quadratic" } {
+	set degree 2
+    }
+
+    if { $usemask > 0 && $degree > 0 } {
+	set mask_in    [ $InputsArray(second_image) GetObject ]
+	if { [ $mask_in GetImageSize ] !=  [ $image_in GetImageSize ] } {
+	    set errormessage "Supplied mask does not have the same dimensions as the input image"
+	    return 0
+	} else {
+	    puts stdout "Supplied mask [ $mask_in GetImageSize ] does not have the same dimensions as the input image [ $image_in GetImageSize ]"
+	}
+    }
+
+    set md 0
+    if { $initmode == "Slice" }  {
+	set md 1
+    } elseif { $initmode == "TripleSlice" } {
+	set md 2
+    }
+
+    set tmplst  ""
+    set deletetmplst 0
+    set outlst ""
+    set outimage [ [ $this GetInput ] GetImage ]
+
+    puts stderr "Md=$md, degree=$degree"
+
+    if { $md ==  1 } {
+	puts stderr "Running Slice"
+	set outlst [ RunSliceHomogeneity [$image_in GetObject]]
+	set outimg [ lindex $outlst 0 ]
+	set modename "slicehom"
+	set deletetmplst 1
+    } elseif { $md == 2 } {
+	puts stderr "Running Triple Slice"
+	set outlst [ RunTripleSliceHomogeneity [$image_in GetObject]]
+	set outimg [ lindex $outlst 0 ]
+	set modename "triplehom"
+	set deletetmplst 1
+    } 
+
+    if { $degree > 0 } {
+	set modename "pabic${degree}"
+	set tmplst $outlst
+	puts stderr "Running Polynomial degree=$degree"
+	if { $usemask > 0 } {
+	    set msk [ $mask_in GetImage ]
+	} else {
+	    set msk 0
+	}
+	set outlst [ RunPolynomial $outimage  $msk $degree $numclasses $resolution $sigmaratio $minb1 $maxb1 ]
+    }
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage [ lindex $outlst 0 ]
+    [ $OutputsArray(bias_field_image) GetObject ] ShallowCopyImage [ lindex $outlst 1 ]
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set bfield [ $OutputsArray(bias_field_image) GetObject ]
+    $bfield CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ $this GetCommandLine "full" ]
+
+    [ $outimage GetImageHeader ] AddComment $comment 0
+
+    for { set i 0 } { $i < [ llength $outlst ] } { incr i } {
+	[ lindex $outlst $i ] Delete
+    }
+
+    if { $deletetmplst > 0 } {
+	for { set i 0 } { $i < [ llength $tmplist ] } { incr i } {
+	    [ lindex $tmplst $i ] Delete
+	}
+    }
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_biasfield.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_biasfield [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_blendimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_blendimage.tcl
new file mode 100755
index 0000000..6a5a3e6
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_blendimage.tcl
@@ -0,0 +1,206 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagereslicetransformationalgorithm 1.0
+package provide bis_blendimage 1.0
+
+#
+# blend image
+#
+
+itcl::class bis_blendimage {
+
+    inherit bis_dualimagereslicetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Image Blend"}
+
+    protected method ConfigureOptionsGUICallbacks { } 
+    public    method AutoBlend { args } 
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_blendimage::Initialize { } {
+
+    PrintDebug "bis_blendimage::Initialize" 
+
+    set options {
+	{ interp      "Interpolation Mode that is used when reslicing the image" "Interpolation Mode"  listofvalues Linear { "NearestNeighbor" "Linear" "Cubic" }  -10 }
+	{ background  "Background Level used to fill voxels outside of mapped area" "Background Value"  real 0.0 { -100000 100000 }  -100 }
+	{ blend       "Weight (between 0 and 100) of target image" "Blend"  { real scale } 50.0 { 0.0 100.0 }  1 }
+	{ guiautoupdate  "Auto Update on changing scale values" "Auto-update"  { boolean } 0 { 0 1 }  2 }
+	{ scale      "Image 1: Scale" "Scale Image 1"   real    1.0 { 0.0 10000.0 }  3 }
+    }
+
+    set defaultsuffix { "_blend" }
+    
+    set scriptname bis_blendimage
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    set category "Image Processing Dual"
+    set description "blends an image using one or more transformations."
+    set description2 "a useful check of the quality of the transformations"
+    set backwardcompatibility "Reimplemented from pxmat_blendimage.tcl."
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageTransformationAlgorithm
+    $this SetUseReslicedImageAsInput 1
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_blendimage::ConfigureOptionsGUICallbacks { } {
+
+    eval "$OptionsArray(blend) SetGUICallbackFunction { $this AutoBlend }"
+}
+
+itcl::body bis_blendimage::AutoBlend {  args } {
+
+    if { [ $OptionsArray(guiautoupdate) GetValue ] ==0 } {
+	return
+    }
+
+    $OptionsArray(blend) SetGUICallbackFunction ""
+    $this InvokeAlgorithmFromGUI 
+    $this ConfigureOptionsGUICallbacks
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_blendimage::Execute {  } {
+
+    PrintDebug "bis_blendimage::Execute"
+
+    set lst [ $this ResliceImageIfNeeded ]
+    set reslimage [ lindex $lst 0 ]
+
+    set dt [ $reslimage  GetScalarType ]
+    set num [ $reslimage  GetNumberOfScalarComponents ]
+    set num2 [ [ [ $this GetInput ] GetImage ] GetNumberOfScalarComponents ]
+
+
+
+    set blendCreator [ vtkImageBlend [ pxvtable::vnewobj ]]    
+
+    # VTK_UNSIGNED_CHAR == 3
+    if { $dt == 3 &&  $num == 3 && $num2 ==1 } {
+	puts stdout "Need 3 color image"
+	set img [ vtkImageData New ]
+	$img CopyStructure  [ [ $this GetInput ] GetImage ]
+	$img SetNumberOfScalarComponents 3
+	$img SetScalarType  [ [ [ $this GetInput ] GetImage ] GetScalarType ]
+	$img AllocateScalars
+	for { set i 0 } { $i <=2 } { incr i } {
+	    [ [ $img GetPointData ] GetScalars ] CopyComponent $i [ [ [ [ $this GetInput ] GetImage ] GetPointData ] GetScalars ] 0 
+	}
+
+	set imcast2 [ vtkImageShiftScale [ pxvtable::vnewobj ]]
+	$imcast2 SetInput $img
+	$img Delete
+	
+	#	puts stdout "Appending to create color image"
+	$imcast2 SetShift 0.0
+	$imcast2 SetScale  [ $OptionsArray(scale) GetValue ]
+	$imcast2 ClampOverflowOn
+	$imcast2 SetOutputScalarType $dt
+	puts stdout "Scale  = [ $imcast2 GetScale ] dt=$dt"
+	$imcast2 Update
+	puts stdout "Input1 [ [ $imcast2 GetOutput ] GetDimensions ], [ [ $imcast2 GetOutput ] GetScalarRange ]"
+	$blendCreator AddInput [ $imcast2 GetOutput ]
+	$blendCreator AddInput $reslimage 
+	$imcast2 Delete 
+    } else {
+	#	puts stdout "Just casting"
+	set imcast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+	$imcast2 SetInput $reslimage
+	$imcast2 SetOutputScalarType [ [ [ $this GetInput ] GetImage ] GetScalarType ]
+	$imcast2 Update
+	$blendCreator AddInput [ [ $this GetInput ] GetImage ]
+	$blendCreator AddInput [ $imcast2 GetOutput ]
+	$imcast2 Delete 
+    }
+
+    set bl [ expr [ $OptionsArray(blend) GetValue ] /100.0 ]
+
+
+    $blendCreator SetOpacity 1 $bl
+    SetFilterCallbacks $blendCreator "Blending Images"
+    $blendCreator Update
+    
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage [ $blendCreator GetOutput ]
+
+    # Output orientation etc. is same as input
+    set outimage [ $this GetOutput ] 
+    set pimage   [ $this GetSecondInput ] 
+
+    $outimage CopyImageHeader [ $pimage GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    $blendCreator Delete
+
+    $this DeleteResliceAlgorithmIfNeeded $lst 
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_blendimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+   
+
+    set alg [bis_blendimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_castimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_castimage.tcl
new file mode 100755
index 0000000..dbe35d8
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_castimage.tcl
@@ -0,0 +1,148 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+
+package provide bis_castimage 1.0
+
+#
+# cast image
+#
+
+itcl::class bis_castimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Cast Image" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_castimage::Initialize { } {
+
+    PrintDebug "bis_castimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ type "output image type.Specify one of  Float , Double or Short" "Type"  listofvalues  Float { Float Double Short }  0 }
+    }
+
+    set defaultsuffix { "_cast" }
+    
+    set scriptname bis_castimage
+
+    set completionstatus "Done Needs testing, perhaps add more types"
+
+
+    set description "cast (or convert) image data type."
+    set description2 "type can be one of float, double, or short"
+    set backwardcompatibility "N/A."
+    set authors "hirohito.okuda at yale.edu"
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_castimage::Execute {  } {
+
+    PrintDebug "bis_castimage::Execute starts.."
+
+    set type   [ $OptionsArray(type) GetValue ]
+
+    set image_in    [ $InputsArray(input_image) GetObject ]
+
+    #vtkImageCast
+    set cast [vtkImageCast [pxvtable::vnewobj]]
+    $cast SetInput [$image_in GetObject]
+    switch $type {
+	Float { 
+	    $cast SetOutputScalarTypeToFloat
+	}
+	Double { 
+	    $cast SetOutputScalarTypeToDouble
+	}
+	Short { 
+	    $cast SetClampOverflow 32767
+	    $cast SetOutputScalarTypeToShort
+	}
+	default {
+	    $cast SetOutputScalarTypeToFloat
+	}
+    }
+    $this SetFilterCallbacks $cast "Casting Image"
+    $cast Update
+    set image_out [ $cast GetOutput ]
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage  $image_out
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    $cast Delete
+    PrintDebug "bis_castimage::Execute ends.."
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_castimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main functionsSaveOb
+
+    
+
+    set alg [bis_castimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_checkerboardimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_checkerboardimage.tcl
new file mode 100755
index 0000000..2ffde39
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_checkerboardimage.tcl
@@ -0,0 +1,150 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagereslicetransformationalgorithm 1.0
+package provide bis_checkerboardimage 1.0
+
+#
+# blend image
+#
+
+itcl::class bis_checkerboardimage {
+
+    inherit bis_dualimagereslicetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "CheckerBoard"}
+
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_checkerboardimage::Initialize { } {
+
+    PrintDebug "bis_checkerboardimage::Initialize" 
+
+    set options {
+		{ interp        "Interpolation Mode that is used when reslicing the image" "Interpolation Mode"  listofvalues Linear { "NearestNeighbor" "Linear" "Cubic" }  0 }
+		{ spacing      "Checkerboard spacing" "Checkerboard spacing"  listofvalues 12 { 2 5 8 10 11 16 23 32 }  0 }
+		{ background  "Background Level used to fill voxels outside of mapped area" "Background Value"  real 0.0 { -100000 100000 }  -100 }
+		{ normalizeimages  "Normalize images" "Normalize Images"  { boolean } 0 { 0 1 }  1 }
+    }
+	
+    set defaultsuffix { "_checkerboard" }
+    
+    set scriptname bis_checkerboardimage
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    set category "Image Processing Dual"
+    set description "Creates checkerboard image"
+    set description2 "a useful check of the quality of the transformations"
+    set backwardcompatibility "Reimplemented from pxmat_blendimage.tcl."
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageTransformationAlgorithm
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_checkerboardimage::Execute {  } {
+
+    PrintDebug "bis_checkerboardimage::Execute"
+    set lst [ $this ResliceImageIfNeeded ]
+    set reslimage [ lindex $lst 0 ]
+
+    
+    set imcast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+    $imcast2 SetInput $reslimage
+    $imcast2 SetOutputScalarType [ [ [ $this GetInput ] GetImage ] GetScalarType ]
+    $imcast2 Update
+
+    set sq [ expr round ([ $OptionsArray(spacing) GetValue ]) ] 
+
+
+    set checkerboardCreator [  vtkpxCreateCheckerBoardImage [ pxvtable::vnewobj ]]
+    $checkerboardCreator SetInput [ [ $this GetInput ] GetImage ]
+    $checkerboardCreator SetInput2 [ $imcast2 GetOutput ]
+    $checkerboardCreator SetSquareSize $sq
+    $checkerboardCreator SetNormalizeImages [ $OptionsArray(normalizeimages) GetValue ]
+    $checkerboardCreator Update
+    
+    $imcast2 Delete 
+    
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage [ $checkerboardCreator GetOutput ]
+
+    # Output orientation etc. is same as input
+    set outimage [ $this GetOutput ] 
+    set pimage   [ $this GetSecondInput ] 
+
+    $outimage CopyImageHeader [ $pimage GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    $checkerboardCreator Delete
+    $this DeleteResliceAlgorithmIfNeeded $lst 
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_checkerboardimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+   
+
+    set alg [bis_checkerboardimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_cleansurface.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_cleansurface.tcl
new file mode 100755
index 0000000..471a5e4
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_cleansurface.tcl
@@ -0,0 +1,167 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_surfacetosurfacealgorithm 1.0
+
+package provide bis_cleansurface 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_cleansurface {
+
+    inherit bis_surfacetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Clean Surface" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_cleansurface::Initialize { } {
+
+    PrintDebug "bis_cleansurface::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ cleanTolerance "Specify the tolerance for the cleansurface algorithm" "Clean Tolerance"  { real triplescale 100 }    0.1 { 0.0 20.0 }  0 }
+	{ cleanMethod "Pick a smoothing method: Distance Sampling or Quadric Clustering. " "Clean Method" { listofvalues radiobutton}  Distance_Sampling { Distance_Sampling Quadric_Clustering}   1}
+    }
+
+    set defaultsuffix { "_clean" }
+    
+    set scriptname bis_cleansurface
+
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "smooths a surface "
+    set description2 ""
+    set backwardcompaibitlity "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeSurfacetoSurfaceAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_cleansurface::Execute {  } {
+
+    PrintDebug "bis_cleansurface::Execute"
+
+    # Get Inputs
+    set surface    [ $this GetInput  ]
+    # GetOptions
+    
+    set cleanTolerance [ $OptionsArray(cleanTolerance) GetValue ]
+    set cleanMethod [ $OptionsArray(cleanMethod)      GetValue ]
+    
+    # Run Algorithm
+    
+    if { $cleanMethod == "Distance_Sampling"} {
+	set cleanfilter [ vtkCleanPolyData [ pxvtable::vnewobj ] ]
+	$cleanfilter SetInput [ $surface GetObject ]
+	$cleanfilter SetToleranceIsAbsolute 1 
+	$cleanfilter SetAbsoluteTolerance $cleanTolerance
+	$cleanfilter Update
+	
+	set surface_out [$cleanfilter GetOutput ]
+	[ $OutputsArray(output_surface) GetObject ] DeepCopySurface  $surface_out
+	$cleanfilter Delete
+
+    } else {
+	set trianglefilter [vtkTriangleFilter [ pxvtable::vnewobj ] ]
+	$trianglefilter SetInput [ $surface GetObject ]
+	$trianglefilter Update
+	
+	set bounds [ [ $trianglefilter GetOutput] GetBounds]
+	
+	set clusterFilter [ vtkQuadricClustering [ pxvtable::vnewobj ] ]
+	$clusterFilter SetInput [ $trianglefilter GetOutput]
+	
+	set b0 [ lindex $bounds 0]
+	set b1 [ lindex $bounds 1]
+	set b2 [ lindex $bounds 2]
+	set b3 [ lindex $bounds 3]
+	set b4 [ lindex $bounds 4]
+	set b5 [ lindex $bounds 5]
+	
+	$clusterFilter SetDivisionOrigin $b0 $b2 $b4
+	$clusterFilter SetDivisionSpacing $cleanTolerance $cleanTolerance $cleanTolerance 
+	
+	set xdiv [ expr {int (1.5 + (($b1 - $b0)/$cleanTolerance))} ]
+	set ydiv [ expr {int (1.5 + (($b3 - $b2)/$cleanTolerance))} ]
+	set zdiv [ expr {int (1.5 + (($b5 - $b4)/$cleanTolerance))} ]
+	
+#	puts stderr "xdiv=$xdiv, $ydiv, $zdiv, $bounds, [ $clusterFilter GetDivisionOrigin ], [ $clusterFilter GetDivisionSpacing]"
+	
+	$clusterFilter SetNumberOfXDivisions $xdiv
+	$clusterFilter SetNumberOfYDivisions $ydiv
+	$clusterFilter SetNumberOfZDivisions $zdiv
+	$clusterFilter Update
+	
+	puts "Numpoints = [ [$clusterFilter GetOutput ] GetNumberOfPoints ]"
+
+	[ $OutputsArray(output_surface) GetObject ] DeepCopySurface  [$clusterFilter GetOutput ]
+	$clusterFilter Delete
+	
+    }
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_cleansurface.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_cleansurface [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_clipsurface.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_clipsurface.tcl
new file mode 100755
index 0000000..bf0decd
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_clipsurface.tcl
@@ -0,0 +1,146 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_clipsurface 1.0
+package require bis_imageandsurfacetosurfacealgorithm 1.0
+
+
+
+itcl::class bis_clipsurface {
+
+    inherit bis_imageandsurfacetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Clip Surface" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_clipsurface::Initialize { } {
+
+    PrintDebug "bis_clipsurface::Initialize" 
+
+     #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+		{ lowthreshold "Low Threshold" "Low Threshold"  { real triplescale 100 }    0.0 { 0.0 1096.0 }  0 }
+		{ highthreshold "High Threshold" "High Threshold"  { real triplescale 100 }    255.0 { 0.0 1096.0 }  1 }
+    }
+	
+    set defaultsuffix { "_clipsurface" }
+    
+    set scriptname bis_clipsurface
+
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "Clip polygonal data with user-specified implicit function or input scalar data"
+    set description2 ""
+    set backwardcompatibility "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+
+
+    $this InitializeImageandSurfacetoSurfaceAlgorithm 
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_clipsurface::Execute {  } {
+
+    PrintDebug "bis_clipsurface::Execute"
+
+    # Get Inputs
+    set surface    [ $this GetInputSurface  ]
+    # GetOptions
+    set lowthreshold [ $OptionsArray(lowthreshold) GetValue ]
+    set highthreshold [ $OptionsArray(highthreshold) GetValue ]
+
+    set image_in [ $this GetInputImage ] 
+    
+   # Run Algorithm    
+    set thrfilter [ vtkImageThreshold [ pxvtable::vnewobj ] ]
+    $thrfilter SetInput [ $image_in GetImage ]
+	$thrfilter ThresholdBetween $lowthreshold  $highthreshold 
+    $thrfilter SetOutValue 0.0
+    $thrfilter SetInValue 1.0
+    $thrfilter ReplaceInOn
+    $thrfilter ReplaceOutOn
+    $thrfilter Update 
+
+    set vol [ vtkImplicitVolume [ pxvtable::vnewobj ] ]
+    $vol SetVolume [ $thrfilter GetOutput ]
+    $vol SetOutValue 0.0
+
+    set clipfilter [ vtkClipPolyData [ pxvtable::vnewobj ] ]
+    $clipfilter SetInput  [ $surface GetObject ]
+    $clipfilter SetClipFunction $vol
+    $clipfilter GenerateClipScalarsOff
+    $clipfilter SetValue 0.5
+    $clipfilter Update
+	
+    # Store Results in output
+    set surface_out [$clipfilter GetOutput ]
+    [ $OutputsArray(output_surface) GetObject ] DeepCopySurface $surface_out 
+
+    # Clean up
+    $thrfilter Delete
+    $clipfilter Delete
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_clipsurface.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_clipsurface [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_clusterthresholdimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_clusterthresholdimage.tcl
new file mode 100755
index 0000000..4d03ac3
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_clusterthresholdimage.tcl
@@ -0,0 +1,261 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_basethresholdimage 1.0
+package require bis_thresholdimage 1.0
+
+package provide bis_clusterthresholdimage 1.0
+
+# -----------------------------------------------------------------------------------------
+# threshold image
+#
+
+itcl::class bis_clusterthresholdimage {
+
+    inherit bis_basethresholdimage
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Cluster Threshold" }
+    public method UpdateInputsFromContainer { }
+
+};
+
+
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_clusterthresholdimage::Initialize { } {
+
+    PrintDebug "bis_clusterthresholdimage::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ clustersize "Cluster Threshold Value" "Cluster Size"  integer  100 { 0 100000000 }  4 }
+	{ oneconnected  "Use 1-Connected Clustering (if off use 3x3x3 cube around voxel, if on using 6 neighbors of voxel)"  "1-Connected" boolean  1 { 0 1 }  -10 }
+	{ outputclustno "Output Cluster Number" "Output Cluster Number"  boolean  0 { 0 1 }  7 }
+	{ absolutevalue "Cluster Based on Absolute Value of input" "Absolute Value"  boolean  0 { 0 1 }  -12 }
+	{ frame   "Frame to use when clustering" "Frame"  integer  1 { 0 100000000 }  11 }
+    }
+
+    set defaultsuffix { "_cthr" }
+    
+    set scriptname bis_clusterthresholdimage
+    set completionstatus "Implementation needs work, interface is OK" 
+    #document
+    #
+    set description "thresholds an image to generate a binary output using a specific threshold and clusters to a certain voxel size."
+    set description2 "The output is a binary image with value = 100 where the original image had values above the threshold and zero elsewhere."
+    set backwardcompatibility "Reimplemented from pxmat_clusterthresholdimage.tcl"
+    
+
+    $this InitializeBaseThresholdImage
+}
+
+# -----------------------------------------------------------------------------------------
+# Update GUI
+# -----------------------------------------------------------------------------------------
+itcl::body bis_clusterthresholdimage::UpdateInputsFromContainer { } {
+
+
+    bis_basethresholdimage::UpdateInputsFromContainer 
+
+    # This happens when image has changed 
+    set currentimage  [ $InputsArray(input_image) GetObject ]
+    set d [ $currentimage GetImageSize ]
+
+    $OptionsArray(clustersize) SetValueRange [ list 0 $d ]
+
+    set r [ [ [ [ $currentimage GetImage ] GetPointData ] GetScalars ] GetRange ]
+    set minr [ expr [ lindex $r 0 ] + 0.8 * [ lindex $r 1 ]]
+    set maxr [ lindex $r 1 ]
+
+    $OptionsArray(minth) SetValue $minr
+    $OptionsArray(maxth) SetValue $maxr
+
+}
+
+# --------------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_clusterthresholdimage::Execute {  } {
+
+    set lst [ $this ParseArgs ]
+    set invalue  [ lindex $lst 0 ]
+    set outvalue [ lindex $lst 1 ]
+    set replin   [ lindex $lst 2 ] 
+    set replout  [ lindex $lst 3 ]
+    set dobinary [ lindex $lst 4 ]
+    set minth         [ $OptionsArray(minth) GetValue ]
+    set maxth         [ $OptionsArray(maxth) GetValue ]
+    set clustsize     [ $OptionsArray(clustersize) GetValue ]
+    set shownumber    [ $OptionsArray(outputclustno) GetValue ]
+
+    #    set util [ vtkpxUtil New ]
+
+
+    #$util SaveAnalyze 00_inp.hdr [ [ $this GetInput ] GetImage ] 0
+
+    # ---------------------------------------------------------------------
+    # First Threshold the Image as usual ....
+
+    set frame [ expr [ $OptionsArray(frame) GetValue ] -1 ]
+    set numc [ [ [ $this GetInput ] GetImage ] GetNumberOfScalarComponents ]
+
+    set extr 0
+    if { $numc > 1 } {
+	if { $frame  <  0 } { set frame 0 } 
+	if { $frame  >= $numc } { set frame [ expr $numc -1 ] }
+	
+	set extr [ vtkImageExtractComponents [ pxvtable::vnewobj ]]
+	$extr SetInput [ [ $this GetInput ] GetImage ]
+	$extr SetComponents $frame
+	$extr Update
+	set img [ $extr GetOutput ]
+    } else {
+	set img [ [ $this GetInput ] GetImage ]
+    }
+
+    
+    set abs [ $OptionsArray(absolutevalue) GetValue ]
+    set clusterThreshold [ vtknrImageCluster New ]
+    if { $abs == 0 } {
+	set thresholdF  [  vtkImageThreshold New ]
+	$thresholdF ThresholdBetween  $minth $maxth
+	$thresholdF SetInValue    100
+	$thresholdF SetOutValue   0
+	$thresholdF ReplaceOutOn
+	$thresholdF ReplaceInOn
+	$thresholdF SetInput $img
+	$thresholdF SetOutputScalarTypeToInt
+	SetFilterCallbacks $thresholdF "Thresholding image"
+	$thresholdF Update
+	$clusterThreshold SetInput [ $thresholdF GetOutput ] 
+	$thresholdF Delete
+	$clusterThreshold SetIntensityThreshold 50
+    } else {
+	$clusterThreshold SetIntensityThreshold $minth
+	$clusterThreshold SetInput $img
+    }
+
+    $clusterThreshold SetOneConnected  [ $OptionsArray(oneconnected) GetValue ]
+    SetFilterCallbacks $clusterThreshold "Clustering image $abs"
+    $clusterThreshold Update
+    
+    set rr [ [ [ [ $clusterThreshold GetOutput ] GetPointData ] GetScalars ] GetRange ]
+    pxtkprint "\nCluster Threshold: Cluster Size Range $rr\n"
+
+    $OptionsArray(clustersize) SetValueRange [ list 0 [ lindex $rr 1 ] ]
+
+    # Then Figure out the Threshold by size if need be
+    set imageThreshold [ vtkImageThreshold New ]
+    $imageThreshold SetInput [ $clusterThreshold GetOutput ]
+    $imageThreshold ThresholdByUpper $clustsize
+    SetFilterCallbacks $imageThreshold "Thresholding Clustered image"
+    $imageThreshold ReplaceInOn
+    $imageThreshold SetInValue $invalue 
+    $imageThreshold ReplaceOutOn
+    $imageThreshold SetOutValue 0
+
+
+    #    puts stderr "Dobinary=$dobinary, shownumber=$shownumber "
+
+    set math 0
+    if { $shownumber == 1 || $dobinary == 0 } {
+	set math [ vtkImageMathematics New ]
+    }
+
+    if { $shownumber == 1 } {
+	$imageThreshold SetOutputScalarType [ [ $clusterThreshold GetClusterNumberImage ] GetScalarType  ]
+	set tmp [ vtkImageData New ]
+	$tmp ShallowCopy [ $clusterThreshold GetClusterNumberImage ]
+	$clusterThreshold RenumberClusterImage $tmp [expr int($clustsize)]
+	$math SetInput1 $tmp
+	#	puts stderr "Math Input 1 = renumber cluster image = [ $tmp GetScalarType ]"
+	$tmp Delete
+    } elseif { $dobinary == 0 } {
+	$imageThreshold SetOutputScalarType [ [ [ $this GetInput ] GetImage ] GetScalarType ]
+	$math SetInput1 $img 
+    }
+    
+    $imageThreshold Update
+    if { $math !=0 } {
+	$math SetInput2 [ $imageThreshold GetOutput ]
+	#puts stderr "Math Input 2 = threshold image = [ [ $imageThreshold GetOutput ] GetScalarType ]"
+	$math SetOperationToMultiply
+	$math Update
+	$imageThreshold Delete
+	if { $dobinary != 0 } {   
+	    pxtkconsole
+	    set ncl [ [ [ [ $math GetOutput ] GetPointData ] GetScalars ] GetRange ]
+	    pxtkprint "Total Number Of Clusters > $clustsize = [ lindex $ncl 1 ]\n"
+	}
+	set outfilter $math 
+    } else {
+	set outfilter $imageThreshold 
+    }
+
+    # ----------------------------------------------------------------------
+
+    set outimage [ $this GetOutput ]
+    $outimage ShallowCopyImage [ $outfilter GetOutput ] 
+    $outimage CopyImageHeader  [ [ $this GetInput ] GetImageHeader ]
+    [ $outimage GetImageHeader ] AddComment "[ $this GetCommandLine full ]" 0
+
+    catch { $clusterThreshold Delete }
+    catch { $outfilter Delete }
+    catch { $extr Delete }
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_clusterthresholdimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    set alg [bis_clusterthresholdimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_colorblendimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_colorblendimage.tcl
new file mode 100755
index 0000000..332fdf8
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_colorblendimage.tcl
@@ -0,0 +1,252 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagereslicetransformationalgorithm 1.0
+package provide bis_colorblendimage 1.0
+
+#
+# blend image
+#
+
+itcl::class bis_colorblendimage {
+
+    inherit bis_dualimagereslicetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Color Blend Image"}
+    public method UpdateInputsFromContainer { }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_colorblendimage::Initialize { } {
+
+    PrintDebug "bis_colorblendimage::Initialize" 
+
+    set options {
+	{ mode "Color Combination to Use" "ColorMode"  listofvalues RedGreen { RedGreen RedBlue GreenBlue Red Green Blue }   0 }
+	{ background  "Background Level used to fill voxels outside of mapped area" "Background Value"  real 0.0 { -100000 100000 }  -100 }
+    }
+    lappend options [ list  default1   "Default Scaling for Image 1" "Default Scale 1"  boolean   1    { 0 1  } 0  ]
+    lappend options [ list  minth1 "Image 1: Lower Window" "Image 1 Low"   real    0 { -100000000.0 100000000.0 }  1 ]
+    lappend options [ list  maxth1 "Image 1: Upper Window" "Image 1 High"  real    255 { -100000000.0 100000000.0 }  2 ]
+    lappend options [ list  default2   "Default Scaling for Image 2" "Default Scale 2"  boolean   1    { 0 1  } 10  ]
+    lappend options [ list  minth2 "Image 2: Lower Window" "Image 2 Low"   real    0 { -100000000.0 100000000.0 }  13 ]
+    lappend options [ list  maxth2 "Image 2: Upper Window" "Image 2 High"  real    255 { -100000000.0 100000000.0 }  14 ]
+
+
+	
+    set defaultsuffix { "_colorblend" }
+    
+    set scriptname bis_colorblendimage
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    set category "Image Processing Dual"
+    set description "Creates colorblend image"
+    set description2 "a useful check of the quality of the transformations"
+    set backwardcompatibility "Reimplemented from pxmat_blendimage.tcl."
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageTransformationAlgorithm
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_colorblendimage::Execute {  } {
+
+    PrintDebug "bis_colorblendimage::Execute"
+
+    set mode [ $OptionsArray(mode) GetValue ]
+
+
+    set lst [ $this ResliceImageIfNeeded ]
+    set reslimage [ lindex $lst 0 ]
+    set minval(1) [ $OptionsArray(minth1) GetValue ]
+    set minval(2) [ $OptionsArray(minth2) GetValue ]
+    set maxval(1) [ $OptionsArray(maxth1) GetValue ]
+    set maxval(2) [ $OptionsArray(maxth2) GetValue ]
+    set default(1) [ $OptionsArray(default1) GetValue ]
+    set default(2) [ $OptionsArray(default1) GetValue ]
+
+
+    set img(1)  $reslimage 
+    set img(2) [  [ $this GetInput ] GetImage ]
+
+    set appnd [ vtkpxAppendComponents [ pxvtable::vnewobj ]]
+
+
+    if { $mode == "RedGreen" } {
+	set index(1) 1
+	set index(2) 2
+	set index(3) 2
+	set null     3
+    } elseif { $mode == "RedBlue" } {
+	set index(1) 1
+	set index(2) 2
+	set index(3) 2
+	set null     2
+    } elseif { $mode == "Red" } {
+	set index(1) 1
+	set index(2) 1
+	set index(3) 1
+	set null     { 2 3 }
+    } elseif { $mode == "Green" } {
+	set index(1) 1
+	set index(2) 1
+	set index(3) 1
+	set null     { 1 3 }
+    } elseif { $mode == "Blue" } {
+	set index(1) 1
+	set index(2) 1
+	set index(3) 1
+	set null     { 1 2 }
+    }  else { 
+	set index(1) 1
+	set index(2) 1
+	set index(3) 2
+	set null     1
+    }
+	
+
+
+
+    for { set i 1 } { $i <=3 } { incr i } {
+
+	if { $default($index($i)) > 0 } {
+	    set r [ [ [ $img($index($i)) GetPointData ] GetScalars ] GetRange ]
+	    set rmin [ lindex $r 0 ]
+	    set rmax [ lindex $r 1 ]
+	    set $minval($index($i)) $rmin
+	    set $maxval($index($i)) $rmax
+	} else {
+	    set rmin $minval($index($i))
+	    set rmax $maxval($index($i))
+	}
+	
+	set sc [ vtkImageShiftScale New ]
+	$sc SetInput $img($index($i))
+	$sc SetShift $rmin
+	$sc ClampOverflowOn
+
+	if {  [ lsearch -exact $null $i  ] >=0 } {
+	    $sc SetScale 0.0
+	} else {
+	    if { $rmax > 0 }  {
+		$sc SetScale [ expr 255.0/$rmax ]
+	    } else {
+		$sc SetScale 1.0
+	    }
+	}
+	$sc SetOutputScalarTypeToUnsignedChar
+	$sc Update
+
+	$appnd AddInput [ $sc GetOutput ]
+    }
+    $appnd Update
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage [ $appnd GetOutput ]
+    $appnd Delete
+
+    # Output orientation etc. is same as input
+    set outimage [ $this GetOutput ] 
+    set pimage   [ $this GetSecondInput ] 
+
+    $outimage CopyImageHeader [ $pimage GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    $this DeleteResliceAlgorithmIfNeeded $lst 
+
+    return 1
+}
+
+itcl::body bis_colorblendimage::UpdateInputsFromContainer { } {
+
+    set ok [ bis_dualimagetransformationalgorithm::UpdateInputsFromContainer ]
+
+    set imglist(1)  [ $this GetInput ]  
+    set imglist(2)  [ $this GetSecondInput ]  
+
+    for { set i 1 } { $i <= 2 } { incr i } {
+	set img $imglist($i)
+	set r [  [$img GetImage ]  GetScalarRange ]
+	set rmin [ lindex $r 0 ]
+	set rmax [ expr [ lindex $r 1 ] ]
+	if { $rmax == $rmin } {
+	    set rmax [ expr $rmin +1 ]
+	}
+
+	$OptionsArray(minth$i) SetValueRange [ list $rmin [ expr 2*$rmax ] ]
+	$OptionsArray(maxth$i) SetValueRange [ list $rmin [ expr 2*$rmax ] ]
+	if { [ $OptionsArray(minth$i) GetValue ] == [ $OptionsArray(minth$i) GetDefaultValue ] } {
+	    $OptionsArray(minth$i) SetValue $rmin
+	}
+
+	if { [ $OptionsArray(maxth$i) GetValue ] == [ $OptionsArray(maxth$i) GetDefaultValue ] } {
+	    $OptionsArray(maxth$i) SetValue $rmax
+	}
+    }
+
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_colorblendimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+   
+
+    set alg [bis_colorblendimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_combineframes.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_combineframes.tcl
new file mode 100755
index 0000000..2fcce37
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_combineframes.tcl
@@ -0,0 +1,164 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_combineframes 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+itcl::class bis_combineframes {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Combine Frames" }
+    public method  UpdateOutputFilenames { } 
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_combineframes::Initialize { } {
+
+    PrintDebug "bis_combineframes::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ mode "Combining Mode either Mean,Sum,Min, Max or Magnitude" "mode" listofvalues Mean { Mean Sum Min Max Magn } 1 }
+    }
+
+    set defaultsuffix { "mean" }
+    
+    set scriptname bis_combineframes
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    set category "Image Processing-4D"
+
+    set description "Takes in a 4d image and creates a 3d mean, maximum, sum, minimum, or magnitude"
+    set description2 ""
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_combineframes::Execute {  } {
+
+    PrintDebug "bis_combineframes::Execute"
+
+
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+
+    set average  [ vtkbisTimeSeriesStat [ pxvtable::vnewobj ]  ]
+    if { $average == 0 } {
+	set errormessage "Cannot compute Time Series average .. bad library"
+	return 0
+    }
+
+    set image_in    [ $this GetInput ]
+    set outimage [ $OutputsArray(output_image) GetObject ]
+
+    set md [ $OptionsArray(mode) GetValue ]
+    
+    $average SetInput [ $image_in GetObject ]
+
+    if { $md == "Max" } {
+	$average SetMode 3
+    } elseif { $md == "Sum" } {
+	$average SetMode 1
+    }  elseif { $md == "Min" } {
+	$average SetMode 2
+    }  elseif { $md == "Magn" } {
+	$average SetMode 4
+    } else {
+	$average SetMode 0
+    }
+    $average Update
+    $outimage ShallowCopyImage [ $average GetOutput ]
+    $average Delete
+
+	
+
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment" 0
+
+    return 1
+}
+
+itcl::body bis_combineframes::UpdateOutputFilenames { } { 
+
+    set md [ $OptionsArray(mode) GetValue ]
+
+    if { $md == "Max" } {
+	set defaultsuffix { "_max" }
+    } elseif { $md == "Sum" } {
+	set defaultsuffix { "_sum" }
+    }  elseif { $md == "Min" } {
+	set defaultsuffix { "_min" }
+    }  elseif { $md == "Magn" } {
+	set defaultsuffix { "_magn" }
+    } else {
+	set defaultsuffix { "_mean" }
+    }
+
+    return [ ::bis_imagetoimagealgorithm::UpdateOutputFilenames  ]
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_combineframes.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_combineframes [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_combineimages.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_combineimages.tcl
new file mode 100755
index 0000000..5a00119
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_combineimages.tcl
@@ -0,0 +1,166 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_combineimages 1.0
+package require bis_imagelisttoimagealgorithm 1.0
+
+itcl::class bis_combineimages {
+
+    inherit bis_imagelisttoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Combine Set of Images" }
+    public method UpdateOutputFilenames { } 
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_combineimages::Initialize { } {
+
+    PrintDebug "bis_combineimages::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ mode "Method to combinie images" "mode" listofvalues Mean { Mean Sum Max Min Median } 1 }
+    }
+
+    set defaultsuffix { "mean" }
+    
+    set scriptname bis_combineimages
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    set category "Image Processing Multiple"
+    set description "Takes in a set of 3d images and creates a 3d mean, maximum, sum or minimum"
+    set description2 ""
+    set backwardcompatibility "Reimplemented from pxaverageimages.tcl, with extra features."
+
+    $this InitializeImageListToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_combineimages::Execute {  } {
+
+    set inplist [ $InputsArray($directinputs) GetAllObjects ]
+    set numfiles [ llength $inplist ]
+    
+    if { $numfiles < 2 } {
+	set errormessage "Nothing do less than 2 inputs specified"
+	return 0
+    }
+
+    set md [ $OptionsArray(mode) GetValue ]
+    if { $md == "Min" || $md == "Max" } {
+	set filt [ vtkpxMaximumImages New ]
+    } else {
+	set filt [ vtkpxAverageImages New ]
+    }
+
+    for { set i 0 } { $i < $numfiles } { incr i } {
+	$filt AddInput [ [ lindex $inplist $i ] GetImage ]
+    }
+
+    if { $md == "Min" || $md == "Max" } {
+	if { $md == "Min" } {
+	    $filt SetDoMinimum 1
+	} else {
+	    $filt SetDoMinimum 0
+	}
+    } else {
+	$filt SetMedian 0
+	$filt SetSumOnly 0
+	if { $md == "Median" } {
+	    $filt SetMedian 1
+	} elseif { $md == "Sum" } {
+	    $filt SetSumOnly 1
+	} 
+    }
+    $this SetFilterCallbacks $filt "Computing $md Image"
+    $filt Update
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $filt GetOutput ]
+    $filt Delete
+
+    $outimage CopyImageHeader [ [ lindex $inplist 0 ] GetImageHeader ]
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment" 0
+    return 1
+}
+
+# ----------------------------------------------------------------------
+
+itcl::body bis_combineimages::UpdateOutputFilenames { } { 
+
+    set md [ $OptionsArray(mode) GetValue ]
+
+    if { $md == "Max" } {
+	set defaultsuffix { "_max" }
+    } elseif { $md == "Sum" } {
+	set defaultsuffix { "_sum" }
+    }  elseif { $md == "Min" } {
+	set defaultsuffix { "_min" }
+    }  elseif { $md == "Median" } {
+	set defaultsuffix { "_median" }
+    } else {
+	set defaultsuffix { "_mean" }
+    }
+
+    return [ ::bis_imagelisttoimagealgorithm::UpdateOutputFilenames  ]
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_combineimages.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_combineimages [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_combinetransformations.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_combinetransformations.tcl
new file mode 100755
index 0000000..e6aab1c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_combinetransformations.tcl
@@ -0,0 +1,309 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagetransformationalgorithm 1.0
+package provide bis_combinetransformations 1.0
+
+#
+# combinetransformations
+#
+
+itcl::class bis_combinetransformations {
+
+    inherit bis_dualimagetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Combine Transformations" }
+    public method  UpdateOutputFilenames { } 
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_combinetransformations::Initialize { } {
+
+
+    set defaultsuffix "dispfield"
+
+    set inputs {
+	{ xform2   "Transformation 2"    pxitcltransform  "" 101 }
+	{ xform3   "Transformation 3"    pxitcltransform  "" 102 }
+    }
+
+    set outputs {
+	{ comboxform   "Combined Transformation"    pxitcltransform  "" 1 }
+    }
+
+    set options {
+	{ inverse  "Create Inverse Transformation" "Inverse" boolean   0  { 0 1 } 1 }
+    }
+    set scriptname bis_combinetransformations
+
+
+    #
+    #document
+    #
+    set defaultsuffix { "combined" }
+    set category "Registration"
+    set description  "computes a combined (optionally inverse) transformation  for a set  transformation given an image to define the space."
+    set description2 ""
+    set backwardcompatibility ""
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageTransformationAlgorithm
+
+    $this RenameInput 1 "Unused Second Image" 200
+    $this RenameInput 2 "Transformation 1" 101
+    $this RenameOutput 0 "Combined Disp Field" 200
+
+}
+# -----------------------------------------------------------------------------------------
+itcl::body bis_combinetransformations::UpdateOutputFilenames { } {
+
+    set f(0) [ $InputsArray(transformation) GetFileName ]
+    set f(1) [ $InputsArray(xform2) GetFileName ]
+    set f(2) [ $InputsArray(xform3) GetFileName ]
+
+    for { set i 0 } { $i <= 2 } { incr i } {
+	set l($i) [ ::bis_common::SplitFileNameGZ $f($i) ]
+	set f($i) [ file tail [ lindex $l($i) 0 ] ]
+	set ext($i) [ lindex $l($i) 1 ]
+    }
+
+    set fname [ file join [ file dirname $f(0) ] $f(0) ]
+    for { set i 1 } { $i<=2 } { incr i } {
+	if { $f($i) != "" } {
+	    set fname "${fname}_$f($i)"
+	}
+    }
+    
+    set md [ $OptionsArray(inverse) GetValue ]
+    if { $md == 1 } {
+	set defaultsuffix "inverse"
+    } else  {
+	set defaultsuffix "comb"
+    }
+
+    set dest [ $OutputsArray(comboxform) GetObject ] 
+
+    unset ext
+
+    if { [  [ $dest GetTransformation ] IsA "vtkHomogeneousTransform" ] ==1 } {
+	set ext ".matr"
+    } else {
+	set ext ".grd.gz"
+    }
+    
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+
+    $OutputsArray(comboxform) SetFileName "${fname}_${defaultsuffix}${ext}" $force
+    $OutputsArray(output_image) SetFileName "" $force
+
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_combinetransformations::Execute {  } {
+
+    PrintDebug "bis_combinetransformations::Execute"
+    set inversemode [ $OptionsArray(inverse) GetValue ]
+    set numgoodxforms 1
+    set allxformsarelinear 1
+    set ref_image    [ $InputsArray(input_image) GetObject ] 
+
+    set tlist(0)  [ $this GetInputObject transformation ] 
+    set tlist(1)  [ GetInputObject xform2 ] 
+    set tlist(2)  [ GetInputObject xform3 ]
+
+    set xforms ""
+
+    for { set i 0 } { $i <= 2 } { incr i } {
+	if { [ $tlist($i)  IsIdentity ] == 0 } {
+	    lappend xforms $tlist($i) 
+	    if { [ [ $tlist($i) GetTransformation ] IsA "vtkHomogeneousTransform" ] == 0  } {
+		set allxformsarelinear 0
+	    }
+	}
+    }
+    set numgoodxforms [ llength $xforms ]
+    
+    set dest [ $OutputsArray(comboxform) GetObject ] 
+    set fname [ $dest cget -filename ]
+    $dest Clear
+    $dest configure -filename $fname
+
+    puts stderr "xforms=$xforms, allxformsarelinear=$allxformsarelinear"
+
+    # No Tranformations
+    if { $numgoodxforms == 0 } {
+	puts stdout "All Transformations are identity. Operation is pointless"
+	return 1
+    }
+    
+    if { $numgoodxforms == 1 } {
+	puts stdout "One Transformation copying"
+	set dest [ $OutputsArray(comboxform) GetObject ] 
+	set fname [ $dest cget -filename ]
+	$dest Copy  [ $this GetInputObject transformation ] 
+	
+	if { $inversemode == 1 && $allxformsarelinear == 1} {
+	    puts stdout " and inverting"
+	    $dest Invert
+	}
+
+	if { $inversemode == 0 || ( $inversemode ==1 && $allxformsarelinear ==1 ) } {
+	    if { $fname != "" } {
+		if { [ [ $dest GetTransformation ]  IsA "vtkHomogeneousTransform" ] ==1 } {
+		    set fname "[ file rootname $fname ].matr"
+		}
+		$dest configure -filename $fname
+	    } else {
+		$dest configure -filename ""
+	    }
+	    return 1
+	} else {
+	    puts stdout "Need to invert a single nonlinear transformation"
+	}
+    }
+   
+    if { $allxformsarelinear == 1 } {
+	set trans [ vtkTransform [ pxvtable::vnewobj ]]
+	$trans Identity
+	$trans PostMultiply
+	for { set i 0 } { $i < $numgoodxforms } { incr i } {
+	    puts stdout "Concatenating linear [ [ lindex $xforms $i ] cget -filename ]"
+	    $trans Concatenate [ [ lindex $xforms $i ] GetObject ]
+	}
+	if { $inversemode == 1 } {
+	    $trans Inverse
+	}
+	set dest [ $OutputsArray(comboxform) GetObject ] 
+	$dest CopyTransformation  $trans
+	$trans Delete
+	return 1
+    }
+	
+    set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+    $trans Identity
+    $trans PostMultiply
+    for { set i 0 } { $i < $numgoodxforms } { incr i } {
+	puts stdout "Concatenating linear/non-linear [ [ lindex $xforms $i ] cget -filename ]"
+	$trans Concatenate [ [ lindex $xforms $i ] GetObject ]
+    }
+
+    set dim [[ $ref_image GetObject ] GetDimensions ]
+    set spa [[ $ref_image GetObject ] GetSpacing ]
+    set ori [[ $ref_image GetObject ] GetOrigin ]
+
+    puts stderr "Spacing = $spa, Origin=$ori, dim=$dim"
+
+
+    set tgrid [ vtkTransformToGrid [ pxvtable::vnewobj ]]
+    $tgrid SetGridExtent 0 [ expr [ lindex $dim  0 ] -1 ] 0 [ expr [ lindex $dim  1 ] -1 ] 0 [ expr [ lindex $dim  2 ] -1 ]
+    $tgrid SetGridOrigin  [ lindex $ori 0 ] [ lindex $ori 1 ] [ lindex $ori 2 ] 
+    $tgrid SetGridSpacing [ lindex $spa 0 ] [ lindex $spa 1 ] [ lindex $spa 2 ] 
+    $tgrid SetInput $trans
+    $tgrid Update
+
+    set tr2 [ vtkpxGridTransform [ pxvtable::vnewobj ]]
+    $tr2 SetInterpolationModeToLinear
+
+    if { $inversemode == 1 } {
+	set trg [ vtkGridTransform [ pxvtable::vnewobj ]]
+	$trg SetDisplacementGrid [ $tgrid GetOutput ]
+	$trg SetInterpolationModeToLinear
+	$trg Inverse
+	
+	set tgrid2 [ vtkTransformToGrid [ pxvtable::vnewobj ]]
+	$tgrid2 SetGridExtent  0 [ expr [ lindex $dim  0 ] -1 ] 0 [ expr [ lindex $dim  1 ] -1 ] 0 [ expr [ lindex $dim  2 ] -1 ]
+	$tgrid2 SetGridOrigin  [ lindex $ori 0 ] [ lindex $ori 1 ] [ lindex $ori 2 ] 
+	$tgrid2 SetGridSpacing [ lindex $spa 0 ] [ lindex $spa 1 ] [ lindex $spa 2 ] 
+	$tgrid2 SetInput $trg
+	$tgrid2 Update
+	
+	$tr2 SetDisplacementGrid [ $tgrid2 GetOutput ]
+	$tgrid2 Delete
+	$trg Delete
+    } else {
+	$tr2 SetDisplacementGrid [ $tgrid GetOutput ]
+    }
+
+    set image_out [ $tgrid GetOutput ]
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage [ $tr2 GetDisplacementGrid ]
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $ref_image GetImageHeader ]
+    [ $outimage GetImageHeader ] AddComment [ $this GetCommandLine full ] 
+
+    set dest [ $OutputsArray(comboxform) GetObject ] 
+    $dest CopyTransformation  $tr2
+    $dest configure -filename $fname
+
+    
+    $tr2 Delete
+    $tgrid Delete
+    $trans Delete
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_displacementfield.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+#    DebugOn
+
+    set alg [bis_combinetransformations [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_common.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_common.tcl
new file mode 100644
index 0000000..bc0bd44
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_common.tcl
@@ -0,0 +1,84 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_common 1.0
+
+# Author Hirohito Okuda <hirohito.okuda at yale.edu>
+
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main ]
+
+namespace eval ::bis_common {
+    variable bis_testlog testlog
+
+    proc   GetIndexedFilename { filename idx suffix} {
+	if { $idx < 10 } {
+	    set tmp 00$idx
+	} elseif { $idx < 100 } {
+	    set tmp 0$idx
+	} else {
+	    set tmp $idx
+	}
+	return  ${filename}${tmp}${suffix}
+    }
+
+    proc SplitFileNameGZ { fname } {
+
+	set extension [ file extension $fname ]
+	set inname    [ file rootname  $fname ]
+	
+	if { $extension == ".gz" } { 
+	    set extension [ file extension $inname ].gz
+	    set inname    [ file rootname  $inname ]
+	}
+	
+	return [ list $inname $extension ]
+    }
+
+    proc CleanString { ln } {
+	regsub -all "\"" $ln "\\\"" val
+	regsub -all "\n" $val " " val
+	regsub -all "\t" $val " " val
+	return "\"$val\""
+    }
+
+    proc GetCategories { } {
+	return [ list "Image Processing" "Image Processing-4D" "Image Processing Dual"  "Image Processing Multiple"  "Surface Processing"  "Registration" "Segmentation" "Functional Imaging"  "DiffSPECT"  "Diffusion Tensor"   "Vascular Imaging" "Landmarks Processing"  "Utility" ]
+    }
+
+    proc GetSlicerXMLLogo { } {
+	set bis_logo "LOGO\n"
+	append bis_logo "200\n"
+	append bis_logo "41\n"
+	append bis_logo "4\n"
+	append bis_logo "27616\n"
+	append bis_logo "eNrkvWWYXUeSNjhN0+75GsYN7vZ43Mzc5u42yLZkkkFgkC1ZlkWWxUwFl4q56vKtqlvMt5iZmUslqUolKhJLlqF5Zt99I88p2TO78/3YffbX/sgnz82TJ09mnoiMeCMj8v4n/gP/+d/Sf/wfWvr7f/wDf/nb35n+hr/89W/4M9Nf//53lctvufenv2j5nz9xXyv7+P7CM3/+b89InT/9+S//4/1Ptvnn/9bm//07tTb//Je//s/vlDJ1/VftPutK+Ufsx/+bcfz5f3P//+k4/rfv/P/oe/z/bRx//fs/8I///L/ywP+U/v4ff8eNmx9i9NRV9I9fRnXPZRS3XERRK/PWiyjhta/1EopaLt0qK2ZexLJiVbaQS7n2u7SN122XVX15Tq6lTXmutO0Kf19CIa9L2q4yv8J6V3nvCgpbeN3CshZ5z1V1XaTKtftSVshUyt8+9QzrdfCZdva346K6X6zuX0 [...]
+	return $bis_logo
+    }
+}
+			     
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computecorrelations.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computecorrelations.tcl
new file mode 100755
index 0000000..a5c7ae1
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computecorrelations.tcl
@@ -0,0 +1,306 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_computecorrelations 1.0
+package require bis_imagetoimagealgorithm 
+package require bis_seedcorrelation
+
+itcl::class bis_computecorrelations {
+
+    inherit bis_imagetoimagealgorithm
+
+    constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Compute Correlations" }
+
+
+    protected method TextFileToImage { textfile } 
+    public method UpdateOutputFilenames { } 
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computecorrelations::Initialize { } {
+
+    PrintDebug "bis_computecorrelations::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ mname  "specify the measures file used to compute the correlations" "Measures File"   { filename default } "" { text { .txt } }   10 }
+	{ split  "save individual measures to separate files (if guimode then off by default)"  "Save Individuals" boolean 0 { 0 1 } 11 }
+	{ raw  "Output is raw-correlations instead of z-scores"  "Raw Correlations" boolean 0 { 0 1 } 11 }
+    }
+	
+    set defaultsuffix { "" }
+    set category "Functional Imaging"    
+    set scriptname bis_computecorrelations
+    set completionstatus "Done"
+    
+    #
+    #document
+    #
+    
+    set description "Compute Correlations between the 4D image as input 1 and the measures in filename. 4D Image must have the same number of frames as the subjects in the filename and the frames MUST be in the same order as the subjects as listed below, i.e. The first subject must be in frame 1, the second in frame 2 etc."
+    set description2 "Measures File Example\n------------------------"
+    append description2 "\n\\\#Individual Subject Measures"
+    append description2 "\n\\\#Number of Subjects\n4"
+    append description2 "\n\\\#Number of Measures\n2"
+    append description2 "\n\\\#Data (either , or tab-delimited)"
+    append description2 "\nSubject IQ Weight"
+    append description2 "\n1314	100 100"
+    append description2 "\n1361	110 200"
+    append description2 "\n1518	120 200"
+    append description2 "\n2205	130 121"
+    append description2 "\n------------------------\n"
+
+    set backwardcompatibility ""
+    set authors "isabella.murphy at yale.edu, xenophon.papademetris at yale.edu."
+    
+    $this InitializeImageToImageAlgorithm
+    $this RenameInput 0 "4D Input Image"
+}
+
+# -----------------------------------------------------------------------------------------
+# FileaNames
+# ----------------------------------------------------------------------------------------
+itcl::body bis_computecorrelations::UpdateOutputFilenames { } {
+
+    set fname   [ $OptionsArray(mname) GetValue ]
+    set l [ ::bis_common::SplitFileNameGZ $fname ]
+    set defaultsuffix [ file tail [ lindex $l 0 ] ]
+    set ok [ ::bis_imagetoimagealgorithm::UpdateOutputFilenames  ]
+    return $ok
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_computecorrelations::TextFileToImage { textfile } {
+
+    set fileid [open $textfile r]
+	
+    gets $fileid line
+    set line [ string trim $line ]
+    
+    if { [ string compare $line "#Individual Subject Measures" ] != 0 } {
+	set errormessage  "Bad Measures File File, does not have proper header\n"
+	close $fileid
+	return 0
+    }
+    
+    set numsubjects 1
+    set nummeasures 1
+    gets $fileid line;     gets $fileid numsubjects
+    gets $fileid line;     gets $fileid nummeasures
+    
+    puts stdout "Reading textfile = $textfile, numsubjects=$numsubjects, nummeasures=$nummeasures"
+
+    gets $fileid line
+
+    set img [ vtkImageData New ]
+    $img SetDimensions $nummeasures 1 1
+    $img SetNumberOfScalarComponents $numsubjects
+    $img SetScalarTypeToFloat
+    $img AllocateScalars
+    
+    set numcols [ expr $nummeasures +1 ]
+    gets $fileid line
+
+    set subjectlist ""
+    set measurelist ""
+
+    set ln [ string trim $line ]
+    regsub -all " +" $ln "\t" ln
+    regsub -all "\t" $ln "|" ln
+    regsub -all ","  $ln "|" ln
+    set tmp  [ split $ln | ]	
+    if { [ llength $tmp ] != $numcols } {
+	set errormessage "Not Engough Measure names specified (numcols=$numcols) ($ln,$tmp)"
+	close $fileid
+	return 0
+    }
+    for { set i 1 } { $i < $numcols } { incr i } {
+	lappend measurelist [ lindex $tmp $i ]
+    }
+
+
+    for { set i 0 } { $i < $numsubjects } { incr i } {
+	gets $fileid line
+	set ln [ string trim $line ]
+	regsub -all " +" $ln "\t" ln
+	regsub -all "\t" $ln "|" ln
+	regsub -all ","  $ln "|" ln
+	set tmp  [ split $ln | ]	
+	#	puts stdout "ln=$ln, tmp=$tmp"
+	if { [ llength $tmp ] != $numcols } {
+	    set errormessage "Bad Line for subject [ expr $i +1 ], number of columns = [ llength $tmp ] != $numcols "
+	    close $fileid
+	    return 0
+	}
+	for { set j 1 } { $j < $numcols } { incr j } {
+	    $img SetScalarComponentFromDouble [ expr $j -1 ] 0 0 $i [ expr double([ lindex $tmp $j ]) ]
+	}
+	lappend subjectlist [ lindex $tmp 0 ]
+    }
+    close $fileid
+
+    puts stdout "Verifying ...."
+
+    puts -nonewline stdout " \t :"
+    for { set j 0 } { $j < $nummeasures } { incr j } {
+	puts -nonewline stdout " [ lindex $measurelist $j ]\t"
+    }
+    puts stdout ""
+
+    for { set i 0 } { $i < $numsubjects } { incr i } {
+	puts -nonewline stdout "Subject [ lindex $subjectlist $i ] \t"
+	for { set j 0 } { $j < $nummeasures } { incr j } {
+	    puts -nonewline stdout "[ $img GetScalarComponentAsDouble $j 0 0 $i ]\t"
+	}
+	puts stdout ""
+    }
+
+
+    set ref [ pxitclimage \#auto ]
+    $ref ShallowCopyImage $img
+    $ref configure -filename "(from $textfile)"
+    $img Delete
+    return [ list [ $ref GetThisPointer ] $measurelist ]
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+itcl::body bis_computecorrelations::Execute {  } {
+
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+
+    set raw [ $OptionsArray(raw) GetValue ]
+
+    set mname [ $OptionsArray(mname) GetValue ]
+    #    puts stderr "mname=$mname"
+    set saveall [ $OptionsArray(split) GetValue ]
+    set rlist [ TextFileToImage $mname ]
+    if { $rlist == 0 } {
+	return 0
+    }
+
+    set ref [ $this GetInput ]	
+    set roimean     [ lindex $rlist 0 ]
+    set measurelist [ lindex $rlist 1 ]
+
+
+    set corr [ bis_seedcorrelation \#auto ]
+    $corr InitializeFromContainer 0
+    $corr SetInput $ref
+    $corr SetSecondInput $roimean
+    $corr SetOptionValue raw $raw
+    $corr SetOptionValue ztransform 0
+    $corr SetOptionValue usemask 0
+    $corr Execute
+
+
+    if { $saveall > 0 } {
+	$this UpdateOutputFilenames
+	set outimage [ $corr GetOutput ]
+	set tname [ $OutputsArray(output_image) GetFileName]
+	set l [ ::bis_common::SplitFileNameGZ $tname ]
+	set outname [ lindex $l 0 ]
+	set tmp [ pxitclimage \#auto ]
+
+	for { set i 0 } { $i < [ [ $outimage GetImage ] GetNumberOfScalarComponents ] } { incr i } {
+	    
+	    set extr [ vtkImageExtractComponents New ]
+	    $extr SetInput [ $outimage GetImage ]
+	    $extr SetComponents $i
+	    $extr Update
+	    
+	    $tmp ShallowCopyImage [ $extr GetOutput ]
+	    $tmp CopyImageHeader  [ $outimage GetImageHeader ]
+	    set name "${outname}_[ lindex $measurelist $i ].nii.gz"
+	    set ok [ $tmp Save $name ]
+	    if { $ok > 0 } {
+		puts stdout "\t\t Correlation with [ lindex $measurelist $i ] saved in $name"
+	    }
+	    $extr Delete
+	}
+	itcl::delete object $tmp
+    }
+
+    set output [ $this GetOutput ] 
+    $output ShallowCopy [ $corr GetOutput ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $output GetImageHeader ] AddComment "$comment $Log" 0
+
+    set framenames "---------------------------------------------\n"
+    append framenames "Frame \t Name\n"
+    append framenames "---------------------------------------------\n"
+    for { set i 0 } { $i < [ llength $measurelist ] } { incr i } {
+	append framenames "[ expr $i+1] \t [ lindex $measurelist $i ]\n"
+    }
+    append framenames "---------------------------------------------\n"
+    [ $output GetImageHeader ] AddComment "[ $this GetGUIName ], framenames\n$framenames" 0
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_mediantemporalsmoothimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_computecorrelations [ pxvtable::vnewobj ] ]
+    $alg MainFunction 
+}
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computedisplacementfield.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computedisplacementfield.tcl
new file mode 100755
index 0000000..3f84eeb
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computedisplacementfield.tcl
@@ -0,0 +1,151 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagetransformationalgorithm 1.0
+package provide bis_computedisplacementfield 1.0
+
+#
+# computedisplacementfield
+#
+
+itcl::class bis_computedisplacementfield {
+
+    inherit bis_dualimagetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Compute Displacement Field" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computedisplacementfield::Initialize { } {
+
+
+    set defaultsuffix "dispfield"
+
+    set inputs {
+	{ xform2   "Transformation 2"    pxitcltransform  "" 100 }
+	{ xform3   "Transformation 3"    pxitcltransform  "" 101 }
+    }
+
+    set options {
+	{ guicmt     "Description of the filter"  "Note"  comment "Compute a displacement field given transformations" "Compute disp field"  400 }
+    }
+    set scriptname bis_computedisplacementfield
+
+    #
+    #document
+    #
+    set category "Registration"
+    set description  "computes the displacement field for a transformation given an image to define the space."
+    set description2 ""
+    set backwardcompatibility "Reimplemented from pxmat_displacementfield.tcl"
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageTransformationAlgorithm
+
+    $this RenameInput 1 "Unused Second Image" 200
+    $this RenameInput 2 "Transformation 1" 10
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computedisplacementfield::Execute {  } {
+
+
+    PrintDebug "bis_computedisplacementfield::Execute"
+
+    set ref_image    [ $InputsArray(input_image) GetObject ] 
+
+    set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+    $trans Identity
+    $trans PostMultiply
+    $trans Concatenate [ [ $this GetInputObject transformation ] GetTransformation ]
+    $trans Concatenate [ [ $this GetInputObject xform2 ] GetTransformation ]
+    $trans Concatenate [ [ $this GetInputObject xform3 ] GetTransformation ]
+
+
+
+    set dim [[ $ref_image GetObject ] GetDimensions ]
+    set spa [[ $ref_image GetObject ] GetSpacing ]
+
+    set tgrid [ vtkTransformToGrid [ pxvtable::vnewobj ]]
+    $tgrid SetGridExtent 0 [ expr [ lindex $dim  0 ] -1 ] 0 [ expr [ lindex $dim  1 ] -1 ] 0 [ expr [ lindex $dim  2 ] -1 ]
+    $tgrid SetGridOrigin  0 0 0
+    $tgrid SetGridSpacing [ lindex $spa 0 ] [ lindex $spa 1 ] [ lindex $spa 2 ] 
+    $tgrid SetInput $trans
+    $tgrid Update
+
+    set image_out [ $tgrid GetOutput ]
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out 
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $ref_image GetImageHeader ]
+
+    [ $outimage GetImageHeader ] AddComment [ $this GetCommandLine full ] 
+
+    $tgrid Delete
+    $trans Delete
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_displacementfield.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+#    DebugOn
+
+    set alg [bis_computedisplacementfield [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computeglm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computeglm.tcl
new file mode 100755
index 0000000..f9af010
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computeglm.tcl
@@ -0,0 +1,180 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_computeglm 1.0
+package require bis_dualimagealgorithm 1.0
+
+
+itcl::class bis_computeglm {
+
+    inherit bis_imagetoimagealgorithm
+
+    constructor { } {	 $this Initialize  }
+    
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Compute GLM Regression" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computeglm::Initialize { } {
+
+    PrintDebug "bis_computeglm::Initialize" 
+    
+	#commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ matrix "GLM matrix file name, either in Matlab .mat format or BioImage Suite .matr format" "GLM Matrix File:" { filename default } "" { MAT-File  { .mat,.matr } } 1 }
+	{ matrixname "Name of Matrix in matlab file e.g. Q_set ..." "Matrix Name" string "" { } 2 }
+	{ residual "Generate residual image" "Generate Residual Image" boolean 0 { 0 1 } 3 }
+    }
+
+    set outputs { 
+	{ resimage "Residual Image" pxitclimage  ""  120 }   
+    }
+
+
+
+    set defaultsuffix { "_glm" }
+    set scriptname bis_computeglm
+    set completionstatus "Needs testing!"
+
+    #
+    #document
+    #
+    
+    set description "Compute GLM Fit using Matrix to define regressors. Optionally save the residual image."
+    set description2 ""
+    set backwardcompatibility ""
+    set authors "xenophon.papademetris at yale.edu"
+    set category "Functional Imaging"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computeglm::Execute {  } {
+
+    PrintDebug "bis_computeglm::Execute"
+
+
+    set matrixfname   [ $OptionsArray(matrix) GetValue ]
+    set mname         [ $OptionsArray(matrixname) GetValue ]
+    set image_in      [ $this GetInput ]
+    set res         [ $OptionsArray(residual) GetValue ]
+	
+    set matrix [ vtkpxMatrix New ]
+    set ok [ $matrix Load $matrixfname ]
+    if { $ok == 0 } {
+	set ok [  $matrix ImportFromMatlab $matrixfname $mname ]
+	if { $ok == 0 } {
+	    $matrix Delete
+	    set errormessage "Failed to read matrix from $matrixfname (name=$mname)"
+	    return 0
+	}
+    }
+	
+    set numrows [ lindex [ $matrix GetSize ] 0 ]
+    puts stdout "Matrix = [ $matrix GetSize ], comp = [ [ $image_in GetImage ] GetNumberOfScalarComponents ] "
+    if { $numrows != [ [ $image_in GetImage ] GetNumberOfScalarComponents ] } {
+	set errormessage "Matrix size (rows) is not equal to number of frames in input image"
+	$matrix Delete
+	return 0
+    }
+
+    set glm [ vtkbisComputeGLM  [ pxvtable::vnewobj ]]
+    set outimg [ $glm ComputeSimpleGLM [ $image_in GetImage ]  $matrix ]
+    $glm Delete
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage $outimg
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    if { $res > 0 } {
+	set glm [ vtkbisComputeGLM  [ pxvtable::vnewobj ]]
+	set outimg2 [ $glm MatrixImageMultiply $outimg  $matrix ]
+	$glm Delete
+
+	set cast [ vtkImageCast New ]
+	$cast SetInput [ $image_in GetImage ]
+	$cast SetOutputScalarType [ $outimg2 GetScalarType ]
+	$cast Update
+
+	set math [ vtkImageMathematics New ]
+	$math SetInput1 [ $cast GetOutput ]
+	$math SetInput2 $outimg2
+	$math SetOperationToSubtract
+	$math Update
+
+	set second [ $this GetOutputObject resimage ]
+	$second CopyImageHeader [ $image_in GetImageHeader ]
+	$second ShallowCopyImage [ $math GetOutput ]
+	$math Delete
+	$cast Delete
+	$outimg2 Delete
+    }
+
+    $matrix Delete
+    $outimg Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_computeglm.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+	# this is essentially the main function
+
+	set alg [bis_computeglm [pxvtable::vnewobj]]
+	$alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computejointhistogram.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computejointhistogram.tcl
new file mode 100755
index 0000000..1093c8d
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computejointhistogram.tcl
@@ -0,0 +1,198 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_computejointhistogram 1.0
+package require bis_dualimagealgorithm 1.0
+
+itcl::class bis_computejointhistogram {
+
+    inherit bis_dualimagealgorithm
+    
+    constructor { } {	 $this Initialize  }
+    
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Compute Joint Histogram" }
+    #override parent function
+    
+    public method CheckInputObjects { }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computejointhistogram::Initialize { } {
+
+    PrintDebug "bis_computejointhistogram::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ numbins     "Number Of Bins"	"Number Of Bins"  int 64 { 2 256 } 0 }
+	{ usegpu   "Use GPU Implementation (if available)"  "Use GPU"  boolean   0  { 0 1  }  1  }
+	{ weighted   "Compute Weighted  Histogram"  "Weighted"  boolean   0  { 0 1  }  1  }
+	{ optimized   "Use Optimized GPU Implementation (if available)"  "Optimized"  boolean   0  { 0 1  }  2  }
+    }
+
+    set inputs { 
+    	{ weight_image1 "Weight Image 1" pxitclimage "" 102}     
+    	{ weight_image2 "Weight Image 2" pxitclimage "" 103}     
+    }
+
+
+    set defaultsuffix { "_computejointhistogram" }
+    set scriptname bis_computejointhistogram
+    set completionstatus "Done"
+    
+    #
+    #document
+    #
+    
+    set description "joint histogram."
+    set description2 "computes joint histogram from two images"
+
+    set backwardcompatibility ""
+    set authors "xenophon.papademetris at yale.edu"
+
+    $this InitializeDualImageAlgorithm
+    
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computejointhistogram::Execute {  } {
+    PrintDebug "bis_computejointhistogram::Execute"
+    
+
+    
+    set image1 [ $this GetInput ]
+    set image2 [ $this GetSecondInput ]
+    
+    set img1  [ $image1 GetImage ]
+    set img2  [ $image2 GetImage ] 
+
+    set wgt1 [ [ $this GetInputObject weight_image1 ] GetObject ]
+    set wgt2 [ [ $this GetInputObject weight_image2 ] GetObject ]
+
+    set usegpu [ $OptionsArray(usegpu) GetValue ]
+    set numbins [ $OptionsArray(numbins) GetValue ]
+    set optimized [ $OptionsArray(optimized) GetValue ]
+    set weighted [ $OptionsArray(weighted) GetValue ]
+
+    set histo 0
+    if { $usegpu > 0 } {
+	catch { set histo  [ vtkbisCUDAJointHistogram New ] }
+	if { $histo == 0 } { set usegpu 0 }
+    }
+
+    if { $usegpu == 0 } {
+	catch { set histo  [ vtkpxJointHistogram New  ] }
+	if { $histo ==0 } {
+	    return 0
+	}
+    }
+
+    if { [ $histo GetClassName ] == "vtkbisCUDAJointHistogram" } {
+	puts stdout "+++++++++++++ Using GPU Accelerated Version "
+    }
+
+    if { $weighted > 0 } {
+	puts stdout "Computing Dual Weighted!!!!"
+	$histo CreateDualWeightedHistogram $img1 $numbins $img2 $numbins $wgt1 $wgt2
+    } elseif { $usegpu == 0 } {
+	$histo CreateHistogram $img1 $numbins $img2 $numbins
+    } else {
+	$histo CreateHistogram $img1 $numbins $img2 $numbins $optimized
+    }
+
+    set ex  [ $histo EntropyX ]
+    set ey  [ $histo EntropyY ]
+    set je  [ $histo JointEntropy ]
+    set nmi [ $histo NormalizedMutualInformation ]
+    puts stdout "Normalized Mutual Information = $nmi (ex=$ex, ey=$ey je=$je)"
+
+
+    set img [ $histo GetHistogramAsImage ]
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage $img
+    $img Delete
+    $histo Delete
+    
+    set comment [ format " [ $this GetCommandLine full ], nmi=$nmi" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+               
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------------------
+itcl::body bis_computejointhistogram::CheckInputObjects { } {
+
+    set image1 [ $this GetInput ]
+    set image2 [ $this GetSecondInput ]
+    
+    set img1  [ $image1 GetImage ]
+    set img2  [ $image2 GetImage ] 
+    if { [ $img1 GetNumberOfPoints ] != [ $img2 GetNumberOfPoints ] } {
+	set errormessage "Unequal Image Sizes\n Cannot Perform Compare $mode t-test!"
+	return 0
+    }
+    
+    
+    return 1
+    
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_computejointhistogram.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+	# this is essentially the main function
+
+	set alg [bis_computejointhistogram [pxvtable::vnewobj]]
+	$alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computenormals.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computenormals.tcl
new file mode 100755
index 0000000..5ca3449
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computenormals.tcl
@@ -0,0 +1,142 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_surfacetosurfacealgorithm 1.0
+
+package provide bis_computenormals 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_computenormals {
+
+    inherit bis_surfacetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Compute Normals" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computenormals::Initialize { } {
+
+    PrintDebug "bis_computenormals::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ featureangle "Feature angle between 0 to 180 degrees" "Feature angle"  { real triplescale 100 }    90.0 { 0.0 180.0 }  0 }
+	{ edgesplit      "Edge Splitting" "Edge Splitting" { boolean}  0 { 0 1 }   1}
+	{ flipnormals "Flip normals" "Flip normals" { boolean}  0  {0 1}   2}
+    }
+
+    set defaultsuffix { "_normals" }
+    
+    set scriptname bis_computenormals
+
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "computes normals of a surface"
+    set description2 ""
+    set backwardcompaibitlity "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeSurfacetoSurfaceAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computenormals::Execute {  } {
+
+    PrintDebug "bis_computenormals::Execute"
+
+    # Get Inputs
+    set surface    [ $this GetInput  ]
+    # GetOptions
+    
+	set featureangle 	[ $OptionsArray(featureangle) GetValue ]
+	set edgesplit    	[ $OptionsArray(edgesplit)      GetValue ]
+	set flipnormals     [ $OptionsArray(flipnormals)    GetValue ]
+	
+    # Run Algorithm
+    set filter [ vtkPolyDataNormals [ pxvtable::vnewobj ] ]
+    $filter SetInput [ $surface GetObject ]
+    $filter SetFeatureAngle $featureangle
+    if { $edgesplit == "1"} {
+    	$filter SplittingOn
+    } else {
+    	$filter SplittingOff
+    }
+    
+    if { $flipnormals == "1"} {
+		$filter FlipNormalsOn
+	} else {
+		$filter FlipNormalsOff
+    }
+
+	$filter Update
+    
+    # Store Results in output
+    set surface_out [$filter GetOutput ]
+    [ $OutputsArray(output_surface) GetObject ] DeepCopySurface $surface_out 
+
+    # Clean up
+    $filter Delete
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_computenormals.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_computenormals [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computeoverlap.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computeoverlap.tcl
new file mode 100755
index 0000000..c93f35b
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computeoverlap.tcl
@@ -0,0 +1,533 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagetransformationalgorithm 1.0
+package provide bis_computeoverlap 1.0
+
+#
+# compute overlap
+#
+
+itcl::class bis_computeoverlap {
+
+    inherit bis_dualimagetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Compute Overlap" }
+    public method UpdateContainerWithOutput { } { }
+
+    #
+    #protected
+    #
+    protected method ComputeOverlap      { img1 img2 comment sigma xform } 
+    protected method ComputeMultiOverlap { img1 img2 comment sigma xform } 
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computeoverlap::Initialize { } {
+
+    PrintDebug "bis_computeoverlap::Initialize" 
+    set options {
+	{ sigma     "gaussian standard deviation for smoothing binary image" "sigma"  real    1.0 { 0.0 10.0 }  0 }
+	{ multioverlap "Treat Intensity levels as separate obejcts"  "Multi Overlap Mode"  boolean   0  { 0 1  }  1  } 
+    	{ filename   "specify the filname for the output text file" "Text File Name" { filename writefile } "" { text { .txt } 50 } -30 }
+	{ saveasimage "If on the output is an image instead of a text file"  "SaveImage"  boolean   0  { 0 1  }  -40  } 
+    }
+
+    set defaultsuffix { "_overlap" }
+    
+    set scriptname bis_computeoverlap
+    set completionstatus "Done -- some issues with 4D images"
+
+    #
+    #document
+    #
+
+    set category    "Registration"
+    set description  "computes overlap metrics of the pre-segmented structures after registration."
+    set description2 "Computed metrics are overlap1 = 100*(intersection(V1,V2))/(Union(V1,V2)),overlap2 = 100* V2/avarage(V1,V2), where V1 is the pre-segmented structure in the reference image and V2 is the pre-segmented structure in the target image after transformation. If the transformation is not specified, metrics are computed without transformation. "
+    set backwardcompatibility "Reimplemented from pxmat_computeoverlap.tcl"
+    set authors "alark.joshi at yale.edu, hirohito.okuda at yale.edu, xenophon.papademetris.yale.edu"
+
+    $this InitializeDualImageTransformationAlgorithm
+
+    $this RenameInput 0 "Reference Objectmap" 1  
+    $this RenameInput 1 "Target Objectmap" 2
+    $this RenameInput 2 "Tranformation" 101
+
+
+}
+
+# -----------------------------------------------------------------------------------------
+# duplicated from pxmat_computeoverlap
+# -----------------------------------------------------------------------------------------
+itcl::body bis_computeoverlap::ComputeOverlap { img1 img2 comment sigma xform } {
+
+    #    puts stdout "Comment=$comment, $sigma, [ $xform GetClassName ]"
+
+    set image(1) $img1
+    set image(2) $img2
+
+    scan [ $image(1) GetDimensions ] "%f %f %f" x1 y1 z1
+    scan [ $image(2) GetDimensions ] "%f %f %f" x2 y2 z2
+
+    if { $x1 < 2 || $x2  < 2 } { 
+	set errormessage  "No Reference or Transform Image in Memory\n Cannot Compute Overlap!"
+	return  ""
+    }
+
+    set range [ [ [ $image(1) GetPointData ] GetScalars ] GetRange ]
+    
+    set highthr  [ lindex $range 1 ]
+    set lowthr   [ expr $highthr *0.5 ]
+    set output ""
+
+    for { set k 1 } { $k <= 2 } { incr k } {
+	    
+	set cast($k)  [  vtkImageCast [ pxvtable::vnewobj ] ]
+	$cast($k) SetInput $image($k)
+	$cast($k) SetOutputScalarTypeToFloat
+	$cast($k) Update
+	
+	set prethreshold($k)  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+	
+	$prethreshold($k) SetInput [$cast($k)  GetOutput ]
+	$prethreshold($k) ThresholdBetween  $lowthr $highthr
+	$prethreshold($k) SetInValue    100
+	$prethreshold($k) SetOutValue   0
+	$prethreshold($k) ReplaceInOn
+	$prethreshold($k) ReplaceOutOn
+	$prethreshold($k) SetOutputScalarTypeToFloat
+	$prethreshold($k) Update
+	$cast($k) Delete
+	
+	set spa [ $image($k)  GetSpacing ]
+	
+	for { set i 0 } { $i <= 2 } { incr i } {
+	    set smsigma($i) [ expr $sigma / [ lindex $spa $i ]]
+	}
+	
+	set smooth($k)  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+	$smooth($k) SetStandardDeviations $smsigma(0) $smsigma(1) $smsigma(2)
+	$smooth($k) SetInput [ $prethreshold($k) GetOutput ] 
+	$smooth($k) SetRadiusFactors 1.5 1.5 1.5
+	$smooth($k) Update
+	$prethreshold($k) Delete
+	
+	
+	set threshold($k)  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+	
+	if { $k == 2 } {
+	    set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+	    $resl SetInput [ $smooth($k)  GetOutput ]
+	    $resl SetInformationInput [ $smooth(1) GetOutput ]
+	    $resl SetInterpolationMode 1
+	    $resl SetBackgroundLevel 0.0
+	    
+	    $resl SetResliceTransform $xform
+	    $resl Update
+	    $threshold($k) SetInput [ $resl GetOutput ]		
+	    $resl Delete
+	} else {
+	    $threshold($k) SetInput [ $smooth($k) GetOutput ]
+	}
+	    
+	set r [ [ [ [ $threshold($k) GetInput ] GetPointData ] GetScalars ] GetRange ]
+	set lowr [ expr 0.5* ([lindex $r 0 ] + [ lindex $r 1 ]) ]
+	set highr [ lindex $r 1 ]
+	$threshold($k) ThresholdBetween  $lowr $highr
+	$threshold($k) SetInValue    1
+	$threshold($k) SetOutValue   0
+	$threshold($k) ReplaceInOn
+	$threshold($k) ReplaceOutOn
+	$threshold($k) SetOutputScalarTypeToInt
+	$threshold($k) Update
+	
+	set finalimage($k) [ $threshold($k) GetOutput ]
+	
+	set accum($k)  [  vtkImageAccumulate [ pxvtable::vnewobj ] ]
+	
+	$accum($k) SetInput $finalimage($k)
+	$accum($k) SetComponentExtent 0 1 0 0 0 0
+	$accum($k) SetComponentOrigin 0 0 0 
+	$accum($k) SetComponentSpacing 1.0 1.0 1.0
+	$accum($k) Update
+	
+	if { $k == 1 } {
+	    set ve [ [ [ [ $accum($k) GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+	} else {
+	    set va [ [ [ [ $accum($k) GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+	}
+	
+    }
+    
+    set compare1 [ vtkImageMathematics [ pxvtable::vnewobj ]]
+    $compare1 SetInput1 $finalimage(1)
+    $compare1 SetInput2 $finalimage(2)
+    $compare1 SetOperationToMultiply
+    $compare1 Update
+    
+    set accumcompare1  [  vtkImageAccumulate [ pxvtable::vnewobj ] ]
+    $accumcompare1 SetInput [ $compare1 GetOutput ]
+    $accumcompare1 SetComponentExtent 0 1 0 0 0 0
+    $accumcompare1 SetComponentOrigin 0 0 0 
+    $accumcompare1 SetComponentSpacing 1.0 1.0 1.0
+    $accumcompare1 Update
+    
+    # vae == intersection 
+    set vae [ [ [ [ $accumcompare1 GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+    
+    set overlap [ expr 100.0 * $vae / ( $va + $ve - $vae ) ]
+    set overlap2 [ expr 100.0* $vae / ( 0.5 * ( $va + $ve )  ) ]
+    
+    if { $output == "" } {
+	set output  "\#thr \t Va\t Ve\t Vae\t Overlap\t Overlap2 \t Sigma\n"
+	$this PrintMessage $output
+    }
+
+    set line1 [ format "%.1f\t %.0f\t %.0f\t%.0f\t %.2f\t%.2f\t%.3f\n" $lowthr $va $ve $vae $overlap $overlap2 $sigma ]
+    $this PrintMessage $line1
+
+    set output  "${output}${line1}"
+
+    for { set k 1 } { $k <= 2 } { incr k } {
+	$threshold($k) Delete
+	$accum($k) Delete
+	$smooth($k) Delete
+	$finalimage($k) Delete
+    }
+    
+    $compare1 Delete
+    $accumcompare1 Delete
+    return $output
+}
+
+# -----------------------------------------------------------------------------------------
+# duplicated from pxmat_computeoverlap
+# -----------------------------------------------------------------------------------------
+itcl::body bis_computeoverlap::ComputeMultiOverlap { img1 img2 comment sigma xform } {
+
+    #    puts stdout "Comment=$comment, $sigma, [ $xform GetClassName ]"
+
+    set image(1) $img1
+    set image(2) $img2
+
+    set ut [ vtkpxTransformationUtil New ]
+
+    scan [ $image(1) GetDimensions ] "%f %f %f" x1 y1 z1
+    scan [ $image(2) GetDimensions ] "%f %f %f" x2 y2 z2
+
+    if { $x1 < 2 || $x2  < 2 } { 
+	set errormessage  "No Reference or Transform Image in Memory\n Cannot Compute Overlap!"
+	return  ""
+    }
+
+    set output ""
+
+    set range [ [ [ $image(1) GetPointData ] GetScalars ] GetRange ]
+
+    set low_thr [ expr [ lindex $range 0 ] + 1 ]
+    set high_thr  [ lindex $range 1 ]
+
+    # Step One Threshold both 
+    
+    for { set thr $low_thr } { $thr <=$high_thr } { set thr [ expr $thr +1.0 ] } {
+	for { set k 1 } { $k <= 2 } { incr k } {
+	    
+	    set cast($k)  [  vtkImageCast New ]
+	    $cast($k) SetInput $image($k)
+	    $cast($k) SetOutputScalarTypeToFloat
+	    $cast($k) Update
+
+	    set prethreshold($k)  [  vtkImageThreshold New ]
+	    
+	    set low  $thr 
+	    #[ expr $thr - 0.000001 ]
+	    set high $thr 
+	    #[ expr $thr + 0.000001 ]
+
+
+	    #	    puts stdout "Thresholds $low:$high"
+	    $prethreshold($k) SetInput [$cast($k)  GetOutput ]
+	    $prethreshold($k) ThresholdBetween  $low $high
+	    $prethreshold($k) SetInValue    100
+	    $prethreshold($k) SetOutValue   0
+	    $prethreshold($k) ReplaceInOn
+	    $prethreshold($k) ReplaceOutOn
+	    $prethreshold($k) SetOutputScalarTypeToFloat
+	    $prethreshold($k) Update
+
+	    $cast($k) Delete
+
+	    set spa [ $image($k)  GetSpacing ]
+	    
+	    for { set i 0 } { $i <= 2 } { incr i } {
+		set smsigma($i) [ expr $sigma / [ lindex $spa $i ]]
+	    }
+	    
+	    set smooth($k)  [ vtkImageGaussianSmooth New ]  
+	    $smooth($k) SetStandardDeviations $smsigma(0) $smsigma(1) $smsigma(2)
+	    $smooth($k) SetInput [ $prethreshold($k) GetOutput ] 
+	    $smooth($k) SetRadiusFactors 1.5 1.5 1.5
+	    $smooth($k) Update
+	    $prethreshold($k) Delete
+	    
+	    set threshold($k)  [  vtkImageThreshold New ]
+	    
+	    if { $k == 2 } {
+		set resl [ vtkbisImageReslice New ]
+		$resl SetInput [ $smooth($k)  GetOutput ]
+		$resl SetInformationInput [ $smooth(1) GetOutput ]
+		$resl SetInterpolationMode 1
+		$resl SetBackgroundLevel 0.0
+		$resl SetResliceTransform $xform
+		$resl Update
+		$threshold($k) SetInput [ $resl GetOutput ]		
+		$resl Delete
+	    } else {
+		$threshold($k) SetInput [ $smooth($k) GetOutput ]
+	    }
+	    
+
+	    set r [ [ [ [ $threshold($k) GetInput ] GetPointData ] GetScalars ] GetRange ]
+
+	    #	    puts stdout "r=$r\n"
+
+	    set lowr [ expr 0.5* ([lindex $r 0 ] + [ lindex $r 1 ]) ]
+	    set highr [ lindex $r 1 ]
+	    if { $highr == $lowr } {
+		if { $highr == 0.0 } {
+		    set lowr [ expr $lowr + 1.0 ]
+		} else {
+		    set lowr [ expr $lowr - 1.0 ]
+		}
+		set highr [ expr $lowr +1.0 ]
+
+	    }
+	    #	    puts stdout "New lowr:highr $lowr:$highr"
+	    $threshold($k) ThresholdBetween  $lowr $highr
+	    $threshold($k) SetInValue    1
+	    $threshold($k) SetOutValue   0
+	    $threshold($k) ReplaceInOn
+	    $threshold($k) ReplaceOutOn
+	    $threshold($k) SetOutputScalarTypeToUnsignedChar
+	    $threshold($k) Update
+
+	    set r2 [ lindex [ [ [ [ $threshold($k) GetOutput ] GetPointData ] GetScalars ] GetRange ] 1 ]
+	    set finalimage($k) [ $threshold($k) GetOutput ]
+		set accum($k)  [  vtkImageAccumulate New ]
+	    
+	    if { $r2 > 0 } {
+		$accum($k) SetInput $finalimage($k)
+		$accum($k) SetComponentExtent 0 1 0 0 0 0
+		$accum($k) SetComponentOrigin 0 0 0 
+		$accum($k) SetComponentSpacing 1.0 1.0 1.0
+		$accum($k) Update
+		
+		if { $k == 1 } {
+		    set ve [ [ [ [ $accum($k) GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+		} else {
+		    set va [ [ [ [ $accum($k) GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+		}
+	    } else {
+		if { $k == 1 } {
+		    set ve 0.0
+		} else {
+		    set va 0.0
+		}
+	    }
+	}
+	    
+	set compare1 [ vtkImageMathematics New ] 
+	$compare1 SetInput1 $finalimage(1)
+	$compare1 SetInput2 $finalimage(2)
+	$compare1 SetOperationToMultiply
+	$compare1 Update
+	
+	set accumcompare1  [  vtkImageAccumulate New ]
+	$accumcompare1 SetInput [ $compare1 GetOutput ]
+	$accumcompare1 SetComponentExtent 0 1 0 0 0 0
+	$accumcompare1 SetComponentOrigin 0 0 0 
+	$accumcompare1 SetComponentSpacing 1.0 1.0 1.0
+	$accumcompare1 Update
+	
+	# vae == intesection 
+	set vae [ [ [ [ $accumcompare1 GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+	
+	if { $va ==0 && $ve == 0 } {
+	    set overlap 0
+	    set overlap2 0
+	} else {
+	    set overlap [ expr 100.0 * $vae / ( $va + $ve - $vae ) ]
+	    set overlap2 [ expr 100.0* $vae / ( 0.5 * ( $va + $ve )  ) ]
+	}
+	
+	if { $output == "" } {
+	    set output  "\#thr \t Va\t Ve\t Vae\t Overlap\t Overlap2 \t Sigma\n"
+	    $this PrintMessage $output
+	}
+	set line1 [ format "%.1f\t %.0f\t %.0f\t%.0f\t %.2f\t%.2f\t%.3f\n" $thr $va $ve $vae $overlap $overlap2 $sigma ]
+	$this PrintMessage $line1
+
+	set output  "${output}${line1}"
+	
+	for { set k 1 } { $k <= 2 } { incr k } {
+	    $threshold($k) Delete
+	    $accum($k) Delete
+	    $smooth($k) Delete
+		$finalimage($k) Delete
+	}
+	
+	${compare1} Delete
+	${accumcompare1} Delete
+	
+    }
+
+    return $output
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computeoverlap::Execute {  } {
+
+    PrintDebug "bis_computeoverlap::Execute"
+
+    set saveimage [  $OptionsArray(saveasimage)  GetValue ]
+
+    if { $saveimage == 0 } {
+	if { $guimode == "commandline" } {
+	    if { [ $OptionsArray(filename) GetValue ] == "" } {
+		set errormessage "Empty Output Filename (-filename) for computing overlaps"
+		return 0
+	    }
+	}
+    }
+    
+    set sigma   [ $OptionsArray(sigma) GetValue ]
+    set ref    [ [ $this GetInput ] GetObject ]
+    set trg    [ [ $this GetSecondInput ]  GetObject ]
+    set xform  [ [  $this GetTransformation ]  GetObject ]
+
+    set comment ""
+    if { $guimode !="commandline" } {
+	#	puts "GUIMODE = $guimode "
+	pxtkconsole; 
+	pxtkprint "\n-------------------------------------------------\n"
+	pxtkprint "Computing Overlaps [ $this GetCommandLine short ]\n" 
+	pxtkprint "-------------------------------------------------\n"
+    }
+
+    if { [  $OptionsArray(multioverlap) GetValue ] == 0 } {
+	set output [ ComputeOverlap $ref $trg $comment $sigma $xform ]
+    } else {
+	set output [ ComputeMultiOverlap $ref $trg $comment $sigma $xform ]
+    }
+    
+
+    if { $saveimage == 0 } { 
+	if { [ $OptionsArray(filename) GetValue ] != "" } {
+	    set fout [ open [ $OptionsArray(filename) GetValue ] w ]
+	    puts $fout $output
+	    close $fout
+	    PrintMessage "Output saved in [ $OptionsArray(filename) GetValue ]\n"
+	}
+    } 
+	
+    set lines [ split $output "\n" ]
+    set goodlines ""
+    set max 0 
+
+    for { set i 0 } { $i < [ llength $lines ] } { incr i } {
+	set line [ lindex $lines $i ] 
+	#	puts stdout "Line $i = $line"
+	set n [ llength $line ]
+	set m [ string range $line 0 0 ]
+	if { $m != "\#"  && $n > 1 } {
+	    lappend goodlines $line
+	    if { $n > $max } {
+		set max $n
+	    }
+	}
+    }
+
+    set img [ vtkImageData New ]
+    $img SetDimensions [ llength $goodlines ] $max 1
+    $img SetScalarTypeToFloat
+    $img AllocateScalars
+    
+    set dat [ [ $img GetPointData ] GetScalars ]
+    $dat FillComponent 0 -10000.0
+
+    for { set i 0 } { $i < [ llength $goodlines ] } { incr i } {
+	set line [ lindex $goodlines $i ]
+	for { set j 0 } { $j < [ llength $line ] } { incr j } {
+	    catch { $img SetScalarComponentFromDouble $i $j 0 0 [ lindex $line $j ]  }
+	}
+    }
+
+    set outimage [ $this GetOutput ]
+    $outimage ShallowCopyImage $img;     $img Delete
+    $outimage CopyImageHeader [ [ $this GetInput ] GetImageHeader ]
+    
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment" 0
+    [ $outimage GetImageHeader ] AddComment "Overlap Output\n$output\n" 0
+    
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_computeoverlap.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+   
+
+    set alg [bis_computeoverlap [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computesimilarity.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computesimilarity.tcl
new file mode 100755
index 0000000..d052bbc
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computesimilarity.tcl
@@ -0,0 +1,323 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagetransformationalgorithm 1.0
+package provide bis_computesimilarity 1.0
+
+#
+# compute similarity
+#
+
+itcl::class bis_computesimilarity {
+
+    inherit bis_dualimagetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Compute Similarity" }
+    public method UpdateContainerWithOutput { } { }
+    
+    #
+    #protected
+    #
+    protected method ComputeImageSimilarity { }
+    protected method ComputeSurfaceSimilarity { }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computesimilarity::Initialize { } {
+
+    PrintDebug "bis_computesimilarity::Initialize" 
+    set inputs { 
+	{ reference_surface   "Reference Surface Objectmap" pxitclsurface  ""  103 }
+	{ target_surface      "Target Surface Objectmap"    pxitclsurface  ""  104 }
+    }
+
+    set options {
+	{ temperature    "Surface Matching: temperature. Used when matchmode !=0 " "temperature" int   0     { 0 1 }  -100 }
+	{ numpoints      "Surface Matching: number of points to use for distance computation" "numpoints" int   0     { 0 1 } -101 }
+	{ matchmode     "Surface Matching:  0 = ICP, 1=Mixture, 2=RPM (Use 0 for nearest neighbor)" "matchmode"  int   0     { 0 1 }  -102 }
+	{ numberofbins    "Number of bins for the joint histogram"          "Number of Bins"     int   64    { 32  1024 } -103 }
+	{ mode           "Mode (Surface/Image/Both)"   "Mode"  listofvalues  Image    { Image Surface Both }  1  }
+	{ filename       "specify the filname for the output text file" "Text File Name" { filename writefile } "" { text { .txt } 50 } -30 }
+	{ saveasimage "If on the output is an image instead of a text file"  "SaveImage"  boolean   0  { 0 1  }  -40  } 
+    }
+
+
+    set defaultsuffix { "_similarity" }
+    
+    set scriptname bis_computesimilarity
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+
+    set category "Registration"
+    set description  "computes image similarity measures between the reference image and the target image after a transform and optionally point distances between the reference surface and the target surface."
+    set description2 "Computed metrics for images are Joint Entropy, CR, Gradient Correlation, Mutual Information, Normalized Mutual Information, Sum of Squared Differences, Correlation ratio C(X|Y), Correlation ratio C(Y|X), Product, DifferenceEntropy."
+    set backwardcompatibility "Reimplemented from pxmat_computesimilarity.tcl.point distance computation part should be integrated with bis_computedistance.tcl"
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+
+    $this InitializeDualImageTransformationAlgorithm
+
+    $this RenameInput 0 "Reference Objectmap" 100
+    $this RenameInput 1 "Target Objectmap" 101
+    $this RenameInput 2 "Tranformation" 102
+
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_computesimilarity::ComputeImageSimilarity { } {
+
+    set inp(1) [ $this GetInput ] 
+    set inp(2) [ $this GetSecondInput ] 
+
+    for { set i 1 } { $i  <=2 } { incr i } {
+	set d [ $inp($i) GetImageSize ]
+	if { $d < 2 } {
+	    set errormessage "Input Image $i is bad, cannot compute image similarity"
+	    return 0
+	}
+    }
+
+    set image_ref [ $inp(1) GetImage ]
+    set image_trn [ $inp(2) GetImage ]
+    set current_transform  [ [  $this GetTransformation ]  GetObject ]
+    set numbins [ $OptionsArray(numberofbins) GetValue ]
+
+    set reg [ vtkpxRegistration [ pxvtable::vnewobj ]]
+    set arr [ vtkFloatArray [ pxvtable::vnewobj ]]
+    set reg_measures [ list "Joint Entropy" "CR" "Gradient Correlation" "Mutual Information" "NMI" "Sum of Sq Diff" "Correlation ratio C(X|Y)" "Correlation ratio C(Y|X)" ]
+
+    set image_ref_short [vtkImageData [pxvtable::vnewobj]]
+    set image_trn_short [vtkImageData [pxvtable::vnewobj]]
+
+    $reg ExtractComponentAndCastImageToShort $image_ref_short $image_ref 0 0
+    $reg ExtractComponentAndCastImageToShort $image_trn_short $image_trn 0 0
+    $reg ComputeAllSimilarityMetricsBetweenImages $image_ref_short $image_trn_short $current_transform $arr $numbins
+    $reg Delete
+
+    PrintMessage  "Computing Similarity between ref and resliced transform images\n"
+
+    set headerline "\#"
+    set contentline ""
+    
+    for { set i 0 } { $i < [ llength $reg_measures ] } { incr i } {
+	if { $i== 1 || $i ==3 || $i==4 || $i==5 } {
+	    append headerline "[ lindex $reg_measures $i ]\t"
+	    append contentline "[ $arr GetComponent $i 0 ]\t"
+	    #	    puts stdout "H=$headerline\nC=$contentline\n"
+	}
+    }
+
+    $image_ref_short Delete
+    $image_trn_short Delete
+    $arr Delete
+
+    set sm 0.0
+    if { [ $current_transform IsA vtkpxComboTransform  ] ==1 } {
+	set sm [ [ $current_transform GetGridTransform ] ComputeTotalBendingEnergy ]
+	append headerline "Bending Energy"
+	append contentline $sm
+    }
+
+    PrintMessage "$headerline\n$contentline\n"
+    return "$headerline\n$contentline\n"
+}
+
+itcl::body bis_computesimilarity::ComputeSurfaceSimilarity {  } {
+
+
+    set inp(1) [ $this GetInputObject reference_surface ]
+    set inp(2) [ $this GetInputObject target_surface ]
+
+    for { set i 1 } { $i  <=2 } { incr i } {
+	set d [ $inp($i) GetSurfaceSize ]
+	if { $d < 2 } {
+	    set errormessage "Input Surface $i is bad, cannot compute surface similarity"
+	    return 0
+	}
+    }
+
+    set distance 0.0
+    set surface_ref [ $inp(1)   GetObject ] 
+    set surface_trn [ $inp(2)   GetObject ] 
+
+    set rpm [ vtkpxRPMCorrespondenceFinder New ]
+    $rpm SetSource [$surface_ref GetObject ]
+    $rpm SetTarget [$surface_trn GetObject ]
+    $rpm SetMaximumNumberOfLandmarks $numpoint
+    $rpm SetMatchMode $matchmode
+    $rpm SetUseLabels 1
+    $rpm SetFastThreshold 3.0
+    $rpm Initialize
+	
+    $rpm WarpAndUpdateCorrespondence $trn $temperature
+    set d [ $rpm ComputeDistance [ lindex $argv 2 ] ]
+    set output [ format "\#EX \t %s \t RPM \n%8.5f\n" [ lindex $argv 2 ] $d ]
+    $rpm Delete
+
+    PrintMessage $output
+    return output
+    
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computesimilarity::Execute {  } {
+
+    PrintDebug "bis_computesimilarity::Execute"
+    set saveimage [  $OptionsArray(saveasimage)  GetValue ]
+    set mode [ $OptionsArray(mode) GetValue ]
+
+    if { $saveimage == 0 } {
+	if { $guimode == "commandline" } {
+	    if { [ $OptionsArray(filename) GetValue ] == "" } {
+		set errormessage "Empty Output Filename (-filename) for computing similarity metrics ($mode)"
+		return 0
+	    }
+	}
+    }
+
+    set out1 "#No Image Similarity Computed\n0\t0\t0"
+    set out2 "#No Surface Similarity Computed\n 0\t0\t0"
+
+
+    if { $guimode !="commandline" } {
+	pxtkconsole; 
+	pxtkprint "\n-------------------------------------------------\n"
+	pxtkprint "Computing Similarities ($mode), [ $this GetCommandLine short ]\n" 
+	pxtkprint "-------------------------------------------------\n"
+    }
+
+
+
+    if { $mode == "Image" || $mode == "Both" } {
+	set out1 [ $this ComputeImageSimilarity ]
+	#	puts stderr "out1 = $out1"
+	if { $out1 == 0 } {
+	    return 0
+	}
+    }
+
+    if { $mode == "Surface" || $mode == "Both" } {
+	set out2 [ $this ComputeSurfaceSimilarity ]
+	if { $out2 == 0 } {
+	    return 0
+	}
+    }
+
+    if { $saveimage == 0 } {
+	if { [ $OptionsArray(filename) GetValue ] != "" } {
+	    set fout [ open [ $OptionsArray(filename) GetValue ] w ]
+	    puts -nonewline $fout $out1
+	    puts -nonewline $fout $out2
+	    close $fout
+	    PrintMessage "Output saved in [ $OptionsArray(filename) GetValue ]"
+	}
+    }
+
+    set output "$out1\n$out2\n"
+    set lines [ split $output "\n" ]
+    set goodlines ""
+    set max 0 
+    for { set i 0 } { $i < [ llength $lines ] } { incr i } {
+	set line [ lindex $lines $i ] 
+	#	puts stdout "Line $i = $line"
+	set n [ llength $line ]
+	set m [ string range $line 0 0 ]
+	if { $m != "\#"  && $n > 1 } {
+	    lappend goodlines $line
+	    if { $n > $max } {
+		set max $n
+	    }
+	}
+    }
+    #    puts stderr "Goodlines = $goodlines"
+
+    set img [ vtkImageData New ]
+    $img SetDimensions 2 $max 1
+    $img SetScalarTypeToFloat
+    $img AllocateScalars
+    
+    set dat [ [ $img GetPointData ] GetScalars ]
+    $dat FillComponent 0 -10000.0
+
+    for { set i 0 } { $i < [ llength $goodlines ] } { incr i } {
+	set line [ lindex $goodlines $i ]
+	for { set j 0 } { $j < [ llength $line ] } { incr j } {
+	    $img SetScalarComponentFromDouble $i $j 0 0 [ lindex $line $j ] 
+	}
+    }
+
+    set outimage [ $this GetOutput ]
+    $outimage ShallowCopyImage $img;     $img Delete
+    $outimage CopyImageHeader [ [ $this GetInput ] GetImageHeader ]
+    
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment" 0
+    [ $outimage GetImageHeader ] AddComment "Similarity Output\n$output\n" 0
+    
+
+
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_computesimilarity.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_computesimilarity [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computetensor.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computetensor.tcl
new file mode 100755
index 0000000..9013263
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_computetensor.tcl
@@ -0,0 +1,284 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] mjack]
+
+package require bis_imagelisttoimagealgorithm 
+package require vtkmpjcontrib 
+package require mpjtensorutility 
+package require bis_basecontrolhelper
+
+package provide bis_computetensor 1.0
+
+
+# -------------------------------
+itcl::class bis_computetensor {
+
+    inherit bis_imagelisttoimagealgorithm
+    
+    constructor { } {
+	$this Initialize
+    }
+
+    destructor { $this DeleteDTIControl }
+    
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Compute Tensor" }
+    public method UpdateOutputFilenames { } 
+    public method ConfigureOptionsGUICallbacks { } 
+
+    public method ShowDTIControl {  args } 
+    protected method DeleteDTIControl { }
+    protected method CopyOutputObject { name index comment comment2 } 
+
+    # variables
+    protected variable tensorutility 0
+    protected variable bishelper 0
+
+
+
+}
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_computetensor::Initialize { } {
+
+    PrintDebug "bis_computetensor::Initialize" 
+
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set inputs { }
+
+
+    set outputs {
+	{ outadc "ADC"    pxitclimage  "" 100 }
+	{ outbase "Baseline"          pxitclimage  "" 101 }
+    }
+    
+    set gradientnamelist [ list ME6 ICO6 ICO10 ICO15 ICO21 ME24 ME32 VAR15 Custom ]
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options ""
+
+    lappend options [ eval "list directions  \"acquisition directions\" Directions  listofvalues [ lindex $gradientnamelist 0 ]  { $gradientnamelist }  1" ]
+    lappend options [ eval "list ndw  \"Number of Baseline Images\" \"Num Baseline\"  integer 1 { 0 20 } 2 " ]
+    lappend options [ eval "list bval  \"b-value (s/mm**2)\" \"b-value\"  real 1000 { 1 10000 } 3 " ]
+    lappend options [ list dirfname   "specify the filname for custom directions" "Directions File Name" { filename readfile } "" { text { .txt } } 30 ]
+    lappend options [ list flipx   "Flip the x-direction of the images" "Flip-X" listofvalues Auto  { On Off Auto } -30 ]
+    lappend options [ list flipy   "Flip the y-direction of the images" "Flip-Y" listofvalues Auto  { On Off Auto } -31 ]
+    lappend options [ list flipz   "Flip the z-direction of the images" "Flip-Z" listofvalues Auto  { On Off Auto } -32 ]
+    lappend options [ list guishowcontrol  "Show Tensor Utility Control" "Show Control"  { boolean } 0 { 0 1 }  5 ]
+
+    set defaultsuffix { _tensor }
+    
+    set scriptname bis_computetensor
+
+    #
+    #document
+    #
+
+    set category "Diffusion Tensor"
+    set description  "Given Raw DWI images, it estimates the symmetric 6-component tensor"
+    set description2 "BioImage Suite assumes(or forces on load in the case of NIFTI images) LPS Image Orientation hence flipx=flipy=1 by default"
+    set backwardcompatibility "Reimplemented from pxmat_diffusionutility.tcl"
+    set authors "marcel.jackowski at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this InitializeImageListToImageAlgorithm
+
+    $this RenameOutput 0 "Tensor Image"
+}
+
+# ---------------------------------------------------------------
+
+itcl::body bis_computetensor::DeleteDTIControl { } {
+
+    if { $tensorutility == 0 } {
+	return
+    }
+
+    $tensorutility ClearAllResults
+    $tensorutility RemoveAllInputs
+
+    itcl::delete obj $bishelper
+    itcl::delete obj $tensorutility
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_computetensor::UpdateOutputFilenames { } {
+
+    set inplist [ $InputsArray($directinputs) GetAllObjects ]
+    set fn  [ [ lindex $inplist 0 ] GetFileName ]
+    set outlist [ $this CreateDefaultOutputFileList $fn ]
+
+    set l [ ::bis_common::SplitFileNameGZ $fn ]
+    set ext [ lindex $l 1 ]
+
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+
+    set m [ lindex $outlist 0 ]
+    $OutputsArray(output_image) SetFileName "${m}${ext}" $force
+    return 1
+}
+# -----------------------------------------------------------------------------------------
+itcl::body bis_computetensor::CopyOutputObject { name index comment comment2 } {
+
+    set f2 [ [ $this GetOutputObject $name ] GetFileName ]
+    [ $this GetOutputObject $name ] ShallowCopy [ $tensorutility GetOutputImage $index ]
+    [ $this GetOutputObject $name ] AddComment "$comment ($comment2)" 
+    if { [ string length $f2 ] > 1 } {
+	[ $this GetOutputObject $name ] SetFileName $f2
+    }
+
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_computetensor::ConfigureOptionsGUICallbacks { } {
+
+    eval "$OptionsArray(guishowcontrol) SetGUICallbackFunction { $this ShowDTIControl }"
+}
+
+itcl::body bis_computetensor::ShowDTIControl {  args } {
+
+
+    if { $tensorutility != 0 } {
+	if { [ $OptionsArray(guishowcontrol) GetValue ] ==0 } {
+	    $tensorutility HideWindow
+	} else  {
+	    $tensorutility ShowWindow Diffusion
+	}
+    }
+}
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_computetensor::Execute {  } {
+
+
+
+    set inplist [ $InputsArray($directinputs) GetAllObjects ]
+    set numfiles [ llength $inplist ]
+    set directions  [ $OptionsArray(directions) GetValue ]
+    set ndw         [ $OptionsArray(ndw) GetValue ]
+    set bval        [ $OptionsArray(bval) GetValue ]
+    set dirfname    [ $OptionsArray(dirfname) GetValue ]
+    set flip(1)       [ $OptionsArray(flipx) GetValue ]
+    set flip(2)     [ $OptionsArray(flipy) GetValue ]
+    set flip(3)     [ $OptionsArray(flipz) GetValue ]
+
+    if { $numfiles == 0 } {
+	set errormessage "No Inputs specified"
+	return 0
+    }
+
+
+    if { $tensorutility == 0 } {
+
+	set bishelper [ [ bis_basecontrolhelper #auto $this ] GetThisPointer ]
+
+	if { $basewidget!=0 } {
+	    set b $basewidget.[pxvtable::vnewobj ]
+	} else {
+	    set b .[pxvtable::vnewobj ]
+	}
+	set  tensorutility [ [  mpjtensorutility \#auto $bishelper  ] GetThisPointer ]
+	$tensorutility Initialize $b
+	$tensorutility ShowWindow Diffusion
+	$tensorutility HideWindow
+    }
+
+    if { [ $OptionsArray(guishowcontrol) GetValue ] == 1 } {
+	$tensorutility ShowWindow Diffusion
+    } else {
+	$tensorutility HideWindow
+    }
+    
+
+    $tensorutility RemoveAllInputs
+    for { set i 0 } { $i < $numfiles } { incr i } {
+	set ok [ $tensorutility AddInput [ [ lindex $inplist $i ] GetFileName ] 0 ]
+	if { [ lindex $ok 0 ] == 0 } {
+	    set errormessage [ lindex $ok 1 ]
+	    return 0
+	}
+    }
+
+    set hdr [ [ lindex $inplist 0 ] GetImageHeader ]
+    for { set i 1 } { $i <=3 } { incr i } {
+	if { $flip($i) == "On" } {
+	    set flip($i) 1
+	} elseif { $flip($i) == "Off" } {
+	    set flip($i) 0
+	} else {
+	    set orient [ $hdr GetOrientation ]
+	    puts stdout "Orientation = $orient"
+	    set flip($i) 0
+	    if { [ $hdr GetMode ] > 0  } {
+		
+	    } elseif { $orient == 0 } {
+		if { $i < 3 } {
+		    set flip($i) 1
+		} else {
+		    set flip($i) 0
+		}
+	    } 
+	}
+    }
+
+
+    $tensorutility SetParametersFromBisAlgorithm $ndw $bval $directions $dirfname $flip(1) $flip(2) $flip(3)
+    $tensorutility ComputeResults
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    $this CopyOutputObject output_image 2 $comment "tensor"
+    $this CopyOutputObject outadc 4 $comment "adc"
+    $this CopyOutputObject outbase 0 $comment "baseline"
+    
+    return 1
+
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_computetensor.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_computetensor [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_connect.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_connect.tcl
new file mode 100755
index 0000000..3ee8453
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_connect.tcl
@@ -0,0 +1,141 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_surfacetosurfacealgorithm 1.0
+
+package provide bis_connect 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_connect {
+
+    inherit bis_surfacetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Connect" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_connect::Initialize { } {
+
+    PrintDebug "bis_connect::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	    { connectType "Connect Largest Region or Nearest Point" "Type of connection"  { listofvalues radiobutton}  Largest_Region { Largest_Region Nearest_Point}   1}
+	    { nx "X-coordinate of Nearest Point" "Nearest Point-x"  real  1.0 {0.0 500.0} 2 }
+        { ny "Y-coordinate of Nearest Point" "Nearest Point-y"  real  1.0 {0.0 500.0} 3 }
+        { nz "Z-coordinate of Nearest Point" "Nearest Point-z"  real  1.0 {0.0 500.0} 4 }
+  	}
+
+    set defaultsuffix { "_connect" }
+    
+    set scriptname bis_connect
+
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "Extract polygonal data based on geometric connectivity"
+    set description2 "takes a surface as an input"
+    set backwardcompatibility "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeSurfacetoSurfaceAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_connect::Execute {  } {
+
+    PrintDebug "bis_connect::Execute"
+
+    # Get Inputs
+    set surface    [ $this GetInput  ]
+    # GetOptions
+    
+    set connectType [ $OptionsArray(connectType) GetValue ]
+    set nx [ $OptionsArray(nx) GetValue ]
+    set ny [ $OptionsArray(ny) GetValue ]
+    set nz [ $OptionsArray(nz) GetValue ]
+    
+   # Run Algorithm    
+	set filter [ vtkPolyDataConnectivityFilter [ pxvtable::vnewobj ] ]
+	$filter SetInput [ $surface GetObject ]
+
+	if { $connectType == "Largest_Region" } {
+		$filter SetExtractionModeToLargestRegion 	
+	} else {
+		$filter SetExtractionModeToClosestPointRegion
+		$filter SetClosestPoint $nx $ny $nz
+	}
+	    
+	$filter Update
+    
+    # Store Results in output
+    set surface_out [$filter GetOutput ]
+    [ $OutputsArray(output_surface) GetObject ] DeepCopySurface $surface_out 
+
+    # Clean up
+    $filter Delete
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_connect.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_connect [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_convolveimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_convolveimage.tcl
new file mode 100755
index 0000000..314269c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_convolveimage.tcl
@@ -0,0 +1,179 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_convolveimage 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+itcl::class bis_convolveimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Convolve Image" }
+	public method UpdateOutputFilenames { } 
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_convolveimage::Initialize { } {
+
+    PrintDebug "bis_convolveimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ blursigma "kernel size [mm/voxel] of FWHM filter size" "Filter Size"  { real triplescale 100 }    2.0 { 0.0 20.0 }  2 }
+	{ unit      "kernel size unit mm or voxels " "Units" { listofvalues radiobuttons }  mm { mm voxels }   3 }
+	{ radius    "radius factor of the gaussian in voxel units " "Filter Radius" real  1.5   { 0.0 5.0 }  -1 }
+	{ mode      "Operation to perform" "Mode" { listofvalues }  Smooth { Smooth Gradient Hessian }   1}
+    }
+
+    set outputs { 
+	{ filterbank   "FilterBank Image" pxitclimage  ""  200 }
+    }
+
+    set defaultsuffix { "_sm" }
+    
+    set scriptname bis_convolveimage
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Convolvees an image with a specific gaussian/gaussian derivative/hessian kernel."
+    set description2 "Convolveing kernel size blursigma (in mm by default ) represents the FWHM filter size."
+    set backwardcompatibility ""
+
+    $this InitializeImageToImageAlgorithm
+}
+# -----------------------------------------------------------------------------------------
+itcl::body bis_convolveimage::UpdateOutputFilenames { } {
+
+    set mode   [ $OptionsArray(mode) GetValue ]
+    if { $mode == "Smooth" } {
+	set defaultsuffix { "_sm" }
+    } elseif { $mode == "Gradient" } {
+	set defaultsuffix { "_grad" }
+    } else {
+	set defaultsuffix { "_hessian" }
+    }
+
+    return [ ::bis_imagetoimagealgorithm::UpdateOutputFilenames  ]
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_convolveimage::Execute {  } {
+
+    PrintDebug "bis_convolveimage::Execute"
+
+    set mode   [ $OptionsArray(mode) GetValue ]
+    set blursigma   [ $OptionsArray(blursigma) GetValue ]
+    set unit        [ $OptionsArray(unit)      GetValue ]
+    set radius      [ $OptionsArray(radius)    GetValue ]
+    set image_in    [ $this GetInput ]
+
+    set spacing [[ $image_in GetImage ] GetSpacing ]
+
+    if { $unit == "mm"} {
+	for { set j 0 } { $j <=2 } { incr j } {
+	    set sigma($j) [ expr $blursigma * 0.4247 / [ lindex $spacing $j ]]
+	}
+    } else {
+	for { set j 0 } { $j <=2 } { incr j } {
+	    set sigma($j) [ expr $blursigma * 0.4247 ]
+	}
+    }
+
+
+    PrintDebug "radius = $radius sigma = $sigma(0) $sigma(1) $sigma(2), mode=$mode"
+    set convolve  [ vtkxqImageFourierConvolution [ pxvtable::vnewobj ]  ]
+    
+    if { $mode == "Smooth" } {
+	$convolve SetFilterBankToGaussian $sigma(0) $sigma(1) $sigma(2) $radius
+    } elseif { $mode == "Gradient" } {
+	$convolve SetFilterBankToGaussianDerivative $sigma(0) $sigma(1) $sigma(2) $radius
+#    } elseif { $mode == "Blob" } {
+#	$convolve SetFilterBankToMultiScaleBlob [ $OptionsArray(blobscale) GetValue ] $sigma(0) 
+    } else {
+	$convolve SetFilterBankToHessian $sigma(0) $sigma(1) $sigma(2) $radius
+    }
+    $convolve SetMode 0
+    $convolve SetInput [ $image_in GetObject ]
+    $this SetFilterCallbacks $convolve "Convolving Image ($mode)"
+    $convolve Update
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $convolve GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    set fbank [ $OutputsArray(filterbank) GetObject ]
+    $fbank ShallowCopyImage [ $convolve GetFilterBank ]
+    [ $fbank GetImageHeader ] AddComment "$comment -- this is the filterbank" 0
+
+
+    $convolve Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_convolveimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_convolveimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_create4dimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_create4dimage.tcl
new file mode 100755
index 0000000..39c409d
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_create4dimage.tcl
@@ -0,0 +1,140 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagelisttoimagealgorithm 
+package provide bis_create4dimage 1.0
+
+#
+# create 4d image
+#
+
+itcl::class bis_create4dimage {
+
+    #inherit bis_imagelisttoimagealgorithm
+    inherit bis_imagelisttoimagealgorithm
+
+    constructor { } {
+	$this Initialize
+    }
+
+    public method Initialize { }
+    public method Execute    { }
+    public method GetGUIName    { } { return "Concatenate Set of 3D Images" }
+}
+
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_create4dimage::Initialize { } {
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{  guicmt "Inputs"  "Note"  comment "Takes in a variable amount of images" \
+	       "Create a 4d image by appending each image to the first image as a new frame"  1 }
+
+    }
+
+    set defaultsuffix { "_4D" }
+    
+    set scriptname bis_create4dimage
+    set completionstatus "Done"
+    #
+    #document
+    #
+    set category "Image Processing Multiple"
+    set description  "combines a number of 3D volumes into a single 4D image."
+    set description2 "Output filename is image1_4D.hdr (or image1_4D.nifti)"
+
+    set backwardcompatibility "Reimplemented from pxmat_create4dimage.tcl."
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu, dustin.scheinost at yale.edu"
+
+    $this InitializeImageListToImageAlgorithm
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_create4dimage::Execute {  } {
+
+    PrintDebug "bis_create4dimage::Execute"
+
+    set maxi 0
+    set errorflag 0
+
+    set inplist [ $InputsArray($directinputs) GetAllObjects ]
+    set numfiles [ llength $inplist ]
+    
+    if { $numfiles < 2 } {
+	set errormessage "Nothing do less than 2 inputs specified"
+	return 0
+    }
+
+    set appnd [ vtkImageAppendComponents [ pxvtable::vnewobj ]]	
+    for { set i 0 } { $i < $numfiles } { incr i } {
+	puts stdout "Adding image [ expr $i+1 ], [ [ lindex $inplist $i ] GetShortDescription ]"
+	$appnd AddInput  [ [ lindex $inplist $i]  GetImage ]
+    }
+    $this SetFilterCallbacks $appnd "Creating 4D Image"
+    $appnd Update
+    set image_out [ $appnd GetOutput ]
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader  [ [ lindex $inplist 0 ] GetImageHeader ]
+    [ $outimage GetImageHeader ] AddComment [ $this GetCommandLine full ] 0
+    $appnd Delete
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_create4dimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_create4dimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_createoverlayimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_createoverlayimage.tcl
new file mode 100755
index 0000000..6014f40
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_createoverlayimage.tcl
@@ -0,0 +1,502 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagereslicetransformationalgorithm 1.0
+package require bis_clusterthresholdimage 1.0
+package provide bis_createoverlayimage 1.0
+package require pxtcluserprefs 1.0
+#
+# createoverlay image
+#
+
+itcl::class bis_createoverlayimage {
+
+    inherit bis_dualimagereslicetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Create Image Overlay"}
+    protected method PackOptionsGUIInterface { lst }
+
+    protected method ConfigureOptionsGUICallbacks { } 
+    public    method ShowScalarBar { args } 
+
+    public method UpdateInputsFromContainer { }
+    public method UpdateInputRanges { args }
+    public method UpdateContainerWithOutput { } 
+
+
+
+    
+    protected variable lastrmax ""
+    protected variable noguiupdates 0
+
+};
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_createoverlayimage::Initialize { } {
+
+    PrintDebug "bis_createoverlayimage::Initialize" 
+
+    set options {
+
+	{ otype       "Overlay Type, select which part of the functional image is used " "Overlay Type"  listofvalues Both { "Positive" "Negative" "Both" }  1 }
+	{ colormap    "Select the colormap needed for this overlay F1 (anat=0.55,func=56.63) F2(anat=0.191, func=192:255), F4=(anat=0.237,func=239:255)" "Colormap"  listofvalues F1 { "F1" "F2" "F4" }  2 }
+	{  minth      "Lower Threshold value for functional image" "Low Threshold"   real   0.0 { -100000000.0 100000000.0 }  3 }
+	{  maxth      "Upper Threshold value for functional image" "High Threshold"  real 100.0 { -100000000.0 100000000.0 }  4 }
+	{  inth       "Intensity Threshold value -- used to mask overlay if base image is lower than this" "Anat Threshold"  real 5.0 { 0.0 255.0 }  -11 }
+	{  clustersize "Cluster Threshold Value" "Cluster Size"  integer  0 { 0 100000000 }  7 }
+	{  origvoxels  "Use Voxel size in Functional Image (before reslicing) to determine clustersize" "Orig Voxels"  boolean  0 { 0 1 }  6 }
+	{  normanat    "Intensity Normalize Anatomical Image prior to overlay" "Normalize Anatomical Image"  boolean  1 { 0 1 }  -10 }
+	{ interp      "Interpolation Mode that is used when reslicing the functional image" "Interpolation Mode"  listofvalues Linear { "NearestNeighbor" "Linear" "Cubic" } -12 }
+	{  singframe  "Use Single frame from Functional Image to create overlay" "Single Frame"  boolean  1 { 0 1 }  8 }
+	{  frame      "Specify frame to use in case of single frame overlay" "frame"  integer 1 { 1 1000 }  9 }
+	{ oneconnected  "Use 1-Connected Clustering"  "1-Connected" boolean  1 { 0 1 }  -10 }
+	{  guisbar     "Show Scalar Bar below overlay" "Show Color Bar"  boolean  0 { 0 1 }  12 }
+	{  guireslice  "Show Reslice Output Only" "Show Resliced Functional"  boolean  0 { 0 1 }  -12 }
+	{  guilateral  "Laterality Index" "Laterality"  comment  "         " ""  13 }
+    }
+
+    set outputs { { resliced_tmap "Resliced Output Image"  pxitclimage  "" 120 }}
+
+    set defaultsuffix { "_createoverlay" }
+    
+    set scriptname bis_createoverlayimage
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    set category "Image Processing Dual"
+    set description "createoverlays an image using one or more transformations."
+    set description2 "a useful check of the quality of the transformations"
+    set backwardcompatibility "Reimplemented from pxmat_createoverlayimage.tcl."
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageTransformationAlgorithm
+    $this SetUseReslicedImageAsInput 1
+
+
+    global pxtcl_pref_array
+
+    $OptionsArray(colormap) SetValue $pxtcl_pref_array(FmriMode)
+    $OptionsArray(normanat) SetValue [ expr $pxtcl_pref_array(NormalizeAnatomical) > 0 ]
+}
+
+itcl::body bis_createoverlayimage::PackOptionsGUIInterface { lst } { 
+
+
+    if { $guimode == "standalone" } {
+	return [ bis_algorithm::PackOptionsGUIInterface $lst ]
+    }
+
+    set n [ llength $lst ]
+    PrintDebug "\n\n Length of list = $n"
+
+    for { set tab 0 } { $tab <= 1 } { incr tab } {
+	set wlist ""
+	for { set i 0 } { $i < $n } { incr i } {
+	    
+		set pair [ lindex $lst $i ]
+		set ind  [ lindex $pair 1 ]
+		if { $ind == $tab } {
+		    lappend wlist $pair
+		}
+	    }
+
+	set wlist [ lsort -integer  -index 0 $wlist ]
+
+
+	if { $tab == 1 } {
+	    for { set j 0 } { $j < [ llength $wlist ] } { incr j } {
+		set pair [ lindex $wlist $j ]
+		set name [ lindex $pair 2 ]
+		set widg [ lindex $pair 3 ]
+		pack $widg -side top -expand false -fill x -padx 1
+	    }
+	} else {
+	    set row 0
+	    set col 0
+
+	    for { set j 0 } { $j < [ llength $wlist ] } { incr j } {
+		set pair [ lindex $wlist $j ]
+		set name [ lindex $pair 2 ]
+		set widg [ lindex $pair 3 ]
+		grid $widg -row $row -column [ expr 2*$col ] -sticky new
+		incr col
+		if { $col == 2 } {
+		    set col 0
+		    incr row
+		}
+	    }
+
+	    set v  [ file rootname  [ $OptionsArray(otype) GetBaseWidget ] ]
+	    grid rowconfigure $v 10 -weight 100
+	}
+    }
+    update idletasks
+
+
+}
+# -----------------------------------------------------------------------------------------
+itcl::body bis_createoverlayimage::UpdateInputsFromContainer { } {
+
+    bis_dualimagetransformationalgorithm::UpdateInputsFromContainer 
+
+    set img1  [ $this GetSecondInput ] 
+    set img2 [  $this GetInput ]
+    
+    set sp1 [ [  $img1 GetImage ] GetSpacing ] 
+    set sp2 [ [  $img2  GetImage ]  GetSpacing ]
+    
+    set vox1 [ expr [ lindex $sp1 0 ] *  [ lindex $sp1 1 ] *  [ lindex $sp1 2 ]  ]
+    set vox2 [ expr [ lindex $sp2 0 ] *  [ lindex $sp2 1 ] *  [ lindex $sp2 2 ]  ]
+    set scale [ expr $vox1 / $vox2 ]
+    set w [ $OptionsArray(origvoxels) GetBaseWidget ] 
+    if { [ expr abs($scale -1.0) < 0.0001 ] } {
+	$OptionsArray(origvoxels) SetValue 0
+	if { [ winfo exists $w ] } {
+	    ::bis_algorithm::DisableUI [ $OptionsArray(origvoxels) GetBaseWidget ]
+	}
+    } else {
+	if { [ winfo exists $w ] } {
+	    ::bis_algorithm::EnableUI [ $OptionsArray(origvoxels) GetBaseWidget ]
+	}
+    }
+    
+
+    if { $noguiupdates == 0 } {
+	return [ $this UpdateInputRanges  ]
+    }
+}
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_createoverlayimage::UpdateInputRanges { args } {
+
+
+    # This happens when image has changed 
+    set currentimage  [ $this GetSecondInput ] 
+    set internal 0
+    if { [ llength $args ] > 0 } {
+	set internal 1
+	if { $noguiupdates == 1 } {
+#	    puts stdout "Currently Executing"
+	    return
+	}
+    }
+
+    set noguiupdates 1
+#    puts stderr "Update Input Ranges ($args) ................"
+    set clustersize [ $OptionsArray(clustersize) GetValue ]
+    if { $clustersize > 0 } {
+	 $OptionsArray(singframe) SetValue 1
+    }
+
+    set fr 0
+    if { [ $OptionsArray(singframe) GetValue ] > 0 } {
+	set fr [ expr [ $OptionsArray(frame) GetValue ] -1 ]
+	set maxfr [ [ $currentimage GetImage ] GetNumberOfScalarComponents ]
+	if { $fr >= $maxfr } {
+	    set fr [ expr $maxfr -1 ]
+	}
+    }
+
+    set r [ [ [ [ $currentimage GetImage ] GetPointData ] GetScalars ] GetRange $fr ]
+    set rmin [ lindex $r 0 ]
+    set rmax [ lindex $r 1 ]
+
+    set rmin  [ expr  abs ($rmin) ]
+    set rmax  [ expr  abs ($rmax) ] 
+    
+    if { $rmax<$rmin } {
+	set rmax $rmin
+    }
+
+    if { $rmax == 0 } {
+	set rmax 1
+    }
+
+    set n [ [ $currentimage GetImage ] GetNumberOfScalarComponents ]
+
+    $OptionsArray(minth) SetValueRange [ list 0 $rmax ]
+    $OptionsArray(maxth) SetValueRange [ list 0 $rmax ]
+    $OptionsArray(frame) SetValueRange [ list 1 $n ]
+
+#    puts stdout "internal=$internal rmax=$rmax ([$currentimage cget -filename]) oldrmax=$lastrmax "
+
+    if { $internal == 0 } {
+	if { $rmax != $lastrmax } {
+	    if { $rmax > 2000 } {
+		$OptionsArray(minth) SetValue 2000
+		$OptionsArray(maxth) SetValue $rmax
+	    } elseif { $rmax > 1000 } {
+		$OptionsArray(minth) SetValue 1000
+		$OptionsArray(maxth) SetValue $rmax
+	    } else {
+		$OptionsArray(minth) SetValue [ expr $rmax/2.0 ]
+		$OptionsArray(maxth) SetValue $rmax
+	    } 	
+	    set lastrmax $rmax
+	}
+	$OptionsArray(frame) SetValueIfCurrentIsTheDefault 1
+    }
+
+    set noguiupdates 0
+#    puts stdout "Done with Update Input Ranges\n"
+}
+
+itcl::body bis_createoverlayimage::ConfigureOptionsGUICallbacks { } {
+
+    eval "$OptionsArray(guisbar) SetGUICallbackFunction { $this ShowScalarBar }"
+    eval "$OptionsArray(singframe) SetGUICallbackFunction { $this UpdateInputRanges }"
+    eval "$OptionsArray(frame) SetGUICallbackFunction { $this UpdateInputRanges }"
+}
+
+itcl::body bis_createoverlayimage::ShowScalarBar {  args } {
+
+    set vv [ $this GetViewer ]
+    if  { $vv == 0 } {
+	return 0
+    }
+
+    if { [ $OptionsArray(guisbar) GetValue ] == 0 } {
+	if { [ $vv GetShowKeyRenderer ] == 1 } {
+	    $vv ToggleKeyRenderer
+	}
+	return 
+    }
+
+
+    set md 0;
+    switch -exact -- [ $OptionsArray(colormap) GetValue ]  {
+	"F1"  {  $vv SetPresetLookupTable 1 ; set md 0} 
+	"F2"  {  $vv SetPresetLookupTable 2 ; set md 1} 
+	"F4"  {  $vv SetPresetLookupTable 6 ; set md 5} 
+    }
+
+    set scalarbar [ $vv GetScalarBar ]
+    set positive 1
+    if { [  $OptionsArray(otype) GetValue ] == "Negative"  } { set positive 0 }
+    set pcmap [ vtkLookupTable [ pxvtable::vnewobj ]] 
+    set cutil [ vtkpxColorMapUtil [ pxvtable::vnewobj ]] 
+    $cutil SetScalarBarColormap $pcmap $md [ $OptionsArray(minth) GetValue ] [ $OptionsArray(maxth) GetValue ] $positive
+    
+    $scalarbar SetTitle ""
+    $scalarbar SetLookupTable $pcmap
+    $pcmap Delete ; $cutil Delete
+    
+    [$scalarbar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport
+    [$scalarbar GetPositionCoordinate] SetValue 0.1 0.1
+    $scalarbar SetOrientationToHorizontal
+    $scalarbar SetWidth 0.8
+    $scalarbar SetHeight 0.9
+    $scalarbar VisibilityOn
+    if { [ $vv GetShowKeyRenderer ] == 0 } {
+	$vv ToggleKeyRenderer
+    }
+
+}
+
+itcl::body bis_createoverlayimage::UpdateContainerWithOutput { } {
+
+    set r [ bis_dualimagetransformationalgorithm::UpdateContainerWithOutput  ]	
+    set vv [ $this GetViewer ]
+    if  { $vv == 0 } {
+	return $r
+    }
+
+    if { [ $OptionsArray(guireslice) GetValue ] == 0 } {
+	switch -exact -- [ $OptionsArray(colormap) GetValue ]  {
+	    "F1"  {  $vv SetPresetLookupTable 1 } 
+	    "F2"  {  $vv SetPresetLookupTable 2 } 
+	    "F4"  {  $vv SetPresetLookupTable 6 } 
+	}
+
+	set outimage2 [ $this GetOutputObject resliced_tmap ]
+	$vv SetEnableRendering 0
+	$vv SetValueImage [ $outimage2 GetImage ]
+	$vv SetEnableRendering 1
+    }
+}
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_createoverlayimage::Execute {  } {
+
+    set noguiupdates 1
+    set lst [ $this ResliceImageIfNeeded ]
+    set resliced_tmap [ lindex $lst 0 ]
+    set tmap [  $this GetSecondInput ]  
+
+    if { [ $OptionsArray(guireslice) GetValue ] == 1 } {
+	set outimage [ $this GetOutput ]
+	$outimage ShallowCopyImage $resliced_tmap
+	$outimage CopyImageHeader  [ $tmap GetImageHeader ]
+	$this DeleteResliceAlgorithmIfNeeded $lst 
+	set noguiupdates 0
+	return 1
+    }
+
+
+    set currentimage  [ $InputsArray(input_image) GetObject ]
+    set clustersize [ $OptionsArray(clustersize) GetValue ]
+    set clusterscale [ $OptionsArray(origvoxels) GetValue ]
+
+
+    set fmriOverlayCreator [ vtkpxMergeFmriConventional New ]
+    $fmriOverlayCreator SetConventional [ $currentimage GetImage ]
+    
+    if { $clustersize > 0 } {
+
+	set clustthr $clustersize
+
+	if { $clusterscale  == 1 } {
+
+	    set sp1 [ [ $tmap GetImage ] GetSpacing ] 
+	    set sp2 [  $resliced_tmap  GetSpacing ]
+	    
+	    set vox1 [ expr [ lindex $sp1 0 ] *  [ lindex $sp1 1 ] *  [ lindex $sp1 2 ]  ]
+	    set vox2 [ expr [ lindex $sp2 0 ] *  [ lindex $sp2 1 ] *  [ lindex $sp2 2 ]  ]
+	    set scale [ expr $vox1 / $vox2 ]
+	    if { [ expr abs($scale -1.0) < 0.0001 ] } {
+		$OptionsArray(origvoxels) SetValue 0
+		::bis_algorithm::DisableUI [ $OptionsArray(origvoxels) GetBaseWidget ]
+	    } else {
+		set clustthr [ expr round($scale*$clustthr) ]
+		::bis_algorithm::EnableUI [ $OptionsArray(origvoxels) GetBaseWidget ]
+	    }
+	} 
+
+	set img [ pxitclimage \#auto ]
+	$img ShallowCopyImage $resliced_tmap
+
+	set clust_alg [bis_clusterthresholdimage [pxvtable::vnewobj]]
+	$clust_alg InitializeFromContainer 0
+	$clust_alg SetInput [ $img GetThisPointer ]
+	$clust_alg SetOptionValue frame [ $OptionsArray(frame) GetValue ]
+	$OptionsArray(singframe) SetValue  1
+	$clust_alg SetOptionValue minth [ $OptionsArray(minth) GetValue ]
+	set r [ $OptionsArray(minth) GetValueRange ]
+	$clust_alg SetOptionValue maxth [ lindex $r 1 ]
+
+	pxtkprint "Using Cluster Size = $clustthr [ $OptionsArray(minth) GetValue ], [ lindex $r 1 ]\n"
+	puts stderr "Using Cluster Size = $clustthr, \n"
+	$clust_alg SetOptionValue clustersize $clustthr
+	$clust_alg SetOptionValue outputclustno 0
+	$clust_alg SetOptionValue binary    Off
+	$clust_alg SetOptionValue oneconnected  [ $OptionsArray(oneconnected) GetValue ]
+	$clust_alg SetOptionValue absolutevalue 1
+	$clust_alg SetOptionValue inverse   Off
+	$clust_alg Execute
+
+	$OptionsArray(singframe) SetValue 1
+
+	itcl::delete obj $img
+
+	$fmriOverlayCreator SetFmriInput [ [ $clust_alg GetOutput ] GetImage ]
+
+    } else {
+	$fmriOverlayCreator SetFmriInput     $resliced_tmap 
+    }
+
+    $fmriOverlayCreator SetSingleFrameMode [ expr [ $OptionsArray(singframe) GetValue ] > 0 ]
+    $fmriOverlayCreator SetCurrentFrame    [ expr int([ $OptionsArray(frame) GetValue ])  -1 ]
+    $fmriOverlayCreator SetIntensityThreshold [expr round([$OptionsArray(inth) GetValue ])  ]
+    $fmriOverlayCreator SetMinimumThreshold   [ $OptionsArray(minth) GetValue ]
+    $fmriOverlayCreator SetMaximumThreshold   [ $OptionsArray(maxth) GetValue ]
+    switch -exact -- [ $OptionsArray(colormap) GetValue ]  {
+	"F1"  {  $fmriOverlayCreator SetOutputMode 0 }
+	"F2"  {  $fmriOverlayCreator SetOutputMode 1 }
+	"F4"  {  $fmriOverlayCreator SetOutputMode 2 }
+    }
+	    
+    $fmriOverlayCreator SetNormalizeAnatomical [ expr [ $OptionsArray(normanat) GetValue ] > 0 ] 
+    
+    switch -exact -- [ $OptionsArray(otype) GetValue ] { 
+	"Positive" { $fmriOverlayCreator SetThresholdMode 1}
+	"Both"     { $fmriOverlayCreator SetThresholdMode 3}
+	"Negative" { $fmriOverlayCreator SetThresholdMode 2}
+    }
+    $this SetFilterCallbacks $fmriOverlayCreator "Creating Overlays"
+    $fmriOverlayCreator Update
+
+
+    pxtkprint "\n\nPositive Laterality = [ $fmriOverlayCreator GetPositiveLaterality ]\nNegative Laterality = [ $fmriOverlayCreator GetNegativeLaterality ]\n"
+
+    set r [ lindex [ [ [  [ $fmriOverlayCreator GetOutput ]  GetPointData ] GetScalars ] GetRange ] 1 ]
+
+    $OptionsArray(guilateral) SetValue [ format "P = %.2f, N=%.2f, ($r)" [ $fmriOverlayCreator GetPositiveLaterality ] [ $fmriOverlayCreator GetNegativeLaterality ]]
+
+    set outimage [ $this GetOutput ]
+
+
+
+    $outimage ShallowCopyImage [ $fmriOverlayCreator GetOutput ] 
+    $outimage CopyImageHeader  [ $tmap GetImageHeader ]
+    
+    set outimage2 [ $this GetOutputObject resliced_tmap ]
+    $outimage2 ShallowCopyImage $resliced_tmap
+    $outimage2 CopyImageHeader  [ $tmap GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+    [ $outimage2 GetImageHeader ] AddComment "$comment $Log" 0
+    
+    $fmriOverlayCreator Delete
+    
+    $this DeleteResliceAlgorithmIfNeeded $lst 
+    set noguiupdates 0
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_createoverlayimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+    set alg [bis_createoverlayimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_cropimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_cropimage.tcl
new file mode 100755
index 0000000..402c30e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_cropimage.tcl
@@ -0,0 +1,402 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+
+package provide bis_cropimage 1.0
+
+#
+# smooth image
+#
+
+itcl::class bis_cropimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Crop Image" }
+
+    # Override these methods
+    protected method PackOptionsGUIInterface { lst }
+    public method UpdateInputsFromContainer { }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_cropimage::Initialize { } {
+
+    PrintDebug "bis_cropimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ startx   "Start Value of Crop Region in X" "Start X"  { integer default   } 0 { -100 1999 }  0 }
+	{ stopx    "End  Value of Crop Region in X" "Stop X"    { integer default   } -1 { -100 1999 }  1 }
+	{ ratex    "X Increment for Cropping" "Rate X"          { integer default 1 } 1 { 1    50 }  2 }
+	{ starty   "Start Value of Crop Region in Y" "Start Y"  { integer default   } 0 { -100 1999 }  3 }
+	{ stopy    "End  Value of Crop Region in Y" "Stop Y"    { integer default   } -1 { -100 1999 }  4 }
+	{ ratey    "Y Increment for Cropping" "Rate Y"          { integer default 1 } 1 { 1    50 }  5 }
+	{ startz   "Start Value of Crop Region in Z" "Start Z"  { integer default   } 0 { -100 1999 }  6 }
+	{ stopz    "End  Value of Crop Region in Z" "Stop Z"    { integer default   } -1 { -100 1999 }  7 }
+	{ ratez    "Z Increment for Cropping" "Rate Z"          { integer default 1 } 1 { 1    50 }  8 }
+	{ startt   "Start Value of Crop Region in T" "Start T"  { integer default   } 1 { 1   999 }  9 }
+	{ stopt    "End  Value of Crop Region in T" "Stop T"    { integer default   } 999 { 1   999 } 10 }
+	{ ratet    "T Increment for Cropping" "Rate T"          { integer default 1 } 1 { 1    50 } 11 }
+
+	{ blank    "If set to on perform blank instead of crop" "Blank" { listofvalues radiobuttons }  off { on off }   12 }
+	{ autocrop "If set to on perform autocrop instead of crop" "AutoCrop" { listofvalues radiobuttons }  off { on off }   13 }
+	{ autocroppad  "Padding Value Used for AutoCropping factor of the gaussian in voxel units " "Autocrop Boundary Size" integer  2   { 0 10 }  -1 }
+    }
+
+    set defaultsuffix { "_crop" }
+    
+    set scriptname bis_cropimage
+    set completionstatus "Done"
+    #
+    #document
+    
+    set description "Crops an image with a specific cropping window/radius."
+    set description2 "Optionally can be used to blank image or autocrop."
+    set backwardcompatibility "Reimplemented from GUI code in pxitclimageutility.tcl.  "
+    set authors "xenophon.papademetris at yale.edu."
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+itcl::body bis_cropimage::UpdateInputsFromContainer { } {
+
+    bis_imagetoimagealgorithm::UpdateInputsFromContainer 
+
+    # This happens when image has changed 
+    set currentimage  [ $InputsArray(input_image) GetObject ]
+
+
+    scan [ [ $currentimage GetImage ] GetDimensions ] "%d %d %d" dim(0) dim(1) dim(2)
+    for { set i 0 } { $i <=2 } { incr i } { 
+	set dim($i) [ expr $dim($i) -1 ] 
+	set min($i) -100
+	set max($i) [ expr $dim($i) + 100 ]
+    }
+
+    set nc [ [ $currentimage GetImage ] GetNumberOfScalarComponents ]
+
+
+    $OptionsArray(startx) SetValueRange [ list $min(0) $dim(0)  ]
+    $OptionsArray(stopx)  SetValueRange [ list 0 $max(0) ]
+    $OptionsArray(starty) SetValueRange [ list $min(1) $dim(1) ]
+    $OptionsArray(stopy)  SetValueRange [ list 0 $max(1) ]
+    $OptionsArray(startz) SetValueRange [ list $min(2)  $dim(2) ]
+    $OptionsArray(stopz)  SetValueRange [ list  0 $max(2) ]
+    $OptionsArray(startt) SetValueRange [ list 1 $nc ]
+    $OptionsArray(stopt)  SetValueRange [ list 1 $nc ]
+
+    if { $guimode == "managed" || $guimode =="standalone" } {
+	$OptionsArray(startx) SetValue 0
+	$OptionsArray(stopx)  SetValue  $dim(0) 
+	$OptionsArray(starty) SetValue 0
+	$OptionsArray(stopy)  SetValue $dim(1) 
+	$OptionsArray(startz) SetValue 0
+	$OptionsArray(stopz)  SetValue $dim(2) 
+	$OptionsArray(startt) SetValue 1
+	$OptionsArray(stopt)  SetValue $nc
+    } else {
+	$OptionsArray(startx) SetValueIfCurrentIsTheDefault 0
+	$OptionsArray(stopx)  SetValueIfCurrentIsTheDefault  $dim(0) 
+	$OptionsArray(starty) SetValueIfCurrentIsTheDefault 0
+	$OptionsArray(stopy)  SetValueIfCurrentIsTheDefault  $dim(1) 
+	$OptionsArray(startz) SetValueIfCurrentIsTheDefault 0
+	$OptionsArray(stopz)  SetValueIfCurrentIsTheDefault  $dim(2) 
+	$OptionsArray(startt) SetValueIfCurrentIsTheDefault 1
+	$OptionsArray(stopt)  SetValueIfCurrentIsTheDefault $nc
+    }
+}
+
+
+itcl::body bis_cropimage::PackOptionsGUIInterface { lst } { 
+
+
+    set n [ llength $lst ]
+    PrintDebug "\n\n Length of list = $n"
+
+    for { set tab 0 } { $tab <= 1 } { incr tab } {
+	set wlist ""
+	for { set i 0 } { $i < $n } { incr i } {
+	    
+		set pair [ lindex $lst $i ]
+		set ind  [ lindex $pair 1 ]
+		if { $ind == $tab } {
+		    lappend wlist $pair
+		}
+	    }
+
+	set wlist [ lsort -integer  -index 0 $wlist ]
+
+
+	if { $tab == 1 } {
+	    for { set j 0 } { $j < [ llength $wlist ] } { incr j } {
+		set pair [ lindex $wlist $j ]
+		set name [ lindex $pair 2 ]
+		set widg [ lindex $pair 3 ]
+		pack $widg -side top -expand false -fill x -padx 1
+	    }
+	} else {
+	    # Custom Pack
+	    grid  [ $OptionsArray(startx) GetBaseWidget ] -row 0 -column 0 -padx 0 
+	    grid  [ $OptionsArray(stopx) GetBaseWidget ]  -row 0 -column 1 -padx 0 
+	    grid  [ $OptionsArray(ratex) GetBaseWidget ]  -row 0 -column 2 -padx 0 
+
+	    grid  [ $OptionsArray(starty) GetBaseWidget ]  -row 1 -column 0 -padx 0 
+	    grid  [ $OptionsArray(stopy) GetBaseWidget ]   -row 1 -column 1 -padx 0
+	    grid  [ $OptionsArray(ratey) GetBaseWidget ]   -row 1 -column 2 -padx 0 
+
+	    grid  [ $OptionsArray(startz) GetBaseWidget ]  -row 2 -column 0 -padx 0 
+	    grid  [ $OptionsArray(stopz) GetBaseWidget ]   -row 2 -column 1 -padx 0
+	    grid  [ $OptionsArray(ratez) GetBaseWidget ]   -row 2 -column 2 -padx 0 
+
+	    grid  [ $OptionsArray(startt) GetBaseWidget ]   -row 3 -column 0 -padx 0 
+	    grid  [ $OptionsArray(stopt) GetBaseWidget ]    -row 3 -column 1 -padx 0
+	    grid  [ $OptionsArray(ratet) GetBaseWidget ]    -row 3 -column 2 -padx 0 
+
+	    grid  [ $OptionsArray(blank) GetBaseWidget ]     -row 4 -column 0 
+	    grid  [ $OptionsArray(autocrop) GetBaseWidget ]  -row 4 -column 1 -columnspan 2 
+
+	    set v [ file rootname [  $OptionsArray(startx) GetBaseWidget ] ]
+
+	    grid rowconfigure $v 5 -weight 100
+	    #	    grid columnconfigure $v 3 -weight 100
+	}
+    }
+    update idletasks
+
+
+}
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+
+
+itcl::body bis_cropimage::Execute {  } {
+
+    #    $this UpdateInputsFromContainer
+
+
+    PrintDebug "bis_cropimage::Execute"
+ #   puts stderr "Starting [ $this GetCommandLine full ]"
+
+
+    set x0   [ $OptionsArray(startx) GetValue ]
+    set x1   [ $OptionsArray(stopx) GetValue ]
+    set dx   [ $OptionsArray(ratex) GetValue ]
+
+    set y0   [ $OptionsArray(starty) GetValue ]
+    set y1   [ $OptionsArray(stopy) GetValue ]
+    set dy   [ $OptionsArray(ratey) GetValue ]
+
+    set z0   [ $OptionsArray(startz) GetValue ]
+    set z1   [ $OptionsArray(stopz) GetValue ]
+    set dz   [ $OptionsArray(ratez) GetValue ]
+
+    set t0   [ $OptionsArray(startt) GetValue ]
+    set t1   [ $OptionsArray(stopt) GetValue ]
+    set dt   [ $OptionsArray(ratet) GetValue ]
+
+    set doblank [ $OptionsArray(blank) GetValue ]
+    set autocrop [ $OptionsArray(autocrop) GetValue ]
+    set autopad  [ $OptionsArray(autocroppad) GetValue ]
+
+    set currentimage  [ $InputsArray(input_image) GetObject ]
+    set currentresults [ $OutputsArray(output_image) GetObject ]
+
+
+
+#    puts stderr "x = $x0:$dx:$x1"
+#    puts stderr "y = $y0:$dy:$y1"
+    #puts stderr "z = $z0:$dz:$z1"
+#    puts stderr "t = $t0:$dt:$t1"
+
+    set ori { 0.0 0.0 0.0 }
+    
+    if { $autocrop == "on" } {
+
+	#puts stderr "Doing Autocrop ... $autopad"
+	set ut [ vtkpxUtil [ pxvtable::vnewobj ]]
+	set tmp [ vtkImageData [ pxvtable::vnewobj ]]
+	$tmp ShallowCopy [  $currentimage GetImage ]
+
+	$ut AutoCropImage $tmp $autopad
+	set ori [ $tmp GetOrigin ]
+	$tmp SetOrigin 0 0 0 
+
+	$currentresults ShallowCopyImage $tmp
+	$ut Delete
+	$tmp Delete
+    } else {
+	set spa [ [ $currentimage GetImage ] GetSpacing ]
+	set ori [ [ $currentimage GetImage ] GetOrigin ]
+	set dim [ [ $currentimage GetImage ] GetDimensions ]
+	set nc [ [ $currentimage GetImage ] GetNumberOfScalarComponents ]
+	
+	# Leave this as negative to enable padding in the other direction also
+	if { $x0 < -256 } { set x0 -256 } 
+	if { $y0 < -256 } { set y0 -256 } 
+	if { $z0 < -256 } { set z0 -256 } 
+	if { $t0 < 1 } { set t0 1 } 
+	
+	#puts "Bottom: $x0 $y0 $z0 $t0" 
+	set max 4096
+	if { $x1 > $max } { set x1 $max } 
+	if { $y1 > $max } { set y1 $max } 
+	if { $z1 > $max } { set z1 $max } 
+	if { $t1 > $max } { set t1 $max } 
+	#puts "Top:    $x1 $y1 $z1 $t1" 
+
+	if { $x1 < $x0 } { set x1 [ expr [ lindex $dim 0 ] -1 ] }
+	if { $y1 < $y0 } { set y1 [ expr [ lindex $dim 1 ] -1 ] }
+	if { $z1 < $z0 } { set z1 [ expr [ lindex $dim 2 ] -1 ] }
+	if { $t1 == 999 } { set t1 $nc }
+	#puts "Top:    $x1 $y1 $z1 $t1" 
+
+	set voi0  [ list   $x0 $y0 $z0 ]
+	set voi1  [ list   $x1 $y1 $z1 ]
+	set voisp [ list   $dx $dy $dz ] 
+
+	#puts "Bottom: $x0 $y0 $z0 $t0" 
+	#puts "Top:    $x1 $y1 $z1 $t1" 
+
+	$OptionsArray(startx) SetValue $x0; 	$OptionsArray(stopx) SetValue $x1;   
+	$OptionsArray(starty) SetValue $y0; 	$OptionsArray(stopy) SetValue $y1;   
+	$OptionsArray(startz) SetValue $z0; 	$OptionsArray(stopz) SetValue $z1;   
+	$OptionsArray(startt) SetValue $t0; 	$OptionsArray(stopt) SetValue $t1;   
+
+
+	set trans  [  vtkIdentityTransform [ pxvtable::vnewobj ] ]	
+	
+	for { set i 0 } { $i <=2 } { incr i } {
+	    set pos0 [ expr round([ lindex $voi0 $i ]) ]
+	    set pos1 [ expr round([ lindex $voi1 $i ]) ]
+	    set dpos [ expr $pos1 - $pos0 + 1 ]
+	    set rat  [ lindex $voisp $i ] 
+	    if { $rat <1 } { set rat 1 } elseif { $rat>50 } {set rat 50 }
+
+	    if { $pos1 < $pos0 } { set pos1 [ expr $pos0 ] }
+	    if { $dpos < 0 } { set dpos 0 } 
+	    
+	    set origin($i)  [ expr [lindex $ori $i ] + $pos0 * [ lindex $spa $i ]]
+	    set spacing($i) [ expr [lindex $spa $i ] * double($rat) ]
+	    set ext($i)     [ expr int(double($dpos)/double($rat)+0.5) ]
+	    
+	    #puts stderr "voisp = ${voisp} , voi0 = ${voi0}, voi1 = ${voi1} "
+	    #puts stderr "Dimension = $i Origin($i) = $origin($i), spa=$spacing($i) ext=$ext($i)  (pos0=$pos0,pos1=$pos1, dpos=$dpos, rat=$rat)"
+	}
+
+
+	set tmp 0
+	if { $dt !=1 || $t0 !=1 || $t1 != $nc } {
+	    set tmp [ vtkImageData [ pxvtable::vnewobj ]]
+	    set ut [ vtkpxUtil [ pxvtable::vnewobj ]]
+#	    puts stdout "Extracting frames from [ expr int($t0 -1) ] to [ expr  int($t1 -1) ] with increment [ expr int($dt) ]"
+	    $ut ExtractFrames $tmp [ $currentimage GetImage ] [ expr int($t0 -1) ] [ expr  int($t1 -1) ] [ expr int($dt) ]
+	    $ut Delete
+	} 
+
+
+	set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+	if { $tmp ==0 } {
+	    $resl SetInput [ $currentimage GetImage ]
+	} else {
+	    $resl SetInput $tmp
+	}
+	$resl SetResliceTransform $trans
+	$resl SetOutputSpacing $spacing(0) $spacing(1) $spacing(2)
+	$resl SetOutputOrigin  $origin(0)  $origin(1)  $origin(2)
+	$resl SetOutputExtent  0 [ expr $ext(0)-1 ] 0 [ expr $ext(1)-1 ] 0 [ expr $ext(2)-1 ]
+	$resl SetInterpolationMode 0 
+	$this SetFilterCallbacks $resl "Cropping Image"
+	$resl Update
+
+
+	
+	if { $doblank == "on" } {
+	    # Pad back to original size
+	    set padresl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+	    $padresl SetInput [ $resl GetOutput ]  
+	    $padresl SetInformationInput [ $currentimage GetImage ]
+	    $padresl SetResliceTransform $trans
+	    $padresl SetInterpolationMode 0
+	    $this SetFilterCallbacks $padresl "Blanking Image"
+	    $padresl Update
+	    set ori [ [ $padresl GetOutput ] GetOrigin ]
+	    $currentresults ShallowCopyImage [ $padresl GetOutput ]
+	} else {
+	    $currentresults ShallowCopyImage [ $resl GetOutput ]
+	}
+	if { $tmp != 0 } {
+	    $tmp Delete
+	}
+	$resl Delete
+    }
+	
+    $currentresults CopyImageHeader [ $currentimage GetImageHeader ]
+    #puts stderr "Crop Image: [ $this GetCommandLine full ]\n [ $currentresults GetDescription ]"
+    [ $currentresults GetImageHeader ] AddComment [ $this GetCommandLine full ] 
+    
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_cropimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_cropimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_csfwmmotioncorr.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_csfwmmotioncorr.tcl
new file mode 100755
index 0000000..2f93331
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_csfwmmotioncorr.tcl
@@ -0,0 +1,181 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_csfwmmotioncorr 1.0
+package require bis_dualimagealgorithm 1.0
+
+
+itcl::class bis_csfwmmotioncorr {
+
+	inherit bis_dualimagealgorithm
+
+	 constructor { } {	 $this Initialize  }
+
+	public method Initialize { }
+	public method Execute { }
+	public method GetGUIName    { } { return "CSF WM Motion Correction" }
+	public method CheckInputObjects { }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_csfwmmotioncorr::Initialize { } {
+
+	PrintDebug "bis_csfwmmotioncorr::Initialize" 
+	
+	#commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+	set options {
+		{ filename "matlab motion file name" "Input Motion File:" { filename default } "" { MAT-File  { .mat } } 1 }
+		{ domotion "Motion Corr Only"  "Correct Motion "  boolean   0  { 0 1  }  40  } 
+		{ docsfwm "Correct CSF and White Matter"  "Correct CSF and WM "  boolean   0  { 0 1  }  45  }
+		{ usemask   "Use Mask Image"  "Use Mask Image"  boolean   0  { 0 1  }  50 }  
+	}
+
+	set defaultsuffix { "_cwmcorr" }
+	set scriptname bis_csfwmmotioncorr
+	set completionstatus "Done"
+
+	#
+	#document
+	#
+	
+	set description "Preprocessing: remove artifects from cerebrospinal fluid, brain white matter and motion correction."
+	set description2 "This takes a time series, a segmentaion map and motion parameters and removes components parallel to csf/white matter timecourses and motion parameters."
+	set backwardcompatibility ""
+	set authors "isabella.murphy at yale.edu, xilin.shen at yale.edu."
+
+	$this InitializeDualImageAlgorithm
+	
+	$this RenameInput 0 "Functional Image"
+	#Mask is optional
+	$this RenameInput 1 "Mask Image" 102
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_csfwmmotioncorr::Execute {  } {
+
+    PrintDebug "bis_csfwmmotioncorr::Execute"
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+
+
+	set filename   [ $OptionsArray(filename) GetValue ]
+	set domotion   [ $OptionsArray(domotion) GetValue ]
+	set docsfwm    [ $OptionsArray(docsfwm) GetValue ]
+	set image_in    [ $this GetInput ]
+	
+	#set matrix [ vtkpxMatrix New ]
+	#set mname "Q_ser"
+	#set A [ $matrix ImportFromMatlab $filename $mname ]
+	
+	
+	
+	set corr [ vtkbisCsfWmMotionCorrection New  ] 
+
+
+	
+	$corr SetFileName $filename
+	#$corr SetMotionMatrix $A
+	$corr SetdoMotion $domotion
+	$corr SetdoCsfWm $docsfwm
+	$corr SetInput [ $image_in GetObject ]
+	set msk [ $OptionsArray(usemask) GetValue ]
+	if { $msk == "1" } {
+	puts stdout "Using Mask ..."
+	$corr SetImageMask [ [ $this GetInputObject second_image ] GetObject ]
+	} 
+	
+	$this SetFilterCallbacks $corr "Pre-preprocessing"
+	$corr Update
+
+	set outimage [ $OutputsArray(output_image) GetObject ]
+	$outimage ShallowCopyImage [ $corr GetOutput ]
+	$outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+	set comment [ format " [ $this GetCommandLine full ]" ]
+	[ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+	$corr Delete
+	#$matrix Delete
+
+	return 1
+}
+itcl::body bis_csfwmmotioncorr::CheckInputObjects { } {
+
+
+	set image_in    [ $this GetInput ]
+	set d [ $image_in GetImageSize ]
+	if { $d < 2 } {
+	return 0
+	}
+	
+	set msk [ $OptionsArray(usemask) GetValue ]
+	if { $msk == "1" } {
+		set image_in    [ $this GetSecondInput ]
+		set d [ $image_in GetImageSize ]
+		if { $d < 2 } {
+		return 0
+		}
+	}
+	
+	return 1
+
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_csfwmmotioncorr.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+	# this is essentially the main function
+
+	set alg [bis_csfwmmotioncorr [pxvtable::vnewobj]]
+	$alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_curvatures.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_curvatures.tcl
new file mode 100755
index 0000000..08657f1
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_curvatures.tcl
@@ -0,0 +1,131 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_surfacetosurfacealgorithm 1.0
+
+package provide bis_curvatures 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_curvatures {
+
+    inherit bis_surfacetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Curvatures" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_curvatures::Initialize { } {
+
+    PrintDebug "bis_curvatures::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ ctype     "gaussian: Gaussian curvature , mean:Mean curvature   " "ctype" listofvalues   gaussian   { mean gaussian }  0 }
+    }
+
+    set defaultsuffix { "_curv" }
+    
+    set scriptname bis_curvatures
+
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "computes curvatures of a surface"
+    set description2 "curvature can be either gaussian curvature or mean curvature"
+    set backwardcompaibitlity "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeSurfacetoSurfaceAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_curvatures::Execute {  } {
+
+    PrintDebug "bis_curvatures::Execute"
+
+    # Get Inputs
+    set surface    [ $this GetInput  ]
+    # GetOptions
+    set ctype      [ $OptionsArray(ctype) GetValue ]
+
+    # Run Algorithm
+    set filter [ vtkCurvatures [ pxvtable::vnewobj ] ]
+    $filter SetInput [ $surface GetObject ]
+    if { $ctype == "gaussian" } {
+	$filter SetCurvatureTypeToGaussian
+    } else {
+	$filter SetCurvatureTypeToMean
+    }
+    $filter Update
+
+    # Store Results in output
+    set surface_out [$filter GetOutput ]
+    [ $OutputsArray(output_surface) GetObject ] DeepCopySurface $surface_out 
+
+    # Clean up
+    $filter Delete
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_curvatures.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_curvatures [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_cylindricalcropimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_cylindricalcropimage.tcl
new file mode 100755
index 0000000..887abe7
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_cylindricalcropimage.tcl
@@ -0,0 +1,154 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+
+package provide bis_cylindricalcropimage 1.0
+
+#
+# smooth image
+#
+
+itcl::class bis_cylindricalcropimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "C-Blank Image" }
+
+    # Override these methods
+    public method UpdateInputsFromContainer { }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_cylindricalcropimage::Initialize { } {
+
+    PrintDebug "bis_cylindricalcropimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ centerx   "Cylinder Center X-coordinate (voxels)" "Center X"  { integer default }    0 { 0 1000 }  0 }
+	{ centery   "Cylinder Center Y-coordinate (voxels)" "Center Y"  { integer default }    0 { 0 1000 }  0 }
+	{ radius    "Cylinder Radius (voxels)" "Radius"  { integer default }    20 { 0 1000 }  0 }
+    }
+
+    set defaultsuffix { "_ccrop" }
+    
+    set scriptname bis_cylindricalcropimage
+    set completionstatus "Done"
+    #
+    #document
+    
+    set description "Blanks an image with a specific cylinder."
+    set description2 "Values inside the cylinder are preserved, outside are set to 0"
+    set backwardcompatibility "Reimplemented from GUI code in pxitclimageutility.tcl.  "
+    set authors "xenophon.papademetris at yale.edu."
+
+    $this InitializeImageToImageAlgorithm
+}
+
+itcl::body bis_cylindricalcropimage::UpdateInputsFromContainer { } {
+
+    bis_imagetoimagealgorithm::UpdateInputsFromContainer 
+
+    # This happens when image has changed 
+    set currentimage  [ $InputsArray(input_image) GetObject ]
+
+
+    scan [ [ $currentimage GetImage ] GetDimensions ] "%d %d %d" dim(0) dim(1) dim(2)
+
+    $OptionsArray(centerx) SetValueRange [ list 1  [ expr $dim(0) -2 ] ]
+    $OptionsArray(centerx) SetValue  [ expr int($dim(0) /2) ]
+    $OptionsArray(centery) SetValueRange [ list 1  [ expr $dim(1) -2 ] ]
+    $OptionsArray(centery) SetValue  [ expr int($dim(1) /2) ]
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_cylindricalcropimage::Execute {  } {
+
+    PrintDebug "bis_cylindricalcropimage::Execute"
+
+    set cx   [ $OptionsArray(centerx) GetValue ]
+    set cy   [ $OptionsArray(centery) GetValue ]
+    set r   [ $OptionsArray(radius) GetValue ]
+
+    set currentimage  [ $InputsArray(input_image) GetObject ]
+    set currentresults [ $OutputsArray(output_image) GetObject ]
+
+
+    set crop [ vtkpxImageCylindricalCrop [ pxvtable::vnewobj ] ]
+    $crop SetInput  [ $currentimage GetImage ]
+    $crop SetCenter $cx $cy 0
+    $crop SetRadius $r
+    SetFilterCallbacks $crop "Cylindrical Blanking Image"
+    $crop Update
+
+	
+    $currentresults CopyImageHeader [ $currentimage GetImageHeader ]
+    $currentresults ShallowCopyImage [ $crop GetOutput ] 
+    [ $currentresults GetImageHeader ] AddComment [ $this GetCommandLine full ]  0
+    
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_cylindricalcropimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_cylindricalcropimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_datamanager.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_datamanager.tcl
new file mode 100644
index 0000000..83fa01c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_datamanager.tcl
@@ -0,0 +1,1748 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_datamanager 1.0
+
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    lappend auto_path [ file dirname [ info script ]]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+}
+
+package require Itcl
+package require struct
+package require  pxitclsubjectentry     1.0
+package require pxtcluserprefs 1.0
+# ----------------------------------------------------------
+#
+#  Tree like interface for managing data
+#
+# ----------------------------------------------------------
+
+
+itcl::class bis_datamanager {
+
+    constructor { } { 
+	$this Initialize
+    }
+
+    destructor { $this Cleanup }
+
+    # Initialization and Cleanup
+    # --------------------------
+    protected method Initialize { }
+    protected method Cleanup { }
+    public method GetThisPointer { } { return $this }
+
+    # Utility
+    # ----------------------------------
+    public method GetTypeAttributeForObjectType { obj }
+    public method GetObjectTypeForTypeAttribute { tp }
+
+    # Basic Interface
+    # ---------------
+    public method GetRootNode { } { return $rootnode }
+    public method FindNode { nodename  } 
+    public method FindFirstNodeByAttribute { attname attval } 
+
+    # Import Old Style Data Tree file (.tre) or MSB File (.msb)
+    # ---------------------------------------------------------
+    protected method ConvertTreeElementToXMLElement { xmltree tcltreenode tcltree { depth 0 } } 
+    public method ImportTree { fname }
+    public method ImportMSBFile { fname }
+
+
+    # Tree Maintenance
+    # ----------------
+    public method RecursiveDeleteChildren { elem }
+    protected method RecursiveFixTreeAndAllocatePointers { elem { globalpath "" } }
+    public method CleanXML { }
+    public method UpdateDisplayAttributes { elem } 
+    public method UpdateAttributesByList { elem changedlist  } 
+
+    public method LoadObjectPointers { elem } 
+    public method SaveObjectPointers { elem } 
+    protected method RecursiveAllocateNewPointersAndCopy { elem }
+    protected method CreateUniqueIds { elem }
+
+    # Tree Edit & Paste style
+    # -----------------------
+    public method CopyElement { elem newparent }
+    public method MoveElement { elem newparent }
+    public method DeleteElement { elem  }
+    public method InsertElement { elem newparent }
+
+
+    # Load and Save new style XML file
+    # --------------------------------
+    public method XMLElementToString { elem { n 0 } { savemode 0 } { globalpath "" }  }
+    public method LoadXML  { fname }
+    public method SaveXML  { fname }
+    public method CheckSavedObjects  { { node 0 } { dosave 0 } }
+
+    # Methds to Create Elements and basic utility functions
+    #Next Id to ensure that all nodes have unique ids!
+    # ------------------------------------------------------
+    public method FileNameToRelative { fname globalpath }
+    public method FileNameToAbsolute { fname globalpath }
+    protected method GetNextId { } 
+    protected method CleanString { line } 
+    protected method SetUniqueName { elem { title "" } }
+    protected method AllocatePointersXMLDataElement { elem }
+    public method GetNewXMLDataElement { { ndtype Folder } { title "" } { attlist "" } }
+    public method CreateChildElement { parent { ndtype Folder } { title "" } { attlist "" } }
+
+
+    #Path Issues
+    # -----------
+    public method GetAncestors { elem }
+    public method GetShortestPath { e1 e2 }
+    public method GetTransformationList { first last }
+    public method GetCombinedTransformation { xformlist }
+
+    # variables
+    protected variable rootnode 0
+    private variable nextid   0
+
+    # associative array  mapping Chelly field names to attributes
+    protected variable treemap
+    # list of attributes in rootnode which are global
+    protected common globalattributes ""
+
+    # attributes to be set to zero on import/load/save
+    protected common attributeszero ""
+    # attributes that are pointers and needed to be deleted
+    protected common attributepointers ""
+    # Filenames of all pointers
+    protected common attributepointerfilenames ""
+    # list of all attributes
+    protected common attributeslist ""
+    # boolean attributes
+    protected common attributesboolean ""
+    # guionly attributes
+    protected common attributesgui ""
+
+
+    # Static Interface
+    public method GetAttributesList { } { return $attributeslist }
+    public method GetFilenamesList { } { return $attributepointerfilenames }
+    public method GetAttributesZeroList { } { return $attributeszero }
+    public method GetAttributePointersList { } { return $attributepointers }
+    public method GetAttributeBooleanList { } { return $attributesboolean }
+    public method GetAttributeGUIList { } { return $attributesgui }
+}
+
+# ---------------------------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::Initialize { } {
+    # Transformation stuff
+
+    array unset treemap
+
+    set treemap(FromParFilenameSet) "none"
+    set treemap(TransFromParFileName) "TransformationFilename"
+    set treemap(pxitclTransToParent)  "none"
+    set treemap(ToParFilenameSet)   "none"
+    set treemap(TransToParFileName)  "InverseTransformationFilename"
+    set treemap(pxitclTransFromParent) "none"
+    set treemap(IsIdentity) "IsIdentity"
+
+    set treemap(group) "Group"
+    set treemap(linecolor) "Linecolor"
+    set treemap(icon) "Icon"
+    set treemap(type) "Type"
+    set treemap(expanded) "Expanded"
+    set treemap(notes) "Notes"
+    set treemap(FileName) "Filename"
+    set treemap(FileLoaded) "none"
+    set treemap(title)  "Title"
+    set treemap(pxitclobj) "none"
+
+    if { $globalattributes == "" } {
+	# Initialize Stuff if needed -- these are common
+	set globalattributes { GlobalSubjectProperties GlobalDataTypes GlobalFilename GlobalPath }
+	set attributeszero { PointerTransformation PointerInverseTransformation  ObjectLoaded PointerObject VisTreePath }
+	set attributepointers { PointerObject PointerTransformation PointerInverseTransformation   }
+	set attributepointerfilenames {  Filename TransformationFilename InverseTransformationFilename }
+	set attributesboolean {  IsIdentity ObjectLoaded Expanded }
+	set attributesgui     {  VisTreePath Linecolor DisplayList }
+
+	set attributeslist { 
+	    { Filename "" }
+	    { Title "" }
+	    { Type Image }
+	    { SubType None }
+	    { Group 1 }
+	    { Notes "" } 
+	    { IsIdentity 0 } 
+	    { TransformationFilename "" } 
+	    { InverseTransformationFilename "" }
+	    { Icon ifile }
+	    { VisTreePath  0 }
+	    { Linecolor red } 
+	    { Expanded 0 }
+	    { PointerTransformation 0 } 
+	    { PointerInverseTransformation 0 } 
+	    { ObjectLoaded 0 } 
+	    { PointerObject 0 } 
+	    { DisplayList 0 }
+	}
+    }
+	
+    # -----------------------------------------------
+    $this CleanXML
+
+
+}
+
+
+itcl::body bis_datamanager::Cleanup { } {
+    $this CleanXML
+    $rootnode Delete
+}
+
+# -----------------------------------------------------------------------
+# Creating Elements and utility functions
+# -----------------------------------------------------------------------
+itcl::body bis_datamanager::GetTypeAttributeForObjectType { objtype } {
+ 
+    while { [string first ":" $objtype  ] == 0 } {
+	set objtype [ string range $objtype 1 end ]
+    }
+   
+    switch --  $objtype {
+	"pxitclimage" { return "Image" }
+	"pxitclsurface"  { return "Surface" }
+	"pxitclmesh"  { return "Mesh" }
+	"pxitcllandmarks" { return "Landmarks" }
+	"pxitclelectrodemultigrid" { return "Electrodes" }
+    }
+
+    return 0
+}
+
+itcl::body bis_datamanager::GetObjectTypeForTypeAttribute { tp } {
+
+    switch --  $tp {
+	"Folder" { return 0 } 
+	"Subject" { return 0 }
+	"Subject" { return pxitclsurface  }
+	"Landmarks" { return pxitcllandmarks }
+	"Electrodes" { return  pxitclelectrodemultigrid } 
+	"Mesh" { return  pxitclmesh } 
+	"Image" { return pxitclimage }
+    }
+    return 0
+}
+# -----------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::FileNameToRelative { fname globalpath } {
+
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    if { $fname == "\"0\"" || $fname == "0" || $fname == "" || $fname =="-1" } {
+	return "0"
+    }
+
+
+    set f [ file pathtype $fname ]
+
+    if { $f != "absolute" } {
+	return $fname
+    }
+
+#    puts stderr "Looking at $fname in $globalpath, $f"
+	
+    set ind [ string first $globalpath $fname ]
+    if { $ind >=0 } {
+	set n [ expr [ string length $globalpath ] +1 ]
+	return [ string range $fname $n end ]
+    }
+
+    return $fname
+}
+# -----------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::FileNameToAbsolute { fname globalpath } {
+
+    if { [ string length $fname ] <1 } {
+	return 0
+    }
+
+    if { $fname == "\"0\"" || $fname == "0" || $fname == "" || $fname =="-1" } {
+	return "0"
+    }
+
+    
+    set f [ file pathtype $fname ]
+    if { $f == "absolute" } {
+	return $fname
+    }
+    set f2 [ file join $globalpath $fname ]
+    return $f2
+}
+
+itcl::body bis_datamanager::CleanString { line } {
+    set line [ string trim $line ]
+    regsub -all "\n" $line " " line
+    regsub -all "\t" $line " " line
+    regsub -all ":" $line "_" line
+    regsub -all " +" $line "_" line
+    regsub -all "_-_" $line "-" line
+    return $line
+}
+
+itcl::body bis_datamanager::GetNextId  {  } {
+    incr nextid
+    return $nextid
+}
+
+itcl::body bis_datamanager::SetUniqueName { elem { title "" } } {
+
+    set ttl [ $this CleanString [ $elem GetAttribute Title ] ]
+    if { $ttl =="" } {
+	set ttl "Node:[ $elem GetAttribute UniqueId]"
+    }
+    set nd [ $this FindNode $ttl ]
+    if { $nd == 0 ||  $nd == $elem  } {
+	$elem SetName $ttl
+    } else {
+	$elem SetName "$ttl:[ $elem GetAttribute UniqueId]"
+    }
+}
+
+# --------------------------------------------------------
+itcl::body bis_datamanager::AllocatePointersXMLDataElement {  element } {
+
+    set ndtype [ $element GetAttribute Type ]
+    
+    set orig $ndtype
+    set subtype "None"
+
+    switch --  $ndtype {
+	"Folder" {
+	    set lst { { Type "Folder" }	{ Icon "idir" }	{ Linecolor "green" } { IsIdentity "1" } }
+	}
+	"Subject" {
+	    set lst { {  Type "Subject" } { Icon ipersonicon }	{ Linecolor green } { IsIdentity 1 }}
+	}
+	"Surface" {
+	    set lst -1 
+	    $element SetAttribute  Type "Surface"
+	    $element SetAttribute "PointerObject" [ [ pxitclsurface \#auto ] GetThisPointer ]
+	}
+	"Mesh" {
+	    set lst -1 
+	    $element SetAttribute  Type "Mesh"
+	    $element SetAttribute "PointerObject" [ [ pxitclmesh \#auto ] GetThisPointer ]
+	}
+	"Landmarks" {
+	    set lst  -1
+	    $element SetAttribute Type "Landmarks"
+	    $element SetAttribute "PointerObject" [ [ pxitcllandmarks \#auto ] GetThisPointer ]
+	}
+	"Electrodes" {
+	    set lst -1 
+	    $element SetAttribute  Type  Electrodes
+	    $element SetAttribute "PointerObject" [ [ pxitclelectrodemultigrid \#auto ] GetThisPointer ]
+	}
+	default {
+	    $element SetAttribute Type Image
+	    $element SetAttribute SubType $subtype
+	    $element SetAttribute "PointerObject" [ [ pxitclimage \#auto ] GetThisPointer ]
+	    $element SetAttribute "PointerTransformation" [ [ pxitcltransform \#auto ] GetThisPointer ]
+	    $element SetAttribute "PointerInverseTransformation" [ [ pxitcltransform \#auto ] GetThisPointer ]
+	    set lst {  { Icon ibraingrey } { Linecolor red }  }
+	}
+    }
+    
+    if { $lst == -1 } {
+	set lst {  { Icon ibraingrey } { Linecolor green } { IsIdentity 1 } { TransformationFilename "" } { InverseTransformationFilename "" } } 
+    }
+
+    foreach pair $lst {
+	set attr [ lindex $pair 0 ]
+	set val  [ lindex $pair 1 ]
+	$element SetAttribute $attr $val
+    }
+
+    # Set name #1 -- this should be the place 
+
+    return 1
+}
+# ----------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::GetNewXMLDataElement { { ndtype Folder } { title "" } { attlist "" } } {
+
+    set element [ vtkXMLDataElement New ]
+
+    # 1. Set Defaults first
+    set num [ llength attributeslist ]
+    foreach pair $attributeslist {
+	set attr [ lindex $pair 0 ]
+	set val  [ lindex $pair 1 ]
+	$element SetAttribute $attr $val
+    }
+    
+    # 2. Set ID
+    $element SetAttribute UniqueId  [ $this GetNextId ]
+
+    # 3. Set Type and allocate pointers
+    $element SetAttribute Type $ndtype
+    $this AllocatePointersXMLDataElement $element
+
+    # 4. Set Title if specified as option
+    if { $title != "" } {
+	$element SetAttribute Title $title
+    }
+
+    # 5. Set Attributes as specified in attlist
+    set n [ expr [ llength $attlist ] -1 ]
+    if { $n > 0 } {
+	for { set i 0 } { $i < $n } { set i [ expr $i+2 ] } {
+	    set ip [ expr $i + 1 ]
+	    set attname [ lindex $attlist $i ]
+	    set attvalue [ lindex $attlist $ip ]
+	    $element SetAttribute $attname $attvalue
+	}
+    }
+
+    # 6. Give this a unique name
+    $this SetUniqueName $element
+
+    # 7. Done
+    return $element
+}
+# ----------------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::CreateChildElement { parent { ndtype Folder } { title "" } { attlist "" } } {
+
+    if { $parent == 0 || $parent == "" } {
+	return 0
+    }
+    set elem [ $this GetNewXMLDataElement $ndtype $title $attlist ]
+    if { $elem !=0  } {
+	$parent AddNestedElement $elem
+    }
+    return $elem
+}
+
+
+# ----------------------------------------------------------------------------------------------------------
+#
+#   Traversing tree ancestors/lists etc
+#
+# ----------------------------------------------------------------------------------------------------------
+
+itcl::body bis_datamanager::GetAncestors { elem }  {
+
+    if { $elem == "" } {
+	#	puts stderr "Empty!"
+	return ""
+    }
+
+    if { $elem == $rootnode } {
+	return "[ $rootnode GetName ]"
+    }
+
+    set done 0
+    set ancestors [ $elem GetName ]
+    while { $done == 0 } {
+	set e [ $elem GetParent ]
+	lappend ancestors [ $e GetName ] 
+	set elem $e
+	if { $e == $rootnode } {
+	     set done 1
+	} 
+    }
+    return $ancestors
+}
+
+# -----------------------------------------------------------------------------
+
+itcl::body bis_datamanager::GetShortestPath { e1 e2 } {
+
+    # e1 = ref
+    # e2 = trg
+
+    set trglist [ $this GetAncestors $e2 ]
+    set reflist [ $this GetAncestors $e1 ]
+
+    if { $e1 == $e2 } {
+	return [ list 1 1 ]
+    }
+    
+    set lst1 ""
+    set i 0
+    set found  0
+    set f1 ""
+    set f2 ""
+
+    while { $i < [ llength $trglist ] && $found == 0 } {
+
+	set ind [ lsearch -exact $reflist [ lindex $trglist $i ] ]
+	#	puts stderr "Looking for [ lindex $trglist $i ] in *** $reflist *** \t\t index = $ind"
+	if { $ind >=0 } {
+	    set found 1
+	    set f1 [ lrange $trglist 0 $i ]
+	    set f2 [ lrange $reflist 0 $ind ]
+	}
+	incr i
+    }
+    
+    if { $found == 0 } {
+	return [ list 0 0 ]
+    }
+    
+    set f3 ""
+    for { set i 0 } { $i < [ llength $f1 ] } { incr i } {
+	set ind [ expr ([ llength $f1 ]-1) - $i ]
+	lappend f3 [ lindex $f1 $ind ]
+    }
+    return [ list $f2 $f3 ]
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body bis_datamanager::GetTransformationList { first last } {
+
+#    puts stderr "first=$first, last=$last"
+
+    set p [ $this GetShortestPath $first $last ]
+
+    set t(1) [ lindex $p 0 ]
+    set t(2) [ lindex $p 1 ]
+    set m(1) "Inverse"
+    set m(2) "Forward"
+
+    set tlist ""
+    set tnamelist ""
+    for { set pass 1 } { $pass <= 2 } { incr pass } {
+	for { set i 0 } { $i < [ expr [ llength $t($pass)]  -1 ] } { incr i } {
+	    
+	    set e1 [ lindex $t($pass) $i ]
+	    set e2 [ lindex $t($pass) [ expr $i +1 ]]
+#	    puts stderr "\n\n ************************ $m($pass) $e1 --> $e2"
+
+
+	    if { $pass == 2 } {
+		set mode "transformation"
+		set currentelement [ $this FindNode $e2 ]
+	    } else {
+		set mode "inverse transformation"
+		set currentelement [ $this FindNode $e1 ]
+	    }
+	    
+	    if { $currentelement ==0 } {
+		return "Failed :: missing node in pair ($e1,$e2)"
+	    }
+
+	    if { [ $currentelement GetAttribute IsIdentity ] != 1 } {
+#		puts stderr "Needs to load $currentelement [ $currentelement GetName ], $mode"
+		if {  [ $currentelement GetAttribute ObjectLoaded ] != 1 } {
+		    set ok [ $this LoadObjectPointers $currentelement  ]
+		    if { [ lindex $ok 0 ] == 0 } {
+			return "Failed :: $ok"
+		    }
+		}
+		    
+		if { $pass == 2 } {
+		    set fname  [ $currentelement GetAttribute TransformationFilename ]
+		    if {  $fname == 0 || $fname == "-1" || $fname == ""  } {
+			return "Failed :: missing transformation in [ $currentelement GetName ]"
+		    }
+		    set tr [ $currentelement GetAttribute PointerTransformation ]
+		} else {
+		    set fname  [ $currentelement GetAttribute InverseTransformationFilename ]
+		    if {  $fname == 0 || $fname == "-1" || $fname == ""  } {
+			return "Failed :: missing inverse transformation in [ $currentelement GetName ]"
+		    }
+		    set tr [ $currentelement GetAttribute PointerInverseTransformation ]
+		}
+		lappend tlist $tr
+		lappend tnamelist [ $tr cget -filename ]
+	    } else {
+#		puts stderr "[$currentelement GetName ] Is Identity ... skipping"
+	    }
+	    
+	}
+    }
+
+    set lst [ list  $first $last ]
+    foreach nodename $lst {
+	if {  [ $nodename GetAttribute ObjectLoaded ] != 1 } {
+	    set ok [ $this LoadObjectPointers $nodename  ]
+	    if { [ lindex $ok 0 ] == 0 } {
+		return "Failed :: loading node [ $nodename GetName ] $ok"
+	    }
+	}
+    }
+#    puts stderr "tnamelist=$tnamelist"
+    return $tlist
+}
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_datamanager::GetCombinedTransformation { xformlist } {
+
+    # step 1 ... are they linear
+
+    if { [ llength $xformlist ] == 0  } {
+	return [ vtkIdentityTransform New ]
+    }
+
+    set alllinear 1
+
+    foreach tr $xformlist { 
+	if { [ $tr IsLinear ] ==0 } {
+	    set alllinear 0
+	}
+    }
+
+    if { $alllinear == 1 } {
+	set gen [ vtkTransform New ]
+    } else {
+	set gen [ vtkGeneralTransform New ]
+    }
+    $gen Identity
+    $gen PostMultiply
+
+    for { set i 0 } { $i < [ llength $xformlist ]} { incr i } {
+	$gen Concatenate [ [ lindex $xformlist $i ] GetTransformation ]
+    }
+    return $gen
+}
+
+# ----------------------------------------------------------------------------------------------
+#  Find Node
+# ----------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::FindNode {  nodename } {
+
+    if { $rootnode == 0 } {
+	return 0
+    }
+    
+    if { $nodename == [ $rootnode GetName ] } {
+#	puts stderr "Nodename is rootname"
+	return $nodename
+    }
+
+    set elem [ $rootnode LookupElementWithName $nodename ]
+    if { $elem == $rootnode } {
+	puts stderr "Bad Search ... "
+	return 0
+    }
+    if { $elem != ""  && $elem !=0 } {
+	#	puts stderr "Found $nodename, $elem"
+	return $elem
+    }
+
+    return 0
+}
+# --------------------------------------------------------
+itcl::body bis_datamanager::FindFirstNodeByAttribute { attname attval } {
+
+    set currentlist $rootnode 
+    set done 0
+    set error 0
+
+    while { $done == 0 } {
+
+	#	puts  -nonewline stderr "Examining {"
+	#	for { set i 0 } { $i < [ llength $currentlist ] } { incr i } {
+	#	    puts -nonewline stderr " [ [ lindex $currentlist $i ] GetName ]"
+	#	}
+	#	puts stderr "}"
+	
+	for { set i 0 } { $i < [ llength $currentlist ] } { incr i } {
+	    set nd [ lindex $currentlist $i ]
+	    set val [ $nd GetAttribute $attname ]
+	    if { $val == $attval } {
+		return $nd
+	    }
+	}
+
+	set newlist ""
+	set done 1
+	for { set i 0 } { $i < [ llength $currentlist ] } { incr i } {
+	    set elem [ lindex $currentlist $i ]
+	    for { set j 0 } { $j < [ $elem GetNumberOfNestedElements ] } { incr j } {
+		lappend newlist [ $elem GetNestedElement $j ]
+		# At least one element found
+		set done 0 
+	    }
+	}
+	set currentlist $newlist
+    }
+    
+    return 0
+}
+# --------------------------------------------------------
+# Updates from GUI/Updates
+# --------------------------------------------------------
+itcl::body bis_datamanager::UpdateAttributesByList { elem changedlist }  {
+
+#    puts stderr "The following has changed = $changedlist"
+    if {  [ lsearch -exact $changedlist "Title" ] > -1 } {
+	set ttl [ $this CleanString [ $elem GetAttribute Title ] ]
+	regsub -all "\"" $ttl "" ttl
+	$elem SetAttribute Title $ttl
+	puts -nonewline stderr "Changing the name of $elem from [ $elem GetName ] to "
+	$this SetUniqueName $elem
+	puts stderr "\t\t [ $elem GetName ]"
+	
+    }
+
+    if {  [ lsearch -exact $changedlist IsIdentity ] > -1 } {
+#	puts stderr "IsIdentity Changed!"
+	if { [ $elem GetAttribute "IsIdentity"  ] == 1 } {
+	    $elem SetAttribute Icon ibraingreen
+	} else {
+	    set fn [  $elem GetAttribute Filename ]
+	    if {  $fn != "" && $fn !=0 } {
+		$elem SetAttribute Icon ibrainpurple
+	    } else {
+		$elem SetAttribute Icon ibraingrey
+	    }
+	}
+    }
+
+    set fn    [ $this  GetFilenamesList ]
+    set ptrs  [ $this GetAttributePointersList ]
+
+    # Filenames done !
+    for { set i 0 } { $i < [ llength $fn ] } { incr i } {
+	set p $elem
+	if {  [ lsearch -exact $changedlist [ lindex $fn $i ] ] > -1 } {
+	    puts stderr "[ lindex $fn $i ] Changed !"
+	    
+	    set obj   [ $p GetAttribute [ lindex $ptrs $i ] ]
+	    set fname [ $p GetAttribute [ lindex $fn $i ] ]
+	    set fold  [ $obj cget -filename ]
+	    if { $fname != $fold } {
+		$obj Clear
+		$obj configure -filename $fname
+		if { $i == 0 } {
+		    $elem SetAttribute ObjectLoaded 0
+		}
+	    }
+	}
+    }
+	  
+}
+
+# -------------------------------------------------------------------------------
+
+
+itcl::body bis_datamanager::UpdateDisplayAttributes { elem }  {
+
+    set ndtype [ $elem GetAttribute Type ]
+    #    puts stderr "Updating display attributes [ $elem GetName ] $ndtype"
+
+    if { $ndtype == "Folder" || $ndtype == "Subject" } {
+	return 0
+    }
+
+    if {  $ndtype == "Image" } {
+	
+	# Step 1 check for transformations!
+	if { [ $elem GetAttribute IsIdentity ] !=1 } {
+	    set t(1) [ $elem GetAttribute  TransformationFilename ]
+	    set t(2) [ $elem GetAttribute  InverseTransformationFilename ]
+	    set ok(1) 1
+	    set ok(2) 1
+
+	    if { [ file extension $t(1) ] == ".matr" } {
+		set t(2) "$t(1).donotsave"
+		$elem SetAttribute  InverseTransformationFilename $t(2)
+	    } else {
+		for { set i 1 } { $i<=2 } { incr i } {
+		    if { $t($i) ==0 || $t($i) == -1 || $t($i) == "" } {
+			set ok($i) 0
+		    } 
+		}
+	    }
+	    
+	    if { $ok(1) == 1 && $ok(2) == 1 } {
+		$elem SetAttribute Linecolor green
+	    } elseif { $ok(1) == 1 && $ok(2) == 0 } {
+		$elem SetAttribute Linecolor goldenrod
+	    } elseif { $ok(1) == 0 && $ok(2) == 1  } {
+		$elem SetAttribute Linecolor purple
+	    } else {
+		$elem SetAttribute Linecolor red
+	    }
+	} else {
+	    $elem SetAttribute  TransformationFilename 0
+	    $elem SetAttribute  InverseTransformationFilename 0
+	    $elem SetAttribute Linecolor green
+	    $elem SetAttribute Icon iarrowbrain
+	}
+	
+	# Step 2 check if loaded
+	set img [ $elem GetAttribute PointerObject ]
+	set d [ $img GetImageSize ]
+	if { $d > 1 } {
+	    $elem SetAttribute ObjectLoaded 1
+	} else {
+	    $elem SetAttribute ObjectLoaded 0
+
+	} 
+
+	set fn [  $elem GetAttribute Filename ]
+	if {  $fn != "" && $fn !=0 } {
+	    $elem SetAttribute Icon ibrainpurple
+	} else {
+	    $elem SetAttribute Icon ibraingrey
+	}
+
+	if { [ $elem GetAttribute "IsIdentity"  ] == 1 } {
+	    $elem SetAttribute Icon ibraingreen
+	}
+
+	return 1
+    }
+
+    if { $ndtype == "Surface" || $ndtype == "Landmarks" || $ndtype == "Electrodes" || $ndtype == "Mesh"} {
+	set obj [ $elem GetAttribute PointerObject ]
+	set d -1
+	if { $ndtype == "Surface" } {
+	    set d [ $obj GetSurfaceSize ]
+	} elseif { $ndtype == "Landmarks" } {
+	    set d [ $obj GetLandmarksSize ]
+	} elseif { $ndtype == "Mesh" } {
+	    set d [ $obj GetMeshSize ]
+	} elseif { $ndtype == "Electrodes" } {
+	    set d [ $obj GetElectrodeMultiGridSize ]
+	}
+	if { $d > 0 } {
+	    $elem SetAttribute FileLoaded 1
+	} elseif { $d !=-1 } {
+	    $elem SetAttribute FileLoaded 0
+	} 
+
+	set fn [  $elem GetAttribute Filename ]
+	if {  $fn != "" && $fn !=0 } {
+	    $elem SetAttribute Icon ibrainyellow
+	} else {
+	    $elem SetAttribute Icon ibraingrey
+	}
+
+    }
+}
+# --------------------------------------------------------
+itcl::body bis_datamanager::LoadObjectPointers { elem } {
+
+    #set attributepointers { PointerObject PointerTransformation PointerInverseTransformation   }
+    #set attributepointerfilenames {  Filename TransformationFilename InverseTransformationFilename }
+
+    set maxno [ llength $attributepointers ]
+    set ndtype [ $elem GetAttribute Type ]
+    if { $ndtype == "Folder" || $ndtype == "Subject" } {
+	return 1
+    } elseif { $ndtype != "Image" } {
+	set maxno 1
+    } 
+
+#    puts stderr "maxno=$maxno"
+    
+    set err ""
+    set i 0
+    while { $i < $maxno && $err == "" } {
+	set fname [ $elem GetAttribute [ lindex $attributepointerfilenames  $i ] ]
+	#	puts stderr "To load $fname"
+	set ext [ file extension $fname ]
+	set doload 1
+	if { $ext == ".donotsave" || $fname == 0 || $fname == "-1" || $fname == "" } {
+	    set doload 0
+	}
+	
+	if { $doload } {
+	    set obj [ $elem GetAttribute [ lindex $attributepointers $i ] ]
+	    if { $i == 0 } {
+		#		puts stderr "To load $fname in $obj"
+		set ok [ $obj Load $fname ]
+		if { $ok == 0 } {
+		    set err "Failed to load [ lindex $attributepointers $i ] from $fname" 
+		    $obj Clear
+		} else {
+		    #		    puts stderr "Ok=$ok loaded $fname in $obj"
+		    $elem SetAttribute ObjectLoaded 1
+		}
+	    } else {
+		if { $obj == 0 } {
+		    set obj [ [  pxitcltransform \#auto ] GetThisPointer ]
+		}
+		set ok [ $obj Load $fname ]
+		if { $ok > 0 } {
+		    $elem SetAttribute [ lindex $attributepointers $i ] $obj
+		} else {
+		    $elem SetAttribute [ lindex $attributepointerfilenames  $i ] ""
+		    set err "Failed to load [ lindex $attributepointers $i ] from $fname" 
+		    $obj Clear
+		}
+	    }
+	}
+	
+	if { $i == 1 && $err == "" } {
+	    set tr1 [ $elem GetAttribute [ lindex $attributepointers 1 ]]
+	    set tr2 [ $elem GetAttribute [ lindex $attributepointers 2 ]]
+	    if { [ $tr1 IsLinear ] > 0 } {
+		if { $tr2 == 0 } {
+		    set tr2 [ [  pxitcltransform \#auto ] GetThisPointer ]
+		}
+		$tr2 Copy $tr1
+		$tr2 Invert
+		$tr2 configure -filename "[ $tr1 cget -filename].donotsave"
+		$elem SetAttribute [ lindex $attributepointers 2 ] $tr2
+		set i 4
+	    }
+	}
+	incr i
+    }
+
+    if { $err == "" } {
+	$this UpdateDisplayAttributes $elem
+	return 1
+    }
+		     
+    return [ list 0 $err ]
+}
+# --------------------------------------------------------
+itcl::body bis_datamanager::SaveObjectPointers { elem }  {
+    #set attributepointers { PointerObject PointerTransformation PointerInverseTransformation   }
+    #set attributepointerfilenames {  Filename TransformationFilename InverseTransformationFilename }
+
+    set maxno [ llength $attributepointers ]
+    set ndtype [ $elem GetAttribute Type ]
+    if { $ndtype == "Folder" || $ndtype == "Subject" } {
+	return 1
+    } elseif { $ndtype != "Image" } {
+	set maxno 1
+    } 
+
+    set err ""
+
+    while { $i < $maxno && $err == "" } {
+	set fname [ $elem GetAttribute [ lindex $attributepointerfilenames  $i ] ]
+	set obj [ $elem GetAttribute [ lindex $attributepointers $i ] ]
+	if { $obj != 0  } {
+	    set ext [ file extension $fname ]
+	    set dosave 1
+	    if { $ext != ".donotsave" && [ string length $fname ] > 2 } {
+		set ok [ $obj Save $fname ]
+		if { $ok == 0 } {
+		    set err "Failed to save [ lindex $attributepointers $i ] from $fname" 
+		}
+	    }
+	}else {
+	    set err "Failed to save [ lindex $attributepointers $i ], bad pointer" 
+	}
+	incr i
+    }
+
+    if { $err == "" } {
+	$this UpdateDisplayAttributes
+	return 1
+    }
+		     
+    return { 0 $err }
+}
+# --------------------------------------------------------
+#  Importing Other Formats .tre and .msb
+# --------------------------------------------------------
+itcl::body bis_datamanager::ConvertTreeElementToXMLElement { xmltree tcltreenode tcltree { depth 0 } } {
+
+    set offset ""
+    for { set i 0 } { $i < $depth } { incr i } {
+	set offset "${offset}\t"
+    }
+    set n ""
+    catch { set n  [ $tcltree get $tcltreenode $name  ] }
+
+#    puts stderr "$offset Starting ConvertTreeElementToXMLElement $tcltreenode ($n) ***************************\n"
+
+    set lst [ array names treemap ]
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	set name [ lindex $lst $i ]
+	set val 0
+	catch { set val  [ $tcltree get $tcltreenode $name  ] }
+	set attname $treemap($name)
+	if { $name == "type" } {
+
+
+	    if { $val == -1 || $val == 0 } {
+		$xmltree SetAttribute Type "Image"
+	    } elseif { $val == "Patient" } {
+		$xmltree SetAttribute Type "Subject"
+	    } elseif { $val == "Folder" } {
+		$xmltree SetAttribute Type "Folder"
+	    } elseif { $val == "Surface Surface" } {
+		$xmltree SetAttribute Type "Surface"
+	    } elseif { $val == "Surface Landmark" } {
+		$xmltree SetAttribute Type "Landmarks"
+	    } elseif { $val == "Surface Electrode" }  {
+		$xmltree SetAttribute Type "Electrodes" 
+	    } else {
+		$xmltree SetAttribute Type "Image"
+		set outname "None"
+		array set dtypes [ $rootnode GetAttribute GlobalDataTypes ]
+		catch { set outname $dtypes($val) }
+		$xmltree SetAttribute SubType "$outname"
+	    }
+	} elseif { $attname != "none" } {
+	    $xmltree SetAttribute $attname  [ CleanString $val  ]
+	}
+    }
+
+    set name ""
+    set keys [ $tcltree keys $tcltreenode ]
+    catch { set name  [ $tcltree get $tcltreenode title  ] }
+    if { $name == "" } {
+	set name "Folder"
+    }
+
+    if { $xmltree != $rootnode } { 
+	set nm [ CleanString $name ]
+	$this SetUniqueName $xmltree $nm
+    }
+
+    foreach attr $attributeszero { 
+	$xmltree SetAttribute $attr 0
+    }
+    
+    set par [ $xmltree GetParent ]
+    if { $par == "" || $par == 0 } {
+	set nm ""
+    } else {
+	set nm "<-- [ $par GetName ]"
+    }
+
+    # -------------------------------------------------------------------------------------------------------
+    #    puts stderr "$offset Added Element [$xmltree GetName ], [ $xmltree GetAttribute Filename ] to $nm"
+    # -------------------------------------------------------------------------------------------------------
+
+    set children  [ $tcltree children $tcltreenode ]
+    if { [ llength $children ] > 0 } {
+	for { set j 0 } { $j < [ llength $children ] } { incr j } {
+	    set child [ lindex $children $j ]
+	    set newxml [ $this GetNewXMLDataElement ]
+	    $xmltree AddNestedElement $newxml
+	    $this ConvertTreeElementToXMLElement $newxml $child $tcltree  [ expr $depth +1 ]
+	}
+    } 
+}
+
+# ---------------------------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::ImportTree { fname } { 
+
+    if { [ file readable $fname ]  == 0 } {
+	return 0
+    }
+
+    set fileid [open $fname r]
+    gets $fileid line
+    
+    if { [ string compare $line "#Chelly's Datatree File Format" ] != 0 } {
+	puts stderr " File is not in Datatree File Format "
+	close $fileid
+	return 0
+    }
+	
+    while { [ gets $fileid line ] >=0 } {
+	set index [string first ":" $line]
+	
+	if { $index > 0 }  {
+	    set len   [string length $line]
+	    
+	    set key   [string trim   [string range $line 0 [expr $index - 1]]]
+	    set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+	    set newtree($key)  $value 
+#	    puts stderr "Importing $key $value"
+	}
+    }  
+    close $fileid
+	
+    #Throw a key into the array to tag its type
+    set newtree(ChellysTreeFormat) 1
+    set newtree(ThisFileName) $fname
+    set newlist [ array get newtree ]
+
+    set patientprops $newtree(PatientProps)
+    set typedefarray $newtree(TypeDefArray)
+
+    array set TreeDefArray $newlist
+
+    set mytree [ ::struct::tree [ pxvtable::vnewobj ] deserialize $TreeDefArray(serialized)  ]
+    set treeelement [ $mytree rootname ]
+    
+    foreach node [ $mytree children -all $treeelement ] {
+		
+	#set the notes for the node
+	$mytree set $node notes [string map {{\n} \n} $TreeDefArray($node,notes)]
+		
+	#--------------------------------------------------
+	#Set the filenames if they are saved
+	#--------------------------------------------------
+	if { $TreeDefArray($node,filename) != -1 } {
+	    $mytree set $node FileName $TreeDefArray($node,filename)
+	}
+	if { $TreeDefArray($node,transtoparfilename) != -1 } {
+	    $mytree set $node TransToParFileName $TreeDefArray($node,transtoparfilename)
+	}
+	if { $TreeDefArray($node,transfromparfilename) != -1 } {
+	    $mytree set $node TransFromParFileName $TreeDefArray($node,transfromparfilename)
+	}
+    }
+
+    # ---------------------------------------------------
+    
+    # ---------------------------------------------------
+
+#    puts stderr "Serialized ............. [ $mytree serialize [ $mytree rootname ]]"
+
+    #    puts stderr "OK -- Heading out to XML $nextid ----------------------------\n"
+    $this CleanXML
+
+
+    
+    #    set xml2 [ vtkXMLDataElement New ]
+    #    $rootnode AddNestedElement $xml2
+
+    #    puts stderr "Begin importing tree \n\n"
+    $this ConvertTreeElementToXMLElement $rootnode $treeelement $mytree
+
+    #    puts stderr "\n\n\n Done Importing \n\n\n\n\n"
+
+    $rootnode SetName "BioImageSuite_DataTree"
+    $rootnode SetAttribute Title "BioImageSuite_DataTree"
+    $rootnode SetAttribute "Type" "Folder"
+    $rootnode SetAttribute "Icon" "idir"
+    $rootnode SetAttribute "Linecolor"  green
+    $rootnode SetAttribute "IsIdentity"  1
+    $rootnode SetAttribute "Expanded"  1
+    $rootnode SetAttribute GlobalSubjectProperties $patientprops
+    $rootnode SetAttribute GlobalDataTypes $typedefarray
+    $rootnode SetAttribute GlobalFilename [ file normalize $fname ]
+    $rootnode SetAttribute GlobalPath    [ file dirname  [ file normalize $fname ] ]
+
+    $this RecursiveFixTreeAndAllocatePointers $rootnode [ $rootnode GetAttribute GlobalPath ]
+    return 1
+}
+
+# ------------------------------------------------------------------
+# Importing MSB File
+# ---------------------------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::ImportMSBFile { fname } { 
+
+    if { [ file readable $fname ] == 0 } {
+	puts stderr "Failed to read $fname"
+	return 0
+    }
+
+    set fileid [open $fname r]
+	
+    gets $fileid line
+
+    set setupmode 0
+
+    if { [ string compare $line "#Multisubject Description File"  ] != 0 } {
+	if { [ string compare $line "#Multisubject Description File v2"  ] != 0 } {
+	    if { [ string compare $line "#Multisubject Description File v3"  ] != 0 } {
+		close $fileid
+		puts stderr "Cannot read setupfile file from $fname\n Bad File Type"
+		return 0
+	    } else {
+		set setupmode 2
+	    }
+	} else {
+	    set setupmode 1
+	}
+    }
+
+    #    puts stderr "Setupmode =$setupmode"
+
+    gets $fileid line ;     gets $fileid line  ;     set numtasks $line ;    gets $fileid line 
+
+    set tasklist ""
+
+    for { set i 0 } { $i < $numtasks } { incr i } {
+	set tmp [ [ pxitcltask \#auto ]  GetThisPointer ]
+	lappend tasklist $tmp
+	$tmp LoadFromSetupFile $fileid
+    }
+
+
+    gets $fileid line ;     gets $fileid line  ;     set numsub $line ;    gets $fileid line 
+
+    set subjectlist ""
+
+    for { set i 0 } { $i < $numsub } { incr i } {
+	set tmp [ [ pxitclsubject \#auto ]  GetThisPointer ]
+	lappend subjectlist $tmp
+	$tmp LoadFromSetupFile $fileid $setupmode
+    }
+
+    gets $fileid line ; gets $fileid line 
+
+    # Do the Reference Separately
+    set refname [ pxitclsubject::GetFileElement $fileid ]
+    # Next do the VOI Control
+    if { $setupmode == 2 } {
+	set voiname [ pxitclsubject::GetFileElement $fileid ]
+    } else {
+	set voiname ""
+    }
+    
+    set output_list [ list "Average Anatomical" "Std Anatomical" "Average Functional" "Std Functional" "Tscore Functional" ]
+
+    for { set i 0 } { $i < [ llength $output_list ] } { incr i } {
+	set resname($i) [ pxitclsubject::GetFileElement $fileid ]
+    }
+
+    #    puts stderr "OK -- Heading out to XML $nextid ----------------------------\n"
+    $this CleanXML
+    # ---------------------------------------------------------------------------------
+    $rootnode SetName "BioImageSuite_DataTree"
+    $rootnode SetAttribute Title "BioImageSuite_DataTree"
+    $rootnode SetAttribute "Type" "Folder"
+    $rootnode SetAttribute "Icon" "idir"
+    $rootnode SetAttribute "Linecolor"  green
+    $rootnode SetAttribute "IsIdentity"  1
+    $rootnode SetAttribute "Expanded"  1
+    $rootnode SetAttribute GlobalSubjectProperties "MSB File"
+    $rootnode SetAttribute GlobalDataTypes ""
+    $rootnode SetAttribute GlobalFilename [ file normalize $fname ]
+    $rootnode SetAttribute GlobalPath    [ file dirname  [ file normalize $fname ] ]
+
+
+    set ref [ eval "$this CreateChildElement $rootnode Image Reference_Image { Filename $refname } " ]
+    set refdata [ $this CreateChildElement $ref Folder  A_Reference_Data {  Expanded "1" } ]
+    set subjectdata [ $this CreateChildElement $ref Folder B_Subject_Data {  Expanded "1"  IsIdentity 1 } ]
+    eval "$this CreateChildElement $refdata Image  VOI_Image { Filename \"$voiname\" IsIdentity  1 }"
+
+
+    for { set i 0 } { $i < [ llength $subjectlist ] } { incr i } {
+	
+	set ind [ expr $i + 1 ]
+	set sname "S$ind-"
+	set pt [ lindex $subjectlist $i ]
+	set subj [ $this CreateChildElement  $subjectdata "Subject" "${sname}[ $this CleanString [ $pt GetBaseName ] ]" { IsIdentity 1 } ]
+#	puts stderr "Added Subject $i [ $subj GetAttribute Title ]"
+	
+
+	set aname [ [ $pt cget -anatomical_image ] cget -filename ]
+	set xname [ [ $pt cget -reference_transform ] cget -filename ]
+	set cname [ [ $pt cget -conventional_image ] cget -filename ]
+	set iname [ [ $pt cget -internal_transform ] cget -filename ]
+	set ename [ [ $pt cget -echoplanar_image ] cget -filename ]
+	set dname [ [ $pt cget -distortion_transform ] cget -filename ]
+#	puts stderr "images = ($aname,$cname,$ename)\n, xforms=($xname,$iname,$dname)"
+
+
+	set anat [ eval "$this CreateChildElement $subj Image \"${sname}3D_Anatomical_Image\" { Filename \"$aname\"   TransformationFilename \"$xname\" }" ]
+	set conv [ eval "$this CreateChildElement $anat Image \"${sname}Conventional_Image\" { Filename \"$cname\"  TransformationFilename \"$iname\" }" ]
+	set epi [ eval "$this CreateChildElement $conv Image  \"${sname}Echoplanar_Image\" { Filename \"$ename\"  TransformationFilename \"$dname\" } " ]
+	set func [ $this CreateChildElement $epi "Folder" "${sname}Functional_Data" ]
+	set fname [ [ $pt cget -functional_image ] cget -filename  ]
+	set oldfname $fname
+	set oldsuffix ""
+
+	for { set j 0 } { $j < [ llength $tasklist ] } { incr j } {
+	    set task [ lindex $tasklist $j ]
+	    set tname   [ $task cget -task_name ]
+	    set tsuffix [ $task cget -task_suffix ]
+
+	    set ttsname "T[ expr $j +1 ]-"
+	    
+	    if { $oldsuffix != "" } {
+		set ind [ string last $oldsuffix $fname ]
+		if { $ind >=0 } {
+		    regsub -start $ind $oldsuffix $fname $tsuffix fname
+		}
+	    }
+	    set oldsuffix $tsuffix
+	    set t [ $this CreateChildElement $func Image "${sname}${ttsname}[ $this CleanString $tname]" ]
+	    $t SetAttribute Filename $fname
+	    $t SetAttribute IsIdentity 1
+
+	    
+	}
+    }
+
+    set n 0
+    for { set i 0 } { $i < 5 } { incr i } {
+	set n [ expr $n + [ string length $resname($i) ] ]
+    }
+
+    if { $n > 0 } {
+	set results [ $this CreateChildElement $ref "Folder"  C_Results { IsIdentity 1  Expanded "1" } ]
+	
+	if { [ string length $resname(0) ] > 0 || [ string length $resname(1) ] > 0 } {
+	    set func [ $this CreateChildElement $results "Folder" "Anatomical_Images"  ]
+	    eval "$this CreateChildElement $func Image  Average_Anatomical_Image {  Filename \"$resname(0)\"   IsIdentity 1 } "
+	    eval "$this CreateChildElement $func Image  Stdev_Anatomical_Image   { Filename \"$resname(1)\"   IsIdentity 1 } "
+	}
+	
+	set tfname(0) $resname(2)
+	set tfname(1) $resname(3)
+	set tfname(2) $resname(4)
+	
+	set tn 0
+	for { set i 0 } { $i < 3 } { incr i } {
+	    set tn [ expr $tn + [ string length $tfname($i) ] ]
+	}
+	
+	if { $tn > 0 } {
+	    
+	    set tflist { "Average_Functional" "Std_Functional" "Tscore_Functional" }
+	    set oldsuffix ""
+	    
+	    
+	    for { set j 0 } { $j < [ llength $tasklist ] } { incr j } {
+		set task [ lindex $tasklist $j ]
+		set tname   [ $task cget -task_name ]
+		set tsuffix [ $task cget -task_suffix ]
+		
+		if { $oldsuffix != "" } {
+		    set ind [ string last $oldsuffix $fname ]
+		    if { $ind >=0 } {
+			for { set k 0 } { $k <=2 } { incr k } {
+			    regsub -start $ind $oldsuffix $tfname($k) $tsuffix tfname($k)
+			}
+		    }
+		}
+		set oldsuffix $tsuffix
+		set ttsname "T[ expr $j +1 ]-"	
+		set funcdir [ eval "$this CreateChildElement $results Folder [ $this CleanString \"${ttsname}Results_$tname\" ] " ]
+		for { set k 0 } { $k<=2 } { incr k } {
+		    eval " $this CreateChildElement $funcdir Image [ $this CleanString \"${ttsname}[ lindex $tflist $k ]_$tname\" ] {  Filename \"$tfname($k)\"  IsIdentity 1 } "
+		}
+	    }
+	}
+    }
+    # This is the critical command
+    # unique names, allocate pointers, fixes icons/colors .....
+    $this RecursiveFixTreeAndAllocatePointers $rootnode [ $rootnode GetAttribute GlobalPath ]
+    return 1
+}
+
+# ------------------------------------------------------------------
+itcl::body bis_datamanager::RecursiveFixTreeAndAllocatePointers { elem { globalpath "" } } {
+
+    for { set j 0 } { $j < [ $elem GetNumberOfNestedElements ] } { incr j } {
+	set e [ $elem GetNestedElement $j ]
+	$this RecursiveFixTreeAndAllocatePointers $e $globalpath
+    }
+
+
+    if { $elem == $rootnode } {
+	return 1
+    }
+
+    $this AllocatePointersXMLDataElement $elem 
+    $this SetUniqueName $elem
+
+    foreach attr $attributepointerfilenames {
+	set in [ $elem GetAttribute $attr ]
+	set f [ $this FileNameToAbsolute $in $globalpath ]
+	if { $in != $f }  {
+	    $elem SetAttribute $attr $f
+	}
+    }
+    $this UpdateDisplayAttributes $elem
+
+    return 1
+}
+
+itcl::body bis_datamanager::RecursiveDeleteChildren { elem } {
+
+    for { set j 0 } { $j < [ $elem GetNumberOfNestedElements ] } { incr j } {
+	set e [ $elem GetNestedElement $j ]
+	$this RecursiveDeleteChildren $e
+	$elem RemoveNestedElement $e
+	#	$e Delete
+    }
+
+    foreach nm $attributepointers { 
+	set ptr [ $elem GetAttribute $nm ]
+	if { $ptr !=0 &&  $ptr != "" } {
+	    #	    puts stderr "Deleting children"
+	    itcl::delete obj $ptr
+	} 
+    }
+}
+# -----------------------------------------------------------------------
+# Load & Save Issues
+# -----------------------------------------------------------------------
+
+itcl::body bis_datamanager::CleanXML  {  } {
+
+    if { $rootnode !=0 } {
+	$this RecursiveDeleteChildren $rootnode
+    } else {
+	set rootnode [ $this GetNewXMLDataElement "Folder" ]
+    }
+
+    #    puts stderr "Adding Root node [ $rootnode GetAttribute UniqueId ]"
+    $rootnode SetName "BioImageSuite_DataTree"
+    $rootnode SetAttribute "Type" "Folder"
+    $rootnode SetAttribute "Icon" "idir"
+    $rootnode SetAttribute "Linecolor"  green
+    $rootnode SetAttribute "IsIdentity"  1
+    $rootnode SetAttribute "Expanded"  1
+}
+# ------------------------------------------------------------------
+itcl::body bis_datamanager::CheckSavedObjects {  { node 0 } { dosave 0 } } {
+
+    if { $node == 0 } {
+	set node [ $this GetRootNode ]
+    }
+
+    puts stderr "Checking [ $node GetName ]"
+    set lst ""
+    for { set j 0 } { $j < [ $node GetNumberOfNestedElements ] } { incr j } {
+	set a [ $this CheckSavedObjects [ $node GetNestedElement $j ] ]
+	if { [ llength $a ] > 0 } {
+	    set lst [ concat $lst $a ]
+	}
+    }
+
+    set maxno [ llength $attributepointers ]
+    set ndtype [ $node GetAttribute Type ]
+    if { $ndtype == "Folder" || $ndtype == "Subject" } {
+	return $lst
+    } elseif { $ndtype != "Image" } {
+	set maxno 1
+    } 
+
+    set i 0
+    while { $i < $maxno  } {
+	set fname [ $node GetAttribute [ lindex $attributepointerfilenames  $i ] ]
+	set obj [ $node GetAttribute [ lindex $attributepointers $i ] ]
+        set name [ $node GetName ]
+	set attr [ lindex $attributepointers $i ]
+	if { $obj != 0  } {
+	    set ext [ file extension $fname ]
+	    set sz [ $obj GetSize ]
+	    if { [ $obj isa pxitclimage ] } {
+		set sz [ expr $sz -1 ]
+	    }
+	    if { $ext != ".donotsave" && $sz > 0 } {
+		set ok 0
+		if { [ string length $fname ]  < 2 } {
+		    set fname ""
+		} elseif { [ file exists $fname ] == 1 } {
+		    set ok 1
+		}
+		
+		if { $ok == 0 &&  $dosave > 0 } {
+		    set ok [ $obj Save $fname ]
+		    if { $ok > 0 } {
+			pxtkprint "Saved $name:$attr --> ($fname)"
+		    }
+		}
+
+		if { $ok == 0 } {
+		    lappend lst "$name:$attr ($fname)  [ $obj GetSize ]"
+		}
+	    }
+	}
+	incr i
+    }
+    
+    puts stderr "lst=$lst"
+    return $lst
+
+
+}
+# ------------------------------------------------------------------
+itcl::body bis_datamanager::LoadXML  { fname } {
+
+    set parse [ vtkXMLDataParser New ]
+    $parse SetFileName $fname
+    $parse SetIgnoreCharacterData 1
+    $parse Parse
+
+    set elem [ $parse GetRootElement ]
+    set ok 0
+    if { $elem != "" } {
+	if { [ $elem GetName ] ==  "BioImageSuite_DataTree"  } {
+	    $this CleanXML
+	    $rootnode DeepCopy $elem
+	    #	    puts stdout "Succesfully  Read XML Data Tree File from $fname"
+	}
+	set ok 1
+    }
+    $parse Delete
+    $rootnode SetName "BioImageSuite_DataTree"
+    $rootnode SetAttribute "Type" "Folder"
+    $rootnode SetAttribute "Icon" "idir"
+    $rootnode SetAttribute "Linecolor"  green
+    $rootnode SetAttribute "IsIdentity"  1
+    $rootnode SetAttribute "Expanded"  1
+    $rootnode SetAttribute GlobalFilename [ file normalize $fname ]
+    $rootnode SetAttribute GlobalPath    [ file dirname  [ file normalize $fname ] ]
+
+    $this RecursiveFixTreeAndAllocatePointers $rootnode [ $rootnode GetAttribute GlobalPath ]
+    return ok
+}
+# -----------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::SaveXML  { fname } {
+
+    set fout [ open $fname w ]
+    if { $fout!=0 } {
+	set gp [ file dirname  [ file normalize $fname ] ]
+	$rootnode SetAttribute GlobalFilename [ file normalize $fname ]
+	$rootnode SetAttribute GlobalPath     $gp
+	set line [ $this XMLElementToString $rootnode 0 1  $gp ]
+	puts $fout $line
+	close $fout
+	return 1
+    }
+    return 0
+}
+
+# -----------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::XMLElementToString { elem { n 0 } { savemode 0 } { globalpath "" } } {
+    set line ""
+    set offset ""
+    for { set i 0 } { $i < $n } { incr i } {
+	set offset "$offset\t"
+    }
+    set line ""
+
+    set preservelist [ concat $attributeszero $attributepointerfilenames ]
+    
+    if { $savemode  == 1 } {
+	foreach attr $preservelist {
+	    set old($attr) [ $elem GetAttribute $attr ]
+	}
+	
+	foreach attr $attributeszero {
+	    $elem SetAttribute $attr 0 
+	}
+
+	foreach attr $attributepointerfilenames {
+	    set f  [ $elem GetAttribute $attr ]
+	    set f2 [ $this FileNameToRelative $f $globalpath ]
+	    if { $f2 != $f } {
+#	    puts stderr "Remapping to relative filenames $f -> $f2"
+		$elem SetAttribute $attr $f2 
+	    }
+	}
+    }
+
+
+    if { $elem != $rootnode } {
+	set tagname "Node"
+	set myline "\n${offset}<$tagname "
+    } else {
+	set tagname "[ $rootnode GetName ]"
+	set myline "<$tagname"
+    }
+    if { [ $elem GetNumberOfAttributes ] > 0 } { 
+	for { set i 0 } { $i < [ $elem GetNumberOfAttributes ] } { incr i } {
+	    set myline "$myline [ $elem GetAttributeName $i ]=\"[ $elem GetAttributeValue $i]\"" 
+	}
+    }
+
+    set myline "$myline\>"
+    #    puts stderr "$offset *** myline=$myline *** "
+    set line "${line}${myline}"
+
+    if { $savemode  == 1 } {
+	foreach attr $preservelist {
+	    $elem SetAttribute $attr $old($attr)
+	}
+    }
+
+    for { set j 0 } { $j < [ $elem GetNumberOfNestedElements ] } { incr j } {
+	set newline "[ $this XMLElementToString [ $elem GetNestedElement $j ] [ expr $n +1 ] $savemode  $globalpath]"
+	#	puts stderr "$offset ****** newline=$newline *** "
+	set line "${line}${newline}"
+    }
+
+    set cline "$offset</$tagname>"
+#    puts stderr "$offset *** cline = $cline *** "
+    set line "${line}\n${cline}"
+    return $line
+}
+
+# ---------------------------------------------------------------------------------------------------------------------
+# Tree Manipulation -- this is key !
+# 
+# Theoretically all in place -- check, check, check
+# ---------------------------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::RecursiveAllocateNewPointersAndCopy { elem } {
+
+    if { $elem == 0 || $elem == $rootnode } {
+	return 0
+    }
+
+    for { set j 0 } { $j < [ $elem GetNumberOfNestedElements ] } { incr j } {
+	$this RecursiveAllocateNewPointersAndCopy [ $elem GetNestedElement $j ]
+    }
+
+    foreach nm $attributepointers { 
+	set ptr [ $elem GetAttribute $nm ]
+	if { $ptr !=0 &&  $ptr != "" } {
+
+	    #do something
+	    set cl [ $ptr info class ]
+	    set newptr [ eval "$cl #auto" ]
+	    set newptr [ $newptr GetThisPointer ]
+	    $newptr Copy $ptr
+	    $elem SetAttribute $nm $newptr
+	} 
+    }
+
+    return 1
+    
+
+}
+# ---------------------------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::CreateUniqueIds { elem } {
+
+    if { $elem == 0 } {
+	return 0
+    }
+
+    set nm [ $elem GetName ]
+    set lst [ split $nm : ]
+    set id [ $this GetNextId ]
+    
+
+    if { [ llength $lst ] == 2 } {
+	set newname "[lindex $lst 0 ]"
+    } else {
+	set upper [ expr [ llength $lst ] -2 ]
+	set newname ""
+	for { set i 0 } { $i < $upper } { incr i } {
+	    set newname "$newname[llength $lst $i]"
+	}
+	set newname "${newname}"
+    }
+
+    $xmltree SetAttribute UniqueId $id
+    $this SetUniqueName $xmltree $newname
+    
+    for { set j 0 } { $j < [ $elem GetNumberOfNestedElements ] } { incr j } {
+	$this CreateUniqueIds [ $elem GetNestedElement $j ]
+    }
+    return $id
+}
+# ---------------------------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::CopyElement { elem newparent } {
+
+    if { $elem == 0 || $elem == $rootnode } {
+	return 0
+    }
+
+    if { [ $elem GetParent ] == $newparent } {
+	return 0
+    }
+
+    set newnode [ vtkXMLDataElement New ]
+    $newnode DeepCopy $elem
+    $this CreateUniqueIds $newnode
+    $this RecursiveAllocateNewPointersAndCopy $newnode
+    $newparent AddNestedElement $newnode
+    return 1
+}
+# ---------------------------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::MoveElement { elem newparent } {
+
+    if { $elem == 0 || $elem == $rootnode } {
+	return 0
+    }
+
+    if { [ $elem GetParent ] == $newparent } {
+	return 0
+    }
+    
+    puts stderr "[[ $elem GetParent ] GetName ] Removing [ $elem GetName ]"
+
+    $elem Register $rootnode
+    [ $elem GetParent ] RemoveNestedElement $elem
+    #    puts stderr "[ $newparent GetName ] Adding [ $elem GetName ]"
+    $newparent AddNestedElement $elem
+    $elem UnRegister $rootnode
+    return 1
+    
+}
+# ---------------------------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::DeleteElement { elem  } {
+
+    if { $elem ==0 || $elem == $rootnode } {
+	return 0
+    }
+
+    $this RecursiveDeleteChildren $elem
+    [ $elem GetParent ] RemoveNestedElement $elem
+    $elem Delete
+}
+# ---------------------------------------------------------------------------------------------------------------------
+itcl::body bis_datamanager::InsertElement { elem newparent } {
+
+    if { $elem == 0 || $elem == $rootnode } {
+	return 0
+    }
+
+    if { [ $elem GetParent ] == $newparent } {
+	return 0
+    }
+    
+    set newnode [ vtkXMLDataElement New ]
+    $newnode DeepCopy $elem
+    $this CreateUniqueIds $newnode
+    $newparent AddNestedElement $newnode
+    return 1
+}
+
+
+# ---------------------------------------------------------------------------------------------------------------------
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    package require vtkpxcontrib
+
+    # Random Testing Code Here
+
+    set alg [ bis_datamanager \#auto ]
+    set f [ lindex $argv 0 ]
+    set ok [ $alg ImportMSBFile $f ]
+    if { $ok > 0 } {
+	set ok [ $alg SaveXML "$f.xmltree" ]
+	puts stderr "Saved in $f.xmltree" 
+    }
+
+    exit
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_decimate.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_decimate.tcl
new file mode 100755
index 0000000..e786452
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_decimate.tcl
@@ -0,0 +1,143 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_surfacetosurfacealgorithm 1.0
+
+package provide bis_decimate 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_decimate {
+
+    inherit bis_surfacetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Decimate" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_decimate::Initialize { } {
+
+    PrintDebug "bis_decimate::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ decimatefactor "Specify the desired reduction in the total number of polygons." "Decimate factor"  { real triplescale 100 }    0.2 { 0.0 1.0 }  0 }
+	{ preserveTopology "Turn on/off whether to preserve the topology of the original mesh. If on, mesh splitting and hole elimination will not occur. This may limit the maximum reduction that may be achieved." "Preserve Topology" { listofvalues radiobutton}  On { On Off}   1}
+    }
+
+    set defaultsuffix { "_decimate" }
+    
+    set scriptname bis_decimate
+
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "decimate a surface"
+    set description2 "takes in a surface and returns a surface with less points"
+    set backwardcompaibitlity "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeSurfacetoSurfaceAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_decimate::Execute {  } {
+
+    PrintDebug "bis_decimate::Execute"
+
+    # Get Inputs
+    set surface    [ $this GetInput  ]
+    # GetOptions
+    
+    set decimatefactor [ $OptionsArray(decimatefactor)      GetValue ]
+    set preserveTopology [ $OptionsArray(preserveTopology)    GetValue ]
+    
+	
+    # Run Algorithm
+    set triangleFilter [ vtkTriangleFilter [ pxvtable::vnewobj ] ]
+    $triangleFilter SetInput [ $surface GetObject ]
+	
+    set decimateFilter [vtkDecimatePro  [ pxvtable::vnewobj ] ]
+    $decimateFilter SetInput [$triangleFilter GetOutput]
+    $decimateFilter SetTargetReduction $decimatefactor
+    
+    if { $preserveTopology == "On"} {
+	$decimateFilter PreserveTopologyOn
+    } else { 
+	$decimateFilter PreserveTopologyOff
+    }
+    
+    #$triangleFilter Update
+    $decimateFilter Update
+    
+    # Store Results in output
+    set surface_out [$decimateFilter GetOutput ]
+    [ $OutputsArray(output_surface) GetObject ] DeepCopySurface $surface_out 
+
+    # Clean up
+    $triangleFilter Delete
+    $decimateFilter Delete
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_decimate.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_decimate [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_delaunay3D.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_delaunay3D.tcl
new file mode 100755
index 0000000..4bd7bee
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_delaunay3D.tcl
@@ -0,0 +1,141 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_surfacetosurfacealgorithm 1.0
+
+package provide bis_delaunay3D 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_delaunay3D {
+
+    inherit bis_surfacetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Delaunay Triangulation" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_delaunay3D::Initialize { } {
+
+    PrintDebug "bis_delaunay3D::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ merging "Turn on/off merging of coincident points. Note that is merging is on, points with different point attributes (e.g., normals) are merged, which may cause rendering artifacts." "Toggle Merging" { boolean}  0 { 0 1 }   1}
+    }
+
+    set defaultsuffix { "_delaunay3D" }
+    
+    set scriptname bis_delaunay3D
+
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "Delaunay triangulation of a surface"
+    set description2 ""
+    set backwardcompaibitlity "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeSurfacetoSurfaceAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_delaunay3D::Execute {  } {
+
+    PrintDebug "bis_delaunay3D::Execute"
+
+    # Get Inputs
+    set surface    [ $this GetInput  ]
+    # GetOptions
+    
+    set merging [ $OptionsArray(merging)  GetValue ]
+	
+    # Run Algorithm
+    set filter [vtkDelaunay3D [ pxvtable::vnewobj ] ]
+    $filter SetInput [ $surface GetObject ]
+    $filter Update
+
+#    set dt [vtkDataSet [$filter GetOutput]]
+
+    set geom [ vtkGeometryFilter [ pxvtable::vnewobj ] ]
+    $geom SetInput [$filter GetOutput ]
+   
+    if { $merging == "1"} {
+	    $geom MergingOn
+       } else {
+	    $geom MergingOff
+       }
+	
+	$geom Update
+    
+    # Store Results in output
+    set surface_out [$geom GetOutput ]
+    [ $OutputsArray(output_surface) GetObject ] DeepCopySurface $surface_out 
+
+    # Clean up
+    $filter Delete
+    $geom Delete
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_delaunay3D.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_delaunay3D [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_dicom2nifti.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_dicom2nifti.tcl
new file mode 100755
index 0000000..98c5d0a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_dicom2nifti.tcl
@@ -0,0 +1,326 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+
+package require bis_algorithm 1.0
+package require bis_newreorientimage 1.0
+
+package provide bis_dicom2nifti 1.0
+
+#
+# Operations involving multisubject average for testing ....
+#
+
+itcl::class bis_dicom2nifti {
+
+    inherit bis_algorithm
+    
+    constructor { } {
+	$this Initialize
+    }
+
+    public method Initialize { }
+    public method Execute { }
+    public method PrintOutput { nn }
+    public method GetGUIName { } { return "DICOM 2 NIFTI" }
+}
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_dicom2nifti::Initialize { } {
+
+    PrintDebug "bis_dicom2nifti::Initialize" 
+
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set inputs { }
+    set outputs { }
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ indir "Input directory containing DICOM Files" "Input Directory:"  { filename directory 40 }  "" "" 1 }
+	{ outdir "Output directory for NIFTI Files" "Output Directory:"  { filename directory 40 }  "" "" 2 }
+	{ mode "Postprocessing of Original Data" "Mode"  listofvalues  NONE { NONE RAS LPS }   3}
+	{ name  "Study Name" "Name"  { string 20 }  "" ""  4 }
+	{ dosave "If set to off no files are created" "Do Save:"  { boolean checkbutton } 1 { 0 1 }  -10 }
+	{ dodump "If set to one (default) then a dump of one of the dicom files in a series is saved" "Do DICOM Dump:"  { boolean checkbutton } 1 { 0 1 }  -4 }
+	{ debugmode "Extra Header Info (if dodump=1)" "DebugMode"  listofvalues  NONE { NONE SIEMENS GE }   -20 }
+
+    }
+
+    set outputs { }
+
+    set defaultsuffix { "" }
+
+    set scriptname bis_dicom2nifti
+    set completionstatus ""
+    #
+    #document
+    #
+    set category "Utility"
+    set description "This script parses a directory containing DICOM images and creates NIFTI output files"
+    set description2 "Has capabilities for Siemens Mosaic Format (for FMRI)"
+    set backwardcompatibility "Based on original ImageConversion script at Yale MRRC"
+    set authors "xenophon.papademetris.yale.edu"
+
+    $this AddDefaultOptions
+
+
+}
+
+itcl::body bis_dicom2nifti::PrintOutput { nn } {
+
+    if { $basewidget == 0 } {
+	puts stdout "${nn}"
+    } else {
+	pxtkprint "${nn}\n"
+    }
+}
+
+
+itcl::body bis_dicom2nifti::Execute {  } {
+
+    set dryrun 0
+    if { [ $OptionsArray(dosave) GetValue ] == 0 } {
+	set dryrun 1
+    }
+    
+    set basedir [ file normalize [ $OptionsArray(indir) GetValue ] ]
+
+    set savednames ""
+
+    set outputdir [ $OptionsArray(outdir) GetValue ] 
+
+    if { $outputdir == "" } {
+	set n [ pid ]
+	set f  [ file join [ pwd ] nifti_$n ]
+	while { [ file exists $f ] > 0 } {
+	    incr n
+	    set f  [ file join $outdir tmp_$n ]
+	}
+	set outputdir $f 
+    }
+
+    set outputdir [ file normalize $outputdir ]
+    catch {    file mkdir $outputdir }
+
+
+    set dodump [ $OptionsArray(dodump) GetValue ]
+    set debugmode [ $OptionsArray(debugmode) GetValue ]
+    set outmode [ $OptionsArray(mode) GetValue ]
+    set pname   [ $OptionsArray(name) GetValue ]
+
+
+    if { $basewidget != 0 } {
+	pxtkconsole
+    }
+
+    $this PrintOutput "Beginning -- Input Directory = $basedir, outputdir=$outputdir, convmode=$outmode, pname=$pname"
+    
+    set dname $basedir
+    cd $dname
+    
+
+    # ----------------------------------------------------------------------
+    # Find last acquired image, newest file in $dname
+    # ----------------------------------------------------------------------
+    
+    set outname "$basedir"
+    set convertedlist ""
+    set done 0
+    set pass 0
+    while { $done == 0 } {
+	
+	incr pass
+	set a [ glob [ file join $dname * ] ]
+	set lst ""
+	for { set i 0 } { $i < [ llength $a ] } { incr i } {
+	    set f [ lindex $a $i ]
+	    set f2 [ file tail $f ]
+	    set ind [ lsearch -exact $convertedlist $f2 ] 
+	    #	$this PrintOutput "Searching for $f2 in [ lindex $convertedlist 0 ], index = $ind"
+	    if { $ind == -1 } {
+		lappend lst $f
+	    }
+	}
+	
+	if { [ llength $lst ] == 0 } {
+	    $this PrintOutput "\n\n------------------------------------------------------------\n No More Files To Convert \n------------------------------------------------------------\n"
+
+	    set savednames [ lsort -ascii -index 0 $savednames  ]
+	    for { set i 0 } { $i < [ llength $savednames ] } { incr i } {
+		$this PrintOutput "[ expr $i +1 ]. [ lindex [ lindex $savednames $i ] 0 ]  ( [ lindex [ lindex $savednames $i ] 1 ] )"
+	    }
+	    return 1
+	}
+	
+	$this PrintOutput "\n\n------------------------------------------------------------\n Doing Pass $pass \n------------------------------------------------------------\n"
+	$this PrintOutput "Number of Available DICOM Images to process = [ llength $lst ]"
+	
+	
+	set anchorfile [ lindex $lst 0 ]
+	$this PrintOutput "First file = [ file join $dname $anchorfile ]"
+	
+	# ----------------------------------------------------------------------
+	#  Read $anchorfile file and extract key info (e.g. patientid)
+	# ----------------------------------------------------------------------
+	
+	set dcm [ vtkbisDICOMReader New ]
+	$dcm SetFileName $anchorfile
+	$dcm Update
+	
+	set pid [ $dcm GetPatientID ]
+	if { [ string length $pname ] < 2 } {
+	    set pname [ $dcm GetPName ]
+	}
+	if { [ string length $pname ] < 2 } {
+	    set pname "Study"
+	}
+	set pst [ $dcm GetStudy]
+	set pse [ $dcm GetSeries ]
+	set pdt [ $dcm GetDate ]
+	if { $pse == "" } {
+	    set pse 0
+	}
+	$dcm Delete
+	
+	if { $pst != "1" } {
+	    set outname2 [ format "%s_s%03d_s_%s_%s" $pid $pse $pst $pname $pdt  ]
+	} else {
+	    set outname2 [ format "%s_s%03d_%s_%s" $pid $pse $pname $pdt  ]
+	}
+	regsub -all " +" $outname2 "" outname2
+	set outname [ file join $outputdir $outname2 ]
+	$this PrintOutput "NIFTI Output name stem =$outname"
+	
+	
+	
+	# ----------------------------------------------------------------------
+	#  Do Full Blown DICOM Import
+	# ----------------------------------------------------------------------
+	
+	set img [ [ pxitclimage \#auto ] GetThisPointer ]
+	set pxitclimage::forcebioimagesuitecoordinates 0
+	puts stdout "$img LoadDICOM $anchorfile 0 0"
+	$img LoadDICOM $anchorfile 0 0
+	
+	$this PrintOutput "Reading Input Image Done\n"
+	
+	set lst [ $img cget -lastdicomlist ]
+	for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	    set nf [ file tail [ lindex [ lindex $lst $i ] 0 ] ]
+	    lappend convertedlist $nf
+	}
+	$this PrintOutput "Adding [ llength $lst ] files to list of images already converted"
+	
+	$img configure  -lastdicomlist ""
+	
+	set nf [ [ $img GetImage ] GetNumberOfScalarComponents ]
+	set extra "stack3d" 
+	if { $nf > 1 } {
+	    set extra "stack4d"
+	}
+
+	if { $dryrun == 0 && $dodump > 0} {
+	    set txtname "${outname}_${extra}_orig_header.txt"
+	    set eflag "-V"
+	    if { $debugmode == "SIEMENS" } {
+		set eflag "--csa" 
+	    } elseif { $debugmode == "GE" } {
+		set eflag "--pdb"
+	    }
+	    
+	    $this PrintOutput "Executing gdcmdump -i $anchorfile $eflag -p "
+	    catch { file delete $txtname }
+	    catch { exec gdcmdump -i $anchorfile $eflag -p > $txtname  }
+	    if { [ file exists $txtname ] } {
+		$this PrintOutput "\t\t DICOM Dump saved in $txtname"
+	    } else {
+		$this PrintOutput "\t\t DICOM Dump failed"
+	    }
+	}
+
+	if { $outmode == "NONE" } {
+	    set f1 ${outname}_${extra}_orig.nii.gz 
+	    set dm [ [ $img GetImage ] GetDimensions ]
+	    set details "d=$dm, $nf"
+	    if { $dryrun == 0 } {
+		$img Save $f1
+		$this PrintOutput "Output NIFTI image saved in $f1 ($details), file size=[ file size $f1 ]"
+	    } else {
+		$this PrintOutput "Output should have been saved in $f1 ($details)"
+	    }
+	    lappend savednames [ list $f1 $details ]
+
+	} else {
+	    set dm [ [ $img GetImage ] GetDimensions ]
+
+	    set reorient [ bis_newreorientimage \#auto ]
+	    $reorient InitializeFromContainer 0
+	    $reorient SetInput $img
+	    $reorient SetOptionValue orientation $outmode
+	    $reorient Execute
+	    
+	    set finalimg [ [ pxitclimage \#auto ] GetThisPointer ]
+	    $finalimg ShallowCopy [ $reorient GetOutput ]
+	    itcl::delete object $reorient
+	    
+	    set dm2 [ [ $finalimg GetImage ] GetDimensions ]
+
+	    set f2 ${outname}_${extra}_${outmode}.nii.gz
+	    set details "d=$dm -- >$dm2, $nf" 
+	    if { $dryrun == 0 } {
+		$finalimg  Save $f2
+		$this PrintOutput "Reoriented ($outmode) output NIFTI image saved in $f2 ($details), file size=[ file size $f2 ]"
+	    } else {
+		$this PrintOutput "Reoriented ($outmode) output should have been saved in $f2 ($details)"
+	    }
+	    lappend savednames [ list $f2 $details ]
+	    itcl::delete obj $finalimg 
+	}
+	itcl::delete object $img
+    }
+}
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_dicom2nifti [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_displayroimean.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_displayroimean.tcl
new file mode 100644
index 0000000..9701318
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_displayroimean.tcl
@@ -0,0 +1,166 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide  bis_displayroimean  1.0
+package require bis_dualimagealgorithm 1.0
+
+
+itcl::class bis_displayroimean {
+
+	inherit bis_dualimagealgorithm
+
+	 constructor { } {	 $this Initialize  }
+
+	public method Initialize { }
+	public method Execute { }
+	public method GetGUIName    { } { return "Display ROI Mean" }
+	public method CheckInputObjects {}
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_displayroimean::Initialize { } {
+
+	PrintDebug " bis_displayroimean::Initialize" 
+	
+	set inputs { 
+		{ third_image "ROI Mean" pxitclimage "" 80 }     
+	}
+	
+	set options {
+		{ guicmt "Display ROI Mean"  "Note"  comment "Takes in 3 images as input" "The output will be the same size as the functional image"  400 }
+	}
+
+	set defaultsuffix { "_drm" }
+	
+	set scriptname bis_displayroimean 
+	set completionstatus "Debugging"
+	
+	#
+	#document
+	#
+	
+	set description "Display ROI Mean as an image"
+	set description2 "This algorithm requires 3 inputs, one is a brain 4D image, the other is the ROI 3D image for this brain image, the third is the roi mean 4D image. This algorithm returns a 4D image of ROI mean looks like original brain. "
+	set backwardcompatibility ""
+	set authors "isabella.murphy at yale.edu"
+	
+	$this InitializeDualImageAlgorithm
+
+	$this RenameInput 0 "Functional Image"
+	$this RenameInput 1 "VOI Image"
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_displayroimean::Execute {  } {
+
+	PrintDebug "bis_displayroimean::Execute"
+	set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+	if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+	}
+
+   
+	PrintDebug "bis_displayroimean::Execute"
+	
+	set image_in [ $this GetInput ]
+
+	set calMean [ vtkbisDisplayROIMean [ pxvtable::vnewobj ]  ] 
+	$calMean SetInput    [ $image_in GetObject ]	
+	$calMean SetImageROI [ [ $this GetInputObject second_image ] GetObject ]
+	$calMean SetAverageROI [ [ $this GetInputObject third_image ] GetObject ]
+	$this SetFilterCallbacks $calMean "Display ROI Mean"
+	$calMean Update
+
+	set outimage [ $OutputsArray(output_image) GetObject ]
+	$outimage ShallowCopyImage [ $calMean GetOutput ]
+	$outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+	set comment [ format " [ $this GetCommandLine full ]" ]
+	[ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+	$calMean Delete
+
+	return 1
+}
+
+itcl::body bis_displayroimean::CheckInputObjects { } {
+
+
+	set image_in    [ $this GetInput ]
+	set d [ $image_in GetImageSize ]
+	if { $d < 1 } {
+	return 0
+	}
+	
+	set image_in    [ $this GetSecondInput ]
+	set d [ $image_in GetImageSize ]
+	if { $d < 1 } {
+	return 0
+	}
+	
+	
+	set image_in    [ $this GetInputObject third_image ]
+	set d [ $image_in GetImageSize ]
+	if { $d < 1 } {
+	return 0
+	}
+	
+	return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_displayroimean.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+	# this is essentially the main function
+
+	set alg [bis_displayroimean [pxvtable::vnewobj]]
+	$alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_distancemapimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_distancemapimage.tcl
new file mode 100755
index 0000000..73d82b9
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_distancemapimage.tcl
@@ -0,0 +1,138 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_distancemapimage 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+itcl::class bis_distancemapimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Signed DistanceMap" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_distancemapimage::Initialize { } {
+
+    PrintDebug "bis_distancemapimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{  minth "Lower Threshold value" "Low Threshold"   real  1.0 { -100000000.0 100000000.0 }  1 }
+	{  maxth "Upper Threshold value" "High Threshold"  real 200000.0 { -100000000.0 100000000.0 }  -22 }
+	{  invalue "In Threshold value" "In Value"  real  3000.0 { -100000000.0 100000000.0 } 3 }
+	{  outvalue "Out Threshold value" "Out Value"  real 0.0 { -100000000.0 100000000.0 }  -21 }
+	{  radius  "Radius used in dilation filter " "Radius"  integer 1 { 0 10 }  2 }
+    }
+
+    set defaultsuffix { "_dmap" }
+    
+    set scriptname bis_distancemapimage
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Create a distance map from a binarized image"
+    set description2 ""
+    set backwardcompatibility "None"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_distancemapimage::Execute {  } {
+
+    PrintDebug "bis_distancemapimage::Execute"
+
+    set minth   [ $OptionsArray(minth) GetValue ]
+    set maxth   [ $OptionsArray(maxth) GetValue ]
+    set invalue   [ $OptionsArray(invalue) GetValue ]
+    set outvalue   [ $OptionsArray(outvalue) GetValue ]
+    set radius      [ $OptionsArray(radius)    GetValue ]
+
+    set image_in [ $this GetInput ]
+
+    set distancemap  [ vtkjwsSignedDanielssonDistanceMapImageFilter New ]
+    $distancemap SetLowerThreshold $minth
+    $distancemap SetUpperThreshold $maxth
+    $distancemap SetInValue $invalue
+    $distancemap SetOutValue $outvalue
+    $distancemap SetRadius $radius
+    $distancemap SetInput [ $image_in GetImage ]
+    $this SetFilterCallbacks $distancemap "Computing Distancemap from Image"
+    $distancemap Update
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $distancemap GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $distancemap Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_distancemapimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_distancemapimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_dualimagealgorithm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_dualimagealgorithm.tcl
new file mode 100644
index 0000000..d6b22f2
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_dualimagealgorithm.tcl
@@ -0,0 +1,202 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+package provide bis_dualimagealgorithm 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+
+#
+# This is a base class for things like overlay creator etc
+#
+#  container == Transform Viewer status
+#  secondcontainer == Reference Viewer
+#
+
+itcl::class bis_dualimagealgorithm {
+
+    inherit bis_imagetoimagealgorithm
+
+
+    constructor { } { }
+    public method InitializeDualImageAlgorithm { }
+
+    # Get Info about Algorithm for use in GUI Container
+    public method IsDualImage { } { return 1 }
+
+
+    public method UpdateInputsFromContainer { }
+    public method UpdateContainerWithOutput { } 
+
+    # Input and Output Methods
+    public method GetSecondInput { }
+    public method SetSecondInput { img }
+
+    # Set Filenames etc
+    public method  UpdateOutputFilenames { } 
+    public method  CheckInputObjects { } 
+
+
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_dualimagealgorithm::InitializeDualImageAlgorithm { } {
+
+
+    # This assumes that a derived class has done some work here already
+
+    PrintDebug "bis_dualimagealgorithm::Initialize" 
+
+    set tmp $inputs
+    set inputs { 
+	{ second_image   "Second Image" pxitclimage  "" 20 }   
+    }
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend inputs [ lindex $tmp $i ]
+    }
+
+	
+    if { $defaultsuffix == "" } {
+	set defaultsuffix { "_resl" }
+    }
+
+    if { $category == "" } {
+	set category    "Image Processing Dual"
+    }
+    if { $authors == "" } {
+	set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+    }
+    
+    $this InitializeImageToImageAlgorithm
+}
+
+
+# ----------------------------------------------------------
+#
+#  Container Stuff ....
+#
+# ----------------------------------------------------------
+
+itcl::body bis_dualimagealgorithm::SetSecondInput  { img } {
+
+    $this SetInputObject second_image $img
+}
+
+itcl::body bis_dualimagealgorithm::GetSecondInput  { } {
+
+    return [ $this GetInputObject second_image ]
+}
+
+
+
+# ---------------------------------------------------------------------------------
+
+itcl::body bis_dualimagealgorithm::UpdateInputsFromContainer { } {
+
+    if { $containerobject == 0 } {    
+	return 0
+    }
+
+    $this SetInput [ $containerobject GetFirstInputObject ] 
+    $this SetSecondInput [ $containerobject GetSecondInputObject ] 
+    $this UpdateOutputFilenames
+}
+
+itcl::body bis_dualimagealgorithm::UpdateContainerWithOutput { } {
+
+    set img  [ $this GetOutput ] 
+
+    PrintDebug "In Update Container With Output $this, $img [ $img GetDescription ]\n"
+
+
+    if { $containerobject == 0 } {
+	if { $bis_viewer !=0 } {
+	    $bis_viewer SetImage $img
+	}  elseif { $vtk_viewer !=0 } {
+	    $vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+	} 
+    } else {
+	PrintDebug "Calling Container ($this, $containerobject) SetResultsFromObject" 
+	$containerobject SetResultsFromObject $img $this
+    }
+}
+
+# --------------------------------------------------------------------------------------------
+
+itcl::body bis_dualimagealgorithm::UpdateOutputFilenames { } {
+
+    set fname ""
+    if { $fname == "" } {
+	set f(0) [ $InputsArray(input_image) GetFileName ]
+	set f(1) [ $InputsArray(second_image) GetFileName ]
+
+	for { set i 0 } { $i <= 1 } { incr i } {
+	    set l($i) [ ::bis_common::SplitFileNameGZ $f($i) ]
+	    set f($i) [ file tail [ lindex $l($i) 0 ] ]
+	    set ext($i) [ lindex $l($i) 1 ]
+	}
+
+	set fname [ file join [ file dirname $f(0) ] "$f(0)_$f(1)" ]
+    } 
+    
+    set outlist [ $this CreateDefaultOutputFileList $fname ]
+
+    set force 0 ; if { $guimode == "managed" } { set force 1  }
+    $OutputsArray(output_image) SetFileName "[ lindex $outlist 0 ]$ext(0)" $force
+    return 1
+
+}
+
+
+itcl::body bis_dualimagealgorithm::CheckInputObjects { } {
+
+
+    set image_in    [ $this GetInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 2 } {
+	return 0
+    }
+
+    set image_in    [ $this GetSecondInput ]
+    set n [ lindex [ array names InputsArray ] 1 ]
+    set pr [ $InputsArray($n) GetPriority ]
+    if { $pr < 100 } {
+	set image_in [ $InputsArray($n) GetObject ]
+	set d [ $image_in GetImageSize ]
+	if { $d < 2 } {
+	    return 0
+	}
+    }
+    
+    return 1
+
+}
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_dualimagereslicetransformationalgorithm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_dualimagereslicetransformationalgorithm.tcl
new file mode 100644
index 0000000..90c6eec
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_dualimagereslicetransformationalgorithm.tcl
@@ -0,0 +1,119 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagetransformationalgorithm 1.0
+package require bis_resliceimage 1.0
+package provide bis_dualimagereslicetransformationalgorithm 1.0
+
+#
+# blend image
+#
+
+itcl::class bis_dualimagereslicetransformationalgorithm {
+
+    inherit bis_dualimagetransformationalgorithm
+
+     constructor { } {
+	 $this SetUseReslicedImageAsInput 1
+     }
+
+    public method ResliceImageIfNeeded { }
+    public method DeleteResliceAlgorithmIfNeeded { lst }
+
+    public method SetResliceAlgorithm { alg } { set reslice_algorithm $alg    }
+    protected variable reslice_algorithm 0
+
+}
+
+# -----------------------------------------------------------------------------------------
+# A messy routine that uses a pre-specified bis_resliceimage if available ....
+# If transformation is identity skips this altogether
+# ----------------------------------------------------------------------------------------
+itcl::body bis_dualimagereslicetransformationalgorithm::ResliceImageIfNeeded { } {
+
+    set delete_reslice_alg 0
+
+    if {  [ [ $this GetTransformation ] IsIdentity ] == 1 } { 
+	set reslimage [  [ $this GetSecondInput ] GetImage ]
+	
+	scan [ [ [ $this GetInput ] GetImage ] GetDimensions ] "%d %d %d" dx1 dy1 dz1
+	scan [ [ [ $this GetSecondInput ] GetImage ]  GetDimensions ] "%d %d %d" dx2 dy2 dz2
+	
+	if { $dx1==$dx2 && $dy1==$dy2 && $dz1 == $dz2 } {
+	    #	    puts stderr "No need to reslice same size, identity transform"
+	    return $reslimage
+	}
+    }
+
+
+    
+    if { $reslice_algorithm !=0 } {
+	set reslice_alg $reslice_algorithm
+    } else {
+	set reslice_alg [bis_resliceimage [pxvtable::vnewobj]]
+	$reslice_alg InitializeFromContainer $this
+	set delete_reslice_alg 1
+    }
+    $reslice_alg SetInput [ $this GetInput ] 
+    $reslice_alg SetSecondInput [ $this GetSecondInput ] 
+    $reslice_alg SetTransformation [ $this GetTransformation ] 
+    catch { $reslice_alg SetOptionValue interp     [ $OptionsArray(interp) GetValue ] }
+    $reslice_alg Execute
+    
+    if { $delete_reslice_alg == 0 } {
+	$reslice_alg UpdateContainerWithOutput
+    }
+    
+    set reslimage [  [ $reslice_alg GetOutput ] GetImage ]
+
+    if { $delete_reslice_alg == 1 } {
+	return [ list $reslimage  $reslice_alg ]
+    } else {
+	return $reslimage
+    }
+}
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_dualimagereslicetransformationalgorithm::DeleteResliceAlgorithmIfNeeded { lst } {
+
+    if { [ llength $lst ] < 2 } {
+	return 0
+    }
+
+    itcl::delete object [ lindex $lst 1 ] 
+    return 1
+
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_dualimagetransformationalgorithm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_dualimagetransformationalgorithm.tcl
new file mode 100644
index 0000000..930cf77
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_dualimagetransformationalgorithm.tcl
@@ -0,0 +1,243 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+package provide bis_dualimagetransformationalgorithm 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+#
+# This is a base class for things like overlay creator etc
+#
+#  container == Transform Viewer status
+#  secondcontainer == Reference Viewer
+#
+
+itcl::class bis_dualimagetransformationalgorithm {
+
+    inherit bis_imagetoimagealgorithm
+
+    constructor { } { }
+    public method InitializeDualImageTransformationAlgorithm { }
+
+    # Get Info about Algorithm for use in GUI Container
+    public method IsDualImageTransformation { } { return 1 }
+
+
+    public method UpdateInputsFromContainer { }
+    public method UpdateContainerWithOutput { } 
+
+    # Input and Output Methods
+    public method GetSecondInput { }
+    public method SetSecondInput { img }
+
+
+    public method GetTransformation { }
+    public method SetTransformation { tr }
+    public method SetVTKTransformation { tr }
+
+    # Set Filenames etc
+    public method  UpdateOutputFilenames { } 
+    public method  CheckInputObjects { } 
+
+    # Protected Method 
+
+
+    # Flag to set whether to ask for transformation from parent
+    # or already resliced image ... to replace pxitcloverlaytool.tcl
+
+    public method SetUseReslicedImageAsInput { md } { set use_reslicedimage 1 }
+
+    protected variable use_reslicedimage 0
+
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_dualimagetransformationalgorithm::InitializeDualImageTransformationAlgorithm { } {
+
+
+    # This assumes that a derived class has done some work here already
+
+    PrintDebug "bis_dualimagetransformationalgorithm::Initialize" 
+
+    set tmp $inputs
+    set inputs { 
+	{ second_image   "Overlay Image" pxitclimage  ""  20 }   
+	{ transformation "Transformation" pxitcltransform  ""  101 }   
+    }
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend inputs [ lindex $tmp $i ]
+    }
+
+    if { $defaultsuffix == "" } {
+	set defaultsuffix { "_resl" }
+    }
+
+    if { $category == "" } {
+	set category    "Image Processing Dual"
+    }
+    if { $authors == "" } {
+	set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+    }
+    
+    $this InitializeImageToImageAlgorithm
+}
+
+
+# ----------------------------------------------------------
+#
+#  Container Stuff ....
+#
+# ----------------------------------------------------------
+
+itcl::body bis_dualimagetransformationalgorithm::SetSecondInput  { img } {
+
+    $this SetInputObject second_image $img
+}
+
+itcl::body bis_dualimagetransformationalgorithm::GetSecondInput  { } {
+
+    return [ $this GetInputObject second_image ]
+}
+
+
+itcl::body bis_dualimagetransformationalgorithm::SetTransformation  { tr } {
+
+    $this SetInputObject transformation $tr
+}
+
+itcl::body bis_dualimagetransformationalgorithm::SetVTKTransformation  { tr } {
+
+    set t [ $this GetInputObject transformation ]
+    #    puts stderr "$t copying transformation from $tr ([$tr GetClassName])"
+    $t CopyTransformation $tr
+    $t configure -filename [ $tr GetClassName ]
+}
+
+itcl::body bis_dualimagetransformationalgorithm::GetTransformation { } {
+
+    return [ $this GetInputObject transformation ]
+}
+
+
+# ---------------------------------------------------------------------------------
+
+itcl::body bis_dualimagetransformationalgorithm::UpdateInputsFromContainer { } {
+
+    if { $containerobject == 0 } {    
+	return
+    }
+
+    $this SetInput          [ $containerobject GetReferenceImage ] 
+
+    if { $use_reslicedimage == 0 } {
+	$this SetSecondInput    [ $containerobject GetTargetImage ] 
+	$this SetTransformation [ $containerobject GetTransformation ] 
+    } else {
+	#puts stderr "$this Using Resliced Image"
+	$containerobject SetReslicedImageAndTransformation $this
+    }
+	
+	
+    $this UpdateOutputFilenames
+}
+
+itcl::body bis_dualimagetransformationalgorithm::UpdateContainerWithOutput { } {
+
+    set img  [ $this GetOutput ] 
+
+    PrintDebug "In Update Container With Output $this, $img [ $img GetDescription ]\n"
+    
+    if { $containerobject == 0 } {
+	if { $bis_viewer !=0 } {
+	    $bis_viewer SetImage $img
+	}  elseif { $vtk_viewer !=0 } {
+	    $vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+	}
+    } else {
+	PrintDebug "Calling Container ($this, $containerobject) SetResultsFromObject" 
+	$containerobject SetResultsFromObject $img $this
+    }
+}
+
+# --------------------------------------------------------------------------------------------
+
+itcl::body bis_dualimagetransformationalgorithm::UpdateOutputFilenames { } {
+
+    set f1 [ [ $this GetTransformation ] cget -filename ]
+
+    set fname ""
+    if { $fname == "" } {
+	set f(0) [ $InputsArray(input_image) GetFileName ]
+	set f(1) [ $InputsArray(second_image) GetFileName ]
+
+	for { set i 0 } { $i <= 1 } { incr i } {
+	    set l($i) [ ::bis_common::SplitFileNameGZ $f($i) ]
+	    set f($i) [ file tail [ lindex $l($i) 0 ] ]
+	    set ext($i) [ lindex $l($i) 1 ]
+	}
+
+	set fname [ file join [ file dirname $f(0) ] "$f(0)_$f(1)" ]
+    } 
+    
+    set outlist [ $this CreateDefaultOutputFileList $fname ]
+    set force 0; if { $guimode == "managed" } {	set force 1    }
+    catch {     $OutputsArray(output_image) SetFileName "[ lindex $outlist 0 ]$ext(0)" $force }
+    return 1
+
+}
+
+
+itcl::body bis_dualimagetransformationalgorithm::CheckInputObjects { } {
+
+
+    set image_in    [ $this GetInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 2 } {
+	return 0
+    }
+
+    set image_in    [ $this GetSecondInput ]
+    set n [ lindex [ array names InputsArray ] 1 ]
+    set pr [ $InputsArray($n) GetPriority ]
+    if { $pr < 100 } {
+	set image_in [ $InputsArray($n) GetObject ]
+	set d [ $image_in GetImageSize ]
+	if { $d < 2 } {
+	    return 0
+	}
+    }
+
+    return 1
+
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_edgedetectimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_edgedetectimage.tcl
new file mode 100755
index 0000000..cedc8e3
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_edgedetectimage.tcl
@@ -0,0 +1,180 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_edgedetectimage 1.0
+package require bis_imagetoimagealgorithm 1.0
+package require bis_smoothimage 1.0
+
+#
+# smooth image
+#
+
+itcl::class bis_edgedetectimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Edge Detection" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_edgedetectimage::Initialize { } {
+
+    PrintDebug "bis_edgedetectimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ blursigma "kernel size [mm/voxel] of FWHM filter size" "Filter Size"  { real triplescale 200 }    2.0 { 0.0 20.0 }  0 }
+	{ unit      "kernel size unit mm or voxels " "Units" { listofvalues radiobuttons }  mm { mm voxels }   1}
+	{ mode      "Use image gradient or raw intensity" "Mode"  { listofvalues radiobuttons } gradient { intensity gradient }  4 }
+	{ nonmax    "Use Non-Maximal Suppression" "Non-Maximum Suppression"  { boolean checkbutton } 1 { 0 1 }  6 }
+
+    }
+
+    set defaultsuffix { "_edge" }
+    
+    set scriptname bis_edgedetectimage
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Computes an edge map for an image following smoothing"
+    set description2 "first smooths the image than finds the edges "
+    set backwardcompatibility "New"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_edgedetectimage::Execute {  } {
+
+    PrintDebug "bis_edgedetectimage::Execute"
+
+    set blursigma   [ $OptionsArray(blursigma) GetValue ]
+    set unit        [ $OptionsArray(unit) GetValue ]
+    set mode        [ $OptionsArray(mode) GetValue ]
+    set nonmax      [ $OptionsArray(nonmax) GetValue ]
+    set image_in    [ $InputsArray(input_image) GetObject ]
+
+    # Step 1 ... Invoke bis_smoothimage -----
+    set smooth_alg [bis_smoothimage [pxvtable::vnewobj]]
+    $smooth_alg InitializeFromContainer $this
+    $smooth_alg SetInput $image_in
+    $smooth_alg SetOptionValue blursigma $blursigma
+    $smooth_alg SetOptionValue unit      $unit
+    $smooth_alg Execute
+
+    set smimage [  [ $smooth_alg GetOutput ] GetImage ]
+
+    set grad [ vtkImageGradient [ pxvtable::vnewobj ]]
+    $grad HandleBoundariesOn
+    $grad SetInput $smimage
+    set magn [ vtkImageMagnitude [ pxvtable::vnewobj ]]
+    $magn SetInput [ $grad GetOutput ]
+    SetFilterCallbacks $magn "Computing Gradient Magnitude"	
+    
+    
+    if { $nonmax == 0 } {
+	$magn Update
+	[ $OutputsArray(output_image) GetObject ] ShallowCopyImage [ $magn GetOutput ]
+    } else {
+	set sup [ vtkImageNonMaximumSuppression [ pxvtable::vnewobj ]]
+	$sup SetVectorInput [ $grad GetOutput ]
+
+	
+	if { $mode == "gradient" } {
+	    $sup SetMagnitudeInput [ $magn GetOutput ]
+	} else {
+	    set cast [ vtkImageCast [ pxvtable::vnewobj ]]
+	    $cast SetInput  $smimage
+	    $cast SetOutputScalarTypeToDouble
+	    $sup SetMagnitudeInput [ $cast GetOutput ]
+	    $cast Delete
+	} 
+
+	$sup HandleBoundariesOn
+	SetFilterCallbacks $sup "Eliminating NonMaxima"	
+	$sup Update
+	[ $OutputsArray(output_image) GetObject ] ShallowCopyImage [ $sup GetOutput ]
+	$sup Delete
+    }
+
+    $magn Delete
+    $grad Delete
+
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format "BIS::bis_edgedetectimage.tcl blursigma = %.2f unit=%s mode=%s nonmax=%d "\
+		      $blursigma $unit $mode $nonmax ]
+
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    itcl::delete obj $smooth_alg
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_edgedetectimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+    set alg [bis_edgedetectimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_electrodeeditor.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_electrodeeditor.tcl
new file mode 100644
index 0000000..26f1587
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_electrodeeditor.tcl
@@ -0,0 +1,1926 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_electrodeeditor 1.0
+
+# 	$Id: bis_electrodeeditor.tcl,v 1.4 2004/02/17 20:58:26 xenios Exp xenios $	
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    lappend auto_path [ file dirname [ info script ]]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+}
+
+
+
+
+
+# Added some capability
+
+package require pxvtable 1.0
+package require Itcl
+package require Iwidgets 
+package require pxitclbasecontrol 1.0
+package require  labelframe 1.0
+package require  pxitcllistselector  1.0
+package require bis_viewer 1.0
+
+itcl::class bis_electrodeeditor {
+
+    inherit pxitclbasecontrol
+
+    protected variable function_selector 0
+    private variable vtk_viewer 0
+    private variable bis_viewer 0
+    protected variable polymanager 0
+    private variable itclgrid 0
+    private variable electrodemultigrid 0
+    private variable back_electrodemultigrid 0
+    private variable pick_sphere 0
+    private variable pick_sphere_outline 0
+
+    private variable pick_sphere_surface 0
+    private variable pick_sphere_outline_surface 0
+    private variable pick_sphere_outline_surface2 0
+
+
+
+    private variable last_picked_electrode -1
+    private variable grid_listbox 0
+    private variable update_location_button 0
+    private variable location_text 0
+
+    protected variable nomouseinput 0
+    private common   thisparam
+    protected variable initialized 0
+    protected variable fontname "{ fixed 8 }"
+    protected variable last_filename "multigrid.mgrid"
+    protected variable back_last_filename "none"
+
+    public variable batch_selector 0
+
+    private common functional_activations [ list "MotorFunction" "SensoryFunction" "VisualFunction" "LanguageFunction" "AuditoryFunction" "User1Function"  ]
+    private common electrical_activations [ list "SeizureOnset" "SpikesPresent" ]
+    private common other_attributes [ list "ElectrodePresent" ]
+    private common electrode_attributes 0
+
+    private variable last_radiobutton 0
+    public  variable maxelectrodes 12
+
+
+    private variable distance_array 0
+    protected variable datatree 0
+    protected variable xmlpointer 0
+    protected variable filemenu 0
+    
+    constructor { par } {
+	pxitclbasecontrol::constructor $par
+    } {
+	InitializeMultiGridControl
+    }
+
+    private method InitializeMultiGridControl { } 
+
+    public method SetNoMouseInput { } { set nomouseinput 1 }
+    public method Initialize { inpwidg viewer }
+    public method DelayedInitialize { }
+    protected method SetViewer  { viewer }
+    protected method AddToViewer  {  }
+    public method GetViewer  {  } { return $bis_viewer }
+
+
+    # -------------------------------------
+
+    # Create User Interface Stuff
+    # -------------------------------------
+    protected method CreateMenu { menubar }
+    protected method CreateGridPropertySheet { par }
+    protected method CreateElectrodePropertySheet { par }
+    protected method CreatePatientPropertySheet { par }
+
+
+    # --------------------------------------
+    # Update Inteface Stuff
+    # --------------------------------------
+    public method UpdateInterface { }
+    public method UpdateElectrodePropertySheet { }
+    public method UpdateGridPropertySheet { }
+    public method UpdatePatientPropertySheet { }
+    public method UpdateVolumeTrace { }
+
+    public method GetMultiGrid { } { [ return $electrodemultigrid ] }
+    public method GetLastFilename { } { [ return $last_filename ] }
+    # ----------------------------------------
+    # Patient Callbacks
+    # ----------------------------------------
+    public method UpdatePatient { }
+    public method UpdatePatientProperties { }
+    public method SelectElectrodeGrid { index } 
+    public method AddNewElectrodeGrid { }
+    public method DeleteCurrentElectrodeGrid { }
+    # ----------------------------------------
+    # Grid Callbacks
+    # ----------------------------------------
+    public method UpdateElectrodeGridProperties { }
+    public method SelectElectrode { } 
+    public method ElectrodeShowValues { }
+    public method CenterOnElectrode { mode } 
+    public method GridColor { } 
+    public method LabelsColor { } 
+    public method ReorientGrid { mode } 
+    public method PickFunction { }
+    public method PickAndDisplayFunction { }
+    public method ShowValues { }
+    public method AutoWarp { mode }
+
+    # ----------------------------------------
+    # Electrode Callbacks
+    # ----------------------------------------
+    public method UpdateElectrodeProperties { }
+    public method UpdateElectrodeLocationFromText { }
+
+    # ----------------------------------------
+    # Menu/Mouse Callbacks
+    # ----------------------------------------
+    public method HandleClickedPoint { vx pt mouse stat }
+    public method PickElectrode { index args } 
+    public method MovePickedElectrode { x y z} 
+    public method ReleaseElectrodePick { args } 
+
+    public method UndoMoveElectrode { }
+    public method ShowGrids { mode }
+    public method SelectGridsToDisplay { }
+    public method ShowLabels { mode }
+    public method DisableElectrodePropertySheet { }
+    # -----------------------------------
+    # Load and Save Stuff
+    # -----------------------------------
+    public method LoadElectrodeMultiGrid { fname }
+    public method SaveElectrodeMultiGrid { fname }
+    public method AutoSaveMultiGrid { mode }
+    public method EnableAutoSave { }
+    public method ExportAsSurface { fname }
+    public method ExportPickedFunction { fname mode }
+    public method ExportAsPixelImage { fname }
+    
+    # ---------------------------------------------
+    # Tree Hooks
+    # ---------------------------------------------
+    public method TreeEditGrids { land dtree node }
+    public method StoreInTree {  }
+
+}
+# -------------------------------------------------------------------------------------------    
+::itcl::body bis_electrodeeditor::InitializeMultiGridControl { }  {
+
+    global tcl_platform
+    if { $tcl_platform(platform) == "windows" } {
+	set fontname "{ fixed 5 }"
+    } else {
+	set fontname "{ fixed 8 }"
+    }
+
+    set itclgrid  [ [ pxitclelectrodemultigrid \#auto ] GetThisPointer ]
+    set electrodemultigrid [ $itclgrid GetObject ]
+    set back_electrodemultigrid [ vtkpxElectrodeMultiGridSource [ pxvtable::vnewobj ]]
+
+    set distance_array [ vtkFloatArray [ pxvtable::vnewobj ]]
+    $distance_array SetNumberOfTuples 4
+    $distance_array FillComponent 0 -1.0
+    $electrodemultigrid InitializeMultiGrid 1
+
+    set thisparam($this,autosave) 1
+    set thisparam($this,autosaveon) 0
+    set thisparam($this,visible) "none"
+    set thisparam($this,visiblelines) 1
+    set thisparam($this,current_grid) 0 
+    set thisparam($this,current_electrode) 0 
+    set thisparam($this,current_electrode_index) 1
+    set thisparam($this,current_position) "0.0 0.0 0.0"
+    set thisparam($this,auto_pick)  0
+    set thisparam($this,readonly) 2
+    set thisparam($this,showlabels) 0
+    set thisparam($this,showlabelsgap) 1
+    set thisparam($this,pick_frame) 0
+    set thisparam($this,electrodepropertylist) ""
+    set thisparam($this,volume_voi_size) 10
+    set thisparam($this,volume_weighted_voi) 0
+    set thisparam($this,griduniformcolor) 1
+    set electrode_attributes [ concat $functional_activations $electrical_activations $other_attributes ]
+    set thisparam($this,current_electrode_radio) 0
+
+}
+  
+   
+# Sets the input
+::itcl::body bis_electrodeeditor::SetViewer { bviewer } {
+
+    if { $bis_viewer != 0 } {
+	return 0
+    }
+
+    if { [ $bviewer isa bis_viewer ] == 0 } {
+	return 0
+    }
+
+    set bis_viewer $bviewer
+    set vtk_viewer [ $bviewer GetViewer ]
+    set polymanager [ $bis_viewer GetPolygonalDisplayManager ]
+
+}
+
+itcl::body bis_electrodeeditor::AddToViewer  {  } {
+
+    $bis_viewer AddCursorNotifier "$this" "HandleClickedPoint"
+
+    $vtk_viewer SetTraceVolumeVOI $thisparam($this,volume_voi_size)
+    $vtk_viewer SetTraceVolumeWeightedMode $thisparam($this,volume_weighted_voi) 
+
+    set pick_sphere [ vtkpxCrossHairSource [ pxvtable::vnewobj ]]
+    set pick_sphere_outline [ vtkpxCrossHairSource [ pxvtable::vnewobj ]]
+
+    set   pick_sphere_surface [ [ pxitclsurface \#auto ] GetThisPointer ]
+    set   pick_sphere_outline_surface  [ [ pxitclsurface \#auto ] GetThisPointer ]
+    set   pick_sphere_outline_surface2 [ [ pxitclsurface \#auto ] GetThisPointer ]
+
+    $pick_sphere_surface ShallowCopySurface [ $pick_sphere GetOutput ]
+    $pick_sphere_outline_surface ShallowCopySurface [ $pick_sphere GetOutput ]
+    $pick_sphere_outline_surface2 ShallowCopySurface [ $pick_sphere GetOutput ]
+
+
+    $bis_viewer AddPolygonalObject $itclgrid 1 { visible 1 gridfontsize 0 name "ElecEdit_1"}
+    $bis_viewer AddPolygonalObject $pick_sphere_surface 1 { visible 0 color "1 0 0" name "ElecEdit_2" }
+    $bis_viewer AddPolygonalObject $pick_sphere_outline_surface 1 { visible 0 color "1 1 0" name "ElecEdit_3" }
+    $bis_viewer AddPolygonalObject $pick_sphere_outline_surface2 1 { visible 0 color "1 1 0" name "ElecEdit_4" }
+
+    $polymanager UpdateObject $itclgrid
+    $vtk_viewer UpdateDisplay
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::Initialize { inpwidg bviewer } {
+
+    global tcl_platform
+
+    if { $initialized } { return $basewidget } 
+
+    set basewidget [ toplevel $inpwidg ]
+    wm withdraw $basewidget
+    
+    if { $tcl_platform(platform) == "windows" } {
+	wm geometry $basewidget 680x730
+    } else {
+	wm geometry $basewidget 550x600
+    }
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    set initialized 1
+
+    if { $bviewer !=0 } {
+	SetViewer $bviewer
+    }
+    return $basewidget
+
+}
+
+::itcl::body bis_electrodeeditor::DelayedInitialize { } {
+   
+    if { $fullyinitialized == 1 } {
+	return
+    }
+
+    set last_filename ""
+    DisableElectrodePropertySheet
+
+
+    set function_selector [ pxitcllistselector \#auto $basewidget.[ pxvtable::vnewobj ] ]
+    $function_selector configure -singleoutput 1
+
+    set menubar [ menu $basewidget.menubar ]; $basewidget configure -menu $menubar
+    
+    if { $bis_viewer == 0 } {
+	set nt [ panedwindow $basewidget.nt -orient horizontal -showhandle 1 \
+		     -borderwidth 10 -relief raised -sashwidth 4 -sashpad 4 \
+		     -handlesize 5 -handlepad 50  ]
+	pack $nt -side top -expand true -fill both
+	set notebook [ iwidgets::tabnotebook $nt.notebook  -tabpos n   ]
+	set vframe   [ frame $nt.right ]
+	$nt add $notebook -minsize  500
+	$nt add $vframe -minsize 500
+
+	set viewer [ bis_viewer \#auto ]
+	$viewer CreateGUI $vframe
+	$this SetViewer [ $viewer GetThisPointer ]
+    } else {
+	set notebook $basewidget.notebook ; 
+	iwidgets::tabnotebook $notebook  -tabpos n  
+	pack $notebook -side top -expand true -fill both -pady 2 -padx 2
+    }
+    
+
+    $this AddToViewer
+    set bottom [ $notebook add -label  "Patient Info" ]
+    set middle [ $notebook add -label  "Electrode Info" ]
+    
+    frame $middle.left -bg black ; frame $middle.right
+    pack $middle.right -side right -expand false -fill y -padx 2 -pady 2
+    pack $middle.left -side right -expand true -fill both -padx 2 -pady 2
+
+
+    CreateMenu $menubar
+    CreateGridPropertySheet $middle.left
+    CreateElectrodePropertySheet $middle.right
+    CreatePatientPropertySheet $bottom
+
+    set grid [ $electrodemultigrid GetElectrodeGrid 0 ]
+    $grid SetElectrodeSpacing 10.0 10.0
+    $grid SetRadius  2.0
+
+    UpdateInterface
+    $notebook view "Patient Info"
+    DisableElectrodePropertySheet
+
+    set batch_selector [ pxitcllistselector \#auto $basewidget.[ pxvtable::vnewobj ] ]
+    set fullyinitialized 1
+
+    set canvas [ [ $notebook component tabset ] component canvas ];     set l [ AddLogoLabel $canvas ];     pack $l -side right -padx 1 
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::CreateMenu { menubase } {
+
+    #menubutton $menubase.file -text "File"  -menu $menubase.file.m -underline 0
+    set mb [ menu $menubase.filem -tearoff 0 ]
+    #pack $menubase.file  -side left
+    $menubase add cascade -underline 0  -label File -menu $mb
+
+    eval "$mb add command -label Load -command { $this LoadElectrodeMultiGrid \"\" }"
+    eval "$mb add command -label Save -command { $this SaveElectrodeMultiGrid \"\" }"
+    $mb add separator
+    
+    $mb add cascade -underline 0  -label "Export" -menu $mb.cascade1
+    set casc1 [ menu $mb.cascade1 -tearoff 0  ]
+
+    eval "$casc1 add command -label \"Export Values As Text\" -command { $this ExportPickedFunction \"\" 0 }"
+    eval "$casc1 add command -label \"Export as Surface\" -command { $this ExportAsSurface \"\" }"
+    eval "$casc1 add command -label \"Export as Image (One Pixel per electrode)\" -command { $this ExportAsPixelImage \"\"  }"
+    eval "$casc1 add command -label \"Export Picked Function\" -command { $this ExportPickedFunction \"\" dopick }"
+    $mb add separator
+    eval "$mb add command -label Close -command { $this HideWindow }"
+    set filemenu $mb
+
+    #    menubutton $menubase.edit -text "Edit"  -menu $menubase.editm -underline 0
+    #pack $menubase.edit  -side left
+    set mb [ menu $menubase.editm -tearoff 0 ]
+    $menubase add cascade -underline 0  -label Edit -menu $mb
+
+
+    eval "$mb add checkbutton -label \"Auto Save\" -variable [ itcl::scope thisparam($this,autosave) ] -command { $this EnableAutoSave}"
+    $mb add separator
+    eval "$mb add radiobutton -label \"Display Only Mode\" -command { $this DisableElectrodePropertySheet } -value 2 -variable [ itcl::scope thisparam($this,readonly) ]"
+    eval "$mb add radiobutton -label \"Only Edit Attributes\" -command { $this DisableElectrodePropertySheet } -value 1 -variable [ itcl::scope thisparam($this,readonly) ]"
+    if { $nomouseinput == 0 } {
+	eval "$mb add radiobutton -label \"Full Edit Mode\" -command { $this DisableElectrodePropertySheet } -value 0 -variable [ itcl::scope thisparam($this,readonly) ]"
+	$mb add separator
+	eval "$mb add command -label \"Undo Move Electrode\" -command { $this UndoMoveElectrode }"
+    }
+
+    #   menubutton $menubase.display -text "Display"  -menu $menubase.displaym -underline 0
+    #    pack $menubase.display  -side left
+    set mb [ menu $menubase.displaym -tearoff 0 ]
+    $menubase add cascade -underline 0  -label Display -menu $mb
+
+
+    set l [ list current all none some ]
+    set l2 [ list Current All None Some ]
+    for { set i 0 } { $i <=2 } { incr i } {
+	eval "$mb add radiobutton -label \"Show [ lindex $l2 $i]\" -command { $this ShowGrids [ lindex $l $i ] } -value [ lindex $l $i ] -variable [ itcl::scope thisparam($this,visible) ]"
+    }
+    eval "$mb add radiobutton -label \"Show [ lindex $l2 3]\" -command { $this SelectGridsToDisplay } -value [ lindex $l 3 ] -variable [ itcl::scope thisparam($this,visible) ]"
+    $mb add separator 
+    eval "$mb add checkbutton -label \"Show Grid Lines\" -command { $this ShowGrids -1 } -variable [ itcl::scope thisparam($this,visiblelines) ]"
+    eval "$mb add checkbutton -label \"Uniform Color Grids\" -command { $this ShowGrids -1 } -variable [ itcl::scope thisparam($this,griduniformcolor) ]"
+    $mb add separator
+    eval "$mb add command -label \"Pick and Display Image Function\" -command { $this PickAndDisplayFunction }"
+    $mb add separator
+    eval "$mb add command -label \"Show Attributes\" -command { $this ShowValues }"
+
+    set mb [ menu $menubase.gridm -tearoff 0 ]
+    $menubase add cascade -underline 0  -label Grid -menu $mb
+    #    menubutton $menubase.grid -text "Grid"  -menu $menubase.gridm -underline 0
+    #    set mb [ menu $menubase.gridm -tearoff 0 ]
+    #    pack $menubase.grid  -side left
+
+    eval "$mb add command -label \"Grid Color\" -command { $this GridColor }"
+    $mb add separator
+    eval "$mb add command -label \"Grid Flip X\" -command { $this ReorientGrid 1 }"
+    eval "$mb add command -label \"Grid Flip Y\" -command { $this ReorientGrid 2 }"
+    eval "$mb add command -label \"Grid Transpose\" -command { $this ReorientGrid 0 }"
+    $mb add separator
+
+    eval "$mb add command -label \"Auto Warp\" -command { $this AutoWarp 1 }"
+    eval "$mb add command -label \"Undo Auto Warp\" -command { $this AutoWarp 0 }"
+
+    #    menubutton $menubase.labels -text "Labels"  -menu $menubase.labelsm -underline 0
+    #    set mb [ menu $menubase.labelsm -tearoff 0 ]
+    #    pack $menubase.labels  -side left
+
+    set mb [ menu $menubase.labelm -tearoff 0 ]
+    $menubase add cascade -underline 0  -label Labels -menu $mb
+
+    eval "$mb add radiobutton -label \"Label Font 0\" -command  { $this ShowLabels 0  } -variable [ itcl::scope thisparam($this,showlabels) ] -value 0"
+    eval "$mb add radiobutton -label \"Label Font 6\" -command { $this ShowLabels 6  } -variable [ itcl::scope thisparam($this,showlabels) ] -value 6"
+    eval "$mb add radiobutton -label \"Label Font 8\" -command { $this ShowLabels 8  } -variable [ itcl::scope thisparam($this,showlabels) ] -value 8"
+    eval "$mb add radiobutton -label \"Label Font 10\" -command { $this ShowLabels 10 } -variable [ itcl::scope thisparam($this,showlabels) ] -value 10"
+    eval "$mb add radiobutton -label \"Label Font 12\" -command { $this ShowLabels 12 } -variable [ itcl::scope thisparam($this,showlabels) ] -value 12"
+    eval "$mb add radiobutton -label \"Label Font 16\" -command { $this ShowLabels 16 } -variable [ itcl::scope thisparam($this,showlabels) ] -value 16"
+    eval "$mb add radiobutton -label \"Label Font 24\" -command { $this ShowLabels 24 } -variable [ itcl::scope thisparam($this,showlabels) ] -value 24"
+    eval "$mb add radiobutton -label \"Label Font 32\" -command { $this ShowLabels 32 } -variable [ itcl::scope thisparam($this,showlabels) ] -value 32"
+    $mb add separator 
+    eval "$mb add radiobutton -label \"All Labels \" -command  { $this ShowLabels -1 } -variable [ itcl::scope thisparam($this,showlabelsgap) ] -value 0"
+    eval "$mb add radiobutton -label \"Skip 1\" -command { $this ShowLabels -1  } -variable [ itcl::scope thisparam($this,showlabelsgap) ] -value 1"
+    eval "$mb add radiobutton -label \"Skip 2\" -command { $this ShowLabels -1  } -variable [ itcl::scope thisparam($this,showlabelsgap) ] -value 2"
+    eval "$mb add radiobutton -label \"Skip 3\" -command { $this ShowLabels -1 } -variable [ itcl::scope thisparam($this,showlabelsgap) ] -value 3"
+    #    eval "$mb add checkbutton -label \"Label All Electrodes\" -command { $this ShowLabels -1 } -variable [ itcl::scope thisparam($this,showlabelsgap) ]"
+    $mb add separator 
+    eval "$mb add command -label \"Labels Color\" -command { $this LabelsColor }"
+
+    if { $nomouseinput == 0 } {
+	#menubutton $menubase.voltrace -text "Volume Trace"  -menu $menubase.voltracem -underline 0
+	#set mb [ menu $menubase.voltracem -tearoff 0 ]
+	#pack $menubase.voltrace  -side left
+	set mb [ menu $menubase.voltrace -tearoff 0 ]
+	$menubase add cascade -underline 0  -label "Volume Trace" -menu $mb
+
+
+	eval "$mb add checkbutton -label \"Weighted Centroid\" -variable [ itcl::scope thisparam($this,volume_weighted_voi) ] -command { $this UpdateVolumeTrace} "
+	$mb add separator
+	eval "$mb add radiobutton -label \"VOI Size 0\" -command { $this UpdateVolumeTrace} -value  0 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+	eval "$mb add radiobutton -label \"VOI Size 1\" -command { $this UpdateVolumeTrace} -value  1 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+	eval "$mb add radiobutton -label \"VOI Size 5\" -command { $this UpdateVolumeTrace} -value  5 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+	eval "$mb add radiobutton -label \"VOI Size 10\" -command { $this UpdateVolumeTrace} -value 10 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+	eval "$mb add radiobutton -label \"VOI Size 15\" -command { $this UpdateVolumeTrace} -value 15 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+	eval "$mb add radiobutton -label \"VOI Size 20\" -command { $this UpdateVolumeTrace} -value 20 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+	eval "$mb add radiobutton -label \"VOI Size 25\" -command { $this UpdateVolumeTrace} -value 25 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+    }
+
+    
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::PickFunction { } {
+
+    set img [ $vtk_viewer GetImage ]
+    $electrodemultigrid PickFunction $img 
+
+    $electrodemultigrid Modified
+    $polymanager UpdateSameObject $itclgrid 
+    UpdateGridPropertySheet
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::ShowValues { } {
+
+    set l "None"
+    set n [ $electrodemultigrid GetNumberOfValues ]
+    for { set i 0 } { $i < $n } { incr i } {
+	lappend l "Attribute_[expr $i+1]"
+    }
+
+    
+    $batch_selector configure -singleoutput 1
+    $batch_selector Activate $l "" "Select which value index to display (only the first one will be used)" "Select Value Component To Display"
+    set sel [ $batch_selector GetSelectedIndices ]
+
+    if { [ llength $sel ] > 0 } {
+	set newv [ expr [ lindex $sel 0 ] -1 ]
+#	puts stderr "Setting Current Value Index $newv ($sel)"
+	$electrodemultigrid SetCurrentValueIndex $newv
+    } else {
+	$electrodemultigrid SetCurrentValueIndex -1
+    }
+    
+    $electrodemultigrid Modified
+    $electrodemultigrid Update
+    $polymanager UpdateSameObject $itclgrid 
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::PickAndDisplayFunction { } {
+
+    set img [ $vtk_viewer GetImage ]
+    $electrodemultigrid PickFunction $img 
+    $electrodemultigrid SetElectrodeColorsFromFunction [ $vtk_viewer GetLookupTable ]
+    $electrodemultigrid Modified;
+    $polymanager UpdateSameObject $itclgrid 
+}
+# -------------------------------------------------------------------------------------------
+#
+# Pick and Edit Stuff 
+#
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::PickElectrode { index args } {
+
+    if { $thisparam($this,visible) == "none"  } {
+	return 0
+    }
+
+    set editing_mode 1
+    if { $thisparam($this,readonly) > 0 } {
+	if { $index >=0 } {
+	    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $index ]
+	    set thisparam($this,current_electrode) $index
+	    set thisparam($this,current_electrode_index) [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrodeRealIndex $index  ]
+	    set editing_mode 0
+	}
+    } else {
+	if { $last_picked_electrode != - 1 } {
+	    # Some Other Electrode is picked already release this first 
+	    return 0
+	}
+	
+	if { $index == - 1 } {
+	    set index $thisparam($this,current_electrode)
+	}
+    }
+
+    if { $index == -1 } {
+	puts stdout "Nothing to do!"
+	return 0
+    }
+
+    set egrid [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+    scan  [ $egrid GetDimensions ] "%d %d" dimx dimy
+    set dimt [ expr $dimx * $dimy ]
+
+    if { $index >= $dimt } {
+	return 0
+    }
+
+
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $index ]
+
+    if { $editing_mode == 1 } {
+	scan [ $electrode GetPosition ] "%f %f %f" px py pz
+	
+	if { [ llength $args ] == 3 } {
+	    set x [ lindex $args 0 ]
+	    set y [ lindex $args 1 ]
+	    set z [ lindex $args 2 ]
+	    set  r [ expr 2.0 * [ $electrode GetRadius ]]
+	} else {
+	    set x $px
+	    set y $py
+	    set z $pz
+	    set  r [ expr 2.0 * [ $electrode GetRadius ]]
+	}
+
+	
+	$pick_sphere SetPosition $x $y $z
+	$pick_sphere SetLength $r
+	$pick_sphere_outline SetPosition $x $y $z
+	$pick_sphere_outline SetLength $r
+	
+	scan [ $electrode GetColor ] "%f %f %f" cx cy cz
+	
+	$pick_sphere Update
+	$pick_sphere_outline Update
+
+	$pick_sphere_surface ShallowCopySurface [ $pick_sphere GetOutput ]
+	$pick_sphere_outline_surface ShallowCopySurface [ $pick_sphere GetOutput ]
+	$pick_sphere_outline_surface2 ShallowCopySurface [ $pick_sphere GetOutput ]
+
+	eval "$polymanager UpdateSameObject $pick_sphere_surface { visible 1 } 0"
+	eval "$polymanager UpdateSameObject $pick_sphere_outline_surface { visible 1 color \"$cz $cy $cz\" } 0"
+	eval "$polymanager UpdateSameObject $pick_sphere_outline_surface2 { visible 1 color \"$cz $cy $cz\" } 0"
+
+	$polymanager UpdateSameObject $itclgrid 
+	
+	set last_picked_electrode $index
+	set thisparam($this,current_electrode_index) [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrodeRealIndex $index ]
+	set thisparam($this,current_electrode) $last_picked_electrode
+	$thisparam($this,pick_frame) configure -bg red
+    }
+    $electrode StoreColorInColorName 
+    UpdateElectrodePropertySheet
+    
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::MovePickedElectrode { x y z }  {
+
+    if { $last_picked_electrode == - 1 } {
+	#	puts stderr "Nothing to move ...."
+	return 0
+    }
+
+#    puts stderr "Moving to $x $y $z"
+
+    $pick_sphere SetPosition $x $y $z
+    $pick_sphere Update
+    $pick_sphere_outline SetPosition $x $y $z
+    $pick_sphere_outline Update
+
+    $pick_sphere_surface ShallowCopySurface [ $pick_sphere GetOutput ]
+    $pick_sphere_outline_surface ShallowCopySurface [ $pick_sphere GetOutput ]
+    $pick_sphere_outline_surface2 ShallowCopySurface [ $pick_sphere GetOutput ]
+
+
+    set thisparam($this,current_position) [ format "%.2f %.2f %.2f " $x $y $z ]
+
+    [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetNeighborDistances $thisparam($this,current_electrode) $distance_array $x $y $z
+    for { set i 0 } { $i <=3 } { incr i } {
+	set thisparam($this,current_distance_$i) [ format "%.2f" [ $distance_array GetComponent $i 0 ]]
+    }
+
+    $polymanager UpdateSameObject $pick_sphere_surface "" 0
+    $polymanager UpdateSameObject $pick_sphere_outline_surface "" 0
+    $polymanager UpdateSameObject $pick_sphere_outline_surface2 "" 1
+    
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::ReleaseElectrodePick { args } {
+
+    if { $last_picked_electrode == -1 } {
+	return 0
+    }
+    
+    # Hide Pick Actors
+    # ----------------
+    
+    eval "$polymanager UpdateSameObject $pick_sphere_surface { visible 0 } 0"
+    eval "$polymanager UpdateSameObject $pick_sphere_outline_surface { visible 0 opacity 1.0 dispmode Wireframe } 0"
+    eval "$polymanager UpdateSameObject $pick_sphere_outline_surface2 { visible 0 opacity 0.5 dispmode Filled} 0"
+
+    $thisparam($this,pick_frame) configure -bg gray
+
+    if { [ llength $args  ] == 3 } {
+
+	set x [ lindex $args 0 ]
+	set y [ lindex $args 1 ]
+	set z [ lindex $args 2 ]
+
+	set egrid [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+	scan  [ $egrid GetDimensions ] "%d %d" dimx dimy
+	set dimt [ expr $dimx * $dimy ]
+	
+	if { $last_picked_electrode < $dimt } {
+	    
+	    set electrode [ $egrid GetElectrode $last_picked_electrode ]
+	    
+	    # Do undo stuff and then set position
+	    scan [ $electrode GetPosition ] "%f %f %f " ox oy oz ; $electrode SetPreviousPosition $ox $oy $oz
+	    $electrode SetPosition $x $y $z
+	    
+	    $egrid Modified
+	    $electrodemultigrid Modified;	
+	}
+    }
+    
+    $polymanager UpdateSameObject $itclgrid 
+    UpdateElectrodePropertySheet
+    set last_picked_electrode -1
+    
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::HandleClickedPoint { vx pt mode stat } {
+
+    set a [ wm state $basewidget  ]
+    if { $a != "normal" } {
+	return 0
+    }
+
+    if { $thisparam($this,visible) == "none" } {
+	return 0
+    }
+
+    if { [ llength $pt ] !=3 } { return 0 }
+    scan $pt  "%f %f %f" x y z
+    if { $x == -1.0 && $y == -1.0 && $z == -1.0 } { return 0 }
+    set ok 0
+    
+#    puts stderr "x=$x, y=$y, z=$z, mode=$mode, stat=$stat"
+    if { $mode == -1 && $stat == -1 } {
+	return 0
+    }
+
+    if { $mode == 1 } {
+	if { $stat == 0 } {
+	    if { $last_picked_electrode == -1  } {
+		set index [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] FindClosestElectrodeIndex $x $y $z ]
+
+		if { $index >=0 } { 
+		    set ok [ PickElectrode $index $x $y $z  ]
+		}
+	    }
+	} 
+    }
+
+    if { $stat == 1 && $last_picked_electrode !=-1 } {
+	
+	set ok [ MovePickedElectrode $x $y $z ]
+	
+    } elseif { $stat == 2 && $last_picked_electrode !=-1 } {
+	
+	set ok [ ReleaseElectrodePick $x $y $z  ]
+	
+    }
+
+#    puts stderr "Last=$last_picked_electrode"
+    return $ok
+}
+# ---------------------------------------------------------------------------------------------
+# Callback Stuff
+# ---------------------------------------------------------------------------------------------
+itcl::body bis_electrodeeditor::TreeEditGrids { land dtree node } {
+
+
+    if { [ $land isa pxitclelectrodemultigrid  ] == 0 } {
+	return 0
+    }
+
+    set old $datatree
+
+    set datatree $dtree
+    set xmlpointer $node
+
+    $itclgrid Copy $land
+    set electrodemultigrid [ $itclgrid GetObject ]
+
+    set last_filename ""
+    set f [ $node GetAttribute Title ]
+    SetTitle "(DataTree) Electrode Editor node=$f"
+    DisableElectrodePropertySheet
+    UpdateInterface
+    SelectElectrodeGrid 0
+
+ #   if { $old == 0 } {
+#	$filemenu add separator
+#	eval "$filemenu add command -label \"Store in Tree\" -command { $this StoreInTree }"
+#    }
+}
+# ------------------------------------------------------------------------
+itcl::body bis_electrodeeditor::StoreInTree {  } {
+
+    if { $datatree ==0 } {
+	return
+    }
+
+#    $datatree UpdateEditedSurface $xmlpointer $itclgrid
+
+
+}
+# ------------------------------------------------------------------------------
+itcl::body bis_electrodeeditor::LoadElectrodeMultiGrid { fname } {
+
+    if { $electrodemultigrid == 0 } {
+	return 0
+    }
+
+    if { $fname == "" } {
+	set typelist { 
+	    {"Electrode Grid Files" {".mgrid*" } }
+	    {"All Files" {*}}
+	}
+	
+	set f1 $last_filename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+
+	set fname [tk_getOpenFile -title "Load Electrode Multi Grid File" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    set ok [ $electrodemultigrid Load $fname ]
+    if { $ok > 0 } {
+	set last_filename $fname
+	SetTitle "Electrode Editor [ file tail $last_filename]"
+	DisableElectrodePropertySheet
+	UpdateInterface
+	SelectElectrodeGrid 0
+    }
+
+    return $ok
+}
+
+# -------------------------------------------------------------------------------------------
+itcl::body bis_electrodeeditor::SaveElectrodeMultiGrid { fname } {
+
+    if { $electrodemultigrid == 0 } {
+	return 0
+    }
+
+    if { $fname == "" } {
+	set typelist { 
+	    {"Electrode Grid Files" {".mgrid*" } }
+	    {"All Files" {*}}
+	}
+	
+	set f1 $last_filename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname [tk_getSaveFile -title "Save Electrode Multi Grid File" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    UpdatePatient
+ 
+    set ok [ $electrodemultigrid Save $fname ]
+
+    if { $ok > 0 } {
+	set last_filename $fname
+	SetTitle "Electrode Control [ file tail $last_filename]"
+    }
+    
+    return $ok
+}
+
+
+# -------------------------------------------------------------------------------------------
+itcl::body bis_electrodeeditor::EnableAutoSave { } {
+
+    if { $thisparam($this,autosave) == 0 } {
+	set thisparam($this,autosaveon) 0
+    } else {
+	AutoSaveMultiGrid once
+    }
+}
+
+itcl::body bis_electrodeeditor::AutoSaveMultiGrid { mode } {
+
+    if { $thisparam($this,autosaveon) == 1 && $mode =="once" } {
+	return 0
+    }
+
+    if { $thisparam($this,autosave) == 0 } {
+	set thisparam($this,autosaveon) 0
+	return 0
+    }
+
+    if { $last_filename == "" } {
+	set last_filename "autosave"
+    }
+
+    set l_filename "[ file root $last_filename]_autosave.mgrid"
+    
+    UpdatePatient
+
+    if { $thisparam($this,readonly) != 2 } {
+	set ok [ $electrodemultigrid Save $l_filename ]
+    } else {
+	set ok 1
+    }
+
+    if { $thisparam($this,autosaveon) == 0 } {
+	set thisparam($this,autosaveon) 1
+    }
+    
+    eval "after 30000  $this AutoSaveMultiGrid timer"
+
+    return $ok
+}
+# -------------------------------------------------------------------------------------------
+itcl::body bis_electrodeeditor::ExportAsSurface { fname } {
+
+    if { $electrodemultigrid == 0 } {
+	return 0
+    }
+
+    if { $fname == "" } {
+	set typelist { 
+	    {"VTK Surface Files" {".vtk" } }
+	    {"All Files" {*}}
+	}
+	
+	set l_filename "[ file root $last_filename].vtk"
+	set f1 $l_filename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname [tk_getSaveFile -title "Save Electrode Multi-Grid As Surface" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    $electrodemultigrid Update; 
+    #$thisparam($this,label_mapper) Modified
+    set w [ vtkPolyDataWriter [ pxvtable::vnewobj ]]
+    $w SetInput [ $electrodemultigrid GetOutput ]
+    $w SetFileName $fname
+    $w Write
+    $w Delete
+}
+# -------------------------------------------------------------------------------------------
+itcl::body bis_electrodeeditor::ExportPickedFunction { fname mode } {
+
+    if { $electrodemultigrid == 0 } {
+	return 0
+    }
+
+    if { $fname == "" } {
+	set typelist { 
+	    {"Text Files" {".txt" } }
+	    {"All Files" {*}}
+	}
+	
+	set l_filename "[ file root $last_filename].txt"
+	set f1 $l_filename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname [tk_getSaveFile -title "Export picked function in text file" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    if { $mode == "dopick" } {
+	$this PickFunction
+    }
+
+    set ok [ $electrodemultigrid ExportValues $fname " " " " " "  ]
+    if { $ok == 0 } { 
+	::pxtclutil::Warning "Failed to export picked function in $fname"
+    }
+}
+# -------------------------------------------------------------------------------------------
+# Export as Pixel Image
+# -------------------------------------------------------------------------------------------
+itcl::body bis_electrodeeditor::ExportAsPixelImage { fname  } {
+
+    if { $electrodemultigrid == 0 } {
+	return 0
+    }
+
+    set l [ list "Location" "Epilepsy" "Any Function" "Motor Function" "Sensory Function" "Visual Function" "Language Function" "Auditory Function" "User1 Function"  ]
+    set n [ $electrodemultigrid GetNumberOfValues ]
+    for { set i 0 } { $i < $n } { incr i } {
+	lappend l "Attribute_[expr $i+1]"
+    }
+    
+    $function_selector configure -singleoutput 0
+    $function_selector Activate $l "Epilepsy" "The selected function will be used to generate the output label for the output pixel-image" "Select Output Label"
+    
+    set mode [ $function_selector GetSelectedIndices ]
+
+    #    puts stderr "Mode = $mode"
+    set numcomp [ llength $mode ]
+
+    if { $numcomp == 0 } {
+	return 0
+    }
+    
+    set arr [ vtkShortArray [ pxvtable::vnewobj ]]
+    $arr SetNumberOfTuples $numcomp
+    $arr FillComponent 0 0
+    
+    for { set i 0 } { $i < $numcomp } { incr i } {
+
+	set md [ lindex $mode $i ]
+	if { $md > 8 } { 
+	    set md [ expr $md + 11 ]
+	}
+	$arr SetComponent $i 0 $md
+    }
+    
+    set typelist { 
+	{"Analyze Image Files" {".hdr" } }
+	{"All Files" {*}}
+    }
+    
+    set l_filename "[ file root $last_filename].hdr"
+    set f1 $l_filename
+    set f1path [ file dirname $f1 ]
+    set f1tail [ file tail    $f1 ]
+    
+    set fname [tk_getSaveFile -title "Save Electrode Multi-Grid As Labeled Image" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    
+    if { [ string length $fname ] < 1 } {
+	$arr Delete
+	return 0
+    }
+
+    
+    WatchOn
+     update idletasks
+    set img [ $electrodemultigrid CreateSinglePixelImage $arr [ $vtk_viewer GetImage ] ]
+    set ana [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+    $ana SetInput $img
+    $ana SetOrientation [ $vtk_viewer GetOrientation ]
+    $ana Save $fname
+    $ana Delete
+    $img Delete
+    $arr Delete
+    WatchOff
+    
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::UpdateInterface { } {
+
+    UpdatePatientPropertySheet
+    UpdateGridPropertySheet
+    UpdateElectrodePropertySheet
+    AutoSaveMultiGrid once
+}
+
+::itcl::body bis_electrodeeditor::UpdatePatient { } {
+    UpdateElectrodePropertySheet
+    UpdateElectrodeGridProperties 
+    UpdatePatientProperties
+}
+
+
+::itcl::body bis_electrodeeditor::UpdateVolumeTrace { } {
+
+    catch { $vtk_viewer SetTraceVolumeVOI $thisparam($this,volume_voi_size) }
+    catch { $vtk_viewer SetTraceVolumeWeightedMode $thisparam($this,volume_weighted_voi) }
+    
+}
+
+# -------------------------------------------------------------------------------------------
+#
+#           Electrode Property Sheet
+#
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::CreateElectrodePropertySheet { par } {
+    
+    label $par.0 -text "Electrode Properties" -bg black -fg white 
+    pack $par.0 -side top -expand f -fill x -pady 2 -padx 2
+    
+    frame $par.1 ; pack $par.1 -side top
+    label $par.1.l -text "Grid/Electrode:"
+    entry $par.1.e -width 6 -textvariable [ itcl::scope thisparam($this,current_grid) ] -state disabled
+    label $par.1.l2 -text "/"
+    entry $par.1.e2 -width 6 -textvariable [ itcl::scope thisparam($this,current_electrode_index) ] -state disabled
+    pack $par.1.l $par.1.e $par.1.l2 $par.1.e2 -side left -expand f -fill x -pady 1
+
+    frame $par.11 ; pack $par.11 -side top
+    label $par.11.l -text "Position:"
+    entry $par.11.e -width 20 -textvariable [ itcl::scope thisparam($this,current_position) ] -state disabled
+    eval "button $par.11.f -text Upd -command { $this UpdateElectrodeLocationFromText } -state disabled"
+    set update_location_button $par.11.f
+    set location_text $par.11.e
+    pack $par.11.l $par.11.e $par.11.f -side left -expand f -fill x -pady 1
+
+    set w [frame $par.12 -bg darkgray ] ; pack $par.12 -side top -padx 2 -pady 2
+    set thisparam($this,pick_frame) $w
+
+
+    label $w.lab -text "Distances"
+    for { set i 0 } { $i <=3 } { incr i } {
+	entry $w.$i -width 8 -textvariable [ itcl::scope thisparam($this,current_distance_$i) ] -state disabled
+    }
+    
+    grid $w.lab -row 1 -column 1
+    grid $w.0 -row 1 -column 0
+    grid $w.1 -row 1 -column 2
+    grid $w.2 -row 0 -column 1
+    grid $w.3 -row 2 -column 1
+       
+
+    checkbutton $par.15 -text "Electrode Enabled" -variable [ itcl::scope thisparam($this,ElectrodePresent) ]  
+    lappend thisparam($this,electrodepropertylist) $par.15
+    eval "$par.15 configure -command  { $this UpdateElectrodeProperties }"
+    pack  $par.15 -side top -expand f -fill x -ipadx 2 -ipady 2
+
+    set thisparam(this,electrode_color) [ frame $par.17 -height 10 -bg white ]
+    pack $par.17 -side top -expand f -fill x -pady 5 -padx 10
+
+    set base  [ LabelFrame:create $par.center -text "Locate Viewer"]
+    pack $par.center -side top -expand f -fill x -pady 2
+    
+    eval "button $base.1 -text \"Cross Hairs\" -command { $this CenterOnElectrode 0 }"
+    eval "button $base.2 -text \"Clip Tight\" -command { $this CenterOnElectrode 1 }"
+    eval "button $base.3 -text \"Clip Wide\" -command { $this CenterOnElectrode 2 }"
+    pack $base.1 $base.2 $base.3 -side left -expand f -fill x -padx 2
+
+    set base  [ LabelFrame:create $par.2 -text "Functional Attributes"]
+    pack $par.2 -side top -expand f -fill x
+
+    for { set i 0 } { $i < [ expr [ llength $functional_activations ]/2 ] } { incr i } {
+	frame $base.$i ; pack $base.$i -side top -expand f -fill x -pady 0
+
+	for { set j 0 } { $j <=1 } { incr j } {
+	    set index [ expr $i * 2 + $j ]
+	    set l [ lindex $functional_activations $index ]
+	    set m [ string length $l ]
+	    set n [ string range $l 0 [ expr $m - 9 ]]
+	    eval "checkbutton $base.$i.m$n -text $n -variable [ itcl::scope thisparam($this,$l) ] -width 10"
+	    eval "$base.$i.m$n configure -command  { $this UpdateElectrodeProperties }"
+	    pack $base.$i.m$n -side left -expand f -fill x
+	    lappend thisparam($this,electrodepropertylist) $base.$i.m$n
+	}
+    }
+	
+    set base  [ LabelFrame:create $par.3 -text "Electrical Attributes"]
+    pack $par.3 -side top -expand f -fill x
+    checkbutton $base.1 -text "Seizure Onset" -variable [ itcl::scope thisparam($this,SeizureOnset) ] -width 10
+    checkbutton $base.2 -text "Spikes Present" -variable [ itcl::scope thisparam($this,SpikesPresent) ] -width 10
+    eval "$base.1 configure -command  { $this UpdateElectrodeProperties }"
+    eval "$base.2 configure -command  { $this UpdateElectrodeProperties }"
+    pack $base.1 $base.2 -side top -expand f -fill x
+    lappend thisparam($this,electrodepropertylist) $base.1
+    lappend thisparam($this,electrodepropertylist) $base.2
+
+    if { $nomouseinput == 0 } {
+	set base  [ LabelFrame:create $par.4 -text "Editing"]
+	pack $par.4 -side top -pady 2 -expand f -fill x
+	eval "checkbutton $base.auto -text \"Button Pick\"  -variable [ itcl::scope thisparam($this,auto_pick) ] -command { $this ReleaseElectrodePick }"
+	frame $base.p ; 
+	pack $base.auto $base.p -side top -expand t -fill x -padx 2
+	eval "button $base.p.set -text \"Pick Current\" -command { $this PickElectrode -1 }"
+	eval "button $base.p.can -text \"Release\" -command { $this ReleaseElectrodePick }"
+	pack $base.p.set $base.p.can  -side left -expand f -fill x -pady 2
+    }
+
+    eval "button $par.5 -text \"Show Values\" -command { $this ElectrodeShowValues }"
+    
+    pack $par.5  -side bottom -expand f -fill x -pady 2
+   
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::ElectrodeShowValues { } {
+
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $thisparam($this,current_electrode) ]
+    set values [ $electrode GetValues ]
+    set l "Electode $thisparam($this,current_electrode_index)\n"
+    if { [ $values GetNumberOfTuples ] == 0 } {
+	set l "Electrode has no values"
+    } else {
+	for { set i 0 } { $i < [ $values GetNumberOfTuples ] } { incr i } {
+	    lappend l "Comp [ expr $i +1 ]: [ $values GetComponent $i 0 ]"
+	}
+    }
+
+    ::pxtclutil::Info $l 
+
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::CenterOnElectrode { mode } {
+
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $thisparam($this,current_electrode) ]
+    scan [ $electrode GetPosition ] "%f %f %f" p(0) p(1) p(2)
+    set img [ $vtk_viewer GetImage ]
+    
+
+    $vtk_viewer SetScaledCoordinates $p(0) $p(1) $p(2)
+
+    if { $mode > 0  } {
+	# Clip Stuff Also
+
+	set camera [ [ [ $vtk_viewer GetRenderer 3 ] GetRenderer ] GetActiveCamera ]
+
+	scan [ $camera GetPosition ]  "%f %f %f" c(0) c(1) c(2)
+	scan [ $camera GetFocalPoint ] "%f %f %f" f(0) f(1) f(2)
+
+
+	for { set i 0 } { $i<=2} { incr i } {
+	    set d($i) [ expr $f($i) - $c($i) ]
+	    set p($i) [ expr $p($i) - $c($i) ]
+	}
+	set magn [ expr sqrt($d(0)*$d(0) + $d(1)*$d(1) + $d(2)*$d(2)) ]
+	
+	set dist 0.0
+	for { set i 0 } { $i<=2} { incr i } {
+	    set d($i) [ expr $d($i) / $magn ]
+	    set dist [ expr $dist +  $p($i)*$d($i) ]
+	}
+
+	set sp 5.0
+	if { $mode == 2 } {
+	    set sp 20.0
+	}
+
+	$camera SetClippingRange [ expr $dist - $sp ] [ expr $dist+$sp]
+	$polymanager UpdateSameObject $itclgrid 
+	    
+    }
+
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::UpdateElectrodeLocationFromText { } {
+    
+    if { $thisparam($this,readonly)  != 0 } {
+	return
+    }
+
+    set img [ $vtk_viewer GetImage ]
+    set dim [ $img GetDimensions ]
+    set spa [ $img GetSpacing ]
+    if { [ lindex $dim 0 ] < 2 } {
+	return
+    }
+
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $thisparam($this,current_electrode) ]
+
+    set lst $thisparam($this,current_position)
+    if { [ llength $lst ] != 3  } {
+	scan [ $electrode GetPosition ] "%f %f %f" px py pz
+	set thisparam($this,current_position) [ format "%.2f %.2f %.2f " $px $py $pz ]
+	return 
+    }
+
+    for { set i 0 } { $i <= 2 } { incr i } {
+	set x($i) [ lindex $lst $i ]
+	if { $x($i) < -1 } {
+	    set x($i) -1.0
+	} elseif { $x($i) > [ expr [ lindex $dim $i ]*[lindex $spa $i ] ] } {
+	    set x($i) [ expr [ lindex $dim $i ]*[lindex $spa $i ] ]
+	}
+    }
+    
+
+    scan [ $electrode GetPosition ] "%f %f %f " ox oy oz ; 
+    $electrode SetPreviousPosition $ox $oy $oz
+    $electrode SetPosition $x(0) $x(1) $x(2)
+    scan [ $electrode GetPosition ] "%f %f %f" px py pz
+    set thisparam($this,current_position) [ format "%.2f %.2f %.2f " $px $py $pz ]
+
+
+    [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] Modified
+    $electrodemultigrid Modified;	
+#$thisparam($this,label_mapper) Modified
+
+    $this ReleaseElectrodePick
+    $polymanager UpdateSameObject $itclgrid 
+}
+
+# -------------------------------------------------------------------------------------------
+
+::itcl::body bis_electrodeeditor::UpdateElectrodeProperties { } {
+
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $thisparam($this,current_electrode) ]
+
+    for { set i 0 } { $i < [ llength $electrode_attributes ] } { incr i } {
+	set nm [ lindex $electrode_attributes $i ]
+	$electrode Set$nm $thisparam($this,$nm)
+    }
+    
+    [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] Modified
+    $electrodemultigrid Modified
+    [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] Modified
+    $electrodemultigrid Update; 
+    #$thisparam($this,label_mapper) Modified
+
+    $electrode StoreColorInColorName
+    $thisparam(this,electrode_color) configure -bg [ $electrode GetColorName ]
+
+    set width [ lindex [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetDimensions ] 0 ]
+    set row [ expr round(floor($thisparam($this,current_electrode) / $width)) ]
+    set col [ expr round($thisparam($this,current_electrode)  - $width * $row) ]
+    set nm $thisparam($this,radio_${col}_${row})
+    $nm configure -bg [ $electrode GetColorName ] 
+
+    if { [ $electrode GetElectrodePresent ] == 0  } { 
+	ReleaseElectrodePick
+    }
+
+    $polymanager UpdateSameObject $itclgrid 
+    
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::UpdateElectrodePropertySheet { } {
+
+
+    set dim  [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetDimensions ]
+    set numelect [ expr [ lindex $dim 0 ] * [ lindex $dim 1 ]]
+
+    if { $thisparam($this,current_electrode) >= $numelect } {
+	set thisparam($this,current_electrode) 0
+    }
+
+
+    set thisparam($this,current_electrode_radio) $thisparam($this,current_electrode)
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $thisparam($this,current_electrode) ]
+    set thisparam($this,current_electrode_index) [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrodeRealIndex $thisparam($this,current_electrode) ]
+
+
+    for { set i 0 } { $i < [ llength $electrode_attributes ] } { incr i } {
+	set nm [ lindex $electrode_attributes $i ]
+	set thisparam($this,$nm) [ $electrode Get$nm  ]
+    }
+   
+    scan [ $electrode GetPosition ] "%f %f %f" px py pz
+    set thisparam($this,current_position) [ format "%.2f %.2f %.2f " $px $py $pz ]
+
+    [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetNeighborDistances $thisparam($this,current_electrode) $distance_array
+    for { set i 0 } { $i <=3 } { incr i } {
+	set thisparam($this,current_distance_$i) [ format "%.2f" [ $distance_array GetComponent $i 0 ]]
+    }
+
+    $electrode StoreColorInColorName
+    $thisparam(this,electrode_color) configure -bg [ $electrode GetColorName ]
+
+    set width [ lindex [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetDimensions ] 0 ]
+    set row [ expr round(floor($thisparam($this,current_electrode) / $width)) ]
+    set col [ expr round($thisparam($this,current_electrode)  - $width * $row) ]
+
+    set nms $thisparam($this,radio_${col}_${row})
+    $nms configure -relief ridge -highlightbackground black
+
+    if { $last_radiobutton != 0  && $last_radiobutton != $nms } {
+	$last_radiobutton configure -relief flat -highlightbackground gray
+    }
+    set last_radiobutton $nms
+    
+    
+}
+
+
+::itcl::body bis_electrodeeditor::UndoMoveElectrode { } {
+
+
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $thisparam($this,current_electrode) ]
+    scan [ $electrode GetPreviousPosition ] "%f %f %f " ox oy oz ; $electrode SetPreviousPosition $ox $oy $oz
+    $electrode SetPosition $ox $oy $oz
+    set thisparam($this,current_position) [ format "%.2f %.2f %.2f " $ox $oy $oz ]
+    [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] Modified
+    $electrodemultigrid Modified
+    $polymanager UpdateSameObject $itclgrid 
+}
+
+
+# -------------------------------------------------------------------------------------------
+#
+#    Grid Property Sheet
+#
+# -------------------------------------------------------------------------------------------
+
+::itcl::body bis_electrodeeditor::CreateGridPropertySheet { basepar } {
+    
+    set wp  [ LabelFrame:create $basepar.1 -text "Grid Properties"]
+    pack $basepar.1 -side top -expand true -fill x -pady 2 -padx 2
+
+
+    checkbutton $wp.vis -text "Display Grid " -variable [ itcl::scope thisparam($this,current_grid_visible) ]  
+    eval "$wp.vis configure -command  { $this UpdateElectrodeGridProperties  }"
+    pack $wp.vis -side top -padx 5 -pady 2
+
+    set i 0
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l -text "Grid Name:"
+    entry $w.e -width 35 -textvariable [ itcl::scope thisparam($this,current_grid_name) ] -relief sunken
+    pack $w.l $w.e -side left -expand false -fill x -anchor w
+
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l1 -text "Dimensions:"
+    entry $w.e1 -width 3 -textvariable [ itcl::scope thisparam($this,current_grid_dimx) ] -relief sunken
+    entry $w.e2 -width 3 -textvariable [ itcl::scope thisparam($this,current_grid_dimy) ] -relief sunken
+    pack $w.l1 $w.e1 $w.e2 -side left -expand false -fill x -anchor w
+
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l3 -text "Nominal Spacing (mm):"
+    entry $w.e3 -width 3 -textvariable [ itcl::scope thisparam($this,current_grid_spx) ] -relief sunken
+    entry $w.e4 -width 3 -textvariable [ itcl::scope thisparam($this,current_grid_spy) ] -relief sunken
+    pack $w.l3 $w.e3 $w.e4 -side left -expand false -fill x -anchor w
+
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l -text "Electrode Type:"
+    tk_optionMenu $w.opt [ itcl::scope thisparam($this,current_grid_electrodetype) ] "Sphere" "Disc"
+    pack $w.l $w.opt  -side left -expand false  -anchor ne 
+
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l1 -text "Radius/Thick (mm):"
+    entry $w.e1 -width 5 -textvariable [ itcl::scope thisparam($this,current_grid_radius) ] -relief sunken
+    entry $w.e2 -width 5 -textvariable [ itcl::scope thisparam($this,current_grid_thickness) ] -relief sunken
+    pack  $w.l1 $w.e1 $w.e2 -side left -expand false -fill x -anchor w -padx 0
+
+
+    eval "button $wp.bot -text \"Update Grid \" -command { $this UpdateElectrodeGridProperties }"
+    pack $wp.bot -side bottom -expand f -fill x -anchor ne -pady 4 -padx 4    
+
+
+    set wp  [ LabelFrame:create $basepar.2 -text "Electrode Arrangment" ]
+    pack $basepar.2 -side top -expand true -fill both -pady 2 -padx 2
+    label $wp.lab -text "Electrode Leads Here!" -bg black -fg white
+    pack $wp.lab -side top -expand f -fill x 
+
+
+
+    set index 0
+
+	    
+    for { set j 0 } { $j < $maxelectrodes } { incr j } {
+	set w [ frame $wp.$j ] ; pack $w -side top -expand f -fill x -padx 0 -pady 0
+	for { set i 0 } { $i < $maxelectrodes } { incr i } {
+	    set nm radio_${i}_${j}
+	    eval "radiobutton $w.$index -value $index -variable [ itcl::scope thisparam($this,current_electrode_radio) ] -text \"\" -command { $this SelectElectrode } -width 0 -font $fontname -highlightbackground gray -highlightthickness 3"
+	    set thisparam($this,$nm) $w.$index	    
+	    pack  $thisparam($this,$nm) -side left -padx 0 -pady 0 -ipadx 0 -ipady 0 -expand f 
+	    incr index
+	}
+    }
+
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::UpdateElectrodeGridProperties { } {
+
+    set elec_grid  [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+
+    $elec_grid SetGridName $thisparam($this,current_grid_name) 
+    $elec_grid SetElectrodeSpacing $thisparam($this,current_grid_spx) $thisparam($this,current_grid_spy)
+    $elec_grid SetElectrodeTypeTo$thisparam($this,current_grid_electrodetype)
+    $elec_grid SetRadius $thisparam($this,current_grid_radius) 
+    $elec_grid SetThickness $thisparam($this,current_grid_thickness) 
+    $elec_grid SetVisible  $thisparam($this,current_grid_visible) 
+
+    set dimensions [ $elec_grid GetDimensions ]
+    set dimx [ lindex $dimensions 0 ]
+    set dimy [ lindex $dimensions 1 ]
+
+    if { $dimx != $thisparam($this,current_grid_dimx)  || $thisparam($this,current_grid_dimy)!=$dimy } {
+	set ok [ ::pxtclutil::Question "Changing the Grid Dimensions will result in losing all information about the current grid. Are you sure?" ]
+	if { $ok == 1 } {
+	    $elec_grid SetGridName $thisparam($this,current_grid_name) 
+	    #"grid_$thisparam($this,current_grid_dimx)_$thisparam($this,current_grid_dimy)"
+	    $elec_grid InitializeGrid $thisparam($this,current_grid_dimx) $thisparam($this,current_grid_dimy)
+	    $electrodemultigrid Modified
+	    set thisparam($this,current_electrode) 0
+	    UpdateInterface
+	    $polymanager UpdateSameObject $itclgrid 
+	    return
+	}
+    }
+
+    set thisparam($this,current_grid_dimx) $dimx
+    set thisparam($this,current_grid_dimy) $dimy
+    
+
+    $electrodemultigrid Modified
+    UpdatePatientPropertySheet
+    $polymanager UpdateSameObject $itclgrid 
+}
+
+
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::SelectElectrode { } {
+
+    set thisparam($this,current_electrode) $thisparam($this,current_electrode_radio) 
+    UpdateElectrodePropertySheet
+    ReleaseElectrodePick
+    if {  $thisparam($this,auto_pick) == 1 } {
+	PickElectrode -1
+    }
+}
+    
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::UpdateGridPropertySheet { } {
+    
+    set elec_grid [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+    set dimensions [ $elec_grid GetDimensions ]
+    set dimx [ lindex $dimensions 0 ]
+    set dimy [ lindex $dimensions 1 ]
+
+    set thisparam($this,current_grid_name) [ $elec_grid GetGridName ]
+    set thisparam($this,current_grid_dimx) $dimx
+    set thisparam($this,current_grid_dimy) $dimy
+    set thisparam($this,current_grid_spx)  [ lindex [ $elec_grid GetElectrodeSpacing ] 0 ]
+    set thisparam($this,current_grid_spy)  [ lindex [ $elec_grid GetElectrodeSpacing ] 1 ]
+    set thisparam($this,current_grid_visible) [ $elec_grid GetVisible ]
+
+    set thisparam($this,current_grid_electrodetype) "Sphere"
+    if { [ $elec_grid GetElectrodeType ] == 1 } {
+	set thisparam($this,current_grid_electrodetype) "Disc"
+    }
+
+    set thisparam($this,current_grid_radius) [ $elec_grid GetRadius ]
+    set thisparam($this,current_grid_thickness) [ $elec_grid GetThickness ]
+
+    set index 0
+    for { set j 0 } { $j < $maxelectrodes } { incr j } {
+	for { set i 0 } { $i < $maxelectrodes } { incr i } {
+	    #	    puts stderr "Updating Electrode $i $j"
+	    set nm $thisparam($this,radio_${i}_${j})
+	    if {$i >= $dimx || $j >= $dimy } {
+		$nm configure -value -1
+		$nm configure -state disabled -width 0 -bg darkgray -font { fixed 1 }
+		$nm configure -relief sunken
+	    } else {
+		set electrode [ $elec_grid GetElectrode $i $j ]
+		$electrode StoreColorInColorName 
+		set cl [ $electrode GetColorName ]
+		$nm configure -bg $cl
+		#		puts stderr "$nm configure -bg $cl"
+		$nm configure -state normal
+		$nm configure -value $index
+		#$nm configure -text $index
+		$nm configure -state normal -width 0 -font $fontname
+		$nm configure -relief flat -highlightbackground gray
+		incr index
+	    }
+	}
+    }
+
+    if { [ $elec_grid GetShowLabelsGap ] != $thisparam($this,showlabelsgap) } {
+	$elec_grid SetShowLabelsGap $thisparam($this,showlabelsgap)
+	$elec_grid Modified
+	$electrodemultigrid Modified
+#	$thisparam($this,label_mapper) Modified
+    }
+
+    UpdateElectrodePropertySheet
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::CreatePatientPropertySheet { basepar } {
+
+    set wp  [ LabelFrame:create $basepar.1 -text "Patient Information"]
+    pack $basepar.1 -side top -expand true -fill x -pady 2 -padx 2
+
+    
+    set i 0
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l -text "Description:"
+    entry $w.e -width 45 -textvariable [ itcl::scope thisparam($this,current_patient_description) ] -relief sunken
+    pack $w.l  -side left -expand false -fill x -anchor w
+    pack $w.e -side left -expand true -fill x -anchor e
+
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l -text "Comment:"
+    entry $w.e -width 45 -textvariable [ itcl::scope thisparam($this,current_patient_comment) ] -relief sunken
+    pack $w.l  -side left -expand false -fill x -anchor w
+    pack $w.e -side left -expand true  -fill x -anchor e
+
+
+
+    set wp  [ LabelFrame:create $basepar.2 -text "Grid Information"]
+    pack $basepar.2 -side top -expand true -fill x -pady 2 -padx 2
+    
+    set grid_listbox [ iwidgets::scrolledlistbox $wp.left -vscrollmode dynamic -hscrollmode none -selectmode single -labelpos nw -visibleitems 10x40 ]
+    eval "$grid_listbox configure -selectioncommand { $this SelectElectrodeGrid -1 }"
+    $grid_listbox configure -selectmode single
+    
+    frame $wp.right
+
+    eval "button $wp.right.add -text \"Add New Grid\" -command { $this AddNewElectrodeGrid }"
+    eval "button $wp.right.del -text \"Delete  Grid\" -command { $this DeleteCurrentElectrodeGrid }"
+    pack $wp.right.add $wp.right.del -side top -anchor se -padx 2 -pady 4
+
+    pack $wp.right -side right -expand false -fill y
+    pack $wp.left -side left -expand true -fill both -padx 2 -pady 2
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::SelectElectrodeGrid { index } {
+    
+    set ng [ $electrodemultigrid GetNumberOfGrids ] 
+    if { $index < 0 } {
+	set index [ $grid_listbox curselection ]
+    } else {
+	if { $index >= $ng  } {
+	    return 0
+	}
+	
+	$grid_listbox selection clear 0 end
+	$grid_listbox selection set $index $index
+    }
+
+    set thisparam($this,current_grid) $index
+    UpdateGridPropertySheet
+    set thisparam($this,current_electrode_radio)  0
+    SelectElectrode
+
+    if { $thisparam($this,visible) == "current" } {
+	ShowGrids current
+    }
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::AddNewElectrodeGrid { } {
+
+    set a [ $electrodemultigrid GetNumberOfGrids ] 
+    $electrodemultigrid InsertNewGrid
+    set grid [ $electrodemultigrid GetElectrodeGrid $a ]
+    $grid SetElectrodeSpacing 10.0 10.0
+    $grid SetRadius  2.0
+    set nm [ $grid GetGridName ]
+    set nq [ expr $a + 1 ]
+    $grid_listbox insert end "${nq}.${nm}"
+    SelectElectrodeGrid  $a
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::DeleteCurrentElectrodeGrid { } {
+
+    set a [ $electrodemultigrid GetNumberOfGrids ] 
+    if { $a == 1 } {
+	::pxtclutil::Warning "Cannot delete grid as this is the only grid in the patient!"
+	return
+    }
+
+    set ok [ ::pxtclutil::Question "This will delete all information about the current grid! Are you sure?" ]
+    if { $ok == 1 } {
+	$electrodemultigrid DeleteGrid $thisparam($this,current_grid) 
+	UpdatePatientPropertySheet
+	SelectElectrodeGrid 0
+    }
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::UpdatePatientPropertySheet { } {
+
+    set thisparam($this,current_patient_description) [ $electrodemultigrid GetDescription ]
+    set thisparam($this,current_patient_comment)     [ $electrodemultigrid GetComment ]
+
+    $grid_listbox clear 
+
+    set ng [ $electrodemultigrid GetNumberOfGrids ] 
+    for { set i 0 } { $i < $ng } { incr i } {
+	
+	set grid [ $electrodemultigrid GetElectrodeGrid $i ]
+	set nm [ $grid GetGridName ]
+	set nq [ expr $i + 1 ]
+	$grid_listbox insert end "${nq}.${nm}"
+    }
+
+    $grid_listbox selection clear 0 end
+    $grid_listbox selection set $thisparam($this,current_grid) $thisparam($this,current_grid)
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::UpdatePatientProperties { } {
+
+    $electrodemultigrid SetDescription $thisparam($this,current_patient_description) 
+    $electrodemultigrid SetComment     $thisparam($this,current_patient_comment)     
+
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::GridColor { } {
+
+    set egrid [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+    set c [ $egrid GetColor ]
+    set newcolor [ pxtclutil::ColorBox "Set Grid [ $egrid GetGridName ] display color" $c $basewidget ]
+    $egrid SetColor [ lindex $newcolor 0 ] [ lindex $newcolor 1 ] [ lindex $newcolor 2 ]
+    $egrid Modified
+    $egrid Update
+    $electrodemultigrid Modified
+    UpdateGridPropertySheet
+    $polymanager UpdateSameObject $itclgrid 
+}
+
+::itcl::body bis_electrodeeditor::LabelsColor { } {
+
+    $polymanager SetCurrentObject $itclgrid
+    $polymanager SetColor
+}
+
+
+::itcl::body bis_electrodeeditor::ReorientGrid { mode } {
+
+    if { $mode == 0 }  {
+	set ok [ ::pxtclutil::Question "This will transpose current grid! Are you sure?" ]
+    } elseif { $mode == 1 } {
+	set ok [ ::pxtclutil::Question "This will perform a row flip on your current grid! Are you sure?" ]
+    } else {
+	set ok [ ::pxtclutil::Question "This will perform a column flip on your current grid! Are you sure?" ]
+    }
+
+    if { $ok == 0 } {
+	return 
+    }
+
+    set egrid [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+    if { $mode == 0 } {
+	$egrid TransposeGrid
+    } elseif { $mode == 1 } {
+	puts stdout "Flipping X"
+	$egrid GridFlipX
+    } elseif { $mode == 2 } {
+	puts stdout "Flipping Y"
+	$egrid GridFlipY
+    }
+
+    $electrodemultigrid Modified;	
+    $polymanager UpdateSameObject $itclgrid 
+    SelectElectrodeGrid -1
+    return
+}
+
+
+::itcl::body bis_electrodeeditor::DisableElectrodePropertySheet { } {
+
+    set md ""
+
+    if { $thisparam($this,readonly) == 2 } {
+	SetTitle "<Read-Only> Electrode Editor [ file tail $last_filename]"
+	set flag 0
+	set bflag 0
+    } elseif { $thisparam($this,readonly) == 1 } {
+	SetTitle "<Attribute-Only> Electrode Editor [ file tail $last_filename]"
+	set flag 1
+	set bflag 0
+    } else {
+	SetTitle "Electrode Editor [ file tail $last_filename]"
+	set flag 1
+	set bflag 1
+    }
+
+    if { $flag == 1 } {
+	EnableUI $thisparam($this,electrodepropertylist)
+    } else {
+	DisableUI $thisparam($this,electrodepropertylist)
+    }
+
+    if { $update_location_button !=0 } {
+	if { $bflag == 0 } {
+	    $update_location_button configure -state disabled
+	    $location_text configure -state disabled
+	} else {
+	    $update_location_button configure -state normal
+	    $location_text configure -state normal
+	}
+    }
+
+
+}
+
+::itcl::body bis_electrodeeditor::ShowLabels { mode } {
+
+    if { $mode == -1 } {
+	set mode $thisparam($this,showlabels)
+    }
+    set gap $thisparam($this,showlabelsgap)
+    eval "$polymanager UpdateSameObject $itclgrid { gridfontgap $gap gridfontsize $mode } 1"
+}
+
+::itcl::body bis_electrodeeditor::ShowGrids { mode } {
+
+
+    if { $mode != -1 } {
+	set thisparam($this,visible) $mode
+    } else {
+	set mode thisparam($this,visible)
+    }
+
+    set showlines $thisparam($this,visiblelines) 
+    if { $mode == "none" } {
+	$this ReleaseElectrodePick
+	$polymanager UpdateSameObject $itclgrid { visible 0 dispgridlist "" } 1
+	return
+    }
+
+    set flag 1
+    if { $mode == "current" } {
+	set flag 0
+    } 
+    
+    set ng [ $electrodemultigrid GetNumberOfGrids ] 
+    set vlist ""
+    set nlist [ $itclgrid GetGridNamesList ]
+
+#    puts stderr "Ng=$ng, nlist=$nlist"
+
+    for { set i 0 } { $i < $ng } { incr i } {
+	set grid [ $electrodemultigrid GetElectrodeGrid $i ]
+	#$grid SetJustShowElectrodes $justelectrodes
+	$grid SetColorMode [ expr 1-$thisparam($this,griduniformcolor) ]
+	
+	set nm  [ $grid GetGridName ]
+	set nq  [ expr $i + 1 ]
+
+	if { $i == $thisparam($this,current_grid) && $mode == "current" } {
+	    lappend vlist [ lindex $nlist $i ]
+	} elseif { $flag == 1 } {
+	    lappend vlist [ lindex $nlist $i ]
+	}
+    }
+    eval "$polymanager UpdateSameObject $itclgrid { visible 1 dispgridlist \"$vlist\"  gridshowlines $showlines } 1"
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::SelectGridsToDisplay { } {
+
+    set l ""
+    set ng [ $electrodemultigrid GetNumberOfGrids ] 
+    set nlist [ $itclgrid GetGridNamesList ]
+#    puts stderr "nlist=$nlist"
+    for { set i 0 } { $i < $ng } { incr i } {
+	set grid [ $electrodemultigrid GetElectrodeGrid $i ]
+	scan    [ $grid GetDimensions ] "%d %d" dimx dimy
+	lappend l  "[ lindex $nlist $i ] , ($dimx x $dimy)"
+    }
+
+    $batch_selector Activate $l "" "Select which electrode grids to display" "Select Grids To Display"
+    set indices [ $batch_selector GetSelectedIndices ]
+
+    set showlines $thisparam($this,visiblelines) 
+#    puts stdout "Indices = $indices"
+    set vlist ""
+    set ng [ $electrodemultigrid GetNumberOfGrids ] 
+    set cv 0
+    for { set i 0 } { $i < $ng } { incr i } {
+	set grid [ $electrodemultigrid GetElectrodeGrid $i ]
+	#	$grid SetJustShowElectrodes $justelectrodes
+	
+	if { [  lsearch -exact $indices  $i  ] != -1 } {
+	    lappend vlist [ lindex $nlist $i ] 
+	    if { $i == $thisparam($this,current_grid) } {
+		set cv 1
+
+	    }
+	}
+    }
+    set thisparam($this,current_grid_visible) $cv
+    ReleaseElectrodePick
+    set thisparam($this,visible) "some"
+    set mode $thisparam($this,showlabels)
+    set gap $thisparam($this,showlabelsgap)
+    eval "$polymanager UpdateSameObject $itclgrid { visible 1 dispgridlist \"$vlist\" gridshowlines $showlines gridfontgap $gap gridfontsize $mode} 1"
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_electrodeeditor::AutoWarp { mode } {
+    
+    if { $mode == 1 } {
+	set egrid [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+	$back_electrodemultigrid Copy $electrodemultigrid
+	set back_last_filename $last_filename 
+	set ok [ $egrid AutoWarp ]
+	if { $ok == 1 } {
+	    $egrid Modified
+	    $electrodemultigrid Modified;	
+	    $polymanager UpdateSameObject $itclgrid 
+	    SelectElectrodeGrid -1
+	} else {
+	    ::pxtclutil::Warning "Cannot do autowarp as less than three electrodes have been modified. You need to manually position at least three electrodes before autowarp can work!\n"
+	}
+    } elseif { $back_last_filename != "none" } {
+	$electrodemultigrid Copy $back_electrodemultigrid
+	set last_filename $back_last_filename 
+	SetTitle "Electrode Control [ file tail $last_filename]"
+	UpdateInterface
+	$polymanager UpdateSameObject $itclgrid 
+    }
+}
+
+# -------------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    package require vtkpxcontrib
+    wm withdraw .
+
+
+    set tp .[ pxvtable::vnewobj ] 
+
+    set electrode_editor [ [ bis_electrodeeditor \#auto 0 ]  GetThisPointer ]
+    $electrode_editor Initialize $tp 0
+    wm geometry $tp 1024x800
+    $electrode_editor DelayedInitialize
+
+    if { [ llength $argv ] > 0 } {
+	set img [ pxitclimage \#auto ]
+	$img Load [ lindex $argv 0 ]
+	[ $electrode_editor GetViewer ]  SetImage $img
+	[ $electrode_editor GetViewer ]  SetImageColormapMode 0
+	itcl::delete object $img
+    }
+
+
+    if { [ llength $argv ] > 1 } {
+	set ok [ $electrode_editor LoadElectrodeMultiGrid [ lindex $argv 1 ] ]
+    }
+    $electrode_editor ShowGrids "all"
+}
+
+
+    
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_exponentialfitimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_exponentialfitimage.tcl
new file mode 100755
index 0000000..93651d9
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_exponentialfitimage.tcl
@@ -0,0 +1,217 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_exponentialfitimage 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+itcl::class bis_exponentialfitimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Exponentia Fit Image" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_exponentialfitimage::Initialize { } {
+
+    PrintDebug "bis_exponentialfitimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ mode  "Gen t-values automatically or use list" "Use List"  boolean 0 { 0 1 } 1 }
+	{ t0    "First t-value" "T0" real  15.0   { 0.0 50000.0 }  1 }
+	{ dt    "T-spacing" "DT" real  15.0   { 0.0 50000.0 }  2 }
+	{ tlist  "List of t-values" "T-List"  string "" { "" }  3 }
+	{ t2  "Output T2 Instead of R2" "Output T2" boolean   0  { 0 1 } 25 }
+	{ reverse  "Reverse Order of T-times" "Reverse t-list" boolean   0  { 0 1 } 30 }
+	{ maxt2    "Maximum t2 value to output" "Max T2" real  500.0   { 0.0 10000.0 }  -102 }
+	{ reciprocalt    "Use 1/t instead of t -- useful for fitting exp(- t_i*T) instead of exp(-T/t_i) sequences" "ReciprocalT" boolean 0   { 0 1 }  -105 }
+	{ threshold    "Do not fit if intensity is below this * max" "Threshold" real  0.05   { 0.0 1.0 }  -103 }
+    }
+
+    set defaultsuffix { "_t2" }
+
+    set outputs {
+	{ density_image "Density Image"  pxitclimage  "" 120 }
+    }
+    
+    set scriptname bis_exponentialfitimage
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Computes a T2-fit (or other decaying exponential) from a 4D image"
+    set description2 ""
+    set backwardcompatibility "Reimplemented from pxitclexpfit.tcl"
+    set category "Image Processing-4D"
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_exponentialfitimage::Execute {  } {
+
+    PrintDebug "bis_exponentialfitimage::Execute"
+
+    set mode      [ $OptionsArray(mode) GetValue ]
+    set t0        [ $OptionsArray(t0)      GetValue ]
+    set dt        [ $OptionsArray(dt)    GetValue ]
+    set tlist     [ $OptionsArray(tlist)    GetValue ]
+    set t2        [ $OptionsArray(t2)    GetValue ]
+    set maxt2     [ $OptionsArray(maxt2)    GetValue ]
+    set reverse   [ $OptionsArray(reverse)    GetValue ]
+    set reciprocal [ $OptionsArray(reciprocalt) GetValue ]
+    set threshold [ $OptionsArray(threshold)    GetValue ]
+    set image_in  [ $this GetInput ]
+
+
+    set nc [ [ $image_in GetImage ]  GetNumberOfScalarComponents ]
+    if { $nc < 3 } {
+	set errormessage "Not enough frames for for mono-exponential fitting $nc <3 "
+	return 0
+    }
+
+    set fl [ vtkFloatArray [ pxvtable::vnewobj ]]
+    $fl SetNumberOfComponents 1
+    $fl SetNumberOfTuples $nc
+
+    if { $reverse == 1 } {
+	set t0 [ expr $t0 + $dt * ($nc -1 ) ]
+	set dt [ expr -1.0 *$dt  ]
+	if { [ llength $tlist ] > 1  } {
+	    set old $tlist
+	    set tlist ""
+	    set i [ llength $old ]
+	    while {$i > 0 } {
+		lappend tlist [lindex $old [incr i -1] ]
+	    }
+	}
+    }
+    
+
+
+    if { $mode == 0 } {
+	for { set i 0 } { $i < $nc } { incr i } {
+	    if { $reciprocal == 0 } {
+		$fl SetComponent $i 0 [ expr $t0 + $i * $dt ] 
+	    } else {
+		$fl SetComponent $i 0 [ expr 1.0/($t0 + $i * $dt) ]
+	    }
+	}
+    } else {
+	if { [ llength $tlist ] < $nc } {
+	    set errormessage "Not Enough t-values specified in list"
+	    $fl Delete
+	    return 0
+	}
+	for { set i 0 } { $i < $nc } { incr i } {
+	    if { $reciprocal == 0 } {
+		$fl SetComponent $i 0 [ lindex $tlist $i ]
+	    } else {
+		$fl SetComponent $i 0 [ expr 1.0/[ lindex $tlist $i ] ]
+	    }
+	}
+    }
+
+    puts -nonewline stdout "TES (reciprocal=$reciprocal) = "
+    for { set i 0 } { $i < $nc } { incr i } {
+	puts -nonewline stdout "$i->[ $fl GetComponent $i 0 ] "
+    }
+    puts stdout ""
+    
+    set fit [ vtkpxLogExponentialFit  [ pxvtable::vnewobj ]]
+    $fit SetInput [ $image_in GetImage ] 
+    $fit SetEchoTrain $fl
+    $fit SetMaxT2Value $maxt2
+    $fit SetIntensityThreshold $threshold
+
+    $this SetFilterCallbacks $fit "Mono-exponential fitting"
+    $fit Update
+
+    set densityimage [ $OutputsArray(density_image) GetObject ] 
+    $densityimage  ShallowCopyImage [ $fit GetDensityMap ]
+    $densityimage  CopyImageHeader  [ $image_in GetImageHeader ]
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    if { $t2 > 0 } { 
+	$outimage  ShallowCopyImage [ $fit GetOutput ]
+    } else {
+	$outimage  ShallowCopyImage [ $fit GetR2Map ]
+    }
+
+    puts -nonewline stdout "Density range [ [ [ [ $densityimage GetImage ] GetPointData ] GetScalars ] GetRange ]\t"
+    puts stdout "T2/R2 range [ [ [ [ $outimage GetImage ] GetPointData ] GetScalars ] GetRange ]"
+
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    $fit Delete
+
+    $fl Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_exponentialfitimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_exponentialfitimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_exponentialfitt1.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_exponentialfitt1.tcl
new file mode 100755
index 0000000..57f6105
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_exponentialfitt1.tcl
@@ -0,0 +1,217 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_exponentialfitt1 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+itcl::class bis_exponentialfitt1 {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Exponentia Fit T1" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_exponentialfitt1::Initialize { } {
+
+    PrintDebug "bis_exponentialfitt1::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ mode  "Gen t-values automatically or use list" "Use List"  boolean 1 { 0 1 } -120 }
+	{ t0    "First t-value" "T0" real  100.0   { 0.0 50000.0 }  -121 }
+	{ dt    "T-spacing" "DT" real  100.0   { 0.0 50000.0 }  -122 }
+	{ alpha  "Estimate alpha parameter (else alpha=1.0)" "Estimate Alpha" boolean   1  { 0 1 } 4 }
+	{ tlist  "List of TR-values" "TR-List"  string "" { "" }  3 }
+	{ t1  "Output T1 Instead of R1" "Output T1" boolean   1  { 0 1 } 25 }
+	{ reverse  "Reverse Order of T-times" "Reverse t-list" boolean   0  { 0 1 } 30 }
+	{ maxt1    "Maximum t2 value to output" "Max T1" real  500.0   { 0.0 10000.0 }  -102 }
+	{ threshold    "Do not fit if intensity is below this * max" "Threshold" real  0.05   { 0.0 1.0 }  -103 }
+    }
+
+    set defaultsuffix { "_t1" }
+
+    set outputs {
+	{ density_image "Density Image"  pxitclimage  "" 120 }
+	{ alpha_image "Alpha Image"  pxitclimage  "" 121 }
+    }
+    
+    set scriptname bis_exponentialfitt1
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Computes a T1-fit from a 4D image"
+    set description2 ""
+    set backwardcompatibility ""
+    set category "Image Processing-4D"
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_exponentialfitt1::Execute {  } {
+
+    PrintDebug "bis_exponentialfitt1::Execute"
+
+    set mode      [ $OptionsArray(mode) GetValue ]
+    set t0        [ $OptionsArray(t0)      GetValue ]
+    set dt        [ $OptionsArray(dt)    GetValue ]
+    set tlist     [ $OptionsArray(tlist)    GetValue ]
+    set t1        [ $OptionsArray(t1)    GetValue ]
+    set maxt1     [ $OptionsArray(maxt1)    GetValue ]
+    set reverse   [ $OptionsArray(reverse)    GetValue ]
+    set threshold [ $OptionsArray(threshold)    GetValue ]
+    set alpha [ $OptionsArray(alpha)    GetValue ]
+    set image_in  [ $this GetInput ]
+
+
+    set nc [ [ $image_in GetImage ]  GetNumberOfScalarComponents ]
+    if { $nc < ( 3 + $alpha) } {
+	set errormessage "Not enough frames for for mono-exponential fitting $nc < [ expr 3 + $alpha] "
+	return 0
+    }
+
+    set fl [ vtkFloatArray [ pxvtable::vnewobj ]]
+    $fl SetNumberOfComponents 1
+    $fl SetNumberOfTuples $nc
+
+    if { $reverse == 1 } {
+	set t0 [ expr $t0 + $dt * ($nc -1 ) ]
+	set dt [ expr -1.0 *$dt  ]
+	if { [ llength $tlist ] > 1  } {
+	    set old $tlist
+	    set tlist ""
+	    set i [ llength $old ]
+	    while {$i > 0 } {
+		lappend tlist [lindex $old [incr i -1] ]
+	    }
+	}
+    }
+    
+
+
+    if { $mode == 0 } {
+	for { set i 0 } { $i < $nc } { incr i } {
+	    $fl SetComponent $i 0 [ expr $t0 + $i * $dt ] 
+	}
+    } else {
+	if { [ llength $tlist ] < $nc } {
+	    set errormessage "Not Enough t-values specified in list"
+	    $fl Delete
+	    return 0
+	}
+	for { set i 0 } { $i < $nc } { incr i } {
+	    $fl SetComponent $i 0 [ lindex $tlist $i ]
+	} 
+    }
+
+    puts -nonewline stdout "TRs  = "
+    for { set i 0 } { $i < $nc } { incr i } {
+	puts -nonewline stdout "$i->[ $fl GetComponent $i 0 ] "
+    }
+    puts stdout ""
+    
+    set fit [ vtkpxExponentialFitT1  [ pxvtable::vnewobj ]]
+    $fit SetInput [ $image_in GetImage ] 
+    $fit SetRelaxationTimes $fl
+    $fit SetMaxT1Value $maxt1
+    $fit SetIntensityThreshold $threshold
+    $fit SetThreeParameterFit $alpha
+
+    $this SetFilterCallbacks $fit "Exponential Fit for T1"
+    $fit Update
+
+    set densityimage [ $OutputsArray(density_image) GetObject ] 
+    $densityimage  ShallowCopyImage [ $fit GetDensityMap ]
+    $densityimage  CopyImageHeader  [ $image_in GetImageHeader ]
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    if { $t1 > 0 } { 
+	$outimage  ShallowCopyImage [ $fit GetOutput ]
+    } else {
+	$outimage  ShallowCopyImage [ $fit GetR1Map ]
+    }
+
+    if { $alpha > 0  } {
+	set aimage [ $OutputsArray(alpha_image) GetObject ]
+	$aimage  ShallowCopyImage [ $fit GetAlphaMap ]
+	$aimage  CopyImageHeader  [ $image_in GetImageHeader ]
+	puts -nonewline stdout "Alpha range [ [ [ [ $aimage GetImage ] GetPointData ] GetScalars ] GetRange ]\t"
+    }
+
+    puts -nonewline stdout "Density range [ [ [ [ $densityimage GetImage ] GetPointData ] GetScalars ] GetRange ]\t"
+    puts stdout "T1/R1 range [ [ [ [ $outimage GetImage ] GetPointData ] GetScalars ] GetRange ]"
+
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    $fit Delete
+    $fl Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_exponentialfitt1.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_exponentialfitt1 [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_extractobjectmap.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_extractobjectmap.tcl
new file mode 100755
index 0000000..099bc60
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_extractobjectmap.tcl
@@ -0,0 +1,139 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetosurfacealgorithm 1.0                
+package provide bis_extractobjectmap 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_extractobjectmap {
+
+    inherit bis_imagetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Extract Objectmap" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_extractobjectmap::Initialize { } {
+
+    PrintDebug "bis_extractobjectmap::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ lowthreshold "Low Threshold" "Low Threshold"  { real triplescale 100 }    0.0 { 0.0 255.0 }  0 }
+	{ highthreshold "High Threshold" "High Threshold"  { real triplescale 100 }    255.0 { 0.0 255.0 }  1 }
+	{ smoothingxy "Smoothing XY 1-4" "Smoothing XY" { listofvalues radiobutton}  0.0 { 0.0 1.0 2.0 3.0 4.0 }   2}
+	{ smoothingz "Smoothing Z 1-4" "Smoothing Z" { listofvalues radiobutton}  0.0 { 0.0 1.0 2.0 3.0 4.0 }   3}
+	{ resample "Resample scale 1-4" "Resample" { listofvalues radiobutton}  1.0 { 1.0 2.0 3.0 4.0 }   4}
+    }
+
+    set defaultsuffix { "_objmap" }
+    
+    set scriptname bis_extractobjectmap
+
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "Extract a surface from an objectmap (image)"
+    set description2 ""
+    set backwardcompaibitlity "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeImageToSurfaceAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_extractobjectmap::Execute {  } {
+
+    PrintDebug "bis_extractobjectmap::Execute"
+
+    # Get Inputs
+    set image_in [ $this GetInput ]
+
+    # GetOptions
+    
+    set smoothingxy [ $OptionsArray(smoothingxy) GetValue ]
+    set smoothingz [ $OptionsArray(smoothingz) GetValue ]
+    set resample [ $OptionsArray(resample)      GetValue ]
+    set lowthreshold [ $OptionsArray(lowthreshold) GetValue ]
+    set highthreshold [ $OptionsArray(highthreshold)      GetValue ]
+   
+    set lt [expr { int( $lowthreshold) } ]
+    set ht [expr { int( $highthreshold) } ]
+
+
+    set temp  [ vtkPolyData [ pxvtable::vnewobj ] ]
+    set objtopoly [ vtkpxSurfaceUtil [ pxvtable::vnewobj ] ]
+    $objtopoly ObjectMapToPolyData [ $image_in GetObject] $temp $lt $ht $smoothingxy $smoothingz [ expr 1.0 + $resample ] 
+    
+    if { $temp > 0 } {
+             # Store Results in output
+	    [ $OutputsArray(output_surface) GetObject ] DeepCopySurface $temp
+	}
+
+    # Clean up
+     $temp Delete
+       
+       return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_extractobjectmap.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_extractobjectmap [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_extractsurface.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_extractsurface.tcl
new file mode 100755
index 0000000..b68e9ef
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_extractsurface.tcl
@@ -0,0 +1,203 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetosurfacealgorithm 1.0                
+package provide bis_extractsurface 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_extractsurface {
+
+    inherit bis_imagetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Extract Surface" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_extractsurface::Initialize { } {
+
+    PrintDebug "bis_extractsurface::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+		{ smoothing "Pick smoothing On/Off. " "Smoothing" { boolean}  1 { 0 1 }   0}
+		{ smoothscale "Smoothing scale" "Smoothing scale"  { real triplescale 100 }    1.0 { 0.25 6.0 }  1 }
+        { resample "Resample On/Off" "Resampling" { boolean}  1 { 0 1 }   2}
+		{ resamplescale "Resample scale" "Resample scale"  { real triplescale 100 }    2.0 { 1.0 6.0 }  3 }
+        { thresholding "Perform Thresholding" "Thresholding" { boolean }  1 { 0 1 }   4}
+		{ extractLevel "Extract Level" "Extract Level"  { real triplescale 100 }    128.0 { 0.0 255.0 }  5 }
+		{ lowthreshold "Low Threshold" "Low Threshold"  { real triplescale 100 }    0.0 { 0.0 255.0 }  6 }
+		{ highthreshold "High Threshold" "High Threshold"  { real triplescale 100 }    255.0 { 0.0 255.0 }  7 }
+    }
+
+    set defaultsuffix { "_extractsurface" }
+    
+    set scriptname bis_extractsurface
+
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "Extract a surface from an image"
+    set description2 ""
+    set backwardcompaibitlity "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeImageToSurfaceAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_extractsurface::Execute {  } {
+
+    PrintDebug "bis_extractsurface::Execute"
+
+    # Get Inputs
+    set image_in [ $this GetInput ]
+
+
+    # GetOptions
+    
+    set smoothing [ $OptionsArray(smoothing) GetValue ]
+    set smoothscale [ $OptionsArray(smoothscale) GetValue ]
+    set resample [ $OptionsArray(resample)      GetValue ]
+    set resamplescale [ $OptionsArray(resamplescale)      GetValue ]
+    set thresholding [ $OptionsArray(thresholding)      GetValue ]
+    set extractLevel [ $OptionsArray(extractLevel)      GetValue ]
+    set lowthreshold [ $OptionsArray(lowthreshold) GetValue ]
+    set highthreshold [ $OptionsArray(highthreshold)      GetValue ]
+
+    set lastoutput [ vtkImageData [ pxvtable::vnewobj ] ]
+    $lastoutput ShallowCopy [ $image_in GetObject] 
+    
+    
+    if { $smoothing == "1"} {
+	    set smrad [ expr { int( $smoothscale * 2.0 + 1.5 ) } ]
+	    set smoothFilter [ vtkImageGaussianSmooth [ pxvtable::vnewobj ] ]
+	    $smoothFilter SetInput $lastoutput 
+	    $smoothFilter SetStandardDeviations $smoothscale $smoothscale $smoothscale
+	    $smoothFilter SetRadiusFactors $smoothscale $smoothscale $smoothscale
+	    $smoothFilter Update 
+	    
+	    $lastoutput ShallowCopy [ $smoothFilter GetOutput ]
+	    
+	    $smoothFilter Delete 
+    }
+	
+    if { $resample == "1" } {
+	    set scalefact [ expr { 1.0 / $resamplescale } ]
+  	    set resl [ vtkbisImageResample [ pxvtable::vnewobj ] ]
+	    $resl SetInput $lastoutput
+	    $resl SetInterpolate 1 
+	    $resl SetAxisMagnificationFactor 0 $scalefact
+	    $resl SetAxisMagnificationFactor 1 $scalefact
+	    $resl SetAxisMagnificationFactor 2 $scalefact
+	    $resl Update 
+	    
+	    $lastoutput ShallowCopy [ $resl GetOutput ] 
+	    $resl Delete 
+    }
+	    
+    if { $thresholding == "1" } { 
+	    if { $lowthreshold > $highthreshold } {
+		    set t $highthreshold
+		    set highthreshold $lowthreshold
+		    set lowthreshold $t		      
+		    puts "Low threshold higher than high threshold. Values have been swapped"
+		}
+		
+		set thrFilter [ vtkImageThreshold [ pxvtable::vnewobj ] ]
+		$thrFilter SetInput $lastoutput 
+
+		if  { $smoothing == "1" } { 
+				$thrFilter ThresholdByUpper $highthreshold  
+		    } else {
+				$thrFilter ThresholdBetween $lowthreshold $highthreshold
+		    }
+		    
+		    $thrFilter SetOutValue 0.0
+		    $thrFilter ReplaceInOff
+		    $thrFilter Update 
+		    $lastoutput ShallowCopy [ $thrFilter GetOutput ]
+		    
+		    $thrFilter Delete
+	}
+	
+	set skinExtractor  [ vtkContourFilter [ pxvtable::vnewobj ] ]
+	$skinExtractor SetInput $lastoutput 
+	$skinExtractor SetUseScalarTree 0 
+	$skinExtractor SetNumberOfContours 1 
+	$skinExtractor SetValue 0 $extractLevel
+	$skinExtractor ComputeScalarsOff
+	$skinExtractor ComputeNormalsOff
+	$skinExtractor Update
+	
+	set surface_out [$skinExtractor GetOutput ]
+		
+    # Store Results in output
+    [ $OutputsArray(output_surface) GetObject ] DeepCopySurface $surface_out 
+
+    # Clean up
+     #  $filter Delete
+       
+       return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_extractsurface.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_extractsurface [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_fdr.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_fdr.tcl
new file mode 100755
index 0000000..e0d7110
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_fdr.tcl
@@ -0,0 +1,276 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_fdr 1.0
+package require bis_dualimagealgorithm	1.0
+package require bis_tmaptopvalue 1.0
+package require bis_zscoretopvalue 1.0
+package require bis_maskimage 1.0
+package require bis_shiftscaleimage 1.0
+
+itcl::class bis_fdr {
+
+    inherit bis_dualimagealgorithm 
+    
+    constructor { } {	 $this Initialize  }
+    
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Compute FDR" }
+    #override parent function
+    public method CheckInputObjects { }
+    public method UpdateOutputFilenames { }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_fdr::Initialize { } {
+
+    PrintDebug "bis_fdr::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ inptype     "Data type of input" "Input data type" { listofvalues radiobuttons } t { t z p "1-p" }	   0 }
+	{ usemask     "Use Mask"	  "Use Mask"   boolean			     0 { 0 1  }	      5 } 
+	{ autoscale   "Detect Whether t-values are scaled by 1000 or not"	  "AutoScale"   boolean	 1 { 0 1  }  6 } 
+	{ scaleFactor "Scale factor "     "Scale" float  1.0  { -100000000.0 100000000.0 }	-20 }
+	{ dof	      "Degree of Freedom" "DOF"	  int	 1    { .0	      100000000	  }  10 }
+	{ q	          "FDR bound "	  "q"	  float	 0.01 { 0.0 1.0 } 30 }	       
+	{ guiout      "Results from FDR Computation" "Info:"  comment  "         " ""  40 }
+    }
+	
+	
+	set defaultsuffix { "_fdr" }
+	
+	
+	set scriptname bis_fdr
+	set completionstatus "Done"
+	
+	#
+	#document
+	#
+	
+	set description "Compute False Detection Rate."
+	set description2 "An approach to control the expected proportion of false positives. Takes p-values and a FDR rate, and returns a p-value thresholds."
+	set backwardcompatibility ""
+	set authors "isabella.murphy at yale.edu, xilin.shen at yale.edu."
+	
+	$this InitializeDualImageAlgorithm
+	
+	$this RenameInput 0 "Functional Image"
+	#set priority to 102 to make it optional
+	$this RenameInput 1 "Mask Image" 102
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_fdr::Execute {  } {
+
+
+    set con 0
+    catch {set con [ vtkbisFDR New ]	}
+    if { $con == 0 } {
+	pxtclvtkpxcontrib::LoadLibraries { vtkpxImagingTCL }
+    }
+    catch { $con Delete }
+    
+    PrintDebug "bis_fdr::Execute"
+    
+    set inptype	    [ $OptionsArray(inptype)	     GetValue  ]
+    set dof	        [ $OptionsArray(dof)	  GetValue  ]
+    set scaleFactor [ $OptionsArray(scaleFactor)  GetValue  ]
+    set q	        [ $OptionsArray(q)		  GetValue  ]
+    set image_in    [ $this GetInput ]
+    set autoscale   [ $OptionsArray(autoscale)  GetValue  ]
+	
+    set fdr 0
+    catch { set fdr  [ vtkbisFDR New ] }
+    if { $fdr == 0 } {
+	return 0
+    }
+
+    set tmpimg [ pxitclimage \#auto ]
+    set textv ""
+    
+    if { $inptype == "t" } {
+	puts stdout "Computing t-to-p conversion"
+	set cal [ bis_tmaptopvalue \#auto ]
+	$cal InitializeFromContainer $this
+	$cal SetInput $image_in 
+	$cal SetOptionValue dof $dof
+	$cal SetOptionValue autoscale $autoscale
+	$cal SetOptionValue scaleFactor $scaleFactor
+	$cal Execute
+	$this SetOptionValue scaleFactor [ $cal GetOptionValue scaleFactor]
+	set textv "(SFactor = [ $cal GetOptionValue scaleFactor ])"
+
+	# GetOutput = pxitclimage
+	# [  GetOutput	] GetImage = vtkImageData  (GetImage is same as GetObject )
+	$tmpimg ShallowCopy [ $cal GetOutput ] 
+	itcl::delete obj $cal
+    } elseif { $inptype == "z" } {
+	puts stdout "Computing z-to-p conversion"
+	set cal [ bis_zscoretopvalue \#auto ]
+	$cal InitializeFromContainer $this
+	$cal SetInput $image_in 
+	$cal Execute
+	$tmpimg ShallowCopy [ $cal GetOutput ] 
+	itcl::delete obj $cal
+    } elseif { $inptype == "1-p" } {
+	puts stdout "Computing (1-p)-to-p conversion"
+	set cal [ bis_shiftscaleimage \#auto ]
+	$cal InitializeFromContainer $this
+	$cal SetInput $image_in 
+	$cal SetOptionValue shift  -1.0
+	$cal SetOptionValue scale -1.0
+	$cal SetOptionValue abs	   1
+	$cal Execute
+	# GetOutput = pxitclimage
+	# [  GetOutput	] GetImage = vtkImageData  (GetImage is same as GetObject )
+	$tmpimg ShallowCopy [ $cal GetOutput ] 
+	itcl::delete obj $cal
+    } else {
+	#puts stderr "Simple Shallow Copy"
+	$tmpimg ShallowCopy $image_in
+    }
+    
+    #$tmpimg Save "/mnt/cluster1/isabella/Desktop/empty fdr/fdrinput.nii.gz"
+	#de
+set inpname "t-p_result.nii.gz"
+$tmpimg Save $inpname
+	#de
+    $fdr SetInput [ $tmpimg GetImage ]
+    $fdr SetQ $q
+
+    set msk [ $OptionsArray(usemask) GetValue ]
+    if { $msk == "1" } {
+	puts stdout "Using Mask ..."
+	$fdr SetImageMask [ [ $this GetInputObject second_image ] GetObject ]
+    } 
+    $this SetFilterCallbacks $fdr "Compute FDR"
+    $fdr Update
+
+    set textv "Cutoff = [ $fdr GetMaxPvalue ] $textv"
+    $OptionsArray(guiout) SetValue $textv
+    puts stdout "Output Info=$textv"
+	
+    set cast [ vtkImageCast New ]
+    $cast SetInput [ $fdr GetOutput ]
+    $cast SetOutputScalarType [ [ $image_in GetImage ] GetScalarType ]
+
+
+    set math [ vtkImageMathematics New ]
+    $math SetInput1 [ $image_in GetImage ]
+    $math SetInput2 [ $cast GetOutput ]
+    $math SetOperationToMultiply
+    $math Update
+
+    set outimage [ $this GetOutput ]
+    $outimage ShallowCopyImage [ $math GetOutput ] 
+    $outimage CopyImageHeader  [ $image_in GetImageHeader ]
+	
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+    [ $outimage GetImageHeader ] AddComment "[ $this GetGUIName ] Log: $textv" 0
+	
+    $fdr Delete
+    $cast Delete
+    $math Delete
+    itcl::delete obj $tmpimg
+   
+    return 1
+}
+itcl::body bis_fdr::UpdateOutputFilenames { } {
+
+    set fname ""
+    if { $fname == "" } {
+	set f(0) [ $InputsArray(input_image) GetFileName ]
+	set f(1) [ $InputsArray(second_image) GetFileName ]
+	set s(0) [ $OptionsArray(q)		  GetValue  ]
+	
+	for { set i 0 } { $i <= 1 } { incr i } {
+	    set l($i) [ ::bis_common::SplitFileNameGZ $f($i) ]
+	    set f($i) [ file tail [ lindex $l($i) 0 ] ]
+	    set ext($i) [ lindex $l($i) 1 ]
+	}
+	set fname [ file join [ file dirname $f(0) ] "$f(0)_$f(1)" ]
+    } 
+    
+    set outlist [ $this CreateDefaultOutputFileList $fname ]
+    $OutputsArray(output_image) SetFileName "[ lindex $outlist 0 ]_q$s(0)$ext(0)"
+    return 1
+}
+
+# -------------------------------------------------------------------------------
+
+itcl::body bis_fdr::CheckInputObjects { } {
+
+    set image_in    [ $this GetInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 2 } {
+	return 0
+    }
+    
+    set msk [ $OptionsArray(usemask) GetValue ]
+    if { $msk == "1" } {
+	set image_in	[ $this GetSecondInput ]
+	set d [ $image_in GetImageSize ]
+	if { $d < 2 } {
+	    return 0
+	}
+    }
+    
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_fdr.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+    set alg [bis_fdr [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_fftimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_fftimage.tcl
new file mode 100755
index 0000000..94ff9e3
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_fftimage.tcl
@@ -0,0 +1,141 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+
+package provide bis_fftimage 1.0
+
+#
+# fft image
+#
+
+itcl::class bis_fftimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Fourier Transform" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_fftimage::Initialize { } {
+
+    PrintDebug "bis_fftimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ dimension "dimension of fourier transform operation. The default value is 3. " "dimension"  int   3 { 2 3 }  0 }
+  	{ fftoperation "if true, the algorithm will shift the zeroth frequency to the center of the image" "operations"  { boolean checkbutton } 0 { 0 1 } 1 }
+    }
+    set defaultsuffix { "_fft" }
+    
+    set completionstatus "Done  --  needs testing"
+
+    set scriptname bis_fftimage
+
+
+    set description "computes the fourier transformation of an image."
+    set description2 "outputs can either of the zero frequency at the center or at the corners depending on options"
+    set backwardcompatibility "N/A"
+    set authors "hirohito.okuda at yale.edu.,"
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_fftimage::Execute {  } {
+
+    PrintDebug "bis_fftimage::Execute"
+
+    set dimension   [ $OptionsArray(dimension)    GetValue  ]
+    set image_in    [ $InputsArray(input_image)   GetObject ]
+
+   
+    #vtkImageFFT
+    set fft [vtkImageFFT [pxvtable::vnewobj]] 
+    set callback "FFT Transforming Image"
+
+    $fft SetDimensionality $dimension
+    $fft SetInput [$image_in GetObject]
+    $this SetFilterCallbacks $fft $callback
+    $fft Update
+    set image_out [ $fft GetOutput ]
+
+    if { [ $OptionsArray(fftoperation) GetValue  ] } {
+	set cfft [vtkImageFourierCenter [pxvtable::vnewobj]]
+	$cfft SetDimensionality $dimension
+	$cfft SetInput $image_out
+	$cfft Update
+	set image_out [ $cfft GetOutput ]
+    }
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage $image_out 
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    [ $outimage GetImageHeader ] AddComment "[ $this GetCommandLine full ]" 0
+
+    $fft Delete
+    if { [ info exist cfft ] } { $cfft Delete }
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_fftimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_fftimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_flipimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_flipimage.tcl
new file mode 100755
index 0000000..0ba2157
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_flipimage.tcl
@@ -0,0 +1,141 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+
+package provide bis_flipimage 1.0
+
+#
+# flip image
+#
+
+itcl::class bis_flipimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Flip Image" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_flipimage::Initialize { } {
+
+    PrintDebug "bis_flipimage::Initialize" 
+
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ direction "flip direction X,Y,Z" "Direction To Flip"  { listofvalues radiobuttons } Z { X Y Z }  0 }
+    }
+
+    set defaultsuffix { "_flip" }
+    
+    set scriptname bis_flipimage
+    set completionstatus "Done  --  needs testing, perhaps add transpose, flip transpose options"
+
+    set description "flips image about one of the coordinate axes."
+    set description2 ""
+    set backwardcompatibility "Reimplemented from pxmat_flip.tcl. Multiple image processing eliminated,which will be recovered upon request. "
+    
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_flipimage::Execute {  } {
+
+    PrintDebug "bis_flipimage::Execute"
+
+    set direction   [ $OptionsArray(direction) GetValue ]
+    set image_in    [ $InputsArray(input_image) GetObject ]
+    set flip [ vtkImageFlip [ pxvtable::vnewobj ]]
+
+    if { $direction == "X" } {
+	$flip SetFilteredAxis 0
+    } elseif { $direction == "Y" } {
+	$flip SetFilteredAxis 1
+    } else {
+	$flip SetFilteredAxis 2
+    }
+    $flip SetInput [ $image_in GetObject ]
+    $flip PreserveImageExtentOn
+    $this SetFilterCallbacks $flip "Flipping Image"
+    $flip Update
+
+    set image_out [ $flip GetOutput ]
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out 
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format "BIS::bis_flipimage.tcl "  ] 
+
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    $flip Delete
+    return 1
+}
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_flipimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_flipimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_fmritoolbox.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_fmritoolbox.tcl
new file mode 100755
index 0000000..64eef42
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_fmritoolbox.tcl
@@ -0,0 +1,221 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_fmritoolbox  1.0
+package require bis_dualimagealgorithm 1.0
+
+itcl::class bis_fmritoolbox {
+
+    inherit bis_dualimagealgorithm
+    
+    constructor { } { $this Initialize  }
+    
+    public method Initialize { }
+    public method Execute { }
+	public method GetGUIName    { } { return "fMRI Tool Box" }
+    public method GetSecondOutput { }
+    public method CheckInputObjects {}
+    }
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_fmritoolbox::Initialize { } {
+    
+    PrintDebug " bis_fmritoolbox::Initialize" 
+    
+    set inputs { 
+	{ third_image "ROI Map Image" pxitclimage "" 80 }     
+    }
+    
+    set options {
+	{ threshold "Threshold to be count as connected" "Threshold" { real triplescale 100 } 0.3 { 0.0 1.0 } 10 }
+    }
+    
+    #this provide output GUI
+    set outputs { 
+	{ second_output "Network Measures" pxitclimage  ""  10 }   
+    }
+    
+#    puts stdout "$inputs, $options, $outputs"
+    
+    set defaultsuffix { "_shortestPath" }
+    set category "Functional Imaging"    
+    set scriptname bis_fmritoolbox 
+    set completionstatus "testing"
+    
+    #
+    #document
+    #
+    set description "fmri Tool Box. Calculate complex network measures."
+    set description2 "This algorithm requires 3 inputs, which are ROI correlation result, functional image and ROI image."
+    set backwardcompatibility ""
+    set authors "isabella.murphy at yale.edu, xilin.shen at yale.edu."
+    
+    InitializeDualImageAlgorithm
+    RenameInput 0 "ROI Correlation Image"
+    RenameInput 1 "Functional Image"
+    
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_fmritoolbox::Execute {  } {
+
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+    
+    PrintDebug "bis_fmritoolbox::Execute"
+    
+    set threshold    [ $OptionsArray(threshold)  GetValue ]
+    set image_in [ $this GetInput ]
+    
+    set alg 0
+    catch { set alg  [ vtkbisfmriToolBox New  ] }
+    if { $alg ==0 } {
+	return 0
+    }
+	
+    set f(0) [ $InputsArray(input_image) GetFileName ]
+    set l [ ::bis_common::SplitFileNameGZ $f(0) ]
+    set f(0) [ file tail [ lindex $l 0 ] ]
+    set textfilename [ file join [ file dirname $f(0) ] "$f(0)_adjMatrixForAlarkViewer.txt" ]
+    set textfilename2 [ file join [ file dirname $f(0) ] "$f(0)_networkMeasures.txt" ]
+    set textfilename3 [ file join [ file dirname $f(0) ] "$f(0)_roiCorrelationForAlarkViewer.txt" ]
+    
+    $alg SetInput           [ $image_in GetObject ]	
+    $alg SetFunctionalImage [ [ $this GetInputObject second_image ] GetObject ]
+    $alg SetroiMap          [ [ $this GetInputObject third_image ] GetObject ]
+    $alg SetThreshold       $threshold
+    $alg SetFilename        $textfilename
+    $alg SetFilename2       $textfilename2
+    $alg SetFilename3       $textfilename3
+    $this SetFilterCallbacks $alg "Calculate Network Measures"
+
+
+
+    $alg Update
+
+
+    #set brainnetwork [ $alg ComputeBrainNetwork [ [ $this GetSecondInput ] GetObject ] $threshold 1 ]
+    #set degrees [ $alg ComputeDegreesUnd $brainnetwork ]
+    #$alg ComputeNetworkMeasures [ [ $this GetSecondInput ] GetObject ] [ $image_in GetObject ] [ [ $this GetInputObject third_image ] GetObject ] $textfilename
+    #$alg ComputeShortestPath $brainnetwork [ $image_in GetObject ] [ [ $this GetInputObject third_image ] GetObject ] $textfilename 1 $degrees
+    #set BC [ $alg ComputeBetweenessCentrality $brainnetwork ]
+    #set localE [ $alg ComputeLocalEfficiency $brainnetwork $degrees ]
+    #set otherdata [$alg ComputeNetworkMeasures $brainnetwork [ $image_in GetObject ] [ [ $this GetInputObject third_image ] GetObject ] $degrees]
+    
+    #set oimage1 [ $alg GenerateOutputForAlarkViewer $localE $BC $otherdata $textfilename ]
+    #$alg GenerateAdjMatrixOutputForAlarkViewer $brainnetwork $otherdata $textfilename2
+	
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $alg GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+	
+    set outimage2 [ $OutputsArray(second_output) GetObject ]
+    $outimage2 ShallowCopyImage [ $alg GetOutData2 ]
+    $outimage2 CopyImageHeader [ $image_in GetImageHeader ]
+    
+    set text "index x y z label ind.CharPathLength ind.GlobalEffi. ClosenessCentrality #ofTriangles Degrees LocalEffi BetweenessCentrality"
+    puts stdout "\nNetwork Measures Output: $text\n"
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+    [ $outimage2 GetImageHeader ] AddComment "$comment $Log" 0
+    [ $outimage2 GetImageHeader ] AddComment "[ $this GetGUIName ] Log: Column Name: $text" 0
+
+    set fname3 [ $outimage2 cget -filename ]
+    if { $fname3 == "" } {
+	set f(0) [ $InputsArray(input_image) GetFileName ]
+	set l [ ::bis_common::SplitFileNameGZ $f(0) ]
+	set f(0) [ file tail [ lindex $l 0 ] ]
+	set newname [ file join [ file dirname $f(0) ]  "$f(0)_networkMeasures.nii.gz" ]
+	$outimage2 configure -filename $newname
+    }
+	
+    catch {  $alg Delete }
+    
+    return 1
+}
+itcl::body bis_fmritoolbox::GetSecondOutput {  } {
+	return [ $this GetOutputObject second_output ]
+}
+itcl::body bis_fmritoolbox::CheckInputObjects { } {
+
+
+	set image_in    [ $this GetInput ]
+	set d [ $image_in GetImageSize ]
+	if { $d < 1 } {
+	return 0
+	}
+	
+	set image_in    [ $this GetSecondInput ]
+	set d [ $image_in GetImageSize ]
+	if { $d < 1 } {
+	return 0
+	}
+	
+	
+	set image_in    [ $this GetInputObject third_image ]
+	set d [ $image_in GetImageSize ]
+	if { $d < 1 } {
+	return 0
+	}
+	
+	return 1
+
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_fmritoolbox.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+	# this is essentially the main function
+
+	set alg [bis_fmritoolbox [pxvtable::vnewobj]]
+	$alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_frangivesselness.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_frangivesselness.tcl
new file mode 100755
index 0000000..cf6de9f
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_frangivesselness.tcl
@@ -0,0 +1,372 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] mjack ]
+
+package provide bis_frangivesselness 1.0
+package require bis_imagetoimagealgorithm 1.0
+package require vtkmpjcontrib
+
+itcl::class bis_frangivesselness {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Frangi Vesselness" }
+
+    protected method linspace { x1 x2 n }
+    protected method logspace { x1 x2 n }
+    protected method ResampleImage { img spacing }
+    protected method ComputeResults { input numscales gamma minscale maxscale logmode smoothsigma scalevesselness usegpu }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_frangivesselness::Initialize { } {
+
+    PrintDebug "bis_frangivesselness::Initialize" 
+    
+    set outputs {
+	{ outhessian "Hessian"     pxitclimage  "" 101 }
+	{ outscale   "Scale"       pxitclimage  "" 102 }
+    }
+   
+     set options {
+ 	{ frac            " max intensity in the middle of the vessel (0..1) where 1= max intensity of the image" "Frac Intensity"  real    0.7 { 0.0 1.0 }  0 }
+ 	{ numscales       "number of scales "                   "Number of Scales"       integer       1 { 1 20 }      1 }
+ 	{ minscale        "minimum scale in voxels"        "Minimum Scale"        real    1.0 { 0.1 25.0 }  2 }
+ 	{ maxscale        "maximum scale in voxels"        "Maximum Scale"        real    5.0 { 1.0 25.0 }  3 }
+ 	{ logarithmic     "use logarithmic scale spacing"  "Logarithmic"    boolean  1 { 0 1}        4 }
+ 	{ smoothing       "post-process gaussian smoothing" "Sigma"        real    0.0 { 0.0 4.0 }  -10  }
+ 	{ scalevesselness "scale vesselness"               "Scale Vesselness"  boolean   1 { 0 1 }   -11 }
+ 	{ forcecpu "Force CPU even if GPU convolution if available"               "Force CPU"  boolean   0 { 0 1 }   -12 }
+ 	{ debug "Debug Mode -- prints more info as process is running"               "Debug Mode"  boolean   0 { 0 1 }   -5 }
+     }
+
+
+    set defaultsuffix  "_vess" 
+    
+    set scriptname bis_frangivesselness
+
+    #
+    #document
+    #
+
+    set category "Vascular Imaging"
+    set description " computes the multiscale hessian tensor and associated vesslness and scale images from Frangi 1998."
+    set description2 ""
+    set backwardcompatibility "Reimplemented from pxmat_vesselutility.tcl."
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+#------------------------------------------------------------------------------------------
+# Create list of (n-1) equaly divided partial intervals of [x1,x2]
+#------------------------------------------------------------------------------------------
+
+itcl::body bis_frangivesselness::linspace { x1 x2 n } {
+
+    set linlist ""
+    
+    if { $n < 2 } { return $x1 }
+    
+    set delta [expr ($x2 - $x1) / ($n - 1) ]
+    for { set i 0 } { $i <= [expr $n - 2] } { incr i } {
+	lappend linlist [expr $x1 + $i*$delta]
+    }
+    lappend linlist $x2
+
+    return $linlist    
+}
+
+################################################################
+# Create list of (n-1) log-scale-equaly divided intervals of [x1,x2]
+################################################################
+
+itcl::body bis_frangivesselness::logspace { x1 x2 n } {
+
+    set loglist ""
+
+    if { $n < 2 } { return $x1 }
+    
+    set linlist [ linspace [expr log10($x1)] [expr log10($x2)] $n ]
+    
+    foreach item $linlist {
+	lappend loglist [expr pow(10,$item)]
+    }
+    
+    return $loglist
+}
+
+###############################################################
+#
+###############################################################
+
+itcl::body bis_frangivesselness::ResampleImage { img spacing } {
+
+    puts stdout "Resampling at $spacing x $spacing x $spacing "
+
+    set resamp [ vtkImageResample [ pxvtable::vnewobj ]]
+    $resamp SetInput $img
+    $resamp SetAxisOutputSpacing 0 $spacing
+    $resamp SetAxisOutputSpacing 1 $spacing
+    $resamp SetAxisOutputSpacing 2 $spacing
+    $resamp Update
+    set out [ vtkImageData [ pxvtable::vnewobj ]]
+    $out ShallowCopy [ $resamp GetOutput ]
+    $resamp Delete
+
+    puts stdout " Dimensions Input [ $img GetDimensions ] --> Output [ $out GetDimensions ] "
+    return $out
+}
+
+###############################################################
+# Compute results
+###############################################################
+
+itcl::body bis_frangivesselness::ComputeResults { input numscales gamma minscale maxscale logmode smoothsigma scalevesselness forcecpu } {
+
+    set hessian [ vtkImageData [ pxvtable::vnewobj ]] 
+    set vessel [ vtkImageData [ pxvtable::vnewobj ]] 
+    set sigma [  vtkImageData [ pxvtable::vnewobj ]] 
+
+    set deb [ $OptionsArray(debug) GetValue ] 
+
+    set scales 0
+
+    ## generate scales
+    if { $logmode == 0 } {
+	set scales [ linspace $minscale $maxscale $numscales ]
+    } else {
+	set scales [ logspace $minscale $maxscale $numscales ]
+    }
+    
+    set doresample 0
+    set newinput   0
+    set newhess    0
+
+    set spa [ lsort [ $input GetSpacing ] ]
+    
+    if { ([ lindex $spa 2 ] - [ lindex $spa 0 ]) > [ expr 0.05* [lindex $spa 1 ] ] } {
+	set doresample 1
+	set spx [ expr ( [ lindex $spa 0 ] + [ lindex $spa 1 ] + [ lindex $spa 2 ])/3.0 ]
+	
+	set newinput [ ResampleImage $input $spx ]
+    } else {
+	set newinput $input
+    }
+
+    set truegamma [ expr [ lindex [ [ [ $newinput GetPointData ] GetScalars ] GetRange ] 1 ] * $gamma ]
+
+    set firsttime 1
+
+    #    puts stdout "Computing scales = \{ $scales \}, gamma=$truegamma"
+       
+    ## run the filter for all scales
+    set n [ llength $scales ]
+    for { set sc 0 } { $sc < $n } { incr sc } {
+	set sig [ lindex $scales $sc ]
+
+	#puts stdout "\n-------------------------------------\n  Computing at scale $sig ($scales)\n-------------------------------------\n"
+
+	set hess [ vtkxqImageHessian [ pxvtable::vnewobj ] ]
+	$hess SetInput $newinput
+	$this SetFilterCallbacks $hess "Computing Hessian at $sig"
+	set sgmlabel [format "%7.4f" $sig]
+	$hess SetSigma $sig
+	if { $deb > 0 } {
+	    $hess DebugOn 
+	}
+	if { $forcecpu > 0 } {
+	    $hess SetForceCPU 1
+	} else {
+	    $hess SetForceCPU 0
+	}
+	$hess Update
+
+	set img [ vtkImageData New ]
+	$img ShallowCopy [ $hess GetOutput ]
+	$hess Delete
+
+	## vesselness filter
+	set vess [ vtkmpjImageVesselEnhancement [ pxvtable::vnewobj ] ]
+	$vess SetInput $img
+	$vess SetAlpha 0.5
+	$vess SetBeta  0.5
+	$vess SetGamma $truegamma
+	$vess SetStructureType 0
+	$this SetFilterCallbacks $vess "Computing Vesselness at $sig"
+	$vess SetBrightStructure 1
+
+	if { $scalevesselness == 1 } {
+	    $vess SetVesselnessScaleFactor 1000.0
+	} else {
+	    $vess SetVesselnessScaleFactor 1.0
+	}
+	
+	## compute vesselness measure
+	$vess Update
+	#	puts -nonewline stdout "Vesselness Done \t"
+    
+	## store maximum
+	if { $firsttime ==1 } {
+	    
+	    ## store hessian
+	    $hessian ShallowCopy $img
+
+	    ## store vesselness
+	    $vessel ShallowCopy [ $vess GetOutput ]
+	    
+	    ## store sigma
+	    $sigma CopyStructure  $newinput
+	    $sigma SetScalarTypeToFloat 
+	     $sigma AllocateScalars
+	    [ [ $sigma GetPointData ] GetScalars ] FillComponent 0 $sig
+	    set firsttime 0
+	} else {
+	    $vess UpdateHessianResponse $hessian  $vessel $sigma $img [ $vess GetOutput ] $sig
+	    #puts -nonewline stdout "\t Max Done "
+	}
+
+	$img Delete
+	$vess Delete
+	#	puts stdout "\t Cleanup Done"
+
+    }
+
+    puts stdout "\n-------------------------------------\n  Generating Output\n-------------------------------------\n"
+
+    if { $smoothsigma > 0.0 } { 
+	
+	set s1  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+	$s1 SetStandardDeviations $smoothsigma $smoothsigma $smoothsigma
+	$s1 SetInput $vessel 
+	$s1 Update
+	$vessel ShallowCopy [ $s1 GetOutput ]
+	$s1 Delete
+
+    	set s2  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+	$s2 SetStandardDeviations $smoothsigma $smoothsigma $smoothsigma
+	$s2 SetInput $sigma 
+	$s2 Update
+	$sigma ShallowCopy [ $s2 GetOutput ]
+	$s2 Delete
+    }
+
+    if { $doresample == 1 } {
+	#	puts stdout "Scaling scales by $spx "
+
+	set sc [ vtkImageShiftScale [ pxvtable::vnewobj ]]
+	$sc SetInput  $sigma 
+	$sc SetShift 0.0
+	$sc SetScale $spx
+	$sc Update
+	$sigma ShallowCopy [ $sc GetOutput ]
+	$sc Delete
+
+	catch { $newinput Delete } 
+    }
+
+    set outlist [ list $vessel $hessian $sigma ]
+    return $outlist
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_frangivesselness::Execute {  } {
+
+    PrintDebug "bis_frangivesselness::Execute"
+
+    set image_in            [ $this GetInput ] 
+    set intensity          [ $OptionsArray(frac) GetValue  ]
+    set minscale           [ $OptionsArray(minscale) GetValue  ]
+    set maxscale           [ $OptionsArray(maxscale) GetValue  ]
+    set numscales          [ $OptionsArray(numscales) GetValue ]
+    set logarithmic        [ $OptionsArray(logarithmic)      GetValue ]
+    set smoothing          [ $OptionsArray(smoothing)      GetValue ]
+    set scalevesselness    [ $OptionsArray(scalevesselness)      GetValue ]
+    set forcecpu           [ $OptionsArray(forcecpu)      GetValue ]
+
+
+    set cast [ vtkImageCast [ pxvtable::vnewobj ]]
+    $cast SetInput [$image_in GetObject]
+    $cast SetOutputScalarTypeToFloat
+    $cast Update
+
+    set resultslist [ ComputeResults [ $cast GetOutput ] $numscales $intensity $minscale $maxscale $logarithmic $smoothing $scalevesselness $forcecpu ]
+
+
+    set outimagelist [ list   [ $this GetOutput ] [ $this GetOutputObject outhessian ] [ $this GetOutputObject outscale ] ]
+    set max [ llength $resultslist ]
+    for { set i 0 } { $i < $max } { incr i } {
+	set outimage [ lindex $outimagelist $i ]
+	$outimage ShallowCopyImage [ lindex $resultslist $i ]
+	[ lindex $resultslist $i ] Delete
+	$outimage CopyImageHeader [ $image_in GetImageHeader ]
+	[ $outimage GetImageHeader ] AddComment "[ $this GetCommandLine full  ]" 0
+    }
+
+    $cast Delete
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_frangivesselness.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_frangivesselness [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_graphvis.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_graphvis.tcl
new file mode 100644
index 0000000..3b063cf
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_graphvis.tcl
@@ -0,0 +1,432 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_graphvis 1.0
+package require bis_imagetosurfacealgorithm 1.0
+
+
+itcl::class bis_graphvis {
+
+    inherit bis_imagetosurfacealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Connectivity Graph Visualization" }
+    public method RenderGraph { alg ren red green blue size stippleStyle vradius } 
+    public method StartInteractor { v }
+
+    protected variable view 0
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_graphvis::Initialize { } {
+
+    PrintDebug "bis_graphvis::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+    { vertexradius "Radius of the Vertex" "Vertex Radius"  { real triplescale 100 }    4.0 { 0.0 20.0 }  0 }
+	{ lowerthreshold     "Lower Threshold" "Lower Threshold" { real triplescale 100 }    0.2 { -5.0 5.0 }  1 }
+	{ higherthreshold    "Higher Threshold" "Higher Threshold" { real triplescale 100 }    1.0 { -5.0 5.0 }  2 }
+	{ linewidth  "Width of the Edges" "Edge Width"  { real triplescale 100 }    4.0 { 1.0 10.0 }  3 }
+	{ radiochoice  "Positive/Negative/Both" "Show "  { listofvalues radiobuttons }    Positive { Positive  Negative Both }  4 }
+	{ mname  "specify the measures file used to compute the correlations" "Measures File"   { filename default } "" { text { .txt } }   5 }
+    }
+
+    set defaultsuffix { "_connectivity" }
+    
+    set scriptname bis_graphvis
+
+    #
+    #document
+    #
+    
+     set category "Surface Processing"
+	 set description  "Extract a surface from an image"
+	 set description2 ""
+	set backwardcompatibility "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeImageToSurfaceAlgorithm
+}
+
+itcl::body bis_graphvis::StartInteractor {  v } {
+    if { $v == 0 } {
+	return 
+    }
+
+    [ $v GetRenderWindow ] SetWindowName "Graph View -- press `q'"
+    [ $v GetInteractor ] Initialize
+    $v SetInteractionModeTo3D 
+    $v Render 
+    [$v GetInteractor ] Start 
+
+}
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_graphvis::Execute {  } {
+
+    PrintDebug "bis_graphvis::Execute"
+
+    set vertexradius   [ $OptionsArray(vertexradius) GetValue ]
+    set lowerthreshold        [ $OptionsArray(lowerthreshold)      GetValue ]
+    set higherthreshold      [ $OptionsArray(higherthreshold)    GetValue ]
+    set linewidth   [ $OptionsArray(linewidth)    GetValue ]
+    set radiochoice   [ $OptionsArray(radiochoice)    GetValue ]
+    set inputfilename   [ $OptionsArray(mname)    GetValue ]
+    
+    set image_in    [ $this GetInput ]
+
+	# Create a graph
+	set graph [ vtkMutableUndirectedGraph New]
+	# $graph SetDirected 0
+
+	# Create points
+	set pts [vtkPoints New]
+	     
+	#puts "The input file name is [.fsb get]"
+	puts "In create connectivity selected $radiochoice"
+		
+	set inputfile [ open $inputfilename "r" ] 
+    # set inputfile [open [.fsb get] "r"]
+    gets $inputfile fileType
+        
+    set checkstring "#Connectivity file"
+    # trimright trims trailing white spaces
+	set filecheck [string compare [ string trimright $fileType ] $checkstring]   
+
+	if {$filecheck == 0} {
+		puts "Connectivity file loaded"
+	} else {
+		puts "Incorrect Connectivity File Format"
+		return
+	}
+    
+    gets $inputfile pointsType
+    #puts $pointsType
+    
+    gets $inputfile num_of_centroids
+    #puts "Number of points: $num_of_centroids"
+    
+    gets $inputfile headerCategories
+        
+    set nameArray [vtkStringArray New]
+    $nameArray SetName "VertexLabel"
+    
+    set indpathlength [ vtkDoubleArray New ] 
+    $indpathlength SetName "indpathlength"
+    
+    set globalEfficiency [ vtkDoubleArray New ] 
+    $globalEfficiency SetName "globalEfficiency" 
+    
+    set cCentrality [ vtkDoubleArray New ] 
+    $cCentrality SetName "ClosenessCentrality"
+    
+    set numTriangles [ vtkIntArray New ] 
+    $numTriangles SetName "numTriangles" 
+
+	set vertDegree [ vtkIntArray New ] 
+	$vertDegree SetName "vertDegree"
+
+	set localEfficiency [ vtkDoubleArray New ] 
+	$localEfficiency SetName "localEfficiency"
+
+	set betweennessCentrality [ vtkDoubleArray New ] 	
+	$betweennessCentrality SetName "BetweennessCentrality" 
+	
+    for {set i 0} {$i < $num_of_centroids} {incr i} {
+	    
+	    gets $inputfile pt1
+		scan $pt1 "%d %f %f %f %s %f %f %f %d %d %f %f" index px py pz name_of_roi pathlength globalEff closenessCentrality numTri vdegrees localEff BetweenCentrality
+		
+		set xval [expr {$px * 1.17 }]
+		set yval [expr {$py * 1.17 }]
+		set zval [expr {$pz * 1.17 }]
+
+		
+		$graph AddVertex
+		$pts InsertNextPoint $xval $yval $zval
+		
+		$nameArray InsertNextValue $name_of_roi
+		$indpathlength InsertNextValue $pathlength
+		$globalEfficiency InsertNextValue $globalEff
+		$cCentrality InsertNextValue $closenessCentrality
+		$numTriangles InsertNextValue $numTri
+		$vertDegree InsertNextValue $vdegrees
+		$localEfficiency InsertNextValue $localEff
+	  	$betweennessCentrality InsertNextValue $BetweenCentrality
+		
+    }    
+       
+    ## Process edges now 
+    
+    gets $inputfile connections
+    #puts $connections 
+    
+    gets $inputfile num_of_connections
+    puts $num_of_connections 
+    
+    set edgeStrengthArray [vtkDoubleArray New]
+        
+    for {set i 0} {$i < $num_of_connections} {incr i} {
+   
+	   gets $inputfile edge_info
+	   scan $edge_info "%d %d %f" edge_src edge_dist edge_strength
+	  #  puts "Edge source and destination are $edge_src and $edge_dist" 	   
+	   
+	   $graph AddGraphEdge $edge_src $edge_dist 
+	   
+	   $edgeStrengthArray InsertNextValue $edge_strength
+
+	}
+	
+  $edgeStrengthArray SetName "EdgeStrength"
+  
+   $graph SetPoints $pts     
+       
+    [$graph GetVertexData] AddArray $nameArray      
+	[$graph GetVertexData ] AddArray $indpathlength
+	[$graph GetVertexData ] AddArray $globalEfficiency
+	[$graph GetVertexData ] AddArray $cCentrality 
+	[$graph GetVertexData ] AddArray $numTriangles
+	[$graph GetVertexData ] AddArray $vertDegree 
+	[$graph GetVertexData ] AddArray $localEfficiency
+	[$graph GetVertexData ] AddArray $betweennessCentrality
+    
+  [$graph GetEdgeData] AddArray $edgeStrengthArray
+  
+  	set layout [vtkGraphLayout New]
+  	$layout SetInput $graph
+  	
+  	set passthrough [vtkPassThroughLayoutStrategy New]
+  	$layout SetLayoutStrategy $passthrough 
+  		  
+  		  
+	#################################################################################################  		  
+    if { $view == 0 } {
+  	set view [ vtkGraphLayoutView New ]
+    }
+		    	
+    	$view DisplayHoverTextOn
+	# $view SetLayoutStrategyToCircular
+	$view SetLayoutStrategyToPassThrough 
+	# $view SetLayoutStrategyToForceDirected 
+
+	$view SetVertexLabelArrayName [ $nameArray GetName ]
+	$view VertexLabelVisibilityOn
+	$view SetVertexColorArrayName [$betweennessCentrality GetName ] 
+	$view ColorVerticesOn
+	$view SetVertexLabelFontSize 24
+
+	$view SetRepresentationFromInputConnection [ $layout GetOutputPort ] 
+	$view SetEdgeColorArrayName [ $edgeStrengthArray GetName ] 
+	$view ColorEdgesOn
+	$view SetEdgeLabelArrayName [$edgeStrengthArray GetName ]
+	$view EdgeLabelVisibilityOn
+	$view SetEdgeLabelFontSize 10
+
+	set theme [ vtkViewTheme New ] 
+	$theme SetLineWidth 5.0
+	$view ApplyViewTheme $theme
+	$view Update
+
+	# Need to figure this out for hovering labels 
+	# vtkRenderedGraphRepresentation* rep = vtkRenderedGraphRepresentation::SafeDownCast(view->GetRepresentation());
+	# $rep [ $view GetRepresentation ] 
+	#$rep SetVertexHoverArrayName [ $betweennessCentrality GetName ] 
+	# $rep SetEdgeHoverArrayName [ $edgeStrengthArray GetName ]
+	 
+
+	$view SetHideEdgeLabelsOnInteraction 1
+  	$view ResetCamera
+
+
+    after 100 eval "$this StartInteractor $view"
+
+  
+    #################################################################################################
+  	# 1st Extraction 
+  	
+	#puts "Testing threshold selection..." 
+	set threshold [vtkSelection New]
+	set thresholdnode [vtkSelectionNode New]
+	$threshold AddNode $thresholdnode
+	# Set ContentType to 'Thresholds' = 7
+	$thresholdnode SetContentType 7 
+	# Set FieldType to 'Edge' = 4
+	$thresholdnode SetFieldType 4 
+	
+	set thresholdArr [vtkDoubleArray New]		
+	$thresholdArr SetName "value"
+	$thresholdArr InsertNextValue $lowerthreshold
+	$thresholdArr InsertNextValue $higherthreshold
+	
+	$thresholdnode SetSelectionList $thresholdArr 
+		
+	set extractThreshold [vtkExtractSelectedGraph New]
+	$extractThreshold SetInputConnection 0 [$layout GetOutputPort]	
+	$extractThreshold SetInput 1 $threshold	
+	
+	
+	# 2nd graph 
+	set threshold2 [vtkSelection New]
+	set threshold2node [vtkSelectionNode New]
+	$threshold2 AddNode $threshold2node
+	$threshold2node SetContentType 7
+	$threshold2node SetFieldType 4
+	
+	set thresholdArr2 [vtkDoubleArray New]
+	$thresholdArr2 SetName "value"
+	$thresholdArr2 InsertNextValue 0.0
+	$thresholdArr2 InsertNextValue 0.4
+		
+	$threshold2node SetSelectionList $thresholdArr2 
+	
+	set layout2 [vtkGraphLayout New]
+	$layout2 SetInput $graph
+
+	set passthrough2 [vtkPassThroughLayoutStrategy New]
+	$layout2 SetLayoutStrategy $passthrough2 			
+		
+	set extractThreshold2 [vtkExtractSelectedGraph New]
+	$extractThreshold2 SetInputConnection 0 [$layout GetOutputPort]		
+	$extractThreshold2 SetInput 1 $threshold2
+	
+	# Raw Viewer
+	set ortho [ $this GetViewer ]
+	$ortho SetDisplay3DMode 1
+
+	set ren [ [ $ortho GetRenderer 3 ] GetRenderer ] 
+	puts stderr "Viewer = [ $ren GetClassName ]"
+	
+	
+	############ RenderGraph $layout $ren 0.5 0.5 0.5 2.0 65535 $vertexradius
+
+	
+	############RenderGraph $extractThreshold $ren 0.8 1.0 0.2 $linewidth 65535 $vertexradius
+	
+	set graphToPoly [vtkGraphToPolyData New]
+	$graphToPoly SetInputConnection [ $layout GetOutputPort]
+	$graphToPoly Update 
+
+	set surface_out [ $graphToPoly GetOutput ]
+
+    # Store Results in output
+    [ $OutputsArray(output_surface) GetObject ] DeepCopySurface $surface_out 
+    
+    # set comment [ format " [ $this GetCommandLine full ]" ]
+
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_graphvis.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_graphvis [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+itcl::body bis_graphvis::RenderGraph { alg ren red green blue size stippleStyle vradius} {
+	
+	set centroid_sphere [vtkSphereSource New]
+	$centroid_sphere SetRadius $vradius
+	$centroid_sphere SetPhiResolution 12
+	$centroid_sphere SetThetaResolution 12 
+
+	set graphToPoly [vtkGraphToPolyData New]
+	$graphToPoly SetInputConnection [$alg GetOutputPort]
+	
+	set edgeMapper [vtkPolyDataMapper New]
+	$edgeMapper SetInputConnection [$graphToPoly GetOutputPort]
+	
+	set edgeActor [vtkActor New]
+	$edgeActor SetMapper $edgeMapper
+	[$edgeActor GetProperty] SetColor $red $green $blue
+  	[$edgeActor GetProperty] SetLineWidth $size
+ 	[$edgeActor GetProperty] SetLineStipplePattern $stippleStyle
+	[$edgeActor GetProperty] SetLineStippleRepeatFactor 2  	  	
+	 
+ 	 set glyph [vtkGlyph3D New]
+	$glyph SetInputConnection 0 [$graphToPoly GetOutputPort]
+	$glyph SetInputConnection 1 [$centroid_sphere GetOutputPort]
+
+	set vertMapper [vtkPolyDataMapper New]
+	$vertMapper SetInputConnection [$glyph GetOutputPort]
+	
+	set vertActor [vtkLODActor New]
+	$vertActor SetMapper $vertMapper
+  	[$vertActor GetProperty] SetColor $red $green $blue
+  	   
+  	 set labelMapper [vtkLabeledDataMapper New]
+	 $labelMapper SetInputConnection [$graphToPoly GetOutputPort]
+	 $labelMapper SetLabelFormat "%s"
+	 $labelMapper SetLabelModeToLabelFieldData	 
+ 	 $labelMapper SetFieldDataName "VertexLabel"
+	 
+	set labelActor [vtkActor2D New]
+	$labelActor SetMapper $labelMapper  	
+	
+	$vertActor Modified
+	
+	$ren AddActor $edgeActor
+	$ren AddActor $vertActor
+	$ren AddActor $labelActor
+	
+	
+	$graphToPoly  Update 
+		
+  	$labelActor Delete
+  	$vertActor Delete
+  	$edgeActor Delete
+  	$labelMapper Delete
+ 	
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guicompareutility.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guicompareutility.tcl
new file mode 100644
index 0000000..7bc5e91
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guicompareutility.tcl
@@ -0,0 +1,296 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_guicompareutility 1.0
+package require bis_guicontainer 1.0
+package require pxitclsurface 1.0
+
+
+
+itcl::class bis_guicompareutility {
+
+    inherit bis_guicontainer
+
+    constructor { } { $this InitializeGUICompareUtility  }
+
+    # Create Input/Output GUI Controls for Objects in standalone mode
+    protected method InitializeGUICompareUtility { }
+
+    # -----------------------------------------------
+    # Legacy Interface for pxitclmultisubject
+    # -----------------------------------------------
+    public    method SetImageToCompareControl { ctrl image }
+    public    method SetCompareMean1  { image args } { SetImageToCompareControl $meanimagecontrol1   $image } 
+    public    method SetCompareMean2  { image args } { SetImageToCompareControl $meanimagecontrol2   $image } 
+    public    method SetCompareSigma1 { image args } { SetImageToCompareControl $sigmaimagecontrol1  $image } 
+    public    method SetCompareSigma2 { image args } { SetImageToCompareControl $sigmaimagecontrol2  $image } 
+    public    method SetCompareN1     { num } 
+    public    method SetCompareN2     { num } 
+    public    method ClearCompareSigma1 {  args } { catch { $sigmaimagecontrol1 ClearObject } }
+    public    method ClearCompareSigma2 {  args } { catch { $sigmaimagecontrol2 ClearObject } }
+    # -----------------------------------------------------
+
+
+    public method ImagesModified { args }
+    public method SetResultsFromObject { img obj }  
+
+    # Other Stuff STORAGE
+    protected variable inputoutputtab 0
+
+    # GUI Stuff
+    protected method CreateContainedAlgorithmsGUIs { nt }
+    public    method DelayedCreateGUI { }
+
+    # protected variables for GUIs
+    protected    variable meanimagecontrol1 0
+    protected    variable meanimagecontrol2 0
+    protected    variable sigmaimagecontrol1 0
+    protected    variable sigmaimagecontrol2 0
+    protected    variable fourdimagecontrol1 0
+    protected    variable fourdimagecontrol2 0
+
+    protected variable comparetool 0
+    protected variable comparefourdtool 0
+
+    protected method  CreateImageCompareControl { origpar } 
+    protected method  CreateImageFourDCompareControl { origpar } 
+
+}
+
+
+#------------------------------------------------------------------------------------------
+itcl::body bis_guicompareutility::InitializeGUICompareUtility { } {
+
+    set inputs { }
+
+    set outputs { 
+	{ output_image "Results Image" pxitclimage  ""  }
+    }
+
+    
+    set scriptname "bis_guicompareutility"
+    set category "Graphical-User-Interface-Module"
+    set description " Utility Class for containing two image compare tools."
+    set backwardcompatibility "See (parts of) pxitcloverlaytool.tcl"
+    set authors "xenophon.papademetris at yale.edu."
+
+    set completionstatus "ongoing  -- Xenios needs to revisit"
+
+    # does not contain extract surface and mapfunctional
+    set componentnamelist [ list  bis_ttest bis_imagecompare ]
+    $this AddDefaultOptions
+}
+
+
+
+#------------------------------------------------------------------------------------------
+::itcl::body bis_guicompareutility::DelayedCreateGUI { } {
+    
+    $this CreateContainedAlgorithmsGUIs $maintabnotebook
+    set fullyinitialized 1
+    return 1
+}
+# -----------------------------------------------------------------------------
+::itcl::body bis_guicompareutility::CreateContainedAlgorithmsGUIs { nt } {
+
+    set comparetool 0
+    set comparefourdtool 0
+
+    set l [ llength $componentlist ]
+    for { set i 0 } { $i < $l } { incr i } {
+	set alg [ lindex $componentlist $i ]
+	if { [ $alg isa bis_ttest ] == 1 }  { 
+	    set comparefourdtool $alg
+	}
+	if { [ $alg isa bis_imagecompare ] == 1 }  { 
+	    set comparetool $alg
+	}
+	
+    }
+
+    #    puts stderr "Creating Image COmpare Control"
+
+    $this CreateImageCompareControl [ $nt add -label "Image Compare" ]
+    $this CreateImageFourDCompareControl [ $nt add -label "4D Image Compare" ]
+    return 1
+}
+
+# -----------------------------------------------------------------------------------
+itcl::body bis_guicompareutility::CreateImageCompareControl { origpar } {
+
+    label $origpar.top -bg black -fg white -text "Statistical Comparison"
+    pack $origpar.top -fill x -side top -expand f
+    
+    set statpar $origpar
+    frame $statpar.bot -bg gray; 
+    pack $statpar.bot -side bottom -expand f -fill x
+    
+    set meanimagecontrol1  [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+    set sigmaimagecontrol1 [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+    
+    set meanimagecontrol2 [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+    set sigmaimagecontrol2 [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+
+    set nt1 [ iwidgets::tabnotebook $statpar.1 -tabpos n  -angle 45 -margin 2 -backdrop gray -raiseselect true  ]
+    set nt2 [ iwidgets::tabnotebook $statpar.2 -tabpos n  -angle 45 -margin 2 -backdrop gray -raiseselect true   ]
+    pack $nt1 $nt2 -side top -expand false -fill x -pady 1
+    
+    
+    set clist [ list $meanimagecontrol1 $sigmaimagecontrol1 $meanimagecontrol2 $sigmaimagecontrol2 ]
+    set dlist [ list "Mean 1" "Standard Deviation 1" "Mean 2" "Standard Deviation 2" ]
+    set elist [ list $nt1 $nt1 $nt2 $nt2 ] 
+
+    for { set i 0 } { $i<=3 } { incr i } {
+	
+	set ctrl [ lindex $clist $i ]
+	set desc [ lindex $dlist $i ]
+	set nt   [ lindex $elist $i ]
+
+	set fr [ $nt add -label $desc ]
+
+	$ctrl configure -description $desc
+	$ctrl InitializeLite $fr.a 3
+	#$ctrl AddFunction "$this SetFunctionalImage" "Display" "$this" 
+	if { $i == 1 || $i == 3 } { 
+	    $fr configure -background darkgray
+	}
+	pack $fr.a -side top -expand f -fill x -pady 0 -padx 0
+	$ctrl configure -callback "$this ImagesModified 3d"
+    }
+
+    $nt1 view "Mean 1"
+    $nt2 view "Mean 2"
+
+
+    $comparetool SetGUIMode managed
+    $comparetool SetMainTabScrollMode 0
+    $comparetool CreateGUI $statpar.bot
+
+    
+}
+
+# --------------------------------------------------------
+itcl::body bis_guicompareutility::CreateImageFourDCompareControl { origpar } {
+
+    label $origpar.top -bg black -fg white -text "4D Image Statistical Comparison"
+    pack $origpar.top -fill x -side top -expand f
+
+    set statpar $origpar
+
+    frame $statpar.bot -bg gray; pack $statpar.bot -side bottom -expand f -fill x
+    $comparefourdtool SetGUIMode managed
+    $comparefourdtool SetMainTabScrollMode 0
+    $comparefourdtool CreateGUI $statpar.bot
+   
+    set fourdimagecontrol1 [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+    set fourdimagecontrol2 [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+
+    set clist [ list $fourdimagecontrol1 $fourdimagecontrol2 ]
+    set dlist [ list "4D Image 1" "4D Image 2" ]
+
+    for { set i 0 } { $i<=1 } { incr i } {
+	
+	set ctrl [ lindex $clist $i ]
+	set desc [ lindex $dlist $i ]
+
+	set nm $statpar.fr$i 
+
+
+	$ctrl configure -description $desc
+	$ctrl InitializeLite $nm 3
+	#	$ctrl AddFunction "$this SetFunctionalImage" "Display" "$this" 
+	pack $nm -side top -expand f -fill x -pady 0 -padx 0
+	$ctrl configure -callback "$this ImagesModified 4d"
+    }
+
+}
+# --------------------------------------------------------------------------------------
+
+::itcl::body bis_guicompareutility::ImagesModified { args } {
+
+    if { $meanimagecontrol1 == 0 ||  $comparetool == 0 ||  $comparefourdtool ==  0 } {
+	# GUI Not yet established
+	return
+    }
+    
+    set md [ lindex $args 0 ]
+
+    if { $md == "4d" } {
+#	puts stderr "updating comparefourdtool = $comparefourdtool"
+	$comparefourdtool SetInput [ $fourdimagecontrol1 GetObject ]
+	$comparefourdtool SetSecondInput [ $fourdimagecontrol2 GetObject ]
+    }
+
+    if { $md == "3d" } {
+#	puts stderr "updating comparetool = $comparetool"
+	$comparetool SetInput [ $meanimagecontrol1 GetObject ]
+	$comparetool SetSecondInput [ $meanimagecontrol2 GetObject ]
+	$comparetool SetInputObject first_sigma  [ $sigmaimagecontrol1 GetObject ]
+	$comparetool SetInputObject second_sigma [ $sigmaimagecontrol2 GetObject ]
+    }
+}
+
+
+#------------------------------------------------------------------------------------------
+::itcl::body bis_guicompareutility::SetResultsFromObject { img obj }  { 
+
+    set out [ $this GetFirstOutputObject ]
+    $out ShallowCopy $img
+    PrintDebug "In $this SetResultsFromObject, going to updatecontainerwithoutput, $containerobject\n\n\n"
+
+    $containerobject SetResultsFromObject $out $this
+}
+#------------------------------------------------------------------------------------------
+
+
+
+itcl::body bis_guicompareutility::SetCompareN1     { num } {
+    if { $comparetool !=0 } {
+	$comparetool SetOptionValue n1 $num
+    }
+}
+
+itcl::body bis_guicompareutility::SetCompareN2     { num }  {
+    if { $comparetool ==0 } {
+	return 
+    }
+    
+    if { $comparetool !=0 } {
+	$comparetool SetOptionValue n2 $num
+    }
+}
+
+
+itcl::body bis_guicompareutility::SetImageToCompareControl { ctrl image } {
+    if { $ctrl ==0 } {
+	return 
+    }
+    [ $ctrl GetObject ] ShallowCopy $image; 
+    $ctrl Update 
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guicontainer.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guicontainer.tcl
new file mode 100644
index 0000000..d663fcd
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guicontainer.tcl
@@ -0,0 +1,284 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_guicontainer 1.0
+package require bis_algorithm 1.0
+
+
+itcl::class bis_guicontainer {
+
+    inherit bis_algorithm
+
+    constructor { } {	$this InitializeGUIContainer  }
+
+    # Create Input/Output GUI Controls for Objects in standalone mode
+    protected method InitializeGUIContainer { }
+
+    # Create GUI Stuff etc.
+    public method CreateGUI { parent { callafter 0 } { callbefore 0 } }
+    public    method DelayedCreateGUI   { }
+    protected method CreateContainedAlgorithmsGUIs { nt }
+
+    # Invokation Stuff
+    protected    variable fullyinitialized 0
+    protected    variable buttonbar 0
+
+
+    # Method to add logo label to something 
+    public method AddToMenuButton { mb args}
+    public method ShowWindow { args }
+    public method HideWindow { }
+    public method SetTitle { title }
+    
+    # Method to create embedded controls -- nt = notebook to add tab in
+    public method CreateInputOutputControl { nt } { }
+    protected method CreateMainNotebook { name } 
+
+    public method TabCommand { } { }
+    protected method InitializeComponents {  }
+    protected method AddComponentsToMenuButton { mb }
+
+
+    protected variable componentnamelist ""
+    protected variable componentlist ""
+    protected variable extratablist  ""
+    protected variable dualImageList [ list ]
+
+}
+
+
+
+
+itcl::body bis_guicontainer::InitializeGUIContainer { } {
+
+    PrintDebug "bis_guicontainer::Initialize" 
+
+    set scriptname bis_guicontainer
+    set category "Graphical-User-Interface-Module"
+    set description "Abstract Clss for Containing a variety of algorithms."
+    set backwardcompatibility "Attempt to maintain compatibility with controls as expected in pxitclbaseimageviewer.tcl. "
+    set authors "xenophon.papademetris at yale.edu."
+
+    $this AddDefaultOptions
+}
+#------------------------------------------------------------------------------------------
+::itcl::body bis_guicontainer::InitializeComponents {  } {
+
+    set n [ llength $componentnamelist ]
+    for { set i 0 } { $i < $n } { incr i } {
+	
+	set ln [ lindex $componentnamelist $i ]
+
+	if { $ln !=0 && [ llength $ln ] == 1  } {
+	    eval "package require $ln"
+	    set alg [ [ $ln \#auto ] GetThisPointer ]
+	    $alg InitializeFromContainer [ $this GetThisPointer ]
+	    lappend componentlist $alg
+	}
+    }
+}
+
+
+#------------------------------------------------------------------------------------------
+::itcl::body bis_guicontainer::AddComponentsToMenuButton { mb} {
+
+
+    set l [ llength $componentlist ]
+    set ln [ llength $componentnamelist ]
+    set index 0
+    set cascindex 0
+
+    set pnt [ $this GetThisPointer ]
+
+    set spl [  split $pnt ":" ]
+    set pnt [ lindex $spl [ expr [ llength $spl ] -1 ] ]
+    #    puts stderr "To $pnt from $spl"
+    set current $mb
+
+
+    for { set i 0 } { $i < $ln } { incr i } {
+	set tp [ lindex $componentnamelist $i ]	
+	if { [ llength $tp ] > 1  } {
+	    set mname $mb.${pnt}${cascindex}
+	    set newm [ menu $mname -tearoff 0  ] 
+	    incr cascindex
+	    $mb add cascade -underline [ lindex $tp 0 ] -label [ lindex $tp 1] -menu $newm
+	    set current $newm
+	} elseif { $tp == 0 } {
+	    eval "$mb add separator"
+	    set current $mb
+	} elseif { $index < $l } {
+	    set alg [ lindex $componentlist $index ]
+	    set n [ $alg GetGUIName ]
+	    eval "$current add command -command {$this ShowWindow \"$n\" \"$alg\" } -label \"$n\" "
+	    incr index
+	}
+    }
+}
+
+
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_guicontainer::AddToMenuButton { mb args} {
+    
+
+    for { set i 0 } { $i < [ llength $extratablist ] } { incr i } {
+	set n [ lindex $extratablist $i ]
+	eval "$mb add command -command {$this ShowWindow \"$n\"  } -label \"$n\" "
+    }
+    if { [ llength $extratablist ] > 0 } {
+	$mb add separator
+    }
+    $this AddComponentsToMenuButton $mb
+
+} 
+
+
+
+::itcl::body bis_guicontainer::CreateGUI { basew { callafter 0 } { callbefore 0 } } {
+
+    if { $fullyinitialized == 1 } {
+	return
+    }
+
+    set callbackbefore $callbefore
+    set callbackafter  $callafter
+    set progressbar($this) 0
+    set progress_lab($this) "Status"
+    set progress_val($this) 0
+
+    set basewidget $basew
+    set fullyinitialized 0
+    $this InitializeComponents
+}
+
+::itcl::body bis_guicontainer::DelayedCreateGUI { } {
+
+
+    if { $fullyinitialized == 1 } {
+	return 1
+    }
+
+    if { $basewidget == 0 } {
+	return 0
+    }
+
+    set tp [ toplevel $basewidget ];  wm withdraw $tp
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget  }"
+
+
+    set buttonbar [ frame $basewidget.bt ]
+    set bbt [ frame $basewidget.bt2 -bg black -height 5 ]
+    
+
+    pack $buttonbar $bbt -side bottom -expand false -fill x 
+    
+    eval "button $buttonbar.close   -text Close -command { wm withdraw $basewidget }"
+    pack $buttonbar.close -side right
+
+    set nt [ $this CreateMainNotebook  $basewidget.nt ]
+    set maintabnotebook $nt
+    pack $nt -side top -expand true -fill both
+
+    $this CreateInputOutputControl $nt
+    $this CreateContainedAlgorithmsGUIs $nt
+
+
+    set canvas [ [ $nt component tabset ] component canvas ]
+    set l [ AddLogoLabel $canvas ]
+    pack $l -side bottom -expand false -fill x
+
+
+
+    set fullyinitialized 1
+    return 1
+}
+# -----------------------------------------------------------------------------
+::itcl::body bis_guicontainer::CreateMainNotebook { name } {
+
+    set nt [ iwidgets::tabnotebook $name -tabpos w  -margin 2 -backdrop gray -raiseselect true -width 500]
+    return $nt
+}
+# -----------------------------------------------------------------------------
+::itcl::body bis_guicontainer::CreateContainedAlgorithmsGUIs { nt } {
+
+    set l [ llength $componentlist ]
+    for { set i 0 } { $i < $l } { incr i } {
+	set alg [ lindex $componentlist $i ]
+	
+	set n [ $alg GetGUIName ]
+
+	set w [ $nt add -label $n -command [ itcl::code $this TabCommand ] ]	
+	
+	set isdual 0 ; catch { set isdual [ $alg IsDualImage ] }
+	if { $isdual } { 
+	    lappend dualImageList $alg 
+	}
+	
+	$alg SetGUIMode managed
+	$alg CreateGUI $w
+    }
+
+}
+# -----------------------------------------------------------------------------
+
+
+::itcl::body bis_guicontainer::ShowWindow { args } {
+
+    if { $basewidget == 0 } { 
+	return 
+    }
+
+    if { $fullyinitialized == 0 } {
+	PrintDebug "From Show Window Calling DelayedCreateGUI $fullyinitialized"
+	$this DelayedCreateGUI
+    }
+  
+    if { $maintabnotebook !=0 && [ llength $args ] > 0 } {
+	$maintabnotebook view [ lindex $args 0 ]
+    }
+
+
+
+    catch  {
+	if { [ winfo ismapped $basewidget ] == 1 } {
+	    wm withdraw $basewidget
+	}
+	wm deiconify $basewidget
+    }
+    return $basewidget
+}
+# ----------------------------------------------------------
+::itcl::body bis_guicontainer::HideWindow { } {
+    catch { wm withdraw $basewidget }
+}
+# ----------------------------------------------------------
+::itcl::body bis_guicontainer::SetTitle { title } {
+    catch {  wm title $basewidget $title }
+}
+# ----------------------------------------------------------
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guiimageutility.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guiimageutility.tcl
new file mode 100644
index 0000000..4b5904f
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guiimageutility.tcl
@@ -0,0 +1,248 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_guiimageutility 1.0
+package require bis_guicontainer 1.0
+
+
+itcl::class bis_guiimageutility {
+
+    inherit bis_guicontainer
+
+    constructor { { 4dmode 0 }  } { 
+	$this InitializeGUIImageUtility $4dmode 
+    }
+
+    # Create Input/Output GUI Controls for Objects in standalone mode
+    protected method InitializeGUIImageUtility { { 4dmode 0 } }
+
+
+    # The following methods are needed by pxitclbaseimageviewer 
+    #                  type main applications
+    # Change Current Working Directory
+    # 
+    public method SetImageFromObject { img obj  } 
+    public method SetImage { img { img2 0 } } 
+
+    # Methods for chaining into other tools
+    public method SetResultsFromObject { img obj } 
+    public    method DelayedCreateGUI   { }
+
+    # Public Method -- data model control
+    public method CreateInputOutputControl { nt } 
+    public method SecondImageModified { args  }
+    public method GrabViewerImage { args }
+
+    # protected variables for GUIs
+    protected variable image_gui 0
+    protected variable second_gui 0
+    protected variable fourdmode 0
+}
+
+
+
+#------------------------------------------------------------------------------------------
+itcl::body bis_guiimageutility::InitializeGUIImageUtility { { 4dmode 0 } } {
+
+    set inputs { 
+	{ input_image "Input Image" pxitclimage  ""  }
+	{ second_image "Second Input Image" pxitclimage  ""  }
+    }
+    
+    set outputs {
+	{ output_image "Output Image"  pxitclimage  "" }
+    }
+    
+    set scriptname bis_guiimageutility
+    set category "Graphical-User-Interface-Module"
+    set description "Image Utility Clss for containing a variety of image-to-image algorithms."
+    set backwardcompatibility "An upgrade of pxitclimageutility.tcl. "
+    set authors "xenophon.papademetris at yale.edu."
+
+    set completionstatus "ongoing  -- Xenios needs to revisit"
+
+    set fourdmode $4dmode
+
+    if { $fourdmode == 0 } {
+	set componentnamelist [ list { 0 Smooth } bis_smoothimage bis_convolveimage bis_nonlinearsmoothimage bis_imagemedian bis_imagedilate bis_edgedetectimage \
+				    { 0 Relabel }  bis_relabelimage  bis_newreorientimage \
+				    { 0 Threshold } bis_thresholdimage bis_listthresholdimage bis_clusterthresholdimage \
+				    { 0 Modify } bis_castimage bis_logimage bis_shiftscaleimage bis_piecewiseimagemap bis_distancemapimage \
+				    { 0 Bias_Field } bis_sliceinhomogeneity bis_biasfield \
+				    { 1 Segment } bis_stripskull bis_intsegment \
+				    { 1 Crop/Resample }   bis_flipimage bis_resampleimage bis_manualreslice bis_cropimage bis_cylindricalcropimage \
+				    { 2 Statistics } bis_fdr bis_rtotmap bis_rtopvalue bis_tmaptopvalue bis_tmaptozscore bis_computecorrelations \
+				    { 0 FFT}  bis_fftimage bis_rfftimage ]
+    } else {
+	set componentnamelist [ list { 0 "4D Processing"}  bis_combineframes bis_interleave  bis_preprocessimage bis_temporalsmoothimage bis_mediantemporalsmoothimage bis_imageremoveframes bis_exponentialfitimage bis_exponentialfitt1 ]
+    }
+
+    $this AddDefaultOptions
+}
+
+
+
+::itcl::body bis_guiimageutility::DelayedCreateGUI { } {
+
+    if { $fullyinitialized == 1 } {
+	return 1
+    }
+
+    ::bis_guicontainer::DelayedCreateGUI 
+
+    if { $fourdmode == 0 } {
+	wm geometry $basewidget 600x850
+    } else {
+	wm geometry $basewidget 600x400
+    }
+
+    if { $fullyinitialized == 0 } {
+	return 0
+    }
+
+     if { $containerobject !=0 } {
+ 	eval "button $buttonbar.l1  -text \"Copy Results To Image\" -command { $containerobject CopyResultsToImage }"
+ 	pack $buttonbar.l1 -side left
+     }
+
+
+    if { $fourdmode == 0 } {
+	$this SetTitle "BioImageSuite::Image Utility v2 (bis_algo)"
+    } else {
+	$this SetTitle "BioImageSuite::4D Image Utility v2 (bis_algo)"
+    }
+    set fullyinitialized 1
+
+
+    return 1
+}
+#------------------------------------------------------------------------------------------
+
+
+::itcl::body bis_guiimageutility::SetImageFromObject { img obj  }  {
+    $this SetImage $img
+}
+
+::itcl::body bis_guiimageutility::SetImage { img { img2 0 }  }  { 
+
+    #    PrintDebug "\n\n\n\n\n\n .... GetImage \n\n\n\n"
+
+
+    set timg [ $this GetFirstInputObject ]
+    $timg ShallowCopy $img
+    if { $image_gui !=0 } {
+	$image_gui Update
+    }
+
+    
+
+    if { $img2 != 0 } {
+	set timg2 [ $this GetSecondInputObject ]
+	$timg2 ShallowCopy $img2
+	if { $second_gui !=0 } {
+	    $second_gui Update
+	}
+    }
+
+    set l [ llength $componentlist ]
+    for { set i 0 } { $i < $l } { incr i } {
+	set alg [ lindex $componentlist $i ]
+	PrintDebug "In $this SetImage, going to call $alg UpdateInputsFromImageutility"
+	$alg UpdateInputsFromContainer
+#	puts stderr "Updated algorithm $alg , number of inputs= [ llength [ $alg GetInputsList ] ], [ $alg GetInputsList ]"
+    }
+}
+
+
+::itcl::body bis_guiimageutility::SetResultsFromObject { img obj }  { 
+
+    set out [ $this GetFirstOutputObject ]
+    $out ShallowCopy $img
+    PrintDebug "In $this SetResultsFromObject, going to updatecontainerwithoutput, $containerobject\n\n\n"
+
+    $containerobject SetResultsFromObject $out $this
+}
+
+
+::itcl::body bis_guiimageutility::GrabViewerImage { args } {
+    set vv 0
+    set vv [ $this GetViewer ]
+    if { $vv !=0 } {
+	# This has a problem with headers -- hence save is disabled, mostly used to create masks etc.
+	set timg2 [ $this GetSecondInputObject ]
+	$timg2 ShallowCopyImage [ $vv GetImage ]
+	$second_gui Update
+	$this SecondImageModified
+    }
+}
+
+    
+::itcl::body bis_guiimageutility::SecondImageModified { args } {
+
+    set l [ llength $componentlist ]
+    for { set i 0 } { $i < $l } { incr i } {
+	set alg [ lindex $componentlist $i ]
+	if { [ llength [ $alg GetInputsList ] ] > 2 } {
+	    #	    puts stdout "Updating $alg"
+	    $alg UpdateInputsFromContainer
+	}
+    }
+}
+
+::itcl::body bis_guiimageutility::CreateInputOutputControl { nt } {
+ 
+    set inputoutputtab [ $nt add -label "Inputs" ]   
+    set w $inputoutputtab
+
+    set image_gui [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $image_gui configure -description "Input Image"
+
+    set second_gui [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $second_gui configure -description "Second Input Image"
+
+    set slist [ list $image_gui $second_gui ]
+    for { set i 0 } { $i <=1 } { incr i } {
+	set c [ lindex $slist $i ]
+	$c Initialize $w.$i
+	
+	if { $i == 0 } {
+	    pack forget [ $c cget -loadbutton ]
+	    pack forget [ $c cget -clearbutton ]
+	    pack forget [ $c cget -browsebutton ]
+	} else {
+	    pack forget [ $c cget -savebutton ]
+	    $c AddFunction "$this GrabViewerImage" "Grab From Viewer" "$this"
+	}
+
+	pack $w.$i -side top -expand false -fill x -pady 5 -padx 5
+    }
+    
+    
+    $image_gui SetObject [ $this GetFirstInputObject ]
+    $second_gui SetObject [ $this GetSecondInputObject ]
+    $second_gui configure -callback "$this SecondImageModified"
+}
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guioverlayutility.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guioverlayutility.tcl
new file mode 100644
index 0000000..7125610
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guioverlayutility.tcl
@@ -0,0 +1,655 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_guioverlayutility 1.0
+package require bis_guicontainer 1.0
+package require bis_guicompareutility 1.0
+
+
+
+itcl::class bis_guioverlayutility {
+
+    inherit bis_guicontainer
+
+    constructor { } { $this InitializeGUIOverlayUtility  }
+
+    # Create Input/Output GUI Controls for Objects in standalone mode
+    protected method InitializeGUIOverlayUtility { }
+    public method DelayedCreateGUI { }
+
+
+    # Methods for chaining into other tools
+    public method SetResultsFromObject { img obj } 
+    public method SetTransformationFromObject { tr obj } 
+    public method SetImageFromObject { img obj } 
+
+    #
+    public method UpdateContainedAlgorithms { { includereslice 1 } }
+    public method SetSecondContainerObject { cont2 } { set containerobject2 $cont2 }
+
+
+    # methods for getting stuff
+    public method GetReferenceImage   { } { return [ $this GetInputObject reference_image ] }
+    public method GetTargetImage      { } { return [ $this GetInputObject target_image    ] }
+    public method GetReslicedImage    { } { return [ $this GetInputObject resliced_image  ] }
+    public method GetTransformation   { } 
+    public method SetTransformation   { newtr args } 
+    public method LoadAndAddTransformation { fname } 
+    public method AddTransformation { tr { name "" }  }
+
+    public method SetReslicedImageAndTransformation { alg }
+
+
+    protected method UpdateTransformation   { } 
+    public method UpdateTransformationCallback   { } 
+
+    # transform/weight image control
+    public method CreateInputOutputControl { nt }
+    protected method CreateManualControl { base }
+    public method WeightImagesModified { args }
+
+    # Force image reslice if needed as input for various algorithms
+    protected method CheckCachedReslicedSecondInputIsCorrect { } 
+    public method EnsureCachedReslicedSecondInputIsCorrect { { force 0 } } 
+
+
+    # Other Stuff STORAGE
+    protected variable inputoutputtab 0
+    protected variable transformation_control 0
+    protected variable containerobject2 0
+
+    protected variable current_transformation  [ [ pxitcltransform \#auto ] GetThisPointer ]
+    protected variable owns_current_transformation 1
+    protected variable reslice_alg 0
+
+    # protected variables for GUIs
+    protected variable ref_weight_gui 0
+    protected variable trg_weight_gui 0
+    
+    # Compare utility
+    protected variable compareutility 0
+    public method GetCompareUtility { } { return $compareutility }
+
+
+    # Manual Transformation Related
+    public   method CreateManualTransformGUI { parent}
+    public   method ClearManualTransformGUI { }
+    public   method SetManualTransform { }
+    public   method ExtractLinearTransform { in_xform image_ref image_trn numparam }
+    public   method SetManualTransformGUI { }
+
+    protected variable manualparam
+
+    # Modified Times
+    
+}
+
+
+#------------------------------------------------------------------------------------------
+itcl::body bis_guioverlayutility::InitializeGUIOverlayUtility { } {
+
+    set inputs { 
+	{ reference_image   "Reference Image"   pxitclimage  ""  }
+	{ target_image    "Target    Image"   pxitclimage  ""  }
+	{ resliced_image    "Resliced Image"   pxitclimage  ""  }
+	{ reference_weight_image   "Reference Weight Image"   pxitclimage  ""  }
+	{ target_weight_image    "Target Weight Image"   pxitclimage  ""  }
+
+    }
+
+    set outputs { 
+	{ output_image "Results Image" pxitclimage  ""  }
+    }
+
+    
+    set scriptname "bis_guioverlayutility"
+    set category "Graphical-User-Interface-Module"
+    set description " Utility Class for containing a variety of registration and image merge algorithms."
+    set backwardcompatibility "See pxitcloverlaytool.tcl"
+    set authors "xenophon.papademetris at yale.edu."
+
+    set completionstatus "ongoing  -- Xenios needs to revisit"
+
+    # does not contain extract surface and mapfunctional
+    set componentnamelist [ list  bis_createoverlayimage bis_manualregistration { 0 Combine Images }  bis_stitchimage  bis_blendimage bis_maskimage bis_colorblendimage bis_checkerboardimage { 0 Compare Images } bis_imagemathoperations bis_singlejacobian  bis_computesimilarity bis_computeoverlap { 0 Registration }  bis_linearintensityregister bis_nonlinearintensityregister bis_nonlineardistortioncorrection  bis_computedisplacementfield bis_visualizetransformation ]
+    $this AddDefaultOptions
+
+    set extratablist { "Transformations" "Weight Images" "Image Compare" "4D Image Compare" }
+    
+    package require bis_resliceimage
+    set reslice_alg [ [ bis_resliceimage \#auto ] GetThisPointer ]
+    $reslice_alg InitializeFromContainer [ $this GetThisPointer ]
+}
+
+
+#------------------------------------------------------------------------------------------
+::itcl::body bis_guioverlayutility::DelayedCreateGUI { } {
+
+    if { $fullyinitialized == 1 } {
+	return 1
+    }
+
+    ::bis_guicontainer::DelayedCreateGUI 
+    wm geometry $basewidget 720x540
+
+    if { $fullyinitialized == 0 } {
+	#	puts stderr "Can not create gui in bis_guioverlayutility"
+	return 0
+    }
+
+     if { $containerobject !=0 } {
+	 eval "button $buttonbar.l1  -text \"Copy Results To Image\" -command { $containerobject CopyResultsToImage }"
+	 pack $buttonbar.l1 -side left
+     }
+
+
+    
+    $this SetTitle "BioImageSuite::Overlay/Registration Utility v2 (bis_algo)"
+    set fullyinitialized 1
+    return 1
+}
+
+
+
+#------------------------------------------------------------------------------------------
+#  Called by surfacetosurface filter to pass output back up the chain
+#------------------------------------------------------------------------------------------
+::itcl::body bis_guioverlayutility::SetResultsFromObject { img obj }  { 
+
+    set out [ $this GetFirstOutputObject ]
+    $out ShallowCopy $img
+    PrintDebug "In $this SetResultsFromObject, going to updatecontainerwithoutput, $containerobject\n\n\n"
+    $containerobject SetResultsFromObject $out $this
+
+    set keep 0
+
+    if { $obj == $reslice_alg } { set keep 1 } 
+    
+    if { $keep == 1 } {
+	[ $this GetReslicedImage ] ShallowCopy $img
+	$this UpdateContainedAlgorithms 0
+    }
+}
+
+::itcl::body bis_guioverlayutility::SetTransformationFromObject { tr obj }  { 
+
+    # add the incoming tr
+    $this DelayedCreateGUI
+
+    if { $transformation_control == 0 } {
+	return 0
+    }
+
+    $transformation_control AddInternalObject 
+    set basetr [ $transformation_control GetCurrentObject ]
+    $basetr Copy $tr
+
+    $transformation_control CurrentObjectModified
+
+
+}
+
+# --------------------------------------------------------------------------------------
+
+::itcl::body bis_guioverlayutility::SetImageFromObject { img obj  }  {
+
+
+
+    if { $obj == $containerobject } {
+	$this SetInputObject target_image $img
+    } else {
+	$this SetInputObject reference_image $img
+    }
+
+    #    puts stderr "Getting Image $img from obj=$obj ($containerobject), updating contained algorithms"
+    $this UpdateContainedAlgorithms 
+}
+
+
+# ------------------------------------------------------------------------------------
+# Transformation Interface
+# ------------------------------------------------------------------------------------
+
+::itcl::body bis_guioverlayutility::GetTransformation   { }  {
+
+    $this UpdateTransformation
+    return $current_transformation 
+}
+
+itcl::body bis_guioverlayutility::LoadAndAddTransformation { fname } {
+
+    $this DelayedCreateGUI
+    $transformation_control AddInternalObject 
+    set basetr [ $transformation_control GetCurrentObject ]
+    $basetr Load [ pxtclutil::GetAbsoluteFileName $fname ]
+    $transformation_control CurrentObjectModified
+}
+
+
+itcl::body bis_guioverlayutility::AddTransformation { tr { name "" } } {
+
+    $this DelayedCreateGUI
+    set ind [ $transformation_control GetNextObjectIndex ]
+
+    if { $name == "" } {
+	$transformation_control AddInternalObject 
+    } else {
+	$transformation_control AddObject  "$name.$ind"
+    }
+    set basetr [ $transformation_control GetCurrentObject ]
+
+    set vtkmode 1
+    catch { 
+	if { [ $obj isa pxitcltransform ] == 1 } {
+	    set vtkmode 0
+	}
+    }
+    
+    if { $vtkmode == 0 } {
+	$basetr Copy $tr
+    } else {
+	$basetr CopyTransformation $tr
+    }
+    $transformation_control CurrentObjectModified
+    return $ind
+}
+# -----------------------------------------------------------------------
+
+itcl::body bis_guioverlayutility::SetTransformation { newtr args } {
+
+    set mode "modify"
+
+    if { [ llength $args ] > 0 } {
+	set mode [ lindex $args 0 ]
+    }
+
+    $this DelayedCreateGUI
+
+
+    if { $mode == "add" } {
+	$transformation_control AddInternalObject 
+    }
+
+    set basetr [ $transformation_control GetCurrentObject ]
+    $basetr CopyTransformation $newtr
+    $transformation_control CurrentObjectModified
+    update idletasks
+}
+
+# -------------------------------------------------------------------
+
+::itcl::body bis_guioverlayutility::SetReslicedImageAndTransformation { alg } {
+
+    set ok 0
+    if { $alg == $reslice_alg } {
+	return
+    }
+
+    if { $alg != $reslice_alg } {
+	set ok [ $this CheckCachedReslicedSecondInputIsCorrect ]
+    }
+
+    if { $ok == 1 } {
+	$alg SetSecondInput [ $this GetReslicedImage ]
+	[ $alg GetTransformation ] Clear 
+    } else {
+	$alg SetSecondInput [ $this  GetTargetImage ]
+	$alg SetTransformation [ $this GetTransformation ]
+    }
+}
+
+
+::itcl::body bis_guioverlayutility::UpdateTransformation   { }  {
+    
+    if { $transformation_control == 0 } { return 0 } 
+
+    if {  $owns_current_transformation == 1 } {
+	itcl::delete object $current_transformation
+	set owns_current_transformation 0
+    }
+    set current_transformation [ $transformation_control GetObject -1 ]
+
+}
+
+::itcl::body bis_guioverlayutility::UpdateTransformationCallback   { }  {
+
+    [ $this GetReslicedImage ] Clear
+    $this UpdateTransformation
+    $this UpdateContainedAlgorithms
+}
+
+#------------------------------------------------------------------------------------------
+#  Called to update contained algorithms
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_guioverlayutility::UpdateContainedAlgorithms { { includereslice 1 } } { 
+
+    if { $includereslice > 0 } {
+	$reslice_alg UpdateInputsFromContainer
+    }
+
+    set l [ llength $componentlist ]
+    for { set i 0 } { $i < $l } { incr i } {
+	set alg [ lindex $componentlist $i ]
+	catch { $alg SetResliceAlgorithm $reslice_alg  }
+	$alg UpdateInputsFromContainer
+    }
+
+}
+
+
+#------------------------------------------------------------------------------------------
+
+itcl::body bis_guioverlayutility::WeightImagesModified {  } {
+
+#    puts stderr "Weight Images Changed..."
+    set l [ llength $componentlist ]
+    for { set i 0 } { $i < $l } { incr i } {
+	set alg [ lindex $componentlist $i ]
+	if { [ $alg isa bis_baseintensityregistration  ] == 1 } {
+	    #	puts stderr "Updating $alg"
+	    $alg SetInputObject weight_image  [ $this GetInputObject reference_weight_image ]
+	    $alg SetInputObject weight_image2  [ $this GetInputObject target_weight_image ]
+	}
+    }
+}
+
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_guioverlayutility::CreateInputOutputControl { nt } {
+
+
+    set inputoutputtab [ $nt add -label "Transformations" ]
+    
+    set w $inputoutputtab
+
+
+    set transformation_control [ [ pxitclmultiTransformGUI \#auto  ] GetThisPointer ]
+    $transformation_control Initialize $w.b
+    $transformation_control AddTransformation "Default"
+    eval "$transformation_control configure -callback \"$this UpdateTransformationCallback\""
+    $this UpdateTransformation
+
+    pack $w.b -side top -expand false -fill x
+
+    iwidgets::labeledframe $w.c  -labeltext "Image Reslice"   
+    pack $w.c -side bottom -expand true -fill x
+
+    set isdual 0 ; catch { set isdual [ $reslice_alg IsDualImage ] }
+    if { $isdual } { 
+	lappend dualImageList $reslice_alg
+    }
+    $reslice_alg SetGUIMode managed
+    $reslice_alg CreateGUI [ $w.c childsite ]
+    
+    set w2 [ $nt add -label "Weight Images" ]   
+    label $w2.top -bg black -fg white -text "Use these to specify registration weights"
+
+    set ref_weight_gui [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $ref_weight_gui configure -description "Reference Image Weight"
+
+    set trg_weight_gui [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $trg_weight_gui configure -description "Transform Image Weight"
+
+
+    set slist [ list $ref_weight_gui $trg_weight_gui ]
+    for { set i 0 } { $i <=1 } { incr i } {
+	set c [ lindex $slist $i ]
+	$c InitializeLite $w2.$i 3
+	$c configure -callback "$this WeightImagesModified"
+	pack $w2.$i -side top -expand false -fill x -pady 5 -padx 5
+    }
+    
+    
+    $ref_weight_gui SetObject [ $this GetInputObject reference_weight_image ]
+    $trg_weight_gui SetObject [ $this GetInputObject target_weight_image   ]
+
+    set compareutility  [ [ bis_guicompareutility \#auto ] GetThisPointer ]
+    $compareutility InitializeFromContainer $this
+    $compareutility CreateGUI $maintabnotebook
+    $compareutility SetMainTabNotebook $maintabnotebook
+    $compareutility DelayedCreateGUI 
+
+}
+
+
+
+itcl::body bis_guioverlayutility::CheckCachedReslicedSecondInputIsCorrect {  } {
+
+    set image_ref     [ [ $this GetReferenceImage ] GetImage ]
+    set image_trn     [ [ $this GetTargetImage    ] GetImage ]
+    set resliced_tmap [ [ $this GetReslicedImage  ] GetImage ]
+    
+    set r [ $image_ref GetMTime ]
+    set t [ $image_trn GetMTime ]
+    set x [ [ [ $this GetTransformation ] GetTransformation ] GetMTime ]
+    set o [ $resliced_tmap GetMTime ]
+    if { $o > $r && $o > $t && $o > $x } {
+
+	#	puts stdout "Perhaps no Update Needed, [ expr $o - $r ] ,[ expr $o - $t ],  [ expr $o - $x ]"
+
+	set dim1 [ $image_ref GetDimensions ]
+	set dim2 [ $image_trn GetDimensions ]
+	if { [lindex $dim2 0 ] <2 || [ lindex $dim1 0 ] < 2 } { 
+	    #	puts stderr "Bad Image Sizes ..."
+	    return -1
+	}
+    
+	scan [ $image_ref GetDimensions ] "%d %d %d" dx1 dy1 dz1
+	scan [ $resliced_tmap  GetDimensions ] "%d %d %d" dx2 dy2 dz2
+	
+	if { $dx1==$dx2 && $dy1==$dy2 && $dz1 == $dz2 } {
+	    #	puts stderr "Size is Correct .... "
+	    return 1
+	}
+    }
+
+#    puts stdout "CachedResliced is Bad Update Needed, [ expr $o - $r ] ,[ expr $o - $t ],  [ expr $o - $x ]"
+    return 0
+}
+
+itcl::body bis_guioverlayutility::EnsureCachedReslicedSecondInputIsCorrect { { force 0 } } {
+
+    if { $force == 0 } {
+	set ok [ $this CheckCachedReslicedSecondInputIsCorrect ]
+	if { $ok !=0 } {
+	    return $ok
+	}
+    }
+
+    $reslice_alg UpdateInputsFromContainer
+    $reslice_alg Execute
+    [ $this GetReslicedImage ] ShallowCopy [ $reslice_alg GetOutput ] 
+
+    if { $force == 1 } {
+	$containerobject SetResultsFromObject [ $reslice_alg GetOutput ] $this
+    }
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------
+#   Manual Transform GUI
+# -----------------------------------------------------------------------
+itcl::body bis_guioverlayutility::CreateManualTransformGUI { parentw  } {
+
+    for { set i 0 } { $i <= 2 } { incr i } {
+
+	if { $i ==0 } { 
+	    set name "x"
+	} elseif { $i ==1 } {
+	    set name "y"
+	} else {
+	    set name "z"
+	}
+
+	set f [ frame ${parentw}.$name ] ; pack $f -side top -expand t -fill x
+
+	iwidgets::entryfield $f.1 -labeltext "${name}-Shift:" -fixed 6 -width 6 -validate real -textvariable [ itcl::scope  manualparam($this,manxf_shift${name}) ]
+	iwidgets::entryfield $f.2 -labeltext "${name}-Rotate:" -fixed 6 -width 6 -validate real -textvariable [ itcl::scope  manualparam($this,manxf_rotate${name}) ]
+	iwidgets::entryfield $f.3 -labeltext "${name}-Scale:" -fixed 6 -width 6 -validate real -textvariable [ itcl::scope  manualparam($this,manxf_scale${name}) ]
+	pack $f.1 $f.2 $f.3 -side left -expand f -fill x
+    }
+    
+    $this ClearManualTransformGUI
+    set f [ frame $parentw.bot] 
+    pack $f -side bottom -expand t -fill x
+    
+    eval "button $f.1 -text \"Set Xformation\" -command { $this SetManualTransform }"
+    eval "button $f.2 -text \"Set & Apply\" -command { $this SetManualTransform ; $this EnsureCachedReslicedSecondInputIsCorrect 1}"
+    eval "button $f.3 -text \"Extract!\" -command { $this SetManualTransformGUI  }"
+    eval "button $f.4 -text \"Clear Values\" -command { $this ClearManualTransformGUI }"
+    pack $f.1 $f.2 $f.3 $f.4 -side left -padx 5
+
+
+}
+# ----------------------------------------------------------------------------------------------
+itcl::body bis_guioverlayutility::ClearManualTransformGUI { } {
+
+    for { set i 0 } { $i <=2 } { incr i } {
+
+	if { $i == 0 } { 
+	    set pname "x"
+	} elseif { $i == 1 } {
+	    set pname "y"
+	} else {
+	    set pname "z"
+	}
+
+	set manualparam($this,manxf_scale$pname) 100
+	set manualparam($this,manxf_rotate$pname) 0
+	set manualparam($this,manxf_shift$pname) 0
+    }
+}
+
+
+
+itcl::body bis_guioverlayutility::SetManualTransform { } {
+    
+    for { set i 0 } { $i <=2 } { incr i } {
+	
+	if { $i == 0 } { 
+	    set pname "x"
+	} elseif { $i == 1 } {
+	    set pname "y"
+	} else {
+	    set pname "z"
+	}
+
+	set scale($pname) $manualparam($this,manxf_scale$pname)
+	if { $scale($pname) < 10 } { 
+	    set scale($pname) 10 
+	} elseif { $scale($pname) > 1000.0 } {
+	    set scale($pname) 1000.0
+	}
+
+	set dshift($pname) $manualparam($this,manxf_shift$pname)
+	if { $dshift($pname) < -2000 } { 
+	    set dshift($pname) -2000
+	} elseif { $dshift($pname) > 2000.0 } {
+	    set dshift($pname) 2000.0
+	}
+				     
+	set drotate($pname) $manualparam($this,manxf_rotate$pname)
+	if { $drotate($pname) < -360 } { 
+	    set drotate($pname) 360
+	} elseif { $drotate($pname) > 360.0 } {
+	    set drotate($pname) 360.0
+	}
+
+    }
+
+    set image_trn  [ $this GetTargetImage ] 
+    set image_ref  [ $this GetReferenceImage ]
+
+    set sp(x) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 0 ]
+    set sp(y) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 1 ]
+    set sp(z) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 2 ]
+
+
+
+    set tr2 [ vtkTransform [ pxvtable::vnewobj ]]
+    set xform [ vtkpxLinearTransform [ pxvtable::vnewobj ]]
+    $xform ManualSetParameters [expr $dshift(x)*$sp(x) ] [ expr $dshift(y) * $sp(y) ] [ expr $dshift(z)*$sp(z) ] $drotate(x) $drotate(y) $drotate(z) $scale(x) $scale(y) $scale(z)  [ $image_ref GetImage ] [ $image_ref GetOrientation ] [  $image_trn GetImage ] [ $image_trn GetOrientation ] $tr2
+    $this SetTransformation $tr2
+    $xform Delete
+    $tr2 Delete
+}
+
+
+itcl::body bis_guioverlayutility::ExtractLinearTransform { in_xform image_ref image_trn numparam } {
+
+    set image_trn  [ $this GetTargetImage ] 
+    set image_ref  [ $this GetReferenceImage ]
+
+    
+    set xform [ vtkpxLinearTransform [ pxvtable::vnewobj ]]
+    $xform ExtractParameters [ $in_xform GetTransformation ] 9  [ $image_ref GetImage ] [ $image_ref GetOrientation ] [  $image_trn GetImage ] [ $image_trn GetOrientation ]
+
+    for { set k $numparam } { $k < 15 } { incr k } {
+	$xform Put $k 0
+    }
+    return $xform
+}
+
+itcl::body bis_guioverlayutility::SetManualTransformGUI {  } {
+
+    set in_xform [ $this GetTransformation ]
+
+
+    set image_trn  [ $this GetTargetImage ] 
+    set image_ref  [ $this GetReferenceImage ]
+
+
+    set xform [ $this ExtractLinearTransform $in_xform $image_ref $image_trn 9 ]
+    set or [ list [ $xform  Get 3 ] [ $xform  Get 4 ] [ $xform  Get 5 ] ]
+    set sc [ list [ $xform  Get 6 ] [ $xform  Get 7 ] [ $xform  Get 8 ] ]
+    set tr [ list [ $xform  Get 0 ] [ $xform  Get 1 ] [ $xform  Get 2 ] ]
+
+    set sp(x) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 0 ]
+    set sp(y) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 1 ]
+    set sp(z) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 2 ]
+    
+    for { set i 0 } { $i <=2 } { incr i } {
+	
+	if { $i == 0 } { 
+	    set pname "x"
+	} elseif { $i == 1 } {
+	    set pname "y"
+	} else {
+	    set pname "z"
+	}
+	
+	set manualparam($this,manxf_scale$pname) [lindex $sc $i ]
+	set manualparam($this,manxf_rotate$pname) [ lindex $or $i ]
+	set manualparam($this,manxf_shift$pname) [ expr [ lindex $tr $i ] / $sp($pname) ]
+    }
+    $xform Delete
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guirpmcontainer.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guirpmcontainer.tcl
new file mode 100644
index 0000000..0644324
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guirpmcontainer.tcl
@@ -0,0 +1,274 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_guirpmcontainer 1.0
+package require bis_guicontainer 1.0
+
+
+itcl::class bis_guirpmcontainer {
+
+    inherit bis_guicontainer
+
+    constructor { } { $this InitializeGUIRpmContainer  }
+
+    # Create Input/Output GUI Controls for Objects in standalone mode
+    protected method InitializeGUIRpmContainer { }
+    public method DelayedCreateGUI { }
+
+
+    # Methods for chaining into other tools
+    public method SetTransformationFromObject { tr obj } 
+
+    # Update Stuff
+    public method UpdateContainedAlgorithms { }
+
+
+    # transform/weight surface control
+    public method CreateInputOutputControl { nt }
+    public method InputsModified { args }
+
+    # Update Stuff
+    public method HasRPMGUI { } { return 1 }
+    public method UpdateRPMViewer { visib alg currentregistration } 
+
+    # methods for getting stuff
+    public method GetTransformation { }
+    public method GetOutputTransformation { } { return [ $this GetTransformation ] }
+    public method GetReferenceSurface { }
+    public method GetTransformSurface { }
+    public method GetOutputSurface { }
+    public method GetInitialTransformation { }
+    public method UpdateInputTransformation { args } 
+
+    # Other Stuff STORAGE
+    #protected variable transformation_control 0
+}
+
+#------------------------------------------------------------------------------------------
+itcl::body bis_guirpmcontainer::InitializeGUIRpmContainer { } {
+
+    set inputs { 
+	{ reference_surface   "Reference Surface"   pxitclsurface  ""  }
+	{ transform_surface    "Target    Surface"   pxitclsurface  ""  }
+	{ initial_transform "Initial Transformation" pxitcltransform  "" 100  }
+    }
+
+    set outputs { 
+	{ output_transform "Output Transformation"  pxitcltransform  "" }
+	{ output_surface   "Transformed Surface" pxitclsurface  ""  200 }
+    }
+
+
+    
+    set scriptname "bis_guirpmcontainer"
+    set category "Graphical-User-Interface-Module"
+    set description " Utility Class for containing a variety of registration and image merge algorithms."
+    set backwardcompatibility "See pxitcloverlaytool.tcl"
+    set authors "xenophon.papademetris at yale.edu."
+
+    set completionstatus "ongoing  -- Xenios needs to revisit"
+
+    # does not contain extract surface and mapfunctional
+    set componentnamelist [ list  bis_linearpointregister bis_nonlinearpointregister ]
+
+    $this AddDefaultOptions
+
+    set extratablist { "Transformations" "Weight Images" "Image Compare" "4D Image Compare" }
+
+}
+
+
+#------------------------------------------------------------------------------------------
+::itcl::body bis_guirpmcontainer::DelayedCreateGUI { } {
+
+    if { $fullyinitialized == 1 } {
+	return 1
+    }
+
+    if { $basewidget == 0 } {
+	return 0
+    }
+
+    set tp [ toplevel $basewidget ];  wm withdraw $tp
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget  }"
+
+    set basewidget $tp
+
+    set buttonbar [ frame $basewidget.bt ]
+    set bbt [ frame $basewidget.bt2 -bg black -height 5 ]
+    
+    pack $buttonbar $bbt -side bottom -expand false -fill x 
+    
+    $this CreateProgressBar $buttonbar
+
+    eval "button $buttonbar.close   -text Close -command { wm withdraw $basewidget }"
+    pack $buttonbar.close -side right
+
+
+    set main [ frame $basewidget.top ]
+    pack $main -side top -expand true -fill both
+
+    set nt [ $this CreateMainNotebook  $main.nt ]
+    set w  [ frame $main.middle -width 2 -bg black ]
+    set vr [ frame $main.right ]
+    pack $nt $w -side left -expand false -fill y
+    pack $vr -side right -expand true -fill both
+
+
+    set maintabnotebook $nt
+
+    set bis_viewer [ [ bis_viewer \#auto ] GetThisPointer ]
+    $bis_viewer CreateGUI $vr
+    set vtk_viewer [ $bis_viewer GetViewer ]
+    #    $bis_viewer AddOrReplacePolygonalObject [ $this GetReferenceSurface ]  1 { color "1.0 0.0 0.0" opacity 0.5 visible 0} 
+    #    $bis_viewer AddOrReplacePolygonalObject [ $this GetTransformSurface ]  1 { color "0.0 1.0 0.0" opacity 1.0 visible 0} 
+    #    $bis_viewer AddOrReplacePolygonalObject [ $this GetOutputSurface ]  1 { color "1.0 1.0 0.0" opacity 0.5 visible 0 dispmode Wireframe }  
+
+    $this CreateInputOutputControl $nt
+    $this CreateContainedAlgorithmsGUIs $nt
+
+
+    $nt view "Input/Output"
+
+    $this SetTitle "BioImageSuite::Point-Based Registration Utility v2 (bis_algo)"
+    set fullyinitialized 1
+    return 1
+}
+
+
+# ------------------------------------------------------------------------------------
+# Transformation Interface
+# ------------------------------------------------------------------------------------
+::itcl::body bis_guirpmcontainer::UpdateContainedAlgorithms {  } { 
+    set l [ llength $componentlist ]
+    for { set i 0 } { $i < $l } { incr i } {
+	set alg [ lindex $componentlist $i ]
+	$alg UpdateInputsFromContainer
+    }
+}
+
+
+#------------------------------------------------------------------------------------------
+
+itcl::body bis_guirpmcontainer::InputsModified { args  } {
+
+
+    set ind [ lindex $args 0 ]
+    if { $ind == 0 || $ind ==1 || $ind ==4 } {
+	$bis_viewer AddOrReplacePolygonalObject [ $this GetReferenceSurface ]  1 { color "1.0 0.0 0.0" opacity 0.5 visible 1} 
+	$bis_viewer AddOrReplacePolygonalObject [ $this GetTransformSurface ]  1 { color "0.0 1.0 0.0" opacity 1.0 visible 1} 
+	$bis_viewer AddOrReplacePolygonalObject [ $this GetOutputSurface ]  1 { color "1.0 1.0 0.0" opacity 0.5 visible 0 dispmode Wireframe }  
+    }
+    $this UpdateContainedAlgorithms
+
+}
+
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_guirpmcontainer::CreateInputOutputControl { nt } {
+
+    set w2 [ $nt add -label "Input/Output" ]
+    set slist [ list $InputsArray(reference_surface) $InputsArray(transform_surface) $InputsArray(initial_transform) $OutputsArray(output_transform) $OutputsArray(output_surface) ]
+    for { set i 0 } { $i < [ llength $slist ] } { incr i } {
+	set obj [ lindex $slist $i ]
+	$obj CreateObjectGUI $w2.$i [ expr ($i >2) ] "" $this
+	$obj SetUpdateCallback  "$this InputsModified $i"
+	pack $w2.$i -side top -expand false -fill x -pady 5 -padx 5
+    }
+    $this UpdateContainedAlgorithms
+}
+
+
+# -------------------------------------------------------------------------------
+::itcl::body bis_guirpmcontainer::GetTransformation { }  {
+    
+    return [ $this GetOutputObject output_transform ]
+}
+
+::itcl::body bis_guirpmcontainer::GetReferenceSurface { }  {
+    
+    return [ $this GetInputObject reference_surface ]
+}
+
+::itcl::body bis_guirpmcontainer::GetTransformSurface { }  {
+    
+    return [ $this GetInputObject transform_surface ]
+}
+
+::itcl::body bis_guirpmcontainer::GetInitialTransformation { }  {
+    
+    return [ $this GetInputObject initial_transform ]
+}
+
+itcl::body bis_guirpmcontainer::GetOutputSurface  { } {
+    return [ $this GetOutputObject output_surface ]
+}
+
+
+# -------------------------------------------------------------------------------
+
+::itcl::body bis_guirpmcontainer::UpdateInputTransformation { args }  {
+    [ $this GetOutputObject initial_transform ] Copy $tr [ $containerobject GetTransformation ]
+    [ $OutputsArray(initial_transform) GetObjectGUI ] Update
+    $this InputsModified
+}
+
+
+# -------------------------------------------------------------------------------
+
+itcl::body bis_guirpmcontainer::SetTransformationFromObject { tr obj } {
+
+    [ $this GetOutputObject output_transform ] Copy $tr
+    [ $OutputsArray(output_transform) GetObjectGUI ] Update
+    if { $containerobject !=0 } {
+	$containerobject SetTransformationFromObject $tr $obj 
+    }
+    return 1
+}
+
+# --------------------------------------------------------------------------------------
+itcl::body bis_guirpmcontainer::UpdateRPMViewer { visib alg currentreg } {
+
+    if {  $currentreg == 0 || $bis_viewer == 0 } {
+	return 0
+    }
+    set dat_trn  [ $currentreg GetCurrentTransformation ]
+    set filt2m [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $filt2m SetInput [ [ $this GetReferenceSurface ] GetSurface ]
+    $filt2m SetTransform $dat_trn
+    $filt2m Update
+    
+    [ $this GetOutputSurface ] ShallowCopySurface [ $filt2m GetOutput ]
+    $filt2m Delete 
+    
+    $bis_viewer UpdatePolygonalObject [ $this GetReferenceSurface ]   {  visible 0 } 0
+    $bis_viewer UpdatePolygonalObject [ $this GetTransformSurface ]   {  opacity 1.0 visible 1 } 0
+    $bis_viewer UpdatePolygonalObject [ $this GetOutputSurface ]     { color "1.0 1.0 0.0" opacity 0.5 visible 1 dispmode Wireframe }   1
+    return 1
+}
+
+# --------------------------------------------------------------------------------------
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guisurfacecontrol.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guisurfacecontrol.tcl
new file mode 100644
index 0000000..550b52f
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guisurfacecontrol.tcl
@@ -0,0 +1,440 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_guisurfacecontrol 1.0
+package require pxitclsurface 1.0
+
+
+
+itcl::class bis_guisurfacecontrol {
+
+    constructor { } { 
+	set currentsurface [ [ pxitclsurface \#auto ] GetThisPointer ]
+	set currentresults [ [ pxitclsurface \#auto ] GetThisPointer ]
+
+    }
+    destructor { 
+	itcl::delete object $currentsurface
+	itcl::delete object $currentresults
+	catch { 
+	    itcl::delete object $surfacecontrol 
+	    itcl::delete object $resultscontrol 
+	}
+    }
+    # Create Input/Output GUI Controls for Objects in standalone mode
+    protected method InitializeGUISurfacecontrol { }
+
+
+    # Methods for chaining into other tools
+    public method SetResultsFromObject { sur obj } 
+    public method SetSurfaceFromObject { sur obj } 
+    public method CopyResultsToSurface { }
+
+    public method GetSurface { } { return $currentsurface }
+    public method GetResults { } { return $currentresults }
+    public method GetThisPointer { } { return $this }
+    
+    # multisurfacegui control
+    public method CreateGUI { container basew { modifiedcallback "" } { displayonly 0 } }
+    public method Callback_SurfaceModified { mode args }
+    public method UpdateActorProperties { mode attribute args }
+    public method ColorDialog { mode } 
+
+    protected method GetOrthoViewer {  } 
+    protected method CreateActors { }
+    protected method InvokeCallback { }
+
+    # SURFACE INFO STORAGE
+    protected variable actorarray    
+    protected variable surfacecontrol 0
+    protected variable resultscontrol 0
+
+    protected variable surfacemode 0
+    protected variable resultsmode 0
+    protected variable currentsurface 0
+    protected variable currentresults 0
+    protected variable hasactors 0
+    protected variable surfacecolor { 1 0 0 }
+    protected variable resultscolor { 0 1 0 }
+    protected variable callback ""
+    protected variable containerobject 0
+    protected variable displayonlymode 0
+}
+
+
+
+#------------------------------------------------------------------------------------------
+#  Called by surfacetosurface filter to pass output back up the chain
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_guisurfacecontrol::SetSurfaceFromObject { sur obj }  { 
+    
+    $currentsurface ShallowCopy $sur
+    $surfacecontrol Update
+    $this Callback_SurfaceModified surface
+}
+::itcl::body bis_guisurfacecontrol::SetResultsFromObject { sur obj }  { 
+
+    $currentresults ShallowCopy $sur
+    $resultscontrol Update
+    $this Callback_SurfaceModified results 
+}
+
+
+#------------------------------------------------------------------------------------------
+
+itcl::body bis_guisurfacecontrol::InvokeCallback { } {
+
+    if { $callback ==0 || $callback == "" } {
+	return
+    }
+
+    return [ eval $callback ]
+}
+
+
+
+itcl::body bis_guisurfacecontrol::CreateGUI { container basew { modifiedcallback "" } { displayonly 0 } } { 
+
+
+    set displayonlymode [ expr $displayonly > 0 ]
+    set callback $modifiedcallback
+    set containerobject $container
+    set w $basew
+    frame $w.top; pack $w.top -side top -expand false -fill x
+
+    set w2 $w.top
+
+    if { $displayonlymode == 0 } {
+	eval "button $w2.bot -text \"Copy Results to Surface\" -command { $this CopyResultsToSurface }"
+	pack $w2.bot -side bottom -expand false -fill x -pady 2
+    }
+
+    set surfacecontrol [ [ pxitclsurfaceGUI \#auto  ] GetThisPointer ]
+    if { $displayonlymode == 0 } {
+	$surfacecontrol configure -description "Surface"
+    } else {
+	$surfacecontrol configure -description "Input Surface"
+    }
+    $surfacecontrol Initialize $w2.a
+    if { $displayonlymode == 0 } {
+	$surfacecontrol configure -callback "$this Callback_SurfaceModified surface"
+    }
+
+    frame $w2.b
+
+    set surfacemode [ [ bis_option \#auto ] GetThisPointer ]
+    $surfacemode SetAllProperties "-metric" "" "Surface Mode" listofvalues Surface { None Points Wireframe Surface } 102
+    $surfacemode CreateGUIElement $w2.b.1 [ itcl::code $this Callback_SurfaceModified surface ]
+    $surfacemode HideHelpButton
+    eval "button $w2.b.2 -text Color -command { $this ColorDialog surface }"
+    pack $w2.b.1 $w2.b.2  -side left -expand true -fill x
+
+    frame $w2.c
+
+    set slinewidth [ [ bis_option \#auto ] GetThisPointer ]
+    $slinewidth SetAllProperties "-linewidth" "Line width" "Line width" real 2.0 { 1.0 10.0 } 1 
+    $slinewidth CreateGUIElement $w2.c.1 [ itcl::code $this UpdateActorProperties surface linewidth ] 
+    $slinewidth SetValueRange { 1.0 10.0 }
+
+    set spointsize [ [ bis_option \#auto ] GetThisPointer ]
+    $spointsize SetAllProperties "-pointsize" "Point Size" "Point size" real 2.0 { 1.0 10.0 } 2
+    $spointsize CreateGUIElement $w2.c.2 [ itcl::code $this UpdateActorProperties surface pointsize ] 
+    $spointsize SetValueRange { 1.0 10.0 } 
+    pack $w2.c.1 $w2.c.2  -side left -expand true -fill x
+
+    frame $w2.d  -height 3 -bg black
+    pack $w2.a $w2.b $w2.c $w2.d -side top -expand false -fill x
+
+
+    set resultscontrol [ [ pxitclsurfaceGUI \#auto  ] GetThisPointer ]
+    if { $displayonlymode == 0 } {
+	$resultscontrol configure -description "Results"
+    } else {
+	$resultscontrol configure -description "Output Surface"
+    }
+    $resultscontrol Initialize $w2.e
+
+    if { $displayonlymode == 0 } {
+	$resultscontrol configure -callback "$this Callback_SurfaceModified results"
+    }
+
+    frame $w2.f
+
+    set resultsmode [ [ bis_option \#auto ] GetThisPointer ]
+    $resultsmode SetAllProperties "-metric" "" "Results Mode" listofvalues Surface { None Points Wireframe Surface } 102
+    $resultsmode CreateGUIElement $w2.f.1 [ itcl::code $this Callback_SurfaceModified results ]
+    $resultsmode HideHelpButton
+    eval "button $w2.f.2 -text Color -command { $this ColorDialog results }"
+    pack $w2.f.1 $w2.f.2 -side left -expand true -fill x
+
+    frame $w2.g
+
+    set rpointsize [ [ bis_option \#auto ] GetThisPointer ]
+    $rpointsize SetAllProperties "-pointsize" "Point Size" "Point size" real 2.0 { 1.0 10.0 } 3
+    $rpointsize CreateGUIElement $w2.g.1 [ itcl::code $this UpdateActorProperties results pointsize ]
+    $rpointsize SetValueRange { 1.0 10.0 } 
+
+    set rlinewidth [ [ bis_option \#auto ] GetThisPointer ]
+    $rlinewidth SetAllProperties "-linewidth" "Line width" "Line width" real 2.0 { 1.0 10.0 } 4
+    $rlinewidth CreateGUIElement $w2.g.2 [ itcl::code $this UpdateActorProperties results linewidth ]
+    $rlinewidth SetValueRange { 1.0 10.0 }
+    pack $w2.g.1 $w2.g.2 -side left -expand false -fill x
+
+    pack $w2.e $w2.f $w2.g -side top -expand false -fill x
+
+
+    if { $displayonlymode == 1 } {
+	set slist [ list $surfacecontrol $resultscontrol ]
+	for { set i 0 } { $i <=1 } { incr i } {
+	    set c [ lindex $slist $i ]
+	    catch {
+		pack forget [ $c cget -loadbutton ]
+		pack forget [ $c cget -savebutton ]
+		pack forget [ $c cget -clearbutton ]
+		pack forget [ $c cget -browsebutton ]
+	    }
+	}
+    }
+	
+
+    $this CreateActors
+
+}
+
+
+
+#------------------------------------------------------------------------------------------
+itcl::body bis_guisurfacecontrol::GetOrthoViewer {  } {
+
+    if { $containerobject == 0 } {
+	return
+    } 
+    
+    set viewer [ $containerobject GetViewer ]
+    if { $viewer ==0 } {
+	return 0
+    }
+
+    set tmp 0;    catch { set tmp [ $viewer IsA "vtkpxGUIOrthogonalViewer" ] }
+
+    if { $tmp == 0 } {
+	return 0
+    }
+
+    return $viewer
+}
+
+
+
+#------------------------------------------------------------------------------------------
+itcl::body bis_guisurfacecontrol::CopyResultsToSurface { } {
+
+    $currentsurface Copy $currentresults 1
+    $surfacecontrol Update
+    $this Callback_SurfaceModified "surface"
+}
+
+
+
+#------------------------------------------------------------------------------------------
+itcl::body bis_guisurfacecontrol::CreateActors {  } {
+
+    $currentsurface configure -filename "surface.vtk"
+    $surfacecontrol SetObject $currentsurface
+    $currentresults configure -filename "results.vtk"
+    $resultscontrol SetObject $currentresults
+
+    set slist [ list $currentsurface $currentresults ]
+
+
+    
+    set viewer [ $this GetOrthoViewer ]
+    if { $viewer == 0 } {
+	return 0    
+    }
+
+    
+
+    for { set k 0 } { $k <= 1 } { incr k } {
+	set ns [ lindex $slist $k ]
+	for { set i 0 } { $i <=3 } { incr i } {
+	    set map [ vtkPolyDataMapper New ]
+	    $map SetInput [ $ns GetSurface ]
+	    
+	    set act [ vtkActor New ]
+	    set actorarray($ns,$i) $act
+	    $act SetMapper $map
+	    $act SetVisibility 1
+	    [ [ $viewer GetRenderer $i ] GetRenderer ] AddActor $act
+	    if { $k == 0 } {
+		[ $act GetProperty ] SetColor [ lindex $surfacecolor 0 ]  [ lindex $surfacecolor 1 ]  [ lindex $surfacecolor 2 ] 
+	    } else {
+		[ $act GetProperty ] SetColor [ lindex $resultscolor 0 ]  [ lindex $resultscolor 1 ]  [ lindex $resultscolor 2 ] 
+	    }
+	}
+    }
+	
+    set hasactors 1
+    $surfacemode SetValue "Surface"
+    $resultsmode SetValue "Surface"
+    $this Callback_SurfaceModified "both"
+}
+
+
+#-----------------------------------------------------------------------------------------
+itcl::body bis_guisurfacecontrol::ColorDialog { mode } {
+
+    if { $hasactors == 0 } {
+	return
+    }
+
+    set viewer [ $this GetOrthoViewer ]
+    if { $viewer == 0 } {
+	return
+    }
+
+    if { $mode == "surface" } { 
+	set surfacecolor [ pxtclutil::ColorBox "Set Color for Surface" $surfacecolor $basewidget ]
+	set c $surfacecolor
+	set ns $currentsurface
+    } else {
+	set resultscolor [ pxtclutil::ColorBox "Set Color for Results" $resultscolor $basewidget ]
+	set c $resultscolor
+	set ns $currentresults 
+    }
+	
+    for { set i 0 } { $i <=3 } { incr i } {
+	set act $actorarray($ns,$i) 
+	[ $act GetProperty ] SetColor [ lindex $c 0 ]  [ lindex $c 1 ]  [ lindex $c 2 ] 
+    }
+    $viewer UpdateDisplay
+}
+
+
+
+itcl::body bis_guisurfacecontrol::UpdateActorProperties { mode attribute args } {
+
+    if { $hasactors == 0 } {
+	return 0
+    }
+
+    set input_value [ lindex $args 1 ]
+	
+    set slist [ list $currentsurface $currentresults ]
+    set viewer [ $this GetOrthoViewer ]
+    if { $viewer == 0 } {	return 0    }
+    
+
+    if { $mode == "surface" } { 
+	set k 0
+    } else  {
+	set k 1 
+    }
+    set ns [ lindex $slist $k ]
+    set md [ $surfacemode GetValue ]
+    if { $k == 1 } {
+	set md [ $resultsmode GetValue ]
+    }
+    
+    for { set i 0 } { $i <=3 } { incr i } {
+	set act $actorarray($ns,$i) 
+	set map [ $act GetMapper ] 
+	$map SetInput [ $ns GetSurface ]
+	
+	if { $md == "None" } {
+	    $act SetVisibility 0
+	} elseif { $md == "Wireframe"} { 
+	    [ $act GetProperty ] SetRepresentationToWireframe 
+	    [ $act GetProperty ] SetLineWidth $input_value
+	    $act SetVisibility 1
+	} elseif { $md == "Points"} { 
+	    [ $act GetProperty ] SetRepresentationToPoints
+	    [ $act GetProperty ] SetPointSize $input_value
+	    $act SetVisibility 1
+	} else {
+	    [ $act GetProperty ] SetRepresentationToSurface
+	    $act SetVisibility 1
+	}
+    }    
+    $viewer UpdateDisplay
+}
+
+
+
+
+
+itcl::body bis_guisurfacecontrol::Callback_SurfaceModified { mode args } {
+
+    if { $hasactors == 0 } {
+	return 0
+    }
+
+    #    puts [ lindex $args 0 ]
+    #    puts [ lindex $args 1 ]
+
+    set slist [ list $currentsurface $currentresults ]
+    set viewer [ $this GetOrthoViewer ]
+    if { $viewer == 0 } { return 0    }
+    
+    for { set k 0 } { $k <= 1 } { incr k } {
+	set ns [ lindex $slist $k ]
+	set md [ $surfacemode GetValue ]
+	if { $k == 1 } {
+	    set md [ $resultsmode GetValue ]
+	}
+	
+	for { set i 0 } { $i <=3 } { incr i } {
+	    set act $actorarray($ns,$i) 
+	    set map [ $act GetMapper ] 
+	    $map SetInput [ $ns GetSurface ]
+	    
+	    if { $md == "None" } {
+		$act SetVisibility 0
+	    } elseif { $md == "Wireframe"} { 
+		[ $act GetProperty ] SetRepresentationToWireframe 
+		#		[ $act GetProperty ] SetLineWidth
+		$act SetVisibility 1
+ 	    } elseif { $md == "Points"} { 
+		[ $act GetProperty ] SetRepresentationToPoints
+		$act SetVisibility 1
+	    } else {
+		[ $act GetProperty ] SetRepresentationToSurface
+		$act SetVisibility 1
+	    }
+	}    
+    }
+
+    if { $displayonlymode == 0 } {
+	if { $mode != "results" } {
+	    $this InvokeCallback
+	}
+    }
+    $viewer UpdateDisplay
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guisurfaceutility.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guisurfaceutility.tcl
new file mode 100644
index 0000000..9581f5b
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guisurfaceutility.tcl
@@ -0,0 +1,185 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_guisurfaceutility 1.0
+package require bis_guicontainer 1.0
+package require pxitclsurface 1.0
+package require bis_guisurfacecontrol 1.0
+
+
+
+itcl::class bis_guisurfaceutility {
+
+    inherit bis_guicontainer
+
+    constructor { } { $this InitializeGUISurfaceUtility  }
+
+    # Create Input/Output GUI Controls for Objects in standalone mode
+    protected method InitializeGUISurfaceUtility { }
+    public method DelayedCreateGUI { }
+
+    # Methods for chaining into other tools
+    public method SetResultsFromObject { sur obj } 
+    public method SetImageFromObject { img obj } 
+    public method SetImage { img   } 
+
+    #
+    public method UpdateContainedAlgorithms { } 
+    public method CopyResultsToSurface { }
+
+    # multisurfacegui control
+    public method CreateInputOutputControl { nt }
+
+    # methods for getting stuff
+    public method GetImage   { } { return [ $this GetInputObject current_image ] }
+    public method GetSurface { } 
+
+    protected variable bis_surfacecontrol 0
+}
+
+
+
+#------------------------------------------------------------------------------------------
+itcl::body bis_guisurfaceutility::InitializeGUISurfaceUtility { } {
+
+    set inputs { 
+	{ current_image   "Current Image"   pxitclimage  ""  }
+    }
+
+    
+    set scriptname bis_guisurfaceutility
+    set category "Graphical-User-Interface-Module"
+    set description "Surface Utility Class for containing a variety of surface-to-surface algorithms."
+    set backwardcompatibility "See vtkpxGUIPolyDataControl "
+    set authors "xenophon.papademetris at yale.edu."
+
+    set completionstatus "ongoing  -- Xenios needs to revisit"
+
+    # does not contain extract surface and mapfunctional
+    set componentnamelist [ list bis_smoothsurface  bis_computenormals bis_curvatures 0 bis_decimate  bis_subdivide bis_connect bis_cleansurface bis_triangulate  bis_delaunay3D 0   bis_extractsurface bis_mapfunctional bis_extractobjectmap bis_thresholdpoints ] 
+
+    set bis_surfacecontrol  [ [ bis_guisurfacecontrol \#auto ] GetThisPointer ]
+
+    set extratablist "Surfaces"
+
+    $this AddDefaultOptions
+}
+
+
+ 
+::itcl::body bis_guisurfaceutility::GetSurface { }  {
+    return [ $bis_surfacecontrol GetSurface ]
+}
+
+
+
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_guisurfaceutility::DelayedCreateGUI { } {
+
+    if { $fullyinitialized == 1 } {
+	return 1
+    }
+
+    ::bis_guicontainer::DelayedCreateGUI 
+
+    wm geometry $basewidget 700x440
+
+    if { $fullyinitialized == 0 } {
+	puts stderr "Can not create gui in bis_guisurfaceutility"
+	return 0
+    }
+
+    
+    $this SetTitle "BioImageSuite::Surface Utility v2 (bis_algo)"
+    set fullyinitialized 1
+    return 1
+}
+
+
+
+
+#------------------------------------------------------------------------------------------
+#  Called by surfacetosurface filter to pass output back up the chain
+#------------------------------------------------------------------------------------------
+::itcl::body bis_guisurfaceutility::SetResultsFromObject { sur obj }  { 
+
+    $bis_surfacecontrol SetResultsFromObject $sur $obj
+    
+}
+
+::itcl::body bis_guisurfaceutility::SetImageFromObject { img obj  }  {
+
+    $this SetImage $img
+}
+
+::itcl::body bis_guisurfaceutility::SetImage { img   }  { 
+
+    PrintDebug "\n\n\n\n\n\n .... GetImage \n\n\n\n"
+
+    set timg [ $this GetImage ]
+    $timg ShallowCopy $img
+    $this UpdateContainedAlgorithms
+}
+
+
+#------------------------------------------------------------------------------------------
+#  Called to update contained algorithms
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_guisurfaceutility::UpdateContainedAlgorithms { } { 
+
+    set l [ llength $componentlist ]
+    for { set i 0 } { $i < $l } { incr i } {
+	set alg [ lindex $componentlist $i ]
+	PrintDebug "In $this SetImage, going to call $alg UpdateInputsFromSurfaceUtility"
+	$alg UpdateInputsFromContainer
+    }
+}
+
+
+#------------------------------------------------------------------------------------------
+
+itcl::body bis_guisurfaceutility::CreateInputOutputControl { nt } {
+
+
+    set inputoutputtab [ $nt add -label "Surfaces" ]
+    
+    set w $inputoutputtab
+    eval "$bis_surfacecontrol CreateGUI $this $inputoutputtab \"$this UpdateContainedAlgorithms\" "
+}
+
+
+#------------------------------------------------------------------------------------------
+itcl::body bis_guisurfaceutility::CopyResultsToSurface { } {
+
+    $bis_surfacecontrol CopyResultsToSurface $sur $obj
+}
+
+#------------------------------------------------------------------------------------------
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guitreecreate4d.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guitreecreate4d.tcl
new file mode 100644
index 0000000..ad789e9
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guitreecreate4d.tcl
@@ -0,0 +1,135 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package require bis_guitreeimageutility 1.0
+package provide bis_guitreecreate4d     1.0
+
+itcl::class bis_guitreecreate4d {
+
+    inherit bis_guitreeimageutility
+    
+    constructor { args } { 
+	set componentnamelist [ list bis_create4dimage ]
+    }
+    
+    public method DelayedCreateGUI  { }
+    public method GrabTreeSelection { field { imageNumber 0 } } 
+    public method updateGUI         { tab } { return 0 }
+    public method SetSpaceNode      { }
+    public method ClearSpaceNode    { } 
+}
+
+itcl::body bis_guitreecreate4d::DelayedCreateGUI { } {
+
+    if { $fullyinitialized == 1 } {
+	return 1
+    }
+
+    if { $basewidget == 0 } {
+	return 0
+    }
+    ::bis_guitreeimageutility::DelayedCreateGUI
+    
+    wm geometry $basewidget 620x600
+    
+    pack forget $guiArray(ent1) $guiArray(but1) $guiArray(f1)
+    pack forget $guiArray(f2) $guiArray(label) $guiArray(radio1) $guiArray(radio2) $guiArray(check)
+    
+    set guiArray(f12)   [ labelframe $basewidget.f12 ]
+    set guiArray(but12) [ eval "button $guiArray(f12).grabbutton -activebackground white -foreground black -activeforeground black -text \"Grab Selection\" -command {$this GrabTreeSelection 0 2 } " -state disabled ] 
+  
+    set guiArray(f32)   [ labelframe $basewidget.f32 ]
+    set guiArray(ent32) [ ::iwidgets::entryfield $guiArray(f32).ent -width 30 -state normal -labeltext "Space Node" -foreground black -textbackground white ]
+    set guiArray(but22) [ eval "button $guiArray(f32).grabbutton  -activebackground white -foreground black -activeforeground black -text \"Set Space Node\" -command {$this SetSpaceNode } " ] 
+    set guiArray(but32) [ eval "button $guiArray(f32).clearbutton -activebackground white -foreground black -activeforeground black -text \"Clear Space Node\" -command {$this ClearSpaceNode } -state disable " ] 
+    
+    pack $guiArray(f12)   -side top  -fill x -pady 6
+    pack $guiArray(but12) -side left -fill x -expand 1 -padx 3
+    pack $guiArray(f32)   -side top  -fill x -pady 6
+    pack $guiArray(ent32) $guiArray(but22) $guiArray(but32) -side left -fill x -expand 1 -padx 3
+    pack $guiArray(f2)    -side top  -fill x -pady 6
+    pack $guiArray(label) $guiArray(radio1) $guiArray(radio2) $guiArray(check) -side left -fill x -expand 1 -padx 3
+
+    $this SetTitle "BioImageSuite::Concatenate Image (bis_algo)"
+}
+
+itcl::body bis_guitreecreate4d::GrabTreeSelection { field { imageNumber 0 } } {
+
+    set tree1 [ $treeGUI getTree ]
+    if { $tree != $tree1 || [ lsearch [ $tree1 getPathList ] $parentNode ] < 0 } { 
+ 	tk_messageBox -type ok  -title "Cannot Grab Image" -message "Cannot Find Parent Node" -icon error
+ 	return 0 
+    }
+    set imageNode [ $treeGUI getSelectionPath ]
+    
+    if { ![ file exists [ $tree1 getNodeFileName $imageNode ] ] } { 
+	tk_messageBox -type ok  -title "Cannot Grab Image" -message "File does not exist" -icon error
+	return 0
+    }
+    
+    if { [ $tree1 getNodeType $imageNode ] != "Image" } { 
+	tk_messageBox -type ok  -title "Cannot Grab Image" -message "Node must be an image type" -icon error
+	return 0
+    }
+    
+    set img [ $treeGUI getReslicedImage $parentNode $imageNode ]
+    if { $img == 0 } { return 0 }
+    [ lindex $componentlist 0 ] addImage $imageNode $img
+}
+
+::itcl::body bis_guitreecreate4d::SetSpaceNode { } {
+
+    set tree [ $treeGUI getTree ]
+    set imageNode [ $treeGUI getSelectionPath ]
+
+    if { [ $tree getNodeType $imageNode ] != "Image" && [ $tree getNodeType $imageNode ] != "Folder" } {
+	tk_messageBox -type ok -title "Cannot Grab Node" -message "Node must be a Image or Folder" -icon error
+	return 0
+    }
+    
+    set pathName [ $tree getNodeTitle $imageNode ]
+
+    [ lindex $componentlist 0 ] deleteAll
+
+    $guiArray(ent32) clear
+    $guiArray(ent32) insert 0 $pathName
+    $guiArray(ent32) configure -foreground black
+    $guiArray(but32) configure -state normal
+    $guiArray(but12) configure -state normal
+    
+    set parentNode $imageNode
+}
+
+::itcl::body bis_guitreecreate4d::ClearSpaceNode { } {
+
+    if { $parentNode == "" } { return 0 }
+    [ lindex $componentlist 0 ] deleteAll
+    set parentNode ""
+    $guiArray(ent32)   clear
+    $guiArray(but32) configure -state disable
+    $guiArray(but12) configure -state normal
+}
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guitreeimageutility.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guitreeimageutility.tcl
new file mode 100644
index 0000000..7e41e48
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_guitreeimageutility.tcl
@@ -0,0 +1,205 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_guitreeimageutility 1.0
+package require bis_guiimageutility 1.0
+
+
+itcl::class bis_guitreeimageutility {
+
+    inherit bis_guiimageutility
+
+    protected variable treeGUI ""
+    protected variable tree ""
+    protected variable parentNode ""
+    protected variable output 0
+    protected variable save   0
+    protected variable guiArray 
+    protected variable nodeObjectArray
+    protected variable inputName
+
+    constructor { args } { 
+
+	if { [ llength $args ] } {
+	    set componentnamelist [ list bis_seedcorrelation bis_roimean bis_temporalsmoothimage  bis_mediantemporalsmoothimage bis_removetemporaldrift bis_removeslicemean  bis_matrixcorrelation ]
+	} else {
+	set componentnamelist [ lsort [ list bis_thresholdimage bis_listthresholdimage bis_castimage  bis_flipimage bis_shiftscaleimage bis_piecewiseimagemap  bis_resampleimage bis_cropimage bis_cylindricalcropimage bis_interleave  bis_smoothimage bis_nonlinearsmoothimage bis_imagemedian bis_edgedetectimage  bis_relabelimage  bis_reorientimage  bis_fftimage bis_rfftimage ] ]
+	}
+
+	set nodeObjectArray(1) "" ; set nodeObjectArray(2) ""
+    }
+    
+    public method AddTreeGUI { GUI } { set treeGUI $GUI }
+   
+    public method DelayedCreateGUI  { }
+    public method GrabTreeSelection { field { imageNumber 0 } } 
+    public method SetResultsFromObject { img obj }
+    public method ShowWindow { args }
+    public method SaveInTree { out } 
+    public method TabCommand { }
+    public method updateGUI  { tab } 
+}
+
+::itcl::body bis_guitreeimageutility::DelayedCreateGUI { } {
+
+    if { $fullyinitialized == 1 } {
+	return 1
+    }
+
+    if { $basewidget == 0 } {
+	return 0
+    }
+    ::bis_guiimageutility::DelayedCreateGUI
+    
+      wm geometry $basewidget 620x600
+  
+    set guiArray(f1)  [ labelframe $basewidget.f1 ]
+    set guiArray(ent1) [ ::iwidgets::entryfield $guiArray(f1).ent -width 30 -state normal -labeltext "Input Image" -foreground black -textbackground white ]
+    set guiArray(but1) [ eval "button $guiArray(f1).grabbutton -activebackground white -foreground black -activeforeground black -text \"Grab Selection\" -command {$this GrabTreeSelection $guiArray(ent1) } "  ] 
+    pack $guiArray(f1) -side top -fill x -pady 6
+    pack $guiArray(ent1) $guiArray(but1) -side left -fill x -expand 1 -padx 3
+
+    set guiArray(f3)  [ labelframe $basewidget.f3 ]
+    set guiArray(ent) [ ::iwidgets::entryfield $guiArray(f3).ent -width 30 -state normal -labeltext "Second input" -foreground black -textbackground white ]
+    set guiArray(but) [ eval "button $guiArray(f3).grabbutton -activebackground white -foreground black -activeforeground black -text \"Grab Selection\" -command {$this GrabTreeSelection $guiArray(ent) 1 } "  ] 
+
+    set guiArray(f2)     [ labelframe $basewidget.f2 ]
+    set guiArray(label)  [ label $guiArray(f2).label -text "Output Viewer:" ]
+    set guiArray(radio1) [ radiobutton $guiArray(f2).radio1 -text "Reference Viewer"     -variable [ itcl::scope output ] -value 0 ]
+    set guiArray(radio2) [ radiobutton $guiArray(f2).radio2 -text "Transform Viewer"     -variable [ itcl::scope output ] -value 1 ]
+    set guiArray(check)  [ checkbutton $guiArray(f2).check  -text "Save Results in Tree" -variable [ itcl::scope save   ] ]
+   
+    pack $guiArray(f2) -side top -fill x -pady 6
+    pack $guiArray(label) $guiArray(radio1) $guiArray(radio2) $guiArray(check) -side left -fill x -expand 1 -padx 3
+}
+
+::itcl::body bis_guitreeimageutility::GrabTreeSelection { field { imageNumber 0 } } {
+
+    if { $imageNumber && $nodeObjectArray(1) == "" } {
+	tk_messageBox -type ok -title "Cannot Grab Image" -message "Please set $inputName first" -icon error
+	return 0
+    }
+
+    set tree [ $treeGUI getTree ]
+    set imageNode [ $treeGUI getSelectionPath ]
+    
+    if { ![ file exists [ $tree getNodeFileName $imageNode ] ] } { 
+	tk_messageBox -type ok -title "Cannot Grab Image" -message "File does not exist" -icon error
+	return 0
+    }
+    
+    if { [ $tree getNodeType $imageNode ] != "Image" } { 
+	tk_messageBox -type ok -title "Cannot Grab Image" -message "Node must be an image type" -icon error
+	return 0
+    }
+    
+    if { [ $tree getNodeImageObject $imageNode ] == "" } {
+	set img [ [ pxitclimage \#auto ] GetThisPointer ]
+	$img Load "[ $tree getNodeFileName $imageNode ]"
+	$tree setNodeImageObject $img $imageNode 
+    }
+    
+    if { $imageNumber } {
+ 	set img [ $treeGUI getReslicedImage $parentNode $imageNode ]
+ 	if { $img == 0 } { return 0 }
+	set nodeObjectArray(2) $img
+    } else { 
+	set nodeObjectArray(1) [ $tree getNodeImageObject $imageNode ]
+	$guiArray(ent) clear; set nodeObjectArray(2) ""
+	set parentNode $imageNode
+    }
+    
+    $field clear
+    $field insert 0 [ $tree getNodeTitle $imageNode ]
+    $field configure -foreground black
+    
+    SetImage $nodeObjectArray(1) $nodeObjectArray(2)
+ }
+
+::itcl::body bis_guitreeimageutility::SetResultsFromObject { img obj } {
+    
+    set out [ $this GetFirstOutputObject ]
+    $out ShallowCopy $img
+    
+    if { $output } { 
+	set viewer [ $treeGUI cget -viewer2 ]
+    } else {
+	set viewer [ $treeGUI cget -viewer1 ]
+    }
+    
+    $viewer SetImageFromObject $out $treeGUI
+    $viewer ShowWindow
+    if { $save } { SaveInTree $out }
+}
+
+::itcl::body bis_guitreeimageutility::SaveInTree { out } {
+
+    if { $tree != [ $treeGUI getTree ] || [ lsearch [ [ $treeGUI getTree ] getPathList ] $parentNode ] < 0 } { 
+	tk_messageBox -type ok  -title "Cannot Save Image in Tree" -message "Cannot Find Parent Node" -icon error
+	return 0 
+    }
+    if { [ expr ![ $out Save "" ] ] } { return 0 }
+    
+    $treeGUI addNodeToTree Image [ file tail [ $out cget -filename ] ] $parentNode
+    $treeGUI setIdentityToggle
+    $treeGUI setFileName [ $out cget -filename ]
+}
+
+::itcl::body bis_guitreeimageutility::ShowWindow { args } {
+ 
+    ::bis_guicontainer::ShowWindow [ lindex $args 0 ]
+    $this updateGUI [ lindex $args 0 ]
+}
+
+::itcl::body bis_guitreeimageutility::TabCommand { } {
+    
+    updateGUI [ lindex [ $maintabnotebook pageconfigure select -label] end ]
+}
+
+::itcl::body bis_guitreeimageutility::updateGUI { tab } {
+
+    set nameList [ list ]
+    foreach alg $dualImageList { 
+	lappend nameList [ $alg GetGUIName ]
+    }    
+
+    set index [ lsearch $nameList $tab ] 
+    
+    if { $index > -1 } {
+	set inputName [ [ lindex $dualImageList $index ] GetInputName 0 ]
+	$guiArray(ent1) configure -labeltext $inputName
+	$guiArray(ent)  configure -labeltext [ [ lindex $dualImageList $index ] GetInputName 1 ]
+	catch { pack forget $guiArray(f2) $guiArray(label) $guiArray(radio1) $guiArray(radio2) $guiArray(check) }
+	catch { pack $guiArray(f3) -side top -fill x -pady 6 }
+	catch { pack $guiArray(ent) $guiArray(but) -side left -fill x -expand 1 -padx 3 }
+	catch { pack $guiArray(f2) -side top -fill x -pady 6 }
+	catch { pack $guiArray(label) $guiArray(radio1) $guiArray(radio2) $guiArray(check) -side left -fill x -expand 1 -padx 3 }
+    } else {
+	$guiArray(ent1) configure -labeltext "Input Image" 
+	catch { pack forget $guiArray(f3) $guiArray(ent) $guiArray(but) }
+    }
+}
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_headerinfo.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_headerinfo.tcl
new file mode 100755
index 0000000..df6e5cf
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_headerinfo.tcl
@@ -0,0 +1,148 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_algorithm 1.0
+package provide bis_headerinfo 1.0
+
+#
+# output headerinformation
+#
+
+itcl::class bis_headerinfo {
+
+    inherit bis_algorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Image Info" }
+    public method LoadObjects { }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_headerinfo::Initialize { } {
+
+    PrintDebug "bis_headerinfo::Initialize" 
+
+    set inputs { { input_image "Input Image List" { pxitclimage multiple } "" 0  } }
+    set directinputs "input_image"
+
+    set options {
+	{ detail "description length for header" "Detail" {listofvalues radiobuttons}  short {short long full }  0 }
+    }
+
+    set defaultsuffix ""
+    
+    set scriptname bis_headerinfo
+
+    #
+    #document
+    #
+    
+    set category "Utility"
+    set description "prints NIFTI/Analyze image header."
+    set description2 "Multiple number of input files can be specified."
+    set backwardcompatibility "Reimplemented from pxmat_headerinfo.tcl. bis_headerdump.tcl can be integrated upon request."
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this AddDefaultOptions 1
+}
+
+itcl::body bis_headerinfo::LoadObjects { } {
+
+    set old  $::pxitclimage::forcebioimagesuitecoordinates 
+    set ::pxitclimage::forcebioimagesuitecoordinates 0
+    set out [  bis_basealgorithm::LoadObjects ]
+    set ::pxitclimage::forcebioimagesuitecoordinates $old
+    return $out
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_headerinfo::Execute {  } {
+
+    PrintDebug "bis_headerinfo::Execute"
+    
+    set dogui [ $OptionsArray(dogui) GetValue ]
+    set inplist [ $InputsArray($directinputs) GetAllObjects ]
+    set numfiles [ llength $inplist ]
+
+
+    set fullmode 0
+    switch [ $OptionsArray(detail) GetValue ] {
+	"short" { 	set fullmode -1 }
+	"full"  {      set fullmode 2 }
+	"long"  {      set fullmode 1 }
+    }
+
+
+    if { $dogui > 0 } {
+	pxtkconsole
+    }
+    for { set i 0 } { $i < $numfiles } { incr i } {
+	set ana [ [ lindex $inplist $i ]  GetImageHeader ]
+	set name [ [ lindex $inplist $i ] cget -filename ]
+	if { $dogui > 0 } {
+	    pxtkprint "\n$name:\n [ $ana GetHeaderDescription $fullmode ]\n\n"
+	} else {
+	    puts stdout "\n$name:\n [ $ana GetHeaderDescription $fullmode ]\n"
+	}
+    }
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_headerinfo.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_headerinfo [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_help.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_help.tcl
new file mode 100755
index 0000000..5d9a8bf
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_help.tcl
@@ -0,0 +1,495 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#
+# AUTHOR Hirohito Okuda, hirohito.okuda at yale.edu
+# 
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main ]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] bis_algorithm]
+
+#if { $env(TESTING) != "" } { 
+#    lappend auto_path [file join  $env(TESTING)  bis_algorithm]
+#    puts stdout "auto_path = $auto_path"
+#}
+
+package require bis_algorithm 1.0
+package require vtkpxcontrib  1.0
+package require bis_common 1.0
+#
+# 
+#
+
+itcl::class bis_help {
+
+    public variable tools1
+    public variable categories ""
+
+#bis_computeaveragebrain missed
+# bis_fastpostprocess missed
+
+    constructor { fname } {  
+	set fin [ open $fname r ]
+	set tools1 ""
+	while { [ gets $fin line ] >=0 } {
+	    if { [ string first "\#" $line ]  == -1 } {
+		lappend tools1 "[ file rootname [ string trim $line ]]"
+	    }
+	}
+	close $fin
+
+	set categories [ ::bis_common::GetCategories ]
+    }
+
+    # Print short description of all the command line tools
+    public method Summarize { } 
+    public method GenerateHTML { use_stylesheet  }
+    public method GenerateLatex {   }
+    public method InsertFile { chan file } 
+
+    private variable outputdirectory   ""
+    private variable pathdirectory     ""
+    private variable headpart html/headpart.html
+    private variable tailpart html/tailpart.html
+    private variable headpart2  html/headpart.html
+    private variable tailpart2 html/tailpart.html
+
+
+    private variable headlatex  html/head.tex
+    private variable introlatex html/intro.tex
+    private variable taillatex  html/tail.tex
+
+    public method SetHTMLDirectories { outdir pathdir }
+
+    public method ToLatexString { line { mode 0 } }
+    public method SetLatexDirectories { outdir pathdir }
+}
+
+
+#
+# Print short description of all the command line tools
+#
+
+itcl::body bis_help::SetHTMLDirectories { outdir pathdir } {
+
+    set outputdirectory [ file normalize $outdir ]
+    set pathdirectory   [ file normalize $pathdir ]
+    file delete -force  $outputdirectory 
+    file mkdir $outputdirectory
+}
+
+itcl::body bis_help::SetLatexDirectories { outdir pathdir } {
+
+    set outputdirectory [ file normalize $outdir ]
+    set pathdirectory   [ file normalize $pathdir ]
+    if { [ file exists  $outputdirectory  ] == 0 } {
+	file mkdir $outputdirectory
+    }
+}
+
+
+
+itcl::body bis_help::Summarize { } {
+    foreach tool $tools {
+#	puts stderr "Reading $tool\n"
+	package require $tool 
+	set alg [$tool [pxvtable::vnewobj]]
+	#    $alg PrintUsage
+	set d [ $alg GetDescription ]
+#	puts stderr "${tool}.tcl : $d"
+    }
+}
+
+#
+# 
+#
+
+itcl::body bis_help::InsertFile { chan filename  } {
+
+    set fs [open  $filename r ]
+    while { [gets $fs line ]>=0 } {
+	puts $chan "$line"
+    }
+    close $fs
+}
+
+#
+# 
+#
+# ---------------------------------------------------------------------------------------------------------------
+itcl::body bis_help::GenerateHTML { use_stylesheet  } {
+
+    puts stderr "+++ bis_help::GenerateHTML"
+
+
+    set qlist [lsort -ascii  $tools1 ]
+    set slist ""
+    foreach tool $qlist {
+	set ok 0 
+	catch { package require $tool ; set ok 1  }
+	if { $ok == 1 } {
+	    lappend slist $tool
+	}  else {
+	    puts stderr "--------- Ignoring $tool "
+	}
+    }
+
+    
+
+
+    #index.html
+    set filename index.html
+    set chan [open $outputdirectory/$filename w ]
+
+    if { $use_stylesheet  } {
+	InsertFile $chan [ file join $pathdirectory $headpart ]
+	puts $chan "<div id=\"pagetitle\">"
+	puts $chan "<center>BIS Command Line Tools Index </center>"
+	puts $chan "</div>"
+    } else {
+	puts $chan "<HTML><HEAD background=\"white\"><TITLE>BIS - index </TITLE></HEAD><BODY>"
+	puts $chan "<font size=\"2\" >"
+	puts $chan "<H2><CENTER>BioImage Suite Command Line Tools Index </CENTER></H2>"
+    }
+
+    puts $chan "<HR><P><B>Note:</B> Any tool can be executed also as an applet with a graphical user interface using the --dogui 1 flag.</P>"
+    puts $chan "<P>For example in the case of bis_smoothimage, you can invoke this as an applet using:</P>"
+    puts $chan "<PRE>bis_smoothimage.tcl --dogui 1</PRE><HR>"
+
+
+    foreach c $categories { 
+	set tools($c) ""
+    }
+
+
+    set alltools ""
+    foreach tool $slist {
+	set algorithm($tool) [$tool [pxvtable::vnewobj]]
+	set alg $algorithm($tool)
+	set categ  [$alg GetCategory]
+	if { $categ == "" } {
+	    set categ "other"
+	}
+	#	puts stderr "tool categ = $tool $categ"
+	lappend tools(${categ}) $tool
+	if { [ lsearch -exact $categories $categ ] == -1 } {
+	    lappend categories $categ
+	}
+    }
+    
+    #set clist [ lsort -ascii $categories]
+    #puts stderr "categories=$categories"
+
+    for { set i 0 } { $i < [ llength $categories ] } { incr i } {
+	set categ  [ lindex $categories $i ]
+	#puts stderr "category =$categ, $tools($categ)"
+	puts $chan "<H2>$categ</H2>"
+	#	puts stderr "\n ++++++++++++++++++++++ $categ"
+	foreach tool $tools($categ) {
+	    set alg $algorithm($tool)
+	    puts $chan "<A HREF=\"man_$tool.html\" NAME=\"$tool\">${tool}</A> </span>, [$alg GetDescription] <br>"
+	}
+    }
+
+    if { $use_stylesheet  } {
+	InsertFile $chan [ file join $pathdirectory $tailpart ]
+    } else {
+	puts $chan "<hr>"
+	#	puts $chan "This is the man pages for the command line tools of the upcoming 3.0 release of <a href=\"http://www.bioimagesuite.org\">BioImage Suite.</a>"
+	puts $chan "</font>"
+	puts $chan "</BODY></HTML>"
+    }
+
+    close $chan
+    #    exit
+    #
+    # generate description page for each command line tool
+    #
+
+    foreach tool $slist {
+	set alg $algorithm($tool)
+	set ok [$alg GetCmdLineOptionsList]	
+
+	set filename ${outputdirectory}/man_${tool}.html
+	puts stderr "++++++ generating $filename ..."
+	set chan [open $filename w ]
+
+	if { $use_stylesheet  } {
+	    InsertFile $chan [ file join $pathdirectory $headpart2 ]
+	    puts $chan "<H2><CENTER>${tool}</CENTER></H2>"
+	    puts $chan "<br> <font size=\"2\" > <i>This part is under construction</i> </font>"
+	} else {
+	    puts $chan "<HTML><HEAD><TITLE>BioImage Suite - ${tool} </TITLE></HEAD><BODY>"
+	    puts $chan "<H2><CENTER><a href=\"index.html\">BioImage Suite Command Line Tools</a></CENTER></H2>"
+	}
+
+	puts $chan "<font size=\"2\" >"
+	puts $chan "<br> <br><H3>NAME</H3>"
+	puts $chan "${tool}.tcl --[$alg GetDescription]"
+
+	    puts $chan "<br> <br><H3>SYNOPSIS</H3>"
+	    puts $chan "</font>"
+	    
+#	    puts stderr "category = [$alg GetCategory ] "
+
+	    puts $chan "<font size=\"3\" >"
+
+	    puts $chan "[$alg GetSynopsis html]"
+	    puts $chan "</font>"
+
+
+
+	    puts $chan "<font size=\"2\" >"
+	    puts $chan "<br> <br><H3>DESCRIPTION</H3>"
+	    puts $chan "${tool}.tcl [$alg GetDetailDescription html] "
+
+	    
+	    puts $chan "<br> <br><H3>BACKWARD COMPATIBILITY ISSUES</H3>"
+	    puts $chan "[$alg GetBackwardCompatibility]"
+
+
+
+	    puts $chan "<br> <br><H3>Authors</H3>"
+	    puts $chan "[$alg GetAuthors]"
+	    puts $chan "<br>"
+
+#	    puts $chan "<H3>Status</H3>"
+#	    puts $chan "([ $alg GetCompletionStatus ])"
+	    itcl::delete object $alg
+
+
+	if { $use_stylesheet  } {
+	    InsertFile $chan [ file join $pathdirectory $tailpart2 ]
+	} else {
+	    puts $chan ""
+	    puts $chan "<HR><CENTER><A HREF=\"index.html\" NAME=\"Back to index\">\[Return to Command Line Tools Index\]</A></CENTER>"
+	    puts $chan "</font>"
+	    puts $chan "</BODY></HTML>"
+	}
+	close $chan
+    }
+
+    #
+    # generate description page for test script
+    #
+
+}
+# ---------------------------------------------------------------------------------
+itcl::body bis_help::ToLatexString { line { mode 0 } } {
+
+    if { $mode == 0 } {
+	regsub -all "_" $line "\\_" out
+    } else {
+	regsub -all "_" $line "" out
+    }
+    regsub -all "%" $out "\\%" out
+
+#    puts stderr "$line -> $out"
+    return $out
+
+    puts stdout "Output saved in $outputdirectory"
+}
+# ---------------------------------------------------------------------------------
+itcl::body bis_help::GenerateLatex { } {
+
+    puts stderr "bis_help::GenerateLatex"
+
+
+    set qlist [lsort -ascii  $tools1 ]
+    set slist ""
+    foreach tool $qlist {
+	set ok 0 
+	catch { package require $tool ; set ok 1  }
+	if { $ok == 1 } {
+	    lappend slist $tool
+	}  else {
+	    puts stderr "--------- Ignoring $tool "
+	}
+    }
+
+    #index.html
+    set filename biotools.tex
+    set chan [open $outputdirectory/$filename w ]
+
+    InsertFile $chan [ file join $pathdirectory $headlatex ]
+
+
+    foreach c $categories { 
+	set tools($c) ""
+    }
+    
+
+    set alltools ""
+    foreach tool $slist {
+	set algorithm($tool) [$tool [pxvtable::vnewobj]]
+	set alg $algorithm($tool)
+	set categ  [$alg GetCategory]
+	if { $categ == "" } {
+	    set categ "other"
+	}
+	puts stdout "tool categ = $tool $categ"
+	lappend tools(${categ}) $tool
+	if { [ lsearch -exact $categories $categ ] == -1 } {
+	    lappend categories $categ
+	}
+    }
+    
+    InsertFile $chan [ file join $pathdirectory $introlatex ]
+
+    puts $chan "\\chapter{Catalog}"
+
+    puts $chan "\\textbf{Note:} The manual pages for each module are automatically generated from the BioImage Suite source code."
+
+    for { set i 0 } { $i < [ llength $categories ] } { incr i } {
+	set categ  [ lindex $categories $i ]
+	puts $chan "\\paragraph*{$categ}"
+	puts $chan "\\begin{compactenum}"
+	puts stderr "\n ++++++++++++++++++++++ $categ"
+	foreach tool $tools($categ) {
+	    set alg $algorithm($tool)
+	    set toolname [ $this ToLatexString $tool ]
+	    set guiname [ $this ToLatexString [ $alg GetGUIName ] ]
+	    set refname [ $this ToLatexString $tool 1 ]
+	    puts $chan "\\item ${guiname} ($toolname)  [ $this ToLatexString [$alg GetDescription]] -- See Section \\ref{$refname} (on page \\pageref{$refname})"
+	}
+	puts $chan "\\end{compactenum}"
+    }
+
+    puts $chan "\n\\clearpage"
+
+    
+
+
+    for { set i 0 } { $i < [ llength $categories ] } { incr i } {
+	
+	set categ [ lindex $categories $i ]
+	puts $chan "\\clearpage\\chapter{$categ}"
+	foreach tool $tools($categ) {
+
+	    set alg $algorithm($tool)
+	    set ok [$alg GetCmdLineOptionsList]	
+	    #	    set filename ${outputdirectory}/${tool}.html
+	    #    puts stderr "generating $filename ..."
+	    #set chan [open $filename w ]
+	    set toolname [ $this ToLatexString $tool ]
+	    set refname [ $this ToLatexString $tool 1 ]
+	    set guiname [ $this ToLatexString [ $alg GetGUIName ] ]
+
+	    puts $chan  "\\section{$guiname ($toolname)}"
+	    puts $chan  "\\label{$refname}"
+
+	    puts $chan "\\paragraph{Description:}"
+
+	    set d [ $alg GetDescription ] 
+	    set desc  [ $this ToLatexString $d ]
+	    set ldesc [ $this ToLatexString  [ $alg GetDetailDescription tex ] ]
+
+
+	    puts $chan "${toolname}.tcl -- $desc"
+
+	    puts $chan "\\paragraph{Synopsis:}"
+	    puts $chan "[ $alg GetSynopsis tex ]"
+
+	    puts $chan "\\paragraph{Detailed Description:}"
+	    puts $chan "\\textbf{${toolname}.tcl} $ldesc"
+
+	    
+	    puts $chan "\\paragraph{Backward Compatibility Issues:}"
+	    puts $chan "[ $this ToLatexString [$alg GetBackwardCompatibility]]"
+
+	    puts $chan "\\paragraph{Authors:}"
+	    puts $chan "[ $this ToLatexString [$alg GetAuthors]]"
+
+
+	    #	    puts $chan "\\paragraph{Status:}"
+	    #	    puts $chan "[ $this ToLatexString [ $alg GetCompletionStatus ] ]"
+	    #	    puts $chan "\\clearpage"
+	    puts $chan "\\vspace{0.5\\baselineskip}\\hrule"
+	    puts $chan "\\vspace{0.5\\baselineskip}"
+	}
+    }
+
+    puts $chan "\\appendix"
+    puts $chan "\\chapter{Alphabetical Algorithm List}"
+    puts $chan "\\begin{compactenum}"
+
+    set sslist [ lsort -ascii $slist ]
+
+    foreach tool $sslist {
+	set alg $algorithm($tool)
+	set toolname [ $this ToLatexString $tool ]
+	set refname [ $this ToLatexString $tool 1 ]
+	set guiname [ $this ToLatexString [ $alg GetGUIName ] ]
+	puts $chan  "\\item $toolname ($guiname) -- see page \\pageref{$refname}"
+	itcl::delete object $alg
+    }
+    puts $chan "\\end{compactenum}"
+
+
+    InsertFile $chan [ file join $pathdirectory $taillatex ]
+    puts $chan "\\end{document}"
+    close $chan
+    #
+    # generate description page for test script
+    #
+    puts stdout "Output saved in $outputdirectory/$filename"
+}
+
+
+# ---------------------------------------------------------------------------------------------------------------------------------------------
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    if { [ llength $argv ] < 2  } {
+	puts stdout "Usage $argv0  listofscripts directory \[ latex \] "
+	exit
+    }
+
+    set help [bis_help [pxvtable::vnewobj]  [ lindex $argv 0 ] ]
+    set use_stylesheet 0
+    
+    if { [ llength $argv ] == 2 || [ lindex $argv 2 ] == "html" } {
+	$help SetHTMLDirectories [ lindex $argv 1 ] [ file dirname [  info script ] ]
+	$help GenerateHTML $use_stylesheet
+    } else {
+	$help SetLatexDirectories [ lindex $argv 1 ] [ file dirname [  info script ] ]
+	$help GenerateLatex 
+    }
+
+    exit
+}
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imageandsurfacetosurfacealgorithm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imageandsurfacetosurfacealgorithm.tcl
new file mode 100644
index 0000000..6192cb7
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imageandsurfacetosurfacealgorithm.tcl
@@ -0,0 +1,198 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_imageandsurfacetosurfacealgorithm 1.0
+package require bis_surfacetosurfacealgorithm 1.0
+
+# -----------------------------------------------------------------------------------------
+#  Header Stuff
+# -----------------------------------------------------------------------------------------
+itcl::class bis_imageandsurfacetosurfacealgorithm {
+
+    inherit bis_surfacetosurfacealgorithm
+
+    constructor { } { }
+    public method InitializeImageandSurfacetoSurfaceAlgorithm { }
+    public method Execute { } { puts stderr "Nothing to Do" }
+
+
+    # Get Info about Algorithm for use in GUI Container
+    public method SetContainer { cont }  { set containerobject $cont }
+    public method GetContainer { }  { return $containerobject }
+    public method UpdateInputsFromContainer { }
+
+    # Input and Output Methods
+    public method GetInputImage { }
+    public method GetInputSurface { }
+    public method GetOutput { }
+    public method SetInput { img sur}
+
+    # Set Filenames etc
+    public method  UpdateOutputFilenames { } 
+    public method  CheckInputObjects { } 
+
+    # GUI Extra Stuff
+    public method InputModified { }
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imageandsurfacetosurfacealgorithm::InitializeImageandSurfacetoSurfaceAlgorithm { } {
+
+    # This assumes that a derived class has done some work here already
+
+    PrintDebug "bis_imageandsurfacetosurfacealgorithm::Initialize" 
+
+    set tmp $inputs
+    set inputs { { input_image "Input Image" pxitclimage  "" 3 } }
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend inputs [ lindex $tmp $i ]
+    }
+
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    #    lappend options [ list outname  "output filename root" "Output" string ""     { "" }  -1000 ]
+
+
+    if { $defaultsuffix == "" } {
+	set defaultsuffix { "_surfout" }
+    }
+    
+    
+    #
+    #document stuff
+    #
+
+    if { $category =="" } {
+	set category    "Image+Surface Processing"
+    }
+    
+    if { $authors == "" } {
+	set authors "alark.joshi at yale.edu, xenophon.papademetris at yale.edu."
+    }
+
+    $this InitializeSurfacetoSurfaceAlgorithm
+
+}
+
+# ----------------------------------------------------------
+# GUI Stuff
+# ----------------------------------------------------------
+itcl::body bis_imageandsurfacetosurfacealgorithm::InputModified { } {
+    
+    if { $bis_surfacecontrol != 0 } {
+	$bis_surfacecontrol SetSurfaceFromObject [ $this GetInput ] $this
+    }
+}
+
+# ----------------------------------------------------------
+#
+#  Container Stuff ....
+#
+# ----------------------------------------------------------
+
+itcl::body bis_imageandsurfacetosurfacealgorithm::SetInput  { img sur } {
+
+    $this SetInputObject input_image   $img
+    $this SetInputObject input_surface $sur
+
+}
+
+itcl::body bis_imageandsurfacetosurfacealgorithm::GetInputImage  { } {
+
+    return [ $this GetInputObject input_image ]
+}
+
+itcl::body bis_imageandsurfacetosurfacealgorithm::GetInputSurface  { } {
+
+    return [ $this GetInputObject input_surface ]
+}
+
+
+itcl::body bis_imageandsurfacetosurfacealgorithm::GetOutput { } {
+
+    return [ $this GetOutputObject output_surface ]
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_imageandsurfacetosurfacealgorithm::UpdateInputsFromContainer { } {
+
+    if { $containerobject == 0 } {	return    }
+
+    set img [ $this GetInputImage ]
+    $img ShallowCopy [ $containerobject GetImage ] 
+
+    set sur [ $this GetInputSurface ]
+    $sur ShallowCopy [ $containerobject GetSurface ] 
+
+    $this UpdateOutputFilenames
+}
+
+
+
+# --------------------------------------------------------------------------------------------
+
+itcl::body bis_imageandsurfacetosurfacealgorithm::UpdateOutputFilenames { } {
+
+    set f1 [ [ $this GetOutput ] cget -filename ]
+    set fn [ $InputsArray(input_image) GetFileName ]
+    set outlist [ $this CreateDefaultOutputFileList $fn ]
+
+    set l [ ::bis_common::SplitFileNameGZ $fn ]
+    set ext ".vtk"
+    set m [ lindex $outlist 0 ]
+
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+
+    $OutputsArray(output_surface) SetFileName "${m}${ext}" $force
+    return 1
+
+}
+
+
+itcl::body bis_imageandsurfacetosurfacealgorithm::CheckInputObjects { } {
+
+    # Checking Input Image 
+    set image_in    [ $this GetInputImage ]
+   	set d [ $image_in GetImageSize ]
+    if { $d < 27 } {
+		return 0
+    }
+
+    ## Checking for input surface
+   set surface_in    [ $this GetInputSurface ]
+    set d [ [ $surface_in GetSurface ] GetNumberOfPoints ]
+    if { $d < 4 } {
+	return 0
+    }
+
+    return 1
+
+}
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagecompare.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagecompare.tcl
new file mode 100755
index 0000000..4d94652
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagecompare.tcl
@@ -0,0 +1,177 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagealgorithm 1.0
+package require bis_resliceimage 1.0
+package provide bis_imagecompare 1.0
+
+#
+# blend image
+#
+
+itcl::class bis_imagecompare {
+
+    inherit bis_dualimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Compute Image Comparison"}
+
+    protected method PackOptionsGUIInterface { lst }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imagecompare::Initialize { } {
+
+    PrintDebug "bis_imagecompare::Initialize" 
+
+    set inputs { 
+	{ first_sigma   "Standard Deviation 1" pxitclimage  ""  102 }   
+	{ second_sigma   "Standard Deviation 2" pxitclimage  "" 103 }   
+    }
+
+
+    set options {
+	{ n1  "Number of Samples for data set 1 (Mean 1, and Sigma 1)" "N1"   integer   2 { 1 20000 }  0 }
+	{ n2  "Number of Samples for data set 2 (Mean 2, and Sigma 2)" "N2"   integer   1 { 1 20000 }  1 }
+	{ scale  "Scale Factor to multiply resulting t by (typically 1000)" "Scale"   integer   1000 { 1 1000 }  2 }
+    }
+	
+    set defaultsuffix { "_ttest" }
+    
+    set scriptname bis_imagecompare
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    set category "Image Processing Dual"
+    set description "Add, Subtract, Multiply or Divide two images to give an output. NormalT and PairedT assumed 4D Images and perform t-test comparisons"
+    set description2 ""
+    set backwardcompatibility " "
+    set authors "alark.joshi at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageAlgorithm
+    
+    $this RenameInput 0 "Mean Image 1"
+    $this RenameInput 1 "Mean Image 2"
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_imagecompare::PackOptionsGUIInterface { lst } { 
+
+    
+    grid  [ $OptionsArray(n1) GetBaseWidget ] -row 0 -column 0 -padx 0
+    grid  [ $OptionsArray(n2) GetBaseWidget ] -row 0 -column 1 -padx 0
+    grid  [ $OptionsArray(scale) GetBaseWidget ] -row 0 -column 2 -padx 0
+
+    set v  [ file rootname  [ $OptionsArray(scale) GetBaseWidget ] ]
+    grid rowconfigure $v 2 -weight 100
+    grid columnconfigure $v 3 -weight 100
+
+    update idletasks
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+itcl::body bis_imagecompare::Execute {  } {
+
+    PrintDebug "bis_imagecompare::Execute"
+
+    set img1 [ [ $this GetInput ] GetImage ]
+    set img2 [ [ $this GetSecondInput ]  GetImage ]
+    set sig1 [ [ $this GetInputObject first_sigma ] GetImage ]
+    set sig2 [ [ $this GetInputObject second_sigma ] GetImage ]
+
+    set l [ list $img1 $img2 $sig1 $sig2 ]
+    for { set i 0 } { $i < [ llength $l ] } { incr i } {
+	puts stderr "Dimensions = [ [ lindex $l $i ] GetDimensions ]"
+    }
+
+
+    if { [ $img1 GetNumberOfPoints ] != [ $img2 GetNumberOfPoints ] } {
+	set errormessage  "Unequal Image Sizes\n Cannot Perform Compare t-test!"
+	return 0
+    }
+
+	
+    set outimage [ $this GetOutput ] 
+
+    set math [ vtkpxComputeTmap [ pxvtable::vnewobj ]]
+    $math SetInput  $img1
+    $math SetInput2 $img2
+    $math SetInputStandardDeviation  $sig1
+    $math SetInputStandardDeviation2 $sig2
+    $math SetNumberOfSamples1 [ $OptionsArray(n1) GetValue ] 
+    $math SetNumberOfSamples2 [ $OptionsArray(n2) GetValue ] 
+    $math SetScaleFactor [ $OptionsArray(scale) GetValue ] 
+    $math Update
+    $outimage ShallowCopyImage [ $math GetOutput ]
+    puts stderr " Results Range: [ [ [ [ $outimage GetImage ] GetPointData ] GetScalars ] GetRange ]"
+
+    set pimage   [ $this GetSecondInput ] 
+
+    $outimage CopyImageHeader [ $pimage GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $math Delete
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_imagecompare.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+ 
+
+    set alg [bis_imagecompare [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagedilate.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagedilate.tcl
new file mode 100755
index 0000000..ddd1896
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagedilate.tcl
@@ -0,0 +1,154 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_imagedilate 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+#
+# smooth image
+#
+
+itcl::class bis_imagedilate {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Dilate/Erode Filter" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imagedilate::Initialize { } {
+
+    PrintDebug "bis_imagedilate::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ windowsize "kernel size [voxels] -ve values =erosion" "Filter Size"  {  listofvalues  } 3 { -9 -7 -5 -3 3 5 7 9 }  0 }
+	{ dimension  "2 or 3 to to do dilation/erosion in 2D or 3D" "Dimensionality"  { listofvalues radiobuttons }    3 { 2  3 }  -999 }
+
+    }
+
+    set defaultsuffix { "_dil" }
+    
+    set scriptname bis_imagedilate
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Modifies an image using continuous dilation filtering"
+    set description2 " "
+    set backwardcompatibility "New"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imagedilate::Execute {  } {
+
+    PrintDebug "bis_imagedilate::Execute"
+
+    set windowsize   [ $OptionsArray(windowsize) GetValue ]
+    set dimension   [ $OptionsArray(dimension)    GetValue ]
+    set image_in    [ $InputsArray(input_image) GetObject ]
+
+    PrintDebug "windowsize = $windowsize, dimension = $dimension "
+
+    if { $windowsize > 0 } {
+	set smooth  [ vtkImageContinuousDilate3D [ pxvtable::vnewobj ]  ]
+    } else {
+	set smooth  [ vtkImageContinuousErode3D [ pxvtable::vnewobj ]  ]
+    }
+    
+    set r [ expr abs($windowsize) ]
+
+    if { $dimension == 3 } {
+	$smooth SetKernelSize $r $r $r
+    } else {
+	$smooth SetKernelSize $r $r 1
+    }
+    $smooth SetInput [ $image_in GetImage ]
+    $this SetFilterCallbacks $smooth "Dilate Smoothing Image"
+    $smooth Update
+
+
+    set image_out [ $smooth GetOutput ]
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out 
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format "BIS::pxmat_imagedilate.tcl windowsize=%d " $windowsize ]
+
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    $smooth Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_imagedilate.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_imagedilate [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagelisttoimagealgorithm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagelisttoimagealgorithm.tcl
new file mode 100644
index 0000000..2a0c737
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagelisttoimagealgorithm.tcl
@@ -0,0 +1,171 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_imagelisttoimagealgorithm 1.0
+package require bis_algorithm 1.0
+
+
+#
+# create 4d image
+#
+
+itcl::class bis_imagelisttoimagealgorithm {
+
+    #inherit bis_algorithm
+    inherit bis_algorithm
+
+
+    constructor { } { }
+    protected method InitializeImageListToImageAlgorithm { }
+    public method CheckInputObjects { } 
+    public method UpdateOutputFilenames { } 
+    public method UpdateContainerWithOutput { } 
+
+}
+
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imagelisttoimagealgorithm::InitializeImageListToImageAlgorithm { } {
+    
+
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set tmp $outputs
+    set outputs {
+	{ output_image "output 4d image "  pxitclimage  "" }
+    }
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+    	lappend outputs [ lindex $tmp $i ]
+    }
+
+
+    #number of input files should be equal or larger than 1
+    set tmp $inputs
+    set inputs { { input_image "Input Image List" { pxitclimage multiple } "" 0  } }
+
+
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend inputs [ lindex $tmp $i ]
+    }
+
+    set directinputs "input_image"
+    if { $defaultsuffix == "" } {
+	set defaultsuffix { "_4D" }
+    }
+
+    if { $scriptname == "" } {
+	set scriptname bis_imagelisttoimagealgorithm
+    }
+
+    #
+    #document
+    #
+
+    if { $category == "" } {
+	set category "Image Processing Multiple"
+    }
+
+
+    $this AddDefaultOptions
+
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_imagelisttoimagealgorithm::UpdateOutputFilenames { }  {
+
+    set inplist [ $InputsArray($directinputs) GetAllObjects ]
+    set numfiles [ llength $inplist ]
+
+    set fn [ $InputsArray(input_image) GetFileName ]
+    set outlist [ $this CreateDefaultOutputFileList $fn ]
+    set l [ ::bis_common::SplitFileNameGZ $fn ]
+    set ext [ lindex $l 1 ]
+    set m [ lindex $outlist 0 ]
+
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+    $OutputsArray(output_image) SetFileName "${m}_N${numfiles}${ext}"  $force
+    return 1
+
+}
+
+itcl::body bis_imagelisttoimagealgorithm::CheckInputObjects { }  {
+    set inplist [ $InputsArray($directinputs) GetAllObjects ]
+    set numfiles [ llength $inplist ]
+    
+    set sz [ [ lindex $inplist 0 ] GetImageSize ]
+    if { $sz < 1 } {
+	return 0
+    }
+    
+    if { $numfiles > 1 } {
+	for { set i 1 } { $i < $numfiles } { incr i } {
+	    if { $sz != [ [ lindex $inplist $i ] GetImageSize ] } {
+		set errormessage "Input Images must have same size (index = [ expr $i +1 ] )"
+		return 0
+	    }
+	}
+    }
+    return 1
+}
+
+itcl::body bis_imagelisttoimagealgorithm::UpdateContainerWithOutput { } {
+
+    set img  [ $this GetOutputObject output_image ] 
+
+    if { $containerobject == 0 } {
+	if { $bis_viewer !=0 } {
+	    $bis_viewer SetImage $img
+	}  elseif { $vtk_viewer !=0 } {
+	    $vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+	} 
+    } else {
+	PrintDebug "Calling Container ($this, $containerobject) SetResultsFromObject" 
+	$containerobject SetResultsFromObject $img $this
+	# Unload result at this point
+	$img Clear
+    }
+}
+
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_imagelisttoimagealgorithm.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagemathoperations.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagemathoperations.tcl
new file mode 100755
index 0000000..5bfde72
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagemathoperations.tcl
@@ -0,0 +1,220 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagetransformationalgorithm 1.0
+package require bis_resliceimage 1.0
+package provide bis_imagemathoperations 1.0
+
+#
+# blend image
+#
+
+itcl::class bis_imagemathoperations {
+
+    inherit bis_dualimagetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+
+    public method GetGUIName { } { return "Math Operations"}
+    public method UpdateOutputFilenames { } 
+
+
+    # T-test computation for 4D Images
+    protected method ComputeIntersection { img1 img2 threshold mode } 
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imagemathoperations::Initialize { } {
+
+    PrintDebug "bis_imagemathoperations::Initialize" 
+
+    set options {
+	{ interp        "Interpolation Mode that is used when reslicing the image" "Interpolation Mode"  listofvalues Linear { "NearestNeighbor" "Linear" "Cubic" }  -10 }
+	{ background    "Background Level used to fill voxels outside of mapped area" "Background Value"  real 0.0 { -100000 100000 }  -100 }
+	{ mathoperation "Pick math operation" "Operation "  listofvalues Add { "Add" "Subtract" "Multiply" "Divide"  "Intersection" }  1 }
+	{ interthr  "Threshold for interesection Operation" "Intersection Threshold"   real   0.0 { -100000000.0 100000000.0 }  2 }
+	{ intermode "Type of Interesection mode" "Intersection Mode"  listofvalues Positive { "Positive" "Negative" "Both" }  3 }
+    }
+	
+    set defaultsuffix { "_mathop" }
+    
+    set scriptname bis_imagemathoperations
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    set category "Image Processing Dual"
+    set description "Add, Subtract, Multiply or Divide two images to give an output."
+    set description2 ""
+    set backwardcompatibility " "
+    set authors "alark.joshi at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageTransformationAlgorithm
+}
+
+itcl::body bis_imagemathoperations::UpdateOutputFilenames { } {
+
+    set defaultsuffix "_[ string tolower [ $OptionsArray(mathoperation) GetValue ]]"
+    return [ bis_dualimagetransformationalgorithm::UpdateOutputFilenames ]
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imagemathoperations::ComputeIntersection { img1 img2 threshold mode } {
+
+    if { [ $img1 GetNumberOfPoints ] != [ $img2 GetNumberOfPoints ] } {
+	set errormessage "Unequal Image Sizes\n Cannot Perform Compare Operation $mode!"
+	return 0
+    }
+
+    set currentresults [ pxitclimage \#auto ]
+    set math [ vtkpxImageThresholdedIntersection [ pxvtable::vnewobj ]]
+    $math AddInput $img1
+    $math AddInput $img2
+    $math SetThreshold  $threshold
+    switch -exact -- $mode {
+	"Positive" { $math SetThresholdMode 0}
+	"Negative" { $math SetThresholdMode 1}
+	"Both"     { $math SetThresholdMode 2}
+    }
+    SetFilterCallbacks $math "Computing Intersection"    
+    $math Update
+    $currentresults ShallowCopyImage [ $math GetOutput ]
+    
+    $math Delete
+    return $currentresults
+}
+
+
+
+# ----------------------------------------------------------------------------------------------------------------
+
+itcl::body bis_imagemathoperations::Execute {  } {
+
+    PrintDebug "bis_imagemathoperations::Execute"
+    set mathop [ $OptionsArray(mathoperation) GetValue ]
+
+    set reslice_alg [bis_resliceimage [pxvtable::vnewobj]]
+    $reslice_alg InitializeFromContainer $this
+    $reslice_alg SetInput [ $this GetInput ] 
+    $reslice_alg SetSecondInput [ $this GetSecondInput ] 
+    $reslice_alg SetTransformation [ $this GetTransformation ] 
+    $reslice_alg SetOptionValue interp     [ $OptionsArray(interp) GetValue ]
+    $reslice_alg Execute
+
+    set reslimage [  [ $reslice_alg GetOutput ] GetImage ]
+    set mathOpsResult 0
+
+    set outimage [ $this GetOutput ] 
+
+    if { $mathop == "Intersection" } {
+	set thr [ $OptionsArray(interthr) GetValue ]
+	set md [ $OptionsArray(intermode) GetValue ]
+	set tmp [ $this ComputeIntersection [ [ $this GetInput ] GetImage ] $reslimage $thr $md ]
+	if { $tmp == 0 } {
+	    return 0
+	}
+	$outimage ShallowCopyImage [ $tmp GetImage ]
+	itcl::delete object $tmp
+    } else {
+	set imcast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+	$imcast2 SetInput $reslimage
+	$imcast2 SetOutputScalarType [ [ [ $this GetInput ] GetImage ] GetScalarType ]
+	$imcast2 Update
+
+	set mathOpsResult [ vtkImageMathematics [  pxvtable::vnewobj ] ]
+	
+	if { $mathop == "Add" } {
+	    $mathOpsResult SetOperationToAdd 
+	} elseif { $mathop == "Subtract" } {
+	    $mathOpsResult SetOperationToSubtract
+	} elseif { $mathop == "Multiply" } { 
+	    $mathOpsResult SetOperationToMultiply
+	} else {
+	    $mathOpsResult SetOperationToDivide
+	    $mathOpsResult DivideByZeroToCOn
+	    $mathOpsResult SetConstantC 0.0
+	}
+	
+	$mathOpsResult SetInput1  [ [ $this GetInput ] GetImage ]
+	$mathOpsResult SetInput2  [ $imcast2 GetOutput ] 
+	$mathOpsResult Update
+	$outimage ShallowCopyImage [ $mathOpsResult GetOutput ]
+    }
+
+
+    # Output orientation etc. is same as input
+
+    set pimage   [ $this GetSecondInput ] 
+
+    $outimage CopyImageHeader [ $pimage GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    puts stderr "Outimage Description = [ $outimage GetDescription ]"
+
+    if { $mathOpsResult !=0 } {
+	$mathOpsResult Delete
+    }
+    itcl::delete object $reslice_alg
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_imagemathoperations.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+ 
+
+    set alg [bis_imagemathoperations [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagemedian.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagemedian.tcl
new file mode 100755
index 0000000..8325cdf
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagemedian.tcl
@@ -0,0 +1,146 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_imagemedian 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+#
+# smooth image
+#
+
+itcl::class bis_imagemedian {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Median Filter" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imagemedian::Initialize { } {
+
+    PrintDebug "bis_imagemedian::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ windowsize "kernel size [voxels]" "Filter Size"  {  listofvalues  } 3 { 3 5 7 9 }  0 }
+	{ dimension  "2 or 3 to to do smoothin in 2D or 3D" "Dimensionality"  { listofvalues radiobuttons }    3 { 2  3 }  -999 }
+
+    }
+
+    set defaultsuffix { "_med" }
+    
+    set scriptname bis_imagemedian
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Smoothes an image using median filtering"
+    set description2 " "
+    set backwardcompatibility "New"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imagemedian::Execute {  } {
+
+    PrintDebug "bis_imagemedian::Execute"
+
+    set windowsize   [ $OptionsArray(windowsize) GetValue ]
+    set dimension   [ $OptionsArray(dimension)    GetValue ]
+    set image_in    [ $InputsArray(input_image) GetObject ]
+
+    PrintDebug "windowsize = $windowsize, dimension = $dimension "
+    set smooth  [ vtkImageMedian3D [ pxvtable::vnewobj ]  ]
+    set r $windowsize
+
+    if { $dimension == 3 } {
+	$smooth SetKernelSize $r $r $r
+    } else {
+	$smooth SetKernelSize $r $r 1
+    }
+    $smooth SetInput [ $image_in GetImage ]
+    $this SetFilterCallbacks $smooth "Median Smoothing Image"
+    $smooth Update
+
+
+    set image_out [ $smooth GetOutput ]
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out 
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $smooth Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_imagemedian.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_imagemedian [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imageremoveframes.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imageremoveframes.tcl
new file mode 100755
index 0000000..8f255cc
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imageremoveframes.tcl
@@ -0,0 +1,257 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_imageremoveframes 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+#
+# smooth image
+#
+
+itcl::class bis_imageremoveframes {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    protected method ParseFramesString { val usingseconds tr numframes offset { message "Parsing String"}  { debug 0 }} 
+    public method GetGUIName    { } { return "Remove Frames" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imageremoveframes::Initialize { } {
+
+    PrintDebug "bis_imageremoveframes::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ framelist "List of frame pairs to remove e.g. \"1 2,7 22,40 52\", keep these in quotes. If in frames start at 1, if seconds start at 0.0" "Framelist"  {  string  } "" { "" }  0 }
+	{ keep      "If set to 1 then the inverse operation is performed, i.e. the frame pairs are kept" "Keep Frames" boolean 0 {  0 1  } 1 }
+	{ unit      "Frames defined in seconds or frames " "Unit" { listofvalues radiobuttons }  frames { frames seconds }   -1}
+	{ offset    "Offset from specified values (to be added to the frame list in the same unit as the framelist)" "Offset" real  0.0   { 0.0 10.0 }  -2 }
+	{ tr        "Length of each frame in seconds " "Time Dimension (TR)" real  1.0   { 0.01 100.0 }  -3 }
+	
+    }
+
+    set defaultsuffix { "_crp" }
+    
+    set scriptname bis_imageremoveframes
+    set completionstatus "Testing"
+
+    #
+    #document
+    #
+    
+    set description "Extracts frames from a 4D image"
+    set description2 " "
+    set backwardcompatibility "New"
+    set category "Image Processing-4D"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_imageremoveframes::ParseFramesString { val usingseconds tr numframes offset { message "Parsing String"}  { debug 0 }} {
+    
+    puts stdout "Val=$val"
+
+    regsub -all "," $val " " val2
+    regsub -all "\"" $val2 " " val2
+    regsub -all ";" $val2 " " val2
+    regsub -all ":" $val2 " " val2
+    regsub -all -- "-" $val2 " " val2
+    regsub -all " +" $val2 " " val3
+    set val3 [ string trim $val3 ]
+    set n [ llength $val3 ]
+    set m [ expr 2*(int($n/2)) - $n ]
+
+    set val4 [ lsort -real -increasing $val3 ]
+
+    if { $val4 != $val3 } {
+	set errormessage "Error: Bad Definition for $message, frames ($val3) are not specified in ascending order"
+	return 0
+    }
+
+    if { $debug > 0 } {
+	puts stdout "+++++ Cleaned up  val=$val3 , number = $n (isodd = $m)\n"
+    }
+
+    if { $m != 0 } {
+	set errormessage "Error: Bad Definition for $message, $n total elements ($val3), which is not an even number"
+	return 0
+    }
+    set half [ expr int($n/2) ]
+    set arr [ vtkIntArray New ]
+    $arr SetNumberOfComponents 2
+
+    set plist ""
+    for { set i 0 } { $i < $half } { incr i } {
+	
+	set ind(0) [ expr $i *2 ]
+	set ind(1) [ expr $ind(0) +1 ]
+	
+	if { $debug > 1 } {
+	    puts  -nonewline stdout "\t\t\t Checking Pair [ expr $i+1 ]/$half  $ind(0):$ind(1)"
+	}
+	
+	
+	set op(0) -1
+	set op(1) -1
+	for { set k 0 } { $k <= 1 } { incr k } {
+	    set op($k)   [ lindex $val3 $ind($k) ]
+
+	    if { $usingseconds == "seconds"  } {
+		set p($k) [ expr int(($op($k)+$offset)/$tr) ]
+	    } else {
+		set p($k) [ expr int($op($k)+$offset-1) ]
+	    }
+	    
+	    if { $debug > 1 } {
+		puts -nonewline stdout "p($k) = $op($k) sec --> $p($k) fr, "
+	    }
+	    
+	    
+	    if { $p($k) < 0 || $p($k) >= $numframes } {
+		set errormessage "Error: Out of bounds Block Definition for $message, blockpart = [ expr $i+1 ] ( $op(0):$op(1)), numframes= $numframes, allowed range 0: [ expr $numframes-1]"
+		$arr Delete
+		return 0
+	    }
+	    
+	    set p($k) [ expr $p($k)  ]
+	    if { $debug > 1 } {
+		puts -nonewline stdout "--> + $offset = $p($k) "
+	    }
+	}
+	if { $debug > 0 } {
+	    puts stdout ""
+	}
+	lappend plist [ list [ expr $p(0)+1 ] [ expr $p(1)+1 ] ]
+	$arr InsertNextTuple2 $p(0) $p(1)
+    }
+
+    puts stdout "\n Final List plist in frames beginning at 1 = $plist"
+    return $arr
+    
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imageremoveframes::Execute {  } {
+
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+
+
+    set framelist    [ $OptionsArray(framelist) GetValue ]
+    set usingseconds [ $OptionsArray(unit) GetValue ]
+    set offset       [ $OptionsArray(offset) GetValue ]
+    set tr           [ $OptionsArray(tr) GetValue ]
+    set keep         [ $OptionsArray(keep) GetValue ]
+    set image_in    [ $InputsArray(input_image) GetObject ]
+
+
+
+
+    set nframes [ [ $image_in GetImage ] GetNumberOfScalarComponents ]
+    set arr [ $this ParseFramesString $framelist $usingseconds $tr $nframes $offset "parsing framelist" 0 ]
+
+    if { $arr == 0 } {
+	return 0
+    }
+    
+    set tmp [ vtkImageData New ]
+    set util [ vtkbisConnectivityUtility New ]
+
+
+    
+
+    if { $keep > 0 } {
+	set ok  [ $util ExtractImageBlocks [ $image_in GetImage ] $tmp $arr ]
+    } else {
+	set ok  [ $util DiscardImageBlocks [ $image_in GetImage ] $tmp $arr ]
+    }
+    
+    $arr Delete
+    $util Delete
+
+    if { $ok ==0 } {
+	$tmp Delete
+	return 0
+    }
+    
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $tmp
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    $tmp Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_imageremoveframes.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_imageremoveframes [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagetoimagealgorithm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagetoimagealgorithm.tcl
new file mode 100644
index 0000000..0925a8b
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagetoimagealgorithm.tcl
@@ -0,0 +1,200 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_imagetoimagealgorithm 1.0
+package require bis_algorithm 1.0
+
+
+
+#
+# smooth image
+#
+
+itcl::class bis_imagetoimagealgorithm {
+
+    inherit bis_algorithm
+
+    constructor { } { }
+    public method InitializeImageToImageAlgorithm { }
+    public method Execute { } { puts stderr "Nothing to Do" }
+
+    # Get Info about Algorithm for use in GUI Container
+    public method IsImageToImage { } { return 1 }
+    public method IsDualImage    { } { return 0 }
+    public method SetContainer { cont }  { set containerobject $cont }
+    public method GetContainer { }  { return $containerobject }
+    public method UpdateInputsFromContainer { }
+    public method UpdateContainerWithOutput { } 
+
+    # Input and Output Methods
+    public method GetInput { }
+    public method GetOutput { }
+    public method SetInput { img }
+
+    # Set Filenames etc
+    public method  UpdateOutputFilenames { } 
+    public method CheckInputObjects { } 
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imagetoimagealgorithm::InitializeImageToImageAlgorithm { } {
+
+    set executename [ $this GetGUIName ]
+    # This assumes that a derived class has done some work here already
+
+    PrintDebug "bis_imagetoimagealgorithm::Initialize" 
+
+    set tmp $inputs
+    set inputs { { input_image "Input Image" pxitclimage  ""    0 } }
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend inputs [ lindex $tmp $i ]
+    }
+    
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set tmp $outputs
+    
+    set outputs { { output_image "Output Image"  pxitclimage  "" 1 }}
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+    	lappend outputs [ lindex $tmp $i ]
+    }
+
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    #    lappend options [ list outname  "output filename root" "Output" string ""     { "" }  -1000 ]
+
+
+    if { $defaultsuffix == "" } {
+	set defaultsuffix { "_out" }
+    }
+    
+    
+
+    #
+    #document stuff
+    #
+
+
+    if { $category == "" } {
+	set category    "Image Processing"
+    }
+    
+    if { $authors == "" } {
+	set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+    }
+
+    $this AddDefaultOptions
+}
+
+
+# ----------------------------------------------------------
+#
+#  Container Stuff ....
+#
+# ----------------------------------------------------------
+
+itcl::body bis_imagetoimagealgorithm::SetInput  { img } {
+
+    #puts stderr "Setting Input Image $this, [ $img GetShortDescription ]"
+    $this SetInputObject input_image $img
+}
+
+itcl::body bis_imagetoimagealgorithm::GetInput  { } {
+
+    return [ $this GetInputObject input_image ]
+}
+
+itcl::body bis_imagetoimagealgorithm::GetOutput { } {
+
+    return [ $this GetOutputObject output_image ]
+}
+
+
+itcl::body bis_imagetoimagealgorithm::UpdateInputsFromContainer { } {
+
+    if { $containerobject == 0 } {	return    }
+
+    set img [ $this GetInput ]
+    $img ShallowCopy [ $containerobject GetFirstInputObject ] 
+    $this UpdateOutputFilenames
+}
+
+itcl::body bis_imagetoimagealgorithm::UpdateContainerWithOutput { } {
+
+    set img  [ $this GetOutput ] 
+
+    PrintDebug "In Update Container With Output $this, $img [ $img GetDescription ]\n"
+    if { $containerobject == 0 } {
+	if { $bis_viewer !=0 } {
+	    $bis_viewer SetImage $img
+	}  elseif { $vtk_viewer !=0 } {
+	    $vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+	} 
+    } else {
+	PrintDebug "Calling Container ($this, $containerobject) SetResultsFromObject" 
+	$containerobject SetResultsFromObject $img $this
+	# Unload result at this point
+	$img Clear
+    }
+}
+
+# --------------------------------------------------------------------------------------------
+
+itcl::body bis_imagetoimagealgorithm::UpdateOutputFilenames { } {
+
+    set fn [ $InputsArray(input_image) GetFileName ]
+    set outlist [ $this CreateDefaultOutputFileList $fn ]
+
+    set l [ ::bis_common::SplitFileNameGZ $fn ]
+    set ext [ lindex $l 1 ]
+    set m [ lindex $outlist 0 ]
+
+    set force 0;   if { $guimode == "managed" } { set force 1     }
+
+    $OutputsArray(output_image) SetFileName "${m}${ext}"  $force
+    return 1
+
+}
+
+
+itcl::body bis_imagetoimagealgorithm::CheckInputObjects { } {
+
+
+    set image_in    [ $this GetInput ]
+    set d [ $image_in GetImageSize ]
+
+    if { $d < 1 } {
+	return 0
+    }
+
+
+    return 1
+
+}
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagetosurfacealgorithm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagetosurfacealgorithm.tcl
new file mode 100644
index 0000000..ddebf12
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_imagetosurfacealgorithm.tcl
@@ -0,0 +1,194 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_imagetosurfacealgorithm 1.0
+package require bis_surfacetosurfacealgorithm 1.0
+
+# -----------------------------------------------------------------------------------------
+#  Header Stuff
+# -----------------------------------------------------------------------------------------
+itcl::class bis_imagetosurfacealgorithm {
+
+    inherit bis_surfacetosurfacealgorithm
+
+    constructor { } { }
+    public method InitializeImageToSurfaceAlgorithm { }
+    public method Execute { } { puts stderr "Nothing to Do" }
+
+
+    # Get Info about Algorithm for use in GUI Container
+    public method IsImageToSurface { } { return 1 }
+    public method SetContainer { cont }  { set containerobject $cont }
+    public method GetContainer { }  { return $containerobject }
+    public method UpdateInputsFromContainer { }
+
+
+    # Input and Output Methods
+    public method GetInput { }
+    public method GetOutput { }
+    public method SetInput { img }
+
+    # Set Filenames etc
+    public method  UpdateOutputFilenames { } 
+    public method  CheckInputObjects { } 
+
+    # Keep track of GUI elements in standalonemode
+    protected method CreateInputGUIInterface { fr }
+    public method OutputModified { }
+    public method InputModified { } { }
+
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_imagetosurfacealgorithm::InitializeImageToSurfaceAlgorithm { } {
+
+
+    # This assumes that a derived class has done some work here already
+
+    PrintDebug "bis_imagetosurfacealgorithm::Initialize" 
+
+    set tmp $inputs
+    set inputs { { input_image "Input Image" pxitclimage  ""  }    }
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend inputs [ lindex $tmp $i ]
+    }
+    
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set tmp $outputs
+    
+    set outputs { { output_surface "Output Surface"  pxitclsurface  "" }}
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+    	lappend outputs [ lindex $tmp $i ]
+    }
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    #    lappend options [ list outname  "output filename root" "Output" string ""     { "" }  -1000 ]
+
+
+    if { $defaultsuffix == "" } {
+	set defaultsuffix { "_surfout" }
+    }
+    
+    
+    #
+    #document stuff
+    #
+
+    if { $category =="" } {
+	set category    "Image to Surface Algorithms"
+    }
+    
+    if { $authors == "" } {
+	set authors "alark.joshi at yale.edu, xenophon.papademetris at yale.edu."
+    }
+
+    $this AddDefaultOptions
+}
+
+
+# ----------------------------------------------------------
+# Standalone GUI Stuff
+# ----------------------------------------------------------
+
+itcl::body bis_imagetosurfacealgorithm::CreateInputGUIInterface { fr } {
+
+    return [ ::bis_algorithm::CreateInputGUIInterface $fr ]
+}
+
+itcl::body bis_imagetosurfacealgorithm::OutputModified { } {
+    
+    if { $bis_surfacecontrol != 0 } {
+	$bis_surfacecontrol SetResultsFromObject [ $this GetOutput ] $this
+    }
+}
+
+# ----------------------------------------------------------
+#
+#  Container Stuff ....
+#
+# ----------------------------------------------------------
+
+itcl::body bis_imagetosurfacealgorithm::SetInput  { img } {
+
+    $this SetInputObject input_image $img
+}
+
+itcl::body bis_imagetosurfacealgorithm::GetInput  { } {
+
+    return [ $this GetInputObject input_image ]
+}
+
+itcl::body bis_imagetosurfacealgorithm::GetOutput { } {
+
+    return [ $this GetOutputObject output_surface ]
+}
+
+
+itcl::body bis_imagetosurfacealgorithm::UpdateInputsFromContainer { } {
+
+    if { $containerobject == 0 } {	return    }
+
+    set img [ $this GetInput ]
+    $img ShallowCopy [ $containerobject GetImage ] 
+    $this UpdateOutputFilenames
+}
+
+# --------------------------------------------------------------------------------------------
+
+itcl::body bis_imagetosurfacealgorithm::UpdateOutputFilenames { } {
+
+    set fn [ $InputsArray(input_image) GetFileName ]
+    set outlist [ $this CreateDefaultOutputFileList $fn ]
+
+    set l [ ::bis_common::SplitFileNameGZ $fn ]
+    set ext ".vtk"
+    set m [ lindex $outlist 0 ]
+
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+    $OutputsArray(output_surface) SetFileName "${m}${ext}" $force
+    return 1
+
+}
+
+
+itcl::body bis_imagetosurfacealgorithm::CheckInputObjects { } {
+
+
+    set image_in    [ $this GetInput ]
+   	set d [ $image_in GetImageSize ]
+    if { $d < 27 } {
+		return 0
+    }
+
+
+    return 1
+
+}
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_interleave.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_interleave.tcl
new file mode 100755
index 0000000..ddab37b
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_interleave.tcl
@@ -0,0 +1,156 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] mjack]
+
+package require bis_imagetoimagealgorithm 1.0
+package provide bis_interleave 1.0
+
+#
+# interleave
+#
+
+itcl::class bis_interleave {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Interleave Frames" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_interleave::Initialize { } {
+
+#    puts stdout "bis_interleave::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ interleave "Reorder Slices/Frames" "Interleave"  boolean   1 { 0 1 }  0 }
+	{ numframes "number of output frames" "Num Frames"  int   1 { 1 10000 }  2 }
+	{ numslices "number of output slices" "Num Slices"  int   1 { 1 10000 }  1 }
+    }
+
+    set defaultsuffix { "_interleave" }
+    
+    set scriptname bis_interleave
+
+    set description "interleaves image."
+    set description2 ""
+    set backwardcompatibility "Reimplemented from mpjinterleave.tcl. Once default output file (***_inter) was output, now you need to specify output file name."
+    set authors "hirohito.okuda at yale.edu,marcel.jackowski.yale.edu"
+    set category "Image Processing-4D"
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_interleave::Execute {  } {
+
+    set currentimage  [ $this GetInput ]
+
+
+    set nc [ [ $currentimage GetImage ] GetNumberOfScalarComponents ]
+    set outfr [ $OptionsArray(numframes) GetValue ] 
+    set outsl [ $OptionsArray(numslices) GetValue ] 
+    set doreord [ $OptionsArray(interleave) GetValue ] 
+    
+    if { $nc == $outfr && $doreord == 0 } {
+	set errormessage "Current image already has $nc frames!\n No need to reorder slices/frames!"
+	return 0
+    }
+
+    set currentresults [ $this GetOutput ] 
+	
+    set tmpimg [ vtkImageData [ pxvtable::vnewobj ]]
+
+    if { $nc == 1 } {
+	set co [ vtkpxImageComponentsToFrames [ pxvtable::vnewobj ]]
+	$co SetInverse 1
+	$co SetInput [ $currentimage GetImage ]
+	if { $doreord == 0 } {
+	    $co SetSlicesPerFrame $outsl
+	} else {
+	    $co SetSlicesPerFrame $outfr
+	}
+	$co Update
+	$tmpimg ShallowCopy [ $co GetOutput ]
+	$co Delete
+    } else {
+	$tmpimg ShallowCopy [ $currentimage GetImage ] 
+    }
+
+    if { $doreord == 1 } {
+	set ut [ vtkpxUtil  [ pxvtable::vnewobj ]]
+	$ut ReorderImage [ $currentresults GetImage ] $tmpimg
+	$ut Delete
+    } else {
+	$currentresults ShallowCopyImage $tmpimg
+    }
+    
+    $tmpimg Delete
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $currentimage GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment" 0
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_interleave.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_interleave [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_intrinsicconnectivity.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_intrinsicconnectivity.tcl
new file mode 100755
index 0000000..6c6d8c7
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_intrinsicconnectivity.tcl
@@ -0,0 +1,275 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_intrinsicconnectivity 1.0
+package require bis_dualimagealgorithm 1.0
+
+
+itcl::class bis_intrinsicconnectivity {
+
+    inherit bis_dualimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Intrinsic Connectivity Map" }
+	public method GetSecondOutput { }
+	#overwrite parent method
+	public method CheckInputObjects { }
+	
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_intrinsicconnectivity::Initialize { } {
+
+    PrintDebug "bis_intrinsicconnectivity::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+		{ mode      "Type of intrinsic connectivity"                       "Mode"             { listofvalues radiobuttons } Whole { Whole Ipsilateral Contralateral }       0 }
+		{ usemask   "Use Mask"                                             "Use Mask"         boolean                       1     { 0 1  }                    20 } 
+		{ threshold "Threshold to be count as connected"                   "Threshold"        { real triplescale 100 }      0.0   { 0.0 1.0 }                 30 }
+		{ calculate "Take absolute sum or square sum of correlation"       "Calculate Method" { listofvalues radiobuttons } Abs   { Abs Sqr }                 50 }
+		{ range     "Take positive correlation/negative correlation/both " "Range"            { listofvalues radiobuttons } Both  {  Positive Negative Both } 40 }
+    }
+
+    #this provide output GUI
+    set outputs { 
+	{ second_output "Overthreshold Count" pxitclimage  ""  10 }   
+    }
+	
+    set defaultsuffix { "_ic" }
+    set category "Functional Imaging"    
+    set scriptname bis_intrinsicconnectivity
+    set completionstatus "Done"
+    
+    #
+    #document
+    #
+    
+    set description "Calculate the intrinsic connectivity of an image."
+	set description2 "User can choose the threshold, look at which range (+, - or both correlation) and look at absolute sum or sum squares. Output is a 3D image of absolute sum or sum squares."
+    set backwardcompatibility ""
+    set authors "isabella.murphy at yale.edu, xilin.shen at yale.edu."
+    
+    $this InitializeDualImageAlgorithm
+	$this RenameInput 0 "Functional Image"
+	$this RenameInput 1 "Mask Image" 102
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_intrinsicconnectivity::Execute {  } {
+
+
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+
+    #set doraw  [ $OptionsArray(raw)   GetValue ]
+    set mode [ $OptionsArray(mode) GetValue ]
+	
+    set msk          [ $OptionsArray(usemask)   GetValue ]
+    set threshold    [ $OptionsArray(threshold) GetValue ]
+	set calculate    [ $OptionsArray(calculate) GetValue ]
+	set range        [ $OptionsArray(range)     GetValue ]
+	#set textfilename [ $OptionsArray(filename)  GetValue ]
+    set image_in     [ $this GetInput ]
+	#set lookN       [ $OptionsArray(lookN)     GetValue ]
+
+
+    if { $mode == "Whole" } {
+	set map  [ vtkbisIntrinsicConnMap New  ] 
+    } else {
+	set map [ vtkbisIpsilateralConnMap New ] 
+    }
+
+    #$map SetOutputRaw  [ expr $doraw > 0 ]
+    $map SetThreshold $threshold
+	#$map SetFileName $textfilename
+    $map SetInput [ $image_in GetObject ]
+	if { $mode == "Contralateral" } {
+		$map SetDoContralateral 1
+	}
+	
+	
+    if { $msk == "1" } {
+	puts stdout "Using Mask ..."
+	$map SetImageMask [ [ $this GetInputObject second_image ] GetObject ]
+    } 
+	
+	set f(2) 0
+	if { $range == "Positive" } {		
+		$map SetRange 1
+		set f(2) Pos
+	} elseif { $range == "Negative" } {
+		$map SetRange 2
+		set f(2) Neg
+	} else {
+		$map SetRange 3
+		set f(2) Both
+	}
+	set f(3) 0
+	if { $calculate == "Abs" } {
+		$map SetAbs 1
+		set f(3) Abs
+	} else {
+		$map SetAbs 2
+		set f(3) Sqr
+	}
+	
+	#if { $lookN == "N" } {
+	#	$map SetLookN 1
+	#} else {
+	#	$map SetLookN 2
+	#}
+	
+    $this SetFilterCallbacks $map "Calculate intrinsic connectivity map with threshold=$threshold"
+    $map Update
+	
+	if { $mode == "Whole" } {
+		set mean [ $map GetMean ]
+		set std [ $map GetStd ]
+		set degreemean [ $map GetDegreeMean ]
+		set degreestd [ $map GetDegreeStd ]
+		set textv1 "Mean: $mean, Standard Deviation: $std."
+		set textv2 "Degree Mean: $degreemean, Degree Standard Deviation: $degreestd."
+	} else {
+		set lmean [ $map GetLMean ]
+		set rmean [ $map GetRMean ]
+		set lstd [ $map GetLStd ]
+		set rstd [ $map GetRStd ]
+		set lsize [ $map GetLSize ]
+		set rsize [ $map GetRSize ]
+		set ldegreemean [ $map GetLDegreeMean ]
+		set rdegreemean	[ $map GetRDegreeMean ]
+		set ldegreestd [ $map GetLDegreeStd ]
+		set rdegreestd [ $map GetRDegreeStd ]
+		set textv1 "Left Brain Mean\t $lmean\n Left Brain Standard Deviation\t $lstd\n Left Brain Number of Voxels\t $lsize\n Right Brain Mean\t $rmean\n Right Brain Standard Deviation\t $rstd\n Right Brain Number of Voxels\t $rsize\n"
+		set textv2 "Left Brain Degree Mean\t $ldegreemean\n Left Brain Degree Standard Deviation\t $ldegreemean\n Right Brain Degree Mean\t $rdegreemean\n Right Brain Standard Deviation\t $rdegreestd\n"
+		
+	}
+	
+
+	set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $map GetOutput ]
+	$outimage CopyImageHeader [ $image_in GetImageHeader ]
+	
+	set outimage2 [ $OutputsArray(second_output) GetObject ]
+	$outimage2 ShallowCopyImage [ $map GetOutData2 ]
+    $outimage2 CopyImageHeader [ $image_in GetImageHeader ]
+    
+   
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+	[ $outimage GetImageHeader ] AddComment "[ $this GetGUIName ] Log: $textv1" 0
+	[ $outimage2 GetImageHeader ] AddComment "$comment $Log" 0
+	[ $outimage2 GetImageHeader ] AddComment "[ $this GetGUIName ] Log: $textv2" 0
+
+	set fname2 [ $outimage2 cget -filename ]
+	if { $fname2 == "" } {
+		set f(0) [ $InputsArray(input_image) GetFileName ]
+	    set f(1) [ $InputsArray(second_image) GetFileName ]
+		for { set i 0 } { $i <= 1 } { incr i } {
+		set l($i) [ ::bis_common::SplitFileNameGZ $f($i) ]
+		set f($i) [ file tail [ lindex $l($i) 0 ] ]
+	    set ext($i) [ lindex $l($i) 1 ]
+		}
+		set newname [ file join [ file dirname $f(0) ]  "$f(0)_$f(1)_$f(2)_$f(3)_N_ic" ]
+		$outimage2 configure -filename $newname
+	}
+	
+
+	# This crashes the code -- there is some morey leak somewhere!
+	#	$map Delete
+
+    return 1
+}
+itcl::body bis_intrinsicconnectivity::GetSecondOutput {  } {
+	return [ $this GetOutputObject second_output ]
+}
+itcl::body bis_intrinsicconnectivity::CheckInputObjects { } {
+
+
+    set image_in    [ $this GetInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 2 } {
+	return 0
+    }
+	
+	set msk [ $OptionsArray(usemask) GetValue ]
+	if { $msk == "1" } {
+		set image_in    [ $this GetSecondInput ]
+        set d [ $image_in GetImageSize ]
+        if { $d < 2 } {
+	    return 0
+    	}
+	}
+	
+    return 1
+
+}
+
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_mediantemporalsmoothimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_intrinsicconnectivity [ pxvtable::vnewobj ] ]
+    $alg MainFunction 
+}
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_intsegment.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_intsegment.tcl
new file mode 100755
index 0000000..7e16922
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_intsegment.tcl
@@ -0,0 +1,207 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package provide bis_intsegment 1.0
+
+#
+# segment image
+#
+
+itcl::class bis_intsegment {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Intensity Segmentation" }
+    #
+    #protected
+    #
+
+    protected method HistogramSegmentation { img  } 
+    protected method MRFSegmentation       { img  }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_intsegment::Initialize { } {
+
+    PrintDebug "bis_intsegment::Initialize" 
+    #name,description,type,object,filename(if applicable),priority (optional)
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ algorithm  "Algorithm to use for segmentation " "Algorithm" { listofvalues radiobuttons }  Clustering { Clustering MRF }   1}
+	{ numclasses "Number of classes (tissue labels) including background " "Number of Classes"  int    3 { 2 10 }  3 }
+	{ smoothness  "Spatial smoothness. If  algoirithm is set to clustering this is ignored " "Smoothness" real  1.0 { 0.01 10.0 }  2 }
+	{ maxsigmaratio    "The ratio of the max standard deviation to the min standard deviation" "MaxSigmaRatio" real  0.05   { 0.0 1.0 }  -100 }
+	{ iterations    "Number of iterations in Markov Random Field smoothness relaxation" "Iterations" int  20  { 2 40 }  2 }
+	{ clustiterations    "Number of iterations in Clustering Step" "Initial Iterations" int  50  { 2 100 }  -101 }
+	{ numbins    "Number of bins in Clustering Step" "Clustering Bins" int  256  { 16 1024 }  -102 }
+	{ epsilon    "Convergence level (percentage of changed voxels)" "Epsilon" real  0.05  { 0.0 10.0 }  -103 }
+    }
+
+    set defaultsuffix { "_segm" }
+    
+    set scriptname bis_intsegment
+
+    #
+    #document
+    #
+
+    set category "Segmentation"
+    set description "segment image."
+    set description2 ""
+    set backwardcompatibility "The default output filename was ****_quicksegm when smoothness is set 0. Now the default output file is always  **_segm. upon request."
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+itcl::body bis_intsegment::HistogramSegmentation { img  } {
+
+    set numclasses     [ $OptionsArray(numclasses) GetValue ]
+    set smoothness     [ $OptionsArray(smoothness) GetValue ]
+    set maxsigmaratio  [ $OptionsArray(maxsigmaratio) GetValue ]
+    set mrfiterations  [ $OptionsArray(iterations)    GetValue ]
+
+    set segm [ vtkpxHistogramSegmentation [ pxvtable::vnewobj ]]
+    $segm SetInput $img
+    $segm SetNumberOfClasses $numclasses
+    $segm SetIterations [ $OptionsArray(clustiterations) GetValue ]
+    $segm SetNumberOfBins [ $OptionsArray(numbins) GetValue ]
+    $segm SetConvergence [ $OptionsArray(epsilon) GetValue ]
+    $segm SetSigma 0.05
+    $segm GenerateLabelsOn
+    $segm SetOutlierDetection 0
+    $segm SetPreprocessingMode 0
+    $segm SetDistributionModel 0
+    $segm SetOutlierProbability 0
+    $this SetFilterCallbacks $segm "Histogram Segmenting Image"
+    $segm SetMaxSigmaRatio     $maxsigmaratio
+    $segm Update
+
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+    $img ShallowCopy [ $segm GetOutput ]
+    $segm Delete
+    return $img
+}
+
+# ------------------------------------------------------------------------------------
+
+itcl::body bis_intsegment::MRFSegmentation { img  } {
+
+    set numclasses     [ $OptionsArray(numclasses) GetValue ]
+    set smoothness     [ $OptionsArray(smoothness) GetValue ]
+    set maxsigmaratio  [ $OptionsArray(maxsigmaratio) GetValue ]
+    set mrfiterations  [ $OptionsArray(iterations)    GetValue ]
+
+    set segm [ vtkpxMRFSegmentation [ pxvtable::vnewobj ]]
+    $segm SetInput $img
+    $segm SetNumberOfClasses $numclasses
+    $segm SetIterations [ $OptionsArray(clustiterations) GetValue ]
+    $segm SetNumberOfBins [ $OptionsArray(numbins) GetValue ]
+    $segm SetConvergence [ $OptionsArray(epsilon) GetValue ]
+    $segm SetSigma 0.05
+    $segm GenerateLabelsOn
+    $segm SetOutlierDetection 0
+    $segm SetPreprocessingMode 0
+    $segm SetDistributionModel 0
+    $segm SetOutlierProbability 0
+    $segm SetMaxSigmaRatio     $maxsigmaratio
+    $segm SetComputeBiasField 0
+    $segm SetMRFIterations $mrfiterations
+    $segm SetSmoothness $smoothness
+    $this SetFilterCallbacks $segm "MRF Segmenting Image"
+    $segm Update
+
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+    $img ShallowCopy [ $segm GetOutput ]
+    $segm Delete
+    return $img
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_intsegment::Execute {  } {
+
+    PrintDebug "bis_intsegment::Execute"
+
+    set algorithm      [ $OptionsArray(algorithm) GetValue ]
+
+    set image_in      [ $this GetInput ] 
+
+    if { $algorithm == "Clustering" } {
+	set image_out [ HistogramSegmentation [ $image_in GetObject ]  ]
+    } else {
+	set image_out [  MRFSegmentation [$image_in GetObject ]  ]
+    }
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out 
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    [ $outimage GetImageHeader ] AddComment [ $this GetCommandLine full ] 
+    return 1
+}
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_intsegment.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_intsegment [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_landmarkeditor.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_landmarkeditor.tcl
new file mode 100644
index 0000000..07cabf6
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_landmarkeditor.tcl
@@ -0,0 +1,771 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_landmarkeditor 1.0
+
+# 	$Id: bis_landmarkeditor.tcl,v 1.4 2004/02/17 20:58:26 xenios Exp xenios $	
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    lappend auto_path [ file dirname [ info script ]]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+}
+
+
+
+
+
+# Added some capability
+
+package require pxvtable 1.0
+package require Itcl
+package require Iwidgets 
+package require pxitclbasecontrol 1.0
+package require bis_viewer 1.0
+
+itcl::class bis_landmarkeditor {
+
+    inherit pxitclbasecontrol
+
+    private variable vtk_viewer 0
+    private variable bis_viewer 0
+
+    protected variable polymanager 0
+    private variable itcllandmarks 0
+    private variable landmarks 0
+    private variable back_landmarks 0
+
+    private variable highlight_sphere 0
+    private variable highlight_surface 0
+
+    private variable last_picked_point -1
+
+    protected variable nomouseinput 0
+    private common   thisparam
+    protected variable initialized 0
+    protected variable fontname "{ fixed 8 }"
+    public variable selectionbox 0
+    protected variable last_filename ""
+
+
+    protected variable datatree 0
+    protected variable xmlpointer 0
+    protected variable filemenu 0
+
+
+    
+    constructor { par } {
+	pxitclbasecontrol::constructor $par
+    } {
+	InitializeLandmarkControl
+    }
+
+    # Fixed
+    private method InitializeLandmarkControl { } 
+
+    # Viewer Interface
+    protected method SetViewer  { viewer }
+    protected method AddToViewer  {  }
+    public method GetViewer  {  } { return $bis_viewer }
+
+    public method SetNoMouseInput { } { set nomouseinput 1 }
+    public method Initialize { inpwidg viewer }
+    public method DelayedInitialize { }
+
+
+    # -------------------------------------
+
+    # Create User Interface Stuff
+    # -------------------------------------
+    protected method CreateMenu { menubar }
+    public method UpdateInterface { }
+    public method UpdateStatus { }
+    public method SelectedLandmark { } 
+    public method DisplayAttributes { }
+    public method CenterOnLandmark { mode } 
+    public method SetColor { }
+
+    # ----------------------------------------
+    # Menu/Mouse Callbacks
+    # ----------------------------------------
+    public method HandleClickedPoint { vx pt mouse stat }
+    public method PickLandmark { x y z } 
+    public method MovePickedLandmark { x y z} 
+    public method ReleaseLandmarkPick { args } 
+    public method UndoLast { }
+    public method DeleteLandmark { }
+    public method DeleteAllLandmark { }
+
+    # -----------------------------------
+    # Load and Save Stuff
+    # -----------------------------------
+    public method TreeEditLandmarks { land datatree node }
+    public method LoadLandmarks { fname }
+    public method StoreInTree { }
+    public method SaveLandmarks { fname }
+    public method AutoSaveLandmarks { mode }
+    public method EnableAutoSave { }
+
+    
+
+}
+# -------------------------------------------------------------------------------------------    
+::itcl::body bis_landmarkeditor::InitializeLandmarkControl { }  {
+
+    global tcl_platform
+    if { $tcl_platform(platform) == "windows" } {
+	set fontname "{ fixed 5 }"
+    } else {
+	set fontname "{ fixed 8 }"
+    }
+
+    set itcllandmarks  [ [ pxitcllandmarks \#auto ] GetThisPointer ]
+    set landmarks [ $itcllandmarks GetObject ]
+    set back_landmarks [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+
+
+    set thisparam($this,autosave) 1
+    set thisparam($this,autosaveon) 0
+    set thisparam($this,current_landmark) 0 
+    set thisparam($this,readonly) 2
+    set thisparam($this,status) ""
+    set thisparam($this,mousemode) 0
+}
+  
+   
+# Sets the input
+::itcl::body bis_landmarkeditor::SetViewer { bviewer } {
+
+    if { $bis_viewer != 0 } {
+	return 0
+    }
+
+    if { [ $bviewer isa bis_viewer ] == 0 } {
+	return 0
+    }
+
+
+    set bis_viewer $bviewer
+    set vtk_viewer [ $bviewer GetViewer ]
+    set polymanager [ $bis_viewer GetPolygonalDisplayManager ]
+}
+
+
+::itcl::body bis_landmarkeditor::AddToViewer { } {
+
+    $bis_viewer AddCursorNotifier "$this" "HandleClickedPoint"
+
+ 
+    set highlight_sphere [ vtkpxCrossHairSource New ]
+    set highlight_surface [ [ pxitclsurface \#auto ] GetThisPointer ]
+    $highlight_surface ShallowCopySurface [ $highlight_sphere GetOutput ]
+
+    $bis_viewer AddPolygonalObject $itcllandmarks 1 { visible 1 name "LndmrkEdit_1" } 
+    $bis_viewer AddPolygonalObject $highlight_surface 1 { visible 0 name "LndmrkEdit_2" } 
+    $polymanager UpdateObject $itcllandmarks
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_landmarkeditor::Initialize { inpwidg bviewer } {
+
+    global tcl_platform
+
+    if { $initialized } { return $basewidget } 
+
+    set basewidget [ toplevel $inpwidg ]
+    wm withdraw $basewidget
+    wm title $basewidget "Landmark Editor"
+    wm geometry $basewidget 300x300
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    set initialized 1
+
+    if { $bviewer !=0 } {
+	SetViewer $bviewer
+    }
+    return $basewidget
+
+}
+
+::itcl::body bis_landmarkeditor::DelayedInitialize { } {
+   
+    if { $fullyinitialized == 1 } {
+	return
+    }
+
+    set last_filename ""
+
+
+    set menubar [ menu $basewidget.menubar ]; $basewidget configure -menu $menubar
+
+
+    
+    if { $bis_viewer == 0 } {
+	set nt [ panedwindow $basewidget.nt -orient horizontal -showhandle 1 \
+		     -borderwidth 10 -relief raised -sashwidth 4 -sashpad 4 \
+		     -handlesize 5 -handlepad 50  ]
+	pack $nt -side top -expand true -fill both
+	set mainframe [frame $nt.left ]
+	set vframe   [ frame $nt.right ]
+	$nt add $mainframe -minsize  500
+	$nt add $vframe -minsize 500
+	set viewer [ bis_viewer \#auto ]
+	$viewer CreateGUI $vframe
+	$this SetViewer [ $viewer GetThisPointer ]
+    } else {
+	set mainframe [ frame $basewidget.notebook ]
+	pack $mainframe -side top -expand true -fill both -pady 2 -padx 2
+    }
+    
+    $this AddToViewer    
+    set ttop [ frame $mainframe.0  ]
+    set top [ [ iwidgets::labeledframe $mainframe.1  -labeltext "Info"  ] childsite ]
+    set bot [ [ iwidgets::labeledframe $mainframe.2  -labeltext "Points"  ] childsite ]
+    set bbar [ frame $mainframe.3 ]
+
+    pack $bbar -side bottom -expand false -fill x -pady 2
+
+    pack $mainframe.0 $mainframe.1 -side top -expand false -fill x
+    pack $mainframe.2 -side top -expand true -fill both
+
+
+    set thisparam($this,mousemode) 0
+    if { $nomouseinput == 0 } {    
+	eval "radiobutton $ttop.1 -text \"Disabled\" -value 0 -variable [ itcl::scope thisparam($this,mousemode) ]"
+	eval "radiobutton $ttop.2 -text \"Pick Mode\"     -value 1 -variable [ itcl::scope thisparam($this,mousemode) ]"
+	eval "radiobutton $ttop.3 -text \"Add Mode\"      -value 2 -variable [ itcl::scope thisparam($this,mousemode) ]"
+	pack $ttop.1 $ttop.2 $ttop.3 -side left -padx 0
+    }
+
+    CreateMenu $menubar
+
+    # ------------------------------------------------------------------------------------------
+    #  info box
+    # ------------------------------------------------------------------------------------------
+    set ent1 [ ::iwidgets::entryfield $top.ent -width 40 -state normal -labeltext "" -foreground black -textbackground white -textvariable [ itcl::scope thisparam($this,status) ]]
+    pack $ent1 -side top -expand true -fill x
+
+
+    set selectionbox $bot.a
+    eval "iwidgets::scrolledlistbox $bot.a -selectmode single -labelpos nw -vscrollmode dynamic -hscrollmode dynamic -selectioncommand { $this SelectedLandmark } -exportselection 1"
+    
+
+    eval "button $bbar.0 -text \"Undo Last Deletion\" -command { $this UndoLast } -padx 5"
+    eval "button $bbar.1 -text \"Delete Current\" -command { $this DeleteLandmark } -padx 5"
+    eval "button $bbar.2 -text \"Display Attributes\" -command { $this DisplayAttributes } -padx 5"
+    pack $bbar.0 $bbar.1 $bbar.2 -side top -expand true -fill x
+    pack $bot.a -side top -expand true -fill both -padx 2 -pady 2
+    set fullyinitialized 1
+    set l [ AddLogoLabel $bbar ];     pack $l -side bottom -padx 1 
+}
+
+# -----------------------------------------------------------------------------------------------------------
+itcl::body bis_landmarkeditor::UndoLast  { } {
+
+    $landmarks Copy $back_landmarks
+    $this UpdateInterface
+    $polymanager UpdateObject $itcllandmarks
+}
+
+itcl::body bis_landmarkeditor::DeleteLandmark { } {
+
+    set ind $thisparam($this,current_landmark) 
+    set n [ $landmarks GetNumPoints ]
+    if { $ind <0 || $ind>=$n } {
+	return ""
+    }
+    
+    $back_landmarks Copy $landmarks
+
+    $landmarks DeletePoint $ind
+
+    set sel [ expr $ind -1 ]
+    if { $sel < 0 } {
+	set sel 0
+    }
+    $this UpdateInterface
+    $selectionbox selection clear 0 end
+    if { $n > 1 } {
+	$selectionbox selection set $sel $sel
+	$this SelectedLandmark
+    }
+
+
+    $polymanager UpdateObject $itcllandmarks
+}
+
+itcl::body bis_landmarkeditor::DeleteAllLandmark { } {
+
+    set ok [ tk_messageBox -type yesno -default no -title "Think again ..." -message "Do you want to delete all points?" -icon question  ]
+    if { $ok == "no" } {
+	return 0
+    }
+    $back_landmarks Copy $landmarks
+    $landmarks DeleteAllPoints
+    $this UpdateInterface
+    $polymanager UpdateObject $itcllandmarks
+}
+
+itcl::body bis_landmarkeditor::SelectedLandmark { }  {
+
+    set ind [ [ $selectionbox component listbox ] curselection ]
+    if { $ind == "" || $ind < 0 } {
+	$polymanager UpdateSameObject $highlight_surface { visible 0 } 1
+	return 
+    }
+    set thisparam($this,current_landmark) $ind
+
+    set r [ expr [ $landmarks GetPointScale ] * 2.5 ]
+    scan [ [  $landmarks GetPoints ] GetPoint $ind ] "%f %f %f" x y z
+    scan  [  $landmarks GetOrigin ]  "%f %f %f"  ox oy oz
+    scan  [  $landmarks GetSpacing ]  "%f %f %f" sx sy sz
+
+    $highlight_sphere SetPosition [ expr $x*$sx +$ox ] [ expr  $y*$sy +$oy ] [ expr $z * $sz + $oz ]
+    $highlight_sphere SetLength $r
+    $highlight_sphere Update
+    $highlight_surface ShallowCopySurface [ $highlight_sphere GetOutput ]
+    eval "$polymanager UpdateSameObject $highlight_surface { visible 1 } 1"
+}
+
+itcl::body bis_landmarkeditor::DisplayAttributes { } {
+
+    $polymanager SetCurrentObject $itcllandmarks
+    $polymanager ShowWindow
+}
+# -----------------------------------------------------------------------------------------------------------
+# Menu stuff
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_landmarkeditor::CreateMenu { menubase } {
+
+    set mb [ menu $menubase.filem -tearoff 0 ]
+    $menubase add cascade -underline 0  -label File -menu $mb
+
+    eval "$mb add command -label Load -command { $this LoadLandmarks \"\" }"
+    eval "$mb add command -label Save -command { $this SaveLandmarks \"\" }"
+    $mb add separator
+    eval "$mb add command -label Close -command { $this HideWindow }"
+
+    set filemenu  $mb
+
+    set mb [ menu $menubase.editm -tearoff 0 ]
+    $menubase add cascade -underline 0  -label Edit -menu $mb
+    eval "$mb add checkbutton -label \"Auto Save\" -variable [ itcl::scope thisparam($this,autosave) ] -command { $this EnableAutoSave}"
+    $mb add separator
+    set thisparam($this,mousemode) 0
+	eval "$mb add radiobutton -label \"Disabled Mode\"  -value 0 -variable [ itcl::scope thisparam($this,mousemode) ]"
+	eval "$mb add radiobutton -label \"Pick Mode\"  -value 1 -variable [ itcl::scope thisparam($this,mousemode) ]"
+	eval "$mb add radiobutton -label \"Add Mode\"  -value 2 -variable [ itcl::scope thisparam($this,mousemode) ]"
+	$mb add separator
+    if { $nomouseinput == 0 } {
+	eval "$mb add command -label \"Delete Landmark\" -command { $this DeleteLandmark }"
+	eval "$mb add command -label \"Delete All Landmarks\" -command { $this DeleteAllLandmark }"
+    }
+}
+# -------------------------------------------------------------------------------------------
+#
+# Pick and Edit Stuff 
+#
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_landmarkeditor::PickLandmark { x y z } {
+
+    if { $last_picked_point !=-1 } {
+	return 0
+    }
+
+    set pt [ [  $landmarks GetPoints ] GetPoint $last_picked_point ]
+    scan $pt "%f %f %f" px py pz
+	
+    set r [ expr [ $landmarks GetPointScale ] * 2.5 ]
+    $highlight_sphere SetPosition $x $y $z
+    $highlight_sphere SetRadius $r
+    $highlight_sphere Update
+
+    $highlight_surface ShallowCopySurface [ $highlight_sphere GetOutput ]
+    eval "$polymanager UpdateSameObject $highlight_surface { visible 1 } 0"
+    $polymanager UpdateSameObject $itcllandmarks 
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_landmarkeditor::MovePickedLandmark { x y z }  {
+
+    if { $last_picked_point == - 1 } {
+	return 0
+    }
+
+    $landmarks SetPoint $last_picked_point $x $y $z 1
+
+    $selectionbox delete $last_picked_point $last_picked_point
+    set pt  [ [ $landmarks GetPoints ] GetPoint $last_picked_point ]
+    scan $pt "%f %f %f" px py pz
+    set line [ format "Point: %.3f %.3f %.3f"  $px $py $pz ]
+    $selectionbox insert $last_picked_point $line
+    $selectionbox selection clear 0 end
+    $selectionbox selection set $last_picked_point $last_picked_point
+
+
+    $highlight_sphere SetPosition $x $y $z
+    $highlight_sphere Update
+    
+    $highlight_surface ShallowCopySurface [ $highlight_sphere GetOutput ]
+    $polymanager UpdateSameObject $highlight_surface { visible 1 } 0
+    $polymanager UpdateSameObject $itcllandmarks { visible 1 }
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_landmarkeditor::ReleaseLandmarkPick { args } {
+
+    if { $last_picked_point == -1 } {
+	return 0
+    }
+    
+    $polymanager UpdateSameObject $highlight_surface { visible 1 } 0
+    $polymanager UpdateSameObject $itcllandmarks 
+    set last_picked_point -1
+    
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_landmarkeditor::HandleClickedPoint { vx pt mode stat } {
+
+    if { $thisparam($this,mousemode) == 0 } {  return 0 }
+
+    set a [ wm state $basewidget  ]
+    if { $a != "normal" } {
+	return 0
+    }
+    
+
+    if { [ llength $pt ] !=3 } { return 0 }
+
+    scan $pt  "%f %f %f" x y z
+    if { $x == -1.0 && $y == -1.0 && $z == -1.0 } {  return 0 }
+    set ok 0
+    
+    if { $mode == -1 && $stat == -1 } {
+	return 0
+    }
+
+    if { $mode == 1 &&  $stat == 0 &&  $last_picked_point == -1 } { 
+	set r [ expr [ $landmarks GetPointScale ] * 2.5 ]
+	set index [  $landmarks FindClosestPoint $x $y $z $r 1 ]
+	if { $index >=0 } { 
+	    set last_picked_point $index
+	    set ok [ PickLandmark  $x $y $z  ]
+	}
+    } 
+
+    if { $last_picked_point == -1 && $mode==1 && $stat == 0 &&  $thisparam($this,mousemode) == 2 } {
+	puts stderr "Adding points here .............."
+	$landmarks AddPoint $x $y $z 1 
+	$this UpdateInterface
+	set n [ $landmarks GetNumPoints ]
+	$selectionbox selection clear 0 end
+	$selectionbox selection set end end
+	$this  SelectedLandmark
+	set last_picked_point [ expr $n -1 ]
+	$this PickLandmark $x $y $z
+#	$this UpdateStatus
+    }
+
+
+    if { $stat == 1 && $last_picked_point !=-1 } {
+	
+	set ok [ MovePickedLandmark $x $y $z ]
+	
+    } elseif { $stat == 2 && $last_picked_point !=-1 } {
+	
+	set ok [ ReleaseLandmarkPick $x $y $z  ]
+	
+    }
+
+    return $ok
+}
+# ---------------------------------------------------------------------------------------------
+# Callback Stuff
+# ---------------------------------------------------------------------------------------------
+itcl::body bis_landmarkeditor::TreeEditLandmarks { land dtree node } {
+
+
+    if { [ $land isa pxitcllandmarks  ] == 0 } {
+	return 0
+    }
+
+    set old $datatree
+
+    set datatree $dtree
+    set xmlpointer $node
+
+
+
+    $itcllandmarks Copy $land
+    set landmarks [ $itcllandmarks GetObject ]
+
+    set last_filename ""
+    set f [ $node GetAttribute Title ]
+    SetTitle "(DataTree) Landmark Editor node=$f"
+    UpdateInterface
+    $polymanager SetCurrentObject $itcllandmarks
+    $polymanager UpdateSameObject $itcllandmarks { visible 1 } 
+    puts stderr "Done ..."
+
+#    if { $old == 0 } {
+#	$filemenu add separator
+#	eval "$filemenu add command -label \"Update Tree\" -command { $this StoreInTree }"
+#    }
+}
+# ------------------------------------------------------------------------
+itcl::body bis_landmarkeditor::StoreInTree {  } {
+
+    if { $datatree == 0 } {
+	return
+    }
+
+    $datatree UpdateEditedSurface $xmlpointer $itcllandmarks
+
+}
+# ------------------------------------------------------------------------
+
+itcl::body bis_landmarkeditor::LoadLandmarks { fname } {
+
+    if { $landmarks == 0 } {
+	return 0
+    }
+
+    if { $fname == "" } {
+	set typelist { 
+	    {"Landmark Grid Files" {".mgrid*" } }
+	    {"All Files" {*}}
+	}
+	
+	set f1 $last_filename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+
+	set fname [tk_getOpenFile -title "Load Landmark Multi Grid File" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    set ok [ $itcllandmarks Load $fname ]
+    if { $ok > 0 } {
+	set last_filename $fname
+	SetTitle "Landmark Editor [ file tail $last_filename]"
+	UpdateInterface
+	$polymanager SetCurrentObject $itcllandmarks
+	$polymanager UpdateSameObject $itcllandmarks { visible 1 } 
+
+	set datatree 0
+	set xmlpointer 0
+    }
+
+
+
+    return $ok
+}
+
+# -------------------------------------------------------------------------------------------
+itcl::body bis_landmarkeditor::SaveLandmarks { fname } {
+
+    if { $landmarks == 0 } {
+	return 0
+    }
+
+    if { $fname == "" } {
+	set typelist { 
+	    {"Landmark Grid Files" {".mgrid*" } }
+	    {"All Files" {*}}
+	}
+	
+	set f1 $last_filename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname [tk_getSaveFile -title "Save Landmark Multi Grid File" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    set ok [ $itcllandmarks Save $fname ]
+
+    if { $ok > 0 } {
+	set last_filename $fname
+	SetTitle "Landmark Editor [ file tail $last_filename]"
+    }
+    
+    return $ok
+}
+
+
+# -------------------------------------------------------------------------------------------
+itcl::body bis_landmarkeditor::EnableAutoSave { } {
+
+    if { $thisparam($this,autosave) == 0 } {
+	set thisparam($this,autosaveon) 0
+    } else {
+	AutoSaveLandmarks once
+    }
+}
+
+itcl::body bis_landmarkeditor::AutoSaveLandmarks { mode } {
+
+    if { $thisparam($this,autosaveon) == 1 && $mode =="once" } {
+	return 0
+    }
+
+    if { $thisparam($this,autosave) == 0 } {
+	set thisparam($this,autosaveon) 0
+	return 0
+    }
+
+    if { $last_filename == "" } {
+	set last_filename "autosave"
+    }
+
+    set l_filename "[ file root $last_filename]_autosave.land"
+    
+    if { $thisparam($this,readonly) != 2 } {
+	set ok [ $landmarks Save $l_filename ]
+    } else {
+	set ok 1
+    }
+    
+    if { $thisparam($this,autosaveon) == 0 } {
+	set thisparam($this,autosaveon) 1
+    }
+    
+    eval "after 30000  $this AutoSaveLandmarks timer"
+
+    return $ok
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_landmarkeditor::UpdateStatus { } {
+
+    set fn [ file tail [ $itcllandmarks cget -filename ]]
+    set thisparam($this,status) "[$itcllandmarks GetShortDescription] $fn"
+}
+# ------------------------------------------------------------------------------------------
+
+::itcl::body bis_landmarkeditor::UpdateInterface { } {
+
+    $this UpdateStatus
+    $selectionbox delete 0 end
+    set n [ $landmarks GetNumPoints ]
+    
+    for { set i 0 } { $i < $n } { incr i } {
+	set pt  [ [ $landmarks GetPoints ] GetPoint $i ]
+	scan $pt "%f %f %f" px py pz
+
+	set line [ format "Point: %.3f %.3f %.3f"  $px $py $pz ]
+	$selectionbox insert end $line
+    }
+    $selectionbox selection clear 0 end
+    $selectionbox selection set end end
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_landmarkeditor::CenterOnLandmark { mode } {
+
+    set point [ [ $landmarks  GetPoints ] GetPoint $thisparam($this,current_landmark) ]
+    scan [ $point GetPosition ] "%f %f %f" p(0) p(1) p(2)
+    set img [ $vtk_viewer GetImage ]
+    
+
+    $vtk_viewer SetScaledCoordinates $p(0) $p(1) $p(2)
+
+    if { $mode > 0  } {
+	# Clip Stuff Also
+
+	set camera [ [ [ $vtk_viewer GetRenderer 3 ] GetRenderer ] GetActiveCamera ]
+
+	scan [ $camera GetPosition ]  "%f %f %f" c(0) c(1) c(2)
+	scan [ $camera GetFocalPoint ] "%f %f %f" f(0) f(1) f(2)
+
+
+	for { set i 0 } { $i<=2} { incr i } {
+	    set d($i) [ expr $f($i) - $c($i) ]
+	    set p($i) [ expr $p($i) - $c($i) ]
+	}
+	set magn [ expr sqrt($d(0)*$d(0) + $d(1)*$d(1) + $d(2)*$d(2)) ]
+	
+	set dist 0.0
+	for { set i 0 } { $i<=2} { incr i } {
+	    set d($i) [ expr $d($i) / $magn ]
+	    set dist [ expr $dist +  $p($i)*$d($i) ]
+	}
+
+	set sp 5.0
+	if { $mode == 2 } {
+	    set sp 20.0
+	}
+
+	$camera SetClippingRange [ expr $dist - $sp ] [ expr $dist+$sp]
+	$polymanager UpdateSameObject $itcllandmarks 
+    }
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body bis_landmarkeditor::SetColor { } {
+
+    $polymanager SetCurrentObject $itcllandmarks
+    $polymanager SetColor
+}
+# -------------------------------------------------------------------------------------------
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    package require vtkpxcontrib
+    wm withdraw .
+
+
+    set tp .[ pxvtable::vnewobj ] 
+
+    set electrode_editor [ [ bis_landmarkeditor \#auto 0 ]  GetThisPointer ]
+    $electrode_editor Initialize $tp 0
+    wm geometry $tp 1024x800
+    $electrode_editor DelayedInitialize
+
+    if { [ llength $argv ] > 0 } {
+	set img [ pxitclimage \#auto ]
+	$img Load [ lindex $argv 0 ]
+	[ $electrode_editor GetViewer ]  SetImage $img
+	[ $electrode_editor GetViewer ]  SetImageColormapMode 0
+	itcl::delete object $img
+    }
+
+
+    if { [ llength $argv ] > 1 } {
+	set ok [ $electrode_editor LoadLandmarks [ lindex $argv 1 ] ]
+    }
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_landmarkstolandmarksalgorithm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_landmarkstolandmarksalgorithm.tcl
new file mode 100644
index 0000000..3112d04
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_landmarkstolandmarksalgorithm.tcl
@@ -0,0 +1,190 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_landmarkstolandmarksalgorithm 1.0
+package require bis_algorithm 1.0
+
+
+# -----------------------------------------------------------------------------------------
+#  Header Stuff
+# -----------------------------------------------------------------------------------------
+itcl::class bis_landmarkstolandmarksalgorithm {
+
+    inherit bis_algorithm
+
+    constructor { } { }
+    public method InitializeLandmarksToLandmarksAlgorithm { }
+    public method Execute { } { puts stderr "Nothing to Do" }
+
+
+    # Get Info about Algorithm for use in GUI Container
+    public method IsLandmarksToLandmarks { } { return 1 }
+    public method SetContainer { cont }  { set containerobject $cont }
+    public method GetContainer { }  { return $containerobject }
+    public method UpdateInputsFromContainer { }
+    public method UpdateContainerWithOutput { } 
+
+
+    # Input and Output Methods
+    public method GetInput { }
+    public method GetOutput { }
+    public method SetInput { sur }
+
+    # Set Filenames etc
+    public method  UpdateOutputFilenames { } 
+    public method  CheckInputObjects { } 
+
+    
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_landmarkstolandmarksalgorithm::InitializeLandmarksToLandmarksAlgorithm { } {
+
+
+    # This assumes that a derived class has done some work here already
+
+    PrintDebug "bis_landmarkstolandmarksalgorithm::Initialize" 
+
+    set tmp $inputs
+    set inputs { { input_landmarks "Input Landmarks" pxitcllandmarks  "" 2 }    }
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend inputs [ lindex $tmp $i ]
+    }
+    
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set tmp $outputs
+    
+    set outputs { { output_landmarks "Output Landmarks"  pxitcllandmarks  "" 1 }}
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+    	lappend outputs [ lindex $tmp $i ]
+    }
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    #    lappend options [ list outname  "output filename root" "Output" string ""     { "" }  -1000 ]
+
+
+    if { $defaultsuffix == "" } {
+	set defaultsuffix { "_out" }
+    }
+    
+    
+
+    #
+    #document stuff
+    #
+
+    if { $category =="" } {
+	set category    "Landmarks Processing"
+    }
+    
+    if { $authors == "" } {
+	set authors "xenophon.papademetris at yale.edu."
+    }
+
+    $this AddDefaultOptions
+}
+
+# ----------------------------------------------------------
+#
+#  Container Stuff ....
+#
+# ----------------------------------------------------------
+itcl::body bis_landmarkstolandmarksalgorithm::SetInput  { land } {
+
+    $this SetInputObject input_landmarks $land
+}
+
+itcl::body bis_landmarkstolandmarksalgorithm::GetInput  { } {
+
+    return [ $this GetInputObject input_landmarks ]
+}
+
+itcl::body bis_landmarkstolandmarksalgorithm::GetOutput { } {
+
+    return [ $this GetOutputObject output_landmarks ]
+}
+
+
+itcl::body bis_landmarkstolandmarksalgorithm::UpdateInputsFromContainer { } {
+
+    if { $containerobject == 0 } {	return    }
+    $this SetInput [ $containerobject GetLandmarks ]
+    $this UpdateOutputFilenames
+
+}
+
+itcl::body bis_landmarkstolandmarksalgorithm::UpdateContainerWithOutput { } {
+
+    set land  [ $this GetOutput ] 
+
+
+    PrintDebug "In Update Container With Output $this, $land [ $land GetDescription ]\n"
+    
+    if { $containerobject == 0 } {
+	if { $bis_viewer !=0 } {
+	    $bis_viewer AddOrReplacePolygonalObject $land
+	}
+    } else {
+	PrintDebug "Calling Container ($this, $containerobject) SetResultsFromObject" 
+	$containerobject SetResultsFromObject $land $this
+    }
+}
+
+# --------------------------------------------------------------------------------------------
+
+itcl::body bis_landmarkstolandmarksalgorithm::UpdateOutputFilenames { } {
+
+    set fn [ $InputsArray(input_landmarks) GetFileName ]
+    set outlist [ $this CreateDefaultOutputFileList $fn ]
+
+    set ext ".land"
+    set m [ lindex $outlist 0 ]
+
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+
+    $OutputsArray(output_landmarks) SetFileName "${m}${ext}" $force
+    return 1
+
+}
+
+
+itcl::body bis_landmarkstolandmarksalgorithm::CheckInputObjects { } {
+
+
+    set landmarks_in    [ $this GetInput ]
+    if {  [ $landmarks_in  GetSize ] < 1 } {
+	return 0
+    }
+
+
+    return 1
+
+}
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_levelset.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_levelset.tcl
new file mode 100755
index 0000000..f576e66
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_levelset.tcl
@@ -0,0 +1,170 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_levelset 1.0
+package require bis_baselevelset 1.0
+
+
+#
+# strip skull
+#
+
+itcl::class bis_levelset {
+
+    inherit bis_baselevelset
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Tissue Levelset" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_levelset::Initialize { } {
+
+    PrintDebug "bis_levelset::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ insidemean "Inside Mean Intensity" "Inside Mean" real 100 { -100000 100000 } 6 }
+	{ outsidemean "Outside Mean Intensity" "Outside Mean" real 20 { -100000 100000 } 8 }
+	{ insidesigma "Inside Standard Deviation of Intensity" "Inside Sigma" real 10 { -100000 100000 } 7 }
+	{ outsidesigma "Outside Standard Deviation Intensity" "Outside Sigma" real 10 { -100000 100000 } 9 }
+	{ biexponential "Outside Distribution is BiExponential" "Biexponential" boolean 0 { 0 1 } { -10 } }
+	{ outsidemean2 "Outside Mean Intensity 2" "Outside Mean 2" real 50 { -100000 100000 } -11 }
+	{ outsidesigma2 "Outside Standard Deviation Intensity 2" "Outside Sigma 2" real 100 { -100000 100000 } -12 }
+	{ dynamicupdate "Dynamic Parameter Update" "Update Parameters" boolean 0 { 0 1 } { 10 } }
+	{ approximatevolume "Volume to constrain levelset to" "Approximate Volume" real 1000 { 0 100000 } -14 }
+	{ volumeweight "Volume constraint weight" "Volume Weight" real 0.0 { 0.0 100.0 } -15 }
+    }
+    lappend options [ list beginlevel "Starting Resolution Level (x native)" "Begin Level"  integer 2 { 1 4  }  20 ]
+    lappend options [ list endlevel   "Final Resolution Level (x native)" "Final Level"  integer 2 { 1 4  }  21 ]
+
+	
+    set defaultsuffix { "_levelset" }
+
+    set scriptname bis_levelset
+    set completionstatus "To be tested"
+
+    #
+    #document
+    #
+    
+    set description "Performs levelset segmentation using the  levelset method of Chan and Vesse with bi-exponential output extensions"
+    set description2 ""
+    set backwardcompatibility "None"
+    set authors "xenios.papademetris at yale.edu"
+
+    $this InitializeBaseLevelset
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+
+itcl::body bis_levelset::Execute {  } {
+
+    PrintDebug "bis_levelset::Execute"
+    set filter [ vtkpxTissueLevelSetFilter New]
+
+    $this SetLevelsetParameters $filter
+
+    $filter SetInsideMean [ $OptionsArray(insidemean) GetValue ]
+    $filter SetInsideSigma [ $OptionsArray(insidesigma) GetValue ]
+    $filter SetOutsideMean [ $OptionsArray(outsidemean) GetValue ]
+    $filter SetOutsideSigma [ $OptionsArray(outsidesigma) GetValue ]
+    $filter SetOutside2Mean [ $OptionsArray(outsidemean2) GetValue ]
+    $filter SetOutside2Sigma [ $OptionsArray(outsidesigma2) GetValue ]
+    $filter SetDynamicParameterUpdate [ $OptionsArray(dynamicupdate) GetValue ]
+    $filter SetBiExponentialOutside [ $OptionsArray(biexponential) GetValue ]
+    $filter SetApproximateVolume [ $OptionsArray(approximatevolume) GetValue ]
+    $filter SetVolumeWeight      [ $OptionsArray(volumeweight) GetValue ]
+    $filter SetBeginLevel [ $OptionsArray(beginlevel) GetValue ]
+    $filter SetEndLevel [ $OptionsArray(endlevel) GetValue ]
+
+    $this SetFilterCallbacks $filter " Levelset"
+    set levelset $filter
+    $filter Update
+
+    set image_in      [ $this GetInput ]
+    set comment [ format " [ $this GetCommandLine full ]" ]
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    $outimage ShallowCopyImage [ $filter GetOutput ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+
+    # Clean up
+    $filter Delete
+
+    
+#    if { $has_surface_actors !=0 } {
+#	set ortho [ $this GetViewer ]
+#	for { set i 0 } { $i <=3 } { incr i } {
+#	    [ [ $ortho GetRenderer $i ] GetRenderer ] RemoveActor $surf_actor($i)
+#	    $surf_actor($i) Delete
+#	}
+#	set has_surface_actors 0
+#    }
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_levelset.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_levelset [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_linearintensityregister.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_linearintensityregister.tcl
new file mode 100755
index 0000000..13f12b4
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_linearintensityregister.tcl
@@ -0,0 +1,199 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_baseintensityregistration 1.0
+package provide bis_linearintensityregister 1.0
+
+#
+# register image
+#
+
+
+
+itcl::class bis_linearintensityregister {
+
+    inherit bis_baseintensityregistration
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Linear Registration" }
+
+
+    # Initialize Transformation
+    protected method ExtractLinearTransform {  numparam } 
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+
+
+itcl::body bis_linearintensityregister::Initialize { } {
+
+    PrintDebug "bis_linearintensityregister::Initialize" 
+
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ mode   "Type of linear registration" "Transformation Mode" { listofvalues } rigid { rigid affine similarity affine2d rigid2d similarity2d } 0 }
+	{ useinitial "Use Initial Transformation" "Use Initial Xform"  boolean   0     { 0 1 } 25 }
+	{ optscalefactor  "Scale Factor for non-translation optimization parameters"   "Opt Scale Factor"  real   1.0    { 0.001 1000.0 } -800 }
+	{ autooptscalefactor "Automatic Setting for Optimization Scale Factor" "Auto Opt Scale Factor"  boolean   1     { 0 1 } -799 }
+    }
+    set scriptname bis_linearintensityregister
+
+    #
+    #document
+    #
+
+    set category "Registration"
+    set description "computes a linear  intensity based registrations."
+    set description2 ""
+    set backwardcompatibility "Refactored from pxmat_register.tcl."
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this InitializeBaseIntensityRegistration
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute. reimplemented from DoNMIAll of pxmat_register.tcl
+# ----------------------------------------------------------------------------------------
+
+
+
+
+itcl::body bis_linearintensityregister::ExtractLinearTransform {  numparam } {
+
+    set image_ref    [ $this GetReferenceImage  ]
+    set image_trn    [ $this GetTransformImage ]
+    set in_xform     [ [ $this GetInitialTransformation ] GetObject ]
+    
+    set xform [ vtkpxLinearTransform [ pxvtable::vnewobj ]]
+    $xform ExtractParameters $in_xform 9 [ $image_ref GetImage ] [ $image_ref GetOrientation ] [  $image_trn GetImage ] [ $image_trn GetOrientation ]
+    for { set k $numparam } { $k < 15 } { incr k } {
+	$xform Put $k 0
+    }
+    return $xform
+}
+
+
+
+
+
+itcl::body bis_linearintensityregister::Execute {  } {
+
+
+    PrintDebug "bis_linearintensityregister::Execute"
+
+    set numparam 6
+
+    set usegpu      [ $OptionsArray(usegpu) GetValue ]
+    set threadmode [  $OptionsArray(threadmode) GetValue ]
+
+    puts stdout "GPU = $usegpu"
+    set areg 0
+    if { $usegpu > 0 } {
+	catch { 
+
+	    set areg  [ vtkbisCUDALinearRegistration New ]; 
+	    $areg SetThreadMode $threadmode
+	}
+    }
+
+    if { $areg == 0 } {
+	set areg [ vtkpxLinearRegistration [ pxvtable::vnewobj ]]
+    }
+
+    set mode [ $OptionsArray(mode) GetValue ]
+    #    puts stderr "Mode=$mode"
+
+    switch -exact $mode { 
+	"rigid"  { 	$areg SetTransformModeToRigid;   }
+	"affine"  { 	$areg SetTransformModeToAffine; set numparam 9  }
+	"similarity"  { 	$areg SetTransformModeToSimilarity; set numparam 9  }
+	"rigid2d"  { 	$areg SetTransformModeToRigid2D }
+	"affine2d"  { 	$areg SetTransformModeToAffine2D  }
+	"similarity2d"  { 	$areg SetTransformModeToSimilarity2D  }
+
+    }
+
+    if { [ $OptionsArray(useinitial) GetValue ] !=0 } {
+	set xform [ ExtractLinearTransform $numparam ]
+	$areg SetInitialTransform $xform
+	$xform Delete
+    }
+    $this SetCommonIntensityRegistrationOptions $areg
+
+    $areg SetOptimizationAutoScale [ expr int( [ $OptionsArray(autooptscalefactor) GetValue ] ) ]
+    $areg SetOptimizationScaleFactor [ $OptionsArray(optscalefactor) GetValue ]
+
+    $this SetFilterCallbacks $areg "Linearly Registering Image"
+
+    set current_registration $areg
+
+    puts stderr " Running [ $areg GetClassName ]"
+
+    $areg Run
+    set current_registration 0
+    [ $this GetOutputTransformation ] CopyTransformation [ $areg GetTransformation ]
+
+    $areg Delete
+
+    $this CreateWarpedImage
+
+    return 1
+}
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_linearintensityregister.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_linearintensityregister [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_linearpointregister.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_linearpointregister.tcl
new file mode 100755
index 0000000..4f5a85a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_linearpointregister.tcl
@@ -0,0 +1,146 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_basepointbasedregistration 1.0
+package provide bis_linearpointregister 1.0
+#
+# register image
+#
+
+
+
+itcl::class bis_linearpointregister {
+
+    inherit bis_basepointbasedregistration
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Linear RPM" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+
+
+itcl::body bis_linearpointregister::Initialize { } {
+
+    PrintDebug "bis_linearpointregister::Initialize" 
+
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ mode   "Type of linear registration" "Transformation Mode" { listofvalues } affine { rigid affine similarity } 0 }
+    }
+    set scriptname bis_linearpointregister
+
+    #
+    #document
+    #
+
+    set category "Registration"
+    set description "computes a linear point based registrations."
+    set description2 ""
+    set backwardcompatibility "Refactored from pxmat_pointregister.tcl"
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this InitializeBasePointBasedRegistration
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute. reimplemented from DoNMIAll of pxmat_register.tcl
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_linearpointregister::Execute {  } {
+    set rpm [ vtkpxLinearRPMRegistration [ pxvtable::vnewobj ]]
+
+    set mode [ $OptionsArray(mode) GetValue ]
+    $rpm SetTransformModeToAffine 
+
+    if { $mode == "rigid" } {
+	$rpm SetTransformModeToRigid   
+    } elseif { $mode == "similarity" } {
+	$rpm SetTransformModeToSimilarity 
+    }
+
+    $this SetCommonPointBasedRegistrationOptions $rpm
+
+    if { [ $OptionsArray(useinitial) GetValue ] !=0 } {
+	set in_xform     [ [ $this GetInitialTransformation ] GetObject ]
+	$rpm SetInitialTransform   $in_xform
+    }
+
+    set surface1    [ $this GetReferenceSurface  ]
+    set surface2    [ $this GetTransformSurface ]
+    
+    puts stderr "This far"
+    puts stderr "Inputs = [ $surface1  GetDescription ], [ $surface2 GetDescription ]"
+
+
+    $this SetFilterCallbacks $rpm "Linear RPM Registration"
+    set currentregistration $rpm
+    $rpm SetSource [ $surface1 GetSurface ]
+    $rpm SetTarget [ $surface2 GetSurface ]
+
+    $rpm Run
+    set currentregistration 0
+    [ $this GetOutputTransformation ] CopyTransformation [ $rpm GetCurrentTransformation ]
+    $rpm Delete
+
+    $this CreateWarpedSurface
+
+    return 1
+}
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_linearpointregister.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_linearpointregister [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_listthresholdimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_listthresholdimage.tcl
new file mode 100755
index 0000000..1684616
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_listthresholdimage.tcl
@@ -0,0 +1,181 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+
+package provide bis_listthresholdimage 1.0
+
+# -----------------------------------------------------------------------------------------
+# threshold image
+#
+
+itcl::class bis_listthresholdimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Threshold By List" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_listthresholdimage::Initialize { } {
+
+    PrintDebug "bis_listthresholdimage::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ list  "Threshold Image List (as opposed to thresholds)" "Threshold List"  string "" { "" }  3 }
+	{ inverse "Inverse Threshold"  "Inverse" { listofvalues radiobuttons } Off  { On Off }  -10 }
+	{ binary "Binary Output" "Binary Output Size"   { listofvalues radiobuttons } Off  { Off On x100 }  6 }
+    }
+
+    set defaultsuffix { "_lthr" }
+    
+    set scriptname bis_listlistthresholdimage
+    set completionstatus "Implementation needs work, interface is OK" 
+    #document
+    #
+    set description "thresholds an image to generate a binary output using a specific threshold."
+    set description2 "The output is a binary image with value = 100 where the original image had values above the threshold and zero elsewhere."
+    set backwardcompatibility "Reimplemented from pxmat_listthresholdimage.tcl"
+    
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Threshold Algorithms
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_listthresholdimage::Execute {  } { 
+
+    set bm          [ $OptionsArray(binary) GetValue ]
+    set scalef 1
+    set binarymask 1
+    if { $bm == "Off" } {
+	set binarymask 0
+    } elseif { $bm == "x100" } {
+	set scalef 100
+    }
+
+    set invalue $scalef
+    set outvalue 0
+
+    
+    if { [ $OptionsArray(inverse) GetValue ] == "On"  } {
+	set outvalue $invalue
+	set invalue  0
+    }
+
+    set lst           [ $OptionsArray(list) GetValue ]
+    # Remove quotes from string !
+    regsub -all "\"" $lst " " lst
+
+    set newlst ""
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	catch { 
+	    set v [ expr round([ lindex $lst $i ] ) ] 
+	    lappend newlst $v
+	}
+    }
+    set newlst [ lsort -integer -increasing -unique $newlst  ]
+    $OptionsArray(list) SetValue $newlst
+
+    set idlist [ vtkIdList New]
+    for { set i 0 } { $i < [ llength $newlst ] } { incr i } {
+	$idlist InsertNextId [ lindex $newlst $i ]
+    }
+
+    set outimage [ $this GetOutput ]
+    
+    set id [ vtkpxImageIDFilter New]
+    $id SetInput [ [ $this GetInput ] GetImage ]
+    $id SetIdList $idlist
+    $id SetInValue  $invalue
+    $id SetOutValue $outvalue
+    $id SetOutputScalarType [ [ [ $this GetInput ] GetImage ] GetScalarType ]
+    $id Update
+ 
+    if { $binarymask == 1 } {
+	$outimage ShallowCopyImage [ $id GetOutput ]
+    } else {
+	set sh  [ vtkImageMathematics New  ]
+	$sh SetInput1 [ [ $this GetInput ] GetImage ]
+	$sh SetInput2 [ $id GetOutput ]
+	$sh SetOperationToMultiply
+	$sh Update
+	
+	$outimage ShallowCopyImage [ $sh GetOutput ]
+	$sh Delete
+    }
+    
+    $id Delete
+    $idlist Delete
+    $outimage CopyImageHeader [ [ $this GetInput ] GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+    
+
+}
+
+# --------------------------------------------------------------------------------------------
+
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_listthresholdimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    set alg [bis_listthresholdimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_logimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_logimage.tcl
new file mode 100755
index 0000000..6092dfe
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_logimage.tcl
@@ -0,0 +1,174 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package require bis_castimage 1.0
+
+package provide bis_logimage 1.0
+
+#
+# shift sccale image
+#
+
+itcl::class bis_logimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Log Image" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_logimage::Initialize { } {
+
+    PrintDebug "bis_logimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ scale "Scale Output to be 0:255" "Scale 256" boolean 0 { 0 1 } 1 }
+    }
+
+    set defaultsuffix { "_log" }
+    
+    set scriptname bis_logimage
+    set completionstatus "Done, needs checking"
+
+
+    set description  "computes linear intensity transformation"
+    set description2 "Output intensity = scale *(Input intensity + shift).Data is thresholded so that the outpu value does not exceed the max or min of the data type."
+    set backwardcompatibility "N/A."
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_logimage::Execute {  } {
+
+    PrintDebug "bis_logimage::Execute"
+
+    set scalef   [ $OptionsArray(scale) GetValue ]
+    set image_in [ $InputsArray(input_image) GetObject ]
+
+    set range [ [ [ [ $image_in GetImage ] GetPointData] GetScalars] GetRange ]
+    set low  [ lindex $range 0 ]
+
+    #   pxtkprint "\nBeginning logarithm range = $range "
+
+    set sh  [ vtkImageShiftScale [ pxvtable::vnewobj ]  ]
+    $sh SetInput [ $image_in GetImage ]
+    $sh SetShift [ expr -$low+1.0 ]
+    $sh SetScale 1.0
+    $sh SetOutputScalarTypeToFloat
+    SetFilterCallbacks $sh "Scaling Intensities of image pass 1"
+    $sh Update
+    
+    #puts stdout "After Scale 1 range [ [ [ [ $sh GetOutput ] GetPointData ] GetScalars ] GetRange ]\n"
+
+    set mt  [ vtkImageMathematics [ pxvtable::vnewobj ]  ]
+    $mt SetInput1 [ $sh GetOutput ]
+    $mt SetOperationToLog
+    SetFilterCallbacks $mt "Performing logarithm"
+    $mt Update
+
+    if { $scalef > 0 } {
+	set maxv 255.0
+	set r [  [ [  [ $mt GetOutput ] GetPointData ] GetScalars ] GetRange ]
+	set scale [ expr $maxv/ [ lindex $r 1 ] ]
+    } else {
+	set scale 1.0
+    }
+
+    # puts stdout "After log 1 range [ [ [ [ $mt GetOutput ] GetPointData ] GetScalars ] GetRange ] scale=$scale\n"
+
+
+    set sh2  [ vtkImageShiftScale [ pxvtable::vnewobj ]  ]
+    $sh2 SetInput [ $mt GetOutput ]
+    $sh2 SetShift 0.0
+    $sh2 SetScale $scale 
+    if { $scale > 1.0 } {
+	$sh2 SetOutputScalarType [ [ $image_in GetImage ] GetScalarType ]
+    } 
+	
+    SetFilterCallbacks $sh2 "Scaling Intensities of image pass 2"
+    
+    $sh2 Update
+    puts stdout "Log: Output range [ [ [ [ $sh2 GetOutput ] GetPointData ] GetScalars ] GetRange ]"
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage [ $sh2 GetOutput ]
+    
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    $sh2 Delete 
+    $sh Delete 
+    $mt Delete 
+
+    return 1
+}
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_logimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_logimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_makebatch.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_makebatch.tcl
new file mode 100755
index 0000000..9851fdc
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_makebatch.tcl
@@ -0,0 +1,548 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_algorithm 1.0
+package provide bis_makebatch 1.0
+
+#
+# output makebatchrmation
+#
+
+itcl::class bis_makebatch {
+
+    inherit bis_algorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+
+    protected method GenerateExample { }
+    protected method ReadSetupFile   { fname docheck }
+    protected method CreateSetupFile { makefile outputdir setparams mode }
+
+    protected method GenerateOutFile { inplist suffix }
+    protected method GenerateFlagString { mode index isinput }
+    protected method DoesInputExist { fname }
+    protected method CleanString { line { nospace 1 }}
+
+    public method GetGUIName { } { return "Make Batch" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_makebatch::Initialize { } {
+
+    PrintDebug "bis_makebatch::Initialize" 
+
+    set options {
+	{ setup "specify the setup file for the batch job" "Setup File"  { filename readfile 40 } "" "textfile" 1 }
+	{ makefile "specify the output makefile for the batch job" "Makefile Name"  { filename writefile 40 } "" "textfile" 2 }
+	{ odir  "specify the output directory for the batch job" "Output Directory" { filename directory 40 } "" "to store outputs" 3 }
+	{ doexample  "generate an example file"   "Do Example" boolean 0 { 0 1 } -10 }
+	{ mode  "default is BioImage Suite mode , i.e. specifiy inputs using -inp, -inp 2 etc. If 0 lists inputs and outputs in sequence" "Mode"  boolean 1 { 0 1 } -11 }
+	{ docheck  "if 1 then we test if the input files exist" "Check Files"  boolean 1 { 0 1 } -12 }
+	{ dummymode  "if 1 then we simply test the setup file but not create any output makefile/directories" "Dummy Mode"  boolean 0 { 0 1 } -13 }
+
+    }
+
+    set defaultsuffix ""
+    
+    set scriptname bis_makebatch
+    set inputs { }
+    set outputs { }
+
+    #
+    #document
+    #
+    
+    set category "Utility"
+    set description "Creates a makefile given a batch input definition file"
+    set description2 ""
+    set backwardcompatibility "Replaces a bunch of old style batch files"
+    set authors "xenophon.papademetris at yale.edu."
+
+    $this AddDefaultOptions 1
+}
+# -----------------------------------------------------------------------------------------
+#  Generating Example for registration ....
+# -----------------------------------------------------------------------------------------
+itcl::body bis_makebatch::GenerateExample { } {
+
+    puts stdout "# Example Batch File"
+    puts stdout "# The following variables can be defined"
+    puts stdout "\# inputlist(1) .. inputlist(9) :  lists of inputs"
+    puts stdout "\# outputsuffix : list of outputsuffices"
+    puts stdout "\# cmdline : the command line beginning with the algorithm"
+    puts stdout "\# logsuffix : the suffix of the log file for each command\n\n"
+    puts stdout "set inputlist(1) {"
+    puts stdout "    ref.hdr"
+    puts stdout "}\n"
+    puts stdout "set inputlist(2) {"
+    puts stdout "    test1.hdr"
+    puts stdout "    test2.hdr"
+    puts stdout "    test3.nii.gz"
+    puts stdout "}\n"
+    puts stdout "#Use the *ignore* flag to skip an optional input, i.e. in this case -inp3 will not be used"
+    puts stdout "set inputlist(3) {"
+    puts stdout "    *ignore*"
+    puts stdout "}\n"
+    puts stdout "set inputlist(4) {"
+    puts stdout "    ref_weight.hdr"
+    puts stdout "}\n"
+    puts stdout "set inputlist(5) {"
+    puts stdout "    w1.hdr"
+    puts stdout "    w2.hdr"
+    puts stdout "    w3.nii.gz"
+    puts stdout "}\n"
+    
+
+    puts stdout "set outputsuffix {"
+    puts stdout "    map.grd"
+    puts stdout "}\n"
+    puts stdout "set logsuffix \"results\"\n"
+    puts stdout "set cmdline \"bis_nonlinearintensityregister.tcl --spacing 20.0 --useinitial \\"
+    puts stdout "  0.0 --useweightimage 2\" "
+
+}
+# -----------------------------------------------------------------------------------------
+itcl::body bis_makebatch::CleanString { line { nospace 1 } } {
+    set line [ string trim $line ]
+    regsub -all "\n" $line " " line
+    regsub -all "," $line " " line
+    regsub -all "\t" $line " " line
+    regsub -all " +" $line " " line
+    if { $nospace == 1 } {
+	regsub -all " " $line "" line
+    }
+    return $line
+}
+# -----------------------------------------------------------------------------------------
+itcl::body bis_makebatch::DoesInputExist { fname } {
+
+    if { $fname == "*ignore*" } {
+	return 1
+    }
+
+    # Step 1 -- is this an image -- then if this is a .hdr file
+
+    set f2 $fname
+    set ext [ file extension $fname ]
+    if { $ext == ".gz" } {
+	set f2 [ file rootname $fname ]
+	set ext [ file extension $f2  ]
+    }
+    
+    if { [ file exists $fname ] == 0 } {
+	set errormessage "$fname does not exist"
+	return 0
+    }
+    if { [ file readable $fname ] == 0 } {
+	set errormessage "Cannot read $fname -- check permissions"
+	return 0
+    }
+
+    if { $ext != ".hdr" } {
+	return 1
+    }
+
+    # From here on we are in analyze mode 
+    set test(1) "[ file rootname $f2].img"
+    set test(2) "$test(1).gz"
+    for { set i 1 } { $i <= 2 } { incr i } {
+	set ok [ $this DoesInputExist $test($i) ]
+	if { $ok ==1 } {
+	    return 1
+	}
+    }
+
+    set errormessage "Cannot read either $test(1) or $test(2)"
+    return 0
+
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_makebatch::ReadSetupFile { fname docheck } {
+
+    if { [ file readable $fname ] == 0 } {
+	set errormessage "Failed to read Setupfile $setupname"
+	return 0
+    }
+
+    set cmdline ""
+    for { set i 1 } { $i <= 9 } { incr i } {
+	set inputlist($i) ""
+	set outputsuffix ""
+    }
+
+    set logsuffix ".results"
+    source $fname
+
+    if { $cmdline == "" } {
+	set errormessage "No Command line specified in $setupname"
+	return 0
+    }
+
+    set pname(cmdline) [ $this CleanString $cmdline   0 ]
+    set logsuffix      [ $this CleanString $logsuffix 1 ]
+
+    if { [ string first "." $logsuffix ] == 0 } {
+	set pname(logsuffix)  $logsuffix
+    } else {
+	set pname(logsuffix) ".$logsuffix"
+    }
+    set icount 1
+
+
+    for { set i 1 } { $i <= 9 } { incr i } {
+	set v [ $this CleanString $inputlist($i) 0 ]
+	if { $v != "" } {
+	    set pname(inputlist,$icount) $v
+	    incr icount
+	}
+    }
+
+    puts stderr "OutputSuffix=$outputsuffix"
+
+    set pname(outputsuffix) [ $this CleanString $outputsuffix 0 ]
+
+    
+    set nlist ""
+    set goodlists 0
+
+    set icount [ expr $icount -1 ]
+    set jcount [ llength $outputsuffix ]
+
+    if { $icount ==0 || $jcount == 0 } {
+	set errormessage "No inputs or outputs specified in setupfile"
+	return 0
+    }
+
+    set pname(numberofinputs) $icount
+    set pname(numberofoutputs) $jcount
+
+
+
+    if { $docheck > 0 } {
+	# Check if inputs exist
+	#
+	for { set i 1 } { $i <= $icount } { incr i } {
+	    set l [ llength $pname(inputlist,$i) ]
+	    for { set j 0 } { $j < $l } { incr j } {
+		set ok [ $this DoesInputExist [ lindex $pname(inputlist,$i) $j ] ]
+		if { $ok == 0 } {
+		    return 0
+		}
+	    }
+	}
+    }
+
+
+    for { set i 1 } { $i <= $icount } { incr i } {
+	set l [ llength $pname(inputlist,$i) ]
+	if { $l > 1 } {
+	    lappend nlist $l
+	}
+    }
+
+#    puts stderr "nlist = $nlist "
+
+    set pname(numberofjobs) 1
+
+    if { [ llength $nlist ] > 0 } {
+	set v [ lindex $nlist 0 ]
+	# Need to do some testing
+	for { set j 1 } { $j < [ llength $nlist ] } { incr j } {
+	    if { $v != [ lindex $nlist $j ] } {
+		set errormessage "Unequal numbers of inputs specified in inputlists"
+		return 0
+	    }
+	}
+	set pname(numberofjobs) $v
+    }
+
+
+    
+
+
+    if { [ llength $nlist ] > 0 } {
+	for { set i 1 } { $i <= $icount } { incr i } {
+	    set l [ llength $pname(inputlist,$i) ]
+	    if { $l == 1 } {
+		set elem [ lindex $pname(inputlist,$i) ]
+		for { set j 1 } { $j < $pname(numberofjobs) } { incr j } {
+		    lappend pname(inputlist,$i) $elem
+		}
+	    }
+	}
+    }
+
+
+
+
+
+
+    return [ array get pname ]
+
+}
+# -----------------------------------------------------------------------------------------
+itcl::body bis_makebatch::GenerateOutFile { inplist suffix } {
+
+
+    set oname ""
+    for { set i 0 } { $i < [ llength $inplist ] } { incr i } {
+
+	if {  [  lindex $inplist $i ] != "*ignore*" } {
+	    puts stdout "using [ lindex $inplist $i ]"
+	    set fname [ file tail [  lindex $inplist $i ] ]
+	    if { [ file extension $fname ] == ".gz" } {
+		set fname [ file rootname $fname ]
+	    }
+	    set fname [ file rootname $fname ]
+	    if { $i > 0 } {
+		set oname "${oname}_${fname}"
+	    } else {
+		set oname $fname
+	    }
+	}
+    }
+
+
+    set ind [ string first "."  $suffix  ] 
+    set ind2 [ string first "_"  $suffix  ] 
+
+    if { $ind == "-1" } {
+	set oname "${oname}.${suffix}"
+    } elseif { $ind ==0 || $ind2 ==0 } {
+	set oname "${oname}${suffix}"
+    } else {
+	set oname "${oname}_${suffix}"
+    }
+    return $oname
+}
+
+# -------------------------------------------------------------------------
+
+itcl::body bis_makebatch::GenerateFlagString { mode index isinput } {
+    if { $mode == 0 } {
+	return ""
+    }
+
+    if { $index ==  0 } {
+	if { $isinput ==1 } {
+	    return "-inp"
+	} else {
+	    return "-out"
+	}
+    }
+
+    set ip [ expr $index + 1 ]
+
+    if { $isinput ==1 } {
+	return "-inp$ip"
+    }
+
+    return "-out$ip"
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_makebatch::CreateSetupFile { makefile outputdir setparams mode } {
+
+    set fout 0
+    if { $makefile != "" } {
+	catch { set fout [ open $makefile w ] }
+	if { $fout == 0 } {
+	    set errormessage "Cannot write makefile in $makefile"
+	    return 0
+	}
+    }
+    
+    array set pname $setparams 
+
+    set outtext ""
+    set listofresults ""
+    set cleanfiles ""
+    
+    for { set job 0 } { $job < $pname(numberofjobs) } { incr job } {
+	
+	set ilist ""
+	for { set i 1 } { $i <= $pname(numberofinputs) } { incr i } {
+	    lappend ilist [ lindex $pname(inputlist,$i) $job ]
+	}
+	
+	set olist ""
+	for { set j 1 } { $j <= $pname(numberofoutputs) } { incr j } {
+	    lappend olist [ file join $outputdir [ $this GenerateOutFile $ilist [ lindex $pname(outputsuffix) [ expr $j -1 ] ] ] ]
+	}
+
+	set outtext "$outtext\n# Job [ expr $job + 1] / $pname(numberofjobs)"
+	set outtext "$outtext\n[ lindex $olist 0 ] : "
+
+	lappend listofresults [ lindex $olist 0 ]
+
+	for { set i 0 } { $i < [ llength $ilist ] } { incr i } {
+	    if { [ lindex $ilist $i ] != "*ignore*" } {
+		set outtext "$outtext [ lindex $ilist $i ]"
+	    }
+	}
+	set outtext "$outtext\n\t $pname(cmdline)"
+	
+	for { set i 0 } { $i < [ llength $ilist ] } { incr i } {
+	    set flag [ $this GenerateFlagString $mode $i 1 ]
+	    if { [ lindex $ilist $i ] != "*ignore*" } {
+		set outtext "$outtext $flag [ lindex $ilist $i ]"
+	    }
+	}
+
+	for { set i 0 } { $i < [ llength $olist ] } { incr i } {
+	    set flag [ $this GenerateFlagString $mode $i 0 ]
+	    set outtext "$outtext $flag [ lindex $olist $i ]"
+	    lappend outputlist($i)  [ lindex $olist $i ]
+	}
+	
+	set resultsfile "[ lindex $olist 0 ]$pname(logsuffix)"
+	set outtext "$outtext > $resultsfile 2>&1\n\n"
+	
+	lappend cleanfiles $resultsfile
+
+    }
+
+    set header "# BioImage Suite Batch File"
+    set header "$header\n# cmdline = $pname(cmdline)"
+    set header "$header\n# logsuffix = $pname(logsuffix)"
+    set header "$header\n# numberofjobs = $pname(numberofjobs)"
+    set header "$header\n# numberofinputs = $pname(numberofinputs)"
+    set header "$header\n# numberofoutputs = $pname(numberofoutputs)\n\n"
+    
+    set header2 "all : $listofresults\n\n"
+    set header2 "$header2\nclean : \n\t rm $listofresults $cleanfiles\n"
+    set header2 "$header2\ncleanwin : \n\t delete $listofresults $cleanfiles\n"
+    set outtext "$header\n$header2\n$outtext"
+
+
+    if { $makefile != "" } {
+	puts $fout "$outtext"
+	close $fout
+	
+	set makelog "$makefile$pname(logsuffix)"
+	
+	set fout [ open $makelog w ]
+	puts $fout "\# Output File lists for future use"
+	puts $fout "\# These  files might become inputs to a new batch job down the road\n"
+	for { set i 0 } { $i < [ llength $olist ] } { incr i } {
+	    puts $fout "set inputlist([ expr $i+1 ]) { "
+	    for { set j 0 } { $j < [ llength $outputlist($i) ] } { incr j } {
+		puts $fout "\t [ lindex $outputlist($i) $j ]"
+	    }
+	    puts $fout "}\n"
+	}
+	close $fout
+	
+	puts stdout "Details = \n$header\n"
+	puts stdout "Makefile stored in $makefile (lists of outputs in $makelog)"
+	puts stdout "use gmake -f $makefile to execute the batch job\n"
+    } else {
+	puts stdout "$outtext\n"
+    }
+
+}
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_makebatch::Execute {  } {
+
+    PrintDebug "bis_makebatch::Execute"
+    
+    set setupname [ $OptionsArray(setup) GetValue ]
+    set makefile  [ $OptionsArray(makefile) GetValue ]
+    set outputdir [ $OptionsArray(odir) GetValue ]
+    set doexample [ $OptionsArray(doexample) GetValue ]
+    set mode      [ $OptionsArray(mode) GetValue ]
+    set docheck   [ $OptionsArray(docheck) GetValue ]
+    set dummymode   [ $OptionsArray(dummymode) GetValue ]
+
+
+    if { $doexample == 1 } {
+	$this GenerateExample
+	return 1
+    }
+
+    set setparams [ $this ReadSetupFile $setupname $docheck ]
+    if { $setparams == 0 } {
+	return 0
+    }
+
+
+
+    if { $dummymode > 0 } {
+	set makefile ""
+    } else {
+	set making 0
+	if { [ file exists $outputdir ] == 0 } {
+	    set making 1
+	    catch { file mkdir $outputdir }
+	}
+	
+	if { [ file exists $outputdir ] == 0 } {
+	    set errormessage "Cannot create $outputdir .. "
+	    return 0
+	}
+
+	puts stdout "Created output directory $outputdir"
+    }
+
+    set ok [ $this CreateSetupFile $makefile $outputdir $setparams $mode ]
+    return $ok
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_makebatch.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_makebatch [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_manualregistration.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_manualregistration.tcl
new file mode 100755
index 0000000..52a3d09
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_manualregistration.tcl
@@ -0,0 +1,372 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_manualregistration 1.0
+package require bis_dualimagealgorithm 1.0
+package require bis_resliceimage 1.0
+package require bis_colorblendimage 1.0
+
+#
+# smooth image
+#
+
+itcl::class bis_manualregistration {
+
+    inherit bis_dualimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Manual Registration" }
+
+    # Override these methods
+    protected method PackOptionsGUIInterface { lst }
+    public method  UpdateOutputFilenames { } 
+    public method GetOutputTransformation { }
+    public method UpdateContainerWithOutput { } 
+    public method UpdateInputsFromContainer { } 
+    public method CheckInputObjects { } 
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_manualregistration::Initialize { } {
+
+    PrintDebug "bis_manualregistration::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ shiftx   "X-Translation (in voxels)" "Shift X"  { real default 4  } 0 { -500 500 }  0 }
+	{ shifty   "Y-Translation (in voxels)" "Shift Y"  { real default 4  } 0 { -500 500 }  1 }
+	{ shiftz   "Z-Translation (in voxels)" "Shift Z"  { real default 4  } 0 { -500 500 }  2 }
+	{ anglex   "X-Rotation in degrees" "Angle X"    { real default 4  } 0 { -359 359 }  3 }
+	{ angley   "Y-Rotation in degrees" "Angle Y"    { real default 4  } 0 { -359 359 }  4 }
+	{ anglez   "Z-Rotation in degrees" "Angle Z"    { real default 4  } 0 { -359 359 }  5 }
+	{ scalex   "X-Scale Factor (percentage 100=identity)" "Scale X"          { real default 4 } 100 { 20 500 }  6 }
+	{ scaley   "Y-Scale Factor (percentage 100=identity)" "Scale Y"          { real default 4 } 100 { 20 500 }  7 }
+	{ scalez   "Z-Scale Factor (percentage 100=identity)" "Scale Z"          { real default 4 } 100 { 20 500 }  8 }
+	{ usepoints   "If 0 -- set transformation manually, otherwise use point sets (which must have the same number of points)" "Use Landmarks"  boolean 0  { 0 1 }  10 }
+	{ mode   "Type of transformation (if using points)" "Transformation Mode" { listofvalues } affine { rigid affine similarity tps } 11 }
+	{ reslimage   "Output a resliced image, or  a red-green blend image, or no  resliced image" "Resliced Image"  listofvalues Resliced  { Resliced ColorBlend }  9 }
+    }
+
+    set outputs { 
+	{ output_transform "Output Transformation"  pxitcltransform  "" 20 }
+    }
+
+    set inputs { 
+	{ refpoints    "Reference Points" pxitcllandmarks  ""  102 }   
+	{ targpoints   "Target Points" pxitcllandmarks  ""  103 }   
+    }
+
+
+    set defaultsuffix  "_mreg" 
+    
+    set scriptname bis_manualregistration
+    set completionstatus "Done"
+    #
+    #document
+    
+    set description "Computes a manual registration of an image"
+    set description2 ""
+    set category "Registration"
+    set backwardcompatibility "Reimplemented from GUI code in pxitcloverlaytool.tcl.  "
+    set authors "xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageAlgorithm
+    $this RenameInput 0 "Reference Image"
+    $this RenameInput 1 "Transform Image" 
+    $this RenameOutput 0 "Resliced Image" 101
+}
+
+# --------------------------------------------------------------------------
+
+itcl::body bis_manualregistration::PackOptionsGUIInterface { lst } { 
+
+
+    set n [ llength $lst ]
+    
+    for { set tab 0 } { $tab <= 1 } { incr tab } {
+	set wlist ""
+	for { set i 0 } { $i < $n } { incr i } {
+	    
+		set pair [ lindex $lst $i ]
+		set ind  [ lindex $pair 1 ]
+		if { $ind == $tab } {
+		    lappend wlist $pair
+		}
+	    }
+
+	set wlist [ lsort -integer  -index 0 $wlist ]
+
+	if { $tab == 1 } {
+	    for { set j 0 } { $j < [ llength $wlist ] } { incr j } {
+		set pair [ lindex $wlist $j ]
+		set name [ lindex $pair 2 ]
+		set widg [ lindex $pair 3 ]
+		pack $widg -side top -expand false -fill x -padx 1
+	    }
+	} else {
+	    # Custom Pack
+	    if { $guimode != "managed" } {
+		grid  [ $OptionsArray(usepoints) GetBaseWidget ]  -row 0 -column 0 -padx 0 -columnspan 2
+		grid  [ $OptionsArray(mode) GetBaseWidget ]       -row 1 -column 0 -columnspan 3 
+	    }
+
+	    grid  [ $OptionsArray(shiftx) GetBaseWidget ]  -row 2 -column 0 
+	    grid  [ $OptionsArray(anglex) GetBaseWidget ]  -row 2 -column 1 
+	    grid  [ $OptionsArray(scalex) GetBaseWidget ]  -row 2 -column 2 
+
+	    grid  [ $OptionsArray(shifty) GetBaseWidget ]  -row 3 -column 0 
+	    grid  [ $OptionsArray(angley) GetBaseWidget ]   -row 3 -column 1
+	    grid  [ $OptionsArray(scaley) GetBaseWidget ]   -row 3 -column 2
+
+	    grid  [ $OptionsArray(shiftz) GetBaseWidget ]  -row 4 -column 0 
+	    grid  [ $OptionsArray(anglez) GetBaseWidget ]   -row 4 -column 1
+	    grid  [ $OptionsArray(scalez) GetBaseWidget ]   -row 4 -column 2
+
+	    grid  [ $OptionsArray(reslimage) GetBaseWidget ]   -row 5 -column 0
+
+	    set v [ file rootname  [ $OptionsArray(reslimage) GetBaseWidget ]]
+	    grid rowconfigure $v 6 -weight 100
+	    grid columnconfigure $v 3 -weight 100
+	}
+    }
+    update idletasks
+
+
+}
+# -----------------------------------------------------------------------------------------
+itcl::body bis_manualregistration::GetOutputTransformation  { } {
+    return [ $this GetOutputObject output_transform ]
+}
+
+itcl::body bis_manualregistration::UpdateOutputFilenames { } {
+
+    set f(0) [ $InputsArray(input_image) GetFileName ]
+    set f(1) [ $InputsArray(second_image) GetFileName ]
+    
+    for { set i 0 } { $i <= 1 } { incr i } {
+	set l($i) [ ::bis_common::SplitFileNameGZ $f($i) ]
+	set f($i) [ file tail [ lindex $l($i) 0 ] ]
+	set ext($i) [ lindex $l($i) 1 ]
+    }
+    
+    set fname [ file join [ file dirname $f(0) ] "$f(0)_$f(1)" ]
+
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+
+    $OutputsArray(output_image) SetFileName "${fname}_${defaultsuffix}$ext(0)" $force
+    if {  [ $OptionsArray(usepoints)  GetValue ] > 0 && [ $OptionsArray(mode) GetValue ] == "tps" } {
+	$OutputsArray(output_transform) SetFileName "${fname}_${defaultsuffix}.tps"  $force
+    } else {
+	$OutputsArray(output_transform) SetFileName "${fname}_${defaultsuffix}.matr" $force
+    }
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_manualregistration::UpdateInputsFromContainer { } {
+
+    if { $containerobject == 0 } {    
+	return
+    }
+
+
+    $this SetSecondInput [ $containerobject GetTargetImage ] 
+    $this SetInput       [ $containerobject GetReferenceImage ] 
+    [ $this GetOutputTransformation ] configure -filename ""
+    [ $this GetOutput ] configure -filename ""
+    $this UpdateOutputFilenames
+    return
+
+}
+# ------------------------------------------------------------------------------------------
+itcl::body bis_manualregistration::UpdateContainerWithOutput { } {
+
+    set img [ $this GetOutput ]
+    if { [ $img GetImageSize ] < 2 } {
+	return ""
+    }
+    if { $containerobject == 0 } {
+	if { $bis_viewer !=0 } {
+	    $bis_viewer SetImage $img
+	}  elseif { $vtk_viewer !=0 } {
+	    $vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+	} 
+    } else {
+	$containerobject SetResultsFromObject $img $this
+	$containerobject SetTransformationFromObject [ $this GetOutputTransformation ] $this
+    }
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_manualregistration::CheckInputObjects { } {
+
+
+    set imglist [ list    [ $this GetInput ]   [ $this GetSecondInput ] ]
+    
+    foreach image_in $imglist {
+	set d [ $image_in GetImageSize ]
+	if { $d < 2 } {
+	return 0
+	}
+    }
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+
+
+itcl::body bis_manualregistration::Execute {  } {
+
+    #    $this UpdateInputsFromContainer
+
+
+    PrintDebug "bis_manualregistration::Execute"
+ #   puts stderr "Shifting [ $this GetCommandLine full ]"
+
+
+    if {  [ $OptionsArray(usepoints)  GetValue ] > 0 } {
+	set land1 [ [ $this GetInputObject refpoints ] GetLandmarks ]
+	set land2 [ [ $this GetInputObject targpoints ] GetLandmarks ]
+	
+	if { [ $land1 GetNumPoints ] != [ $land2 GetNumPoints ]  } {
+	    set errormessage "Point sets do not have equal numbers of points"
+	    return 0
+	}
+
+	set b1 [ vtkpxBaseCurve New ]
+	$b1 Copy $land1
+	$b1 Compact
+	
+	set b2 [ vtkpxBaseCurve New ]
+	$b2 Copy $land2
+	$b2 Compact
+
+	set mode [ $OptionsArray(mode) GetValue ]
+	if { $mode != "tps" } {
+	    set tr [  vtkLandmarkTransform New ] 
+	    if { $mode == "rigid" } { 
+		$tr SetModeToRigidBody
+	    } elseif { $mode == "similarity" } {
+		$tr SetModeToSimilarity
+	    } else {
+		$tr SetModeToAffine
+	    }
+	} else {
+	    set tr [ vtkThinPlateSplineTransform New ]
+	    $tr SetBasisToR
+	}
+	
+	$tr SetSourceLandmarks [ $b1 GetPoints ]
+	$tr SetTargetLandmarks [ $b2 GetPoints ]
+	$tr Modified
+	$tr Update
+	[ $this GetOutputTransformation ] CopyTransformation $tr
+	$tr Delete
+	$b1 Delete
+	$b2 Delete
+    } else {
+	set dshift(x)   [ $OptionsArray(shiftx) GetValue ]
+	set drotate(x)  [ $OptionsArray(anglex) GetValue ]
+	set scale(x)    [ $OptionsArray(scalex) GetValue ]
+	set dshift(y)   [ $OptionsArray(shifty) GetValue ]
+	set drotate(y) [ $OptionsArray(angley) GetValue ]
+	set scale(y)    [ $OptionsArray(scaley) GetValue ]
+	set dshift(z)  [ $OptionsArray(shiftz) GetValue ]
+	set drotate(z) [ $OptionsArray(anglez) GetValue ]
+	set scale(z)   [ $OptionsArray(scalez) GetValue ]
+
+	set image_ref  [ $InputsArray(input_image) GetObject ]
+	set image_trn  [ $InputsArray(second_image) GetObject ]
+	
+	set sp(x) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 0 ]
+	set sp(y) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 1 ]
+	set sp(z) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 2 ]
+	
+	
+	set tr2 [ vtkTransform [ pxvtable::vnewobj ]]
+	set xform [ vtkpxLinearTransform [ pxvtable::vnewobj ]]
+	$xform ManualSetParameters [expr $dshift(x)*$sp(x) ] [ expr $dshift(y) * $sp(y) ] [ expr $dshift(z)*$sp(z) ] $drotate(x) $drotate(y) $drotate(z) $scale(x) $scale(y) $scale(z)  [ $image_ref GetImage ] [ $image_ref GetOrientation ] [  $image_trn GetImage ] [ $image_trn GetOrientation ] $tr2
+	
+	[ $this GetOutputTransformation ] CopyTransformation $tr2
+	$xform Delete
+	$tr2 Delete
+    }
+
+    if { [ $OptionsArray(reslimage) GetValue ] == "Resliced" } {
+	set reslice_alg [bis_resliceimage [pxvtable::vnewobj]]
+    } else {
+	set reslice_alg [bis_colorblendimage [pxvtable::vnewobj]]
+    }
+    
+    $reslice_alg InitializeFromContainer $this
+    $reslice_alg SetInput [ $this GetInput ] 
+    $reslice_alg SetSecondInput [ $this GetSecondInput ] 
+    $reslice_alg SetTransformation [ $this GetOutputTransformation ] 
+    $reslice_alg Execute
+    
+    [ $this GetOutput ] ShallowCopy [ $reslice_alg GetOutput ]
+    itcl::delete obj $reslice_alg
+    [ [ $this GetOutput ] GetImageHeader ] AddComment [ $this GetCommandLine full ] 
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_manualregistration.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_manualregistration [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_manualreslice.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_manualreslice.tcl
new file mode 100755
index 0000000..9943889
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_manualreslice.tcl
@@ -0,0 +1,179 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+
+package provide bis_manualreslice 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+#
+# reslice image
+#
+
+itcl::class bis_manualreslice {
+
+     inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Manual Reslice"}
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_manualreslice::Initialize { } {
+
+    PrintDebug "bis_manualreslice::Initialize" 
+        
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+    { rotx    "Custom Rotation of image around X-axis" "Rotation-X"  real 0.0 { -360.0 360.0 } 0 }
+    { roty    "Custom Rotation of image around Y-axis" "Rotation-Y"  real 0.0 { -360.0 360.0 } 1 }
+    { rotz    "Custom Rotation of image around Z-axis" "Rotation-Z"  real 0.0 { -360.0 360.0 } 2 }
+    
+	{ interp    "Interpolation Mode that is used when reslicing the image" "Interpolation Mode"  listofvalues Linear { "NearestNeighbor" "Linear" "Cubic" }  3 }
+	{ background  "Background Level used to fill voxels outside of mapped area" "Background Value"  real 0.0 { -100000 100000 }  -100 }
+	
+    }
+
+    set defaultsuffix { "_resl" }
+    
+    set scriptname bis_manualreslice
+    set completionstatus "Done"
+    #
+    #documents
+    #
+
+    set category "Image Processing Dual"
+    set description "reslices an image using one or more transformations."
+    set description2 ""
+    set backwardcompatibility "Reimplemented from pxmat_manualreslice.tcl."
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_manualreslice::Execute {  } {
+
+    PrintDebug "bis_manualreslice::Execute"
+
+	set rotx 	   [ $OptionsArray(rotx) GetValue ]
+	set roty 	   [ $OptionsArray(roty) GetValue ]
+	set rotz 	   [ $OptionsArray(rotz) GetValue ]
+	
+    set mode       [ $OptionsArray(interp) GetValue ]
+    set interp 1
+    switch -exact $mode {
+	"NearestNeighbor" { set interp 0 }  
+	"Cubic" { set interp 3 }
+    }
+
+    #vtkobject
+    set image_in    [ $this GetInput ]
+    set spa [[ $image_in GetImage ] GetSpacing ]
+    set dim [[ $image_in GetImage ] GetDimensions ]
+
+    
+    for { set i 0 } { $i <= 2 } { incr i } {
+		set pos($i) [ expr 0.5*[lindex $dim $i]*[lindex $spa $i ] ]
+		set min($i) [ expr -1.0*$pos($i) ]
+	}
+
+    set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+    $trans Identity
+    $trans PostMultiply
+    $trans Translate $min(0) $min(1) $min(2)
+    $trans RotateX $rotx
+    $trans RotateY $roty
+    $trans RotateZ $rotz
+    $trans Translate $pos(0) $pos(1) $pos(2)
+
+    set resl [  vtkbisImageReslice [ pxvtable::vnewobj ] ]
+    $resl SetInput  [ $image_in GetObject ]
+    
+    # set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+    #$resl SetInput             $image_in
+    #$resl SetInformationInput  [ $image_in GetObject ]
+    $resl SetInterpolationMode $interp
+    $resl SetBackgroundLevel   [ $OptionsArray(background) GetValue ]
+    $resl OptimizationOff
+    $resl SetResliceTransform $trans
+    $resl AutoCropOutputOn
+    $resl Update
+    
+
+    # set image_out [$resl GetOutput ]
+    #[ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out 
+
+	set outimage [ $OutputsArray(output_image) GetObject ]
+	$outimage ShallowCopyImage [ $resl GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    
+        
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $trans Delete
+    $resl Delete
+
+#    puts stderr "\t\t\t Reslicing Done\n"
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_manualreslice.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_manualreslice [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_maskimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_maskimage.tcl
new file mode 100755
index 0000000..b4d71cf
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_maskimage.tcl
@@ -0,0 +1,165 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagereslicetransformationalgorithm 1.0
+package provide bis_maskimage 1.0
+
+#
+# blend image
+#
+
+itcl::class bis_maskimage {
+
+    inherit bis_dualimagereslicetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Mask Image"}
+
+
+
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_maskimage::Initialize { } {
+
+    PrintDebug "bis_maskimage::Initialize" 
+
+    set options {
+	{ interp       "Interpolation Mode that is used when reslicing the image" "Interpolation Mode"  listofvalues Linear { "NearestNeighbor" "Linear" "Cubic" }  0 }
+	{ maskdilation "Dilate binary mask prior to masking" "Dilatation of Mask"  listofvalues 0 { 0 1 2 3 4 5 }   2 }
+	{ background   "Background Level used to fill voxels outside of mapped area" "Background Value"  real 0.0 { -100000 100000 }  -100 }
+    }
+
+    set defaultsuffix { "_masked" }
+    
+    set scriptname bis_maskimage
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    set category "Image Processing Dual"
+    set description "blends an image using one or more transformations."
+    set description2 "a useful check of the quality of the transformations"
+    set backwardcompatibility "Reimplemented from pxmat_maskimage.tcl."
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageTransformationAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_maskimage::Execute {  } {
+
+    PrintDebug "bis_maskimage::Execute"
+
+    set d [ $OptionsArray(maskdilation) GetValue ]
+
+
+    set lst [ $this ResliceImageIfNeeded ]
+    set reslimage [ lindex $lst 0 ]
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+
+    set thr [ vtkImageThreshold [ pxvtable::vnewobj ]]
+    $thr ThresholdByUpper 1.0
+    $thr SetInput  $reslimage 
+    $thr SetInValue 1.0
+    $thr SetOutValue 0.0
+    $thr ReplaceInOn
+    $thr ReplaceOutOn
+    
+    if { $d > 0 } {
+	set r [ expr 2*$d + 1 ]
+	set dilate  [  vtkImageContinuousDilate3D [ pxvtable::vnewobj ] ]
+	$dilate SetInput [ $thr GetOutput ] 
+	$dilate SetKernelSize $r $r $r
+	SetFilterCallbacks $dilate "Dilating Mask"
+	$dilate Update
+	$img ShallowCopy [ $dilate GetOutput ]
+	$dilate Delete
+    } else {
+	$thr Update
+	$img ShallowCopy [ $thr GetOutput ]
+    }
+    
+    
+    set mask  [  vtkpxImageMask [ pxvtable::vnewobj ] ]
+    $mask SetInput [ [ $this GetInput ]  GetImage ]
+    $mask SetMask  $img
+    SetFilterCallbacks $mask  "Mask x Image"
+    $mask Update
+    $thr Delete
+    
+    
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage [ $mask GetOutput ]
+
+    # Output orientation etc. is same as input
+    set outimage [ $this GetOutput ] 
+    $outimage CopyImageHeader [ [ $this GetInput ] GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $img Delete
+
+    $this DeleteResliceAlgorithmIfNeeded $lst 
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_maskimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+   
+
+    set alg [bis_maskimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_matrixcorrelation.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_matrixcorrelation.tcl
new file mode 100755
index 0000000..77e64da
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_matrixcorrelation.tcl
@@ -0,0 +1,158 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_matrixcorrelation 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+itcl::class bis_matrixcorrelation {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Matrix Correlation" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_matrixcorrelation::Initialize { } {
+
+    PrintDebug "bis_matrixcorrelation::Initialize" 
+    
+    set options {
+	{ guicmt     "Description of the filter"  "Note"  comment "Matrix Correlation. Take ROI Mean as input." "Calculate the correlation to itself. Output dimension is voxel*voxel*1*1."  400 }
+    	{ dotextfile "Generate output text file" "Generate Text File" boolean 0 { 0 1 } 20 }
+    	{ filename   "specify the filname for the output text file" "Text File Name" { filename writefile } "bismatrix_result.txt" { text { .txt } } 30 }
+	{ filename2  "specify the filname for the output text file for Viewer" "Text File Name" { filename writefile } "outputForConnectivityViewer.txt" { text { .txt } } -30 }
+	{ raw   "Raw Correlation"  "Compute Raw Correlations"  boolean   0  { 0 1  }  -10  }
+	
+	}
+    
+    set defaultsuffix { "_mc" }
+    
+    set scriptname bis_matrixcorrelation
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Calculate correlation among time series."
+    set description2 "Calculate correlation between pairs of voxels. Usually input image is a ROI mean image. Can use ROI Mean algorithm to generate such image."
+    set backwardcompatibility ""
+    set authors "isabella.murphy at yale.edu, xilin.shen at yale.edu"
+    
+    set category "Functional Imaging"
+
+    $this InitializeImageToImageAlgorithm
+	
+    $this RenameInput 0 "ROI Mean"
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_matrixcorrelation::Execute {  } {
+    
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+	
+    set dotext       [ $OptionsArray(dotextfile) GetValue ]
+    set textfilename [ $OptionsArray(filename)   GetValue ]
+	set textfilename2 [ $OptionsArray(filename2)   GetValue ]
+    set doraw        [ $OptionsArray(raw)   GetValue ]
+    
+    if { $textfilename != "" } {
+	set extrafilenames $textfilename
+    }
+	if { $textfilename2 != "" } {
+	set extrafilenames2 $textfilename2
+	}
+	set name [ file normalize  $extrafilenames   ]
+	set name2 [ file normalize $extrafilenames2 ]
+    set image_in    [ $this GetInput ]
+
+
+    set crr  [ vtkbisTimeSeriesCorrelation [ pxvtable::vnewobj ] ]
+
+
+    $crr SetInput [ $image_in GetObject ]
+	$crr SetDoText $dotext
+	$crr SetOutputRaw  [ expr $doraw > 0 ]
+	if { $dotext == "1" } {
+		$crr SetFileName $name
+		$crr SetFileName2 $name2
+	}
+    $this SetFilterCallbacks $crr "Time Series Correlation"
+    $crr Update
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $crr GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $crr Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_temporalsmoothimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_matrixcorrelation [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_mediantemporalsmoothimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_mediantemporalsmoothimage.tcl
new file mode 100755
index 0000000..44f70f4
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_mediantemporalsmoothimage.tcl
@@ -0,0 +1,195 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_mediantemporalsmoothimage 1.0
+package require bis_dualimagealgorithm  1.0
+
+
+itcl::class bis_mediantemporalsmoothimage {
+
+    inherit bis_dualimagealgorithm 
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Median Temporal Smooth" }
+	#override parent function
+	public method CheckInputObjects { }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_mediantemporalsmoothimage::Initialize { } {
+
+    PrintDebug "bis_mediantemporalsmoothimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ radius  "Median Temporal Window size" "Radius in frames"  integer 2 { 1 9 }  0 }
+	{ usemask   "Use Mask Image"  "Use Mask Image"  boolean   0  { 0 1  }  40  }         
+    }
+	
+	#for testing functions has nothing to do with this class
+	#set outputs { 
+	#		 { second_output "selected blocks" pxitclimage  ""  10 }   
+	#	}
+
+    set defaultsuffix { "_mtsm" }
+    
+    set scriptname bis_mediantemporalsmoothimage
+    set completionstatus "Done"
+    
+    #
+    #document
+    #
+    
+    set description "Smooth an image with median filter."
+	set description2 "Temporal smoothing using median filter. Length of the kernel is 2*radius+1."
+    set backwardcompatibility ""
+    set authors "isabella.murphy at yale.edu, xilin.shen at yale.edu."
+    set category "Image Processing-4D"
+    
+    $this InitializeDualImageAlgorithm
+	
+	$this RenameInput 0 "Functional Image"
+	#set priority to 102 to make it optional
+    $this RenameInput 1 "Mask Image" 102
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_mediantemporalsmoothimage::Execute {  } {
+
+
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+
+    
+    PrintDebug "bis_mediantemporalsmoothimage::Execute"
+
+    set radius   [ $OptionsArray(radius) GetValue ]
+	#set threshold [ $OptionsArray(threshold) GetValue ]
+    set image_in    [ $this GetInput ]
+
+    
+    set smooth  [ vtkbisMedianTemporalSmoothing [ pxvtable::vnewobj ]  ] 
+    $smooth SetRadius $radius
+    $smooth SetInput [ $image_in GetObject ]
+	#$smooth SetThreshold $threshold
+	set msk [ $OptionsArray(usemask) GetValue ]
+	if { $msk == "1" } {
+	puts stdout "Using Mask ..."
+	$smooth SetImageMask [ [ $this GetInputObject second_image ] GetObject ]
+    } 
+    $this SetFilterCallbacks $smooth "Median Temporal Smoothing Image with radius=$radius"
+    $smooth Update
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $smooth GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+	
+	#set outimage2 [ $OutputsArray(second_output) GetObject ]
+	#$outimage2 ShallowCopyImage [ $smooth GetResult ] 
+	#$outimage2 CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+	#[ $outimage2 GetImageHeader ] AddComment "$comment $Log" 0
+    $smooth Delete
+	
+	#set fname2 [ $outimage2 cget -filename ]
+	#if { $fname2 == "" } {
+	#set f(0) [ $InputsArray(input_image) GetFileName ]
+	#set f(1) [ $InputsArray(second_image) GetFileName ]
+	#for { set i 0 } { $i <= 1 } { incr i } {
+	#set l($i) [ ::bis_common::SplitFileNameGZ $f($i) ]
+	#set f($i) [ file tail [ lindex $l($i) 0 ] ]
+	#set ext($i) [ lindex $l($i) 1 ]
+	#}
+	#set newname [ file join [ file dirname $f(0) ]  "_selectedblocks" ]
+	#$outimage2 configure -filename $newname
+	#}
+
+    return 1
+}
+
+itcl::body bis_mediantemporalsmoothimage::CheckInputObjects { } {
+
+
+    set image_in    [ $this GetInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 2 } {
+	return 0
+    }
+	
+	set msk [ $OptionsArray(usemask) GetValue ]
+	if { $msk == "1" } {
+		set image_in    [ $this GetSecondInput ]
+        set d [ $image_in GetImageSize ]
+        if { $d < 2 } {
+	    return 0
+    	}
+	}
+	
+    return 1
+
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_mediantemporalsmoothimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_mediantemporalsmoothimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_multisubjectfmri.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_multisubjectfmri.tcl
new file mode 100755
index 0000000..479d0df
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_multisubjectfmri.tcl
@@ -0,0 +1,262 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+
+package require bis_algorithm 1.0
+package require pxitclmultisubjectaverage
+package provide bis_multisubjectfmri 1.0
+
+#
+# Operations involving multisubject average for testing ....
+#
+
+itcl::class bis_multisubjectfmri {
+
+    inherit bis_algorithm
+    
+    constructor { } {
+	$this Initialize
+    }
+
+    destructor { $this DeleteMultiSubject }
+    
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "MultiSubject fMRI" }
+
+    public method UpdateContainerWithOutput { } 
+    public method ConfigureOptionsGUICallbacks { } 
+    public method ShowMultiSubject {  args } 
+    protected method DeleteMultiSubject { }
+
+    # variables
+    protected variable multigadget 0
+}
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_multisubjectfmri::Initialize { } {
+
+    PrintDebug "bis_multisubjectfmri::Initialize" 
+
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set inputs { }
+
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ setup "MultiSubject .msb Setup file name" "Setup Name:"  { filename readfile }  "" { "Setup Files" { .msb}} 1 }
+	{ mode "Operation to perform" "Mode"  listofvalues  Average { Average AverageAnat VOI Create4D Create4DVOI }   2}
+	{ resol "Resolution of Output Image" "Resolution" listofvalues 3.0 { "Ref" "1.5" "2.0" "3.0" "4.5" } -11 }
+	{ interp "Interpolation Mode" "Interpolation" listofvalues "Cubic" { "NearestNeighbor" "Linear" "Cubic" } -10 }
+	{ task  "Task Number to perform operation for" "Task Number" integer 1 { 1 40 } 3 }
+	{  guitask  "Current Task Name" "Task Name"  comment  "         " ""  4 }
+	{ guishowmsb  "Show MultiSubject Control" "Show Control"  { boolean } 0 { 0 1 }  5 }
+    }
+
+    set outputs { 
+	{ output_image "Output Image"  pxitclimage  "" 101 }
+	{ second_output "Sigma Image"  pxitclimage  "" 102 }
+	{ third_output "Tscore Image"  pxitclimage  "" 103 }
+    }
+
+
+    set defaultsuffix { "_multisubject" }
+
+    
+    set scriptname bis_multisubjectfmri
+    set completionstatus "Xenios has revisited  this -- looks almost done"
+    #
+    #document
+    #
+    set category "Functional Imaging"
+    set description "Mostly a test class for pxitclmultisubject.tcl based multi subject operations"
+    set description2 ""
+    set backwardcompatibility "Uses pxitclmultisubject.tcl"
+    set authors "xenophon.papademetris.yale.edu"
+
+    $this AddDefaultOptions
+
+
+}
+
+itcl::body bis_multisubjectfmri::DeleteMultiSubject { } {
+
+    if { $multigadget == 0 } {
+	return
+    }
+
+    itcl::delete obj $multigadget
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_multisubjectfmri::ConfigureOptionsGUICallbacks { } {
+
+    eval "$OptionsArray(guishowmsb) SetGUICallbackFunction { $this ShowMultiSubject }"
+}
+
+itcl::body bis_multisubjectfmri::ShowMultiSubject {  args } {
+
+
+    if { $multigadget != 0 } {
+	if { [ $OptionsArray(guishowmsb) GetValue ] ==0 } {
+	    $multigadget HideWindow
+	} else  {
+	$multigadget ShowWindow Results
+	}
+    }
+}
+
+itcl::body bis_multisubjectfmri::UpdateContainerWithOutput { } {
+
+    set img  [ $this GetOutputObject output_image ] 
+
+    PrintDebug "In Update Container With Output $this, $img [ $img GetDescription ]\n"
+    if { $containerobject == 0 } {
+	if { $bis_viewer !=0 } {
+	    $bis_viewer SetImage $img
+	}  elseif { $vtk_viewer !=0 } {
+	    $vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+	} 
+    } else {
+	PrintDebug "Calling Container ($this, $containerobject) SetResultsFromObject" 
+	$containerobject SetResultsFromObject $img $this
+	# Unload result at this point
+	$img Clear
+    }
+}
+
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_multisubjectfmri::Execute {  } {
+
+    set fname [ $OptionsArray(setup) GetValue ]
+    set mode  [ $OptionsArray(mode) GetValue ]
+    set resol [ $OptionsArray(resol) GetValue ]
+    set interp [ $OptionsArray(interp) GetValue ]
+    set task   [ $OptionsArray(task) GetValue ]
+
+    puts stdout "Parameters = $fname, $mode, $resol, $interp, $task"
+    catch { cd [ file dirname [ file normalize $fname ]] }
+    puts stdout "Operating in Directory [ pwd ]"
+
+  
+
+
+    if { $multigadget == 0 } {
+	set vr [ $this GetViewer ]
+	if { $basewidget!=0 } {
+	    set b $basewidget.[pxvtable::vnewobj ]
+	} else {
+	    set b .[pxvtable::vnewobj ]
+	}
+	set  multigadget [ [  pxitclmultisubjectaverage \#auto $vr  ] GetThisPointer ]
+	$multigadget Initialize $b
+	$multigadget ShowWindow Results
+	$multigadget HideWindow
+    }
+
+    if { [ $OptionsArray(guishowmsb) GetValue ] == 1 } {
+	$multigadget ShowWindow Results
+    } else {
+	$multigadget HideWindow
+    }
+    
+    $multigadget SetInterpolationAndResolution $interp $resol
+    update
+    set ok [ $multigadget LoadSetup $fname ]
+    if { $ok ==0 } {
+	set errormessage "Failed to Load Setup $fname"
+	return 0
+    }
+
+
+    puts stderr "Setting New Task [ expr $task -1 ]"
+    set c [ $multigadget SetCurrentTask [ expr $task -1 ] ]
+    $OptionsArray(task) SetValue [ expr [ lindex $c 0 ]  +1 ]
+    $OptionsArray(guitask) SetValue "Using   [ lindex $c 1 ]:[lindex $c 2] (ind=[ expr [ lindex $c 0 ]  +1 ])"
+    $multigadget LoadAll 0
+
+    if { $mode == "Average" } {
+	$multigadget ComputeAverages Functional
+	[ $this GetOutputObject output_image ] ShallowCopy [ $multigadget GetMeanFunctionalOutput ]
+	[ $this GetOutputObject second_output ] ShallowCopy [ $multigadget GetSigmaFunctionalOutput ]
+	[ $this GetOutputObject third_output ] ShallowCopy [ $multigadget GetTscoreFunctionalOutput ]
+    } elseif { $mode == "AverageAnat" } {
+	$multigadget ComputeAverages Images
+	[ $this GetOutputObject output_image ] ShallowCopy [ $multigadget GetMeanAnatomicalOutput ]
+	[ $this GetOutputObject second_output ] ShallowCopy [ $multigadget GetSigmaAnatomicalOutput ]
+    } elseif { $mode == "VOI" } {
+	set img [ $multigadget DoVOIAnalysis "_do_not_save" 0 ]
+	[ $this GetOutputObject output_image ] ShallowCopyImage $img
+	$img Delete
+    } else {
+	if { $mode == "Create4DVOI" } {
+	    $multigadget SetInterpolationAndResolution $interp "Ref"
+	    set imglist [ $multigadget WarpTasksToCommonSpace warp "" 0 ]
+	    set roimeanalg [ [ bis_roimean \#auto ] GetThisPointer ]
+	    $roimeanalg InitializeFromContainer $this
+	    set cimg [ $multigadget  Create4DImageForSingleFrameAndCurrentTask $imglist 0 $roimeanalg ]
+	    itcl::delete object $roimeanalg
+	    $multigadget SetInterpolationAndResolution $interp $resol
+	} else {
+	    set imglist [ $multigadget WarpTasksToCommonSpace warp "" 0 ]
+	    set cimg [ $multigadget  Create4DImageForSingleFrameAndCurrentTask $imglist 0 0 ]
+	}
+	[ $this GetOutputObject output_image ] ShallowCopy $cimg
+	itcl::delete obj $cimg
+	for { set ai 0 } { $ai < [ llength $imglist ] } { incr ai } {
+	    [ lindex $imglist $ai ] Delete
+	}
+    }
+
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_multisubjectfmri.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_multisubjectfmri [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_newreorientimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_newreorientimage.tcl
new file mode 100755
index 0000000..5f99a25
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_newreorientimage.tcl
@@ -0,0 +1,133 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package provide bis_newreorientimage 1.0
+
+#
+# newreorient image
+#
+
+itcl::class bis_newreorientimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "ReOrient Image" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_newreorientimage::Initialize { } {
+
+    PrintDebug "bis_newreorientimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ orientation "orientation of output image eiter axial LPS or axial RAS, coronal LIP or RSA or saggital PSR or ASR" "Orientation"  { listofvalues  } LPS { LPS RAS LIP RSA PSR ASR }  0 }
+    }
+
+    set defaultsuffix { "" }
+    
+    set scriptname bis_newreorientimage
+    set completionstatus "Done -- needs testing"
+    #
+    #document
+    #
+    
+    set description "newreorients an image to a given orientation."
+    set description2 " Output orientation is one of default six including LPS or RAS. The input orientation is detected automatically. This tool does not reslice oblique images, it simply permutes/flips the axis only."
+    set backwardcompatibility ""
+    
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_newreorientimage::Execute {  } {
+
+    PrintDebug "bis_newreorientimage::Execute"
+
+    set out   [ $OptionsArray(orientation) GetValue ]
+    set image_in          [ $InputsArray(input_image) GetObject ]
+    set orientation_in    [ $image_in GetOrientation ]
+
+
+    #vtk object
+    set vtk_image_in [ $image_in GetObject ]
+    set header [ $image_in GetImageHeader ]
+    set outimage [ $OutputsArray(output_image) GetObject ]
+
+    set f [ vtkbisImageReOrient New ]
+    $f SetInput $vtk_image_in
+    $f SetInputImageHeader $header
+    #    $f SetOutputOrientationToLPS
+    $f SetOutputOrientationTo$out
+    $f Update
+
+    # Output orientation etc. is same as input
+    $outimage CopyImageHeader  [ $f GetOutputImageHeader ]
+    $outimage ShallowCopyImage [ $f GetOutput ] 
+    [ $outimage GetImageHeader ] AddComment "[ $this GetCommandLine full ]" 0
+
+    $f Delete
+    
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_newreorientimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_newreorientimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_nonlineardistortioncorrection.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_nonlineardistortioncorrection.tcl
new file mode 100755
index 0000000..9c81ef2
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_nonlineardistortioncorrection.tcl
@@ -0,0 +1,176 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_nonlineardistortioncorrection 1.0
+package require bis_baseintensityregistration 1.0
+package require bis_linearintensityregister 1.0
+
+
+#
+# register image
+#
+
+itcl::class bis_nonlineardistortioncorrection {
+
+    inherit bis_baseintensityregistration
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Distortion Cor" }
+    public method GetExtension { } { return ".grd" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_nonlineardistortioncorrection::Initialize { } {
+
+    PrintDebug "bis_nonlineardistortioncorrection::Initialize" 
+
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ initialmode   "Type of initial registration" "Initial Mode" { listofvalues } rigid { none rigid affine similarity  } 0 }
+	{ spacing       "Control Point Spacing in mm" "Control Point Spacing" { real } 20.0 { 1.0 50.0 } 1 }
+	{ spacingrate   "Rate of increase of Control Point Spacing" "Cont Spacing Rate" { real } 2.0 { 1.1 3.0 } -105 }
+	{ smoothness    "Smoothness factor (using bending energy regularization)" "Smoothness" { real } 0.005 { 0.0 1.0 } 1 }
+	{ dir             "phase encode direction 0=x, 1=y, or 2=z"  "Phase Encode Axis"   int    1      { 0 2       }  2 }
+	{ windowsize    "Size (in control points of the window to use for computing gradients (2.0=full,1.0=accelerated)" "Windowsize" { real } 1.0 { 1.0 2.0 } -150 }
+	{ extralevels   "Number of `fluid' iterations at end of main level " "Extra Levels" { integer } 0 { 0 10 } -106 }
+    }
+    set scriptname bis_nonlineardistortioncorrection
+
+    #
+    #document
+    #
+
+    set category "Registration"
+    set description  "Computes non-linear distortion corrections for echoplanar images."
+    set description2 "This is essentially one-dimensional non-rigid registration. Computes linear registration first, non-linear registration second."
+    set backwardcompatibility "Refactored from pxmat_register.tcl."
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this InitializeBaseIntensityRegistration
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute. reimplemented from DoNMIAll of pxmat_register.tcl
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_nonlineardistortioncorrection::Execute {  } {
+
+
+    $this UpdateOutputFilenames
+
+    PrintDebug "bis_nonlineardistortioncorrection::Execute"
+
+    set nreg [ vtkpxDistortionCorrection New ]
+    set initialmode [ $OptionsArray(initialmode) GetValue ]
+
+    if { $initialmode != "none" } {
+	set lin_alg [bis_linearintensityregister [pxvtable::vnewobj]]
+	$lin_alg InitializeFromContainer 0
+	$lin_alg SetReferenceImage [ $this GetReferenceImage ]
+	$lin_alg SetTransformImage [ $this GetTransformImage ]
+	$lin_alg SetInitialTransformation [ $this GetInitialTransformation ]
+	$lin_alg SetOptionValue mode $initialmode
+	set useweights     [ $OptionsArray(useweightimage) GetValue ]
+	if { $useweights > 0 } {
+	    $lin_alg SetOptionValue useweightimage $useweights
+	    $lin_alg SetInputObject weight_image  [ $this GetInputObject weight_image  ]
+	    if { $useweights > 1 } {
+		$lin_alg SetInputObject weight_image2 [ $this GetInputObject weight_image2 ]
+	    }
+	}
+	$lin_alg Execute
+	$nreg SetInitialTransform [ [ $lin_alg GetOutputTransformation ] GetTransformation ]
+	itcl::delete obj $lin_alg
+    } else {
+	$nreg SetInitialTransform [ [ $this GetInitialTransformation ] GetTransformation ]
+    }
+
+    set dir [ $OptionsArray(dir) GetValue ] 
+    set axis 1
+    if { $dir == "X" } {
+	set axis 0 
+    } elseif { $dir == "Z" } {
+	set axis 2
+    }
+
+    $this SetCommonIntensityRegistrationOptions $nreg
+    $nreg SetLambda [ expr 0.01 * [  $OptionsArray(smoothness) GetValue ]]
+    $nreg SetControlPointSpacing [  $OptionsArray(spacing) GetValue ]
+    $nreg SetControlPointSpacingRate [  $OptionsArray(spacingrate) GetValue ]
+    $nreg SetWindowSize [  $OptionsArray(windowsize) GetValue ]
+    $nreg SetNumberOfExtraLevels [  $OptionsArray(extralevels) GetValue ]
+    $nreg SetUseJacobian 0
+    $nreg SetUseSignalLossCorrection 0
+    $nreg SetPhaseEncodeAxis $axis
+    $this SetFilterCallbacks $nreg "Non-Linearly Registering Image"
+
+    set current_registration $nreg
+    $nreg Run
+    set current_registration 0
+    [ $this GetOutputTransformation ] CopyTransformation [ $nreg GetTransformation ]
+
+    $nreg Delete
+    $this CreateWarpedImage
+
+
+    return 1
+}
+
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_nonlineardistortioncorrection.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_nonlineardistortioncorrection [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_nonlinearintensityregister.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_nonlinearintensityregister.tcl
new file mode 100755
index 0000000..ae7dc59
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_nonlinearintensityregister.tcl
@@ -0,0 +1,195 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_nonlinearintensityregister 1.0
+package require bis_baseintensityregistration 1.0
+package require bis_linearintensityregister 1.0
+
+
+#
+# register image
+#
+
+itcl::class bis_nonlinearintensityregister {
+
+    inherit bis_baseintensityregistration
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "NonLinear Reg" }
+    public method GetExtension { } { return ".grd" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_nonlinearintensityregister::Initialize { } {
+
+    PrintDebug "bis_nonlinearintensityregister::Initialize" 
+
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ initialmode   "Type of initial registration" "Initial Mode" { listofvalues } affine { none rigid affine similarity  } 0 }
+	{ spacing       "Control Point Spacing in mm" "Control Point Spacing" { real } 15.0 { 1.0 50.0 } 1 }
+	{ spacingrate   "Rate of increase of Control Point Spacing" "Cont Spacing Rate" { real } 2.0 { 1.1 3.0 } -105 }
+	{ smoothness    "Smoothness factor (using bending energy regularization)" "Smoothness" { real } 0.001 { 0.0 1.0 } 2 }
+	{ windowsize    "Size (in control points of the window to use for computing gradients (2.0=full,1.0=accelerated)" "Windowsize" { real } 1.0 { 1.0 2.0 } -150 }
+	{ extralevels   "Number of `fluid' iterations at end of main level " "Extra Levels" { integer } 0 { 0 10 } -106 }
+	{ useinitial "Use Initial Transformation" "Use Initial Xform"  boolean   0     { 0 1 } 25 }
+	{ directstorage "GPU Direct Storage  " "GPU Direct Storage Mode" boolean 1 { 0 1 }  -502 }
+    }
+    set scriptname bis_nonlinearintensityregister
+
+    #
+    #document
+    #
+
+    set category "Registration"
+    set description "computes a linear  intensity based registrations."
+    set description2 ""
+    set backwardcompatibility "Refactored from pxmat_register.tcl."
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this InitializeBaseIntensityRegistration
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute. reimplemented from DoNMIAll of pxmat_register.tcl
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_nonlinearintensityregister::Execute {  } {
+
+
+    PrintDebug "bis_nonlinearintensityregister::Execute"
+    set usegpu      [ $OptionsArray(usegpu) GetValue ]
+    set threadmode [  $OptionsArray(threadmode) GetValue ]
+    set directstorage [ $OptionsArray(directstorage) GetValue ]
+
+    set nreg 0
+    if { $usegpu > 0 } {
+	catch { 
+	    set nreg  [ vtkbisCUDANonLinearRegistration New ]; 
+	    $nreg SetThreadMode $threadmode
+	    $nreg SetDirectStorageMode $directstorage
+	}
+    }
+
+    if { $nreg == 0 } {
+	set nreg [ vtkpxNonLinearRegistration [ pxvtable::vnewobj ]]
+    }
+
+    puts stderr "Using class [ $nreg GetClassName ]"
+
+    set initialmode [ $OptionsArray(initialmode) GetValue ]
+
+    if { $initialmode != "none" } {
+	set lin_alg [bis_linearintensityregister [pxvtable::vnewobj]]
+	$lin_alg InitializeFromContainer 0
+	$lin_alg SetReferenceImage [ $this GetReferenceImage ]
+	$lin_alg SetTransformImage [ $this GetTransformImage ]
+	if { [ $OptionsArray(useinitial) GetValue ] !=0 } {
+	    $lin_alg SetOptionValue useinitial 1
+	    $lin_alg SetInitialTransformation  [ $this GetInitialTransformation ] 
+	}
+	$lin_alg SetOptionValue mode $initialmode
+	$lin_alg SetOptionValue threadmode $threadmode
+	$lin_alg SetOptionValue usegpu $usegpu
+	set useweights     [ $OptionsArray(useweightimage) GetValue ]
+	if { $useweights > 0 } {
+	    $lin_alg SetOptionValue useweightimage $useweights
+	    $lin_alg SetInputObject weight_image  [ $this GetInputObject weight_image  ]
+	    if { $useweights > 1 } {
+		$lin_alg SetInputObject weight_image2 [ $this GetInputObject weight_image2 ]
+	    }
+	}
+	$lin_alg Execute
+	$nreg SetInitialTransform [ [ $lin_alg GetOutputTransformation ] GetTransformation ]
+	itcl::delete obj $lin_alg
+    } else {
+	if { [ $OptionsArray(useinitial) GetValue ] !=0 } {
+	    $nreg SetInitialTransform [ [ $this GetInitialTransformation ] GetTransformation ]
+	}
+    }
+
+
+    $this SetCommonIntensityRegistrationOptions $nreg
+
+    $nreg SetLambda [ expr 0.01 * [  $OptionsArray(smoothness) GetValue ]]
+    $nreg SetControlPointSpacing [  $OptionsArray(spacing) GetValue ]
+    $nreg SetControlPointSpacingRate [  $OptionsArray(spacingrate) GetValue ]
+    $nreg SetWindowSize [  $OptionsArray(windowsize) GetValue ]
+    $nreg SetNumberOfExtraLevels [  $OptionsArray(extralevels) GetValue ]
+
+    $this SetFilterCallbacks $nreg "Non-Linearly Registering Image"
+
+    set current_registration $nreg
+
+    set tstart [ clock clicks -milliseconds ]
+    $nreg Run
+    set tend [ clock clicks -milliseconds ]
+
+    puts stdout "++++++        End of non rigid registration [ expr $tend - $tstart ] ms\n"
+    set current_registration 0
+    [ $this GetOutputTransformation ] CopyTransformation [ $nreg GetTransformation ]
+
+    puts stdout "Deleting\n"
+    $nreg Delete
+    $this CreateWarpedImage
+
+    return 1
+}
+
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_nonlinearintensityregister.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_nonlinearintensityregister [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_nonlinearpointregister.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_nonlinearpointregister.tcl
new file mode 100755
index 0000000..e32b8b5
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_nonlinearpointregister.tcl
@@ -0,0 +1,178 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_basepointbasedregistration 1.0
+package require bis_linearpointregister 1.0
+package provide bis_nonlinearpointregister 1.0
+
+#
+# register image
+#
+
+
+
+itcl::class bis_nonlinearpointregister {
+
+    inherit bis_basepointbasedregistration
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "NonLinear RPM" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+
+
+itcl::body bis_nonlinearpointregister::Initialize { } {
+
+    PrintDebug "bis_nonlinearpointregister::Initialize" 
+
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ smoothstart   "Starting Smoothness Value"                                      "smoothstart"    real 5.0  { 0.0 10.0}  20 }
+	{ smoothend     "Final Smoothness Value"                                        "smoothend"      real 1.0  { 0.0 10.0}  21 }
+	{ cpsstart      "Starting Control Point Spacing"                                         "cpsstart"       real 30.0     { 0.0 100}  22 }
+	{ cpsend        "Final Control Point Spacing"                                           "cpsend"         real 15.0     { 0.0 100.0} 23 }
+	{ linearmode        "Type of linear registration" "LinearMode"  { listofvalues } rigid { rigid affine similarity none } 24 }
+	{ linearnumpoints   "number of points for linear part (0=default, figure out from nonlinear)" "Linear Numpoints"          int  0 { 0 10000 }    -100 }
+	{ lineartstart      "linear start temparature (0=default, figure out from nonlinear)"         "Linear Init Temperature"   real 0  { 0.0 10.0 }  -101}
+	{ lineartstop        "end temparature (0=default, figure out from nonlinear)"                 "Linear Stop Temperature"    real 0  { 0.0 10.0}   -102}
+
+    }
+    set scriptname bis_nonlinearpointregister
+
+    #
+    #document
+    #
+
+    set category "Registration"
+    set description "computes a linear  point-based registrations."
+    set description2 ""
+    set backwardcompatibility "Refactored from pxmat_pointregister.tcl"
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this InitializeBasePointBasedRegistration
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute. reimplemented from DoNMIAll of pxmat_register.tcl
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_nonlinearpointregister::Execute {  } {
+
+    set rpm [ vtkpxBSplineRPMRegistration  [ pxvtable::vnewobj ]]
+    $this SetCommonPointBasedRegistrationOptions $rpm
+
+    $rpm SetInitialControlPointSpacing  [ $OptionsArray(cpsstart) GetValue ]
+    $rpm SetFinalControlPointSpacing    [ $OptionsArray(cpsend) GetValue ]
+    $rpm SetInitialSmoothnessFactor     [ $OptionsArray(smoothstart) GetValue ]
+    $rpm SetFinalSmoothnessFactor       [ $OptionsArray(smoothend) GetValue ]
+
+    set currentregistration 0
+    set linearmode [ $OptionsArray(linearmode) GetValue ]
+    if { $linearmode != "none" } {
+
+	set nfactor 0.5
+	set tfactor 3.0
+	
+	if { [ $OptionsArray(linearnumpoints) GetValue ] == 0 } {
+	    $OptionsArray(linearnumpoints) SetValue [ expr int($nfactor * [ $OptionsArray(numpoints) GetValue ]) ]
+	}
+	if { [ $OptionsArray(lineartstart) GetValue ] == 0 } {
+	    $OptionsArray(lineartstart)    SetValue [ expr $tfactor * [ $OptionsArray(tstart) GetValue ] ]
+	}
+	if { [ $OptionsArray(lineartstop) GetValue ] == 0 } {
+	    $OptionsArray(lineartstop) SetValue [ expr $nfactor * [ $OptionsArray(tstop) GetValue ] ]
+	}
+
+	set lin_alg [ [bis_linearpointregister [pxvtable::vnewobj]] GetThisPointer ]
+	$lin_alg InitializeFromContainer $this
+	$lin_alg SetReferenceSurface [ $this GetReferenceSurface ]
+	$lin_alg SetTransformSurface [ $this GetTransformSurface ]
+	$lin_alg SetInitialTransformation [ $this GetInitialTransformation ]
+	$lin_alg SetOptionValue useinitial [ $OptionsArray(useinitial) GetValue ]
+	$lin_alg SetOptionValue mode $linearmode
+	$lin_alg SetOptionValue tstart [ $OptionsArray(lineartstart) GetValue ]
+	$lin_alg SetOptionValue tstop [ $OptionsArray(lineartstop) GetValue ]
+	$lin_alg SetOptionValue numpoints [ $OptionsArray(linearnumpoints) GetValue ]
+	#	set currentregistration $lin_alg
+	$lin_alg Execute
+	$rpm SetInitialTransform [ [ $lin_alg GetOutputTransformation ] GetTransformation ]
+	itcl::delete obj $lin_alg
+    } elseif { [ $OptionsArray(useinitial) GetValue ] !=0 } {
+	set in_xform     [ [ $this GetInitialTransformation ] GetObject ]
+	$rpm SetInitialTransform   $in_xform
+    }
+
+    set surface1    [ $this GetReferenceSurface  ]
+    set surface2    [ $this GetTransformSurface ]
+    
+    $this SetFilterCallbacks $rpm "Non-Linear RPM Registration"
+    set currentregistration $rpm
+    $rpm SetSource [ $surface1 GetSurface ]
+    $rpm SetTarget [ $surface2 GetSurface ]
+    $rpm Run
+    set currentregistration 0
+    [ $this GetOutputTransformation ] CopyTransformation [ $rpm GetCurrentTransformation ]
+    $rpm Delete
+
+    $this CreateWarpedSurface
+
+    return 1
+}
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_nonlinearpointregister.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_nonlinearpointregister [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_nonlinearsmoothimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_nonlinearsmoothimage.tcl
new file mode 100755
index 0000000..e9e55aa
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_nonlinearsmoothimage.tcl
@@ -0,0 +1,172 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_nonlinearsmoothimage 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+#
+# smooth image
+#
+
+itcl::class bis_nonlinearsmoothimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Anisotropic Diffusion" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_nonlinearsmoothimage::Initialize { } {
+
+    PrintDebug "bis_nonlinearsmoothimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ threshold "Threshold for  Anisotropic Diffusion" "Threshold"   real   30 { 1 20000 }  1 }
+	{ factor    "Lambda factor  Regular Anisotropic Diffusion" "Lambda"   real   1.0 { 0.2 10.0 }  2 }
+	{ iterations "Number of Iterations" "Iterations"   int  4 { 1 20  }  3 }
+	{ mode  "Use intensity difference or gradient difference as constraint" "Mode"  { listofvalues radiobuttons } intensity { intensity gradient }  4 }
+	{ dimension  "2 or 3 to to do smoothin in 2D or 3D" "Dimensionality"  { listofvalues radiobuttons }    3 { 2  3 } 6 }
+
+    }
+
+#	{ keyframe  "Use the difference of the firstframe (in case of 4D Images) to control smoothing, instead of doing each frame differently (for 3D Only)" "Keyframe"  { listofvalues radiobuttons } On { On Off }  5 }
+
+    set defaultsuffix { "_nlsm" }
+    
+    set scriptname bis_nonlinearsmoothimage
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Smoothes an image using anisotropic diffusion filtering"
+    set description2 " "
+    set backwardcompatibility "New"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_nonlinearsmoothimage::Execute {  } {
+
+    PrintDebug "bis_nonlinearsmoothimage::Execute"
+
+    set threshold   [ $OptionsArray(threshold) GetValue ]
+    set factor      [ $OptionsArray(factor) GetValue ]
+    set iterations  [ $OptionsArray(iterations) GetValue ]
+    set mode        [ $OptionsArray(mode) GetValue ]
+    #    set keyframe    [ $OptionsArray(keyframe) GetValue ]
+    set keyframe 0
+    set dimension   [ $OptionsArray(dimension)    GetValue ]
+
+    if { $keyframe == "On" && $dimension == 2 } {
+	set dimension 2
+	$OptionsArray(dimensions) SetValue 3
+    }
+    
+    set image_in    [ $InputsArray(input_image) GetObject ]
+
+    if { $dimension == 2 } {
+	set smooth  [ vtkImageAnisotropicDiffusion2D [ pxvtable::vnewobj ]  ]
+    } else {
+	set smooth  [ vtkImageAnisotropicDiffusion3D [ pxvtable::vnewobj ]  ]
+    }
+    #else { 
+    #	set smooth  [ vtkpxImageAnisotropicDiffusion3D [ pxvtable::vnewobj ]  ]
+    #    }
+
+
+    $smooth SetDiffusionFactor $factor
+    if { $mode == "intensity" } {
+	$smooth SetDiffusionThreshold $threshold
+    } else {
+	$smooth SetGradientMagnitudeThreshold $threshold
+    }
+
+    $smooth SetInput [ $image_in GetImage ]
+    $smooth SetNumberOfIterations  $iterations
+    SetFilterCallbacks $smooth "[ $smooth GetClassName ] Diffusing Image"
+    $smooth Update
+
+    set image_out [ $smooth GetOutput ]
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out 
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format "BIS::pxmat_nonlinearsmoothimage.tcl threshold=%.2f factor= %.2f iterations=%d mode=%s  dimension=%d " \
+		      $threshold $factor $iterations $mode  $dimension ]
+
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $smooth Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_nonlinearsmoothimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_nonlinearsmoothimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_object.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_object.tcl
new file mode 100644
index 0000000..b910bd7
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_object.tcl
@@ -0,0 +1,1159 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_object 1.0
+
+#
+# bis_object.tcl
+# 
+
+package require pxitclobject 1.0
+package require pxitclimage
+package require pxitcltransform
+package require pxitclsurface
+package require pxitclmesh
+package require pxitcllandmarks
+package require pxitclelectrodemultigrid
+package require bis_common
+
+itcl::class bis_object {
+
+#
+#protected
+#
+    protected variable name "some object"
+    protected variable description "this is some object"
+    protected variable cmdlineoption ""
+
+    # this is a list of allowed object types
+    protected common objecttypelist { pxitclimage pxitcltransform pxitclsurface pxitcllandmarks pxitclelectrodemultigrid pxitclmesh }
+
+    protected variable objecttype ""
+    protected variable multipleobjectflag 0
+
+    protected variable internalobject    0
+
+    # For multiple inputs this contains objects 2..N
+    protected variable objectlist  ""
+
+    protected variable objectgui 0
+    protected variable objectguimode "normal"
+
+    protected variable updatecallback ""
+    protected variable priority 0
+    protected variable update_gui_internally 0
+    protected variable default_filename ""
+    protected variable guimode ""
+    protected variable xmlpointer 0
+    protected variable algparent 0
+    protected common guiparam
+#
+#public
+#
+    # Constructor and Destructor
+    constructor { } {      set guiparam($this,treelistbox) 0 }
+    destructor { $this CleanAll }
+
+    public method GetThisPointer { } { return $this }
+    protected method CleanAll { }
+
+    # Name of Object e.g. Input Image
+    public method SetName        { a } { set name $a }
+    public method GetName        {   } { return $name}
+
+    # Description of what the object does
+    public method SetDescription { a } { set description $a }
+    public method GetDescription {   } { return $description }
+
+    # Priority of  the object for GUI Generation
+    public method SetPriority { a } { set priority $a }
+    public method GetPriority {   } { return $priority }
+
+    # Type of Object e.g. pxitclimage
+    public method SetObjectType        { a } 
+    public method GetObjectType        {   } { 	return $objecttype     }
+
+    public method SetMultipleObjectFlag  { a }  { if { $a == "multiple" } { set multipleobjectflag 1 } else { set multipleobjectflag 0 }}
+    public method GetMultipleObjectFlag  {  }   { return  $multipleobjectflag }
+
+    public method CreateVTKObject      {  mode  }
+
+    # Filename of Object 
+    public method SetFileName    { a { force 0 } } 
+    public method GetFileName    {   } 
+    public method IsFileNameTheDefault { }
+
+    # This is for multiobject stuff ....
+    public method AddFileNames { fnamelist }
+    public method GetFileNameList {  }
+
+
+    # Command Line Option for Object 
+    public method SetCommandSwitch    { a } { set cmdlineoption $a }
+    public method GetCommandSwitch    {   } { return $cmdlineoption }
+    public method GetCmdLineString {} { 
+	return [ list ${cmdlineoption}.arg $default_filename "filename for $description" ] 	
+    }
+    public proc   GetSlicerListXMLDescription { dlist { input 1 } { index 1 } { channelindex -1 } }
+    public method GetLONIXMLDescription { { input 1 }  }
+    public method  GetJSONString     {  dlist { input 1 } { index 1 } { channelindex -1 } }
+
+
+    # Return a pointer to the object (pxitcl....) 
+    public method GetObject      {   } { 		return $internalobject         }
+    public method GetObjectList      {   } { 		return $objectlist     }
+    public method GetAllObjects    {   } {  return [ concat $internalobject $objectlist ]  }
+
+
+    # Use this to link to parent
+    public method SetUpdateCallback { c } {  set updatecallback $c }
+
+    # Return a pointer to the object GUI If it exists
+    public method GetObjectGUI { } { return $objectgui }
+    public method CreateObjectGUI { base { enablesave 1 } { desc "" } { parent 0 } }
+    protected method CreateMultipleObjectGUI { base { enablesave 1 } { desc "" } { parent 0 } }
+
+    public method CreateDataTreeObjectGUI { base { enablegrab 0 } { enablestore 0 } { parent 0 } { datatree 0 }}
+    protected method CreateMultipleDataTreeObjectGUI { base { enablegrab 0 } { enablestore 0 } { parent 0 } { datatree 0 }}
+
+    public method GrabTreeSelection { datatree { refspace 0 } }
+    public method ClearTreeObject { { mode current } }
+    public method StoreInTree { datatree }
+    public method GUICallback { }
+    public method UpdateInternalGUI { }
+    public method UpdateObjectListFromGUI { }
+
+    # Returns the vtkObject e.g. vtkImageData encapsulated in the the itcl object
+    public method GetVTKObject   { }
+
+    # XML Pointer -- for interfacing with Datatree cleanly
+    public method SetXMLPointer  { a } { set xmlpointer $a  }
+    public method GetXMLPointer  {   } { return $xmlpointer }
+
+
+    # GUI Callbacks Internal
+    public method InfoObject {  }
+    public method DisplayImage { image viewer }
+    public method DisplayObject { sur viewer }
+    public method GUIQuickHelp { image args }
+
+
+    # Load and Save Object (args means a list  of parameters, possibly empty)
+    # If I call this as LoadObject a.hdr 2 --> args  = { a.hdr 2 }
+    # argument 0 = filename (if absent it will popup a dialog to get it )
+    # argument 1 = description (for Get FileName Dialog 
+    # argument 2 = parent object in GUI (for 
+    # LoadObject "a.hdr" "Input FileName" $someviewer
+    # For command line usage use one argument -- the filename
+    public method LoadObject { args } 
+    public method SaveObject { args } 
+
+    public method LoadObjectList { index args } 
+    public method SaveObjectList { index args } 
+
+
+
+    public method SetValueAsList { input  } 
+    public method SetValue       { i_name i_desc i_type i_fname {  i_priority 0 } } {
+	SetName         $i_name
+	SetDescription  $i_desc
+	SetObjectType   [ lindex $i_type 0 ]
+	if { [ llength $i_type ] > 1 } {
+	    SetMultipleObjectFlag [ lindex $i_type 1 ]
+	}
+	set default_filename $i_fname 
+	SetPriority     $i_priority
+    }
+
+    public method PrintSelf     { } {
+	puts stdout "name =         [$this GetName]"
+	puts stdout "description =  [$this GetDescription]"
+	puts stdout "objecttype  =  [$this GetObjectType]"
+	puts stdout "filename    =  [$this GetFileName]"
+	puts stdout "default_filename    =  $default_filename "
+	puts stdout "object      =  [$this GetObject]"
+	puts stdout "objectgui   =  [$this GetObjectGUI]"
+	puts stdout "priority    =  [$this GetPriority]"
+	puts stdout "cmdlineoption    =  [$this GetCommandSwitch ]"
+	puts stdout "\n"
+    }
+}
+
+itcl::body bis_object::GetJSONString     {  dlist { input 1 } { index 1 } { channelindex -1 } } {
+
+    set name [ lindex $dlist 0 ]
+    set desc [ lindex $dlist 1 ]
+    
+    if { [ llength $dlist ] > 4 } {
+	set priority  [ lindex $dlist 4 ] 
+    } else {
+	set priority 0
+    }
+    set objecttype [ lindex [ lindex $dlist 2 ] 0 ]
+    
+    set cmd "inp"
+    if { $input == 0 } {
+	set cmd "out"
+    }
+    if { $index > 1 } {
+	append cmd "$index"
+    }
+    
+    set txt "\t\t\"$cmd\": \{\n"
+    append txt "\t\t\t\"name\": [ ::bis_common::CleanString $name],\n"
+    append txt "\t\t\t\"description\": [ ::bis_common::CleanString $desc],\n"
+    append txt "\t\t\t\"objecttype\": [ ::bis_common::CleanString $objecttype],\n"
+    append txt "\t\t\t\"priority\": [ ::bis_common::CleanString $priority]\n"
+    append txt "\t\t\}"
+    return $txt
+}
+
+# -------------------------------------------------------------------------------------------------
+itcl::body bis_object::GetSlicerListXMLDescription { dlist { input 1 } { index 1 } { channelindex -1 } } {
+
+    set name [ lindex $dlist 0 ]
+    set desc [ lindex $dlist 1 ]
+
+    #    puts stderr "Adding $name, index=$index, channel=$channelindex"
+    if { [ llength $dlist ] > 4 } {
+	set optional [ expr [ lindex $dlist 4 ] >= 100 ]
+    } else {
+	set optional 0
+    }
+    set objecttype [ lindex [ lindex $dlist 2 ] 0 ]
+
+    if {$objecttype == "pxitclimage" } {
+	set line "<image fileExtensions=\".nii.gz,.hdr\">\n"
+    } elseif { $objecttype=="pxitcllandmarks" || $objecttype=="pxitclsurface"}  {
+	set line "<geometry type=\"model\" fileExtensions=\".vtk,.vtp\">\n"
+    } elseif { $objecttype=="pxitcllandmarks" || $objecttype=="pxitclmesh"}  {
+	set line "<geometry type=\"model\" fileExtensions=\".ugrid,.ugridx\">\n"
+    } elseif { $objecttype=="pxitcltransform" } {
+	set line "<file fileExtensions=\".matr,.grd,.vtk\">\n"
+    } else {
+	set line "<file fileExtensions=\".mgrid\">\n"
+    }
+    
+    set cmd "inp"
+    if { $input == 0 } {
+	set cmd "out"
+    }
+    if { $index > 1 } {
+	append cmd "$index"
+    }
+
+    if { $channelindex >=0 } {
+	set s [ expr $channelindex + 1 ]
+    } else {
+	set s ""
+    }
+
+    append line "\t<label>$name$s</label>\n"
+    append line "\t<description>$desc$s</description>\n"
+    if { $channelindex >=0 } {
+	append line "\t<index>$channelindex</index>\n"	
+    } else {
+	append line "\t<longflag>--$cmd</longflag>\n"
+    }
+    if {  $optional > 0 } {
+	append line "\t<default>\"\"</default>\n"
+    }
+    
+    if { $input > 0 } {
+	append line "\t<channel>input</channel>\n"
+    } else {
+	append line "\t<channel>output</channel>\n"
+    }
+    
+    if {$objecttype == "pxitclimage" } {
+	append line "</image>\n"
+    } elseif { $objecttype=="pxitcllandmarks" || $objecttype=="pxitclsurface" || $objecttype=="pxitclmesh"}  {
+	append line "</geometry>\n"
+    } else {
+	append line "</file>\n"
+    }
+    return $line
+}
+
+
+
+# -------------------------------------------------------------------------------------------------
+itcl::body bis_object::GetLONIXMLDescription { { input 1 } } {
+    
+    set optional  0
+    if { $priority >= 100  } {
+	set optional 1
+    }
+
+    if { $input > 0 } {
+	set line "\t\t\t<input name=\"$name\" "
+    } else {
+	set line "\t\t\t<output name=\"$name\" "
+    }
+    
+    append line  "description=\"$description\" "
+
+    if { $optional == 0 } {
+	append line  "required=\"true\" "
+    } else {
+	append line  "required=\"false\" "
+    }
+    append line  "switchedSpaced=\"true\" "
+    append line  "switch=\"-[$this GetCommandSwitch ]\">\n"
+    append line "\t\t\t\t<format type=\"File\" cardinality=\"1\">\n"
+    append line "\t\t\t\t\t<fileTypes>\n"
+
+    switch $objecttype {
+	pxitclimage {
+	    append line "\t\t\t\t\t\t<filetype name=\"NIFTI file\" extension=\"nii.gz\" description=\"NIFTI File Format Compressed\"/>\n"
+	    append line "\t\t\t\t\t\t<filetype name=\"NIFTI file\" extension=\"nii\" description=\"NIFTI File Format\"/>\n"
+	    if { $input == 1 } {
+		append line "\t\t\t\t\t\t<filetype name=\"Analyze file format\" extension=\"hdr\" description=\"Analyze File Format\">" 
+		append line "<need>img</need></filetype>\n"
+	    } else {
+		append line "\t\t\t\t\t\t<filetype name=\"Analyze file format\" extension=\"hdr\" description=\"Analyze File Format\"/>\n" 
+	    }
+	}
+	pxitcltransform {
+	    append line "\t\t\t\t\t\t<filetype name=\"BioImage Suite matrix file\" extension=\"matr\" description=\"BioImage Suite Matrix File\"/>\n"
+	    append line "\t\t\t\t\t\t<filetype name=\"BioImage Suite non-linear transform file\" extension=\"grd\" description=\"BioImage Non-linear grid transform file\"/>\n"
+	    append line "\t\t\t\t\t\t<filetype name=\"BioImage Suite non-linear transform file\" extension=\"vtk\" description=\"BioImage Non-linear grid transform file as image\"/>\n"
+	}
+	pxitclsurface {
+	    append line "\t\t\t\t\t\t<filetype name=\"VTK Surface file\" extension=\".vtk\" description=\"VTK Surface File\"/>\n"
+	    append line "\t\t\t\t\t\t<filetype name=\"VTK Surface file\" extension=\".vtp\" description=\"VTK Surface File\"/>\n"
+	}
+	pxitclmesh {
+	    append line "\t\t\t\t\t\t<filetype name=\"VTK Mesh file\" extension=\".ugrid\" description=\"VTK Mesh File\"/>\n"
+	    append line "\t\t\t\t\t\t<filetype name=\"VTK Mesh file\" extension=\".ugridx\" description=\"VTK Mesh File\"/>\n"
+	}
+	pxitcllandmarks {
+	    append line "\t\t\t\t\t\t<filetype name=\"BioImage Surface landmarks file\" extension=\".land\" description=\"BioImage Suite Landmarks File\"/>\n"
+	    append line "\t\t\t\t\t\t<filetype name=\"VTK Surface file\" extension=\".vtk\" description=\"VTK Surface File\"/>\n"
+	    append line "\t\t\t\t\t\t<filetype name=\"VTK Surface file\" extension=\".vtp\" description=\"VTK Surface File\"/>\n"
+	}
+	pxitclelectrodemultigrid {
+	    append line "\t\t\t\t\t\t<filetype name=\"BioImage Surface electrode file\" extension=\".mgrid\" description=\"BioImage Suite Electrode File\"/>\n"
+	}
+    }
+
+    append line "\t\t\t\t\t</fileTypes>\n"
+    append line "\t\t\t\t</format>\n"
+    if { $input > 0 } {
+	append line "\t\t\t</input>\n"
+    } else {
+	append line "\t\t\t</output>\n"
+    }
+    return $line
+}
+
+# ------------------------------------------------------------------------------------
+
+itcl::body bis_object::CleanAll    {   } {
+
+    foreach obj $objectlist {
+	itcl::delete obj $obj 
+    }
+
+    catch { itcl::delete obj $objectgui }
+    catch { itcl::delete obj $internalobject }
+}
+
+#------------------------------------------
+#Set object type and allocate a new one
+#------------------------------------------
+
+itcl::body bis_object::SetValueAsList    { input  } {
+
+    if { [ llength $input ] < 4 } {
+	return 0
+    }
+
+    if { [ llength $input ] == 4 } {
+	SetValue [lindex $input 0] [lindex $input 1] [lindex $input 2] [lindex $input 3]
+	return 4
+    }
+
+    SetValue [lindex $input 0] [lindex $input 1] [lindex $input 2] [lindex $input 3]  [ lindex $input 4 ]
+    return 5
+}
+
+
+itcl::body bis_object::SetObjectType { objtype } {
+
+    set index [ lsearch -exact $objecttypelist $objtype ]
+    if { $index == -1 } {
+	return 0
+    }
+
+   # eval "set object [ [ $objecttype \#new ] GetThisPointer ]"
+
+    set  objecttype $objtype
+}
+
+itcl::body bis_object::CreateVTKObject { mode  } {
+
+    if { $internalobject !=0 } {
+	#puts stderr "--------------------------------  Already created  $this $name \n"
+	return 1
+    } 
+
+
+    switch $objecttype {
+	pxitclimage {
+	    set internalobject [ [ pxitclimage \#auto ] GetThisPointer ]
+	}
+	pxitcltransform {
+	    set internalobject [ [ pxitcltransform \#auto ] GetThisPointer ]
+	}
+	pxitclsurface {
+	    set internalobject [ [ pxitclsurface \#auto ] GetThisPointer ]
+	}
+	pxitclmesh {
+	    set internalobject [ [ pxitclmesh \#auto ] GetThisPointer ]
+	}
+	pxitcllandmarks {
+	    set internalobject [ [ pxitcllandmarks \#auto ] GetThisPointer ]
+	}
+	pxitclelectrodemultigrid {
+	    set internalobject [ [ pxitclelectrodemultigrid \#auto ] GetThisPointer ]
+	}
+	default { 
+	    puts stderr "Specifid type $objecttype is not among pxitcl..."
+	    return 0
+	}
+    }
+
+    set guimode $mode
+    $this SetFileName $default_filename 1
+
+    return 1
+}
+
+#------------------------------------------
+
+itcl::body bis_object::IsFileNameTheDefault { } {
+
+    if { $internalobject == 0 } {
+	return 1
+    }
+
+    if {  $default_filename == [ $this GetFileName ]  } {
+	return 1
+    }
+
+    return 0
+}
+
+#------------------------------------------
+# Return a pointer to the VTK object.essentially same as GetObject
+#------------------------------------------
+itcl::body bis_object::GetVTKObject {  } {
+
+    return [ $internalobject GetObject ]
+}
+
+# --------------------------------------------------------------------------------------------------------
+
+itcl::body bis_object::CreateObjectGUI { base { enablesave 1 } { desc "" } { parent 0 } } {
+    
+    if { $internalobject == 0 } {
+	return 0
+    }
+
+    if { $multipleobjectflag > 0 } {
+	return [ $this CreateMultipleObjectGUI $base $enablesave $desc $parent ]
+    }
+
+    set algparent  $parent
+    switch $objecttype { 
+	pxitclimage {
+	    set objectgui [ [ pxitclimageGUI \#auto ] GetThisPointer ]
+	}
+	pxitcltransform {
+	    set objectgui [ [ pxitcltransformGUI \#auto ] GetThisPointer ]
+	}
+	pxitclsurface {
+	    set objectgui [ [ pxitclsurfaceGUI \#auto ] GetThisPointer ]
+	}
+	pxitclmesh {
+	    set objectgui [ [ pxitclmeshGUI \#auto ] GetThisPointer ]
+	}
+	pxitcllandmarks {
+	    set objectgui [ [ pxitcllandmarksGUI \#auto ] GetThisPointer ]
+	}
+	pxitclelectrodemultigrid {
+	    set objectgui [ [ pxitclelectrodemultigridGUI \#auto ] GetThisPointer ]
+	}
+	default { 
+	    puts stderr "Specifid type $objecttype is not among pxitcl..."
+	    set objectgui 0
+	}
+    }
+
+    if { $desc == "" } {
+	$objectgui configure -description $description
+    } else {
+	$objectgui configure -description $desc
+    }
+
+    $objectgui InitializeLite $base 2
+    if { $enablesave == 0 } {
+	set but [ $objectgui cget -savebutton ]; pack forget $but
+	set but [ $objectgui cget -clearbutton ]; pack forget $but
+    }
+    
+    $objectgui SetObject $internalobject
+    $objectgui Update
+    $objectgui configure -callback "$this GUICallback"
+
+    if { $parent == 0 } {
+	return
+    }
+
+    if { $objecttype == "pxitclimage" } {
+	set viewer [ $parent GetViewer ]
+	if { $viewer !=0 } {
+	    $objectgui AddFunction "$this DisplayImage" "Display" "$viewer"
+	}
+    } elseif { $objecttype != "pxitcltransform" } {
+	set viewer [ $parent GetBisViewer ]
+#	puts stderr "Viewer =$viewer, parent=$parent [ $parent info class ]"
+	$objectgui AddFunction "$this DisplayObject" "Display" "$viewer"
+    }
+
+    $objectgui AddFunction "$this GUIQuickHelp" "?" ""
+
+    
+
+}
+# --------------------------------------------------------------------------------------------------------
+itcl::body bis_object::LoadObject { args } { 	
+    set ok [ $internalobject Load $args]     
+    return $ok
+}
+
+itcl::body bis_object::SaveObject { args } { 
+    return [ $internalobject Save $args]         
+}
+
+# -------------------------------------------------------------------------
+
+itcl::body bis_object::LoadObjectList { index args } { 	
+    if { $index >=0 && $index < [ llength $objectlist ] } {
+	set obj [ lindex $objectlist $index ]
+	return [ $obj Load $args]     
+    }
+    return -1
+}
+
+itcl::body bis_object::SaveObjectList { index args } { 
+    if { $index >=0 && $index < [ llength $objectlist ] } {
+	set obj [ lindex $objectlist $index ]
+	return [ $obj Save $args]         
+    }
+    return -1
+}
+# -------------------------------------------------------------------------
+itcl::body bis_object::GetFileNameList {  } { 
+    set n ""
+    for { set i 0 } { $i < [ llength $objectlist ] } { incr i } {
+	append n " [ [ lindex $objectlist $i ] cget -filename ]"
+    }
+    return $n
+
+}
+# ----------------------------------------------------------------
+itcl::body bis_object::AddFileNames { fnamelist } { 
+
+    if { $multipleobjectflag == 0 } {
+	return 0
+    }
+
+    if { $objectlist != "" } {
+	return 0
+    }
+
+#    puts stderr "Filenames =$fnamelist"
+
+    set n [ llength $fnamelist ]
+    for { set i 0 } { $i < $n } { incr i } {
+	switch $objecttype { 
+	    pxitclimage {
+		set newobj [ [ pxitclimage \#auto ] GetThisPointer ]
+	    }
+	    pxitcltransform {
+		set newobj [ [ pxitcltransform \#auto ] GetThisPointer ]
+	    }
+	    pxitclsurface {
+		set newobj [ [ pxitclsurface \#auto ] GetThisPointer ]
+	    }
+	    pxitclmesh {
+		set newobj [ [ pxitclmesh \#auto ] GetThisPointer ]
+	    }
+	    default { 
+		puts stderr "Specifid type $objecttype is not among pxitcl... for multiple"
+		set newobj 0
+	    }
+	}
+	if { $newobj !=0 } {
+	    $newobj configure -filename [ lindex $fnamelist $i ]
+	    #	    puts stderr "Adding object $newobj filename = [ $newobj cget -filename ]"
+	    lappend objectlist $newobj
+	}
+    }
+
+    $this UpdateInternalGUI
+
+}
+
+itcl::body bis_object::CreateMultipleObjectGUI { base { enablesave 1 } { desc "" } { parent 0 } } {
+    
+    if { $internalobject == 0 } {
+	return 0
+    }
+
+    set algparent  $parent
+    switch $objecttype { 
+	pxitclimage {
+	    set objectgui [ [ pxitclmultiImageGUI \#auto ] GetThisPointer ]
+	}
+	pxitcltransform {
+	    set objectgui [ [ pxitclmultiTransformGUI \#auto ] GetThisPointer ]
+	}
+	pxitclsurface {
+	    set objectgui [ [ pxitclmultiSurfaceGUI \#auto ] GetThisPointer ]
+	} 
+	pxitclmesh {
+	    set objectgui [ [ pxitclmultiMeshGUI \#auto ] GetThisPointer ]
+	}
+	default { 
+	    puts stderr "Specifid type $objecttype is not among pxitcl... for multiple"
+	    set objectgui 0
+	}
+    }
+
+
+
+    if { $desc == "" } {
+	$objectgui configure -description $description
+    } else {
+	$objectgui configure -description $desc
+    }
+
+
+    $objectgui configure -enabledeleteall 1
+    $objectgui configure -enableupdown 1
+    $objectgui InitializeLite $base 
+    if { $enablesave == 0 } {
+	set but [ [ $objectgui GetObjectGUI ] cget -savebutton ]; pack forget $but
+	set but [ [ $objectgui GetObjectGUI ] cget -clearbutton ]; pack forget $but
+    }
+    
+
+    [ $objectgui GetObjectGUI ] configure -description $description
+    $objectgui Update
+    $objectgui configure -callback "$this GUICallback"
+
+    if { $parent == 0 } {
+	$this UpdateInternalGUI
+	return
+    }
+
+    if { $objecttype == "pxitclimage" } {
+	set viewer [ $parent GetViewer ]
+	if { $viewer !=0 } {
+	    [ $objectgui GetObjectGUI ] AddFunction "$this DisplayImage" "Display" "$viewer"
+	}
+    } elseif { $objecttype != "pxitcltransform" } {
+	set viewer [ $parent GetBisViewer ]
+#	puts stderr "Viewer =$viewer, parent=$parent [ $parent info class ]"
+	[ $objectgui GetObjectGUI ] AddFunction "$this DisplayObject" "Display" "$viewer"
+    }
+
+    $objectgui AddFunction "$this GUIQuickHelp" "?" ""
+    $this UpdateInternalGUI
+    
+
+}
+# ------------------------------------------------------------------------------------------------------------------
+itcl::body bis_object::CreateDataTreeObjectGUI { base { enablegrab 0 } { enablestore 0 } { parent 0 } { datatree 0 }} {
+
+    if { $internalobject == 0 } {
+	return 0
+    }
+
+    if { $multipleobjectflag == 1 } {
+	return [ $this CreateMultipleDataTreeObjectGUI $base $enablegrab $enablestore $parent $datatree ]
+    }
+
+
+    set algparent  $parent
+    #    puts stderr "Parent=$parent, datatree=$datatree"
+    set objectguimode "datatree"
+
+    set fr [ [  iwidgets::Labeledframe $base -labelpos n -labeltext $description ] childsite ]
+    pack $base -side top -expand true -fill x -pady 0
+
+    set guiparam($this,treetext) ""
+    set ent1 [ entry $fr.ent -width 30 -state normal  -foreground black -background white -textvariable [ itcl::scope guiparam($this,treetext) ]]
+
+    if { $objecttype!="pxitcltransform" } {
+	set but2 [ eval "button $fr.grabbutton2 -activebackground white -foreground black -activeforeground black -text \"Display\" -command { $this DisplayObject 0 $datatree }" ]
+	pack $but2 -side left -expand false -padx 1
+	
+	if { $enablegrab >  1 } {
+	    set but2 [ eval "button $fr.grabbutton0 -activebackground white -foreground black -activeforeground black -text \"GRef\" -command { $this GrabTreeSelection $datatree 1 }" ]
+	    pack $but2 -side left -expand false -padx 0
+	}
+    } else {
+	set but2 [ eval "button $fr.grabbutton2 -activebackground white -foreground black -activeforeground black -text \"Info\" -command { $this InfoObject }" ]
+	pack $but2 -side left -expand false -padx 1
+    }
+	
+    if { $enablegrab >  0 } {
+	set but1 [ eval "button $fr.grabbutton -activebackground white -foreground black -activeforeground black -text \"Grab\" -command { $this GrabTreeSelection $datatree 0 }" ]
+	pack $but1  -side left -expand false -padx 0
+    }
+
+    if { $enablestore >  0 } {
+	set but1 [ eval "button $fr.grabbutton -activebackground white -foreground black -activeforeground black -text \"Store\" -command { $this StoreInTree $datatree  }" ]
+	pack $but1  -side left -expand false -padx 0
+    }
+
+
+    pack $ent1 -side right -expand true -padx 0 -fill x
+}
+# ------------------------------------------------------------------------------------------------------------------
+itcl::body bis_object::CreateMultipleDataTreeObjectGUI { base { enablegrab 0 } { enablestore 0 } { parent 0 } { datatree 0 }} {
+
+    if { $internalobject == 0 } {
+	return 0
+    }
+
+    set algparent  $parent
+    set objectguimode "datatree"
+
+    set fr [ [  iwidgets::Labeledframe $base -labelpos n -labeltext $description ] childsite ]
+    pack $base -side top -expand true -fill x -pady 0
+    frame $fr.right; pack $fr.right -side right -expand false -fill x -padx 2
+
+    set guiparam($this,treelistbox) [ iwidgets::scrolledlistbox $fr.left -vscrollmode dynamic -hscrollmode dynamic -selectmode single -labelpos nw -visibleitems 5x20 ]
+    [ $fr.left component listbox ] configure -bg white -fg black -width 30
+    pack $fr.left -side left -expand true -fill both
+
+    set fr $fr.right
+
+    if { $objecttype!="pxitcltransform" } {
+	set but2 [ eval "button $fr.grabbutton2 -activebackground white -foreground black -activeforeground black -text \"Display\" -command { $this DisplayObject 0 $datatree }" ]
+	pack $but2 -side top -expand true -padx 1 -fill x -pady 5
+	
+	if { $enablegrab >  1 } {
+	    set but2 [ eval "button $fr.[ pxvtable::vnewobj ]  -activebackground white -foreground black -activeforeground black -text \"GRef\" -command { $this GrabTreeSelection $datatree 1 }" ]
+	    pack $but2 -side top -expand false -padx 0 -fill x -pady 5
+	}
+    } else {
+	set but2 [ eval "button $fr.[ pxvtable::vnewobj ] -activebackground white -foreground black -activeforeground black -text \"Info\" -command { $this InfoObject }" ]
+
+	pack $but2 -side top -expand false -padx 1 -fill x -pady 5
+    }
+
+
+    if { $enablegrab >  0 } {
+	set but1 [ eval "button $fr.[ pxvtable::vnewobj ] -activebackground white -foreground black -activeforeground black -text \"Grab\" -command { $this GrabTreeSelection $datatree 0 }" ]
+	pack $but1  -side top -expand false -padx 0 -fill x -pady 5
+    }
+
+    if { $enablestore >  0 } {
+	set but1 [ eval "button $fr.[ pxvtable::vnewobj ] -activebackground white -foreground black -activeforeground black -text \"Store\" -command { $this StoreInTree $datatree  }" ]
+	pack $but1  -side top -expand false -padx 0 -fill x -pady 5
+    }
+
+	set but3 [ eval "button $fr.[ pxvtable::vnewobj ] -activebackground white -foreground black -activeforeground black -text \"Clear Last\" -command { $this ClearTreeObject current }" ]
+	set but4 [ eval "button $fr.[ pxvtable::vnewobj ] -activebackground white -foreground black -activeforeground black -text \"Clear All\" -command { $this ClearTreeObject all }" ]
+	pack $but3 $but4 -side top -expand false -padx 0 -fill x -pady 10
+
+    #    pack $ent1 -side right -expand true -padx 0 -fill x
+}
+# ---------------------------------------------------------------------------------------------------------
+
+itcl::body bis_object::GUIQuickHelp { image args } {
+
+    set line $description
+    if { $cmdlineoption != "" } {
+	set line "$line\n specify on the command line using -$cmdlineoption"
+    }
+    
+    tk_messageBox -type ok -message $line -title "Quick Help: $name" -icon info
+}
+# ----------------------------------------------------------------------------------------------
+itcl::body bis_object::InfoObject {  } {
+    if { $multipleobjectflag == 0 } {
+	tk_messageBox -type ok -title "Object Info" -message  [ $internalobject GetDescription ] 
+    } else {
+	set sur [ $objectgui GetObject -1 ]
+	tk_messageBox -type ok -title "Object Info" -message  [ $sur GetDescription ] 
+    }
+}
+
+itcl::body bis_object::DisplayImage { image viewer } {	
+    $viewer SetImage [ $image GetImage ] [ $image GetOrientation ] 
+}
+# ----------------------------------------------------------------------------------------------
+itcl::body bis_object::DisplayObject { sur viewer } {	
+
+    if { $sur == 0 } {
+	if { $multipleobjectflag == 0 } {
+	    set sur [ $this GetObject ]
+	} else {
+	    set ind [ [ $guiparam($this,treelistbox) component listbox ] curselection ]
+	    
+	    if { $ind == -1  || $ind == "" } {
+		return
+	    }
+	    if { $ind == 0 } {
+		set sur [ $this GetObject ]
+	    } else {
+		set sur [ lindex $objectlist [ expr $ind -1 ]]
+	    }
+	}
+    }
+    
+    if { [ $viewer  info class ] != "::bis_viewer"  } {
+	puts stderr "My viewer is an algorithm!"
+	set viewer [ $viewer GetBisViewer ]
+	puts stderr "Using viewer = $viewer"
+    }
+    
+
+    if { $sur == 0 } {
+	return 0
+    }
+
+    if { [ $sur isa "pxitclimage" ] == 1 } {
+	return [ $viewer SetImage $sur ]
+    }
+    $viewer AddOrReplacePolygonalObject $sur 0 { visible 1 }
+}
+    
+# ----------------------------------------------------------------------------------------------
+itcl::body bis_object::ClearTreeObject { { mode current } } {
+
+    if {  [ $guiparam($this,treelistbox) index end ] == 0 } {
+	return
+    }
+
+    if { $mode == "current" } {
+	if { [ llength $objectlist ] > 0 } {
+	    set n [ expr [ llength $objectlist] -1 ]
+	    itcl::delete object [ lindex $objectlist $n ] 
+	    set lst [ lrange $objectlist 0 [ expr $n -1 ] ]
+	    set objectlist $lst
+	} else {
+	    $internalobject Clear
+	}
+	$guiparam($this,treelistbox) delete end end 
+    } else {
+	set ok [ tk_messageBox -type yesno -default no -title "Think again ..." -message "Do you want to clear the whole list?" -icon question  ]
+	if { $ok == "no" } {
+	    return
+	}
+	$internalobject Clear
+	foreach obj $objectlist {
+	    itcl::delete object $obj
+	}
+	$guiparam($this,treelistbox) delete 0 end 
+    }
+}
+
+itcl::body bis_object::GrabTreeSelection { datatree { refspace 0 } } {
+
+    if { $datatree == 0 } {
+	return  0
+    }
+
+    if { $objecttype=="pxitcltransform" } {
+	$internalobject  Copy  [ $datatree GetTransformation ] 
+	set guiparam($this,treetext) "[$internalobject GetShortDescription]"
+	
+	if { $updatecallback != "" } {
+	    eval $updatecallback
+	}
+	return 1
+    }
+
+    set datamanager [ $datatree GetDataManager ]
+    set elem [ $datatree GetCurrentXMLElement ]
+    if { $elem == "" || $elem == "0" } {
+	return 0
+    }
+
+    set tp [ $elem GetAttribute Type ]
+    set otype [ $datamanager GetObjectTypeForTypeAttribute $tp ]
+
+    if {  $otype  != $objecttype } {
+	return 0
+    }
+
+    # -----------------------------------
+
+    if {  [ $elem GetAttribute ObjectLoaded ] != 1 } {
+	set ok [ $datamanager LoadObjectPointers $elem  ]
+	if { $ok == 0 } {
+	    return 0 
+	}
+    }
+    
+
+    set newobj $internalobject
+    if { $multipleobjectflag == 1 } {
+	if {  [ $guiparam($this,treelistbox) index end ] > 0 } {
+	    puts stderr "Adding new object"
+	    set cl [ $internalobject info class ]
+	    set newobj [ [ eval "$cl \#auto" ] GetThisPointer ]
+	    lappend objectlist $newobj
+	}
+    }
+
+    if { $refspace == 1 } {
+	set img [  $datatree ResliceNodeInReferenceSpace $elem ]
+	if { $img == 1 } {
+	    set refspace 0
+	}
+	if { $img != 0 && $img!=1 } {
+	    $newobj ShallowCopy $img
+	    itcl::delete object $img
+	    set xmlpointer 0
+	}
+    }
+    
+    if { $refspace == 0 } {
+	$newobj ShallowCopy [ $elem GetAttribute PointerObject ]
+	set xmlpointer $elem
+    }
+
+
+
+    set fn [ file tail [ $elem GetAttribute Filename ]]
+    if { $fn == 0 } {
+	set fn ""
+    } else {
+	set fn ":${fn}"
+    }
+
+    set txt "[ $elem GetName ]$fn ([$internalobject GetShortDescription])"
+    if { $multipleobjectflag == 0 } {
+	set guiparam($this,treetext)  $txt
+    } else {
+	set n [ expr [ llength $objectlist ] +1 ]
+	$guiparam($this,treelistbox) insert end $txt.$n
+	$guiparam($this,treelistbox) selection clear 0  end 
+	$guiparam($this,treelistbox) selection set end  end 
+    }
+    
+    if { $updatecallback != "" } {
+	eval $updatecallback
+    }
+}
+# ----------------------------------------------------------------------------------------------
+itcl::body bis_object::StoreInTree { datatree } {
+
+    if { $datatree == 0 } {
+	return  0
+    }
+    
+
+    set nm ""
+    catch { set nm "[ $algparent GetGUIName ]" }
+    regsub -all " " $nm "_" nm
+
+    if { $objecttype=="pxitcltransform" } {
+	$datatree AddTransformation  $internalobject $nm
+	return 1
+    }
+
+
+    set elem [ $datatree GetCurrentXMLElement ]
+    if { $elem == "" || $elem == "0" } {
+	return 0
+    }
+
+    set datamanager [ $datatree GetDataManager ]
+    set ndtype [ $datamanager GetTypeAttributeForObjectType $objecttype ]
+
+    set newelem [ $datatree AddNewNode $ndtype ]
+    if  { $newelem == 0 } {
+	return 0
+    }
+
+    if { [ $internalobject isa "pxitclimage" ] == 1 || [ $internalobject isa "pxitclsurface"  ] ==1  || [ $internalobject isa "pxitclmesh" ] == 1 } {
+	[ $newelem GetAttribute PointerObject ] ShallowCopy $internalobject
+    } else {
+	[ $newelem GetAttribute PointerObject ] Copy $internalobject
+    }
+    $newelem SetAttribute Filename [ $internalobject cget -filename ]
+
+    set nm ""
+    catch { set nm "[ $algparent GetGUIName ]_" }
+    append nm $description
+
+    $newelem SetAttribute Title    $nm
+    $datamanager UpdateAttributesByList $newelem { "ObjectLoaded" Filename Title }
+    $datatree    UpdateVisTree  [ $newelem GetParent ]
+    $datatree    UpdateStatus 
+    return $newelem
+}
+# ----------------------------------------------------------------------------------------------
+itcl::body bis_object::UpdateInternalGUI { } {
+
+    if { $objectguimode  == "normal" && $objectgui !=0 } {
+
+	if { $multipleobjectflag == 0 } {
+	    $objectgui Update
+	} else {
+	    set update_gui_internally 1
+	    set num [ $objectgui GetNumberOfObjects ]
+	    set newlist [ concat $internalobject $objectlist ]
+	    set num2 [ llength $newlist ]
+
+	    for { set i 0 } { $i < $num2 } { incr i } {
+		set oldobj [ lindex $newlist $i ]
+		if { $i >= $num } {
+		    set newobj [ $objectgui AddInternalObject ]
+		} else {
+		    set newobj [ $objectgui GetObject $i ]
+		}
+
+		$newobj ShallowCopy $oldobj
+	    }
+
+	    set num [ $objectgui GetNumberOfObjects ]
+	    if { $num > 0 } {
+		$objectgui CurrentObjectModified
+	    }
+	    set update_gui_internally 0
+	}
+    }
+    set guiparam($this,treetext) "[$internalobject GetShortDescription]"
+}
+
+
+itcl::body bis_object::UpdateObjectListFromGUI { } {
+
+    if { $objectguimode  == "normal" && $objectgui !=0 } {
+	set update_gui_internally 1
+	set num [ $objectgui GetNumberOfObjects ]
+	if { $num == 0 } {
+	    set update_gui_internally 0
+	    return 
+	}
+	set newlist [ concat $internalobject $objectlist ]
+	set num2 [ llength $newlist ]
+	
+	for { set i 0 } { $i < $num } { incr i } {
+	    set oldobj [ $objectgui GetObject $i ]
+	    
+	    if { $i < $num2 } {
+		set newobj [ lindex $newlist $i ]
+	    } else {
+		set cl [ $oldobj info class ]
+		set newobj [ [ eval "$cl \#auto" ] GetThisPointer ]
+		lappend objectlist $newobj
+	    }
+	    $newobj ShallowCopy $oldobj
+	}
+	set update_gui_internally 0
+    }
+}
+# ----------------------------------------------------------------------------------------------
+itcl::body bis_object::GUICallback { } {
+
+
+    if { $update_gui_internally == 1 } {
+	return
+    }
+
+    if { $objectgui == 0 || $internalobject == 0 } {
+	return 0
+    }
+    
+    if { $multipleobjectflag == 0 } {
+	if { $internalobject != [ $objectgui GetObject ] } {
+	    $internalobject ShallowCopy [ $objectgui GetObject ]
+	}
+    } else {
+
+    }
+
+    if { $updatecallback != "" } {
+	eval $updatecallback
+    }
+}
+
+itcl::body bis_object::GetFileName { } { 
+    if { $internalobject == 0 } {
+	return ""
+    }
+    return [ $internalobject cget -filename ]
+}
+
+itcl::body bis_object::SetFileName { a { force 0 } } {
+
+    if { $a == "" } {
+	return 0
+    }
+
+    if { $guimode == "managed" } {
+	set force 1
+    }
+    
+#    puts stderr "Setting FileName of $name, $description to \"$a\" force=$force $internalobject"
+    if { $internalobject == 0 } {
+	return 0
+    }
+
+
+    set fn [ $this GetFileName ]
+    if { [ string length $fn ] > 1 && $force == 0 } {
+	#	puts stderr "Filenames not set to $a"
+	return 0
+    }
+
+
+
+    $internalobject configure -filename $a  
+    set update_gui_internally 1
+    if { $objectgui != 0 } {
+	$objectgui Update
+    }
+    set update_gui_internally 0
+
+ #   puts stderr "Filenames set to $a"
+
+    return 1
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_option.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_option.tcl
new file mode 100644
index 0000000..b4942e9
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_option.tcl
@@ -0,0 +1,1058 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_option 1.0
+
+#
+# bis_option.tcl
+#
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    lappend auto_path [ file dirname [ info script ]]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+}
+
+package require Itcl
+package require Iwidgets
+package require bis_common
+
+itcl::class bis_option {
+
+        # This is a static array to store GUI input
+        private   common   thisparam
+
+	constructor { } {
+	    set thisparam($this,value) 0
+	    set thisparam($this,listbox) 0
+	    set thisparam($this,selectiondialog) 0
+	    set thisparam($this,textbox) 0
+	}
+
+	# More GUI Stuff
+	protected variable callbackfunction 0
+	
+	# This is the command line switch (e.g. -h) 
+	protected variable commandswitch     "-h"
+	protected variable description       "Print a help message for this algorithm"
+	protected variable shortdescription  "Help Message"
+	
+	# Created Possible List
+	# The following static arrays contain all valid options
+	protected common optiontypelist [ list listofvalues boolean real integer string filename comment multiplevalues ] 
+	protected common optiontypehintlist { scale triplescale entrywidget radiobuttons optionmenu checkbutton default readfile writefile directory comment }
+
+	# These are the actual option settings for this class
+	private variable optiontype     "real"
+	private variable optiontypehint "default"
+	
+	# Some public stuff for the GUI
+	public variable optionguiwidth -1
+	
+	# This is the default value for the option
+	protected variable defaultvalue 0
+
+	# a list of either { min,max} or allowed entries
+	protected variable valuerange  { 0 10 }
+	protected variable valuerangewidget 0 
+	protected variable valuewidget 0
+	protected variable labeledwidget 0
+
+	public method GetValueWidget { } { return $valuewidget }
+	public method GetLabeledWidget { } { return $labeledwidget }
+
+
+	# this is the basewidget
+	protected variable basewidget 0
+	# this is needed by comment elements
+	protected variable labelwidget 0 
+
+        # oneoff { positive value (normal)  negative value (experimental) } higher is better
+	protected variable priority  0   
+
+        # switch for input value automatic correction 
+	# If this is on, input value is clamped.
+	# If this is off, return code is 0(NG) or 1(OK).
+        protected   common autocorrection 1
+
+	# Basic Class Interface
+	# Setting and Getting of Member Variables
+  	public method SetCommandSwitch    { a } { set commandswitch $a }
+  	public method GetCommandSwitch    {   } { return $commandswitch  }
+
+  	public method SetDescription      { a } { set description $a }
+  	public method GetDescription      {   } { return $description }
+
+  	public method SetShortDescription { a } { set shortdescription $a }
+  	public method GetShortDescription {  } { return $shortdescription}
+
+	# Option Type -- full implementation below
+  	public method SetOptionType       { optiontype { optionhint default }}
+  	public method GetOptionType       {   } { return  $optiontype }
+
+	#
+  	public method SetDefaultValue     { a } 
+  	public method GetDefaultValue     {   } { return $defaultvalue }
+
+	# Get Widget
+	public method GetBaseWidget { } { return $basewidget }
+
+	# Get Slicer XML Description
+	public method GetSlicerXMLDescription { }
+	public method GetLONIXMLDescription { }
+	public method GetJSONString { }
+
+	# Value Range
+  	public method SetValueRange       { a } 
+  	public method GetValueRange       {   } { return $valuerange }
+
+  	public method SetPriority         { a } { set priority $a }
+  	public method GetPriority         {   } { return $priority }
+
+  	public method SetAutoCorrection        { a } { set autocorrection $a }
+  	public method GetAutoCorrection        {   } { return $autocorrection }
+
+	public method SetAllPropertiesAsList { il  } 
+
+
+	public method SetAllProperties    { i_cmdswitch i_description i_shortdescription i_opttype i_defvalue i_val i_priority } {
+	    SetCommandSwitch    $i_cmdswitch
+	    SetDescription      $i_description
+	    SetShortDescription $i_shortdescription
+	    SetOptionType   [ lindex    $i_opttype 0 ]
+
+	    set optiontypehint "default"
+	    set optionguiwidth  -1
+	    
+	    if { [ llength $i_opttype ] > 1 } {
+		set optiontypehint  [ lindex    $i_opttype 1 ]
+		if { [ llength $i_opttype ] > 2 } {
+		    set optionguiwidth  [ lindex    $i_opttype 2 ]
+		}
+	    }
+	    SetValueRange       [ string trim $i_val ]
+	    SetDefaultValue     [ string trim $i_defvalue ]
+	    SetPriority         $i_priority
+	    SetValue            [ $this GetDefaultValue ]
+	}
+
+	# 
+	public method PrintSelf     { }
+
+	public method GetCmdLineString { } { 
+	    return [ list ${commandswitch}.arg $defaultvalue $description ] 	
+	}
+
+	# Get Set Value
+	
+  	public method GetValue     {   } { 
+	    set thisparam($this,value) [CheckValue  $thisparam($this,value) ]
+	    return $thisparam($this,value) 
+	}
+
+	public method SetValue { inpval } { 
+	    set thisparam($this,value) [CheckValue $inpval ]
+	    if { $optiontype == "comment" &&  $labelwidget!=0 } {
+		#$labelwidget configure -text $thisparam($this,value)
+		$thisparam($this,textbox) configure -state normal
+		$thisparam($this,textbox) delete 1.0 end
+		$thisparam($this,textbox) insert end $thisparam($this,value)
+		$thisparam($this,textbox) configure -state disabled
+	    }
+	}
+
+
+	public method SetValueIfCurrentIsTheDefault { inpval } { 
+	    if { $thisparam($this,value) == $defaultvalue } {
+		set thisparam($this,value) [CheckValue $inpval]
+	    }
+	}
+
+
+	public method UpdateFromGUI { } 
+	#
+	public method CheckValue { inpval }
+	protected method CheckValueByRange { inpval }
+	protected method CheckValueByListOfValues { inpval }
+	protected method CheckValueByMultipleValues { inpval }
+
+	public method SetCommandLine { name } 
+
+	# returns a string for a logfile
+	# public method GetLogElement { }   
+
+	# GUI Stuff
+	# parent widget must not exists, it will be created by this method
+	# it must be packed on return
+	public method CreateGUIElement { parentwidget { callback "" } }
+	public method SetGUICallbackFunction { cl } {  set callbackfunction $cl }
+	public method GUICallbackFunction { }
+
+	public method GUIQuickHelp { }
+	protected method CreateGUIElementList { parentwidget  }
+	protected method CreateGUIElementRange { parentwidget  }
+	protected method CreateGUIElementMultiple { parentwidget  }
+	protected method CreateGUIElementString { parentwidget  }
+	protected method CreateGUIElementBoolean { parentwidget  }
+	protected method CreateGUIElementFilename { parentwidget  }
+	protected method CreateGUIElementComment { parentwidget  }
+	
+
+	# Method Get FileName
+	public method GetFileName { }
+
+	# Method Get Multiple Selection
+	public method GetMultipleSelection { }
+
+
+	# boolean -- checkbutton
+	# listofvalues -- option menu
+	# multiple values -- string + popup dialog i.e. like filename
+	# real/integer  -- textentry
+
+	# It does proper scoping
+	#Instead of
+	#set option  [ bis_option #auto ]
+	#use	set option [ [ bis_option #auto ] GetThisPointer ]
+	public method GetThisPointer { } { return $this }
+
+	# Help Button (Hide)
+	# 
+
+	protected variable helpbutton 0
+	protected variable helpmessage "default"
+
+	public method SetHelpMessage { msg } {  set helpmessage $msg }
+	public method HideHelpButton { } {     catch { pack forget $helpbutton }	}
+
+
+	# selection dialog
+
+    }
+#----------------------------------------------------
+itcl::body bis_option::PrintSelf { } {
+    puts stdout "commandswitch    =  [$this GetCommandSwitch]"
+    puts stdout "description      =  [$this GetDescription]"
+    puts stdout "shortdescription =  [$this GetShortDescription]"
+    puts stdout "optiontype       =  [$this GetOptionType]"
+    puts stdout "defaultvalue     =  [$this GetDefaultValue]"
+    puts stdout "value            =  [$this GetValue]"
+    puts stdout "valuerange       =  [$this GetValueRange]"
+    puts stdout "priority         =  [$this GetPriority]"
+    puts stdout "\n"
+}
+
+#----------------------------------------------------
+itcl::body bis_option::GetSlicerXMLDescription { } {
+
+
+    set base "\t<name>[ $this GetCommandSwitch]</name>\n"
+    set base "$base\t<label>[ $this GetShortDescription]</label>\n"
+    set base "$base\t<longflag>--[ $this GetCommandSwitch]</longflag>\n"
+    set base "$base\t<description>[ $this GetDescription ]</description>\n"
+    set base "$base\t<default>[ $this GetDefaultValue ]</default>\n"
+
+    set range "\t<constraints>\n"
+    set range "$range\t\t<minimum>[ lindex [ $this GetValueRange ] 0 ]</minimum>\n"
+    set range "$range\t\t<maximum>[ lindex [ $this GetValueRange ] 1 ]</maximum>\n"
+    set range "$range\t</constraints>"
+
+    set elrange ""
+    for { set i 0 } { $i < [ llength [ $this GetValueRange ] ] } { incr i } {
+	set elrange "$elrange\t\t<element>[ lindex  [ $this GetValueRange ] $i ]</element>\n"
+    }
+    
+    # ---------------------------------------------
+    switch $optiontype {
+	integer { 
+	    set line "<integer>\n$base$range</integer>\n"
+	}
+	real    { 
+	    set line "<double>\n$base$range\n</double>\n"
+	}
+	boolean {
+	    set line "<string-enumeration>\n$base$elrange</string-enumeration>"
+	}
+	listofvalues { 
+	    set line "<string-enumeration>\n$base$elrange</string-enumeration>"
+	}
+	filename { 
+	    if { $optiontypehint == "writefile" } {
+		set tmp "<channel>output</channel>\n"
+	    } else {
+		set tmp "<channel>input</channel>\n"
+	    }
+	    set line "<file>\n$base\t$tmp</file>\n"
+	}
+	default {
+	    set line "<file>\n$base</file>\n"
+	}
+    }
+    # ---------------------------------------------
+}
+
+# -------------------------------------------------------------------------------------------------------------
+itcl::body bis_option::GetJSONString { } {
+
+    set val [ $this GetValueRange] 
+    set v1 [ ::bis_common::CleanString $description]
+    set v2 [ ::bis_common::CleanString $shortdescription]
+
+    set txt "\t\t\"$commandswitch\": \{\n"
+    append txt "\t\t\t\"description\": $v1,\n"
+    append txt "\t\t\t\"shortdescription\": $v2,\n"
+    append txt "\t\t\t\"optiontype\": [ ::bis_common::CleanString $optiontype],\n"
+    append txt "\t\t\t\"optiontypehint\": [ ::bis_common::CleanString $optiontypehint],\n"
+    append txt "\t\t\t\"optionguiwidth\": [ ::bis_common::CleanString $optionguiwidth],\n"
+    append txt "\t\t\t\"defaultvalue\": [ ::bis_common::CleanString $defaultvalue],\n"
+    append txt "\t\t\t\"valuerange\": [ ::bis_common::CleanString $val],\n"
+    append txt "\t\t\t\"priority\": [ ::bis_common::CleanString [$this GetPriority]]\n"
+    append txt "\t\t\}"
+    return $txt
+}
+
+# -------------------------------------------------------------------------------------------------------------
+
+itcl::body bis_option::GetLONIXMLDescription { } {
+
+    set mode 0
+    if { $optiontype=="filename" } {
+	set mode 1
+	if { $optiontypehint == "directory" } {
+	    set mode 2
+	}
+    }
+    
+    set line "\t\t\t<input name=\"[ $this GetShortDescription ]\" "
+#    append line  "id=\"bis_option_[$this GetCommandSwitch ]\" "
+    append line  "description=\"[ $this GetDescription ]\" "
+    append line  "enabled=\"true\" "
+    append line  "required=\"false\" "
+    append line  "switchedSpaced=\"true\" "
+    append line  "switch=\"-[$this GetCommandSwitch ]\">\n"
+
+     
+    if { $mode == 1 } {
+	append line "\t\t\t\t<format type=\"File\" cardinality=\"1\" />\n"
+    } elseif { $mode == 2 } {
+	append line "\t\t\t\t<format type=\"Directory\" cardinality=\"1\"/>\n"
+    } elseif { $optiontype == "listofvalues" } {
+	append line "\t\t\t\t<format type=\"String\" cardinality=\"1\"/>\n"
+    } elseif { $optiontype == "integer" || $optiontype == "real" || $optiontype == "boolean" } {
+	append line "\t\t\t\t<format type=\"Number\" cardinality=\"1\"/>\n"
+    } else {
+	append line "\t\t\t\t<format type=\"String\" cardinality=\"1\"/>\n"
+    }
+    append line "\t\t\t</input>\n"
+    return $line
+}
+
+#----------------------------------------------------
+#Check the value 
+#----------------------------------------------------
+itcl::body bis_option::SetDefaultValue     { a }  {
+    set defaultvalue $a
+}
+
+itcl::body bis_option::CheckValue { inpval  } {
+    
+    set type  $optiontype 
+    if { $type == "string" || $type == "comment" } {
+	return $inpval
+    }
+
+    if { $type == "filename" } {
+	if { $inpval == "" || $inpval == "0" } {
+	    return $inpval
+	}
+	return [ file normalize $inpval ]
+    }
+
+    set ret 1
+    switch $type {
+	integer {
+	    set ret [CheckValueByRange $inpval]
+	}
+	real {
+	    set ret [CheckValueByRange $inpval]
+	}
+	listofvalues {
+	    set ret [CheckValueByListOfValues  $inpval]
+	}
+	multiplevalues {
+	    set ret [CheckValueByMultipleValues  $inpval]
+	}
+	boolean {
+	    set ret [CheckValueByListOfValues  $inpval]
+	}
+    }
+    return $ret
+}
+
+
+#----------------------------------------------------
+#Check the value in the specified range {min,max}
+#----------------------------------------------------
+itcl::body bis_option::CheckValueByRange { inpval } {
+
+    set min [lindex  $valuerange 0 ]
+    set max [lindex  $valuerange 1 ]
+    if { $autocorrection == 1 } {
+	if { $inpval  < $min }  {
+	    return $min
+	} elseif { $inpval > $max } {
+	    return $max
+	}
+	return $inpval
+    } else {
+	#returns  1:ok,0:ng (autocorrection off)
+	if { $inpval  < $min }  {
+	    return 0
+	} elseif { $inpval > $max } {
+	    return 0
+	}
+	return 1
+    }
+}
+
+#----------------------------------------------------
+#Check the value in the specified list
+#----------------------------------------------------
+itcl::body bis_option::CheckValueByListOfValues { inpval } {
+    
+    if { $autocorrection == 1 } {
+	if { [ lsearch -exact $valuerange $inpval ] >=0 } {
+	    return $inpval
+	}
+	return [ lindex $valuerange 0 ]
+    } else {
+	#returns  1:ok,0:ng (autocorrection off)
+	if { [ lsearch -exact $valuerange $inpval ] >=0 } {
+	    return 1
+	}
+	return  0
+    }
+}
+
+# ----------------------------------------------------------------------------
+itcl::body bis_option::CheckValueByMultipleValues { inpval } {
+    
+    set goodvalues ""
+    if { $autocorrection == 1 } {
+	if { [ llength $inpval ] == 0 } { return $inpval }
+
+	for { set i 0 } { $i < [ llength $inpval ] } { incr i } {
+	    if { [ lsearch -exact $valuerange [ lindex $inpval $i ] ] >=0  } {
+		lappend goodvalues [ lindex $inpval $i ]
+	    }
+	}
+	if { $goodvalues != "" } {
+	    return $goodvalues
+	}
+	return [ lindex $valuerange 0 ]
+    } else {
+	#returns  1:ok,0:ng (autocorrection off)
+	if { [ llength $inpval ] == 0 } { return 1 }
+	set ok 1
+	for { set i 0 } { $i < [ llength $inpval ] } { incr i } {
+	    if { [ lsearch -exact $valuerange [ lindex $inpval $i ] ] ==-1 } {
+		return 0
+	    }
+	}
+	return 1
+    }
+}
+
+# ----------------------------------------------------------------------------
+
+itcl::body bis_option::SetCommandLine { name } {
+    set  CommandLine $name
+    puts stdout "Command Line = $CommandLine"
+}
+
+itcl::body bis_option::SetOptionType { i_optiontype { i_optionhint default } } {
+    if { [ lsearch $optiontypelist $i_optiontype ] == - 1 } {
+	return 0
+    }
+    
+    set optiontype $i_optiontype
+
+    if { [ lsearch -exact $optiontypehintlist $i_optionhint ] == - 1 } {
+	set optiontypehint "default"
+    } else {
+        set optiontypehint  $i_optionhint 
+    }
+    
+    if { $optiontype == "boolean" } {
+	set valuerange { 0 1 }
+    }
+
+    return 1
+}
+# --------------------------------------------------------------------------------------
+itcl::body bis_option::SetAllPropertiesAsList { il } {
+
+    if { [ llength $il ] < 7 } {
+	return 0
+    }
+
+    SetAllProperties [ lindex $il 0 ] [ lindex $il 1 ] [ lindex $il 2 ] [ lindex $il 3 ] [ lindex $il 4 ] [ lindex $il 5 ] [ lindex $il 6 ] 
+    return [ llength $il ]
+}
+
+itcl::body bis_option::SetValueRange { a }  {
+
+    if { $optiontype == "filename" } {
+
+	if { [ string match -nocase "*image*" $a ] > 0 } {
+	    set valuerange { 
+		{"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}
+		{"VTK Files" {.vt*}}
+		{"All Files" {*}}}
+	} elseif { [ string match -nocase "*transform*" $a ] > 0 } {
+	    set valuerange { 
+		{"Matrix/Grid Files" {".matr" ".grd" ".grd.gz" } }
+		{"Grid/Combo Transform Files"  {".grd" ".grd.gz" }}
+		{"VTK Displacement Fields" {.vtk}} 
+		{"PolySimilarity Transforms" {.psim}} 
+		{"Matrix Files" {.matr}} 
+		{"Thin Plate Spline Transforms" {.tps}} 
+		{"All Files" {*}}}
+	} elseif { [ string match -nocase "*surface*" $a ] > 0 } {
+	    set valuerange { 
+		{"VTK Surface" {.vtk .vsp}} 
+		{"All Files" {*}}}
+	} elseif { [ string match -nocase "*landmarks*" $a ] > 0 } {
+	    set valuerange { 
+		{"Landmark Files" {.land .vtk}} 
+		{"All Files" {*}}}
+	} elseif { [ string match -nocase "*electrode*" $a ] > 0 } {
+	    set valuerange { 
+		{"Electrode Grid Files" {.mgrid}} 
+		{"All Files" {*}}}
+	} elseif { [ string match -nocase "*textfile*" $a ] > 0 } {
+	    set valuerange { 
+		{"Text Files" {.txt}} 
+		{"All Files" {*}}}
+	} elseif { [ string match -nocase "*datatree*" $a ] > 0 } {
+	    set valuerange { 
+		{"XMLTree Files" { .xmltree  .tre .msb}}
+		{"All Files" {*}}}
+	} elseif { [ string match -nocase "*allfiles*" $a ] > 0 } {
+	    set valuerange { 
+		{"All Files" {*}}}
+	} else {
+	    set valuerange "{ $a }"
+	}
+
+	return
+    }
+
+    if { $optiontype != "real" && $optiontype != "integer" } {
+	set valuerange $a
+	return
+    }
+    if { [llength $a ] < 2 } { return 0}
+    set minv [ lindex $a 0 ]
+    set maxv [ lindex $a 1 ]
+    if { $maxv < $minv } {
+	set maxv $minv
+	set minv [ lindex $a 1 ]
+    }
+
+    set valuerange [ list $minv $maxv ]
+
+    if { $valuerangewidget !=0 } {
+	$valuerangewidget configure -from $minv -to $maxv
+    }
+    
+    if { $thisparam($this,value) < $minv } {
+	set thisparam($this,value) $minv
+    } elseif { $thisparam($this,value) > $maxv } {
+	set thisparam($this,value) $maxv
+    }
+
+    return $valuerange
+}
+# --------------------------------------------------------------------------------------
+#           GUI Stuff
+# --------------------------------------------------------------------------------------
+
+itcl::body bis_option::CreateGUIElement { parentwidget { callback "" } } {
+
+    set callbackfunction $callback
+    frame $parentwidget
+
+    switch $optiontype {
+	integer { set f [ $this CreateGUIElementRange $parentwidget.lab ] }
+	real    { set f [ $this CreateGUIElementRange $parentwidget.lab ] }
+	listofvalues { set f [ $this CreateGUIElementList $parentwidget.lab ] }
+	multiplevalues { set f [ $this CreateGUIElementMultiple $parentwidget.lab ] }
+	boolean { set f [ $this CreateGUIElementBoolean $parentwidget.lab ] }
+	filename { set f [ $this CreateGUIElementFilename $parentwidget.lab ] }
+	comment { set f [ $this CreateGUIElementComment $parentwidget.lab ] }
+	default { set f [ $this CreateGUIElementString $parentwidget.lab ] }
+    }
+
+    eval "button $parentwidget.2 -text \"?\" -command { $this GUIQuickHelp }"
+#    if { $optiontype != "comment" } {
+	pack $parentwidget.2 -side right -padx 0 -expand false
+#    }
+    pack $f -side left -expand true -fill x
+    set helpbutton $parentwidget.2
+
+
+    set basewidget $parentwidget
+    return $parentwidget
+}
+
+itcl::body bis_option::UpdateFromGUI { } {
+    $this GUICallbackFunction 
+}
+
+itcl::body bis_option::GUIQuickHelp {  } {
+
+    if { $optiontype == "comment"  } {
+	tk_messageBox -type ok -message "$description \n  [  $this GetDefaultValue ]\n[ $this GetValueRange ]" -title "Quick Help -$commandswitch" -icon info
+    } elseif { $helpmessage == "default" } {
+	tk_messageBox -type ok -message "$description\n(default = [  $this GetDefaultValue ])\n(allowed = [ $this GetValueRange ])" -title "Quick Help -$commandswitch" -icon info
+    } else {
+	tk_messageBox -type ok -message "$helpmessage" -title "Quick Help" -icon info	
+    }
+}
+
+itcl::body bis_option::GUICallbackFunction {  } {
+
+    if { $callbackfunction != "" && $callbackfunction !=0 } {
+	set cmd "$callbackfunction $this $thisparam($this,value) "
+	eval $cmd 
+    }
+}
+
+itcl::body bis_option::CreateGUIElementList { parentwidget  } {
+
+    set base [ [ iwidgets::labeledwidget $parentwidget  -labeltext "${shortdescription}:"  ] childsite ]
+
+    
+
+    set n [ llength $valuerange ]
+    if { $optiontypehint == "radiobuttons" } {
+	for { set i 0 } { $i < $n } { incr i }  {
+	    set v [ lindex $valuerange $i ]
+	    radiobutton $base.$i -variable [itcl::scope thisparam($this,value)] -value $v -text $v 
+	    eval "$base.$i configure -command { $this GUICallbackFunction }"
+	    pack $base.$i -side left
+	}
+    } else {
+	eval "tk_optionMenu ${base}.opt [ itcl::scope thisparam($this,value) ] $valuerange"
+	pack ${base}.opt  -side left -expand t -fill x
+
+	for { set i 0 } { $i < $n } { incr i } { 
+	    eval "$base.opt.menu entryconfigure $i -command { $this GUICallbackFunction }"
+	}
+    }
+    return $parentwidget
+}
+
+
+# ------------------------------------------------------------------------
+itcl::body bis_option::CreateGUIElementMultiple { base  } {
+
+#    puts stderr "In multiple $shortdescription base=$base"
+    set valuewidget  $base
+    iwidgets::entryfield $base -labeltext "${shortdescription}:"   -textvariable [ itcl::scope thisparam($this,value) ] -relief sunken  
+    set labeledwidget $base
+
+ #   if { $optionguiwidth > 0 } { 
+#	$base configure -width $optionguiwidth
+#    }
+    eval "bind [ $base component entry ] <KeyRelease-Return> { $this GUICallbackFunction }"
+
+    set cs [ $base childsite ]
+    eval "button $cs.2 -text \"Select\" -command { $this GetMultipleSelection }"
+    pack $cs.2 -side right 
+    return $base
+}
+# -----------------------------------------------------------------------------------------------------
+	
+itcl::body bis_option::CreateGUIElementRange { parentwidget  } {
+
+    # here check hint ... triplescale, scale, or entrywidget (default)
+
+    set minv   [ lindex $valuerange 0 ]
+    set maxv   [ lindex $valuerange 1 ]
+
+    if { $minv < [ expr 0.05*$maxv ]  && $minv >= 0.0 && $maxv < 10.1 } {
+	set resol [ expr 0.025* $maxv ]
+	set interv [ expr 0.001*$maxv ]
+    } else {
+	set resol  [ expr 0.01*($maxv-$minv) ]
+	set interv [ expr 0.001*($maxv-$minv) ]
+    }
+
+    if { $optiontype == "integer" } {
+	set interv [ expr int($interv) ]
+	if { $interv < 1 } {
+	    set interv 1
+	}
+	set minv [ expr int($minv) ]
+	set maxv [ expr int($maxv) ]
+	if { $resol <1 } {
+	    set resol 1
+	}
+    } elseif { $optiontype == "real" } {
+
+    }
+
+    switch $optiontypehint  {
+	"triplescale" {
+	    set base [ [ iwidgets::labeledwidget $parentwidget  -labeltext "${shortdescription}:"  ] childsite ]
+	    scale  $base.scale -orient horizontal  -from $minv -to $maxv -resolution $resol \
+		-showvalue 1  -variable [ itcl::scope thisparam($this,value) ]
+	    set labeledwidget $parentwidget
+
+	    if { $optionguiwidth < 0 } { set optionguiwidth 100  }
+	    $base.scale configure -length $optionguiwidth
+
+	    eval "bind $base.scale <ButtonRelease> { $this GUICallbackFunction }"
+
+	    if { $minv == $maxv } {
+		set entw 3 
+	    } else {
+		set entw [ expr int((log(($maxv-$minv)/$resol))/log(10)) + 3 ]
+	    }
+	    
+	    if { $entw <3 } { 
+		set entw  3
+	    }
+
+	    entry  $base.en  -textvariable [ itcl::scope thisparam($this,value) ] -relief sunken -width $entw
+	    set valuewidget  $base.en
+	    eval "bind $base.en <KeyRelease-Return> {$this GUICallbackFunction }"
+	    pack $base.en    -side right -expand f
+	    pack $base.scale -side left -expand t -fill x
+	}
+	"scale" {
+	    set base [ [ iwidgets::labeledwidget $parentwidget  -labeltext "${shortdescription}:"  ] childsite ]
+
+	    scale  $base.scale -orient horizontal  -from $minv -to $maxv -resolution $resol \
+		-showvalue 1  -variable [ itcl::scope thisparam($this,value) ]
+	    if { $optionguiwidth < 0 } { set optionguiwidth 100  }
+	    $base.scale configure -length $optionguiwidth
+	    set valuewidget  $base.scale
+	    set valuerangewidget $base.scale
+	    eval "bind $base.scale <ButtonRelease> { $this GUICallbackFunction }"
+	    pack $base.scale -side left -expand t -fill x
+	}
+	"default" {
+	    iwidgets::entryfield $parentwidget -labeltext "${shortdescription}:"  -validate $optiontype -textvariable [ itcl::scope thisparam($this,value) ] -relief sunken 
+	    set valuewidget  $parentwidget
+	    if { $optionguiwidth < 0 } { 
+		catch {		set optionguiwidth [ expr int((log(($maxv-$minv)/$resol))/log(10)) + 3 ]   }
+		if { $optionguiwidth < 3 } {
+		    set optionguiwidth 3
+		}
+	    }
+
+	    $parentwidget configure -width $optionguiwidth
+	    eval "bind [ $parentwidget component entry ] <KeyRelease-Return> { $this GUICallbackFunction }"
+	    #eval "bind [ $parentwidget component entry ] <Leave> { $this GUICallbackFunction }"
+
+	}
+    }
+
+
+
+    return $parentwidget
+}
+
+itcl::body bis_option::CreateGUIElementString { base  } {
+    iwidgets::entryfield $base -labeltext "${shortdescription}:"   -textvariable [ itcl::scope thisparam($this,value) ] -relief sunken 
+
+    set valuewidget  $base
+    if { $optionguiwidth > 0 } { 
+	$base configure -width $optionguiwidth
+    }
+    eval "bind [ $base component entry ] <KeyRelease-Return> { $this GUICallbackFunction }"
+    return $base
+}
+
+itcl::body bis_option::CreateGUIElementComment { base  } {
+
+    set basea [ [ iwidgets::labeledwidget $base  -labeltext ""  ] childsite ]
+    #entry $basea.o -textvariable [ itcl::scope thisparam($this,value)] -relief raised -state disabled -background black -foreground white
+    set thisparam($this,textbox) [ text $basea.o -bg black -fg white ]
+
+
+    if { $optionguiwidth > 0 } { 
+	#	puts stderr "Option width=$optionguiwidth"
+	if { $optionguiwidth <= 25 } {
+	    $thisparam($this,textbox) configure -width 25 -height 1
+	} else {
+	    set  numlines [ expr $optionguiwidth / 25 ]
+	    $thisparam($this,textbox) configure -width 25 -height [ expr $numlines +1 ] -wrap word
+	}
+    } else {
+	$thisparam($this,textbox) configure -width 25 -height 0
+	#-height 1 
+    }
+    $thisparam($this,textbox) insert end $thisparam($this,value)
+    $thisparam($this,textbox) configure -state disabled
+    pack $basea.o -side right -expand true -fill both
+    set labelwidget $basea.o
+    return $base
+}
+
+itcl::body bis_option::CreateGUIElementFilename { base  } {
+    set valuewidget  $base
+    iwidgets::entryfield $base -labeltext "${shortdescription}:"   -textvariable [ itcl::scope thisparam($this,value) ] -relief sunken  
+    set labeledwidget $base
+
+    if { $optionguiwidth > 0 } { 
+	$base configure -width $optionguiwidth
+    }
+    eval "bind [ $base component entry ] <KeyRelease-Return> { $this GUICallbackFunction }"
+
+    set cs [ $base childsite ]
+    eval "button $cs.2 -text \"...\" -command { $this GetFileName }"
+
+    pack $cs.2 -side right 
+    return $base
+}
+
+
+
+itcl::body bis_option::CreateGUIElementBoolean { base  } {
+
+    iwidgets::labeledwidget $base  -labeltext "${shortdescription}:" 
+    set labeledwidget $base
+    set w [ $base childsite ]
+    set valuewidget  $w.0
+    checkbutton $w.0 -variable [itcl::scope thisparam($this,value)] 
+    eval "$w.0 configure -command { $this GUICallbackFunction }"
+    pack $w.0 -side left
+
+    return $base
+}
+
+
+itcl::body bis_option::GetFileName { } {
+    
+    set doinitial 0
+    set initial $thisparam($this,value)
+    if { [ string length $initial ] > 1 } {
+	set f2tail [ file tail $initial ]
+	set f2path [ file dirname $initial ]
+	set doinitial 1
+    }
+
+    set mode 0
+    if { $optiontypehint == "directory" } {
+	# directory 
+	if { $doinitial > 0 } {
+	    set dirname  [tk_chooseDirectory -title "Select Directory ${shortdescription}" -initialdir $initial ]
+	} else {
+	    set dirname  [tk_chooseDirectory -title "Select Directory ${shortdescription}" ]
+	}
+	if { [ string length $dirname ] < 1 } { return 0 }
+	set thisparam($this,value) $dirname
+	
+    } elseif { $optiontypehint == "writefile" } {
+	if { $doinitial > 0 } {
+	    set fname  [tk_getSaveFile -title "Select Filename for $description" -filetypes $valuerange -initialfile $f2tail -initialdir $f2path ]
+	} else {
+	    set fname  [tk_getSaveFile -title "Select Filename for $description" -filetypes $valuerange ]
+	}
+	if { [ string length $fname ] < 1 } { return 0 }
+	set thisparam($this,value) $fname
+
+    } else { 
+	# filename to read
+	
+	if { $doinitial > 0 } {
+	    set fname  [tk_getOpenFile -title "Select Filename for $description" -filetypes $valuerange -initialfile $f2tail -initialdir $f2path ]
+	} else {
+	    set fname  [tk_getOpenFile -title "Select Filename for $description" -filetypes $valuerange ]
+	}
+	if { [ string length $fname ] < 1 } { return 0 }
+	set thisparam($this,value) $fname
+    }
+
+    $this GUICallbackFunction
+}
+
+# ---------------------------------------------------------------------------------------------------------------------------------------
+itcl::body bis_option::GetMultipleSelection { } {
+
+    if { $thisparam($this,selectiondialog) == 0 } {
+	set tb [ iwidgets::dialog ${basewidget}.lab.selectiondialog \
+		     -title "Select Items for $shortdescription" \
+		     -modality application ]
+
+	set n [ llength $valuerange ]
+	$tb configure -height [ expr 80+20*$n ]  -width 300
+	
+	set cs [ $tb childsite ]
+	set listbox [ iwidgets::scrolledlistbox $cs.a -vscrollmode dynamic -hscrollmode none -selectmode multiple -labelpos nw -visibleitems 15x10 ]
+	pack $cs.a -side top -expand true -fill both
+	set thisparam($this,listbox) $listbox
+	eval "$tb buttonconfigure Apply -text \"Select All\" -command { $listbox selection set 0 end }"
+	eval "$tb buttonconfigure Cancel  -text \"Clear All\" -command { $listbox selection clear 0 end }"
+	eval "$tb buttonconfigure Help  -text \"Close\" -command { $tb deactivate }" 
+	set thisparam($this,selectiondialog) $tb
+	update idletasks
+    }
+
+    $thisparam($this,listbox) delete 0 end
+    $thisparam($this,listbox) selection clear 0 end
+    for { set i 0 } { $i < [ llength $valuerange ] } { incr i } {
+	$thisparam($this,listbox) insert end [ lindex $valuerange $i ]
+    }
+	
+
+    for { set i 0 } { $i < [ llength $valuerange ] } { incr i } {
+	set v [ lindex $valuerange $i ]
+	if { [ lsearch -exact $thisparam($this,value) $v ] >=0 } {
+	    $thisparam($this,listbox) selection set $i $i
+	}
+    }
+
+    
+    set a  [$thisparam($this,selectiondialog) activate ] 
+
+    if { $a > 0 } {
+	set a [ [ $thisparam($this,listbox) component listbox ] curselection ]
+	set thisparam($this,value) ""
+	for { set i 0 } { $i < [ llength $a ] } { incr i } {
+	    lappend thisparam($this,value) [  lindex $valuerange [ lindex $a $i ]]
+	}
+
+	$this GUICallbackFunction
+    }
+}
+
+# ---------------------------------------------------------------------------------------------------------------------------------------
+proc myprint { args } {
+
+    puts stderr "$args"
+}
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+
+
+    # this is essentially the main function
+    wm withdraw .
+    toplevel .top 
+    wm title .top "Test Option"
+    wm geometry .top 500x500
+
+
+    set opt1 [ [ bis_option \#auto ] GetThisPointer ]
+    $opt1 SetAllProperties "-r" "Registration Resolution" "Resolution" real 2.0 { 1.0 5.0 } 100
+    $opt1 SetOptionType real triplescale
+    $opt1 CreateGUIElement .top.1 { myprint }
+    pack .top.1 -side top -expand t -fill x
+    $opt1 SetValueRange { 1.0 4.0 }
+
+
+    set opt2 [ [ bis_option \#auto ] GetThisPointer ]
+    $opt2 SetAllProperties "-norm" "Normalize Intensities" "AutoNorm" "boolean" 1 { 0 1 } 101
+    $opt2 CreateGUIElement .top.2 { myprint}
+    pack .top.2 -side top -expand t -fill x
+
+
+    set opt3 [ [ bis_option \#auto ] GetThisPointer ]
+    $opt3 SetAllProperties "-metric" "Intensity Metric" "Metric" "listofvalues" NMI { CC MI NMI } 102
+    $opt3 CreateGUIElement .top.3 { myprint}
+    $opt3 SetValueRange { NMI CC }
+    pack .top.3 -side top -expand t -fill x
+    
+
+    set opt4 [ [ bis_option \#auto ] GetThisPointer ]
+    $opt4 SetAllProperties "-metric" "Long Comment" "Comment" "string" "Registration" {} 102
+    $opt4 CreateGUIElement .top.4 { myprint}
+    pack .top.4 -side top -expand t -fill x
+
+    set opt5 [ [ bis_option \#auto ] GetThisPointer ]
+    $opt5 SetAllProperties "-r2" "Registration Resolution" "Resolution" real 2.0 { 1.0 5.0 } 100
+    $opt5 SetOptionType real scale
+    $opt5 CreateGUIElement .top.5 { myprint }
+    pack .top.5 -side top -expand t -fill x
+
+
+    set opt6 [ [ bis_option \#auto ] GetThisPointer ]
+    $opt6 SetAllProperties "-r2" "Number of Levels" "Levels" integer 2 { 1 6 } 100
+    $opt6 configure -optionguiwidth 2
+    $opt6 SetOptionType integer default
+    $opt6 CreateGUIElement .top.6 { myprint }
+    pack .top.6 -side top -expand t -fill x
+
+    set opt7 [ [ bis_option \#auto ] GetThisPointer ]
+    $opt7 SetAllProperties "-orientation" "Image Orientation" "Orientation" "listofvalues" Axial { Axial Coronal Sagittal } 102
+    $opt7 SetOptionType listofvalues radiobuttons
+    $opt7 CreateGUIElement .top.7 
+    pack .top.7 -side top -expand t -fill x
+
+    set opt77 [ [ bis_option \#auto ] GetThisPointer ]
+    $opt77 SetAllProperties "-orientation" "Image Orientation" "Orientation" { multiplevalues } Red { Red Green Blue Yellow Brown } 120
+    $opt77 CreateGUIElement .top.77  { myprint }
+    pack .top.77 -side top -expand t -fill x
+
+
+set f 0
+    if { $f == 1 } {
+    set opt8 [ [ bis_option \#auto ] GetThisPointer ]
+    $opt8 SetAllProperties "-setupfile" "Setup File Name" "Setup:" "filename" "test.msb" { Setup Files {*.msb} } 102
+    $opt8 SetOptionType filename readfile
+    $opt8 CreateGUIElement .top.8
+    pack .top.8 -side top -expand t -fill x
+
+    set opt81 [ [ bis_option \#auto ] GetThisPointer ]
+    $opt81 SetAllProperties "-input" "Input Image Name" "Input:" "filename" "test.nii.gz" { pxitclimage } 102
+    $opt81 SetOptionType filename readfile
+    $opt81 CreateGUIElement .top.81
+    pack .top.81 -side top -expand t -fill x
+
+    set opt82 [ [ bis_option \#auto ] GetThisPointer ]
+    $opt82 SetAllProperties "-output" "Output Image Name Stem" "OutStem:" "filename" "test.matr" { pxitcltransform } 102
+    $opt82 SetOptionType filename directory
+    $opt82 CreateGUIElement .top.82
+    pack .top.82 -side top -expand t -fill x
+
+ 
+    }
+
+
+    
+
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_optiondialog.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_optiondialog.tcl
new file mode 100644
index 0000000..287dbd6
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_optiondialog.tcl
@@ -0,0 +1,495 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    lappend auto_path [ file dirname [ info script ]]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+}
+
+
+package provide bis_optiondialog 1.0
+package require  Itcl 3.2
+package require bis_option 1.0
+package require bis_common 1.0
+package require bis_algorithm 1.0
+package require Iwidgets 
+package require pxitclobject 1.0
+package require bis_datamanager 1.0
+
+
+itcl::class bis_optiondialog {
+
+    #
+    #public
+    #
+
+    constructor { } { }
+    destructor { $this CleanAll }
+
+    # This Pointer
+    public method GetThisPointer { } { return $this }
+
+    # ------------------------------------------
+    public method CreateGUI { base { dialog 1 } {  optionslist -1 }  }
+    public method InitializeAsXMLDataElement { datamanager }
+    public method SetCallback { clb } { set callbackfunction $clb }
+    public method SetOptionsFromXMLDataElement  { eml }
+    public method StoreOptionsInXMLDataElement  {  }
+
+    # -----------------------------------------
+    public method ShowWindow { }
+    public method HideWindow { }
+    public method SetTitle   { ttl }
+    public method SetIcon   { ico }
+
+    # -----------------------------------------------------------
+    # vtk-like interface to Modify/access invidual option and inputs outputs
+    # -----------------------------------------------------------
+    public method SetOptionValue  { optionname value }
+    public method SetOptionRange  { optionname value }
+    public method GetOptionValue  { optionname }
+    public method GetOption  { optionname }
+    public method GetXMLElement   { } { return $xmlelement }
+    public method GetBaseWidget   { } { return $basewidget }
+    public method GetButtonBar   { } { return $buttonbar }
+    # Enable/Disable Options
+    # ----------------------
+    public method DisableOption   { optionname } { return [ $this SetOptionStatus $optionname 0 ] }
+    public method EnableOption    { optionname } { return [ $this SetOptionStatus $optionname 1 ] }
+    public method SetOptionStatus { optionname opt } 
+
+    #Internal tcl array for input files 
+    protected variable OptionsArray
+    protected variable StandardOptionsList ""
+    protected variable AdvancedOptionsList ""
+    protected variable options ""
+    protected variable basewidget 0
+    protected variable buttonbar  0
+
+    # Status array one per option
+    protected variable optionstatus
+    protected variable isdialog 0
+    protected variable title "Options Dialog"
+    protected variable iconname 0
+
+    # XML Stuff
+    protected variable xmlelement 0
+    protected variable callbackfunction 0
+    public    method UpdateValues { args }
+
+    public method   SetStateOfWidget { widget mode }
+
+
+
+    #set until execution
+    protected method   CreateOptionsArray { }
+};
+
+# -----------------------------------------------------------
+#  VTK Like interface to options and outputs
+# -----------------------------------------------------------
+itcl::body bis_optiondialog::SetOptionValue { optionname value } {
+
+    $OptionsArray($optionname) SetValue $value
+}
+
+itcl::body bis_optiondialog::SetOptionRange { optionname value } {
+    $OptionsArray($optionname) SetValueRange $value
+}
+
+itcl::body bis_optiondialog::GetOptionValue { optionname } {
+
+    return [ $OptionsArray($optionname) GetValue ]
+}
+
+itcl::body bis_optiondialog::GetOption { optionname } {
+
+    return $OptionsArray($optionname) 
+}
+
+
+
+#----------------------------------------------------
+#Generate InputsArray,OutputsArray, and OptionsArray
+#----------------------------------------------------
+itcl::body bis_optiondialog::CreateOptionsArray { } {
+
+    array set OptionsArray {}
+    set nlist ""
+    for { set i 0 } { $i < [llength $options  ] } { incr i } {
+	set lst [ lindex $options $i]
+	set name [ lindex $lst  0]
+
+	if { $name == "out" || $name == "inp" || $name == "i" || $name =="o" } {
+	    puts stderr "Bad Option Name \"out\" -- this is reserved"
+	    exit
+	}
+
+	if { [ regexp "out\[0-9\]+" $name  ] > 0 } {
+	    puts stderr "Bad Option Name $name -- this matches a  reserved name"
+	    exit
+	}
+
+	if { [ regexp "inp\[0-9\]+" $name  ] > 0 } {
+	    puts stderr "Bad Option Name $name -- this matches a  reserved name"
+	    exit
+	}
+
+	if { [ llength $lst ] ==7 } {
+	    set p [ lindex $lst 6 ]
+	    if { $p < 0 } {
+		set p [ expr abs($p) + 1000000 ]
+	    }
+	    lappend nlist [ list $i $p $name ]
+	}
+    }
+
+    set pluspr    0
+    set minuspr -1
+
+    set StandardOptionsList ""
+    set AdvancedOptionsList ""
+
+    set nlist [ lsort -integer  -index 1 $nlist ]
+    for { set i 0 } { $i < [ llength $nlist ] } { incr i } {
+	
+	set ind [ lindex [ lindex $nlist $i ] 0 ]
+	set lst [ lindex $options $ind ]
+	set p   [ lindex $lst 6 ]
+
+	set name [ lindex $lst 0 ]
+	if { $p >= 0 } {
+	    lset lst 6 $pluspr; incr pluspr
+	    lappend StandardOptionsList $name
+	} else {
+	    lappend AdvancedOptionsList $name
+	    if { $p > -10000 } {
+		lset lst 6 $minuspr; set minuspr [ expr $minuspr -1 ]
+	    }
+	}
+
+	set elem [ [ bis_option \#auto ] GetThisPointer ]
+	set OptionsArray($name) $elem
+	$OptionsArray($name) SetAllPropertiesAsList $lst
+
+    }
+}
+
+# ------------------------------------------
+#
+# Easy Stuff !
+#
+# -----------------------------------------
+itcl::body bis_optiondialog::ShowWindow { } {
+    
+    if { $basewidget !=0 && $isdialog > 0 } {
+	if { [ winfo ismapped $basewidget ] == 1 } {
+	    raise $basewidget
+	} else {
+	    wm deiconify $basewidget
+	}
+    }
+} 
+
+itcl::body bis_optiondialog::HideWindow { } {
+    catch { wm withdraw $basewidget }
+}
+
+itcl::body bis_optiondialog::SetTitle   { ttl } {
+    if { $basewidget !=0 && $isdialog > 0 } {
+	wm title $basewidget $ttl
+    }
+    
+}
+
+itcl::body bis_optiondialog::SetIcon   { ico } {
+    set iconname $icon
+}
+
+itcl::body bis_optiondialog::SetOptionStatus { optionname opt }  {
+
+#    puts stderr "Setting $optionname = $opt"
+    set optionstatus($optionname) $opt
+    if { $basewidget ==0 } {
+	return
+    }
+
+    set b [ $OptionsArray($optionname) GetBaseWidget ]
+    if { $optionstatus($optionname) > 0 } {
+	pack $b -side top -expand false -fill x
+    } else {
+	pack forget $b
+    }
+}
+
+
+
+# ----------------------------------------------------------------------------------------
+itcl::body bis_optiondialog::InitializeAsXMLDataElement { datamanager } {
+
+    set tmp [ $datamanager GetAttributesList ]
+    set n [ llength $tmp ]
+    set alloptions ""
+    for { set i 0 } { $i < $n } { incr i } {
+	lappend alloptions [ lindex [ lindex $tmp $i ] 0 ]
+    }
+    #    puts $alloptions
+
+
+    set fnamelist  [ $datamanager GetFilenamesList  ]
+    set excludelist [ concat [  $datamanager GetAttributesZeroList ] [ $datamanager GetAttributeGUIList ] ]
+    set booleanlist [ $datamanager GetAttributeBooleanList ]
+
+    set n [ llength $alloptions ]
+    set options ""
+    set priority 1
+    for { set i 0 } { $i < $n } { incr i } {
+	
+	set att [ lindex $alloptions $i ]
+	set ind [ lsearch -exact $excludelist $att ]
+	set dobool [ expr [ lsearch -exact $booleanlist $att ] > -1 ]
+	set isfname [ expr [ lsearch -exact $fnamelist $att ] > -1 ]
+	if { $ind == -1 } {
+	    if { $dobool > 0 } {
+		lappend options [ list  $att $att $att boolean 0 { 0 1 }  $priority ]
+	    } elseif { $isfname > 0 } {
+		if { $att == "Filename" } {
+		    lappend options [ list $att $att $att { filename readfile } ""  pxitclimage  $priority ]
+		} else {
+		    lappend options [ list $att $att $att { filename readfile } ""  pxitcltransform  $priority ]
+		}
+	    } else {
+		lappend options [ list $att $att $att string "" "" $priority ]
+	    }
+	    incr priority
+	}
+    }
+}
+# ----------------------------------------------------------------------------------------
+itcl::body bis_optiondialog::UpdateValues { args } {
+
+    set changed ""
+    if { $xmlelement != 0 } {
+	set changed [ $this StoreOptionsInXMLDataElement ]
+    }
+
+#    puts stderr "Changed in updvalues = $changed"
+
+    if { $callbackfunction != "" && $callbackfunction !=0 } {
+	set cmd "$callbackfunction $this $changed"
+#	puts stderr "Calling callback $cmd"
+	eval $cmd 
+    }
+    return $changed
+}
+# ----------------------------------------------------------------------------------------
+itcl::body bis_optiondialog::CreateGUI { base { dialog 1 } {  optionslist -1 }  } {
+
+    if { $options == "" && $optionslist == -1 } {
+	puts stderr "Options undefined"
+	return 0
+    }
+
+    if { $optionslist != -1 } {
+	set options $optionslist
+    }
+
+    #    puts stderr "options=$options"
+
+    $this CreateOptionsArray
+    
+    set basewidget $base.[ pxvtable::vnewobj ]
+    if { $dialog > 0 } {
+#	puts stderr "Creating toplevel $basewidget"
+	toplevel $basewidget
+	wm withdraw $basewidget
+	eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget  }"
+	wm geometry $basewidget 500x420
+	set isdialog 1
+    } else {
+	frame $basewidget
+	set isdialog 0
+	pack $basewidget -side top -expand true -fill both
+    }
+
+    
+
+    set bbar [ iwidgets::buttonbox $basewidget.b -orient horizontal ]
+    pack $bbar -side bottom -expand true -fill x
+
+    set buttonbar $bbar
+#    $inputbbox add add -text "Add..." -command [ itcl::code $this addinput ]
+#    $inputbbox add remove -text "Remove" -command [ itcl::code $this removeinput ] -state disabled
+#    $inputbbox add display -text "Display" -command [ itcl::code $this displayinput ] -state disabled   
+
+#    set bbar [ frame $basewidget.b ]
+
+    $bbar add update -text "Update" -command [ itcl::code  $this UpdateValues ]
+    
+    if { $isdialog > 0 } {
+	$bbar add close -text "Close Window" -command [ itcl::code  $this HideWindow ]
+    }
+#    pack $bbar.l -side left -expand false 
+
+    set w [ iwidgets::labeledframe $basewidget.sf  -labeltext "" ]
+    set nlist [ concat $StandardOptionsList $AdvancedOptionsList ]
+    set elemlist ""
+    pack $w -side top -expand true -fill both
+    set  wc [ $w childsite ]
+
+#    puts stderr "nlist=$nlist"
+    set alist ""
+    for { set i 0 } { $i < [ llength $nlist ] } { incr i } {
+
+	set name  [ lindex $nlist $i ]
+	set opt $OptionsArray($name)
+	set w2  $wc.[pxvtable::vnewobj ] 
+	#puts stderr "Creating $name $w2"
+	$opt configure -optionguiwidth 25
+	$opt CreateGUIElement $w2 ""
+	$opt HideHelpButton
+	eval "$opt  SetGUICallbackFunction { $this UpdateValues } "
+	pack $w2 -side top -expand true -fill x
+	lappend alist  $w2.lab
+    }
+
+    eval "iwidgets::Labeledwidget::alignlabels $alist"
+
+    return $basewidget
+}
+
+
+itcl::body bis_optiondialog::SetOptionsFromXMLDataElement  { eml } {
+    
+    set xmlelement $eml
+    set names [array names OptionsArray]
+    if { $names == "" } { return 0 }
+
+    foreach n $names {
+	set v [ $xmlelement GetAttribute $n ]
+	$OptionsArray($n) SetValue $v
+    }
+
+
+    set v [ $xmlelement GetAttribute Type ]
+    set n Filename
+    switch -exact $v { 
+	"Image"   { $OptionsArray($n) SetValueRange image }
+	"Surface" { $OptionsArray($n) SetValueRange surface }
+	"Landmarks" { $OptionsArray($n) SetValueRange landmarks }
+	"Electrodes" { $OptionsArray($n) SetValueRange electrode }
+    } 
+}
+
+itcl::body bis_optiondialog::StoreOptionsInXMLDataElement  { } {
+    set names [array names OptionsArray]
+
+    set changed ""
+
+    foreach n $names {
+	set v [ $OptionsArray($n) GetValue ]
+	set a [ string first " " $v ]
+	if { $a == -1 } {
+	    set ln [ expr [ string length $v ] -1 ]
+	    if { [ string range $v 0 0 ] == "\"" &&
+		 [ string range $v $ln $ln ] == "\"" } {
+		set v [ string range $v 1 [ expr $ln -1 ] ]
+	    }
+	}
+
+	set ind [ string first "Filename" $n ]
+	set v1 [ $xmlelement GetAttribute $n ]
+	if { $ind > -1 &&  [ file tail $v ] == 0 } {
+	    set v 0
+	}
+	if { $v != $v1 } {
+	    lappend changed $n
+	    $xmlelement SetAttribute $n $v
+#	    puts stderr "Mapping [ $xmlelement GetName ] $n $v1 -> $v"
+	}
+    }
+    return $changed
+}
+
+
+::itcl::body bis_optiondialog::SetStateOfWidget { widget state } {
+    
+    set children [ winfo children $widget ]
+    set a [ llength $children ]
+    if { $a == 0 } {
+	set ok 0
+	catch { $widget configure -state $state ; set ok 1 }
+	if { $ok == 0 } {
+	    catch {
+		set tl [ file extension $widget ]
+		if { $tl == ".menu" } {
+		    set n [ $widget  index end ]
+		    for { set i 0 } { $i <= $n } { incr i } {
+			$widget entryconfigure $i -state $state	
+		    }
+		}
+	    }
+	}
+	return 0
+    } else {
+	for { set i 0 } { $i < $a } { incr i } {
+	    SetStateOfWidget [ lindex $children $i ] $state
+	}
+    }
+}
+
+
+proc bis_optiondialog_callback { args } {
+    puts stderr "args = $args"
+}
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    frame .bot; pack .bot -side top -expand true
+    set alg [ bis_datamanager \#auto ]
+    $alg ImportMSBFile [ lindex $argv 0 ]
+    
+    set opt [ bis_optiondialog \#auto ]
+    $opt InitializeAsXMLDataElement $alg
+    $opt SetCallback bis_optiondialog_callback
+    set b [ $opt CreateGUI .bot  ]
+    $opt ShowWindow
+    wm withdraw . 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_piecewiseimagemap.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_piecewiseimagemap.tcl
new file mode 100755
index 0000000..26a826a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_piecewiseimagemap.tcl
@@ -0,0 +1,240 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_piecewiseimagemap 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+itcl::class bis_piecewiseimagemap {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "PiecewiseMap" }
+    public method UpdateInputsFromContainer { }
+
+    # Number of knots
+    protected variable numknots 8
+
+    # Improve GUI Somewhat
+    protected method PackOptionsGUIInterface { lst }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+
+itcl::body bis_piecewiseimagemap::Initialize { } {
+
+    PrintDebug "bis_piecewiseimagemap::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ type "output image type.Specify one of  Default (same as input) UnsignedChar Short Float Double" "Output Type"  listofvalues  Default { Default UnsignedChar Float Double Short }  50 }
+    }
+
+    set count 1
+    for { set i 1 } { $i <= $numknots } { incr i } {
+
+	lappend options [ list on$i  "enable knot $i"  "Enable $i"  { boolean }  0 { 0 1 }  $count ] ; incr count
+	lappend options [ list x$i   "input value for knot  $i"  "X$i"  { real default }  0.0 { -10000000000 1000000000 }  $count ]; incr count
+	lappend options [ list y$i   "output value for knot $i" "Y$i"   { real default }  0.0 { -10000000000 1000000000 }  $count ]; incr count
+    }
+
+    set defaultsuffix { "_mt" }
+    
+    set scriptname bis_piecewiseimagemap
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Perfoms piecewise mapping of an image using a linear spline with prescribed knots."
+    set description2 " "
+    set backwardcompatibility "Reimplemented from code in pxitcloverlaytool.tcl"
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# ------------------------------------------------------------------------------
+
+itcl::body bis_piecewiseimagemap::UpdateInputsFromContainer { } {
+
+    bis_imagetoimagealgorithm::UpdateInputsFromContainer 
+
+    # This happens when image has changed 
+    set currentimage  [ $InputsArray(input_image) GetObject ]
+
+    set r [ [ $currentimage GetImage ] GetScalarRange ]
+    set rmin [ lindex $r 0 ]
+    set rmax [ lindex $r 1 ]
+    if { $rmax == $rmin } {
+	set rmax [ expr $rmin +1 ]
+    }
+
+    for { set i 1 } { $i <= $numknots } { incr i } {
+	$OptionsArray(x$i)  SetValueRange [ list $rmin $rmax ]
+    }
+}
+
+# ------------------------------------------------------------------------------
+itcl::body bis_piecewiseimagemap::PackOptionsGUIInterface { lst } { 
+
+
+    set n [ llength $lst ]
+    PrintDebug "\n\n Length of list = $n"
+
+    for { set tab 0 } { $tab <= 1 } { incr tab } {
+	set wlist ""
+	for { set i 0 } { $i < $n } { incr i } {
+	    
+		set pair [ lindex $lst $i ]
+		set ind  [ lindex $pair 1 ]
+		if { $ind == $tab } {
+		    lappend wlist $pair
+		}
+	    }
+
+	set wlist [ lsort -integer  -index 0 $wlist ]
+
+
+	if { $tab == 1 } {
+	    for { set j 0 } { $j < [ llength $wlist ] } { incr j } {
+		set pair [ lindex $wlist $j ]
+		set name [ lindex $pair 2 ]
+		set widg [ lindex $pair 3 ]
+		pack $widg -side top -expand false -fill x -padx 1
+	    }
+	} else {
+	    # Custom Pack
+
+	    for { set l 1 } { $l <= $numknots } { incr l } {
+		grid  [ $OptionsArray(on$l) GetBaseWidget ]  -row $l -column 0 -padx 0
+		 $OptionsArray(on$l) HideHelpButton
+		grid  [ $OptionsArray(x$l) GetBaseWidget ]  -row $l -column 1 -padx 0
+		$OptionsArray(x$l) HideHelpButton
+		grid  [ $OptionsArray(y$l) GetBaseWidget ]  -row $l -column 2 -padx 0
+		$OptionsArray(y$l) SetHelpMessage "Map x$l -> y$l if enabled"
+	    }
+
+	    grid  [ $OptionsArray(type) GetBaseWidget ] -row [ expr $numknots +1 ] -column 0 -columnspan 3 -padx 0
+
+	    set v  [ file rootname  [ $OptionsArray(type) GetBaseWidget ] ]
+	    grid rowconfigure $v 10 -weight 100
+	    grid columnconfigure $v 10 -weight 100
+
+
+
+
+	}
+    }
+    update idletasks
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_piecewiseimagemap::Execute {  } {
+
+    PrintDebug "bis_piecewiseimagemap::Execute"
+
+    set otype   [ $OptionsArray(type) GetValue ]
+
+    
+    set newmap [ vtkDoubleArray [ pxvtable::vnewobj ]]
+    $newmap SetNumberOfComponents 2
+
+    for { set l 1 } { $l <= $numknots } { incr l } {
+	set enableknot [ $OptionsArray(on$l) GetValue ]
+	if { $enableknot > 0 } {
+	    set x [ $OptionsArray(x$l) GetValue ]
+	    set y [ $OptionsArray(y$l) GetValue ]
+	    $newmap InsertNextTuple2 $x $y
+	}
+    }
+
+    if { [ $newmap GetNumberOfTuples ] < 1 } {
+	$newmap Delete
+	return 0
+    }
+
+    set sh  [ vtkpxImageAlgebra [ pxvtable::vnewobj ]  ]
+    $sh SetInput [ [ $this GetInput ] GetImage ]
+    set ok [  $sh CreateMapArrayFromKnots $newmap ]
+    $newmap Delete
+
+    if { $otype != "Default" } {
+	
+	$sh SetOutputScalarTypeTo$otype
+    }
+    $this SetFilterCallbacks $sh "Multi-Linear Scaling of Image"
+    $sh Update
+    
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $sh GetOutput ]
+    $outimage CopyImageHeader [ [ $this GetInput ] GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    $sh Delete
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_piecewiseimagemap.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_piecewiseimagemap [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_pointbasedregistrationviewer.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_pointbasedregistrationviewer.tcl
new file mode 100644
index 0000000..147d38e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_pointbasedregistrationviewer.tcl
@@ -0,0 +1,229 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_pointbasedregistrationviewer 1.0
+
+itcl::class bis_pointbasedregistrationviewer {
+
+    constructor { } { }
+    public method Initialize { }
+
+    # Custom Viewer for RPM
+    public method CreateViewer { fr }
+    public method GetThisPointer { } { return $this }
+
+    # Protected Variable
+    public method SetAlgorithm { alg } { set algorithm $alg }
+
+    # Callbacks from surfaces
+    public method SetSurfaceMode { sur } 
+    public method ShowSurfaces { { applytransformation 0 } }
+    public method Update { visib rpmfilter } 
+
+
+    public method HasRPMGUI { } { return $has_rpm_gui }
+
+    protected common guiparam
+    protected variable renderwindow 0
+    protected variable algorithm 0
+    protected variable vtk_viewer 0
+    protected variable bis_viewer 0
+
+    protected variable refsur  0
+    protected variable targsur 0
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_pointbasedregistrationviewer::Initialize { } {
+    
+
+
+}
+
+
+
+# ----------------------------------------------------------
+#
+#  Input/Output Utility Stuff
+#
+# ----------------------------------------------------------
+
+itcl::body  bis_pointbasedregistrationviewer::CreateViewer { par  } {
+
+ 
+    set topframe [ LabelFrame:create  $par.cont -text "Display Controls" ]
+    pack $par.cont -side top -fill x -pady 0 -expand false
+
+    set b [ frame $topframe.1 ]
+    set w2 [ frame $topframe.2 ]
+    pack $b $w2     -side top -expand true -fill x
+    set thisparam($this,gui_control2) [ button $b.b3 -text "Show Original Surfaces" ]
+    set thisparam($this,gui_control3) [ button $b.b4 -text "Show Transformed Surfaces" ]
+    eval "$thisparam($this,gui_control2) configure -command {  $this ShowSurfaces 0 }"
+    eval "$thisparam($this,gui_control3) configure -command {  $this ShowSurfaces 1 }"
+    pack $b.b3 $b.b4   -side left -fill x -padx 2 -expand true
+
+     frame $par.bot
+     pack $par.bot -side bottom -expand true -fill both
+    
+    set bis_viewer [ [ bis_viewer \#auto ] GetThisPointer ]
+    $bis_viewer CreateGUI $par.bot
+    set vtk_viewer [ $bis_viewer GetViewer ]
+
+#    $bis_viewer AddPolygonalObject $itclgrid 1
+#    $bis_viewer AddPolygonalObject $itclgrid 1
+#    $bis_viewer AddPolygonalObject $itclgrid 1
+#
+#     set ren [ vtkRenderer [ pxvtable::vnewobj ]]
+
+#     set renWidg [ vtkTkRenderWidget $wtop.r -width 500 -height 500 ]
+#     pack $renWidg -side top -expand true -fill both
+#     set renderwindow [ $renWidg GetRenderWindow ]
+#     $renderwindow AddRenderer $ren
+
+#     set vtk_viewer [ vtkpxGUIRenderer [ pxvtable::vnewobj ] ]
+#     $vtk_viewer BindMouseEvents $renWidg "$this HandleMouseEvent" "$this HandleUpdateEvent"
+#     $vtk_viewer SetNoPolyClipControls 1
+#     $vtk_viewer Initialize $wtop.bot $ren 1
+    
+#     for { set j 1 } { $j <= 2 } { incr j } {
+# 	set guiparam($this,gui_actor$j) [ vtkActor [ pxvtable::vnewobj ] ]
+# 	set act $guiparam($this,gui_actor$j)
+	
+# 	set map [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+# 	$act SetMapper $map
+	
+# 	$map Delete
+# 	$act SetVisibility 0
+	
+# 	[ $act GetProperty] SetRepresentationToWireframe
+# 	[ $act GetProperty ] SetAmbient 1.0 
+# 	[ $act GetProperty ] SetDiffuse 0.0
+# 	[ $act GetProperty ] SetOpacity 1.0
+# 	[ $act GetProperty ] SetLineWidth 1.0
+# 	if { $j == 1 } {
+# 	    [ $act GetProperty] SetColor 1.0 0.0 0.0
+# 	} else {
+# 	    [ $act GetProperty] SetColor 0.0 1.0 0.0
+# 	}
+	
+# 	[ $vtk_viewer GetRenderer ] AddActor $act
+#     }
+#     [ $vtk_viewer GetRenderer ] SetBackground 0.2 0.2 0.3
+#     puts stderr "I am now ($this) getting an rpm_gui"
+    set has_rpm_gui 1
+
+    #        wm geometry $basewidget 600x1500
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body bis_pointbasedregistrationviewer::ShowSurfaces { { applytransformation 0 } } {
+ 
+
+    if { $algorithm == 0 } {
+	return 0
+    }
+
+    if { $refsur == 0 } {
+	set refsur  [ [ pxitclsurface \#auto ] GetThisPointer ]
+	set targsur [ [ pxitclsurface \#auto ] GetThisPointer ]
+    }
+
+    set sourcesurface  [ [ $algorithm GetReferenceSurface ] GetSurface ]
+    set targetsurface  [ [ $algorithm GetTransformSurface ] GetSurface ]
+
+    $refsur ShallowCopySurface $sourcesurface
+
+    set dat1 $sourcesurface
+    set dat2 $targetsurface
+    set dat_trn 0
+
+    if { $applytransformation ==0 } {
+	$targsur ShallowCopySurface $targetsurface
+    } else {
+	set dat_trn [ [ $algorithm GetOutputTransformation ] GetObject ]
+	
+	set filt2m [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+	$filt2m SetInput $dat1
+	$filt2m SetTransform $dat_trn
+	$filt2m Update
+
+	$targsur ShallowCopySurface [ $filt2m GetOutput ]
+	$filt2m Delete 
+    }
+
+    $bis_viewer AddPolygonalObject $refsur 1
+    $bis_viewer AddPolygonalObject $targsur 1
+}
+
+
+# ---------------------------------------------------------------------------------
+#  Update  commands
+# -----------------------------------------------------------------------------------
+
+itcl::body bis_pointbasedregistrationviewer::Update { visib  regfilter } {
+
+
+    if { $algorithm == 0 } {
+	return
+    }
+
+    set sourcesurface [ [ $algorithm GetReferenceSurface ] GetSurface ]
+    set targetsurface [ [ $algorithm GetTransformSurface ] GetSurface ]
+
+    if { $refsur == 0 } {
+	set refsur  [ [ pxitclsurface \#auto ] GetThisPointer ]
+	set targsur [ [ pxitclsurface \#auto ] GetThisPointer ]
+    }
+
+    $refsur ShallowCopySurface $sourcesurface
+    
+    set dat1 $sourcesurface
+    set dat2 $targetsurface
+
+    set dat_trn  [ $regfilter GetCurrentTransformation ]
+
+    set filt2m [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $filt2m SetInput $dat1
+    $filt2m SetTransform $dat_trn
+    $filt2m Update
+    $targsur ShallowCopySurface [ $filt2m GetOutput ]
+    $filt2m Delete 
+
+    
+    $bis_viewer AddPolygonalObject $refsur 1
+    $bis_viewer AddPolygonalObject $targsur 1
+
+    update idletasks
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_polygonaldisplaymanager.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_polygonaldisplaymanager.tcl
new file mode 100644
index 0000000..01efc92
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_polygonaldisplaymanager.tcl
@@ -0,0 +1,1013 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_polygonaldisplaymanager 1.0
+package require vtkpxcontrib 1.0
+package require  Itcl 3.2
+package require bis_option 1.0
+package require bis_common 1.0
+package require Iwidgets 
+package require pxitclsurface 1.0
+package require pxitclmesh 1.0
+package require pxitcllandmarks 1.0
+package require pxitclelectrodemultigrid 1.0
+package require pxitclbasecontrol 1.0
+package require bis_optiondialog 
+
+itcl::class bis_polygonaldisplaymanager {
+
+    #
+    #public
+    #
+    inherit pxitclbasecontrol
+
+    constructor { { par 0 } } { 
+	::pxitclbasecontrol::constructor $par
+    } {	$this Initialize }
+    destructor { $this CleanAll }
+
+
+    # Key Outside Interface
+    public method AddObject { sur { linked 0 } { attr "" }  }
+    public method RemoveObject { sur { updgui 1}  }
+    public method AddOrReplaceObject { inputsur { linked 0 } { attr "" }  } 
+    public method UpdateSameObject { sur { attr "" } { updisplay 1 } }
+    protected method CreateActor { sur ren }
+
+    
+    # Update Display for object
+    public method UpdateObject { { sur -1 } { updviewer 1 }}
+    public method UpdateRendererList { args }
+    public method SetAttributes { sur attr }
+    public method GetAttribute { sur attname }
+    
+    # Final one is GUI
+    public method SetColor { }
+    protected method ColorToHex { cl }
+    public method ShowAll { mode }
+    public method UpdateGUI { }
+    public method SelectionBoxCallback { }
+
+    public method UpdateFromGUI { args }
+    public method CreateGUI { base { dlgmode 1  }}
+
+    # Set/Get Current Object via index or pointer
+    public method SetCurrentObjectIndex { indx} 
+    public method SetCurrentObject { sur }
+    public method GetCurrentObjectIndex { }
+    public method GetCurrentObject { }
+
+
+    # ------------------------------------------------------------------------------
+    # Internal Stuff
+    # ------------------------------------------------------------------------------
+
+    # protected method
+    protected method Initialize { } 
+    public method CleanAll { } 
+
+    # key internal variables
+    protected variable objectlist ""
+    protected variable rendererlist ""
+
+    # actorarray(object,renderer)
+    protected variable actorarray
+
+    # label arrey is only for surfaces
+    protected variable labelactorarray
+
+    # attributearray(object,type) = { Surface, Landmarks, Electrodes }
+    # attributearray(object,color) =
+    # attributearray(object,linewidth) =
+    # attributearray(object,pointsize) =
+    protected variable attributearray
+
+    # renderermode( )   , slice or volume
+    protected variable renderermode
+    
+    protected variable externalattributelist ""
+    protected variable currentobject    0
+    protected variable vtk_viewer       0 
+    protected variable orthoviewermode  1
+    protected variable attributebox     0
+    protected variable selectionbox     0
+    protected variable optionslist     ""
+    protected variable objindex         1
+    protected variable currentsurface   0
+    protected variable colorbar   0
+    # Common Stuff
+    protected common guiparam
+};
+
+# ------------------------------------------------------------------------------------------------------
+#             Implementation
+# ------------------------------------------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::Initialize { }  {
+    
+    set isdialog 0
+    set currentobject 0
+    set vtk_viewer [ $parent GetViewer ]
+    if { [ $vtk_viewer IsA "vtkpxGUIOrthogonalViewer" ] } {
+	set orthoviewermode 1
+	set renererlist ""
+	for { set i 0 } { $i <=3 } { incr i } {
+	    set r [ [ $vtk_viewer GetRenderer $i ] GetRenderer ]
+	    lappend rendererlist $r
+	    if { $i < 3 } {
+		set renderermode($r) "Slice"
+	    } else {
+		set renderermode($r) "Volume"
+	    }
+	}
+    } else {
+	set orthoviewermode 0
+	$vtk_viewer SetCallback "$this UpdateRendererList"
+	$this UpdateRendererList
+    }
+
+
+    set optionslist { 
+	{  name "Name" "Name" comment "" ""  0 }
+	{  type "Object Type" "Type" comment Surface ""  1 }
+	{  color "Surface Color" "Color" comment "" ""  2 }
+	{  visible "Show Object" "Show Object" boolean 0 { 0 1 }  3 }
+
+	{  lsize "Curve Point Scale" "Curve Point Scale" { real scale } 1.0 { 0.1 10.0 }  10 }
+	{  lmode "Curve Mode"       "Landmark Mode"   listofvalues landmarks { landmarks open_curve closed_curve "land+open" "land+closed"  } 11 }
+	{ dispgridlist "Grid To Display" "Electrode: Disp Grids" { multiplevalues } 0 { 0 1 2 } 10 }
+	{ gridfontsize "Grid Font" "Electrode: Label Font Size" listofvalues 0 { 0 6 8 10 12 16 24 32 } 11 }
+	{ gridfontgap "Grid Label Skip" "Electrode: Label Skip" listofvalues 1 { 0 1 2 3 }  12 }
+	{ gridshowlines "Grid Show Lines" "Electrode: Show Lines" boolean 1 { 0 1 } 13 }
+
+	{  opacity "Surface Opacity" "Opacity" { real scale } 1.0 { 0.0 1.0 } 20 }
+	{  dispmode "Display Mode (for 3D Viewer)" "Display Mode" listofvalues Filled { Filled Wireframe Points }  21 }
+	{  lwidth "Line width  (for wireframe rendering)" "LineWidth" listofvalues 2.0 { 0.1 0.5 1.0 2.0 4.0 6.0 8.0 10.0 }  22 }
+	{  psize "Point size  (for points rendering)" "PointSize" listofvalues 2.0 { 0.1 0.5 1.0 2.0 4.0 6.0 8.0 10.0 } 23 }
+
+    }
+
+    set  externalattributelist [ list name color visible lsize lmode dispgridlist gridfontsize gridfontgap gridshowlines opacity dispmode lwidth psize ]
+
+
+}
+
+itcl::body bis_polygonaldisplaymanager::CleanAll { } {
+
+    $this ShowAll 0
+    #    puts stderr "Clean All $objectlist"
+    foreach obj $objectlist {    
+	$this RemoveObject $obj 0
+    }
+
+#    puts stderr "Cleaning selection box $objectlist"
+    $selectionbox delete 0 end
+    set currentobject 0
+
+    if { [ llength $objectlist ] > 0 } {
+	for { set i 0 } { $i < [ llength $objectlist ] } { incr i } {
+	    set newptr [ lindex $objectlist $i ]
+	    $selectionbox insert end $attributearray($newptr,name) 
+	}
+	$selectionbox selection set end end
+	$this SetCurrentObject $newptr
+	$this UpdateGUI
+	$this UpdateObject $newptr
+	return
+    }
+
+    $this UpdateGUI
+}
+
+# -----------------------------------------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::UpdateSameObject { sur { attr "" } { updisplay 1 } } {
+
+    set v [ lsearch $objectlist $sur ]
+    if { $v == -1 } {
+	return 0
+    }
+
+    if { $attr != "" } {
+	$this SetAttributes $sur $attr
+    }
+
+
+
+    foreach ren $rendererlist {
+	
+	set map [ $actorarray($sur,$ren) GetMapper ]
+	if { [ $sur isa pxitclsurface ] } {
+	    $map SetInput [ $sur GetObject ] 
+	} elseif { [ $sur isa pxitclmesh ] } {
+            $map SetInput [ $sur GetSurfaceRepresentation ]
+	} else {
+	    $map SetInput [ [ $sur GetObject ] GetOutput ]
+	}
+	if { [ $sur isa pxitclelectrodemultigrid  ] } {
+	    set map [ $labelactorarray($sur,$ren) GetMapper ]
+	    $map SetInput [ [ $sur GetObject ] GetLabelSurface ]
+	}
+    
+	if { [ $sur isa pxitclelectrodemultigrid  ] } {
+	    [ $labelactorarray($sur,$ren) GetMapper ] Modified
+	    $labelactorarray($sur,$ren) Modified
+	}
+
+	$map Modified
+	$actorarray($sur,$ren) Modified
+	
+    }
+    $this UpdateObject $sur $updisplay
+    $this UpdateGUI
+    return 0
+}
+# -----------------------------------------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::AddOrReplaceObject { inputsur { linked 0 } { attr "" }  } { 
+
+#    puts stderr "Add Or Replace\n"
+    if { $inputsur == 0 || $inputsur == "" } { return 0 }
+    set v [ lsearch $objectlist $inputsur ]
+    if { $v > -1 } { 
+#	puts stderr "Updating Same\n"
+	return [ $this UpdateSameObject $inputsur $attr ]
+    } 
+
+    set fn [ $inputsur cget -filename ]
+    if { $fn == "" || $fn == "0" || [ file tail $fn ] == "0" } {
+#	puts stderr "On to adding fn=$fn"
+	return [ $this AddObject $inputsur $linked $attr ]
+    }
+    
+    set goodsurface 0
+
+#    puts stderr "Linked=$linked, looking for inputsur in $objectlist"
+
+    set v [ lsearch $objectlist $inputsur ]
+
+    foreach tmpsur $objectlist {
+	set f2 ""
+	set f2 $attributearray($tmpsur,filename) 
+	if { $f2 == $fn && $f2 != "" } { 
+	    #	    puts stderr "Found existing copying ... $inputsur [ $inputsur isa pxitclsurface ], $tmpsur, [ $tmpsur  isa pxitclsurface ], linked=$linked"
+	    if { [ $tmpsur isa "pxitclsurface" ] == 1 || [ $tmpsur isa "pxitclmesh" ] == 1 } {
+		$tmpsur ShallowCopy $inputsur
+	    } else { 
+		$tmpsur Copy $inputsur
+	    }
+	    set goodsurface $tmpsur
+	}
+    }
+    
+    if { $goodsurface == 0 } {
+#	puts stderr "no good surface .... adding $inputsur"
+	$this AddObject $inputsur $linked $attr
+	return 1
+    }
+
+    $this UpdateSameObject $goodsurface $attr 
+    $this SetCurrentObject $goodsurface
+    return 0
+}
+# -----------------------------------------------------------------------------------------------------
+
+itcl::body bis_polygonaldisplaymanager::AddObject { sur { linked 0 } { attr "" }  } {
+
+    if { $sur == 0 || $sur == "" } { 
+	return 0
+    }
+
+#    puts stderr "\n\n\n\n AddObject Sur=$sur linked=$linked attr=$attr  addingobject"
+
+    set newptr 0
+    set adding 1
+
+    if { $linked > 0 } {
+	set v [ lsearch $objectlist $sur ]
+	set newptr $sur
+	if { $v > -1 } {
+#	    puts stderr "Linked::Object $sur exists, nothing to do ... updating same"
+	    return [ $this UpdateSameObject $sur $attr ]
+	} else {
+#	    puts stderr "Linked::Object $sur does not exist adding to pointer list"
+	    lappend objectlist $newptr
+	    set adding 1
+	}
+    } else {
+#	puts stderr "Not Linked:Copying and creating surface "
+	set cl [ $sur info class ]
+	set newptr [ [ eval "$cl \#auto" ]  GetThisPointer ]
+	if { [ $newptr isa pxitclsurface ] || [ $newptr isa pxitclmesh ] } {
+	    $newptr ShallowCopy $sur
+	} else { 
+	    $newptr Copy $sur
+	}
+	set adding 1
+	lappend objectlist $newptr
+    }
+
+
+    set l [ expr [ llength $objectlist ] -1 ]
+    while { $l > 10 } {
+	set l [ expr $l -10 ]
+    }
+
+    if { [ $newptr isa pxitclelectrodemultigrid  ] } {
+	set cl "1.0 1.0 1.0"
+    } else {
+	set ut [ vtkpxSurfaceUtil New ]
+	set cl [ $ut GetColor $l ]
+	$ut Delete
+    }
+
+    set attributearray($newptr,linked) [ expr $linked > 0 ]
+
+    set attributearray($newptr,color) $cl
+    set attributearray($newptr,opacity)    1.0
+    set attributearray($newptr,type)      Electrodes
+    set attributearray($newptr,visible)     1
+    set attributearray($newptr,lwidth)  2.0
+    set attributearray($newptr,psize)  3.0
+    set attributearray($newptr,dispmode)    "Filled"
+    set attributearray($newptr,dispgridlist) ""
+    set attributearray($newptr,gridfontsize) 12
+    set attributearray($newptr,gridfontgap) 2
+    set attributearray($newptr,gridshowlines) 1
+    set attributearray($newptr,name) ""
+
+    if { [ $newptr isa pxitclsurface  ] } {
+	set attributearray($newptr,type)      Surface
+    } 
+
+    if { [ $newptr isa pxitclmesh  ] } {
+	set attributearray($newptr,type)      Mesh
+    } 
+
+    if { [ $newptr isa pxitcllandmarks  ] } {
+	set attributearray($newptr,type)      Landmarks
+	set attributearray($newptr,lsize)  1.0
+	set attributearray($newptr,lmode)  "land+open"
+    }
+
+
+    if { [ $newptr isa pxitclelectrodemultigrid  ] } {
+	set multigrid [ $newptr GetObject ]
+	for { set i 0 } { $i < [ $multigrid GetNumberOfGrids ] } { incr i } {
+	    [ $multigrid GetElectrodeGrid $i ] Modified
+	    [ $multigrid GetElectrodeGrid $i ] SetVisible [ expr ($i == 0) ] 
+	}
+	set attributearray($newptr,dispgridlist) [ $newptr GetDisplayedGridNamesList ]
+    }
+
+    if { $attr != "" } {
+	# Potentially copy stuff from attributes
+#	puts stderr "Adding Copying attributes $attr"
+	$this SetAttributes $newptr $attr
+    }
+
+    foreach ren $rendererlist {
+	$this CreateActor $newptr $ren
+    }
+
+#    puts stderr "Adding $newptr, linked = $attributearray($newptr,linked)"
+
+
+    if { $attributearray($newptr,name) == "" } {
+	set filename [ $newptr cget -filename ]  
+	set attributearray($newptr,filename) $filename    
+	set fn [ file tail $filename  ]
+	if { [ string length $fn ] < 2 } {
+	    set fn $attributearray($newptr,type)
+	}
+    } else {
+	set fn $attributearray($newptr,name)
+    }
+
+    set fn "${fn}.${objindex}" ; incr objindex
+    $selectionbox insert end $fn
+    if {  $attributearray($newptr,linked) > 0 } {  
+	set fn "RO:${fn}"
+    }
+    set attributearray($newptr,name) $fn
+
+    update idletasks
+    $selectionbox selection clear 0 end
+    $selectionbox selection set end end
+    
+
+    
+    $this SetCurrentObject $newptr
+    $this UpdateGUI
+    $this UpdateObject $newptr
+
+}
+# -------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::GetAttribute { sur attname } {
+    set v [ lsearch $objectlist $sur ]
+    if { $v == -1 } {
+	return 0
+    }
+
+    if { [ lsearch -exact $externalattributelist $attname ] > -1 } {
+	return $attributearray($sur,$attname) 
+    }
+
+    return 0
+}
+
+itcl::body bis_polygonaldisplaymanager::SetAttributes { sur attr } {
+
+    set v [ lsearch $objectlist $sur ]
+    if { $v == -1 } {
+	return 0
+    }
+
+    set n [ llength $attr ]
+    set maxn [ expr $n -1 ]
+    if { $maxn < 1 } {
+	return
+    }
+	
+    for { set i 0 } { $i < $maxn } { set i [ expr $i +2 ] } {
+	set attname [ lindex $attr $i ]
+	set val     [ lindex $attr [ expr $i +1 ] ]
+	if { [ lsearch -exact $externalattributelist $attname ] > -1 } {
+	    set attributearray($sur,$attname) $val
+	    #	    puts stderr "Setting attributes of $sur $attname=$val"
+	}
+    }
+
+
+}
+# -----------------------------------------------------------------------
+
+itcl::body bis_polygonaldisplaymanager::CreateActor { sur ren  }  {
+
+    set map [ vtkPolyDataMapper New ]
+    #if { [ $sur isa pxitclsurface ] || [ $sur isa pxitclmesh ] } {}
+    if { [ $sur isa pxitclsurface ] } {
+	$map SetInput [ $sur GetObject ] 
+    } elseif { [ $sur isa pxitclmesh ] } {
+        $map SetInput [ $sur GetSurfaceRepresentation ]
+    } else { 
+	$map SetInput [ [ $sur GetObject ] GetOutput ]
+    } 
+    #$map SetInput [ [ $sur GetObject ] GetLabelSurface ]
+
+    set act [ vtkActor New ]
+    $act SetMapper $map
+    $map Delete
+    $act SetVisibility 0
+    $ren AddActor $act
+    set actorarray($sur,$ren) $act
+    
+    if { [ $sur isa pxitclelectrodemultigrid  ] } {
+	
+	set m [ vtkLabeledDataMapper [ pxvtable::vnewobj ]]
+	$m SetInput [ [ $sur GetObject ] GetLabelSurface ]
+	$m SetLabelModeToLabelScalars
+
+	set a [ vtkActor2D [ pxvtable::vnewobj ]]
+	$a SetMapper $m
+	$a SetVisibility 0
+	set labelactorarray($sur,$ren) $a
+	$m Delete
+
+	$ren AddActor2D $a
+    }
+}
+
+# -----------------------------------------------------------------------------------------------
+ 
+itcl::body bis_polygonaldisplaymanager::RemoveObject { sur { updgui 1 } }  {
+
+    if { $sur == 0 } { set sur $currentobject }
+    if { $sur == 0 } { return }
+
+    set ind [ lsearch -exact $objectlist $sur ]
+    if { $ind == - 1 } {
+	return 0
+    }
+
+
+
+    if { $attributearray($sur,linked) > 0 } {
+	if { $updgui == 1 } {
+	    set ok [ tk_messageBox -type ok -default ok -title "Think again ..." -message "This object can not be deleted" -icon info  ]
+	} else {
+	    puts stderr "Not Removing $sur, linked=$attributearray($sur,linked)"	    
+	}
+	return 0
+    }
+
+    if { $updgui == 1 } {
+	set ok [ tk_messageBox -type yesno -default no -title "Think again ..." -message "Do you want to delete $attributearray($sur,name)?" -icon question  ]
+	if { $ok == "no" } {
+	    return
+	}
+    }
+
+    foreach ren $rendererlist {
+	$ren RemoveActor $actorarray($sur,$ren)
+	$actorarray($sur,$ren) Delete
+	if { [ $sur isa pxitclelectrodemultigrid  ] } {
+	    $ren RemoveActor $labelactorarray($sur,$ren)
+	    $labelactorarray($sur,$ren) Delete
+	}
+    }
+    #    array unset attributearray "(${sur},*"
+
+#    puts stderr "Objectlist $objectlist -->\n"
+
+    if { $ind > 0 } {
+	set obj1 [ lrange $objectlist 0 [ expr $ind -1 ] ]
+    } else { 
+	set obj1 ""
+    }
+    set obj2 [ lrange $objectlist [ expr $ind +1 ] end ]
+
+    set objectlist [ concat $obj1 $obj2 ]
+#    puts stderr "\t\t $objectlist -->\n"
+
+    itcl::delete object $sur
+    
+    if { $updgui } {
+#	puts stderr "Cleaned Selection box"
+	$selectionbox delete 0 end
+#	puts stderr "Cleaned Selection box"
+	for { set i 0 } { $i < [ llength $objectlist ] } { incr i } {
+	    set newptr [ lindex $objectlist $i ]
+	    $selectionbox insert end $attributearray($newptr,name)
+#	    puts stderr "Inserting $attributearray($newptr,name)"
+	}
+
+	if { $currentobject ==  $sur } {
+	    if { [ llength $objectlist  ] > 0 } {
+		set currentobject [ lindex $objectlist 0 ]
+		$selectionbox selection set 0 0
+	    } else {
+		set currentobject 0
+	    }
+	    $this UpdateGUI
+	}
+    }
+}
+
+
+# -------------------------------------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::UpdateObject { { sur -1 } { updviewer 1 }} {
+
+    if { $vtk_viewer == 0 } {	return    }
+    if { $sur == -1 } {	set sur [ $this GetCurrentObject ]    } 
+    if { [ llength $rendererlist ] == 0 } { return }
+    if { [ llength $objectlist ] == 0 } { return }
+
+
+
+    set ind [ lsearch -exact $objectlist $sur ]
+    if { $ind < 0 } {
+	return 0
+    }
+
+    set tp  $attributearray($sur,type)     
+    regsub -all "\"" $tp "" tp
+
+    if { $tp == "Landmarks" } {
+	set land [ $sur GetLandmarks ]
+	$land SetPointScale $attributearray($sur,lsize)  
+	set sland $attributearray($sur,lmode)
+	set cl 0   ; if { $sland == "closed_curve" || $sland == "land+closed"  } { set cl 1 } 
+	set sc 0   ; if { $sland != "landmarks" } { set sc 1 } 
+	set sl 1   ; if { $sland == "closed_curve" || $sland == "open_curve" } { set sl 1 }
+	$land SetClosedCurve  $cl
+	$land SetShowCurve    $sc
+	$land SetShowControls $sl
+	$land Update
+    } elseif { $tp == "Electrodes" } {
+	$sur SetLabelGap $attributearray($sur,gridfontgap) 
+	$sur SetGridNamesToDisplay $attributearray($sur,dispgridlist)
+	$sur SetJustShowElectrodes [ expr 1 - $attributearray($sur,gridshowlines) ] 
+
+	set egrid [ $sur GetObject ]
+	$egrid Modified
+    }
+
+    # --------------------------------------------
+
+    foreach ren $rendererlist { 
+
+	set cl  $attributearray($sur,color) 
+
+	set act $actorarray($sur,$ren)
+	set prop [ $act GetProperty ]
+	
+	regsub -all "\"" $cl "" cl
+	if {  [ llength $cl ] == 3 } {
+	    $prop SetColor [ lindex $cl 0 ] [ lindex $cl 1 ] [ lindex $cl 2 ]
+	}
+	$prop SetOpacity  $attributearray($sur,opacity)   
+
+	set dt $attributearray($sur,dispmode)    
+	if { $renderermode($ren) == "Slice" } {
+	    set dt "Wireframe"
+	}
+	    
+	$prop SetLineWidth $attributearray($sur,lwidth)
+	$prop SetPointSize $attributearray($sur,psize)
+
+	if { $dt == "Filled" } {
+	    $prop SetRepresentationToSurface
+	    $prop SetDiffuse 1.0
+	    $prop SetAmbient 0.0
+	    $prop SetSpecular 0.0
+	} else {
+	    $prop SetDiffuse 0.0
+	    $prop SetAmbient 1.0
+	    $prop SetSpecular 0.0
+	    if { $dt == "Wireframe" } {
+		$prop SetRepresentationToWireframe
+	    } else {
+		$prop SetRepresentationToPoints
+	    }
+	}
+
+	$act SetVisibility $attributearray($sur,visible)
+	if { [ $sur isa pxitclelectrodemultigrid  ] } {
+	    set fontsize $attributearray($sur,gridfontsize)
+	    set act $labelactorarray($sur,$ren)
+	    set map [ $act GetMapper ]
+	    set prop [ $map GetLabelTextProperty ]
+	    if { $renderermode($ren) == "Slice" } {
+		$act SetVisibility 0
+	    } elseif { $fontsize > 0 } {
+		$prop SetFontSize $fontsize
+		$prop ShadowOff
+		if {  [ llength $cl ] == 3 } {
+		    $prop SetColor [ lindex $cl 0 ] [ lindex $cl 1 ] [ lindex $cl 2 ]
+		}
+		$map Modified
+		$act Modified
+		$act SetVisibility 1
+
+	    } else {
+		$act SetVisibility 0
+	    }
+	}
+    }
+
+    if { $updviewer > 0 } {
+	$vtk_viewer Update
+    }
+}
+# -----------------------------------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::UpdateRendererList { args } {
+
+    if { $orthoviewermode == 1 } {
+	return 0
+    }
+
+    #    puts stderr "updating renderer list"
+
+    set numold [ llength $rendererlist ]
+    set newrenlist ""
+    set num [ $vtk_viewer GetNumberOfViewers ]
+    for { set i 0 } { $i < $num } { incr i } {
+	set r [ $vtk_viewer GetRenderer $i ] 
+	if { $r !="" } {
+	    if { [ lsearch -exact $rendererlist $r ] == -1 } {
+		#		puts stderr "Adding Renderer $r"
+		lappend rendererlist $r
+		lappend newrenlist $r
+		set renderermode($r) "Slice"
+	    } 
+	}
+    }
+
+    if { [ llength $objectlist ] > 0  && [ llength $newrenlist ] > 0  } {
+	foreach ren $newrenlist  {
+	    foreach sur $objectlist {
+		#		puts stderr "Creating new actor $sur $ren"
+		$this CreateActor $sur $ren
+	    }
+	}
+
+	foreach sur $objectlist {
+	    $this UpdateObject $sur
+	}
+	return 1
+    }
+    
+    return 0
+    
+}
+
+# --------------------------------------------------------------------
+#
+# Get/Set Current Object
+#
+# --------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::GetCurrentObject { } {
+
+    if { $objectlist == "" } {	return 0 }
+    return $currentobject 
+}
+
+# --------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::SetCurrentObject { sur } {
+    if { $objectlist == "" } {	return }
+
+    set ind [ lsearch -exact $objectlist $sur ]
+    if { $ind != -1 } {
+	$this SetCurrentObjectIndex $ind
+	set currentobject $sur
+    }
+}
+# -------------------------------------------------------------------------    
+itcl::body bis_polygonaldisplaymanager::SetCurrentObjectIndex { index } {
+
+    if { $objectlist == "" } {	return }
+
+    $selectionbox selection clear 0 end
+    $selectionbox selection set $index $index
+
+}
+# --------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::GetCurrentObjectIndex { } {
+    if { $objectlist == "" } {	return 0 }
+    set ind [ lsearch -exact $objectlist $currentobject ]
+    return $ind
+
+}
+
+# -------------------------------------------------------------------------    
+#
+# Create and update GUI
+#
+# -------------------------------------------------------------------------    
+itcl::body bis_polygonaldisplaymanager::UpdateFromGUI { args } { 
+
+    set sur [ $this GetCurrentObject ]
+    if { $sur == 0 } {
+	return
+    }
+
+
+
+    for { set i 1 } { $i < [ llength $optionslist ] } { incr i } {
+	set opt [ lindex [ lindex $optionslist $i ] 0 ]
+	set attributearray($sur,$opt) [ $attributebox GetOptionValue $opt ]
+	#	puts stderr "Setting ($sur,$opt) to [ $attributebox GetOptionValue $opt ]"
+    }
+
+    $this UpdateObject $sur
+
+}
+# ------------------------------------------------------------------------
+#
+# ------------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::ShowAll { md } {
+    set md [ expr $md > 0 ]
+
+    foreach obj $objectlist {    
+	set attributearray($obj,visible)  $md
+	foreach ren $rendererlist {
+	    $actorarray($obj,$ren) SetVisibility $md
+	}
+    }
+    $this UpdateGUI
+    $vtk_viewer Update
+}
+# ------------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::ColorToHex { cl } {
+
+    regsub -all "\"" $cl "" cl
+
+
+    if { [ llength $cl ]  != 3 } {
+	set cl { 1.0 0.0 0.0 }
+    }
+
+    set line "\#"
+    for { set i 0 } { $i <= 2 } { incr i } {
+	set v 0.0
+	catch { set v [expr int(255.0*[ lindex $cl $i ])] }
+	if { $v < 0 } {set v 0 }
+	if { $v > 255 } { set v 255 }
+	set h [format %02x $v ]
+	set line "$line$h"
+    }
+    return $line
+}
+# ------------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::SetColor { } {
+
+    set sur [ $this GetCurrentObject ]
+    if { $sur == 0 } {
+	return
+    }
+
+
+    set cl  $attributearray($sur,color) 
+    set line [ $this ColorToHex $cl ]
+
+    set name 	[ $attributebox GetOptionValue name ]
+    set inhex [ tk_chooseColor -title "Color for $name" -initialcolor $line -parent $basewidget ]
+    if { $inhex == "" } {
+	return
+    }
+    set inhex [ string range $inhex 1 end ]
+
+    for { set i 0 } { $i <=2 } { incr i } {
+	set im [ expr 2*$i ]
+	set ip [ expr $im + 1 ]
+	set nh  [ string range $inhex $im $ip ]
+	set out($i) [expr 0x$nh]
+	set out($i) [ expr $out($i) / 255.0 ]
+
+    }
+
+    set outcl [ format "%.2f %.2f %.2f" $out(0) $out(1) $out(2) ]
+
+
+    set attributearray($sur,color) $outcl
+    $this UpdateObject $sur
+    $this UpdateGUI
+
+
+}
+# ------------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::SelectionBoxCallback { } { 
+
+    set ind [ [ $selectionbox component listbox ] curselection ]
+#    puts stderr "Here in Callback ind=$ind"
+    if { $ind == "" || $ind < 0 } {
+	return 
+    }
+    set currentobject [ lindex $objectlist $ind ]
+    $this UpdateGUI 
+
+}
+
+itcl::body bis_polygonaldisplaymanager::UpdateGUI { } {
+
+    set sur [ $this GetCurrentObject ]
+    if { $sur == 0 } {
+	return
+    }
+    
+    set md 0
+    if { [ $sur isa pxitclelectrodemultigrid  ] } {
+	set md 2 
+    } elseif { [ $sur isa pxitcllandmarks  ] } {
+	set md 1
+    } 
+
+    foreach opt { lsize lmode } {
+	if { $md != 1 } {
+	    $attributebox DisableOption $opt
+	} else {
+	    $attributebox EnableOption $opt
+	    $attributebox SetOptionValue $opt $attributearray($sur,$opt)
+	}
+    }
+
+
+    foreach opt { gridfontsize gridfontgap gridshowlines } {
+	if { $md != 2 } {
+	    $attributebox DisableOption $opt
+	} else {
+	    $attributebox EnableOption $opt
+	    $attributebox SetOptionValue $opt $attributearray($sur,$opt)
+	}
+    }
+
+    if { $md != 2 } {
+	$attributebox DisableOption dispgridlist
+    } else {
+	$attributebox EnableOption dispgridlist
+	$attributebox SetOptionRange dispgridlist [ $sur GetGridNamesList ]
+	$attributebox SetOptionValue dispgridlist [ $sur GetDisplayedGridNamesList ]
+    }
+
+
+    foreach opt { name color type }  {
+	regsub -all "\"" $attributearray($sur,$opt) "" tp
+	if { $opt == "color" } {
+	    $attributebox SetOptionValue $opt $tp
+	    set optgui [ [ $attributebox GetOption $opt ]  GetBaseWidget ]
+	    set h [ $this ColorToHex $tp ]
+	    $colorbar configure -background  [ $this ColorToHex $tp ]
+	} else {
+	    $attributebox SetOptionValue $opt $tp
+	}
+    }
+
+    foreach opt { opacity visible dispmode lwidth psize } {
+	$attributebox SetOptionValue $opt $attributearray($sur,$opt)
+	$attributebox EnableOption $opt
+    }
+
+}
+# -------------------------------------------------------------------------------------------------
+itcl::body bis_polygonaldisplaymanager::CreateGUI { base { dlgmode 1  } } {
+
+    if { $basewidget !=0 } { return $basewidget }
+
+    set basewidget $base
+    if { $dlgmode > 0 } {
+	toplevel $basewidget
+	wm withdraw $basewidget
+	eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget  }"
+	wm geometry $basewidget 500x480
+	wm title $basewidget "Surface Display Manager"
+	set isdialog 1
+
+	#	set bar [ frame $basewidget.bt ]
+	#	pack $bar -side bottom -expand false -fill x
+
+	set btf $basewidget
+    } else {
+	set btf [ [ iwidgets::labeledframe $basewidget  -labeltext "Polygonal Object Control"  ] childsite ]
+	set isdialog 0
+	pack $basewidget -side top -expand true -fill both
+    }
+
+
+    set bbar [ iwidgets::buttonbox $basewidget.bt -orient horizontal ]
+    set bbar2 [ frame $basewidget.bt2 -height 2 -bg black ]
+    pack $bbar $bbar2 -side bottom -expand false -fill x 
+
+
+    # ------------------------------------------------------------------------------
+
+    set w [ frame $btf.b ]
+
+    set lf [ [ iwidgets::labeledframe $btf.a  -labeltext "List"  ] childsite ]
+    frame $btf.mid -width 2 -bg black 
+    pack $btf.a $btf.mid -side left -expand false -fill y
+
+    set colorbar $lf
+    eval "iwidgets::scrolledlistbox $lf.a -selectmode single -labelpos nw -vscrollmode dynamic -hscrollmode dynamic -selectioncommand { $this SelectionBoxCallback } -exportselection 1"
+
+    pack $lf.a -side top -expand false -fill both -padx 4 -pady 4
+    pack $w -side right -expand true -fill both
+    set selectionbox $lf.a 
+
+    set attributebox  [ bis_optiondialog \#auto ]
+    $attributebox SetCallback "$this UpdateFromGUI"
+    $attributebox CreateGUI $w 0 $optionslist
+
+    set bb [ $attributebox GetButtonBar ]
+    $bb add cl  -text "Set Color" -command [ itcl::code  $this SetColor ]
+
+
+    $bbar add dl  -text "Delete Current" -command [ itcl::code  $this RemoveObject 0 ]
+    $bbar add c1  -text "Hide All" -command [ itcl::code  $this ShowAll 0 ]
+    $bbar add c2  -text "Show All" -command [ itcl::code  $this ShowAll 1 ]
+    if { $dlgmode > 0 } {
+	$bbar add c3  -text "Close" -command [ itcl::code  $this HideWindow ]
+    }
+
+
+    # ------------------------------------------------------------------------------
+    return $basewidget
+}
+# -------------------------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_preprocessimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_preprocessimage.tcl
new file mode 100755
index 0000000..cfacccc
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_preprocessimage.tcl
@@ -0,0 +1,231 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_preprocessimage 1.0
+package require bis_dualimagealgorithm 1.0
+package require bis_temporalsmoothimage 1.0
+package require bis_removetemporaldrift 1.0
+package require bis_removeslicemean 1.0
+
+
+itcl::class bis_preprocessimage {
+
+    inherit bis_dualimagealgorithm
+    
+    constructor { } {	 $this Initialize  }
+    
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "4D Preprocess Image" }
+    #override parent function
+    public method CheckInputObjects { }
+
+    # Some GUI Callbacks
+    protected method ConfigureOptionsGUICallbacks { } 
+    public    method HandleCallbacks { args } 
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_preprocessimage::Initialize { } {
+
+    PrintDebug "bis_preprocessimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{  blursigma "kernel sigma (gaussian) in frames" "Temporal Sigma" { real triplescale 100 } 0 { 0 5 } 10 }
+	{  order  "Order of Drift Polynomial" "Drift Polynomial Order"  integer 3 { -1 6 }  0 }
+	{  rmslicemean "Remove Slice Mean "  "Remove Slice Mean"  boolean   0  { 0 1  }  30  } 
+	{  rmvolumemean "Remove Volumn Mean "  "Remove Volume Mean"  boolean   0  { 0 1  }  35  }
+	{  usemask   "Use Mask Image"  "Use Mask"  boolean   0  { 0 1  }  -2  }
+    }
+    
+    set defaultsuffix { "_pre" }
+    set scriptname bis_preprocessimage
+    set completionstatus "Done"
+    
+    #
+    #document
+    #
+    
+    set description "Preprocess an image."
+    set description2 "Preprocess an image with temporal smoothing and/or remove temporal drift and/or remove slice mean or remove volumn mean ."
+	set backwardcompatibility ""
+    set authors "isabella.murphy at yale.edu, xilin.shen at yale.edu."
+    set category "Image Processing-4D"    
+    $this InitializeDualImageAlgorithm
+    
+    $this RenameInput 0 "Functional Image"
+    #set priority to 102 to make it optional
+    $this RenameInput 1 "Mask Image" 102
+}
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_preprocessimage::ConfigureOptionsGUICallbacks { } {
+
+    eval "$OptionsArray(rmslicemean) SetGUICallbackFunction { $this HandleCallbacks slice }"
+    eval "$OptionsArray(rmvolumemean) SetGUICallbackFunction { $this HandleCallbacks volume }"
+}
+
+itcl::body bis_preprocessimage::HandleCallbacks {  args } {
+
+    set md [ lindex $args 0 ]
+    if { $md == "slice" && ( [ $OptionsArray(rmslicemean) GetValue ] == 1 ) } {
+	$OptionsArray(rmvolumemean) SetValue 0
+    } elseif { $md == "volume" && ( [ $OptionsArray(rmvolumemean) GetValue ]  == 1 ) } {
+	$OptionsArray(rmslicemean) SetValue 0
+    }
+
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_preprocessimage::Execute {  } {
+	
+    PrintDebug "bis_preprocessimage::Execute"
+    
+    set currentinput [ $this GetInput ]
+    set tempsmooth_alg [ bis_temporalsmoothimage \#auto ] 
+    set tempdrift_alg  [ bis_removetemporaldrift  \#auto ]
+    set tempremove_alg [ bis_removeslicemean \#auto ]
+    
+    set blursigma     [ $OptionsArray(blursigma) GetValue ]
+    set order         [ $OptionsArray(order) GetValue ]
+    set rmslicemean   [ $OptionsArray(rmslicemean) GetValue ]
+    set rmvolumemean  [ $OptionsArray(rmvolumemean) GetValue ]
+    set image_in      [ $this GetInput ]
+    set msk [ $OptionsArray(usemask) GetValue ]
+    set mask [  [ pxitclimage \#auto ] GetThisPointer ]
+    
+    if { $msk == "1" } {
+	puts stdout "Using Mask ..."
+    set mask [ $this GetInputObject second_image ]
+    } 
+    
+    # temporal smooth
+    if { $blursigma > 0 } {
+	puts stdout "executing temporal smooth"
+	$tempsmooth_alg InitializeFromContainer 0 $this
+	$tempsmooth_alg SetInput $currentinput
+	$tempsmooth_alg SetSecondInput $mask
+	$tempsmooth_alg SetOptionValue blursigma $blursigma
+	$tempsmooth_alg SetOptionValue usemask $msk
+	$tempsmooth_alg Execute
+	set currentinput [ $tempsmooth_alg GetOutput ]
+    }
+
+    # temporal drift removal
+    if { $order > -0.1 } {
+	puts stdout "executing drift removal"
+	$tempdrift_alg InitializeFromContainer 0 $this
+	$tempdrift_alg SetInput $currentinput
+	$tempdrift_alg SetSecondInput $mask
+	$tempdrift_alg SetOptionValue order $order
+	$tempdrift_alg SetOptionValue usemask $msk
+	$tempdrift_alg SetOptionValue legendre 1
+	$tempdrift_alg Execute
+	set currentinput [ $tempdrift_alg GetOutput ]
+    }
+    
+    # remove slice mean
+    if { $rmslicemean > 0 || $rmvolumemean > 0 } {
+	$tempremove_alg InitializeFromContainer 0 $this
+	$tempremove_alg SetInput $currentinput
+	$tempremove_alg SetSecondInput $mask
+	$tempremove_alg SetOptionValue usemask $msk
+	if { $rmslicemean > 0 } {
+	    $tempremove_alg SetOptionValue globalmean 0
+	    puts stdout "executing remove slice mean"
+	} else {
+	    $tempremove_alg SetOptionValue globalmean 1
+	    puts stdout "executing remove volume mean"
+	}
+	$tempremove_alg Execute
+	set currentinput [ $tempremove_alg GetOutput ]
+    }
+    
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopy $currentinput 
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+    
+    # Clean up objects
+    itcl::delete obj $tempsmooth_alg
+    itcl::delete obj $tempdrift_alg
+    itcl::delete obj $tempremove_alg
+    
+    return 1
+}
+# -------------------------------------------------------------------------
+itcl::body bis_preprocessimage::CheckInputObjects { } {
+
+    set image_in    [ $this GetInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 2 } {
+	return 0
+    }
+    
+    set msk [ $OptionsArray(usemask) GetValue ]
+
+    if { $msk == "1" } {
+	set image_in    [ $this GetSecondInput ]
+	set d [ $image_in GetImageSize ]
+	if { $d < 2 } {
+	    return 0
+	}
+    }
+    return 1
+    
+}
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_preprocessimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+    
+    set alg [bis_preprocessimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_proportionalscale.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_proportionalscale.tcl
new file mode 100755
index 0000000..bfa1202
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_proportionalscale.tcl
@@ -0,0 +1,150 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_proportionalscale     1.0
+package require bis_imagetoimagealgorithm 1.0
+package require bis_castimage             1.0
+package require bis_shiftscaleimage       1.0
+package require bis_thresholdimage        1.0
+
+itcl::class bis_proportionalscale {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Proportional Scale Image" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_proportionalscale::Initialize { } {
+
+    PrintDebug "bis_proportionalscale::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ mean      "The mean to which the image is scaled to"     "image mean" real    50.0 { 0.0 200.0 }  0 }
+	{ threshold "Images with be thresholded at threshold*mean" "threshold"  real    0.8  { 0.0 2.0 }    0 }
+
+    }
+
+    set defaultsuffix { "_ps" }
+    
+    set scriptname bis_proportionalscale
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Proportional scales input images to the mean specified in the options."
+    set description2 "sets all voxels of intensity less than threshold*mean to zero"
+    set backwardcompatibility ""
+    set authors "dustin.scheinost at yale.edu"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_proportionalscale::Execute {  } {
+
+    PrintDebug "bis_proportionalscale::Execute"
+
+    set mean      [ $OptionsArray(mean)      GetValue ]
+    set threshold [ $OptionsArray(threshold) GetValue ]
+    set image_in  [ $this GetInput ]
+
+    set pscale [ vtkdsSpectUtil [ pxvtable::vnewobj ] ]    
+    set cast   [ bis_castimage       [ pxvtable::vnewobj ] ] 
+    set shift  [ bis_shiftscaleimage [ pxvtable::vnewobj ] ] 
+    set thrsh  [ bis_thresholdimage  [ pxvtable::vnewobj ] ] 
+
+    set imgMean [ $pscale imageMean [ $image_in GetObject ] -1 ] 
+    set imgMean [ $pscale imageMean [ $image_in GetObject ] [ expr $imgMean/8.0 ] ]
+
+    $cast InitializeFromContainer $this 
+    $cast SetInput                $image_in
+    $cast SetOptionValue          type float
+    $cast Execute
+
+    $shift InitializeFromContainer $this 
+    $shift SetInput                [ $cast GetOutput ]
+    $shift SetOptionValue          scale [ expr $mean/$imgMean ]
+    $shift Execute
+    
+    $thrsh InitializeFromContainer $this 
+    $thrsh SetInput                [ $shift GetOutput ]
+    $thrsh SetOptionValue          minth [ expr $mean*$threshold ]
+    $thrsh SetOptionValue          maxth 10000000
+    $thrsh Execute
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ [ $thrsh GetOutput ] GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    itcl::delete object $thrsh $shift $cast
+    $pscale Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_proportionalscale.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_proportionalscale [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_qianvesselness.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_qianvesselness.tcl
new file mode 100755
index 0000000..d01d7e9
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_qianvesselness.tcl
@@ -0,0 +1,319 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package require bis_castimage 1.0
+
+package provide bis_qianvesselness 1.0
+
+
+itcl::class bis_qianvesselness {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Qian Vesselness" }
+    public method UpdateOutputFilenames { } 
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_qianvesselness::Initialize { } {
+
+    PrintDebug "bis_qianvesselness::Initialize" 
+
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ beta "Beta factor" "Beta"  float  800.0 { 1.0 10000.0 }  0 }
+	{ mode "Sphere Subdivision (Original=theta,phi), New = barycentric, NewWedges=barycentric wegdes" "Mode"  listofvalues New { Orig New NewWedges }  1 }
+	{ subdivide "Subvidide Sphere (New Sphere), if on use adds more" "Subdivide"  integer  1 { 0 3 }  3 }
+	{ radius  "Sphere Radius" "Radius" real 8 { 1 100 } 4 }
+	{ forcecpu "Force Execution on CPU" "ForceCPU"  boolean  0 { 0 1 }  -20 }
+ 	{ debug "Debug Mode -- prints more info as process is running"               "Debug Mode"  boolean   0 { 0 1 }   -5 }
+
+    }
+
+    set outputs { 
+	{ outdeviation "Deviation"  pxitclimage  ""  100 }   
+	{ outmean      "Mean"  pxitclimage  ""  101 }   
+	{ outtight     "Tightness"  pxitclimage  ""  104 }   
+	{ outbright    "Brightness" pxitclimage  ""  103 }   
+	{ wedges       "Wedges" pxitclimage  ""  102 }   
+    }
+
+
+    set defaultsuffix { "_vesselness" "_deviation" "_mean" "_tight" "_bright" "_wedges" }
+    
+    set scriptname bis_qianvesselness
+    set completionstatus "Done"
+    set category "Vascular Imaging"
+
+    set description " computes the non-parameteric vesselness measure from Qian et al, MedIA 2009."
+    set description2 ""
+    set authors "Levent Alpoge: levent.alpoge at gmail.com, xenophon.papademetris at yale.edu"
+    set backwardcompatibility "N/A."
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_qianvesselness::Execute {  } {
+#    $this UpdateOutputFilenames 
+
+    PrintDebug "bis_qianvesselness::Execute"
+
+
+    set beta   [ $OptionsArray(beta) GetValue ]
+    set usenewsphere 0
+    set usenewwedges 0
+    if {   [  $OptionsArray(mode) GetValue ] != "Orig" } {
+	set usenewsphere 1
+    }
+    if {  [ $OptionsArray(mode) GetValue ] == "NewWedges" } {
+	set usenewwedges 1
+    }
+    
+    set radius    [ $OptionsArray(radius) GetValue ]
+    set forcecpu  [ expr  [ $OptionsArray(forcecpu) GetValue ] > 0 ]
+    set subdiv  [ expr  [ $OptionsArray(subdivide) GetValue ] > 0 ]
+    set image_in [ $InputsArray(input_image) GetObject ]
+
+    # ------------------------------------------------------------------------------------
+    # Beginning of Levent's code
+
+    set timer [clock seconds]
+    
+    set range [ [ [ [ $image_in GetImage ] GetPointData ] GetScalars ] GetRange ]
+    set K [expr 1.0/([lindex $range 1]-[lindex $range 0])]
+
+    # -------------------------------------------------------------------
+
+    set conv [ vtkxqImageFourierConvolution [ pxvtable::vnewobj ] ]
+
+    set filtertimer [clock seconds]
+    if { $usenewsphere == 0 } {
+	set filterbank [ $conv qVesselFilter 30.0 [ expr int($radius) ] 0.0 0.0 ]
+    } else {
+	# Replace old style filterbank with new code below
+	set sph [ vtkjoColoredSphereSource  New ]
+	$sph SetRadius [ expr int($radius) ]
+	$sph SetColorValue 1
+	$sph SetSubdivisionLevels $subdiv
+	$sph SetUseNewWedges $usenewwedges
+	$sph Update
+	set filterbank [ vtkImageData New ]
+	$filterbank ShallowCopy [ $sph GetOutput ]
+	$sph Delete
+    }
+
+    puts stdout "Filters done in [expr ([clock seconds] - $filtertimer)/1.0] seconds."
+    set deb [ $OptionsArray(debug) GetValue ] 
+
+    set convtimer [clock seconds]
+
+    set castspheres [vtkImageCast New]
+    $castspheres SetOutputScalarTypeToDouble
+    $castspheres SetInput $filterbank
+    $castspheres Update
+
+    $conv SetInput  [  $image_in GetImage ]
+    $conv SetFilterBank [ $castspheres GetOutput]
+    $conv SetMode 2
+    $conv SetDoublePrecision 1
+    if { $deb > 0 } {
+	$conv DebugOn 
+    }
+
+    $conv SetForceCPU $forcecpu
+    $this SetFilterCallbacks $conv "Computing Filters [ $filterbank GetNumberOfScalarComponents ]"
+
+    set wedges [ $OutputsArray(wedges) GetObject ]
+    $wedges CopyImageHeader [ $image_in GetImageHeader ]
+    $wedges ShallowCopyImage [ $conv GetFilterBank ]
+
+    set start [ clock clicks -milliseconds ]
+    $conv Update
+    puts "Setup in conv update takes [ expr [ clock clicks -milliseconds ] - $start ]"    
+#puts stdout "Convolutions done in [expr ([clock seconds] - $convtimer)/1.0] seconds."
+
+    puts stdout "Spacing = [  [$conv GetOutput] GetSpacing ]"
+
+    # Store outputs of convolution first
+    set outimage [ $OutputsArray(outdeviation) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    $outimage ShallowCopyImage [ $conv GetOutput ]
+
+    set outimage [ $OutputsArray(outmean) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    $outimage ShallowCopyImage [ $conv GetSecondOutput ]
+    
+
+    puts stdout "\nStarting v(x) calculations."
+
+    set ttimer [clock seconds]
+
+    set tightness [ vtkxqImageODFVesselnessFilter [ pxvtable::vnewobj ] ]
+    $tightness SetInput [ $conv GetOutput ]
+    $tightness SetBeta [ expr $beta/1.0]
+    $tightness SetDebug 0
+    $tightness Update
+
+    set tightnesstodouble [vtkImageCast [pxvtable::vnewobj]]
+    $tightnesstodouble SetInput [$tightness GetOutput]
+    $tightnesstodouble SetOutputScalarTypeToDouble
+    $tightnesstodouble Update
+
+    set outimage [ $OutputsArray(outtight) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    $outimage ShallowCopyImage [ $tightnesstodouble GetOutput ]
+
+    puts stdout "v(x) saved."
+    puts stdout "v(x) done in [expr ([clock seconds] - $ttimer)/1.0] seconds."
+    puts stdout "\nStarting b(x) calculations."
+
+    set btimer [clock seconds]
+
+    set castimage [vtkImageCast [pxvtable::vnewobj]]
+    $castimage SetInput [ $image_in GetImage ]
+    $castimage SetOutputScalarTypeToDouble
+    $castimage Update
+    
+    set normalizedimage [vtkImageMathematics [pxvtable::vnewobj]]
+    $normalizedimage SetInput [$castimage GetOutput]
+    $normalizedimage SetOperationToMultiplyByK
+    $normalizedimage SetConstantK $K
+    $normalizedimage Update
+
+    set brightness [vtkImageGaussianSmooth [pxvtable::vnewobj]]
+    $brightness SetInput [$normalizedimage GetOutput]
+    $brightness Update
+    #note: $brightness GetOutput is now an image consisting of our newly-defined b(x).
+
+    puts stdout "Saving b(x)..."
+
+    set outimage [ $OutputsArray(outbright) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    $outimage ShallowCopyImage [ $brightness GetOutput ]
+
+    puts stdout "b(x) saved."
+    puts stdout "b(x) done in [expr ([clock seconds] - $btimer)/1.0] seconds."
+
+    puts stdout "\nStarting PPV(x) calculations..."
+
+    set ppvtimer [clock seconds]
+
+    set ppv [vtkImageMathematics [ pxvtable::vnewobj ]]
+    $ppv SetInput1 [$tightnesstodouble GetOutput]
+    $ppv SetInput2 [$brightness GetOutput] 
+    $ppv SetOperationToMultiply
+    $ppv Update
+    #note: $ppv GetOutput is now an image consisting of PPV(x)=v(x)*b(x), as defined in the paper.
+    
+    puts stdout "PPV(x) done in [expr ([clock seconds] - $ppvtimer)/1.0] seconds."
+
+    puts stdout "Everything done in [expr ([clock seconds] - $timer)/1.0] seconds."
+
+    set outimage [ $this GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    $outimage ShallowCopyImage [ $ppv GetOutput ]
+    [ $outimage GetImageHeader ] AddComment "[ $this GetCommandLine full ]"
+
+    $tightness Delete;    $tightnesstodouble Delete;
+    $castimage Delete;    $normalizedimage Delete;    $brightness Delete
+    $ppv Delete;          $castspheres Delete;        $conv Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_qianvesselness::UpdateOutputFilenames { } {
+
+    set fn [ $InputsArray(input_image) GetFileName ]
+    set outlist [ $this CreateDefaultOutputFileList $fn ]
+
+    set l [ ::bis_common::SplitFileNameGZ $fn ]
+    set ext [ lindex $l 1 ]
+    set m [ lindex $outlist 0 ]
+
+    set beta   [ $OptionsArray(beta) GetValue ]
+    set mode   [ $OptionsArray(mode) GetValue ]
+
+    set forcecpu  [ expr  [ $OptionsArray(forcecpu) GetValue ] > 0 ]
+    set radius    [ $OptionsArray(radius) GetValue ]
+    set subdivide    [ $OptionsArray(subdivide) GetValue ]
+
+    set extrastring ""
+    set extrastring [ format "_b%.1f_%s_fc%d_r%.1f" $beta $mode $forcecpu $radius ]
+
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+
+    set namelist { output_image outdeviation  outmean  outtight   outbright    wedges    }
+    for { set i 0 } { $i < [ llength $namelist ] } { incr i } {
+	set m [ lindex $outlist $i ]
+	set n [ lindex $namelist $i ]
+	$OutputsArray($n) SetFileName "${m}${extrastring}${ext}" $force
+    }
+    
+
+    return 1
+
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_qianvesselness.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_qianvesselness [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_regularizeobjectmap.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_regularizeobjectmap.tcl
new file mode 100755
index 0000000..30dadf0
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_regularizeobjectmap.tcl
@@ -0,0 +1,142 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_regularizeobjectmap 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+itcl::class bis_regularizeobjectmap {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Regularize Objectmap" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_regularizeobjectmap::Initialize { } {
+
+    PrintDebug "bis_regularizeobjectmap::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ lambda "Relaxation factor for smoothing the objectmap" "Smoothness Factor:"   real  2.0 { 0.5 50.0 }  0 }
+	{ epsilon  "Convergence factor as % of voxels changed " "Convergence" real 0.2 { 0.01 2.0 } 1 }
+	{ maxobjects  "Maximum number of labels in objectmap  " "Max Labels" integer 128 { 2 512 } -10 }
+	{ maxiter  "Maximum number of iterations  " "Max Iterations" integer 25 { 1 512 } -11 }
+    }
+
+    set defaultsuffix { "_reg" }
+    
+    set scriptname bis_regularizeobjectmap
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Regularizes an objectmap (an image where each value represents an object) to smooth manual segmentations"
+    set description2 ""
+    set backwardcompatibility ""
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_regularizeobjectmap::Execute {  } {
+
+    PrintDebug "bis_regularizeobjectmap::Execute"
+
+    set lambda   [ $OptionsArray(lambda) GetValue ]
+    set epsilon   [ $OptionsArray(epsilon) GetValue ]
+    set maxobjects   [ $OptionsArray(maxobjects) GetValue ]
+    set maxiter   [ $OptionsArray(maxiter) GetValue ]
+    set image_in    [ $this GetInput ]
+
+    set r [ [ [ [  $image_in GetImage ] GetPointData ] GetScalars ] GetRange ]
+    
+    set rmin [ lindex $r 0 ]
+    set rmax [ lindex $r 1 ]
+    if {  ( ($rmax-$rmin)> $maxobjects ) } {
+	set errormessage "The input image has too big a range ($r) for this algorithm to be useful. If you really know what you are doing set the maxobjects parameter to a value greater than [ expr $rmax-$min ]"
+	return 0
+    }
+
+    set segm [ vtkbisObjectmapRegularization New ] 
+    $segm SetInput [ $image_in GetImage ] 
+    $segm SetSmoothness $lambda
+    $segm SetConvergencePercentage $epsilon
+    $segm SetNumberOfIterations $maxiter
+    $this SetFilterCallbacks $segm "Objectmap Regularization"
+    $segm Update
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $segm GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $segm Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_regularizeobjectmap.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_regularizeobjectmap [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_relabelimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_relabelimage.tcl
new file mode 100755
index 0000000..82b2801
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_relabelimage.tcl
@@ -0,0 +1,136 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+
+package provide bis_relabelimage 1.0
+
+#
+# relabel image
+#
+
+itcl::class bis_relabelimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+
+    public method GetGUIName    { } { return "Relabel Header" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_relabelimage::Initialize { } {
+
+    PrintDebug "bis_relabelimage::Initialize" 
+    #name,description,type,object,filename(if applicable),priority (optional)
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ orientation "orientation of image axial,coronal,sagittal" "Orientation"  { listofvalues radiobuttons }  axial { axial coronal sagittal }  0 }
+    }
+
+    set defaultsuffix { "" }
+    
+    set scriptname bis_relabelimage
+    set completionstatus "Done -- needs testing"
+
+    #
+    #document
+    #
+    
+    set description "relabels an image to a given orientation. Output orientation is 0=axial, 1=coronal, or 2=sagittal."
+    set description2 ""
+    set backwardcompatibility "Reimplemented from pxmat_relabelimage.tcl"
+    
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_relabelimage::Execute {  } {
+
+    PrintDebug "bis_relabelimage::Execute"
+
+    set orientation_out   [ $OptionsArray(orientation) GetValue ]
+    set image_in          [ $InputsArray(input_image) GetObject ]
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage [$image_in GetObject ]
+
+    set header [ $image_in GetImageHeader ]
+
+    if { $orientation_out == "coronal" } {
+	$header  SetOrientation 20
+    } elseif { $orientation_out == "sagittal" } {
+	$header  SetOrientation 30
+    } else {
+	$header  SetOrientation 10
+    }
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader $header
+    set comment [ format "BIS::bis_relabelimage.tcl"  ] 
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_relabelimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_relabelimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_removeslicemean.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_removeslicemean.tcl
new file mode 100755
index 0000000..01d9a86
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_removeslicemean.tcl
@@ -0,0 +1,182 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_removeslicemean 1.0
+package require bis_dualimagealgorithm 1.0
+
+
+itcl::class bis_removeslicemean {
+
+    inherit bis_dualimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Remove Slice Mean" }
+	#overwrite parent method
+	public method  CheckInputObjects { } 
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_removeslicemean::Initialize { } {
+
+    PrintDebug "bis_removeslicemean::Initialize"     
+
+    set options {
+	    {  usemask   "Use Mask Image"  "Use Mask Image"  boolean   0  { 0 1  }  40  } 
+	    {  globalmean "Remove Volume Mean instead of Slice Mean"  "Volume Mean"  boolean   0  { 0 1  }  41  } 
+    }
+	
+	#set inputs { { mask_image  "Mask Image" pxitclimage  ""  2} }
+	
+    set defaultsuffix { "_rsm" }
+    
+    set scriptname bis_removeslicemean
+    set completionstatus "Done"
+    
+    #
+    #document
+    #
+    
+    set description "Remove Slice/Volumn Mean."
+	set description2 "Calculate mean of each slice(frame) or the whole volumn and subtract this value from each voxel of that slice(frame)."
+    set backwardcompatibility ""
+    set authors "isabella.murphy at yale.edu, xilin.shen at yale.edu."
+
+    set category "Image Processing-4D"    
+    
+    $this InitializeDualImageAlgorithm
+	
+	$this RenameInput 0 "Functional Image"
+    $this RenameInput 1 "Mask Image" 101
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_removeslicemean::Execute {  } {
+
+
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+
+    
+    PrintDebug "bis_removeslicemean::Execute"
+
+    set image_in    [ $this GetInput ]
+
+    set remove 0
+    set globalmean [ $OptionsArray(globalmean) GetValue ]
+
+    if { $globalmean == 1 } {
+	set remove  [ vtkbisRemoveVolumeMean [ pxvtable::vnewobj ]  ] 
+    } else {
+	set remove  [ vtkbisRemoveSliceMean [ pxvtable::vnewobj ]  ] 
+    }
+    
+    $remove SetInput [ $image_in GetObject ]
+
+    set msk [ $OptionsArray(usemask) GetValue ]
+    if { $msk == "1" } {
+	puts stdout "Using Mask ..."
+	$remove SetImageMask [ [ $this GetInputObject second_image ] GetObject ]
+    } 
+
+    if { $globalmean == 1 } {
+	$this SetFilterCallbacks $remove "Remove Volume Mean"
+    } else {
+	$this SetFilterCallbacks $remove "Remove Slice Mean"
+    }
+    $remove Update
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $remove GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $remove Delete
+
+    return 1
+}
+
+itcl::body bis_removeslicemean::CheckInputObjects { } {
+
+
+    set image_in    [ $this GetInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 2 } {
+	return 0
+    }
+	
+	set msk [ $OptionsArray(usemask) GetValue ]
+	if { $msk == "1" } {
+		set image_in    [ $this GetSecondInput ]
+        set d [ $image_in GetImageSize ]
+        if { $d < 2 } {
+	    return 0
+    	}
+	}
+	
+    return 1
+
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_mediantemporalsmoothimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_removeslicemean [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_removetemporaldrift.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_removetemporaldrift.tcl
new file mode 100755
index 0000000..a0884c0
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_removetemporaldrift.tcl
@@ -0,0 +1,178 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_removetemporaldrift 1.0
+package require bis_dualimagealgorithm 1.0
+
+
+itcl::class bis_removetemporaldrift {
+
+    inherit bis_dualimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Temporal Drift Removal" }
+	#override parent function
+	public method CheckInputObjects { }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_removetemporaldrift::Initialize { } {
+
+    PrintDebug "bis_removetemporaldrift::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ order    "Order of Drift Polynomial" "Polynomial Order"  integer 3 { -1 6 }  0 }
+	{ usemask  "Use Mask Image"  "Use Mask Image"  boolean   0  { 0 1  }  40  } 
+	{ legendre "Use Legendre Polynomials" "Legendre"  boolean 1 { 0 1 }  -1 }
+	{ global   "Global Fit, i.e. assume drift is same for all voxels" "Global Fit" boolean 0 { 0 1 }  -2 }
+    }
+
+    set defaultsuffix { "_rdrift" }
+	
+    
+    set scriptname bis_removetemporaldrift
+    set completionstatus "Done"
+	
+    #
+    #document
+    #
+    
+    set description "Correct the drift of an image."
+	set description2 "User can choose to use Legendre polynomial or regular polynomial function to remove the drift in fMRI time courses."
+    set backwardcompatibility ""
+    set authors "isabella.murphy at yale.edu, xilin.shen at yale.edu."
+    set category "Image Processing-4D"        
+    $this InitializeDualImageAlgorithm
+	
+	$this RenameInput 0 "Functional Image"
+    $this RenameInput 1 "Mask Image" 101
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_removetemporaldrift::Execute {  } {
+	
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+
+
+
+    
+    set order     [ $OptionsArray(order) GetValue ]
+    set legendre  [ $OptionsArray(legendre) GetValue ]
+    set doglob    [ $OptionsArray(global) GetValue ]
+    
+    set image_in    [ $this GetInput ]
+
+    if { $doglob > 0 } {
+	set drift  [ vtkbisRemoveGlobalTemporalDrift [ pxvtable::vnewobj ]  ] 
+    } else {
+	set drift  [ vtkbisRemoveTemporalDrift [ pxvtable::vnewobj ]  ] 
+    }
+	
+    set msk [ $OptionsArray(usemask) GetValue ]
+    if { $msk == "1" } {
+	puts stdout "Using Mask ..."
+	$drift SetImageMask [ [ $this GetInputObject second_image ] GetObject ]
+    } 
+    $drift SetOrder $order
+	$drift SetUseLegendrePolynomials $legendre
+    $drift SetInput [ $image_in GetObject ]
+    $this SetFilterCallbacks $drift "Temporal Drift Removal (order=$order)"
+    $drift Update
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $drift GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $drift Delete
+
+    return 1
+}
+
+itcl::body bis_removetemporaldrift::CheckInputObjects { } {
+
+
+    set image_in    [ $this GetInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 2 } {
+	return 0
+    }
+	
+	set msk [ $OptionsArray(usemask) GetValue ]
+	if { $msk == "1" } {
+		set image_in    [ $this GetSecondInput ]
+        set d [ $image_in GetImageSize ]
+        if { $d < 2 } {
+	    return 0
+    	}
+	}
+	
+    return 1
+
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_removetemporaldrift.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_removetemporaldrift [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_reorientimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_reorientimage.tcl
new file mode 100755
index 0000000..3c29b88
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_reorientimage.tcl
@@ -0,0 +1,159 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package provide bis_reorientimage 1.0
+
+#
+# reorient image
+#
+
+itcl::class bis_reorientimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Reorient Image" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_reorientimage::Initialize { } {
+
+    PrintDebug "bis_reorientimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ orientation "orientation of image axial,coronal,sagittal" "Orientation"  { listofvalues radiobuttons }  axial { axial coronal sagittal }  0 }
+    }
+
+    set defaultsuffix { "" }
+    
+    set scriptname bis_reorientimage
+    set completionstatus "Done -- needs testing"
+    #
+    #document
+    #
+    
+    set description "reorients an image to a given orientation."
+    set description2 " Output orientation is 0=axial, 1=coronal, or 2=sagittal. The input orientation is detected automatically."
+    set backwardcompatibility "Reimplemented from pxmat_reorientimage.tcl"
+    
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_reorientimage::Execute {  } {
+
+    PrintDebug "bis_reorientimage::Execute"
+
+    set out   [ $OptionsArray(orientation) GetValue ]
+    set image_in          [ $InputsArray(input_image) GetObject ]
+    set orientation_in    [ $image_in GetOrientation ]
+
+
+    if { $out == "coronal" } {
+	set orientation_out 1
+    } elseif { $out == "sagittal" } {
+	set orientation_out 2
+    } else {
+	set orientation_out 0
+    }
+
+
+    puts stderr "\n\n\n Reorienting $orientation_in --> $orientation_out "
+
+    #vtk object
+    set vtk_image_in [ $image_in GetObject ]
+    set header [ $image_in GetImageHeader ]
+    set outimage [ $OutputsArray(output_image) GetObject ]
+
+    if { $orientation_in != $orientation_out } {
+	set image_out [ vtkImageData [ pxvtable::vnewobj ]]
+	set ut [ vtkpxUtil [ pxvtable::vnewobj ]]
+	$ut ReOrientImage $image_out $vtk_image_in $orientation_in  $orientation_out
+
+	if { $orientation_out==0 } {
+	    $header  SetOrientation 10
+	} elseif { $orientation_out==1 } {
+	    $header  SetOrientation 20
+	} elseif { $orientation_out==2 } {
+	    $header  SetOrientation 30
+	} else {
+	    $header  SetOrientation $orientation_out
+	}
+	# Output orientation etc. is same as input
+	$outimage CopyImageHeader $header
+	$outimage ShallowCopyImage $image_out 
+	set comment [ format "BIS::bis_reorientimage.tcl to $out"  ] 
+	[ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+	$image_out Delete
+	$ut Delete
+
+    } else {
+	# Nothing to do
+	$outimage CopyImageHeader $header
+	$outimage ShallowCopyImage $vtk_image_in 
+
+    }
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_reorientimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_reorientimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_resampleimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_resampleimage.tcl
new file mode 100755
index 0000000..d6c7c9b
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_resampleimage.tcl
@@ -0,0 +1,194 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package provide bis_resampleimage 1.0
+
+#
+# resample image
+#
+
+itcl::class bis_resampleimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Resample Image" }
+
+    #reimplemented from base class 
+    public method SetArguments { parameterlist commandline  } 
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_resampleimage::Initialize { } {
+
+    PrintDebug "bis_resampleimage::Initialize" 
+
+    #In case vox2 or vox3 not specified, voxx1 will be used for vox2 and vox3
+    set options {
+	{ blurmode  "0 or 1 to blur with appropriate FHWM filter" "Blurmode"  boolean    1 { 0  1 }  0 }
+	{ vox1      "x voxel size [mm] " "X spacing" real   2.0 { 0.05 80.0 }  1 }
+	{ vox2      "y voxel size [mm] " "Y spacing" real   2.0 { 0.05 80.0 }  2 }
+	{ vox3      "z voxel size [mm] " "Z spacing" real   2.0 { 0.05 80.0 }  3 }
+    }
+
+    set defaultsuffix { "_resampled" }
+    
+    set scriptname bis_resampleimage
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    
+    set description  "Resamples an image to a specific resolution with optional blurring."
+    set description2 "Ths output dimensions of the voxels in mm are set using vox1, vox2 and vox3 options.If only vox1 is specified, vox1 will be used for vox2 and vox3, and isotropic image is generated."
+    set backwardcompatibility "Reimplemented from pxmat_resampleimage.tcl."
+    
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# reimplemented
+# -----------------------------------------------------------------------------------------
+itcl::body bis_resampleimage::SetArguments { parameterlist commandline  } {
+
+    set ret 1
+    set ret [ bis_basealgorithm::SetArguments $parameterlist $commandline  ]
+
+    if { $ret ==1 } {
+	set tmp -1
+	set v1 [$OptionsArray(vox1) GetValue] 
+	#In case vox2 or vox3 is not specified, vox1 will be substituted as vox2
+	if { [lsearch $parameterlist vox2 ]  < 0 } {
+	    PrintDebug "voxel size 2 not specified.voxel size 1  will be substituted"  
+	    $OptionsArray(vox2) SetValue $v1 
+	}
+	if { [lsearch $parameterlist vox3 ]  < 0 } {
+	    PrintDebug "voxel size 3 not specified.voxel size 1  will be substituted"  
+	    $OptionsArray(vox2) SetValue $v1
+	}
+    }
+
+    return $ret
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_resampleimage::Execute {  } {
+
+    PrintDebug "bis_resampleimage::Execute"
+
+    set blurmode    [ $OptionsArray(blurmode) GetValue ]
+    set spacing(0)  [ $OptionsArray(vox1)     GetValue ]
+    set spacing(1)  [ $OptionsArray(vox2)     GetValue  ]
+    set spacing(2)  [ $OptionsArray(vox3)     GetValue  ]
+
+    PrintDebug "blurmode = $blurmode, spacing = $spacing(0), $spacing(1), $spacing(2)"
+
+    set image_in    [ $InputsArray(input_image) GetObject ]
+
+    if { $blurmode == 1 } {
+	set input_spacing [[ $image_in GetImage ] GetSpacing ]
+	for { set j 0 } { $j <=2 } { incr j } {
+	    set sigma($j) [ expr $spacing($j) * 0.4247 / [ lindex $input_spacing $j ]]
+	} 
+	set smooth  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+	$smooth SetStandardDeviations $sigma(0) $sigma(1) $sigma(2)
+	$smooth SetRadiusFactors 1.5 1.5 1.5
+	$smooth SetInput [ $image_in GetObject ]
+	$smooth Update
+
+	set image_tmp [ $smooth GetOutput ]
+
+    } else {
+	set image_tmp [  $image_in GetObject ]
+    }
+
+    PrintDebug "spacing = $spacing(0) $spacing(1) $spacing(2)"
+
+    set resl [ vtkbisImageResample [ pxvtable::vnewobj ]]
+    $resl SetAxisOutputSpacing 0 $spacing(0)
+    $resl SetAxisOutputSpacing 1 $spacing(1)
+    $resl SetAxisOutputSpacing 2 $spacing(2)
+    $resl SetInput $image_tmp
+    $resl InterpolateOn
+    $resl SetDimensionality 3
+    $this SetFilterCallbacks $resl "Resampling Image"
+    $resl Update
+    set image_out [$resl GetOutput ]
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out 
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    # Dimensions and Spacings are automatically set.
+    set comment [ format "BIS::bis_resampleimage.tcl" ] 
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    if { $blurmode == 1 } { $smooth Delete }
+
+    $resl Delete
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_resampleimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [ bis_resampleimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_resamplelandmarks.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_resamplelandmarks.tcl
new file mode 100755
index 0000000..0167006
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_resamplelandmarks.tcl
@@ -0,0 +1,131 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_resamplelandmarks 1.0
+package require bis_landmarkstolandmarksalgorithm 1.0
+
+
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_resamplelandmarks {
+
+    inherit bis_landmarkstolandmarksalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Resample Landmarks" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_resamplelandmarks::Initialize { } {
+
+    PrintDebug "bis_resamplelandmarks::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ mode   "Type of resampling (sample,subsample,resample)" "Mode" { listofvalues } resample { sample subsample resample } 1 }
+	{ factor "Factor for sampling or subsampling operations" "Factor"  { integer }  2 { 2 8 }  2 }
+	{ distance "Distance to equisample a curve for" "Distance"  real  1.0 { 0.1 10.0 }  3 }
+    }
+
+    set defaultsuffix { "_resamp" }
+    
+    set scriptname bis_resamplelandmarks
+
+    #
+    #document
+    #
+    set category "Landmarks Processing"
+    set description  "Sampling/Sub-sampling curves stored as landmarks"
+    set description2 ""
+    set backwardcompaibitlity "Newly added."
+    set authors "xenophon.papademetris at yale.edu"
+
+    $this InitializeLandmarksToLandmarksAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_resamplelandmarks::Execute {  } {
+
+    PrintDebug "bis_resamplelandmarks::Execute"
+
+    # Get Inputs
+    set landmarks    [ $this GetInput  ]
+    # GetOptions
+    
+    set mode [ $OptionsArray(mode) GetValue ]
+    set out [ $this GetOutput ]
+    $out CopyLandmarks [  $landmarks  GetLandmarks ]
+    [ $out GetLandmarks ] SetClosedCurve [ [ $landmarks GetLandmarks ] GetClosedCurve ] 
+    [ $out GetLandmarks ] Compact
+
+    if { $mode == "resample" } {
+	[ $out GetLandmarks ] Equispace [ $OptionsArray(distance) GetValue ]
+    } elseif { $mode == "sample" } {
+	[ $out GetLandmarks ] Sample [ $OptionsArray(factor) GetValue ]
+    } else {
+	[ $out GetLandmarks ] SubSample [ $OptionsArray(factor) GetValue ]
+    }
+    [ $out GetLandmarks ] SetClosedCurve [ [ $landmarks GetLandmarks ] GetClosedCurve ] 
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_resamplelandmarks.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_resamplelandmarks [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_resliceimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_resliceimage.tcl
new file mode 100755
index 0000000..5cb7490
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_resliceimage.tcl
@@ -0,0 +1,213 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagetransformationalgorithm 1.0
+package provide bis_resliceimage 1.0
+
+#
+# reslice image
+#
+
+itcl::class bis_resliceimage {
+
+    inherit bis_dualimagetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+
+    # Fix caching issues
+    public method SetTransformation { tr }
+    public method UpdateInputsFromContainer { } 
+
+    public method GetGUIName { } { return "Image Reslice"}
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_resliceimage::Initialize { } {
+
+    PrintDebug "bis_resliceimage::Initialize" 
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set inputs {
+	{ xform2   "Transformation 2"    pxitcltransform  "" 300 }
+	{ xform3   "Transformation 3"    pxitcltransform  "" 400 }
+    }
+    
+    #od descriptions of xfrom2, xform3
+    #Transformation 2: (e.g. 3D->Conventional Transform)
+    #Transformation 3: (e.g. Conventional->Echoplanar Transform)
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ interp    "Interpolation Mode that is used when reslicing the image" "Interpolation Mode"  listofvalues Linear { "NearestNeighbor" "Linear" "Cubic" }  0 }
+	{ background  "Background Level used to fill voxels outside of mapped area" "Background Value"  real 0.0 { -100000 100000 }  -100 }
+	
+    }
+
+    set defaultsuffix { "_resl" }
+    
+    set scriptname bis_resliceimage
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    set category "Image Processing Dual"
+    set description "reslices an image using one or more transformations."
+    set description2 ""
+    set backwardcompatibility "Reimplemented from pxmat_resliceimage.tcl."
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageTransformationAlgorithm
+
+    $this RenameInput 0 "Reference Image"
+    $this RenameInput 1 "Transform Image"
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_resliceimage::Execute {  } {
+
+    PrintDebug "bis_resliceimage::Execute"
+
+    set mode       [ $OptionsArray(interp) GetValue ]
+    set interp 1
+    switch -exact $mode {
+	"NearestNeighbor" { set interp 0 }  
+	"Cubic" { set interp 3 }
+    }
+
+    #vtkobject
+    set image_ref    [ [ $this GetInput ] GetObject ]
+    set image_trg    [ [ $this GetSecondInput ]  GetObject ]
+    set xform1       [ [ $this GetTransformation ]  GetObject ]
+
+    set xform2 0
+    set xform3 0
+    if { [ $InputsArray(xform2) IsFileNameTheDefault ] != 1 } { 
+	set xform2  [[ $InputsArray(xform2)    GetObject ] GetObject ] 
+    }
+
+    if { [ $InputsArray(xform3) IsFileNameTheDefault ] != 1 } { 
+	set xform3  [[ $InputsArray(xform3)    GetObject ] GetObject ] 
+    }
+
+    set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+    $trans Identity
+    $trans PostMultiply
+    $trans Concatenate $xform1
+    if { $xform2 !=0 } {
+	$trans Concatenate $xform2
+	puts stdout "xform2 in use" 
+    }
+    if { $xform3 !=0 } {
+	$trans Concatenate $xform3
+	puts stdout "xform3 in use" 
+    }
+
+
+#    puts stderr "Running vtkbisImageReslice ... [ [ $this GetTransformation ] GetDescription ] "
+#    puts stderr "Running vtkbisImageReslice ... [ [ $this GetInput ] GetDescription ] "
+#    puts stderr "Running vtkbisImageReslice ... [ [ $this GetSecondInput ] GetDescription ] "
+
+    set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+    $resl SetInput             $image_trg
+    $resl SetInformationInput  $image_ref
+    $resl SetInterpolationMode $interp
+    $resl SetBackgroundLevel   [ $OptionsArray(background) GetValue ]
+    $resl OptimizationOff
+    $resl SetResliceTransform $trans
+    $resl Update
+
+    set image_out [$resl GetOutput ]
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out 
+
+    # Output orientation etc. is same as input
+    set outimage [ $this GetOutput ] 
+    set pimage   [ $this GetSecondInput ] 
+
+    $outimage CopyImageHeader [ $pimage GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $trans Delete
+    $resl Delete
+
+#    puts stderr "\t\t\t Reslicing Done\n"
+
+    return 1
+}
+
+
+itcl::body bis_resliceimage::SetTransformation { tr } {
+
+    set ok [ bis_dualimagetransformationalgorithm::SetTransformation $tr ]
+    # puts stdout "Image Reslice Clearing Output"
+    [ $this GetOutput ]  CreateNewImage
+    return $ok
+}
+
+itcl::body bis_resliceimage::UpdateInputsFromContainer { } {
+    set ok [ bis_dualimagetransformationalgorithm::UpdateInputsFromContainer ]
+
+    # clear output
+    # puts stdout "Image Reslice Clearing Output"
+    [ $this GetOutput ]  CreateNewImage
+    return $ok
+
+}
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_resliceimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_resliceimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_reslicetensor.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_reslicetensor.tcl
new file mode 100755
index 0000000..b0c2591
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_reslicetensor.tcl
@@ -0,0 +1,220 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagetransformationalgorithm 1.0
+package provide bis_reslicetensor 1.0
+
+#
+# reslice image
+#
+
+itcl::class bis_reslicetensor {
+
+    inherit bis_dualimagetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+
+    # Fix caching issues
+    public method SetTransformation { tr }
+    public method UpdateInputsFromContainer { } 
+
+    public method GetGUIName { } { return "Tensor Reslice"}
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_reslicetensor::Initialize { } {
+
+    PrintDebug "bis_reslicetensor::Initialize" 
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set inputs {
+	{ xform2   "Transformation 2"    pxitcltransform  "" 300 }
+	{ xform3   "Transformation 3"    pxitcltransform  "" 400 }
+    }
+    
+    #od descriptions of xfrom2, xform3
+    #Transformation 2: (e.g. 3D->Conventional Transform)
+    #Transformation 3: (e.g. Conventional->Echoplanar Transform)
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ interp    "Interpolation Mode that is used when reslicing the image" "Interpolation Mode"  listofvalues Linear { "NearestNeighbor" "Linear" "Cubic" }  0 }
+	{ background  "Background Level used to fill voxels outside of mapped area" "Background Value"  real 0.0 { -100000 100000 }  -100 }
+	
+    }
+
+    lappend options [ list flipx   "Flip the x-direction of the images" "Flip-X" boolean 0  { 0 1 } -30 ]
+    lappend options [ list flipy   "Flip the y-direction of the images" "Flip-Y" boolean 0  { 0 1 } -31 ]
+    lappend options [ list flipz   "Flip the z-direction of the images" "Flip-Z" boolean 0  { 0 1 } -32 ]
+    lappend options [ list quick   "If one use 6 neighboring voxels to estimate the local rotation, else use 26 neighbors" "QuickMode" boolean 1  { 0 1 } 2 ]
+	
+
+    set defaultsuffix { "_reslt" }
+    
+    set scriptname bis_reslicetensor
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    set category "Diffusion Tensor"
+    set description "Reslices an tensor/vector image using one or more transformations."
+    set description2 "This modifies the tensor with a local rigid transformation estimated at each voxel"
+    set backwardcompatibility "Reimplemented from pxmat_reslicetensor.tcl."
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageTransformationAlgorithm
+
+    $this RenameInput 0 "Reference Image"
+    $this RenameInput 1 "Tensor or Vector Image"
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_reslicetensor::Execute {  } {
+
+    PrintDebug "bis_reslicetensor::Execute"
+
+    set mode       [ $OptionsArray(interp) GetValue ]
+    set interp 1
+    switch -exact $mode {
+	"NearestNeighbor" { set interp 0 }  
+	"Cubic" { set interp 3 }
+    }
+
+    #vtkobject
+    set image_ref    [ [ $this GetInput ] GetObject ]
+    set image_trg    [ [ $this GetSecondInput ]  GetObject ]
+    set xform1       [ [ $this GetTransformation ]  GetObject ]
+
+    set xform2 0
+    set xform3 0
+    if { [ $InputsArray(xform2) IsFileNameTheDefault ] != 1 } { 
+	set xform2  [[ $InputsArray(xform2)    GetObject ] GetObject ] 
+    }
+
+    if { [ $InputsArray(xform3) IsFileNameTheDefault ] != 1 } { 
+	set xform3  [[ $InputsArray(xform3)    GetObject ] GetObject ] 
+    }
+
+    set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+    $trans Identity
+    $trans PostMultiply
+    $trans Concatenate $xform1
+    if { $xform2 !=0 } {
+	$trans Concatenate $xform2
+    }
+    if { $xform3 !=0 } {
+	$trans Concatenate $xform3
+    }
+
+    set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+    $resl SetInput             $image_trg
+    $resl SetInformationInput  $image_ref
+    $resl SetInterpolationMode $interp
+    $resl SetBackgroundLevel   [ $OptionsArray(background) GetValue ]
+    $resl OptimizationOff
+    $resl SetResliceTransform $trans
+    $this SetFilterCallbacks $resl "Reslicing Image"
+    $resl Update
+    
+    set reor [  vtkpxImageReorientTensorOrVector [ pxvtable::vnewobj ]]
+    $reor SetInput [ $resl GetOutput ]
+    $reor SetTransformation $trans
+    if { [ $OptionsArray(flipx) GetValue ] > 0 } { $reor FlipXOn }
+    if { [ $OptionsArray(flipy) GetValue ] > 0 } { $reor FlipYOn }
+    if { [ $OptionsArray(flipz) GetValue ] > 0 } { $reor FlipZOn }
+    if { [ $OptionsArray(quick) GetValue ] > 0 } { $reor  Use7PointsOn }
+    $this SetFilterCallbacks $resl "Reorienting Vector/Tensor"
+    $reor Update
+
+    set image_out [$reor GetOutput ]
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out 
+
+    # Output orientation etc. is same as input
+    set outimage [ $this GetOutput ] 
+    set pimage   [ $this GetSecondInput ] 
+    $outimage CopyImageHeader [ $pimage GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment" 0
+
+    $trans Delete
+    $resl Delete
+    $reor Delete
+
+    return 1
+}
+
+
+itcl::body bis_reslicetensor::SetTransformation { tr } {
+
+    set ok [ bis_dualimagetransformationalgorithm::SetTransformation $tr ]
+    # puts stdout "Image Reslice Clearing Output"
+    [ $this GetOutput ]  CreateNewImage
+    return $ok
+}
+
+itcl::body bis_reslicetensor::UpdateInputsFromContainer { } {
+    set ok [ bis_dualimagetransformationalgorithm::UpdateInputsFromContainer ]
+
+    # clear output
+    # puts stdout "Image Reslice Clearing Output"
+    [ $this GetOutput ]  CreateNewImage
+    return $ok
+
+}
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_reslicetensor.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_reslicetensor [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_rfftimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_rfftimage.tcl
new file mode 100755
index 0000000..40cb1a0
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_rfftimage.tcl
@@ -0,0 +1,145 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package require bis_cropimage 1.0
+
+package provide bis_rfftimage 1.0
+
+#
+# inverse fourier transform image
+#
+
+itcl::class bis_rfftimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Inv Fourier Xform" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_rfftimage::Initialize { } {
+
+    PrintDebug "bis_rfftimage::Initialize" 
+    #name,description,type,object,filename(if applicable),priority (optional)
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ dimension "dimension of fourier transform operation. The default value is 3. " "Dimension"  { listofvalues radiobuttons }   3 { 2 3 }  0 }
+	{ fftoperation "if true, the algorithm will look for the zeroth frequency at the center of the image" "operations"  { boolean checkbutton } 0 { 0 1 } 1 }
+	{ magnitude "if true, the algorithm will compute the magnitude of the final image" "Magnitude"  { boolean checkbutton } 0 { 0 1 } 2 }
+    }
+
+    set defaultsuffix { "_rfft"}
+    
+    set scriptname bis_rfftimage
+    set completionstatus "Done, needs checking"
+
+
+    set description "computes inverse fourier transform."
+    set description2 "take in a transformed image or a shifted transform image"
+    set backwardcompatibility "N/A."
+    set authors "hirohito.okuda at yale.edu."
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_rfftimage::Execute {  } {
+
+    PrintDebug "bis_rfftimage::Execute"
+
+    set dimension   [ $OptionsArray(dimension) GetValue ]
+    set image_in    [ $InputsArray(input_image) GetObject ]
+
+    set rfft [vtkImageRFFT [pxvtable::vnewobj]]
+    $rfft SetInput [ $image_in GetObject ]
+    $rfft SetDimensionality $dimension
+    $this SetFilterCallbacks $rfft "RFFT Transforming Image"
+    $rfft Update
+
+    set mag [ vtkImageMagnitude [ pxvtable::vnewobj ] ]
+    if { [ $OptionsArray(magnitude) GetValue  ] > 0 } {
+	#keep only the magnitude
+	$mag SetInput [ $rfft GetOutput ]
+	$mag Update
+	set image_out [ $mag GetOutput ]
+    } else {
+ 	set image_out [ $rfft GetOutput ]
+    }
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out 
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format "BIS::bis_rfftimage.tcl"  ] 
+
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $mag Delete
+    $rfft Delete
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_rfftimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_rfftimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_roimean.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_roimean.tcl
new file mode 100755
index 0000000..905c09d
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_roimean.tcl
@@ -0,0 +1,201 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide  bis_roimean  1.0
+package require bis_dualimagealgorithm 1.0
+package require bis_displayroimean 1.0
+
+itcl::class bis_roimean {
+
+    inherit bis_dualimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "ROI Mean" }
+    public method CheckInputObjects {}
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_roimean::Initialize { } {
+
+    PrintDebug " bis_roimean::Initialize" 
+	
+    #set inputs { 
+    #	{ third_image "Mask Image" pxitclimage "" 102}     
+    #}
+	
+    set options {
+	{ dotextfile "Generate output text file" "Generate Text File" boolean 1 { 0 1 } 20 }
+	{ filename   "specify the filname for the output text file" "Text File Name" { filename writefile } "roimean_result.txt" { text { .txt } } 30 }
+	{ filename2   "specify the filname for the output XYZ coordinate" "Text File Name" { filename writefile } "xyz_coordinate.txt" { text { .txt } } -30 }
+	{ addregion "Add extra roi region" "Add Region" double 0 { 0 100 } -20 }
+	{ fullsizeoutput "Generate Full Size Output Image" "Full Size" boolean 0 { 0 1 } 31 }
+    }
+
+    set defaultsuffix { "_rm" }
+    
+    set scriptname bis_roimean 
+    set completionstatus "Done"
+    
+    #
+    #document
+    #
+    
+    set description "Calculate the mean time course of each ROI defined by ROI mask."
+    set description2 "This algorithm requires two inputs, one is a brain 4D image, the other is the ROI 3D image for this brain image. This algorithm returns a 4D image of ROI mean and can also output a text file. "
+    set backwardcompatibility ""
+    set authors "isabella.murphy at yale.edu, xilin.shen at yale.edu."
+    
+    $this InitializeDualImageAlgorithm
+
+    $this RenameInput 0 "Functional Image"
+    $this RenameInput 1 "ROI Image"
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_roimean::Execute {  } {
+
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+
+   
+    PrintDebug "bis_roimean::Execute"
+	
+    set dotext       [ $OptionsArray(dotextfile) GetValue ]
+    set textfilename [ $OptionsArray(filename)   GetValue ]
+	set textfilename2 [ $OptionsArray(filename2)   GetValue ]
+	set addregion    [ $OptionsArray(addregion)  GetValue ]
+	
+    set image_in [ $this GetInput ]
+
+    set calMean [ vtkbisROIMean [ pxvtable::vnewobj ]  ] 
+    $calMean SetInput    [ $image_in GetObject ]	
+    $calMean SetImageROI [ [ $this GetInputObject second_image ] GetObject ]
+    #set msk [ $OptionsArray(usemask) GetValue ]
+    #if { $msk == "1" } {
+    #puts stdout "Using Mask ..."
+    #$calMean SetImageMask [ [ $this GetInputObject third_image ] GetObject ]
+    #} 
+    $calMean SetDoText $dotext
+    if { $dotext == "1" } {
+	$calMean SetFileName $textfilename
+	$calMean SetFileName2 $textfilename2
+    }
+	$calMean SetAddRegion $addregion
+    
+    $this SetFilterCallbacks $calMean "Calculate ROI Mean"
+    $calMean Update
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $calMean GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+
+    if { [ $OptionsArray(fullsizeoutput) GetValue ] > 0 } {
+
+	set alg [ [ bis_displayroimean \#auto ] GetThisPointer ]
+	$alg InitializeFromContainer $this
+	$alg SetInput [ $this GetInput ]
+	$alg SetSecondInput [ $this GetSecondInput ]
+	$alg SetInputObject third_image $outimage
+	$alg Execute
+	$outimage ShallowCopy [ $alg GetOutput ]
+	itcl::delete object $alg
+    }
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $calMean Delete
+
+    return 1
+}
+
+itcl::body bis_roimean::CheckInputObjects { } {
+
+
+    set image_in    [ $this GetInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 2 } {
+	return 0
+    }
+	
+	set image_in    [ $this GetSecondInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 2 } {
+	return 0
+    }
+	
+	#set msk [ $OptionsArray(usemask) GetValue ]
+	#if { $msk == "1" } {
+	#	set image_in    [ $this GetThirdInput ]
+    #    set d [ $image_in GetImageSize ]
+    #    if { $d < 2 } {
+	#    return 0
+    #	}
+	#}
+	
+    return 1
+
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_ROIMean.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_roimean [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_rtopvalue.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_rtopvalue.tcl
new file mode 100755
index 0000000..d0f7ecc
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_rtopvalue.tcl
@@ -0,0 +1,156 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package provide bis_rtopvalue 1.0
+
+
+itcl::class bis_rtopvalue {
+
+	inherit bis_imagetoimagealgorithm
+
+	 constructor { } {
+	 $this Initialize
+	 }
+
+	public method Initialize { }
+	public method Execute { }
+	public method GetGUIName    { } { return "R-value to 1-p value" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_rtopvalue::Initialize { } {
+
+	PrintDebug "bis_rtopvalue::Initialize" 
+	
+	#commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+   
+	set options {
+	    { subject     "Number of Subjects" "Number of Subjects"   int    0   { 0            100000000   }  0 }
+	    { dof         "Degree of Freedom" "DOF"   int    0   { 0            100000000   }  0 }
+	    { scaleFactor "Scale factor "     "Scale" float  1.0 { -100000000.0 100000000.0 }  0 }
+	}
+	
+	set defaultsuffix { "_1-pvalue" }
+	
+	set completionstatus "Done"
+
+	set scriptname bis_rtopvalue
+
+
+	set description "Converts r value to 1-p value."
+	set description2 "Take behavior correlation r value and number of subjects, degree of freedom as input, convert to 1-p value."
+	set backwardcompatibility "N/A"
+	set authors "isabella.murphy at yale.edu,xilin.shen at yale.edu"
+	set category "Functional Imaging"
+
+	$this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_rtopvalue::Execute {  } {
+
+	PrintDebug "bis_rtopvalue::Execute"
+	set con 0
+	catch {set con [ vtkbisRtoPvalue New ]    }
+	if { $con == 0 } {
+	pxtclvtkpxcontrib::LoadLibraries { vtkpxImagingTCL }
+	}
+	catch { $con Delete }
+	
+	set subject     [ $OptionsArray(subject)      GetValue  ]
+	set dof         [ $OptionsArray(dof)          GetValue  ]
+	set scaleFactor [ $OptionsArray(scaleFactor)  GetValue  ]
+	set image_in    [ $this GetInput ]
+	
+	if { $subject==0 || $dof ==0 } {
+	    set errormessage "Number of Subjects or DOF is not set"
+	    return 0
+	}
+
+	# GetOutput = pxitclimage
+	# [  GetOutput  ] GetImage = vtkImageData  (GetImage is same as GetObject )
+	# ShallowCopy take image from bis_algorithm; ShallowCopyImage take image from vtk class
+	#set tmpimg [ pxitclimage \#auto ]
+	
+	set calp 0
+	catch { set calp [ vtkbisRtoPvalue New  ] }
+	if { $calp == 0 } {
+	    return 0
+	}
+	
+	$calp SetInput    [ $image_in GetObject ]
+	$calp SetNumSubject $subject
+	$calp SetDOF $dof
+	$calp SetScaleFactor $scaleFactor
+	$this SetFilterCallbacks $calp "compute r to 1-p"
+	$calp Update
+	
+	
+	set outimage [ $OutputsArray(output_image) GetObject ]
+	$outimage ShallowCopyImage [ $calp GetOutput ]
+	$outimage CopyImageHeader [ $image_in GetImageHeader ]
+	
+	set comment [ format " [ $this GetCommandLine full ]" ]
+	[ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+	
+	$calp Delete
+	
+	return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_rtopvalue.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+	# this is essentially the main function
+
+	
+
+	set alg [bis_rtopvalue [pxvtable::vnewobj]]
+	$alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_rtotmap.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_rtotmap.tcl
new file mode 100755
index 0000000..bec4cfd
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_rtotmap.tcl
@@ -0,0 +1,140 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package require vtkpxcontrib     1.2
+
+package provide bis_rtotmap 1.0
+
+
+itcl::class bis_rtotmap {
+
+	inherit bis_imagetoimagealgorithm
+
+	 constructor { } {
+	 $this Initialize
+	 }
+
+	public method Initialize { }
+	public method Execute { }
+	public method GetGUIName    { } { return "R-value to T-Score" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_rtotmap::Initialize { } {
+
+	PrintDebug "bis_rtotmap::Initialize" 
+	
+	#commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+   
+	 set options {
+	{ subject        "Number of Subjects" "Number of Subjects"   int    6   {6            100000000   }  0 }
+	}
+
+	set defaultsuffix { "_rtotvalue" }
+	
+	set completionstatus "Done"
+
+	set scriptname bis_rtotmap
+
+
+	set description "convert r value to t value."
+	set description2 "take behavior correlation r value and number of subjects as input, convert to t value."
+	set backwardcompatibility "N/A"
+	set authors "isabella.murphy at yale.edu,xilin.shen at yale.edu"
+	set category "Functional Imaging"
+
+	$this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_rtotmap::Execute {  } {
+
+	PrintDebug "bis_rtotmap::Execute"
+	
+	set con 0
+	catch {set con [ vtkbisRtoTmap New ]    }
+	if { $con == 0 } {
+	pxtclvtkpxcontrib::LoadLibraries { vtkpxImagingTCL }
+	}
+	catch { $con Delete }
+	
+	set subject     [ $OptionsArray(subject)      GetValue  ]
+	set image_in    [ $this GetInput ]
+	
+	set calp 0
+	catch { set calp [ vtkbisRtoTmap New  ] }
+	if { $calp == 0 } {
+	return 0
+	}
+	
+	$calp SetInput    [ $image_in GetObject ]
+	$calp SetNumSubject $subject
+	$this SetFilterCallbacks $calp "compute r to t"
+	$calp Update
+	
+	set outimage [ $OutputsArray(output_image) GetObject ]
+	$outimage ShallowCopyImage [ $calp GetOutput ]
+	$outimage CopyImageHeader [ $image_in GetImageHeader ]
+	
+	set comment [ format " [ $this GetCommandLine full ]" ]
+	[ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+	$calp Delete
+	return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_rtotmap.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+	# this is essentially the main function
+
+	
+
+	set alg [bis_rtotmap [pxvtable::vnewobj]]
+	$alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_seedcorrelation.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_seedcorrelation.tcl
new file mode 100755
index 0000000..367f63e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_seedcorrelation.tcl
@@ -0,0 +1,231 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_seedcorrelation 1.0
+package require bis_dualimagealgorithm 1.0
+
+
+itcl::class bis_seedcorrelation {
+
+    inherit bis_dualimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Seed Correlation" }
+    public method CheckInputObjects { }
+    public method UpdateOutputFilenames { }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_seedcorrelation::Initialize { } {
+
+    PrintDebug "bis_seedcorrelation::Initialize" 
+	
+    set inputs { 
+    	{ third_image "Mask Image" pxitclimage "" 102}     
+    }
+    
+    set options {
+	{ usemask   "Use Mask Image"  "Use Mask Image"  boolean   0  { 0 1  }  10  }
+	{ raw   "Raw Correlation"  "Compute Raw Correlations"  boolean   0  { 0 1  }  -10  }
+	{ ztransform   "Z Transform"  "Z Transform"  boolean   0  { 0 1  }  -20  }
+	{ usegpu   "Use GPU Implementation (if available)"  "Use GPU"  boolean   0  { 0 1  }  -21  }
+    }
+    
+    set defaultsuffix { "_sc" }
+    
+    set scriptname bis_seedcorrelation
+    set completionstatus "Done"
+    set category "Functional Imaging"
+    #
+    #document
+    #
+    
+    set description "Correlation between brain and ROIs."
+    set description2 "Calculate correlation among ROIs and the whole brain image voxel by voxel."
+    set backwardcompatibility ""
+    set authors "isabella.murphy at yale.edu, xilin.shen at yale.edu."
+
+    $this InitializeDualImageAlgorithm
+	
+    $this RenameInput 0 "Functional Image"
+    $this RenameInput 1 "ROI Mean"
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_seedcorrelation::Execute {  } {
+
+
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+
+
+    set doraw       [ $OptionsArray(raw)   GetValue ]
+    set ztranform   [ $OptionsArray(ztransform) GetValue ]
+    set usegpu      [ $OptionsArray(usegpu) GetValue ]
+    set con 0
+
+    set image_in    [ $this GetInput ]
+
+    set crr 0
+    if { $usegpu > 0 } {
+	catch { set crr  [ vtkbisCUDAROICorrelation New ] }
+	if { $crr == 0 } { set usegpu 0 }
+    }
+
+    if { $usegpu == 0 } {
+	catch { set crr  [ vtkbisROICorrelation New  ] }
+	if { $crr ==0 } {
+	    return 0
+	}
+    }
+
+    if { [ $crr GetClassName ] == "vtkbisCUDAROICorrelation" } {
+	puts stdout "+++++++++++++ Using GPU Accelerated Version "
+    }
+
+    $crr SetOutputRaw  [ expr $doraw > 0 ]
+    $crr SetInput [ $image_in GetObject ]
+    $crr SetAverageROI [ [ $this GetInputObject second_image ] GetObject ]
+    set msk [ $OptionsArray(usemask) GetValue ]
+    if { $msk == "1" } {
+	puts stdout "Using Mask ..."
+	$crr SetImageMask [ [ $this GetInputObject third_image ] GetObject ]
+    } 
+    $this SetFilterCallbacks $crr "ROI Correlation"
+    $crr Update
+    
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    if { $ztranform == "1" } {
+	puts "doing z transform"
+	set output [ vtkImageData New ]
+	set fit [ vtkbisConnectivityUtility New ]
+	$fit Ztransform [ $crr GetOutput ] $output
+	$outimage ShallowCopyImage $output
+	$fit Delete
+    } else {
+	$outimage ShallowCopyImage [ $crr GetOutput ]
+    }
+    
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    
+    set nc [ [ $outimage GetImage ] GetNumberOfScalarComponents ]
+    for { set i 0 } { $i < $nc } { incr i } {
+	puts stderr "Frame $i : Range = [ [ [ [ $outimage GetImage ] GetPointData ] GetScalars ] GetRange $i ]"
+    }
+    $crr Delete
+    
+
+    return 1
+}
+itcl::body bis_seedcorrelation::CheckInputObjects { } {
+
+
+    set image_in    [ $this GetInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 1 } {
+	return 0
+    }
+	
+    set image_in    [ $this GetSecondInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 1 } {
+	return 0
+    }
+	
+    set msk [ $OptionsArray(usemask) GetValue ]
+    if { $msk == "1" } {
+	set image_in    [ $this GetInputObject third_image ]
+	set d [ $image_in GetImageSize ]
+	if { $d < 1 } {
+	    return 0
+	}
+    }
+    
+    return 1
+
+}
+itcl::body bis_seedcorrelation::UpdateOutputFilenames { } {
+
+    set f(0) [ $InputsArray(input_image) GetFileName ]
+    set f(1) [ $InputsArray(second_image) GetFileName ]
+    set f(2) [ $InputsArray(third_image) GetFileName ]
+    
+    for { set i 0 } { $i <= 2 } { incr i } {
+	set l($i) [ ::bis_common::SplitFileNameGZ $f($i) ]
+	set f($i) [ file tail [ lindex $l($i) 0 ] ]
+	set ext($i) [ lindex $l($i) 1 ]
+    }
+    
+    set fname [ file join [ file dirname $f(0) ] "$f(0)_$f(1)_$f(2)" ]
+    set outlist [ $this CreateDefaultOutputFileList $fname ]
+    
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+    $OutputsArray(output_image) SetFileName "[ lindex $outlist 0 ]$ext(0)" $force
+    return 1
+
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_temporalsmoothimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_seedcorrelation [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_serialdemonmousereg.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_serialdemonmousereg.tcl
new file mode 100755
index 0000000..e27c6ac
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_serialdemonmousereg.tcl
@@ -0,0 +1,528 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_resliceimage 1.0
+package provide bis_serialdemonmousereg 1.0
+
+#
+# blend image
+#
+
+itcl::class bis_serialdemonmousereg {
+
+    inherit bis_algorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Serial Demons Mouse Registration"}
+
+
+    # Debug/Utility Methods
+    # ---------------------
+    protected method SaveImage { img fname }
+    protected method SaveTransformation { img fname }
+    protected method ResliceImage { ref input trans interp }
+    protected method  CombineTransformations { reference t1 t2 t3 } 
+    protected method GenerateReducedImage { itclimg factor } 
+    public method  UpdateOutputFilenames { } 
+}
+
+
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_serialdemonmousereg::Initialize { } {
+
+    PrintDebug "bis_serialdemonmousereg::Initialize" 
+
+    set options {
+	{ symmetric      "Symmetric or Non-symmetric" "Symmetric Mode"  boolean 1 { 0 1 } 1} 
+	{ debug          "Debug Output On/Off" "Debug"  boolean 0 { 0 1 } 2} 
+	{ reduction      "Perform computations on reduced image size " "Reduction"  integer 1 { 1 12 } 3 } 
+    }
+
+    set inputs { 
+	{ image_ref           "Reference Image" pxitclimage  ""  20 }   
+	{ binary_image_ref    "Reference Image Objectmap" pxitclimage  ""  20 }   
+	{ image_trg   "Transform Image" pxitclimage  ""  25 }   
+	{ binary_image_trg   "Transform Image Objectmap " pxitclimage  ""  30 }   
+    }
+
+    set outputs { 
+	{ transformation "Transformation" pxitcltransform  ""  1 }   
+	{ warped_target  "Resliced Target Image" pxitclimage  ""  101 }   
+    }
+
+    set defaultsuffix { "_output" }
+    
+    set scriptname bis_serialdemonmousereg
+    set completionstatus "Done -- needs testing"
+    #
+    #document
+    #
+
+    set category "Registration"
+    set description "Serial demon registration"
+    set description2 "This is the nonrigid whole body mouse registration algorithm from Suh et al MICCAI 2009."
+    set backwardcompatibility ""
+    set authors "alark.joshi at yale.edu, jung.suh at yale.edu, dustin.scheinost at yale.edu, hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this AddDefaultOptions
+}
+
+# --------------------------------------------------------------------------------------
+itcl::body bis_serialdemonmousereg::UpdateOutputFilenames { } {
+
+
+    set f1 [ [ $this GetOutputObject transformation ] cget -filename ]
+
+    if { [ string length $f1 ] > 1 } {
+	return 1
+    }
+
+    set f(0) [ $InputsArray(image_ref) GetFileName ]
+    set f(1) [ $InputsArray(image_trg) GetFileName ]
+    
+    for { set i 0 } { $i <= 1 } { incr i } {
+	set l($i) [ ::bis_common::SplitFileNameGZ $f($i) ]
+	set f($i) [ file tail [ lindex $l($i) 0 ] ]
+    }
+    
+    set fname [ file join [ file dirname $f(0) ] "$f(0)_$f(1)" ]
+    set outlist [ $this CreateDefaultOutputFileList $fname ]
+    
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+    $OutputsArray(transformation) SetFileName "[ lindex $outlist 0 ].vtk" $force
+    puts stderr "[ lindex $outlist 0 ].vtk"
+
+    return 1
+}
+
+
+# --------------------------------------------------------------------------------------
+itcl::body bis_serialdemonmousereg::SaveImage { img fname } {
+
+    set w [ vtkpxAnalyzeImageWriter New ]
+    $w SetInput $img
+    $w SetForceOutputFileFormat 2
+    $w Save ${fname}.nii.gz
+    puts stderr "Image Saved in $fname"
+    
+    $w Delete
+
+    return
+}
+
+# --------------------------------------------------------------------------------------
+itcl::body bis_serialdemonmousereg::SaveTransformation { tr fname } {
+
+    # Save as .grd
+    $tr Save ${fname}.grd.gz
+
+    # Save as .vtk
+    set w [ vtkStructuredPointsWriter New ]
+    $w SetInput [ $tr GetDisplacementGrid ]
+    $w SetFileTypeToBinary
+    $w SetFileName ${fname}.vtk
+    $w Write
+    puts stderr "Transformation Saved in ${fname}.vtk"
+    $w Delete
+
+    return
+}
+
+#----------------------------------------------------------------------------------------
+itcl::body bis_serialdemonmousereg::ResliceImage { reference input transformation interp } {
+
+    # Reslice input to look like reference using transformation
+
+    puts stderr "Reslicing Image interpolation = $interp"
+
+    set w [ vtkImageReslice New ]
+    $w SetInput $input
+    $w SetInformationInput $reference
+    $w SetResliceTransform $transformation
+    $w SetInterpolationMode $interp
+    $w Update
+
+    set outimg [ vtkImageData New ]
+    $outimg ShallowCopy [ $w GetOutput ]
+
+    $w Delete
+
+    return $outimg
+}
+# --------------------------------------------------------------------------------------
+itcl::body bis_serialdemonmousereg::CombineTransformations { reference t1 t2 t3 } {
+
+
+    set trans [ vtkGeneralTransform New ]
+    $trans Identity
+    $trans PostMultiply
+    if { $t1 !=0 } { $trans Concatenate $t1 }
+    if { $t2 !=0 } { $trans Concatenate $t2 }
+    if { $t3 !=0 } { $trans Concatenate $t3 }
+    
+
+    set dim [ $reference GetDimensions ]
+    set spa [ $reference GetSpacing    ]
+    
+    set tgrid [ vtkTransformToGrid New ]
+    $tgrid SetGridExtent 0 [ expr [ lindex $dim  0 ] -1 ] 0 [ expr [ lindex $dim  1 ] -1 ] 0 [ expr [ lindex $dim  2 ] -1 ]
+    $tgrid SetGridOrigin  0 0 0
+    $tgrid SetGridSpacing [ lindex $spa 0 ] [ lindex $spa 1 ] [ lindex $spa 2 ] 
+    $tgrid SetInput $trans
+    $tgrid Update
+    
+    
+    set trg [ vtkpxGridTransform New ]
+    $trg SetDisplacementGrid [ $tgrid GetOutput ]
+    $trg SetInterpolationModeToLinear
+
+    $tgrid Delete
+    $trans Delete
+    return $trg
+}
+# --------------------------------------------------------------------------------------
+itcl::body bis_serialdemonmousereg::GenerateReducedImage { itclimg factor } {
+    
+    set img [ $itclimg GetImage ]
+    scan [  $img GetSpacing ] "%f %f %f" s(0) s(1) s(2)
+    scan [  $img GetOrigin ] "%f %f %f" o(0) o(1) o(2)
+    scan [ $img GetDimensions ] "%d %d %d" d(0) d(1) d(2)
+
+    puts stderr "In Spacing $s(0) $s(1) $s(2), $d(0), $d(1), $d(2)"
+
+    set fact $factor
+    set div [ expr 1.0/$fact ]
+
+    for { set i 0 } { $i <= 2 } { incr i } {
+	set s($i) [ expr $fact*$s($i) ]
+	set d($i) [ expr round($div*$d($i)) - 1 ]
+    }
+
+    puts stderr "Out Spacing $s(0) $s(1) $s(2), $d(0), $d(1), $d(2)"
+
+    set resl [vtkImageReslice [pxvtable::vnewobj]] 
+    $resl SetInput [ $itclimg GetImage ] 
+    $resl SetOutputSpacing $s(0) $s(1) $s(2)
+    $resl SetOutputOrigin  $o(0) $o(1) $o(2)
+    $resl SetInterpolationMode 0 
+    $resl SetOutputExtent 0 $d(0) 0 $d(1) 0 $d(2) 
+    $resl Update
+	
+    $itclimg  ShallowCopyImage [ $resl GetOutput ]
+    $resl Delete
+
+}
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_serialdemonmousereg::Execute {  } {
+
+    PrintDebug "bis_serialdemonmousereg::Execute"
+    pxtclvtkpxcontrib::LoadLibraries { vtkjwsDemonsRegistrationTCL }
+
+    set symmetric [ $OptionsArray(symmetric) GetValue ] 
+    set reduction [ $OptionsArray(reduction) GetValue ] 
+    set debug [ $OptionsArray(debug) GetValue ] 
+    
+    set refgray [ [ pxitclimage \#auto ] GetThisPointer ]
+    $refgray ShallowCopy  [ $this GetInputObject image_ref ] 
+
+    set refbinary  [ [ pxitclimage \#auto ] GetThisPointer ]
+    $refbinary ShallowCopy [ $this GetInputObject binary_image_ref ] 
+
+    set targgray  [ [ pxitclimage \#auto ] GetThisPointer ]
+    $targgray ShallowCopy  [ $this GetInputObject image_trg ]
+
+    set targbinary [ [ pxitclimage \#auto ] GetThisPointer ]
+    $targbinary ShallowCopy [ $this GetInputObject binary_image_trg ] 
+
+
+    # Resizing in case halfsize is selected 
+    set lst [ list $refbinary $refgray $targbinary $targgray ]
+    foreach img $lst {
+	puts stderr "Inp dims = [ [ $img GetImage ] GetDimensions ]"
+	$this GenerateReducedImage $img $reduction
+	puts stderr "\t\t\t out dims = [ [ $img GetImage ] GetDimensions ]"
+    }
+    set outname "output_grid"
+  
+    
+    if {$symmetric == 0} {
+	set demclass [ vtkjwsDemonsRegistration [pxvtable::vnewobj]] 
+    } else {
+	set demclass [vtkjwsSymmetricDemonsRegistration [pxvtable::vnewobj]] 
+    }
+    
+    puts stdout "\n\n Deciding on Image Size\n"
+    set arr [ $demclass DecideImageSize  [ $refgray GetImage ] [ $targgray GetImage ]  ]
+    
+    set width  [ $arr GetComponent 0 0 ]
+    set height [ $arr GetComponent 0 1 ]
+    set depth  [ $arr GetComponent 0 2 ]
+    puts stdout "Suggested Dimensions = $width x $height x $depth"
+    
+        
+    # --------------------------------------------------------------------------------
+    # Step 5 is to pad images to suggested dimensions
+    # --------------------------------------------------------------------------------
+    set p_refbinary  [ $demclass PadImage [ $refbinary  GetImage] [ expr int($width) ] [expr int($height) ]  [ expr int($depth) ]]
+    set p_targbinary [ $demclass PadImage [ $targbinary GetImage] [ expr int($width) ] [expr int($height) ]  [ expr int($depth) ]]
+    
+	
+    puts stderr "Padded Dimensions: RefB = [  $p_refbinary GetDimensions ]"
+    puts stderr "Padded Dimensions: TargB = [  $p_targbinary GetDimensions ]"
+    
+    # by wook
+    if { $debug > 0 } {
+	$this SaveImage $p_refbinary "${outname}_ref_paddedImage"
+    }
+    if { $debug > 0 } {
+	$this SaveImage $p_targbinary "${outname}_targ_paddedImage"
+    }
+    
+    # --------------------------------------------------------------------------------
+    # Step 6 is to compute distance maps for bone .... 
+    # --------------------------------------------------------------------------------
+    
+    puts stdout "\n\n Computing Bone Distance Maps \n\n"
+    
+    puts stdout "Reference :"
+    set bone_ref  [ $demclass ComputeDistanceMap $p_refbinary 2 3 ]
+    
+    if { $debug > 0 } {
+	$this SaveImage $bone_ref "${outname}_ref_bone_distancemap"
+    }
+    
+    puts stdout "Target :"
+    set bone_targ [ $demclass ComputeDistanceMap $p_targbinary 2 3 ]
+    
+    if { $debug > 0 } {
+	$this SaveImage $bone_targ "${outname}_targ_bone_distancemap"
+    }
+    
+    # --------------------------------------------------------------------------------
+    # Step 7 is to run First Demons 
+    # --------------------------------------------------------------------------------
+    puts stdout "\n\n Computing First Demon \n\n"
+    
+    ## by wook
+    if {$symmetric == 0} {
+	set firstdemon [ vtkjwsDemonsRegistration New ]
+    } else { 
+	set firstdemon [vtkjwsSymmetricDemonsRegistration New ]
+    }
+    $firstdemon SetReferenceDistanceMap $bone_ref
+    $firstdemon SetTargetDistanceMap $bone_targ
+    $firstdemon RunExtendedDemons 1
+    
+    set transformation(1) [ $firstdemon GetGridTransform ]
+    
+    if { $debug > 0 } {
+	set out1 ${outname}_first
+	$this SaveTransformation $transformation(1) $out1
+	puts stdout "Transformation Field -- First Edemons Saved in $out1"
+    }
+    $bone_targ Delete
+       
+    
+    # --------------------------------------------------------------------------------
+    # Step 8 is to deform objectmap for target 
+    # --------------------------------------------------------------------------------
+    
+    puts stdout "\n\n Computing More Bone Distance Maps \n\n"
+    puts stdout "Reference Skin:"
+    set skin_ref  [ $demclass ComputeDistanceMap $p_refbinary 1 2 ]
+    
+    puts stdout "Target : First Reslice Binary"
+    set warp1_targbinary [ $this ResliceImage $p_refbinary $p_targbinary $transformation(1) 0 ]
+    
+    set bone_targ  [ $demclass ComputeDistanceMap $warp1_targbinary 2 3 ]
+    set skin_targ  [ $demclass ComputeDistanceMap $warp1_targbinary 1 2 ]
+    
+    if { $debug > 0 } {
+	$this SaveImage $skin_ref  "${outname}_ref_skin_distancemap"
+	$this SaveImage $bone_targ "${outname}_warp1_targ_bone_distancemap"
+	$this SaveImage $skin_targ "${outname}_warp1_targ_skin_distancemap"
+    }
+    
+    
+    # -------------------------------------------------------------------------------
+    # Step 9 is to combine distance maps
+    # -------------------------------------------------------------------------------
+    set combo_ref [ $demclass MergeDistanceMaps $skin_ref $bone_ref ]
+    set combo_targ [ $demclass MergeDistanceMaps $skin_targ $bone_targ ]
+    
+    if { $debug > 0 } {
+	$this SaveImage $combo_ref  "${outname}_combo_ref_distancemap"
+	$this SaveImage $combo_targ "${outname}_combo_targ_distancemap"
+    }
+    
+    $skin_targ Delete
+    $skin_ref  Delete
+    $bone_targ Delete
+    
+    
+    # -------------------------------------------------------------------------------
+    # Step 10 is to run second edemons
+    # -------------------------------------------------------------------------------
+    puts stdout "\n\n Computing Second Demon \n\n"
+    
+    #set seconddemon [ vtkjwsDemonsRegistration New ]
+    
+    ## by wook
+    if {$symmetric== 0} {
+	set seconddemon [ vtkjwsDemonsRegistration New ]
+    } else { 
+	set seconddemon [vtkjwsSymmetricDemonsRegistration New ]
+    }
+    
+    
+    $seconddemon SetReferenceDistanceMap $combo_ref
+    $seconddemon SetTargetDistanceMap    $combo_targ
+    $seconddemon RunExtendedDemons 2
+    
+    set transformation(2) [ $seconddemon GetGridTransform ]
+    set transformation(21) [ $this CombineTransformations $bone_ref $transformation(2) $transformation(1) 0 ]
+    
+    if { $debug > 0 } {
+	set out2 ${outname}_second
+	$this SaveTransformation $transformation(2) $out2
+	puts stdout "Transformation Field -- Second Edemons Saved in $out2"
+	
+	
+	set out21 ${outname}_first_second
+	$this SaveTransformation $transformation(21) $out21
+	puts stdout "Transformation Field -- First and Second Edemons Saved in $out21"
+    }
+    
+    
+    
+    # --------------------------------------------------------------------------------
+    # Step 15 Gray Level Demons
+    # --------------------------------------------------------------------------------
+    set p_refgray    [ $demclass PadImage [ $refgray    GetImage] [expr int($width) ] [ expr int($height) ] [expr int($depth) ] ]
+    set p_targgray   [ $this ResliceImage $p_refgray [ $targgray   GetImage ] $transformation(21) 1 ]
+    
+    puts stdout "Padded Dimensions: RefG  = [  $p_refgray GetDimensions  ]"
+    puts stdout "Padded Dimensions: TargG = [  $p_targgray GetDimensions ]"
+    
+    # by wook
+    if { $debug > 0 } {
+	$this SaveImage $p_refgray "${outname}_ref_paddedGrayImage"
+	$this SaveImage $p_targgray "${outname}_21Tr_targ_paddedGrayImage"
+    }
+    
+    ## by wook
+    if {$symmetric == 0} {
+	set thirddemon [ vtkjwsDemonsRegistration New ]
+    } else { 
+	set thirddemon [vtkjwsSymmetricDemonsRegistration New ]
+    }
+    
+    $thirddemon SetReferenceDistanceMap $p_refgray
+    $thirddemon SetTargetDistanceMap    $p_targgray
+    $thirddemon RunNormalDemons 
+    
+    set transformation(3) [ $thirddemon GetGridTransform ]
+    
+    
+    if { $debug > 0 } {
+	set out3 ${outname}_third
+	$this SaveTransformation $transformation(3) $out3
+	puts stdout "Transformation Field -- Third Edemons Saved in $out3"
+    }
+    
+    set transformation(321) [ $this CombineTransformations $p_refgray $transformation(3) $transformation(2) $transformation(1) ]
+    if { $debug > 0 } {
+	set out321 ${outname}_complete
+        $this SaveTransformation $transformation(321) $out321
+	puts stdout "Transformation Field -- First, Second and Third Edemons Saved in $out321"
+    }
+
+    [ $this GetOutputObject transformation ] CopyTransformation $transformation(321)
+
+    set r [ [ $this GetInputObject image_ref ]  GetImage ]
+    set t [ [ $this GetInputObject image_trg ]  GetImage ]
+
+    set w [ $this ResliceImage $r $t $transformation(321) 1 ]
+    
+    [ $this GetOutputObject warped_target ] ShallowCopyImage  $w
+    [ $this GetOutputObject warped_target ] CopyImageHeader [ [ $this GetInputObject image_ref ]  GetImageHeader ]
+
+    $w Delete
+    
+    $p_refgray Delete
+    $p_targgray Delete
+    
+    $combo_ref  Delete
+    $combo_targ Delete
+    $bone_ref  Delete
+    
+    # ---------------------------------------------------------
+    #  Cleaning up
+    # ---------------------------------------------------------
+    
+    $firstdemon Delete
+    
+    ##############################
+    
+    
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_serialdemonmousereg.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+
+    set alg [bis_serialdemonmousereg [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_shiftscaleimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_shiftscaleimage.tcl
new file mode 100755
index 0000000..ac535b0
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_shiftscaleimage.tcl
@@ -0,0 +1,167 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package require bis_castimage 1.0
+
+package provide bis_shiftscaleimage 1.0
+
+#
+# shift sccale image
+#
+
+itcl::class bis_shiftscaleimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Shift/Scale Image" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_shiftscaleimage::Initialize { } {
+
+    PrintDebug "bis_shiftscaleimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ shift "Shift factor" "Shift"  float  0.0 { -100000000.0 100000000.0 }  0 }
+	{ scale "Scale factor " "Scale" float  1.0 { -100000000.0 100000000.0 }  1 }
+	{ abs "Do Absolute Value First" "Do Absolute Value"  { boolean checkbutton } 0 { 0 1 }  -2 }
+	{ type "output image type.Specify one of  Same (same as input), Float , Double or Short" "Ouput Image Type"  listofvalues  Same { Same Short Float Double }  2 }
+    }
+
+    set defaultsuffix { "_ss" }
+    
+    set scriptname bis_shiftscaleimage
+    set completionstatus "Done, needs checking"
+
+
+    set description  "computes linear intensity transformation"
+    set description2 "Output intensity = scale *(Input intensity + shift).Data is thresholded so that the outpu value does not exceed the max or min of the data type."
+    set backwardcompatibility "N/A."
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_shiftscaleimage::Execute {  } {
+
+    PrintDebug "bis_shiftscaleimage::Execute"
+
+    set scale   [ $OptionsArray(scale) GetValue ]
+    set shift   [ $OptionsArray(shift) GetValue ]
+    set type    [ $OptionsArray(type)  GetValue ]
+    set abs    [ $OptionsArray(abs)  GetValue ]
+
+    set image_in [ $InputsArray(input_image) GetObject ]
+
+
+    #vtkImageShiftScale
+    set ft [vtkImageShiftScale [pxvtable::vnewobj]]
+    
+    if { $abs > 0 } {
+	set math [ vtkImageMathematics New ]
+	$math SetInput [ $image_in GetObject ]
+	$math SetOperationToAbsoluteValue
+	$math Update
+	$ft SetInput [ $math GetOutput ]
+	$math Delete
+    } else {
+	$ft SetInput [ $image_in GetObject ]
+	$ft SetShift $shift
+	$ft SetScale $scale
+    }
+	
+    switch $type {
+	Float { 
+	    $ft SetOutputScalarTypeToFloat
+	}
+	Double { 
+	    $ft SetOutputScalarTypeToDouble
+	}
+	Short { 
+	    $ft SetOutputScalarTypeToShort
+	}
+	Same {
+	}
+    }
+    $ft ClampOverflowOn
+    $this SetFilterCallbacks $ft "Shift and Scaling Image"
+    $ft Update
+    set image_out [ $ft GetOutput ]
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage $image_out 
+
+    # Output orientation etc. is same as input
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+
+    $ft Delete
+    return 1
+}
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_shiftscaleimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_shiftscaleimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_singleimagemathoperations.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_singleimagemathoperations.tcl
new file mode 100755
index 0000000..89c4f26
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_singleimagemathoperations.tcl
@@ -0,0 +1,145 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package require bis_resliceimage 1.0
+package provide bis_singleimagemathoperations 1.0
+
+#
+# blend image
+#
+
+itcl::class bis_singleimagemathoperations {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Math Operations"}
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_singleimagemathoperations::Initialize { } {
+
+    PrintDebug "bis_singleimagemathoperations::Initialize" 
+
+    set options {
+	{ mathoperation "Pick math operation" "Pick math operation"  listofvalues Invert { "Invert" "Absolute" "Exp" "Log" "Sin" "Cos" }  1 }
+    }
+	
+	# { guiautoupdate  "Auto Update on changing scale values" "Auto-update"  { boolean } 0 { 0 1 }  2 }
+
+    set defaultsuffix { "_singlemathop" }
+    
+    set scriptname bis_singleimagemathoperations
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    set category "Image Processing Dual"
+    set description "Image to Image algorithm that does more complex operations than bis_imagemathoperations"
+    set description2 "Invert, Exp, Log, Sin, Cos of an image to give an output."
+    set backwardcompatibility " "
+    set authors "alark.joshi at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_singleimagemathoperations::Execute {  } {
+
+    PrintDebug "bis_singleimagemathoperations::Execute"
+
+
+    set mathOpsResult [ vtkImageMathematics [  pxvtable::vnewobj ] ]
+    set mathop        [ $OptionsArray(mathoperation) GetValue ]
+    set image_in      [ $this GetInput ]
+    
+    if { $mathop == "Invert" } {
+	$mathOpsResult SetOperationToInvert
+    } elseif { $mathop == "Absolute" } {
+	$mathOpsResult SetOperationToAbsoluteValue
+    } elseif { $mathop == "Exp" } {
+	$mathOpsResult SetOperationToExp
+    } elseif { $mathop == "Log" } { 
+	$mathOpsResult SetOperationToLog
+    } elseif { $mathop == "Sin" } {
+	$mathOpsResult SetOperationToSin
+    } elseif { $mathop == "Cos" } {
+	$mathOpsResult SetOperationToCos
+    }
+    
+    $mathOpsResult SetInput1  [ $image_in GetImage ]
+    $mathOpsResult Update
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage [ $mathOpsResult GetOutput ]
+
+    # Output orientation etc. is same as input
+    set outimage [ $this GetOutput ] 
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+   
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $mathOpsResult Delete
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_singleimagemathoperations.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+ 
+
+    set alg [bis_singleimagemathoperations [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_singlejacobian.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_singlejacobian.tcl
new file mode 100755
index 0000000..123c4d6
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_singlejacobian.tcl
@@ -0,0 +1,182 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_algorithm 1.0
+package require bis_dualimagetransformationalgorithm 1.0
+package provide bis_singlejacobian 1.0
+
+#
+# compute overlap
+#
+
+
+itcl::class bis_singlejacobian {
+
+    inherit bis_dualimagetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Compute Jacobian"}
+    #
+    #protected
+    #
+
+    protected variable outputs1
+    protected variable outputs2
+    protected variable defaultsuffix1
+    protected variable defaultsuffix2
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_singlejacobian::Initialize { } {
+
+    PrintDebug "bis_singlejacobian::Initialize" 
+
+    set options {
+	{ resolution "resolution" "resolution"  real    3.0 { -1 10.0 }  0 }
+	{ threshold  "jacobian image threshold  " "threshold"  real    0.05 { 0.0 1.0 }  0 }
+	{ mode        "switch output files" "mode"   { listofvalues radiobuttons }  jacobian {jacobian tensor strains  }  0 }
+
+    }
+
+    set defaultsuffix  { "jacobian" }
+    set defaultsuffix1 { "_raw" }
+    set defaultsuffix2 { "_combined" "_nonlinear" }
+    
+    set scriptname bis_singlejacobian
+
+    #
+    #document
+    #
+
+    set category "Registration"
+    set description "computes either the determinant of the jacobian or the full tensor for a transformation."
+    set description2 ""
+    set backwardcompatibility "Reimplemented from pxsinglejacobian.tcl"
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this InitializeDualImageTransformationAlgorithm
+
+    $this RenameInput 1 "(Not used)" 101  
+}
+
+itcl::body bis_singlejacobian::Execute {  } {
+
+    PrintDebug "bis_singlejacobian::Execute"
+
+    set resolution   [ $OptionsArray(resolution) GetValue ]
+    set threshold    [ $OptionsArray(threshold) GetValue ]
+    set mode         [ $OptionsArray(mode) GetValue ]
+
+    set refimage  [ $this GetInput ] 
+    set transform [ $this GetTransformation ]
+    set outimage  [ $this GetOutput ]
+
+    set spa  [ lindex [[ $refimage GetObject ] GetSpacing ] 0 ]
+
+    set reg    [ vtkpxRegistration [ pxvtable::vnewobj ] ]
+    set newimg [ vtkImageData      [ pxvtable::vnewobj ] ]
+ 
+    set imcast [ vtkImageCast [ pxvtable::vnewobj ]]
+    $imcast SetInput  [ $refimage GetObject ]
+    $imcast SetOutputScalarTypeToFloat
+    $imcast Update
+
+    if { $resolution > 1.0 } {
+
+	if { $resolution > 10.0 } {
+	    set resolution 10.0
+	} 
+	
+	set spa [ $newimg GetSpacing ]
+	for { set i 0 } { $i <=2 } { incr i } {
+	    set sp($i) [ expr $resolution*[ lindex $spa $i ] ]
+	}
+
+	set resl [ vtkImageResample [ pxvtable::vnewobj ] ]
+	$resl SetAxisOutputSpacing 0 $sp(0)
+	$resl SetAxisOutputSpacing 1 $sp(1)
+	$resl SetAxisOutputSpacing 2 $sp(2)
+	$resl InterpolateOff
+	$resl SetDimensionality 3
+	$resl SetInput [ $imcast GetOutput ]
+	$resl Update
+	$newimg ShallowCopy [ $resl GetOutput ]
+	$resl Delete
+    } else {
+	$newimg ShallowCopy [ $refimage GetObject ]
+    }
+
+    $outimage ShallowCopyImage $newimg
+
+    switch -exact $mode { 
+	"tensor"   { $reg ComputeJacobianImage       $newimg [ $outimage GetObject ] [ $transform GetObject ] 1 1.0 $threshold }
+	"strains"  { $reg ComputePrincipalStrains    $newimg [ $outimage GetObject ] [ $transform GetObject ] $threshold }
+	"jacobian" { $reg ComputeSimpleJacobianImage $newimg [ $outimage GetObject ] [ $transform GetObject ] 100.0 1.0 $threshold }
+    }
+
+    $outimage CopyImageHeader [ $refimage GetImageHeader ]
+
+    $reg    Delete
+    $newimg Delete
+    $imcast Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  You may need not modify this method
+# ----------------------------------------------------------------------------------------
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_singlejacobian.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_singlejacobian [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_singlesubjectfmri.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_singlesubjectfmri.tcl
new file mode 100755
index 0000000..ff66516
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_singlesubjectfmri.tcl
@@ -0,0 +1,218 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+
+package require bis_algorithm 1.0
+package require bis_fmrisetup 1.0
+package provide bis_singlesubjectfmri 1.0
+
+#
+# Operations involving multisubject average for testing ....
+#
+
+itcl::class bis_singlesubjectfmri {
+
+    inherit bis_algorithm
+    
+    constructor { } {
+	$this Initialize
+    }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "MultiSubject fMRI" }
+    public method UpdateContainerWithOutput { } 
+}
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_singlesubjectfmri::Initialize { } {
+
+    PrintDebug "bis_singlesubjectfmri::Initialize" 
+
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set inputs { }
+
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ setup "Input .xmlg Setup file name" "Setup Name:"  { filename readfile }  "" { "Setup Files" { .xmlg}} 1 }
+	{ setup2 "Optional Second .xmlg Setup file name" "Second Setup Name:"  { filename readfile }  "" { "Setup Files" { .xmlg}} 1 }
+	{ mode "Operation to perform" "Mode"  listofvalues  glm { glm seed matrix taskseed whole ipsi contra }   2}
+	{ guilabel  "Current XML Tree Name" "Tree Name"  comment  "         " ""  6 }
+	{ outdir  "Specify the output directory for the results" "Output Directory" { filename directory 40 } "" "" 4 }
+	{ tmpresults "If on then results will be deleted on exit (use for testing)" "Discard Results"  boolean  0 { 0 1 }  5 }
+    }
+
+    set outputs { 
+	{ output_image "Output Image"  pxitclimage  "" 101 }
+	{ output2 "Output 2"  pxitclimage  "" 102 }
+	{ output3 "Output 3"  pxitclimage  "" 103 }
+	{ output4 "Output 4"  pxitclimage  "" 104 }
+	{ output5 "Output 5"  pxitclimage  "" 105 }
+	{ output6 "Output 6"  pxitclimage  "" 106 }
+	{ output7 "Output 7"  pxitclimage  "" 107 }
+	{ output8 "Output 8"  pxitclimage  "" 108 }
+	{ output9 "Output 9"  pxitclimage  "" 109 }
+    }
+
+
+    set defaultsuffix { "_singlesubject" }
+
+    
+    set scriptname bis_singlesubjectfmri
+    set completionstatus ""
+    #
+    #document
+    #
+    set category "Functional Imaging"
+    set description "Mostly a test class for bis_fmrisetup.tcl based single subject fMRI Operations"
+    set description2 ""
+    set backwardcompatibility "Uses bis_fmrisetup.tcl"
+    set authors "xenophon.papademetris.yale.edu"
+
+    $this AddDefaultOptions
+
+
+}
+
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_singlesubjectfmri::UpdateContainerWithOutput { } {
+
+    set img  [ $this GetOutputObject output_image ] 
+
+    PrintDebug "In Update Container With Output $this, $img [ $img GetDescription ]\n"
+    if { $containerobject == 0 } {
+	if { $bis_viewer !=0 } {
+	    $bis_viewer SetImage $img
+	}  elseif { $vtk_viewer !=0 } {
+	    $vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+	} 
+    } else {
+	PrintDebug "Calling Container ($this, $containerobject) SetResultsFromObject" 
+	$containerobject SetResultsFromObject $img $this
+	# Unload result at this point
+	$img Clear
+    }
+}
+
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_singlesubjectfmri::Execute {  } {
+
+    set fname [ $OptionsArray(setup) GetValue ]
+    set fname2  [ $OptionsArray(setup2) GetValue ]
+    set mode [ $OptionsArray(mode) GetValue ]
+    set outdir   [ $OptionsArray(outdir) GetValue ]
+    set tmpmode [ $OptionsArray(tmpresults) GetValue ]
+
+    if { [ string length $fname2 ] < 3 } {
+	set fname2 "_do_not_use"
+    }
+
+    if { $fname == "" } {
+	set errormessage "Must set setup file to non empty value"
+	return 0
+    }
+
+    set outdir [ $OptionsArray(ctesttmpdir)  GetValue ]
+    set outdir [ $this CreateTempOutputDirectory $outdir ]
+    
+    if { [ file writable $outdir ] == 0 } {
+	set errormessage "Output directory $outdir is not writable by the current user"
+	return 0
+    }
+    
+    
+    puts stdout "Parameters = $fname, ($fname2) mode=$mode, outdir=$outdir"
+
+    set arglist [ list $fname $mode $fname2 $outdir ]
+
+
+    set alg [bis_fmrisetup \#auto ]
+    set status [ $alg MainFunction [ llength $arglist ] $arglist  ]
+    set ok [ lindex $status 0 ]
+    if { $ok == 0 } {
+	set errormessage [ lindex $status 1 ]
+	itcl::delete obj $alg
+	catch { $OptionsArray(guilabel) SetValue "Failed" }
+	return 0
+    }
+
+    catch { $OptionsArray(guilabel) SetValue  [ $alg GetDataManagerFilename ]  }
+
+
+    set dm [ $alg GetDataManager ]
+    set nd [ $dm FindNode "Outputs" ]
+
+    set numout [ llength [ $this GetOutputsList ] ]
+
+    for { set j 0 } { $j < [ $nd GetNumberOfNestedElements ] } { incr j } {
+	set child [ $nd GetNestedElement $j ]
+	set f [ $child GetAttribute Filename ]
+	if { $j < $numout } {
+	    set obj [ $this GetOutputObjectByIndex $j ]
+	    $obj Load $f
+	    if { $guimode == "commandline" } {
+		$obj configure -filename ""
+	    }
+	    puts stdout "Storing output $j/ $numout = $f"
+	}
+    }
+
+    itcl::delete obj $alg
+    if { $tmpmode > 0 } {
+	set tst [ $this RemoveTempOutputDirectory $outdir ]
+	puts stdout "Deleting $outdir, success=$tst"
+    }
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_singlesubjectfmri.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_singlesubjectfmri [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_skeletonizeimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_skeletonizeimage.tcl
new file mode 100755
index 0000000..b0e3f89
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_skeletonizeimage.tcl
@@ -0,0 +1,153 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_skeletonizeimage 1.0
+package require bis_imagetoimagealgorithm 1.0
+package require bis_distancemapimage 1.0
+
+
+itcl::class bis_skeletonizeimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Skeletonize Image" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_skeletonizeimage::Initialize { } {
+
+    PrintDebug "bis_skeletonizeimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+ 	{ dodistance     "Compute Distance Map as Output"  "Do Distance Map"    boolean  0 { 0 1}        4 }
+    }
+
+    set defaultsuffix { "_skel" }
+    
+    set scriptname bis_skeletonizeimage
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Create a skeleton and/or a distance map from a binarized image. if dodistance is 1 multiples by inverse distance map"
+    set description2 "Skeletonization code comes from Homann H., ``Implementation of a 3D thinning algorithm''. Oxford University, Wolfson Medical Vision Lab. Insight Journal Dec 2007"
+    set backwardcompatibility "None"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_skeletonizeimage::Execute {  } {
+
+    PrintDebug "bis_skeletonizeimage::Execute"
+    set dodistance   [ $OptionsArray(dodistance) GetValue ]
+    set image_in [ $this GetInput ]
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+
+    set skeletonize  [ vtkbisBinaryThinningFilter New ]
+    $skeletonize SetInput [ $image_in GetImage ]
+    $this SetFilterCallbacks $skeletonize "Skeletonizing Image"
+    $skeletonize Update
+
+    if { $dodistance > 0 } {
+	set dist_alg [bis_distancemapimage [pxvtable::vnewobj]]
+	$dist_alg InitializeFromContainer $this
+	$dist_alg SetInput $image_in
+	$dist_alg SetOptionValue minth -1.0
+	$dist_alg SetOptionValue maxth  0.5
+	$dist_alg SetOptionValue radius 1
+	$dist_alg Execute
+
+	set cst [ vtkImageCast New ]
+	$cst SetInput [ [ $dist_alg GetOutput ] GetImage ] 
+	$cst SetOutputScalarType [ [ $skeletonize GetOutput ] GetScalarType ]
+	$cst Update
+
+	puts stdout "Computing Distance map"
+	set mth [ vtkImageMathematics New ]
+	$mth SetInput1 [ $skeletonize GetOutput ]
+	$mth SetInput2 [ $cst GetOutput ]
+	$mth SetOperationToMultiply
+	$this SetFilterCallbacks $mth "Multiplying Distance map with Skeleton Image"
+	$mth Update
+	
+	$outimage ShallowCopyImage [ $mth GetOutput ]
+	$mth Delete
+	$cst Delete
+	itcl::delete obj $dist_alg
+    } else {
+	$outimage ShallowCopyImage [ $skeletonize GetOutput ]
+    }
+
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $skeletonize Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_skeletonizeimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_skeletonizeimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_sliceinhomogeneity.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_sliceinhomogeneity.tcl
new file mode 100755
index 0000000..a5b111a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_sliceinhomogeneity.tcl
@@ -0,0 +1,179 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+
+package provide bis_sliceinhomogeneity 1.0
+
+#
+# bias field correction
+#
+
+itcl::class bis_sliceinhomogeneity {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Slice Inhomogeneity" }
+
+    #
+    #protected
+    #
+
+    protected method RunSliceHomogeneity   { inputimage } 
+    protected method RunTripleSliceHomogeneity   { inputimage } 
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_sliceinhomogeneity::Initialize { } {
+
+    PrintDebug "bis_sliceinhomogeneity::Initialize" 
+    #name,description,type,object,filename(if applicable),priority (optional)
+
+
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ dotriple "if off do slice else tripleslice. When dotriple is off, the algorithm computes inhomogeneity along the slice direction, else this is computed for all three axis" "DoTriple" boolean 0 { 0 1 } 0 }
+    }
+    
+    set defaultsuffix { "_inhom"  }
+    
+    set scriptname bis_sliceinhomogeneity
+
+    #
+    #document
+    #
+
+    set category "Image Processing Dual"
+    set description "corrects  slice inhomogeneity correction for MRI acquisitions."
+    set description2 "Single slice is default, triple slice is useful as a crude bias field correction for high field acquisitions."
+    set backwardcompatibility "Reimplemented from pxmat_biasfieled.tcl. "
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this InitializeImageToImageAlgorithm
+
+}
+# ---------------------------------------------------------------------------------------------------------
+
+itcl::body bis_sliceinhomogeneity::RunSliceHomogeneity   { inputimage } { 
+
+    set fit [ vtkpxSliceBiasFieldCorrection  [ pxvtable::vnewobj ]]
+    $this SetFilterCallbacks $fit "Slice Correction"
+    $fit SetPureScaling 0
+    $fit SetInput       $inputimage
+
+	
+    $fit Update
+
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+    $img ShallowCopy [ $fit GetOutput ]
+    $fit Delete
+    return  $img 
+}
+# ----------------------------------------------------------------------------------------------------
+itcl::body bis_sliceinhomogeneity::RunTripleSliceHomogeneity   { inputimage } { 
+
+    set axislist { x y z }
+
+    set output [ vtkImageData [ pxvtable::vnewobj ]]
+    $output ShallowCopy $inputimage
+    
+    for { set axis 0 } { $axis <=2 } { incr axis } {
+	set nm [ lindex $axislist $axis ]
+	puts stderr ".... Slice Inhomogeneity Correction orientation  axis= [ lindex $axislist $axis ]\n"
+	set fit [ vtkpxSliceBiasFieldCorrection New ]
+	$fit SetAxis $axis
+	$this SetFilterCallbacks $fit "Axis $nm Correction"
+	$fit SetPureScaling 0
+	$fit SetInput       $output
+	$fit Update
+	$output ShallowCopy [ $fit GetOutput ]
+	$fit Delete
+    }
+    return  $output
+}
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_sliceinhomogeneity::Execute {  } {
+
+    DebugOn
+    PrintDebug "bis_sliceinhomogeneity::Execute"
+
+    set mode        [ $OptionsArray(dotriple)      GetValue ]
+    set image_in    [ $InputsArray(input_image) GetObject ]
+    
+
+    if { $mode ==  0 } {
+	puts stdout "Running Slice"
+	set outimg [ RunSliceHomogeneity [$image_in GetObject]]
+    } else {
+	puts stderr "Running Triple Slice"
+	set outimg [ RunTripleSliceHomogeneity [$image_in GetObject]]
+    }
+    
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage $outimg
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ $this GetCommandLine "full" ]
+    [ $outimage GetImageHeader ] AddComment $comment 0
+
+    $outimg Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_sliceinhomogeneity.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_sliceinhomogeneity [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_smoothimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_smoothimage.tcl
new file mode 100755
index 0000000..465732c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_smoothimage.tcl
@@ -0,0 +1,156 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_smoothimage 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+itcl::class bis_smoothimage {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Smooth Image" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_smoothimage::Initialize { } {
+
+    PrintDebug "bis_smoothimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ blursigma "kernel size [mm/voxel] of FWHM filter size" "Filter Size"  { real triplescale 100 }    2.0 { 0.0 20.0 }  0 }
+	{ unit      "kernel size unit mm or voxels " "Units" { listofvalues default }  mm { mm voxels }   1}
+	{ radius    "radius factor of the gaussian in voxel units " "Filter Radius" real  1.5   { 0.0 5.0 }  -1 }
+	{ dimension  "2 or 3 to to do smoothing in 2D or 3D" "Dimensionality"  { listofvalues radiobuttons }    3 { 2  3 }  -999 }
+    }
+
+
+    set defaultsuffix { "_sm" }
+    
+    set scriptname bis_smoothimage
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Smoothes an image with a specific gaussian kernel."
+    set description2 "Smoothing kernel size blursigma (in mm by default ) represents the FWHM filter size."
+    set backwardcompatibility "Reimplemented from pxmat_smoothimage.tcl. unit and radius options are  added. Multiple image processing eliminated,which will be recovered upon request. "
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_smoothimage::Execute {  } {
+
+    PrintDebug "bis_smoothimage::Execute"
+
+    set blursigma   [ $OptionsArray(blursigma) GetValue ]
+    set unit        [ $OptionsArray(unit)      GetValue ]
+    set radius      [ $OptionsArray(radius)    GetValue ]
+    set dimension   [ $OptionsArray(dimension)    GetValue ]
+    set image_in    [ $this GetInput ]
+
+    set spacing [[ $image_in GetImage ] GetSpacing ]
+
+    if { $unit == "mm"} {
+	for { set j 0 } { $j <=2 } { incr j } {
+	    set sigma($j) [ expr $blursigma * 0.4247 / [ lindex $spacing $j ]]
+#	    puts stdout "Axis = $j Voxels in=$blursigma out=$sigma($j)  (spacing=[lindex $spacing $j ])"
+	}
+    } else {
+	for { set j 0 } { $j <=2 } { incr j } {
+	    set sigma($j) [ expr $blursigma * 0.4247 ]
+#	    puts stdout "Axis = $j MM in=$blursigma out=$sigma($j)  (spacing=[lindex $spacing $j ])"
+	}
+    }
+
+    set radiusz $radius
+    if { $dimension == 2 } {
+	set radiusz 0
+	set sigma(2) 0.0
+    }
+
+
+    $this PrintMessage "Smoothing radius = $radius,$radius,$radiusz, sigma = $sigma(0) $sigma(1) $sigma(2)\n"
+    set smooth  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+    $smooth SetStandardDeviations $sigma(0) $sigma(1) $sigma(2)
+    $smooth SetRadiusFactors $radius $radius $radiusz
+    $smooth SetInput [ $image_in GetObject ]
+    $this SetFilterCallbacks $smooth "Smoothing Image"
+    $smooth Update
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $smooth GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $smooth Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_smoothimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_smoothimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_smoothlandmarks.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_smoothlandmarks.tcl
new file mode 100755
index 0000000..fee3ca6
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_smoothlandmarks.tcl
@@ -0,0 +1,120 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_landmarkstolandmarksalgorithm 1.0
+
+package provide bis_smoothlandmarks 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_smoothlandmarks {
+
+    inherit bis_landmarkstolandmarksalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Smooth Landmarks" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_smoothlandmarks::Initialize { } {
+
+    PrintDebug "bis_smoothlandmarks::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ factor "Specify the relaxation factor for  smoothing" "Relaxation factor"  { real triplescale 100 }    0.33 { 0.0 1.0 }  1 }
+    }
+
+    set defaultsuffix { "_smooth" }
+    
+    set scriptname bis_smoothlandmarks
+
+    #
+    #document
+    #
+    set category "Landmarks Processing"
+    set description  "Smoothing a curve stored as landmarks"
+    set description2 ""
+    set backwardcompaibitlity "Newly added."
+    set authors "xenophon.papademetris at yale.edu"
+
+    $this InitializeLandmarksToLandmarksAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_smoothlandmarks::Execute {  } {
+
+    PrintDebug "bis_smoothlandmarks::Execute"
+
+    # Get Inputs
+    set landmarks    [ $this GetInput  ]
+    # GetOptions
+    
+    set factor [ $OptionsArray(factor)      GetValue ]
+
+    set out [ $this GetOutput ]
+    [ $out GetLandmarks ] Compact
+
+    $out CopyLandmarks [  $landmarks  GetLandmarks ]
+    [ $out GetLandmarks ] Smooth $factor
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_smoothlandmarks.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_smoothlandmarks [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_smoothsurface.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_smoothsurface.tcl
new file mode 100755
index 0000000..b0f6404
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_smoothsurface.tcl
@@ -0,0 +1,150 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_surfacetosurfacealgorithm 1.0
+
+package provide bis_smoothsurface 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_smoothsurface {
+
+    inherit bis_surfacetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Smooth Surface" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_smoothsurface::Initialize { } {
+
+    PrintDebug "bis_smoothsurface::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ iterations "Number of iterations for smoothing" "Number of iterations"  { integer triplescale 100 }    5 { 0 200 }  0 }
+	{ relaxationfactor "Specify the relaxation factor for Laplacian smoothing" "Relaxation factor"  { real triplescale 100 }    0.2 { 0.0 1.0 }  1 }
+	{ smoothBoundary "Turn on/off the smoothing of vertices on the boundary of the mesh. " "Smooth Boundaries (Sinc)" { boolean }  0 { 0 1}   2}
+	{ smoothMethod "Pick a smoothing method: Laplacian or Windowed Sinc. " "Smooth Method" { listofvalues radiobutton}  Laplacian { Laplacian Windowed_Sinc}   3}
+    }
+
+    set defaultsuffix { "_smooth" }
+    
+    set scriptname bis_smoothsurface
+
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "smoothing a surface"
+    set description2 ""
+    set backwardcompaibitlity "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeSurfacetoSurfaceAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_smoothsurface::Execute {  } {
+
+    PrintDebug "bis_smoothsurface::Execute"
+
+    # Get Inputs
+    set surface    [ $this GetInput  ]
+    # GetOptions
+    
+	set iterations [ $OptionsArray(iterations) GetValue ]
+	set relaxationfactor [ $OptionsArray(relaxationfactor)      GetValue ]
+	set smoothBoundary     [ $OptionsArray(smoothBoundary)    GetValue ]
+	set smoothMethod [ $OptionsArray(smoothMethod)    GetValue ]
+	
+    # Run Algorithm
+    
+    if { $smoothMethod == "Laplacian"} {
+		set filter [ vtkSmoothPolyDataFilter [ pxvtable::vnewobj ] ]
+		$filter SetInput [ $surface GetObject ]
+		$filter SetNumberOfIterations $iterations
+		$filter SetRelaxationFactor $relaxationfactor
+		$filter Update
+	} else {
+		set filter [vtkWindowedSincPolyDataFilter [ pxvtable::vnewobj ] ]
+		$filter SetInput [ $surface GetObject ]
+		$filter SetNumberOfIterations $iterations
+
+		if { $smoothBoundary == "1"} {
+				$filter BoundarySmoothingOn  	
+		} else {
+				$filter BoundarySmoothingOff  	
+    	}
+    	$filter Update
+	}
+	
+    
+    # Store Results in output
+    set surface_out [$filter GetOutput ]
+    [ $OutputsArray(output_surface) GetObject ] DeepCopySurface $surface_out 
+
+    # Clean up
+    $filter Delete
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_smoothsurface.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_smoothsurface [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_spectbase.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_spectbase.tcl
new file mode 100644
index 0000000..673fedc
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_spectbase.tcl
@@ -0,0 +1,269 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_spectbase 1.0
+
+package require bis_dualimagealgorithm  1.0
+package require bis_imagemathoperations 1.0
+package require bis_smoothimage         1.0
+package require bis_thresholdimage      1.0
+package require bis_proportionalscale   1.0 
+package require bis_castimage           1.0 
+
+itcl::class bis_spectbase {
+
+    inherit bis_dualimagealgorithm
+
+    constructor { } { }
+
+    public method InitializeBaseSpect { }
+
+    protected method cast            { img type }
+    protected method mathops         { img1 img2 op }
+    protected method smooth          { image }   
+    protected method propScale       { image }
+    protected method createBrainMask { img1 img2 img3 } 
+    protected method createTmap      { ict int std { mean 0 } }
+    protected method delete          { args } 
+    protected method loadImage       { fname }
+
+    private variable imgPath        ""
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_spectbase::InitializeBaseSpect { } {
+
+    PrintDebug "bis_basespce::InitializeBaseSpect" 
+
+    set tmp $inputs
+    set inputs {
+	{ stdimage   "Standard Deviation Spect Image (Optional)"    pxitclimage  "" 300 }
+	{ maskimage  "Mask for Analysis (Optional)"             pxitclimage  "" 500 }
+    }
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend inputs [ lindex $tmp $i ]
+    }
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ usemask   "Mask used to remove the skull on spect images" "Brain Mask" boolean 1    { 0 1 }      0 }
+	{ smoothval "FWHM Gaussian smoothing kernel in mm"          "FWHM"       real    16.0 { 0.0 20.0 } 2 }  
+
+    }
+
+    set defaultsuffix { "_sm" }
+    
+    set scriptname bis_spectbase
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description1 "A diff SPECT processing algorithm for epilepsy"
+    set category "DiffSPECT"
+    set backwardcompatibility "ISAS see http://spect.yale.edu"
+    set authors "dustin.scheinost at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this InitializeDualImageAlgorithm
+
+    $this RenameInput 0 "Interictal SPECT"
+    $this RenameInput 1 "Ictal SPECT"
+
+    set imgPath [ file join [ file join [ file dirname [ info script ] ] ".." ] images ]
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_spectbase::cast { img1 type } {
+
+    set cast [ bis_castimage [ pxvtable::vnewobj ] ]
+    $cast InitializeFromContainer $this
+
+    $cast SetInput       $img1
+    $cast SetOptionValue type $type
+    $cast Execute
+  
+    set out [ [ pxitclimage \#auto ] GetThisPointer ]
+    $out ShallowCopy  [ $cast GetOutput ] 
+    itcl::delete object $cast 
+
+    return $out
+ }
+
+itcl::body bis_spectbase::mathops { img1 img2 op } {
+
+    set mathop [ bis_imagemathoperations [ pxvtable::vnewobj ] ]
+    $mathop InitializeFromContainer $this
+
+    $mathop SetInput       $img1
+    $mathop SetSecondInput $img2
+    $mathop SetOptionValue mathoperation $op
+    $mathop Execute
+  
+    set out [ [ pxitclimage \#auto ] GetThisPointer ]
+    $out ShallowCopy  [ $mathop GetOutput ] 
+    itcl::delete object $mathop 
+
+    return $out
+ }
+
+itcl::body bis_spectbase::smooth { image} {
+
+    set smoothingSigma [ expr { [ $OptionsArray(smoothval) GetValue ] / sqrt( 8 * log(2) ) } ]
+    
+    set spa [ [ $image GetImage ] GetSpacing ]
+    
+    for { set i 0 } { $i <= 2 } { incr i } {
+	set sigma($i) [ expr $smoothingSigma / [ lindex $spa $i ]]             
+    }
+
+    set sm  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+    $sm SetStandardDeviations $sigma(0) $sigma(1) $sigma(2)
+    $sm SetRadiusFactors [ expr round(6*$sigma(0)) ] [ expr round(6*$sigma(1)) ] [ expr round(6*$sigma(2)) ]
+    $sm SetInput [ $image GetImage ]
+    $sm Update
+
+    set out [ [ pxitclimage \#auto ] GetThisPointer ]
+    $out ShallowCopyImage [ $sm GetOutput ] 
+    $out CopyImageHeader  $image
+    $sm Delete
+
+    return $out
+}
+
+itcl::body bis_spectbase::propScale { image} {
+ 
+    set scale [ bis_proportionalscale [ pxvtable::vnewobj ] ]
+    $scale InitializeFromContainer $this
+        
+    $scale SetInput $image
+    $scale SetOptionValue threshold 0.8
+    $scale SetOptionValue mean 50
+    $scale Execute
+  
+    set out [ [ pxitclimage \#auto ] GetThisPointer ]
+    $out ShallowCopy  [ $scale GetOutput ] 
+    itcl::delete object $scale
+
+    return $out
+}
+
+itcl::body bis_spectbase::createBrainMask { img1 img2 img3 } {
+    
+    catch { itcl::delete object $thresholdimage }
+    
+    set thresholdimage [ bis_thresholdimage [ pxvtable::vnewobj ] ]
+    $thresholdimage InitializeFromContainer $this
+    
+    $thresholdimage SetInput [ mathops $img1 [ mathops $img2 $img3 Multiply ] Multiply ]
+    $thresholdimage SetOptionValue minth 0.0000001
+    $thresholdimage SetOptionValue maxth 1000000000000000000000000
+    $thresholdimage SetOptionValue binary On
+    $thresholdimage Execute 
+   
+    set out [ [ pxitclimage \#auto ] GetThisPointer ]
+    $out ShallowCopy  [ $thresholdimage GetOutput ] 
+    itcl::delete object $thresholdimage
+
+    return $out
+}
+
+itcl::body bis_spectbase::createTmap { ict int std { mean 0 } } {
+
+    set sub [ mathops $ict $int Subtract ]
+
+    if { $mean != 0 } {
+	set sub [ mathops $sub $mean Subtract ]
+    }
+
+    set tmp [ mathops $sub $std Divide ]
+
+    ::itcl::delete object $sub 
+
+    return $tmp
+}
+
+itcl::body bis_spectbase::delete { args } { 
+ 
+    foreach item $args {
+	catch { itcl::delete object $item } 
+    }
+}
+
+itcl::body bis_spectbase::loadImage { fname } { 
+    
+    set fileName [ file join $imgPath $fname ] 
+    set img [ [ pxitclimage [ pxvtable::vnewobj ] ] GetThisPointer ]
+    
+    if { [ file exists $fileName ] } {
+	$img Load $fileName
+	return $img
+    } 
+    
+    if { [ file exists $fname ] } {
+	$img Load $fname
+	return $img
+    } 
+
+    if { [ GetGUIMode ] != "commandline" } {
+	tk_messageBox -type ok -message "Could not find $fileName. Please set load it now." -icon error
+	if { [ $img Load "" ] } { 
+	    return $img
+	} else {
+	    itcl::delete object $img; return 0
+	}
+    }
+    
+    itcl::delete object $img
+
+    puts stdout "Could not find $fileName. Please now the full path for $fname now or Q to quit.\n" 
+    gets stdin  newImage
+
+    if { $newImage == "Q" || $newImage == "q" } {
+	return 0
+    } else {
+	return [ loadImage $newImage ]
+    }
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_spectrf.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_spectrf.tcl
new file mode 100755
index 0000000..8233cea
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_spectrf.tcl
@@ -0,0 +1,215 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_spectrf 1.0
+package require bis_imagetoimagealgorithm 1.0
+package require bis_imagemathoperations 1.0
+package require bis_shiftscaleimage 1.0
+package require bis_thresholdimage      1.0
+
+itcl::class bis_spectrf {
+
+    inherit bis_imagetoimagealgorithm
+
+    constructor { } {	 $this Initialize  }
+    
+    public method WriteOutput   { fname outputList } 
+    public method Initialize    { }
+    public method Execute       { }
+    public method GetGUIName    { } { return "Calculate RF" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_spectrf::Initialize { } {
+
+    PrintDebug "bis_spectrf::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ savefile "Generate and save an output text file" "Save results to text file" boolean 0 { 0 1 } 20 }
+	{ filename   "specify the filname for the output text file" "Text File Name" { filename writefile } "spectrf_result.txt" { text { .txt } } 30 }
+	{ mode "Perform Hyperperfusion or Hypoperfusion statistics" "Mode"  { listofvalues radiobuttons } hyper { hyper hypo } 0 }
+	{ sig  "P-value Signigicance level threshold" "Significance"        real 0.01 { 0.00000000000000001 1 }  0 }
+	{ ext  "Minimum cluster size used for analysis" "Extent Threshold"  real 125  { 1  1000000 }             1 }
+
+    }
+
+    set scriptname bis_spectrf
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    set category "DiffSPECT"
+    set description "Computes Statistics for DIFF Spect Analysis"
+    set description2 ""
+    set backwardcompatibility ""
+
+    set author "dustin.scheinost at yale.edu"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_spectrf::WriteOutput { fname outputList } {
+
+    set fileid [ open $fname w ]
+    puts $fileid "\n#Vxs\tuncorrPvalue \tcorrPvalue \tmaxTscore \tX \tY \tZ"
+    for { set index1 1 } { $index1 <= [ llength $outputList ] } { incr index1 } {
+	set out ""
+	for { set index2 0 } { $index2 < 7 } { incr index2 } {
+	    set out  "$out[ lindex [ lindex $outputList [ expr $index1 - 1 ] ] $index2 ]\t" 
+	}
+	puts $fileid $out
+	}
+    close $fileid
+}
+
+itcl::body bis_spectrf::Execute {  } {
+    
+    PrintDebug "bis_spectrf::Execute"
+
+    set tmap   [ $this GetInput ]
+    set extThr [ $OptionsArray(ext)      GetValue ]
+    set sigThr [ $OptionsArray(sig)      GetValue ] 
+    set mode   [ $OptionsArray(mode)     GetValue ]
+    set save   [ $OptionsArray(savefile) GetValue ]
+    set fname  [ $OptionsArray(filename) GetValue ]
+
+    #convert p to t
+    set Pvalue [ vtkpxMath [ pxvtable::vnewobj ] ]
+    set tscore [ $Pvalue PvalueToTvalue [ expr $sigThr * 2 ] 14 ]
+
+    $Pvalue Delete
+ 
+    #calculating euler density
+    set tmp [ expr pow(1+$tscore*$tscore/13,-6) ]
+    set eulerDensity(0) $sigThr
+    set eulerDensity(1) [ expr 0.2650*$tmp ]
+    set eulerDensity(2) [ expr 0.1727*$tscore*$tmp ] 
+    set eulerDensity(3) [ expr 0.1169*$tmp*(12*$tscore*$tscore/13-1) ]
+    set expectedVoxPerCluster [ expr $eulerDensity(0) / $eulerDensity(3) ]  
+
+    #calculate resel count
+    set util [ vtkdsSpectUtil [ pxvtable::vnewobj ] ]
+    set expectedNumOfCluster [ $util reselCount [ $tmap GetObject ] $eulerDensity(0) $eulerDensity(1) $eulerDensity(2) $eulerDensity(3) ]
+  
+    set clusterThreshold [ vtknrImageCluster [ pxvtable::vnewobj ] ]
+    $clusterThreshold SetInput [ $tmap GetObject ]
+    $clusterThreshold SetIntensityThreshold $tscore
+    SetFilterCallbacks $clusterThreshold "Clustering image"
+    $clusterThreshold Update
+
+    if  { $mode == "hypo" } {
+	set math [ bis_shiftscaleimage [ pxvtable::vnewobj ] ]
+	$math InitializeFromContainer $this
+	$math SetInput $tmap
+	$math SetOptionValue scale -1.0
+	$math Execute
+	set tmap2 [ $math GetOutput ]
+    }  else { 
+	set tmap2 $tmap 
+    }
+
+    #new way
+    set clusterInfo [ $util ClusterImage [ $tmap2 GetObject ] [ $clusterThreshold GetClusterNumberImage ]\
+			  [ $clusterThreshold GetOutput ] $expectedVoxPerCluster $expectedNumOfCluster $tscore $extThr ]
+
+    set numComponents [ $clusterInfo GetNumberOfComponents ]
+    set numTuples [ $clusterInfo GetNumberOfTuples ]
+    set outputList [ list ]
+
+    if { $numTuples < 1 } {
+	puts "No significant clusters found"
+	return 2
+    }
+
+    #Note: for some reason tuple and compoments labeling gets switch
+    #numComponents is actually the number of tuples in the out image
+    #and vice versa for the numTuples
+    set img [ vtkImageData [ pxvtable::vnewobj ] ]
+    $img SetDimensions $numComponents 1 1
+    $img SetWholeExtent 0 [ expr $numComponents - 1 ] 0 0 0 0
+    $img SetNumberOfScalarComponents $numTuples
+    $img SetScalarTypeToFloat 
+    $img AllocateScalars
+    
+    for { set tupleCount 0 } { $tupleCount<$numTuples } { incr tupleCount } {
+	set tempList [ list ]
+	for { set compCount 0 } { $compCount<$numComponents } { incr compCount } {	  
+	    $img SetScalarComponentFromFloat $compCount 0 0 $tupleCount [ $clusterInfo GetComponent $tupleCount $compCount ]
+	    lappend tempList [ $clusterInfo GetComponent $tupleCount $compCount ]
+	    puts "for $tupleCount $compCount the value is [ $clusterInfo GetComponent $tupleCount $compCount ]"
+	}
+	lappend outputList $tempList
+    }
+    set outputList [ lsort -increasing -index 1 -real $outputList ]
+
+    if { $save } { 
+	$this WriteOutput $fname $outputList 
+    }
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage $img    
+
+    $util Delete
+    $img Delete
+    catch { itcl::delete object $math }
+    return 1 ; # return 0 for error, 1 to save object, 2 to not save object
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_spectrf.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_spectrf [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_split4dimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_split4dimage.tcl
new file mode 100755
index 0000000..0652420
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_split4dimage.tcl
@@ -0,0 +1,184 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_algorithm 1.0
+
+package provide bis_split4dimage 1.0
+
+#
+# split4d image
+#
+
+itcl::class bis_split4dimage {
+
+    inherit bis_algorithm
+    
+    constructor { } {
+	$this Initialize
+    }
+    
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Split 4D Image" }
+}
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_split4dimage::Initialize { } {
+
+    PrintDebug "bis_split4dimage::Initialize" 
+
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set inputs {
+	{ input_image "input 4D image" pxitclimage  ""  }
+    }
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ begin       "begin frame" "begin frame" int 1  {1 1000} 0 }
+	{ end         "end   frame" "end frame"   int 1000  {1 1000} 1 }
+	{ ostem       "Stem of output filename, if set output files will be ostem_frame.extension, else the input name is used" "Output Stem"  string "" { "" } 2}
+
+    }
+
+    set defaultsuffix { "" }
+    #default output is created by rule2
+    
+    set scriptname bis_split4dimage
+    set completionstatus "Xenios has revisited  this -- looks almost done"
+    #
+    #document
+    #
+    set category "Utility"
+    set description "extracts 3D volumes from the beginning time-frame to the ending time-frame from a 4D image."
+    set description2 "Output files are input_001.hdr, input_002.hdr ,,, etc (or input_001.nifti, input_002.nifti ,,, ). input_001.hdr corresponds to the begin frame. If the -begin and -end option is not specified, all the the 3D volumes are extracted. "
+    set backwardcompatibility "Reimplemented from pxmat_split4dimage.tcl."
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this AddDefaultOptions
+
+}
+
+
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_split4dimage::Execute {  } {
+
+    PrintDebug "bis_split4dimage::Execute"
+    
+    set image_in        [ $InputsArray(input_image) GetObject ]
+    set beginframe      [ $OptionsArray(begin)  GetValue  ]
+    set endframe        [ $OptionsArray(end)    GetValue  ]
+    set stem            [ $OptionsArray(ostem)    GetValue  ]
+    regsub -all "\"" $stem "" stem
+
+
+    set number_of_frames [ [$image_in GetObject ] GetNumberOfScalarComponents ]
+    set name [ $InputsArray(input_image) GetFileName]
+
+    if { $number_of_frames == 1 } {
+	puts stdout "Nothing to do $name only has one frame"
+	return 1
+    }
+
+    if { $beginframe < 1 } { set beginframe 1 }
+    if { $beginframe > $number_of_frames } { set beginframe $number_of_frames }
+
+    if { $endframe <= $beginframe }      { set endframe $beginframe }
+    if { $endframe > $number_of_frames } { set endframe $number_of_frames }
+
+    PrintDebug "beginframe = $beginframe, endframe = $endframe"
+
+    set extr [ vtkImageExtractComponents [ pxvtable::vnewobj ]]
+    $extr SetInput [$image_in GetObject ]
+
+    set bg [ expr $beginframe -1 ]
+
+
+    set number [expr $endframe - $beginframe + 1 ]
+
+
+    set l [ ::bis_common::SplitFileNameGZ $name ]
+    set ext [ lindex $l 1 ]
+    set m [ lindex $l 0 ]
+
+    if { [ string length $stem ] > 1 } {
+	set m $stem
+    }
+
+    set namelist [lsort [array names OutputsArray ]]
+
+    set outimage [ [ pxitclimage \#auto ] GetThisPointer ]
+
+
+    for { set i $bg } { $i < $endframe } { incr i } {
+	set idx [ expr $i +1 ]
+
+	$extr SetComponents $i
+	$extr Modified
+	$extr Update
+	set image_out [ $extr GetOutput ]
+	
+	set outfilename  "${m}_${idx}${ext}" 
+
+	$outimage ShallowCopyImage $image_out 
+	# Output orientation etc. is same as input
+	$outimage CopyImageHeader [ $image_in GetImageHeader ]
+	[ $outimage GetImageHeader ] AddComment "split4d" 0
+	$outimage Save  $outfilename
+
+	puts stdout "Saved Output Frame $idx  in $outfilename"
+    }
+
+    $extr Delete
+    itcl::delete obj $outimage
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_split4dimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_split4dimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_stitchimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_stitchimage.tcl
new file mode 100755
index 0000000..9c6717a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_stitchimage.tcl
@@ -0,0 +1,251 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagetransformationalgorithm 1.0
+package require bis_resliceimage 1.0
+package provide bis_stitchimage 1.0
+
+#
+# blend image
+#
+
+itcl::class bis_stitchimage {
+
+    inherit bis_dualimagetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Stitch images"}
+
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_stitchimage::Initialize { } {
+
+    PrintDebug "bis_stitchimage::Initialize" 
+
+    set options {
+	{ interp        "Interpolation Mode that is used when reslicing the image" "Interpolation Mode"  listofvalues Linear { "NearestNeighbor" "Linear" "Cubic" }  0 }
+	{ axis      "Stitching Axis" "Stitching Axis" { listofvalues radiobuttons }  X { X Y Z }   1}
+	{ seam    "Seam" "Seam" real -1 { -1 256 }  1 }
+	{ flip  "Flip" "Flip"  { boolean } 0 { 0 1 }  1 }
+	{ pad   "Pad" "Pad"  real 0 { 0 10 } 2 }
+    }
+	
+    set defaultsuffix { "_stitched" }
+    
+    set scriptname bis_stitchimage
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    set category "Image Processing Dual"
+    set description "Stitches images"
+    set description2 ""
+    set backwardcompatibility "Reimplemented from pxmat_blendimage.tcl."
+    set authors "alark.joshi at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageTransformationAlgorithm
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_stitchimage::Execute {  } {
+
+    PrintDebug "bis_stitchimage::Execute"
+
+    set reslice_alg [bis_resliceimage [pxvtable::vnewobj]]
+    $reslice_alg InitializeFromContainer $this
+    $reslice_alg SetInput [ $this GetInput ] 
+    $reslice_alg SetSecondInput [ $this GetSecondInput ] 
+    $reslice_alg SetTransformation [ $this GetTransformation ] 
+    $reslice_alg SetOptionValue interp [ $OptionsArray(interp) GetValue ]
+    $reslice_alg Execute
+
+    # set reslimage [  [ $reslice_alg GetOutput ] GetImage ]
+    set reslimage  [ [ $this GetInput ] GetImage ]
+    
+    set imcast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+    $imcast2 SetInput $reslimage
+    $imcast2 SetOutputScalarType [ [ [ $this GetInput ] GetImage ] GetScalarType ]
+    $imcast2 Update
+
+    set pad [ $OptionsArray(pad) GetValue ]
+    set flip [ $OptionsArray(flip) GetValue ]
+    set seam [ $OptionsArray(seam) GetValue ] 
+    set interpolate [ $OptionsArray(interp) GetValue ] 
+    set axis [ $OptionsArray(axis) GetValue ] 
+    
+    set stitchimage [  vtkpxImageStitch [ pxvtable::vnewobj ]]
+    
+    if { $pad == "0" } {
+	
+	if { [ $OptionsArray(axis) GetValue ] == "X" } { 
+	    $stitchimage SetAxis  0
+	} elseif  { [ $OptionsArray(axis) GetValue ] == "Y" } {
+	    $stitchimage SetAxis  1			
+	} else {
+	    $stitchimage SetAxis  2			
+	}
+	$stitchimage SetInput  [ [ $this GetInput ] GetImage ] 
+	$stitchimage SetInput2 [ [ $this GetSecondInput ] GetImage ] 
+	$stitchimage SetSeamCoordinate $seam 
+	$stitchimage SetFlipOrientation  [ $OptionsArray(flip) GetValue ]
+	$stitchimage Update
+	
+#	puts "getting here" 
+	
+    } else { 
+	
+	set resl [ vtkbisImageReslice [ pxvtable::vnewobj ] ]
+	$resl OptimizationOff 
+	
+	set trans  [  vtkIdentityTransform [ pxvtable::vnewobj ] ]	
+	
+	set spa  [  $reslimage  GetSpacing ]
+	set ori  [  $reslimage  GetOrigin ]
+	set dim  [  $reslimage  GetDimensions ]
+	set voi0 [ list   0 0 0 ]
+	set voi1 [ list   [ expr [ lindex $dim 0 ] -1 ]  [ expr [ lindex $dim 1 ] -1 ]  [ expr [ lindex $dim 2 ] -1 ]  ]
+	
+	set seampoint $seam 
+	
+	for { set i 0 } { $i <=2 } { incr i } {
+	    set x0 [ expr round([ lindex $voi0 $i ]) ]
+	    set x1 [ expr round([ lindex $voi1 $i ]) ]
+	    
+	    if { $axis == $i } {
+		set dpad $pad 
+		if {  $flip == 0 } {
+		    set x1 [ expr $x1 + $dpad ]
+		} else {
+		    set x0 [ expr $x0 - $dpad ]
+		    if { $seampoint > 0 } {
+			set seampoint [ expr $seampoint + $dpad ]
+		    }
+		}
+	    }
+	    
+	    if { $x1 < $x0 } { set x1 [ expr $x0 ] }
+	    
+	    set origin($i)  [ expr [lindex $ori $i ] + $x0 * [ lindex $spa $i ]]
+	    set spacing($i) [lindex $spa $i ]
+	    set ext($i)     [ expr ($x1-$x0) ]
+	}
+	
+	$resl SetInput $reslimage
+	$resl SetResliceTransform $trans
+	$resl SetOutputSpacing $spacing(0) $spacing(1) $spacing(2)
+	$resl SetOutputOrigin  $origin(0)  $origin(1)  $origin(2)
+	$resl SetOutputExtent  0 $ext(0) 0 $ext(1) 0 $ext(2)
+	$resl SetInterpolationMode 0 
+	SetFilterCallbacks $resl "Padding Reference Image"
+	$resl Update
+	
+	set resl2 [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+	$resl2 OptimizationOff
+	set current_transform [ $this GetTransformation ]
+	# set image_trn [  $imcast2 GetImage ]
+	set image_trn [ [ $this GetSecondInput ] GetImage ] 
+	
+	$resl2 SetInformationInput [ $resl GetOutput ]
+	$resl2 SetInput $image_trn
+	$resl2 SetInterpolationModeTo$interpolate
+	$resl2 SetBackgroundLevel 0.0
+	$resl2 SetResliceTransform [ $current_transform GetObject ] 
+	SetFilterCallbacks $resl "Reslicing Target Image"
+	$resl2 Update
+	
+	if { [ $OptionsArray(axis) GetValue ] == "X" } { 
+	    $stitchimage SetAxis  0
+	} elseif  { [ $OptionsArray(axis) GetValue ] == "Y" } {
+	    $stitchimage SetAxis  1
+	} else {
+	    $stitchimage SetAxis  2
+	}
+	
+	$stitchimage SetInput           [ $resl GetOutput ] 
+	$stitchimage SetInput2          [ $resl2 GetOutput ]
+	$stitchimage SetSeamCoordinate  $seampoint 
+	$stitchimage SetFlipOrientation $flip
+	SetFilterCallbacks $stitchimage "Stitching Images"
+	$stitchimage Update
+    }
+    
+	 $imcast2 Delete 
+    
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage [ $stitchimage GetOutput ]
+    
+    # Output orientation etc. is same as input
+    set outimage [ $this GetOutput ] 
+    set pimage   [ $this GetSecondInput ] 
+
+    $outimage CopyImageHeader [ $pimage GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $stitchimage Delete
+    itcl::delete object $reslice_alg
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_stitchimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+   
+
+    set alg [bis_stitchimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_stripskull.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_stripskull.tcl
new file mode 100755
index 0000000..d627c67
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_stripskull.tcl
@@ -0,0 +1,318 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_stripskull 1.0
+package require bis_imagetoimagealgorithm 1.0
+
+
+#
+# strip skull
+#
+
+itcl::class bis_stripskull {
+
+    inherit bis_imagetoimagealgorithm
+
+    constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method UpdateOutputFilenames { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Strip Skull" }
+    public method CreateGUI { parent { callafter 0 } { callbefore 0 } }
+    public method HandleCoordinateChangeEvent { args }
+
+    protected variable chain_viewer_callback ""
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_stripskull::Initialize { } {
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ radiusfactor "Scale Factor for the Radius" "Radius Scale Factor"  { real triplescale 100 }  0.5 { 0.2 1.0 }  0 }
+	{ subdivisions "Number of Subvidisions for Icosahedron" "Subvidisions"  { integer }  4 { 0 8 }  1 }
+	{ iterations "Number of Iterations for Updates" "Iterations"  { integer }  1000 { 1 2000 }  2 }
+	{ tolerance "Tolerance for Convergenece in mm" "Tolerance"  { real }  0.1 { 0.0 2.0 }  -110 }
+	{ smoothing "Use Increased Smoothing" "Smoothing"  boolean  1 { 0 1 } -111 }
+	{ numpasses "Number Passes Made To Smooth the Surface" "Passes"  { integer }  10 { 1 10 } -112 }
+	{ initMethod "Set the Center of Gravity and Radius Automatically, Manually, or Using the Crosshairs" "Manual Init."  { listofvalues radiobuttons } auto { auto manual crosshair } -113 }
+	{ manRadius "Set the Initial Surface Radius Manually" "Radius"  { real }  1.0 { 0.01 1000.0 } -114 }
+	{ manX "Set the Initial Surface Center x-coord Manually (Using Display Coordinates)" "X"  { real }  0.0 { 0.0 1000.0 } -115 }
+	{ manY "Set the Initial Surface Center y-coord Manually (Using Display Coordinates)" "Y"  { real }  0.0 { 0.0 1000.0 } -116 }
+	{ manZ "Set the Initial Surface Center z-coord Manually (Using Display Coordinates)" "Z"  { real }  0.0 { 0.0 1000.0 } -117 }
+	{ numbins "Number of Bins for Histogram Fitting" "Bins"  { integer }  1000 { 32 1024 } -118 }
+	{ minPercent "Cummulative Histogram Lower Threshold Percent" "MinPercent"  { real }  0.02 { 0.0 0.5 } -119 }
+	{ maxPercent "Cummulative Histogram Upper Threshold Percent" "MaxPercent"  { real }  0.98 { 0.5 1.0 } -120 }
+	{ minIntenSearchDist "Distance Searched for Minimum Intensity" "Min Intensity Search"  { real }  7.0 { 1.0 20.0 } -123 }
+	{ maxIntenSearchDist "Distance Searched for Maximum Intensity" "Max Intensity Search"  { real }  3.0 { 0.5 10.0 } -124 }
+	{ rMin "Minimum Local Radius Used for Smoothing" "rMin"  { real }  3.33 { 0.1 100.0 } -125 }
+	{ rMax "Maximum Local Radius Used for Smoothing" "rMax"  { real }  10.0 { 0.1 100.0 } -126 }
+	{ localThreshConst "Local Fractional Constant" "Local Threshold"  { real }  0.5 { 0.01 1.0 } -127 }
+	{ selfIntersectThresh "Threshold for Surface Self-Intersections" "Self-Intersection"  { real }  3000 { 0 10000 } -128 }
+    }
+	#{ manual "Use Manual Center of Gravity and Radius" "Manual Init."  boolean  0 { 0 1 } -113 }
+
+    set outputs {
+    { output_mask "Output Mask" pxitclimage "" 2 }   
+    { output_surface "Output Surface" pxitclsurface "" 3 }   
+    }
+    
+    
+    set defaultsuffix "_stripped"
+
+    set scriptname bis_stripskull
+    set completionstatus "To be tested"
+
+    #
+    #document
+    #
+	
+    set description "Performs skull stripping" 
+    set description2 "a reimplementation of the BET algorithm"
+    set backwardcompatibility "None"
+    set authors "john.onofrey at yale.edu"
+    set category "Segmentation"
+
+    $this InitializeImageToImageAlgorithm
+}
+
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_stripskull::UpdateOutputFilenames { } {
+#    puts stderr "Updating output filenames!"
+    
+    set f [ $InputsArray(input_image) GetFileName ]
+    
+    set l [ ::bis_common::SplitFileNameGZ $f ]
+    set f [ file tail [ lindex $l 0 ] ]
+    set ext [ lindex $l 1 ]
+
+    $OutputsArray(output_image) SetFileName "$f${defaultsuffix}$ext"
+    $OutputsArray(output_mask) SetFileName "$f${defaultsuffix}_mask$ext"
+    $OutputsArray(output_surface) SetFileName "$f${defaultsuffix}_surface.vtk"
+}
+
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_stripskull::HandleCoordinateChangeEvent { args } {
+
+    #puts "In Handle Mouse Event $args"
+    if { [ $this GetBisViewer ] ==0 } {
+	   set lv [ [ $this GetViewer ] GetLastClickedPointScaled ] 
+    } else {
+	   set lv [ lindex $args 1]
+    }
+    set px [ lindex $lv 0 ]
+    set py [ lindex $lv 1 ]
+    set pz [ lindex $lv 2 ]
+    #puts stderr "Setting bet cog to $px $py $pz"
+    
+    
+    $OptionsArray(manX) SetValue $px
+    $OptionsArray(manY) SetValue $py
+    $OptionsArray(manZ) SetValue $pz
+    
+    if { [ $this GetBisViewer ] ==0  && $chain_viewer_callback !="" } {
+	catch { eval $chain_viewer_callback }
+    }
+}
+
+# ------------------------------------------------------------------------------------------
+
+itcl::body bis_stripskull::CreateGUI { parent { callafter 0 } { callbefore 0 } } {
+
+
+    set r [ bis_algorithm::CreateGUI $parent $callafter $callbefore ]
+    
+    if { [ $this GetBisViewer ] !=0 } {
+	$bis_viewer AddCursorNotifier $this "HandleCoordinateChangeEvent"
+	set chain_viewer_callback ""
+    } else {
+
+	# Legacy to put it mildly 
+	set vv [ $this GetViewer ]
+	if { $vv !=0 } {
+	    if { [ $vv IsA "vtkpxGUIOrthogonalViewer" ] == 0 } {
+		  set vv 0
+	    }
+	}
+    
+	if { $vv !=0 } {
+	    set a "$this HandleCoordinateChangeEvent"
+	    set chain_viewer_callback [ $vv GetCoordinateChangeCallback ]
+	    $vv SetCoordinatesChangeCallback $a
+	    #	puts stderr "Callbacks $a, $chain_viewer_callback"
+	    $vv SetEnableCoordinatesChangeCallback 1
+	}
+    }
+    return $r
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_stripskull::Execute {  } {
+
+    set radiusscale   [ $OptionsArray(radiusfactor) GetValue ]
+    set initMethod    [ $OptionsArray(initMethod)   GetValue ]
+    set radius	      [ $OptionsArray(manRadius)    GetValue ]
+    set manX	      [ $OptionsArray(manX)         GetValue ]
+    set manY	      [ $OptionsArray(manY)	    GetValue ]
+    set manZ	      [ $OptionsArray(manZ)	    GetValue ]
+    set tolerance     [ $OptionsArray(tolerance)    GetValue ]
+    set res           [ $OptionsArray(subdivisions) GetValue ]
+    set smooth        [ $OptionsArray(smoothing)    GetValue ]
+    set bins          [ $OptionsArray(numbins)      GetValue ]
+    set minT          [ $OptionsArray(minPercent)   GetValue ]
+    set maxT          [ $OptionsArray(maxPercent)   GetValue ]
+    set numiter       [ $OptionsArray(iterations)   GetValue ]
+    set passes	      [ $OptionsArray(numpasses)    GetValue ]
+    set minSearch     [ $OptionsArray(minIntenSearchDist)    GetValue ]
+    set maxSearch     [ $OptionsArray(maxIntenSearchDist)    GetValue ]
+    set rMin	      [ $OptionsArray(rMin)         GetValue ]
+    set rMax	      [ $OptionsArray(rMax)         GetValue ]
+    set localT	      [ $OptionsArray(localThreshConst)      GetValue ]
+    set selfIntersectT  [ $OptionsArray(selfIntersectThresh) GetValue ]
+	
+    # image_in is a pxitclimage which is a wrapper around vtkImageData
+    set image_in      [ $this GetInput ]
+	
+    # Get spacing and origin of the image for use during manual initialization
+    set spa [ [ $image_in GetImage ] GetSpacing ]
+    set ori [ [ $image_in GetImage ] GetOrigin ]
+
+    set bet [ vtkjoBETImageFilter New ]
+    $bet SetInput [ $image_in GetImage]
+    $bet SetBins $bins
+    $bet SetMinIntensityPercent $minT
+    $bet SetMaxIntensityPercent $maxT
+    
+    if { $initMethod != "auto" } {
+	   puts stderr "Setting manual radius and CoG"
+	   $bet ManualRadiusAndCOGOn
+	   $bet SetRadius $radius
+
+        set px $manX
+        set py $manY
+        set pz $manZ
+
+        # Check if a viewer exists for crosshair mode
+        if { [ $this GetViewer ] == 0 } {
+            puts stderr "No viewer - disabling crosshair method, and using manual cog"
+        }
+        
+        if { $initMethod == "crosshair" && [ $this GetViewer ] != 0 } {
+            puts stderr "Using crosshair method..."
+
+		    set lv [ $vtk_viewer GetLastClickedPointScaled ] 
+            set px [ lindex $lv 0 ]
+            set py [ lindex $lv 1 ]
+            set pz [ lindex $lv 2 ]
+	   }
+       puts stderr "Setting bet cog to $px $py $pz"
+       $bet SetCenterOfGravity $px $py $pz
+    }
+    
+    $bet SetRadiusScaleFactor $radiusscale
+    $bet SetMaxIterations $numiter
+    $bet SetMaxPasses $passes
+    $bet SetSurfaceResolution $res
+    $bet SetMinChangeTolerance $tolerance
+    $bet SetMinIntensitySearchDist $minSearch
+    $bet SetMaxIntensitySearchDist $maxSearch
+    $bet SetRMin $rMin
+    $bet SetRMax $rMax
+    $bet SetLocalThresholdConst $localT
+    $bet SetSelfIntersectionThreshold $selfIntersectT
+    $bet SetIncreasedSmoothing $smooth
+
+    # This sets the callbacks for updating the interface
+    $this SetFilterCallbacks $bet "Stripping Skull"
+
+    # Run The Algorithm
+    $bet Update
+	
+    # Compute Stripped Image
+    set img [ $bet GetOutput ]
+
+    # Copy output image into proper structure
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+    $outimage ShallowCopyImage $img
+
+    # Add a comment to image header
+    set comment [ format "BIS::bis_stripskull.tcl skull stripped" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    # Copy the output image mask into the proper structure
+    set outmask [ $OutputsArray(output_mask) GetObject ]
+    $outmask CopyImageHeader [ $image_in GetImageHeader ]
+    $outmask ShallowCopyImage [ $bet GetOutputMask ]
+    [ $outmask GetImageHeader ] AddComment "$comment $Log" 0
+
+    # Copy the output surface to the output object structure
+    set outsurf [ $OutputsArray(output_surface) GetObject ]
+    $outsurf ShallowCopySurface [ $bet GetSurface ]
+    $outsurf AddComment "$comment $Log"
+    
+    # Clean up
+    $img Delete
+    $bet Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_stripskull.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_stripskull [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_subdivide.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_subdivide.tcl
new file mode 100755
index 0000000..8300bd8
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_subdivide.tcl
@@ -0,0 +1,128 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_surfacetosurfacealgorithm 1.0
+
+package provide bis_subdivide 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_subdivide {
+
+    inherit bis_surfacetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Subdivide" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_subdivide::Initialize { } {
+
+    PrintDebug "bis_subdivide::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ numberOfSubdivisions "Number of Subdivisions" "Number of Subdivisions"  { integer triplescale 100 }    1 { 1 10}  0 }
+	}
+
+    set defaultsuffix { "_subdivide" }
+    
+    set scriptname bis_subdivide
+
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "subdividing a surface"
+    set description2 ""
+    set backwardcompaibitlity "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeSurfacetoSurfaceAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_subdivide::Execute {  } {
+
+    PrintDebug "bis_subdivide::Execute"
+
+    # Get Inputs
+    set surface    [ $this GetInput  ]
+    # GetOptions
+    
+	set numberOfSubdivisions [ $OptionsArray(numberOfSubdivisions) GetValue ]
+	
+    # Run Algorithm    
+	set filter [ vtkLinearSubdivisionFilter [ pxvtable::vnewobj ] ]
+	$filter SetInput [ $surface GetObject ]
+	$filter SetNumberOfSubdivisions $numberOfSubdivisions
+	$filter Update
+    
+    # Store Results in output
+    set surface_out [$filter GetOutput ]
+    [ $OutputsArray(output_surface) GetObject ] DeepCopySurface $surface_out 
+
+    # Clean up
+    $filter Delete
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_subdivide.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_subdivide [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_surfaceinfo.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_surfaceinfo.tcl
new file mode 100755
index 0000000..4f2f43c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_surfaceinfo.tcl
@@ -0,0 +1,183 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_algorithm 1.0
+
+package provide bis_surfaceinfo 1.0
+
+#
+# output surface information
+#
+
+itcl::class bis_surfaceinfo {
+
+    inherit bis_algorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Surface Info" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_surfaceinfo::Initialize { } {
+
+    PrintDebug "bis_surfaceinfo::Initialize" 
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ detail "description length for header" "Detail" {listofvalues radiobuttons}  short {short long  }  0 }
+    }
+
+    set outputs ""
+    set inputs { { input_surface "Input Surface List" { pxitclsurface multiple } "" 0  } }
+    set directinputs "input_surface"
+
+
+
+    set defaultsuffix { "" }
+    
+    set scriptname bis_surfaceinfo
+
+    #
+    #document
+    #
+
+    set category "Utility"
+    set description "prints information about .vtk surface files."
+    set description2 ""
+    set backwardcompatibility "Reimplemented from pxmat_surfaceinfo.tcl"
+    set authors "hirohito.okuda at yale.edu,xenophon.papademetris.yale.edu"
+
+    $this AddDefaultOptions
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_surfaceinfo::Execute {  } {
+
+    PrintDebug "bis_headerinfo::Execute"
+
+    set dogui [ $OptionsArray(dogui) GetValue ]
+    set fullmode 0
+    switch [ $OptionsArray(detail) GetValue ] {
+	"long"  {      set fullmode 1 }
+    }
+
+
+    set inplist [ $InputsArray($directinputs) GetAllObjects ]
+    set numfiles [ llength $inplist ]
+
+    for { set i 0 } { $i < $numfiles } { incr i } {
+	if { $dogui > 0 } {
+	    pxtkconsole
+	}
+	for { set i 0 } { $i < $numfiles } { incr i } {
+	    set sur [ [ lindex $inplist $i ] GetSurface ]
+	    set name [ [ lindex $inplist $i ] cget -filename ]
+
+	    set np [ $sur GetNumberOfPoints ]
+	    set nc [ $sur GetNumberOfCells  ]
+	    set bd [ $sur GetBounds ]
+	    
+	    set scalardata "no point scalars"
+	    set celldata   "no cell  scalars"
+	    set testscal 0
+	    
+	    catch {
+		set scal [ [  $sur GetPointData ] GetScalars ]
+		set ns [ $scal GetNumberOfTuples ]
+		set nc [ $scal GetNumberOfComponents ]
+		set range [ $scal GetRange ]
+		set scalardata  "$ns point-scalars ($nc components) range=[lindex $range 0 ]:[lindex $range 1 ]"
+		set testscal 1
+	    }
+	    
+	    catch {
+		set scal [ [  $sur GetCellData ] GetScalars ]
+		set ns [ $scal GetNumberOfTuples ]
+		set nc [ $scal GetNumberOfComponents ]
+		set range [ $scal GetRange ]
+		set celldata  "$ns cell-scalars ($nc components) range=[lindex $range 0 ]:[lindex $range 1 ]"
+		set testscal 0
+	    }
+	    
+	    set outline " $np points $nc cells (bounds=$bd) ($scalardata,$celldata)"
+	    
+	    if { $fullmode == 1 } {
+		set histline ""
+		if { $testscal > 0 } {
+		    set thrFilter [ vtkThresholdPoints [ pxvtable::vnewobj ]]
+		    for { set j [ lindex $range 0 ] } { $j <= [ lindex $range 1 ]} { incr j } {
+			$thrFilter SetInput $sur
+			$thrFilter ThresholdBetween [ expr $j-0.1 ] [ expr $j+0.1 ]
+			$thrFilter Update
+			set histline "$histline \t $j \t [ [ $thrFilter GetOutput ] GetNumberOfPoints ]\n"
+		    }
+		    $thrFilter Delete 
+		    set outline "$outline\n $histline"
+		}
+	    }
+	    
+	    if { $dogui > 0 } {
+		pxtkprint "\n$name:\n $outline\n"
+	    } else {
+		puts stdout "\n$name:\n $outline"
+	    }
+	}
+    }
+    return 1
+}
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_surfaceinfo.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_surfaceinfo [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_surfacetosurfacealgorithm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_surfacetosurfacealgorithm.tcl
new file mode 100644
index 0000000..a2ac2ae
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_surfacetosurfacealgorithm.tcl
@@ -0,0 +1,191 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_surfacetosurfacealgorithm 1.0
+package require bis_algorithm 1.0
+
+
+# -----------------------------------------------------------------------------------------
+#  Header Stuff
+# -----------------------------------------------------------------------------------------
+itcl::class bis_surfacetosurfacealgorithm {
+
+    inherit bis_algorithm
+
+    constructor { } { }
+    public method InitializeSurfacetoSurfaceAlgorithm { }
+    public method Execute { } { puts stderr "Nothing to Do" }
+
+
+    # Get Info about Algorithm for use in GUI Container
+    public method IsSurfacetoSurface { } { return 1 }
+    public method SetContainer { cont }  { set containerobject $cont }
+    public method GetContainer { }  { return $containerobject }
+    public method UpdateInputsFromContainer { }
+    public method UpdateContainerWithOutput { } 
+
+    # Input and Output Methods
+    public method GetInput { }
+    public method GetOutput { }
+    public method SetInput { sur }
+
+    # Set Filenames etc
+    public method  UpdateOutputFilenames { } 
+    public method  CheckInputObjects { } 
+
+    
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_surfacetosurfacealgorithm::InitializeSurfacetoSurfaceAlgorithm { } {
+
+
+    # This assumes that a derived class has done some work here already
+
+    PrintDebug "bis_surfacetosurfacealgorithm::Initialize" 
+
+    set tmp $inputs
+    set inputs { { input_surface "Input Surface" pxitclsurface  "" 2 }    }
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+	lappend inputs [ lindex $tmp $i ]
+    }
+    
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set tmp $outputs
+    
+    set outputs { { output_surface "Output Surface"  pxitclsurface  "" 1 }}
+    for { set i 0 } { $i < [ llength $tmp ] } { incr i } {
+    	lappend outputs [ lindex $tmp $i ]
+    }
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    #    lappend options [ list outname  "output filename root" "Output" string ""     { "" }  -1000 ]
+
+
+    if { $defaultsuffix == "" } {
+	set defaultsuffix { "_out" }
+    }
+    
+    
+
+    #
+    #document stuff
+    #
+
+    if { $category =="" } {
+	set category    "Surface Processing"
+    }
+    
+    if { $authors == "" } {
+	set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+    }
+
+    $this AddDefaultOptions
+}
+
+# ----------------------------------------------------------
+#
+#  Container Stuff ....
+#
+# ----------------------------------------------------------
+itcl::body bis_surfacetosurfacealgorithm::SetInput  { sur } {
+
+    $this SetInputObject input_surface $sur
+}
+
+itcl::body bis_surfacetosurfacealgorithm::GetInput  { } {
+
+    return [ $this GetInputObject input_surface ]
+}
+
+itcl::body bis_surfacetosurfacealgorithm::GetOutput { } {
+
+    return [ $this GetOutputObject output_surface ]
+}
+
+
+itcl::body bis_surfacetosurfacealgorithm::UpdateInputsFromContainer { } {
+
+
+    if { $containerobject == 0 } {	return    }
+    $this SetInput [ $containerobject GetSurface ]
+    $this UpdateOutputFilenames
+
+}
+
+itcl::body bis_surfacetosurfacealgorithm::UpdateContainerWithOutput { } {
+
+    set sur  [ $this GetOutput ] 
+
+
+    PrintDebug "In Update Container With Output $this, $sur [ $sur GetDescription ]\n"
+    
+    if { $containerobject == 0 } {
+	if { $bis_viewer !=0 } {
+	    $bis_viewer AddOrReplacePolygonalObject $sur
+	}
+    } else {
+	PrintDebug "Calling Container ($this, $containerobject) SetResultsFromObject" 
+	$containerobject SetResultsFromObject $sur $this
+    }
+}
+
+# --------------------------------------------------------------------------------------------
+
+itcl::body bis_surfacetosurfacealgorithm::UpdateOutputFilenames { } {
+
+    set fn [ $InputsArray(input_surface) GetFileName ]
+    set outlist [ $this CreateDefaultOutputFileList $fn ]
+
+    set l [ ::bis_common::SplitFileNameGZ $fn ]
+    set ext [ lindex $l 1 ]
+    set m [ lindex $outlist 0 ]
+
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+    $OutputsArray(output_surface) SetFileName "${m}${ext}" $force
+    return 1
+
+}
+
+
+itcl::body bis_surfacetosurfacealgorithm::CheckInputObjects { } {
+
+
+    set surface_in    [ $this GetInput ]
+    set d [ [ $surface_in GetSurface ] GetNumberOfPoints ]
+    if { $d < 4 } {
+	return 0
+    }
+
+
+    return 1
+
+}
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_temporalsmoothimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_temporalsmoothimage.tcl
new file mode 100755
index 0000000..cb5cfbf
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_temporalsmoothimage.tcl
@@ -0,0 +1,166 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_temporalsmoothimage 1.0
+package require bis_dualimagealgorithm 1.0
+
+
+itcl::class bis_temporalsmoothimage {
+
+    inherit bis_dualimagealgorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Temporal Smooth" }
+	#override parent function
+	public method CheckInputObjects { }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_temporalsmoothimage::Initialize { } {
+
+    PrintDebug "bis_temporalsmoothimage::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+		{  blursigma "kernel sigma (gaussian) in frames" "Sigma" { real triplescale 100 } 2.0 { 0 5 } 10 }
+		{  usemask   "Use Mask Image"  "Use Mask Image"  boolean   0  { 0 1  }  40  }
+    }
+
+    set defaultsuffix { "_tsm" }
+    set scriptname bis_temporalsmoothimage
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Temporal smoothing with Gaussian kernel."
+	set description2 "Time courses are convolved with a Gaussian kernel with specified width."
+    set backwardcompatibility ""
+	set authors "isabella.murphy at yale.edu, xilin.shen at yale.edu."
+    set category "Image Processing-4D"
+    $this InitializeDualImageAlgorithm
+	
+	$this RenameInput 0 "Functional Image"
+	#set priority to 102 to make it optional
+    $this RenameInput 1 "Mask Image" 102
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_temporalsmoothimage::Execute {  } {
+
+
+    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary  vtkbisConnectivityTCL vtkbisROICorrelation 0  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to load library vtkbisConnectivityTCL"
+	return 0
+    }
+    
+
+    PrintDebug "bis_temporalsmoothimage::Execute"
+
+    set blursigma   [ $OptionsArray(blursigma) GetValue ]
+    set image_in    [ $this GetInput ]
+
+    set smooth  [ vtkbisImageTemporalSmoothing [ pxvtable::vnewobj ]  ] 
+    $smooth SetSigma $blursigma
+    $smooth SetInput [ $image_in GetObject ]
+	set msk [ $OptionsArray(usemask) GetValue ]
+    if { $msk == "1" } {
+	puts stdout "Using Mask ..."
+	$smooth SetImageMask [ [ $this GetInputObject second_image ] GetObject ]
+    } 
+    $this SetFilterCallbacks $smooth "Temporal Smoothing Image"
+    $smooth Update
+
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $smooth GetOutput ]
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+    $smooth Delete
+
+    return 1
+}
+itcl::body bis_temporalsmoothimage::CheckInputObjects { } {
+
+
+    set image_in    [ $this GetInput ]
+    set d [ $image_in GetImageSize ]
+    if { $d < 2 } {
+	return 0
+    }
+	
+	set msk [ $OptionsArray(usemask) GetValue ]
+	if { $msk == "1" } {
+		set image_in    [ $this GetSecondInput ]
+        set d [ $image_in GetImageSize ]
+        if { $d < 2 } {
+	    return 0
+    	}
+	}
+	
+    return 1
+
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_temporalsmoothimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_temporalsmoothimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_tensoranalysis.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_tensoranalysis.tcl
new file mode 100755
index 0000000..8f5a9d5
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_tensoranalysis.tcl
@@ -0,0 +1,288 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] mjack]
+
+package require bis_imagetoimagealgorithm 1.0
+package require vtkmpjcontrib 
+package require mpjtensoranalysis
+package require bis_basecontrolhelper
+
+package provide bis_tensoranalysis 1.0
+
+#
+# tensor analysis
+#
+
+itcl::class bis_tensoranalysis {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+    destructor { $this DeleteDTIControl }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Compute DTI Maps" }
+    #
+    #public
+    #
+
+    public method UpdateOutputFilenames { } 
+
+    public method ConfigureOptionsGUICallbacks { } 
+
+    public method ShowDTIControl {  args } 
+    protected method DeleteDTIControl { }
+    protected method CopyOutputObject { name index comment comment2 } 
+
+    # variables
+    protected variable tensoranalysis 0
+    protected variable bishelper 0
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_tensoranalysis::Initialize { } {
+
+    PrintDebug "bis_tensoranalysis::Initialize" 
+    #name,description,type,object,filename(if applicable),priority (optional)
+    
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set outputs {
+	{ out_ormap "Orientation Map" pxitclimage  "" 10 }
+	{ out_ramap "Relative Anistropy map"    pxitclimage  "" 100 }
+	{ out_meand "Mean Diffusivity map"        pxitclimage  "" 102 }
+    }
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ cscheme  "Color Scheme for orientation map" "Col Scheme"  { listofvalues } Absolute { AbsoluteValue RotSymmetry NoSymmetry MirrorSymmetry } 1 }
+	{ satfactor  "Saturation Factor" "Saturation"  real 0.5 { 0.1 5.0 } 2 }
+	{ brightness  "Brightness" "Brightness"  real 2.0 { 0.1 5.0 } 3 }
+	{ usemask     "Use Mask when creating orientation map" "Use Mask" boolean 1 { 0 1 } -10 }
+    }
+    lappend options [ list guishowcontrol  "Show Tensor Utility Control" "Show Control"  { boolean } 0 { 0 1 }  5 ]
+
+    set defaultsuffix { _fractani _ormap }
+    
+    set scriptname bis_tensoranalysis
+
+    #
+    #document
+    #
+
+    set category "Diffusion Tensor"
+    set description  "computes FA map, orientation map and optionally (RA, MD, VR, CI)." 
+    set description2 "This tool takes as an input a calculated tensor map and computes useful maps such as the Fractional Anisotropy map, an orientation colormap and optionally Relative Anisotropy map, Volume Ratio map, Mean Diffusity map, Inter voxel  Coherence map"
+    set backwardcompatibility "Reimplemented from pxmat_tensoranalysis.tcl"
+    set authors "marcel.jackowski at yale.edu,xenophon.papademetris.yale.edu,hirohito.okuda at yale.edu"
+
+    $this InitializeImageToImageAlgorithm
+
+    $this RenameInput 0 "Tensor Image"
+    $this RenameOutput 0 "Frac Anisotropy Map"
+}
+
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_tensoranalysis::UpdateOutputFilenames { } {
+
+    set fn [ $InputsArray(input_image) GetFileName ]
+    set outlist [ $this CreateDefaultOutputFileList $fn ]
+
+    set l [ ::bis_common::SplitFileNameGZ $fn ]
+    set ext [ lindex $l 1 ]
+
+    set force 0;    if { $guimode == "managed" } {	set force 1    }    
+
+    set m [ lindex $outlist 0 ]
+    $OutputsArray(output_image) SetFileName "${m}${ext}" $force
+    set m [ lindex $outlist 1 ]
+    $OutputsArray(out_ormap) SetFileName "${m}${ext}" $force
+    return 1
+}
+
+itcl::body bis_tensoranalysis::CopyOutputObject { name index comment comment2 } {
+
+    set f2 [ [ $this GetOutputObject $name ] GetFileName ]
+    [ $this GetOutputObject $name ] ShallowCopy [ $tensoranalysis GetOutputImage $index ]
+    [ $this GetOutputObject $name ] AddComment "$comment ($comment2)" 
+    if { [ string length $f2 ] > 1 } {
+	[ $this GetOutputObject $name ] SetFileName $f2
+    }
+
+}
+
+
+itcl::body bis_tensoranalysis::DeleteDTIControl { } {
+
+    if { $tensoranalysis == 0 } {
+	return
+    }
+
+    $tensoranalysis ClearAllResults
+    #    $tensoranalysis RemoveAllInputs
+
+    itcl::delete obj $bishelper
+    itcl::delete obj $tensoranalysis
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_tensoranalysis::ConfigureOptionsGUICallbacks { } {
+
+    eval "$OptionsArray(guishowcontrol) SetGUICallbackFunction { $this ShowDTIControl }"
+}
+
+itcl::body bis_tensoranalysis::ShowDTIControl {  args } {
+
+
+    if { $tensoranalysis != 0 } {
+	if { [ $OptionsArray(guishowcontrol) GetValue ] ==0 } {
+	    $tensoranalysis HideWindow
+	} else  {
+	    $tensoranalysis ShowWindow Tensor
+	}
+    }
+}
+# ---------------------------------------------------------------
+
+itcl::body bis_tensoranalysis::DeleteDTIControl { } {
+
+    if { $tensoranalysis == 0 } {
+	return
+    }
+
+    $tensoranalysis ClearAllResults
+    #    $tensoranalysis RemoveAllInputs
+
+    itcl::delete obj $bishelper
+    itcl::delete obj $tensoranalysis
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_tensoranalysis::ConfigureOptionsGUICallbacks { } {
+
+    eval "$OptionsArray(guishowcontrol) SetGUICallbackFunction { $this ShowDTIControl }"
+}
+
+itcl::body bis_tensoranalysis::ShowDTIControl {  args } {
+
+
+    if { $tensoranalysis != 0 } {
+	if { [ $OptionsArray(guishowcontrol) GetValue ] ==0 } {
+	    $tensoranalysis HideWindow
+	} else  {
+	    $tensoranalysis ShowWindow Tensor
+	}
+    }
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_tensoranalysis::Execute {  } {
+
+    set image_in    [ $this GetInput ]  
+    set cscheme     [ $OptionsArray(cscheme) GetValue ]
+    set satfactor   [ $OptionsArray(satfactor) GetValue ]
+    set brightness  [ $OptionsArray(brightness) GetValue ]
+    set usemask     [ $OptionsArray(usemask) GetValue ]
+
+
+    if { $tensoranalysis == 0 } {
+
+	set bishelper [ [ bis_basecontrolhelper #auto $this ] GetThisPointer ]
+
+	if { $basewidget!=0 } {
+	    set b $basewidget.[pxvtable::vnewobj ]
+	} else {
+	    set b .[pxvtable::vnewobj ]
+	}
+	set  tensoranalysis [ [  mpjtensoranalysis \#auto $bishelper  ] GetThisPointer ]
+	$tensoranalysis Initialize $b
+	$tensoranalysis ShowWindow Tensor
+	$tensoranalysis HideWindow
+    }
+
+    if { [ $OptionsArray(guishowcontrol) GetValue ] == 1 } {
+	$tensoranalysis ShowWindow Tensor
+    } else {
+	$tensoranalysis HideWindow
+    }
+    
+
+    $tensoranalysis LoadTensor [ [ $this GetInput ] GetFileName ]
+    $tensoranalysis SetParametersFromBisAlgorithmAndCompute $cscheme $satfactor $brightness $usemask
+
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    
+    $this CopyOutputObject output_image 5 $comment "fa map"
+    $this CopyOutputObject out_ramap 6 $comment "relative anisotropy map"
+    $this CopyOutputObject out_meand 7 $comment "mean diff map"
+
+    $tensoranalysis BisComputeDirectionMaps
+    
+    set f2 [ [ $this GetOutputObject out_ormap ] GetFileName ]
+    [ $this GetOutputObject out_ormap ] ShallowCopy [ $tensoranalysis GetBisDirectionImage ]
+    [ $this GetOutputObject out_ormap ] AddComment "$comment (orientation map)" 
+    if { [ string length $f2 ] > 1 } {
+	[ $this GetOutputObject out_ormap ] SetFileName $f2
+    }
+
+    return 1
+
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_tensoranalysis.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_tensoranalysis [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_testdatabase.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_testdatabase.tcl
new file mode 100755
index 0000000..a2c6693
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_testdatabase.tcl
@@ -0,0 +1,197 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+
+package require bis_algorithm 1.0
+package require bis_viewer 1.0
+package require pxitclcamera 1.0
+package provide bis_testdatabase 1.0
+
+#
+# Operations involving multisubject average for testing ....
+#
+
+itcl::class bis_testdatabase {
+
+    inherit bis_algorithm
+    
+    constructor { } {
+	$this Initialize
+    }
+
+    public method Initialize { }
+    public method Execute { }
+    public method CreateTable { dbname tpname imgname }
+    public method GetGUIName { } { return "Test Database" }
+
+}
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_testdatabase::Initialize { } {
+
+    PrintDebug "bis_testdatabase::Initialize" 
+
+    #name,description,type,object,filename(if applicable),priority (optional)
+
+    set outputs { 
+	{ out_image "Saved Image" pxitclimage  ""    2000 }
+    }
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ sqlfile "Input database file name" "SQLite Filename:"  { filename readfile }  "" { "BioImage Suite SQLITE Files" { * }} 1 }
+	{ tablename  "SQL Table Name" "Table Name"  string "" { "" }  2 }
+	{ tableindex  "Index into table" "Index"  integer 0 { 0 1000 } 3 }
+	{ createtable  "0 or 1 to create table instead of doing anything else" "Create Table"  boolean  0 { 0  1 }  -10 }       
+	{ imgname "Input Image file name" "Image Filename to Add:"  { filename readfile }  "" pxitclimage -11 }
+    }
+
+    set defaultsuffix { "" }
+
+    set scriptname bis_testdatabase
+    set completionstatus ""
+    #
+    #document
+    #
+    set category "Utility"
+    set description "This is a test script for the BioImage Suite Viewers, primarily for regression testing"
+    set description2 ""
+    set backwardcompatibility ""
+    set authors "xenophon.papademetris.yale.edu"
+
+    $this AddDefaultOptions
+}
+
+itcl::body bis_testdatabase::CreateTable { dbname tpname imgname } {
+
+    set connector [ vtkbisDatabase New ]
+    $connector InitializeSQLite $dbname 
+    set ok [ $connector Connect ]
+    
+    if { $ok > 0 } {
+	set dbase [ vtkbisFilenameTable New ]
+	$dbase SetConnector $connector
+	$dbase CreateTable
+	$dbase DeleteAll $tpname
+
+	for { set i 0 } { $i < [ llength $imgname ] } { incr i } {
+	    puts stdout "AddingItem  $tpname [ file tail [ file rootname [ lindex $imgname $i ] ] ]  [ lindex $imgname $i ]"
+	    $dbase AddItem $tpname "IM_[ file tail [ file rootname [ lindex $imgname $i ] ] ]"  [ lindex $imgname $i ]
+	}
+	$dbase Delete
+    } else {
+	puts stdout "Failed to connect to $dbname"
+	set errormessage "Failed to connect to $dbname"
+    }
+
+    $connector Delete
+    return $ok
+}
+
+
+itcl::body bis_testdatabase::Execute {  } {
+
+
+    set dbname [ $OptionsArray(sqlfile) GetValue ]
+    set tpname [ $OptionsArray(tablename) GetValue ]
+    set index  [ $OptionsArray(tableindex) GetValue ]
+    set createtable  [ $OptionsArray(createtable) GetValue ]
+    set imgname  [ $OptionsArray(imgname) GetValue ]
+
+    if { $createtable > 0 } {
+	return [ $this CreateTable $dbname $tpname $imgname ]
+    }
+
+    set connector [ vtkbisDatabase New ]
+    $connector InitializeSQLite $dbname
+    set ok [ $connector Connect ]
+    if { $ok == 0 } {
+	set errormessage "Failed to open sqlite database $dbname" 
+	$connector Delete
+	return 0
+    }
+    set dbase [ vtkbisFilenameTable New ]
+    $dbase SetConnector $connector
+    $dbase CreateTable
+
+    set lst [ split [ $dbase QueryAll $tpname ] "|" ]
+    set max [ expr [ llength $lst ] -1 ]
+    for { set i 0 } { $i < $max } { incr i } {
+	puts stdout "Item $i = [ lindex $lst $i ]"
+    }
+
+    puts stdout "max=$max, lst=$lst"
+
+    if { [ llength $lst ] >= $index } {
+
+	set line [ lindex $lst $index ]
+	set lst2 [  split $line "," ]
+	set key   [string trim   [ lindex $lst2 1 ] ]
+	set fname0 [string trim   [ lindex $lst2 2 ] ]
+
+	set fname [ file join [ file dirname $dbname ] [ file tail $fname0 ] ]
+	puts stdout "\n\n\n\n Loading $key:$fname0 --> $fname "
+	set ok [ [ $this GetOutputObject out_image ] Load $fname ]
+
+	if { $ok > 0 } {
+	    set fdir [ file normalize [ file dirname $fname ] ]
+	    set ftail [ file tail $fname ]
+	    [ $this GetOutputObject out_image ] SetFileName  [ file join $fdir  "SQL_${ftail}" ]
+	} else {
+	    set errormessage "Failed to load image from $fname"
+	}
+    } else {
+	set ok 0
+	set errormessage "Failed To Find $index in database $tpname"
+    }
+
+    $dbase Delete
+    $connector Delete
+
+    return $ok
+}
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_testdatabase [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_testmatrix.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_testmatrix.tcl
new file mode 100755
index 0000000..8d8a0cd
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_testmatrix.tcl
@@ -0,0 +1,135 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+
+package require bis_algorithm 1.0
+package require bis_viewer 1.0
+package require pxitclcamera 1.0
+package provide bis_testmatrix 1.0
+
+#
+# Operations involving multisubject average for testing ....
+#
+
+itcl::class bis_testmatrix {
+
+    inherit bis_algorithm
+    
+    constructor { } {
+	$this Initialize
+    }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Test Matrix" }
+
+}
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_testmatrix::Initialize { } {
+
+    PrintDebug "bis_testmatrix::Initialize" 
+
+    #name,description,type,object,filename(if applicable),priority (optional)
+
+    set outputs { 
+	{ out_image "Saved Image" pxitclimage  ""    2000 }
+    }
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ matfile "Input matrix file name" "Matrix Filename:"  { filename readfile }  "" { "Matrix File" { *.mat* }} 1 }
+	{ matname  "Matrix Name" "Matrix Name"  string "" { "" }  2 }
+    }
+
+    set defaultsuffix { "" }
+
+    set scriptname bis_testmatrix
+    set completionstatus ""
+    #
+    #document
+    #
+    set category "Utility"
+    set description "This is a test script for the BioImage Suite Matrix code, primarily for regression testing"
+    set description2 ""
+    set backwardcompatibility ""
+    set authors "xenophon.papademetris.yale.edu"
+
+    $this AddDefaultOptions
+}
+
+
+itcl::body bis_testmatrix::Execute {  } {
+
+
+    set matname [ $OptionsArray(matname) GetValue ]
+    set matfile [ $OptionsArray(matfile) GetValue ]
+
+    set mat [ vtkpxMatrix New ]
+    set ok [ $mat ImportFromMatlab $matfile $matname  ]
+    if { $ok == 0 } {
+	set errormessage "Failed to read matrix $matfile ($matname)"
+    }
+
+    set img [ vtkImageData New ]
+    set sz [ $mat GetSize ]
+    $img SetDimensions [ lindex $sz 0 ] [ lindex $sz 1 ] 1
+    $img SetScalarTypeToFloat
+    $img AllocateScalars
+    for { set i 0 } { $i < [ lindex $sz 0 ] } { incr i } {
+	for { set j 0 } { $j < [ lindex $sz 1 ] } { incr j } {
+	    $img SetScalarComponentFromDouble $i $j 0 0 [ $mat GetElement $i $j ]
+	}
+    }
+
+    [ $this GetOutputObject out_image ] ShallowCopyImage $img
+    $img Delete
+    $mat Delete
+
+    return $ok
+}
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_testmatrix [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_testviewer.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_testviewer.tcl
new file mode 100755
index 0000000..656d9d1
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_testviewer.tcl
@@ -0,0 +1,221 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+
+package require bis_algorithm 1.0
+package require bis_viewer 1.0
+package require pxitclcamera 1.0
+package provide bis_testviewer 1.0
+
+#
+# Operations involving multisubject average for testing ....
+#
+
+itcl::class bis_testviewer {
+
+    inherit bis_algorithm
+    
+    constructor { } {
+	$this Initialize
+    }
+    destructor {
+	if { $test_viewer !=0 } {
+	    wm deiconify $tp
+	    destroy $tp
+	    itcl::delete object $test_viewer
+	}
+    }
+	
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Test Viewer" }
+
+    protected variable test_viewer 0
+    protected variable tp 0
+
+}
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_testviewer::Initialize { } {
+
+    PrintDebug "bis_testviewer::Initialize" 
+
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set inputs { 
+	{ input_image "Input Image" pxitclimage  ""    1000 }
+	{ objectmap_image "Objectmap Image" pxitclimage  ""    1001 }
+	{ input_surface "Input Surface" pxitclsurface  ""    1002 }
+	{ input_landmarks "Input Landmarks" pxitcllandmarks  ""    1003 }
+    }
+    set outputs { 
+	{ out_image "Viewer 2D Grab Image" pxitclimage  ""    2000 }
+    }
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ magn "Zoom Mode for Snapshots" "Magnification" integer 1 { 1 4 } 1 }
+	{ vtype "Type of Viewer" "ViewerType"  listofvalues  ortho { ortho ortho4d mos singleslice }   -1 }
+	{ edit "Enable Editor in viewer" "Editor:"  { boolean checkbutton } 0 { 0 1 }  -2 }
+	{ ortho3d "Items to display in 3D Viewer Mode" "Ortho3D"  integer 1 { 0 7 } -10 }
+	{ orthomode "Mode for ortho viewer" "OrthoMode" integer 1 { 0 7 } -11 }
+	{ mosrows  "Rows to display in mosaic Viewer" "Mosaic Rows" integer 1 { 1 6 } -12 }
+	{ moscols  "Columns to display in mosaic Viewer" "Mosaic Columns" integer 1 { 1 6 } -12 }
+	{ camera "Input camera file name" "Camera Name:"  { filename readfile }  "" { "Camera Files" { .cm}} -15 }
+    }
+
+
+    set createviewermode 0
+
+
+    set defaultsuffix { "" }
+
+    set scriptname bis_testviewer
+    set completionstatus ""
+    #
+    #document
+    #
+    set category "Utility"
+    set description "This is a test script for the BioImage Suite Viewers, primarily for regression testing"
+    set description2 ""
+    set backwardcompatibility ""
+    set authors "xenophon.papademetris.yale.edu"
+
+    $this AddDefaultOptions
+
+
+}
+
+
+
+
+itcl::body bis_testviewer::Execute {  } {
+
+    if { $test_viewer == 0 } {
+	set tp [ toplevel .[ pxvtable::vnewobj ] -bg red ]
+	wm deiconify $tp
+	wm geometry $tp 800x620
+	update idletasks
+	wm title $tp "Test Viewer "
+
+	set nv [ frame $tp.1 -height 600 -width 600 ]
+	pack $nv -side left -expand false
+	
+	frame $tp.2 -bg darkgreen -height 600 -width 100
+	pack $tp.2 -side right -expand true -fill both
+	
+	
+	set test_viewer [ [ bis_viewer \#auto ] GetThisPointer ]
+	$test_viewer configure -enable_toolbar 0
+	$test_viewer configure -enable_openigtlinkgadget 0
+	$test_viewer configure -enable_landmarkeditor 0
+	$test_viewer configure -enable_electrodeeditor 0
+	$test_viewer SetViewerType [ $OptionsArray(vtype) GetValue ] [ $OptionsArray(edit) GetValue ]
+	$test_viewer CreateGUI $nv
+	[ $test_viewer GetViewer ] SetShowControls 0 
+	update idletasks
+	puts stdout "Width = [ $nv cget -width ], Height = [ $nv cget -height ]"
+    } 
+	
+    wm deiconify $tp
+    update idletasks    
+
+    set img  [ $this GetInputObject input_image ]
+
+    if { [ $img GetSize  ] > 1 } {
+	$test_viewer SetImage $img
+	$test_viewer SetImageColormapMode 0
+    }
+
+    set msk  [ $this GetInputObject objectmap_image ] 
+    $test_viewer SetMask $msk
+
+    set vt [ $test_viewer GetViewer ]
+    if { [ $vt IsA "vtkpxGUIOrthogonalViewer"  ] == 1 } {
+	$vt SetDisplayMode [ expr int([$OptionsArray(orthomode) GetValue]) ]
+	$vt SetDisplay3DMode [ expr int([$OptionsArray(ortho3d) GetValue]) ]
+
+	if { [ $OptionsArray(camera)  GetValue ] != ""  } {
+	    set cam [ pxitclcamera #auto ]
+	    $cam Load [ $OptionsArray(camera) GetValue ]
+	    set ren [ $vt GetRenderer 3 ]
+	    set newcam [ [ $ren GetRenderer ] GetActiveCamera ]
+	    $ren CopyCamera $newcam [ $cam GetCamera ]
+	    itcl::delete object $cam
+	    $ren CameraModifiedCallback
+	    $ren Render
+	}
+    } else {
+	$vt SetConfiguration [ expr int([$OptionsArray(mosrows) GetValue ]) ] [ expr int([$OptionsArray(moscols) GetValue]) ]
+    }
+
+    if { [ $vt IsA "vtkpxGUIOrthogonalViewer"  ] == 1 } {
+	set sur [ $this GetInputObject input_surface ]
+	if { [ $sur GetSize ] > 0 } {
+	    $test_viewer AddPolygonalObject $sur
+	}
+	
+	set land [ $this GetInputObject input_landmarks ]
+	if { [ $sur GetSize ] > 0 } {
+	    $test_viewer AddPolygonalObject $sur
+	}
+    }
+
+    $this SetOptionValue ctestgui 1
+
+    update idletasks
+
+    # --------------------
+    # Generate Output
+    # ---------------------
+    set img [ $test_viewer GetScreenshotImage [ $OptionsArray(magn) GetValue ] ]
+    [ $this GetOutputObject out_image ] ShallowCopyImage $img
+    $img Delete
+
+    return 1
+}
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_testviewer [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_thresholdimage.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_thresholdimage.tcl
new file mode 100755
index 0000000..41b27de
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_thresholdimage.tcl
@@ -0,0 +1,168 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_basethresholdimage 1.0
+
+package provide bis_thresholdimage 1.0
+
+# -----------------------------------------------------------------------------------------
+# threshold image
+#
+
+itcl::class bis_thresholdimage {
+
+    inherit bis_basethresholdimage
+
+     constructor { } {
+	 $this InitializeThresholdImage
+     }
+
+    public method InitializeThresholdImage { }
+    public method Execute { }
+    public method GetGUIName    { } { return "Threshold Image" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_thresholdimage::InitializeThresholdImage { } {
+
+    PrintDebug "bis_thresholdimage::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    lappend  options [ list setmintozero "Set Minimum Value to Zero" "Min Value to Zero"   { listofvalues radiobuttons } Off  { On Off }  7 ]
+
+    set scriptname bis_thresholdimage
+    set completionstatus "Implementation needs work, interface is OK" 
+    #document
+    #
+    set description "thresholds an image to generate a binary output using a specific threshold."
+    set description2 "The output is a binary image with value = 100 where the original image had values above the threshold and zero elsewhere."
+    set backwardcompatibility "Reimplemented from pxmat_thresholdimage.tcl"
+    
+
+    $this InitializeBaseThresholdImage
+}
+
+
+itcl::body bis_thresholdimage::Execute {  } {
+    
+    set lst [ $this ParseArgs ]
+    set invalue  [ lindex $lst 0 ]
+    set outvalue [ lindex $lst 1 ]
+    set replin   [ lindex $lst 2 ] 
+    set replout  [ lindex $lst 3 ]
+    set dobinary [ lindex $lst 4 ]
+    set dosub    [ $OptionsArray(setmintozero) GetValue ]
+
+    set dosubtraction 0
+    if { $dosub == "On" && $dobinary ==0 } {
+	set dosubtraction 1
+    } 
+
+    set minth         [ $OptionsArray(minth) GetValue ]
+    set maxth         [ $OptionsArray(maxth) GetValue ]
+    
+    puts stderr "Dosub=$dosubtraction ($dosub), binm=$dobinary $minth:$maxth inout=$invalue:$outvalue"
+
+    set outimage [ $this GetOutput ]
+
+    
+    if { $dosubtraction == 0 } {
+	set thresholdF  [  vtkImageThreshold New ]
+	$thresholdF ThresholdBetween  $minth $maxth
+	$thresholdF SetInValue    $invalue
+	$thresholdF SetOutValue   $outvalue
+	$thresholdF SetReplaceOut $replout
+	$thresholdF SetReplaceIn  $replin
+	$thresholdF SetInput [ [ $this GetInput ] GetImage ]
+	
+	if { $dobinary == 1 } {
+	    $thresholdF SetOutputScalarTypeToShort
+	}
+	SetFilterCallbacks $thresholdF "Thresholding image"
+	$thresholdF Update
+	
+	$outimage ShallowCopyImage  [ $thresholdF GetOutput ]
+	$thresholdF Delete 
+    } else {
+        set sh [ vtkImageShiftScale New]
+	set lower   $minth
+	set upper   $maxth
+	set range   [ expr $upper - $lower ]
+	
+	$sh SetInput [ [ $this GetInput ] GetImage ]
+	$sh SetShift [expr -1.0*$lower ]
+	$sh SetScale 1.0
+	SetFilterCallbacks $sh "Shifting offset"
+	
+	set thresholdF  [  vtkImageThreshold New ]
+	$thresholdF SetInput [ $sh GetOutput ]	
+	$thresholdF ThresholdBetween -0.001 [expr $range + 0.001 ]
+	$thresholdF ReplaceOutOn
+	$thresholdF SetInValue    $invalue
+	$thresholdF SetOutValue   $outvalue
+	$thresholdF SetReplaceOut $replout
+	$thresholdF SetReplaceIn  $replin
+	
+	SetFilterCallbacks $thresholdF "Thresholding image"
+	$thresholdF Update
+	$outimage ShallowCopyImage  [ $thresholdF GetOutput ]
+	$thresholdF Delete 
+	$sh Delete
+    }
+
+
+    $outimage CopyImageHeader  [ [ $this GetInput ] GetImageHeader ]
+    [ $outimage GetImageHeader ] AddComment "[ $this GetCommandLine full ]" 0
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_thresholdimage.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    set alg [bis_thresholdimage [pxvtable::vnewobj]]
+    $alg MainFunction 
+
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_thresholdpoints.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_thresholdpoints.tcl
new file mode 100755
index 0000000..e509ebd
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_thresholdpoints.tcl
@@ -0,0 +1,146 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetosurfacealgorithm 1.0                
+package provide bis_thresholdpoints 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_thresholdpoints {
+
+    inherit bis_imagetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Threshold points" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_thresholdpoints::Initialize { } {
+
+    PrintDebug "bis_thresholdpoints::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+		{ thresholdMethod "Thresholding method" "Thresholding method" { listofvalues radiobutton}  Below_Lower { Below_Lower Above_Higer Between}   0}
+		{ lowthreshold "Low Threshold" "Low Threshold"  { real triplescale 100 }    0.0 { 0.0 255.0 } 1 }
+		{ highthreshold "High Threshold" "High Threshold"  { real triplescale 100 }    255.0 { 0.0 255.0 } 2 }
+    }
+	
+    set defaultsuffix { "_thresholdsurface" }
+    
+    set scriptname bis_thresholdpoints
+	
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "Extract a surface from an image"
+    set description2 ""
+    set backwardcompaibitlity "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeImageToSurfaceAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_thresholdpoints::Execute {  } {
+
+    PrintDebug "bis_thresholdpoints::Execute"
+
+    # Get Inputs
+    set image_in [ $this GetInput ]
+
+    # GetOptions
+    set thresholdMethod [ $OptionsArray(thresholdMethod) GetValue ]
+    set lowthreshold [ $OptionsArray(lowthreshold) GetValue ]
+    set highthreshold [ $OptionsArray(highthreshold) GetValue ]
+
+    if { $lowthreshold > $highthreshold } { 
+	    set temp $lowthreshold 
+	    set lowthreshold $highthreshold
+	    set highthreshold $temp
+	    puts "Lower threshold was greater than High threshold. The values have been swapped"
+	}
+	
+	set thrfilter [ vtkThresholdPoints [ pxvtable::vnewobj ] ]
+	$thrfilter SetInput  [ $image_in GetObject]
+
+	if { $thresholdMethod == "Below_Lower" } { 
+			$thrfilter ThresholdByLower $lowthreshold
+		} elseif { $thresholdMethod == "Above_Higher" } {
+			$thrfilter ThresholdByUpper $highthreshold
+		} else {
+			$thrfilter ThresholdBetween $lowthreshold $highthreshold
+		}
+
+		$thrfilter Update
+		
+	set surface_out [$thrfilter GetOutput ]
+	
+    # Store Results in output
+	[ $OutputsArray(output_surface) GetObject ] DeepCopySurface $surface_out 
+	
+    # Clean up
+	$thrfilter Delete
+	
+	return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_thresholdpoints.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_thresholdpoints [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_tmaptopvalue.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_tmaptopvalue.tcl
new file mode 100755
index 0000000..cea7c74
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_tmaptopvalue.tcl
@@ -0,0 +1,140 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package require vtkpxcontrib     1.2
+
+package provide bis_tmaptopvalue 1.0
+
+
+itcl::class bis_tmaptopvalue {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "T-score to P-value" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_tmaptopvalue::Initialize { } {
+
+    PrintDebug "bis_tmaptopvalue::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+   
+     set options {
+	 { dof         "Degree of Freedom" "DOF"   int    1   {.0            100000000   }  0 }
+	 { scaleFactor "Scale factor "     "Scale" float  1.0 { -100000000.0 100000000.0 }  -10 }
+	 { autoscale   "Detect Whether t-values are scaled by 1000 or not"	  "AutoScale"   boolean	 1 { 0 1  }  6 } 
+    }
+
+    set defaultsuffix { "_pvalue" }
+    
+    set completionstatus "Done, tested"
+
+    set scriptname bis_tmaptopvalue
+
+
+    set description "converts tmap to pvalue."
+    set description2 ""
+    set backwardcompatibility "N/A"
+    set authors ""
+    set category "Functional Imaging"
+
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_tmaptopvalue::Execute {  } {
+
+    PrintDebug "bis_tmaptopvalue::Execute"
+
+    set dof         [ $OptionsArray(dof)          GetValue  ]
+    set image_in    [ $InputsArray(input_image)   GetObject ]
+    set outimage    [ $OutputsArray(output_image) GetObject ]
+    set autoscale   [ $OptionsArray(autoscale)  GetValue  ]
+    
+
+    if { $autoscale == 1 } {
+	set r [ lindex [ [ [ [ $image_in GetImage ] GetPointData ] GetScalars ] GetRange ] 1 ]
+	if { $r > 1000.0 } {
+	    puts stderr "Setting scaleFactor to 1000.0"
+	    $this SetOptionValue scaleFactor 1000.0
+	} else {
+	    $this SetOptionValue scaleFactor 1.0
+	}
+    }
+    set scaleFactor [ $OptionsArray(scaleFactor)  GetValue  ]
+
+    set tm [ vtkpxComputeTmap [ pxvtable::vnewobj ] ]
+    set image_out [ $tm TmapToPvalueConversion [ $image_in GetImage ] $dof $scaleFactor ]
+
+    $outimage ShallowCopyImage $image_out 
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format "BIS::bis_tmaptopvalue.tcl"  ]
+    [ $outimage GetImageHeader ] AddComment "[ $this GetCommandLine full ]" 0
+
+    $tm Delete
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_tmaptopvalue.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_tmaptopvalue [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_tmaptozscore.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_tmaptozscore.tcl
new file mode 100755
index 0000000..5000eed
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_tmaptozscore.tcl
@@ -0,0 +1,136 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package require vtkpxcontrib     1.2
+
+package provide bis_tmaptozscore 1.0
+
+
+itcl::class bis_tmaptozscore {
+
+    inherit bis_imagetoimagealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName    { } { return "T-score to Z-score" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_tmaptozscore::Initialize { } {
+
+    PrintDebug "bis_tmaptozscore::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+   
+     set options {
+	{ dof         "Degree of Freedom" "DOF"   int    1   {.0            100000000   }  0 }
+	{ scaleFactor "Scale factor "     "Scale" float  1.0 { -100000000.0 100000000.0 }  -10 }
+	 { autoscale   "Detect Whether t-values are scaled by 1000 or not"	  "AutoScale"   boolean	 1 { 0 1  }  6 } 
+    }
+
+    set defaultsuffix { "_zscore" }
+    
+    set completionstatus "Done  --  needs testing"
+
+    set scriptname bis_tmaptozscore
+
+
+    set description "converts tmap to zscore."
+    set description2 ""
+    set backwardcompatibility "N/A"
+    set authors ""
+    set category "Functional Imaging"
+    $this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_tmaptozscore::Execute {  } {
+
+    PrintDebug "bis_tmaptozscore::Execute"
+
+    set dof         [ $OptionsArray(dof)          GetValue  ]
+    set image_in    [ $InputsArray(input_image)   GetObject ]
+    set outimage    [ $OutputsArray(output_image) GetObject ]
+    set autoscale   [ $OptionsArray(autoscale)  GetValue  ]
+    if { $autoscale == 1 } {
+	set r [ lindex [ [ [ [ $image_in GetImage ] GetPointData ] GetScalars ] GetRange ] 1 ]
+	if { $r > 1000.0 } {
+	    $this SetOptionValue scaleFactor 1000.0
+	} else {
+	    $this SetOptionValue scaleFactor 1.0
+	}
+    }
+    set scaleFactor [ $OptionsArray(scaleFactor)  GetValue  ]
+
+    set tm [ vtkpxComputeTmap [ pxvtable::vnewobj ] ]
+    set image_out [ $tm TmapToZScoreConversion [ $image_in GetImage ] $dof $scaleFactor ]
+
+    $outimage ShallowCopyImage $image_out 
+    $outimage CopyImageHeader [ $image_in GetImageHeader ]
+
+    set comment [ format "BIS::bis_tmaptozscore.tcl"  ]
+    [ $outimage GetImageHeader ] AddComment "[ $this GetCommandLine full ]" 0
+
+    $tm Delete
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_tmaptozscore.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_tmaptozscore [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_transformsurface.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_transformsurface.tcl
new file mode 100755
index 0000000..5e0c40e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_transformsurface.tcl
@@ -0,0 +1,173 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_surfacetosurfacealgorithm 1.0
+
+package provide bis_transformsurface 1.0
+
+#
+# transform polydata
+#
+
+itcl::class bis_transformsurface {
+
+    inherit bis_surfacetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+
+    public method GetTransformation { }
+    public method SetTransformation { tr }
+    public method SetVTKTransformation { tr }
+    public method GetGUIName { } { return "Transform Surface" }
+    public method  UpdateOutputFilenames { } 
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_transformsurface::Initialize { } {
+
+    PrintDebug "bis_transformsurface::Initialize" 
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set inputs {
+	{ transformation "Transformation"    pxitcltransform  ""  80 }
+    }
+
+    set options { 
+	{ guicmt2  "Description of the filter"  "Note"  comment "Transform surface" "Transforms a surface using the transformation specified." 400 }
+    }
+
+    
+    set defaultsuffix { "_xform" }
+    
+    set scriptname bis_transformsurface
+
+    #
+    #document
+    #
+
+    set category "Surface Processing"
+    set description "Transforms (warps) a surface using a transformation"
+    set description2 ""
+    set backwardcompatibility ""
+    set authors "hirohito.okuda at yale.edu"
+
+    $this InitializeSurfacetoSurfaceAlgorithm
+}
+
+itcl::body bis_transformsurface::SetTransformation  { tr } {
+
+    $this SetInputObject transformation $tr
+}
+
+itcl::body bis_transformsurface::SetVTKTransformation  { tr } {
+
+    set t [ $this GetInputObject transformation ]
+    #    puts stderr "$t copying transformation from $tr ([$tr GetClassName])"
+    $t CopyTransformation $tr
+    $t configure -filename [ $tr GetClassName ]
+}
+
+itcl::body bis_transformsurface::GetTransformation { } {
+
+    return [ $this GetInputObject transformation ]
+}
+
+itcl::body bis_transformsurface::UpdateOutputFilenames { } {
+
+    set f(0) [ $InputsArray(input_surface) GetFileName ]
+    set f(1) [ [ $this GetTransformation ] cget -filename ]
+
+    for { set i 0 } { $i <= 1 } { incr i } {
+	set l($i) [ ::bis_common::SplitFileNameGZ $f($i) ]
+	set p($i) [ file dirname $f($i) ]
+	set f($i) [ file tail [ lindex $l($i) 0 ] ]
+
+	set ext($i) [ lindex $l($i) 1 ]
+    }
+    
+    set fname [ file join $p(0) "$f(0)_$f(1)" ]
+    
+    set outlist [ $this CreateDefaultOutputFileList $fname ]
+    set force 0; if { $guimode == "managed" } {	set force 1    }
+    $OutputsArray(output_surface) SetFileName "[ lindex $outlist 0 ]$ext(0)" $force 
+    return 1
+
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_transformsurface::Execute {  } {
+
+    set surface    [ $InputsArray(input_surface) GetObject ]
+    set trans      [ $InputsArray(transformation) GetObject ] 
+
+
+    set filter [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $filter SetInput  [ $surface  GetSurface ]
+    $filter SetTransform  [ $trans  GetTransformation ]
+    $filter Update
+
+    set surface_out [$filter GetOutput ]
+
+    [ $OutputsArray(output_surface) GetObject ] DeepCopySurface $surface_out 
+
+    $filter Delete
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_transformsurface.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_transformsurface [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_treeapp.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_treeapp.tcl
new file mode 100755
index 0000000..0d02fef
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_treeapp.tcl
@@ -0,0 +1,730 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+
+package provide bis_treeapp 1.0
+package require bis_treewidget 1.0
+package require bis_algorithm 1.0
+package require bis_xmlalgorithm
+package require pxitclfilelistmenu 1.0
+package require pxtcluserprefs 1.0
+package require bis_common 1.0
+itcl::class bis_treeapp {
+
+    inherit bis_algorithm
+
+     constructor { } {	 $this Initialize  }
+
+    public method Initialize { }
+    public method CreateGUI  { parent { callafter 0 } { callbefore 0 } }
+    public method GetGUIName    { } { return "BioImage Suite DataTree" }
+
+    protected method CreateMenu { menubase viewerlist }
+    protected method AddComponents { }
+    protected method AddPlugins { }
+    public method AddSinglePlugin { fname }
+
+
+    public method LoadTree { args }
+    public method GetTreeName {  } { return [ $OptionsArray(treefile) GetValue ] }
+    public method SaveTree { mode args }
+    public method CheckTree { args }
+
+    public method ShowTool { tool }
+    public method SetCurrentViewer { vr }
+    public method GrabImageFromViewer { vr }
+    public method SetComponentsList { lst } { set componentslist $lst }
+    public method SetPlugins { lst } { set pluginslist $lst }
+    public method UpdateToolChoiceMenu { }
+
+    protected variable treewidget 0
+    protected variable menubase 0
+    protected variable compmenu 0
+    protected variable viewmenu 0
+
+    protected variable componentlist ""
+    protected variable pluginslist  ""
+    protected variable toollist ""
+    protected variable initializedtools ""
+    protected variable toolwidgetarray
+    protected variable toolbase 0
+    protected variable currenttoolwidget 0
+    protected variable currenttool 0
+    protected variable toolchoicemenu 0
+    protected variable categorychoicemenu 0
+    protected variable categorytoolarray 
+    protected variable categories "" 
+    protected variable pluginmenu 0
+    protected variable pref_dialog 0
+    protected variable viewerlist ""
+    protected variable pluginname "Plugins"
+    protected common thisparam
+    protected variable helpdialog 0
+
+    public method HelpCommand { }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_treeapp::Initialize { } {
+
+    PrintDebug "bis_treeapp::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+    	{ treefile   "specify the filname for the datatree" "DataTree  File Name" { filename readile } "" { datatree } 1 }
+	{ componentfile   "specify the filname of the text file containing the list of components to use" "Component  File Name" { filename readile } "" { textfile } 2 }
+	{ pluginfile   "specify the filname of the text file containing the list of executable plugins to use" "Plugin  File Name" { filename readile } "" { textfile } 2 }
+    }
+
+    set scriptname "DataTree v2"
+    set completionstatus "Done"
+
+    #
+    #document
+    #
+    
+    set description "Data Tree Application"
+    set description2 ""
+    set backwardcompatibility "Replaces old BioImage Suite datatree"
+    set forceguimode 1
+    set category "GUI"
+    set componentlist [ list bis_computeglm bis_ISAS bis_ISASHN bis_biasfield bis_sliceinhomogeneity bis_blendimage bis_castimage bis_checkerboardimage bis_cleansurface bis_clipsurface bis_clusterthresholdimage bis_colorblendimage bis_combineframes bis_combineimages bis_computedisplacementfield bis_computenormals bis_computeoverlap bis_computesimilarity bis_connect bis_convolveimage bis_create4dimage bis_createoverlayimage bis_cropimage bis_csfwmmotioncorr bis_curvatures bis_cylindricalc [...]
+
+#    set componentlist [ list bis_smoothimage bis_manualregistration bis_nonlinearintensityregister bis_create4dimage ]
+#    set pluginslist [ list /usr/local/slicer/Slicer3-build/lib/Slicer3/Plugins/MedianImageFilter /usr/local/slicer/Slicer3-build/lib/Slicer3/Plugins/OtsuThresholdSegmentation  ]
+
+    set thisparam($this,currentviewer) 0
+    $this AddDefaultOptions
+}
+# -----------------------------------------------------------------------------------------
+itcl::body bis_treeapp::CheckTree { args } {
+
+    set lst  [ [ $treewidget GetDataManager ] CheckSavedObjects 0 0 ]
+    if { [ llength $lst ] == 0 } {
+	tk_messageBox -type ok -message "All Objects in the tree are saved" -title "Tree OK" -icon info
+	return  1
+    }
+	
+    pxtkconsole
+    foreach l $lst {
+	if { [ string length $l ] > 0 } {
+	    pxtkprint "Item $l not saved\n"
+	}
+    }
+
+    set msg [ tk_messageBox -type yesno -message "Same Objects in the tree are not saved on disk. Do you want to save them?" -title "Not all nodes are saved" -icon warning ]
+
+    if { $msg == "no" } {
+	return 0
+    }
+
+    
+    set lst  [ [ $treewidget GetDataManager ] CheckSavedObjects 0 1 ]
+    if { [ llength $lst ] == 0 } {
+	tk_messageBox -type ok -message "All Objects in the tree are saved" -title "Tree OK" -icon info
+	return  1
+    }
+
+    tk_messageBox -type ok -message "Some Objects in the tree are still not saved. Try to fix manually." -title "Tree Problem" -icon info
+    foreach l $lst {
+	if { [ string length $l ] > 0 } {
+	    pxtkprint "Item $l not saved\n"
+	}
+    }
+	
+    
+}
+# -----------------------------------------------------------------------------------------
+itcl::body bis_treeapp::LoadTree { args } {
+
+    if { [ llength $args ] > 0 } {
+	set val [ lindex $args 0 ]
+    } else {
+	set val [ $OptionsArray(treefile) GetValue ]
+    }
+
+    if { [ file exists $val ] == 0 } {
+	set val ""
+    }
+    set fname [ $treewidget LoadDataTree  $val ]
+    if { [ string length $fname ] > 1 } {
+	$OptionsArray(treefile) SetValue $fname
+	wm title $basewidget "DataTree Application $fname"
+    }
+}
+
+itcl::body bis_treeapp::SaveTree { mode args } {
+
+    if { $mode == 1 } {
+	set val [ $OptionsArray(treefile) GetValue ]
+    } else {
+	set val ""
+    }
+
+    set fname [ $treewidget SaveDataTree  $val ]
+    if { [ string length $fname ] > 1 } {
+	$OptionsArray(treefile) SetValue $fname
+	wm title $basewidget "DataTree Application $fname"
+    }
+}
+
+# --------------------------------------------------------------
+
+itcl::body bis_treeapp::CreateMenu { menubase viewerlist } {
+    global env
+    global pxtcl_pref_array
+
+    set filem [ menu $menubase.file -tearoff 0  ]
+    $menubase add cascade -underline 0  -label "File" -menu $filem
+
+    eval "$filem add command -label Load -command { $this LoadTree \"\" }  "
+    eval "$filem add command -label Save -command { $this SaveTree 1 \"\" }  "
+    eval "$filem add command -label SaveAs -command { $this SaveTree 0 \"\" }  "
+    $filem add separator
+    eval "$filem add command -label \"Check Tree\" -command { $this CheckTree }"
+    eval "$filem add command -label \"Switch Directory\" -command { $this SetCurrentDirectory } "
+    $filem add separator
+
+    set thisparam($this,custdirectories)  [ pxitclfilelistmenu \#auto $filem "Custom Directories" "$this SetCurrentDirectory" ]
+    $thisparam($this,custdirectories) SetModeToDirectories
+    $thisparam($this,custdirectories) InitializeDisplay
+    global env
+
+    set tthis [ itcl::scope $this ]
+    set thisparam($this,custsetups)  [ pxitclfilelistmenu \#auto $filem "Tree Files" "$tthis LoadTree" "$tthis GetTreeName" ]
+    $thisparam($this,custsetups) SetModeToCustom "DataTree Files" .xmltree [ file join $env(HOME) .xmltreefiles ] 1 
+    $thisparam($this,custsetups) InitializeDisplay
+    $filem add separator
+
+    eval "$filem add command -label Exit -command {  $this ExitCommand } -underline 1"
+
+
+    set viewmenu [ menu $menubase.vmenu -tearoff 0 ]
+    $menubase add cascade -underline 0  -label "Viewer" -menu $viewmenu
+
+    set n [ llength $viewerlist ]
+    set vm2 [ menu $viewmenu.s -tearoff 0 ]
+    $viewmenu add cascade -underline 0  -label "Select Current Viewer" -menu $vm2
+    $viewmenu add separator
+    for { set i 1 } { $i <= $n } { incr i } {
+        eval "$vm2 add radio -variable [ itcl::scope thisparam($this,currentviewer) ]  -value [ expr $i -1 ] -label \"Viewer $i\" -command { $this SetCurrentViewer [ expr $i -1 ] } "
+    }
+
+    set compmenu [ menu $menubase.comp -tearoff 0 ]
+    $menubase add cascade -underline 0  -label "Algorithms" -menu $compmenu
+
+
+    set helpm [ menu $menubase.help -tearoff 0  ]
+    $menubase add cascade -underline 0  -label "Help" -menu $helpm 
+    
+    eval "$helpm add command -label \"Help Index\" -command { $this HelpCommand }"
+    eval "$helpm add separator"
+
+    eval "$helpm add command -label Preferences -command { wm deiconify $pref_dialog}"
+    $helpm add command -label Console -command { pxtkconsole }
+    eval "$helpm add separator"
+    eval "$helpm add command -label About -command { $this AboutCommand }"
+
+}
+
+itcl::body bis_treeapp::HelpCommand { } {
+
+    if { $helpdialog != 0 } {
+	::pxtclutil::ShowWindow $helpdialog
+	return
+    }
+
+    set bname [ file normalize [ file join $::pxtclvtkpxcontrib::baselibrarypath  .. ] ]
+
+    set b(1) [ file join $bname html ]
+    set b(2) [ file join [ file join $bname .. ] build/html ]
+    set b(3) [ file join [ file join $bname .. ] build64/html ]
+
+    set i 1
+    set rootname 0
+    while { $i < 3 } {
+	set f [ file normalize [ file join $b($i) index.html ] ]
+	puts stdout "Looking for $f"
+	if { [ file exists $f ] > 0 } {
+	    set i 4
+	    set rootname $f
+	}
+	incr i
+    }
+    
+    set w .
+    if { [ string length $basewidget ] > 2 } { set w $basewidget }
+    
+    set helpdialog  [ toplevel $w.[ pxvtable::vnewobj ]] 
+    wm geometry $helpdialog 800x600
+    
+    wm title $helpdialog "BioImage Suite Tools Manual Pages"
+    
+    set scr [ iwidgets::scrolledhtml $helpdialog.t  -labeltext "" \
+		  -width 6i -height 3i \
+		  -wrap word -padx 2 ]
+    $scr configure -fontsize large
+    
+    pack $scr -side top -expand true -fill both
+    ::bis_algorithm::SetWidgetTreeColors $scr "\#8197c5" white    
+       
+    if { $rootname != 0 } {
+	$scr import $rootname
+    } else {
+	$scr insert end "No Man Pages Found"
+    }
+    
+    ::pxtclutil::ShowWindow $helpdialog
+}
+
+
+itcl::body bis_treeapp::AddComponents {  } {
+
+    #set componentlist { bis_smoothimage bis_cropimage }
+
+    set val [ $OptionsArray(componentfile) GetValue ]
+    if { [ file exists $val ]  > 0 } {
+	set componentlist ""
+	set fin [ open $val r ]
+	while { [ gets $fin line ] >=0 } {
+	    if { [ string first "\#" $line ]  == -1 } {
+		lappend componentlist [ file rootname [ string trim $line ] ]
+	    }
+	}
+	close $fin
+    }
+    puts stderr "New Components = $componentlist"
+    
+    set qlist [lsort -ascii  $componentlist ]
+    set componentlist ""
+    set index 0
+    set num [ llength $qlist ]
+
+    foreach tool $qlist {
+	set ok 0 
+	catch { package require $tool ; set ok 1 }
+	if { $ok == 1 } {
+	    lappend componentlist $tool
+	    set cmt "Loading"
+	}  else {
+	    set cmt "Ignoring"
+	} 
+	incr index
+	set per [ expr double($index)/double($num) ]
+	$treewidget ShowProgressVal "Loading Components" $per
+	update idletasks
+    }
+    $treewidget ShowProgressVal "Done" 1.0
+
+    set categories [ ::bis_common::GetCategories ]
+    set toollist ""
+
+    eval "iwidgets::optionmenu $toolbase.0 -labeltext \"Grp:\" -labelpos w -command { $this UpdateToolChoiceMenu } "
+    eval "iwidgets::optionmenu $toolbase.1 -labeltext \"Alg:\" -labelpos w -command { $this ShowTool 0 } "
+    pack $toolbase.0 $toolbase.1 -side top -expand false -fill x
+    set toolchoicemenu  $toolbase.1
+    set categorychoicemenu  $toolbase.0
+
+    foreach tool $componentlist {
+	set alg [ [ $tool [pxvtable::vnewobj] ] GetThisPointer ]
+	$alg InitializeFromContainer 0 $treewidget
+	$alg SetBisViewer $bis_viewer
+	$alg SetDataTree $treewidget
+
+	set categ  [$alg GetCategory]
+	if { $categ == "" } {
+	    set categ "Other"
+	}
+	if { $categ != "GUI" } {
+	    set componentcat($alg) $categ
+	    if { [ lsearch -exact $categories $categ ] == -1 } {
+		lappend categories $categ
+	    }
+	    
+	    lappend toollist $alg
+	}
+    }
+    
+    for { set i 0 } { $i < [ llength $categories ] } { incr i } {
+	set grp [ lindex $categories $i ]
+
+	set num 0
+	foreach alg $toollist {
+	    set categ  $componentcat($alg)
+	    if { $categ == "" } {
+		set categ "Other"
+	    }
+	    if { $grp==$categ } {
+		set n [ $alg GetGUIName ]
+		
+		if { $num == 0 } {
+		    set disp [ menu $compmenu.[ pxvtable::vnewobj ] -tearoff 0 ]
+		    $compmenu add cascade -label "$grp" -menu $disp
+		}
+
+		eval "$disp add command -label \"$n\" -command { $this ShowTool $alg  } "
+		lappend categorytoolarray($categ) $alg
+		incr num
+	    }
+	}
+	if { $num > 0 } {
+	    $categorychoicemenu insert end "$grp"
+	}
+    }
+
+}
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_treeapp::AddPlugins {  } {
+
+    set val [ $OptionsArray(pluginfile) GetValue ]
+    if { [ file exists $val ]  } {
+	set pluginslist ""
+	set fin [ open $val r ]
+	while { [ gets $fin line ] >=0 } {
+	    if { [ string first "\#" $line ]  == -1 } {
+		lappend pluginslist  [ string trim $line ]
+	    }
+	}
+	close $fin
+	puts stderr "New Plugins = $pluginslist"
+    }
+
+
+    if { [ llength $pluginslist ] == 0 } {
+	return
+    }
+
+    set tmpname [ file join /tmp [pid].xml ]
+    set pluginmenu [ menu $compmenu.[ pxvtable::vnewobj ] -tearoff 0 ]
+    $compmenu add cascade -label "$pluginname" -menu $pluginmenu
+    $categorychoicemenu insert end "$pluginname"
+    set categorytoolarray($pluginname) ""
+
+    eval "$pluginmenu add command -label \"Add Plugin\" -command { $this AddSinglePlugin \"\" }"
+    $pluginmenu add separator
+
+    foreach tool $pluginslist {
+	set alg [ $this AddSinglePlugin $tool ]
+	if { $alg ==0 } {
+	    puts stderr "Bad plugin $tool"
+	}
+    }
+}
+
+# -------------------------------------------------------------------------------------------------------------
+itcl::body bis_treeapp::AddSinglePlugin { tool } { 
+
+    if { [ string length $tool ] < 2 } {
+	set typelist { {"Plugin Executable Files" { *}}}
+	set fname  [tk_getOpenFile -title "Find Plugin" -filetypes $typelist ]
+	if { [ string length $fname ] < 1 } {
+	    return 0
+	}
+	set tool $fname
+    }
+	
+
+    set tmpname [ file join /tmp [pid].xml ]
+    set a ""
+    puts stderr "Fishing for $tool"
+    catch { set a [ exec $tool --xml  ] }
+    puts stderr "a=$a"
+    if { [ string length $a ] < 30 } {
+	return 0
+    }
+	
+    set fout [ open  $tmpname w ]
+    puts $fout $a
+    close $fout
+
+    set alg [ [ bis_xmlalgorithm \#auto $tmpname ] GetThisPointer ]
+    $alg SetOptionValue cmd $tool
+    file delete -force $tmpname
+    
+    $alg InitializeFromContainer 0 $treewidget
+    $alg SetBisViewer $bis_viewer
+    $alg SetDataTree $treewidget
+    $alg SetCategory $pluginname
+    set componentcat($alg) $pluginname
+    lappend categorytoolarray($pluginname) $alg
+
+    set n [ $alg GetGUIName ]
+    set v "$pluginmenu add command -label \"$n\" -command { $this ShowTool $alg  } "
+    eval $v
+
+    lappend toollist $alg
+
+    return $alg
+}
+# -------------------------------------------------------------------------------------------------------------
+
+itcl::body bis_treeapp::UpdateToolChoiceMenu { } {
+
+    $toolchoicemenu delete 0 end
+    set categ [ $categorychoicemenu get ]
+    
+    foreach alg $categorytoolarray($categ) {
+	$toolchoicemenu insert end [ $alg GetGUIName ]
+    }
+}
+
+# --------------------------------------------------------------------------------------------------------------
+
+itcl::body bis_treeapp::ShowTool { tool } {
+
+#    puts stderr "Tool is $tool"
+    if { $tool == 0 } {
+	set toolname [ $toolchoicemenu get ]
+	#	puts stderr "$tool is really name of tool $toolname"
+	set tool 0
+	foreach t $toollist {
+	    if { [ $t GetGUIName ] == "$toolname" } {
+		set tool $t
+	    }
+	}
+#	puts stderr "Found tool $tool"
+	if { $tool == 0 } {
+	    return 0
+	}
+    } else {
+	
+	set categ  [ $tool GetCategory]
+#	puts stderr "Category of tool $tool = $categ"
+	if { $categ == "" } {
+	    set categ "Other"
+	} elseif { $categ == "Plugin" } {
+	    set categ "Slicer Plugin"
+	}
+#	puts stderr "Looking for $categ"
+	set c [ $categorychoicemenu index $categ ]
+#	puts stderr "categ=$categ,c"
+	catch { $categorychoicemenu select $c }
+	$this UpdateToolChoiceMenu
+	set d [ $toolchoicemenu index [ $tool GetGUIName ] ]
+#	puts stderr "tool=[ $tool GetGUIName] , $d"
+	catch { $toolchoicemenu select $d }
+    }
+
+    set ind [ lsearch -exact $initializedtools $tool ]
+    if { $ind == -1 } {
+	set tp [ frame $toolbase.[pxvtable::vnewobj ]]
+	$tool CreateGUI $tp
+	lappend initializedtools $tool
+	set toolwidgetarray($tool) $tp
+    }
+    
+    catch { wm deiconify $toolbase }
+    
+    if { $currenttoolwidget ==  $toolwidgetarray($tool) } {
+	return 1
+    }
+
+    if { $currenttoolwidget != 0 } {
+	pack forget $currenttoolwidget
+    }
+    # Unload stuff in currenttool -- maybe
+    if { $currenttool != 0 } {
+	$currenttool ClearOutputs
+    }
+    #
+    pack $toolwidgetarray($tool) -side top -expand true -fill both
+    set currenttoolwidget $toolwidgetarray($tool)
+    set currenttool $tool
+    $currenttool SetBisViewer $bis_viewer
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_treeapp::SetCurrentViewer { vr } {
+
+    set bis_viewer [ lindex $viewerlist $vr ]
+    set vtk_viewer [ $bis_viewer GetViewer ]
+    $treewidget SetBisViewer $bis_viewer
+    if { $currenttool !=0 } {
+	$currenttool SetBisViewer $bis_viewer
+    }
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body bis_treeapp::GrabImageFromViewer { vr } {
+
+    set v [ lindex $viewerlist $vr ]
+    set img [ $v GetImage ]
+    #    puts stderr "img=[ $img GetShortDescription ]"
+
+    set elem [ $treewidget AddNewNode Image ]
+    if { $elem == "" || $elem == "0" } {
+	puts stdout "Failed to add element $elem"
+	return 0
+    }
+
+    set datamanager [ $treewidget GetDataManager ]
+    [ $elem GetAttribute PointerObject ] ShallowCopy $img
+    $elem SetAttribute Filename [ $img cget -filename ]
+    $elem SetAttribute Title [ file tail [ file rootname [ $img cget -filename ]] ]
+    $elem SetAttribute ObjectLoaded 1
+    $datamanager UpdateAttributesByList $elem { "ObjectLoaded" Filename Title }
+    $treewidget  UpdateVisTree  [ $elem GetParent ]
+    $treewidget  UpdateStatus 
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+# CreateGUI
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_treeapp::CreateGUI { basew { callafter 0 } { callbefore 0 } } {
+
+    set basewidget $basew
+    wm geometry $basewidget 930x900
+    set callbackbefore $callbefore
+    set callbackafter  $callafter
+    set progressbar($this) 0
+    set progress_lab($this) "Status"
+    set progress_val($this) 0
+    set guimode "standalone"
+    
+    set tp $basewidget
+    #    set tp [ toplevel $basewidget ];  wm withdraw $tp
+    set menubase [ menu $tp.menubar -tearoff 0  ]
+    $tp configure -menu $menubase
+    set toolbar [ frame $tp.[ pxvtable::vnewobj ] ]
+    set toolbar2 [ frame $tp.[ pxvtable::vnewobj ] -height 2 -bg black]
+    pack $toolbar $toolbar2 -side top -expand false -fill x
+
+    set nt [ panedwindow $basew.1 -orient horizontal -showhandle 1 \
+		 -borderwidth 4 -relief raised -sashwidth 4 -sashpad 4 \
+		 -handlesize 5 -handlepad 50  ]
+    pack $nt -side top -expand true -fill both 
+
+    set guibase  [ frame $nt.c  -width   500 ]
+    set toolbase  [ frame $nt.v -width   400 ]
+    $nt add $guibase -minsize  300
+    $nt add $toolbase -minsize 300
+
+    set numv 2
+    for { set i 1 } { $i<= $numv } { incr i } {
+	set viewbase($i)  [ toplevel $nt.c$i ]
+	wm withdraw $viewbase($i)
+	wm title $viewbase($i) "Viewer $i"
+	wm geometry $viewbase($i) 700x700
+
+	set bv [ [ bis_viewer \#auto ] GetThisPointer ]
+	$bv configure -enable_toolbar  1
+	$bv configure -enable_landmarkeditor  1
+	$bv configure -enable_electrodeeditor  1
+	$bv CreateGUI $viewbase($i)
+	lappend viewerlist  $bv 
+    }
+    # Link Viewers
+    for { set i 0 } { $i <= 1 } { incr i } {
+	for { set j 0 } { $j <= 1 } { incr j } {
+	    if { $i != $j } {
+		[ lindex $viewerlist $i ]   SetLinkedCursorViewer  [ lindex $viewerlist $j ]
+	    }
+	}
+    }
+
+    set bis_viewer [ lindex $viewerlist 0 ]
+    set vtk_viewer [ $bis_viewer GetViewer ]
+
+    set treewidget [ [ bis_treewidget \#auto ] GetThisPointer ]
+    $treewidget SetBisViewer $bis_viewer
+    $treewidget configure -createtransformcontrol 1
+    $treewidget CreateGUI $guibase 1  0 1
+
+    set pref_dialog [ ::pxtcluserprefs::CreatePreferenceEditor ]
+
+    $this CreateMenu $menubase $viewerlist 
+    label $toolbar.0 -text "Current Viewer:"; pack $toolbar.0 -side left -padx 3 -expand false
+    for { set i 1 } { $i <= [ llength $viewerlist ] } { incr i } {
+	eval "$viewmenu add command -label \"Show Viewer $i\" -command { wm deiconify $viewbase($i)}"
+	eval "radiobutton $toolbar.$i -variable  [ itcl::scope thisparam($this,currentviewer) ]  -value [ expr $i -1 ] -text \"Viewer $i\" -command { $this SetCurrentViewer [ expr $i -1 ] } "
+	pack $toolbar.$i -side left -padx 2 -expand false
+    }
+
+    $viewmenu add separator
+    for { set i 1 } { $i <= [ llength $viewerlist ] } { incr i } {
+        eval "$viewmenu add command  -label \"Grab Image From Viewer $i\" -command { $this GrabImageFromViewer [ expr $i -1 ] } "
+    }
+
+
+
+    update
+    $this AddComponents 
+    $this UpdateToolChoiceMenu
+    $this AddPlugins
+    $this UpdateToolChoiceMenu
+
+    if { [ string length [ $OptionsArray(treefile) GetValue  ] ] > 0  } {
+	$this LoadTree [ $OptionsArray(treefile) GetValue  ]
+    }
+
+
+    
+    eval "bind all <Control-d>  { $this ExitCommand }"
+    eval "wm protocol . WM_DELETE_WINDOW { $this ExitCommand } "
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { $this ExitCommand  }"
+
+
+    $this ShowTool 0
+
+}
+
+
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_treeapp.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_treeapp [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_treewidget.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_treewidget.tcl
new file mode 100644
index 0000000..b1ea8a1
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_treewidget.tcl
@@ -0,0 +1,1684 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+# Add Surface Display now!
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    lappend auto_path [ file dirname [ info script ]]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] bis_algorithm ]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] main]
+}
+package require  vtkpxcontrib 1.1
+package require  pxtclutil    1.0
+package require  pxvtable     1.0
+package require  pxtclhelp    1.0
+package require  Itcl         3.2
+package require VisTree 3.0
+package require  Iwidgets     4.0
+package require bis_datamanager 1.0
+package require bis_resliceimage 1.0
+package require bis_optiondialog 1.0
+package require pxtclutil
+package require bis_createoverlayimage 1.0
+package provide bis_treewidget 1.0
+package require bis_viewer 1.0
+package require bis_algorithm 1.0
+# --------------------------------------------------------------------------
+#
+#  Todo --- add node
+#       --- edit node properties
+#       --- display in ref space
+#      
+#   File:   New/Load/Save/Save Reorganized Copy/Anonymize/Validate (all objects exist)/Exit
+#   Edit:   Undo/Delete/Cut/Copy/Paste/Paste Structure/enable drag and drop/Properties
+#   Insert: Image/Surface/Landmarks/Electrodes/Folder/Subject/Tree
+#      
+# start here ..........
+# Right Click Menu: Set Filenames (Object/Xform1/Xform2), Insert Child, Edit Properties
+#              edit node properties dialog (eventually)
+#
+#
+#  to create a new element
+#   set datamanager [ $xmltree GetDataManager ]
+#      create this parentnode
+#   set ref [ eval "$datamanager CreateChildElement $parentnode Image MNI_Image { Filename $f2 } " ]
+#
+#   $xmltree UpdateVisTree $parentnode
+#
+# --------------------------------------------------------------------------
+
+
+itcl::class bis_treewidget {
+
+    inherit bis_algorithm
+
+    constructor { } { $this Initialize }
+
+    public method GetThisPointer { } { return $this }
+    protected method Initialize { }
+    # Cleaned up
+    public method UpdateVisTree  { {  rdnode 0 } args } 
+    public method UpdateExpandedFlag {  {  rdnode 0 } }
+    public method UpdateAll { }
+
+    # Not cleaned up
+    public method CreateGUI { base { overlaymode 0 } { readonly 0 }  { hasfilemenu 0 } }
+    public method CreateUglyGUI { base }
+
+    # Shortest path along tree
+    public method SetReferenceSpace { { nd 0 } }
+
+
+    # Mouse Bindings
+    public method SetSelection { W x y }
+    public method GetCurrentXMLElement { }
+    public method GetCurrentObject { }
+    public method GetCurrentObjectFilename { }
+
+    public method UpdateStatus {  }
+    public method PrintCurrentNode { }
+    public method LockEditing { }
+    public method LockSpace { } 
+    public method DisplayObject { img }
+    public method DisplayCurrentNode { { space ref } }
+    public method EditCurrentSurface { } 
+    public method UpdateEditedSurface { elem obj } 
+    public method DisplayNodeInReferenceSpace { elem }
+    public method ResliceNodeInReferenceSpace { elem }
+    
+
+
+    # ----------------------------
+    public method ClipboardOperation { operation }
+
+
+    # Overlay Tool Stuff
+    # -----------------------------------
+    public method CreateOverlayTool { base }
+    public method UpdateOverlayTool { mode }
+    public method ShowOverlayTool {  }
+
+    # Viewer Stuff
+    # --------------------------------------------
+    #    public method SetViewerList { lst } { set viewerlist $lst; $this SetBisViewer [ lindex $lst 0 ] }
+    #    public method SetCurrentViewer { args }
+
+
+    # Context Menus ..............
+    #$mdmenubar add cascade -label $m -menu $mdmenubar.m$m -background $menucolor 
+
+    protected method AddContextMenuEntry { mb label  command {  ronlyflag 0 } { spaceflag 0 } }
+    protected method AddToolbarEntry { mb text balloonstring { command 0 } {  ronlyflag 0 } { spaceflag 0 } }
+
+    protected method CreateContextMenus { }
+    protected method CreateContextToolbars { w }
+
+    
+    public method ShowContextMenu { W x y }   
+    public method ShowContextToolbar {  }
+    public method SetNodeFilename { md }  
+    public method SaveNode { md }  
+    public method EditNodeProperties { args } 
+    public method UpdateNodeProperties { args } 
+    public method ToggleNodeProperty { property } 
+    public method AddNewNode { ndtype } 
+
+
+    # Load & Save
+    public method LoadDataTree { { fname "" } }
+    public method SaveDataTree { { fname "" } }
+
+    # GetDatamanager
+    public method GetDataManager { } { return $datamanager }
+
+    # Transformation Stuff
+    public method GetTransformation   { } 
+    public method SetTransformation   { newtr args } 
+    public method AddTransformation { tr { name "" }  }
+    public method UpdateTransformation   { } 
+    public method SetBisViewer { vr } {
+	::bis_algorithm::SetBisViewer $vr
+	if { $overlaytool !=0 } {
+	    $overlaytool SetBisViewer $vr
+	}
+    }
+    
+    # --------------------------------------------------
+
+
+
+    # Variables
+    # This is the manager
+    protected variable datamanager 0
+    # this is the root node
+    protected variable rootnode 0
+
+    # This is the tree!
+    protected variable vistree 0
+    
+    # Parameters for other stuff
+    protected common guiparams
+
+    # Context Menus
+    protected variable contextmenu
+    protected variable contextbar
+    protected variable currentcontextbar 0
+    protected variable optionsdialog 0
+    protected variable forcereadonlymode 0
+    protected variable readonlybuttonlist ""
+    protected variable readonlymenulist ""
+    protected variable setspacebuttonlist ""
+    protected variable setspacemenulist ""
+
+    # Overlay Tool Stuff
+    protected variable overlaytool 0
+    protected variable reslicealg  0
+    protected variable overlaytooldlg 0
+    protected variable hasfilemenu 0
+    protected variable viewerlist ""
+    protected variable transformation_control 0
+    protected variable owns_current_transformation 0
+    protected variable current_transformation 0 
+    public variable createtransformcontrol 0
+}
+
+# -----------------------------------------------------------------------
+itcl::body bis_treewidget::Initialize { } {
+
+    set guiparams($this,helpVar) ""
+    set guiparams($this,status) ""
+    set guiparams($this,ref_space) ""
+    set guiparams($this,clipboard) ""
+    set guiparams($this,clipboardelement) 0
+    set guiparams($this,interpmode) 0
+    set guiparams($this,viewerindex) 0
+    set guiparams($this,undoelement) 0
+    set guiparams($this,undoelementparent) 0
+    set guiparams($this,treefilename) ""
+    set guiparams($this,displayonlymode) 1
+    set guiparams($this,lockspaceimage) 1
+    
+
+    set current_transformation [ [ pxitcltransform \#auto ] GetThisPointer ]
+    set  owns_current_transformation 1
+
+    set datamanager [ [ bis_datamanager \#auto ] GetThisPointer ]
+    set rootnode [ $datamanager GetRootNode ]
+
+    set p1 [ file dirname [ info script ]]
+    set p2 [ file normalize [ file join $p1 [ file join ".." images ] ] ]
+    set f2 "[ file join $p2 MNI_T1_1mm_stripped.nii.gz ]" 
+
+    set ref [ eval "$datamanager CreateChildElement $rootnode Image MNI_Image { Filename $f2 } " ]
+
+    set optionsdialog [ bis_optiondialog \#auto ]
+    $optionsdialog InitializeAsXMLDataElement $datamanager
+    $optionsdialog SetCallback "$this UpdateNodeProperties"
+
+    set guiparams($this,ref_space) [ $ref GetName ]
+    $this AddDefaultOptions
+}
+
+# ------------------------------------------------------------------------------------
+# Transformation Interface
+# ------------------------------------------------------------------------------------
+
+::itcl::body bis_treewidget::GetTransformation   { }  {
+
+    $this UpdateTransformation
+    return $current_transformation 
+}
+
+
+itcl::body bis_treewidget::AddTransformation { tr { name "" } } {
+
+    if { $transformation_control == 0 } { return 0 } 
+    set ind [ $transformation_control GetNextObjectIndex ]
+    if { $name == "" } {
+	$transformation_control AddInternalObject 
+    } else {
+	$transformation_control AddObject  "$name.$ind"
+    }
+    set basetr [ $transformation_control GetCurrentObject ]
+
+    set vtkmode 1
+    catch { 
+	if { [ $tr isa pxitcltransform ] == 1 } {
+	    set vtkmode 0
+	}
+    }
+    
+    if { $vtkmode == 0 } {
+	$basetr Copy $tr
+    } else {
+	$basetr CopyTransformation $tr
+    }
+    $transformation_control CurrentObjectModified
+    return $ind
+}
+# -----------------------------------------------------------------------
+itcl::body bis_treewidget::SetTransformation { newtr args } {
+
+    if { $transformation_control == 0 } { return 0 } 
+    set mode "modify"
+    if { [ llength $args ] > 0 } {
+	set mode [ lindex $args 0 ]
+    }
+    
+    if { $mode == "add" } {
+	$transformation_control AddInternalObject 
+    }
+
+    set basetr [ $transformation_control GetCurrentObject ]
+    $basetr CopyTransformation $newtr
+    $transformation_control CurrentObjectModified
+    update idletasks
+}
+
+# -------------------------------------------------------------------
+::itcl::body bis_treewidget::UpdateTransformation   { }  {
+    
+    if { $transformation_control == 0 } { return 0 } 
+
+    if {  $owns_current_transformation == 1 } {
+	itcl::delete object $current_transformation
+	set owns_current_transformation 0
+    }
+    set current_transformation [ $transformation_control GetObject -1 ]
+    
+}
+
+# --------------------------------------------------------------------------
+#::itcl::body bis_treewidget::SetCurrentViewer { args } {
+#    #    puts stderr "args=$args"
+#    set vname [ lindex $args 1 ]
+#    set number [ expr [ string range [ file extension $vname ] 1 end ] -1 ]
+#    #puts stderr "Index=$number"
+#    $this SetBisViewer [ lindex $viewerlist $number ]
+#    puts stderr "Tree viewer = $bis_viewer "
+#}
+# --------------------------------------------------------------------------
+::itcl::body bis_treewidget::UpdateExpandedFlag { { rdnode 0 } } {
+
+    if { $rdnode ==0 }  {
+	set rdnode $rootnode
+    }
+    set pathname  [ $rdnode GetAttribute VisTreePath ]
+    set v $::Tree::Tree($vistree:$pathname:open)  
+    $rdnode SetAttribute Expanded $v
+    set num 0
+    catch { set num [ $rdnode GetNumberOfNestedElements ] }
+    if { $num > 0 } {
+	for { set j 0 } { $j < $num } { incr j } {
+	    $this UpdateExpandedFlag  [ $rdnode GetNestedElement $j ]
+	}
+    }
+}
+# --------------------------------------------------------------------------
+::itcl::body bis_treewidget::UpdateVisTree { { rdnode 0 } args } {
+    
+    if { $rdnode !=0 }  {
+	set nodename [ $rdnode GetName ] 
+	if { [ llength $args ] == 0 } {
+	    set pathname  [ file rootname  [ $rdnode GetAttribute VisTreePath ] ]
+	} else {
+	    set basename [ lindex $args 0 ]
+	    set pathname [ file join $basename $nodename ]
+	}
+	set dirname [ file dirname $pathname ]
+    } else {
+	set rdnode $rootnode
+	set nodename [ $rdnode GetName ]
+	set pathname "/Data"
+	set dirname "/Data"
+    }
+
+    
+    #Delete the node in the vis tree (which deletes all children)
+    ::Tree::delitem $vistree $pathname 
+
+    
+    # Add new one based on tree
+    #    puts stderr "Updating attributes [ $rdnode GetName ]"
+    $datamanager UpdateDisplayAttributes $rdnode
+    set linecolor goldenrod2
+    set x [ $rdnode GetAttribute Linecolor ]
+    switch -exact -- $x {
+	0 { set linecolor red}
+	1 { set linecolor purple}
+	2 { set linecolor green}
+	green { set linecolor green }
+	purple { set linecolor purple }
+	red { set linecolor red }
+    }
+    
+    set icname [ $rdnode GetAttribute Icon ]
+
+    if { [ string length $icname ] > 1 } {
+	Tree::newitem $vistree $pathname -image $icname -linecolor $linecolor 
+    } else {
+	Tree::newitem $vistree $pathname  -linecolor $linecolor 
+    }
+
+    $rdnode SetAttribute VisTreePath $pathname
+
+    #--------------------------------------------------------------------------------
+    # Now deal with the children in the same way
+    #--------------------------------------------------------------------------------
+    set num 0
+    catch { set num [ $rdnode GetNumberOfNestedElements ] }
+
+    if { $num > 0 } {
+
+	for { set j 0 } { $j < $num } { incr j } {
+	    set elem [ $rdnode GetNestedElement $j ]
+	    $this UpdateVisTree $elem $pathname
+	}
+    }
+
+    Tree::open $vistree $pathname
+    if { [ $rdnode GetAttribute Expanded ] != 1 && $dirname!= "/Data" } {
+	Tree::close $vistree $pathname
+    } 
+
+    set guiparams($this,status) ""
+    set guiparams($this,clipboard) ""
+    set guiparams($this,clipboardelement) 0
+
+    
+};#End updateVisTree method
+
+
+
+#----------------------------------------------------------------------
+#These methods set the functions for the mouse bindings in the tree
+#----------------------------------------------------------------------
+::itcl::body bis_treewidget::SetSelection { W x y } {
+    set lbl [Tree::labelat $W $x $y ]
+    if { $lbl == "" } { 
+	return 
+    }
+    Tree::setselection $W $lbl
+    if { $lbl == "/Data" } { 
+	return 
+    }
+    set nodeID [ file tail $lbl ]
+    $this UpdateStatus
+    $this ShowContextToolbar 
+} 
+
+# ---------------------------------------------------------------------
+itcl::body bis_treewidget::GetCurrentObject { } {
+    set p [ $this GetCurrentXMLElement ] 
+    if { $p ==0 } {
+	return
+    }
+    
+    return [ $p GetAttribute PointerObject ]
+}
+# ---------------------------------------------------------------------
+itcl::body bis_treewidget::GetCurrentObjectFilename { } {
+    set p [ $this GetCurrentXMLElement ] 
+    if { $p ==0 } {
+	return
+    }
+    return [ $p GetAttribute Filename ]
+}
+# ---------------------------------------------------------------------
+itcl::body bis_treewidget::GetCurrentXMLElement { } {
+
+    set nodepath [Tree::getselectionpath $vistree ]
+    set p [ file tail $nodepath ]
+    set elem [ $datamanager FindNode $p ]
+
+    if { $elem ==0  } {
+	return 0
+    }
+    return $elem
+}
+# ---------------------------------------------------------------------
+::itcl::body bis_treewidget::UpdateStatus {} {   
+
+    set p [ $this GetCurrentXMLElement ] 
+    if { $p ==0 } {
+	return
+    }
+	
+    set fn [ file tail [ $p GetAttribute Filename ]]
+    if { $fn == 0 } {
+	set fn ""
+    } else {
+	set fn ":${fn}"
+    }
+    set guiparams($this,status) "[ $p GetName ]([ string toupper [ $p GetAttribute Type ]])$fn"
+    
+    if { $overlaytool !=0 } {
+	#	$this UpdateOverlayTool func
+    }
+}
+
+itcl::body bis_treewidget::LockEditing { } {
+
+    if { $forcereadonlymode ==  1 } {
+	set guiparams($this,displayonlymode) 1
+    }
+
+    set state normal
+    if { $guiparams($this,displayonlymode) == 1 } {
+	set state disabled 
+    }
+    
+    foreach pair $readonlybuttonlist {
+	set mb [ lindex $pair 0 ]
+	set en [ lindex $pair 1 ]
+	$mb itemconfigure $en -state $state
+    }
+
+    foreach pair $readonlymenulist {
+	set mb [ lindex $pair 0 ]
+	set en [ lindex $pair 1 ]
+	$mb entryconfigure $en -state $state
+    }
+
+}
+# -----------------------------------------------
+itcl::body bis_treewidget::LockSpace { } {
+
+    set state normal
+    if { $guiparams($this,lockspaceimage) == 1 } {
+	set state disabled 
+    }
+    
+    foreach pair $setspacebuttonlist {
+	set mb [ lindex $pair 0 ]
+	set en [ lindex $pair 1 ]
+	$mb itemconfigure $en -state $state
+    }
+
+    foreach pair $setspacemenulist {
+	set mb [ lindex $pair 0 ]
+	set en [ lindex $pair 1 ]
+	$mb entryconfigure $en -state $state
+    }
+
+}
+
+
+
+itcl::body bis_treewidget::PrintCurrentNode { } {
+
+    set elem [ $this GetCurrentXMLElement ] 
+    if { $elem == 0 || $elem == "" } {
+	puts stdout "no node selected\n"
+	return 
+    }
+    set lst [ list PointerObject PointerTransformation PointerInverseTransformation ]
+#    pxtkconsole
+    pxtkprint "\n ----------------------------------------------------------------\n"
+    pxtkprint "Reporting on node [ $elem GetName ]\n"
+    for { set i 0 } { $i < [ $elem GetNumberOfAttributes ] } { incr i } {
+	set desc ""
+	set nm  [ $elem GetAttributeName $i ]
+	set ind [ lsearch -exact $lst $nm ]
+	if { $ind >= 0 } {
+	    set obj [ $elem GetAttribute $nm ]
+	    if { $obj !=0 && $obj != "" } {
+		set desc [ $obj GetShortDescription ]
+	    }
+	}
+	pxtkprint "\t\t [ $elem GetAttributeName $i ]=[ $elem GetAttributeValue $i] $desc\n"
+    }
+
+    pxtkprint "\t ********* Objects\t\n"
+    set ptrs  [ $datamanager GetAttributePointersList ]
+    for { set i 0 } {$i < [ llength $ptrs ] } {incr i } {
+	set obj [ $elem GetAttribute [ lindex $ptrs $i ] ]
+	if { $obj > 0 } {
+	    pxtkprint "\n ********* [ lindex $ptrs $i ] = [ $obj GetDescription ]\n"
+	} else {
+	    pxtkprint "\n ********* [ lindex $ptrs $i ] = NULL\n"
+	}
+    }
+	
+
+    pxtkprint " ----------------------------------------------------------------\n"
+}
+# ----------------------------------------------------------------------
+itcl::body bis_treewidget::LoadDataTree { { fname "" } } {
+
+    if { [ string length $fname ] == 0 } {
+	set typelist { {"XMLTree Files" { .xmltree  .tre .msb}}}
+	set fname  [tk_getOpenFile -title "Load Tree" -filetypes $typelist ]   
+    }
+    
+    if { [ string length $fname ] <1 } {
+	return 0
+    }
+
+    set ext [ file extension $fname ]
+    if { $ext == ".tre" } {
+	set ok [ $datamanager ImportTree $fname ]
+    } elseif { $ext == ".msb" }  {
+	set ok [ $datamanager ImportMSBFile $fname ]
+    } else {
+	set ok [ $datamanager LoadXML $fname ]
+    }
+
+    if { $ok == 0 } {
+	pxtclutil::Error "Failed to load tree from $fname"
+	return 0
+    }
+    if { [ file extension $fname  ] != ".xmltree" } {
+	set fname "[ file rootname $fname].xmltree"
+    }
+
+    set guiparams($this,treefilename) $fname
+
+    $this UpdateAll 
+    return $fname
+}
+
+# -----------------------------------------------------------------------
+itcl::body bis_treewidget::UpdateAll { } {
+
+    $this UpdateVisTree
+    set guiparams($this,undoelementparent) 0
+
+    set guiparams($this,lockspaceimage) 0
+    $this SetReferenceSpace [ $datamanager FindFirstNodeByAttribute Type Image ]
+
+    set guiparams($this,displayonlymode) 1
+    set guiparams($this,lockspaceimage) 0
+    $this LockEditing
+    $this LockSpace
+    return 1
+}
+
+#--------------------------------------------------------------------------
+
+itcl::body bis_treewidget::SaveDataTree { { fname "" } } {
+
+    if { [ string length $fname ] == 0 } {
+	set typelist { {"XMLTree Files" { .xmltree }}}
+	lappend typelist {"Old Style Files" {.tre }}
+	set fname  [tk_getSaveFile -title "Load Tree" -filetypes $typelist -initialdir [ file dirname $guiparams($this,treefilename) ] -initialfile [ file tail $guiparams($this,treefilename) ] ]
+    }
+
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+    $this UpdateExpandedFlag
+
+    set ok [ $datamanager SaveXML $fname ]
+        if { $ok == 0 } {
+	pxtclutil::Error "Failed to save tree in $fname"
+	return 0
+    }
+
+    set guiparams($this,treefilename) $fname
+    return $fname
+}
+# ----------------------------------------------------------------------
+itcl::body bis_treewidget::ClipboardOperation { operation } {
+
+    if { $guiparams($this,displayonlymode) == 1 } { return }
+
+    if { $operation != "undo" } {
+	set elem [ $this GetCurrentXMLElement ] 
+	if { $elem ==0 } {
+	    return 0
+	}
+	
+	
+	if { $operation == "cut" || $operation == "delete" } {
+	    if { $elem == $rootnode } {
+		puts stderr "Can't move rootnode"
+		return 0
+	    }
+	}
+    }
+
+    if { $operation == "cut" } {
+	set guiparams($this,clipboard) [ $elem GetAttribute VisTreePath ]
+	set guiparams($this,clipboardelement) $elem	
+	puts stdout "Reporting on clipboard node [ $elem GetName ]"
+	for { set i 0 } { $i < [ $elem GetNumberOfAttributes ] } { incr i } {
+	    puts stdout "\t\t [ $elem GetAttributeName $i ]=\"[ $elem GetAttributeValue $i]\"" 
+	}
+
+	return 1
+    }
+
+    if { $operation == "paste" } {
+	if { $guiparams($this,clipboardelement) == 0 } {
+	    puts stderr "Nothing to paste\n"
+	    return 0
+	}
+
+	set clipelem $guiparams($this,clipboardelement)
+	if { $elem == $clipelem } {
+	    puts stderr "Paste to itself makes no sense"
+	    return 0
+	}
+
+	set ok [ $datamanager MoveElement $clipelem $elem ]
+	if { $ok == 1 } {
+	    $elem SetAttribute Expanded  1
+	    $this UpdateVisTree
+	}
+	return 1
+    }
+
+    if { $operation == "delete" } {
+	
+	if { $guiparams($this,undoelement)  != 0 } {
+	    $datamanager RecursiveDeleteChildren $guiparams($this,undoelement)
+	}
+	set guiparams($this,undoelement) $elem
+	set guiparams($this,undoelementparent) [ $elem GetParent ]
+	$elem Register $rootnode
+	puts stderr "Detatching $elem"
+	[ $elem GetParent ] RemoveNestedElement $elem
+	puts stderr "Detached $elem, [ $elem GetName ]"
+
+	$this UpdateVisTree
+	return 1
+    }
+
+    if { $operation == "undo" } {
+
+	puts stderr "in Undo"
+	if { $guiparams($this,undoelement)  == 0 || $guiparams($this,undoelementparent) == 0 } {
+	    puts stderr "0 undoelement or parent"
+	    return 0
+	}
+
+	set nm [ $guiparams($this,undoelementparent) GetName ]
+	set par [ $datamanager FindNode $nm ]
+	if { $par != $guiparams($this,undoelementparent) } {
+	    puts stderr "Bad parent $par"
+	    return 0
+	}
+
+	set elem $guiparams($this,undoelement)
+	$par AddNestedElement $elem
+	$par SetAttribute Expanded  1
+	$elem Register $rootnode
+	puts stderr "Re-attached $elem, [ $elem GetName ]"
+
+	set guiparams($this,undoelement) 0
+	set guiparams($this,undoelementparent) 0
+	$this UpdateVisTree
+	return 1
+    }
+
+}
+# ----------------------------------------------------------------------
+
+itcl::body bis_treewidget::SetReferenceSpace { { nd 0 } } {
+
+    if { $guiparams($this,lockspaceimage) == 1 } {
+	return 0
+    }
+
+    if { $nd == 0 } {
+	set elem [ $this GetCurrentXMLElement ]
+    } else {
+	set elem $nd
+    }
+	
+    if { $elem ==0 } {
+	return 0
+    }
+
+    if { [ $elem GetAttribute Type ] != "Image" } {
+	return 0
+    }
+
+    set currentselection [ $elem GetName ]
+    set guiparams($this,ref_space) $currentselection
+
+    if { $overlaytool !=0 } {
+	#	$this UpdateOverlayTool ref
+    }
+
+
+    return 1
+
+}
+# -----------------------------------------------------------------------
+itcl::body bis_treewidget::DisplayNodeInReferenceSpace { nd } {
+
+
+    set img [  $this ResliceNodeInReferenceSpace $nd ]
+    $this DisplayObject $img
+    itcl::delete object $img
+}
+
+# -----------------------------------------------------------------------
+itcl::body bis_treewidget::ResliceNodeInReferenceSpace { nd } {
+
+    if { $nd == 0 || $nd == "" } {
+	return 0
+    }
+
+
+    set elem(1) [ $datamanager FindNode $guiparams($this,ref_space) ]
+    set elem(2) $nd
+
+    if { $elem(1) == $elem(2) } {
+	puts stderr "Same Node"
+	return 1
+    }
+
+    if { $elem(1) == 0 || $elem(2) == 0 } {
+	puts stderr "Nodes not found\n"
+	return 0
+    }
+	
+
+    for { set i 1 } { $i <=2 } { incr i } {
+	set anc($i) [ $datamanager GetAncestors $elem($i) ]
+    }
+    
+    if { [ $nd GetAttribute Type ] != "Image" } {
+	set lst [ $datamanager GetTransformationList $elem(2) $elem(1) ]
+    } else {
+	set lst [ $datamanager GetTransformationList $elem(1) $elem(2) ]
+    }
+
+
+    if { [ lindex $lst 0 ] == "Failed" } {
+	pxtclutil::Info "Error $lst"
+	return 0
+    }
+
+#    pxtkconsole
+    pxtkprint "\nTransformation list:\n"
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	pxtkprint "[expr $i+1 ] : [ [ lindex $lst $i ] cget -filename ], [ [ lindex $lst $i ] GetShortDescription ]\n"
+    }
+
+    
+    set tr [ $datamanager GetCombinedTransformation $lst ]
+    set inputobj [ $elem(2) GetAttribute PointerObject ]
+
+    switch -exact [ $nd GetAttribute Type ] {
+	"Surface" {
+	    pxtkprint  "Transforming Surface ...\n"
+	    set tempobject [ [ pxitclsurface \#auto] GetThisPointer ]
+	    $tempobject ShallowCopy $inputobj
+	    $tempobject Transform $tr
+	}
+	"Mesh" {
+	    pxtkprint  "Cannot Transform Mesh ...\n"
+	    pxtkconsole
+	    # Needs fixing -- i.e. Transform method needs fixing
+	    set tempobject [ [ pxitclmesh \#auto] GetThisPointer ]
+	    $tempobject ShallowCopy $inputobj
+	    $tempobject Transform $tr
+	}
+	"Landmarks" {
+	    set tempobject [ [ pxitcllandmarks \#auto] GetThisPointer ]
+	    pxtkprint  "Transforming Landmarks ...\n"
+	    $tempobject Copy $inputobj
+	    $tempobject Transform $tr
+	} 
+	"Electrodes" {
+	    set tempobject [ [ pxitclelectrodemultigrid \#auto] GetThisPointer ]
+	    puts "Sending $tempobject to electrodecontrol: $electrodecontrol"
+	    pxtkprint  "Transforming Electrodes ...\n"
+	    $tempobject Copy $inputobj
+	    $tempobject Transform $tr
+	} 
+	"Image"  {
+	    pxtkprint  "Reslicing ...\n"
+	    set resl [ bis_resliceimage \#auto ]
+	    $resl InitializeFromContainer 0
+	    $resl SetInput [ $elem(1) GetAttribute PointerObject ]
+	    $resl SetSecondInput [ $elem(2) GetAttribute PointerObject ]
+	    $resl SetVTKTransformation $tr
+	    $resl SetOptionValue interp [ $guiparams($this,interpmode) GetValue ]
+	    $resl SetOptionValue background 0.0
+	    $resl Execute
+	    
+	    
+	    set tempobject  [ [ pxitclimage \#auto ] GetThisPointer ]
+	    $tempobject ShallowCopy [ $resl GetOutput ]
+	    itcl::delete object $resl 
+	}
+    }
+    $tr Delete
+
+    return $tempobject
+
+}
+# ----------------------------------------------------------------------
+itcl::body bis_treewidget::EditCurrentSurface {  } { 
+
+    if { $bis_viewer ==0 } {
+	return
+    }
+
+    set elem [ $this GetCurrentXMLElement ]
+    if { $elem == 0 || $elem == "" } {
+	puts stdout "no node selected\n"
+	return 
+    }
+	
+    $datamanager LoadObjectPointers $elem
+    set sur [ $elem GetAttribute PointerObject ]
+    $sur configure -filename "editObj"
+    $bis_viewer EditPolygonalObject $sur $this $elem
+
+}
+
+# ------------------------------------------------------------------
+itcl::body bis_treewidget::UpdateEditedSurface { xmlpointer obj }  {
+
+
+    set nm ""
+    catch { set nm [ $xmlpointer GetName ] }
+    if { $nm != "" } {
+	set newelem [ $datamanager FindNode $nm ]
+    } else {
+	set newelem -1
+    }
+
+    if { $newelem != $xmlpointer } {
+	puts stderr "Tree has changed ... can't update, save and update nm=$nm"
+	return 0
+    }
+
+    set obj2 [  $newelem GetAttribute PointerObject ] 
+    if { [ $obj2 info class ] != [ $obj info class ] } {
+	puts stderr "Class mismatch [ $obj2 info class ] != [ $obj info class ]"
+    }
+
+    puts stdout "OK proceeding newelem=$newelem, xmlpointer=$xmlpointer, obj = [ $obj info class ], obj2=[ $obj2 info class ]"
+
+    puts stderr "Old = [ $obj2 GetDescription ]"
+    $obj2 Copy $obj
+    [ $obj2 GetObject ]  Modified
+    [ $obj2 GetObject ]  Update
+    
+    puts stderr "New = [ $obj2 GetDescription ], $newelem"
+}
+
+# --------------------------------------------------------------
+
+itcl::body bis_treewidget::DisplayCurrentNode { { space ref } } {
+
+    set elem [ $this GetCurrentXMLElement ]
+    if { $elem == 0 || $elem == "" } {
+	puts stdout "no node selected\n"
+	return 
+    }
+	
+    if { [ $elem GetAttribute ObjectLoaded ] != 1 } {
+	$datamanager LoadObjectPointers $elem
+    }
+    if { $space == "ref" } {
+	return [ $this DisplayNodeInReferenceSpace $elem ]
+    }
+
+    $this DisplayObject [ $elem GetAttribute PointerObject ]
+    return
+}
+
+# ----------------------------------------------------------------------
+itcl::body bis_treewidget::DisplayObject { img } {
+
+    if { $img ==0 || $img =="" } {
+	return
+    }
+
+    if { $bis_viewer !=0 } {
+	if { [ $img isa pxitclimage  ] } {
+	    $bis_viewer SetImage $img	    
+	} else {
+	    puts stderr "displaying [ $img GetDescription ]"
+	    $bis_viewer AddOrReplacePolygonalObject $img
+	} 
+    } elseif { $vtk_viewer !=0 } {
+	$vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+	$vtk_viewer SetPresetLookupTable -1
+    } 
+}
+
+# -----------------------------------------------------------
+itcl::body bis_treewidget::AddToolbarEntry { mb txt balloonstring { command 0 } {  ronlyflag 0 } { spaceflag 0 } } {
+
+    set nm [ pxvtable::vnewobj ]
+    if { $txt == "frame" } {
+	set ln "$mb add frame \"$nm\" $balloonstring"
+	eval $ln
+	return
+    }
+	
+
+    set nm [ pxvtable::vnewobj ]
+    set ln "$mb add button \"$nm\"  -balloonstr \"$balloonstring\" -command { $command } -text $txt"
+    eval $ln
+    if { $ronlyflag > 0 } {
+    	lappend readonlybuttonlist [ list $mb $nm  ]
+    }
+    if { $spaceflag > 0 } {
+	lappend  setspacebuttonlist [ list $mb $nm ] 
+    }
+
+}
+# -----------------------------------------------------------
+itcl::body bis_treewidget::CreateContextToolbars { tc } { 
+
+    foreach m { Image Surface Folder Subject } {
+
+	set contextbar($m) [ iwidgets::toolbar $tc.[ pxvtable::vnewobj ] \
+				 -balloondelay1 100 \
+				 -balloondelay2 50 \
+				 -orient vertical \
+				 -font { helvetica 9 }\
+				 -disabledforeground \#A0A0A0 \
+				 -helpvariable guiparams($this,helpVar) ]
+
+#				 -balloonbackground darkgray  -balloonforeground white 
+#				 -background black -foreground \#ffffee 
+
+
+	set tb $contextbar($m)
+    }
+    
+    foreach m { Image Surface } {
+	$this AddToolbarEntry $contextbar($m) ".." "Set Filename" "$this SetNodeFilename 0" 1
+	$this AddToolbarEntry $contextbar($m) "Sv" "Save Object" "$this SaveNode 0" 1
+	$this AddToolbarEntry $contextbar($m) frame "-borderwidth 1 -width 7 -height 4" 
+	$this AddToolbarEntry $contextbar($m) "D" "Display" "$this DisplayCurrentNode native" 0 
+        $this AddToolbarEntry $contextbar($m) "DR" "Display in Ref Space"  "$this DisplayCurrentNode ref" 0 
+    }
+
+    foreach m { Surface } {
+        $this AddToolbarEntry $contextbar($m) "ED" "Edit Surface"  "$this EditCurrentSurface" 1
+    }
+	
+
+    $this AddToolbarEntry $contextbar(Subject)  frame "-borderwidth 1 -width 7 -height 4"
+    $this AddToolbarEntry $contextbar(Subject) "+F" "Add Folder" "$this AddNewNode Folder" 1
+
+
+    foreach m { Image Folder } {
+	$this AddToolbarEntry $contextbar($m) frame "-borderwidth 1 -width 7 -height 4"
+	if { $m == "Folder" } {
+	    $this AddToolbarEntry $contextbar(Folder) "+X" "Add Subject" "$this AddNewNode Subject" 1
+	}
+	$this AddToolbarEntry $contextbar($m)   "+F" "Add Folder" "$this AddNewNode Folder" 1
+	$this AddToolbarEntry $contextbar($m)   "+I" "Add Image" "$this AddNewNode Image" 1
+	$this AddToolbarEntry $contextbar($m)   "+S" "Add Surface " "$this AddNewNode Surface" 1
+	$this AddToolbarEntry $contextbar($m)   "+L" "Add Landmark Set" "$this AddNewNode Landmarks" 1
+	$this AddToolbarEntry $contextbar($m)   "+E" "Add Electrode Set" "$this AddNewNode Electrodes" 1
+	$this AddToolbarEntry $contextbar($m)   "+M" "Add Mesh" "$this AddNewNode Mesh" 1
+
+
+
+	if { $m == "Image" } {
+	    $this AddToolbarEntry $contextbar($m) frame "-borderwidth 1 -width 7 -height 4"
+	    $this AddToolbarEntry $contextbar($m) "Sp" "Set As Space" "$this SetReferenceSpace" 0 1
+	    $this AddToolbarEntry $contextbar($m) frame "-borderwidth 1 -width 7 -height 4" 
+	    $this AddToolbarEntry $contextbar($m) "ST" "Set Transformation" "$this SetNodeFilename 1" 1
+	    $this AddToolbarEntry $contextbar($m) "SI" "Set Inverse Transformation" "$this SetNodeFilename 2" 1
+	    $this AddToolbarEntry $contextbar($m) "Id" "(Un)set as Identity"  "$this ToggleNodeProperty IsIdentity" 1
+	    $this AddToolbarEntry $contextbar($m) "cL" "Clear Transformations" "$this ToggleNodeProperty ClearTransformations" 1
+	}
+    }
+
+
+    pack $contextbar(Folder) -side top -expand false -fill x
+    set currentcontextbar $contextbar(Folder)
+}
+# -----------------------------------------------------------
+itcl::body bis_treewidget::CreateUglyGUI { base } {
+
+    set w3 [ frame $base.bot2 ]
+    entry $w3.a -textvariable [ itcl::scope guiparams($this,status) ] -relief ridge \
+	-disabledforeground white -state disabled  -disabledbackground black
+    pack $w3.a -side top  -expand true -fill x
+
+    frame $w3.b ;     pack $w3.b -side bottom -expand false -fill x
+    pack $w3 -side top  -fill x -expand false
+
+    set opt7 [ [ bis_option \#auto ] GetThisPointer ]
+    $opt7 SetAllProperties "-interp" "Reslice Mode" "Mode" "listofvalues" Linear { "NearestNeighbor" "Linear" "Cubic" }  0 
+    $opt7 CreateGUIElement $w3.b.1
+    pack $w3.b.1 -side right 
+    set guiparams($this,interpmode) $opt7
+
+#    if { [ llength $viewerlist ] > 1 } {
+#	set vname ""
+#	for { set i 1 } { $i <= [ llength $viewerlist ] } { incr i } {
+#	    lappend vname "Viewer.$i"
+#	}
+#
+#	set opt8 [ [ bis_option \#auto ] GetThisPointer ]
+#	$opt8 SetAllProperties "-viewer" "Viewer" "Viewer" "listofvalues" "Viewer.1" $vname  0 
+#	eval "$opt8 CreateGUIElement $w3.b.11 { $this SetCurrentViewer }"
+#	pack $w3.b.11 -side right 
+#	set guiparams($this,viewerindex) $opt8
+#    }
+#
+
+
+    set sp [ frame $w3.b.2  ]
+    label $sp.1 -text "Reference Space:" 
+    entry $sp.2  -textvariable [ itcl::scope guiparams($this,ref_space) ] -relief ridge \
+	-disabledbackground black -disabledforeground white -state disabled 
+    pack $sp.1 -side left -expand false
+    pack $sp.2 -side right -expand true -fill x
+    pack $w3.b.2 -side left -expand true -fill x
+
+
+    set w [ frame $base.bot5  ]; pack $w -side top -expand true -fill x
+    if { $hasfilemenu == 0 } {
+	eval "button $w.1 -text \"Load\" -command { $this LoadDataTree } "
+	eval "button $w.2 -text \"Save\" -command { $this SaveDataTree } "
+	pack $w.1 $w.2  -side left -expand false -padx 2
+    } 
+
+    eval "button $w.3 -text \"Redraw\" -command {   $this UpdateExpandedFlag;  $this UpdateVisTree; $this UpdateStatus   } "
+    eval "button $w.4 -text \"Overlay Tool\" -command { $this ShowOverlayTool   } "
+    pack $w.3 $w.4 -side left -expand false -padx 2
+
+
+
+}
+
+# -------------------------------------------------------------------------
+itcl::body bis_treewidget::AddContextMenuEntry { mb label  command {  ronlyflag 0 } { spaceflag 0 } } {
+
+    set ln "$mb add command -label \"$label\" -command { $command }"
+    eval $ln
+    if { $ronlyflag > 0 } {
+	lappend readonlymenulist [ list $mb  [ $mb index last ] ]
+    }
+    if { $spaceflag > 0 } { 
+	lappend setspacemenulist [ list $mb  [ $mb index last ] ]
+    }
+}
+ 
+
+itcl::body bis_treewidget::CreateContextMenus { } {
+    
+    foreach m { Image Surface Folder Subject } {
+	set contextmenu($m) [menu $vistree.[ pxvtable::vnewobj ] -tearoff 0 ] 
+	set mb $contextmenu($m)
+	if { $m == "Image" || $m == "Surface" } {
+	    $this AddContextMenuEntry $mb "Set Filename (..)" "$this SetNodeFilename 0" 1
+	    $this AddContextMenuEntry $mb "Display (D)" "$this DisplayCurrentNode native" 0
+	    $this AddContextMenuEntry $mb "Display in Ref Space (DR)" "$this DisplayCurrentNode ref" 0
+	    $mb add separator
+	}
+	$this AddContextMenuEntry $mb "Edit Properties" "$this EditNodeProperties" 1
+    }
+}
+
+itcl::body bis_treewidget::ShowContextMenu { W x y } {
+
+    $this SetSelection $W $x $y
+    set nd [ $this GetCurrentXMLElement ] 
+    if { $nd == 0 } {
+	return 0
+    }
+
+    set tp [ $nd GetAttribute Type ]
+
+    if { $tp == "Surface" || $tp == "Landmarks" || $tp == "Electrodes" || $tp == "Mesh" } {
+	set tp Surface
+    } elseif { $tp != "Image" && $tp !="Subject" } {
+	set tp Folder
+    }
+
+
+    set h [ expr 300- [ winfo height $contextmenu($tp) ] ]
+    if { $h > 190 } {
+	if { $tp == "Surface" || $tp == "Image" } {
+	    set h 200
+	} else {
+	    set h 200
+	}
+    }
+    puts stderr "h=$h, tp=$tp, $x, $y"
+    tk_popup $contextmenu($tp) [ expr $x + 20 ] [ expr $y + $h ]
+}
+
+
+itcl::body bis_treewidget::ShowContextToolbar {  } {
+    set nd [ $this GetCurrentXMLElement ] 
+    if { $nd == 0 } {
+	return 0
+    }
+
+    set tp [ $nd GetAttribute Type ]
+    if { $tp == "Surface" || $tp == "Landmarks" || $tp == "Electrodes" || $tp == "Mesh" } {
+	set tp Surface
+    } elseif { $tp != "Image" && $tp !="Subject" } {
+	set tp Folder
+    }
+    regsub -all "\"" $tp "" tp
+    if { $currentcontextbar != 0 } {
+	pack forget $currentcontextbar
+    }
+    pack $contextbar($tp) -side top -expand false -fill x
+    set currentcontextbar $contextbar($tp)
+
+}
+
+
+itcl::body bis_treewidget::AddNewNode { ndtype } { 
+    if { $guiparams($this,displayonlymode) == 1 } { return 0 }
+
+    set nd [ $this GetCurrentXMLElement ] 
+    if { $nd == 0 } {
+	return 0
+    }
+
+    set elem [ $datamanager GetNewXMLDataElement $ndtype "New $ndtype" ]
+    $nd AddNestedElement $elem
+    $nd SetAttribute "Expanded" 1
+    $this UpdateVisTree $nd
+    Tree::setselection $vistree  [ $elem GetAttribute VisTreePath ]
+    $this ShowContextToolbar
+    return $elem
+}
+
+
+
+itcl::body bis_treewidget::EditNodeProperties { args }  {
+
+    if { $guiparams($this,displayonlymode) == 1 } { return 0 }
+    set p [ $this GetCurrentXMLElement ] 
+    if { $p==0 || $p == "" } {
+	return
+    }
+    
+    set w [ $optionsdialog GetBaseWidget ]
+    if { $w == 0 } {
+	set w [ $optionsdialog CreateGUI  $basewidget ]
+	wm geometry $w 700x350
+	$optionsdialog SetOptionStatus Type 0
+	$optionsdialog SetOptionStatus Icon 0
+	$optionsdialog SetOptionStatus Expanded 0
+    }
+    $optionsdialog SetOptionsFromXMLDataElement $p
+    $optionsdialog SetTitle "Editing Node [ $p GetAttribute Title ] Properties"
+
+    set tp [ $p GetAttribute Type ]
+    set dt 1
+    if { $tp != "Image" } { 
+	set dt 0 
+    }
+    $optionsdialog SetOptionStatus     TransformationFilename $dt 
+    $optionsdialog SetOptionStatus     InverseTransformationFilename $dt
+    $optionsdialog SetOptionStatus     IsIdentity $dt
+
+    
+    if { $tp == "Folder" || $tp == "Subject" } {
+	$optionsdialog SetOptionStatus Filename 0
+    } else {
+	$optionsdialog SetOptionStatus Filename 1
+    }
+
+    wm deiconify $w
+    wm focus $w
+    $optionsdialog ShowWindow
+}
+
+# --------------------------------------------------------------------------
+
+itcl::body bis_treewidget::ToggleNodeProperty { property } { 
+
+    if { $guiparams($this,displayonlymode) == 1 } { return 0 }
+    $this UpdateExpandedFlag
+    set p [ $this GetCurrentXMLElement ] 
+    if { $p == 0 } {
+	return
+    }
+    if { $property == "ClearTransformations" } {
+	set propery ""
+	set ptrs  [ $datamanager GetAttributePointersList ]
+	set fn    [ $datamanager  GetFilenamesList ]
+	for { set i 1} { $i <=2 } { incr i } {
+	    $p SetAttribute [ lindex $fn $i ] 0
+	    set obj [ $p GetAttribute [ lindex $ptrs $i ] ] 
+	    #	    puts stderr "obj=$obj"
+	    catch { $obj Clear }
+	    lappend property [ lindex $fn $i ]
+	}
+    } else {
+	set v [ $p GetAttribute $property ]
+	if { $v == 1 } {
+	    $p SetAttribute $property 0
+	} elseif { $v == 0 } {
+	    $p SetAttribute $property 1
+	}
+    }
+
+    $datamanager UpdateAttributesByList $p $property
+    $this UpdateVisTree  [ $p GetParent ]
+    $this UpdateStatus 
+    $optionsdialog SetOptionsFromXMLDataElement $p
+    
+    Tree::setselection $vistree  [ $p GetAttribute VisTreePath ]
+
+}
+
+# -----------------------------------------------------------
+
+itcl::body bis_treewidget::UpdateNodeProperties { args } {
+
+    if { $guiparams($this,displayonlymode) == 1 } { return 0 }    
+    $this UpdateExpandedFlag
+    set xml [ $optionsdialog GetXMLElement ]
+#    puts stderr "In Update Node Properties $xml"
+
+    if { $xml == 0 || $xml == "" } {
+	return 0
+    }
+
+    set name [ $xml GetName ]
+    set elem [ $datamanager FindNode $name ]
+    if { $elem == 0 || $elem =="" } {
+	return 0
+    }
+
+    if { [ llength $args ] < 2 } {
+	return
+    }
+    
+    set nm [ $elem GetName ]
+    $datamanager UpdateAttributesByList $elem [ lrange $args 1 end ]
+    set nm2 [ $elem GetName ]
+
+    if {  $nm != $nm2 &&  $guiparams($this,ref_space) == $nm } {
+	# Refspace rename!
+	#	puts stderr "Chaning ref space to $nm2"
+	set guiparams($this,ref_space) $nm2
+    }
+
+    $this UpdateVisTree [ $elem GetParent ]
+    Tree::setselection $vistree  [ $elem GetAttribute VisTreePath ]
+    $this UpdateStatus 
+    
+}
+# ---------------------------------------------------------------------------
+
+itcl::body bis_treewidget::SetNodeFilename { args }  {
+    
+    if { $guiparams($this,displayonlymode) == 1 } { return 0 }
+
+    set p [ $this GetCurrentXMLElement ] 
+    if { $p ==0 || $p == "" } {
+	return 0
+    }
+
+    set dt [ $p GetAttribute Type ]
+    if { $dt == "Folder" || $dt == "Patient" } {
+	return 0
+    }
+
+    if { $dt == "Image" } {
+        set l [ lindex $args 0 ]
+	if { $l !=1 && $l !=2 } {
+	    set l 0
+	}
+    } else {
+	set l 0
+    }
+
+    set ptrs  [ $datamanager GetAttributePointersList ]
+    set fn    [ $datamanager  GetFilenamesList ]
+    set obj   [ $p GetAttribute [ lindex $ptrs $l ] ]
+    set fname [ $p GetAttribute [ lindex $fn $l ] ]
+    if { $fname == 0 || $fname == -1 } {
+	set fname ""
+    }
+
+    set fold [ $obj cget -filename ]
+    $obj configure -filename $fname
+    set ok [ $obj Browse "[$p GetName ]:  [ lindex $fn $l ]" ]
+    if { $ok > 0 } {
+	set fname [ $obj cget -filename ]
+	#	puts stderr "Updating $fname=$fold"
+	if { $fname != $fold } {
+	    $obj Clear
+	}
+	#	puts stderr "Setting [ lindex $fn $l ]= $fname "
+	$p SetAttribute [ lindex $fn $l ] $fname 
+	$this UpdateVisTree $p
+	$this  UpdateStatus 
+	$optionsdialog SetOptionsFromXMLDataElement $p
+	Tree::setselection $vistree  [ $p GetAttribute VisTreePath ]
+    }
+}
+# ---------------------------------------------------------------------------------------------------------------------  
+itcl::body bis_treewidget::SaveNode { args }  {
+    
+    if { $guiparams($this,displayonlymode) == 1 } { return 0 }
+
+    set p [ $this GetCurrentXMLElement ] 
+    if { $p ==0 || $p == "" } {
+	return 0
+    }
+
+    set dt [ $p GetAttribute Type ]
+    if { $dt == "Folder" || $dt == "Patient" } {
+	return 0
+    }
+
+    set ptrs  [ $datamanager GetAttributePointersList ]
+    set fn    [ $datamanager  GetFilenamesList ]
+    set obj   [ $p GetAttribute [ lindex $ptrs 0 ] ]
+    set fname [ $p GetAttribute [ lindex $fn 0 ] ]
+    if { $fname == 0 || $fname == -1 } {
+	set fname ""
+    }
+
+    set fold [ $obj cget -filename ]
+    $obj configure -filename $fname
+    set ok [ $obj Save "" "[$p GetName ]" ]
+    if { $ok > 0 } {
+	set fname [ $obj cget -filename ]
+	if { $fname != $fold } {
+	    $obj Clear
+	}
+	$p SetAttribute [ lindex $fn 0 ] $fname 
+	$this UpdateVisTree $p
+	$this  UpdateStatus 
+	$optionsdialog SetOptionsFromXMLDataElement $p
+	Tree::setselection $vistree  [ $p GetAttribute VisTreePath ]
+    }
+}
+# ---------------------------------------------------------------------------------------------------------------------  
+    
+itcl::body bis_treewidget::CreateOverlayTool { base } {
+
+#    protected variable overlaytool 0
+#    protected variable overlaytooldlg 0
+
+    set tp [ toplevel $base.[pxvtable::vnewobj ]];  wm withdraw $tp
+    eval "wm protocol $tp WM_DELETE_WINDOW { wm withdraw $tp  }"
+    wm title $tp "Overlay Tool"
+
+    set buttonbar [ frame $tp.bt ]
+    set bbt [ frame $tp.bt2 -bg black -height 5 ]
+    pack $buttonbar $bbt -side bottom -expand false -fill x 
+    
+    eval "button $buttonbar.close   -text Close -command { wm withdraw $tp }"
+    pack $buttonbar.close -side right
+    
+    set w [ frame $tp.top  ]
+    pack $w -side top -expand true -fill both
+
+    set overlaytool [ [ bis_createoverlayimage \#auto ] GetThisPointer ]
+    $overlaytool InitializeFromContainer 0
+    $overlaytool SetGUIMode managed
+    if { $bis_viewer !=0 } {
+	$overlaytool SetBisViewer $bis_viewer
+    } else {
+	$overlaytool SetBisViewer $vtk_viewer
+    }
+    $overlaytool CreateGUI $w
+    $overlaytool SetOptionValue interp "NearestNeighbor"
+
+
+
+    wm geometry $tp 600x400
+
+    return $tp
+}
+# -----------------------------------------------------------------------
+itcl::body bis_treewidget::UpdateOverlayTool {  mode } {
+
+    if { $overlaytool == 0 } {
+	return 0
+    }
+
+    set elem [ $this GetCurrentXMLElement ]
+    if { $elem == 0 } { 
+	return 0
+    }
+
+    set img [  $this ResliceNodeInReferenceSpace $elem ]
+    if { $img == 0 } {
+	return 0
+    }
+    
+    set ref [ $datamanager FindNode $guiparams($this,ref_space) ]
+
+
+    set f1 [ file tail  [ $ref  GetAttribute Filename ] ]
+    set f2 [ file tail  [ $elem GetAttribute Filename ] ]
+
+    $overlaytool SetInput   [ $ref GetAttribute PointerObject ]
+    $overlaytool SetSecondInput  $img
+    wm title $overlaytooldlg "$f1 <-> $f2"
+    $overlaytool UpdateInputRanges
+    itcl::delete obj $img
+
+    return 1
+
+}
+
+itcl::body bis_treewidget::ShowOverlayTool {  } {
+
+    if { $overlaytool == 0 } {
+	return 0
+    }
+    set ok [ $this UpdateOverlayTool both ]
+    if { $ok > 0 } {
+	wm withdraw $overlaytooldlg
+	wm deiconify $overlaytooldlg
+    } else {
+	wm withdraw $overlaytooldlg
+    }
+}
+
+# -----------------------------------------------------------------------
+# Create GUI -- be all , end all
+# -----------------------------------------------------------------------
+
+itcl::body bis_treewidget::CreateGUI { base { overlaymode 0 } { readonly 0 } { filem 0 } }  {
+
+    set forcereadonlymode [ expr $readonly > 0 ]
+    set hasfilemenu [ expr $filem > 0 ]
+
+    set  basewidget $base.btf
+    set btf [ [ iwidgets::labeledframe $basewidget  -labeltext "Data Manager Control"  ] childsite ]
+    pack $basewidget -side top -expand true -fill both
+
+    set overlaytooldlg [ $this CreateOverlayTool $basewidget ]
+
+    # ------------------------------
+    # Bottom Bar
+    # ------------------------------
+
+    set pbar [ frame $btf.bot5 ]
+    pack $pbar -side bottom -expand false -fill x
+
+    CreateProgressBar  $pbar
+
+    set bbar [ frame $btf.bot ]
+    $this CreateUglyGUI $bbar
+    pack $bbar -side bottom -expand false -fill x
+    
+    #Set a variable "vistree" to hold the tree
+
+
+    if { $createtransformcontrol == 1 } {
+	set notebook [  iwidgets::tabnotebook $btf.top -tabpos n  -angle 45 -margin 2 -backdrop gray -raiseselect true ]
+	pack $notebook -side top -expand true -fill both
+	set maintab  [ $notebook add -label "Main Tree" ]
+	set xformtab [ $notebook add -label "Transformations" ]
+	$notebook view "Main Tree"
+    } else {
+	set maintab $btf
+    }
+
+    set tbar [ frame $maintab.0 ]
+    set tbarleft  [ frame $tbar.1  ]
+    set tbarright [ frame $tbar.2 ]
+    pack $tbarleft -side left -expand false -fill x
+    pack $tbarright -side left -expand true -fill both
+
+    set tb [ iwidgets::toolbar $tbarright.[ pxvtable::vnewobj ] \
+		 -balloondelay1 500 \
+		 -balloondelay2 50 \
+		 -orient horizontal \
+		 -font { helvetica 9 }\
+		 -helpvariable guiparams($this,helpVar)\
+		 -disabledforeground \#A0A0A0 \
+		 -selectcolor \#ff1000  ]
+
+#		 -background black -foreground \#ffffee -disabledforeground \#A0A0A0 
+#		 -balloonbackground darkgray 		 -balloonforeground white \
+
+    pack $tb -side top -expand false -fill x 
+    eval "$tb add button undo -height 1 -balloonstr \"Undo Delete\" -helpstr \"Undo Delete\"  -command { $this ClipboardOperation undo } -text \"Undo\""
+    eval "$tb add button delete -height 1 -balloonstr \"Delete\" -helpstr \"Delete\"  -command { $this ClipboardOperation delete } -text \"Delete\""
+    eval "$tb add button cut -height 1 -balloonstr \"Cut\"  -helpstr \"Cut\"  -command { $this ClipboardOperation cut } -text \"Cut\""
+    eval "$tb add button paste -height 1 -balloonstr \"Paste\" -helpstr \"Cut\"  -command { $this ClipboardOperation paste } -text \"Paste\""
+
+    lappend readonlybuttonlist [ list $tb undo ]
+    lappend readonlybuttonlist [ list $tb delete ]
+    lappend readonlybuttonlist [ list $tb cut ]
+    lappend readonlybuttonlist [ list $tb paste ]
+    lappend readonlybuttonlist [ list $tb edit ]
+
+    $tb add frame spacer2 -borderwidth 1 -width 3 -height 8
+    eval "$tb add button edit -height 1 -balloonstr \"Edit Properties\" 	-helpstr \"Edit Properties\"  -command { $this EditNodeProperties } -text \"Edit Node\""
+    eval "$tb add button desc -height 1 -balloonstr \"Show Properties\" 	-helpstr \"Print Properties\"  -command { $this PrintCurrentNode } -text \"Print\""
+    $tb add frame spacer3 -borderwidth 1 -width 3 -height 8
+
+    eval "$tb add checkbutton ae -text \"Lock\" -variable [ itcl::scope guiparams($this,displayonlymode) ] -command { $this LockEditing } "
+    $tb add frame spacer4 -borderwidth 1 -width 3 -height 8
+
+    eval "$tb add checkbutton ag -text \"Lock Space\" -variable [ itcl::scope guiparams($this,lockspaceimage) ] -command { $this LockSpace}"
+    
+
+    
+    set treeframe [ frame $tbarright.tree ]
+    pack $treeframe -side top -expand true -fill both
+
+    $this CreateContextToolbars $tbarleft
+
+    set vistree $treeframe.v
+
+    eval "Tree::create $vistree -bg white -width 170 -yscrollcommand {$treeframe.sb set} -xscrollcommand { $maintab.mid set }"
+    eval "scrollbar $treeframe.sb -orient vertical -command { $treeframe.v yview } "
+    eval "scrollbar $maintab.mid -orient horizontal -command { $treeframe.v xview } "
+    pack $maintab.mid -side bottom -expand false -fill x
+
+    pack $vistree -side left -fill both -expand 1 -padx {4 0} -pady {0 0}
+    focus $vistree
+    pack $treeframe.sb -side left -fill both -padx {0 3} -pady {0 3}
+
+    pack $tbar -side top -expand true -fill both
+    pack $maintab -side top -expand true -fill both
+    
+    #eval "$vistree bind x <1> { $this SetSelection %W %x %y }"
+    eval "bind $vistree <ButtonPress-1> { $this SetSelection %W %x %y }"
+    eval "bind $vistree <ButtonPress-3> { $this ShowContextMenu %W %x %y }"
+
+    if { $createtransformcontrol == 1 } {
+	set w $xformtab
+	set transformation_control [ [ pxitclmultiTransformGUI \#auto  ] GetThisPointer ]
+	$transformation_control Initialize $w.b
+	$transformation_control AddTransformation "Default"
+	eval "$transformation_control configure -callback \"$this UpdateTransformation\""
+	$this UpdateTransformation
+	pack $w.b -side top -expand false -fill x
+    }
+
+
+
+    $this CreateContextMenus
+    $this LockEditing
+    $this LockSpace
+
+
+
+$this UpdateVisTree     
+    return $basewidget
+}
+
+
+
+
+
+# ---------------------------------------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+ 
+    package require vtkpxcontrib
+    package require bis_datamanager
+
+
+    # Random Testing Code Here
+
+    wm geometry . 1100x600
+    frame .bot; pack .bot -side bottom
+    set nt [ panedwindow .base -orient horizontal -showhandle 1 \
+		 -borderwidth 10 -relief raised -sashwidth 4 -sashpad 4 \
+		 -handlesize 5 -handlepad 50  ]
+    pack .base -side top -expand true -fill both
+
+    set guibase  [ frame $nt.c  -width 500 ]
+    set viewbase  [ frame $nt.v -width 450 ]
+    $nt add $guibase -minsize  500
+    $nt add $viewbase -minsize 500
+
+    set viewer [ bis_viewer \#auto ]
+    $viewer CreateGUI $viewbase
+
+    set alg [ bis_treewidget \#auto ]
+    $alg SetBisViewer $viewer
+    $alg CreateGUI $guibase 1 0
+
+
+    if { [ llength $argv ] > 0 } {
+	$alg LoadDataTree [ lindex $argv 0 ]
+    }
+
+
+    wm title . "Test Data Tree Widget"
+    update idletasks
+
+} 
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_triangulate.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_triangulate.tcl
new file mode 100755
index 0000000..7ed8bcf
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_triangulate.tcl
@@ -0,0 +1,151 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_surfacetosurfacealgorithm 1.0
+package require bis_computenormals 1.0
+package provide bis_triangulate 1.0
+
+#
+# compute curvatures of polydata
+#
+
+itcl::class bis_triangulate {
+
+    inherit bis_surfacetosurfacealgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Triangulate" }
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_triangulate::Initialize { } {
+
+    PrintDebug "bis_triangulate::Initialize" 
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ computeNormals "Turn normal computation on/off " "Compute Normals" { listofvalues radiobutton}  On { On Off}   1}
+	{ featureangle "Feature angle between 0 to 180 degrees" "Feature angle"  { real triplescale 100 }    90.0 { 0.0 180.0 }  1 }
+	{ edgesplit      "Edge Splitting" "Edge Splitting" { boolean}  0  { 0 1 }   2}
+	{ flipnormals "Flip normals" "Flip normals" { boolean}  0 { 0 1 }   3}
+    }
+
+    set defaultsuffix { "_triangulate" }
+    
+    set scriptname bis_triangulate
+
+    #
+    #document
+    #
+    set category "Surface Processing"
+    set description  "triangulate a surface"
+    set description2 ""
+    set backwardcompaibitlity "Newly added."
+    set authors "alark.joshi at yale.edu"
+
+    $this InitializeSurfacetoSurfaceAlgorithm
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_triangulate::Execute {  } {
+
+    PrintDebug "bis_triangulate::Execute"
+
+    # Get Inputs
+    set surface    [ $this GetInput  ]
+    
+    set computeNormals  [ $OptionsArray(computeNormals) GetValue ]
+    set featureangle 	[ $OptionsArray(featureangle) 	GetValue ]
+	set edgesplit    	[ $OptionsArray(edgesplit)      GetValue ]
+	set flipnormals     [ $OptionsArray(flipnormals)    GetValue ]
+	
+    # Run Algorithm
+	set triangleFilter [ vtkTriangleFilter [ pxvtable::vnewobj ] ]
+	$triangleFilter SetInput [ $surface GetObject ]	
+	$triangleFilter Update
+	
+	set fname [ [ $this GetOutput ] cget -filename ] 	
+	
+	if { $computeNormals == "On" } {	
+	 # Step 1 ... Invoke bis_computeNormals -----
+	    set normal_surf [ [  bis_computenormals #auto ] GetThisPointer ]
+	    $normal_surf InitializeFromContainer $this
+	    
+	    [ $normal_surf GetInput ] ShallowCopySurface [ $triangleFilter GetOutput ]
+	    [ $normal_surf GetInput ] configure -filename $fname
+	    
+	    $normal_surf SetOptionValue featureangle $featureangle
+       	$normal_surf SetOptionValue edgesplit $edgesplit
+    	$normal_surf SetOptionValue flipnormals $flipnormals
+    	$normal_surf Execute
+		set surface_out1 [$normal_surf GetOutput ]
+		[ $OutputsArray(output_surface) GetObject ] DeepCopy $surface_out1 
+	
+	} else {
+    # Store Results in output
+    	set surface_out2 [ $triangleFilter GetOutput ]
+    	[ $OutputsArray(output_surface) GetObject ] ShallowCopySurface [ $triangleFilter GetOutput ]
+    }
+    
+    # Clean up
+    $triangleFilter Delete
+
+    return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_triangulate.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_triangulate [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_ttest.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_ttest.tcl
new file mode 100755
index 0000000..4d24841
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_ttest.tcl
@@ -0,0 +1,259 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_ttest 1.0
+package require bis_dualimagealgorithm 1.0
+
+itcl::class bis_ttest {
+
+	inherit bis_dualimagealgorithm
+
+	 constructor { } {	 $this Initialize  }
+
+	public method Initialize { }
+	public method Execute { }
+	public method GetGUIName    { } { return "Compute T-Test" }
+	#override parent function
+	public method CheckInputObjects { }
+	public method UpdateOutputFilenames { } 
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_ttest::Initialize { } {
+
+	PrintDebug "bis_ttest::Initialize" 
+	
+	#commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+	set options {
+	    { mode      "Type of T Test"	"Mode"	{ listofvalues radiobuttons } paired { paired unpaired singlegroup } 0 }
+	}
+
+	set defaultsuffix { "_ttest" }
+	set scriptname bis_ttest
+	set completionstatus "Done"
+
+	#
+	#document
+	#
+	
+	set description "t test."
+	set description2 "takes two inputs and computes either a paired t-test or an unpaired t-test or a single group t-test. For paired t-test both images must have the same number of frames."
+	set backwardcompatibility ""
+	set authors "isabella.murphy at yale.edu"
+
+	$this InitializeDualImageAlgorithm
+	
+	$this RenameInput 0 "DataSet 1"
+	$this RenameInput 1 "DataSet 2" 101
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_ttest::Execute {  } {
+    PrintDebug "bis_ttest::Execute"
+    
+    set mode   [ $OptionsArray(mode) GetValue ]
+    
+    set image1 [ $this GetInput ]
+    set image2 [ $this GetSecondInput ]
+    
+    set img1  [ $image1 GetImage ]
+    set img2  [ $image2 GetImage ] 
+    
+    set tlist [ list $img1 $img2 ]
+    set timg ""
+
+    if { $mode == "paired" } {
+	set imcast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+	$imcast2 SetInput $img2
+	$imcast2 SetOutputScalarType [ $img1 GetScalarType ]
+	$imcast2 Update
+	
+	set math [ vtkImageMathematics [ pxvtable::vnewobj ]]
+	$math SetInput1 $img1
+	$math SetInput2 [ $imcast2 GetOutput ]
+	$math SetOperationToSubtract
+	$math Update
+	
+	set timg [ vtkImageData New ]
+	$timg ShallowCopy [ $math GetOutput ]
+	$math Delete
+	$imcast2 Delete
+	set tlist $timg
+    }
+
+    if { $mode == "singlegroup" } {
+	set tlist $img1 
+    }
+    
+    set n [ llength $tlist ] 
+    puts stderr "tlist=$tlist n=$n"
+    set math [ vtkpxComputeTmap [ pxvtable::vnewobj ]]
+    
+    for { set i 0 } { $i < $n } { incr i } {
+	set ave($i) [ vtkbisImageAverageComponents [ pxvtable::vnewobj ] ]
+	$ave($i) SetInput [ lindex $tlist $i ]
+	$ave($i) Update
+
+	if { $i == 0 } {
+	    $math SetInput  [ $ave($i) GetOutput ]
+	    $math SetInputStandardDeviation  [ $ave($i) GetStandardDeviationImage ] 
+	    $math SetNumberOfSamples1 [ $img1 GetNumberOfScalarComponents ]
+	} else {
+	    $math SetInput2  [ $ave($i) GetOutput ]
+	    $math SetInputStandardDeviation2  [ $ave($i) GetStandardDeviationImage ]
+	    $math SetNumberOfSamples2 [ $img2 GetNumberOfScalarComponents ]
+	}
+	$ave($i) Delete
+    }
+    
+    $math SetNumberOfInputs $n
+    $math SetScaleFactor 1000.0
+    $math Update
+    
+    set outimage [ $OutputsArray(output_image) GetObject ]
+    $outimage ShallowCopyImage [ $math GetOutput ]
+    $outimage CopyImageHeader [ $image1 GetImageHeader ]
+    
+    set comment [ format " [ $this GetCommandLine full ]" ]
+    [ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+    
+    if { $timg !="" } {
+	$timg Delete
+    }
+
+   
+    puts stdout "Results Range: [ [ [ [ $outimage GetImage ] GetPointData ] GetScalars ] GetRange ]"
+    $math Delete
+           
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------------------
+itcl::body bis_ttest::UpdateOutputFilenames { } {
+
+    set mode   [ $OptionsArray(mode) GetValue ]
+    if { $mode == "singlegroup" } {
+	set defaultsuffix { "_singlettest" }
+    } elseif { $mode == "paired" } {
+	set defaultsuffix { "_pairedttest" }
+    } else {
+	set defaultsuffix { "_unpairedttest" }
+    }
+    
+    #puts stderr "ttest defaultsuffix=$defaultsuffix, guimode=$guimode"
+
+    if { $mode != "singlegroup" } {
+	return [ ::bis_dualimagealgorithm::UpdateOutputFilenames  ]
+    }
+
+    return [ ::bis_imagetoimagealgorithm::UpdateOutputFilenames  ]
+
+}
+
+
+itcl::body bis_ttest::CheckInputObjects { } {
+
+    set mode   [ $OptionsArray(mode) GetValue ]
+    set image1    [ $this GetInput ]
+    set d [ $image1 GetImageSize ]
+    if { $d < 2 } {
+	set errormessage "Bad Second Image\n Cannot Perform $mode t-test!"
+	return 0
+    }
+
+    set img1  [ $image1 GetImage ]
+    if { [ $img1 GetNumberOfScalarComponents ] <2  } { 
+	set errormessage "Not enough frmes to  perform compare $mode t-test!"
+	return 0
+    }
+
+
+    if { $mode == "singlegroup" } {
+	return 1
+    }
+    
+
+
+    set image2    [ $this GetSecondInput ]
+    set d [ $image2 GetImageSize ]
+    if { $d < 2 } {
+	set errormessage "Bad Second Image\n Cannot Perform $mode t-test!"
+	return 0
+    }
+    
+    set img1  [ $image1 GetImage ]
+    set img2  [ $image2 GetImage ] 
+    set mode   [ $OptionsArray(mode) GetValue ]
+    
+
+    if { [ $img1 GetNumberOfPoints ] != [ $img2 GetNumberOfPoints ] } {
+	set errormessage "Unequal Image Sizes\n Cannot Perform Compare $mode t-test!"
+	return 0
+    }
+    
+    if { $mode == "paired" } {
+	if { [ $img1 GetNumberOfScalarComponents ] != [ $img2 GetNumberOfScalarComponents ] } {
+	    set errormessage "Unequal Number of Image Frames\n Cannot Perform paired t-test!"
+	    return 0
+	}
+    }
+    
+    return 1
+    
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_ttest.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+	# this is essentially the main function
+
+	set alg [bis_ttest [pxvtable::vnewobj]]
+	$alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_util.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_util.tcl
new file mode 100644
index 0000000..2e67f25
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_util.tcl
@@ -0,0 +1,140 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_util 1.0
+
+#
+# AUTHOR Hirohito Okuda, hirohito.okuda at yale.edu
+# 
+
+package require  Itcl 3.2
+package require  Iwidgets 
+
+itcl::class bis_util {
+
+    constructor { } {
+    }
+
+    #
+    #file operaton
+    #
+
+    # createa a sequential filelist (e.g., {file001 file002 file003..})
+    public method create_sequential_filelist { file_trunk start end } 
+
+    #make directory
+    public method MakeDirectory { directory }
+
+    # generate abolute path name of the file
+    public method GenAbsolute { fname } 
+
+    public method TestIfTransformsExist { transformlist }
+
+    public method TestIfImagesExist { imagelist }
+
+    #
+    #private
+    #
+    private method TestIfFilesExist   { filelist mode }
+
+}
+
+#######################################################
+# createa a sequential filelist (e.g., {file001 file002 file003..})
+#######################################################
+
+itcl::body bis_util::create_sequential_filelist { file_trunk start end } {
+    set filelists ""
+    for {set i $start } {$i  <= $end } {incr i} {
+	if { $i <10 } {
+	    set target  [format "%s_00%s" $file_trunk $i]
+	} elseif { $i < 100 } {
+	    set target  [format "%s_0%s"  $file_trunk $i]
+	} else {
+	    set target  [format "%s_%s"  $file_trunk $i]
+	}
+	lappend filelists $target
+    }
+    return $filelists
+}
+
+itcl::body bis_util::MakeDirectory { directory } {
+    if { [ file exists $directory ] == 0 } {
+	file mkdir $directory
+    }
+}
+
+itcl::body bis_util::GenAbsolute { fname } {
+
+    if { [ file pathtype $fname ] == "relative" } {
+	set out [ file join [ pwd ] $fname ]
+	regsub -all  "/./" $out "/" out
+    } else {
+	set out $fname
+    }
+
+    puts stderr "$fname -> $out"
+    return $out
+}
+
+
+itcl::body bis_util::TestIfTransformsExist { transformlist } {
+    TestIfFilesExist  $transformlist  0 
+}
+
+itcl::body bis_util::TestIfImagesExist { imagelist } {
+    TestIfFilesExist  $transformlist  1 
+}
+
+#
+# mode=0 transform,mode=1,image files
+#
+itcl::body bis_util::TestIfFilesExist { filelist mode } {
+    for { set i 0 } { $i < [ llength $filelist ] } { incr i } {
+	set a [ lindex $filelist $i ]
+
+	switch $mode {
+	    0 {
+		set b $a 
+	    }
+	    1 {
+		set b "[ file root $a ].img"
+	    }
+	}
+	set index [ format "%3d" [ expr $i +1 ] ]
+	set ok1 [ file exists $a ] ;   set sz1 -1 ; catch { set sz1 [ file size $b ] }
+	
+	if { $ok1 > 0 } {
+	    puts stderr "\t$index  $a ($sz1)  ok"
+	} else {
+	    puts stderr "\n*********** Missing Transform $a ($sz1)"
+	    exit
+	}
+    }
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_varian2nifti.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_varian2nifti.tcl
new file mode 100755
index 0000000..d49ae07
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_varian2nifti.tcl
@@ -0,0 +1,290 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+
+package require bis_algorithm 1.0
+package require bis_newreorientimage 1.0
+
+package provide bis_varian2nifti 1.0
+
+#
+# Operations involving multisubject average for testing ....
+#
+
+itcl::class bis_varian2nifti {
+
+    inherit bis_algorithm
+    
+    constructor { } {
+	$this Initialize
+    }
+
+    public method Initialize { }
+    public method Execute { }
+    public method PrintOutput { nn }
+    public method GetGUIName { } { return "Varian2Nifti" }
+}
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_varian2nifti::Initialize { } {
+
+    PrintDebug "bis_varian2nifti::Initialize" 
+
+    #name,description,type,object,filename(if applicable),priority (optional)
+    set inputs { }
+    set outputs { }
+
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set options {
+	{ indir "Input directory containing VARIAN Files" "Input Directory"  { filename directory 40 }  "" "" 1 }
+	{ outdir "Output directory for NIFTI Files" "Output Directory"  { filename directory 40 }  "" "" 2 }
+	{ mode "Postprocessing of Original Data" "Mode"  listofvalues  LPS { NONE RAS LPS }   3}
+	{ name  "Study Name" "Name"  { string 20 }  "" ""  4 }
+	{ dosave "If set to off no files are created" "Do Save"  { boolean checkbutton } 1 { 0 1 }  -10 }
+	{ flipdti "If set to on DTI images are flipped left-right" "Flip DTI"  { boolean checkbutton } 1 { 0 1 }  -11 }
+
+    }
+
+    set outputs { }
+
+    set defaultsuffix { "" }
+
+    set scriptname bis_varian2nifti
+    set completionstatus ""
+    #
+    #document
+    #
+    set category "Utility"
+    set description "This script parses a directory containing VARIAN images and creates NIFTI output files"
+    set description2 "Has capabilities for Siemens Mosaic Format (for FMRI)"
+    set backwardcompatibility "Based on original ImageConversion script at Yale MRRC"
+    set authors "xenophon.papademetris.yale.edu"
+
+    $this AddDefaultOptions
+
+
+}
+
+itcl::body bis_varian2nifti::PrintOutput { nn } {
+
+    if { $basewidget == 0 } {
+	puts stdout "${nn}"
+    } else {
+	pxtkprint "${nn}\n"
+    }
+}
+
+
+itcl::body bis_varian2nifti::Execute {  } {
+
+    set dryrun 0
+    if { [ $OptionsArray(dosave) GetValue ] == 0 } {
+	set dryrun 1
+    }
+    
+    set basedir [ file normalize [ $OptionsArray(indir) GetValue ] ]
+
+    set savednames ""
+
+    set outputdir [ $OptionsArray(outdir) GetValue ] 
+
+    if { $outputdir == "" } {
+	set n [ pid ]
+	set f  [ file join [ pwd ] nifti_$n ]
+	while { [ file exists $f ] > 0 } {
+	    incr n
+	    set f  [ file join $outdir tmp_$n ]
+	}
+	set outputdir $f 
+    }
+
+    set outputdir [ file normalize $outputdir ]
+    catch {    file mkdir $outputdir }
+
+    puts stderr "Using output directory = $outputdir\n"
+
+
+
+    set outmode [ $OptionsArray(mode) GetValue ]
+    set pname   [ $OptionsArray(name) GetValue ]
+    set flipdti [ $OptionsArray(flipdti) GetValue ]
+
+    if { $basewidget != 0 } {
+	pxtkconsole
+    }
+
+    $this PrintOutput "Beginning -- Input Directory = $basedir, outputdir=$outputdir, convmode=$outmode, pname=$pname"
+    
+    set dname $basedir
+    cd $dname
+    
+
+    # ----------------------------------------------------------------------
+    # Find last acquired image, newest file in $dname
+    # ----------------------------------------------------------------------
+    
+    set outname [ file tail $basedir ]
+    set convertedlist ""
+    set done 0
+    set pass 0
+    while { $done == 0 } {
+	
+	incr pass
+	set b [ glob [ file join $dname [ file join * *.fdf ] ] ]
+	set a ""
+	for { set i 0 } { $i < [ llength $b ] } { incr i } {
+	    lappend a [ file normalize [ lindex $b $i ] ]
+	}
+	$this PrintOutput "Starting with a total of [ llength $a ] images ]"
+
+
+	set lst ""
+	for { set i 0 } { $i < [ llength $a ] } { incr i } {
+	    set f [ lindex $a $i ]
+	    set ind [ lsearch -exact $convertedlist $f ] 
+	    if { $ind == -1 } {
+		lappend lst $f
+	    }
+	}
+
+	if { [ llength $lst ] == 0 } {
+	    $this PrintOutput "\n\n------------------------------------------------------------\n No More Files To Convert \n------------------------------------------------------------\n"
+
+	    set savednames [ lsort -ascii -index 0 $savednames  ]
+	    for { set i 0 } { $i < [ llength $savednames ] } { incr i } {
+		$this PrintOutput "[ expr $i +1 ]. [ lindex [ lindex $savednames $i ] 0 ]  ( [ lindex [ lindex $savednames $i ] 1 ] )"
+	    }
+	    return 1
+	}
+	
+	$this PrintOutput "\n\n------------------------------------------------------------\n Doing Pass $pass \n------------------------------------------------------------\n"
+	$this PrintOutput "Number of Available VARIAN Images to process = [ llength $lst ]"
+	
+	
+	set anchorfile [ lindex $lst 0 ]
+	$this PrintOutput "First file = [ file join $dname $anchorfile ]"
+	
+	
+	# ----------------------------------------------------------------------
+	#  Do Full Blown VARIAN Import
+	# ----------------------------------------------------------------------
+	
+	set img [ [ pxitclimage \#auto ] GetThisPointer ]
+	set pxitclimage::forcebioimagesuitecoordinates 0
+	$img LoadVarian $anchorfile 0 $flipdti
+	
+	$this PrintOutput "Reading Input Image Done\n"
+	
+	set lst [ $img cget -lastdicomlist ]
+	for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	    set nf [ file normalize [ lindex [ lindex $lst $i ] 0 ] ]
+	    lappend convertedlist $nf
+	}
+	$this PrintOutput "Adding [ llength $lst ] files to list of images already converted"
+	
+	$img configure  -lastdicomlist ""
+	
+	set nf [ [ $img GetImage ] GetNumberOfScalarComponents ]
+	set extra "stack3d" 
+	if { $nf > 1 } {
+	    set extra "stack4d"
+	}
+
+	set fa [ file tail [ file normalize [ $img cget -filename ] ] ]
+
+	if { $outmode == "NONE" } {
+
+	    if { [ string length $pname ] > 0 } {
+		set f1 [ file join ${outputdir}  ${outname}_${pname}_${fa}_orig.nii.gz  ]
+	    } else {
+		set f1 [ file join ${outputdir} ${outname}_${fa}_orig.nii.gz  ]
+	    }
+	    set dm [ [ $img GetImage ] GetDimensions ]
+	    set details "d=$dm, $nf"
+	    if { $dryrun == 0 } {
+		$img Save $f1
+		$this PrintOutput "Output NIFTI image saved in $f1 ($details), file size=[ file size $f1 ]"
+	    } else {
+		$this PrintOutput "Output should have been saved in $f1 ($details)"
+	    }
+	    lappend savednames [ list $f1 $details ]
+
+	} else {
+	    set dm [ [ $img GetImage ] GetDimensions ]
+
+	    set reorient [ bis_newreorientimage \#auto ]
+	    $reorient InitializeFromContainer 0
+	    $reorient SetInput $img
+	    $reorient SetOptionValue orientation $outmode
+	    $reorient Execute
+	    
+	    set finalimg [ [ pxitclimage \#auto ] GetThisPointer ]
+	    $finalimg ShallowCopy [ $reorient GetOutput ]
+	    itcl::delete object $reorient
+	    
+	    set dm2 [ [ $finalimg GetImage ] GetDimensions ]
+
+	    if { [ string length $pname ] > 0 } {
+		set f2 [ file join $outputdir ${outname}_${pname}_${fa}_${outmode}.nii.gz ]
+	    } else {
+		set f2 [ file join $outputdir ${outname}_${fa}_${outmode}.nii.gz ]
+	    }
+
+	    set details "d=$dm -- >$dm2, $nf" 
+	    if { $dryrun == 0 } {
+		$finalimg  Save $f2
+		$this PrintOutput "Reoriented ($outmode) output NIFTI image saved in $f2 ($details), file size=[ file size $f2 ]"
+	    } else {
+		$this PrintOutput "Reoriented ($outmode) output should have been saved in $f2 ($details)"
+	    }
+	    lappend savednames [ list $f2 $details ]
+	    itcl::delete obj $finalimg 
+	}
+	itcl::delete object $img
+    }
+}
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    
+
+    set alg [bis_varian2nifti [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_viewer.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_viewer.tcl
new file mode 100644
index 0000000..6c36143
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_viewer.tcl
@@ -0,0 +1,1062 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    lappend auto_path [ file dirname [ info script ]]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+    lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] main]
+}
+
+
+package provide bis_viewer 1.0
+package require vtkpxcontrib 1.0
+package require  Itcl 3.2
+package require bis_option 1.0
+package require bis_common 1.0
+package require Iwidgets 
+package require pxitclimage 1.0
+package require pxitclbasecontrol 1.0
+package require bis_polygonaldisplaymanager 1.0
+
+
+
+# -----------------------------------------------
+#
+# Master Viewer needs work
+# trace on surface vs volume and tolerance issues
+# 
+# -----------------------------------------------
+itcl::class bis_viewer {
+
+    #
+    #public
+    #
+    inherit pxitclbasecontrol
+
+    constructor { { par 0 } } { 
+	::pxitclbasecontrol::constructor $par
+    } {	$this Initialize }
+    destructor { $this CleanAll }
+
+    # Different tools enable/disable
+    public    variable enable_animationgadget 1
+    public    variable enable_tracegadget 0
+    public    variable enable_talaraichoption 1
+    public    variable enable_atlastools      1
+    public    variable enable_vvlinkgadget  1
+    public    variable enable_openigtlinkgadget  1
+    public    variable enable_landmarkeditor  0
+    public    variable enable_electrodeeditor 0
+    public    variable enable_toolbar  1
+
+    # Key Outside Interface
+    public method SetImage { img } 
+    public method GetImage { } 
+    # Legacy mode
+    public method SetResultsFromObject { img obj }
+
+
+    public method SetMask  { msk } 
+    public method SetImageColormap { cmap }
+    public method SetImageColormapMode { cm }
+    public method SetMaskColormap { cmap }
+
+    # This is in mm
+    public method GetCursorPoint { }
+    # This is in voxels (i,j,k)
+    public method GetLastVoxel { } 
+
+    # Observer Interface
+    #AddCursorNotifier {    } .. args  $x $y $z $this
+    #AddImageNotifier  {    } .. args image $this
+    public method AddCursorNotifier { object command }
+    public method RemoveCursorNotifier { object command }
+    public method AddImageNotifier { object command }
+    public method RemoveImageNotifier { object command }
+
+    # Mouse Events
+    # ------------
+    public method HandleUpdateEvent { args }
+    public method HandleMouseEvent { mouse stat x1 x2 widgetname args }
+    public method HandleCoordinatesChangeEvent { { mouse -1 } { stat -1 } }
+
+
+    # Viewer Issues
+    public method GetViewer { } { return $vtk_viewer }
+    public method GetScreenshotImage  { { magnification 1 } } 
+    # md = ortho, simple, singleslice, ortho4d; editor = 0 or 1
+    public method SetViewerType {  md { enableedit 0 }} 
+    public method CanAcceptMask { }
+
+    # Other Viewers
+    public method SetLinkedCursorViewer { vv } { set linked_viewer $vv }
+    public method SetMasterViewer { vv } { set master_viewer $vv }
+    public method SetAtlasTool { atl } { set atlastool $atl }
+
+    # Data Management sur is electodes/surface/landmarks (actor!)
+    public method EditPolygonalObject {  sur datatree node }
+    public method AddPolygonalObject {  sur { linked 0 } { attr "" } }
+    public method AddOrReplacePolygonalObject {  sur { linked 0 } { attr "" } }
+    public method UpdatePolygonalObject {  sur  attr { updisplay 1 } }
+    public method RemovePolygonalObject { sur }
+    public method GetPolygonalDisplayManager { } { return $bis_polygonalobjectmanager }
+
+    # Final one is GUI
+    protected method InitializeViewer { viewerbase }
+    protected method InitializeToolbar { toolbase }
+    protected method InitializeTools   { toolbase }
+    public method CreateGUI { base }
+    public method AddToMenu { viewm }
+
+    # Methods for Toolbar
+    public method SetSnapshotResolution { factor }
+
+    public method SetTraceMode { enablevolume { size 0 } { weightedfactor 0 } }
+    public method SetViewerBackground { }
+
+
+    # ------------------------------------------------------------------------------
+    # Internal Stuff
+    # ------------------------------------------------------------------------------
+
+    # protected method
+    protected method Initialize { } 
+    protected method CleanAll { } 
+
+    # key internal variables
+    protected variable vtk_viewer  0
+    protected variable master_viewer  0
+    protected variable linked_viewer  0
+    protected variable vtk_viewertype  "vtkpxGUIOrthogonalViewer"
+    protected variable vtk_extratype  ""
+    protected variable bis_polygonalobjectmanager 0
+    protected variable datamanager 0
+    protected variable landmarkeditor 0
+    protected variable electrodeeditor 0
+    protected variable cursorcallbacklist ""
+    protected variable imagecallbacklist ""
+    protected variable currentimage 0
+    protected variable currentmask 0
+    protected variable vvlinkgadget 0
+    protected variable openigtlinkgadget 0
+
+    # Animation Gadget
+    protected variable animationgadget 0
+    protected variable atlastool 0
+
+
+    # Common Stuff
+    protected common guiparam
+
+};
+
+# ------------------------------------------------------------------------------------------------------
+#             Implementation
+# ------------------------------------------------------------------------------------------------------
+itcl::body bis_viewer::Initialize { }  {
+    
+    set  datamanager 0
+    set cursorcallbacklist ""
+    set imagecallbacklist ""
+    set currentimage [ [ pxitclimage \#auto ] GetThisPointer ]
+    set img [ $currentimage GetImage ]
+
+    set currentmask [ [ pxitclimage \#auto ] GetThisPointer ]
+    set isdialog 0
+    set guiparam($this,snapshotresdlg) 0
+    set guiparam($this,tracedialog) 0
+}
+
+itcl::body bis_viewer::CleanAll { } {
+    
+    itcl::delete obj $currentimage
+    itcl::delete obj $currentmask
+}
+
+# -------------------------------------------------------------------------------------------------
+itcl::body bis_viewer::GetScreenshotImage  { { magnification 1 } } {
+
+    if { $vtk_viewer == 0 } {
+	return 0
+    }
+    
+    set rw [ $vtk_viewer GetRenderWidgetName ]
+    set renwin [ $rw GetRenderWindow ]
+
+    set renSrc [ vtkWindowToImageFilter New ]
+    $renSrc SetInput $renwin
+    $renSrc SetMagnification $magnification
+    $renSrc Update
+
+    set img [ vtkImageData New ]
+    $img ShallowCopy [ $renSrc GetOutput ]
+    $renSrc Delete
+
+    return $img
+}
+# -------------------------------------------------------------------------------------------------
+itcl::body bis_viewer::CanAcceptMask { } { 
+
+    if { $vtk_viewer == 0 } {
+	return 0
+    }
+
+    if { [ $vtk_viewer IsA "vtkpxGUIObjectmapOrthogonalViewer"  ] == 0 &&
+	 [ $vtk_viewer IsA "vtkpxGUIObjectmapMosaicViewer"  ] == 0 } {
+	return 0
+    }
+
+    return 1
+
+}
+
+# --------------------------------------------------------------------------
+itcl::body bis_viewer::SetResultsFromObject { img obj } {
+    puts stderr "Legacy warning set results from object ..... in $this"
+    return [ $this SetImage $img ]
+}
+
+# ------------------------------------------------------------------------------
+itcl::body bis_viewer::GetImage { }  {
+    return $currentimage
+}
+# ------------------------------------------------------------------------------
+
+itcl::body bis_viewer::SetImage { img }  {
+
+    if { [ $img GetImageSize  ] < 2 } {	return 0    }
+
+
+    # Do I need to clean the surface display?
+
+    set same [ $currentimage IsSameDisplaySize $img ]
+    
+    $currentimage ShallowCopy $img
+
+    if { $vtk_viewer == 0 } {
+	return 0
+
+   }
+
+    set cmap [ $img GetLookupTable ]
+
+    if { $cmap !=0 } {
+	$vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ]  $cmap
+    } else {
+	$vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ]  
+    }
+
+    if { $cmap == 0  } {
+	
+	global pxtcl_pref_array
+	if { $pxtcl_pref_array(NormalizeAnatomical) > 0 } {
+	    set normalize_anatomical 1
+	}
+
+	set r [ [ [ [ $img GetImage ] GetPointData ] GetScalars ] GetRange ]
+	set d [ expr [ lindex $r 1 ]- [ lindex $r 0 ] ]
+	if { $normalize_anatomical > 0 && $d > 20 } {
+	    $this SetImageColormapMode 0
+	} else {
+	    $this SetImageColormapMode -1
+	}
+    }
+
+
+    if { $same == 0 } {
+	$bis_polygonalobjectmanager CleanAll
+    }
+
+
+
+    foreach cmd $imagecallbacklist {
+	if { [ string length $cmd ] > 1 } {
+	    set a "$cmd $img"
+	    #	    puts stderr "invoking $a"
+	    eval $a
+	}
+    }
+
+
+    set v [ winfo parent [  $this GetBaseWidget ] ]
+    catch { wm deiconify $v }
+
+}
+
+itcl::body bis_viewer::SetMask  { msk }  {
+
+    if { [ $msk GetImageSize  ] < 2 } {	return 0    }
+    $currentmask ShallowCopy $msk
+
+    if { [ $currentimage GetImageSize ] < 2 || [ $this CanAcceptMask ] == 0 } {
+	return 0
+    }
+
+    
+    set nc [ [  $currentimage GetImage ] GetNumberOfScalarComponents ]
+    set oc [ [  $currentmask  GetImage ] GetNumberOfScalarComponents ]
+
+
+    # Scenario 1
+    if { $oc != $nc } {
+	set tmp [ vtkImageData [ pxvtable::vnewobj ]]
+	$tmp CopyStructure [ $currentmask GetImage ]
+	$tmp SetNumberOfScalarComponents $nc
+	$tmp AllocateScalars
+
+	set t_data [ [ $tmp GetPointData ] GetScalars ] 
+	set i_data [ [ [ $currentmask GetImage ] GetPointData ] GetScalars ]
+
+	set mval $nc
+	if { $oc < $nc } {
+	    set mval $oc 
+	}
+
+	for { set i 0 } { $i < $mval  } { incr i } {
+	    $t_data CopyComponent $i $i_data $i
+	}
+
+	if { $nc > $oc } {
+	    for { set i $oc } { $i < $nc  } { incr i } {
+		$t_data CopyComponent $i $i_data [ expr $oc -1 ]
+	    }
+	}
+    } else {
+	set tmp [ $currentmask GetImage ]
+    }
+	
+    if { [ $currentmask GetImageSize ] == [ $currentimage GetImageSize ] } {
+	$vtk_viewer SetObjectMapImage $tmp
+    } else {
+	set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+	$resl SetInput $tmp
+	$resl SetInterpolationMode 0
+	$resl SetInformationInput [ $currentimage GetImage ]
+	$resl Update
+	$vtk_viewer SetObjectMapImage [ $resl GetOutput ]
+	
+	$resl Delete
+    }
+
+    if { $oc!=$nc } {
+	$tmp Delete
+    }
+}
+
+# ---------------------------------------------------------------------------------------
+itcl::body bis_viewer::SetImageColormap { cmap } {
+
+    if { $vtk_viewer != 0 } {
+	$vtk_viewer SetLookupTable $cmap
+    }
+}
+
+itcl::body bis_viewer::SetImageColormapMode { cm } {
+    
+    if { $vtk_viewer != 0 } {
+	$vtk_viewer SetPresetLookupTable $cm
+    }
+}
+
+itcl::body bis_viewer::SetMaskColormap { cmap } {
+
+    if { [ $this CanAcceptMask ] == 0 } {
+	return 0
+    }
+    $vtk_viewer SetObjectLookupTable $cmap 1
+    return 1
+}
+# ---------------------------------------------------------------------------------------
+# This is in mm
+itcl::body bis_viewer::GetCursorPoint { } {
+    set lv 0
+    catch { set lv [ $vtk_viewer GetLastClickedPoint ] }
+    return $lv
+}
+
+# This is in voxels (i,j,k)
+itcl::body bis_viewer::GetLastVoxel { }  {
+
+    set lv [ list -1 -1 -1 ]
+    catch { set lv [ $vtk_viewer GetLastClickedPoint ] }
+    if { [ llength $lv ] > 1 } {
+	if { [ lindex $lv 0 ] > -1 } {
+	    return  [ $vtk_viewer GetLastClickedPointScaled ] 
+	}
+    }
+
+    return 0
+}
+
+# -------------------------------------------------------------------------------
+# Observer Interface
+#AddCursorNotifier {    } .. args  $x $y $z $this
+#AddImageNotifier  {    } .. args image $this
+# -------------------------------------------------------------------------------
+itcl::body bis_viewer::AddCursorNotifier { object command } {
+
+    set ll "$object $command"
+    set ind [ lsearch -exact $cursorcallbacklist $ll ]
+    if { $ind > -1 } {
+	return 0
+    }
+    lappend cursorcallbacklist $ll
+
+}
+
+itcl::body bis_viewer::RemoveCursorNotifier { object command } {
+    set ll "$object $command"
+    set ind [ lsearch -exact $cursorcallbacklist $ll ]
+    if { $ind > -1 } {
+	set cursorcallbacklist [ lreplace $cursorcallbacklist $ind $ind "" ]
+    }
+}
+
+itcl::body bis_viewer::AddImageNotifier { object command } {
+
+    set ll "$object $command"
+    set ind [ lsearch -exact $imagecallbacklist $ll ]
+    if { $ind > -1 } {
+	return 0
+    }
+    lappend imagecallbacklist $ll
+
+}
+
+itcl::body bis_viewer::RemoveImageNotifier { object command } {
+    set ll "$object $command"
+    set ind [ lsearch -exact $imagecallbacklist $ll ]
+    if { $ind > -1 } {
+	set imagecallbacklist [ lreplace $imagecallbacklist $ind $ind "" ]
+    }
+}
+
+# -------------------------------------------------------------------------------
+# Mouse Events
+# -------------------------------------------------------------------------------
+itcl::body bis_viewer::HandleMouseEvent { mouse stat x1 x2 widgetname args } {
+    if { $vtk_viewer == 0 } {
+	return
+    }
+
+    # Need to flip y-axis vtk counts from bottom tk counts from top !!!
+    set wd [ [ $widgetname GetRenderWindow ] GetSize ]
+    set x2 [ expr [lindex $wd 1 ] - $x2 ]
+    $vtk_viewer HandleMouseButtonEvent $mouse $stat $x1 $x2
+    $this HandleCoordinatesChangeEvent $mouse $stat
+}
+
+itcl::body bis_viewer::HandleCoordinatesChangeEvent { { mouse -1 } { stat -1 } } {
+
+    set pt  [ $this GetCursorPoint ]
+    set vx [ $this GetLastVoxel   ]
+
+#    if { $stat == 2 } {
+#	return
+#    }
+    
+    if { [ llength $pt ] == 3 } {
+	foreach cmd $cursorcallbacklist {
+	    if { [ string length $cmd ] > 1 } {
+		set a "$cmd \[ list $pt \] \[ list $vx \] $mouse $stat"
+		#puts stderr "invoking $a"
+		eval $a
+	    }
+	}
+    }
+
+    if { $linked_viewer != 0 } {
+	set other_viewer [ $linked_viewer GetViewer ]
+	if { [ $vtk_viewer IsA "vtkpxGUIOrthogonalViewer" ] && [ $other_viewer IsA "vtkpxGUIOrthogonalViewer" ] } {
+	    
+	    set upd0 [ $vtk_viewer GetMouseSliceChangeMode ]	
+	    set upd1 [ $other_viewer GetMouseSliceChangeMode ]
+	    if { $upd0 == 1 && $upd1 == 1 } {
+		$other_viewer CopyCamera $vtk_viewer
+		if { [ llength $vx ] == 3 } {
+		    $other_viewer SetScaledCoordinates [ lindex $vx 0 ] [ lindex $vx 1 ] [ lindex $vx 2 ]
+		} else {
+		    $other_viewer Update
+		}
+	    } 
+	}
+    }
+    
+    if { [ llength $pt ] == 3  &&  $atlastool != 0 } {
+	set tal [ $vtk_viewer GetTalairachTransform ]
+	if { $tal != "" } {
+	    set md [ $tal GetColinMode ]
+	    set ysz [ $tal GetColinYSize ]
+	    
+	    if { $ysz != 216 } {
+		set md 0
+	    }
+
+	    set px [ lindex $pt 0 ]
+	    set py [ lindex $pt 1 ]
+	    set pz [ lindex $pt 2 ]
+	    
+	    if { $md == 1 } {
+		$atlastool IdentifyPoint $px $py $pz
+	    } elseif { $md == -1 } {
+		$atlastool IdentifyPoint [ expr 180 - $px ] [ expr 216.0 - $py ] $pz
+	    } else {
+		$atlastool SetError "Image Not in MNI Space, Cannot Identify Point.\n"
+	    }
+	}
+    }
+}
+
+#----------------------------------------------------------------------------
+itcl::body bis_viewer::SetViewerType {  md { enableedit 0 }}  {
+
+    if { $enableedit == 0 } {
+	if { $md == "ortho" } {
+	    set vtk_viewertype "vtkpxGUIOrthogonalViewer"
+	} elseif { $md == "ortho4d" } {
+	    set vtk_viewertype "vtkpxGUI4DOrthogonalViewer"
+	} else {
+	    set vtk_viewertype "vtkpxGUIMosaicViewer"
+	    if { $md == "singleslice" } {
+		set vtk_extratype  single
+	    }
+	}
+    } else { 
+	if { $md == "ortho" } { 
+	    set vtk_viewertype "vtkpxGUIObjectmapOrthogonalViewer"
+	} else {
+	    set vtk_viewertype "vtkpxGUIObjectmapMosaicViewer"
+	}
+    }
+}
+# ---------------------------------------------------------------------
+itcl::body bis_viewer::EditPolygonalObject {  sur datatree node } {
+
+    if { [ $sur isa pxitcllandmarks ] ==1 && $landmarkeditor !=0 } {
+	catch { $electrodeeditor HideWindow }
+	$landmarkeditor ShowWindow	
+	$landmarkeditor TreeEditLandmarks $sur $datatree $node
+    }
+
+    if { [ $sur isa pxitclelectrodemultigrid ] ==1 && $electrodeeditor !=0 } {
+	catch { $landmarkeditor HideWindow }
+	$electrodeeditor ShowWindow	
+	$electrodeeditor TreeEditGrids $sur $datatree $node
+    }
+}
+# -----------------------------------------------------------------------
+# Data Management sur is electodes/surface/landmarks (actor!)
+itcl::body bis_viewer::UpdatePolygonalObject {  sur attr { updisplay 1 } } {
+
+    return [ $bis_polygonalobjectmanager UpdateSameObject $sur $attr $updisplay ]
+}
+
+
+
+
+itcl::body bis_viewer::AddPolygonalObject {  sur { linked 0 } { attr "" } } {
+
+    set d [ $currentimage GetImageSize ]
+    if { $d == 1 } {
+	# If we don't have an image, create a simple one and hide it such
+	# that the viewer will work ............
+	set obj [ $sur GetObject ]
+	if { [ $obj IsA "vtkPolyDataSource" ] } {
+	    $obj Update
+	    set obj [ $obj GetOutput ]
+	}
+	set bounds [ $obj GetBounds ]
+	for { set i 0 } { $i <=2 } { incr i } {
+	    set m [ lindex $bounds [ expr 2*$i +1 ]]
+	    set s($i) [ expr $m*1.2/10.0 ]
+	    if { $s($i) < 1.0 } {
+		set s($i) 1.0
+	    }
+	}
+
+	# Create New base Image
+	set itclimg [ [ pxitclimage \#auto ] GetThisPointer ]
+	set img  [ $itclimg GetImage ]
+	$img SetDimensions 10 10 10
+	$img SetSpacing  $s(0) $s(1) $s(2)
+	$img AllocateScalars
+	[ [ $img GetPointData  ] GetScalars ] FillComponent 0  1.0
+	[ [ $img GetPointData  ] GetScalars ] SetComponent 99  0 2.0
+	[ [ $img GetPointData  ] GetScalars ] SetComponent 0 0 0.0
+	$this SetImage $itclimg
+	itcl::delete object $itclimg
+
+	if { [ $vtk_viewer IsA   "vtkpxGUIOrthogonalViewer" ] } {
+	    $vtk_viewer SetDisplayMode3DIfNeeded
+	    $vtk_viewer SetDisplay3DMode 0
+	}
+    }
+
+    $bis_polygonalobjectmanager AddObject $sur $linked $attr
+    set v [ winfo parent [  $this GetBaseWidget ] ]
+    catch { wm deiconify $v }
+
+}
+
+itcl::body bis_viewer::AddOrReplacePolygonalObject {  sur { linked 0 } { attr "" } } {
+
+    set d [ $currentimage GetImageSize ]
+    if { $d == 1 } {
+	return [ $this AddPolygonalObject $sur $linked $attr ]
+    }
+
+    $bis_polygonalobjectmanager AddOrReplaceObject $sur $linked $attr
+    set v [ winfo parent [  $this GetBaseWidget ] ]
+    catch { wm deiconify $v }
+
+}
+
+
+# -------------------------------------------------------------------------------------
+itcl::body bis_viewer::RemovePolygonalObject { sur } {
+    # for later
+    $bis_polygonalobjectmanager RemoveObject $sur
+}
+
+
+
+
+# -------------------------------------------------------------------------------------
+itcl::body bis_viewer::SetSnapshotResolution { mode } {
+
+    if { $vtk_viewer == 0 } {	return 0    }
+    if { $mode == -1 } {
+	set mode 1
+	if { $guiparam($this,snapshotresdlg)  == 0 } { 
+	    set tb [ iwidgets::selectiondialog ${basewidget}.[ pxvtable::vnewobj ] \
+			 -childsitepos w -title "Set Viewer Snapshot Resolution" \
+			 -itemslabel "Resolution Levels" -modality application ]
+	    $tb configure -height 250 -width 250
+
+	    $tb insert items end  Low
+	    $tb insert items end  Medium
+	    $tb insert items end  High
+	    $tb insert items end  VeryHigh
+
+	    $tb hide Apply
+	    $tb buttonconfigure OK -text "Set Resolution"
+	    #	    [ $tb component selectionbox ]  selectitem 0
+	    set guiparam($this,snapshotresdlg) $tb
+	    update idletasks
+	}
+
+	if { [$guiparam($this,snapshotresdlg) activate ] } {
+	    set tlist "Low Medium High VeryHigh"
+	    set tval  [ $guiparam($this,snapshotresdlg) get ]
+	    set mode [ expr 1 + [ lsearch -exact $tlist $tval ] ]
+	} 
+    }
+    set md $mode
+    catch {  set md [ expr int($mode) ] }
+    if { $md < 1 } { set md 1 } 
+    if { $md > 4 } { set md 4 } 
+
+    $vtk_viewer SetMagnificationFactor $md
+    puts stderr "Setting Magn = $md"
+    return $md
+}
+
+# -----------------------------------------------------------------------------
+itcl::body bis_viewer::SetTraceMode { enablevolume { size 0 } { weightedfactor 0 } } {
+
+    if { $vtk_viewer == 0 } {	return 0    }
+    if { [ $vtk_viewer IsA vtkpxGUIOrthogonalViewer ] == 0 } { return 0 }
+
+    if { $enablevolume == -1 } {
+	if { $guiparam($this,tracedialog)  == 0 } { 
+
+	    set tb [ iwidgets::dialog ${basewidget}.[ pxvtable::vnewobj ] \
+			 -title "Set 3D Tracing Parameters" \
+			 -modality application ]
+	    $tb configure -height 200 -width 200
+
+	    set guiparam($this,tracedialog) $tb
+	    set guiparam($this,volumetrace) 1
+	    set guiparam($this,volumevoi)   0
+	    set guiparam($this,volumemode)  0
+
+	    set cs [ $tb childsite ]
+
+	    checkbutton $cs.cb 	-text "Volume Trace" \
+		-variable [ itcl::scope guiparam($this,volumetrace) ] -indicatoron 1
+
+
+	    iwidgets::spinint $cs.cc \
+		-labeltext "VOI Size: " \
+		-width 4 \
+		-range { 0 20 } \
+		
+	    $cs.cc insert 0 0
+	    set guiparam($this,volumevoispin) $cs.cc
+
+	    
+	    checkbutton $cs.cd 	-text "Weighted VOI" \
+		-variable [ itcl::scope guiparam($this,volumemode) ] -indicatoron 1
+	    
+	    grid $cs.cb -row 0 -column 0
+	    grid $cs.cc -row 1 -column 0
+	    grid $cs.cd -row 2 -column 0
+	    $tb hide Apply
+	    $tb hide Help
+	    update idletasks
+	}
+	
+	if { [$guiparam($this,tracedialog) activate ] } {
+	    set guiparam($this,volumevoi)   [  $guiparam($this,volumevoispin)  get ]
+	}
+    } else {
+	set guiparam($this,volumetrace) [ expr $enablevolume > 0 ]
+	set guiparam($this,volumevoi) $size
+	set guiparam($this,volumemode) [ expr $weightedfactor > 0 ]
+    }
+    
+    if { $guiparam($this,volumetrace) == 0 } {
+	$vtk_viewer SetTraceGeometry 1
+	$vtk_viewer SetTraceVolume   0
+    } else {
+	$vtk_viewer SetTraceGeometry 0
+	$vtk_viewer SetTraceVolume   1
+    }
+    
+    $vtk_viewer SetTraceVolumeVOI $guiparam($this,volumevoi)
+    $vtk_viewer SetTraceVolumeWeightedMode $guiparam($this,volumemode)
+
+}
+
+itcl::body bis_viewer::SetViewerBackground {  } {
+
+    if { $vtk_viewer == 0 } {	return 0    }
+    set rw [ $vtk_viewer GetRenderWidgetName ]
+    set renwin [ $rw GetRenderWindow ]
+    $vtk_viewer SetBackgroundColor $renwin
+}
+ 
+
+
+# ---------------------------------------------------------------------------------
+# Create GUI
+# ---------------------------------------------------------------------------------
+itcl::body bis_viewer::InitializeViewer { viewerbase } {
+
+    set vtk_viewer [ eval "$vtk_viewertype New" ]
+    catch { $vtk_viewer  SetCreateInternalEditorOn }
+    if { $enable_talaraichoption == 0 } {
+	$vtk_viewer DisableTalairachButtons
+    } else {
+	$vtk_viewer EnableTalairachButtons
+	set p2 $::pxtclvtkpxcontrib::imagedir 
+	set fname [ file join $p2 colinlookup ]
+	set tal [ vtkpxTalairachTransform [ pxvtable::vnewobj ]]
+	$tal SetColinLookupFileName $fname 0
+	set fname [ file join $p2 colin_talairach_lookup.nii.gz ]
+	$tal SetColinLookupFileName $fname 1
+	$tal Delete
+    }
+
+    if { $vtk_extratype == "single" } {
+	$vtk_viewer SetSingleSliceMode 
+	$vtk_viewer SetXYSliceOnly 
+	$vtk_viewer SetOffset 0
+    }
+
+    $vtk_viewer Initialize $viewerbase 1
+    $vtk_viewer BindMouseEvents [ $vtk_viewer GetRenderWidgetName ] "$this HandleMouseEvent" "" 
+    $vtk_viewer SetCoordinatesChangeCallback "$this HandleCoordinatesChangeEvent" 
+    $vtk_viewer SetEnableCoordinatesChangeCallback 1
+
+    if { [ $vtk_viewer IsA "vtkpxGUI4DOrthogonalViewer" ] == 1  } {
+	set cn [ $vtk_viewer InitializeMovieControl $w 0 ]
+	eval "bind all <Control-m> { wm deiconify $cn} "
+    }
+    
+    return $viewerbase
+}
+
+# ---------------------------------------------------------------------------
+itcl::body bis_viewer::AddToMenu { viewm } {
+
+    eval "$viewm add command -label \"Surface Manager\" -command { $bis_polygonalobjectmanager ShowWindow Server } "
+    $viewm add separator
+    eval "$viewm add command -label \"Set Viewer Background Delete\"   -command { $this SetViewerBackground } "
+    eval "$viewm add command -label \"Set Viewer Snapshot Resolution\"   -command { $this SetSnapshotResolution -1 } "
+    eval "$viewm add command -label \"Set 3D Tracing Parameters\"   -command { $this SetTraceMode -1 } "
+
+    if { $animationgadget != 0 } {
+	$viewm add separator
+	eval "$viewm add command -label \"Show Viewer Controls Tool\" -command { [ $vtk_viewer GetRenderer 3 ] ShowCameraControls } "
+	eval "$viewm add command -label \"Show Animation Tool\" -command { $animationgadget ShowWindow } "
+    }
+
+    if { $atlastool != 0 } {
+	$viewm add separator
+	eval "$viewm add command -label \"Show Yale Brodmann Atlas Tools\" -command { $atlastool ShowGadget yale } "
+	eval "$viewm add command -label \"Show WFU Atlas Tool\" -command { $atlastool ShowGadget wfu } "
+    }
+
+
+    if { $landmarkeditor !=0 } {
+	eval "$viewm add command -label \"Show Landmark Editor\" -command { catch { $electrodeeditor HideWindow };$landmarkeditor ShowWindow } "
+    }
+
+    if { $electrodeeditor !=0 } {
+	eval "$viewm add command -label \"Show ElectrodeEditor\" -command { catch { $landmarkeditor HideWindow }; $electrodeeditor ShowWindow } "
+    }
+
+
+
+    if { $vvlinkgadget !=0 } {
+	$viewm add separator
+	eval "$viewm add command -label \"VVLink Control\" -command { $vvlinkgadget ShowWindow Server } "
+    }
+
+    if { $openigtlinkgadget !=0 } {
+	eval "$viewm add command -label \"OpenIGTLink Control\" -command { $openigtlinkgadget ShowWindow Server } "
+    }
+	
+}
+
+# ---------------------------------------------------------------------------
+itcl::body bis_viewer::InitializeToolbar { toolbase } {
+
+    set tb [ iwidgets::toolbar $toolbase.[ pxvtable::vnewobj ] \
+		 -balloondelay1 500 \
+		 -balloondelay2 50 \
+		 -orient horizontal \
+		 -font { helevetica 9 }]
+
+    pack $tb -side top -expand false -fill x 
+    
+    eval "$tb add button sur -height 1 -balloonstr \"Surface Manager\" -command { $bis_polygonalobjectmanager ShowWindow Server } -text \"Surfaces\" "
+    eval "$tb add button cl -height 1 -balloonstr \"Set Viewer Background Delete\"   -command { $this SetViewerBackground } -text \"ViewerBg\""
+    eval "$tb add button cv -height 1 -balloonstr \"Set Viewer Snapshot Resolution\"   -command { $this SetSnapshotResolution -1 } -text \"Resol\""
+    eval "$tb add button cvv -height 1 -balloonstr \"Set 3D Tracing Parameters\"   -command { $this SetTraceMode -1 } -text \"3D Trace\""
+
+    if { $animationgadget != 0 } {
+	eval "$tb add button vc -height 1 -balloonstr \"Show Viewer Controls Tool\" -command { [ $vtk_viewer GetRenderer 3 ] ShowCameraControls } -text \"3DControls\" "	
+	eval "$tb add button an -height 1 -balloonstr \"Show Animation Tool\" -command { $animationgadget ShowWindow } -text \"Animation\" "
+    }
+
+    if { $atlastool != 0 } {
+	eval "$tb add button atb -height 1 -balloonstr \"Show Yale Brodmann Atlas Tools\" -command { $atlastool ShowGadget yale } -text \"Brodmann\" "
+	eval "$tb add button atw -height 1 -balloonstr \"Show WFU Atlas Tool\" -command { $atlastool ShowGadget wfu } -text \"WFU\" "
+    }
+
+    if { $landmarkeditor !=0 } {
+	eval "$tb add button le -height 1 -balloonstr \"Show Landmark Editor\" -command { catch { $electrodeeditor HideWindow }; $landmarkeditor ShowWindow } -text \"LE\" "
+    }
+
+    if { $electrodeeditor !=0 } {
+	eval "$tb add button ee -height 1 -balloonstr \"Show Electrode Editor\" -command { catch { $landmarkeditor HideWindow }; $electrodeeditor ShowWindow } -text \"EE\" "
+    }
+
+    if { $vvlinkgadget !=0 } {
+	eval "$tb add button vvl -height 1 -balloonstr \"VVLink Control\" -command { $vvlinkgadget ShowWindow } -text \"VVLink\" "
+    }
+
+    if { $openigtlinkgadget !=0 } {
+	eval "$tb add button openigtl -height 1 -balloonstr \"OpenIGTLink Control\" -command { $openigtlinkgadget ShowWindow Server } -text \"OpenIGT\" "
+    }
+	
+}
+
+itcl::body bis_viewer::InitializeTools   { toolbase } {
+
+    global pxtcl_pref_array
+
+    set obj [ [ bis_polygonaldisplaymanager \#auto $this ] GetThisPointer ]
+    $obj CreateGUI $toolbase.[pxvtable::vnewobj ] 1 
+    set  bis_polygonalobjectmanager $obj
+
+
+    if { $enable_animationgadget == 1 && [ $vtk_viewer IsA "vtkpxGUIOrthogonalViewer" ] == 1 } {
+	package require pxitclanimationgadget 1.0
+	set animationgadget [ [ pxitclanimationgadget \#auto $this ] GetThisPointer ]
+	$animationgadget Initialize ${toolbase}.[ pxvtable::vnewobj ]
+	$animationgadget SetViewer $vtk_viewer
+    }
+
+
+    if { $enable_talaraichoption == 1 && $enable_atlastools == 1 && $atlastool == 0} {
+	package require pxitclatlasgadget 1.0
+	set atlastool [ pxitclatlasgadget \#auto $this ]
+	set w ${toolbase}.${atlastool}
+	set atlastool [ $atlastool GetThisPointer ]
+	$atlastool Initialize $w
+    }
+
+
+    if { $enable_vvlinkgadget == 1 && $pxtcl_pref_array(VectorVisionLink)=="Enabled" } {
+	package require pxitclvvlinkgadget 1.0
+	set vvlinkgadget [ pxitclvvlinkgadget  \#auto $this ]
+	set w ${toolbase}.${vvlinkgadget}
+	set vvlinkgadget [ $vvlinkgadget GetThisPointer ]
+	$vvlinkgadget Initialize $w $vtk_viewer
+    }
+
+
+    if { $enable_openigtlinkgadget == 1 &&  $pxtcl_pref_array(OpenIGTLink)=="Enabled" } {
+	package require pxitclopenigtlinkgadget 1.0
+	set openigtlinkgadget [ pxitclopenigtlinkgadget  \#auto $this ]
+	set w ${toolbase}.${openigtlinkgadget}
+	set openigtlinkgadget [ $openigtlinkgadget GetThisPointer ]
+	$openigtlinkgadget Initialize $w $vtk_viewer
+    }
+
+    if { $enable_landmarkeditor == 1 } { 
+	package require bis_landmarkeditor 1.0
+	set landmarkeditor [ [ bis_landmarkeditor \#auto $this ] GetThisPointer ]
+	set w ${toolbase}.[ pxvtable::vnewobj ]
+	$landmarkeditor Initialize $w $this
+    }
+
+
+    if { $enable_electrodeeditor == 1 } { 
+	package require bis_electrodeeditor 1.0
+	set electrodeeditor [ [ bis_electrodeeditor \#auto $this ] GetThisPointer ]
+	set w ${toolbase}.[ pxvtable::vnewobj ]
+	$electrodeeditor Initialize $w $this
+    }
+
+
+
+}
+# ---------------------------------------------------------------------
+itcl::body bis_viewer::CreateGUI { base } {
+
+    if { $basewidget !=0 } { return $basewidget }
+
+    set  basewidget $base.[pxvtable::vnewobj ]
+
+    set btf [ frame $basewidget ]
+    pack $basewidget -side top -expand true -fill both
+
+    set viewerbase   [ frame $btf.viewer1 -width 400 -height 300 ] 
+    if { $enable_toolbar > 0 } {
+	set toolbase      [ frame $btf.toolbar -height 10  ]
+	set midbase      [ frame $btf.mid1 -height 2 ]
+	pack $toolbase $midbase -side top -expand false -fill x 
+    } else {
+	set toolbase $viewerbase
+    }
+    pack $viewerbase -side top -expand true -fill both
+
+    $this InitializeViewer $viewerbase
+    $this InitializeTools $toolbase
+    if { $enable_toolbar > 0 } {
+	$this InitializeToolbar $toolbase
+    }
+
+    return $basewidget
+}
+# ---------------------------------------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    proc Test { args } {
+	puts stdout "args=$args"
+    }
+ 
+    package require vtkpxcontrib
+    wm geometry . 900x600
+    set viewbase  [ frame .v ]
+    pack $viewbase -side left -expand true -fill both
+
+    set bis_viewer [ [ bis_viewer \#auto ] GetThisPointer ]
+    #    $bis_viewer SetViewerType singleslice
+    $bis_viewer configure -enable_openigtlinkgadget 1
+    $bis_viewer configure -enable_landmarkeditor 1
+    $bis_viewer configure -enable_electrodeeditor 1
+    $bis_viewer CreateGUI $viewbase 
+    wm title . "Test Viewer"
+
+
+    set img [ pxitclimage \#auto ]
+    $img Load [ lindex $argv 0 ]
+    $bis_viewer SetImage $img
+    $bis_viewer SetImageColormapMode 0
+
+    
+    set dual 2
+
+    if { $dual == 1 } {
+	$bis_viewer AddCursorNotifier "Test" "Cursor"
+	$bis_viewer AddImageNotifier "Test" "Image"
+
+	set viewbase2  [ frame .v2 ]
+	pack  $viewbase2 -side left -expand true -fill both
+
+	set bis_viewer2 [ [ bis_viewer \#auto ] GetThisPointer ]
+	$bis_viewer2 CreateGUI $viewbase2 
+	$bis_viewer2 SetImage $img
+	$bis_viewer2 SetImageColormapMode -1
+	$bis_viewer  SetLinkedCursorViewer  $bis_viewer2 
+	$bis_viewer2 SetLinkedCursorViewer  $bis_viewer 
+    } elseif { $dual == 2 } {
+	vtkSphereSource r
+	r SetRadius 50
+	r Update
+	set s1 [ [ pxitclsurface \#auto ] GetThisPointer ]
+	$s1 ShallowCopySurface [ r GetOutput ]
+	
+	set l1 [ [ pxitcllandmarks \#auto ] GetThisPointer ]
+	$l1 Load /agrino/xenios/vtk5_src/bioimagesuite/images/seed1.land
+		
+
+	$bis_viewer AddPolygonalObject $s1
+	$bis_viewer AddPolygonalObject [ [ pxitclsurface \#auto ] GetThisPointer ] 
+	$bis_viewer AddPolygonalObject $l1
+	$bis_viewer AddPolygonalObject [ [ pxitclelectrodemultigrid \#auto ] GetThisPointer ]
+    }
+
+} 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_visualizetransformation.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_visualizetransformation.tcl
new file mode 100755
index 0000000..5004010
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_visualizetransformation.tcl
@@ -0,0 +1,169 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_dualimagetransformationalgorithm 1.0
+package provide bis_visualizetransformation 1.0
+
+#
+# blend image
+#
+
+itcl::class bis_visualizetransformation {
+
+    inherit bis_dualimagetransformationalgorithm
+
+     constructor { } {
+	 $this Initialize
+     }
+
+    public method Initialize { }
+    public method Execute { }
+    public method GetGUIName { } { return "Visualize Transformation"}
+
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_visualizetransformation::Initialize { } {
+
+    PrintDebug "bis_visualizetransformation::Initialize" 
+
+    set options {
+	{ sp "Spacing (in voxels) for lines" "Grid Spacing"  integer 8 { 4 32 }   1 }
+	{ zsp "Spacing (in voxels) for lines in z direction" "Grid Z-Spacing"  integer 8 { 4 32 }   1 }
+	{ opa "Grid Opacity" "Opacity"  real 0.5 { 0.0 1.0 }   2 }
+	{ int "Grid Intensity" "Intensity"  real 0.9 { 0.0 5.0 }   -3 }
+    }
+	
+    set defaultsuffix { "_vgrid" }
+    
+    set scriptname bis_visualizetransformation
+    set completionstatus "Done"
+    #
+    #document
+    #
+
+    set category "Registration"
+    set description "Creates a grid visualization of a transformation"
+    set description2 "a useful check of the quality of the transformations"
+    set backwardcompatibility "none"
+    set authors "hirohito.okuda at yale.edu, xenophon.papademetris at yale.edu."
+
+    $this InitializeDualImageTransformationAlgorithm
+}
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_visualizetransformation::Execute {  } {
+
+    set gridspacing  [ $OptionsArray(sp) GetValue ]
+    set gridspacing2 [ $OptionsArray(zsp) GetValue ]
+    set gridopacity [ $OptionsArray(opa) GetValue ]
+    set gridintensity [ $OptionsArray(int) GetValue ]
+
+
+    set image_trn [  [ $this GetSecondInput ] GetImage ]
+    set image_ref  [ [ $this GetInput ]  GetImage ]
+    set xform [ [ $this GetTransformation ] GetObject ]
+
+    scan [ $image_trn GetExtent ]  "%d %d %d %d %d %d" e1 e2 e3 e4 e5 e6
+    scan [ $image_trn GetSpacing ] "%f %f %f" s1 s2 s3
+    scan [ $image_trn GetOrigin ]  "%f %f %f" o1 o2 o3
+    set range [ lindex [[ [  $image_ref GetPointData ] GetScalars ] GetRange ] 1]
+    
+    set grdsource [ vtkImageGridSource [ pxvtable::vnewobj ]]
+    $grdsource SetDataExtent  $e1 $e2 $e3 $e4 $e5 $e6
+    $grdsource SetDataSpacing $s1 $s2 $s3 
+    $grdsource SetDataOrigin  $o1 $o2 $o3 
+    $grdsource SetGridSpacing $gridspacing $gridspacing $gridspacing2
+    $grdsource SetDataScalarType [ $image_trn GetScalarType ]
+    $grdsource SetLineValue [ expr $range * $gridintensity ]
+    $grdsource Update
+
+    set blendCreator [ vtkImageBlend [ pxvtable::vnewobj ]]
+    $blendCreator AddInput $image_trn 
+    $blendCreator AddInput [ $grdsource GetOutput ]
+    $blendCreator SetOpacity 1 $gridopacity
+    $blendCreator SetOpacity 0 [ expr 1.0 -  $gridopacity ]
+    SetFilterCallbacks $blendCreator "Blending Grid Images"
+    $blendCreator Update
+    
+    set reslice [  vtkbisImageReslice [ pxvtable::vnewobj ]]
+    $reslice OptimizationOff
+    $reslice SetInterpolationMode 0
+    $reslice SetBackgroundLevel 0.0
+    $reslice SetInformationInput $image_ref
+    $reslice SetResliceTransform $xform
+    $reslice SetInput [ $blendCreator GetOutput ]
+    SetFilterCallbacks $reslice "Reslicing Grid Source"
+    $reslice Update
+
+    [ $OutputsArray(output_image) GetObject ] ShallowCopyImage [ $reslice GetOutput ]
+    # Output orientation etc. is same as input
+    set outimage [ $this GetOutput ] 
+    set pimage   [ $this GetSecondInput ] 
+
+    $outimage CopyImageHeader [ $pimage GetImageHeader ]
+
+    set comment [ $this GetCommandLine full ]
+    [ $outimage GetImageHeader ] AddComment "$comment" 0
+
+
+    $blendCreator Delete
+    $reslice Delete
+    $grdsource Delete
+    return 1
+ }
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_visualizetransformation.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+   
+
+    set alg [bis_visualizetransformation [pxvtable::vnewobj]]
+    $alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_xmlalgorithm.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_xmlalgorithm.tcl
new file mode 100644
index 0000000..6f1daa9
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_xmlalgorithm.tcl
@@ -0,0 +1,641 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package provide bis_xmlalgorithm 1.0
+package require bis_algorithm 1.0
+
+
+itcl::class bis_xmlalgorithm {
+
+    inherit bis_algorithm
+
+     constructor { xmlfile } {	 $this Initialize $xmlfile }
+
+    public method Initialize { xmlfile }
+    public method Execute { }
+    public method ExecuteDone { args }
+    public method ExecuteCallback { args }
+    public method GetGUIName { } { return "Pl:$algname" }
+
+    # Parse XML stuff
+    protected method InitializeFromXML { xmlfile }
+    protected method InitializeFromSlicerXML { xmlelement }
+    protected method InitializeFromLONIXML { xmlelement }
+
+
+    # XML Basics
+    protected method CleanString { line } 
+    protected method PrintElement { elem n } 
+    protected method ParseSlicerParameterTags { elem priority advanced } 
+    protected method ParseSlicerContraints { nd ptype  }
+
+    protected method SaveObject { obj index dir } 
+    protected method CreateFilenameForObject { obj index dir } 
+    protected method CreateExtensionForObject { obj } 
+
+
+    # basic stuff
+    protected variable algname "XML"
+    protected variable commandline ""
+    protected variable slicertaglist ""
+    protected variable slicermaparray
+    protected variable commandlineparameters
+    protected variable commandlineobjects
+    protected variable commandlinechannels
+    protected variable inpxmlfile
+    protected variable algdone 0
+    protected variable inputpipe 0
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_xmlalgorithm::Initialize { xmlfile } {
+
+    PrintDebug "bis_xmlalgorithm::Initialize" 
+    
+    #commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+    set inputs { }
+    set outputs {  }
+    set options {    }
+
+    set defaultsuffix { "_sm" }
+    
+    set scriptname bis_xmlalgorithm
+    set completionstatus "Done"
+    set forceguimode 1
+
+    #
+    #document
+    #
+    
+    set description "Smoothes an image with a specific gaussian kernel."
+    set description2 "Smoothing kernel size blursigma (in mm by default ) represents the FWHM filter size."
+    set backwardcompatibility "Reimplemented from pxmat_xmlalgorithm.tcl. unit and radius options are  added. Multiple image processing eliminated,which will be recovered upon request. "
+    set authors ""
+    set category ""
+    
+
+    set slicertaglist { list integer  float  double  boolean  string  integer-vector  float-vector  double-vector  string-vector  integer-enumeration  float-enumeration  double-enumeration  string-enumeration  file  directory  image  geometry  point  region }
+    set slicermaparray(integer) integer
+    set slicermaparray(float)   real
+    set slicermaparray(double)   real
+    set slicermaparray(boolean) boolean
+    set slicermaparray(string) string
+    set slicermaparray(integer-vector) string
+    set slicermaparray(float-vector) string
+    set slicermaparray(double-vector) string
+    set slicermaparray(string-vector) string
+    set slicermaparray(integer-enumeration) listofvalues
+    set slicermaparray(float-enumeration) listofvalues
+    set slicermaparray(double-enumeration) listofvalues
+    set slicermaparray(string-enumeration) listofvalues
+    set slicermaparray(file) { filename readfile allfiles }
+    set slicermaparray(directory)  { filename directory }
+    set slicermaparray(image)      { object pxitclimage }
+    set slicermaparray(geometry)   { object pxitclsurface }
+    set slicermaparray(point)  string
+    set slicermaparray(region)  filename
+
+
+    set inputs ""
+    set outputs ""
+    set options ""
+    $this InitializeFromXML $xmlfile
+    lappend options [ list tmpdir  "Specify the output directory for temporary files" "Temp Directory" { filename directory 40 } "/tmp" "" 1 ]
+    lappend options [ list keeptmp  "Keep  the output directory and temporary files" "Keep Temp" { boolean } 0 { 0 1 }  -1 ]
+    lappend options [ list cmd      "Executable name" "Exec" { filename readfile } "" { allfiles }  -2 ]
+    
+    $this AddDefaultOptions
+    set category "Plugin"
+
+    set inpxmlfile $xmlfile
+
+}
+# -----------------------------------------------------------------------------------------
+# -------------------------------------------------------------------------------
+#  Parse either Slicer3 or LONI pipeline xml file
+# -------------------------------------------------------------------------------
+itcl::body bis_xmlalgorithm::CleanString { line } {
+    set line [ string trim $line ]
+    regsub -all "\n" $line " " line
+    regsub -all "\t" $line " " line
+    regsub -all " +" $line " " line
+    regsub -all " " $line "_" line
+    return $line
+}
+# ----------------------------------------------------------------------------------
+itcl::body bis_xmlalgorithm::PrintElement { elem n } {
+    for { set i 0 } { $i < $n } { incr i } {
+	puts -nonewline stdout "   "
+    }
+
+    puts -nonewline stdout "[ $elem GetName ]:\"[ CleanString [ $elem GetCharacterData ]]\""
+    if { [ $elem GetNumberOfAttributes ] } { 
+	puts -nonewline "attr=("
+	for { set i 0 } { $i < [ $elem GetNumberOfAttributes ] } { incr i } {
+	    puts -nonewline stdout "[ $elem GetAttributeName $i ]:\"[ CleanString [ $elem GetAttributeValue $i]]\" "
+	}
+	puts -nonewline ")"
+    }
+
+
+    for { set j 0 } { $j < [ $elem GetNumberOfNestedElements ] } { incr j } {
+	set ok [ PrintElement [ $elem GetNestedElement $j ] [ expr $n +1 ] ]
+    }
+}
+
+# ----------------------------------------------------------------------------------
+
+itcl::body bis_xmlalgorithm::InitializeFromXML { xmlfile } {
+
+    set parse [ vtkXMLDataParser New ]
+    $parse SetFileName $xmlfile
+    $parse SetIgnoreCharacterData 0
+    $parse Parse
+
+    set elem [ $parse GetRootElement ]
+#    PrintElement $elem 0
+   
+    set ok 0
+
+    if { $elem != "" } {
+	set nm [ $elem GetName ]
+	if { $nm == "executable" } {
+	    set ok [ $this InitializeFromSlicerXML $elem ]
+	} elseif { $nm == "pipeline" } {
+	    set ok [ $this InitializeFromLONIXML $elem ]
+	}
+    }
+    $parse Delete
+    return $ok
+}
+# ---------------------------------------------------------------------
+itcl::body bis_xmlalgorithm::ParseSlicerContraints { elem ptype  } {
+
+    if { $ptype != "integer" && $ptype != "real"  } {
+	return 0
+    }
+
+    set minv ""
+    set maxv ""
+
+    for { set j 0 } { $j < [ $elem GetNumberOfNestedElements ] } { incr j } {
+	set nd [ $elem GetNestedElement $j ] 
+	set nm [ $nd GetName ]
+	if { $nm == "minimum" } { set minv [ $nd GetCharacterData ] }
+	if { $nm == "maximum" } { set maxv [ $nd GetCharacterData ] }
+    }
+
+    return [ list $minv $maxv ]
+}
+
+# ----------------------------------------------------------------------
+
+itcl::body bis_xmlalgorithm::ParseSlicerParameterTags { elem thispriority advanced } {
+
+    set n [ $elem GetName ]
+    set ind [ lsearch $slicertaglist $n ]
+    if { $ind < 0 } { 
+	if { $n == "label" } {
+	    return [ list 0 [ $elem GetCharacterData ]  [ $elem GetName ] ]
+	} 
+	return [ list 0 "" [ $elem GetName ] ]
+    }
+
+    set tp $slicermaparray($n)
+    set n [ lindex $tp 0 ]
+    if { $n != "object" } {
+
+	set p_type $tp
+	if { [ llength $tp ] > 1 } {
+	    set p_type [ list [ lindex $tp 0 ] [ lindex $tp 1 ] ]
+	}
+	
+	if { [ llength $tp ] == 3 } {
+	    set p_valrange [ lindex $tp 2 ]
+	    set p_defaultvalue ""
+	}
+
+	set tval [ $elem GetAttribute fileExtensions ]
+	if { $tval != "" } {
+	    regsub -all "," $tval " " tval
+	    set p_valrange [ list "Prefered Files" "{ $tval }" ]
+	}
+	
+    }
+
+    set p_valrange ""
+    set p_shortdescription ""
+    set p_commandswitch ""
+    set p_commandswitchshort ""
+    set p_description ""
+    set p_defaultvalue ""
+    set p_valrange ""
+    set p_channel ""
+    set p_extension ""
+    set p_index 0
+    set numinputs  [ llength $inputs ] 
+    set numoutputs [ llength $outputs ] 
+
+    set addedoption 0
+
+    for { set j 0 } { $j < [ $elem GetNumberOfNestedElements ] } { incr j } {
+	set nd [ $elem GetNestedElement $j ] 
+	set nm [ $nd GetName ]
+	switch -exact $nm {
+	    "label" {      set p_shortdescription [ $nd GetCharacterData ] }
+	    "longflag" {    set p_commandswitch   [ $nd GetCharacterData ] }
+	    "flag" {    set p_commandswitchshort   [ $nd GetCharacterData ] }
+	    "description" { set p_description     [ $nd GetCharacterData ] } 
+	    "default"     { set p_defaultvalue    [ $nd GetCharacterData ] } 
+	    "constraints" { set p_valrange [ $this ParseSlicerContraints $nd $p_type ] }
+	    "element"     { if { $p_type == "listofvalues" } { lappend p_valrange [ $nd GetCharacterData ] } }
+	    "channel"     { set p_channel         [ $nd GetCharacterData ] }
+	    "index"       { set p_index           [ $nd GetCharacterData ] }
+	}
+    }
+
+    set cname ""
+    if { $p_commandswitch != "" } {
+	set cname $p_commandswitch
+    } else {
+	set cname $p_commandswitchshort
+    }
+    
+
+    if { $n != "object" } {
+	set paramname "param$thispriority"
+
+	if { $cname != "" } {
+	    if { $advanced > 0 } {
+		set thispriority [ expr - $thispriority ]
+	    }
+	    set plist [ list $paramname  $p_description $p_shortdescription  $p_type  $p_defaultvalue  $p_valrange  $thispriority  ]
+	    lappend options $plist
+	    set commandlineparameters($paramname) $cname
+	    set addedoption 1
+	} else {
+	    puts stderr "Skipping parameters  $p_description"
+	}
+    } else {
+	if { $p_channel == "input" } {
+	    incr numinputs
+	    set cflag inp$numinputs
+	    set plist  [ list $cflag "$p_description" [ lindex $tp 1 ] "$p_defaultvalue"  $numinputs ]
+	    if { $cname != "" } {
+		set commandlineobjects($cflag) [ list $cname input ]
+		lappend inputs $plist
+	    } elseif { $p_index !="" } {
+		set commandlinechannels(${p_index}) [ list $cflag input ]
+		lappend inputs $plist
+	    } else {
+		puts stderr "Skipping input  $p_description"
+	    }
+
+	} else {
+	    incr numoutputs
+	    set cflag out$numoutputs
+	    set plist  [ list  $cflag "$p_description" [ lindex $tp 1 ] "$p_defaultvalue"  $numoutputs ]
+	    if { $cname != "" } {
+		set commandlineobjects($cflag) [ list $cname output ]
+		lappend outputs $plist
+	    } elseif { $p_index !="" } {
+		set commandlinechannels(${p_index}) [ list $cflag output ]
+		lappend outputs $plist
+	    } else {
+		puts stderr "Skipping input  $p_description"
+	    }
+	}
+    }
+
+    return [ list $addedoption "" [ $elem GetName ] $thispriority ]
+
+}
+# ---------------------------------------------------------------------
+
+itcl::body bis_xmlalgorithm::InitializeFromSlicerXML { xmlelement } {
+
+#    puts stderr "In Slicer"
+    set elem [ $xmlelement LookupElementWithName "title" ]
+    if { $elem !="" } {    set algname [ string trim [ $elem GetCharacterData ] ]}
+    
+    set elem [ $xmlelement LookupElementWithName "description" ]
+    if { $elem !="" } {    set description [ $elem GetCharacterData ] }
+
+    set lname { version documentation_url license contributor }
+    for { set i 0 } { $i < [ llength $lname ] } { incr i } {
+	set elem [ $xmlelement LookupElementWithName [ lindex $lname $i ] ]
+	if { $elem !="" } {    append description2 "[lindex $lname $i]:[ $elem GetCharacterData ] " }
+    }
+	
+    set plist ""
+    for { set j 0 } { $j < [ $xmlelement GetNumberOfNestedElements ] } { incr j } {
+	set elem [ $xmlelement GetNestedElement $j ] 
+	if { [ $elem GetName ] == "parameters" } {
+	    lappend plist $elem
+	}
+    }
+
+    lappend options [ list about  "$description"  "Name"  { comment "" 35 } $algname $algname 0 ]
+    lappend options [ list about2 "$description $description2"  ""  { comment "" 100 } "$description $description2" "" 1 ]
+#    lappend options [ list guicmt$pelement "Parameter group $labelname"  "Parameter Set"  comment $labelname $labelname $labelpriority ]
+#    lappend options [ list guicmt$pelement "Parameter group $labelname"  "Parameter Set"  comment $labelname $labelname $labelpriority ]
+
+    set thispriority 10
+
+    for { set pelement 0 } { $pelement <  [ llength $plist ] } { incr pelement } {
+	set  nd [ lindex $plist $pelement ]
+	set labelname 0
+	set labelpriority $thispriority
+	set numadded 0
+	incr thispriority
+	set advanced 0
+	if { [ $nd GetAttribute "advanced" ] == "true" } {
+	    set advanced 1
+	}
+
+	for { set j 0 } { $j < [ $nd GetNumberOfNestedElements ] } { incr j } {
+	    set lst [ $this ParseSlicerParameterTags [ $nd GetNestedElement $j ]   $thispriority   $advanced ]
+	    #	    puts stderr $lst
+	    set v [ lindex $lst 0 ]
+	    if { $v > 0 } {
+		incr numadded
+		incr thispriority 
+	    }
+	    if { [ lindex $lst 1 ] != "" } {
+		set labelname [ lindex $lst 1 ]
+	    }
+	}
+	if { $numadded > 0 && $labelname != "" } {
+	    if { $advanced > 0 } {
+		set labelpriority [ expr  -$labelpriority ]
+	    } 
+	    set n [ $nd GetAttribute advanced ]
+	    lappend options [ list guicmt$pelement "Parameter group $labelname $n"  "Parameter Set"  comment $labelname $labelname $labelpriority ]
+	}
+    }
+    #    foreach inp $inputs { puts stderr "Input=$inp" }
+    #    puts stderr ""
+    #    foreach inp $outputs { puts stderr "Output=$inp" }
+    #    puts stderr ""
+    #    foreach inp $options { puts stderr "Option=$inp" }
+    
+}
+ 
+# ----------------------------------------------------------------------
+
+itcl::body bis_xmlalgorithm::InitializeFromLONIXML { xmlelement } {
+
+    #    puts stderr "In LONI"
+    set elem [ $xmlelement LookupElementWithName "module" ]
+    
+    PrintElement $elem 0
+    return 1
+}
+
+
+
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+itcl::body bis_xmlalgorithm::SaveObject { obj index odir }  {
+
+    set oldfname [ $obj cget -filename ]
+    set f [ $this CreateFilenameForObject $obj $index $odir ]
+    $obj Save  $f
+    $obj configure -filename $oldfname
+    return $f
+
+}
+# ----------------------------------------------------------------------------------------
+itcl::body bis_xmlalgorithm::CreateFilenameForObject { obj index odir }  {
+
+    set ext [ $this CreateExtensionForObject $obj ]
+    set name [ file join $odir object_${index}$ext ]
+    $obj configure -filename $name
+    return $name
+
+}
+ 
+itcl::body bis_xmlalgorithm::CreateExtensionForObject { obj }  {
+    
+    #    puts stderr "$obj , [ $obj info class ]"
+
+    set ext ".txt"
+    switch -exact [ $obj info class ] {
+	"::pxitclimage"   { set ext ".nii.gz" }
+	"::pxitclsurface"  { set ext ".vtk" }
+    }
+
+    return $ext
+}
+# ----------------------------------------------------------------------------------------
+itcl::body bis_xmlalgorithm::Execute {  } {
+    set cmdline "[ $OptionsArray(cmd) GetValue ] "
+    set command [ file tail $cmdline ]
+
+    set names [array names commandlineparameters ]
+
+    foreach name $names { 
+	set flag $commandlineparameters($name)  
+	set val [ $OptionsArray($name) GetValue ]
+	append cmdline "$flag $val "
+    }
+
+    set names [array names commandlineobjects ]
+
+    set obase [ file join [ $OptionsArray(tmpdir) GetValue ] [ pid ]]
+    set i 0
+    set odir "${obase}_bistmp_${i}"
+    while { [ file exists $odir ] } {
+	incr i
+	set odir "${obase}_${i}"
+	
+    }
+    file mkdir $odir
+    puts  stdout "making temp directory $odir"
+
+    set usingoutputs ""
+
+    
+    set i 0
+    foreach name $names { 
+	set lst $commandlineobjects($name)  
+
+	set flag [ lindex $lst 0 ]
+	set inout [ lindex $lst 1 ]
+	if { $inout == "input" } {
+	    set val [ $this SaveObject [  $InputsArray($name)  GetObject ] $i $odir ]
+	} else {
+	    set val [ $this CreateFilenameForObject [  $OutputsArray($name)  GetObject ] [ expr $i + 100 ] $odir ]
+	    lappend usingoutputs $name
+	}
+	append cmdline "$flag $val"
+	incr i
+    }
+
+
+    set names [ array names commandlinechannels ]
+    set names [lsort -increasing  $names ]
+    for { set i 0 } { $i < [ llength $names ] } { incr i } { 
+	set name  [ lindex $names $i ]
+	set lst $commandlinechannels($name)  
+	set flag [ lindex $lst 0 ]
+	set inout [ lindex $lst 1 ]
+	puts stderr "looking at $name, $flag $inout"
+	if { $inout == "input" } {
+	    set val [ $this SaveObject [  $InputsArray($flag) GetObject ] $i $odir ]
+	} else {
+	    set val [ $this CreateFilenameForObject [  $OutputsArray($flag)  GetObject ] [ expr $i + 100 ] $odir ]
+	    lappend usingoutputs $flag
+	}
+	append cmdline "$val "
+    }
+
+
+    
+    set algdone 0
+    puts stdout "cmdline=\n$cmdline"
+
+    if { $guimode == "standalone" } {
+	wm geometry $basewidget 1280x700
+    }
+
+    set c [ file tail [ $OptionsArray(cmd) GetValue ] ]
+
+    set inputpipe 0
+    if { [catch {  set inputpipe [ open "| $cmdline 2>@1 " ] } ] } {
+	puts stderr "Error invoking $cmdline"
+	delete -force $odir
+	return 0
+    }
+
+    puts stderr "Done invoking $inputpipe"
+    fileevent $inputpipe readable [ list $this ExecuteCallback ]
+    
+    pxtkconsole
+    after 50
+    update 
+    while { $algdone == 0 } {
+	after 1000
+	update
+    }
+
+    foreach objname $usingoutputs {
+	[ $OutputsArray($objname) GetObject ] Load
+	$OutputsArray($objname) UpdateInternalGUI
+    }
+
+
+    if { [ $OptionsArray(keeptmp) GetValue ] == 0 } {
+	puts stdout "Removing directory $odir"
+	file delete -force $odir
+    }
+
+    ::pxtclutil::Info "Execution of  Plugin $command done"
+
+}
+
+itcl::body bis_xmlalgorithm::ExecuteDone { args } {
+    puts stderr "In Done ..............."
+    catch {close $inputpipe }
+    set inputpipe 0
+    set algdone 1
+}
+
+itcl::body bis_xmlalgorithm::ExecuteCallback { args } {
+
+
+    if { $inputpipe == 0 } {
+	return
+    }
+
+    if {  [eof $inputpipe ]  } {
+	return [ $this ExecuteDone ]
+    }
+
+    set ok 1
+
+    while { $ok ==1 } {
+	if { $inputpipe !=0 } {
+	    set ok [ gets $inputpipe nm ] 
+	    if { $ok } {
+		pxtkprint "$nm\n"
+		
+		set f [ string first "<filter-progress>" $nm ]
+		if { $f == 0 } {
+		    set ind [ expr [ string first ">" $nm ] +1 ]
+		    set ind2 [ expr [ string first "</filter-progress>" $nm ] -1 ]
+		    set t [ expr [ string range $nm $ind $ind2 ] ]
+		    $this ShowProgressVal Running $t 
+		}
+	    }
+	} else {
+	    set ok 0
+	}
+    }
+
+    if { $inputpipe == 0 } {
+	return
+    }
+
+    if {  [eof $inputpipe ]  } {
+	$this ExecuteDone
+    }
+
+}
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_xmlalgorithm.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    # this is essentially the main function
+
+    set alg [bis_xmlalgorithm [pxvtable::vnewobj] [ lindex $argv 0 ] ]
+    set argv [ lrange $argv 1 end ]
+    $alg MainFunction 
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_zscoretopvalue.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_zscoretopvalue.tcl
new file mode 100755
index 0000000..9ca14fa
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/bis_zscoretopvalue.tcl
@@ -0,0 +1,137 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" -- "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require bis_imagetoimagealgorithm 1.0
+package require vtkpxcontrib     1.2
+
+package provide bis_zscoretopvalue 1.0
+
+
+itcl::class bis_zscoretopvalue {
+
+	inherit bis_imagetoimagealgorithm
+
+	 constructor { } {
+	 $this Initialize
+	 }
+
+	public method Initialize { }
+	public method Execute { }
+	public method GetGUIName    { } { return "Zmap to pvalue" }
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Initialize
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_zscoretopvalue::Initialize { } {
+
+	PrintDebug "bis_zscoretopvalue::Initialize" 
+	
+	#commandswitch,description,shortdescription,optiontype,defaultvalue,valuerange,priority
+   
+	 set options {
+	{ guicmt     "Description of the filter"  "Note"  comment "Zscore to p-value" "Compute zmap to p-value"  400 }
+	}
+
+	set defaultsuffix { "_ztopvalue" }
+	
+	set completionstatus "Done"
+
+	set scriptname bis_zscoretopvalue
+
+	set category "Functional Imaging"
+	set description "Converts zmap to pvalue."
+	set description2 "Take zmap as input and output it p-value."
+	set backwardcompatibility "N/A"
+	set authors "isabella.murphy at yale.edu"
+
+	$this InitializeImageToImageAlgorithm
+
+}
+
+# -----------------------------------------------------------------------------------------
+# Execute
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_zscoretopvalue::Execute {  } {
+
+	PrintDebug "bis_zscoretopvalue::Execute"
+	
+	set con 0
+	catch {set con [ vtkbisZscoretoPvalue New ]    }
+	if { $con == 0 } {
+	pxtclvtkpxcontrib::LoadLibraries { vtkpxImagingTCL }
+	}
+	catch { $con Delete }
+	
+	set image_in    [ $InputsArray(input_image)   GetObject ]
+	
+	set calp 0
+	catch { set calp [ vtkbisZscoretoPvalue New  ] }
+	if { $calp == 0 } {
+	return 0
+	}
+	
+	$calp SetInput    [ $image_in GetObject ]
+	$this SetFilterCallbacks $calp "compute zmap to pvalue"
+	$calp Update
+	
+	set outimage [ $OutputsArray(output_image) GetObject ]
+	$outimage ShallowCopyImage [ $calp GetOutput ]
+	$outimage CopyImageHeader [ $image_in GetImageHeader ]
+	
+	set comment [ format " [ $this GetCommandLine full ]" ]
+	[ $outimage GetImageHeader ] AddComment "$comment $Log" 0
+
+	$calp Delete
+	return 1
+}
+
+
+# -----------------------------------------------------------------------------------------
+#  This checks if executable is called (in this case bis_zscoretopvalue.tcl) if it is execute
+# ----------------------------------------------------------------------------------------
+ 
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+	# this is essentially the main function
+
+	
+
+	set alg [bis_zscoretopvalue [pxvtable::vnewobj]]
+	$alg MainFunction 
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/bis_algorithm/pkgIndex.tcl b/bioimagesuite30_src/bioimagesuite/bis_algorithm/pkgIndex.tcl
new file mode 100644
index 0000000..c851cd7
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/bis_algorithm/pkgIndex.tcl
@@ -0,0 +1,298 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#
+# px libraries
+#
+package ifneeded pxitclobject            1.0 [list source [file join [file join [file join $dir ".."] base ] pxitclobject.tcl]] 
+package ifneeded vtkpxcontrib            1.2 [list source [file join [file join [file join $dir ".."] base ] vtkpxcontrib.tcl]] 
+package ifneeded pxappscommon            1.0 [list source [file join [file join [file join $dir ".."] apps ] pxappscommon.tcl]]  
+
+# -----------
+# Core Stuff
+# -----------
+package ifneeded bis_basealgorithm       1.0 [list source [file join $dir bis_basealgorithm.tcl]] 
+package ifneeded bis_algorithm           1.0 [list source [file join $dir bis_algorithm.tcl]] 
+package ifneeded bis_algorithmdbaseinterface 1.0 [list source [file join $dir bis_algorithmdbaseinterface.tcl]] 
+package ifneeded bis_option              1.0 [list source [file join $dir bis_option.tcl]] 
+package ifneeded bis_optiondialog              1.0 [list source [file join $dir bis_optiondialog.tcl]] 
+package ifneeded bis_object              1.0 [list source [file join $dir bis_object.tcl]] 
+package ifneeded bis_test                1.0 [list source [file join $dir bis_test.tcl]] 
+package ifneeded bis_util                1.0 [list source [file join $dir bis_util.tcl]] 
+package ifneeded bis_common              1.0 [list source [file join $dir bis_common.tcl]] 
+package ifneeded bis_datamanager         1.0 [list source [file join $dir bis_datamanager.tcl]] 
+package ifneeded bis_treewidget          1.0 [list source [file join $dir bis_treewidget.tcl]]
+package ifneeded bis_viewer          1.0 [list source [file join $dir bis_viewer.tcl]]
+package ifneeded bis_polygonaldisplaymanager          1.0 [list source [file join $dir bis_polygonaldisplaymanager.tcl]]
+package ifneeded bis_xmlalgorithm          1.0 [list source [file join $dir bis_xmlalgorithm.tcl]]
+package ifneeded bis_electrodeeditor          1.0 [list source [file join $dir bis_electrodeeditor.tcl]]
+package ifneeded bis_landmarkeditor          1.0 [list source [file join $dir bis_landmarkeditor.tcl]]
+package ifneeded bis_basecontrolhelper       1.0 [list source [file join $dir bis_basecontrolhelper.tcl]] 
+
+
+# Image to Image Algorithms
+# -----------------------------------------------------------------------------
+# This is the parent class
+package ifneeded bis_imagetoimagealgorithm     1.0 [list source [file join $dir bis_imagetoimagealgorithm.tcl ]] 
+package ifneeded bis_imagelisttoimagealgorithm  1.0 [list source [file join $dir bis_imagelisttoimagealgorithm.tcl ]]
+package ifneeded bis_basethresholdimage        1.0 [list source [file join $dir bis_basethresholdimage.tcl ]] 
+package ifneeded bis_imagetosurfacealgorithm   1.0 [list source [file join $dir bis_imagetosurfacealgorithm.tcl ]] 
+
+#
+# These all derive (or should derive from bis_imagetoimagealgorithm)
+#
+package ifneeded bis_testsurface.tcl       1.0 [list source [file join $dir bis_testsurface.tcl]] 
+package ifneeded bis_create4dimage         1.0 [list source [file join $dir bis_create4dimage.tcl]] 
+package ifneeded bis_manualregistration         1.0 [list source [file join $dir bis_manualregistration.tcl]] 
+package ifneeded bis_split4dimage          1.0 [list source [file join $dir bis_split4dimage.tcl]] 
+package ifneeded bis_smoothimage           1.0 [list source [file join $dir bis_smoothimage.tcl]] 
+package ifneeded bis_exponentialfitimage           1.0 [list source [file join $dir bis_exponentialfitimage.tcl]] 
+package ifneeded bis_exponentialfitt1           1.0 [list source [file join $dir bis_exponentialfitt1.tcl]] 
+package ifneeded bis_regularizeobjectmap   1.0 [list source [file join $dir bis_regularizeobjectmap.tcl]] 
+package ifneeded bis_convolveimage           1.0 [list source [file join $dir bis_convolveimage.tcl]] 
+package ifneeded bis_distancemapimage           1.0 [list source [file join $dir bis_distancemapimage.tcl]] 
+package ifneeded bis_skeletonizeimage      1.0 [list source [file join $dir bis_skeletonizeimage.tcl]] 
+package ifneeded bis_temporalsmoothimage   1.0 [list source [file join $dir bis_temporalsmoothimage.tcl]] 
+package ifneeded bis_nonlinearsmoothimage  1.0 [list source [file join $dir bis_nonlinearsmoothimage.tcl]] 
+package ifneeded bis_edgedetectimage       1.0 [list source [file join $dir bis_edgedetectimage.tcl]] 
+package ifneeded bis_imagemedian           1.0 [list source [file join $dir bis_imagemedian.tcl]] 
+package ifneeded bis_imageremoveframes     1.0 [list source [file join $dir bis_imageremoveframes.tcl]] 
+package ifneeded bis_imagedilate           1.0 [list source [file join $dir bis_imagedilate.tcl]] 
+package ifneeded bis_cropimage             1.0 [list source [file join $dir bis_cropimage.tcl]] 
+package ifneeded bis_cylindricalcropimage  1.0 [list source [file join $dir bis_cylindricalcropimage.tcl]] 
+package ifneeded bis_piecewiseimagemap     1.0 [list source [file join $dir bis_piecewiseimagemap.tcl]] 
+package ifneeded bis_flipimage             1.0 [list source [file join $dir bis_flipimage.tcl]] 
+package ifneeded bis_castimage             1.0 [list source [file join $dir bis_castimage.tcl]] 
+package ifneeded bis_shiftscaleimage       1.0 [list source [file join $dir bis_shiftscaleimage.tcl]] 
+package ifneeded bis_logimage       1.0 [list source [file join $dir bis_logimage.tcl]] 
+package ifneeded bis_rfftimage             1.0 [list source [file join $dir bis_rfftimage.tcl]] 
+package ifneeded bis_fftimage              1.0 [list source [file join $dir bis_fftimage.tcl]] 
+package ifneeded bis_resampleimage         1.0 [list source [file join $dir bis_resampleimage.tcl]] 
+package ifneeded bis_thresholdimage        1.0 [list source [file join $dir bis_thresholdimage.tcl]] 
+package ifneeded bis_clusterthresholdimage 1.0 [list source [file join $dir bis_clusterthresholdimage.tcl]] 
+package ifneeded bis_listthresholdimage    1.0 [list source [file join $dir bis_listthresholdimage.tcl]] 
+package ifneeded bis_reorientimage         1.0 [list source [file join $dir bis_reorientimage.tcl]] 
+package ifneeded bis_newreorientimage         1.0 [list source [file join $dir bis_newreorientimage.tcl]] 
+package ifneeded bis_relabelimage          1.0 [list source [file join $dir bis_relabelimage.tcl]] 
+package ifneeded bis_intsegment            1.0 [list source [file join $dir bis_intsegment.tcl]] 
+package ifneeded bis_biasfield            1.0 [list source [file join $dir bis_biasfield.tcl]] 
+package ifneeded bis_sliceinhomogeneity   1.0 [list source [file join $dir bis_sliceinhomogeneity.tcl]] 
+package ifneeded bis_computedisplacementfield   1.0 [list source [file join $dir bis_computedisplacementfield.tcl]] 
+package ifneeded bis_computejointhistogram   1.0 [list source [file join $dir bis_computejointhistogram.tcl]] 
+package ifneeded bis_visualizetransformation    1.0 [list source [file join $dir bis_visualizetransformation.tcl]] 
+
+#package ifneeded bis_fastpostprocess       1.0 [list source [file join $dir bis_fastpostprocess.tcl]] 
+package ifneeded bis_interleave            1.0 [list source [file join $dir bis_interleave.tcl]] 
+package ifneeded bis_tmaptozscore          1.0 [list source [file join $dir bis_tmaptozscore.tcl]] 
+package ifneeded bis_tmaptopvalue          1.0 [list source [file join $dir bis_tmaptopvalue.tcl]] 
+package ifneeded bis_imagemathoperations   1.0 [list source [file join $dir bis_imagemathoperations.tcl]]
+package ifneeded bis_singleimagemathoperations   1.0 [list source [file join $dir bis_singleimagemathoperations.tcl]]
+package ifneeded bis_imagecompare          1.0 [list source [file join $dir bis_imagecompare.tcl]]
+package ifneeded bis_ttest                 1.0 [list source [file join $dir bis_ttest.tcl]] 
+package ifneeded bis_zscoretopvalue        1.0 [list source [file join $dir bis_zscoretopvalue.tcl]] 
+package ifneeded bis_fdr                   1.0 [list source [file join $dir bis_fdr.tcl]]
+package ifneeded bis_preprocessimage       1.0 [list source [file join $dir bis_preprocessimage.tcl]]
+package ifneeded bis_combineframes         1.0 [list source [file join $dir bis_combineframes.tcl]]
+package ifneeded bis_combineimages         1.0 [list source [file join $dir bis_combineimages.tcl]]
+package ifneeded bis_combinetransformations         1.0 [list source [file join $dir bis_combinetransformations.tcl]]
+package ifneeded bis_rtotmap               1.0 [list source [file join $dir bis_rtotmap.tcl]]
+package ifneeded bis_rtopvalue             1.0 [list source [file join $dir bis_rtopvalue.tcl]]
+#package ifneeded bis_oneminuspvalue        1.0 [list source [file join $dir bis_oneminuspvalue.tcl]]
+package ifneeded bis_csfwmmotioncorr       1.0 [list source [file join $dir bis_csfwmmotioncorr.tcl]]
+package ifneeded bis_computeglm            1.0 [list source [file join $dir bis_computeglm.tcl]]
+package ifneeded bis_imagematrixmultiply           1.0 [list source [file join $dir bis_imagematrixmultiply.tcl]]
+#package ifneeded bis_testfmritool          1.0 [list source [file join $dir bis_testfmritool.tcl]]
+package ifneeded bis_displayroimean        1.0 [list source [file join $dir bis_displayroimean.tcl]]
+
+
+#Connectivity
+package ifneeded bis_temporalsmoothimage              1.0 [list source [file join $dir bis_temporalsmoothimage.tcl]] 
+package ifneeded bis_mediantemporalsmoothimage        1.0 [list source [file join $dir bis_mediantemporalsmoothimage.tcl]] 
+package ifneeded bis_removetemporaldrift              1.0 [list source [file join $dir bis_removetemporaldrift.tcl]] 
+package ifneeded bis_removeslicemean                  1.0 [list source [file join $dir bis_removeslicemean.tcl]] 
+package ifneeded bis_roimean                          1.0 [list source [file join $dir bis_roimean.tcl]]
+package ifneeded bis_seedcorrelation                  1.0 [list source [file join $dir bis_seedcorrelation.tcl]]
+package ifneeded bis_matrixcorrelation                1.0 [list source [file join $dir bis_matrixcorrelation.tcl]]
+package ifneeded bis_intrinsicconnectivity            1.0 [list source [file join $dir bis_intrinsicconnectivity.tcl]] 
+package ifneeded bis_computecorrelations              1.0 [list source [file join $dir bis_computecorrelations.tcl]] 
+package ifneeded bis_fmritoolboxoptimize              1.0 [list source [file join $dir bis_fmritoolboxoptimize.tcl]]
+package ifneeded bis_fmritoolbox                      1.0 [list source [file join $dir bis_fmritoolbox.tcl]]
+package ifneeded bis_optionsampling                   1.0 [list source [file join $dir bis_optionsampling.tcl]]
+
+# Surface to Surface Algorithm
+# These will populate the new surface control
+# --------------------------------------------
+# This is the parent class
+package ifneeded bis_surfacetosurfacealgorithm     1.0 [list source [file join $dir bis_surfacetosurfacealgorithm.tcl ]] 
+package ifneeded bis_imageandsurfacetosurfacealgorithm     1.0 [list source [file join $dir bis_imageandsurfacetosurfacealgorithm.tcl ]] 
+#
+# derived classes
+#
+package ifneeded bis_cleansurface          1.0 [list source [file join $dir bis_cleansurface.tcl]] 
+package ifneeded bis_clipsurface           1.0 [list source [file join $dir bis_clipsurface.tcl]] 
+package ifneeded bis_computenormals        1.0 [list source [file join $dir bis_computenormals.tcl]] 
+package ifneeded bis_connect               1.0 [list source [file join $dir bis_connect.tcl]] 
+package ifneeded bis_curvatures            1.0 [list source [file join $dir bis_curvatures.tcl]] 
+package ifneeded bis_decimate              1.0 [list source [file join $dir bis_decimate.tcl]]
+package ifneeded bis_delaunay3D            1.0 [list source [file join $dir bis_delaunay3D.tcl]]
+package ifneeded bis_extractobjectmap      1.0 [list source [file join $dir bis_extractobjectmap.tcl]]
+package ifneeded bis_extractsurface        1.0 [list source [file join $dir bis_extractsurface.tcl]]
+#package ifneeded bis_mapfunctional         1.0 [list source [file join $dir bis_mapfunctional.tcl]]
+package ifneeded bis_smoothsurface         1.0 [list source [file join $dir bis_smoothsurface.tcl]]
+package ifneeded bis_subdivide		   1.0 [list source [file join $dir bis_subdivide.tcl]]
+package ifneeded bis_thresholdpoints       1.0 [list source [file join $dir bis_thresholdpoints.tcl]]
+package ifneeded bis_triangulate	   1.0 [list source [file join $dir bis_triangulate.tcl]]
+
+
+#
+package ifneeded bis_landmarkstolandmarksalgorithm     1.0 [list source [file join $dir bis_landmarkstolandmarksalgorithm.tcl ]] 
+
+#
+# these need to be "reparented"
+#
+package ifneeded bis_transformsurface     1.0 [list source [file join $dir bis_transformsurface.tcl]] 
+package ifneeded bis_computedistance       1.0 [list source [file join $dir bis_computedistance.tcl]] 
+
+# Transformation Manipulation
+# ---------------------------
+
+# Image and transformation combo algorithms
+#     -- some of this will come from pxitcloverlaytool
+# ----------------------------------------------------
+# parent class
+package ifneeded bis_dualimagealgorithm     1.0 [list source [file join $dir bis_dualimagealgorithm.tcl ]] 
+package ifneeded bis_dualimagetransformationalgorithm     1.0 [list source [file join $dir bis_dualimagetransformationalgorithm.tcl ]] 
+package ifneeded bis_dualimagereslicetransformationalgorithm     1.0 [list source [file join $dir bis_dualimagereslicetransformationalgorithm.tcl ]] 
+
+#
+# derived classes
+#
+package ifneeded bis_resliceimage          1.0 [list source [file join $dir bis_resliceimage.tcl]] 
+package ifneeded bis_reslicetensor          1.0 [list source [file join $dir bis_reslicetensor.tcl]] 
+package ifneeded bis_manualreslice          1.0 [list source [file join $dir bis_manualreslice.tcl]] 
+package ifneeded bis_checkerboardimage	           1.0 [list source [file join $dir bis_checkerboardimage.tcl]] 
+package ifneeded bis_colorblendimage	           1.0 [list source [file join $dir bis_colorblendimage.tcl]] 
+package ifneeded bis_createoverlayimage	           1.0 [list source [file join $dir bis_createoverlayimage.tcl]] 
+package ifneeded bis_maskimage	           1.0 [list source [file join $dir bis_maskimage.tcl]] 
+package ifneeded bis_blendimage          1.0 [list source [file join $dir bis_blendimage.tcl]] 
+package ifneeded bis_stitchimage         1.0 [list source [file join $dir bis_stitchimage.tcl]] 
+package ifneeded bis_computeoverlap         1.0 [list source [file join $dir bis_computeoverlap.tcl]] 
+package ifneeded bis_computesimilarity      1.0 [list source [file join $dir bis_computesimilarity.tcl]] 
+package ifneeded bis_singlejacobian        1.0 [list source [file join $dir bis_singlejacobian.tcl]] 
+package ifneeded bis_stripskull        1.0 [list source [file join $dir bis_stripskull.tcl]] 
+
+
+# Registration Stuff
+# ------------------
+# parent class
+package ifneeded bis_baseintensityregistration     1.0 [list source [file join $dir bis_baseintensityregistration.tcl ]] 
+# derived classes
+package ifneeded bis_linearintensityregister       1.0 [list source [file join $dir    bis_linearintensityregister.tcl ]] 
+package ifneeded bis_nonlinearintensityregister    1.0 [list source [file join $dir bis_nonlinearintensityregister.tcl ]] 
+package ifneeded bis_nonlineardistortioncorrection 1.0 [list source [file join $dir bis_nonlineardistortioncorrection.tcl ]] 
+#package ifneeded bis_labelregister                 1.0 [list source [file join $dir bis_labelregister.tcl ]]
+# parent class
+package ifneeded bis_basepointbasedregistration     1.0 [list source [file join $dir bis_basepointbasedregistration.tcl ]] 
+package ifneeded bis_pointbasedregistrationviewer     1.0 [list source [file join $dir bis_pointbasedregistrationviewer.tcl ]] 
+package ifneeded bis_linearpointregister         1.0 [list source [file join $dir bis_linearpointregister.tcl]] 
+package ifneeded bis_nonlinearpointregister         1.0 [list source [file join $dir bis_nonlinearpointregister.tcl]] 
+#package ifneeded bis_integrated_registration    1.0 [list source [file join $dir bis_integrated_registration.tcl]] 
+package ifneeded bis_serialdemonmousereg 1.0 [ list source [ file join $dir bis_serialdemonmousereg.tcl ]]
+
+
+# Generic Utilities
+# -----------------
+package ifneeded bis_headerinfo            1.0 [list source [file join $dir bis_headerinfo.tcl]] 
+package ifneeded bis_surfaceinfo           1.0 [list source [file join $dir bis_surfaceinfo.tcl]] 
+#package ifneeded bis_imageaccumulate     1.0 [list source [file join $dir bis_imageaccumulate.tcl]] 
+
+# Larger Things for group input (i.e. setup driven)
+# ------------------------------------------------
+#package ifneeded bis_multiregister_int          1.0 [list source [file join $dir bis_multiregister_int.tcl]] 
+#package ifneeded bis_pairwiseregister           1.0 [list source [file join $dir bis_pairwiseregister.tcl]] 
+#package ifneeded bis_multijacobian              1.0 [list source [file join $dir bis_multijacobian.tcl]] 
+#package ifneeded bis_multisegment              1.0 [list source [file join $dir bis_multisegment.tcl]] 
+
+
+# More Complex Things (i.e. DTI/Vascular)
+# ---------------------------------------
+#package ifneeded bis_tensoranalysis        1.0 [list source [file join $dir bis_tensoranalysis.tcl]] 
+#package ifneeded bis_vesselprop            1.0 [list source [file join $dir bis_vesselprop.tcl]] 
+#package ifneeded bis_vesselregion          1.0 [list source [file join $dir bis_vesselregion.tcl]] 
+#package ifneeded bis_vesselutility         1.0 [list source [file join $dir bis_vesselutility.tcl]] 
+#package ifneeded bis_vesseltrack           1.0 [list source [file join $dir bis_vesseltrack.tcl]] 
+
+# Levelset Algorithms
+package ifneeded bis_baselevelset        1.0 [list source [file join $dir bis_baselevelset.tcl]] 
+package ifneeded bis_levelset        1.0 [list source [file join $dir bis_levelset.tcl]] 
+package ifneeded bis_coupledlevelset        1.0 [list source [file join $dir bis_coupledlevelset.tcl]] 
+
+# GUI Stuff
+# ---------------------------------------
+package ifneeded bis_guicontainer          1.0 [list source [file join $dir bis_guicontainer.tcl       ]] 
+package ifneeded bis_guiimageutility       1.0 [list source [file join $dir bis_guiimageutility.tcl    ]] 
+package ifneeded bis_guitreeimageutility   1.0 [list source [file join $dir bis_guitreeimageutility.tcl]] 
+package ifneeded bis_guitreecreate4d       1.0 [list source [file join $dir bis_guitreecreate4d.tcl    ]]
+package ifneeded bis_guisurfacecontrol     1.0 [list source [file join $dir bis_guisurfacecontrol.tcl  ]] 
+package ifneeded bis_guisurfaceutility     1.0 [list source [file join $dir bis_guisurfaceutility.tcl  ]] 
+package ifneeded bis_guioverlayutility     1.0 [list source [file join $dir bis_guioverlayutility.tcl  ]] 
+package ifneeded bis_guirpmcontainer     1.0 [list source [file join $dir bis_guirpmcontainer.tcl  ]]
+package ifneeded bis_guicompareutility     1.0 [list source [file join $dir bis_guicompareutility.tcl  ]] 
+
+#spect stuff
+package ifneeded bis_proportionalscale 1.0 [list source [file join $dir bis_proportionalscale.tcl ]] 
+package ifneeded bis_spectbase         1.0 [list source [file join $dir bis_spectbase.tcl         ]] 
+package ifneeded bis_ISAS              1.0 [list source [file join $dir bis_ISAS.tcl              ]] 
+package ifneeded bis_ISASHN            1.0 [list source [file join $dir bis_ISASHN.tcl            ]] 
+package ifneeded bis_spectrf           1.0 [list source [file join $dir bis_spectrf.tcl           ]] 
+package ifneeded bis_spectapp          1.0 [list source [file join $dir bis_spectapp.tcl          ]] 
+
+# Landmark stuff
+package ifneeded bis_smoothlandmarks          1.0 [list source [file join $dir bis_smoothlandmarks.tcl          ]] 
+package ifneeded bis_resamplelandmarks          1.0 [list source [file join $dir bis_resamplelandmarks.tcl          ]] 
+
+# Batch File Generator
+package ifneeded bis_makebatch               1.0 [list source [file join $dir bis_makebatch.tcl          ]] 
+
+# DTI Stuff
+package ifneeded bis_tensoranalysis               1.0 [list source [file join $dir bis_tensoranalysis.tcl          ]] 
+package ifneeded bis_computetensor               1.0 [list source [file join $dir bis_computetensor.tcl          ]] 
+
+#Vascular Stuff
+package ifneeded bis_frangivesselness 1.0 [ list source [ file join $dir bis_frangivesselness.tcl ]]
+package ifneeded bis_qianvesselness 1.0 [ list source [ file join $dir bis_qianvesselness.tcl ]]
+
+# fMRI Test
+package ifneeded bis_multisubjectfmri 1.0 [ list source [ file join $dir bis_multisubjectfmri.tcl ]]
+package ifneeded bis_singlesubjectfmri 1.0 [ list source [ file join $dir bis_singlesubjectfmri.tcl ]]
+
+package ifneeded bis_graphvis       1.0 [list source [file join $dir bis_graphvis.tcl]] 
+
+# DICOM
+package ifneeded bis_dicom2nifti 1.0 [ list source [ file join $dir bis_dicom2nifti.tcl ]]
+package ifneeded bis_varian2nifti 1.0 [ list source [ file join $dir bis_varian2nifti.tcl ]]
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/CMakeLists.txt b/bioimagesuite30_src/bioimagesuite/datatree/CMakeLists.txt
new file mode 100644
index 0000000..1457a1e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/CMakeLists.txt
@@ -0,0 +1,58 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+
+SET(KITSCRIPTS
+    bis_treegui.tcl	
+    dsitcltree.tcl
+    pkgIndex.tcl
+    ChellyGUI_exp.tcl
+    pxitclbraintreegadget.tcl
+    ElectrodeAttributeTemplate.ele
+    no.xbm   
+)
+
+SET(KITAPPS
+    biodatatree.tcl
+)
+
+SUBDIRS(packages)
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+bis_complex_tcl(bioimagesuite/datatree ${FILELIST2} ${FILELIST})
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/ChellyGUI_exp.tcl b/bioimagesuite30_src/bioimagesuite/datatree/ChellyGUI_exp.tcl
new file mode 100644
index 0000000..6a61d13
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/ChellyGUI_exp.tcl
@@ -0,0 +1,8259 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide chellyGUI_2 1.0
+
+#---------------------------------------------------------------------------------------------
+#Import of required packages and other required initialization defs
+#---------------------------------------------------------------------------------------------
+# This package sets the required paths
+lappend auto_path [file dirname [info script]]
+package require pxitclchellypackages 1.0
+package require pxitclfilelistmenu 1.0
+#package require bis_guitreeimageutility
+#------------------------------------------------------------------------------------------
+
+
+# Chelly's Packages
+package require VisTree2;        #This is the "Tcl only" Tree widget that handles the tree display
+package require struct;          #This package includes the "struct::tree"
+package require chellyDB;        #This is the package that handles saving and loading of patient tree files
+
+# Optional Modules - require if files are present in packages directory
+if {[file exists [ file join [ file dirname [ info script ] ] packages AtlasProg.tcl]]} {
+      package require AtlasProg;       #This is the atlas lookup package
+}
+
+# Optional Modules - require if files are present in packages directory
+if {[file exists [ file join [ file dirname [ info script ] ] packages SPECTtools.tcl]]} {
+    package require SPECTProcessProg;       #This is the atlas lookup package
+}
+
+if {[file exists [ file join [ file dirname [ info script ] ] packages AdvancedRegTools.tcl]]} {
+    package require AdvancedRegTools;       #This is the atlas lookup package
+}
+
+
+if {[file exists [ file join [ file dirname [ info script ] ] packages ElectrodeAttrProg.tcl]]} {
+    package require ElectrodeAttrProg;       #This is the atlas lookup package
+}
+
+# Require key packages
+package require Itcl
+package require Iwidgets
+
+# Xenios' C++ Extensions
+package require vtkpxcontrib     1.0
+
+# Simple Naming package  [ pxvtable::vnewobj ]
+package require pxvtable         1.0
+
+# Wrappers around vtkImageData and vtkAbstractTransform
+package require pxitclimage              1.0
+package require pxitcllandmarks          1.0
+package require pxitclelectrodemultigrid 1.0
+package require pxitcltransform          1.0
+
+::itcl::class chellyGUI {
+    
+
+    #Note: throughout this class, Image 2 is the Image to Be Resliced into the Space of
+    #Image 1, which is sometimes referred to as Base Image
+    
+    
+    #Class Data Members
+    
+    #----------------------------------------------------
+    #---------Module Enable/Disable Options--------------
+    public variable enable_atlas 0
+    public variable enable_SPECT 1
+    public variable enable_AdvancedReg 1
+    public variable enable_elec_att 1
+    #----------------------------------------------------
+
+
+    public variable FileManager 0;         #This is the FileManager Object (an instance of a child of chellyDB)
+    public variable RelativeFileManager 0; #These are the two options for it 
+    public variable AbsoluteFileManager 0
+
+    #Package Variables
+    public variable AtlasModule 0;         #This is the Atlas Lookup program 
+    public variable AtlasRefFilename -1;   #This is the filename of the reference image for the atlas
+    public variable SPECTmodule 0;         #This is the SPECT processing program
+    public variable SPECT_initialized 0;   #Has the SPECT tool been initialized?
+    public variable REGmodule 0;         #This is the REG processing program
+    public variable REG_initialized 0;   #Has the REG tool been initialized?
+
+
+    public variable ElectAttrModule 0;     #This is the Electrode Attribute Selector Program
+    #--------------------------------------------------
+
+    public variable MasterCount;  #This is the counter to ensure all nodes in the tree have a unique ID
+
+    public variable ClipboardTreeArray; #This is the temporary serialized tree, for cutting and pasting
+
+    public variable mdTopWidget
+    public variable osmode; # variable to hold which operating system we are on
+    public variable menucolor; # color for the top menu
+    public variable menuactivebgcolor; # active background for top menu
+    public variable leftpane
+    public variable midpane
+    public variable rightpane
+    public variable treeframe 
+    public variable descriptionbox
+    public variable hasatlastool 1
+    #    public variable RecentFilesMenu
+    #    public variable recentfileslist ""
+    #    public variable recentfilesnames ""
+    public variable toolsmenu 0
+
+
+    public variable TreeChanged 0
+
+    public variable SurgeryMode 0; # Disables some options
+    public variable SpaceLocked 0; # Locks SpaceImage
+
+    public variable brainiconchoice "ibrainpurple"
+    public variable surfaceiconchoice "ibrainyellow"
+    public variable resulticonchoice "ibrainred"
+    public variable atlasiconchoice "ibrainrainbow"
+    public variable roiiconchoice "ibrainorange"
+
+    public variable reslmode 1
+
+    public variable IC;   #This is the canvas widget in the middle pane
+    public variable rbX
+    public variable rbY
+    public variable abX
+    public variable abY
+    public variable fbX
+    public variable fbY
+    public variable REF_AnatomicalImage 0
+    public variable REF_FunctionalImage 0
+
+    public variable OCanv -1; #This varible will point to the canvas in the overlay tab
+    public variable OCdispX
+    public variable OCdispY
+
+    protected variable surgerygadget 0
+
+    public variable SpaceImage -1
+    public variable AnatomicalImage -1
+    public variable FunctionalImage -1
+    public variable AtlasImage -1
+    
+    variable RecognizedTypes
+    variable PatientProperties ""
+    variable RealTree; # This is the main tree array
+    variable TransformsCache
+    variable NodeIDs
+    variable statusbar
+    variable statusLabel
+    variable vistree
+    variable popup
+    variable surfacepopup
+    variable electrodepopup
+    variable patientpopup
+    variable rootpopup
+    variable rightpanelpopup
+    
+    variable NodeInfoDialogName -1
+    variable nodeDialogBGColor -1
+    public variable entrylist
+    public variable nodeinfoitemlist
+
+    variable mdEntries 
+    variable RecognizedTypesChecks
+    variable dialogEntries ""
+    variable RecogTypeDialogName -1
+    variable showGrabButtonDialogName -1
+    variable SearchDialogName -1
+
+    variable PatientPropDialogName -1
+    variable PatientProperty_selectionbox1 -1
+    
+    variable ImageThresholdForROICalcs
+    variable threshDialog
+
+    variable SearchResultList ""
+    variable titlequery ""
+    variable FinalResultList ""
+    variable ResultDisplay
+    variable foldersearchselbox
+    variable folderchoicearray
+    variable foldersearchboxlist
+    variable folderbox
+    
+    variable SpaceControlWidget
+    variable AnatomicalControlWidget
+    variable FunctionalControlWidget
+    variable TransformationControlWidget
+    
+    public variable viewer1 0
+    public variable viewer2 0
+    public variable electrodecontrol1 0
+    public variable electrodecontrol2 0
+    public variable overlaycontrol 0
+    public variable myname 0
+    
+    public variable dragAndDropEnabled 0    
+    public variable undoArray
+    public variable theNoCursor
+    
+    # Switch Directory
+    public method SwitchDirectory { { newdir ""  } }
+
+    #---------------
+    #private methods
+    #---------------
+    
+    public method AddDefaults {realtreename}
+    public method AddPatient {realtreename ParentNodeID {title -1}}
+    public method AddFolder {realtreename ParentNodeID {title -1}}
+    public method AddImage {realtreename ParentNodeID {title -1} {type -1}}
+    public method AddSurface { realtreename ParentNodeID {title -1} {type -1}}
+    public method AddLandmark { realtreename ParentNodeID {title -1} {type -1}}
+    public method AddElectrode { realtreename ParentNodeID {title -1} {type -1}}
+    public method AddSubtree {realtreename ParentNodeID {ListedTree -1}}
+    public method AddMSBData {  realtreename ParentNodeID {title -1} {ListedTree -1} }
+    public method AddCSIPatient { realtreename ParentNodeID {title -1} {ListedTree -1}} 
+    public method AddAllCSI { realtreename  ParentNodeID }
+    
+    private method NodeInitialize {realtreename node}
+    private method ImageInitialize {realtreename node}
+    private method PatientInitialize {realtreename node}
+    private method FolderInitialize {realtreename node}
+    private method SurfaceInitialize {realtreename node}
+    private method LandmarkInitialize {realtreename node}
+    private method ElectrodeInitialize {realtreename node}
+    
+    public  method findTransforms { realtreename args }
+    private method commonAncestor { realtreename node1 node2 }
+    private method removeIDnodes { realtreename nodelist } 
+    private method makeTransformList { realtreename node1 node2 }
+    private method doTransformsExist { realtreename node }
+    public  method setNodeFilename { node {filename -1}}
+    private method setNodeTransformToParFile { node {filename -1}}
+    private method setNodeTransformFromParFile { node {filename -1}}
+    public  method toggleIdentity { node {explicitSetting -1}}
+    
+    private method checkForIllegalCharacters { inputName }
+    private method getPath {realtreename ImageID}
+    private method nodeName { node }
+    private method getNodesOfTransformation { trans }    
+    public  method EnsureFileLoaded { node }
+    public  method EnsureTransListLoaded { listoftransforms } 
+    
+    #--------------
+    #public methods
+    #--------------
+    public method GetThisPointer { } { return $this }
+    public method GetRealTree { } { return $RealTree }
+    public method GetVisTree { } { return $vistree }
+    public method GetTransformsCache { } { return [array get TransformsCache] }
+    
+    public method Debug { }
+
+    public method OnWidgetClose { }
+
+    #This forces an update of the visualization tree with the contents of the real data tree
+    public method updateVisTree { vistree RealTree {args}}
+    public method AutoSetIcon { realtreename node }
+    public method CloseNodes { args }
+    public method updateBigTransLines { } 
+    public method updateOverlayCanvas { }
+    public method updateRightCanvasDisplay { }
+
+    public method setSurgeryMode { }
+
+    #These methods send pxitcl objcets to the various controls 
+    public method setSpaceControlWidget { widget }
+    public method setAnatomicalControlWidget { widget }
+    public method setFunctionalControlWidget { widget } 
+    public method setTransformationControlWidget { widget }
+    
+    #Here are some methods to send/receive surfaces to/from the viewers (surfaces, landmarks, electrodes)
+    #------------------------------------------------------------------------------------------
+    public method sendSelectionToDisplay { viewerno {ref -1} {node -1}} 
+    public method displayImage      { viewerno imageobj { refobj -1 } {background 0} }
+    public method displaySurface    { viewerno surfaceobj { refobj -1 }}
+    public method displayLandmarks  { viewerno landobj { refobj -1 }}
+    public method displayElectrodes { econtrol electrodeobj { refobj -1 }}
+    
+    
+    #These grab the images from the viewers
+    public method PutViewerObjectInTree { viewerno objtype }
+    
+    public method GrabViewerImage { viewerno destinationobj }
+    public method GrabViewerSurface { viewer newsur }
+    public method GrabViewerLandmarkSet { viewer newsur } 
+    public method GrabViewerElectrodes { viewer newelec }
+
+    public method grabElectrodeAttributes { electrodecontrolno }
+    
+    
+    #methods to create the total concatenated transformation and export it
+    public method CreateTransformation { listoftransforms }
+    public method sureTransLoad { transobjname }
+    
+    # Reslmode 0=nn, 1=linear 3=cubic
+    public method ResliceImage  { baseimage imagetoberesliced listoftransforms {fname auto } {background 0 } }
+    public method Reslice { }
+    
+    
+    #User I/O methods
+    public method showButtonToolBar {mdTopWidget {args}}
+    public method showGrabButtonDialog { }
+    public method Single_Entry_Dialog {title msgstring {defstring -1}}
+    public method ImageEntryDialog {}
+    
+    public method GetIDFromSelection { args }
+    public method IsNodeImage { node {treename -1} {broad 0}}
+    public method IsNodeSurface { node {treename -1} }
+
+    #button click methods and related helper methods
+    public method bindxrelease1 { W x y mode }
+    public method bindxmotion1 { W x y } 
+    public method bindx1 { W x y }
+    public method displayFilename {}
+    public method isCurrentAChildOfSelection { currentPath selectionPath W }
+    public method isCurrentTheParentOfSelection { currentPath selectionPath W }
+    public method selectTreeFromBind { W x y } 
+    public method bindxcontrol1 { W x y }
+    public method bindxdouble1 { W x y }
+    public method bindx3 { W x y }
+    public method bindxRightPane { W x y menu }  
+    public method bindRightPaneTest { W x y text }
+    public method setCurrent { W x y }
+    public method setSelection { W x y }
+    public method bindxControlX { W K N }
+    public method bindxControlC { W K N }
+    public method releaseOnTreeCut { W x y }
+    public method releaseOnTreeCopy { W x y }
+    public method releaseOnImagesTab { x y }
+    public method displayMarkerOnImageTab { W x y }
+
+    public method NodeInfoDialog { } 
+    public method updateNodeDialogField  { entry function node item} 
+    public method updateAllNodeDialogFields {entries node items}
+    public method updateNodeNotes { realtreename node text dialogname} 
+    public method setPatientProperty { property entryfield }
+    
+    public method ShowMidpaneTools { parent } 
+    public method OCanvasInitialize { parent }
+    public method ShowManager {pw surgerygadget0 menubase };#This is the most imporatant method
+    public method ShowTextBox { parent }
+    
+    #methods that deal with event bindings, menus and such
+    public method makeFileMenu { menu0 }
+    public method makeEditMenu { menu0 }
+    public method makeToolsMenu { menu0 }
+    public method makeImageMenu { menu0 }
+    public method makeSurfaceMenu { menu0 }
+    public method makeElectrodeMenu { menu0 }
+    public method makePatientMenu { menu0 }
+    public method makeDataMenu { menu0 }
+    public method makeAtlasMenu { menu0 }
+    public method makeOptionsMenu { menu0 }
+    public method makeViewMenu { menu0 }
+    public method makeColorMenu { colormenu icon }
+    public method menuActivation { menu menutype }
+    
+    public method addImageToTree { }
+    public method addPatientToTree { }
+    public method addFolderToTree { }
+    public method addSurfaceToTree { }
+    public method addLandmarkToTree { }
+    public method addElectrodeToTree { }
+    public method addSubtreeAtSelection { {type 1} }
+    
+    public method mdLoadElectrodeAttributes { }
+
+    public method renameSelected { }
+    public method delSelectedFromTree { }
+    
+    public method setSelectionSpace { realtreename }
+    public method setSelectionAnatomical { realtreename }
+    public method setSelectionFunctional { realtreename }
+    
+    public method setSelectedFileName { }
+    
+    public method setTransToParent { }
+    public method setTransFromParent { }
+
+    public method clearTransToParent { }
+    public method clearTransFromParent { }
+    
+    public method setIdentityToggle { }
+    public method nameNode {realtreename node newtitle } 
+    #----------------------------------------
+    
+    
+    #Atlas Module methods--------------------
+    public method addAtlasToTree { }
+    public method AddAtlasNode { realtreename ParentNodeID {title -1}} 
+    public method AtlasInitialize { realtreename node }  
+    
+    public method ShowAtlas { } { $AtlasModule ShowTop }
+    public method AtlasShowSelectedNode { }
+    public method SendImageToAtlasModule { { nodeID -1} {raise 1}} 
+    public method BringUpAtlasModule { } 
+    #----------------------------------------
+
+    #SPECT Processing Tool methods-----------
+    public method ShowSPECTtool { }
+    public method ShowREGtool { }
+    #----------------------------------------
+
+    #ElectrodeAtrribute Module methods-------
+    public method SendElectrodeToAtrrControl { { nodeID -1} {raise 1} }
+    public method PutElectrodeAttrControlOutputInTree { }
+    #----------------------------------------
+    
+    #ROI Defintion methods-------------------
+    public method addROIDefToTree { }
+    public method AddROIDefNode { realtreename ParentNodeID {title -1}}
+    public method ROIDefInitialize { realtreename node }
+    #----------------------------------------
+    
+    #Search Module methods-------------------
+    public method SearchDialog { }
+    public method SearchGetFolder { }
+    public method FolderSelectionInsert { }
+    public method SearchCallback { dialog command }
+    public method doSearch { dialog }
+    
+    #Method to enable searching of the tree for a given characteristic
+    public method SearchTree { realtreename startnode key args }
+    
+    public method SaveAllInRef { {listofnodes -1} }
+    public method sendAllToCommonSpace { spacenode imagelist } 
+    public method ComputeAverages { imagelist filename { background -32767 } } 
+    public method ComputeTscoreMap { immean imvar numsubjects }
+    public method ComputeROIStatistics  { functional_input roi_image_input { threshold none } } 
+    public method MultipleROI { imagelist } 
+    public method ThresholdLevelDialogCallback { } 
+    #----------------------------------------
+    
+    #Subject Property List editor dialog-----
+    public method EditPatientPropList { }
+    public method PatientPropDialogCallback { command }
+    #----------------------------------------
+
+    #Recognized type setter module-----------
+    public method showRecognizedTypes { array }
+    public method recognizedTypeDialogCallback { dlg mode }
+    public method setRecognizedTypes { }
+    #----------------------------------------
+    
+    #----------------------------------------
+    #Cut/Copy/Paste methods
+    public method mdCopy { {cut 0} { parentNode -1 } }
+    public method mdPaste { { parentNode -1 } }
+    public method undo
+    #----------------------------------------
+
+    #-----------------------------
+    # Added Methods to handle Save/Load with chellyDB
+    #------------------------------
+    public method mdSaveTree { datatree { updatefiles 0 } }
+    public method mdNewTree { };# (Does not call chellyDB)
+
+    public method mdLoadTreeFile { filename } { return [ $this mdLoadTree -1 $filename ] }
+    public method mdGetTreeFileName { } {
+	array set AddedTreeDefArray $ListedTree
+	return $TreeDefArray(ThisFileName)
+    }
+
+    public method mdLoadTree { {ListedTree -1} {filename -1} }
+    public method mdSaveTypeDefs { }
+    public method mdLoadTypeDefs { }
+   
+
+    #constructor
+    constructor { args } {
+	global tcl_platform
+
+	set thisfolder [ file dirname [ info script ] ]
+
+	if { $tcl_platform(platform) == "unix" } {
+	    set theNoCursor [ list @$thisfolder/no.xbm black ]
+	} elseif { $tcl_platform(platform) == "windows" } { 
+	    set theNoCursor "no" 
+	} else {
+	    set theNoCursor "boat" 
+	}
+
+	set masterpath [file normalize [ file join [ file join [ file dirname [ info script ] ] [ file join ..  images  ]]]]
+	set AbsoluteFileManager [chellyDBBasic \#auto]
+	set RelativeFileManager [chellyDBRelative \#auto]
+
+	set FileManager $RelativeFileManager
+	$FileManager configure -masterpath $masterpath
+	$FileManager configure -masterlist [ list "MNI_T1_1mm.nii.gz" "MNI_T1_1mm_stripped.nii.gz" "MNI_T1_colin_1mm_fixed.matr" "ISAS_Mean_Diff_SPECT.nii.gz" "ISAS_SPECT_Mask.nii.gz" "ISAS_SPECT_Template.nii.gz" "ISAS_Standard_Deviation.nii.gz" "ISASHN_Standard_Deviation.nii.gz" "MNI_T1_2mm_stripped.nii.gz" "MNI_T1_2mm.nii.gz" ]
+
+	puts stderr "[ $FileManager cget -masterpath ] [ $FileManager cget -masterlist ]"
+	set MasterCount 1
+
+	set myname [ pxvtable::vnewobj ]
+
+	#-------------------------------------------------------------------------------------------------------
+	# Optional Module Loading
+	#-------------------------------------------------------------------------------------------------------
+	
+	# The Atlas Tool
+	#-------------------------------------------------------------------------------------------------------
+	if {![file exists [ file join [ file dirname [ info script ] ] packages AtlasProg.tcl]]} {
+	    set enable_atlas 0
+	}
+	if {$enable_atlas == 1} {
+	    set AtlasModule [AtlasTool \#auto] 
+	    $AtlasModule configure -folderpath [ file join [ file dirname [ info script ] ] packages AtlasDefImages]
+	    $AtlasModule Initialize .[pxvtable::vnewobj]
+	}
+	#-------------------------------------------------------------------------------------------------------
+	
+	#The SPECT Processing Tool
+	#-------------------------------------------------------------------------------------------------------
+	if {![file exists [ file join [ file dirname [ info script ] ] packages SPECTtools.tcl]]} {
+	    set enable_SPECT 0
+	}
+	if {$enable_SPECT == 1} {
+	    set SPECTmodule [SPECTprocess \#auto]
+	}
+	#-------------------------------------------------------------------------------------------------------
+
+	#The Advanced Registration Tool
+	#-------------------------------------------------------------------------------------------------------
+	if {![file exists [ file join [ file dirname [ info script ] ] packages AdvancedRegTools.tcl]]} {
+	    set enable_AdvancedReg 0
+	}
+	if {$enable_AdvancedReg == 1} {
+	    set REGmodule [ AdvancedReg \#auto]
+	}
+	#-------------------------------------------------------------------------------------------------------
+
+
+	#The ElectrodeAttribute Tool
+	#-------------------------------------------------------------------------------------------------------
+	if {![file exists [ file join [ file dirname [ info script ] ] packages ElectrodeAttrProg.tcl]]} {
+	    set enable_elec_att 0
+	}
+	if {$enable_elec_att == 1} {
+	    set ElectAttrModule [ElectrodeAttr \#auto]
+	    $ElectAttrModule Initialize .[pxvtable::vnewobj] [::itcl::scope RealTree] $this
+	}
+	#-------------------------------------------------------------------------------------------------------
+
+	#-------------------------------------------------------------------------------------------------------
+	#End of optional module loading
+	#-------------------------------------------------------------------------------------------------------
+	
+	#--------------------------------------------------
+	#Initialize a default array of recognized types
+	set RecognizedTypes(10)   "Common Space"
+	set RecognizedTypes(1000) "3D Anatomical MR"
+	set RecognizedTypes(7100) "Post-op MR"
+	set RecognizedTypes(7200) "Post-op CT"
+	set RecognizedTypes(8000) "Interictal SPECT"
+	set RecognizedTypes(8100) "Ictal SPECT"
+	set RecognizedTypes(8200) "Differential SPECT"
+	set RecognizedTypes(3000) "PET-FDG"
+	set RecognizedTypes(9000) "CSI Scout"
+	set RecognizedTypes(9100) "CSI Raw Data"
+	set RecognizedTypes(9200) "CSI PMAP"
+	set RecognizedTypes(4000) "fMRI Scout - Conventional 2D"
+	set RecognizedTypes(4100) "Spin-Echo Echoplanar"
+	set RecognizedTypes(4050) "Field Map"
+	set RecognizedTypes(4200) "fMRI Motor Task"
+	set RecognizedTypes(4300) "fMRI Language Task"
+	set RecognizedTypes(4400) "fMRI Sensory Task"
+	#--------------------------------------------------
+
+	#--------------------------------------------------
+	#Initialize a default list of patient parameters
+	set PatientProperties [list Sex Age Weight Height IQ Cholesterol {Fat percentage} BP]
+	#--------------------------------------------------
+    }
+    
+    #destructor
+    destructor { 
+	unset MasterCount
+    }
+    
+    
+};#End chellyGUI class
+
+
+#------------------------------------------------------------------------------------------
+#Method defs for class chellyGUI
+#------------------------------------------------------------------------------------------
+#------------------------------------------------------------------------------------------
+itcl::body chellyGUI::SwitchDirectory { { dirname "" } } {
+
+    if { [ string length $dirname ] == 0 } {
+	set dirname  [tk_chooseDirectory -title "Select Current Directory" ]
+    }
+
+    if { [ string length $dirname ] < 1 } {
+	return 0
+    }
+
+    cd $dirname
+    set dirname [ pwd ]
+    pxtkprint "Switched directory to $dirname"
+}
+
+
+::itcl::body chellyGUI::OnWidgetClose { } { 
+    
+    if { $TreeChanged == 0 } {
+	pxtkexit
+    }
+
+    set ans [ tk_messageBox -type yesnocancel -default yes \
+		  -message "The tree has changed since it was last saved.  Would you like to save it before exiting?" -icon question ]
+
+    if { $ans == "cancel"} {
+	return
+    }
+    
+    if { $ans == "yes"} {
+	if { [ mdSaveTree $RealTree ] < 0 } {
+	    return 
+	}
+    }
+    
+    pxtkexit
+
+}
+
+#Creates a Toolbar right below main menu to contain a row of buttons
+::itcl::body chellyGUI::showButtonToolBar {mdTopWidget {args}} {
+    frame $mdTopWidget.buttonTools -borderwidth 1
+    pack $mdTopWidget.buttonTools -side top -fill x
+    foreach thisButton $args {
+	button $mdTopWidget.buttonTools.$thisButton -font fixed -text $thisButton
+	pack $mdTopWidget.buttonTools.$thisButton -side left
+    }
+}
+
+
+::itcl::body chellyGUI::Single_Entry_Dialog {title msgstring {defstring -1}} {
+
+    #defstring is the default entry in the dialog
+
+    global Single_Entry_Dialog_Result -1
+
+    iwidgets::promptdialog .sed -modality application -title $title -modality application \
+	-labeltext $msgstring -labelpos s
+    .sed hide Apply
+
+    .sed buttonconfigure OK -command { set Single_Entry_Dialog_Result [.sed get]; .sed deactivate }
+    .sed buttonconfigure Cancel -command { set Single_Entry_Dialog_Result -1; .sed deactivate }
+
+    if {$defstring != -1} {
+	.sed insert 0 $defstring
+	.sed selection range 0 end
+    }
+
+    focus [.sed component prompt component entry]
+    .sed center
+    update idletasks
+    .sed activate
+
+    destroy .sed
+    
+    return $Single_Entry_Dialog_Result
+
+}
+
+::itcl::body chellyGUI::ImageEntryDialog {} {
+    
+    global ImageDialogEntryResult -1
+    
+    iwidgets::selectiondialog .selbox -borderwidth 2 -height 200 \
+	-labelfont -Adobe-Helvetica-Bold-R-Normal--*-140-*-*-*-*-*-* \
+	-title "Add a Child Image" \
+	-textbackground ghostwhite -itemslabel "Select an Image Type:" \
+	-selectionlabel "or Specify a Custom Image Type:"
+    
+    #This just makes sure that they are displayed sorted by type key (which is not seen by the user)
+    foreach index [array names RecognizedTypes] {
+	lappend typekeyz $index
+    }
+    set typekeyz [lsort -integer $typekeyz]
+    
+    for {set tx 0} {$tx < [llength $typekeyz]} {incr tx} {
+	lappend imagetypes $RecognizedTypes([lindex $typekeyz $tx])
+    }
+    
+    eval .selbox insert items 0 $imagetypes
+    .selbox hide Apply
+    .selbox center
+    .selbox configure -modality application
+    .selbox buttonconfigure OK -command {set ImageDialogEntryResult [.selbox get]; .selbox deactivate }
+    .selbox buttonconfigure Cancel -command {set ImageDialogEntryResult -1; .selbox deactivate }
+    
+    update idletasks
+    .selbox activate
+    
+    destroy .selbox
+    
+    return $ImageDialogEntryResult
+    
+}
+
+
+
+#------------------------------------------------------------------------------------------
+# Private methods of chellyGUI
+#------------------------------------------------------------------------------------------
+#InitInit
+
+::itcl::body chellyGUI::NodeInitialize {realtreename node} {
+    
+    $realtreename set $node title $node
+    $realtreename set $node group data
+    $realtreename set $node notes ""
+    
+    $realtreename set $node FileName -1
+    $realtreename set $node FileLoaded 0
+    
+    #this is the transformation object FROM this object TO the parent
+    $realtreename set $node TransToParFileName -1
+    $realtreename set $node pxitclTransToParent [[pxitcltransform "$myname,$node:[$RealTree parent $node]"] GetThisPointer]
+    
+    
+    #this is the transformation object TO this object FROM the parent
+    $realtreename set $node TransFromParFileName -1
+    $realtreename set $node pxitclTransFromParent [[pxitcltransform "$myname,[$RealTree parent $node]:$node"] GetThisPointer]
+
+    #Also, we set a key in the visualization array for the new node's expanded status (1, though it has no children yet)
+    set ::Tree::Tree($vistree:[getPath $realtreename $node]:open) 1
+    $realtreename set $node expanded 1
+
+    #We will force the node's parent to automatically expand in the visualization tree
+    set ::Tree::Tree($vistree:[getPath $realtreename [$realtreename parent $node]]:open) 1
+    $realtreename set [$realtreename parent $node] expanded 1
+
+    #--------------------------------------------------
+    #This sets the key in the reverse array for a lookup
+    set pathList [$realtreename rootname]
+    set pathListIDs [$realtreename ancestors $node]
+    
+    for {set y [expr [llength $pathListIDs] - 1]} {$y > -1} {incr y -1} {
+	if {[lindex $pathListIDs $y] != [$realtreename rootname]} {
+	    lappend pathList [$realtreename get [lindex $pathListIDs $y] title]
+	    
+	}
+    }
+    
+    set pathName /
+    for {set i 0} {$i < [llength $pathList]} {incr i} {
+	append pathName [lindex $pathList $i]
+	append pathName /
+    }
+    append pathName [$realtreename get $node title]
+    set NodeIDs($pathName) $node
+    #--------------------------------------------------
+    
+    
+}
+
+
+::itcl::body chellyGUI::SurfaceInitialize {realtreename node} {
+    
+    NodeInitialize $realtreename $node
+    
+    $realtreename set $node type [list Surface Surface]
+    $realtreename set $node pxitclobj [ [pxitclsurface \#auto] GetThisPointer ]
+    
+    #A couple display properties for the node
+    $realtreename set $node icon $surfaceiconchoice
+    $realtreename set $node linecolor green
+    
+    #This node property toggles the "identity" propery for the image - ie, no transformation 
+    $realtreename set $node FromParFilenameSet 0
+    $realtreename set $node ToParFilenameSet 0
+    $realtreename set $node IsIdentity 0;# Initialize it to zero
+    
+    #Toggle the identity to 1 (with an explicit setting)
+    toggleIdentity $node 1
+    
+}
+
+::itcl::body chellyGUI::LandmarkInitialize {realtreename node} {
+    
+    NodeInitialize $realtreename $node
+    
+    $realtreename set $node type [list Surface Landmark]
+    $realtreename set $node pxitclobj [ [pxitcllandmarks \#auto] GetThisPointer ]
+    
+    #A couple display properties for the node
+    $realtreename set $node icon $surfaceiconchoice
+    $realtreename set $node linecolor green
+    
+    #This node property toggles the "identity" propery for the image - ie, no transformation 
+    $realtreename set $node FromParFilenameSet 0
+    $realtreename set $node ToParFilenameSet 0
+    $realtreename set $node IsIdentity 0;# Initialize it to zero
+    
+    #Toggle the identity to 1 (with an explicit setting)
+    toggleIdentity $node 1
+    
+}
+
+::itcl::body chellyGUI::ElectrodeInitialize {realtreename node} {
+    
+    NodeInitialize $realtreename $node
+    
+    $realtreename set $node type [list Surface Electrode]
+    $realtreename set $node pxitclobj [ [pxitclelectrodemultigrid \#auto] GetThisPointer ]
+    
+    #A couple display properties for the node
+    $realtreename set $node icon $surfaceiconchoice
+    $realtreename set $node linecolor green
+    
+    #An "Attribute" List, which may be optionally set
+    $realtreename set $node Attributes -1
+
+    #This node property toggles the "identity" propery for the image - ie, no transformation 
+    $realtreename set $node FromParFilenameSet 0
+    $realtreename set $node ToParFilenameSet 0
+    $realtreename set $node IsIdentity 0;# Initialize it to zero
+    
+    #Toggle the identity to 1 (with an explicit setting)
+    toggleIdentity $node 1
+    
+}
+
+
+
+
+::itcl::body chellyGUI::PatientInitialize {realtreename node} {
+  
+    NodeInitialize $realtreename $node
+
+    $realtreename set $node type Patient
+    $realtreename set $node pxitclobj [ [pxitclimage \#auto] GetThisPointer ]
+    
+    #A couple display properties for the node
+    $realtreename set $node icon idir
+    $realtreename set $node linecolor green
+
+    #This node property toggles the "identity" propery for the image - ie, no transformation 
+    $realtreename set $node FromParFilenameSet 1
+    $realtreename set $node ToParFilenameSet 1
+    $realtreename set $node IsIdentity 1
+
+    set propArray(init) 1
+    $realtreename set $node Properties [array get propArray]
+
+    toggleIdentity $node 1
+
+}
+
+::itcl::body chellyGUI::FolderInitialize {realtreename node} {
+   
+    NodeInitialize $realtreename $node
+
+    $realtreename set $node type Folder
+    $realtreename set $node pxitclobj [ [pxitclimage \#auto] GetThisPointer ]
+
+    #A couple display properties for the node
+    $realtreename set $node icon idir
+    $realtreename set $node linecolor green
+
+    #This node property toggles the "identity" propery for the image - ie, no transformation 
+    $realtreename set $node FromParFilenameSet 1
+    $realtreename set $node ToParFilenameSet 1
+    $realtreename set $node IsIdentity 1
+
+    toggleIdentity $node 1
+
+}
+
+
+#This method sets all the initial values for the node keys (ie, properties of each image object)
+::itcl::body chellyGUI::ImageInitialize {realtreename node} {
+ 
+    NodeInitialize $realtreename $node
+
+    $realtreename set $node type -1
+    $realtreename set $node pxitclobj [ [pxitclimage \#auto] GetThisPointer ]
+
+    #A couple display properties for the node
+    $realtreename set $node icon ibraingrey
+    $realtreename set $node linecolor red
+
+    #This node property toggles the "identity" propery for the image - ie, no transformation 
+    $realtreename set $node FromParFilenameSet 0
+    $realtreename set $node ToParFilenameSet 0
+    $realtreename set $node IsIdentity 0
+    
+   
+}
+
+
+::itcl::body chellyGUI::IsNodeImage { node {treename -1} {broad 0}} {
+    
+    if {$treename == -1} {
+	set treename $RealTree
+    }
+    
+    if {$node == [$treename rootname]} {return 0}
+    
+    if {$broad == 0} {
+	#Does not Include Atlas and ROI Def Images as "Image"
+	switch -exact -- [lindex [$treename get $node type] 0] {
+	    
+	    "Surface" -
+	    "Landmark" -
+	    "Electrode" -
+	    "Folder" -
+	    "Patient" -
+	    "Atlas" -
+	    "ROIDef" {
+		return 0
+	    }
+	}	
+	return 1
+    } else {
+	# Includes Atlas and ROI Def Images as "Image"
+	switch -exact -- [lindex [$treename get $node type] 0] {
+	    
+	    "Surface" -
+	    "Landmark" -
+	    "Electrode" -
+	    "Folder" -
+	    "Patient" {
+		return 0
+	    }
+	}	
+	return 1
+	
+    }
+    
+}
+
+::itcl::body chellyGUI::IsNodeSurface { node {treename -1} } {
+    
+    if {$treename == -1} {
+	set treename $RealTree
+    }
+    
+    if {$node == [$treename rootname]} {return 0}
+    if {[lindex [$treename get $node type] 0]== "Surface"} {
+	return 1
+    }
+    
+    return 0
+    
+}
+
+::itcl::body chellyGUI::AddDefaults {realtreename} {
+    
+    global datatreebioimagesuitepath
+    set masterpath [file normalize [ file join $datatreebioimagesuitepath images ] ]
+    
+    if {$enable_atlas == 1} {
+	#Reference Image for Atlas comparison
+	set thisID [lindex [AddAtlasNode $realtreename $NodeIDs(/Data) "Brain_Atlas"] 2]
+	set AtlasRefFilename [file join $masterpath MNI_T1_1mm.nii.gz]
+	setNodeFilename $thisID $AtlasRefFilename
+	
+	set thatID [lindex [AddImage $realtreename $thisID "Colin 1mm"] 2]
+	set Node2Filename [file join $masterpath  MNI_T1_1mm_stripped.nii.gz]
+	setNodeFilename $thatID $Node2Filename
+	$realtreename set $thatID type 10
+	
+	setNodeTransformFromParFile $thatID [file join $masterpath MNI_T1_colin_1mm_fixed.matr ]
+    } else {
+	#Only add regular base image
+	set thatID [lindex [AddImage $realtreename $NodeIDs(/Data) "MNI T1 1mm"] 2]
+	set Node2Filename [file join $masterpath MNI_T1_1mm.nii.gz]
+	setNodeFilename $thatID $Node2Filename
+	$realtreename set $thatID type 10
+    }    
+
+    #Select the root node in the tree
+    ::Tree::setselection $vistree /[$RealTree rootname]
+}
+
+::itcl::body chellyGUI::getPath { realtreename NodeID } {
+    
+    #returns the pathname back to the root, given the node ID
+    set node $NodeID
+    set pathList [$realtreename rootname]
+    
+    set pathListIDs [$realtreename ancestors $node]
+    
+    for {set y [expr [llength $pathListIDs] - 1]} {$y > -1} {incr y -1} {
+	if {[lindex $pathListIDs $y] != [$realtreename rootname]} {
+	    lappend pathList [$realtreename get [lindex $pathListIDs $y] title]
+	}
+    }
+    
+    set pathName /
+    
+    for {set i 0} {$i < [llength $pathList]} {incr i} {
+	append pathName [lindex $pathList $i]
+	append pathName /
+    }
+    
+    if {![string match [$realtreename rootname] $node]} {
+	append pathName [$realtreename get $node title]
+    } 
+
+    #else { set pathName [string trimright $pathName /] }
+    
+    
+    return $pathName
+}
+
+
+
+
+#Updates the visualization tree with the contents of the real tree
+::itcl::body chellyGUI::updateVisTree {vistree realtreename {args} } {
+    
+    if {[llength $args] > 0} {
+	for {set i 0} {$i < [llength $args]} {incr i} {
+	    lappend roots [lindex $args $i]
+  	}
+    } else {set roots [$realtreename rootname] }
+    
+    
+    foreach updateroot $roots {
+	
+	#--------------------------------------------------------------------------------
+	# get a path to the node in the tree that needs to be updated
+	set updaterootpathname [string trimright [getPath $realtreename $updateroot] /]
+	
+	#--------------------------------------------------------------------------------
+	
+	foreach node [$realtreename children -all $updateroot] {
+	    if { [lsearch [array names ::Tree::Tree] $vistree:[getPath $realtreename $node]:open ] != -1 } {
+		$realtreename set $node expanded $::Tree::Tree($vistree:[getPath $realtreename $node]:open)
+	    } else {$realtreename set $node expanded 1}
+	}
+	
+ 	#Delete the node in the vis tree (which deletes all children)
+ 	::Tree::delitem $vistree $updaterootpathname
+	
+	#Now put the new image in
+	AutoSetIcon $realtreename $updateroot
+
+	#If the node is the root node, then just put the right icon in...otherwise, figure out transformations, and
+	#put the right color line in also
+	if {$updateroot != [$realtreename rootname]} {
+	    doTransformsExist $realtreename $updateroot
+	    Tree::newitem $vistree $updaterootpathname -image [$realtreename get $updateroot icon]\
+		-linecolor [$realtreename get $updateroot linecolor]
+	} else { 
+	    Tree::newitem $vistree $updaterootpathname -image [$realtreename get $updateroot icon] 
+	}
+
+	lappend items $updaterootpathname
+	
+	#--------------------------------------------------------------------------------
+	# Now deal with the children in the same way
+	#--------------------------------------------------------------------------------
+	if {[llength [$realtreename children $updateroot]] > 0} {
+	    foreach node [$realtreename children -all $updateroot] {
+		
+		set pathName [getPath $realtreename $node]
+		
+		AutoSetIcon $realtreename $node
+		
+		#This will update the linecolor of the node based on wheter the transformations exist
+		doTransformsExist $realtreename $node
+		
+		Tree::newitem $vistree $pathName -image [$realtreename get $node icon]\
+		    -linecolor [$realtreename get $node linecolor]
+		lappend items $pathName
+	    }
+	    
+	} 
+	#--------------------------------------------------------------------------------
+	
+	#open all nodes in the tree
+	Tree::open $vistree $updaterootpathname
+	foreach item $items {
+	    Tree::open $vistree $item
+	}
+	
+	#Reclose any nodes that were closed before updating the tree
+	foreach node [$realtreename children -all $updateroot] {
+	    if {[$realtreename get $node expanded] != 1} {
+		set thisnodepath [getPath $realtreename $node]
+		Tree::close $vistree $thisnodepath
+	    } 
+	}
+
+
+    }
+	
+};#End updateVisTree method
+
+::itcl::body chellyGUI::AutoSetIcon { realtreename node } {
+
+    if {$node == [$realtreename rootname]} {	
+	$realtreename set $node icon icactus
+	return 0
+    }
+    
+    #---Check if it's of type "Image"-----------------------------------------------
+    if {[IsNodeImage $node]} {
+	if {[$realtreename get $node FileName] != -1} {
+	    if {[$realtreename get $node IsIdentity]} {
+		$realtreename set $node icon iarrowbrain
+	    } else { $realtreename set $node icon $brainiconchoice }
+	} else { $realtreename set $node icon ibraingrey }
+    }  else { $realtreename set $node icon ibraingrey }
+    
+    
+    #---Check if it's of type "Surface"-----------------------------------------------
+    if {[IsNodeSurface $node]} {
+	if {[$realtreename get $node FileName] != -1} {
+	    $realtreename set $node icon $surfaceiconchoice
+	} else {$realtreename set $node icon ibraingrey }
+    }
+    
+    #---Check if it's of type "Result"-----------------------------------------------	    
+    if {[$realtreename get $node type] == "Result"} {
+	$realtreename set $node icon $resulticonchoice
+    }
+    
+    #---Check if it's of type "Patient"-----------------------------------------------	    
+    if {[$realtreename get $node type] == "Patient"} {
+	$realtreename set $node icon ipersonicon
+    }
+    
+    #---Check if it's of type "Folder"-----------------------------------------------	    
+    if {[$realtreename get $node type] == "Folder"} {
+	
+	$realtreename set $node icon idir
+    }
+    
+    #---Check if it's of type "Atlas"-----------------------------------------------	    
+    if {[$realtreename get $node type] == "Atlas"} {
+	if {[$realtreename get $node FileName] != -1} {
+	    $realtreename set $node icon $atlasiconchoice 
+	} else {$realtreename set $node icon ibraingrey }
+    }
+    
+    #---Check if it's of type "ROIDef"-----------------------------------------------	    
+    if {[$realtreename get $node type] == "ROIDef"} {
+	if {[$realtreename get $node FileName] != -1} {
+	    $realtreename set $node icon $roiiconchoice 
+	} else {$realtreename set $node icon ibraingrey }
+    }
+    
+    
+    
+}
+
+
+::itcl::body chellyGUI::CloseNodes { args } {
+
+    #If any nodes have been explicitly set to collapse, then do so
+    if {[llength $args] > 0} {
+	for {set i 0} {$i < [llength $args]} {incr i} {
+	    set closelist [lindex $args $i]
+	    foreach thisnode $closelist {
+		set thisnodepath [getPath $RealTree $thisnode]
+		Tree::close $vistree $thisnodepath
+	    }
+	}
+    }
+}
+
+::itcl::body chellyGUI::doTransformsExist { realtreename node } {
+    
+    if {[$realtreename get $node ToParFilenameSet] && [$realtreename get $node FromParFilenameSet]} { set x 2 } else {
+	if {[$realtreename get $node ToParFilenameSet]} { set x 1 } else {
+	    if {[$realtreename get $node FromParFilenameSet]} { set x -1 } else { set x 0 }    
+	}};#End of elses
+    
+    
+    switch -exact -- $x\
+	-1 {$RealTree set $node linecolor goldenrod2}\
+	0 {$RealTree set $node linecolor red}\
+	1 {$RealTree set $node linecolor purple}\
+	2 {$RealTree set $node linecolor green}
+    
+    
+    
+};#end of doTransformsExist method
+
+::itcl::body chellyGUI::updateBigTransLines { } {
+
+    if {$SpaceLocked == 1} {
+	if {$SpaceImage != -1} {
+	    set SpaceLockNoticeText [$IC create text [expr $rbX+65] [expr $rbY - 15] -text "(Space Locked)" \
+				  -fill red -font {times 16 bold italic} -tag SpaceLockNotice]
+	} else { catch {$IC delete SpaceLockNotice} }
+    } else { 
+	catch {$IC delete SpaceLockNotice}
+    }
+
+    catch {$IC delete Anat2Space Func2Space }
+    
+    #-----Anat --> Space -----------------------------------------------------------------
+    if {$SpaceImage != -1 && $AnatomicalImage != -1} {
+	
+	set GO 1
+	findTransforms $RealTree $SpaceImage $AnatomicalImage
+	foreach trans $TransformsCache($myname,$SpaceImage:$AnatomicalImage) {
+
+	    if { ![info exists TransformsCache($trans,fileset)] } {
+		set GO 0
+	    } else {
+		if {$TransformsCache($trans,fileset) != 1 } {
+		    set GO 0
+		}
+	    }
+	}
+	
+	if {$GO == 1} {
+	    $IC create line [expr $rbX - 13] [expr $rbY + 50] \
+		[expr $rbX - 55] [expr $rbY + 55] \
+		[expr $abX + 35 ] [expr $abY - 85] \
+		[expr $abX + 50 ] [expr $abY - 8] \
+		-tag Anat2Space -smooth true  -splinesteps 20 -width 12 \
+		-arrow first -arrowshape {15 18 8} -fill green
+	} else {
+	    $IC create line [expr $rbX - 13] [expr $rbY + 50] \
+		[expr $rbX - 55] [expr $rbY + 55] \
+		[expr $abX + 35 ] [expr $abY - 85] \
+		[expr $abX + 50 ] [expr $abY - 8] \
+		-tag Anat2Space -smooth true  -splinesteps 20 -width 12 \
+		-arrow first -arrowshape {15 18 8} -fill red
+	}
+	
+    }
+    
+    
+    
+    #-----Func --> Space -----------------------------------------------------------------
+    
+    if {$SpaceImage != -1 && $FunctionalImage != -1} {
+	
+	set GO 1
+	
+	findTransforms $RealTree $SpaceImage $FunctionalImage
+	foreach trans $TransformsCache($myname,$SpaceImage:$FunctionalImage) {
+
+#	    puts "-------$trans-------------------------------"
+#	    puts "Does fileset exist? [info exists TransformsCache($trans,fileset)]"
+	    if { [info exists TransformsCache($trans,fileset)] } {
+#		puts "What is it? $TransformsCache($trans,fileset)"
+	    }
+
+	    if { [info exists TransformsCache($trans,fileset)] != 1 } {
+		set GO 0
+	    } else {
+		if {$TransformsCache($trans,fileset) != 1 } {
+		    set GO 0
+		}
+	    }
+	}
+	
+	
+	
+	if {$GO == 1} {
+	    
+	    $IC create line [expr $rbX + 150] [expr $rbY + 50] \
+		[expr $rbX + 190] [expr $rbY + 55] \
+		[expr $fbX + 95 ] [expr $fbY - 85] \
+		[expr $fbX + 80 ] [expr $fbY - 8] \
+		-tag Func2Space -smooth true  -splinesteps 20 -width 12 \
+		-arrow first -arrowshape {15 18 8} -fill green
+	    
+	} else {
+	    
+	    $IC create line [expr $rbX + 150] [expr $rbY + 50] \
+		[expr $rbX + 190] [expr $rbY + 55] \
+		[expr $fbX + 95 ] [expr $fbY - 85] \
+		[expr $fbX + 80 ] [expr $fbY - 8] \
+		-tag Func2Space -smooth true  -splinesteps 20 -width 12 \
+		-arrow first -arrowshape {15 18 8} -fill red
+	}   
+	
+	
+    } ;# End "if both images are set"
+    
+}; #End method
+
+::itcl::body chellyGUI::updateRightCanvasDisplay { } {
+
+    if {[$RealTree exists $SpaceImage] != 1} {set SpaceImage -1}
+    if {[$RealTree exists $AnatomicalImage] != 1} {set AnatomicalImage -1}
+    if {[$RealTree exists $FunctionalImage] != 1} {set FunctionalImage -1}
+
+    #Clear all
+    catch {$IC delete refPIC}
+    catch {$IC delete anatomPIC}
+    catch {$IC delete funcPIC}
+    $IC delete refTEXT
+    $IC delete anatomTEXT
+    $IC delete funcTEXT
+    
+    #--Space Image------------------------------------------------------------------------------
+    if {$SpaceImage != -1} {
+	if {[$RealTree get $SpaceImage FileName] != -1} {
+	    set refcolorbrainPIC [$IC create image $rbX $rbY -image multicolorbrain -anchor nw -tag refPIC]
+	    set refbrainTEXT  [$IC create text [expr $rbX+65] [expr $rbY+52] -text "[$RealTree get $SpaceImage title]" \
+				   -fill white -activefill yellow -font {helvetica 15 bold} -tag refTEXT -width 150]
+	} else {
+	    set refbrainTEXT  [$IC create text [expr $rbX+65] [expr $rbY+52] -text "[$RealTree get $SpaceImage title]" \
+				   -fill grey61  -activefill yellow -font {helvetica 15 bold} -tag refTEXT]
+	}
+    } else {
+	set refbrainTEXT  [$IC create text [expr $rbX+65] [expr $rbY+52] -text "Not Set" \
+			       -fill grey61 -activefill yellow  -font {helvetica 15 bold} -tag refTEXT]
+    }
+    #------------------------------------------------------------------------------------------------
+
+   
+    #--Anatomical Image------------------------------------------------------------------------------
+    if {$AnatomicalImage != - 1} {
+	if {[$RealTree get $AnatomicalImage FileName] != -1} {
+	    
+	    set anatomicalcolorbrainPIC [$IC create image $abX $abY -image multicolorbrain -anchor nw -tag anatomPIC]
+	    set anatomicalbrainTEXT  [$IC create text [expr $abX+65] [expr $abY+52] -text "[$RealTree get $AnatomicalImage title]" -fill white -activefill yellow -font {helvetica 15 bold} -tag anatomTEXT -width 150]
+	} else { 
+	    set anatomicalbrainTEXT  [$IC create text [expr $abX+65] [expr $abY+52] -text "[$RealTree get $AnatomicalImage title]" -fill grey61  -activefill yellow -font {helvetica 15 bold} -tag anatomTEXT]
+	}
+    } else {
+	set anatomicalbrainTEXT  [$IC create text [expr $abX+65] [expr $abY+52] -text "Not Set" \
+				      -fill grey61 -font {helvetica 15 bold}  -activefill yellow -tag anatomTEXT]
+    }
+    #-------------------------------------------------------------------------------------------------
+
+
+    #--Functional Image------------------------------------------------------------------------------
+    if {$FunctionalImage != -1} {
+	if {[$RealTree get $FunctionalImage FileName] != -1} {
+	    set funccolorbrainPIC [$IC create image $fbX $fbY -image multicolorbrain -anchor nw -tag funcPIC]
+	    set funcbrainTEXT  [$IC create text [expr $fbX+65] [expr $fbY+52] -text "[$RealTree get $FunctionalImage title]" -fill white -activefill yellow -font {helvetica 15 bold} -tag funcTEXT -width 150]
+	    
+	} else { 
+	    set funcbrainTEXT  [$IC create text [expr $fbX+65] [expr $fbY+52] -text "[$RealTree get $FunctionalImage title]" -fill grey61  -activefill yellow -font {helvetica 15 bold} -tag funcTEXT]
+	}
+    } else { 
+	set funcbrainTEXT  [$IC create text [expr $fbX+65] [expr $fbY+52] -text "Not Set" \
+				-fill grey61 -activefill yellow -font {helvetica 15 bold} -tag funcTEXT]
+    }
+    #-------------------------------------------------------------------------------------------------
+
+
+    updateBigTransLines
+
+}
+
+::itcl::body chellyGUI::setSurgeryMode { } {
+
+    if {$SpaceImage != -1} {
+	set SpaceLocked 1
+    }
+    
+    set SurgeryMode 1
+
+}
+
+
+::itcl::body chellyGUI::AddSurface {realtreename ParentNodeID {title -1} {type -1}} {
+    if {[llength $ParentNodeID] > 0} { 
+	if {$title == -1} {
+	    set SurfaceTitle [Single_Entry_Dialog "New Surface" "Enter a name for the new surface"]
+	} else { set SurfaceTitle $title }
+	
+	set origTitle $SurfaceTitle
+	
+	if {[string equal $SurfaceTitle -1] | $SurfaceTitle == "" | [string equal -nocase $SurfaceTitle "Cancel"]} {
+	    return 
+	} else {
+
+
+	    #----Input Validation----------------------------------------------------------------------
+	    for {set a 0} {$a < [string length $SurfaceTitle]} {incr a} {
+		set achar [string range $SurfaceTitle $a $a]
+		
+		if {![string is wordchar $achar] && ![string is space $achar] \
+			&& ![string match {[.]} $achar] && ![string match {[-]} $achar] && ![string match {[^]} $achar] } {
+		    	    error "Cannot add surface using character $achar  -- Node names can only can contain the following characters: \n     a-z, A-Z, 0-9, _, -, ., ^, and spaces"
+		    
+		}
+	    }
+	    #------------------------------------------------------------------------------------------
+
+	    if {$type == -1} {
+		set ThisSurfaceType [list Surface Surface]
+	    } else {
+		set ThisSurfaceType $type
+	    }
+	    
+	    set ProposedPath [file join [getPath $realtreename $ParentNodeID] $SurfaceTitle]
+	    set UniqueSuffix 1
+	    set suffixed 0
+	    
+	    while {[Tree::itemexists $vistree $ProposedPath]} {
+		
+		if { $suffixed == 1 } {
+		    #delete the suffix
+		    set SurfaceTitle [string replace $SurfaceTitle [string last _ $SurfaceTitle] end]
+		}
+		
+		append SurfaceTitle _ $UniqueSuffix
+		set ProposedPath [file join [getPath $realtreename $ParentNodeID] $SurfaceTitle]
+		set suffixed 1
+		incr UniqueSuffix
+	    }
+	    
+	    
+	    if {![Tree::itemexists $vistree $ProposedPath]} {
+		
+		#Create a unique identifier for the Surface
+		set SurfaceID $MasterCount
+		incr MasterCount
+		
+		$realtreename insert $ParentNodeID end $SurfaceID
+		SurfaceInitialize $realtreename $SurfaceID
+		nameNode $realtreename $SurfaceID $SurfaceTitle
+		
+		$realtreename set $SurfaceID type $ThisSurfaceType
+		
+	    } else { 
+		error "Please select a unique surface name"
+	    }
+	}
+
+	set TreeChanged 1
+
+	return [list $suffixed $origTitle $SurfaceID]
+    } else {tk_messageBox -type ok -title "Need Selection" -message "Please select a parent in the tree" -icon info}
+};#end of AddSurface method
+
+::itcl::body chellyGUI::AddLandmark {realtreename ParentNodeID {title -1} {type -1}} {
+    if {[llength $ParentNodeID] > 0} {
+	if {$title == -1} {
+	    set LandmarkTitle [Single_Entry_Dialog "New Landmark" "Enter a name for the new landmark surface"]
+	} else { set LandmarkTitle $title }
+	
+	set origTitle $LandmarkTitle
+	
+	if {[string match $LandmarkTitle -1] | $LandmarkTitle == "" | [string equal -nocase $LandmarkTitle "Cancel"]} { 
+	    return
+	} else {
+	    
+
+	    #----Input Validation----------------------------------------------------------------------
+	    for {set a 0} {$a < [string length $LandmarkTitle]} {incr a} {
+		set achar [string range $LandmarkTitle $a $a]
+		
+		if {![string is wordchar $achar] && ![string is space $achar] \
+			&& ![string match {[.]} $achar] && ![string match {[-]} $achar] && ![string match {[^]} $achar]} {
+		    error "Cannot add landmark using character $achar  -- Node names can only can contain the following characters: \n     a-z, A-Z, 0-9, _, -, ., ^, and spaces"
+
+		    
+		}
+	    }
+	    #------------------------------------------------------------------------------------------
+
+
+	    
+	    if {$type == -1} {
+		set ThisLandmarkType [list Surface Landmark]   
+	    } else {
+		set ThisLandmarkType $type
+	    }
+	    
+	    set ProposedPath [file join [getPath $realtreename $ParentNodeID] $LandmarkTitle]
+	    set UniqueSuffix 1
+	    set suffixed 0
+	    
+	    while {[Tree::itemexists $vistree $ProposedPath]} {
+		
+		if { $suffixed == 1 } {
+		    #delete the suffix
+		    set LandmarkTitle [string replace $LandmarkTitle [string last _ $LandmarkTitle] end]
+		}
+		
+		append LandmarkTitle _ $UniqueSuffix
+		set ProposedPath [file join [getPath $realtreename $ParentNodeID] $LandmarkTitle]
+		set suffixed 1
+		incr UniqueSuffix
+	    }
+	    
+	    
+	    if {![Tree::itemexists $vistree $ProposedPath]} {
+		
+		#Create a unique identifier for the Landmark
+		set LandmarkID $MasterCount
+		incr MasterCount
+		
+		$realtreename insert $ParentNodeID end $LandmarkID
+		LandmarkInitialize $realtreename $LandmarkID
+		nameNode $realtreename $LandmarkID $LandmarkTitle
+		
+		$realtreename set $LandmarkID type $ThisLandmarkType
+		
+		
+	    } else { 
+		error "Please select a unique landmark name"
+	    }
+	}
+	set TreeChanged 1
+	return [list $suffixed $origTitle $LandmarkID]
+    } else {tk_messageBox -type ok -title "Need Selection" -message "Please select a parent in the tree" -icon info}         
+};#end of AddLandmark method
+
+::itcl::body chellyGUI::AddElectrode {realtreename ParentNodeID {title -1} {type -1}} {
+    if {[llength $ParentNodeID] > 0} {
+	if {$title == -1} {
+	    set ElectrodeTitle [Single_Entry_Dialog "New Electrode" "Enter a name for the new electrode map"]
+	} else { set ElectrodeTitle $title }
+	
+	set origTitle $ElectrodeTitle
+	
+	if {[string match $ElectrodeTitle -1] | $ElectrodeTitle == "" | [string equal -nocase $ElectrodeTitle "Cancel"]} { 
+	    return
+	} else {
+	    
+
+	    #----Input Validation----------------------------------------------------------------------
+	    for {set a 0} {$a < [string length $ElectrodeTitle]} {incr a} {
+		set achar [string range $ElectrodeTitle $a $a]
+		
+		if {![string is wordchar $achar] && ![string is space $achar] \
+			&& ![string match {[.]} $achar] && ![string match {[-]} $achar] && ![string match {[^]} $achar]} {
+		    		    error "Cannot add electrode using character $achar  -- Node names can only can contain the following characters: \n     a-z, A-Z, 0-9, _, -, ., ^, and spaces"
+		   
+		    
+		}
+	    }
+	    #------------------------------------------------------------------------------------------
+
+	    
+	    if {$type == -1} {
+		set ThisElectrodeType [list Surface Electrode]
+	    } else {
+		set ThisElectrodeType $type
+	    }
+	    
+	    set ProposedPath [file join [getPath $realtreename $ParentNodeID] $ElectrodeTitle]
+	    set UniqueSuffix 1
+	    set suffixed 0
+	    
+	    while {[Tree::itemexists $vistree $ProposedPath]} {
+		
+		if { $suffixed == 1 } {
+		    #delete the suffix
+		    set ElectrodeTitle [string replace $ElectrodeTitle [string last _ $ElectrodeTitle] end]
+		}
+		
+		append ElectrodeTitle _ $UniqueSuffix
+		set ProposedPath [file join [getPath $realtreename $ParentNodeID] $ElectrodeTitle]
+		set suffixed 1
+		incr UniqueSuffix
+	    }
+	    
+	    
+	    if {![Tree::itemexists $vistree $ProposedPath]} {
+		
+		#Create a unique identifier for the Electrode
+		set ElectrodeID $MasterCount
+		incr MasterCount
+		
+		$realtreename insert $ParentNodeID end $ElectrodeID
+		ElectrodeInitialize $realtreename $ElectrodeID
+		nameNode $realtreename $ElectrodeID $ElectrodeTitle
+		
+		$realtreename set $ElectrodeID type $ThisElectrodeType
+		
+		
+	    } else { 
+		error "Please select a unique electrode map name"
+	    }
+	}
+	set TreeChanged 1	
+	return [list $suffixed $origTitle $ElectrodeID]
+    } else {tk_messageBox -type ok -title "Need Selection" -message "Please select a parent in the tree" -icon info}
+    
+};#end of AddElectrode method
+
+::itcl::body chellyGUI::AddPatient {realtreename ParentNodeID {title -1}} {
+
+    if {[llength $ParentNodeID] > 0} {
+	if {$title == -1} {
+	    set PatientTitle [Single_Entry_Dialog "New Patient" "Enter a name for the new patient"]
+	} else { set PatientTitle $title }
+	
+	set origTitle $PatientTitle
+	
+	if {[string match $PatientTitle -1] | [string equal -nocase $PatientTitle "Cancel"]} { return } else {
+
+
+	    #----Input Validation----------------------------------------------------------------------
+	    for {set a 0} {$a < [string length $PatientTitle]} {incr a} {
+		set achar [string range $PatientTitle $a $a]
+		
+		if {![string is wordchar $achar] && ![string is space $achar] \
+			&& ![string match {[.]} $achar] && ![string match {[-]} $achar] && ![string match {[^]} $achar]} {
+		    
+		    error "Cannot add patient using character $achar  -- Node names can only can contain the following characters: \n     a-z, A-Z, 0-9, _, -, ., ^, and spaces"
+		    
+		}
+	    }
+	    #------------------------------------------------------------------------------------------
+
+	    set ProposedPath [file join [getPath $realtreename $ParentNodeID] $PatientTitle]
+	    set UniqueSuffix 1
+	    set suffixed 0
+	    
+	    while {[Tree::itemexists $vistree $ProposedPath]} {
+		
+		if { $suffixed == 1 } {
+		    #delete the suffix
+		    set PatientTitle [string replace $PatientTitle [string last _ $PatientTitle] end]
+		}
+		
+		append PatientTitle _ $UniqueSuffix
+		set ProposedPath [file join [getPath $realtreename $ParentNodeID] $PatientTitle]
+		set suffixed 1
+		incr UniqueSuffix
+	    }
+	    
+	    if {![Tree::itemexists $vistree $ProposedPath]} {
+		
+		#Create a unique identifier for the Patient
+		set PatientID $MasterCount
+		incr MasterCount
+		
+		$realtreename insert $ParentNodeID end $PatientID
+		PatientInitialize $realtreename $PatientID
+		nameNode $realtreename $PatientID $PatientTitle
+		
+		
+	    } else { error "Please select a unique patient name" }
+	}
+	set TreeChanged 1	
+	return [list $suffixed $origTitle $PatientID]
+	
+    } else {tk_messageBox -type ok -title "Need Selection" -message "Please select a parent in the tree" -icon info}
+}
+
+::itcl::body chellyGUI::AddFolder {realtreename ParentNodeID {title -1}} {
+    if {[llength $ParentNodeID] > 0} {
+	if {$title == -1} {
+	    set FolderTitle  [Single_Entry_Dialog "Add Folder" "Enter a name for the new folder"]
+	} else { set FolderTitle $title }
+	
+	set origTitle $FolderTitle
+	
+	if {[string match $FolderTitle -1] | $FolderTitle == "" | \
+		[string equal -nocase $FolderTitle "Cancel"]} { return } else {
+
+
+	    #----Input Validation----------------------------------------------------------------------
+	    for {set a 0} {$a < [string length $FolderTitle]} {incr a} {
+		set achar [string range $FolderTitle $a $a]
+		
+		if {![string is wordchar $achar] && ![string is space $achar] \
+			&& ![string match {[.]} $achar] && ![string match {[-]} $achar] && ![string match {[^]} $achar]} {
+		    error "Cannot add folder using character $achar  -- Node names can only can contain the following characters: \n     a-z, A-Z, 0-9, _, -, ., ^, and spaces"
+		    
+		}
+	    }
+	    #------------------------------------------------------------------------------------------
+
+
+
+		    
+		    set ProposedPath [file join [getPath $realtreename $ParentNodeID] $FolderTitle]
+		    set UniqueSuffix 1
+		    set suffixed 0
+		    
+		    while {[Tree::itemexists $vistree $ProposedPath]} {
+			
+			if { $suffixed == 1 } {
+			    #delete the suffix
+			    set FolderTitle [string replace $FolderTitle [string last _ $FolderTitle] end]
+			}
+			
+			append FolderTitle _ $UniqueSuffix
+			set ProposedPath [file join [getPath $realtreename $ParentNodeID] $FolderTitle]
+			set suffixed 1
+			incr UniqueSuffix
+		    }
+		    
+		    
+		    if {![Tree::itemexists $vistree $ProposedPath]} {
+			
+			#Create a unique identifier for the Folder
+			set FolderID $MasterCount
+			incr MasterCount
+			
+			$realtreename insert $ParentNodeID end $FolderID
+			FolderInitialize $realtreename $FolderID
+			nameNode $realtreename $FolderID $FolderTitle
+			
+						
+		    } else { 
+			error "Please select a unique image name"
+		    }
+		}
+	set TreeChanged 1	
+	return [list $suffixed $origTitle $FolderID]
+    } else {tk_messageBox -type ok -title "Need Selection" -message "Please select a parent in the tree" -icon info}
+};#end of AddFolder method
+
+
+::itcl::body chellyGUI::AddImage {realtreename ParentNodeID {title -1} {type -1}} {
+    if {[llength $ParentNodeID] > 0} {
+	if {$title == -1} {
+	    set ImageTitle [ImageEntryDialog]
+	} else { set ImageTitle $title }
+	
+	set origTitle $ImageTitle
+	
+	if {[string match $ImageTitle -1] | $ImageTitle == ""} { return } else {
+
+	    #----Input Validation----------------------------------------------------------------------
+	    for {set a 0} {$a < [string length $ImageTitle]} {incr a} {
+		set achar [string range $ImageTitle $a $a]
+		
+		if {![string is wordchar $achar] && ![string is space $achar] \
+			&& ![string match {[.]} $achar] && ![string match {[-]} $achar] && ![string match {[^]} $achar]} {
+		    error "Cannot add image using character $achar  -- Node names can only can contain the following characters: \n     a-z, A-Z, 0-9, _, -, ., ^, and spaces"
+		    
+		}
+	    }
+	    #------------------------------------------------------------------------------------------
+
+	    
+	    set ThisImageType -1
+	    if {$type == -1} {
+		#set image type if the name corresponds with one of the known types
+		foreach {key value} [array get RecognizedTypes] {
+		    if { $ImageTitle == $value } {
+			set ThisImageType $key
+		    }
+		}
+		
+		if {$ThisImageType == -1} {
+		    #		puts "Added an image of unrecognized type"
+		}
+		
+	    } else {
+		set ThisImageType $type
+	    }
+	    
+	    set ProposedPath [file join [getPath $realtreename $ParentNodeID] $ImageTitle]
+	    set UniqueSuffix 1
+	    set suffixed 0
+	    
+	    while {[Tree::itemexists $vistree $ProposedPath]} {
+		
+		if { $suffixed == 1 } {
+		    #delete the suffix
+		    set ImageTitle [string replace $ImageTitle [string last _ $ImageTitle] end]
+		}
+		
+		append ImageTitle _ $UniqueSuffix
+		set ProposedPath [file join [getPath $realtreename $ParentNodeID] $ImageTitle]
+		set suffixed 1
+		incr UniqueSuffix
+	    }
+	    
+	    
+	    if {![Tree::itemexists $vistree $ProposedPath]} {
+		
+		#Create a unique identifier for the Image
+		set ImageID $MasterCount
+		incr MasterCount
+		
+		$realtreename insert $ParentNodeID end $ImageID
+		ImageInitialize $realtreename $ImageID
+		nameNode $realtreename $ImageID $ImageTitle
+		$realtreename set $ImageID type $ThisImageType
+		
+		
+	    } else { 
+		error "Please select a unique image name"
+	    }
+	}
+	set TreeChanged 1	
+	return [list $suffixed $origTitle $ImageID]
+    } else {tk_messageBox -type ok -title "Need Selection" -message "Please select a parent in the tree" -icon info}
+};#end of AddImage method
+
+::itcl::body chellyGUI::undo { } {
+
+    puts "==========================="
+    puts $undoArray(previousCutParent)
+    puts $undoArray(previousPaste)
+    puts "==========================="
+#need before cut selectpath parent (call this B)
+#need after cut selectpath (call this A)
+#cut from A to B
+    $this mdCopy 1 $undoArray(previousPaste) 
+    $this mdPaste $undoArray(previousCutParent)
+#select A
+#cut A
+#select B
+}
+
+::itcl::body chellyGUI::AddSubtree {realtreename ParentNodeID {ListedTree -1}} {
+
+    if {$ListedTree == -1} {
+	#Get the list that specifies the tree definition arra
+	set ListedTree [$FileManager LoadDatatree]
+    }
+
+    if {$ListedTree != -1} {
+	$mdTopWidget config -cursor watch;  update idletasks    
+	#Rebuild the tree definition array
+	array set AddedTreeDefArray $ListedTree
+	
+	set TempTree [	::struct::tree [pxvtable::vnewobj] deserialize $AddedTreeDefArray(serialized)  ]
+
+	$TempTree set [$TempTree rootname] title [$TempTree rootname]
+	foreach node [$TempTree children -all [$TempTree rootname]] {
+	    $TempTree set $node title $AddedTreeDefArray($node,title)
+	}
+
+	set container 0;# Force no container for now.
+	if {$container != 0} {
+
+	    #------------------------------------------------------------------------------------------
+	    # Use this part to put in an extra containing folder made from the root node to hold the 
+	    # imported tree
+	    #------------------------------------------------------------------------------------------
+	    
+	    set FolderID $MasterCount
+	    incr MasterCount
+	    $realtreename insert $ParentNodeID end $FolderID
+	    FolderInitialize $realtreename $FolderID
+	    
+	    nameNode $realtreename $FolderID [$TempTree rootname]
+	    updateVisTree $vistree $RealTree $FolderID
+	    
+	    set folderpath [getPath $realtreename [$realtreename parent $FolderID]]
+	
+	    #------------------------------------------------------------------------------------------
+	} else {
+	    #make sure that folderpath refers to an existing, initialized node in the tree.  
+	    #(it becomes eqivalent to the rootnode in the source tree)
+	    set folderpath [getPath $realtreename $ParentNodeID]
+	    set folderpath [append folderpath /]
+	}
+	
+	$TempTree walk [$TempTree rootname] node {
+	    if {$node != [$TempTree rootname]} {
+
+		if {$container != 0} {
+		    set newpath [file join $folderpath [string trimleft [getPath $TempTree [$TempTree parent $node]] / ] ]
+		} else {
+		    set newpath [file join $folderpath [string trimleft [getPath $TempTree [$TempTree parent $node]] "/[$TempTree rootname]" ] ]
+		}
+
+		set ImageTitle [$TempTree get $node title]
+		set proposedpath [file join $newpath $ImageTitle]
+		set UniqueSuffix 1
+		set suffixed 0
+
+		while {[Tree::itemexists $vistree $proposedpath]} {
+		    
+		    if { $suffixed == 1 } {
+			#delete the suffix
+			set ImageTitle [string replace $ImageTitle [string last _ $ImageTitle] end]
+		    }
+		    
+		    append ImageTitle _ $UniqueSuffix
+		    set proposedpath [file join [getPath $realtreename $ParentNodeID] $ImageTitle]
+		    set suffixed 1
+		    incr UniqueSuffix
+		}
+		
+		#Rename the node in the def tree, so the walk works
+		$TempTree set $node title $ImageTitle
+		
+		set realparentID [GetIDFromSelection $newpath]
+
+	
+		#set the type
+		$TempTree set $node type $AddedTreeDefArray($node,type)
+
+		#----------------------------------------
+		if {[$TempTree get $node type] == "Patient"} { 
+		    set addedpatient [AddPatient $RealTree $realparentID $ImageTitle]
+		    if {[lindex $addedpatient 0]} {
+			error "Patient [lindex $addedpatient 1] already exists in tree"
+		    }
+		}
+		if {[$TempTree get $node type] == "Atlas"} {
+		    AddAtlasNode $RealTree $realparentID $ImageTitle
+		}
+		if {[$TempTree get $node type] == "ROIDef"} {
+		    AddROIDefNode $RealTree $realparentID $ImageTitle
+		}
+		if {[$TempTree get $node type] == "Folder"}  { 
+		    AddFolder $RealTree $realparentID $ImageTitle
+		}
+		if {[IsNodeImage $node $TempTree]} { 
+		    AddImage $RealTree $realparentID $ImageTitle [$TempTree get $node type]
+		}
+		if {[IsNodeSurface $node $TempTree]} {
+		    switch -exact -- [lindex [$TempTree get $node type] 1] {
+			"surface" -
+			"Surface" {
+			    AddSurface $RealTree $realparentID $ImageTitle [$TempTree get $node type]
+			}
+			"landmark" -
+			"Landmark" {
+			    AddLandmark $RealTree $realparentID $ImageTitle [$TempTree get $node type]
+			}
+			"electrode" -
+			"Electrode" {
+			    AddElectrode $RealTree $realparentID $ImageTitle [$TempTree get $node type]
+			}
+		    };# End switch
+		    
+		};#End if (Is it a surface?)
+		#----------------------------------------
+
+		#Now that it exists, figure out what ID it has been assigned
+		set RealNodeID [GetIDFromSelection [append newpath / $ImageTitle]]
+		
+		
+		#--------------------------------------------------
+		#Set the filenames if they are saved
+		#--------------------------------------------------
+		if { $AddedTreeDefArray($node,filename) != -1 } {
+		    setNodeFilename $RealNodeID $AddedTreeDefArray($node,filename)
+		}
+		if { $AddedTreeDefArray($node,transtoparfilename) != -1 } {
+		    setNodeTransformToParFile $RealNodeID $AddedTreeDefArray($node,transtoparfilename)
+		}
+		if { $AddedTreeDefArray($node,transfromparfilename) != -1 } {
+		    setNodeTransformFromParFile $RealNodeID $AddedTreeDefArray($node,transfromparfilename)
+		}
+		#--------------------------------------------------
+		
+		
+		if {$AddedTreeDefArray($node,isid)} {
+		    toggleIdentity $RealNodeID 1
+		}
+	
+		#set the notes for the node
+		if { [lsearch [array names AddedTreeDefArray] "${node},notes"] != -1 } {
+		    $RealTree set $RealNodeID notes [string map {{\n} \n} $AddedTreeDefArray($node,notes)]
+		} else {puts " ${node},notes Not there" }
+
+		
+		if {$container != 0} {
+		    set folderpath [getPath $realtreename [$realtreename parent $FolderID]]
+		} else { set folderpath [getPath $realtreename $ParentNodeID] }
+
+	    };# End if
+	}; # End walk
+
+	updateVisTree $vistree $RealTree $ParentNodeID
+	$surgerygadget WatchOff
+	$mdTopWidget config -cursor ""
+	set TreeChanged 1	
+
+    }
+}
+
+
+
+
+::itcl::body chellyGUI::AddMSBData { realtreename ParentNodeID {title -1} {ListedTree -1}} {
+
+    if {[llength $ParentNodeID] > 0} {
+ 	if {$ListedTree == -1} {
+ 	    #Get the list that specifies the tree definition arra
+ 	    set ListedTree [$FileManager LoadMSBfile]
+ 	}
+
+ 	if {$ListedTree != -1} {
+	    
+ 	    #Rebuild the tree definition array
+ 	    array set AddedTreeDefArray $ListedTree
+	    
+ 	    #First, add the reference Image as a child of the selection
+ 	    set ReferenceImage $AddedTreeDefArray(ReferenceImage)
+	    puts stderr "ParentNodeId=$ParentNodeID, $ReferenceImage"
+ 	    set REFimageID [lindex [AddImage $realtreename $ParentNodeID [file tail $ReferenceImage]] 2]
+ 	    setNodeFilename $REFimageID $ReferenceImage
+	    
+	    set suffixlist $AddedTreeDefArray(tasksuffixes)
+	    set tasknamelist $AddedTreeDefArray(tasknames)
+
+	    
+ 	    #Now, add all subjects as children of reference
+ 	    for {set n 0} {$n < $AddedTreeDefArray(numsubjects)} {incr n} {
+		
+ 		set AnatImage $AddedTreeDefArray($n,Anatomical)
+ 		set subjname  $AddedTreeDefArray($n,Name)
+
+ 		if {[llength $AnatImage] > 0} {
+
+ 		    set ANATimageID [lindex [AddImage $realtreename $REFimageID $subjname ] 2]
+ 		    setNodeFilename $ANATimageID $AnatImage
+ 		    if {[llength $AddedTreeDefArray($n,ReferenceTrans)] > 0} {
+ 			setNodeTransformFromParFile $ANATimageID $AddedTreeDefArray($n,ReferenceTrans)
+ 		    }
+ 		} else {set ANATimageID [lindex [AddImage $realtreename $REFimageID "Anatomical"] 2]}
+		
+ 		set ConvImage $AddedTreeDefArray($n,Conventional)
+ 		if {[llength $ConvImage] > 0} {
+ 		    set CONVimageID [lindex [AddImage $realtreename $ANATimageID "${subjname} Conventional"] 2]
+ 		    setNodeFilename $CONVimageID $ConvImage
+ 		    if {[llength $AddedTreeDefArray($n,InternalTrans)] > 0} {
+ 			setNodeTransformFromParFile $CONVimageID $AddedTreeDefArray($n,InternalTrans)
+ 		    }
+ 		} else {set CONVimageID [lindex [AddImage $realtreename $ANATimageID "${subjname} Conventional"] 2]}
+
+		#Add fieldmap image under conventional if it exists
+		set FieldMapImage $AddedTreeDefArray($n,FieldMap)
+ 		if {[llength $FieldMapImage] > 0} {
+ 		    set FIELDimageID [lindex [AddImage $realtreename $CONVimageID "$subjname Fieldmap"] 2]
+ 		    setNodeFilename $ECHOimageID $FieldMapImage
+ 		}
+
+		set NewFolderID [lindex [AddFolder $realtreename $CONVimageID "$subjname Functional Data"] 2]
+		toggleIdentity $NewFolderID 0
+		setNodeTransformFromParFile $NewFolderID $AddedTreeDefArray($n,DistortionTrans)
+
+		lappend VisCloseList $NewFolderID
+
+		#Add echoplanar image in folder if it exists
+		set EchoplanarImage $AddedTreeDefArray($n,Echoplanar)
+ 		if {[llength $EchoplanarImage] > 0} {
+ 		    set ECHOimageID [lindex [AddImage $realtreename $NewFolderID "$subjname Echoplanar"] 2]
+ 		    setNodeFilename $ECHOimageID $EchoplanarImage
+ 		    toggleIdentity $ECHOimageID 1
+ 		}
+
+ 		#--------------------------------------------------------------------------------
+		#Add all tasks in folder
+ 		for {set g 0} {$g < [llength $suffixlist]} {incr g} {
+ 		    set suffix [lindex $suffixlist $g]
+ 		    set ThisTaskImageFile $AddedTreeDefArray($n,Task_$suffix)
+ 		    if {[llength $ThisTaskImageFile] > 0} {
+ 			set TASKimageID [lindex [AddImage $realtreename $NewFolderID [lindex $tasknamelist $g]] 2]
+ 			setNodeFilename $TASKimageID $ThisTaskImageFile
+ 			toggleIdentity $TASKimageID 1
+ 		    } 
+		};# End of loop that runs for each task
+ 		#--------------------------------------------------------------------------------
+	    
+ 	    };# End of loop that runs for each subject
+
+
+	    # Add a folder to include all Average functional data etc.
+	    set FolderID [lindex [AddFolder $realtreename $REFimageID "00 Statistics"] 2]
+	    lappend VisCloseList $FolderID
+
+	    #--------------------------------------------------------------------------------
+	    #Now add the Average Anatomical
+	    set AverageAnatImage $AddedTreeDefArray(AverageAnatomical)
+	    if {[llength $AverageAnatImage] > 0} {
+		set AVGANATimageID [lindex [AddImage $realtreename $FolderID "Average Anatomical"] 2]
+		setNodeFilename $AVGANATimageID $AverageAnatImage
+		toggleIdentity $AVGANATimageID 1
+	    } 
+	    #Now add the Anatomical StdDev
+	    set StdAnatImage $AddedTreeDefArray(StdAnatomical)
+	    if {[llength $StdAnatImage] > 0} {
+		set STDANATimageID [lindex [AddImage $realtreename $FolderID "Anatomical Std Dev"] 2]
+		setNodeFilename $STDANATimageID $StdAnatImage
+		toggleIdentity $STDANATimageID 1
+	    } 
+		
+	    #--------------------------------------------------------------------------------
+	    # Functional Averages
+	    #--------------------------------------------------------------------------------
+	    foreach st {AverageFunctional StdFunctional ZscoreFunctional} {	   
+	     	for {set h 0} {$h < [llength $suffixlist]} {incr h} {
+	      		    set suffix [lindex $suffixlist $h]
+	      		    set ThisImageFile $AddedTreeDefArray($st,Task_$suffix)
+	      		    if {[llength $ThisTaskImageFile] > 0} {
+	      			set STATimageID [lindex [AddImage $realtreename $FolderID "$st - [lindex $tasknamelist $h]"] 2]
+	      			setNodeFilename $STATimageID $ThisImageFile
+	      			toggleIdentity $STATimageID 1
+	      		    } 
+	    	    
+		};# End of loop that runs for each task
+	    }
+	    updateVisTree $vistree $RealTree $ParentNodeID; CloseNodes $VisCloseList
+	}
+    } else {
+	tk_messageBox -type ok -title "Need Selection" -message "Please select a parent in the tree" -icon info
+    }
+}
+
+::itcl::body chellyGUI::AddCSIPatient { realtreename ParentNodeID {title -1} {ListedTree -1}} {
+
+    
+    if {$ListedTree == -1} {
+	#Get the list that specifies the tree definition arra
+	set ListedTree [$FileManager LoadCSIPatientFile]
+    }
+
+    if {$ListedTree != -1} {
+
+	#Rebuild the tree definition array
+	array set AddedTreeDefArray $ListedTree
+
+	#First, add the reference Image as a child of the selection
+	set CSIAnatomicalImage $AddedTreeDefArray(Anatomical)
+	set CSIAnatomicalID [lindex [AddImage $realtreename $ParentNodeID [file tail $CSIAnatomicalImage]] 2]
+	setNodeFilename $CSIAnatomicalID $CSIAnatomicalImage
+	
+	#Then, add the conventional image as a child of the Anatomical Image
+	set ConventionalImage $AddedTreeDefArray(Conventional)
+	set ConventionalID [lindex [AddImage $realtreename $CSIAnatomicalID [file tail $ConventionalImage]] 2]
+	setNodeFilename $ConventionalID $ConventionalImage
+	
+	#Set the transformation from the CSI Conv. up to the Anatomical
+	setNodeTransformFromParFile $ConventionalID $AddedTreeDefArray(TransAnat2CSIConv)
+
+
+	#Now add the other images as children of the conventional (They will all be identities)
+	set RawCSIImage $AddedTreeDefArray(RawCSIImage)
+	set RawCSIID [lindex [AddImage $realtreename $ConventionalID "Raw_CSI_Image"] 2]
+	setNodeFilename $RawCSIID $RawCSIImage
+	toggleIdentity $RawCSIID 1
+	#----------------------------------------------------------------------
+	set PMAPCSIImage $AddedTreeDefArray(PMAPCSIImage)
+	set PMAPCSIID [lindex [AddImage $realtreename $ConventionalID [file tail "PMAP_CSI_Image"]] 2]
+	setNodeFilename $PMAPCSIID $PMAPCSIImage
+	toggleIdentity $PMAPCSIID 1
+	#----------------------------------------------------------------------
+	if {[llength $AddedTreeDefArray(NormSmooth1)] > 0} {
+	    set NormSmooth1Image $AddedTreeDefArray(NormSmooth1)
+	    set NormSmooth1ID [lindex [AddImage $realtreename $ConventionalID "Normalized_Smoothed_1"] 2]
+	    setNodeFilename $NormSmooth1ID $NormSmooth1Image
+	    toggleIdentity $NormSmooth1ID 1
+	}
+	#----------------------------------------------------------------------
+	if {[llength $AddedTreeDefArray(NormSmooth2)] > 0} {
+	    set NormSmooth2Image $AddedTreeDefArray(NormSmooth2)
+	    set NormSmooth2ID [lindex [AddImage $realtreename $ConventionalID "Normalized_Smoothed_2"] 2]
+	    setNodeFilename $NormSmooth2ID $NormSmooth2Image
+	    toggleIdentity $NormSmooth2ID 1
+	}
+	
+	updateVisTree $vistree $RealTree $ParentNodeID
+	set TreeChanged 1
+	
+    }
+
+
+}
+
+::itcl::body chellyGUI::AddAllCSI { realtreename ParentNodeID } {
+
+    set folderpath [tk_chooseDirectory]
+    
+    foreach CSIfile [glob -directory $folderpath *.csi] {
+	
+	set ThisPatientID [lindex [AddPatient $realtreename $ParentNodeID [file tail [file root $CSIfile]]] 2]
+
+	set ThisListedTree [$FileManager LoadCSIPatientFile $CSIfile]
+	AddCSIPatient $RealTree $ThisPatientID -1 $ThisListedTree
+		
+    }
+
+    updateVisTree $vistree $RealTree $ParentNodeID
+    set TreeChanged 1
+
+}
+
+######################################################################
+######################################################################
+######################################################################
+######################################################################
+
+::itcl::body chellyGUI::nodeName { node } {
+    
+    foreach {key value} [array get NodeIDs] {
+	#	puts "$value --> $key"
+	if {$value == $node} {
+	    return [file tail $key]
+	}
+    }
+    
+    return -1
+    
+}
+
+::itcl::body chellyGUI::getNodesOfTransformation { trans } {
+    
+    set a [string range $trans [expr [string last , $trans] + 1] [expr [string first : $trans] - 1] ]
+    set b [string range $trans [expr [string last : $trans] + 1] end]
+    
+    lappend result $a
+    lappend result $b
+    
+    return $result
+    
+}
+
+
+::itcl::body chellyGUI::findTransforms { realtreename args } {
+    
+    #This method takes in (optionally) sequential pair of nodeIDs, and calculates the transformations between them
+    #If no nodes are specified, then all nodes in the tree are assumed, and all possible transformations calculated
+    
+    if {[llength $args] > 0} {
+	if {[expr fmod([llength $args],2)]} {error "findTransforms requires an even number of arguments"}
+	
+	foreach {n1 n2} $args {
+	    lappend nodeones $n1
+	    lappend nodetwos $n2
+	}
+	
+    } else {
+	
+	set nodeones  [$realtreename children -all [$realtreename rootname]]
+	set nodetwos  [$realtreename children -all [$realtreename rootname]]
+	
+    };# End else
+    
+    #--------------------------------------------------------------------------------
+    #This part of the method sets the "Transforms" array variable to
+    #contain the possible transformations for the tree nodes specified
+    
+    foreach node1 $nodeones {
+	foreach node2 $nodetwos {
+	    set TransformsCache($myname,$node1:$node2) [makeTransformList $realtreename $node1 $node2]
+	}
+    }
+    
+    
+};# End findTransforms method
+
+::itcl::body chellyGUI::makeTransformList { realtreename node1 node2 } {
+    
+    #This makes a list of transformations to go from the image at node1
+    #to the image at node2.  
+    
+    #First, get the nearest common ancestor for the two nodes
+    set common [commonAncestor $realtreename $node1 $node2]
+    
+    #-----------------------------------------------------------------------
+    #-----------------------------------------------------------------------
+    #Get the whole list of ancestors for node2
+    
+    set twoancestors [$realtreename ancestors $node2]
+    set twoparents [linsert $twoancestors 0 $node2]
+    
+    
+    #this yields the number of steps taken from node2 up to the common node
+    set num2 [lsearch $twoparents $common]
+    
+    #this trims the list to avoid overlaps
+    if { $node2 != $common } {
+	if {[llength $twoparents] > [expr [lsearch $twoparents $common] + 1]} {
+	    #set the list of images to go through back from node2 to the common node
+	    set twoback [lreplace $twoparents [expr [lsearch $twoparents $common] + 1] end]
+	} {set twoback [list $twoparents]} 
+    } else {set twoback [list $node2]}
+    
+    
+    #-----------------------------------------------------------------------
+    #Now Get the list of ancestors for node1
+    
+    set oneancestors [$realtreename ancestors $node1];#(this fails to include node1 itself)
+    set oneparents [linsert $oneancestors 0 $node1];#so we append it manually
+    
+    
+    #this yields the number of steps taken from node1 up to the common node
+    set num1 [lsearch $oneparents $common]
+    
+    #trim the list
+    if { $node1 != $common } {
+	if {[llength $oneparents] > [expr [lsearch $oneparents $common] + 1]} {
+	    #set the list of images to go through back from node1 to the common node
+	    set oneback [lreplace $oneparents [expr [lsearch $oneparents $common] + 1] end]
+	} else {set oneback [list $oneparents]}
+    } else { set oneback [list $node1]}
+    
+    
+    
+    #-----------------------------------------------------------------------
+    #-----------------------------------------------------------------------
+    
+    
+    #Create a list out of the connections between each member of oneback and its
+    #subsequent entry
+    if {[llength $oneback] > 1} {
+	for {set y 0} {$y < [expr [llength $oneback] - 1]} {incr y} {
+	    lappend TransformList "$myname,[lindex $oneback $y]:[lindex $oneback [expr $y + 1]]"
+	}
+    } else {lappend TransformList "identity"}
+    
+    #Now append an inverse list of twoback, forming the total transformation path
+    if {[llength $twoback] > 1} {
+	for {set x [expr [llength $twoback] - 1]} {$x > 0} {incr x -1} {
+	    lappend TransformList "$myname,[lindex $twoback $x]:[lindex $twoback [expr $x - 1]]"
+	}
+    } else {lappend TransformList "identity"}
+    
+    
+    #Strike out any element in listoftransforms with the value "identity"
+    while {[lsearch $TransformList identity] != -1} {
+	set z [lsearch $TransformList identity]
+	set TransformList [ lreplace $TransformList $z $z ]
+    }
+    
+    return $TransformList
+    
+}
+
+::itcl::body chellyGUI::commonAncestor { realtreename node1 node2 } {
+    
+    set oneuppers [$realtreename ancestors $node1] 
+    set twouppers [$realtreename ancestors $node2]
+    
+    set ones [ linsert $oneuppers 0 $node1]
+    set twos [ linsert $twouppers 0 $node2]
+    
+    for {set x 0} {$x < [llength $ones]} {incr x} {
+	if {[lsearch $twos [lindex $ones $x]] != -1} {
+	    set commonNode [lindex $twos [lsearch $twos [lindex $ones $x]]]
+	    if {$commonNode != [$realtreename rootname]} {
+
+		    return $commonNode
+
+	    } else { return $commonNode }
+	}
+    }
+}
+
+
+::itcl::body chellyGUI::removeIDnodes { realtreename nodelist } {
+    
+    #This will get rid of any images in the list whose "IsIdentity" property has been set to 1
+    #First set up a key list from the values of the key in the tree
+    for {set n 0} {$n < [llength $nodelist]} {incr n} {
+	lappend ikeylist [$realtreename get [lindex $nodelist $n] IsIdentity]
+    }
+    
+    
+    #Now modify the list, to change any node that corresponds to an identity key to a dummy value
+    for {set m 0} {$m < [llength $nodelist]} {incr m} {
+	if {[lindex $ikeylist $m] == 1} {
+	    lappend modlist identity
+	} else { lappend modlist [lindex $nodelist $m] }
+    }
+    
+    return $modlist
+    
+    #now go through and strike out any element in the list with the value "identity"
+    while {[lsearch $modlist identity] != -1} {
+	set z [lsearch $modlist identity]
+	set modlist [ lreplace $modlist $z $z]
+    }
+    
+    
+}
+
+
+::itcl::body chellyGUI::checkForIllegalCharacters { inputName } {
+  
+    for {set a 0} {$a < [string length $inputName]} {incr a} {
+	set achar [string range $inputName $a $a]
+	
+	if {![string is wordchar $achar] && ![string is space $achar] \
+		&& ![string match {[.]} $achar] && ![string match {[-]} $achar] && ![string match {[^]} $achar]} {
+	    
+	    set warning "Cannot rename node using character $achar  -- Node names can only can contain the following characters: \n     a-z, A-Z, 0-9, _, -, ., ^, and spaces."
+	    
+	    tk_messageBox -type ok -title "Please choose a new name" -message $warning -icon error
+	    return 0
+	}
+    }   
+    return 1
+}
+
+::itcl::body chellyGUI::nameNode {realtreename node newtitle  } {
+     
+    if {0} {
+    set selectionPath "[ lindex [ Tree::getselectionpath $vistree ] 0 ]/"
+    foreach path [ array names NodeIDs ] {
+	if { [ regexp ^$selectionPath $path ] } {
+	    #unset NodeIDs($path)
+	}   
+    }
+    #unset NodeIDs([ lindex [ Tree::getselectionpath $vistree ] 0 ])
+    }
+
+
+    if {0} {
+	
+	set selectionTitle [ $realtreename get $node title ]
+	set selectionPath "[ lindex [ Tree::getselectionpath $vistree ] 0 ]/"
+	set offset [ expr [ string length $selectionPath ] - [ string length $selectionTitle ] - 2 ]
+	
+	foreach path [ array names NodeIDs ] {
+	    if { [ regexp ^$selectionPath $path ] } {
+		puts "-------------------------------"
+		puts $path
+		set newSelectionPath [ regsub -start $offset -- $selectionTitle $path $newtitle ] ;#figure out
+		puts $newSelectionPath
+		puts "-------------------------------"
+		#set NodeIDs($newSelectionPath) $NodeIDs($path)
+		#unset NodeIDs($path)
+	    }
+	}
+	#unset NodeIDs([ lindex [ Tree::getselectionpath $vistree ] 0 ])
+	#$realtreename set $node title $newtitle
+    }
+    
+
+
+
+
+
+
+
+    #--------------------------------------------------
+    #This figures out all keys in NodeIDs that will be deleted
+    set pathList [$realtreename rootname]
+    set pathListIDs [$realtreename ancestors $node]
+ 
+    for {set y [expr [llength $pathListIDs] - 1]} {$y > -1} {incr y -1} {
+	if {[lindex $pathListIDs $y] != [$realtreename rootname]} {
+	    lappend pathList [$realtreename get [lindex $pathListIDs $y] title]
+    	}
+    }
+    
+    set pathName /
+    for {set i 0} {$i < [llength $pathList]} {incr i} {
+	    append pathName [lindex $pathList $i]
+	append pathName /
+    }
+    
+    append pathName [$realtreename get $node title]
+    
+    lappend PathsToDelete $pathName
+    
+    unset pathName
+    
+    #--------------------------------------------------
+    
+    #We must also delete all the keys for the children 
+    foreach child [$realtreename children -all $node] {
+	
+	#--------------------------------------------------
+	#This sets the key in the reverse array for a lookup
+	set pathList [$realtreename rootname]
+	set pathListIDs [$realtreename ancestors $child]
+	
+	for {set y [expr [llength $pathListIDs] - 1]} {$y > -1} {incr y -1} {
+	    if {[lindex $pathListIDs $y] != [$realtreename rootname]} {
+		    lappend pathList [$realtreename get [lindex $pathListIDs $y] title]
+		
+	    }
+	}
+	
+	set pathName /
+	for {set i 0} {$i < [llength $pathList]} {incr i} {
+		append pathName [lindex $pathList $i]
+	    append pathName /
+	}
+	
+	append pathName [$realtreename get $child title]
+	
+	lappend PathsToDelete $pathName
+	
+	    unset pathName
+	
+	#--------------------------------------------------
+    }
+    
+    
+    #Now, for any item in PathsToDelete, we delete the key in NodeIDs
+
+    foreach path $PathsToDelete {
+	catch {unset NodeIDs($path)}
+    }
+
+    
+    #------------------------------------------------------------------------------------------
+    
+    
+    #Now we rename the node and reset all the Lookup keys in NodeIDs
+    #####################################################
+	
+    $realtreename set $node title $newtitle	
+   
+    #####################################################
+    
+    #--------------------------------------------------
+    #This sets the key in the reverse array for a lookup
+    set pathList [$realtreename rootname]
+    set pathListIDs [$realtreename ancestors $node]
+    
+    for {set y [expr [llength $pathListIDs] - 1]} {$y > -1} {incr y -1} {
+	if {[lindex $pathListIDs $y] != [$realtreename rootname]} {
+	    lappend pathList [$realtreename get [lindex $pathListIDs $y] title]
+	    
+	}
+    }
+	
+    set pathName /
+	for {set i 0} {$i < [llength $pathList]} {incr i} {
+	    append pathName [lindex $pathList $i]
+	    append pathName /
+	}
+    append pathName [$realtreename get $node title]
+    #puts $pathName
+    set NodeIDs($pathName) $node
+	
+    #--------------------------------------------------
+    
+    foreach child [$realtreename children -all $node] {
+	
+	#--------------------------------------------------
+	#This sets the key in the reverse array for a lookup
+	set pathList [$realtreename rootname]
+	set pathListIDs [$realtreename ancestors $child]
+	
+	for {set y [expr [llength $pathListIDs] - 1]} {$y > -1} {incr y -1} {
+		if {[lindex $pathListIDs $y] != [$realtreename rootname]} {
+		    lappend pathList [$realtreename get [lindex $pathListIDs $y] title]
+		    
+		}
+	}
+	
+	    set pathName1 /
+	for {set i 0} {$i < [llength $pathList]} {incr i} {
+	    append pathName1 [lindex $pathList $i]
+	    append pathName1 /
+	}
+	append pathName1 [$realtreename get $child title]
+	
+	set NodeIDs($pathName1) $child
+	#--------------------------------------------------
+	    
+    }
+    
+    set TreeChanged 1
+}
+
+
+
+
+#------------------------------------------------------------------------------------------
+::itcl::body chellyGUI::setNodeFilename { node {filename -1}} {
+    
+    if {$node != ""} {
+	if {$node == [$RealTree rootname]} { return -1 } 
+	if {![$RealTree keyexists $node pxitclobj]} { return -1 }
+	
+	if {$filename == -1} {
+	    
+	    if {[IsNodeImage $node -1 1]} {
+		set nu  [$FileManager GetImageFileName]
+		if {$nu != -1} {
+		    $RealTree set $node FileName $nu
+		}
+	    } else {
+		if {[lindex [$RealTree get $node type] 0] == "Surface"} {
+		    switch -exact -- [lindex [$RealTree get $node type] 1] {
+			"Surface" {
+			    set nu  [$FileManager GetSurfaceFileName]
+			    if {$nu != -1} {
+				$RealTree set $node FileName $nu
+			    }
+			}
+			"Landmark" {
+			    set nu  [$FileManager GetLandmarkFileName]
+			    if {$nu != -1} {
+				$RealTree set $node FileName $nu
+			    }
+			}
+			"Electrode" {
+			    set nu [$FileManager GetElectrodeFileName]
+			    if {$nu != -1} {
+				$RealTree set $node FileName $nu
+			    }
+			}
+		    }
+		}
+	    }
+	} else {
+	    $RealTree set $node FileName $filename
+	}
+	
+	$RealTree set $node FileLoaded 0
+	
+	
+	#----------------------------------------------------------------------------------------------------------#
+	#Uncomment this for loading of file as soon as filename is set (insted of on-demand)                       #
+	# 	if {[IsNodeImage $node -1 1]} {                                                                         #
+	# 	    $FileManager LoadFile [$RealTree get $node pxitclobj] [$RealTree get $node FileName] Image     #
+	# 	} else {                                                                                           #
+	#                                                                                                          #
+	#	if {[lindex [$RealTree get $node type] 0] == "Surface"} {                                          #
+	#	    switch -exact -- [lindex [$RealTree get $node type] 1] {                                       #
+	#		                                                                                           #
+	# 		"Surface" {$FileManager LoadFile [$RealTree get $node pxitclobj] \                         #
+	# 			       [$RealTree get $node FileName] Surface}                                     #
+	# 		"Landmark" {$FileManager LoadFile [$RealTree get $node pxitclobj] \                        #
+	# 				[$RealTree get $node FileName] Landmark}                                   #
+	# 		"Electrode" {$FileManager LoadFile [$RealTree get $node pxitclobj] \                       #
+	# 				 [$RealTree get $node FileName] Electrode}                                 #
+	# 	    }                                                                                              #
+	#         }                                                                                           #
+	#	}                                                                                                  #
+	#----------------------------------------------------------------------------------------------------------#
+	
+	#If the node happens to be the atlas definition node, send the pxitcl object to AtlasProg class
+	# and load the Image automatically
+	if {[$RealTree get $node type] == "Atlas"} {
+	    if { $AtlasModule !=0 } {
+		$AtlasModule SetAtlasSpaceDefImage [$RealTree get $node pxitclobj]
+	    }
+	    $FileManager LoadFile [$RealTree get $node pxitclobj] [$RealTree get $node FileName] Image
+	    $RealTree set $node FileLoaded 1
+	}
+	
+	#Set the status bar to read out the filename
+	$statusLabel config -text [$RealTree get $node FileName]
+	
+	if {[$RealTree get $node FileName] != -1} {
+	    $RealTree set $node icon $brainiconchoice
+	}
+
+	set TreeChanged 1	
+
+    } else {return -1}
+}
+
+::itcl::body chellyGUI::setNodeTransformToParFile { node {filename -1}} {
+    
+    ###Sets the transformation up TO the parent
+ 
+    if {$node != ""} {
+	if {$node == [$RealTree rootname]} { return -1 }
+	if {![$RealTree keyexists $node pxitclTransToParent]} { return -1 }
+	
+	if {$filename == -1} {
+	    set nutrns [$FileManager GetTransformationFileName]
+	    if {$nutrns != -1} {
+		$RealTree set $node TransToParFileName $nutrns
+	    }
+
+	} else {
+	    $RealTree set $node TransToParFileName $filename
+	}
+
+	#Set the "filename" "fileset" tags in the TransformsCache Array
+	if {[$RealTree get $node TransToParFileName] != -1} {
+	    $RealTree set $node ToParFilenameSet 1
+
+	    set TransformsCache($myname,$node:[$RealTree parent $node],fname) [$RealTree get $node TransToParFileName]
+	    set TransformsCache($myname,$node:[$RealTree parent $node],fileset) 1
+
+	    #puts "Setting TransformsCache($node:[$RealTree parent $node],fileset) to 1"
+	    #puts " --- name:  [$RealTree get $node TransToParFileName]"
+	    #puts "-------- extension:  [file extension [$RealTree get $node TransToParFileName]]"
+
+	}
+
+	#----------------------------------------
+	#If the transformation is a matrix, it is pretty small, so just load it right away
+	if { [file extension [$RealTree get $node TransToParFileName]] == ".matr"} {
+	    #puts "Loading $node:$RealTree parent $node automatically"
+
+	    $FileManager LoadTransformationFile [$RealTree get $node pxitclTransToParent] \
+		[$RealTree get $node TransToParFileName]
+	    
+	    #Set the "loaded" property of the Cache Array to 1
+
+	    set TransformsCache($myname,$node:[$RealTree parent $node],loaded) 1
+	    
+	    
+	    set vtk_transform [[$RealTree get $node pxitclTransToParent] GetObject]
+	    set forig [ $RealTree get $node TransToParFileName ]
+	    
+#	    puts "Is Transformation Linear?: [ $vtk_transform IsA "vtkLinearTransform" ]"
+
+	    #If it's linear, we can just load the inverse as well
+	    #------------------------------------------------------------
+
+
+	    if { [ $vtk_transform IsA "vtkLinearTransform" ] == 1 } {
+
+		set tr2 $myname,[$RealTree parent $node]:$node 
+		$tr2 CopyTransformation $vtk_transform
+		$tr2 configure -filename $forig
+		$tr2 Invert
+		$tr2 configure -filename "[ $tr2 cget -filename ].donotsave" 
+
+		$RealTree set $node FromParFilenameSet 1
+
+		#set the inverse file name
+		$RealTree set $node TransFromParFileName [$tr2 cget -filename]
+
+		
+
+		set TransformsCache($myname,[$RealTree parent $node]:$node,fname) [$tr2 cget -filename]
+		set TransformsCache($myname,[$RealTree parent $node]:$node,fileset) 1
+		set TransformsCache($myname,[$RealTree parent $node]:$node,loaded) 1
+		
+	    }
+	    #------------------------------------------------------------
+	}
+	#----------------------------------------
+		
+	doTransformsExist $RealTree $node
+	set TreeChanged 1
+    }
+     
+}
+
+::itcl::body chellyGUI::setNodeTransformFromParFile { node {filename -1}} {
+    
+    ###Set the transformation down FROM the parent
+ 
+
+    if {$node != ""} {
+	if {$node == [$RealTree rootname]} { return -1 } 
+	if {![$RealTree keyexists $node pxitclTransFromParent]} { return -1 }
+	
+	if {$filename == -1} {
+	    set nutrns [$FileManager GetTransformationFileName]
+	    if {$nutrns != -1} {
+		$RealTree set $node TransFromParFileName $nutrns
+	    }
+	} else {
+	    $RealTree set $node TransFromParFileName $filename
+	}
+
+	if {[$RealTree get $node TransFromParFileName] != -1} {
+	    $RealTree set $node FromParFilenameSet 1	
+	    set TransformsCache($myname,[$RealTree parent $node]:$node,fname) [$RealTree get $node TransFromParFileName]
+	    set TransformsCache($myname,[$RealTree parent $node]:$node,fileset) 1
+
+	    #puts "Setting TransformsCache($myname,$node:[$RealTree parent $node],fileset) to 1"
+	    #puts "---name: [$RealTree get $node TransFromParFileName]"
+	    #puts "extension:  [file extension [$RealTree get $node TransFromParFileName]]"
+
+
+
+	}
+
+
+
+	#----------------------------------------
+	#If the transformation is a matrix, it is pretty small, so just load it right away
+	if { [file extension [$RealTree get $node TransFromParFileName]] == ".matr"} {
+
+
+
+	    $FileManager LoadTransformationFile [$RealTree get $node pxitclTransFromParent] \
+		[$RealTree get $node TransFromParFileName]
+	
+	    set TransformsCache($myname,[$RealTree parent $node]:$node,loaded) 1
+
+	    set vtk_transform [[$RealTree get $node pxitclTransFromParent] GetObject]
+	    set forig [ $RealTree get $node TransFromParFileName ]
+	    
+	    #If it's linear, we can just load the inverse as well
+	    if { [ $vtk_transform IsA "vtkLinearTransform" ] == 1 } {
+
+		set tr2 [$myname,$node:[$RealTree parent $node] GetThisPointer]
+		$tr2 CopyTransformation $vtk_transform
+		$tr2 configure -filename $forig
+		$tr2 Invert
+		$tr2 configure -filename "[ $tr2 cget -filename ].donotsave" 
+		
+
+		$RealTree set $node ToParFilenameSet 1
+
+		$RealTree set $node TransToParFileName [$tr2 cget -filename]
+
+		set TransformsCache($myname,$node:[$RealTree parent $node],fname) [$tr2 cget -filename]
+		set TransformsCache($myname,$node:[$RealTree parent $node],fileset) 1
+		set TransformsCache($myname,$node:[$RealTree parent $node],loaded) 1
+
+	    }
+	    
+	}
+	#----------------------------------------
+	
+    #This sets the Visualization tree linecolors to reflect the presence of transforms
+    doTransformsExist $RealTree $node
+    set TreeChanged 1
+
+    }
+
+   
+    
+}
+
+
+::itcl::body chellyGUI::toggleIdentity { node {explicitSetting -1}} {
+      
+    if {![$RealTree keyexists $node IsIdentity]} { return -1 }
+    set current [$RealTree get $node IsIdentity]
+    
+        
+    if { $current == 1 | $explicitSetting == 0 } { 
+	
+	####----------------------------------------
+	#set the "IsIdentity" property to 0 and set all transformations to and from this node as unloaded
+	####----------------------------------------
+	
+	$RealTree set $node IsIdentity 0
+	
+	if {[$RealTree get $node FileName] != -1} {
+	    $RealTree set $node icon $brainiconchoice
+	} else {
+	    $RealTree set $node icon ibraingrey
+	}
+	
+	$RealTree set $node ToParFilenameSet 0
+	set TransformsCache($myname,$node:[$RealTree parent $node],fileset) 0
+	set TransformsCache($myname,$node:[$RealTree parent $node],loaded) 0
+	$RealTree set $node FromParFilenameSet 0
+	set TransformsCache($myname,[$RealTree parent $node]:$node,fileset) 0
+	set TransformsCache($myname,[$RealTree parent $node]:$node,loaded) 0
+	
+	
+	#  	foreach child [$RealTree children $node] {
+	#  	    $RealTree set $child ToParFilenameSet 0
+	#  	    set TransformsCache($myname,$child:[$RealTree parent $child],fileset) 0
+	#  	    set TransformsCache($myname,$child:[$RealTree parent $child],loaded) 0
+	#  	    $RealTree set $child FromParFilenameSet 0
+	#  	    set TransformsCache($myname,[$RealTree parent $child]:$child,fileset) 0
+	#  	    set TransformsCache($myname,[$RealTree parent $child]:$child,loaded) 0
+	
+	# 	}
+	
+	set new [$RealTree get $node IsIdentity]
+
+	set TreeChanged 1
+	
+	if { $explicitSetting != 1} {
+	    return $new
+	}
+
+    } 
+    
+    if { $current == 0 | $explicitSetting == 1 } {
+	
+	#--------------------------------------------------
+	#Set as Identity
+	#--------------------------------------------------
+	
+	#Set the tag
+	$RealTree set $node IsIdentity 1 
+	#Set transformation to and from parent to identity matrix (Clear)
+	[$RealTree get $node pxitclTransToParent] Clear
+	[$RealTree get $node pxitclTransFromParent] Clear
+	
+	$RealTree set $node ToParFilenameSet 1
+	set TransformsCache($myname,$node:[$RealTree parent $node],fileset) 1
+	set TransformsCache($myname,$node:[$RealTree parent $node],loaded) 1
+	$RealTree set $node FromParFilenameSet 1
+	set TransformsCache($myname,[$RealTree parent $node]:$node,fileset) 1
+	set TransformsCache($myname,[$RealTree parent $node]:$node,loaded) 1
+	
+	# 	#Also set transform objects to Clear for to and from children
+	#  	foreach child [$RealTree children $node] {
+	#  	    [$RealTree get $child pxitclTransToParent] Clear
+	#  	    [$RealTree get $child pxitclTransFromParent] Clear
+	
+	#  	    $RealTree set $child ToParFilenameSet 1
+	#  	    set TransformsCache($myname,$child:[$RealTree parent $child],fileset) 1
+	#  	    set TransformsCache($myname,$child:[$RealTree parent $child],loaded) 1
+	#  	    $RealTree set $child FromParFilenameSet 1
+	#  	    set TransformsCache($myname,[$RealTree parent $child]:$child,fileset) 1
+	#  	    set TransformsCache($myname,[$RealTree parent $child]:$child,loaded) 1
+	#  	}
+	
+	#     }
+	
+	set new [$RealTree get $node IsIdentity]
+	set TreeChanged 1
+	return $new
+	
+    }
+
+
+::itcl::body chellyGUI::GetIDFromSelection {args} {
+    
+    if {[llength $args] > 0} {
+	set nodepath [concat $args]
+    } else {
+	set nodepath [Tree::getselectionpath $vistree]
+    }    
+
+    if {[lindex $nodepath 0] != "" && [lindex $nodepath 0] != "{}" && $nodepath != "{}" && $nodepath != "" } {
+	set ID $NodeIDs([lindex $nodepath 0])
+	return $ID
+    }
+}
+
+::itcl::body chellyGUI::EnsureFileLoaded { node } {
+    
+    set reload 0; #if this is reset to 1 by the FileManager, then the user will be queried to set a new filename
+    
+    #------------------------------------------------------------------------------------------
+    #If the file is known, but not loaded, load it
+    if {[$RealTree get $node FileName] != -1 } {
+	if {![$RealTree get $node FileLoaded]} {
+	    
+	    
+	    if {[IsNodeImage $node -1 1]} {
+		set reload [$FileManager LoadFile [$RealTree get $node pxitclobj] [$RealTree get $node FileName] Image]
+	    } else {
+		if {[lindex [$RealTree get $node type] 0] == "Surface"} {
+		    switch -exact -- [lindex [$RealTree get $node type] 1] {
+			"Surface" {set reload [$FileManager LoadFile [$RealTree get $node pxitclobj] \
+						   [$RealTree get $node FileName] Surface]}
+			"Landmark" {set reload [$FileManager LoadFile [$RealTree get $node pxitclobj] \
+						    [$RealTree get $node FileName] Landmark]}
+			"Electrode" {set reload [$FileManager LoadFile [$RealTree get $node pxitclobj] \
+						     [$RealTree get $node FileName] Electrode]}
+		    }
+		}
+	    }
+	    
+	    #--------------------------------------------------------------------------------
+	    # If reload has been set to 1, then let the user specify the node filename
+	    if { $reload == 1 } { 
+		setNodeFilename $node 
+		EnsureFileLoaded $node
+		updateVisTree $vistree $RealTree $node
+	    }
+	    #--------------------------------------------------------------------------------
+
+	    $RealTree set $node FileLoaded 1
+	}
+    } else { 
+
+	#--------------------------------------------------------------------------------
+	# If the user wants to specify a file here, do it, and update the tree
+	if {[tk_messageBox -type yesno -default no \
+		 -message "The file that [$RealTree get $node title] points to does not appear to exist.  Would you like to specify a new one?" -icon question] == "yes"} {
+	    setNodeFilename $node 
+	    EnsureFileLoaded $node	 
+	    updateVisTree $vistree $RealTree $node
+	}
+	#--------------------------------------------------------------------------------
+    }
+    #------------------------------------------------------------------------------------------
+    
+    
+    
+}
+
+
+::itcl::body chellyGUI::EnsureTransListLoaded { listoftransforms } {
+  
+    #-----------------------------------------------------------------------
+    # make sure all members of listoftransforms have been loaded
+    foreach trns $listoftransforms {
+
+	#If the filename of the transformation is known, but it has not been loaded, then load it
+	if { [info exists TransformsCache($trns,fileset)] } {
+	    if { $TransformsCache($trns,fileset) == 1 } {
+		
+		if { [info exists TransformsCache($trns,loaded)] } {
+		    if { $TransformsCache($trns,loaded) != 1 } {
+			$FileManager LoadTransformationFile chellyGUI::$trns $TransformsCache($trns,fname)
+		    }
+		} else {
+		    $FileManager LoadTransformationFile chellyGUI::$trns $TransformsCache($trns,fname)
+		}
+	    } else { 
+		set g [nodeName [lindex [getNodesOfTransformation $trns] 0]]
+		set h [nodeName [lindex [getNodesOfTransformation $trns] 1]]
+		error "Transformation not specified for $trns -- $g to $h (Error 0)"
+	    }
+	} else { 
+	    set g [nodeName [lindex [getNodesOfTransformation $trns] 0]]
+	    set h [nodeName [lindex [getNodesOfTransformation $trns] 1]]
+	    error "Transformation not specified for $trns -- $g to $h (Error -1)"
+	}
+
+
+    }
+    #---------------------------------------------------------------------------
+
+  
+     
+    
+}
+
+
+
+
+
+
+#------------------------------------------------------------------------------------------
+# Public Methods of chellyGUI 
+#------------------------------------------------------------------------------------------
+
+
+#Setter methods to let this class know where the image and transformation control objects are
+::itcl::body chellyGUI::setSpaceControlWidget { widget } { set SpaceControlWidget $widget }
+::itcl::body chellyGUI::setAnatomicalControlWidget { widget } { set AnatomicalControlWidget $widget }
+::itcl::body chellyGUI::setFunctionalControlWidget { widget } { set FunctionalControlWidget $widget }
+::itcl::body chellyGUI::setTransformationControlWidget { widget } { set TransformationControlWidget $widget }
+
+::itcl::body chellyGUI::sendSelectionToDisplay { viewerno {ref -1} {node -1}} {
+    
+    set referencenode -1
+    switch -exact -- $node {
+	
+	"SpaceImage" {
+	    set node $SpaceImage
+	}
+	
+	"AnatomicalImage" {
+	    set node $AnatomicalImage
+	}
+	
+	"FunctionalImage" {
+	    set node $FunctionalImage
+	}	
+	
+	-1 {
+	    set node [GetIDFromSelection]
+	}
+    }
+    
+    if {$node != -1} {
+	
+	set pxiobj [$RealTree get $node pxitclobj]
+	set type [$RealTree get $node type]
+	
+	#If the "ref" argument is set, then get the reference object from "SpaceImage"
+	if {$ref != -1} { 
+	    if {$SpaceImage != -1} {
+		set referencenode $SpaceImage
+	    } else { error "The Space has not been set"; return -1 }
+	}
+	
+	EnsureFileLoaded $node
+	
+	if {[IsNodeSurface $node]} {
+	    set surftype [lindex $type 1]
+	    switch -exact -- $surftype {
+		"surface" - 
+		"Surface" {
+		    displaySurface $viewerno $node $referencenode
+		}
+		"landmark" -
+		"Landmark" {
+		    displayLandmarks $viewerno $node $referencenode
+		}
+		"electrode" -
+		"Electrode" {
+		    displayElectrodes $viewerno $node $referencenode
+		}
+	    };# End switch
+	};# End if IsNodeSurface
+	
+	if {[IsNodeImage $node -1 1]} {
+	    
+	    displayImage $viewerno $node $referencenode
+	    
+	};# end if IsNodeImage
+	
+    };# end "if $node != -1"
+    
+};#End sendSelectionToDisplay method
+
+::itcl::body chellyGUI::displayImage { viewerno imagenode { refnode -1} {background 0} } {
+    
+    EnsureFileLoaded $imagenode
+    set imageobj [$RealTree get $imagenode pxitclobj]
+    
+    set viewer $viewer1; if { $viewerno == 2 && $viewer2 != 0 }  { set viewer $viewer2 }
+    if { $viewer == 0 } {	return    }
+    
+    if {$refnode != -1} {
+	puts "sending image to $viewerno in space of $refnode"
+	
+	findTransforms $RealTree $refnode $imagenode
+	set TopDownTransList $TransformsCache($myname,$refnode:$imagenode)
+	EnsureTransListLoaded $TopDownTransList
+	set gen [ CreateTransformation $TopDownTransList ]
+	
+	if { $reslmode < 1 } {
+	    set reslmode 0 
+	} elseif { $reslmode > 1 } {
+	    set reslmode 3
+	}
+
+	if { $reslmode == 1 } {
+	    set range [ [ [ [ $imageobj GetImage ] GetPointData ] GetScalars ] GetRange ]
+	    if { [ lindex $range 1 ] < 2.0 } {
+		set reslmode 3
+		puts stderr "Switching to Cubic Interpolation because intensity range is 0 - 1"
+	    }
+	}
+
+	
+	set baseimage [$RealTree get $refnode pxitclobj]
+	set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+	
+	$resl SetInformationInput [ $baseimage GetImage ]
+	$resl SetInput [ $imageobj GetImage ]
+	$resl SetResliceTransform $gen
+	$resl SetInterpolationMode $reslmode
+	
+	$resl SetBackgroundLevel $background
+	$resl OptimizationOff
+	$resl Update
+	
+	set newimg [ [ pxitclimage \#auto] GetThisPointer ]
+	$newimg ShallowCopyImage [ $resl GetOutput ]
+	$newimg CopyImageHeader [ $baseimage GetImageHeader ]
+	
+	$resl Delete
+	$gen Delete
+	
+	$viewer SetImageFromObject $newimg $this
+	$viewer ShowWindow
+	::itcl::delete object $newimg 
+	
+	
+    } else {
+	$viewer SetImageFromObject $imageobj $this  
+	$viewer ShowWindow
+    }
+    
+    
+    
+}
+
+::itcl::body chellyGUI::displaySurface { viewerno surfacenode { refnode -1}} {
+    
+    EnsureFileLoaded $surfacenode
+    set surfaceobj [$RealTree get $surfacenode pxitclobj]
+    
+    set viewer $viewer1; if { $viewerno == 2 && $viewer2 != 0 }  { set viewer $viewer2 }
+    if { $viewer == 0 } {	return    }
+    
+    if {$refnode != -1} {
+	puts "sending surface to $viewerno in space of $refnode"
+	
+	findTransforms $RealTree $surfacenode $refnode
+	set BottomUpTransList $TransformsCache($myname,$surfacenode:$refnode)
+	EnsureTransListLoaded $BottomUpTransList
+	
+	#debuggin
+	pxtkprint "List of Transformation nodes for surface [$RealTree get $surfacenode title] to ref [$RealTree get $refnode title]\n"
+	pxtkprint "--------------------------------------------------\n$BottomUpTransList\n\n"
+	pxtkprint "Associated list of filenames\n--------------------------------------------------\n"
+	for {set v 0} {$v < [llength $BottomUpTransList]} {incr v} {
+	    pxtkprint "[lindex $BottomUpTransList $v]:  [[lindex $BottomUpTransList $v] cget -filename]\n"
+	}
+	pxtkprint "\n\n"
+	
+	set gen [ CreateTransformation $BottomUpTransList ]
+	set newsur [ pxitclsurface \#auto]
+	$newsur ShallowCopy $surfaceobj
+	$newsur Transform $gen
+	$newsur Display $viewer
+	$gen Delete
+	::itcl::delete object $newsur 
+    } else {
+	$surfaceobj Display $viewer
+    }
+}
+
+::itcl::body chellyGUI::displayLandmarks { viewerno landnode { refnode -1}} {
+    
+    EnsureFileLoaded $landnode
+    set landobj [$RealTree get $landnode pxitclobj]
+    puts "landmarks: [$landobj GetDescription]"
+    
+    set viewer $viewer1; if { $viewerno == 2 && $viewer2 != 0 }  { set viewer $viewer2 }
+    if { $viewer == 0 } {	return    }
+    
+    
+    if {$refnode != -1} {
+	
+	findTransforms $RealTree $landnode $refnode
+	set BottomUpTransList $TransformsCache($myname,$landnode:$refnode)
+	EnsureTransListLoaded $BottomUpTransList
+	
+	set gen [ CreateTransformation $BottomUpTransList ]
+	set newland [ pxitcllandmarks \#auto]
+	$newland Copy $landobj
+	$newland Transform $gen
+	$newland Display $viewer
+	$gen Delete
+	::itcl::delete object $newland
+    } else {
+	$landobj Display $viewer
+    }
+}
+
+
+::itcl::body chellyGUI::displayElectrodes { econtrol electrodenode { refnode -1}} {
+
+    EnsureFileLoaded $electrodenode
+    set electrodeobj [$RealTree get $electrodenode pxitclobj]
+    
+    set electrodecontrol $electrodecontrol1; if { $econtrol == 2 && $electrodecontrol2 != 0 }  { set electrodecontrol $electrodecontrol2 }
+    if { $electrodecontrol == 0 } {	return    }
+
+    #    $electrodecontrol DelayedInitialize
+    $electrodecontrol ShowWindow
+    
+    if {$refnode != -1} {
+	
+	findTransforms $RealTree $electrodenode $refnode
+	set BottomUpTransList $TransformsCache($myname,$electrodenode:$refnode)
+	EnsureTransListLoaded $BottomUpTransList
+	
+	set gen [ CreateTransformation $BottomUpTransList ]
+	set newelec [ pxitclelectrodemultigrid \#auto]
+	puts "Sending $newelec to electrodecontrol: $electrodecontrol"
+	$newelec Copy $electrodeobj
+	$newelec Transform $gen
+
+	$newelec Display $electrodecontrol
+	$gen Delete
+	::itcl::delete object $newelec
+	puts "Displaying electrodes"
+    } else {
+	puts "Displaying electrodes in their own space"
+	$electrodeobj Display $electrodecontrol
+    }
+}
+
+
+::itcl::body chellyGUI::grabElectrodeAttributes { electrodecontrolno } {
+
+    set electrodecontrol $electrodecontrol1; if { $electrodecontrolno == 2 && $electrodecontrol2 != 0 }  { set electrodecontrol $electrodecontrol2 }
+    if { $electrodecontrol == 0 } {	return    }
+
+    set source [ $electrodecontrol GetMultiGrid ]
+
+    set ThisNode [GetIDFromSelection]
+    EnsureFileLoaded $ThisNode
+    set electrodeobj        [$RealTree get $ThisNode pxitclobj]
+    set target  [$electrodeobj GetObject]
+
+    $target CopyAttributes $source
+
+    #Save a new file
+    set newName "[file rootname [$RealTree get $ThisNode FileName]]_Attr_Updated.mgrid"
+    $target Save $newName
+    setNodeFilename $ThisNode $newName
+
+    
+
+
+}
+
+::itcl::body chellyGUI::PutViewerObjectInTree { viewerno objtype } {
+    
+    if {[llength [GetIDFromSelection]] > 0} {
+	switch -exact -- $objtype {
+	    
+	    "image" -
+	    "Image" {
+		
+		
+		set ObjectID $MasterCount
+		incr MasterCount
+		$RealTree insert [GetIDFromSelection] end $ObjectID
+		ImageInitialize $RealTree $ObjectID
+		GrabViewerImage $viewerno [$RealTree get $ObjectID pxitclobj]
+		nameNode $RealTree $ObjectID "Grabbed_Image_$ObjectID"
+		
+	    }
+	    
+	    "surface" - 
+	    "Surface" {
+		
+		puts "Adding a surface"
+		set ObjectID $MasterCount
+		incr MasterCount
+		$RealTree insert [GetIDFromSelection] end $ObjectID
+		SurfaceInitialize $RealTree $ObjectID
+		GrabViewerSurface $viewerno [$RealTree get $ObjectID pxitclobj]
+		nameNode $RealTree $ObjectID "Grabbed_Surface_$ObjectID"
+		
+	    }
+	    
+	    "landmark" -
+	    "Landmark" {
+		set ObjectID $MasterCount
+		incr MasterCount
+		$RealTree insert [GetIDFromSelection] end $ObjectID
+		LandmarkInitialize $RealTree $ObjectID
+		GrabViewerLandmarkSet $viewerno [$RealTree get $ObjectID pxitclobj]
+		nameNode $RealTree $ObjectID "Grabbed_Landmarks_$ObjectID"
+		
+	    }
+	    
+	    "electrode" -
+	    "Electrode" {
+	    	set ObjectID $MasterCount
+		incr MasterCount
+		$RealTree insert [GetIDFromSelection] end $ObjectID
+		ElectrodeInitialize $RealTree $ObjectID
+		GrabViewerElectrodes $viewerno [$RealTree get $ObjectID pxitclobj]
+		nameNode $RealTree $ObjectID "Grabbed_Electrodes_$ObjectID"
+		
+	    }
+	}
+	
+	#-----------------------------------------------------------------------------
+	#Everything below here occurs for the initialization of any type added to tree
+	#-----------------------------------------------------------------------------
+	set pathList [$RealTree rootname]
+	set pathListIDs [$RealTree ancestors $ObjectID]
+	
+	for {set y [expr [llength $pathListIDs] - 1]} {$y > -1} {incr y -1} {
+	    if {[lindex $pathListIDs $y] != [$RealTree rootname]} {
+		lappend pathList [$RealTree get [lindex $pathListIDs $y] title]
+		
+	    }
+	}
+	
+	set pathName /
+	for {set i 0} {$i < [llength $pathList]} {incr i} {
+	    append pathName [lindex $pathList $i]
+	    append pathName /
+	}
+	append pathName [$RealTree get $ObjectID title]
+	set NodeIDs($pathName) $ObjectID
+	
+	set newfilename [$FileManager SaveFile [$RealTree get $ObjectID pxitclobj]]
+	setNodeFilename $ObjectID $newfilename
+	updateVisTree $vistree $RealTree $ObjectID
+
+	
+    };#End of main if
+    
+};#End of method
+
+::itcl::body chellyGUI::GrabViewerImage { viewerno destinationobj } {
+    
+    set viewer $viewer1; if { $viewerno == 2 && $viewer2 != 0 }  { set viewer $viewer2 }
+    if { $viewer == 0 } {	return    }
+    
+    set img [ $viewer GetDisplayedImage ]
+    
+    $destinationobj ShallowCopy $img
+    
+}
+
+::itcl::body chellyGUI::GrabViewerSurface { viewerno newsur} {
+    
+    set viewer $viewer1; if { $viewerno == 2 && $viewer2 != 0 }  { set viewer $viewer2 }
+    if { $viewer == 0 } {	return    }
+    
+    set surface 0
+    catch {
+	set surface [ [ [ $viewer GetPolyDataControl ] GetPolyDataControl ]  GetSurface  -1 ]
+    }
+    if { $surface ==0 } {
+	return
+    }
+    
+    $newsur ShallowCopySurface $surface
+    $newsur configure -filename "grabbed.vtk"
+    puts stderr "[ $newsur GetDescription]"
+    
+    
+}
+
+::itcl::body chellyGUI::GrabViewerLandmarkSet { viewerno newsur } {
+    
+    set viewer $viewer1; if { $viewerno == 2 && $viewer2 != 0 }  { set viewer $viewer2 }
+    if { $viewer == 0 } {	return    }
+    
+    set landmarkset 0
+    catch {
+	set landmarkset [ [ [ 
+    }
+    if { $landmarkset ==0 } {
+	return
+    }
+    
+    $newsur CopyLandmarks $landmarkset
+    $newsur configure -filename "grabbed.land"
+    puts stderr "[ $newsur GetDescription]"
+    
+    
+}
+
+::itcl::body chellyGUI::GrabViewerElectrodes { electrodecontrolno newelec} {
+    
+    set electrodecontrol $electrodecontrol1; if { $electrodecontrolno == 2 && $electrodecontrol2 != 0 }  { set electrodecontrol $electrodecontrol2 }
+    if { $electrodecontrol == 0 } {	return    }
+    
+    $newelec CopyElectrodeMultiGrid [ $electrodecontrol GetMultiGrid ] 
+    
+}
+
+
+::itcl::body chellyGUI::mdCopy { {cut 0} { topnode -1 } } {
+
+    if { $topnode == -1 } {
+	set topnode  [GetIDFromSelection]
+    }
+    
+    set parentoftop [$RealTree parent $topnode]
+    set undoArray(previousCutParent) $parentoftop
+    catch {array unset ClipboardTreeArray}
+    catch {unset TemporaryTree}
+    
+    set TemporaryTree [	::struct::tree [pxvtable::vnewobj] deserialize [$RealTree serialize] ]
+
+    set topsiblings [$TemporaryTree children $parentoftop]
+    foreach sib $topsiblings {
+	if {$sib != $topnode} {$TemporaryTree delete $sib}
+    }
+    
+    set ClipboardTreeArray(serialized) [$TemporaryTree serialize $parentoftop]
+    
+    if { $parentoftop == [$RealTree rootname] } {
+	set ClipboardTreeArray(rootname) [$RealTree rootname]
+    } else { set ClipboardTreeArray(rootname) [$RealTree get $parentoftop title] }
+
+    set ClipboardTreeArray(MC) $MasterCount
+    set ClipboardTreeArray(IDs) [array get NodeIDs]
+
+    foreach node [$RealTree children -all $parentoftop] {
+	set ClipboardTreeArray($node,title)         [$RealTree get $node title]
+	set ClipboardTreeArray($node,type)          [$RealTree get $node type]
+	set ClipboardTreeArray($node,isid)          [$RealTree get $node IsIdentity]
+	set ClipboardTreeArray($node,icon)          [$RealTree get $node icon]
+	set ClipboardTreeArray($node,filename)     [$RealTree get $node FileName]
+	set ClipboardTreeArray($node,transtoparfilename)    [$RealTree get $node TransToParFileName]
+	set ClipboardTreeArray($node,transfromparfilename)  [$RealTree get $node TransFromParFileName]
+	set ClipboardTreeArray($node,notes)  [$RealTree get $node notes]
+
+	#This is just a array key that sets whether a node is expanded or not
+	set ClipboardTreeArray($node,expanded) $::Tree::Tree($vistree:[getPath $RealTree $node]:open)
+
+	if {[$RealTree get $node type] == {Surface Electrode}} {
+	    set ClipboardTreeArray($node,Attributes)  [$RealTree get $node Attributes]
+	}
+	if {[$RealTree get $node type] == "Patient"} {
+	    set ClipboardTreeArray($node,Properties)  [$RealTree get $node Properties]
+	}
+    }
+    
+
+    if {$cut == 1} {
+	delSelectedFromTree
+    }
+}
+
+::itcl::body chellyGUI::mdPaste { { parentNode -1 } } {
+
+    if { $parentNode == -1 } {
+	set parentNode [GetIDFromSelection]
+    }
+   
+    set undoArray(previousPaste) $parentNode
+    set listedarray [array get ClipboardTreeArray]
+    AddSubtree $RealTree $parentNode $listedarray
+}
+
+
+#Save and Load Tree Methods 
+
+::itcl::body chellyGUI::mdSaveTree { datatree { updatefiles 0 } } {
+    
+    #Wrap the "notes" key of all nodes in braces, to avoid interpreter confusion on loading
+    foreach {node val} [$datatree attr notes] {
+	set oldvals($node) [$datatree get $node notes]
+	set newval [string map {\n {\n}} [$datatree get $node notes]]
+	$datatree set $node notes $newval
+    }
+    
+    #Serialize the tree structure for saving to a variable to be sent over a channel
+    set SerializedTree [$datatree serialize]
+        
+    #Initialize an array, and set the "serialized" index to the tree stucture, and record the rootname 
+    #This is the "Tree definition array" - it conatains all info needed to rebuild the tree
+    set TreeDefArray(serialized) $SerializedTree
+    set TreeDefArray(rootname) [$datatree rootname]
+    set TreeDefArray(MC) $MasterCount
+    set TreeDefArray(IDs) [array get NodeIDs]
+    set TreeDefArray(TypeDefArray) [array get RecognizedTypes]
+    set TreeDefArray(PatientProps) $PatientProperties
+    
+    #Save the filenames in the array for the image, and transformations up and down
+    foreach node [$datatree children -all [$datatree rootname]] {
+	set TreeDefArray($node,title)         [$datatree get $node title]
+	set TreeDefArray($node,type)          [$datatree get $node type]
+	set TreeDefArray($node,isid)          [$datatree get $node IsIdentity]
+	set TreeDefArray($node,icon)          [$datatree get $node icon]
+	set TreeDefArray($node,filename)     [$datatree get $node FileName]
+	set TreeDefArray($node,transtoparfilename)    [$datatree get $node TransToParFileName]
+	set TreeDefArray($node,transfromparfilename)  [$datatree get $node TransFromParFileName]
+	set TreeDefArray($node,notes)  [$datatree get $node notes]
+	#This is just a array key that sets whether a node is expanded or not
+	set TreeDefArray($node,expanded) $::Tree::Tree($vistree:[getPath $RealTree $node]:open)
+
+	if {[$datatree get $node type] == {Surface Electrode}} {
+	    set TreeDefArray($node,Attributes)  [$datatree get $node Attributes]
+	}
+	if {[$datatree get $node type] == "Patient"} {
+	    set TreeDefArray($node,Properties)  [$datatree get $node Properties]
+	}
+    }
+    
+    foreach {node val} [$datatree attr notes] {
+	$datatree set $node notes $oldvals($node)
+    }
+
+
+    puts stderr "Updatefiles =$updatefiles"
+    
+    switch -exact -- $updatefiles {
+	0 {
+	    set ok [ $FileManager SaveDatatree [array get TreeDefArray] ]
+	    if { $ok < 0 } { return -1 }
+	    set TreeChanged 0
+	}
+	1 {
+	    if {$FileManager == $RelativeFileManager} {
+		tk_messageBox -type ok  -message "This function will save a new tree file, and copy all files specified in the tree into the folder that contains it, creating subfolders to preserve the organization of the files.  Use it to create a clean record of the tree files, uncluttered by any extranneous files generated by processing."
+		set UpdatedTreeList [$FileManager SaveDataTreeClean [array get TreeDefArray]]
+		if {$UpdatedTreeList == -1} { return -1 }
+		mdLoadTree $UpdatedTreeList 
+		
+	    } else { 
+		error "The Update Files function requires you to use the Relative Pathnaming Option (See Options menu)." 
+	    }
+	    set TreeChanged 0
+	}
+
+	2 {
+	    if {$FileManager == $RelativeFileManager} {
+		tk_messageBox -type ok  -message "This function will save a new tree file, and copy all files specified in the tree into the folder that contains it, creating subfolders to match the structure of the folders in the tree."
+		set UpdatedTreeList [$FileManager SaveDataTreeFilesReorg [array get TreeDefArray]]
+		if {$UpdatedTreeList == -1} { return -1 }
+		mdLoadTree $UpdatedTreeList 
+	    } else { 
+		error "The Update Files function requires you to use the Relative Pathnaming Option (See Options menu)." 
+	    }
+	    set TreeChanged 0
+	}
+	
+    }
+
+    return 1
+}
+
+::itcl::body chellyGUI::mdNewTree { } {
+
+    #If the tree has changes in it, offer the option to save, or cancel
+    if {$TreeChanged != 0} {
+	set saveNowResponse [tk_messageBox -type yesnocancel -default yes \
+		 -message "The tree has changed since it was last saved.  Would you like to save it before exiting?" -icon question]
+
+	if { $saveNowResponse == "cancel"} {
+	    return -1;
+	}
+	if { $saveNowResponse == "yes"} {
+	    mdSaveTree $RealTree
+	}
+
+    }
+    
+
+    #----------------------------------------
+    
+    #Delete all image and transformation objects
+    foreach child [$RealTree children -all [$RealTree rootname]] {
+	if {[$RealTree keyexists $child pxitclobj]} {
+	    set obj [$RealTree get $child pxitclobj]
+	    ::itcl::delete object $obj
+	}
+	if {[$RealTree keyexists $child pxitclTransToParent]} {
+	    set obj [$RealTree get $child pxitclTransToParent]
+	    ::itcl::delete object $obj
+	}
+	if {[$RealTree keyexists $child pxitclTransFromParent]} {
+	    set obj [$RealTree get $child pxitclTransFromParent]
+	    ::itcl::delete object $obj
+	}
+    }
+    
+    foreach obj [array names TransformsCache] {
+	catch {::itcl::delete object $obj}
+    }
+    
+    #And delete all the nodes
+    foreach child [$RealTree children -all [$RealTree rootname]] {
+	catch {$RealTree delete $child}
+	}
+    
+    #Also reset the space, anatomical, and functional images, and AtlasImage
+    set SpaceImage -1; 	catch {$IC delete refPIC refTEXT};
+    set refbrainTEXT  [$IC create text [expr $rbX+65] [expr $rbY+52] -text "Not Set" \
+			   -fill grey61 -font {helvetica 15 bold} -activefill yellow  -tag refTEXT]
+    
+    set AnatomicalImage -1;	catch {$IC delete anatomPIC anatomTEXT}
+    set anatomicalbrainTEXT  [$IC create text [expr $abX+65] [expr $abY+52] -text "Not Set" \
+				  -fill grey61 -font {helvetica 15 bold} -activefill yellow  -tag anatomTEXT]
+    
+    set FunctionalImage -1;	catch {$IC delete funcPIC funcTEXT}
+    set funcbrainTEXT  [$IC create text [expr $fbX+65] [expr $fbY+52] -text "Not Set" \
+			    -fill grey61 -font {helvetica 15 bold} -activefill yellow -tag funcTEXT]
+    
+    set AtlasImage -1
+    
+    updateBigTransLines
+    
+    #Also Clear the Overlay Tab
+    updateOverlayCanvas
+    #----------------------------------------
+    
+    set TreeChanged 0
+    updateVisTree $vistree $RealTree
+    ::Tree::setselection $vistree /[$RealTree rootname]
+    
+    
+    
+}
+
+::itcl::body chellyGUI::mdLoadTree { {ListedTree -1} {filename -1} } {
+    
+    if {$ListedTree == -1} {
+	#Get the list that specifies the tree definition array
+	if {$filename == -1} {
+	    set ListedTree [$FileManager LoadDatatree]
+	} else { set ListedTree [$FileManager LoadDatatree $filename] }
+	if { $ListedTree == 0 } {
+	    set ListedTree -1 
+	}
+    }
+
+
+
+    if {$ListedTree != -1} {    
+	
+	#----------------------------------------
+	
+	#Delete all image and transformation objects
+	foreach child [$RealTree children -all [$RealTree rootname]] {
+	    if {[$RealTree keyexists $child pxitclobj]} {
+		set obj [$RealTree get $child pxitclobj]
+		::itcl::delete object $obj
+	    }
+	    if {[$RealTree keyexists $child pxitclTransToParent]} {
+		set obj [$RealTree get $child pxitclTransToParent]
+		::itcl::delete object $obj
+	    }
+	    if {[$RealTree keyexists $child pxitclTransFromParent]} {
+		set obj [$RealTree get $child pxitclTransFromParent]
+		::itcl::delete object $obj
+	    }
+	}
+	
+	foreach obj [array names TransformsCache] {
+	    catch {::itcl::delete object $obj}
+	}
+	
+	#And delete all the nodes
+	foreach child [$RealTree children -all [$RealTree rootname]] {
+	    catch {$RealTree delete $child}
+	}
+	
+	#Also reset the space, anatomical, and functional images, and AtlasImage
+	set SpaceImage -1; 	catch {$IC delete refPIC refTEXT};
+	set refbrainTEXT  [$IC create text [expr $rbX+65] [expr $rbY+52] -text "Not Set" \
+			       -fill grey61 -activefill yellow -font {helvetica 15 bold} -tag refTEXT]
+	
+	set AnatomicalImage -1;	catch {$IC delete anatomPIC anatomTEXT}
+	set anatomicalbrainTEXT  [$IC create text [expr $abX+65] [expr $abY+52] -text "Not Set" \
+				      -fill grey61 -activefill yellow -font {helvetica 15 bold} -tag anatomTEXT]
+	
+	set FunctionalImage -1;	catch {$IC delete funcPIC funcTEXT}
+	set funcbrainTEXT  [$IC create text [expr $fbX+65] [expr $fbY+52] -text "Not Set" \
+				-fill grey61 -activefill yellow -font {helvetica 15 bold} -tag funcTEXT]
+
+	set AtlasImage -1
+	
+	updateBigTransLines
+
+	#Also Clear the Overlay Tab
+	updateOverlayCanvas
+	#----------------------------------------
+	
+	#Rebuild the tree definition array from the loaded listing
+	array set TreeDefArray $ListedTree
+	
+	if { [lsearch [array names TreeDefArray] ChellysTreeFormat] != -1 } {
+	    
+	    #explicitly delete the tree held by RealTree
+	    $RealTree destroy
+	    
+	    #initialize MasterCount
+	    set MasterCount $TreeDefArray(MC)
+	    
+	    #reset the "NodeIDs"  array
+	    array unset NodeIDs;# $TreeDefArray(IDs)
+	    
+	    #rebuild the "RealTree" data structure from the serialization contained in the array
+	    ::struct::tree $RealTree deserialize $TreeDefArray(serialized)
+	    set NodeIDs(/Data) [$RealTree rootname]	
+	    
+	    #Initialize a list that will hold pointers to nodes that should be displayed collapsed
+	    set closenodes ""
+	    #Set the image object and transformation object properties at each node
+	    foreach node [$RealTree children -all [$RealTree rootname]] {
+		
+		#set the type
+		$RealTree set $node type $TreeDefArray($node,type)
+
+		if {[$RealTree get $node type] == "Atlas"} { AtlasInitialize $RealTree $node }
+		if {[$RealTree get $node type] == "ROIDef"} { ROIDefInitialize $RealTree $node }
+		if {[$RealTree get $node type] == "Patient"} { 
+		    #Initialize as a patient node
+		    PatientInitialize $RealTree $node 
+		    #set the Properties key
+		    if { [lsearch [array names TreeDefArray] "$node,Properties" ] != -1 } {
+			$RealTree set $node Properties $TreeDefArray($node,Properties)
+		    }
+		}
+		if {[$RealTree get $node type] == "Folder"}  { FolderInitialize $RealTree $node }
+		if {[IsNodeImage $node]}                     { ImageInitialize $RealTree $node }
+		if {[IsNodeSurface $node]} {
+		    switch -exact -- [lindex [$RealTree get $node type] 1] {
+			"surface" -
+			"Surface" {
+			    SurfaceInitialize $RealTree $node
+			}
+			"landmark" -
+			"Landmark" {
+			    LandmarkInitialize $RealTree $node
+			}
+			"electrode" -
+			"Electrode" {
+			    ElectrodeInitialize $RealTree $node
+			    if {[llength [array names TreeDefArray -exact $node,Attributes]] == 1} {
+				$RealTree set $node Attributes $TreeDefArray($node,Attributes)
+			    }
+			}
+		    };# End switch
+		    
+		};#End if (Is it a surface?)
+		
+		
+		#set the title
+		nameNode $RealTree $node $TreeDefArray($node,title)
+		
+		#reset the type (since initialization overwrites it)
+		$RealTree set $node type $TreeDefArray($node,type)
+		
+		#set the notes for the node
+		$RealTree set $node notes [string map {{\n} \n} $TreeDefArray($node,notes)]
+		
+		#--------------------------------------------------
+		#Set the filenames if they are saved
+		#--------------------------------------------------
+		if { $TreeDefArray($node,filename) != -1 } {
+		    setNodeFilename $node $TreeDefArray($node,filename)
+		}
+		if { $TreeDefArray($node,transtoparfilename) != -1 } {
+		    setNodeTransformToParFile $node $TreeDefArray($node,transtoparfilename)
+		}
+		if { $TreeDefArray($node,transfromparfilename) != -1 } {
+		    setNodeTransformFromParFile $node $TreeDefArray($node,transfromparfilename)
+		}
+		#--------------------------------------------------
+		
+		#if the expanded/collapsed state of the node has been set explicitly, then set it
+		
+		if { [lsearch [array names TreeDefArray] "$node,expanded"] != -1 } {
+		    if {$TreeDefArray($node,expanded) == 0} {
+			lappend closenodes $node
+		    }
+		} 
+	    }
+	    
+	    #set the "IsIdentity" property of each node explicitly, based on the saved data
+	    foreach node [$RealTree children -all [$RealTree rootname]] {
+		if {[IsNodeImage $node -1 1] && $TreeDefArray($node,isid)} {
+		    toggleIdentity $node 1
+		}
+	    }
+	}
+	
+	if { [lsearch [array names TreeDefArray] MultiSubjectFormat] != -1 } {
+	    
+	    AddMultiSubjfMRI $RealTree [$RealTree rootname] x $ListedTree
+	    
+	}
+	
+	#If the file contains info for setting the type def array, then do so
+	if { [lsearch [array names TreeDefArray] TypeDefArray ] != -1 } {
+	    catch {unset RecognizedTypes}
+	    array set RecognizedTypes $TreeDefArray(TypeDefArray)
+	}
+	
+	#Same for Patient Properties list
+	if { [lsearch [array names TreeDefArray] PatientProps ] != -1 } {
+	    unset PatientProperties
+	    set PatientProperties  $TreeDefArray(PatientProps)
+	    
+	}
+
+
+	set TreeChanged 0
+	updateVisTree $vistree $RealTree; CloseNodes $closenodes
+	::Tree::setselection $vistree /[$RealTree rootname]
+	wm title [$surgerygadget GetBaseWidget] "[file tail $TreeDefArray(ThisFileName)] - Data Tree Manager" 
+	
+	
+	#Update the recent files menu to include the loaded tree
+# 	if {[lsearch -exact [array names TreeDefArray] ThisFileName] != -1} {
+	    
+# 	    set Ser [lsearch $recentfileslist $TreeDefArray(ThisFileName)]
+# 	    if { $Ser != -1 } {
+# 		set recentfileslist [lreplace $recentfileslist $Ser $Ser]
+# 		set recentfilesnames [lreplace $recentfilesnames $Ser $Ser]
+# 	    }
+
+# 	    set recentfileslist  [linsert $recentfileslist 0 $TreeDefArray(ThisFileName)]
+# 	    set recentfilesnames [linsert $recentfilesnames 0 [file tail $TreeDefArray(ThisFileName)]]
+
+# 	    $RecentFilesMenu delete 0 end
+# 	    for {set y 0} { $y < [llength $recentfileslist] } { incr y } {
+# 		eval "$RecentFilesMenu add command -label [lindex $recentfilesnames $y] \
+# -command {$this mdLoadTree -1 [lindex $recentfileslist $y]} -background \"$menucolor\" -activebackground \"$menuactivebgcolor\""
+# 	    }
+#	}
+        
+    }
+    
+};# end method mdLoadTree
+
+
+::itcl::body chellyGUI::mdSaveTypeDefs { } {
+    
+    $FileManager SaveTypeDefs [array get RecognizedTypes]
+    
+}
+
+::itcl::body chellyGUI::mdLoadTypeDefs { } {
+    
+    catch {array unset RecognizedTypes}
+    set loadedtypes [$FileManager LoadTypeDefs]
+    if {$loadedtypes != -1} {
+	array set RecognizedTypes $loadedtypes
+	set RecogTypeDialogName -1
+	setRecognizedTypes
+    }
+
+}
+
+::itcl::body chellyGUI::EditPatientPropList { } {
+
+   if {$PatientPropDialogName == -1} {
+
+       #Make a dialog box
+       set PatientPropDialogName .[ pxvtable::vnewobj ]
+       iwidgets::dialog $PatientPropDialogName -title "Patient Properties" -modality application
+       $PatientPropDialogName hide Help
+       $PatientPropDialogName hide Apply
+       $PatientPropDialogName hide Cancel
+       eval "$PatientPropDialogName buttonconfigure OK -command { $this PatientPropDialogCallback ok }"
+       eval "$PatientPropDialogName add removebutton -text Remove -command { $this PatientPropDialogCallback remove }"
+       eval "$PatientPropDialogName add addbutton -text Add -command { $this PatientPropDialogCallback add }"
+
+       set cs1 [ $PatientPropDialogName childsite ]
+       set PatientProperty_selectionbox1 [iwidgets::selectionbox $cs1.selbox -itemslabel "Patient Property List" -selectionlabel "Add:"]
+       pack $PatientProperty_selectionbox1
+       
+	
+   }
+    
+   set patientproplistbox [$PatientProperty_selectionbox1 component items]
+   $patientproplistbox clear
+   for {set u 0} {$u < [llength $PatientProperties]} {incr u} {
+       $patientproplistbox insert end [lindex $PatientProperties $u]
+   }
+   
+   wm geometry $PatientPropDialogName +300+200
+   $PatientPropDialogName activate
+   
+}
+
+::itcl::body chellyGUI::PatientPropDialogCallback { command } {
+
+  
+    #Get pointers to the entry field and the listbox
+    set thisentryfield [$PatientProperty_selectionbox1 component selection]
+    set thislistbox [$PatientProperty_selectionbox1 component items]
+
+    #If the command is OK, update the internal property list, and deactivate dialog
+    if {$command == "ok"} {
+	set PatientProperties ""
+	for {set y 0} {$y < [llength [$thislistbox get 0 end]]} {incr y} {
+	    lappend PatientProperties [$thislistbox get $y]
+	}
+	
+	$PatientPropDialogName deactivate; return 0
+    }
+     
+    #If the command is add, insert the contents of the entryfield into the list
+    if {$command == "add"} {
+	set input [$thisentryfield get]
+	if {[llength $input]} {
+	    $thislistbox insert 0 $input
+	    $thisentryfield clear
+	}
+    }
+
+    #If the command is remove, remove the selected items from the list
+    if {$command == "remove"} {
+	set sel  [$thislistbox getcurselection]
+	if { [llength $sel] } {
+	    $thislistbox delete $sel
+	}
+    }
+}
+
+::itcl::body chellyGUI::showRecognizedTypes { arraylist } {
+    
+    catch {array unset tempArray}
+    array set tempArray $arraylist
+    set keylist [ array names tempArray ]
+    set keylist [lsort $keylist]
+    
+    if {$RecogTypeDialogName == -1} {
+	set mdEntries ""
+    	set RecogTypeDialogName .[ pxvtable::vnewobj ]
+	iwidgets::dialog $RecogTypeDialogName -title "Recognized Image Types" -modality application
+	
+	for { set k 0 } { $k < [llength $keylist] } { incr k } {
+	    set key [lindex $keylist $k]
+	    set val $tempArray($key)
+	    
+	    set f $key; append f "_f"	
+	    set c $key; append c "_c"
+	    set y $key; append y "_y"
+	    set v $key; append v "_v"
+	    
+	    set cs [$RecogTypeDialogName childsite]
+	    set framebox [frame $cs.$f]	
+	    
+	    set checkedvar $key; append checkedvar "_checked"
+	    set RecognizedTypesChecks($checkedvar) 0
+	    set checkbox [checkbutton $framebox.$c -variable [itcl::scope RecognizedTypesChecks($checkedvar)]]
+	    
+	    set keybox [iwidgets::entryfield $framebox.$y -clientdata "Keybox$f" ]
+	    $keybox insert 0 $key
+	    
+	    set valbox [iwidgets::entryfield $framebox.$v -clientdata "Valbox$v" ]
+	    $valbox insert 0 $val
+	    
+	    pack $checkbox $keybox $valbox  -padx 4 -pady 4 -side left
+	    pack $framebox -side top
+	    
+	    lappend mdEntries $checkedvar
+	    lappend mdEntries $keybox
+	    lappend mdEntries $valbox
+	    
+	}
+	
+	$RecogTypeDialogName hide Help
+	$RecogTypeDialogName hide Cancel
+	$RecogTypeDialogName hide Apply
+	eval "$RecogTypeDialogName buttonconfigure OK -command { $this recognizedTypeDialogCallback $RecogTypeDialogName OK }"
+	eval "$RecogTypeDialogName add Add -text Add -command { $this recognizedTypeDialogCallback $RecogTypeDialogName Add }"
+	eval "$RecogTypeDialogName add Delete -text \"Delete Checked\" -command { $this recognizedTypeDialogCallback $RecogTypeDialogName Delete }"
+	
+    }
+    
+    set dialogEntries -1
+    
+    for { set k 0 } { $k < [llength $keylist] } { incr k } {
+	set key [lindex $keylist $k]
+	set varname $key; append varname "_checked"
+    }
+    
+    wm geometry $RecogTypeDialogName +300+200
+    $RecogTypeDialogName activate
+    
+    return $dialogEntries
+    
+};#End showRecognizedTypes method
+
+
+::itcl::body chellyGUI::recognizedTypeDialogCallback { dialogname mode } {
+    
+    if { $mode == "Cancel" } {
+	$dialogname deactivate
+    }
+    
+    set dialogEntries ""
+    foreach {checkbox keyentry valentry} $mdEntries {
+#	puts [$checkbox cget -variable]
+	lappend dialogEntries [$keyentry get]	   
+	lappend dialogEntries [$valentry get] 
+    }
+    
+    #--------------------------------------------------------------------------------
+    if {$mode == "Add"} {
+	set newList $dialogEntries
+	lappend newList 99999
+	lappend newList "New Type"
+	
+	$dialogname deactivate
+    	set RecogTypeDialogName -1
+	showRecognizedTypes $newList
+    }
+
+    #--------------------------------------------------------------------------------
+    if {$mode == "Delete"} {
+	set dialogEntries ""
+	foreach {checkvar keyentry valentry} $mdEntries {
+	    if {$RecognizedTypesChecks($checkvar) != 1} {
+		lappend dialogEntries [$keyentry get]	   
+		lappend dialogEntries [$valentry get] 
+	    }
+	}
+	set newList $dialogEntries
+	$dialogname deactivate
+    	set RecogTypeDialogName -1
+	showRecognizedTypes $newList
+    }
+    
+    #--------------------------------------------------------------------------------
+    if { $mode == "OK" } {
+	$dialogname deactivate
+    }
+}
+
+
+::itcl::body chellyGUI::setRecognizedTypes { } {
+    
+    set newarray [showRecognizedTypes [array get RecognizedTypes] ]
+    if {$newarray != -1} {
+	catch {array unset RecognizedTypes}
+	array set RecognizedTypes $newarray
+    }
+    
+}
+
+
+
+::itcl::body chellyGUI::SearchTree { realtreename startnode key values } {
+    
+    set SearchResult ""
+    foreach val $values {
+	
+	set nodelist [$realtreename children -all $startnode]
+	set ValList [$realtreename attr $key -nodes $nodelist]
+	
+	
+	foreach { node nodevalue } $ValList {
+	    if {$nodevalue == $val} {
+		lappend SearchResult $node
+	    }
+	}
+	
+    }
+    
+    if {[llength $SearchResult]} {
+	set SearchResult [lsort $SearchResult]
+    }
+    
+    #    puts "The following nodes have value(s) of $values for key \"$key\": $SearchResult"
+    return $SearchResult
+    
+}
+
+##########################################################################################
+#Transformation concatenation methods
+
+::itcl::body chellyGUI::CreateTransformation { listoftransforms } {
+    
+    # Generates of vtkGeneralTransform from of a list of transforms
+    # -------------------------------------------------------------
+    
+    #Strike out any element in listoftransforms with the value "identity"
+    while {[lsearch $listoftransforms identity] != -1} {
+	set z [lsearch $listoftransforms identity]
+	set listoftransforms [ lreplace $listoftransforms $z $z ]
+    }
+    
+    
+#    puts "Concatenating Transforms: $listoftransforms"
+    
+    set alllinear 1
+    
+    
+    for { set pass 0 } { $pass <=1 } { incr pass } {
+	for { set i 0 } { $i < [ llength $listoftransforms ] } { incr i } {
+	    
+	    
+	    set ta chellyGUI::[lindex $listoftransforms $i]
+	    set tr [ $ta  GetTransformation ]
+	    
+	    if { $pass ==1 } { 
+		$gen Concatenate $tr
+	    } else {
+		if { [ $tr IsA "vtkLinearTransform" ] == 0 } {
+		    set alllinear 0
+		}
+	    }
+	}
+	
+	if { $pass == 0 } {
+	    if { $alllinear == 0 } {
+		set gen [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+	    } else {
+		set gen [ vtkTransform [ pxvtable::vnewobj ]]
+	    }
+	    $gen Identity
+	    $gen PostMultiply
+	    
+	    puts stderr "End of $pass = 0 alllinear = $alllinear"
+	}
+    }
+        
+    return $gen
+}
+
+
+::itcl::body chellyGUI::ResliceImage { baseimage imagetoberesliced listoftransforms {fname auto } {background 0 } } {
+    
+    $mdTopWidget config -cursor watch;  update idletasks
+    
+    #-----------------------------------------------------------------------
+    #First, make sure all members of listoftransforms have been loaded
+    
+    EnsureTransListLoaded $listoftransforms
+
+    puts \n
+    puts \n
+    puts "*********************Reslicing! (method chellyGUI::ResliceImage)********************"
+    puts "* SpaceImage: [$baseimage cget -filename]"
+    puts "* Image Being Resliced: [$imagetoberesliced cget -filename]"
+    puts "* List of Transformation filenames sent to Reslicer: \n * ----------------------------------------------------------------------------------"
+    foreach l $listoftransforms {
+	puts "[$l cget -filename]"
+    }
+    puts "* ----------------------------------------------------------------------------------"
+    puts "************************************************************************************"
+    puts \n
+    puts \n
+    
+    set gen [ CreateTransformation $listoftransforms ]
+    
+    
+    if { $reslmode < 1 } {
+	set reslmode 0 
+    } elseif { $reslmode > 1 } {
+	set reslmode 3
+    }
+
+    if { $reslmode == 1 } {
+	set range [ [ [ [ $imagetoberesliced GetImage ] GetPointData ] GetScalars ] GetRange ]
+	if { [ lindex $range 1 ] < 2.0 } {
+	    set reslmode 3
+	    puts stderr "Switching to Cubic Interpolation to avoid 0..1 bug"
+	}
+    }
+    
+    set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+    $resl SetInformationInput [ $baseimage GetImage ]
+    $resl SetInput [ $imagetoberesliced GetImage ]
+    $resl SetResliceTransform $gen
+    $resl SetInterpolationMode $reslmode
+    
+    # Have 1 replaced by a variable of values 0,1 or 3  
+    # 0=NearestNeighbor for ROI
+    # 1 -- is normal -- use this for anatomical images
+    # 3 -- is cubic  -- use this for functional images
+    
+    $resl SetBackgroundLevel $background
+    $resl OptimizationOff
+    $resl Update
+    
+    set imgout [ [pxitclimage \#auto] GetThisPointer ]
+    $imgout ShallowCopyImage [ $resl GetOutput ]
+    $imgout CopyImageHeader [ $baseimage GetImageHeader ]
+
+    # Extensions Addition
+    [ $imgout GetImageHeader ] CopyExtensionsOnly  [ $imagetoberesliced GetImageHeader ]
+    # Extensions Addition done
+
+    if { $fname != "auto" } {
+	$imgout configure -filename $fname
+    } else {
+	set refname [ file tail [ file root [$baseimage cget -filename] ] ]
+	set srcname [ file root [$imagetoberesliced cget -filename]]
+
+	set newname "${srcname}_mappedto_${refname}.hdr"
+	$imgout configure -filename $newname
+	puts stderr "New name = $newname"
+    }
+
+	
+    
+    $resl Delete
+    $gen Delete 
+    
+    $surgerygadget WatchOff
+    
+    $mdTopWidget config -cursor ""
+    
+    return $imgout
+}
+
+
+
+
+##########################################################################################
+
+
+::itcl::body chellyGUI::makeFileMenu { menu0 } {
+
+    eval "$menu0 add command -label \"New Datatree\" -command {$this mdNewTree} -underline 0  -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Load Datatree\" -command {$this mdLoadTree} -underline 0 -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Save Datatree\" -command {$this mdSaveTree $RealTree} -underline 0 -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator 
+    eval "$menu0 add command -label \"Save Reorganized Copy\" -command {$this mdSaveTree $RealTree 2} -underline 0 -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator 
+    eval "$menu0 add command -label \"Switch Directory\" -command { $this SwitchDirectory } "
+    set thisparam($this,custdirectories)  [ pxitclfilelistmenu \#auto $menu0 "Custom Directories" "$this SwitchDirectory" ]
+    $thisparam($this,custdirectories) SetModeToDirectories
+    $thisparam($this,custdirectories) InitializeDisplay
+
+    global env
+    set thisparam($this,custtrees)  [ pxitclfilelistmenu \#auto $menu0 "Previous Trees" "$this mdLoadTreeFile " "$this mdGetTreeFileName" ]
+
+    $thisparam($this,custtrees) SetModeToCustom "DataTrees" .tre [ file join $env(HOME) .datatrees ] 1 
+    $thisparam($this,custtrees) InitializeDisplay
+
+
+
+    $menu0 add separator 
+    eval "$menu0 add command -label Exit -command {  $this OnWidgetClose; } -underline 1 -activebackground \"$menuactivebgcolor\""
+#    $menu0 add separator 
+#    $menu0 add cascade -label "Recent" -menu $menu0.recent -background "$menucolor"  -activebackground "$menuactivebgcolor"
+#    set RecentFilesMenu [menu $menu0.recent -tearoff 0]
+#    $RecentFilesMenu add separator -background $menucolor
+
+    #Set the background for all menu entries
+    for {set i 0} {$i < [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+
+
+}
+
+::itcl::body chellyGUI::makeEditMenu { menu0 } {
+
+    eval "$menu0 add command -label \"Cut\" -command {$this mdCopy 1} -underline 1 -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Copy\" -command {$this mdCopy 0} -underline 0 -activebackground \"$menuactivebgcolor\""
+   #  eval "$menu0 add command -label \"Undo\" -command {$this undo} -underline 0 -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator
+    eval "$menu0 add command -label \"Paste\" -command {$this mdPaste} -activebackground \"$menuactivebgcolor\""   
+    $menu0 add separator
+    eval "$menu0 add checkbutton -label \"Enable Drag and Drop\" -variable {[itcl::scope dragAndDropEnabled]} \
+	    -onvalue 1 -offvalue 0 -activebackground \"$menuactivebgcolor\""
+    
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+
+
+}
+
+
+::itcl::body chellyGUI::makeToolsMenu { menu0 } {
+
+    set toolsmenu $menu0
+
+#     #Add any menu entries in the functional menu from pxitclbrainregister
+#     set fmenu [$surgerygadget cget -functional_menu]
+#     for {set i 0} {$i < [$fmenu index end]} {incr i} {
+# 	if {[$fmenu type $i] == "command"} {
+# 	    lappend fmenu_labels [$fmenu entrycget $i -label]
+# 	    lappend fmenu_commands [$fmenu entrycget $i -command]
+# 	}
+#     }
+
+#     for {set j 0} {$j < [llength $fmenu_labels]} {incr j} {
+	
+# 	eval "$menu0 add command -label \"[lindex $fmenu_labels $j]\" -command { [lindex $fmenu_commands $j] } -activebackground \"$menuactivebgcolor\"" 
+#     }
+
+#     $menu0 add separator
+
+   eval "$menu0 add command -label \"Multiple Image Calculations\" -command { $this SearchDialog } -activebackground \"$menuactivebgcolor\""   
+
+
+   #------------------------------------------------------------------------------------------
+   # If the SPECT module is loaded, make a menu for it
+   if {$enable_SPECT == 1} {
+       eval "$menu0 add command -label \"SPECT Processing Tool\" -command { $this ShowSPECTtool } -activebackground \"$menuactivebgcolor\""  
+   }
+
+   if {$enable_AdvancedReg == 1 } {
+       eval "$menu0 add command -label \"Advanced Registration Tool\" -command { $this ShowREGtool } -activebackground \"$menuactivebgcolor\""  
+   }
+
+   #------------------------------------------------------------------------------------------
+   # If the atlas module is loaded, make a menu for it
+   if {$enable_atlas == 1} {
+       $menu0 add cascade -label "Atlas" -menu $menu0.atlas -activebackground "$menuactivebgcolor"
+       set atlasSubMenu [menu $menu0.atlas -tearoff 0]
+       	makeAtlasMenu $atlasSubMenu
+   }
+
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+
+
+}
+
+
+#----------------------------------------------------------------------
+# Node Menu and Tree Popup Menu Option Methods (Can be accessed from elsewhere, too)
+# (This Menu is associated with image files)
+#----------------------------------------------------------------------
+
+::itcl::body chellyGUI::makeImageMenu { menu0 } {
+    #Set the "Node" menu contents (same as tree popup menu contents)
+    eval "$menu0 add command -label \"Set Filename\" -command { $this setSelectedFileName } -underline 0 -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator
+    eval "$menu0 add command -label \"Rename\" -command { $this renameSelected } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label Delete -command { $this delSelectedFromTree } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    $menu0 add separator
+    eval "$menu0 add command -label \"Add an Image as Child\" -command { $this addImageToTree } -underline 7 -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator
+    eval "$menu0 add command -label \"Add an ROI Definition\" -command { $this addROIDefToTree } -activebackground \"$menuactivebgcolor\""
+    $menu0 add cascade -label "Add a Surface as Child" -menu $menu0.surfsub -activebackground "$menuactivebgcolor"
+    set surfsubmenu [menu $menu0.surfsub -tearoff 0]
+    eval "$surfsubmenu add command -label \"Surface\" -command { $this addSurfaceToTree } -background \"$menucolor\" -activebackground \"$menuactivebgcolor\""
+    eval "$surfsubmenu add command -label \"Landmark\" -command { $this addLandmarkToTree } -background \"$menucolor\" -activebackground \"$menuactivebgcolor\""
+    eval "$surfsubmenu add command -label \"Electrode\" -command { $this addElectrodeToTree } -background \"$menucolor\" -activebackground \"$menuactivebgcolor\""
+    
+    $menu0 add separator
+    eval "$menu0 add command -label \"Load Transformation FROM Parent\" -command { $this setTransFromParent } -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Load Transformation TO Parent (if nonlinear)\" -command { $this setTransToParent } -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"(Un)set as Identity\" -command {$this setIdentityToggle} -activebackground \"$menuactivebgcolor\""
+ 
+    $menu0 add separator
+    eval "$menu0 add command -label \"Set Space/Anat. & Send to Ref. Viewer\" -command { $this setSelectionSpace $RealTree; $this setSelectionAnatomical $RealTree; $this sendSelectionToDisplay 1 -1 SpaceImage } -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Set Functional & Send to Trans. Viewer in Ref. Space\" -command { $this setSelectionFunctional $RealTree; $this sendSelectionToDisplay 2 1 FunctionalImage; set REF_FunctionalImage 1 } -activebackground \"$menuactivebgcolor\""
+  
+
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+
+
+    
+}
+
+#----------------------------------------
+#This menu will go with Surfaces and Landmarks
+#----------------------------------------
+
+::itcl::body chellyGUI::makeSurfaceMenu { menu0 } {
+    #Set the "Node" menu contents (same as tree popup menu contents)
+    eval "$menu0 add command -label \"Set Filename\" -command { $this setSelectedFileName } -underline 0 -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator
+    eval "$menu0 add command -label \"Rename\" -command { $this renameSelected } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label Delete -command { $this delSelectedFromTree } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    $menu0 add separator
+    eval "$menu0 add command -label \"Send to Left Viewer\" -command { $this sendSelectionToDisplay 1} -underline 9 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label \"Send to Right Viewer\" -command { $this sendSelectionToDisplay 2} -underline 9 -activebackground \"$menuactivebgcolor\"" 
+    $menu0 add separator
+    eval "$menu0 add command -label \"Send to Left Viewer (in Reference Space)\" -command { $this sendSelectionToDisplay 1 1} -underline 9 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label \"Send to Right Viewer (in Reference Space)\" -command { $this sendSelectionToDisplay 2 1} -underline 9 -activebackground \"$menuactivebgcolor\"" 
+
+
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+
+    
+}
+
+#----------------------------------------
+#This menu will go with Electrodes
+#----------------------------------------
+::itcl::body chellyGUI::makeElectrodeMenu { menu0 } {
+    #Set the "Node" menu contents (same as tree popup menu contents)
+    eval "$menu0 add command -label \"Set Filename\" -command { $this setSelectedFileName } -underline 0 -activebackground \"$menuactivebgcolor\""
+   
+    #If the attribute package is loaded, then allow manipulation of attirbutes
+    if {$enable_elec_att == 1} {
+	$menu0 add separator
+	eval "$menu0 add command -label \"Attribute Visualization Control\" -command { $this SendElectrodeToAtrrControl } -underline 0 -activebackground \"$menuactivebgcolor\""
+	eval "$menu0 add command -label \"Load Attributes\" -command { $this mdLoadElectrodeAttributes } -underline 0 -activebackground \"$menuactivebgcolor\""
+	eval "$menu0 add command -label \"Update Attributes from Viewer Electrodes\" -command { $this grabElectrodeAttributes 1 } -underline 0 -activebackground \"$menuactivebgcolor\""
+	
+    }
+    $menu0 add separator
+    eval "$menu0 add command -label \"Rename\" -command { $this renameSelected } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label Delete -command { $this delSelectedFromTree } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    $menu0 add separator
+    eval "$menu0 add command -label \"Send to Electrode Control 1\" -command { $this sendSelectionToDisplay 1} -underline 9 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label \"Send to Electrode Control 1 (in Reference Space)\" -command { $this sendSelectionToDisplay 1 1} -underline 9 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label \"Send to Electrode Control 2\" -command { $this sendSelectionToDisplay 2} -underline 9 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label \"Send to Electrode Control 2 (in Reference Space)\" -command { $this sendSelectionToDisplay 2 1} -underline 9 -activebackground \"$menuactivebgcolor\""    
+
+
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+
+    
+}
+
+
+#------------------------------------------------------------------------------------------
+# This Menu is associated with Patient nodes
+#------------------------------------------------------------------------------------------
+::itcl::body chellyGUI::makePatientMenu { menu0 } {
+    
+    #Set the "Patient" menu contents (same as tree popup menu contents)
+    eval "$menu0 add command -label \"Rename\" -command { $this renameSelected } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label \"Delete Selected Patient\" -command { $this delSelectedFromTree } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    $menu0 add separator
+    eval "$menu0 add command -label \"Load Transformation FROM Parent\" -command { $this setTransFromParent } -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Load Transformation TO Parent (if nonlinear)\" -command { $this setTransToParent } -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator
+    eval "$menu0 add command -label \"Add a Patient to Tree at Selection\" -command { $this addPatientToTree } -underline 0 -activebackground \"$menuactivebgcolor\""    
+ 
+
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+   
+}
+
+#------------------------------------------------------------------------------------------
+# This Menu is associated with the top Data node
+#------------------------------------------------------------------------------------------
+
+::itcl::body chellyGUI::makeDataMenu { menu0 } {
+    
+    
+    $menu0 add cascade -label "Add Subtree" -menu $menu0.subtreesub -activebackground "$menuactivebgcolor"
+    set subtreemenu [menu $menu0.subtreesub -tearoff 0]
+    eval "$subtreemenu add command -label \"Native Type\" -command { $this addSubtreeAtSelection 1} -activebackground \"$menuactivebgcolor\""        
+    eval "$subtreemenu add command -label \"Multisubject Definition (*.msb)\" -command { $this addSubtreeAtSelection 5} -activebackground \"$menuactivebgcolor\""        
+    #    eval "$subtreemenu add command -label \"CSI Patient\" -command { $this addSubtreeAtSelection 3} -activebackground \"$menuactivebgcolor\""        
+    #    eval "$subtreemenu add command -label \"All CSI Patients in dir...\" -command { $this addSubtreeAtSelection 4} -activebackground \"$menuactivebgcolor\""        
+
+    $menu0 add separator
+ 
+    eval "$menu0 add command -label \"Add a Folder as Child\" -command { $this addFolderToTree } -activebackground \"$menuactivebgcolor\""  
+
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+    #Set the background for all subtreemenu menu entries
+    for {set i 0} {$i <= [$subtreemenu index end]} {incr i} {
+	$subtreemenu entryconfigure $i -background $menucolor 
+    }
+ 
+    
+}
+
+#------------------------------------------------------------------------------------------
+# This Menu is for bringing up and dealing with the Atlas Tool
+#------------------------------------------------------------------------------------------
+
+::itcl::body chellyGUI::makeAtlasMenu { menu0 } {
+    
+    eval "$menu0 add command -label \"Open Atlas Tool\" -command { $this ShowAtlas } -activebackground \"$menuactivebgcolor\"" 
+    eval "$menu0 add command -label \"Send Selected Image to Atlas Tool\" -command { $this AtlasShowSelectedNode } -activebackground \"$menuactivebgcolor\"" 
+    $menu0 add separator
+    eval "$menu0 add command -label \"Add Atlas to Tree at Selection\" -command { $this addAtlasToTree } -activebackground \"$menuactivebgcolor\""  
+    
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+
+
+}
+
+#------------------------------------------------------------------------------------------
+# This is the definition method for the Options Menu
+#------------------------------------------------------------------------------------------
+
+::itcl::body chellyGUI::makeOptionsMenu { menu0 } {
+    
+    eval "$menu0 add checkbutton -label \"Lock Space Image\" -variable {[itcl::scope SpaceLocked]} \
+-onvalue 1 -offvalue 0 -command {$this updateBigTransLines} -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator
+    eval "$menu0 add command -label \"View/Set Recognized Image Types\" -command { $this setRecognizedTypes } -activebackground \"$menuactivebgcolor\""  
+    eval "$menu0 add command -label \"Save Image Type Definition File\" -command { $this mdSaveTypeDefs } -activebackground \"$menuactivebgcolor\""  
+    eval "$menu0 add command -label \"Load Image Type Definition File\" -command { $this mdLoadTypeDefs } -activebackground \"$menuactivebgcolor\""  
+    $menu0 add separator    
+    eval "$menu0 add command -label \"Edit Patient Property List\" -command { $this EditPatientPropList } -activebackground \"$menuactivebgcolor\""  
+    $menu0 add separator
+    
+    $menu0 add cascade -label "File Path Save Mode" -menu $menu0.savemodesub -activebackground "$menuactivebgcolor"
+    set savemodemenu [menu $menu0.savemodesub -tearoff 0]
+    eval "$savemodemenu add radio -label Relative -variable {[itcl::scope FileManager]} -value $RelativeFileManager -activebackground \"$menuactivebgcolor\""
+    eval "$savemodemenu add radio -label Absolute -variable {[itcl::scope FileManager]} -value $AbsoluteFileManager -activebackground \"$menuactivebgcolor\""
+    
+    $menu0 add separator
+    $menu0 add cascade -label "Choose Icon Colors" -menu $menu0.icontypesub -activebackground "$menuactivebgcolor"
+    set icontypecascade [menu $menu0.icontypesub -tearoff 0]
+    
+    $icontypecascade add cascade -label "Images" -menu $icontypecascade.colorsub1 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub1 -tearoff 0]
+    makeColorMenu $colormenu brainiconchoice
+    
+    $icontypecascade add cascade -label "Surfaces" -menu $icontypecascade.colorsub2 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub2 -tearoff 0]
+    makeColorMenu $colormenu surfaceiconchoice
+    
+    $icontypecascade add cascade -label "Results" -menu $icontypecascade.colorsub3 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub3 -tearoff 0]
+    makeColorMenu $colormenu resulticonchoice
+
+    $icontypecascade add cascade -label "ROI Definitions" -menu $icontypecascade.colorsub4 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub4 -tearoff 0]
+    makeColorMenu $colormenu roiiconchoice
+    
+
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+
+    #Set the background for all savemodemenu menu entries
+    for {set i 0} {$i <= [$savemodemenu index end]} {incr i} {
+	$savemodemenu entryconfigure $i -background $menucolor 
+}
+
+    #Set the background for all icontypecascade entries
+    for {set i 0} {$i <= [$icontypecascade index end]} {incr i} {
+	$icontypecascade entryconfigure $i -background $menucolor 
+    }
+
+       
+}
+
+#------------------------------------------------------------------------------------------
+# This is the definition method for the View Menu
+#------------------------------------------------------------------------------------------
+
+::itcl::body chellyGUI::makeViewMenu { menu0 } {
+    
+    #$menu0 add separator
+    $menu0 add cascade -label "Choose Icon Colors" -menu $menu0.icontypesub -activebackground "$menuactivebgcolor"
+    set icontypecascade [menu $menu0.icontypesub -tearoff 0]
+    
+    $icontypecascade add cascade -label "Images" -menu $icontypecascade.colorsub1 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub1 -tearoff 0]
+    makeColorMenu $colormenu brainiconchoice
+    
+    $icontypecascade add cascade -label "Surfaces" -menu $icontypecascade.colorsub2 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub2 -tearoff 0]
+    makeColorMenu $colormenu surfaceiconchoice
+    
+    $icontypecascade add cascade -label "Results" -menu $icontypecascade.colorsub3 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub3 -tearoff 0]
+    makeColorMenu $colormenu resulticonchoice
+
+    $icontypecascade add cascade -label "ROI Definitions" -menu $icontypecascade.colorsub4 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub4 -tearoff 0]
+    makeColorMenu $colormenu roiiconchoice
+    
+
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+
+    #Set the background for all icontypecascade entries
+    for {set i 0} {$i <= [$icontypecascade index end]} {incr i} {
+	$icontypecascade entryconfigure $i -background $menucolor 
+    }
+
+
+}
+
+::itcl::body chellyGUI::makeColorMenu { colormenu icon } {
+    
+    eval "$colormenu add radio -label Red -variable {[itcl::scope $icon]} -value ibrainred -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label Orange -variable {[itcl::scope $icon]} -value ibrainorange -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label Yellow -variable {[itcl::scope $icon]} -value ibrainyellow -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label Green -variable {[itcl::scope $icon]} -value ibraingreen -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label Blue -variable {[itcl::scope $icon]} -value ibrainblue -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label \"Light Blue\" -variable {[itcl::scope $icon]} -value ibrainlightblue -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label Purple -variable {[itcl::scope $icon]} -value ibrainpurple -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label Rainbow -variable {[itcl::scope $icon]} -value ibrainrainbow -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+
+
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$colormenu index end]} {incr i} {
+	$colormenu entryconfigure $i -background $menucolor 
+    }
+
+    
+}
+
+::itcl::body chellyGUI::menuActivation { menu menutype } {
+    
+    if {[llength [GetIDFromSelection]]} {
+
+	if { [$RealTree exists [GetIDFromSelection]]} {
+	    
+	    
+	    switch -exact -- $menutype {
+		
+		"Image" -
+		"image" {
+		    #--------------------------------------------------
+		    if {[GetIDFromSelection] == [$RealTree rootname]} {
+			
+			for {set q 0} {$q <= [$menu index last]} {incr q} {
+			    if {[$menu type $q] == "command"} {
+				$menu entryconfigure $q -state disabled
+			    }
+			}
+			$menu entryconfigure 5 -state normal
+			
+		    } elseif { [$RealTree get [GetIDFromSelection] type] == "Patient" } {
+			
+			for {set q 0} {$q <= [$menu index last]} {incr q} {
+			    if {[$menu type $q] == "command"} {
+				$menu entryconfigure $q -state disabled
+			    }
+			}
+			$menu entryconfigure 5 -state normal
+		    } else  {
+			for {set q 0} {$q <= [$menu index last]} {incr q} {
+			    if {[$menu type $q] == "command"} {
+				$menu entryconfigure $q -state normal 
+			    }
+			}
+		    }
+		    #--------------------------------------------------
+		}
+		
+		"Patient" -
+		"patient" {
+		    
+		    #--------------------------------------------------
+		    if {[GetIDFromSelection] == [$RealTree rootname]} {
+			
+			for {set q 0} {$q <= [$menu index last]} {incr q} {
+			    if {[$menu type $q] == "command"} {
+				$menu entryconfigure $q -state disabled
+			    }
+			}
+			$menu entryconfigure 6 -state normal
+			
+		    } elseif { [$RealTree get [GetIDFromSelection] type] != "Patient" } {
+			
+			for {set q 0} {$q <= [$menu index last]} {incr q} {
+			    if {[$menu type $q] == "command"} {
+				$menu entryconfigure $q -state disabled
+			    }
+			}
+			$menu entryconfigure 6 -state normal
+
+		    } else  {
+			for {set q 0} {$q <= [$menu index last]} {incr q} {
+			    if {[$menu type $q] == "command"} {
+				$menu entryconfigure $q -state normal 
+			    }
+			}
+		    }
+		    #--------------------------------------------------
+		}
+		
+	    }
+	} else { 
+	    for {set q 0} {$q <= [$menu index last]} {incr q} {
+		if {[$menu type $q] == "command"} {
+		    $menu entryconfigure $q -state disabled
+		}
+	    }
+	}
+    } else {  
+	for {set q 0} {$q <= [$menu index last]} {incr q} {
+	    if {[$menu type $q] == "command"} {
+		$menu entryconfigure $q -state disabled
+	    }
+	}
+    }
+}
+
+::itcl::body chellyGUI::addImageToTree { } {
+    
+    set newnode [lindex [AddImage $RealTree [GetIDFromSelection]] 2]
+    
+    if {[llength $newnode]} {
+	updateVisTree $vistree $RealTree $newnode
+    }
+}
+
+::itcl::body chellyGUI::addSurfaceToTree { } {
+    
+    set newnode [lindex [AddSurface $RealTree [GetIDFromSelection]] 2]
+    
+    if {[llength $newnode]} {
+	updateVisTree $vistree $RealTree $newnode
+    }
+}
+
+::itcl::body chellyGUI::addLandmarkToTree { } {
+    
+    set newnode [lindex [AddLandmark $RealTree [GetIDFromSelection]] 2]
+   
+    if {[llength $newnode]} { 
+	updateVisTree $vistree $RealTree $newnode
+    }
+}
+
+::itcl::body chellyGUI::addElectrodeToTree { } {
+    
+    set newnode [lindex [AddElectrode $RealTree [GetIDFromSelection]] 2]
+    
+    if {[llength $newnode]} {
+	updateVisTree $vistree $RealTree $newnode
+    }    
+
+}
+
+::itcl::body chellyGUI::addPatientToTree { } {
+    
+    set newnode [lindex [AddPatient $RealTree [GetIDFromSelection]] 2]
+    
+    if {[llength $newnode]} {
+	updateVisTree $vistree $RealTree $newnode
+    }
+}
+
+
+::itcl::body chellyGUI::addFolderToTree { } {
+    
+    set newnode [lindex [AddFolder $RealTree [GetIDFromSelection]] 2]
+    
+    #recalculate the transformation cache
+    
+    if {[llength $newnode]} {
+	updateVisTree $vistree $RealTree $newnode
+    }    
+}
+
+
+::itcl::body chellyGUI::addSubtreeAtSelection { {type 1} } {
+    
+    $mdTopWidget config -cursor watch;  update idletasks
+
+    switch -exact -- $type {
+
+	1 { AddSubtree $RealTree [GetIDFromSelection] }
+	2 { AddMultiSubjfMRI $RealTree [GetIDFromSelection] }
+	3 { AddCSIPatient $RealTree [GetIDFromSelection] }
+	4 { AddAllCSI $RealTree [GetIDFromSelection] }
+	5 { AddMSBData $RealTree [GetIDFromSelection] }
+	
+    }
+	$mdTopWidget config -cursor ""
+
+}
+
+::itcl::body chellyGUI::renameSelected { } {
+    
+    set thisNode [GetIDFromSelection] 
+    if {!$thisNode} {return -1}
+
+    set selectionTitle [ $RealTree get $thisNode title ]
+    set newTitle [Single_Entry_Dialog "Rename" "Enter the new name for this node" $selectionTitle]
+    
+    if { $newTitle == -1} {return -1}
+    if { $newTitle == [$RealTree get $thisNode title ] } {return -1}  
+    if { ![ checkForIllegalCharacters $newTitle ] } {
+	renameSelected
+    } else {
+	
+	set selectionPath "[ lindex [ Tree::getselectionpath $vistree ] 0 ]/"
+	set offset [ expr [ string length $selectionPath ] - [ string length $selectionTitle ] - 2 ]
+	foreach path [ array names NodeIDs ] {
+	    if { [ regexp ^$selectionPath $path ] } {
+		set newPath [ regsub -start $offset -- $selectionTitle $path $newTitle ] 
+		set NodeIDs($newPath) $NodeIDs($path)
+		unset NodeIDs($path)
+	    }
+	}
+	 
+	unset NodeIDs([ lindex [ Tree::getselectionpath $vistree ] 0 ])
+	set newSelectionPath [ regsub $selectionTitle$ [ lindex [ Tree::getselectionpath $vistree ] 0 ] $newTitle ]
+	set NodeIDs($newSelectionPath) $thisNode
+	$RealTree set $thisNode title $newTitle
+	updateVisTree $vistree $RealTree [ $RealTree parent $thisNode ]
+		
+	set TreeChanged 1
+    } 
+}
+
+
+::itcl::body chellyGUI::delSelectedFromTree { } {
+    
+    if {[$RealTree get [GetIDFromSelection] type] == "Atlas"} {
+	set AtlasImage -1
+    }
+
+    set killnode [GetIDFromSelection]
+    set parentofkillnode [$RealTree parent [GetIDFromSelection]]
+    
+    foreach child [$RealTree children -all $killnode] {
+
+	if {[$RealTree keyexists $child pxitclobj]} {
+	    set obj [$RealTree get $child pxitclobj]
+	    ::itcl::delete object $obj
+	}
+	if {[$RealTree keyexists $child pxitclTransToParent]} {
+	    set obj [$RealTree get $child pxitclTransToParent]
+	    ::itcl::delete object $obj
+	}
+	catch { unset TransformsCache($myname,$child:$killnode) }
+	catch { unset TransformsCache($myname,$child:$killnode,fname) }
+	catch { unset TransformsCache($myname,$child:$killnode,fileset) }
+	
+	if {[$RealTree keyexists $child pxitclTransFromParent]} {
+	    set obj [$RealTree get $child pxitclTransFromParent]
+	::itcl::delete object $obj
+	}
+	catch { unset TransformsCache($myname,$killnode,$child) }
+	catch { unset TransformsCache($myname,$killnode,$child,fname) }
+	catch { unset TransformsCache($myname,$killnode,$child,fileset) }
+	
+    }
+    
+    #Now delete the actual node to be killed
+    
+    if {[$RealTree keyexists $killnode pxitclobj]} {
+	set obj [$RealTree get $killnode pxitclobj]
+	::itcl::delete object $obj
+    }
+    if {[$RealTree keyexists $killnode pxitclTransToParent]} {
+	set obj [$RealTree get $killnode pxitclTransToParent]
+	::itcl::delete object $obj
+    }
+    catch { unset TransformsCache($myname,$killnode:$parentofkillnode) }
+    catch { unset TransformsCache($myname,$killnode:$parentofkillnode,fname) }
+    catch { unset TransformsCache($myname,$killnode:$parentofkillnode,fileset) }
+    
+    if {[$RealTree keyexists $killnode pxitclTransFromParent]} {
+	set obj [$RealTree get $killnode pxitclTransFromParent]
+	::itcl::delete object $obj
+    }
+    catch { unset TransformsCache($myname,$parentofkillnode,$killnode) }
+    catch { unset TransformsCache($myname,$parentofkillnode,$killnode,fname) }
+    catch { unset TransformsCache($myname,$parentofkillnode,$killnode,fileset) }
+    
+    
+    
+    $RealTree delete $killnode
+    
+    updateVisTree $vistree $RealTree $parentofkillnode
+
+    set TreeChanged 1
+    
+}
+
+::itcl::body chellyGUI::setSelectedFileName { } {
+    
+    #Set the image in question to the currently selected tree item
+    set node [GetIDFromSelection]
+    
+    #Set this node's file name
+    setNodeFilename $node
+    
+    #update the visualization tree
+    updateVisTree $vistree $RealTree $node
+    
+}
+
+::itcl::body chellyGUI::setTransToParent { } {
+    
+    set node [GetIDFromSelection]
+    
+    setNodeTransformToParFile $node
+    
+    updateVisTree $vistree $RealTree $node
+    
+}
+
+::itcl::body chellyGUI::setTransFromParent { } {
+    
+    set node [GetIDFromSelection]
+    
+    setNodeTransformFromParFile $node
+    
+    updateVisTree $vistree $RealTree $node
+    
+}
+
+# -----------------------------------------------------
+
+::itcl::body chellyGUI::clearTransToParent { } {
+    
+    set node [GetIDFromSelection]
+
+    $RealTree set $node TransToParFileName -1
+    $RealTree set $node ToParFilenameSet 0
+    set TransformsCache($myname,$node:[$RealTree parent $node],fileset) 0
+    set TransformsCache($myname,$node:[$RealTree parent $node],loaded) 0
+    
+    doTransformsExist $RealTree $node
+    set TreeChanged 1
+    updateVisTree $vistree $RealTree $node
+    
+}
+
+::itcl::body chellyGUI::clearTransFromParent { } {
+    
+    set node [GetIDFromSelection]
+    
+    $RealTree set $node TransFromParFileName -1
+    $RealTree set $node FromParFilenameSet 0
+    set TransformsCache($myname,[$RealTree parent $node]:$node,fileset) 0
+    set TransformsCache($myname,[$RealTree parent $node]:$node,loaded) 0
+
+    doTransformsExist $RealTree $node
+    set TreeChanged 1
+    updateVisTree $vistree $RealTree $node
+    
+}
+
+
+::itcl::body chellyGUI::setIdentityToggle { } {
+    
+    set node [GetIDFromSelection]
+    
+    toggleIdentity $node
+    
+    updateVisTree $vistree $RealTree $node
+    
+}
+
+#------------------------------------------------------------------------------------------
+# These are the Atlas Module Integration Methods
+#------------------------------------------------------------------------------------------
+
+::itcl::body chellyGUI::addAtlasToTree { } {
+    
+    set newnode [lindex [AddAtlasNode $RealTree [GetIDFromSelection]] 2]
+    
+    #recalculate the transformation cache
+    
+    if {[llength $newnode]} {
+	updateVisTree $vistree $RealTree $newnode
+    }
+}
+
+::itcl::body chellyGUI::AddAtlasNode { realtreename ParentNodeID {title -1}} {
+    if {[llength $ParentNodeID] > 0} {
+	if {$title == -1} {
+	    set AtlasTitle "Brain_Atlas"
+	} else { set AtlasTitle $title }
+	
+	set origTitle $AtlasTitle
+	
+	if {[string match $AtlasTitle -1] | $AtlasTitle == ""} { return } else {
+
+	    #----Input Validation----------------------------------------------------------------------
+	    for {set a 0} {$a < [string length $AtlasTitle]} {incr a} {
+		set achar [string range $AtlasTitle $a $a]
+		
+		if {![string is wordchar $achar] && ![string is space $achar] \
+			&& ![string match {[.]} $achar] && ![string match {[-]} $achar] && ![string match {[^]} $achar]} {
+		    error "Cannot add atlas using character $achar  -- Node names can only can contain the following characters: \n     a-z, A-Z, 0-9, _, -, ., ^, and spaces"
+		    
+		}
+	    }
+	    #------------------------------------------------------------------------------------------
+
+	    
+	    set ProposedPath [file join [getPath $realtreename $ParentNodeID] $AtlasTitle]
+	    set UniqueSuffix 1
+	    set suffixed 0
+	    
+	    while {[Tree::itemexists $vistree $ProposedPath]} {
+		
+		if { $suffixed == 1 } {
+		    #delete the suffix
+		    set AtlasTitle [string replace $AtlasTitle [string last _ $AtlasTitle] end]
+		}
+		
+		append AtlasTitle _ $UniqueSuffix
+		set ProposedPath [file join [getPath $realtreename $ParentNodeID] $AtlasTitle]
+		set suffixed 1
+		incr UniqueSuffix
+	    }
+	    
+	    
+	    if {![Tree::itemexists $vistree $ProposedPath]} {
+		
+		#Create a unique identifier for the Atlas
+		set AtlasID $MasterCount
+		incr MasterCount
+		
+		set AtlasImage $AtlasID
+		
+		$realtreename insert $ParentNodeID end $AtlasID
+		AtlasInitialize $realtreename $AtlasID
+		nameNode $realtreename $AtlasID $AtlasTitle
+		$realtreename set $AtlasID type Atlas
+		
+	    } else { 
+		error "Please select a unique image name"
+	    }
+	}
+	
+	set TreeChanged 1
+	return [list $suffixed $origTitle $AtlasID]
+	
+    } else {tk_messageBox -type ok -title "Need Selection" -message "Please select a parent in the tree" -icon info}
+}
+
+::itcl::body chellyGUI::AtlasInitialize { realtreename node } {
+    
+    NodeInitialize $realtreename $node
+    
+    $realtreename set $node type Atlas
+    $realtreename set $node pxitclobj [ [pxitclimage \#auto] GetThisPointer ]
+    
+    #A couple display properties for the node
+    $realtreename set $node icon $atlasiconchoice
+    $realtreename set $node linecolor red
+    
+    #This node property toggles the "identity" propery for the image - ie, no transformation 
+    $realtreename set $node FromParFilenameSet 0
+    $realtreename set $node ToParFilenameSet 0
+    $realtreename set $node IsIdentity 0
+    
+ 
+    
+};# end AtlasInitialize method
+
+
+
+::itcl::body chellyGUI::AtlasShowSelectedNode { } {
+    
+    set node [GetIDFromSelection]
+    
+    SendImageToAtlasModule $node 
+}
+
+::itcl::body chellyGUI::SendImageToAtlasModule { { nodeID -1} {raise 1}} {
+
+
+    #Let user choose an atlas from all displayed in tree:
+    #------------------------------------------------------------------------------------------
+    catch {unset AtlasChoices}
+    foreach node [$RealTree children -all [$RealTree rootname]] {
+	if {[$RealTree get $node type] == "Atlas"} {
+	    lappend AtlasChoices $node
+	}
+    }
+    
+    if {[llength $AtlasChoices] > 1} {
+	global AtlasSelectDialogEntryResult -1
+	
+	foreach c $AtlasChoices {
+	    set atlaschoicearray([getPath $RealTree $c]) $c
+	}
+	
+	iwidgets::selectiondialog .atlasselbox -borderwidth 2 -height 200\
+	    -labelfont -Adobe-Helvetica-Bold-R-Normal--*-140-*-*-*-*-*-* \
+	    -title "Choose ATLAS Definition Image" \
+	-textbackground ghostwhite -itemslabel "Atlases Available In Tree:" \
+	    -selectionon 0
+    
+	eval .atlasselbox insert items 0 [array names atlaschoicearray]
+	.atlasselbox hide Apply
+	.atlasselbox center
+	.atlasselbox configure -modality application
+	.atlasselbox buttonconfigure OK -command {set AtlasSelectDialogEntryResult [.atlasselbox get]; .atlasselbox deactivate }
+	.atlasselbox buttonconfigure Cancel -command {set AtlasSelectDialogEntryResult -1; .atlasselbox deactivate }
+	
+	update idletasks
+	.atlasselbox activate
+	destroy .atlasselbox
+	#------------------------------------------------------------------------------------------
+	
+	if {[llength $AtlasSelectDialogEntryResult] < 1} {return}
+	if {$AtlasSelectDialogEntryResult == -1} {return}
+	
+	set AtlasImage $atlaschoicearray($AtlasSelectDialogEntryResult)
+
+    } else { set AtlasImage [lindex $AtlasChoices 0] }
+
+#    puts "Atlas Image - $AtlasImage"
+    if {$AtlasImage != -1} {
+
+	if {$nodeID == -1} {
+	    set node [GetIDFromSelection]
+	} else { set node $nodeID }
+	
+	
+	if {$node != -1 && $node != ""} {
+	    
+	    #--------------------------------------------------
+	    # First send the selected node to the atlas program
+	    #--------------------------------------------------
+	    EnsureFileLoaded $node
+	    set pxiobj [$RealTree get $node pxitclobj]
+	    set type [$RealTree get $node type]
+	    
+	    $AtlasModule LoadImage $pxiobj
+	    
+	    #--------------------------------------------------
+	    # Then figure out the transformation, and send it too
+	    #--------------------------------------------------
+	    
+	    findTransforms $RealTree $node $AtlasImage
+	    set AtlasTransList $TransformsCache($myname,$node:$AtlasImage)
+	    catch {EnsureTransListLoaded $AtlasTransList} 
+	    
+	    set gen [ CreateTransformation $AtlasTransList ]    
+	    $AtlasModule SetTransToAtlasSpace $gen
+	    
+	}
+	
+	if {$raise} {
+	    $AtlasModule ShowTop
+	} 
+    } else { error "No atlas has been set for this tree" }
+}
+
+::itcl::body chellyGUI::BringUpAtlasModule { } {
+    
+    $AtlasModule ShowTop
+    
+};# end BringUpAtlasModule method
+
+
+#------------------------------------------------------------------------------------------
+# This is the end of the Atlas Module Integration Methods
+#------------------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------------------
+# These are the SPECT Processing Module Integration Methods
+#------------------------------------------------------------------------------------------
+
+::itcl::body chellyGUI::ShowSPECTtool { } {
+
+    if {$SPECT_initialized == 0} {
+	$SPECTmodule Initialize .[pxvtable::vnewobj] $this $viewer2
+	set SPECT_initialized 1
+    }
+
+    $SPECTmodule ShowTop
+
+}
+
+::itcl::body chellyGUI::ShowREGtool { } {
+
+    if {$REG_initialized == 0} {
+	$REGmodule Initialize .[pxvtable::vnewobj] $this
+	set REG_initialized 1
+    }
+    $REGmodule ShowTop
+
+}
+
+
+#------------------------------------------------------------------------------------------
+# This is the end of the SPECT Processing Module Integration Methods
+#------------------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------------------
+# These are the Electrode Attribute Control Module Integration Methods
+#------------------------------------------------------------------------------------------
+
+::itcl::body chellyGUI::mdLoadElectrodeAttributes { } { 
+
+ 
+    catch {unset AttrArray}
+    set newlyLoadedArray [$FileManager LoadElectrodeAttributes]
+    if { $newlyLoadedArray != -1} {array set AttrArray $newlyLoadedArray} else {return -1}
+    
+    #Get all grids, and set up a lookup array
+    #----------------------------------------------------------------------
+    set ThisNode [GetIDFromSelection]
+    EnsureFileLoaded $ThisNode
+    set electrodeobj        [$RealTree get $ThisNode pxitclobj]
+    set electrodemultigrid  [$electrodeobj GetObject]
+   
+    set ng [$electrodemultigrid GetNumberOfGrids] 
+
+    for {set gridnumber 0} {$gridnumber < $ng} {incr gridnumber} {
+	set grid [ $electrodemultigrid GetElectrodeGrid $gridnumber ]
+	set gridname [ $grid GetGridName  ]
+	set gridletter [ string range [ string trim $gridname ] 0 0 ]
+	set gridnum($gridletter) $gridnumber
+	
+	scan [ $grid GetDimensions ] "%d %d" dimx dimy
+	set gridsize [ expr $dimx * $dimy ]
+	
+	# Make an array to hash real index to internal index
+	#iindex = electrodeInternalIndex(gridnumber,realindex)
+	for {set j 0} {$j < $gridsize} {incr j} {
+	    set realindex [ $grid GetElectrodeRealIndex $j ]
+	    set electrodeInternalIndex($gridnumber,$realindex) $j
+	    set elec [ $grid GetElectrode $j ]
+	    $elec SetElectrodePresent 0
+	    set values [ $elec GetValues ]
+	    $values SetNumberOfTuples [llength $AttrArray(titles)]
+	    $values FillComponent 0 -1.0
+	}
+    }
+    #----------------------------------------------------------------------
+
+    set l [llength [array names AttrArray]]
+
+    # Now read the attribute array back out and store it in appropriate electrode
+
+    for { set i 0 } { $i < $l } { incr i } {
+	
+	set thisname [lindex [lsort [array names AttrArray]]  $i]
+
+	if {$thisname != "titles"} {
+	    #####-------
+	    set gridletter [string range $thisname 0 [expr [string first , $thisname] - 1] ]
+	    #####-------
+	    
+	    set firstcommaindex [string first , $thisname]
+	    set secondcommaindex [string first , $thisname [expr $firstcommaindex + 1] ]
+	    
+	    #####-------
+	    set electrodenumber [ string range $thisname [expr $firstcommaindex + 1] [expr $secondcommaindex - 1] ]
+	    set valueindex      [ string range $thisname [expr $secondcommaindex +1 ] end ]
+	    
+	    #####-------
+	    
+	    set gridindex $gridnum($gridletter) 
+	    set electrodeindex $electrodeInternalIndex($gridindex,$electrodenumber) 
+	    
+	    set grid       [ $electrodemultigrid GetElectrodeGrid $gridindex ]
+	    set electrode  [ $grid GetElectrode $electrodeindex ]
+	    $electrode SetElectrodePresent 1
+
+	    [ $electrode GetValues ] SetComponent $valueindex 0 $AttrArray($gridletter,$electrodenumber,$valueindex)
+#	    puts stderr "$gridletter, $electrodenumber $valueindex =  $AttrArray($gridletter,$electrodenumber,$valueindex) "
+	} else {
+#	    puts stderr "$thisname is bad"
+	}
+    }
+
+    #----------------------------------------------------------------------
+    #Now all electrode properties have been set - Save a file
+    #----------------------------------------------------------------------
+
+    #Save a new file
+    set newName "[file rootname [$RealTree get $ThisNode FileName]]_Attr_Loaded.mgrid"
+    $electrodemultigrid Save $newName
+    
+    set changefname [tk_messageBox -type yesno -default no -title "Warning"\
+			  -message "Would you like to have this node in the tree point to the new electrode file you just created?" -icon question]
+
+    if {$changefname == "no"} { return -1 }
+    if {$changefname == "yes"} {
+	setNodeFilename $ThisNode $newName
+	$RealTree set $ThisNode Attributes $AttrArray(titles)
+	$RealTree set $ThisNode notes "The following attributes are loaded for this electrode file:\n-------------------------------------------------------------\n\n$AttrArray(titles)"
+    }
+    
+
+
+
+}; #end mdLoadElectrodeAttributes method
+
+
+::itcl::body chellyGUI::SendElectrodeToAtrrControl { { nodeID -1} {raise 1} } {
+    
+    if {$nodeID == -1} {
+	set node [GetIDFromSelection]
+    } else { set node $nodeID }
+    	
+
+    if {$node != -1 && $node != ""} {
+	    
+	#--------------------------------------------------
+	# First be sure node is an electrode, and is loaded
+	#--------------------------------------------------
+	EnsureFileLoaded $node
+	set pxielectrodeobj [$RealTree get $node pxitclobj]
+	set type [$RealTree get $node type]
+	if {$type != {Surface Electrode} } { 
+	    error "The selected object is not an Electrode Map"
+	    return -1  
+	}
+	
+	#--------------------------------------------------
+	# Now transform the selected electrode to ref space
+	#--------------------------------------------------
+	
+	if {$SpaceImage != -1} {
+	    
+	    findTransforms $RealTree $node $SpaceImage
+	    set BottomUpTransList $TransformsCache($myname,$node:$SpaceImage)
+	    EnsureTransListLoaded $BottomUpTransList
+	    
+	    set gen [ CreateTransformation $BottomUpTransList ]
+	    set newelec [ [pxitclelectrodemultigrid \#auto] GetThisPointer ]
+	    $newelec Copy $pxielectrodeobj
+	    $newelec Transform $gen
+	    
+	    #--------------------------------------------------
+	    # Now send the transformed electrode object, space 
+	    # image object, and selected node's  Attribute title 
+	    # list to the Attribute Control
+	    #--------------------------------------------------
+	    
+	    
+	    set SpaceImageObject [$RealTree get $SpaceImage pxitclobj]
+	    $ElectAttrModule SetElectrodeObject $newelec  $SpaceImageObject \
+		[$RealTree get $node Attributes] [$RealTree get $node FileName]
+	    if {$raise} {
+		$ElectAttrModule ShowTop
+	    } 
+	    
+	} else {
+	    error "You must have a Space Image set in order to create an electrode visulization overlay."
+	    return -1
+	}
+	
+	
+    }
+    
+};# end SendElectrodeToAttrControl method
+
+::itcl::body chellyGUI::PutElectrodeAttrControlOutputInTree { } {
+
+    if { [$ElectAttrModule GetOutputImage] != -1 } {
+
+	set NewImage [$ElectAttrModule GetOutputImage]
+	
+	set ObjectID $MasterCount
+	incr MasterCount
+	$RealTree insert $SpaceImage end $ObjectID
+	ImageInitialize $RealTree $ObjectID
+
+	[$RealTree get $ObjectID pxitclobj] ShallowCopy $NewImage
+
+	nameNode $RealTree $ObjectID "Electrode_Overlay_$ObjectID"
+	toggleIdentity $ObjectID 1
+	
+	#-----------------------------------------------------------------------------
+	#Everything below here occurs for the initialization of any type added to tree
+	#-----------------------------------------------------------------------------
+	set pathList [$RealTree rootname]
+	set pathListIDs [$RealTree ancestors $ObjectID]
+	
+	for {set y [expr [llength $pathListIDs] - 1]} {$y > -1} {incr y -1} {
+	    if {[lindex $pathListIDs $y] != [$RealTree rootname]} {
+		lappend pathList [$RealTree get [lindex $pathListIDs $y] title]
+		
+	    }
+	}
+	
+	set pathName /
+	for {set i 0} {$i < [llength $pathList]} {incr i} {
+	    append pathName [lindex $pathList $i]
+	    append pathName /
+	}
+	append pathName [$RealTree get $ObjectID title]
+	set NodeIDs($pathName) $ObjectID
+	
+	set newfilename [$FileManager SaveFile [$RealTree get $ObjectID pxitclobj]]
+	setNodeFilename $ObjectID $newfilename
+	
+	updateVisTree $vistree $RealTree $ObjectID			
+
+	puts "[[$RealTree get $ObjectID pxitclobj] GetDescription]"
+
+
+    }
+
+};# end BringUpElectrodeAttrControl method
+
+
+#------------------------------------------------------------------------------------------
+# This is the end of the Electrode Attribute Control Module Integration Methods
+#------------------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------------------
+# ROI Definiton Stuff
+#------------------------------------------------------------------------------------------
+
+::itcl::body chellyGUI::addROIDefToTree { } {
+    
+    set newnode [lindex [AddROIDefNode $RealTree [GetIDFromSelection]] 2]
+    
+    #recalculate the transformation cache
+    if {[llength $newnode]} {
+	updateVisTree $vistree $RealTree $newnode
+    }
+}
+
+::itcl::body chellyGUI::AddROIDefNode { realtreename ParentNodeID {title -1}} {
+    
+    if {[llength $ParentNodeID] > 0} {
+	if {$title == -1} {
+	    set ROIDefTitle [Single_Entry_Dialog "ROI Definition" "Enter a name for the ROI Definition Image"]
+	} else { set ROIDefTitle $title }
+	
+	set origTitle $ROIDefTitle
+	
+	if {[string match $ROIDefTitle -1] | $ROIDefTitle == ""} { return } else {
+
+
+	    #----Input Validation----------------------------------------------------------------------
+	    for {set a 0} {$a < [string length $ROIDefTitle]} {incr a} {
+		set achar [string range $ROIDefTitle $a $a]
+		
+		if {![string is wordchar $achar] && ![string is space $achar] \
+			&& ![string match {[.]} $achar] && ![string match {[-]} $achar] && ![string match {[^]} $achar]} {
+		    
+		    error "Cannot add ROI image using character $achar  -- Node names can only can contain the following characters: \n     a-z, A-Z, 0-9, _, -, ., ^, and spaces"
+
+		}
+	    }
+	    #------------------------------------------------------------------------------------------
+	    
+	    
+	    set ProposedPath [file join [getPath $realtreename $ParentNodeID] $ROIDefTitle]
+	    set UniqueSuffix 1
+	    set suffixed 0
+	    
+	    while {[Tree::itemexists $vistree $ProposedPath]} {
+		
+		if { $suffixed == 1 } {
+		    #delete the suffix
+		    set ROIDefTitle [string replace $ROIDefTitle [string last _ $ROIDefTitle] end]
+		}
+		
+		append ROIDefTitle _ $UniqueSuffix
+		set ProposedPath [file join [getPath $realtreename $ParentNodeID] $ROIDefTitle]
+		set suffixed 1
+		incr UniqueSuffix
+	    }
+	    
+	    
+	    if {![Tree::itemexists $vistree $ProposedPath]} {
+		
+		#Create a unique identifier for the ROIDef
+		set ROIDefID $MasterCount
+		incr MasterCount
+		
+		set ROIDefImage $ROIDefID
+		
+		$realtreename insert $ParentNodeID end $ROIDefID
+		ROIDefInitialize $realtreename $ROIDefID
+		nameNode $realtreename $ROIDefID $ROIDefTitle
+		$realtreename set $ROIDefID type ROIDef
+		
+				
+	    } else { 
+		error "Please select a unique image name"
+	    }
+	}
+
+	set TreeChanged 1	
+	return [list $suffixed $origTitle $ROIDefID]
+	
+    } else {tk_messageBox -type ok -title "Need Selection" -message "Please select a parent in the tree" -icon info}
+}
+
+::itcl::body chellyGUI::ROIDefInitialize { realtreename node } {
+    
+    NodeInitialize $realtreename $node
+    
+    $realtreename set $node type ROIDef
+    $realtreename set $node pxitclobj [ [pxitclimage \#auto] GetThisPointer ]
+    
+    #A couple display properties for the node
+    $realtreename set $node icon $atlasiconchoice
+    $realtreename set $node linecolor red
+    
+    #This node property toggles the "identity" propery for the image - ie, no transformation 
+    $realtreename set $node FromParFilenameSet 0
+    $realtreename set $node ToParFilenameSet 0
+    $realtreename set $node IsIdentity 0
+    
+        
+};# end ROIDefInitialize method
+
+
+#------------------------------------------------------------------------------------------
+# end of ROI Definiton Stuff
+#------------------------------------------------------------------------------------------
+
+#------------------------------------------------------------------------------------------
+# These are the search Dialog methods 
+#------------------------------------------------------------------------------------------
+::itcl::body chellyGUI::SearchDialog { } {
+    
+    update idletasks
+    
+    if {$SearchDialogName == -1 | ![winfo exists $SearchDialogName]} {
+	
+	set SearchDialogName .[ pxvtable::vnewobj ]
+	toplevel $SearchDialogName -bg "light blue"
+	wm title $SearchDialogName "Search the Tree"
+	
+	set SearchTopFrame [frame $SearchDialogName.topframe -bg "light blue"]
+	pack $SearchTopFrame -side top
+	
+	#--------------------------------------------------
+	set modWidgetWrapper [labelframe $SearchTopFrame.wrapper -bg "light blue" -text "Filter by Modality"]
+	pack $modWidgetWrapper -side left -fill x -padx 4 -pady 4
+	
+	set modalitysel [::iwidgets::scrolledlistbox $modWidgetWrapper.modl -selectmode extended -exportselection 0 \
+			     -borderwidth 2 -textbackground ghostwhite -visibleitems 25x15]
+	
+	foreach r [lsort [array names RecognizedTypes]] {
+	    lappend ModalityNames $RecognizedTypes($r)
+	}
+	
+	foreach a $ModalityNames {
+	    $modalitysel insert end $a
+	}
+	pack $modalitysel -fill both -expand 1 -padx 5 -pady 5
+	
+	#--------------------------------------------------
+	
+	set wrap2 [frame $SearchTopFrame.wrapper2 -bg "light blue"]
+	pack $wrap2 -side left -fill both -padx 4 -pady 4
+	#--------------------------------------------------
+	set titleWidgetWrapper [labelframe $wrap2.titlewrap -bg "light blue" -text "Filter by Title"]
+	pack $titleWidgetWrapper -side top -fill x -padx 4 -pady 4
+	#
+	set titlesel [::iwidgets::entryfield $titleWidgetWrapper.titl]
+	pack $titlesel -side top -fill x -padx 5 -pady 5
+	#
+	#--------------------------------------------------
+
+	#--------------------------------------------------
+	set folderWidgetWrapper [labelframe $wrap2.folderwrap -bg "light blue" -text "Specify Folder(s)"]
+	pack $folderWidgetWrapper -side top -fill both -padx 4 -pady 4
+	#
+	set folderbox [::iwidgets::entryfield $folderWidgetWrapper.folder]
+	pack $folderbox -side left -fill x -expand 1 -padx 5 -pady 5
+	set folderbutton [eval "button $folderWidgetWrapper.[pxvtable::vnewobj] -text ... -command { $this SearchGetFolder } -background \"light blue\" -width 1"]
+	pack $folderbutton -side right -padx {0 4} -pady {0 3}
+	#
+	#--------------------------------------------------
+
+	set clearbutton [eval "button $wrap2.clearbut -bg yellow -text \"Clear Search Fields\" -command { $SearchDialogName.topframe.wrapper2.titlewrap.titl delete 0 end; $SearchDialogName.topframe.wrapper.modl selection clear 0 end; $folderbox delete 0 end; }"]
+	pack $clearbutton -side top -fill x -padx 3 -pady 5
+	#
+	#--------------------------------------------------
+	set instructions [message $wrap2.inst -justify center -relief ridge -text "Select the modalities to search for (left), or enter a title to search for (above).  If both are specified, only images matching both parameters will be returned. Results will appear selected in the list at right.  You may deselect unwanted elements to exclude them from analysis.  Operations below will be performed on the selected elements in the Results list"]
+	
+	pack $instructions -side top -fill both -padx 5 -pady 5 -expand 1
+	#
+	#
+	#--------------------------------------------------
+	#--------------------------------------------------
+	set resultWidgetWrapper [labelframe $SearchTopFrame.reswrapper -bg "light blue" -text "Results"]
+	pack $resultWidgetWrapper -side left -fill x -padx 4 -pady 4
+	
+	set resultlist [::iwidgets::scrolledlistbox $resultWidgetWrapper.resl -selectmode multiple -exportselection 0 \
+			    -borderwidth 2 -textbackground ghostwhite -visibleitems 45x15]
+	pack $resultlist -fill both -expand 1 -padx 5 -pady 5
+	
+	#--------------------------------------------------------------------------------
+	set searchbutton [eval "button $SearchDialogName.sbut -bg green -text \"Search!\" -command {$this SearchCallback $SearchDialogName Search}"]
+	pack $searchbutton -side top -fill x -padx 5 -pady 4
+	#--------------------------------------------------------------------------------
+	
+	#------------------------------------------------------------------------------------------------------------
+	#--------------Here are the functions that can be performed on the result group------------------------------
+	#------------------------------------------------------------------------------------------------------------
+	#This frame holds all the group operation buttons
+	set OperationsFrame [labelframe $SearchDialogName.oper -bg "light blue" -text "Operations"]
+	pack $OperationsFrame -side top -fill both -padx 5 -pady 5
+	
+	#--------------------------------------------------------------------------------
+	set SaveButton [eval "button $OperationsFrame.savebut -bg \"bisque\" -text \"Save Images in Reference Space\" -command {$this SearchCallback $SearchDialogName SaveInRef}"]
+	pack $SaveButton -side top -fill x -padx 40 -pady 4
+	#--------------------------------------------------------------------------------
+	set AverageButton [eval "button $OperationsFrame.avgbut -bg \"bisque\" -text \"Average Images in Reference Space\" -command {$this SearchCallback $SearchDialogName Average}"]
+	pack $AverageButton -side top -fill x -padx 40 -pady 4
+	#--------------------------------------------------------------------------------
+	set ROIButton [eval "button $OperationsFrame.roibut -bg \"bisque\" -text \"Compute ROI stats in Reference Space\" -command {$this SearchCallback $SearchDialogName ROI}"]
+	pack $ROIButton -side top -fill x -padx 40 -pady 4
+	
+	
+	
+    } else {
+	#If the dialog already exists, show it
+	switch -- [wm state $SearchDialogName] {
+	    normal {
+		raise $SearchDialogName
+	    }
+	    withdrawn -
+	    iconic {
+		wm deiconify $SearchDialogName
+	    }
+	}
+	return 0
+	
+    }
+};# End SearchDialog method
+
+::itcl::body chellyGUI::SearchGetFolder { } {
+    
+    set FolderChoices ""
+    set foldersearchboxlist ""
+    foreach node [$RealTree children -all [$RealTree rootname]] {
+	if {[$RealTree get $node type] == "Folder"} {
+	    lappend FolderChoices $node
+	}
+    }
+    
+    foreach c $FolderChoices {
+	set folderchoicearray([$RealTree get $c title]) $c
+    }
+    
+    set foldersearchselbox .[ pxvtable::vnewobj ]
+
+    iwidgets::selectiondialog $foldersearchselbox -borderwidth 2 -height 200\
+	-labelfont -Adobe-Helvetica-Bold-R-Normal--*-140-*-*-*-*-*-* \
+	-title "Choose Folder" \
+	-textbackground ghostwhite -itemslabel "Folders In Tree:" \
+	-selectionon 0 
+
+    [$foldersearchselbox component selectionbox]  component items configure -selectmode multiple
+   
+    eval $foldersearchselbox insert items end [lsort [array names folderchoicearray]]
+    set foldersearchboxlist [lsort [array names folderchoicearray]]
+
+    $foldersearchselbox hide Apply
+    $foldersearchselbox center
+    $foldersearchselbox configure -modality application
+    eval "$foldersearchselbox buttonconfigure OK -command {$this FolderSelectionInsert; $foldersearchselbox deactivate }"
+    eval "$foldersearchselbox buttonconfigure Cancel -command {$foldersearchselbox deactivate }"
+    
+    update idletasks
+    $foldersearchselbox activate
+    destroy $foldersearchselbox
+    
+    
+}
+
+::itcl::body chellyGUI::FolderSelectionInsert { } {
+
+    $folderbox delete 0 end
+    foreach indx [$foldersearchselbox curselection] {
+	lappend result [lindex $foldersearchboxlist $indx]
+    }
+    $folderbox insert 0 $result
+    
+}
+
+::itcl::body chellyGUI::SearchCallback { dialog command } {
+    
+    set ActiveList [ list ]
+
+    switch -exact -- $command {
+	
+	"search" -
+	"Search" {
+	    
+	    doSearch $dialog
+	    
+	}
+	
+	"saveinref" -
+	"SaveInRef" {
+	    
+	    foreach r [$dialog.topframe.reswrapper.resl getcurselection] {
+		lappend ActiveList $ResultDisplay($r)
+	    }
+	    
+	    SaveAllInRef $ActiveList
+	    
+	}
+	
+	"average" -
+	"Average" {
+	    
+	    foreach r [$dialog.topframe.reswrapper.resl getcurselection] {
+		lappend ActiveList $ResultDisplay($r)
+	    }
+	    
+	    if { ![ llength $ActiveList ] } {
+		tk_messageBox -type ok -title "Warning" -message "No images selected" -icon info 
+		return -1
+	    }
+
+	    set ParentDirectory [tk_chooseDirectory -title "Choose directory to save average in"]	    
+	    
+	    set AvgFileName [file join $ParentDirectory "group_task"]
+	    set ResultImages [ComputeAverages [sendAllToCommonSpace $SpaceImage $ActiveList] $AvgFileName]
+	    
+	    foreach img $ResultImages {
+		$img Save
+		
+		set ThisName [string totitle [string range [$img cget -filename] [expr [string last "_" [$img cget -filename]] + 1] end]]
+		set ThisNodeID [lindex [AddImage $RealTree $SpaceImage $ThisName "Result"] 2 ]
+		setNodeFilename $ThisNodeID "[$img cget -filename].hdr"
+		toggleIdentity $ThisNodeID 1
+		
+		updateVisTree $vistree $RealTree $ThisNodeID
+	    }
+	    
+	}
+	
+	"roi" -
+	"ROI" {
+	    
+	    foreach r [$dialog.topframe.reswrapper.resl getcurselection] {
+		lappend ActiveList $ResultDisplay($r)
+	    }
+	    
+	    MultipleROI $ActiveList
+	    
+	}
+	
+	
+    };# End switch
+    
+}
+
+::itcl::body chellyGUI::doSearch { dialog } {
+    
+    
+    set selectedlist [$dialog.topframe.wrapper.modl getcurselection]
+    set titlequery [$dialog.topframe.wrapper2.titlewrap.titl get]
+    set folderquery [$folderbox get]
+
+    set FinalResultList ""
+    set allfolderlist ""
+    set allfoldernamelist ""
+    set foldermatches ""
+    set Result1 ""
+    set Result2 ""
+    set Result3 ""
+    
+    #Clear the result window
+    $dialog.topframe.reswrapper.resl delete 0 end
+
+    #--------------------------------------------------------------------------------
+    #Make a list of all folder nodes, and a list of all their titles
+    set allfolderlist [SearchTree $RealTree [$RealTree rootname] type Folder]
+    foreach t $allfolderlist {
+	lappend allfoldernamelist [$RealTree get $t title]
+    }
+
+    #Now, for each query title, check if it matches one of the folder titles in the tree
+    for {set n 0} {$n < [llength $folderquery] } {incr n} {
+	set res [lsearch -all -glob $allfoldernamelist [lindex $folderquery $n]]
+	if {[llength $res]} {
+	    foreach Match $res {
+		lappend foldermatches [lindex $allfolderlist $Match]
+	    }
+	}
+    }
+
+    
+
+    #if there are any folder matches, add all children of all matching folders
+    if {[llength $foldermatches]} {
+	foreach mat1 $foldermatches {
+	    foreach child1 [$RealTree children -all $mat1] {
+		lappend Result1 $child1
+	    }
+	}
+    } else { 
+	#...otherwise, add all nodes
+	if {[llength $selectedlist] > 0 | [llength $titlequery] > 0 } {
+	    set Result1 [$RealTree children -all [$RealTree rootname]] 
+	} 
+    }
+
+    set FinalResultList $Result1
+    	
+    #--------------------------------------------------------------------------------
+    #Now check the modality query
+    if {[llength $selectedlist] > 0} {
+	
+	#If a modality has been specified, get a list of all metching nodes
+	foreach t [lsort [array names RecognizedTypes]] {
+	    
+	    lappend ModalityKeys $t
+	    lappend ModalityNames $RecognizedTypes($t)
+	    
+	}
+	
+	foreach item $selectedlist {
+	    lappend selectedkeys [lindex $ModalityKeys [lsearch $ModalityNames $item]]
+	};# selected keys is the list of types that the user wants to match
+	
+	foreach Result1Item $Result1 {
+	    set ThisItemType [$RealTree get $Result1Item type]
+	    if { [lsearch $selectedkeys $ThisItemType] != -1 } {
+		lappend Result2 $Result1Item
+	    }
+	}
+
+	set FinalResultList $Result2
+    } else { 
+	#If the modality query has not been specified, just set the results to the same as folder results
+	set Result2 $Result1
+    }
+
+    if {$titlequery != ""} {
+	
+	#If a title query has been entered, search the results of the modality search for the title
+	foreach node $Result2 {
+		if {[$RealTree get $node title] == $titlequery} {
+		    lappend Result3 $node
+		}
+	}
+	set FinalResultList $Result3
+    }    
+
+    
+    foreach d $FinalResultList {
+	
+	#This translates the node number into a display value for the result list
+	set thisresult [getPath $RealTree $d]
+	$dialog.topframe.reswrapper.resl insert end $thisresult
+	
+	#(But we have to keep track of what was displayed, so the user can interact with it)
+	set ResultDisplay($thisresult) $d
+	
+	
+    }
+    $dialog.topframe.reswrapper.resl selection set 0 end
+    
+}
+
+::itcl::body chellyGUI::SaveAllInRef { {listofnodes -1} } {
+    
+    
+    if {$listofnodes == -1} {
+	return
+    } else { set SaveList $listofnodes }
+    
+    if {[llength $SaveList] > 0} {
+	if {$SpaceImage != -1} {
+	    
+	    set ParDirectory [tk_chooseDirectory -title "Choose parent directory for new folder"]	    
+	    set GroupPrefix [Single_Entry_Dialog "Group Folder"  "Enter the Group Folder Name"]
+	    if {$GroupPrefix == -1} {return -1}
+	    
+	    set SaveDirectory [file join $ParDirectory $GroupPrefix]
+	    
+	    file mkdir $SaveDirectory
+	    
+	    puts "SaveDirectory: $SaveDirectory\n--------------------------------------------------\n"
+	    
+	    set count 0
+	    foreach node $SaveList {
+		
+		EnsureFileLoaded $node
+		
+		incr count
+		set thisfilename [nodeName $node]
+		set thisfilename [string map {" " _} $thisfilename]
+		if {[string first . $thisfilename] != -1} {
+		    set thisfilename [string range $thisfilename 0 [expr [string first . $thisfilename] - 1] ]
+		}
+		append thisfilename _ $count
+		
+		set filepath [file join $SaveDirectory $thisfilename]
+		
+		set imageToReslice [$RealTree get $node pxitclobj]
+		set baseimage [$RealTree get $SpaceImage pxitclobj]
+		
+		if {[IsNodeImage $node -1 1]} {
+		    findTransforms $RealTree $SpaceImage $node
+		    set TransList $TransformsCache($myname,$SpaceImage:$node)
+		    
+		    puts stdout "Reslicing: [ $imageToReslice GetDescription ] \t [ [ [ [ $imageToReslice GetImage ]  GetPointData ] GetScalars ] GetRange ]"
+		    set newreslicedimage [ResliceImage $baseimage $imageToReslice $TransList $filepath]
+		    
+		    puts stdout "Output: [ $newreslicedimage GetDescription ] \t [ [ [ [ $newreslicedimage GetImage ]  GetPointData ] GetScalars ] GetRange ]"
+		    
+		    $newreslicedimage Save
+		    ::itcl::delete object $newreslicedimage
+		}
+		
+		if {[IsNodeSurface $node]} {
+		    findTransforms $RealTree $node $SpaceImage 
+		    set TransList $TransformsCache($myname,$node:$SpaceImage)
+		    
+		    set newreslicedimage [ResliceImage $baseimage $imageToReslice $TransList $filepath]
+		    $newreslicedimage Save
+		    ::itcl::delete object $newreslicedimage
+		}
+		
+		
+	    };# End foreach node
+	    
+	} else {tk_messageBox -type ok -title "No Space Image Set" -message "The Reference Space image has not been set" -icon info}
+    } else {tk_messageBox -type ok -title "No Results to Save" -message "There are no items selected in the results list" -icon info}
+    
+};# End SaveAllInRef method
+
+
+::itcl::body chellyGUI::sendAllToCommonSpace { spacenode imagelist } {
+    
+    set ResList ""
+    
+    if {$SpaceImage != -1} {
+	for {set u 0} {$u < [llength $imagelist]} {incr u} {
+	    set node [lindex $imagelist $u]
+
+	    EnsureFileLoaded $node
+	    
+	    set imageToReslice [$RealTree get $node pxitclobj]
+	    set baseimage [$RealTree get $spacenode pxitclobj]
+	    
+	    
+	    if {[IsNodeImage $node -1 1]} {
+		findTransforms $RealTree $spacenode $node
+		set TransList $TransformsCache($myname,$spacenode:$node)
+		
+		set newreslicedimage [ResliceImage $baseimage $imageToReslice $TransList]
+		
+		lappend ResList $newreslicedimage
+	    }
+	    
+	    if {[IsNodeSurface $node]} {
+		findTransforms $RealTree $node $spacenode 
+		set TransList $TransformsCache($myname,$node:$spacenode)
+		
+		set newreslicedimage [ResliceImage $baseimage $imageToReslice $TransList $filepath]
+		lappend ResList $newreslicedimage
+		
+	    }
+	    
+	    
+	};# End for u
+    } else {tk_messageBox -type ok -title "No Space Image Set" -message "The Reference Space image has not been set" -icon info}
+    
+    return $ResList
+    
+}
+
+::itcl::body chellyGUI::ComputeAverages { imagelist filename { background -32767 } } {
+    
+    set filename [ file root $filename ]
+    
+    # imagelist is a list of pxitclimages that have been resliced to same space
+    
+    set num [ llength $imagelist ]
+    
+    set value     $background   
+    # -32767
+    set valueout  0.0
+    set outputStd 1
+    
+    set combofmri [  vtkpxAverageImages [ pxvtable::vnewobj ]]
+    $combofmri SetMedian 0
+    $combofmri SetIgnoreValue $value
+    $combofmri SetIgnoreValueOutput $valueout
+    $combofmri IgnoreFlagOn
+    
+    for { set i 0 } { $i < $num } { incr i } {
+	
+	#ShowProgressVal "Computing Averages image=$i" $progress 
+	$combofmri AddInput [ [ lindex $imagelist $i ] GetImage ]
+    }
+    
+    
+    #ShowProgressVal  "Computing Averages image=$i" $progress 
+    
+    $combofmri ComputeStandardDeviationOn
+    
+    
+    $combofmri Update
+    #ShowProgressVal "Computed Averages image=$i" $progress 
+    
+    set baseimage [ lindex $imagelist 0 ]
+    
+    set meanout [ [pxitclimage \#auto] GetThisPointer ]
+    $meanout ShallowCopyImage [ $combofmri GetOutput ]
+    $meanout CopyImageHeader [ $baseimage GetImageHeader ]
+    $meanout configure -filename "${filename}_average"
+    
+    set sigmaout [ [pxitclimage \#auto] GetThisPointer ]
+    $sigmaout ShallowCopyImage [ $combofmri GetOutputStandardDeviation ]
+    $sigmaout CopyImageHeader [ $baseimage GetImageHeader ]
+    $sigmaout configure -filename "${filename}_stdev"
+    
+    $combofmri Delete
+    
+    set tscoreimage [ ComputeTscoreMap $meanout $sigmaout $num ]
+    
+    $tscoreimage configure -filename "${filename}_tscore"
+    
+    return [ list $meanout $sigmaout $tscoreimage ]
+    
+}
+
+
+itcl::body chellyGUI::ComputeTscoreMap { immean imvar numsubjects } {
+    
+    if { [ $immean GetImageSize ] < 2  } {
+	::pxtclutil::Warning "No Composite Task In Memory"
+	return 0;
+    }
+    
+    if { [ $imvar GetImageSize ] < 2  }  {
+	::pxtclutil::Warning "No Composite Task Standard Deviation In Memory"
+	return 0;
+    }
+    
+    set cast [ vtkImageCast [ pxvtable::vnewobj ]]
+    $cast  SetInput [ $immean GetImage ]
+    $cast  SetOutputScalarTypeToFloat
+    $cast  Update
+    
+    set cast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+    $cast2 SetInput [ $imvar  GetImage ]
+    $cast2 SetOutputScalarTypeToFloat
+    $cast2 Update
+    
+    set tcomp [  vtkpxComputeTmap [ pxvtable::vnewobj ]]
+    $tcomp SetInput [ $cast GetOutput ]
+    $tcomp SetInputStandardDeviation [ $cast2 GetOutput ]
+    $tcomp SetNumberOfInputs 1
+    $tcomp SetNumberOfSamples1 $numsubjects
+    #SetFilterCallbacks $tcomp  "Computing Composite TMap"
+    $tcomp Update
+    
+    set tscoreout [ [pxitclimage \#auto] GetThisPointer ]
+    $tscoreout ShallowCopyImage [ $tcomp GetOutput ]
+    $tscoreout CopyImageHeader [ $immean GetImageHeader ]
+    $tscoreout configure -filename "tscore_of_group"
+    [ $tscoreout GetImage ] SetOrigin 0.0 0.0 0.0
+    
+    $tcomp Delete 
+    $cast Delete
+    $cast2 Delete
+    return $tscoreout
+}
+
+itcl::body chellyGUI::MultipleROI { imagelist } {
+
+    
+    
+    if {$SpaceImage != -1} {
+	
+	foreach node [$RealTree children -all [$RealTree rootname]] {
+	    if {[$RealTree get $node type] == "ROIDef"} {
+		lappend ROIChoices $node
+	    }
+	}
+
+	#------------------------------------------------------------------------------------------
+	global ROIDefDialogEntryResult -1
+	
+	foreach c $ROIChoices {
+	    set roichoicearray([$RealTree get $c title]) $c
+	}
+	
+	iwidgets::selectiondialog .roiselbox -borderwidth 2 -height 200\
+	    -labelfont -Adobe-Helvetica-Bold-R-Normal--*-140-*-*-*-*-*-* \
+	    -title "Choose ROI Definition Image" \
+	    -textbackground ghostwhite -itemslabel "ROI Images In Tree:" \
+	    -selectionon 0
+        
+	eval .roiselbox insert items 0 [array names roichoicearray]
+	.roiselbox hide Apply
+	.roiselbox center
+	.roiselbox configure -modality application
+	.roiselbox buttonconfigure OK -command {set ROIDefDialogEntryResult [.roiselbox get]; .roiselbox deactivate }
+	.roiselbox buttonconfigure Cancel -command {set ROIDefDialogEntryResult -1; .roiselbox deactivate }
+	
+	update idletasks
+	.roiselbox activate
+	destroy .roiselbox
+	#------------------------------------------------------------------------------------------
+	
+	
+
+	#------------------------------------------------------------------------------------------
+	# See if user wants to apply a threshold
+	#------------------------------------------------------------------------------------------
+	set dothresh [tk_messageBox -type yesnocancel -default no \
+			  -message "Would you like to run a second round of ROI computations after application of a threshold?" -icon question]
+
+	if {$dothresh == "cancel"} { return -1 }
+	if {$dothresh == "yes"} {
+	    
+
+	    
+	    set threshDialog [iwidgets::promptdialog .[ pxvtable::vnewobj ] -modality application -title "Threshold" \
+				  -labeltext "Enter a value to threshold the images at"]
+	    
+	    $threshDialog hide Apply
+	    $threshDialog hide Cancel
+	    
+	    eval "$threshDialog buttonconfigure OK -command { $this ThresholdLevelDialogCallback }"
+	    focus [$threshDialog component prompt component entry]
+
+h
+	    
+	    $threshDialog center
+	    update idletasks
+	    $threshDialog activate
+	    
+	}	    
+	#------------------------------------------------------------------------------------------
+
+
+
+
+ 	set ROIImageID $roichoicearray($ROIDefDialogEntryResult)
+
+ 	#Send the ROI Image to Reference space
+ 	set ROIinCommonSpace [sendAllToCommonSpace $SpaceImage $ROIImageID] 
+
+ 	#Send all images to reference space
+ 	set commonSpaceImageList [sendAllToCommonSpace $SpaceImage $imagelist] 
+	
+
+ 	#Do the unthresholded calcs regardless of yes/no
+ 	foreach image $commonSpaceImageList {
+	    
+ 	    puts "Sending image $image - to ROI Stats"
+ 	    set UnThreshResult($image) [ComputeROIStatistics $image $ROIinCommonSpace]
+ 	    # Only do thresholding if dothresh == yes
+ 	    if {$dothresh == "yes"} {
+ 		    set threshlist [list $ImageThresholdForROICalcs 10000]
+ 		    set ThreshResult($image) [ComputeROIStatistics $image $ROIinCommonSpace $threshlist]
+ 	    }
+ 	}
+	
+	#-----Output----------------------------------------------------------------------------
+	#Now the data is two arrays - send it to user/file output
+
+	# Fix this to get proper suffix 
+	set filename [tk_getSaveFile -title "Saving ROI Output" -initialfile roioutput.txt  -filetypes { {"Text Files" {.txt}} } ]
+	if {[llength $filename]} {
+	
+	    puts "Saving $filename ...."
+	    set f [ open $filename w 0666]
+	    
+	    for {set a 0} {$a < [llength $commonSpaceImageList]} {incr a} {
+		
+		set image [lindex $commonSpaceImageList $a]
+		set imagename [file tail [ file root [[$RealTree get [lindex $imagelist $a] pxitclobj] cget -filename]]]
+			
+		puts $f     "\#Subject $imagename\n"
+		puts $f     "\#Unthresholded"
+		foreach line $UnThreshResult($image) {
+		    puts $f [string trim $line]
+		}
+		puts $f "\n"
+		if {$dothresh == "yes"} {
+		    puts $f \n
+		    puts $f "\#Thresholded"
+		    puts $f "\#Threshold Level:  $ImageThresholdForROICalcs"
+		    foreach line $ThreshResult($image) {
+			puts $f [string trim $line]
+		    }
+		}
+		
+	    }
+	    close $f
+	}
+		       
+	#---------------------------------------------------------------------------------------
+			   
+
+		
+    } else {tk_messageBox -type ok -title "No Space Image Set" -message "The Reference Space image has not been set" -icon info}
+  
+   
+};# End method MultipleROI
+
+itcl::body chellyGUI::ThresholdLevelDialogCallback { } {
+    
+    set ImageThresholdForROICalcs [$threshDialog get]
+    $threshDialog deactivate 
+
+}
+
+# if ComputerROIStatistics gets threshold: it should be -- set threshold [ list $lower $upper ]
+itcl::body chellyGUI::ComputeROIStatistics { functional_input roi_image_input { threshold none } } {
+
+    set ReturnData ""
+
+    set fname [ file tail [ $functional_input cget -filename ]]
+    set rname [ file tail [ $roi_image_input  cget -filename ]]
+	
+
+    set functional [ vtkImageData [ pxvtable::vnewobj ]]
+    $functional ShallowCopy [ $functional_input GetImage ] 
+
+    set roi_image [  ${roi_image_input} GetImage ] 
+
+    set dim1 [ $functional GetDimensions ]
+    set dim2 [ $roi_image  GetDimensions ]
+    if { [lindex $dim2 0 ] <2 || [ lindex $dim1 0 ] < 2 } { 
+	::pxtclutil::Warning "No Image in Memory\n Cannot Reslice!"
+	return  0
+    }
+
+    
+    if { $threshold != "none" } {
+
+	puts "Threshold for ROI: $threshold"
+
+	set thr [ vtkImageThreshold [ pxvtable::vnewobj ]]
+	$thr SetInput $functional
+	$thr ThresholdBetween [ lindex $threshold 0 ] [ lindex $threshold 1 ]
+	#------added stuff here-------
+	$thr SetOutputScalarTypeToShort
+	$thr SetOutValue   0
+	$thr ReplaceOutOn
+	#---end added stuff-----------
+	$thr Update
+	$functional ShallowCopy [ $thr GetOutput ]
+	$thr Delete
+    }
+
+    #    WatchOn
+    
+    set tr [ vtkIdentityTransform [ pxvtable::vnewobj ] ]
+
+    set thr [ vtkpxMergeFmriConventional [ pxvtable::vnewobj ]]
+    set arr [ vtkFloatArray [ pxvtable::vnewobj ]]
+    set nt  [  $thr ComputeROIStatistics $functional $roi_image $tr $arr]
+
+
+    if { $nt > 0 } {
+	# Show Console
+	pxtkconsole
+	# Print Statement
+	pxtkprint "ROI Statistics for $fname\n"
+	pxtkprint "ROIimage\tFrame\tLevel\tm\tstddev\tnVox\tVol\tnVox>0\tVolVox>0\n"
+	#add this same string to the return list
+	lappend ReturnData "\#ROI Statistics for $fname\n"
+	lappend ReturnData "\#ROIimage\tFrame\tLevel\tm\tstddev\tnVox\tVol\tnVox>0\tVolVox>0\n"
+	set total  0
+	set totalv 0 
+	
+	# runs through all frames
+	for { set i 0 } { $i < [ $arr GetNumberOfTuples ] } { incr i } {
+	   
+	    set a1 [ expr round([ $arr GetComponent $i 0 ])]
+	    set a2 [ expr round([ $arr GetComponent $i 1 ])]
+	    set a3 [ $arr GetComponent $i 3 ]
+	    set a4 [ $arr GetComponent $i 4 ]
+	    set n1 [ expr round([ $arr GetComponent $i 2 ])]
+	    set v1 [ expr round([ $arr GetComponent $i 6 ])]
+	    set n2 [ expr round([ $arr GetComponent $i 5 ])]
+	    set v2 [ expr round([ $arr GetComponent $i 7 ])]
+
+	    if { $n1 >  0 } {
+		#set output1 [ format "Frame %3d\t Region=%5.0f:\t m=%5.2f s=%5.2f\t\t nvox=%7d (%.1f mm^3) nvox>0=%7d (%.1f mm^3)\n" $a1 $a2 $a3 $a4 $n1 $v1 $n2 $v2 ]
+		set output1 "$fname\t$a1\t$a2\t$a3\t$a4\t$n1\t$v1\t$n2\t$v2\n"
+		pxtkprint $output1
+		lappend ReturnData $output1
+	    }
+
+	    if { $a2 > 0 } {
+		set total [ expr $total + $n2 ]
+		set totalv [ expr $totalv + $v2 ]
+	    }
+	}
+	set output2  [ format "\#Total volume for levels >0  nvox>0 = %d  (%.1f mm^3)\n\n" $total $totalv ]
+	pxtkprint $output2
+	lappend ReturnData $output2
+    }
+
+    $thr Delete
+    $arr Delete
+    $tr  Delete
+    $functional Delete
+    #    WatchOff 
+    
+    return $ReturnData
+
+}
+
+
+
+#------------------------------------------------------------------------------------------
+# End Search Dialog Methods 
+#------------------------------------------------------------------------------------------
+
+    
+
+
+
+#----------------------------------------------------------------------
+#These methods set the functions for the mouse bindings in the tree
+#----------------------------------------------------------------------
+::itcl::body chellyGUI::bindx1 { W x y } {
+ 
+    $this setSelection $W $x $y
+    $this setCurrent $W $x $y
+    displayFilename
+}
+
+::itcl::body chellyGUI::setSelection { W x y } {
+   
+    set lbl [Tree::labelat $W $x $y ]
+    if { $lbl == "" } { return }
+    Tree::setselection $W $lbl
+    if { $lbl == "/Data" } { return }
+    set nodeID [GetIDFromSelection]
+    if { [$RealTree get $nodeID type] == "Image" } {
+	set inputImg [$RealTree get $nodeID pxitclobj]
+	$imageutility SetInput $inputImg
+    }
+} 
+
+::itcl::body chellyGUI::displayFilename {} {   
+    
+    $descriptionbox configure -state normal
+    $descriptionbox delete 1.0 end
+    
+    ############################
+    #Freely defined Item Selection Binding Definitions Go Here
+    if {[Tree::getselectionpath $vistree] != "{}"} {
+	if {[Tree::getselection $vistree] != [$RealTree rootname]} {
+	    if {[IsNodeImage [GetIDFromSelection] -1 1] | [IsNodeSurface [GetIDFromSelection]]} {		
+		$statusLabel config -text "Filename: [$RealTree get [GetIDFromSelection] FileName]"
+		
+		#$statusLabel config -text "Type: [$RealTree get [GetIDFromSelection] type] \n Filename: [$RealTree get [GetIDFromSelection] FileName] \n Transformation TO Parent: [$RealTree get [GetIDFromSelection] TransToParFileName] \n Transformation FROM Parent[$RealTree get [GetIDFromSelection] TransFromParFileName]"
+		
+		#Debugging reporters:
+		set a1  "Image: [[$RealTree get [GetIDFromSelection] pxitclobj] GetDescription]"
+		set a1  "$a1\nFromPar:[[$RealTree get [GetIDFromSelection] pxitclTransFromParent] GetDescription]"
+		set a1  "$a1\nToPar:[[$RealTree get [GetIDFromSelection] pxitclTransToParent] GetDescription]"
+		
+	    } else {set a1 "[$RealTree get [GetIDFromSelection] title]"
+		$statusLabel config -text $a1
+	    }
+	} else {set a1 "Datatree: [$RealTree rootname]"
+	    $statusLabel config -text $a1
+	}
+	
+	$descriptionbox insert end $a1 
+    } else {
+	$descriptionbox insert end "Nothing Selected"
+	############################
+    }
+    
+    $descriptionbox configure -state disabled
+    
+}
+
+::itcl::body chellyGUI::bindxControlX { W K N } {
+    
+
+    set selectionPath [ Tree::getselectionpath $W ]
+    if { $selectionPath != "{}" } {
+	$this mdCopy 1
+    }
+}
+
+::itcl::body chellyGUI::bindxControlC { W K N } {
+
+    puts "here"
+    set selectionPath [ Tree::getselectionpath $W ]
+    if { $selectionPath != "{}" } {
+	$this mdCopy 0
+    }
+}
+
+::itcl::body chellyGUI::bindxcontrol1 { W x y } { 
+    #Control Clicking on the tree adds multiple selections
+    if { $dragAndDropEnabled } { return -1 }
+    set lbl [Tree::labelat $W $x $y]
+    Tree::addselection $W $lbl
+    displayFilename    
+}
+
+
+
+::itcl::body chellyGUI::bindxmotion1 { W x y } {
+    
+    if { $dragAndDropEnabled == 0 } { return -1 }
+
+    set widget [ winfo containing [winfo pointerx $W] [winfo pointery $W] ]
+#    puts "$widget"
+    if { $widget == $IC } { 
+	displayMarkerOnImageTab $W $x $y
+    } elseif { $widget == $vistree } {
+	set selectionPath [ Tree::getselectionpath $W ]
+	set currentPath   [ Tree::getCurrentPath $W ]
+	$this setCurrent $W $x $y
+	$this displayFilename
+	if { $currentPath != "{}" && $selectionPath != "{}" } {
+	    $W configure -cursor plus
+	} else { 
+	    $W configure -cursor $theNoCursor
+	}
+    } else {
+	$W configure -cursor $theNoCursor
+   }
+}
+
+::itcl::body chellyGUI::displayMarkerOnImageTab { W x y } {
+
+    set width [ winfo width $vistree ]
+    catch {$IC delete box}
+
+    if { $x > [expr 63 + $width] && $x < [expr 203 + $width] && $y > 335 && $y < 448 } {
+
+	$IC create rect 23 265 163 375 -tag box
+	$W configure -cursor plus
+
+    } elseif { $x > [expr 203 + $width] && $x < [expr 343 + $width] && $y > 117 && $y < 230 } {
+
+	$IC create rect  163 47 303 157 -tag box
+	$W configure -cursor plus
+
+    } elseif { $x > [expr 353 + $width] && $x < [expr 493 + $width] && $y > 335 && $y < 448 } {
+
+	$IC create rect 313 265 453 375 -tag box
+	$W configure -cursor plus
+
+    } else { $W configure -cursor $theNoCursor }
+}
+
+::itcl::body chellyGUI::setCurrent { W x y } {
+ 
+    set lbl [Tree::labelat $W $x $y]
+    Tree::setCurrent $W $lbl
+}
+
+::itcl::body chellyGUI::bindxrelease1 { W x y mode } {
+    
+    if { $dragAndDropEnabled == 0 } { return -1 }
+  
+    set widget [ winfo containing [winfo pointerx $W] [winfo pointery $W] ]
+    
+    $vistree configure -cursor ""
+    . configure -cursor ""
+
+    if { $widget == $IC } { 
+	$this releaseOnImagesTab $x $y 
+	return -1
+    }
+
+    if { $widget == $vistree && $mode } { 
+	$this releaseOnTreeCut $W $x $y  
+	return -1
+    }
+    
+    if { $widget == $vistree } { 
+	$this releaseOnTreeCopy $W $x $y  
+	return -1
+    }
+}
+
+::itcl::body chellyGUI::releaseOnTreeCut { W x y } {
+    
+    set selectionPath [ Tree::getselectionpath $W ]
+    set currentPath   [ Tree::getCurrentPath $W ]
+   
+    if { $currentPath == "{}" } { return -2 }
+	
+    if { [ $this isCurrentAChildOfSelection $currentPath $selectionPath $W ] } { 
+	tk_messageBox -type ok -title "Warning" -message "Cannot cut a node to its descendant." -icon question
+	Tree::eraseCurrentBox $W 
+	return -1
+    }
+
+    if { [ $this isCurrentTheParentOfSelection $currentPath $selectionPath $W ] } {
+	tk_messageBox -type ok -title "Warning" -message "Unnecessary cut to parent node." -icon question
+	Tree::eraseCurrentBox $W 	
+	return -1
+    }
+
+    if { $selectionPath != $currentPath } {
+	
+	set ok [ tk_messageBox -type okcancel -title "Warning" -message "Cutting from $selectionPath to $currentPath" -icon question ]
+	if { $ok == "ok" } {
+	    set lbl [Tree::labelat $W $x $y ]
+	    $this mdCopy 1 
+	    Tree::setselection $W $lbl
+	    $this displayFilename
+	    $this mdPaste 
+	}
+    }
+    Tree::eraseCurrentBox $W 
+}
+
+::itcl::body chellyGUI::releaseOnTreeCopy { W x y } {
+
+    set selectionPath [ Tree::getselectionpath $W ]
+    set currentPath   [ Tree::getCurrentPath $W ]
+    
+    if { $selectionPath != $currentPath && $currentPath != "{}" && $selectionPath != "{}" } {
+	
+	set ok [ tk_messageBox -type okcancel -title "Warning" -message "Copying from $selectionPath to $currentPath" -icon question ]
+	if { $ok == "ok" } {
+	    set lbl [Tree::labelat $W $x $y ]
+	    $this mdCopy 0 
+	    Tree::setselection $W $lbl
+	    $this displayFilename
+	    $this mdPaste 
+	}
+    }
+    Tree::eraseCurrentBox $W 
+}
+
+::itcl::body chellyGUI::releaseOnImagesTab { x y } {
+
+    set width [ winfo width $vistree ]
+    catch {$IC delete box}
+
+    if { $x > [expr 63 + $width] && $x < [expr 203 + $width] && $y > 335 && $y < 448 } {
+	$this setSelectionAnatomical $RealTree
+    }
+
+    if { $x > [expr 203 + $width] && $x < [expr 343 + $width] && $y > 117 && $y < 220 } {
+	$this setSelectionSpace $RealTree
+    }
+    
+    if { $x > [expr 353 + $width] && $x < [expr 493 + $width] && $y > 335 && $y < 448 } {
+	$this setSelectionFunctional $RealTree
+    }
+}
+
+::itcl::body chellyGUI::isCurrentAChildOfSelection { currentPath selectionPath W } {
+ 
+    set selectionPath "[ lindex $selectionPath 0 ]/"
+    return [ regexp ^$selectionPath [ lindex $currentPath 0 ] ]
+}
+
+::itcl::body chellyGUI::isCurrentTheParentOfSelection { currentPath selectionPath W } {
+    
+    set tmp "[ lindex $currentPath 0 ]/[ Tree::getselection $W ]"
+    return [ regexp ^$tmp [ lindex $selectionPath 0 ] ]
+}
+
+::itcl::body chellyGUI::bindxdouble1 { W x y } {
+    
+    $this setSelection $W $x $y
+    if { [ Tree::getselectionpath $W ] != "{}" } { $this NodeInfoDialog }
+}
+
+::itcl::body chellyGUI::bindx3 { W x y } {
+    #This is a right-click - it should open a flyout menu for the item under the mouse
+    #First, change the selection to the item right-clicked on
+  
+    $this setSelection $W $x $y
+    $this displayFilename
+    #Now retrieve the ID in the real tree that corresponds to the selection
+    set Selection [GetIDFromSelection]
+    if {$Selection == ""} {return -1}
+    #If the user has clicked on the root, post the rootpopup menu
+    #The the selected ID corresponds to a node with key "type" set to "Patient", show patient menu
+    #if nothing else, show the regular image node menu
+
+    if {$Selection == [$RealTree rootname]} {
+	tk_popup $rootpopup [winfo pointerx $vistree] [winfo pointery $vistree]
+    } else {
+	if { [$RealTree get $Selection type] == "Patient" } {
+	    tk_popup $patientpopup [winfo pointerx $vistree] [winfo pointery $vistree]
+	} else {
+	    if { [lindex [$RealTree get $Selection type] 0] == "Surface" } { 
+		if { [lindex [$RealTree get $Selection type] 1] == "Electrode" } { 
+		    tk_popup $electrodepopup [winfo pointerx $vistree] [winfo pointery $vistree]
+		} else {
+		    tk_popup $surfacepopup [winfo pointerx $vistree] [winfo pointery $vistree]
+		}
+	    } else {
+		tk_popup $popup [winfo pointerx $vistree] [winfo pointery $vistree]
+	    }; #end else 3
+	}; #end else 2
+	
+    }; #end else 1
+    
+    
+    
+};# End method
+
+::itcl::body chellyGUI::bindRightPaneTest { W x y text } {
+    
+    puts "x:$x y:$y"
+}
+
+::itcl::body chellyGUI::bindxRightPane { W x y menu} {
+
+    tk_popup $menu [winfo pointerx $IC] [winfo pointery $IC] 
+};# End method
+
+
+
+
+#-------------------------------------------------------------------------
+#These are methods bound to the buttons in the middle pane as well as menu entries in node and popup
+#-------------------------------------------------------------------------
+
+::itcl::body chellyGUI::NodeInfoDialog { } {
+
+   
+    set node [ GetIDFromSelection ]
+    if {$node != "" && $node != [$RealTree rootname] } {
+	
+	update idletasks
+	
+	if {$NodeInfoDialogName == -1 | ![winfo exists $NodeInfoDialogName]} {
+	    
+	    set nodeDialogBGColor "Light Cyan"
+	    set NodeInfoDialogName .[ pxvtable::vnewobj ]
+	    toplevel $NodeInfoDialogName -bg $nodeDialogBGColor
+	    wm title $NodeInfoDialogName "Info for [$RealTree get $node title]"
+	    wm geometry $NodeInfoDialogName +300+200
+	    
+	    set icon [ $RealTree get $node icon  ]
+	    set infolabelframe [frame $NodeInfoDialogName.labelfr -bg $nodeDialogBGColor]
+	    set infolabeltext [label $infolabelframe.labeltxt -text "[$RealTree get $node title]" -bg $nodeDialogBGColor]
+	    $infolabeltext config -font -*-times-bold-r-normal-*-18-*-*-*-*-*-iso8859-1
+	    set infolabelpicture [label $infolabelframe.labelpict -image $icon -bg $nodeDialogBGColor]
+	    pack $infolabelpicture -side left -padx [list 4 0]
+	    pack $infolabeltext -side left -padx [list 0 4]
+	    
+	    set NodeInfoTopFrame [labelframe $NodeInfoDialogName.topframe -bg $nodeDialogBGColor -labelwidget $infolabelframe]
+	    pack $NodeInfoTopFrame -side top -ipadx 3 -ipady 7 -padx 10 -pady [list 2 10] -expand true -fill both
+
+	    set entrylist ""
+	    #------------------------------------------------------------
+	    # Here are all the attributes for the node
+	    set fields [list type group FileName TransFromParFileName TransToParFileName]
+	    set nodeinfoitemlist $fields
+	    set titles [list Type Group Filename  {Transformation from Parent} {Transformation to Parent}]
+	    set functions [list -1 -1 setSelectedFileName setTransFromParent setTransToParent]
+	    foreach item $fields {
+		if {[llength $item] > 0} {
+		    set itemframe [frame $NodeInfoTopFrame.[pxvtable::vnewobj] -background $nodeDialogBGColor]
+		    set name [lindex $titles [lsearch -exact $fields $item]]
+		    set val [$RealTree get $node $item]
+		    set entry [ iwidgets::entryfield $itemframe.\#auto -background "$nodeDialogBGColor" -width 75]
+		    pack $entry -fill both -padx {10 0} -side left -expand true
+		    $entry configure -labeltext $name
+		    $entry insert 0 $val
+		    lappend entrylist $entry
+		    if {[lindex $functions [lsearch -exact $fields $item]] != -1} {
+			set button [eval "button $itemframe.[pxvtable::vnewobj] -text ... -command { $this updateNodeDialogField $entry [lindex $functions [lsearch -exact $fields $item]] $node $item; } -background white -width 1"]
+			pack $button -side left -padx {0 10}
+
+			set func [lindex $functions [lsearch -exact $fields $item]]
+
+			# XP -- Potential Addition
+			#
+			if { $func == "setTransFromParent" || $func == "setTransToParent" } {
+			    if { $func == "setTransFromParent" } {
+				set newfunct "clearTransFromParent"
+			    } else {
+				set newfunct "clearTransToParent"
+			    }
+			    
+			    set but "button $itemframe.[pxvtable::vnewobj] -text \"Clear\" -command { $this updateNodeDialogField $entry $newfunct $node $item; } -background white -width 2"
+			    set button2 [ eval $but ]
+			    pack forget $button
+			    pack $button -side left -padx {0 2}		    
+			    pack $button2 -side left -padx {0 10}
+			    
+			}
+					
+		    } else {
+			pack $entry -fill both -padx {10 42} -side left -expand true
+		    }
+		    
+		    
+		    
+		    pack $itemframe -side top -anchor w -expand true -fill x
+		    
+		}
+	    }
+	    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+
+	    #This frame holds the bottom stuff: notes, and properties for subjects, if they are set
+	    #---------------------------------------------------------------------------------------
+	    set infobottomframe [frame $NodeInfoTopFrame.bottomsection -background "$nodeDialogBGColor"]; pack $infobottomframe -side top -expand 1 -fill both
+
+
+	    #The notes box
+	    #------------------------------------------------------------
+	    set notelabel [label $infobottomframe.notelabel -text "Notes" -background "$nodeDialogBGColor"] ; pack $notelabel -side left
+	    set notebox [ iwidgets::scrolledtext $infobottomframe.\#auto -wrap none \
+			      -vscrollmode static -hscrollmode static \
+			      -width 5i -height 2i ]
+	    pack $notebox -fill x -padx 10 -pady 10 -expand true -fill both -side left
+	    $notebox insert 1.0 [$RealTree get $node notes]
+	 	    
+	    eval "wm protocol $NodeInfoDialogName WM_DELETE_WINDOW { wm withdraw $NodeInfoDialogName ; $this updateNodeNotes $RealTree $node \[$notebox get 1.0 end\] $NodeInfoDialogName}"
+
+	    #The extras property fields for patient nodes
+	    if {[$RealTree get $node type] == "Patient"} {
+		set propertyframe [frame $infobottomframe.right -background $nodeDialogBGColor -width 40]
+		pack $propertyframe -side left -pady 5
+		
+		array set propArray [$RealTree get $node Properties] 
+
+		set entrylist ""
+		for {set p 0} {$p < [llength $PatientProperties]} {incr p}  {
+		    
+		    set itemframe [frame $propertyframe.[pxvtable::vnewobj] -background $nodeDialogBGColor]
+
+		    set name [lindex $PatientProperties $p]
+	
+		    if {[lsearch -exact [array names propArray] $name] != -1} {
+			set val $propArray($name)
+		    } else {set val "-"}
+
+		    set entry [ iwidgets::entryfield $itemframe.\#auto -background "$nodeDialogBGColor" -width 15]
+		    pack $itemframe -side top
+		    pack $entry -fill both -padx {0 0} -side left
+		    $entry configure -labeltext "$name"
+		    $entry insert 0 $val
+		    lappend entrylist $entry
+		    set button [eval "button $itemframe.[pxvtable::vnewobj] -text > -command { $this setPatientProperty \"$name\" $entry }" ]
+		    pack $button -side left -padx {0 10}
+		}
+		eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+	    }
+
+	} else {
+	    
+	    #--------------------------------------------------------------------------------
+	    #--------------------------------------------------------------------------------
+	    #--------------------------------------------------------------------------------
+	    #--------------------------------------------------------------------------------
+	    #--------------------------------------------------------------------------------
+
+	    #If the dialog already exists change all the fields and then show it
+	    
+	    wm title $NodeInfoDialogName "Info for [$RealTree get $node title]"
+	    set icon [ $RealTree get $node icon  ]
+	    set infolabeltext $NodeInfoDialogName.labelfr.labeltxt  
+	    $infolabeltext config -text "[$RealTree get $node title]"
+	    set infolabelpicture $NodeInfoDialogName.labelfr.labelpict
+	    $infolabelpicture config -image $icon
+	    
+	    destroy $NodeInfoDialogName.topframe
+	    
+	    set NodeInfoTopFrame [labelframe $NodeInfoDialogName.topframe -bg $nodeDialogBGColor -labelwidget $NodeInfoDialogName.labelfr]
+	    pack $NodeInfoTopFrame -side top -ipadx 3 -ipady 7 -padx 10 -pady [list 2 10] -expand true -fill both
+	    
+	    set entrylist ""
+	    #------------------------------------------------------------
+	    # Here are all the attributes for the node
+	    set fields [list type group FileName TransFromParFileName TransToParFileName]
+	    set nodeinfoitemlist $fields
+	    set titles [list Type Group Filename  {Transformation from Parent} {Transformation to Parent}]
+	    set functions [list -1 -1 setSelectedFileName setTransFromParent setTransToParent]
+	    foreach item $fields {
+		if {[llength $item] > 0} {
+		    set itemframe [frame $NodeInfoTopFrame.[pxvtable::vnewobj] -background $nodeDialogBGColor]
+		    set name [lindex $titles [lsearch -exact $fields $item]]
+		    set val [$RealTree get $node $item]
+		    set entry [ iwidgets::entryfield $itemframe.\#auto -background "$nodeDialogBGColor" -width 75]
+		    pack $entry -fill both -padx {10 0} -side left -expand true
+		    $entry configure -labeltext $name
+		    $entry insert 0 $val
+		    lappend entrylist $entry
+		    if {[lindex $functions [lsearch -exact $fields $item]] != -1} {
+			set button [eval "button $itemframe.[pxvtable::vnewobj] -text ... -command { $this updateNodeDialogField $entry [lindex $functions [lsearch -exact $fields $item]] $node $item; } -background white -width 1"]
+			pack $button -side left -padx {0 10}
+		    } else {
+			pack $entry -fill both -padx {10 42} -side left -expand true
+		    }
+		    
+		    
+		    
+		    pack $itemframe -side top -anchor w -expand true -fill x
+		    
+		}
+	    }
+	    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+	    
+	    #This frame holds the bottom stuff: notes, and properties for subjects, if they are set
+	    #---------------------------------------------------------------------------------------
+	    set infobottomframe [frame $NodeInfoTopFrame.bottomsection -background "$nodeDialogBGColor"]; pack $infobottomframe -side top -expand 1 -fill both
+	    
+	    
+	    #The notes box
+	    #------------------------------------------------------------
+	    set notelabel [label $infobottomframe.notelabel -text "Notes" -background "$nodeDialogBGColor"] ; pack $notelabel -side left
+	    set notebox [ iwidgets::scrolledtext $infobottomframe.\#auto -wrap none \
+			      -vscrollmode static -hscrollmode static \
+			      -width 5i -height 2i ]
+	    pack $notebox -fill x -padx 10 -pady 10 -expand true -fill both -side left
+	    $notebox insert 1.0 [$RealTree get $node notes]
+	    
+	    eval "wm protocol $NodeInfoDialogName WM_DELETE_WINDOW { wm withdraw $NodeInfoDialogName ; $this updateNodeNotes $RealTree $node \[$notebox get 1.0 end\] $NodeInfoDialogName}"
+	    
+	    #The extras property fields for patient nodes
+	    if {[$RealTree get $node type] == "Patient"} {
+		set propertyframe [frame $infobottomframe.right -background $nodeDialogBGColor -width 40]
+		pack $propertyframe -side left -pady 5
+		
+		array set propArray [$RealTree get $node Properties] 
+		
+		set entrylist ""
+		for {set p 0} {$p < [llength $PatientProperties]} {incr p}  {
+		    
+		    set itemframe [frame $propertyframe.[pxvtable::vnewobj] -background $nodeDialogBGColor]
+		    
+		    set name [lindex $PatientProperties $p]
+		    
+		    if {[lsearch -exact [array names propArray] $name] != -1} {
+			set val $propArray($name)
+		    } else {set val "-"}
+		    
+		    set entry [ iwidgets::entryfield $itemframe.\#auto -background "$nodeDialogBGColor" -width 15]
+		    pack $itemframe -side top
+		    pack $entry -fill both -padx {0 0} -side left
+		    $entry configure -labeltext "$name"
+		    $entry insert 0 $val
+		    lappend entrylist $entry
+		    set button [eval "button $itemframe.[pxvtable::vnewobj] -text > -command { $this setPatientProperty \"$name\" $entry }" ]
+		    pack $button -side left -padx {0 10}
+		}
+		eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+	    }
+	    
+	    switch -- [wm state $NodeInfoDialogName] {
+		normal {
+		    raise $NodeInfoDialogName
+		}
+		withdrawn -
+		iconic {
+		    wm deiconify $NodeInfoDialogName
+		}
+	    }
+	    return 0
+
+	    #--------------------------------------------------------------------------------
+	    #--------------------------------------------------------------------------------
+	    #--------------------------------------------------------------------------------
+	    #--------------------------------------------------------------------------------
+	    
+	}; #End else if dialog already exists
+
+	
+	
+    };# end "if node != 0"
+}
+
+::itcl::body chellyGUI::updateNodeDialogField { entry function node item } {
+    
+    $function
+
+    $entry clear
+    $entry insert 0 [$RealTree get $node $item]
+    set TreeChanged 1
+    
+    updateAllNodeDialogFields $entrylist $node $nodeinfoitemlist
+
+
+}
+
+::itcl::body chellyGUI::updateAllNodeDialogFields {entries node items} {
+
+    for {set en 0} {$en < [llength $entries]} {incr en} {
+
+	[lindex $entries $en] clear
+	[lindex $entries $en] insert 0 [$RealTree get $node [lindex $items $en]]
+    }
+
+}
+
+::itcl::body chellyGUI::updateNodeNotes { realtreename node text dialogname } {
+    
+    $realtreename set $node notes [string trimright $text \n]
+    destroy $dialogname
+    set TreeChanged 1
+    
+}
+
+::itcl::body chellyGUI::setPatientProperty { property entryfield } {
+
+    #Get input from user
+    set thisinput6 [Single_Entry_Dialog "New Value" "Enter new value for $property"]
+    if {$thisinput6 != -1 } {
+
+	set thisnode [GetIDFromSelection]
+	array set tempProps [$RealTree get $thisnode Properties]
+    
+ 	set tempProps($property) $thisinput6
+
+	$RealTree set $thisnode Properties [array get tempProps]
+	
+	#update the nodeinfo box
+	$entryfield clear
+	$entryfield insert 0 $thisinput6
+
+	set TreeChanged 1
+
+    }
+
+
+}; #End setPatientProperty method
+
+::itcl::body chellyGUI::setSelectionSpace { realtreename } {
+
+    if { $SpaceLocked == 0 | $SpaceImage == -1} {
+	#get the currently selected node
+	set node [GetIDFromSelection]
+	puts "Space Node: $node"
+	if {$node != ""} {
+	    
+	    EnsureFileLoaded $node
+	    set SpaceImage $node
+
+	    updateRightCanvasDisplay
+	    
+	    if { $SurgeryMode == 1 } { set SpaceLocked 1 } 
+
+
+	} else { error "Please select an item to set as the Space" }
+    } else { error "The Space Image has been Locked (see Options Menu)" }
+}
+
+
+::itcl::body chellyGUI::setSelectionAnatomical { realtreename } {
+    
+    #get the currently selected node
+    set node [GetIDFromSelection]
+    puts "Anatomical Node: $node"
+    if {$node != ""} {
+	
+	EnsureFileLoaded $node
+	set AnatomicalImage $node
+
+	updateRightCanvasDisplay
+	
+    } else { 
+	error "Please select an item to set as the Anatomical Image" 
+    }
+    
+}
+
+
+
+::itcl::body chellyGUI::setSelectionFunctional { realtreename } {
+    
+    #get the currently selected node
+    set node [GetIDFromSelection]
+    puts "Functional Node: $node"
+    if {$node != ""} {
+	
+	EnsureFileLoaded $node
+	set FunctionalImage $node
+
+	updateRightCanvasDisplay
+	
+	
+    } else { 
+	error "Please select an item to set as the Functional Image"
+    }
+    
+}
+
+::itcl::body chellyGUI::updateOverlayCanvas { } {
+    
+    #--------------------------------------------------------------------------------
+    #Update the display in the overlay tab canvas
+    #
+    #Show image titles that have been resliced
+
+    catch {$OCanv delete presPIC}
+    #Check to see if reslicer outputs have been sent to surgery gadget
+    if {[$surgerygadget cget -overlayinputbase] != -1 && [$surgerygadget cget -overlayinputfunc] != -1} {
+	set OC_reslice_presentPIC [$OCanv create image $OCdispX $OCdispY -image multicolorbrain -anchor nw -tag presPIC]
+    } 
+    
+    #Space Label
+    $OCanv delete ocSPACE
+    if {$SpaceImage != -1} {
+	set OC_SPACE  [$OCanv create text [expr $OCdispX+220] [expr $OCdispY+60] -text "SPACE: [$RealTree get $SpaceImage title]" -fill "darkgreen" -font {helvetica 11 bold} -tag ocSPACE -width 145]
+    } else {
+	set OC_SPACE  [$OCanv create text [expr $OCdispX+205] [expr $OCdispY+60] -text "Space" \
+			   -fill grey61 -font {helvetica 15 bold} -tag ocSPACE]
+    }
+    
+    #Func Label (Change if FunctionalImage has been set)
+    $OCanv delete ocFUNC
+    if {$FunctionalImage != -1} {
+	set OC_FUNC  [$OCanv create text [expr $OCdispX+315] [expr $OCdispY+20] -text "FUNCTIONAL: [$RealTree get $FunctionalImage title]" -fill "darkgreen" -font {helvetica 11 bold} -tag ocFUNC -width 150 -justify left -anchor w]
+    } else { 
+	set OC_FUNC  [$OCanv create text [expr $OCdispX+375] [expr $OCdispY+20] -text "Functional" \
+			  -fill grey61 -font {helvetica 15 bold} -tag ocFUNC]
+    }
+    
+    #Anat Label (Change if AnatomicalImage has been set)
+    $OCanv delete ocANAT
+    if {$AnatomicalImage != -1} {
+	set OC_ANAT  [$OCanv create text [expr $OCdispX+315] [expr $OCdispY+110] -text "ANATOMICAL: [$RealTree get $AnatomicalImage title]" -fill "darkgreen" -font {helvetica 11 bold} -tag ocANAT -width 150 -justify left -anchor w]
+    } else { 
+	set OC_ANAT  [$OCanv create text [expr $OCdispX+375] [expr $OCdispY+110] -text "Anatomical" \
+			  -fill grey61 -font {helvetica 15 bold} -tag ocANAT]
+    }
+
+    #--------------------------------------------------------------------------------
+        
+    
+}
+
+::itcl::body chellyGUI::Reslice { } {
+    
+    
+#     puts "SpaceImage: $SpaceImage"
+#     puts "AnatomicalImage: $AnatomicalImage"
+#     puts "FunctionalImage: $FunctionalImage"
+    
+    if {$SpaceImage != -1} {
+
+	set FuncOnly [expr ($AnatomicalImage == -1) && ($FunctionalImage != -1)]
+	set AnatOnly [expr ($FunctionalImage == -1) && ($AnatomicalImage != -1)]
+	set SpaceEqAnat [expr $SpaceImage == $AnatomicalImage]
+	set SpaceEqFunc [expr $SpaceImage == $FunctionalImage]
+
+	set ResliceFuncOnly [expr ($FunctionalImage != -1) && ($FuncOnly | $SpaceEqAnat)]
+	set ResliceAnatOnly [expr ($AnatomicalImage != -1) && ($AnatOnly | $SpaceEqFunc)]
+	
+	if {$ResliceFuncOnly} {
+
+	    #This runs if: 
+	    # SpaceImage == Anatomical Image
+	    # or
+	    # Anatomical has not been set, but Functional Has
+	    
+	    set SpaceImgObj [$RealTree get $SpaceImage pxitclobj]
+	    set FunctionalImgObj [$RealTree get $FunctionalImage pxitclobj] 
+	    
+	    findTransforms $RealTree $SpaceImage $FunctionalImage
+	    set TransList $TransformsCache($myname,$SpaceImage:$FunctionalImage)
+	    
+	    set resliced_image [ ResliceImage $SpaceImgObj $FunctionalImgObj $TransList ]
+#	    puts "Resliced $FunctionalImage into $SpaceImage with $TransList"
+	    
+	    $surgerygadget SetOverlayToolInputs  $SpaceImgObj  $resliced_image
+	    catch { itcl::delete object $resliced_image  }
+	    
+	    updateOverlayCanvas	
+
+	    return
+	    
+	} else {
+	    if {$ResliceAnatOnly} {
+
+		set SpaceImgObj [$RealTree get $SpaceImage pxitclobj]
+		set AnatomicalImgObj [$RealTree get $AnatomicalImage pxitclobj] 
+		
+		findTransforms $RealTree $SpaceImage $AnatomicalImage
+		set TransList $TransformsCache($myname,$SpaceImage:$AnatomicalImage)
+		
+		set resliced_image [ ResliceImage $SpaceImgObj $AnatomicalImgObj $TransList ]
+		#		puts "Resliced $AnatomicalImage into $SpaceImage with $TransList"
+		$surgerygadget SetOverlayToolInputs $SpaceImgObj $resliced_image
+		catch { itcl::delete object $resliced_image  }
+
+		updateOverlayCanvas
+
+	    } else {
+	
+		set SpaceImgObj [$RealTree get $SpaceImage pxitclobj]
+		set AnatomicalImgObj [$RealTree get $AnatomicalImage pxitclobj] 
+		set FunctionalImgObj [$RealTree get $FunctionalImage pxitclobj] 
+
+		findTransforms $RealTree $SpaceImage $AnatomicalImage
+		set TransListA $TransformsCache($myname,$SpaceImage:$AnatomicalImage)
+		set resliced_imageA [ ResliceImage $SpaceImgObj $AnatomicalImgObj $TransListA ]
+		puts "Resliced $AnatomicalImage into $SpaceImage with $TransListA"
+		
+		findTransforms $RealTree $SpaceImage $FunctionalImage
+		set TransListF $TransformsCache($myname,$SpaceImage:$FunctionalImage)
+		set resliced_imageF [ ResliceImage $SpaceImgObj $FunctionalImgObj $TransListF ]
+		puts "Resliced $FunctionalImage into $SpaceImage with $TransListF"
+		
+		$surgerygadget SetOverlayToolInputs $resliced_imageA $resliced_imageF
+		
+		catch { itcl::delete object $resliced_imageA; itcl::delete object $resliced_imageF } 
+
+		updateOverlayCanvas
+		
+	    }
+	}
+    } else {error "The Space Image has not been set"}	   
+    
+    
+}
+
+
+::itcl::body chellyGUI::ShowTextBox { parent } {
+    
+    
+    set base $parent
+    
+    
+    
+    frame $base.toptextboxframe    -width 450 -height 400
+    frame $base.bottomtextboxframe -width 450 -height 70
+    
+    set descriptionbox $base.toptextboxframe.descriptionbox 
+    set ybar    $base.toptextboxframe.ybar 
+    set xbar    $base.xbar 
+    eval "scrollbar $ybar  -command { $descriptionbox yview } -orient vertical"
+    eval "scrollbar $xbar  -command { $descriptionbox xview } -orient horizontal"
+    eval "text $descriptionbox  -width 150 -height 30  -wrap word -relief ridge -yscrollcommand { $ybar set} -xscrollcommand {$xbar set} -bg black -fg white"
+    
+    pack $base.bottomtextboxframe -side bottom -expand f -fill x -padx 5 -pady 2
+    pack $xbar -side bottom -expand f -fill x 
+    pack $base.toptextboxframe -side top -expand true -fill both -padx 2 -pady 5
+    pack $ybar -side right -expand false -fill y
+    pack $descriptionbox -side left -expand true -fill both
+    $descriptionbox configure -state disabled
+    
+    
+}
+
+::itcl::body chellyGUI::showGrabButtonDialog { } {
+    
+    if {$showGrabButtonDialogName == -1 | ![winfo exists $showGrabButtonDialogName]} {
+	
+	set showGrabButtonDialogName .[ pxvtable::vnewobj ]
+	toplevel $showGrabButtonDialogName
+	wm title $showGrabButtonDialogName "Grab"
+	
+	#Create the control frame at the bottom of the left pane
+	set leftwrapperframe [frame $showGrabButtonDialogName.leftwrapper -bg "light blue"]
+	pack $leftwrapperframe -side bottom -fill x -padx 4 -pady 4
+	set leftcontrolsframe [labelframe $leftwrapperframe.controls -bg "light blue" -text "Grab Item From Viewer" -labelanchor n]
+	pack $leftcontrolsframe -side bottom -fill x -padx 4 -pady 2
+	
+	set refgrabsframe [labelframe $leftcontrolsframe.refgrabbuttons -bg "light blue" -text "Reference" -labelanchor s]
+	set transgrabsframe [labelframe $leftcontrolsframe.transgrabbuttons -bg "light blue" -text "Transform" -labelanchor s]
+	
+	set grimagebut [eval "button $refgrabsframe.getimg -text \"Image\" -command { $this PutViewerObjectInTree 1 Image}"]
+	set grsurfacebut [eval "button $refgrabsframe.getsurf -text \"Surface\" -command { $this PutViewerObjectInTree 1 Surface }"]
+	set grlandbut [eval "button $refgrabsframe.getland -text \"Landmark\" -command { $this PutViewerObjectInTree 1 Landmark }"]
+	set grelecbut [eval "button $refgrabsframe.getelec -text \"Electrode\" -command { $this PutViewerObjectInTree 1 Electrode }"]
+	set gtimagebut [eval "button $transgrabsframe.getimg -text \"Image\" -command { $this PutViewerObjectInTree 2 Image}"]
+	set gtsurfacebut [eval "button $transgrabsframe.getsurf -text \"Surface\" -command { $this PutViewerObjectInTree 2 Surface }"]
+	set gtlandbut [eval "button $transgrabsframe.getland -text \"Landmark\" -command { $this PutViewerObjectInTree 2 Landmark }"]
+	set gtelecbut [eval "button $transgrabsframe.getelec -text \"Electrode\" -command { $this PutViewerObjectInTree 2 Electrode }"]
+	
+	pack $refgrabsframe -side left -fill x -expand 1 -padx 2 -pady 3
+	pack $transgrabsframe -side left -fill x -expand 1 -padx 2 -pady 3 
+	pack $grimagebut -side top -fill both -expand 1 -padx 5 -pady [list 3 0]
+	pack $grsurfacebut $grlandbut $grelecbut -side top -fill both -expand 1 -padx 5
+	pack $gtimagebut  -side top -fill both -expand 1 -padx 5 -pady [list 3 0]
+	pack $gtsurfacebut $gtlandbut $gtelecbut -side top -fill both -expand 1 -padx 5
+	
+	return 1
+	
+    } else {
+	
+	switch -- [wm state $showGrabButtonDialogName] {
+	    normal {
+		raise $showGrabButtonDialogName
+	    }
+	    withdrawn -
+	    iconic {
+		wm deiconify $showGrabButtonDialogName
+	    }
+	}
+	return 0
+	
+    }
+    
+};# End showGrabButtonDialog method
+
+
+::itcl::body chellyGUI::ShowMidpaneTools { parent } {
+    
+    
+    image create photo smallviewericon -data {
+	R0lGODlhHgAaAOf/AAABAAIABQACAAYAAAcAAAABDgEEAAIFAQUHAwYGEgcJ\
+	    BQgLBw8JBwsNCgwPCxcLCxIUERUSHw8WHBUWHRYYFRYXHhcYFhkbGBocGRwd\
+	    Gx0fHCUcHSIkIiosKSU0JTAxLzg5Nzk6OEI3ODs9Ojw+O0E8Oz0/PD9APj9C\
+	    T0BJOkRGQ0VHRElKSE5KSU1PTFtRUVVWVFtaUltdWlxeW1NiZ15gXWBiX2Fj\
+	    YF1oaWFlcmhoYCh8r2hpZ2Vodmxua29uZm1vbG9xbj+CnnFzcHtwcHV3dHZ4\
+	    dT6Ou3SBdXt9ekCQvX9+dkGRv31/fEiPt02TvIKEgXuHh0+VvY1/jISGg1CW\
+	    voeGfleVuFGXv1OYwYqJgYSIl1SZwoiKh1Wbw4yMg4eLmouNil2bvo6NhYyO\
+	    i4+OhpCPh4+RjpSTi5SWk5iXj5ial5aZqJybk5Wjl52fnJakmKebnJufrpim\
+	    mqWgn5upnaOloqijop2rn6WnpKaopbCkpaqpoKuqoaGtrqmrqKyroq2so6er\
+	    u6utqq6tpK+upaqvsa6wrbGwqKeztLKxqa2ytKm3qrOyqrC2rLW0rKu5rbO1\
+	    sra2rbW3tLm4r7u6sbm7uLy7srq9rbm6xL28s7PBtbu9ur69tL++tcC/tsHA\
+	    t77BvbjGucLBucDCvsPCusfDtcTEu8DGvMXFvMPFwsTGw8fGvb3Lv8jHvs3F\
+	    vsPKv8bIxdPDvsnIv8XMwcvKwdLGxsnLyMzLwsfOw83Mw8vOys/OxcbUx9DP\
+	    x8vSx87QzNHRyNDSz9PSyc7VytTTytHU0NXUy9rSy9DXzNbVzNPW0tfWzdrW\
+	    x9/S0tjXztvXyOHU1NrZ0NXa3Nzb0uDczeDa2d7d1OHb2uHez9/e1drh1uLf\
+	    0ODf1uPd3N7g3eHg1+Tg0eLh2OXh0uDi3+Pi2ebi0+fj1OXk2+jk1efm3eno\
+	    3+fp5uzp2urp4Ovq4e7q2+zr4u/r3O3s4/Ds3e7t5PHt3uvu6u/v5e3v6/Pv\
+	    4O7w7fHw5vLx6PPy6fL08CH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAA\
+	    AB4AGgAACP4AhTDhUuWIlCwDmWTJ8kRJFi9VshxBSLDKkx07nFwRkwgTJj6d\
+	    avXBVEhSoFyOAgXqg6pTIULVAgGitA0cuHDhiOEAouWLz58+rejQ8aNoM3vx\
+	    6MGzp8+evXr17G2TQECAgAACAAhAgIBAVa1ZW0WFSjaqPX7dJGz9gOIEAqtW\
+	    I3DgoEAAAVpmnTolu2+ahABdVLHJlOQthBtbwiThcUFALn384uWilQuWvsvq\
+	    eEkoYWhfJna2PgSgckfQoj13mhBglW7btmvJtiVTpw6dumIVXuyJNiXaHhEK\
+	    +GyiAgcPHkceLqHKVW8bJZvbYKnrBEsCj0h0thg6UwJACxw9DP7ZSgSjgSlk\
+	    r0aZkoWpkblfjoYlk5DhDpkcce5YyBogAQxSewQAgAxF/RAED0X84MMz1eCC\
+	    y18BMFBABhaA1R8AH2Tw1hJhfGGGGWWsgUYb3JxDzS8SAKBiAQBgBReLKmI1\
+	    SzW6aMLNPM3Q81RUaWlFQAFwBRkkAIFsc86R2+hS4pHuVJKiVQiAJWSQnYzz\
+	    Dj/z8KNOPPx0aU8ualHQxRx/jDAlXADUEs4vmGRTDzHyOIVPc3/xYIwo3mTi\
+	    wJlWwdTaOenkss2f7Tj5ABG2eOJNHBtUNSUAnYRjz5zN1aNPP/zgo8tmd2DT\
+	    izd3tODolLRsk4sm49gDTT387DUVEcrC7NPKPrEkwacAhFBzzqDq0DKOa+k0\
+	    KQEU5GSChC3sEHErJdrEE8829ZTzzmX+6HOLBCEss4wbmQhzgpRBEgAIKq4w\
+	    g0o1v8jmiCOoaBbAGs4wYkwY4AqZCjWndGNPMp1w0086o6Cb4gIupNBCvUPq\
+	    gokn9KxTyyntxFNKLZ0ok6KKGN8qgCnqtGYOoEYeWQ4xNNRQgw0mp5yyDCys\
+	    sAILnzwjzTPJJCNNzck88wwwfjzCSzLKBC100L7Iscgihhx9yNGLLK000gEB\
+	    ADs=
+	
+    }			
+    
+    
+    image create photo brainbg -data {
+	
+	R0lGODlhigBzAKEDAMnJycrKyszMzP///yH+FUNyZWF0ZWQgd2l0aCBUaGUg\
+	    R0lNUAAh+QQBCgADACwAAAAAigBzAAAC/pyPqcvdAqOctAqHs968MwuG4uSV\
+	    5ukF48qG6AujakvXUIznj83b+o/rCYXAYmeIJBqXiqTTyQQ+p9BojIpFWlHZ\
+	    rnZ79IqVYMxsjK6VHek2b910y9XwwfxOg+P3qzX/P7IFOAgSRXhosYS4SFHE\
+	    +BjxAzl5E0RJeXWJ+aKpydl5eQLaWTJKGmbqyZEKqsE66vrayiY7u1N7uoBr\
+	    +rFri+DLmxAMC0z8a3f8qwwacMBsC30qPU3taX2Njam9ze39DR4uPk5ebn6O\
+	    nq6+zt7u/g4fLz9PD59cj3WPP2WwT2Vwxt+XfgIHEizYQwEAhD56MWSB4WGg\
+	    DBJdxKpIYgPGdQkAUG30sLGSx4qlPpYkaQIjF4mfGMJ4mMmfDoGS5jFx5+dc\
+	    HWPjdsYJ59Oht6BCsRG9ZfQoUmhKKULr2DSisqiriFEd+erqyT9ac/LpWmcP\
+	    2J13xvqcY5ZomrRNvbDVyu/t2CFy0yasa5cOXrN69/Lt47dEAQA7
+	
+    }
+    
+    
+    image create photo blackandwhitebrain -data {
+	
+	
+	R0lGODlh5gC/AMIAAAAAABgYGF5eXqOjo+np6QAAAAAAAAAAACH+FUNyZWF0\
+	    ZWQgd2l0aCBUaGUgR0lNUAAh+QQBCgAHACwAAAAA5gC/AAAD/ni63P4wykmr\
+	    vTjrzbv/YCiOZGmeaKqubOu+cCzPdG3feK7vfO//wKBwSCwaj8jkKRAQDAhQ\
+	    AgA6qD4HyiyR6bQOBAEAUyzoPqPodHQqJXy1cBv3rHZX7fe6fu8uM+OAKk10\
+	    fGlehYhRd19/gY4geYl1X4qSVJNueAKPnBmElmqLlleZoXqdqBECoIVWrJeR\
+	    hVOptAqfr6aIoot5t3UAWLWPAb6JxZfGpVVluGDCccC40nxXy07SXwDPSE2r\
+	    05XUxlaDpKR8bFRg2ttAXd+4x4p+5K7moHdl7DnE7/3UX5G8HIqni4C+Gfz8\
+	    IWMVr1gZVwqpHGwhhmDEi2goYUw3/hFFQowNN5YSCWVTxxG37JFcafHdgAAn\
+	    P3iT5KvlyputYMbckBIcLJs4aQYVsG6nBULFeB0D6jIoQ2dGJQTIaEpprIXf\
+	    mOIZiYkhV5pRI5yhY66awFxCx24dJRCiIWzSgIVtcA1pJitdylzLeNVs279X\
+	    sRrSa0ZP4D3V3pkM645vW0WHP/nNa+1h41F+9iK2abbf4p1T18o7bDiU3l1f\
+	    LsMjHYopQbXUdJ7kx/o1LJ8AJz1Bt5om62m/qcg+GA1yU2VfE/EOl7xqbq3/\
+	    akcZzu5j866t+ToN/nNjbuYv9VWsJApTSGXQdUluFU7lPbfYwz8bP5gs2uZq\
+	    e2LrW7ul/l+v97n1Bi11+dJYSv7ZYcghmGlGBWnuRcdgRLfQ0gZVhNQVn0+O\
+	    mebOf3yBMRNkSV23WWrw3TNSQHZ0YldSDu5XE0BWLWNNE1WdCByNQlU1Yimf\
+	    xdFTiQtBF2OIXhDGCBe6BTWhYRHihWEVgfxo3F1cWfTaa4SJyMQcuqWn4HsD\
+	    4fHkaEjhFcdeaUapkpjcgfHlGDgiNo2Vujz0F2WtWWfHQ9QdQVuYX/VlnoIz\
+	    IqLOnBG+9QqeiXgpJxdOHCkaifIlMWgvV6ZZmmP9vfYlGWNSyJ0eYAg0z0NQ\
+	    lkaUEqukiCky9pWKaT2taSkGPdwBdeqnpjFhF5buLROoEMQI/tiho1TlSl6r\
+	    Oc3xGLSt/GrnJMwAu1SQQeDY6G3DXrnjb4wAA9iMWu527VuwJXfeg80GMwQ9\
+	    6KFnD6dZChapRUQl++weqpnmK4m2mojhbY5y20Oy5bX7ZLED18HqMSJeyger\
+	    AEMqIbzaJROgG8fqQJuAseALcZEr6uJnKPTSpDEBqbanzIFHylqvuLQO6IM3\
+	    u2CZc8plnboeGv4iNoilwE5StHHlVDNxH7WeeZ+7HC3sVy89+wxxfjmHm0ad\
+	    iCkpZkbCgnMuI3qmE2ZZ/94VWRUh08DmQLiSlRiiTHNo82ArIyWtfzVVjC1h\
+	    cw6iHboGp5NiWToUWI81iXGNcGfl/rgdWK0YG/03e6aIOKScu3Zz1ne6Fdbu\
+	    n2n/xAsOsZr5l5lM5zdWz7NreN0yzYIjZ+r6Xo5i2KFrBhGNMKbNItqFPZj5\
+	    DRrSjdq9bM+edZJLKV9TRiLynrQ8hhu2aHmQxawvAZR+CGQ3ZiyS/BM1JHQ1\
+	    opEf7vb8TeNlOlZ7K01M8rm7SzqqZCgWyGznk0WJ7i7ZIw+PwBE3QUwGawqE\
+	    TeUkGJAkCet+0ouXYYQFH/1MrU8cPB3MvDWjVDltHJaykezcIAMSjg5eE1zW\
+	    vWxnv90RL2vgiUL2EgQPaWXMKoZY2e6qVbJlxCBWeGFQBYkFQyY670ab+1bi\
+	    +sDBa1lL/g1gGlbQ6vY/NGRrQ/a5AgyQCMTRnQtqPntQWebxpYChhW1csaHX\
+	    OHQPzy1FdpH4YpGulyvpNZAEI1PjC1G3wNQMym2mWxL6/CVFS9iQjv1jheci\
+	    6b8nIE2EtQIXlhR2AiVS7nGnkaCc7qZCvMxJL0WD470K9SAfVqtH0zHc9WzW\
+	    xRwRTDJ1Ix8LGMYLqA3PRr3jVQ0rg75JHWgUhZqUoRSoopIAAE9Dy04uTncW\
+	    cDUsUyg42w17mcs/8cIPu6KeqrJIR+jhsl9IWxAsqVgyHWnQiiUxmeXMwUkR\
+	    mO+JWCsTUo7Jxm6OZZIpExjtXuLKOdqGZSPK5LOiWRq7rec//uX4owfSt5XH\
+	    XI12fWidJiZZOViEklma4A9ByUFJW70rcwgzGB+pVrAmPqaeMsHn68q4opew\
+	    CXUmzBdkuseu39WNjW5sEkizlMKCdIxIsDvcZPJSFBJsM30WPSP3ZFlDkoKv\
+	    HKeh1Uc/OdIDBtSL7VEVz6yJTKd9tWlTqqjxYNoBgEBVVfUrpeW6pD6x0Q85\
+	    wtGTImtkPzppL17pdN0C04rXpFyBp2ar6Dwjh5SmhqBSBXrr4wBDMHl8VLEx\
+	    hM2kCuc4tyqyfPiSJm66hFJrnucKqDzklF60zTHhowSQK+VM3zpPbOUzl/HD\
+	    3mnk6FlUBq+WavhiGM1QWozaJLUk/l2ow7TpRxJA1kaSdRptlZhGCmYWb7fL\
+	    Xl5A51fLdBB7gbNMcnN3t6F+ll5tYq3YIKozEOxvmxb9Ey9BhCBzTrCbzFqS\
+	    l+gUhv6uV1+l9WZqMkdKTbIyo9xlmEdfVBJKKWWeInjvTCuKNjNe04n2IhY3\
+	    XQtCziL3aH9Fk4cq3DD/EXGfoaxmyugaVTWBIMXinMzf4gs7XNkLrZRDGSLb\
+	    +NbNVoqWerxaijulyWgCF0U/bucJz5hEeXmAHtGFLItpjDfcChLDHc0k3Bgp\
+	    u1XptYCqQdGAJ2vjyi6onQh87oYFC9fFspUCz4RqknlLWdzODYc11lpm7euu\
+	    SvG4zN4E/tWAP2QNWsEPN9IZdBIpqkI2A+YDR0tSkm3MXCBlEMd5vm8agRZJ\
+	    6PqXfyJuMokRKMss+Q7NajEmafVK6EbDN6aUmXSL63zpxzGxD1gmqwQnh0jI\
+	    hhN8ajTTdo0HN/PBb4ZzdJvolCzmJVeGMh8Ys6iZ7Oj6ZXqgxr31riUn6H6i\
+	    OqSmTKRNVWnSAD+UotbMaoy1mxcPEI+4np0wjc2Ya9cB7bphRM7z5GvVeD2V\
+	    Vwg22X0JbDnyYJBYxB53W8wgUVWocLvwdR6jUds6buIWNdarroE9dc4ZY0iv\
+	    +u2xalfY6ProG6oabjaCxe1inuiJMoqebmwljd5L1xTbxuN0/pEXx+/m7TTF\
+	    M76RPO3WULApL7qSdhzIr9ZwCKhZnKtOH2SL6eP4vfDBWwvodTNKzZ6jhsdT\
+	    XzojVnlrR6VGYlRXc2ZuK9M3q0JsUY66l+mqJA37PM+Euje2EJsz5BLOw8Zc\
+	    ONgk9ybwfhzkK//zA6PcgW6IDunQ9a0wg6akzCi2yibOd2aJkk4LFq58Tfj8\
+	    fAn63Y4W1tiKM7TToshcI3KA7mKP/DgPHlcWp3yVXIueYUhVWMF+ftW/n33u\
+	    yx7Bnlq7aejbE5JpBBUNpBjG0JV2kzOt72Df19YN1RqtwOROY3Eh+Tf6bbgx\
+	    venamsY89bDjnk7pBcdewLs/lvWw/g+xdMwOnHbG3nq4yNK3M68e7JPFfsPE\
+	    WPr3PyfUU3MVdOH2Vk3nAO/GfA+HSl8mZhR2aNIzQfeUWDomGT/yUPpUdclU\
+	    PhDHV6Y3WIZ3MHuyO3KGdG73ADAXa/ZjLBM4bfp0TVykf9UHJdVzZWTjSkS1\
+	    bH5mg9dXXCWRUOa3ZKHkBxFHJRswZ24Fg/OnPmdjb3G1SdODYYX1OzoWPtGz\
+	    Q9+yW4b0HIJ1dGgGMri3WKBEOCD3ghzQW9MWf9DXeoO0FhClbSnFhWwhKxX2\
+	    RmMmgfAlSPezIkanYfbSWTYkZ0nyesz3ck+4iIQWezeEXRSmT8SXXgalQMcE\
+	    Xkj1bA4G/hh2RU1udHy4FjlLJ2tW8Hrxd0OpGIN1BXlzWE34Rl4qNlSWxnMC\
+	    Vk5J92k3xH29N0DkRYf2d1EPRzyK6IhSBn8z14fCiHWph1FbOC05lA7ohkv5\
+	    c3SjwisJRIheFIpHODyLJWx/0VapuDvJB4eOI0xUCGjeSHaRV1C0uI1Jxi7N\
+	    iFceJXph5zB9p0W1VWA3qHxm0AEQZ45uaEd2QA4YNG++ZHo6JHqMlEOLRmmr\
+	    BYsnd42ntD6F8h1RQ32zM4kLF44AOZDRt13YGHu9VmYkZhVKiFpfkl8RtF7f\
+	    Rhbwhi6/B2qGxnUsKVtad4PVxoQckCwjGJLeB1fU5mpkuIhh/pgmMfM2z4Z9\
+	    +bJFyVgkVUeJ+WFuHwdwFSR1ntiHMgGHDygQyzaMV2dv8lCTUjRKxjeBm+Yf\
+	    dVFUW7Y5ZpdRN4kH/SVMxJUZ32cZYteCEjBniKgJUGZhUcVy4xM2PPU+8tg7\
+	    2mcmCoY/i8IMMVSQQTVcDAl+DjVM8teAewmUEfd8rfeN2NVIXlRF1iZU5tVT\
+	    FaMfIBg1vJiWyqN4i7OOLKiXFCCUJTeAS+hPr4OFcERF4/WSz5iDrZRKZvMS\
+	    YvBMWZZAOyhdX5k3qiN9quhc6+aJrhiWPIhnmzEPCuUc3/JQI+SYuEFFu9I8\
+	    g3ZWmCiDJrlacWhBJcBqzAWGtiZv/mK5df5DcHrjkhVYXXvInaZkVWNGj0j5\
+	    bpdlVliVnl6AmRhAlylYaZRYbeX3DwWiN4NWeXVWj8k1JA3mLXiHaCqHQgHT\
+	    bCqoTc13AjAmkjRYRmUCbtk2NcCFJu0YevX3T1/yXQsFMqOnU2m2jtKGcIDH\
+	    XAY6UQNgLkQBAEIak/J2ntFDdqzkUwuSLblYkXLmokyKgOHjcTtHk9JFQJb0\
+	    lWczdTpgLtpUcFIkQvhjWRV0pItoj343SmumUMSJWHaDelq0PmdAoCkYojiw\
+	    pU+kenqakSTyZ+i3fHQHoH5odawJMsZ5fTJqWleVp83pVj9AVYpGSMCmN5Xo\
+	    fXMJhL0l/neypT7gV2QatGU+JzUBskSUkHsPBDfdgoyPM1/lR36oM5MRSjKx\
+	    CoEls3YMZqHSV6jvpH02R6gLVwQBhCsBip+XR0jB9kEegpbJKkD9Iz1bVSqY\
+	    1ESqUy/Pk4jAyqr6hXu99BNfdqw480pdQXHHZJ3O6mfTSC34djzVWg09WgOH\
+	    ilPqtqtXyh/rEiUNwmjQqlOZinLbdij86EsWeIrcYJvO+TkA9Y5G9UZORHst\
+	    xa14iZPSpXkpp2+eVA/tegMGCZhxF6MeRI+HiQ37VUzEo3UoKllqiKui8T7s\
+	    5WRIUBFICiq8Oa7wtIWHKbHlMpM0mW5XF2P4WF5Eh0f1AA0N/sltIVKYJQVS\
+	    WpY0pMBGImiL6DFd84MfYBpGiPoggEAqk/oWzzqmR5u1NclrfSWyuNioJzpN\
+	    hLhncRW0gSCk+GVqGdhpZAkzGuWxbcNmKhhU/haWjVS1eyZsF+sDQvpMmEcw\
+	    3ll47BhcL0N+ohhwy0S18ZhbNluFWCYQ7gcE5fMAgRu4XotamJZBdKtDY1V2\
+	    uwkzNTisGrhR44qkVgeR52KnPyApYgVOmcu2Pyuu3TErHmRJcyuP1Cg1Qwa3\
+	    S8mMx0Ox2JaAQ3CMb0g4s3sZ1COexpcIGDp8zki6LaVwu9YaMDeaj1mHPus0\
+	    QpC9YgWBmxW4Lolu31q2WDFentpH/tGkfoXnZnQzPpBbZQEoBM3busA3KqET\
+	    VfV2KSlhtNt7h6HVSi86OK7GWLkWv/UjmzPwhJA4YEAYsoHLSxxzuzdmdlq4\
+	    LtU3wDCJjso1UyUIpne1RkMAOaZYQ8P2fQxpqgejWwrpi+H6qTgTOMvZR3ao\
+	    kAicWX87RqVEmXkJe20UetZ5nfqohfh4tt6qMjmnemS2wXlDqK4LBOu2gvEG\
+	    dUzLO0e8IucqjQeFw3zEgVX0sSXGKTl2pEhAmxGHoq7zd+75tcPVdcWWZXYo\
+	    wlMkqTdHbQ06T36gBAv3dHeVVHAlgbJmIvMbIh0at9+qwWijdSglx7E7D0JS\
+	    slp6kKgB/oYSCrUwGybuab5dI6ZiysVQ6V9kLHiVCwiSFmNOVDvPs4aRN2ns\
+	    VmrJJH+NWJnbAzDKAjOzC8teJAxY9Uu3Q3GjTIGnDIcrrIMkqGjlpcH1qTSl\
+	    fAB6oQ9K8cDAeIFAWyBgx7TBh0mGNX0OiZgsQgXNHBOaAaw+e2Yp52v8FZ6a\
+	    qlIYDLCnW8esucOp0FmxhXI26r938XmhI7Jt/M5hRZWAllg1MRcOwK8Cl8FK\
+	    lVVT9WGKx56gmaR+KVkIe2AE7YKiVlPAqEbHiJcVOWhpl1MT9rWQ5HUvq3Nc\
+	    UdEuKHMcbEgH0ooi+FxRR1UJWXsQkoCiiqyZgNIPILISqVTt/putqmiU/flP\
+	    1DWAdoJClZhhaaTTTtdaTZOzFQzUaPx0E3eGOcari8B3a4MhTO1wIzuFQgWq\
+	    ldm6Pdyt+TaYmtx1tyJfXS0BDsw/SatVYdYhIBpiSfy5HJhoSNYIbe3VQ21c\
+	    HBgjNnhsMrV7oYsdezQTqBkGfX0UlkloHBOpHdMpaZvMCxUGgvuWdqLQ/vmj\
+	    jW0Bo/fWCj126aVziwuaP0q+1+vPZhgPn32gZPZypHVq4dqvIz0W7lczn0Jl\
+	    UfDaGTCNbBcZwOI4vXgMDURdaO1Pvp0BNUc/FvoxxM1hVNNeEWCcBTHQy60B\
+	    2NrTFWxy1senDYGZWk0x8uzb4Bta9bdMeBB0VLHRk3ibGtkdAqzKoHcoSOwo\
+	    NOV9AI8XxfH9ZNEVaAoLTFFNnl/T30cwcXQY1w2brxcTzgbeAwa9kTfDmtup\
+	    NA+uKQ+KhibVNqvtE/l94TIgmNX4zhXOsiAuKDzryOlGkIXw4Sc+A+dKMlOC\
+	    2RhKDS8OCJ3FHLg8wdzh4jdeAzQ0utmQuagXXD/OCTF+oQowwQRk5EeeCqKH\
+	    uS6bndj05B0RrKTh41bODd2KRVtuFC3j5V++E11eClo+5keA3HKB5kZxJibO\
+	    5hNhknAeFgEx53Z+53ie53q+53ze537+54Ae6II+6IRe6IZ+6Ije5wkAADs=
+    }
+    
+    
+    
+    
+    image create photo multicolorbrain -data {
+	
+	R0lGODlhigBzAOf/AAgLBxkbGDkOJiwWIzURNDAWRkQYFkgZDTgeITYVW1IU\
+	    GEkYJSkpJz0kGTMjPkUZV0EfVzEoUzAtO0UiRUEoOE0iODwlVzsyHk4jb1st\
+	    JGAuFFE0I1I3FEctcEctgVQmiWMwR1cwbGkrcD1Af2I0XGA5SlU7Zk9ETmI2\
+	    aFUypFRAX0lKSUs7olJAdkpFclZPIUtUKk1XFmdLEEpLY29BNVs7lHZCJWA8\
+	    hV5TEURFo2M9eldQOFZAlVhEiU9GmG5MKGpMO2s9iXxKGVhiBYsukT5SonU4\
+	    n09SlJoqplFLvWdDuKgpn4U+loo4qVBUs2hEyXtcGF1fXGVMs2JZgUdaxj1k\
+	    sag0kmlVjV1bjntDwFJjhmxZeXtVZnVRjWBYq1BlkndnHUtva19ie0tit4lA\
+	    yU1sgXVlOktnpmpyGIdNkG5ib5NJkW9Wr2FpcGdoZnhOxHdhYVxipnZUsYJN\
+	    t3Faolx9I3JpVIRSo2h9EIRkWaJRcpdeW09u3WNryWptsmKAZVl1uVV1xEaA\
+	    tE6LZlSBj2hyqVF7uGJ0sKVZj2d7goxftXd2dLNWfIRgx1t6rVaNVm6CUVx9\
+	    pH9ze1B61nJ1llOKemN9mGODeFyEhmt3o41lrGR/kXmDQ3l4fkyHqZB+IIWF\
+	    G0qCz3F6kKdjeVeFnatqSrFqO6tlaVOMiIJrvZZvdJRrkIJvsYtuo354ko9z\
+	    hXaTHoJ1omecIZV3a4t1k6RwaoKDbp16YJiEPXmGjpKCdJiDY4uEg2aZeIWH\
+	    hFmjZqOAWIyKZ52FWWeNyI2EkmmiVJWLWWqQuHCuEGKbp4mVZWCnfZaXQH+f\
+	    V3iha5OYVXuOzYeYeJGRjnCikpKVf2+hoIukR5eQqp6PnX2wTaCmK5eXoGS8\
+	    aZqZlniti2u6e5i0OHrKFJq4H52Yw4C5bYvAK6edonjEWqKkoa2eq7OWzKeo\
+	    pY7ITIPVPaayqK+vrYPXVZ7TI43fILW3psOo0be2tMGx0qrJoLq60cPCwcrM\
+	    ydDO2dXX1N7g3Obo5f///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQB\
+	    CgD/ACwAAAAAigBzAAAI/gD/CRxIsKDBgwgTJtTHsKHDhxAj6lNIsaLFixgz\
+	    ItS3r2O+fBw7Nsy3DyTDkvtGlmyIUmVKhhpjypypkZ8+kx1fgkwJ0iRDnzeD\
+	    jnTYkyXHhjSTKqXJb+fLiE1X2kRpMyrIqSSrkjzqMOfEpWDDIrT5kyE/kURT\
+	    Pj26ti3Xsi/RjuQnti5Yjh8hily5U6hNn27yefO0AlC9w/XykQ267+9JoTxt\
+	    2p2cUe3TtlsZLkK8DQ4cfXCk1Xt3pky1aZ4EBRoDqLC+epIUK3a4+DFEyrgP\
+	    Xj4b8qZaON38jMGSqZAfLJuS5Srz7l2ZRJWmeSM3LZkgQ6snRaoT7l0/XnCA\
+	    /tpmrFef5Nx11771rc/cO2Kt6MQZU+RLISyH7n8pUwbdummkRGKIINeFEoo5\
+	    /p3xiCzlrBPOg+KUw1ZQsxm1U19foaeUSl0tlo8r2BATCx1elBiHcWcUEscV\
+	    m0yzDiqkDPjFGTSeAYghY/iDjjN1yCLPg0CKM5tlOKnHUkoa0sSVWkuaJMk1\
+	    ULoi5YgkehHHOlh8MQ0hltBYxZdfTgImOv6YEwUhvwyBzINrAhmOJBPSRpJ4\
+	    vSWp0UNA+QQHL7HE0kormmiyCi1+ktiDF190Q8gZY1BRRSjorDbGGGKOEQg6\
+	    2wSwTi/dSINOj7LIsmY77ZRTjjRGytXSY3TZWdF6/ksGxcs744zDyq103CGH\
+	    Jn/G54UTZ3whyBlVjPHopZIGEgggVazjRgBRoGPONujEEAOoyGSLTDngaFOP\
+	    NuZ8NCRetanVqqsIqYdhSXD0GQsrdCiiSCqKNNLIG280cscdmqDjwxiMAgxI\
+	    HDca0o0hZyB8iI04RuNLFOts88ILMFxbR7biiKONNmDIIMTHQph01VteZYju\
+	    QEId1Vc+9cybCh10pKIJvffii28W+MoRXw5xfLnNso544smABALiiCNnKOtJ\
+	    MJ5sM8QQMUx8rajiyNKxDGB88gkuWYNijso+fbTWyQJBZpZ5DL1DRyNsrNNI\
+	    Kqk0Uu+9UryhhBJvPJHF/hxpeCGFsZYmTKAgjkQSyXVIB/Ll0p7UYQ7UMFQc\
+	    AyywIKONx1CAAYYZZqBhRtaSpDQVkzf5dPJ4an1UTzOL+OEF3OvAjo4SWeAs\
+	    Be21P0EGvzwU0TMgNBKIcCFHI90zwYIQIggseDwO9QtTyyIDFFD8YAYQuNhh\
+	    By7UC8HLSEWF9BK6Rt3ET1P62KFMMJJcEYsfrazjT8TrvJGFEut8kEIKuus+\
+	    Bx1ssFIRzuAITAzOEXGIAwEPYQhMoUMQofAEHoYwwSFU7AV1gAUaoPAJKHSj\
+	    G7hwBS9sgQvumcIMbbBFN1J3Np2cKzdGks0+4LCLd1DDFbQwh5/8s4511M1u\
+	    /kq4XRb0pjs50ME/VfAPOgzxhdQIYkZGa2AP0fHAQVCwG0+zFgzqUAwcZM0M\
+	    XDDDM1rxDGZojYNRCEMwVjAnx9wmN7wxWz76oQ9pvCMY1NBFN9aBoHXEAgvd\
+	    QEfdnhDEupmjTOiIFoKioAYqHsIRWvhCJg4HwaFFAQBREAQqilEHPDCvWlHD\
+	    IBqwhg4gbIMTxnCFLTgBCVBAwg6XsIUdgqEMXXTFNiDBTfma0hSSSMIWNtTF\
+	    LYCxi13wwhVqmIIcpFC3+zHzHfhqAxsUwQYWUMEcACgEJShxhCfk4AiWEJo4\
+	    3eEJQsiiDp3EwwTXgQ4YQK8OnMAaLoCAgjww4xmx/shENILBCXRAwha22Kcu\
+	    dpGYChXJZGHhDZHElbZgRAMdxQQGMXmhBmJsYZl4ywI6WOBDKZhjDrqSAhVy\
+	    4LtCFAIASUgCFrAQCU+EghDuGAQ6snFOTzIvYm3wzwtwMAQcyGBrQDBBGJlh\
+	    i18ag4qSkEQ01rcLicJJVSepy08w1BCyuOEZwniHOW7xjjzM4ha62EYntsCG\
+	    Zmo0BehIwTtyIIUkpCAJOXCCXJ2QBCUkQQwvuEAbCFENWVBOGqGCBTpz6s7I\
+	    Vcw/5pie5rhAAhXAARfMEMYupMUMYwgDGMK4xTrycAs4lKwv+wgLeXjSmMbk\
+	    ozn1UEUe8sCFHkriq7qQ/sQ6ptCI2+0vb90wRwpYkISIbSOlSiBkcHngzm5E\
+	    4RFlKAaCAlSGMMCAihSL7ueoZ44ergMMQCBBCHSgAi6s9hbCqIVqucCFLXRm\
+	    Fru4RflWglCZ4Al8+TAHCcjLBa2SAAUQM4cuZoGNTmzjCuZgZhaaQIY5aPQJ\
+	    T9htImenBP/UzQvdWEEA7FAJVPwBQX/YwQ5ekAt/yODD08vch6FARTdQEQ0g\
+	    KEEHeNABHdC3CyTgow5W8Y5F6EIX9SiL2TakrvM1pR436EEPtuCPRUhCDWqQ\
+	    BDpkywtJbGEKPWBDbZWwPyMYIQo2w9kb1tEGdkbBDWYKQBsoVolLoIMDF7gA\
+	    /gfWvGYQ48CnIJYBBzRgAxlQEQw/0O4Ngiy/TixCDa5AUFJ5UaZ3cMghScHL\
+	    hEjinhKE4AFB4EEP0LGIEX5wHZJ4BTpG0AMAltW2TQh1N5qAhFIjgdRtCAAD\
+	    AgAACWzgDzBoQ6i6sQfxquLWtQACDTaw5ii0mQMe44AQNAAFUEQhWuw0UyJ7\
+	    0IJO+MIcAbCFLnjhniazJ2XtvQhErgIS75SABCR4wB2kkI4pbEHJ5ljEK7Zw\
+	    BCGz4R1sYIM5WFBlIpijG6bONwMAsOpAXiIMlCgHJ4CwjlcY/OCvgMOuNxCF\
+	    DWzgBT9Y87BpIANQaOPYUQiAmI/NzClIohPo0MWf/qeAjndEYS8nQUtMfCMb\
+	    xfCGF3imAQlAUAEI8EAJ6ZDCpLHQAx74AB1eiHcPq0vF/TWBikhYgtKXjk0G\
+	    vGMb69iEJYqRiB28QhSSEIXWRRGLVaziFaPohgEywIEMbCADw9aABoQAClC8\
+	    Awe6JsE2Mn67J0jaH0d4h7984IV38GIquMy2QkSSmV6SBAzVo4E5aE4ACLDh\
+	    blLgAQ+k0DY5WJ4NmMrBRu/2BCQYwRxEULoVllBqdDBAAj3cRiAzvANVvMIc\
+	    H8/FJvrUilXwcQ9jN/sG1M77YncwDzQAAQjMJPlCrqMGUqhBDT4t79qYxySV\
+	    cbnhmwIHX0AhHT9QvPAn/lCAdHTgBh2VgiCl0I0crCMH6OdBDuqaAiIQAQnm\
+	    ULqplZ5xdDwBCHtYxwrgMAtVwEHJavAKlFAIrbAGibQKo7AHDeBwO2ADGoAO\
+	    CqAB6wAF5iAEurZ4IMB9CdABNSAHhfRpNcAD71ADD4FyL5QQZ4EW0wcH6WAD\
+	    NkADGpABJbAAC+AAEAABCWAB3tcBGJAAGNCDHcBOPOABPsBWKWAE7ocEAXBq\
+	    ezMHStcNXZZIozAK4vV/cKAGUbBNmcAvawAA64CAtdAADZBmG4AOBwAxNpBI\
+	    MCiD6NANExABDlAAD5AA6PCD6MCDGHCH6/A9RhEXFoEhH3E+L3EAGaB4NMAP\
+	    /jMoDRRwgxagg93QiBZwgw/wABCgAx2QAzxwfu1HBKQWAPUwB3NABm+QdOkQ\
+	    BTnlBlywB3lwZFJCCZkQC7yyBmvAR+9AhXnQHGlGJspmDmaiABlgDiVARRTg\
+	    ABGQABBQADeIjN0AAZNYiTfAh0YieAOhFS2XEtLQQwZgAAqwjQaAAN0wjDbY\
+	    DQ6wDiYwW1MwBebQAwmwgT1QA5iYAynABFbABEsQLfVCBmQQekiASW24A2Zw\
+	    TICiCEywDnfABGuQBugQAFN4ChlwASbnBqnGauawAAfgHumgAQqwABTATtUQ\
+	    hxMwAS7gAlMQMXe4ji2WDjl2bVE1eKLDS03RDeng/g4DMAACIAA02A0IoJES\
+	    YIMqsAXpwE5fEJRahQWPZgE3gA48gA5GwARE4ITmADdzQGpLsA5NkHHR8gJA\
+	    IAl3MAdrcAfvkAYHiQjmkFPi1QAIUIb8xgDmQAACcG8CADHpsADbWAEncGzb\
+	    oCMq4AKJImZtOAId8AAr0AI5RifmkRA4EYhzYg7pkA81WQ81iZIIgACLsJMQ\
+	    0JPpYA4zgjDNgQV/aXM94AFSwARMgA5MYHJ+cAZKQAal1gRZYIpqYA4vYAet\
+	    kAZ3IIvmkAaIsAqIkHHmAARiuAEXAG0AcJfoIAAEQAAJaQ5tKZcVQAEbRyaq\
+	    dwYrEAUroHfd0AFuYAIW/vAO6SAUIgMTByEn7FIP6XCcBZAYx0kC9RCZFCAB\
+	    EQABW6AF5nAG7hAsX7ANM9IDbQAAHdBzNaAjpYkOS8AK68AGb4CPoght22AO\
+	    OwAHtYkIEIoOC1kL5hBxF7CACMAApscA6zCTA0AABcBI82OTGWlyvDh3/tFl\
+	    YFIE6NAGGLAI1FkPX0Me0GcQpaMYJWET6ZAOA7ACDqCD9TABKBACE0AB3VAB\
+	    M3CDO0oj6HAGWKAFkeQIGRcAcNACHNgERFADTGkF6+CKXiAHbzAHUrAOATAA\
+	    6LAFmrAGjKAH27AH3VALpTBMHCCGGUCDNDmTUeAPH1oAyOgPlGhdvLgO3RAB\
+	    /hHgAkVQBG1QBYc6AkUgDYzqAfe2J4dJFO3lFvsgDTy6p0oqpCFAAhXQAAuQ\
+	    pBCwo8BzBkVwBJ3yBYtQptAyAjxQA+4Hq/LIBPcWB+bABn3ACicVAObQCrW5\
+	    poxQC6dQC8MEBQdwAGaJADUpAN0QACZGk8hoAeYwiQ/AizYZBQ7gABOADkUw\
+	    Bt1QBEWYA9LwJSPwARBgAZUmDZ8xHhxREM+3E1MxAAjAo4NKiRAwARAgAiRA\
+	    ASWgADbYBgxwIwPjA8rnBc8CLanWAjUgqAMZBOZQD/MYC37WZYuQKQGADrKo\
+	    pnqgB6dQCvkgUcZwAGOXjbzQjQMALQjgAASQANTa/kPUSgBR4A4eOQJf0oYe\
+	    wAK5sA39QCMfgAE60ANqdVotsRgFcT5hkw8NEAAIMAB8CgEhYAE2eK/7mg8p\
+	    CwEmcAbpcAaL0AkMwACSFwXSEEjQFgUegA5EwARBcAMDWQ9LMJqJtALBCQAX\
+	    awWMULd6QIWlUA/CIAwhqwDZaADSMIbQhg4pi4yTyLIEsJYkIADroADbEAEm\
+	    QLOH6gEe8AFRsA2NWgSKmQ49wALvUA98qBcEYT49kQ+80AA7yrSSaAETkA/p\
+	    MHMQ4AvLCAEtEAc72g+L0LU1YKv1cAR1SKZuwAKkGQRdEAT0aAVuAHWB5AoW\
+	    2w11ywgTegvpwLfPcADb/ogOBjCGFyANbRCZ3WC4c5i41ioABoAOxNgCippE\
+	    28ACH+AfRcCoH5AOQbajIpBuccQqKDNVHSGGqKu6IRACEbCI+VACJQABBjC7\
+	    I+AGO8oP7+ALnbACfvAOhXBE38eLUXC2QRAEaYCQbaCY5sCU79AGEhAAzssI\
+	    wypetQAM72AMz6AMHGAO2SiyxxoFDcAAhTuJGPAANAgC6QAC5Pu93cCoRYB+\
+	    KfABgcStOfABH9ACN+ADUsACUaADvCAXZTGN06cPnZC9F8AAxggBbnCDNJgB\
+	    UaCR6EC7X9YG3vEO0rANvkAHmqAPrWAOW9AC2+AFLAAt/sGbPfQOfOQs+8YA\
+	    /lHQDSc8CwM1D2CGDc/QtwvqZdhbw9KQD4vwANiQAAKwjdy4rQUgZkUwUvCY\
+	    Av7wdL7AC+mAAT1QhOnwAQWVGTwBnmIzEtuwCAp8AStwgx0AAQ6wDWC8AAhw\
+	    g7TrA1/iBp0gDbHwDlegCayQDw/sntLgBaB3sBqXvOnAQy0qAatmYuhQC9h8\
+	    C02FDq/QCrzQDQ1gAMeGhVGgAMd6AfzgC5W2jjqckco5AWYit4rqBPC4De/Q\
+	    DUqsmB4wAkS4o/UgAlLME2EzEf7QD6TDCzCqAA0QBRFQy7wMAcf50CG5RzQS\
+	    C+NAzJ3GMlFQl53gu3dgDmsQBELWBakWBQjiBn/M/gBuAJElpwq1oLfPQEUo\
+	    oAi6QHBtgHGLt40HMAAOUGm8wLLGeZyJqwYad7FIvD8Ro8Tr4H0cZwT9AND5\
+	    0AOLIBKLEVrcZhJqowlyibrp0AI3GAIMcIMokA5WqwKOKg1OiilusAjucw3p\
+	    gNIS4ALx4gvSIA1dcAVX0AIt8A6nd3or7QYjjNPZLAzKcG/oQAs1bSbd4IWx\
+	    swoVoAAMEAEWUK05TK3nKi2R6wMYl2zdwAKezQPb0AZYaGUGyblX0AOhyxL/\
+	    QLoNwQuaoAiIYM4OsKNWitIhMKRkjQK+4AJ1jdaq981XwAq1wgsnMAMnoAl3\
+	    kFvrkNfd0AJXgA4ordJ7/nywjYQpX7UL0WAmtsAL61CRVBTI68Ar5qAA5rsN\
+	    0vAAGPC/D9ANQxotKHAFjIpx1rxbLNAN/kBvLLCUQaAD+oDXXcDfOtGupUMW\
+	    +9AJXNB1ChAFI8wAJjCkKIACAP3f6aADauxsXxC2nUAJsNgK6uAKf80QW/Bs\
+	    sTAFj3wFU9AcO5oI/2ZcU2rS6/AOylByJm0NZVhdpogO0QzdCrAOEkAteyQC\
+	    ENANIhAC6yACQ34D/Vkmx9aGvLACSpwP+b2UIrDfU3AFPKcDe4ESq32Y0rAI\
+	    W+AGx9aNjWgCOzrhOgAzwY3XJvAOWCAG3eAKlSYGfhLH5kAMr+C6q7DGDSyS\
+	    /uugBf4M43z83aYYAFAXDM7QDa1ARXDQQyZ2bLwoLQBAJuhQAEGMDiHQDSGQ\
+	    SF5AB0KG5DpQJtCCfofBC5ULB0aQDiIQxVOw0W7QbN0gNqTDJPtQY7RAC6uQ\
+	    vRJgASOg1y2QDnidQAm0Dqxw4iYgCmKFZLPCCrFwDW++BdwZC+hQ1/mwDVni\
+	    5zsaDdFgC5BwYbxI1Ly6I+6ADiRAdGC2DnU5RQlp3u5pAYHUASHQA1/Gd0fA\
+	    6T0Afv7QBjngAyjpbHsWBUxg5lGABVa5CFgwxX0oGwxhR+qmBgsQBRQwASOg\
+	    63qdDvJxBPOBBfWABSugAp1wAis9AzMgBgu67JS2/gjnqMbvAKVakPLVdpmL\
+	    kAg4ng5aoAbAoXEO1AokcJlu4GXQ8uJ8dLnfGwF+aQ6doANeIC0mwk4+kOn3\
+	    Llc5sKP+8LVNDO9RAKX8EElf8D0eIjovYUeoyAViLAEY92W97gZx8GVg3tcq\
+	    4Asevw7jIApwLgZiMA7XwAti8AVawB96L587qlWpEAydgAU7LwboYAdwMC2Z\
+	    svP+UAJkCgBtAOamCHV8lFPboOsW0AFI5gJHcAQlYiVRUCJBlgPQcmwGewSQ\
+	    fwQ7CqX84Q95XwbfAxSyng/SwAsoTQEUQKgd0AE3/fhg/ixYOJ3qutJ1yQuU\
+	    EGi+gEzXIArSIAZToPp6/r8OhND3tKAJ1AAJCioGauAGdmAL/rECcotxGuf4\
+	    Uzp0ZtIGQt8Bd5j9vGDxXtAHXuAHn+8FPZdIuYUOTnBsctsGR+ACWTIDeq/3\
+	    AMFL3759A/UdJHhQWic35qJEGdHBg4cPHqJ48OHlYZw4WKS9e1evU6coIynh\
+	    U7NIjShi68S46vauzDZCmGpuS/fHlytXttYFsLPITjdO3datM7ctwNIAbaK0\
+	    acO0DTp05px6SIf1w4koko54YePFyTp0YHX4MIduG5V06ZwUORLn4ZczXwQ9\
+	    XeEUk698Bw/2RahwkZso2yau8FDjYhQ1N+KkU4PlCkcsU1xcqbdt3The48jy\
+	    /rpGyVWnd0a7WSJVExMmVJX+oHuFLoAtZcaMPXuGK+26d+gABACgJm2QtEsL\
+	    b3uI80O6GiHbSOvmxKG5Il6oRkFXxAkVPlT8+aPSZ0CUQ4a+RLIEoI1qVAb9\
+	    IgRcj9c7N+g+qLHYg3GAiz3SuaGDjo7yuYKVMcbYhpdMjjnGF4ZEySSTRbrJ\
+	    ZJhILtwEHdYq6eYPSNRQ4xlqbEFHGWWe4aSq3miJir9HzOEhCyWiaCoKpNxY\
+	    J50WrmjBApGkActGL7zooYd1uqHiQHT4KEK77qIAIJBADDFkhQstqamS9wri\
+	    0q9tQKrvgyiueCgtNaKowb8oiOSxFSzS8eGITlyQ/gYaaCxxYyQ7peFljHfM\
+	    CQSQSMyxpJJBOHQoGDjeoSaYYCCBZB0b13llnW3UM+cRdEYIQo43zuwGHRrd\
+	    SAeqNsRo4YMOHmKDjiDQOYIOAJLYxgl0/HnHlxGoSIK7XqngLgopHUGPw78C\
+	    e08faRaRNIopHoqCMOSiCCIdubzwoQcvxvDiiCNccAELPwJhxZxMZsiEEmnq\
+	    mSSdScyZBBBzHCGFqm5QGWSdR4LhxRwQ1gkGnc+2+OORbeqDpJkppKiBjScc\
+	    2i8KSizowAIXom2DDbfM8SEHSbfRzglf3hmhZGL4cIMPPvpQmY9JJnnIEHov\
+	    8YvLfPjRB7CPDo5CDDEe/qoqLTTbimIFNqrzw4+OsHAhaT+gKaSQTjLRwg1p\
+	    QnH35UlCMSdUdCoB+5FHansFhFZe2aaqVqJ4BAaytoFEGXSkkCKV3iBWr+ge\
+	    eODPHIzSSWUsJ/hT8ogJRwApnZal5CcUrV92w5BIMMmncpxrNigfhooD7qlo\
+	    zXHDv3T4S7oQSiyhpJ90uxGjEDuhAWmRThgc5h2yaIzCHEG2ac3QQTjBRZgz\
+	    2zBqm4KbMWOHP6LA1RwWynLiT6aWCoLGbrCAcZs40PFDVEAyQb0Qfd6ZwYV0\
+	    zGFZZWiGYX/9UBx34/1IFkF2IH4S0sfBP7vBDh2n1nFDAHpQg3QwJg7EsoQY\
+	    /ii0iGF8gReUsNMKoAG+RUgDgNswhzl+szVBoKM1+Eob6OqTlmLUoRmQ2EHc\
+	    lJEWh6yDbmzoAwYDwAAJBKAhMDpCLLrhA3RcwSkIfMchAJGPL1ipEOkYQx/Q\
+	    MYljVKMtmMgFKY4xDMeFQhDdAAxC9gGYgjCrE+jAkajQ8SdzBIAHPIiDG+JS\
+	    CPRooRvdKEQUviCNSBzDdcNY30MaUg1MbGIbU/lSJHonMMLUJx3ogEQxOgQE\
+	    sqAjGI2sD1WkYI4pSGopDaEKVbDAA3QUsBtxOIQlLAEIxtGIfY44kMui0Bo3\
+	    9AIVucjFMULhhkUIJDD7uFyyRvaONuDIUjgxhxra/lCkK/TgC+mIRCbqMoNu\
+	    OCIKoQDEMAABjXRA4xh/+EMlVlONXGRCKesIhSX0sQ0M/uIRv1hGOpQRsE4s\
+	    QhLm0IWjqLEz3myDDVJYxxaEMwAb+oMOAltHD2STOyx8IROOABQ4o8LPpUDl\
+	    ZW3phTYfsolIDEMQoVhEl/BXEPeMEyTmOEoG2yKqKBwBC1EgBSkyEYhhOAI6\
+	    24DG+/DoiH2kw3bv2MSfSLEORxiiDQygZdrQ8YtfdIMbY/yFOUikCzhwAR1q\
+	    UMU6ZtGvAGjGB3RbRxvKyAAAdDJAzTokFiJBilGuQ0qBUAN/QmEIaS4pFKhI\
+	    ByYYFAVLVNSihsjZQPrC/lF+ZPEvuQBJGxr5J964waCRIMQmpOkILcxgBvlg\
+	    ayiGwQ9+gIQfvcAEKRwhCE9EQhCSYgAD3tiJQXyDG6flhj8yqYtZwGEFXODC\
+	    Fl4BUn/wxx8+UAI6OrEOf7jhN21oi6ScYg6xYgmcgaJPKILzPnMYYklXTAcq\
+	    HtLZYwhCEMPIRbL68o98cBRZ+xgMSN6xCPG+oxNlKAMhCJEJO+XDElqgozTY\
+	    isdoVnYdvSAEKQTh2WNEwhOgU9YguPEN0/rPKdBqJDreOCkagZQHT1DCIhZB\
+	    lSm4gQGHrEo61oHe9BIiLW1IWzpC0RTJQgMQouoGcgBwAk94wrqCOIYn3NDR\
+	    /u0WZK/JsrE+yFuPegDmEWFYBCEiUQhAlMENbpiBIerhiPK8I5yV6AVZDlUJ\
+	    VGiodwD8BToIzA18MA+1UDJOFIwiqrRK7Ao5eMLzyLIIV4CRATZChxb+4Ax0\
+	    hAG9SAkEg9wBsygA4h2AaNcKTnDOXwxiEKhQLy07kVeObvcfHcWfe/a6V4I0\
+	    YxBhoIQjAKEFMZRBC1+ohyHAOYxjJGMQ3UAnOsHWO0ODzh3fWEY9erOMdZw2\
+	    d21gKAAeUua0vrEbSjDHFo5sDp9pMADoKIYs2NEOdhTjD2FAB6CHkQxSvO+Z\
+	    gXhfqdxAVKJOGWyd8AWkCfKPf+TSu1w8lkEKcj9e/vhDiG5YQRjs3AYGNXEa\
+	    hu6GN9rSG27/IqvTm5RmoAKtoomqN15Tj9W20AlpfGALcJCdJMSwhTJGgR3m\
+	    4AY74MGOZkciUExERzJazFlPvGMQbfhFP9Lxi0Tk4hfc4PaMA7NXcpM7WX7p\
+	    bhYjPfM+B+ILzJrGMtLJD6RMwx2Vq0c6hC7cZWRwGd6ohCi0bA3UEhViR8lG\
+	    1rNBDoe0IX/lq8EV1ACHdYBoG/4ohzOiRQ5ynOMd7YDHJXgK6JB3Qx+VWMY2\
+	    vKHvtqxgBSUZBFG/IY3ubmkgNbc5zm+O47y+h8l+UFYAhN6WfeecHzbNalpQ\
+	    YRRUrEbL3LCGabkhNmdk/lDr2UAHN45SJhfkCTrogIMatoCOaMD9IQGoRBgG\
+	    kQ54wOMPB3WElNAxH0PlYhpObEsY/P6OMLRmGfQr/BYpqw/Ek/tyNt6idtW9\
+	    pU444hikJGdPqbIO7+4jEW+uRjVQkYx1pD8Z6ffGN8hhDWtkmRvZaMYzHuGM\
+	    bJDlDzc4n7T4jn3oGhfoAS7IA+FIh0WIAmdwg0yIgkhIJ9t5iEMQhHfYBl/Y\
+	    Bh6zC8AqAwkIrVyIK0xIv/fAGY6qPsRzj0bLnJzpC7/aIjc4Bn84Bkd4B/bh\
+	    rC/hh074u26oht5YDUoQhU1YB0t4B0zoBW7YhXfAhWZoBhLhgRpAhxw4gRZA\
+	    /grQ+Y3OETNzaIYZeDiyCANy6IW6Sr52kAdMOoZ1QI96cINP+wJf4LAA8Lv0\
+	    Qz6704e+UrwUrD6cKTzMobSB8K6DyIVkeAcGySBS84RjOBjRosNNyAVREMJc\
+	    aLlcWAdU+IZ3eAZTKAVg6IY92AMUYIEcCIIWcINwKKAA4CcE64VHaAZ04AI4\
+	    YIdBOIc/IAXEagt4kIf+cwRLcARP0J8p2iwtOK8VYIAVoMN0qIbuwsMu0cMU\
+	    3BKOyj5Kg8aaeYfKusE0jLEC2gZceodkgMROS4R68IZ1yAU/qoQ2GDBnwIZS\
+	    YMc9OIVRIAFcAId4ACm1wB3skIVsIIUPgQN0IAdu/tgEQigDysuHdhgEBIqE\
+	    TTCH3SrEC8mHbSgDqCAEZKwGSWjBLuGHZnTGQDS8dpIGwvOr8QmJemOQtEkG\
+	    f+AtUnAFLdgGSpgCNRDH48MEMXCDS/wG3jAHeYiH8wEGncyGtDGKchAVEHuE\
+	    apAFTFgHLvgDaygGS3iIdqC8tgAEshKFXJAGSeiES6iGTSCGSPCFGEuG96uG\
+	    GVu3yukLytJIZ6SxvZIEOPAFXpC1euCTKAiMd/CGaRDHbeiHaJmGqliHdBEY\
+	    SiC2MsiFeoAlUWgD0cMEcJAHsliHeIDMIzmKcLAGXGAGoLGGSpCFdSAEF7CD\
+	    WtMjeAiu73gHUaoGBzkB/nh7toeoBCd6v+Mrv8rJvoxMy+rrw+yDS2YBCaSQ\
+	    sHWQHb/LmcHAkW5YgY94v2RAB0o4nRDSEHmDIlHAjm/whh/MkXSIB52Mhygz\
+	    h3fAA8iUB3k4E6rwB1nohRYwA3D4BkxADxiIgRjQsDVYA0SgBWmwBXh7B3cg\
+	    jGJchGpIhnRIBky4uZu5nNpMwRzLGVkbDJBqC3MoIKg4iiOjIeDYBmngC3MI\
+	    S3TIBHMYskJAim44j5rwhY+5S2/ABZFDB1zQhneQO0t5zHDQyVvggorDIHRo\
+	    AUjoGkJIhkQQg1joAqpIG0Z4BW/oBmewg3rwhRWYIZIIg27sB43Kmfs5CAJV\
+	    /kvvGi8F1bBO+g8biRYaCq3QCoDv+A7OzIVCsIRMKITtKQx0+AJMuIRE+CPp\
+	    RIVlyIaLCoV7+ISdTIdioMd4MENrUIEW2IJucIqqaAFlyIZz6Dy4SgdZyxFG\
+	    OApvuAdYowYucAMJiAIH2YZEyCXLoawbk9Lq45KCYNT6eIqgARqvuZsWsaGz\
+	    U61NkIRyyYQ4KILtccxqSIQMaYN6+AZPCMuLQocLtBRUwIMxctF2sINgAAdl\
+	    YIZeKKMAWAd2eAR4+AbKgwdZe4d0GIVRAAlncAZyeAdeYLgvSbF3wJy/qJw7\
+	    /NTqO5Z9sNa26CV0ULl0UC1/cAd3OKS0aAjcASiQ/riCQjiEODiDW0kLqUuE\
+	    RMAE5HiHafAGT+iGUEAHh/UEQ6gGWEAHeQgHPi2HFrCDXkCHP4gG/8mdb+g9\
+	    eVgEdvCHejCDpGuLfjiKzOCFhVhX+Lgc2UTXdEW8cyWIeqhOyiOVqKQ8d7hW\
+	    zDsyzxm/RsKCQyiEDDLYgk0EgXmKqUjTSZiSbjCEFHPRcLjYeOAEOBADbDoB\
+	    M3CIZdC4dqgHv5sPdi0vaZA5guiuHLuZnNmit70Zm7XN95C1kfLZqKwHfvAF\
+	    ytMHDcMRf9CM3CGMpwCOpTCHQSSFT0OKqhCY60gOgSmGi7XYeGAHywWHZ7CG\
+	    eMiGXoiC3juHcniH8hun/m3AosVD3be9nH6gW3UtvHyICc0gSF7ghai8h3UA\
+	    xHQ4iJCgjyMDDq7iD6dog/BEB/SahuOtRUPYnapFSbM6g0eAhXKwWIvluHjo\
+	    vUG4hDDABGc4B3D4hEXrKL0yPNSF245qXXXdEpDAibbIB599h3sgB4Lc2354\
+	    h++ooaXIQqeYlqnAgk0IOnQghP06gyo4gzMwBHPwB4dAB2+oA2TIpKstB8vN\
+	    BnM4B45jB22oh/pZvGiENGVstH04X/SFj1zQDHSoB1zK27YwCjVoC1/oho9c\
+	    AUu1igByA66AkkxSMKqogh3ehiqQ2h2ugkApDjc4O6ztBqwNh3YIB4EpB3EA\
+	    /gdt0Iac+4tzSwiOzJybybkQ1sPGU4iP8lkem4d7IIwtIL+2wAcH+bsyyR1o\
+	    KTN/IBpy2ocqOKSpmAQ+COJACJVuUOCjkAVk8GMkTuJyaGJxeAcuOrcXXEEN\
+	    pqx96Afq0+KNvKXx2tm8vYd5GAd6SIdxsIdu4I90mNERghYFxgly2saautJt\
+	    kJIxAIQgPgPNcIhtwIEXiIE6qANZkAW18ONy4AfC077bFN8uQeRHrs10Kwjz\
+	    aqdFYN95qJx0uIdouIZtoAdscAVzIIhqXsh8GBlLyQUHaYNnxodvxgeQAATl\
+	    RYeANYRxRodzrgLsKIYYwIEYkOUYeIdw7KXxhcZp/gTEJhVmm80lv1gX3+wE\
+	    XLEdlY0GfcCGcRAVawaJfWiDkSAGDDKHfukEbLiGa8CHScCHfUCHfQhYQaAS\
+	    QwjYnqqCJUKKZYiBbojlF3iHGOAFdCPmcnXkfT5fLcK5TtCwm06H2jWHm9Gg\
+	    WGAFu7EUcxgHdfCHGSAGeOsEnDhqNbCHcciBOAiFb47bX12HDvJoJnuHII4E\
+	    Wzi2IRiC9pRladCitoXGLJJpYb5DQJxiC8LSL56HRRiHn06FVPCDuV4HdVCH\
+	    aziTKWgLe3gHdegGTWADqMYHr8s+ZQkJGzyDOKiCOAAETwjg3XSHIchgnNuo\
+	    wKDNsxbmD0aI3VqHeI1K/n2YB3Tw6VRghdN+h59mg7xmDBMoDXWYhFRQhFYI\
+	    Aj/AB3cI0IOoh0Mo4DMYZ0Fwh3WAhSFAAzRwhy5Ja+T2C82WadL1528NrraY\
+	    B9FOh3COBXOIhXWoa1Zgg0ZYBza4p954gycgAzmgAy8IZ5ljPI76COW1LmeQ\
+	    hm3QYGR5XeY+636uHwvy2TFKB7Nc1HqYazp4g0Z4B/BuhPGuhwO/AylggYw+\
+	    N8UzUL+4n/KLNJvZIta177OONMAADMJi0LbQhx7726SrB3Wgg0Y4cClgg21o\
+	    hCzIhzd4gzlQBCnIgXDrZcy5bPh4RnPFmQy3b5qWtJzhhX7ohn2Y7nlIh+m2\
+	    /imQkgM5IHA2QAc2eAcCbwQ2kIMc0GRIo7HtK1cWFF/KQksfZ+5bkuL3gIN5\
+	    WAddMIdZ0AU3Rtt7UgRc6QSgMockyAEWYIFewQf1vsOQjD4t2iLlltl8EHMx\
+	    f9s+N7cO1+Pv+O+QSAUCBwl9WIH6yPMkYAE/GIcTNtAHP2xAr+IpPgh+wPBC\
+	    93E8bEG1/gtz6IdVz6B9WAd7sIfK1gfSsIcnSIEUyHN84GJATzcdx/FG84fM\
+	    JnUx52JB1y7hnDGzvEOQsAd1YHFNXrQbwx9HG/Zqb1217kN1Q+4/dA8bAQm8\
+	    1gR6sAcsPtc/t/ZzP99pzKL7mT7D68Nspgd1oAd6qaAfXi9fdMd3ut3yQ55v\
+	    fdjO0Z0HewCCMte5nMn3g09XF7Sxfs6xavaLf6/m0QVE0sUlhLf4T73DmbXn\
+	    LOKx+znhc/2u5b74kZdSw6vi28TZm1s3aCT5lk/4vsr2mnFS9+irE3T5m7fZ\
+	    lH8PDs94XAIMYcf5oE/LmM94v4J5FxT6pCdQKKV5kO+ruAV6pZd6FcS56cOl\
+	    msf6qdd6PewHnIF5LD63rd/ngAAAOw==	
+	
+    }
+    
+    # ShowMidpaneTools begins here 
+    
+    set wr $parent
+    
+    #This stuff ends up on the "Images" tab of the middle window in chellyGUI
+    set ICbackgroundcolor "LightSteelBlue1"
+    set IC [canvas $wr.imagecanvas -height 500 -bg "$ICbackgroundcolor"];     pack $IC -fill both -expand 1
+    
+    #This is the button frame window which will pack into the canvas at each brain
+    foreach n {SpaceImage AnatomicalImage FunctionalImage} {
+	
+	set bf_$n [frame $midpane.viewbuttonsframe_$n -bg $ICbackgroundcolor -borderwidth 2 -relief groove]
+	pack $midpane.viewbuttonsframe_$n
+	set bftf [frame $midpane.viewbuttonsframe_$n.topfr -bg $ICbackgroundcolor]; pack $bftf -padx 4 -pady {1 3}
+	set bfbf [frame $midpane.viewbuttonsframe_$n.bottomfr -bg $ICbackgroundcolor]; pack $bfbf -padx 2 -pady {1 3}
+	
+	set viewer1but [eval "button $bftf.view1but -image smallviewericon -height 16 -width 24\
+			    -command {$this sendSelectionToDisplay 1 -1 $n } "]
+	set viewer1butlabel [label $bftf.label1 -text "RF Viewer" -font {helvetica 13 bold} -bg "$ICbackgroundcolor"]
+	pack $viewer1but $viewer1butlabel -side left -pady {3 0}
+	
+	set viewer2but [eval "button $bfbf.view2but -image smallviewericon -height 16 -width 24\
+			    -command {$this sendSelectionToDisplay 2 -1 $n } "]
+	set viewer2butlabel [label $bfbf.label2 -text "TR Viewer" -font {helvetica 13 bold} -bg "$ICbackgroundcolor"]
+	pack $viewer2but $viewer2butlabel -side left -pady {0 2}
+	
+	
+	if {$n != "SpaceImage"} {
+	    
+	    set REFcheckbox [checkbutton $midpane.viewbuttonsframe_$n.refcheckbut \
+				 -text "Ref Space" -variable REF_$n -bg $ICbackgroundcolor]
+	    pack $REFcheckbox -side top -pady {0 3}
+	    
+	    eval "$viewer1but configure -command {    if { $[subst REF_$n] } {$this sendSelectionToDisplay 1 1 $n} else {$this sendSelectionToDisplay 1 -1 $n } }   "
+	    
+	    eval "$viewer2but configure -command {    if { $[subst REF_$n] } {$this sendSelectionToDisplay 2 1 $n} else {$this sendSelectionToDisplay 2 -1 $n } }   "
+	    
+	    
+	};# End "if != SpaceImage
+	    
+	};# End foreach
+	
+    
+    
+    
+    
+    #**************************************************
+    set rbX 165
+    set rbY 45
+    set refbrainBG [$IC create image $rbX $rbY -image brainbg -anchor nw -tag refAREA]
+    set refbrainTITLE [$IC create text [expr $rbX+80] [expr $rbY+130] -text Space \
+			   -fill blue -font {times 20 bold} -tag refAREA -anchor e]
+    set refbrainTEXT  [$IC create text [expr $rbX+65] [expr $rbY+52] -text "Not Set" \
+			   -fill grey61 -activefill yellow -font {helvetica 15 bold} -tag refTEXT]
+    
+    set refbrainBUTTONS [$IC create window [expr $rbX+145] [expr $rbY+140] -window $bf_SpaceImage]
+    #**************************************************
+    set abX 25
+    set abY 265
+    set anatomicalbrainBG [$IC create image $abX $abY -image brainbg -anchor nw -tag anatomAREA]
+    set anatomicalbrainTITLE [$IC create text  [expr $abX+90] [expr $abY+130] -text Anatomical \
+				  -fill blue -font {times 19 bold} -tag anatomAREA -anchor e]
+    set anatomicalbrainTEXT  [$IC create text [expr $abX+65] [expr $abY+52] -text "Not Set" \
+				  -fill grey61 -activefill yellow -font {helvetica 15 bold} -tag anatomTEXT]
+    
+    
+    set anatomicalbrainBUTTONS [$IC create window [expr $abX+153] [expr $abY+146] -window $bf_AnatomicalImage]
+    #**************************************************
+    set fbX 315
+    set fbY 265
+    set funcbrainBG [$IC create image $fbX $fbY -image brainbg -anchor nw -tag funcAREA]
+    set funcbrainTITLE [$IC create text  [expr $fbX+90] [expr $fbY+130] -text Functional \
+			    -fill blue -font {times 19 bold} -tag funcAREA -anchor e]
+    set funcbrainTEXT  [$IC create text [expr $fbX+65] [expr $fbY+52] -text "Not Set" \
+			    -fill grey61 -activefill yellow -font {helvetica 15 bold} -tag funcTEXT]
+    
+    set funcbrainBUTTONS [$IC create window [expr $fbX+150] [expr $fbY+146] -window $bf_FunctionalImage]
+    #**************************************************
+    
+    set arrowlinebgcolor grey80
+    #-----Func --> Space -----------------------------------------------------------------
+    $IC create line [expr $rbX + 145] [expr $rbY + 50] \
+	[expr $rbX + 190] [expr $rbY + 55] \
+	[expr $fbX + 95 ] [expr $fbY - 85] \
+	[expr $fbX + 80 ] [expr $fbY - 6] \
+	-tag Func2SpaceBG -smooth true  -splinesteps 20 -width 18 \
+	-arrow first -arrowshape {15 28 10} -fill $arrowlinebgcolor
+    
+    
+    
+    
+    #-----Anat --> Space -----------------------------------------------------------------
+    $IC create line [expr $rbX - 10] [expr $rbY + 50] \
+	[expr $rbX - 55] [expr $rbY + 55] \
+	[expr $abX + 35 ] [expr $abY - 85] \
+	[expr $abX + 50 ] [expr $abY - 6] \
+	-tag Anat2SpaceBG -smooth true  -splinesteps 20 -width 18 \
+	-arrow first -arrowshape {15 25 10} -fill $arrowlinebgcolor
+      
+    #menus associated with the right click binding
+    #Space Image
+    set rpp_space [menu $IC.spacemenu -tearoff 0]
+    eval "$rpp_space add command -label \"Clear\" -command { set \"[itcl::scope SpaceImage]\" -1; $this updateRightCanvasDisplay } -underline 0"
+
+    #Anatomical Image
+    set rpp_anat [menu $IC.anatmenu -tearoff 0]
+    eval "$rpp_anat add command -label \"Clear\" -command { set \"[itcl::scope AnatomicalImage]\" -1; $this updateRightCanvasDisplay } -underline 0"
+
+    #Functional Image
+    set rpp_func [menu $IC.funcmenu -tearoff 0]
+    eval "$rpp_func add command -label \"Clear\" -command { set \"[itcl::scope FunctionalImage]\" -1; $this updateRightCanvasDisplay} -underline 0"
+    
+    #Bind a right click on the pic or text for each of the three to the popup menus just created
+    eval "$IC bind refPIC <3> { $this bindxRightPane %W %x %y $rpp_space }"
+    eval "$IC bind refTEXT <3> { $this bindxRightPane %W %x %y $rpp_space }"
+    eval "$IC bind anatomPIC <3> { $this bindxRightPane %W %x %y $rpp_anat }"
+    eval "$IC bind anatomTEXT <3> { $this bindxRightPane %W %x %y $rpp_anat }"
+    eval "$IC bind funcPIC <3> { $this bindxRightPane %W %x %y $rpp_func }"
+    eval "$IC bind funcTEXT <3> { $this bindxRightPane %W %x %y $rpp_func }"
+	}   
+
+
+::itcl::body chellyGUI::OCanvasInitialize { canvas } {
+    
+    ##########################################################################################
+    ###########################                                     ##########################
+    ###########################         Overlay Tab Canvas          ##########################
+    ###########################                                     ##########################
+    ##########################################################################################
+
+    set OCanv $canvas
+    
+    set OCdispX 15
+    set OCdispY 20
+    set OC_BG [$OCanv create image $OCdispX $OCdispY -image brainbg -anchor nw -tag ocAREA]
+    set OC_TITLE [$OCanv create text [expr $OCdispX+160] [expr $OCdispY+145] -text "Resliced Image" \
+		      -fill blue -font {times 20 bold} -tag ocAREA -anchor e]
+    set OC_TEXT  [$OCanv create text [expr $OCdispX+65] [expr $OCdispY+52] -text "Empty" \
+		      -fill grey61 -font {helvetica 15 bold} -tag ocTEXT]
+    set OC_FUNC  [$OCanv create text [expr $OCdispX+375] [expr $OCdispY+20] -text "Functional" \
+		      -fill grey61 -font {helvetica 15 bold} -tag ocFUNC]
+    set OC_ANAT  [$OCanv create text [expr $OCdispX+375] [expr $OCdispY+110] -text "Anatomical" \
+		      -fill grey61 -font {helvetica 15 bold} -tag ocANAT]
+    set OC_SPACE  [$OCanv create text [expr $OCdispX+205] [expr $OCdispY+60] -text "Space" \
+		       -fill grey61 -font {helvetica 15 bold} -tag ocSPACE]
+    
+    set doublearrowcolor "LightSteelBlue"
+    $OCanv create line [expr $OCdispX + 340] [expr $OCdispY + 40] \
+ 	[expr $OCdispX + 338] [expr $OCdispY + 50] \
+	[expr $OCdispX + 325] [expr $OCdispY + 55] \
+ 	[expr $OCdispX + 300] [expr $OCdispY + 60] \
+	-tag OCtopline -smooth true  -splinesteps 20 -width 12 \
+	-arrow none -arrowshape {15 18 8}  -fill "$doublearrowcolor"
+
+    $OCanv create line [expr $OCdispX + 340] [expr $OCdispY + 80] \
+ 	[expr $OCdispX + 338] [expr $OCdispY + 70] \
+	[expr $OCdispX + 325] [expr $OCdispY + 65] \
+ 	[expr $OCdispX + 300] [expr $OCdispY + 60] \
+	-tag OCbotline -smooth true  -splinesteps 20 -width 12 \
+	-arrow none -fill "$doublearrowcolor" -arrowshape {15 18 8}
+    
+     $OCanv create line [expr $OCdispX + 289] [expr $OCdispY + 60] \
+ 	[expr $OCdispX + 290] [expr $OCdispY + 60] \
+ 	-tag OCarrow -smooth true  -splinesteps 20 -width 1 \
+ 	-arrow first -arrowshape {15 18 13}  -fill "$doublearrowcolor"
+
+}
+
+
+#------------------------------------------------------------------------------------------
+#------------------------------------------------------------------------------------------
+#  This is the most important method of chellyGUI - it creates all the frames and widgets
+#------------------------------------------------------------------------------------------
+#------------------------------------------------------------------------------------------
+
+::itcl::body chellyGUI::ShowManager {pw surgerygadget0 menubase } {
+
+   
+    #Set a variable to hold the top window
+    set mdTopWidget $pw
+    set surgerygadget $surgerygadget0
+    
+    #---------------------------------------------------------------------------
+    #Create a top frame to hold the panedwindow and the status bar frame
+    set top [frame $mdTopWidget.topframe -width 1100 -height 700]
+    pack $top -expand 1 -fill both
+    pack propagate $top 0
+    
+    
+    #---------------------------------------------------------------------------
+    #Show the Status Bar at the Bottom - pack it into the $top frame
+    set statusbar [frame $mdTopWidget.status -borderwidth 3 -relief ridge -height 20]
+    pack $mdTopWidget.status -in $top -side bottom -fill x
+    #Add a label
+    
+    set statusLabel [label $statusbar.l -text "Status Bar" -fg black -bg [$statusbar cget -bg]]
+    pack $statusLabel -side left
+    
+    #Create a paned window - pack it into the $top frame
+    panedwindow $mdTopWidget.mainpane -orient horizontal -showhandle 1 \
+	-borderwidth 2 -relief raised -sashwidth 4 -sashpad 1 \
+	-handlesize 5 -handlepad 50
+    pack $mdTopWidget.mainpane -in $top -expand 1 -fill both
+
+
+    set LeftPaneColor white
+    set MidPaneColor "light steel blue"
+    set RightPaneColor "medium sea green"
+    
+    #Create the three frames in paned window
+    set leftpane [frame $mdTopWidget.mainpane.left -bg $LeftPaneColor -width 375]
+    set midpane [frame $mdTopWidget.mainpane.middle -bg $MidPaneColor -width 600 -height 50]
+    set rightpane [frame $mdTopWidget.mainpane.right -bg $RightPaneColor -width 200]
+    
+    pack propagate $midpane 0;  #Don't let window shrink to wrap buttons; we'll let the buttons grow
+    pack propagate $leftpane 0;
+    pack propagate $rightpane 0;
+    
+    $mdTopWidget.mainpane add $leftpane
+    $mdTopWidget.mainpane add $midpane -minsize 300
+    #    $mdTopWidget.mainpane add $rightpane
+    
+    
+    ShowTextBox $rightpane
+    
+    
+    
+    
+    #------------------------------------------------------------------------------------------
+    #Left Pane
+    #------------------------------------------------------------------------------------------
+    #Initialize the Left Pane with tree in it
+    #Put a visualization tree in the left frame (Tree name $leftpane.w)
+    #Create a labelframe to go around tree
+    
+    
+    set treeframe [ labelframe $leftpane.treeframe -bg $LeftPaneColor -text "Image List"  ]
+    pack $treeframe -fill both -expand true -padx 5 -pady 2
+    
+    #Set a variable "vistree" to hold the tree
+    set vistree $treeframe.w
+#    focus $treeframe
+    #Create the tree and its associated scrollbar and pack into treeframe
+    
+    eval "Tree::create $vistree -bg $LeftPaneColor -width 170 -yscrollcommand {$treeframe.sb set}"
+    
+    eval "scrollbar $treeframe.sb -orient vertical -command { $treeframe.w yview }"
+    pack $vistree -side left -fill both -expand 1 -padx {4 0} -pady {0 0}
+    focus $vistree
+    pack $treeframe.sb -side left -fill both -padx {0 3} -pady {0 3}
+    
+    set grabButton [eval "button $leftpane.gb -text \"Grab an Object from Viewer\" -command { $this showGrabButtonDialog }"]
+    pack $grabButton -fill x
+    
+    #---------------------------------------------------------------------------
+    #Create a struct::tree object to hold pointer keys to the image objects
+    #This is the heart of the tree -- RealTreex
+    
+    set RealTree [struct::tree [pxvtable::vnewobj]]
+    #Sets a root for the tree
+    $RealTree rename root Data
+    set NodeIDs(/Data) [$RealTree rootname]
+    
+    #---------------------------------------------------------------------------
+    #Add the default object set to the tree
+    AddDefaults $RealTree
+    set TreeChanged 0
+    
+    
+    #Update the Visualization Tree with the contents of the real tree
+    updateVisTree $vistree $RealTree 
+    findTransforms $RealTree
+    
+    
+    #------------------------------------------------------------------------------------------
+    #---------------------------------------------------------------------------
+    #Create a menubar at the top
+    #---------------------------------------------------------------------------
+    #------------------------------------------------------------------------------------------
+
+    set menucolor "#ede9e3"
+    set menuactivebgcolor "#ede9e3"
+
+    catch {
+	set menucolor [option get $mdTopWidget background ""]
+	if { $menucolor == "" } {
+	    set menucolor white
+	}
+	set menuactivebgcolor [option get $mdTopWidget background ""]
+	if { $menuactivebgcolor == "" } {
+	    set menuactivebgcolor "#6666cc"
+	}
+    }
+
+    set mdmenubar $menubase
+    # [ $surgerygadget cget -menubase ]
+    $mdmenubar configure -background $menucolor
+    $mdmenubar configure -activebackground $menuactivebgcolor
+
+    foreach m {File Edit Tools Datatree Patient Image Options} {
+	set $m [menu $mdmenubar.m$m -tearoff 0]
+	$mdmenubar add cascade -label $m -menu $mdmenubar.m$m -background $menucolor 
+    }
+    
+    makeFileMenu $File
+    makeEditMenu $Edit
+    makeToolsMenu $Tools
+    makeDataMenu $Datatree
+    makePatientMenu $Patient
+    
+    makeImageMenu $Image
+    
+    #Add a couple extra options to the "Image" menu
+    $Image add separator
+    eval "$Image add command -label \"Set As Space/Anatomical Image\" -command { $this setSelectionSpace $RealTree; $this setSelectionAnatomical $RealTree} -activebackground \"$menuactivebgcolor\""
+    eval "$Image add command -label \"Set As Functional Image\" -command { $this setSelectionFunctional $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$Image add command -label \"Set As Space ONLY\" -command { $this setSelectionSpace $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$Image add command -label \"Set As Anatomical ONLY\" -command { $this setSelectionAnatomical $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$Image add command -label \"Set As Space and Functional\" -command { $this setSelectionSpace $RealTree; $this setSelectionFunctional $RealTree } -activebackground \"$menuactivebgcolor\""
+
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$Image index end]} {incr i} {
+	$Image entryconfigure $i -background $menucolor 
+    }
+    #--------------------------------------------------------------------------------
+    
+#    makeViewMenu $View
+    makeOptionsMenu $Options
+   
+    
+
+    #------------------------------------------------------------------------------------------
+    #    Old, frame-based menu
+    #------------------------------------------------------------------------------------------
+    #    $mdmenubar configure -width 400 -height 50 -relief raised -background $menucolor
+    
+    
+    #     #------------------------------------------------------------------------------------------
+    #     menubutton $mdmenubar.file -text File -menu $mdmenubar.file.m -underline 0\
+	# 	-background $menucolor -activebackground "$menuactivebgcolor"
+    #     pack $mdmenubar.file   -side left
+    
+    #     makeFileMenu [menu $mdmenubar.file.m -tearoff 0]
+    
+    #     #------------------------------------------------------------------------------------------
+    #     menubutton $mdmenubar.edit -text Edit -menu $mdmenubar.edit.m -underline 0\
+	# 	-background $menucolor -activebackground "$menuactivebgcolor"
+    #     pack $mdmenubar.edit   -side left
+    
+    #     makeEditMenu [menu $mdmenubar.edit.m -tearoff 0]
+    
+    #     #------------------------------------------------------------------------------------------
+    #     menubutton $mdmenubar.tools -text Tools -menu $mdmenubar.tools.m -underline 0\
+	# 	-background $menucolor -activebackground "$menuactivebgcolor"
+    #     pack $mdmenubar.tools  -side left
+    
+    #     makeToolsMenu [menu $mdmenubar.tools.m -tearoff 0]
+    
+    #     #------------------------------------------------------------------------------------------
+    
+    #     menubutton $mdmenubar.datatree -text Datatree -menu $mdmenubar.datatree.m\
+	# 	-underline 0 -background $menucolor -activebackground "$menuactivebgcolor"
+    #     pack $mdmenubar.datatree   -side left
+    
+    #     set datatreemenu [ menu $mdmenubar.datatree.m -tearoff 0 ]
+    
+    #     makeDataMenu $datatreemenu
+    
+    #     #------------------------------------------------------------------------------------------
+    #     menubutton $mdmenubar.patient -text Patient -menu $mdmenubar.patient.m\
+	# 	-underline 0 -background $menucolor -activebackground "$menuactivebgcolor"
+    #     pack $mdmenubar.patient -side left
+    
+    #     set patientmenu [eval "menu $mdmenubar.patient.m -tearoff 0 \
+	#  -postcommand { $this menuActivation $mdmenubar.patient.m patient}   "]
+    #     makePatientMenu $patientmenu
+    
+    #     #------------------------------------------------------------------------------------------
+    #     menubutton $mdmenubar.image0 -text Image -menu $mdmenubar.image0.m\
+	# 	-underline 0 -background $menucolor -activebackground "$menuactivebgcolor"
+    #     pack $mdmenubar.image0 -side left
+    
+    #     set imagemenu [eval "menu $mdmenubar.image0.m -tearoff 0 \
+	#  -postcommand { $this menuActivation $mdmenubar.image0.m image}   "]
+    
+    #     makeImageMenu $imagemenu
+    
+    #     #------------------------------------------------------------------------------------------
+    #     menubutton $mdmenubar.view -text View -menu $mdmenubar.view.m -underline 0\
+	# 	-background $menucolor -activebackground "$menuactivebgcolor"
+    #     pack $mdmenubar.view -side left
+    
+    #     set viewmenu [menu $mdmenubar.view.m -tearoff 0]
+    
+    #     makeViewMenu $viewmenu
+    
+    
+    #     #------------------------------------------------------------------------------------------
+    #     menubutton $mdmenubar.options -text Options -menu $mdmenubar.options.m -underline 0\
+	# 	-background $menucolor -activebackground "$menuactivebgcolor"
+    #     pack $mdmenubar.options -side left
+    
+    #     set optionsmenu [menu $mdmenubar.options.m -tearoff 0]
+    
+    #     makeOptionsMenu $optionsmenu
+    
+    #     #------------------------------------------------------------------------------------------
+    
+ 
+
+    #------------------------------------------------------------------------------------------
+    #Middle Pane
+    #------------------------------------------------------------------------------------------
+    #Initialize the Middle Pane with buttons and display space
+    #Create frame to hold both buttons next to each other horizontally (tbf = "two-button frame")
+    set tbf [frame $midpane.twoButtonFrame -bg $menucolor]
+    
+    #Create indiv. frame for each button
+    set leftBF [frame $tbf.leftButtonFrame]
+    pack $leftBF -side left -fill x -expand 1
+
+    
+    #Create buttons to occupy their respective frames
+    eval "button $leftBF.l1 -text \"Set Space and Anatomical Image\" -command { $this setSelectionSpace $RealTree; $this setSelectionAnatomical $RealTree }"
+    eval "button $leftBF.l2 -text \"Set Anatomical Image\" -command { $this setSelectionAnatomical $RealTree }"
+    eval "button $leftBF.r3 -text \"Set Functional Image\" -command { $this setSelectionFunctional $RealTree }"
+    pack $leftBF.l1 $leftBF.l2 $leftBF.r3 -fill x -expand 1 -side left
+    
+    #pack the whole two-bar frame (tbf)
+    pack $tbf -side top -fill x -padx {3 3} -pady {2 0}
+    
+    set rbfr [frame $midpane.reslframe -bg $menucolor]; pack $rbfr -side top -fill x -padx {3 3}
+    eval "button $rbfr.big -text \"Reslice Images\" -command { $this Reslice }"
+    pack $rbfr.big -side left -fill x -expand 1
+    
+    #Interpolation mode menu
+    menubutton $rbfr.modemenu -text Mode -menu $rbfr.modemenu.m\
+	-underline 0 -background $menucolor -activebackground "$menuactivebgcolor" -relief raised
+    pack $rbfr.modemenu -side right -padx {2 0} -pady {0 2}
+    
+    set modemenu [menu $rbfr.modemenu.m -tearoff 0 ]
+    eval "$modemenu add radio -label Linear -variable {[itcl::scope reslmode]} -value 1"
+    eval "$modemenu add radio -label Cubic -variable {[itcl::scope reslmode]} -value 3"
+    eval "$modemenu add radio -label \"Nearest Neighbor\" -variable {[itcl::scope reslmode]} -value 0"
+
+    #------------------------------------------------------------------------------------------
+    #Right Pane
+    #------------------------------------------------------------------------------------------
+    
+    # (Empty)
+    
+    #------------------------------------------------------------------------------------------
+    #Event Bindings
+    #Set behavior for events in the tree						 
+    #------------------------------------------------------------------------------------------
+    set popup [menu $vistree.pop -tearoff 0]
+    makeImageMenu $popup
+    
+    set surfacepopup [menu $vistree.surfpop -tearoff 0]
+    makeSurfaceMenu $surfacepopup
+    
+    set electrodepopup [ menu $vistree.elecpop -tearoff 0]
+    makeElectrodeMenu $electrodepopup
+
+    set patientpopup [menu $vistree.patientpop -tearoff 0]
+    makePatientMenu $patientpopup
+    $patientpopup add separator
+    eval "$patientpopup add command -label \"Add an Image as Child\" -command { $this addImageToTree }"
+    for {set i 0} {$i <= [$patientpopup index end]} {incr i} {
+	$patientpopup entryconfigure $i -background $menucolor 
+    }
+
+
+    set rootpopup [menu $vistree.rootpop -tearoff 0]
+    makeDataMenu $rootpopup
+    if { 0 } {    
+    set imageutility [ bis_guitreeimageutility \#auto ]
+    $imageutility InitializeFromContainer $this
+    set w $mdTopWidget.$imageutility
+
+    set imageutility [ $imageutility GetThisPointer ]
+    $imageutility CreateGUI $w 
+    set imageUtilityMenu [menu $mdmenubar.imageutitily -tearoff 0]
+    $mdmenubar add cascade -label ImageUtility -menu $imageUtilityMenu -background $menucolor
+    $imageutility AddToMenuButton $imageUtilityMenu
+    }
+    
+    #Bind button clicks in the tree
+    eval "$vistree bind x <1> { $this bindx1 %W %x %y }"
+    eval "$vistree bind x <Button1-Motion> { $this bindxmotion1 %W %x %y }"
+    eval "$vistree bind x <ButtonRelease-1> { $this bindxrelease1 %W %x %y 1 }"
+    eval "$vistree bind x <Control-ButtonRelease-1> { $this bindxrelease1 %W %x %y 0 }"
+    eval "$vistree bind x <Control-1> { $this bindxcontrol1 %W %x %y }"
+    eval "$vistree bind x <Double-1>  { $this bindxdouble1 %W %x %y }"
+    eval "$vistree bind x <3> { $this bindx3 %W %x %y }"	
+    eval "$vistree bind x <Control-Key-x> { $this bindxControlX %W %K %N }"
+    eval "$vistree bind x <Control-KeyPress-c> { $this bindxControlC %W %K %N }"
+   
+
+    update
+    
+};#End ShowManager method def
+
+::itcl::body chellyGUI::Debug { } {
+    
+    
+    #     pxtkconsole
+    
+    #     foreach p [array names NodeIDs] {
+    # 	pxtkprint "$p\n"
+    #     }
+    
+    #    pxtkprint "--------------------------------------------------------------------------------\n"
+    
+}
+
+
+##########################################################################################
+#                             This ends the chellyGUI class                              #
+##########################################################################################
+#
+#
+#
+#
+#
+# A couple static procs
+#
+proc Compute { image_ref image_trn { mode linear } } {
+    
+    set dim1 [ [ $image_ref GetImage ] GetDimensions ]
+    set dim2 [ [ $image_trn GetImage ] GetDimensions ]
+    if { [lindex $dim2 0 ] <2 || [ lindex $dim1 0 ] < 2 } { 
+	::pxtclutil::Warning "No Images in Memory\n Cannot Compute Registration!"
+	return  0
+    }
+    
+    
+    if { $mode == "linear" } {
+	set swindow "Linear Reg"
+    } else {
+	set swindow "NonLinear Reg"
+    }
+    
+    $viewer1  SetImageFromObject $image_ref $this
+    $viewer2  SetImageFromObject $image_trn $this
+    
+    $overlaycontrol EnableRegistrationButtons
+    $overlaycontrol ShowWindow $swindow
+    $overlaycontrol SetAutoSave 0
+}
+
+proc GrabRegistration { image_ref image_trn } { 
+    
+    set n0 [ file dirname [ ${image_ref} cget -filename ] ]
+    set n1 [ file tail [ ${image_trn} cget -filename ] ]
+    set n2 [ file tail [ file rootname [ ${image_ref}  cget -filename ] ] ]
+    set suffix "matr"
+    
+    if { [ $newtr IsA "vtkGridTransform" ] == 1 } {
+	set suffix "grd"
+    } elseif { [ $newtr IsA "vtkpxComboTransform" ] == 1 } {
+	set suffix "grd"
+    } elseif { [ $newtr IsA "vtkThinPlateSplineTransform" ] == 1 } {
+	set suffix "tps"
+    }
+    
+    set mname [ file join $n0 "${n1}_${n2}.${suffix}" ]
+    set ok 1
+    
+    
+    set newtr [ [pxitcltransform \#auto ] GetThisPointer  ]
+    $newtr configure -filename $mname
+    set tr [ $overlaycontrol GetTransformation ]
+    $newtr  CopyTransformation 
+    $newtr  Save ""
+    return $newtr
+}
+
+# ------------------------------------------------------------------
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/ElectrodeAttributeTemplate.ele b/bioimagesuite30_src/bioimagesuite/datatree/ElectrodeAttributeTemplate.ele
new file mode 100644
index 0000000..facad4f
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/ElectrodeAttributeTemplate.ele
@@ -0,0 +1,6 @@
+#Electrode Attribute Description File
+#----------------------------------------------------------------------------------------------------
+# (space or tab delimited)
+electrode# name brain exclude theta_up theta_down beta_up beta_down gamma_up
+#----------------------------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/biodatatree.tcl b/bioimagesuite30_src/bioimagesuite/datatree/biodatatree.tcl
new file mode 100755
index 0000000..283022c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/biodatatree.tcl
@@ -0,0 +1,119 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# 	$Id: pxitclbrainregister.tcl,v 1.3 2003/02/26 16:29:58 papad Exp $	
+
+# This is the main application
+
+lappend auto_path [file dirname [info script]]
+package require pxitclchellypackages 1.0
+package require dsitcltree 1.0
+package require pxitclbrainregister 1.0
+package require pxitclbraintreegadget 1.0
+
+
+
+wm withdraw .
+set breg [ pxitclbrainregister \#auto 0 ]
+$breg configure -enable_multi2gadget 0
+$breg configure -enable_multigadget 0
+$breg configure -enable_csigadget 1
+$breg configure -enable_fmrigadget 0
+$breg configure -enable_electrodecontrol 1
+$breg configure -enable_electrodecontrol2 1
+$breg configure -enable_vvlink 1
+$breg configure -donotcreatemenu 1
+$breg configure -appname "BioImage Suite::Datatree Tool"
+
+$breg Initialize .[pxvtable::vnewobj ]
+    
+[ [ $breg GetOrthoViewer ref ] GetViewer ] SetEnableRendering 1
+[ [ $breg GetOrthoViewer ref ] GetViewer ] UpdateDisplay
+[ [ $breg GetOrthoViewer trn ] GetViewer ] SetEnableRendering 1
+[ [ $breg GetOrthoViewer trn ] GetViewer ] UpdateDisplay
+
+set viewer1 [ $breg GetOrthoViewer ref ]
+set viewer2 [ $breg GetOrthoViewer trn ]
+
+set numberoftools 1
+
+set  surgerytool [ [  pxitclsurgerygadget \#auto $viewer1 $viewer2 ] GetThisPointer ]
+set  basewidget  [ $breg GetBaseWidget ]
+
+wm geometry $basewidget  930x700
+
+#get the usenew flag 
+#if an input of -new is given as the first arg
+#use the new datatree
+
+if { [lindex $argv 0] == "-new" } {
+    set usenew 1 
+    set inputTree [lindex $argv 1]
+} else { 
+    set usenew 0
+    set inputTree [lindex $argv 0]
+}
+
+$surgerytool configure -electrodecontrol  [ $breg cget -electrode_control  ]
+$surgerytool configure -electrodecontrol2 [ $breg cget -electrode_control2 ]
+$surgerytool configure -useNew $usenew
+$surgerytool Initialize $basewidget
+
+set chellyMain [  [ $surgerytool cget -chellyMain ] GetThisPointer ]
+
+set toolmenu [ $chellyMain cget -toolsmenu ]
+$toolmenu add separator
+$breg CreateChildMenus 0 0  $toolmenu
+
+
+set mb2 [ $breg cget -functionalmenu ]
+
+if { $numberoftools > 1 } {
+    set  surgerytool2 [ [  pxitclsurgerygadget \#auto $viewer1 $viewer2 ] GetThisPointer ]
+    $surgerytool2 configure -electrodecontrol [ $breg cget -electrode_control ]
+    $surgerytool2 configure -overlaycontrol   [ $breg cget -overlaytool ]
+    $surgerytool2     Initialize $basewidget.[pxvtable::vnewobj ]
+}
+
+$breg HideViewers
+
+set argc [llength $argv]
+
+if { $argc > 0 } {
+    if { [ file exist $inputTree ] } { 
+	$chellyMain mdLoadTree $inputTree 
+    } else {
+	puts "Cannot load $inputTree. File does not exist"
+    }
+}
+
+update idletasks
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/bis_treegui.tcl b/bioimagesuite30_src/bioimagesuite/datatree/bis_treegui.tcl
new file mode 100644
index 0000000..ba4f0ef
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/bis_treegui.tcl
@@ -0,0 +1,3931 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide bis_treegui 1.0
+
+#---------------------------------------------------------------------------------------------
+#Import of required packages and other required initialization defs
+#---------------------------------------------------------------------------------------------
+# This package sets the required paths
+lappend auto_path [file dirname [info script]]
+
+package require pxitclchellypackages 1.0
+package require pxitclfilelistmenu   1.0
+package require dsitcltree           1.0
+package require bis_guiimageutility  1.0
+
+package require bis_resliceimage        1.0
+package require bis_guitreeimageutility 1.0
+package require bis_guitreecreate4d     1.0                    
+#------------------------------------------------------------------------------------------
+
+package require VisTree2;        #This is the "Tcl only" Tree widget that handles the tree display
+
+
+# Optional Modules - require if files are present in packages directory
+if {[file exists [ file join [ file dirname [ info script ] ] packages AtlasProg.tcl]]} {
+      package require AtlasProg;       #This is the atlas lookup package
+}
+
+# Optional Modules - require if files are present in packages directory
+if {[file exists [ file join [ file dirname [ info script ] ] packages SPECTtools.tcl]]} {
+    package require SPECTProcessProg;       #This is the atlas lookup package
+}
+
+if {[file exists [ file join [ file dirname [ info script ] ] packages AdvancedRegTools.tcl]]} {
+    package require AdvancedRegTools;       #This is the atlas lookup package
+}
+
+
+if {[file exists [ file join [ file dirname [ info script ] ] packages ElectrodeAttrProg.tcl]]} {
+    package require ElectrodeAttrProg;       #This is the atlas lookup package
+}
+
+# Require key packages
+package require Itcl
+package require Iwidgets
+
+# Xenios' C++ Extensions
+package require vtkpxcontrib     1.0
+
+# Simple Naming package  [ pxvtable::vnewobj ]
+package require pxvtable         1.0
+
+# Wrappers around vtkImageData and vtkAbstractTransform
+package require pxitclimage              1.0
+package require pxitcllandmarks          1.0
+package require pxitclelectrodemultigrid 1.0
+package require pxitcltransform          1.0
+
+::itcl::class bis_treegui {
+    
+
+    #inherit bis_treeguibase
+    #Note: throughout this class, Image 2 is the Image to Be Resliced into the Space of
+    #Image 1, which is sometimes referred to as Base Image
+    public variable nodeInfoBox ""
+    
+    #Class Data Members
+    
+    #----------------------------------------------------
+    #---------Module Enable/Disable Options--------------
+    public variable enable_atlas 0
+    public variable enable_SPECT 1
+    public variable enable_AdvancedReg 1
+    public variable enable_elec_att 1
+    #----------------------------------------------------
+
+    public variable relativePath 1;
+    public variable FileManager 0;         #This is the FileManager Object (an instance of a child of chellyDB)
+
+    #Package Variables
+    public variable AtlasModule 0;         #This is the Atlas Lookup program 
+    public variable AtlasRefFilename -1;   #This is the filename of the reference image for the atlas
+    public variable SPECTmodule 0;         #This is the SPECT processing program
+    public variable SPECT_initialized 0;   #Has the SPECT tool been initialized?
+    public variable REGmodule 0;         #This is the REG processing program
+    public variable REG_initialized 0;   #Has the REG tool been initialized?
+
+
+    public variable ElectAttrModule 0;     #This is the Electrode Attribute Selector Program
+    #--------------------------------------------------
+    public variable clipBoardTree; #This is the temporary serialized tree, for cutting and pasting
+
+    public variable mdTopWidget
+   
+    public variable menucolor; # color for the top menu
+    public variable menuactivebgcolor; # active background for top menu
+    public variable leftpane
+    public variable midpane
+    public variable rightpane
+    public variable treeframe 
+    public variable descriptionbox
+    public variable hasatlastool 1
+    public variable toolsmenu 0
+
+    public variable TreeChanged 0
+
+    public variable SurgeryMode 0; # Disables some options
+    public variable SpaceLocked 0; # Locks SpaceImage
+
+    public variable brainiconchoice "ibrainpurple"
+    public variable surfaceiconchoice "ibrainyellow"
+    public variable resulticonchoice "ibrainred"
+    public variable atlasiconchoice "ibrainrainbow"
+    public variable roiiconchoice "ibrainorange"
+
+    public variable reslmode Linear
+
+    public variable IC;   #This is the canvas widget in the middle pane
+    public variable rbX
+    public variable rbY
+    public variable abX
+    public variable abY
+    public variable fbX
+    public variable fbY
+    public variable REF_AnatomicalImage 0
+    public variable REF_FunctionalImage 0
+
+    public variable OCanv -1; #This varible will point to the canvas in the overlay tab
+    public variable OCdispX
+    public variable OCdispY
+
+    protected variable surgerygadget 0
+    protected variable mdmenubar
+
+    public variable SpaceImage -1
+    public variable AnatomicalImage -1
+    public variable FunctionalImage -1
+    public variable AtlasImage -1
+    
+    variable RecognizedTypes
+    variable PatientProperties ""
+    variable RealTree; # This is the main tree array
+    variable TransformsCache
+    variable NodeIDs
+    variable statusbar
+    variable statusLabel
+    variable vistree
+    variable popup
+    variable surfacepopup
+    variable electrodepopup
+    variable folderpopup
+    variable patientpopup
+    variable rootpopup
+    variable rightpanelpopup
+    
+    variable NodeInfoDialogName ""
+
+    variable mdEntries 
+    variable RecognizedTypesChecks
+    variable dialogEntries ""
+    variable RecogTypeDialogName -1
+    variable showGrabButtonDialogName -1
+    variable SearchDialogName -1
+
+    variable PatientPropDialogName -1
+    variable PatientProperty_selectionbox1 -1
+    
+    variable ImageThresholdForROICalcs
+    variable threshDialog
+
+    variable SearchResultList ""
+    variable titlequery ""
+    variable FinalResultList ""
+    variable ResultDisplay
+    variable foldersearchselbox
+    variable folderchoicearray
+    variable foldersearchboxlist
+    variable folderbox
+    
+    public variable viewer1 0
+    public variable viewer2 0
+    public variable electrodecontrol1 0
+    public variable electrodecontrol2 0
+    public variable overlaycontrol 0
+    public variable myname 0
+    
+    protected variable dragAndDropEnabled 1    
+    public variable undoList ""
+    protected variable theNoCursor
+
+    protected variable spaceImageList ""
+    protected variable anatomicalImageList ""
+    protected variable functionalImageList ""
+    
+    public variable dustin
+    public variable selectionPath ""
+
+    public method getTree          { } { return $dustin }
+    public method getSelectionPath { } { return $selectionPath }
+
+    # Switch Directory
+    public method SwitchDirectory { { newdir ""  } }
+
+    #---------------
+    #private methods
+    #---------------
+    public method drawFuncSpaceArrow { color }
+    public method drawAnatSpaceArrow { color } 
+
+    public  method findTransforms { node1 node2 direction }
+    private method commonAncestor { realtreename node1 node2 }
+    public  method setNodeFilename { node {filename -1}}
+    private method setNodeTransformToParFile { node {filename -1}}
+    private method setNodeTransformFromParFile { node {filename -1}}
+    public  method toggleIdentity { node {explicitSetting -1}}
+    
+    private method checkForIllegalCharacters { inputName }
+    private method getPath {realtreename ImageID}
+    private method nodeName { node }
+    private method getNodesOfTransformation { trans }    
+    
+    #--------------
+    #public methods
+    #--------------
+    public method GetThisPointer { } { return $this }
+  
+    public method AddPatient {realtreename ParentNodeID {title -1}}
+    public method AddImage {realtreename ParentNodeID {title -1} {type -1}}
+    public method AddSubtree { {treeObj ""} { parentNode "" } }
+    public method AddMSBData {  realtreename ParentNodeID {title -1} {ListedTree -1} }
+    public method AddCSIPatient { realtreename ParentNodeID {title -1} {ListedTree -1}} 
+    public method AddAllCSI { realtreename  ParentNodeID }
+    public method addSubtreeAtSelection { {type 1} }
+
+    public method OnWidgetClose { }
+
+    #This forces an update of the visualization tree with the contents of the real data tree
+    public method updateBigTransLines { } 
+    public method updateOverlayCanvas { }
+    public method updateRightCanvasDisplay { }
+
+    #Here are some methods to send/receive surfaces to/from the viewers (surfaces, landmarks, electrodes)
+    #------------------------------------------------------------------------------------------
+    public method sendSelectionToDisplay { viewerNumber node { inRefSpace 0 } } 
+    public method checkSpaceImageExsist { }
+    public method displayImage      { viewerNumber imageNode inRefSpace {background 0} }
+    public method setViewer   { viewerNumber }
+    public method setElectrodeViewer { econtrolNumber }
+    public method displaySurface    { viewerNubmer surfaceNode inRefSpace }
+    public method setNodeObject { node }
+    public method reslice { spaceNode imageNode transform }  
+    public method resliceSetOverlayInputs { }
+    public method getReslicedImage { spaceNode imageNode }
+    
+    #These grab the images from the viewers
+    public method PutViewerObjectInTree { viewerno objtype }
+    
+    public method GrabViewerImage { viewerno }
+    public method GrabViewerSurface { viewer }
+    public method GrabViewerLandmark { viewer } 
+    public method GrabViewerElectrode { electrodecontrolno }
+
+    public method grabElectrodeAttributes { electrodecontrolno }
+    
+    
+    #methods to create the total concatenated transformation and export it
+    public method CreateTransformation { listoftransforms }
+    public method sureTransLoad { transobjname }
+    
+    #User I/O methods
+    public method showButtonToolBar {mdTopWidget {args}}
+    public method showGrabButtonDialog { }
+    public method Single_Entry_Dialog {title msgstring {defstring ""}}
+    public method ImageEntryDialog { }
+    public method createNodeInfoGUI { } 
+    public method showNodeInfoBox { }
+    public method updateGUI { }
+    public method updateNotes { }
+
+    public method GetIDFromSelection { args }
+    public method IsNodeImage { node {treename -1} {broad 0}}
+    public method IsNodeSurface { node {treename -1} }
+
+    #button click methods and related helper methods
+    public method bindxrelease1 { W x y mode }
+    public method bindxmotion1 { W x y } 
+    public method bindx1 { W x y }
+    public method isCurrentAChildOfSelection { currentPath selectionPath W }
+    public method isCurrentTheParentOfSelection { currentPath selectionPath W }
+    public method bindxcontrol1 { W x y }
+    public method bindxdouble1 { W x y }
+    public method bindx3 { W x y }
+    public method bindxRightPane { W x y menu }  
+    public method bindRightPaneTest { W x y text }
+    public method setCurrent { W x y }
+    public method setSelection { W x y }
+    public method bindxControlX { W K N }
+    public method bindxControlC { W K N }
+    public method releaseOnTreeCut { W x y }
+    public method releaseOnTreeCopy { W x y }
+    public method releaseOnImagesTab { x y }
+    public method displayMarkerOnImageTab { W x y }
+
+    public method NodeInfoDialog { } 
+    public method updateNodeDialogField  { entry function node item} 
+    public method updateAllNodeDialogFields {entries node items}
+    public method updateNodeNotes { realtreename node text dialogname} 
+    public method setPatientProperty { property entryfield }
+    
+    public method ShowMidpaneTools { parent } 
+    public method OCanvasInitialize { parent }
+    public method ShowManager {pw surgerygadget0 menubase };#This is the most imporatant method
+    public method ShowTextBox { parent }
+    
+    #methods that deal with event bindings, menus and such
+    public method makeFileMenu { menu0 }
+    public method makeEditMenu { menu0 }
+    public method makeToolsMenu { menu0 }
+    public method makeImageMenu { menu0 }
+    public method makeSurfaceMenu { menu0 }
+    public method makeFolderMenu { menu0 } 
+    public method makeElectrodeMenu { menu0 }
+    public method makePatientMenu { menu0 }
+    public method makeDataMenu { menu0 }
+    public method makeAtlasMenu { menu0 }
+    public method makeOptionsMenu { menu0 }
+    public method makeViewMenu { menu0 }
+    public method makeColorMenu { colormenu icon }
+    public method menuActivation { menu menutype }
+    
+    public method addNodeToTree { type { title "" } { path "" }}
+    public method addPatientToTree { }
+    public method addSubtree { {treeObj ""} { parentNode "" } } 
+    
+    public method mdLoadElectrodeAttributes { }
+
+
+    public method delSelectedFromTree { }
+    
+    public method setSelectionSpace { }
+    public method setSelectionAnatomical { }
+    public method setSelectionFunctional { }
+    
+
+
+    
+    public method nameNode {realtreename node newtitle } 
+    #----------------------------------------
+    
+    
+    #Atlas Module methods--------------------
+    public method addAtlasToTree { }
+    public method AddAtlasNode { realtreename ParentNodeID {title -1}} 
+    public method AtlasInitialize { realtreename node }  
+    
+    public method ShowAtlas { } { $AtlasModule ShowTop }
+    public method AtlasShowSelectedNode { }
+    public method SendImageToAtlasModule { { nodeID -1} {raise 1}} 
+    public method BringUpAtlasModule { } 
+    #----------------------------------------
+
+    #SPECT Processing Tool methods-----------
+    public method ShowSPECTtool { }
+    public method ShowREGtool { }
+    #----------------------------------------
+
+    #ElectrodeAtrribute Module methods-------
+    public method SendElectrodeToAtrrControl { { nodeID -1} {raise 1} }
+    public method PutElectrodeAttrControlOutputInTree { }
+    #----------------------------------------
+    
+    #ROI Defintion methods-------------------
+    public method addROIDefToTree { }
+    public method AddROIDefNode { realtreename ParentNodeID {title -1}}
+    public method ROIDefInitialize { realtreename node }
+    #----------------------------------------
+    
+    #Search Module methods-------------------
+    public method SearchDialog { }
+    public method SearchGetFolder { }
+    public method FolderSelectionInsert { }
+    public method SearchCallback { dialog command }
+    public method doSearch { dialog }
+    
+    #Method to enable searching of the tree for a given characteristic
+    public method SearchTree { realtreename startnode key args }
+    
+    public method SaveAllInRef { {listofnodes -1} }
+    public method sendAllToCommonSpace { spacenode imagelist } 
+    public method ComputeAverages { imagelist filename { background -32767 } } 
+    public method ComputeTscoreMap { immean imvar numsubjects }
+    public method ComputeROIStatistics  { functional_input roi_image_input { threshold none } } 
+    public method MultipleROI { imagelist } 
+    public method ThresholdLevelDialogCallback { } 
+    #----------------------------------------
+    
+    #Subject Property List editor dialog-----
+    public method EditPatientPropList { }
+    public method PatientPropDialogCallback { command }
+    #----------------------------------------
+
+    #Recognized type setter module-----------
+    public method showRecognizedTypes { array }
+    public method recognizedTypeDialogCallback { dlg mode }
+    public method setRecognizedTypes { }
+    #----------------------------------------
+    
+    #----------------------------------------
+    #Cut/Copy/Paste methods
+    public method mdCopy { {cut 0} {parentNode ""} }
+    public method mdPaste { { parentNode "" } }
+    public method undo { }
+    public method redo { }
+    public method setUndoList { }
+    #----------------------------------------
+
+    #-----------------------------
+    # Added Methods to handle Save/Load 
+    #------------------------------
+    public method mdSaveTree { }
+    public method mdNewTree { }
+    public method saveReorganize { }
+    public method mdLoadTree { {filename ""} }
+    public method mdGetTreeFileName { } {
+	array set AddedTreeDefArray $ListedTree
+	return $TreeDefArray(ThisFileName)
+    }
+
+    public method mdSaveTypeDefs { }
+    public method mdLoadTypeDefs { }
+   
+    public method updateTreeWidget { {nodeID ""}}
+    public method dsrevertGUI {}
+    public method displayFileName {}
+    public method setDisplayBox { nodePath }
+    public method getIcon { nodePath }
+    public method getLineColor { nodePath }
+    public method isRoot { nodeID }
+    public method printTree { } 
+    public method makeTransformList { refNode transNode }
+    public method combineTransforms { transformList }
+    #constructor
+
+    public method setTitle           { } 
+    public method setFileName        { { name "" } } 
+    public method setTransFromParent { }
+    public method setTransToParent   { }
+    public method setIdentityToggle  { }
+    public method clearTrans         { item }
+
+    public method showImageProcessTool { }
+
+    constructor { args } {
+
+	global tcl_platform
+	
+	set thisfolder [ file dirname [ info script ] ]
+
+	if { $tcl_platform(platform) == "unix" } {
+	    set theNoCursor [ list @$thisfolder/no.xbm black ]
+	} elseif { $tcl_platform(platform) == "windows" } { 
+	    set theNoCursor "no" 
+	} else {
+	    set theNoCursor "boat" 
+	}
+
+	#-------------------------------------------------------------------------------------------------------
+	# Optional Module Loading
+	#-------------------------------------------------------------------------------------------------------
+	
+	# The Atlas Tool
+	#-------------------------------------------------------------------------------------------------------
+	if {![file exists [ file join [ file dirname [ info script ] ] packages AtlasProg.tcl]]} {
+	    set enable_atlas 0
+	}
+	if {$enable_atlas == 1} {
+	    set AtlasModule [AtlasTool \#auto] 
+	    $AtlasModule configure -folderpath [ file join [ file dirname [ info script ] ] packages AtlasDefImages]
+	    $AtlasModule Initialize .[pxvtable::vnewobj]
+	}
+	#-------------------------------------------------------------------------------------------------------
+	
+	#The SPECT Processing Tool
+	#-------------------------------------------------------------------------------------------------------
+	if {![file exists [ file join [ file dirname [ info script ] ] packages SPECTtools.tcl]]} {
+	    set enable_SPECT 0
+	}
+	if {$enable_SPECT == 1} {
+	    set SPECTmodule [SPECTprocess \#auto]
+	}
+	#-------------------------------------------------------------------------------------------------------
+
+	#The Advanced Registration Tool
+	#-------------------------------------------------------------------------------------------------------
+	if {![file exists [ file join [ file dirname [ info script ] ] packages AdvancedRegTools.tcl]]} {
+	    set enable_AdvancedReg 0
+	}
+	if {$enable_AdvancedReg == 1} {
+	    set REGmodule [ AdvancedReg \#auto]
+	}
+	#-------------------------------------------------------------------------------------------------------
+
+
+	#The ElectrodeAttribute Tool
+	#-------------------------------------------------------------------------------------------------------
+	if {![file exists [ file join [ file dirname [ info script ] ] packages ElectrodeAttrProg.tcl]]} {
+	    set enable_elec_att 0
+	}
+	if {$enable_elec_att == 1} {
+	    set ElectAttrModule [ElectrodeAttr \#auto]
+	    $ElectAttrModule Initialize .[pxvtable::vnewobj] [::itcl::scope RealTree] $this
+	}
+	#-------------------------------------------------------------------------------------------------------
+
+	#-------------------------------------------------------------------------------------------------------
+	#End of optional module loading
+	#-------------------------------------------------------------------------------------------------------
+	
+	#--------------------------------------------------
+	#Initialize a default array of recognized types
+	set RecognizedTypes(10)   "Common Space"
+	set RecognizedTypes(1000) "3D Anatomical MR"
+	set RecognizedTypes(7100) "Post-op MR"
+	set RecognizedTypes(7200) "Post-op CT"
+	set RecognizedTypes(8000) "Interictal SPECT"
+	set RecognizedTypes(8100) "Ictal SPECT"
+	set RecognizedTypes(8200) "Differential SPECT"
+	set RecognizedTypes(3000) "PET-FDG"
+	set RecognizedTypes(9000) "CSI Scout"
+	set RecognizedTypes(9100) "CSI Raw Data"
+	set RecognizedTypes(9200) "CSI PMAP"
+	set RecognizedTypes(4000) "fMRI Scout - Conventional 2D"
+	set RecognizedTypes(4100) "Spin-Echo Echoplanar"
+	set RecognizedTypes(4050) "Field Map"
+	set RecognizedTypes(4200) "fMRI Motor Task"
+	set RecognizedTypes(4300) "fMRI Language Task"
+	set RecognizedTypes(4400) "fMRI Sensory Task"
+	#--------------------------------------------------
+
+	#--------------------------------------------------
+	#Initialize a default list of patient parameters
+	set PatientProperties [list Sex Age Weight Height IQ Cholesterol {Fat percentage} BP]
+	#--------------------------------------------------
+
+   }
+    
+    #destructor
+    destructor { 
+	foreach item $undoList {
+	    ::itcl::delete Object $item
+	}
+	::itcl::delete Object $dustin
+    }
+    
+    
+};#End bis_treegui class
+
+
+#------------------------------------------------------------------------------------------
+#Method defs for class bis_treegui
+#------------------------------------------------------------------------------------------
+#------------------------------------------------------------------------------------------
+itcl::body bis_treegui::SwitchDirectory { { dirname "" } } {
+
+    if { $dirname == "" } {
+	set dirname  [tk_chooseDirectory -title "Select Current Directory" ]
+    }
+    
+    if {![string length $dirname]} {return 0}
+    
+    cd $dirname
+}
+
+
+::itcl::body bis_treegui::OnWidgetClose { } { 
+    
+    if { $TreeChanged == 0 } { $surgerygadget ExitCommand; return }
+    
+    set answer [tk_messageBox -type yesnocancel -default yes -message \
+	   "The tree has changed since it was last saved.  Would you like to save it before exiting?" -icon question] 
+    
+    if { $answer == "cancel" } { return }
+    
+    if { $answer == "yes" } {
+	mdSaveTree 
+    }
+
+    pxtkexit
+}
+
+::itcl::body bis_treegui::Single_Entry_Dialog {title msgstring {defstring ""}} {
+
+    #defstring is the default entry in the dialog
+
+    global Single_Entry_Dialog_Result ""
+
+    iwidgets::promptdialog .sed -modality application -title $title -modality application \
+	-labeltext $msgstring -labelpos s
+    .sed hide Apply
+
+    .sed buttonconfigure OK -command { set Single_Entry_Dialog_Result [.sed get]; .sed deactivate }
+    .sed buttonconfigure Cancel -command { set Single_Entry_Dialog_Result ""; .sed deactivate }
+
+    .sed insert 0 $defstring
+    .sed selection range 0 end
+  
+    focus [.sed component prompt component entry]
+    .sed center
+    update idletasks
+    .sed activate
+
+    destroy .sed
+    
+    return $Single_Entry_Dialog_Result
+}
+
+::itcl::body bis_treegui::ImageEntryDialog {} {
+    
+    global ImageDialogEntryResult ""
+    
+    iwidgets::selectiondialog .selbox -borderwidth 2 -height 200 \
+	-labelfont -Adobe-Helvetica-Bold-R-Normal--*-140-*-*-*-*-*-* \
+	-title "Add a Child Image" \
+	-textbackground ghostwhite -itemslabel "Select an Image Type:" \
+	-selectionlabel "or Specify a Custom Image Type:"
+    
+    #This just makes sure that they are displayed sorted by type key (which is not seen by the user)
+    foreach index [array names RecognizedTypes] {
+	lappend typekeyz $index
+    }
+    set typekeyz [lsort -integer $typekeyz]
+    
+    for {set tx 0} {$tx < [llength $typekeyz]} {incr tx} {
+	lappend imagetypes $RecognizedTypes([lindex $typekeyz $tx])
+    }
+    
+    eval .selbox insert items 0 $imagetypes
+    .selbox hide Apply
+    .selbox center
+    .selbox configure -modality application
+    .selbox buttonconfigure OK -command {set ImageDialogEntryResult [.selbox get]; .selbox deactivate }
+    .selbox buttonconfigure Cancel -command {set ImageDialogEntryResult ""; .selbox deactivate }
+    
+    update idletasks
+    .selbox activate
+    
+    destroy .selbox
+    
+    return $ImageDialogEntryResult
+ }
+
+::itcl::body bis_treegui::drawAnatSpaceArrow { color } {
+    
+    $IC create line [expr $rbX - 13] [expr $rbY + 50] \
+	[expr $rbX - 55 ] [expr $rbY + 55] \
+	[expr $abX + 35 ] [expr $abY - 85] \
+	[expr $abX + 50 ] [expr $abY - 8] \
+	-tag Anat2Space -smooth true  -splinesteps 20 -width 12 \
+	-arrow first -arrowshape {15 18 8} -fill $color
+}
+
+::itcl::body bis_treegui::drawFuncSpaceArrow { color } {
+
+    $IC create line [expr $rbX + 150] [expr $rbY + 50] \
+	[expr $rbX + 190] [expr $rbY + 55] \
+	[expr $fbX + 95 ] [expr $fbY - 85] \
+	[expr $fbX + 80 ] [expr $fbY - 8] \
+	-tag Func2Space -smooth true  -splinesteps 20 -width 12 \
+	-arrow first -arrowshape {15 18 8} -fill $color
+}
+
+#------------------------------------------------------------------------------------------
+# Private methods of bis_treegui
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_treegui::updateBigTransLines { } {
+
+    set anatomcialColor grey80; set functionalColor grey80
+    $IC delete Anat2Space Func2Space
+   
+    if { [ llength $spaceImageList ] && [ llength $anatomicalImageList ] } {
+	if { [ makeTransformList [ lindex $spaceImageList 0 ] [ lindex $anatomicalImageList 0 ] ] == 0 } { 
+	    set anatomcialColor red
+	} else {
+	    set anatomcialColor green
+	}
+    }
+	    
+    if { [ llength $spaceImageList ] && [ llength $functionalImageList ] } {
+	if { [ makeTransformList [ lindex $spaceImageList 0 ] [ lindex $functionalImageList 0 ] ] == 0 } { 
+	    set functionalColor red
+	} else {
+	    set functionalColor green
+	}
+    }
+    drawFuncSpaceArrow $functionalColor
+    drawAnatSpaceArrow $anatomcialColor 
+}
+
+::itcl::body bis_treegui::updateRightCanvasDisplay { } {
+
+    #Clear all
+    catch {$IC delete refPIC};    $IC delete refTEXT
+    catch {$IC delete anatomPIC}; $IC delete anatomTEXT
+    catch {$IC delete funcPIC};   $IC delete funcTEXT
+    
+    #--Anatomical Image------------------------------------------------------------------------------
+    if { [ llength $anatomicalImageList ] } {
+	set anatomicalcolorbrainPIC [$IC create image $abX $abY -image multicolorbrain -anchor nw -tag anatomPIC]
+	set anatomicalbrainTEXT  [$IC create text [expr $abX+65] [expr $abY+52] -text "[ lindex $anatomicalImageList 1 ]" \
+				      -fill white -activefill yellow -font {helvetica 15 bold} -tag anatomTEXT -width 150]
+    } else {
+	set anatomicalbrainTEXT  [$IC create text [expr $abX+65] [expr $abY+52] -text "Not Set" \
+				      -fill grey61 -font {helvetica 15 bold}  -activefill yellow -tag anatomTEXT]
+    }
+    #-------------------------------------------------------------------------------------------------
+    
+    #--Functional Image------------------------------------------------------------------------------
+    if { [ llength $functionalImageList ] } {
+	set funccolorbrainPIC [$IC create image $fbX $fbY -image multicolorbrain -anchor nw -tag funcPIC]
+	set funcbrainTEXT  [$IC create text [expr $fbX+65] [expr $fbY+52] -text "[ lindex $functionalImageList 1 ]"\
+				-fill white -activefill yellow -font {helvetica 15 bold} -tag funcTEXT -width 150]
+    } else {
+	set funcbrainTEXT  [$IC create text [expr $fbX+65] [expr $fbY+52] -text "Not Set" \
+				-fill grey61 -activefill yellow -font {helvetica 15 bold} -tag funcTEXT]
+    }
+    #-------------------------------------------------------------------------------------------------
+    
+    #--Space Image------------------------------------------------------------------------------
+    if { [ llength $spaceImageList ] } {
+	set refcolorbrainPIC [$IC create image $rbX $rbY -image multicolorbrain -anchor nw -tag refPIC]
+	set refbrainTEXT  [$IC create text [expr $rbX+65] [expr $rbY+52] -text "[ lindex $spaceImageList 1 ]" \
+			       -fill white -activefill yellow -font {helvetica 15 bold} -tag refTEXT -width 150]	
+    } else {
+	set refbrainTEXT  [$IC create text [expr $rbX+65] [expr $rbY+52] -text "Not Set" \
+			       -fill grey61 -activefill yellow  -font {helvetica 15 bold} -tag refTEXT]
+    }
+    #------------------------------------------------------------------------------------------------
+    updateBigTransLines
+}
+
+::itcl::body bis_treegui::undo { } {
+
+    if { [ llength $undoList ] < 1 } { return }
+    itcl::delete object $dustin
+    set dustin [ [ dsitcltree \#suto ] GetThisPointer ]
+    $dustin copyTree [ lindex $undoList 1 ]
+    lappend undoList [ lindex $undoList 0 ]
+    set undoList [ lrange $undoList 1 end ]
+    
+    updateTreeWidget /Data
+    setDisplayBox    /Data
+}
+
+::itcl::body bis_treegui::redo { } {
+
+    if { [ llength $undoList ] < 1 } { return }
+    itcl::delete object $dustin
+    set dustin [ [ dsitcltree \#suto ] GetThisPointer ]
+    $dustin copyTree [ lindex $undoList end ]
+    set undoList [ linsert $undoList 0 [ lindex $undoList end ] ]
+    set undoList [ lrange  $undoList 0 end-1 ]
+  
+    updateTreeWidget /Data
+    setDisplayBox    /Data
+}
+
+::itcl::body bis_treegui::setUndoList { } {
+
+    set tmpTree [ [ dsitcltree \#auto ] GetThisPointer ]
+    $tmpTree copyTree $dustin
+    set undoList [ linsert $undoList 0 $tmpTree ]
+}
+
+::itcl::body bis_treegui::addSubtree { {treeObj ""} { parentNode "" } } {
+
+    set delete 0
+    if {$treeObj == ""} {
+	set treeObj [ [ dsitcltree \#auto ] GetThisPointer ]
+	$treeObj readDatatree
+	set delete 1
+    }
+    
+    if { $parentNode == "" } {
+	set parentNode $selectionPath 
+    }
+
+    $dustin addSubTree $treeObj $parentNode
+    if { $delete } {  itcl::delete object $treeObj }
+    updateTreeWidget $parentNode
+    setUndoList; set TreeChanged 1
+}
+
+# for findtransfrom node2 is an ancestor of node1
+::itcl::body bis_treegui::findTransforms { node1 node2 direction } {
+
+    set transformList ""
+    while { $node1 != $node2 } {
+	set trans [ $dustin getNodeTrans$direction $node1 ]
+
+	if { $trans == "" } {
+	    return 0
+	}
+
+	if { $trans == 1 } { 
+	    set node1 [ $dustin getNodeParent $node1 ]
+	} else {
+	    set newtr [ [pxitcltransform \#auto ] GetThisPointer  ]
+	    if {[ regexp {linear.nosave$} $trans ]} {
+		set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+		$newtr CopyTransformation [ $ut LoadAbstractTransform [ $dustin getNodeTransFromParent $node1 ] ]
+		$ut Delete
+		$newtr Invert
+		puts "inverting transform"
+	    } else {
+		set ut [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+		$newtr CopyTransformation [ $ut LoadAbstractTransform [ $dustin getNodeTrans$direction $node1 ] ]
+		$ut Delete
+	    }
+	    lappend transformList $newtr
+	    set node1 [ $dustin getNodeParent $node1 ]
+	}
+    }
+   
+    return $transformList
+}
+    
+#input is two nodes
+#returns 0 if no transform exsist between the nodes or the nodes are the same
+#return a list of transform objects starting at the transnode and ending at the refnode
+::itcl::body bis_treegui::makeTransformList { refNode transNode } {
+    
+    set ancestor [ $dustin getCommonAncestor $refNode $transNode ]
+
+    # determine which direction the transforms must be applied 
+    #surfaces are reversed from images
+    if { [ $dustin getNodeType $transNode ] == "Image" } {
+	set directionList [ list FromParent ToParent ]
+    } else { set directionList [ list ToParent FromParent ]}
+
+    set transformList  [ findTransforms $transNode $ancestor [ lindex $directionList 0 ] ]
+    set transformList2 [ findTransforms $refNode   $ancestor [ lindex $directionList 1 ] ]
+
+    if { $transformList == 0 || $transformList2 == 0 } {
+	return 0
+    }
+
+    for { set index 0 } { $index < [ llength $transformList2 ] } { incr index } {
+	lappend transformList [ lindex $transformList2 $index ] 
+    }
+
+    return $transformList
+}
+
+#take in a proposed title for a node
+#give an error and return 0 if an illegal char exists
+::itcl::body bis_treegui::checkForIllegalCharacters { inputName } {
+    
+    if {[ regexp {[^A-Za-z0-9\^\-\_\.\s]} $inputName illegalChar ]} {
+	
+	set warning "Cannot rename node using character $illegalChar  -- Node names can only can contain the following characters: \n     a-z, A-Z, 0-9, _, -, ., ^, and spaces."
+	
+	tk_messageBox -type ok -title "Please choose a new name" -message $warning -icon error
+	return 0
+    } 
+    return 1
+}   
+    
+::itcl::body bis_treegui::sendSelectionToDisplay { viewerNumber node { inRefSpace 0 } } {
+    
+    switch -exact -- $node {
+	
+	"SpaceImage" {
+	    set node [ lindex $spaceImageList 0 ]
+	    set inRefSpace 0
+	}
+	
+	"AnatomicalImage" {
+	    set node [ lindex $anatomicalImageList 0 ]
+	    set inRefSpace $REF_AnatomicalImage
+	}
+	
+	"FunctionalImage" {
+	    set node [ lindex $functionalImageList 0 ]
+	    set inRefSpace $REF_FunctionalImage
+	}	
+	
+	default {
+	    set node $selectionPath
+	}
+    }
+    
+    switch -exact -- [ $dustin getNodeType $node ] { 
+	
+	"Image"     { displayImage     $viewerNumber $node $inRefSpace }
+	"Surface"   { displaySurface   [ setViewer          $viewerNumber ] $node $inRefSpace }
+	"Landmark"  { displaySurface   [ setViewer          $viewerNumber ] $node $inRefSpace }
+	"Electrode" { displaySurface   [ setElectrodeViewer $viewerNumber ] $node $inRefSpace }
+    }
+}
+
+::itcl::body bis_treegui::setNodeObject { node } {
+
+    if { [ $dustin getNodeImageObject $node ] != "" } { return 0 }
+
+    switch -exact [ $dustin getNodeType $node ] {
+	"Image"     { set img [ [ pxitclimage              \#auto ] GetThisPointer ] }
+	"Surface"   { set img [ [ pxitclsurface            \#auto ] GetThisPointer ] }
+	"Landmark"  { set img [ [ pxitcllandmarks          \#auto ] GetThisPointer ] }
+	"Electrode" { set img [ [ pxitclelectrodemultigrid \#auto ] GetThisPointer ] }
+    }
+    
+    $img Load "[ $dustin getNodeFileName $node ]"
+    $dustin setNodeImageObject $img $node 
+}
+
+::itcl::body bis_treegui::checkSpaceImageExsist { } {
+    
+    if { $spaceImageList == "" } { 
+	tk_messageBox -type ok  -title "Cannot Reslice" -message "space image is not set" -icon error
+	return 1
+    } else { return 0 }
+}
+
+::itcl::body bis_treegui::displayImage { viewerNumber imageNode inRefSpace {background 0} } {
+   
+    if { ![ file exists [ $dustin getNodeFileName $imageNode ] ] } { 
+	tk_messageBox -type ok  -title "Cannot open image" -message "File does not exist" -icon error
+	return 0
+    }
+   
+    if { $viewerNumber == 1 } { set viewer $viewer1 } else { set viewer $viewer2 }
+	
+    setNodeObject $imageNode
+
+    if { [ expr !$inRefSpace ] } {
+	$viewer SetImageFromObject [ $dustin getNodeImageObject $imageNode ] $this
+	$viewer ShowWindow
+	return 0
+    }
+    
+    if { [ checkSpaceImageExsist ] } { return 0 } 
+
+    set spaceNode [ lindex $spaceImageList 0 ]
+    setNodeObject $spaceNode
+    
+    set transformList [ makeTransformList $spaceNode $imageNode ]
+    if { $transformList == 0 } {
+	tk_messageBox -type ok  -title "Cannot open image" -message "Transformation is missing" -icon error
+	return 0
+    }
+
+    if { ![ llength $transformList ] } {
+	$viewer SetImageFromObject [ $dustin getNodeImageObject $imageNode ] $this
+	$viewer ShowWindow
+	return 0
+    }
+
+    set transform [ combineTransforms $transformList ]
+
+    set reslicedImg [ $this reslice $spaceNode $imageNode $transform ]
+    itcl::delete object $transform
+
+    $viewer SetImage $reslicedImg 
+    $viewer ShowWindow
+    itcl::delete object $reslicedImg
+}
+
+::itcl::body bis_treegui::reslice { spaceNode imageNode transform } {
+ 
+    set reslice_alg [ bis_resliceimage   [ pxvtable::vnewobj ] ]
+
+    $reslice_alg InitializeFromContainer $this			
+    $reslice_alg SetInput                [ $dustin getNodeImageObject $spaceNode ]
+    $reslice_alg SetSecondInput          [ $dustin getNodeImageObject $imageNode ]
+    $reslice_alg SetTransformation       $transform
+    $reslice_alg SetOptionValue          interp $reslmode
+    $reslice_alg Execute
+    
+    #set output [ [ pxitclimage \#auto ] GetThisPointer ]
+    #$output ShallowCopy [ $reslice_alg GetOutput ] 
+    #$output Save "test.hdr"
+    #itcl::delete object $reslice_alg
+    #return $output
+    return [ $reslice_alg GetOutput ] 
+}
+
+::itcl::body bis_treegui::resliceSetOverlayInputs { } {
+
+    if { [ checkSpaceImageExsist ] } { return 0 }
+    set spaceImage [ lindex $spaceImageList 0 ]
+    setNodeObject $spaceImage 
+
+    if { $anatomicalImageList != "" } { 
+	set anatomicalImage [ lindex $anatomicalImageList 0 ]
+	setNodeObject $anatomicalImage
+	set reslicedAnatomicalImage [ getReslicedImage $spaceImage $anatomicalImage ]
+	set input1 1
+    }  else { set input1 0 }
+   
+    if { $functionalImageList != "" } { 
+	set functionalImage [ lindex $functionalImageList 0 ]
+	setNodeObject $functionalImage
+	set reslicedFunctionalImage [ getReslicedImage $spaceImage $functionalImage ]
+	set input2 1
+    } else { set input2 0 }
+ 
+    if { $input1 && $input2 } {
+	$surgerygadget SetOverlayToolInputs $reslicedAnatomicalImage $reslicedFunctionalImage 
+	::itcl::delete object $reslicedAnatomicalImage
+	::itcl::delete object $reslicedFunctionalImage 
+    } elseif { $input1 } {
+	$surgerygadget SetOverlayToolInputs [ $dustin getNodeImageObject $spaceImage ] $reslicedAnatomicalImage
+	::itcl::delete object $reslicedAnatomicalImage
+    } elseif { $input2 } { 
+	$surgerygadget SetOverlayToolInputs [ $dustin getNodeImageObject $spaceImage ] $reslicedFunctionalImage 
+	::itcl::delete object $reslicedFunctionalImage 
+    } else {
+	$surgerygadget SetOverlayToolInputs [ $dustin getNodeImageObject $spaceImage ] [ $dustin getNodeImageObject $spaceImage ]
+    }
+    updateOverlayCanvas
+}
+
+::itcl::body bis_treegui::getReslicedImage { spaceNode imageNode } {
+    
+    setNodeObject $spaceNode ; setNodeObject $imageNode
+    
+    set transformList [ makeTransformList $spaceNode $imageNode ]
+    
+    if { $transformList == 0 } {
+	tk_messageBox -type ok  -title "Cannot open image" -message "Transformation is missing" -icon error
+	return 0
+    }
+    
+    if { ![ llength $transformList ] } {
+	set img [ [ pxitclimage \#auto ] GetThisPointer ]
+	$img ShallowCopy [ $dustin getNodeImageObject $imageNode ]
+	return $img
+    }
+
+    set transform [ combineTransforms $transformList ]
+    return [ reslice $spaceNode $imageNode $transform ]
+}
+
+::itcl::body bis_treegui::setViewer { viewerNumber } {
+   
+    if { $viewerNumber == 1 } { set viewer $viewer1 } else { set viewer $viewer2}
+    return $viewer
+}
+
+::itcl::body bis_treegui::setElectrodeViewer { econtrolNumber } {
+
+    if { $econtrolNumber == 1 } { set viewer $electrodecontrol1 } else { set viewer $electrodecontrol2}
+    return $viewer
+}
+
+::itcl::body bis_treegui::displaySurface { viewer surfaceNode inRefSpace } {
+    
+    if { ![ file exists [ $dustin getNodeFileName $surfaceNode ] ] } { 
+	tk_messageBox -type ok  -title "Cannot open surface" -message "File does not exist" -icon error
+	return 0
+    }
+    
+    if { [ string match [ $dustin getNodeType $surfaceNode ] "Electrode" ] } { 
+	set exp [ string match [ [ $viewer2 GetDisplayedImage ] cget -filename ] "" ] 
+    } else {
+	set exp [ string match [ [ $viewer  GetDisplayedImage ] cget -filename ] "" ] 
+    }
+
+    if { $exp } {
+	::pxtclutil::Info "Please put an image into the viewer to properly display the surface" 
+    }
+    
+    setNodeObject $surfaceNode
+    
+    if { [ expr !$inRefSpace ] } {
+	catch { [ $dustin getNodeImageObject $surfaceNode ] Display $viewer }
+	$viewer ShowWindow
+	return 0
+    }
+    
+    if { [ checkSpaceImageExsist ] } { return 0 }
+    
+    set spaceNode [ lindex $spaceImageList 0 ]
+    setNodeObject $spaceNode
+
+    set transformList [ makeTransformList $spaceNode $surfaceNode ]
+    if { $transformList == 0 } {
+	tk_messageBox -type ok  -title "Cannot open aurface" -message "Transformation is missing" -icon error ; return 
+	return 0
+    }
+    
+    if { ![ llength $transformList ] } {
+	[ $dustin getNodeImageObject $surfaceNode ] Display $viewer
+	$viewer ShowWindow
+	return 0
+   }
+    
+    set transform [ combineTransforms $transformList ]
+
+    switch -exact [ $dustin getNodeType $surfaceNode ] {
+	
+	"Surface"  { 
+	    set newsur [ pxitclsurface \#auto ] 
+	    $newsur ShallowCopy [ $dustin getNodeImageObject $surfaceNode ]
+	}
+	
+	"Electrode" {
+	    set newsur [ pxitclelectrodemultigrid \#auto ] 
+	    $newsur Copy [ $dustin getNodeImageObject $surfaceNode ]
+	}
+	
+	"Landmark" {
+	    set newsur [ pxitcllandmarks \#auto ]
+	    $newsur Copy [ $dustin getNodeImageObject $surfaceNode ]
+	}
+	
+	default { :itcl::delete object $transform; return 0 }
+    }
+	
+    $newsur Transform [ $transform GetObject ]
+    catch { $newsur Display $viewer }
+  
+    ::itcl::delete object $newsur
+    ::itcl::delete object $transform
+}
+
+::itcl::body bis_treegui::combineTransforms { transformList } {
+  
+    set trans [ vtkGeneralTransform [ pxvtable::vnewobj ] ]
+    $trans Identity
+    $trans PostMultiply
+
+    for { set index 1 } { $index <= [ llength $transformList ] } { incr index } {
+	set index2 [ expr [ llength $transformList ] - $index ]
+	$trans Concatenate [ [ lindex $transformList $index2 ] GetTransformation ]
+	itcl::delete object [ lindex $transformList $index2 ]
+    }
+ 
+    set output [ [ pxitcltransform \#auto ] GetThisPointer ]
+    $output CopyTransformation $trans
+    #$trans Delete
+    $output Save /tmp/output
+    return $output
+}
+
+::itcl::body bis_treegui::setTitle {  } {
+    
+    set oldTitle [ $dustin getNodeTitle $selectionPath ]
+    set newTitle [ Single_Entry_Dialog "Rename" "Enter the new name for this node" $oldTitle ]
+   
+    if { $newTitle == ""} {return}
+    if { $newTitle == $oldTitle } {return}  
+    
+    if { [checkForIllegalCharacters $newTitle] } {
+    	set tmpPath $selectionPath
+	#because of trouble with updating the path and title at the same time with the node info box
+	#we switch the node info box to the parent node and then change the title of the selected node 
+	#then update the node info box to the selected node
+	set selectionPath [ $dustin getNodeParent $selectionPath ]; updateGUI
+	setDisplayBox  [ $dustin setNodeTitle $newTitle $tmpPath ]; updateGUI
+	updateTreeWidget $tmpPath
+	#puts [ lindex $spaceImageList      0 ]
+	if { ![ $dustin pathExist [ lindex $spaceImageList      0 ] ] } { set spaceImageList      "" }
+	if { ![ $dustin pathExist [ lindex $functionalImageList 0 ] ] } { set functionalImageList "" }
+	if { ![ $dustin pathExist [ lindex $anatomicalImageList 0 ] ] } { set anatomicalImageList "" }
+	updateRightCanvasDisplay
+    } else {
+	$this setTitle
+    }
+}
+
+::itcl::body bis_treegui::setFileName { { name "" } } {
+    
+    switch -exact [ $dustin getNodeType $selectionPath ] {
+	"Image"      { set typelist {{"Image"       {".hdr" ".hdr.gz" ".nii" ".nii.gz"}} {"All Files" {*}}}}
+	"Landmark"   { set typelist {{"Landmark"    {".land"}}                           {"All Files" {*}}}}
+	"Surface"    { set typelist {{"Surface"     {".vtk"}}                            {"All Files" {*}}}}
+	"Electrode"  { set typelist {{"Electrodes"  {".mgrid"}}                          {"All Files" {*}}}}
+	default      { return 0 }
+    }
+    
+    if { $name == "" } { set name [tk_getOpenFile -filetypes $typelist] }
+    if { $name == "" } { return }
+    $dustin setNodeFileName $name $selectionPath 
+    displayFileName
+    updateTreeWidget $selectionPath
+    updateGUI 
+}
+
+::itcl::body bis_treegui::setTransFromParent {  } {
+  
+    set typelist {
+	{"Linear/Non-Linear Transforms" {".matr" ".grd" }}
+	{"Linear Transforms" {.matr}}
+	{"Non-Linear Transforms" {.grd}}
+	{"All Files" {*}}
+    }
+   
+    set transform [tk_getOpenFile -filetypes $typelist]
+    if { $transform == "" } { return }
+    $dustin setNodeTransFromParent $transform $selectionPath
+    if { [ file extension $transform ] == ".matr" } {
+	$dustin setNodeTransToParent "linear.nosave" $selectionPath 
+    }
+    updateTreeWidget $selectionPath; updateBigTransLines
+}
+
+::itcl::body bis_treegui::setTransToParent {  } {
+    
+    set typelist {
+	{"Non-Linear Transforms" {.grd}}
+	{"Linear Transforms" {.matr}}
+	{"All Files" {*}}
+    }
+   
+    set transform [tk_getOpenFile -filetypes $typelist]
+    if { $transform == "" } { return }
+    $dustin setNodeTransToParent $transform $selectionPath
+    updateTreeWidget $selectionPath;  updateBigTransLines
+}
+
+::itcl::body bis_treegui::setIdentityToggle {  } {
+    
+    if { [ $dustin getNodeTransFromParent $selectionPath ] == 1 \
+	    && [ $dustin getNodeTransToParent $selectionPath ] == 1 } { 
+	$dustin setNodeTransFromParent "" $selectionPath 
+	$dustin setNodeTransToParent   "" $selectionPath 	
+	updateTreeWidget $selectionPath
+	updateBigTransLines
+    } else { 
+	$dustin setNodeTransFromParent 1 $selectionPath 
+	$dustin setNodeTransToParent   1 $selectionPath 
+	updateTreeWidget $selectionPath
+	updateBigTransLines
+    }
+}
+
+::itcl::body bis_treegui::clearTrans { item } { 
+    $dustin setNode${item} "" $selectionPath 
+    updateOverlayCanvas ; updateTreeWidget $selectionPath ;  updateGUI
+}
+
+::itcl::body bis_treegui::grabElectrodeAttributes { electrodecontrolno } {
+
+    set electrodecontrol $electrodecontrol1; if { $electrodecontrolno == 2 && $electrodecontrol2 != 0 }  { set electrodecontrol $electrodecontrol2 }
+    if { $electrodecontrol == 0 } {	return    }
+
+    set source [ $electrodecontrol GetMultiGrid ]
+
+    set ThisNode [GetIDFromSelection]
+    EnsureFileLoaded $ThisNode
+    set electrodeobj        [$RealTree get $ThisNode pxitclobj]
+    set target  [$electrodeobj GetObject]
+
+    $target CopyAttributes $source
+
+    #Save a new file
+    set newName "[file rootname [$RealTree get $ThisNode FileName]]_Attr_Updated.mgrid"
+    $target Save $newName
+    setNodeFilename $ThisNode $newName
+}
+
+::itcl::body bis_treegui::PutViewerObjectInTree { viewerno objtype } {
+    
+    set MC [ $dustin getMasterCount ]
+    set filename [ GrabViewer${objtype} $viewerno ]
+    if { $filename == "" } { return 0 }
+    addNodeToTree $objtype "Grabbed_${objtype}_$MC"
+    setFileName $filename
+}
+
+::itcl::body bis_treegui::GrabViewerImage { viewerno } {
+    
+    set viewer [ setViewer $viewerno ]
+    
+    set img [ $viewer GetDisplayedImage ]
+    if { [ $img cget -filename ] == "" } {
+	tk_messageBox -type ok  -title "Cannot Grab Image" -message "No image in viewer" -icon error ; return ""
+    }
+
+    if { [ $img Save "" ] } {
+	return [ $img cget -filename ]
+    } else { return "" }
+}
+
+::itcl::body bis_treegui::GrabViewerSurface { viewerno } {
+    
+    set viewer  [ setViewer $viewerno ]
+    set newsur  [ [ pxitclsurface \#auto ] GetThisPointer ]
+    set surface [ [ [ $viewer GetPolyDataControl ] GetPolyDataControl ]  GetSurface  -1 ]
+    $newsur ShallowCopySurface $surface
+    
+    if { [ $newsur GetSurfaceSize ] < 6 } { 
+	tk_messageBox -type ok  -title "Cannot Grab Surface" -message "No surface in the control" -icon error ; return ""
+    }
+
+    if { [ $newsur Save "" ] } {
+	set fname [ $newsur cget -filename ]
+	itcl::delete object $newsur
+	return $fname
+    } else { 
+	itcl::delete object $newsur
+	return "" 
+    }
+}
+
+::itcl::body bis_treegui::GrabViewerLandmark { viewerno } {
+    
+    set viewer  [ setViewer $viewerno ]
+    set newsur  [ [ pxitcllandmarks \#auto ] GetThisPointer ]
+    set surface [ [ [ $viewer GetLandmarkControl ] GetLandmarkControl ]  GetCollection  -1 ] 
+    $newsur CopyLandmarks $surface
+    
+    # GetLandmarkSize outputs a interger with the format of # of  PointSet and some other #
+    # 20 is no points`
+    if { [ $newsur GetLandmarksSize ] == 20 } { 
+	tk_messageBox -type ok  -title "Cannot Grab landmark" -message "No landmark in the control" -icon error ; return ""
+    }
+
+    if { [ $newsur Save "" ] } {
+	set fname [ $newsur cget -filename ]
+	itcl::delete object $newsur
+	return $fname
+    } else { 
+	itcl::delete object $newsur
+	return "" 
+    }
+}
+
+::itcl::body bis_treegui::GrabViewerElectrode { electrodecontrolno } {
+    
+    set viewer [ setElectrodeViewer $electrodecontrolno ]
+
+    if { [ $viewer SaveElectrodeMultiGrid "" ] } {
+	return [ $viewer GetLastFilename ]
+    } else { return "" }
+}
+
+
+::itcl::body bis_treegui::mdCopy { {cut 0} {node ""} } {
+
+    if { $node == "" } {
+	set node $selectionPath 
+    }
+    
+    if {[ info exist clipBoardTree ]} {
+	itcl::delete object $clipBoardTree
+	set clipBoardTree [ [ dsitcltree \#auto ] GetThisPointer ]
+    } else {
+	set clipBoardTree [ [ dsitcltree \#auto ] GetThisPointer ]
+    }
+    $clipBoardTree copyTreeAtNode $dustin $node
+
+    if {$cut == 1} {
+	$this delSelectedFromTree
+    }
+}
+
+::itcl::body bis_treegui::mdPaste { { parentNode "" } } {
+
+    if { $parentNode == "" } {
+	set parentNode $selectionPath 
+    }
+    
+    if {![ info exist clipBoardTree ]} {
+	tk_messageBox -type ok -title "Cannot paste" -message "Nothing in the clipboard" 
+	return 0
+    }
+    
+    if {     [ $dustin getNodeType $parentNode ] == "Surface"   || \
+	     [ $dustin getNodeType $parentNode ] == "Electrode" || \
+	     [ $dustin getNodeType $parentNode ] == "Landmark" } {
+	
+	tk_messageBox -type ok -title "Cannot paste" -message "Surface cannot have children nodes"
+	return 0
+    } 
+
+    $this addSubtree $clipBoardTree $parentNode
+    setUndoList; set TreeChanged 1
+}
+
+#Save and Load Tree Methods 
+
+::itcl::body bis_treegui::mdSaveTree { } {
+    
+    updateNotes
+    $dustin writeDatatree $relativePath
+}
+
+::itcl::body bis_treegui::saveReorganize { } {
+    
+    updateNotes
+    $dustin saveReorangized
+}
+
+::itcl::body bis_treegui::mdNewTree { } {
+    
+    updateNotes 
+    destroy $NodeInfoDialogName
+    ::itcl::delete object $dustin
+    
+    set dustin [ [ dsitcltree \#auto new ] GetThisPointer ]
+    
+    set spaceImageList ""; set anatomicalImageList ""; set functionalImageList ""
+    updateRightCanvasDisplay
+    updateTreeWidget /Data
+    setDisplayBox /Data
+}
+
+::itcl::body bis_treegui::mdLoadTree { {filename ""} } {
+   
+    set tmpTree [ [ dsitcltree \#auto ] GetThisPointer ]
+
+    if { ![ $tmpTree readDatatree $filename ] } {
+	::itcl::delete object $tmpTree
+	return 0
+    }
+
+    foreach path [ $dustin getPathList ] {
+	if {[ regexp {(/)(.+)(/)} $path ]} { 
+	    if {[ Tree::itemexists $vistree $path ]} { Tree::delitem $vistree $path }
+	}
+    }	
+    
+    updateNotes
+    destroy $NodeInfoDialogName
+    ::itcl::delete object $dustin
+    set dustin $tmpTree
+    set spaceImageList ""; set anatomicalImageList ""; set functionalImageList ""
+    updateRightCanvasDisplay
+    updateTreeWidget Data
+    setDisplayBox /Data
+    #wm title $mdTopWidget $filename 
+}
+
+::itcl::body bis_treegui::mdSaveTypeDefs { } {
+    
+    $FileManager SaveTypeDefs [array get RecognizedTypes]
+    
+}
+
+::itcl::body bis_treegui::mdLoadTypeDefs { } {
+    
+    catch {array unset RecognizedTypes}
+    set loadedtypes [$FileManager LoadTypeDefs]
+    if {$loadedtypes != -1} {
+	array set RecognizedTypes $loadedtypes
+	set RecogTypeDialogName -1
+	setRecognizedTypes
+    }
+
+}
+
+::itcl::body bis_treegui::EditPatientPropList { } {
+
+   if {$PatientPropDialogName == -1} {
+
+       #Make a dialog box
+       set PatientPropDialogName .[ pxvtable::vnewobj ]
+       iwidgets::dialog $PatientPropDialogName -title "Patient Properties" -modality application
+       $PatientPropDialogName hide Help
+       $PatientPropDialogName hide Apply
+       $PatientPropDialogName hide Cancel
+       eval "$PatientPropDialogName buttonconfigure OK -command { $this PatientPropDialogCallback ok }"
+       eval "$PatientPropDialogName add removebutton -text Remove -command { $this PatientPropDialogCallback remove }"
+       eval "$PatientPropDialogName add addbutton -text Add -command { $this PatientPropDialogCallback add }"
+
+       set cs1 [ $PatientPropDialogName childsite ]
+       set PatientProperty_selectionbox1 [iwidgets::selectionbox $cs1.selbox -itemslabel "Patient Property List" -selectionlabel "Add:"]
+       pack $PatientProperty_selectionbox1
+       
+	
+   }
+    
+   set patientproplistbox [$PatientProperty_selectionbox1 component items]
+   $patientproplistbox clear
+   for {set u 0} {$u < [llength $PatientProperties]} {incr u} {
+       $patientproplistbox insert end [lindex $PatientProperties $u]
+   }
+   
+   wm geometry $PatientPropDialogName +300+200
+   $PatientPropDialogName activate
+   
+}
+
+::itcl::body bis_treegui::PatientPropDialogCallback { command } {
+
+  
+    #Get pointers to the entry field and the listbox
+    set thisentryfield [$PatientProperty_selectionbox1 component selection]
+    set thislistbox [$PatientProperty_selectionbox1 component items]
+
+    #If the command is OK, update the internal property list, and deactivate dialog
+    if {$command == "ok"} {
+	set PatientProperties ""
+	for {set y 0} {$y < [llength [$thislistbox get 0 end]]} {incr y} {
+	    lappend PatientProperties [$thislistbox get $y]
+	}
+	
+	$PatientPropDialogName deactivate; return 0
+    }
+     
+    #If the command is add, insert the contents of the entryfield into the list
+    if {$command == "add"} {
+	set input [$thisentryfield get]
+	if {[llength $input]} {
+	    $thislistbox insert 0 $input
+	    $thisentryfield clear
+	}
+    }
+
+    #If the command is remove, remove the selected items from the list
+    if {$command == "remove"} {
+	set sel  [$thislistbox getcurselection]
+	if { [llength $sel] } {
+	    $thislistbox delete $sel
+	}
+    }
+}
+
+::itcl::body bis_treegui::showRecognizedTypes { arraylist } {
+    
+    catch {array unset tempArray}
+    array set tempArray $arraylist
+    set keylist [ array names tempArray ]
+    set keylist [lsort $keylist]
+    
+    if {$RecogTypeDialogName == -1} {
+	set mdEntries ""
+    	set RecogTypeDialogName .[ pxvtable::vnewobj ]
+	iwidgets::dialog $RecogTypeDialogName -title "Recognized Image Types" -modality application
+	
+	for { set k 0 } { $k < [llength $keylist] } { incr k } {
+	    set key [lindex $keylist $k]
+	    set val $tempArray($key)
+	    
+	    set f $key; append f "_f"	
+	    set c $key; append c "_c"
+	    set y $key; append y "_y"
+	    set v $key; append v "_v"
+	    
+	    set cs [$RecogTypeDialogName childsite]
+	    set framebox [frame $cs.$f]	
+	    
+	    set checkedvar $key; append checkedvar "_checked"
+	    set RecognizedTypesChecks($checkedvar) 0
+	    set checkbox [checkbutton $framebox.$c -variable [itcl::scope RecognizedTypesChecks($checkedvar)]]
+	    
+	    set keybox [iwidgets::entryfield $framebox.$y -clientdata "Keybox$f" ]
+	    $keybox insert 0 $key
+	    
+	    set valbox [iwidgets::entryfield $framebox.$v -clientdata "Valbox$v" ]
+	    $valbox insert 0 $val
+	    
+	    pack $checkbox $keybox $valbox  -padx 4 -pady 4 -side left
+	    pack $framebox -side top
+	    
+	    lappend mdEntries $checkedvar
+	    lappend mdEntries $keybox
+	    lappend mdEntries $valbox
+	    
+	}
+	
+	$RecogTypeDialogName hide Help
+	$RecogTypeDialogName hide Cancel
+	$RecogTypeDialogName hide Apply
+	eval "$RecogTypeDialogName buttonconfigure OK -command { $this recognizedTypeDialogCallback $RecogTypeDialogName OK }"
+	eval "$RecogTypeDialogName add Add -text Add -command { $this recognizedTypeDialogCallback $RecogTypeDialogName Add }"
+	eval "$RecogTypeDialogName add Delete -text \"Delete Checked\" -command { $this recognizedTypeDialogCallback $RecogTypeDialogName Delete }"
+	
+    }
+    
+    set dialogEntries -1
+    
+    for { set k 0 } { $k < [llength $keylist] } { incr k } {
+	set key [lindex $keylist $k]
+	set varname $key; append varname "_checked"
+    }
+    
+    wm geometry $RecogTypeDialogName +300+200
+    $RecogTypeDialogName activate
+    
+    return $dialogEntries
+    
+};#End showRecognizedTypes method
+
+
+::itcl::body bis_treegui::recognizedTypeDialogCallback { dialogname mode } {
+    
+    if { $mode == "Cancel" } {
+	$dialogname deactivate
+    }
+    
+    set dialogEntries ""
+    foreach {checkbox keyentry valentry} $mdEntries {
+#	puts [$checkbox cget -variable]
+	lappend dialogEntries [$keyentry get]	   
+	lappend dialogEntries [$valentry get] 
+    }
+    
+    #--------------------------------------------------------------------------------
+    if {$mode == "Add"} {
+	set newList $dialogEntries
+	lappend newList 99999
+	lappend newList "New Type"
+	
+	$dialogname deactivate
+    	set RecogTypeDialogName -1
+	showRecognizedTypes $newList
+    }
+
+    #--------------------------------------------------------------------------------
+    if {$mode == "Delete"} {
+	set dialogEntries ""
+	foreach {checkvar keyentry valentry} $mdEntries {
+	    if {$RecognizedTypesChecks($checkvar) != 1} {
+		lappend dialogEntries [$keyentry get]	   
+		lappend dialogEntries [$valentry get] 
+	    }
+	}
+	set newList $dialogEntries
+	$dialogname deactivate
+    	set RecogTypeDialogName -1
+	showRecognizedTypes $newList
+    }
+    
+    #--------------------------------------------------------------------------------
+    if { $mode == "OK" } {
+	$dialogname deactivate
+    }
+}
+
+
+::itcl::body bis_treegui::setRecognizedTypes { } {
+    
+    set newarray [showRecognizedTypes [array get RecognizedTypes] ]
+    if {$newarray != -1} {
+	catch {array unset RecognizedTypes}
+	array set RecognizedTypes $newarray
+    }
+    
+}
+
+
+
+::itcl::body bis_treegui::SearchTree { realtreename startnode key values } {
+    
+    set SearchResult ""
+    foreach val $values {
+	
+	set nodelist [$realtreename children -all $startnode]
+	set ValList [$realtreename attr $key -nodes $nodelist]
+	
+	
+	foreach { node nodevalue } $ValList {
+	    if {$nodevalue == $val} {
+		lappend SearchResult $node
+	    }
+	}
+	
+    }
+    
+    if {[llength $SearchResult]} {
+	set SearchResult [lsort $SearchResult]
+    }
+    
+    #    puts "The following nodes have value(s) of $values for key \"$key\": $SearchResult"
+    return $SearchResult
+    
+}
+
+##########################################################################################
+
+::itcl::body bis_treegui::makeFileMenu { menu0 } {
+
+    eval "$menu0 add command -label \"New Datatree\"  -command { $this mdNewTree  } -underline 0  -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Load Datatree\" -command { $this mdLoadTree } -underline 0 -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Save Datatree\" -command { $this mdSaveTree } -underline 0 -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator 
+    eval "$menu0 add command -label \"Save Reorganized Copy\" -command { $this saveReorganize } -underline 0 -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator 
+    eval "$menu0 add command -label \"Switch Directory\" -command { $this SwitchDirectory } "
+    set thisparam($this,custdirectories)  [ pxitclfilelistmenu \#auto $menu0 "Custom Directories" "$this SwitchDirectory" ]
+    $thisparam($this,custdirectories) SetModeToDirectories
+    $thisparam($this,custdirectories) InitializeDisplay
+
+    global env
+    set thisparam($this,custtrees)  [ pxitclfilelistmenu \#auto $menu0 "Previous Trees" "$this mdLoadTree" "$this mdGetTreeFileName" ]
+    $thisparam($this,custtrees) SetModeToCustom "DataTrees" .tre [ file join $env(HOME) .datatrees ] 1 
+    $thisparam($this,custtrees) InitializeDisplay
+
+    $menu0 add separator 
+    eval "$menu0 add command -label Exit -command { $this OnWidgetClose; } -underline 1 -activebackground \"$menuactivebgcolor\""
+}
+
+::itcl::body bis_treegui::makeEditMenu { menu0 } {
+
+    eval "$menu0 add command -label \"Cut\" -command {$this mdCopy 1} -underline 1 -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Copy\" -command {$this mdCopy 0} -underline 0 -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Undo\" -command {$this undo} -underline 0 -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Redo\" -command {$this redo} -underline 0 -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator
+    eval "$menu0 add command -label \"Paste\" -command {$this mdPaste} -activebackground \"$menuactivebgcolor\""   
+    $menu0 add separator
+    eval "$menu0 add checkbutton -label \"Enable Drag and Drop\" -variable {[itcl::scope dragAndDropEnabled]} \
+	    -onvalue 1 -offvalue 0 -activebackground \"$menuactivebgcolor\""
+ }
+
+::itcl::body bis_treegui::makeToolsMenu { menu0 } {
+
+    set toolsmenu $menu0
+    eval "$menu0 add command -label \"Multiple Image Calculations\" -command { $this SearchDialog } -activebackground \"$menuactivebgcolor\""   
+
+    #------------------------------------------------------------------------------------------
+    # If the SPECT module is loaded, make a menu for it
+    if {$enable_SPECT == 1} {
+	eval "$menu0 add command -label \"SPECT Processing Tool\" -command { $this ShowSPECTtool } -activebackground \"$menuactivebgcolor\""  
+    }
+    
+    if {$enable_AdvancedReg == 1 } {
+	eval "$menu0 add command -label \"Advanced Registration Tool\" -command { $this ShowREGtool } -activebackground \"$menuactivebgcolor\""  
+   }
+    
+    #eval "$menu0 add command -label \"Image Processing\" -command { $this showImageProcessTool } -activebackground \"$menuactivebgcolor\""  
+
+    #showImageProcessTool
+
+   #------------------------------------------------------------------------------------------
+    # If the atlas module is loaded, make a menu for it
+    if {$enable_atlas == 1} {
+	$menu0 add cascade -label "Atlas" -menu $menu0.atlas -activebackground "$menuactivebgcolor"
+	set atlasSubMenu [menu $menu0.atlas -tearoff 0]
+       	makeAtlasMenu $atlasSubMenu
+    }
+    
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+}
+
+
+#----------------------------------------------------------------------
+# Node Menu and Tree Popup Menu Option Methods (Can be accessed from elsewhere, too)
+# (This Menu is associated with image files)
+#----------------------------------------------------------------------
+
+::itcl::body bis_treegui::printTree { } {
+    $dustin printSelf
+}
+
+
+::itcl::body bis_treegui::makeImageMenu { menu0 } {
+    #Set the "Node" menu contents (same as tree popup menu contents)
+    eval "$menu0 add command -label \"Printtree\" -command { $this printTree } -underline 0 -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator
+    eval "$menu0 add command -label \"Set Filename\" -command { $this setFileName } -underline 0 -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator
+    eval "$menu0 add command -label \"Rename\" -command { $this setTitle } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label Delete -command { $this delSelectedFromTree } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    $menu0 add separator
+    eval "$menu0 add command -label \"Add an Image as Child\" -command { $this addNodeToTree Image } -underline 7 -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Add a ROI as Child\" -command { $this addROIDefToTree } -activebackground \"$menuactivebgcolor\""
+    $menu0 add cascade -label "Add a Surface as Child" -menu $menu0.surfsub -activebackground "$menuactivebgcolor"
+    set surfsubmenu [menu $menu0.surfsub -tearoff 0]
+    eval "$surfsubmenu add command -label \"Surface\" -command { $this addNodeToTree Surface } -background \"$menucolor\" -activebackground \"$menuactivebgcolor\""
+    eval "$surfsubmenu add command -label \"Landmark\" -command { $this addNodeToTree Landmark } -background \"$menucolor\" -activebackground \"$menuactivebgcolor\""
+    eval "$surfsubmenu add command -label \"Electrode\" -command { $this addNodeToTree Electrode } -background \"$menucolor\" -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Add a Folder as Child\" -command { $this addNodeToTree Folder } -activebackground \"$menuactivebgcolor\""    
+    $menu0 add cascade -label "Add Subtree" -menu $menu0.subtreesub -activebackground "$menuactivebgcolor"
+    set subtreemenu [menu $menu0.subtreesub -tearoff 0]
+    eval "$subtreemenu add command -label \"Native Type\" -command { $this addSubtree } -activebackground \"$menuactivebgcolor\""        
+    eval "$subtreemenu add command -label \"Multisubject Definition (*.msb)\" -command { $this addSubtreeAtSelection 5} -activebackground \"$menuactivebgcolor\""  
+    $menu0 add separator
+    eval "$menu0 add command -label \"Load Transformation FROM Parent\" -command { $this setTransFromParent } -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Load Transformation TO Parent (if nonlinear)\" -command { $this setTransToParent } -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"(Un)set as Identity\" -command {$this setIdentityToggle } -activebackground \"$menuactivebgcolor\""
+}
+
+#----------------------------------------
+#This menu will go with Surfaces and Landmarks
+#----------------------------------------
+
+::itcl::body bis_treegui::makeSurfaceMenu { menu0 } {
+
+    #Set the "Node" menu contents (same as tree popup menu contents)
+    eval "$menu0 add command -label \"Set Filename\" -command { $this setFileName } -underline 0 -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator
+    eval "$menu0 add command -label \"Rename\" -command { $this setTitle } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label Delete -command { $this delSelectedFromTree } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    $menu0 add separator
+    eval "$menu0 add command -label \"Send to Left Viewer\"  -command { $this sendSelectionToDisplay 1 \"\" } -underline 9 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label \"Send to Right Viewer\" -command { $this sendSelectionToDisplay 2 \"\" } -underline 9 -activebackground \"$menuactivebgcolor\"" 
+    $menu0 add separator
+    eval "$menu0 add command -label \"Send to Left Viewer (in Reference Space)\"  -command { $this sendSelectionToDisplay 1 \"\" 1} -underline 9 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label \"Send to Right Viewer (in Reference Space)\" -command { $this sendSelectionToDisplay 2 \"\" 1} -underline 9 -activebackground \"$menuactivebgcolor\"" 
+}
+
+::itcl::body bis_treegui::makeFolderMenu { menu0 } {
+    
+    eval "$menu0 add command -label \"Rename\" -command { $this setTitle  } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label Delete -command { $this delSelectedFromTree } -underline 0 -activebackground \"$menuactivebgcolor\"" 
+    $menu0 add separator
+    eval "$menu0 add command -label \"Add an Image as Child\" -command { $this addNodeToTree Image } -underline 7 -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Add an ROI Definition\" -command { $this addROIDefToTree } -activebackground \"$menuactivebgcolor\""
+    $menu0 add cascade -label "Add Subtree" -menu $menu0.subtreesub -activebackground "$menuactivebgcolor"
+    set subtreemenu [menu $menu0.subtreesub -tearoff 0]
+    eval "$subtreemenu add command -label \"Native Type\" -command { $this addSubtree } -activebackground \"$menuactivebgcolor\""        
+    eval "$subtreemenu add command -label \"Multisubject Definition (*.msb)\" -command { $this addSubtreeAtSelection 5} -activebackground \"$menuactivebgcolor\""   
+}
+
+#----------------------------------------
+#This menu will go with Electrodes
+#----------------------------------------
+::itcl::body bis_treegui::makeElectrodeMenu { menu0 } {
+    #Set the "Node" menu contents (same as tree popup menu contents)
+    eval "$menu0 add command -label \"Set Filename\" -command { $this setFileName } -underline 0 -activebackground \"$menuactivebgcolor\""
+   
+    #If the attribute package is loaded, then allow manipulation of attirbutes
+    if {$enable_elec_att == 1} {
+	$menu0 add separator
+	eval "$menu0 add command -label \"Attribute Visualization Control\" -command { $this SendElectrodeToAtrrControl } -underline 0 -activebackground \"$menuactivebgcolor\""
+	eval "$menu0 add command -label \"Load Attributes\" -command { $this mdLoadElectrodeAttributes } -underline 0 -activebackground \"$menuactivebgcolor\""
+	eval "$menu0 add command -label \"Update Attributes from Viewer Electrodes\" -command { $this grabElectrodeAttributes 1 } -underline 0 -activebackground \"$menuactivebgcolor\""
+	
+    }
+    $menu0 add separator
+    eval "$menu0 add command -label \"Rename\" -command { $this setTitle } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label Delete -command { $this delSelectedFromTree } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    $menu0 add separator
+    eval "$menu0 add command -label \"Send to Electrode Control 1\" -command { $this sendSelectionToDisplay 1 \"\" } -underline 9 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label \"Send to Electrode Control 1 (in Reference Space)\" -command { $this sendSelectionToDisplay 1 \"\" 1 } -underline 9 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label \"Send to Electrode Control 2\" -command { $this sendSelectionToDisplay 2 \"\" } -underline 9 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label \"Send to Electrode Control 2 (in Reference Space)\" -command { $this sendSelectionToDisplay 2 \"\" 1} -underline 9 -activebackground \"$menuactivebgcolor\""    
+}
+
+
+#------------------------------------------------------------------------------------------
+# This Menu is associated with Patient nodes
+#------------------------------------------------------------------------------------------
+::itcl::body bis_treegui::makePatientMenu { menu0 } {
+    
+    #Set the "Patient" menu contents (same as tree popup menu contents)
+    eval "$menu0 add command -label \"Rename\" -command { $this setTitle } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    eval "$menu0 add command -label \"Delete Selected Patient\" -command { $this delSelectedFromTree } -underline 0 -activebackground \"$menuactivebgcolor\""    
+    $menu0 add separator
+    eval "$menu0 add command -label \"Load Transformation FROM Parent\" -command { $this setTransFromParent } -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Load Transformation TO Parent (if nonlinear)\" -command { $this setTransToParent $this } -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator
+    eval "$menu0 add command -label \"Add a Patient to Tree at Selection\" -command { $this addPatientToTree } -underline 0 -activebackground \"$menuactivebgcolor\""    
+}
+
+#------------------------------------------------------------------------------------------
+# This Menu is associated with the top Data node
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_treegui::makeDataMenu { menu0 } {
+    
+    eval "$menu0 add command -label \"Add an Image as Child\" -command { $this addNodeToTree Image } -underline 7 -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Add a ROI as Child\" -command { $this addROIDefToTree } -activebackground \"$menuactivebgcolor\""
+    eval "$menu0 add command -label \"Add a Folder as Child\" -command { $this addNodeToTree Folder } -activebackground \"$menuactivebgcolor\""    
+    $menu0 add cascade -label "Add Subtree" -menu $menu0.subtreesub -activebackground "$menuactivebgcolor"
+    set subtreemenu [menu $menu0.subtreesub -tearoff 0]
+    eval "$subtreemenu add command -label \"Native Type\" -command { $this addSubtree } -activebackground \"$menuactivebgcolor\""        
+    eval "$subtreemenu add command -label \"Multisubject Definition (*.msb)\" -command { $this addSubtreeAtSelection 5} -activebackground \"$menuactivebgcolor\"" 
+}
+
+#------------------------------------------------------------------------------------------
+# This Menu is for bringing up and dealing with the Atlas Tool
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_treegui::makeAtlasMenu { menu0 } {
+    
+    eval "$menu0 add command -label \"Open Atlas Tool\" -command { $this ShowAtlas } -activebackground \"$menuactivebgcolor\"" 
+    eval "$menu0 add command -label \"Send Selected Image to Atlas Tool\" -command { $this AtlasShowSelectedNode } -activebackground \"$menuactivebgcolor\"" 
+    $menu0 add separator
+    eval "$menu0 add command -label \"Add Atlas to Tree at Selection\" -command { $this addAtlasToTree } -activebackground \"$menuactivebgcolor\""  
+    
+    #Set the background for all menu entries
+    for {set i 0} {$i <= [$menu0 index end]} {incr i} {
+	$menu0 entryconfigure $i -background $menucolor 
+    }
+}
+
+#------------------------------------------------------------------------------------------
+# This is the definition method for the Options Menu
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_treegui::makeOptionsMenu { menu0 } {
+    
+    eval "$menu0 add checkbutton -label \"Lock Space Image\" -variable {[itcl::scope SpaceLocked]} \
+-onvalue 1 -offvalue 0 -command {$this updateBigTransLines} -activebackground \"$menuactivebgcolor\""
+    $menu0 add separator
+    eval "$menu0 add command -label \"View/Set Recognized Image Types\" -command { $this setRecognizedTypes } -activebackground \"$menuactivebgcolor\""  
+    eval "$menu0 add command -label \"Save Image Type Definition File\" -command { $this mdSaveTypeDefs } -activebackground \"$menuactivebgcolor\""  
+    eval "$menu0 add command -label \"Load Image Type Definition File\" -command { $this mdLoadTypeDefs } -activebackground \"$menuactivebgcolor\""  
+    $menu0 add separator    
+    eval "$menu0 add command -label \"Edit Patient Property List\" -command { $this EditPatientPropList } -activebackground \"$menuactivebgcolor\""  
+    $menu0 add separator
+    
+    $menu0 add cascade -label "File Path Save Mode" -menu $menu0.savemodesub -activebackground "$menuactivebgcolor"
+    set savemodemenu [menu $menu0.savemodesub -tearoff 0]
+    eval "$savemodemenu add radio -label Relative -variable {[itcl::scope relativePath]} -value 1 -activebackground \"$menuactivebgcolor\""
+    eval "$savemodemenu add radio -label Absolute -variable {[itcl::scope relativePath]} -value 0 -activebackground \"$menuactivebgcolor\""
+    
+    $menu0 add separator
+    $menu0 add cascade -label "Choose Icon Colors" -menu $menu0.icontypesub -activebackground "$menuactivebgcolor"
+    set icontypecascade [menu $menu0.icontypesub -tearoff 0]
+    
+    $icontypecascade add cascade -label "Images" -menu $icontypecascade.colorsub1 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub1 -tearoff 0]
+    makeColorMenu $colormenu brainiconchoice
+    
+    $icontypecascade add cascade -label "Surfaces" -menu $icontypecascade.colorsub2 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub2 -tearoff 0]
+    makeColorMenu $colormenu surfaceiconchoice
+    
+    $icontypecascade add cascade -label "Results" -menu $icontypecascade.colorsub3 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub3 -tearoff 0]
+    makeColorMenu $colormenu resulticonchoice
+
+    $icontypecascade add cascade -label "ROI Definitions" -menu $icontypecascade.colorsub4 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub4 -tearoff 0]
+    makeColorMenu $colormenu roiiconchoice
+}
+
+#------------------------------------------------------------------------------------------
+# This is the definition method for the View Menu
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_treegui::makeViewMenu { menu0 } {
+    
+    #$menu0 add separator
+    $menu0 add cascade -label "Choose Icon Colors" -menu $menu0.icontypesub -activebackground "$menuactivebgcolor"
+    set icontypecascade [menu $menu0.icontypesub -tearoff 0]
+    
+    $icontypecascade add cascade -label "Images" -menu $icontypecascade.colorsub1 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub1 -tearoff 0]
+    makeColorMenu $colormenu brainiconchoice
+    
+    $icontypecascade add cascade -label "Surfaces" -menu $icontypecascade.colorsub2 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub2 -tearoff 0]
+    makeColorMenu $colormenu surfaceiconchoice
+    
+    $icontypecascade add cascade -label "Results" -menu $icontypecascade.colorsub3 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub3 -tearoff 0]
+    makeColorMenu $colormenu resulticonchoice
+
+    $icontypecascade add cascade -label "ROI Definitions" -menu $icontypecascade.colorsub4 -activebackground "$menuactivebgcolor"
+    set colormenu [menu $icontypecascade.colorsub4 -tearoff 0]
+    makeColorMenu $colormenu roiiconchoice
+}
+
+::itcl::body bis_treegui::makeColorMenu { colormenu icon } {
+    
+    eval "$colormenu add radio -label Red -variable {[itcl::scope $icon]} -value ibrainred -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label Orange -variable {[itcl::scope $icon]} -value ibrainorange -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label Yellow -variable {[itcl::scope $icon]} -value ibrainyellow -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label Green -variable {[itcl::scope $icon]} -value ibraingreen -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label Blue -variable {[itcl::scope $icon]} -value ibrainblue -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label \"Light Blue\" -variable {[itcl::scope $icon]} -value ibrainlightblue -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label Purple -variable {[itcl::scope $icon]} -value ibrainpurple -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+    eval "$colormenu add radio -label Rainbow -variable {[itcl::scope $icon]} -value ibrainrainbow -command { $this updateVisTree $vistree $RealTree } -activebackground \"$menuactivebgcolor\""
+}
+
+::itcl::body bis_treegui::addNodeToTree { type { title "" } { path "" } } {
+    
+    if { $path == "" } { set path $selectionPath }
+ 
+    if { $type == "Image" && $title == ""} { 
+	set title [ ImageEntryDialog ]
+    } elseif { $title == "" } {
+	set title [ Single_Entry_Dialog "Set Title" "Enter the name for this node" $type ]
+    }
+
+    if { $title == "" } { return }
+    
+    if { [checkForIllegalCharacters $title] } {
+	set title [ $dustin uniqueTitle $title $path ]
+	$dustin addNode $title $path $type
+	updateTreeWidget
+	setDisplayBox "$path/$title"
+	setUndoList; set TreeChanged 1
+    } else {
+	addNodeToTree $type 
+    }
+}
+
+::itcl::body bis_treegui::addSubtreeAtSelection { {type 1} } {
+    
+    $mdTopWidget config -cursor watch;  update idletasks
+
+    switch -exact -- $type {
+
+	1 { AddSubtree $RealTree [GetIDFromSelection] }
+	2 { AddMultiSubjfMRI $RealTree [GetIDFromSelection] }
+	3 { AddCSIPatient $RealTree [GetIDFromSelection] }
+	4 { AddAllCSI $RealTree [GetIDFromSelection] }
+	5 { AddMSBData $RealTree [GetIDFromSelection] }
+	
+    }
+	$mdTopWidget config -cursor ""
+}
+
+::itcl::body bis_treegui::delSelectedFromTree { } {
+        
+    if { $selectionPath == [ lindex $anatomicalImageList 0 ] } {
+	set anatomicalImageList ""
+    }
+    if { $selectionPath == [ lindex $functionalImageList 0 ] } {
+	set functionalImageList ""
+    } 
+    if { $selectionPath == [ lindex $spaceImageList      0 ] } {
+	set spaceImageList ""
+    }
+    updateRightCanvasDisplay
+
+    set deletedNode $selectionPath
+    setDisplayBox [ $dustin getNodeParent $selectionPath ]
+    updateGUI
+    puts $deletedNode
+    $dustin deleteNode $deletedNode
+    updateTreeWidget   $deletedNode
+    setUndoList; set TreeChanged 1
+}
+# -----------------------------------------------------
+
+::itcl::body bis_treegui::showImageProcessTool { } { 
+
+    set imageutility [ bis_guiimageutility \#auto ]
+    $imageutility InitializeFromContainer $surgerygadget
+    set w $mdmenubar.$imageutility
+    
+    set imageutility [ $imageutility GetThisPointer ]
+    $imageutility CreateGUI $w 
+    $imageutility AddToMenuButton $toolsmenu
+}
+
+#------------------------------------------------------------------------------------------
+# These are the SPECT Processing Module Integration Methods
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_treegui::ShowSPECTtool { } {
+
+    if {$SPECT_initialized == 0} {
+	$SPECTmodule Initialize .[pxvtable::vnewobj] $this $viewer2
+	set SPECT_initialized 1
+    }
+
+    $SPECTmodule ShowTop
+}
+
+::itcl::body bis_treegui::ShowREGtool { } {
+
+    if {$REG_initialized == 0} {
+	$REGmodule Initialize .[pxvtable::vnewobj] $this
+	set REG_initialized 1
+    }
+    $REGmodule ShowTop
+
+}
+
+
+#------------------------------------------------------------------------------------------
+# This is the end of the SPECT Processing Module Integration Methods
+#------------------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------------------
+# These are the Electrode Attribute Control Module Integration Methods
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_treegui::mdLoadElectrodeAttributes { } { 
+
+ 
+    catch {unset AttrArray}
+    set newlyLoadedArray [$FileManager LoadElectrodeAttributes]
+    if { $newlyLoadedArray != -1} {array set AttrArray $newlyLoadedArray} else {return -1}
+    
+    #Get all grids, and set up a lookup array
+    #----------------------------------------------------------------------
+    set ThisNode [GetIDFromSelection]
+    EnsureFileLoaded $ThisNode
+    set electrodeobj        [$RealTree get $ThisNode pxitclobj]
+    set electrodemultigrid  [$electrodeobj GetObject]
+   
+    set ng [$electrodemultigrid GetNumberOfGrids] 
+
+    for {set gridnumber 0} {$gridnumber < $ng} {incr gridnumber} {
+	set grid [ $electrodemultigrid GetElectrodeGrid $gridnumber ]
+	set gridname [ $grid GetGridName  ]
+	set gridletter [ string range [ string trim $gridname ] 0 0 ]
+	set gridnum($gridletter) $gridnumber
+	
+	scan [ $grid GetDimensions ] "%d %d" dimx dimy
+	set gridsize [ expr $dimx * $dimy ]
+	
+	# Make an array to hash real index to internal index
+	#iindex = electrodeInternalIndex(gridnumber,realindex)
+	for {set j 0} {$j < $gridsize} {incr j} {
+	    set realindex [ $grid GetElectrodeRealIndex $j ]
+	    set electrodeInternalIndex($gridnumber,$realindex) $j
+	    set elec [ $grid GetElectrode $j ]
+	    $elec SetElectrodePresent 0
+	    set values [ $elec GetValues ]
+	    $values SetNumberOfTuples [llength $AttrArray(titles)]
+	    $values FillComponent 0 -1.0
+	}
+    }
+    #----------------------------------------------------------------------
+
+    set l [llength [array names AttrArray]]
+
+    # Now read the attribute array back out and store it in appropriate electrode
+
+    for { set i 0 } { $i < $l } { incr i } {
+	
+	set thisname [lindex [lsort [array names AttrArray]]  $i]
+
+	if {$thisname != "titles"} {
+	    #####-------
+	    set gridletter [string range $thisname 0 [expr [string first , $thisname] - 1] ]
+	    #####-------
+	    
+	    set firstcommaindex [string first , $thisname]
+	    set secondcommaindex [string first , $thisname [expr $firstcommaindex + 1] ]
+	    
+	    #####-------
+	    set electrodenumber [ string range $thisname [expr $firstcommaindex + 1] [expr $secondcommaindex - 1] ]
+	    set valueindex      [ string range $thisname [expr $secondcommaindex +1 ] end ]
+	    
+	    #####-------
+	    
+	    set gridindex $gridnum($gridletter) 
+	    set electrodeindex $electrodeInternalIndex($gridindex,$electrodenumber) 
+	    
+	    set grid       [ $electrodemultigrid GetElectrodeGrid $gridindex ]
+	    set electrode  [ $grid GetElectrode $electrodeindex ]
+	    $electrode SetElectrodePresent 1
+
+	    [ $electrode GetValues ] SetComponent $valueindex 0 $AttrArray($gridletter,$electrodenumber,$valueindex)
+#	    puts stderr "$gridletter, $electrodenumber $valueindex =  $AttrArray($gridletter,$electrodenumber,$valueindex) "
+	} else {
+#	    puts stderr "$thisname is bad"
+	}
+    }
+
+    #----------------------------------------------------------------------
+    #Now all electrode properties have been set - Save a file
+    #----------------------------------------------------------------------
+
+    #Save a new file
+    set newName "[file rootname [$RealTree get $ThisNode FileName]]_Attr_Loaded.mgrid"
+    $electrodemultigrid Save $newName
+    
+    set changefname [tk_messageBox -type yesno -default no -title "Warning"\
+			  -message "Would you like to have this node in the tree point to the new electrode file you just created?" -icon question]
+
+    if {$changefname == "no"} { return -1 }
+    if {$changefname == "yes"} {
+	setNodeFilename $ThisNode $newName
+	$RealTree set $ThisNode Attributes $AttrArray(titles)
+	$RealTree set $ThisNode notes "The following attributes are loaded for this electrode file:\n-------------------------------------------------------------\n\n$AttrArray(titles)"
+    }
+    
+
+
+
+}; #end mdLoadElectrodeAttributes method
+
+
+::itcl::body bis_treegui::SendElectrodeToAtrrControl { { nodeID -1} {raise 1} } {
+    
+    if {$nodeID == -1} {
+	set node [GetIDFromSelection]
+    } else { set node $nodeID }
+    	
+
+    if {$node != -1 && $node != ""} {
+	    
+	#--------------------------------------------------
+	# First be sure node is an electrode, and is loaded
+	#--------------------------------------------------
+	EnsureFileLoaded $node
+	set pxielectrodeobj [$RealTree get $node pxitclobj]
+	set type [$RealTree get $node type]
+	if {$type != {Surface Electrode} } { 
+	    error "The selected object is not an Electrode Map"
+	    return -1  
+	}
+	
+	#--------------------------------------------------
+	# Now transform the selected electrode to ref space
+	#--------------------------------------------------
+	
+	if {$SpaceImage != -1} {
+	    
+	    findTransforms $RealTree $node $SpaceImage
+	    set BottomUpTransList $TransformsCache($myname,$node:$SpaceImage)
+	    EnsureTransListLoaded $BottomUpTransList
+	    
+	    set gen [ CreateTransformation $BottomUpTransList ]
+	    set newelec [ [pxitclelectrodemultigrid \#auto] GetThisPointer ]
+	    $newelec Copy $pxielectrodeobj
+	    $newelec Transform $gen
+	    
+	    #--------------------------------------------------
+	    # Now send the transformed electrode object, space 
+	    # image object, and selected node's  Attribute title 
+	    # list to the Attribute Control
+	    #--------------------------------------------------
+	    
+	    
+	    set SpaceImageObject [$RealTree get $SpaceImage pxitclobj]
+	    $ElectAttrModule SetElectrodeObject $newelec  $SpaceImageObject \
+		[$RealTree get $node Attributes] [$RealTree get $node FileName]
+	    if {$raise} {
+		$ElectAttrModule ShowTop
+	    } 
+	    
+	} else {
+	    error "You must have a Space Image set in order to create an electrode visulization overlay."
+	    return -1
+	}
+	
+	
+    }
+    
+};# end SendElectrodeToAttrControl method
+
+::itcl::body bis_treegui::PutElectrodeAttrControlOutputInTree { } {
+
+    if { [$ElectAttrModule GetOutputImage] != -1 } {
+
+	set NewImage [$ElectAttrModule GetOutputImage]
+	
+	set ObjectID $MasterCount
+	incr MasterCount
+	$RealTree insert $SpaceImage end $ObjectID
+	ImageInitialize $RealTree $ObjectID
+
+	[$RealTree get $ObjectID pxitclobj] ShallowCopy $NewImage
+
+	nameNode $RealTree $ObjectID "Electrode_Overlay_$ObjectID"
+	toggleIdentity $ObjectID 1
+	
+	#-----------------------------------------------------------------------------
+	#Everything below here occurs for the initialization of any type added to tree
+	#-----------------------------------------------------------------------------
+	set pathList [$RealTree rootname]
+	set pathListIDs [$RealTree ancestors $ObjectID]
+	
+	for {set y [expr [llength $pathListIDs] - 1]} {$y > -1} {incr y -1} {
+	    if {[lindex $pathListIDs $y] != [$RealTree rootname]} {
+		lappend pathList [$RealTree get [lindex $pathListIDs $y] title]
+		
+	    }
+	}
+	
+	set pathName /
+	for {set i 0} {$i < [llength $pathList]} {incr i} {
+	    append pathName [lindex $pathList $i]
+	    append pathName /
+	}
+	append pathName [$RealTree get $ObjectID title]
+	set NodeIDs($pathName) $ObjectID
+	
+	set newfilename [$FileManager SaveFile [$RealTree get $ObjectID pxitclobj]]
+	setNodeFilename $ObjectID $newfilename
+	
+	updateVisTree $vistree $RealTree $ObjectID			
+
+	puts "[[$RealTree get $ObjectID pxitclobj] GetDescription]"
+
+
+    }
+
+};# end BringUpElectrodeAttrControl method
+
+
+#------------------------------------------------------------------------------------------
+# This is the end of the Electrode Attribute Control Module Integration Methods
+#------------------------------------------------------------------------------------------
+
+
+#------------------------------------------------------------------------------------------
+# ROI Definiton Stuff
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_treegui::addROIDefToTree { } {
+    
+    set newnode [lindex [AddROIDefNode $RealTree [GetIDFromSelection]] 2]
+    
+    #recalculate the transformation cache
+    if {[llength $newnode]} {
+	updateVisTree $vistree $RealTree $newnode
+    }
+}
+
+::itcl::body bis_treegui::AddROIDefNode { realtreename ParentNodeID {title -1}} {
+    
+    if {[llength $ParentNodeID] > 0} {
+	if {$title == -1} {
+	    set ROIDefTitle [Single_Entry_Dialog "ROI Definition" "Enter a name for the ROI Definition Image"]
+	} else { set ROIDefTitle $title }
+	
+	set origTitle $ROIDefTitle
+	
+	if {[string match $ROIDefTitle -1] | $ROIDefTitle == ""} { return } else {
+
+
+	    #----Input Validation----------------------------------------------------------------------
+	    for {set a 0} {$a < [string length $ROIDefTitle]} {incr a} {
+		set achar [string range $ROIDefTitle $a $a]
+		
+		if {![string is wordchar $achar] && ![string is space $achar] \
+			&& ![string match {[.]} $achar] && ![string match {[-]} $achar] && ![string match {[^]} $achar]} {
+		    
+		    error "Cannot add ROI image using character $achar  -- Node names can only can contain the following characters: \n     a-z, A-Z, 0-9, _, -, ., ^, and spaces"
+
+		}
+	    }
+	    #------------------------------------------------------------------------------------------
+	    
+	    
+	    set ProposedPath [file join [getPath $realtreename $ParentNodeID] $ROIDefTitle]
+	    set UniqueSuffix 1
+	    set suffixed 0
+	    
+	    while {[Tree::itemexists $vistree $ProposedPath]} {
+		
+		if { $suffixed == 1 } {
+		    #delete the suffix
+		    set ROIDefTitle [string replace $ROIDefTitle [string last _ $ROIDefTitle] end]
+		}
+		
+		append ROIDefTitle _ $UniqueSuffix
+		set ProposedPath [file join [getPath $realtreename $ParentNodeID] $ROIDefTitle]
+		set suffixed 1
+		incr UniqueSuffix
+	    }
+	    
+	    
+	    if {![Tree::itemexists $vistree $ProposedPath]} {
+		
+		#Create a unique identifier for the ROIDef
+		set ROIDefID $MasterCount
+		incr MasterCount
+		
+		set ROIDefImage $ROIDefID
+		
+		$realtreename insert $ParentNodeID end $ROIDefID
+		ROIDefInitialize $realtreename $ROIDefID
+		nameNode $realtreename $ROIDefID $ROIDefTitle
+		$realtreename set $ROIDefID type ROIDef
+		
+				
+	    } else { 
+		error "Please select a unique image name"
+	    }
+	}
+
+	set TreeChanged 1	
+	return [list $suffixed $origTitle $ROIDefID]
+	
+    } else {tk_messageBox -type ok -title "Need Selection" -message "Please select a parent in the tree" -icon info}
+}
+
+::itcl::body bis_treegui::ROIDefInitialize { realtreename node } {
+    
+    NodeInitialize $realtreename $node
+    
+    $realtreename set $node type ROIDef
+    $realtreename set $node pxitclobj [ [pxitclimage \#auto] GetThisPointer ]
+    
+    #A couple display properties for the node
+    $realtreename set $node icon $atlasiconchoice
+    $realtreename set $node linecolor red
+    
+    #This node property toggles the "identity" propery for the image - ie, no transformation 
+    $realtreename set $node FromParFilenameSet 0
+    $realtreename set $node ToParFilenameSet 0
+    $realtreename set $node IsIdentity 0
+    
+        
+};# end ROIDefInitialize method
+
+
+#------------------------------------------------------------------------------------------
+# end of ROI Definiton Stuff
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_treegui::bindx1 { W x y } {
+    
+    #Events for tree function
+    set lbl [Tree::labelat $W $x $y ]
+    $this setDisplayBox $lbl 
+}
+ 
+::itcl::body bis_treegui::setDisplayBox { nodePath } {
+   
+    if { $nodePath == "" } { return }
+    Tree::setCurrent $vistree $nodePath
+    Tree::setselection $vistree $nodePath
+    if { [ info exist selectionPath ] } { updateNotes }
+    set selectionPath [ lindex [ Tree::getselectionpath $vistree ] 0 ]
+    updateGUI 
+    $this displayFileName
+}
+
+::itcl::body bis_treegui::displayFileName { } {
+    
+    if { $selectionPath == "" } { return }
+    $descriptionbox delete 1.0 end
+    
+    if { [ isRoot $selectionPath ] } { 
+	$statusLabel config -text "Filename: Root"
+    } else {
+	$statusLabel config -text "Filename: [ $dustin getNodeFileName $selectionPath ]"
+    }
+}
+
+::itcl::body bis_treegui::bindxdouble1 { W x y } {
+    
+    set lbl [Tree::labelat $W $x $y]
+    if { $lbl == "" } { return }
+    Tree::setselection $W $lbl
+    if { ![ winfo exists $NodeInfoDialogName ] } { createNodeInfoGUI }
+    showNodeInfoBox
+}
+
+::itcl::body bis_treegui::bindx3 { W x y } {
+      
+    set lbl [Tree::labelat $W $x $y]
+    setDisplayBox $lbl
+    if { $lbl == "" } { return }
+
+    switch  -exact [ $dustin getNodeType $selectionPath ] {
+	Image     { set menu $popup          }
+	Surface   { set menu $surfacepopup   }
+	Landmark  { set menu $surfacepopup   }
+	Folder    { set menu $folderpopup    }
+	Electrode { set menu $electrodepopup }
+	default   { set menu $rootpopup      }
+    }
+    
+    tk_popup $menu [winfo pointerx $vistree] [winfo pointery $vistree]
+ }
+
+
+::itcl::body bis_treegui::bindxRightPane { W x y menu} {
+
+    tk_popup $menu [winfo pointerx $IC] [winfo pointery $IC]
+}
+
+
+
+#----------------------------------------------------------------------
+#drag and drop 
+#----------------------------------------------------------------------
+
+::itcl::body bis_treegui::bindxcontrol1 { W x y } { 
+    #Control Clicking on the tree adds multiple selections
+    if { $dragAndDropEnabled } { return 0 }
+    set lbl [Tree::labelat $W $x $y]
+    Tree::addselection $W $lbl
+    displayFileName    
+}
+
+::itcl::body bis_treegui::bindxmotion1 { W x y } {
+    
+    if { $dragAndDropEnabled == 0 } { return 0 }
+    if { $selectionPath == "/Data" } { return 0 }
+
+    set widget [ winfo containing [winfo pointerx $W] [winfo pointery $W] ]
+
+    if { $widget == $IC } { 
+	displayMarkerOnImageTab $W $x $y
+    } elseif { $widget == $vistree } {
+	set selectionPath [ lindex [ Tree::getselectionpath $W ] 0 ]
+	set currentPath   [ lindex [ Tree::getCurrentPath $W ] 0 ]
+	set lbl [Tree::labelat $W $x $y ]
+	Tree::setCurrent $vistree $lbl
+	$this displayFileName
+	if { $currentPath != "" && $selectionPath != "" } {
+	    $W configure -cursor plus
+	} else { 
+	    $W configure -cursor $theNoCursor
+	}
+    } else {
+	$W configure -cursor $theNoCursor
+   }
+}
+
+::itcl::body bis_treegui::displayMarkerOnImageTab { W x y } {
+
+    set width [ winfo width $vistree ]
+    catch {$IC delete box}
+
+    if { $x > [expr 63 + $width] && $x < [expr 203 + $width] && $y > 335 && $y < 448 } {
+
+	$IC create rect 23 265 163 375 -tag box
+	$W configure -cursor plus
+
+    } elseif { $x > [expr 203 + $width] && $x < [expr 343 + $width] && $y > 117 && $y < 230 } {
+
+	$IC create rect  163 47 303 157 -tag box
+	$W configure -cursor plus
+
+    } elseif { $x > [expr 353 + $width] && $x < [expr 493 + $width] && $y > 335 && $y < 448 } {
+
+	$IC create rect 313 265 453 375 -tag box
+	$W configure -cursor plus
+
+    } else { $W configure -cursor $theNoCursor }
+}
+
+
+::itcl::body bis_treegui::bindxrelease1 { W x y mode } {
+    
+    if { $dragAndDropEnabled == 0 } { return -1 }
+  
+    set widget [ winfo containing [winfo pointerx $W] [winfo pointery $W] ]
+    
+    $vistree configure -cursor ""
+    . configure -cursor ""
+
+    if { $widget == $IC } { 
+	$this releaseOnImagesTab $x $y 
+	return 0
+    }
+
+    if { $widget == $vistree && $mode } { 
+	$this releaseOnTreeCut $W $x $y  
+	return 0
+    }
+    
+    if { $widget == $vistree } { 
+	$this releaseOnTreeCopy $W $x $y  
+	return 0
+    }
+}
+
+::itcl::body bis_treegui::releaseOnTreeCut { W x y } {
+    
+    set selectionPath [ lindex [ Tree::getselectionpath $W ] 0 ]
+    set currentPath   [ lindex [ Tree::getCurrentPath $W ] 0 ]
+     
+    #puts "$selectionPath----------$currentPath"
+ 
+    if { $currentPath == "" } { return 0 }
+    if { $selectionPath == $currentPath } { return 0 }	
+
+    if { [ $this isCurrentAChildOfSelection $currentPath $selectionPath $W ] } { 
+	tk_messageBox -type ok -title "Warning" -message "Cannot cut a node to its descendant." -icon question
+	Tree::eraseCurrentBox $W 
+	return 0
+    }
+
+    if { [ $this isCurrentTheParentOfSelection $currentPath $selectionPath $W ] } {
+	tk_messageBox -type ok -title "Warning" -message "Unnecessary cut to parent node." -icon question
+	Tree::eraseCurrentBox $W 	
+	return 0
+    }
+
+    if {       [ $dustin getNodeType $currentPath ] == "Surface"   || \
+	       [ $dustin getNodeType $currentPath ] == "Electrode" || \
+	       [ $dustin getNodeType $currentPath ] == "Landmark" } {
+	
+	tk_messageBox -type ok -title "Cannot paste" -message "Surface cannot have children nodes"
+	Tree::eraseCurrentBox $W
+	return 0
+    } 
+    
+    set ok [ tk_messageBox -type okcancel -title "Warning" -message "Cutting from $selectionPath to $currentPath" -icon question ]
+    if { $ok == "ok" } {
+	set lbl [Tree::labelat $W $x $y ]
+	$this mdCopy 1 
+	Tree::setselection $W $lbl
+	$this displayFileName
+	$this mdPaste $currentPath
+	$this updateTreeWidget
+    }
+    
+    Tree::eraseCurrentBox $W 
+}
+
+::itcl::body bis_treegui::releaseOnTreeCopy { W x y } {
+
+    set selectionPath [ lindex [ Tree::getselectionpath $W ] 0 ]
+    set currentPath   [ lindex [ Tree::getCurrentPath $W ] 0 ]
+    
+    #puts "$selectionPath----------$currentPath"
+
+    if { $currentPath == "" } {	return 0 }
+	
+    if {     [ $dustin getNodeType $currentPath ] == "Surface"   || \
+	     [ $dustin getNodeType $currentPath ] == "Electrode" || \
+	     [ $dustin getNodeType $currentPath ] == "Landmark" } {
+	
+	tk_messageBox -type ok -title "Cannot paste" -message "Surface cannot have children nodes"
+	Tree::eraseCurrentBox $W
+	return 0
+    } 
+    
+    set ok [ tk_messageBox -type okcancel -title "Warning" -message "Copying from $selectionPath to $currentPath" -icon question ]
+    if { $ok == "ok" } {
+	set lbl [Tree::labelat $W $x $y ]
+	$this mdCopy 0 
+	Tree::setselection $W $lbl
+	$this displayFileName
+	$this mdPaste $currentPath
+	$this updateTreeWidget
+    }
+    
+    Tree::eraseCurrentBox $W 
+}
+
+::itcl::body bis_treegui::releaseOnImagesTab { x y } {
+
+    set width [ winfo width $vistree ]
+    catch {$IC delete box}
+
+    if { $x > [expr 63 + $width] && $x < [expr 203 + $width] && $y > 335 && $y < 448 } {
+	$this setSelectionAnatomical 
+    }
+
+    if { $x > [expr 203 + $width] && $x < [expr 343 + $width] && $y > 117 && $y < 220 } {
+	$this setSelectionSpace 
+    }
+    
+    if { $x > [expr 353 + $width] && $x < [expr 493 + $width] && $y > 335 && $y < 448 } {
+	$this setSelectionFunctional
+    }
+}
+
+::itcl::body bis_treegui::isCurrentAChildOfSelection { currentPath selectionPath W } {
+    
+    set exp "^$selectionPath/"
+    return [ regexp $exp $currentPath ]
+}
+
+::itcl::body bis_treegui::isCurrentTheParentOfSelection { currentPath selectionPath W } {
+
+    if { [ $dustin getNodeParent $selectionPath ] == $currentPath } { 
+	return 1 
+    } else { return 0 }
+}
+
+::itcl::body bis_treegui::showNodeInfoBox { } {
+
+    if { [ wm state $NodeInfoDialogName ] == "normal" } {
+	raise $NodeInfoDialogName
+    } else { 
+	wm deiconify $NodeInfoDialogName
+    } 
+}
+
+::itcl::body bis_treegui::createNodeInfoGUI { } {
+
+    set NodeInfoDialogName .[ pxvtable::vnewobj ]
+    set nodeDialogBGColor "Light Cyan"
+    toplevel $NodeInfoDialogName -bg $nodeDialogBGColor
+    wm geometry $NodeInfoDialogName +300+200
+    
+    set infolabelframe [ frame $NodeInfoDialogName.labelfr -bg $nodeDialogBGColor ]
+    set infolabeltext  [ label $infolabelframe.labeltxt -bg $nodeDialogBGColor -font -*-times-bold-r-normal-*-18-*-*-*-*-*-iso8859-1 ]
+    pack $infolabeltext -side left -padx [list 0 4]
+    
+    set   NodeInfoTopFrame [ labelframe $NodeInfoDialogName.topframe -bg $nodeDialogBGColor -labelwidget $infolabelframe ]
+    pack $NodeInfoTopFrame -side top -ipadx 3 -ipady 7 -padx 10 -pady [list 2 10] -expand true -fill both
+
+    foreach item [ list Type Title FileName TransFromParent TransToParent ] {
+	set frame [ frame $NodeInfoTopFrame.frame${item} -bg $nodeDialogBGColor ]
+	set entry${item} [ iwidgets::entryfield $frame.ent -background $nodeDialogBGColor -width 75  -labeltext "$item" -relief sunken ]
+	if { [ lsearch [ list Title FileName TransFromParent TransToParent ] $item ] > -1 } { 
+	    set but [ eval "button $frame.but -text ... -command { $this set${item} ; $this updateGUI } -background white -width 5" ]
+	}
+	
+	if { [ lsearch [ list FileName TransFromParent TransToParent ] $item ] > -1 } { 
+	    set clear [ eval "button $frame.clear -text \"Clear\" -command { $this clearTrans $item } -background white -width 5" ]
+	}
+
+	pack $frame.ent -fill both -padx {10 0} -side left -expand true
+	pack $frame     -side top -anchor w -expand true -fill x
+	catch { pack $but   -side left -padx {0 10} }
+	catch { pack $clear -side left -padx {0 10} }
+    }
+
+    set bottomframe [ frame $NodeInfoTopFrame.bottomsection      -background "$nodeDialogBGColor" ] ; pack $bottomframe -side top -expand 1 -fill both
+    set notelabel   [ label $bottomframe.notelabel -text "Notes" -background "$nodeDialogBGColor" ] ; pack $notelabel -side left
+    set notebox     [ iwidgets::scrolledtext $bottomframe.note -wrap none -vscrollmode static -hscrollmode static -width 5i -height 2i ]
+    pack $notebox -fill x -padx 10 -pady 10 -expand true -fill both -side left
+
+    ::iwidgets::Labeledwidget::alignlabels $entryTitle $entryType $entryFileName $entryTransFromParent $entryTransToParent
+   
+    updateGUI
+}
+
+::itcl::body bis_treegui::updateNotes { } {
+
+    if { ![ winfo exists $NodeInfoDialogName ] } { return }
+    if { ![ regexp {.+[^\n]} [ $NodeInfoDialogName.topframe.bottomsection.note get 1.0 end ] text ] } { set text "" }
+    set text [ regsub -all {\n} $text  \\n ]
+    $dustin setNodeNotes $text $selectionPath
+    $NodeInfoDialogName.topframe.bottomsection.note delete 1.0 end
+}
+
+::itcl::body bis_treegui::updateGUI { } {
+    
+    if { ![ winfo exists $NodeInfoDialogName ] } { return }
+
+    if {[ isRoot $selectionPath ]}  { set nodeTitle "Root" 
+    } else { set nodeTitle [ $dustin getNodeTitle $selectionPath ] }
+
+    wm title $NodeInfoDialogName "Info for $nodeTitle"
+    $NodeInfoDialogName.labelfr.labeltxt configure -text $nodeTitle 
+    
+    set updateList [ list Type Title FileName ] 
+    set hideList   [ list TransFromParent TransToParent ]
+
+    #surface,landmarks, and electrode all have same option definded above
+    switch  -exact [ $dustin getNodeType $selectionPath ] {
+	
+	Surface   { } 
+	Landmark  { } 
+	Electrode { }
+	Image     { 
+	    set updateList [ list Type Title FileName TransFromParent TransToParent ] 
+	    set hideList   [ list ]
+	}
+	Folder    {
+	    set updateList [ list Type ]
+	    set hideList   [ list FileName Title TransFromParent TransToParent ] 
+	}
+	default   {     
+	    set updateList [ list ]
+	    set hideList   [ list Type Title FileName TransFromParent TransToParent ] 
+	}
+    }
+    
+    foreach item $updateList {
+	catch { pack $NodeInfoDialogName.topframe.frame${item}       -side top -anchor w -expand true -fill x }
+	catch { pack $NodeInfoDialogName.topframe.frame${item}.ent   -fill both -padx {10 0} -side left -expand true } 
+	catch { pack $NodeInfoDialogName.topframe.frame${item}.but   -side left -padx {0 10} }
+	catch { pack $NodeInfoDialogName.topframe.frame${item}.clear -side left -padx {0 10} }
+	$NodeInfoDialogName.topframe.frame${item}.ent delete 0 end
+	$NodeInfoDialogName.topframe.frame${item}.ent insert 0 [ $dustin getNode${item} $selectionPath ]
+    }
+    
+    foreach item $hideList { 
+	catch { pack forget $NodeInfoDialogName.topframe.frame${item} }
+	catch { pack forget $NodeInfoDialogName.topframe.frame${item}.ent } 
+	catch { pack forget $NodeInfoDialogName.topframe.frame${item}.but }
+	catch { pack forget $NodeInfoDialogName.topframe.frame${item}.clear }
+    }
+
+    pack forget $NodeInfoDialogName.topframe.bottomsection -side top -expand 1 -fill both
+    pack $NodeInfoDialogName.topframe.bottomsection -side top -expand 1 -fill both
+    set text [ regsub -all {\\n} [ $dustin getNodeNotes $selectionPath ] \n ]
+    $NodeInfoDialogName.topframe.bottomsection.note insert 1.0 $text
+}
+
+::itcl::body bis_treegui::setPatientProperty { property entryfield } {
+    
+    #Get input from user
+    set thisinput6 [Single_Entry_Dialog "New Value" "Enter new value for $property"]
+    if {$thisinput6 != -1 } {
+
+	set thisnode [GetIDFromSelection]
+	array set tempProps [$RealTree get $thisnode Properties]
+    
+ 	set tempProps($property) $thisinput6
+
+	$RealTree set $thisnode Properties [array get tempProps]
+	
+	#update the nodeinfo box
+	$entryfield clear
+	$entryfield insert 0 $thisinput6
+
+	set TreeChanged 1
+
+    }
+
+
+}; #End setPatientProperty method
+
+::itcl::body bis_treegui::isRoot { nodeID } {
+    
+    return [ expr ![ regexp {(/)(.+)(/)} $selectionPath ] ]
+}     
+
+::itcl::body bis_treegui::setSelectionSpace { } {
+
+    if { [ isRoot $selectionPath ] } { return }
+    set filename [ $dustin getNodeFileName $selectionPath ] 
+   
+    if { $SpaceLocked == 1 } {
+	tk_messageBox -type ok -title "Warning: Cannot set Space Image" -message "Space Image Locked" -icon error ; return
+    }
+    
+    if { $filename  == "" } {
+	tk_messageBox -type ok -title "Warning: Cannot set Space Image" -message "Image Filename not set" -icon error ; return
+    }
+    
+    if { ![ file exist $filename ] } {
+	tk_messageBox -type ok -title "Warning: Cannot set Space Image" -message "Image Filename does not exist" -icon error ; return
+    }
+    
+    set spaceImageList [ list $selectionPath [ $dustin getNodeTitle $selectionPath ] ]
+    updateRightCanvasDisplay 
+}
+
+
+::itcl::body bis_treegui::setSelectionAnatomical { } {
+    
+    if { [ isRoot $selectionPath ] } { return }
+    set filename [ $dustin getNodeFileName $selectionPath ] 
+    
+    if { $filename  == "" } {
+	tk_messageBox -type ok -title "Warning: Cannot set Anatomical Image" -message "Image Filename not set" -icon error ; return
+    }
+    
+    if { ![ file exist $filename ] } {
+	tk_messageBox -type ok -title "Warning: Cannot set Anatomical Image" -message "Image Filename does not exist" -icon error ; return
+    }
+
+    set anatomicalImageList [ list $selectionPath [ $dustin getNodeTitle $selectionPath ] ]
+    updateRightCanvasDisplay 
+}
+
+::itcl::body bis_treegui::setSelectionFunctional { } {
+    
+    if { [ isRoot $selectionPath ] } { return }
+    set filename [ $dustin getNodeFileName $selectionPath ] 
+    
+    if { $filename  == "" } {
+	tk_messageBox -type ok -title "Warning: Cannot set Functional Image" -message "Image Filename not set" -icon error ; return
+    }
+    
+    if { ![ file exist $filename ] } {
+	tk_messageBox -type ok -title "Warning: Cannot set Functional Image" -message "Image Filename does not exist" -icon error ; return
+    }
+    
+    set functionalImageList [ list $selectionPath [ $dustin getNodeTitle $selectionPath ] ]
+    updateRightCanvasDisplay 
+}
+
+::itcl::body bis_treegui::updateOverlayCanvas { } {
+    
+    $OCanv delete presPIC
+    if { [ $surgerygadget cget -overlayinputbase ] != -1 && [ $surgerygadget cget -overlayinputfunc ] != -1 } {
+	set OC_reslice_presentPIC [ $OCanv create image $OCdispX $OCdispY -image multicolorbrain -anchor nw -tag presPIC ]
+    } 
+    
+    $OCanv delete ocSPACE
+    if { $spaceImageList == "" } {
+	set OC_SPACE [ $OCanv create text [ expr $OCdispX+205 ] [ expr $OCdispY+60 ] -text \
+			   "Space" -fill grey61 -font {helvetica 15 bold} -tag ocSPACE ]
+    } else {
+	set OC_SPACE [ $OCanv create text [expr $OCdispX+220] [expr $OCdispY+60] -text \
+			   "SPACE: [ lindex $spaceImageList 1 ]" -fill "darkgreen" -font {helvetica 11 bold} -tag ocSPACE -width 145 ]
+    }
+    
+    $OCanv delete ocFUNC
+    if { $functionalImageList == "" } {
+	set OC_FUNC [ $OCanv create text [ expr $OCdispX+375 ] [ expr $OCdispY+20 ] -text \
+			  "Functional" -fill grey61 -font {helvetica 15 bold} -tag ocFUNC ]
+    } else { 
+	set OC_FUNC [ $OCanv create text [ expr $OCdispX+315 ] [ expr $OCdispY+20 ] -text \
+			  "FUNCTIONAL: [ lindex $functionalImageList 1 ]" -fill "darkgreen" -font {helvetica 11 bold} -tag ocFUNC -width 150 -justify left -anchor w ]
+    }
+    
+    $OCanv delete ocANAT
+    if { $anatomicalImageList == "" } {
+	set OC_ANAT  [ $OCanv create text [ expr $OCdispX+375 ] [ expr $OCdispY+110 ] -text \
+			  "Anatomical" -fill grey61 -font {helvetica 15 bold} -tag ocANAT ]
+    } else { 
+	set OC_ANAT  [ $OCanv create text [ expr $OCdispX+315 ] [ expr $OCdispY+110 ] -text \
+			  "ANATOMICAL: [ lindex $anatomicalImageList 1 ]" -fill "darkgreen" -font {helvetica 11 bold} -tag ocANAT -width 150 -justify left -anchor w ]
+    }
+}
+
+::itcl::body bis_treegui::ShowTextBox { parent } {
+    
+    set base $parent
+    
+    frame $base.toptextboxframe    -width 450 -height 400
+    frame $base.bottomtextboxframe -width 450 -height 70
+    
+    set descriptionbox $base.toptextboxframe.descriptionbox 
+    set ybar    $base.toptextboxframe.ybar 
+    set xbar    $base.xbar 
+    eval "scrollbar $ybar  -command { $descriptionbox yview } -orient vertical"
+    eval "scrollbar $xbar  -command { $descriptionbox xview } -orient horizontal"
+    eval "text $descriptionbox  -width 150 -height 30  -wrap word -relief ridge -yscrollcommand { $ybar set} -xscrollcommand {$xbar set} -bg black -fg white"
+    
+    pack $base.bottomtextboxframe -side bottom -expand f -fill x -padx 5 -pady 2
+    pack $xbar -side bottom -expand f -fill x 
+    pack $base.toptextboxframe -side top -expand true -fill both -padx 2 -pady 5
+    pack $ybar -side right -expand false -fill y
+    pack $descriptionbox -side left -expand true -fill both
+    $descriptionbox configure -state disabled
+}
+
+::itcl::body bis_treegui::showGrabButtonDialog { } {
+    
+    if {![winfo exists $showGrabButtonDialogName]} {
+        set showGrabButtonDialogName .[ pxvtable::vnewobj ]
+	toplevel $showGrabButtonDialogName
+	wm title $showGrabButtonDialogName "Grab"
+	
+	#Create the control frame at the bottom of the left pane
+	set leftwrapperframe [frame $showGrabButtonDialogName.leftwrapper -bg "light blue"]
+	pack $leftwrapperframe -side bottom -fill x -padx 4 -pady 4
+	set leftcontrolsframe [labelframe $leftwrapperframe.controls -bg "light blue" -text "Grab Item From Viewer" -labelanchor n]
+	pack $leftcontrolsframe -side bottom -fill x -padx 4 -pady 2
+	
+	set refgrabsframe [labelframe $leftcontrolsframe.refgrabbuttons -bg "light blue" -text "Reference" -labelanchor s]
+	set transgrabsframe [labelframe $leftcontrolsframe.transgrabbuttons -bg "light blue" -text "Transform" -labelanchor s]
+    
+	set grimagebut [eval "button $refgrabsframe.getimg -text \"Image\" -command { $this PutViewerObjectInTree 1 Image}"]
+	set grsurfacebut [eval "button $refgrabsframe.getsurf -text \"Surface\" -command { $this PutViewerObjectInTree 1 Surface }"]
+	set grlandbut [eval "button $refgrabsframe.getland -text \"Landmark\" -command { $this PutViewerObjectInTree 1 Landmark }"]
+	set grelecbut [eval "button $refgrabsframe.getelec -text \"Electrode\" -command { $this PutViewerObjectInTree 1 Electrode }"]
+	set gtimagebut [eval "button $transgrabsframe.getimg -text \"Image\" -command { $this PutViewerObjectInTree 2 Image}"]
+	set gtsurfacebut [eval "button $transgrabsframe.getsurf -text \"Surface\" -command { $this PutViewerObjectInTree 2 Surface }"]
+	set gtlandbut [eval "button $transgrabsframe.getland -text \"Landmark\" -command { $this PutViewerObjectInTree 2 Landmark }"]
+	set gtelecbut [eval "button $transgrabsframe.getelec -text \"Electrode\" -command { $this PutViewerObjectInTree 2 Electrode }"]
+	
+	pack $refgrabsframe -side left -fill x -expand 1 -padx 2 -pady 3
+	pack $transgrabsframe -side left -fill x -expand 1 -padx 2 -pady 3 
+	pack $grimagebut -side top -fill both -expand 1 -padx 5 -pady [list 3 0]
+	pack $grsurfacebut $grlandbut $grelecbut -side top -fill both -expand 1 -padx 5
+	pack $gtimagebut  -side top -fill both -expand 1 -padx 5 -pady [list 3 0]
+	pack $gtsurfacebut $gtlandbut $gtelecbut -side top -fill both -expand 1 -padx 5
+    }
+
+    if { [wm state $showGrabButtonDialogName] == "normal" } {
+	raise $showGrabButtonDialogName
+    } else { 
+	wm deiconify $showGrabButtonDialogName
+    }    
+}
+
+
+::itcl::body bis_treegui::ShowMidpaneTools { parent } {
+        
+    image create photo smallviewericon -data {
+	R0lGODlhHgAaAOf/AAABAAIABQACAAYAAAcAAAABDgEEAAIFAQUHAwYGEgcJBQgL\
+	    Bw8JBwsNCgwPCxcLCxIUERUSHw8WHBUWHRYYFRYXHhcYFhkbGBocGRwd\
+	    Gx0fHCUcHSIkIiosKSU0JTAxLzg5Nzk6OEI3ODs9Ojw+O0E8Oz0/PD9APj9C\
+	    T0BJOkRGQ0VHRElKSE5KSU1PTFtRUVVWVFtaUltdWlxeW1NiZ15gXWBiX2Fj\
+	    YF1oaWFlcmhoYCh8r2hpZ2Vodmxua29uZm1vbG9xbj+CnnFzcHtwcHV3dHZ4\
+	    dT6Ou3SBdXt9ekCQvX9+dkGRv31/fEiPt02TvIKEgXuHh0+VvY1/jISGg1CW\
+	    voeGfleVuFGXv1OYwYqJgYSIl1SZwoiKh1Wbw4yMg4eLmouNil2bvo6NhYyO\
+	    i4+OhpCPh4+RjpSTi5SWk5iXj5ial5aZqJybk5Wjl52fnJakmKebnJufrpim\
+	    mqWgn5upnaOloqijop2rn6WnpKaopbCkpaqpoKuqoaGtrqmrqKyroq2so6er\
+	    u6utqq6tpK+upaqvsa6wrbGwqKeztLKxqa2ytKm3qrOyqrC2rLW0rKu5rbO1\
+	    sra2rbW3tLm4r7u6sbm7uLy7srq9rbm6xL28s7PBtbu9ur69tL++tcC/tsHA\
+	    t77BvbjGucLBucDCvsPCusfDtcTEu8DGvMXFvMPFwsTGw8fGvb3Lv8jHvs3F\
+	    vsPKv8bIxdPDvsnIv8XMwcvKwdLGxsnLyMzLwsfOw83Mw8vOys/OxcbUx9DP\
+	    x8vSx87QzNHRyNDSz9PSyc7VytTTytHU0NXUy9rSy9DXzNbVzNPW0tfWzdrW\
+	    x9/S0tjXztvXyOHU1NrZ0NXa3Nzb0uDczeDa2d7d1OHb2uHez9/e1drh1uLf\
+	    0ODf1uPd3N7g3eHg1+Tg0eLh2OXh0uDi3+Pi2ebi0+fj1OXk2+jk1efm3eno\
+	    3+fp5uzp2urp4Ovq4e7q2+zr4u/r3O3s4/Ds3e7t5PHt3uvu6u/v5e3v6/Pv\
+	    4O7w7fHw5vLx6PPy6fL08CH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAsAAAA\
+	    AB4AGgAACP4AhTDhUuWIlCwDmWTJ8kRJFi9VshxBSLDKkx07nFwRkwgTJj6d\
+	    avXBVEhSoFyOAgXqg6pTIULVAgGitA0cuHDhiOEAouWLz58+rejQ8aNoM3vx\
+	    6MGzp8+evXr17G2TQECAgAACAAhAgIBAVa1ZW0WFSjaqPX7dJGz9gOIEAqtW\
+	    I3DgoEAAAVpmnTolu2+ahABdVLHJlOQthBtbwiThcUFALn384uWilQuWvsvq\
+	    eEkoYWhfJna2PgSgckfQoj13mhBglW7btmvJtiVTpw6dumIVXuyJNiXaHhEK\
+	    +GyiAgcPHkceLqHKVW8bJZvbYKnrBEsCj0h0thg6UwJACxw9DP7ZSgSjgSlk\
+	    r0aZkoWpkblfjoYlk5DhDpkcce5YyBogAQxSewQAgAxF/RAED0X84MMz1eCC\
+	    y18BMFBABhaA1R8AH2Tw1hJhfGGGGWWsgUYb3JxDzS8SAKBiAQBgBReLKmI1\
+	    SzW6aMLNPM3Q81RUaWlFQAFwBRkkAIFsc86R2+hS4pHuVJKiVQiAJWSQnYzz\
+	    Dj/z8KNOPPx0aU8ualHQxRx/jDAlXADUEs4vmGRTDzHyOIVPc3/xYIwo3mTi\
+	    wJlWwdTaOenkss2f7Tj5ABG2eOJNHBtUNSUAnYRjz5zN1aNPP/zgo8tmd2DT\
+	    izd3tODolLRsk4sm49gDTT387DUVEcrC7NPKPrEkwacAhFBzzqDq0DKOa+k0\
+	    KQEU5GSChC3sEHErJdrEE8829ZTzzmX+6HOLBCEss4wbmQhzgpRBEgAIKq4w\
+	    g0o1v8jmiCOoaBbAGs4wYkwY4AqZCjWndGNPMp1w0086o6Cb4gIupNBCvUPq\
+	    gokn9KxTyyntxFNKLZ0ok6KKGN8qgCnqtGYOoEYeWQ4xNNRQgw0mp5yyDCys\
+	    sAILnzwjzTPJJCNNzck88wwwfjzCSzLKBC100L7Iscgihhx9yNGLLK000gEB\
+	    ADs=
+    }			
+    
+    
+    image create photo brainbg -data {
+	
+	R0lGODlhigBzAKEDAMnJycrKyszMzP///yH+FUNyZWF0ZWQgd2l0aCBUaGUg\
+	    R0lNUAAh+QQBCgADACwAAAAAigBzAAAC/pyPqcvdAqOctAqHs968MwuG4uSV\
+	    5ukF48qG6AujakvXUIznj83b+o/rCYXAYmeIJBqXiqTTyQQ+p9BojIpFWlHZ\
+	    rnZ79IqVYMxsjK6VHek2b910y9XwwfxOg+P3qzX/P7IFOAgSRXhosYS4SFHE\
+	    +BjxAzl5E0RJeXWJ+aKpydl5eQLaWTJKGmbqyZEKqsE66vrayiY7u1N7uoBr\
+	    +rFri+DLmxAMC0z8a3f8qwwacMBsC30qPU3taX2Njam9ze39DR4uPk5ebn6O\
+	    nq6+zt7u/g4fLz9PD59cj3WPP2WwT2Vwxt+XfgIHEizYQwEAhD56MWSB4WGg\
+	    DBJdxKpIYgPGdQkAUG30sLGSx4qlPpYkaQIjF4mfGMJ4mMmfDoGS5jFx5+dc\
+	    HWPjdsYJ59Oht6BCsRG9ZfQoUmhKKULr2DSisqiriFEd+erqyT9ac/LpWmcP\
+	    2J13xvqcY5ZomrRNvbDVyu/t2CFy0yasa5cOXrN69/Lt47dEAQA7
+    }
+    
+    
+    image create photo blackandwhitebrain -data {
+	
+	
+	R0lGODlh5gC/AMIAAAAAABgYGF5eXqOjo+np6QAAAAAAAAAAACH+FUNyZWF0\
+	    ZWQgd2l0aCBUaGUgR0lNUAAh+QQBCgAHACwAAAAA5gC/AAAD/ni63P4wykmr\
+	    vTjrzbv/YCiOZGmeaKqubOu+cCzPdG3feK7vfO//wKBwSCwaj8jkKRAQDAhQ\
+	    AgA6qD4HyiyR6bQOBAEAUyzoPqPodHQqJXy1cBv3rHZX7fe6fu8uM+OAKk10\
+	    fGlehYhRd19/gY4geYl1X4qSVJNueAKPnBmElmqLlleZoXqdqBECoIVWrJeR\
+	    hVOptAqfr6aIoot5t3UAWLWPAb6JxZfGpVVluGDCccC40nxXy07SXwDPSE2r\
+	    05XUxlaDpKR8bFRg2ttAXd+4x4p+5K7moHdl7DnE7/3UX5G8HIqni4C+Gfz8\
+	    IWMVr1gZVwqpHGwhhmDEi2goYUw3/hFFQowNN5YSCWVTxxG37JFcafHdgAAn\
+	    P3iT5KvlyputYMbckBIcLJs4aQYVsG6nBULFeB0D6jIoQ2dGJQTIaEpprIXf\
+	    mOIZiYkhV5pRI5yhY66awFxCx24dJRCiIWzSgIVtcA1pJitdylzLeNVs279X\
+	    sRrSa0ZP4D3V3pkM645vW0WHP/nNa+1h41F+9iK2abbf4p1T18o7bDiU3l1f\
+	    LsMjHYopQbXUdJ7kx/o1LJ8AJz1Bt5om62m/qcg+GA1yU2VfE/EOl7xqbq3/\
+	    akcZzu5j866t+ToN/nNjbuYv9VWsJApTSGXQdUluFU7lPbfYwz8bP5gs2uZq\
+	    e2LrW7ul/l+v97n1Bi11+dJYSv7ZYcghmGlGBWnuRcdgRLfQ0gZVhNQVn0+O\
+	    mebOf3yBMRNkSV23WWrw3TNSQHZ0YldSDu5XE0BWLWNNE1WdCByNQlU1Yimf\
+	    xdFTiQtBF2OIXhDGCBe6BTWhYRHihWEVgfxo3F1cWfTaa4SJyMQcuqWn4HsD\
+	    4fHkaEjhFcdeaUapkpjcgfHlGDgiNo2Vujz0F2WtWWfHQ9QdQVuYX/VlnoIz\
+	    IqLOnBG+9QqeiXgpJxdOHCkaifIlMWgvV6ZZmmP9vfYlGWNSyJ0eYAg0z0NQ\
+	    lkaUEqukiCky9pWKaT2taSkGPdwBdeqnpjFhF5buLROoEMQI/tiho1TlSl6r\
+	    Oc3xGLSt/GrnJMwAu1SQQeDY6G3DXrnjb4wAA9iMWu527VuwJXfeg80GMwQ9\
+	    6KFnD6dZChapRUQl++weqpnmK4m2mojhbY5y20Oy5bX7ZLED18HqMSJeyger\
+	    AEMqIbzaJROgG8fqQJuAseALcZEr6uJnKPTSpDEBqbanzIFHylqvuLQO6IM3\
+	    u2CZc8plnboeGv4iNoilwE5StHHlVDNxH7WeeZ+7HC3sVy89+wxxfjmHm0ad\
+	    iCkpZkbCgnMuI3qmE2ZZ/94VWRUh08DmQLiSlRiiTHNo82ArIyWtfzVVjC1h\
+	    cw6iHboGp5NiWToUWI81iXGNcGfl/rgdWK0YG/03e6aIOKScu3Zz1ne6Fdbu\
+	    n2n/xAsOsZr5l5lM5zdWz7NreN0yzYIjZ+r6Xo5i2KFrBhGNMKbNItqFPZj5\
+	    DRrSjdq9bM+edZJLKV9TRiLynrQ8hhu2aHmQxawvAZR+CGQ3ZiyS/BM1JHQ1\
+	    opEf7vb8TeNlOlZ7K01M8rm7SzqqZCgWyGznk0WJ7i7ZIw+PwBE3QUwGawqE\
+	    TeUkGJAkCet+0ouXYYQFH/1MrU8cPB3MvDWjVDltHJaykezcIAMSjg5eE1zW\
+	    vWxnv90RL2vgiUL2EgQPaWXMKoZY2e6qVbJlxCBWeGFQBYkFQyY670ab+1bi\
+	    +sDBa1lL/g1gGlbQ6vY/NGRrQ/a5AgyQCMTRnQtqPntQWebxpYChhW1csaHX\
+	    OHQPzy1FdpH4YpGulyvpNZAEI1PjC1G3wNQMym2mWxL6/CVFS9iQjv1jheci\
+	    6b8nIE2EtQIXlhR2AiVS7nGnkaCc7qZCvMxJL0WD470K9SAfVqtH0zHc9WzW\
+	    xRwRTDJ1Ix8LGMYLqA3PRr3jVQ0rg75JHWgUhZqUoRSoopIAAE9Dy04uTncW\
+	    cDUsUyg42w17mcs/8cIPu6KeqrJIR+jhsl9IWxAsqVgyHWnQiiUxmeXMwUkR\
+	    mO+JWCsTUo7Jxm6OZZIpExjtXuLKOdqGZSPK5LOiWRq7rec//uX4owfSt5XH\
+	    XI12fWidJiZZOViEklma4A9ByUFJW70rcwgzGB+pVrAmPqaeMsHn68q4opew\
+	    CXUmzBdkuseu39WNjW5sEkizlMKCdIxIsDvcZPJSFBJsM30WPSP3ZFlDkoKv\
+	    HKeh1Uc/OdIDBtSL7VEVz6yJTKd9tWlTqqjxYNoBgEBVVfUrpeW6pD6x0Q85\
+	    wtGTImtkPzppL17pdN0C04rXpFyBp2ar6Dwjh5SmhqBSBXrr4wBDMHl8VLEx\
+	    hM2kCuc4tyqyfPiSJm66hFJrnucKqDzklF60zTHhowSQK+VM3zpPbOUzl/HD\
+	    3mnk6FlUBq+WavhiGM1QWozaJLUk/l2ow7TpRxJA1kaSdRptlZhGCmYWb7fL\
+	    Xl5A51fLdBB7gbNMcnN3t6F+ll5tYq3YIKozEOxvmxb9Ey9BhCBzTrCbzFqS\
+	    l+gUhv6uV1+l9WZqMkdKTbIyo9xlmEdfVBJKKWWeInjvTCuKNjNe04n2IhY3\
+	    XQtCziL3aH9Fk4cq3DD/EXGfoaxmyugaVTWBIMXinMzf4gs7XNkLrZRDGSLb\
+	    +NbNVoqWerxaijulyWgCF0U/bucJz5hEeXmAHtGFLItpjDfcChLDHc0k3Bgp\
+	    u1XptYCqQdGAJ2vjyi6onQh87oYFC9fFspUCz4RqknlLWdzODYc11lpm7euu\
+	    SvG4zN4E/tWAP2QNWsEPN9IZdBIpqkI2A+YDR0tSkm3MXCBlEMd5vm8agRZJ\
+	    6PqXfyJuMokRKMss+Q7NajEmafVK6EbDN6aUmXSL63zpxzGxD1gmqwQnh0jI\
+	    hhN8ajTTdo0HN/PBb4ZzdJvolCzmJVeGMh8Ys6iZ7Oj6ZXqgxr31riUn6H6i\
+	    OqSmTKRNVWnSAD+UotbMaoy1mxcPEI+4np0wjc2Ya9cB7bphRM7z5GvVeD2V\
+	    Vwg22X0JbDnyYJBYxB53W8wgUVWocLvwdR6jUds6buIWNdarroE9dc4ZY0iv\
+	    +u2xalfY6ProG6oabjaCxe1inuiJMoqebmwljd5L1xTbxuN0/pEXx+/m7TTF\
+	    M76RPO3WULApL7qSdhzIr9ZwCKhZnKtOH2SL6eP4vfDBWwvodTNKzZ6jhsdT\
+	    XzojVnlrR6VGYlRXc2ZuK9M3q0JsUY66l+mqJA37PM+Euje2EJsz5BLOw8Zc\
+	    ONgk9ybwfhzkK//zA6PcgW6IDunQ9a0wg6akzCi2yibOd2aJkk4LFq58Tfj8\
+	    fAn63Y4W1tiKM7TToshcI3KA7mKP/DgPHlcWp3yVXIueYUhVWMF+ftW/n33u\
+	    yx7Bnlq7aejbE5JpBBUNpBjG0JV2kzOt72Df19YN1RqtwOROY3Eh+Tf6bbgx\
+	    venamsY89bDjnk7pBcdewLs/lvWw/g+xdMwOnHbG3nq4yNK3M68e7JPFfsPE\
+	    WPr3PyfUU3MVdOH2Vk3nAO/GfA+HSl8mZhR2aNIzQfeUWDomGT/yUPpUdclU\
+	    PhDHV6Y3WIZ3MHuyO3KGdG73ADAXa/ZjLBM4bfp0TVykf9UHJdVzZWTjSkS1\
+	    bH5mg9dXXCWRUOa3ZKHkBxFHJRswZ24Fg/OnPmdjb3G1SdODYYX1OzoWPtGz\
+	    Q9+yW4b0HIJ1dGgGMri3WKBEOCD3ghzQW9MWf9DXeoO0FhClbSnFhWwhKxX2\
+	    RmMmgfAlSPezIkanYfbSWTYkZ0nyesz3ck+4iIQWezeEXRSmT8SXXgalQMcE\
+	    Xkj1bA4G/hh2RU1udHy4FjlLJ2tW8Hrxd0OpGIN1BXlzWE34Rl4qNlSWxnMC\
+	    Vk5J92k3xH29N0DkRYf2d1EPRzyK6IhSBn8z14fCiHWph1FbOC05lA7ohkv5\
+	    c3SjwisJRIheFIpHODyLJWx/0VapuDvJB4eOI0xUCGjeSHaRV1C0uI1Jxi7N\
+	    iFceJXph5zB9p0W1VWA3qHxm0AEQZ45uaEd2QA4YNG++ZHo6JHqMlEOLRmmr\
+	    BYsnd42ntD6F8h1RQ32zM4kLF44AOZDRt13YGHu9VmYkZhVKiFpfkl8RtF7f\
+	    Rhbwhi6/B2qGxnUsKVtad4PVxoQckCwjGJLeB1fU5mpkuIhh/pgmMfM2z4Z9\
+	    +bJFyVgkVUeJ+WFuHwdwFSR1ntiHMgGHDygQyzaMV2dv8lCTUjRKxjeBm+Yf\
+	    dVFUW7Y5ZpdRN4kH/SVMxJUZ32cZYteCEjBniKgJUGZhUcVy4xM2PPU+8tg7\
+	    2mcmCoY/i8IMMVSQQTVcDAl+DjVM8teAewmUEfd8rfeN2NVIXlRF1iZU5tVT\
+	    FaMfIBg1vJiWyqN4i7OOLKiXFCCUJTeAS+hPr4OFcERF4/WSz5iDrZRKZvMS\
+	    YvBMWZZAOyhdX5k3qiN9quhc6+aJrhiWPIhnmzEPCuUc3/JQI+SYuEFFu9I8\
+	    g3ZWmCiDJrlacWhBJcBqzAWGtiZv/mK5df5DcHrjkhVYXXvInaZkVWNGj0j5\
+	    bpdlVliVnl6AmRhAlylYaZRYbeX3DwWiN4NWeXVWj8k1JA3mLXiHaCqHQgHT\
+	    bCqoTc13AjAmkjRYRmUCbtk2NcCFJu0YevX3T1/yXQsFMqOnU2m2jtKGcIDH\
+	    XAY6UQNgLkQBAEIak/J2ntFDdqzkUwuSLblYkXLmokyKgOHjcTtHk9JFQJb0\
+	    lWczdTpgLtpUcFIkQvhjWRV0pItoj343SmumUMSJWHaDelq0PmdAoCkYojiw\
+	    pU+kenqakSTyZ+i3fHQHoH5odawJMsZ5fTJqWleVp83pVj9AVYpGSMCmN5Xo\
+	    fXMJhL0l/neypT7gV2QatGU+JzUBskSUkHsPBDfdgoyPM1/lR36oM5MRSjKx\
+	    CoEls3YMZqHSV6jvpH02R6gLVwQBhCsBip+XR0jB9kEegpbJKkD9Iz1bVSqY\
+	    1ESqUy/Pk4jAyqr6hXu99BNfdqw480pdQXHHZJ3O6mfTSC34djzVWg09WgOH\
+	    ilPqtqtXyh/rEiUNwmjQqlOZinLbdij86EsWeIrcYJvO+TkA9Y5G9UZORHst\
+	    xa14iZPSpXkpp2+eVA/tegMGCZhxF6MeRI+HiQ37VUzEo3UoKllqiKui8T7s\
+	    5WRIUBFICiq8Oa7wtIWHKbHlMpM0mW5XF2P4WF5Eh0f1AA0N/sltIVKYJQVS\
+	    WpY0pMBGImiL6DFd84MfYBpGiPoggEAqk/oWzzqmR5u1NclrfSWyuNioJzpN\
+	    hLhncRW0gSCk+GVqGdhpZAkzGuWxbcNmKhhU/haWjVS1eyZsF+sDQvpMmEcw\
+	    3ll47BhcL0N+ohhwy0S18ZhbNluFWCYQ7gcE5fMAgRu4XotamJZBdKtDY1V2\
+	    uwkzNTisGrhR44qkVgeR52KnPyApYgVOmcu2Pyuu3TErHmRJcyuP1Cg1Qwa3\
+	    S8mMx0Ox2JaAQ3CMb0g4s3sZ1COexpcIGDp8zki6LaVwu9YaMDeaj1mHPus0\
+	    QpC9YgWBmxW4Lolu31q2WDFentpH/tGkfoXnZnQzPpBbZQEoBM3busA3KqET\
+	    VfV2KSlhtNt7h6HVSi86OK7GWLkWv/UjmzPwhJA4YEAYsoHLSxxzuzdmdlq4\
+	    LtU3wDCJjso1UyUIpne1RkMAOaZYQ8P2fQxpqgejWwrpi+H6qTgTOMvZR3ao\
+	    kAicWX87RqVEmXkJe20UetZ5nfqohfh4tt6qMjmnemS2wXlDqK4LBOu2gvEG\
+	    dUzLO0e8IucqjQeFw3zEgVX0sSXGKTl2pEhAmxGHoq7zd+75tcPVdcWWZXYo\
+	    wlMkqTdHbQ06T36gBAv3dHeVVHAlgbJmIvMbIh0at9+qwWijdSglx7E7D0JS\
+	    slp6kKgB/oYSCrUwGybuab5dI6ZiysVQ6V9kLHiVCwiSFmNOVDvPs4aRN2ns\
+	    VmrJJH+NWJnbAzDKAjOzC8teJAxY9Uu3Q3GjTIGnDIcrrIMkqGjlpcH1qTSl\
+	    fAB6oQ9K8cDAeIFAWyBgx7TBh0mGNX0OiZgsQgXNHBOaAaw+e2Yp52v8FZ6a\
+	    qlIYDLCnW8esucOp0FmxhXI26r938XmhI7Jt/M5hRZWAllg1MRcOwK8Cl8FK\
+	    lVVT9WGKx56gmaR+KVkIe2AE7YKiVlPAqEbHiJcVOWhpl1MT9rWQ5HUvq3Nc\
+	    UdEuKHMcbEgH0ooi+FxRR1UJWXsQkoCiiqyZgNIPILISqVTt/putqmiU/flP\
+	    1DWAdoJClZhhaaTTTtdaTZOzFQzUaPx0E3eGOcari8B3a4MhTO1wIzuFQgWq\
+	    ldm6Pdyt+TaYmtx1tyJfXS0BDsw/SatVYdYhIBpiSfy5HJhoSNYIbe3VQ21c\
+	    HBgjNnhsMrV7oYsdezQTqBkGfX0UlkloHBOpHdMpaZvMCxUGgvuWdqLQ/vmj\
+	    jW0Bo/fWCj126aVziwuaP0q+1+vPZhgPn32gZPZypHVq4dqvIz0W7lczn0Jl\
+	    UfDaGTCNbBcZwOI4vXgMDURdaO1Pvp0BNUc/FvoxxM1hVNNeEWCcBTHQy60B\
+	    2NrTFWxy1senDYGZWk0x8uzb4Bta9bdMeBB0VLHRk3ibGtkdAqzKoHcoSOwo\
+	    NOV9AI8XxfH9ZNEVaAoLTFFNnl/T30cwcXQY1w2brxcTzgbeAwa9kTfDmtup\
+	    NA+uKQ+KhibVNqvtE/l94TIgmNX4zhXOsiAuKDzryOlGkIXw4Sc+A+dKMlOC\
+	    2RhKDS8OCJ3FHLg8wdzh4jdeAzQ0utmQuagXXD/OCTF+oQowwQRk5EeeCqKH\
+	    uS6bndj05B0RrKTh41bODd2KRVtuFC3j5V++E11eClo+5keA3HKB5kZxJibO\
+	    5hNhknAeFgEx53Z+53ie53q+53ze537+54Ae6II+6IRe6IZ+6Ije5wkAADs=
+    }
+    
+    
+    
+    
+    image create photo multicolorbrain -data {
+	
+	R0lGODlhigBzAOf/AAgLBxkbGDkOJiwWIzURNDAWRkQYFkgZDTgeITYVW1IU\
+	    GEkYJSkpJz0kGTMjPkUZV0EfVzEoUzAtO0UiRUEoOE0iODwlVzsyHk4jb1st\
+	    JGAuFFE0I1I3FEctcEctgVQmiWMwR1cwbGkrcD1Af2I0XGA5SlU7Zk9ETmI2\
+	    aFUypFRAX0lKSUs7olJAdkpFclZPIUtUKk1XFmdLEEpLY29BNVs7lHZCJWA8\
+	    hV5TEURFo2M9eldQOFZAlVhEiU9GmG5MKGpMO2s9iXxKGVhiBYsukT5SonU4\
+	    n09SlJoqplFLvWdDuKgpn4U+loo4qVBUs2hEyXtcGF1fXGVMs2JZgUdaxj1k\
+	    sag0kmlVjV1bjntDwFJjhmxZeXtVZnVRjWBYq1BlkndnHUtva19ie0tit4lA\
+	    yU1sgXVlOktnpmpyGIdNkG5ib5NJkW9Wr2FpcGdoZnhOxHdhYVxipnZUsYJN\
+	    t3Faolx9I3JpVIRSo2h9EIRkWaJRcpdeW09u3WNryWptsmKAZVl1uVV1xEaA\
+	    tE6LZlSBj2hyqVF7uGJ0sKVZj2d7goxftXd2dLNWfIRgx1t6rVaNVm6CUVx9\
+	    pH9ze1B61nJ1llOKemN9mGODeFyEhmt3o41lrGR/kXmDQ3l4fkyHqZB+IIWF\
+	    G0qCz3F6kKdjeVeFnatqSrFqO6tlaVOMiIJrvZZvdJRrkIJvsYtuo354ko9z\
+	    hXaTHoJ1omecIZV3a4t1k6RwaoKDbp16YJiEPXmGjpKCdJiDY4uEg2aZeIWH\
+	    hFmjZqOAWIyKZ52FWWeNyI2EkmmiVJWLWWqQuHCuEGKbp4mVZWCnfZaXQH+f\
+	    V3iha5OYVXuOzYeYeJGRjnCikpKVf2+hoIukR5eQqp6PnX2wTaCmK5eXoGS8\
+	    aZqZlniti2u6e5i0OHrKFJq4H52Yw4C5bYvAK6edonjEWqKkoa2eq7OWzKeo\
+	    pY7ITIPVPaayqK+vrYPXVZ7TI43fILW3psOo0be2tMGx0qrJoLq60cPCwcrM\
+	    ydDO2dXX1N7g3Obo5f///yH+FUNyZWF0ZWQgd2l0aCBUaGUgR0lNUAAh+QQB\
+	    CgD/ACwAAAAAigBzAAAI/gD/CRxIsKDBgwgTJtTHsKHDhxAj6lNIsaLFixgz\
+	    ItS3r2O+fBw7Nsy3DyTDkvtGlmyIUmVKhhpjypypkZ8+kx1fgkwJ0iRDnzeD\
+	    jnTYkyXHhjSTKqXJb+fLiE1X2kRpMyrIqSSrkjzqMOfEpWDDIrT5kyE/kURT\
+	    Pj26ti3Xsi/RjuQnti5Yjh8hily5U6hNn27yefO0AlC9w/XykQ267+9JoTxt\
+	    2p2cUe3TtlsZLkK8DQ4cfXCk1Xt3pky1aZ4EBRoDqLC+epIUK3a4+DFEyrgP\
+	    Xj4b8qZaON38jMGSqZAfLJuS5Srz7l2ZRJWmeSM3LZkgQ6snRaoT7l0/XnCA\
+	    /tpmrFef5Nx11771rc/cO2Kt6MQZU+RLISyH7n8pUwbdummkRGKIINeFEoo5\
+	    /p3xiCzlrBPOg+KUw1ZQsxm1U19foaeUSl0tlo8r2BATCx1elBiHcWcUEscV\
+	    m0yzDiqkDPjFGTSeAYghY/iDjjN1yCLPg0CKM5tlOKnHUkoa0sSVWkuaJMk1\
+	    ULoi5YgkehHHOlh8MQ0hltBYxZdfTgImOv6YEwUhvwyBzINrAhmOJBPSRpJ4\
+	    vSWp0UNA+QQHL7HE0kormmiyCi1+ktiDF190Q8gZY1BRRSjorDbGGGKOEQg6\
+	    2wSwTi/dSINOj7LIsmY77ZRTjjRGytXSY3TZWdF6/ksGxcs744zDyq103CGH\
+	    Jn/G54UTZ3whyBlVjPHopZIGEgggVazjRgBRoGPONujEEAOoyGSLTDngaFOP\
+	    NuZ8NCRetanVqqsIqYdhSXD0GQsrdCiiSCqKNNLIG280cscdmqDjwxiMAgxI\
+	    HDca0o0hZyB8iI04RuNLFOts88ILMFxbR7biiKONNmDIIMTHQph01VteZYju\
+	    QEId1Vc+9cybCh10pKIJvffii28W+MoRXw5xfLnNso544smABALiiCNnKOtJ\
+	    MJ5sM8QQMUx8rajiyNKxDGB88gkuWYNijso+fbTWyQJBZpZ5DL1DRyNsrNNI\
+	    Kqk0Uu+9UryhhBJvPJHF/hxpeCGFsZYmTKAgjkQSyXVIB/Ll0p7UYQ7UMFQc\
+	    AyywIKONx1CAAYYZZqBhRtaSpDQVkzf5dPJ4an1UTzOL+OEF3OvAjo4SWeAs\
+	    Be21P0EGvzwU0TMgNBKIcCFHI90zwYIQIggseDwO9QtTyyIDFFD8YAYQuNhh\
+	    By7UC8HLSEWF9BK6Rt3ET1P62KFMMJJcEYsfrazjT8TrvJGFEut8kEIKuus+\
+	    Bx1ssFIRzuAITAzOEXGIAwEPYQhMoUMQofAEHoYwwSFU7AV1gAUaoPAJKHSj\
+	    G7hwBS9sgQvumcIMbbBFN1J3Np2cKzdGks0+4LCLd1DDFbQwh5/8s4511M1u\
+	    /kq4XRb0pjs50ME/VfAPOgzxhdQIYkZGa2AP0fHAQVCwG0+zFgzqUAwcZM0M\
+	    XDDDM1rxDGZojYNRCEMwVjAnx9wmN7wxWz76oQ9pvCMY1NBFN9aBoHXEAgvd\
+	    QEfdnhDEupmjTOiIFoKioAYqHsIRWvhCJg4HwaFFAQBREAQqilEHPDCvWlHD\
+	    IBqwhg4gbIMTxnCFLTgBCVBAwg6XsIUdgqEMXXTFNiDBTfma0hSSSMIWNtTF\
+	    LYCxi13wwhVqmIIcpFC3+zHzHfhqAxsUwQYWUMEcACgEJShxhCfk4AiWEJo4\
+	    3eEJQsiiDp3EwwTXgQ4YQK8OnMAaLoCAgjww4xmx/shENILBCXRAwha22Kcu\
+	    dpGYChXJZGHhDZHElbZgRAMdxQQGMXmhBmJsYZl4ywI6WOBDKZhjDrqSAhVy\
+	    4LtCFAIASUgCFrAQCU+EghDuGAQ6snFOTzIvYm3wzwtwMAQcyGBrQDBBGJlh\
+	    i18ag4qSkEQ01rcLicJJVSepy08w1BCyuOEZwniHOW7xjjzM4ha62EYntsCG\
+	    Zmo0BehIwTtyIIUkpCAJOXCCXJ2QBCUkQQwvuEAbCFENWVBOGqGCBTpz6s7I\
+	    Vcw/5pie5rhAAhXAARfMEMYupMUMYwgDGMK4xTrycAs4lKwv+wgLeXjSmMbk\
+	    ozn1UEUe8sCFHkriq7qQ/sQ6ptCI2+0vb90wRwpYkISIbSOlSiBkcHngzm5E\
+	    4RFlKAaCAlSGMMCAihSL7ueoZ44ergMMQCBBCHSgAi6s9hbCqIVqucCFLXRm\
+	    Fru4RflWglCZ4Al8+TAHCcjLBa2SAAUQM4cuZoGNTmzjCuZgZhaaQIY5aPQJ\
+	    T9htImenBP/UzQvdWEEA7FAJVPwBQX/YwQ5ekAt/yODD08vch6FARTdQEQ0g\
+	    KEEHeNABHdC3CyTgow5W8Y5F6EIX9SiL2TakrvM1pR436EEPtuCPRUhCDWqQ\
+	    BDpkywtJbGEKPWBDbZWwPyMYIQo2w9kb1tEGdkbBDWYKQBsoVolLoIMDF7gA\
+	    /gfWvGYQ48CnIJYBBzRgAxlQEQw/0O4Ngiy/TixCDa5AUFJ5UaZ3cMghScHL\
+	    hEjinhKE4AFB4EEP0LGIEX5wHZJ4BTpG0AMAltW2TQh1N5qAhFIjgdRtCAAD\
+	    AgAACWzgDzBoQ6i6sQfxquLWtQACDTaw5ii0mQMe44AQNAAFUEQhWuw0UyJ7\
+	    0IJO+MIcAbCFLnjhniazJ2XtvQhErgIS75SABCR4wB2kkI4pbEHJ5ljEK7Zw\
+	    BCGz4R1sYIM5WFBlIpijG6bONwMAsOpAXiIMlCgHJ4CwjlcY/OCvgMOuNxCF\
+	    DWzgBT9Y87BpIANQaOPYUQiAmI/NzClIohPo0MWf/qeAjndEYS8nQUtMfCMb\
+	    xfCGF3imAQlAUAEI8EAJ6ZDCpLHQAx74AB1eiHcPq0vF/TWBikhYgtKXjk0G\
+	    vGMb69iEJYqRiB28QhSSEIXWRRGLVaziFaPohgEywIEMbCADw9aABoQAClC8\
+	    Awe6JsE2Mn67J0jaH0d4h7984IV38GIquMy2QkSSmV6SBAzVo4E5aE4ACLDh\
+	    blLgAQ+k0DY5WJ4NmMrBRu/2BCQYwRxEULoVllBqdDBAAj3cRiAzvANVvMIc\
+	    H8/FJvrUilXwcQ9jN/sG1M77YncwDzQAAQjMJPlCrqMGUqhBDT4t79qYxySV\
+	    cbnhmwIHX0AhHT9QvPAn/lCAdHTgBh2VgiCl0I0crCMH6OdBDuqaAiIQAQnm\
+	    ULqplZ5xdDwBCHtYxwrgMAtVwEHJavAKlFAIrbAGibQKo7AHDeBwO2ADGoAO\
+	    CqAB6wAF5iAEurZ4IMB9CdABNSAHhfRpNcAD71ADD4FyL5QQZ4EW0wcH6WAD\
+	    NkADGpABJbAAC+AAEAABCWAB3tcBGJAAGNCDHcBOPOABPsBWKWAE7ocEAXBq\
+	    ezMHStcNXZZIozAK4vV/cKAGUbBNmcAvawAA64CAtdAADZBmG4AOBwAxNpBI\
+	    MCiD6NANExABDlAAD5AA6PCD6MCDGHCH6/A9RhEXFoEhH3E+L3EAGaB4NMAP\
+	    /jMoDRRwgxagg93QiBZwgw/wABCgAx2QAzxwfu1HBKQWAPUwB3NABm+QdOkQ\
+	    BTnlBlywB3lwZFJCCZkQC7yyBmvAR+9AhXnQHGlGJspmDmaiABlgDiVARRTg\
+	    ABGQABBQADeIjN0AAZNYiTfAh0YieAOhFS2XEtLQQwZgAAqwjQaAAN0wjDbY\
+	    DQ6wDiYwW1MwBebQAwmwgT1QA5iYAynABFbABEsQLfVCBmQQekiASW24A2Zw\
+	    TICiCEywDnfABGuQBugQAFN4ChlwASbnBqnGauawAAfgHumgAQqwABTATtUQ\
+	    hxMwAS7gAlMQMXe4ji2WDjl2bVE1eKLDS03RDeng/g4DMAACIAA02A0IoJES\
+	    YIMqsAXpwE5fEJRahQWPZgE3gA48gA5GwARE4ITmADdzQGpLsA5NkHHR8gJA\
+	    IAl3MAdrcAfvkAYHiQjmkFPi1QAIUIb8xgDmQAACcG8CADHpsADbWAEncGzb\
+	    oCMq4AKJImZtOAId8AAr0AI5RifmkRA4EYhzYg7pkA81WQ81iZIIgACLsJMQ\
+	    0JPpYA4zgjDNgQV/aXM94AFSwARMgA5MYHJ+cAZKQAal1gRZYIpqYA4vYAet\
+	    kAZ3IIvmkAaIsAqIkHHmAARiuAEXAG0AcJfoIAAEQAAJaQ5tKZcVQAEbRyaq\
+	    dwYrEAUroHfd0AFuYAIW/vAO6SAUIgMTByEn7FIP6XCcBZAYx0kC9RCZFCAB\
+	    EQABW6AF5nAG7hAsX7ANM9IDbQAAHdBzNaAjpYkOS8AK68AGb4CPoght22AO\
+	    OwAHtYkIEIoOC1kL5hBxF7CACMAApscA6zCTA0AABcBI82OTGWlyvDh3/tFl\
+	    YFIE6NAGGLAI1FkPX0Me0GcQpaMYJWET6ZAOA7ACDqCD9TABKBACE0AB3VAB\
+	    M3CDO0oj6HAGWKAFkeQIGRcAcNACHNgERFADTGkF6+CKXiAHbzAHUrAOATAA\
+	    6LAFmrAGjKAH27AH3VALpTBMHCCGGUCDNDmTUeAPH1oAyOgPlGhdvLgO3RAB\
+	    /hHgAkVQBG1QBYc6AkUgDYzqAfe2J4dJFO3lFvsgDTy6p0oqpCFAAhXQAAuQ\
+	    pBCwo8BzBkVwBJ3yBYtQptAyAjxQA+4Hq/LIBPcWB+bABn3ACicVAObQCrW5\
+	    poxQC6dQC8MEBQdwAGaJADUpAN0QACZGk8hoAeYwiQ/AizYZBQ7gABOADkUw\
+	    Bt1QBEWYA9LwJSPwARBgAZUmDZ8xHhxREM+3E1MxAAjAo4NKiRAwARAgAiRA\
+	    ASWgADbYBgxwIwPjA8rnBc8CLanWAjUgqAMZBOZQD/MYC37WZYuQKQGADrKo\
+	    pnqgB6dQCvkgUcZwAGOXjbzQjQMALQjgAASQANTa/kPUSgBR4A4eOQJf0oYe\
+	    wAK5sA39QCMfgAE60ANqdVotsRgFcT5hkw8NEAAIMAB8CgEhYAE2eK/7mg8p\
+	    CwEmcAbpcAaL0AkMwACSFwXSEEjQFgUegA5EwARBcAMDWQ9LMJqJtALBCQAX\
+	    awWMULd6QIWlUA/CIAwhqwDZaADSMIbQhg4pi4yTyLIEsJYkIADroADbEAEm\
+	    QLOH6gEe8AFRsA2NWgSKmQ49wALvUA98qBcEYT49kQ+80AA7yrSSaAETkA/p\
+	    MHMQ4AvLCAEtEAc72g+L0LU1YKv1cAR1SKZuwAKkGQRdEAT0aAVuAHWB5AoW\
+	    2w11ywgTegvpwLfPcADb/ogOBjCGFyANbRCZ3WC4c5i41ioABoAOxNgCippE\
+	    28ACH+AfRcCoH5AOQbajIpBuccQqKDNVHSGGqKu6IRACEbCI+VACJQABBjC7\
+	    I+AGO8oP7+ALnbACfvAOhXBE38eLUXC2QRAEaYCQbaCY5sCU79AGEhAAzssI\
+	    wypetQAM72AMz6AMHGAO2SiyxxoFDcAAhTuJGPAANAgC6QAC5Pu93cCoRYB+\
+	    KfABgcStOfABH9ACN+ADUsACUaADvCAXZTGN06cPnZC9F8AAxggBbnCDNJgB\
+	    UaCR6EC7X9YG3vEO0rANvkAHmqAPrWAOW9AC2+AFLAAt/sGbPfQOfOQs+8YA\
+	    /lHQDSc8CwM1D2CGDc/QtwvqZdhbw9KQD4vwANiQAAKwjdy4rQUgZkUwUvCY\
+	    Av7wdL7AC+mAAT1QhOnwAQWVGTwBnmIzEtuwCAp8AStwgx0AAQ6wDWC8AAhw\
+	    g7TrA1/iBp0gDbHwDlegCayQDw/sntLgBaB3sBqXvOnAQy0qAatmYuhQC9h8\
+	    C02FDq/QCrzQDQ1gAMeGhVGgAMd6AfzgC5W2jjqckco5AWYit4rqBPC4De/Q\
+	    DUqsmB4wAkS4o/UgAlLME2EzEf7QD6TDCzCqAA0QBRFQy7wMAcf50CG5RzQS\
+	    C+NAzJ3GMlFQl53gu3dgDmsQBELWBakWBQjiBn/M/gBuAJElpwq1oLfPQEUo\
+	    oAi6QHBtgHGLt40HMAAOUGm8wLLGeZyJqwYad7FIvD8Ro8Tr4H0cZwT9AND5\
+	    0AOLIBKLEVrcZhJqowlyibrp0AI3GAIMcIMokA5WqwKOKg1OiilusAjucw3p\
+	    gNIS4ALx4gvSIA1dcAVX0AIt8A6nd3or7QYjjNPZLAzKcG/oQAs1bSbd4IWx\
+	    swoVoAAMEAEWUK05TK3nKi2R6wMYl2zdwAKezQPb0AZYaGUGyblX0AOhyxL/\
+	    QLoNwQuaoAiIYM4OsKNWitIhMKRkjQK+4AJ1jdaq981XwAq1wgsnMAMnoAl3\
+	    kFvrkNfd0AJXgA4ordJ7/nywjYQpX7UL0WAmtsAL61CRVBTI68Ar5qAA5rsN\
+	    0vAAGPC/D9ANQxotKHAFjIpx1rxbLNAN/kBvLLCUQaAD+oDXXcDfOtGupUMW\
+	    +9AJXNB1ChAFI8wAJjCkKIACAP3f6aADauxsXxC2nUAJsNgK6uAKf80QW/Bs\
+	    sTAFj3wFU9AcO5oI/2ZcU2rS6/AOylByJm0NZVhdpogO0QzdCrAOEkAteyQC\
+	    ENANIhAC6yACQ34D/Vkmx9aGvLACSpwP+b2UIrDfU3AFPKcDe4ESq32Y0rAI\
+	    W+AGx9aNjWgCOzrhOgAzwY3XJvAOWCAG3eAKlSYGfhLH5kAMr+C6q7DGDSyS\
+	    /uugBf4M43z83aYYAFAXDM7QDa1ARXDQQyZ2bLwoLQBAJuhQAEGMDiHQDSGQ\
+	    SF5AB0KG5DpQJtCCfofBC5ULB0aQDiIQxVOw0W7QbN0gNqTDJPtQY7RAC6uQ\
+	    vRJgASOg1y2QDnidQAm0Dqxw4iYgCmKFZLPCCrFwDW++BdwZC+hQ1/mwDVni\
+	    5zsaDdFgC5BwYbxI1Ly6I+6ADiRAdGC2DnU5RQlp3u5pAYHUASHQA1/Gd0fA\
+	    6T0Afv7QBjngAyjpbHsWBUxg5lGABVa5CFgwxX0oGwxhR+qmBgsQBRQwASOg\
+	    63qdDvJxBPOBBfWABSugAp1wAis9AzMgBgu67JS2/gjnqMbvAKVakPLVdpmL\
+	    kAg4ng5aoAbAoXEO1AokcJlu4GXQ8uJ8dLnfGwF+aQ6doANeIC0mwk4+kOn3\
+	    Llc5sKP+8LVNDO9RAKX8EElf8D0eIjovYUeoyAViLAEY92W97gZx8GVg3tcq\
+	    4Asevw7jIApwLgZiMA7XwAti8AVawB96L587qlWpEAydgAU7LwboYAdwMC2Z\
+	    svP+UAJkCgBtAOamCHV8lFPboOsW0AFI5gJHcAQlYiVRUCJBlgPQcmwGewSQ\
+	    fwQ7CqX84Q95XwbfAxSyng/SwAsoTQEUQKgd0AE3/fhg/ixYOJ3qutJ1yQuU\
+	    EGi+gEzXIArSIAZToPp6/r8OhND3tKAJ1AAJCioGauAGdmAL/rECcotxGuf4\
+	    Uzp0ZtIGQt8Bd5j9vGDxXtAHXuAHn+8FPZdIuYUOTnBsctsGR+ACWTIDeq/3\
+	    AMFL3759A/UdJHhQWic35qJEGdHBg4cPHqJ48OHlYZw4WKS9e1evU6coIynh\
+	    U7NIjShi68S46vauzDZCmGpuS/fHlytXttYFsLPITjdO3datM7ctwNIAbaK0\
+	    acO0DTp05px6SIf1w4koko54YePFyTp0YHX4MIduG5V06ZwUORLn4ZczXwQ9\
+	    XeEUk698Bw/2RahwkZso2yau8FDjYhQ1N+KkU4PlCkcsU1xcqbdt3The48jy\
+	    /rpGyVWnd0a7WSJVExMmVJX+oHuFLoAtZcaMPXuGK+26d+gABACgJm2QtEsL\
+	    b3uI80O6GiHbSOvmxKG5Il6oRkFXxAkVPlT8+aPSZ0CUQ4a+RLIEoI1qVAb9\
+	    IgRcj9c7N+g+qLHYg3GAiz3SuaGDjo7yuYKVMcbYhpdMjjnGF4ZEySSTRbrJ\
+	    ZJhILtwEHdYq6eYPSNRQ4xlqbEFHGWWe4aSq3miJir9HzOEhCyWiaCoKpNxY\
+	    J50WrmjBApGkActGL7zooYd1uqHiQHT4KEK77qIAIJBADDFkhQstqamS9wri\
+	    0q9tQKrvgyiueCgtNaKowb8oiOSxFSzS8eGITlyQ/gYaaCxxYyQ7peFljHfM\
+	    CQSQSMyxpJJBOHQoGDjeoSaYYCCBZB0b13llnW3UM+cRdEYIQo43zuwGHRrd\
+	    SAeqNsRo4YMOHmKDjiDQOYIOAJLYxgl0/HnHlxGoSIK7XqngLgopHUGPw78C\
+	    e08faRaRNIopHoqCMOSiCCIdubzwoQcvxvDiiCNccAELPwJhxZxMZsiEEmnq\
+	    mSSdScyZBBBzHCGFqm5QGWSdR4LhxRwQ1gkGnc+2+OORbeqDpJkppKiBjScc\
+	    2i8KSizowAIXom2DDbfM8SEHSbfRzglf3hmhZGL4cIMPPvpQmY9JJnnIEHov\
+	    8YvLfPjRB7CPDo5CDDEe/qoqLTTbimIFNqrzw4+OsHAhaT+gKaSQTjLRwg1p\
+	    QnH35UlCMSdUdCoB+5FHansFhFZe2aaqVqJ4BAaytoFEGXSkkCKV3iBWr+ge\
+	    eODPHIzSSWUsJ/hT8ogJRwApnZal5CcUrV92w5BIMMmncpxrNigfhooD7qlo\
+	    zXHDv3T4S7oQSiyhpJ90uxGjEDuhAWmRThgc5h2yaIzCHEG2ac3QQTjBRZgz\
+	    2zBqm4KbMWOHP6LA1RwWynLiT6aWCoLGbrCAcZs40PFDVEAyQb0Qfd6ZwYV0\
+	    zGFZZWiGYX/9UBx34/1IFkF2IH4S0sfBP7vBDh2n1nFDAHpQg3QwJg7EsoQY\
+	    /ii0iGF8gReUsNMKoAG+RUgDgNswhzl+szVBoKM1+Eob6OqTlmLUoRmQ2EHc\
+	    lJEWh6yDbmzoAwYDwAAJBKAhMDpCLLrhA3RcwSkIfMchAJGPL1ipEOkYQx/Q\
+	    MYljVKMtmMgFKY4xDMeFQhDdAAxC9gGYgjCrE+jAkajQ8SdzBIAHPIiDG+JS\
+	    CPRooRvdKEQUviCNSBzDdcNY30MaUg1MbGIbU/lSJHonMMLUJx3ogEQxOgQE\
+	    sqAjGI2sD1WkYI4pSGopDaEKVbDAA3QUsBtxOIQlLAEIxtGIfY44kMui0Bo3\
+	    9AIVucjFMULhhkUIJDD7uFyyRvaONuDIUjgxhxra/lCkK/TgC+mIRCbqMoNu\
+	    OCIKoQDEMAABjXRA4xh/+EMlVlONXGRCKesIhSX0sQ0M/uIRv1hGOpQRsE4s\
+	    QhLm0IWjqLEz3myDDVJYxxaEMwAb+oMOAltHD2STOyx8IROOABQ4o8LPpUDl\
+	    ZW3phTYfsolIDEMQoVhEl/BXEPeMEyTmOEoG2yKqKBwBC1EgBSkyEYhhOAI6\
+	    24DG+/DoiH2kw3bv2MSfSLEORxiiDQygZdrQ8YtfdIMbY/yFOUikCzhwAR1q\
+	    UMU6ZtGvAGjGB3RbRxvKyAAAdDJAzTokFiJBilGuQ0qBUAN/QmEIaS4pFKhI\
+	    ByYYFAVLVNSihsjZQPrC/lF+ZPEvuQBJGxr5J964waCRIMQmpOkILcxgBvlg\
+	    ayiGwQ9+gIQfvcAEKRwhCE9EQhCSYgAD3tiJQXyDG6flhj8yqYtZwGEFXODC\
+	    Fl4BUn/wxx8+UAI6OrEOf7jhN21oi6ScYg6xYgmcgaJPKILzPnMYYklXTAcq\
+	    HtLZYwhCEMPIRbL68o98cBRZ+xgMSN6xCPG+oxNlKAMhCJEJO+XDElqgozTY\
+	    isdoVnYdvSAEKQTh2WNEwhOgU9YguPEN0/rPKdBqJDreOCkagZQHT1DCIhZB\
+	    lSm4gQGHrEo61oHe9BIiLW1IWzpC0RTJQgMQouoGcgBwAk94wrqCOIYn3NDR\
+	    /u0WZK/JsrE+yFuPegDmEWFYBCEiUQhAlMENbpiBIerhiPK8I5yV6AVZDlUJ\
+	    VGiodwD8BToIzA18MA+1UDJOFIwiqrRK7Ao5eMLzyLIIV4CRATZChxb+4Ax0\
+	    hAG9SAkEg9wBsygA4h2AaNcKTnDOXwxiEKhQLy07kVeObvcfHcWfe/a6V4I0\
+	    YxBhoIQjAKEFMZRBC1+ohyHAOYxjJGMQ3UAnOsHWO0ODzh3fWEY9erOMdZw2\
+	    d21gKAAeUua0vrEbSjDHFo5sDp9pMADoKIYs2NEOdhTjD2FAB6CHkQxSvO+Z\
+	    gXhfqdxAVKJOGWyd8AWkCfKPf+TSu1w8lkEKcj9e/vhDiG5YQRjs3AYGNXEa\
+	    hu6GN9rSG27/IqvTm5RmoAKtoomqN15Tj9W20AlpfGALcJCdJMSwhTJGgR3m\
+	    4AY74MGOZkciUExERzJazFlPvGMQbfhFP9Lxi0Tk4hfc4PaMA7NXcpM7WX7p\
+	    bhYjPfM+B+ILzJrGMtLJD6RMwx2Vq0c6hC7cZWRwGd6ohCi0bA3UEhViR8lG\
+	    1rNBDoe0IX/lq8EV1ACHdYBoG/4ohzOiRQ5ynOMd7YDHJXgK6JB3Qx+VWMY2\
+	    vKHvtqxgBSUZBFG/IY3ubmkgNbc5zm+O47y+h8l+UFYAhN6WfeecHzbNalpQ\
+	    YRRUrEbL3LCGabkhNmdk/lDr2UAHN45SJhfkCTrogIMatoCOaMD9IQGoRBgG\
+	    kQ54wOMPB3WElNAxH0PlYhpObEsY/P6OMLRmGfQr/BYpqw/Ek/tyNt6idtW9\
+	    pU444hikJGdPqbIO7+4jEW+uRjVQkYx1pD8Z6ffGN8hhDWtkmRvZaMYzHuGM\
+	    bJDlDzc4n7T4jn3oGhfoAS7IA+FIh0WIAmdwg0yIgkhIJ9t5iEMQhHfYBl/Y\
+	    Bh6zC8AqAwkIrVyIK0xIv/fAGY6qPsRzj0bLnJzpC7/aIjc4Bn84Bkd4B/bh\
+	    rC/hh074u26oht5YDUoQhU1YB0t4B0zoBW7YhXfAhWZoBhLhgRpAhxw4gRZA\
+	    /grQ+Y3OETNzaIYZeDiyCANy6IW6Sr52kAdMOoZ1QI96cINP+wJf4LAA8Lv0\
+	    Qz6704e+UrwUrD6cKTzMobSB8K6DyIVkeAcGySBS84RjOBjRosNNyAVREMJc\
+	    aLlcWAdU+IZ3eAZTKAVg6IY92AMUYIEcCIIWcINwKKAA4CcE64VHaAZ04AI4\
+	    YIdBOIc/IAXEagt4kIf+cwRLcARP0J8p2iwtOK8VYIAVoMN0qIbuwsMu0cMU\
+	    3BKOyj5Kg8aaeYfKusE0jLEC2gZceodkgMROS4R68IZ1yAU/qoQ2GDBnwIZS\
+	    YMc9OIVRIAFcAId4ACm1wB3skIVsIIUPgQN0IAdu/tgEQigDysuHdhgEBIqE\
+	    TTCH3SrEC8mHbSgDqCAEZKwGSWjBLuGHZnTGQDS8dpIGwvOr8QmJemOQtEkG\
+	    f+AtUnAFLdgGSpgCNRDH48MEMXCDS/wG3jAHeYiH8wEGncyGtDGKchAVEHuE\
+	    apAFTFgHLvgDaygGS3iIdqC8tgAEshKFXJAGSeiES6iGTSCGSPCFGEuG96uG\
+	    GVu3yukLytJIZ6SxvZIEOPAFXpC1euCTKAiMd/CGaRDHbeiHaJmGqliHdBEY\
+	    SiC2MsiFeoAlUWgD0cMEcJAHsliHeIDMIzmKcLAGXGAGoLGGSpCFdSAEF7CD\
+	    WtMjeAiu73gHUaoGBzkB/nh7toeoBCd6v+Mrv8rJvoxMy+rrw+yDS2YBCaSQ\
+	    sHWQHb/LmcHAkW5YgY94v2RAB0o4nRDSEHmDIlHAjm/whh/MkXSIB52Mhygz\
+	    h3fAA8iUB3k4E6rwB1nohRYwA3D4BkxADxiIgRjQsDVYA0SgBWmwBXh7B3cg\
+	    jGJchGpIhnRIBky4uZu5nNpMwRzLGVkbDJBqC3MoIKg4iiOjIeDYBmngC3MI\
+	    S3TIBHMYskJAim44j5rwhY+5S2/ABZFDB1zQhneQO0t5zHDQyVvggorDIHRo\
+	    AUjoGkJIhkQQg1joAqpIG0Z4BW/oBmewg3rwhRWYIZIIg27sB43Kmfs5CAJV\
+	    /kvvGi8F1bBO+g8biRYaCq3QCoDv+A7OzIVCsIRMKITtKQx0+AJMuIRE+CPp\
+	    RIVlyIaLCoV7+ISdTIdioMd4MENrUIEW2IJucIqqaAFlyIZz6Dy4SgdZyxFG\
+	    OApvuAdYowYucAMJiAIH2YZEyCXLoawbk9Lq45KCYNT6eIqgARqvuZsWsaGz\
+	    U61NkIRyyYQ4KILtccxqSIQMaYN6+AZPCMuLQocLtBRUwIMxctF2sINgAAdl\
+	    YIZeKKMAWAd2eAR4+AbKgwdZe4d0GIVRAAlncAZyeAdeYLgvSbF3wJy/qJw7\
+	    /NTqO5Z9sNa26CV0ULl0UC1/cAd3OKS0aAjcASiQ/riCQjiEODiDW0kLqUuE\
+	    RMAE5HiHafAGT+iGUEAHh/UEQ6gGWEAHeQgHPi2HFrCDXkCHP4gG/8mdb+g9\
+	    eVgEdvCHejCDpGuLfjiKzOCFhVhX+Lgc2UTXdEW8cyWIeqhOyiOVqKQ8d7hW\
+	    zDsyzxm/RsKCQyiEDDLYgk0EgXmKqUjTSZiSbjCEFHPRcLjYeOAEOBADbDoB\
+	    M3CIZdC4dqgHv5sPdi0vaZA5guiuHLuZnNmit70Zm7XN95C1kfLZqKwHfvAF\
+	    ytMHDcMRf9CM3CGMpwCOpTCHQSSFT0OKqhCY60gOgSmGi7XYeGAHywWHZ7CG\
+	    eMiGXoiC3juHcniH8hun/m3AosVD3be9nH6gW3UtvHyICc0gSF7ghai8h3UA\
+	    xHQ4iJCgjyMDDq7iD6dog/BEB/SahuOtRUPYnapFSbM6g0eAhXKwWIvluHjo\
+	    vUG4hDDABGc4B3D4hEXrKL0yPNSF245qXXXdEpDAibbIB599h3sgB4Lc2354\
+	    h++ooaXIQqeYlqnAgk0IOnQghP06gyo4gzMwBHPwB4dAB2+oA2TIpKstB8vN\
+	    BnM4B45jB22oh/pZvGiENGVstH04X/SFj1zQDHSoB1zK27YwCjVoC1/oho9c\
+	    AUu1igByA66AkkxSMKqogh3ehiqQ2h2ugkApDjc4O6ztBqwNh3YIB4EpB3EA\
+	    /gdt0Iac+4tzSwiOzJybybkQ1sPGU4iP8lkem4d7IIwtIL+2wAcH+bsyyR1o\
+	    KTN/IBpy2ocqOKSpmAQ+COJACJVuUOCjkAVk8GMkTuJyaGJxeAcuOrcXXEEN\
+	    pqx96Afq0+KNvKXx2tm8vYd5GAd6SIdxsIdu4I90mNERghYFxgly2saautJt\
+	    kJIxAIQgPgPNcIhtwIEXiIE6qANZkAW18ONy4AfC077bFN8uQeRHrs10Kwjz\
+	    aqdFYN95qJx0uIdouIZtoAdscAVzIIhqXsh8GBlLyQUHaYNnxodvxgeQAATl\
+	    RYeANYRxRodzrgLsKIYYwIEYkOUYeIdw7KXxhcZp/gTEJhVmm80lv1gX3+wE\
+	    XLEdlY0GfcCGcRAVawaJfWiDkSAGDDKHfukEbLiGa8CHScCHfUCHfQhYQaAS\
+	    QwjYnqqCJUKKZYiBbojlF3iHGOAFdCPmcnXkfT5fLcK5TtCwm06H2jWHm9Gg\
+	    WGAFu7EUcxgHdfCHGSAGeOsEnDhqNbCHcciBOAiFb47bX12HDvJoJnuHII4E\
+	    Wzi2IRiC9pRladCitoXGLJJpYb5DQJxiC8LSL56HRRiHn06FVPCDuV4HdVCH\
+	    aziTKWgLe3gHdegGTWADqMYHr8s+ZQkJGzyDOKiCOAAETwjg3XSHIchgnNuo\
+	    wKDNsxbmD0aI3VqHeI1K/n2YB3Tw6VRghdN+h59mg7xmDBMoDXWYhFRQhFYI\
+	    Aj/AB3cI0IOoh0Mo4DMYZ0Fwh3WAhSFAAzRwhy5Ja+T2C82WadL1528NrraY\
+	    B9FOh3COBXOIhXWoa1Zgg0ZYBza4p954gycgAzmgAy8IZ5ljPI76COW1LmeQ\
+	    hm3QYGR5XeY+636uHwvy2TFKB7Nc1HqYazp4g0Z4B/BuhPGuhwO/AylggYw+\
+	    N8UzUL+4n/KLNJvZIta177OONMAADMJi0LbQhx7726SrB3Wgg0Y4cClgg21o\
+	    hCzIhzd4gzlQBCnIgXDrZcy5bPh4RnPFmQy3b5qWtJzhhX7ohn2Y7nlIh+m2\
+	    /imQkgM5IHA2QAc2eAcCbwQ2kIMc0GRIo7HtK1cWFF/KQksfZ+5bkuL3gIN5\
+	    WAddMIdZ0AU3Rtt7UgRc6QSgMockyAEWYIFewQf1vsOQjD4t2iLlltl8EHMx\
+	    f9s+N7cO1+Pv+O+QSAUCBwl9WIH6yPMkYAE/GIcTNtAHP2xAr+IpPgh+wPBC\
+	    93E8bEG1/gtz6IdVz6B9WAd7sIfK1gfSsIcnSIEUyHN84GJATzcdx/FG84fM\
+	    JnUx52JB1y7hnDGzvEOQsAd1YHFNXrQbwx9HG/Zqb1217kN1Q+4/dA8bAQm8\
+	    1gR6sAcsPtc/t/ZzP99pzKL7mT7D68Nspgd1oAd6qaAfXi9fdMd3ut3yQ55v\
+	    fdjO0Z0HewCCMte5nMn3g09XF7Sxfs6xavaLf6/m0QVE0sUlhLf4T73DmbXn\
+	    LOKx+znhc/2u5b74kZdSw6vi28TZm1s3aCT5lk/4vsr2mnFS9+irE3T5m7fZ\
+	    lH8PDs94XAIMYcf5oE/LmM94v4J5FxT6pCdQKKV5kO+ruAV6pZd6FcS56cOl\
+	    msf6qdd6PewHnIF5LD63rd/ngAAAOw==	
+    }
+    
+    # ShowMidpaneTools begins here 
+    
+    set wr $parent
+    
+    #This stuff ends up on the "Images" tab of the middle window in bis_treegui
+    set ICbackgroundcolor "LightSteelBlue1"
+    set IC [canvas $wr.imagecanvas -height 500 -bg "$ICbackgroundcolor"];     pack $IC -fill both -expand 1
+    
+    #This is the button frame window which will pack into the canvas at each brain
+    foreach n {SpaceImage AnatomicalImage FunctionalImage} {
+	
+	set bf_$n [frame $midpane.viewbuttonsframe_$n -bg $ICbackgroundcolor -borderwidth 2 -relief groove]
+	pack $midpane.viewbuttonsframe_$n
+	set bftf [frame $midpane.viewbuttonsframe_$n.topfr -bg $ICbackgroundcolor]; pack $bftf -padx 4 -pady {1 3}
+	set bfbf [frame $midpane.viewbuttonsframe_$n.bottomfr -bg $ICbackgroundcolor]; pack $bfbf -padx 2 -pady {1 3}
+	
+	set viewer1but [eval "button $bftf.view1but -image smallviewericon -height 16 -width 24\
+			    -command {$this sendSelectionToDisplay 1 $n } "]
+	set viewer1butlabel [label $bftf.label1 -text "RF Viewer" -font {helvetica 13 bold} -bg "$ICbackgroundcolor"]
+	pack $viewer1but $viewer1butlabel -side left -pady {3 0}
+	
+	set viewer2but [eval "button $bfbf.view2but -image smallviewericon -height 16 -width 24\
+			    -command {$this sendSelectionToDisplay 2 $n } "]
+	set viewer2butlabel [label $bfbf.label2 -text "TR Viewer" -font {helvetica 13 bold} -bg "$ICbackgroundcolor"]
+	pack $viewer2but $viewer2butlabel -side left -pady {0 2}
+	
+	
+	if {$n != "SpaceImage"} {
+	    
+	    set REFcheckbox [checkbutton $midpane.viewbuttonsframe_$n.refcheckbut \
+				 -text "Ref Space" -variable [ itcl::scope REF_$n ] -bg $ICbackgroundcolor]
+	    pack $REFcheckbox -side top -pady {0 3}
+	    
+	    eval "$viewer1but configure -command {$this sendSelectionToDisplay 1 $n}"
+	    
+	    eval "$viewer2but configure -command {$this sendSelectionToDisplay 2 $n}"
+	    
+	    
+	};# End "if != SpaceImage
+	    
+	};# End foreach
+	
+    
+    
+    
+    
+    #**************************************************
+    set rbX 165
+    set rbY 45
+    set refbrainBG [$IC create image $rbX $rbY -image brainbg -anchor nw -tag refAREA]
+    set refbrainTITLE [$IC create text [expr $rbX+80] [expr $rbY+130] -text Space \
+			   -fill blue -font {times 20 bold} -tag refAREA -anchor e]
+    set refbrainTEXT  [$IC create text [expr $rbX+65] [expr $rbY+52] -text "Not Set" \
+			   -fill grey61 -activefill yellow -font {helvetica 15 bold} -tag refTEXT]
+    
+    set refbrainBUTTONS [$IC create window [expr $rbX+145] [expr $rbY+140] -window $bf_SpaceImage]
+    #**************************************************
+    set abX 25
+    set abY 265
+    set anatomicalbrainBG [$IC create image $abX $abY -image brainbg -anchor nw -tag anatomAREA]
+    set anatomicalbrainTITLE [$IC create text  [expr $abX+90] [expr $abY+130] -text Anatomical \
+				  -fill blue -font {times 19 bold} -tag anatomAREA -anchor e]
+    set anatomicalbrainTEXT  [$IC create text [expr $abX+65] [expr $abY+52] -text "Not Set" \
+				  -fill grey61 -activefill yellow -font {helvetica 15 bold} -tag anatomTEXT]
+    
+    
+    set anatomicalbrainBUTTONS [$IC create window [expr $abX+153] [expr $abY+146] -window $bf_AnatomicalImage]
+    #**************************************************
+    set fbX 315
+    set fbY 265
+    set funcbrainBG [$IC create image $fbX $fbY -image brainbg -anchor nw -tag funcAREA]
+    set funcbrainTITLE [$IC create text  [expr $fbX+90] [expr $fbY+130] -text Functional \
+			    -fill blue -font {times 19 bold} -tag funcAREA -anchor e]
+    set funcbrainTEXT  [$IC create text [expr $fbX+65] [expr $fbY+52] -text "Not Set" \
+			    -fill grey61 -activefill yellow -font {helvetica 15 bold} -tag funcTEXT]
+    
+    set funcbrainBUTTONS [$IC create window [expr $fbX+150] [expr $fbY+146] -window $bf_FunctionalImage]
+    #**************************************************
+    
+    drawAnatSpaceArrow grey80
+    drawFuncSpaceArrow grey80
+      
+    #menus associated with the right click binding
+    #Space Image
+    set rpp_space [menu $IC.spacemenu -tearoff 0]
+    eval "$rpp_space add command -label \"Clear\" -command { set \"[itcl::scope SpaceImage]\" -1; $this updateRightCanvasDisplay } -underline 0"
+
+    #Anatomical Image
+    set rpp_anat [menu $IC.anatmenu -tearoff 0]
+    eval "$rpp_anat add command -label \"Clear\" -command { set \"[itcl::scope AnatomicalImage]\" -1; $this updateRightCanvasDisplay } -underline 0"
+
+    #Functional Image
+    set rpp_func [menu $IC.funcmenu -tearoff 0]
+    eval "$rpp_func add command -label \"Clear\" -command { set \"[itcl::scope FunctionalImage]\" -1; $this updateRightCanvasDisplay} -underline 0"
+    
+    #Bind a right click on the pic or text for each of the three to the popup menus just created
+    eval "$IC bind refPIC <3> { $this bindxRightPane %W %x %y $rpp_space }"
+    eval "$IC bind refTEXT <3> { $this bindxRightPane %W %x %y $rpp_space }"
+    eval "$IC bind anatomPIC <3> { $this bindxRightPane %W %x %y $rpp_anat }"
+    eval "$IC bind anatomTEXT <3> { $this bindxRightPane %W %x %y $rpp_anat }"
+    eval "$IC bind funcPIC <3> { $this bindxRightPane %W %x %y $rpp_func }"
+    eval "$IC bind funcTEXT <3> { $this bindxRightPane %W %x %y $rpp_func }"
+}   
+
+::itcl::body bis_treegui::OCanvasInitialize { canvas } {
+    
+    ##########################################################################################
+    ###########################                                     ##########################
+    ###########################         Overlay Tab Canvas          ##########################
+    ###########################                                     ##########################
+    ##########################################################################################
+
+    set OCanv $canvas
+    
+    set OCdispX 15
+    set OCdispY 20
+    set OC_BG [$OCanv create image $OCdispX $OCdispY -image brainbg -anchor nw -tag ocAREA]
+    set OC_TITLE [$OCanv create text [expr $OCdispX+160] [expr $OCdispY+145] -text "Resliced Image" \
+		      -fill blue -font {times 20 bold} -tag ocAREA -anchor e]
+    set OC_TEXT  [$OCanv create text [expr $OCdispX+65] [expr $OCdispY+52] -text "Empty" \
+		      -fill grey61 -font {helvetica 15 bold} -tag ocTEXT]
+    set OC_FUNC  [$OCanv create text [expr $OCdispX+375] [expr $OCdispY+20] -text "Functional" \
+		      -fill grey61 -font {helvetica 15 bold} -tag ocFUNC]
+    set OC_ANAT  [$OCanv create text [expr $OCdispX+375] [expr $OCdispY+110] -text "Anatomical" \
+		      -fill grey61 -font {helvetica 15 bold} -tag ocANAT]
+    set OC_SPACE  [$OCanv create text [expr $OCdispX+205] [expr $OCdispY+60] -text "Space" \
+		       -fill grey61 -font {helvetica 15 bold} -tag ocSPACE]
+    
+    set doublearrowcolor "LightSteelBlue"
+    $OCanv create line [expr $OCdispX + 340] [expr $OCdispY + 40] \
+ 	[expr $OCdispX + 338] [expr $OCdispY + 50] \
+	[expr $OCdispX + 325] [expr $OCdispY + 55] \
+ 	[expr $OCdispX + 300] [expr $OCdispY + 60] \
+	-tag OCtopline -smooth true  -splinesteps 20 -width 12 \
+	-arrow none -arrowshape {15 18 8}  -fill "$doublearrowcolor"
+
+    $OCanv create line [expr $OCdispX + 340] [expr $OCdispY + 80] \
+ 	[expr $OCdispX + 338] [expr $OCdispY + 70] \
+	[expr $OCdispX + 325] [expr $OCdispY + 65] \
+ 	[expr $OCdispX + 300] [expr $OCdispY + 60] \
+	-tag OCbotline -smooth true  -splinesteps 20 -width 12 \
+	-arrow none -fill "$doublearrowcolor" -arrowshape {15 18 8}
+    
+     $OCanv create line [expr $OCdispX + 289] [expr $OCdispY + 60] \
+ 	[expr $OCdispX + 290] [expr $OCdispY + 60] \
+ 	-tag OCarrow -smooth true  -splinesteps 20 -width 1 \
+ 	-arrow first -arrowshape {15 18 13}  -fill "$doublearrowcolor"
+
+}
+
+
+#------------------------------------------------------------------------------------------
+#------------------------------------------------------------------------------------------
+#  This is the most important method of bis_treegui - it creates all the frames and widgets
+#------------------------------------------------------------------------------------------
+#------------------------------------------------------------------------------------------
+
+::itcl::body bis_treegui::ShowManager {pw surgerygadget0 menubase } {
+
+   
+    #Set a variable to hold the top window
+    set mdTopWidget $pw
+    set surgerygadget $surgerygadget0
+    
+    #---------------------------------------------------------------------------
+    #Create a top frame to hold the panedwindow and the status bar frame
+    set top [frame $mdTopWidget.topframe -width 1100 -height 700]
+    pack $top -expand 1 -fill both
+    pack propagate $top 0
+    
+    
+    #---------------------------------------------------------------------------
+    #Show the Status Bar at the Bottom - pack it into the $top frame
+    set statusbar [frame $mdTopWidget.status -borderwidth 3 -relief ridge -height 20]
+    pack $mdTopWidget.status -in $top -side bottom -fill x
+    #Add a label
+    
+    set statusLabel [label $statusbar.l -text "Status Bar" -fg black -bg [$statusbar cget -bg]]
+    pack $statusLabel -side left
+    
+    #Create a paned window - pack it into the $top frame
+    panedwindow $mdTopWidget.mainpane -orient horizontal -showhandle 1 \
+	-borderwidth 2 -relief raised -sashwidth 4 -sashpad 1 \
+	-handlesize 5 -handlepad 50
+    pack $mdTopWidget.mainpane -in $top -expand 1 -fill both
+
+
+    set LeftPaneColor white
+    set MidPaneColor "light steel blue"
+    set RightPaneColor "medium sea green"
+    
+    #Create the three frames in paned window
+    set leftpane [frame $mdTopWidget.mainpane.left -bg $LeftPaneColor -width 375]
+    set midpane [frame $mdTopWidget.mainpane.middle -bg $MidPaneColor -width 600 -height 50]
+    set rightpane [frame $mdTopWidget.mainpane.right -bg $RightPaneColor -width 200]
+    
+    pack propagate $midpane 0;  #Don't let window shrink to wrap buttons; we'll let the buttons grow
+    pack propagate $leftpane 0;
+    pack propagate $rightpane 0;
+    
+    $mdTopWidget.mainpane add $leftpane
+    $mdTopWidget.mainpane add $midpane -minsize 300
+    #    $mdTopWidget.mainpane add $rightpane
+    
+    
+    ShowTextBox $rightpane
+    
+    
+    
+    
+    #------------------------------------------------------------------------------------------
+    #Left Pane
+    #------------------------------------------------------------------------------------------
+    #Initialize the Left Pane with tree in it
+    #Put a visualization tree in the left frame (Tree name $leftpane.w)
+    #Create a labelframe to go around tree
+    
+    
+    set treeframe [ labelframe $leftpane.treeframe -bg $LeftPaneColor -text "Image List"  ]
+    pack $treeframe -fill both -expand true -padx 5 -pady 2
+    
+    #Set a variable "vistree" to hold the tree
+    set vistree $treeframe.w
+#    focus $treeframe
+    #Create the tree and its associated scrollbar and pack into treeframe
+    
+    eval "Tree::create $vistree -bg $LeftPaneColor -width 170 -yscrollcommand {$treeframe.sb set}"
+    
+    eval "scrollbar $treeframe.sb -orient vertical -command { $treeframe.w yview }"
+    pack $vistree -side left -fill both -expand 1 -padx {4 0} -pady {0 0}
+    focus $vistree
+    pack $treeframe.sb -side left -fill both -padx {0 3} -pady {0 3}
+    
+    set grabButton [eval "button $leftpane.gb -text \"Grab an Object from Viewer\" -command { $this showGrabButtonDialog }"]
+    pack $grabButton -fill x
+    
+    #---------------------------------------------------------------------------
+    #Create a struct::tree object to hold pointer keys to the image objects
+    #This is the heart of the tree -- RealTreex
+    set RealTree 0
+    set dustin [ [ dsitcltree \#auto new ] GetThisPointer ]
+    setUndoList
+    set TreeChanged 0
+    updateTreeWidget
+    setDisplayBox /Data
+   
+    #------------------------------------------------------------------------------------------
+    #---------------------------------------------------------------------------
+    #Create a menubar at the top
+    #---------------------------------------------------------------------------
+    #------------------------------------------------------------------------------------------
+
+    set menucolor "#ede9e3"
+    set menuactivebgcolor "#ede9e3"
+
+    catch {
+	set menucolor [option get $mdTopWidget background ""]
+	if { $menucolor == "" } {
+	    set menucolor white
+	}
+	set menuactivebgcolor [option get $mdTopWidget background ""]
+	if { $menuactivebgcolor == "" } {
+	    set menuactivebgcolor "#6666cc"
+	}
+    }
+
+    set mdmenubar $menubase
+    # [ $surgerygadget cget -menubase ]
+    $mdmenubar configure -background $menucolor
+    $mdmenubar configure -activebackground $menuactivebgcolor
+
+    foreach m { File Edit Tools Options } {
+	set $m [menu $mdmenubar.m$m -tearoff 0]
+	$mdmenubar add cascade -label $m -menu $mdmenubar.m$m -background $menucolor 
+    }
+    
+    makeFileMenu $File
+    makeEditMenu $Edit
+    makeToolsMenu $Tools
+    makeOptionsMenu $Options
+
+#     set imageProcess [menu $menubase.m1 -tearoff 0]
+#     $menubase add cascade -label "Image Processing" -menu $menubase.m1 -background "#ede9e3"
+
+#     set imageutility [ bis_guitreeimageutility \#auto ]
+#     $imageutility InitializeFromContainer $this
+#     set w2 $menubase.$imageutility
+    
+#     set imageutility [ $imageutility GetThisPointer ]
+#     $imageutility CreateGUI $w2 
+#     $imageutility AddToMenuButton $imageProcess
+
+#     set surfaceProcess [menu $menubase.m2 -tearoff 0]
+#     $menubase add cascade -label "Surface Processing" -menu $menubase.m2 -background "#ede9e3"
+    
+#     set surfacecontrol [ bis_guisurfaceutility \#auto ] 
+#     $surfacecontrol InitializeFromContainer $this
+#     set w3 $menubase.$surfacecontrol
+    
+#     set surfacecontrol [ $surfacecontrol GetThisPointer ]
+#     $surfacecontrol CreateGUI $w3 
+#     $surfacecontrol AddToMenuButton $surfaceProcess
+
+    #------------------------------------------------------------------------------------------
+    #Middle Pane
+    #------------------------------------------------------------------------------------------
+    #Initialize the Middle Pane with buttons and display space
+    #Create frame to hold both buttons next to each other horizontally (tbf = "two-button frame")
+    set tbf [frame $midpane.twoButtonFrame -bg $menucolor]
+    
+    #Create indiv. frame for each button
+    set leftBF [frame $tbf.leftButtonFrame]
+    pack $leftBF -side left -fill x -expand 1
+
+    
+    #Create buttons to occupy their respective frames
+    eval "button $leftBF.l1 -text \"Set Space and Anatomical Image\" -command { $this setSelectionSpace; $this setSelectionAnatomical }"
+    eval "button $leftBF.l2 -text \"Set Anatomical Image\" -command { $this setSelectionAnatomical }"
+    eval "button $leftBF.r3 -text \"Set Functional Image\" -command { $this setSelectionFunctional }"
+    pack $leftBF.l1 $leftBF.l2 $leftBF.r3 -fill x -expand 1 -side left
+    
+    #pack the whole two-bar frame (tbf)
+    pack $tbf -side top -fill x -padx {3 3} -pady {2 0}
+    
+    set rbfr [frame $midpane.reslframe -bg $menucolor]; pack $rbfr -side top -fill x -padx {3 3}
+    eval "button $rbfr.big -text \"Reslice Images and Set Overlay Inputs\" -command { $this resliceSetOverlayInputs }"
+    pack $rbfr.big -side left -fill x -expand 1
+    
+    #Interpolation mode menu
+    menubutton $rbfr.modemenu -text Mode -menu $rbfr.modemenu.m\
+	-underline 0 -background $menucolor -activebackground "$menuactivebgcolor" -relief raised
+    pack $rbfr.modemenu -side right -padx {2 0} -pady {0 2}
+    
+    set modemenu [menu $rbfr.modemenu.m -tearoff 0 ]
+    eval "$modemenu add radio -label Linear -variable {[itcl::scope reslmode]} -value Linear"
+    eval "$modemenu add radio -label Cubic -variable {[itcl::scope reslmode]} -value Cubic"
+    eval "$modemenu add radio -label \"Nearest Neighbor\" -variable {[itcl::scope reslmode]} -value NearestNeighbor"
+
+    #------------------------------------------------------------------------------------------
+    #Right Pane
+    #------------------------------------------------------------------------------------------
+    
+    # (Empty)
+    
+    #------------------------------------------------------------------------------------------
+    #Event Bindings
+    #Set behavior for events in the tree						 
+    #------------------------------------------------------------------------------------------
+    set popup [menu $vistree.pop -tearoff 0]
+    makeImageMenu $popup
+    
+    set surfacepopup [menu $vistree.surfpop -tearoff 0]
+    makeSurfaceMenu $surfacepopup
+
+    set folderpopup [menu $vistree.folderpop -tearoff 0]
+    makeFolderMenu $folderpopup
+    
+    set electrodepopup [ menu $vistree.elecpop -tearoff 0]
+    makeElectrodeMenu $electrodepopup
+
+    set patientpopup [menu $vistree.patientpop -tearoff 0]
+    makePatientMenu $patientpopup
+
+    $patientpopup add separator
+    eval "$patientpopup add command -label \"Add an Image as Child\" -command { $this addImageToTree }"
+    for {set i 0} {$i <= [$patientpopup index end]} {incr i} {
+	$patientpopup entryconfigure $i -background $menucolor 
+    }
+
+
+    set rootpopup [menu $vistree.rootpop -tearoff 0]
+    makeDataMenu $rootpopup
+    
+    
+    
+    
+    #Bind button clicks in the tree
+    eval "$vistree bind x <1> { $this bindx1 %W %x %y }"
+    eval "$vistree bind x <Button1-Motion> { $this bindxmotion1 %W %x %y }"
+    eval "$vistree bind x <ButtonRelease-1> { $this bindxrelease1 %W %x %y 1 }"
+    eval "$vistree bind x <Control-ButtonRelease-1> { $this bindxrelease1 %W %x %y 0 }"
+    eval "$vistree bind x <Control-1> { $this bindxcontrol1 %W %x %y }"
+    eval "$vistree bind x <Double-1>  { $this bindxdouble1 %W %x %y }"
+    eval "$vistree bind x <3> { $this bindx3 %W %x %y }"	
+    update
+    
+}
+
+::itcl::body bis_treegui::updateTreeWidget { {node ""} } {
+
+    set pathList [ $dustin getPathList ] 
+
+    if { $node != "" } { 
+	Tree::delitem $vistree $node
+    }
+
+    foreach pathName $pathList {
+	if { ![Tree::itemexists $vistree $pathName] } { 
+	    if {![ regexp {(/)(.+)(/)} $pathName ]} { 
+		Tree::newitem $vistree /Data -image icactus 
+	    } else {
+		set color [ $this getLineColor $pathName ]
+		set icon [ $this getIcon $pathName ]
+		Tree::newitem $vistree $pathName -image $icon -linecolor $color
+		Tree::open $vistree [ $dustin getNodeParent $pathName ]
+	    }
+	}
+    }
+}
+
+::itcl::body bis_treegui::getIcon { path } {
+
+    if { [ $dustin getNodeType $path ] == "Folder" } {
+	return idir
+    }
+    
+    if { [ $dustin getNodeFileName $path ] == "" } {
+	return ibraingrey
+    }
+
+    if { [ $dustin getNodeType $path ] == "Image" } {
+	 if { [ $dustin getNodeTransFromParent $path ] == 1 && [ $dustin getNodeTransToParent $path ] == 1 } {
+	     return iarrowbrain
+	 } else {
+	     return ibrainpurple
+	 }
+    }
+
+    return ibrainyellow
+}
+
+::itcl::body bis_treegui::getLineColor { path } {
+    if { [ $dustin getNodeTransFromParent $path ] != "" && [ $dustin getNodeTransToParent $path ] != "" } {
+	return green
+    }
+    if { [ $dustin getNodeTransFromParent $path ] == "" && [ $dustin getNodeTransToParent $path ] != "" } {
+	return purple
+    }
+    if { [ $dustin getNodeTransFromParent $path ] != "" && [ $dustin getNodeTransToParent $path ] == "" } {
+	return orange
+    }
+    if { [ $dustin getNodeTransFromParent $path ] == "" && [ $dustin getNodeTransToParent $path ] == "" } {
+	return red
+    }
+}
+
+
+##########################################################################################
+#                             This ends the bis_treegui class                              #
+##########################################################################################
+#
+#
+#
+#
+#
+# A couple static procs
+#
+proc Compute { image_ref image_trn { mode linear } } {
+    
+    set dim1 [ [ $image_ref GetImage ] GetDimensions ]
+    set dim2 [ [ $image_trn GetImage ] GetDimensions ]
+    if { [lindex $dim2 0 ] <2 || [ lindex $dim1 0 ] < 2 } { 
+	::pxtclutil::Warning "No Images in Memory\n Cannot Compute Registration!"
+	return  0
+    }
+    
+    
+    if { $mode == "linear" } {
+	set swindow "Linear Reg"
+    } else {
+	set swindow "NonLinear Reg"
+    }
+    
+    $viewer1  SetImageFromObject $image_ref $this
+    $viewer2  SetImageFromObject $image_trn $this
+    
+    $overlaycontrol EnableRegistrationButtons
+    $overlaycontrol ShowWindow $swindow
+    $overlaycontrol SetAutoSave 0
+}
+
+proc GrabRegistration { image_ref image_trn } { 
+    
+    set n0 [ file dirname [ ${image_ref} cget -filename ] ]
+    set n1 [ file tail [ ${image_trn} cget -filename ] ]
+    set n2 [ file tail [ file rootname [ ${image_ref}  cget -filename ] ] ]
+    set suffix "matr"
+    
+    if { [ $newtr IsA "vtkGridTransform" ] == 1 } {
+	set suffix "grd"
+    } elseif { [ $newtr IsA "vtkpxComboTransform" ] == 1 } {
+	set suffix "grd"
+    } elseif { [ $newtr IsA "vtkThinPlateSplineTransform" ] == 1 } {
+	set suffix "tps"
+    }
+    
+    set mname [ file join $n0 "${n1}_${n2}.${suffix}" ]
+    set ok 1
+    
+    
+    set newtr [ [pxitcltransform \#auto ] GetThisPointer  ]
+    $newtr configure -filename $mname
+    set tr [ $overlaycontrol GetTransformation ]
+    $newtr  CopyTransformation 
+    $newtr  Save ""
+    return $newtr
+}
+
+# ------------------------------------------------------------------
+
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    
+    set thisGUI [bis_treegui \#auto]
+    wm withdraw .
+    
+    $thisSPECT configure -IsSolo 1
+    $thisSPECT Initialize .[pxvtable::vnewobj] 2
+    $thisSPECT ShowTop
+    
+}
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/dsitcltree.tcl b/bioimagesuite30_src/bioimagesuite/datatree/dsitcltree.tcl
new file mode 100644
index 0000000..6c80a83
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/dsitcltree.tcl
@@ -0,0 +1,720 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide dsitcltree 1.0
+
+package require Itcl
+package require pxvtable 1.0
+package require struct;          #This package includes the "struct::tree"
+
+lappend auto_path [file dirname [info script]]
+
+::itcl::class dsitcltree {
+   
+    protected variable imageList 
+    protected variable imagePath
+    protected variable treeArray
+    protected variable pathArray
+    protected variable masterCount
+    protected variable tree
+
+    public method printSelf {}
+    
+    #accessor methods
+    public method GetThisPointer   { } 
+    public method getNumberOfNodes { }
+    public method getRoot          { }
+    public method getPathList      { }
+    public method pathExist        { path }
+    public method getMasterCount   { } { return $masterCount }
+    public method getAllNodes      { } 
+
+    protected method getNodeProperty     { property nodeID }
+
+    public method getNodeParent          { nodeID } 
+    public method getNodeType            { nodeID } { return [ getNodeProperty type     $nodeID ] }
+    public method getNodeTitle           { nodeID } { return [ getNodeProperty title    $nodeID ] }
+    public method getNodeFileName        { nodeID } { return [ getNodeProperty filename $nodeID ] }
+    public method getNodeNotes           { nodeID } { return [ getNodeProperty note     $nodeID ] }
+    public method getNodeImageObject     { nodeID } { return [ getNodeProperty imageobject          $nodeID ] }
+    public method getNodeTransFromParent { nodeID } { return [ getNodeProperty transfromparfilename $nodeID ] }
+    public method getNodeTransToParent   { nodeID } { return [ getNodeProperty transfromparfilename $nodeID ] }
+
+
+    public method getCommonAncestor      { node1 node2 }
+
+    #modifer methods
+    public method setNodeFileName        { fileName  nodeID }
+    public method setNodeType            { fileName  nodeID }
+    public method setNodeNotes           { fileName  nodeID }    
+    public method setNodeTransFromParent { transform nodeID }
+    public method setNodeTransToParent   { transform nodeID }
+    public method setNodeImageObject     { object    nodeID }
+    public method setNodeTitle           { title     nodeID }    
+
+    public method addSubTree        { treeObj newParentNode }
+    public method addNode           { title parentNode type }
+    public method deleteNode        { nodeID }
+    public method initializeNewTree { }
+
+    public method copyTree       { treeObj }
+    public method copyTreeAtNode { treeobj node }
+    public method copyNode       { treeobj path newPath newParentPath }
+
+    protected method convertNodeNumberToNodePath { nodeID }
+    protected method convertNodePathToNodeNumber { nodeID }
+    public method uniqueTitle { title parentPath }
+
+    protected method getTreeFile  { {mode 0} }
+    public method saveReorangized { {filename ""} }
+    public method writeDatatree   { {relativePath 1} {filename ""} }
+    public method readDatatree    { {filename ""} }
+   
+    protected method readChellyDatatree { filename } 
+    protected method formatIDValue { text }
+    constructor { args } {
+
+	set tree [ struct::tree [ pxvtable::vnewobj ] ]
+	set imageList [ list "MNI_T1_1mm.nii.gz" "MNI_T1_1mm_stripped.nii.gz" "MNI_T1_2mm.nii.gz" "MNI_T1_2mm_stripped.nii.gz" ]
+	set imagePath [ file normalize [ file join [ file join [ file dirname [ info script ] ] [ file join ..  images  ] ] ] ]
+	set masterCount 1
+	$tree rename root /Data
+	
+	if { [string length $args] } { $this initializeNewTree }
+    }
+    
+    destructor {
+	set pathList [ $tree descendants /Data ]
+	foreach path $pathList {
+	    if { [ $tree keyexists $path imageobject ] } {
+		::itcl::delete object [ getNodeImageObject ]
+	    }   
+	}
+	$tree destroy
+    }
+}
+#change to use struct tree
+::itcl::body dsitcltree::printSelf { } {
+
+    puts \n
+    set pathList [ $tree descendants /Data ]
+    foreach path $pathList {
+	puts "path=$path"
+	foreach property { Parent Title Type Notes
+	    FileName TransToParent TransFromParent }  {
+	    puts "$property= [ getNode${property} $path ]"
+	}
+	puts "-----------------------"
+    }
+}
+
+
+::itcl::body dsitcltree::GetThisPointer { } {
+    return $this
+}
+#do we need it
+::itcl::body dsitcltree::getNumberOfNodes { } {
+    return [ llength [ array names pathArray ] ]
+}
+#do we need it
+::itcl::body dsitcltree::getRoot { } {
+    return $treeArray(rootname)
+}
+#do we need it
+::itcl::body dsitcltree::getPathList { } {
+
+    set root [ $tree rootname ]
+    set out  [ $tree descendants $root  ]
+    set out  [ linsert $out 0 $root ]
+    return $out
+}
+#do we need it
+::itcl::body dsitcltree::getAllNodes { } {
+   return [ lsort [ $tree nodes ] ]
+}
+
+#is used in tree gui
+::itcl::body dsitcltree::pathExist { path } {
+    #also could do return [ $tree exsists $path ]
+    if { [ lsearch -exact [ getPathList ] $path ] > -1 } {
+	return 1
+    } else { 
+	return 0
+    }
+}
+
+#possilbe add getDesendant to return current node with [ tree decendant ]
+#possilbe add getDesendant to return current node with [ tree decendant ] with ancestor
+
+#takes in a node path and returns the node parent 
+::itcl::body dsitcltree::getNodeParent { nodeID } {
+ 
+    if { [ $tree exists $nodeID  ] && $nodeID != [ $tree rootname ] } {
+	return [ $tree parent $nodeID  ]
+    } else { return "" }
+}
+
+#takes in a node path and a property key for the node
+#return the value stored by the node for the key
+#returns empty string if key doesn't exists
+#private method-- should only be called be the other accesor methods
+::itcl::body dsitcltree::getNodeProperty { property nodeID } {
+    
+    if { [ $tree keyexists $nodeID $property ] } {
+	return [ $tree get $nodeID $property ]
+    } else { return "" }
+}
+
+::itcl::body dsitcltree::getCommonAncestor { node1 node2 } {
+ 
+    set oneuppers [ $tree ancestors $node1 ] 
+    set twouppers [ $tree ancestors $node2 ]
+    
+    set ones [ linsert $oneuppers 0 $node1 ]
+    set twos [ linsert $twouppers 0 $node2 ]
+    
+    set length [ llength $ones ]
+
+    for { set x 0 } { $x < [ llength $ones ] } { incr x } {
+	if { [ lsearch $twos [ lindex $ones $x ] ] != -1 } {
+	    return [ lindex $twos [ lsearch $twos [ lindex $ones $x ] ] ]
+	}
+    }
+    return [ $tree rootname ]
+}
+#delete
+::itcl::body dsitcltree::convertNodePathToNodeNumber { nodeID } {
+
+    set isPath [ regexp {\D} $nodeID ]
+    if { $isPath } {
+	set nodeID $pathArray($nodeID)   
+    }
+    return $nodeID
+}
+#delete
+::itcl::body dsitcltree::convertNodeNumberToNodePath { nodeID } {
+
+    set isPath [ regexp {\D} $nodeID ]
+    if { $isPath != 1 } {
+	set nodeID $treeArray($nodeID,path) 
+    }
+    return $nodeID
+}
+
+#Modifier methods to change the filename, type, transforms and object of a node
+#all take in the new value and the node
+::itcl::body dsitcltree::setNodeFileName { fileName nodeID } {
+    
+    $tree set   $nodeID filename $fileName
+    #add delete object
+    $tree unset $nodeID imageobject
+}
+
+::itcl::body dsitcltree::setNodeType { fileName nodeID } {
+   
+    $tree set $nodeID type $fileName
+}
+
+::itcl::body dsitcltree::setNodeNotes { fileName nodeID } {
+
+    $tree set $nodeID note $fileName
+}
+
+::itcl::body dsitcltree::setNodeTransFromParent { transform nodeID } {
+
+    $tree set $nodeID transfromparfilename $transform
+}
+
+::itcl::body dsitcltree::setNodeTransToParent { transform nodeID } {
+
+    $tree set $nodeID transtoparfilename $transform
+}
+
+::itcl::body dsitcltree::setNodeImageObject { object nodeID } {
+
+    $tree set $nodeID imageobject $object 
+}
+
+
+#setNodeTitle - inputs a new title and node path
+#change the title of the selected node
+#also corrects the paths for the node
+#and it children for the change in title
+::itcl::body dsitcltree::setNodeTitle { title nodeID } {
+
+    set parentID [ getNodeParent $nodeID ]
+    set title    [ uniqueTitle $title $parentID ]
+    set newnode  "$parentID/$title"
+
+    $tree rename $nodeID $newnode
+    $tree set $newnode title $title
+
+    set childList [ $tree descendants $newnode ]
+    foreach child $childList {
+	set newChild [ regsub $nodeID $child $newnode ]
+	$tree rename $child $newChild
+    }
+
+    return $newnode
+} 
+
+::itcl::body dsitcltree::addSubTree { treeObj newParentNode } {
+   
+    set path [ lindex [ $treeObj getPathList ]  1 ]
+    set newParentPath [ regsub {/Data} [ $treeObj getNodeParent $path ] $newParentNode ]
+    set newTitle [ $this uniqueTitle [ $treeObj getNodeTitle  $path ] $newParentPath ]
+    
+    if { $newTitle != [ $treeObj getNodeTitle $path ] } {
+	$treeObj setNodeTitle $newTitle $path
+    }
+
+    foreach path [ lrange [ $treeObj getPathList ]  1 end ] {
+	set newPath [ regsub {/Data} $path $newParentNode ]
+	set newParentPath [ regsub {/Data} [ $treeObj getNodeParent $path ] $newParentNode ]
+	$this copyNode $treeObj $path $newPath $newParentPath 
+    }
+}
+
+#take in the new nodes title, parentNode, and type
+#surfaces, electordes, landmarks, and folders all have their transform set to identity
+::itcl::body dsitcltree::addNode { title parentNode type } {
+
+    set title [ uniqueTitle $title $parentNode ]
+    set newNode "$parentNode/$title"
+
+    $tree insert $parentNode end $newNode
+    $tree set $newNode title $title
+    $tree set $newNode type  $type
+
+    if { $type != "Image" } { 
+	$tree set $newNode transtoparfilename   1
+	$tree set $newNode transfromparfilename 1
+    }
+}
+
+#delete input node and all children from tree
+::itcl::body dsitcltree::deleteNode { nodeID } {
+    
+    if { [ $tree exists $nodeID ] } {
+	$tree delete $nodeID
+    }
+}
+
+#takes in the title and a node
+#ensures that all nodes have a unique path
+#if a node exisits with the same path an interger is added to the title
+::itcl::body dsitcltree::uniqueTitle { title parentNode } {
+
+    if { $parentNode == "" } { return $title } 
+    set count 1
+    set newTitle $title
+    set pathList [ $tree children $parentNode ]
+    while { [ lsearch -exact $pathList "$parentNode/$newTitle" ] >= 0  } {
+	set newTitle "$title$count"
+	incr count
+    }
+    return $newTitle
+}
+		
+#add the first node to the tree
+#is called by the constructor if arguments are given to the constructor
+::itcl::body dsitcltree::initializeNewTree { } {
+
+    addNode "MNI T1 1mm" /Data Image
+    setNodeFileName "$imagePath/MNI_T1_1mm.nii.gz" "/Data/MNI T1 1mm"
+}
+
+#COPY treeobj at the node to this
+itcl::body dsitcltree::copyTree { treeObj } {
+
+    set pathList [ $tree descendants [ $tree rootname ] ]
+    foreach path $pathList {
+	$this copyNode $treeObj $path $path [ $treeObj getNodeParent $path ]
+    }
+}
+
+itcl::body dsitcltree::copyTreeAtNode { treeObj node } {
+    
+    set node [ $treeObj convertNodeNumberToNodePath $node ]
+    set nodeParent [ $treeObj getNodeParent $node ]
+    set pathList [ $treeObj getPathList ]
+
+    foreach path $pathList {
+	set exp1 "$node/"; set exp2 "$node$"
+	if {[ regexp $exp1 $path ] || [ regexp $exp2 $path ]} {
+ 
+	    set newPath [ regsub $nodeParent $path /Data ]
+	    set parentPath [ $treeObj getNodeParent $path ]
+	    set newParentPath [ regsub $nodeParent $parentPath /Data ]
+	    
+	    $this copyNode $treeObj $path $newPath $newParentPath 
+	}    
+    }
+}
+
+#copies from treeobj to this 
+itcl::body dsitcltree::copyNode { treeObj path newPath newParentPath } {
+
+    set type [ $treeObj getNodeType $path ]
+    
+    $this addNode                [ $treeObj getNodeTitle    $path ] $newParentPath $type
+    $this setNodeFileName        [ $treeObj getNodeFileName $path ] $newPath
+    $this setNodeNotes           [ $treeObj getNodeNotes    $path ] $newPath
+
+    if { $type == "Image" } {
+	$this setNodeTransToParent   [ $treeObj getNodeTransToParent   $path ] $newPath
+	$this setNodeTransFromParent [ $treeObj getNodeTransFromParent $path ] $newPath
+    }
+}
+
+::itcl::body dsitcltree::getTreeFile { {mode 0} } {
+    
+    set typelist {
+	{"Tree Definition File" {.tre}}
+	{"All Files" {*}}
+    }
+    if { $mode } {
+	return [tk_getOpenFile -filetypes $typelist]
+    } else {
+	return [tk_getSaveFile -filetypes $typelist]
+    }
+}
+
+::itcl::body dsitcltree::saveReorangized { {filename ""} } { 
+    
+    if { $filename == "" } { set filename [ $this getTreeFile 0 ] }
+    if {![string length $filename]} {return 0}
+    set treepath [ file dirname $filename ]
+    set savePath $treepath
+
+    foreach path [ lsort [ array names pathArray ] ] {
+	set nodeID $pathArray($path)
+	if { $nodeID && $treeArray($nodeID,type) == "Folder" } {
+	    file mkdir [ file join $treepath $treeArray($nodeID,title) ]
+	    set savePath [ file join $treepath $treeArray($nodeID,title) ]
+	}
+
+	foreach value { filename transtoparfilename transfromparfilename }  {
+	    if { [ info exist treeArray($nodeID,$value) ] && [ file exist $treeArray($nodeID,$value) ] && ![ regexp {/MNI_T1_(1|2)mm(_stripped)?.nii.gz$} $treeArray($nodeID,$value) ] } {
+			
+		set fileID [ file tail $treeArray($nodeID,$value) ]
+		set newFilePath [ file join $savePath $fileID ] 
+		puts "copying $treeArray($nodeID,$value) to $newFilePath"
+	        file copy -force $treeArray($nodeID,$value) $newFilePath
+		
+		if { [ file extension $fileID ] == ".hdr" } {
+		    set fileRoot [ file rootname $fileID ]
+		    set fileDir  [ file dirname  $treeArray($nodeID,$value) ]
+		    set oldImagePath   [ file join $fileDir "$fileRoot.img"    ]
+		    set oldImageGzPath [ file join $fileDir "$fileRoot.img.gz" ]
+		    
+		    if { [ file exist $oldImagePath ] } {
+			set newImagePath   [ file join $savePath "$fileRoot.img"    ]
+			puts "copying $oldImagePath to $newImagePath"
+			file copy -force -- $oldImagePath   $newImagePath 
+		    } elseif { [ file exist $oldImageGzPath ] } {
+			set newImageGzPath [ file join $savePath "$fileRoot.img.gz" ]
+			puts "copying $oldImagePath to $newImagePath"
+			file copy -force -- $oldImageGzPath $newImageGzPath
+		    }
+		}
+		set treeArray($nodeID,$value) $newFilePath
+	    }
+	}
+    }
+    writeDatatree 1 $filename
+}
+
+::itcl::body dsitcltree::writeDatatree { {relativePath 1} {filename ""} } {
+ 
+    if { $filename == "" } { set filename [ $this getTreeFile 0 ] }
+    
+    if {![string length $filename]} {return 0}
+    
+    if { [ file extension $filename ] != ".tre" } {
+	set filename "${filename}.tre"
+    }
+        
+    set treepath "[ file dirname $filename ]/"
+    set fileID [ open $filename w ]
+    
+    puts $fileID "\#new Datatree File Format"
+
+    if { $relativePath } { 
+	puts $fileID "relativePath : 1" 
+    } else { 
+	puts $fileID "relativePath : 0" 
+    }
+    
+    puts $fileID "\n\n"
+    
+    set pathList [ $tree descendants /Data ]
+    
+    foreach path $pathList {
+	
+	puts $fileID "Path : $path"
+	foreach value { Parent Title Type Notes }  {
+	    puts $fileID "$value : [ getNode${value} $path]"
+	}
+	foreach value { FileName TransToParent TransFromParent } {
+	    if { $relativePath } {
+		regsub $treepath [ getNode${value} $path] "" match
+		puts $fileID "$value : $match"
+	    } else {
+		puts $fileID "$value : [ getNode${value} $path]"
+	    }   
+	}
+	puts $fileID "-------------------------"
+    }
+    close $fileID
+    return 1
+}
+
+#formatIDValue puts curly brackets around each string in idString
+#this is need because string with space already are enclosed in curly brackets
+#returns a string in format [ path number path2 number2 ... ]
+::itcl::body dsitcltree::formatIDValue { idString } {
+
+    set start 0
+    set returnString ""
+    puts "formating ids"
+    while { [ regexp -lineanchor -start $start -indices {(?:.).+?(?:\{|\}|$)} $idString sub ] } {
+	set start [ lindex $sub 1 ]
+	set text1 [ string range $idString [ lindex $sub 0 ] [ lindex $sub 1 ] ]
+	if { [ regexp {(?:\})(.+)} $text1 -> text1]} {
+	    set text1 [ regsub      {^\s} $text1 "\{"   ]
+	    set text1 [ regsub      {\s$} $text1 "\}"   ]
+	    set text1 [ regsub -all {\s}  $text1 "\}\{" ]
+	} 
+	set returnString "$returnString$text1"
+    }
+    return $returnString
+}
+
+::itcl::body dsitcltree::readChellyDatatree { filename } {   
+
+
+
+    if {[llength $filename]} {
+	set treepath [file dirname $filename]
+	
+	set fileid [ open $filename r ]
+	gets $fileid line
+	
+	if { [ string compare $line "#Chelly's Datatree File Format" ] != 0 } {
+	    puts stderr " File is not in Chelly's Datatree File Format "
+	    close $fileid
+	    return 0
+	}
+	
+	
+	#    set OutTreeList [read $f]
+	
+	while { [ gets $fileid line ] >=0 } {
+	    set index [string first ":" $line]
+	    
+	    if { $index > 0 }  {
+		set len   [string length $line]
+		set key   [string trim   [string range $line 0 [expr $index - 1]]]
+		
+		if {[string match -nocase {*filename} $key]} {
+		    
+		    set tempvalue [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		    if {$tempvalue != -1} {
+			set value [file join $treepath $tempvalue]
+		    } else {
+			set value $tempvalue
+		    }
+		    
+		} else {
+		    set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		}
+		set masterlist ""; set masterpath "" 
+		if { [ llength $masterlist ] > 0 } {
+		    
+		    # Detect and change
+		    set newindex [string first "filename" $key]
+		    if { $newindex >= 0 } {
+			set fname [ file tail $value ]
+			set tt [ lsearch $masterlist $fname ]
+			if { $tt >= 0 } {
+			    set newfname [ file join $masterpath $fname ]
+			    pxtkprint "DataTree: Found $fname, $value replacing with $newfname\n"
+			    set value $newfname
+			}
+		    }
+		}
+
+		set newtree($key)  $value 
+		puts stderr "New key = \"$key\" \t\t value = \"$value\""
+	    }
+	}  
+
+#	puts stderr [ array names newtree ]
+	close $fileid
+	#end of chelly's method
+
+	#a small work around for the different naming schemes
+	#create a new tree and copy it to the current tree
+	set tree2 [ struct::tree [ pxvtable::vnewobj ] ]
+	$tree2 deserialize $newtree(serialized)
+	$tree2 --> $tree
+	$tree2 destroy
+	
+	#loop through each node and rename certain properties to fit new scheme
+	$tree rename Data /Data
+	set pathList [ $tree descendants /Data ]
+	foreach path $pathList { 
+
+	    #rename all the paths to work with current naming scheme
+	    set parentID [ getNodeParent $path ]
+	    set title    [ getNodeTitle  $path ]
+	    set title    [ uniqueTitle $title $parentID ]
+	    set newnode  "$parentID/$title"
+	    $tree rename $path $newnode
+
+	    #rename the types to fit current scheme (no change to Folder type)
+	    #Surface Surface -> Surface, Surface Landmark -> Landmark,  
+	    #Surface Electrode -> Electrode, any numbers -> Image
+	    #set transformations: surface, electrodes, landmarks, and folders are idenity
+	    switch  -exact -- [ getNodeType $newnode ] {
+
+		"Surface Surface"   { 
+		    setNodeType Surface      $newnode 
+		    setNodeTransFromParent 1 $newnode
+		    setNodeTransToParent   1 $newnode
+		}
+
+		"Surface Electrode" { 
+		    setNodeType Electrode    $newnode 
+		    setNodeTransFromParent 1 $newnode
+		    setNodeTransToParent   1 $newnode
+		}
+
+		"Surface Landmark"  { 
+		    setNodeType Landmark     $newnode 
+		    setNodeTransFromParent 1 $newnode
+		    setNodeTransToParent   1 $newnode
+		}
+
+		"Folder"            { 
+		    setNodeType Folder       $newnode 
+		    setNodeTransFromParent 1 $newnode
+		    setNodeTransToParent   1 $newnode
+		}
+		default             {
+		    setNodeType Image     $newnode 
+		    if { [ $tree keyexists $newnode TransFromParFileName ] \
+			     && [ $tree get $newnode TransFromParFileName ] != -1 } {
+			setNodeTransFromParent [ $tree get $newnode TransFromParFileName ] $newnode
+		    }
+		    #need to check if *.matr and update the transto parent
+		    if { [ $tree keyexists $newnode TransToParFileName  ] \
+			     && [ $tree get $newnode TransToParFileName ] != -1 } {
+			setNodeTransToParent [ $tree get $newnode TransToParFileName ] $newnode
+		    }
+		}
+	    }								  
+	    
+	    #filename if there are any
+	    if { [ $tree keyexists $newnode FileName ] && [ $tree get $newnode FileName ] != -1 } {
+		setNodeFileName [ $tree get $newnode FileName ] $newnode
+	    }
+
+	}
+	
+	
+	printSelf
+	return 1
+    }
+}
+
+::itcl::body dsitcltree::readDatatree { {filename ""} } {   
+    
+    if {$filename == ""} { set filename [ $this getTreeFile 1 ] }
+    
+    if {![string length $filename]} { return 0 }
+    
+    set treepath [file dirname $filename]
+    set fileid [open $filename r]
+    
+    gets $fileid line
+
+    if {[ regexp {\#Chelly's Datatree File Format} $line ]} {
+	close $fileid
+	puts "Tree in old format"
+	return [ readChellyDatatree $filename ]
+    }
+
+    if {![ regexp {\#new Datatree File Format} $line ]} {
+	tk_messageBox -type ok -title "Please select another file" -message "File is not in the correct file format" -icon error
+	close $fileid
+       	return [ $this readDatatree ]
+    }
+    
+    gets $fileid line
+#    regexp {(?\S+:\s+:\s)(.+)} $line -> relativePath
+    regexp {(\S+)(?:\s+:\s)(.+)} $line -> key relativePath ; #double check this
+
+    while { [ gets $fileid line ] >=0 } {
+
+	#only read line that fit "key : value"
+	#store value into an array
+	#-> is a dummy variable that store " : "
+
+	if {[ regexp {([[:alpha:]]+)(?:\s:\s)(.+)} $line -> key value ]} {
+
+	    #parse out any key with thats a filename#double check
+	    if { [ regexp {filename} $key ] } {
+		if { [ regexp {/MNI_T1_(1|2)mm(_stripped)?.nii.gz$} $value ] && [ llength $imageList ] } {
+		    set fname [ file tail $value ]
+		    set value [ file join $imagePath $fname ]
+		} elseif { $relativePath && $value != "linear.nosave" && $value != 1} {
+		    set value [file join $treepath $value]
+		}
+	    }	       
+	    set treeArray($key) $value
+	}
+	
+	#once at the finished reading a node completely add it to the tree
+	if { $line == "-------------------------" } { 
+
+	    addNode $treeArray(Title) $treeArray(Parent) $treeArray(Type)
+
+	    catch { setNodeTransFromParent $treeArray(TransFromParent) $treeArray(Path) } 
+	    catch { setNodeTransToParent $treeArray(TransToParent) $treeArray(Path) }
+	    catch { setNodeFileName $treeArray(FileName) $treeArray(Path) }
+	    catch { setNodeNotes $treeArray(Notes) $treeArray(Path) }
+	    
+	    array unset treeArray
+	} 
+    }
+    close $fileid
+    return 1
+}
+	
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/no.xbm b/bioimagesuite30_src/bioimagesuite/datatree/no.xbm
new file mode 100644
index 0000000..5dfe50e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/no.xbm
@@ -0,0 +1,10 @@
+ #define no_width 17
+ #define no_height 17
+ #define no_x_hot 8
+ #define no_y_hot 8
+ static unsigned char no_bits[] = {
+   0x80, 0x03, 0x00, 0xf0, 0x1f, 0x00, 0xf8, 0x3e, 0x00, 0x3c, 0x70, 0x00,
+   0x7e, 0xe0, 0x00, 0xfe, 0xc0, 0x00, 0xf6, 0xc1, 0x01, 0xe7, 0xc3, 0x01,
+   0xc3, 0x87, 0x01, 0x87, 0xcf, 0x00, 0x06, 0xdf, 0x00, 0x06, 0xfe, 0x00,
+   0x0e, 0xfc, 0x00, 0x1c, 0x78, 0x00, 0xf8, 0x3c, 0x00, 0xf0, 0x1f, 0x00,
+   0x00, 0x05, 0x00 };
\ No newline at end of file
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/packages/CMakeLists.txt b/bioimagesuite30_src/bioimagesuite/datatree/packages/CMakeLists.txt
new file mode 100644
index 0000000..eb249bd
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/packages/CMakeLists.txt
@@ -0,0 +1,57 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+
+SET(KITSCRIPTS
+  ElectrodeAttrProg.tcl  
+  ImageDialog.tcl        
+  VisTree2.tcl
+  chellyDB.tcl           
+  mdImageUtils.tcl  
+  metakitDB.tcl      
+  pkgIndex.tcl              
+  pxitclchellypackages.tcl  
+  pxitcloverlaytab.tcl  
+  SPECTtools.tcl
+)
+
+SET(KITAPPS )
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+bis_complex_tcl3(bioimagesuite/datatree/packages datatree/packages ${FILELIST2} ${FILELIST})
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/packages/ElectrodeAttrProg.tcl b/bioimagesuite30_src/bioimagesuite/datatree/packages/ElectrodeAttrProg.tcl
new file mode 100644
index 0000000..e96be55
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/packages/ElectrodeAttrProg.tcl
@@ -0,0 +1,244 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec wish "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#Now we have access to tk from within this script
+
+
+package provide ElectrodeAttrProg 1.0
+
+#Add to the auto path the bioimagesuite dirs base and main
+lappend auto_path [file dirname [info script]]
+package require pxitclchellypackages
+
+# Require key packages
+package require Itcl
+package require Iwidgets
+package require VisTree2
+
+# Xenios' C++ Extensions
+package require vtkpxcontrib     1.0
+
+# Simple Naming package  [ pxvtable::vnewobj ]
+package require pxvtable         1.0
+
+::itcl::class ElectrodeAttr {
+
+    public variable IsSolo 0
+    public variable basewidget 0
+    public variable mf 0
+    public variable chckbttns 0
+    public variable ElectrodeEntryBox 0
+    public variable ImageEntryBox 0
+    public variable ElectAttrBGColor 
+    public variable mainGUIObject 0
+         
+    private variable pxitclElectrodeObj -1
+    private variable ImgObjForOverlay -1
+    private variable AttributeList -1
+    private variable AttributeSelectionArray -1
+    
+    public variable OutputImage -1
+
+    constructor { args } {
+
+    }
+
+    public method Initialize { widget electrodecontrol mainGUI }
+    public method ShowTop { }
+    public method SetElectrodeObject { obj imgobj {AttrNameList -1} {display -1}}
+    public method ShowAttributesOnImage { }
+    public method GetOutputImage { } { return $OutputImage }
+    public method SendOutputToTree { }
+
+}
+
+::itcl::body ElectrodeAttr::Initialize { widget electrodecontrol mainGUI } {
+    
+    set mainGUIObject $mainGUI
+    set ElectAttrBGColor "DarkGreen"
+    set basewidget [ toplevel $widget -bg $ElectAttrBGColor -padx 10 -pady 10 ]
+
+    wm title $basewidget "Electrode Attribute Selection Tool"
+    wm geometry $basewidget 425x350+100+50
+    
+    #The main frame of the dialog
+    set mf [labelframe $basewidget.mainframe -text "Available Attributes" -bg $ElectAttrBGColor -foreground white -padx 20]
+    pack $mf -fill both
+    
+
+    #Electrode Filename box---------------------------------------------------------
+    set elef [labelframe $basewidget.elecentryframe -text "Electrode File" -bg $ElectAttrBGColor -foreground white -padx 20]
+    pack $elef -fill x
+    set ElectrodeEntryBox [iwidgets::entryfield $elef.elecentrybox]
+    pack $ElectrodeEntryBox -side bottom -fill x 
+    #--------------------------------------------------------------------------------
+
+    #Image Filename box--------------------------------------------------------------
+    set imgf [labelframe $basewidget.imageentryframe -text "Space Image File" -bg $ElectAttrBGColor -foreground white -padx 20]
+    pack $imgf -fill x
+    set ImageEntryBox [iwidgets::entryfield $imgf.imgentrybox]
+    pack $ImageEntryBox -side bottom -fill x
+    #--------------------------------------------------------------------------------
+
+    #Button to create overlay--------------------------------------------------------
+    set CreateButton [eval "button $basewidget.[pxvtable::vnewobj] -text \"Create Electrode Overlay Image!\" -command {$this ShowAttributesOnImage; $this SendOutputToTree }"]
+    pack $CreateButton -side bottom
+    #--------------------------------------------------------------------------------
+    
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    wm withdraw $basewidget
+
+    
+}
+
+::itcl::body ElectrodeAttr::ShowTop { } {
+
+    if { $basewidget == 0 } { 
+	return 
+    }
+    
+    
+    if { [ winfo ismapped $basewidget ] == 1 } {
+	raise $basewidget
+	return $basewidget
+    }
+    
+    wm deiconify $basewidget
+    
+    return $basewidget
+    
+
+}
+
+::itcl::body ElectrodeAttr::SetElectrodeObject { obj imgobj {AttrNameList -1} {display -1}} {
+
+    
+
+    set  pxitclElectrodeObj $obj
+    set  ImgObjForOverlay     $imgobj
+    set  AttributeList      $AttrNameList
+
+    #Clear the Attribute Selection Array
+    catch { unset AttributeSelectionArray } 
+
+    #Remove all previous buttons (and error label, if present)
+    foreach bttn $chckbttns { 
+	catch { destroy $bttn }
+    }
+    catch { destroy $mf.noattributeslabel }
+
+    set chckbttns ""
+ 
+    if {$AttrNameList != -1} {
+	foreach name $AttributeList {
+	    set AttributeSelectionArray($name) 1
+	    lappend chckbttns [checkbutton $mf.$name -text $name -variable [itcl::scope AttributeSelectionArray($name)] -bg $ElectAttrBGColor -activebackground "dark sea green" -foreground white -activeforeground white]
+	    pack $mf.$name 
+	}
+    } else {
+	label $mf.noattributeslabel -text "No attributes have been loaded for this electrode set" -foreground red -bg $ElectAttrBGColor
+	pack $mf.noattributeslabel -padx 20 -pady 20
+    }
+
+    $ElectrodeEntryBox clear
+    if {$display != -1} {
+	$ElectrodeEntryBox insert 0 $display
+    }
+    $ImageEntryBox clear
+    catch {$ImageEntryBox insert 0 [$ImgObjForOverlay cget -filename]}
+
+
+}; #End SetElectrodeObject
+
+
+::itcl::body ElectrodeAttr::ShowAttributesOnImage { } {
+
+    set AttrExportList ""
+    for {set k 0} {$k < [llength $AttributeList] } {incr k} {
+	if {$AttributeSelectionArray([lindex $AttributeList $k]) == 1} {
+	    lappend AttrExportList $k
+	}
+    }
+
+    puts $AttrExportList
+    set electrodemultigrid [$pxitclElectrodeObj GetObject]
+
+    set ng [ $electrodemultigrid GetNumberOfGrids ] 
+    for { set i 0 } { $i < $ng } { incr i } {
+	set grid [ $electrodemultigrid GetElectrodeGrid $i ]
+	$grid SetVisible 1
+    }
+    $grid Update
+
+    set numcomp [ llength $AttrExportList ]
+    set arr [ vtkShortArray [ pxvtable::vnewobj ]]
+    $arr SetNumberOfTuples $numcomp
+    $arr FillComponent 0 0
+    for { set i 0 } { $i < $numcomp } { incr i } {
+	set md [ lindex $AttrExportList $i ]
+	set md [ expr $md + 20 ]
+	$arr SetComponent $i 0 $md
+	puts stderr "Attribute $i [ $arr GetComponent $i 0 ]"
+    }
+    
+  
+    set img [ $electrodemultigrid CreateSinglePixelImage $arr [ $ImgObjForOverlay GetImage ] ]
+    
+    set imgout [ [pxitclimage \#auto] GetThisPointer ]
+    $imgout ShallowCopyImage $img
+    $imgout CopyImageHeader [ $ImgObjForOverlay GetImageHeader ]
+    $img Delete
+    $arr Delete
+
+    set OutputImage $imgout
+}
+
+::itcl::body ElectrodeAttr::SendOutputToTree { } {
+
+    $mainGUIObject PutElectrodeAttrControlOutputInTree
+
+}
+
+# ---------------------------------------------------------------------------
+# if ElectrodeAttrProg is called from the command line, start it in its own window
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    
+    set thisAttrControl [ElectrodeAttr \#auto]
+    wm withdraw .
+    
+    $thisAttrControl configure -IsSolo 1
+    $thisAttrControl Initialize .[pxvtable::vnewobj]
+    $thisAttrControl ShowTop
+    
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/packages/ImageDialog.tcl b/bioimagesuite30_src/bioimagesuite/datatree/packages/ImageDialog.tcl
new file mode 100644
index 0000000..c1d49eb
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/packages/ImageDialog.tcl
@@ -0,0 +1,56 @@
+#!/bin/sh
+#Next line is a comment in Tcl, but not in bash \
+exec wish -f "$0" ${1+"@0"}
+#Now we have access to tk from within this script
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+package require Itcl
+package require Iwidgets
+
+
+::itcl::class ImageDialog {
+
+    public method getType {}
+
+    constructor { } { }
+
+}
+
+::itcl::body ImageDialog::getType {} {
+
+    return "This type"
+
+}
+
+set CD [ImageDialog \#auto]
+
+set result [$CD ImageDialog::getType]
+puts "result: $result"
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/packages/SPECTtools.tcl b/bioimagesuite30_src/bioimagesuite/datatree/packages/SPECTtools.tcl
new file mode 100644
index 0000000..ce497ec
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/packages/SPECTtools.tcl
@@ -0,0 +1,784 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec wish "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+#Now we have access to tk from within this script
+
+package provide SPECTProcessProg 1.0
+
+#Add to the auto path the bioimagesuite dirs base and main
+lappend auto_path [ file dir [ info script ] ]
+package require pxitclchellypackages 
+
+# Require key packages
+package require Itcl
+package require Iwidgets
+
+# C++ Extensions
+package require vtkpxcontrib 1.2
+
+# Simple Naming package  [ pxvtable::vnewobj ]
+package require pxvtable         1.0
+
+#Chelly's ImageUtils Package
+package require mdImageUtils     1.0
+
+
+
+::itcl::class SPECTprocess {
+
+    public variable IsSolo 0
+    public variable basewidget 0
+    public variable thisfolder 0
+    public variable viewer
+
+    #GUI variables
+    public variable MainGUIObject 0
+    public variable mainname 0
+    public variable Tabs 0
+
+    public variable SPECTmessagebox 
+    public variable blobMessagebox 
+
+    #imageArray variables refer to nodes, 
+    #objectArray refer to pxitcl objects
+    public variable imageArray
+    public variable objectArray
+
+    #These are the parameter variables
+    public variable parameters
+    public variable statDisplay 
+    public variable entryfieldArray
+
+    public variable resultTreeFolder 
+    public variable SPECTpath  
+    public variable MNINode 
+    public variable PatientMRINode 
+    public variable InterictalNode 
+
+    private variable tree 0; #pointer to the main tree
+	
+    constructor { args } {
+	set parameters(smoothingSigma) 16
+	set parameters(extentThresh) 125
+	set parameters(sigLevel) 0.01
+	set parameters(useMask) 1
+	set parameters(saveprocessdata) 0
+
+	set thisfolder [ file dirname [ info script ] ]
+	set SPECTpath [ file join $thisfolder .. images ]
+    }
+    
+    #GUI Init Method for SPECTprocess
+    public method Initialize { widget mainGUIObj viewerIn } 
+    public method setTabs  { color label index }
+    public method setTab1  { iframe color }
+    public method setTab23 { topfr botfr index }
+    public method setTab4 { iframe color }
+    public method setResultDispField { index1 mode }
+    
+    #Button Callbacks
+    public method AddTreeInMain { }
+    public method addImageToTree { nodeName nodeLoc nodeTitle imageName  } 
+    public method GrabTreeSelection { num field }
+    public method ClearTab1Fields { args }
+	
+    #Processing Methods
+    public method ShowTop { } 
+    public method toggle { name value }
+
+    public method bisCalcs { }
+    public method RVIEWcalcs { }
+    public method ISAScalcs { }
+    public method rejoinBlobs { }
+	
+    public method preprocess { mode }
+    public method stats { ictal inter }
+    public method message { messageList messagebox }
+    public method finishMessage { messagebox }
+    public method saveInTree { inputImage treeLoc imageTitle messagebox }
+    public method checkForImage { inputImage inputObject inputName }
+    public method checkLoadImage { imageName inputObject }    
+    public method setResultFolder { inputImage folderTitle }
+    public method getTransform { inputImage1 inputImage2 }
+    public method clusterStats { mode }
+    public method saveStats    { }
+    public method setCrosshair { index }
+    public method resetDisplayField { }
+    public method displayStats { statList }
+} 
+
+#------------------------------------------------------------------------------------------
+# GUI Methods
+#------------------------------------------------------------------------------------------
+
+#creates the basic gui window and calls setTabs to create each tab individually 
+::itcl::body SPECTprocess::Initialize { widget mainGUIObj viewerIn } {
+
+    set MainGUIObject $mainGUIObj
+    set mainname [ $MainGUIObject cget -myname ]
+    set viewer $viewerIn
+   
+    set basewidget [ toplevel $widget -bg "grey85" ]
+    wm title $basewidget "SPECT Processing Tool"
+    wm geometry $basewidget 610x600+100+50
+    
+    set Tabs [ iwidgets::tabnotebook $basewidget.notebook  -tabpos s ]
+    $Tabs config -background "grey85" -backdrop "grey85" -raiseselect 1 
+    pack $Tabs -side top -expand 1 -fill both
+
+    for { set index 1 } { $index < 5 } { incr index } {
+	switch -exact $index {
+	    "1" { $this setTabs grey10    [ list "Images"  "Select The Images"         ] 1 }
+	    "2" { $this setTabs grey30    [ list "SPECT Processing"                    ] 2 }  
+	    "4" { $this setTabs Darkgreen [ list "Results" "Most Significant Clusters" ] 4 } 
+	} 
+    }
+
+    $Tabs select 0 
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    wm withdraw $basewidget
+}
+
+#sets the tab and the their display fields 
+#first creates common features to all tabs and then calls each tabs own set method	
+::itcl::body SPECTprocess::setTabs { color label index } { 
+   
+    set parent [ $Tabs add -label [ lindex $label 0 ] -background $color -selectbackground $color -foreground white -selectforeground white ]
+    set tabTop [ frame $parent.top -bg $color -padx 10 -pady 10 ]
+    pack $tabTop -fill both -expand 1
+		
+    if { [ llength $label ] == 2 } {
+	set iframe [ labelframe $tabTop.imageframe -bg $color -text [ lindex $label 1 ] -foreground white -padx 10 -pady 5 ]
+	pack $iframe -fill both -expand 1
+	$this setTab$index $iframe $color
+    } else {
+	set topfr [ frame $tabTop.top -bg $color ]; pack $topfr -side top -fill x
+	set botfr [ frame $tabTop.bot -bg $color ]; pack $botfr -side top -fill both -expand 1 -pady { 2 0 }
+	$this setTab23 $topfr $botfr $index
+    }
+}
+
+#Tab 1 Method
+::itcl::body SPECTprocess::setTab1 { iframe color } { 
+     
+    for { set index 1 } { $index <= 3 } { incr index } {
+        set f$index [ frame $iframe.frame$index -bg $color ]
+        
+	switch -exact $index {
+	    "1" { set parent $f1; set label "Interictal SPECT"    }
+	    "2" { set parent $f2; set label "Ictal SPECT"         }
+	    "3" { set parent $f3; set label "MNI Template"        }
+	} 
+
+	pack $parent -side top -fill x -pady 6 
+	
+	set parentent [ ::iwidgets::entryfield $parent.ent -width 30 -state normal -labeltext $label -foreground red -background $color -textbackground black ]
+	set parentbut [ eval "button $parent.grabbutton -background grey10 -activebackground grey15 -foreground white -activeforeground white -text \"Grab Selection\" -command {$this GrabTreeSelection $index $parent.ent } "  ] 
+	
+	pack $parentent $parentbut -side left -fill x -expand 1 -padx 3
+    }
+    
+    ::iwidgets::Labeledwidget::alignlabels $f1.ent $f2.ent $f3.ent
+    
+    set f8 [ frame $iframe.frame8 -bg $color ]
+    pack $f8 -side top -fill x -pady 2 
+
+    set treebut  [ eval "button $f8.treebutton  -text \"Make Tree\" -background grey10 -activebackground grey15 -width 30 -foreground white -activeforeground white -command {$this AddTreeInMain}" ]
+   
+    set clearbut [ eval "button $f8.clearbutton -text \"Clear All\" -background grey10 -activebackground grey15 -foreground white -activeforeground white -command {$this ClearTab1Fields $f1.ent $f2.ent $f3.ent  }" ]
+   
+    pack $treebut -side left; pack $clearbut -side left -fill x -expand 1
+
+    for { set index 10 } { $index <= 50 } { incr index 10 } { 
+	set tempFrame [ frame $iframe.frame$index -bg $color ]; pack $tempFrame
+    }
+  
+    set chkButMask [ checkbutton $iframe.frame50.chkMask -text "Use SPECT mask" -variable [ itcl::scope parameters(useMask) ] ]
+    set chkButSave [ checkbutton $iframe.frame50.chkSave -text "Save Intermediate Data" -variable [ itcl::scope parameters(saveprocessdata) ] ]
+
+    pack $chkButMask $chkButSave -side left -fill x -expand 1 -padx 3
+
+    set entryfieldArray(smooth) [ ::iwidgets::entryfield $iframe.frame10.ent -width 30 -state normal -labeltext "Smoothing Kernel FWHM(mm)" -background $color -foreground green -textbackground black ]
+   
+    set entryfieldArray(extentThresh) [ ::iwidgets::entryfield $iframe.frame20.ent -width 30 -state normal -labeltext "Extent Threshold" -background $color -foreground green -textbackground black ]
+
+    set entryfieldArray(significance) [ ::iwidgets::entryfield $iframe.frame30.ent -width 30 -state normal -labeltext "Significance Level" -background $color -foreground green -textbackground black ]
+	
+    pack $entryfieldArray(smooth) $entryfieldArray(extentThresh) $entryfieldArray(significance) -side left -fill x -expand 1 -padx 3
+    $entryfieldArray(smooth)       insert 0 $parameters(smoothingSigma) 
+    $entryfieldArray(extentThresh) insert 0 $parameters(extentThresh)
+    $entryfieldArray(significance) insert 0 $parameters(sigLevel)
+    ::iwidgets::Labeledwidget::alignlabels $entryfieldArray(smooth) $entryfieldArray(extentThresh) $entryfieldArray(significance)
+}
+
+#Tab 2 and 3 Method
+::itcl::body SPECTprocess::setTab23 { topfr botfr mode } {
+
+    if { $mode == 2 } { set buttonList [ list "ISAS_Processing" ISAScalcs "ISAS_HN_Processing" bisCalcs "Subtraction_Processing" RVIEWcalcs SPECTmessagebox ] 
+    } else { return }
+
+    for { set index 1 } { $index < [ llength $buttonList ] } { incr index 2 } {
+	set but [ eval "button $topfr.button$index -text [ lindex $buttonList [ expr $index - 1 ] ] -command { $this [ lindex $buttonList $index ] } -background green -activebackground LightGreen" ]
+	pack $but -fill x
+    }
+	
+    set  [ lindex $buttonList [ expr [ llength $buttonList ] - 1 ] ] [ iwidgets::scrolledtext $botfr.output -width 40 -height 14 -wrap word -background grey80 -textbackground white ];
+    pack $botfr.output -side top -fill both -expand 1
+}   
+    
+#Tab 4 Method
+::itcl::body SPECTprocess::setTab4 { iframe color } {
+
+    for { set index 1 } { $index <= 12 } { incr index } {
+	set h$index [ labelframe $iframe.frame$index -bg $color ] 
+    }
+
+    pack $h1 $h2 $h3 $h4 $h5 $h6 $h7 $h8 $h9 $h10 -side top -fill x -pady 3
+    pack  $h11 $h12
+    #label $h9.label -text "Note: Only the five most significant clusters are listed" -background $color -foreground orange; pack $h6.label 
+
+    set grabEnt [ ::iwidgets::entryfield $h11.ent -width 30 -state normal -labeltext "TMAP" -foreground red -background $color -textbackground black ]
+    set grabBut [ eval "button $h11.grabbutton -background $color -activebackground grey15 -foreground white -activeforeground white -text \"Grab Selection\" -command { $this GrabTreeSelection 8 $h11.ent } "  ]
+    pack $grabEnt $grabBut -side left -fill x -expand 1 -padx 3
+
+    set but1 [ eval "button $h12.button1 -text \"Hyperperfusion Statistics\" -command { $this clusterStats 2 } -background $color -activebackground grey15 -foreground white -activeforeground white" ]
+    set but2 [ eval "button $h12.button2 -text \"Hypoperfusion Statistics\"  -command { $this clusterStats 3 } -background $color -activebackground grey15 -foreground white -activeforeground white" ]
+    set but3 [ eval "button $h12.button3 -text \"Save Statisitcs\"  -command { $this saveStats } -background $color -activebackground grey15 -foreground white -activeforeground white" ]
+    pack $but1 $but2 $but3 -side left -fill x -expand 1 -padx 3
+
+    for { set index1 0 } { $index1 < 10 } { incr index1 } {
+	for { set index2 0 } { $index2 < 7} { incr index2 } {
+	    
+	    switch -exact $index1 {
+		"0" { set entField $h1 }
+		"1" { set entField $h2 }
+		"2" { set entField $h3 }
+		"3" { set entField $h4 }
+		"4" { set entField $h5 }
+		"5" { set entField $h6 }
+		"6" { set entField $h7 }
+		"7" { set entField $h8 }
+		"8" { set entField $h9 }
+		"9" { set entField $h10 }
+	    }
+	   
+	    switch -exact $index2 {
+		"0" { set width 5;  set label "ksize" }
+		"1" { set width 12; set label "cluster pvalue" }
+		"2" { set width 14; set label "corrected pvalue" }
+		"3" { set width 9;  set label "max tscore" }
+		"4" { set width 3;  set label "x" }
+		"5" { set width 3;  set label "y" }
+		"6" { set width 3;  set label "z" }
+	    }
+	    set tmp [ ::iwidgets::entryfield $entField.ent$index2 -width $width -state normal -foreground white -background $color -textbackground black -textvariable [ itcl::scope statDisplay($index1,$index2) ] ]
+	    if { $index1 == 0 } { 
+		set statDisplay(0,$index2) $label 
+	    } else {
+		set statDisplay($index1,$index2) 0
+	    }
+		    
+	    pack $tmp -side left -padx 1 -pady 4            
+	}
+	if { $index1 != 0 } {
+	    set but [ eval "button $entField.button -text \"Set Crosshairs\"  -command { $this setCrosshair $index1 } -background $color -activebackground grey15 -foreground white -activeforeground white" ]
+	    pack $but -side left -padx 1 -pady 4
+	}
+    }
+} 
+  
+#------------------------------------------------------------------------------------------
+# Button callbacks
+#------------------------------------------------------------------------------------------
+
+#Adds a Node to the tree with name nodeTitle to the location nodeLoc if the image exsist in SPECT_images it's set in the tree
+::itcl::body SPECTprocess::addImageToTree { nodeName nodeLoc nodeTitle imageName } {
+
+    set temp [ lindex [ $MainGUIObject AddImage [ $MainGUIObject GetRealTree ] $nodeLoc $nodeTitle ] 2 ]
+    set $nodeName $temp
+    if { [ file exists [ file join $SPECTpath $imageName ] ] && $imageName != "" } {
+	$MainGUIObject setNodeFilename $temp [ file join $SPECTpath $imageName ]
+	$MainGUIObject toggleIdentity $temp 1
+    }
+}
+
+#creates the tree structure for SPECT processing 
+::itcl::body SPECTprocess::AddTreeInMain { } {
+
+    #Join the name of the main script with "packages" and "SPECT_Images" folders to get path
+    #to SPECT processing images
+        
+    set SelectionID [ $MainGUIObject GetIDFromSelection ]
+    #Add a containing folder
+    set FolderNode [ lindex [ $MainGUIObject AddFolder [ $MainGUIObject GetRealTree ] $SelectionID "SPECT Processing" ] 2 ]
+	
+    $this addImageToTree MNINode           $FolderNode     "MNI Template MRI"          MNI_T1_2mm.nii.gz
+    $this addImageToTree MNIstrippedNode   $MNINode        "MNI Template MRI stripped" MNI_T1_2mm_stripped.nii.gz
+    $this addImageToTree TemplateSPECTNode $MNINode        "MNI Template SPECT"        ISAS_SPECT_Template.nii.gz
+    $this addImageToTree PatientMRINode    $MNINode	   "Patient MRI" 	       ""
+    $this addImageToTree InterictalNode    $PatientMRINode "Interictal SPECT"          ""
+    $this addImageToTree IctalNode         $InterictalNode "Ictal SPECT"               ""
+
+    $MainGUIObject updateVisTree [ $MainGUIObject GetVisTree ]  [ $MainGUIObject GetRealTree ]
+}
+
+::itcl::body SPECTprocess::GrabTreeSelection { num field } {
+    
+    set SelectionID [ $MainGUIObject GetIDFromSelection ]
+    set tree [ $MainGUIObject GetRealTree ]
+    
+    if { $SelectionID != -1 && $SelectionID != [ $tree rootname ] } {    
+    	$MainGUIObject EnsureFileLoaded $SelectionID
+	set imageArray($num) $SelectionID
+	$field clear
+	$field insert 0 [ $tree get $SelectionID title ]
+	$field configure -foreground green
+    }
+}
+
+#Clears the all the Fields in Tab1
+::itcl::body SPECTprocess::ClearTab1Fields { args } {
+    
+    foreach field $args {
+	$field clear
+	$field config -foreground red;
+    }
+   
+    for { set index 1 } { $index <= 7 } { incr index } {
+        if { [ info exists imageArray($index) ] } {
+	    unset imageArray($index)
+	}
+    }
+}
+
+::itcl::body SPECTprocess::setCrosshair { index } {
+    
+    for { set i 4 } { $i < 7 } { incr i } {
+	set coordinate$i [ expr 2*$statDisplay($index,$i) ]
+    }
+
+    [ $viewer GetViewer ] SetScaledCoordinates $coordinate4 $coordinate5 $coordinate6
+}
+
+#------------------------------------------------------------------------------------------
+# Processing methods
+#------------------------------------------------------------------------------------------
+
+
+
+#Saves the imputImage to the harddrive
+#Places a node on the datatree at treeloc with name imageTitle and pointing to the inputImage
+#If identity is true the transformation is set to indentity
+::itcl::body SPECTprocess::saveInTree { inputImage treeLoc imageTitle messagebox} {
+   
+   $inputImage Save 
+   set thenewimg [ lindex [ $MainGUIObject AddImage $tree $treeLoc $imageTitle ] 2 ]
+   $MainGUIObject toggleIdentity $thenewimg 1
+   $MainGUIObject setNodeFilename $thenewimg [ $inputImage cget -filename ]
+   $MainGUIObject updateVisTree [ $MainGUIObject GetVisTree ] $tree
+   $messagebox insert end "$imageTitle Saved as : [ $inputImage cget -filename ]\n"
+}
+
+#Only checks to see in the input image is specified in the SPECTtool gui; does not check if image exsist
+::itcl::body SPECTprocess::checkForImage { arrayLoc inputObject inputName } {
+   
+   if { [ info exists imageArray($arrayLoc) ] } {
+       set objectArray($inputObject) [ $tree get $imageArray($arrayLoc) pxitclobj ]
+       return 0
+   } else {
+       set ok [ tk_messageBox -type ok -message "$inputName is not set. Quiting Process" -icon error ]
+       return -1
+   }
+}
+
+::itcl::body SPECTprocess::checkLoadImage { imageName inputObject } {
+    
+    set fileName [ file join $SPECTpath $imageName ]
+    set objectArray($inputObject) [ [pxitclimage \#auto] GetThisPointer ]
+    if { [ file exists $fileName ] } {
+	$objectArray($inputObject) Load $fileName
+	return 0
+    } else {
+	tk_messageBox -type ok -message "Could not find $imageName. Please set load it now." -icon error
+	if { [ $objectArray($inputObject) Load "" ] } { 
+	    return 0
+	} else {
+	    ::itcl::delete object $objectArray($inputObject)
+	    return -1 
+	}
+    }
+}
+
+#Gets the transformations from inputImage to inputImage2 and returns them in a list
+::itcl::body SPECTprocess::getTransform { inputImage1 inputImage2 } {
+	
+    $MainGUIObject findTransforms $tree $inputImage1 $inputImage2
+    array set TransCache [ $MainGUIObject GetTransformsCache ]
+    set TransList $TransCache($mainname,$inputImage1:$inputImage2)
+    return $TransList
+}
+
+#Creates a folder for results name folderTitle as a child of inputImage
+::itcl::body SPECTprocess::setResultFolder { inputImage folderTitle } {
+	
+    set resultTreeFolder [ lindex [ $MainGUIObject AddFolder $tree $inputImage $folderTitle ] 2 ]
+    $MainGUIObject updateVisTree [ $MainGUIObject GetVisTree]  $tree
+}
+
+#Inserts this finishing message to messagebox
+::itcl::body SPECTprocess::finishMessage { messagebox } {
+   
+    $messagebox insert end "\n\n-----------------------------------------\n"
+    $messagebox insert end "-------------Finished!!-----------\n"
+    $messagebox insert end "-----------------------------------------\n"
+    $messagebox yview moveto 1
+}
+
+#Inserts the text into the messagebox and scrolls the messagebox so the message is the first thing on the messagebox
+::itcl::body SPECTprocess::message { messageList messagebox } {
+    
+    for { set index 0 } { $index < [ llength $messageList ] } { incr index } {
+	$messagebox insert end [ lindex $messageList $index ] 
+    }
+    $messagebox yview moveto 1
+}
+
+
+#RVIEWcalcs does not smooth, warp, or mask the images.
+#It does this simple subtraction as a check for ISAS against smoothing and warping errors.
+::itcl::body SPECTprocess::RVIEWcalcs { } {
+
+    if { [ $this checkForImage 1 InterSPECTObj "Interictal SPECT" ] || [ $this checkForImage 2 IctalSPECTObj "Ictal SPECT" ] } {
+	 return -1
+    }
+
+    $this setResultFolder $imageArray(1) "Subtraction SPECT Results"
+    $this message [ list "Subtraction Calulation\n---------------------\n" ] $SPECTmessagebox
+
+    set TransList [ $this getTransform $imageArray(1) $imageArray(2) ]
+
+    #Applies transformation and reslices ictal into interictal space 
+    set Ictal_in_Int_Space [ $MainGUIObject ResliceImage $objectArray(InterSPECTObj) $objectArray(IctalSPECTObj) $TransList ] 
+    if { $parameters(saveprocessdata) } { $this saveInTree $Ictal_in_Int_Space $resultTreeFolder "Resliced Ictal" $SPECTmessagebox }
+    $this message [ list "Done Reslicing Ictal\n" "\Ictal resliced into Interictal space\n" ] $SPECTmessagebox
+
+    #Normalizes ictal to the interictal
+    #A the percentage threshold is applied, based on the option set in the Options Tab
+    set Ict_norm [ ::mdImageUtil::Normalize $Ictal_in_Int_Space $objectArray(InterSPECTObj) 0.05] 
+    if { $parameters(saveprocessdata) } { $this saveInTree $Ict_norm $resultTreeFolder "Normalize Ictal" $SPECTmessagebox }
+    $this message [ list "Done Normalizing Ictal\n" "Ictal thresholded at 0.05 of their max value\n\n" ] $SPECTmessagebox
+    
+    #Subtracts ictal from the interictal
+    set DiffSPECT [ ::mdImageUtil::Subtract $Ict_norm $objectArray(InterSPECTObj) ]
+    $this message [ list "\nDone Computing Difference SPECT\n" ] $SPECTmessagebox
+    $this saveInTree $DiffSPECT $resultTreeFolder "Subtraction_SPECT" $SPECTmessagebox
+    
+    $this finishMessage $SPECTmessagebox
+}
+
+#==========================================================================================
+
+::itcl::body SPECTprocess::rejoinBlobs { } {
+  
+    $blobMessagebox clear
+	
+    if { [ $this checkForImage 6 hyperBlob "Hyperprefusion Blob" ] || [ $this checkForImage 7 hypoBlob  "Hypoprefusion Blob" ] } {
+       	return -1
+    }
+
+    $blobMessagebox insert end "Blob Reconstruction\n---------------------\n"
+
+    SPECTprocess::setResultFolder $imageArray(6) "ISAS Blob" 
+ 
+    set reconstructedBlob [ ::mdImageUtil::Subtract $objectArray(hyperBlob) $objectArray(hypoBlob) ]
+    $this saveInTree $reconstructedBlob $resultTreeFolder "reconstructedBlob" $blobMessagebox
+ 
+    $this finishMessage $blobMessagebox
+}
+       
+	
+#-------------------------------------------------------------------------------------------------
+#ISAScalcs does the "full monty". It normalizes, masked, and smooths the images before subtraction
+#------------------------------------------------------------------------------------------------
+
+# preprocessing for ISAS (reslice, mask, smooth, scales) 
+# returns created mask for implicate masking and preprocessed SPECT 
+::itcl::body SPECTprocess::preprocess { mode } {
+    
+    set smoothingSigma [ expr { [ $entryfieldArray(smooth) get ] / sqrt( 8 * log(2) ) } ] 
+
+    #Reslice into MNI space
+    if { [ string length $mode ] == 10 } {
+	set inMNI [ $MainGUIObject ResliceImage $objectArray(STDdiffObj) $objectArray(InterSPECTObj) [ $this getTransform $imageArray(3) $imageArray(1) ] ]
+    } else {
+	set inMNI [ $MainGUIObject ResliceImage $objectArray(STDdiffObj) $objectArray(IctalSPECTObj) [ $this getTransform $imageArray(3) $imageArray(2) ] ] 
+    }
+    $this message [ list "\nDone Reslicing $mode SPECT" "\n$mode SPECT resliced into MNI space\n" ] $SPECTmessagebox    
+    if { $parameters(saveprocessdata) } { $this saveInTree $inMNI $resultTreeFolder "Reslice_$mode" $SPECTmessagebox } 
+   
+    if { $parameters(useMask) } {
+	#Mask the reslice spect with optional mask
+	set inMNI [ ::mdImageUtil::Multiply $inMNI $objectArray(SPECTMaskObj) ]
+	$this message [ list "\nDone Masking $mode SPECT\n" ] $SPECTmessagebox
+	if { $parameters(saveprocessdata) } { $this saveInTree $inMNI $resultTreeFolder "Mask_$mode" $SPECTmessagebox }
+    }
+ 
+    #Gaussian smooth the spect default to 16 mm fwhm
+    set smInMNI [ ::mdImageUtil::SmoothImage $inMNI $smoothingSigma ]
+    $this message [ list "\nDone Smoothing $mode SPECT\n" ] $SPECTmessagebox 
+    if { $parameters(saveprocessdata) } { $this saveInTree $smInMNI $resultTreeFolder "Smooth_$mode" $SPECTmessagebox }
+ 
+    #propotional scaling to 50 
+    set scale [ ::mdImageUtil::PropScale $smInMNI ]
+    $this message [ list "\nDone Scaling $mode SPECT\n" ] $SPECTmessagebox 
+    $this saveInTree [ lindex $scale 1 ] $resultTreeFolder "Preprocessed_$mode" $SPECTmessagebox
+    
+    return $scale
+}
+
+::itcl::body SPECTprocess::stats { ictal inter } {
+    
+    #subtracts Interictal SPECT from the Ictal SPECT
+    set DiffSPECT [ ::mdImageUtil::Subtract $ictal $inter ]
+    if { $parameters(saveprocessdata) } { $this saveInTree $DiffSPECT $resultTreeFolder "Diff_SPECT" $SPECTmessagebox }
+    $this message [ list "\nDone Subtracting Ictal and Interictal SPECT\n" ] $SPECTmessagebox
+
+    if { $parameters(saveprocessdata) } { $this saveInTree $objectArray(STDdiffObj)   $resultTreeFolder "STD SPECT"  $SPECTmessagebox }
+    if { $parameters(saveprocessdata) } { $this saveInTree $objectArray(MeanSPECTObj) $resultTreeFolder "mean SPECT" $SPECTmessagebox }
+
+    #Calculate the tmap for ISAS
+    #H0 is the DiffSPECT - MeanSPECTObj = 0
+    #Ha is the DiffSPECT - MeanSPECTobj != 0
+
+    set tmap [ ::mdImageUtil::ComputeIndividualVsGroup $DiffSPECT $objectArray(STDdiffObj) 1 $objectArray(MeanSPECTObj) ] 
+    #set tmap [ ::mdImageUtil::MultiplyByConstant $tmap 3 ] 
+    $this saveInTree $tmap $resultTreeFolder "TMAP" $SPECTmessagebox 
+    $this message [ list "\nDone calculating Tmap\n" ] $SPECTmessagebox
+
+    return $tmap
+}
+
+::itcl::body SPECTprocess::clusterStats { mode } {
+ 
+    if { [ $this checkForImage 8 TMAP "TMAP" ] } {
+	 return -1
+    }
+
+    $this resetDisplayField
+
+    set extentThreshold [ $entryfieldArray(extentThresh) get ]
+    set sigLevel [ expr [ $entryfieldArray(significance) get ] * 2 ] 
+    set tscore [ ::mdImageUtil::PvalueToTscore $sigLevel 13 ] 
+
+    set eulerDensity [ ::mdImageUtil::eulerCharacteristicDensity $tscore [ $entryfieldArray(significance) get ] ]
+    set reselCount   [ ::mdImageUtil::reselCount $objectArray(TMAP) 17.2 16.6 18.3 ]
+
+    set expectedVoxPerCluster [ expr [ lindex $eulerDensity 0 ] / [ lindex $eulerDensity 3 ] ]  
+    set expectedNumOfCluster 0.0
+    for { set index 0 } { $index < 4 } { incr index } {
+	set expectedNumOfCluster [ expr $expectedNumOfCluster + [ lindex $eulerDensity $index ] * [ lindex $reselCount $index ] ]
+    } 
+  
+    set statList [ ::mdImageUtil::ComputeCluster $objectArray(TMAP) $expectedVoxPerCluster $expectedNumOfCluster $tscore $extentThreshold $mode ]
+    $this displayStats $statList
+}   
+
+:::itcl::body SPECTprocess::saveStats { } {
+
+    set typelist {
+	{"text" {.txt}}
+	{"All Files" {*}}
+    }
+
+    set filename [ tk_getSaveFile -filetypes $typelist ]
+    if { ![ string length $filename ] } { return 0 }
+    set fileid [ open $filename w ]
+    puts $fileid "\n#Vxs\tuncorrPvalue \tcorrPvalue \tmaxTscore \tX \tY \tZ"
+    for { set index1 1 } { $index1 < 10 } { incr index1 } {
+	puts $fileid "\n$statDisplay($index1,0) \t$statDisplay($index1,1) \t$statDisplay($index1,2) \t$statDisplay($index1,3) \t$statDisplay($index1,4) \t$statDisplay($index1,5) \t$statDisplay($index1,5)"
+    }
+    close $fileid
+} 
+
+:::itcl::body SPECTprocess::displayStats { statList } {
+    
+    $this message [ list "\n\n#Vxs\tuncorrPvalue \tcorrPvalue \tmaxTscore \tX \tY \tZ" ] $SPECTmessagebox
+    for { set index1 1 } { $index1 <= [ llength $statList ] && $index1 < 10 } { incr index1 } {
+	$this message [ list "\n" ] $SPECTmessagebox
+	for { set index2 0 } { $index2 < 7 } { incr index2 } {
+	    set statDisplay($index1,$index2) [ lindex [ lindex $statList [ expr $index1 - 1 ] ] $index2 ]
+	    $this message [ list "[ lindex [ lindex $statList [ expr $index1 - 1 ] ] $index2 ]\t" ] $SPECTmessagebox
+	}
+    }
+}
+
+::itcl::body SPECTprocess::resetDisplayField { } {
+    for { set index1 1 } { $index1 < 10 } { incr index1 } {
+	for { set index2 0 } { $index2 < 7 } { incr index2 } {
+	     set statDisplay($index1,$index2) 0
+	}
+    }
+}
+
+::itcl::body SPECTprocess::ISAScalcs { } {
+ 
+    if {    [ $this checkForImage 1 InterSPECTObj "Interictal SPECT" ] 
+         || [ $this checkForImage 2 IctalSPECTObj "Ictal SPECT"      ]
+         || [ $this checkForImage 3 MNIObj        "MNI Template"     ] } {
+	     return -1
+    }
+    
+    if { [ $this checkLoadImage ISAS_Mean_Diff_SPECT.nii.gz MeanSPECTObj ] } {
+	return -1
+    }
+
+    if { [ $this checkLoadImage ISAS_Standard_Deviation.nii.gz  STDdiffObj ] } {
+	return -1
+    }
+   
+    if { $parameters(useMask) } {
+	if { [ $this checkLoadImage ISAS_SPECT_Mask.nii.gz SPECTMaskObj ] } {
+	    return -1
+	}
+    }
+
+    $this message [ list "\nStarting ISAS calculations\n" ] $SPECTmessagebox
+  
+    $this setResultFolder $imageArray(3) "ISAS Results"
+    
+    set intPreprocessList [ $this preprocess "Interictal" ]
+    set ictPreprocessList [ $this preprocess "Ictal" ]
+
+    set stdMask [ ::mdImageUtil::threshold $objectArray(STDdiffObj) .01 10000 ]
+    set mask    [ ::mdImageUtil::Multiply [ lindex $intPreprocessList 0 ]  [ lindex $ictPreprocessList 0 ] ]
+    set mask    [ ::mdImageUtil::Multiply $mask $stdMask ]
+    if { $parameters(saveprocessdata) } { $this saveInTree $mask $resultTreeFolder "Mask" $SPECTmessagebox }
+  
+    set preprocessIct [ ::mdImageUtil::Multiply [ lindex $ictPreprocessList 1 ] $mask ]
+    set preprocessInt [ ::mdImageUtil::Multiply [ lindex $intPreprocessList 1 ] $mask ]
+    set objectArray(MeanSPECTObj) [ ::mdImageUtil::Multiply $objectArray(MeanSPECTObj) $mask ]
+    set objectArray(STDdiffObj)   [ ::mdImageUtil::Multiply $objectArray(STDdiffObj)   $mask ]
+   
+    #$this setResultFolder $imageArray(2) "ISAS Results"
+
+    set tmap [ $this stats $preprocessIct $preprocessInt ]
+
+    set blobs [ ::mdImageUtil::ComputeCluster $tmap ] 
+    $this saveInTree [ lindex $blobs 0 ] $resultTreeFolder "Perfusion Blobs" $SPECTmessagebox 
+
+    $this RVIEWcalcs
+    $this finishMessage $SPECTmessagebox
+}
+ 
+
+::itcl::body SPECTprocess::bisCalcs { } {
+ 
+    if {    [ $this checkForImage 1 InterSPECTObj "Interictal SPECT" ] 
+         || [ $this checkForImage 2 IctalSPECTObj "Ictal SPECT"      ]
+	 || [ $this checkForImage 3 MNIObj        "MNI Template"     ] } {
+	 return -1
+    }
+       
+    if { [ $this checkLoadImage  ISASHN_Standard_Deviation.nii.gz STDdiffObj ] } {
+	return -1
+    }
+
+    if { $parameters(useMask) } {
+	if { [ $this checkLoadImage ISAS_SPECT_Mask.nii.gz SPECTMaskObj ] } {
+	    return -1
+	}
+    }
+
+    $this message [ list "\nStarting ISASHN calculations\n" ] $SPECTmessagebox
+
+    $this setResultFolder $imageArray(3) "ISASHN Results"
+
+    set intPreprocessList [ $this preprocess "Interictal" ]
+    set ictPreprocessList [ $this preprocess "Ictal" ]
+    set objectArray(MeanSPECTObj) [ ::mdImageUtil::MultiplyByConstant $objectArray(STDdiffObj) 0 ]
+
+    set stdMask  [ ::mdImageUtil::threshold $objectArray(STDdiffObj) .01 10000 ]
+    set mask     [ ::mdImageUtil::Multiply [ lindex $intPreprocessList 0 ]  [ lindex $ictPreprocessList 0 ] ]
+    set mask     [ ::mdImageUtil::Multiply $mask $stdMask ]
+    if { $parameters(saveprocessdata) } { $this saveInTree $mask $resultTreeFolder "Mask" $SPECTmessagebox }
+
+    set preprocessIct [ ::mdImageUtil::Multiply [ lindex $ictPreprocessList 1 ] $mask ]
+    set preprocessInt [ ::mdImageUtil::Multiply [ lindex $intPreprocessList 1 ] $mask ]
+    set objectArray(STDdiffObj)   [ ::mdImageUtil::Multiply $objectArray(STDdiffObj)   $mask ]
+
+    set tmap [ $this stats $preprocessIct $preprocessInt ]
+
+    set blobs [ ::mdImageUtil::ComputeCluster $tmap ] 
+    $this saveInTree [ lindex $blobs 0 ] $resultTreeFolder "Perfusion Blobs" $SPECTmessagebox 
+
+    $this RVIEWcalcs
+    $this finishMessage $SPECTmessagebox
+}
+    
+
+
+#------------------------------------------------------------------------------------------
+# End Processing methods
+#------------------------------------------------------------------------------------------
+
+::itcl::body SPECTprocess::ShowTop { } {
+    
+    if { $basewidget == 0 } { 
+	return 
+    }
+    
+    
+    if { [ winfo ismapped $basewidget ] == 1 } {
+	raise $basewidget
+	return $basewidget
+    }
+    
+    wm deiconify $basewidget
+    
+    return $basewidget
+}
+
+
+# ---------------------------------------------------------------------------
+# if called from the command line, start module in its own window
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    
+    set thisSPECT [SPECTprocess \#auto]
+    wm withdraw .
+    
+    $thisSPECT configure -IsSolo 1
+    $thisSPECT Initialize .[pxvtable::vnewobj] 2
+    $thisSPECT ShowTop
+    
+}  
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/packages/VisTree2.tcl b/bioimagesuite30_src/bioimagesuite/datatree/packages/VisTree2.tcl
new file mode 100644
index 0000000..bbe8c72
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/packages/VisTree2.tcl
@@ -0,0 +1,900 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+########################################################################################
+########################################################################################
+#				File Tree Widget Definition			       #
+#			     based on Widget by D. Richard Hipp			       #
+#			Modified July 2005 by Marcello DiStasio	to Version 2.0         #
+########################################################################################
+########################################################################################
+
+
+
+package provide VisTree2 2.0
+
+#A Couple preliminary formatting options for the file tree
+
+option add *highlightThickness 0
+
+
+namespace eval Tree { 
+
+    namespace export create dfltconfig config newitem delitem setselection getselection build buildlayer open close drawselection buildwhenidle labelat
+
+    #main Tree variable
+    variable Tree
+
+    #icon data variables
+    variable fileicon
+    variable diricon
+    variable brainiconbw
+    variable brainicongrey
+    variable purplebrainicon
+    variable redbrainicon
+    variable orangebrainicon 
+    variable yellowbrainicon 
+    variable greenbrainicon 
+    variable bluebrainicon 
+    variable lightbluebrainicon 
+    variable rainbowbrainicon 
+    variable arrowicon2 
+    variable arrowicon 
+    variable arrowbrain
+    variable cactusicon
+
+
+
+    global tcl_platform
+    switch $tcl_platform(platform) {
+	unix {
+	    set Tree(font) \
+		-adobe-helvetica-medium-r-normal-*-12-80-100-100-p-56-iso8859-1
+	}
+	windows {
+	    set Tree(font) \
+		-adobe-helvetica-medium-r-normal-*-14-100-100-100-p-76-iso8859-1
+	}
+    }
+
+    #
+    # Create a new tree widget.  $args become the configuration arguments to
+    # the canvas widget from which the tree is constructed.
+    #
+    proc create {w args} {
+
+	variable Tree
+	variable diricon
+	variable brainiconbw
+	variable brainicongrey
+	variable purplebrainicon
+	variable redbrainicon
+	variable orangebrainicon 
+	variable yellowbrainicon 
+	variable greenbrainicon 
+	variable bluebrainicon 
+	variable lightbluebrainicon 
+	variable rainbowbrainicon 
+	variable arrowicon2 
+	variable arrowicon 
+	variable arrowbrain
+	variable cactusicon
+
+
+	eval canvas $w $args
+	bind $w <Destroy> "::Tree::delitem $w /"
+	Tree::dfltconfig $w /
+	Tree::buildwhenidle $w
+	set Tree($w:selection) {}
+	set Tree($w:current) {}
+	set Tree($w:selidx) {}
+	set Tree($w:selidcurrent) {}
+	#------------------------------------------------------------------------------------------
+	# These are all the icon image definitions
+	#------------------------------------------------------------------------------------------
+
+	set diricon [image create photo idir -data {
+	    R0lGODdhEAAQAPIAAAAAAHh4eLi4uPj4APj4+P///wAAAAAAACwAAAAAEAAQAAADPVi63P4w
+	    LkKCtTTnUsXwQqBtAfh910UU4ugGAEucpgnLNY3Gop7folwNOBOeiEYQ0acDpp6pGAFArVqt
+	    hQQAO///}
+		    ]
+	#lots of for loops to clean up the transparency of the folder image
+	for {set i1 0} {$i1 < 3} {incr i1} {
+	    for {set i2 0} {$i2 < 16} {incr i2} {
+		$diricon transparency set $i2 $i1 1
+	    }
+	}
+	for {set i3 0} {$i3 < 16} {incr i3} {
+	    $diricon transparency set 15 $i3 1
+	}
+	for {set i4 15} {$i4 > 6} {incr i4 -1} {
+	    $diricon transparency set $i4 3 1
+	}
+	for {set i4 15} {$i4 > 7} {incr i4 -1} {
+	    $diricon transparency set $i4 4 1
+	}
+	#A couple more spots
+	$diricon transparency set 14 5 1
+	$diricon transparency set 0 15 1
+	$diricon transparency set 0 3 1
+	$diricon transparency set 0 4 1
+	$diricon transparency set 1 3 1
+	
+	#Now I'll correct the file image to have a transparent bg with for loops as above
+	set fileicon [image create photo ifile -data {
+	    R0lGODdhEAAQAPIAAAAAAHh4eLi4uPj4+P///wAAAAAAAAAAACwAAAAAEAAQAAADPkixzPOD
+	    yADrWE8qC8WN0+BZAmBq1GMOqwigXFXCrGk/cxjjr27fLtout6n9eMIYMTXsFZsogXRKJf6u
+	    P0kCADv/}
+		     ]
+	for {set i5 0} {$i5 < 16} {incr i5} {
+	    $fileicon transparency set 0 $i5 1
+	    $fileicon transparency set 14 $i5 1
+	    $fileicon transparency set 15 $i5 1
+	}
+	#And a couple more pixels in the corner...
+	$fileicon transparency set 11 0 1
+	$fileicon transparency set 12 0 1
+	$fileicon transparency set 12 1 1
+	$fileicon transparency set 13 0 1
+	$fileicon transparency set 13 1 1
+	$fileicon transparency set 13 2 1
+	
+	#Define a brain icon with hexadecimal values
+	set brainiconbw [image create bitmap ibrainbw -data {
+	    
+	    #define smallbrain2_width 18
+	    #define smallbrain2_height 16
+	    static char smallbrain2_bits[] = {
+		0xff,0xff,0x03,0x3f,0xf0,0x03,0x0f,0xc0,0x03,0x97,0xa4,0x03,0x07,0x11,0x03,
+		0x53,0x88,0x03,0xa5,0x45,0x02,0x0b,0x94,0x02,0x93,0x88,0x02,0x2f,0x92,0x02,
+		0x4f,0x24,0x03,0x57,0xd1,0x03,0x27,0xfd,0x03,0x9f,0xff,0x03,0xff,0xff,0x03,
+		0xff,0xff,0x03,0x00,0x88,0x00,0x00,0x00,0x19,0x00,0x00,0x00,0x66,0x61,0x6c,
+		0x73,0x65,0x00,0x67 };
+	    
+	} ]
+
+	set brainicongrey [image create photo ibraingrey -data {
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtu6WkpNvS0vT59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+IeHh/f/9v77/f3+9/r88sK6yvX69Pr+/P39\
+		/vf596Ojo7qxwvz9+9PB2CcrJVtfWYOEhpyRo/789jo4O4+NiI2KioOBimdn\
+		YOfd5tnMxIGAhnd1d2pna5WTlYKChmRoZZeXl25te5WPkXBycmVlZVRUVNXO\
+		1oGDgnd3dMrLyrvAvbatwPz8+dfJ0ZCFlrCytNfT1szMzL6+vqGfoaOeosrQ\
+		yIKAhf78/vr+/fv++eLc37apuMHDwuLi4s/Pz76/vq6vsL61voB9hPj7+rCx\
+		sdnZ2aysrL+/v6urq2lnaubZ6vj8/Ozn8qusr8vLy83NzZqampKSkn9/f8PD\
+		wvz59/77+f/8+f38//j7+fj9+Pz7+fj6+dHNz7y8vMnJyZiYmPb29v3/+/v/\
+		///9+v36///7/Pr+/vz8+rCwsM7OzqampvHx8f/////+/f/+/MTExK6uruTk\
+		5Onp6cLCwt7e3v//////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		/////////////////////ywAAAAAEgASAAAI9QABBBAwgEABAwcQHFiYQMEC\
+		Bg0iOngAIYJCBBgxLpQwISKFCgk1ZhRp4UJEDAlTXhypMUMDDRlDRtgQciSH\
+		Dh5YIojwAUQIESMPjLBYk8SBEiZOoKCZMcVFFQhWsDjQwsULGDFGRlCZUcYM\
+		GjVsMM14Q+PCnThyRIigYwePjD18xETwA0gQIUOIFDFyBCOSJEqWjGTSxMkT\
+		KFGkTFEYsQGVmhGqWHlyBUsWLQe2NObS5ewBL1/AhBEzhkwZM43PoEmjZg2b\
+		Nm7ebIATp4Gcxg3m0EFSx84dPHn07OHToI+fP7iTNwAEJpCgPn2UKx9EyE0h\
+		3AEBADs=
+	} ]
+
+	set purplebrainicon [image create photo ibrainpurple -data {
+	    R0lGODlhEgASAOcAACIiKnZ6dpqamsK6ymZmYs7OzmIqisrSymZWct7e3q5m\
+		yo4+ulZKYmZGiuLi4opSpjYyNqZ6vopiqoYqvurq6lYidqKeokJGQo5SsmIy\
+		ir62vpKGmvLy8jo6OppSwn5iko6KiqKiom5GitLC1p6Govb29mYyinIioop2\
+		jmZqZlo2erqWyrKawsrKyqpW4nY+mn5Okn42oq6urnIymvr+8tbS1p5CzlZW\
+		VoZ2hl5CZnpWhoZCro5GtnIinqKOqn5KmnJ2cnI6lrJW4oo2utK22o5uomom\
+		kr6+vv7+9o6CnoKChnYqqvr6+rauwloqepJ2ptrO4uLW5qqqqrpq4oZenpaK\
+		omI+dsbGxq6SuppKytLK1noymrKyspp+qno6rqZe0v7++opOqooyrloiho6O\
+		imouinpejmpudpJiqm4yjraqun5+fu7m8sKu0rrCvtbO1pZCwiYqJq5q0q6C\
+		wn5qitra2qJKzlpeWoo+vqJS0nIqmvb+9noypq5i2q5e2sLCwpZSwn46spZq\
+		snp2fpaOkpJGvnoqtnY2ov769v7+/oYyuiomJube5no6omIugp6KrnJyfpp6\
+		tvr++v76/vb69oKGhl4mho5Cwoo6tnouqm5ycno2ppKSkmZmZvby+oJ+hubm\
+		5oZWno5mrp5WwqamplY6cn46qp6Sorqywuba6qqurpZmrrauum4umqpm1pJK\
+		vtLOzmoykraayopCtrZW6l4qgmYuipJGsl4iimpmavr+/mYqjuLe3pI+uno+\
+		nnZ2dpZ2qtbK0n5eim5uenIykooyupaSlv76+q6usnIynoKCirKyttLC2p6G\
+		ppp+ropOrnoyqpJGtv//////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		////////////////////////////////////////////////////////////\
+		/////////////////////yH5BAEKAP8ALAAAAAASABIAAAj+ABMJRHKMAysf\
+		kYAlGUHp2CRdAgXq8sQCzbM0s774cqVDy55JAmnQiBKhFqYpYTYNWSIkz4MB\
+		lCRCcQSnlx8jFUxNyMRDjwcnjwRSWgVogalWKuh0eSIhSBYFW1yhAsPMRTFL\
+		m8wMuxDnTqVTInyNsVEEEQtMXxzNQtBhERkQygig4IOrlwlGguyk8TLjDAQA\
+		uTgpIcBgE49Yr9pEonXiS6YxVoYRGkbgBiRhGQwswfImSJ9bMxTNwhEAyK8A\
+		Bdyo+eFhzrFgzhok41MqCZcaBY5YsHDg048ViXQhSRXDVA4Dav44yM1FwydR\
+		RASCoUSlxxBFj2TUOSDliJRcwlJFRWTChkoZDBtktGghwNiaP0wQRUTEZA8N\
+		MExgHWkRQkAJMGBEFFwikzDx0CQyFEAKBwI22OAfBcgAioMUJkLBHxokIGBA\
+		ADs=
+	}]
+
+	set redbrainicon [image create photo ibrainred -data {
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtu8kAAOgSC/T59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+LKawvQHB/f/9v77/f3+9/r88sK6yvX69Pr+\
+		/P39/vf597qxwvz9+9PB2Id9dkBEQScrJVtfWYOEhuhMJ/789mRXcTo4Oykm\
+		JY+NiI2KioOBimdnYOfd5mtsdDQwNCIiKmpna5WTlYKChmRoZVRIYsOu0G5t\
+		e5WPkW9xcWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8fMrLyrvAvbat\
+		wPz8+dfJ0ZOFmrCytNfT1szMzL6+vqGfoaOeosrQyIKAhf78/vr+/fv++eLc\
+		37apuMHDwuLi4s/Pz76/vq6vsL61voB9hPj7+p6Ho7CxsdnZ2aysrL+/v6ur\
+		q2lnaubZ6vj8/Ozn8qusr8vLy83NzZqampKSkn9/f8PDwvz59/77+f/8+f38\
+		//j7+fj9+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb29v3/+/v////9+v36///7\
+		/Pr+/vz8+rCwsM7OzqampvHx8f/////+/f/+/MTExK6uruTk5Onp6cLCwt7e\
+		3skAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkAAMkA\
+		AMkAAMkAAMkAAMkAAMkAACH5BAEKAP8ALAAAAAASABIAAAj3AAEEEDCAQAED\
+		BxAcWJhAwQIGDSI6eAAhggQEGDNinEAhYgULCTWKRHABQ8QMCxOGDIlRpYYG\
+		GzKqTLlQJocOHmQe+AAihIgRKxGQKNFSoYkTKFKoWMEiJcYWLRe6eAEjhowZ\
+		NGqwtFE05Q0cOXTs4NGDpQ+FK38ACSJkCJEiRloeQTITQRIlS5g0cfIEShSM\
+		UqZQqcLSyhUsWbRs4dJlYcQGXlh+ARMmi5gxZMpIMPP4DJqaB9KoWcOmjZs3\
+		cOI8ljOHTh07d/Dk0bOHT58Gfh43+ANISiBBgwgVMnQIUYNEihbpXt6A0ZpG\
+		jhIlYs78EaQ8kXQHBAA7
+	}]
+	
+	set orangebrainicon [image create photo ibrainorange -data {
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtu85/JeuqQb9lEfT5\
+		9/z5+v77/vv+/v7+/vz+/P3+/vbz+LKawv+yQf/DZeOlQf+6Wff/9v77/f3+\
+		9/r88vmuQcK6yvX69Pr+/P39/vf59/S5bH5oipyFp8SQd7qxwvz9+9PB2OWo\
+		Y4d9dkBEQScrJVtfWYOEhpyRo+mlU/789rWayOGuXmRXcTo4OykmJY+NiI2K\
+		ioOBimdnYIp1jufd5tGaQeGgQWtsdDQwNCIiKmpna5WTlYKChmRoZVRIYsOu\
+		0NaheuGqaG5te5WPkW9xcWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8\
+		fMrLyrvAvbatwOmrdfz8+dfJ0ey2cpOFmrCytNfT1szMzL6+vqGfoaOeosrQ\
+		yIKAhf78/vr+/fv++eLc37apuMHDwuLi4s/Pz76/vq6vsL61voB9hPj7+p6H\
+		o7CxsdnZ2aysrL+/v6urq2lnaubZ6vj8/Ozn8qusr8vLy83NzZqampKSkn9/\
+		f8PDwvz59/77+f/8+f38//j7+fj9+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb2\
+		9v3/+/v////9+v36///7/Pr+/vz8+rCwsM7OzqampvHx8f/////+/f/+/MTE\
+		xK6uruTk5Onp6cLCwt7e3m03BW03BW03BW03BW03BW03BW03BW03BW03BW03\
+		BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03\
+		BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03\
+		BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03\
+		BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03\
+		BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03BW03\
+		BW03BW03BW03BW03BW03BSH5BAEKAP8ALAAAAAASABIAAAj+AAEEEDCAQAED\
+		BxAkWKhgAYMGDiI+gBBBwoQEFCpMmGBh4QUMETNoSGChJEYEGzhi5NAhogeM\
+		JA90PJASpsIPDkCEoKCwpIgRJDhS4JmghIkTQxFYQJFCxQoWLVwMTTDhBYwY\
+		MhJOmEGjho0bOHLoSIBg446OMnj08PEDSBAhQ4gU4bnRyBEKZDkiSaJkCZMm\
+		Tp6U5Qhl6kIKUaRMoVLFyhUsHLNo2cKl7AEKXbx8ARNGzBgyZUqaOYMmjVAE\
+		atawaePmDZw4HSM6kEOS5xw6ddrYuYMnTwI9svfwWaiwj58/gAIJGkSokGxD\
+		hxAlUrSIUSNHjyBFciBJtoNJlMwhVLJ0CVMmTZs4Oejk6ZP39w5A/QklqlMn\
+		+PBHkWpUyntAADs=
+	}]
+
+	set yellowbrainicon [image create photo ibrainyellow -data {
+	    
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtuxuZFv/yAPT59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+LKawvf/9v77/f3+9/r88sK6yvX69Pr+/P39\
+		/vf59wf0I7qxwvz9+9PB2Id9dkBEQScrJVtfWYOEhv789mRXcTo4OykmJY+N\
+		iI2KioOBimdnYOfd5mtsdDQwNCIiKmpna5WTlYKChmRoZVRIYsOu0G5te5WP\
+		kW9xcWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8fMrLyrvAvbatwPz8\
+		+dfJ0ZOFmrCytNfT1szMzL6+vqGfoaOeosrQyIKAhf78/vr+/fv++eLc37ap\
+		uMHDwuLi4s/Pz76/vq6vsL61voB9hPj7+p6Ho7CxsdnZ2aysrL+/v6urq2ln\
+		aubZ6vj8/Ozn8qusr8vLy83NzZqampKSkn9/f8PDwvz59/77+f/8+f38//j7\
+		+fj9+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb29v3/+/v////9+v36///7/Pr+\
+		/vz8+rCwsM7OzqampvHx8f/////+/f/+/MTExK6uruTk5Onp6cLCwt7e3gOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOqEQOq\
+		EQOqEQOqEQOqEQOqEQOqESH5BAEKAP8ALAAAAAASABIAAAjuAAEEEDCAQIED\
+		BxAgPJBAwQIGDSI6eABhIYKLGA9ImBCRQgWEGENitHAhIoaEIlFeTHggQwMN\
+		IDNazMihg0qEH0CEEDECJUoSKhGUMHECRQoVK2ayuNnCxQsYMWTMoKGyBkuf\
+		Nm7gyKFjBw+VPYIi8PEDSBAhQ4gUWWkEJEgkSZQsYdLEyRMoF6NImUIlZBUr\
+		V7Bk0bKFC8KIDbqo9PIFDJYwYsaQ2VAGsZkzbtGkUbOGTRs3b+AgjiNnDp06\
+		du7gyaNnD58GfRA38PMnCqBAggYRKmToUANEiRTJHt5gkRpGjRAhIk7c0SM8\
+		kGQHBAA7
+	}]
+
+	set greenbrainicon [image create photo ibraingreen -data {
+
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtuxuZFgf0I/T59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+LKawvf/9v77/f3+9/r88sK6yvX69Pr+/P39\
+		/vf597qxwvz9+9PB2Id9dkBEQScrJVtfWYOEhv789mRXcTo4OykmJY+NiI2K\
+		ioOBimdnYOfd5mtsdDQwNCIiKmpna5WTlYKChmRoZVRIYsOu0G5te5WPkW9x\
+		cWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8fMrLyrvAvbatwPz8+dfJ\
+		0ZOFmrCytNfT1szMzL6+vqGfoaOeosrQyIKAhf78/vr+/fv++eLc37apuMHD\
+		wuLi4s/Pz76/vq6vsL61voB9hPj7+p6Ho7CxsdnZ2aysrL+/v6urq2lnaubZ\
+		6vj8/Ozn8qusr8vLy83NzZqampKSkn9/f8PDwvz59/77+f/8+f38//j7+fj9\
+		+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb29v3/+/v////9+v36///7/Pr+/vz8\
+		+rCwsM7OzqampvHx8f/////+/f/+/MTExK6uruTk5Onp6cLCwt7e3gf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0IyH5BAEKAP8ALAAAAAASABIAAAj1AAEEEDCAQAED\
+		BxAcWJhAwQIGDSI6eAAhAoKLGDFKmBCRQoWEGUMisHAhIoaFCUGCvJgyQwMN\
+		GFOiXBhzA4cOMQ94+AAihAiVF0ewVEiihIkTKFKoQHlxBcuFLFq4eAEjhowZ\
+		K2kMRVnDxg0cOXTsWMlDocoePn4ACSJkCBGWRYzIRHAESRIlS5g0cfLkIpQo\
+		UqaspFLFyhUsWbRsWRixAZeVXbx8uQImjJgxCMg0LmOG5oEzaNKoWcOmjZs3\
+		jeHEkTOHTh07d/Dk0bOnAZ/GDfr4gfIHUCBBgwgVMtTgEKJEuJM3UJRmEaND\
+		h5Qrb+ToziPcAQEAOw==
+	}]
+	set bluebrainicon [image create photo ibrainblue -data {
+	    
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtu/97AAAq//T59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+LKawvf/9v77/f3+9/r88sK6yvX69Pr+/P39\
+		/vf597qxwvz9+9PB2Id9dkBEQScrJVtfWYOEhv789mRXcTo4OykmJY+NiI2K\
+		ioOBimdnYOfd5mtsdDQwNCIiKmpna5WTlYKChmRoZVRIYsOu0G5te5WPkW9x\
+		cWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8fMrLyrvAvbatwPz8+dfJ\
+		0ZOFmrCytNfT1szMzL6+vqGfoaOeosrQyIKAhf78/vr+/fv++eLc37apuMHD\
+		wuLi4s/Pz76/vq6vsL61voB9hPj7+p6Ho7CxsdnZ2aysrL+/v6urq2lnaubZ\
+		6vj8/Ozn8qusr8vLy83NzZqampKSkn9/f8PDwvz59/77+f/8+f38//j7+fj9\
+		+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb29v3/+/v////9+v36///7/Pr+/vz8\
+		+rCwsM7OzqampvHx8f/////+/f/+/MTExK6uruTk5Onp6cLCwt7e3gf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0Iwf0\
+		Iwf0Iwf0Iwf0Iwf0Iwf0IyH5BAEKAP8ALAAAAAASABIAAAj1AAEEEDCAQAED\
+		BxAcWJhAwQIGDSI6eAAhAoKLGDFKmBCRQoWEGUMisHAhIoaFCUGCvJgyQwMN\
+		GFOiXBhzA4cOMQ94+AAihAiVF0ewVEiihIkTKFKoQHlxBcuFLFq4eAEjhowZ\
+		K2kMRVnDxg0cOXTsWMlDocoePn4ACSJkCBGWRYzIRHAESRIlS5g0cfLkIpQo\
+		UqaspFLFyhUsWbRsWRixAZeVXbx8uQImjJgxCMg0LmOG5oEzaNKoWcOmjZs3\
+		jeHEkTOHTh07d/Dk0bOnAZ/GDfr4gfIHUCBBgwgVMtTgEKJEuJM3UJRmEaND\
+		h5Qrb+ToziPcAQEAOw==
+	}]
+	set lightbluebrainicon [image create photo ibrainlightblue -data {
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtuxj06QAq//T59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+LKawvf/9v77/f3+9/r88sK6yvX69Pr+/P39\
+		/vf597qxwvz9+9PB2Id9dkBEQScrJVtfWYOEhv789mRXcTo4OykmJY+NiI2K\
+		ioOBimdnYOfd5mtsdDQwNCIiKmpna5WTlYKChmRoZVRIYsOu0G5te5WPkW9x\
+		cWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8fMrLyrvAvbatwPz8+dfJ\
+		0ZOFmrCytNfT1szMzL6+vqGfoaOeosrQyIKAhf78/vr+/fv++eLc37apuMHD\
+		wuLi4s/Pz76/vq6vsL61voB9hPj7+p6Ho7CxsdnZ2aysrL+/v6urq2lnaubZ\
+		6vj8/Ozn8qusr8vLy83NzZqampKSkn9/f8PDwvz59/77+f/8+f38//j7+fj9\
+		+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb29v3/+/v////9+v36///7/Pr+/vz8\
+		+rCwsM7OzqampvHx8f/////+/f/+/MTExK6uruTk5Onp6cLCwt7e3v/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/yAP/y\
+		AP/yAP/yAP/yAP/yAP/yACH5BAEKAP8ALAAAAAASABIAAAj2AAEEEDCAQAED\
+		BxAcWJhAwQIGDSI6eAAhAoKLGDFKmBCRQoWEGTGCtHAhIoaFCUGmvJgyQwMN\
+		IhWiXChyA4cOIg94+AAihAiVF0ewVEiihIkTKFKoQHlxBcuFLFq4eAEjhowZ\
+		IBHQGIqyho0bOHLo2JGVh0yWPXz8ABJEyBAiLIsYSZnwCJIkSpYwaeLkyUUo\
+		UaRMyUqlipUrWLJo2bIwYgMuWbt4+XIFTBgxYxCQcVzGDM0DZ9CkUbOGTRs3\
+		bxzDiSNnDp06du7gyaNnTwM+jhv08QPlD6BAggYRKmSowSFEiXIrb6AozSJG\
+		hw4tX97I0Z1HuQMCADs=
+	    
+	}]
+	set rainbowbrainicon [image create photo ibrainrainbow -data {
+	    R0lGODlhEgASAOcAAP3+/f79//z//fz89/z7+/Ly8rWtu4wA//8IAPT59/z5\
+		+v77/vv+/v7+/vz+/P3+/vbz+LKawgB3//f/9v77/f3+9/r88sK6yvX69Pr+\
+		/AD/CP9lAP39/vf597qxwvz9+9PB2EBEQScrJVtfWYOEhv789jo4OykmJY+N\
+		iI2KioOBimdnYP/2AOfd5v/uADQwNCIiKmpna5WTlYKChmRoZVRIYsOu0P+M\
+		AG5te5WPkW9xcWVlZVRUVHp2fXxgktXO1oV1hXR5d3N0cHZ2dnx8fMrLyrvA\
+		vbatwBH/APz8+dfJ0ZOFmrCytNfT1szMzL6+vqGfoaOeosrQyIKAhf78/vr+\
+		/fv++eLc3/QfGLapuMHDwuLi4s/Pz76/vq6vsL61voB9hAAM//j7+p6Ho7Cx\
+		sdnZ2aysrL+/v6urq2lnagAq/+bZ6vj8/Ozn8qusr8vLy83NzZqampKSkn9/\
+		f8PDwvz59/77+f/8+f38//j7+fj9+Pz7+fj6+dHNz7y8vMnJyaOjo5iYmPb2\
+		9v3/+/v////9+v36///7/Pr+/vz8+rCwsM7OzqampvHx8f/////+/f/+/MTE\
+		xK6uruTk5Onp6cLCwt7e3hH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/ABH/\
+		ABH/ABH/ABH/ABH/ABH/ACH5BAEKAP8ALAAAAAASABIAAAj+AAEEEDCAQAED\
+		BxIeQJBAwQIGDSI6eAAhggSFCRFonEAhYgULEkKGVKhR4wUMETNo0CByZEaN\
+		GzZwaNBhJUuRJBHE3ODhAwibN0OIGEEC5s4SQFeaOIEihYoVOmOyaOGiqtUX\
+		MGLImEGjhlQWNqxWvXEDRw4dO3j08MGiLYsfVsneABJEyBAiRYwcQcI3iRIX\
+		cm8sYdLEyRMoUaRM4UulipUrZLFgyaJlC5cuXr6ACRMmYgMxNyRjGUOmDBcz\
+		Z9CkUbPGM5s2bUS7eQMnjpw5dOrY8XwHTx49e/j08fMHUCBBDQZ5bkCoEBVD\
+		hxAlUrSIUaMGjh5BWs69QSQ4kiYMOXLUvTulSn4sLQ8IADs=
+	    
+	}]
+	
+	#A person icon for "Subject" nodes
+	set personicon [image create photo ipersonicon -data {
+	    R0lGODlhEgASAKEAAAAAAP8AAP///wAAACH+FUNyZWF0ZWQgd2l0aCBUaGUg\
+		R0lNUAAsAAAAABIAEgAAAi6UL6CAjZqgeyzKmc6qmG9sSB8YWaS2nNS5AUHQ\
+		NpcLo+SljmyFd0/+YwVBuF4BADs=
+	}]
+
+
+	#Here are a couple arrows
+	#This one has a bend in it
+	set arrowicon2 [image create bitmap iarrow2 -data {          
+	    
+	    #define arrow2_width 16
+	    #define arrow2_height 16
+	    static unsigned char arrow2_bits[] = {
+		0x10, 0x00, 0x18, 0x00, 0xfc, 0x1f, 0xfe, 0x3f, 0xff, 0x3f, 0xfe, 0x3f,
+		0xfc, 0x3f, 0x18, 0x3e, 0x10, 0x3e, 0x00, 0x3e, 0x00, 0x3e, 0x80, 0xff,
+		0x00, 0x7f, 0x00, 0x3e, 0x00, 0x1c, 0x00, 0x08};
+	    
+	    
+    	}]
+	
+	#This one is diagonal
+	set arrowicon [image create bitmap iarrow -data { 
+
+	    #define arrow_width 17
+	    #define arrow_height 17
+	    static char arrow_bits[] = {
+		0x1f,0x00,0x00,0x0f,0x00,0x00,0xcf,0x07,0x00,0x3f,0x08,0x00,0x99,0x13,0x00,
+		0x68,0x24,0x00,0xe4,0x4b,0x00,0xd4,0x57,0x00,0xd4,0x57,0x00,0xd4,0x57,0x00,
+		0xa4,0x4f,0x00,0x48,0x2c,0x00,0x90,0x33,0x01,0x20,0xf8,0x01,0xc0,0xe7,0x01,
+		0x00,0xe0,0x01,0x00,0xf0,0x01,0x00,0x90,0x00,0x00,0x00,0x11,0x00,0x00,0x00,
+		0x48,0x79,0x15,0x08,0x98,0xd8,0x24,0x08 };
+	}]
+
+	#This one is in color and over a green brain
+	set arrowbrain [image create photo iarrowbrain -data {
+	    
+	    R0lGODlhEgASAMYAAAcP8v7+/huZFgf0I/T59/z5+v77/vv+/vf/9v77/cK6\
+		yvX69P39/rqxwvz9+0BEQScrJVtfWYOEhv789o+NiI2KioOBimdnYOfd5mts\
+		dJWTlYKChmRoZVRIYsOu0GVlZVRUVHp2fXxgktXO1oV1hXx8fMrLyrvAvbat\
+		wPz8+dfJ0ZOFmrCytKGfoaOeosrQyIKAhf78/vr+/fv++eLc37apuMHDwq6v\
+		sL61voB9hPj7+p6Ho7CxsdnZ2aurq2lnavj8/Ozn8qusr8vLy83NzcPDwv/8\
+		+f38//j7+fj9+Pz7+fj6+dHNz7y8vMnJyaOjo/v////9+v36///7/Pr+/vz8\
+		+rCwsM7OzqampvHx8cTExK6urunp6cLCwv//////////////////////////\
+		////////////////////////////////////////////////////////////\
+		/////////////////////////////////////////////////ywAAAAAEgAS\
+		AAAHvoAAgoMBAgMCiAQFBgcBAYOCA5KTkwgJjpCUmgMKC5iQhoeUhgIMjwAD\
+		g4iroYcNDqiSgw8QERKhoROSpIMUFRYXq5IYu4gZgxobHB2tHruHiIMfICEi\
+		rSPQuySDJSYnKLspKqSGKyyDLS4vMJIxMjM0rTU2gzc4OQKOjjqtOzw9g3z8\
+		SKUPSBBEh4QMITKoiCB9Ro4gSaJkCZMmTp5AAqAPSpQYUqZQqWLlCpYskPSp\
+		1KeFyJaNK1dy6bIRQCAAOw==
+	} ]
+	
+	set cactusicon [image create photo icactus -data { 
+
+	    R0lGODlhEQARAPcAMf///wR8HAR8JASELASENAyEPASERCSMJCSMLCyUHCSM
+	    NCyUNByMPBSMTByMTFykFFykHEScLFykJEScRDycXEScXDScZESkdFykPFys
+	    VEykbGysJHSsHIy0FHS0NIS0HHy0THy8hJS8FKTEDJTETJzETKTETKzEDKTM
+	    TLTMTJzEVKTMbKTMhKzMVLzMBLzMLMTUJPz89P9oLAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+	    AAAAAAAAAAAAAAAAAAAAACH5BAEAADIALAAAAAARABEAAAiWAGUIHEiwoEGB
+	    HhJiMHFw4AsKEgwYEKHgRUMZGBhENMBgQwSLDAm+iHAggkQDGwSYMCAgg0MZ
+	    BxSYlJhyJUqBKRpsSLBgpoEIAjZIBCFQhIEJPH2mbCBxoFGkPU8ubTrwaFKp
+	    Jy0iZLogKk0BHgy+YGDAK0oDDV8IMItBgFaDA2Se5CDg4lqlBt6KjPBgg4K/
+	    Hi8KHhgQADs=
+	    
+	}]
+
+
+
+
+
+	#------------------------------------------------------------------------------------------
+	# End of icon image definitions
+	#------------------------------------------------------------------------------------------
+		
+    };#End of the "create" procedure
+    
+    
+    # Initialize an element of the tree.
+    # Internal use only
+    #
+    proc dfltconfig {w v} {
+	variable Tree
+	set Tree($w:$v:children) {}
+	set Tree($w:$v:open) 0
+	set Tree($w:$v:icon) {}
+	set Tree($w:$v:tags) {}
+	set Tree($w:$v:linecolor) gray50
+    }
+    
+    #
+    # Pass configuration options to the tree widget
+    #
+    proc config {w args} {
+	eval $w config $args
+
+    }
+
+    #Configure a single node of the tree
+    proc nodeconfig {w v args} {
+	foreach {op arg} $args {
+	    switch -exact -- $op {
+		-linecolor {set Tree($w:$v:linecolor) $arg}
+		-image {set Tree($w:$v:icon) $arg}
+		-tags {set Tree($w:$v:tags) $arg}
+	    }
+	}
+    }
+    
+    proc itemexists {w v} {
+	
+	variable Tree
+	
+	if {[info exists Tree($w:$v:open)]} {
+	    return 1
+	} else {return 0}
+
+    }
+
+
+    proc gettreeobjects {w} {
+    	variable Tree
+    	foreach t [array names Tree $w:*] {
+    		lappend n $t
+    	}
+	return $n
+    }
+
+    #
+    # Insert a new element $v into the tree $w.
+    #
+    proc newitem {w v args} {
+	variable Tree
+	set dir [file dirname $v]
+	set n [file tail $v]
+	if {![info exists Tree($w:$dir:open)]} {
+	    error "parent item \"$dir\" is missing"
+	}
+	set i [lsearch -exact $Tree($w:$dir:children) $n]
+	if {$i>=0} {
+	    error "item \"$v\" already exists"
+	}
+	lappend Tree($w:$dir:children) $n
+	set Tree($w:$dir:children) [lsort $Tree($w:$dir:children)]
+	Tree::dfltconfig $w $v
+	foreach {op arg} $args {
+	    switch -exact -- $op {
+		-linecolor {set Tree($w:$v:linecolor) $arg}
+		-image {set Tree($w:$v:icon) $arg}
+		-tags {set Tree($w:$v:tags) $arg}
+	    }
+	}
+	Tree::buildwhenidle $w
+}
+
+#
+# Delete element $v from the tree $w.  If $v is /, then the widget is
+# deleted.
+#
+proc delitem {w v} {
+    variable Tree
+    if {![info exists Tree($w:$v:open)]} return
+    if {[string compare $v /]==0} {
+	# delete the whole widget
+	catch {destroy $w}
+	foreach t [array names Tree $w:*] {
+	    unset Tree($t)
+    }
+}
+foreach c $Tree($w:$v:children) {
+    catch {Tree::delitem $w $v/$c}
+}
+unset Tree($w:$v:open)
+unset Tree($w:$v:children)
+unset Tree($w:$v:icon)
+set dir [file dirname $v]
+set n [file tail $v]
+set i [lsearch -exact $Tree($w:$dir:children) $n]
+if {$i>=0} {
+    set Tree($w:$dir:children) [lreplace $Tree($w:$dir:children) $i $i]
+  }
+  Tree::buildwhenidle $w
+}
+
+#
+# Change the selection to the indicated item
+#
+proc setselection {w v} {
+    variable Tree
+    set Tree($w:selection) [list $v]
+    Tree::drawselection $w
+}
+
+proc setCurrent {w v} {
+    
+    variable Tree
+    set Tree($w:current) [ list $v ] 
+    Tree::drawCurrent $w 
+}
+
+proc addselection {w v} {
+    variable Tree
+    lappend Tree($w:selection) $v
+    set Tree($w:selection) [ linsert $Tree($w:selection) 0 $v ]
+    Tree::drawselection $w
+}
+
+
+#Accessor method for the name of the element currently selected
+proc getselection {w {option_list 0}} {
+    variable Tree
+    if {[llength $Tree($w:selection)]} {
+	foreach p $Tree($w:selection) {
+	    set q [string last / $p]
+	    if {$q == -1} {lappend result $p} else {
+		lappend result [string range $p [expr $q + 1] end]
+	    }	
+	}
+	if {$option_list == 0} {
+	    return [lindex $result 0]
+	}
+	return $result
+    }
+}
+
+
+#
+# Retrieve the current selection (with fully qualified path name)
+#
+proc getCurrentPath w {
+    variable Tree
+    if {[llength $Tree($w:current)]} {
+	return $Tree($w:current)
+    }
+}
+
+proc getselectionpath w {
+    variable Tree
+    if {[llength $Tree($w:selection)]} {
+	return $Tree($w:selection)
+    }
+}
+
+#
+# Bitmaps used to show which parts of the tree can be opened.
+#
+set maskdata "#define solid_width 9\n#define solid_height 9"
+append maskdata {
+    static unsigned char solid_bits[] = { 
+	0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01, 0xff, 0x01,
+	0xff, 0x01, 0xff, 0x01, 0xff, 0x01
+    };
+}
+set data "#define open_width 9\n#define open_height 9"
+append data {
+    static unsigned char open_bits[] = {
+	0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7d, 0x01, 0x01, 0x01,
+	0x01, 0x01, 0x01, 0x01, 0xff, 0x01
+    };
+}
+image create bitmap Tree::openbm -data $data -maskdata $maskdata \
+    -foreground black -background white
+set data "#define closed_width 9\n#define closed_height 9"
+append data {
+    static unsigned char closed_bits[] = {
+	0xff, 0x01, 0x01, 0x01, 0x11, 0x01, 0x11, 0x01, 0x7d, 0x01, 0x11, 0x01,
+	0x11, 0x01, 0x01, 0x01, 0xff, 0x01
+    };
+}
+image create bitmap Tree::closedbm -data $data -maskdata $maskdata \
+    -foreground black -background white
+
+# Internal use only.
+# Draw the tree on the canvas
+proc build w {
+    variable Tree
+    $w delete all
+    catch {unset Tree($w:buildpending)}
+    set Tree($w:y) 30
+    Tree::buildlayer $w / 20
+    $w config -scrollregion [$w bbox all]
+    Tree::drawselection $w
+}
+
+# Internal use only.
+# Build a single layer of the tree on the canvas.  Indent by $in pixels
+proc buildlayer {w v in} {
+    variable Tree
+    
+    incr in 5  
+    if {$v=="/"} {
+	set vx {}
+    } else {
+	set vx $v
+    }
+
+    set start [expr $Tree($w:y)-10]
+    foreach c $Tree($w:$v:children) {
+	set y $Tree($w:y)
+	incr Tree($w:y) 19
+	set li($y) [$w create line $in $y [expr $in+15] $y -fill $Tree($w:$vx/$c:linecolor) -width 3]
+	set icon $Tree($w:$vx/$c:icon)
+	set taglist x
+	foreach tag $Tree($w:$vx/$c:tags) {
+	    lappend taglist $tag
+	}
+	set x [expr $in+16]
+	if {[string length $icon]>0} {
+	    set k [$w create image $x $y -image $icon -anchor w -tags $taglist]
+	    incr x 20
+	    set Tree($w:tag:$k) $vx/$c
+	}
+	set j [$w create text $x $y -text $c -font $Tree(font) \
+		   -anchor w -tags $taglist]
+	set Tree($w:tag:$j) $vx/$c
+	set Tree($w:$vx/$c:tag) $j
+	if {[string length $Tree($w:$vx/$c:children)]} {
+	    if {$Tree($w:$vx/$c:open)} {
+		set j [$w create image $in $y -image Tree::openbm]
+		$w bind $j <1> "set {::Tree::Tree($w:$vx/$c:open)} 0; ::Tree::build $w"
+		Tree::buildlayer $w $vx/$c [expr $in+18]
+	    } else {
+		set j [$w create image $in $y -image Tree::closedbm]
+		$w bind $j <1> "set {::Tree::Tree($w:$vx/$c:open)} 1; ::Tree::build $w"
+	    }
+	}
+    }
+
+    set j [$w create line $in $start $in [expr $y+2] -fill gray50 -width 3]
+    $w lower $j
+    foreach index [array names li] {
+	$w lower $li($index) $j
+    }
+}
+
+# Open a branch of a tree
+#
+proc open {w v} {
+  variable Tree
+  if {[info exists Tree($w:$v:open)] && $Tree($w:$v:open)==0
+      && [info exists Tree($w:$v:children)]
+      && [string length $Tree($w:$v:children)]>0} {
+    set Tree($w:$v:open) 1
+    Tree::build $w
+  }
+}
+
+proc close {w v} {
+  variable Tree
+  if {[info exists Tree($w:$v:open)] && $Tree($w:$v:open)==1} {
+    set Tree($w:$v:open) 0
+    Tree::build $w
+  }
+}
+
+proc eraseCurrentBox w {
+    
+    variable Tree
+    
+    if {[llength $Tree($w:selidcurrent)] > 0} {
+	foreach x $Tree($w:selidcurrent) {
+	    $w delete $x
+	}
+    }
+    
+    #unset $Tree($w:selidcurrent)
+    #unset $Tree($w:current)
+}
+
+proc drawCurrent w {
+    
+    variable Tree
+    
+    if {[llength $Tree($w:selidcurrent)] > 0} {
+	foreach x $Tree($w:selidcurrent) {
+	   $w delete $x
+	}
+    }
+
+    foreach v $Tree($w:current) {
+	if {[string length $v]==0} return
+	if {![info exists Tree($w:$v:tag)]} return
+	set bbox [$w bbox $Tree($w:$v:tag)]
+	if {[llength $bbox]==4} {
+	    set i [eval $w create rectangle $bbox -outline black]
+	lappend Tree($w:selidcurrent) $i
+	    $w lower $i
+	} else {
+	    set Tree($w:selidcurrent) {}
+	}
+    }
+ }
+
+
+# Internal use only.
+# Draw the selection highlight
+proc drawselection w {
+    variable Tree
+
+    if {[llength $Tree($w:selidx)] > 0} {
+	foreach x $Tree($w:selidx) {
+	$w delete $x
+	}
+	
+    }
+    
+    foreach v $Tree($w:selection) {
+	if {[string length $v]==0} return
+	if {![info exists Tree($w:$v:tag)]} return
+	set bbox [$w bbox $Tree($w:$v:tag)]
+	if {[llength $bbox]==4} {
+	    set i [eval $w create rectangle $bbox -fill skyblue -outline {{}} ] 
+	    lappend Tree($w:selidx) $i
+	    $w lower $i
+	} else {
+	    set Tree($w:selidx) {}
+	}
+    }
+}
+
+
+
+
+# Internal use only
+# Call Tree::build then next time we're idle
+proc buildwhenidle w {
+  variable Tree
+  if {![info exists Tree($w:buildpending)]} {
+    set Tree($w:buildpending) 1
+    after idle "Tree::build $w"
+  }
+}
+
+#
+# Return the full pathname of the label for widget $w that is located
+# at real coordinates $x, $y
+#
+proc labelat {w x y} {
+  set x [$w canvasx $x]
+  set y [$w canvasy $y]
+  variable Tree
+  foreach m [$w find overlapping $x $y $x $y] {
+    if {[info exists Tree($w:tag:$m)]} {
+      return $Tree($w:tag:$m)
+    }
+  }
+  return ""
+}
+
+}
+########################################################################################
+#				End of Tree Widget Definition			       #
+########################################################################################
+########################################################################################
+########################################################################################
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/packages/chellyDB.tcl b/bioimagesuite30_src/bioimagesuite/datatree/packages/chellyDB.tcl
new file mode 100644
index 0000000..dc31372
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/packages/chellyDB.tcl
@@ -0,0 +1,1297 @@
+#!/bin/sh
+#Next line is a comment in Tcl, but not in bash \
+exec wish -f "$0" ${1+"@0"}
+#Now we have access to tk from within this script
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+wm withdraw .
+
+package provide chellyDB 1.0
+
+#---------------------------------------------------------------------------------------------
+#Import of required packages and other required initialization defs
+#---------------------------------------------------------------------------------------------
+lappend auto_path [file dirname [info script]]
+package require pxitclchellypackages 1.0
+
+
+# Require key packages
+# Xenios' C++ Extensions
+package require vtkpxcontrib     1.0
+
+# Simple Naming package
+package require Itcl
+package require Iwidgets
+
+package require struct;#This package includes the "struct::tree"
+
+#This is the metakit package -  may be used at some point
+#package require Mk4tcl;
+
+
+#------------------------------------------------------------------------------------------
+#Base Class defining the database
+#------------------------------------------------------------------------------------------
+::itcl::class chellyDBManager {
+
+    variable DataTree
+    variable MultiSubjData
+    variable msbDataArray
+    variable CSIPatientData
+    variable ElectrodeAttributeArray
+    public variable masterpath ""
+    public variable masterlist ""
+
+    public method SaveDatatree {} {}
+    public method LoadDatatree {} {}
+
+    constructor { } { 
+
+    }
+    
+    destructor {
+	catch {unset DataTree}
+    }
+
+
+}
+
+
+
+#------------------------------------------------------------------------------------------
+# Basic Save/Load file implementation of the DB
+#------------------------------------------------------------------------------------------
+
+
+::itcl::class chellyDBBasic {
+
+    inherit chellyDBManager
+
+    #These two methods overload the methods in the abstract class chellyDBManager
+    public method SaveDatatree { TreeArrayList {filename -1} }
+    public method LoadDatatree { {filename -1} }
+    public method LoadElectrodeAttributes { {filename -1} } 
+    public method LoadMSBfile { {filename -1} }
+    public method LoadCSIPatientFile { {filename -1} }
+
+    public method SaveFile {object}
+    public method LoadFile {imgobj filename desc}
+    public method LoadTransformationFile {transobj filename}
+    
+    public method GetImageFileName {}
+    public method GetSurfaceFileName {}
+    public method GetLandmarkFileName {}
+    public method GetElectrodeFileName {}
+
+    public method GetTransformationFileName {}    
+
+    public method SaveTypeDefs { TypeArrayList }
+    public method LoadTypeDefs { }
+
+    constructor { } {
+
+    }
+
+}
+
+##########################################################################################
+# These methods load and save whole trees
+##########################################################################################
+
+::itcl::body chellyDBBasic::SaveDatatree { TreeArrayList {filename -1} } {
+
+    #puts  [ file extension $filename ]
+   
+    if {$filename == -1} {
+	set typelist {
+	    {"Tree Definition File" {.tre}}
+	    {"All Files" {*}}
+	}
+	
+	set filename [tk_getSaveFile -filetypes $typelist]
+    }
+    
+    if {[llength $filename]} {
+
+	set ext [ file extension $filename ]
+	if { $ext != ".tre" } {
+	    set filename set "${filename}.tre"
+	    
+	}
+
+
+	array set tmparray $TreeArrayList
+	
+	set f [ open $filename w ]
+	puts $f "\#Chelly's Datatree File Format"
+	
+	set keylist [ array names tmparray ]
+	set keylist [lsort $keylist]
+	
+	for { set k 0 } { $k < [llength $keylist] } { incr k } {
+	    set key [lindex $keylist $k]
+	    set val $tmparray($key)
+	    set ext [ file extension $val ]
+	    if { $key != "serialized" } {
+		if { $ext != ".donotsave" } {
+		    puts $f "$key  : $val"
+		} else {
+		    puts $f "$key : "
+		}
+	    }
+	}
+	set key "serialized" 
+	puts $f "$key  : $tmparray($key)"
+	close $f
+    } else {return -1}
+
+}
+
+
+::itcl::body chellyDBBasic::LoadDatatree { {filename -1} } {
+
+    if { $filename == -1 } {
+	set typelist {
+	    {"Tree Definition File" {.tre}}
+	    {"All Files" {*}}
+	}
+	
+	set filename [tk_getOpenFile -filetypes $typelist]
+    }
+
+    if {[llength $filename]} {
+	set fileid [open $filename r]
+	
+	gets $fileid line
+	
+	if { [ string compare $line "#Chelly's Datatree File Format" ] != 0 } {
+	    puts stderr " File is not in Chelly's Datatree File Format "
+	    close $fileid
+	    return 0
+	}
+	
+	while { [ gets $fileid line ] >=0 } {
+	    set index [string first ":" $line]
+	    
+	    if { $index > 0 }  {
+		set len   [string length $line]
+		
+		set key   [string trim   [string range $line 0 [expr $index - 1]]]
+		set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		set newtree($key)  $value 
+		#puts stderr "New key = $key, value = \"$value\""
+	    }
+	}  
+	close $fileid
+	
+	#Throw a key into the array to tag its type
+	set newtree(ChellysTreeFormat) 1
+	set newtree(ThisFileName) $filename
+	set newlist [ array get newtree ]
+	return $newlist
+	
+    } else { return -1 }
+}
+
+::itcl::body chellyDBBasic::LoadElectrodeAttributes { { filename -1 } } {
+
+    catch {unset ElectrodeAttributeArray}
+
+    if {$filename == -1} {
+	set typelist {
+	    {"Electrode Attribute File" {.ele}}
+	    {"All Files" {*}}
+	}
+
+	set filename [tk_getOpenFile -filetypes $typelist]
+
+    } 
+    
+    if {[llength $filename]} {
+	set fileid [open $filename r]
+	
+	gets $fileid line
+	
+	if { [ string compare $line "#Electrode Attribute Description File" ] != 0 } {
+	    puts stderr " File is not in Electrode Attribute File Format "
+	    close $fileid
+	    return 0
+	}
+	
+	gets $fileid line
+	gets $fileid line
+	gets $fileid line
+	
+	set alltitles $line
+	set numtitles [llength $alltitles]
+
+	set titles [lrange $alltitles 2 end]
+	set ElectrodeAttributeArray(titles) $titles
+	
+	gets $fileid line
+
+	while { [ gets $fileid line ] >=0 } {
+	    #Read the line in:
+	    set istr $line
+		
+	    set gridletter [ string range [lindex $istr 1] 0 0 ]
+	    set electrodenumber [ string range [lindex $istr 1] 1 end ]
+	   
+	    for {set a 0} {$a < [expr $numtitles - 2 ]} {incr a} {
+		if {[llength $gridletter] > 0 && [llength $electrodenumber] > 0} {
+		    set ElectrodeAttributeArray($gridletter,$electrodenumber,$a) [lindex $istr [expr $a + 2] ]
+		}
+	    }
+	    
+	}
+
+	close $fileid
+	return [array get ElectrodeAttributeArray]
+
+    } else { return -1 }
+    
+}; #End LoadElectrodeAttributes method
+
+
+::itcl::body chellyDBBasic::LoadMSBfile { {filename -1} } {
+
+    if {$filename == -1} {
+	set typelist {
+	    {"Multisubject Description File" {.msb}}
+	    {"All Files" {*}}
+	}
+	
+	set filename [tk_getOpenFile -filetypes $typelist]
+    } 
+
+    if {[llength $filename]} {
+	set fileid [open $filename r]
+	
+	gets $fileid line
+
+	if { [ string compare $line "#Multisubject Description File v2" ] != 0 } {
+	    if { [ string compare $line "#Multisubject Description File v3"  ] != 0 } {
+		puts stderr " File is not in Multisubject fMRI Description File Format "
+		close $fileid
+		return 0
+	    } else {
+		set setupmode 2
+	    }
+	} else {
+	    set setupmode 1
+	}
+	
+
+	gets $fileid line 
+	if {$line == "Tasks"} {
+	    gets $fileid line 
+	    set numtasks $line
+	    if {$numtasks < 1} {error "There are no tasks in this file"; return -1}
+	}
+	set msbDataArray(numtasks) $numtasks
+
+	gets $fileid line;# skip a line
+
+	for {set i 0} {$i < $numtasks} {incr i} {
+	    gets $fileid line;     #Task Name 
+	    set index [string first ":" $line]
+	    set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	    lappend TaskNames $value
+	    gets $fileid line;     #Task Suffix 
+	    set index [string first ":" $line]
+	    set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	    lappend TaskSuffixes $value
+	    gets $fileid line;     # skip a line
+	}
+	set msbDataArray(tasknames) $TaskNames
+	set msbDataArray(tasksuffixes) $TaskSuffixes
+
+	puts stderr "TaskNames=$TaskNames, $TaskSuffixes"
+
+	gets $fileid line;         # Subjects 
+	if {$line == "Subjects"} {
+	    gets $fileid line 
+	    set numsubjects $line
+	    if {$numsubjects < 1} {error "There are no subjects in this file"; return -1}
+	}	
+	set msbDataArray(numsubjects) $numsubjects
+	
+	gets $fileid line;     # skip a line
+
+	#For each subject:
+	#------------------------------------------------------------------------------------------
+	for {set n 0} {$n < $numsubjects} {incr n} {
+
+	    if { $setupmode == 2 } {
+		gets $fileid line
+		set index [string first ":" $line]
+		set value2 [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+		regsub -all ":" $value2 " " value
+		if { [ string length $value ] > 0 } {
+		    set msbDataArray($n,Name) $value
+		} else {
+		    set msbDataArray($n,Name) [ format "Subject %02d" [expr $n+1 ] ]
+		}
+	    } else {
+		set msbDataArray($n,Name) [ format "Subject %02d" [expr $n+1 ] ]
+	    }
+	    puts stderr "Name=$msbDataArray($n,Name)"
+
+	    gets $fileid line;     # Anatomical Image
+	    set index [string first ":" $line]
+	    set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	    set msbDataArray($n,Anatomical) $value
+	    #--------------------------------------------------
+	    gets $fileid line;     # Conventional Image
+	    set index [string first ":" $line]
+	    set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	    set msbDataArray($n,Conventional) $value
+	    #--------------------------------------------------
+
+	    #----------------------------------------------------------##
+	    #----------------------------------------------------------##
+	    #Generation and reading of functional data file names
+	    gets $fileid line;     # Functional Image (use this to generate the rest)
+	    set index [string first ":" $line]
+	    set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+
+	    set basefilename $value
+	    set oldsuffix [lindex $TaskSuffixes 0]
+
+	    foreach TaskSuf $TaskSuffixes {
+		set ind [ string last $oldsuffix $basefilename ]
+		regsub -start $ind $oldsuffix $basefilename $TaskSuf f2
+		set msbDataArray($n,Task_$TaskSuf) $f2
+	    }
+	    #----------------------------------------------------------##
+	    #----------------------------------------------------------##
+	   
+	    #--------------------------------------------------
+	    gets $fileid line;     # Reference Transformation
+	    set index [string first ":" $line]
+	    set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	    set msbDataArray($n,ReferenceTrans) $value
+	    #----------------------------------------	    	    
+	    gets $fileid line;     # Internal Transformation
+	    set index [string first ":" $line]
+	    set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	    set msbDataArray($n,InternalTrans) $value
+	    #----------------------------------------	    	    
+	    gets $fileid line;     # Echoplanar Image
+	    set index [string first ":" $line]
+	    set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	    set msbDataArray($n,Echoplanar) $value
+	    #----------------------------------------	    	    
+	    gets $fileid line;     # Distortion Transformation
+	    set index [string first ":" $line]
+	    set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	    set msbDataArray($n,DistortionTrans) $value
+	    #----------------------------------------	    	    
+	    gets $fileid line;     # Fieldmap Image
+	    set index [string first ":" $line]
+	    set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	    set msbDataArray($n,FieldMap) $value
+	    #----------------------------------------	    	    
+	    gets $fileid line;     # skip a line
+
+	 #   puts stderr "Subject [ expr $n+1 ]: $msbDataArray($n,Name), $msbDataArray($n,Anatomical), $msbDataArray($n,Conventional)"
+
+	};# matches "for $numsubjects"
+	
+	#------------------------------------------------------------------------------------------
+	# Now read in the reference image stuff
+	#------------------------------------------------------------------------------------------
+	
+	gets $fileid line;     # skip a line
+	gets $fileid line;     # skip a line
+	#gets $fileid line;     # skip a line
+	#puts stderr "Last Skipped line = $line"
+
+	gets $fileid line;     # Reference Image
+	set index [string first ":" $line]
+	set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	set msbDataArray(ReferenceImage) $value
+	#	puts stderr "$index :$value, $msbDataArray(ReferenceImage)"
+
+	if { $setupmode == 2 } {
+	    gets $fileid line;     # VOI Image
+	}
+	
+	gets $fileid line;     # Average Anatomical
+	set index [string first ":" $line]
+	set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	set msbDataArray(AverageAnatomical) $value
+	
+	gets $fileid line;     # Std Anatomical
+	set index [string first ":" $line]
+	set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	set msbDataArray(StdAnatomical) $value
+	
+	foreach st {AverageFunctional StdFunctional ZscoreFunctional} {
+	
+	    #----------------------------------------------------------##
+	    #----------------------------------------------------------##
+	    #Generation and reading of functional data file names
+	    gets $fileid line;     # Base (Average Functional, Standard Functional, Z-score Functional)
+	    set index [string first ":" $line]
+	    set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	    
+	    set basefilename $value
+	    puts stderr "$value"
+	    set oldsuffix [lindex $TaskSuffixes 0]
+	    
+	    foreach TaskSuf $TaskSuffixes {
+		set ind [ string last $oldsuffix $basefilename ]
+		regsub -start $ind $oldsuffix $basefilename $TaskSuf f2
+		set msbDataArray($st,Task_$TaskSuf) $f2
+	    }
+	    #----------------------------------------------------------##
+	    #----------------------------------------------------------##
+	    
+	}
+	
+	close $fileid
+	
+# 	foreach {k} [lsort [array names msbDataArray]] {
+# 	    puts "$k   :   $msbDataArray($k)"
+#	}
+	
+
+	return [array get msbDataArray]
+
+    } else {return -1}
+    
+}
+
+
+##########################################################################################
+
+::itcl::body chellyDBBasic::LoadCSIPatientFile { {filename -1} } {
+
+    if {$filename == -1} {
+	set typelist {
+	    {"CSI Patient Description File" {.csi}}
+	    {"All Files" {*}}
+	}
+	
+	set filename [tk_getOpenFile -filetypes $typelist]
+    } 
+
+    if {[llength $filename]} {
+	set fileid [open $filename r]
+	
+	gets $fileid line
+
+	if { [ string compare $line "#CSI Subject Description File" ] != 0 } {
+	    puts stderr " File is not in CSI Patient Description File Format "
+	    close $fileid
+	    return 0
+	}
+
+	gets $fileid line 
+	gets $fileid line;# "Transformations" title
+	gets $fileid line 
+
+	gets $fileid line 
+	set index [string first ":" $line]
+	set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	set CSIPatientData(TransAnat2CSIConv) $value
+
+	gets $fileid line;# skip a line
+	gets $fileid line;# "Images" title
+	gets $fileid line;# skip a line
+
+	#----------------------------------------------------------------------
+	gets $fileid line 
+	set index [string first ":" $line]
+	set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	set CSIPatientData(Anatomical) $value
+	#----------------------------------------------------------------------
+	gets $fileid line 
+	set index [string first ":" $line]
+	set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	set CSIPatientData(Conventional) $value
+	#----------------------------------------------------------------------
+	gets $fileid line 
+	set index [string first ":" $line]
+	set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	set CSIPatientData(RawCSIImage) $value
+	#----------------------------------------------------------------------
+	gets $fileid line 
+	set index [string first ":" $line]
+	set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	set CSIPatientData(PMAPCSIImage) $value
+	#----------------------------------------------------------------------
+	gets $fileid line 
+	set index [string first ":" $line]
+	set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	set CSIPatientData(NormSmooth1) $value
+	#----------------------------------------------------------------------
+	gets $fileid line 
+	set index [string first ":" $line]
+	set value [string trim [string range $line [expr $index +1] [expr [string length $line] -1]]]
+	set CSIPatientData(NormSmooth2) $value
+	#----------------------------------------------------------------------
+
+	gets $fileid line;# skip a line
+	gets $fileid line;# "Extra Information" title
+	gets $fileid line;# skip a line
+
+
+
+
+
+	close $fileid
+	
+		foreach {k} [lsort [array names CSIPatientData]] {
+		    puts "$k   :   $CSIPatientData($k)"
+		}
+
+
+	return [array get CSIPatientData]
+
+    } else {return -1}
+
+}
+
+::itcl::body chellyDBBasic::SaveFile {objeect} {
+
+    #    set filename [tk_getSaveFile]
+    $object Save ""
+    return [$object cget -filename]
+    
+}
+
+::itcl::body chellyDBBasic::LoadFile {object filename desc} {
+    
+    set obj $object
+    set picknew "no"
+    
+    #If the filename has not been set, offer the option of setting it here.
+    if {$filename == -1} {
+	return -1
+#	set picknew [tk_messageBox -type yesno -default no  -message "No filename has been specified for this object.  Would you like to select one?" -icon question]
+    } else {
+	
+	#If the file exists, load it (this should be the normal case)
+	if {[file exists $filename]} {
+	    $obj Load $filename $desc
+	} else {
+	    #If the filename has been set, but the file doesn't exist, offer the option of resetting
+	    set picknew [tk_messageBox -type yesno -default no \
+			     -message "The file that this object points to does not appear to exist.  Would you like to specify a new one?" -icon question]
+	}
+	
+    }; #end if filename == -1
+    
+    
+    
+    #---------------------------------------------------------------------------------
+    #If picknew has been set to yes, choose a new file, and return it, else return 0
+    if {$picknew == "yes"} {
+	return 1	
+    } else { return 0 }
+    #---------------------------------------------------------------------------------
+    
+    
+    
+}; #end method LoadFile
+
+::itcl::body chellyDBBasic::LoadTransformationFile {transobj filename} {
+
+	if {$filename == -1} {
+	    $transobj Load "" Transformation
+	} else {  $transobj Load $filename Transformation }
+
+
+
+}
+
+::itcl::body chellyDBBasic::GetImageFileName { } {
+
+    set desc "Image"
+
+    set filename [info script]
+
+	set typelist {
+	    {"Analyze/NIFTI" {".hdr*" ".nii*" } }
+	    {"Analyze Files" {.hdr*}}
+	    {"Brain Voyager Files"  {.vtc}}
+	    {"All Files" {*}}}
+
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getOpenFile -title "Load $desc" -filetypes $typelist -initialfile $f2tail -initialdir $f2path ]
+    
+    if {[llength $fname]} {
+	return $fname
+    } else {return -1}
+}
+
+::itcl::body chellyDBBasic::GetSurfaceFileName { } {
+
+    set desc "Surface"
+
+    set filename [info script]
+
+	set typelist {
+	    {"Surface" {".vtk" } }
+	    {"All Files" {*}}}
+
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getOpenFile -title "Load $desc" -filetypes $typelist -initialfile $f2tail -initialdir $f2path ]
+    
+    if {[llength $fname]} {
+	return $fname
+    } else {return -1}
+}
+
+::itcl::body chellyDBBasic::GetLandmarkFileName { } {
+
+    set desc "Landmark"
+
+    set filename [info script]
+
+	set typelist {
+	    {"Landmark" {".land" } }
+	    {"All Files" {*}}}
+
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getOpenFile -title "Load $desc" -filetypes $typelist -initialfile $f2tail -initialdir $f2path ]
+    
+    if {[llength $fname]} {
+	return $fname
+    } else {return -1}
+}
+
+::itcl::body chellyDBBasic::GetElectrodeFileName { } {
+
+    set desc "Electrode"
+
+    set filename [info script]
+
+	set typelist {
+	    {"Electrode" {".mgrid" } }
+	    {"All Files" {*}}}
+
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getOpenFile -title "Load $desc" -filetypes $typelist -initialfile $f2tail -initialdir $f2path ]
+    
+    if {[llength $fname]} {
+	return $fname
+    } else {return -1}
+}
+
+
+
+
+
+::itcl::body chellyDBBasic::GetTransformationFileName { } {
+
+
+    set desc "Transformation"
+
+    set filename [info script]
+
+	set typelist {
+	    {"Matrix/Grid Files" {".matr" ".grd*" } }
+	    {"Matrix Files" {.matr}}
+	    {"Grid/Combo Transform Files"  {.grd*}}
+	    {"Thin Plate Spline Transforms" {.tps}}
+	    {"PolySimilarity Transforms" {.psim}}
+	    {"Old Matrix Files" {.mat}}
+	    {"All Files" {*}}}
+	
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set f [tk_getOpenFile -title "Load $desc" -initialfile $f2tail -filetypes $typelist -initialdir $f2path]
+
+    if {[llength $f]} {
+	return $f
+    } else { return -1 }
+
+}
+
+::itcl::body chellyDBBasic::SaveTypeDefs { TypeArrayList } {
+
+    set filename [tk_getSaveFile]
+
+    if {[llength $filename]} {
+	array set tmparray $TypeArrayList
+	
+	set f [ open $filename w ]
+	puts $f "\#Chelly's TypeList File Format"
+    
+	set keylist [ array names tmparray ]
+	
+	for { set k 0 } { $k < [llength $keylist] } { incr k } {
+	    set key [lindex $keylist $k]
+	    set val $tmparray($key)
+	    set ext [ file extension $val ]
+	    
+	    puts $f "$key  : $val"
+	    
+	}
+	
+	close $f
+
+    } else {return -1}
+}
+
+
+
+::itcl::body chellyDBBasic::LoadTypeDefs { } {
+
+    set typelist {
+	{"All Files" {*}}
+    }
+    set filename [tk_getOpenFile -filetypes $typelist]
+
+    if {[llength $filename]} {
+	
+	set fileid [open $filename r]
+	
+	gets $fileid line
+	
+	if { [ string compare $line "#Chelly's TypeList File Format" ] != 0 } {
+	    
+	    puts stderr " File is not in Chelly's TypeList File Format "
+	    close $fileid
+	    return 0
+	}
+	
+	
+	#    set OutTreeList [read $f]
+	
+	while { [ gets $fileid line ] >=0 } {
+	    set index [string first ":" $line]
+	    
+	    if { $index > 0 }  {
+		set len   [string length $line]
+		
+		set key   [string trim   [string range $line 0 [expr $index - 1]]]
+		set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		set newdefarray($key)  $value 
+		#puts stderr "New key = $key, value = \"$value\""
+	    }
+	}  
+	close $fileid
+	
+	set newlist [ array get newdefarray ]
+	return $newlist 
+    } else { return -1 }
+
+}
+
+#------------------------------------------------------------------------------------------
+#-----This class extends the Basic Class, and simply uses relative path names -------------
+#-----for all saving and loading operations.  This allows for portability of --------------
+#-----of the trees, and the potential to move all data contained within a tree-------------
+#-----efficiently--------------------------------------------------------------------------
+#------------------------------------------------------------------------------------------
+#------------------------------------------------------------------------------------------
+
+
+::itcl::class chellyDBRelative {
+
+    inherit chellyDBBasic
+
+    #These two methods overload the methods in chellyDBBasic
+    public method SaveDatatree { TreeArrayList {filename -1} }
+    public method SaveDataTreeClean { TreeArrayList } 
+    public method SaveDataTreeFilesReorg { TreeArrayList }
+    public method LoadDatatree { {filename -1} }
+
+    constructor { } { 
+
+    }
+
+}
+
+
+::itcl::body chellyDBRelative::SaveDatatree { TreeArrayList {filename -1} } {
+
+    if {$filename == -1} {
+	set typelist {
+	    {"Tree Definition File" {.tre}}
+	    {"All Files" {*}}
+	}
+
+	set filename [tk_getSaveFile -filetypes $typelist]
+    }
+
+    if { [ string length $filename ] < 1 } {
+	return -1
+    }
+
+    if { [ file extension $filename ] != ".tre" } {
+	set filename "${filename}.tre"
+    }
+
+    set treepath [file dirname $filename]
+    
+
+    array set tmparray $TreeArrayList
+    
+    set f [ open $filename w ]
+    puts $f "\#Chelly's Datatree File Format"
+    
+    set keylist [ array names tmparray ]
+    set keylist [lsort $keylist]
+    
+    for { set k 0 } { $k < [llength $keylist] } { incr k } {
+	
+	#Look at each member of the array in order, and evaluate them for saving
+	
+	set key [lindex $keylist $k]
+	
+	#If the key is "filename" we have to trim it in order to support portability
+	if {[string match -nocase {*filename} $key]} {
+	    
+	    set valmodified 0
+	    for {set b 0} {$b < [string length $tmparray($key)]} {incr b} {
+		if {[string match -nocase $treepath [string range $tmparray($key) 0 $b]]} {
+		    set valmodified 1
+		    set val [string range $tmparray($key) [expr $b + 2] end]
+		    
+		}
+	    } 
+	    if {!$valmodified} {
+		set val $tmparray($key)
+	    }
+	    
+	} else {
+	    set val $tmparray($key)
+	}
+	set ext [ file extension $val ]
+	if { $key != "serialized" } {
+	    if { $ext != ".donotsave" } {
+		puts $f "$key : $val"
+	    } else {
+		puts $f "$key :  "
+	    }
+	}
+    }
+    set key "serialized" 
+    puts $f "$key : $tmparray($key)"
+    close $f
+    return 1
+
+};# End SaveDataTree
+
+::itcl::body chellyDBRelative::SaveDataTreeClean { TreeArrayList } {
+
+#This method is obsolete by the SaveDataTreeFilesReorg method
+#It never gets called from the main program
+
+    set typelist {
+	{"Tree Definition File" {.tre}}
+	{"All Files" {*}}
+    }
+
+    set filename [tk_getSaveFile -filetypes $typelist]
+    set treepath [file dirname $filename]
+
+    if {[llength $filename]} {
+	
+	if { [ file extension $filename ] != ".tre" } {
+	    set filename "${filename}.tre"
+	}
+	
+	array set tmparray $TreeArrayList
+	
+	set f [ open $filename w ]
+	puts $f "\#Chelly's Datatree File Format"
+	
+	set keylist [ array names tmparray ]
+	set keylist [lsort $keylist]
+	
+	for { set k 0 } { $k < [llength $keylist] } { incr k } {
+
+	    #Look at each member of the array in order, and evaluate them for saving
+
+	    set key [lindex $keylist $k]
+
+	    #-------------------------------------------------------------------------------------------
+	    #If the key is "filename" we have to trim it in order to support portability,
+	    #as well as save the filenames in a separate  array for later use in the new folder location
+	    #-------------------------------------------------------------------------------------------
+	    if {[string match -nocase {*filename} $key]} {
+		
+		set val $tmparray($key)
+	
+		set ext [ file extension $val ]
+		if { $ext != ".donotsave" } {
+		    if { $val != -1 } {
+			
+			set valFileNames($key) [file tail $val]
+			set valDirNames($key) [file dirname $val]
+			set valFolderLists($key) [file split $valDirNames($key)]
+			
+			#--Debug----------------------------------------
+#			puts "$key  :  $valFolderLists($key)"
+			#-----------------------------------------------
+			
+		    }
+		}
+		#End of file name stuff
+			
+	    } else {
+		#This is for all other keys (that do not include the string "filename")
+		set val $tmparray($key)
+	    }
+	    
+	    set ext [ file extension $val ]
+	    if { $key != "serialized" } {
+		if { $ext != ".donotsave" } {
+		    set SavingArray($key) "$key : $val"
+		} else {
+		    set SavingArray($key)  "$key : "
+		}
+	    }
+	}
+	
+	
+	#-----------------------------------------------------------------------------
+	#Trim the filenames 
+	#-----------------------------------------------------------------------------
+	
+	foreach r [array names valFolderLists] {
+	    lappend listOfDirLists $valFolderLists($r)
+	}
+	set longest 0
+	foreach l $listOfDirLists {
+	    if {[llength $l] > $longest} {
+		set longest [llength $l]
+	    }
+	}
+	for {set i 0} {$i < $longest} {incr i} {
+	    set remove($i) 1
+	    for {set j 0} {$j < [llength $listOfDirLists]} {incr j} {
+		if {[lindex [lindex $listOfDirLists $j] $i] != [lindex [lindex $listOfDirLists 0] $i]} {
+		    set remove($i) 0
+		    for {set pt $i} {$pt < $longest} {incr pt} {set remove($pt) 0}
+		}		
+	    }
+	}
+	
+	set commonEnd 0
+	set done 0
+	while {$done == 0 } {
+	    if {$commonEnd < $longest} {
+		if {$remove($commonEnd) == 1} {
+		    incr commonEnd
+		} else {set done 1}
+	    } else {set done 1}
+	}
+
+
+	
+	#-----------------------------------------------------------------------------------------------
+	#
+	# If you comment this out, then no containing directory will be created, and the files will be
+	# copied directly into the directory that holds the tree
+	#
+	#-----------------------------------------------------------------------------------------------
+	set commonEnd [expr $commonEnd - 1]
+	#-----------------------------------------------------------------------------------------------
+
+
+	#Construct Full path
+	for {set v 0} {$v < [llength [array names valFolderLists]]} {incr v} {
+	    set ind [lindex [lsort [array names valFolderLists]] $v]
+	    set endofpath [lrange $valFolderLists($ind) $commonEnd end ]
+
+	    set pathEnd ""
+	    for {set g 0 } {$g < [llength $endofpath]} {incr g} {
+		set pathEnd [file join $pathEnd [lindex $endofpath $g]]
+	    }
+
+	    lappend dirstomake [file join $treepath $pathEnd]
+	    set newfilename($ind) [file join $treepath $pathEnd $valFileNames($ind)]
+
+	}
+
+	#------------------------------------------------------------------------------------------
+	# Make directories, and copy the file to its new location
+	foreach direktory $dirstomake {
+	    file mkdir $direktory
+	}
+	for {set w 0} {$w < [llength [array names newfilename]]} {incr w} {
+	    set TheKey [lindex [lsort [array names valFolderLists]] $w]
+	    puts stderr "$TheKey, $tmparray($TheKey)"
+	    if {[string match -nocase {*trans*filename} $TheKey]} {
+		#Create and Save a temporary transformation object
+		set newobj [ [pxitcltransform \#auto ] GetThisPointer  ]
+	    } else {
+		set ext  [ file extension $newfilename($TheKey) ]
+		if { $ext == ".mgrid" } {
+		    set newobj [ [ pxitclelectrodemultigrid \#auto] GetThisPointer ]
+		} elseif { $ext == ".land" } {
+		    set newobj [ [ pxitcllandmarks \#auto] GetThisPointer ]
+		} elseif { $ext == ".vtk" } {
+		    set newobj [ [ pxitclsurface \#auto] GetThisPointer ]
+		} else {
+		    set newobj [ [ pxitclimage \#auto] GetThisPointer ]
+		}
+	    }
+	    $newobj Load $tmparray($TheKey) 
+	    $newobj Save $newfilename($TheKey)
+	    ::itcl::delete object $newobj
+	}
+
+	#----------------------------------------------------------------------
+	# Now trim each newly saved filename to support relative pathname saving in the tree
+	#----------------------------------------------------------------------
+	for {set w 0} {$w < [llength [array names newfilename]]} {incr w} {
+	    set TheKey [lindex [lsort [array names valFolderLists]] $w]
+	    set valmodified 0
+	    for {set b 0} {$b < [string length $newfilename($TheKey)]} {incr b} {
+		if {[string match -nocase $treepath [string range $newfilename($TheKey) 0 $b]]} {
+		    set valmodified 1
+		    set Thisval [string range $newfilename($TheKey) [expr $b + 2] end]
+		    
+		}
+	    } 
+	    if {!$valmodified} {
+		set Thisval $newfilename($TheKey)
+	    }
+
+	    set ext [ file extension $Thisval ]
+	    if { $TheKey != "serialized" } {
+		if { $ext != ".donotsave" } {
+		    set SavingArray($TheKey) "$TheKey : $Thisval"
+		} else {
+		    set SavingArray($TheKey) "$TheKey : "
+		}
+	    }
+	    
+	}
+
+	
+
+	#----------------------------------------------------------------------
+	#Write the results to the file
+	#----------------------------------------------------------------------
+	foreach name [lsort [array names SavingArray]] {
+	    
+	    puts $f $SavingArray($name)
+	    
+	}
+	
+	set key "serialized" 
+	puts $f "$key  : $tmparray($key)"
+	close $f
+	
+	return [LoadDatatree $filename]
+	
+    } else {return -1}
+    
+}; #End SaveDataTreeClean method
+
+
+
+::itcl::body chellyDBRelative::SaveDataTreeFilesReorg { TreeArrayList } {
+
+    set typelist {
+	{"Tree Definition File" {.tre}}
+	{"All Files" {*}}
+    }
+
+    set filename [tk_getSaveFile -filetypes $typelist]
+    set treepath [file dirname $filename]
+
+
+    if {[llength $filename]} {
+
+	if { [ file extension $filename ] != ".tre" } {
+	    set filename "${filename}.tre"
+	}
+
+	#Add a key to every node in the this temporary tree that will contain a list of its parent folders
+	array set tmparray $TreeArrayList
+	set tempTree [	::struct::tree [pxvtable::vnewobj] deserialize $tmparray(serialized)]
+	foreach child [$tempTree children -all [$tempTree rootname]] {
+	    $tempTree set $child ffList ""
+	}
+
+	#Walk the tree in a breadth-first manner
+	$tempTree walk [$tempTree rootname] -type bfs node {
+	    if {$node != [$tempTree rootname]} {
+		
+		set par [$tempTree parent $node]
+
+		if {$par != [$tempTree rootname]} {
+		    set newffList [$tempTree get $par ffList]
+		    if {[$tempTree get $par type] == "Folder" | [$tempTree get $par type] == "Patient"} {
+			lappend newffList [string map {" " _} [$tempTree get $par title]]
+		    }
+		    $tempTree set $node ffList $newffList
+
+		};#End if $par != root
+
+		set newfilepath $treepath
+		for {set r 0} {$r < [llength [$tempTree get $node ffList]]} {incr r} {
+		    set newfilepath [file join $newfilepath [lindex [$tempTree get $node ffList] $r] ]	
+		}	
+
+		#Create a directory (this does not overwrite old directories, and intermediates are created if needed
+		file mkdir $newfilepath
+
+		foreach key [$tempTree keys $node] {
+		    if { [string match -nocase {*filename} $key] } {
+			if {[$tempTree get $node $key] != -1 && [file extension [$tempTree get $node $key]] != ".donotsave"} {
+			    set NewFilename [ file join $newfilepath [file tail [$tempTree get $node $key]]]
+			    #If it's a transformation, create a new trans object, and save it in the new place
+			    #			    puts stderr "$NewFilename, $key"
+			    if { [string match -nocase {*trans*filename} $key] } {
+				set newtemptr [ [pxitcltransform \#auto ] GetThisPointer  ]
+				$newtemptr Load [$tempTree get $node $key]
+				$newtemptr Save $NewFilename
+				::itcl::delete object $newtemptr
+			    } else {
+				#Otherwise, assume it's an image
+				set ext  [ file extension $NewFilename ]
+				if { $ext == ".mgrid" } {
+				    set newtempimg [ [ pxitclelectrodemultigrid \#auto] GetThisPointer ]
+				} elseif { $ext == ".land" } {
+				    set newtempimg [ [ pxitcllandmarks \#auto] GetThisPointer ]
+				} elseif { $ext == ".vtk" } {
+				    set newtempimg [ [ pxitclsurface \#auto] GetThisPointer ]
+				} else {
+				    set newtempimg [ [ pxitclimage \#auto] GetThisPointer ]
+				}
+				
+				$newtempimg Load [$tempTree get $node $key]
+				$newtempimg Save $NewFilename
+				::itcl::delete object $newtempimg
+			    }
+			    #set the key properly in the tree, and tmparray
+			    $tempTree set $node $key $NewFilename
+
+			    set alllowers [string tolower $key];#A lower-case key title
+			    set tmparray($node,$alllowers) $NewFilename
+			}
+		    }
+		}
+		
+	    };#End if $node != root
+	};#End walk
+
+	#Now unset all those temporary ffList keys in the tree
+	foreach child [$tempTree children -all [$tempTree rootname]] {
+	    $tempTree unset $child ffList
+	}
+
+
+	chellyDBRelative::SaveDatatree [array get tmparray] $filename 
+	return [LoadDatatree $filename]
+	
+    } else {return -1}
+    
+}; #End SaveDataTreeFilesReorg method		
+
+
+::itcl::body chellyDBRelative::LoadDatatree { {filename -1} } {
+
+    if {$filename == -1} {
+	set typelist {
+	    {"Tree Definition File" {.tre}}
+	    {"All Files" {*}}
+	}
+	set filename [tk_getOpenFile -filetypes $typelist]
+    }
+
+    if {[llength $filename]} {
+	set treepath [file dirname $filename]
+
+	set fileid [ open $filename r ]
+	gets $fileid line
+	
+	if { [ string compare $line "#Chelly's Datatree File Format" ] != 0 } {
+	    puts stderr " File is not in Chelly's Datatree File Format "
+	    close $fileid
+	    return 0
+	}
+	
+	
+	#    set OutTreeList [read $f]
+	
+	while { [ gets $fileid line ] >=0 } {
+	    set index [string first ":" $line]
+	    
+	    if { $index > 0 }  {
+		set len   [string length $line]
+		set key   [string trim   [string range $line 0 [expr $index - 1]]]
+
+		if {[string match -nocase {*filename} $key]} {
+
+		    set tempvalue [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		    if {$tempvalue != -1} {
+			set value [file join $treepath $tempvalue]
+		    } else {
+			set value $tempvalue
+		    }
+
+		} else {
+		    set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		}
+
+		if { [ llength $masterlist ] > 0 } {
+		    
+		    # Detect and change
+		    set newindex [string first "filename" $key]
+		    if { $newindex >= 0 } {
+			set fname [ file tail $value ]
+			set tt [ lsearch $masterlist $fname ]
+			if { $tt >= 0 } {
+			    set newfname [ file join $masterpath $fname ]
+			    pxtkprint "DataTree: Found $fname, $value replacing with $newfname\n"
+			    set value $newfname
+			}
+		    }
+		}
+
+		set newtree($key)  $value 
+		#puts stderr "New key = \"$key\" \t\t value = \"$value\""
+	    }
+	}  
+	close $fileid
+
+	#Throw a couple keys into the array to tag its type, filename, etc.
+	set newtree(ChellysTreeFormat) 1
+	set newtree(ThisFileName) $filename
+	set newlist [ array get newtree ]
+	return $newlist 
+
+    } else { return -1 }
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/packages/mdImageUtils.tcl b/bioimagesuite30_src/bioimagesuite/datatree/packages/mdImageUtils.tcl
new file mode 100644
index 0000000..b5535d3
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/packages/mdImageUtils.tcl
@@ -0,0 +1,689 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec wish "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#Now we have access to tk from within this script
+
+package provide mdImageUtils 1.0
+
+#Add to the auto path the bioimagesuite dirs base and main
+lappend auto_path [file dir [info script]]
+package require pxitclchellypackages
+
+# Require key packages
+package require Itcl
+package require Iwidgets
+
+# C++ Extensions
+package require vtkpxcontrib     1.2
+package require vtknrcontrib 1.2
+
+# Simple Naming package  [ pxvtable::vnewobj ]
+package require pxvtable         1.0
+
+# Call us ::mdImageUtil::SmoothImage { }
+
+#set util [vtkClusterSignificance [pxvtable::vnewobj ] ]
+#puts stderr "Util Created"
+#$util Delete
+
+namespace eval ::mdImageUtil { 
+
+
+    # ------------------------------------------------------------------------
+    #   Convert vtkImageData to pxitclimage using ref (pxitclimage) and prefix
+    # ------------------------------------------------------------------------
+
+    proc ProcessResultingImage { img ref prefix } {
+	
+	set thisnewobj  [ [ pxitclimage \#auto] GetThisPointer ]
+	$thisnewobj CopyImageHeader [ $ref GetImageHeader ]
+	$thisnewobj ShallowCopyImage $img
+	
+#	puts [ $ref cget -filename  ] 
+	set dname [ file dirname [ $ref cget -filename  ] ]
+	set tname [ file tail    [ $ref cget -filename  ] ]
+	set newname [ file join $dname $prefix ]
+	set newname "${newname}_${tname}"
+
+	#make sure the filename is unique, so it doesn't overwrite anything
+	set sufnum 1
+	while {[file exists $newname]} {
+	    set newroot [string trimright [file rootname $newname] ${sufnum}]
+	    set newext [file extension $newname]
+	    set newname "${newroot}${sufnum}${newext}"
+	    incr sufnum
+	}
+
+	$thisnewobj configure -filename $newname
+	return $thisnewobj
+    }
+
+    
+    # --------------------------------------------------------------------
+
+ 
+    # --------------------------------------------------------------------
+    # Threshold image works with percentile values in the image
+    # lower and upper are values 0.1..1.01 
+    #    
+
+    proc ThresholdImage { currentimage { lower 0.01 } { upper 1.01 } } {
+
+	set range [ [ [ [ $currentimage GetImage ] GetPointData ] GetScalars ] GetRange ]
+	set lv    [ lindex $range 0 ]
+	set up    [ lindex $range 1 ]
+
+	set thr1 [ expr $lv + $lower*($up-$lv) ]
+	set thr2 [ expr $lv + $upper*($up-$lv) ]
+
+	puts stderr "Input Range = $range .. input thresholds $lower, $upper, output = $thr1, $thr2"
+
+	set thresholdF  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+	$thresholdF ThresholdBetween  $thr1 $thr2 
+	$thresholdF SetInValue    1
+	$thresholdF SetOutValue   0
+	$thresholdF ReplaceInOn
+	$thresholdF ReplaceOutOn
+	$thresholdF SetInput [ $currentimage GetImage ]
+	$thresholdF SetOutputScalarTypeToFloat
+	$thresholdF Update
+
+	set results [ ::mdImageUtil::ProcessResultingImage [ $thresholdF GetOutput ] $currentimage "Thr" ] 	
+	$thresholdF Delete
+	return $results
+    }
+
+    proc threshold { image lowThr highThr } {
+
+	set thresholdF  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+	$thresholdF ThresholdBetween  $lowThr $highThr 
+	$thresholdF SetInValue    1
+	$thresholdF SetOutValue   0
+	$thresholdF ReplaceInOn
+	$thresholdF ReplaceOutOn
+	$thresholdF SetInput [ $image GetImage ]
+	$thresholdF SetOutputScalarTypeToFloat
+	$thresholdF Update
+
+	set results [ ::mdImageUtil::ProcessResultingImage [ $thresholdF GetOutput ] $image "Thr" ] 	
+	$thresholdF Delete
+	return $results
+    }
+
+
+    proc Erode { currentimage { kernelsize 3 }  } {
+    
+	set erode  [  vtkImageContinuousErode3D [ pxvtable::vnewobj ] ]
+	$erode SetInput [ $currentimage GetImage ]
+	$erode SetKernelSize $kernelsize $kernelsize $kernelsize
+	$erode Update
+	
+	set results [ ::mdImageUtil::ProcessResultingImage [ $erode GetOutput ] $currentimage "Erod" ] 	
+	$erode Delete
+	return $results
+    }
+
+
+
+    proc SmoothImage { currentimage smoothingsigma } {
+
+	set spa [ [ $currentimage GetImage ] GetSpacing ]
+	
+	for { set i 0 } { $i <= 2 } { incr i } {
+	    set sigma($i) [ expr $smoothingsigma / [ lindex $spa $i ]]             
+	}
+
+	set smooth  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+	$smooth SetStandardDeviations $sigma(0) $sigma(1) $sigma(2)
+	$smooth SetRadiusFactors [ expr round(6*$sigma(0)) ] [ expr round(6*$sigma(1)) ] [ expr round(6*$sigma(2)) ]
+    	$smooth SetInput [ $currentimage GetImage ]
+	$smooth Update
+
+	set results [ ::mdImageUtil::ProcessResultingImage [ $smooth GetOutput ] $currentimage "Smooth" ] 	
+	$smooth Delete
+	return $results
+    }
+
+    # ------------------------------------------------------------------------------
+
+    #    (in+shift)*scale
+
+    proc ShiftScale { currentimage shift scale } {
+
+	set scale  [ vtkImageShiftScale [ pxvtable::vnewobj ]  ]
+    	$scale SetInput [ $currentimage GetImage ]
+	$scale SetShift $shift
+	$scale SetScale $scale
+	$scale SetOutputScalarToFloat
+	$scale Update
+
+	set results [ ::mdImageUtil::ProcessResultingImage [ $scale GetOutput ] $currentimage "ShSc" ] 	
+	$scale Delete
+	return $results
+    }
+
+    # -----------------------------------------------------------------------------------------------------
+    proc PropScale { image } {
+	
+	set highThreshold 10000
+	set lowThreshold 40 
+	set scale  [ vtkdsSpectUtil [ pxvtable::vnewobj ]  ]
+	set mean [ $scale imageMean [ $image GetImage ] -1 ] 
+	set mean [ $scale imageMean [ $image GetImage ] [ expr $mean/8 ] ]
+	set results [ ::mdImageUtil::MultiplyByConstant $image [ expr 50.0/$mean ] ]	
+	puts [ expr 50.0/$mean ]
+	set mask [ ::mdImageUtil::threshold  $results $lowThreshold $highThreshold  ] 
+	set results [ ::mdImageUtil::Multiply $results $mask ]
+	$scale Delete
+	set returnList [ list $mask $results ]
+	return $returnList
+    }
+
+    proc Normalize { currentimage pxitclimgRef { threshold 0.05 } } {
+    
+	if {  [ $currentimage GetImageSize ]  ==  [ $pxitclimgRef GetImageSize ] } {
+
+	    set diff [ vtkpxImageComputeNormalizedDifference [ pxvtable::vnewobj ]]
+	    $diff SetInput  [ $pxitclimgRef GetImage ]
+	    $diff SetInput2 [ $currentimage GetImage ]
+	    $diff SetThreshold 0.2
+	    $diff SetSigma     1.0
+	    $diff SetPercentageThreshold $threshold
+	    $diff Update
+
+	    set results [ ::mdImageUtil::ProcessResultingImage [ $diff GetNormalizedSecondImage ] $currentimage "Normalized" ]
+	    $diff Delete
+
+	    return $results
+	}
+	puts stderr "Error Bad Dimensions!"
+	return -1
+    }
+
+
+    # Feed in the ictal and the interictal unnormalized
+    # -------------------------------------------------
+    # (currentimage-pxitclimgRef)
+
+    proc NormalizeDifference { currentimage pxitclimgRef { threshold 0.05} } {
+    
+	if {  [ $currentimage GetImageSize ]  ==  [ $pxitclimgRef GetImageSize ] } {
+
+	    set diff [ vtkpxImageComputeNormalizedDifference [ pxvtable::vnewobj ]]
+	    $diff SetInput  [ $pxitclimgRef GetImage ]
+	    $diff SetInput2 [ $currentimage GetImage ]
+	    $diff SetThreshold 0.2
+	    $diff SetSigma     1.0
+	    $diff SetPercentageThreshold $threshold
+	    $diff Update
+
+	    set results1 [ ::mdImageUtil::ProcessResultingImage [ $diff GetOutput ] $currentimage "NormDiff" ]
+	    set results2 [ ::mdImageUtil::ProcessResultingImage [ $diff GetPercentageOutput ] $currentimage "PercDiff" ]
+	    $diff Delete
+
+	    return [ list $results1 $results2 ]
+	}
+	puts stderr "Error Bad Dimensions!"
+	return -1
+    }
+
+
+    # ------------------------------------------------------------------------------
+
+    proc Add { image1 image2 } {
+
+	if {  [ $image1 GetImageSize ]  !=  [ $image2 GetImageSize ] } {
+	    puts stderr "Error Bad Dimensions!"
+	    return -1
+	}
+	    
+	set cast1 [ vtkImageCast [ pxvtable::vnewobj ]]
+	$cast1 SetInput  [ $image1 GetImage ]
+	$cast1 SetOutputScalarTypeToFloat
+	$cast1 Update
+    
+	set cast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+	$cast2 SetInput [ $image2 GetImage ]
+	$cast2 SetOutputScalarTypeToFloat
+	$cast2 Update
+	
+	set diff [ vtkImageMathematics [ pxvtable::vnewobj ]]
+	$diff SetInput1  [ $cast1 GetOutput ]
+	$diff SetInput2 [ $cast2 GetOutput ]
+	$diff SetOperationToAdd
+	$diff Update
+
+	set results [ ::mdImageUtil::ProcessResultingImage [ $diff GetOutput ] $image1 "Sum" ]
+	$diff Delete
+	$cast2 Delete
+	$cast1 Delete
+
+	return $results
+    }
+
+    # -------------------------------------------------------------------------------------
+
+    proc Multiply { image1 image2 } {
+
+	if {  [ $image1 GetImageSize ]  !=  [ $image2 GetImageSize ] } {
+	    puts stderr "Error Bad Dimensions!"
+	    return -1
+	}
+	    
+	set cast1 [ vtkImageCast [ pxvtable::vnewobj ]]
+	$cast1 SetInput  [ $image1 GetImage ]
+	$cast1 SetOutputScalarTypeToFloat
+	$cast1 Update
+    
+	set cast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+	$cast2 SetInput [ $image2 GetImage ]
+	$cast2 SetOutputScalarTypeToFloat
+	$cast2 Update
+	
+	set diff [ vtkImageMathematics [ pxvtable::vnewobj ]]
+	$diff SetInput1  [ $cast1 GetOutput ]
+	$diff SetInput2 [ $cast2 GetOutput ]
+	$diff SetOperationToMultiply
+	$diff Update
+	
+	set results [ ::mdImageUtil::ProcessResultingImage [ $diff GetOutput ] $image1 "Product" ]
+	$diff Delete
+	$cast2 Delete
+	$cast1 Delete
+
+	return $results
+    }
+
+
+    proc MultiplyByConstant { currentimage const } {
+	
+	set cast1 [ vtkImageCast [ pxvtable::vnewobj ]]
+	$cast1 SetInput  [ $currentimage GetImage ]
+	$cast1 SetOutputScalarTypeToFloat
+	$cast1 Update
+
+	set prod [ vtkImageMathematics [ pxvtable::vnewobj ]]
+	$prod SetInput1 [$cast1 GetOutput]
+	$prod SetConstantK $const
+	$prod SetOperationToMultiplyByK
+	$prod Update
+	set results [ ::mdImageUtil::ProcessResultingImage [ $prod GetOutput ] $currentimage "ProductK" ]
+	$prod Delete
+	return $results
+
+    }
+
+
+    proc Square { image1 } {
+	
+	set cast1 [ vtkImageCast [ pxvtable::vnewobj ]]
+	$cast1 SetInput  [ $image1 GetImage ]
+	$cast1 SetOutputScalarTypeToFloat
+	$cast1 Update
+	
+	set squa [ vtkImageMathematics [ pxvtable::vnewobj ]]
+	$squa SetInput1  [ $cast1 GetOutput ]
+	$squa SetInput2 [ $cast1 GetOutput ]
+	$squa SetOperationToMultiply
+	$squa Update
+	
+	set results [ ::mdImageUtil::ProcessResultingImage [ $squa GetOutput ] $image1 "Squared" ]
+	$squa Delete
+	$cast1 Delete
+	
+	return $results
+    }
+
+    proc SquareRoot { image1 } {
+	
+	set cast1 [ vtkImageCast [ pxvtable::vnewobj ]]
+	$cast1 SetInput  [ $image1 GetImage ]
+	$cast1 SetOutputScalarTypeToFloat
+	$cast1 Update
+	
+	set sqroot [ vtkImageMathematics [ pxvtable::vnewobj ]]
+	$sqroot SetInput1  [ $cast1 GetOutput ]
+	$sqroot SetOperationToSquareRoot
+	$sqroot Update
+	
+	set results [ ::mdImageUtil::ProcessResultingImage [ $sqroot GetOutput ] $image1 "SqRoot" ]
+	$sqroot Delete
+	$cast1 Delete
+	
+	return $results
+    }
+
+
+   
+    # -------------------------------------------------------------------------------------
+    proc Subtract { image1 image2 } {
+
+	# ---------------------
+	# ( image1 - image2 )
+	# ---------------------
+	if {  [ $image1 GetImageSize ]  !=  [ $image2 GetImageSize ] } {
+	    puts stderr "Error Bad Dimensions!"
+	    return -1
+	}
+	    
+	set cast1 [ vtkImageCast [ pxvtable::vnewobj ]]
+	$cast1 SetInput  [ $image1 GetImage ]
+	$cast1 SetOutputScalarTypeToFloat
+	$cast1 Update
+    
+	set cast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+	$cast2 SetInput [ $image2 GetImage ]
+	$cast2 SetOutputScalarTypeToFloat
+	$cast2 Update
+	
+	set diff [ vtkImageMathematics [ pxvtable::vnewobj ]]
+	$diff SetInput1  [ $cast1 GetOutput ]
+	$diff SetInput2 [ $cast2 GetOutput ]
+	$diff SetOperationToSubtract
+	$diff Update
+
+	set results [ ::mdImageUtil::ProcessResultingImage [ $diff GetOutput ] $image1 "Difference" ]
+	$diff Delete
+	$cast2 Delete
+	$cast1 Delete
+
+	return $results
+    }
+
+    # -------------------------------------------------------------------------------------
+    # petimage/spectimage
+    proc Ratio { spectimage petimage } {
+
+	if {  [ $petimage GetImageSize ]  !=  [ $spectimage GetImageSize ] } {
+	    puts stderr "Error Bad Dimensions!"
+	    return -1
+	}
+	    
+	set diff [ vtkpxImageComputeNormalizedRatio [ pxvtable::vnewobj ]]
+	$diff SetInput  [ $spectimage GetImage ]
+	$diff SetInput2 [ $petimage GetImage ]
+	$diff SetThreshold 0.2
+	$diff SetSigma     1.0
+	$diff SetNormalizedThreshold 0.05
+	$diff Update
+	
+	set results [ ::mdImageUtil::ProcessResultingImage [ $diff GetOutput ] $spectimage "Ratio_v_PET" ]
+	$diff Delete
+	return $results
+    }
+
+    proc AbsoluteValue { currentimage } {
+	
+	set absval [ vtkImageMathematics [ pxvtable::vnewobj ]]
+	$absval SetInput1  [ $currentimage GetImage ]
+	$absval SetOperationToAbsoluteValue
+	$absval Update
+
+	set results [ ::mdImageUtil::ProcessResultingImage [ $absval GetOutput ] $currentimage "AbsVal" ]
+	$absval Delete
+	return $results
+
+    }
+
+    proc mask { currentImage lowThreshold highThreshold } {
+	
+	set mask   [ ::mdImageUtil::threshold $currentImage $lowThreshold $highThreshold ]
+	set output [ ::mdImageUtil::Multiply $mask $currentImage ]
+	return $output
+    }
+
+    proc TmapToZscore { tmap dof scaleFactor } {
+	
+	
+	set tm [ vtkpxComputeTmap [ pxvtable::vnewobj ] ]
+
+	set img [ $tm TmapToZScoreConversion [ $tmap GetImage ] $dof $scaleFactor ]
+        
+	set results [ ::mdImageUtil::ProcessResultingImage $img  $tmap "Zscore" ]
+	$img Delete
+	$tm Delete
+	return $results
+    }
+
+    proc PvalueToTscore { pvalue dof } {
+	
+	set Pvalue [ vtkpxMath [ pxvtable::vnewobj ] ]
+	set tscore [ $Pvalue PvalueToTvalue $pvalue $dof ]
+	return $tscore
+    }
+
+    #      Group v Group
+    #      Mean1-Mean2/ (Sigma1+Sigma2)
+    #
+    #      Invidividual v Group
+    #      (Image-Mean)/Sigma1
+
+ proc ComputeIndividualVsGroup { currentimage STDInputImg numberofsubjects { MeanImg 0 } } {
+
+
+	set results $currentimage
+	set newresults 0
+	
+
+	puts stderr "Input Image = [ $results cget -filename ] range: [ [ [ [ $results GetImage ] GetPointData ] GetScalars ] GetRange ]"
+	puts stderr "Input Sigma = [ $STDInputImg cget -filename ] range: [ [ [ [ $STDInputImg GetImage ] GetPointData ] GetScalars ] GetRange ]"
+
+	if { $MeanImg !=0 } {
+	    set results [ Subtract $currentimage $MeanImg ]
+	}
+
+	set math [ vtkpxComputeTmap [ pxvtable::vnewobj ]]
+	$math SetInput [ $results GetImage ]
+	$math SetInputStandardDeviation [ $STDInputImg GetImage ]
+	$math SetNumberOfSamples1 $numberofsubjects
+	$math SetNumberOfSamples2 1
+	$math SetNumberOfInputs 1
+	$math SetScaleFactor 1.0
+	$math Update
+
+	
+	set newresults [ ::mdImageUtil::ProcessResultingImage [ $math GetOutput ] $currentimage "Ttest" ]
+	$math Delete
+
+#	$currentimage Save current.hdr
+#	$STDInputImg Save std.hdr
+#	$MeanImg Save mean.hdr
+
+	if { $newresults !=0 } { 
+	    itcl::delete object $results
+	}
+
+	return $newresults
+    }
+
+    proc calcHAI { hypoBlob } {
+
+	set util [ vtkdsSpectUtil [ pxvtable::vnewobj ] ]
+	$util HAI [ $hypoBlob GetImage ] 
+	$util Delete
+    }
+
+    proc ComputeCluster { zscoreImage { expectedVoxPerCluster 0 } { expectedNumOfCluster 0 } { threshold 2.65 } { minClusterSize 125 } { mode 1 }  } {
+
+	set clusterThreshold [ vtknrImageCluster [ pxvtable::vnewobj ] ]
+	$clusterThreshold SetInput [ $zscoreImage GetImage ] 
+	$clusterThreshold SetIntensityThreshold $threshold
+
+	$clusterThreshold Update
+	
+	set clusterSize [ ::mdImageUtil::ProcessResultingImage [ $clusterThreshold GetOutput ] $zscoreImage "clusterSize" ]
+	set clusterId   [ ::mdImageUtil::ProcessResultingImage [ $clusterThreshold GetClusterNumberImage ]  $zscoreImage "clusterId" ]
+	set clusterId   [ ::mdImageUtil::mask $clusterId 0 100000 ]
+	
+	set mask [ ::mdImageUtil::threshold $clusterSize $minClusterSize 1000000 ]
+	
+	set clusterSize [ ::mdImageUtil::Multiply $clusterSize $mask ]
+	set clusterId   [ ::mdImageUtil::Multiply $clusterId   $mask ]
+	set bothBlobs   [ ::mdImageUtil::Multiply $zscoreImage $mask ]
+	
+	$clusterThreshold Delete
+	
+	if { $mode == 1 } { return $bothBlobs }
+	    
+	if { $mode == 3 } {
+	    set singleBlob [ ::mdImageUtil::mask $bothBlobs -100 -0.01 ]
+	    set util [ vtkdsSpectUtil [ pxvtable::vnewobj ] ]
+	    $util HAI [ $singleBlob GetImage ]
+	    $util Delete
+	} else {
+	    set singleBlob [ ::mdImageUtil::mask $bothBlobs 0.01 100 ]
+	}
+	
+	return [ ::mdImageUtil::clusterStats $singleBlob $clusterSize $clusterId $expectedVoxPerCluster $expectedNumOfCluster ]
+    }
+     
+
+
+    proc reselCount { image xFHWM yFHWM zFHWM } {
+	
+	set xDim 2/$xFHWM;set yDim 2/$yFHWM;set zDim 2/$zFHWM
+	set util [ vtkdsSpectUtil [ pxvtable::vnewobj ] ]
+	set componentArray [ $util reselCount [ $image GetImage ] ]
+	
+	set volume [ $componentArray GetComponent 0 0 ];
+	set cube   [ $componentArray GetComponent 0 1 ]
+	set xyFace [ $componentArray GetComponent 0 2 ]
+	set yzFace [ $componentArray GetComponent 0 3 ]
+	set xzFace [ $componentArray GetComponent 0 4 ]
+	set xEdge  [ $componentArray GetComponent 0 5 ]
+	set yEdge  [ $componentArray GetComponent 0 6 ]
+	set zEdge  [ $componentArray GetComponent 0 7 ]
+	$util Delete
+	$componentArray Delete
+		
+	set outputList [ list ]
+	lappend outputList [ expr $volume - $xEdge - $yEdge - $zEdge + $xyFace + $xzFace + $yzFace - $cube ]
+	lappend outputList [ expr ($xEdge-$xyFace-$xzFace+$cube)*$xDim + ($yEdge-$xyFace-$yzFace+$cube)*$yDim + ($zEdge-$yzFace-$xzFace+$cube)*$zDim ]
+	lappend outputList [ expr ($xyFace-$cube)*$xDim*$yDim + ($xzFace-$cube)*$xDim*$zDim + ($yzFace-$cube)*$zDim*$yDim ]
+	lappend outputList [ expr $cube*$xDim*$yDim*$zDim ]
+	
+	return $outputList
+    }
+    
+    proc eulerCharacteristicDensity { tscore sigLevel } {
+	
+	set tmp [ expr pow(1+$tscore*$tscore/13,-6) ]
+	set outputList [ list ]
+	lappend outputList $sigLevel 
+	lappend outputList [ expr 0.2650*$tmp ]
+	lappend outputList [ expr 0.1727*$tscore*$tmp ] 
+	lappend outputList [ expr 0.1169*$tmp*(12*$tscore*$tscore/13-1) ]
+	return $outputList
+    }
+	
+	
+     proc clusterStats { singleBlob clusterSize clusterId expectedVoxPerCluster expectedNumOfCluster } {
+	 
+	 set util [ vtkdsSpectUtil [ pxvtable::vnewobj ] ]
+	 set clusterInfo [ $util ClusterImage [ $singleBlob GetImage ] [ $clusterId GetImage ] [ $clusterSize GetImage ] $expectedVoxPerCluster $expectedNumOfCluster ]
+	 $util Delete
+	 
+	 set numComponents [ $clusterInfo GetNumberOfComponents ]
+	 set numTuples [ $clusterInfo GetNumberOfTuples ]
+	 set outputList [ list ]
+
+	 for { set tupleCount 0 } { $tupleCount<$numTuples } { incr tupleCount } {
+	     set tempList [ list ]
+	     for { set compCount 0 } { $compCount<$numComponents } { incr compCount } {	  
+		 lappend tempList [ $clusterInfo GetComponent $tupleCount $compCount ]
+	     }
+	     lappend outputList $tempList
+	 }
+	  return  [ lsort -increasing -index 1 -real $outputList ]
+     }
+
+    proc ComputeGroupVsGroup { mean1 sigma1 nsubjects1 mean2 sigma2 nsubjects2 } {
+
+	set math [ vtkpxComputeTmap [ pxvtable::vnewobj ]]
+	$math SetInput  [ $mean1 GetImage ]
+	$math SetInput2 [ $mean2 GetImage ]
+	$math SetInputStandardDeviation  [ $sigma1 GetImage ]
+	$math SetInputStandardDeviation2 [ $sigma2 GetImage ]
+	$math SetNumberOfSamples1 $nsubjects1
+	$math SetNumberOfSamples2 $nsubjects2
+	$math SetNumberOfInputs 2
+	$math SetScaleFactor 1000.0
+	$math Update
+	
+	set newresults [ ::mdImageUtil::ProcessResultingImage [ $math GetOutput ] $mean1 "Group_ttest" ]
+	$math Delete
+
+	return $newresults
+    }
+    
+    #------------------------------------------------------------------------------------------
+    #A couple procs to create a binary mask (or other piecewise mapped image) out of an ROI image
+    proc InsertBump { map c1 val } {
+	$map InsertNextTuple [ expr $c1 - 0.01  ] 0 0
+	$map InsertNextTuple [ expr $c1 - 0.005 ] $val 0
+	$map InsertNextTuple [ expr $c1 + 0.005 ] $val 0
+	$map InsertNextTuple [ expr $c1 + 0.01  ] 0 0
+    }
+    
+    proc ListMaskImage { currentimage roilist0 } {
+	
+	set map [ vtkFloatArray [ pxvtable::vnewobj ]]
+	$map SetNumberOfComponents 3
+	$map InsertNextTuple3 $x $y 0.0
+	
+	st roilist [ lsort $roilist0 ]
+	
+	for { set i 0 } { $i < [ llength $roilist ] } { incr i } {
+	    InsertBump $map [ lindex $roilist $i ] 1
+	}
+	
+	set sh  [ vtkpxImageAlgebra [ pxvtable::vnewobj ]  ]
+	$sh SetInput [ $currentimage GetImage ]
+	$sh SetMap $map
+	$sh SetOutputScalarTypeToShort
+	$sh Update
+
+	set newresults [ ::mdImageUtil::ProcessResultingImage [ $sh GetOutput ] $currentimage "Mask" ]
+	$sh Delete
+	return $newresults
+	
+    }
+    
+    #------------------------------------------------------------------------------------------
+
+}
+    
+
+
+    
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/packages/metakitDB.tcl b/bioimagesuite30_src/bioimagesuite/datatree/packages/metakitDB.tcl
new file mode 100644
index 0000000..149396f
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/packages/metakitDB.tcl
@@ -0,0 +1,98 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+#------------------------------------------------------------------------------------------
+#Meta Kit implementation of the database
+#------------------------------------------------------------------------------------------
+
+::itcl::class chellyMetaDBManager {
+
+    inherit chellyDBManager
+
+    public variable dbKey
+    
+    public method SaveDatatree {} 
+    public method LoadDatatree {}
+
+    constructor {_filename _datatreename _tree} {
+	set filename $_filename
+	set DatatreeName $_datatreename
+	set Tree $_tree
+	set dbKey db;#This is set to a constant
+    }
+
+}
+
+::itcl::body chellyMetaDBManager::SaveDatatree {} {
+
+    #open (or create) a database file named $filename...the key is $db
+    mk::file open $dbKey $filename
+ 
+    #clear out the file
+    set len [mk::file views]
+    if {[llength $len]} {
+	foreach i [mk::file views] {
+	    mk::view delete $i
+	}
+    }
+    
+    #set the view, giving it two spaces, one for the patient name, the other for the whole tree of data
+    set vw [mk::view layout $dbKey.data Name ImageTree]
+    
+    #add a single entry to the view
+    mk::row append $vw Name $DatatreeName ImageTree $Tree
+
+    #commit this entry to the file
+    mk::file commit $dbKey
+
+    mk::file close $dbKey
+
+}
+
+::itcl::body chellyMetaDBManager::LoadDatatree {} {
+    
+    #Open the file
+    mk::file open $dbKey $filename
+    
+    #Create a cursor at the row named "data"
+    catch {mk::cursor create cu $dbKey.data}
+    mk::cursor position cu 0
+
+    #Store the two items - name and tree object - in an array
+    set output(Name) [mk::get $cu Name]
+    set output(ImageTree) [mk::get $cu ImageTree]
+
+    return $output
+
+}
+##########################################################################################
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/packages/pkgIndex.tcl b/bioimagesuite30_src/bioimagesuite/datatree/packages/pkgIndex.tcl
new file mode 100644
index 0000000..9d389fc
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/packages/pkgIndex.tcl
@@ -0,0 +1,85 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# Tcl package index file, version 1.1
+# This file is generated by the "pkg_mkIndex" command
+# and sourced either when an application starts up or
+# by a "package unknown" script.  It invokes the
+# "package ifneeded" command to set up package-related
+# information so that packages will be loaded automatically
+# in response to "package require" commands.  When this
+# script is sourced, the variable $dir must contain the
+# full path name of this file's directory.
+
+#my chellyDB package
+package ifneeded chellyDB 1.0 [list source [file join $dir chellyDB.tcl]]
+package ifneeded pxitclchellypackages 1.0 [list source [file join $dir pxitclchellypackages.tcl]]
+
+
+#my VisTree package
+package ifneeded VisTree      1.0 [list source [file join $dir VisTree.tcl]];#obsolete
+package ifneeded VisTree2      2.0 [list source [file join $dir VisTree2.tcl]]
+
+#my modified OverlayTool package
+package ifneeded pxitcloverlaytab 1.0 [list source [file join $dir pxitcloverlaytab.tcl]]
+
+#struct packages
+if {![package vsatisfies [package provide Tcl] 8.2]} {return}
+package ifneeded struct            2.1   [list source [file join $dir struct.tcl]]
+package ifneeded struct            1.4   [list source [file join $dir struct1.tcl]]
+
+package ifneeded struct::graph     2.0   [list source [file join $dir graph.tcl]]
+package ifneeded struct::queue     1.3   [list source [file join $dir queue.tcl]]
+package ifneeded struct::stack     1.3   [list source [file join $dir stack.tcl]]
+package ifneeded struct::tree      2.0   [list source [file join $dir tree.tcl]]
+package ifneeded struct::matrix    2.0   [list source [file join $dir matrix.tcl]]
+package ifneeded struct::pool      1.2.1 [list source [file join $dir pool.tcl]]
+package ifneeded struct::record    1.2.1 [list source [file join $dir record.tcl]]
+package ifneeded struct::list      1.4   [list source [file join $dir list.tcl]]
+package ifneeded struct::set       2.1   [list source [file join $dir sets.tcl]]
+package ifneeded struct::prioqueue 1.3   [list source [file join $dir prioqueue.tcl]]
+package ifneeded struct::skiplist  1.3   [list source [file join $dir skiplist.tcl]]
+
+package ifneeded struct::graph     1.2.1 [list source [file join $dir graph1.tcl]]
+package ifneeded struct::matrix    1.2.1 [list source [file join $dir matrix1.tcl]]
+
+
+#my AtlasProg package
+package ifneeded AtlasProg 1.0 [list source [file join $dir AtlasProg.tcl]]
+
+#my SPECT Processing  package
+package ifneeded SPECTProcessProg 1.0 [list source [file join $dir SPECTtools.tcl]]
+
+#my ElectrodeAttrProg package
+package ifneeded ElectrodeAttrProg 1.0 [list source [file join $dir ElectrodeAttrProg.tcl]]
+
+#my ElectrodeAttrProg package
+package ifneeded mdImageUtils 1.0 [list source [file join $dir mdImageUtils.tcl]]
+
+#The Advanced Reg Tools  package
+package ifneeded AdvancedRegTools 1.0 [list source [file join $dir AdvancedRegTools.tcl]]
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/packages/pxitclchellypackages.tcl b/bioimagesuite30_src/bioimagesuite/datatree/packages/pxitclchellypackages.tcl
new file mode 100644
index 0000000..e8b82a3
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/packages/pxitclchellypackages.tcl
@@ -0,0 +1,69 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclchellypackages 1.0
+
+set dname [  file dirname [ info script ] ]
+lappend auto_path $dname
+
+
+
+set datatreebioimagesuitepath  [ file join [ file join [ file dirname [ info script ]] .. ] .. ]
+
+if { [ file exists [ file join ${datatreebioimagesuitepath} [ file join base vtkpxcontrib.tcl ]] ] != 1 } {
+
+    # Not in the source tree so try some options
+    # if the environment variable BIOIMAGESUITEDIR is set it is used
+
+    set datatreebioimagesuitepath /usr/local/bioimagesuite
+    if { $tcl_platform(platform) == "windows" } { 
+	set datatreebioimagesuitepath "c:/yale/bioimagesuite"
+    }
+    
+    set fn ""
+    catch { set fn $env(BIOIMAGESUITEDIR) }
+    
+    if { $fn != "" } {
+	set datatreebioimagesuitepath $env(BIOIMAGESUITEDIR)
+    }
+}
+
+if { [ file pathtype $datatreebioimagesuitepath ] == "relative" } {
+    set  datatreebioimagesuitepath [ file join [ pwd ] $datatreebioimagesuitepath ]
+    regsub -all  "/./" $datatreebioimagesuitepath "/" datatreebioimagesuitepath
+}
+
+#puts stderr "BioImage Suite Path=$datatreebioimagesuitepath"
+
+lappend auto_path [ file join $datatreebioimagesuitepath base ]
+lappend auto_path [ file join $datatreebioimagesuitepath main ]
+
+unset dname
+#unset datatreebioimagesuitepath
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/packages/pxitcloverlaytab.tcl b/bioimagesuite30_src/bioimagesuite/datatree/packages/pxitcloverlaytab.tcl
new file mode 100644
index 0000000..e12df60
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/packages/pxitcloverlaytab.tcl
@@ -0,0 +1,198 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitcloverlaytab 1.0
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxvtable   1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitcltransform 1.0
+package require  pxitcloverlaytool 1.0
+
+
+itcl::class pxitcloverlaytabGUI {
+
+    inherit pxitcloverlaytool
+ 
+    public variable inputimagescallback 0
+    public variable itcl_transform 0
+
+    constructor { par args } {
+	pxitcloverlaytool::constructor $par $args
+    } {
+	set itcl_transform [ [  pxitcltransform \#auto ] GetThisPointer ]
+	
+	#Use just the functional overlay part of the reslice control
+	set compact_reslice_control 0
+
+    }
+    
+
+
+    public  method ResliceFunctionalImage { force display } {
+	if { $inputimagescallback != 0 } {
+	    eval $inputimagescallback
+	}
+	return [ ::pxitcloverlaytool::ResliceFunctionalImage $force $display ]
+    }
+    
+
+
+    public method CreateResliceControl { par } {
+
+	#------------------------------------------------------------------------------------------
+	#
+	# Reslice Controls
+	# ----------------
+	#
+	# Edited 01/25/06 by Marcello DiStasio to fit into surgery tool
+	#
+	#------------------------------------------------------------------------------------------
+
+	#Three main frames
+	set w $par
+	set OCbackgroundcolor [$par cget -background]
+	frame $w.m; 
+	frame $w.p; 
+	frame $w.q;  
+	pack $w.m $w.p $w.q -side top -expand 1 -pady 1 -padx 1
+
+	#Reslice Output Canvas
+	set OC [canvas $w.m.imagecanvas -height 190 -width 480 -bg "$OCbackgroundcolor"];     pack $OC -fill both -expand 1
+
+	#Interpolation frame
+	label $w.p.1 -text "Interpolation Type:"
+	tk_optionMenu $w.p.opt [ itcl::scope thisparam($this,resliceinterp) ] "NearestNeighbor" "Linear" "Cubic"
+#	pack $w.p.1 $w.p.opt  -side left -expand f
+
+	#----------------------------------------------------------------------------------------------------
+	#Old Checkbuttons
+	checkbutton   $w.q.1  -text "Bounds to Reference"  -variable [ itcl::scope thisparam($this,reslicetoreference) ]
+	checkbutton   $w.q.2 -text "Scale By Jacobian"   -variable  [ itcl::scope thisparam($this,reslicescaleintensity) ]
+	
+	
+	# 	    pack $w.q.1 $w.q.2  -side top -expand f -fill x
+	checkbutton   $w.p.11 -variable [ itcl::scope thisparam($this,reslicewrappad) ] -text "Wrap"
+	checkbutton   $w.p.12  -text "Automatically Reorient"  -variable [ itcl::scope thisparam($this,autoreorient) ]
+	# 	    pack $w.p.11 $w.p.12  -side top -expand f -fill x
+	#----------------------------------------------------------------------------------------------------
+
+	return $OC
+	
+    }
+    #------------------------------------------------------------------------------------------
+    #-------------------End overloaded method CreateResliceControl-----------------------------
+    #------------------------------------------------------------------------------------------
+
+
+   # --------------------------------------------------------
+   #    overloaded Create Overlay Control 
+      # --------------------------------------------------------
+    public method CreateFunctionalOverlayControl { parent } {
+
+	set basewidget $parent
+   	set w $parent
+   	set OCbgcolor [$w cget -background]
+	
+  	frame $w.m -bg $OCbgcolor -pady 2; frame $w.m2 -bg $OCbgcolor; 
+	frame $w.f0 -bg $OCbgcolor; frame $w.f1 -bg $OCbgcolor; frame $w.f2 -bg $OCbgcolor;
+	pack $w.m $w.m2 $w.f0 $w.f1 $w.f2 -side top -expand f
+	label $w.m.1 -text "Overlay Type:" -bg $OCbgcolor
+  	tk_optionMenu $w.m.opt [ itcl::scope thisparam($this,overlaymode) ] "Positive" "Negative" "Both" 
+	$w.m.opt configure -bg LightBlue3 -activebackground LightBlue1 
+  	pack $w.m.1 $w.m.opt -side left -expand f
+	
+  	if { $disable_colormapchoice == 0 } {
+	    
+  	    label $w.m.c1 -text "Colormap:" -bg $OCbgcolor
+  	    tk_optionMenu $w.m.copt [ itcl::scope thisparam($this,overlaycmapmode) ] "F1" "F2" "F3" 
+  	    pack $w.m.c1 $w.m.copt -side left -expand f
+  	} else {
+  	    set thisparam($this,overlaycmapmode) F1
+  	}
+    
+  	checkbutton $w.m.chk2 -variable [ itcl::scope thisparam($this,overlayanatcmapmode) ] -text "Normalize Anatomical" \
+  	    -bg LightBlue3 -activebackground LightBlue1
+  	pack $w.m.chk2 -side left -expand f  -padx {40 0}
+	
+  	# Clustering Stuff
+  	# ----------------
+  	global tcl_platform
+	
+
+  	label $w.m2.1 -text "Clustering:" -bg $OCbgcolor
+  	set thisparam($this,cluster_threshold_scale) [ scale  $w.m2.s -orient horizontal  -from 0 -to 1000 -resolution 1.0 -showvalue 0 -length 150 -variable [ itcl::scope thisparam($this,cluster_threshold) ] ]
+  	eval "bind $w.m2.s <ButtonRelease> { $this CreateOverlay }"
+  	entry $w.m2.e -textvariable [ itcl::scope thisparam($this,cluster_threshold) ] -width 6 \
+  	    -relief sunken -font { fixed 10 } -bg $OCbgcolor
+	
+  	label $w.m2.l1 -text "Prob: " -bg $OCbgcolor
+  	set thisparam($this,cluster_threshold_prob) [ label $w.m2.l2 -text "1.0" -fg "blue" ]
+	
+  	pack $w.m2.1 $w.m2.s $w.m2.e $w.m2.l1  $w.m2.l2 -side left -expand t -fill x
+
+    
+  	set thisparam($this,overlay_minthresholdscale)  [ ::pxtclutil::CreateTriple $w.f0.0  "Low Threshold"   [ itcl::scope thisparam($this,overlaymin) ]  0.0 1000.0 0.1 10 95 ]
+	$w.f0.0 configure -background $OCbgcolor -ipadx 10 -ipady {0 4}
+  	set thisparam($this,overlay_maxthresholdscale)  [ ::pxtclutil::CreateTriple $w.f0.1  "High Threshold"  [ itcl::scope thisparam($this,overlaymax) ]  0.0 1000.0 0.1 10 95 ]
+	$w.f0.1 configure -background $OCbgcolor -ipadx 10 -ipady {0 4}
+  	::pxtclutil::CreateTriple $w.f0.2  "Inten. Thr"  [ itcl::scope thisparam($this,overlayinten) ]  -1.0 255.0 5 1 60
+	$w.f0.2 configure -background $OCbgcolor -ipadx 10 -ipady {0 4}
+	
+  	checkbutton $w.f1.chk -variable [ itcl::scope thisparam($this,overlaysingleframe) ] \
+  	    -text "Single\nComponent\nOnly" -bg LightBlue3 -activebackground LightBlue1
+  	pack $w.f1.chk -side left -padx 5
+  	set thisparam($this,overlay_componentscale)  [ ::pxtclutil::CreateTriple $w.f1.1 "Select Component:"  [ itcl::scope thisparam($this,overlaycurrentframe) ]  1 10 1 10 95 ] 
+	$w.f1.1 configure -background $OCbgcolor -ipady {2 2} -ipadx 40
+  	eval "bind $thisparam($this,overlay_componentscale) <ButtonRelease> \"$this UpdateOverlayRange\" "
+	
+  	frame $w.c -bg $OCbgcolor; pack $w.c -side bottom -expand 1 -fill x -pady {0 2} -padx 8
+  	eval "button  $w.c.1  -text \"Force  Reslice!\" -command { $this ResliceFunctionalImage 1 1 } -background green4 -activebackground green"
+  	eval "button  $w.c.2  -text \"Create Overlay!\" -command { $this CreateOverlay   } -background green3 -activebackground green -activeforeground blue"
+  	pack $w.c.1 $w.c.2  -side left -expand 1 -fill x -padx 3
+	
+#	puts stderr "comp scale $thisparam($this,overlay_componentscale)"
+
+    }
+    
+        
+    public method GetTransformation { } {
+	return [ $itcl_transform GetTransformation ]
+    }
+    
+    public method SetTransformation { newtr args } {
+	$itcl_transform CopyTransformation $newtr
+    }
+    
+    public    method GetTransformationName { } {
+	return [ $itcl_transform configure -filename ]
+    }
+    
+    
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/pkgIndex.tcl b/bioimagesuite30_src/bioimagesuite/datatree/pkgIndex.tcl
new file mode 100644
index 0000000..5dcd73d
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/pkgIndex.tcl
@@ -0,0 +1,64 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# Tcl package index file, version 1.1
+# This file is generated by the "pkg_mkIndex" command
+# and sourced either when an application starts up or
+# by a "package unknown" script.  It invokes the
+# "package ifneeded" command to set up package-related
+# information so that packages will be loaded automatically
+# in response to "package require" commands.  When this
+# script is sourced, the variable $dir must contain the
+# full path name of this file's directory.
+
+# 	$Id: pkgIndex.tcl,v 1.1 2002/02/20 18:07:50 Xenios Exp $	
+
+
+# -------------------------------------------------------
+# Itcl stuff -- new versions of everything
+# -------------------------------------------------------
+#This is the oldest version
+package ifneeded pxitclbraintreegadget 1.0 [ list source [ file join $dir pxitclbraintreegadget.tcl ]]
+package ifneeded chellyGUI_old 1.0 	[list source /mnt/cluster1/mdistasio/UIproject/JMainTest.tcl]
+
+#Here is the stable version
+package ifneeded pxitclsurgerythingy 1.0 [ list source [ file join $dir pxitclsurgerythingy.tcl ]]
+package ifneeded chellyGUI 1.0  	 [ list source [ file join $dir ChellyGUI.tcl ]]
+
+#This is the test version
+package ifneeded pxitclsurgeryexperimental 1.0 \
+    [ list source [ file join $dir pxitclsurgeryexperimental.tcl ]]
+package ifneeded chellyGUI_2 1.0 \
+    [list source [ file join $dir ChellyGUI_exp.tcl ]]
+
+package ifneeded pxitclchellypackages 1.0 \
+    [list source [ file join $dir [ file join packages pxitclchellypackages.tcl ]] ]
+
+package ifneeded dsitcltree      1.0 [list source [ file join $dir dsitcltree.tcl      ]] 
+package ifneeded bis_treegui     1.0 [list source [ file join $dir bis_treegui.tcl     ]] 
+package ifneeded bis_treeguibase 1.0 [list source [ file join $dir bis_treeguibase.tcl ]] 
+package ifneeded bis_nodeinfobox 1.0 [list source [ file join $dir bis_nodeinfobox.tcl ]] 
diff --git a/bioimagesuite30_src/bioimagesuite/datatree/pxitclbraintreegadget.tcl b/bioimagesuite30_src/bioimagesuite/datatree/pxitclbraintreegadget.tcl
new file mode 100644
index 0000000..1e74422
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/datatree/pxitclbraintreegadget.tcl
@@ -0,0 +1,585 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# This used to be pxitclsurgerygadget.tcl --- complete working version
+
+
+package provide pxitclbraintreegadget 1.0
+
+# 	$Id: pxitclsurgerygadget.tcl,v 1.2 2004/02/03 17:36:31 xenios Exp xenios $	
+
+#This package does nothing but set the required paths
+lappend auto_path [file dirname [info script]]
+package require pxitclchellypackages 1.0
+
+package require chellyGUI_2
+package require bis_treegui 
+package require bis_guitreecreate4d 1.0
+
+#package require  vtkpxcontrib 1.1
+package require  labelframe   1.0
+package require  pxtclutil    1.0
+package require  pxvtable     1.0
+package require  pxtclhelp    1.0
+package require  Itcl         3.2
+package require  Iwidgets     4.0
+package require  pxitclimage            1.0
+package require  pxitcltransform        1.0
+package require  pxitclsubjectentry     1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitclbaseimageviewer  1.0
+package require  pxitcloverlaytab      1.0
+
+
+
+# ----------------------------------------------------------------------------------------------
+
+itcl::class pxitclsurgerygadget {
+    
+    inherit pxitclbaseimagecontrol
+    
+    # Generic Stuff 
+    private   common   thisparam        
+    
+    # New Base Widget
+    protected variable basewidgetframe 0
+    
+    # Subject Specific
+    
+    protected variable second_viewer      0
+    public    variable electrodecontrol   0
+    public    variable electrodecontrol2  0
+    public    variable overlaycontrol     0
+    public    variable functional_menu    0
+    
+    public variable overlayinputbase -1
+    public variable overlayinputfunc -1
+    
+    protected variable image1_control    0
+    protected variable image2_control   0
+    protected variable image3_control   0
+    protected variable transformation_control    0
+    
+    public    variable chellyMain
+    public    variable menubase 0
+    public    variable  overlaytool     0
+    public    variable  OCbgcolor 
+    public    variable ResliceCanvas -1
+    
+    public variable useNew 0 ; # use the new style datatree
+    
+    #public method GetViewer  { } { return $second_viewer }
+    public method getTreeGUI { } { return chellyMain } 
+    public method SetValueImage { vtkimg  } 
+
+    constructor { par args } {
+	pxitclbaseimagecontrol::constructor $par 
+    } {
+	
+	if { [ llength $args] > 0  } {
+	    set second_viewer [ lindex $args 0 ]
+	}
+	InitializeSurgeryGadget
+	set OCbgcolor "LightSteelBlue1"	
+
+	set overlaybase     [ [pxitclimage \#auto] GetThisPointer ]
+	set overlayfunction [ [pxitclimage \#auto] GetThisPointer ]
+	set overlaytool [ [ pxitcloverlaytabGUI \#auto $this ] GetThisPointer ]
+	$overlaytool configure -disable_colormapchoice 0
+	set appname "BioImage Suite::DataTree Tool"
+    }
+    
+    private method InitializeSurgeryGadget { } 
+    public method Initialize { widget }
+    public method bindWindowClose { }
+
+    public method AddToMenuButton { mb args } 
+    public method AddToMenuButtonLite { mb args } 
+    public method SetResultsFromObject { img obj  } 
+    public method SetLookupTable       { colormap }
+    public method SetLookupTableMode   { index }
+    
+    public method GetImageControl1 { } { return $image1_control }
+    public method GetImageControl2 { } { return $image2_control }
+    public method GetImageControl3 { } { return $image3_control }
+    
+    # ---------------------------
+    # Subject Specific Callbacks
+    # ---------------------------
+    protected method CreateOverlayControl   { widget }
+    protected method CreateImageControl     { widget }
+    protected method CreateMainControl      { widget menubase }
+    
+    public    method SetOverlayToolInputs {  base_image functional_image } 
+    public    method ProcessResults { filter opname  } 
+    public    method ProcessResultsImage { img opname  } 
+    public    method SetImageToViewer { img viewer }
+    
+    public method VerifyRegistrationCallback { mode args }
+    public method VerifyRegistration { imgcontrol1 imgcontrol2 xformcontrol }
+    
+    
+}
+
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclsurgerygadget::InitializeSurgeryGadget { } {
+    
+    set transformation_control [ [  pxitcltransformGUI \#auto ] GetThisPointer ]
+    $transformation_control configure -description "Transformation Image1->Image2"
+    
+    set image1_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $image1_control configure -description "Reference Space Image (defines coordinate system)"
+    
+    set image2_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $image2_control configure -description "Anatomical Image"
+    
+    set image3_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $image3_control configure -description "Functional Image"
+    
+    set thisparam($this,overlayviewer) "Reference"
+    if { $second_viewer !=0 } {
+	set thisparam($this,overlayviewer) "Transform"
+    }
+    
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclsurgerygadget::SetValueImage { vtkimg  } {
+    if {$thisparam($this,overlayviewer) == "Transform" && $second_viewer !=0 } {
+	$second_viewer SetValueImage $vtkimg
+    } else {
+	$parent SetValueImage $vtkimg
+    }
+}
+
+itcl::body pxitclsurgerygadget::SetResultsFromObject { img obj  } {
+    
+    if { [ $img GetImageSize ] < 2 } {	
+	return 0    
+    }
+    
+    if { $obj == $overlaytool && $parent !=0 } {
+	
+	# Edit Stuff Here
+	# ---------------
+	
+	if {$thisparam($this,overlayviewer) == "Transform" && $second_viewer !=0 } {
+	    $second_viewer SetResultsFromObject $img $this
+
+	} else {
+	    $parent SetResultsFromObject $img $this
+	}
+
+    } else {
+        SetResults $img
+    }
+    return 1
+}
+
+# ---------------------------------------------------------------------------
+#  Lookup Table Stuff 
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclsurgerygadget::SetLookupTable { colormap } {
+    
+    set v $parent
+    if {$thisparam($this,overlayviewer) == "Transform" && $second_viewer !=0 } {
+	set v $second_viewer
+    }
+    
+    if { $v != 0 } {
+	$v SetLookupTable $colormap
+    }
+}
+
+itcl::body pxitclsurgerygadget::SetLookupTableMode { index } {
+    
+    set v $parent
+
+    if { $thisparam($this,overlayviewer) == "Atlas" } {
+
+	# 
+	#  Needs Editing
+	#
+	# set vtk_viewer = [ [ chellyMain GetAtlas ] GetViewer ]
+	# $vtk_viewer SetLookupTableMode $index 
+    }
+
+    if {$thisparam($this,overlayviewer) == "Transform" && $second_viewer !=0 } {
+	set v $second_viewer
+    }
+    
+    if { $v != 0 } {
+	$v SetLookupTableMode [ expr 0+$index ]
+    }
+}
+
+
+#---------------------------------------------------------------------------
+#   
+# Output Stuff
+#
+# ---------------------------------------------------------------------------
+itcl::body pxitclsurgerygadget::VerifyRegistrationCallback { mode args } { 
+    
+    if { $mode == 1 } {
+	$this VerifyRegistration $image1_control $image2_control  $transformation_control
+    } 
+}
+
+
+itcl::body pxitclsurgerygadget::VerifyRegistration { imgcontrol1 imgcontrol2 xformcontrol } {
+    
+    global pxtcl_pref_array
+    
+    set image_ref [ $imgcontrol1 GetObject ]
+    set image_trn [ $imgcontrol2 GetObject ]
+    
+    set orient_ref [ $image_ref GetOrientation ]
+    set orient_trn [ $image_trn GetOrientation ]
+    
+    set dim1 [ [ $image_ref GetImage ] GetDimensions ]
+    set dim2 [ [ $image_trn GetImage ] GetDimensions ]
+    if { [lindex $dim2 0 ] <2 || [ lindex $dim1 0 ] < 2 } { 
+	::pxtclutil::Warning "No Image in Memory\n Cannot Verify Transformation!"
+	return  0
+    }
+    
+    WatchOn
+    
+    set ut [ vtkpxUtil [ pxvtable::vnewobj ]]
+    set tr [ $xformcontrol GetTransformation ]
+    set tmp  [ [  pxitclimage \#auto ] GetThisPointer ]
+    $ut ResliceImage [ $tmp GetImage ] [ $image_trn GetImage ] [ $image_ref GetImage ] [ $tr GetTransformation ] 1 0.0
+    
+    $tmp CopyImageHeader [ $image_ref GetImageHeader ]
+    $tmp configure -filename "trn_[$image_trn cget -filename ]"
+    
+    $parent SetResultsFromObject $image_ref $this
+    $second_viewer SetResultsFromObject $tmp $this
+    catch { itcl::delete object $tmp }
+    
+    WatchOff
+    return 1
+}
+#--------------------------------------------------------------------------------------------
+
+
+
+itcl::body pxitclsurgerygadget::SetImageToViewer { img viewer } {
+    
+    # img is a pxitclimage
+    # viewer is 
+    # viewer ref or trn
+    
+    set vtk_viewer 0
+    
+    catch { 	set vtk_viewer [ $parent  GetViewer ]  }
+    
+    if { $thisparam($this,overlayviewer) == "Transform" } {
+	catch { set vtk_viewer [ $second_viewer  GetViewer ]  }
+    }
+    
+    if { $vtk_viewer !=0 } {
+	$vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+    }
+    
+}
+
+itcl::body pxitclsurgerygadget::SetOverlayToolInputs { base_image functional_image } {
+    
+    set overlayinputbase $base_image
+    set overlayinputfunc $functional_image
+
+    $overlaytool SetImage $overlayinputbase
+    $overlaytool SetFunctionalImage $overlayinputfunc
+    set tr [ vtkIdentityTransform [ pxvtable::vnewobj ]]
+    $overlaytool SetTransformation $tr
+    $tr Delete
+}
+
+itcl::body pxitclsurgerygadget::CreateImageControl { widget } {
+    
+    #Obsolete for now (the controls are put in by chellyGUI)
+    
+
+}
+
+
+# ----------------------------------------------------------------------------------------------
+itcl::body pxitclsurgerygadget::CreateOverlayControl { widget } {
+
+
+    
+    frame $widget.t3 -background $OCbgcolor
+    pack $widget.t3  -side top -expand f -fill x -pady 4
+    # --------------------------
+    # Visualization Output Stuff
+    # --------------------------
+    iwidgets::Labeledframe $widget.t3.a -labelpos n -labeltext "Reslice Output" -background $OCbgcolor
+    iwidgets::Labeledframe $widget.t3.b -labelpos n -labeltext "Output Overlay" -background $OCbgcolor
+    set c2 [$widget.t3.a childsite]
+    set c3 [$widget.t3.b childsite]
+    $c2 configure -background $OCbgcolor
+    $c3 configure -background $OCbgcolor
+    pack $widget.t3.a $widget.t3.b -side top -fill both -padx 5 -pady 2
+    
+    set w2 [ frame $c3.ttop -background $OCbgcolor -padx 8 -pady 2];
+    pack $w2 -side bottom -expand 1 -fill x -padx 80
+    
+    #   if { $second_viewer != 0 } {
+    label $w2.ml -text "Output Viewer:" -background $OCbgcolor
+    tk_optionMenu $w2.mopt [ itcl::scope thisparam($this,overlayviewer)] "Reference" "Transform" 
+    $w2.mopt configure -background "LightBlue3" -activebackground "LightBlue1"
+    pack $w2.ml -side left -expand 0 -fill x
+    pack  $w2.mopt -side left -expand 1 -fill x
+    
+    #   }
+    
+    set ResliceCanvas [$overlaytool CreateResliceControl $c2]
+    $overlaytool CreateFunctionalOverlayControl $c3
+    
+
+}
+
+
+# ---------------------------------------------------------------------------
+# Main GUI Body 
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclsurgerygadget::Initialize { widget } { 
+
+    set basewidget $widget    
+
+    set basewidgetframe [ frame $basewidget.[ pxvtable::vnewobj ] -height 660 -width 960 ]
+    pack $basewidgetframe -side top -expand true -fill both
+
+    SetTitle "BioImage Suite - Data Tree Manager"
+        
+
+#--------------------------------------------------------------------------------
+#    Old, frame-based menu bar
+#--------------------------------------------------------------------------------
+#    set menubase     [ frame $basewidget.menu    -width 400 -height 50 ]
+#    pack $menubase -side top -expand f -fill x -pady 1 
+#--------------------------------------------------------------------------------
+    set menubase      [ $basewidget cget -menu ]
+    #    [ menu $basewidget.mdtopmenu -tearoff 0  ]
+    #$basewidget configure -menu $menubase
+    set notebook  0
+    set fr [ frame $basewidgetframe.notebook -background $OCbgcolor]
+    
+ 
+    pack $fr -side top -expand t -fill both -pady 1
+    
+    # Clean Menus
+    #    set childlist [ winfo children $menubase ]
+    
+    #    set functional_menu [ lindex $childlist 3 ]
+    #    puts "functional_menu $functional_menu"
+ 
+    #--------------------------------------------------------------------------------
+    #-----Most of Chelly GUI is created right here:----------------------------------
+    CreateMainControl $fr $menubase
+    #--------------------------------------------------------------------------------
+
+#     $menubase delete 0 3
+#     $menubase add cascade -underline 0  -label "Viewers"  -menu [ lindex $childlist 0 ]
+#     $menubase add cascade -underline 2  -label "Registration"  -menu [ lindex $childlist 2 ]   
+    
+#     #Set the background for all menu entries
+#     for {set i 0} {$i <= [[lindex $childlist 0 ] index end]} {incr i} {
+# 	[lindex $childlist 0] entryconfigure $i -background [ $chellyMain cget -menucolor ]
+#     }
+#     for {set i 0} {$i <= [[lindex $childlist 2 ] index end]} {incr i} {
+# 	[lindex $childlist 2] entryconfigure $i -background [ $chellyMain cget -menucolor ]
+#     }
+
+#     set vmenu [ lindex $childlist 0 ]
+#     $vmenu delete end
+#     $vmenu delete end
+
+    
+   
+#    $menubase add cascade -underline 3  -label "Functional"  -menu [ lindex $childlist 3 ]
+#    $menubase add cascade -underline 1  -label "Transfer"  -menu [ lindex $childlist 1 ]
+    
+    # critical command 
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { $this bindWindowClose }"
+    #eval "wm protocol $basewidget WM_DELETE_WINDOW { $this ExitCommand  }"
+    $this ShowWindow "Main"
+    return $basewidget
+    
+}
+
+::itcl::body pxitclsurgerygadget::bindWindowClose { } {
+    
+    $chellyMain OnWidgetClose
+}
+
+::itcl::body pxitclsurgerygadget::AddToMenuButton { mb args} {
+    
+    eval "$mb add command -label \"Overlays\" -command { $this ShowWindow Overlays}"
+}
+
+::itcl::body pxitclsurgerygadget::AddToMenuButtonLite { mb args} {
+    
+    eval "$mb add command -label \"Surgery Tool\" -command {$this ShowWindow \"Overlays\"}"
+}
+
+
+# ---------------------------------------------------------------------------
+itcl::body pxitclsurgerygadget::CreateMainControl { widget menubase } {
+    
+    #show what widget to display the chellyGUI object in
+    
+    
+    set MainControlWidget $widget
+    
+    #instantiate chellyGUI
+    if { $useNew } {
+	set chellyMain [ [bis_treegui \#auto] GetThisPointer ]
+    } else {
+	set chellyMain [ [chellyGUI \#auto] GetThisPointer ]
+    }
+    #call the ShowManager method in chellyGUI, which does most of the display drawing
+    $chellyMain ShowManager $MainControlWidget $this $menubase
+    
+    #put the image1_control, image2_control, and transformation_control GUI objects in the midpane of chellyGUI
+    
+    update idletasks
+    
+    set w [ $chellyMain cget -midpane]
+ 
+    if { $useNew } {
+
+	set bis_menu [menu $menubase.bis -tearoff 0]
+	$menubase add cascade -label "BIS Algorithms" -menu $menubase.bis -background "#ede9e3"
+    
+	$bis_menu add cascade -label "Concatenate Images" -menu $bis_menu.m0 -background "#ede9e3"
+	set 4dmenu [menu $bis_menu.m0 -tearoff 0]
+	
+	set 4d [ bis_guitreecreate4d \#auto ]
+	$4d InitializeFromContainer $this
+	set w0 $bis_menu.$4d
+	
+	set 4d [ $4d GetThisPointer ]
+	$4d CreateGUI $w0 
+	$4d AddToMenuButton $4dmenu
+	$4d AddTreeGUI $chellyMain
+	
+	$bis_menu add cascade -label "Image Processing" -menu $bis_menu.m1 -background "#ede9e3"
+	set imageutilmenu [menu $bis_menu.m1 -tearoff 0]
+    
+	set imageutility [ bis_guitreeimageutility \#auto ]
+	$imageutility InitializeFromContainer $this
+	set w2 $bis_menu.$imageutility
+	
+	set imageutility [ $imageutility GetThisPointer ]
+	$imageutility CreateGUI $w2 
+	$imageutility AddToMenuButton $imageutilmenu
+	$imageutility AddTreeGUI $chellyMain
+	
+	$bis_menu add cascade -label "Connectivity" -menu $bis_menu.m2 -background "#ede9e3"
+	set connectivitymenu [menu $bis_menu.m2 -tearoff 0]
+                           
+	set connectivity [ bis_guitreeimageutility \#auto connectivity ]
+	$connectivity InitializeFromContainer $this
+	set w3 $bis_menu.$connectivity
+	
+	set connectivity [ $connectivity GetThisPointer ]
+	$connectivity CreateGUI $w3 
+	$connectivity AddToMenuButton $connectivitymenu
+	$connectivity AddTreeGUI $chellyMain
+	
+	$bis_menu add cascade -label "Surface Processing" -menu $bis_menu.m3 -background "#ede9e3"
+	set surfaceProcess [menu $bis_menu.m3 -tearoff 0]    
+	
+	set surfacecontrol [ bis_guisurfaceutility \#auto ] 
+	$surfacecontrol InitializeFromContainer $this
+	set w4 $bis_menu.$surfacecontrol
+	
+	set surfacecontrol [ $surfacecontrol GetThisPointer ]
+	$surfacecontrol CreateGUI $w4 
+	$surfacecontrol AddToMenuButton $surfaceProcess
+	#$surfacecontrol AddTreeGUI $chellyMain
+    }
+    
+    set nt $w.notebook 
+    iwidgets::tabnotebook $nt -tabpos n
+    pack $nt -side top -expand 1 -fill both -padx 3 -pady {0 3}
+    $nt config -background $OCbgcolor -backdrop "light steel blue"
+    set n1 [ $nt add -label "Images" ]
+    set n2 [ $nt add -label "Overlays" ] 
+    $nt view "Images"
+
+
+
+    $chellyMain ShowMidpaneTools  $n1
+    CreateOverlayControl    $n2
+
+    #    $w.notebook view "Overlays"
+    
+    #let chellyGUI know that the above three widgets exist
+    #$chellyMain chellyGUI::setSpaceControlWidget $image1_control
+    #$chellyMain chellyGUI::setAnatomicalControlWidget $image2_control
+    #$chellyMain chellyGUI::setFunctionalControlWidget $image3_control
+    
+    $chellyMain configure -viewer1 $parent
+    $chellyMain configure -viewer2 $second_viewer
+    $chellyMain configure -electrodecontrol1 $electrodecontrol
+    $chellyMain configure -electrodecontrol2 $electrodecontrol2
+    $chellyMain configure -overlaycontrol $overlaycontrol
+ 
+    #Now that the canvas has been created in its space, call the method to fill it
+    $chellyMain OCanvasInitialize $ResliceCanvas
+    update idletasks
+
+    
+}
+
+
+
+
+# ---------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    
+    wm withdraw .
+    set viewer1 0
+    set viewer2 0
+    set  surgerytool [ [  pxitclsurgerygadget \#auto $viewer1 $viewer2 ] GetThisPointer ]
+    
+    $surgerytool Initialize .
+    $surgerytool ShowWindow
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/images/CMakeLists.txt b/bioimagesuite30_src/bioimagesuite/images/CMakeLists.txt
new file mode 100644
index 0000000..13adf8a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/images/CMakeLists.txt
@@ -0,0 +1,88 @@
+
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  All rights reserved. This file may not be edited/copied/redistributed
+#BIOIMAGESUITE_LICENSE  without the explicit permission of the authors.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+
+SET (KITSCRIPTS
+#
+# This are various logos and icons
+#
+  bioimagesuite.ico
+  bioimagesuite.png
+  bioimagesuite.xbm
+  bioimagesuite_setuplogo.bmp
+  bioimagesuite_logo_small_www.gif
+  bioimagesuite_logo_www.gif
+# This is the MNI to Talairach Lookup table for MNI Space
+#
+  colin_talairach_lookup.nii.gz
+#
+# This is legacy stuff ignore
+#
+  colinlookup.hdr
+  colinlookup.img.gz
+
+#
+# This is the real MNI stuff
+#
+  MNI_T1_1mm.nii.gz
+  MNI_T1_1mm_mask.nii.gz
+  MNI_T1_1mm_stripped.nii.gz
+  MNI_T1_1mm_graywhite.nii.gz
+  MNI_T1_2mm.nii.gz
+  MNI_T1_2mm_mask.nii.gz
+  MNI_T1_2mm_stripped.nii.gz
+  MNI_T1_2mm_graywhite.nii.gz
+  avg152T1_LR_nifti.nii.gz
+#
+# This is the Yale Broadmann Areas Atlas
+#
+  yale_broadmann.nii.gz
+  yale_broadmann.txt
+  MNI_T1_1mm_graywhite.txt
+  bioimagesuite_atlas.txt
+  README.txt
+#
+# These are SPECT related
+#
+  ISASHN_Standard_Deviation.nii.gz
+  ISAS_SPECT_Template.nii.gz 
+  ISAS_Standard_Deviation.nii.gz
+  ISAS_Mean_Diff_SPECT.nii.gz 
+  ISAS_SPECT_Mask.nii.gz
+#
+# This is a sample sqlite database file
+#
+sampledatabase.sqlite
+)
+
+SET(KITAPPS )
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+# FILELIST4 and 5 are dummy file pointers to make sure that the fixlicense script
+# does not parse these in any way -- this causes problems with the Yale Atlas stuff
+SET (FILELIST4 ${BIOIMAGESUITE3_BINARY_DIR}/imagelist.txt)
+SET (FILELIST5 ${BIOIMAGESUITE3_BINARY_DIR}/imagelist.txt)
+bis_complex_tcl(bioimagesuite/images ${FILELIST4} ${FILELIST5})
+
+#MESSAGE("Appending to ${FILELIST}")
+FILE(APPEND ${FILELIST} "# ---------------------------------\n# ** images\n#-----------------------------------------\n")
+FILE(APPEND ${FILELIST} "${BIOIMAGESUITE_INSTALL_EXTRAPATH}/images/CMakeLists.txt\n")
diff --git a/bioimagesuite30_src/bioimagesuite/images/ISASHN_Standard_Deviation.nii.gz b/bioimagesuite30_src/bioimagesuite/images/ISASHN_Standard_Deviation.nii.gz
new file mode 100644
index 0000000..0d57157
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/ISASHN_Standard_Deviation.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/ISAS_Mean_Diff_SPECT.nii.gz b/bioimagesuite30_src/bioimagesuite/images/ISAS_Mean_Diff_SPECT.nii.gz
new file mode 100644
index 0000000..c2cec65
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/ISAS_Mean_Diff_SPECT.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/ISAS_SPECT_Mask.nii.gz b/bioimagesuite30_src/bioimagesuite/images/ISAS_SPECT_Mask.nii.gz
new file mode 100644
index 0000000..bbf035d
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/ISAS_SPECT_Mask.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/ISAS_SPECT_Template.nii.gz b/bioimagesuite30_src/bioimagesuite/images/ISAS_SPECT_Template.nii.gz
new file mode 100644
index 0000000..e7400d4
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/ISAS_SPECT_Template.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/ISAS_Standard_Deviation.nii.gz b/bioimagesuite30_src/bioimagesuite/images/ISAS_Standard_Deviation.nii.gz
new file mode 100644
index 0000000..4164a4d
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/ISAS_Standard_Deviation.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm.nii.gz b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm.nii.gz
new file mode 100644
index 0000000..4aa99d4
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm_graywhite.nii.gz b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm_graywhite.nii.gz
new file mode 100644
index 0000000..b61c402
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm_graywhite.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm_graywhite.txt b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm_graywhite.txt
new file mode 100644
index 0000000..06bf45a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm_graywhite.txt
@@ -0,0 +1,3 @@
+[ Gray/White Segm ]
+1:  Gray Matter
+2:  White Matter
diff --git a/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm_mask.nii.gz b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm_mask.nii.gz
new file mode 100644
index 0000000..2c40031
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm_mask.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm_stripped.nii.gz b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm_stripped.nii.gz
new file mode 100644
index 0000000..799d456
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_1mm_stripped.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/MNI_T1_2mm.nii.gz b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_2mm.nii.gz
new file mode 100644
index 0000000..d02c842
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_2mm.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/MNI_T1_2mm_graywhite.nii.gz b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_2mm_graywhite.nii.gz
new file mode 100644
index 0000000..36fde73
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_2mm_graywhite.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/MNI_T1_2mm_mask.nii.gz b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_2mm_mask.nii.gz
new file mode 100644
index 0000000..912bf16
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_2mm_mask.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/MNI_T1_2mm_stripped.nii.gz b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_2mm_stripped.nii.gz
new file mode 100644
index 0000000..ec0510b
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/MNI_T1_2mm_stripped.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/README.txt b/bioimagesuite30_src/bioimagesuite/images/README.txt
new file mode 100644
index 0000000..77e82d6
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/images/README.txt
@@ -0,0 +1,4 @@
+Lacadie C, Fulbright RK, Arora J, Constable RT, Papademetris X. Brodmann
+Areas defined in MNI space using a new Tracing Tool in BioImage Suite. In
+Human Brain Mapping 2008 (abstract).
+
diff --git a/bioimagesuite30_src/bioimagesuite/images/avg152T1_LR_nifti.nii.gz b/bioimagesuite30_src/bioimagesuite/images/avg152T1_LR_nifti.nii.gz
new file mode 100644
index 0000000..e2e978d
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/avg152T1_LR_nifti.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/bioimagesuite.ico b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite.ico
new file mode 100644
index 0000000..45dd809
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite.ico differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/bioimagesuite.png b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite.png
new file mode 100644
index 0000000..c46007c
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite.png differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/bioimagesuite.xbm b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite.xbm
new file mode 100644
index 0000000..db70d5a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite.xbm
@@ -0,0 +1,27 @@
+#define bioimagesuite_width 48
+#define bioimagesuite_height 48
+static unsigned char bioimagesuite_bits[] = {
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0xfc, 0xff,
+   0xff, 0x1f, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x1f, 0xfc, 0x3f, 0xf0, 0xff,
+   0xff, 0x3f, 0xf8, 0x7f, 0xe0, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xe0, 0xff,
+   0xff, 0x1f, 0xf8, 0xff, 0xe0, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xe0, 0xff,
+   0xff, 0x3f, 0xf8, 0xff, 0xc0, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xe0, 0xff,
+   0xff, 0x1f, 0xf8, 0x7f, 0xf0, 0xff, 0xff, 0x3f, 0xfc, 0x3f, 0xe0, 0xff,
+   0xff, 0x3f, 0xf0, 0x05, 0xf8, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xfe, 0xff,
+   0xff, 0x1f, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x3f, 0x54, 0x0b, 0xf0, 0xff,
+   0xff, 0x3f, 0xf8, 0x7f, 0xe0, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xe0, 0xff,
+   0xff, 0x1f, 0xfc, 0xff, 0xc1, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xc1, 0xff,
+   0xff, 0x3f, 0xfc, 0xff, 0x83, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0x81, 0xff,
+   0xff, 0x1f, 0xfc, 0xff, 0xc1, 0xff, 0xff, 0x3f, 0xf8, 0xff, 0xc1, 0xff,
+   0xff, 0x3f, 0xfc, 0xff, 0xc0, 0xff, 0xff, 0x1f, 0xf8, 0x3f, 0xc0, 0xff,
+   0xff, 0x1f, 0xa0, 0x02, 0xf0, 0xff, 0xff, 0x03, 0x00, 0x00, 0xf4, 0xff,
+   0xff, 0x03, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xb7, 0xaa, 0xf6, 0xfd, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+   0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
diff --git a/bioimagesuite30_src/bioimagesuite/images/bioimagesuite_atlas.txt b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite_atlas.txt
new file mode 100644
index 0000000..4b25719
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite_atlas.txt
@@ -0,0 +1,7 @@
+#Atlas Description File
+#
+# List here atlases in MNI space 
+#
+Yale Broadmann Atlas  : yale_broadmann
+Yale Gray/White Atlas : MNI_T1_1mm_graywhite
+
diff --git a/bioimagesuite30_src/bioimagesuite/images/bioimagesuite_logo_small_www.gif b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite_logo_small_www.gif
new file mode 100644
index 0000000..3dbb92d
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite_logo_small_www.gif differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/bioimagesuite_logo_www.gif b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite_logo_www.gif
new file mode 100644
index 0000000..9d4d0f5
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite_logo_www.gif differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/bioimagesuite_setuplogo.bmp b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite_setuplogo.bmp
new file mode 100644
index 0000000..e64b0b3
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/bioimagesuite_setuplogo.bmp differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/colin_talairach_lookup.nii.gz b/bioimagesuite30_src/bioimagesuite/images/colin_talairach_lookup.nii.gz
new file mode 100644
index 0000000..1a29e42
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/colin_talairach_lookup.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/colinlookup.hdr b/bioimagesuite30_src/bioimagesuite/images/colinlookup.hdr
new file mode 100644
index 0000000..0163878
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/colinlookup.hdr differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/colinlookup.img.gz b/bioimagesuite30_src/bioimagesuite/images/colinlookup.img.gz
new file mode 100644
index 0000000..0b4274b
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/colinlookup.img.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/sampledatabase.sqlite b/bioimagesuite30_src/bioimagesuite/images/sampledatabase.sqlite
new file mode 100644
index 0000000..b254ca9
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/sampledatabase.sqlite differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/yale_broadmann.nii.gz b/bioimagesuite30_src/bioimagesuite/images/yale_broadmann.nii.gz
new file mode 100644
index 0000000..ea9a298
Binary files /dev/null and b/bioimagesuite30_src/bioimagesuite/images/yale_broadmann.nii.gz differ
diff --git a/bioimagesuite30_src/bioimagesuite/images/yale_broadmann.txt b/bioimagesuite30_src/bioimagesuite/images/yale_broadmann.txt
new file mode 100644
index 0000000..2b20348
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/images/yale_broadmann.txt
@@ -0,0 +1,86 @@
+[ Objectmap Colors for yale_broadmann_HBM08_10_RL ]
+0 : Background
+1 : L_PrimSensory
+4 : L_PrimMotor
+5 : L_SensoryAssoc
+6 : L_BA6
+7 : L_BA7
+8 : L_BA8
+9 : L_BA9
+10 : L_BA10
+11 : L_BA11
+13 : L_Insula
+14 : L_BA14
+17 : L_PrimVisual
+18 : L_VisualAssoc
+19 : L_BA19
+20 : L_BA20
+21 : L_BA21
+22 : L_BA22
+23 : L_BA23
+24 : L_BA24
+25 : L_BA25
+30 : L_BA30
+31 : L_BA31
+32 : L_BA32
+34 : L_BA34
+36 : L_Parahip
+37 : L_Fusiform
+38 : L_BA38
+39 : L_BA39
+40 : L_BA40
+41 : L_PrimAuditory
+44 : L_BA44
+45 : L_BA45
+46 : L_BA46
+47 : L_BA47
+48:  L_Caudate
+49:  L_Putamen
+50:  L_Thalamus
+51:  L_GlobPal
+52:  L_NucAccumb
+53:  L_Amygdala
+54:  L_Hippocampus
+55:  L_Hypothalamus
+101 : R_PrimSensory
+104 : R_PrimMotor
+105 : R_SensoryAssoc
+106 : R_BA6
+107 : R_BA7
+108 : R_BA8
+109 : R_BA9
+110 : R_BA10
+111 : R_BA11
+113 : R_Insula
+114 : R_BA14
+117 : R_PrimVisual
+118 : R_VisualAssoc
+119 : R_BA19
+120 : R_BA20
+121 : R_BA21
+122 : R_BA22
+123 : R_BA23
+124 : R_BA24
+125 : R_BA25
+130 : R_BA30
+131 : R_BA31
+132 : R_BA32
+134 : R_BA34
+136 : R_Parahip
+137 : R_Fusiform
+138 : R_BA38
+139 : R_BA39
+140 : R_BA40
+141 : R_PrimAuditory
+144 : R_BA44
+145 : R_BA45
+146 : R_BA46
+147 : R_BA47
+148:  R_Caudate
+149:  R_Putamen
+150:  R_Thalamus
+151:  R_GlobPal
+152:  R_NucAccumb
+153:  R_Amygdala
+154:  R_Hippocampus
+155:  R_Hypothalamus
diff --git a/bioimagesuite30_src/bioimagesuite/main/CMakeLists.txt b/bioimagesuite30_src/bioimagesuite/main/CMakeLists.txt
new file mode 100644
index 0000000..42d33d7
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/CMakeLists.txt
@@ -0,0 +1,105 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+
+SET(KITSCRIPTS
+    pkgIndex.tcl
+    pxitclHistogramWidget.tcl
+    pxitclLandmarkControl.tcl
+    pxitclbaseimagecontrol.tcl
+    pxitclbrainstrip.tcl
+    pxitclatlasgadget.tcl
+    pxitclyaleatlasgadget.tcl
+    pxitclwfuatlasgadget.tcl
+    pxitclanimationgadget.tcl
+    pxitcldistributiontablegadget.tcl
+    pxitclcreatesolidcontrol.tcl
+    pxitclimagenormalization.tcl
+    pxitclsplineobjectmap.tcl
+    pxitclsubjectentry.tcl
+    pxitclsurfaceobjectmap.tcl
+    pxitclElectrodeMultiControl.tcl
+    pxitclPolyDataControl.tcl
+    pxitclarticulatedmodel.tcl
+    pxitclbase4dimageviewer.tcl
+    pxitclbasecontrol.tcl
+    pxitclbaseimageviewer.tcl
+    pxitcloverlaytool.tcl
+    pxitclfilelistmenu.tcl
+    pxitclcsigadget.tcl
+    pxitclexpfit.tcl
+    pxitclimageimport.tcl
+    pxitcllistselector.tcl
+    pxitclmanualsurfacetransformation.tcl
+    pxitclmousechopper.tcl
+    pxitclrpm.tcl
+    pxitclsplinestackobjectmap.tcl
+    pxitclvvlinkgadget.tcl
+    pxitclopenigtlinkgadget.tcl
+    pxitclmanualtransformation.tcl 
+    alarkutility.tcl
+    pxitclvvlinkprojectorgadget.tcl    
+)
+
+SET(KITAPPS
+    pxitcl4dsurfaceeditor.tcl
+    pxitclbaresimpleviewer.tcl
+    pxitclbrainregister.tcl
+    pxitclbrainsegment.tcl
+    pxitcldualmultisubject.tcl
+    pxitclelectrodeeditor.tcl
+    pxitclmouseregister.tcl
+    pxitclmousesegment.tcl
+    pxitclmultisubjectaverage.tcl
+    pxitclsimpleeditor.tcl
+    pxitclsimpleviewer.tcl
+    pxitclsplineeditor.tcl
+    pxitclsurfaceeditor.tcl
+    pxitclvolumeviewer.tcl
+    pxitclorthoviewer.tcl
+    bis.tcl
+    bis_fmrisetup.tcl
+    bis_fmri.tcl
+    bis_databasetool.tcl
+    alarkviewer.tcl
+    bis_parameterGUI.tcl
+    pxitclvvlinkviewer.tcl
+)
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+bis_complex_tcl(bioimagesuite/main ${FILELIST2} ${FILELIST})
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/alarkutility.tcl b/bioimagesuite30_src/bioimagesuite/main/alarkutility.tcl
new file mode 100644
index 0000000..0ddd1bd
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/alarkutility.tcl
@@ -0,0 +1,489 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+package provide alarkutility 1.0
+package require  Itcl 3.2
+package require  Iwidgets 4.0
+
+package require  pxitclbaseimagecontrol 1.0
+
+
+
+itcl::class alarkutility {
+
+
+    # derives from pxitclbaseimagecontrol
+
+    inherit pxitclbaseimagecontrol
+    protected common thisparam    
+
+    #-----------------------------------
+    # construction and descruction
+    #-----------------------------------
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } { InitializeControl }
+    
+    destructor { }
+
+    #-----------------------------------
+    # initialization methods
+    #-----------------------------------
+
+    # This must exist it creates the interface 
+    public method InitializeControl { }
+    public method Initialize { inpwidg }
+      
+    #-----------------------------------
+    # interface creation methods
+    #-----------------------------------
+    protected method CreateConnectivityControl { name }
+
+    # ----------------------------------
+    # Computational Utility Stuff
+    # ----------------------------------
+    public method CreateConnectivity { }
+    public method RenderGraph { alg ren red green blue size stippleStyle}
+
+    # ----------------------------------
+    # Add this control to a Menu Button
+    # ----------------------------------
+    public method AddToMenuButton { mb args }    
+
+}  
+
+#-------------------------------------------------------------------------------------------
+#  Initialize tool
+# -------------------------------------------------------------------------------------------
+itcl::body alarkutility::InitializeControl { } {
+
+    set appname "My Tool v1.0"
+    set aboutstring "(c)  2006"
+
+    set global_list(appname) "My Utility"
+    set global_list(radioselection) selected_positive
+
+
+    # All Parameters that need to be appear in the GUI need to be part of this array
+    # ------------------------------------------------------------------------------
+    set thisparam($this,radius) 10.0
+    set thisparam($this,lowerthreshold) 0.2
+    set thisparam($this,higherthreshold) 1.0
+    set thisparam($this,linewidth) 3.0
+    set thisparam($this,radiochoice) selected_positive
+    
+}
+
+itcl::body alarkutility::CreateConnectivity { } {
+
+    set sphere [ vtkSphereSource New ]
+    $sphere SetRadius $thisparam($this,radius)
+    $sphere SetCenter 100.0 100.0 0.0
+    $sphere Update
+
+    set map [ vtkPolyDataMapper New ]
+    $map SetInput [ $sphere GetOutput ]
+
+    set act [ vtkActor New ]
+    $act SetMapper $map
+    
+    
+	# Create a graph
+	set graph [ vtkGraph New]
+	$graph SetDirected 0
+
+	# Create points
+	set pts [vtkPoints New]
+	     
+	#puts "The input file name is [.fsb get]"
+	puts "in create connectivity selected $thisparam($this,radiochoice)"
+	
+    set inputfile [open [.fsb get] "r"]
+    gets $inputfile fileType
+        
+    set checkstring "#Connectivity file"
+    # trimright trims trailing white spaces
+	set filecheck [string compare [ string trimright $fileType ] $checkstring]   
+
+	if {$filecheck == 0} {
+		puts "Connectivity file loaded"
+	} else {
+		puts "Incorrect Connectivity File Format"
+		return
+	}
+    
+    gets $inputfile pointsType
+    #puts $pointsType
+    
+    gets $inputfile num_of_centroids
+    #puts "Number of points: $num_of_centroids"
+    
+    set nameArray [vtkStringArray New]
+    $nameArray SetName "name"
+       
+    for {set i 0} {$i < $num_of_centroids} {incr i} {
+	    #puts "testing $i" 
+	    gets $inputfile pt1
+		scan $pt1 "%d %f %f %f %s" index px py pz name_of_roi
+
+		set xval [expr {$px * 1.17}]
+		set yval [expr {$py * 1.17}]
+		set zval [expr {$pz * 1.17}]
+
+		$nameArray InsertNextValue $name_of_roi
+		
+		$graph AddVertex
+		$pts InsertNextPoint $xval $yval $zval
+
+    }    
+   
+    $graph SetPoints $pts
+    
+    [$graph GetVertexData] AddArray $nameArray    
+    
+    ## Process edges now 
+    
+    gets $inputfile connections
+    #puts $connections 
+    
+    gets $inputfile num_of_connections
+    puts $num_of_connections 
+    
+    set strength_array [vtkDoubleArray New]
+        
+    for {set i 0} {$i < $num_of_connections} {incr i} {
+   
+	   gets $inputfile edge_info
+	   scan $edge_info "%d %d %f" edge_src edge_dist edge_strength
+	   $graph AddEdge $edge_src $edge_dist 
+	   $strength_array InsertNextValue $edge_strength
+
+	}
+	
+  $strength_array SetName "value"
+  
+  [$graph GetEdgeData] AddArray $strength_array
+	
+	#puts "Testing threshold selection..." 
+	set threshold [vtkSelection New]
+	$threshold SetContentType 8
+	$threshold SetFieldType 0
+	
+	set thresholdArr [vtkDoubleArray New]
+	$thresholdArr SetName "value"
+	$thresholdArr InsertNextValue $thisparam($this,lowerthreshold)
+	$thresholdArr InsertNextValue $thisparam($this,higherthreshold)
+	
+	$threshold SetSelectionList $thresholdArr 
+	
+	set layout [vtkGraphLayout New]
+	$layout SetInput $graph
+	
+	set passthrough [vtkPassThroughLayoutStrategy New]
+  	$layout SetLayoutStrategy $passthrough 
+		
+	set extractThreshold [vtkExtractSelectedGraph New]
+	$extractThreshold SetInputConnection 0 [$layout GetOutputPort]	
+	$extractThreshold SetInput 1 $threshold	
+	
+	
+	# 2nd graph 
+	set threshold2 [vtkSelection New]
+		$threshold2 SetContentType 8
+		$threshold2 SetFieldType 0
+	
+		set thresholdArr2 [vtkDoubleArray New]
+		$thresholdArr2 SetName "value"
+		$thresholdArr2 InsertNextValue 0.0
+		$thresholdArr2 InsertNextValue 0.1
+		
+	$threshold2 SetSelectionList $thresholdArr2 
+	
+	set layout2 [vtkGraphLayout New]
+		$layout2 SetInput $graph
+		
+		set passthrough2 [vtkPassThroughLayoutStrategy New]
+	  	$layout2 SetLayoutStrategy $passthrough2 
+			
+		
+	set extractThreshold2 [vtkExtractSelectedGraph New]
+	$extractThreshold2 SetInputConnection 0 [$layout GetOutputPort]		
+	$extractThreshold2 SetInput 1 $threshold2
+
+	
+
+    # Getting the Images
+    # Two things
+
+    set viewer [ $parent GetViewer ]
+    puts stderr "Viewer = [ $viewer GetClassName ]"
+
+    set img $currentimage 
+    puts stderr "[$img GetDescription ]"
+
+    set imagedata [ $img GetImage ]
+    puts "ImageData = [ $imagedata  GetClassName ]"
+
+    set objectmap [ $viewer GetObjectMapImage ]
+    puts "ImageData = [ $objectmap  GetClassName ], [ [ [ $objectmap  GetPointData ] GetScalars] GetRange]"
+
+    # parent = master application
+    # the viewer
+ 
+    set guiren [ $viewer GetRenderer 3 ]
+    puts stderr "Viewer = [ $guiren GetClassName ]"
+
+    # Raw Viewer
+    set ren [ $guiren GetRenderer ]
+    puts stderr "Viewer = [ $ren GetClassName ]"
+
+	# Actor showing a small sphere 
+	# $ren AddActor $act
+	
+	# Grey lines
+	#RenderGraph $layout $ren 0.4 0.4 0.4 3.0 65535 
+	#RenderGraph $layout $ren 0.2 0.2 0.2 3.0 65535 
+		
+	RenderGraph $layout $ren 0.5 0.5 0.5 3.0 65535 
+	
+	RenderGraph $extractThreshold2 $ren 0.4 0.4 1.0 $thisparam($this,linewidth) 65535
+			
+	# Green stippled lines
+	#RenderGraph $extractThreshold $ren 0.8 1.0 0.2 $thisparam($this,linewidth) 61680
+	RenderGraph $extractThreshold $ren 1.0 0.4 0.4 $thisparam($this,linewidth) 65535
+	
+	#$ren AddActor $vertexActor
+	#$ren AddActor $edgeActor	    
+
+    $viewer  SetDisplayMode3D
+
+    $guiren Render
+
+}
+
+
+itcl::body alarkutility::RenderGraph { alg ren red green blue size stippleStyle} {
+	
+	 set centroid_sphere [vtkSphereSource New]
+	  $centroid_sphere SetRadius 4
+	  $centroid_sphere SetPhiResolution 12
+	  $centroid_sphere  SetThetaResolution 12 
+
+	set graphToPoly [vtkGraphToPolyData New]
+	$graphToPoly SetInputConnection [$alg GetOutputPort]
+	
+	set edgeMapper [vtkPolyDataMapper New]
+	$edgeMapper SetInputConnection [$graphToPoly GetOutputPort]
+	
+	set edgeActor [vtkActor New]
+	$edgeActor SetMapper $edgeMapper
+	[$edgeActor GetProperty] SetColor $red $green $blue
+  	[$edgeActor GetProperty] SetLineWidth $size
+ 	[$edgeActor GetProperty] SetLineStipplePattern $stippleStyle
+	[$edgeActor GetProperty] SetLineStippleRepeatFactor 2  	  	
+
+	set vertex [vtkGlyphSource2D New]
+	$vertex SetGlyphTypeToVertex
+	
+	set glyph [vtkGlyph3D New]
+	$glyph SetInputConnection 0 [$graphToPoly GetOutputPort]
+	$glyph SetInputConnection 1 [$centroid_sphere GetOutputPort]
+
+	set vertMapper [vtkPolyDataMapper New]
+	$vertMapper SetInputConnection [$glyph GetOutputPort]
+	
+	set vertActor [vtkLODActor New]
+	$vertActor SetMapper $vertMapper
+  	[$vertActor GetProperty] SetColor $red $green $blue
+  	#[$vertActor GetProperty] SetPointSize $size  	
+   
+  	 set labelMapper [vtkLabeledDataMapper New]
+	 $labelMapper SetInputConnection [$graphToPoly GetOutputPort]
+	 $labelMapper SetLabelFormat "%s"
+	 $labelMapper SetLabelModeToLabelFieldData	 
+ 	 $labelMapper SetFieldDataName "name"
+	 #[$labelMapper GetLabelTextProperty ] SetJustificationToLeft
+  	 #[$labelMapper GetLabelTextProperty ] SetColor 0 0 0  	 
+	 		
+	set labelActor [vtkActor2D New]
+	$labelActor SetMapper $labelMapper  	
+	
+	$ren AddActor $edgeActor;
+	$ren AddActor $vertActor
+	$ren AddActor $labelActor
+}
+
+
+# image is a vtkImageData Here !!!!
+# $this StoreResult [ $myfilter GetOutput ] somename someorientation
+
+itcl::body alarkutility::CreateConnectivityControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Parameters"
+    pack $base.frame0 -fill both -expand f -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    #iwidgets::entryfield $frame0.e -labeltext "Radius:" -textvariable [ itcl::scope thisparam($this,radius) ] -relief sunken -width 6 -validate real
+    #pack $frame0.e -side left -padx 2 -fill x -expand false
+     
+    iwidgets::entryfield $frame0.lt -labeltext "Lower threshold:" -textvariable [ itcl::scope thisparam($this,lowerthreshold) ] -relief sunken -width 6 -validate real
+    pack $frame0.lt -side left -padx 2 -fill x -expand false
+    
+    iwidgets::entryfield $frame0.gt -labeltext "Higher threshold:" -textvariable [ itcl::scope thisparam($this,higherthreshold) ] -relief sunken -width 6 -validate real
+    pack $frame0.gt -side left -padx 2 -fill x -expand false
+
+    iwidgets::entryfield $frame0.linewidth -labeltext "Line width:" -textvariable [ itcl::scope thisparam($this,linewidth) ] -relief sunken -width 6 -validate real
+    pack $frame0.linewidth -side bottom -padx 2 -fill x -expand false
+
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Parameters"
+    pack $base.frame1 -fill both -expand f -pady 5
+    
+    set frame1 [ $base.frame1 childsite ]
+        
+	iwidgets::radiobox $frame1.rb -labeltext "Size:" -labelpos nw  -command { puts "test" }
+	
+	
+	#-command { set global_list(radioselection) [$frame1.rb get] }
+	pack $frame1.rb -padx 4 -pady 4 -fill both
+
+	$frame1.rb add selected_positive -text "Positive" 
+	$frame1.rb add selected_negative -text "Negative"
+	$frame1.rb add selected_both -text "Both"
+
+	$frame1.rb select selected_positive
+	    
+    puts " selection [$frame1.rb get]"
+    
+	iwidgets::optionmenu $frame1.pos -labeltext "Position:" 
+	#-command {
+	#    .lw configure -labelpos [.pos get]
+	#}
+	pack $frame1.pos -padx 4 -pady 4
+	
+	$frame1.pos insert end e n ne nw s se sw w
+	$frame1.pos select w
+	
+    	
+	pack $frame1.rb -padx 10 -pady 10 -fill both -expand yes
+	
+	eval "button $base.but -text \"Show Connectivity\" -command { $this CreateConnectivity }"
+	pack $base.but -side bottom -expand t -fill x
+		
+	
+	iwidgets::extfileselectiondialog .fsb -modality application 	
+
+	button $base.select -text "Select Connectivity File" -command {
+		if {[.fsb activate]} {
+			puts "selected: [.fsb get]"	     
+		} else {
+			puts "no file selected" 
+		}
+	}
+		
+	puts "check box ? - [$frame1.pos get]"
+	
+	pack $base.select -side bottom -expand t -fill x
+		
+	iwidgets::optionmenu .cb -labeltext "Font:" -labelpos w -command {
+	    puts "selected: [.cb get]"
+	}
+	pack .cb
+	
+	.cb insert end Ariel Courier Helvetica Knarly Lucida \
+	    Rumpus Symbol Times "Zapf Dingbats"
+	     
+}
+
+# -------------------------------------------------------------------------------------------
+#  Diffusion control inititialization
+# ------------------------------------------------------------------------------------------
+itcl::body alarkutility::Initialize { widget } {
+    
+    if { $initialized == 1 } { return $basewidget }
+    
+    #  -------------------------------------
+    #  Create User Interface
+    #  -------------------------------------	
+    set basewidget [toplevel $widget ]
+    wm geometry $basewidget 610x450
+    wm withdraw $basewidget
+
+
+    set notebook $basewidget.notebook    
+    iwidgets::tabnotebook $notebook -tabpos w         
+    set widget_list(notebook) $notebook
+
+    set mb [ frame $basewidget.mb ]
+    pack $mb -side top -fill x -expand false
+    
+    #    CreateMenu $mb
+    CreateConnectivityControl    [ $notebook add -label "Add Connectivity" ] 
+    pack $notebook -side top -fill both -expand t -padx 5
+    
+     #option add *textBackground seashell
+
+    set initialized 1
+
+    SetTitle "Connection Utility"
+
+    # this is critical 
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget 
+}
+
+#-------------------------------------------------------------------------------------------
+#  Add controls to menu button
+# ------------------------------------------------------------------------------------------
+itcl::body alarkutility::AddToMenuButton { mb args } {
+    eval "$mb add command -label \"Add Connectivity\" -command {$this ShowWindow \"Add Connectivity\"}"   
+}
+
+#-------------------------------------------------------------------------------------------
+#  Main function for stand-alone execution
+# ------------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    puts "\n[ file rootname $argv0 ] is not a stand-alone program.\n"
+    exit
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/alarkviewer.tcl b/bioimagesuite30_src/bioimagesuite/main/alarkviewer.tcl
new file mode 100755
index 0000000..271cc15
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/alarkviewer.tcl
@@ -0,0 +1,81 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package require vtkpxcontrib  1.1
+package require pxtcluserprefs 
+package require pxitclbaseimageviewer 1.0
+package require alarkutility 1.0
+
+# Eliminate the default tk window
+wm withdraw .
+
+set breg [ pxitclbaseimageviewer \#auto 0 ]
+$breg configure -appname "BioImage Suite::Connectivity Tool"
+$breg configure -show_standard_images 1
+$breg configure -enable_helpmenu 0
+$breg configure -enable_multisubjectcontrol 0
+$breg configure -enable_overlaytool 0
+$breg configure -enable_vvlinkgadget  0
+$breg configure -enable_talaraichoption 0
+$breg configure -enable_internaleditor 1
+$breg configure -enable_objectmapmenu   1
+$breg configure -enable_rendering_on_startup  0
+$breg InitializeObjectmapViewer .[pxvtable::vnewobj ] 1
+
+
+set alarkutil [ alarkutility \#auto $breg ]
+$alarkutil Initialize [ $breg GetBaseWidget ].[ pxvtable::vnewobj ]
+
+set menubase [ $breg cget -menubase ]
+set mb [ menu $menubase.vesselm -tearoff 0  ]
+$menubase add cascade  -label "View connections" -menu $menubase.vesselm -underline 0
+
+$alarkutil AddToMenuButton $mb 
+
+$breg AddControl $alarkutil
+$breg CreateHelpMenu
+$breg ShowWindow   
+
+set argc [llength $argv]
+
+if { $argc > 0 } {   $breg LoadImage [lindex $argv 0]   }
+
+update idletasks
+[ $breg GetViewer ] SetEnableRendering 1
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/bis.tcl b/bioimagesuite30_src/bioimagesuite/main/bis.tcl
new file mode 100755
index 0000000..70307b5
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/bis.tcl
@@ -0,0 +1,411 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+# 	$Id: pxmenu.tcl,v 1.9 2005/12/02 14:22:45 xenios Exp xenios $	
+
+lappend auto_path [ file join [ file join [ file join  [ file dirname [ info script ]] .. ] base ]]
+lappend auto_path [ file join [ file join [ file join  [ file dirname [ info script ]] .. ] main ]]
+
+package require Iwidgets 
+package require md5
+package require pxtclutil 1.0
+
+
+package require vtkpxcontrib 1.0
+package require pxtcluserprefs 1.0
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ]]
+
+set location [ file normalize $::pxtclvtkpxcontrib::baselibrarypath  ]
+
+set helpdialog 0
+
+proc HelpCommand { } {
+
+    global helpdialog
+
+    if { $helpdialog != 0 } {
+	::pxtclutil::ShowWindow $helpdialog
+	return
+    }
+
+    set bname [ file normalize [ file join $::pxtclvtkpxcontrib::baselibrarypath  .. ] ]
+
+    set b(1) [ file join $bname html ]
+    set b(2) [ file join [ file join $bname .. ] build/html ]
+    set b(3) [ file join [ file join $bname .. ] build64/html ]
+
+    set i 1
+    set rootname 0
+    while { $i < 3 } {
+	set f [ file normalize [ file join $b($i) index.html ] ]
+#	puts stdout "Looking for $f"
+	if { [ file exists $f ] > 0 } {
+	    set i 4
+	    set rootname $f
+	}
+	incr i
+    }
+    
+    set w .
+    set helpdialog  [ toplevel .[ pxvtable::vnewobj ]]
+    wm geometry $helpdialog 800x600
+    
+    wm title $helpdialog "BioImage Suite Tools Manual Pages"
+    
+    set scr [ iwidgets::scrolledhtml $helpdialog.t  -labeltext "" \
+		  -width 6i -height 3i \
+		  -wrap word -padx 2 ]
+    $scr configure -fontsize large
+    
+    pack $scr -side top -expand true -fill both
+    #::bis_algorithm::SetWidgetTreeColors $scr "\#8197c5" white    
+       
+    if { $rootname != 0 } {
+	$scr import $rootname
+    } else {
+	$scr insert end "No Man Pages Found"
+    }
+    
+    ::pxtclutil::ShowWindow $helpdialog
+}
+
+proc MenuAboutCommand  { } { 
+    set version $::pxtclvtkpxcontrib::version
+    set aboutstring "(c) X. Papademetris, M. Jackowski, D. Scheinost, A. Joshi, I. Murphy, H.Okuda, R.T. Constable, L.H. Staib 1995-2011\nSection of Bioimaging Sciences, Department of Diagnostic Radiology, Yale University School of Medicine\n\n\nThis application is intended for research applications only! Use at your OWN RISK. If used for publication please acknowledge, see the webpage for more details. For additional support please visit the BioImage Suite forum at:\n\thttp://research.y [...]
+    tk_messageBox -title "About This Application" -type ok -message "$version\n $aboutstring"
+}
+
+proc MenuCheckForUpdates { } {
+    ::pxtclvtkpxcontrib::CheckForUpdates
+}
+
+
+proc MenuWhereCommand { } {
+    global location
+    tk_messageBox -title "Path" -type ok -message "$location\n"
+}
+
+
+proc ReturnPath { app directory } {
+
+    if { $app == "mpjdiffusiontool" || $app=="mpjvesseltool" || $app=="mpjfmmtool" } {
+	return [ file join $directory [ file join .. [ file join "mjack" ] ] ]
+    }
+
+    if { $app == "bis_treeapp" } {
+	return [ file join $directory [ file join .. [ file join "bis_algorithm" ] ] ]
+    } 
+
+    if { $app == "bis_dicom2nifti.tcl --dogui 1" } {
+	return [ file join $directory [ file join .. [ file join "bis_algorithm" ] ] ]
+    } 
+
+    if { $app == "bis_varian2nifti.tcl --dogui 1" } {
+	return [ file join $directory [ file join .. [ file join "bis_algorithm" ] ] ]
+    } 
+
+
+    if { $app =="biodatatree" } {
+	return [ file join $directory [ file join .. [ file join "datatree" ] ] ]
+    }
+
+
+
+    return $directory
+}
+
+# -------------------------------------------------------------------------
+
+proc CreateMenuPane { appname applabelname description basewidget directory } {
+ 
+
+    set notebook [ iwidgets::tabnotebook $basewidget.top  -tabpos w -width 510 -angle 10 -gap 2 -margin 2 -raiseselect true]
+    pack $notebook  -side top -expand t -fill both -padx 2 
+
+
+    for { set k 0 } { $k < [llength $appname ]  } { incr k } {
+	
+	set app [ lindex $appname $k ]
+	set applabel [ lindex $applabelname $k ]
+	set des [ lindex $description $k ]
+	set first [ string range $des 0 4 ]
+	if { $first == "None:" } {
+	    set name [ string range $des 5 end ]
+	    set base [ $notebook add -label $name ]
+	    if { $k ==0 } {
+		$notebook view $name 
+	    }
+	} else {
+	    set fr [ frame $base.$k ]
+	    pack $fr -side top -expand f -fill both -pady 1
+	    set dirname [ ReturnPath  $app $directory ]
+	    set lc  [ file normalize [ file join "$dirname" $app ] ]
+
+	    if { [ string first "--dogui" $lc ] == -1 } {
+		append lc ".tcl"
+		append app ".tcl"
+	    }
+
+
+	    frame $fr.top
+
+	    set b [eval "button $fr.top.b -text \"$applabel\" -fg red -font { times 12 } -bg white -width 30 -command { catch { exec [info nameofexecutable] ${lc} & } }"]
+	    set b2 [eval "button $fr.top.b2 -text \"?\"  -width 1 -command { tk_messageBox -type ok -message \"To execute this program on the command line: type ${app}\" -title \"Command Line Information\" -icon info} "]
+	    pack $b2 -side right -expand false -padx 5
+	    pack $b -side top -expand false -padx 20
+	    
+	    set a [ text $fr.t  -width 80 -height 2 -wrap word -relief flat ]
+	    $a insert end $des
+	    $a configure -state disabled
+	    set c [ frame $fr.m -bg black -height 2 ]
+	    pack $c -side bottom -expand f -fill x -pady 4
+	    pack $fr.top -side top -expand true -fill x
+	    pack  $a -side top -expand f -fill x -padx 2
+	    
+	}
+    }
+}
+
+# -------------------------------------------------------------------------
+proc CreateNewApps { basewidget } {
+
+    set directory  [ file dirname [info script ]]
+
+    set appname ""
+    set applabelname ""
+    set description ""
+
+    lappend appname  "General Viewers"
+    lappend applabelname  "General Viewers"
+    lappend description  "None:General"
+
+    lappend appname  "pxitclsimpleviewer"
+    lappend applabelname  "Mosaic Viewer"
+    lappend description "Simple Multi-slice/Multi-frame viewer which can display multiple slices at once."
+    
+    lappend appname  "pxitclorthoviewer"
+    lappend applabelname  "Orthogonal Viewer"
+    lappend description "Orthogonal 3D Viewer with functions for image pre-processing"
+
+    lappend appname  "pxitclbrainregister"
+    lappend applabelname  "Brain Register"
+    lappend description "Coupled 3D Orthogonal viewers with access to image registration facilities"
+
+    lappend appname  "pxitcldualmultisubject"
+    lappend applabelname  "Dual MultiSubject"
+    lappend description "Multiple (2) Group Comparisons"
+
+
+
+    if { ( [ file exists [file join $directory "../mjack/mpjdiffusiontool.tcl" ] ] !=0 ) } {
+	
+	lappend appname "Diffusion Tensor/Angiography"
+	lappend applabelname "Diffusion Tensor/Angiography"
+	lappend description "None:DTI/Angiography"
+	
+	lappend appname "mpjdiffusiontool"
+	lappend applabelname "Diffusion Tool"
+	lappend description "Orthogonal 3D viewer with access to diffusion tensor processing, analysis and fiber tracking"
+
+	if { ( [ file exists [file join $directory "../mjack/mpjvesseltool.tcl" ] ] !=0 ) } {
+
+	    lappend appname "mpjvesseltool"
+	    lappend applabelname "Vessel Tool"
+	    lappend description "Orthogonal 3D viewer with vessel enhancement, tracking and analysis"
+	}
+	
+	if { ( [ file exists [file join $directory "../mjack/mpjfmmtool.tcl" ] ] !=0 ) } {
+	    lappend appname "mpjfmmtool"
+	    lappend applabelname "FMM Tool"
+	    lappend description "Fast Marching Tool with support for generic speed images"
+	}
+
+    }
+
+    lappend appname "FMRI/Statistical Analysis"
+    lappend applabelname "FMRI/Statistical Analysis"
+    lappend description "None:fMRI"
+
+    lappend appname "bis_fmri"
+    lappend applabelname "fMRI Single Subject Analyzer"
+    lappend description "Tool for running single subject GLM analysis as well as interface to AFNI (Also part of Brain Register)"
+
+    set f [file join $directory "../vtknr/nritclmultisubject.tcl" ]
+    if {  [ file exists $f ]  } {
+	lappend appname "nritclmultisubject"
+	lappend applabelname "fMRI Multi-Subject Analyzer"
+	lappend description "fMRI Analysis/Multi Subject Statistical Analysis Tool -- this is provided as a preview only."
+    }
+
+   
+    lappend appname  "Surface/Objectmap Editors"
+    lappend applabelname  "Surface/Objectmap Editors"
+    lappend description  "None:Editors"
+    
+    #    lappend appname  "pxitclobjectmapeditor"
+    #   lappend description "Multi-Slice editor (2D View only) with the ability to edit splines/color regions on image slices."
+
+    lappend appname  "pxitclsurfaceeditor"
+    lappend applabelname  "Surface Editor"
+    lappend description "3D Surface/Objectmap Editor"
+
+    lappend appname  "pxitclsimpleeditor"
+    lappend applabelname  "Mosaic Objectmap Editor"
+    lappend description "MultiSlice Objectmap Editor"
+
+    lappend appname  "pxitclbrainsegment"
+    lappend applabelname  "Orthogonal Objectmap Editor"
+    lappend description "Orthogonal Slice Objectmap Editor"
+
+    lappend appname  "pxitclelectrodeeditor"
+    lappend applabelname  "Electrode Editor"
+    lappend description "Intracranial Electrode Localizer/Editor."
+
+    lappend appname  "4D Dataset processing (cardiac)"
+    lappend applabelname  "4D_Dataset_Processing"
+    lappend description  "None:Cardiac"
+
+    lappend appname  "pxitclvolumeviewer"
+    lappend applabelname  "4D Volume Viewer"
+    lappend description "Orthogonal 3D Viewer with ability to display volumes and cine-loops of multi-frame images"
+
+    lappend appname  "pxitcl4dsurfaceeditor"
+    lappend applabelname  "4D Surface Editor"
+    lappend description "4D Multi-Slice editor (cardiac specific)"
+
+
+    lappend appname "Data Tree Tool"
+    lappend applabelname "DataTree Tool"
+    lappend description "None:Data Tree"
+    
+    if { ( [ file exists [file join $directory "../datatree/biodatatree.tcl" ] ] !=0 ) } {
+	lappend appname "biodatatree"
+	lappend applabelname "Data Tree Manager"
+	lappend description "Database tree front end with additional capabilities"
+    }
+
+    lappend appname "bis_treeapp"
+    lappend applabelname "Data Tree Manager v2"
+    lappend description "Database tree front end with additional capabilities -- enhanced"
+
+    global pxtcl_pref_array
+    if { $pxtcl_pref_array(VectorVisionLink)=="Enabled" } {
+	lappend appname "VVLink"
+	lappend applabelname "VVLink Tool"
+	lappend description "None:VVLink"
+	
+	lappend appname  "pxitclvvlinkviewer"
+	lappend applabelname  "Viewer for VVLink/Slicer Integration"
+	lappend description "Reduced Functionality App for Slicer/VVLink Integration"
+    }
+
+    lappend appname "Mouse Image Analysis"
+    lappend applabelname "Mouse Image Analysis"
+    lappend description "None:MouseSuite"
+    
+    lappend appname "pxitclmousesegment"
+    lappend applabelname "Mouse Segment"
+    lappend description "Orthogonal 3D viewer with mouse segmentation functionality"
+
+    lappend appname "pxitclmouseregister"
+    lappend applabelname "Mouse Register"
+    lappend description "Dual Orthogonal 3D viewer with mouse registration/segmentation functionality"
+
+    lappend appname  "Utilities"
+    lappend applabelname  "Image File Conversion"
+    lappend description  "None:File Conversion Utilities"
+    
+    lappend appname "bis_dicom2nifti.tcl --dogui 1"
+    lappend applabelname "Dicom2NIFTI"
+    lappend description "Convert Images from DICOM to NIFTI"
+
+    lappend appname "bis_varian2nifti.tcl --dogui 1"
+    lappend applabelname "Varian2NIFTI"
+    lappend description "Convert Images from Varian file format to NIFTI"
+
+
+    CreateMenuPane $appname $applabelname $description $basewidget $directory
+
+}
+# -------------------------------------------------------------------------
+
+if { $tcl_platform(platform) != "windows" } { 
+    wm iconbitmap .  @$::pxtclvtkpxcontrib::bioimagesuiteicon 
+}
+
+
+frame .bottom
+pack .bottom -side bottom -fill x -expand f
+
+frame .top; pack .top -side top -fill x -expand f -padx 4
+
+label .top.b -image $::pxtclvtkpxcontrib::logo -width 510
+pack  .top.b -side left -expand t -fill x 
+
+frame .topa -bg black -height 2
+pack .topa -padx 4 -expand f -fill x -pady 2
+
+
+frame .middle
+pack .middle -side top -expand true -fill both -padx 1 -pady 1
+#. configure -background darkblue
+
+CreateNewApps .middle
+
+set pref_dialog [ ::pxtcluserprefs::CreatePreferenceEditor ]
+
+button .bottom.about -text "About!" -command MenuAboutCommand
+button .bottom.upd -text "Check for Updates" -command MenuCheckForUpdates
+button .bottom.here  -text "Which" -command MenuWhereCommand
+button .bottom.pref  -text "Preferences" -command { wm deiconify $pref_dialog}
+button .bottom.pref2  -text "Command Line Tools" -command { HelpCommand }
+button .bottom.exit  -text "Exit!" -command exit
+pack   .bottom.about .bottom.upd  .bottom.here .bottom.pref .bottom.pref2 .bottom.exit -side left -padx 5 -expand t -fill x
+
+
+wm geometry . 650x520
+set version $::pxtclvtkpxcontrib::version
+
+
+wm title . $version
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/bis_databasetool.tcl b/bioimagesuite30_src/bioimagesuite/main/bis_databasetool.tcl
new file mode 100755
index 0000000..7f4ac2b
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/bis_databasetool.tcl
@@ -0,0 +1,1717 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#---------------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+package provide bis_databasetool 1.0
+
+package require vtkpxcontrib 1.0
+package require pxvtable 1.0
+package require pxtclhelp  1.0
+package require pxtclutil  1.0
+package require pxitclimage  1.0
+package require Iwidgets 4.0
+package require pxitclbasecontrol 
+package require  labelframe 1.0
+# This loads the database library
+
+
+# --------------------------------------------------------------------------
+
+itcl::class bis_databasetool {
+    
+    inherit pxitclbasecontrol
+
+
+    protected variable database 0
+    protected variable initialized 0
+    protected variable standalone  0
+    protected variable orthoviewer 0
+    protected variable seriesnameindex -1
+    protected variable seriespathindex -1
+    protected common   thisparam
+
+    constructor { par } {
+	::pxitclbasecontrol::constructor $par
+    } {
+	$this Initialize
+    }
+
+    public method GetThisPointer { } { return $this }
+    public method InitializeGUI { parent { standalone 0 } }
+    
+    public method Initialize { }
+    public method ResetValues { }
+    public method MySQLConnect { }
+    public method SQLiteConnect { { fname "" } }
+    public method SQLiteCreate  { { fname "" } }
+    public method Disconnect { }
+    public method loadImage { } 
+    public method loadImage2 { } 
+    public method loadImageFileName { fname }
+    public method loadDICOMImage { fpath }
+    public method searchImage {} 
+    public method addPatient {} 
+    public method clearPatient {} 
+
+    public method addProtocol {} 
+    public method clearProtocol {} 
+
+
+    public method searchPatient {} 
+    public method selectPatient { } 
+    public method searchProtocol {} 
+    public method selectProtocol { }
+    public method addVisit {} 
+    public method searchVisit {} 
+    public method selectVisit { } 
+    public method addSeries {} 
+    public method browse { } 
+
+    # New Query Stuff 31 Oct 2008
+    #
+
+
+    protected method beuatifyQuery { inp }
+    public method searchSavedQuery { }
+    public method selectSavedQuery { }
+    public method runSavedQuery { } 
+    public method abbreviation { input }
+
+    # ----------------------------------
+    # GUI Stuff
+    # ----------------------------------
+    protected method CreateServerGUI { base } 
+    protected method CreateQueryGUI { base } 
+    protected method CreatePatientGUI { base } 
+    protected method CreateProtocolGUI { base } 
+    protected method CreateVisitGUI { base } 
+    protected method CreateSeriesGUI { base } 
+    protected method CreateQueryQueryGUI { qframe } 
+
+};
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::Initialize { } {
+
+    # Server Info
+    # ---------------
+
+    set thisparam($this,username) ""
+    set thisparam($this,password) ""
+    set thisparam($this,host) ""
+    set thisparam($this,database) "haven"
+    set thisparam($this,port) "3306"
+    set thisparam($this,connected) 0
+    set thisparam($this,connectionstatus) "Not Connected"
+    set thisparam($this,sqlitefile) ""
+    set thisparam($this,debugdbase) 0
+
+    global env
+
+    set fname [ file join $env(HOME) ".my.cnf" ]
+    if { [ file exists $fname ] } {
+	set fin [ open $fname r ]
+	while { [ gets $fin line ] >=0 } {
+	    set lst [ split $line = ]
+	    if { [ llength $lst ] == 2 } {
+		set first [ string trim [ lindex $lst 0 ]]
+		set second [ string trim [ lindex $lst 1 ]]
+		if { $first == "user" } {
+		    set thisparam($this,username) $second
+		} elseif { $first == "password" } {
+		    set thisparam($this,password) $second
+		} elseif { $first == "host" } {
+		    set thisparam($this,host) $second
+		    if { $second == "centos5db" || $second == "192.168.0.111" } {
+			set thisparam($this,database) "YaleTest" 
+		    }
+		}
+	    }
+	}
+	close $fin
+    }
+    $this ResetValues
+}
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::ResetValues {} {
+
+    set thisparam($this,firstname) ""
+    set thisparam($this,lastname)  ""
+    set thisparam($this,birthdate) ""
+    set thisparam($this,protocolname) ""
+    set thisparam($this,pi) ""
+    set thisparam($this,visitdate) ""
+    set thisparam($this,seriesdatapath) ""
+    set thisparam($this,seriesfilename) ""
+}
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::MySQLConnect {} {
+    
+
+    if { $thisparam($this,connected) == 1 } {
+	tk_messageBox -type ok -message "Already Connected to a database" -title "Error" -icon error
+	return
+    }
+
+    set dbname    $thisparam($this,database) 
+    set host      $thisparam($this,host) 
+    set port      $thisparam($this,port)
+    set username  $thisparam($this,username)
+    set password  $thisparam($this,password)
+
+    if { $database == 0 } {
+	set database [ vtkbisDatabase New ]
+    }
+    $database Initialize $dbname $host $username $password $port
+
+    set connect [ $database Connect ]
+
+    if { $connect == "1" } {
+	tk_messageBox -type ok -message "Login to database successfully" -title "OK" -icon info
+	set thisparam($this,connectionstatus) "Connected to server ${host}:$port as $username"
+	set thisparam($this,connected) 1
+    } else {
+	tk_messageBox -type ok -message "Fail to login to database" -title "Error" -icon error
+	set thisparam($this,connected) 0
+	set thisparam($this,connectionstatus) "Not Connected"
+    }
+    wm title $basewidget "BioImage Suite::Database Control $thisparam($this,connectionstatus)"
+
+    if { $thisparam($this,debugdbase) == 1 } {
+	puts stderr "Setting Debug Mode = ON"
+	$database DebugOn
+
+    } else {
+	$database DebugOff
+	puts stderr "Setting Debug Mode = OFF"
+    }
+}
+
+itcl::body bis_databasetool::SQLiteCreate { { fname "" } } { 
+
+    if { $thisparam($this,connected) == 1 } {
+	tk_messageBox -type ok -message "Already Connected to a database" -title "Error" -icon error
+	return
+    }
+
+    if { $fname == "" } {
+	set typelist { {"SQLite Files" { .sqlite }}}
+	set fname [tk_getSaveFile -title "Specify an SQLite Filename" -filetypes $typelist -initialfile $thisparam($this,sqlitefile) ]
+    }
+    if { [ string length $fname ] < 1 } {
+	return 
+    }
+
+
+    set iname [ file join $::pxtclvtkpxcontrib::imagedir sampledatabase.sqlite ]
+    set ok [ file copy -force $iname $fname ]
+
+    if { $ok == 0 } {
+	tk_messageBox -type ok -message "Cannot create $fname" -title "Error" -icon error
+	return 0
+    }
+    puts stderr "ok=$ok"
+
+    return [ $this SQLiteConnect $fname ]
+
+}
+
+
+itcl::body bis_databasetool::SQLiteConnect { { fname "" } } { 
+    
+    if { $thisparam($this,connected) == 1 } {
+	tk_messageBox -type ok -message "Already Connected to a database" -title "Error" -icon error
+	return
+    }
+
+    if { $fname == "" } {
+	set typelist { {"SQLite Files" { .sqlite }}}
+	lappend typelist {"All Files" {*}}
+
+	set fname [tk_getOpenFile -title "Specify an SQLite Filename" -filetypes $typelist -initialfile $thisparam($this,sqlitefile) ]
+    }
+    if { [ string length $fname ] < 1 } {
+	return 
+    }
+
+    if { [ file exists $fname ] == 0 } {
+	return
+    }
+
+    if { $database == 0 } {
+	set database [ vtkbisDatabase New ]
+    }
+
+    if { $thisparam($this,debugdbase) == 1 } {
+	puts stderr "Setting Debug Mode = ON"
+	$database DebugOn
+    } else {
+	puts stderr "Setting Debug Mode = OFF"
+	$database DebugOff
+    }
+
+
+    $database InitializeSQLite $fname
+
+    set connect [ $database Connect ]
+
+    if { $connect == "1" } {
+	tk_messageBox -type ok -message "Connected to database successful" -title "OK" -icon info
+	set thisparam($this,connectionstatus) "Connected to sqlite file $fname"
+	set thisparam($this,connected) 1
+    } else {
+	tk_messageBox -type ok -message "Fail to to access database file" -title "Error" -icon error
+	set thisparam($this,connected) 0
+	set thisparam($this,connectionstatus) "Not Connected"
+    }
+    set thisparam($this,sqlitefile) $fname
+
+    wm title $basewidget "BioImage Suite::Database Control $thisparam($this,sqlitefile)"
+}
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::Disconnect {} {
+    
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Not connected to a database" -title "Error" -icon error
+	return 
+    }
+
+    catch { $database Disconnect }
+    set thisparam($this,connected) 0
+    set thisparam($this,connectionstatus) "Not Connected"
+    wm title $basewidget "BioImage Suite::Database Control $thisparam($this,connectionstatus)"
+
+    return
+
+}
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::loadDICOMImage { filepath } {
+
+    
+    set namelist [ lsort [ glob [ file join ${filepath} *.dcm ]] ]
+    if { [ llength $namelist ] < 1 } {
+	return 0
+    }
+    
+    set fname [ lindex $namelist 0 ]
+
+    if { $standalone == 1 } {
+	set timg [ [ pxitclimage \#auto ] GetThisPointer ]
+	$timg LoadDICOM $fname 1 $parent 
+	
+	set img [ $timg GetImage ]
+	if { [ $img  GetNumberOfPoints ] >  1 } {
+	    $orthoviewer SetImage $img [  $timg GetOrientation ]
+	    wm title $basewidget [ file tail $fname ]
+	    $notebook view "Viewer"
+	}
+	itcl::delete obj $timg
+	return 1
+    }  else {
+	return [ $parent LoadImage $fname ]
+    }
+    
+}
+# ------------------------------------------------------------------------------------
+
+itcl::body bis_databasetool::loadImage2 { } {
+
+    set name [ $thisparam($this,savequeryframe2_querylist) getcurselection ]
+
+    set tmp  [ split $name | ]
+    set n    [ llength $tmp ]
+
+    if { $seriesnameindex == -1 } {
+	set filename [ lindex $tmp [ expr $n -2 ]]
+    } else {
+	set filename [ lindex $tmp $seriesnameindex ]
+    }
+
+    if { $seriespathindex == -1 } {
+	set filepath [ lindex $tmp [ expr $n -1 ]]
+    } else {
+	set filepath [ lindex $tmp $seriespathindex ] 
+    }
+
+    puts stderr "Filename = $filename, filepath=$filepath"
+
+ 
+    if { $filename == "" } {
+	puts stderr "DICOM ... empty filename"
+	return [ $this loadDICOMImage $filepath ]
+    }
+
+    set fname [ file join $filepath $filename ]
+   
+    return [ $this loadImageFileName $fname ]
+}
+
+itcl::body bis_databasetool::loadImage { } {
+
+    set name [ $thisparam($this,optframe_querylist) getcurselection ]
+    
+    set tmp  [ split $name | ]
+    set n    [ llength $tmp ]
+
+    set filename [ lindex $tmp [ expr $n -2 ]]
+    set filepath [ lindex $tmp [ expr $n -1 ]]
+
+    if { $filename == "" } {
+	#puts stderr "DICOM ... empty filename"
+	return [ $this loadDICOMImage $filepath ]
+    }
+
+    set fname [ file join $filepath $filename ]
+
+
+    return [ $this loadImageFileName $fname  ]
+}
+
+itcl::body bis_databasetool::loadImageFileName { fname } {
+
+    if { $standalone == 1 } {
+	set ana  [ vtkpxAnalyzeImageSource New ]
+	$ana Load $fname
+	
+	set img [ $ana GetOutput ]
+	if { [ $img  GetNumberOfPoints ] >  1 } {
+	    $orthoviewer SetImage [ $ana GetOutput ] [ $ana GetOrientation ]
+	    wm title $basewidget [ file tail $fname ]
+	    $notebook view "Viewer"
+	}
+	$ana Delete
+	return
+    }
+    
+    $parent LoadImage $fname
+}
+
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::searchImage {} {
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Please Connect To Server First Before trying to Execute a Query" -title "Error!" -icon error
+	return
+    }
+    
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+    }
+
+    set firstname $thisparam($this,firstname)
+    set lastname $thisparam($this,lastname)  
+    set birthdate $thisparam($this,birthdate)
+    set protocolname $thisparam($this,protocolname)
+    set pi $thisparam($this,pi)
+    set visitdate $thisparam($this,visitdate)
+    set seriesdatapath $thisparam($this,seriesdatapath)
+    set seriesfilename $thisparam($this,seriesfilename)
+
+    # Create Database Connector
+    set  sqlstring "select Patient.Firstname, Patient.Lastname, Patient.Birthdate, Protocol.protocolname, "
+    append sqlstring "Protocol.Pi, Visit.Visitdate, Series.SeriesFileName, Series.seriesdatapath "
+    append sqlstring "from Series,Injection,Visit,Protocol,Patient "
+    append sqlstring "where Series.injectionid=Injection.injectionid and Injection.visitid=Visit.visitid "
+    append sqlstring "and Visit.patientid=Patient.patientid and Visit.protocolid=Protocol.protocolid "
+    append sqlstring "and Patient.firstname like '%"
+    append sqlstring $firstname
+    append sqlstring "%' "
+    append sqlstring "and Patient.lastname like '%"
+    append sqlstring $lastname
+    append sqlstring "%' "
+    append sqlstring "and Patient.birthdate like '%"
+    append sqlstring $birthdate
+    append sqlstring "%' "
+    append sqlstring "and Protocol.protocolname like '%"
+    append sqlstring $protocolname
+    append sqlstring "%' "
+    append sqlstring "and Protocol.pi like '%"
+    append sqlstring $pi
+    append sqlstring "%' "
+    append sqlstring "and Visit.visitdate like '%"
+    append sqlstring $visitdate
+    append sqlstring "%' "
+    append sqlstring "and Series.seriesdatapath like '%"
+    append sqlstring $seriesdatapath
+    append sqlstring "%' "
+    append sqlstring "and (Series.seriesfilename like '%"
+    append sqlstring $seriesfilename
+    append sqlstring "%' or Series.seriesfilename is null) "
+
+    if { ![ $database Connect ]} {
+  	puts "Cannot connect to database. Exit."
+  	pxtkexit
+    }
+
+    $thisparam($this,optframe_querylist) delete 0 end
+
+    set query [ $database RunComplexQuery $sqlstring ]
+    set i 0
+    while {[$query NextRow]} {
+  	set i [expr $i +1 ]
+  	set firstname [ $database GetQueryValueAsString $query 0 ] 
+  	set lastname [ $database GetQueryValueAsString $query 1 ] 
+  	set birthdate [ $database GetQueryValueAsString $query 2 ] 
+  	set protocolname [ $database GetQueryValueAsString $query 3 ] 
+  	set pi [ $database GetQueryValueAsString $query 4 ] 
+  	set visitdate [ $database GetQueryValueAsString $query 5 ] 
+  	set seriesfilename [ $database GetQueryValueAsString $query 6 ] 
+	set seriesdatapath [ $database GetQueryValueAsString $query 7 ] 
+
+  
+	set record "$i|$firstname|$lastname|$birthdate|$protocolname|$pi|$visitdate|$seriesfilename|$seriesdatapath"
+	set rf  $thisparam($this,optframe_rf)
+	$rf.result insert end $record
+    }
+}
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::addPatient {} {
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Please Connect To Server First Before trying to Execute a Query" -title "Error!" -icon error
+	return
+    }
+
+    set thisparam($this,namelist) { { FirstName firstname } { LastName lastname } { BirthDate birthdate } }
+
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	if { $thisparam($this,$field) == "" } {
+	    tk_messageBox -type ok -message "Parameter $label not set" -title "Error!" -icon error
+	    return
+	}
+    }
+
+    set firstname $thisparam($this,firstname)
+    set lastname $thisparam($this,lastname)  
+    set birthdate $thisparam($this,birthdate)
+
+    set match [ regexp {\d\d\d\d-\d\d-\d\d} $thisparam($this,birthdate) ]
+    if { $match == "0" } {
+      tk_messageBox -type ok -message "BirthDate in wrong format yyyy-yy-yy" -title "Error!" -icon error
+      return
+    }
+
+    # Create Database Connector
+    set patient [ vtkbisPatient New ]
+    $patient Initialize $firstname $lastname $birthdate 
+
+    puts stderr "Setting Connector [ $database GetClassName ], [ $database GetMode ]"
+
+    $patient SetConnector $database
+    set ok [ $patient AddPatient ]
+    if { $ok == "0" } {
+      tk_messageBox -type ok -message "Patient exists, not add again." -title "Error!" -icon error
+      return
+    }
+
+    puts stderr "\n\n\n --------------------------- this far OK ----------------------------------\n"
+
+    set patientid [ $patient SearchPatientID $firstname $lastname $birthdate ]
+    $patient Delete
+    #    $patient SetPatientID $patientid
+    tk_messageBox -type ok -message "Patient was added as patientid $patientid" -title "OK" -icon info
+    
+}
+
+
+itcl::body bis_databasetool::clearPatient {} {
+    set thisparam($this,firstname) ""
+    set thisparam($this,lastname)   ""
+    set thisparam($this,birthdate) ""
+
+}
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::addProtocol {} {
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Please Connect To Server First Before trying to Execute a Query" -title "Error!" -icon error
+	return
+    }
+
+    set thisparam($this,namelist) { { ProtocolName protocolname } { Pi pi } }
+
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	if { $thisparam($this,$field) == "" } {
+	    tk_messageBox -type ok -message "Parameter $label not set" -title "Error!" -icon error
+	    return
+	}
+    }
+
+    set protocolname $thisparam($this,protocolname)
+    set pi $thisparam($this,pi)  
+
+    
+    set protocol [ vtkbisProtocol New ]
+    $protocol SetConnector $database
+    $protocol SetProtocolName $protocolname
+    $protocol SetPI $pi
+
+    set protocolid [ $protocol SearchProtocolID $protocolname $pi ]
+    $protocol SetProtocolID $protocolid
+    if { [ string length $protocolid ] ==0 } {
+	puts stderr "Going to Add Protocol"
+	$protocol AddProtocol
+	puts stderr " Protocol added going back to get the true id"
+   	set protocolid [ $protocol SearchProtocolID $protocolname $pi ]
+        tk_messageBox -type ok -message "Protocol was added as protocolid $protocolid" -title "OK" -icon info
+    } else {
+        tk_messageBox -type ok -message "Protocol exists, not add again" -title "Error!" -icon error
+    }
+    $protocol Delete
+}
+
+itcl::body bis_databasetool::clearProtocol {} {
+    set thisparam($this,protocolname) ""
+    set thisparam($this,pi)   ""
+}
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::searchPatient {} {
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Please Connect To Server First Before trying to Execute a Query" -title "Error!" -icon error
+	return
+    }
+    
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+    }
+    set firstname $thisparam($this,firstname)
+    set lastname $thisparam($this,lastname)  
+    set birthdate $thisparam($this,birthdate)
+    set patientid ""
+
+    
+    set  sqlstring "select PatientID, Firstname, Lastname, Birthdate from Patient "
+    append sqlstring "where firstname like '%"
+    append sqlstring $firstname
+    append sqlstring "%' "
+    append sqlstring "and lastname like '%"
+    append sqlstring $lastname
+    append sqlstring "%' "
+    append sqlstring "and birthdate like '%"
+    append sqlstring $birthdate
+    append sqlstring "%' "
+
+    $thisparam($this,visitframe1_querylist) delete 0 end
+    set query [ $database RunComplexQuery $sqlstring ]
+    set i 0
+    while {[$query NextRow]} {
+  	set i [expr $i +1 ]
+ 	set patientid [ $database GetQueryValueAsString $query 0 ] 
+  	set firstname [ $database GetQueryValueAsString $query 1 ] 
+  	set lastname [ $database GetQueryValueAsString $query 2 ] 
+  	set birthdate [ $database GetQueryValueAsString $query 3 ] 
+	set record "$i|$patientid|$firstname|$lastname|$birthdate"
+	set rf $thisparam($this,visitframe1_rf)
+	$rf.result insert end $record
+    }
+}
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::selectPatient { } {
+
+    set name [ $thisparam($this,visitframe1_querylist) getcurselection ]
+    set tmp  [ split $name | ]
+    set patientid [ lindex $tmp 1 ]
+    set thisparam($this,patientid) $patientid
+    tk_messageBox -type ok -message "You select PatientID $patientid" -title "OK" -icon info
+    set thisparam($this,patientid_selected) 1
+}
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::searchProtocol {} {
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Please Connect To Server First Before trying to Execute a Query" -title "Error!" -icon error
+	return
+    }
+    
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+    }
+    set protocolname $thisparam($this,protocolname)
+    set pi $thisparam($this,pi)  
+    set protocolid ""
+
+    
+    set  sqlstring "select ProtocolID, ProtocolName, PI from Protocol "
+    append sqlstring "where protocolname like '%"
+    append sqlstring $protocolname
+    append sqlstring "%' "
+    append sqlstring "and pi like '%"
+    append sqlstring $pi
+    append sqlstring "%' "
+
+    $thisparam($this,visitframe2_querylist) delete 0 end
+    set query [ $database RunComplexQuery $sqlstring ]
+    set i 0
+    while {[$query NextRow]} {
+  	set i [expr $i +1 ]
+ 	set protocolid [ $database GetQueryValueAsString $query 0 ] 
+  	set protocolname [ $database GetQueryValueAsString $query 1 ] 
+  	set pi [ $database GetQueryValueAsString $query 2 ] 
+	set record "$i|$protocolid|$protocolname|$pi"
+	set rf $thisparam($this,visitframe2_rf)
+	$rf.result insert end $record
+    }
+}
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::selectProtocol { } {
+
+    set name [ $thisparam($this,visitframe2_querylist) getcurselection ]
+    set tmp  [ split $name | ]
+    set protocolid [ lindex $tmp 1 ]
+    set thisparam($this,protocolid) $protocolid
+    tk_messageBox -type ok -message "You select ProtocolID $protocolid" -title "OK" -icon info
+    set thisparam($this,protocolid_selected) 1
+}
+
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::addVisit {} {
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Please Connect To Server First Before trying to Execute a Query" -title "Error!" -icon error
+	return
+    }
+    if { $thisparam($this,patientid_selected) == 0 } {
+	tk_messageBox -type ok -message "Please Select Patient first" -title "Error!" -icon error
+	return
+    }
+    if { $thisparam($this,protocolid_selected) == 0 } {
+	tk_messageBox -type ok -message "Please Select Protocol first" -title "Error!" -icon error
+	return
+    }
+
+    set thisparam($this,namelist) { { VisitDate visitdate } }
+    
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	if { $thisparam($this,$field) == "" } {
+	    tk_messageBox -type ok -message "Parameter $label not set" -title "Error!" -icon error
+	    return
+	}
+    }
+    set match [ regexp {\d\d\d\d-\d\d-\d\d} $thisparam($this,visitdate) ]
+    if { $match == "0" } {
+      tk_messageBox -type ok -message "VisitDate in wrong format" -title "Error!" -icon error
+      return
+    }
+
+    set patientid $thisparam($this,patientid)
+    set protocolid $thisparam($this,protocolid)  
+    set visitdate $thisparam($this,visitdate)
+
+    set visit [ vtkbisVisit New ]
+    $visit SetConnector $database
+    $visit SetPatientID $patientid
+    $visit SetProtocolID $protocolid
+    $visit SetVisitDate $visitdate
+    set visitid [ $visit SearchVisitID $patientid $protocolid $visitdate ]
+    $visit SetVisitID $visitid
+    if { [  string length $visitid ] ==0 } {
+	$visit AddVisit 
+  	set visitid [ $visit SearchVisitID $patientid $protocolid $visitdate ]
+ 	$visit SetVisitID $visitid
+	tk_messageBox -type ok -message "Visit was added as visitid $visitid" -title "OK" -icon info
+
+    } else {
+        tk_messageBox -type ok -message "Visit exists, not add again" -title "Error!" -icon error
+    }
+
+}
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::searchVisit {} {
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Please Connect To Server First Before trying to Execute a Query" -title "Error!" -icon error
+	return
+    }
+    
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+    }
+    set firstname $thisparam($this,firstname)
+    set lastname $thisparam($this,lastname)
+    set birthdate $thisparam($this,birthdate)
+    set protocolname $thisparam($this,protocolname)
+    set pi $thisparam($this,pi)  
+    set visitdate $thisparam($this,visitdate)
+    set patientid ""
+    set visitid ""
+
+    set  sqlstring "select Visit.VisitID, Patient.PatientID, Patient.Firstname, Patient.Lastname, Patient.Birthdate, "
+    append sqlstring "Protocol.protocolname, Protocol.Pi, Visit.Visitdate "
+    append sqlstring "from Visit,Protocol,Patient "
+    append sqlstring "where Visit.patientid=Patient.patientid and Visit.protocolid=Protocol.protocolid "
+    append sqlstring "and Patient.firstname like '%"
+    append sqlstring $firstname
+    append sqlstring "%' "
+    append sqlstring "and Patient.lastname like '%"
+    append sqlstring $lastname
+    append sqlstring "%' "
+    append sqlstring "and Patient.birthdate like '%"
+    append sqlstring $birthdate
+    append sqlstring "%' "
+    append sqlstring "and Protocol.protocolname like '%"
+    append sqlstring $protocolname
+    append sqlstring "%' "
+    append sqlstring "and Protocol.pi like '%"
+    append sqlstring $pi
+    append sqlstring "%' "
+    append sqlstring "and Visit.visitdate like '%"
+    append sqlstring $visitdate
+    append sqlstring "%' "
+
+    $thisparam($this,seriesframe1_querylist) delete 0 end
+    set query [ $database RunComplexQuery $sqlstring ]
+    set i 0
+    while {[$query NextRow]} {
+  	set i [expr $i +1 ]
+ 	set visitid [ $database GetQueryValueAsString $query 0 ] 
+ 	set patientid [ $database GetQueryValueAsString $query 1 ] 
+  	set firstname [ $database GetQueryValueAsString $query 2 ] 
+ 	set lastname [ $database GetQueryValueAsString $query 3 ] 
+ 	set birthdate [ $database GetQueryValueAsString $query 4 ] 
+ 	set protocolname [ $database GetQueryValueAsString $query 5 ] 
+  	set pi [ $database GetQueryValueAsString $query 6 ] 
+ 	set visitdate [ $database GetQueryValueAsString $query 7 ] 
+	set record "$i|$visitid|$patientid|$firstname|$lastname|$birthdate|$protocolname|$pi|$visitdate"
+	set rf $thisparam($this,seriesframe1_rf)
+	$rf.result insert end $record
+    }
+}
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::selectVisit { } {
+
+    set name [ $thisparam($this,seriesframe1_querylist) getcurselection ]
+    set tmp  [ split $name | ]
+    set visitid [ lindex $tmp 1 ]
+    set patientid [ lindex $tmp 2 ]
+    set thisparam($this,visitid) $visitid
+    set thisparam($this,patientid) $patientid
+    tk_messageBox -type ok -message "You select VisitID $visitid" -title "OK" -icon info
+    set thisparam($this,visitid_selected) 1
+}
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::addSeries {} {
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Please Connect To Server First Before trying to Execute a Query" -title "Error!" -icon error
+	return
+    }
+    if { $thisparam($this,visitid_selected) == 0 } {
+	tk_messageBox -type ok -message "Please Select Visit first" -title "Error!" -icon error
+	return
+    }
+    append imagefile $thisparam($this,seriesdatapath) "/" $thisparam($this,seriesfilename) 
+    if {![file exist $imagefile]} {
+      tk_messageBox -type ok -message "Imagefile $imagefile not exist" -title "Error!" -icon error
+      return
+    }
+
+    set thisparam($this,namelist) { { ImagePath seriesdatapath } { ImageFileName seriesfilename} }
+    
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	if { $thisparam($this,$field) == "" } {
+	    tk_messageBox -type ok -message "Parameter $label not set" -title "Error!" -icon error
+	    return
+	}
+    }
+
+    set visitid $thisparam($this,visitid)
+    set patientid $thisparam($this,patientid)
+    set seriesdatapath $thisparam($this,seriesdatapath)
+    set seriesfilename $thisparam($this,seriesfilename)
+    
+
+
+    set study [ vtkbisStudy New ]
+    $study SetConnector $database
+    $study SetVisitID $visitid
+    $study SetPatientID $patientid
+    $study AddStudy 
+    set studyid [ $study SearchStudyID $visitid $patientid ]
+    $study SetStudyID $studyid
+    set studyuid [ $study SearchStudyUID $studyid ]
+    $study SetStudyUID $studyuid
+    
+    set  injection [ vtkbisInjection New ]
+    $injection SetConnector $database
+    $injection SetVisitID $visitid
+    $injection AddInjection 
+    set injectionid [ $injection SearchInjectionID $visitid ]
+    $injection SetInjectionID $injectionid
+    $injection SetInjectionDateTime [ $injection SearchInjectionDateTime $injectionid ]
+    
+    set series [  vtkbisSeries New ]
+    $series SetConnector $database
+    $series SetStudyID $studyid
+    $series SetInjectionID $injectionid
+    $series SetSeriesDataPath $seriesdatapath
+    $series SetSeriesFileName $seriesfilename
+    set seriesid [  $series SearchSeriesID $studyid $injectionid ]
+    $series SetSeriesID $seriesid
+    if { [ string length $seriesid ] ==0 } {
+	$series AddSeries 
+	set seriesid [ $series SearchSeriesID $studyid $injectionid ]
+	$series SetSeriesID $seriesid
+	$series SetSeriesUID [ $series SearchSeriesUID $seriesid ]
+	tk_messageBox -type ok -message "Series was added as seriesid $seriesid" -title "OK" -icon info
+    }
+
+}
+
+# ------------------------------------------------------------------------------------
+itcl::body bis_databasetool::browse { } {
+
+    set f2tail $thisparam($this,seriesfilename)
+    set f2path $thisparam($this,seriesdatapath)
+
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Get Filename Series" -filetypes $typelist -initialfile $f2tail -initialdir $f2path ]   
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    set thisparam($this,seriesdatapath) [ file dirname $fname ]
+    set thisparam($this,seriesfilename) [ file tail $fname ]
+    return 1
+}
+
+# --------------------------------------------------------------------------------------------------------
+itcl::body bis_databasetool::searchSavedQuery {} {
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Please Connect To Server First Before trying to Execute a Query" -title "Error!" -icon error
+	return
+    }
+    
+    set namelist { { QueryName queryname } { QueryCategory querycategory } }
+
+    foreach elem $namelist {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+    }
+    set queryname $thisparam($this,queryname)
+    set querycategory $thisparam($this,querycategory)
+    set querydescription ""
+    set queryarg ""
+    set querytable ""
+    set querylink ""
+    set queryfield ""
+    set querywhere ""
+    set queryorder ""
+    set querygroup ""
+    set queryhaving ""
+
+    # Create Database Connector
+    
+    set  sqlstring "select QueryName, QueryCategory,QueryDescription,QueryArg, QueryTable,"
+    append sqlstring "QueryLink,QueryField,QueryWhere,QueryOrder,QueryGroup,QueryHaving "
+    append sqlstring "from Query "
+    append sqlstring "where queryname like '%"
+    append sqlstring $queryname
+    append sqlstring "%' "
+    append sqlstring "and querycategory like '%"
+    append sqlstring $querycategory
+    append sqlstring "%' "
+
+    $thisparam($this,savedqueryframe1_querylist) delete 0 end
+    set query [ $database RunComplexQuery $sqlstring ]
+    set i 0
+    while {[$query NextRow]} {
+  	set i [expr $i +1 ]
+ 	set queryname [ $database GetQueryValueAsString $query 0 ] 
+  	set querycategory [ $database GetQueryValueAsString $query 1 ] 
+ 	set querydescription [ $database GetQueryValueAsString $query 2 ] 
+ 	set queryarg [ $database GetQueryValueAsString $query 3 ] 
+ 	set querytable [ $database GetQueryValueAsString $query 4 ] 
+  	set querylink [ $database GetQueryValueAsString $query 5 ] 
+ 	set queryfield [ $database GetQueryValueAsString $query 6 ] 
+	set querywhere [ $database GetQueryValueAsString $query 7 ] 
+  	set queryorder [ $database GetQueryValueAsString $query 8 ] 
+ 	set querygroup [ $database GetQueryValueAsString $query 9 ] 
+ 	set queryhaving [ $database GetQueryValueAsString $query 10 ] 
+	
+	set record "$i|$queryname|$querycategory|$querydescription"
+	set rf $thisparam($this,savedqueryframe1_rf)
+	$rf.result insert end $record
+    }
+}
+
+itcl::body bis_databasetool::abbreviation { input } {
+ 
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Please Connect To Server First Before trying to Execute a Query" -title "Error!" -icon error
+	return
+    }
+
+    set  sqlstring "select Abbrev, AbbrevTranslation from Abbreviations "
+
+    set query [ $database RunComplexQuery $sqlstring ]
+    set i 0
+    while {[$query NextRow]} {
+ 	set tmp [ $database GetQueryValueAsString $query 0 ] 
+    	if { [ string index $tmp 0 ] == "$" } {
+		set abbrev($i) "\\$tmp"
+        } else {
+		set abbrev($i) $tmp
+	}
+	set abbrevTranslation($i) [ $database GetQueryValueAsString $query 1 ] 
+	set search($i) $abbrev($i)
+	set replace($i) $abbrevTranslation($i)
+
+	set i [expr $i +1 ]
+    }
+
+    set delimiter "(^|\\W|$)"
+    set separator "~~!~~"
+    
+    for {set index 0} {$index < [array size search]} {incr index} {
+      	set search($index) "$delimiter$search($index)$delimiter"
+	set replace($index) "\\1$separator$replace($index)\\2"
+    }
+    
+    set new_text $input
+    set old_text ""
+    set step 0
+    #here, the while loop always runs, why?
+    while { [string equal new_text old_text]==0 } {
+        #puts "step=$step"
+	set step [expr $step +1 ]
+	if { $step > 25 } {
+	     break
+	}
+	for {set index 0} {$index < [array size search]} {incr index} {
+		set old_text $new_text
+		regsub -all -nocase $search($index) $old_text $replace($index) new_text
+		regsub -all -nocase $separator $new_text "" new_text
+	}
+    }	
+	    
+    return $new_text
+
+}
+
+
+itcl::body bis_databasetool::beuatifyQuery { inp } {
+
+#    puts stderr "Beginning with $inp"
+
+    regsub -all {[\n\t ]} $inp "" inp
+    set ok 1
+    while { $ok > 0 } {
+	set old $inp
+	set ok [ regsub -all {\([^\(\)]*\)} $old "+" inp ]
+	#puts stderr "old=$old\t new=$inp\t ok=$ok\n"
+    }
+
+    set ok 1
+    while { $ok > 0 } {
+	set old $inp
+	set ok [ regsub -all {\"[^\"]*\"} $old "*" inp ]
+	#	puts stderr "old=$old\t new=$inp\t ok=$ok\n"
+    }
+
+      #  puts stderr "Final text=$inp"
+    return $inp
+}
+
+itcl::body bis_databasetool::selectSavedQuery { } {
+    
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Please Connect To Server First Before trying to Execute a Query" -title "Error!" -icon error
+	return
+    }
+
+    set name [ $thisparam($this,savedqueryframe1_querylist) getcurselection ]
+    set tmp  [ split $name | ]
+    set queryname [ lindex $tmp 1 ]
+    set querycategory [ lindex $tmp 2 ]
+    set thisparam($this,queryname) $queryname
+    set thisparam($this,querycategory) $querycategory
+    set querydescription ""
+    set queryarg ""
+    set querytable ""
+    set querylink ""
+    set queryfield ""
+    set querywhere ""
+    set queryorder ""
+    set querygroup ""
+    set queryhaving ""
+    # Create Database Connector
+    
+    set  sqlstring "select QueryName, QueryCategory,QueryDescription,QueryArg, QueryTable,"
+    append sqlstring "QueryLink,QueryField,QueryWhere,QueryOrder,QueryGroup,QueryHaving "
+    append sqlstring "from Query "
+    append sqlstring "where queryname='"
+    append sqlstring $queryname
+    append sqlstring "'"
+    append sqlstring " and querycategory='"
+    append sqlstring $querycategory
+    append sqlstring "'"
+
+    set query [ $database RunComplexQuery $sqlstring ]
+    set i 0
+    while {[$query NextRow]} {
+  	set i [expr $i +1 ]
+ 	set queryname [ $database GetQueryValueAsString $query 0 ] 
+  	set querycategory [ $database GetQueryValueAsString $query 1 ] 
+ 	set querydescription [ $database GetQueryValueAsString $query 2 ] 
+ 	set queryarg [ $database GetQueryValueAsString $query 3 ] 
+ 	set querytable [ $database GetQueryValueAsString $query 4 ] 
+  	set querylink [ $database GetQueryValueAsString $query 5 ] 
+ 	set queryfield [ $database GetQueryValueAsString $query 6 ] 
+	set querywhere [ $database GetQueryValueAsString $query 7 ] 
+  	set queryorder [ $database GetQueryValueAsString $query 8 ] 
+ 	set querygroup [ $database GetQueryValueAsString $query 9 ] 
+ 	set queryhaving [ $database GetQueryValueAsString $query 10 ] 
+    }
+
+    set querytable [ $this abbreviation $querytable ]
+    set querylink [ $this abbreviation $querylink ]
+    set queryfield [ $this abbreviation $queryfield ]
+    set querywhere [ $this abbreviation $querywhere ]
+    set queryorder [ $this abbreviation $queryorder ]
+    set querygroup [ $this abbreviation $querygroup ]
+    set queryhaving [ $this abbreviation $queryhaving ]
+
+     
+
+    if { [ string first "Series" $querytable ] < 0 } {
+	tk_messageBox -type ok -message "You selected a query that is not valid for searching for images" -title "Bad Query" -icon error
+	return 0
+    }
+
+    set seriespathindex -1
+    set seriesnameindex -1
+
+    set fielddivision [ split [ beuatifyQuery $queryfield ] "," ]
+
+
+    set thisparam($this,queryfieldnumber) [ llength $fielddivision ]
+
+    for { set i 0 } { $i < [ llength $fielddivision ] } { incr i } {
+	set qt [ string trim [ lindex $fielddivision $i ]]
+	#	puts stderr "Element $i \t $qt"
+	if { [ string first "Series.SeriesFileName" $qt ] >=0 } {
+	    set seriesnameindex [ expr $i  + 1]
+	} elseif { [ string first "Series.SeriesDataPath" $qt ] >= 0 } {
+	    set seriespathindex [ expr $i + 1 ]
+	}
+    }
+
+
+    if { $seriespathindex == -1 } {
+	append queryfield ",Series.SeriesDataPath"
+    }
+    if { $seriesnameindex == -1 } {
+	append queryfield ",Series.SeriesFileName"
+    } 
+
+
+    set fielddivision [ split [ beuatifyQuery $queryfield ] "," ]
+    for { set i 0 } { $i < [ llength $fielddivision ] } { incr i } {
+	set qt [ string trim [ lindex $fielddivision $i ]]
+	#	puts stderr "Element $i \t $qt"
+	if { [ string first "Series.SeriesFileName" $qt ] >=0 } {
+	    set seriesnameindex [ expr $i  + 1]
+	} elseif { [ string first "Series.SeriesDataPath" $qt ] >= 0 } {
+	    set seriespathindex [ expr $i + 1 ]
+	}
+    }
+
+    set thisparam($this,queryfieldnumber) [ llength $fielddivision ]
+    tk_messageBox -type ok -message "You selected query $queryname in category $querycategory" -title "OK" -icon info
+
+    set thisparam($this,queryname) $queryname
+    set thisparam($this,querycategory) $querycategory
+    set thisparam($this,querydescription) $querydescription
+    set thisparam($this,queryarg) $queryarg
+    set thisparam($this,querytable) $querytable
+    set thisparam($this,querylink) $querylink
+    set thisparam($this,queryfield) $queryfield
+    set thisparam($this,querywhere) $querywhere
+    set thisparam($this,queryorder) $queryorder
+    set thisparam($this,querygroup) $querygroup
+    set thisparam($this,queryhaving) $queryhaving
+    set argname [ split $queryarg | ]
+
+    set f $thisparam($this,ontheflyframe) 
+#    puts stderr "Removing $f"
+    pack forget $f
+    destroy $f
+    frame $f  
+    pack $f -side top -expand true -fill both
+
+    set entrylist ""
+    set thisparam($this,ontheflyentries) ""
+    
+    foreach elem $argname {
+
+      set e [ string trim $elem ]
+      #regsub -all  " " $e "_" newelem
+      regsub -all  {[^a-zA-Z0-9]} $e "_" newelem
+      set label  $e
+      set field  parameters_${newelem}
+      set thisparam($this,$field) ""
+      iwidgets::entryfield $f.$field  -labeltext "${label}:" -width 20 -textvariable [ itcl::scope thisparam($this,$field) ] -relief sunken
+      pack $f.$field -side top -expand false -fill x
+      set entrylist "$entrylist $f.$field"
+      lappend thisparam($this,ontheflyentries) $field
+    }
+    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+    #puts stderr "vars=$thisparam($this,ontheflyentries)"
+
+    $thisparam($this,queryquerynotebook) view "2. Input arguments"
+
+}
+
+
+itcl::body bis_databasetool::runSavedQuery { } {
+
+    if { $thisparam($this,connected) == 0 } {
+	tk_messageBox -type ok -message "Please Connect To Server First Before trying to Execute a Query" -title "Error!" -icon error
+	return
+    }
+
+#    foreach elem $thisparam($this,ontheflyentries) {
+#	puts stderr "Value of $elem = $thisparam($this,$elem)"
+#    }
+    # Create Database Connector
+    
+    set queryname $thisparam($this,queryname)
+    set querycategory $thisparam($this,querycategory)
+    set p [ vtkbisQuery New ]
+    $p SetConnector $database
+    set ok [ $p SearchQuery $queryname $querycategory ]
+    #$p Print
+
+   # set ttt [ $p GetQueryField ]
+    set ttt $thisparam($this,queryfield) 
+    $p SetQueryField $ttt
+    
+    set l ""
+    for { set i 0 } { $i < [ llength $thisparam($this,ontheflyentries) ] } { incr i } {
+	set pp [ lindex $thisparam($this,ontheflyentries) $i ]
+	set q $thisparam($this,$pp)
+	if { [ string length $q ] > 0 } {
+	    set l "${l}${q}|"
+	} else {
+	    set l "${l}*|"
+	}
+    }
+    set sql [ $p BuildQuery $l]
+    set sql [ $this abbreviation $sql ]
+   # puts $sql
+    set query [ $database RunComplexQuery $sql ]
+    
+    $thisparam($this,savequeryframe2_querylist) delete 0 end
+    set ok 1
+    set i  0
+    while { $ok !=0 } {
+	set ok [ $query NextRow ]
+	if { $ok > 0 } {
+	    set line ""
+	    incr i
+	    for { set j 0 } { $j < $thisparam($this,queryfieldnumber) } { incr j } {
+		set line "$line|[ $database GetQueryValueAsString $query $j ]"
+	    }
+	    set record "$i$line"
+	    #	    puts stderr $record
+	    set rf $thisparam($this,savequeryframe2_rf)
+	    $rf.result insert end $record
+	}
+    }
+}
+
+# --------------------------------------------------------------------------------------------------------
+itcl::body bis_databasetool::CreateServerGUI { pw } {
+
+    set serverframe  [ LabelFrame:create $pw.a -text "My SQL Server"]
+    set sqliteframe  [ LabelFrame:create $pw.b -text "SQLite File"]
+
+    checkbutton $pw.c -variable [ itcl::scope thisparam($this,debugdbase)  ] -text "Debug SQL" 
+
+    pack $pw.c -side bottom -expand false -fill x
+
+
+
+    set fr [ frame ${serverframe}.info ]
+    set thisparam($this,namelist) { { Username username } { Password password } { Host host }
+	{ Database database } { Port port } }
+    
+    set entrylist ""
+    foreach elem $thisparam($this,namelist) {
+	
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	
+	iwidgets::entryfield $fr.$field  -labeltext "${label}:" -width 20 -textvariable [ itcl::scope thisparam($this,$field) ] -relief sunken
+	pack $fr.$field -side top -expand false -fill x -padx 10
+	
+	if { $field == "password" } {
+	    $fr.$field configure -show "*"
+	}
+	set entrylist "$entrylist $fr.$field"
+    }
+    
+    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+    
+    set bf [ frame ${serverframe}.bf ]
+    
+    eval "button $bf.login -text \"Connect to Database\" -command { $this MySQLConnect }"
+    eval "button $bf.cancel -text \"Disconnect\"  -command { $this Disconnect }"
+    pack $bf.login $bf.cancel -side left
+    
+    pack $fr $bf -side top -expand true -fill both
+
+
+    set db 0
+    catch { 
+	set db [ vtkbisMySQLDatabase New ]
+	$db Delete
+    }
+    
+    if { $db == 0  } {
+#	puts stderr "Eliminating MYSQL Stuff"
+	pack $pw.b -side top -expand true -fill x
+		
+    } else {
+	pack $pw.b -side bottom -expand true -fill x
+	pack $pw.a  -side top -expand true -fill both
+    }
+
+
+
+
+    eval "button $sqliteframe.3 -text \"Disconnect\"  -command { $this Disconnect }"
+    eval "button $sqliteframe.2 -text \"Connect to File\" -command { $this SQLiteConnect }"
+    eval "button $sqliteframe.1 -text \"Create New File\" -command { $this SQLiteCreate }"
+
+    pack $sqliteframe.3 -side right -expand false -padx 2
+    pack $sqliteframe.2 $sqliteframe.1 -side left -expand true -fill x -padx 2
+}
+# --------------------------------------------------------------------------------------------------------
+itcl::body bis_databasetool::CreateQueryGUI { optframe } {
+
+    set fr [ frame ${optframe}.info ]
+    
+    set thisparam($this,namelist) { { FirstName firstname } { LastName lastname } { BirthDate birthdate }
+	{ ProtocolName protocolname } { Pi pi } { VisitDate visitdate } { ImagePath seriesdatapath }
+	{ ImageFileName seriesfilename} }
+    
+    set entrylist ""
+    
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	
+	iwidgets::entryfield $fr.$field  -labeltext "${label}:" -width 20 -textvariable [ itcl::scope thisparam($this,$field) ] -relief sunken
+	pack $fr.$field -side top -expand false -padx 10 -fill x
+	
+	set entrylist "$entrylist $fr.$field"
+    }
+
+    # Eliminate this at some point
+    # ----------------------------
+    set thisparam($this,firstname) "John"
+    set thisparam($this,lastname) "Smith"
+    set thisparam($this,birthdate) "1990-01-01"
+    set thisparam($this,visitdate) "2008-08-20"
+    # ----------------------------
+    
+    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+    
+    set bf [ frame ${optframe}.bf ]
+    
+    eval "button $bf.search -text \"Search for Image\" -command { $this searchImage }"
+    eval "button $bf.load -text \"Load Image\" -command { $this loadImage }"
+    pack $bf.search $bf.load -side left
+    set rf [ frame ${optframe}.rf ]
+    set thisparam($this,optframe_querylist) [ iwidgets::scrolledlistbox $rf.result  ]
+    pack $rf.result -side left -expand true -fill both
+    
+    pack $fr $rf $bf -side top -expand true -fill both
+    set thisparam($this,optframe_rf) $rf
+}
+# --------------------------------------------------------------------------------------------------------
+itcl::body bis_databasetool::CreatePatientGUI { patientframe } {
+
+    set fr [ frame ${patientframe}.info ]
+    
+    set thisparam($this,namelist) { { FirstName firstname } { LastName lastname } { BirthDate birthdate } }
+    set entrylist ""
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	iwidgets::entryfield $fr.$field  -labeltext "${label}:" -width 20 -textvariable [ itcl::scope thisparam($this,$field) ] -relief sunken
+	pack $fr.$field -side top -expand false -fill x
+	set entrylist "$entrylist $fr.$field"
+    }
+    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+
+    set bf [ frame ${patientframe}.bf ]
+    
+    eval "button $bf.add -text Add -command { $this addPatient }"
+    eval "button $bf.clear -text Clear -command { $this clearPatient }"
+    pack $bf.add $bf.clear -side left
+    pack $fr $bf -side top -expand true -fill both
+    
+}
+
+# --------------------------------------------------------------------------------------------------------
+itcl::body bis_databasetool::CreateProtocolGUI { protocolframe } {
+
+    set fr [ frame ${protocolframe}.info ]
+    
+    set thisparam($this,namelist) { { ProtocolName protocolname } { PI pi } }
+    set entrylist ""
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	iwidgets::entryfield $fr.$field  -labeltext "${label}:" -width 20 -textvariable [ itcl::scope thisparam($this,$field) ] -relief sunken
+	pack $fr.$field -side top -expand false -fill x
+	set entrylist "$entrylist $fr.$field"
+    }
+    
+    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+    
+    set bf [ frame ${protocolframe}.bf ]
+    
+    eval "button $bf.add -text Add -command { $this addProtocol }"
+    eval "button $bf.clear -text Clear -command { $this clearProtocol }"
+    pack $bf.add $bf.clear -side left
+    pack $fr $bf -side top -expand true -fill both
+}
+
+# --------------------------------------------------------------------------------------------------------
+itcl::body bis_databasetool::CreateVisitGUI { visitframe } {
+
+    set nt [ iwidgets::tabnotebook $visitframe.1  -tabpos n ]
+
+    # 1. Identify Patient
+    set visitframe1 [ $nt add -label "1. Identify Patient" ]
+    set fr [ frame ${visitframe1}.info ]
+    set thisparam($this,namelist) { { FirstName firstname } { LastName lastname } { BirthDate birthdate } }
+    set entrylist ""
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	iwidgets::entryfield $fr.$field  -labeltext "${label}:" -width 20 -textvariable [ itcl::scope thisparam($this,$field) ] -relief sunken
+	pack $fr.$field -side top -expand false -fill x
+	set entrylist "$entrylist $fr.$field"
+    }
+    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+    set rf [ frame ${visitframe1}.rf ]
+    set thisparam($this,visitframe1_querylist) [ iwidgets::scrolledlistbox $rf.result  ]
+    pack $rf.result -side left -expand true -fill both
+    set bf [ frame ${visitframe1}.bf ]
+    eval "button $bf.search -text Search -command { $this searchPatient }"
+    eval "button $bf.select -text Select -command { $this selectPatient }"
+    pack $bf.search $bf.select -side left
+    pack $fr $rf $bf -side top -expand true -fill both
+    set thisparam($this,visitframe1_rf) $rf
+    set thisparam($this,patientid_selected) 0
+
+    # 2. Identify Protocol
+    set visitframe2 [ $nt add -label "2. Identify Protocol" ]
+    set fr [ frame ${visitframe2}.info ]
+    set thisparam($this,namelist) { { ProtocolName protocolname } { PI pi } }
+    set entrylist ""
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	iwidgets::entryfield $fr.$field  -labeltext "${label}:" -width 20 -textvariable [ itcl::scope thisparam($this,$field) ] -relief sunken
+	pack $fr.$field -side top -expand false -fill x
+	set entrylist "$entrylist $fr.$field"
+    }
+    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+    set rf [ frame ${visitframe2}.rf ]
+    set thisparam($this,visitframe2_querylist) [ iwidgets::scrolledlistbox $rf.result  ]
+    pack $rf.result -side left -expand true -fill both
+    set bf [ frame ${visitframe2}.bf ]
+    eval "button $bf.search -text Search -command { $this searchProtocol }"
+    eval "button $bf.select -text Select -command { $this selectProtocol }"
+    pack $bf.search $bf.select -side left
+    pack $fr $rf $bf -side top -expand true -fill both
+    set thisparam($this,visitframe2_rf) $rf
+    set thisparam($this,protocolid_selected) 0
+    
+    # 3. Add Visit
+
+    set visitframe3 [ $nt add -label "3. Add Visit" ]
+    set fr [ frame ${visitframe3}.info ]
+    
+    set thisparam($this,namelist) { {VisitDate visitdate } }
+    set entrylist ""
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	iwidgets::entryfield $fr.$field  -labeltext "${label}:" -width 20 -textvariable [ itcl::scope thisparam($this,$field) ] -relief sunken
+	pack $fr.$field -side top -expand false -fill x
+	set entrylist "$entrylist $fr.$field"
+    }
+    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+    set bf [ frame ${visitframe3}.bf ]
+    eval "button $bf.add -text Add -command { $this addVisit }"
+    pack $bf.add -side left
+    pack $fr $bf -side top -expand true -fill both
+    
+    $nt view "1. Identify Patient"
+    pack $nt -side top -expand true -padx 4  -fill both
+    
+
+}
+# --------------------------------------------------------------------------------------------------------
+itcl::body bis_databasetool::CreateSeriesGUI { seriesframe } {
+
+    set nt [ iwidgets::tabnotebook $seriesframe.1  -tabpos n ]
+    set seriesframe1 [ $nt add -label "1. Identify Visit" ]
+    set fr [ frame ${seriesframe1}.info ]
+    set thisparam($this,namelist) { { FirstName firstname } { LastName lastname } { BirthDate birthdate }
+	{ ProtocolName protocolname } { PI pi } {VisitDate visitdate} }
+    set entrylist ""
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	iwidgets::entryfield $fr.$field  -labeltext "${label}:" -width 20 -textvariable [ itcl::scope thisparam($this,$field) ] -relief sunken
+	pack $fr.$field -side top -expand false -fill x
+	set entrylist "$entrylist $fr.$field"
+    }
+    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+    set rf [ frame ${seriesframe1}.rf ]
+    set thisparam($this,seriesframe1_querylist) [ iwidgets::scrolledlistbox $rf.result  ]
+    pack $rf.result -side left -expand true -fill both
+    set bf [ frame ${seriesframe1}.bf ]
+    eval "button $bf.search -text Search -command { $this searchVisit }"
+    eval "button $bf.select -text Select -command { $this selectVisit }"
+
+    pack $bf.search $bf.select -side left
+    pack $fr $rf $bf -side top -expand true -fill both
+    set thisparam($this,seriesframe1_rf) $rf
+    set thisparam($this,visitid_selected) 0
+    
+    set seriesframe2 [ $nt add -label "2. Add Series" ]
+    set fr [ frame ${seriesframe2}.info ]
+    
+    set thisparam($this,namelist) { {SeriesDataPath seriesdatapath } {SeriesFileName seriesfilename} }
+    set entrylist ""
+    foreach elem $thisparam($this,namelist) {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	iwidgets::entryfield $fr.$field  -labeltext "${label}:" -width 20 -textvariable [ itcl::scope thisparam($this,$field) ] -relief sunken
+	pack $fr.$field -side top -expand false -fill x
+	set entrylist "$entrylist $fr.$field"
+    }
+    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+    set bf [ frame ${seriesframe2}.bf ]
+
+    eval "button $bf.add -text Add -command { $this addSeries }"
+    eval "button $bf.browse -text Browse -command { $this browse }"
+
+    pack $bf.add $bf.browse -side left
+    pack $fr $bf -side top -expand true -fill both
+    
+    $nt view "1. Identify Visit"
+    pack $nt -side top -expand true -padx 4  -fill both
+}
+
+# --------------------------------------------------------------------------------------------------------
+itcl::body bis_databasetool::CreateQueryQueryGUI { qframe } {
+
+
+    set nt [ iwidgets::tabnotebook $qframe.1  -tabpos n ]
+
+    set thisparam($this,queryquerynotebook) $nt
+
+    set savedqueryframe1 [ $nt add -label "1. Identify Saved Query" ]
+    set fr [ frame ${savedqueryframe1}.info ]
+    set namelist { { QueryName queryname } { QueryCategory querycategory } }
+    set entrylist ""
+    foreach elem $namelist {
+	set label [ lindex $elem 0 ]
+	set field [ lindex $elem 1 ]
+	iwidgets::entryfield $fr.$field  -labeltext "${label}:" -width 20 -textvariable [ itcl::scope thisparam($this,$field) ] -relief sunken
+	pack $fr.$field -side top -expand false -fill x
+	set entrylist "$entrylist $fr.$field"
+    }
+    eval "iwidgets::Labeledwidget::alignlabels $entrylist"
+    set rf [ frame ${savedqueryframe1}.rf ]
+    set thisparam($this,savedqueryframe1_querylist) [ iwidgets::scrolledlistbox $rf.result  ]
+    pack $rf.result -side left -expand true -fill both
+    set bf [ frame ${savedqueryframe1}.bf ]
+    eval "button $bf.search -text \"Execute Query\" -command { $this searchSavedQuery }"
+    eval "button $bf.select -text \"Select\" -command { $this selectSavedQuery }"
+    pack $bf.search $bf.select -side left
+    pack $fr $rf $bf -side top -expand true -fill both
+    set thisparam($this,savedqueryframe1_rf) $rf
+    set thisparam($this,visitid_selected) 0
+
+    set savedqueryframe2 [ $nt add -label "2. Input arguments" ]
+    set fr [ frame ${savedqueryframe2}.info ]
+    set bf [ frame ${savedqueryframe2}.bf ]
+    eval "button $bf.run -text \"Execute Query\" -command { $this runSavedQuery }"
+    eval "button $bf.load -text \"Load Image\" -command { $this loadImage2 }"
+
+    pack $bf.run $bf.load -side left
+    pack $fr $bf -side top -expand false -fill x
+    
+    set ontheflyframe [ frame $savedqueryframe2.tt  ]
+    pack $ontheflyframe -side top -expand true -fill both
+
+    set thisparam($this,ontheflyframe) $ontheflyframe
+    
+    set rf [ frame ${savedqueryframe2}.rf ]
+    set thisparam($this,savequeryframe2_querylist) [ iwidgets::scrolledlistbox $rf.result  ]
+    pack $rf.result -side left -expand true -fill both
+    pack $rf -side top -expand true -fill both
+    set thisparam($this,savequeryframe2_rf) $rf
+    
+
+    $nt view "1. Identify Saved Query"
+    pack $nt -side top -expand true -padx 4  -fill both
+}
+# --------------------------------------------------------------------------------------------------------
+
+itcl::body bis_databasetool::InitializeGUI { base { standal 0 } } {
+
+    if { $initialized == 1 } {
+	return $basewidget
+    }
+
+    set standalone [ expr $standal > 0 ]
+    set basewidget $base
+    toplevel $basewidget
+    wm withdraw $basewidget
+
+    wm title $basewidget "Search information from database"
+
+
+
+    set buttonbar [ frame $basewidget.0 ]
+    pack $buttonbar -side bottom -expand false -fill x -padx 2 -pady 2
+    
+
+
+    if { $standalone > 0 } {
+        button $buttonbar.quit -text Quit -command pxtkexit
+    } else {
+	eval "button $buttonbar.quit -text Close -command { wm withdraw $basewidget }"
+    }
+    eval "button $buttonbar.reset -text Reset -command { $this ResetValues }"
+
+    pack $buttonbar.quit $buttonbar.reset -side right -expand false -padx 5 
+
+    
+
+    entry $buttonbar.st -width 30  -textvariable [ itcl::scope thisparam($this,connectionstatus) ] -relief sunken  -bg black -fg white 
+    pack $buttonbar.st -side left -expand true -fill x
+
+    # ------------------------------------------------
+    
+    set notebook [ iwidgets::tabnotebook $basewidget.1  -tabpos w ]
+    pack $notebook -side top -expand true -fill both -padx 2 -pady 2
+    
+    $this CreateServerGUI [ $notebook add -label "Server" ]
+    $notebook view "Server"
+
+
+    $this CreateQueryQueryGUI [ $notebook add -label "Saved Query" ]
+
+    $this CreateQueryGUI  [ $notebook add -label "Query" ]
+    if { $standalone > 0 } {
+	set viewframe [ $notebook add -label "Viewer" ]
+	set orthoviewer [ vtkpxGUIOrthogonalViewer [ pxvtable::vnewobj ]]
+	$orthoviewer Initialize $viewframe 1
+	wm geometry $basewidget 600x500
+    } else  {
+	wm geometry $basewidget 600x450
+    }
+
+
+    $this CreatePatientGUI  [ $notebook add -label "Add Patient" ]
+    $this CreateProtocolGUI [ $notebook add -label "Add Protocol" ]
+    $this CreateVisitGUI    [ $notebook add -label "Add Visit" ]
+    $this CreateSeriesGUI   [ $notebook add -label "Add Series" ]
+
+
+    wm title $basewidget "BioImage Suite::Database Control $thisparam($this,connectionstatus)"
+
+
+}
+
+# ----------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    wm withdraw .
+
+    set br  .[ pxvtable::vnewobj ]
+    set element [bis_databasetool \#auto 0 ]
+    update idletasks
+    $element InitializeGUI $br 1
+    $element ShowWindow
+
+    if { [ llength $argv ] > 0 } {
+	$element SQLiteConnect [ lindex $argv 0 ]
+    }
+}
+    
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/bis_fmri.tcl b/bioimagesuite30_src/bioimagesuite/main/bis_fmri.tcl
new file mode 100755
index 0000000..d5799e9
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/bis_fmri.tcl
@@ -0,0 +1,2918 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# ---------------------------------------------------------------------------------------
+#                  Allows Running this from outside the tree
+# ---------------------------------------------------------------------------------------
+
+set biopath  [ file normalize [ file join [ file dirname [ info script ]] .. ]  ]
+lappend auto_path [ file join $biopath base ]
+lappend auto_path [ file join $biopath main ]
+lappend auto_path [ file join $biopath bis_algorithm ]
+unset biopath
+
+
+
+#---------------------------------------------------------------------------------------
+package require bis_fmrisetup 1.0
+package require bis_colorblendimage 1.0 
+package require Iwidgets 
+package require pxitclsubjectentry 1.0
+package require vtk
+package require vtkinteraction
+package require vtkpxcontrib 1.0
+package require pxvtable 1.0
+package require pxtclhelp  1.0
+package require pxtcluserprefs 
+package require pxitclfilelistmenu 1.0
+package require  pxtclruncommand 1.0
+package require pxtcluserprefs 1.0
+package require bis_viewer 1.0 
+
+
+
+package provide bis_fmri 1.0
+
+
+#Class Definition
+#----------------------------------------------------------------------------------------------------
+itcl::class bis_fmri {
+
+	inherit bis_fmrisetup
+
+	private common hold
+	protected common canvasdata
+
+
+	protected variable aboutdialog 0
+	public    variable appname "BioImage Suite::fMRI Single Subject Analyzer"
+	public    variable version $::pxtclvtkpxcontrib::version
+	public    variable aboutstring "(c) X. Papademetris, M. Jackowski, I. Murphy, H.Okuda, R.T. Constable, L.H. Staib 1995-2011\nSection of Bioimaging Sciences, Department of Diagnostic Radiology, Yale University School of Medicine\n\n\nThis application is intended for research applications only! Use at your OWN RISK. If used for publication please acknowledge, see the webpage for more details. For additional support please visit the BioImage Suite forum at:\n\thttp://research.yale.edu/bioi [...]
+
+	protected variable runwidget 0
+	protected variable taskwidget 0
+	protected variable outcomewidget 0
+
+	protected variable session 0
+	protected variable tasklistbox 0
+	protected variable runslistbox 0
+	protected variable plotwidget  0
+	protected variable plotmatrix  0
+	protected variable drawcanvas  0
+	protected variable hrfcanvas  0
+
+	protected variable replacewidget 0
+
+	protected variable orthoviewer 0
+	protected variable bis_viewer 0
+	protected variable ownsorthoviewer 0
+	protected variable skipframesentry 0
+	protected variable subjectframe 0
+	protected variable blockwidget 0
+	protected variable directory_changed 0
+		
+	protected variable basewidget 0
+	protected variable notebook   0
+	protected variable runcommandgui 0
+	protected variable standalone 1
+
+	# ------------------------------- Methods ---------------------------
+
+	constructor { parent { standal 1 } { viewer 0 } } {
+	::bis_fmrisetup::constructor 
+	} { set standalone [ expr $standal > 0 ]
+	if { $viewer !=0 } {
+		set orthoviewer $viewer
+	}
+
+	$this CreateGUI $parent }
+	destructor { } 
+	
+	#---------------------------------------------
+	#GUI Stuff
+	#--------------------------------------------
+	public method CreateGUI { base } 
+	public method CreateDescriptionTab {base}
+	public method CreateImageDataTab {base}
+	public method CreateSessionTab {base}
+	public method CreateXMLOutputTab {base}
+	public method CreateAFNITab {base}
+	public method CreateSingleSubjectTab {base}
+	public method CreateRateGLMTab {base}
+
+	public method CreatePreprocessingFrame { base { mode seed } }
+	public method SetGlobalDrift { mode }
+	public method CreateSeedBasedTab {base}
+	public method SetOutputType { mode }
+	public method CreateIntrinsicTab {base}
+	public method CreateTreeTab {base}
+	public method AddToMenuButtonLite { mb args} 
+
+	public method SetMultiSubjectControl { msbcontrol } { set multisubjectcontrol $msbcontrol }
+
+
+	#Browse for filenames 
+	public method GetName {mode}
+	# Use this for external glm matrix filename
+	public method GetMatrixName {}
+	public method GetSetupName { } { return $setupname }
+
+	#Change Directory
+	public method SwitchDirectory { dirname }
+
+	# Run Related Stuff
+	public method EditRunGUI { { index -1 } }
+	public method RemoveRun { rmtype}
+	public method AddOrEditRun { { index -1 } }
+	public method GetRunFilename {currentrun mode}
+	public method GetRunMotionFilename {currentrun mode}
+	public method OperationOnCurrentRun { m }
+	public method AddAllRuns { }
+
+
+	# Task Related Stuff
+	public method AddOrEditTask { }
+	public method EditTaskGUI { { index -1 } }
+	public method RemoveTask { rmtype}
+	public method OperationOnCurrentTask {p }
+
+	public method AddAllTasks { }
+
+	# Override from parent
+	public method ClearAllData {ask }
+
+	# Block Editing
+	public method CreateBlockEditingDialog { }
+	public method CloseBlockWidget { }
+	public method CreatePlotWidget { }
+	public method PlotRun { run }
+
+	# Outcome Stuff
+	public method CreateOutcomeWidget { }
+
+	#  Plot HRF Stuff
+	public method PlotHRF {  }
+	protected method AdjustHRFGUI { }
+	protected method RestrictHRFMode { }
+	public method HRFCanvasUpdate { x y b } 
+	public method CreateGLMTclImage { }
+
+	# Plot Widget Stuff 
+	public method StartInteraction { x y b} 
+	public method EndInteraction { } 
+	public method UpdateInteraction { x y butno} 
+
+
+	# Utilities
+	public method ToggleFrameEntry { entrywidget framebutton } 
+	public method StringParse {mode output_type end thistask thisrun}
+	public method ReplaceStringGUI { }
+	public method ReplaceString { }
+
+	# File Name Utility
+	public method DisplayFilenames { }
+
+
+
+
+	# Commands for about and exit
+	public method AboutCommand { }
+	public method ExitCommand { }
+	public method ShowCommandLineOptions { } 
+	# Command to load and display image
+	public method DisplayImage { thisimage }
+	public method CheckTransformation { thistransformation } 
+	public method OverlayVOIImage { { doblend 1 } }
+
+	# Update GUI after load/save setup file
+	protected method UpdateGUI { { loadmode 1 } } 
+	protected method HasGUI { { loadmode 1 }  } { return 1 }
+
+	# Reorganize Data
+	public method ReorganizeDataGUI { }
+
+	# Display MSB
+	public method DisplayMSBFile { msbsetupname } 
+
+};
+
+
+
+
+::itcl::body bis_fmri::AddToMenuButtonLite { mb args} {
+
+	eval "$mb add command -label \"FMRI Analyzer Tool\" -command { wm deiconify $basewidget }"
+	
+}
+
+#Creates the Main GUI
+#Called in constructor
+#Creates main (toplevel) widget and sets absolute dimensions (geometry). Creates tab notebook packed
+#in toplevel widget and sets absolute dimensions. Calls individual methods to fill each tab.
+#Creates main "File" menu with load, save, and exit commands, calling methods for each
+#----------------------------------------------------------------------------------------------------
+
+itcl::body bis_fmri::CreateGUI { base } {
+
+	global tcl_platform
+
+	set parameters($this,change_to_directory) [ pwd ]
+	set basewidget $base
+
+	#    puts stderr "Base is .... "
+
+	wm title $base $appname; update
+
+	set tabs [frame $base.main -width 600 -bg white]
+	pack  $tabs  -side top -expand true -fill both
+	
+
+	if { $standalone == 1 } {
+	eval "wm protocol $base WM_DELETE_WINDOW { $this ExitCommand }"
+	eval "bind all <Control-d>  { $this ExitCommand }"
+	}
+	
+	#Makes the bottom execute frame
+	set bottomframe [ frame $base.bot ]
+	pack $bottomframe -side bottom -expand false -fill x
+	$this CreateProgressBar $bottomframe    
+
+
+	if { $orthoviewer == 0 } {
+	wm geometry $base 1200x620
+	set nt [ panedwindow $tabs.1 -orient horizontal -showhandle 1 \
+			 -borderwidth 2 -relief raised -sashwidth 4 -sashpad 4 \
+			 -handlesize 5 -handlepad 50  ]
+	pack $tabs.1 -side top -expand true -fill both
+	
+	set guibase   [ frame $nt.c  -width 700 ]
+	set viewbase  [ frame $nt.d  -width 400 ]
+	
+	$nt add $guibase  -minsize  500
+	$nt add $viewbase -minsize  400
+	update idletasks
+	   
+	set notebook [iwidgets::tabnotebook $guibase.1 -state normal -width 5i -height 5i -tabpos w]
+	pack $notebook -padx 5 -pady 5 -expand true -fill both
+
+	set bis_viewer [ [ bis_viewer \#auto ] GetThisPointer ]
+	$bis_viewer CreateGUI $viewbase
+	update idletasks
+	set orthoviewer [ $bis_viewer GetViewer ]
+	set ownsorthoviewer 1
+	} else {
+	wm geometry $base 600x620
+	
+
+	set notebook [iwidgets::tabnotebook $tabs.1 -state normal -width 5i -height 5i -tabpos w]
+	pack $notebook -padx 5 -pady 5 -expand true -fill both
+	}
+
+	#Description Tab
+	$this CreateDescriptionTab [$notebook add -label "Study Definition"]
+
+	#Image Data Tab
+	$this CreateImageDataTab [$notebook add -label "Anatomical Data"]
+
+	#Session Tab
+	$this CreateSessionTab [$notebook add -label "Session Information"]
+
+	# Single Subject
+	$this CreateSingleSubjectTab [$notebook add -label "Single Subject GLM"]
+	$this CreateAFNITab [$notebook add -label "AFNI GLM"]
+
+
+
+	global pxtcl_pref_array
+	#AFNI Tab
+
+
+	$this CreateSeedBasedTab [$notebook add -label "Seed-based Correlation"]
+	$this CreateIntrinsicTab [$notebook add -label "Intrinsic Connectivity"]
+# Excluded TCL Code 
+	update idletasks
+	$this CreateTreeTab [$notebook add -label "DataTree"]
+
+	#Viewer Tab
+
+   
+
+	$notebook view "Study Definition"
+
+	#Creates the menu
+	set menubase [menu $base.top]; $base configure -menu $menubase
+	set file_menu [menu $menubase.file -tearoff 0]
+	$menubase add cascade -underline 0 -label "File" -menu $file_menu
+	eval "$file_menu add command -label \"New\" -command {$this ClearAllData 1}"
+	eval "$file_menu add separator"
+	eval "$file_menu add command -label \"Load Setup File\" -command {$this LoadSetupFile }"
+	eval "$file_menu add command -label \"Save Setup File\" -command {$this SaveSetupFile  }"
+	eval "$file_menu add separator"
+	eval "$file_menu add command -label \"Reorganize Data\" -command {$this ReorganizeDataGUI  }"
+	eval "$file_menu add separator"
+	eval "$file_menu add command -label \"Import Parameter fMRI Overwrite File\" -command { $this LoadParameterFile  }"
+	eval "$file_menu add command -label \"Import Legacy fMRI Setup File\" -command { $this ImportfMRISetup  }"
+	eval "$file_menu add separator"
+
+	eval "$file_menu add command -label \"Change Directory...\" -command {$this GetName work_dir} "
+	set thisparam($this,custdirectories)  [ pxitclfilelistmenu \#auto $file_menu "Custom Directories" "$this SwitchDirectory" ]
+	$thisparam($this,custdirectories) SetModeToDirectories
+	$thisparam($this,custdirectories) InitializeDisplay
+	global env
+
+	set tthis [ itcl::scope $this ]
+	set thisparam($this,custsetups)  [ pxitclfilelistmenu \#auto $file_menu "Setup Files" "$tthis LoadSetupFile" "$tthis GetSetupName" ]
+	$thisparam($this,custsetups) SetModeToCustom "Setup Files" .xmlg [ file join $env(HOME) .xmlgfiles ] 1 
+	$thisparam($this,custsetups) InitializeDisplay
+	$file_menu add separator
+
+	if { $standalone == 1 } {
+	eval "$file_menu add command -label Exit -command { $this ExitCommand }"
+	} else {
+	eval "$file_menu add command -label Close -command { wm withdraw $basewidget }"
+	}
+	set tools_menu [menu $menubase.tools -tearoff 0]
+	$menubase add cascade -underline 0 -label "Tools" -menu $tools_menu
+
+	
+	
+	eval "$tools_menu add command -label \"Global Search and Replace\" -command {$this ReplaceStringGUI}"
+
+	set help_menu [menu $menubase.help -tearoff 0]
+	$menubase add cascade -underline 0 -label "Help" -menu $help_menu
+
+	eval "$help_menu add command -label \"Command Line Usage\" -command { $this ShowCommandLineOptions } "
+	eval "$help_menu add command -label \"Console\" -command { pxtkconsole} "
+	if { $standalone == 1 } {
+	set pref_dialog [ ::pxtcluserprefs::CreatePreferenceEditor ]
+	eval "$help_menu add command -label Preferences -command { wm deiconify $pref_dialog}"
+	}	
+
+	$help_menu add separator
+	eval "$help_menu add command -label \"About\" -command {$this AboutCommand} "
+
+
+	$this SetProcessingDefaults
+}
+
+
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::CheckTransformation { thistransformation } {
+
+	set name1 ""
+	set mode $thistransformation
+	
+	switch -exact $mode {
+	"referenceTransform" {
+		set name1 "reference_brain_path"
+		set name2 "anatomical"
+	}
+	"internalTransform" {
+		set name1 "anatomical"
+		set name2 "conventional"
+	}
+	"distortionTransform" {
+		set name1 "conventional"
+		set name2 "run1"
+	}
+	"inverseReferenceTransform" {
+		set name2 "reference_brain_path"
+		set name1 "anatomical"
+	}
+	}
+	
+	if { $name1 == "" } {
+	return 0
+	}
+
+	set img1 [ [ pxitclimage \#auto ] GetThisPointer ]
+	puts stderr "name1=$name1, $parameters($this,$name1) "
+	set ok1  [ $img1 Load $parameters($this,$name1) ]
+	
+	set img2 [  [ pxitclimage \#auto ] GetThisPointer ]
+	if { $name2 != "run1" } {
+	set ok2  [ $img2 Load $parameters($this,$name2) ]
+	puts stderr "name2=$name2, $parameters($this,$name2) "
+	} else {
+	set fn  $parameters($this,run_file_1)
+	set ok2 [ $img2 Load $fn ]
+	if { $ok2 > 0 } {
+		set extr [ vtkImageExtractComponents New ]
+		$extr SetComponents 0
+		$extr SetInput [ $img2 GetImage ]
+		$extr Update
+		$img2 ShallowCopyImage [ $extr GetOutput ]
+		$extr Delete
+	}
+	}
+
+	set tr [ [ pxitcltransform \#auto ] GetThisPointer ]
+	set ok3 [ $tr Load $parameters($this,$thistransformation) ]
+	puts stderr "Loading tr from $parameters($this,$thistransformation)"
+
+
+	if { $ok1 ==0 || $ok2 ==0 || $ok3 ==0 } {
+	tk_messageBox -type ok -title "Can't Check Transformation" -message "name1=$ok1, name2=$ok2, transform=$ok3"
+	return 0
+	} else {
+
+	puts stderr "Img1 = $img1, range = [ [ [ [ $img1 GetImage ] GetPointData ] GetScalars ] GetRange ]"
+	puts stderr "Img2 = $img2, range = [ [ [ [ $img2 GetImage ] GetPointData ] GetScalars ] GetRange ]"
+
+	set check_alg [ bis_colorblendimage \#auto ] 
+	$check_alg InitializeFromContainer 0 $this
+	$check_alg SetInput $img1
+	$check_alg SetSecondInput $img2
+	$check_alg SetTransformation $tr
+	$check_alg Execute
+
+	set img [ $check_alg GetOutput ]
+	$orthoviewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+				
+	itcl::delete obj $check_alg
+
+	}
+
+	# --------------------------------------------------------------------------------------------
+
+	itcl::delete obj $img1
+	itcl::delete obj $img2
+	itcl::delete obj $tr
+}
+
+# --------------------------------------------------------------------------------------------
+
+itcl::body bis_fmri::OverlayVOIImage { { doblend 1 } } {
+
+	set name1 "run1"
+	set img1 [ [ pxitclimage \#auto ] GetThisPointer ]
+	if { $name1 != "run1" } {
+	set ok2  [ $img1 Load $parameters($this,$name2) ]
+	} else {
+	set fn  $parameters($this,run_file_1)
+	set ok2 [ $img1 Load $fn ]
+	if { $ok2 > 0 } {
+		set extr [ vtkImageExtractComponents New ]
+		$extr SetComponents 0
+		$extr SetInput [ $img1 GetImage ]
+		$extr Update
+		$img1 ShallowCopyImage [ $extr GetOutput ]
+		$extr Delete
+	}
+	}
+
+
+	set img2 [ lindex [ $this GetReslicedVOIImage $img1 ] 0 ]
+	if { $img2 == 0 } {
+	set ok [ tk_messageBox -type ok  -title "WARNING!" -message "Bad VOI Dimensions" ]
+	catch { itcl:delete obj $img1 }
+	return 0
+	}
+
+#
+#    set thr [ vtkImageThreshold New ]
+#    $thr SetInput [ $img2 GetImage ]
+#    $thr ThresholdBetween 1 100000000000000000000000000000
+#    $thr ReplaceInOn
+#    $thr ReplaceOutOn
+#    $thr SetInValue 100
+#    $thr SetOutValue 0
+#    $thr Update
+#    $img2 ShallowCopyImage [ $thr GetOutput ]
+#    $thr Delete
+
+
+
+	if { $doblend == 1 } {
+
+	set extr [ vtkImageExtractComponents New ]
+	$extr SetComponents 0
+	$extr SetInput [ $img1 GetImage ]
+	$extr Update
+	$img1 ShallowCopyImage [ $extr GetOutput ]
+	$extr Delete
+	
+	set tr [ [ pxitcltransform \#auto ] GetThisPointer ]
+	
+	
+	set check_alg [ bis_colorblendimage \#auto ] 
+	$check_alg InitializeFromContainer 0 $this
+	$check_alg SetInput $img2
+	$check_alg SetSecondInput $img1
+	$check_alg SetTransformation $tr
+	
+	$check_alg Execute
+	
+	set img [ $check_alg GetOutput ]
+	$orthoviewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+	itcl::delete obj $check_alg
+	itcl::delete obj $tr
+	} else {
+	$orthoviewer SetImage [ $img2 GetImage ] [ $img2 GetOrientation ]
+	}
+	
+	$notebook view "DataTree"
+				
+
+	itcl::delete obj $img1
+	itcl::delete obj $img2
+
+}
+
+# --------------------------------------------------------------------------------------------
+
+itcl::body bis_fmri::DisplayImage {thisimage } {
+  
+
+	set imagepath $::pxtclvtkpxcontrib::imagedir
+
+	set ind [ lsearch -exact $referenceimagenames $parameters($this,$thisimage) ]
+	if { $ind >=0 } {
+	set thisimage  "reference_brain_path"
+	set parameters($this,$thisimage) [ file join $imagepath [ lindex $referenceimagepaths $ind ] ]
+	} elseif {$thisimage=="display_reference_brain"} { 
+	set thisimage "reference_brain_path"
+	set parameters($this,$thisimage) $parameters($this,reference_brain) 
+	} elseif {$thisimage=="display_reference_gw_map"} { 
+	set thisimage "reference_gw_map"
+	set parameters($this,$thisimage) $parameters($this,reference_gw_map) 
+	}
+
+	if { $parameters($this,$thisimage)!="" && [file exists $parameters($this,$thisimage)]==1} {
+
+	set img [ [ pxitclimage \#auto ]  GetThisPointer ]
+	$img Load $parameters($this,$thisimage)
+	set parameters($this,viewerfilename) $parameters($this,$thisimage)
+
+	if { $ownsorthoviewer > 0 } {
+		$orthoviewer SetImage [ $img GetImage ] [ $img GetOrientation ]
+	} else {
+		$orthoviewer SetImageFromObject $img $this
+	}
+	itcl::delete object $img
+
+	} else {   
+	tk_messageBox -type ok -title "Can't View!" -message "The filename is not specified or the image does not exist! " 
+	}
+}
+
+
+#Sets up replace string window with a pair of entrywidgets, one the search string and the second with content with which to replace
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::ReplaceStringGUI { } {
+
+
+	set parameters($this,replacer) ""
+	set parameters($this,searchstring) ""
+
+	if { $replacewidget != 0 } {
+	wm withdraw  $replacewidget
+	wm deiconify $replacewidget
+	return
+	}
+
+	set replacewidget [ toplevel $basewidget.[ pxvtable::vnewobj ]]
+	wm title $replacewidget "Search And Replace"
+	
+	set parameters($this,replacer) ""
+	set parameters($this,searchstring) ""
+		
+	iwidgets::Labeledframe $replacewidget.frame -labelpos nw -labeltext "Search and Replace" -relief ridge
+	pack $replacewidget.frame -side top -expand true -fill both -pady 2
+	
+	set replace_frame [$replacewidget.frame childsite]
+	
+	frame $replace_frame.1
+	frame $replace_frame.2
+	frame $replace_frame.3
+	pack  $replace_frame.1 $replace_frame.2 $replace_frame.3 -side top
+
+	eval "iwidgets::entryfield $replace_frame.1.1 -labeltext \"Search for:   \" -width 60 -textvariable [itcl::scope parameters($this,searchstring)] -relief sunken -textbackground white"
+	eval "iwidgets::entryfield $replace_frame.2.1 -labeltext \"Replace with: \" -width 60 -relief sunken -textvariable [itcl::scope parameters($this,replacer)] -textbackground white"
+	eval "button $replace_frame.3.1 -text \"Replace!\" -command {$this ReplaceString}"
+	
+	pack $replace_frame.1.1 -side left -expand true -padx 5 -pady 6
+	pack $replace_frame.2.1 -side left -expand true -padx 5 -pady 6
+	pack $replace_frame.3.1 -side bottom -expand false -padx 30 -pady 6
+
+
+}
+
+#Does the actual replacing specified in "ReplaceStringGUI" method
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::ReplaceString { } {
+
+	# ------ -start ind (0)
+	# oldsuffix == searchstring
+	# f = old text variable
+	# newsuffix = relacer
+	# f2 (note the lack of a $ sign) is the neame of the variable to store the output
+	#  regsub "input" $f1 output f2 ; set f1 $f2; unset f2
+	
+
+
+	set ok [ tk_messageBox -type yesno -default no -title "WARNING!" -message "Replace $parameters($this,searchstring) with $parameters($this,replacer)?" ]
+	if { $ok=="no" } {
+	return
+	}
+
+	catch { wm withdraw  $replacewidget }
+
+	
+	set parlist "subject_id session_id"
+	foreach {list_mem} {subject_id study_title display_conventional conventional display_anatomical anatomical display_referenceTransform referenceTransform display_internalTransform internalTransform display_distortionTransform distortionTransform session_id session_description xml_output_file output_dir  xml_output_dir } {
+	regsub -all $parameters($this,searchstring) $parameters($this,$list_mem) $parameters($this,replacer) f2
+	set parameters($this,$list_mem) $f2; unset f2
+	}
+		
+	for {set runcount 1} {$runcount <= $numruns} {incr runcount} {
+	regsub -all $parameters($this,searchstring) $parameters($this,run_file_$runcount) $parameters($this,replacer) f3
+	regsub -all $parameters($this,searchstring) $parameters($this,display_run_file_$runcount) $parameters($this,replacer) f4
+	set parameters($this,run_file_$runcount) $f3; unset f3
+	set parameters($this,display_run_file_$runcount) $f4; unset f4
+	}
+
+	
+
+	$runslistbox clear 
+	for {set runcount 1} {$runcount <= $numruns } {incr runcount} {
+	$runslistbox insert end "Run_${runcount}_$parameters($this,display_run_file_${runcount})"
+	}
+
+
+	regsub -all $parameters($this,searchstring) $setupname $parameters($this,replacer) f3
+	set setupname $f3
+
+	wm title $basewidget "BioImage Suite::$appname [ file tail $setupname ]"
+	update idletasks
+}
+#----------------------------------------------------------------------------------------------------  
+itcl::body bis_fmri::CreateTreeTab {base} {
+
+	set treewidget [ [ bis_treewidget \#auto ] GetThisPointer ]
+	if { $bis_viewer!= 0 } {
+	$treewidget SetBisViewer $bis_viewer
+	} else {
+	$treewidget SetViewer $orthoviewer
+	}
+	$treewidget CreateGUI $base 1 1
+}
+
+#Creates description 
+#Called in CreateGUI
+#This tab asks for the study description information, i.e. study title, subject ID, reference (colin) brain path and filename
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::CreateDescriptionTab {base} {
+
+	set w $base
+	eval "iwidgets::entryfield $w.1 -textbackground white -textvariable  [ itcl::scope parameters($this,study_title) ] -width 18 -labeltext \"Study Title:           \""
+	eval "iwidgets::entryfield $w.2 -textbackground white -textvariable [ itcl::scope parameters($this,subject_id)] -width 18 -labeltext \"Subject ID:           \""
+	
+	frame $w.3 
+	frame $w.4
+	 
+	pack $w.1 $w.2 $w.3 $w.4 -side top -fill x -padx 5 -pady 5
+	set parameters($this,reference_brain) ""
+	
+	eval "iwidgets::combobox $w.3.1 -textbackground white  -labeltext \"Reference Brain: \"  -width 50  -textvariable [ itcl::scope parameters($this,display_reference_brain) ] -relief sunken"
+	for { set i 0 } { $i < [ llength $referenceimagenames ] } { incr i } {
+	$w.3.1 insert list end [ lindex $referenceimagenames $i ]
+	}
+	eval "button $w.3.3 -text \"View\" -command {$this DisplayImage display_reference_brain}"
+	eval "button $w.3.2 -text \"...\" -command {  $this GetName reference_brain}"
+	
+
+
+
+	pack $w.3.1 -side left -expand true -fill x -padx 2 -pady 1
+	pack $w.3.3 -side right -expand false -fill x -padx 4 -pady 1
+	pack $w.3.2 -side right  -expand false -fill x -padx 4 -pady 1
+
+
+	eval "iwidgets::entryfield $w.4.1 -state disabled  -labeltext \"GrayCSFWhite Map: \"  -width 40  -textvariable [ itcl::scope parameters($this,display_reference_gw_map) ] -relief sunken"
+
+	eval "button $w.4.3 -text \"View\" -command {$this DisplayImage display_reference_gw_map}"
+	eval "button $w.4.2 -text \"...\" -command {  $this GetName reference_gw_map}"
+	
+
+
+
+	pack $w.4.1 -side left -expand true -fill x -padx 2 -pady 1
+	pack $w.4.3 -side right -expand false -fill x -padx 4 -pady 1
+	pack $w.4.2 -side right  -expand false -fill x -padx 4 -pady 1
+
+	::iwidgets::Labeledwidget::alignlabels $w.1 $w.2 $w.3.1 $w.4.1
+   
+}
+
+#----------------------------------------------------------------------------------------------------  
+itcl::body bis_fmri::DisplayFilenames { } {
+	$subjectframe.1.conventional clear
+	puts $parameters($this,conventional)
+}
+
+#Creates image tab
+#Called in CreateGUI
+#Asks the user to input image and transformation fully specified filenames
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::CreateImageDataTab {base} {
+	
+	set parameters($this,conventional) ""
+	set parameters($this,anatomical) ""
+	set parameters($this,referenceTransform) ""     
+	set parameters($this,internalTransform) ""
+	set parameters($this,distortionTransform) ""
+	set parameters($this,voiDefinitionImage) ""
+	set parameters($this,inverseReferenceTransform) ""
+	set parameters($this,reference_brain_path) ""
+	
+	set subjectframe  $base
+	frame $subjectframe.1;
+	frame $subjectframe.2;
+	frame $subjectframe.3;
+	frame $subjectframe.4;
+	frame $subjectframe.5;
+	frame $subjectframe.6 -bg black -height 2;
+	frame $subjectframe.7;
+	frame $subjectframe.8;
+	
+	
+	set convtail [file tail $parameters($this,conventional)]
+	pack $subjectframe.1  $subjectframe.2 $subjectframe.3 $subjectframe.4 $subjectframe.5 $subjectframe.6 $subjectframe.7 $subjectframe.8 -side top -fill x -padx 2 -pady 5
+	
+	eval "iwidgets::entryfield $subjectframe.1.conventional -state disabled  -labeltext \"Conventional Image:  \"  -width 40  -textvariable [ itcl::scope  parameters($this,display_conventional)] -relief sunken"
+	eval "button $subjectframe.1.1 -text \"...\" -command { $this GetName conventional}"
+	eval "button $subjectframe.1.2 -text \"View\" -command {$this DisplayImage conventional }"
+   
+	eval "iwidgets::entryfield $subjectframe.2.anatomical -state disabled -labeltext   \"Anatomical Image:     \"  -width 40  -textvariable [ itcl::scope parameters($this,display_anatomical)] -relief sunken"
+	eval "button $subjectframe.2.2 -text \"...\" -command {$this GetName anatomical}"
+	eval "button $subjectframe.2.3 -text \"View\" -command {$this DisplayImage anatomical }"
+	eval "iwidgets::entryfield $subjectframe.3.referenceTransform -state disabled -labeltext \"Reference Transform:\"  -width 40  -textvariable [ itcl::scope parameters($this,display_referenceTransform)] -relief sunken"
+	eval "button $subjectframe.3.3 -text \"...\" -command {$this GetName referenceTransform}"
+	eval "button $subjectframe.3.4 -text \"Check\" -command {$this CheckTransformation referenceTransform }"
+
+	eval "iwidgets::entryfield $subjectframe.4.internalTransform -state disabled -labeltext  \"Internal Transform:     \"  -width 40 -textvariable [ itcl::scope parameters($this,display_internalTransform)] -relief sunken"
+	eval "button $subjectframe.4.4 -text \"...\" -command {$this GetName internalTransform}"
+	eval "button $subjectframe.4.5 -text \"Check\" -command {$this CheckTransformation internalTransform }"
+
+	eval "iwidgets::entryfield $subjectframe.5.distortionTransform -state disabled -labeltext \"Distortion Transform:  \"  -width 40  -textvariable [ itcl::scope parameters($this,display_distortionTransform)] -relief sunken"
+	eval "button $subjectframe.5.5 -text \"...\" -command {$this GetName distortionTransform}"
+	eval "button $subjectframe.5.6 -text \"Check\" -command {$this CheckTransformation distortionTransform }"
+
+	eval "iwidgets::entryfield $subjectframe.7.voiDefinitionImage -state disabled -labeltext \"VOI  Image:  \"  -width 40  -textvariable [ itcl::scope parameters($this,display_voiDefinitionImage)] -relief sunken"
+	eval "button $subjectframe.7.7 -text \"...\" -command {$this GetName voiDefinitionImage}"
+	eval "button $subjectframe.7.8 -text \"View\" -command {$this DisplayImage voiDefinitionImage }"
+
+	eval "iwidgets::entryfield $subjectframe.8.inverseReferenceTransform -state disabled -labeltext \"Inverse Reference Transform:\"  -width 40  -textvariable [ itcl::scope parameters($this,display_inverseReferenceTransform)] -relief sunken"
+	eval "button $subjectframe.8.8 -text \"...\" -command {$this GetName inverseReferenceTransform}"
+	eval "button $subjectframe.8.9 -text \"Check\" -command {$this CheckTransformation inverseReferenceTransform }"
+
+	
+
+	pack $subjectframe.1.2 -side right -expand false -padx 2 -pady 1
+	pack $subjectframe.1.1 -side right -expand false -padx 2 -pady 1
+	pack $subjectframe.1.conventional -side left -expand true -fill x -padx 5 -pady 1 
+
+	pack $subjectframe.2.3 -side right -expand false -padx 2 -pady 1
+	pack $subjectframe.2.2 -side right -expand false -padx 2 -pady 1
+	pack $subjectframe.2.anatomical -side left -expand true -fill x -padx 5 -pady 1
+
+	pack $subjectframe.3.4 -side right -expand false -padx 5 -pady 1  
+	pack $subjectframe.3.3 -side right -expand false -padx 5 -pady 1  
+	pack $subjectframe.3.referenceTransform -side left -expand true -fill x -padx 5 -pady 1
+
+	pack $subjectframe.4.5 $subjectframe.4.4 -side right -expand false -padx 5 -pady 1 
+	pack $subjectframe.4.internalTransform -side left -expand true -fill x -padx 5 -pady 1
+
+	pack $subjectframe.5.6 $subjectframe.5.5 -side right -expand false -padx 5 -pady 1
+	pack $subjectframe.5.distortionTransform -side left -expand true -fill x -padx 5 -pady 1 
+
+
+
+	pack $subjectframe.7.8 -side right -expand false -padx 2 -pady 1
+	pack $subjectframe.7.7 -side right -expand false -padx 2 -pady 1
+	pack $subjectframe.7.voiDefinitionImage -side left -expand true -fill x -padx 5 -pady 1 
+
+
+	pack $subjectframe.8.9 $subjectframe.8.8 -side right -expand false -padx 5 -pady 1
+	pack $subjectframe.8.inverseReferenceTransform -side left -expand true -fill x -padx 5 -pady 1 
+
+	::iwidgets::Labeledwidget::alignlabels $subjectframe.1.conventional $subjectframe.2.anatomical $subjectframe.3.referenceTransform $subjectframe.4.internalTransform $subjectframe.5.distortionTransform $subjectframe.7.voiDefinitionImage $subjectframe.8.inverseReferenceTransform
+
+
+	set fr [  frame $subjectframe.9 ]; pack $fr -side top -expand false -fill x
+
+	label $fr.0 -text "VOI Space:"
+	tk_optionMenu $fr.1  [ itcl::scope parameters($this,voiDefinitionSpace) ] Reference Anatomical Conventional Functional
+	eval "button $fr.2 -command { $this OverlayVOIImage  1 } -text \"Check VOI Image \" "
+	eval "button $fr.3 -command { $this OverlayVOIImage  0 } -text \"Check VOI Image (no overlay)\" "
+	pack $fr.2 $fr.3 -side right -padx 2
+
+	for { set i 0 } { $i <= 3 } { incr i } {
+	eval "$fr.1.menu  entryconfigure $i -command \"$this UpdateDataTreeStructure\" "
+	}
+
+
+	pack $fr.0 $fr.1 -side left -padx 5
+
+
+	
+}
+
+
+#Creates Session tab
+#Called in CreateGUI
+#Asks the user to input descriptive session information for the desired fMRI session, as well as runs fully specified pathnames and 
+#task descriptions
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::CreateSessionTab {base} {
+
+	set session $base
+	frame $session.sessionid
+   
+	
+	eval "iwidgets::entryfield $session.sessionid.1 -textbackground white -labeltext \"Session ID:               \" -width 60 -textvariable [itcl::scope parameters($this,session_id)] -relief sunken"
+	eval "iwidgets::entryfield $session.sessionid.2 -textbackground white -labeltext \"Session Description: \" -width 60 -textvariable [itcl::scope parameters($this,session_description)] -relief sunken"
+	eval "iwidgets::entryfield $session.sessionid.3 -textbackground white -labeltext \"Repetition Time:       \" -width 60 -textvariable [itcl::scope parameters($this,tr)] -relief sunken  -validate real"
+	eval "iwidgets::entryfield $session.sessionid.4 -textbackground white -labeltext \"Number of Slices:     \" -width 60 -textvariable [itcl::scope parameters($this,numslices)] -relief sunken -validate integer"
+	eval "iwidgets::entryfield $session.sessionid.5 -textbackground white  -labeltext \"Number of Frames:   \" -width 60 -textvariable [itcl::scope parameters($this,numframes)] -relief sunken -validate integer"
+	checkbutton $session.sessionid.6 -highlightthickness 0  -variable [ itcl::scope parameters($this,blockunits) ] -justify left -text "Blocks Defined in Seconds" -underline 0 
+
+	pack  $session.sessionid.1 $session.sessionid.2 $session.sessionid.3 $session.sessionid.4 $session.sessionid.5 $session.sessionid.6 -side top -expand true -fill x -padx 10 -pady 2
+
+	frame $session.mid -bg black -height 5
+	frame $session.mid2 -bg black -height 5
+	frame $session.taskorruns
+	frame $session.skipframes
+	frame $session.taskorruns.task
+	frame $session.taskorruns.mid -bg black -width 5
+	frame $session.taskorruns.runs
+	eval "button $session.blocks -text \"Define Blocks\" -command {$this CreateBlockEditingDialog }"
+	option add *$session.blocks.borderWidth: 3
+	$session.blocks configure -borderwidth 3
+
+	pack  $session.sessionid $session.skipframes $session.mid  $session.taskorruns $session.mid2 $session.blocks -side top -expand false -fill x -padx 10 -pady 2
+
+
+	# Add new buttons here
+	#
+	iwidgets::Labeledframe $session.glmextra -labelpos nw -labeltext "Use Predefined Matrix" -relief ridge
+	pack $session.glmextra -side bottom -expand false -fill x -pady 5
+	set w [ $session.glmextra childsite ]
+	checkbutton $w.0 -highlightthickness 0  -variable [ itcl::scope parameters($this,glmextra_useexternalmatrix) ] -justify left -text "Use External Task Matrix" -underline 0 
+	checkbutton $w.1 -highlightthickness 0  -variable [ itcl::scope parameters($this,glmextra_doconvolution) ] -justify left -text "Convolve External Matrix with HRF" -underline 0 
+	frame $w.2
+	pack $w.0 $w.1 $w.2 -side top -expand false -fill x -padx 3
+
+	eval "iwidgets::entryfield $w.2.fname -state disabled  -labeltext \"Matrix Filename:  \"  -width 40  -textvariable [ itcl::scope  parameters($this,glmextra_externalmatrixfilename)] -relief sunken"
+	eval "button $w.2.bt -text \"..\" -command { $this GetMatrixName}"
+	pack $w.2.bt -side right -padx 2 -expand false
+	pack $w.2.fname -side left -expand false -fill x
+
+
+
+
+	# 
+
+	
+	set skipframesentry $session.skipframes.2
+	eval "iwidgets::entryfield $skipframesentry -width 60  -state disabled  -textvariable [itcl::scope parameters($this,skipFrames)]"
+	set checkb $session.skipframes.1
+
+	set parameters($this,checks) 0
+
+	::iwidgets::Labeledwidget::alignlabels $session.sessionid.1 $session.sessionid.2 $session.sessionid.3 $session.sessionid.4 $session.sessionid.5 $skipframesentry
+
+	eval "checkbutton $checkb -highlightthickness 0  -variable [ itcl::scope parameters($this,checks) ] -justify left -text \"Skip Frames?\" -underline 0 -command { $this ToggleFrameEntry $skipframesentry $checkb }"
+	pack $session.skipframes.1 $session.skipframes.2 -side left  -expand true -fill x -padx 2 -pady 0
+	pack $session.taskorruns.task -side left -expand true 
+	pack $session.taskorruns.mid  -side left -expand false -fill y
+	pack $session.taskorruns.runs -side left -expand true 
+
+	set runslistbox [eval "iwidgets::scrolledlistbox $session.taskorruns.runs.slb -labeltext \"Define Runs: \"  \
+		 -vscrollmode dynamic -hscrollmode none \
+		 -selectmode single \
+		 -labelpos nw \
+		 -textbackground white\
+		 -dblclickcommand {$this OperationOnCurrentRun 3 }" ]
+	
+	set w [ frame $session.taskorruns.runs.slb_buttons ]
+	
+	pack $runslistbox $w  -side top -expand false -fill x
+	
+	eval "button $w.add -width 4 -text \"New\" -command {$this EditRunGUI } -padx 1"
+	eval "button $w.delete -width 4 -text \"Del\" -command { $this OperationOnCurrentRun 1} -padx 1"
+	eval "button $w.view -width 6 -text \"Display\" -command {$this OperationOnCurrentRun 2 } -padx 1"
+	eval "button $w.edit -width 4 -text \"Edt\" -command {$this OperationOnCurrentRun 3 } -padx 1"
+	eval "button $w.printall -width 6 -text \"Show All\" -command {$this OperationOnCurrentRun 4 } -padx 1"
+	pack $w.add $w.delete $w.edit $w.view $w.printall -side left -expand false -fill x      
+	
+	  
+	set tasklistbox [eval "iwidgets::scrolledlistbox $session.taskorruns.task.slb -labeltext \"Define Tasks: \"  \
+		 -vscrollmode dynamic -hscrollmode none \
+		 -selectmode single \
+		 -labelpos nw \
+		 -textbackground white\
+		 -dblclickcommand {$this OperationOnCurrentTask 0 }" ]
+	
+	set w [ frame $session.taskorruns.task.slb_buttons ]
+	pack $tasklistbox $w  -side top -expand false -fill x
+	
+	eval "button $w.add -width 8  -text \"New Task\" -command {$this EditTaskGUI} -padx 0"
+	eval "button $w.delete -width 8 -text \"Delete\" -command { $this OperationOnCurrentTask 1} -padx 0"
+	eval "button $w.edit -width 8 -text \"Edit\" -command { $this OperationOnCurrentTask 0 } -padx 0"
+		
+	pack $w.add $w.edit $w.delete -side left -expand true -fill x           
+}
+
+#Skip Frame toggle control
+#Called in CreateSessionTab
+#When user selects checkbox to skip frames in main window or runs window, changes entrywidget from disabled to active, and vice-versa
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::ToggleFrameEntry { entryw checkb } {
+
+	set var [ $checkb cget -variable ]
+	eval "set state  $$var "
+   
+	if {$state== 0 } {
+	$entryw configure -state disabled 
+	} else {
+	$entryw configure -state normal -textbackground white
+	}
+}
+
+#Determines the cursor location where user clicks desired task
+#Called in CreateSessionTab
+#When user clicks, reads the line and keeps the task number
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::OperationOnCurrentTask {p} {
+
+	set taskcurse [$tasklistbox getcurselection]
+	set ind [ string first "-" $taskcurse ]
+	if { $ind > 0 } {
+	set tasknum [string range $taskcurse 1 [ expr $ind -  1  ]]
+	} else {
+	set tasknum ""
+	}
+	if {$tasknum==""} {
+	tk_messageBox -type ok -title "Error!" -message "No task selected"
+	return
+	}
+
+	if {$p==0} {
+	$this EditTaskGUI $tasknum
+	} elseif {$p==1} {
+	RemoveTask $tasknum
+	}  
+}
+#Determines the cursor location where user clicked
+#Called in CreateSessionTab
+#When user clicks, reads the line and keeps the run number
+#----------------------------------------------------------------------------------------------------
+# RUN Stuff
+# ---------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::OperationOnCurrentRun { m } {
+
+	if { $m!=4 } {
+	set curse [$runslistbox getcurselection]
+	set num [string range $curse 4 5 ]
+#	puts stderr "Num1=$num"
+	if { [ string range $num 1 1 ] == "_" } {
+		set num [ string range $num 0 0 ]
+	}
+#	puts stderr "Num2=$num"
+
+	if {$num==""} {
+		tk_messageBox -type ok -title "Error!" -message "Please select a run!"
+		return
+	} 
+	
+	if { $m==0} {
+		EditRunGUI $num
+	} elseif {$m==1} {
+		RemoveRun $num
+	} elseif {$m==2} {
+		$this DisplayImage run_file_$num 
+	} elseif {$m==3 } {
+		$this EditRunGUI $num
+	} 
+	} else {
+	pxtkconsole
+	pxtkprint "\n\n Run Information\n"
+	
+	if { $parameters($this,checks) > 0 } {
+		pxtkprint "#Frames to Skip in Allframes\n"
+		pxtkprint "$parameters($this,skipFrames)\n"
+	} 
+	for {set runcount 1} {$runcount <= $numruns} {incr runcount} {
+		pxtkprint "\n#Run $runcount/$numruns\n"
+		pxtkprint "$parameters($this,run_file_$runcount)\n"
+		if { $parameters($this,runskip_$runcount) == 0 } {
+		pxtkprint "No Skip Frames\n"
+		} else {
+		pxtkprint "Skip Frames:$parameters($this,skiprunsframe_${runcount})\n"
+		}
+	}
+	pxtkprint "\n\n"
+	}
+
+
+}
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::RemoveRun { rmtype} {
+	
+	if { $numruns < 1 } {
+	return 0
+	}
+
+	set ok [ tk_messageBox -type yesno -default no -title "WARNING!" -message "Are you sure you want to delete this run?" ]
+	if { $ok == "no" } {return }
+	set hold($this,run) " "
+	set hold($this,display_run) ""
+	set parameters($this,run_file_$rmtype) ""
+	set parameters($this,run_motionfile_$rmtype) ""
+	set parameters($this,skiprunsframe_$rmtype) ""
+	set parameters($this,runskip_$rmtype) ""
+	set parameters($this,display_run_file_$rmtype) ""
+	set parameters($this,display_run_motionfile_$rmtype) ""
+	for {set c $rmtype} {$c<$numruns} {incr c} {
+	set cplus1 [expr $c+1]
+	set parameters($this,run_file_$c) $parameters($this,run_file_$cplus1)
+	set parameters($this,display_run_file_$c) $parameters($this,display_run_file_$cplus1)
+	set parameters($this,run_motionfile_$c) $parameters($this,run_motionfile_$cplus1)
+	set parameters($this,display_run_motionfile_$c) $parameters($this,display_run_motionfile_$cplus1)
+	
+
+	}
+	for {set runcount $rmtype} {$runcount<$numruns} {incr runcount} {
+	for {set taskcount 1} {$taskcount<=$numtasks} {incr taskcount} {
+		set taskcountplus1 [expr $taskcount+1]
+		set runcountplus1 [expr $runcount+1]
+		
+		set parameters($this,tframe_${taskcount}_$runcount) $parameters($this,tframe_${taskcount}_$runcountplus1)
+		set parameters($this,tframe_${taskcount}_$runcountplus1) ""
+		
+		
+	}
+	}
+	
+	
+	set numruns [expr $numruns-1]
+	$runslistbox clear
+	$this AddAllRuns
+	$this CloseBlockWidget
+	$this UpdateDataTreeStructure ""
+}
+
+#Pop-up window when run is added
+#Called in AddOrEditTaskorRun, OperationOnCurrentRun
+#Pop up when run added, asks used for fully specified filename for the run
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::EditRunGUI { { index -1 } } {
+	
+#    puts stderr "Edit Run GUI = $index"
+
+	if { $index == -1 } {
+	set trueindex [expr $numruns+1]
+	set title "Define New Run"
+	set hold($this,run) " "
+	set hold($this,runmotion) " "
+	set hold($this,display_run) ""
+	set hold($this,display_runmotion) ""
+	set hold($this,skipframe) " "
+	set hold($this,runskip) 0
+	set hold($this,runindex) -1
+	} else {
+	set trueindex $index
+	if { $index < 1 } { 
+		set trueindex 1
+	} elseif { $index > $numruns } {
+		set trueindex $numruns
+	}
+	set title "Editing Run $trueindex"
+	set hold($this,run)  $parameters($this,run_file_$trueindex)
+	set hold($this,runmotion)  $parameters($this,run_motionfile_$trueindex)
+	set hold($this,display_run) [file tail $parameters($this,run_file_$trueindex)]
+	set hold($this,display_runmotion) [file tail $parameters($this,run_motionfile_$trueindex)]
+	set hold($this,skipframe) $parameters($this,skiprunsframe_$trueindex)
+	set hold($this,runskip)   $parameters($this,runskip_$trueindex)
+	set hold($this,runindex) $trueindex
+	}
+
+
+	if { [ winfo exists $runwidget  ] > 0 } {
+	wm withdraw $runwidget
+	wm deiconify $runwidget
+	wm title $runwidget $title
+	if { $hold($this,runskip) == 1 } {
+		$hold($this,run_frame_entry) configure -state normal
+	} else {
+		$hold($this,run_frame_entry) configure -state disabled
+		set hold($this,skipframe) ""
+	}
+	return 0
+	} 
+	
+	set runwidget [ toplevel $basewidget.[ pxvtable::vnewobj ]]
+	wm title $runwidget $title
+	iwidgets::Labeledframe ${runwidget}.frame -labelpos nw -labeltext "Filename:" -relief ridge
+	pack ${runwidget}.frame -side top -expand true -fill both -pady 2
+ 
+	set run_frame [${runwidget}.frame childsite]
+   
+	frame $run_frame.1
+	frame $run_frame.15
+	frame $run_frame.2
+	eval "button $run_frame.3 -text \"Apply Changes\" -command {$this AddOrEditRun }"
+	pack $run_frame.3 -side bottom -padx 10 -expand false -fill x
+
+	pack $run_frame.1 $run_frame.15 $run_frame.2 -side top
+
+	eval "iwidgets::entryfield $run_frame.1.1 -labeltext \"Run Filename\" -width 60 -textvariable [itcl::scope hold($this,display_run)] -relief sunken -state disabled"
+	eval "button $run_frame.1.2 -text \"...\" -command {$this GetRunFilename -1 tohold}"
+
+	eval "iwidgets::entryfield $run_frame.15.1 -labeltext \"Motion Filename\" -width 60 -textvariable [itcl::scope hold($this,display_runmotion)] -relief sunken -state disabled"
+	eval "button $run_frame.15.2 -text \"...\" -command {$this GetRunMotionFilename -1 tohold}"
+
+	eval "iwidgets::entryfield $run_frame.2.1  -width 70 -relief sunken  -textvariable [itcl::scope hold($this,skipframe)]"
+	set hold($this,run_frame_entry) $run_frame.2.1
+	checkbutton $run_frame.2.2 -highlightthickness 0 -variable [ itcl::scope hold($this,runskip) ] -justify left -text "Skip Frames?"
+	eval "$run_frame.2.2 configure -command { $this ToggleFrameEntry $run_frame.2.1 $run_frame.2.2 }"
+
+
+	if { $hold($this,runskip) == 1 } {
+	$hold($this,run_frame_entry) configure -state normal
+	} else {
+	$hold($this,run_frame_entry) configure -state disabled
+	}
+
+	pack $run_frame.1.2 -side right -expand false -padx 4 -pady 6   
+	pack $run_frame.1.1 -side left -expand true -padx 5 -pady 6
+	pack $run_frame.15.2 -side right -expand false -padx 4 -pady 6   
+	pack $run_frame.15.1 -side left -expand true -padx 5 -pady 6
+
+
+	pack $run_frame.2.2 $run_frame.2.1 -side left -expand true
+	set run_frame [${runwidget}.frame childsite]
+}
+
+
+#Adds run to parameters variables and resets
+#Called in Runs Path
+#Closes runwidget, set parameters, updates runcount 
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::AddOrEditRun { { index -1 } } {
+	catch { wm withdraw ${runwidget} }
+
+	if { $index == -1 } {
+	set index $hold($this,runindex) 
+	}
+	
+	if { $index == -1 } {
+	set index [expr $numruns+1]
+	set numruns [ expr $numruns +1 ]
+	set adding 1
+	} else {
+	set adding 0
+	}
+
+#    puts stderr "Using index = $index"
+
+	set parameters($this,run_file_$index)         $hold($this,run)
+	set parameters($this,display_run_file_$index) [file tail $hold($this,run)]
+
+	set parameters($this,run_motionfile_$index)         $hold($this,runmotion)
+	set parameters($this,display_run_motionfile_$index) [file tail $hold($this,runmotion)]
+
+
+	set parameters($this,runskip_$index)          $hold($this,runskip)
+	if { $parameters($this,runskip_$index) == 0 } {
+	set hold($this,skipframe) ""
+	}
+	set parameters($this,skiprunsframe_$index) $hold($this,skipframe)
+
+	if { $adding == 1 } {
+	$runslistbox insert end "Run_${index}_$parameters($this,display_run_file_${index})"
+		for {set taskcount 1} {$taskcount<=$numtasks} {incr taskcount} {
+		set parameters($this,tframe_${taskcount}_${index}) ""	
+		puts "parameters($this,tframe_${taskcount}_${index})"
+		
+	}
+	} else {
+	$runslistbox delete [ expr $index -1 ] [ expr  $index -1 ]
+	$runslistbox insert [ expr $index -1 ] "Run_${index}_$parameters($this,display_run_file_${index})"
+	}
+
+	$this CloseBlockWidget
+	$this UpdateDataTreeStructure ""
+}
+
+#Pop-up window when task is added
+#Called in AddOrEditTaskorRun
+#Pop up when task added, asks user to type a task description 
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::EditTaskGUI { { index -1 } } {
+
+	if { $index == -1 } {
+	set hold($this,task) ""
+	set hold($this,taskindex) -1
+	set title "Adding New Task"
+	} else {
+	
+	if { $index < 1 } { 
+		set index 1
+	} elseif { $index > $numtasks } {
+		set index $numtasks
+	}
+	set hold($this,taskindex) $index
+	set hold($this,task) $parameters($this,task_$index)
+	set title "Editing Task $index"
+	}
+
+	set d $taskwidget
+	if { [ winfo exists $d  ] } {
+	wm withdraw $d
+	wm deiconify $d
+	wm title $d $title
+	} else {
+	set taskwidget $basewidget.[ pxvtable::vnewobj ]
+	toplevel $taskwidget
+	wm title $taskwidget $title
+	
+	iwidgets::Labeledframe ${taskwidget}.frame -labelpos nw -labeltext "Description for Task" -relief ridge
+	pack ${taskwidget}.frame -side top -expand true -fill both -pady 2
+	
+	set task_frame [${taskwidget}.frame childsite]
+	eval "iwidgets::entryfield $task_frame.1 -labeltext \"Task\" -width 60 -textvariable [itcl::scope hold($this,task)] -textbackground white -relief sunken"
+	eval "button $task_frame.3 -text \"Apply Changes\" -command {$this AddOrEditTask }"
+	
+	pack $task_frame.1 -side left -expand true -padx 5 -pady 6
+	pack $task_frame.3 -side right -expand true     
+	}
+}
+
+
+	
+#Sets task description filename in list
+#Called in EditTaskGUI
+#Default is ' ', once filename specifies replaces default in Session tab with filename    
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::AddOrEditTask { } {
+	 wm withdraw ${taskwidget}
+
+	if { $hold($this,taskindex) != -1 } {
+	set index $hold($this,taskindex)
+	set parameters($this,task_$index) $hold($this,task) 
+	} else {
+	set numtasks [expr $numtasks+1]
+	set parameters($this,task_$numtasks) $hold($this,task)
+	for {set runcount 1} {$runcount<=$numruns} {incr runcount} {
+		set parameters($this,tframe_${numtasks}_${runcount}) ""	
+	}
+	}
+
+	$tasklistbox clear
+	$this AddAllTasks
+	
+	$this CloseBlockWidget
+}
+	
+	
+
+#Removes a task  run if specified by user
+#Called in CreateSessionTab
+#If user chooses to remove task or run, removes the last from the list and decrements the number or tasks or runs, resp.
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::RemoveTask { rmtype} {
+
+	if { $numtasks< 1 } {
+	return
+	}
+	
+	set ok [ tk_messageBox -type yesno -default no -title "WARNING!" -message "Are you sure you want to delete this task?" ]
+	if { $ok == "no" } {return }
+
+	set hold($this,task) ""
+	set parameters($this,task_$rmtype)  ""
+	for {set b $rmtype} { $b<$numtasks} {incr b} {
+	set bplus1 [expr $b+1]
+	set parameters($this,task_$b) $parameters($this,task_$bplus1)
+	
+	}
+	for {set runcount 1} {$runcount<=$numruns} {incr runcount} {
+	for {set taskcount $rmtype} {$taskcount<$numtasks} {incr taskcount} {
+		set taskcountplus1 [expr $taskcount+1]
+		set runcountplus1 [expr $runcount+1]
+		
+		set parameters($this,tframe_${taskcount}_${runcount}) $parameters($this,tframe_${taskcountplus1}_${runcount})
+		set parameters($this,tframe_${taskcountplus1}_${runcount}) ""
+		
+	}
+	}
+	set numtasks [expr $numtasks-1]
+	$tasklistbox clear
+	$this AddAllTasks
+	$this CloseBlockWidget
+	return
+}
+
+#Adds all current tasks
+#Called in ChangeTask
+#Adds all current tasks from beginning when a task is changed to change the name
+#--------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::AddAllTasks { } {
+	for {set c 1} {$c<=$numtasks} {incr c} { 
+		$tasklistbox insert end "T$c-$parameters($this,task_$c)"
+	}
+}
+
+#----------------------------------------------------------------------------------------------------  
+itcl::body bis_fmri::AddAllRuns { } {
+	for {set rm 1} {$rm<=$numruns} {incr rm} {
+	$runslistbox insert end "Run_${rm}_$parameters($this,display_run_file_${rm})"
+	}
+}
+
+
+	
+#Sets the run filename 
+#Called in EditRunGUI
+#Dialog which allows user to browse for runs file
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::GetRunFilename {currentrun mode} {
+	set runfname ""
+	set runfpath ""
+	set filetype  {{"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+	set runfpath [tk_getOpenFile -title "Specify Run Filename" -filetypes $filetype]
+	
+	if { [string length $runfpath ]<1}  {
+		return 0
+	}
+   
+	if {$mode=="tohold"} {
+	set hold($this,run) $runfpath
+	set hold($this,display_run) [file tail $runfpath]
+	} else {
+	set parameters($this,run_file_$currentrun) $runfpath
+	set parameters($this,display_run_file_$currentrun) [file tail $runfpath]
+	}
+}
+
+itcl::body bis_fmri::GetRunMotionFilename {currentrun mode} {
+	set runfname ""
+	set runfpath ""
+	set filetype  {{"Matlab Files" { .mat }}}
+	set runfpath [tk_getOpenFile -title "Specify Run Motion Filename" -filetypes $filetype]
+	
+	if { [string length $runfpath ]<1}  {
+		return 0
+	}
+   
+	if {$mode=="tohold"} {
+	set hold($this,runmotion) $runfpath
+	set hold($this,display_runmotion) [file tail $runfpath]
+	} else {
+	set parameters($this,run_motionfile_$currentrun) $runfpath
+	set parameters($this,display_run_motionfile_$currentrun) [file tail $runfpath]
+	}
+}
+
+
+#Sets files for everything other than the runs
+#Called in multiple methods
+#Dialog which allows user to browse for all but runs files
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::GetName { mode } {
+	set fname ""
+	set filetype1 [ list "Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz } ]
+	set filetype2 [ list "All Files" "*"  ]
+	set filetype3 [ list "Transformation Files" [list .matr .grd]]
+	set updatetree 1
+	
+	switch -exact $mode {
+	    "reference_brain" {
+		set filepath [tk_getOpenFile -title "Load Filename" -initialdir $parameters($this,change_to_directory) -filetypes [ list $filetype1 $filetype2 ] ]
+		set fname [file tail $filepath]
+	    }
+	    "reference_gw_map" {
+		set filepath [tk_getOpenFile -title "Load Filename" -initialdir $parameters($this,change_to_directory) -filetypes [ list $filetype1 $filetype2 ] ]
+		set fname [file tail $filepath]
+	    }
+	    "conventional" {	  
+		set filepath [tk_getOpenFile -title "Load Filename" -initialdir $parameters($this,change_to_directory) -filetypes [ list $filetype1 $filetype2 ]]
+		set fname [file tail $filepath]  
+	    }
+	    "anatomical" {	  
+		set filepath [tk_getOpenFile -title "Load Filename" -initialdir $parameters($this,change_to_directory) -filetypes [ list $filetype1 $filetype2] ]
+		set fname [file tail $filepath] 
+	    }
+	    "voiDefinitionImage" {	  
+		set filepath [tk_getOpenFile -title "Load Filename" -initialdir $parameters($this,change_to_directory) -filetypes [ list $filetype1 $filetype2] ]
+		set fname [file tail $filepath] 
+	    }
+	    "referenceTransform" {	    
+		set filepath [tk_getOpenFile -title "Load Filename" -initialdir $parameters($this,change_to_directory) -filetypes [ list $filetype3 ] ]
+		set fname [file tail $filepath] 
+	    }
+	    "inverseReferenceTransform" {	    
+		set filepath [tk_getOpenFile -title "Load Filename" -initialdir $parameters($this,change_to_directory) -filetypes [ list $filetype3 ] ]
+		set fname [file tail $filepath] 
+	    }
+	    "internalTransform" {	  
+		set filepath  [tk_getOpenFile -title "Load Filename" -initialdir $parameters($this,change_to_directory) -filetypes [ list  $filetype3 ] ]
+		set fname [file tail $filepath] 
+	    }
+	    "distortionTransform" {	    
+		set filepath [tk_getOpenFile -title "Load Filename" -initialdir $parameters($this,change_to_directory) -filetypes [ list  $filetype3 ] ]
+		set fname [file tail $filepath] 
+	    }
+	    "output_dir" {
+		set fname " "
+		set filepath [tk_chooseDirectory -title "Select Current Directory" ]    
+		set updatetree 0
+	    }
+	    "xml_output_dir" {
+		set fname " "
+		set filepath [tk_chooseDirectory -title "Select Current Directory"]
+		set updatetree 0
+	    }
+	    "work_dir" {
+		set fname " "
+		set filepath [tk_chooseDirectory -title "Select Working Directory"]
+		set updatetree 0
+	    }
+	}
+    
+	if { [ string length $fname ] < 1 } {
+	   return
+	}
+
+	if { [ string length $filepath ] < 1} {
+	return
+	}
+
+
+
+	set parameters($this,$mode) $filepath
+	set parameters($this,display_$mode) $fname
+
+	if {  $mode=="work_dir"  } {
+	$this SwitchDirectory $filepath
+	} 
+
+	if { $updatetree > 0 } {
+	$this UpdateDataTreeStructure ""
+	}
+
+}
+
+itcl::body bis_fmri::GetMatrixName {  } {
+	set fname ""
+	set filetype1 [ list "Matrix File Name" { .matr } ]
+	set filetype2 [ list "All Files" "*"  ]
+
+    set f [tk_getOpenFile -title "External GLM Matrix" -initialdir $parameters($this,change_to_directory) -filetypes [ list $filetype1 $filetype2 ] ]
+    set parameters($this,glmextra_externalmatrixfilename) $f
+}
+
+itcl::body bis_fmri::SwitchDirectory { filepath } {
+	cd $filepath
+	set parameters($this,change_to_directory) $filepath
+}
+
+	
+#Creates a pop-up window for blocks
+#Called in CreateSessionTab
+#Pop-up widget when user presses "Create Block" button, calculates the number of block and asks for relevant tFrame
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::CreateBlockEditingDialog {} {
+   
+	set numblocks [expr $numtasks*$numruns]
+	if {$numblocks == 0} {
+		tk_messageBox -type ok -title "Error ..." -message "Please define runs and tasks!" -icon error
+	return
+	}
+   
+	if { $blockwidget !=0 } {
+	wm withdraw $blockwidget
+	destroy $blockwidget
+	}
+
+	set blockwidget  $basewidget.[ pxvtable::vnewobj ]
+
+	set dlg [ toplevel $blockwidget ]
+	wm geometry $dlg 700x550
+	wm title $dlg "Edit Blocks"
+	set blockwidget_open 1
+	
+	frame $dlg.bott    
+	pack   $dlg.bott -side bottom -fill x -pady 2 -padx 0
+	eval "button $dlg.bott.done -text \"Close\" -command {$this CloseBlockWidget }"
+	eval "button $dlg.bott.clear -text \"Clear All\" -command {$this ClearAllArrays tframe 1}"
+	eval "button $dlg.bott.plot -text \"Plot\" -command {$this CreatePlotWidget }"
+	eval "button $dlg.bott.val -text \"Validate Blocks\" -command { $this ValidateBlockDefinitions 0 2 }"
+	pack $dlg.bott.done $dlg.bott.plot $dlg.bott.clear $dlg.bott.val -side left -expand true -fill x -padx 2
+
+	iwidgets::scrolledframe $dlg.frame -width 7i -height 5i -labelpos nw -labeltext "Define Blocks" -relief ridge
+	pack $dlg.frame -side top -fill both -pady 2 -padx 2 -expand true
+	
+	set blocki [$dlg.frame childsite]
+	set blockid 1
+	
+	set index 0
+	for {set runcount 1} {$runcount <= $numruns} {incr runcount} {
+	for {set taskcount 1} {$taskcount <= $numtasks} {incr taskcount} {
+		set t t$taskcount
+		set r r$runcount
+		
+		set tn $parameters($this,task_$taskcount)
+		set rn [ file tail [ file root $parameters($this,run_file_$runcount) ]]
+		set tr "($t,$r)"
+		
+		eval "set parameters($this,block_$taskcount$runcount) $tr";
+		if { $index > 0 } {
+		set fr [ frame $blocki.0$index -bg black -height 4 ]
+		pack $fr  -side top -expand false -fill x
+		}
+		set fr2 [ frame $blocki.1$index ]
+		pack $fr2 -side top -expand false -fill x		
+		
+		eval "iwidgets::entryfield $fr2.ent -textbackground white -labeltext \"$parameters($this,block_$taskcount$runcount) tframe:\" -width 60 -textvariable [itcl::scope parameters($this,tframe_${taskcount}_${runcount})] -relief sunken"
+		set v "button $fr2.but  -text \"?\" -command \{ tk_messageBox -type ok -message \"Task = $tn\nRun=$rn\" -title \"Block Information\" -icon info\} -width 1"
+		eval $v
+		pack $fr2.but -side right -padx 1
+		pack $fr2.ent -side left -padx 1 -expand true -fill x
+		set blockid [expr $blockid+1]
+		incr index
+	}
+	}
+}
+
+itcl::body bis_fmri::CloseBlockWidget { } {
+	
+	catch { wm withdraw $blockwidget }
+	catch { wm withdraw $plotwidget  }
+}
+
+
+
+#Creates output tab
+#Called in CreateGUI
+#Asks user for number of outcomes, to define outcomes, to output xml file, xml output directory, fMRI output directory
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::CreateXMLOutputTab {base} {
+	
+
+	iwidgets::Labeledframe $base.output -labelpos nw -labeltext "Output XML File for Rajeevan GLM" -relief ridge 
+	pack $base.output -side top -expand true -fill both -pady 2
+	set parameters($this,output_dir) ""
+	
+	set execute_frame [frame $base.bottom222 -width 200]
+	pack $execute_frame -side bottom -expand false  -fill both -pady 2 -padx 2
+	 
+
+	set directory [ $base.output childsite ]
+	frame $directory.filename
+	frame $directory.xml_directory
+	frame $directory.directory
+	frame $directory.outcomes
+	frame $directory.line
+	
+	pack $directory.outcomes -expand false -side top -padx 2 -pady 5
+	pack $directory.directory -expand false -fill x  -side top -padx 2 -pady 5
+	pack  $directory.line  -expand false -side top -padx 2 -pady 40
+	pack $directory.filename $directory.xml_directory -fill x -expand false -side top -padx 2 -pady 5
+	
+	$directory.line configure -bg grey -relief sunken -height 0.012i -width 7i
+
+	eval "iwidgets::entryfield $directory.filename.1 -textbackground white -labeltext \"XML Output File:\"  -textvariable [ itcl::scope parameters($this,xml_output_file) ] -relief sunken"
+	pack $directory.filename.1 -side top -expand true -fill x -padx 5 -pady 5
+	
+	eval "iwidgets::entryfield $directory.xml_directory.1 -textbackground white -labeltext \"XML Output Directory:\" -textvariable [itcl::scope parameters($this,xml_output_dir)] -relief sunken"
+	eval "button $directory.xml_directory.2 -text \"...\" -command {$this GetName xml_output_dir}" 
+	pack $directory.xml_directory.1 -side left -expand true -fill x -padx 5 -pady 5 
+	pack $directory.xml_directory.2 -side right  -expand false -padx 5 -pady 5
+
+
+	eval "iwidgets::entryfield $directory.directory.1 -textbackground white -labeltext \"fMRI Output Directory:\"  -textvariable [ itcl::scope parameters($this,output_dir) ] -relief sunken"
+	eval "button $directory.directory.2 -text \"...\" -command {$this GetName output_dir}"     
+	pack $directory.directory.1 -side left -expand true -fill x -padx 5 -pady 5
+	pack $directory.directory.2 -side right  -expand false  -padx 5 -pady 5
+	
+	eval "iwidgets::combobox $directory.outcomes.1 -labeltext \"     Number of Outcomes: \" -width 7 -textbackground white  -textvariable [itcl::scope parameters($this,num_outcomes)] -relief sunken"
+	for {set i 0} {$i <=100} {incr i} {
+		$directory.outcomes.1 insert list end $i
+	}
+
+	::iwidgets::Labeledwidget::alignlabels $directory.filename.1 $directory.xml_directory.1 $directory.directory.1
+	update
+	$directory.outcomes.1 invoke
+	eval "button $directory.outcomes.2 -text \"Define Outcomes\" -command {$this CreateOutcomeWidget }"
+	pack $directory.outcomes.1 -side left -expand true -padx 4  -pady 5
+	pack $directory.outcomes.2 -side top  -expand false -padx 4 -pady 5
+
+	eval "button $execute_frame.button -text \"Create .xml file!\" -command {$this WriteXMLFile }"
+	pack $execute_frame.button -side top -expand false -fill both -padx 5 -pady 1
+	option add *$execute_frame.button task.borderWidth: 3
+	$execute_frame.button configure -borderwidth 3
+}
+
+
+#Sets the outcomes
+#Called in CreateXMLOutputTab
+#Creates the number of outcome queries as specified by user
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::CreateOutcomeWidget {} {
+	
+	if { $outcomewidget !=0 } {
+	wm withdraw $outcomewidget
+	destroy $outcomewidget
+	}
+
+	set num $parameters($this,num_outcomes)
+	if {$num == 0} {
+		tk_messageBox -type ok -title "Error ..." -message "Need at least one outcome!" -icon error
+	return 0
+	}
+	
+	set outcomewidget [ toplevel ${basewidget}.[ pxvtable::vnewobj ]]
+	wm title $outcomewidget "Define Outcomes"
+	if { $num > 13 } {
+
+	iwidgets::scrolledframe $outcomewidget.frame -width 7i -height 5i -hscrollmode none -labelpos nw -labeltext "Define Outcomes" -relief ridge
+	frame $outcomewidget.bott
+	} else {
+	iwidgets::Labeledframe $outcomewidget.frame -labelpos nw -labeltext "Define Outcomes" -relief ridge
+	frame $outcomewidget.bott
+	}
+	
+	pack $outcomewidget.frame $outcomewidget.bott -side top -fill both -pady 2 -padx 2
+	
+	
+	set outcomew [$outcomewidget.frame childsite]
+	for {set outcomecount 1}  {$outcomecount <= $num} {incr outcomecount} {
+	
+	eval "iwidgets::entryfield $outcomew.$outcomecount -labeltext \"Outcome_$outcomecount:\" -textbackground white -width 60 -textvariable [itcl::scope parameters($this,outcome_$outcomecount)] -relief sunken"
+	pack $outcomew.$outcomecount -side top -expand true -padx 5 -pady 6
+	}
+	
+	eval "button $outcomewidget.bott.done -text \"Done\" -command {wm withdraw $outcomewidget }"
+	eval "button $outcomewidget.bott.clear -text \"Clear All\" -command {$this ClearAllArrays outcome 1}"
+	pack  $outcomewidget.bott.done $outcomewidget.bott.clear -side left -expand true 
+
+}
+
+
+#Plots the outcomes
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::CreatePlotWidget {} {
+	
+	if { $blockwidget == 0 } {
+	return
+	}
+
+	if { $plotwidget !=0 } {
+	catch { 
+		wm withdraw $plotwidget
+		destroy $plotwidget
+	}
+	}
+
+
+	catch { $plotmatrix Delete } 
+	set plotmatrix 0
+	set plotmatrix [ $this CreateBaseGLMMatrix  0 ]
+	if { $plotmatrix == 0 } {
+	tk_messageBox -type ok -title "Error!" -message "Bad Block Definitions. Cannot plot"
+	return 0
+	}
+
+
+	set plotwidget [ toplevel ${blockwidget}.[ pxvtable::vnewobj ]]
+	wm title $plotwidget "Plotting Time Scales"
+	
+
+	set fr [ frame $plotwidget.fr ]
+	pack $fr -side bottom -expand false -fill x
+
+	set tfr [ frame $plotwidget.fr0 ]
+	pack $tfr -side top -expand false -fill x
+
+
+	set parameters($this,plot_xtics)  [ expr round($parameters($this,run_file_1_length)/3 )]
+	set canvasdata($this,level)  [ expr round($parameters($this,run_file_1_length)/2 )]
+	set canvasdata($this,info)  ""
+
+
+	iwidgets::entryfield $tfr.0 -labeltext "Set Line (frames):" -width 4 -textvariable [itcl::scope canvasdata($this,level)] -relief sunken -textbackground white -validate real
+	eval "button $tfr.1 -text \"Upd Line:\" -command { $this EndInteraction }"
+	iwidgets::entryfield $tfr.2 -labeltext "Info:" -width 4 -textvariable [itcl::scope canvasdata($this,plot_info)] -relief sunken -textbackground white -state disabled
+	pack $tfr.0 $tfr.1   -side left -expand false -padx 2
+	pack $tfr.2   -side left -expand true -fill x
+
+	set drawcanvas [ canvas $plotwidget.canvas -width 800 -height 700  ]
+	pack $drawcanvas -side top -expand true -fill both
+	
+	label $fr.0 -text "Run:"
+
+	set n ""
+	for { set runcount 1 } { $runcount <= $numruns } { incr runcount } {
+	set n "$n $runcount"
+	}
+
+	eval "tk_optionMenu $fr.1  [ itcl::scope parameters($this,plot_run) ] $n"
+	update idletasks
+
+	for { set t 0 } { $t < $numruns } { incr t } {
+	eval "$fr.1.menu entryconfigure $t -command { $this PlotRun [ expr $t +1 ] }"
+	}
+
+	set parameters($this,plot_xunits) 0
+	eval "checkbutton $fr.2 -highlightthickness 0 -variable [ itcl::scope parameters($this,plot_xunits) ]  -text \"X-Axis Frames\"  -command { $this PlotRun -2 }"
+
+
+	iwidgets::entryfield $fr.4 -labeltext "Grid:" -width 4 -textvariable [itcl::scope parameters($this,plot_xtics)] -relief sunken -textbackground white -validate real
+	eval "button $fr.5 -text \"Update\" -command { $this PlotRun -1 }"
+
+	eval "button $fr.6 -text \"Update Plot From Edits\" -command { $this PlotRun -3 }"
+
+
+	eval "button $fr.7 -text \"Close\" -command {wm withdraw $plotwidget }"
+	pack $fr.7 -side right -padx 2
+	pack $fr.0 $fr.1 $fr.2 $fr.4 $fr.5 $fr.6 -side left -expand false -fill x
+	wm deiconify $plotwidget
+
+	eval "bind $drawcanvas <ButtonPress>   { $this StartInteraction   %x %y %b}"
+	eval "bind $drawcanvas <B1-Motion>     { $this UpdateInteraction  %x %y 1}"
+	eval "bind $drawcanvas <ButtonRelease> { $this EndInteraction }  "
+
+	$this PlotRun -1
+}
+
+
+
+itcl::body bis_fmri::PlotRun { run } {
+
+	if { $plotwidget == 0 || $plotmatrix == 0 } {
+	return 0
+	}
+
+	set v $parameters($this,plot_xtics)
+	if { $v < 10 } {
+	set parameters($this,plot_xtics) 10
+	}
+
+	set orun $run
+	if { $orun <= - 1 } {
+	set run [ lindex [ split $parameters($this,plot_run) ":" ] 0 ]
+	if { $orun == -3 } {
+		catch { $plotmatrix Delete } 
+		set plotmatrix 0
+		#	    puts stderr "Recreatting Blocks \n\n\n\n"
+		set plotmatrix [ $this CreateBaseGLMMatrix  0 ]
+		if { $plotmatrix == 0 } {
+		tk_messageBox -type ok -title "Error!" -message "Bad Block Definitions. Cannot plot"
+		return 0
+		}
+	} elseif { $orun == -2 } {
+		set v $parameters($this,plot_xtics)
+		set u $parameters($this,plot_xunits)
+		if { $u == 1 } {
+		set parameters($this,plot_xtics) [ expr $v / $parameters($this,tr) ]
+		} else {
+		set parameters($this,plot_xtics) [ expr $v * $parameters($this,tr) ]
+		}
+	}
+	}
+
+	if { $run < 1 } { set run 1 }
+	if { $run > $numruns } { set run $numruns }
+	
+
+	set runcount $parameters($this,plot_run)
+	set rname [ file rootname [ file tail $parameters($this,run_file_$runcount) ]]
+	wm title $plotwidget  "Plotting $parameters($this,plot_run), $rname Frames=$parameters($this,run_file_${run}_length), TR=$parameters($this,tr)"
+
+	
+	set cwidth  [ $drawcanvas cget -width  ]
+	set cheight [ $drawcanvas cget -height ]
+
+
+	catch { $drawcanvas delete all } 
+	$drawcanvas create rect 0 0 $cwidth $cheight -fill darkblue 
+
+	set baseframe 0
+	for { set runcount 1 } { $runcount < $run } { incr  runcount } {
+	set baseframe [ expr $baseframe +  $parameters($this,run_file_${runcount}_length) ]
+	}
+	set upperframe [  expr $baseframe +  $parameters($this,run_file_${run}_length) - 1]
+
+	
+	set numframes [ expr $upperframe - $baseframe + 1  ]
+	set scale  [ expr int(double($cheight-30) / double($numtasks)) ]
+	set wscale [ expr int(double($cwidth- 30)/ double($numframes) ) ]
+
+
+#    puts stderr "BaseFrame : Upper =  $baseframe:$upperframe"
+
+	set canvasdata($this,cwidth) $cwidth
+	set canvasdata($this,cheight) $cheight
+	set canvasdata($this,scale) $scale
+	set canvasdata($this,wscale) $wscale
+	set canvasdata($this,numframes) $numframes
+	set canvasdata($this,baseframe) $baseframe
+	set canvasdata($this,upperframe) $upperframe
+	set canvasdata($this,dragging) 0
+	set canvasdata($this,level) -1
+	set canvasdata($this,minx) 20
+	set canvasdata($this,maxx) [ expr round(($numframes  * $wscale) -1 + $canvasdata($this,minx))]
+
+	
+#    puts stderr "Width = $cwidth, height=$cheight, scales = $scale, $wscale, numframes=$numframes "
+	set x3 [ expr $cwidth -1 ]
+	
+
+	set frlist ""
+	set frloclist ""
+	set frlast 0
+	set maxfr [ expr $numframes -1 ]
+	if { $parameters($this,plot_xunits) !=1 } {
+	set maxfr [ expr $maxfr * $parameters($this,tr) ]
+	} else {
+	set parameters($this,plot_xtics) [ expr round($parameters($this,plot_xtics)) ]
+	}
+	
+	for { set fr 0 } { $fr < $maxfr } { set fr [ expr $fr + $parameters($this,plot_xtics) ] } {
+
+	if { $parameters($this,plot_xunits) == 1 } {
+		lappend frloclist $fr
+	} else {
+		lappend frloclist [ expr $fr / $parameters($this,tr) ]
+	}
+	lappend frlist $fr
+	}
+
+	set yp0 [ expr 0.1 * $scale ]
+	set yp1 [ expr $numtasks*$scale +0.93 ]
+	set yp2 [ expr $numtasks*$scale +0.98 ]
+	for { set j 1 } { $j  < [ llength $frlist ] } { incr j } {
+	set x  [ lindex $frloclist $j ]
+	set x1 [ expr $x * $wscale + 20 ]
+	$drawcanvas create line $x1 $yp0 $x1 $yp2 -fill pink -dash $wscale
+	
+	set t  [ lindex $frlist $j ]
+	if { $parameters($this,plot_xunits) !=1 } {
+		set t [ format "%.1f sec" $t ]
+	} else { 
+		set t [ format "%d frames" $t ]
+	}
+	$drawcanvas create text [ expr round($x1+2) ] $yp2 -text $t  -anchor nw  -fill yellow
+	}
+
+	set klist [ list  $canvasdata($this,minx) $canvasdata($this,maxx) ]
+	if { $parameters($this,plot_xunits) ==1 } {
+	set knamelist [ list  "0 frames" "$maxfr frames" ]
+	} else {
+	set knamelist [ list  "0 sec" "$maxfr sec" ]
+	}
+
+	for { set j 0 } { $j <=1 } { incr j } {
+	$drawcanvas create line [ lindex $klist $j ] 0 [ lindex $klist $j ] $cheight -fill red -dash [ expr round(0.8*$wscale) ]
+	$drawcanvas create text [ expr round([ lindex $klist $j]+2) ] $yp2 -text [ lindex $knamelist $j ]  -anchor nw  -fill red
+	}
+
+
+	set numf2  0
+	set canvasdata($this,level) $numf2
+	$drawcanvas create line 0  0  0  $cheight -fill green  -tag grayslider -dash [ expr round(1.5 * $wscale) ]
+	$drawcanvas create text 0  0.02 -text $numf2 -tags slidertext -anchor s -fill green
+	$this EndInteraction
+	
+	for { set i 0 } { $i < $numtasks } { incr i } {
+	set yp [ expr ($i+0.01)*$scale ]
+	set y0 [ expr ($i+0.15)*$scale ]
+	set y1 [ expr ($i+0.90)*$scale ]
+	$drawcanvas create line 20 $y1 $x3 $y1 -arrow last -fill red   -dash [ expr round( 1.0*$wscale) ]
+
+	set tsk [ expr $i +1 ]
+	$drawcanvas create text 22 $yp -text "Task [expr $i+1]:$parameters($this,task_$tsk)"  -anchor nw -fill yellow
+	
+	for { set frame 0 } { $frame < $numframes } { incr frame } {
+		if { [ $plotmatrix GetElement [ expr $baseframe + $frame ] $i ] > 0 } {
+		set x  $frame
+		set x1 [ expr $x * $wscale + $canvasdata($this,minx) ]
+		set x2 [ expr $x1 + $wscale -1 ]
+		$drawcanvas create rect $x1 $y0 $x2 $y1 -fill yellow -outline yellow  
+		}
+	}
+	}
+}
+
+# -------------------------------------------------------------------------------------------    
+itcl::body bis_fmri::CreateGLMTclImage { } {
+
+	set lst [ $this CreateWaverMatrix ]
+	if { $lst == 0 } {
+	return 0 
+	}
+	set newmatrix  [ lindex $lst 0 ]
+	set breaks     [ lindex $lst 1 ]
+	set rawmatrix     [ lindex $lst 2 ]
+	$rawmatrix Delete
+
+	set glmmatr [ vtkpxMatrix [ pxvtable::vnewobj ]]
+	set biswaver [ vtkbisWaver [ pxvtable::vnewobj ]]
+	$biswaver AddDriftTerms $newmatrix $glmmatr $breaks $parameters($this,afni_polort) 
+
+	$newmatrix Delete
+	
+	set nt [ $breaks GetNumberOfTuples ]
+	for { set i 0 } { $i < $nt } { incr i } {
+	# puts stderr "Break = $i [ $breaks GetComponent $i 0 ]"
+	}
+	set sz [ $glmmatr GetSize ]
+
+
+
+	set numrows [ lindex $sz 0 ] 
+	set wscale [ expr int($numrows/[lindex $sz 1]) ]
+	if { $wscale > 10 } { set wscale 10 }
+	set numcols [ expr [ lindex $sz 1 ] * $wscale ]
+
+	set maxiy [ expr $wscale -2 ]
+	set countx 0
+	set targetx [ expr [ $breaks GetComponent 1 0 ] -1 ]
+	#    puts stderr "Countx =$countx, targetx=$targetx"
+	set data [list]
+
+	set lrow [ list ]
+	for { set i 0 } { $i < $numcols } { incr i } {
+	lappend lrow [format "#%02x%02x%02x" 128 255 128 ]
+	}
+
+
+	pxtkconsole
+	pxtkprint "Scanning GLM Model to generate image = $numrows x $numcols \n"
+
+	for {set x 0} { $x < $numrows } {incr x} {
+	set row [list]
+	for {set y 0} {$y < [ lindex $sz 1 ] } { incr y} {
+		lappend row [format "#%02x%02x%02x" 128 255 128 ]
+		for { set iy 0 } { $iy < $maxiy } { incr iy } {
+		set v [ expr 256.0*[ $glmmatr GetElement $x $y ] ]
+		set r 0; set g 0; set b 0
+		if { $v > 0.0 } {
+			set  r [ expr int($v) ]; if { $r > 255 } { set r 255 }
+		} else {
+			set  b [ expr -1*int($v) ]; if { $b > 255 } { set b 255 }
+		}
+		lappend row [format "#%02x%02x%02x" $r $g $b ]
+		}
+		lappend row [format "#%02x%02x%02x" 128 255 128 ]
+	}
+	lappend data $row
+
+	if { $x == $targetx } {
+		lappend data $lrow
+		lappend data $lrow
+		lappend data $lrow
+		incr countx
+		if { $countx < [ expr $nt -1 ] } {
+		set targetx [ expr [ $breaks GetComponent  [ expr $countx +1 ]  0] -1 ]
+		#		puts stderr "Added Countx =$countx, targetx=$targetx"
+		}
+	}
+	}
+
+	#    puts stderr "Data = [ llength $data ], numrows=$numrows, numcols=$numcols [ expr $numrows * $numcols ]"
+
+	$glmmatr Delete
+	$breaks  Delete
+
+	set img [ image create photo ]
+	$img put $data
+
+	set bot [ toplevel $basewidget.[ pxvtable::vnewobj ]]
+	wm geometry $bot [ expr $numcols + 5 ]x[ expr $numrows + 40 ];
+	wm title $bot "GLM Image (Drift=$parameters($this,afni_polort), runs=$nt, tasks=$numtasks)"
+	update idletasks
+	set lab [ label $bot.top -image $img ]
+	eval "button $bot.bot -text Close -command { wm withdraw $bot; destroy $bot }"
+	pack $bot.bot -side bottom -expand false -fill x
+	pack $bot.top -side top -expand true -fill both
+	
+	#    unset data 
+}
+
+
+# -------------------------------------------------------------------------------------------    
+itcl::body bis_fmri::PlotHRF { } {
+
+	if { $hrfcanvas == 0  } {
+	return 0
+	}
+
+	if { $parameters($this,afni_useafniwaver) == 1 } {
+	if { $parameters($this,afni_hrfmode) != "wav" && $parameters($this,afni_hrfmode) != "gamma" } {
+		pxtclutil::Warning "Switching hrf_mode to wav as  AFNI's waver does not support $parameters($this,afni_hrfmode)"
+		set parameters($this,afni_hrfmode) "wav" 
+	}
+	}
+
+	set biswaver [ vtkbisWaver [ pxvtable::vnewobj ]]
+	switch -exact $parameters($this,afni_hrfmode) {
+	"wav"  {
+		$biswaver SetWAV_delay_time  $parameters($this,afni_delaytime) 
+		$biswaver SetWAV_rise_time $parameters($this,afni_risetime)
+		$biswaver SetWAV_fall_time $parameters($this,afni_falltime) 
+		$biswaver SetWAV_undershoot $parameters($this,afni_undershoot)
+		$biswaver SetWaveform_type 1
+	}
+	"gamma"        {    $biswaver SetWaveform_type 2 }
+	"doublegamma"  {    $biswaver SetWaveform_type 3 }
+	"triplegamma"  {    $biswaver SetWaveform_type 4 }
+	"spm"          {    $biswaver SetWaveform_type 5 }
+	}
+
+	$this AdjustHRFGUI
+
+	set tr [ expr $parameters($this,tr)*0.25 ]
+	if { $tr < 0.0 || $tr > 10.0 } {
+	set tr 0.5
+	}
+
+	$biswaver SetTR   $tr
+	$biswaver SetPeak $parameters($this,afni_peak) 
+
+
+
+	set arr [ $biswaver GenerateResponseFunction ]
+	
+	set cwidth  [ $hrfcanvas cget -width  ]
+	set cheight [ $hrfcanvas cget -height ]
+
+
+	catch { $hrfcanvas delete all } 
+	$hrfcanvas create rect 0 0 $cwidth $cheight -fill darkblue 
+	
+	set p(0) 0.0
+	set p(1) 0.0
+	
+	set nt [ $arr GetNumberOfTuples ]
+
+	set range [ $arr GetRange ]
+	set rmax  [ lindex $range 1 ]
+	set rmin  [ lindex $range 0 ]
+
+	if { $rmin > [ expr -0.3 * $rmax ] } {
+	set rmin [ expr -0.3 *  $rmax ] 
+	}
+	set rdiff [ expr $rmax - $rmin ]
+
+
+
+	set wscale [ expr  ($cwidth-20.0) /double($nt) ]
+	set scale  [ expr int( (40-$cheight)/$rdiff) ]
+	set sint   [ expr int(40-$rmax*$scale) ]
+
+	set canvasdata($this,hrfwscale) $wscale
+	set canvasdata($this,hrfscale)  $scale
+	set canvasdata($this,hrfsint)   $sint
+	set canvasdata($this,hrfxoff)   10.0
+
+
+	for { set i 0 } { $i < $nt  } { incr i } {
+	set y [ $arr GetComponent $i 0 ]
+	set x [ expr $p(0) + 1.0 ]
+
+	set x1 [ expr $x * $wscale  + $canvasdata($this,hrfxoff) ]
+	set x0 [ expr $p(0) * $wscale + $canvasdata($this,hrfxoff) ]
+	set p(0) $x
+	
+	set y1 [ expr $y * $scale + $sint ]
+	set y0 [ expr $p(1) * $scale + $sint ]
+	set p(1) $y
+
+	$hrfcanvas create line $x0 $y0 $x1 $y1 -fill yellow
+	}
+	
+	set xmin  [ expr int($canvasdata($this,hrfxoff))]
+	set xmax  [ expr int($nt * $wscale) + $canvasdata($this,hrfxoff) ]
+	set ymin  [ expr int($rmin * $scale + $sint) ]
+	set ymax  [ expr int($rmax * $scale + $sint) ]
+	set ymax2  [ expr int(0.5*$rmax * $scale + $sint) ]
+	set yzero $sint 
+
+	$hrfcanvas create line $xmin $yzero $xmax $yzero -arrow last -fill red 
+	$hrfcanvas create line $xmin $ymin $xmin $ymax -arrow both -fill red    
+
+	set xmin [ expr $xmin + 2 ]
+	$hrfcanvas create line $xmin $ymin $xmax $ymin -arrow none -fill pink -dash 10
+	$hrfcanvas create line $xmin $ymax2 $xmax $ymax2 -arrow none -fill pink -dash 10
+	$hrfcanvas create line $xmin $ymax $xmax $ymax -arrow none -fill pink -dash 10
+	$hrfcanvas create line $xmax $ymin $xmax $ymax -arrow none -fill pink -dash 10
+
+
+	$hrfcanvas create text [ expr $xmin + 10 ] [ expr $ymax - 5 ]   -text "" -tags hrftext -anchor sw -fill green
+
+
+
+	set dv 4
+	while { [ expr $nt/ $dv ] > 5 } {
+	set dv [ expr $dv + 4 ]
+	}
+
+	for { set i $dv  } { $i < $nt  } { set i [ expr $i+ $dv  ] } {
+	set x  [ expr  int(double($i) * $wscale) + 10 ]
+	set t  [ format "%d TR" [ expr round(double($i/$dv)) ]]
+	$hrfcanvas create line $x $ymin $x $ymax -arrow none -fill red   -dash 10
+	$hrfcanvas create text $x $ymin -text $t   -anchor s  -fill yellow
+	}
+	$arr Delete
+	$biswaver Delete
+
+	$hrfcanvas create text [ expr $xmax - 30 ] [ expr $ymax + 40 ]   -text "TR = $parameters($this,tr) sec"  -anchor se -fill cyan
+
+	eval "bind $hrfcanvas <B1-ButtonPress>   { $this HRFCanvasUpdate %x %y 1 }"
+	eval "bind $hrfcanvas <B1-Motion>     { $this HRFCanvasUpdate %x %y 2 }"
+	eval "bind $hrfcanvas <B1-ButtonRelease>     { $this HRFCanvasUpdate %x %y 3 }"
+
+}
+
+	
+::itcl::body bis_fmri::HRFCanvasUpdate { x y b } { 
+
+	if { $hrfcanvas == 0 } {
+	return 0
+	}
+
+	$hrfcanvas dchars hrftext 0 end
+	if { $b == 3 } {
+	return
+	}
+
+	set vx [ expr (double($x) - double($canvasdata($this,hrfxoff)) ) / double($canvasdata($this,hrfwscale)) ]
+	set vy [ expr (double($y) - double($canvasdata($this,hrfsint)) ) / double($canvasdata($this,hrfscale)) ]
+
+	set tr  [ expr $vx/8.0 ] 
+	set t   [ expr $tr * $parameters($this,tr) ]
+
+	
+
+
+	$hrfcanvas insert hrftext 0 [ format "t=%.2f sec (%.1f TR), y=%.2f" $t $tr $vy ]
+}
+
+# -------------------------------------------------------------------------------------------    
+::itcl::body bis_fmri::AdjustHRFGUI { } {     
+	
+	for { set i 1 } { $i <=2 } { incr i } {
+	set ok 0
+	catch { set ok  $parameters($this,afni_wavergui$i)   }
+
+	if { $ok != 0 } {
+		if { $parameters($this,afni_hrfmode) == "wav" } {
+		::pxitclbasecontrol::EnableUI $ok
+		} else {
+		::pxitclbasecontrol::DisableUI $ok
+		}
+	} 
+	}
+
+}
+# -------------------------------------------------------------------------------------------    
+::itcl::body bis_fmri::StartInteraction { x y b} {
+	UpdateInteraction  $x $y $b 
+}
+	
+# -------------------------------------------------------------------------------------------    
+::itcl::body bis_fmri::EndInteraction { } {
+
+	set x [ expr ($canvasdata($this,level))*$canvasdata($this,wscale) + $canvasdata($this,minx) ]
+	if { $x < $canvasdata($this,minx) } {
+	set x $canvasdata($this,minx)
+	} elseif { $x > $canvasdata($this,maxx) } {
+	set x $canvasdata($this,maxx)
+	}
+
+	$drawcanvas coords grayslider  $x 0  $x  [ expr 0.98 * $canvasdata($this,cheight) ]
+	$drawcanvas coords slidertext [ expr $x + 2 ]  $canvasdata($this,cheight) 
+	$drawcanvas dchars slidertext 0 end
+
+	if { $canvasdata($this,level) < 0 } {
+	set canvasdata($this,level) 0
+	} elseif { $canvasdata($this,level) > $canvasdata($this,numframes) } {
+	set canvasdata($this,level) [ expr $canvasdata($this,numframes) -1 ]
+	}
+
+	set l [ format "%.1f sec" [ expr $canvasdata($this,level) *$parameters($this,tr) ]]
+	$drawcanvas insert slidertext 0 $l
+
+	set canvasdata($this,plot_info) "$l"
+
+	if { $plotmatrix == 0 || $plotwidget == 0 } { return }
+	set fr [ expr $canvasdata($this,level) + $canvasdata($this,baseframe) ]
+	
+	set qt "$l (fr=$fr) Tasks Active:"
+	for { set i 1 } { $i <= $numtasks } { incr i } {
+	set nm $parameters($this,task_$i)
+	if { [ $plotmatrix GetElement  $fr [ expr  $i -1 ] ] > 0 } {
+		set qt "$qt $i ($nm)"	
+	} 
+	}
+	set canvasdata($this,plot_info) $qt
+}
+	
+# ------------------------------------------------------------------------------------------ -   
+::itcl::body bis_fmri::UpdateInteraction { x y butno} {
+
+	# compute the bin selected by the mouse
+	if { $plotmatrix == 0 || $plotwidget == 0 } { return }
+	
+	if { $butno ==3 } {
+	return
+	}
+	
+	set canvasdata($this,level) [ expr ($x - $canvasdata($this,minx)) / $canvasdata($this,wscale)  ]
+	$this EndInteraction
+	
+}
+# ----------------------------------------------------------------------------------------
+
+
+itcl::body bis_fmri::AboutCommand {  } {
+
+	if { $aboutdialog == 0 } {
+	set w .
+	if { [ string length $basewidget ] > 2 } { set w $basewidget }
+	
+	set aboutdialog  [ toplevel $w.[ pxvtable::vnewobj ]] 
+	
+	::pxtclhelp::HelpDialog $aboutdialog
+	wm title $aboutdialog "About This Application"
+	
+	set version $::pxtclvtkpxcontrib::version
+
+	set line "$appname by Isabella Murphy, Thomas Teisseyre  and Xenios Papademetris is part of $version.\n\n $aboutstring \n\n------------------------------------\n System Information\n------------------------------------\n[ ::pxtclutil::GetAllInfo ]"
+	
+	::pxtclhelp::HelpDialogAddText $aboutdialog $line
+	
+	set logoframe [ ::pxtclhelp::GetLogoFrame  $aboutdialog ]
+	set imgname [ file join $::pxtclvtkpxcontrib::imagedir  bioimagesuite_logo.gif ]
+	
+	label $logoframe.b -image $::pxtclvtkpxcontrib::logo
+	pack  $logoframe.b -side left -expand t -fill x 
+	
+	set textbox [  ::pxtclhelp::GetTextBox  $aboutdialog ]
+	
+	$textbox configure -font "$::pxtclvtkpxcontrib::fontname"
+	::pxitclbasecontrol::SetWidgetTreeColors $aboutdialog "\#8197c5" white
+	}
+	::pxtclutil::ShowWindow $aboutdialog
+	
+	puts stderr "$aboutdialog, [ $this GetSetupName ]"
+}
+
+#Creates output tab
+#Called in CreateGUI
+#Asks user for number of outcomes, to define outcomes, to output xml file, xml output directory, fMRI output directory
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::CreateAFNITab {base} {
+	
+	label $base.oo -bg black -fg white -text "Operations on this tab require that AFNI be installed (see http://afni.nimh.nih.gov/afni/)"
+	label $base.oo2 -bg black -fg white -text "All this functionality is also available under the Single Subject GLM Tab"
+	pack $base.oo $base.oo2 -side top -expand false -fill x
+
+	iwidgets::Labeledframe $base.output -labelpos nw -labeltext "Output Specifications" -relief ridge 
+	pack $base.output -side top -expand true -fill both -pady 2
+
+	set cs [ $base.output childsite ]
+
+	set fr  [ frame $cs.1 ]; 
+	set fr2 [ frame $cs.2 ]; 
+	pack $fr $fr2 -side top -expand false -fill x
+
+
+
+	eval "iwidgets::entryfield $fr.1 -textbackground white -labeltext \"Results Directory:\"  -textvariable [ itcl::scope parameters($this,output_dir) ] -relief sunken"
+	eval "button $fr.2 -text \"...\" -command {$this GetName output_dir}"     
+	pack $fr.2 -side right  -expand false  -padx 5 -pady 5
+	pack $fr.1 -side left -expand true -fill x -padx 5 -pady 5
+
+	checkbutton $fr2.a -highlightthickness 0  -variable [ itcl::scope parameters($this,afni_ensurenifti) ] -text "Ensure all Input 4D Images are in NIFTI format"    
+	checkbutton $fr2.b -highlightthickness 0  -variable [ itcl::scope parameters($this,afni_deletetemp) ] -text "Delete Temporary Files created for/by AFNI"
+	checkbutton $fr2.c -highlightthickness 0  -variable [ itcl::scope parameters($this,afni_useafninormalize) ] -text "Use AFNI Normalize"
+	pack $fr2.a $fr2.b $fr2.c -side top -expand false -padx 20
+
+	iwidgets::Labeledframe $base.output0 -labelpos nw -labeltext "GLM Specifications" -relief ridge 
+	pack $base.output0 -side top -expand true -fill both -pady 2
+	set w [ $base.output0 childsite ]
+
+	frame $w.0; pack $w.0 -side top
+	label $w.0.a -text "HRF Mode :"
+	tk_optionMenu $w.0.b  [ itcl::scope parameters($this,afni_hrfmode) ] "wav" "gamma" "doublegamma" "triplegamma" "spm" 
+	for { set t 0 } { $t < 5 } { incr t } {
+	eval "$w.0.b.menu entryconfigure $t -command { $this PlotHRF  }"
+	}
+
+
+	eval "checkbutton $w.0.d -highlightthickness 0  -variable [ itcl::scope parameters($this,afni_useafniwaver) ] -text \"Use AFNI Waver\" -command { $this PlotHRF }"
+
+	pack $w.0.a $w.0.b  $w.0.d  -side left -expand false -fill x
+
+
+	set parameters($this,afni_wavergui1) [ frame $w.1 ]
+	iwidgets::Labeledframe $w.2 -labelpos nw -labeltext "WAV Parameters" -relief ridge
+	set w3 [ frame $w.3  ]
+	pack $w.1  $w.2 $w.3  -side top -expand false 
+
+	set ws [ $w.2 childsite ]
+
+	iwidgets::entryfield $ws.1 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_delaytime) ] -validate real -width 5 -labeltext "Delay Time:"
+	iwidgets::entryfield $ws.2 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_risetime) ] -validate real -width 5 -labeltext "Rise Time:"
+	iwidgets::entryfield $ws.3 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_falltime) ] -validate real -width 5 -labeltext "Fall Time:"
+	iwidgets::entryfield $ws.4 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_undershoot) ] -validate real -width 5 -labeltext "Undershoot:"
+	iwidgets::entryfield $ws.5 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_peak) ] -validate real -width 5 -labeltext "Peak:"
+#    pack $ws.1 $ws.2 $ws.3 $ws.4 $ws.5 -side left -expand false -fill x
+	grid $ws.1 -row 0 -column 0
+	grid $ws.2 -row 0 -column 1
+	grid $ws.3 -row 0 -column 2
+	grid $ws.4 -row 1 -column 0
+	grid $ws.5 -row 1 -column 1
+
+
+	iwidgets::entryfield $w3.1 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_polort) ] -validate integer -width 2 -labeltext "Drift Polynomial Order:"
+	iwidgets::entryfield $w3.2 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_masklevel) ] -validate real -width 5 -labeltext "Mask Threshold (0-1):"
+	pack $w3.1 $w3.2 -side left -padx 10
+
+
+
+	iwidgets::Labeledframe $base.output12 -labelpos nw -labeltext "AFNI Outputs" -relief ridge 
+	pack $base.output12 -side top -expand true -fill both -pady 2
+
+	set w [ $base.output12 childsite ]
+	set wa [ frame $w.row1 ]; set wb [ frame $w.row2 ]; pack $wa $wb -side top -expand false -fill x
+
+	checkbutton $wa.0 -variable [ itcl::scope parameters($this,afni_bout)  ] -text "Baseline Coeffs"
+	checkbutton $wa.1 -variable [ itcl::scope parameters($this,afni_fout)  ] -text "F-Statistics"
+	checkbutton $wa.2 -variable [ itcl::scope parameters($this,afni_rout)  ] -text "R^2 Statistics"
+	pack $wa.0 $wa.1 $wa.2 -side left -expand false -fill x -padx 2
+
+
+	checkbutton $wb.0 -variable [ itcl::scope parameters($this,afni_tout)  ] -text "T-Statistics"
+	checkbutton $wb.1 -variable [ itcl::scope parameters($this,afni_vout)  ] -text "Variance Map"
+	checkbutton $wb.2 -variable [ itcl::scope parameters($this,afni_bucket)  ] -text "Single 4D Image"
+	pack $wb.0 $wb.1  -side left -expand false -fill x -padx 2
+
+
+	iwidgets::Labeledframe $base.output2 -labelpos nw -labeltext "GLM Processing" -relief ridge 
+	pack $base.output2 -side top -expand true -fill both -pady 2
+
+	set cs [ $base.output2 childsite ]
+
+	eval "button $cs.0 -text \"Reset Defaults\" -command { $this SetProcessingDefaults }"
+	eval "button $cs.1 -text \"Create AFNI Script File for Single Subject GLM\" -command { $this AFNICreateScript 1 1  }"
+	pack $cs.0 -side right -padx 2
+	pack $cs.1 -side left -padx 0 -expand true -fill x
+
+}
+
+
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::CreateSingleSubjectTab {base} {
+	
+	iwidgets::Labeledframe $base.output0 -labelpos nw -labeltext "GLM Specifications" -relief ridge 
+	set w [ $base.output0 childsite ]
+
+
+	frame $w.0; pack $w.0 -side top -expand true -fill x
+	set w1 [ frame $w.0.l ]
+	set hrfcanvas [ canvas $w.1 -width 256 -height 300  ]
+	pack $w.1 -side right
+	pack $w1 -side left -expand true -fill both
+	$hrfcanvas create rect 0 0 256 300 -fill darkblue 
+
+	
+
+	label $w1.a -text "HRF Mode :"
+	tk_optionMenu $w1.b  [ itcl::scope parameters($this,afni_hrfmode) ] "wav" "gamma" "doublegamma" "triplegamma" "spm" 
+	for { set t 0 } { $t < 5 } { incr t } {
+	eval "$w1.b.menu entryconfigure $t -command { $this PlotHRF  }"
+	}
+
+	eval "button $w1.c -text Plot -command { $this PlotHRF }"
+	pack $w1.a $w1.b $w1.c -side left -padx 5
+
+	iwidgets::Labeledframe $w.2 -labelpos nw -labeltext "WAV Parameters" -relief ridge
+	set parameters($this,afni_wavergui2) $w.2 
+	pack $w.2 -side top -expand true -fill both
+
+	set ws [ $w.2 childsite ]
+
+	iwidgets::entryfield $ws.1 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_delaytime) ] -validate real -width 5 -labeltext "Delay Time:"
+	iwidgets::entryfield $ws.2 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_risetime) ] -validate real -width 5 -labeltext "Rise Time:"
+	iwidgets::entryfield $ws.3 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_falltime) ] -validate real -width 5 -labeltext "Fall Time:"
+	iwidgets::entryfield $ws.4 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_undershoot) ] -validate real -width 5 -labeltext "Undershoot:"
+	iwidgets::entryfield $ws.5 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_peak) ] -validate real -width 5 -labeltext "Peak:"
+	pack $ws.1 $ws.2 $ws.3 $ws.4 $ws.5 -side top -expand false 
+	::iwidgets::Labeledwidget::alignlabels $ws.1 $ws.2 $ws.3 $ws.4 $ws.5
+
+
+	iwidgets::entryfield $w.4 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_masklevel) ] -validate real -width 5 -labeltext "Mask Threshold (0-1):"
+	iwidgets::entryfield $w.6 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_polort) ] -validate integer -width 2 -labeltext "Drift Polynomial Order:"
+	checkbutton $w.8 -variable [ itcl::scope parameters($this,afni_glmregressmotion)  ] -text "Regress Motion Parameters"
+	pack  $w.2 $w.4 $w.6 $w.8  -side top -expand false 
+	::iwidgets::Labeledwidget::alignlabels $w.4 $w.6
+
+
+
+
+	iwidgets::Labeledframe $base.output -labelpos nw -labeltext "Outputs" -relief ridge 
+
+
+	set cs [ $base.output childsite ]
+
+	set fr  [ frame $cs.1 ]; 
+	pack $fr -side top -expand false -fill x
+
+
+	eval "iwidgets::entryfield $fr.1 -textbackground white -labeltext \"Results Directory:\"  -textvariable [ itcl::scope parameters($this,output_dir) ] -relief sunken"
+	eval "button $fr.2 -text \"...\" -command {$this GetName output_dir}"     
+	pack $fr.2 -side right  -expand false  -padx 5 -pady 5
+	pack $fr.1 -side left -expand true -fill x -padx 5 -pady 5
+
+	checkbutton $cs.2 -variable [ itcl::scope parameters($this,afni_tout)  ] -text "Compute T-Statistics for each beta value"
+	checkbutton $cs.25 -variable [ itcl::scope parameters($this,afni_saveresidual)  ] -text "Save Residual Image"
+	checkbutton $cs.26 -variable [ itcl::scope parameters($this,afni_savedriftbeta)  ] -text "Save 4D Drift Beta Maps"
+	checkbutton $cs.27 -variable [ itcl::scope parameters($this,afni_glmsinglerunoutput)  ] -text "Compute Individual Run Beta Maps"
+	checkbutton $cs.3 -highlightthickness 0  -variable [ itcl::scope parameters($this,afni_deletetemp) ] -text "Do Not Save Temporary Files"
+	pack $cs.2 $cs.25 $cs.26 $cs.27 $cs.3 -side top -expand false -padx 20
+
+
+
+	iwidgets::Labeledframe $base.output2 -labelpos nw -labeltext "GLM Processing" -relief ridge 
+	pack $base.output2 -side bottom -expand true -fill both -pady 2
+
+	pack $base.output0 -side top -expand true -fill both -pady 2
+	pack $base.output -side top -expand true -fill both -pady 2
+
+	set cs [ $base.output2 childsite ]
+
+	eval "button $cs.0 -text \"Reset Defaults\" -command { $this SetProcessingDefaults }"
+	eval "button $cs.2 -text \"Show Model as Image\" -command  { $this CreateGLMTclImage }"
+
+	eval "button $cs.1 -text \"Compute GLM\" -command { $this ComputeGLM 1 1  }"
+	pack $cs.0 $cs.2 -side right -padx 2
+	pack $cs.1 -side left -padx 0 -expand true -fill x
+
+
+
+
+	set parameters($this,tr) 1.0
+	$this PlotHRF
+}
+
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::CreateRateGLMTab {base} {
+    
+    iwidgets::Labeledframe $base.output0 -labelpos nw -labeltext "Rate GLM Specifications" -relief ridge 
+    set w [ $base.output0 childsite ]
+    $w configure -bg red
+    
+    frame $w.0; pack $w.0 -side top -expand true -fill x
+    set w1 [ frame $w.0.l ]
+#    set hrfcanvas [ canvas $w.1 -width 256 -height 300  ]
+#    pack $w.1 -side right
+    pack $w1 -side left -expand true -fill both
+#    $hrfcanvas create rect 0 0 256 300 -fill darkblue 
+    
+    
+    
+    label $w1.a -text "HRF Mode :"
+    tk_optionMenu $w1.b  [ itcl::scope parameters($this,afni_hrfmode) ] "wav" "gamma" "doublegamma" "triplegamma" "spm" 
+    for { set t 0 } { $t < 5 } { incr t } {
+	eval "$w1.b.menu entryconfigure $t -command { $this PlotHRF  }"
+    }
+    
+    #    eval "button $w1.c -text Plot -command { $this PlotHRF }"
+    pack $w1.a $w1.b  -side left -padx 5
+    
+    iwidgets::Labeledframe $w.2 -labelpos nw -labeltext "WAV Parameters" -relief ridge
+    set parameters($this,afni_wavergui2) $w.2 
+    pack $w.2 -side top -expand true -fill both
+    
+    set ws [ $w.2 childsite ]
+    
+    iwidgets::entryfield $ws.1 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_delaytime) ] -validate real -width 5 -labeltext "Delay Time:"
+    iwidgets::entryfield $ws.2 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_risetime) ] -validate real -width 5 -labeltext "Rise Time:"
+    iwidgets::entryfield $ws.3 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_falltime) ] -validate real -width 5 -labeltext "Fall Time:"
+    iwidgets::entryfield $ws.4 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_undershoot) ] -validate real -width 5 -labeltext "Undershoot:"
+    iwidgets::entryfield $ws.5 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_peak) ] -validate real -width 5 -labeltext "Peak:"
+    pack $ws.1 $ws.2 $ws.3 $ws.4 $ws.5 -side top -expand false 
+    ::iwidgets::Labeledwidget::alignlabels $ws.1 $ws.2 $ws.3 $ws.4 $ws.5
+    
+    
+    iwidgets::entryfield $w.4 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_masklevel) ] -validate real -width 5 -labeltext "Mask Threshold (0-1):"
+    iwidgets::entryfield $w.6 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_polort) ] -validate integer -width 2 -labeltext "Drift Polynomial Order:"
+    iwidgets::entryfield $w.8 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_rateglobal) ] -validate integer -width 2 -labeltext "Do Global Drift Correction:"
+    iwidgets::entryfield $w.10 -textbackground white -textvariable  [ itcl::scope parameters($this,afni_numrateterms) ] -validate integer -width 2 -labeltext "Number of Rate Terms:"
+    pack  $w.2 $w.4 $w.6 $w.8 $w.10  -side top -expand false 
+    ::iwidgets::Labeledwidget::alignlabels  $w.4 $w.6 $w.8 $w.10
+    iwidgets::Labeledframe $base.output -labelpos nw -labeltext "Outputs" -relief ridge 
+    
+    set cs [ $base.output childsite ]
+    
+    set fr  [ frame $cs.1 ]; 
+    pack $fr -side top -expand false -fill x
+    
+    eval "iwidgets::entryfield $fr.1 -textbackground white -labeltext \"Results Directory:\"  -textvariable [ itcl::scope parameters($this,output_dir) ] -relief sunken"
+    eval "button $fr.2 -text \"...\" -command {$this GetName output_dir}"     
+    pack $fr.2 -side right  -expand false  -padx 5 -pady 5
+    pack $fr.1 -side left -expand true -fill x -padx 5 -pady 5
+    
+    checkbutton $cs.2 -variable [ itcl::scope parameters($this,afni_tout)  ] -text "Compute T-Statistics for each beta value"
+    checkbutton $cs.25 -variable [ itcl::scope parameters($this,afni_saveresidual)  ] -text "Save Residual Image"
+    checkbutton $cs.26 -variable [ itcl::scope parameters($this,afni_savedriftbeta)  ] -text "Save 4D Drift Beta Maps"
+    checkbutton $cs.3 -highlightthickness 0  -variable [ itcl::scope parameters($this,afni_deletetemp) ] -text "Do Not Save Temporary Files"
+    pack $cs.2 $cs.25 $cs.26 $cs.3 -side top -expand false -padx 20
+    
+    
+    
+    iwidgets::Labeledframe $base.output2 -labelpos nw -labeltext "GLM Processing" -relief ridge 
+    pack $base.output2 -side bottom -expand true -fill both -pady 2
+    
+    pack $base.output0 -side top -expand true -fill both -pady 2
+    pack $base.output -side top -expand true -fill both -pady 2
+    
+    set cs [ $base.output2 childsite ]
+    
+    eval "button $cs.0 -text \"Reset Defaults\" -command { $this SetProcessingDefaults }"
+    eval "button $cs.2 -text \"Show Model as Image\" -command  { $this CreateGLMTclImage }"
+    
+    eval "button $cs.1 -text \"Compute Rate GLM\" -command { $this ComputeRateGLM 1 1  }"
+    pack $cs.0 $cs.2 -side right -padx 2
+    pack $cs.1 -side left -padx 0 -expand true -fill x
+    set parameters($this,tr) 1.0
+    $this PlotHRF
+}
+
+
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::SetGlobalDrift { mode } { 
+
+	if { $mode == 0 && $parameters($this,resting_slicemeanremoval) == 1 } {
+	set parameters($this,resting_volumemeanremoval) 0
+	} elseif { $mode == 1 && $parameters($this,resting_volumemeanremoval) == 1 } {
+	set parameters($this,resting_slicemeanremoval) 0
+	}
+}
+
+itcl::body bis_fmri::SetOutputType { mode } {
+	
+	if { $mode == 0 && $parameters($this,resting_rawcorrelation) == 1 } {
+		set parameters($this,resting_ztransform) 0
+	} elseif { $mode == 1 && $parameters($this,resting_ztransform) == 1 } {
+		set parameters($this,resting_rawcorrelation) 0
+	}
+}
+
+
+itcl::body bis_fmri::CreatePreprocessingFrame { ws { mode seed } } {
+
+	iwidgets::Labeledframe $ws.top -labelpos nw -labeltext "Global Options" -relief ridge 
+	pack $ws.top -side top -expand false -fill x
+
+	frame $ws.bot;
+	pack $ws.top $ws.bot -side top -expand false -fill x
+
+	iwidgets::Labeledframe $ws.bot.1 -labelpos nw -labeltext "Global Pre-Processing" -relief ridge 
+	iwidgets::Labeledframe $ws.bot.2 -labelpos nw -labeltext "Local  Pre-Processing" -relief ridge 
+	pack $ws.bot.1 $ws.bot.2 -side left -expand true -fill both
+
+	set w [ $ws.top childsite ]
+	
+	checkbutton $w.1 -variable [ itcl::scope parameters($this,resting_individualruns)  ] -text "Process Runs Individually"
+	grid $w.1 -row 0 -column 0 -padx 0
+#    pack $w.1 -side left -expand true -fill x
+	
+	if { $mode != "seed" } {
+	checkbutton $w.2 -variable [ itcl::scope parameters($this,resting_usermask)  ] -text "Use VOI Image As Mask"	
+#	pack $w.3 -side right -padx 2
+	grid $w.2 -row 1 -column 0 -padx 0
+	}
+	
+	if { $mode == "seed" } {
+	checkbutton $w.3 -variable [ itcl::scope parameters($this,resting_rawcorrelation)  ] -text "Compute Raw Correlation"
+	eval "$w.3 configure -command  { $this SetOutputType 0 } "
+		
+	checkbutton $w.4 -variable [ itcl::scope parameters($this,resting_ztransform)  ] -text "Gaussian Normalization (Can't compute Raw if it's selected)" 
+	eval "$w.4 configure -command  { $this SetOutputType 1 } "
+	grid $w.3 -row 1 -column 0 -padx 0
+	grid $w.4 -row 2 -column 0 -padx 0
+	
+	
+	
+	
+		
+	
+		
+	}
+	
+
+
+	set w [ $ws.bot.2 childsite ]
+	iwidgets::entryfield $w.1 -textbackground white -textvariable  [ itcl::scope parameters($this,resting_masklevel) ] -validate real -width 5 -labeltext "Mask Threshold:"
+	iwidgets::entryfield $w.2 -textbackground white -textvariable  [ itcl::scope parameters($this,resting_driftpol) ] -validate integer -width 5 -labeltext "Drift Polynomial Order:"    
+	iwidgets::entryfield $w.3 -textbackground white -textvariable  [ itcl::scope parameters($this,resting_temporalsigma) ] -validate real -width 5 -labeltext "Temporal Smoothing Sigma:"
+	
+	pack $w.1 $w.2 $w.3  -side top -expand false 
+	::iwidgets::Labeledwidget::alignlabels $w.1 $w.2 $w.3
+
+
+	set w [ $ws.bot.1 childsite ]
+	checkbutton $w.1 -variable [ itcl::scope parameters($this,resting_slicemeanremoval)  ] -text "Remove Slice Mean" 
+	eval "$w.1 configure -command { $this SetGlobalDrift 0 }"
+	checkbutton $w.2 -variable [ itcl::scope parameters($this,resting_volumemeanremoval)  ] -text "Remove Volume Mean" 
+	eval "$w.2 configure -command { $this SetGlobalDrift 1 }"
+
+	#if { $mode != "seed" } {
+	checkbutton $w.3 -variable [ itcl::scope parameters($this,resting_usemotionparams)  ] -text "Regress Motion Parameters" 
+	eval "$w.3 configure -command { $this SetGlobalDrift 1 }"
+	
+	checkbutton $w.4 -variable [ itcl::scope parameters($this,resting_usecsfmean)  ] -text "Regress CSF/White Matter Mean" 
+	eval "$w.4 configure -command { $this SetGlobalDrift 1 }"
+	pack $w.1 $w.2 $w.3 $w.4   -side top -expand false 
+	#} else {
+	#pack $w.1 $w.2   -side top -expand false 
+	#}
+	#    ::iwidgets::Labeledwidget::alignlabels $w.1 $w.2 
+
+
+}
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmri::CreateSeedBasedTab {base} {
+	
+	iwidgets::Labeledframe $base.output0 -labelpos nw -labeltext "Seed Based Correlation Specifications" -relief ridge 
+	pack $base.output0 -side top -expand true -fill both -pady 2
+	set w [ $base.output0 childsite ]
+
+	iwidgets::Labeledframe $w.2 -labelpos nw -labeltext "Preprocessing Parameters" -relief ridge
+	pack $w.2 -side top -expand true -fill x
+	set ws [ $w.2 childsite ]
+
+	$this CreatePreprocessingFrame $ws "seed"
+
+
+	iwidgets::Labeledframe $base.output -labelpos nw -labeltext "Outputs" -relief ridge 
+	pack $base.output -side top -expand true -fill both -pady 2
+
+	set cs [ $base.output childsite ]
+
+	set fr  [ frame $cs.1 ]; 
+	pack $fr -side top -expand false -fill x
+
+
+	eval "iwidgets::entryfield $fr.1 -textbackground white -labeltext \"Results Directory:\"  -textvariable [ itcl::scope parameters($this,output_dir) ] -relief sunken"
+	eval "button $fr.2 -text \"...\" -command {$this GetName output_dir}"     
+	pack $fr.2 -side right  -expand false  -padx 5 -pady 5
+	pack $fr.1 -side left -expand true -fill x -padx 5 -pady 5
+
+	#    checkbutton $cs.2 -variable [ itcl::scope parameters($this,afni_tout)  ] -text "Compute T-Statistics for each beta value"
+	#    checkbutton $cs.3 -highlightthickness 0  -variable [ itcl::scope parameters($this,afni_deletetemp) ] -text "Do Not Save Temporary Files"
+	#    pack $cs.2 $cs.3 -side top -expand false -padx 20
+
+	
+	iwidgets::Labeledframe $base.output2 -labelpos nw -labeltext "Connectivity Processing" -relief ridge 
+	pack $base.output2 -side top -expand true -fill both -pady 2
+
+	set cs [ $base.output2 childsite ]
+	
+	frame $cs.top ; pack $cs.top -side top -expand true -fill x -padx 5
+	frame $cs.bot ; pack $cs.bot -side bottom -fill x -expand true -padx 5
+
+	eval "button $cs.top.1 -text \"Seed to Image\" -command { $this ComputeSeedCorrelation 0 1 1 }"
+	eval "button $cs.top.2 -text \"Seed to Seed\" -command { $this ComputeSeedCorrelation 1 1 1 }"
+	eval "button $cs.top.3 -text \"Task Based Seed to Image\" -command { $this TaskBasedComputeSeedCorrelation 1 }"
+	pack $cs.top.1 $cs.top.2 $cs.top.3 -side left -padx 0 -expand true -fill x
+	
+	eval "button $cs.bot.1 -text \"Reset Defaults\" -command { $this SetProcessingDefaults }"
+	pack  $cs.bot.1 -side right -padx 5
+
+}
+
+
+
+itcl::body bis_fmri::CreateIntrinsicTab {base} {
+	iwidgets::Labeledframe $base.output2 -labelpos nw -labeltext "Intrinsic Connectivity Processing" -relief ridge 
+	pack $base.output2 -side bottom -expand true -fill x -pady 2
+
+
+	iwidgets::Labeledframe $base.output0 -labelpos nw -labeltext "Intrinsic Correlation Specifications (SLOW!)" -relief ridge 
+	pack $base.output0 -side top -expand true -fill both -pady 2
+	set w [ $base.output0 childsite ]
+
+	iwidgets::Labeledframe $w.2 -labelpos nw -labeltext "Preprocessing Parameters" -relief ridge
+	pack $w.2 -side top -expand true -fill x
+	set ws [ $w.2 childsite ]
+
+	$this CreatePreprocessingFrame $ws "intrinsic"
+	
+	#------------------------Isabella's try-------------------------------------
+	iwidgets::Labeledframe $w.3 -labelpos nw -labeltext "Connectivity Parameters" -relief ridge
+	pack $w.3 -side bottom -expand true -fill x
+	set wss [ $w.3 childsite ]
+	
+	iwidgets::entryfield $wss.1 -textbackground white -textvariable [ itcl::scope parameters($this,resting_threshold) ] -validate real -width 5 -labeltext "Threshold:"
+	pack $wss.1 -side top -expand false
+	#    ::iwidgets::Labeledwidget::alignlabels $ws.1 $ws.2 $ws.3 $wss.1
+	
+	iwidgets::Labeledframe $wss.2 -labelpos nw -labeltext "Range" -relief ridge
+	pack $wss.2 -padx 10 -pady 10 -fill both -expand yes -side left
+	
+	set index 0
+	set w [ $wss.2 childsite ]
+	foreach f { Both Positive Negative } {
+	radiobutton $w.$index -text [string totitle $f] -value $f -variable [ itcl::scope parameters($this,resting_range) ] 
+	pack $w.$index -side left  -expand false -fill x -pady 2
+	incr index
+	}
+	
+	iwidgets::Labeledframe $wss.3 -labelpos nw -labeltext "Calculate" -relief ridge
+	pack $wss.3 -padx 10 -pady 10 -fill both -expand yes -side right 
+	
+	set index 0
+	set w [ $wss.3 childsite ]
+	foreach f {Abs Sqr} {
+	radiobutton $w.$index -text [string totitle $f]  -value $f -variable [ itcl::scope parameters($this,resting_mode) ] 
+	pack $w.$index -side left -expand false -fill x -pady 2
+	incr index
+	}
+	#---------------------------------------------------------------------------
+	
+	iwidgets::Labeledframe $base.output -labelpos nw -labeltext "Outputs" -relief ridge 
+	pack $base.output -side top -expand true -fill both -pady 2
+
+	set cs [ $base.output childsite ]
+
+	set fr  [ frame $cs.1 ]; 
+	pack $fr -side top -expand false -fill x
+
+
+	eval "iwidgets::entryfield $fr.1 -textbackground white -labeltext \"Results Directory:\"  -textvariable [ itcl::scope parameters($this,output_dir) ] -relief sunken"
+	eval "button $fr.2 -text \"...\" -command {$this GetName output_dir}"     
+	pack $fr.2 -side right  -expand false  -padx 5 -pady 5
+	pack $fr.1 -side left -expand true -fill x -padx 5 -pady 5
+
+	
+	
+	set cs [ $base.output2 childsite ]
+	
+	set w1 [ frame $cs.0 ]
+	set w2 [ frame $cs.1 ]
+	pack $w1 $w2 -side top -expand true -fill x
+
+	eval "button $w2.0 -text \"Reset Defaults\" -command { $this SetProcessingDefaults }"
+	eval "button $w1.1 -text \"Intrinsic Correlation\" -command { $this ComputeIntrinsicCorrelation Whole 1 1  }"
+	eval "button $w1.2 -text \"Ipsilateral Correlation\" -command { $this ComputeIntrinsicCorrelation Ipsilateral 1 1  }"
+	eval "button $w1.3 -text \"Contralateral Correlation\" -command { $this ComputeIntrinsicCorrelation Contralateral 1 1  }"
+	pack $w1.1 $w1.2 $w1.3  -side left -padx 0 -expand true -fill x
+	pack $w2.0  -side right -padx 2
+	
+}
+
+
+itcl::body bis_fmri::ClearAllData {ask } {
+	set ok [ bis_fmrisetup::ClearAllData $ask ]
+	if { $ok == 0 } {
+	return $ok
+	}
+
+	return 1
+}
+
+
+itcl::body bis_fmri::UpdateGUI { { loadmode 1 } } {
+
+	if { $basewidget == 0 } {
+	return 0
+	}
+
+	wm title $basewidget "BioImage Suite::$appname [ file tail $setupname ]"
+	update idletasks
+
+	if { $loadmode == 0 } {
+	return 1
+	}
+
+	$skipframesentry config -state disabled
+	$runslistbox clear 
+	$tasklistbox clear
+	
+	for {set runcount 1} {$runcount <= $numruns } {incr runcount} {
+	$runslistbox insert end "Run_${runcount}_$parameters($this,display_run_file_${runcount})"
+	}
+	for {set taskcount 1} {$taskcount <= $numtasks} {incr taskcount} {
+		$tasklistbox insert end "T$taskcount-$parameters($this,task_$taskcount)"
+
+	}
+	
+	$this CloseBlockWidget
+	$this PlotHRF
+	$this CreateDataTreeStructure ""
+
+	return 1
+	
+
+}
+
+itcl::body bis_fmri::ExitCommand { } {
+	set ok [ tk_messageBox -title "Exiting this Application" -type yesno  -message "Are you sure you want to close $appname. Any unsaved work will be lost."  ]
+	if { $ok == "yes" } {
+	pxtkexit
+	}
+	return 0
+}
+
+
+itcl::body bis_fmri::ShowCommandLineOptions { } {
+	pxtkconsole
+	pxtkprint "\n\n[ $this Usage]\n\n"
+}
+
+# -------------------------------------------------------------------------------------------------------------------
+
+itcl::body bis_fmri::ReorganizeDataGUI { } {
+
+	set dirname  [tk_chooseDirectory -title "Select Directory to reorganize/relocate data" ]
+	if { [ string length $dirname ] < 1 } {
+	return 0
+	}
+	
+	if { [ file exists $dirname ] } {
+	set newtail [ file root [ file tail $setupname ] ]
+	set newtail "${newtail}data"
+	set dirname [ file join $dirname $newtail ] 
+	}
+	set ok [ ::pxtclutil::Question "This operation will COPY your current files from their existing locations and reorganize them under $dirname. This can use a lot of disk space. Are you sure?" ]
+	if { $ok == 0 } {
+	return
+	}
+	
+	return [ $this ReorganizeData $dirname ]
+}
+
+
+itcl::body bis_fmri::DisplayMSBFile { msbsetupname } { 
+
+	if { $multisubjectcontrol !=0 } {
+	$multisubjectcontrol ShowWindow Results " "
+	update idletasks
+	$multisubjectcontrol LoadSetup $msbsetupname
+	$multisubjectcontrol LoadAll 1
+	} elseif { $ownsorthoviewer > 0 } {
+	$notebook view "DataTree"
+	}
+}
+
+
+# ----------------------------------------------------------
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+	wm withdraw .
+	set br [ toplevel .[ pxvtable::vnewobj ]]
+	set element [bis_fmri \#auto $br 1  ]
+	update idletasks
+	if { $argc > 0 } {
+	$element MainFunction $argc $argv
+	}
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/bis_fmrisetup.tcl b/bioimagesuite30_src/bioimagesuite/main/bis_fmrisetup.tcl
new file mode 100755
index 0000000..a4fb611
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/bis_fmrisetup.tcl
@@ -0,0 +1,4578 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] bis_algorithm ]
+
+
+package require vtkpxcontrib 1.0
+package require pxvtable 1.0
+package require pxtclhelp  1.0
+package require pxitclimage  1.0
+package require pxitcltransform	 1.0
+package require bis_datamanager	 1.0
+package require bis_treewidget 1.0
+
+# ------------------------------------
+# Algorithms required
+# ------------------------------------
+package require bis_thresholdimage 1.0
+package require bis_roimean 1.0
+package require bis_csfwmmotioncorr 1.0
+package require bis_temporalsmoothimage	  1.0
+package require bis_removetemporaldrift 1.0
+package require bis_removeslicemean 1.0
+package require bis_imageremoveframes 1.0
+package require bis_matrixcorrelation 1.0
+package require bis_seedcorrelation 1.0
+package require bis_cropimage 1.0
+
+
+package require bis_intrinsicconnectivity 1.0
+
+# ------------------------------------
+# Provides
+package provide bis_fmrisetup 1.0
+
+#Class Definition
+#----------------------------------------------------------------------------------------------------
+itcl::class bis_fmrisetup {
+
+    protected common parameters 
+    private common progressbar 
+    private common progress_lab 
+    private common progress_val 
+    
+    protected variable numtasks 0
+    protected variable numruns 0
+    protected variable numblocks 0
+    
+    protected variable fmriruncount
+    protected variable framecount
+    protected variable fmriread_tframecount 0
+    
+    protected variable setupname "default.xmlg"
+    
+    protected variable processlist ""
+    protected variable processnamelist ""
+    protected variable restinglist ""
+    protected variable restingnamelist ""
+    protected variable referenceimagepaths ""
+    protected variable referenceimagenames ""
+    
+    # Anywhere glmextra appears -- check!
+    protected variable glmextralist ""
+    protected variable glmextranamelist ""
+    
+    protected variable multisubjectcontrol 0
+    protected variable datamanager 0
+    protected variable datamanagerfilename ""
+    protected variable treewidget 0
+    
+    # ------------------------------- Methods ---------------------------
+    
+    constructor { } { 
+	set progressbar($this) 0
+	set progress_lab($this) "Status"
+	set progress_val($this) 0
+	$this SetSetupDefaults
+	pxtclvtkpxcontrib::LoadLibraries { vtkbisConnectivityTCL }
+    }
+    
+    public method GetThisPointer { } { return $this }
+    
+    #Load/Save Files
+    public method SaveSetupFile { { fname "" } }
+    public method LoadSetupFile { { fname "" } }
+    public method LoadParameterFile { { fname "" } }
+    public method LoadOlderSetupFile { fname  }
+    
+    # Part methods
+    protected method ImportParameterBlock { fileid { skipblank 0 }}
+    
+    #This is to import Pawel's old style setup file
+    public method ImportfMRISetup { }
+    #This is to output Rajeevan style XML File
+    public method WriteXMLFile { { outdir 0 } }
+    public method ReadXMLFile { fname { subjectno 1 } { onlyrun -1 }}
+    
+    # This method is used to update the GUI if present on load
+    protected method UpdateGUI { { loadmode 1 }  } { return 1 }
+    protected method HasGUI { { loadmode 1 }  } { return 0 }
+    
+    # Clear Stuff
+    public method ClearAllArrays {par { doask 0 }}
+    public method ClearAllData {ask }
+    
+    # Utilities
+    public method StringParse {mode output_type end thistask thisrun}
+    protected method IsWritable { fname }
+    
+    # Validate Block Definitions
+    protected method ParseFramesString { val usingseconds tr numframes offset message { debug 0 } }
+    public method ValidateBlockDefinitions { { creatematrix 0 } { debug 0 } }
+    protected method ComputeEmptyGLMMatrixDimensions { { debug 0 }  }
+    public  method CreateBaseGLMMatrix { { debug 0 } }
+						       
+	# AFNI Processing
+	public method AFNICreateTimeFile { { tfname "" } { report 0 } }
+	public method AFNICreateScript { { askfname 0 } {  report 0 } }
+	public method AFNICreateScriptHelper { fout line { mirror 0 } }
+	public method EnsureRunsAreNIFTI { }
+	public method SetProcessingDefaults { }
+	public method SetSetupDefaults { }
+
+    # Internal GLM -- New! (years ago!)
+    public method CreateWaverMatrix { }
+    public method ComputeGLM { { askfname 0 } {  report 0 } }
+
+    
+    public method ComputeRateGLM { { askfname 0 } {  report 0 } }
+    
+
+
+    # GLM Pieces
+    protected method PreprocessGLM { outnamestem { dodrift 1 } { numrate 0 } { singlerun 0 } }
+    protected method ComputeGLMComponent { outnamestem { singlerun 0 } { setuptasklist "" } { dodrift 1 } { numrate 0 } }
+
+    # Resting State algorithms
+    public method ComputeSeedCorrelation { mode { askfname 0 } {  report 0 } } 
+    public method ComputeSeedCorrelationSingle { mode inputimage maskimage filename { dosave 1 } }
+    public method TaskBasedProcessing { task image maskimage vimg outname { addrange 0 } }
+    public method TaskBasedComputeSeedCorrelation { { askfname 0 } }
+   
+    public method ComputeIntrinsicCorrelationSingle { mode allrunsimage maskimage outname } 
+    public method ComputeComplexIntrinsicCorrelationSingle { mode allrunsimage maskimage outname } 
+    public method ComputeIntrinsicCorrelation { mode { askfname 0 } {  report 0 } } 
+    
+    
+    # Protected Methods utilities for Correlation
+    # Need to be careful about these ...............
+    protected method ConcatenateAndPreprocessRuns { mask { graywhitemask 0 } { checkformotioncorrection 0 } { enableskipframes 0 } }
+    protected method PreprocessSingle4DImage { img mask { skipframeslist 0 } { motionmatrixname 0 } { graywhitemask 0 } }
+    protected method CreateMask { allruns threshold }
+    
+    # VOI Stuff 
+    protected method CheckTransformationsForVOI { { graywhitemaskmode 0  } }
+    protected method CheckVOIImageSize { voiimage funcimg { graywhitemaskmode 0 } }
+    protected method GetReslicedVOIImage { funcimg { graywhitemaskmode 0 } }
+    
+    # Protected Methods for MSB Files
+    protected method GenerateOutputFilenames { { asfname 0	} }
+    protected method CreateMSBFile { msbsetupname tasklist }
+    protected method DisplayMSBFile { msbsetupname }
+    
+    # Methods for XML Stuff
+    protected method CreateDataTreeStructure { { tasklist "" } { doupdate 1 } }
+    public method UpdateDataTreeStructure { { imagename "" } }
+    
+    
+    # Default Stuff
+    public method ReorganizeData { newdir }
+    
+    
+    # Add Logo Label
+    public proc   AddLogoLabel { w }
+    
+    # create progress bar 
+    protected method CreateProgressBar { w } 
+    
+    # Progress Stuff
+    public method ProgressCallback	 { filter lab } 
+    public method ShowProgress	 { filter lab } 
+    public method ShowProgressVal	 { name	  val }
+    public method SetFilterCallbacks { filter comment } 
+    public method GetFirstInputObject { }  { return 0 }
+    
+    
+    # Main Function
+    public method MainFunction { numarg arglist }
+    public method Usage	   { }
+    public method InfoMessage { msg { title "" } { icon info } }
+    
+    
+    # Get Data Manager
+    public method GetDataManager { } { return $datamanager }
+    public method GetDataManagerFilename { } { return $datamanagerfilename }
+
+};
+
+
+
+
+
+
+#Saves variable parameters to .xmlg file
+#Called in CreateGUI
+#Saves variable information for current xml generator session  so that user can load again later with load command
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::SaveSetupFile { { fname "" } } {
+
+
+
+	if { $fname == "" } {
+	set savename $setupname
+	set filetype1 [ list "XML Gen Files" [ list .xmlg ] ]
+	set savename [tk_getSaveFile -title "Save XML Gen File" -defaultextension .xmlg -initialfile [ file tail $setupname ] -initialdir [ file dirname $setupname ]  -filetypes [ list $filetype1 ] ]
+	if { [ llength $savename ] < 1 } {
+		return 
+	}
+	} else {
+	set savename $fname
+	}
+
+	set setupname $savename
+	set savefile [file tail $savename]
+
+	set fileid [open $savename w+ ]
+	
+	set imagepath $::pxtclvtkpxcontrib::imagedir
+	
+
+	set ind [ lsearch -exact $referenceimagenames $parameters($this,display_reference_brain) ]
+	if { $ind >=0 } {
+	set parameters($this,reference_brain_path) [ lindex $referenceimagepaths $ind ] 
+	} else { 
+	set parameters($this,reference_brain_path) $parameters($this,reference_brain) 
+	}   
+
+	puts $fileid "#BioImageSuite Study Description File v2"	 
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Study Title"
+	puts $fileid "$parameters($this,study_title)"
+	puts $fileid "#Subject ID"
+	puts $fileid "$parameters($this,subject_id)"
+
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Anatomical Data"
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Reference Brain"
+	puts $fileid "$parameters($this,reference_brain_path)"
+	puts $fileid "#Reference Gray/White/CSF Map"
+	puts $fileid "$parameters($this,reference_gw_map)"
+	puts $fileid "#3D Anatomical Image"
+	puts $fileid "$parameters($this,anatomical)"
+	puts $fileid "#Conventional Image"
+	puts $fileid "$parameters($this,conventional)"
+	puts $fileid "#Ref-> 3D Anatomical Transformation"
+	puts $fileid "$parameters($this,referenceTransform)"
+	puts $fileid "#3D Anatomical -> Conventional Transformation"
+	puts $fileid "$parameters($this,internalTransform)"
+	puts $fileid "#Conventional -> EPI Transformation"
+	puts $fileid "$parameters($this,distortionTransform)"
+
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Basic Parameters"
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Session ID"
+	puts $fileid "$parameters($this,session_id)"
+	puts $fileid "#Session Description"
+	puts $fileid "$parameters($this,session_description)"
+	puts $fileid "#Number of Runs"
+	puts $fileid "$numruns"
+	puts $fileid "#Number of Tasks"
+	puts $fileid "$numtasks"
+	puts $fileid "#Number of Outcomes"
+	puts $fileid "$parameters($this,num_outcomes)"
+	puts $fileid "#Repetition Time (TR)"
+	puts $fileid "$parameters($this,tr)"
+	puts $fileid "#Number of Slices"
+	puts $fileid "$parameters($this,numslices)"
+	puts $fileid "#Number of Frames"
+	puts $fileid "$parameters($this,numframes)"
+	puts $fileid "#Skip Frames On"
+	puts $fileid "$parameters($this,checks)"
+	puts $fileid "#Frames to Skip"
+	puts $fileid "$parameters($this,skipFrames)"
+
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Outputs Files/Locations"
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#XML Output File"
+	puts $fileid "$parameters($this,xml_output_file)"
+	puts $fileid "#XML Output Directory"
+	puts $fileid "$parameters($this,xml_output_dir)"
+	puts $fileid "#Data Output Directory"
+	puts $fileid "$parameters($this,output_dir)"
+
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Runs"
+	puts $fileid "#-----------------------------------------------------"
+
+	for {set runcount 1} {$runcount <= $numruns} {incr runcount} {
+	puts $fileid "#Run $runcount (first line=4D Image, second line=Matrix with Motion Parameters)"
+	puts $fileid "$parameters($this,run_file_$runcount)"
+	puts $fileid "$parameters($this,run_motionfile_$runcount)"
+	if { $parameters($this,runskip_$runcount) == 0 } {
+		puts $fileid "No Skip"
+	} else {
+		puts $fileid $parameters($this,skiprunsframe_${runcount})
+	}
+	}
+
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Tasks"
+	puts $fileid "#-----------------------------------------------------"
+   
+	for {set taskcount 1} {$taskcount <= $numtasks} {incr taskcount} {
+	puts $fileid "#Task $taskcount"
+	puts $fileid "$parameters($this,task_$taskcount)"
+	
+	}
+
+	set numblocks [expr $numtasks*$numruns]
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Blocks"
+	puts $fileid "#-----------------------------------------------------"
+	
+	puts $fileid "#Block Definition Time (1=seconds, 0 =frames)"
+	puts $fileid "$parameters($this,blockunits)"
+
+	for {set runcount 1} {$runcount <= $numruns} {incr runcount} {
+	for {set taskcount 1} {$taskcount <= $numtasks} {incr taskcount} {
+		puts $fileid "#Block Task=$taskcount, Run=$runcount ($parameters($this,task_$taskcount),$parameters($this,run_file_$runcount))"
+	    puts $fileid "$parameters($this,tframe_${taskcount}_${runcount})"
+	}
+	}
+
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Outcomes"
+	puts $fileid "#-----------------------------------------------------"
+	
+	for {set outcount 1} {$outcount <= $parameters($this,num_outcomes)} {incr outcount} {
+	puts $fileid "#OutCome $outcount"
+	puts $fileid "$parameters($this,outcome_$outcount)"
+	}	  
+
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#GLM Processing and AFNI Integration"
+	puts $fileid "#-----------------------------------------------------"
+	
+	for { set i 0 } { $i < [ llength $processlist ] } { incr i } {
+	set elem [ lindex $processlist $i ]
+	set desc [ lindex $elem 0 ]
+	set name [ lindex $elem 1 ]
+
+	puts $fileid "$desc"
+	puts $fileid "$name : $parameters($this,afni_$name)"
+	}
+
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Resting State Connectivity Extra Inputs"
+	puts $fileid "#-----------------------------------------------------"
+	
+	puts $fileid "#VOI Definition"
+	puts $fileid "$parameters($this,voiDefinitionImage)"
+	puts $fileid "#VOI Definition Space (Reference,Anatomical,Conventional,Functional)"
+	puts $fileid "$parameters($this,voiDefinitionSpace)"
+	puts $fileid "#Inverse Reference Transformation"
+	puts $fileid "$parameters($this,inverseReferenceTransform)"
+
+
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Connectivity Parameters"
+	puts $fileid "#-----------------------------------------------------"
+	
+	for { set i 0 } { $i < [ llength $restinglist ] } { incr i } {
+	set elem [ lindex $restinglist $i ]
+	set desc [ lindex $elem 0 ]
+	set name [ lindex $elem 1 ]
+
+	puts $fileid "$desc"
+	puts $fileid "$name : $parameters($this,resting_$name)"
+	}
+
+	puts $fileid "#-----------------------------------------------------"
+	puts $fileid "#Extra GLM Parameters Parameters"
+	puts $fileid "#-----------------------------------------------------"
+
+	for { set i 0 } { $i < [ llength $glmextralist ] } { incr i } {
+	    set elem [ lindex $glmextralist $i ]
+	    set desc [ lindex $elem 0 ]
+	    set name [ lindex $elem 1 ]
+	    
+	    puts $fileid "$desc"
+	    puts $fileid "$name : $parameters($this,glmextra_$name)"
+	}
+	
+	close $fileid
+	
+	return [ $this UpdateGUI ]
+
+    }
+#Check if a file or directory is writable
+#-----------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::IsWritable { fname } {
+	
+	if { [ file exists $fname ] } {
+		set ok [ file writable $fname ]
+	} else {
+		set ok [ file writable [ file dirname [ file normalize $fname ] ] ]
+	}
+	return $ok
+}
+#Clears all parameters. If value of "ask" is 1 then a window appears asking
+#user whether to clear contents. If ask=0 then the function is called
+#internally and the user is not prompted
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::ClearAllData {ask } {
+	
+	if {$ask==1} {
+	set ok [ tk_messageBox -type yesno -default no -title "WARNING!" -message "This will clear current parameters!" -icon question ]
+	if { $ok=="no" } {
+		return 0
+	}
+	}
+	
+	$this ClearAllArrays tframe
+	$this ClearAllArrays runs
+	$this ClearAllArrays task
+	$this ClearAllArrays outcome
+	#puts "Number of task, runs before zeroing $numtasks,$numruns"
+	$this SetSetupDefaults
+}
+
+itcl::body bis_fmrisetup::SetSetupDefaults { } {
+	set numruns 0
+	set numtasks 0
+	set numblocks 0
+	set parameters($this,checks) 0
+	set parameters($this,skipFrames) ""
+	set parameters($this,num_outcomes) 0
+	set parameters($this,study_title) ""
+	set parameters($this,subject_id) ""
+	set parameters($this,reference_brain) ""
+	set parameters($this,display_reference_brain) ""
+	set parameters($this,conventional) ""
+	set parameters($this,display_conventional) ""
+	set parameters($this,anatomical) ""
+	set parameters($this,display_anatomical) ""
+	set parameters($this,referenceTransform) ""
+	set parameters($this,display_referenceTransform) ""
+	set parameters($this,internalTransform) ""
+	set parameters($this,display_internalTransform) ""
+	set parameters($this,distortionTransform) ""
+	set parameters($this,display_distortionTransform) ""
+	set parameters($this,voiDefinitionImage) ""
+	set parameters($this,display_voiDefinitionImage) ""
+	set parameters($this,inverseReferenceTransform) ""
+	set parameters($this,display_inverseReferenceTransform) ""
+	set parameters($this,voiDefinitionSpace) "Functional"
+	set parameters($this,display_reference_gw_map) ""
+	set parameters($this,reference_gw_map) ""
+
+	set parameters($this,session_id) ""
+	set parameters($this,session_description) ""
+	set parameters($this,tr) 1.0
+	set parameters($this,numslices) ""
+	set parameters($this,numframes) ""
+	set parameters($this,blockunits) 1
+	set parameters($this,xml_output_file) ""
+	set parameters($this,xml_output_dir) ""
+	set parameters($this,output_dir) ""
+	
+
+
+	set referenceimagepaths ""
+	set referenceimagenames ""
+
+	set imagepath $::pxtclvtkpxcontrib::imagedir
+	lappend referenceimagenames "MNI_Colin_1mm" 
+	lappend referenceimagepaths  [ file join $imagepath MNI_T1_1mm.nii.gz ]
+	lappend referenceimagenames "MNI_Colin_1mm_Stripped" 
+	lappend referenceimagepaths  [ file join $imagepath MNI_T1_1mm_stripped.nii.gz ]
+	lappend referenceimagenames "MNI_Colin_2mm" 
+	lappend referenceimagepaths  [ file join $imagepath MNI_T1_2mm.nii.gz ]
+	lappend referenceimagenames "MNI_Colin_2mm_Stripped" 
+	lappend referenceimagepaths  [ file join $imagepath MNI_T1_2mm_stripped.nii.gz	]
+
+
+
+	# Afni parameters
+	$this SetProcessingDefaults
+	
+	return 1
+}
+
+#Loads fMRI setup file by individually loading all variables based on parsed results
+#----------------------------------------------------------------------------------------------------	 
+itcl::body bis_fmrisetup::ImportfMRISetup {  } {
+
+	set filetype2 [list "fMRI Setup Files" [list .*] ]
+	set loadname2 [tk_getOpenFile -title "Load fMRI Setup File" -filetypes [list $filetype2] ]
+	if { [ string length $loadname2] < 1  } {
+	return
+	}
+	set loadfile2 [file tail $loadname2]
+
+	set fmri_file_id [open $loadname2]
+	seek $fmri_file_id 0 start
+	set fmri_setup_file [read -nonewline $fmri_file_id]
+
+	seek $fmri_file_id 0 start
+	set start "Start Name"
+	set study_name_line 16
+	set headercount 1
+
+	$this ClearAllData 0
+
+	
+
+	while {$headercount<12} {
+	
+	gets $fmri_file_id line
+	if {[string match [string range $line 0 9] "Study Name"]==1} {
+		
+		set starter [string first "#" $line] 
+		set ender [string last "#" $line]
+		set parameters($this,study_title) [string range $line [expr $starter+2] [expr $ender-1]]
+	}
+	
+	if {[string match [string range $line 0 11] "Study Number"]==1} {
+		set starter [string first "#" $line] 
+		set ender [string last "#" $line]
+		set parameters($this,study_number) [string range $line [expr $starter+2] [expr $ender-2]]
+	  }	
+	
+	if {[string match [string range $line 0 12] "series number"]==1} {
+		#puts $parameters($this,series_number)
+		set starter [string first "#" $line] 
+		set ender [string last "#" $line]
+		set parameters($this,series_number) [string range $line [expr $starter+2] [expr $ender-2]]
+		
+	}
+	if {[string match [string range $line 0 23] "directory for saved data"]==1} {
+		set starter [string first "#" $line] 
+		set ender [string last "#" $line]
+		set parameters($this,output_dir) [string range $line [expr $starter+18] [expr $ender-4]]
+	}
+	
+	if {[string match [string range $line 0 15] "Number of slices"]==1} {
+		set starter [string first "#" $line] 
+		set ender [string last "#" $line]
+		set parameters($this,numslices) [string range $line [expr $starter+2] [expr $starter+5]]
+		
+	}
+	
+	if {[string match [string range $line 0 25] "Number of images per slice"]==1} {
+		set starter [string first "#" $line] 
+		set ender [string last "#" $line]
+		set parameters($this,numframes) [string range $line [expr $starter+2] [expr $starter+5]]
+	}
+	
+	if {[string match [string range $line 0 23] "Number of different sets"]==1} {
+		set starter [string first "#" $line] 
+		set ender [string last "#" $line]
+		set numtasks [string range $line [expr $starter+2] [expr $starter+5]]
+		#  puts "NUMBER OF TASKS: $numtasks"
+	}
+	set headercount [expr $headercount+1]
+	
+	}
+	
+	
+	for {set taskcount4 1} {$taskcount4<=$numtasks} {incr taskcount4} {
+	set bodycount 0
+#	puts "TASKCOUNT $taskcount4"
+	set subbodycount 0
+		set parameters($this,fmrirun_$taskcount4) 0
+	set parameters($this,fmriruncount_$taskcount4) 0
+	set parameters($this,tframecount_$taskcount4) 0
+	while {$bodycount<2} {
+		
+		gets $fmri_file_id body_line
+		#   puts "READ ONE LINE Loop1"
+		if {[string match [string range $body_line 0 21] "List of images for set"]==1} {
+		set starter [string first "#" $body_line] 
+		set ender [string last "#" $body_line]
+		set parameters($this,runs_list_$taskcount4) [string range $body_line [expr $starter+1] [expr $ender-1]]
+		$this StringParse "runs_list_$taskcount4" "fmrirun_" $ender $taskcount4 0
+		#     puts "Runcount for task $taskcount4 is $parameters($this,fmriruncount_$taskcount4)"
+		#    puts "List of images for task $taskcount4 is $parameters($this,runs_list_$taskcount4)"
+		set bodycount [expr $bodycount+1]
+		}
+		
+		if {[string match [string range $body_line 0 11] "OFF set name"]==1} {
+		set starter [string first "#" $body_line] 
+		set ender [string last "#" $body_line]
+		set parameters($this,task_$taskcount4) [string range $body_line [expr $starter+2] [expr $ender-1]]
+		#   puts "Current Task name: $parameters($this,task_$taskcount4)"
+		#$tasklistbox insert end "T$taskcount4-$parameters($this,task_$taskcount4)"
+
+		set bodycount [expr $bodycount+1]
+		}
+		if {$subbodycount>=4} {
+		set bodycount 3
+		}
+		set subbodycount [expr $subbodycount+1]
+		
+	}
+	#	puts "OUT OF FIRST LOOP runcount- $parameters($this,fmriruncount_$taskcount4)"
+	
+	for {set bodycount2 1} {$bodycount2<=$parameters($this,fmriruncount_$taskcount4)} {incr bodycount2} {
+		gets $fmri_file_id body_line2
+		#    puts "READ ONE LINE Loop2"
+		if {[string match [string range $body_line2 0 5] "ranges"]==1} {
+		set start [string first "#" $body_line2]
+		set ender [string last "#" $body_line2]
+		set parameters($this,range_$taskcount4) [string range $body_line2 [expr $starter-3] [expr $ender-1]]
+		set framecount 0		#	puts $parameters($this,range_$taskcount4)
+		$this StringParse "range_$taskcount4" "fmriframe_" $ender $taskcount4 $bodycount2
+		
+		}
+	}
+	}
+	set convcount 0
+	
+	while {$convcount < 12} {
+	
+		gets $fmri_file_id line
+	#	puts $line
+	if {[string match [string range $line 0 30] "Series/File Name for anatomical"]==1} {
+		set starter [string first "#" $line] 
+		set ender [string last "#" $line]
+		set conv [string range $line [expr $starter+2] [expr $ender-2]]
+		#	    puts "STUDY NUMBER $parameters($this,study_number)"
+		#	    puts "CONVER: $conv"
+		set parameters($this,conventional) "$parameters($this,study_number)/$conv.hdr"
+		set parameters($this,display_conventional) [file tail $parameters($this,conventional)]
+	}
+	
+	set convcount [expr $convcount+1]
+	}
+
+
+	set lasttask [expr $taskcount4-1]
+   
+	for {set runcount 1} {$runcount <= $parameters($this,fmriruncount_$lasttask)} {incr runcount} {
+		#	    $runslistbox insert end "Run_$runcount"
+		set bonanza "00"
+		set letterbonanza $bonanza$parameters($this,fmrirun_$runcount)
+		set countbonanza [string length $letterbonanza]
+		if {$countbonanza==4} {
+		set letterbonanza "0$parameters($this,fmrirun_$runcount)"
+		} elseif {$countbonanza==5} {
+		set letterbonanza "$parameters($this,fmrirun_$runcount)"
+		}
+		set parameters($this,run_file_$runcount) "$parameters($this,study_number)/$parameters($this,series_number)_S$letterbonanza.hdr"
+		set parameters($this,display_run_file_$runcount) [file tail $parameters($this,run_file_$runcount)]
+
+		set numruns [expr $numruns+1]
+		
+		set parameters($this,runskip_$runcount) 0
+		}
+	
+	set numblocks [expr $numtasks*$numruns]
+	set blockid 1
+
+	for {set runcount2 1} {$runcount2 <= $numruns} {incr runcount2} {
+	    for {set taskcount2 1} {$taskcount2 <= $numtasks} {incr taskcount2} {
+		set parameters($this,skiprunsframe_$runcount2) ""
+		set parameters($this,tframe_${taskcount2}_${runcount2}) $parameters($this,{t$taskcount2}_{r$runcount2})
+	    }
+	}
+
+	return [ $this UpdateGUI ]
+}
+
+#Called in loadfMRI, parses strings based on spaces
+
+#----------------------------------------------------------------------------------------------------  
+itcl::body bis_fmrisetup::StringParse { mode outputtype end thistask thisrun} {
+	set count 0
+	set fmriread_tframecount 0
+	set parameters($this,tframecount_$thistask) 0
+	set parsecount 0
+	
+	while {$parsecount<$end} {
+	set parameters($this,parselist_$parsecount) [string first " " $parameters($this,$mode) $parsecount]
+	set parsecount [expr $parsecount+1]
+	}
+	
+	
+	set c 1
+	
+	while {$parameters($this,parselist_$c)!=-1} {
+	set cadd1 [expr $c+1]
+	set cadd2 [expr $c+2]
+	set cadd3 [expr $c+3]
+	set csub1 [expr $c-1]
+	set csub2 [expr $c-2]
+	
+	if {$parameters($this,parselist_$c)==$parameters($this,parselist_$cadd1) && $parameters($this,parselist_$cadd1)!=$parameters($this,parselist_$cadd2) && $parameters($this,parselist_$c)!=$parameters($this,parselist_$cadd3) &&	 $parameters($this,parselist_$c)!=$parameters($this,parselist_$csub1) } {
+		if {$outputtype=="fmrirun_"} {
+		set parameters($this,fmriruncount_$thistask) [expr $parameters($this,fmriruncount_$thistask)+1]			  
+		}
+		if {$outputtype=="fmriframe_"} {
+		set parameters($this,tframecount_$thistask) [expr $parameters($this,tframecount_$thistask)+1]
+		}
+		
+		
+		
+		set count [expr $count+1]
+		set parameters($this,$outputtype$count) [string range $parameters($this,$mode) $c $c]
+	} elseif {$parameters($this,parselist_$c)==$parameters($this,parselist_$cadd1) && $parameters($this,parselist_$cadd1)==$parameters($this,parselist_$cadd2) && $parameters($this,parselist_$c)!=$parameters($this,parselist_$cadd3) &&  $parameters($this,parselist_$c)!=$parameters($this,parselist_$csub1) } {
+		if {$outputtype=="fmrirun_"} {
+		set parameters($this,fmriruncount_$thistask) [expr $parameters($this,fmriruncount_$thistask)+1]
+		}   
+		if {$outputtype=="fmriframe_"} {
+		set parameters($this,tframecount_$thistask) [expr $parameters($this,tframecount_$thistask)+1]
+		}
+		
+		
+		set count [expr $count+1]
+		set parameters($this,$outputtype$count) [string range $parameters($this,$mode) $c $cadd1]
+		#	puts $parameters($this,$outputtype$count)
+	} elseif {$parameters($this,parselist_$c)==$parameters($this,parselist_$cadd1) && $parameters($this,parselist_$cadd1)==$parameters($this,parselist_$cadd2) && $parameters($this,parselist_$c)==$parameters($this,parselist_$cadd3) &&  $parameters($this,parselist_$c)!=$parameters($this,parselist_$csub1) && $parameters($this,parselist_$c)!=$parameters($this,parselist_$csub2) } {
+		if {$outputtype=="fmrirun_"} {
+		set parameters($this,fmriruncount_$thistask) [expr $parameters($this,fmriruncount_$thistask)+1]
+		}
+		
+		if {$outputtype=="fmriframe_"} {
+		set parameters($this,tframecount_$thistask) [expr $parameters($this,tframecount_$thistask)+1]
+		}
+		
+		set count [expr $count+1]
+		set parameters($this,$outputtype$count) [string range $parameters($this,$mode) $c $cadd2]
+		#	puts $parameters($this,$outputtype$count)
+	}
+	
+	set c [expr $c+1]
+	}
+	
+	set parameters($this,{t$thistask}_{r$thisrun}) ""
+	
+	if {$outputtype=="fmriframe_"} {
+	for {set framecount2 1} {$framecount2<=$parameters($this,tframecount_$thistask)} {incr framecount2} {
+		set framecount2plus1 [expr $framecount2+1]
+		set parameters($this,{t$thistask}_{r$thisrun}) "$parameters($this,{t$thistask}_{r$thisrun}) $parameters($this,fmriframe_$framecount2) $parameters($this,fmriframe_$framecount2plus1); "
+		set framecount2 [expr $framecount2+1]
+		# puts "Task $thistask Run $thisrun: $parameters($this,{t$thistask}_{r$thisrun})"
+		
+		}
+   }
+
+}
+   
+
+#Loads variable parameters from .xmlg file
+#Called in CreateGUI
+#Loads variable information from previous xml generator session, asks user to specify .xmlg file, sets variable 
+#information and displays values in each variable dialogue.	
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::LoadSetupFile { { fname "" } } {
+	 
+    if { [ string length $fname  ] == 0 } {
+	set savename "" 
+	set typelist { {"BioImage Suite Setup File" { .xmlg }} {"Old Style XML Setup File" { .xml }}}
+	set loadname [tk_getOpenFile -title "Load Filename" -filetypes $typelist ]
+	if { [ string length $loadname] < 1  } {
+	    return 0
+	}
+    } else {
+	set loadname $fname
+    }
+    
+    if { [ file extension $fname ] == ".xml"  } {
+	return [ $this ReadXMLFile $fname ]
+    }
+
+    if { [ file exists $loadname ] == 0 } {
+	return 0
+    }
+    set loadfile [file tail $loadname ]
+    set setupname $loadname
+    
+    $this ClearAllData 0
+    
+
+	set fileid [open $loadname r ]
+	seek $fileid 0 start
+
+	gets $fileid line
+	if { [ string compare $line "#BioImageSuite Study Description File"  ] != 0 &&
+	 [ string compare $line "#BioImageSuite Study Description File v2"  ] != 0 } {
+	close $fileid
+	if { [ string compare $line "#BioImageSuite Study Description Parameter File"  ] == 0 } {
+		return 0
+	}
+	return [ $this LoadOlderSetupFile $loadfile ]
+	}
+
+	set motionmode 0
+	if { [ string compare $line "#BioImageSuite Study Description File v2"	] == 0 } {
+	set motionmode 1
+	}
+
+
+	# First Block Study Title etc
+	gets $fileid line;    
+	gets $fileid line;    gets $fileid parameters($this,study_title)
+	gets $fileid line;    gets $fileid parameters($this,subject_id)
+
+	# Second Block Anatomical Data
+	gets $fileid line;    gets $fileid line;    gets $fileid line;	  
+	gets $fileid line;	  gets $fileid parameters($this,reference_brain_path)
+	if { $motionmode == 1 } {
+	gets $fileid line;	  gets $fileid parameters($this,reference_gw_map)
+	} else {
+	set parameters($this,reference_gw_map) ""
+	}
+	gets $fileid line;	  gets $fileid parameters($this,anatomical)
+	gets $fileid line;	  gets $fileid parameters($this,conventional)
+	gets $fileid line;	  gets $fileid parameters($this,referenceTransform)
+	gets $fileid line;	  gets $fileid parameters($this,internalTransform)
+	gets $fileid line;	  gets $fileid parameters($this,distortionTransform)
+
+	# Set some additional stuff
+	set parameters($this,reference_brain) $parameters($this,reference_brain_path)
+	set parameters($this,display_reference_brain) [file tail $parameters($this,reference_brain_path)]
+	set parameters($this,display_reference_gw_map) [file tail $parameters($this,reference_gw_map)]
+	set parameters($this,display_referenceTransform) [file tail $parameters($this,referenceTransform)]
+	set parameters($this,display_internalTransform) [file tail $parameters($this,internalTransform)]
+	set parameters($this,display_distortionTransform) [file tail $parameters($this,distortionTransform)]
+	set parameters($this,display_conventional) [file tail $parameters($this,conventional)]
+	set parameters($this,display_anatomical) [file tail $parameters($this,anatomical)]
+	
+	# Third Block Basic Parameters
+	gets $fileid line;    gets $fileid line;    gets $fileid line;	  
+	gets $fileid line;    gets $fileid parameters($this,session_id)
+	gets $fileid line;    gets $fileid parameters($this,session_description)
+	gets $fileid line;    gets $fileid numruns
+	gets $fileid line;    gets $fileid numtasks
+	gets $fileid line;    gets $fileid parameters($this,num_outcomes)
+	gets $fileid line;    gets $fileid parameters($this,tr)
+	gets $fileid line;    gets $fileid parameters($this,numslices)
+	gets $fileid line;    gets $fileid parameters($this,numframes)
+	gets $fileid line;    gets $fileid parameters($this,checks)
+	set parameters($this,checks) [ expr $parameters($this,checks) > 0 ]
+
+	#    if {$parameters($this,checks)==1} {
+	#	$skipframesentry config -state normal -textbackground white
+	#    }
+	gets $fileid line;    gets $fileid parameters($this,skipFrames)
+
+	# Fourth Block Output Locations
+	gets $fileid line;    gets $fileid line;    gets $fileid line;	  
+	gets $fileid line;    gets $fileid parameters($this,xml_output_file)
+	gets $fileid line;    gets $fileid parameters($this,xml_output_dir)
+	gets $fileid line;    gets $fileid parameters($this,output_dir)
+	
+	
+	# Fifth Block Runs
+	gets $fileid line;    gets $fileid line;    gets $fileid line;	  
+	for {set runcount 1} {$runcount <= $numruns} {incr runcount} {
+	#	puts stdout "Reading run $runcount / $numruns"
+		#$runslistbox insert end "Run_$runcount"
+	
+	gets $fileid line;   gets $fileid parameters($this,run_file_$runcount)
+	set parameters($this,display_run_file_$runcount) [file tail $parameters($this,run_file_$runcount)]
+	if { $motionmode == 1 } {
+		gets $fileid parameters($this,run_motionfile_$runcount)
+	} else {
+		set parameters($this,run_motionfile_$runcount) ""
+	}
+	set parameters($this,display_run_motionfile_$runcount) [file tail $parameters($this,run_motionfile_$runcount)]
+
+	puts stdout "Read Run = $parameters($this,display_run_file_$runcount), $parameters($this,run_motionfile_$runcount)"
+
+	gets $fileid tmp
+	set tmp [ string trim $tmp ]
+	if { $tmp == "No Skip" } {
+		set parameters($this,runskip_$runcount) 0
+		set parameters($this,skiprunsframe_$runcount) ""
+	} else {
+		set parameters($this,runskip_$runcount) 1
+		set parameters($this,skiprunsframe_$runcount) $tmp
+	}
+
+
+	}
+	
+	# Sixth Block Tasks
+	gets $fileid line;    gets $fileid line;    gets $fileid line;	  
+	for {set taskcount 1} {$taskcount <= $numtasks} {incr taskcount} {
+	gets $fileid line; gets $fileid parameters($this,task_$taskcount)
+	#$tasklistbox insert end "T$taskcount-$parameters($this,task_$taskcount)"
+
+	}
+	
+	# Seventh Block -- BLOCKS
+	gets $fileid line;    gets $fileid line;    gets $fileid line;	  
+	set numblocks [expr $numtasks*$numruns]
+	gets $fileid line 
+	gets $fileid parameters($this,blockunits)
+	set parameters($this,blockunits) [ expr $parameters($this,blockunits) > 0 ]
+
+	
+	for {set runcount 1} {$runcount <= $numruns} {incr runcount} {
+	    for {set taskcount 1} {$taskcount <= $numtasks} {incr taskcount} {
+		gets $fileid line
+		gets $fileid parameters($this,tframe_${taskcount}_${runcount})
+	    }
+	}
+	
+	# Eight Block -- Outcomes
+	gets $fileid line;    gets $fileid line;    gets $fileid line;	  
+	for {set outcount 1} {$outcount <= $parameters($this,num_outcomes)} {incr outcount} {
+	gets $fileid line;    
+		gets $fileid parameters($this,outcome_$outcount)
+	}
+	
+	#   puts $numruns
+	#    puts $numtasks
+
+
+	set line ""
+	gets $fileid line;   
+	if { [ string length $line ] < 5 } {
+	close $fileid; return 1
+	}
+
+	$this SetProcessingDefaults
+	$this ImportParameterBlock $fileid 
+	close $fileid
+	puts stdout "On To Update GUI"
+	return [ $this UpdateGUI ]
+}
+# -------------------------------------------------------------------------
+itcl::body bis_fmrisetup::LoadParameterFile { { fname "" } } {
+	 
+	if { [ string length $fname  ] == 0 } {
+	set savename "" 
+	set typelist { {"BioImage Suite Setup PARAMETER Only File" { .xmlg }}}
+	set loadname [tk_getOpenFile -title "Load Filename" -filetypes $typelist ]
+	if { [ string length $loadname] < 1  } {
+		return 0
+	}
+	} else {
+	set loadname $fname
+	}
+
+	if { [ file exists $loadname ] == 0 } {
+	return 0
+	}
+	set fileid [open $loadname r ]
+	gets $fileid line
+	if { [ string compare $line "#BioImageSuite Study Description Parameter File"  ] != 0 } {
+	close $fileid
+	puts stderr "Header of Extra File must be #BioImageSuite Study Description Parameter File"
+	return 0
+	}
+
+	$this ImportParameterBlock $fileid 1
+	return 1
+}
+# -------------------------------------------------------------------------
+itcl::body bis_fmrisetup::ImportParameterBlock { fileid { skipblank 0 } } {
+
+	# NINTH Block -- AFNI Stuff
+	gets $fileid line;    gets $fileid line;    
+	gets $fileid line
+
+	set done 0
+
+	while { [ gets $fileid line ] >=0 && $done == 0 } {
+	set index [string first "#" $line ]
+	if { $index == -1 } {
+		set index [string first ":" $line]
+		if { $index > 0 } {
+		set len	  [string length $line]
+		set key	  [string trim	 [string range $line 0 [expr $index - 1]]]
+		set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		
+		set ind [ lsearch  -exact $processnamelist $key ]
+		if { $ind >= 0 } {
+			set parameters($this,afni_$key) $value 
+		} else {
+			pxtkprint "Bad parameter \"$key\" specified in setup file. Ignored!\n"
+			pxtkconsole
+		}
+		}
+	} elseif { [ string first "Resting State" $line ] >=0 } {
+		set done 1
+	}
+	}
+
+	# Found Resting State ....
+
+	gets $fileid line;    
+	gets $fileid line 
+	set line [ string trim $line ]
+	if { $line !="" || $skipblank == 0 } {
+	set parameters($this,voiDefinitionImage) $line
+	set parameters($this,display_voiDefinitionImage) [file tail $parameters($this,voiDefinitionImage)]
+	gets $fileid line;    
+	}
+	gets $fileid line
+	set line [ string trim $line ]
+	if { $line !="" || $skipblank == 0 } {
+	set parameters($this,voiDefinitionSpace) $line
+	set a $parameters($this,voiDefinitionSpace)
+	if { $a != "Reference" && $a != "Conventional" && $a != "Anatomical" } {
+		set parameters($this,voiDefinitionSpace) "Functional"
+	}
+	}
+
+	gets $fileid line
+	gets $fileid line
+	set line [ string trim $line ]
+	if { $line !="" || $skipblank == 0 } {
+	set parameters($this,inverseReferenceTransform) $line
+	set parameters($this,display_inverseReferenceTransform) [file tail $parameters($this,inverseReferenceTransform)]
+	}
+
+	# Parameters next
+	gets $fileid line;     gets $fileid line;     gets $fileid line;
+
+
+	set done 0
+
+	while { [ gets $fileid line ] >=0 && $done == 0 } {
+	set index [string first "#" $line ]
+	if { $index == -1 } {
+		set index [string first ":" $line]
+		if { $index > 0 } {
+		set len	  [string length $line]
+		set key	  [string trim	 [string range $line 0 [expr $index - 1]]]
+		set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		
+		set ind [ lsearch  -exact $restingnamelist $key ]
+		if { $ind >= 0 } {
+			set parameters($this,resting_$key) $value 
+		} else {
+			pxtkprint "Bad parameter \"$key\" specified in setup file. Ignored!\n"
+			pxtkconsole
+		}
+		}
+	}
+		if { [ string trim $line ] == "#Extra GLM Parameters Parameters" } {
+			set done 1
+		}
+		
+	}
+
+	# GLM Extra next
+	   gets $fileid line;
+
+
+	set done 0
+
+	while { [ gets $fileid line ] >=0 && $done == 0 } {
+	    set index [string first "#" $line ]
+	    if { $index == -1 } {
+		set index [string first ":" $line]
+		if { $index > 0 } {
+		    set len	  [string length $line]
+		    set key	  [string trim	 [string range $line 0 [expr $index - 1]]]
+		    set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		    
+		    set ind [ lsearch  -exact $glmextranamelist $key ]
+		    if { $ind >= 0 } {
+			set parameters($this,glmextra_$key) $value 
+		    } else {
+			pxtkprint "Bad parameter \"$key\" specified in setup file. Ignored!\n"
+			pxtkconsole
+		    }
+		}
+	    } 
+	}
+    }
+#----------------------------------------------------------------------------------------------------  
+itcl::body bis_fmrisetup::LoadOlderSetupFile { loadname } {
+	 
+	if { $loadname == "" } {
+	return	0
+	}
+
+	$this ClearAllData 0
+
+	set fileid [open $loadname r ]
+
+	set setupname $loadname
+
+	seek $fileid 0 start
+	
+	gets $fileid numruns 
+	gets $fileid numtasks
+	gets $fileid parameters($this,num_outcomes)
+	gets $fileid parameters($this,study_title)
+	gets $fileid parameters($this,subject_id)
+	gets $fileid parameters($this,reference_brain_path)
+	set parameters($this,reference_brain) $parameters($this,reference_brain_path)
+	set parameters($this,display_reference_brain) [file tail $parameters($this,reference_brain_path)]
+	gets $fileid parameters($this,conventional)
+	gets $fileid parameters($this,anatomical)
+	gets $fileid parameters($this,referenceTransform)
+	gets $fileid parameters($this,internalTransform)
+	gets $fileid parameters($this,distortionTransform)
+	gets $fileid parameters($this,session_id)
+	gets $fileid parameters($this,session_description)
+	gets $fileid parameters($this,tr)
+	gets $fileid parameters($this,numslices)
+	gets $fileid parameters($this,numframes)
+	gets $fileid parameters($this,checks)
+	gets $fileid parameters($this,skipFrames)
+	gets $fileid parameters($this,xml_output_file)
+	gets $fileid parameters($this,xml_output_dir)
+	gets $fileid parameters($this,output_dir)
+	
+	set parameters($this,display_referenceTransform) [file tail $parameters($this,referenceTransform)]
+	set parameters($this,display_internalTransform) [file tail $parameters($this,internalTransform)]
+	set parameters($this,display_distortionTransform) [file tail $parameters($this,distortionTransform)]
+	
+	set parameters($this,display_conventional) [file tail $parameters($this,conventional)]
+	set parameters($this,display_anatomical) [file tail $parameters($this,anatomical)]
+	
+	
+	#    if {$parameters($this,checks)==1} {
+	#	$skipframesentry config -state normal -textbackground white
+	#    }
+	
+	for {set runcount 1} {$runcount <= $numruns} {incr runcount} {
+		#$runslistbox insert end "Run_$runcount"
+		gets $fileid parameters($this,run_file_$runcount)
+	set parameters($this,display_run_file_$runcount) [file tail $parameters($this,run_file_$runcount)]
+	gets $fileid parameters($this,runskip_$runcount)
+	gets $fileid parameters($this,skiprunsframe_$runcount)
+
+	}
+	
+	for {set taskcount 1} {$taskcount <= $numtasks} {incr taskcount} {
+		gets $fileid parameters($this,task_$taskcount)
+		#$tasklistbox insert end "T$taskcount-$parameters($this,task_$taskcount)"
+
+	}
+	
+	set numblocks [expr $numtasks*$numruns]
+	
+	for {set runcount 1} {$runcount <= $numruns} {incr runcount} {
+	    for {set taskcount 1} {$taskcount <= $numtasks} {incr taskcount} {
+		gets $fileid parameters($this,tframe_${taskcount}_${runcount})
+	    }
+	}
+	
+	for {set outcount 1} {$outcount <= $parameters($this,num_outcomes)} {incr outcount} {
+		gets $fileid parameters($this,outcome_$outcount)
+	}
+	
+	#   puts $numruns
+	#    puts $numtasks
+	close $fileid
+	$this UpdateGUI 
+	return 2
+}
+
+#----------------------------------------------------------------------------------------------------  
+	
+
+
+
+#----------------------------------------------------------------------------------------------------	   
+itcl::body bis_fmrisetup::ClearAllArrays {par { doask 0 }} {
+
+    if { $doask == 1 } {
+	
+	set ok [ tk_messageBox -type yesno -default no -title "WARNING!" -message "Are you sure you want to clear all $par arrays" ]
+	if { $ok == "no" } {
+	    return
+	}
+    }
+    
+    switch -exact $par {
+	"tframe" {
+	    for {set taskcount 1} {$taskcount<=$numtasks} {incr taskcount} {
+		for {set runcount 1} {$runcount<=$numruns} {incr runcount} {
+		    set parameters($this,tframe_${taskcount}_${runcount}) ""
+		}
+	    }
+	} "runs" {
+	    for {set c3 1} {$c3<=$numruns} {incr c3} {
+		set parameters($this,run_file_$c3) ""
+		set parameters($this,run_file_${c3}_length) 0
+	    }
+	} "task" {
+		for {set c4 1} {$c4<=$numtasks} {incr c4} {
+		set parameters($this,task_$c4) ""
+		}
+	} "outcome" {
+	    for {set c5 1} {$c5<=$parameters($this,num_outcomes)} {incr c5} {
+		set parameters($this,outcome_$c5) ""
+	    }
+	}
+	
+    }
+}
+
+
+#Prints all information to file
+#Called in CreateGui
+#Invoked when user presses "Create .xml file!" button in main window
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::WriteXMLFile { { outdir 0 } } {
+	global tcl_platform
+
+	set imagepath $::pxtclvtkpxcontrib::imagedir
+  #  puts stdout "Imagepath = $imagepath"
+
+	if { $outdir !=0 } {
+	set parameters($this,xml_output_dir) $outdir
+	}
+
+	set ind [ lsearch -exact $referenceimagenames $parameters($this,display_reference_brain) ]
+	if { $ind >=0 } {
+	set parameters($this,reference_brain_path) [ lindex $referenceimagepaths $ind ] 
+	} else { 
+	set parameters($this,reference_brain_path) $parameters($this,reference_brain) 
+	}   
+		   
+	set outname [ file join $parameters($this,xml_output_dir) $parameters($this,xml_output_file) ]
+	set present [file exists $outname.xml]
+
+	if { $present==1 } {
+	set ok [ tk_messageBox -type yesno -default no -title "WARNING!" -message "The file $outname.xml already exists. Overwrite?" -icon question ]
+	if { $ok=="no" } {
+		return
+	}
+	} 
+
+	set fileid [open $outname.xml w+ ]
+	
+	set dtdpath [ file normalize [	file join [ file join [ file dirname [ info script ]] .. ] vtknr ] ]
+	set dtdfile [ file join $dtdpath fmri.dtd ]
+	
+	
+	puts $fileid "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"no\" ?>"
+	
+	
+	
+	puts $fileid "<!DOCTYPE setup SYSTEM \"$dtdfile\">"
+	puts $fileid "<!-- xml begins here -->"
+	puts $fileid " <setup>" 
+	puts $fileid "	 <name> fMriGlm </name>"
+	puts $fileid "	 <description> $parameters($this,study_title) </description>"
+	puts $fileid "	 <fmri>"
+	puts $fileid "	   <process id=\"fMriEventGlm\">"
+	puts $fileid "	     <name> Event Related GLM Analysis </name> "
+	puts $fileid "	     <description> Event Related GLM Analysis </description>"
+	puts $fileid "	   </process>"
+	puts $fileid "	   <referenceImage>"
+	puts $fileid "	     $parameters($this,reference_brain_path)"
+	puts $fileid "	   </referenceImage>"
+	
+	for {set taskprintcount 1} {$taskprintcount <= $numtasks} {incr taskprintcount} {
+	puts $fileid "	   <task id=\"$parameters($this,task_$taskprintcount)\">"
+	puts $fileid "	     <name> $parameters($this,task_$taskprintcount) </name>"
+	puts $fileid "	     <description> $parameters($this,task_$taskprintcount) </description>"
+	puts $fileid "	   </task>"
+	}
+	
+	puts $fileid "	   <subject id=\"$parameters($this,subject_id)\">"
+	puts $fileid "	      <name> $parameters($this,subject_id) </name>"
+	puts $fileid "	      <description> Subject $parameters($this,subject_id) </description>"
+	
+	puts $fileid "	      <conventionalImage>"
+	puts $fileid "	       $parameters($this,conventional)"
+	puts $fileid "	      </conventionalImage>"
+	puts $fileid "	      <anatomicalImage>"
+	puts $fileid "		$parameters($this,anatomical)"
+	puts $fileid "	      </anatomicalImage>"
+	puts $fileid "	      <referenceTransform>"
+	puts $fileid "	       $parameters($this,referenceTransform)"
+	puts $fileid "	      </referenceTransform>"
+	puts $fileid "	      <internalTransform>"
+	puts $fileid "	       $parameters($this,internalTransform)"
+	puts $fileid "	      </internalTransform>"
+	puts $fileid "	      <distortionTransform>"
+	puts $fileid "	       $parameters($this,distortionTransform)"
+	puts $fileid "	      </distortionTransform>"
+	
+	puts $fileid "	      <session id=\"$parameters($this,session_id)\">"
+	puts $fileid "		 <description> $parameters($this,session_description) </description>"
+	puts $fileid "		 <tshift/>"
+	if {$parameters($this,checks)==1} {
+	puts $fileid "		 <skipFrames> $parameters($this,skipFrames) </skipFrames>"
+	}
+	puts $fileid "		 <TR>$parameters($this,tr)</TR>"
+	puts $fileid "		 <numSlices> $parameters($this,numslices) </numSlices>"
+	puts $fileid "		 <numFrames> $parameters($this,numframes) </numFrames>"
+	
+	for {set runcount2 1} {$runcount2 <= $numruns} {incr runcount2} {
+	puts $fileid "	      <run id=\"r$runcount2\">"
+	puts $fileid "		 <filename>"
+	puts $fileid "		  $parameters($this,run_file_$runcount2)"
+	puts $fileid "		 </filename>"
+	if {$parameters($this,runskip_$runcount2)==1} {
+		puts $fileid "		  <skipFrames> $parameters($this,skiprunsframe_$runcount2) </skipFrames>"
+	}
+	for {set taskcount2 1} {$taskcount2 <= $numtasks} {incr taskcount2} {
+		set t t$taskcount2
+		set r r$runcount2
+		set tr "$t\_$r"
+		puts $fileid "	      <task_block_id> $tr </task_block_id>"
+	}
+	puts $fileid "	      </run>"
+	}
+	
+	set blockcount3 1
+
+	set tfname "tFrames"
+	if { $parameters($this,blockunits) == 1 } {
+	set tfname "timeFrames"
+	}
+
+
+    for {set runcount3 1} {$runcount3 <= $numruns} {incr runcount3} {
+	for {set taskcount3 1} {$taskcount3 <= $numtasks} {incr taskcount3} {
+	    set t t$taskcount3
+	    set r r$runcount3
+	    set tr "$t\_$r"
+	    puts $fileid "		<block id=\"$tr\">"
+	    puts $fileid "		  <task_id> $parameters($this,task_$taskcount3) </task_id>"
+	    puts $fileid "		  <activation>"
+	    puts $fileid "		     <${tfname}>$parameters($this,tframe_${taskcount3}_${runcount3})</${tfname}>"
+	    puts $fileid "		     <bValue> 1.0 </bValue>"
+	    puts $fileid "		  </activation>"
+	    puts $fileid "		 </block>"
+	    set blockcount3 [expr $blockcount3+1]
+	}    
+    }
+    
+    puts $fileid "		</session>"
+    
+	for {set taskcount4 1} {$taskcount4 <= $parameters($this,num_outcomes)} {incr taskcount4} {
+	puts $fileid "		<outcome> $parameters($this,outcome_$taskcount4) </outcome>"
+	}
+	
+	puts $fileid "		<outputDirectory>"
+	puts $fileid "		    $parameters($this,output_dir)"
+	puts $fileid "		</outputDirectory>"
+	puts $fileid "	     </subject>"
+	puts $fileid "	   </fmri>"
+	puts $fileid "	</setup>"
+	
+	close $fileid
+	 
+	$this InfoMessage "The xml file was saved as $outname.xml "  "File Saved"
+	return 1
+}
+
+#Reads old style Rajeevan XML File -- complement to above
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::ReadXMLFile { fname { subjectno 1 } { onlyrun -1 } } {
+
+    
+    if { $onlyrun < 1 } {
+	set onlyrun 0
+    }
+
+    #    set onlyrun 1
+
+    set parse [ vtkXMLDataParser New ]
+    $parse SetFileName $fname
+    $parse SetIgnoreCharacterData 0
+    $parse Parse
+
+    set rootnode [ $parse GetRootElement ]
+    if { $rootnode == "" } {
+	$parse Delete
+	return 0
+    }
+
+    set nm [ $rootnode GetName ]
+    if { $nm != "setup" } {
+	puts stderr "BAD XML File $nm"
+	$parse Delete
+	return 0
+    }
+
+    puts stdout "Nm=$nm"
+
+    $this ClearAllData 0
+
+    set fmnode [ $rootnode LookupElementWithName "fmri" ]
+    puts stdout "fm=[ $fmnode GetName ]"
+
+    set tmp [ $fmnode LookupElementWithName "referenceImage" ]
+    set v [ string trim [ $tmp GetCharacterData ] ]
+    puts stdout "v=$v"
+    set parameters($this,reference_brain_path) [ file normalize $v ]
+    
+
+    # List all tasks
+    set numtasks 0
+    set xmltaskidlist ""
+    for { set j 0 } { $j < [ $fmnode GetNumberOfNestedElements ] } { incr j } {
+	set c [ $fmnode GetNestedElement $j ]
+	if { [ $c GetName ] == "task" } {
+	    incr numtasks
+	    lappend xmltaskidlist  [ string trim [ $c GetAttribute id ] ]
+	    set tmp [ $c LookupElementWithName "name" ]
+	    set parameters($this,task_$numtasks) [ string trim [ $tmp GetCharacterData ] ]
+	    puts stdout "Adding task $parameters($this,task_$numtasks) with id  [ string trim [ $c GetAttribute id ] ] "
+	}
+    }
+
+    puts stdout "Added $numtasks tasks"
+
+    set count 1
+    set subject 0
+    for { set j 0 } { $j < [ $fmnode GetNumberOfNestedElements ] } { incr j } {
+	set c [ $fmnode GetNestedElement $j ]
+	if { [ $c GetName  ] == "subject" } {
+	    if { $count == $subjectno } {
+		set subject $c
+		set j  [ $fmnode GetNumberOfNestedElements ]
+	    } else {
+		incr count
+	    }
+	}
+    }
+
+    set session 0
+    
+    if { $subject == 0 || $numtasks == 0 } {
+	puts stderr "Bad Setup File\n"
+    } else {
+	set parameters($this,subject_id) [ string trim [ $subject GetAttribute id ] ]
+	puts stdout "Subject = $parameters($this,subject_id)"
+	
+	set chld [ $subject LookupElementWithName name ]
+	set a1 [ string trim [ $chld GetCharacterData ] ]
+	set chld [ $subject LookupElementWithName description ]
+	set a2 [ string trim [ $chld GetCharacterData ] ]
+	set parameters($this,study_title) "$a1,$a2"
+
+	set lst1 [ list conventionalImage anatomicalImage  referenceTransform internalTransform distortionTransform skipFrames ]
+	set lst2 [ list conventional      anatomical       referenceTransform internalTransform distortionTransform skipFrames ]
+	
+	for { set j 0 } { $j < [ $subject GetNumberOfNestedElements ] } { incr j } {
+	    set e [ $subject GetNestedElement $j ]
+	    set n [ $e GetName ]
+	    set ind [ lsearch -exact $lst1 $n ]
+	    if {   $ind > -1 } {
+		set internal [ lindex $lst2 $ind ]
+		set parameters($this,$internal) [ string trim [ $e GetCharacterData ] ]
+		puts stdout "Setting $internal to $parameters($this,$internal)"
+	    } elseif { $n == "session" } {
+		set session $e 
+		puts stdout "Setting Session to $n"
+	    }
+	
+	    set parameters($this,reference_brain) $parameters($this,reference_brain_path)
+	    set parameters($this,display_reference_brain) [file tail $parameters($this,reference_brain_path)]
+	    set parameters($this,display_reference_gw_map) [file tail $parameters($this,reference_gw_map)]
+	    set parameters($this,display_referenceTransform) [file tail $parameters($this,referenceTransform)]
+	    set parameters($this,display_internalTransform) [file tail $parameters($this,internalTransform)]
+	    set parameters($this,display_distortionTransform) [file tail $parameters($this,distortionTransform)]
+	    set parameters($this,display_conventional) [file tail $parameters($this,conventional)]
+	    set parameters($this,display_anatomical) [file tail $parameters($this,anatomical)]
+
+	    if { [ string length $parameters($this,skipFrames)  ] > 1 } {
+		set parameters($this,checks) 1
+	    } else {
+		set parameters($this,checks) 0
+	    }
+    	}
+    }
+
+    set runlst ""
+    set blocklst ""
+    
+
+    if { $session !=0  } {
+	# Parse session stuff now
+	set parameters($this,session_id) [ string trim [ $session GetAttribute id ] ]
+	set de [ $session LookupElementWithName description ]
+	set parameters($this,session_description) [ string trim  [ $de GetCharacterData ] ]
+	puts stdout "Desc = $parameters($this,session_description)"
+
+	set lst1 [ list TR numSlices numFrames ]
+	set lst2 [ list tr numslices numframes ]
+	
+	for { set j 0 } { $j < [ $session GetNumberOfNestedElements ] } { incr j } {
+	    set e [ $session GetNestedElement $j ]
+	    set n [ $e GetName ]
+	    set ind [ lsearch -exact $lst1 $n ]
+	    if {   $ind > -1 } {
+		set internal [ lindex $lst2 $ind ]
+		set parameters($this,$internal) [ string trim [ $e GetCharacterData ] ]
+		puts stdout "Setting $internal to $parameters($this,$internal)"
+	    } elseif { $n == "run" } {
+		lappend runlst $e
+		set xmlrunid([llength $runlst ]) [ string trim [ $e GetAttribute id ] ]
+	    } elseif { $n == "block" } {
+		lappend blocklst $e
+		set xmlblockid([llength $blocklst ]) [ string trim [ $e GetAttribute id ] ]
+	    }
+	}
+	puts stdout "Found [ llength $runlst ] runs and [ llength $blocklst ] blocks" 
+    }
+
+    #set xmlblocklist 
+    set numruns 0
+    for { set i 0 } { $i < [ llength $runlst ] } { incr i } {
+	incr numruns
+	set xmlblocklist($numruns) ""
+	puts stdout "Run ID =  $xmlrunid([ expr $i+1 ])"
+	set rel [ lindex $runlst $i ]
+	for { set j 0 } { $j < [ $rel GetNumberOfNestedElements ] } { incr j } {
+	    set e [ $rel GetNestedElement $j ]
+	    set n [ $e GetName ]
+	    if { $n == "filename" } {
+		set parameters($this,run_file_$numruns) [ string trim [ $e GetCharacterData ] ]
+		set parameters($this,display_run_file_$numruns) [file tail $parameters($this,run_file_$numruns)]
+		set parameters($this,display_run_motionfile_$numruns) ""
+		set parameters($this,run_motionfile_$numruns) ""
+		set parameters($this,runskip_$numruns) 0
+		set parameters($this,skiprunsframe_$numruns) ""
+		for { set k 1 } { $k <= $numtasks } { incr k } {
+		    set parameters($this,tframe_${k}_${numruns}) ""
+		    puts stdout "setting parameters($this,tframe_${k}_${numruns}) to blank"
+		}
+		puts stdout "Adding run filename ($numruns) = $parameters($this,run_file_$numruns)"
+	    } elseif { $n == "task_block_id" } {
+		lappend xmlblocklist($numruns) [ string trim [ $e GetCharacterData ] ]
+	    } elseif { $n ==  "skipFrames" } {
+		set v [ string trim [ $e GetCharacterData ] ]
+		if { [ string length $v ] < 1 } {
+		    set parameters($this,runskip_$numruns) 0
+		    set parameters($this,skiprunsframe_$numruns) ""
+		} else {
+		    set parameters($this,runskip_$numruns) 1
+		    set parameters($this,skiprunsframe_$numruns) $v
+		}
+	    }
+	}
+    }
+    puts stdout "\n\n"
+    for { set i 1 } { $i <= $numruns } { incr i } {
+	puts stdout "Blocklist for run $i = $xmlblocklist($i) "
+    }
+
+    puts stdout "\n\n"
+    for { set i 0 } { $i < [ llength $blocklst ] } { incr i } {
+	set blk [ lindex $blocklst $i ]
+	set bid [ string trim [ $blk GetAttribute id ]]
+	set whichrun 0
+	set count 1
+	
+	#	puts stdout "Block id = $bid"
+
+	while { $count <= $numruns && $whichrun == 0 } {
+	    set ind [ lsearch -exact $xmlblocklist($count) $bid ]
+	    if { $ind > -1 } {
+		set whichrun $count
+	    } else { 
+		incr count
+	    }
+	    #   puts stdout "Looking for $bid in $xmlblocklist($count) (count=$count/ $numruns) ind=$ind (whichrun=$whichrun)"
+	}
+
+	if { $whichrun > 0 } {
+	    set tmp [ $blk LookupElementWithName "task_id" ]
+	    set tsk [ string trim [ $tmp GetCharacterData ] ]
+	    set ind [ lsearch -exact $xmltaskidlist $tsk ]
+	    if { $ind > -1 } {
+		set taskno [ expr $ind +1 ]
+		puts stdout "Adding $bid to task $taskno ($tsk), Run=$whichrun"
+
+		set act [ $blk LookupElementWithName "activation" ]
+		set tfr [ $act LookupElementWithName "tFrames" ]
+		set tfr2 [ $act LookupElementWithName "timeFrames" ]
+		set val ""
+		if { $tfr != "" } {
+		    set parameters($this,blockunits) 1
+		    set val [ string trim [ $tfr GetCharacterData ] ]
+		} elseif { $tfr2 != "" } {
+		    set parameters($this,blockunits) 0
+		    set val [ string trim [ $tfr2 GetCharacterData ] ]
+		}
+		set parameters($this,tframe_${taskno}_${whichrun}) $val
+		puts stdout "Setting parameters($this,tframe_${taskno}_${whichrun}) $val\n"
+	    } else {
+		puts "Bad Run $whichrun  block with id $bid (i.e. $tsk not found in $xmltaskidlist, ind=$ind)\n"
+	    }
+	} else {
+	    puts stdout "Bad Block $bid\n"
+	}
+    }
+
+    set parameters($this,afni_hrfmode) triplegamma
+
+    $parse Delete
+
+    if { $onlyrun >=1 && $onlyrun <= $numruns } {
+	if { $onlyrun != 1 } {
+	    set parameters($this,run_file_1) $parameters($this,run_file_$whichrun)
+	    set parameters($this,display_run_file_1) $parameters($this,display_run_file_$whichrun)
+	    set parameters($this,run_motionfile_1) $parameters($this,run_motionfile_$whichrun)
+	    set parameters($this,display_run_motionfile_1) $parameters($this,display_run_motionfile_$whichrun)
+	}
+	for {set runcount 2 } {$runcount<$numruns} {incr runcount} {
+	    set parameters($this,run_file_${runcount}) ""
+	    set parameters($this,display_run_file_${runcount})  ""
+	    set parameters($this,run_motionfile_${runcount}) ""       
+	    set parameters($this,display_run_motionfile_${runcount}) ""
+	    for {set taskcount 1} {$taskcount<=$numtasks} {incr taskcount} {
+		set parameters($this,tframe_${taskcount}_$runcount) ""
+	    }
+	}
+	set numruns 1
+    }
+    set ok [ $this UpdateGUI ]
+    $this SaveSetupFile "test.xmlg"
+    exit
+    return $ok
+}
+
+
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::ParseFramesString { val usingseconds tr numframes offset message  { debug 0 }} {
+	
+	regsub -all ";" $val "" val2
+	regsub -all " +" $val2 " " val3
+	set val3 [ string trim $val3 ]
+	set n [ llength $val3 ]
+	set m [ expr 2*(int($n/2)) - $n ]
+
+	set plist ""
+
+	if { $debug > 0 } {
+	pxtkprint "+++++ Cleaned up  val=$val3 , number = $n (isodd = $m)\n"
+	}
+
+	if { $m != 0 } {
+	$this InfoMessage "Bad Definition for $message, $n total elements ($val3), which is not an even number"	 "Error ..."  error
+	return 0
+	}
+	set half [ expr int($n/2) ]
+	for { set i 0 } { $i < $half } { incr i } {
+	
+	set ind(0) [ expr $i *2 ]
+	set ind(1) [ expr $ind(0) +1 ]
+	
+	if { $debug > 1 } {
+		pxtkprint "\t\t\t Checking Pair [ expr $i+1 ]/$half  $ind(0):$ind(1)"
+	}
+	
+	
+	for { set k 0 } { $k <= 1 } { incr k } {
+		set op($k)   [ lindex $val3 $ind($k) ]
+		if { $usingseconds > 0	} {
+		set p($k) [ expr int($op($k)/$tr) ]
+		} else {
+		set p($k) [ expr int($op($k)) ]
+		}
+		
+		if { $debug > 1 } {
+		pxtkprint "p($k) = $op($k) sec --> $p($k) fr, "
+		}
+		
+		
+		if { $p($k) < 0 || $p($k) >= $numframes } {
+		$this InfoMessage "Out of bounds Block Definition for $message, blockpart = [ expr $i+1 ] ( $op(0):$op(1))" "Error ..." error
+		return 0
+		}
+		
+		set p($k) [ expr $p($k) + $offset  ]
+		if { $debug > 1 } {
+		pxtkprint "--> + $offset = $p($k) "
+		}
+	}
+	if { $debug > 0 } {
+		pxtkprint "\n"
+	}
+	lappend plist [ list $p(0) $p(1) ]
+	}
+	return $plist
+
+}
+
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::CreateBaseGLMMatrix { { debug 0 } } {
+
+    # If we are not specifying an external matrix then we are fine
+    if { $parameters($this,glmextra_useexternalmatrix)  == 0 } {
+	puts stdout "Creating Matrix From Block Definitions"
+	return [ $this ValidateBlockDefinitions 1 $debug ]
+    }
+
+    set lst [ $this ComputeEmptyGLMMatrixDimensions $debug ]
+    if { [ lindex $lst 0 ] == 0 || [ lindex $lst 1 ] == 0 } {
+	return 0
+    }
+    puts stdout "Creating Empty Matrix [ lindex $lst 0 ] x [ lindex $lst 1 ]"
+	
+    set matrix [ vtkpxMatrix [ pxvtable::vnewobj ]]
+	
+    set ok [ $matrix Load $parameters($this,glmextra_externalmatrixfilename) ]
+	
+    if { $ok == 0 } {
+	# Error message about bad matrix
+	$this InfoMessage "Please provide matrix. Calculation is terminated" "Error ..." error
+	$matrix Delete
+	return 0
+    }
+
+    set sz [ $matrix GetSize ]
+	
+    if { [ lindex $sz 0 ] != [ lindex $lst 0 ] || [ lindex $sz 1 ] != [ lindex $lst 1 ] } {
+	# Error message bad matrix dimensions should be $lst
+	$this InfoMessage "Bad matrix dimensions. Should be [ lindex $lst 0 ] x [ lindex $lst 1 ]. Calculation is terminated. " "Error ..." error
+	$matrix Delete
+	return 0
+    }
+
+    puts stdout "Using External Matrix from $parameters($this,glmextra_externalmatrixfilename), dims = [ $matrix GetSize ]"
+
+    return $matrix
+}
+# --------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::ComputeEmptyGLMMatrixDimensions { { debug 0 } } {
+
+    set totalframes 0
+    
+    if { $debug > 0 } {
+	pxtkconsole
+    }
+    
+    # First Read Headers and Compute Total Number Of Frames
+    for { set runcount 1 } { $runcount <= $numruns } { incr runcount } {
+	set rname $parameters($this,run_file_$runcount)
+	set hd [ vtkbisImageHeader [ pxvtable::vnewobj ]]
+	set ok [ $hd ReadHeader $rname ]
+	if { $ok == 0 } {
+	    $this InfoMessage "Bad run file run=$runcount ($name)" "Error ..." error
+	    return [ list 0 0 ]
+	}
+	set numframes [ $hd  GetNumberOfComponents ]
+		puts $numframes
+	
+	if { $numframes < 2 } { 
+	    $this InfoMessage "Bad run file run=$runcount (numframes=$numframes)" "Error ..." error
+	    return [ list 0 0 ]
+	}
+	set parameters($this,run_file_${runcount}_length)   $numframes
+	pxtkprint "Header $rname, frames = $numframes\n"
+	$hd Delete
+	set totalframes [ expr $totalframes + $numframes ]
+    }
+	
+	
+    if { $debug } {
+	pxtkprint "Total Frames = $numframes\n "
+    }
+    
+    return [ list $totalframes $numtasks ]
+}
+
+itcl::body bis_fmrisetup::ValidateBlockDefinitions { { creatematrix 0 } { debug 0 } } {
+
+    
+    set lst [ $this ComputeEmptyGLMMatrixDimensions $debug ]
+    if { [ lindex $lst 0 ] == 0 } {
+	return 0
+    }
+
+    set totalframes [ lindex $lst 0 ]
+    set matrix 1
+    if { $creatematrix != 0 } {
+	set matrix [ vtkpxMatrix [ pxvtable::vnewobj ]]
+	$matrix Zeros $totalframes $numtasks
+    }
+
+    set offset 0
+    for {set runcount 1} {$runcount<=$numruns} {incr runcount} {
+	set numframes $parameters($this,run_file_${runcount}_length)   
+	if { $debug > 0 } {
+	    pxtkprint "\nChecking Table for run = $runcount/ $numruns, numframes=$numframes\n-----------------------------------------------------------------\n\n"
+	}
+	
+	for {set taskcount 1} {$taskcount<=$numtasks} {incr taskcount} {
+	    set  val $parameters($this,tframe_${taskcount}_${runcount})
+	    
+	    if { $debug > 0 } {
+		pxtkprint "Checking Table for run = $runcount/ $numruns, task = $taskcount/ $numtasks , val = $val\n"
+	    }
+	    
+	    set plist [ $this ParseFramesString $val $parameters($this,blockunits) $parameters($this,tr) $numframes $offset \
+			    "run=$runcount, task=$taskcount" $debug ]
+	    
+	    if { $plist == 0 } {
+		catch { $matrix Delete }
+		return 0
+	    }
+	    
+	    for { set k 0 } { $k < [ llength $plist ] } { incr k } {
+		set p(0) [ lindex [ lindex  $plist $k ]	 0 ]
+		set p(1) [ lindex [ lindex  $plist $k ]	 1 ]
+		set tskindex [ expr $taskcount -1 ]
+		if { $debug > 1 } {
+		    pxtkprint "....\t\t\t\t now filling with 1 between  $p(0):$p(1)\n"
+		}
+		if { $creatematrix > 0 } {
+		    for { set j $p(0) } { $j <= $p(1) } { incr j } {
+			$matrix SetElement $j $tskindex 1
+		    }
+		} 
+	    }
+	}
+	
+	if { $parameters($this,runskip_$runcount) == 1	|| $parameters($this,checks) > 0 } {
+	    set val "$parameters($this,skipFrames) $parameters($this,skiprunsframe_$runcount)"
+	    if { $debug > 0 } {
+		pxtkprint "Checking Table for Skipframes run = $runcount/ $numruns, skipframes= $val\n"
+	    }
+	    
+	    set plist [ $this ParseFramesString $val  0 1 $numframes $offset \
+			    "run=$runcount, skipframes" $debug ]
+	    
+	    if { $plist == 0 } {
+		catch { $matrix Delete }
+		return 0
+	    }
+	    
+	    for { set k 0 } { $k < [ llength $plist ] } { incr k } {
+		set p(0) [ lindex [ lindex  $plist $k ]	 0 ]
+		set p(1) [ lindex [ lindex  $plist $k ]	 1 ]
+		set tskindex [ expr $taskcount -1 ]
+		if { $debug > 1 } {
+		    pxtkprint "....\t\t now filling with zeros all columns Between	$p(0):$p(1)\n"
+		}
+		if { $creatematrix > 0 } {
+		    puts stdout "Zeroing rows (0-offset) $p(0):$p(1)"
+		    for { set j $p(0) } { $j <= $p(1) } { incr j } {
+			for { set ja 0 } { $ja < $numtasks } { incr ja } {
+			    $matrix SetElement $j $ja 0
+			}
+		    }
+		}
+	    }
+	}
+	set offset [ expr $offset + $numframes ]
+    }
+    return $matrix
+}
+#----------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::AFNICreateTimeFile { { tname "" } { report 0 } } {
+
+	if { $tname == "" } {
+	set tname [ file join $parameters($this,output_dir) afni_timepoints ]
+	}
+
+	set stimname "[ file root $tname ]_startpoints.txt"
+	set totalframes [ expr $numruns * $parameters($this,numframes) ]
+	set matrix [ $this CreateBaseGLMMatrix 0 ]
+	if { $matrix == 0 } {
+	return "none"
+	}
+
+	set fout2 [ open $stimname w ]
+	set index 0
+	for { set runcount 1 } { $runcount <= $numruns } { incr runcount } {
+	set numframes $parameters($this,run_file_${runcount}_length)   
+	set tmpname ${tname}_${runcount}.txt
+	set fout [ open $tmpname w ]
+	#	puts stdout "run = $runcount/$numruns Index = $index, file = $tmpname, numframes=$numframes "
+	puts $fout2 $index 
+	for { set frame 1 } { $frame <= $numframes } { incr frame } {
+		for {set taskcount 0} {$taskcount < [ expr $numtasks - 1 ] } {incr taskcount} {
+		puts -nonewline $fout "[ $matrix GetElement $index $taskcount ]\t"
+		}
+		puts $fout "[ $matrix GetElement $index	 [ expr $numtasks -1 ] ]"
+		incr index
+	}
+	close $fout
+	}
+
+	close $fout2
+
+	$this InfoMessage "Saved timepoint files in [ file tail $tname ] and \n [ file tail $stimname ]\n in directory: [ file dirname $stimname ]"  "Block Design Files Saved"	 info
+
+	return [ list $tname $stimname ]
+}
+
+
+
+# ----------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::SetProcessingDefaults {  } {
+
+	set processlist ""
+	set processnamelist ""
+
+	lappend processlist { "#Ensure Inputs are NIFTI"  ensurenifti 0 }
+	lappend processlist { "#Delete Temporary Files"	 deletetemp 1 }
+	lappend processlist { "#Mask Level (% of max intensity)"  masklevel 0.05 }
+	lappend processlist { "#HRF Mode -- one of wav, gamma, doublegamma, triplegamma spm" hrfmode wav }
+	lappend processlist { "#Use AFNI Waver; if 0 use internal code which is cleaner/faster etc" useafniwaver 0 }
+	lappend processlist { "#Use AFNI Commands for intensity normalization; if 0 use internal code which is cleaner/faster etc" useafninormalize 0 }
+	lappend processlist { "#GLM Delaytime"	delaytime 2.0 }
+	lappend processlist { "#GLM Risetime"  risetime 4.0 } 
+	lappend processlist { "#GLM Falltime"  falltime 6.0 } 
+	lappend processlist { "#GLM Undershoot"	 undershoot 0.2 } 
+	lappend processlist { "#GLM Peak"  peak 1.0 } 
+	lappend processlist { "#Polynomial Drift"  polort 3 } 
+	lappend processlist { "#Output Baseline Coefficientts" bout 0 } 
+	lappend processlist { "#Output F-Statistics" fout 0 } 
+	lappend processlist { "#Output R^2-Statistics" rout 0 }	 
+	lappend processlist { "#Output T-Statistics" tout 0 }  
+	lappend processlist { "#Output Residual Time Series" saveresidual 0 }  
+	lappend processlist { "#Output Drift Beta Maps" savedriftbeta 0 }  
+	lappend processlist { "#Output Sample Variance Map" vout 0 }
+	lappend processlist { "#GLM Single Run Output" glmsinglerunoutput 0 }
+	lappend processlist { "#GLM Regress Motion Parameters" glmregressmotion 0 }
+
+	lappend processlist { "#Rate GLM Terms" numrateterms 1 }
+	lappend processlist { "#Rate GLM Global Drift" rateglobal 0 }
+	
+
+	for { set i 0 } { $i < [ llength $processlist ] } { incr i } {
+	set elem [ lindex $processlist $i ]
+	set name [ lindex $elem 1 ]
+	set val	 [ lindex $elem 2 ]
+	lappend processnamelist $name
+	set parameters($this,afni_$name) $val
+	}
+
+	set restinglist ""
+	set restingnamelist ""
+
+	lappend restinglist { "#Mask Level (% of max intensity)"  masklevel 0.05 }
+	lappend restinglist { "#Polynomial Drift"  driftpol 3 } 
+	lappend restinglist { "# Slice Mean Removal "  slicemeanremoval 1 }
+	lappend restinglist { "# Volume Mean Removal "	volumemeanremoval 0 }
+	lappend restinglist { "#Raw Correlation"  rawcorrelation 0 } 
+	lappend restinglist { "#Z Transform"  ztransform 0 }
+	lappend restinglist { "#Process Runs Individually"  individualruns 1 } 
+	lappend restinglist { "#Temporal Smoothing Sigma (Frames)"  temporalsigma 0.0 } 
+	lappend restinglist { "#Intrinsic Connectivity Threshold"  threshold 0.0 } 
+	lappend restinglist { "#Intrinsic Connectivity Range"  range "Both" } 
+	lappend restinglist { "#Intrinsic Connectivity Mode"  mode "Sqr" } 
+	lappend restinglist { "#Use VOI Image as mask For Intrinsic Connectivity"  usermask 1 } 
+	lappend restinglist { "#Preprocess (Eliminate Motion Parameters)"  usemotionparams 0 } 
+	lappend restinglist { "#Preprocess (Eliminate CSF/White Matter Mean)"  usecsfmean 0 } 
+	
+
+	for { set i 0 } { $i < [ llength $restinglist ] } { incr i } {
+	set elem [ lindex $restinglist $i ]
+	set name [ lindex $elem 1 ]
+	set val	 [ lindex $elem 2 ]
+	lappend restingnamelist $name
+	set parameters($this,resting_$name) $val
+	}
+
+
+	set glmextralist ""
+	set glmextranamelist ""
+
+	lappend glmextralist { "#Use External Matrix File"   useexternalmatrix 0 }
+	lappend glmextralist { "#External Matrix FileName"   externalmatrixfilename "" }
+	lappend glmextralist { "#Do Convolution with HRF"    doconvolution 1 }
+
+	for { set i 0 } { $i < [ llength $glmextralist ] } { incr i } {
+	    set elem [ lindex $glmextralist $i ]
+	    set name [ lindex $elem 1 ]
+	    set val	 [ lindex $elem 2 ]
+	    lappend glmextranamelist $name
+	    set parameters($this,glmextra_$name) $val
+	}
+
+
+	
+}
+
+itcl::body bis_fmrisetup::AFNICreateScriptHelper { fout line { mirror 0 } } {
+	
+	if { $mirror == 1 } {
+	regsub -all "\t" $line " " line2
+	regsub -all "\n" $line2 " " line2
+	regsub -all " +" $line2 " " line2
+	regsub -all "\\\\" $line2 " " line2
+	
+	puts $fout "echo \"\""
+	puts $fout "echo \"Executing:  $line2\" "
+	puts $fout "echo \"\" "
+	puts $fout "$line"
+	} else {
+	if { $line == "" } {
+		puts $fout "\necho \"\""
+		puts $fout "echo \"\"\n"
+	} else {
+		puts $fout "echo \"$line\""
+	}
+	}
+}
+
+itcl::body bis_fmrisetup::EnsureRunsAreNIFTI { } {
+
+	for { set runcount 1 } { $runcount <= $numruns } { incr runcount } {
+	set rname $parameters($this,run_file_$runcount)
+
+	set hd [ vtkbisImageHeader [ pxvtable::vnewobj ]]
+	$hd ReadHeader $rname
+	if { [ $hd GetMode ] == 0 } {
+		if { [ file writable $rname ] == 1  && [ file extension $rname ] == ".hdr" } {
+		$hd SetModeToNIFTI_HDRIMG
+		$hd WriteHeader $rname 0
+		pxtkprint "Converted headerfile $rname to NIFTI\n"
+		} else {
+		$this InfoMessage  "Failed to convert headerfile $hd to NIFTI, either read-only or not a .hdr file" "Error ..." error
+		}
+		$hd Delete
+	}
+	}
+}
+
+# ---------------------------------------------------------------------------------------------------
+
+itcl::body bis_fmrisetup::CreateWaverMatrix { } {
+
+    set matrix [ $this CreateBaseGLMMatrix  0 ]
+	if { $matrix == 0 } {
+	return 0
+	}
+	set flist ""
+	
+	set breaks  [ vtkIntArray [ pxvtable::vnewobj ]]
+	$breaks SetNumberOfComponents 1
+	$breaks SetNumberOfTuples $numruns
+
+	$breaks SetComponent 0 0 0.0
+	for { set runcount 1 } { $runcount < $numruns } { incr runcount } {
+	    set fr $parameters($this,run_file_${runcount}_length)	
+	    $breaks SetComponent $runcount 0 [ expr $fr + [ $breaks GetComponent [ expr $runcount -1 ] 0 ]]
+	}
+
+	set biswaver [ vtkbisWaver [ pxvtable::vnewobj ]]
+
+	if { $parameters($this,glmextra_useexternalmatrix) == 1 && $parameters($this,glmextra_doconvolution) == 0 } {
+	    $biswaver SetWaveform_type 0
+	} else {
+	    switch -exact $parameters($this,afni_hrfmode) {
+		"wav"  {
+		    $biswaver SetWAV_delay_time  $parameters($this,afni_delaytime) 
+		    $biswaver SetWAV_rise_time $parameters($this,afni_risetime)
+		    $biswaver SetWAV_fall_time $parameters($this,afni_falltime) 
+		    $biswaver SetWAV_undershoot $parameters($this,afni_undershoot)
+		    $biswaver SetWaveform_type 1
+		}
+		"gamma"	       {    $biswaver SetWaveform_type 2 }
+		"doublegamma"  {    $biswaver SetWaveform_type 3 }
+		"triplegamma"  {    $biswaver SetWaveform_type 4 }
+		"spm"	       {    $biswaver SetWaveform_type 5 }
+	    }
+	}
+	pxtkprint "Using Waveform Type [ $biswaver GetWaveform_type]\n"
+	#pxtkconsole
+	$biswaver SetTR	  $parameters($this,tr)
+	$biswaver SetPeak $parameters($this,afni_peak) 
+	
+	
+	set newmatr [ vtkpxMatrix [ pxvtable::vnewobj ]]
+	    
+	    # First the raw stuff
+	$biswaver CreateStackedWaveform $matrix $newmatr $breaks
+	
+	set status "[$biswaver GetStatus ]"
+
+	$biswaver Delete
+	return [ list $newmatr $breaks $matrix $status ]
+}
+
+# --------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::GenerateOutputFilenames { { askfname 0 } } {
+
+	global tcl_platform
+
+	if { $askfname > 0 } {
+	set endsuffix ".msb"
+	set typelist { {"MSB File" { *.msb} }}
+	
+	set tryname [ file join $parameters($this,output_dir)  $parameters($this,subject_id) ]${endsuffix}
+	set fname [tk_getSaveFile -title "Specify Output Filename (and implicitly path)" \
+			   -filetypes $typelist -initialfile [ file tail $tryname ] -initialdir $parameters($this,output_dir) ]
+	if { [ string length $fname ] == 0 } {
+		return 0
+	}
+	set fname  [ file rootname [ file normalize $fname ] ]
+	set parameters($this,output_dir) [ file dirname $fname ]
+	set outnamestem [ file join $parameters($this,output_dir)  "${fname}_bis" ]
+	set msbsetupname  ${fname}.msb
+	} else	{
+	set outnamestem [ file join $parameters($this,output_dir)  "$parameters($this,subject_id)_bis" ]
+	set msbsetupname  ${outnamestem}.msb
+	}
+
+	return [ list $outnamestem $msbsetupname ]
+}
+
+# -------------------------------------------------------------------------------------------------------------
+
+itcl::body bis_fmrisetup::CreateMSBFile { msbsetupname tasklist	  } {
+	
+	set fileid [ open  $msbsetupname w ]
+	puts $fileid "#Multisubject Description File v3"
+	set nt [ llength $tasklist ]
+	puts $fileid "Tasks\n$nt"
+	puts $fileid "- - - - - - - - - - - - - - - - - - - -"
+	for { set i 0 } { $i < $nt } { incr i } {
+	set tmp [ lindex $tasklist $i ]
+	puts $fileid "Task Name	  : [ lindex $tmp 0 ]"
+	puts $fileid "Task Suffix : [ lindex $tmp 1 ]"
+	puts $fileid "-------------------------------------------------------"
+	}
+	puts $fileid "Subjects\n1"
+	puts $fileid "- - - - - - - - - - - - - - - - - - - -"
+	puts $fileid "Subject Id : $parameters($this,subject_id)"
+	puts $fileid "Anatomical Image : $parameters($this,anatomical)"
+	puts $fileid "Conventional Image : $parameters($this,conventional)"
+	puts $fileid "Functional Image :   [ lindex [ lindex $tasklist 0 ] 2]"
+	puts $fileid "Reference Transformation : $parameters($this,referenceTransform)"
+	puts $fileid "Internal Transformation : $parameters($this,internalTransform)" 
+	puts $fileid "Echoplanar Image :  "
+	puts $fileid "Distortion Transformation :  $parameters($this,distortionTransform)"
+	puts $fileid "Fieldmap Image : "
+	puts $fileid "-------------------------------------------------------"
+	
+	puts $fileid "Reference/Output Images"
+	puts $fileid "--------------------------------------"
+	
+	puts $fileid "Reference Image : $parameters($this,reference_brain_path)"
+	puts $fileid "VOI Image : "
+
+	set olist [ list "Average Anatomical" "Std Anatomical" "Average Functional" "Std Functional" "Tscore Functional" ]
+	for { set i 0 } { $i < [ llength $olist ] } { incr i } {
+	puts $fileid "[ lindex $olist $i ] : "
+	}
+	puts $fileid "Legacy : "
+	puts $fileid "Legacy : "
+	puts $fileid "Legacy : "
+	close $fileid
+
+	set ok [     $this CreateDataTreeStructure $tasklist ]
+	if { $ok > 0 } {
+	set xmlname "[ file rootname $msbsetupname].xmltree"
+	    $datamanager SaveXML $xmlname
+	    set datamanagerfilename $xmlname
+	}
+}
+
+# --------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::DisplayMSBFile { msbsetupname } { 
+
+	return
+
+	# this is obsolete, we now have the tree!
+	if { $multisubjectcontrol !=0 } {
+	$multisubjectcontrol ShowWindow Results " "
+	update idletasks
+	$multisubjectcontrol LoadSetup $msbsetupname
+	$multisubjectcontrol LoadAll 1
+	} 
+}
+# --------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::PreprocessGLM { outnamestem { dodrift 1 } { numrate 0 } { singlerun 0 } } {
+
+    
+    puts stdout "Preprocess GLM singlerun=$singlerun outnamestem=$outnamestem"
+
+    if { $parameters($this,afni_ensurenifti) == 1 } {
+	$this EnsureRunsAreNIFTI
+    }
+    
+    puts stdout "Creating Waver Matrix ................."
+    set lst [ $this CreateWaverMatrix ]
+    if { $lst == 0 } {
+	return 0
+    }
+    set newmatrix  [ lindex $lst 0 ]
+    set breaks     [ lindex $lst 1 ]
+    set rawmatrix	  [ lindex $lst 2 ]
+    
+    puts stdout "done\n"
+
+    if { $singlerun !=0 } {
+	set matname ${outnamestem}_raw.matr
+	$rawmatrix Save $matname
+	lappend flist $matname
+    }
+    
+    set glmmatr [ vtkpxMatrix [ pxvtable::vnewobj ]]
+    set biswaver [ vtkbisWaver [ pxvtable::vnewobj ]]
+    set minrun 1
+    set maxrun $numruns
+
+    if { $singlerun > 0 && $singlerun <= $numruns } {
+	puts stdout "In Single Run Mode ($singlerun) .... copying matrix\n"
+	set minrun $singlerun
+	set maxrun $singlerun
+
+	# Also trim matrix at this point
+	set sz [ $newmatrix GetSize ]
+	set minrow [ $breaks GetComponent [ expr $singlerun -1 ] 0 ]
+
+	if { $singlerun < $numruns } {
+	    set maxrow [ expr [ $breaks GetComponent $singlerun 0 ] -1 ]
+	} else {
+	    set maxrow [ expr [ lindex $sz 0 ] -1 ]
+	}
+	set minrow [ expr int($minrow) ]
+	set maxrow [ expr int($maxrow) ]
+	
+
+	set tmp [ vtkpxMatrix New ]
+	puts stdout "Extracting Global Matrix rows  $minrow $maxrow -- for run $singlerun"
+	$tmp Copy $newmatrix $minrow $maxrow -1 -1
+	$newmatrix Delete
+	set newmatrix $tmp
+
+	set  ln ""
+	for { set i 0 } { $i < [ $breaks GetNumberOfTuples ] } { incr i } {
+	    append ln " [ $breaks GetComponent $i 0 ]"
+	}
+	#puts stdout "Output Size = [ $newmatrix GetSize ] orig=$sz (breaks=$ln)"
+
+
+	$breaks SetNumberOfTuples 1
+	$breaks SetComponent 0 0 0.0
+    } else {
+	puts "Using All Runs\n"
+    }
+
+
+    if {  $parameters($this,afni_deletetemp) == 0 } {
+	set matname ${outnamestem}_afni.matr
+	$newmatrix Save $matname
+	lappend flist $matname
+    }
+    
+
+    set ord $parameters($this,afni_polort) 
+    puts stdout "Preprocessing GLM, dolocaldrift=($dodrift), numrate=$numrate, runs=$minrun:$maxrun, inmatrix [ $newmatrix GetSize ]" 
+
+    if { $numrate == 0 } {
+	$biswaver AddDriftTerms $newmatrix $glmmatr $breaks $ord
+    } else {
+	$biswaver AddDriftAndRateTerms $newmatrix $glmmatr $breaks $ord $numrate
+    }
+    
+    set motnamelst ""
+    set usemotion $parameters($this,afni_glmregressmotion)
+    set badmotion 0
+    set totalrows 0
+    
+    if { $usemotion > 0 } { 
+	for { set runcount $minrun } { $runcount <= $maxrun } { incr runcount } {
+	    set motionmat($runcount) [ vtkpxMatrix New ]
+	    $motionmat($runcount) ImportFromMatlab $parameters($this,run_motionfile_$runcount) "Q_ser"
+	    set m [ $motionmat($runcount) GetSize ]
+	    if { [ lindex $m 1 ] == 6 } {
+		set motionlen($runcount) [ lindex $m 0 ]
+		set totalrows [ expr $totalrows + [ lindex $m 0 ] ]
+	    } else {
+		puts stderr "Bad Motion file $parameters($this,run_motionfile_$runcount) size = $m "
+		set badmotion 0
+	    }
+	}
+
+	set newglm [ vtkpxMatrix New ]
+	set oldsz [ $glmmatr GetSize ]
+	if {  [ lindex $oldsz 0 ] != $totalrows } {
+	    puts stderr "overall motion size"
+	    set badmotion 1
+	}
+	
+	if { $badmotion == 1 } {
+	    $newmatrix Delete
+	    $breaks Delete
+	    $rawmatrix Delete
+	    $glmmatr Delete
+	    $biswaver Delete
+	}
+	
+	puts stdout "\n\n Old GLM Matrix without Motion  ([$glmmatr GetSize])"
+	set newglm [ vtkpxMatrix New ]
+	$newglm Zeros $totalrows [ expr [ lindex $oldsz 1 ] + 6 ]
+	$newglm CopyInto $glmmatr -1 -1 -1 -1 0 6
+	set row 0
+	for { set runcount $minrun } { $runcount <= $maxrun } { incr runcount } {
+	    $motionmat($runcount) Save "run_${runcount}.mat"
+	    $newglm CopyInto $motionmat($runcount) -1 -1 -1 -1 $row  0
+	    set row [ expr $row + $motionlen($runcount) ]
+	}
+	set matname ${outnamestem}_glm_beforemotion.matr
+	$glmmatr Save $matname
+	lappend flist $matname
+	$glmmatr Delete
+	set glmmatr $newglm
+
+
+	puts stdout "\n\n GLM Matrix with Motion addons file saved in $matname ([$newglm GetSize])"
+    }
+
+    set catname ${outnamestem}_allruns.nii.gz
+    
+    
+
+    set matname ${outnamestem}_glm.matr
+    $glmmatr Save $matname
+    lappend flist $matname
+    puts stdout "\n\n GLM Matrix file saved in $matname"
+
+    
+    pxtkprint "\n\n Computing GLM\n\n"
+    pxtkprint "Generated GLM Matrix (see $matname) if delete temp is 0\n"
+
+    set appnd [ vtkpxAppendComponents [ pxvtable::vnewobj ]]
+
+    
+    for { set runcount $minrun } { $runcount <= $maxrun } { incr runcount } {
+	set runimage($runcount)	 [  [ pxitclimage \#auto ] GetThisPointer ]
+	set fn	$parameters($this,run_file_$runcount)
+	$runimage($runcount) Load $fn
+	
+
+	set norm [ vtkbisTimeSeriesNormalize New ]	    
+	if { $dodrift == 1 } {
+	    pxtkprint "\t\t .................... Normalizing Run $runcount ($fn) (masklevel = [ expr $parameters($this,afni_masklevel) *100.0 ]%) \n"
+	    $norm SetInput [ $runimage($runcount) GetImage ]
+	} else {
+	    pxtkprint "\t\t .................... Normalizing and doing Global Drift correction on Run $runcount ($fn) (masklevel = [ expr $parameters($this,afni_masklevel) *100.0 ]%), drift pol=$parameters($this,afni_polort) \n"
+	    set drift [ vtkbisRemoveGlobalTemporalDrift New ]
+	    $drift SetOutputNormalized 0
+	    $drift SetOrder $parameters($this,afni_polort)
+	    $drift SetUseLegendrePolynomials 1
+	    $drift SetInput [ $runimage($runcount) GetImage ]
+	    $drift SetThreshold 0.5
+	    $drift SetNormalizedThreshold 1
+	    $drift Update
+	    $norm SetInput [ $drift GetOutput ]
+	    $drift Delete
+	}
+
+	$norm SetThreshold $parameters($this,afni_masklevel)
+	$norm SetNormalizedThreshold 1
+	$norm Update
+	
+	$appnd AddInput [ $norm GetOutput ]
+	$norm Delete
+	if { $runcount > $minrun } {
+	    itcl::delete obj $runimage($runcount) 
+	}
+    }
+    
+    pxtkprint "\t\t .................... Concatenating Runs\n"
+    
+    $appnd Update
+    
+    
+    $runimage($minrun) ShallowCopyImage [ $appnd GetOutput ]
+    pxtkprint "\t\t .................... Concatenating Runs Done\n"
+    if {  $parameters($this,afni_deletetemp) == 0 } {
+	pxtkprint "\t\t .................... Beginning to Save Concatenated Runs\n"
+	$runimage($minrun) Save $catname
+	puts stdout "\n\n Concatenated Run image saved in $catname [ file size $catname ]" 
+	pxtkprint "........... Concatenated Run image saved in $catname [ file size $catname ]" 
+    }
+    pxtkprint "Generated Concatenated Normalized Run Stack Image\n.....................[ $runimage($minrun) GetShortDescription ]\n"
+    $appnd Delete
+    $biswaver  Delete
+    $breaks	   Delete
+    $newmatrix Delete
+    $rawmatrix    Delete
+
+    puts stdout "\t\t\t image = [ [ $runimage($minrun) GetImage ] GetNumberOfScalarComponents ] matrix= [ $glmmatr GetSize]"
+
+    return [ list $runimage($minrun) $glmmatr ]
+}
+# --------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::ComputeGLMComponent { outnamestem { singlerun 0 } { tasklist "" } { dodrift 1 } { numrate 0 } } {
+
+    if { $singlerun > 0 && $singlerun <= $numruns } {
+	set outnamestem "${outnamestem}_run${singlerun}"
+	set extraname ""
+    } else {
+	set singlerun 0
+	set extraname ""
+    }
+
+    set outlst [ $this PreprocessGLM $outnamestem $dodrift $numrate $singlerun ]
+    if { $outlst == 0 } {
+	return 0
+    }
+    
+
+    set allrunsimage [ lindex $outlst 0 ]
+    set glmmatr  [ lindex $outlst 1 ]
+
+    puts stdout "In Compute GLM Component (single=$singlerun) extra=$extraname (Frames = [ [ $allrunsimage GetImage ] GetNumberOfScalarComponents ] ) mat size = [ $glmmatr GetSize ], numtasks=$numtasks"
+
+    set glm [ vtkbisComputeGLM  [ pxvtable::vnewobj ]]
+    $glm SetRegressorMatrix $glmmatr
+    $glm SetInput [ $allrunsimage GetImage ]
+    $glm SetNumberOfTasks $numtasks
+    $glm Update
+
+    puts stdout "\t\t\t\ Done with vtkbisComputeGLM"
+
+    
+    set outimage  ""; lappend outimage [ $glm GetOutput ]
+    set outsuffix ""; lappend outsuffix "beta"
+    set outzero   ""; lappend outzero   "fstat"
+    if { $parameters($this,afni_tout) > 0 } {
+	lappend outimage [ $glm GetTmapImage ]
+	lappend outsuffix "tmap"
+	lappend outzero   "mse"
+    }
+    
+    # Here is the big job -- create a single subject .msb file for this guy and be done
+    
+    set w [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+    set extr [ vtkImageExtractComponents [ pxvtable::vnewobj ]]
+    set setuptasklist $tasklist
+    
+    for { set i 0 } { $i <= $numtasks } { incr i } {
+	for { set pass 0 } { $pass < [ llength $outzero ] } { incr pass } {
+	    
+	    puts stdout "outimage = $outimage , i=$i, item =$pass, numcomp [ [ lindex $outimage $pass ] GetNumberOfScalarComponents ]"
+	    $extr SetInput [ lindex $outimage $pass ]
+	    
+	    set sf [lindex $outsuffix $pass ]
+	    
+	    if { $i > 0 } {
+		set tname $parameters($this,task_$i)
+		set tname "${tname}${extraname}_${sf}"
+	    } else {
+		set tname "[ lindex $outzero $pass ]${extraname}"
+	    }
+	    $extr SetComponents $i
+	    $extr Modified
+	    $extr Update
+	    
+	    $w SetInput [ $extr GetOutput ]
+	    $w SetImageHeader [ $allrunsimage GetImageHeader ]
+	    $w Modified
+	    
+	    set fname ${outnamestem}_$tname.nii.gz	
+	    lappend setuptasklist [ list $tname $tname $fname ] 
+	    
+	    $w Save $fname
+	    pxtkprint  "Map for  $tname saved in $fname [ file size $fname ] (Component $i, pass=$pass)\n"
+	}
+    }
+    
+    # Add overall term
+    
+    if { $parameters($this,afni_saveresidual) > 0 } {
+	set tname "residualtimeseries${extraname}"
+	$w SetInput [ $glm GetUnfitTimeSeries ]
+	$w SetImageHeader [ $allrunsimage GetImageHeader ]
+	$w Modified
+	
+	set fname ${outnamestem}_$tname.nii.gz	
+	lappend setuptasklist [ list $tname $tname $fname ] 
+	$w Save $fname
+    }
+    
+    if { $parameters($this,afni_savedriftbeta) > 0 } {
+	
+	set tname "driftbetas${extraname}"
+	$w SetInput [ $glm GetDriftBetaValues ]
+	$w SetImageHeader [ $allrunsimage GetImageHeader ]
+	$w Modified
+	
+	set fname ${outnamestem}_$tname.nii.gz	
+	lappend setuptasklist [ list $tname $tname $fname ] 
+	$w Save $fname
+    }
+    
+    pxtkprint "Done Saving .. clean up time\n"
+    puts stdout "\t\t\t\ Done saving\n"
+    
+    $w Delete
+    $extr Delete
+    $glm Delete
+    itcl::delete obj $allrunsimage 
+    $glmmatr   Delete 
+    
+    return $setuptasklist
+}
+# ----------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::ComputeGLM { { askfname 0 } { report 0 } } {
+
+    set ln [ $this GenerateOutputFilenames $askfname ]
+    if { $ln == 0 } {
+	return 0
+    }
+    
+    set outnamestem [ lindex $ln 0 ]
+    set msbsetupname [ lindex $ln 1 ]
+    catch { file mkdir $parameters($this,output_dir) }
+
+    pxtkprint "Beginning Stem =$outnamestem\n\t Setup=$msbsetupname\n"
+    
+    set setuptasklist [ $this ComputeGLMComponent $outnamestem 0 ]
+    if { $parameters($this,afni_glmsinglerunoutput) > 0 } {
+	for { set i 1 } { $i <= $numruns } { incr i } {
+	    puts stdout "\n\n--------------------------------------------------------------\n Single Component Processing for Run = $i"
+	    set tmp $setuptasklist 
+	    set setuptasklist [ $this ComputeGLMComponent $outnamestem $i $tmp ]
+	}
+    }
+    
+    $this CreateMSBFile $msbsetupname $setuptasklist
+    $this InfoMessage  "Done GLM -- see single subject file in $msbsetupname" "FYI"
+    $this DisplayMSBFile $msbsetupname
+    
+    return $outnamestem
+}
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_fmrisetup::ComputeRateGLM { { askfname 0 } { report 0 } } {
+
+    set ln [ $this GenerateOutputFilenames $askfname ]
+    if { $ln == 0 } {
+	return 0
+    }
+    
+    set numrate $parameters($this,afni_numrateterms)
+    if { $numrate > 3 } {
+	set numrate 3
+    }
+
+    set doglobal $parameters($this,afni_rateglobal)
+    set dolocaldrift [ expr $doglobal <1 ]
+
+    set outnamestem [ lindex $ln 0 ]
+    set msbsetupname [ lindex $ln 1 ]
+    catch { file mkdir $parameters($this,output_dir) }
+
+    #    pxtkconsole
+    pxtkprint "Beginning Stem =$outnamestem\n\t Setup=$msbsetupname\n"
+    set outlst [ $this PreprocessGLM $outnamestem $dolocaldrift $numrate ]
+    if { $outlst == 0 } {
+	return 0
+    }
+    
+    set allrunsimage [ lindex $outlst 0 ]
+
+    set glmmatr  [ lindex $outlst 1 ]
+
+
+    set glm [ vtkbisComputeGLM  [ pxvtable::vnewobj ]]
+    $glm SetRegressorMatrix $glmmatr
+    $glm SetInput [ $allrunsimage GetImage ]
+    $glm SetNumberOfTasks [ expr $numtasks* ($numrate+1) ]
+    $glm Update
+
+    puts stdout "GLM Matrix size  [ $glmmatr GetSize ], numtasks=$numtasks, numframes out= [ [ $glm GetOutput ] GetNumberOfScalarComponents ]"
+    
+    set outimage  ""; lappend outimage [ $glm GetOutput ]
+    set outsuffix ""; lappend outsuffix "beta"
+    set outzero   ""; lappend outzero   "fstat"
+    if { $parameters($this,afni_tout) > 0 } {
+	puts stdout " TMap numframes, [ [ $glm GetTmapImage ] GetNumberOfScalarComponents ]"
+	lappend outimage [ $glm GetTmapImage ]
+	lappend outsuffix "tmap"
+	lappend outzero   "mse"
+    }
+    
+    puts stdout "GLM Output = [ $glm GetOutput ], numframes = [ [ $glm GetOutput ] GetNumberOfScalarComponents ]"
+    puts stdout "TMAP Output = [ $glm GetTmapImage ], numframes = [ [ $glm GetTmapImage ] GetNumberOfScalarComponents ]"
+
+    #    set ratepass [ llength $numrate ]
+
+
+    #    for { set i 0 } { $i < $numrate } { incr i } {
+    #	lappend outimage [ $glm GetOutput ]
+    #	lappend outsuffix "beta_rate_[ lindex $ratenames $i ]"
+    #	lappend outzero   "*none*"
+    #    }
+    set maxpass [ llength $outzero ] 
+    
+    # Here is the big job -- create a single subject .msb file for this guy and be done
+    
+    set w [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+    set extr [ vtkImageExtractComponents [ pxvtable::vnewobj ]]
+    set setuptasklist ""	
+    
+    set outframes [ [ $glm GetOutput ] GetNumberOfScalarComponents ]
+    set ratenames [ list "" "_linear" "_quadratic" "_cubic" ]
+
+    for { set i 0 } { $i < $outframes } { incr i } {
+	for { set pass 0 } { $pass < $maxpass } { incr pass } {
+	    
+	    $extr SetInput [ lindex $outimage $pass ]
+	    
+	    set sf [lindex $outsuffix $pass ]
+	    set fr $i
+	    
+	    if { $i > 0 } {
+		set j [ expr int($i-1)/int($numtasks) ]
+		set k [ expr $i - $j * $numtasks ]
+		puts stdout "\t\t i=$i, numtasks=$numtasks j=$j k=$k"
+		set tname $parameters($this,task_$k)
+		set tname "${tname}_${sf}[ lindex $ratenames $j ]"
+	    } else {
+		set tname [ lindex $outzero $pass ]
+	    }
+
+	    $extr SetComponents $fr
+	    $extr Modified
+	    $extr Update
+	    
+	    $w SetInput [ $extr GetOutput ]
+	    $w SetImageHeader [ $allrunsimage GetImageHeader ]
+	    $w Modified
+	    
+	    set fname ${outnamestem}_$tname.nii.gz	
+	    lappend setuptasklist [ list $tname $tname $fname ] 
+	    
+	    puts stdout "outimage = [ lindex $outimage $pass ] , i=$i, pass =$pass \t numcomp=[ [ lindex $outimage $pass ] GetNumberOfScalarComponents ], using frame=$fr, fname=[ file tail $fname ]"
+	    
+		$w Save $fname
+	    pxtkprint  "Map for  $tname saved in $fname [ file size $fname ] (Component $i, pass=$pass)\n"
+	}
+    }
+    
+    # Add overall term
+    
+    if { $parameters($this,afni_saveresidual) > 0 } {
+	set tname "residualtimeseries"
+	$w SetInput [ $glm GetUnfitTimeSeries ]
+	$w SetImageHeader [ $allrunsimage GetImageHeader ]
+	$w Modified
+	
+	set fname ${outnamestem}_$tname.nii.gz	
+	lappend setuptasklist [ list $tname $tname $fname ] 
+	$w Save $fname
+    }
+    
+    if { $parameters($this,afni_savedriftbeta) > 0 } {
+	
+	set tname "driftbetas"
+	$w SetInput [ $glm GetDriftBetaValues ]
+	$w SetImageHeader [ $allrunsimage GetImageHeader ]
+	$w Modified
+	
+	set fname ${outnamestem}_$tname.nii.gz	
+	lappend setuptasklist [ list $tname $tname $fname ] 
+	$w Save $fname
+    }
+    
+    pxtkprint "Done Saving .. clean up time\n"
+    
+    $this CreateMSBFile $msbsetupname $setuptasklist
+    
+    $w Delete
+    $extr Delete
+    $glm Delete
+    itcl::delete obj $allrunsimage 
+    $glmmatr   Delete 
+    
+    $this InfoMessage  "Done GLM -- see single subject file in $msbsetupname" "FYI"
+    $this DisplayMSBFile $msbsetupname
+    
+    
+    return $outnamestem
+}
+
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_fmrisetup::AFNICreateScript { { askfname 0 } { report 0 } } {
+
+	set tempfiles ""
+
+	if { $parameters($this,afni_ensurenifti) == 1 } {
+	$this EnsureRunsAreNIFTI
+	}
+
+	catch { file mkdir $parameters($this,output_dir) }
+
+	global tcl_platform
+	set endsuffix ".sh"
+
+
+	if { $askfname } {
+	set typelist { {"AFNI Script File" { *.sh }}}
+	set tryname [ file join $parameters($this,output_dir)  $parameters($this,subject_id) ]${endsuffix}
+	set fname [tk_getSaveFile -title "Specify Script Filename (and implicitly path)" \
+			   -filetypes $typelist -initialfile [ file tail $tryname ] -initialdir $parameters($this,output_dir) ]
+	if { [ string length $fname ] == 0 } {
+		return 0
+	}
+	set fname  [ file rootname [ file normalize $fname ] ]
+	set parameters($this,output_dir) [ file dirname $fname ]
+	set outnamestem [ file join $parameters($this,output_dir)  $fname ]
+	} else	{
+	set outnamestem [ file join $parameters($this,output_dir)  $parameters($this,subject_id) ]
+	}
+
+	set tr $parameters($this,tr)
+	set outscript ${outnamestem}${endsuffix}
+
+	set stimlist ""
+
+
+	set lbreak "\\\n\t"    
+
+	set timefiles  ${outnamestem}_timepoints
+	if { $parameters($this,afni_useafniwaver) == 1 } {
+
+	set comment "\# Using AFNI Waver"
+
+	set waverout [ AFNICreateTimeFile $timefiles ]
+	if { $waverout == 0 } {
+		return 0
+	}
+	set inpname [ lindex $waverout 0  ]
+	set startpointsfile [ lindex $waverout 1 ]
+	if { [ file exists $startpointsfile ] == 0 } {
+	    $this InfoMessage  "Waver input file $inpname does not exist!" "Error ..." error
+	    return 0
+	}
+
+	#    puts stdout "inpname = $inpname, startpointsfile=$startpointsfile"
+	for {set runcount 1} {$runcount <= $numruns} {incr runcount} {
+		set runfile($runcount) ${inpname}_${runcount}.txt
+		lappend tempfiles $runfile($runcount)
+	}
+	} else {
+	# Do this simply in BioImage Suite !!!!
+	pxtkprint "\n\n NOT Using AFNI Waver\n"
+	puts stdout "\n\n NOT Using AFNI Waver\n"
+	set lst [ $this CreateWaverMatrix ]
+	if { $lst == 0 } {
+		return 0 
+	}
+	set newmatrix  [ lindex $lst 0 ]
+	set breaks     [ lindex $lst 1 ]
+	set rawmat     [ lindex $lst 2 ] ; $rawmat Delete
+	set comment    "Using vtkbisWaver [ lindex $lst 3 ]"
+	set numrows    [ lindex [ $newmatrix GetSize ] 0 ]
+
+
+	for {set taskcount 1} {$taskcount<= $numtasks} {incr taskcount} {
+		set tname $parameters($this,task_$taskcount)
+		set outname ${outnamestem}_task${tname}
+		set col [ expr $taskcount -1 ]
+
+		set bfout [ open $outname w ]
+		for { set row 0 } { $row < $numrows } { incr row } {
+		puts $bfout "[$newmatrix GetElement $row $col ]"
+		}
+		close $bfout
+		lappend stimlist [ list $tname $outname ]    
+	}
+	set startpointsfile "${outnamestem}_startpoints.txt"
+	set inpname "${outnamestem}_matrix.txt"
+	$newmatrix Save $inpname
+	
+	set nt [ $breaks GetNumberOfTuples ]
+	set bfout [ open $startpointsfile w ]
+	for { set i 0 } { $i < $nt } { incr i } {
+		puts $bfout "[ $breaks GetComponent $i 0 ]"
+	}
+	close $bfout
+	$breaks Delete
+	$newmatrix Delete
+	}
+	lappend tempfiles $startpointsfile 
+
+	set fout [ open $outscript w ]
+	AFNICreateScriptHelper $fout "\#---------------------------------------------------------------"
+	AFNICreateScriptHelper $fout "\# AFNI Analysis Script created from BioImage Suite"
+	AFNICreateScriptHelper $fout "\# Original time point files are in:"
+	AFNICreateScriptHelper $fout "\#\t $inpname"
+	AFNICreateScriptHelper $fout "\# and \t $startpointsfile"
+	AFNICreateScriptHelper $fout "\# $comment"
+	AFNICreateScriptHelper $fout "\#---------------------------------------------------------------"
+	AFNICreateScriptHelper $fout "\# Using $numruns runs"
+	#for { set runcount 1 } { $runcount <= $numruns } { incr runcount } {
+	#	set rname $parameters($this,run_file_$runcount)
+	#	AFNICreateScriptHelper $fout "\# Run $runcount : [ file tail $rname ], numframes = $parameters($this,run_file_${runcount}_length)"
+	#    }
+	AFNICreateScriptHelper $fout "\#---------------------------------------------------------------"
+	AFNICreateScriptHelper $fout ""
+
+	if { $parameters($this,afni_useafniwaver) == 1 } {
+	
+	for {set runcount 1} {$runcount <= $numruns} {incr runcount} {
+		set runfile($runcount) ${inpname}_${runcount}.txt
+		lappend tempfiles $runfile($runcount)
+
+		# Step 1 Waver
+		AFNICreateScriptHelper $fout "# Step 1 Waver"
+		AFNICreateScriptHelper $fout ""
+		for {set taskcount 1} {$taskcount<= $numtasks} {incr taskcount} {
+		set tname $parameters($this,task_$taskcount)
+		set i [ expr $taskcount -1 ]
+		set tlist ""
+		
+		AFNICreateScriptHelper $fout "\# +++++ Task $taskcount/$numtasks ($tname) "
+		for {set runcount 1} {$runcount <= $numruns} {incr runcount} {
+			
+			set numf $parameters($this,run_file_${runcount}_length)	  
+			
+			set iname "$runfile($runcount)\[$i\]"
+			set outname ${outnamestem}_task${tname}_run${runcount}
+			set cmd "waver	-delaytime $parameters($this,afni_delaytime) -risetime $parameters($this,afni_risetime) -falltime $parameters($this,afni_falltime) -undershoot $parameters($this,afni_undershoot) -TR $tr -peak $parameters($this,afni_peak) $lbreak -input \'${iname}\' $lbreak | head -$numf > $outname"
+			AFNICreateScriptHelper $fout $cmd 1
+			lappend tempfiles $outname
+			lappend tlist $outname
+		}
+	
+		set outname ${outnamestem}_task${tname}
+		set cmd "cat "
+		for { set i 0 } { $i < [ llength $tlist ] } { incr i } {
+			set cmd "$cmd [ lindex $tlist $i ] $lbreak"
+		}
+		set cmd "$cmd > $outname"
+		AFNICreateScriptHelper $fout $cmd 1
+		lappend stimlist [ list $tname $outname ]
+		lappend tempfiles $outname
+		AFNICreateScriptHelper $fout ""
+		}
+	}
+	} else {
+
+	AFNICreateScriptHelper $fout "\# Stim Files Created using vtkbisWaver"
+	for { set i 0 } { $i < [ llength $stimlist ] } { incr i } {
+		AFNICreateScriptHelper $fout "\# [ lindex $stimlist $i ]"
+	}
+	}
+
+	if { $parameters($this,afni_useafninormalize) == 1 } {
+
+	AFNICreateScriptHelper $fout ""
+	AFNICreateScriptHelper $fout "# Step 2: Normalize and Mask"
+	AFNICreateScriptHelper $fout ""
+	
+	set allruns ""
+	
+	for { set runcount 1 } { $runcount <= $numruns } { incr runcount } {
+		AFNICreateScriptHelper $fout "\# +++++ Run $runcount/$numruns "
+		set fn	$parameters($this,run_file_$runcount)
+		set tt [ file rootname [ file tail $fn ] ]
+		if { [ file extension $tt ] == ".nii" } {
+		set tt [ file rootname $tt ]
+		}
+		set tt ${outnamestem}_${tt}
+		
+		set meanname ${tt}_mean.nii.gz
+		set normname ${tt}_norm.nii.gz 
+		
+		set cmd "3dTstat -mean -prefix $meanname $lbreak $fn\n"
+		AFNICreateScriptHelper $fout $cmd 1
+		lappend tempfiles $meanname
+		set cmd "3dcalc -fscale -a $fn $lbreak -b $meanname $lbreak -expr \' (a/b * 100) \' -prefix $normname"
+		AFNICreateScriptHelper $fout $cmd 1
+		
+		lappend tempfiles $normname
+		lappend allruns $normname
+		puts $fout "\n\n"
+	}
+	
+	set catname ${outnamestem}_allruns.nii.gz
+	AFNICreateScriptHelper $fout ""
+	AFNICreateScriptHelper $fout "# Step 3: Concatenate"
+	AFNICreateScriptHelper $fout ""
+	set cmd "3dTcat -prefix $catname" 
+	set n [ expr [ llength $allruns ] -1 ]
+	for { set i 0 } { $i < [ llength $allruns ] } { incr i } {
+		set cmd	 "$cmd $lbreak [ lindex $allruns $i ]"
+	}
+	AFNICreateScriptHelper $fout $cmd 1
+	lappend tempfiles $catname
+	
+	AFNICreateScriptHelper $fout ""
+	
+	set cmd "3dinfo $catname"
+	AFNICreateScriptHelper $fout $cmd 1
+	} else {
+	set catname ${outnamestem}_allruns.nii.gz
+
+
+	set appnd [ vtkpxAppendComponents [ pxvtable::vnewobj ]]
+#	$appnd DebugOn
+
+	for { set runcount 1 } { $runcount <= $numruns } { incr runcount } {
+		set runimage($runcount)	 [  [ pxitclimage \#auto ] GetThisPointer ]
+		set fn	$parameters($this,run_file_$runcount)
+		$runimage($runcount) Load $fn
+
+		set norm [ vtkbisTimeSeriesNormalize [ pxvtable::vnewobj ]]
+		$norm DebugOn
+		$norm SetInput [ $runimage($runcount) GetImage ]
+		set mname "${outnamestem}_mean_${runcount}.nii.gz"
+		#	    $norm SetDebugName	$mname
+		#	    lappend tempfiles $mname
+		$norm Update
+		
+		
+		$appnd AddInput [ $norm GetOutput ]
+		$norm Delete
+		if { $runcount > 1 } {
+		itcl::delete obj $runimage($runcount) 
+		}
+	}
+	$appnd Update
+	$runimage(1) ShallowCopyImage [ $appnd GetOutput ]
+	$runimage(1) Save $catname
+	$appnd Delete
+	itcl::delete obj $runimage(1) 
+	}
+
+	if { $parameters($this,afni_polort) < 1 } {
+	set parameters($this,afni_polort) 1
+	} elseif { $parameters($this,afni_polort) > 4 } {
+	set parameters($this,afni_polort) 4
+	}
+
+	set decname ${outnamestem}_deconvolve_stats.nii.gz
+
+	AFNICreateScriptHelper $fout ""
+	AFNICreateScriptHelper $fout "\# Step 4: Run GLM"
+	AFNICreateScriptHelper $fout ""
+	set cmd "3dDeconvolve -input $catname $lbreak -polort $parameters($this,afni_polort) -concat $startpointsfile -num_stimts [ llength $stimlist ] $lbreak"
+	for { set i 0 } { $i < [ llength $stimlist ] } { incr i } {
+	set elem [ lindex $stimlist $i ]
+	set fn	 [ lindex $elem 1 ]
+	set tn	 [ lindex $elem 0 ]
+	set j [ expr $i + 1 ]
+	set cmd "$cmd -stim_file $j $fn -stim_label $j $tn $lbreak"
+	}
+
+	if { $parameters($this,afni_fout) > 0 } {	set cmd "$cmd -fout"	} 
+	if { $parameters($this,afni_rout) > 0 } {	set cmd "$cmd -rout"	} 
+	if { $parameters($this,afni_tout) > 0 } {	set cmd "$cmd -tout"	} 
+	if { $parameters($this,afni_vout) > 0 } {	set cmd "$cmd -vout"	} 
+	if { $parameters($this,afni_bout) > 0 } {	set cmd "$cmd -bout"	} 
+
+	set parameters($this,afni_bucket) 1
+
+	if { $parameters($this,afni_bucket) > 0 } {	
+	set cmd "$cmd -bucket $decname"	  
+	}  else {
+	set cmd "$cmd -nobucket"
+	}
+
+
+	AFNICreateScriptHelper $fout $cmd 1
+
+	AFNICreateScriptHelper $fout ""
+ 
+	if { $parameters($this,afni_bucket) > 0 } {	
+	set cmd "3dinfo $decname"
+		AFNICreateScriptHelper $fout $cmd 1
+	}
+
+
+	if { $endsuffix == ".sh" } {
+	exec chmod +x $outscript
+	}
+
+	set cleanfile ""
+	puts $fout "\#---------------------------------------------------------------\n\n"
+	
+	set comment "\#\t\t" 
+	if {  $parameters($this,afni_deletetemp) == 0 } {
+	set comment ""
+	close $fout
+	set cleanfile [ file rootname $outscript ]_clean${endsuffix}
+	set fout [ open $cleanfile w ]
+	}
+	
+	set comment "$comment \\rm"
+
+	puts $fout "\n\# Optional Cleanup"
+	for { set i 0 } { $i < [ llength $tempfiles ] } { incr i } {
+	puts $fout "$comment [ lindex $tempfiles $i ]"
+	}
+	close $fout
+
+	if { $cleanfile != "" } {
+	exec chmod +x $cleanfile
+	set cleanfile "(and also $cleanfile)"
+	}
+	
+
+	if { $report == 1 } {
+	$this InfoMessage  "Saved afni script file in\n $outscript $cleanfile" "FYI"  info
+	}
+	puts stdout "\n\nOutput Script for AFNI saved in $outscript $cleanfile"
+
+	return $outnamestem
+}
+
+
+# ----------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::ReorganizeData { dirname } {
+
+	catch { file mkdir $dirname }
+	if { [ file writable $dirname ] == 0 } {
+	tk_messageBox -type ok -title "Error ..." -message "Bad Output Directory $dirname"
+	return 0
+	}
+
+
+
+	# --------------------------------------------------------------------------------------
+
+	set imglist [ list reference_brain anatomical conventional voiDefinitionImage reference_gw_map ]
+	set trnlist [ list referenceTransform internalTransform distortionTransform inverseReferenceTransform ]
+
+	for { set i 0 } { $i < [ llength $imglist ] } { incr i } {
+	set img	 [  [ pxitclimage \#auto ] GetThisPointer ]
+	set pname [ lindex $imglist $i ]
+	set fn	$parameters($this,$pname) 
+	if { [ string length $fn ] > 0 } {
+		set ok [ $img Load $fn ]
+	} else {
+		set ok 1
+	}
+	if { $ok > 0 && [ string length $fn ] > 0 } {
+		set fn2 [ file tail $fn ]
+		set fn3 [ file join $dirname $fn2 ]
+		$img Save $fn3
+		set parameters($this,$pname) $fn3
+
+		puts stdout "$fn2 -> $fn3"
+
+	} else {
+		set parameters($this,$pname) ""
+	}
+	itcl::delete obj $img
+	}
+
+	set parameters($this,reference_brain_path) $parameters($this,reference_brain) 
+
+	for { set i 0 } { $i < [ llength $trnlist ] } { incr i } {
+	set trn	 [  [ pxitcltransform \#auto ] GetThisPointer ]
+	set pname [ lindex $trnlist $i ]
+	set fn	$parameters($this,$pname) 
+	if { [ string length $fn ] > 0 } {
+		set ok [ $trn Load $fn ] 
+	} else {
+		set ok 1
+	}
+	if { $ok > 0 && [ string length $fn ] > 0 } {
+		set fn2 [ file tail $fn ]
+		set fn3 [ file join $dirname $fn2 ]
+		$trn Save $fn3
+		set parameters($this,$pname) $fn3
+	} else {
+		set parameters($this,$pname) ""
+	}
+	itcl::delete obj $trn
+	}
+
+	for { set runcount 1 } { $runcount <= $numruns } { incr runcount } {
+	set img	 [  [ pxitclimage \#auto ] GetThisPointer ]
+	set fn	$parameters($this,run_file_$runcount)
+	set ok [ $img Load $fn ]
+	if { $ok > 0 } {
+		set fn2 [ file tail $fn ]
+		set fn3 [ file join $dirname $fn2 ]
+		$img Save $fn3
+		set parameters($this,run_file_$runcount) $fn3
+	} else {
+		set parameters($this,run_file_$runcount) ""
+	}
+	itcl::delete obj $img
+	
+	set fn	$parameters($this,run_motionfile_$runcount)
+	puts stdout "\n runcount=$runcount $fn=$fn"
+	if { [ file exists $fn ] > 0 } {
+		set fn2 [ file tail $fn ]
+		set fn3 [ file join $dirname $fn2 ]
+#	    puts stdout "\n $fn2 -> $fn3 "
+		file copy $fn $fn3
+		set parameters($this,run_motionfile_$runcount) $fn3
+	} else {
+		set parameters($this,run_motionfile_$runcount) ""
+	}
+	}
+	
+	set newsetupname [ file join $dirname [ file tail $setupname ]]
+	return [ $this SaveSetupFile $newsetupname ]
+}
+
+# ----------------------------------------------------------------------------------------
+# Progress Stuff
+# ----------------------------------------------------------------------------------------
+::itcl::body bis_fmrisetup::AddLogoLabel { w } {
+
+	global tcl_platform
+
+	set l [ label $w.[ pxvtable::vnewobj ] -image  $::pxtclvtkpxcontrib::smalllogo ]
+
+	return $l
+}
+
+::itcl::body bis_fmrisetup::CreateProgressBar { w } {
+	
+	set l [ AddLogoLabel $w	 ]
+	pack $l -side left -expand f -padx 1
+
+	set progressbar($this) $w.pbar
+	iwidgets::feedbackplus $w.pbar -steps 100  -barheight 10  -labelpos w -labeltext $progress_lab($this) 
+	pack $w.pbar -side right -expand t -fill x
+
+	#   $w configure -bg "\#8197c5" 
+	#    [ $w.pbar component trough ] configure  -bg  "\#cccdf8"
+	#    [ $w.pbar component percentage ] configure	 -fg  black 
+	
+
+
+}
+
+::itcl::body bis_fmrisetup::ProgressCallback { filter lab } {
+
+
+	#    puts stdout "Progress Callback ($this) = [ $filter GetClassName ] $label"
+	if { $progressbar($this) != 0 } {
+	$this ShowProgress $filter $lab
+	}
+	return 0
+
+}
+# ----------------------------------------------------------
+::itcl::body bis_fmrisetup::ShowProgress { filter lab } {
+	
+	if { $progressbar($this) == 0 } {
+	return
+	}
+
+	set progress_val($this) 50
+	catch { set progress_val($this)	 [expr [$filter GetProgress]*100] }
+	set progress_lab($this) $lab
+	
+
+
+	if {$lab == "Done" } { 
+	set progress_val($this) 0
+	}
+	
+
+	$progressbar($this) configure  -labeltext $progress_lab($this)
+	$progressbar($this) setval [ expr round($progress_val($this)) ]
+
+	update idletasks
+}
+# ----------------------------------------------------------
+::itcl::body bis_fmrisetup::ShowProgressVal { name val } {
+	
+	if { $progressbar($this) == 0 } {
+	return
+	}
+	
+	set progress_val($this) [expr $val*100.0]
+	set progress_lab($this) "$name"
+	
+	if {$name == "Done" } { 
+	set progress_val($this) 0
+	}
+
+	$progressbar($this) configure  -labeltext $progress_lab($this)
+	$progressbar($this) setval [ expr round($progress_val($this)) ]
+
+	update idletasks
+}
+# ----------------------------------------------------------
+itcl::body bis_fmrisetup::SetFilterCallbacks { filter comment } {
+	
+	set t [ itcl::scope $this ]
+
+	eval "$filter AddObserver ProgressEvent { $t ProgressCallback $filter \"$comment\"}"
+	eval "$filter AddObserver EndEvent	{ $t ProgressCallback $filter Done}"
+}
+
+
+# ----------------------------------------------------------------------------------------
+#
+#   Resting State Stuff
+#
+#
+# ----------------------------------------------------------------------------------------
+# Utility Methods
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_fmrisetup::PreprocessSingle4DImage { img mask { skipframeslist 0 } { motionmatrixname 0 } { graywhitemask 0 } } {
+
+	# motionmatrixname is either 0 or name of matlab .mat file for image
+	# graywhitemattermask is either 0 or pxitclimage of mask image
+
+	#
+	#    lappend restinglist { "#Mask Level (% of max intensity)"  masklevel 0.05 }
+	#    lappend restinglist { "#Polynomial Drift"	driftpol 3 } 
+	#    lappend restinglist { "#Slice Mean Removal"  slicemeanremoval 0 } 
+	#    lappend restinglist { "#Process Runs Individually"	 individualruns 0 } 
+	#    lappend restinglist { "#Temporal Smoothing Sigma (Frames)"	 temporalsigma 1.0 } 
+	#    
+	
+
+	# Flag parameters($this,resting_usemotionparams)  ] -text "Regress Motion Parameters" 
+	# Flag parameters($this,resting_usecsfmean)  ] -text "Regress CSF/White Matter Mean" 
+	# graywhitemask = gray/white/csf mask in functional space
+	# matrix is motion matrix
+
+	puts stdout "using mask	 [ $mask cget -filename ]"
+	set currentinput $img
+	set csfwmmotion_alg [ bis_csfwmmotioncorr \#auto ]
+	set tempsmooth_alg  [ bis_temporalsmoothimage \#auto ] 
+	set tempdrift_alg   [ bis_removetemporaldrift  \#auto ]
+	set tempremove_alg  [ bis_removeslicemean \#auto ]
+	set skipframe_alg   [ bis_imageremoveframes \#auto ]
+	
+	# csf whitematter temporal drift removal
+	if { $parameters($this,resting_usecsfmean) >0 } {
+		puts stdout "we are doing csf whitematter temporal drift removal"
+	$tempdrift_alg InitializeFromContainer 0 $this
+	$tempdrift_alg SetInput $currentinput
+	$tempdrift_alg SetSecondInput $graywhitemask
+	$tempdrift_alg SetOptionValue order $parameters($this,resting_driftpol)
+	$tempdrift_alg SetOptionValue usemask 1
+	$tempdrift_alg SetOptionValue legendre 1
+	$tempdrift_alg Execute
+	set currentinput [ $tempdrift_alg GetOutput ]
+	}
+	
+	#csf/wm/motion correction
+	if { $parameters($this,resting_usemotionparams) > 0 || $parameters($this,resting_usecsfmean) >0 } {
+		puts stdout "we are doing csfwmmotion correction"
+		$csfwmmotion_alg InitializeFromContainer 0 $this
+		$csfwmmotion_alg SetInput $currentinput
+		
+		if { $parameters($this,resting_usemotionparams) > 0 } {
+			$csfwmmotion_alg SetOptionValue filename $motionmatrixname
+			$csfwmmotion_alg SetOptionValue domotion 1
+		}
+		if { $parameters($this,resting_usecsfmean) > 0 } {
+			$csfwmmotion_alg SetSecondInput $graywhitemask
+			$csfwmmotion_alg SetOptionValue docsfwm 1
+			$csfwmmotion_alg SetOptionValue usemask 1
+		}
+		$csfwmmotion_alg Execute
+		set currentinput [ $csfwmmotion_alg GetOutput ]
+	}
+	
+
+	# temporal smooth
+	if { $parameters($this,resting_temporalsigma) > 0 } {
+		puts stdout "we are doing temporal smooth"
+	$tempsmooth_alg InitializeFromContainer 0 $this
+	$tempsmooth_alg SetInput $currentinput
+	$tempsmooth_alg SetSecondInput $mask
+	$tempsmooth_alg SetOptionValue blursigma $parameters($this,resting_temporalsigma)
+	$tempsmooth_alg SetOptionValue usemask 1
+	$tempsmooth_alg Execute
+	set currentinput [ $tempsmooth_alg GetOutput ]
+	}
+	
+	# gray matter temporal drift removal
+	if { $parameters($this,resting_driftpol) > -0.1 } {
+		puts stdout "we are doing drift removal"
+	$tempdrift_alg InitializeFromContainer 0 $this
+	$tempdrift_alg SetInput $currentinput
+	$tempdrift_alg SetSecondInput $mask
+	$tempdrift_alg SetOptionValue order $parameters($this,resting_driftpol)
+	$tempdrift_alg SetOptionValue usemask 1
+	$tempdrift_alg SetOptionValue legendre 1
+	$tempdrift_alg Execute
+	set currentinput [ $tempdrift_alg GetOutput ]
+	}
+	
+	
+	# remove slice mean
+	if { $parameters($this,resting_slicemeanremoval) > 0 || 
+	 $parameters($this,resting_volumemeanremoval) > 0 } {
+	$tempremove_alg InitializeFromContainer 0 $this
+	$tempremove_alg SetInput $currentinput
+	$tempremove_alg SetSecondInput $mask
+	$tempremove_alg SetOptionValue usemask 1
+	if { $parameters($this,resting_slicemeanremoval) > 0 } {
+		$tempremove_alg SetOptionValue globalmean 0
+		puts stdout "we are doing remove slice mean"
+	} else {
+		$tempremove_alg SetOptionValue globalmean 1
+		puts stdout "we are doing remove volumn mean"
+	}
+	$tempremove_alg Execute
+	set currentinput [ $tempremove_alg GetOutput ]
+	}
+	
+	if { $skipframeslist !=0 } {
+	$skipframe_alg InitializeFromContainer 0 $this
+	$skipframe_alg SetInput $currentinput
+	$skipframe_alg SetOptionValue unit $parameters($this,blockunits)
+	$skipframe_alg SetOptionValue offset 1
+	$skipframe_alg SetOptionValue tr $parameters($this,tr)
+	$skipframe_alg SetOptionValue framelist $skipframeslist
+	$skipframe_alg SetOptionValue keep 0
+	$skipframe_alg Execute
+	set currentinput [ $skipframe_alg GetOutput ]
+	}
+
+
+  #remove frames here----------------------------------
+	# Copy last result
+	set newimg [  [ pxitclimage \#auto ] GetThisPointer ]
+	$newimg ShallowCopy $currentinput
+
+	# Clean up objects
+	itcl::delete obj $tempsmooth_alg
+	itcl::delete obj $tempdrift_alg
+	itcl::delete obj $tempremove_alg
+	itcl::delete obj $skipframe_alg
+	itcl::delete obj $csfwmmotion_alg
+
+	return $newimg
+}
+
+
+# ------------------------------------------------------------------------------------------
+#
+# This concatenates all runs and does group preprocessing using the flags below
+# 
+# -------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::ConcatenateAndPreprocessRuns { mask { graywhitemask 0 } { checkformotioncorrection 0 } { enableskipframes 0 } } {
+
+	set appnd [ vtkpxAppendComponents [ pxvtable::vnewobj ]]
+
+	set comment "Concatenating :"
+	set failed 0
+
+	#    set numruns 2
+
+	for { set runcount 1 } { $runcount <= $numruns } { incr runcount } {
+	set runimage($runcount)	 [  [ pxitclimage \#auto ] GetThisPointer ]
+	set fn	$parameters($this,run_file_$runcount)
+	set ok [ $runimage($runcount) Load $fn ]
+	if { $ok > 0 } {
+		pxtkprint "\t\t .................... Adding Run $runcount ($fn) [ $runimage($runcount) GetShortDescription ] \n"
+		puts stdout "\t\t .................... Adding Run $runcount ($fn) [ $runimage($runcount) GetShortDescription ] \n"
+
+		
+		set runskipframes 0
+		if { $enableskipframes > 0 } {
+		if { $parameters($this,runskip_$runcount) == 1	|| $parameters($this,checks) > 0 } {
+			set runskipframes "$parameters($this,skipFrames) $parameters($this,skiprunsframe_$runcount)"
+		}
+		}
+		puts stdout "\t\t\t\t skipframes for this run = $runskipframes"
+
+		set motionmatrixname 0
+		if { $parameters($this,resting_usemotionparams) > 0 && $checkformotioncorrection > 0 } {
+		    set motionmatrixname $parameters($this,run_motionfile_$runcount)
+		}
+		
+		set tmp [ $this PreprocessSingle4DImage $runimage($runcount) $mask $runskipframes $motionmatrixname $graywhitemask ]
+		$appnd AddInput [ $tmp GetImage ]
+		itcl::delete obj $tmp
+		if { $runcount > 1 } {
+		itcl::delete obj $runimage($runcount)
+		}
+		set comment "$comment $fn"
+	} else {
+		set runcount [ expr $numruns + 5 ]
+		set failed 1
+	}
+	}
+
+	if { $failed == 0 } {
+	$appnd Update
+	set conc  [  [ pxitclimage \#auto ] GetThisPointer ]
+	$conc ShallowCopyImage [ $appnd GetOutput ]
+	$conc CopyImageHeader  [ $runimage(1) GetImageHeader ]
+	itcl::delete obj $runimage(1)
+	[ $conc GetImageHeader ] AddComment "$comment" 0
+	$appnd Delete
+	return $conc
+	}
+
+	itcl::delete obj $runimage(1)
+	return 0
+}
+# ----------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::CreateMask { img threshold } {
+
+	set r [ [ [ [ $img GetImage ] GetPointData ] GetScalars	 ] GetRange ]
+
+	set rmin [ lindex $r 0 ]
+	set rmax [ lindex $r 1 ]
+	
+	puts stdout "image range $rmin $rmax"
+
+	set lth [ expr $threshold*($rmax-$rmin) + $rmin ]
+	set uth [ expr $rmax + 1.0 ]
+
+	pxtkprint "Creating mask threshold = $threshold (thr=$lth)\n"
+	puts stdout "Creating mask threshold = $threshold (thr=$lth)\n"
+	
+	puts stdout "Threshold = $lth, $uth "
+
+
+	set extr [ vtkImageExtractComponents New ]
+	$extr SetInput [ $img GetImage ]
+	$extr SetComponents 0
+	#    $extr DebugOn
+	$extr Update
+	
+	set tthr [ vtkImageThreshold New ]
+	$tthr SetInput [ $extr GetOutput ]
+	$tthr ThresholdBetween $lth $uth
+	$tthr ReplaceInOn
+	$tthr ReplaceOutOn
+	$tthr SetInValue 1
+	$tthr SetOutValue 0
+	#$tthr DebugOn
+	$tthr Update
+
+	set mask  [  [ pxitclimage \#auto ] GetThisPointer ]
+	$mask ShallowCopy $img
+	$mask ShallowCopyImage [ $tthr GetOutput ]
+	$mask configure -filename "mask.nii.gz"
+
+	$tthr Delete
+	$extr Delete
+	return [  $mask GetThisPointer ]
+}
+
+
+
+# ----------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::CheckTransformationsForVOI { { graywhitemaskmode 0 } } {
+
+    set mname  $parameters($this,voiDefinitionSpace) 
+    
+    if { $graywhitemaskmode > 0 } {
+	set mname "Reference"
+    }
+    
+    if { $mname == "Functional" } { return [ vtkIdentityTransform New ] }
+    
+    set tlist [ list [ list 0 $parameters($this,distortionTransform) ] ]
+    if { $mname == "Anatomical" || $mname == "Reference" } {
+	lappend tlist [ list 0 $parameters($this,internalTransform) ]
+    }
+    if { $mname == "Reference" } {
+	lappend tlist [ list $parameters($this,inverseReferenceTransform) $parameters($this,referenceTransform) ]
+    }
+    
+    for { set i 0 } { $i < [ llength $tlist ] } { incr i } {
+	set it [ lindex $tlist $i ]
+	puts stdout "it($i) = $it "
+    }
+    
+    set gen [ vtkGeneralTransform New ]
+    $gen Identity
+    $gen PostMultiply
+    
+    
+    puts stdout "Transformation list = $tlist"
+
+
+    for { set i 0 } { $i < [ llength $tlist ] } { incr i } {
+	set pair [ lindex $tlist $i ]
+	set first [ lindex $pair 0 ];	
+	set second [ lindex $pair 1 ]
+	
+	set ok 0
+	set doinvert 0
+	set tr [ [ pxitcltransform \#auto ] GetThisPointer ]
+	if { $first !=0 && $first != "" } {
+	    set ok [ $tr Load $first ]
+	    if { $ok > 0 } {
+		puts stdout "\n\n Loading $i first = $first (ok=$ok), [ file size $first ]"
+	    }
+	}
+		
+	
+	if { $ok == 0 } {
+	    if { $second !=0 && $second != "" } {
+		set ok	[ $tr Load $second ]
+		puts stdout "Loading $i second = $second ($ok)"
+		if { $ok > 0 } {
+		    puts stdout "Inverting $second [ file size $second ]"
+		    $tr Invert
+		    
+		    if { $i == 2 } {
+			$tr Save
+			set parameters($this,inverseReferenceTransform) [ $tr cget -filename ]
+			set parameters($this,display_inverseReferenceTransform) [file tail [ $tr cget -filename ] ]
+		    }
+		}
+	    }
+	}
+	
+#	if { $ok == 1 } {
+#	    if { [ $tr IsIdentity ] } {
+#		set ok 0
+#		puts stdout "Filename [ $tr GetFileName ]"
+#	    }
+#	}
+	
+	if { $ok == 1 } {
+	    $gen Concatenate [ $tr GetTransformation ]
+	} else {
+	    puts stdout "Bad Transformation Set $tlist (or identity)"
+	    $gen Delete
+	    return 0
+	}
+	itcl::delete obj $tr
+    }
+    
+    return $gen
+}
+
+
+# ----------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::CheckVOIImageSize { voi_image funcimg { graywhitemaskmode 0 } } {
+	
+
+	if { $parameters($this,voiDefinitionSpace) == "Functional" && $graywhitemaskmode == 0  } {
+	if { [ $voi_image GetImageSize ] != [ $funcimg GetImageSize ] } {
+		puts stdout "Bad VOI Image for Functional Space"
+		return 0
+	} else	{
+		return 1
+	}
+	}
+
+	set mname  $parameters($this,voiDefinitionSpace) 
+	if { $graywhitemaskmode > 0 } {
+	set mname "Reference"
+	}
+	set c_image [  [ pxitclimage \#auto ] GetThisPointer ]
+
+	if { $mname == "Conventional"  } {
+	set ok [ $c_image Load $parameters($this,conventional) ]
+	} elseif { $mname == "Anatomical" } {
+	set ok [ $c_image Load $parameters($this,anatomical) ]
+	} elseif { $mname == "Reference" } {
+	set ok [ $c_image Load $parameters($this,reference_brain_path) ]
+	}
+
+	if { $ok == 0 } {
+	puts stdout "Failed to LOAD $mname Image"
+	} elseif { [ $voi_image GetImageSize ] != [ $c_image GetImageSize ] } {
+	puts stdout "Bad VOI or GrayWhiteMask Image for $mname Space"
+	set ok 0
+	}
+	
+	itcl::delete obj $c_image
+	return $ok
+}
+# ----------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::GetReslicedVOIImage { funcimg { graywhitemaskmode 0 } } {
+
+    set vname $parameters($this,voiDefinitionImage) 
+    set vtname "VOI"
+    if { $graywhitemaskmode > 0 } {
+	set vname $parameters($this,reference_gw_map)
+	set vtname "Gray/White/CSF"
+    }
+    
+    set voi_image [ [ pxitclimage \#auto ] GetThisPointer ]
+    
+    set ok [ $voi_image Load $vname ]
+    
+    
+    if { $ok == 0 } {
+	puts stdout "Failed to LOAD $vtname  Image = $vname"
+	return [ list 0	 0 ]
+    }
+    puts stdout "Loaded voi image from $vname  [ $voi_image GetShortDescription ]"
+    
+    set r [ [ [ [ $voi_image GetImage ] GetPointData ] GetScalars  ] GetRange ]
+    set rmin [ lindex $r 0 ]
+    set oldrange [ lindex $r 1 ]
+    
+    puts stdout "image range $rmin $oldrange"
+    
+    set ok [ $this CheckVOIImageSize $voi_image $funcimg $graywhitemaskmode ]
+    puts stdout "Checked $vtname image size\n"
+    
+    if { $ok == 0 } {
+	itcl::delete obj $voi_image 
+	return [ list 0 0 ]
+    }
+    
+    puts stdout "Checking transformations\n"
+    
+    set tr [ $this CheckTransformationsForVOI  $graywhitemaskmode ]
+    if { $tr == 0 } {
+	puts stdout "Transformation Check Failed"
+	itcl::delete obj $voi_image 
+	return [ list 0 0 ]
+    }
+    
+    puts stdout "Reslicing $vtname Image, transformation type=[ $tr GetClassName ] input range=$rmin:$oldrange\n"
+    
+    # else tr is now the transformation
+    set resl [ vtkbisImageReslice New ]
+
+ #   puts stdout "EPI = [ [ $funcimg GetImage ] GetDimensions ]"
+    $resl SetInformationInput [ $funcimg GetImage ]
+#    puts stdout "VOI = [ [ $voi_image GetImage ] GetDimensions ]"
+    $resl SetInput [ $voi_image GetImage ]
+    $resl SetResliceTransform  $tr
+    $resl SetInterpolationMode 0
+    $resl SetBackgroundLevel 0
+#    $resl OptimizationOff
+    $resl Update
+    
+    $voi_image ShallowCopyImage [ $resl GetOutput ]
+    $resl Delete
+    
+    
+    set r  [ [ [ [ $voi_image GetImage ] GetPointData ] GetScalars ] GetRange ]
+    if { [ lindex $r 0 ] == [ lindex $r 1 ] } {
+	puts stdout "Reslicing $vtname failed, range= $r"
+	itcl::delete obj $voi_image 
+	return [ list 0 0 ]
+    }
+    
+    puts stdout "Cleanup and return\n\n voi_image [ $voi_image GetShortDescription ] output range= [ [ [ [ $voi_image GetImage ] GetPointData ] GetScalars ] GetRange ]\n\n"
+    
+    $tr Delete
+    
+    return [ list $voi_image $oldrange ]
+}
+
+#  Main Function
+#  
+#  mode = 0   seed to image
+#  mode = 1   seed to seed
+# ----------------------------------------------------------------------------------------
+
+
+itcl::body bis_fmrisetup::ComputeSeedCorrelationSingle { mode inputimage maskimage filename {dosave 1 } } {
+
+	set lst	  [ $this GetReslicedVOIImage $inputimage ] 
+	set vimg [ lindex $lst 0  ]
+	set oldrange [ lindex $lst 1 ]
+		   
+	if { $vimg == 0 } {
+	return 0
+	}
+
+	set tmpname [ file rootname $filename ]
+	if { [ file extension $tmpname ] == ".nii" } { set tmpname [ file rootname $tmpname ] }
+
+	if { $dosave == 1 } {
+		set tmpname3 ${tmpname}_voi.nii.gz
+		$vimg Save $tmpname3
+		puts stdout "Resliced VOI image saved in $tmpname3"
+		
+		set tmpname4 ${tmpname}_mask.nii.gz
+		$maskimage Save $tmpname4
+		puts stdout "Resliced mask image saved in $tmpname4"
+		
+		#set tmpname2 ${tmpname}_preprocessedinput.nii.gz
+		#$inputimage Save $tmpname2
+		#puts stdout "Saved in $tmpname2"
+	}
+	
+	puts stdout "\n\n\n We are doing seed correlation. inputimage = [ $inputimage GetDescription ]\n, mask = [ $maskimage GetDescription ]\n, output filename = $filename"
+
+	set roimean_alg	 [ bis_roimean \#auto ] 
+	$roimean_alg InitializeFromContainer 0 $this
+	$roimean_alg SetInput $inputimage
+	$roimean_alg SetSecondInput $vimg
+	$roimean_alg SetOptionValue dotextfile 1
+	$roimean_alg SetOptionValue filename ${tmpname}_roimean.txt
+	$roimean_alg SetOptionValue filename2 ${tmpname}_xyzCoordinate.txt
+	set r [ [ [ [ $vimg GetImage ] GetPointData ] GetScalars  ] GetRange ]
+	set newrange [ lindex $r 1 ]
+	if { $newrange != $oldrange } {
+		puts stdout "add new region [ expr $oldrange - $newrange ]"
+	$roimean_alg SetOptionValue addregion [ expr $oldrange - $newrange ]
+	} 
+	$roimean_alg Execute
+	
+	if { $dosave == 1 } {
+	set tmpname1 ${tmpname}_roimean.nii.gz	
+	[ $roimean_alg GetOutput ] Save $tmpname1
+	puts stdout "ROI Mean saved in $tmpname1"
+	}
+	
+	
+	
+	if { $mode == 0 } {
+	set corr [ bis_seedcorrelation \#auto ]
+	$corr InitializeFromContainer 0 $this
+	$corr SetInput $inputimage  
+	$corr SetOptionValue raw $parameters($this,resting_rawcorrelation)
+	$corr SetSecondInput [ $roimean_alg GetOutput ]
+	$corr SetInputObject third_image $maskimage
+	$corr SetOptionValue usemask 1
+	$corr SetOptionValue ztransform $parameters($this,resting_ztransform)
+	$corr Execute
+	} else {
+	set corr [ bis_matrixcorrelation \#auto ]
+	$corr InitializeFromContainer 0 $this
+	$corr SetOptionValue raw $parameters($this,resting_rawcorrelation)
+	$corr SetInput [ $roimean_alg GetOutput ]
+	$corr SetOptionValue dotextfile 1
+	$corr SetOptionValue filename ${tmpname}_matrix.txt
+	$corr SetOptionValue filename2 ${tmpname}_outputForConnectivityViewer.txt
+	$corr Execute
+	}
+	
+	[ $corr GetOutput ] Save $filename
+	
+	itcl::delete obj $corr
+	itcl::delete obj $roimean_alg
+
+}
+itcl::body bis_fmrisetup::TaskBasedProcessing { task image maskimage vimg outname { addrange 0 } } {
+	#-----------get the block/task matrix------------------
+    set matrix [ $this CreateBaseGLMMatrix 0 ]
+	if { $matrix == 0 } {
+	return 0
+	}
+	set tmpname [ file rootname $outname ]
+	if { [ file extension $tmpname ] == ".nii" } { set tmpname [ file rootname $tmpname ] }
+	
+	set matname "${tmpname}_blocks.matr"
+	$matrix Save $matname
+
+	set cal [ vtkbisTaskBasedSeedCorrelation New ]
+	$cal SetInput [ $image GetImage ]
+	$cal SetImageROI [ $vimg GetImage ]
+	$cal SetImageMask [ $maskimage GetImage ]
+	$cal SetMatrix $matrix
+	$cal SetTask $task
+	$cal SetAddRegion $addrange
+	$cal SetDoText 1
+	set roimeanFilename "${tmpname}_roimean.txt"
+	$cal SetFileName $roimeanFilename
+	$cal Update
+	
+	set mp [ pxitclimage \#auto ]
+	$mp ShallowCopyImage [ $cal GetOutput ]
+	$mp Save $outname
+	pxtkprint "Average run image saved in [ $mp GetShortDescription ]"
+	itcl::delete object $mp
+	$cal Delete
+}
+# ----------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::TaskBasedComputeSeedCorrelation { { askfname 0 } } {
+	puts stdout "We are doing task based seed correlation."
+	set ln [ $this GenerateOutputFilenames $askfname ]
+	if { $ln == 0 } {
+	return 0
+	}
+	set outnamestem [ lindex $ln 0 ]
+	set msbsetupname [ lindex $ln 1 ]
+	catch { file mkdir $parameters($this,output_dir) }
+	set ok [ $this IsWritable $outnamestem ]
+	if { $ok == 0 } {
+		$this InfoMessage "You don't have write permission on $outnamestem. Calculation stops." "Error"
+		return 1
+	}
+	pxtkprint "Beginning Stem =$outnamestem\n\t Setup=$msbsetupname\n"
+	set extraname "seed"
+	set setuptasklist ""
+	
+	#---------------Get mask------------------------------------ 
+	set img	 [  [ pxitclimage \#auto ] GetThisPointer ]
+	set whitecsfmask 0
+	set fn	$parameters($this,run_file_1)
+	set ok [ $img Load $fn ]
+	if { $ok > 0 } {
+	set maskimage [ $this CreateMask $img $parameters($this,resting_masklevel) ]
+	if { $parameters($this,resting_usecsfmean) > 0 } {
+		puts stdout "we are doing csf correction all runs"
+		#
+		# Note (1) at end this switches to gray/white mask instead of VOI Image
+		# 
+		set whitecsfmask [ lindex [ $this GetReslicedVOIImage $img 1 ] 0 ]
+		set tmpname2 ${outnamestem}_allruns_whitecsfmask.nii.gz
+		$whitecsfmask Save $tmpname2
+		puts stdout "Resliced csf/white matter mask image saved in $tmpname2"
+		}
+	}
+	itcl::delete obj $img
+	#---------------Geberate giant 4D image----------------------
+
+	# The 1 1 0 enable graywhitemask, enable checkformotioncorrection and disableskipframes
+	# The skip frames here are dealt with in the creation of the GLM Matrix
+	set allrunsimage [ $this ConcatenateAndPreprocessRuns $maskimage $whitecsfmask 1 0	]
+
+	if { $allrunsimage == 0 } {
+	tk_messageBox -type ok -title "Error ..." -message "Failed to Concatenate Runs"
+	return 0
+	}
+	#----------get ROI image-------------------------------
+	
+	set lst	  [ $this GetReslicedVOIImage $allrunsimage ] 
+	set vimg [ lindex $lst 0  ]
+	set oldrange [ lindex $lst 1 ]
+	if { $vimg == 0 } {
+	return 0
+	}
+	set addrange 0
+	set r [ [ [ [ $vimg GetImage ] GetPointData ] GetScalars  ] GetRange ]
+	set newrange [ lindex $r 1 ]
+	if { $newrange != $oldrange } {
+	puts stdout "add new region [ expr $oldrange - $newrange ]"
+	set addrange [ expr $oldrange - $newrange ]
+	} 
+	
+	#---------------Calculate for each task-----------------------
+	for { set task 0 } { $task < $numtasks } { incr task } {
+	# ------Generate output filenames for computation --
+	set taskcount [ expr $task + 1 ]
+	set f $parameters($this,task_$taskcount) 
+	set tname ${extraname}_task${f}
+	
+	set outname   ${outnamestem}_$tname.nii.gz	
+	lappend setuptasklist [ list $tname $tname $outname ]
+	
+	$this TaskBasedProcessing $task $allrunsimage $maskimage $vimg $outname $addrange
+	
+	}
+	itcl::delete obj $allrunsimage
+	itcl::delete obj $maskimage
+	pxtkprint "Done Saving .. clean up time\n"
+	$this CreateMSBFile $msbsetupname $setuptasklist
+	
+	# -----------------------------------------------------------------------------------
+	
+	# Clean up
+
+	# --------------------------------- Report ------------------------------
+	$this InfoMessage "Done Task based Seed Correlation -- see single subejct file in $msbsetupname" "FYI"
+	$this DisplayMSBFile $msbsetupname
+	
+	return $outnamestem
+}
+# ----------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::ComputeSeedCorrelation { mode { askfname 0 } { report 0 }  } { 
+	# ---------------- Generate output filenames/directories --------------
+	
+	set ln [ $this GenerateOutputFilenames $askfname ]
+	if { $ln == 0 } {
+	return 0
+	}
+	set outnamestem [ lindex $ln 0 ]
+	set msbsetupname [ lindex $ln 1 ]
+	catch { file mkdir $parameters($this,output_dir) }
+	set ok [ $this IsWritable $outnamestem ]
+	if { $ok == 0 } {
+		$this InfoMessage "You don't have write permission on $outnamestem. Calculation stops." "Error"
+		return 1
+	}
+
+	if { $mode == 1 } {
+	set extraname "matrix"
+	} else {
+	set extraname "seed"
+	}
+	
+	pxtkprint "Beginning Stem =$outnamestem\n\t Setup=$msbsetupname\n"
+
+	# ---------------- calculate each run individually -------------------
+	set setuptasklist ""
+
+	# Get Average as well 
+
+	if { $parameters($this,resting_individualruns) > 0 } {
+	set tname "${extraname}_average"
+	set meanoutname	  ${outnamestem}_$tname.nii.gz	
+	lappend setuptasklist [ list $tname $tname $meanoutname ]
+	set whitecsfmask 0
+	
+	set imgnamelist ""
+	
+	for { set runcount 1 } { $runcount <= $numruns } { incr runcount } {
+		set img	 [  [ pxitclimage \#auto ] GetThisPointer ]
+		set motionmatrixname 0
+		set fn	$parameters($this,run_file_$runcount)
+		set ok [ $img Load $fn ]
+		
+		# provide motion matrix file location
+		if { $parameters($this,resting_usemotionparams) > 0 } {
+			set motionmatrixname $parameters($this,run_motionfile_$runcount)
+		}
+		
+		if { $ok > 0 } {
+			if { $runcount ==1 } {
+				if { $parameters($this,resting_usecsfmean) > 0 } {
+					puts stdout "we are doing csf correction individually"
+					#
+					# Note (1) at end this switches to gray/white mask instead of VOI Image
+					#
+					set whitecsfmask [ lindex [ $this GetReslicedVOIImage $img 1 ] 0 ]
+					set tmpname2 ${outnamestem}_whitecsfmask.nii.gz
+					$whitecsfmask Save $tmpname2
+					puts stdout "Resliced csf/white matter mask image saved in $tmpname2"
+					}
+			}
+		set msk [ $this CreateMask $img $parameters($this,resting_masklevel) ]
+		
+		# Handle skip frames here 
+		set runskipframes 0
+		if { $parameters($this,runskip_$runcount) == 1	|| $parameters($this,checks) > 0 } {
+			set runskipframes "$parameters($this,skipFrames) $parameters($this,skiprunsframe_$runcount)"
+		} 
+		puts stdout "\t\t\t\t skipframes for this run = $runskipframes"
+		
+		
+		# Yes to motion matrix and graywhite mask
+		set tmp [ $this PreprocessSingle4DImage $img $msk $runskipframes $motionmatrixname $whitecsfmask ]
+		set tname "${extraname}_$runcount"
+		set outname ${outnamestem}_$tname.nii.gz	
+		lappend setuptasklist [ list $tname $tname $outname ]
+		$this ComputeSeedCorrelationSingle $mode $tmp $msk $outname
+		lappend imgnamelist $outname
+		
+		#set tmpname3 ${outnamestem}_${tname}_input.nii.gz
+		#$tmp Save $tmpname3
+		#puts stdout "Saved in $tmpname3"
+		
+		itcl::delete obj $img
+		itcl::delete obj $tmp
+		itcl::delete obj $msk
+		} else {
+		tk_messageBox -type ok -title "Error ..." -message "Failed to Load  Run $runcount ($fn)"
+		itcl::delete obj $img 
+		return 0
+		}
+	}
+	catch { itcl::delete obj $whitecsfmask }
+	
+	# Load all images in imgnamelist, compute average and save in meanoutname ....
+	#
+	#
+	set combofmri [	 vtkpxAverageImages [ pxvtable::vnewobj ]]
+	$combofmri SetMedian 0
+	for { set index 0 } { $index < $numruns } { incr index } {
+		set mp($index) [ pxitclimage \#auto ]
+		$mp($index) Load [ lindex $imgnamelist $index ]
+		pxtkprint "Adding image [ $mp($index) GetShortDescription ]\n"
+		$combofmri AddInput [ $mp($index) GetImage ]
+	}
+	$combofmri Update
+	
+	$mp(0) ShallowCopyImage [ $combofmri GetOutput ]
+	$mp(0) Save $meanoutname
+	pxtkprint "Average run image saved in [ $mp(0) GetShortDescription ]"
+	
+	for { set index 0 } { $index < $numruns } { incr index } {
+		itcl::delete object $mp($index)
+	}
+	# ---------------- Generate giant 4D Image and mask -------------------
+	} else {
+	set whitecsfmask 0
+	set img	 [  [ pxitclimage \#auto ] GetThisPointer ]
+	set fn	$parameters($this,run_file_1)
+	set ok [ $img Load $fn ]
+		if { $ok > 0 } {
+			set maskimage [ $this CreateMask $img $parameters($this,resting_masklevel) ]
+			if { $parameters($this,resting_usecsfmean) > 0 } {
+				puts stdout "we are doing csf correction all runs"
+				#
+				# Note (1) at end this switches to gray/white mask instead of VOI Image
+				# 
+				set whitecsfmask [ lindex [ $this GetReslicedVOIImage $img 1 ] 0 ]
+				set tmpname2 ${outnamestem}_allruns_whitecsfmask.nii.gz
+				$whitecsfmask Save $tmpname2
+				puts stdout "Resliced csf/ white matter mask image saved in $tmpname2"
+				}
+		}
+	
+	itcl::delete obj $img
+
+	# enable gray/csf GLM, enable motion GLM, enable skip frames
+	set allrunsimage [ $this ConcatenateAndPreprocessRuns $maskimage $whitecsfmask 1 1 ]
+	if { $allrunsimage == 0 } {
+		tk_messageBox -type ok -title "Error ..." -message "Failed to Concatenate Runs"
+		return 0
+	}
+	# ------------- Generate output filenames for computation ------------------
+	set tname "${extraname}"
+	set outname   ${outnamestem}_${extraname}.nii.gz	
+	lappend setuptasklist [ list $tname $tname $outname ]
+	$this ComputeSeedCorrelationSingle $mode $allrunsimage $maskimage $outname
+	
+	itcl::delete obj $allrunsimage
+	itcl::delete obj $maskimage
+	catch { itcl::delete obj $whitecsfmask }
+	}
+	
+	pxtkprint "Done Saving .. clean up time\n"
+	$this CreateMSBFile $msbsetupname $setuptasklist
+
+	# -----------------------------------------------------------------------------------
+	
+	# Clean up
+	
+	# --------------------------------- Report ------------------------------
+	$this InfoMessage "Done Seed Correlation -- see single subejct file in $msbsetupname" "FYI"
+	$this DisplayMSBFile $msbsetupname
+	
+	return $outnamestem
+}
+
+
+
+# ----------------------------------------------------------------------------------------
+# Resting State algorithms
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_fmrisetup::ComputeIntrinsicCorrelationSingle { mode allrunsimage maskimage outname } {
+	
+    if { $mode == "Complex" } {
+	return [ $this ComputeComplexIntrinsicCorrelationSingle $mode $allrunsimage $maskimage $outname ]
+    }
+
+    set tmpname [ file rootname $outname ]
+    if { [ file extension $tmpname ] == ".nii" } { set tmpname [ file rootname $tmpname ] }
+    
+    set tmpname4 ${tmpname}_mask.nii.gz
+    $maskimage Save $tmpname4
+    puts stdout "Resliced mask image saved in $tmpname4"
+    
+    puts stdout "\n\n\n We are doing intrinsic correlation. Mode= $mode, inputimage = [ $allrunsimage GetDescription ]\n, mask = [ $maskimage GetDescription ]\n, output filename = $outname "
+    
+    set con [ bis_intrinsicconnectivity \#auto ]
+    $con InitializeFromContainer 0 $this
+    $con SetInput $allrunsimage
+    $con SetSecondInput $maskimage
+    $con SetOptionValue usemask 1
+    $con SetOptionValue mode $mode
+    #$con SetOptionValue raw $parameters($this,resting_rawcorrelation)
+    $con SetOptionValue threshold $parameters($this,resting_threshold)
+    $con SetOptionValue calculate $parameters($this,resting_mode)
+    $con SetOptionValue range     $parameters($this,resting_range)
+    #$con SetOptionValue filename  ${tmpname}_MeanAndStd.txt
+    $con Execute
+    
+    
+    [ $con	GetOutput ] Save $outname
+    #puts stdout "Output saved in [ [ $con  GetOutput ] GetDescription ]"
+    
+    if { $parameters($this,resting_threshold) != 0.0 } {
+	set outname2 ${tmpname}_Degree.nii.gz
+	[ $con GetSecondOutput ] Save $outname2
+    }
+    
+    
+    
+    itcl::delete obj $con
+}
+
+# -------------------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::ComputeComplexIntrinsicCorrelationSingle { mode allrunsimage maskimage outname } {
+	
+
+# Dustin Modify this
+
+	set tmpname [ file rootname $outname ]
+	if { [ file extension $tmpname ] == ".nii" } { set tmpname [ file rootname $tmpname ] }
+
+	set tmpname4 ${tmpname}_mask.nii.gz
+	$maskimage Save $tmpname4
+	puts stdout "Resliced mask image saved in $tmpname4"
+
+	puts stdout "\n\n\n We are doing intrinsic correlation. Mode= $mode, inputimage = [ $allrunsimage GetDescription ]\n, mask = [ $maskimage GetDescription ]\n, output filename = $outname "
+	
+	set con [ bis_intrinsicconnectivity \#auto ]
+	$con InitializeFromContainer 0 $this
+	$con SetInput $allrunsimage
+	$con SetSecondInput $maskimage
+	$con SetOptionValue usemask 1
+	$con SetOptionValue mode $mode
+	#$con SetOptionValue raw $parameters($this,resting_rawcorrelation)
+	$con SetOptionValue threshold $parameters($this,resting_threshold)
+	$con SetOptionValue calculate $parameters($this,resting_mode)
+	$con SetOptionValue range     $parameters($this,resting_range)
+	#$con SetOptionValue filename  ${tmpname}_MeanAndStd.txt
+	$con Execute
+	
+
+	[ $con	GetOutput ] Save $outname
+	#puts stdout "Output saved in [ [ $con  GetOutput ] GetDescription ]"
+	
+	if { $parameters($this,resting_threshold) != 0.0 } {
+			set outname2 ${tmpname}_Degree.nii.gz
+			[ $con GetSecondOutput ] Save $outname2
+		}
+	
+	
+	
+	itcl::delete obj $con
+}
+# --------------------------------------------------------------------------------------------
+
+
+itcl::body bis_fmrisetup::ComputeIntrinsicCorrelation { mode { askfname 0 } {  report 0 } }  {
+	
+	# ---------------- Generate output filenames/directories --------------
+	
+	set ln [ $this GenerateOutputFilenames $askfname ]
+	if { $ln == 0 } {
+	return 0
+	}
+
+	set outnamestem [ lindex $ln 0 ]
+	set msbsetupname [ lindex $ln 1 ]
+	catch { file mkdir $parameters($this,output_dir) }
+	set ok [ $this IsWritable $outnamestem ]
+	if { $ok == 0 } {
+		$this InfoMessage "You don't have write permission on $outnamestem. Calculation stops." "Error"
+		return 1
+	}
+	
+	if { $mode == "Ipsilateral" } {
+	set extraname "ipsilateral"
+	} elseif { $mode == "Whole" } {
+	set extraname "whole"
+	} else {
+	set extraname "contralateral"
+	}
+	
+	pxtkprint "Beginning Stem =$outnamestem\n\t Setup=$msbsetupname\n"
+	
+	#----------------------Calculating--------------------------------------
+	
+	set setuptasklist ""
+	
+	if { $parameters($this,resting_individualruns) > 0 } {
+	# ----------------Do each run individually -------------------
+	set tname "${extraname}_average"
+	set meanoutname	  ${outnamestem}_$tname.nii.gz	
+	lappend setuptasklist [ list $tname $tname $meanoutname ]
+	set imgnamelist ""
+	set msk 0
+	set whitecsfmask 0
+	
+	for { set runcount 1 } { $runcount <= $numruns } { incr runcount } {
+		set img	 [  [ pxitclimage \#auto ] GetThisPointer ]
+		set motionmatrixname 0
+		set fn	$parameters($this,run_file_$runcount)
+		set ok [ $img Load $fn ]
+		
+		if { $parameters($this,resting_usemotionparams) > 0 } {
+		set motionmatrixname $parameters($this,run_motionfile_$runcount)
+		}
+		
+		if { $ok > 0 } {
+		if { $runcount == 1 } {
+			if { $parameters($this,resting_usermask) } {
+			set msk [ lindex [ $this GetReslicedVOIImage $img ]  0 ]
+				if { $mode != "Whole" } {
+					set r [ [ [ [ $maskimage GetImage ] GetPointData ] GetScalars  ] GetRange ]
+					set range [ lindex $r 1 ]
+					if { $range != 200.0 } {
+						$this InfoMessage "Invalid mask. User needs to provide a mask with 0 = background, 100 = right brain, 200 = left brain" "Error"
+						return 1
+					}
+				}
+			} else {
+				if { $mode == "Whole" } {
+					set maskimage [ $this CreateMask $img $parameters($this,resting_masklevel) ]
+				} else {
+					$this InfoMessage "Invalid mask. User needs to provide a mask with 0 = background, 100 = right brain, 200 = left brain" "Error"
+					return 1
+				}
+			}
+
+			if { $parameters($this,resting_usecsfmean) > 0 } {
+			puts stdout "we are doing csf correction individually"
+			#
+			# Note (1) at end this switches to gray/white mask instead of VOI Image
+			#
+			set whitecsfmask [ lindex [ $this GetReslicedVOIImage $img 1 ] 0 ]
+			set tmpname2 ${outnamestem}_whitecsfmask.nii.gz
+			$whitecsfmask Save $tmpname2
+			puts stdout "Resliced csf/white matter mask saved in $tmpname2"
+			}
+		}
+		
+		set runskipframes 0
+		if { $parameters($this,runskip_$runcount) == 1	|| $parameters($this,checks) > 0 } {
+			set runskipframes "$parameters($this,skipFrames) $parameters($this,skiprunsframe_$runcount)"
+		} 
+		puts stdout "\t\t\t\t skipframes for this run = $runskipframes"
+		
+		# Yes to motion and graywhitemask
+		set tmp [ $this PreprocessSingle4DImage $img $msk $runskipframes $motionmatrixname $whitecsfmask ]
+		set tname "${extraname}_$runcountset_$parameters($this,resting_mode)_$parameters($this,resting_range)"
+		set outname ${outnamestem}_$tname.nii.gz
+		lappend setuptasklist [ list $tname $tname $outname ]
+		$this ComputeIntrinsicCorrelationSingle $mode $tmp $msk $outname
+		lappend imgnamelist $outname
+		
+		#set tmpname3 ${outnamestem}_${tname}_input.nii.gz
+		#$img Save $tmpname3
+		#puts stdout "Saved in $tmpname3"
+		
+		itcl::delete obj $img
+		itcl::delete obj $tmp
+		} else {
+		tk_messageBox -type ok -title "Error ..." -message "Failed to Load  Run $runcount ($fn)"
+		itcl::delete obj $img 
+		return 0
+		}
+	}
+	catch { itcl::delete obj $msk }
+	catch { itcl::delete obj $whitecsfmask }
+	# Load all images in imgnamelist, compute average and save in meanoutname ....
+	#
+	#
+	set combofmri [	 vtkpxAverageImages [ pxvtable::vnewobj ]]
+	$combofmri SetMedian 0
+	for { set index 0 } { $index < $numruns } { incr index } {
+		set mp($index) [ pxitclimage \#auto ]
+		$mp($index) Load [ lindex $imgnamelist $index ]
+		pxtkprint "Adding image [ $mp($index) GetShortDescription ]\n"
+		$combofmri AddInput [ $mp($index) GetImage ]
+	}
+	$combofmri Update
+	
+	$mp(0) ShallowCopyImage [ $combofmri GetOutput ]
+	$mp(0) Save $meanoutname
+	pxtkprint "Average run image saved in [ $mp(0) GetShortDescription ]"
+	
+	for { set index 0 } { $index < $numruns } { incr index } {
+		itcl::delete object $mp($index)
+	}
+    } else {
+	set whitecsfmask 0
+	# ---------------- Generate giant 4D Image and mask -------------------
+	set img	 [  [ pxitclimage \#auto ] GetThisPointer ]
+	set fn	$parameters($this,run_file_1)
+	set ok [ $img Load $fn ]
+	if { $ok > 0 } {
+		if { $parameters($this,resting_usermask) } {
+		set maskimage [ lindex [ $this GetReslicedVOIImage $img ]  0]
+			if { $mode != "Whole" } {
+				set r [ [ [ [ $maskimage GetImage ] GetPointData ] GetScalars  ] GetRange ]
+				set range [ lindex $r 1 ]
+				puts stdout "User provided mask max value:  $range"
+					if { $range != 200.0 } {
+						$this InfoMessage "Invalid mask. User needs to provide a mask with 0 = background, 100 = right brain, 200 = left brain" "Error"
+						return 1
+					}
+				}
+		} else {
+			if { $mode == "Whole" } {
+				set maskimage [ $this CreateMask $img $parameters($this,resting_masklevel) ]
+			} else {
+				$this InfoMessage "Invalid mask. User needs to provide a mask with 0 = background, 100 = right brain, 200 = left brain" "Error"
+				return 1
+			}
+		}
+		
+		if { $parameters($this,resting_usecsfmean) > 0 } {
+		puts stdout "we are doing csf correction all runs"
+		#
+		# Note (1) at end this switches to gray/white mask instead of VOI Image
+		# 
+		set whitecsfmask [ lindex [ $this GetReslicedVOIImage $img 1 ] 0 ]
+		set tmpname2 ${outnamestem}_allruns_whitecsfmask.nii.gz
+		$whitecsfmask Save $tmpname2
+		puts stdout "Resliced csf/white matter mask saved in $tmpname2"
+		}
+	}
+	
+	itcl::delete obj $img
+	
+	#set tmpname4 ${outnamestem}_intrimask.nii.gz
+	#$maskimage Save $tmpname4
+	#puts stdout " Saved [ $maskimage GetDescription ]"
+	
+	set allrunsimage [ $this ConcatenateAndPreprocessRuns $maskimage $whitecsfmask 1 1 ]
+	if { $allrunsimage == 0 } {
+		tk_messageBox -type ok -title "Error ..." -message "Failed to Concatenate Runs"
+		return 0
+	}
+	#set tmpname1 ${outnamestem}_intrinput.nii.gz
+	#$allrunsimage Save $tmpname1
+	#puts stdout "Preprocessed and concatenated input image [$allrunsimage GetDescription ]\n saved in $tmpname1"
+	
+	# ------------- Generate output filenames for computation ------------------
+	set tname "${extraname}_$parameters($this,resting_mode)_$parameters($this,resting_range)"
+	set outname ${outnamestem}_$tname.nii.gz
+	lappend setuptasklist [ list $tname $tname $outname ]
+		
+	$this ComputeIntrinsicCorrelationSingle $mode $allrunsimage $maskimage $outname
+	itcl::delete obj $allrunsimage
+	itcl::delete obj $maskimage
+	}
+	
+	pxtkprint "Done Saving .. clean up time\n"
+	$this CreateMSBFile $msbsetupname $setuptasklist
+	
+	# -----------------------------------------------------------------------------------
+	# Clean up
+	# --------------------------------- Report ------------------------------
+	$this InfoMessage  "Done Intrinsic Connectivity -- see single subejct file in $msbsetupname" "FYI"
+	$this DisplayMSBFile $msbsetupname
+	
+	return $outnamestem
+}
+
+
+# ----------------------------------------------------------------------------------------
+# Data Tree Stuff
+# ----------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::CreateDataTreeStructure { { tasklist "" } { doupdate 1 } } {
+	
+	if { $datamanager == 0 } {
+	if { $treewidget !=0 } {	
+		set datamanager [ $treewidget GetDataManager ]
+	} else {
+		set datamanager [ [ bis_datamanager \#auto ] GetThisPointer ]
+	}
+	}
+
+	$datamanager CleanXML
+	set rootnode [ $datamanager GetRootNode ]
+
+	set ref [ eval "$datamanager CreateChildElement $rootnode Image Reference_Image { Filename $parameters($this,reference_brain_path)}" ]
+	set subjectdata [ $datamanager CreateChildElement $ref Subject "S-$parameters($this,subject_id)" {  Expanded "1"  IsIdentity 1 } ]
+	
+	set aname $parameters($this,anatomical)
+	set cname $parameters($this,conventional)
+	set ename ""
+	set xname $parameters($this,referenceTransform)
+	set iname $parameters($this,internalTransform)
+	set dname $parameters($this,distortionTransform)
+
+	set anat [ eval "$datamanager CreateChildElement $subjectdata Image \"3D_Anatomical_Image\" { Filename \"$aname\"   TransformationFilename \"$xname\" Expanded 1 }" ]
+	set conv [ eval "$datamanager CreateChildElement $anat Image \"Conventional_Image\" { Filename \"$cname\"  TransformationFilename \"$iname\" Expanded 1 }" ]
+	set epi [ eval "$datamanager CreateChildElement $conv Image  \"Echoplanar_Image\" { Filename \"$ename\"	 TransformationFilename \"$dname\" Expanded 1 } " ]
+	set func [ $datamanager CreateChildElement $epi "Folder" "Input Runs" { Expanded 1 } ]
+
+	for { set runcount 1 } { $runcount <= $numruns } { incr runcount } {
+	set fn	$parameters($this,run_file_$runcount)
+	eval "$datamanager CreateChildElement $func Image \"Run_${runcount}\" { Filename \"$fn\"   IsIdentity 1 } "
+	}
+
+	set outdata [ $datamanager CreateChildElement $epi "Folder" Outputs { IsIdentity 1  Expanded "1" } ]
+
+	set voiname $parameters($this,voiDefinitionImage)
+	set vspace $parameters($this,voiDefinitionSpace)
+	set vtransform $parameters($this,inverseReferenceTransform)
+
+	#    puts $fileid "#VOI Definition Space (Reference,Anatomical,Conventional,Functional)"
+	if { $vspace == "Reference" } {
+	set voi [ eval "$datamanager CreateChildElement $ref Image 0_VOI_Image { Filename $voiname IsIdentity 1 } " ]
+	$anat SetAttribute InverseTransformationFilename $vtransform
+	}  else {
+	switch -exact  $vspace {
+		"Anatomical"   {  set par $anat }
+		"Conventional" { set par $conv }
+		"Functional"   { set par $epi  }
+	}
+	set voi [ eval "$datamanager CreateChildElement $par Image 0_VOI_Image { Filename \"$voiname\" IsIdentity 1 } " ]
+	}
+
+
+	set nt [ llength $tasklist ]
+	if { $nt > 0 } {
+	for { set j 0 } { $j < $nt  } { incr j } {
+		set task [ lindex $tasklist $j ]
+		set tname   [ lindex $task 0 ]
+		set tsuffix [ lindex $task 1 ] 
+		set tfname  [ lindex $task 2 ]
+	    if { [ llength $tasklist ] < 10 } {
+		set tname "T[ expr $j +1 ]-$tname"
+	    } elseif { [ llength $tasklist ] < 100 } {
+		set tname [ format "T%02d-$tname" [ expr $j +1 ] ]
+	    } else {
+		set tname [ format "T%03d-$tname" [ expr $j +1 ] ]
+	    }
+	    set t [ $datamanager CreateChildElement $outdata Image $tname ]
+	    $t SetAttribute Filename $tfname
+	    $t SetAttribute IsIdentity 1
+	}
+	}
+
+
+	if { $treewidget !=0 && $doupdate == 1 } {
+	$treewidget UpdateAll
+	}
+
+	return 1
+
+}
+# ----------------------------------------------------------------------------------------
+
+itcl::body bis_fmrisetup::UpdateDataTreeStructure { { imagename "" } } {
+
+	if { $treewidget  == 0 } { return 0 }
+	$treewidget UpdateExpandedFlag
+	return [ $this CreateDataTreeStructure "" 1 ]
+}
+
+
+ 
+# ----------------------------------------------------------------------------------------
+itcl::body bis_fmrisetup::InfoMessage { msg { title "" } { icon info } } {
+
+	if { [ $this HasGUI ] == 1 } {
+	tk_messageBox -type ok -message $msg -title $title -icon $icon
+	} else {
+	puts stdout "$msg"
+	}
+}
+
+# -----------------------------------------------------------------------------------------
+
+itcl::body bis_fmrisetup::Usage {  } {
+
+	set line "\n This is the BioImage Suite (www.bioimagesuite.org) v3.0 fmri tool\n"
+	set line "$line\nbis_fmrisetup setupfilename procedure \[ second setup file \] \[ output_directory \]\n"
+	set line "$line\nprocedure = \t	 glm \t\t --> execute general linear model analysis"
+	set line "$line\n\t\t  seed \t\t --> execute seed to image connectivity analysis"
+	set line "$line\n\t\t  matrix \t --> execute seed to seed connectivity analysis"
+	set line "$line\n\t\t  taskseed \t\t --> execute task-based seed to image connectivity analysis"
+	
+
+
+	set line "$line\n\t\t  whole \t --> execute intrinsic connectivity (whole) analysis"
+	set line "$line\n\t\t  ipsi \t\t--> execute intrinsic connectivity (ipsilateral) analysis"
+	set line "$line\n\t\t  contra \t--> execute intrinsic connectivity (contralateral) analysis"
+	
+	set line "$line\n\n If second_setup file is specified then parameters in this ovveride original"
+	set line "$line\n\n If ouput_directory is not specified then the value from the setup file will be used"
+	return $line
+}
+
+itcl::body bis_fmrisetup::MainFunction { numarg arglist } {
+
+	update idletasks
+	global pxtcl_pref_array 
+
+	if { $numarg <	1 } {
+	    puts stdout [ $this Usage ]
+	    return [ list 0 "Bad Arguments" ]
+	}
+
+	puts stdout "numarg=$numarg, arglist=$arglist"
+
+	set pxtcl_pref_array(MirrorConsole) 1
+
+	set f [ file normalize [lindex $arglist 0]]
+	set ok [ $this LoadSetupFile  [ file normalize [lindex $arglist 0]]]
+	if { $ok == 0 } {
+	    puts stdout "Bad Setup File [ file normalize [lindex $arglist 0]]]\n"
+	    return [ list 0 "Bad Setup File [ file normalize [lindex $arglist 0]]" ]
+	}
+
+
+	set count 2
+	if { $numarg > $count } {
+	    set temp [ lindex $arglist $count ]
+	    if { $temp == "_do_not_use" } {
+		incr count
+	    } elseif { [ file extension $temp ] == ".xmlg" } {
+		puts "Read this as a second file"
+		$this LoadParameterFile $temp
+		incr count
+	    }
+	}
+		
+	if { $numarg > $count } {
+	    set outdir [ file normalize [ lindex $arglist $count ]]
+	    puts stdout "Using outdir=$outdir"
+	    if { [ file exists $outdir ] == 1 } {
+		set ok [ file isdirectory $outdir ]
+		if { $ok == 0 } {
+		    puts stdout "Bad output directory $outdir"
+		    return [ list 0 "Bad output directory $outdir" ]
+		}
+	    } else {
+		catch { file mkdir $outdir } 
+	    }
+	    
+	    if { [ file writable $outdir ] == 0 } {
+		puts stdout "Output directory $outdir is not writable by the current user"
+		return [ list 0 "Output directory $outdir is not writable by the current user" ]
+	    }
+	    
+	    set parameters($this,output_dir) $outdir
+	    puts stdout "Using $parameters($this,output_dir) as output directory"
+	}
+
+	if { $numarg > 1 } {
+	set mode [ lindex $arglist 1 ]
+	switch -exact $mode {
+		"seed" {
+		$this ComputeSeedCorrelation 0
+		}
+		"matrix" { 
+		$this ComputeSeedCorrelation 1
+		}
+		"taskseed" {
+		$this TaskBasedComputeSeedCorrelation 0
+		}
+		"whole" {
+		$this ComputeIntrinsicCorrelation "Whole" 
+		} 
+	    "ipsi" {
+		$this ComputeIntrinsicCorrelation "Ipsilateral" 
+		}
+		"contra" {
+		$this ComputeIntrinsicCorrelation "Contralateral" 
+		}
+	    "complex" { 
+		$this ComputeIntrinsicCorrelation "Complex" 
+	    }
+		"glm" {
+		$this ComputeGLM 0
+		}
+
+	}
+	}
+	return 1
+}
+
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+	wm withdraw .
+	set element [bis_fmrisetup \#auto ]
+	$element MainFunction $argc $argv
+	exit
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/bis_parameterGUI.tcl b/bioimagesuite30_src/bioimagesuite/main/bis_parameterGUI.tcl
new file mode 100755
index 0000000..db8ad4a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/bis_parameterGUI.tcl
@@ -0,0 +1,151 @@
+#!/bin/sh
+# the next line restarts using wish \
+	exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps]
+
+package require Itcl 3.2
+package require Iwidgets 
+# This loads the basic BioImage Suite libraries
+package require vtkpxcontrib  1.1
+
+
+# This loads the database library
+pxtclvtkpxcontrib::LoadLibraries { vtkbisDatabaseTCL }
+
+itcl::class bis_parameterGUI {
+	private common parameters
+	protected variable basewidget 0
+	
+	constructor { parent } { CreateGUI $parent }
+	destructor { }
+	
+	public method Reset { ask }
+	public method SetColor { widget }
+	public method GetName { mode }
+	public method CreateGUI { base }
+	
+};
+
+itcl::body bis_parameterGUI::Reset { ask } {
+	if { $ask == 1 } {
+		set ok [ tk_messageBox -type yesno -message "Reseting filenames" -icon question ]
+		if { $ok == "no" } { return }
+	}
+	set parameters($this,readname) ""
+	set parameters($this,writename) ""
+	set parameters($this,directory) ""
+}
+itcl::body bis_parameterGUI::SetColor { widget } {
+	set color [ tk_chooseColor -title "Set Background Color" -parent $basewidget ]
+	if { [string length $color ] > 0 } { $widget configure -bg $color }
+}
+
+itcl::body bis_parameterGUI::GetName { mode } {
+	set fname ""
+	set filetype1 [ list "Text Files" [ list .txt .tex ] ]
+	set filetype2 [ list "All Files" "*" ]
+	switch -exact $mode {
+		"readname" { set fname [tk_getOpenFile -title "Load" -filetypes [ list $filetype1 $filetype2 ] ] }
+		"writename" { set fname [tk_getSaveFile -title "Filename" -filetypes [ list $filetype1 ] ] }
+		"directory" { set fname [tk_chooseDirectory -title "Select Directory" ] }
+	}
+	if { [ string length $fname ] < 1 } { return }
+	set parameters($this,$mode) $fname
+}
+
+itcl::body bis_parameterGUI::CreateGUI { base } {
+	set .tnb $base
+	
+	# Page Add
+	# ----------------------------------------------------------------------
+	set page [.tnb add -label "Add"]
+	
+	iwidgets::entryfield $page.name -labeltext "Preset Name:" 
+	pack $page.name
+	iwidgets::entryfield $page.addr -labeltext "Description:" 
+	pack $page.addr
+	iwidgets::Labeledwidget::alignlabels $page.name $page.addr
+	iwidgets::buttonbox $page.bb 
+	$page.bb add OK -text "Add Current" -command "puts OK" 
+	pack $page.bb -expand yes -fill both
+	 
+	# Page Query
+	# ----------------------------------------------------------------------
+	set page [.tnb add -label "Query"]
+	
+	iwidgets::entryfield $page.presetnameQ -labeltext "Preset Name:" 
+	pack $page.presetnameQ
+	iwidgets::entryfield $page.descrQ -labeltext "Description:" 
+	pack $page.descrQ
+	iwidgets::entryfield $page.date -labeltext "Date:" 
+	pack $page.date
+	iwidgets::entryfield $page.para -labeltext "Parameter:" 
+	pack $page.para
+	iwidgets::Labeledwidget::alignlabels $page.presetnameQ $page.descrQ $page.date $page.para
+	
+	iwidgets::buttonbox $page.btop 
+	$page.btop add querybtn -text "Query" -command "puts OK" 
+	$page.btop add showbtn -text "Show All" -command "puts All"
+	pack $page.btop -fill both
+	
+	iwidgets::scrolledlistbox $page.slb -vscrollmode dynamic -selectmode single 
+	pack $page.slb -expand yes -fill x
+	$page.slb insert 0 Hello Here Me
+	
+	iwidgets::buttonbox $page.bb 
+	$page.bb add btnview -text View -command "puts OK" 
+	$page.bb add btnselect -text Select -command "puts Apply"
+	$page.bb add btndelete -text Delete -command "puts Cancel"
+	$page.bb default btnview
+	
+	pack $page.bb -expand yes -fill both
+	
+	#iwidgets::buttonbox $page.bbtom 
+	#$page.bbtom add viewbtn -text "View" -command "puts OK" 
+	#$page.bbtom add selectbtn -text "Select" -command "puts All"
+	#$page.bbtom add delbtn -text "Delete" -command "puts All"
+	#pack $page.bbtom -expand yes -fill both
+	
+	.tnb view "Add"
+	.tnb configure -tabpos n
+	
+}
+
+option add *textBackground seashell
+option add *Tabnotebook.backdrop DimGray
+option add *Scale.width 8
+. configure -background white
+
+iwidgets::tabnotebook .tnb -width 500 -height 450
+pack .tnb -expand yes -fill both
+set element [ bis_parameterGUI \#auto .tnb ]
diff --git a/bioimagesuite30_src/bioimagesuite/main/pkgIndex.tcl b/bioimagesuite30_src/bioimagesuite/main/pkgIndex.tcl
new file mode 100644
index 0000000..2e632e9
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pkgIndex.tcl
@@ -0,0 +1,108 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# Tcl package index file, version 1.1
+# This file is generated by the "pkg_mkIndex" command
+# and sourced either when an application starts up or
+
+
+
+
+# by a "package unknown" script.  It invokes the
+# "package ifneeded" command to set up package-related
+# information so that packages will be loaded automatically
+# in response to "package require" commands.  When this
+# script is sourced, the variable $dir must contain the
+# full path name of this file's directory.
+
+# 	$Id: pkgIndex.tcl,v 1.2 2004/02/26 21:29:59 xenios Exp xenios $	
+
+
+# -------------------------------------------------------
+# Itcl stuff -- new versions of everything
+# -------------------------------------------------------
+package ifneeded pxitclsubjectentry  1.0 [list source [file join $dir pxitclsubjectentry.tcl]] 
+package ifneeded pxitcllistselector  1.0 [list source [file join $dir pxitcllistselector.tcl]] 
+
+package ifneeded pxitclbasecontrol 1.0 [list source [file join $dir pxitclbasecontrol.tcl]] 
+package ifneeded pxitclbaseimagecontrol 1.0 [list source [file join $dir pxitclbaseimagecontrol.tcl]] 
+package ifneeded pxitclbaseimageviewer 1.0 [list source [file join $dir pxitclbaseimageviewer.tcl]]
+package ifneeded pxitcloverlaytool 1.0 [ list source [file join $dir pxitcloverlaytool.tcl]]
+
+package ifneeded pxitclfilelistmenu 1.0 [list source [file join $dir pxitclfilelistmenu.tcl]]
+package ifneeded pxitclHistogramWidget 1.0 [ list source [ file join $dir pxitclHistogramWidget.tcl ]]
+package ifneeded pxitclLandmarkControl 1.0 [ list source [ file join $dir pxitclLandmarkControl.tcl ]]
+package ifneeded pxitclPolyDataControl 1.0 [ list source [ file join $dir pxitclPolyDataControl.tcl ]]
+package ifneeded pxitclElectrodeMultiControl 1.0 [ list source [ file join $dir pxitclElectrodeMultiControl.tcl ]]
+
+package ifneeded pxitclimagenormalization 1.0 [ list source [ file join $dir pxitclimagenormalization.tcl ]]
+package ifneeded pxitclimageimport 1.0 [ list source [ file join $dir pxitclimageimport.tcl ]]
+
+package ifneeded pxitclatlasgadget   1.0 [list source [file join $dir pxitclatlasgadget.tcl]] 
+package ifneeded pxitclwfuatlasgadget   1.0 [list source [file join $dir pxitclwfuatlasgadget.tcl]] 
+package ifneeded pxitclyaleatlasgadget   1.0 [list source [file join $dir pxitclyaleatlasgadget.tcl]] 
+package ifneeded pxitclanimationgadget   1.0 [list source [file join $dir pxitclanimationgadget.tcl]] 
+package ifneeded pxitcldistributiontablegadget   1.0 [list source [file join $dir pxitcldistributiontablegadget.tcl]] 
+package ifneeded pxitclbrainstrip    1.1 [list source [file join $dir pxitclbrainstrip.tcl]] 
+package ifneeded pxitclexpfit        1.0 [list source [file join $dir pxitclexpfit.tcl]] 
+package ifneeded pxitclcsigadget 1.0 [ list source [ file join $dir pxitclcsigadget.tcl ]] 
+package ifneeded pxitclvvlinkgadget 1.0 [ list source [ file join $dir pxitclvvlinkgadget.tcl ]]
+package ifneeded pxitclvvlinkprojectorgadget 1.0 [ list source [ file join $dir pxitclvvlinkprojectorgadget.tcl ]]
+package ifneeded pxitclopenigtlinkgadget 1.0 [ list source [ file join $dir pxitclopenigtlinkgadget.tcl ]]
+package ifneeded pxitclsplineobjectmap 1.0 [ list source [ file join $dir pxitclsplineobjectmap.tcl ]]
+package ifneeded pxitclsplinestackobjectmap 1.0 [ list source [ file join $dir pxitclsplinestackobjectmap.tcl ]]
+package ifneeded pxitclcreatesolidcontrol 1.0 [ list source [ file join $dir pxitclcreatesolidcontrol.tcl ]]
+
+package ifneeded pxitclmultisubjectaverage 1.0 [ list source [ file join $dir pxitclmultisubjectaverage.tcl ]]
+
+package ifneeded pxitclrpm  1.0 [list source [file join $dir pxitclrpm.tcl]] 
+package ifneeded pxitclarticulatedmodel  1.0 [list source [file join $dir pxitclarticulatedmodel.tcl]] 
+package ifneeded pxitclsurfaceobjectmap  1.0 [list source [file join $dir pxitclsurfaceobjectmap.tcl]] 
+package ifneeded pxitclmanualsurfacetransformation  1.0 [list source [file join $dir pxitclmanualsurfacetransformation.tcl]] 
+package ifneeded pxitclmousechopper  1.0 [list source [file join $dir pxitclmousechopper.tcl]] 
+package ifneeded pxitclmeshgen  1.0 [list source [file join $dir pxitclmeshgen.tcl]] 
+package ifneeded pxitclsurobj  1.0 [list source [file join $dir pxitclsurfaceobjectmap.tcl]] 
+package ifneeded bis_fmrisetup  1.0 [list source [file join $dir bis_fmrisetup.tcl]] 
+package ifneeded bis_fmri  1.0 [list source [file join $dir bis_fmri.tcl]] 
+package ifneeded bis_databasetool  1.0 [list source [file join $dir bis_databasetool.tcl]] 
+package ifneeded bis_realtimefmri  1.0 [list source [file join $dir bis_realtimefmri.tcl]]
+package ifneeded bis_parameterGUI  1.0 [list source [file join $dir bis_algorithmdatabaseGUI.tcl]]
+
+
+# ---------------------------------------------------------
+# Major Viewers
+# ---------------------------------------------------------
+package ifneeded pxitclbaseimageviewer  1.0 [list source [file join $dir pxitclbaseimageviewer.tcl]] 
+package ifneeded pxitclsurfaceeditor  1.0 [list source [file join $dir pxitclsurfaceeditor.tcl]] 
+package ifneeded pxitclbrainregister  1.0 [list source [file join $dir pxitclbrainregister.tcl]] 
+package ifneeded pxitclmouseregister  1.0 [list source [file join $dir pxitclmouseregister.tcl]] 
+package ifneeded pxitclbase4dimageviewer  1.0 [list source [file join $dir pxitclbase4dimageviewer.tcl]] 
+package ifneeded pxitclelectrodeeditor  1.0 [list source [file join $dir pxitclelectrodeeditor.tcl]] 
+
+package ifneeded pxitclmanualtransformation 1.0 [ list source [ file join $dir pxitclmanualtransformation.tcl ]]
+package ifneeded alarkutility 1.0 [list source [file join $dir alarkutility.tcl]]
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitcl4dsurfaceeditor.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitcl4dsurfaceeditor.tcl
new file mode 100755
index 0000000..2adf63e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitcl4dsurfaceeditor.tcl
@@ -0,0 +1,325 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitcl4dsurfaceeditor.tcl,v 1.3 2003/09/03 13:59:52 xenios Exp xenios $	
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package provide pxitcl4dsurfaceeditor 1.0
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+package require pxtclutil 1.0
+package require vtkpxcontrib  1.1
+package require pxitclbase4dimageviewer 1.0
+
+# -----------------------------------------------------
+#  Intialize Variables
+# -----------------------------------------------------
+itcl::class pxitcl4dsurfaceeditor {
+
+    inherit pxitclbase4dimageviewer 
+
+    protected variable splinestackcontrol 0
+    protected variable splineeditor       0 
+    public    variable gui_splineeditor   0
+    public    variable gui_masterframe    0
+    public    variable gui_masterslice    0
+    public    variable gui_currentframe   0
+    public    variable gui_currentslice   0
+
+
+    constructor { par } {
+	::pxitclbase4dimageviewer::constructor $par
+    } {
+	Initialize4dsurfaceeditor
+    }
+    
+    private method Initialize4dsurfaceeditor { }
+    public method SetImageFromObject { this obj } 
+    
+    # Callback Handling
+    public method FrameChangedCallback { } 
+    public method SliceChangedCallback { } 
+    public method UpdateMasterFrame    { } 
+    public method CreateMasterFrame { w }
+    public method UpdateFromMasterFrame { mode }
+
+    # Display Initialization 
+    protected method InitializeViewer  {  } 
+    public    method InitializeDisplay { widg standalone } 
+
+
+
+    # Get Surface from Spline Stack Control
+    public    method GetSurface       { index } 
+    public    method GetCurrentFrame  { } 
+    public    method GetNumberOfFrames { } 
+    public    method SetCurrentFrame  { index } 
+
+
+    public    method CacheAllFrames { }
+}
+# -----------------------------------------------------
+itcl::body pxitcl4dsurfaceeditor::Initialize4dsurfaceeditor { } {
+
+    set appname "BioImage Suite::4D Surface Editor"
+
+    set splinestackcontrol [ vtkpxGUI4DSplineStackControl [ pxvtable::vnewobj ]]
+    set splineeditor  [ vtkpxGUISplineEditor [ pxvtable::vnewobj ]]
+    $splineeditor SetSlaveMode 1
+
+
+    if { $normalize_anatomical  == 1 } {
+	$splineeditor SetPresetLookupTableMode 0
+    } else {
+	$splineeditor SetPresetLookupTableMode -1
+    }
+    $splinestackcontrol SetSplineEditor $splineeditor
+
+
+    set enable_headercontrol   1
+    set enable_polydatacontrol 0
+    set enable_overlaytool     0
+}
+    
+# ---------------------------------------------------------------------------------
+#  GUI Stuff 
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitcl4dsurfaceeditor::SetImageFromObject { img obj } {
+
+    set a [ pxitclbase4dimageviewer::SetImageFromObject $img $obj ]
+    if { $a==0 } { return 0 }
+
+    set numf [ [ $currentimage GetImage  ] GetNumberOfScalarComponents ]
+    set numsl [ lindex [  [ $currentimage GetImage  ] GetDimensions ] 2 ]
+    catch { $thisparam($this,gui_masterframe) configure -from 1 -to $numf }
+    catch { $thisparam($this,gui_masterslice) configure -from 0 -to [expr $numsl -1 ] }
+    
+    if { $splinestackcontrol != 0 } {
+	$splineeditor LinkLookupTable [ $vtk_viewer GetLookupTable ]
+	$splinestackcontrol SetImage [ $currentimage GetImage ] [ $currentimage GetOrientation ] 0 0
+    }
+	
+    UpdateMasterFrame
+
+
+
+
+}
+    
+# ---------------------------------------------------------------------------------
+#  Update Stuff -- for change frame communication between image and splinestack
+# ---------------------------------------------------------------------------------
+itcl::body pxitcl4dsurfaceeditor::GetCurrentFrame  { } {
+    return [ $vtk_viewer GetCurrentFrame]
+}
+
+
+itcl::body pxitcl4dsurfaceeditor::GetNumberOfFrames  { } {
+    return [ $vtk_viewer GetNumberOfFrames]
+}
+
+
+itcl::body pxitcl4dsurfaceeditor::SetCurrentFrame  { index } {
+    $vtk_viewer SetCurrentFrame $index
+}
+
+itcl::body pxitcl4dsurfaceeditor::GetSurface { index } {
+    return [ $splinestackcontrol GetSplineStack $index ]
+}
+
+
+itcl::body pxitcl4dsurfaceeditor::FrameChangedCallback { } {
+
+    set fr [ $vtk_viewer GetCurrentFrame]
+    $splinestackcontrol SetCurrentFrame $fr
+    $tstackcontrol SetCurrentFrame $fr
+    $abaquscontrol SetCurrentFrame $fr
+    UpdateMasterFrame
+}
+
+itcl::body pxitcl4dsurfaceeditor::InitializeViewer {  } {
+
+    if { $vtk_viewer ==0 } { return }
+
+    set vframe [ frame $viewerbase.left ]
+    set note $viewerbase.notebook
+    iwidgets::tabnotebook $note -tabpos n
+    pack $note -side right -expand f -fill y
+    pack $vframe -side left -expand true -fill both
+
+    set cframe [ $note add -label "Image" ] 
+    set dframe [ $note add -label "Surface" ] 
+    set eframe [ $note add -label "Multi" ] 
+    set fframe [ $note add -label "Segment" ] 
+
+    $note view "Surface"
+
+    set vr [ $vtk_viewer Initialize $vframe $cframe 1 ]
+    $splinestackcontrol SetNumberOfSplineStacks $numberofsurfaces
+    set ct [ $splinestackcontrol Initialize $dframe $eframe $fframe 1 ]
+
+    $vtk_viewer SetEnableFrameChangeCallback 1
+    eval "$vtk_viewer SetFrameChangeCallback \"$this FrameChangedCallback\" "
+
+    $splineeditor SetNumberOfSplines $numberofsurfaces
+
+    set gui_splineeditor [ $splineeditor Initialize $viewerbase 0 ]
+    wm title $gui_splineeditor "Spline Editor"
+    wm geometry $gui_splineeditor 650x650
+
+    eval "$splineeditor SetSliceChangeCallback \"$this UpdateMasterFrame\" "
+
+    set cn [ $vtk_viewer InitializeMovieControl $basewidget 0 ]
+    eval "bind all <Control-m> { wm deiconify $cn} "
+
+    SetControlsViewer $vtk_viewer $splinestackcontrol
+    $splinestackcontrol SetBaseViewer $vtk_viewer
+}
+
+# ---------------------------------------------------------------------------------
+#  Initialize Display Stuff
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitcl4dsurfaceeditor::InitializeDisplay { widg st } {
+    
+    if { $initialized == 1 } { return $basewidget }
+
+    ::pxitclbase4dimageviewer::InitializeDisplay $widg $st
+    $tstackcontrol SetNumberOfTriangulatedStacks $numberofsurfaces
+
+
+    #    menubutton $menubase.edit -text "Edit Surface"   -menu $menubase.edit.m -underline 0
+    set mb [ menu $menubase.editm -tearoff 0 ]
+    #    pack $menubase.edit -side left
+    $menubase add cascade -label "Edit Surface" -menu $mb -underline 0
+
+    eval "$mb add command -label \"Spline Editor \" -command {  wm deiconify $gui_splineeditor }"
+    $mb add separator
+    eval "$mb add command -label \"Cache All Frames\" -command { $this CacheAllFrames }"
+
+    eval "bind all <Control-e> { wm deiconify $gui_splineeditor }"
+
+    set masterframe [ frame $basewidget.[pxvtable::vnewobj ] -relief raised]
+    set masterframe2 [ frame $basewidget.[pxvtable::vnewobj ] ]
+    set masterframe3 [ frame $basewidget.[pxvtable::vnewobj ] ]
+    $masterframe2 configure -height 2 -bg black
+    $masterframe3 configure -height 2 -bg black
+    pack $masterframe3 $masterframe $masterframe2 -side bottom -expand f -fill x
+    CreateMasterFrame $masterframe
+
+    eval "button $masterframe.edit  -text Edit -command  {  wm deiconify $gui_splineeditor }"
+    pack $masterframe.edit -side right -padx 2
+
+    wm geometry $basewidget 800x605
+    CreateHelpMenu
+}
+
+
+itcl::body pxitcl4dsurfaceeditor::CacheAllFrames { } {
+
+    set nf [ $this GetNumberOfFrames ]
+    WatchOn
+    for { set i 0 } { $i < $nf } { incr i } {
+	flush stdout
+	$this SetCurrentFrame $i
+	ShowProgressVal "Initializing Frame [ expr $i+1 ] / $nf" [  expr ($i +1.0 )/$nf ]
+    }
+    ShowProgressVal "Done" 1.0
+    WatchOff
+}
+
+itcl::body pxitcl4dsurfaceeditor::UpdateMasterFrame {  } {
+
+    set thisparam($this,gui_currentframe) [ expr [  $vtk_viewer GetCurrentFrame ] +1 ]
+    set thisparam($this,gui_currentslice) [ $splineeditor GetBeginSlice ]
+    set coord [ $vtk_viewer GetLastClickedPoint ]
+    $vtk_viewer SetCoordinates [ expr int([ lindex $coord 0 ]) ] [ expr int([ lindex $coord 1 ])] $thisparam($this,gui_currentslice)  0
+
+}
+
+itcl::body pxitcl4dsurfaceeditor::UpdateFromMasterFrame { mode  } {
+
+    if { $mode == 1 } {
+	$vtk_viewer SetCurrentFrame [ expr $thisparam($this,gui_currentframe) -1 ]
+	return
+    } 
+    
+    if { $mode == 2 } {
+	$splineeditor SetEnableSliceChangeCallback 0
+	$splineeditor SetSlice  $thisparam($this,gui_currentslice) 
+	$splineeditor SetEnableSliceChangeCallback 1
+    }
+
+}
+
+itcl::body pxitcl4dsurfaceeditor::CreateMasterFrame { w } {
+
+    label $w.0 -text "Frame:"
+    set thisparam($this,gui_masterframe)  [ scale $w.s0 -orient horizontal -resolution 1 -showvalue 1 -variable [ itcl::scope thisparam($this,gui_currentframe) ]  ]
+
+    label $w.1 -text "Slice:"
+    set thisparam($this,gui_masterslice)  [ scale $w.s1 -orient horizontal -resolution 1 -showvalue 1 -variable [ itcl::scope thisparam($this,gui_currentslice) ]  ]
+
+    pack $w.0 $w.s0 $w.1 $w.s1 -side left -expand f -padx 2
+
+    eval "bind $thisparam($this,gui_masterframe) <ButtonRelease> \"$this UpdateFromMasterFrame 1\" "
+    eval "bind $thisparam($this,gui_masterslice) <ButtonRelease> \"$this UpdateFromMasterFrame 2\" "
+    
+
+}
+
+
+# ---------------------------------------------------------------------
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    wm withdraw .    
+    set imp [ pxitcl4dsurfaceeditor \#auto 0 ] 
+    $imp InitializeDisplay .a 1
+    $imp ShowWindow
+    if { $argc > 0 } {  
+	set ok [ $imp LoadImage [lindex $argv 0]  ] ; 
+	if { $ok > 0 } {
+	    # $imp CacheAllFrames
+	}
+    }
+
+    [ $imp GetViewer ] SetEnableRendering 1
+    [ $imp GetViewer ] UpdateDisplay
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclElectrodeMultiControl.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclElectrodeMultiControl.tcl
new file mode 100644
index 0000000..31b0d04
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclElectrodeMultiControl.tcl
@@ -0,0 +1,1978 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclElectrodeMultiControl 1.0
+
+# 	$Id: pxitclElectrodeMultiControl.tcl,v 1.4 2004/02/17 20:58:26 xenios Exp xenios $	
+
+
+
+
+
+# Added some capability
+
+package require pxvtable 1.0
+package require Itcl
+package require Iwidgets 
+package require pxitclbasecontrol 1.0
+package require  labelframe 1.0
+package require  pxitcllistselector  1.0
+
+itcl::class pxitclElectrodeMultiControl {
+
+    inherit pxitclbasecontrol
+
+    protected variable man_xform 0
+    protected variable transform_control_1 0
+    protected variable transform_control_2 0
+    protected variable transform_control_3 0
+    protected variable function_selector 0
+    private variable vtk_viewer 0
+    private variable electrodemultigrid 0
+    private variable back_electrodemultigrid 0
+    private variable grid_actor
+    private variable opt_actor
+    private variable pick_actor
+    protected variable label_actor 0
+
+
+    private variable pick_actor_outline
+
+    private variable pick_sphere 0
+    private variable pick_sphere_outline 0
+    private variable last_picked_electrode -1
+    private variable grid_listbox 0
+    private variable update_location_button 0
+    private variable location_text 0
+
+    protected variable nomouseinput 0
+    private common   thisparam
+    protected variable initialized 0
+    protected variable fontname "{ fixed 8 }"
+    protected variable last_filename "multigrid.mgrid"
+    protected variable back_last_filename "none"
+
+    public variable batch_selector 0
+
+    private common functional_activations [ list "MotorFunction" "SensoryFunction" "VisualFunction" "LanguageFunction" "AuditoryFunction" "User1Function"  ]
+    private common electrical_activations [ list "SeizureOnset" "SpikesPresent" ]
+    private common other_attributes [ list "ElectrodePresent" ]
+    private common electrode_attributes 0
+
+    private variable last_radiobutton 0
+    public  variable maxelectrodes 16
+
+    private variable distance_array 0
+    
+    constructor { par } {
+	pxitclbasecontrol::constructor $par
+    } {
+	InitializeMultiGridControl
+    }
+
+    private method InitializeMultiGridControl { } 
+
+    public method SetNoMouseInput { } { set nomouseinput 1 }
+    public method Initialize { inpwidg viewer }
+    public method DelayedInitialize { }
+    protected method SetViewer  { viewer }
+
+
+    # -------------------------------------
+
+    # Create User Interface Stuff
+    # -------------------------------------
+    protected method CreateMenu { menubar }
+    protected method CreateGridPropertySheet { par }
+    protected method CreateElectrodePropertySheet { par }
+    protected method CreatePatientPropertySheet { par }
+    protected method CreateTransformControl { par }
+
+    # --------------------------------------
+    # Update Inteface Stuff
+    # --------------------------------------
+    public method UpdateInterface { }
+    public method UpdateElectrodePropertySheet { }
+    public method UpdateGridPropertySheet { }
+    public method UpdatePatientPropertySheet { }
+    public method UpdateVolumeTrace { }
+    public method ApplyTransformations { mode }
+    public method GetMultiGrid { } { [ return $electrodemultigrid ] }
+    public method GetLastFilename { } { [ return $last_filename ] }
+    # ----------------------------------------
+    # Patient Callbacks
+    # ----------------------------------------
+    public method UpdatePatient { }
+    public method UpdatePatientProperties { }
+    public method SelectElectrodeGrid { index } 
+    public method AddNewElectrodeGrid { }
+    public method DeleteCurrentElectrodeGrid { }
+    # ----------------------------------------
+    # Grid Callbacks
+    # ----------------------------------------
+    public method UpdateElectrodeGridProperties { }
+    public method SelectElectrode { } 
+    public method ElectrodeShowValues { }
+    public method CenterOnElectrode { mode } 
+    public method GridColor { } 
+    public method LabelsColor { } 
+    public method ReorientGrid { mode } 
+    public method PickFunction { }
+    public method PickAndDisplayFunction { }
+    public method ShowValues { }
+    public method AutoWarp { mode }
+
+    # ----------------------------------------
+    # Electrode Callbacks
+    # ----------------------------------------
+    public method UpdateElectrodeProperties { }
+    public method UpdateElectrodeLocationFromText { }
+
+    # ----------------------------------------
+    # Menu/Mouse Callbacks
+    # ----------------------------------------
+    public method HandleClickedPoint { x y z mouse stat }
+    public method PickElectrode { index args } 
+    public method MovePickedElectrode { x y z} 
+    public method ReleaseElectrodePick { args } 
+
+    public method UndoMoveElectrode { }
+    public method ShowGrids { mode }
+    public method SelectGridsToDisplay { }
+    public method ShowLabels { mode }
+    public method DisableElectrodePropertySheet { }
+    # -----------------------------------
+    # Load and Save Stuff
+    # -----------------------------------
+    public method LoadElectrodeMultiGrid { fname }
+    public method SaveElectrodeMultiGrid { fname }
+    public method AutoSaveMultiGrid { mode }
+    public method EnableAutoSave { }
+    public method ExportAsSurface { fname }
+    public method ExportPickedFunction { fname mode }
+    public method ExportAsPixelImage { fname }
+
+    # ---------------------------------------
+    # Last File Name
+    # ---------------------------------------
+    public method SetLastFilename { f } { set last_filename $f }
+    
+
+}
+# -------------------------------------------------------------------------------------------    
+::itcl::body pxitclElectrodeMultiControl::InitializeMultiGridControl { }  {
+
+    global tcl_platform
+    if { $tcl_platform(platform) == "windows" } {
+	set fontname "{ fixed 5 }"
+    } else {
+	set fontname "{ fixed 8 }"
+    }
+
+    set electrodemultigrid [ vtkpxElectrodeMultiGridSource [ pxvtable::vnewobj ]]
+    set back_electrodemultigrid [ vtkpxElectrodeMultiGridSource [ pxvtable::vnewobj ]]
+    set distance_array [ vtkFloatArray [ pxvtable::vnewobj ]]
+    $distance_array SetNumberOfTuples 4
+    $distance_array FillComponent 0 -1.0
+    $electrodemultigrid InitializeMultiGrid 1
+
+    for { set i 0 } { $i <=3 } { incr i } {
+	set grid_actor($i) 0
+	set pick_actor($i) 0
+	set opt_actor($i) 0
+	set pick_actor_outline($i) 0
+    }
+
+    set thisparam($this,autosave) 1
+    set thisparam($this,autosaveon) 0
+    set thisparam($this,visible) "current"
+    set thisparam($this,visiblelines) 1
+    set thisparam($this,current_grid) 0 
+    set thisparam($this,current_electrode) 0 
+    set thisparam($this,current_electrode_index) 1
+    set thisparam($this,current_position) "0.0 0.0 0.0"
+    set thisparam($this,auto_pick)  0
+    set thisparam($this,readonly) 2
+    set thisparam($this,showlabels) 0
+    set thisparam($this,showlabelsgap) 1
+    set thisparam($this,pick_frame) 0
+    set thisparam($this,electrodepropertylist) ""
+    set thisparam($this,volume_voi_size) 10
+    set thisparam($this,volume_weighted_voi) 0
+    set thisparam($this,griduniformcolor) 1
+    set electrode_attributes [ concat $functional_activations $electrical_activations $other_attributes ]
+    set thisparam($this,current_electrode_radio) 0
+
+}
+  
+   
+# Sets the input
+::itcl::body pxitclElectrodeMultiControl::SetViewer { viewer } {
+
+    if { $vtk_viewer != 0 } {
+	return 0
+    }
+
+    if { [ $viewer IsA vtkpxGUIOrthogonalViewer ] == 0 } {
+	return 0
+    }
+
+    set vtk_viewer $viewer
+    $vtk_viewer SetTraceVolumeVOI $thisparam($this,volume_voi_size)
+    $vtk_viewer SetTraceVolumeWeightedMode $thisparam($this,volume_weighted_voi) 
+
+    set pick_sphere [ vtkpxCrossHairSource [ pxvtable::vnewobj ]]
+    set pick_sphere_outline [ vtkpxCrossHairSource [ pxvtable::vnewobj ]]
+
+    
+    for { set i 0 } { $i <= 3 } { incr i } {
+
+	set map [ vtkPolyDataMapper [ pxvtable::vnewobj ]]
+	$map SetInput [ $electrodemultigrid GetOutput ]
+	
+	set map2 [ vtkPolyDataMapper [ pxvtable::vnewobj ]]
+	$map2 SetInput [ $pick_sphere GetOutput ]
+
+	set map3 [ vtkPolyDataMapper [ pxvtable::vnewobj ]]
+	$map3 SetInput [ $pick_sphere_outline GetOutput ]
+
+	set map4 [ vtkPolyDataMapper [ pxvtable::vnewobj ]]
+	$map4 SetInput [ $pick_sphere_outline GetOutput ]
+
+
+	set grid_actor($i) [ vtkActor [ pxvtable::vnewobj ]]
+	$grid_actor($i) SetMapper $map
+	$map Delete
+
+
+	set opt_actor($i) [ vtkActor [ pxvtable::vnewobj ]]
+	$opt_actor($i) SetMapper $map4
+	$map4 Delete
+       
+	set pick_actor($i) [ vtkActor [ pxvtable::vnewobj ]]
+	$pick_actor($i) SetMapper $map2
+	$map2 Delete
+       
+	set pick_actor_outline($i) [ vtkActor [ pxvtable::vnewobj ]]
+	$pick_actor_outline($i) SetMapper $map3
+	$map3 Delete
+       
+
+	[ [ $vtk_viewer GetRenderer $i ] GetRenderer ]  AddActor $grid_actor($i)
+	[ [ $vtk_viewer GetRenderer $i ] GetRenderer ]  AddActor $opt_actor($i)
+	[ [ $vtk_viewer GetRenderer $i ] GetRenderer ]  AddActor $pick_actor($i)
+	[ [ $vtk_viewer GetRenderer $i ] GetRenderer ]  AddActor $pick_actor_outline($i)
+
+	$opt_actor($i) SetVisibility 0
+	$pick_actor($i) SetVisibility 0
+	$pick_actor_outline($i) SetVisibility 0
+	[ $pick_actor($i) GetProperty ] SetColor 1 0 0
+	[ $pick_actor_outline($i) GetProperty ] SetColor 1 1 0
+	[ $pick_actor($i) GetProperty ] SetSpecularPower 0.5
+	[ $pick_actor_outline($i) GetProperty ] SetSpecularPower 0.5
+
+	if { $thisparam($this,visible) == "none" } {
+	     $grid_actor($i) SetVisibility 0
+	} 
+	
+	if { $i < 3 } {
+	    [ $grid_actor($i) GetProperty] SetRepresentationToWireframe
+	    [ $grid_actor($i) GetProperty ] SetAmbient 1.0 
+	    [ $grid_actor($i) GetProperty ] SetDiffuse 0.0
+	    [ $grid_actor($i) GetProperty ] SetOpacity 1.0
+	    [ $grid_actor($i) GetProperty ] SetLineWidth 2.0
+	} else {
+	    [ $grid_actor($i) GetProperty ] SetLineWidth 3.0 
+	}
+	
+	[ $pick_actor($i) GetProperty ] SetLineWidth 2.0
+	[ $pick_actor($i) GetProperty] SetRepresentationToWireframe
+	[ $pick_actor($i) GetProperty ] SetAmbient 1.0 
+	[ $pick_actor($i) GetProperty ] SetDiffuse 0.0
+	[ $pick_actor($i) GetProperty ] SetOpacity 1.0
+	
+	[ $pick_actor_outline($i) GetProperty ] SetLineWidth 2.0
+	[ $pick_actor_outline($i) GetProperty] SetRepresentationToWireframe
+	[ $pick_actor_outline($i) GetProperty ] SetAmbient 1.0 
+	[ $pick_actor_outline($i) GetProperty ] SetDiffuse 0.0
+	[ $pick_actor_outline($i) GetProperty ] SetOpacity 1.0
+	
+    }
+
+     if { $label_actor == 0 } {
+
+	 $electrodemultigrid Update
+	 
+	 set thisparam($this,label_mapper) [ vtkLabeledDataMapper [ pxvtable::vnewobj ]]
+	 $thisparam($this,label_mapper) SetInput [ $electrodemultigrid GetLabelSurface ]
+	 $thisparam($this,label_mapper) SetLabelModeToLabelScalars
+	 #$thisparam($this,label_mapper) ShadowOn
+	 set label_actor [ vtkActor2D [ pxvtable::vnewobj ]]
+	 $label_actor SetMapper $thisparam($this,label_mapper)
+	 $label_actor SetVisibility 0
+
+	 # [ $label_actor GetProperty ] SetColor 0.8 0.8 0.0
+
+	 [ [ $vtk_viewer GetRenderer 3 ] GetRenderer ]  AddActor2D $label_actor
+     }
+
+    $viewer UpdateDisplay
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::Initialize { inpwidg viewer } {
+
+    global tcl_platform
+
+    if { $initialized } { return $basewidget } 
+
+    set basewidget [ toplevel $inpwidg ]
+    
+    if { $tcl_platform(platform) == "windows" } {
+	wm geometry $basewidget 680x730
+    } else {
+	wm geometry $basewidget 550x600
+    }
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    set initialized 1
+
+    SetViewer $viewer
+    return $basewidget
+
+}
+
+::itcl::body pxitclElectrodeMultiControl::DelayedInitialize { } {
+   
+    set last_filename ""
+    DisableElectrodePropertySheet
+
+
+    set function_selector [ pxitcllistselector \#auto $basewidget.[ pxvtable::vnewobj ] ]
+    $function_selector configure -singleoutput 1
+    
+
+    set menubar [ menu $basewidget.menubar ]; $basewidget configure -menu $menubar
+    set notebook $basewidget.notebook ; 
+    iwidgets::tabnotebook $notebook  -tabpos n  
+
+    #    pack $menubar -side top -expand false -fill x
+    pack $notebook -side top -expand true -fill both -pady 2 -padx 2
+    
+
+
+    set bottom [ $notebook add -label  "Patient Info" ]
+    set middle [ $notebook add -label  "Electrode Info" ]
+    
+    frame $middle.left -bg black ; frame $middle.right
+    pack $middle.right -side right -expand false -fill y -padx 2 -pady 2
+    pack $middle.left -side right -expand true -fill both -padx 2 -pady 2
+
+    CreateTransformControl $middle
+    CreateMenu $menubar
+    CreateGridPropertySheet $middle.left
+    CreateElectrodePropertySheet $middle.right
+    CreatePatientPropertySheet $bottom
+
+    set grid [ $electrodemultigrid GetElectrodeGrid 0 ]
+    $grid SetElectrodeSpacing 10.0 10.0
+    $grid SetRadius  2.0
+
+    UpdateInterface
+    $notebook view "Patient Info"
+    DisableElectrodePropertySheet
+
+    set batch_selector [ pxitcllistselector \#auto $basewidget.[ pxvtable::vnewobj ] ]
+    set fullyinitialized 1
+
+    set canvas [ [ $notebook component tabset ] component canvas ];     set l [ AddLogoLabel $canvas ];     pack $l -side right -padx 1 
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::CreateMenu { menubase } {
+
+    #menubutton $menubase.file -text "File"  -menu $menubase.file.m -underline 0
+    set mb [ menu $menubase.filem -tearoff 0 ]
+    #pack $menubase.file  -side left
+    $menubase add cascade -underline 0  -label File -menu $mb
+
+    eval "$mb add command -label Load -command { $this LoadElectrodeMultiGrid \"\" }"
+    eval "$mb add command -label Save -command { $this SaveElectrodeMultiGrid \"\" }"
+    $mb add separator
+    
+    $mb add cascade -underline 0  -label "Export" -menu $mb.cascade1
+    set casc1 [ menu $mb.cascade1 -tearoff 0  ]
+
+    eval "$casc1 add command -label \"Export Values As Text\" -command { $this ExportPickedFunction \"\" 0 }"
+    eval "$casc1 add command -label \"Export as Surface\" -command { $this ExportAsSurface \"\" }"
+    eval "$casc1 add command -label \"Export as Image (One Pixel per electrode)\" -command { $this ExportAsPixelImage \"\"  }"
+    eval "$casc1 add command -label \"Export Picked Function\" -command { $this ExportPickedFunction \"\" dopick }"
+    $mb add separator
+    eval "$mb add command -label Close -command { $this HideWindow }"
+
+    #    menubutton $menubase.edit -text "Edit"  -menu $menubase.editm -underline 0
+    #pack $menubase.edit  -side left
+    set mb [ menu $menubase.editm -tearoff 0 ]
+    $menubase add cascade -underline 0  -label Edit -menu $mb
+
+
+    eval "$mb add checkbutton -label \"Auto Save\" -variable [ itcl::scope thisparam($this,autosave) ] -command { $this EnableAutoSave}"
+    $mb add separator
+    eval "$mb add radiobutton -label \"Display Only Mode\" -command { $this DisableElectrodePropertySheet } -value 2 -variable [ itcl::scope thisparam($this,readonly) ]"
+    eval "$mb add radiobutton -label \"Only Edit Attributes\" -command { $this DisableElectrodePropertySheet } -value 1 -variable [ itcl::scope thisparam($this,readonly) ]"
+    if { $nomouseinput == 0 } {
+	eval "$mb add radiobutton -label \"Full Edit Mode\" -command { $this DisableElectrodePropertySheet } -value 0 -variable [ itcl::scope thisparam($this,readonly) ]"
+	$mb add separator
+	eval "$mb add command -label \"Undo Move Electrode\" -command { $this UndoMoveElectrode }"
+    }
+
+    #   menubutton $menubase.display -text "Display"  -menu $menubase.displaym -underline 0
+    #    pack $menubase.display  -side left
+    set mb [ menu $menubase.displaym -tearoff 0 ]
+    $menubase add cascade -underline 0  -label Display -menu $mb
+
+
+    set l [ list current all none some ]
+    set l2 [ list Current All None Some ]
+    for { set i 0 } { $i <=2 } { incr i } {
+	eval "$mb add radiobutton -label \"Show [ lindex $l2 $i]\" -command { $this ShowGrids [ lindex $l $i ] } -value [ lindex $l $i ] -variable [ itcl::scope thisparam($this,visible) ]"
+    }
+    eval "$mb add radiobutton -label \"Show [ lindex $l2 3]\" -command { $this SelectGridsToDisplay } -value [ lindex $l 3 ] -variable [ itcl::scope thisparam($this,visible) ]"
+    $mb add separator 
+    eval "$mb add checkbutton -label \"Show Grid Lines\" -command { $this ShowGrids -1 } -variable [ itcl::scope thisparam($this,visiblelines) ]"
+    eval "$mb add checkbutton -label \"Uniform Color Grids\" -command { $this ShowGrids -1 } -variable [ itcl::scope thisparam($this,griduniformcolor) ]"
+    $mb add separator
+    eval "$mb add command -label \"Pick and Display Image Function\" -command { $this PickAndDisplayFunction }"
+    $mb add separator
+    eval "$mb add command -label \"Show Attributes\" -command { $this ShowValues }"
+
+    set mb [ menu $menubase.gridm -tearoff 0 ]
+    $menubase add cascade -underline 0  -label Grid -menu $mb
+    #    menubutton $menubase.grid -text "Grid"  -menu $menubase.gridm -underline 0
+    #    set mb [ menu $menubase.gridm -tearoff 0 ]
+    #    pack $menubase.grid  -side left
+
+    eval "$mb add command -label \"Grid Color\" -command { $this GridColor }"
+    $mb add separator
+    eval "$mb add command -label \"Grid Flip X\" -command { $this ReorientGrid 1 }"
+    eval "$mb add command -label \"Grid Flip Y\" -command { $this ReorientGrid 2 }"
+    eval "$mb add command -label \"Grid Transpose\" -command { $this ReorientGrid 0 }"
+    $mb add separator
+    eval "$mb add command -label \"Transform Grid\" -command { wm deiconify $man_xform }"
+    $mb add separator
+    eval "$mb add command -label \"Auto Warp\" -command { $this AutoWarp 1 }"
+    eval "$mb add command -label \"Undo Auto Warp\" -command { $this AutoWarp 0 }"
+
+    #    menubutton $menubase.labels -text "Labels"  -menu $menubase.labelsm -underline 0
+    #    set mb [ menu $menubase.labelsm -tearoff 0 ]
+    #    pack $menubase.labels  -side left
+
+    set mb [ menu $menubase.labelm -tearoff 0 ]
+    $menubase add cascade -underline 0  -label Labels -menu $mb
+
+    eval "$mb add radiobutton -label \"Label Font 0\" -command  { $this ShowLabels 0  } -variable [ itcl::scope thisparam($this,showlabels) ] -value 0"
+    eval "$mb add radiobutton -label \"Label Font 6\" -command { $this ShowLabels 6  } -variable [ itcl::scope thisparam($this,showlabels) ] -value 6"
+    eval "$mb add radiobutton -label \"Label Font 8\" -command { $this ShowLabels 8  } -variable [ itcl::scope thisparam($this,showlabels) ] -value 8"
+    eval "$mb add radiobutton -label \"Label Font 10\" -command { $this ShowLabels 10 } -variable [ itcl::scope thisparam($this,showlabels) ] -value 10"
+    eval "$mb add radiobutton -label \"Label Font 12\" -command { $this ShowLabels 12 } -variable [ itcl::scope thisparam($this,showlabels) ] -value 12"
+    eval "$mb add radiobutton -label \"Label Font 16\" -command { $this ShowLabels 16 } -variable [ itcl::scope thisparam($this,showlabels) ] -value 16"
+    eval "$mb add radiobutton -label \"Label Font 24\" -command { $this ShowLabels 24 } -variable [ itcl::scope thisparam($this,showlabels) ] -value 24"
+    eval "$mb add radiobutton -label \"Label Font 32\" -command { $this ShowLabels 32 } -variable [ itcl::scope thisparam($this,showlabels) ] -value 32"
+    $mb add separator 
+    eval "$mb add radiobutton -label \"All Labels \" -command  { $this ShowLabels -1 } -variable [ itcl::scope thisparam($this,showlabelsgap) ] -value 0"
+    eval "$mb add radiobutton -label \"Skip 1\" -command { $this ShowLabels -1  } -variable [ itcl::scope thisparam($this,showlabelsgap) ] -value 1"
+    eval "$mb add radiobutton -label \"Skip 2\" -command { $this ShowLabels -1  } -variable [ itcl::scope thisparam($this,showlabelsgap) ] -value 2"
+    eval "$mb add radiobutton -label \"Skip 3\" -command { $this ShowLabels -1 } -variable [ itcl::scope thisparam($this,showlabelsgap) ] -value 3"
+    #    eval "$mb add checkbutton -label \"Label All Electrodes\" -command { $this ShowLabels -1 } -variable [ itcl::scope thisparam($this,showlabelsgap) ]"
+    $mb add separator 
+    eval "$mb add command -label \"Labels Color\" -command { $this LabelsColor }"
+
+    if { $nomouseinput == 0 } {
+	#menubutton $menubase.voltrace -text "Volume Trace"  -menu $menubase.voltracem -underline 0
+	#set mb [ menu $menubase.voltracem -tearoff 0 ]
+	#pack $menubase.voltrace  -side left
+	set mb [ menu $menubase.voltrace -tearoff 0 ]
+	$menubase add cascade -underline 0  -label "Volume Trace" -menu $mb
+
+
+	eval "$mb add checkbutton -label \"Weighted Centroid\" -variable [ itcl::scope thisparam($this,volume_weighted_voi) ] -command { $this UpdateVolumeTrace} "
+	$mb add separator
+	eval "$mb add radiobutton -label \"VOI Size 0\" -command { $this UpdateVolumeTrace} -value  0 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+	eval "$mb add radiobutton -label \"VOI Size 1\" -command { $this UpdateVolumeTrace} -value  1 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+	eval "$mb add radiobutton -label \"VOI Size 5\" -command { $this UpdateVolumeTrace} -value  5 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+	eval "$mb add radiobutton -label \"VOI Size 10\" -command { $this UpdateVolumeTrace} -value 10 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+	eval "$mb add radiobutton -label \"VOI Size 15\" -command { $this UpdateVolumeTrace} -value 15 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+	eval "$mb add radiobutton -label \"VOI Size 20\" -command { $this UpdateVolumeTrace} -value 20 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+	eval "$mb add radiobutton -label \"VOI Size 25\" -command { $this UpdateVolumeTrace} -value 25 -variable [ itcl::scope thisparam($this,volume_voi_size)]"
+    }
+
+    
+}
+# -------------------------------------------------------------------------------------------
+#
+# Transform Stuff
+#
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::CreateTransformControl { par } {
+
+    set man_xform [ toplevel $par.[ pxvtable::vnewobj  ] ]
+    eval "wm protocol $man_xform WM_DELETE_WINDOW { wm withdraw $man_xform }"
+    wm withdraw $man_xform
+    wm title $man_xform "Grid Transformation Control"
+
+    set topw [ frame $man_xform.1 ]
+    pack $topw -side top -expand f -fill x
+
+    set transform_control_1 [ [  pxitcltransformGUI \#auto ] GetThisPointer ]
+    $transform_control_1 configure -description "Postop CT --> Postop MR (Invert postopMR->postopCT)"
+    $transform_control_1 Initialize $topw.1
+
+    set transform_control_2 [ [  pxitcltransformGUI \#auto ] GetThisPointer ]
+    $transform_control_2 configure -description "Postop MR --> Preop MR (Invert PreopMR->PostopMR SLOW!)"
+    $transform_control_2 Initialize $topw.2
+
+    set transform_control_3 [ [  pxitcltransformGUI \#auto ] GetThisPointer ]
+    $transform_control_3 configure -description "Preop MR --> MRS"
+    $transform_control_3 Initialize $topw.3
+    
+    pack $topw.1 $topw.2 $topw.3 -side top -expand f -fill x -pady 2
+
+    set f [ frame $man_xform.4 ]
+    pack $man_xform.4 -side bottom -expand f -fill x
+    
+    eval "button $f.1 -text \"Transform\" -command { $this ApplyTransformations 1 }"
+    #eval "button $f.2 -text \"Transform 2\" -command { $this ApplyTransformations 2 }"
+    eval "button $f.3 -text \"Undo\" -command { $this ApplyTransformations  -1 }"
+    eval "button $f.4 -text \"Close\" -command { wm withdraw $man_xform }"
+    pack $f.4 -side right
+    pack $f.1  $f.3 -side left -padx 10
+    return $man_xform
+    
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::PickFunction { } {
+
+    set img [ $vtk_viewer GetImage ]
+    $electrodemultigrid PickFunction $img 
+
+    $electrodemultigrid Modified
+    $vtk_viewer UpdateDisplay
+    UpdateGridPropertySheet
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::ShowValues { } {
+
+    set l "None"
+    set n [ $electrodemultigrid GetNumberOfValues ]
+    for { set i 0 } { $i < $n } { incr i } {
+	lappend l "Attribute_[expr $i+1]"
+    }
+
+    
+    $batch_selector configure -singleoutput 1
+    $batch_selector Activate $l "" "Select which value index to display (only the first one will be used)" "Select Value Component To Display"
+    set sel [ $batch_selector GetSelectedIndices ]
+
+    if { [ llength $sel ] > 0 } {
+	set newv [ expr [ lindex $sel 0 ] -1 ]
+	puts stderr "Setting Current Value Index $newv ($sel)"
+	$electrodemultigrid SetCurrentValueIndex $newv
+    } else {
+	$electrodemultigrid SetCurrentValueIndex -1
+    }
+    
+    $electrodemultigrid Modified
+    $electrodemultigrid Update
+    $vtk_viewer UpdateDisplay
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::PickAndDisplayFunction { } {
+
+    set img [ $vtk_viewer GetImage ]
+    $electrodemultigrid PickFunction $img 
+    $electrodemultigrid SetElectrodeColorsFromFunction [ $vtk_viewer GetLookupTable ]
+    $electrodemultigrid Modified;	$thisparam($this,label_mapper) Modified
+    $vtk_viewer UpdateDisplay
+}
+   
+
+::itcl::body pxitclElectrodeMultiControl::ApplyTransformations { mode } {
+
+    if { $mode == 1 || $mode ==2} {
+	
+	set gen [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+	$gen Identity
+	$gen PostMultiply
+
+	for { set j 1 } { $j <= 3 } { incr j } {
+	    if { $j == 1 } {
+		set tc $transform_control_1
+	    } elseif { $j == 2 } {
+		set tc $transform_control_2
+	    } else {
+		set tc $transform_control_3
+	    }
+
+	    set xf [ $tc GetTransformation ]
+	    set tr [ $xf GetTransformation ]
+	    $gen Concatenate $tr 
+	    puts stdout "Concat Applying $j [ $xf cget -filename ] [ $tr GetClassName ]"
+	}
+	
+	$back_electrodemultigrid Copy $electrodemultigrid
+	
+	set back_last_filename $last_filename 
+	set ok [ $electrodemultigrid ApplyTransformation $gen 1 ]
+	$gen Delete
+	
+	set dname [ file dirname $last_filename ]
+	set tname "trans_[file tail $last_filename ]"
+	set last_filename [ file join $dname $tname ]
+	SetTitle "Electrode Control [ file tail $last_filename]"
+	UpdateInterface
+	$vtk_viewer UpdateDisplay
+    } elseif { $back_last_filename != "none" } {
+	$electrodemultigrid Copy $back_electrodemultigrid
+	set last_filename $back_last_filename 
+	SetTitle "Electrode Control [ file tail $last_filename]"
+	UpdateInterface
+	$vtk_viewer UpdateDisplay
+    }
+}
+
+# -------------------------------------------------------------------------------------------
+#
+# Pick and Edit Stuff 
+#
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::PickElectrode { index args } {
+    if { $thisparam($this,visible) == "none"  } {
+	return 0
+    }
+
+    set editing_mode 1
+    if { $thisparam($this,readonly) > 0 } {
+	if { $index >=0 } {
+	    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $index ]
+	    set thisparam($this,current_electrode) $index
+	    set thisparam($this,current_electrode_index) [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrodeRealIndex $index  ]
+	    set editing_mode 0
+	}
+    } else {
+	if { $last_picked_electrode != - 1 } {
+	    # Some Other Electrode is picked already release this first 
+	    return 0
+	}
+	
+	if { $index == - 1 } {
+	    set index $thisparam($this,current_electrode)
+	}
+    }
+
+    if { $index == -1 } {
+	puts stdout "Nothing to do!"
+	return 0
+    }
+
+    set egrid [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+    scan  [ $egrid GetDimensions ] "%d %d" dimx dimy
+    set dimt [ expr $dimx * $dimy ]
+
+    if { $index >= $dimt } {
+	return 0
+    }
+
+
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $index ]
+
+    if { $editing_mode == 1 } {
+	scan [ $electrode GetPosition ] "%f %f %f" px py pz
+	
+	if { [ llength $args ] == 3 } {
+	    set x [ lindex $args 0 ]
+	    set y [ lindex $args 1 ]
+	    set z [ lindex $args 2 ]
+	    set  r [ expr 2.0 * [ $electrode GetRadius ]]
+	} else {
+	    set x $px
+	    set y $py
+	    set z $pz
+	    set r 1.0
+	}
+
+	
+	$pick_sphere SetPosition $x $y $z
+	$pick_sphere SetLength $r
+	$pick_sphere_outline SetPosition $x $y $z
+	$pick_sphere_outline SetLength $r
+	
+	scan [ $electrode GetColor ] "%f %f %f" cx cy cz
+	
+	$pick_sphere Update
+	for { set i 0 } { $i <=3 } { incr i } {
+	    $pick_actor($i)  SetVisibility 1
+	    $pick_actor_outline($i)  SetVisibility 1
+	    [ $pick_actor($i) GetProperty ] SetColor $cz $cy $cz
+	    [ $pick_actor_outline($i) GetProperty ] SetColor $cz $cy $cz
+	}
+
+	$electrodemultigrid Update; $thisparam($this,label_mapper) Modified
+	$vtk_viewer UpdateDisplay
+	
+	set last_picked_electrode $index
+	set thisparam($this,current_electrode_index) [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrodeRealIndex $index ]
+	set thisparam($this,current_electrode) $last_picked_electrode
+	$thisparam($this,pick_frame) configure -bg red
+    }
+    $electrode StoreColorInColorName 
+    UpdateElectrodePropertySheet
+
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::MovePickedElectrode { x y z }  {
+
+    if { $last_picked_electrode == - 1 } {
+	return 0
+    }
+
+    $pick_sphere SetPosition $x $y $z
+    $pick_sphere Update
+    set thisparam($this,current_position) [ format "%.2f %.2f %.2f " $x $y $z ]
+
+    [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetNeighborDistances $thisparam($this,current_electrode) $distance_array $x $y $z
+    for { set i 0 } { $i <=3 } { incr i } {
+	set thisparam($this,current_distance_$i) [ format "%.2f" [ $distance_array GetComponent $i 0 ]]
+    }
+    
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::ReleaseElectrodePick { args } {
+
+    if { $last_picked_electrode == -1 } {
+	return 0
+    }
+    
+    # Hide Pick Actors
+    # ----------------
+    
+    for { set i 0 } { $i <=3 } { incr i } {
+	$pick_actor($i) SetVisibility 0
+	$pick_actor_outline($i) SetVisibility 0
+    }
+    $thisparam($this,pick_frame) configure -bg gray
+
+    if { [ llength $args  ] == 3 } {
+
+	set x [ lindex $args 0 ]
+	set y [ lindex $args 1 ]
+	set z [ lindex $args 2 ]
+
+	set egrid [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+	scan  [ $egrid GetDimensions ] "%d %d" dimx dimy
+	set dimt [ expr $dimx * $dimy ]
+	
+	if { $last_picked_electrode < $dimt } {
+	    
+	    set electrode [ $egrid GetElectrode $last_picked_electrode ]
+	    
+	    # Do undo stuff and then set position
+	    scan [ $electrode GetPosition ] "%f %f %f " ox oy oz ; $electrode SetPreviousPosition $ox $oy $oz
+	    $electrode SetPosition $x $y $z
+	    
+	    $egrid Modified
+	    $electrodemultigrid Modified;	$thisparam($this,label_mapper) Modified
+	    
+
+	}
+    }
+    
+    #$thisparam($this,label_mapper) SetInput [ $electrodemultigrid GetLabelSurface ]
+    $vtk_viewer UpdateDisplay
+    UpdateElectrodePropertySheet
+    set last_picked_electrode -1
+    
+    return 1
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::HandleClickedPoint { x y z mode stat } {
+
+    if { $thisparam($this,visible) == "none" } {
+	return 0
+    }
+
+    set ok 0
+    
+    if { $mode == 1 } {
+	if { $stat == 0 } {
+	    if { $last_picked_electrode == -1  } {
+		set index [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] FindClosestElectrodeIndex $x $y $z ]
+
+		if { $index >=0 } { 
+		    set ok [ PickElectrode $index $x $y $z  ]
+		}
+	    }
+	} 
+    }
+
+    if { $stat == 1 && $last_picked_electrode !=-1 } {
+	
+	set ok [ MovePickedElectrode $x $y $z ]
+	
+    } elseif { $stat == 2 && $last_picked_electrode !=-1 } {
+	
+	set ok [ ReleaseElectrodePick $x $y $z  ]
+	
+    }
+
+#     elseif  { $mode == 0 && $stat == 0 } {
+# 	set index [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] FindClosestElectrodeIndex $x $y $z ]
+# 	if { $index >=0 } {
+# 	    set thisparam($this,current_electrode) $index
+# 	    UpdateElectrodePropertySheet
+# 	    set ok 1
+# 	}
+#    }
+    
+    return $ok
+}
+# ---------------------------------------------------------------------------------------------
+# Callback Stuff
+# ---------------------------------------------------------------------------------------------
+
+itcl::body pxitclElectrodeMultiControl::LoadElectrodeMultiGrid { fname } {
+
+    if { $electrodemultigrid == 0 } {
+	return 0
+    }
+
+    if { $fname == "" } {
+	set typelist { 
+	    {"Electrode Grid Files" {".mgrid*" } }
+	    {"All Files" {*}}
+	}
+	
+	set f1 $last_filename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+
+	set fname [tk_getOpenFile -title "Load Electrode Multi Grid File" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    set ok [ $electrodemultigrid Load $fname ]
+    if { $ok > 0 } {
+	set last_filename $fname
+	#SetTitle "Electrode Control [ file tail $last_filename]"
+	DisableElectrodePropertySheet
+	UpdateInterface
+	SelectElectrodeGrid 0
+    }
+
+    return $ok
+}
+
+# -------------------------------------------------------------------------------------------
+itcl::body pxitclElectrodeMultiControl::SaveElectrodeMultiGrid { fname } {
+
+    if { $electrodemultigrid == 0 } {
+	return 0
+    }
+
+    if { $fname == "" } {
+	set typelist { 
+	    {"Electrode Grid Files" {".mgrid*" } }
+	    {"All Files" {*}}
+	}
+	
+	set f1 $last_filename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname [tk_getSaveFile -title "Save Electrode Multi Grid File" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    UpdatePatient
+ 
+    set ok [ $electrodemultigrid Save $fname ]
+
+    if { $ok > 0 } {
+	set last_filename $fname
+	SetTitle "Electrode Control [ file tail $last_filename]"
+    }
+    
+    return $ok
+}
+
+
+# -------------------------------------------------------------------------------------------
+itcl::body pxitclElectrodeMultiControl::EnableAutoSave { } {
+
+    if { $thisparam($this,autosave) == 0 } {
+	set thisparam($this,autosaveon) 0
+    } else {
+	AutoSaveMultiGrid once
+    }
+}
+
+itcl::body pxitclElectrodeMultiControl::AutoSaveMultiGrid { mode } {
+
+    if { $thisparam($this,autosaveon) == 1 && $mode =="once" } {
+	return 0
+    }
+
+    if { $thisparam($this,autosave) == 0 } {
+	set thisparam($this,autosaveon) 0
+	return 0
+    }
+
+    if { $last_filename == "" } {
+	set last_filename "autosave"
+    }
+
+    set l_filename "[ file root $last_filename]_autosave.mgrid"
+    
+    UpdatePatient
+
+    if { $thisparam($this,readonly) != 2 } {
+	set ok [ $electrodemultigrid Save $l_filename ]
+    } else {
+	set ok 1
+    }
+
+    if { $thisparam($this,autosaveon) == 0 } {
+	set thisparam($this,autosaveon) 1
+    }
+    
+    eval "after 30000  $this AutoSaveMultiGrid timer"
+
+    return $ok
+}
+# -------------------------------------------------------------------------------------------
+itcl::body pxitclElectrodeMultiControl::ExportAsSurface { fname } {
+
+    if { $electrodemultigrid == 0 } {
+	return 0
+    }
+
+    if { $fname == "" } {
+	set typelist { 
+	    {"VTK Surface Files" {".vtk" } }
+	    {"All Files" {*}}
+	}
+	
+	set l_filename "[ file root $last_filename].vtk"
+	set f1 $l_filename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname [tk_getSaveFile -title "Save Electrode Multi-Grid As Surface" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    $electrodemultigrid Update; $thisparam($this,label_mapper) Modified
+    set w [ vtkPolyDataWriter [ pxvtable::vnewobj ]]
+    $w SetInput [ $electrodemultigrid GetOutput ]
+    $w SetFileName $fname
+    $w Write
+    $w Delete
+}
+# -------------------------------------------------------------------------------------------
+itcl::body pxitclElectrodeMultiControl::ExportPickedFunction { fname mode } {
+
+    if { $electrodemultigrid == 0 } {
+	return 0
+    }
+
+    if { $fname == "" } {
+	set typelist { 
+	    {"Text Files" {".txt" } }
+	    {"All Files" {*}}
+	}
+	
+	set l_filename "[ file root $last_filename].txt"
+	set f1 $l_filename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname [tk_getSaveFile -title "Export picked function in text file" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    if { $mode == "dopick" } {
+	$this PickFunction
+    }
+
+    set ok [ $electrodemultigrid ExportValues $fname " " " " " "  ]
+    if { $ok == 0 } { 
+	::pxtclutil::Warning "Failed to export picked function in $fname"
+    }
+}
+# -------------------------------------------------------------------------------------------
+# Export as Pixel Image
+# -------------------------------------------------------------------------------------------
+itcl::body pxitclElectrodeMultiControl::ExportAsPixelImage { fname  } {
+
+    if { $electrodemultigrid == 0 } {
+	return 0
+    }
+
+    set l [ list "Location" "Epilepsy" "Any Function" "Motor Function" "Sensory Function" "Visual Function" "Language Function" "Auditory Function" "User1 Function"  ]
+    set n [ $electrodemultigrid GetNumberOfValues ]
+    for { set i 0 } { $i < $n } { incr i } {
+	lappend l "Attribute_[expr $i+1]"
+    }
+    
+    $function_selector configure -singleoutput 0
+    $function_selector Activate $l "Epilepsy" "The selected function will be used to generate the output label for the output pixel-image" "Select Output Label"
+    
+    set mode [ $function_selector GetSelectedIndices ]
+
+    puts stderr "Mode = $mode"
+    set numcomp [ llength $mode ]
+
+    if { $numcomp == 0 } {
+	return 0
+    }
+    
+    set arr [ vtkShortArray [ pxvtable::vnewobj ]]
+    $arr SetNumberOfTuples $numcomp
+    $arr FillComponent 0 0
+    
+    for { set i 0 } { $i < $numcomp } { incr i } {
+
+	set md [ lindex $mode $i ]
+	if { $md > 8 } { 
+	    set md [ expr $md + 11 ]
+	}
+	$arr SetComponent $i 0 $md
+    }
+    
+    set typelist { 
+	{"Analyze Image Files" {".hdr" } }
+	{"All Files" {*}}
+    }
+    
+    set l_filename "[ file root $last_filename].hdr"
+    set f1 $l_filename
+    set f1path [ file dirname $f1 ]
+    set f1tail [ file tail    $f1 ]
+    
+    set fname [tk_getSaveFile -title "Save Electrode Multi-Grid As Labeled Image" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    
+    if { [ string length $fname ] < 1 } {
+	$arr Delete
+	return 0
+    }
+
+    
+    WatchOn
+     update idletasks
+    set img [ $electrodemultigrid CreateSinglePixelImage $arr [ $vtk_viewer GetImage ] ]
+    set ana [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+    $ana SetInput $img
+    $ana SetOrientation [ $vtk_viewer GetOrientation ]
+    $ana Save $fname
+    $ana Delete
+    $img Delete
+    $arr Delete
+    WatchOff
+    
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::UpdateInterface { } {
+
+    UpdatePatientPropertySheet
+    UpdateGridPropertySheet
+    UpdateElectrodePropertySheet
+    AutoSaveMultiGrid once
+}
+
+::itcl::body pxitclElectrodeMultiControl::UpdatePatient { } {
+    UpdateElectrodePropertySheet
+    UpdateElectrodeGridProperties 
+    UpdatePatientProperties
+}
+
+
+::itcl::body pxitclElectrodeMultiControl::UpdateVolumeTrace { } {
+
+    catch { $vtk_viewer SetTraceVolumeVOI $thisparam($this,volume_voi_size) }
+    catch { $vtk_viewer SetTraceVolumeWeightedMode $thisparam($this,volume_weighted_voi) }
+    
+}
+
+# -------------------------------------------------------------------------------------------
+#
+#           Electrode Property Sheet
+#
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::CreateElectrodePropertySheet { par } {
+    
+    label $par.0 -text "Electrode Properties" -bg black -fg white 
+    pack $par.0 -side top -expand f -fill x -pady 2 -padx 2
+    
+    frame $par.1 ; pack $par.1 -side top
+    label $par.1.l -text "Grid/Electrode:"
+    entry $par.1.e -width 6 -textvariable [ itcl::scope thisparam($this,current_grid) ] -state disabled
+    label $par.1.l2 -text "/"
+    entry $par.1.e2 -width 6 -textvariable [ itcl::scope thisparam($this,current_electrode_index) ] -state disabled
+    pack $par.1.l $par.1.e $par.1.l2 $par.1.e2 -side left -expand f -fill x -pady 1
+
+    frame $par.11 ; pack $par.11 -side top
+    label $par.11.l -text "Position:"
+    entry $par.11.e -width 20 -textvariable [ itcl::scope thisparam($this,current_position) ] -state disabled
+    eval "button $par.11.f -text Upd -command { $this UpdateElectrodeLocationFromText } -state disabled"
+    set update_location_button $par.11.f
+    set location_text $par.11.e
+    pack $par.11.l $par.11.e $par.11.f -side left -expand f -fill x -pady 1
+
+    set w [frame $par.12 -bg darkgray ] ; pack $par.12 -side top -padx 2 -pady 2
+    set thisparam($this,pick_frame) $w
+
+
+    label $w.lab -text "Distances"
+    for { set i 0 } { $i <=3 } { incr i } {
+	entry $w.$i -width 8 -textvariable [ itcl::scope thisparam($this,current_distance_$i) ] -state disabled
+    }
+    
+    grid $w.lab -row 1 -column 1
+    grid $w.0 -row 1 -column 0
+    grid $w.1 -row 1 -column 2
+    grid $w.2 -row 0 -column 1
+    grid $w.3 -row 2 -column 1
+       
+
+    checkbutton $par.15 -text "Electrode Enabled" -variable [ itcl::scope thisparam($this,ElectrodePresent) ]  
+    lappend thisparam($this,electrodepropertylist) $par.15
+    eval "$par.15 configure -command  { $this UpdateElectrodeProperties }"
+    pack  $par.15 -side top -expand f -fill x -ipadx 2 -ipady 2
+
+    set thisparam(this,electrode_color) [ frame $par.17 -height 10 -bg white ]
+    pack $par.17 -side top -expand f -fill x -pady 5 -padx 10
+
+    set base  [ LabelFrame:create $par.center -text "Locate Viewer"]
+    pack $par.center -side top -expand f -fill x -pady 2
+    
+    eval "button $base.1 -text \"Cross Hairs\" -command { $this CenterOnElectrode 0 }"
+    eval "button $base.2 -text \"Clip Tight\" -command { $this CenterOnElectrode 1 }"
+    eval "button $base.3 -text \"Clip Wide\" -command { $this CenterOnElectrode 2 }"
+    pack $base.1 $base.2 $base.3 -side left -expand f -fill x -padx 2
+
+    set base  [ LabelFrame:create $par.2 -text "Functional Attributes"]
+    pack $par.2 -side top -expand f -fill x
+
+    for { set i 0 } { $i < [ expr [ llength $functional_activations ]/2 ] } { incr i } {
+	frame $base.$i ; pack $base.$i -side top -expand f -fill x -pady 0
+
+	for { set j 0 } { $j <=1 } { incr j } {
+	    set index [ expr $i * 2 + $j ]
+	    set l [ lindex $functional_activations $index ]
+	    set m [ string length $l ]
+	    set n [ string range $l 0 [ expr $m - 9 ]]
+	    eval "checkbutton $base.$i.m$n -text $n -variable [ itcl::scope thisparam($this,$l) ] -width 10"
+	    eval "$base.$i.m$n configure -command  { $this UpdateElectrodeProperties }"
+	    pack $base.$i.m$n -side left -expand f -fill x
+	    lappend thisparam($this,electrodepropertylist) $base.$i.m$n
+	}
+    }
+	
+    set base  [ LabelFrame:create $par.3 -text "Electrical Attributes"]
+    pack $par.3 -side top -expand f -fill x
+    checkbutton $base.1 -text "Seizure Onset" -variable [ itcl::scope thisparam($this,SeizureOnset) ] -width 10
+    checkbutton $base.2 -text "Spikes Present" -variable [ itcl::scope thisparam($this,SpikesPresent) ] -width 10
+    eval "$base.1 configure -command  { $this UpdateElectrodeProperties }"
+    eval "$base.2 configure -command  { $this UpdateElectrodeProperties }"
+    pack $base.1 $base.2 -side top -expand f -fill x
+    lappend thisparam($this,electrodepropertylist) $base.1
+    lappend thisparam($this,electrodepropertylist) $base.2
+
+    if { $nomouseinput == 0 } {
+	set base  [ LabelFrame:create $par.4 -text "Editing"]
+	pack $par.4 -side top -pady 2 -expand f -fill x
+	eval "checkbutton $base.auto -text \"Button Pick\"  -variable [ itcl::scope thisparam($this,auto_pick) ] -command { $this ReleaseElectrodePick }"
+	frame $base.p ; 
+	pack $base.auto $base.p -side top -expand t -fill x -padx 2
+	eval "button $base.p.set -text \"Pick Current\" -command { $this PickElectrode -1 }"
+	eval "button $base.p.can -text \"Release\" -command { $this ReleaseElectrodePick }"
+	pack $base.p.set $base.p.can  -side left -expand f -fill x -pady 2
+    }
+
+    eval "button $par.5 -text \"Show Values\" -command { $this ElectrodeShowValues }"
+    
+    pack $par.5  -side bottom -expand f -fill x -pady 2
+   
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::ElectrodeShowValues { } {
+
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $thisparam($this,current_electrode) ]
+    set values [ $electrode GetValues ]
+    set l "Electode $thisparam($this,current_electrode_index)\n"
+    if { [ $values GetNumberOfTuples ] == 0 } {
+	set l "Electrode has no values"
+    } else {
+	for { set i 0 } { $i < [ $values GetNumberOfTuples ] } { incr i } {
+	    lappend l "Comp [ expr $i +1 ]: [ $values GetComponent $i 0 ]"
+	}
+    }
+
+    ::pxtclutil::Info $l 
+
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::CenterOnElectrode { mode } {
+
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $thisparam($this,current_electrode) ]
+    scan [ $electrode GetPosition ] "%f %f %f" p(0) p(1) p(2)
+    set img [ $vtk_viewer GetImage ]
+    
+
+    $vtk_viewer SetScaledCoordinates $p(0) $p(1) $p(2)
+
+    if { $mode > 0  } {
+	# Clip Stuff Also
+
+	set camera [ [ [ $vtk_viewer GetRenderer 3 ] GetRenderer ] GetActiveCamera ]
+
+	scan [ $camera GetPosition ]  "%f %f %f" c(0) c(1) c(2)
+	scan [ $camera GetFocalPoint ] "%f %f %f" f(0) f(1) f(2)
+
+
+	for { set i 0 } { $i<=2} { incr i } {
+	    set d($i) [ expr $f($i) - $c($i) ]
+	    set p($i) [ expr $p($i) - $c($i) ]
+	}
+	set magn [ expr sqrt($d(0)*$d(0) + $d(1)*$d(1) + $d(2)*$d(2)) ]
+	
+	set dist 0.0
+	for { set i 0 } { $i<=2} { incr i } {
+	    set d($i) [ expr $d($i) / $magn ]
+	    set dist [ expr $dist +  $p($i)*$d($i) ]
+	}
+
+	set sp 5.0
+	if { $mode == 2 } {
+	    set sp 20.0
+	}
+
+	$camera SetClippingRange [ expr $dist - $sp ] [ expr $dist+$sp]
+	$vtk_viewer UpdateDisplay
+	    
+    }
+
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::UpdateElectrodeLocationFromText { } {
+    
+    if { $thisparam($this,readonly)  != 0 } {
+	return
+    }
+
+    set img [ $vtk_viewer GetImage ]
+    set dim [ $img GetDimensions ]
+    set spa [ $img GetSpacing ]
+    if { [ lindex $dim 0 ] < 2 } {
+	return
+    }
+
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $thisparam($this,current_electrode) ]
+
+    set lst $thisparam($this,current_position)
+    if { [ llength $lst ] != 3  } {
+	scan [ $electrode GetPosition ] "%f %f %f" px py pz
+	set thisparam($this,current_position) [ format "%.2f %.2f %.2f " $px $py $pz ]
+	return 
+    }
+
+    for { set i 0 } { $i <= 2 } { incr i } {
+	set x($i) [ lindex $lst $i ]
+	if { $x($i) < -1 } {
+	    set x($i) -1.0
+	} elseif { $x($i) > [ expr [ lindex $dim $i ]*[lindex $spa $i ] ] } {
+	    set x($i) [ expr [ lindex $dim $i ]*[lindex $spa $i ] ]
+	}
+    }
+    
+
+    scan [ $electrode GetPosition ] "%f %f %f " ox oy oz ; 
+    $electrode SetPreviousPosition $ox $oy $oz
+    $electrode SetPosition $x(0) $x(1) $x(2)
+    scan [ $electrode GetPosition ] "%f %f %f" px py pz
+    set thisparam($this,current_position) [ format "%.2f %.2f %.2f " $px $py $pz ]
+
+
+    [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] Modified
+    $electrodemultigrid Modified;	$thisparam($this,label_mapper) Modified
+
+    $this ReleaseElectrodePick
+    $vtk_viewer UpdateDisplay
+}
+
+# -------------------------------------------------------------------------------------------
+
+::itcl::body pxitclElectrodeMultiControl::UpdateElectrodeProperties { } {
+
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $thisparam($this,current_electrode) ]
+
+    for { set i 0 } { $i < [ llength $electrode_attributes ] } { incr i } {
+	set nm [ lindex $electrode_attributes $i ]
+	$electrode Set$nm $thisparam($this,$nm)
+    }
+    
+    [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] Modified
+    $electrodemultigrid Modified
+    [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] Modified
+    $electrodemultigrid Update; $thisparam($this,label_mapper) Modified
+
+    $electrode StoreColorInColorName
+    $thisparam(this,electrode_color) configure -bg [ $electrode GetColorName ]
+
+    set width [ lindex [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetDimensions ] 0 ]
+    set row [ expr round(floor($thisparam($this,current_electrode) / $width)) ]
+    set col [ expr round($thisparam($this,current_electrode)  - $width * $row) ]
+    set nm $thisparam($this,radio_${col}_${row})
+    $nm configure -bg [ $electrode GetColorName ] 
+
+    if { [ $electrode GetElectrodePresent ] == 0  } { 
+	ReleaseElectrodePick
+    }
+
+    $vtk_viewer UpdateDisplay
+    
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::UpdateElectrodePropertySheet { } {
+
+
+    set dim  [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetDimensions ]
+    set numelect [ expr [ lindex $dim 0 ] * [ lindex $dim 1 ]]
+
+    if { $thisparam($this,current_electrode) >= $numelect } {
+	set thisparam($this,current_electrode) 0
+    }
+
+
+    set thisparam($this,current_electrode_radio) $thisparam($this,current_electrode)
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $thisparam($this,current_electrode) ]
+    set thisparam($this,current_electrode_index) [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrodeRealIndex $thisparam($this,current_electrode) ]
+
+
+    for { set i 0 } { $i < [ llength $electrode_attributes ] } { incr i } {
+	set nm [ lindex $electrode_attributes $i ]
+	set thisparam($this,$nm) [ $electrode Get$nm  ]
+    }
+   
+    scan [ $electrode GetPosition ] "%f %f %f" px py pz
+    set thisparam($this,current_position) [ format "%.2f %.2f %.2f " $px $py $pz ]
+
+    [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetNeighborDistances $thisparam($this,current_electrode) $distance_array
+    for { set i 0 } { $i <=3 } { incr i } {
+	set thisparam($this,current_distance_$i) [ format "%.2f" [ $distance_array GetComponent $i 0 ]]
+    }
+
+    $electrode StoreColorInColorName
+    $thisparam(this,electrode_color) configure -bg [ $electrode GetColorName ]
+
+    set width [ lindex [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetDimensions ] 0 ]
+    set row [ expr round(floor($thisparam($this,current_electrode) / $width)) ]
+    set col [ expr round($thisparam($this,current_electrode)  - $width * $row) ]
+
+    set nms $thisparam($this,radio_${col}_${row})
+    $nms configure -relief ridge -highlightbackground black
+
+    if { $last_radiobutton != 0  && $last_radiobutton != $nms } {
+	$last_radiobutton configure -relief flat -highlightbackground gray
+    }
+    set last_radiobutton $nms
+    
+    
+}
+
+
+::itcl::body pxitclElectrodeMultiControl::UndoMoveElectrode { } {
+
+
+    set electrode [ [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] GetElectrode $thisparam($this,current_electrode) ]
+    scan [ $electrode GetPreviousPosition ] "%f %f %f " ox oy oz ; $electrode SetPreviousPosition $ox $oy $oz
+    $electrode SetPosition $ox $oy $oz
+    set thisparam($this,current_position) [ format "%.2f %.2f %.2f " $ox $oy $oz ]
+    [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ] Modified
+    $electrodemultigrid Modified
+    $vtk_viewer UpdateDisplay
+}
+
+
+# -------------------------------------------------------------------------------------------
+#
+#    Grid Property Sheet
+#
+# -------------------------------------------------------------------------------------------
+
+::itcl::body pxitclElectrodeMultiControl::CreateGridPropertySheet { basepar } {
+    
+    set wp  [ LabelFrame:create $basepar.1 -text "Grid Properties"]
+    pack $basepar.1 -side top -expand true -fill x -pady 2 -padx 2
+
+
+    checkbutton $wp.vis -text "Display Grid " -variable [ itcl::scope thisparam($this,current_grid_visible) ]  
+    eval "$wp.vis configure -command  { $this UpdateElectrodeGridProperties  }"
+    pack $wp.vis -side top -padx 5 -pady 2
+
+    set i 0
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l -text "Grid Name:"
+    entry $w.e -width 35 -textvariable [ itcl::scope thisparam($this,current_grid_name) ] -relief sunken
+    pack $w.l $w.e -side left -expand false -fill x -anchor w
+
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l1 -text "Dimensions:"
+    entry $w.e1 -width 3 -textvariable [ itcl::scope thisparam($this,current_grid_dimx) ] -relief sunken
+    entry $w.e2 -width 3 -textvariable [ itcl::scope thisparam($this,current_grid_dimy) ] -relief sunken
+    pack $w.l1 $w.e1 $w.e2 -side left -expand false -fill x -anchor w
+
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l3 -text "Nominal Spacing (mm):"
+    entry $w.e3 -width 3 -textvariable [ itcl::scope thisparam($this,current_grid_spx) ] -relief sunken
+    entry $w.e4 -width 3 -textvariable [ itcl::scope thisparam($this,current_grid_spy) ] -relief sunken
+    pack $w.l3 $w.e3 $w.e4 -side left -expand false -fill x -anchor w
+
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l -text "Electrode Type:"
+    tk_optionMenu $w.opt [ itcl::scope thisparam($this,current_grid_electrodetype) ] "Sphere" "Disc"
+    pack $w.l $w.opt  -side left -expand false  -anchor ne 
+
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l1 -text "Radius/Thick (mm):"
+    entry $w.e1 -width 5 -textvariable [ itcl::scope thisparam($this,current_grid_radius) ] -relief sunken
+    entry $w.e2 -width 5 -textvariable [ itcl::scope thisparam($this,current_grid_thickness) ] -relief sunken
+    pack  $w.l1 $w.e1 $w.e2 -side left -expand false -fill x -anchor w -padx 0
+
+
+    eval "button $wp.bot -text \"Update Grid \" -command { $this UpdateElectrodeGridProperties }"
+    pack $wp.bot -side bottom -expand f -fill x -anchor ne -pady 4 -padx 4    
+
+
+    set wp  [ LabelFrame:create $basepar.2 -text "Electrode Arrangment" ]
+    pack $basepar.2 -side top -expand true -fill both -pady 2 -padx 2
+    label $wp.lab -text "Electrode Leads Here!" -bg black -fg white
+    pack $wp.lab -side top -expand f -fill x 
+
+
+
+    set index 0
+
+	    
+    for { set j 0 } { $j < $maxelectrodes } { incr j } {
+	set w [ frame $wp.$j ] ; pack $w -side top -expand f -fill x -padx 0 -pady 0
+	for { set i 0 } { $i < $maxelectrodes } { incr i } {
+	    set nm radio_${i}_${j}
+	    eval "radiobutton $w.$index -value $index -variable [ itcl::scope thisparam($this,current_electrode_radio) ] -text \"\" -command { $this SelectElectrode } -width 0 -font $fontname -highlightbackground gray -highlightthickness 3"
+	    set thisparam($this,$nm) $w.$index	    
+	    pack  $thisparam($this,$nm) -side left -padx 0 -pady 0 -ipadx 0 -ipady 0 -expand f 
+	    incr index
+	}
+    }
+
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::UpdateElectrodeGridProperties { } {
+
+    set elec_grid  [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+
+    $elec_grid SetGridName $thisparam($this,current_grid_name) 
+    $elec_grid SetElectrodeSpacing $thisparam($this,current_grid_spx) $thisparam($this,current_grid_spy)
+    $elec_grid SetElectrodeTypeTo$thisparam($this,current_grid_electrodetype)
+    $elec_grid SetRadius $thisparam($this,current_grid_radius) 
+    $elec_grid SetThickness $thisparam($this,current_grid_thickness) 
+    $elec_grid SetVisible  $thisparam($this,current_grid_visible) 
+
+    set dimensions [ $elec_grid GetDimensions ]
+    set dimx [ lindex $dimensions 0 ]
+    set dimy [ lindex $dimensions 1 ]
+
+    if { $dimx != $thisparam($this,current_grid_dimx)  || $thisparam($this,current_grid_dimy)!=$dimy } {
+	set ok [ ::pxtclutil::Question "Changing the Grid Dimensions will result in losing all information about the current grid. Are you sure?" ]
+	if { $ok == 1 } {
+	    $elec_grid SetGridName $thisparam($this,current_grid_name) 
+	    #"grid_$thisparam($this,current_grid_dimx)_$thisparam($this,current_grid_dimy)"
+	    $elec_grid InitializeGrid $thisparam($this,current_grid_dimx) $thisparam($this,current_grid_dimy)
+	    $electrodemultigrid Modified
+	    set thisparam($this,current_electrode) 0
+	    UpdateInterface
+	    $vtk_viewer UpdateDisplay
+	    return
+	}
+    }
+
+    set thisparam($this,current_grid_dimx) $dimx
+    set thisparam($this,current_grid_dimy) $dimy
+    
+
+    $electrodemultigrid Modified
+    UpdatePatientPropertySheet
+    $vtk_viewer UpdateDisplay
+}
+
+
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::SelectElectrode { } {
+    set thisparam($this,current_electrode) $thisparam($this,current_electrode_radio) 
+    UpdateElectrodePropertySheet
+    ReleaseElectrodePick
+    if {  $thisparam($this,auto_pick) == 1 } {
+	PickElectrode -1
+    }
+}
+    
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::UpdateGridPropertySheet { } {
+    
+    set elec_grid [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+    set dimensions [ $elec_grid GetDimensions ]
+    set dimx [ lindex $dimensions 0 ]
+    set dimy [ lindex $dimensions 1 ]
+
+    set thisparam($this,current_grid_name) [ $elec_grid GetGridName ]
+    set thisparam($this,current_grid_dimx) $dimx
+    set thisparam($this,current_grid_dimy) $dimy
+    set thisparam($this,current_grid_spx)  [ lindex [ $elec_grid GetElectrodeSpacing ] 0 ]
+    set thisparam($this,current_grid_spy)  [ lindex [ $elec_grid GetElectrodeSpacing ] 1 ]
+    set thisparam($this,current_grid_visible) [ $elec_grid GetVisible ]
+
+    set thisparam($this,current_grid_electrodetype) "Sphere"
+    if { [ $elec_grid GetElectrodeType ] == 1 } {
+	set thisparam($this,current_grid_electrodetype) "Disc"
+    }
+
+    set thisparam($this,current_grid_radius) [ $elec_grid GetRadius ]
+    set thisparam($this,current_grid_thickness) [ $elec_grid GetThickness ]
+
+    set index 0
+    for { set j 0 } { $j < $maxelectrodes } { incr j } {
+	for { set i 0 } { $i < $maxelectrodes } { incr i } {
+	    #	    puts stderr "Updating Electrode $i $j"
+	    set nm $thisparam($this,radio_${i}_${j})
+	    if {$i >= $dimx || $j >= $dimy } {
+		$nm configure -value -1
+		$nm configure -state disabled -width 0 -bg darkgray -font { fixed 1 }
+		$nm configure -relief sunken
+	    } else {
+		set electrode [ $elec_grid GetElectrode $i $j ]
+		$electrode StoreColorInColorName 
+		set cl [ $electrode GetColorName ]
+		$nm configure -bg $cl
+		#		puts stderr "$nm configure -bg $cl"
+		$nm configure -state normal
+		$nm configure -value $index
+		#$nm configure -text $index
+		$nm configure -state normal -width 0 -font $fontname
+		$nm configure -relief flat -highlightbackground gray
+		incr index
+	    }
+	}
+    }
+
+    if { [ $elec_grid GetShowLabelsGap ] != $thisparam($this,showlabelsgap) } {
+	$elec_grid SetShowLabelsGap $thisparam($this,showlabelsgap)
+	$elec_grid Modified
+	$electrodemultigrid Modified
+	$thisparam($this,label_mapper) Modified
+    }
+
+    UpdateElectrodePropertySheet
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::CreatePatientPropertySheet { basepar } {
+
+    set wp  [ LabelFrame:create $basepar.1 -text "Patient Information"]
+    pack $basepar.1 -side top -expand true -fill x -pady 2 -padx 2
+
+    
+    set i 0
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l -text "Description:"
+    entry $w.e -width 45 -textvariable [ itcl::scope thisparam($this,current_patient_description) ] -relief sunken
+    pack $w.l  -side left -expand false -fill x -anchor w
+    pack $w.e -side left -expand true -fill x -anchor e
+
+    set w [ frame $wp.$i]  ; pack $w -anchor w; incr i
+    label $w.l -text "Comment:"
+    entry $w.e -width 45 -textvariable [ itcl::scope thisparam($this,current_patient_comment) ] -relief sunken
+    pack $w.l  -side left -expand false -fill x -anchor w
+    pack $w.e -side left -expand true  -fill x -anchor e
+
+
+
+    set wp  [ LabelFrame:create $basepar.2 -text "Grid Information"]
+    pack $basepar.2 -side top -expand true -fill x -pady 2 -padx 2
+    
+    set grid_listbox [ iwidgets::scrolledlistbox $wp.left -vscrollmode dynamic -hscrollmode none -selectmode single -labelpos nw -visibleitems 10x40 ]
+    eval "$grid_listbox configure -selectioncommand { $this SelectElectrodeGrid -1 }"
+    $grid_listbox configure -selectmode single
+    
+    frame $wp.right
+
+    eval "button $wp.right.add -text \"Add New Grid\" -command { $this AddNewElectrodeGrid }"
+    eval "button $wp.right.del -text \"Delete  Grid\" -command { $this DeleteCurrentElectrodeGrid }"
+    pack $wp.right.add $wp.right.del -side top -anchor se -padx 2 -pady 4
+
+    pack $wp.right -side right -expand false -fill y
+    pack $wp.left -side left -expand true -fill both -padx 2 -pady 2
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::SelectElectrodeGrid { index } {
+    
+    set ng [ $electrodemultigrid GetNumberOfGrids ] 
+    if { $index < 0 } {
+	set index [ $grid_listbox curselection ]
+    } else {
+	if { $index >= $ng  } {
+	    return 0
+	}
+	
+	$grid_listbox selection clear 0 end
+	$grid_listbox selection set $index $index
+    }
+
+    set thisparam($this,current_grid) $index
+    UpdateGridPropertySheet
+    set thisparam($this,current_electrode_radio)  0
+    SelectElectrode
+
+    if { $thisparam($this,visible) == "current" } {
+	ShowGrids current
+    }
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::AddNewElectrodeGrid { } {
+
+    set a [ $electrodemultigrid GetNumberOfGrids ] 
+    $electrodemultigrid InsertNewGrid
+    set grid [ $electrodemultigrid GetElectrodeGrid $a ]
+    $grid SetElectrodeSpacing 10.0 10.0
+    $grid SetRadius  2.0
+    set nm [ $grid GetGridName ]
+    set nq [ expr $a + 1 ]
+    $grid_listbox insert end "${nq}.${nm}"
+    SelectElectrodeGrid  $a
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::DeleteCurrentElectrodeGrid { } {
+
+    set a [ $electrodemultigrid GetNumberOfGrids ] 
+    if { $a == 1 } {
+	::pxtclutil::Warning "Cannot delete grid as this is the only grid in the patient!"
+	return
+    }
+
+    set ok [ ::pxtclutil::Question "This will delete all information about the current grid! Are you sure?" ]
+    if { $ok == 1 } {
+	$electrodemultigrid DeleteGrid $thisparam($this,current_grid) 
+	UpdatePatientPropertySheet
+	SelectElectrodeGrid 0
+    }
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::UpdatePatientPropertySheet { } {
+
+    set thisparam($this,current_patient_description) [ $electrodemultigrid GetDescription ]
+    set thisparam($this,current_patient_comment)     [ $electrodemultigrid GetComment ]
+
+    $grid_listbox clear 
+
+    set ng [ $electrodemultigrid GetNumberOfGrids ] 
+    for { set i 0 } { $i < $ng } { incr i } {
+	
+	set grid [ $electrodemultigrid GetElectrodeGrid $i ]
+	set nm [ $grid GetGridName ]
+	set nq [ expr $i + 1 ]
+	$grid_listbox insert end "${nq}.${nm}"
+    }
+
+    $grid_listbox selection clear 0 end
+    $grid_listbox selection set $thisparam($this,current_grid) $thisparam($this,current_grid)
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::UpdatePatientProperties { } {
+
+    $electrodemultigrid SetDescription $thisparam($this,current_patient_description) 
+    $electrodemultigrid SetComment     $thisparam($this,current_patient_comment)     
+
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::GridColor { } {
+
+    set egrid [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+    set c [ $egrid GetColor ]
+    set newcolor [ pxtclutil::ColorBox "Set Grid [ $egrid GetGridName ] display color" $c $basewidget ]
+    puts stderr "New Color $newcolor"
+    $egrid SetColor [ lindex $newcolor 0 ] [ lindex $newcolor 1 ] [ lindex $newcolor 2 ]
+    $egrid Modified
+    $egrid Update
+    $electrodemultigrid Modified
+    UpdateGridPropertySheet
+    $vtk_viewer UpdateDisplay
+}
+
+::itcl::body pxitclElectrodeMultiControl::LabelsColor { } {
+
+    set c [ [ $label_actor GetProperty ]  GetColor ]
+    set newcolor [ pxtclutil::ColorBox "Set Label Color for All Labels" $c $basewidget ]
+    puts stdout "Newcolor = $newcolor "
+   #  [ $label_actor GetProperty ] SetColor [ lindex $newcolor 0 ] [ lindex $newcolor 1 ] [ lindex $newcolor 2 ]  # Label color can only be set by using GetLabelTextProperty. GetProperty doesnt work. 
+    [ $thisparam($this,label_mapper) GetLabelTextProperty ] SetColor [ lindex $newcolor 0 ] [ lindex $newcolor 1 ] [ lindex $newcolor 2 ]
+    $vtk_viewer UpdateDisplay
+}
+
+
+::itcl::body pxitclElectrodeMultiControl::ReorientGrid { mode } {
+
+    if { $mode == 0 }  {
+	set ok [ ::pxtclutil::Question "This will transpose current grid! Are you sure?" ]
+    } elseif { $mode == 1 } {
+	set ok [ ::pxtclutil::Question "This will perform a row flip on your current grid! Are you sure?" ]
+    } else {
+	set ok [ ::pxtclutil::Question "This will perform a column flip on your current grid! Are you sure?" ]
+    }
+
+    if { $ok == 0 } {
+	return 
+    }
+
+    set egrid [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+    if { $mode == 0 } {
+	$egrid TransposeGrid
+    } elseif { $mode == 1 } {
+	puts stdout "Flipping X"
+	$egrid GridFlipX
+    } elseif { $mode == 2 } {
+	puts stdout "Flipping Y"
+	$egrid GridFlipY
+    }
+
+    $electrodemultigrid Modified;	$thisparam($this,label_mapper) Modified
+    $vtk_viewer UpdateDisplay
+    SelectElectrodeGrid -1
+    return
+}
+
+
+::itcl::body pxitclElectrodeMultiControl::DisableElectrodePropertySheet { } {
+
+    set md ""
+
+    if { $thisparam($this,readonly) == 2 } {
+	SetTitle "<Read-Only> Electrode Control [ file tail $last_filename]"
+	set flag 0
+	set bflag 0
+    } elseif { $thisparam($this,readonly) == 1 } {
+	SetTitle "<Attribute-Only> Electrode Control [ file tail $last_filename]"
+	set flag 1
+	set bflag 0
+    } else {
+	SetTitle "Electrode Control [ file tail $last_filename]"
+	set flag 1
+	set bflag 1
+    }
+
+    if { $flag == 1 } {
+	EnableUI $thisparam($this,electrodepropertylist)
+    } else {
+	DisableUI $thisparam($this,electrodepropertylist)
+    }
+
+    if { $update_location_button !=0 } {
+	if { $bflag == 0 } {
+	    $update_location_button configure -state disabled
+	    $location_text configure -state disabled
+	} else {
+	    $update_location_button configure -state normal
+	    $location_text configure -state normal
+	}
+    }
+
+
+}
+
+::itcl::body pxitclElectrodeMultiControl::ShowLabels { mode } {
+
+    if { $mode == -1 } {
+	$electrodemultigrid ShowLabelsGap $thisparam($this,showlabelsgap)
+	$electrodemultigrid Modified
+    } elseif { $mode == 0 } {
+	$label_actor SetVisibility 0 
+    } else {
+	$label_actor SetVisibility 1
+	[ $thisparam($this,label_mapper) GetLabelTextProperty ] SetFontSize $mode
+    }
+
+    $thisparam($this,label_mapper) Modified
+    $vtk_viewer UpdateDisplay
+	
+}
+
+::itcl::body pxitclElectrodeMultiControl::ShowGrids { mode } {
+
+
+    if { $mode != -1 } {
+	set thisparam($this,visible) $mode
+    } else {
+	set mode thisparam($this,visible)
+    }
+
+
+    set justelectrodes [ expr 1- $thisparam($this,visiblelines) ]
+
+    for { set i 0 } { $i <= 3 } { incr i } {
+	if { $mode == "none" } {
+	    $grid_actor($i) SetVisibility 0
+	} else {
+	    $grid_actor($i) SetVisibility 1
+	}
+    }
+	
+
+    if { $mode != "none" }  {
+	set flag 1
+	if { $mode == "current" } {
+	    set flag 0
+	} 
+    
+	set ng [ $electrodemultigrid GetNumberOfGrids ] 
+	for { set i 0 } { $i < $ng } { incr i } {
+	    set grid [ $electrodemultigrid GetElectrodeGrid $i ]
+	    $grid SetJustShowElectrodes $justelectrodes
+	    $grid SetColorMode [ expr 1-$thisparam($this,griduniformcolor) ]
+
+	    if { $i == $thisparam($this,current_grid) && $mode == "current" } {
+		$grid SetVisible 1
+	    } else {
+		$grid SetVisible $flag
+	    }
+	}
+        $electrodemultigrid Modified;	$thisparam($this,label_mapper) Modified
+	set thisparam($this,current_grid_visible) 1
+    } else {
+	ReleaseElectrodePick
+    }
+    
+   
+
+    $vtk_viewer UpdateDisplay
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::SelectGridsToDisplay { } {
+
+    set l ""
+    set ng [ $electrodemultigrid GetNumberOfGrids ] 
+    for { set i 0 } { $i < $ng } { incr i } {
+	set grid [ $electrodemultigrid GetElectrodeGrid $i ]
+	scan    [ $grid GetDimensions ] "%d %d" dimx dimy
+	set nm  [ $grid GetGridName ]
+	set nq  [ expr $i + 1 ]
+	lappend l  "${nq}.${nm}, ($dimx x $dimy)"
+    }
+
+    $batch_selector Activate $l "" "Select which electrode grids to display" "Select Grids To Display"
+    set indices [ $batch_selector GetSelectedIndices ]
+
+    set justelectrodes [ expr 1- $thisparam($this,visiblelines) ]
+
+    for { set i 0 } { $i <= 3 } { incr i } {
+	$grid_actor($i) SetVisibility 1
+    }
+    
+    puts stdout "Indices = $indices"
+    set ng [ $electrodemultigrid GetNumberOfGrids ] 
+    for { set i 0 } { $i < $ng } { incr i } {
+	set grid [ $electrodemultigrid GetElectrodeGrid $i ]
+	$grid SetJustShowElectrodes $justelectrodes
+	
+	if { [  lsearch -exact $indices  $i  ] != -1 } {
+	    $grid SetVisible 1
+	} else {
+	    $grid SetVisible 0
+	}
+
+	if { $i == $thisparam($this,current_grid) } {
+	    set thisparam($this,current_grid_visible) [ $grid GetVisible ]
+	}
+	
+        $electrodemultigrid Modified;	
+	$thisparam($this,label_mapper) Modified
+    }
+    ReleaseElectrodePick
+    set thisparam($this,visible) "some"
+    ShowLabels -1
+#    $vtk_viewer UpdateDisplay
+    
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclElectrodeMultiControl::AutoWarp { mode } {
+    
+    if { $mode == 1 } {
+	set egrid [ $electrodemultigrid GetElectrodeGrid $thisparam($this,current_grid) ]
+	$back_electrodemultigrid Copy $electrodemultigrid
+	set back_last_filename $last_filename 
+	set ok [ $egrid AutoWarp ]
+	if { $ok == 1 } {
+	    $egrid Modified
+	    $electrodemultigrid Modified;	$thisparam($this,label_mapper) Modified
+	    $vtk_viewer UpdateDisplay
+	    SelectElectrodeGrid -1
+	} else {
+	    ::pxtclutil::Warning "Cannot do autowarp as less than three electrodes have been modified. You need to manually position at least three electrodes before autowarp can work!\n"
+	}
+    } elseif { $back_last_filename != "none" } {
+	$electrodemultigrid Copy $back_electrodemultigrid
+	set last_filename $back_last_filename 
+	SetTitle "Electrode Control [ file tail $last_filename]"
+	UpdateInterface
+	$vtk_viewer UpdateDisplay 
+    }
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclHistogramWidget.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclHistogramWidget.tcl
new file mode 100644
index 0000000..d97ae22
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclHistogramWidget.tcl
@@ -0,0 +1,557 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclHistogramWidget 1.0
+
+# 	$Id: pxitclHistogramWidget.tcl,v 1.3 2004/12/09 15:50:45 xenios Exp xenios $	
+
+
+
+
+
+package require vtkImageInclude 1.0
+package require pxvtable 1.0
+
+itcl::class pxitclHistogramWidget {
+
+    inherit pxitclbaseimagecontrol
+
+    public variable NUM_BINS 64
+    public variable LOWER_BOUND -10000000
+    public variable UPPER_BOUND -10000000
+    public variable LOWER_LEVEL -10000000
+    public variable UPPER_LEVEL -10000000
+    public variable MAX_BINS     128
+    private variable DRAGGING 0
+
+    public variable accumulate 0
+    private variable drawcanvas 0
+    private variable hasinput 0
+    public  variable callback 0
+    public  variable entropy 0.0
+    
+    private common   showmax
+    private common   showaccurate
+    private common   lowerlevel 
+    private common   upperlevel 
+    private common   maxbins
+
+        # create a histogram object
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } {
+	set accumulate [  vtkpxImageRobustHistogram [ pxvtable::vnewobj ]]
+    }
+
+    public method Initialize { inpwidg }
+    public method UpdateRange { } 
+    public method Render { } 
+    public method Reset  { }
+    public method SetImage { img } 
+    public method Bind { probe }
+    public method Save { }
+
+    public method StartInteraction { x y b} 
+    public method EndInteraction { } 
+    public method UpdateInteraction { x y butno} 
+
+    public method ZeroMaximum { data } { } 
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclHistogramWidget::Initialize { inpwidg } {
+
+    if { $initialized } { return $basewidget } 
+
+    set basewidget $inpwidg
+    set initialized 1
+    set showmax($this) 0
+    set showaccurate($this) 0
+
+    frame $basewidget -bg red -bd 2 -relief ridge
+    set topf [ frame $basewidget.top ]
+    set bottomf [ frame $basewidget.bottom ]
+    label $bottomf.label1 -bg darkgray -fg white
+    set drawcanvas [ canvas $basewidget.canvas -width 650 -height 150  ]
+
+    pack $topf -side bottom -fill x
+    pack $bottomf -side top -fill x
+    pack $drawcanvas -side top -fill both -expand true
+
+    set lowerlevel($this) $LOWER_BOUND 
+    set upperlevel($this) $UPPER_BOUND 
+    set maxbins($this) $MAX_BINS 
+
+    label $topf.label1 -bg black -fg white
+
+    iwidgets::entryfield $topf.ent1 -labeltext "Range:" -width 5 -textvariable [ itcl::scope lowerlevel($this) ] -validate real
+    iwidgets::entryfield $topf.ent2 -labeltext ""  -width 5 -textvariable [ itcl::scope upperlevel($this) ] -validate real
+    iwidgets::entryfield $topf.ent25 -labeltext "Bins:"  -width 3 -textvariable [ itcl::scope maxbins($this) ] -validate real
+
+    eval  "bind  [ $topf.ent1 component entry ]  <Return> { $this UpdateRange } "
+    eval  "bind  [ $topf.ent2 component entry ]  <Return> { $this UpdateRange } "
+    eval  "bind  [ $topf.ent25 component entry ]  <Return> { $this UpdateRange } "
+
+    eval "button $topf.but2 -text Upd -command { $this UpdateRange; $this Render } -pady 1"
+    eval "button $topf.but3 -text Reset -command { $this Reset }  -pady 1 "
+    pack $topf.label1 $topf.ent1 $topf.ent2 $topf.ent25 $topf.but2 $topf.but3 -side left -fill x -pady 0
+    
+	
+    set str1 [format "Levels: \[%.1f, %.1f\] Bins=%d" $LOWER_LEVEL $UPPER_LEVEL $NUM_BINS]
+    $topf.label1 configure -text  $str1
+
+    eval "checkbutton $bottomf.but31 -variable [ itcl::scope showaccurate($this) ] -text \"HighRes\" -command { $this SetImage -1 } "
+    eval "checkbutton $bottomf.but3 -variable [ itcl::scope showmax($this) ] -text \"ShowMax\" -command { $this UpdateRange } "
+
+
+    eval "button $bottomf.but5 -text Save  -command { $this Save }  -pady 1 "
+
+    set l [ AddLogoLabel $bottomf ]
+
+    pack $l $bottomf.but5  $bottomf.but3 $bottomf.but31 -side right -expand f -padx 0 -pady 0
+    pack $bottomf.label1  -side left -expand true -padx 1 -pady 0 -fill x
+    $topf.label1 configure -text "(Left: Drag, Middle: Gray, Right: White)"
+
+    set cwidth  [ $drawcanvas cget -width  ]
+    set cheight [ $drawcanvas cget -height ]
+
+    $drawcanvas create rect 0 0 $cwidth $cheight -fill blue -tag background
+    $drawcanvas create rect 0 [expr $cheight/2] $cwidth $cheight -fill white -tag histogram
+    $drawcanvas create rect [expr $cwidth/3] 0 [expr $cwidth/3 +1 ] $cheight -fill gray -outline gray -tag grayslider
+    $drawcanvas create rect [expr $cwidth/2] 0 [expr $cwidth/2 +1 ] $cheight -fill white -outline white -tag whiteslider
+   
+
+    return $basewidget
+}
+# -------------------------------------------------------------------------------------------    
+    
+# Sets the input
+::itcl::body pxitclHistogramWidget::SetImage { image } {
+
+
+    if { $image != -1 } {
+	set ok [ pxitclbaseimagecontrol::SetImage $image ]
+	if { $ok == 0 } { 	
+	    catch { $drawcanvas delete all } 
+	    set hasinput 0
+	    return 0 
+	}
+    }
+    set input [ $currentimage GetImage ]
+    set hasinput 1
+
+    set sp   [ $input GetSpacing ]
+    set extr [ vtkImageExtractComponents [ pxvtable::vnewobj ]]
+    $extr SetInput $input
+    $extr SetComponents 0
+    $extr Update
+
+    if { $showaccurate($this) == 0 } {
+	set resl [ vtkImageResample [ pxvtable::vnewobj ]]
+	$resl InterpolateOff
+	$resl SetAxisOutputSpacing 0 [ expr [ lindex $sp 0 ] *4 ]
+	$resl SetAxisOutputSpacing 1 [ expr [ lindex $sp 1 ] *4 ]
+	$resl SetAxisOutputSpacing 2 [ expr [ lindex $sp 2 ] *4 ]
+	$resl SetInput [ $extr GetOutput ]
+	$resl Update 
+	$accumulate SetInput [ $resl GetOutput ]	
+	$resl Delete
+    } else {
+	$accumulate SetInput [ $extr GetOutput ]
+    }
+    Reset
+    
+    #set data [ [ $input  GetPointData ] GetScalars ]
+    #set inputRange0 [lindex [$data GetRange] 0]
+    #set inputRange1 [lindex [$data GetRange] 1]
+
+    #set LOWER_BOUND $inputRange0
+    #set UPPER_BOUND $inputRange1
+#    $resl Delete
+    $extr Delete
+}
+    
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclHistogramWidget::UpdateRange {  } {
+
+    set LOWER_BOUND $lowerlevel($this)
+    set UPPER_BOUND $upperlevel($this)
+    set MAX_BINS    $maxbins($this)
+    Render
+
+}
+
+::itcl::body pxitclHistogramWidget::Reset {  } {
+
+    set NUM_BINS 64
+    set MAX_BINS     128
+    set DRAGGING 0
+
+    set lowerlevel($this) -1
+    set upperlevel($this) -1
+    set maxbins($this) $MAX_BINS 
+
+    $this UpdateRange
+}
+# -------------------------------------------------------------------------------------------
+# Render
+::itcl::body pxitclHistogramWidget::Render { } {
+
+    if { [ $currentimage GetImageSize  ] < 2 } { 
+	catch { $drawcanvas delete all }
+	return 0 
+    } 
+
+    # get the size of the histogram window
+    set width [lindex  [$basewidget configure -width] 4]
+    set height [lindex [$basewidget configure -height] 4]
+    
+    set data [ [ [ $accumulate GetInput]  GetPointData ] GetScalars ]
+    set inputRange0 [lindex [$data GetRange] 0]
+    set inputRange1 [lindex [$data GetRange] 1]
+    set inputRangeOrig0 [lindex [$data GetRange] 0]
+    set inputRangeOrig1 [lindex [$data GetRange] 1]
+    
+    set lower_bound $LOWER_BOUND  
+    set upper_bound $UPPER_BOUND  
+    set max_bins    $MAX_BINS
+
+    if { $lower_bound == - 1 && $upper_bound == - 1 } {
+	set upper_bound $inputRange1
+	set lower_bound $inputRange0
+    } else {
+	if { $lower_bound >= $inputRange0  && $lower_bound < $inputRange1  } {
+	    set inputRange0 $lower_bound
+	} else {
+	    set lower_bound $inputRange0
+	}
+    
+	if { $upper_bound >= $inputRange0  && $upper_bound < $inputRange1  } {
+	    set inputRange1 $upper_bound
+	} else {
+	    set upper_bound $inputRange1
+	}
+    }
+
+    if { $upper_bound == $lower_bound } {
+	set upper_bound [ expr $lower_bound +1 ]
+    }
+
+    
+    set numBins [ expr  $upper_bound - $lower_bound + 1 ] 
+
+    if {  [ [ $accumulate GetInput] GetScalarType ] == 10 } { 
+	set numBins $max_bins
+    } else {
+	if { $numBins == 0 } { 
+	    set numBins 1 
+	} else {
+	    # Force numbins in range 2-128
+	    if { $numBins > $max_bins } { 
+		set numBins $max_bins
+	    } elseif { $numBins <  2 } { 
+		set numBins 2
+	    }
+	}
+    }
+
+    set numBins [ expr int($numBins) ]
+    set NUM_BINS $numBins
+    set maxbins($this) $NUM_BINS
+
+
+    set lowerlevel($this) $lower_bound 
+    set upperlevel($this) $upper_bound 
+
+
+    # Display Stuff ; create Histogram
+    # --------------------------------
+    #    set origin  $lower_bound
+    #   set spacing [expr 1.0 * ($upper_bound - $origin) / $numBins]
+
+
+    
+    $accumulate SetNumberOfBins $numBins
+    $accumulate SetLowerThreshold $lower_bound
+    $accumulate SetUpperThreshold $upper_bound
+    $accumulate InterpolationOn
+    $accumulate RobustModeOff
+    $accumulate SaturationModeOff
+    $accumulate Update
+    set entropy [ $accumulate ComputeEntropy ]
+    
+
+    # get the histogram data
+    
+    set data [ vtkImageData [ pxvtable::vnewobj ]]
+    $data DeepCopy [$accumulate GetOutput]
+
+
+
+    if { $showmax($this) == 0 && $lower_bound == $inputRangeOrig0 && $upper_bound == $inputRangeOrig1 } {
+	ZeroMaximum $data
+    }
+    
+    
+
+    # initialize the canvas
+    # Get the height and the width
+    set cwidth  [ $drawcanvas cget -width  ]
+    set cheight [ $drawcanvas cget -height ]
+    
+    $drawcanvas delete background histogram grayslider whiteslider
+    $drawcanvas create rect 0 0 $cwidth $cheight -fill blue -tag background
+    
+    # scale the histogram max to fit the window
+    set histRange [[[$data GetPointData] GetScalars] GetRange]
+    #    puts stderr "histRange = $histRange"
+    
+    set histRange1 [ lindex $histRange 1 ]
+    if  { $histRange1 < 1 } { set histRange1 1 }
+    set scale  [expr 0.75 * double($cheight) / $histRange1]
+    set wscale [ expr $cwidth / $numBins ]
+    
+
+
+
+    # Draw Histogram as altenating color bars
+    for {set idx 0} {$idx < $numBins} {incr idx} {
+	
+	set y [$data GetScalarComponentAsDouble $idx 0 0 0]
+	set y1 [expr $cheight - $y * $scale]
+	set y2 [lindex [split $y1 .] 0]
+	
+	set x1 [ expr $idx * $wscale ]
+	set x2 [ expr $x1 +  $wscale ]
+
+	$drawcanvas create rect $x1 $cheight $x2 $y2 -fill yellow -outline red -tag histogram
+    }
+    
+    $data Delete
+    
+    set origin  [lindex [ [ $accumulate GetOutput ] GetOrigin] 0]
+    set spacing [lindex [ [ $accumulate GetOutput ] GetSpacing] 0]
+    
+    if { $LOWER_LEVEL <=   $inputRangeOrig0  || $LOWER_LEVEL >= $inputRangeOrig1  } { 
+	set lower_bin   [ expr 0.2*$numBins]
+	set LOWER_LEVEL [ expr $origin + $spacing * $lower_bin ]
+    } else {
+	if { $LOWER_LEVEL <=   $inputRange0  || $LOWER_LEVEL >= $inputRange1  } { 
+	    set lower_bin 0
+	} else {
+	    set lower_bin   [ expr ($LOWER_LEVEL - $lower_bound)/$spacing ]
+	}
+    }
+    
+    set lower_pos   [ expr $lower_bin * $wscale ] 
+    $drawcanvas create rect  $lower_pos 0 [expr $lower_pos +1 ] $cheight -fill gray -outline gray -tag grayslider
+    
+    
+    if { $UPPER_LEVEL <=   $inputRangeOrig0  || $UPPER_LEVEL >=  $inputRangeOrig1  } { 
+	set upper_bin   [ expr 0.9*$numBins]
+	set UPPER_LEVEL [ expr $origin + $spacing * $upper_bin ]
+    } else {
+	if { $UPPER_LEVEL <=   $inputRange0  || $UPPER_LEVEL >=  $inputRange1  } { 
+	    set upper_bin $numBins
+	} else {
+	    set upper_bin [ expr ($UPPER_LEVEL- $lower_bound)/$spacing ] 
+	}
+    }
+    
+    set upper_pos   [ expr $upper_bin * $wscale ] 
+    $drawcanvas create rect  $upper_pos 0 [expr $upper_pos +1 ] $cheight -fill white -outline white -tag whiteslider
+    
+    
+    set str1 [format "Range \[%.1f:%.1f\] Lv=%.1f,%.1f Ent=%4.3f" $lower_bound $upper_bound $LOWER_LEVEL $UPPER_LEVEL $entropy]
+    $basewidget.bottom.label1 configure -text $str1
+    
+}
+    
+# -------------------------------------------------------------------------------------------        
+# ---- Bindings and interaction procedures ----
+
+::itcl::body pxitclHistogramWidget::Bind {  probe } {
+
+    eval "bind $basewidget <Expose> { $this Render }"
+
+	
+    if {$probe > 0 } {
+	eval "bind $drawcanvas <ButtonPress>   { $this StartInteraction   %x %y %b}"
+	eval "bind $drawcanvas <B1-Motion>     { $this UpdateInteraction  %x %y 1}"
+	eval "bind $drawcanvas <ButtonRelease> { $this EndInteraction }  "
+    }
+}
+    
+# -------------------------------------------------------------------------------------------    
+::itcl::body pxitclHistogramWidget::StartInteraction { x y b} {
+    UpdateInteraction  $x $y $b 
+}
+    
+# -------------------------------------------------------------------------------------------    
+::itcl::body pxitclHistogramWidget::EndInteraction { } {
+
+    if { $hasinput == 0 } { return }
+
+    set data [ [ [ $accumulate GetInput]  GetPointData ] GetScalars ]
+
+    set inputRange0 [lindex [$data GetRange] 0]
+    set inputRange1 [lindex [$data GetRange] 1]
+    
+    set lower_bound $LOWER_BOUND  
+    set upper_bound $UPPER_BOUND  
+
+    if { $lower_bound >= $inputRange0  && $lower_bound < $inputRange1  } {
+	set inputRange0 $lower_bound
+    } 
+    
+    if { $upper_bound >= $inputRange0  && $upper_bound < $inputRange1  } {
+	set inputRange1 $upper_bound
+    } 
+    
+    set str1 [format "Range \[%.1f:%.1f\] Gray=%.1f, White=%.1f Bins=%d" $inputRange0 $inputRange1 $LOWER_LEVEL $UPPER_LEVEL $NUM_BINS]
+    $basewidget.bottom.label1 configure -text $str1
+    set DRAGGING 0
+
+    if { $callback !=0 } {
+	catch { eval $callback }
+    }
+}
+    
+# ------------------------------------------------------------------------------------------ -   
+::itcl::body pxitclHistogramWidget::UpdateInteraction { x y butno} {
+
+    # compute the bin selected by the mouse
+    if { $hasinput == 0 } { return }
+
+    set lower_bound $LOWER_BOUND  
+    set upper_bound $UPPER_BOUND  
+
+    set cwidth  [ $drawcanvas cget -width  ]
+    set cheight  [ $drawcanvas cget -height  ]
+    set numBins $NUM_BINS
+    set wscale [ expr $cwidth / $numBins ]
+
+    set xcoord $x
+    set x [expr $x / $wscale]
+
+    set origin [lindex [ [ $accumulate GetOutput ] GetOrigin ] 0 ]
+    set spacing [lindex [ [ $accumulate GetOutput ] GetSpacing ] 0 ]
+    set binMin [expr $origin + $spacing * $x]
+    set binMax [expr $binMin + $spacing]
+    set gap [ expr 2.0* $spacing ]
+    
+    # now get the height of the histogram
+    set data [$accumulate GetOutput]
+    # $data Update
+    # make sure value is in extent
+    set max [lindex [$data GetExtent] 1]
+    if {$x < 0 || $x > $max} {
+	return
+    }
+    
+
+
+    if { $butno == 1 } {
+	set dr  $DRAGGING 
+	if { $dr > 0 } { 
+	    set butno [ expr $dr + 1 ] 
+	} else {
+	    set butno 1
+	    set diff1 [ expr $wscale*abs($binMin- $LOWER_LEVEL) ]
+	    if { $diff1 < $gap } { 
+		set butno 2 
+	    } else {
+		set diff1 [ expr $wscale*abs($binMin- $UPPER_LEVEL) ]
+		if { $diff1 < $gap } { 
+		    set butno 3 
+		}
+	    }
+	}
+    }
+    
+    
+    set y [$data GetScalarComponentAsDouble $x 0 0 0] 
+    
+    switch -exact $butno {
+	1 {
+	    set y [$data GetScalarComponentAsDouble $x 0 0 0] 
+	    # format the string to display
+	    set str1 [format "Bin: \[%.1f, %.1f) value=%.1f" $binMin $binMax $y]
+	    $basewidget.bottom.label1 configure -text $str1
+	    set DRAGGING 0
+	} 
+	"2" {
+	    set str1 "Setting Lower Level $binMin (value = $y)"
+	    $basewidget.bottom.label1 configure -text $str1
+	    $drawcanvas coords grayslider $xcoord 0 [expr $xcoord + 1 ] $cheight 
+	    #		[$actor GetPositionCoordinate] SetValue $xcoord  0
+	    set LOWER_LEVEL $binMin
+	    set DRAGGING 1
+	} 
+	"3" {
+	    set str1 "Setting Upper Level $binMin (value=$y)"
+	    $basewidget.bottom.label1 configure -text $str1
+	    $drawcanvas coords whiteslider $xcoord 0 [expr $xcoord +1 ] $cheight
+	    set UPPER_LEVEL $binMin
+	    set DRAGGING 2
+	}
+    }
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclHistogramWidget::Save { } {
+    
+    set f  [tk_getSaveFile -title "Histogram Filename" -filetypes { {"Histogram Data File" {.dat}}} -parent $basewidget ]
+    if  { [string length $f] < 1 } { return 0 }
+
+    set ok [ $accumulate SaveGnuplot $f ]
+    if { $ok == 0 } {
+	::pxtclutil::Warning "Failed to save histogram in $f"
+    } else {
+	::pxtclutil::Info "Histogram saved in $f ([file size $f])"
+    }
+    
+
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclHistogramWidget::ZeroMaximum { data } {
+
+    set scal [ [ $data GetPointData ] GetScalars ]
+    set rmax [ lindex [ $scal GetRange ]  1 ]
+    
+    set nt   [ $scal GetNumberOfTuples ]
+    for { set i 0 } { $i < $nt } { incr i } {
+	set v [ $scal GetComponent $i 0 ]
+	if { $v == $rmax } {
+	    $scal SetComponent $i 0 0.0
+	}
+    }
+
+    $scal Modified
+    set rmax [ lindex [ $scal GetRange ]  1 ]
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclLandmarkControl.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclLandmarkControl.tcl
new file mode 100644
index 0000000..9e822ac
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclLandmarkControl.tcl
@@ -0,0 +1,106 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclLandmarkControl 1.0
+
+# 	$Id: pxitclLandmarkControl.tcl,v 1.3 2002/07/16 16:16:36 papad Exp papad $	
+
+
+
+
+
+package require pxvtable 1.0
+package require Iwidgets 4.0
+
+itcl::class pxitclLandmarkControl {
+
+    inherit pxitclbaseimagecontrol
+    
+    private variable vtk_landmarkcontrol 0
+    private variable vtk_viewer 0
+
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } {
+	set vtk_landmarkcontrol [ vtkpxGUIBaseCurveControl [ pxvtable::vnewobj ] ]
+    }
+    
+    public method Initialize { inpwidg viewer }
+    protected method SetViewer  { viewer }
+    public method GetLandmarkControl { } { return $vtk_landmarkcontrol } 
+    public method SetImage { img } 
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclLandmarkControl::Initialize { inpwidg viewer } {
+
+    if { $initialized } { return $basewidget } 
+
+    SetViewer $viewer
+    set basewidget [ $vtk_landmarkcontrol Initialize $inpwidg 0 ]
+    set initialized 1
+    SetTitle "Landmark Control"
+   
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget
+}
+
+# -------------------------------------------------------------------------------------------    
+    
+# Sets the input
+::itcl::body pxitclLandmarkControl::SetViewer { viewer } {
+
+    if { [ $viewer IsA vtkpxGUIBaseImageViewer ] == 0 } {
+	return 0
+    }
+
+    set vtk_viewer $viewer
+    
+    if { [ $vtk_viewer IsA vtkpxGUIOrthogonalViewer ] == 1 } {
+	$vtk_landmarkcontrol SetCallback $vtk_viewer 201
+	$vtk_landmarkcontrol SetRenderer [ [ $vtk_viewer GetRenderer 0 ] GetRenderer ] 0 
+	$vtk_landmarkcontrol SetRenderer [ [ $vtk_viewer GetRenderer 1 ] GetRenderer ] 1 
+	$vtk_landmarkcontrol SetRenderer [ [ $vtk_viewer GetRenderer 2 ] GetRenderer ] 2 
+	$vtk_landmarkcontrol SetRenderer [ [ $vtk_viewer GetRenderer 3 ] GetRenderer ] 3 
+    } elseif { [ $vtk_viewer IsA vtkpxGUIMosaicViewer ] == 1 } {
+	$vtk_landmarkcontrol SetCallback $vtk_viewer 301
+	$vtk_viewer SetEditor $vtk_landmarkcontrol
+	$vtk_viewer SetMouseToEditor 1
+	$vtk_landmarkcontrol DisableLabels
+    }
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclLandmarkControl::SetImage { img } {
+
+    if { [ $img GetImageSize] < 2 } {return 0 }
+    
+    if { $vtk_landmarkcontrol !=0 } {
+	$vtk_landmarkcontrol SetImage [ $img GetImage ] -1 -1 0
+    }
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclPolyDataControl.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclPolyDataControl.tcl
new file mode 100644
index 0000000..adef414
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclPolyDataControl.tcl
@@ -0,0 +1,114 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclPolyDataControl 1.0
+
+# 	$Id: pxitclPolyDataControl.tcl,v 1.2 2002/06/10 13:15:20 papad Exp papad $	
+
+
+
+
+
+package require pxvtable 1.0
+package require Iwidgets 4.0
+package require pxitclbaseimagecontrol 1.0
+
+
+itcl::class pxitclPolyDataControl {
+
+    inherit pxitclbaseimagecontrol
+    
+    private variable vtk_polydatacontrol 0
+    private variable vtk_viewer 0
+
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } {
+	set vtk_polydatacontrol [ vtkpxGUIPolyDataControl [ pxvtable::vnewobj ] ]
+    }
+    
+    public method Initialize { inpwidg viewer }
+    protected method SetViewer  { viewer }
+    public method GetPolyDataControl {} { return $vtk_polydatacontrol } 
+    public method SetImage { img } 
+    public method LoadSurface { fname }
+}
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclPolyDataControl::Initialize { inpwidg viewer } {
+
+    if { $initialized } { return $basewidget } 
+
+    if { [ $viewer IsA vtkpxGUIOrthogonalViewer ] == 1 } {
+	$vtk_polydatacontrol SetCallback $viewer 201
+    }
+    set basewidget [ $vtk_polydatacontrol Initialize $inpwidg 0 ]
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    set initialized 1
+    SetTitle "Surface Control"
+
+    $vtk_polydatacontrol SetProgressCommand "$this ShowProgressVal"
+    SetViewer $viewer
+    return $basewidget
+}
+
+# -------------------------------------------------------------------------------------------    
+    
+# Sets the input
+::itcl::body pxitclPolyDataControl::SetViewer { viewer } {
+
+    if { [ $viewer IsA vtkpxGUIOrthogonalViewer ] == 0 } {
+	return 0
+    }
+
+    set vtk_viewer $viewer
+
+    $vtk_polydatacontrol SetRenderer [ [ $vtk_viewer GetRenderer 3 ] GetRenderer ] 0 0
+    $vtk_polydatacontrol SetRenderer [ [ $vtk_viewer GetRenderer 0 ] GetRenderer ] 1 1
+    $vtk_polydatacontrol SetRenderer [ [ $vtk_viewer GetRenderer 1 ] GetRenderer ] 2 1
+    $vtk_polydatacontrol SetRenderer [ [ $vtk_viewer GetRenderer 2 ] GetRenderer ] 3 1
+    
+}
+
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclPolyDataControl::SetImage { img } {
+
+    if { [ $img GetImageSize] < 2 } {return 0 }
+    
+    if { $vtk_polydatacontrol !=0 } {
+	$vtk_polydatacontrol SetImage [ $img GetImage ] 
+    }
+}
+
+itcl::body pxitclPolyDataControl::LoadSurface { fname } {
+
+    if { $vtk_polydatacontrol == 0 } {
+	return 0
+    }
+
+    return [ $vtk_polydatacontrol LoadCurrentSurface $fname ]
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclanimationgadget.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclanimationgadget.tcl
new file mode 100644
index 0000000..0af72c7
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclanimationgadget.tcl
@@ -0,0 +1,735 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+package provide pxitclanimationgadget 1.0
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+package require  vtkpxcontrib 1.1
+package require  labelframe   1.0
+package require  pxtclutil    1.0
+package require  pxvtable     1.0
+package require  pxtclhelp    1.0
+package require  Itcl         3.2
+package require  Iwidgets     4.0
+package require  pxitclimage            1.0
+package require  pxitclcamera           1.0
+package require  pxitcltransform        1.0
+package require  pxitclbaseimagecontrol 1.0
+
+# ----------------------------------------------------------------------------------------------
+
+itcl::class pxitclanimationgadget {
+
+    inherit pxitclbasecontrol
+    
+    # Generic Stuff 
+
+    protected common   thisparam        
+    protected common   animation_initialized 0
+
+    # Animation Stuff
+    public    variable animation_frame     1
+    public    variable animation_stop      0
+    protected variable animation_manualstatus  0
+    protected variable animation_manualbutton 0
+    protected variable animation_startbutton 0
+    protected variable animation_stopbutton 0
+    protected variable vtk_viewer 0
+    protected variable spinning   0
+    protected variable cameracontrol 0
+    protected variable setupfilename ""
+    protected variable titlestring "Animation Tool"
+
+    # public 
+
+    
+    #
+    constructor { par args } {
+	pxitclbasecontrol::constructor $par
+    } {
+	InitializeAnimationGadget
+    }
+    protected method InitializeAnimationGadget { }
+    public method Initialize { widget }
+    public method DelayedInitialize { }
+    public method SetViewer { vr }  { set vtk_viewer $vr }
+    public method AddToMenuButton { mb args }
+    public method GetAnimationName { }
+    public method SaveAnimationFrame { mode }
+    public method ManualGrabNextFrame { }
+    public method ShowViewerControls { }
+    public method SetViewerTo3DMode { }
+
+    public method LoadScript { args } 
+    public method SaveScript { args } 
+    public method GrabFromViewer { }
+    public method UpdateFromViewer { }
+    public method SendToViewer { forcemode } 
+    public method AddSpin { angle }
+    public method AnimateScript { }
+
+    protected method SetRendererClips { camera }
+    protected method SetWeightedRendererClips { camera camera2 factor }
+    protected method GetRendererClips { camera }
+
+
+}
+
+
+::itcl::body pxitclanimationgadget::AddToMenuButton { mb args} {
+    eval "$mb add command -label \"Animation Tool\" -command { $this ShowWindow }"
+}
+
+itcl::body pxitclanimationgadget::InitializeAnimationGadget { } {
+
+    set thisparam($this,animationdelay) 200
+    set thisparam($this,animationname) "grabbedframe.jpg"
+    set thisparam($this,autosave) 0
+    set thisparam($this,scriptdivide) 15
+    set thisparam($this,scriptbegin) -1
+    set thisparam($this,scriptend) 1000
+    set thisparam($this,scriptunit)   0.2
+    set thisparam($this,autoupdate) 0
+    set thisparam($this,animateandsave) 0
+    set thisparam($this,spinpositive) 1
+    set thisparam($this,spinazimuth) 1
+}
+
+itcl::body pxitclanimationgadget::Initialize { widget } { 
+	
+
+    set basewidget [ toplevel $widget ]
+    wm geometry $basewidget 600x400
+    wm withdraw $basewidget
+
+    SetTitle $titlestring
+    set initialized 1    
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget
+
+}
+
+itcl::body pxitclanimationgadget::DelayedInitialize { } { 
+
+    if { $fullyinitialized == 1 } {
+	return
+    }
+
+    set menubase     [ menu $basewidget.menu ]; $basewidget configure -menu $menubase
+
+    set pbar     [ frame $basewidget.pbar    -width 450 -height 20 ]
+    set notebook $basewidget.notebook
+    iwidgets::tabnotebook $notebook  -tabpos n
+
+    pack $pbar     -side bottom -expand f -fill x -pady 1
+    pack $notebook -side top -expand t -fill both -pady 1
+
+    set w  [ $notebook add -label "Main" ]
+    set w2 [ $notebook add -label "Script " ]
+
+    frame $w.1 ; frame $w.2 ; frame $w.3
+    pack $w.1 $w.2 $w.3 -side top -expand false -fill x -pady 1 -padx 2
+    
+    iwidgets::entryfield $w.1.1 -labeltext "Base name:" -textvariable [ itcl::scope thisparam($this,animationname) ] -relief sunken -width 40 
+    eval "button $w.1.2  -text \"Browse\" -command { $this GetAnimationName }"
+    pack $w.1.1 $w.1.2 -side left -padx 3
+    
+    label $w.2.1 -text "Delay Time (ms): "
+    tk_optionMenu $w.2.2 [ itcl::scope thisparam($this,animationdelay) ]  "50" "100" "200" "500" "1000" "2000" "Manual"
+    eval "button $w.2.3 -text \"Grab Next <ctrl-a>\" -command { $this ManualGrabNextFrame  }" 
+    set animation_manualbutton $w.2.3
+    pack $w.2.1 $w.2.2 $w.2.3 -side left -padx 3
+    
+    pack forget $animation_manualbutton 
+    
+    
+    eval "button $w.3.1  -text \"Start Grabbing\" -command { $this SaveAnimationFrame begin }"
+    eval "button $w.3.2  -text \"Stop Grabbing\" -command { $this  SaveAnimationFrame end }"
+    pack $w.3.1 $w.3.2  -side left -padx 1
+    
+    set animation_startbutton $w.3.1
+    set animation_stopbutton $w.3.2
+    
+    DisableWidget $animation_stopbutton
+    eval "bind all <Control-a> { $this ManualGrabNextFrame} "
+
+
+    eval "button $pbar.1  -text \"Show Viewer Controls\" -command { $this ShowViewerControls }"
+    eval "button $pbar.2  -text \"Switch Viewer to 3D Mode\" -command { $this SetViewerTo3DMode }"
+    set l [ AddLogoLabel $pbar ]
+    pack $l -side right -padx 1
+    pack $pbar.1 $pbar.2  -side left -padx 4
+
+    frame $w2.d; pack $w2.d -side bottom -expand false -fill x -pady 2
+    frame $w2.c; pack $w2.c -side bottom -expand false -fill x -pady 2
+    frame $w2.bc -bg black -height 3 ; pack $w2.bc -side bottom -expand false -fill x -pady 1
+    frame $w2.b; pack $w2.b -side bottom -expand false -fill x -pady 2
+
+    set cameracontrol [ [ pxitclmultiCameraGUI \#auto  ] GetThisPointer ]
+    $cameracontrol configure -enableadd 0
+    $cameracontrol configure -enabledeleteall 1
+    $cameracontrol Initialize $w2.a
+    $cameracontrol configure -callback "$this SendToViewer 0"
+    
+    set cm [ $cameracontrol GetObjectGUI ]
+    set lb [ $cm cget -loadbutton ]; pack forget $lb
+    set lb [ $cm cget -savebutton ]; pack forget $lb
+    set lb [ $cm cget -clearbutton ]; pack forget $lb
+    $cameracontrol AddCamera "None"
+
+    menu $menubase.filem -tearoff 0 ;      $menubase add cascade -label Setup      -menu $menubase.filem
+    menu $menubase.spinm -tearoff 0 ;      $menubase add cascade -label Spin      -menu $menubase.spinm
+
+    eval "$menubase.filem add command -label \"Load Script\" -command { $this LoadScript \"\" }"
+    eval "$menubase.filem add command -label \"Save Script\" -command { $this SaveScript \"\" }"
+    $menubase.filem add separator
+    eval "$menubase.filem add command -label \"Close\" -command { wm withdraw $basewidget }"
+
+    set mb $menubase.spinm
+    eval "$mb add check -label \"Positive Rotation\" -variable [ itcl::scope thisparam($this,spinpositive)] "
+    eval "$mb add check -label \"Do Azimuth\" -variable [ itcl::scope thisparam($this,spinazimuth)] "
+    $mb add separator
+    eval "$mb add command -label \"Spin 10\" -command { $this AddSpin 10 }"
+    eval "$mb add command -label \"Spin 20\" -command { $this AddSpin 20 }"
+    eval "$mb add command -label \"Spin 30\" -command { $this AddSpin 30 }"
+
+
+    eval "button $w2.b.1 -text \"Add\" -command { $this GrabFromViewer }"
+    eval "button $w2.b.2 -text \"Update\" -command { $this UpdateFromViewer }"
+    eval "button $w2.b.3 -text \"Send To Viewer\" -command { $this SendToViewer 1 }"
+    checkbutton $w2.b.6 -variable [ itcl::scope thisparam($this,autoupdate) ] -text "Auto Update"
+
+    pack $w2.b.1 $w2.b.2 $w2.b.3 $w2.b.6 -side left -expand false -padx 1
+    pack $w2.a -side top -expand false -fill x
+
+   
+    iwidgets::entryfield $w2.c.1 -labeltext "Subdivision:" -textvariable [ itcl::scope thisparam($this,scriptdivide) ] -relief sunken -width 4 -validate integer
+    iwidgets::entryfield $w2.c.2 -labeltext "Duration (s):" -textvariable [ itcl::scope thisparam($this,scriptunit) ] -relief sunken -width 4 -validate real
+    iwidgets::entryfield $w2.c.3 -labeltext "Begin :" -textvariable [ itcl::scope thisparam($this,scriptbegin) ] -relief sunken -width 4 -validate integer
+    iwidgets::entryfield $w2.c.4 -labeltext "End   :" -textvariable [ itcl::scope thisparam($this,scriptend) ] -relief sunken -width 4 -validate integer
+
+    pack $w2.c.1 $w2.c.2 $w2.c.3 $w2.c.4 -side left -padx 2
+
+
+    eval "button $w2.d.1  -text \"Animate\" -command { $this AnimateScript }"
+    checkbutton $w2.d.2 -variable [ itcl::scope thisparam($this,animateandsave) ] -text "Save While Animating"
+    pack $w2.d.1 $w2.d.2  -side left -padx 2
+
+    $notebook view "Main"
+
+    set fullyinitialized 1
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclanimationgadget::GetAnimationName { } {
+    
+    
+    set fname [tk_getSaveFile -title "Filename" -defaultextension .jpg -initialfile $thisparam($this,animationname)  -filetypes { {"JPG FILES" {.jpg}}} ]
+
+
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    set ext [ file extension $fname ]
+    if { $ext != ".jpg" } {
+	set fname "[ file root $fname ].jpg"
+    }
+
+    set thisparam($this,animationname) $fname
+    return 1
+	
+}
+
+itcl::body pxitclanimationgadget::ManualGrabNextFrame {  } {
+
+    if { $animation_manualstatus == 1 } {
+	$this SaveAnimationFrame "manual"
+    }
+}
+
+itcl::body pxitclanimationgadget::SaveAnimationFrame { mode } {
+
+    
+    if { $mode == "end" } {
+	wm title $basewidget $titlestring
+	set animation_stop 1
+	set animation_manualstatus 0
+	catch { pack forget $animation_manualbutton  }
+	DisableWidget $animation_stopbutton
+	EnableWidget $animation_startbutton
+	return
+    }
+
+    if { $mode == "continue" && $animation_stop == 1 } {
+	wm title $basewidget $titlestring
+	set animation_stop 1
+	set animation_manualstatus 0
+	catch { pack forget $animation_manualbutton  }
+	return
+    }
+
+    if { $mode == "begin" } {
+	set animation_frame 1
+	set animation_stop  0
+	if { $thisparam($this,animationdelay) == "Manual" } {
+	    pack  $animation_manualbutton -side left -padx 2
+	    wm title $basewidget  "Manual Grabbing in Progress .... "
+	    set animation_manualstatus 1
+	} else {
+	    wm title $basewidget  "Grabbing in Progress .... "
+	    set animation_manualstatus 0
+	}
+	DisableWidget $animation_startbutton
+	EnableWidget $animation_stopbutton
+    }
+
+    set fname $thisparam($this,animationname) 
+    set ext [ file extension $fname  ]
+    if { $ext == ".jpg" } {
+	set fname [ file root $fname ]
+    }
+
+    set outname [ format "%s_%04d.jpg" $fname $animation_frame ]
+    wm title $basewidget  "Grabbing [ file tail $outname ]"
+
+    incr animation_frame
+
+    catch { 
+	set renwin [ [ $vtk_viewer GetRenderWidgetName ] GetRenderWindow ]
+	$vtk_viewer SaveAsTiff $renwin $outname 
+    }
+
+    if { $thisparam($this,animationdelay) != "Manual" } {
+	eval "after $thisparam($this,animationdelay) $this SaveAnimationFrame continue"
+    }
+}
+
+::itcl::body pxitclanimationgadget::SetViewerTo3DMode {} {
+    if { $vtk_viewer == 0 } {
+	return
+    }
+
+    $vtk_viewer SetDisplayMode3D
+}
+
+::itcl::body pxitclanimationgadget::ShowViewerControls { } {
+
+    if { $vtk_viewer == 0 } {
+	return
+    }
+
+    [ $vtk_viewer GetRenderer 3 ] ShowCameraControls
+}
+
+# ----------------------------------------------------------------------
+itcl::body pxitclanimationgadget::SetRendererClips { camera } {
+
+
+    set clipvalues [ $camera cget -polyclipvalues ]
+    set ren 0
+    catch { set ren [ $vtk_viewer GetRenderer 3 ] }
+    if { $ren == 0  || [ llength $clipvalues ] !=6 } { return }
+
+    for { set i 0 } { $i <= 5 } { incr i } {
+	$ren SetClipScaleValue $i [ expr round([ lindex $clipvalues $i ])]
+    }
+    $ren UpdateClippingPlanes
+
+    set clipvalues [ $camera cget -volclipvalues ]
+    set vol 0
+    catch { set vol [ $vtk_viewer GetVolumeControl ] }
+    if { $ren == 0  || [ llength $clipvalues ] !=6 } { return }
+
+    for { set i 0 } { $i <= 5 } { incr i } {
+	$vol SetClipScaleValue $i [ expr round([ lindex $clipvalues $i ] )]
+    }
+    $vol UpdateCrop
+}
+
+itcl::body pxitclanimationgadget::SetWeightedRendererClips { camera camera2 factor } {
+
+    set c1 [ $camera cget -polyclipvalues ]
+    set c2 [ $camera2 cget -polyclipvalues ]
+    if { [ llength $c1 ]  !=6  || [ llength $c2 ] !=6 } {
+	puts stderr "Bad Clip Values"
+	return
+    }
+
+    set ren [ $vtk_viewer GetRenderer 3 ]
+    for { set i 0 } { $i <= 5 } { incr i } {
+	set vv [ expr round($factor*[ lindex $c1 $i ]  + (1.0-$factor)*[lindex $c2 $i ] )]
+	$ren SetClipScaleValue $i $vv 
+    }
+    $ren UpdateClippingPlanes
+
+    set c1 [ $camera cget -volclipvalues ]
+    set c2 [ $camera2 cget -volclipvalues ]
+    if { [ llength $c1 ]  !=6  || [ llength $c2 ] !=6 } {
+	puts stderr "Bad Clip Values"
+	return
+    }
+
+    set vol 0
+    catch { 	set vol [ $vtk_viewer GetVolumeControl ]    }
+    if { $vol == 0 } {
+	return
+    }
+
+    for { set i 0 } { $i <= 5 } { incr i } {
+	set vv [ expr round($factor*[ lindex $c1 $i ]  + (1.0-$factor)*[lindex $c2 $i ] )]
+	$vol SetClipScaleValue $i $vv 
+    }
+    $vol UpdateCrop
+}
+
+# ----------------------------------------------------------------------
+itcl::body pxitclanimationgadget::GetRendererClips { camera } {
+
+    set a { -1 -1 -1 -1 -1 -1  } 
+    catch { 
+	set vol [ $vtk_viewer GetVolumeControl ]
+	set a ""
+	for { set i 0 } { $i <= 5 } { incr i } {
+	    lappend a [ $vol GetClipScaleValue $i ]
+	}
+    }
+    $camera configure -volclipvalues $a
+
+    set a { -1 -1 -1 -1 -1 -1  } 
+    set ren 0
+    catch { set ren [ $vtk_viewer GetRenderer 3 ] }
+    if { $ren !=0 } {
+	set a ""
+	for { set i 0 } { $i <= 5 } { incr i } {
+	    lappend a [ $ren GetClipScaleValue $i ]
+	}
+    }
+    $camera configure -polyclipvalues $a
+}
+# ----------------------------------------------------------------------
+itcl::body pxitclanimationgadget::GrabFromViewer { } {
+    
+    set old $thisparam($this,autoupdate)
+    set thisparam($this,autoupdate) 0
+
+    set ren [ $vtk_viewer GetRenderer 3 ]
+    set incam [ [ $ren GetRenderer ] GetActiveCamera ]
+
+    if { $spinning == 0 } {
+	set f [ format "CM_%d" [ $cameracontrol GetNextObjectIndex ] ]
+    } else {
+	set f [ format "SP_%d" [ $cameracontrol GetNextObjectIndex ] ]
+    }
+    $cameracontrol AddObject  $f
+    set newcam [ $cameracontrol GetCurrentObject ]
+    $newcam configure -filename $f
+    $newcam CopyCamera $incam
+    $newcam configure -delay 1.0
+    
+    $this GetRendererClips $newcam
+    update idletasks
+    $cameracontrol CurrentObjectModified
+    set thisparam($this,autoupdate) $old
+}
+
+itcl::body pxitclanimationgadget::UpdateFromViewer { } {
+    set old $thisparam($this,autoupdate)
+    set thisparam($this,autoupdate) 0
+    
+    set ren [ $vtk_viewer GetRenderer 3 ]
+    set incam [ [ $ren GetRenderer ] GetActiveCamera ]
+    set newcam  [ $cameracontrol GetCamera -1 ]
+    $this GetRendererClips $newcam
+    $newcam CopyCamera $incam
+    update idletasks
+    $cameracontrol CurrentObjectModified
+    set thisparam($this,autoupdate) $old
+}
+
+itcl::body pxitclanimationgadget::SendToViewer { forcemode } {
+
+    if { $forcemode == 0  &&  $thisparam($this,autoupdate)  == 0 } {
+	return
+    }
+    
+    $this SetRendererClips [ $cameracontrol GetCamera -1 ] 
+    set ren [ $vtk_viewer GetRenderer 3 ]
+    set newcam [ [ $ren GetRenderer ] GetActiveCamera ]
+    $ren CopyCamera $newcam [ [ $cameracontrol GetCamera -1 ] GetCamera ]
+
+    $ren CameraModifiedCallback
+    $ren Render
+}
+
+itcl::body pxitclanimationgadget::LoadScript { args } {
+
+    set len [ llength $args ]
+   
+    if { $len < 1 } {
+	set fname $setupfilename 
+    } else {
+	set fname [ lindex $args 0 ]
+    }
+
+    if { [ string length $fname  ] == 0 } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname  [tk_getOpenFile -title "Animation Script File" -filetypes { {"Animation Script File" {.anim}}} -initialfile $f1tail -initialdir $f1path ]
+    }
+
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    if { [ file readable $fname ] == 0 } {
+	::pxtclutil::Warning "Cannot read animation script file from $fname\n Bad File"
+	return 0
+    }
+
+    set fileid [open $fname r]
+	
+    gets $fileid line
+
+    set setupmode 0
+
+    set mode "none"
+
+    if { $line == "#Animation Script File"  } {
+	set mode "old"
+    } elseif {  $line == "#Animation Script File v2" } {
+	set mode "new"
+    }
+
+    if { $mode == "none" } {
+	close $fileid
+	::pxtclutil::Warning "Cannot read animation script file from $fname\n Bad File"
+	return
+    }
+
+
+    gets $fileid line
+    gets $fileid numcameras
+
+    if { $numcameras > 0 } {
+	
+	$cameracontrol DeleteAllObjects 1 0
+	set count 1
+	
+	for { set i 0 } { $i < $numcameras } { incr i } {
+	    set f [ format "C_%d" [ expr $i +1 ]]
+	    $cameracontrol AddObject  $f
+	    set newcam [ $cameracontrol GetCurrentObject ]
+	    $newcam configure -filename $f
+	    $newcam LoadStream $fileid $mode
+	}
+	close $fileid
+	set titlestring "Animation Tool : $fname"
+	wm title $basewidget $titlestring
+	set setupfilename $fname
+	$cameracontrol SetObject 0
+    }
+}
+
+itcl::body pxitclanimationgadget::SaveScript { args } {
+
+
+    set len [ llength $args ]
+    if { $len < 1 } {
+	set fname $setupfilename 
+    } else {
+	set fname [ lindex $args 0 ]
+    }
+
+    if { [ string length $fname  ] == 0  } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname  [tk_getSaveFile  -title "Animation Script File" -filetypes { {"Animation Script File" {.anim}}} -initialfile $f1tail -initialdir $f1path ]
+    }
+
+    if { [ string length $fname ] > 0 } {
+
+	set fileid [open $fname w]
+	
+	puts $fileid "#Animation Script File v2"
+
+	set lst [ $cameracontrol cget -itclobjectlist ]
+	puts $fileid "Focal Point \t Position \t ViewUp \t Clipping Range \t ParallelProjection \t Parallel Scale \t Duration\t Clipping Planes"
+	puts $fileid "[llength $lst]"
+	for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	    set cm [ lindex $lst $i ]
+	    $cm SaveStream $fileid
+	}
+	
+	close $fileid
+	set titlestring "Animation Tool : $fname"
+	wm title $basewidget $titlestring
+	set setupfilename $fname
+    }
+}
+
+
+
+itcl::body pxitclanimationgadget::AnimateScript { } {
+
+    set dosave $thisparam($this,animateandsave)
+
+    if { $dosave == 1 } {
+	set ok [ $this GetAnimationName ]
+	if { $ok == 0 } {
+	    return
+	}
+
+	set thisparam($this,animationdelay) "Manual"
+	set animation_manualstatus 1
+    }
+
+    
+	
+    set ren [ $vtk_viewer GetRenderer 3 ]
+    set newcam [ [ $ren GetRenderer ] GetActiveCamera ]
+
+    if { $thisparam($this,scriptdivide)  > 30 } {
+	set thisparam($this,scriptdivide) 30 
+    } elseif { $thisparam($this,scriptdivide) < 1 } {
+	set thisparam($this,scriptdivide) 1
+    }
+
+    if { $thisparam($this,scriptunit)  > 5} {
+	set thisparam($this,scriptunit) 5 
+    } elseif { $thisparam($this,scriptunit) < 0.1 } {
+	set thisparam($this,scriptunit) 0.1
+    }
+
+
+    set numdiv  $thisparam($this,scriptdivide) 
+
+    set del [ expr round((1000 * $thisparam($this,scriptunit)) / $numdiv) ]
+    set lst [ $cameracontrol cget -itclobjectlist ]
+    set numlst [ llength $lst ]
+    set maxi [ expr $numlst -1 ]
+
+    set endframe [ expr $thisparam($this,scriptend) -1 ]
+    if { $endframe> $maxi } {
+	set endframe $maxi
+    } 
+
+    set begframe [ expr $thisparam($this,scriptbegin) -1 ]
+    if { $begframe < 0 } {
+	set begframe 0
+    }
+	
+    if { $begframe > $endframe } {
+	set begframe [ expr $endframe -1 ]
+	if { $begframe < 0 } {
+	    set begframe 0
+	}
+    }
+	
+    for { set i $begframe } { $i < $endframe  } { incr i } {
+	set cm [ lindex $lst $i ]
+	$ren CopyCamera $newcam [ $cm GetCamera ]
+
+	$this SetRendererClips $cm
+	$ren Render
+
+	set dv [ $cm cget -delay ]
+	set ndiv [ expr round($dv * $numdiv)]
+	update idletasks
+	if { $dosave == 1 } {
+	    if { $i == 0 } {
+		$this SaveAnimationFrame begin
+	    } else {
+		$this ManualGrabNextFrame
+	    }
+	    wm withdraw $basewidget
+	}
+	after $del
+	
+
+	if { $i < $endframe } {
+	    set cm2 [ lindex $lst [ expr $i +1 ] ]
+	    for { set j 1 } { $j < $ndiv } { incr j } {
+		set factor [ expr ($j+0.01)/($ndiv+0.01)]
+
+		$this SetWeightedRendererClips $cm2 $cm $factor 
+		$ren InterpolateCamera $newcam [ $cm2 GetCamera ] [ $cm GetCamera ] $factor 
+		$ren Render
+		update idletasks
+		if { $dosave == 1 } {
+		    $this ManualGrabNextFrame
+		}
+		after $del
+	    }
+	}
+    }
+    if { $dosave == 1 } {
+	$this SaveAnimationFrame end
+	$this ShowWindow
+    }
+    $ren CameraModifiedCallback
+}
+
+
+itcl::body pxitclanimationgadget::AddSpin { angle } {
+
+    set spinning 1
+    $this UpdateFromViewer
+    set ren [ $vtk_viewer GetRenderer 3 ]
+
+    set md $thisparam($this,spinazimuth)
+
+
+
+    set angle [ expr abs($angle) ]
+    set nsteps [ expr round(360.0/$angle) ]
+    
+    if { $thisparam($this,spinpositive) == 0 } {
+	set angle [ expr -1.0*$angle]
+    }
+
+    after 200
+    for { set i 1 } { $i <= $nsteps } { incr i } {
+	$ren Rotate $angle $md
+	update idletasks
+	$this GrabFromViewer
+	after 200
+    }
+    set spinning 0
+}
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclarticulatedmodel.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclarticulatedmodel.tcl
new file mode 100644
index 0000000..197f8ac
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclarticulatedmodel.tcl
@@ -0,0 +1,563 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclarticulatedmodel 1.0
+
+# 	$Id: pxitclarticulatedmodel.tcl,v 1.2 2005/10/05 20:36:33 xenios Exp xenios $	
+
+
+
+
+
+
+package require pxvtable 1.0
+package require pxitclimage 1.0
+
+itcl::class pxitclarticulatedmodel {
+
+    inherit pxitclbasecontrol
+
+    public variable jointlist     [ list ox oy oz rx ry rz  ]
+    public variable lowerlist [ list -50  -50   -50 -60 -60 -60 ]
+    public variable upperlist [ list  100  100  100  60  60  60  ]
+    public variable numberofparts 2
+    public variable olist  ""
+
+    public variable updatecallback 0
+    public variable tmodel 0
+
+    # ---------------------
+    protected variable jointmenu 0
+    protected variable jointgui  0
+    protected variable translationlabel 0
+    protected variable nonlineargui 0
+    private   common   thisparam        
+
+
+
+    # ------------------------------------------------------------------
+
+    constructor { par callback } {
+	pxitclbasecontrol::constructor $par 
+    } {
+	set updatecallback "$par ShowSurfaces articulatedmodel"
+	InitializeArticulatedModelTool
+    }
+
+    private method InitializeArticulatedModelTool { } 
+    public method  Initialize { widget { isinside 0 } }
+
+    # --------------------------------------------------------------------
+
+    public method Load { fname } 
+    public method Save { fname } 
+    public method FitNonLinear { mode }
+    public method Identity { part } 
+
+    public method ResetParameters { }
+    public method InitializeTransformation { } 
+    public method UpdateTransformation { }
+    public method UpdateAllTransformations { }
+
+    public method UpdateGUIFromTransformation { updatedisplay }
+    public method InitializeGUIFromTransformation { updatedisplay } 
+    public method CreateJointGUI { widget } 
+
+    public method GetTransformation { }  { return $tmodel }
+
+
+}
+# --------------------------------------------------------------------------------------------------------------------------
+itcl::body pxitclarticulatedmodel::Identity { part } {
+
+    if { $tmodel == 0 } {
+	return
+    }
+
+    if { $part == "all" } {
+	 $tmodel Identity
+
+    } else {
+	set index [ $jointmenu index $thisparam($this,jointindex) ]
+	set tsim [ $tmodel GetTransform $index ]
+	$tsim Identity
+    }
+
+    UpdateGUIFromTransformation 1 
+    return
+}
+
+# ------------------------------------------------------------------------------------------------------------------------
+itcl::body pxitclarticulatedmodel::FitNonLinear { mode  } {
+
+    if { $tmodel == 0 } {
+	return
+    }
+
+    if { $mode == "setup" } {
+	if { $nonlineargui == 0 } {
+	    set thisparam($this,bsplinesmoothness) 0.001
+	    set thisparam($this,bsplinespacing) 10
+	    set thisparam($this,bsplinenumpoints) 5000
+	    set thisparam($this,bsplinestep) 0.05
+	    set thisparam($this,bsplinenumsteps) 1
+	    
+	    
+	    set nonlineargui [ toplevel $basewidget.[pxvtable::vnewobj ] ]
+	    wm withdraw $nonlineargui
+	    eval "wm protocol $nonlineargui WM_DELETE_WINDOW { wm withdraw $nonlineargui }"
+	    wm  title $nonlineargui "Articulated --> BSpline Converter"
+	    wm  geometry $nonlineargui 400x200
+	    
+	    set w $nonlineargui
+	    
+	    set top [ LabelFrame:create  $w.a -text "Parameters" ]
+	    set bot [ frame  $w.b ]
+	    pack $bot -side bottom -expand false -fill x
+	    pack $w.a -side top -expand false -fill x
+	    
+	    set cw [ [ iwidgets::labeledwidget $top.0  -labeltext "Number of Points:"  ] childsite ]
+	    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,bsplinenumpoints) ] 1000 2000 5000 10000
+	    pack $cw.optmenu  -expand f
+	    pack $top.0 -side top -expand f
+
+	    set cw [ [ iwidgets::labeledwidget $top.1  -labeltext "Spacing (mm):"  ] childsite ]
+	    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,bsplinespacing) ] "1" "1.5" "2" "2.5" "3" "4" "5" "6" "10" "20" "30" "40" 
+	    pack $cw.optmenu  -expand f
+	    pack $top.1 -side top -expand f
+	    
+	    set cw [ [ iwidgets::labeledwidget $top.2  -labeltext "Smoothness:"  ] childsite ]
+	    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,bsplinesmoothness) ] "0.001" "0.01" "0.1" "0.5" "1.0" 
+	    pack $cw.optmenu  -expand f
+	    pack $top.2 -side top -expand f
+
+	    set cw [ [ iwidgets::labeledwidget $top.3  -labeltext "Num Steps :"  ] childsite ]
+	    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,bsplinenumsteps) ] 1 2 4 8 16 32
+	    pack $cw.optmenu  -expand f
+	    pack $top.3 -side top -expand f
+	    
+	    eval "button $bot.1 -text \"Fit\" -command { $this FitNonLinear compute  } "	    
+	    eval "button $bot.2 -text \"Close\" -command { wm withdraw $nonlineargui  } "	    
+	    pack $bot.2 -side right -padx 10
+	    pack $bot.1 -side left -padx 10
+	}
+	wm deiconify $nonlineargui
+	return
+    }
+    
+    if { $mode != "compute" } { return }
+    
+    set ident [ vtkIdentityTransform [ pxvtable::vnewobj ]]
+    
+    set combo [ vtkpxComboTransform [ pxvtable::vnewobj ]]
+    set grid [ $combo GetGridTransform ]
+    $grid InitializeDisplacementGrid  [ $tmodel GetRegionLabel ] $thisparam($this,bsplinespacing) 0.05 $ident 
+    $ident Delete
+    
+    $tmodel InitializeComboTransform  $combo $thisparam($this,bsplinenumpoints) \
+	$thisparam($this,bsplinenumsteps) $thisparam($this,bsplinesmoothness)
+    
+    $parent SetTransformationToParentControl $combo "nonl_artic"
+
+    set fname  [tk_getSaveFile -title "Saving B-Spline Transformation"  -filetypes { {"Combo Transform Files" {.grd}} } ]
+    if { [ string length $fname  ] > 0 } {
+	set ok [ $combo Save $fname ]
+	if { $ok == 0 } {
+	    ::pxtclutil::Warning "Failed to save combo transform in $fname\n"
+	}
+    }
+    $combo Delete
+    return
+}
+# ------------------------------------------------------------------------------------------------------------------------
+itcl::body pxitclarticulatedmodel::Load { fname } {
+
+    if { $fname == "" } {
+	
+	set typelist { 
+	    {"PolySimilarity Transforms" {.psim}} 
+	    {"All Files" {*}}}
+	
+	set f [tk_getOpenFile -title "Load Transformation" -filetypes $typelist ]
+	
+	if { [ string length $f ] > 0 } {
+	    set fname $f
+	}
+    }
+
+    if { [ string length $f ] > 0 } {
+	if { $tmodel == 0 } {
+	    set tmodel [ vtkpxPolySimilarityTransform [ pxvtable::vnewobj ] ]
+	}
+	set ok [ $tmodel Load $fname ]
+	if { $ok ==1 } {
+	    $this InitializeGUIFromTransformation 1
+	    SetTitle "Articulated Tool [ file tail $fname ]"
+	}
+    }
+}
+
+itcl::body pxitclarticulatedmodel::Save { fname } {
+
+    if { $tmodel == 0 } {
+	return
+    }
+
+
+    if { [ string length $fname ] == 0 } {
+	set fname  [tk_getSaveFile -title "Saving Transformation"  -filetypes { {"PolySimilarity Transform Files" {.psim}} } ]
+    }
+    if { [ string length $fname ] > 0 } {
+	$tmodel Save $fname
+	$this UpdateGUIFromTransformation 0
+    }
+}
+
+# -------------------------------------------------------------------------------------------------------------------------
+itcl::body pxitclarticulatedmodel::InitializeArticulatedModelTool {  } {
+
+    ResetParameters
+
+}
+    
+
+# --------------------------------------------------------------------------------------------------------------------------
+
+itcl::body pxitclarticulatedmodel::ResetParameters { } {
+    
+    set thisparam($this,jointindex) "Global"
+
+    set thisparam($this,rx) 0.0
+    set thisparam($this,ry) 0.0
+    set thisparam($this,rz) 0.0
+    set thisparam($this,ox) 0.0
+    set thisparam($this,oy) 0.0
+    set thisparam($this,oz) 0.0
+
+    set thisparam($this,p_sectorangle) 5.0
+    set thisparam($this,p_blend)       2
+    set thisparam($this,p_blendname)   "Both"
+    set thisparam($this,p_cubic)       0
+    set thisparam($this,p_smooth)      0
+    set thisparam($this,p_smoothradius) 2.0
+    set thisparam($this,p_thetablend)   1.0
+    set thisparam($this,p_zblend)       3.0
+
+
+    set thisparam($this,enableguiupdate) 1
+}
+# --------------------------------------------------------------------------------------------------------------------------
+itcl::body pxitclarticulatedmodel::UpdateTransformation { } {
+
+    if { $tmodel == 0 } {
+	return
+    }
+
+    set index [ $jointmenu index $thisparam($this,jointindex) ]
+    set tsim [ $tmodel GetTransform $index ]
+
+    set nlist [ list "None" "Fold" "Both" ]
+    set thisparam($this,p_blend) [ lsearch -exact $nlist $thisparam($this,p_blendname) ]
+
+    $tsim SetFreezeUpdates 1    
+    $tsim SetBlendedMode     $thisparam($this,p_blend)
+    $tsim SetCubicBlending   $thisparam($this,p_cubic)
+    $tsim SetSmoothingMode   $thisparam($this,p_smooth)      
+    $tsim SetSmoothingRadius $thisparam($this,p_smoothradius)
+
+
+    $tsim SetBlendingWindow $thisparam($this,p_thetablend)
+    $tsim SetZBlendingSize $thisparam($this,p_zblend)
+    $tsim SetMinimumSectorAngle $thisparam($this,p_sectorangle)
+
+    
+    if { $index == 0 } {
+	$tsim Put 0 $thisparam($this,ox)
+	$tsim Put 1 $thisparam($this,oy)
+	$tsim Put 2 $thisparam($this,oz)
+    } else {
+	$tsim Put 3 $thisparam($this,ox)
+	$tsim Put 4 $thisparam($this,oy)
+	$tsim Put 5 $thisparam($this,oz)
+    }
+    
+    $tsim Put 6 $thisparam($this,rx)
+    $tsim Put 7 $thisparam($this,ry)
+    $tsim Put 8 $thisparam($this,rz)
+    
+    $tsim SetFreezeUpdates 0
+    $tsim Put 9 100.0
+    $tsim Modified
+
+    $tmodel Modified
+    if { $updatecallback !=0 && $thisparam($this,enableguiupdate) ==1 } { 
+	#	puts stderr "Calling $updatecallback"
+	eval $updatecallback 
+    } 
+
+    UpdateGUIFromTransformation 0
+}
+# --------------------------------------------------------------------
+itcl::body pxitclarticulatedmodel::UpdateAllTransformations { } {
+
+    if { $tmodel == 0 } {
+	return
+    }
+
+#    puts stderr "Update All Transformation Init $thisparam($this,p_blend) , $thisparam($this,p_blendname) "
+
+    set nlist [ list "None" "Fold" "Both" ]
+    set thisparam($this,p_blend) [ lsearch -exact $nlist $thisparam($this,p_blendname) ]
+
+#    puts stderr "Update All Transformation $thisparam($this,p_blend) , $thisparam($this,p_blendname) "
+
+
+    set numberofparts [ $tmodel GetNumberOfTransformations ]
+    for { set i 0 } { $i < $numberofparts } { incr i } {
+
+	set tsim [ $tmodel GetTransform $i ]
+	$tsim SetFreezeUpdates 1    
+	$tsim SetBlendedMode    $thisparam($this,p_blend)
+	$tsim SetCubicBlending   $thisparam($this,p_cubic)
+	$tsim SetSmoothingMode   $thisparam($this,p_smooth)      
+	$tsim SetSmoothingRadius $thisparam($this,p_smoothradius)
+	$tsim SetBlendingWindow $thisparam($this,p_thetablend)
+	$tsim SetZBlendingSize $thisparam($this,p_zblend)
+	$tsim SetMinimumSectorAngle $thisparam($this,p_sectorangle)
+	$tsim SetFreezeUpdates 0
+	$tsim Modified
+    }
+    $tmodel Modified
+    if { $updatecallback !=0 && $thisparam($this,enableguiupdate) ==1 } { 
+	eval $updatecallback 
+    } 
+
+    UpdateGUIFromTransformation 0
+}
+# --------------------------------------------------------------------
+itcl::body pxitclarticulatedmodel::InitializeGUIFromTransformation {  updatedisplay } {
+
+    if { $tmodel == 0 } {
+	return
+    }
+
+    set numberofparts [ $tmodel GetNumberOfTransformations ]
+    set abdomenpieces [ expr $numberofparts - 7 ]
+    EnableUI $jointgui
+    
+    set numoptions [ expr [ $jointmenu index last ] +1 ]
+
+    for { set i [ expr $numoptions -1 ] } { $i >= 1 } { set i [ expr $i -1 ] } {
+	$jointmenu delete $i
+    }
+
+    for { set i 1 } { $i < $numberofparts } { incr i } {
+	
+	set name "Joint_${i}"
+	set name2 [ [ $tmodel GetTransform $i ] GetJointName ]
+	if { $name2 != "Joint" } {
+	    set name $name2
+	}
+#	puts stdout "Adding $name $i"
+	$jointmenu add radio -label $name -variable [ itcl::scope thisparam($this,jointindex) ] 
+	eval "$jointmenu entryconfigure $i -command { $this UpdateGUIFromTransformation 0 }"
+    }
+
+    set thisparam($this,currentjoint) "Global"
+    $this UpdateGUIFromTransformation $updatedisplay
+}
+
+
+itcl::body pxitclarticulatedmodel::UpdateGUIFromTransformation { updatedisplay  } {
+
+    if { $tmodel == 0 } {
+	return
+    }
+
+ 
+    set index [ $jointmenu index $thisparam($this,jointindex) ]
+
+#    puts stderr "Current Transformation Index = $index"
+
+    set tsim [ $tmodel GetTransform $index ]
+#    puts stderr "[ $tsim GetClassName ] "
+
+    set thisparam($this,p_blend) [ $tsim GetBlendedMode ]
+    set thisparam($this,p_theablend) [ $tsim GetBlendingWindow ]
+    set thisparam($this,p_zblend) [ $tsim GetZBlendingSize ]
+    set thisparam($this,p_sectorangle) [ $tsim GetMinimumSectorAngle ]
+    set thisparam($this,p_cubic) [ $tsim GetCubicBlending ]
+    set thisparam($this,p_smooth)       [ $tsim GetSmoothingMode ]
+    set thisparam($this,p_smoothradius) [ $tsim GetSmoothingRadius ]
+
+
+
+    set nlist [ list "None" "Fold" "Both" ]
+    set thisparam($this,p_blendname) [ lindex $nlist $thisparam($this,p_blend) ]
+
+
+    if { $index == 0 } {
+	set thisparam($this,ox) [ $tsim Get 0 ]
+	set thisparam($this,oy) [ $tsim Get 1 ]
+	set thisparam($this,oz) [ $tsim Get 2 ]
+	$translationlabel configure -text "Global Translation:"
+	
+
+
+    } else {
+	set thisparam($this,ox) [ $tsim Get 3 ]
+	set thisparam($this,oy) [ $tsim Get 4 ]
+	set thisparam($this,oz) [ $tsim Get 5 ]
+	$translationlabel configure -text "Joint Position:"
+    }
+    
+    set thisparam($this,rx) [ $tsim Get 6 ]
+    set thisparam($this,ry) [ $tsim Get 7 ]
+    set thisparam($this,rz) [ $tsim Get 8 ]
+    
+    if { $updatedisplay == 1 } {
+	if { $updatecallback !=0 } { eval $updatecallback } 
+    }
+
+}
+# --------------------------------------------------------------------
+
+itcl::body pxitclarticulatedmodel::CreateJointGUI { w  } {
+
+    set b [ LabelFrame:create  $w.a -text "Joint Parameters" ]
+    set g [ LabelFrame:create  $w.b -text "Global Parameters" ]
+    pack $w.a $w.b -side top -expand false -fill x
+
+    set top [ frame $b.1 ] 
+    set md1 [ frame $b.2 ] 
+    set md2 [ frame $b.3 ] 
+    set md3 [ frame $g.4 ] 
+    set bot [ frame $g.5 ] 
+    
+    pack $bot $md3 -side bottom -expand true -fill x
+    pack $top $md1 $md2  -side top -expand true -fill x
+
+
+    set cw [ [ iwidgets::labeledwidget $top.1  -labeltext "Joint:"  ] childsite ]
+    set jointmenu [ tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,jointindex) ] "Global" ]
+    pack $cw.optmenu  -expand f
+    pack $top.1 -side left -expand f
+    
+    eval "$cw.optmenu.menu entryconfigure 0 -command { $this UpdateGUIFromTransformation 0 }"
+
+    checkbutton $top.2 -variable [ itcl::scope thisparam($this,enableguiupdate) ] -text "Update Display" 
+    pack $top.2 -side right -expand f
+    
+
+    set translationlabel [ label $md1.1 -text "Global Translation:" ]
+    pack  $md1.1 -side left 
+    
+    # Origin 
+    for { set i 2 } { $i <=4 } { incr i } {
+
+	set index [ expr $i -2 ]
+	set vname [ lindex $jointlist $index ]
+	set lower [ lindex $lowerlist $index ]
+	set upper [ lindex $upperlist $index ]
+	scale $md1.$i -variable  [ itcl::scope thisparam($this,$vname) ]  -from $lower -to $upper -orient horizontal  -digits 5 -resolution 0.1
+	eval "bind $md1.$i <ButtonRelease> \{ $this UpdateTransformation \}"
+	pack $md1.$i -side left  -expand f -fill x
+    }
+
+    label $md2.5 -text "Rotations:"
+    pack $md2.5 -side left 
+
+    for { set i 6 } { $i <=8 } { incr i } {
+
+	set index [ expr $i -3 ]
+	set vname [ lindex $jointlist $index ]
+	set lower [ lindex $lowerlist $index ]
+	set upper [ lindex $upperlist $index ]
+	scale $md2.$i -variable [ itcl::scope  thisparam($this,$vname) ] -from $lower -to $upper -orient horizontal  -digits 5 -resolution 0.01 
+	eval "bind $md2.$i <ButtonRelease> \{ $this UpdateTransformation \}"
+	pack $md2.$i -side left  -expand f -fill x
+    }
+    eval "button $md2.10 -text \"Identity\" -command { $this Identity current  } "	    
+    pack $md2.10 -side right -padx 2
+
+
+    iwidgets::entryfield $md3.16 -labeltext "Blend Theta:"  -width 2 -validate real -textvariable [ itcl::scope thisparam($this,p_thetablend) ] -relief sunken 
+    iwidgets::entryfield $md3.17 -labeltext "Blend Z:"  -width 2 -validate real -textvariable [ itcl::scope thisparam($this,p_zblend) ] -relief sunken 
+    
+    iwidgets::entryfield $md3.18 -labeltext "Sector Angle:"  -width 2 -validate real -textvariable [ itcl::scope thisparam($this,p_sectorangle) ] -relief sunken 
+											
+    eval "button $md3.19 -text \"Upd\" -command { $this UpdateTransformation } "	    
+
+    pack $md3.19 -side right -padx 2
+    pack  $md3.16 $md3.17 $md3.18  -side left -padx 1 -expand t -fill x
+
+    
+    set cw [ [ iwidgets::labeledwidget $bot.12  -labeltext "Mode:"  ] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,p_blendname) ] "None" "Fold" "Both"
+    pack $cw.optmenu  -expand f
+    
+    checkbutton $bot.13 -variable [ itcl::scope  thisparam($this,p_cubic) ] -text Cubic 
+    checkbutton $bot.14 -variable [ itcl::scope  thisparam($this,p_smooth) ] -text Smooth 
+    iwidgets::entryfield $bot.15 -labeltext "Radius:"  -width 2 -validate real -textvariable [ itcl::scope thisparam($this,p_smoothradius) ] -relief sunken 
+    eval "button $bot.16 -text \"Upd All\" -command { $this UpdateAllTransformations } "
+
+    pack $bot.12 $bot.13 $bot.14 $bot.15 $bot.16  -side left -padx 1 -expand t -fill x
+
+}
+
+itcl::body pxitclarticulatedmodel::Initialize { widget { isinside 0 } } {
+
+    if { $isinside == 0 } {
+        set basewidget [ toplevel $widget ]
+	wm geometry $basewidget 460x270
+	wm withdraw $basewidget
+	SetTitle "Articulated Tool"
+	eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    } else {
+	set basewidget [ frame $widget ]
+    }
+
+    set bbar [ frame $basewidget.bot ]; pack $bbar -side bottom -expand f -fill x    
+    
+    set jointgui [ frame $basewidget.top -height 200 ]; pack $widget.top -side top -expand t -fill both 
+    CreateJointGUI $jointgui
+    DisableUI $jointgui
+
+    
+    eval "button $bbar.load  -text \"Load\"     -command { $this Load \"\" } "
+    eval "button $bbar.save  -text \"Save\"     -command { $this Save \"\" } "
+    eval "button $bbar.ident -text \"Identity\" -command { $this Identity all  } "
+    eval "button $bbar.fit   -text \"FitNonLinear \" -command { $this FitNonLinear setup  } "
+
+
+    eval "button $bbar.close -text \"Close\"    -command { $this HideWindow  } "
+    pack $bbar.close -side right 
+    pack $bbar.load $bbar.save $bbar.ident $bbar.fit -side left -expand f -fill x -padx 1
+
+}
+# --------------------------------------------------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclatlasgadget.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclatlasgadget.tcl
new file mode 100644
index 0000000..6bfe9c1
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclatlasgadget.tcl
@@ -0,0 +1,183 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+# This tool loads and interogates the FUWFU Pickatlas version 2.4 
+# It also   interogates the Yale Atlas if present
+#
+# No part of the atlas software/images is integrated by BioImage Suite, it simply
+# looks for the atlas software and loads the ROIs
+#
+#     The wfu_pickatlas toolbox and user manual can be obtained from:
+#        www.fmri.wfubmc.edu 
+
+
+package provide pxitclatlasgadget 1.0
+
+# 	$Id: pxitclatlasgadget.tcl,v 1.2 2004/02/03 17:36:31 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+package require  vtkpxcontrib 1.1
+package require  pxtclutil    1.0
+package require  pxvtable     1.0
+package require  Itcl         3.2
+package require pxitclwfuatlasgadget 1.0
+package require pxitclyaleatlasgadget 1.0
+# ----------------------------------------------------------------------------------------------
+
+itcl::class pxitclatlasgadget {
+
+    inherit pxitclbasecontrol
+    
+    # Generic Stuff 
+
+    protected variable wfugadget 0
+    protected variable yalegadget 0
+
+    public variable enable_yalegadget 1
+    public variable enable_wfugadget  1
+
+    # public 
+
+    
+    #
+    constructor { par args } {
+	pxitclbasecontrol::constructor $par
+    } {
+	InitializeAtlasGadget
+    }
+
+    protected method InitializeAtlasGadget { }
+
+    public method Initialize { widget }
+    public method DelayedInitialize { }
+    public method AddToMenuButton { mb args }
+    public method IdentifyPoint { x y z } 
+    public method SetError { txt }
+    public method SetImageFromObject   { img obj }
+    public method ShowGadget { md }
+
+}
+
+
+::itcl::body pxitclatlasgadget::AddToMenuButton { mb args} {
+
+    foreach gadg [ list $yalegadget $wfugadget ] { 
+	if { $gadg !=0 } {
+	    $gadg AddToMenuButton $mb $args
+	}
+    } 
+
+}
+
+::itcl::body pxitclatlasgadget::ShowGadget { md } {
+
+    if { $md == "wfu" } {
+	$wfugadget ShowWindow
+    } else {
+	$yalegadget ShowWindow
+    }
+}
+
+
+itcl::body pxitclatlasgadget::InitializeAtlasGadget { } {
+
+    if { $enable_wfugadget } {
+	set wfugadget  [ [ pxitclwfuatlasgadget \#auto $this ] GetThisPointer ]
+    }
+    
+    if { $enable_yalegadget == 1 } {
+	set yalegadget [ [ pxitclyaleatlasgadget \#auto $this ] GetThisPointer ]
+    }
+
+#    puts stderr "Created gadgets wfu=$wfugadget, yale=$yalegadget"
+}
+
+itcl::body pxitclatlasgadget::Initialize { widget } { 
+
+    set i 0
+
+
+    foreach gadg [ list $wfugadget $yalegadget ] { 
+	if { $gadg !=0 } {
+	    $gadg Initialize ${widget}_$i
+	    incr i
+	}
+    } 
+
+}
+
+itcl::body pxitclatlasgadget::DelayedInitialize { } { 
+
+    foreach gadg [ list $wfugadget $yalegadget ] { 
+	if { $gadg !=0 } {
+	    $gadg DelayedInitialize
+	    $gadg LoadAtlas
+	}
+    }
+
+    set fullyinitialized 1
+}
+
+itcl::body pxitclatlasgadget::IdentifyPoint { x y z }  {
+
+    foreach gadg [ list $wfugadget $yalegadget ] { 
+	if { $gadg !=0 } {
+	    $gadg IdentifyPoint $x $y $z
+	}
+    }
+}
+
+itcl::body pxitclatlasgadget::SetImageFromObject { img obj }  {
+
+    foreach gadg [ list $wfugadget $yalegadget ] { 
+	if { $gadg !=0 } {
+	    $gadg SetImageFromObject $img $obj
+	}
+    }
+}
+
+
+itcl::body pxitclatlasgadget::SetError { txt } { 
+
+    foreach gadg [ list $wfugadget $yalegadget ] { 
+	if { $gadg !=0 } {
+	    $gadg SetError $txt
+	}
+    }
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclbaresimpleviewer.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclbaresimpleviewer.tcl
new file mode 100755
index 0000000..fde1122
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclbaresimpleviewer.tcl
@@ -0,0 +1,75 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclbaresimpleviewer.tcl,v 1.1 2003/09/03 18:17:05 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package require vtkpxcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+
+
+wm withdraw .
+set breg [ pxitclbaseimageviewer \#auto 0 ]
+$breg configure -appname pxitclbaresimpleviewer
+$breg configure -show_standard_images 0
+$breg configure -enable_multisubjectcontrol 0
+$breg configure -enable_rendering_on_startup  0
+$breg configure -enable_headercontrol  0
+$breg configure -enable_importcontrol  0
+$breg configure -enable_imageutility  0
+$breg configure -enable_landmarkcontrol  0
+$breg configure -enable_overlaytool  0
+$breg configure -enable_histcontrol  0
+$breg configure -enable_displaymenu  0
+$breg configure -enable_helpmenu  0
+$breg InitializeMosaicViewer .[pxvtable::vnewobj ] 1
+
+set argc [llength $argv]
+
+if { $argc > 0 } {   $breg LoadImage [lindex $argv 0]   }
+if { $argc > 1 } {  [ $breg cget -overlaytool ] LoadFunctionalImage [lindex $argv 1] }
+if { $argc > 2 } {   [ $breg cget -overlaytool ] LoadTransformation [lindex $argv 2] }
+
+
+set vr [ $breg GetViewer ]
+$breg ShowWindow
+$vr SetEnableRendering 1
+#after 100 "$vr UpdateDisplay"
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclbase4dimageviewer.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclbase4dimageviewer.tcl
new file mode 100644
index 0000000..01796c7
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclbase4dimageviewer.tcl
@@ -0,0 +1,230 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+package provide pxitclbase4dimageviewer 1.0
+
+# 	$Id: pxitclbase4dimageviewer.tcl,v 1.2 2005/11/09 22:04:54 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+package require vtkpxcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+package require Itcl 
+package require Iwidgets 
+package require pxitclcreatesolidcontrol 1.0
+
+
+# ----------------------------------------------------------------------------
+
+itcl::class pxitclbase4dimageviewer {
+
+    inherit pxitclbaseimageviewer
+
+    protected variable multisplinestackcontrol 0
+    public    variable enable_multisplinestackcontrol 0
+
+    protected variable tstackcontrol 0 
+    public    variable enable_tstackcontrol 1
+
+    public    variable abaquscontrol 0 
+    public    variable enable_abaquscontrol 1 
+
+    public    variable createsolidcontrol 0
+    public    variable enable_createsolidcontrol 1
+
+
+    public    variable numberofsurfaces   5
+
+    constructor { par } {
+	::pxitclbaseimageviewer::constructor $par
+    } {
+	InitializeBase4dImageViewer
+    }
+
+    protected method InitializeBase4dImageViewer { } 
+
+    protected method Create4DControls { cardiacmenu } 
+    protected method SetControlsViewer { viewer control } 
+
+    public method InitializeDisplay { widget standalone}
+    public method SetImageFromObject { img obj } 
+
+    public    method GetTstack        { index } 
+    public    method GetViewer { }
+}
+
+# ----------------------------------------------------------------------------
+
+itcl::body pxitclbase4dimageviewer::InitializeBase4dImageViewer { } {
+
+    set appname "volume viewer"
+    set enable_landmarkcontrol 1
+    set enable_surfaceobjectmap 0
+    set enable_multisubjectcontrol 0
+    set enable_talairachoption 0
+    set enable_landmarkclicks  0
+    set enable_overlaytool 0
+    set show_standard_images 0
+
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbase4dimageviewer::SetImageFromObject { img obj } {
+
+    set a [ pxitclbaseimageviewer::SetImageFromObject $img $obj ]
+    if { $a==0 } { return 0 }
+    
+    if { $multisplinestackcontrol != 0 } {
+	$multisplinestackcontrol SetImage [ $currentimage GetImage ] [ $currentimage GetOrientation ] 0 0
+    }
+
+    if { $tstackcontrol != 0 } {
+	$tstackcontrol SetImage [ $currentimage GetImage ] [ $currentimage GetOrientation ] 0 0
+    }
+
+    if { $abaquscontrol != 0 } {
+	$abaquscontrol SetImage [ $currentimage GetImage ] [ $currentimage GetOrientation ] 
+    }
+
+	
+}
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclbase4dimageviewer::GetTstack { index } {
+    if { $tstackcontrol != 0 } {
+	return [ $tstackcontrol GetTriangulatedStack $index ] 
+    }
+
+    puts stderr "Error in GetTstack\n"
+    return 0
+}
+
+itcl::body pxitclbase4dimageviewer::GetViewer  { } {
+    return $vtk_viewer 
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbase4dimageviewer::Create4DControls { cardiacmenu } {
+
+    if { $enable_multisplinestackcontrol == 1 } {
+
+	set tnote [ toplevel $basewidget.[ pxvtable::vnewobj ] ]
+	eval "wm protocol $tnote WM_DELETE_WINDOW { wm withdraw $tnote  }"
+	wm title $tnote "Spline Surface Control"
+	wm withdraw $tnote
+	
+	set note $tnote.notebook
+
+	iwidgets::tabnotebook $note -tabpos n
+	pack $note -side top -expand t -fill both
+
+	set dframe [ $note add -label "Surface" ] 
+	set eframe [ $note add -label "Multi" ] 
+	set fframe [ $note add -label "Segment" ] 
+	$note view "Surface"
+    
+	set multisplinestackcontrol [ vtkpxGUI4DSplineStackControl [ pxvtable::vnewobj ]]
+	$multisplinestackcontrol Initialize $dframe $eframe $fframe 1
+	SetControlsViewer $vtk_viewer $multisplinestackcontrol 
+	eval "$cardiacmenu add command -label \"Spline Surface Control\" -command { wm deiconify $tnote }"
+    }
+
+    if { $enable_tstackcontrol == 1 } {
+	
+	set tstackcontrol [ vtkpxGUI4DTriangulatedStackControl [ pxvtable::vnewobj ]]
+	
+	#set t [ toplevel $basewidget.[ pxvtable::vnewobj ] ] ; wm withdraw $t
+	$tstackcontrol SetCallback $tstackcontrol -1
+	set t [ $tstackcontrol Initialize $basewidget 0  ]
+	eval "wm protocol $t WM_DELETE_WINDOW { wm withdraw $t  }"
+	wm title $t "T-stack Control"
+	SetControlsViewer $vtk_viewer $tstackcontrol 
+	eval "$cardiacmenu add command -label \"Tstack Control\" -command { wm deiconify $t }"
+
+	if { $enable_createsolidcontrol == 1 } {
+	    set createsolidcontrol  [ [ pxitclcreatesolidcontrol \#auto $this ] GetThisPointer ]
+	    set t2 [ $createsolidcontrol Initialize $basewidget.[pxvtable::vnewobj] $this ]
+	    eval "wm protocol $t2 WM_DELETE_WINDOW { wm withdraw $t2  }"
+	    wm title $t2 "Create-Solid Control"
+	    eval "button $t.bbot -text \"(Create) Solid Control\" -command {  wm deiconify $t2 }"
+	    pack $t.bbot -side bottom -expand f -fill x -pady 2
+	}
+    }
+
+    if { $enable_abaquscontrol == 1 } {
+
+	set abaquscontrol [ vtkpxGUIFemPostControl [ pxvtable::vnewobj ]]
+	$abaquscontrol SetCallback $abaquscontrol -1
+	set t [ $abaquscontrol Initialize $basewidget 0 ]	
+	eval "wm protocol $t WM_DELETE_WINDOW { wm withdraw $t  }"
+	wm title $t "Abaqus post Control"
+	SetControlsViewer $vtk_viewer $abaquscontrol 
+	eval "$cardiacmenu add command -label \"Abaqus Post Control\" -command { wm deiconify $t }"
+    }
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbase4dimageviewer::SetControlsViewer { viewer control }  {
+
+
+    $control SetRenderer [ $viewer GetMultiRenderer 3 ] 0 0
+    $control SetRenderer [ $viewer GetMultiRenderer 0 ] 1 1
+    $control SetRenderer [ $viewer GetMultiRenderer 1 ] 2 1
+    $control SetRenderer [ $viewer GetMultiRenderer 2 ] 3 1
+
+
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbase4dimageviewer::InitializeDisplay { widget st } {
+    
+    set	oldhelpmenu $enable_helpmenu
+    set ok [ InitializeOrthogonal4DViewer $widget $st ]
+
+    if { $ok == 0 } {
+	return 0
+    }
+
+    set mb [ menu $menubase.cardiacm -tearoff 0 ]
+    $menubase add cascade -label "Cardiac" -menu $mb -underline 0
+
+    Create4DControls $mb 
+    set enable_helpmenu $oldhelpmenu 
+    return $ok
+
+}
+# ---------------------------------------------------------------------------------
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclbasecontrol.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclbasecontrol.tcl
new file mode 100644
index 0000000..623c273
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclbasecontrol.tcl
@@ -0,0 +1,516 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclbasecontrol 1.0
+
+# 	$Id: pxitclbasecontrol.tcl,v 1.1 2002/05/09 14:04:36 papad Exp papad $	
+
+
+
+
+
+package require pxtclutil  1.0
+package require Itcl 3.2
+package require feedbackplus 1.0
+package require vtkpxcontrib 1.2
+package require http
+package require pxtclhelp 
+
+itcl::class pxitclbasecontrol { 
+
+    # --- begin variable def -----
+    
+    protected variable basewidget   0
+    protected variable notebook 0
+    protected variable itclobjectlist ""
+    protected variable vtkobjectlist ""
+    public    variable debugprogress 0
+    public    variable fullyinitialized 0
+    protected variable aboutdialog 0
+    protected variable helpdialog 0
+    protected variable parent 0
+    protected variable isdialog 1
+
+    private common progressbar 
+    private common progress_lab 
+    private common progress_val 
+
+
+    public    variable appname "BaseControl"
+    public    variable version $::pxtclvtkpxcontrib::version
+    public    variable aboutstring "(c) X. Papademetris, M. Jackowski, A. Joshi, D. Scheinost, H.Okuda, R.T. Constable, L.H. Staib 1995-2011\nSection of Bioimaging Sciences, Department of Diagnostic Radiology, Yale University School of Medicine\n\n\nThis application is intended for research applications only! Use at your OWN RISK. If used for publication please acknowledge, see the webpage for more details. For additional support please visit the BioImage Suite forum at:\n\thttp://resear [...]
+
+    # --- end of variable def -----
+
+    constructor { par } {
+
+	set dopar 0 
+	catch { 
+	    if { [ $par isa pxitclbasecontrol ] == 1 } {
+		set parent $par
+	    } 
+	}
+	set itclobjectlist ""
+	set vtkobjectlist ""
+
+	set progressbar($this) 0
+	set progress_lab($this) "Status"
+	set progress_val($this) 0
+    }
+
+    destructor  {
+	for { set i 0 } { $i < [ llength $itclobjectlist ] } { incr i } {
+	    catch { delete object [ lindex $itclobjectlist $i ] }
+	}
+
+	for { set i 0 } { $i < [ llength $vtkobjectlist ] } { incr i } {
+	    catch { [ lindex $vtkobjectlist $i ] Delete }
+	}
+    }
+
+    # --- begin method def -----
+
+    # GUI Stuff
+    public method AddToMenuButton { mb args}
+    public method ShowWindow { args }
+    public method DelayedInitialize { }
+    public method HideWindow { }
+    public method SetTitle { title }
+    public method WatchOn { } 
+    public method WatchOff { } 
+    public method SetCurrentDirectory { fname } { }
+
+    # About Command 
+    public method HelpCommand { }
+    public method AboutCommand { }
+    public method PrintDatabase { }
+    public method CheckForUpdates { }
+    public method ExitCommand { }
+
+    # Enable/Disable pieces of the User Interface
+    public proc   DisableWidget { widget  }
+    public proc   DisableUI     { widgetlist }
+    public proc   EnableWidget { widget }
+    public proc   EnableUI     { widgetlist  }
+    public proc   SetStateOfWidget { widget mode }
+    public proc   SetStateOfUI     { widgetlist mode  }
+
+    # Configure Whole Trees
+    public proc   ConfigureWidgetTree { widget optionlist }
+    public proc   SetWidgetTreeColors { widget backc forec }
+
+    # For Global Scoping
+    public method GetThisPointer { } { return $this }
+    public method GetBaseWidget  { } { return $basewidget }
+    public method GetParent  { } { return $parent }
+
+    # Add Logo Label
+    public proc   AddLogoLabel { w }
+    
+    # create progress bar 
+    protected method CreateProgressBar { w } 
+    public method ProgressCallback   { filter lab } 
+    public method ShowProgress       { filter lab } 
+    public method ShowProgressVal    { name   val }
+    public method SetFilterCallbacks { filter comment } 
+    # --- end method def -----
+}
+# ------------------- End of Header ---------------------------------
+# -------------------------------------------------------------------------------------------
+#  
+#    GUI Stuff 
+#
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclbasecontrol::AddToMenuButton { mb args} {
+
+    if { $isdialog == 0 } { return 0 }
+    set name "Show Control" 
+
+    if { [ llength $args ] > 0 } {
+	set name [ lindex $args 0 ]
+    }
+
+    eval "$mb add command -command { $this ShowWindow } -label \"$name\""
+} 
+
+
+::itcl::body pxitclbasecontrol::DelayedInitialize { } {
+
+    set fullyinitialized 1
+}
+
+::itcl::body pxitclbasecontrol::ShowWindow { args } {
+
+    if { $isdialog == 0 } { return 0 }
+
+    if { $basewidget == 0 } { 
+	return 
+    }
+
+    if { $fullyinitialized == 0 } {
+	$this DelayedInitialize
+    }
+
+
+    if { $notebook !=0 && [ llength $args ] > 0 } {
+	$notebook view [ lindex $args 0 ]
+    }
+
+    catch  {
+	if { [ winfo ismapped $basewidget ] == 1 } {
+	    wm withdraw $basewidget
+	}
+	wm deiconify $basewidget
+    }
+    return $basewidget
+}
+# ----------------------------------------------------------
+::itcl::body pxitclbasecontrol::HideWindow { } {
+    if { $isdialog == 0 } { return 0 }
+    catch { wm withdraw $basewidget }
+}
+# ----------------------------------------------------------
+::itcl::body pxitclbasecontrol::SetTitle { title } {
+    if { $isdialog == 0 } { return 0 }
+    catch {  wm title $basewidget $title }
+}
+# ----------------------------------------------------------
+::itcl::body pxitclbasecontrol::SetStateOfWidget { widget state } {
+    
+    set children [ winfo children $widget ]
+    set a [ llength $children ]
+    if { $a == 0 } {
+	catch { $widget configure -state $state  }
+	return 0
+    } else {
+	for { set i 0 } { $i < $a } { incr i } {
+	    SetStateOfWidget [ lindex $children $i ] $state
+	}
+    }
+}
+# ----------------------------------------------------------
+
+::itcl::body pxitclbasecontrol::ConfigureWidgetTree { widget optionlist } {
+
+    catch { eval "$widget configure $optionlist" }
+
+    set children [ winfo children $widget ]
+    set a [ llength $children ]
+    if { $a == 0 } {
+	catch { eval " $widget configure $optionlist" }
+	return 0
+    } else {
+	for { set i 0 } { $i < $a } { incr i } {
+	    ConfigureWidgetTree [ lindex $children $i ] $optionlist
+	}
+    }
+
+}
+# ----------------------------------------------------------
+itcl::body pxitclbasecontrol::SetWidgetTreeColors { widget backc forec } {
+
+    ::pxitclbasecontrol::ConfigureWidgetTree $widget "-background $backc"
+    ::pxitclbasecontrol::ConfigureWidgetTree $widget "-foreground $forec"
+    ::pxitclbasecontrol::ConfigureWidgetTree $widget "-highlightbackground $backc"
+    ::pxitclbasecontrol::ConfigureWidgetTree $widget "-highlightcolor $forec"
+}
+# ----------------------------------------------------------
+::itcl::body pxitclbasecontrol::SetStateOfUI { disablelist state } {
+	
+    set a [ llength $disablelist ]
+    for { set i 0 } { $i < $a } { incr i } {
+	SetStateOfWidget [ lindex $disablelist $i ] $state
+    }
+}
+# ----------------------------------------------------------	
+::itcl::body pxitclbasecontrol::DisableWidget { widget  }    { SetStateOfWidget $widget disabled }
+::itcl::body pxitclbasecontrol::DisableUI     { widgetlist } { SetStateOfUI $widgetlist disabled }
+::itcl::body pxitclbasecontrol::EnableWidget  { widget }     { SetStateOfWidget $widget normal   }
+::itcl::body pxitclbasecontrol::EnableUI      { widgetlist } { SetStateOfUI $widgetlist normal   }
+
+# ----------------------------------------------------------
+::itcl::body pxitclbasecontrol::WatchOn { } {
+    $basewidget config -cursor watch; 
+    
+    if { $parent != 0 } {
+	$parent WatchOn
+    }
+}
+# ----------------------------------------------------------
+::itcl::body pxitclbasecontrol::WatchOff { } {
+
+    $basewidget config -cursor ""
+    ShowProgressVal "Done" 0.0
+    if { $parent !=0 } {
+	$parent WatchOff
+	$parent ShowProgressVal "Done" 0.0
+    }
+}
+# -------------------------------------------------------------------------------------------
+#  
+#    Progress Bar Stuff 
+#
+# -------------------------------------------------------------------------------------------
+::itcl::body pxitclbasecontrol::AddLogoLabel { w } {
+
+    global tcl_platform
+
+    set l [ label $w.[ pxvtable::vnewobj ] -image  $::pxtclvtkpxcontrib::smalllogo ]
+
+    return $l
+}
+
+::itcl::body pxitclbasecontrol::CreateProgressBar { w } {
+    
+    set l [ AddLogoLabel $w  ]
+    pack $l -side left -expand f -padx 1
+
+    set progressbar($this) $w.pbar
+    iwidgets::feedbackplus $w.pbar -steps 100  -barheight 10  -labelpos w -labeltext $progress_lab($this) 
+    pack $w.pbar -side right -expand t -fill x
+
+    #   $w configure -bg "\#8197c5" 
+    #    [ $w.pbar component trough ] configure  -bg  "\#cccdf8"
+    #    [ $w.pbar component percentage ] configure  -fg  black 
+    
+
+
+}
+# ----------------------------------------------------------
+::itcl::body pxitclbasecontrol::ProgressCallback { filter label } {
+
+#    puts stderr "Progress Callback ($this) = [ $filter GetClassName ] $label"
+
+    if { $progressbar($this) != 0 } {
+	ShowProgress $filter $label
+    }
+
+    if { $parent !=0 } {
+	$parent ProgressCallback $filter $label
+    }
+}
+# ----------------------------------------------------------
+::itcl::body pxitclbasecontrol::ShowProgress { filter lab } {
+	
+    if { $progressbar($this) == 0 } {
+	return
+    }
+    
+    set progress_val($this) 50
+    catch { set progress_val($this)  [expr [$filter GetProgress]*100] }
+    set progress_lab($this) $lab
+    
+
+ #   puts stderr "Progress ($this) = $progress_val($this), $progress_lab($this)"
+
+    if {$lab == "Done" } { 
+	set progress_val($this) 0
+    }
+    
+    if { $debugprogress == 1 } {
+	#	puts stdout "$lab $progress_val($this)"
+    }
+
+    $progressbar($this) configure  -labeltext $progress_lab($this)
+    $progressbar($this) setval [ expr round($progress_val($this)) ]
+
+    update idletasks
+}
+# ----------------------------------------------------------
+::itcl::body pxitclbasecontrol::ShowProgressVal { name val } {
+	
+    if { $progressbar($this) == 0 } {
+	return
+    }
+	
+    set progress_val($this) [expr $val*100.0]
+    set progress_lab($this) "$name"
+	
+    if {$name == "Done" } { 
+	set progress_val($this) 0
+    }
+#    if { $debugprogress == 1 } {
+#	puts stdout "$name $val"
+#    }
+
+    $progressbar($this) configure  -labeltext $progress_lab($this)
+    $progressbar($this) setval [ expr round($progress_val($this)) ]
+
+    update idletasks
+}
+# ----------------------------------------------------------
+itcl::body pxitclbasecontrol::SetFilterCallbacks { filter comment } {
+    
+    set t [ itcl::scope $this ]
+
+    eval "$filter AddObserver ProgressEvent { $t ProgressCallback $filter \"$comment\"}"
+    eval "$filter AddObserver EndEvent      { $t ProgressCallback $filter Done}"
+}
+# ----------------------------------------------------------
+
+itcl::body pxitclbasecontrol::CheckForUpdates { } {
+    
+    ::pxtclvtkpxcontrib::CheckForUpdates
+}
+
+# ----------------------------------------------------------
+itcl::body pxitclbasecontrol::PrintDatabase { } {
+
+    global env
+    set fn ".bioimagesuite3"
+    catch { set fn $env(BIODBASE) }
+    set fn [ file join $env(HOME) $fn ]
+    
+    set connector [ vtkbisDatabase New ]
+    $connector InitializeSQLite "$fn" 
+    set ok [ $connector Connect ]
+    pxtkconsole
+    pxtkprint "Reading database from $fn status = $ok\n"
+
+    if { $ok > 0 } {
+	set dbase [ vtkbisFilenameTable New ]
+	$dbase SetConnector $connector
+	set line [ $dbase PrintTable ]
+	set dbline [ split $line "\n" ]
+	set dbline [ lsort  -ascii -index 0 $dbline ]
+	for { set i 0 } { $i < [ llength $dbline ] } { incr i } {
+	    pxtkprint "[lindex $dbline $i ]\n"
+	}
+	$dbase Delete
+    }
+    $connector Delete
+    return 
+
+}
+# ----------------------------------------------------------
+itcl::body pxitclbasecontrol::AboutCommand { } {
+
+    if { $aboutdialog == 0 } {
+	
+	set w .
+	if { [ string length $basewidget ] > 2 } { set w $basewidget }
+    
+	set aboutdialog  [ toplevel $w.[ pxvtable::vnewobj ]] 
+	
+    
+	::pxtclhelp::HelpDialog $aboutdialog
+	wm title $aboutdialog "About This Application"
+    
+	set extra ""
+
+	set opt [ vtkpxOptimizer [ pxvtable::vnewobj ]]
+	if { [ $opt UsesNumericalRecipes ] == 1 } {
+	    set extra "Uses a small amount of code from Numerical Recipes in C\n"
+	}
+	$opt Delete
+
+	set line "$appname\nVersion: $version\n$aboutstring \n$extra\n\n------------------------------------\n System Information\n------------------------------------\n[ ::pxtclutil::GetAllInfo ]"
+	                                                
+	::pxtclhelp::HelpDialogAddText $aboutdialog $line
+
+	set logoframe [ ::pxtclhelp::GetLogoFrame  $aboutdialog ]
+	set imgname [ file join $::pxtclvtkpxcontrib::imagedir  bioimagesuite_logo.gif ]
+
+	label $logoframe.b -image $::pxtclvtkpxcontrib::logo
+	pack  $logoframe.b -side left -expand t -fill x 
+
+ 	set textbox [  ::pxtclhelp::GetTextBox  $aboutdialog ]
+
+	$textbox configure -font "$::pxtclvtkpxcontrib::fontname"
+	::pxitclbasecontrol::SetWidgetTreeColors $aboutdialog "\#8197c5" white
+    } 
+
+    ::pxtclutil::ShowWindow $aboutdialog
+
+    #    option clear
+    #    global pxtcl_pref_array
+    #    set pxtcl_pref_array(ColorScheme)  "Suite Blue"
+    #    ::pxtcluserprefs::InitializeBioImageSuiteColorScheme
+
+}
+
+itcl::body pxitclbasecontrol::ExitCommand { } {
+    set ok [ tk_messageBox -title "Exiting this Application" -type yesno  -message "Are you sure you want to close $appname. Any unsaved work will be lost."  ]
+    if { $ok == "yes" } {
+	pxtkexit
+    }
+    return 0
+}
+
+
+# ------------------------------------------------------------------------------------
+
+itcl::body pxitclbasecontrol::HelpCommand { } {
+
+    if { $helpdialog != 0 } {
+	::pxtclutil::ShowWindow $helpdialog
+	return
+    }
+
+    set bname [ file normalize [ file join $::pxtclvtkpxcontrib::baselibrarypath  .. ] ]
+
+    set b(1) [ file join $bname html ]
+    set b(2) [ file join [ file join $bname .. ] build/html ]
+    set b(3) [ file join [ file join $bname .. ] build64/html ]
+
+    set i 1
+    set rootname 0
+    while { $i < 3 } {
+	set f [ file normalize [ file join $b($i) index.html ] ]
+#	puts stdout "Looking for $f"
+	if { [ file exists $f ] > 0 } {
+	    set i 4
+	    set rootname $f
+	}
+	incr i
+    }
+    
+    set w .
+    if { [ string length $basewidget ] > 2 } { set w $basewidget }
+    
+    set helpdialog  [ toplevel $w.[ pxvtable::vnewobj ]] 
+    wm geometry $helpdialog 800x600
+    
+    wm title $helpdialog "BioImage Suite Tools Manual Pages"
+    
+    set scr [ iwidgets::scrolledhtml $helpdialog.t  -labeltext "" \
+		  -width 6i -height 3i \
+		  -wrap word -padx 2 ]
+    $scr configure -fontsize large
+    
+    pack $scr -side top -expand true -fill both
+
+       
+    if { $rootname != 0 } {
+	$scr import $rootname
+    } else {
+	$scr insert end "No Man Pages Found"
+    }
+    
+    ::pxtclutil::ShowWindow $helpdialog
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclbaseimagecontrol.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclbaseimagecontrol.tcl
new file mode 100644
index 0000000..33338a3
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclbaseimagecontrol.tcl
@@ -0,0 +1,265 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclbaseimagecontrol 1.0
+
+# 	$Id: pxitclbaseimagecontrol.tcl,v 1.1 2002/05/09 14:04:36 papad Exp papad $	
+
+
+
+
+
+package require pxtclutil  1.0
+package require pxvtable 1.0
+package require Itcl 3.2
+package require pxitclimage 1.0
+package require pxitclbasecontrol 1.0
+
+
+itcl::class pxitclbaseimagecontrol { 
+
+    inherit pxitclbasecontrol
+
+    # --- begin variable def -----
+    protected common forceimageoutputformat 0
+    protected variable currentresults 0
+    public    variable currentimage 0 
+    protected variable undoimage 0 
+    protected variable imagelist ""
+    public    variable currentpoint [ list 0 0 0 ]
+    protected variable initialized 0
+
+    # --- end of variable def -----
+
+    constructor { par } {
+	::pxitclbasecontrol::constructor $par
+    } {
+	set currentresults  [  [ pxitclimage \#auto ] GetThisPointer ]
+	set currentimage    [  [ pxitclimage \#auto ] GetThisPointer ]
+	set undoimage       [  [ pxitclimage \#auto ] GetThisPointer ]
+      
+	lappend itclobjectlist $currentresults
+	lappend itclobjectlist $currentimage 
+
+	set imagelist [ list $currentresults $currentimage $undoimage ]
+
+	$this SetDefaultOutputImageFormat
+    }
+	
+    # --- begin method def -----
+    protected method AddImagesToLists { args }
+    public    method UnloadImages { args } 
+    public    method Debug { } 
+
+    # --- Set Image/Results Methods 
+    # -----------------------------
+    public method SetImage   { img }
+    public method SetResults { img }
+    public method SetValueImage { vtkimg  }
+    public method SetImageFromObject   { img obj }
+    public method SetResultsFromObject { img obj }
+
+    # --------------------
+    # parent communication
+    # ---------------------
+    public proc   AddPrefix { oldname prefix }
+    public method SendResultsToParent { args }
+    public method SendImageToParent { args } 
+
+    # Change Image
+    # ------------
+    public method CopyResultsToImage { }
+    public method RevertToPreviousImage { }  
+
+    public method SetImageOutputFormat { mode } 
+    protected method SetDefaultOutputImageFormat { }
+    # --- end method def -----
+}
+# ------------------- End of Header ---------------------------------
+::itcl::body pxitclbaseimagecontrol::AddImagesToLists { args } {
+
+    for { set i 0 } { $i < [ llength $args ] } { incr i } {
+	set obj [ lindex $args $i ] 
+	append imagelist $obj
+	append itclobjectlist $obj
+    }
+}
+# -----------------------------------------------------------------
+::itcl::body pxitclbaseimagecontrol::UnloadImages { args } {
+
+    set dounload 0
+
+    if { $basewidget == 0 } {
+	set dounload 1 
+    } elseif { [ llength $args ] > 0 } {
+	if { [ lindex $args 0 ] == "force" } {
+	    set dounload 1
+	}
+    }
+    
+    if { $dounload == 0 } {
+	set ok [ tk_messageBox -type yesno -default no -parent $basewidget -title "Think again ..." -message "Unload all images (for this control) from memory?" -icon question  ]
+	if { $ok == "yes" } {
+	    set dounload 1
+	}
+    }
+    
+    if { $dounload == 0 } { return   }
+    
+    for { set i 0 } { $i < [ llength $imagelist ] } { incr i } {
+	[ lindex $imagelist $i ] UnLoad
+    }
+}
+# ----------------------------------------------------------
+::itcl::body pxitclbaseimagecontrol::Debug { } {
+    for { set i 0 } { $i < [ llength $imagelist ] } { incr i } {
+	puts stdout "[ [ lindex $imagelist $i ] GetDescription ]\n"
+    }
+    puts stdout "\n"
+}
+
+# -------------------------------------------------------------------------------------------
+#  
+#    Programming Interface for master objects
+#
+# -------------------------------------------------------------------------------------------
+
+::itcl::body pxitclbaseimagecontrol::SetImage { img  } {
+
+    if { [ $img GetImageSize  ] < 2 } {	return 0    }
+    $undoimage ShallowCopy $currentimage
+    $currentimage ShallowCopy $img
+    return 1
+}
+
+::itcl::body pxitclbaseimagecontrol::SetResults { img  } {
+    if { [ $img GetImageSize  ] < 2 } {	return 0    }
+    $currentresults ShallowCopy $img
+    return 1
+}
+
+itcl::body pxitclbaseimagecontrol::SetValueImage { vtkimg  } {
+    if { $parent == 0 } { 
+	return  0
+    } 
+    return [ $parent SetValueImage $vtkimg ]
+}
+
+::itcl::body pxitclbaseimagecontrol::SetImageFromObject { img obj  } {
+    if { [ $img GetImageSize  ] < 2 } {	return 0    }
+    $undoimage ShallowCopy $currentimage
+    SetImage $img
+    return 1
+}
+
+::itcl::body pxitclbaseimagecontrol::SetResultsFromObject { img obj  } {
+    if { [ $img GetImageSize  ] < 2 } {	return 0    }
+    SetResults $img
+    return 1
+}
+   
+
+
+
+# -------------------------------------------------------------------------------------------
+#  
+#    Send Results/Info/Requests To Parent
+#
+# -------------------------------------------------------------------------------------------
+
+::itcl::body pxitclbaseimagecontrol::AddPrefix { oldname prefix } {
+
+    set dname [ file dirname $oldname ]
+    set tname [ file tail $oldname ]
+    
+    set newname [ file join $dname $prefix ]
+    set newname "${newname}_${tname}"
+    return $newname 
+}
+
+::itcl::body pxitclbaseimagecontrol::SendResultsToParent { } {
+
+    if { $parent == 0 } { return  } 
+    if { [ $currentresults GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No results image in Memory! Cannot send to parent!"
+	return 0
+    }
+
+    puts stderr "Here $parent=$parent"
+    return [ $parent SetResultsFromObject $currentresults $this ]
+    
+}
+# -------------------------------------------------------------------------------------------    
+::itcl::body pxitclbaseimagecontrol::SendImageToParent { } {
+
+    if { $parent == 0 } { return  } 
+    if { [ $currentresults GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No results image in Memory! Cannot send to parent!"
+	return 0
+    }
+
+    return [ $parent SetImageFromObject $currentresults $this ]
+    
+}
+# -------------------------------------------------------------------------------------------    
+ 
+::itcl::body pxitclbaseimagecontrol::RevertToPreviousImage { }  {
+
+    if {  [ $undoimage GetImageSize ] < 2 } {
+	return 0
+    }
+    set tmp  [  [ pxitclimage \#auto ] GetThisPointer ]
+    $tmp ShallowCopy $undoimage
+    set ok [ SetImageFromObject $tmp $this ]
+    itcl::delete object $tmp 
+    return $ok
+}
+# -------------------------------------------------------------------------------------------    
+itcl::body pxitclbaseimagecontrol::CopyResultsToImage { } {
+    
+    return [ SetImageFromObject $currentresults $this  ]
+}
+
+
+# -------------------------------------------------------------------------------------------    
+itcl::body pxitclbaseimagecontrol::SetImageOutputFormat { mode } {
+    set forceimageoutputformat [ ::pxitclimage::SetOutputFormat $mode ]
+}
+
+itcl::body pxitclbaseimagecontrol::SetDefaultOutputImageFormat { } {
+
+    global pxtcl_pref_array
+    if {  $pxtcl_pref_array(ForceOutputFormat) == "Analyze" } {
+	set forceimageoutputformat 1
+    } elseif { $pxtcl_pref_array(ForceOutputFormat) == "NIFTI" } {
+	set forceimageoutputformat 2
+    } else {
+	set forceimageoutputformat 0
+    }
+    set forceimageoutputformat [ ::pxitclimage::SetOutputFormat $forceimageoutputformat ]
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclbaseimageviewer.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclbaseimageviewer.tcl
new file mode 100644
index 0000000..396bd21
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclbaseimageviewer.tcl
@@ -0,0 +1,2059 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclbaseimageviewer.tcl,v 1.3 2005/06/22 13:01:09 xenios Exp $	
+
+package provide pxitclbaseimageviewer 1.0
+
+
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] bis_algorithm ]
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+package require vtkpxcontrib  1.1
+package require pxtcluserprefs 1.0
+package require pxitclbaseimagecontrol   1.0
+package require pxitclimagenormalization 1.0
+package require pxitclimageimport        1.0
+package require bis_guiimageutility      1.0
+package require bis_guioverlayutility 1.0
+
+
+
+package require pxitclbrainstrip         1.0
+package require pxitclLandmarkControl    1.0
+package require pxitclPolyDataControl    1.0
+package require pxitclsurfaceobjectmap   1.0
+package require pxitclmultisubjectaverage 1.0
+
+package require pxitclcsigadget 1.0
+package require pxitclatlasgadget 1.0
+
+package require pxitclanimationgadget 1.0
+package require pxitclvvlinkgadget 1.0
+
+
+
+
+package require pxitclopenigtlinkgadget 1.0
+package require pxitclexpfit 1.0
+package require pxitclfilelistmenu 1.0
+package require bis_fmri 1.0
+package require bis_databasetool 1.0
+
+
+# -----------------------------------------------------
+#  Intialize Variables
+# -----------------------------------------------------
+
+itcl::class pxitclbaseimageviewer {
+
+    #initialize vtable
+    inherit pxitclbaseimagecontrol 
+
+    protected common   thisparam
+    protected variable vtk_viewer  0
+    protected variable standalone  0
+
+    public    variable mousecallback 0
+    public    variable setnewimagecallback 0
+    public    variable viewerbase 0
+    public    variable menubase   0
+    public    variable objectmapmenu   0
+    public    variable bind_mouse_events 0
+    public    variable enable_rendering_on_startup 1
+    protected variable pref_dialog 0
+    protected variable normalize_anatomical   0
+    protected variable import_filetype 0
+    protected variable in_expose 0
+    protected variable can_accept_mask 1
+
+    public    variable viewermode "neuro"
+    public    variable objectmapname "objectmap.nii.gz"
+
+    public variable show_standard_images 0
+
+    
+    protected variable controllist        ""
+    protected variable showcontrollist    ""
+
+
+    public    variable enable_displaymenu   1
+    public    variable enable_helpmenu      1
+
+    protected variable histcontrol            0
+    public    variable enable_histcontrol     1
+
+    public    variable overlaytool            0
+    public    variable enable_overlaytool     1
+
+    public    variable brainstriptool         0
+    public    variable enable_brainstriptool  1
+
+    # enabled by enable_talairachoption
+    public    variable enable_talaraichoption 0
+    protected variable atlastool              0
+
+
+    public    variable expfittool         0
+    public    variable enable_expfittool  0
+
+
+    protected variable headercontrol          0
+    public    variable enable_headercontrol   1
+
+    protected variable importcontrol          0
+    public    variable enable_importcontrol   1
+
+    protected variable imageutility           0
+    protected variable imageutility2          0
+    public    variable enable_imageutility    1
+
+    protected variable landmarkcontrol    0
+    public    variable enable_landmarkcontrol 1
+    public    variable enable_landmarkclicks  0
+
+    protected variable polydatacontrol     0
+    protected variable surfacecontrol     0
+    public    variable enable_polydatacontrol 1
+
+    protected variable surfaceobjectmap    0
+    public    variable enable_surfaceobjectmap    1
+
+    protected variable multisubjectcontrol 0
+    public    variable enable_multisubjectcontrol 0
+
+
+    protected variable fmrigadget 0
+    public    variable enable_fmrigadget 0
+
+    protected variable vvlinkgadget 0
+    public    variable enable_vvlinkgadget  0
+
+    protected variable openigtlinkgadget 0
+    public    variable enable_openigtlinkgadget  1
+
+    protected variable databasegadget 0
+    public    variable enable_databasegadget  1
+
+
+    protected variable csigadget 0
+    public    variable enable_csigadget 0
+
+    public    variable enable_internaleditor 0
+    public    variable enable_objectmapmenu 0
+
+    protected variable animationgadget 0
+    public    variable enable_animationgadget 1
+
+
+    public   variable  featuremenu 0
+
+    # -------------------------------------------------
+    
+    constructor { par } {
+	::pxitclbaseimagecontrol::constructor $par
+    } {
+	InitializeBaseImageControl
+    }
+
+    # Initialize Variables etc 
+    private method InitializeBaseImageControl {  }
+
+    # Access Key Data Structures
+    public method GetLandmarkControl { } { return $landmarkcontrol }
+    public method GetPolyDataControl { } { return $polydatacontrol }
+    public method GetViewer { }
+
+    # Set/Display Image
+    public method SetResultsFromObject { img obj }
+    public method SetValueImage        { vtkimg  }
+    public method SetImageFromObject   { img obj } 
+    public method SetMaskFromObject   { img obj } 
+    public method CanAcceptMask { }
+
+    public method UpdateControlsWithNewImage   { obj } 
+    public method SetLookupTable       { colormap }
+    public method SetLookupTableMode   { index }
+    public method GetDisplayedImage { }
+    public method ShowImage { flag args }
+    public method SetSnapshotResolution { factor }
+    public method SetViewerBackground { }
+
+    # Load/Save Images 
+    public method GetImageTypeList { mode } 
+    public method LoadImage { f }
+    public method QueryImage { }
+    public method ImportImage { args }
+    public method SaveImage { }
+    public method ExportImage { }
+    public method SwitchDirectory { { newdir ""  } }
+    public method CopyMaskToResults { }
+    public method GetImageName { } { return [ $currentimage cget -filename ] }
+
+    # Objectmap Stuff
+    public method ObjectmapInfo { }
+    public method QuestionReplaceObjectmap { objectmap { message "" } { forceask 0 } }
+    public method LoadObjectmap  {  f }
+    public method GetObjectmapName  { } 
+    public method LoadBrodmann  {  }
+    public method GrabObjectmap { }
+    public method SaveObjectmap  { fname comment }
+    public method ClearObjectmap { }
+    public method ShowPaintControls { }
+    public method AutosaveEvent  { }
+    public method AutosaveInvoke  { }
+    public method ObjectmapHistogram { inp }
+
+
+
+    # Talairach Stuff
+    public method ResliceImageToTalairach {  mode }
+    public method SetOldStyleMNITalairachTransform { mode }
+    public method SetAtlasTool { atl } { set atlastool $atl }
+    public method GetAtlasTool {  } { return $atlastool }
+
+    # Header Stuff
+    public method PrintHeader { imgno detail }
+
+    # Create GUI Stuff
+    public method CreateMenu { menubase }
+    public method CreateControls { inpwidget }
+    public method CreateHelpMenu { }
+
+    # Callback Handlers
+    public method HandleUpdateEvent { args }
+    public method HandleMouseEvent { mouse stat x1 x2 widgetname args }
+    public method HandleCoordinatesChangeEvent { { mouse -1 } { stat -1 } }
+    public method SetShiftMouseToEditor { } 
+    public method EnableVolumeTrace { }
+    public method EnableSurfaceTrace { }
+    public method HeaderControlCallback { }
+    public method CurrentLandmarkToTalairach { } 
+
+    # Add To Control List
+    public method AddControl { control }
+    public method AddShowControl { control }
+
+    # Main Display Initialization Routines 
+    protected method InitializeInterface { widget standalone  }
+    protected method InitializeViewer    {  } 
+
+    # Access Methods to create different kinds of viewers
+    public method InitializeOrthogonalViewer { widget standalone }
+    public method InitializeObjectmapViewer { widget standalone }
+    public method InitializeMosaicViewer { widget standalone }
+    public method InitializeObjectmapMosaicViewer { widget standalone }
+    public method InitializeMultipleMosaicViewer { widget standalone }
+    public method InitializeOrthogonal4DViewer { widget standalone } 
+
+    # Generic Initialize Display Method --> InitializeOrthogonalViewer
+    public method InitializeDisplay { widget standalone }
+
+
+}
+
+# -----------------------------------------------------------
+# Main Body Definitions
+# -----------------------------------------------------------
+itcl::body pxitclbaseimageviewer::InitializeBaseImageControl { } {
+
+    global pxtcl_pref_array
+    
+    if { $pxtcl_pref_array(NormalizeAnatomical) > 0 } {
+	set normalize_anatomical 1
+    }
+    
+    set thisparam($this,display) "Image";	
+    set thisparam($this,snapshotresolution) 0	
+    set thisparam($this,mousetolandmarks) 1;
+
+    set thisparam($this,volumetrace) 1
+    set thisparam($this,geometrytrace) 0
+    set thisparam($this,toolbarhelp) ""
+
+
+#     if { $enable_databasegadget == 1 } {
+	
+# 	set db 0
+# 	catch { 
+# 	    set db [ vtkbisMySQLDatabase New ]
+# 	    $db Delete
+# 	}
+# 	if { $db == 0 } {
+# 	    set enable_databasegadget 0
+# 	}
+#     }
+
+
+}
+
+# -----------------------------------------------------------
+# Control Objects Return
+# -----------------------------------------------------------
+itcl::body pxitclbaseimageviewer::CopyMaskToResults { } {
+
+    set img 0
+    catch {
+	set image [ $vtk_viewer GetObjectMapImage ]
+	set img   [ [ pxitclimage \#autor ] GetThisPointer ]
+	$img ShallowCopyImage $image
+	$img CopyImageHeader [ $currentimage GetImageHeader ]
+	$this SetResultsFromObject $img $this
+	itcl::delete object $img
+    }
+}
+
+itcl::body pxitclbaseimageviewer::GetViewer { } {
+    return $vtk_viewer
+}
+
+itcl::body pxitclbaseimageviewer::SetLookupTable { colormap } {
+    if { $vtk_viewer != 0 } {
+	$vtk_viewer SetLookupTable $colormap
+    }
+}
+
+itcl::body pxitclbaseimageviewer::SetLookupTableMode { index } {
+    if { $vtk_viewer != 0 } {
+	$vtk_viewer SetPresetLookupTable $index
+    }
+}
+# ---------------------------------------------------------------------------------
+#   Utility Functions for Setting New Image and Undo Features
+# ---------------------------------------------------------------------------------
+
+
+
+itcl::body pxitclbaseimageviewer::SetImageFromObject { img obj } {
+    
+    set a [ pxitclbaseimagecontrol::SetImageFromObject $img $obj ]
+    SetTitle "No Image"
+    if { $a == 0 } { return 0 } 
+    
+    $this UpdateControlsWithNewImage $obj
+
+}
+itcl::body pxitclbaseimageviewer::UpdateControlsWithNewImage   { obj }  {
+
+    for { set i 0 } { $i < [ llength $controllist ] } { incr i }  {
+	set cnt [ lindex $controllist $i ]
+	if { $cnt != $obj  } {
+	 #   puts stderr "Updating control $cnt with image = [ $currentimage GetShortDescription ]"
+	    $cnt SetImageFromObject $currentimage $this
+	}
+    }
+
+    if { $headercontrol != 0 && $obj != $headercontrol } {
+	$headercontrol SetHeader [ $currentimage GetImageHeader ]
+    }
+
+    if { $setnewimagecallback != 0 } {
+	eval "$setnewimagecallback $this"
+    }
+    
+    $vtk_viewer SetEnableRendering 0
+    ShowImage  "Image" 1
+    SetTitle "$appname [ $currentimage GetShortDescription ]"
+    $vtk_viewer SetEnableRendering 1
+    return 1
+}
+
+itcl::body pxitclbaseimageviewer::SetResultsFromObject { img obj  } {
+    if { [ $img GetImageSize ] < 2 } {	return 0    }
+    $vtk_viewer SetEnableRendering 0
+    SetResults $img
+    $vtk_viewer SetEnableRendering 1
+    ShowImage "Results" 1
+
+    return 1
+}
+
+itcl::body pxitclbaseimageviewer::SetValueImage { vtkimg  } {
+    set ok 0
+
+    catch { 
+	if { [ $vtkimg GetNumberOfPoints ] > 1 } {	
+	    set ok 1
+	}
+    }
+    if { $ok == 0 } {
+	return
+    }
+    $vtk_viewer SetEnableRendering 0
+    $vtk_viewer SetValueImage $vtkimg
+    $vtk_viewer SetEnableRendering 1
+
+    
+
+    if { $parent != 0 } { 
+	$parent SetValueImage $vtkimg 
+    }
+    return 1
+}
+
+itcl::body pxitclbaseimageviewer::GetDisplayedImage { } {
+
+    if { $thisparam($this,display) == "Image"} { 
+	set img $currentimage
+    } else {
+	set img $currentresults
+    }
+
+    return $img
+}
+
+itcl::body pxitclbaseimageviewer::CanAcceptMask { } {
+
+    if { $vtk_viewer == 0 } {	return  0  }
+    if { [ $vtk_viewer IsA "vtkpxGUIObjectmapOrthogonalViewer"  ] == 0
+	    && [ $vtk_viewer IsA "vtkpxGUIObjectmapMosaicViewer" ] == 0 } {
+	    return 0
+	}
+
+    if { $can_accept_mask == 0 } {
+	return 0
+    }
+
+    return 1
+
+}
+
+itcl::body pxitclbaseimageviewer::SetMaskFromObject { img obj } {
+    
+    if { [ $this CanAcceptMask ] == 0 } {
+	return 0
+    }
+
+    if { [ $img GetImageSize ] < 2 } {	return 0    }
+    set disp [ $this GetDisplayedImage ]
+    if { [ $disp GetImageSize ] < 2 } {	return 0    }
+
+    set nc [ [  $disp GetImage ] GetNumberOfScalarComponents ]
+    set oc [ [  $img  GetImage ] GetNumberOfScalarComponents ]
+
+
+    # Scenario 1
+    if { $oc != $nc } {
+	set tmp [ vtkImageData [ pxvtable::vnewobj ]]
+	$tmp CopyStructure [ $img GetImage ]
+	$tmp SetNumberOfScalarComponents $nc
+	$tmp AllocateScalars
+
+	set t_data [ [ $tmp GetPointData ] GetScalars ] 
+	set i_data [ [ [ $img GetImage ] GetPointData ] GetScalars ]
+
+	set mval $nc
+	if { $oc < $nc } {
+	    set mval $oc 
+	}
+
+	for { set i 0 } { $i < $mval  } { incr i } {
+	    $t_data CopyComponent $i $i_data $i
+	}
+
+	if { $nc > $oc } {
+	    for { set i $oc } { $i < $nc  } { incr i } {
+		$t_data CopyComponent $i $i_data [ expr $oc -1 ]
+	    }
+	}
+    } else {
+	set tmp [ $img GetImage ]
+    }
+	
+    if { [ $img GetImageSize ] == [ $disp GetImageSize ] } {
+	$vtk_viewer SetObjectMapImage $tmp
+    } else {
+	set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+	$resl SetInput $tmp
+	$resl SetInterpolationMode 0
+	$resl SetInformationInput [ $disp GetImage ]
+	$resl Update
+	$vtk_viewer SetObjectMapImage [ $resl GetOutput ]
+	
+	$resl Delete
+    }
+
+    if { $oc!=$nc } {
+	$tmp Delete
+    }
+    
+
+}
+
+
+# ---------------------------------------------------------------------------------
+#   Display Code
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::SetSnapshotResolution { mode } {
+
+    if { $vtk_viewer == 0 } {
+	return 0
+    }
+
+    if { $mode < 1 } { set mode 1 } 
+    if { $mode > 4 } { set mode 4 } 
+
+    $vtk_viewer SetMagnificationFactor $mode
+    puts stderr "Setting Magnification to $mode"
+    return $mode
+}
+
+itcl::body pxitclbaseimageviewer::SetViewerBackground { } {
+    set rw [ $vtk_viewer GetRenderWidgetName ]
+    set renwin [ $rw GetRenderWindow ]
+    $vtk_viewer SetBackgroundColor $renwin
+}
+
+itcl::body pxitclbaseimageviewer::ShowImage { flag args } {
+    
+    set doupdate 1
+    if { [ llength $args ] > 0 } {
+	set doupdate [ expr [ lindex $args 0 ] > 0 ]
+    }
+
+    set thisparam($this,display) $flag
+    set img [ GetDisplayedImage ]
+    if {  [ $img GetImageSize ] < 2 } { 
+	if { $img == $currentresults } {
+	    set thisparam($this,display) "Image"
+	    return 0 
+	} 
+    }
+
+    #    puts stdout " [ $img GetShortDescription ], or=[ [ $img GetImage ] GetOrigin ] sp=[ [ $img GetImage ] GetSpacing ]"
+
+    set cmap [ $img GetLookupTable ]
+
+    if { $vtk_viewer != 0 } {
+
+	if { $cmap !=0 } {
+	    $vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ] $cmap [ $img GetIntensityOffset ] [ $img GetIntensityScale ]
+	} else {
+	    $vtk_viewer SetImage [ $img GetImage ] [ $img GetOrientation ] [ $img GetIntensityOffset ] [ $img GetIntensityScale ]
+	}
+    }
+
+    if { $doupdate > 0 && $cmap == 0  } {
+	
+	set r [ [ [ [ $img GetImage ] GetPointData ] GetScalars ] GetRange ]
+	set d [ expr [ lindex $r 1 ]- [ lindex $r 0 ] ]
+
+	#	puts stderr "Setting Automatic Lookup Table $normalize_anatomical $d "
+
+	if { $normalize_anatomical > 0 && $d > 20 } {
+	 #   puts stderr "Lookup Table Mode 0"
+	    SetLookupTableMode 0
+	} else {
+	  #  puts stderr "Lookup Table Mode 1"
+	    SetLookupTableMode 0
+	}
+    }
+   
+    for { set i 0 } { $i < [ llength $showcontrollist ] } { incr i }  {
+	set cnt [ lindex $showcontrollist $i ]
+	$cnt SetImage $img 
+    }
+    
+
+    return 1
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::PrintHeader { imageno detail } {
+
+    pxtkconsole
+    set img $currentimage
+    set name "Current Image"
+    if { $imageno == 1 } {
+	set img $currentresults
+	set name "Current Results"
+    }
+
+    set a [ [ $img GetImageHeader ] GetHeaderDescription  $detail]
+    pxtkprint "$name Header\n\t $a"
+
+}
+
+# ---------------------------------------------------------------------------------
+#   Talairach Stuff
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::SetOldStyleMNITalairachTransform { mode }  {
+    set tal 0
+    catch { set tal [ $vtk_viewer GetTalairachTransform ] }
+
+    if { $tal == 0 } { return }
+
+    $tal SetMontrealMode $mode
+    catch { $vtk_viewer MoveAxis 1 }
+}
+
+itcl::body pxitclbaseimageviewer::ResliceImageToTalairach { mode } {
+
+    set txform [ $vtk_viewer GetTalairachTransform ]
+    
+    set tmp  [  [ pxitclimage \#auto ] GetThisPointer ]
+    set resl [  vtkbisImageReslice [ pxvtable::vnewobj ]]
+    
+    if { $mode == 0 } {
+	SetFilterCallbacks $resl "Reslicing Image To Talairach Space"
+    } else {
+	SetFilterCallbacks $resl "Reorienting Image To AC-PC Space"
+    }
+    WatchOn
+
+    $tmp ShallowCopyImage [ $txform ResliceImage [ $currentimage GetImage ] $mode $resl ]
+    $tmp CopyImageHeader 0
+
+    if { $mode == 0 } {
+	$tmp configure -filename [ AddPrefix [ $currentimage cget -filename ] "tal" ]
+    } else {
+	$tmp configure -filename [ AddPrefix [ $currentimage cget -filename ] "acpc" ]
+    }
+
+    $this SetResultsFromObject $tmp $this
+    itcl::delete object $tmp 
+    WatchOff
+    $resl Delete
+    return 
+
+}
+# ---------------------------------------------------------------------------------
+#   I/O Functions
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::SwitchDirectory { { dirname "" } } {
+
+    if { [ string length $dirname ] == 0 } {
+	set dirname  [tk_chooseDirectory -title "Select Current Directory" ]
+    }
+
+    if { [ string length $dirname ] < 1 } {
+	return 0
+    }
+
+    cd $dirname
+    set dirname [ pwd ]
+    pxtkprint "Switched directory to $dirname"
+    for { set i 0 } { $i < [ llength $controllist ] } { incr i }  {
+	set cnt [ lindex $controllist $i ]
+	catch { $cnt SetCurrentDirectory $dirname  }
+    }
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::GetImageTypeList { mode } {
+    return [ ::pxitclimage::GetImageTypeList $mode ]
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::QueryImage { } {
+
+    if { $databasegadget ==0 } {
+	set databasegadget [ bis_databasetool \#auto $this ]
+	set w $basewidget.databasecontrol
+	$databasegadget InitializeGUI $w 0
+    }
+    $databasegadget ShowWindow 
+
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::LoadImage { f } {
+
+    set img [ [ pxitclimage \#auto ] GetThisPointer ]
+    set ok [ $img Load $f "Image" $this ]
+    if { $ok == 1 } {
+	SetImageFromObject $img $this
+    }
+    
+    itcl::delete object $img 
+    return $ok
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::ImportImage { args } {
+    
+    if { $importcontrol == 0 } {
+	set importcontrol [ pxitclimageimport \#auto $this ]
+	set w $basewidget.$importcontrol
+	$importcontrol Initialize $w
+	$this AddControl $importcontrol
+    }
+
+    if { ( $import_filetype != 0) && ( [ llength $args ] ==0 ) } {
+	$importcontrol SetFileType $import_filetype	
+	set import_filetype 0
+    }
+
+    if { [ llength $args ] > 0 } {
+	set import_filetype [ $importcontrol GetFileType ]
+	$importcontrol SetFileType [ lindex $args 0 ]
+    }
+
+    $importcontrol ShowWindow 
+
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::SaveImage { } {
+    
+    set img [ GetDisplayedImage ]
+    if { $img == 0 } {
+	return
+    }
+
+    $img SetLookupTable [ $vtk_viewer GetLookupTable ]    
+
+    WatchOn
+    set ok [ $img Save "" $thisparam($this,display) $this $forceimageoutputformat ]
+    if { $thisparam($this,display) == "Image" && $ok > 0 } { 
+	$this UpdateControlsWithNewImage $this
+    }
+    WatchOff
+    return $ok
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::ExportImage { } {
+
+    set img [ GetDisplayedImage ]
+    if { $img == 0 } {
+	return
+    }
+    
+    set a $thisparam($this,display)
+    set f  [tk_getSaveFile -title "Output Filename for $a" -initialfile export  -filetypes { {"JPEG Images" {.jpg}}}]   
+    if  { [string length $f] < 1} { return }
+
+    WatchOn
+    ::pxtclutil::ExportJPEGImage $f [ $img GetImage ]
+    WatchOff
+}
+
+# ---------------------------------------------------------------------------------
+# Objectmap Stuff
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::ObjectmapInfo  {  } {
+
+    set mask [ $vtk_viewer GetObjectMapImage ]
+    [ [ $mask GetPointData ] GetScalars ] Modified 
+    set range [ [ [ $mask GetPointData ] GetScalars ] GetRange ]
+    tk_messageBox -title "Objectmap Info!" -type ok -message "Objectmap Information\n$objectmapname\n Range $range"
+}
+
+itcl::body pxitclbaseimageviewer::QuestionReplaceObjectmap { objectmap { message "" } { forceask 0 } } {
+
+
+    if { $forceask == 0 } {
+	[ [ $objectmap GetPointData ] GetScalars ] Modified
+	set range [ [ [ $objectmap GetPointData ] GetScalars ] GetRange ]
+	set r1 [ lindex $range 1 ]
+	set r0 [ lindex $range 0 ]
+	
+	
+	if { [ expr abs($r1-$r0) ] < 0.001  } {
+	    return 1
+	}
+    }
+
+    if { $message == "" } {
+	set message "This operation will erase the current objectmap. Are you sure?"
+    }
+    set ok [ pxtclutil::Question $message ]
+    if { $ok == 0 } {
+	return 0
+    }
+
+    return 1
+}
+
+
+itcl::body pxitclbaseimageviewer::GrabObjectmap  { } {
+
+    set mask [ $vtk_viewer GetObjectMapImage ]
+    set img [ $this GetDisplayedImage ]
+    set range [ [ [ [ $img GetImage ] GetPointData ] GetScalars ] GetRange  ]
+    if { [ lindex $range 1 ] > 20  } {
+	set warningtext "RANGE IS RATHER HIGH = $range"
+	set forceask 1
+    } else {
+	set warningtext "Range = $range"
+	set forceask 0
+    }
+
+    set ok [ $this QuestionReplaceObjectmap $mask "Grab Objectmap from current displayed image ($warningtext). This will erase the current objectmap. Are you sure?" $forceask ]
+    
+    if { $ok == 1 } {
+
+	$vtk_viewer SetObjectMapImage [ $img GetImage ] 
+
+	pxtclutil::Warning "Setting autosave to off, please enable if this is desired"
+	set thisparam($this,autosave) 0
+	$this ShowImage Image
+    } 
+}
+
+itcl::body pxitclbaseimageviewer::LoadBrodmann  { } {
+
+    global auto_path
+    
+    set m5 [ lsearch -inline -glob $auto_path "*/../base*" ]
+    set m5 [ file normalize [ file join [ file dirname $m5 ] images ] ]
+
+    set f [ file join $m5   yale_broadmann.nii.gz ]
+    #puts stderr "f=$f"
+    $this LoadObjectmap $f
+}
+
+itcl::body pxitclbaseimageviewer::LoadObjectmap  { f } {
+
+    set mask [ $vtk_viewer GetObjectMapImage ]
+    if { $mask != "" } {
+	set ok [ $this QuestionReplaceObjectmap $mask "This will clear your current objectmap. Are you sure?" ]
+	if { $ok == 0 } {
+	    return
+	}
+    }
+
+    if  { [string length $f] < 1 } { 
+	
+	set typelist { 
+	    {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}
+	    {"VTK Files" {.vt*}}
+	}
+
+	set f  [tk_getOpenFile -title "Load Objectmap" -filetypes $typelist ]
+	if { [ string length $f ] < 1 } {
+	    return 0
+	}
+    }
+
+    set ext [ file extension $f ]
+    set img [ [ pxitclimage \#auto ] GetThisPointer ]
+    
+
+    if { $ext == ".vt" || $ext == ".vtk" } {
+	set ana [ vtkStructuredPointsReader [ pxvtable::vnewobj ]]
+	$ana SetFileName $f
+	SetFilterCallbacks $ana "Reading Image"
+	WatchOn
+	$ana Update
+	$img ShallowCopyImage [ $ana GetOutput ]
+	$img configure -filename $f
+	$img CopyImageHeader 0
+	$ana Delete
+    } else {
+	set ana [vtkpxAnalyzeImageSource [ pxvtable::vnewobj ] ]
+	SetFilterCallbacks $ana "Reading Image"
+	WatchOn
+	$ana Load $f
+	set img [ [ pxitclimage \#auto ] GetThisPointer ]
+	$img SetFromAnalyzeSource $ana
+	$ana Delete
+    }
+    
+    $vtk_viewer SetObjectMapImage [ $img GetImage ] 
+    set objectmapname [ $img cget -filename ]
+    $vtk_viewer UpdateDisplay
+
+    set tname [ ::pxtclutil::GenerateVOIFileNameFromImageName $objectmapname ]
+    set ineditor [ $vtk_viewer GetInternalEditor ]
+    if { $ineditor != "" &&  [ file exists $tname ] ==1 } {
+	
+	set numc [ $ineditor GetNumberOfVOIS ]
+	set mlist [ ::pxtclutil::LoadVOINamesList $tname $numc ]
+	array set tmpname $mlist
+	for { set i 0 } { $i < $numc } { incr i } {
+	    $ineditor SetVOIName $i $tmpname($i)
+	}
+    }
+
+    itcl::delete object $img 
+    WatchOff
+    return 1
+
+}
+
+itcl::body pxitclbaseimageviewer::GetObjectmapName  { } {
+    return $objectmapname
+}
+
+itcl::body pxitclbaseimageviewer::SaveObjectmap  { fname comment } {
+
+    set mask [ $vtk_viewer GetObjectMapImage ]
+
+    if { [ string length $fname ] < 2 } {
+	set f2  $objectmapname 
+	set f2path [ file dirname $f2 ]
+	set f2tail [ file tail    $f2 ]
+	
+	set typelist { 	    {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }} }
+
+	set fname  [tk_getSaveFile -title "Objectmap Filename" -filetypes $typelist -initialfile $f2tail -initialdir $f2path ]
+    }
+    
+    if { [  string length $fname ] < 2 } {
+	return 0
+    }
+
+    set ext [ file extension $fname ]
+
+    set ok [ file writable [ file dirname $fname ] ]
+    if { [ file exists $fname ] } {
+	set ok [ file writable $fname ]
+    }
+    if { $ok ==0 } {
+	tk_messageBox -title "Cannot save objectmap!" -type ok -message "You can not save objectmap in $fname [ file writable $fname ]"
+	return 0
+    }
+
+    if { [ string length $fname ] > 0 } {
+	set vtkwriter [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ] ]
+	$vtkwriter SetFileName    $fname
+	$vtkwriter SetInput       $mask
+	$vtkwriter SetImageHeader [ $currentimage GetImageHeader ]
+	
+	set hd [ $vtkwriter GetImageHeader ]
+	set md [ $hd GetMode ]
+	if { $md ==0 && $forceimageoutputformat == 2 } {
+	    $hd SetModeToNIFTI_HDRIMG
+	} elseif { $md > 0 && $forceimageoutputformat == 1 } {
+	    $hd SetModeToAnalyze
+	}
+	
+	if { $ext == ".gz" } {
+	    $vtkwriter SetCompression 9
+	    set line "Compressed"
+	    set objectmapname [ file root $fname ]
+	} else {
+	    set line ""
+	    set objectmapname  $fname 
+	}
+
+	SetFilterCallbacks $vtkwriter "${comment}Saving ${line} $ Image"
+	WatchOn 
+	$vtkwriter Update
+	set status [ $vtkwriter GetSaveStatus ]
+	
+	if { $status == 0 } {
+	    ::pxtclutil::Warning "Failed to save objectmap in $fname"
+	} else {
+	    set tname [ ::pxtclutil::GenerateVOIFileNameFromImageName $objectmapname ]
+
+	    set ineditor [ $vtk_viewer GetInternalEditor ]
+	    if { $ineditor != "" } {
+		set numc [ $ineditor GetNumberOfVOIS ]
+		set fileid [open $tname w]
+		puts $fileid "\[ Objectmap Colors for $objectmapname \]"
+		for { set i 0 } { $i < $numc } { incr i } {
+		    puts $fileid "$i : [ $ineditor GetVOIName $i ]"
+		}
+		close $fileid
+	    }
+	}
+	WatchOff 
+	catch { $vtkwriter Delete }
+    }
+}
+
+itcl::body pxitclbaseimageviewer::ShowPaintControls { } {
+    set ineditor [ $vtk_viewer GetInternalEditor ]
+    #    puts stderr "ineditor=$ineditor"
+    $ineditor Show 1
+}
+
+itcl::body pxitclbaseimageviewer::ClearObjectmap { } {
+
+    set mask [ $vtk_viewer GetObjectMapImage ]
+    set ok [ $this QuestionReplaceObjectmap $mask "This will clear your current objectmap. Are you sure?" ]
+
+    if { $ok == 0 } {
+	return
+    }
+
+    set tmp [ vtkImageData [ pxvtable::vnewobj ]]
+    $tmp CopyStructure [ [ $this GetDisplayedImage ] GetImage ]
+    $tmp SetScalarTypeToUnsignedChar
+    $tmp SetNumberOfScalarComponents 1
+    $tmp AllocateScalars
+    [ [ $tmp GetPointData ] GetScalars ] FillComponent 0 0.0
+    $vtk_viewer SetObjectMapImage $tmp
+    set  objectmapname    "objectmap.hdr"
+    $tmp Delete
+
+    set ineditor [ $vtk_viewer GetInternalEditor ]
+    if { $ineditor != "" } {
+	    set numc [ $ineditor GetNumberOfVOIS ]
+	    for { set i 0 } { $i < $numc } { incr i } {
+		$ineditor SetVOIName $i "Region $i"
+	    }
+	}
+
+}
+
+itcl::body pxitclbaseimageviewer::AutosaveInvoke  { } {
+
+    if { $thisparam($this,autosave) == 1 } {
+	$this AutosaveEvent
+    }
+}
+
+
+itcl::body pxitclbaseimageviewer::AutosaveEvent  { } {
+
+    if { $thisparam($this,autosave) == 1 } {
+	set oldname $objectmapname
+	
+	set newname $objectmapname
+	set ext [ file extension $newname ]
+	set ext2 ""
+	set outn [ file root $newname ]
+	if { $ext == ".gz" } {
+	    set ext2 ".gz"
+	    set ext  [ file extension $outn ]
+	    set outn [ file root $outn   ]
+	}
+	
+	set newname "${outn}_autosave${ext}${ext2}"
+
+	$this SaveObjectmap $newname "Auto-"
+	pxtkprint "**** Autosaved objectmap in\n\t [ file normalize $newname ] [ exec date ]\n"
+	set objectmapname $oldname
+	eval "after 60000 $this AutosaveEvent"
+    }
+}
+
+itcl::body pxitclbaseimageviewer::ObjectmapHistogram { inp } { 
+
+    set image_ref [ $currentimage GetImage ]
+
+    if { $inp == 1 } {
+	set dognuplot 1
+	set inp 0
+    } else {
+	set dognuplot 0
+    }
+
+    if { $inp == 0 || $inp == 1 } {
+	set inp   [ $vtk_viewer GetObjectMapImage ]
+    }
+
+    
+    if { [ $currentimage  GetImageSize ] < 2 } {
+	if { [ $currentresults  GetImageSize ] < 2 } {
+	    puts stderr "Bailing Out ..."
+	    return
+	}
+	set image_ref [  $currentresults GetImage ]
+    }
+
+    catch {
+	set timg [ $vtk_viewer GetValueImage ]
+	set d [ $timg GetDimensions ]
+	if { [ lindex $d 0 ] > 1 } {
+	    set image_ref $timg
+	    pxtkprint "Using Value Image for ROI Analysis"
+	}
+    }
+
+    set rmin 0
+    set rmax 0
+
+    catch {
+	[ [ $inp GetPointData ] GetScalars ] Modified
+	set r   [ [ [ $inp GetPointData ] GetScalars ] GetRange ]
+	set rmin [ lindex $r 0 ]
+	set rmax [ lindex $r 1 ]
+    }
+
+    if { $rmax == $rmin } {
+	pxtclutil::Warning "No Objectmap in memory (uniform level)\n"
+	puts stderr "Bailing Out ..."
+	return
+    }
+    
+    set ident [ vtkIdentityTransform [pxvtable::vnewobj ]]
+    set thr [ vtkpxMergeFmriConventional [ pxvtable::vnewobj ]]
+    set arr [ vtkFloatArray [ pxvtable::vnewobj ]]
+    set nt [  $thr ComputeROIStatistics $image_ref $inp  $ident $arr ]
+    $thr Delete
+    $ident Delete
+    
+
+    if { $dognuplot != 1 } {
+	set fname  [tk_getSaveFile -title "Output VOI File" -filetypes { {"VOI Text File" {.txt}}} ]
+	set fout 0
+	if { [ string length $fname ] > 0 } {
+	    set fout [ open $fname w ]
+	}
+	
+	set spa [ $inp GetSpacing ]
+	set vox [ expr [ lindex $spa 0 ] * [ lindex $spa 1 ] * [ lindex $spa 2 ]]
+	pxtkconsole
+	set line "\n\nVOI Statistics Output\n-------------------------------------------------------------------------------------------------------------------------\n\n"
+	pxtkprint $line
+	
+        set nc [ $image_ref GetNumberOfScalarComponents ]
+	
+	if { $nc > 1 } {
+	    set line "\#VOI                \t Frame \t Volume (mm^3) \t Volume (voxels) \t Centroid (Vox) i \t j \t k \t  Mean Value \t Std Value \t Max Value \t Max Location i \t j \t k \n"
+	} else {
+	    set line "\#VOI             \t Volume (mm^3)\t Vol (voxels)\tCentroid i\tCentroid j\tCentroid k\t Mean Value \t Std Value \t Max Value \t Max Loc i \t Max Loc j \t Max Loc k \n"
+	}
+	pxtkprint $line
+	if { $fout!=0 } { puts -nonewline $fout $line }
+	
+	
+	set doeditor 0
+	set ineditor [ $vtk_viewer GetInternalEditor ]
+	if { $ineditor != "" } {
+	    set doeditor 1
+	}
+	
+	
+	pxtkprint "\n---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"
+	for { set i 0 } { $i < $nt } { incr i } {
+	    set n [ $arr GetComponent $i 2 ]
+	    set ind [ expr int([ $arr GetComponent $i 1 ]) ]
+	    if { $n > 0 } {
+		#	    puts stderr "ind = $ind , [ $arr GetComponent $i 0 ]"
+		if { $ind > 0 } {
+		    if { $doeditor ==1 } { 
+			set name [ $ineditor GetVOIName $ind ]
+		    } else {
+			set name "VOI $ind "
+		    }
+
+		    set frame [ $arr GetComponent $i 0 ]
+		    set line [ format "%-20s " $name ]
+		    if { $nc > 1 } {
+			set line "$line \t $frame"
+		    }
+		    
+		    # volume in mm^3 and voxels
+		    set line [ format "%s \t %-8.2f \t %-8d "  $line [ expr [ $arr GetComponent $i 6 ] ] [ expr int([ $arr GetComponent $i 2 ])] ]
+		    
+		    # Centroid is next
+		    set line [ format "%s \t %-06.2f \t %-06.2f \t %-06.2f " $line [ $arr GetComponent $i 12 ] [ $arr GetComponent $i 13 ] [ $arr GetComponent $i 14 ]  ]
+		    
+		    # Mean and Sigma and Max Value
+		    set line [ format "%s \t %-010.4f \t %-010.4f \t %-010.4f " $line [ $arr GetComponent $i 3 ] [ $arr GetComponent $i 4 ] [ $arr GetComponent $i 8 ] ]
+		    set line [ format "%s \t %-010.4f \t %-010.4f \t %-010.4f " $line [ $arr GetComponent $i 9 ] [ $arr GetComponent $i 10 ] [ $arr GetComponent $i 11 ] ]
+		    
+		    
+		    pxtkprint "$line\n"
+		    if { $fout !=0 } { puts $fout $line }
+		}
+	    } else {
+		puts stdout "Ignoring VOI=$ind"
+	    }
+	}
+
+	if { $fout != 0 } {
+	    close $fout
+	}
+    } else {
+
+	set nc [ $image_ref GetNumberOfScalarComponents ]
+	set tname "/tmp/[ pid].dat"
+	set numusing 0
+#	puts stdout "Writing to $tname nc=$nc nt=$nt numtuples=[ $arr GetNumberOfTuples ]"
+	set fout [ open $tname w  ]
+
+	set doeditor 0
+	set ineditor [ $vtk_viewer GetInternalEditor ]
+	if { $ineditor != "" } {
+	    set doeditor 1
+	}
+	
+	for { set i 0 } { $i < $nt } { incr i  } {
+	    set using($i) 0
+	}
+
+	set line "\# Frame\t"
+	set f 1
+	for { set i 0 } { $i < $nt } { incr i  } {
+
+#	    puts "Checking line $i/$nt"
+	    set n [ $arr GetComponent $i 2 ]
+	    set ind [ expr int([ $arr GetComponent $i 1 ]) ]
+	    set frame [ expr int([ $arr GetComponent $i 0 ])]
+	    if { $n > 0 && $ind > 0 && $frame == 0 } {
+		if { $doeditor ==1 } { 
+		    set name [ $ineditor GetVOIName $ind ]
+		} else {
+		    set name "VOI $ind "
+		}
+		append line "$name\t"
+		set using($ind) 1
+		set voiname($f) $name
+		incr f
+		incr numusing
+	    } 		
+	}
+	puts $fout "$line"
+#	puts stdout "$line"
+
+	set line ""
+	set currentframe 0
+	for { set it 0 } { $it < $nt } { incr it } {
+	    set ind [ expr int([ $arr GetComponent $it 1 ]) ]
+	    set frame [ expr int([ $arr GetComponent $it 0 ])]
+	    set val [ $arr GetComponent $it 3 ]
+	    if { $ind == 0 } {
+		set currentframe $frame
+		if { $currentframe > 0 } {
+		    append line "\n[expr $frame+1 ]\t"
+		} else {
+		    append line "[expr $frame+1]\t"
+		}
+	    }
+	    
+	    if { $using($ind) > 0 } {
+		if {  $frame == $currentframe } {
+		    append line "$val\t"
+#		    puts stderr "Using it=$it, ind=$ind, frame=$frame current=$currentframe, line=$line"
+		} else {
+	#	    puts stderr "Skipping it=$it, ind=$ind, frame=$frame current=$currentframe, line=$line"
+		} 
+	    }
+	}
+	puts $fout $line
+	close $fout
+
+	set sname "/tmp/[ pid].gpl"
+	set fout [ open $sname w ]
+	puts $fout "set grid"
+	puts $fout "set xlabel 'Time (frames)'"
+	puts $fout "set ylabel 'ROI Value'"
+	puts $fout "set title 'VOI Plot' "
+	set line "plot"
+	for { set i 1 } { $i <=$numusing } { incr i } {
+	    append line " '$tname' using 1:[expr $i+1 ] w lp title \"$voiname($i)\" " 
+	    if { $i != $numusing } {
+		append line ", "
+	    }
+	}
+	puts $fout $line
+#	puts stdout "$line\n"
+	puts $fout "pause -1 'Press return to close gnuplot "
+	close $fout
+	catch { exec xterm -geometry 40x2 -bg blue -fg white -title gnuplot -e  gnuplot $sname & }
+	after 500
+	file delete $tname
+	file delete $sname
+    }
+
+    $arr Delete
+}
+
+
+# -----------------------
+#  Basic Menu
+# -----------------------
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::AddControl { control } {
+    
+    lappend controllist $control
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::AddShowControl { control } {
+    
+    lappend showcontrollist $control
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::CreateControls { inpwidget } {
+
+    global pxtcl_pref_array
+
+    if { $enable_talaraichoption == 1 } {
+	set p2 $::pxtclvtkpxcontrib::imagedir 
+
+	set fname [ file join $p2 colinlookup ]
+	set tal [ vtkpxTalairachTransform [ pxvtable::vnewobj ]]
+	$tal SetColinLookupFileName $fname 0
+	set fname [ file join $p2 colin_talairach_lookup.nii.gz ]
+	$tal SetColinLookupFileName $fname 1
+	$tal Delete
+    }
+
+    if { $enable_histcontrol ==1 || $enable_imageutility == 1  } {
+
+	set cntrlm [ menu $menubase.cntrl -tearoff 0  ] 
+	$menubase add cascade -underline 0  -label "Image Processing"  -menu $cntrlm
+    }
+
+    if { $enable_histcontrol == 1 } {
+
+	set histcontrol [ pxitclimagenormalization \#auto $this ] 
+	set w $inpwidget.$histcontrol
+	set histcontrol [ $histcontrol GetThisPointer ]
+	$histcontrol Initialize $w
+	AddControl $histcontrol
+	$histcontrol AddToMenuButton $cntrlm "Histogram Control"
+	$cntrlm add separator
+    }
+
+
+    if { $enable_imageutility == 1 } {
+	set imageutility [ bis_guiimageutility \#auto  0 ]
+	$imageutility InitializeFromContainer $this
+	set w $inpwidget.$imageutility
+
+	set imageutility [ $imageutility GetThisPointer ]
+	$imageutility CreateGUI $w 
+	AddControl $imageutility
+	$imageutility AddToMenuButton $cntrlm
+
+	set imageutility2 [ [ bis_guiimageutility \#auto 1 ] GetThisPointer ]
+	$imageutility2 InitializeFromContainer $this
+	set w $inpwidget.[ pxvtable::vnewobj ]
+	$imageutility2 CreateGUI $w 
+	$cntrlm add separator
+	AddControl $imageutility2
+	$imageutility2 AddToMenuButton $cntrlm
+
+    }
+
+
+    if { $enable_landmarkcontrol == 1 } {
+	set landmarkcontrol [ [ pxitclLandmarkControl \#auto $this ]  GetThisPointer ]
+	$landmarkcontrol Initialize $inpwidget $vtk_viewer
+
+	if { [ $vtk_viewer IsA "vtkpxGUIOrthogonalViewer"  ] } {
+#	    puts stderr "Adding here ................... [ $landmarkcontrol GetLandmarkControl ], [ $vtk_viewer GetVolumeControl ]"
+	    [ $vtk_viewer GetVolumeControl ] SetLandmarkControl [ $landmarkcontrol GetLandmarkControl ]
+#	    puts stderr "Added here ................... [ [ $vtk_viewer GetVolumeControl ] GetLandmarkControl ] [ [ [ $vtk_viewer GetVolumeControl ] GetLandmarkControl ] GetClassName ]"
+	}
+    }
+    if { $enable_polydatacontrol == 1 } {
+	set polydatacontrol [ [ pxitclPolyDataControl \#auto $this ]  GetThisPointer ]
+	$polydatacontrol Initialize $inpwidget $vtk_viewer
+    }
+
+
+
+
+    if { ( $enable_brainstriptool > 0 ) || $enable_expfittool==1 } {
+
+	set mb [ menu $menubase.seg -tearoff 0  ]
+	$menubase add cascade -underline 0  -label "Segmentation" -menu $mb
+    
+        if { $enable_brainstriptool > 0 } {
+	    set brainstriptool [ pxitclbrainstrip \#auto $this ]
+	    set w ${inpwidget}.${brainstriptool}
+	    set brainstriptool [ $brainstriptool GetThisPointer ]
+
+	    if { $enable_brainstriptool == 2 } {
+		$brainstriptool configure -enable_fsl 0
+		$brainstriptool configure -enable_duallevelset 0
+	    } 
+
+	    if { $enable_polydatacontrol == 1 && $enable_landmarkcontrol == 1 } {
+		$brainstriptool SetPolyDataAndLandmarkControls [  $polydatacontrol GetPolyDataControl ] [ $landmarkcontrol GetLandmarkControl ] 
+	    } else { 
+		$brainstriptool DisableLevelSets
+	    }
+	    $brainstriptool Initialize $w $vtk_viewer
+	    AddControl $brainstriptool
+	    $brainstriptool AddToMenuButton $mb
+	}
+	
+	if { $enable_expfittool == 1 } {
+
+	    if { $brainstriptool != 0 } {
+		$mb add separator
+	    }
+	    
+	    set expfittool [ pxitclexpfit \#auto $this ]
+	    set w ${inpwidget}.[ pxvtable::vnewobj ] 
+	    set expfittool [ $expfittool GetThisPointer ]
+	    
+	    $expfittool Initialize $w 
+	    AddControl $expfittool
+	    $expfittool AddToMenuButton $mb
+
+	}
+
+    }
+
+    if { $enable_landmarkcontrol ==1 || $enable_polydatacontrol == 1 } {
+
+	#	menubutton $menubase.features -text "Features" -menu $menubase.features.m 
+	#	set packfeatures 1
+	#	set mb [ menu $menubase.features.m -tearoff 0  ]
+	set mb [ menu $menubase.features -tearoff 0  ]
+	$menubase add cascade -underline 0  -label "Features" -menu $mb
+	set featuremenu $mb
+
+	if { ($enable_landmarkcontrol == 1 || $enable_landmarkclicks == 1 ) && $vtk_viewer != 0 } {
+	    if { [ $vtk_viewer IsA vtkpxGUIOrthogonalViewer ] } {
+		eval "$mb add check -label \"Shift/Click to Landmark\" -variable [ itcl::scope thisparam($this,mousetolandmarks)] "
+		eval "$mb add check  -variable [ itcl::scope thisparam($this,volumetrace) ] -label \"Enable Volume Trace\" -command { $this EnableVolumeTrace  } "
+		eval "$mb add check  -variable [ itcl::scope thisparam($this,geometrytrace) ] -label \"Enable Geometry Trace\" -command { $this EnableSurfaceTrace  } "
+	    } else {
+		eval "$mb add check -label \"Shift/Click to Landmark\" -variable [ itcl::scope thisparam($this,mousetolandmarks)] -command { $this SetShiftMouseToEditor  }"
+		SetShiftMouseToEditor
+	    }
+	    $mb add separator
+	    
+	    if { $enable_landmarkcontrol == 1 } {
+		AddShowControl $landmarkcontrol
+		$landmarkcontrol AddToMenuButton $mb "Landmark Control"
+	    }
+	}
+	
+	if { $enable_polydatacontrol == 1 } {
+	    AddShowControl $polydatacontrol
+	    $polydatacontrol AddToMenuButton $mb "Surface Control"
+
+	    if { $enable_surfaceobjectmap == 1 } {
+		set surfaceobjectmap [ [ pxitclsurfaceobjectmap \#auto $this ] GetThisPointer ]
+		$surfaceobjectmap Initialize $inpwidget.[pxvtable::vnewobj] [ $polydatacontrol GetPolyDataControl ]
+		$surfaceobjectmap AddToMenuButton $mb "Surface Objectmap Control"
+	    }
+
+
+	}
+	
+	
+
+	set val $pxtcl_pref_array(ManualTalairach)
+	if { $enable_talaraichoption == 1 && $val == "On" } {
+	    
+	    $mb add separator
+	    set mb2 [ menu $menubase.features.tal -tearoff 0  ]
+	    $menubase.features add cascade -underline 0  -label "Talairach"  -menu $mb2
+	
+	    if { $landmarkcontrol !=0  } {
+		eval "$mb2 add command -label \"Current Landmark -> Talairach\" -command {  $this CurrentLandmarkToTalairach }"
+		$mb2 add separator
+	    }
+	    eval "$mb2 add command -label \"Load Talairach Transform\" -command { $vtk_viewer LoadTalairachTransform \"\" } "
+	    eval "$mb2 add command -label \"Save Talairach Transform\" -command { $vtk_viewer SaveTalairachTransform \"\" } "
+	    $mb2 add separator
+	    eval "$mb2 add command -label \"Old Style Mni2Talairach AP\" -command { $this SetOldStyleMNITalairachTransform 1 }"
+	    eval "$mb2 add command -label \"Old Style Mni2Talairach PA\" -command { $this SetOldStyleMNITalairachTransform 0 }"
+	}
+
+	if { $enable_vvlinkgadget == 1 && $pxtcl_pref_array(VectorVisionLink)=="Enabled" } {
+	    set vvlinkgadget [ pxitclvvlinkgadget  \#auto $this ]
+	    set w ${basewidget}.${vvlinkgadget}
+	    set vvlinkgadget [ $vvlinkgadget GetThisPointer ]
+	    $vvlinkgadget Initialize $w $vtk_viewer
+	    $mb add separator
+	    $vvlinkgadget AddToMenuButton $mb
+	}
+
+	    if { $enable_openigtlinkgadget == 1 &&  $pxtcl_pref_array(OpenIGTLink)=="Enabled" } {
+	    set openigtlinkgadget [ pxitclopenigtlinkgadget  \#auto $this ]
+	    set w ${basewidget}.${openigtlinkgadget}
+	    set openigtlinkgadget [ $openigtlinkgadget GetThisPointer ]
+	    $openigtlinkgadget Initialize $w $vtk_viewer
+	    $mb add separator
+	    $openigtlinkgadget AddToMenuButton $mb
+	}
+
+    }
+
+
+    if { $enable_talaraichoption == 1 } {
+	set mb [ menu $menubase.atl -tearoff 0  ]
+	$menubase add cascade -underline 0  -label "Atlas Tools"   -menu $mb
+	if { $atlastool == 0 } {
+	    set atlastool [ pxitclatlasgadget \#auto $this ]
+	    set w ${basewidget}.${atlastool}
+	    set atlastool [ $atlastool GetThisPointer ]
+	    $atlastool Initialize $w
+	    AddControl $atlastool
+	}
+	$atlastool AddToMenuButton $mb
+    }
+
+    if { $enable_overlaytool == 1 } {
+
+	set mb [ menu $menubase.reg -tearoff 0  ]
+	$menubase add cascade -underline 0  -label Registration   -menu $mb
+
+	set overlaytool [ [ bis_guioverlayutility \#auto ] GetThisPointer ]
+	set w ${inpwidget}.${overlaytool}
+	$overlaytool InitializeFromContainer $this
+	$overlaytool CreateGUI $w 
+	AddControl $overlaytool
+	$overlaytool AddToMenuButton $mb
+    }
+
+    if { $enable_multisubjectcontrol == 1 } {
+	
+	set mb [ menu $menubase.mt -tearoff 0  ]
+	$menubase add cascade -underline 0  -label Multi-Subject -menu $mb
+
+	set multisubjectcontrol [ pxitclmultisubjectaverage \#auto $this ]
+	set w ${inpwidget}.${multisubjectcontrol}
+	set multisubjectcontrol [ $multisubjectcontrol GetThisPointer ]
+	$multisubjectcontrol Initialize $w 
+	AddControl $multisubjectcontrol
+	$multisubjectcontrol AddToMenuButton $mb
+    }
+
+    if { $enable_objectmapmenu == 1 } {
+	set mb2 [ menu $menubase.fmrim -tearoff 0  ]
+	$menubase add cascade -underline 0  -label  "Objectmap"  -menu $mb2
+	eval "$mb2 add check -variable [ itcl::scope thisparam($this,autosave) ] -label \"Autosave\"  -command { $this AutosaveInvoke }"
+	$mb2 add separator
+	eval "$mb2 add command -label \"Show Paint Controls \" -command {  $this ShowPaintControls }"
+	$mb2 add separator
+	eval "$mb2 add command -label \"New Objectmap \" -command {  $this ClearObjectmap }"
+	eval "$mb2 add command -label \"Load Objectmap \" -command {  $this LoadObjectmap \"\" }"
+	eval "$mb2 add command -label \"Save Objectmap \" -command {  $this SaveObjectmap \"\" \"\" }"
+	$mb2 add separator
+	set thisparam($this,custobjectmaps)  [ pxitclfilelistmenu \#auto $mb2 "Custom Objectmaps" "$this LoadObjectmap  " "$this GetObjectmapName" ]
+	$thisparam($this,custobjectmaps) SetModeToObjectmaps
+	$thisparam($this,custobjectmaps) InitializeDisplay
+
+	if { $enable_talaraichoption == 1 } {
+	    $mb2 add separator
+	    eval "$mb2 add command  -label \"Load Brodmann Atlas \" -command {  $this LoadBrodmann }"
+	}
+	$mb2 add separator
+	eval "$mb2 add command  -label \"Grab From Current Displayed Image \" -command {  $this GrabObjectmap }"
+	$mb2 add separator
+	eval "$mb2 add command -label \"Objectmap Info \" -command {  $this ObjectmapInfo }"
+	eval "$mb2 add command -label \"VOI Volume/Stats Computation\"  -command { $this ObjectmapHistogram 0 }"
+	if {  [ ::pxtclutil::FindCommandInPath gnuplot ] !=0  } {
+	    if {  [ ::pxtclutil::FindCommandInPath xterm ] !=0  } {
+		eval "$mb2 add command -label \"Plot 4D Voi MAP\"  -command { $this ObjectmapHistogram 1 }"
+	    }
+	}
+	set objectmapmenu $mb2
+    }
+
+
+    if { $enable_fmrigadget ==1 || $enable_csigadget ==1 } {
+
+	set mb [ menu $menubase.fmrim -tearoff 0  ]
+	$menubase add cascade -underline 1  -label  "Functional"  -menu $mb
+
+	if { $enable_fmrigadget == 1 } {
+	    set w ${inpwidget}.${fmrigadget}
+	    toplevel $w; wm withdraw $w
+	    update idletasks 
+	    set fmrigadget [ bis_fmri \#auto $w 0 $vtk_viewer ]
+	    set fmrigadget [ $fmrigadget GetThisPointer ]
+	    $fmrigadget AddToMenuButtonLite $mb
+	}
+
+
+	if { $enable_csigadget == 1 } {
+	    set csigadget [ pxitclcsigadget \#auto $this ]
+	    set w ${inpwidget}.${csigadget}
+	    set csigadget [ $csigadget GetThisPointer ]
+	    $csigadget Initialize $w 
+	    AddControl $csigadget
+	    $csigadget AddToMenuButtonLite $mb
+	}
+
+    }
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::CreateHelpMenu { } { 
+
+    set helpm [ menu $menubase.help -tearoff 0  ]
+    $menubase add cascade -underline 0  -label "Help" -menu $helpm 
+    
+    eval "$helpm add command -label \"Help Index\" -command { $this HelpCommand }"
+    eval "$helpm add separator"
+    eval "$helpm add command -label Preferences -command { wm deiconify $pref_dialog}"
+    eval "$helpm add command -label ShowDBase -command { $this PrintDatabase }"
+    $helpm add command -label Console -command { pxtkconsole }
+    eval "$helpm add separator"
+    eval "$helpm add command -label \"Check for Updates\" -command { $this CheckForUpdates }"
+    eval "$helpm add separator"
+    eval "$helpm add command -label About -command { $this AboutCommand }"
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::CreateMenu { menubase } {
+
+    global env
+    global pxtcl_pref_array
+
+    #    menubutton $menubase.file          -text File      -menu $menubase.file.m 
+    #   pack $menubase.file   -side left
+
+    set filem [ menu $menubase.file -tearoff 0  ]
+    $menubase add cascade -underline 0  -label "File" -menu $filem
+
+    eval "$filem add command -label Load -command { $this LoadImage \"\" }  "
+    if { $enable_databasegadget == 1 } {
+	eval "$filem add command -label Query -command { $this QueryImage  }  "
+    }
+    eval "$filem add command -label Save -command { $this SaveImage } "
+    
+
+    
+
+    $filem add separator
+    eval "$filem add radio -variable [ itcl::scope forceimageoutputformat ] -value 0 -label \"Auto-Output Format\" -command { $this SetImageOutputFormat 0 } "
+    eval "$filem add radio -variable [ itcl::scope forceimageoutputformat ] -value 1 -label \"Force Analyze Format on Save\" -command { $this SetImageOutputFormat 1 }"
+    eval "$filem add radio -variable [ itcl::scope forceimageoutputformat ] -value 2 -label \"Force NIFTI Format on Save\" -command { $this SetImageOutputFormat 2 } "
+
+    $filem add separator
+    eval "$filem add command -label \"Switch Directory\" -command { $this SwitchDirectory } "
+
+
+    set thisparam($this,standimages) 0
+    $filem add separator
+
+    if { $show_standard_images == 1 } {
+	set thisparam($this,standimages) [ pxitclfilelistmenu \#auto $filem "Standard Images" "$this LoadImage"  ]
+	$thisparam($this,standimages) SetModeToStandardImages
+	$thisparam($this,standimages) InitializeDisplay
+    }
+
+    set thisparam($this,custimages)  [ pxitclfilelistmenu \#auto $filem "Custom Images" "$this LoadImage" "$this GetImageName" ]
+    $thisparam($this,custimages) SetModeToImages
+    $thisparam($this,custimages) InitializeDisplay
+    
+    
+    set thisparam($this,custdirectories)  [ pxitclfilelistmenu \#auto $filem "Custom Directories" "$this SwitchDirectory" ]
+    $thisparam($this,custdirectories) SetModeToDirectories
+    $thisparam($this,custdirectories) InitializeDisplay
+
+    if { $enable_headercontrol == 1 } {
+	$filem add separator
+	set headercontrol   [ vtkbisGUINIFTIHeaderEditor [ pxvtable::vnewobj ] ]
+	$headercontrol SetCallback "$this HeaderControlCallback"
+	$headercontrol Initialize $basewidget 0 
+	eval "$filem add command -label \"Image Header Editor\" -command { $headercontrol Show 1 } "
+	eval "bind all <Control-h>  { $headercontrol Show 1} "
+    }
+    
+    if { $enable_importcontrol == 1 } {
+	$filem add separator
+	eval "$filem add command -label Import -command { $this ImportImage }  ";
+	eval "$filem add command -label Export -command { $this ExportImage }  "
+    }
+    
+
+
+    $filem add separator
+    if { $standalone == 1 } {
+	    eval "$filem add command -label Exit -command {  $this ExitCommand } -underline 1"
+    } else {
+	eval "$filem add command -label Close -command {  $this HideWindow } -underline 1"
+    }
+
+
+    if { $enable_displaymenu == 1 } {
+
+	set displaym [ menu $menubase.display ]
+	$menubase add cascade -underline 0  -label "Display" -menu $displaym
+
+	#	menubutton $menubase.display       -text Display   -menu $menubase.display.m 
+	#	pack $menubase.display  -side left
+	#	menu $$displaym -tearoff 1
+	eval "$displaym add radio -variable [ itcl::scope thisparam($this,display)] -label Image  -command { $this ShowImage Image } "
+	eval "$displaym add radio -variable [ itcl::scope thisparam($this,display)] -label Results  -command { $this ShowImage Results } "
+	$displaym add separator
+	eval "$displaym add radio -variable [ itcl::scope thisparam($this,snapshotresolution) ] -value 0 -label \"Low Res Snapshots\" -command { $this SetSnapshotResolution 1 } "
+	eval "$displaym add radio -variable [ itcl::scope thisparam($this,snapshotresolution) ] -value 1 -label \"Low Medium Res Snapshots\" -command { $this SetSnapshotResolution 2 } "
+	eval "$displaym add radio -variable [ itcl::scope thisparam($this,snapshotresolution) ] -value 2 -label \"High Medium Res Snapshots\" -command { $this SetSnapshotResolution 3 } "
+	eval "$displaym add radio -variable [ itcl::scope thisparam($this,snapshotresolution) ] -value 3 -label \"High Res Snapshots\" -command { $this SetSnapshotResolution 4 } "
+	$displaym add separator
+	eval "$displaym add command -label \"Copy Results to Image\" -command { $this CopyResultsToImage }"
+	eval "$displaym add command -label \"Undo Copy Results\" -command { $this RevertToPreviousImage }"
+	if { [ $vtk_viewer IsA "vtkpxGUIObjectmapOrthogonalViewer"  ] == 1 ||
+	     [ $vtk_viewer IsA "vtkpxGUIObjectmapMosaicViewer" ] == 1 } {
+	    $displaym add separator
+	    eval "$displaym add command -label \"Copy Mask to Results\" -command { $this CopyMaskToResults }"
+	}
+      
+	$displaym add separator
+	eval "$displaym add command -label \"Set Viewer Background\" -command { $this SetViewerBackground }"
+
+
+	if { $enable_animationgadget == 1 } {
+	    if { [  $vtk_viewer IsA "vtkpxGUIOrthogonalViewer"] ==1 } {
+		$displaym add separator
+		set animationgadget [ [ pxitclanimationgadget \#auto $this ] GetThisPointer ]
+		$animationgadget Initialize ${basewidget}.[ pxvtable::vnewobj ]
+		$animationgadget SetViewer $vtk_viewer
+		$animationgadget AddToMenuButton $displaym
+	    }
+	}
+    }
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::HandleUpdateEvent { args } {
+    
+    if { $in_expose == 1 } { 
+	return
+    }
+
+    if {$vtk_viewer != 0 } {
+	set in_expose 1
+	update idletasks
+	$vtk_viewer UpdateDisplay
+	set in_expose 0
+    }
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::SetShiftMouseToEditor { } {
+    
+    if { $vtk_viewer == 0 } {
+	return
+    }
+    
+
+    if { [ $vtk_viewer IsA vtkpxGUIMosaicViewer ] ==1 } {
+	$vtk_viewer SetShiftMouseToEditor $thisparam($this,mousetolandmarks)
+    }
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::HandleMouseEvent { mouse stat x1 x2 widgetname args} {
+    
+    if { $vtk_viewer == 0 } {
+	return
+    }
+
+    # Need to flip y-axis vtk counts from bottom tk counts from top !!!
+    set wd [ [ $widgetname GetRenderWindow ] GetSize ]
+    set x2 [ expr [lindex $wd 1 ] - $x2 ]
+    $vtk_viewer HandleMouseButtonEvent $mouse $stat $x1 $x2
+    $this HandleCoordinatesChangeEvent $mouse $stat
+}
+
+itcl::body pxitclbaseimageviewer::HandleCoordinatesChangeEvent { { mouse -1 } { stat -1 } } {    
+
+    catch { set lv [ $vtk_viewer GetLastClickedPoint ] }
+
+    set currentpoint $lv
+    
+    if { [ llength $lv ] > 1 } {
+	if { [ lindex $lv 0 ] > -1 } {
+	    
+	    set lv [ $vtk_viewer GetLastClickedPointScaled ] 
+	    set px [ lindex $lv 0 ]
+	    set py [ lindex $lv 1 ]
+	    set pz [ lindex $lv 2 ]
+	    
+
+	    if { [ $vtk_viewer PaintingEnabled ] == 0 } {
+		if { $landmarkcontrol != 0 } {
+		    if {$mouse == 4 || $thisparam($this,mousetolandmarks) == 0 } {
+			[ $landmarkcontrol GetLandmarkControl ]  HandleClickedPoint $px $py $pz 1 $stat
+		    }
+		}
+	    }
+	    
+	    set lv [ $vtk_viewer GetLastClickedPointScaled ] 
+	    set px [ lindex $lv 0 ]
+	    set py [ lindex $lv 1 ]
+	    set pz [ lindex $lv 2 ]
+
+	    #	    puts stderr "Raw = [ $vtk_viewer GetLastClickedPoint ], Scaled = [ $vtk_viewer GetLastClickedPointScaled ] mouse=$mouse status=$stat"
+	    
+	    if { $polydatacontrol != 0 } {
+		[ $polydatacontrol GetPolyDataControl ] SetLastPoint $px $py $pz
+	    }
+	    
+	    if { $atlastool != 0 } {
+		set tal [ $vtk_viewer GetTalairachTransform ]
+		if { $tal != "" } {
+		    set md [ $tal GetColinMode ]
+		    set ysz [ $tal GetColinYSize ]
+
+		    if { $ysz != 216 } {
+			set md 0
+		    }
+			
+		    if { $md == 1 } {
+			$atlastool IdentifyPoint $px $py $pz
+		    } elseif { $md == -1 } {
+			$atlastool IdentifyPoint [ expr 180 - $px ] [ expr 216.0 - $py ] $pz
+		    } elseif { $ysz == 219 } {
+			$atlastool SetError "You are using the Yale-modified Colin brain which is  Not in MNI Space, Cannot Identify Point.\n"
+		    } else {
+			$atlastool SetError "Image Not in MNI Space, Cannot Identify Point.\n"
+		    }
+		}
+	    }
+	    
+	    if { $brainstriptool !=0 } {
+		$brainstriptool RequestUpdatedSeed 0
+	    }
+
+	    
+
+	    
+	    if { [ $vtk_viewer IsA "vtkpxGUIOrthogonalViewer" ] == 1} {
+		set upd [ $vtk_viewer GetMouseSliceChangeMode ]
+		if { $upd ==0 } {
+		    $vtk_viewer UpdateDisplay
+		}
+	    }
+	}
+	
+	if { $mousecallback != 0 } {
+	    eval "$mousecallback $this $mouse $stat"
+	}
+    }
+
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::CurrentLandmarkToTalairach { } {
+	
+    set baseCurve [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    $baseCurve Copy [ [ $landmarkcontrol GetLandmarkControl ] GetCollection -1 ]
+    $baseCurve Compact 
+    
+    set np [ [ $baseCurve GetPoints ] GetNumberOfPoints ]
+    if { $np < 4 } {
+	::pxtclutil::Warning "Need at least 4 points for talairach coordinate setup!"
+	$baseCurve Delete
+	return
+    }
+
+    $vtk_viewer SetTalairachPoints [ $baseCurve GetPoints]
+    $vtk_viewer MoveAxis 1
+    $baseCurve Delete 
+    tk_messageBox -title "For your information!" -type ok -message "Talairach Transformation Set!\n Make sure you save it before exiting the program"
+}
+
+itcl::body pxitclbaseimageviewer::EnableVolumeTrace {  } {
+    
+    if { $vtk_viewer == 0 } { return } 
+    if { [ $vtk_viewer IsA vtkpxGUIOrthogonalViewer  ] == 0 } { return }
+    $vtk_viewer SetTraceVolume $thisparam($this,volumetrace)
+    if { $thisparam($this,volumetrace) == 1 } { 
+	set thisparam($this,geometrytrace) 0 
+	$vtk_viewer SetTraceGeometry $thisparam($this,geometrytrace) 
+    }
+}
+
+itcl::body pxitclbaseimageviewer::EnableSurfaceTrace { } {
+    if { $vtk_viewer == 0 } { return } 
+    if { [ $vtk_viewer IsA vtkpxGUIOrthogonalViewer  ] == 0 } { return }
+    
+    $vtk_viewer SetTraceGeometry $thisparam($this,geometrytrace) 
+    if { $thisparam($this,geometrytrace) == 1 } { 
+	set thisparam($this,volumetrace) 0 
+	$vtk_viewer SetTraceVolume $thisparam($this,volumetrace)
+    }
+}
+
+itcl::body pxitclbaseimageviewer::HeaderControlCallback { } {
+    
+    set hdr [ $headercontrol GetHeader ]
+    set img [ [ pxitclimage \#auto ] GetThisPointer ]
+    $img ShallowCopy $currentimage
+    $img CopyImageHeaderAndFixImage $hdr
+    $this SetResultsFromObject $img $headercontrol
+    itcl::delete object $img
+
+}
+
+# ---------------------------------------------------------------------------------
+    
+itcl::body pxitclbaseimageviewer::InitializeOrthogonal4DViewer { widg standalone } {
+    if { $initialized == 1 } { return $basewidget }
+    set enable_polydatacontrol 0
+    set enable_overlaytool 0
+    set enable_brainstriptool 0
+    set enable_surfaceobjctmap 0
+    set  bind_mouse_events 1
+    set  enable_helpmenu 0
+    set vtk_viewer [ vtkpxGUIOrthogonal4DViewer [ pxvtable::vnewobj ]]
+    set w [ InitializeInterface $widg $standalone ]
+    set cn [ $vtk_viewer InitializeMovieControl $w 0 ]
+    eval "bind all <Control-m> { wm deiconify $cn} "
+    return $w
+}
+
+itcl::body pxitclbaseimageviewer::InitializeOrthogonalViewer { widg standalone } {
+    if { $initialized == 1 } { return $basewidget }
+    set vtk_viewer [ vtkpxGUIOrthogonalViewer [ pxvtable::vnewobj ]]
+    if { $enable_talaraichoption == 0 } {
+	$vtk_viewer DisableTalairachButtons
+    }
+    set  bind_mouse_events 1
+    return [ InitializeInterface $widg $standalone ]
+}
+
+itcl::body pxitclbaseimageviewer::InitializeObjectmapViewer { widg standalone } {
+    if { $initialized == 1 } { return $basewidget }
+    set vtk_viewer [ vtkpxGUIObjectmapOrthogonalViewer [ pxvtable::vnewobj ]]
+
+    if { $enable_internaleditor == 1 } {
+	$vtk_viewer  SetCreateInternalEditorOn
+	set enable_landmarkcontrol 1
+	set enable_brainstriptool 1
+    }
+    
+    if { $enable_talaraichoption == 0 } {
+	$vtk_viewer DisableTalairachButtons
+    }
+
+    set  bind_mouse_events 1
+    return [ InitializeInterface $widg $standalone ]
+}
+
+
+itcl::body pxitclbaseimageviewer::InitializeMosaicViewer { widg standalone } {
+    if { $initialized == 1 } { return $basewidget }
+    set vtk_viewer [ vtkpxGUIMosaicViewer [ pxvtable::vnewobj ]]
+    set enable_polydatacontrol 0
+    set  bind_mouse_events 0
+
+
+    if { $enable_talaraichoption == 0 } {
+	$vtk_viewer DisableTalairachButtons
+    } else {
+	$vtk_viewer EnableTalairachButtons
+    }
+
+    return [ InitializeInterface $widg $standalone ]
+}
+
+itcl::body pxitclbaseimageviewer::InitializeMultipleMosaicViewer { widg standalone } {
+    if { $initialized == 1 } { return $basewidget }
+    set vtk_viewer [ vtkpxGUIMultipleMosaicViewer [ pxvtable::vnewobj ]]
+    set enable_polydatacontrol 0
+    set  bind_mouse_events 0
+
+    if { $enable_talaraichoption == 0 } {
+	$vtk_viewer DisableTalairachButtons
+    } else {
+	$vtk_viewer EnableTalairachButtons
+    }
+
+    return [ InitializeInterface $widg $standalone ]
+}
+
+
+itcl::body pxitclbaseimageviewer::InitializeObjectmapMosaicViewer { widg standalone } {
+    if { $initialized == 1 } { return $basewidget }
+    set vtk_viewer [ vtkpxGUIObjectmapMosaicViewer [ pxvtable::vnewobj ]]
+    set enable_polydatacontrol 0
+    set bind_mouse_events 0
+    set enable_landmarkcontrol 1
+    set enable_brainstriptool 1
+
+    if { $enable_talaraichoption == 0 } {
+	$vtk_viewer DisableTalairachButtons
+    } else {
+	$vtk_viewer EnableTalairachButtons
+    }
+    if { $enable_internaleditor == 1 } {
+	$vtk_viewer  SetCreateInternalEditorOn
+    }
+    return [ InitializeInterface $widg $standalone ]
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::InitializeViewer {  } {
+
+    if { $vtk_viewer ==0 } { return }
+
+    $vtk_viewer SetEnableRendering $enable_rendering_on_startup 
+    $vtk_viewer Initialize $viewerbase 1
+    if { $bind_mouse_events == 1 } {
+	$vtk_viewer BindMouseEvents [ $vtk_viewer GetRenderWidgetName ] "$this HandleMouseEvent" "" 
+    }
+    
+    $vtk_viewer SetCoordinatesChangeCallback "$this HandleCoordinatesChangeEvent" 
+    $vtk_viewer SetEnableCoordinatesChangeCallback 1
+
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::InitializeInterface { widg st } {
+
+    if { $initialized == 1 } { return $basewidget }
+    
+    set basewidget $widg
+    toplevel $basewidget ; wm withdraw $basewidget
+    wm geometry $basewidget 650x590
+    wm title $basewidget $appname
+    set standalone $st
+
+    #    set menubasef    [ frame $basewidget.top     -width 400 -height 50 ]
+    set menubase     [ menu $basewidget.top -tearoff 0  ]
+    $basewidget configure -menu $menubase
+    set viewerbase   [ frame $basewidget.viewer1 -width 400 -height 300 ]
+    set pbar         [ frame $basewidget.pbar    -width 400 -height 20 ]
+
+    InitializeViewer
+	
+    CreateProgressBar  $pbar
+    
+    pack $pbar       -side bottom -expand false -fill x
+    pack $viewerbase -side top -expand true -fill both
+    
+    bind all <F1>  { pxtkconsole }
+
+    if { $standalone == 1 } {
+	eval "bind all <Control-d>  { $this ExitCommand }"
+	eval "wm protocol . WM_DELETE_WINDOW { $this ExitCommand } "
+	eval "wm protocol $basewidget WM_DELETE_WINDOW { $this ExitCommand  }"
+	set pref_dialog [ ::pxtcluserprefs::CreatePreferenceEditor ]
+    } else {
+	eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    }
+
+
+    #    set menubase [ menu $menubasef.menubar -tearoff 0  ]
+    #puts stderr "$menubase $menubasef"
+    #pack $menubasef.m -side top -expand t -fill both
+    #$basewidget configure -menu $menubase
+    CreateMenu $menubase
+    CreateControls $viewerbase
+
+    set initialized 1
+
+    if { $standalone == 1 &&  $enable_helpmenu == 1 } {
+	CreateHelpMenu
+    }
+
+
+    
+
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbaseimageviewer::InitializeDisplay { widget st } {
+	
+    return [ InitializeOrthogonalViewer $widget $st ]
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclbrainregister.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclbrainregister.tcl
new file mode 100755
index 0000000..c7e653d
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclbrainregister.tcl
@@ -0,0 +1,806 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclbrainregister.tcl,v 1.3 2003/02/26 16:29:58 papad Exp $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] bis_algorithm ]
+
+package provide pxitclbrainregister 1.0
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+
+package require pxtcluserprefs 1.0
+package require labelframe 1.0
+package require pxtclutil 1.0
+package require pxvtable 1.0
+
+package require pxitclbaseimageviewer 1.0
+package require pxitclbasecontrol 1.0
+package require pxitclmanualtransformation 1.0
+package require pxitclmultisubjectaverage 1.0
+package require pxitcldistributiontablegadget 1.0
+package require bis_guioverlayutility 1.0
+package require bis_guirpmcontainer 1.0
+package require bis_fmri 1.0
+package require pxitclElectrodeMultiControl 1.0
+# -----------------------------------------------------
+#  Intialize Variables
+# -----------------------------------------------------
+
+itcl::class pxitclbrainregister {
+
+    inherit pxitclbasecontrol
+
+    protected variable pref_dialog 0
+    protected variable orthoviewer
+    protected variable simpleviewer 0
+    protected variable viewername
+    protected variable longviewername 
+    protected variable initialized 0
+    protected variable standalone 1
+    public    variable overlaytool 0
+    public    variable manualtransformationtool 0
+    public    variable rpmtool 0
+    public    variable csigadget 0
+    public    variable fmrigadget 0
+    public    variable multigadget 0
+    public    variable multi2gadget 0
+    public    variable electrode_control 0
+    public    variable electrode_control2 0
+    public    variable enable_multi2gadget 0
+    public    variable enable_multigadget 1
+    public    variable enable_rpmtool 1
+    public    variable enable_manualtransformation 1
+    public    variable enable_csigadget 0
+    public    variable enable_fmrigadget 1
+    public    variable enable_electrodecontrol 0
+    public    variable enable_electrodecontrol2 0
+    public    variable enable_rendering_on_startup 1
+    public    variable enable_simpleviewer 1
+    public    variable enable_vvlink 1
+    public    variable menubase 0
+    public    variable functionalmenu 0
+    public    variable donotcreatemenu 0
+    public    variable tdistgadget 0
+
+    private   common thisparam
+
+    constructor { par } {
+	pxitclbasecontrol::constructor $par
+    } {
+	InitializeBrainRegister
+    }
+
+    protected method InitializeBrainRegister { }
+    public method LoadImage { f transflag } 
+
+    public method HandleNewImage { viewer } 
+    public method HandleMouseEvent { viewer args } 
+    public method TransferImage { from_viewer args  } 
+    public method SimpleViewerGrabImage { from_viewer index  } 
+    public method CreateMenu { menubase }
+    public method CreateChildMenus { { viewerbase 0 } { registrationbase 0 } { functionalbase 0 } { multiplebase 0 } { helpbase 0 } }
+    public method CreateSimpleViewerMenu { viewm }
+    public method PositionWindows {  } 
+    public method Initialize { basewidget } 
+    public method GetOrthoViewer { name } { return $orthoviewer($name) }
+    public method ShowTTable { }
+    public method HideViewers { }
+
+}
+# -----------------------------------------------------    
+itcl::body pxitclbrainregister::InitializeBrainRegister { } {
+
+    global pxtcl_pref_array
+    
+    # -----------------------------
+    # Global Vtk Objects
+    # -----------------------------
+
+    set pref_dialog       [ ::pxtcluserprefs::CreatePreferenceEditor ]
+    set viewername(0)     "ref"
+    set viewername(1)     "trn"
+    set longviewername(0) "Reference"
+    set longviewername(1) "Transform"
+    set orthoviewer(ref) 0
+    set orthoviewer(trn) 0
+    set overlaytool 0
+
+    set appname "BioImage Suite::BrainRegister"
+
+}
+# ---------------------------------------------------------------------------------
+#   I/O Functions
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclbrainregister::LoadImage { f transflag } {
+    
+    $orthoviewer($transflag) LoadImage $f 
+}
+
+# ---------------------------------------------------------------------------------
+# Handle Mouse Press Callback
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbrainregister::HandleNewImage { viewer } {
+
+    set img [ $viewer cget -currentimage ]
+    set fname [ $img cget -filename ]
+    set or    [ $img GetOrientation ]
+
+    if { $viewer == $orthoviewer(trn) } {
+	set thisname  "trn"
+	$overlaytool SetFunctionalImage $img 
+    } else {
+	$overlaytool SetImage $img 
+    }
+}
+
+
+
+
+itcl::body pxitclbrainregister::HandleMouseEvent { viewer args  } {
+
+    # Assume it is the reference viewer
+    set thisname "ref"
+    set othername "trn"
+
+    # Check whether widgetname matches transform viewer
+    if { $viewer == $orthoviewer(trn) } {
+	set thisname  "trn"
+	set othername "ref"
+    }
+
+    # Label Viewers etc
+    set thisviewer   [ $orthoviewer($thisname)  GetViewer ]
+    set otherviewer  [ $orthoviewer($othername) GetViewer ]
+
+    set lv "" 
+    catch { set lv [ $thisviewer GetLastClickedPoint ] }
+
+    if { [ llength $lv ] > 1 } {
+	if { [ lindex $lv 0 ] > -1 } {
+	    # PolyData Control needs scaled points
+	    set lv [ $thisviewer GetLastClickedPointScaled ] 
+	    set px [ lindex $lv 0 ]
+	    set py [ lindex $lv 1 ]
+	    set pz [ lindex $lv 2 ]
+	    set upd0 [ $thisviewer GetMouseSliceChangeMode ]	
+	    set upd1 [ $otherviewer GetMouseSliceChangeMode ]
+	    if { $upd0 == 1 && $upd1 == 1 } {
+		$otherviewer CopyCamera $thisviewer
+		#		puts stderr "Setting ScaledCoordinates $px $py $pz"
+		$otherviewer SetScaledCoordinates $px $py $pz
+	    } 
+	}
+    }
+	
+    set upd1 [ $otherviewer GetMouseSliceChangeMode ]
+    if { $upd1 ==1 } {
+	$otherviewer CopyCamera $thisviewer
+	$otherviewer Update
+    }
+    
+    
+}
+
+
+itcl::body pxitclbrainregister::TransferImage { from_viewer args  } {
+
+    if { $from_viewer == "help" } {
+	tk_messageBox -title "About Transfer Images" -type ok -message "The image transfered is the one currently displayed.\n It is stored as \"image\" on the target viewer"
+    }
+    
+    if { $from_viewer == "swap" } {
+	set tmpimage       [  [ pxitclimage \#auto ] GetThisPointer ]
+	$tmpimage ShallowCopy [ $orthoviewer(ref) GetDisplayedImage ]
+	$orthoviewer(ref) SetImageFromObject [ $orthoviewer(trn) GetDisplayedImage ] $this
+	$orthoviewer(trn) SetImageFromObject $tmpimage $this
+	itcl::delete object $tmpimage
+	return
+    }
+    
+    if { [ llength $args ] > 0 } {
+	set to_viewer [ lindex $args 0 ]
+	if { ( $from_viewer == "trn" || $from_viewer == "ref" ) &&
+	     ( $to_viewer == "trn" || $to_viewer == "ref" ) && 
+	     ( $from_viewer != $to_viewer) } {
+	    $orthoviewer($to_viewer) SetImageFromObject [ $orthoviewer($from_viewer) GetDisplayedImage ] $this
+	    $orthoviewer($to_viewer) SetLookupTable [ [ $orthoviewer($from_viewer) GetViewer  ] GetLookupTable ]
+	    [ $orthoviewer($to_viewer) GetViewer ] UpdateDisplay
+	}
+    }
+}
+
+itcl::body pxitclbrainregister::SimpleViewerGrabImage { from_viewer index  } {
+
+
+    set simpvtkviewer [ $simpleviewer GetViewer ]
+    if { $from_viewer == "Clear" } {
+	$simpvtkviewer ClearAuxImages
+	return
+    }
+
+    
+    if { $from_viewer != "trn" && $from_viewer != "ref" } {
+	return
+    }
+
+    if { $index == 0 } {
+	$simpleviewer SetImageFromObject [ $orthoviewer($from_viewer) GetDisplayedImage ] $this
+	$simpleviewer SetLookupTable     [ [ $orthoviewer($from_viewer) GetViewer  ] GetLookupTable ]
+	$simpleviewer SetValueImage      [ [ $orthoviewer($from_viewer) GetViewer  ] GetValueImage  ]
+    } else {
+	$simpvtkviewer SetAuxImage [ [ $orthoviewer($from_viewer) GetDisplayedImage ] GetImage ] [ expr $index -1 ]
+    }
+
+    $simpvtkviewer UpdateDisplay
+    return
+
+}
+
+
+itcl::body pxitclbrainregister::HideViewers { } { 
+
+    catch { 
+	$orthoviewer(ref) HideWindow; 
+	$orthoviewer(trn) HideWindow
+	$simpleviewer     HideWindow;
+    }
+}
+
+# ---------------------------------------------------------------------------------
+# Create Menu
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbrainregister::CreateSimpleViewerMenu { viewm } {
+
+    eval "$viewm add command -label \"Simple Viewer\" -command { $simpleviewer ShowWindow }"
+    
+    set mbar [ $simpleviewer cget -menubase ]
+    $mbar delete 0 1
+    set mb [ menu $mbar.dispm -tearoff 0 ]; $mbar add cascade -underline 0  -label Display -menu $mb
+    set mb2 [ menu $mbar.atlas -tearoff 0 ]; $mbar add cascade -underline 0  -label "Atlas Tool" -menu $mb2
+
+    
+    eval "$mb add command  -label \"Grab Image From Reference Viewer\"  -command { $this SimpleViewerGrabImage ref 0 } "
+    eval "$mb add command  -label \"Grab Image From Transform Viewer\"  -command { $this SimpleViewerGrabImage trn 0 } "
+
+    set vname [ list ref trn ]
+    set name [ list Reference Transform ]
+
+    for { set j 0 } { $j <=1 } { incr j } {
+	$mb add separator
+	for { set i 1 } { $i <= 4 } { incr i } {
+	    eval "$mb add command  -label \"Grab Aux Image $i From [ lindex $name $j ] Viewer\"  -command { $this SimpleViewerGrabImage  [ lindex $vname $j ] $i } "
+	}
+    }
+    $mb add separator
+    eval "$mb add command -label \"Clear Aux Images\" -command {  $this SimpleViewerGrabImage Clear -1 } -underline 1"
+    eval "$mb add command -label Close -command {  $simpleviewer HideWindow } -underline 0"
+    [ $simpleviewer GetAtlasTool ] AddToMenuButton $mb2
+}
+
+
+itcl::body pxitclbrainregister::CreateMenu { menubase } {
+
+#    menubutton $menubase.view      -text Viewers      -menu $menubase.view.m -underline 0
+#    menubutton $menubase.tr      -text Transfer      -menu $menubase.tr.m -underline 0
+#    menubutton $menubase.help      -text Help         -menu $menubase.help.m -underline 0 -padx 4
+#    pack $menubase.view $menubase.tr  -side left
+#    pack $menubase.help  -side right
+
+    
+    set viewm [ menu $menubase.view -tearoff 0 ];     $menubase add cascade -underline 0  -label "Viewers" -menu $viewm
+    set trm   [ menu $menubase.tr   -tearoff 0 ];     $menubase add cascade -underline 0  -label "Transfer" -menu $trm
+
+
+    if { $overlaytool !=0 } {
+	set regm [ menu $menubase.regm -tearoff 0 ] ; $menubase add cascade -underline 0  -label "Registration"    -menu $regm ;
+	$overlaytool AddToMenuButton $regm
+	
+	if { $manualtransformationtool !=0 } {
+	    $regm add separator
+	    eval "$regm add command -label \"Manual Registration II\" -command { $manualtransformationtool ShowWindow }"
+	}
+
+	if {  $rpmtool !=0 } {
+	    $regm add separator
+	    eval "$regm add command -label \"Point-Based Registration\" -command { $this HideViewers;  $rpmtool ShowWindow }"
+	}
+    }
+    
+    if { $fmrigadget !=0 || $csigadget !=0  } {
+
+	set mb [ menu $menubase.fmri -tearoff 0 ]
+	set functionalmenu $mb
+	$menubase add cascade -underline 0  -label "Functional"  -menu $mb
+
+	if { $fmrigadget !=0 }  { $fmrigadget AddToMenuButtonLite $mb }
+	if { $csigadget !=0 }   { $csigadget AddToMenuButtonLite $mb;  }
+
+	if { $electrode_control !=0 } {
+	    $mb add separator
+	    eval "$mb add command -label \"Electrode Control (Transform Viewer)\" -command { $electrode_control ShowWindow }"
+	}
+	if { $electrode_control2 !=0 } {
+	    eval "$mb add command -label \"Electrode Control 2 (Transform Viewer)\" -command { $electrode_control2 ShowWindow }"
+	}
+
+    }
+
+
+
+
+    eval "$trm add command  -label \"Help with Transfer Features\"  -command { $this TransferImage help help } "
+    $trm add separator
+    eval "$trm add command  -label \"Displayed Image Reference->Transform\"  -command { $this TransferImage ref trn } "
+    eval "$trm add command  -label \"Displayed Image Transform->Reference\"  -command { $this TransferImage trn ref } "
+    $trm add separator
+    eval "$trm add command  -label \"Swap Displayed Transform->Reference\"  -command  { $this TransferImage  swap } "
+
+
+    eval "$viewm add command -label \"Reference Viewer\" -command { $orthoviewer(ref) ShowWindow; $this PositionWindows}"
+    eval "$viewm add command -label \"Transform Viewer\" -command { $orthoviewer(trn) ShowWindow ; $this PositionWindows}"
+    
+    if { $enable_simpleviewer == 1 } {
+	$viewm add separator
+	CreateSimpleViewerMenu $viewm
+    }
+
+    $viewm add separator
+    eval "$viewm add command -label \"Close Viewers\" -command { $this HideViewers  }"
+	
+    $viewm add separator
+    if { $standalone == 1 } {
+	    eval "$viewm add command -label Exit -command {  $this ExitCommand } -underline 1"
+    } else {
+	eval "$viewm add command -label Close -command { wm deiconify $basewidget }"
+    }
+    
+
+    if { $multigadget !=0 } {
+	set multi1 [ menu $menubase.multi1 -tearoff 0 ];     $menubase add cascade -underline 0  -label "Multi-subject" -menu $multi1
+	$multigadget AddToMenuButton $multi1 "$this PositionWindows"
+    }
+
+    if { $multi2gadget !=0 } {
+	set multi2 [ menu $menubase.multi2 -tearoff 0 ];     $menubase add cascade -underline 1  -label "Multi-subject 2" -menu $multi2
+	$multi2gadget AddToMenuButton $multi2 "$this PositionWindows"
+    }
+
+    set helpm [ menu $menubase.help -tearoff 0 ];     $menubase add cascade -underline 0  -label "Help" -menu $helpm
+
+    eval "$helpm add command -label \"Help Index\" -command { $this HelpCommand }"
+    eval "$helpm add separator"
+    eval "$helpm add command -label Preferences -command { wm deiconify $pref_dialog }"
+    $helpm add separator
+    eval "$helpm add command -label \"T-distribution table\" -command {  $this ShowTTable }"
+    $helpm add separator
+    $helpm add command -label "Console" -command {  pxtkconsole }
+    $helpm add separator
+    eval "$helpm add command -label \"Check for Updates\" -command { $this CheckForUpdates }"
+    $helpm add separator
+    eval "$helpm add command -label About -command { $this AboutCommand }"
+
+
+}
+
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclbrainregister::CreateChildMenus { { viewerbase 0 } { registrationbase 0 } { functionalbase 0 } { multiplebase 0 } { helpbase 0 } } {
+
+    if { $viewerbase == 0 } {
+	set viewm [ menu $menubase.view -tearoff 0 ];     $menubase add cascade -underline 0  -label "Viewers" -menu $viewm
+    } else {
+	set viewm $viewerbase
+    }
+
+
+    if { $overlaytool !=0 } {
+	if { $registrationbase == 0 } {
+	    set regm [ menu $menubase.regm -tearoff 0 ] ; $menubase add cascade -underline 0  -label "Registration"    -menu $regm ;
+	} else { 
+	    set regm $registrationbase
+	}
+	
+	$overlaytool AddToMenuButton $regm
+
+	
+	if {  $rpmtool !=0 } {
+	    $regm add separator
+	    eval "$regm add command -label \"Point-Based Registration\" -command { $this HideViewers; $rpmtool ShowWindow }"
+	}
+    }
+    
+    if { $fmrigadget !=0 || $csigadget !=0 } { 
+
+	if { $functionalbase == 0 } {
+	    set mb [ menu $menubase.fmri -tearoff 0 ]
+	    set functionalmenu $mb
+	    $menubase add cascade -underline 0  -label "Functional"  -menu $mb
+	} else {
+	    set functionalmenu $functionalbase
+	}
+
+	if { $fmrigadget !=0 }  { $fmrigadget AddToMenuButtonLite $functionalmenu }
+	if { $csigadget !=0 }   { $csigadget AddToMenuButtonLite $functionalmenu;  }
+	if { $electrode_control !=0 } {
+	    $functionalmenu add separator
+	    eval "$functionalmenu add command -label \"Electrode Control (Transform Viewer)\" -command { $electrode_control ShowWindow }"
+	}
+	if { $electrode_control2 !=0 } {
+	    eval "$functionalmenu add command -label \"Electrode Control 2 (Transform Viewer)\" -command { $electrode_control2 ShowWindow }"
+	}
+
+    }
+
+
+
+
+
+    eval "$viewm add command -label \"Reference Viewer\" -command { $orthoviewer(ref) ShowWindow }"
+    eval "$viewm add command -label \"Transform Viewer\" -command { $orthoviewer(trn) ShowWindow }"
+    
+    if { $enable_simpleviewer == 1 } {
+	$viewm add separator
+	CreateSimpleViewerMenu $viewm
+    }
+
+    $viewm add separator
+    eval "$viewm add command -label \"Close Viewers\" -command { $this HideViewers }"
+ 	
+
+    if { $multigadget !=0 } {
+	if { $multiplebase == 0 } {
+	    set multi1 [ menu $menubase.multi1 -tearoff 0 ];     $menubase add cascade -underline 0  -label "Multi-subject" -menu $multi1
+	} else {
+	    set multi1 $multiplebase
+	}
+	$multigadget AddToMenuButton $multi1 "$this PositionWindows"
+    }
+
+    if { $multi2gadget !=0 } {
+	if { $multiplebase == 0 } {
+	    set multi2 [ menu $menubase.multi2 -tearoff 0 ];     $menubase add cascade -underline 1  -label "Multi-subject 2" -menu $multi2
+	} else {
+	    set multi2 $multiplebase
+	}
+	$multi2gadget AddToMenuButton $multi2 "$this PositionWindows"
+    }
+
+    if { $helpbase == 0 } {
+	set helpm [ menu $menubase.help -tearoff 0 ];     $menubase add cascade -underline 0  -label "Help" -menu $helpm
+    } else {
+	set helpm $helpbase
+    }
+
+
+    eval "$helpm add command -label Preferences -command { wm deiconify $pref_dialog }"
+    $helpm add separator
+    eval "$helpm add command -label \"T-distribution table\" -command {  $this ShowTTable }"
+    $helpm add separator
+    
+
+    $helpm add command -label "Console" -command {  pxtkconsole }
+    $helpm add separator
+    eval "$helpm add command -label \"Check for Updates\" -command { $this CheckForUpdates }"
+    $helpm add separator
+    eval "$helpm add command -label About -command { $this AboutCommand }"
+
+
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbrainregister::ShowTTable {  } {
+
+    if {  $tdistgadget == 0 } {
+
+	set tdistgadget [ [ pxitcldistributiontablegadget \#auto $this ] GetThisPointer ]
+	$tdistgadget RegisterViewer $orthoviewer(ref) "Ref"
+	$tdistgadget RegisterViewer $orthoviewer(trn) "Trn"
+	$tdistgadget Initialize $basewidget.[pxvtable::vnewobj ]
+    }
+    $tdistgadget ShowWindow
+
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclbrainregister::PositionWindows {  } {
+    
+    set geom [ winfo geometry $basewidget ] 
+    scan $geom "%dx%d+%d+%d" w0 h0 x0 y0
+
+
+    set ref [ $orthoviewer(ref) GetBaseWidget ]
+    set trn [ $orthoviewer(trn) GetBaseWidget ]
+
+    set mult 0
+    set ok 0
+    if { $enable_multigadget } {
+	set mult [ $multigadget GetBaseWidget ] 
+	catch { set ok   [ winfo ismapped $mult ] }
+    }  elseif { $overlaytool != 0 } {
+	set mult [ $overlaytool GetBaseWidget ]
+	catch { set ok   [ winfo ismapped $mult ] }
+    } else {
+	set ok 0
+    }
+
+    if { $ok == 0 } {
+	set y0 [ expr $y0 + $h0 + 25 ]
+	set y1 $y0 
+	set x1 [ expr $x0 + 550 ]
+	set hgt 600
+    } else {
+	set y0 [ expr $y0 + $h0 + 15 ]
+	set x1 $x0
+	set y1 [ expr $y0 + 450 ]
+	set x2 [ expr $x0 + 580 ]
+	set y2 $y0
+	set hgt 600
+    }
+
+    if  { [ winfo ismapped $ref ] } {
+	wm geometry $ref "550x${hgt}+$x0+$y0"
+	raise $ref
+	if  { [ winfo ismapped $trn ] } {
+	    wm geometry $trn "550x${hgt}+$x1+$y1"
+	    raise $trn
+	}
+    } else {
+	if  { [ winfo ismapped $trn ] } {
+	    wm geometry $trn "550x${hgt}+$x0+$y0"
+	    raise $trn
+	}
+    }
+
+    if { $ok == 1 } {
+	wm geometry $mult "+$x2+$y2"
+	raise $mult
+    }
+	
+}
+
+
+
+
+
+
+# ---------------
+# User Interface 
+# ---------------
+
+itcl::body pxitclbrainregister::Initialize { basewidg } {
+
+    if { $initialized == 1 } { return $basewidget }
+
+    set basewidget [ toplevel $basewidg ]; 
+    wm geometry $basewidg 700x40+10+10
+
+    
+    
+    SetTitle "Brain Register"
+    set standalone 1
+
+
+    set menubase [ menu $basewidget.pxtclbrainreg -tearoff 0 ]
+    $basewidget configure -menu $menubase
+    set pbar     [ frame $basewidget.status -width 400 -height 30 ]
+    pack  $pbar -side bottom -fill x 
+ 
+    CreateProgressBar  $pbar
+
+    set orthoviewer(ref) [ [ pxitclbaseimageviewer \#auto 0 ]  GetThisPointer ]
+    $orthoviewer(ref) configure -enable_overlaytool 0 
+    $orthoviewer(ref) configure -appname "Reference Viewer"
+    $orthoviewer(ref) configure -show_standard_images 1
+    $orthoviewer(ref) configure -enable_talaraichoption 1
+    $orthoviewer(ref) configure -enable_vvlinkgadget $enable_vvlink 
+    $orthoviewer(ref) configure -enable_rendering_on_startup  $enable_rendering_on_startup  
+    $orthoviewer(ref) InitializeOrthogonalViewer $basewidget.[pxvtable::vnewobj] 0
+    [ $orthoviewer(ref) GetViewer ] SetEnableRendering 0
+
+    #    [ $orthoviewer(ref) cget -atlastool ] SetTitle "Ref Viewer Atlas Tool"
+
+    eval "$orthoviewer(ref) configure -mousecallback \"$this HandleMouseEvent \""
+    #eval "$orthoviewer(ref) configure -setnewimagecallback \"$this HandleNewImage\""
+    $orthoviewer(ref) ShowWindow
+
+    set orthoviewer(trn) [ [ pxitclbaseimageviewer \#auto 0 ]  GetThisPointer ]
+    $orthoviewer(trn) configure -show_standard_images 1
+    $orthoviewer(trn) configure -enable_overlaytool 0
+    $orthoviewer(trn) configure -appname "Transform Viewer"
+    $orthoviewer(trn) configure -enable_talaraichoption 1
+    $orthoviewer(trn) configure -enable_vvlinkgadget $enable_vvlink 
+    $orthoviewer(trn) configure -enable_rendering_on_startup  $enable_rendering_on_startup  
+    $orthoviewer(trn) SetAtlasTool [ $orthoviewer(ref) GetAtlasTool ]
+    $orthoviewer(trn) configure -enable_internaleditor 1
+    $orthoviewer(trn) configure -enable_objectmapmenu   1
+
+    $orthoviewer(trn) InitializeObjectmapViewer .[pxvtable::vnewobj] 0
+    [ $orthoviewer(trn) GetViewer ] SetEnableRendering 0
+    #    [ $orthoviewer(trn) cget -atlastool ] SetTitle "Ref Viewer Atlas Tool"
+    eval "$orthoviewer(trn) configure -mousecallback \"$this HandleMouseEvent \""
+    $orthoviewer(trn) ShowWindow
+
+    if { $enable_simpleviewer == 1 } {
+	set simpleviewer [ [ pxitclbaseimageviewer \#auto 0 ] GetThisPointer ]
+	$simpleviewer configure -appname "Simple Viewer"
+	$simpleviewer configure -show_standard_images 0
+	$simpleviewer configure -enable_multisubjectcontrol 0
+	$simpleviewer configure -enable_csigadget 0
+	$simpleviewer configure -enable_rendering_on_startup  1
+	$simpleviewer configure -enable_headercontrol  0
+	$simpleviewer configure -enable_importcontrol  0
+	$simpleviewer configure -enable_imageutility  0
+	$simpleviewer configure -enable_landmarkcontrol  0
+	$simpleviewer configure -enable_overlaytool  0
+	$simpleviewer configure -enable_histcontrol  0
+	$simpleviewer configure -enable_displaymenu  0
+	$simpleviewer configure -enable_brainstriptool  0
+	$simpleviewer configure -enable_helpmenu  0
+	$simpleviewer configure -enable_talaraichoption 1
+	$simpleviewer SetAtlasTool [ $orthoviewer(ref) GetAtlasTool ]
+	$simpleviewer InitializeMultipleMosaicViewer .[pxvtable::vnewobj ] 0
+
+    }
+
+    if { $enable_electrodecontrol == 1 } {
+	set electrode_control [ [ pxitclElectrodeMultiControl \#auto $this ]  GetThisPointer ]
+	$electrode_control SetNoMouseInput
+	$electrode_control Initialize $basewidget.[ pxvtable::vnewobj ] [ $orthoviewer(trn) GetViewer ]
+	$electrode_control HideWindow
+	$electrode_control ShowGrids none
+
+	if { $enable_electrodecontrol2 == 1 } {
+	    set electrode_control2 [ [ pxitclElectrodeMultiControl \#auto $this ]  GetThisPointer ]
+	    $electrode_control2 SetNoMouseInput
+	    $electrode_control2 Initialize $basewidget.[ pxvtable::vnewobj ] [ $orthoviewer(trn) GetViewer ]
+	    $electrode_control2 HideWindow
+	    $electrode_control2 SetTitle "Second Electrode Editor"
+	    $electrode_control2 ShowGrids none
+	}
+    }
+   
+    set overlaytool [ [ bis_guioverlayutility \#auto ] GetThisPointer ]
+    $overlaytool SetSecondContainerObject $orthoviewer(ref)
+    $overlaytool InitializeFromContainer $orthoviewer(trn)
+    $overlaytool CreateGUI $basewidget.[pxvtable::vnewobj ]
+    $orthoviewer(ref) AddControl $overlaytool
+    $orthoviewer(trn) AddControl $overlaytool
+
+    [ $orthoviewer(ref) GetLandmarkControl ] SetTitle "Reference Landmarks"
+    [ $orthoviewer(ref) GetPolyDataControl ] SetTitle "Reference Surfaces"
+    [ $orthoviewer(trn) GetLandmarkControl ] SetTitle "Transform Landmarks"
+    [ $orthoviewer(trn) GetPolyDataControl ] SetTitle "Transform Surfaces"
+
+
+
+    if { $enable_csigadget ==1 } {
+	set  csigadget [ [  pxitclcsigadget \#auto $orthoviewer(ref) $orthoviewer(trn) ] GetThisPointer ]
+	$csigadget Initialize $basewidget.[pxvtable::vnewobj ]
+	if { $electrode_control !=0 } {
+	    $csigadget configure -electrodetool $electrode_control
+	}
+    }
+
+
+    if { $enable_multigadget == 1 } {
+	set  multigadget [ [  pxitclmultisubjectaverage \#auto $orthoviewer(ref) $orthoviewer(trn) $overlaytool ] GetThisPointer ]
+	$multigadget Initialize $basewidget.[pxvtable::vnewobj ]
+		       
+	if { $enable_multi2gadget == 1 } {
+	    set  multi2gadget [ [  pxitclmultisubjectaverage \#auto $orthoviewer(ref) $orthoviewer(trn) $overlaytool ] GetThisPointer ]
+	    $multi2gadget Initialize $basewidget.[pxvtable::vnewobj ]
+	}
+    }
+
+    if { $enable_fmrigadget } {
+	set w [ toplevel $basewidget.[pxvtable::vnewobj ] ]; wm withdraw $w
+	set fmrigadget [  [ bis_fmri \#auto $w 0 $orthoviewer(trn) ] GetThisPointer ]
+	$fmrigadget SetMultiSubjectControl $multigadget 
+    }
+
+
+
+    if { $enable_rpmtool  == 1 } {
+	set rpmtool [ [ bis_guirpmcontainer \#auto  ] GetThisPointer ]
+	$rpmtool InitializeFromContainer $overlaytool
+	$rpmtool CreateGUI $basewidget.[pxvtable::vnewobj ]
+    }
+
+
+    if { $enable_manualtransformation  == 1 } {
+	set manualtransformationtool [ [ pxitclmanualtransformation \#auto $orthoviewer(ref) $orthoviewer(trn)  $overlaytool ] GetThisPointer ]
+	$manualtransformationtool Initialize $basewidget.[pxvtable::vnewobj ]
+	update idletasks
+    }
+
+    
+
+
+    if { $donotcreatemenu == 0 } {
+	CreateMenu   $menubase
+    }
+
+    update idletasks
+    PositionWindows
+    set initialized 1
+
+    eval "bind all <Control-d>  { $this ExitCommand }"
+    wm protocol . WM_DELETE_WINDOW pxtkexit 
+
+    return $basewidget
+
+}
+
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    wm withdraw .
+    set breg [ pxitclbrainregister \#auto 0 ]
+    $breg configure -enable_rendering_on_startup  0
+
+
+    $breg Initialize .[pxvtable::vnewobj ]
+    
+    set argc [llength $argv]; set ok 0
+    if { $argc > 0 } {  set ok [ $breg LoadImage [lindex $argv 0]  "ref" ] }
+    if { $argc > 1 } {  set ok [ $breg LoadImage [lindex $argv 1]  "trn" ] }
+    if { $argc > 2 } {  
+	[ $breg cget -overlaytool ] LoadAndAddTransformation [ lindex $argv 2 ]
+    } 
+    if { $argc > 3 } {
+	set ok [ [ [ $breg GetOrthoViewer ref ] GetPolyDataControl ] LoadSurface [lindex $argv 3] ]
+    }
+    if { $argc > 4 } {
+	set ok [ [ [ $breg GetOrthoViewer trn ] GetPolyDataControl ] LoadSurface [lindex $argv 4] ]
+    }
+
+
+    [ [ $breg GetOrthoViewer ref ] GetViewer ] SetEnableRendering 1
+    [ [ $breg GetOrthoViewer trn ] GetViewer ] SetEnableRendering 1
+    [ [ $breg GetOrthoViewer trn ] GetViewer ] UpdateDisplay
+    [ [ $breg GetOrthoViewer ref ] GetViewer ] UpdateDisplay
+
+
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclbrainsegment.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclbrainsegment.tcl
new file mode 100755
index 0000000..483bbd2
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclbrainsegment.tcl
@@ -0,0 +1,86 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclbrainsegment.tcl,v 1.2 2004/12/16 16:10:43 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package require vtkpxcontrib  1.1
+package require pxtcluserprefs 
+#package require vtkmpjcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+#package require mpjdiffusionutility 1.0
+
+wm withdraw .
+set bsegm [ pxitclbaseimageviewer \#auto 0 ]
+$bsegm configure -appname "BioImage Suite::Brain Segment"
+$bsegm configure -show_standard_images 1
+$bsegm configure -enable_multisubjectcontrol 0
+$bsegm configure -enable_overlaytool 0
+$bsegm configure -enable_vvlinkgadget  1
+$bsegm configure -enable_talaraichoption 1
+$bsegm configure -enable_rendering_on_startup  0
+$bsegm configure -enable_internaleditor 1
+$bsegm configure -enable_objectmapmenu   1
+$bsegm InitializeObjectmapViewer .[pxvtable::vnewobj ] 1
+
+$bsegm ShowWindow   
+
+set argc [llength $argv]
+
+if { $argc > 0 } {   $bsegm LoadImage [lindex $argv 0]   }
+
+
+update idletasks
+[ $bsegm GetViewer ] SetEnableRendering 1
+
+
+#set ed [ [ $bsegm GetViewer ] GetInternalEditor ]
+#if { $ed != "" } {
+#    $ed SetVOISelectMode 254 259 1#
+#
+#    set lst [ list Black Red Green Blue ]##
+#
+#    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+#	$ed SetVOIName $i [ lindex $lst $i ]
+#    }
+#}
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclbrainstrip.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclbrainstrip.tcl
new file mode 100644
index 0000000..97ca854
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclbrainstrip.tcl
@@ -0,0 +1,2891 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclbrainstrip 1.1
+
+# 	$Id: pxitclbrainstrip.tcl,v 1.1 2005/10/18 21:25:14 xenios Exp xenios $	
+
+
+
+
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxvtable   1.0
+package require  pxtclhelp  1.0
+#package require  notebook   1.0
+package require  pxtclruncommand 1.0
+package require vtkpxcontrib  1.1
+package require pxitclbaseimagecontrol   1.0
+package require pxitclLandmarkControl    1.0
+package require pxitclPolyDataControl    1.0
+
+itcl::class pxitclbrainstrip {
+
+    # Base Class
+    inherit pxitclbaseimagecontrol 
+
+    protected common thisparam
+    protected variable levelsetimagecontrol
+    protected variable landmarkcontrol 0
+    protected variable polydatacontrol 0
+    protected variable curve_extractor 0
+    protected variable brain_util      0
+    protected variable currentmask 0
+    protected variable oldmask 0
+    protected variable runcommandgui 0
+    protected variable vtk_viewer 0
+
+    public variable enable_fsl            1
+    public variable enable_duallevelset   0
+    public variable enable_singlelevelset 1
+    public variable enable_mousemode      0
+
+    protected variable has_duallevelset   0
+    protected variable has_singlelevelset 0
+    protected variable has_mousemode      0
+
+
+    constructor { par } {
+	::pxitclbaseimagecontrol::constructor $par
+    } {
+	InitializeBrainStrip
+    }
+
+    # Initialize and Set Up
+    public method InitializeBrainStrip { } 
+    public method SetPolyDataAndLandmarkControls { landmarkcontrol polydatacontrol }
+    public method Initialize { inpwidg vtk_viewer }
+    public method DelayedInitialize {  }
+    public method DisableLevelSets { } 
+    # ----------------
+    # Create GUI Stuff
+    # ----------------
+    public method CreateSimpleControl { parent } 
+    public method CreateBETTool       { parent } 
+    public method CreateFASTTool       { parent } 
+    public method CreateLevelsetControl { parent } 
+    public method CreateHistogramSegmentationControl { parent }
+    public method CreateBiasFieldCorrectionControl { parent }
+
+    # ------------------------------
+    # OOP Override
+    # ------------------------------
+    public    method SetImage { img } 
+    
+    # ----------------------------
+    # Real Code
+    # ----------------------------
+    public method Help { } 
+    public method ProcessImageResults { mode } 
+
+    public method RunSingleLevelSet { mode } 
+
+    public method UpdateFromLevelSet { args } 
+
+    public method HistogramSegmentation { }
+    public method MRFSegmentation { }
+    public method DisplayHistogramParameters { }
+    public method GenerateMaskFromSegmentedOutput { mode } 
+    
+    public method RunManualShim {  }
+    public method RunSplinePabic { }
+    public method RunPolynomialPabic { }
+    public method ClearPolynomial { }
+    public method PrintPolynomial { { fileid 0} }
+    public method LoadPolynomial { }
+    public method SavePolynomial { }
+
+    public method RunSliceHomogeneity   { }
+    public method RunTripleSliceHomogeneity   { }
+    public method RunImageApproximation { }
+    public method ApplyB1Field { args }
+    public method GrabMorphologyMask { arg1 arg2 }
+    public method SetMorphologyMask { arg1 arg2 }
+    public method SetMorphologyMaskImage { img }
+
+
+
+    # -----------------------------
+    # Morphology Operations
+    # -----------------------------
+    public method CheckImage {  image name operation verbosity } 
+    public method ThresholdImage { }
+    public method SimpleSegment { }
+    public method ErodeMap { } 
+    public method DilateMap { } 
+    public method DilateErodeMap {  posval minval  } 
+    public method BinaryMedianMap {  } 
+    public method ConnectMap { mode }
+    public method UndoLastMorphologyOperation { }
+    public method RequestUpdatedSeed { { force 1  }  } 
+    public method ProcessMorphologyResults { filteroutput args } 
+    public method DisplayMorphologyResults {  } 
+
+
+    # -----------------------------
+    # BET Operations
+    # -----------------------------
+    public method EnsureCurrentImageIsSaved { operation }
+    public method GenerateMaskFromBETOutput { mode }
+
+    public method RunBET { do }
+    public method BETDone { }
+    public method FixOriginSpacingOrientation { newimg }
+
+    # -----------------------------
+    # FAST Operations
+    # -----------------------------
+    public method RunFAST { do }
+    public method FASTDone { }
+    public method FASTStatistics { mode }
+    public method FASTNormalizeBrain { }
+    
+
+    # ----------------------------
+    public method AddToMenuButton { mb args } 
+}
+
+# ----------------------------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::DisableLevelSets {  } {
+
+    if { $initialized == 1 } { return 0 } 
+
+    set enable_singlelevelset 0
+    set enable_duallevelset   0
+}
+
+
+itcl::body pxitclbrainstrip::InitializeBrainStrip {  } {
+
+    set thisparam($this,helpdialog) ""
+    set currentmask   [[ pxitclimage \#auto ] GetThisPointer ]
+    set oldmask [[ pxitclimage \#auto ] GetThisPointer ]
+
+    set polydatacontrol  0
+    set landmarkcontrol  0
+
+    AddImagesToLists  $currentmask $oldmask
+
+    set thisparam($this,currentsurface) 1
+    
+    # Single Levelset Parameters
+    # ------------------------------------------------------------
+    set thisparam($this,sn_inmean)  100
+    set thisparam($this,sn_outmean) 0
+    set thisparam($this,sn_outmean2) 0
+    set thisparam($this,sn_insigma)   20
+    set thisparam($this,sn_outsigma)   20
+    set thisparam($this,sn_outsigma2)   20
+    set thisparam($this,sn_biexpoutside) 0
+    set thisparam($this,sn_numiter) "200"
+    set thisparam($this,sn_updateper) "0.1"
+    set thisparam($this,sn_distance) 3.0
+    set thisparam($this,sn_advection)   0.0
+    set thisparam($this,sn_curvature)   0.2
+    set thisparam($this,sn_propagation)  1.0
+    set thisparam($this,sn_conv)     0.02
+    set thisparam($this,sn_updateparams) 0
+    set thisparam($this,sn_beginlevel)   2
+    set thisparam($this,sn_endlevel)    1
+
+    # ------------------------------------------------------------
+    # Extract Image Smooth and Resample Parameters
+    # ------------------------------------------------------------
+    set thisparam($this,extr_sigma) 1.0
+    set thisparam($this,extr_res)   2.0
+    set thisparam($this,extr_do)     0
+
+    # ------------------------------------------------------------
+    # Morphology Parameters
+    # ------------------------------------------------------------
+    set thisparam($this,lowthreshold) 0; set thisparam($this,highthreshold) 100;
+    set thisparam($this,seedx)        0; set thisparam($this,seedy)           0; set thisparam($this,seedz) 0
+    set thisparam($this,seedautoupdate) 1;
+    set thisparam($this,gui_lowthreshold) 0; 
+    set thisparam($this,gui_highthreshold) 0; 
+    set thisparam($this,gui_morphkernelsize) 3 ; 
+    set thisparam($this,gui_displaymask) 1
+    set thisparam($this,gui_morphology2d) 0
+    # ------------------------------------------------------------
+    # BET Parameters
+    # ------------------------------------------------------------
+    set thisparam($this,bet_fth) 0.3
+    set thisparam($this,bet_gth) 0.0
+    set thisparam($this,bet_center) 0
+    set thisparam($this,bet_radius) -1.0
+    set thisparam($this,bet_braingui) 0
+    set thisparam($this,bet_overlaygui) 0
+    set thisparam($this,bet_outputroot) 0
+
+    # ------------------------------------------------------------
+    # FAST Parameters
+    # ------------------------------------------------------------
+    set thisparam($this,fast_type) "T1-Weighted"
+    set thisparam($this,fast_numclasses) "3"
+    
+    set thisparam($this,fast_segmentedimagegui) 0
+    set thisparam($this,fast_outputroot) 0
+
+    set thisparam($this,fslbet)  ""
+    set thisparam($this,fslfast) ""
+
+
+    # ------------------------------------------------------------
+    # Histogram Segmentation Parameters
+    # ------------------------------------------------------------
+    set thisparam($this,histo_numclasses) 3
+    set thisparam($this,histo_outlier) 0
+    set thisparam($this,histo_premode) "Positive"
+    set thisparam($this,histo_distmode) "Gaussian"
+    set thisparam($this,histo_outlierprobability) 0.0001
+    set thisparam($this,histo_sigmaratio) 0.2
+    set thisparam($this,histo_frame) 1
+    set thisparam($this,histo_numbins) 256
+    set thisparam($this,histo_sigma) 0.05
+    set thisparam($this,histo_iterations) 50
+    set thisparam($this,histo_epsilon) 0.05
+    set thisparam($this,histo_robustscalefactor) 4.0
+    set thisparam($this,histo_params) [ vtkFloatArray [ pxvtable::vnewobj ]]
+    set thisparam($this,histo_details) "No parameters in memory"
+
+    set thisparam($this,histo_mean1) 1
+    set thisparam($this,histo_mean2) 2
+    set thisparam($this,histo_mean3) 3
+    set thisparam($this,histo_mean4) 4
+    set thisparam($this,histo_mean5) 5
+    set thisparam($this,histo_mean6) 6
+    set thisparam($this,histo_mean7) 7
+    set thisparam($this,histo_vsigma) 200
+    set thisparam($this,histo_useinitial) 0
+
+
+
+    set thisparam($this,mrf_iterations)   20
+    set thisparam($this,mrf_smoothness)   1.0
+    set thisparam($this,mrf_histonorm)    0
+    set thisparam($this,mrf_convergence)  0.25
+    set thisparam($this,mrf_fuzzy)        0
+    set thisparam($this,mrf_dobiasfield)    0
+    set thisparam($this,mrf_biasfieldsigma) 5.0
+    set thisparam($this,mrf_singlechannel) 1
+    set thisparam($this,mrf_imagenoise)  15
+
+    set thisparam($this,segm_useclass1)   0
+    set thisparam($this,segm_useclass2)   1
+    set thisparam($this,segm_useclass3)   1
+    set thisparam($this,segm_useclass4)   0
+    set thisparam($this,segm_useclass5)   0
+    set thisparam($this,segm_useclass6)   0
+    set thisparam($this,segm_useclass7)   0
+
+    set thisparam($this,segmoutput_gui) 0
+    
+    # ------------------------------------------------------------
+    #   PABIC Bias Field Correction 
+    # ------------------------------------------------------------
+    set thisparam($this,pabic_maskgui)      0
+    set thisparam($this,pabic_restoredgui)  0
+    set thisparam($this,pabic_biasfieldgui) 0
+
+    set thisparam($this,pabic_slice_usemask)     0
+    set thisparam($this,pabic_slice_robust)      1
+    set thisparam($this,pabic_slice_purescaling) 0
+    set thisparam($this,pabic_optmethod) "ConjugateGradient"
+
+    set thisparam($this,pabic_usemask)          0
+    set thisparam($this,pabic_usefatmask)       1
+    set thisparam($this,pabic_slicecorrection)  0
+    set thisparam($this,pabic_multiplicative)   1
+    set thisparam($this,pabic_sample)           3
+    set thisparam($this,pabic_iterations)      10
+
+    set thisparam($this,pabic_spl_metric)       0
+    set thisparam($this,pabic_spl_spacing)   30.0
+    set thisparam($this,pabic_spl_lambda)     1.0
+    set thisparam($this,pabic_spl_presmooth)    8
+    set thisparam($this,pabic_spl_stepsize)   5.0
+    set thisparam($this,pabic_spl_fatmaskweight) 2
+
+
+    # ---------------- Shim Algorithm ---------------
+    # ----------------------------------------------
+    set thisparam($this,pabic_shim_degree)   2
+    set thisparam($this,pabic_shim_useinitial) 0
+    set thisparam($this,pabic_shim_updatesegm) 0
+    set thisparam($this,pabic_shim_metric) 0
+    # Hidden Variables (advanced)
+    for { set i 0 } { $i <=18 } { incr i } {
+	set thisparam($this,pabic_shimval_$i) 0.0
+    }
+
+    set thisparam($this,pabic_shim_stepsize)   0.05
+    set thisparam($this,pabic_shim_numsteps)   1
+    set thisparam($this,pabic_shim_numlevels)  1
+    set thisparam($this,pabic_shim_resolution) 3
+    set thisparam($this,pabic_shim_iterations) 10
+    set thisparam($this,pabic_shim_usemask)    1
+    set thisparam($this,pabic_min) 0.2
+    set thisparam($this,pabic_max) 5.0
+    
+    # ------------------------------------------------------------
+
+    global tcl_platform
+
+    set gm 0
+    set g [ vtkpxTissueLevelSetFilter  [ pxvtable::vnewobj ]]    
+    set gm 1
+    $g Delete
+
+
+    if { $gm == 0 } {
+	set enable_singlelevelset 0
+    }
+
+    set enable_duallevelset 0
+    set brain_util 0
+
+    if { $enable_singlelevelset == 1 } {
+	set has_singlelevelset 1
+    }
+}
+
+
+# -------------------------------------------------------------------------------
+
+itcl::body pxitclbrainstrip::SetPolyDataAndLandmarkControls { landmarkc polydatac } {
+
+    set polydatacontrol  $landmarkc
+    set landmarkcontrol $polydatac
+}
+
+
+# -------------------------------------------------------------------------------
+
+itcl::body pxitclbrainstrip::Initialize { inpwidg viewer } {
+
+    global tcl_platform
+
+    if { $initialized == 1 } { return $basewidget } 
+
+    if { $enable_fsl == 1 } {
+	
+	if { $tcl_platform(platform) == "windows"} {
+	    if {  [ ::pxtclutil::FindCommandInPath bet.exe ] !=0  } {
+		set thisparam($this,fslbet)  "bet.exe"
+		set thisparam($this,fslfast) ""
+	    } elseif {  [ ::pxtclutil::FindCommandInPath bet2.exe ] !=0  } {
+		set thisparam($this,fslbet)  "bet2.exe"
+		set thisparam($this,fslfast) "bash -l -e fast"
+	    } elseif {  [ ::pxtclutil::FindCommandInPath bet2.exe ] !=0  } {
+		set thisparam($this,fslbet)  "bet.exe"
+		set thisparam($this,fslfast) "bash -l -e fast"
+	    }
+	} else {
+	    if { ( [ ::pxtclutil::FindCommandInPath fast_bis ] !=0 ) &&
+		 ( [ ::pxtclutil::FindCommandInPath bet2_bis ] !=0 ) } {
+		set thisparam($this,fslbet)  bet2_bis
+		set thisparam($this,fslfast) fast_bis
+	    } elseif { ( [ ::pxtclutil::FindCommandInPath fast ] !=0 ) &&
+		       ( [ ::pxtclutil::FindCommandInPath bet2 ] !=0 ) } {
+		set thisparam($this,fslbet)  bet2
+		set thisparam($this,fslfast) fast
+	    } elseif { ( [ ::pxtclutil::FindCommandInPath fast ] !=0 ) &&
+		       ( [ ::pxtclutil::FindCommandInPath bet ] !=0 ) } {
+		set thisparam($this,fslbet) bet
+		set thisparam($this,fslfast) fast
+	    }
+	}
+    }
+
+    #    puts stderr "BET = $thisparam($this,fslbet), FAST = $thisparam($this,fslfast)"
+
+    set vtk_viewer $viewer
+    set basewidget $inpwidg
+    toplevel $basewidget ; wm geometry $basewidget 700x550; wm withdraw $basewidget
+
+
+    SetTitle "Segmentation Control"
+    set initialized 1
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget
+}
+
+itcl::body pxitclbrainstrip::DelayedInitialize {  } {
+
+    global pxtcl_pref_array
+
+    if { $fullyinitialized == 1 } {
+	return
+    }
+
+    set notebook $basewidget.notebook
+    iwidgets::tabnotebook $notebook -width 5i -height 3i -tabpos w
+
+    CreateSimpleControl        [ $notebook add -label "Math_Morphology" ]
+    CreateHistogramSegmentationControl        [ $notebook add -label "Histogram Segmentation" ]
+    CreateBiasFieldCorrectionControl          [ $notebook add -label "Bias Field Correction" ]
+
+    if {  $thisparam($this,fslbet) !=  "" || $thisparam($this,fslfast) != "" } {
+	set  runcommandgui [  [ pxtclruncommand \#auto ] GetThisPointer ]
+	$runcommandgui Initialize $basewidget.runcommandgui 0 0
+	$runcommandgui Hide
+	if { $thisparam($this,fslbet) !=  "" } {
+	    CreateBETTool              [ $notebook add -label "Brain Extraction Tool"    ]
+	} 
+	if { $thisparam($this,fslfast) !=  "" } {
+	    CreateFASTTool              [ $notebook add -label "Gray/White Segmentation" ]
+	}
+    }
+
+    if { $enable_singlelevelset  == 1 } {
+	CreateLevelsetControl [ $notebook add -label "Levelset Segmentation" ]
+    }
+	
+
+    set canvas [ [ $notebook component tabset ] component canvas ];     set l [ AddLogoLabel $canvas ];     pack $l -side bottom -padx 1 
+    set w  [ frame $basewidget.buttonbar  ]
+    pack $w -side bottom -fill x -expand f
+    pack $notebook -side top -fill both -expand true
+
+    if { $parent != 0 } {
+	eval "button $w.l1  -text \"Copy Results To Image\" -command { $parent CopyResultsToImage }"
+	eval "button $w.l2  -text \"Undo Copy Results\" -command { $parent RevertToPreviousImage }"
+	pack $w.l1 $w.l2 -side left -padx 5
+    }
+
+    eval "button $w.close   -text Close -command { $this HideWindow } "
+    pack  $w.close -side right -fill x -padx 5 -pady 5 -expand f
+    set fullyinitialized 1
+}
+
+# ------------------------------------------------------------------------------------------------
+#    Create GUI Stuff 
+# ------------------------------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::CreateLevelsetControl { par } {
+    
+    set levelsetimagecontrol [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $levelsetimagecontrol configure -description "Level Set Image"
+    $levelsetimagecontrol InitializeLite $par.lvlimg 2
+    $levelsetimagecontrol AddFunction "$parent SetResultsFromObject" "Display" "$this"
+    pack $par.lvlimg -side bottom -expand false -fill x -pady 5
+
+    label $par.o -bg black -fg white -text "Using Current Image And Current Landmark Collection."
+    set w [ frame $par.o3 ]
+    pack $par.o  $par.o3 -side top -expand f -fill x -padx 1 -pady 0
+    
+    label $w.lab  -text "To Generate Seeds Use:" -bg darkgrey
+    eval "button $w.land  -text \"Landmark Control\" -command { $landmarkcontrol Show 1}"
+    pack $w.lab $w.land -side left -fill x -padx 2 -expand t -pady 2
+    
+    set w [LabelFrame:create $par.t -text "Tissue Description" -expand false -fill x ]
+    set w2 [LabelFrame:create $par.ta -text "Levelset Weights" -expand false -fill x ]
+    set w3 [LabelFrame:create $par.tb -text "Optimization Parameters" -expand false -fill x ]
+    set w4 [LabelFrame:create $par.sur -text "Output Surface Destination" -expand false -fill x ]
+
+    set butbar [ frame $par.but ]
+
+    # ------------------------- Tissue description -------------------------
+
+    pack $par.t $par.ta $par.tb $par.sur $butbar -side top -expand f -fill x -padx 2 -pady 1
+
+    frame $w.t; frame $w.t2 ; frame $w.t25; frame $w.t3
+
+    pack $w.t $w.t2 $w.t25 $w.t3 -side top -expand false -fill x
+
+    iwidgets::entryfield $w.t.1 -labeltext "Inside  Mean/Sigma:" -textvariable [ itcl::scope thisparam($this,sn_inmean) ] -relief sunken -width 6 -validate real 
+    iwidgets::entryfield $w.t.2 -labeltext "" -textvariable [ itcl::scope thisparam($this,sn_insigma) ] -relief sunken -width 6 -validate real
+
+    pack $w.t.1 $w.t.2  -side left -expand f -padx 2 -fill x
+    
+    iwidgets::entryfield $w.t2.1 -labeltext "Outside Mean/Sigma:" -textvariable [ itcl::scope thisparam($this,sn_outmean) ] -relief sunken -width 6 -validate real
+    iwidgets::entryfield $w.t2.2 -labeltext "" -textvariable [ itcl::scope thisparam($this,sn_outsigma) ] -relief sunken -width 6 -validate real
+
+    pack $w.t2.1  $w.t2.2 -side left -expand f -padx 2 -fill x
+
+    
+    iwidgets::entryfield $w.t2.11 -labeltext "Outside (2) Mean/Sigma:" -textvariable [ itcl::scope thisparam($this,sn_outmean2) ] -relief sunken -width 6 -validate real
+    iwidgets::entryfield $w.t2.12 -labeltext "" -textvariable [ itcl::scope thisparam($this,sn_outsigma2) ] -relief sunken -width 6 -validate real
+    pack $w.t2.11 $w.t2.12 -side left -expand f -padx 2 -fill x
+
+    checkbutton $w.t3.1 -text "Bi-exponential Outside" -variable [ itcl::scope thisparam($this,sn_biexpoutside) ]
+    checkbutton $w.t3.2 -variable [ itcl::scope thisparam($this,sn_updateparams) ] -text "Dynamicly Update Parameters"
+    pack $w.t3.1 $w.t3.2  -side left -expand f -padx 2 -fill x
+
+
+    # ------------------------------------------------------------------------- ----------------------
+    # Optimization
+    # ------------------------------------------------------------------------------------------------
+
+    set top [ frame $w3.1 ];     set bot [ frame $w3.2 ]; pack $top $bot -side top -expand f -fill x
+
+    label $top.1 -text "Levels:"
+    tk_optionMenu $top.2  [ itcl::scope thisparam($this,sn_beginlevel) ]  1 2 3 4
+    tk_optionMenu $top.2a [ itcl::scope thisparam($this,sn_endlevel) ]  1 2 3 4
+
+    label $top.3 -text "Initial Radius:"
+    tk_optionMenu $top.4 [ itcl::scope thisparam($this,sn_distance) ]  "1.0" "2.0" "3.0" "4.0" "5.0" "8.0" "12.0" "15.0" "20.0"
+    pack  $top.1 $top.2 $top.2a $top.3 $top.4 -side left -padx 2 -expand f -fill x
+  
+    label $bot.1 -text "Iterations:"
+    tk_optionMenu $bot.2 [ itcl::scope thisparam($this,sn_numiter) ]  "2" "20" "50" "100" "200" "400" "800" "1000" "2000"
+    label $bot.3 -text "Error:"
+    tk_optionMenu $bot.4 [ itcl::scope thisparam($this,sn_conv) ]  "0.0" "0.01" "0.1" "0.02" "0.05" "0.1"
+    label $bot.5 -text "Upd::"
+    tk_optionMenu $bot.6 [ itcl::scope thisparam($this,sn_updateper) ]  "0.05" "0.1" "0.2" "0.33" "0.5" "1.01"
+    pack $bot.1 $bot.2 $bot.3 $bot.4 $bot.5 $bot.6 -side left -expand f -padx 1 -fill x
+
+    # ------------------------------------------------------------------------- ----------------------
+    # Levelset Weights
+    # ------------------------------------------------------------------------------------------------
+    label $w2.1 -text "Propagtion"
+    tk_optionMenu $w2.2 [ itcl::scope thisparam($this,sn_propagation) ] "0.0" "0.01" "0.02" "0.05" "0.1" "0.25" "0.5" "1.0" "2.0" 
+    label $w2.3 -text "Smoothness"
+    tk_optionMenu $w2.4 [ itcl::scope thisparam($this,sn_curvature) ] "0.0" "0.01" "0.02" "0.05" "0.1" "0.25" "0.5" "1.0" "2.0" 
+    label $w2.5 -text "Advection"
+    tk_optionMenu $w2.6 [ itcl::scope thisparam($this,sn_advection) ] "0.0" "0.01" "0.02" "0.05" "0.1" "0.25" "0.5" "1.0" "2.0" 
+    pack $w2.1 $w2.2 $w2.3 $w2.4 $w2.5 $w2.6 -side left -expand f -padx 5 -fill x
+
+
+    label $w4.a -text "Outer Surface: "
+    set menu1 [ tk_optionMenu $w4.b [ itcl::scope thisparam($this,currentsurface) ] 1  ]
+
+    set num 2; catch { set num [ $polydatacontrol  GetNumberOfSurfaces ]  }
+    for { set k 2 } { $k <= $num } { incr k } {
+	$menu1 add radio -label "$k" -variable [ itcl::scope thisparam($this,currentsurface) ]
+    }
+    
+    eval "button $w4.sc  -text \"Show Surface Control\" -command { $polydatacontrol Show 1}"
+    pack $w4.sc -side right -padx 2
+    pack $w4.a $w4.b   -side left -fill x -padx 10    
+    
+    eval "button $butbar.1 -text \"Run Single Levelset\" -command { $this RunSingleLevelSet 0 }"
+    eval "button $butbar.2 -text \"Continue Current\" -command { $this RunSingleLevelSet 1 }"
+    eval "button $butbar.3 -text \"Fast March\" -command { $this RunSingleLevelSet -1 }"
+    pack $butbar.1 $butbar.2 $butbar.3 -side left -expand t -padx 10 -fill x -pady 10
+
+
+
+}
+# --------------------------------------------------------
+#    Help
+# --------------------------------------------------------
+
+itcl::body pxitclbrainstrip::Help { } {
+
+    if { [ string length $thisparam($this,helpdialog) ] > 2 } { 
+	::pxtclutil::ShowWindow $thisparam($this,helpdialog)
+	return
+    }
+    
+    set w .
+    if { [ string length $basewidget ] > 2 } { set w $basewidget }
+    
+    set thisparam($this,helpdialog)  [ toplevel $w.helpdialog ]
+    
+    ::pxtclhelp::HelpDialog $thisparam($this,helpdialog)
+    wm title $thisparam($this,helpdialog) "Help on Extracting Curves"
+    
+    set line "To extract sulcal curves the following are needed:\n\n"
+    set line "$line \t 1. The outer brain surface with curvature information.\n"
+    set line "$line \t 2. Two initial points at either end of the curve\n\n"
+    set line "$line \t The outer brain surface is obtained from the surface control, and it is the surface specified by the \"outer brain surface\" option menu in the surfaces pane. The two initial points are the last two points of the current point set in the landmark control.\n\n"
+    set line "$line \t The final output is stored in the clipboard of the surface control. To see/access the curve, first select an unused surface in the surface control and then click on Edit/Paste on the surface control menu.\n\n"
+    ::pxtclhelp::HelpDialogAddText $thisparam($this,helpdialog) $line
+    
+    
+    set line "To extract sulcal ribbons the following are needed:\n\n"
+    set line "$line \t 1. The outer   brain surface with curvature information.\n"
+    set line "$line \t 2. The wrapper brain surface with curvature information.\n"
+    set line "$line \t3. Two initial points at either end of the curve\n"
+    set line "$line \t4. The levelset outer distance function as produced by brainstrip\n\n"
+    set line "$line \tThe outer brain surface and the outer wrapper surface are obtained from the surface control, and are the surfaces specified by the \"outer brain surface\" and \"wrapper brain surface\" option menus respectively, in the surfaces pane. The two initial points are the last two points of the current point set in the landmark control. The levelset outer distance function must be loaded using the \"Load\" button in the \"Levelset Distance Image\" pane.\n\n"
+    set line "$line \tThe final output is stored in the clipboard of the surface control. To see/access the ribbon, first select an unused surface in the surface control and then click on Edit/Paste on the surface control menu.\n\n"
+    ::pxtclhelp::HelpDialogAddText $thisparam($this,helpdialog) $line
+    
+    $thisparam($this,helpdialog) configure -width 650	
+    ::pxtclutil::ShowWindow $thisparam($this,helpdialog)
+}
+
+# --------------------------------------------------------
+#   Generate Output Images 
+# --------------------------------------------------------
+itcl::body pxitclbrainstrip::ProcessImageResults { mode } {
+    
+    $currentresults configure -filename    [ AddPrefix [ $currentimage cget -filename  ] $mode ]
+    $currentresults CopyImageHeader [ $currentimage GetImageHeader ]
+    $parent SetResultsFromObject $currentresults $this
+}
+
+
+# ----------------------------------------------------------------------------
+# Single Levelset Options
+# ----------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::UpdateFromLevelSet { args } {
+
+    set current_levelset [ lindex $args 0 ]
+            
+    pxtkprint "[ $current_levelset GetOutputStatus ]\n"
+
+    
+    set pd [ vtkImageData New ] 
+    $pd ShallowCopy [  $current_levelset GetOutput ] 
+
+    set skinExtractor [ vtkContourFilter [ pxvtable::vnewobj ] ]
+    $skinExtractor SetUseScalarTree 0
+    $skinExtractor ComputeScalarsOff
+    $skinExtractor ComputeGradientsOff
+    $skinExtractor SetInput $pd
+    $skinExtractor SetValue 0 0.0
+    $skinExtractor Update
+    $pd Delete
+    
+
+    set surnum [ expr $thisparam($this,currentsurface) - 1 ]
+    $polydatacontrol  SetSurface $surnum [ $skinExtractor GetOutput ] "levelset"
+
+    $vtk_viewer UpdateDisplay
+    $skinExtractor Delete
+
+    $this ProgressCallback  $current_levelset "Running levelset" 
+    update idletasks
+
+}
+# ----------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::RunSingleLevelSet { mode } {
+
+    if {  [$currentimage GetImageSize ]  < 2 } {
+	::pxtclutil::Warning "No Image In Memory! Cannot Segment!"
+	return 0 
+    }
+    
+    set nm "out" 
+
+    set usepoints 1
+
+    if { $mode == 1 } {
+
+	set outimage [ $levelsetimagecontrol GetObject ]
+	set dim1 [ $outimage      GetImageSize ]
+	set dim2 [ $currentimage  GetImageSize ]
+	if { $dim1 == $dim2 } {
+	    set usepoints 0
+	}
+    }
+
+    if { $usepoints == 1 } {
+	set temp [ [ $landmarkcontrol GetCollection -1 ] GetNumPoints ] 
+	if { $temp< 1 } {
+	    ::pxtclutil::Warning "Current point set on landmark control must have at least 1 seed point to initialize the segmentation!"
+	    return 0
+	}
+    }
+    
+    set baseCurve [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    $baseCurve Copy [ $landmarkcontrol GetCollection -1 ] 
+    $baseCurve SetSpacing 1.0 1.0 1.0
+    $baseCurve SetOrigin 0.0 0.0 0.0
+    $baseCurve Compact
+
+    set tmp [ vtkImageData [ pxvtable::vnewobj ]]
+
+    WatchOn 
+    after 100
+    update idletasks
+
+    set outimage [ $levelsetimagecontrol GetObject ]
+
+    if { $mode == -1 } {
+
+	set lv [ vtkpxLevelSetUtil [ pxvtable::vnewobj ]]
+	set img [ $lv GenerateInputLevelSet [ $currentimage GetImage ] [ $baseCurve GetPoints ] $thisparam($this,sn_distance)  1.0 ]
+	$outimage ShallowCopyImage $img
+	$img Delete
+    } else {
+	set g [ vtkpxTissueLevelSetFilter  [ pxvtable::vnewobj ]]
+	$g SetInput [ $currentimage GetImage ]
+	if { $usepoints == 1 } {
+	    $g SetInitialPoints [ $baseCurve GetPoints ]
+	    $g SetInitialDistance  $thisparam($this,sn_distance) 
+	} else {
+	    $tmp ShallowCopy [ $outimage GetImage ]
+	    $g SetInitialLevelSet $tmp
+	}
+	
+	$g SetBeginLevel $thisparam($this,sn_beginlevel)
+	$g SetEndLevel $thisparam($this,sn_endlevel)
+	$g SetOutsideMean $thisparam($this,sn_outmean)
+	$g SetOutsideSigma $thisparam($this,sn_outsigma)
+	$g SetInsideMean $thisparam($this,sn_inmean)
+	$g SetInsideSigma $thisparam($this,sn_insigma)
+	$g SetBiExponentialOutside $thisparam($this,sn_biexpoutside)
+	$g SetOutside2Mean $thisparam($this,sn_outmean2)
+	$g SetOutside2Sigma $thisparam($this,sn_outsigma2)
+	
+	$g SetLevelsetIterations $thisparam($this,sn_numiter)
+	$g SetDynamicParameterUpdate $thisparam($this,sn_updateparams)
+	$g SetIterationSave 0
+	$g SetRMSError $thisparam($this,sn_conv)
+	$g SetAdvectionWeight $thisparam($this,sn_advection)
+	$g SetCurvatureWeight  $thisparam($this,sn_curvature)
+	$g SetPropagationWeight $thisparam($this,sn_propagation)
+	$g SetUpdatePercentage $thisparam($this,sn_updateper)
+	
+	if { $thisparam($this,sn_numiter) < 100 } {
+	    if { $thisparam($this,sn_updateper) < 0.5 } {
+		$g SetUpdatePercentage 0.5
+	    }
+	}
+	
+	pxtkconsole
+	update idletasks
+	pxtkprint [ $g GetOutputStatus ]
+	eval "$g AddObserver ProgressEvent { $this UpdateFromLevelSet $g }"
+	eval "$g AddObserver EndEvent      { $this UpdateFromLevelSet $g }"
+	$g Update
+
+
+
+	$outimage ShallowCopyImage  [ $g GetOutput ] 
+	$g Delete
+    }  
+    
+    $outimage CopyImageHeader [ $currentimage GetImageHeader ]
+    $levelsetimagecontrol Update
+    $baseCurve Delete
+    
+    $tmp Delete
+
+    if { $mode == - 1 } {
+	$currentresults ShallowCopyImage $outimage
+	ProcessImageResults  "Levelset" 
+    }
+    WatchOff
+}
+
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::CreateBETTool { base } {
+
+    set a $thisparam($this,fslbet) 
+    label $base.o1 -bg black -fg white -text "Brain Extraction Tool  (FSL)"
+    label $base.o2 -bg black -fg white -text "From FMRIB Analysis Group, Oxford (cmdline=$a)"
+    label $base.o3 -bg black -fg white -text "(This calls the FSL $a program as an external process)"
+
+    pack $base.o1 $base.o2 $base.o3  -side top -fill x -expand f -padx 1 -pady 0
+
+#    set   thresholdbar [ LabelFrame:create $base.bar2  -width 300  -text "Parameters" ]
+    set   thresholdbar [ frame $base.bar2  ]
+    set   midbar [ frame $base.bar22 -bg black -height 3  ]
+    set   outputbar    [ frame $base.bar25 ]
+
+    pack  $base.bar25 $midbar  -side bottom -expand t -fill x  -pady 5 -padx 2
+    pack  $base.bar2   -side top -expand t -fill both  -pady 5 -padx 2
+
+    frame $thresholdbar.t ; frame $thresholdbar.b ;
+    pack $thresholdbar.t $thresholdbar.b -side top -expand f -fill x
+    ::pxtclutil::CreateTriple $thresholdbar.t.y  "Fractional Intensity Threshold (Smaller value=Larger Brain)" [ itcl::scope thisparam($this,bet_fth) ] 0.0 0.99 0.05 0.5 170 
+    ::pxtclutil::CreateTriple $thresholdbar.b.y  "Gradient Threshold (+ve =Large Brain at Bottom, Small at Top)" [ itcl::scope thisparam($this,bet_gth) ] -0.99 0.99 0.05 0.0 170 
+    frame $thresholdbar.z; frame $thresholdbar.h
+    pack $thresholdbar.z $thresholdbar.h  -side top -expand f -fill x
+    checkbutton   $thresholdbar.z.1 -variable [ itcl::scope thisparam($this,bet_center) ] -text "Use Current Cross-Hairs"
+    label         $thresholdbar.z.2  -text "Initial Radius:"
+    entry         $thresholdbar.z.3  -textvariable [ itcl::scope thisparam($this,bet_radius) ] -relief sunken -width 5
+    pack $thresholdbar.z.1 $thresholdbar.z.2 $thresholdbar.z.3 -side left -expand f -fill x
+
+    eval "button  $thresholdbar.h.1  -text \"Execute Brain Extraction Tool\" -command { $this RunBET 1 }"    
+    eval "button  $thresholdbar.h.2  -text \"Show Console\" -command { $this RunBET 0 }"    
+    pack $thresholdbar.h.1 $thresholdbar.h.2 -side left -padx 2 -pady 5
+
+
+
+
+    
+    set thisparam($this,bet_braingui) [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $thisparam($this,bet_braingui) configure -description "Stripped Brain"
+    $thisparam($this,bet_braingui) InitializeLite $outputbar.1 2
+    $thisparam($this,bet_braingui) AddFunction "$parent SetResultsFromObject" "Display" "$this"
+
+    set thisparam($this,bet_overlaygui) [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $thisparam($this,bet_overlaygui) configure -description "Brain/Skull Overlay"
+    $thisparam($this,bet_overlaygui) InitializeLite $outputbar.2 2
+    $thisparam($this,bet_overlaygui) AddFunction "$parent SetResultsFromObject" "Display" "$this"
+
+    pack $outputbar.1 $outputbar.2 -side top -pady 0 -ipady 0
+
+    ::pxitclbasecontrol::SetWidgetTreeColors $thresholdbar  "\#ffdddd" "black"
+}
+# ----------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::CreateFASTTool { base } {
+
+    set a $thisparam($this,fslfast) 
+    label $base.o1 -bg black -fg white -text "Automated Segmentation Tool (FSL)"
+    label $base.o2 -bg black -fg white -text "From FMRIB Analysis Group, Oxford (cmdline=$a)"
+    label $base.o3 -bg black -fg white -text "(This calls the FSL fast program as an external process)"
+
+    
+    pack $base.o1 $base.o2 $base.o3  -side top -fill x -expand f -padx 2 -pady 0
+
+    set   thresholdbar [ frame $base.bar2  ]
+    set   midbar [ frame $base.bar22 -bg black -height 3  ]
+    set   outputbar    [ frame $base.bar25 ]
+
+    pack $outputbar $midbar -side bottom -expand f -fill x -pady 2
+    pack  $base.bar2   -side top -expand t -fill both  -pady 10 -padx 2
+
+    frame $thresholdbar.z; frame $thresholdbar.h
+    pack $thresholdbar.z $thresholdbar.h  -side top -expand f -fill x
+
+    label         $thresholdbar.z.1  -text "Input Image Type:"
+    tk_optionMenu $thresholdbar.z.2 [ itcl::scope thisparam($this,fast_type) ]  "T1-Weighted" "T2-Weighted" "PD-Weighted"
+    label         $thresholdbar.z.3  -text "Number Of Classes:"
+    tk_optionMenu $thresholdbar.z.4 [ itcl::scope thisparam($this,fast_numclasses) ] "2" "3" "4" "5" "6"
+
+    pack $thresholdbar.z.1 $thresholdbar.z.2 $thresholdbar.z.3 $thresholdbar.z.4 -side left -expand f -fill x
+
+    eval "button  $thresholdbar.h.1  -text \"Execute Automated Segmentation Tool\" -command { $this RunFAST 1 }"    
+    eval "button  $thresholdbar.h.2  -text \"Show Console\" -command { $this RunFAST 0 }"    
+    pack $thresholdbar.h.1 $thresholdbar.h.2 -side left -padx 2 -pady 5
+
+
+    ::pxitclbasecontrol::SetWidgetTreeColors $thresholdbar  "\#ffdddd" "black"
+    
+    set thisparam($this,fast_segmentedimagegui) [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $thisparam($this,fast_segmentedimagegui) configure -description "Classification Map"
+    $thisparam($this,fast_segmentedimagegui) InitializeLite $outputbar.1 2
+    $thisparam($this,fast_segmentedimagegui) AddFunction "$parent SetResultsFromObject" "Display" "$this"
+
+    pack $outputbar.1  -side top -pady 0 -ipady 0
+
+    set w [LabelFrame:create $outputbar.3 -text "Post-process Output" -expand false -fill x ]
+    pack $outputbar.3 -side bottom -expand f -fil x
+
+    eval "button  $w.1  -text \"Statistics\" -command { $this FASTStatistics cleanup }"    
+#    eval "button  $w.2  -text \"Normalize Brain Intensity\" -command { $this FASTNormalizeBrain }"    
+    pack $w.1  -side left -padx 2 -pady 5
+    
+
+}
+# ----------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::CreateSimpleControl { base } {
+
+    set   thresholdbar [ LabelFrame:create $base.bar2  -width 300  -text "Thresholds (to create mask)" ]
+    set   morphbar     [ LabelFrame:create $base.bar3  -width 300  -text "Morphology (to manipulate mask)" ]
+    pack  $base.bar2 $base.bar3 -side top -expand t -fill both  -pady 2
+
+
+    frame $thresholdbar.t ; frame $thresholdbar.b ; frame $thresholdbar.b2
+
+    pack $thresholdbar.t $thresholdbar.b $thresholdbar.b2 -side top -expand f -fill x
+    set thisparam($this,gui_lowthreshold)  [  ::pxtclutil::CreateTriple $thresholdbar.t.y  "Low Threshold" [ itcl::scope thisparam($this,lowthreshold) ] 0.0 1000.0 0.1 10 110 ]
+    set thisparam($this,gui_highthreshold) [  ::pxtclutil::CreateTriple $thresholdbar.t.z "High Threshold" [ itcl::scope thisparam($this,highthreshold) ]  0.0 1000.0 0.11 10 110 ]
+    eval "button  $thresholdbar.b.h  -text Threshold -command { $this ThresholdImage }"
+    eval "button  $thresholdbar.b.h2  -text \"Simple-Segment\" -command { $this SimpleSegment }"
+    eval "button  $thresholdbar.b.h3  -text \"Display\" -command { $this DisplayMorphologyResults }"
+    checkbutton $thresholdbar.b.l -variable [ itcl::scope thisparam($this,gui_displaymask) ] -text "Display Mask"
+    pack $thresholdbar.b.l -side left -padx 2
+    pack $thresholdbar.b.h3 $thresholdbar.b.h2 $thresholdbar.b.h -side right -padx 2
+
+
+    if { $thisparam($this,fslbet) != "" } {
+	eval "button  $thresholdbar.b2.h22  -text \"Generate Mask from Brain Extract Tool Output\" -command { $this GenerateMaskFromBETOutput 1 }"
+	pack  $thresholdbar.b2.h22 -side right -padx 2
+    }
+
+    frame $morphbar.1; frame $morphbar.2;  frame $morphbar.4 ; frame $morphbar.35; frame $morphbar.32 -height 2 -bg black
+
+    eval "button $morphbar.5 -text \"Undo Last Operation\"   -command { $this UndoLastMorphologyOperation }"
+    pack $morphbar.5  -side bottom -expand f -padx 20 -pady 5
+    pack $morphbar.1 $morphbar.2 $morphbar.32 $morphbar.35 $morphbar.4 -side top -fill x
+    
+    label         $morphbar.1.1  -text "Kernel Size:"
+    tk_optionMenu $morphbar.1.2  [ itcl::scope thisparam($this,gui_morphkernelsize) ]  "1" "3" "5" "7"
+    checkbutton   $morphbar.1.3 -variable [ itcl::scope thisparam($this,gui_morphology2d) ] -text "2D"
+    eval          "button $morphbar.1.4 -text \"BMedian\"  -command { $this BinaryMedianMap  }"
+    pack          $morphbar.1.1 $morphbar.1.2 $morphbar.1.3 $morphbar.1.4 -side left -expand t -padx 3 -fill x 
+    
+    eval "button $morphbar.2.3 -text Erode -command { $this ErodeMap  }"
+    eval "button $morphbar.2.4 -text Dilate      -command { $this DilateMap }"
+    pack          $morphbar.2.3 $morphbar.2.4 -side left -expand t -padx 3 -fill x 
+    
+    set b $morphbar.35
+    label  $b.1  -text "Seed Location:"
+    iwidgets::entryfield $b.2 -labeltext "x" -textvariable [ itcl::scope thisparam($this,seedx) ] -relief sunken -width 4 -validate integer
+    iwidgets::entryfield $b.3 -labeltext "y" -textvariable [ itcl::scope thisparam($this,seedy) ] -relief sunken -width 4 -validate integer
+    iwidgets::entryfield $b.4 -labeltext "z" -textvariable [ itcl::scope thisparam($this,seedz) ] -relief sunken -width 4 -validate integer
+    checkbutton   $b.5 -variable [ itcl::scope thisparam($this,seedautoupdate) ] -text "Auto Update"
+    eval "button $b.6 -text \"Update\"  -command { $this RequestUpdatedSeed 1 }"
+    pack $b.1 $b.2 $b.3 $b.4 $b.5 $b.6 -side left -expand t -fill x
+
+
+    set b   $morphbar.4 
+
+
+    eval "button $b.41 -text \"Connect Foreground\"  -command { $this ConnectMap 1 }"
+    eval "button $b.42 -text \"Connect Background\"  -command { $this ConnectMap 0 }"
+    pack  $b.41 $b.42 -side left -fill x -expand t -pady 0 -padx 1
+
+}
+
+# ----------------------------------------------------------------------------
+#  Histogram Segmentation Control
+# ----------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::CreateHistogramSegmentationControl { base } {
+
+    global pxtcl_pref_array
+    
+    entry $base.out -textvariable [ itcl::scope thisparam($this,histo_details)] -relief raised -state disabled -width 40 -background black -foreground white
+    
+    set   origtopbar  [ LabelFrame:create $base.bar1   -text "Histogram Segmentation (K-Means Clustering)" ]
+    set   mrfbar      [ LabelFrame:create $base.bar2   -text "Region Segmentation (extends Histogram Segmentation)" ]
+    set   maskbar     [  LabelFrame:create $base.bar3   -text "Create Mask" ]
+    pack  $base.bar3 -side bottom -expand f -fill x -pady 0
+    pack  $base.out $base.bar1 $base.bar2  -side top -expand false -fill x -pady 0
+
+
+    # ----------------------------------------------------------------------------
+    # Output Fields
+    # ----------------------------------------------------------------------------
+
+    set thisparam($this,segmoutput_gui) [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $thisparam($this,segmoutput_gui) configure -description "Segmentation Output"
+    $thisparam($this,segmoutput_gui) InitializeLite $maskbar.top 2
+    $thisparam($this,segmoutput_gui) AddFunction "$parent SetResultsFromObject" "Display" "$this"
+    pack $maskbar.top -side top -expand false -fill x
+    frame $maskbar.bot;     pack $maskbar.bot -side bottom -expand false -fill x
+
+    label $maskbar.bot.0 -text "Use Class:"
+    pack $maskbar.bot.0 -side left -padx 2
+
+    for { set i 1 } { $i <= 7 } { incr i } {
+	set j [ expr $i -1 ]
+	eval "checkbutton  $maskbar.bot.$i -variable [ itcl::scope thisparam($this,segm_useclass$i) ] -text $j"
+	pack $maskbar.bot.$i -side left -padx 1
+    }
+    eval "button $maskbar.bot.8 -text \"Generate\"  -command { $this GenerateMaskFromSegmentedOutput 1 }"
+
+    pack $maskbar.bot.8 -side right -padx 2
+
+    # --------------------------------------------------------------------------
+    # Histogram Segmentation
+    # --------------------------------------------------------------------------
+
+    set bbar [  frame $origtopbar.hb ]
+    pack $bbar -side bottom -expand f -fill x
+
+    set nt [ iwidgets::tabnotebook $origtopbar.nt -tabpos s -height 125 -angle 45 -margin 2 -backdrop gray -raiseselect true ]
+    pack $nt -side top -expand f  -fill x
+
+    set topbar  [ $nt add -label Standard   ]
+    set topbar2 [ $nt add -label Experimental ]
+    set advanced $topbar2
+    $nt view "Standard"
+
+    set mainbar  [ frame $topbar.1 ]
+    set meanbar  [ frame $topbar.2 ]
+
+    set sbar     [ frame $topbar2.1 ]
+    set probar   [ frame $topbar2.2 ]
+    set outbar   [ frame $topbar2.3 ]
+
+    pack $mainbar $meanbar -side top -expand false -fill x -pady 0
+    pack  $sbar $outbar  $probar -side top -expand false -fill x -pady 0
+
+    # ----------------------- Common ---------------------------------------------
+    label         $mainbar.1  -text "Classes:"
+    tk_optionMenu $mainbar.2 [ itcl::scope thisparam($this,histo_numclasses) ] "1" "2" "3" "4" "5" "6" "7"
+    iwidgets::entryfield $mainbar.3 -labeltext "sigmaratio:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,histo_sigmaratio) ] -relief sunken 
+    label         $mainbar.4  -text "Preprocessing Mode:"
+    tk_optionMenu $mainbar.5  [ itcl::scope thisparam($this,histo_premode) ] "None" "Positive" "Autorange" 
+
+
+    pack $mainbar.1 $mainbar.2 $mainbar.3 $mainbar.3 $mainbar.4 $mainbar.5  -side left -expand false -fill x -pady 3
+
+    label $meanbar.0 -text "Means:"
+    pack $meanbar.0 -side left -padx 2
+    for { set i 1 } { $i <=7 } { incr i } {
+	eval "iwidgets::entryfield $meanbar.$i -labeltext \"\"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,histo_mean$i) ] -relief sunken "
+	pack $meanbar.$i -side left -expand false -padx 0
+    }
+
+    checkbutton   $meanbar.a -variable [ itcl::scope thisparam($this,histo_useinitial) ] -text "Use Initial"
+    pack $meanbar.a -side left
+
+    eval "button $bbar.0 -text \"Segment\"  -command { $this HistogramSegmentation  }"
+    eval "button $bbar.1 -text \"Show Params\"  -command { $this     DisplayHistogramParameters  }"
+    pack $bbar.0 $bbar.1  -side left -fill x -expand false -padx 10 -pady 0
+
+    # -------------------------- Experimental ------------------------------------
+
+
+    
+    label         $probar.1  -text "Distributions:"
+    tk_optionMenu $probar.2  [ itcl::scope thisparam($this,histo_distmode) ] "Gaussian" "Robust" 
+
+    eval "iwidgets::entryfield $probar.3 -labeltext \"Valley\"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,histo_vsigma) ] -relief sunken "
+    eval "iwidgets::entryfield $probar.4 -labeltext \"RSigma\"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,histo_robustscalefactor) ] -relief sunken "
+    pack $probar.1 $probar.2 $probar.3 $probar.4 -side left -expand false -fill x 
+
+    
+    iwidgets::entryfield $sbar.1 -labeltext "Bins:"  -width 4 -validate integer -textvariable [ itcl::scope thisparam($this,histo_numbins) ] -relief sunken 
+    iwidgets::entryfield $sbar.2 -labeltext "Iterations:"  -width 4 -validate integer -textvariable [ itcl::scope thisparam($this,histo_iterations) ] -relief sunken 
+    iwidgets::entryfield $sbar.3 -labeltext "Sigma:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,histo_sigma) ] -relief sunken 
+    iwidgets::entryfield $sbar.4 -labeltext "Convergence:"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,histo_epsilon) ] -relief sunken 
+    
+    pack $sbar.1 $sbar.2 $sbar.3 $sbar.4 -side left -expand false -fill x 
+
+    checkbutton   $outbar.1 -variable [ itcl::scope thisparam($this,histo_outlier) ] -text "Enable Outlier Detection"
+    iwidgets::entryfield $outbar.2 -labeltext "p(outlier):"  -width 6 -validate real -textvariable [ itcl::scope thisparam($this,histo_outlierprobability) ] -relief sunken 
+    iwidgets::entryfield $outbar.3 -labeltext "Frame:"  -width 3 -validate integer -textvariable [ itcl::scope thisparam($this,histo_frame) ] -relief sunken 
+    pack $outbar.1 $outbar.2 $outbar.3 -side left
+
+
+    # -------------------
+    # MRF Bar
+    # -------------------
+    label $mrfbar.l -bg black -fg white -text "Using All parameters from Histogram Segmentation as well"
+    pack $mrfbar.l  -side top -pady 1 -fill x -expand t
+    set bbar    [ frame $mrfbar.2 ]
+    pack $bbar  -side bottom -pady 1 -fill x -expand t
+
+    eval "button $bbar.0 -text \"Do MRF Segmentation\"  -command { $this MRFSegmentation  }"
+    eval "button $bbar.1 -text \"Show Params\"  -command { $this     DisplayHistogramParameters  }"
+    pack $bbar.0 $bbar.1  -side left -fill x -expand false -padx 10 -pady 0
+    
+    set nt [ iwidgets::tabnotebook $mrfbar.nt -tabpos s -angle 45 -margin 2 -backdrop gray -raiseselect true ]
+    pack $nt -side top -expand t -fill both
+
+    set simpane  [ $nt add -label Standard   ]
+    set exppane [ $nt add -label Experimental ]
+    $nt view "Standard"
+
+    set mainbar   $simpane
+    set mainbar2   $exppane
+    #    pack $mainbar2 -side top -expand false -fill x -pady 0
+
+    # Simple --
+    # ---------
+    
+    iwidgets::entryfield $mainbar.1 -labeltext "Iterations"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,mrf_iterations) ] -relief sunken 
+    iwidgets::entryfield $mainbar.2 -labeltext "Smoothness:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,mrf_smoothness) ] -relief sunken 
+    iwidgets::entryfield $mainbar.3 -labeltext "Convergence:"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,mrf_convergence) ] -relief sunken 
+    iwidgets::entryfield $mainbar.4 -labeltext "Noise Sigma"  -width 4 -validate integer -textvariable [ itcl::scope thisparam($this,mrf_imagenoise) ] -relief sunken 
+    pack $mainbar.1 $mainbar.2 $mainbar.3 $mainbar.4  -side left -expand false -fill x 
+
+
+
+    # Advanced ------
+    # ----------------
+    checkbutton   $mainbar2.4 -variable [ itcl::scope thisparam($this,mrf_fuzzy) ] -text "Fuzzy"
+    checkbutton   $mainbar2.5 -variable [ itcl::scope thisparam($this,mrf_singlechannel) ] -text "Single"
+    iwidgets::entryfield $mainbar2.6 -labeltext "Channel:"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,histo_frame) ] -relief sunken 
+    pack $mainbar2.4 $mainbar2.5 $mainbar2.6  -side left -expand false -fill x 
+
+    if { $pxtcl_pref_array(EnableBetaFeatures) == "Enabled" } {
+	checkbutton   $mainbar2.7 -variable [ itcl::scope thisparam($this,mrf_dobiasfield) ] -text "B1 Correction"
+	iwidgets::entryfield $mainbar2.8 -labeltext "B1 Sigma:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,mrf_biasfieldsigma) ] -relief sunken 
+	pack  $mainbar2.7 $mainbar2.8  -side left -expand false -fill x 
+    }
+
+
+
+
+    ::pxitclbasecontrol::SetWidgetTreeColors $exppane  "\#aaabd7" "black"
+    ::pxitclbasecontrol::SetWidgetTreeColors $advanced "\#aaabd7" "black"
+}
+
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclbrainstrip::CreateBiasFieldCorrectionControl { base } {
+
+
+    set   pbar      [ frame $base.1  ]
+    set   midbar    [ frame $base.2 -bg black -height 3  ]
+    set   outputbar [ frame $base.3 ]
+
+
+    pack  $base.3 $base.2  -side bottom -expand false -fill x  -pady 1 -padx 2
+    pack  $base.1  -side top -expand true -fill both  -pady 1 -padx 2
+
+   
+    label $pbar.a -bg black -fg white -text "Using modified PABIC method (Styner et al, TMI 2000)"
+    pack $pbar.a -side top -expand false -fill x -pady 0 -padx 1
+
+    set slbar   [LabelFrame:create $pbar.1 -text "Slice Homogeneity" -expand false -fill x ]
+    set polybar [LabelFrame:create $pbar.2 -text "Polynomial Homogeneity" -expand false -fill x ]
+
+    pack  $pbar.1 $pbar.2  -side top -expand false -fill x
+
+    # ------------- Slice Homogeneity GUI ---------------------
+    checkbutton   $slbar.1 -variable [ itcl::scope thisparam($this,pabic_slice_usemask) ] -text "Use Mask"
+    checkbutton   $slbar.2 -variable [ itcl::scope thisparam($this,pabic_slice_robust)  ] -text "Median"	    
+    checkbutton   $slbar.25 -variable [ itcl::scope thisparam($this,pabic_slice_purescaling)  ] -text "Pure Scaling"	    
+    eval  "button $slbar.3 -text \"Run Slice\"  -command { $this RunSliceHomogeneity  }"
+    eval  "button $slbar.4 -text \"Run All Slices\"  -command { $this RunTripleSliceHomogeneity  }"
+    pack $slbar.4 $slbar.3 -side right -padx 4
+    pack $slbar.1 $slbar.2 $slbar.25 -side left -padx 2
+
+    
+    
+    # ------------- Polynomial Fitting -------------------------
+
+    set butbar    [ frame $polybar.nt2 ]
+    set nt [ iwidgets::tabnotebook $polybar.nt -tabpos s -height 100 -angle 45 -margin 2 -backdrop gray -raiseselect true ]
+    pack $nt  -side top -expand t -fill both
+    pack $butbar  -side top -expand f -fill x -pady 1
+
+    set topbar  [ $nt add -label Standard   ]
+    set topbar2 [ $nt add -label Advanced ]
+    $nt view "Standard"
+
+
+    set parambar  [ frame $topbar.2 ]
+    set parambar2  [ frame $topbar.3 ]
+
+    pack $parambar2 $parambar  -side top -expand false -fill x -pady 1
+
+    set advbar   [ frame $topbar2.1 ]
+    set advbar2   [ frame $topbar2.2 ]
+
+    pack $advbar $advbar2  -side top -expand false -fill x -pady 1
+
+    # ----------------------------------------------------------------------------------------------
+
+    label $parambar.0 -text "Parameters:"
+    iwidgets::entryfield $parambar.1 -labeltext "x"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,pabic_shimval_0) ] -relief sunken 
+    iwidgets::entryfield $parambar.2 -labeltext "y"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,pabic_shimval_1) ] -relief sunken 
+    iwidgets::entryfield $parambar.3 -labeltext "z"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,pabic_shimval_2) ] -relief sunken 
+    iwidgets::entryfield $parambar.4 -labeltext "x2"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,pabic_shimval_3) ] -relief sunken 
+    iwidgets::entryfield $parambar.5 -labeltext "y2"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,pabic_shimval_4) ] -relief sunken 
+    iwidgets::entryfield $parambar.6 -labeltext "z2"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,pabic_shimval_5) ] -relief sunken 
+    pack $parambar.0 $parambar.1 $parambar.2 $parambar.3 $parambar.4  $parambar.5 $parambar.6 -side left -expand t -fill x -padx 0
+
+    label $parambar2.1 -text "Resolution:" 
+    tk_optionMenu $parambar2.2 [ itcl::scope thisparam($this,pabic_shim_resolution) ] 1 2 3 4 
+    label         $parambar2.3 -text "Degree"
+    tk_optionMenu  $parambar2.4 [ itcl::scope thisparam($this,pabic_shim_degree) ] 1 2 3
+    checkbutton   $parambar2.5 -variable [ itcl::scope thisparam($this,pabic_shim_usemask) ] -text "Mask"	    
+    checkbutton   $parambar2.6 -variable [ itcl::scope thisparam($this,pabic_shim_useinitial) ] -text "Initial Params"
+#    checkbutton   $parambar2.7 -variable [ itcl::scope thisparam($this,pabic_shim_updatesegm) ] -text "Upd Segm"
+
+    pack  $parambar2.1 $parambar2.2 $parambar2.3 $parambar2.4  $parambar2.5 $parambar2.6 -side left -expand true -fill x -padx 0
+
+    eval "button $butbar.1 -text \"Apply\"  -command { $this RunManualShim  }"
+    eval "button $butbar.2 -text \"Optimize\"  -command { $this RunPolynomialPabic  }"
+
+    #    $butbar.1 configure -fg red
+    #    $butbar.2 configure -fg red
+
+    frame $butbar.25 -bg black
+    eval "button $butbar.3 -text \"Clear \"  -command { $this ClearPolynomial  }"
+    eval "button $butbar.4 -text \"Print\"  -command { $this PrintPolynomial   }"
+    eval "button $butbar.5 -text \"Load\"  -command { $this LoadPolynomial  }"
+    eval "button $butbar.6 -text \"Save\"  -command { $this SavePolynomial  }"
+
+    pack $butbar.6 $butbar.5 $butbar.4 $butbar.3 $butbar.25 -side right -expand t -padx 0  -fill y
+    pack $butbar.1 $butbar.2  -side left -expand t -padx 5 -fill both
+
+    # ----------------------------------------------------------------------------------------------
+    # Experimental
+    # ----------------------------------------------------------------------------------------------
+    label $advbar.0 -text "Lvls/Stps:" 
+    tk_optionMenu $advbar.1 [ itcl::scope thisparam($this,pabic_shim_numlevels) ] 1 2 3
+    tk_optionMenu $advbar.2 [ itcl::scope thisparam($this,pabic_shim_numsteps) ]  1 2 3 4
+    label $advbar.3 -text "Step:" 
+    tk_optionMenu $advbar.4 [ itcl::scope thisparam($this,pabic_shim_stepsize) ] 0.2 0.1 0.05 0.025 0.01 0.005
+    label $advbar.5 -text "Iter:" 
+    tk_optionMenu $advbar.6 [ itcl::scope thisparam($this,pabic_shim_iterations) ] 1 2 5 10 20
+    iwidgets::entryfield $advbar.7 -labeltext "Frame (4D Images):"  -width 3 -validate integer -textvariable [ itcl::scope thisparam($this,histo_frame) ] -relief sunken 
+
+    pack  $advbar.0 $advbar.1 $advbar.2 $advbar.3 $advbar.4  $advbar.5 $advbar.6 $advbar.7   -side left -expand false -fill x -padx 0
+
+    set opt_methods [ list  "Powell" "GradientDescent" "ConjugateGradient" ]
+    label $advbar2.1 -text "Opt Method"
+    eval "tk_optionMenu $advbar2.2 [ itcl::scope thisparam($this,pabic_optmethod) ] $opt_methods"
+    iwidgets::entryfield $advbar2.3 -labeltext "Min B1:" -textvariable [ itcl::scope thisparam($this,pabic_min) ] -relief sunken -width 4 -validate real 
+    iwidgets::entryfield $advbar2.4 -labeltext "Max B1:" -textvariable [ itcl::scope thisparam($this,pabic_max) ] -relief sunken -width 4 -validate real 
+
+
+    pack  $advbar2.1 $advbar2.2  $advbar2.3 $advbar2.4 -side left -expand false -fill x -padx 0
+
+    # ----------------------------------------------------------------------------------------------
+    set thisparam($this,pabic_maskgui) [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $thisparam($this,pabic_maskgui) configure -description "Mask"
+    $thisparam($this,pabic_maskgui) InitializeLite $pbar.3 2
+    $thisparam($this,pabic_maskgui) AddFunction "$parent SetResultsFromObject" "Display" "$this"
+    $thisparam($this,pabic_maskgui) AddFunction "$this GrabMorphologyMask" "Grab Morph" "$this"
+    $thisparam($this,pabic_maskgui) AddFunction "$this SetMorphologyMask" "Set Morph" "$this"
+    pack $pbar.3  -side top -pady 0 -ipady 0 -padx 2
+
+    # ----------------------------------------------------------------------------------------------
+
+    set thisparam($this,pabic_restoredgui) [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $thisparam($this,pabic_restoredgui) configure -description "Bias Corrected Image"
+    $thisparam($this,pabic_restoredgui) InitializeLite $outputbar.2 2
+    $thisparam($this,pabic_restoredgui) AddFunction "$parent SetResultsFromObject" "Display" "$this"
+
+    set thisparam($this,pabic_biasfieldgui) [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $thisparam($this,pabic_biasfieldgui) configure -description "Bias Field Estimate"
+    $thisparam($this,pabic_biasfieldgui) InitializeLite $outputbar.3 2
+    $thisparam($this,pabic_biasfieldgui) AddFunction "$parent SetResultsFromObject" "Display" "$this"
+    $thisparam($this,pabic_biasfieldgui) AddFunction "$this ApplyB1Field 0" "Apply" ""
+    $thisparam($this,pabic_biasfieldgui) AddFunction "$this ApplyB1Field 1" "Msk_Apply" ""
+
+
+
+    pack $outputbar.2 $outputbar.3 -side top -pady 0 -ipady 0 -padx 2
+
+
+    ::pxitclbasecontrol::SetWidgetTreeColors $topbar2  "\#aaabd7" "black"
+
+}
+
+# ----------------------------------------------------------------------------
+#  Morphology Stuff 
+# ----------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::CheckImage {  image name operation verbosity } {
+    
+    set ok 0
+    
+    catch { if { [ $image GetImageSize ] > 1 } {  set ok 1 }   }
+    
+    if { $verbosity >0 && $ok == 0 } {
+	::pxtclutil::Warning "No $name in Memory\n Cannot perform $operation !"
+    }
+
+    return $ok
+}
+
+# ----------------------------------------------------
+#  Histogram Segmentation
+# ----------------------------------------------------
+itcl::body pxitclbrainstrip::HistogramSegmentation { } {
+
+    if { [ CheckImage $currentimage "Image" "Histogram Segmentation" 1 ] == 0 } {
+	return 0
+    }
+
+    WatchOn
+    set segm [ vtkpxHistogramSegmentation [ pxvtable::vnewobj ]]
+    $segm SetInput [ $currentimage GetImage ]
+    $segm SetNumberOfClasses $thisparam($this,histo_numclasses)
+    $segm SetIterations $thisparam($this,histo_iterations)
+    $segm SetNumberOfBins $thisparam($this,histo_numbins)
+    $segm SetConvergence $thisparam($this,histo_epsilon)
+    $segm SetSigma $thisparam($this,histo_sigma)
+    $segm SetKeyChannel [ expr $thisparam($this,histo_frame) -1 ]
+    $segm GenerateLabelsOn
+    $segm SetOutlierDetection $thisparam($this,histo_outlier)
+
+    if { $thisparam($this,histo_premode) == "None" } {
+	$segm SetPreprocessingMode 0 
+    } elseif { $thisparam($this,histo_premode) == "Positive" } {
+	$segm SetPreprocessingMode 1
+    } elseif { $thisparam($this,histo_premode) == "Autorange" } {
+	$segm SetPreprocessingMode 2
+    } 
+
+    if { $thisparam($this,histo_distmode) ==  "Gaussian" } {
+	$segm SetDistributionModel 0
+    } else {
+	$segm SetDistributionModel 1
+    }
+
+    $segm SetOutlierProbability $thisparam($this,histo_outlierprobability)
+    $segm SetMaxSigmaRatio      $thisparam($this,histo_sigmaratio)
+    $segm SetRobustScaleFactor  $thisparam($this,histo_robustscalefactor)
+
+    if { $thisparam($this,histo_useinitial) == 1 } {
+	set ar [ vtkFloatArray [ pxvtable::vnewobj ]]
+	set np $thisparam($this,histo_numclasses)
+	$ar SetNumberOfComponents 3
+	$ar SetNumberOfTuples $np
+
+	for { set i 1 } { $i <= $np } { incr i } {
+	    set j [ expr $i -1 ]
+	    $ar SetComponent $j 1 $thisparam($this,histo_mean$i)
+	    $ar SetComponent $j 2 $thisparam($this,histo_vsigma)
+	    $ar SetComponent $j 0 100
+	}
+	$segm SetInitialParameters $ar
+	$ar Delete
+    }
+    
+    SetFilterCallbacks $segm   "Histogram Segmenting image"
+
+
+    $segm Update
+
+
+
+    $currentresults ShallowCopyImage [ $segm GetOutput ]
+
+
+    set outimage [ $thisparam($this,segmoutput_gui) GetObject ]
+    $outimage ShallowCopyImage [ $segm GetOutput ]
+    $outimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "histo" ]
+    $outimage  CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,segmoutput_gui) Update
+
+    $this GenerateMaskFromSegmentedOutput 0
+
+    ProcessImageResults "histo"
+    $thisparam($this,histo_params) DeepCopy [ $segm GetParameters ]
+
+
+    if { $thisparam($this,histo_outlier) == 1 } {
+	set nt [ expr [ $thisparam($this,histo_params) GetNumberOfTuples ] -1 ]
+	$thisparam($this,histo_params) SetComponent $nt 2 -1
+    }
+
+    $segm Delete
+    WatchOff
+    DisplayHistogramParameters
+}
+
+
+itcl::body pxitclbrainstrip::MRFSegmentation { } {
+
+    if { [ CheckImage $currentimage "Image" "MRF Segmentation" 1 ] == 0 } {
+	return
+    }
+
+    WatchOn
+    set segm [ vtkpxMRFSegmentation [ pxvtable::vnewobj ]]
+    $segm SetInput [ $currentimage GetImage ]
+    $segm SetNumberOfClasses $thisparam($this,histo_numclasses)
+    $segm SetIterations $thisparam($this,histo_iterations)
+    $segm SetNumberOfBins $thisparam($this,histo_numbins)
+    $segm SetConvergence $thisparam($this,histo_epsilon)
+    $segm SetSigma $thisparam($this,histo_sigma)
+    $segm SetImageNoiseSigma $thisparam($this,mrf_imagenoise)
+    $segm SetOutlierDetection $thisparam($this,histo_outlier)
+    $segm SetComputeBiasField  $thisparam($this,mrf_dobiasfield)
+    $segm SetBiasFieldFactor $thisparam($this,mrf_biasfieldsigma)
+    $segm SetKeyChannel [ expr $thisparam($this,histo_frame) -1 ]
+
+    $segm SetPreprocessingMode 0 
+    if { $thisparam($this,histo_premode) == "None" } {
+	$segm SetPreprocessingMode 0 
+    } elseif { $thisparam($this,histo_premode) == "Positive" } {
+	$segm SetPreprocessingMode 1
+    }  elseif { $thisparam($this,histo_premode) == "Autorange" } {
+	$segm SetPreprocessingMode 2
+    } 
+
+    if { $thisparam($this,histo_distmode) ==  "Gaussian" } {
+	$segm SetDistributionModel 0
+    } else {
+	$segm SetDistributionModel 1
+    }
+    
+    $segm SetRobustScaleFactor  $thisparam($this,histo_robustscalefactor)
+    $segm SetMaxSigmaRatio      $thisparam($this,histo_sigmaratio)
+    $segm SetOutlierProbability $thisparam($this,histo_outlierprobability)
+    $segm SetMRFIterations $thisparam($this,mrf_iterations)
+    $segm SetSmoothness $thisparam($this,mrf_smoothness)
+    $segm SetHistogramNormalization $thisparam($this,mrf_histonorm)
+    $segm SetMRFConvergencePercentage $thisparam($this,mrf_convergence)
+    $segm SetFuzzyClassification $thisparam($this,mrf_fuzzy)
+    $segm SetSingleChannel       $thisparam($this,mrf_singlechannel)
+    SetFilterCallbacks $segm   "Histogram Segmenting image"
+    $segm SetDebugVoxel 1
+    $segm Update
+
+    if { $thisparam($this,mrf_fuzzy) == 0 } {
+	$currentresults ShallowCopyImage [ $segm GetOutput ]
+    } else {
+	$currentresults ShallowCopyImage [ $segm GetMultiFrameOutput ]
+    }
+
+    ProcessImageResults "histo"
+    $thisparam($this,histo_params) DeepCopy [ $segm GetParameters ]
+
+
+    if { $thisparam($this,histo_outlier) == 1 } {
+	set nt [ expr [ $thisparam($this,histo_params) GetNumberOfTuples ] -1 ]
+	$thisparam($this,histo_params) SetComponent $nt 2 -1
+    }
+
+    set outimage [ $thisparam($this,segmoutput_gui) GetObject ]
+    $outimage ShallowCopyImage [ $segm GetOutput ]
+    $outimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "histo" ]
+    $outimage  CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,segmoutput_gui) Update
+
+    if {  $thisparam($this,mrf_dobiasfield) == 1 } {
+	set biasfieldimage [ $thisparam($this,pabic_biasfieldgui) GetObject ]
+	$biasfieldimage  ShallowCopyImage [ $segm GetBiasField ]
+	$biasfieldimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "biasfield" ]
+	$biasfieldimage  CopyImageHeader [ $currentimage GetImageHeader ]
+	$thisparam($this,pabic_biasfieldgui) Update
+    }
+
+
+
+    $this GenerateMaskFromSegmentedOutput 0
+    $segm Delete
+    WatchOff
+    DisplayHistogramParameters
+}
+
+itcl::body pxitclbrainstrip::DisplayHistogramParameters { } {
+
+    pxtkconsole
+    pxtkprint "\n Histogram Segmentation Results\n---------------------------\nClass \t Number of Voxels \t\t Mean \t Standard Deviation\n\n"
+    
+    set hasoutlier 0
+
+    for { set i 1 } { $i <=7 } { incr i } {
+	set thisparam($this,histo_mean$i) $i
+    }
+
+    set arr $thisparam($this,histo_params)
+    if { $arr != "" } {
+	if { [ $arr GetNumberOfTuples ] > 0 } {
+	    for { set i 0 } { $i < [ $arr GetNumberOfTuples ] } { incr i } {
+		set v [ $arr GetComponent $i 2 ]
+		if { $v >= 0.0 } {
+		    pxtkprint "Class [ expr $i+1 ]\t"
+		    set k [ expr $i +1 ]
+		    set thisparam($this,histo_mean$k) [ $arr GetComponent $i 1 ]
+		} else {
+		    pxtkprint "Outlier\t"
+		    set hasoutlier 1
+		}
+		for { set j 0 } { $j < [ $arr GetNumberOfComponents ] } { incr j } {
+		    pxtkprint " [ $arr GetComponent $i $j ] \t"
+		}
+
+		set mean [ $arr GetComponent  $i 1 ]
+		set sigma [ $arr GetComponent $i 2 ]
+		pxtkprint [ format "ratio=%.2f " [ expr $mean / $sigma ] ]
+
+		pxtkprint "\n"
+	    }
+	    set thisparam($this,histo_details) " [ expr [ $arr GetNumberOfTuples ] - $hasoutlier ] classes in memory (outlier=$hasoutlier)"
+	} else {
+	    set thisparam($this,histo_details) "No parameters in memory"
+	}
+
+	set hist [ vtkpxHistogramSegmentation [ pxvtable::vnewobj ]]
+
+	# Do Thresholds 
+	for { set i 0 } { $i < [ expr [  $arr GetNumberOfTuples ] - 1 ] } { incr i } {
+	    set k1 [ expr $i    ]
+	    set k2 [ expr $i +1 ] 
+	    set v [ $arr GetComponent $k2 1 ]
+	    if { $v >= 0.0 } {
+		pxtkprint "Threshold [ expr $i+1 ]:[ expr $i+2 ]:"
+		set m1 [ $arr GetComponent $k1 1 ]
+		set m2 [ $arr GetComponent $k2 1 ]
+		set s1 [ $arr GetComponent $k1 2 ]
+		set s2 [ $arr GetComponent $k2 2 ]
+		
+		set t1 [ $hist GetThreshold $m1 $m2 $s1 $s2 ]
+
+		pxtkprint  "Threshold $k2 = $t1 \n" 
+	    }
+	}
+	
+    } else {
+	set thisparam($this,histo_details) "No parameters in memory"
+    }
+
+}
+
+itcl::body pxitclbrainstrip::GenerateMaskFromSegmentedOutput { mode } {
+    
+    set ok 0
+    set img1 [ $thisparam($this,segmoutput_gui) GetObject ]
+    catch { if { [ $img1 GetImageSize ] > 1 } {  set ok 1 }   }
+    if { $ok == 0 } {
+	pxtkconsole "No Segmentation; Running Histogram Segmentation First!"
+	set ok [ HistogramSegmentation ]
+	pxtkconsole "Histogram Segmentation Done!"
+    }
+    
+    if { $ok == 0 } {
+	return
+    }
+
+    set numgood 0
+    for { set i 1 } { $i <= 7 } { incr i } {
+	if { $thisparam($this,segm_useclass$i) == 1 } {
+	    incr numgood
+	}
+    }
+
+    if { $numgood == 0 } {
+	::pxtclutil::Warning "At least one class must be selected to create a morphology mask!"
+	return 0
+    }
+
+    set map [ vtkDoubleArray [ pxvtable::vnewobj ]]
+    $map SetNumberOfComponents 3
+    $map SetNumberOfTuples 14
+    
+    $map SetTuple3 0 -0.5 0.0 0.0
+    for { set l 0 } { $l <= 6 } { incr l } {
+	set t1  [ expr $l -0.1 ]
+	set t2  [ expr $l +0.1 ]
+	set k  0.0
+	set c  0.0 
+	set lp [ expr $l + 1 ]
+	if { $thisparam($this,segm_useclass$lp) == 1 } {
+	    set c 1.0
+	}
+	$map SetTuple3 [ expr 2*$l   ] $t1 0  $k
+	$map SetTuple3 [ expr 2*$l+1 ] $t2 $c $k
+    }
+       
+    WatchOn
+    set sh  [ vtkpxImageAlgebra [ pxvtable::vnewobj ]  ]
+    $sh SetInput [ $img1 GetImage ]
+    $sh SetMap $map
+    $sh SetOutputScalarTypeToUnsignedChar
+    SetFilterCallbacks $sh "Creating Mask From Segmented Data"
+    $sh Update
+    
+    $oldmask ShallowCopy $currentmask
+    if { $mode == 0 } {
+	$currentmask ShallowCopyImage  [ $sh GetOutput ]
+    }  else {
+	ProcessMorphologyResults [ $sh GetOutput ]
+    }
+    WatchOff
+    catch { $sh Delete }
+    $map Delete
+    WatchOff
+}    
+
+# ----------------------------------------------------
+#  Pabic Bias Field Correction
+# ----------------------------------------------------
+itcl::body pxitclbrainstrip::RunSliceHomogeneity   {  } { 
+
+    if { [ CheckImage $currentimage "Image" "Bias Field Correction" 1 ] == 0 } { 
+	return 0  
+    }
+    
+    if { $thisparam($this,pabic_slice_usemask) == 1  } {
+	set img1 [ $thisparam($this,pabic_maskgui) GetObject ]
+	if { [ $img1 GetImageSize ] != [ $currentimage GetImageSize ] } {
+	    ::pxtclutil::Warning "Mask does not have the same size as the image to be corrected! Cannot perform bias field correction!"
+	    return 0
+	}
+    }
+
+    WatchOn    
+
+
+    pxtkprint ".... Slice Inhomogeneity Correction\n"
+    set fit [ vtkpxSliceBiasFieldCorrection  [ pxvtable::vnewobj ]]
+    if { $thisparam($this,pabic_slice_usemask) == 1  } {
+	pxtkprint ".... Using mask image\n"
+	$fit SetMaskImage [ [ $thisparam($this,pabic_maskgui) GetObject ] GetImage ]
+    }
+	
+    $fit SetRobustMode $thisparam($this,pabic_slice_robust)
+    $fit SetPureScaling $thisparam($this,pabic_slice_purescaling) 
+    $fit SetInput [ $currentimage GetImage ] 
+    $fit SetFrame  [ expr $thisparam($this,histo_frame) -1 ]
+    
+    pxtkconsole
+    eval "$fit AddObserver ProgressEvent { pxtkprint  \"Sl:\[ $fit GetOutputStatus \] \n\" }"
+    $fit Update
+
+    set outimage [ $thisparam($this,pabic_restoredgui) GetObject ]
+    set b1image  [ $thisparam($this,pabic_biasfieldgui) GetObject ]
+
+    $outimage ShallowCopyImage [ $fit GetOutput ]
+    $b1image  ShallowCopyImage [ $fit GetBiasField ]
+    $fit Delete
+    WatchOff
+
+    $outimage  CopyImageHeader [ $currentimage GetImageHeader ]
+    $outimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "slice" ]
+    $b1image  CopyImageHeader [ $currentimage GetImageHeader ]
+    $b1image  configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "b1_slice" ]
+
+
+    $thisparam($this,pabic_restoredgui) Update
+    $thisparam($this,pabic_biasfieldgui) Update
+    $parent SetResultsFromObject $outimage $this
+
+}
+
+# ----------------------------------------------------------------------------------------------------
+
+
+itcl::body pxitclbrainstrip::RunTripleSliceHomogeneity   {  } { 
+
+    if { [ CheckImage $currentimage "Image" "Bias Field Correction" 1 ] == 0 } { 
+	return 0  
+    }
+    
+    if { $thisparam($this,pabic_slice_usemask) == 1  } {
+	set img1 [ $thisparam($this,pabic_maskgui) GetObject ]
+	if { [ $img1 GetImageSize ] != [ $currentimage GetImageSize ] } {
+	    ::pxtclutil::Warning "Mask does not have the same size as the image to be corrected! Cannot perform bias field correction!"
+	    return 0
+	}
+    }
+
+    WatchOn    
+
+    set axislist { x y z }
+
+    set output [ vtkImageData [ pxvtable::vnewobj ]]
+    $output ShallowCopy [ $currentimage GetImage ] 
+
+    for { set axis 0 } { $axis <=2 } { incr axis } {
+	pxtkprint ".... Slice Inhomogeneity Correction orientation  axis= [ lindex $axislist $axis ]\n"
+	
+	set fit [ vtkpxSliceBiasFieldCorrection  [ pxvtable::vnewobj ]]
+	
+	if { $thisparam($this,pabic_slice_usemask) == 1  } {
+	    pxtkprint ".... Using mask image\n"
+	    $fit SetMaskImage [ [ $thisparam($this,pabic_maskgui) GetObject ] GetImage ]
+	}
+
+	$fit SetAxis $axis
+	$fit SetRobustMode $thisparam($this,pabic_slice_robust) 
+	$fit SetPureScaling $thisparam($this,pabic_slice_purescaling) 
+	$fit SetInput $output
+	$fit SetFrame  [ expr $thisparam($this,histo_frame) -1 ]
+	
+	pxtkconsole
+	eval "$fit AddObserver ProgressEvent { pxtkprint  \"Sl:\[ $fit GetOutputStatus \] \n\" }"
+	$fit Update
+	$output ShallowCopy [ $fit GetOutput ]
+	$fit Delete
+    }
+
+    set fit [ vtkpxSliceBiasFieldCorrection  [ pxvtable::vnewobj ]]
+    set b1tmp [ $fit ComputeRatioBiasFieldImage [ $currentimage GetImage ] $output ]
+    $fit Delete
+
+    set b1image  [ $thisparam($this,pabic_biasfieldgui) GetObject ]
+    $b1image ShallowCopyImage $b1tmp
+    $b1tmp Delete
+    $b1image  configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "b1_triple" ]
+    $b1image  CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,pabic_biasfieldgui) Update
+
+    set outimage [ $thisparam($this,pabic_restoredgui) GetObject ]
+    $outimage ShallowCopyImage $output;
+    $output Delete
+    WatchOff
+
+
+    $outimage  CopyImageHeader [ $currentimage GetImageHeader ]
+    $outimage  configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "tripleslice" ]
+
+    $thisparam($this,pabic_restoredgui) Update
+    $parent SetResultsFromObject $outimage $this
+}
+
+# ----------------------------------------------------------------------------------------------------
+
+
+itcl::body pxitclbrainstrip::RunImageApproximation {  } { 
+
+    if { [ CheckImage $currentimage "Image" "Bias Field Correction" 1 ] == 0 } { 
+	return 0  
+    }
+
+    set mask [ $thisparam($this,pabic_maskgui) GetObject ]
+    if { [ $mask GetImageSize ] != [ $currentimage GetImageSize ] } {
+	::pxtclutil::Warning "Image Approximation Requires a Mask. The mask does not have the same size as the image to be approximated!"
+	return 0
+    }
+    
+    WatchOn
+    set bspl [ vtkpxImageTensorSpline [ pxvtable::vnewobj ]]
+    $bspl SetMaskImage [ $mask GetImage ]
+    $bspl SetInput [ $currentimage GetImage ]
+    $bspl SetLambda [ expr 100.0*$thisparam($this,pabic_spl_lambda) ]
+    $bspl SetStepSize $thisparam($this,pabic_spl_stepsize)
+    $bspl SetResolution $thisparam($this,pabic_sample)
+    $bspl SetPreSmoothIterations $thisparam($this,pabic_spl_presmooth);
+    $bspl SetMode 1
+    $bspl SetControlPointSpacing $thisparam($this,pabic_spl_spacing)
+    $bspl SetAutoInitialize 1
+    $bspl SetIterations $thisparam($this,pabic_iterations)
+    $bspl SetEpsilon 0.01
+    $bspl Run
+
+    set b1image  [ $thisparam($this,pabic_biasfieldgui) GetObject ]
+    $b1image  ShallowCopyImage [ $bspl GetOutput ]
+    $b1image  configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "b1_approx" ]
+    $b1image  CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,pabic_biasfieldgui) Update
+
+    set fit [ vtkpxAbstractBiasFieldCorrection  [ pxvtable::vnewobj ]]
+    set img [ $fit ComputeMeanPreservingCorrectedImage [ $currentimage GetImage ] [ $b1image GetImage ] 
+
+    set outimage [ $thisparam($this,pabic_restoredgui) GetObject ]
+    $outimage ShallowCopyImage $img
+    $outimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "approx" ]
+    $outimage CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,pabic_restoredgui) Update
+    $img Delete
+
+    WatchOff
+    $parent SetResultsFromObject $outimage $this
+}
+
+# ----------------------------------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::GrabMorphologyMask { arg1 arg2 } {
+
+    [ $thisparam($this,pabic_maskgui) GetObject ]  ShallowCopy $currentmask
+    [ $thisparam($this,pabic_maskgui) GetObject ] configure -filename [ AddPrefix [ $currentimage cget -filename  ] "smask" ]
+    $thisparam($this,pabic_maskgui) Update
+}
+
+itcl::body pxitclbrainstrip::SetMorphologyMask { arg1 arg2 } {
+
+    set sh [ vtkImageCast [ pxvtable::vnewobj ]]
+    $sh SetInput [ [ $thisparam($this,pabic_maskgui) GetObject ]  GetImage ]
+    $sh SetOutputScalarTypeToUnsignedChar
+    $sh Update
+
+    $currentmask ShallowCopyImage  [ $sh GetOutput ]
+    $sh Delete
+}
+
+itcl::body pxitclbrainstrip::SetMorphologyMaskImage { img } {
+
+    set sh [ vtkImageCast [ pxvtable::vnewobj ]]
+    $sh SetInput $img
+    $sh SetOutputScalarTypeToUnsignedChar
+    $sh Update
+
+    $currentmask ShallowCopyImage  [ $sh GetOutput ]
+
+    puts stdout "Getting mask from $img [ [ [ $img GetPointData ] GetScalars ] GetRange ]"
+    $sh Delete
+}
+
+itcl::body pxitclbrainstrip::ApplyB1Field { args } { 
+
+    if { [ CheckImage $currentimage "Image" "Bias Field Correction" 1 ] == 0 } { 
+	return 0  
+    }
+
+    set b1image  [ $thisparam($this,pabic_biasfieldgui) GetObject ]
+
+    if { [ $b1image GetImageSize ] != [ $currentimage GetImageSize ] } {
+	::pxtclutil::Warning "B1 - Field  does not have the same size as the image to be corrected! Cannot apply the bias field!"
+	return 0
+    }
+
+    set domask 0
+    if { [ llength $args ] > 0 } {
+	if { [ lindex $args 0 ] > 0 } {
+	    set domask 1
+	}
+    }
+
+    if { $domask == 1 } {
+	set mask_image [ $thisparam($this,pabic_maskgui) GetObject ]
+	if { [ $mask_image GetImageSize ] != [ $currentimage GetImageSize ] } {
+	    ::pxtclutil::Warning "Mask does not have the same size as the image to be corrected! Cannot apply masked bias field correction!"
+	    return 0
+	}
+    }
+
+    WatchOn    
+    
+    set fit [ vtkpxAbstractBiasFieldCorrection  [ pxvtable::vnewobj ]]
+    if { $domask == 0  } {
+	pxtkprint "Unmasked bias field correction !\n"
+	set img [ $fit ComputeCorrectedImage [ $currentimage GetImage ] [ $b1image GetImage ] 0 ]
+    } else {
+	pxtkprint "Msked bias field correction!\n"
+	set img [ $fit ComputeMaskCorrectedImage [ $currentimage GetImage ] [ $b1image GetImage ] [ $mask_image GetImage ] $thisparam($this,pabic_multiplicative) ]
+    }
+    WatchOff
+
+    $currentresults ShallowCopyImage $img
+    $currentresults configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "Corr" ]
+    $currentresults CopyImageHeader [ $currentimage GetImageHeader ]
+    $parent SetResultsFromObject $currentresults $this
+    $img Delete
+
+
+
+}
+
+# ----------------------------------------------------------------------------------------------------
+
+itcl::body pxitclbrainstrip::RunSplinePabic {  } {
+
+
+    if { [ CheckImage $currentimage "Image" "Bias Field Correction" 1 ] == 0 } { 
+	return 0  
+    }
+    
+    if { $thisparam($this,pabic_usemask) == 1  } {
+	set img1 [ $thisparam($this,pabic_maskgui) GetObject ]
+	if { [ $img1 GetImageSize ] != [ $currentimage GetImageSize ] } {
+	    ::pxtclutil::Warning "Mask does not have the same size as the image to be corrected! Cannot perform bias field correction!"
+	    return 0
+	}
+    }
+
+
+    WatchOn    
+
+    set outimage [ $thisparam($this,pabic_restoredgui) GetObject ]
+    set b1image  [ $thisparam($this,pabic_biasfieldgui) GetObject ]
+
+    pxtkprint ".... Slice Inhomogeneity Correction\n"
+    set fit [ vtkpxSplineFitBiasFieldCorrection  [ pxvtable::vnewobj ]]
+    if { $thisparam($this,pabic_usemask) == 1 || $thisparam($this,pabic_usefatmask) == 1 } {
+	pxtkprint ".... Using mask image\n"
+	if { $thisparam($this,pabic_usefatmask) == 1 } {
+	    $fit SetFatMask [ [ $thisparam($this,pabic_maskgui) GetObject ] GetImage ]
+	} else {
+	    $fit SetMaskImage [ [ $thisparam($this,pabic_maskgui) GetObject ] GetImage ]
+	}
+    }
+    $fit SetMode [ expr 1-$thisparam($this,pabic_multiplicative) ]
+    $fit SetInput [ $currentimage GetImage ] 
+    $fit SetMetric $thisparam($this,pabic_spl_metric) 
+    $fit SetLambda [ expr $thisparam($this,pabic_spl_lambda)*0.01 ]
+    $fit SetStepSize $thisparam($this,pabic_spl_stepsize)
+    $fit SetNumberOfLevels 1
+    $fit SetFatMaskWeight $thisparam($this,pabic_spl_fatmaskweight)
+    $fit SetResolution $thisparam($this,pabic_sample)
+    $fit SetControlPointSpacing $thisparam($this,pabic_spl_spacing)
+    $fit SetNumberOfIterations $thisparam($this,pabic_iterations)
+    $fit SetEpsilon 0.1
+    
+
+    $fit SetHisto_NumberOfClasses $thisparam($this,histo_numclasses)
+    $fit SetHisto_Iterations $thisparam($this,histo_iterations)
+    $fit SetHisto_NumberOfBins $thisparam($this,histo_numbins)
+    $fit SetHisto_Convergence $thisparam($this,histo_epsilon)
+    $fit SetHisto_Sigma $thisparam($this,histo_sigma)
+    $fit SetHisto_OutlierDetection $thisparam($this,histo_outlier)
+    $fit SetHisto_OutlierProbability $thisparam($this,histo_outlierprobability)
+
+
+    if { $thisparam($this,histo_premode) == "None" } {
+	$fit SetHisto_PreprocessingMode 0
+    } elseif { $thisparam($this,histo_premode) == "Positive Only" } {
+	$fit SetHisto_PreprocessingMode 1
+    } else {
+	$fit SetHisto_PreprocessingMode 2
+    }
+
+    
+    #$fit SetNumberOfLevels 1
+    $fit SetNumberOfSteps  1
+    
+    pxtkconsole
+
+    eval "$fit AddObserver ProgressEvent { pxtkprint  \"Sl:\[ $fit GetOutputStatus \] \n\" }"
+    $fit Update
+
+    $outimage ShallowCopyImage [ $fit GetOutput ]
+    $b1image  ShallowCopyImage [ $fit GetBiasField ]
+    $fit Delete
+    WatchOff
+
+    $outimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "spline" ]
+    $outimage CopyImageHeader [ $currentimage GetImageHeader ]
+    $b1image  configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "b1_spline" ]
+    $b1image  CopyImageHeader [ $currentimage GetImageHeader ]
+
+
+    $thisparam($this,pabic_restoredgui) Update
+    $thisparam($this,pabic_biasfieldgui) Update
+    $parent SetResultsFromObject $outimage $this
+}
+
+# ----------------------------------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::ClearPolynomial {  } {
+
+    for { set i 0 } { $i <=18 } { incr i } {
+	set thisparam($this,pabic_shimval_$i) 0.0
+    }
+}
+
+itcl::body pxitclbrainstrip::PrintPolynomial { { fileid 0 }  } {
+
+    set line "\#Polynomial Bias Field Correction Parameters"
+    if { $fileid != 0 } {
+	puts $fileid $line
+    } else {
+	pxtkconsole
+	pxtkprint "\n\n------------------------------------------\n$line\n"
+    }
+
+    set pnamelist "x y z x2 y2 z2 xy xz yz  x3-x y3-y z3-z x2y x2z y2z y2z z2x z2y xyz"
+
+    set count 1
+    for { set i 0 } { $i <= 18 } { incr i } {
+	set line [ format "%10s : %7.2f " [ lindex $pnamelist $i ] $thisparam($this,pabic_shimval_$i)  ]
+	if { $fileid != 0 } {
+	    puts $fileid $line
+	} else {
+	    pxtkprint "$line"
+	    incr count
+	    if { $count == 5 } {
+		pxtkprint "\n"
+		set count 1
+	    } else {
+		pxtkprint "\t"
+	    }
+	}
+    }
+
+    if { $fileid == 0 } {
+	pxtkprint "\n\n"
+    }
+
+}
+
+itcl::body pxitclbrainstrip::LoadPolynomial {  } {
+
+    set fname [tk_getOpenFile -title "Filename"   -filetypes { {"Polynomial Parameter Files" {.plist}}}]
+    if { [ llength $fname ] > 0 } {
+	if { [ file exists $fname ] > 0 } {
+	    set fileid [open $fname r ]
+	    gets $fileid line
+	    if { $line == "\#Polynomial Bias Field Correction Parameters" } {
+		$this ClearPolynomial
+		for { set i 0 } { $i <= 18 } { incr i } {
+		    gets $fileid line
+		    set index [string first ":" $line]
+		    if { $index > 0 }  {
+			set len   [string length $line]
+			set key   [string trim   [string range $line 0 [expr $index - 1]]]
+			set value [string trim [string range $line [expr $index +1] [expr $len -1]]]	
+			set thisparam($this,pabic_shimval_$i) $value
+		    }
+		}
+		close $fileid
+	    } else {
+		pxtclutil::Warning "Failed to Read Polynomial Parameters from $fname"
+	    }
+	}
+    }
+}
+
+itcl::body pxitclbrainstrip::SavePolynomial {  } {
+
+    set fname [tk_getSaveFile -title "Filename" -defaultextension .plist  -filetypes { {"Polynomial Parameter Files" {.plist}}}]
+    if { [ llength $fname ] > 0 } {
+	set fileid [open $fname w]
+	$this PrintPolynomial $fileid
+	close $fileid
+	pxtclutil::Info "Polynomial Parameters Saved in $fname"
+    }
+}
+
+
+itcl::body pxitclbrainstrip::RunPolynomialPabic {  } {
+
+
+    if { [ CheckImage $currentimage "Image" "Polynomial Bias Field Correction" 1 ] == 0 } { 
+	return 0  
+    }
+    
+    if { $thisparam($this,pabic_shim_usemask) == 1  } {
+	set img1 [ $thisparam($this,pabic_maskgui) GetObject ]
+	if { [ $img1 GetImageSize ] != [ $currentimage GetImageSize ] } {
+	    ::pxtclutil::Warning "Mask does not have the same size as the image to be corrected! Cannot perform bias field correction!"
+	    return 0
+	}
+    }
+
+    WatchOn    
+    set outimage [ $thisparam($this,pabic_restoredgui) GetObject ]
+    set b1image  [ $thisparam($this,pabic_biasfieldgui) GetObject ]
+
+    pxtkprint ".... Polynomial Inhomogeneity Correction\n"
+    set fit [ vtkpxPolynomialBiasFieldCorrection  [ pxvtable::vnewobj ]]
+
+    if { $thisparam($this,pabic_shim_usemask) == 1 } {
+	pxtkprint ".... Using mask image\n"
+	$fit SetMaskImage [ [ $thisparam($this,pabic_maskgui) GetObject ] GetImage ]
+    }
+
+    $fit SetInput   [ $currentimage GetImage ] 
+    $fit SetMetric   $thisparam($this,pabic_shim_metric) 
+    $fit SetNumberOfLevels     $thisparam($this,pabic_shim_numlevels)
+    $fit SetNumberOfSteps      $thisparam($this,pabic_shim_numsteps)
+    $fit SetResolution         $thisparam($this,pabic_shim_resolution)
+    $fit SetStepSize           $thisparam($this,pabic_shim_stepsize)
+    $fit SetNumberOfIterations $thisparam($this,pabic_shim_iterations)
+    $fit SetEpsilon 0.1
+    $fit SetDegree $thisparam($this,pabic_shim_degree)
+    $fit SetOptimizationMethodTo$thisparam($this,pabic_optmethod)
+    $fit SetFrame  [ expr $thisparam($this,histo_frame) -1 ]
+    $fit SetMinValue $thisparam($this,pabic_min)
+    $fit SetMaxValue $thisparam($this,pabic_max)
+    $fit SetRecomputeParameters 0
+    $fit SetHisto_NumberOfClasses $thisparam($this,histo_numclasses)
+    $fit SetHisto_Iterations $thisparam($this,histo_iterations)
+    $fit SetHisto_NumberOfBins $thisparam($this,histo_numbins)
+    $fit SetHisto_Convergence $thisparam($this,histo_epsilon)
+    $fit SetHisto_Sigma $thisparam($this,histo_sigma)
+    $fit SetHisto_MaxSigmaRatio $thisparam($this,histo_sigmaratio)
+    $fit SetHisto_OutlierDetection $thisparam($this,histo_outlier)
+    $fit SetHisto_OutlierProbability $thisparam($this,histo_outlierprobability)
+
+    if { $thisparam($this,histo_premode) == "None" } {
+	$fit SetHisto_PreprocessingMode 0
+    } elseif { $thisparam($this,histo_premode) == "Positive Only" } {
+	$fit SetHisto_PreprocessingMode 1
+    } else {
+	$fit SetHisto_PreprocessingMode 2
+    }
+
+    
+    if { $thisparam($this,pabic_shim_useinitial) == 1 } {
+	set db [ vtkDoubleArray [ pxvtable::vnewobj ]]
+	$db SetNumberOfTuples 19
+	for { set i 0 } { $i <=18 } { incr i } {
+	    $db SetComponent $i 0 $thisparam($this,pabic_shimval_$i) 
+	}
+	$fit SetInitialCoefficients $db
+	$db Delete
+    }
+    
+    pxtkconsole
+
+    eval "$fit AddObserver ProgressEvent { pxtkprint  \"Sl:\[ $fit GetOutputStatus \] \n\" }"
+    $fit Update
+
+    $outimage ShallowCopyImage [ $fit GetOutput ]
+    $b1image  ShallowCopyImage [ $fit GetBiasField ]
+
+
+    set db [ $fit GetCoefficients ]
+    for { set i 0 } { $i <=18 } { incr i } {
+	set thisparam($this,pabic_shimval_$i) 0.0
+    }
+
+    set maxn 3
+    if { $thisparam($this,pabic_shim_degree) == 3 } {
+	set maxn 18
+    } elseif { $thisparam($this,pabic_shim_degree) == 2 } {
+	set maxn 8
+    }
+	
+    for { set i 0 } { $i <= $maxn } { incr i } {
+	set thisparam($this,pabic_shimval_$i) [ $db GetComponent $i 0 ]
+    }
+
+    $fit Delete
+    WatchOff
+
+    $outimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "poly" ]
+    $outimage CopyImageHeader [ $currentimage GetImageHeader ]
+    $b1image  configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "b1_poly" ]
+    $b1image  CopyImageHeader [ $currentimage GetImageHeader ]
+
+
+    $thisparam($this,pabic_restoredgui) Update
+    $thisparam($this,pabic_biasfieldgui) Update
+    $parent SetResultsFromObject $outimage $this
+
+}
+
+# ----------------------------------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::RunManualShim {  } {
+
+
+    if { [ CheckImage $currentimage "Image" "Manual Bias Field Correction" 1 ] == 0 } { 
+	return 0  
+    }
+    
+
+    WatchOn    
+
+
+    pxtkprint ".... Manual Inhomogeneity Correction\n"
+    set fit [ vtkpxPolynomialBiasFieldCorrection  [ pxvtable::vnewobj ]]
+
+    set db [ vtkDoubleArray [ pxvtable::vnewobj ]]
+    $db SetNumberOfTuples 18
+    $db FillComponent 0 0.0
+    for { set i 0 } { $i <= 5 } { incr i } {
+	$db SetComponent $i 0 $thisparam($this,pabic_shimval_$i) 
+    }
+    set tmp [ $fit ComputeBiasFieldImage [ $currentimage GetImage ] $db  2 $thisparam($this,pabic_min) $thisparam($this,pabic_max) ]
+    puts stdout "Computing Corrected Image"
+    set img [ $fit ComputeMeanPreservingCorrectedImage [ $currentimage GetImage ] $tmp  ]
+    puts stdout "Done ...\n"
+    set outimage [ $thisparam($this,pabic_restoredgui) GetObject ]
+    set b1image  [ $thisparam($this,pabic_biasfieldgui) GetObject ]
+
+    set entropy [ $fit ComputeEntropy $img ]
+
+    pxtkconsole
+    pxtkprint "\nEntropy = $entropy\n"
+
+    $outimage ShallowCopyImage  $img
+    $b1image  ShallowCopyImage  $tmp 
+
+    $db Delete
+    $fit Delete
+    WatchOff
+
+    $outimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "shim" ]
+    $outimage CopyImageHeader [ $currentimage GetImageHeader ]
+
+    $b1image  configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "shim_b1" ]
+    $b1image  CopyImageHeader [ $currentimage GetImageHeader ]
+
+    $thisparam($this,pabic_restoredgui) Update
+    $thisparam($this,pabic_biasfieldgui) Update
+    $parent SetResultsFromObject $outimage $this
+}
+
+# ----------------------------------------------------
+itcl::body pxitclbrainstrip::SimpleSegment {  } {
+    ThresholdImage
+    ErodeMap
+    ConnectMap 1
+    DilateMap
+}
+
+itcl::body pxitclbrainstrip::ThresholdImage {  } {
+
+    if { [ CheckImage $currentimage "Image" "thresholding" 1 ] == 0 } {
+	return
+    }
+    
+    WatchOn
+    
+ #   puts stderr "Beginning to threshold image spacing = [ [ $currentimage GetImage ] GetSpacing ]\n\n\n"
+
+    set castF [ vtkImageCast [ pxvtable::vnewobj ]]
+    $castF SetInput  [ $currentimage GetImage ]
+    $castF SetOutputScalarTypeToFloat
+    $castF Update
+
+    set thresholdF  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+    $thresholdF ThresholdBetween  $thisparam($this,lowthreshold) $thisparam($this,highthreshold)
+    $thresholdF SetInValue    1
+    $thresholdF SetOutValue   0
+    $thresholdF ReplaceInOn
+    $thresholdF ReplaceOutOn
+    $thresholdF SetInput [ $castF GetOutput ]
+    $thresholdF SetOutputScalarTypeToUnsignedChar
+    SetFilterCallbacks $thresholdF   "Thresholding image"
+    $thresholdF Update
+
+#    puts stderr "Done Thresholding image on to processing "
+
+    ProcessMorphologyResults [ $thresholdF GetOutput ]
+    catch { $thresholdF Delete }
+    catch { $castF Delete }
+    WatchOff
+}
+# ----------------------------------------------------------------------------------------------------
+#  
+#    Morphology
+#
+# -------------------------------------------------------------------------------------------
+
+itcl::body pxitclbrainstrip::ErodeMap {  } {
+    
+    if { [ CheckImage $currentmask "Segmentation Mask" "erosion" 1 ] == 0 } {
+	return
+    }
+	
+    WatchOn
+    set erode  [  vtkImageContinuousErode3D [ pxvtable::vnewobj ] ]
+    $erode SetInput [ $currentmask GetImage ]
+    if {  $thisparam($this,gui_morphology2d) == 0  } {
+	$erode SetKernelSize $thisparam($this,gui_morphkernelsize) $thisparam($this,gui_morphkernelsize) $thisparam($this,gui_morphkernelsize)
+    } else {
+	$erode SetKernelSize $thisparam($this,gui_morphkernelsize) $thisparam($this,gui_morphkernelsize) 1
+    }
+    SetFilterCallbacks $erode "Eroding image"
+    $erode Update
+    ProcessMorphologyResults  [ $erode  GetOutput ]
+    catch { $erode Delete }
+    WatchOff
+}
+# -------------------------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::DilateMap {  } {
+    
+    if { [ CheckImage $currentmask "Segmentation Mask" "dilation" 1 ] == 0 } {
+	return
+    }
+    WatchOn
+    
+    set dilate  [  vtkImageContinuousDilate3D [ pxvtable::vnewobj ] ]
+    $dilate SetInput [ $currentmask GetImage ]
+    
+    if {  $thisparam($this,gui_morphology2d) == 0  } {
+	$dilate SetKernelSize $thisparam($this,gui_morphkernelsize) $thisparam($this,gui_morphkernelsize) $thisparam($this,gui_morphkernelsize)
+    } else {
+	$dilate SetKernelSize $thisparam($this,gui_morphkernelsize) $thisparam($this,gui_morphkernelsize) 1
+    }
+    SetFilterCallbacks $dilate "Dilating image"
+
+    $dilate Update
+    ProcessMorphologyResults [   $dilate  GetOutput ]
+    catch { $dilate Delete }
+    WatchOff
+    
+}
+# -------------------------------------------------------------------------------------------    
+itcl::body pxitclbrainstrip::DilateErodeMap {  posval minval  } {
+    
+    if { [ CheckImage $currentmask "Segmentation Mask" "dilation/erosion" 1 ] == 0 } {
+	return
+    }
+    
+    WatchOn
+    
+    set DilateErode  [  vtkImageDilateErode3D [ pxvtable::vnewobj ]  ]
+    $DilateErode SetInput [ $currentmask GetImage ]
+    if {  $thisparam($this,gui_morphology2d) == 0  } {
+	$DilateErode SetKernelSize $thisparam($this,gui_morphkernelsize) $thisparam($this,gui_morphkernelsize) $thisparam($this,gui_morphkernelsize)
+    } else {
+	$DilateErode SetKernelSize $thisparam($this,gui_morphkernelsize) $thisparam($this,gui_morphkernelsize) 1
+    }
+    $DilateErode SetDilateValue $posval
+    $DilateErode SetErodeValue  $minval
+    
+    SetFilterCallbacks $DilateErode "Dilating-Eroding image"
+    $DilateErode Update
+    ProcessMorphologyResults [ $DilateErode  GetOutput ]
+    catch { $DilateErode Delete }
+    WatchOff
+}
+# -------------------------------------------------------------------------------------------    
+itcl::body pxitclbrainstrip::BinaryMedianMap { } {
+	
+    if { [ CheckImage $currentmask "Segmentation Mask" "median filtering" 1 ] == 0 } {
+	return
+    }
+    
+    WatchOn
+    
+    set BMedian  [  vtkpxBinaryImageMedian3D [ pxvtable::vnewobj ]  ]
+    $BMedian SetInput [ $currentmask GetImage ]
+    if {  $thisparam($this,gui_morphology2d) == 0  } {
+	$BMedian SetKernelSize $thisparam($this,gui_morphkernelsize) $thisparam($this,gui_morphkernelsize) $thisparam($this,gui_morphkernelsize)
+    } else {
+	$BMedian SetKernelSize $thisparam($this,gui_morphkernelsize) $thisparam($this,gui_morphkernelsize) 1
+    }
+    SetFilterCallbacks $BMedian "BMedian-Filtering image"
+    $BMedian Update
+    ProcessMorphologyResults [ $BMedian GetOutput ]
+    catch { $BMedian Delete }
+    WatchOff
+}
+# -------------------------------------------------------------------------------------------        
+itcl::body pxitclbrainstrip::ConnectMap { mode  } {
+    
+    if { [ CheckImage $currentmask "Segmentation Mask" "connectivity" 1 ] == 0 } {
+	return
+    }
+
+
+    RequestUpdatedSeed 0
+    
+    
+    set seedF  [  vtkImageSeedConnectivity [ pxvtable::vnewobj ] ]
+    $seedF SetInput [ $currentmask GetImage ]
+
+    pxtkprint "\n Seed: $thisparam($this,seedx) $thisparam($this,seedy) $thisparam($this,seedz) mode=$mode\n"
+    $seedF AddSeed $thisparam($this,seedx) $thisparam($this,seedy) $thisparam($this,seedz)
+    $seedF SetDimensionality 3
+
+    if { $mode == 1 } { 
+	$seedF SetInputConnectValue 1
+	$seedF SetOutputConnectedValue 1
+	$seedF SetOutputUnconnectedValue 0 
+    } else {
+	$seedF SetInputConnectValue      0
+	$seedF SetOutputConnectedValue   0
+	$seedF SetOutputUnconnectedValue 1
+    }
+
+    SetFilterCallbacks $seedF "Connecting image mode=$mode seed=$thisparam($this,seedx) $thisparam($this,seedy) $thisparam($this,seedz)"
+    $seedF Update
+    ProcessMorphologyResults [ $seedF GetOutput ]
+    catch { seedF Delete }
+    WatchOff
+}
+# -------------------------------------------------------------------------------------------        
+itcl::body pxitclbrainstrip::ProcessMorphologyResults { img args } { 
+
+    if { [ CheckImage $currentimage "Image" "overlay" 1 ] == 0 } {
+	return
+    }
+    set backup 1
+    if { [ llength $args ] > 0 } {
+	if { [ lindex $args 0 ] == "NoBackup" } {
+	    set backup 0 
+	}
+    }
+
+    if { $backup == 1 } {
+	$oldmask ShallowCopy $currentmask
+    }
+
+#    puts stderr "------------------------------------------------------------------------------------------------------"
+#    puts stderr "Going to shallow copy  mask = [ [ $currentmask GetImage ] GetSpacing ] , result = [ $img GetSpacing ]"
+
+    $currentmask ShallowCopyImage $img
+
+
+    # puts stderr done with current mask
+    #    $currentmask Save "test.nii.gz"
+#    exit
+
+    if { [ CheckImage $currentmask "Segmentation Mask" "overlay" 1 ] == 0 } {
+	return
+    }	
+
+    DisplayMorphologyResults
+}
+
+itcl::body pxitclbrainstrip::DisplayMorphologyResults {  } { 
+
+    
+
+    if { $thisparam($this,gui_displaymask) == 0 } {
+	WatchOn
+	set mask  [  vtkpxImageMask [ pxvtable::vnewobj ] ]
+	$mask SetInput [ $currentimage GetImage ]
+	$mask SetMask  [ $currentmask GetImage ]
+	#$mask SetMaskedOutputValue 1
+	SetFilterCallbacks $mask "Creating Overlay"
+	$mask Update
+	$currentresults ShallowCopyImage [ $mask GetOutput ]
+	catch { $mask Delete }    
+	WatchOff
+	$parent SetResultsFromObject  $currentresults $this
+    } else {
+	$currentresults ShallowCopy $currentmask
+	if { [ $parent  CanAcceptMask ] } {
+	    $parent SetMaskFromObject $currentresults $this
+	} else {
+	    $parent SetResultsFromObject  $currentresults $this
+	}	
+    }
+}
+
+# ----------------------------------------------------------------------------
+
+itcl::body pxitclbrainstrip::UndoLastMorphologyOperation {  } {
+	
+    ProcessMorphologyResults [ $oldmask GetImage ] "NoBackup"
+}
+# -------------------------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::SetImage { img  } {
+	
+    DelayedInitialize
+    
+    $currentimage ShallowCopy $img
+    $currentresults UnLoad
+    $currentresults CopyImageHeader [ $currentimage GetImageHeader ]
+    $currentmask UnLoad
+    $currentmask CopyImageHeader [ $currentimage GetImageHeader ]
+    $oldmask UnLoad
+    $oldmask CopyImageHeader [ $currentimage GetImageHeader ]
+
+    set dim2 [ [ $currentimage GetImage ] GetDimensions ]
+    set thisparam($this,seedx)  [expr [lindex $dim2 0 ] /2 ]
+    set thisparam($this,seedy)  [expr [lindex $dim2 1 ] /2 ]
+    set thisparam($this,seedz)  [expr [lindex $dim2 2 ] /2 ]
+
+    set range [ [ [ [ $currentimage GetImage ] GetPointData] GetScalars] GetRange ]
+    set lowrange  [ expr [ lindex $range 0] -1.0 ]
+    set highrange [ expr [ lindex $range 1] +1.0 ]
+
+    # Set Segmentation Algorithm Parameters 
+    if { $initialized == 1 } {
+	$thisparam($this,gui_lowthreshold)  configure -from $lowrange -to $highrange
+	$thisparam($this,gui_highthreshold) configure -from $lowrange -to $highrange
+    }
+    
+    set thisparam($this,lowthreshold)  [ expr  0.05*($highrange-$lowrange) + $lowrange ] 
+    set thisparam($this,highthreshold)  $highrange 
+
+}
+# -------------------------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::RequestUpdatedSeed { { force 1 }  } {
+
+    if { $parent == 0 } { return 0 }
+    if { $force == 0 &&  $thisparam($this,seedautoupdate) == 0 } {
+	return
+    }
+
+    set done 0
+
+    set currentpoint [ $parent cget -currentpoint ]
+    scan $currentpoint "%f %f %f " thisparam($this,seedx) thisparam($this,seedy) thisparam($this,seedz)
+    
+    set dim2 [ [ $currentimage GetImage ] GetDimensions ]
+    set indlist [ list x y z ]
+    for { set i 0 } { $i <=2 } { incr i } {
+	set a [ lindex $indlist $i ]
+	set thisparam($this,seed$a) [ expr round ($thisparam($this,seed$a)) ]
+	if { $thisparam($this,seed$a) < 0 } {
+	    set thisparam($this,seed$a) 0
+	} elseif { $thisparam($this,seed$a) >= [ lindex $dim2 $i ] } {
+	    set thisparam($this,seed$a) [ lindex $dim2 $i ]
+	}
+
+    }
+
+
+    return 1
+}
+# ----------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::EnsureCurrentImageIsSaved { operation } {
+
+
+    set exists [ $currentimage DoesImageExistOnDisk ]
+    if { $exists == 0 } {
+	set ok [ pxtclutil::Question "The current image has not been saved\n Would you like to save the current image\n (No Cancels $operation)" ]
+	if { $ok == 0 } {
+		return 0
+	    }
+	$currentimage Save
+    }
+
+    set exists [ $currentimage DoesImageExistOnDisk ]
+    if { $exists == 0 } {
+	set ok [ pxtclutil::Warning "The current image has not been saved\n as $fname does not exist!\n Canceling $operation!" ]
+	return 0
+    }
+
+    set fname [ $currentimage cget -filename ]
+    set outname $fname
+    set ext [ file extension $outname ]
+    if { $ext == ".gz" } {
+	set outname [ file rootname $outname ]
+	set ext [ file extension $outname ]
+    }
+    if { $ext == ".nii" || $ext == ".hdr"  } {
+	set outname [ file rootname $outname ]
+    }
+    
+    return  [ list $fname $outname ]
+}
+
+itcl::body pxitclbrainstrip::RunBET { mode } {
+    
+    set lst [ $this EnsureCurrentImageIsSaved "Brain Segmentation" ]
+    if {  [ lindex $lst 0 ] == 0 } {
+	return 0
+    }
+    
+    set fname [ lindex $lst 0 ]
+    set outname [ lindex $lst 1 ]
+
+    set spa [ [ $currentimage GetImage ] GetSpacing ]
+    set ori [ [ $currentimage GetImage ] GetOrigin ]
+
+    RequestUpdatedSeed
+
+
+    set p(0) [ expr $thisparam($this,seedx) *  [ lindex $spa 0 ] + [ lindex $ori 0 ] ] 
+    set p(1) [ expr $thisparam($this,seedy) *  [ lindex $spa 1 ] + [ lindex $ori 1 ] ] 
+    set p(2) [ expr $thisparam($this,seedz) *  [ lindex $spa 2 ] + [ lindex $ori 2 ] ] 
+
+    set cmdline "$thisparam($this,fslbet) $fname ${outname}_stripped -v -o -f $thisparam($this,bet_fth) -g $thisparam($this,bet_gth)"
+
+    if { $thisparam($this,bet_center) } {
+	set cmdline "${cmdline} -c $p(0) $p(1) $p(2)"
+    }
+
+    if { $thisparam($this,bet_radius) > 0 } {
+	set cmdline "$cmdline -r $thisparam($this,bet_radius)"
+    }
+ 
+
+    set thisparam($this,bet_outputroot) $outname
+    $runcommandgui SetCommand  $cmdline
+    $runcommandgui Show
+    $runcommandgui SetCallback  "$this BETDone"
+    if { $mode > 0 } {
+	$runcommandgui Run "Stripping Brain"
+    }
+    
+
+}
+
+
+
+
+itcl::body pxitclbrainstrip::BETDone { } {
+    
+    set out $thisparam($this,bet_outputroot) 
+    set outb ${out}_stripped
+    set outo ${out}_stripped_overlay
+
+    set img1 [ $thisparam($this,bet_braingui) GetObject ]
+    $img1 Load ${outb}.hdr
+    $this FixOriginSpacingOrientation $img1
+    $thisparam($this,bet_braingui)  Update
+
+    set img2 [ $thisparam($this,bet_overlaygui) GetObject ]
+    $img2 Load ${outo}.hdr
+    $this FixOriginSpacingOrientation $img2
+    $thisparam($this,bet_overlaygui) Update
+
+    # This is a temporary file -- delete it 
+    catch { file delete ${outo}.img }
+    catch { file delete ${outo}.hdr }
+    catch { file delete ${outb}.img }
+    catch { file delete ${outb}.hdr }
+
+    $parent SetResultsFromObject $img1 $this
+    
+    $this GenerateMaskFromBETOutput 0
+
+    set cast [ vtkImageShiftScale [ pxvtable::vnewobj ]]
+    $cast SetInput [ $img1 GetImage ]
+    $cast SetScale 1.0
+    $cast SetOutputScalarType [ [ $currentimage GetImage ] GetScalarType ] 
+    $cast Update
+    $img1 ShallowCopyImage [ $cast GetOutput ]
+    $cast Delete
+
+    set fname [ $currentimage cget -filename ]
+    set ext [ file extension $fname ]
+    set ext2 ""
+    if { $ext == ".gz" } {
+	set ext   [ file extension [ file rootname $fname ]]
+	set fname [ file rootname $fname ]
+	set ext2 ".gz"
+    }
+    if { $ext == ".nii" } {
+	$img1 Save ${out}_stripped.nii${ext2}
+	$img2 configure -filename ${out}_stripped_overlay.nii${ext2}
+    } else {
+        $img1 Save ${out}_stripped.hdr
+	$img2 configure -filename ${out}_stripped_overlay.hdr
+    }
+    $thisparam($this,bet_braingui)  Update
+    $thisparam($this,bet_overlaygui)  Update
+    pxtclutil::Info "Brain Extraction Done\n (Mask for Morphology Updated Also)\n"
+
+}
+
+itcl::body pxitclbrainstrip::FixOriginSpacingOrientation { newimg } {
+
+    set spacing  [ [ $currentimage GetImage ] GetSpacing ]
+    set origin   [ [ $currentimage GetImage ] GetOrigin ]
+
+    $newimg CopyImageHeader [ $currentimage GetImageHeader ]
+    [ $newimg GetImage ] SetSpacing [ lindex $spacing 0 ] [ lindex $spacing 1 ] [ lindex $spacing 2 ]
+    [ $newimg GetImage ] SetOrigin [ lindex $origin 0 ] [ lindex $origin 1 ] [ lindex $origin 2 ]
+}
+
+
+itcl::body pxitclbrainstrip::GenerateMaskFromBETOutput { mode } {
+    
+
+    set img1 [ $thisparam($this,bet_braingui) GetObject ]
+    if { [ CheckImage $img1 "Brain Extraction Results" "Create Mask from BET Output" 1 ] == 0 } {
+	return
+    }
+
+
+    WatchOn
+    set thresholdF  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+    $thresholdF ThresholdBetween  1 1000000
+    $thresholdF SetInValue    1
+    $thresholdF SetOutValue   0
+    $thresholdF ReplaceInOn
+    $thresholdF ReplaceOutOn
+    $thresholdF SetInput [ $img1 GetImage ]
+    $thresholdF SetOutputScalarTypeToUnsignedChar
+    SetFilterCallbacks $thresholdF   "Thresholding brain image"
+    $thresholdF Update
+
+    $oldmask ShallowCopy $currentmask
+    if { $mode == 0 } {
+	$currentmask ShallowCopyImage  [ $thresholdF GetOutput ]
+    }  else {
+	ProcessMorphologyResults [ $thresholdF GetOutput ]
+    }
+    WatchOff
+    catch { $thresholdF Delete }
+    
+    
+
+}
+# ----------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::RunFAST { mode  } {
+    
+    set lst [ $this EnsureCurrentImageIsSaved "Brain Segmentation" ]
+
+    if {  $lst == 0 } {
+	return 0
+    }
+
+    set fname [ lindex $lst 0 ]
+    set outname [ lindex $lst 1 ]
+    
+    set imgtype 3
+    if { $thisparam($this,fast_type) == "T2-Weighted" } {
+	set imgtype 2
+    } elseif { $thisparam($this,fast_type) == "T1-Weighted" } {
+	set imgtype 1
+    }
+    set numc    $thisparam($this,fast_numclasses) 
+    
+    set cmdline "$thisparam($this,fslfast) -c $numc -t$imgtype -v 5 -or -op -od ${outname}_segm $fname |& tee "
+    puts stderr $cmdline
+
+    set thisparam($this,fast_outputroot) ${outname}_segm
+    set thisparam($this,fast_outputclasses) $numc
+    $runcommandgui SetCommand  $cmdline
+    $runcommandgui Show
+    $runcommandgui SetCallback  "$this FASTDone"
+    if { $mode > 0 } {
+	$runcommandgui Run "Segmenting Brain"
+    }
+    
+}
+
+itcl::body pxitclbrainstrip::FASTDone { } {
+    
+    set out  $thisparam($this,fast_outputroot) 
+    set img2 [ $thisparam($this,fast_segmentedimagegui) GetObject ]
+   
+    set outo ${out}_seg
+    	
+    if { [ file exists ${outo}.hdr ] } {
+	$img2 Load ${outo}.hdr
+    } else { 
+	tk_messageBox -type ok -title Error! -message "Could not find $outo"
+	return
+    }
+
+    set exp ${out}*
+    foreach filename [glob $exp] {
+	pxtkprint "deleting $filename \n"
+	file delete $filename
+    }
+     
+    $this FixOriginSpacingOrientation $img2
+    set fname [ $currentimage cget -filename ]
+    set ext [ file extension $fname ]
+    set ext2 ""
+    if { $ext == ".gz" } {
+	set ext   [ file extension [ file rootname $fname ]]
+	set fname [ file rootname $fname ]
+	set ext2 ".gz"
+    }
+    if { $ext == ".nii" } {
+	$img2 Save ${out}seg_classification.nii${ext2}
+    } else {
+        $img2 Save ${out}seg_classification.hdr
+    }
+    
+    $thisparam($this,fast_segmentedimagegui) Update
+    pxtclutil::Info "Brain Segmentation Done\n"
+
+    $parent SetResultsFromObject $img2 $this
+}
+
+
+itcl::body pxitclbrainstrip::FASTStatistics { mode } {
+
+    set img $currentimage
+    if { [ $currentimage GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No image  in memory! Cannot compute Gray/White statistics!"
+	return 0 
+    }
+
+    set img1 [ $thisparam($this,fast_segmentedimagegui) GetObject ]
+    if { [ CheckImage $img1 "Brain Segmentation Results" "Generate Gray/White Statistics" 1 ] == 0 } {
+	return 0
+    }
+
+    set results [ vtkFloatArray [ pxvtable::vnewobj ]]
+    set util    [ vtkpxHistogramSegmentation [ pxvtable::vnewobj ]]
+    $util ComputeSegmentedMapStatistics [ $img GetImage ] [ $img1 GetImage ] $results 
+
+    pxtkconsole
+    pxtkprint "\n ---------------------------------------------------------\n"
+    pxtkprint "Current Image Statistics [ file tail [ $currentimage cget -filename ]]\n\n"
+
+    set numcomp [  [ $currentimage GetImage ] GetNumberOfScalarComponents ]
+    set numlabels [ $results GetNumberOfTuples ]
+    
+    for { set c 0 } { $c < $numcomp } { incr c } {
+	if { $numcomp > 1 } {
+	    pxtkprint "Frame [ expr $c +1 ]\n"
+	}
+	set indexv [ expr $c*4 ]
+	set indexm [ expr $c*4+2 ]
+	set indexs [ expr $c*4+3 ]
+
+	for { set l 0 } { $l < $numlabels } { incr l } {
+	    pxtkprint [ format "label = %2d  volume=%.2f cc  mean=%.2f  std=%.2f\n" [ expr $l +1 ]  [ expr [ $results GetComponent $l $indexv ]*0.001 ] [ $results GetComponent $l $indexm ] [ $results GetComponent $l $indexs ] ]
+	}
+    }
+    $util Delete
+
+    if { $mode == "cleanup" } {
+        $results Delete
+	return 0
+    }
+
+    return $results
+
+}
+
+itcl::body pxitclbrainstrip::FASTNormalizeBrain { } {
+
+    set results [ FASTStatistics "test" ]
+    if { $results == 0 } {
+	return 0
+    }
+
+    puts stdout "Onto normalizing brain intensities ...."
+
+    set numcomp   [ $results GetNumberOfComponents ]
+    set numlabels [ $results GetNumberOfTuples ]
+
+    puts stdout "Numcomp=$numcomp  numlabels=$numlabels "
+
+    if { $numcomp == 4 && $numlabels == 3 } {
+
+	set csf_m   [ $results GetComponent 1 2 ]
+	set csf_s   [ $results GetComponent 1 3 ]
+	set gray_m  [ $results GetComponent 2 2 ]
+	set gray_s  [ $results GetComponent 2 3 ]
+	set white_m [ $results GetComponent 3 2 ]
+	set white_s [ $results GetComponent 3 3 ]
+
+	set r  [ [ [ [$currentimage GetImage ] GetPointData ] GetScalars ] GetRange ]
+
+	set upper [ expr $white_m + 2.0*$white_s ]
+        if { $upper > [ lindex $r 1 ] } {
+	    ::pxtclutil::Info "Image is well adjusted no need to normalize it\n"
+	} else {
+	    set scalefactor [ expr 200.0/$gray_m ]
+	    set sc_upper    [ expr $scalefactor * $upper ]
+
+	    pxtkprint "Scalefactor = $scalefactor = (200/$gray_m) scaled_upper=$sc_upper "
+
+	    set map [ vtkDouble [ pxvtable::vnewobj ]]
+	    $map SetNumberOfComponents 3
+	    $map SetNumberOfTuples 3
+
+	    $map SetComponent 0 0 [ expr $gray_m * 0.5 ]
+	    $map SetComponent 0 1 0.0
+	    $map SetComponent 0 2 0.0
+    
+	    $map SetComponent 1 0 $upper
+	    $map SetComponent 1 1 0.0
+	    $map SetComponent 1 2 $scalefactor 
+
+	    $map SetComponent 2 0 [ expr [ lindex $r 1 ] + 10 ] 
+	    $map SetComponent 2 1 $sc_upper
+	    $map SetComponent 2 2 0.0
+
+	    for { set i 0 } { $i <= 2 } { incr i } {
+		puts -nonewline stdout "Row $i:"
+		for { set j 0 } { $j <= 2 } { incr j } {
+		    puts -nonewline stdout "[ $map GetComponent $i $j ],"
+		}
+		puts stdout ""
+	    }
+
+	    set sh  [ vtkpxImageAlgebra [ pxvtable::vnewobj ]  ]
+	    $sh SetInput [ $currentimage GetImage ]
+	    $sh SetMap $map
+	    $sh SetOutputScalarTypeToShort
+	    SetFilterCallbacks $sh "Normalizing Image"
+	    $sh Update
+    
+	    pxtkprint "Saturating at $upper"
+
+	    $currentresults ShallowCopyImage [ $sh GetOutput ] 
+	    ProcessImageResults  "Norm" 
+	    catch { $sh Delete }
+	    $map Delete
+	    WatchOff
+	}
+    } else {
+	::pxtclutil::Warning "Failed to Normalize Brain using FAST Output"
+    }
+
+    $results Delete
+    
+    return 1
+}
+
+# ----------------------------------------------------------------------------
+itcl::body pxitclbrainstrip::AddToMenuButton { mb args } {
+
+    global pxtcl_pref_array
+
+    eval "$mb add command -command {$this ShowWindow \"Math_Morphology\" } -label \"Math_Morphology\" "
+    eval "$mb add command -command {$this ShowWindow \"Histogram Segmentation\" } -label \"Histogram Segmentation\" "
+    eval "$mb add command -command {$this ShowWindow \"Bias Field Correction\" } -label \"Bias Field Correction\" "
+    if { $enable_mousemode == 1 } {
+	eval "$mb add command -command {$this ShowWindow \"Exponential Fit\"} -label \"Exponential Fit\" "
+    }
+    
+    if { $enable_fsl == 1 } {
+
+	if { $thisparam($this,fslbet) !=  ""  ||  $thisparam($this,fslfast) !=  "" } {
+	    $mb add separator
+	    if { $thisparam($this,fslbet) !=  "" } {
+		eval "$mb add command -command {$this ShowWindow \"Brain Extraction Tool\" } -label \"Brain Extraction Tool\"  " 
+	    }
+	    if { $thisparam($this,fslfast) !=  "" } {
+		eval "$mb add command -command {$this ShowWindow \"Gray/White Segmentation\" } -label \"Gray/White Segmentation\"  "
+	    }
+	} else {
+	    $mb add separator
+	    eval "$mb add command -command { pxtclutil::Info \"FSL installation not found, make sure bet or bet2 and fast are in your path.\" } -label \"FSL Not Found!\"  " 
+	}
+    }
+    
+    if { $has_singlelevelset == 1 } {
+	$mb add separator
+	eval "$mb add command -command {$this ShowWindow \"Levelset Segmentation\" } -label \"Levelset Segmentation\" "
+    }
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclcreatesolidcontrol.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclcreatesolidcontrol.tcl
new file mode 100644
index 0000000..4168158
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclcreatesolidcontrol.tcl
@@ -0,0 +1,267 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclsplinestackobjectmap.tcl,v 1.1 2003/03/03 20:17:28 papad Exp $	
+
+package provide pxitclcreatesolidcontrol 1.0
+
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  Iwidgets 4.0
+
+itcl::class pxitclcreatesolidcontrol {
+
+    inherit pxitclbaseimagecontrol
+
+    private common thisparam
+    protected variable base4dviewer
+    protected variable numberofsurfaces
+    protected variable solid 0
+    protected variable solidactorlist ""
+    protected variable rendererlist   ""
+
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+	set solid [ vtkpxFemSolid [ pxvtable::vnewobj ]]
+    } {
+    }
+
+    public method Initialize   { widget base4dviewer }
+    public method CreateSolid  { }
+    public method LoadSolid    { }
+    public method SaveSolid    { }
+    public method ToggleDisplay { }
+    public method DisplaySolid { }
+}
+
+
+itcl::body pxitclcreatesolidcontrol::Initialize { widget surfaceed } {
+	
+    set base4dviewer $surfaceed
+    
+    if { $initialized == 1 } { return $basewidget }
+
+    set basewidget $widget
+    toplevel $basewidget; wm withdraw $basewidget
+    wm geometry $basewidget 450x100
+
+
+    set numberofsurfaces [ $base4dviewer cget -numberofsurfaces ]
+
+    set thisparam($this,inner_surface) 1
+    set thisparam($this,outer_surface) 2
+    set thisparam($this,numpoints) 35
+    set thisparam($this,numstacks) 4
+    set thisparam($this,skipslices) 2
+    set thisparam($this,bias) 1
+
+    set surlist ""
+    for { set k 0 } { $k < $numberofsurfaces } { incr k } {
+	lappend surlist [ expr $k + 1 ]
+    }
+
+    set w [ frame $basewidget.top -bg darkgray -width 10 ]
+    pack $w -side top -expand t -fill x -padx 5 
+  
+    frame $w.s1 ; frame $w.s2 ; pack $w.s1 $w.s2 -side top -expand f -fill x
+
+    set cw [ [ iwidgets::labeledwidget  $w.s1.i -labeltext "Inner Surface:"] childsite ]
+    pack $w.s1.i -side left -expand f -fill x -padx 10
+    eval "tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,inner_surface) ] $surlist"
+    pack $cw.optmenu  -expand f -fill x
+
+    set cw [ [ iwidgets::labeledwidget  $w.s1.o -labeltext "Outer Surface:"] childsite ]
+    pack $w.s1.o -side left -expand f -fill x -padx 10
+    eval "tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,outer_surface) ] $surlist"
+    pack $cw.optmenu  -expand f -fill x
+
+
+
+    set base $w.s2
+
+    set k 0 
+    iwidgets::entryfield $base.$k -labeltext "Points:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,numpoints) ] -relief sunken 
+    pack $base.$k -side left -expand f -fill x  ;incr k
+
+
+    iwidgets::entryfield $base.$k -labeltext "Layers:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,numstacks) ] -relief sunken 
+    pack $base.$k -side left -expand f -fill x  ;incr k
+
+
+    iwidgets::entryfield $base.$k -labeltext "Skip Slices:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,skipslices) ] -relief sunken 
+    pack $base.$k -side left -expand f -fill x  ;incr k
+
+
+    iwidgets::entryfield $base.$k -labeltext "Endo Bias(0,1)"  -width 1 -validate real -textvariable [ itcl::scope thisparam($this,bias) ] -relief sunken 
+    pack $base.$k -side left -expand f -fill x  ;incr k
+
+	
+    frame $w.com; 
+    pack $w.com -side top -fill x
+    eval "button $w.com.b1 -text Create! -command { $this CreateSolid  } "
+    eval "button $w.com.b2a -text Load -command { $this LoadSolid } "
+    eval "button $w.com.b2b -text Save -command { $this SaveSolid } "
+    eval "button $w.com.b2c -text Show/Hide -command { $this ToggleDisplay } "
+    eval "button $w.com.b3 -text Close -command {  wm withdraw $basewidget }"
+    pack $w.com.b1 $w.com.b2a $w.com.b2b $w.com.b2c $w.com.b3 -side left -fill x -expand t   
+
+    entry $w.base -textvariable [ itcl::scope thisparam($this,results) ] -relief raised -state disabled  -fg white -bg black
+    pack $w.base -side bottom -fill x -expand f
+
+    set initialized 1
+    SetTitle "Surface Solid Control"
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget 
+    
+}
+
+
+itcl::body pxitclcreatesolidcontrol::CreateSolid { } {
+
+    set endo [ $base4dviewer GetTstack [ expr $thisparam($this,inner_surface)-1 ] ]
+    set epi  [ $base4dviewer GetTstack [ expr $thisparam($this,outer_surface)-1 ] ]
+       
+    
+
+    set thisparam($this,results) "Geneating Solid $thisparam($this,numpoints) $thisparam($this,numstacks) $thisparam($this,bias) 1.0 $thisparam($this,skipslices)"
+    WatchOn
+
+    set ok [ $solid GenerateHexahedralSolid $endo $epi $thisparam($this,numpoints) $thisparam($this,numstacks) $thisparam($this,bias) 1.0 $thisparam($this,skipslices) ]
+    WatchOff
+    if { $ok == 0 } {
+	pxtclutil::Warning "Failed to Generate Solid!"
+	return 0
+    }
+    
+    SetTitle "Surface Solid Control \[ new solid \] "
+    DisplaySolid 
+    return 1
+}
+
+itcl::body pxitclcreatesolidcontrol::ToggleDisplay { } {
+
+    if { [ llength $rendererlist ] > 0 } {
+	for { set i 0 } {$i < [ llength $rendererlist ] } { incr i } {
+	    set a [ lindex $solidactorlist $i ]
+	    $a SetVisibility [ expr 1 - [ $a GetVisibility ] ]
+	}
+	[ [ lindex $rendererlist 0 ] GetRenderWindow ] Render
+    }
+}
+
+itcl::body pxitclcreatesolidcontrol::DisplaySolid { } {
+
+
+    if { [ llength $rendererlist ] > 0 } {
+	for { set i 0 } {$i < [ llength $rendererlist ] } { incr i } {
+	    set r [ lindex $rendererlist $i ]
+	    set a [ lindex $solidactorlist $i ]
+	    catch { $r RemoveActor $a ; $a Delete
+	    }
+	}
+    }
+
+    set thisparam($this,results) "Nodes = [ $solid GetNumberOfNodes ], Elements = [ $solid GetNumberOfElements]"
+	    
+    set rendererlist ""
+    set solidactorlist ""
+    $solid Update
+
+    for { set i 0 } { $i <= 3 } { incr i } {
+	set renderer [ [ [ $base4dviewer GetViewer ] GetMultiRenderer $i ] GetRenderer ]
+	lappend rendererlist $renderer
+	
+	
+	set map [ vtkPolyDataMapper [ pxvtable::vnewobj ]]
+	$map SetInput [ $solid GetOutput ]
+	set solidactor [ vtkActor  [ pxvtable::vnewobj ]]
+	$solidactor SetMapper $map
+	$map Delete
+
+	[ $solidactor GetProperty ] SetColor 1.0 1.0 0.0
+
+	if { $i < 3 } {
+	    [ $solidactor GetProperty ] SetLineWidth 2.0
+	    [ $solidactor GetProperty ] SetAmbient 1.0
+	    [ $solidactor GetProperty ] SetDiffuse 0.0
+	    [ $solidactor GetProperty ] SetSpecular 0.0
+	    [ $solidactor GetProperty ] SetRepresentationToWireframe
+	} else {
+	    
+	}
+	$renderer AddActor $solidactor
+	lappend solidactorlist $solidactor
+    }
+    [ [ lindex $rendererlist 0 ] GetRenderWindow ] Render
+}
+
+itcl::body pxitclcreatesolidcontrol::LoadSolid { } {
+
+    set typelist { 
+	{"Solid  file" {.sld}} 
+	{"All Files" {*}}
+    }
+	    
+    set fname [tk_getOpenFile -title "Load Solid" -filetypes $typelist]
+    
+    if { [string length $fname ] < 2 } { return 0 }
+    if { [ file exists $fname ] == 0 } { return 0 }
+
+    if { [ $solid Load $fname ] > 0 } {
+	SetTitle "Surface Solid Control [ file tail $fname]"
+	DisplaySolid
+    }
+    
+}
+
+itcl::body pxitclcreatesolidcontrol::SaveSolid { } {
+
+    set typelist { 
+	{"Solid  file" {.sld}} 
+	{"All Files" {*}}
+    }
+	    
+    set fname [tk_getSaveFile -title "Save Solid" -filetypes $typelist]
+    
+    if { [string length $fname ] < 2 } { return 0;   }
+
+    if { [ $solid Save $fname ] > 0 } {
+	SetTitle "Surface Solid Control [ file tail $fname]"
+    }
+
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclcsigadget.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclcsigadget.tcl
new file mode 100644
index 0000000..414d43e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclcsigadget.tcl
@@ -0,0 +1,1056 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+package provide pxitclcsigadget 1.0
+
+# 	$Id: pxitclcsigadget.tcl,v 1.2 2004/02/03 17:36:31 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+package require  vtkpxcontrib 1.1
+package require  labelframe   1.0
+package require  pxtclutil    1.0
+package require  pxvtable     1.0
+package require  pxtclhelp    1.0
+package require  Itcl         3.2
+package require  Iwidgets     4.0
+package require  pxitclimage            1.0
+package require  pxitcltransform        1.0
+package require  pxitclsubjectentry     1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitclbaseimageviewer  1.0
+# ----------------------------------------------------------------------------------------------
+
+itcl::class pxitclcsigadget {
+
+    inherit pxitclbaseimagecontrol
+
+    # Generic Stuff 
+    private   common   thisparam        
+    protected variable setupfilename   "subject.csi"
+    
+
+    # Subject Specific
+    protected variable anat_control    0
+    protected variable conv_control   0
+    protected variable raw_control   0
+    protected variable pmap_control   0
+    protected variable refx_control    0
+    protected variable smooth_control1  0
+    protected variable smooth_control2  0
+
+
+    protected variable second_viewer   0
+
+    protected variable image_controllist ""
+    protected variable xform_controllist ""
+
+    protected variable overlaytool     0
+    public    variable electrodetool   0
+
+    constructor { par args } {
+	pxitclbaseimagecontrol::constructor $par 
+    } {
+
+	if { [ llength $args] > 0  } {
+	    set second_viewer [ lindex $args 0 ]
+	}
+	InitializeCsiGadget
+
+	set overlaytool [ [ pxitcloverlaytoolplus \#auto $this ] GetThisPointer ]
+	$overlaytool configure -disable_colormapchoice 1
+    }
+
+    private method InitializeCsiGadget { } 
+    public method Initialize { widget }
+    public method DelayedInitialize { }
+
+
+    public method AddToMenuButton { mb args } 
+    public method AddToMenuButtonLite { mb args } 
+    public method SetResultsFromObject { img obj  } 
+    public method SetLookupTable       { colormap }
+    public method SetLookupTableMode   { index }
+    
+    # ----------------------------
+    # Setup Stuff
+    # ----------------------------
+    public method LoadSetup { args } 
+    public method SaveSetup { args } 
+    public method ReadExtraInfo { fname } 
+    protected method GetFileElement { fileid } 
+
+    # ----------------------------
+    # Computational Stuff
+    # ----------------------------
+    public method ComputeSmooth    { } 
+    public method SampleElectrodes { args } 
+
+    # ---------------------------
+    # Subject Specific Callbacks
+    # ---------------------------
+
+    public method VerifyRegistrationCallback { mode args }
+    public method VerifyRegistration { imgcontrol1 imgcontrol2 xformcontrol }
+
+    protected method CreateImageControl     { widget }
+    protected method CreateImportControl    { widget }
+    protected method CreateTransformControl { widget }
+    protected method CreateOverlayControl   { widget }
+    protected method CreateSamplingControl     { widget }
+
+    public    method SetOverlayToolInputs { } 
+
+    public    method UpdateFromRegistration { mmvutil } 
+    public    method UpdateFromRegistrationDone { mmvutil } 
+
+
+    # -------------------------------
+    # Import Stuff
+    # -------------------------------
+    public   method BrowseImport { mode } 
+    public   method RunImport    { } 
+    public   method ResetImport  { } 
+
+}
+
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclcsigadget::InitializeCsiGadget { } {
+    
+
+    set refx_control [ [  pxitcltransformGUI \#auto ] GetThisPointer ]
+    $refx_control configure -description "Transformation Anatomical->CSI Conventional"
+
+    set anat_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $anat_control configure -description "Anatomical (3D) Image"
+
+    set conv_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $conv_control configure -description "Conventional Image"
+
+    set raw_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $raw_control configure -description "Raw CSI Image"
+
+    set pmap_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $pmap_control configure -description "PMAP CSI Image"
+
+    set smooth_control1 [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $smooth_control1 configure -description "Normalized Smooth 1"
+
+    set smooth_control2 [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $smooth_control2 configure -description "Normalized Smooth 2"
+
+    lappend itclobjectlist $refx_control $anat_control $conv_control $raw_control   $pmap_control $smooth_control1 $smooth_control2
+
+    set thisparam($this,overlayviewer) "Reference"
+    if { $second_viewer !=0 } {
+	set thisparam($this,overlayviewer) "Transform"
+    }
+
+    set thisparam($this,overlayanatomy) "3D Anatomical" 
+    set thisparam($this,overlayfunction) "Raw-CSI"
+    set thisparam($this,autosave) 1
+    set thisparam($this,smooth_sigma) 2.0
+    set thisparam($this,smooth_control) 1
+    set thisparam($this,smooth_sigma1) 0.0
+    set thisparam($this,smooth_sigma2) 0.0
+
+    set thisparam($this,csi_categories) "row\tcolumn\tdelta\tpgm\tratio\tCh\tCr\tNAA"
+    set thisparam($this,csi_scalefactors) "1000\t1000\t1000\t.001\t.001\t.001"
+    set thisparam($this,autosavesetup) 1
+
+    set thisparam($this,csi_importinplane) 1.0
+    set thisparam($this,csi_importslice)   1.25
+    set thisparam($this,csi_importscout) ""
+    set thisparam($this,csi_outputstem) ""
+
+
+    lappend image_controllist $anat_control $conv_control $raw_control $pmap_control $smooth_control1 $smooth_control2
+    lappend xform_controllist $refx_control 
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclcsigadget::SetResultsFromObject { img obj  } {
+
+    if { [ $img GetImageSize ] < 2 } {	
+	return 0    
+    }
+    
+    if { $obj == $overlaytool && $parent !=0 } {
+
+	if {$thisparam($this,overlayviewer) == "Transform" && $second_viewer !=0 } {
+	    $second_viewer SetResultsFromObject $img $this
+	} else {
+	    $parent SetResultsFromObject $img $this
+	}
+    } else {
+        SetResults $img
+    }
+    return 1
+}
+
+# ---------------------------------------------------------------------------
+#  Lookup Table Stuff 
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclcsigadget::SetLookupTable { colormap } {
+    
+    set v $parent
+    if {$thisparam($this,overlayviewer) == "Transform" && $second_viewer !=0 } {
+	set v $second_viewer
+    }
+    
+    if { $v != 0 } {
+	$v SetLookupTable $colormap
+    }
+}
+
+itcl::body pxitclcsigadget::SetLookupTableMode { index } {
+
+    set v $parent
+    if {$thisparam($this,overlayviewer) == "Transform" && $second_viewer !=0 } {
+	set v $second_viewer
+    }
+    
+    if { $v != 0 } {
+	$v SetLookupTableMode [ expr 0+$index ]
+    }
+}
+
+
+# ---------------------------------------------------------------------------
+itcl::body pxitclcsigadget::SaveSetup { args } { 
+
+    set len [ llength $args ]
+    
+    if { $len < 1 } {
+	set fname $setupfilename 
+    } else {
+	set fname [ lindex $args 0 ]
+    }
+
+    if { [ string length $fname  ] == 0  } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname  [tk_getSaveFile -title "Saving Setup File" -filetypes { {"CSI-Setup File" {.csi}}} -initialfile $f1tail -initialdir $f1path ]
+    }
+    if { [ string length $fname ] > 0 } {
+
+	set fileid [open $fname w]
+	
+	puts $fileid "#CSI Subject Description File"
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Transformations"
+	puts $fileid "#---------------------------------------------"
+	for { set i 0 } { $i < [ llength $xform_controllist ] } { incr i } {
+	    set tmp [ lindex $xform_controllist $i ]
+	    puts $fileid "[ $tmp cget -description] : [ [ $tmp GetObject ] cget -filename ]"
+	}
+
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Images"
+	puts $fileid "#---------------------------------------------"
+	
+	for { set i 0 } { $i < [ llength $image_controllist ] } { incr i } {
+	    set tmp [ lindex $image_controllist $i ]
+	    puts $fileid "[ $tmp cget -description] : [ [ $tmp GetObject ] cget -filename ]"
+	}
+	
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Extra Information"
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "Categories    : $thisparam($this,csi_categories)"
+	puts $fileid "Scale Factors : $thisparam($this,csi_scalefactors)"
+	puts $fileid "Smooth1       : $thisparam($this,smooth_sigma1)"
+	puts $fileid "Smooth2       : $thisparam($this,smooth_sigma2)"
+
+	close $fileid
+	set setupfilename $fname
+	SetTitle "CSI Tool $setupfilename"
+    }
+}
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclcsigadget::GetFileElement { fileid } {
+
+   gets $fileid line 
+   set index [string first ":" $line]
+   if { $index > 0 }  {
+       set len   [string length $line]
+       set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+       return $value
+   }
+   return ""
+}
+
+itcl::body pxitclcsigadget::LoadSetup { args } { 
+
+    set len [ llength $args ]
+    
+    if { $len < 1 } {
+	set fname $setupfilename 
+    } else {
+	set fname [ lindex $args 0 ]
+    }
+
+    if { [ string length $fname  ] == 0 } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	
+	set fname  [tk_getOpenFile -title "Setup File" -filetypes { {"Csi-Setup File" {.csi}}} -initialfile $f1tail -initialdir $f1path ]
+    }
+
+    if { [ string length $fname ] < 1 } {
+	return
+    }
+
+    if { [ file readable $fname ] == 0 } {
+	::pxtclutil::Warning "Cannot read setupfile file from $fname\n Bad File"
+	return 0
+    }
+
+    WatchOn; update idletasks
+
+    set fileid [open $fname r]
+	
+    gets $fileid line
+    if { [ string compare $line "#CSI Subject Description File"  ] != 0 } {
+	close fileid
+	::pxtclutil::Warning "Cannot read setupfile file from $fname\n Bad File Type"
+	return 0
+    }
+
+    gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+
+    for { set i 0 } { $i < [ llength $xform_controllist ] } { incr i } {
+	set tmp [ lindex $xform_controllist $i ]
+	set name [ GetFileElement $fileid ]
+	if { [ string length $name ] > 0 } {
+	    [ $tmp GetObject ] Load $name 
+	    $tmp Update
+	}
+    }
+	  
+    gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+
+    for { set i 0 } { $i < [ llength $image_controllist ] } { incr i } {
+	set tmp [ lindex $image_controllist $i ]
+	set name [ GetFileElement $fileid ]
+	if { [ string length $name ] > 0 } {
+	    [ $tmp GetObject ] Load $name 
+	    $tmp Update
+	}
+    }
+
+    catch {
+	gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+	set thisparam($this,csi_categories) [ GetFileElement $fileid ]
+	set thisparam($this,csi_scalefactors) [ GetFileElement $fileid ]
+	set thisparam($this,smooth_sigma1) [ GetFileElement $fileid ]
+	set thisparam($this,smooth_sigma2) [ GetFileElement $fileid ]
+    }
+    close $fileid
+    set setupfilename $fname
+
+    SetTitle "CSI Tool $setupfilename"
+    WatchOff
+}
+
+# ---------------------------------------------------------------------------
+itcl::body pxitclcsigadget::BrowseImport { mode } { 
+
+    set f1 $setupfilename
+    set f1path [ file dirname $f1 ]
+    
+    if { $mode == "Raw CSI" || $mode == "CSI PMAP" } {
+	set fname  [tk_getOpenFile -title "Reading $mode File" -filetypes { {"Raw Text File" {.txt}}}  -initialdir $f1path ]
+	if { [ llength $fname ] > 0 } {
+
+	    if { $mode == "Raw CSI" } {
+		$thisparam($this,csi_importraw) insert end $fname
+	    } else {
+		$thisparam($this,csi_importpmap) insert end $fname
+	    }
+	}
+    } elseif { $mode == "scout" } {
+	set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+	set fname  [tk_getOpenFile -title "Conventional/Scout Anatomical Image" -filetypes $typelist  -initialdir $f1path ]
+	if { [ llength $fname ] > 0 } {
+	    set thisparam($this,csi_importscout) $fname
+	}
+    } else {
+	set fname  [tk_getSaveFile -title "Output Setup File" -filetypes { {"Setup File" {.csi}}}  -initialdir $f1path ]
+	if { [ llength $fname ] > 0 } {
+	    set thisparam($this,csi_outputstem) [ file root $fname ]
+	}
+    }
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclcsigadget::RunImport { } {
+
+    # Check that there are enough data first 
+
+
+    if { [ file exists $thisparam($this,csi_importscout) ] == 0 } {
+	::pxtclutil::Warning "No/or bad Scout Image specified\n"
+	return 0
+    }
+
+    set np  [ $thisparam($this,csi_importraw)  index end ]
+    set np2 [ $thisparam($this,csi_importpmap) index end ]
+    if { $np <1 && $np2 <1 } {
+	::pxtclutil::Warning "Must specifiy at least one csi slice\n"
+	return 0
+    }
+
+    WatchOn
+    #    puts stdout "Input Anatomical $thisparam($this,csi_importscout)"
+
+    set ana [ vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+    $ana DebugOn
+    $ana  Load $thisparam($this,csi_importscout)
+    $ana DebugOff
+
+    set maxpass 1
+    if { $np > 0 && $np2 > 0 } {
+	set maxpass 2
+    }
+
+    set stem $thisparam($this,csi_outputstem)
+
+    for { set pass 0 } { $pass < $maxpass } { incr pass } {
+
+	set dt "importraw"
+	set cont $raw_control
+	set name "csi"
+	
+	if { $pass == 1 || ( $pass == 0 && $np == 0 ) } {
+	    set dt "importpmap"
+	    set cont $pmap_control
+	    set name "pmap"
+	}
+
+	set stack [ vtkpxCSIStackImages [ pxvtable::vnewobj ]]
+	for { set i 0 } { $i < $np } { incr i } {
+	    set it($i) [  vtkpxEpilepsyCSIReader [ pxvtable::vnewobj ]]
+	    set fname [ $thisparam($this,csi_$dt) get $i $i ]
+	    puts stdout "Loading  $fname"
+	    $it($i) Load $fname
+	    $stack AddInput [ $it($i) GetOutput ]
+	}
+	
+	$stack SetResolutionXY $thisparam($this,csi_importinplane)
+	$stack SetResolutionZ  $thisparam($this,csi_importslice)
+	if { $pass == 0 } {
+	    $stack SetAnatomicalInput [ $ana GetOutput ]
+	} else {
+	    $stack SetAnatomicalInput [ [ $conv_control  GetObject ] GetImage ]
+	}
+	$stack Update
+	set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+	$anaw SetInput [ $stack GetOutput ]
+	$anaw Save "${stem}_${name}.hdr"
+	
+	[ $cont GetObject ] Load "${stem}_${name}.hdr"; $cont Update
+	$anaw Delete
+	
+	if { $pass == 0 } {
+	    set anaw [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+	    $anaw SetInput [ $stack GetAnatomicalOutput ]
+	    $anaw Save "${stem}_convscout.hdr"
+	    $anaw Delete
+	    [ $conv_control GetObject ] Load "${stem}_convscout.hdr"; $conv_control Update
+	}
+
+	if { $pass == 0 && $np > 0 } {
+	    set thisparam($this,csi_categories) [ string range [ $it(0) GetCategoryNames ] 1 end-1  ]
+	    set sc [ $it(0) GetScaleFactors ]
+	    set n  [ $sc GetNumberOfTuples ]
+	    set thisparam($this,csi_scalefactors) ""
+	    for { set i 0 } { $i <  $n } { incr i } {
+		set a $thisparam($this,csi_scalefactors) 
+		set thisparam($this,csi_scalefactors) "$a \t [$sc GetComponent $i 0 ]"
+	    }
+	}
+	
+	$stack Delete
+	for { set i 0 } { $i < $np } { incr i } {
+	    $it($i) Delete
+	}
+    }
+    $ana Delete
+    SaveSetup "${stem}.csi"
+    WatchOff
+}
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclcsigadget::ResetImport  { } {
+    
+    $thisparam($this,csi_importraw)   delete 0 end
+    $thisparam($this,csi_importpmap)  delete 0 end
+    set thisparam($this,csi_importscout) ""
+    set thisparam($this,csi_output) "patient"
+
+}
+
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclcsigadget::ReadExtraInfo { fname } { 
+
+    if { [ string length $fname  ] == 0 } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname  [tk_getOpenFile -title "Extra Info File" -filetypes { {"Csi-Extra Info File" {_extra.txt}}} -initialfile $f1tail -initialdir $f1path ]
+    }
+
+    if { [ string length $fname ] < 1 } {
+	return
+    }
+
+    if { [ file readable $fname ] == 0 } {
+	::pxtclutil::Warning "Cannot read extra info file from $fname\n Bad File"
+	return 0
+    }
+
+    set fileid [open $fname r]
+	
+    gets $fileid line
+    if { [ string compare $line "#CSI Extra Information" ] != 0 } {
+	close fileid
+	::pxtclutil::Warning "Cannot read extra info file from $fname\n Bad File Type"
+	return 0
+    }
+
+    gets $fileid line ;     gets $fileid line  ;
+    gets $fileid thisparam($this,csi_categories)
+    gets $fileid line  ;
+    gets $fileid thisparam($this,csi_scalefactors)
+    close $fileid
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclcsigadget::VerifyRegistrationCallback { mode args } { 
+
+    if { $mode == 1 } {
+	$this VerifyRegistration $anat_control $conv_control $refx_control
+    } 
+}
+
+itcl::body pxitclcsigadget::UpdateFromRegistration { mmvutil } {
+
+    if { [ $mmvutil GetProgress ] == 1.0 } {
+	$this UpdateFromRegistrationDone $mmvutil
+	return
+    } 
+    
+    pxtkprint "[ $mmvutil GetOutputStatus ]"
+    $this ProgressCallback  $mmvutil "Registering Images"
+}
+
+itcl::body pxitclcsigadget::UpdateFromRegistrationDone { mmvutil } {
+
+    pxtkprint "[ $mmvutil GetOutputStatus ]"
+    $this ProgressCallback  $mmvutil Done
+}
+
+# ---------------------------------------------------------------------------------------
+itcl::body pxitclcsigadget::VerifyRegistration { imgcontrol1 imgcontrol2 xformcontrol } {
+
+    global pxtcl_pref_array
+
+    set image_ref [ $imgcontrol1 GetObject ]
+    set image_trn [ $imgcontrol2 GetObject ]
+
+    set orient_ref [ $image_ref GetOrientation ]
+    set orient_trn [ $image_trn GetOrientation ]
+    
+    set dim1 [ [ $image_ref GetImage ] GetDimensions ]
+    set dim2 [ [ $image_trn GetImage ] GetDimensions ]
+    if { [lindex $dim2 0 ] <2 || [ lindex $dim1 0 ] < 2 } { 
+	::pxtclutil::Warning "No Image in Memory\n Cannot Verify Transformation!"
+	return  0
+    }
+
+    WatchOn
+
+    set ut [ vtkpxUtil [ pxvtable::vnewobj ]]
+    set tr [ $xformcontrol GetTransformation ]
+    set tmp  [ [  pxitclimage \#auto ] GetThisPointer ]
+    $ut ResliceImage [ $tmp GetImage ] [ $image_trn GetImage ] [ $image_ref GetImage ] [ $tr GetTransformation ] 1 0.0
+    $ut Delete
+
+
+    $tmp CopyImageHeader [ $image_ref GetImageHeader ]
+    $tmp configure -filename "trn_[$image_trn cget -filename ]"
+
+    $parent SetResultsFromObject $image_ref $this
+    $second_viewer SetResultsFromObject $tmp $this
+    catch { itcl::delete object $tmp }
+    
+    WatchOff
+    return 1
+}
+#--------------------------------------------------------------------------------------------
+#
+#          GUI Stuff
+#
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclcsigadget::CreateImportControl { widget } {
+
+    frame $widget.t1; frame $widget.t15 -height 3 -bg black
+    frame $widget.t2; frame $widget.t25 -height 3 -bg black
+    frame $widget.t3; frame $widget.t35 -height 3 -bg black
+    frame $widget.t5; frame $widget.t55 -height 3 -bg black
+    frame $widget.t4
+
+    pack $widget.t1 $widget.t15 $widget.t2 $widget.t25 $widget.t3 $widget.t5 $widget.t55 $widget.t4 -side top -expand true -fill x
+    
+    set thisparam($this,csi_importraw) [ iwidgets::scrolledlistbox $widget.t1.a -labeltext "RAW CSI Text Files"  -vscrollmode static -hscrollmode dynamic -selectmode single -exportselection 0  ]
+
+    eval "button $widget.t1.b -text \"Add\" -command { $this BrowseImport \"Raw CSI\"} "
+    pack $widget.t1.b -side right -expand false
+    pack $widget.t1.a -side left  -expand true -fill both    
+    
+
+    set thisparam($this,csi_importpmap) [ iwidgets::scrolledlistbox $widget.t2.a -labeltext "PMAP Text Files"  -vscrollmode static -hscrollmode dynamic -selectmode single -exportselection 0 ]
+    eval "button $widget.t2.b -text \"Add\" -command { $this BrowseImport \"CSI PMAP\" } "
+    pack $widget.t2.b -side right -expand false
+    pack $widget.t2.a -side left -expand true -fill both    
+
+    iwidgets::entryfield  $widget.t3.a -labeltext "Scout:" -textvariable [ itcl::scope  thisparam($this,csi_importscout) ] -width 50 
+    eval "button $widget.t3.b -text \"Browse\" -command { $this BrowseImport scout} "
+    pack $widget.t3.b -side right -expand false
+    pack $widget.t3.a -side left -expand true -fill both    
+
+    iwidgets::entryfield  $widget.t5.a -labeltext "Output:" -textvariable [ itcl::scope  thisparam($this,csi_outputstem) ] -width 50 
+    eval "button $widget.t5.b -text \"Browse\" -command { $this BrowseImport output} "
+    pack $widget.t5.b -side right -expand false
+    pack $widget.t5.a -side left -expand true -fill both    
+
+
+    label $widget.t4.lab2 -text "In-Plane (mm):"
+    tk_optionMenu $widget.t4.res2 [ itcl::scope thisparam($this,csi_importinplane) ] "0.5" "0.75" "1.0" "2.0" "4.0" "8.0"
+    pack $widget.t4.lab2 $widget.t4.res2 -side left -expand f -fill x	
+
+    label $widget.t4.lab3 -text "Slice (mm):"
+    tk_optionMenu $widget.t4.res3 [ itcl::scope thisparam($this,csi_importslice) ] "0.25" "0.5" "0.625" "0.75" "1.0" "1.25" "1.5"  "2.0" "2.5" "5.0" "10.0"
+    pack $widget.t4.lab3 $widget.t4.res3 -side left -expand f -fill x	
+
+    eval "button $widget.t4.d -text \"Import\" -command { $this RunImport} "
+    eval "button $widget.t4.d2 -text \"Reset\" -command { $this ResetImport} "
+    pack $widget.t4.d2 $widget.t4.d -side right -expand f -fill x -padx 10 -pady 5
+
+
+
+
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclcsigadget::CreateImageControl { widget } {
+
+    set wr $widget
+
+    $anat_control Initialize $wr.1 
+    $conv_control Initialize $wr.2 
+    $raw_control Initialize $wr.4
+    $pmap_control Initialize $wr.5
+
+    pack $wr.1 $wr.2 $wr.4 $wr.5 -side top -expand f -fill x -pady 2
+
+    if { $parent != 0 } {
+
+	if { $second_viewer == 0 } {
+	    $anat_control AddFunction "$parent SetResultsFromObject" "Display" "$this"
+	    $conv_control AddFunction "$parent SetResultsFromObject" "Display" "$this"
+	    $raw_control AddFunction "$parent SetResultsFromObject" "Display" "$this"
+	    $pmap_control AddFunction "$parent SetResultsFromObject" "Display" "$this"
+	} else {
+	    $raw_control AddFunction "$parent SetImageFromObject" "DRef" "$this"
+	    $raw_control AddFunction "$second_viewer SetImageFromObject" "DTrn" "$this"
+
+	    $conv_control AddFunction "$second_viewer SetImageFromObject" "DTrn" "$this"
+	    $conv_control AddFunction "$parent SetImageFromObject" "DRef" "$this"
+
+	    $anat_control AddFunction "$parent SetImageFromObject" "DRef" "$this"
+	    $anat_control AddFunction "$second_viewer SetImageFromObject" "DTrn" "$this"
+
+	    $pmap_control AddFunction "$parent SetImageFromObject" "DRef" "$this"
+	    $pmap_control AddFunction "$second_viewer SetImageFromObject" "DTrn" "$this"
+	}
+    }
+
+}
+    
+# ---------------------------------------------------------------------------
+#
+#           Task Specific
+#
+# ----------------------------------------------------------------------
+itcl::body pxitclcsigadget::CreateTransformControl { widget } {
+
+
+    set wr $widget
+
+    $refx_control Initialize $wr.2 
+
+    pack  $wr.2 -side top -expand f -fill x -pady 10
+
+    if { $parent !=0 && $second_viewer !=0 } {
+	$refx_control AddFunction "$this VerifyRegistrationCallback 1" "Check!" "$this"
+    }
+
+}
+#---------------------------------------------------------------------------
+#   
+# Output Stuff
+#
+# ---------------------------------------------------------------------------
+itcl::body pxitclcsigadget::SetOverlayToolInputs { } {
+
+    $overlaytool SetImage [ $anat_control GetObject ]
+    set fmode 0
+    
+    if { $thisparam($this,overlayfunction) == "Raw-CSI" } {
+	$overlaytool SetFunctionalImage [ $raw_control GetObject ]
+	set fmode 0
+    } elseif { $thisparam($this,overlayfunction) == "PMAP-CSI" } {
+	$overlaytool SetFunctionalImage [ $pmap_control GetObject ] 
+	set fmode 0
+    } elseif { $thisparam($this,overlayfunction) == "Smooth1" } {
+	$overlaytool SetFunctionalImage [ $smooth_control1 GetObject ] 
+	set thisparam($this,overlayanatomy) "3D Anatomical" 
+	set fmode 1
+    } elseif { $thisparam($this,overlayfunction) == "Smooth2" } {
+	$overlaytool SetFunctionalImage [ $smooth_control2 GetObject ] 
+	set thisparam($this,overlayanatomy) "3D Anatomical" 
+	set fmode 1
+    }
+
+    set tmode 1
+
+    if { $thisparam($this,overlayanatomy) == "3D Anatomical" } {
+	$overlaytool SetImage [ $anat_control GetObject ]
+	set tmode 1
+    } else {
+	puts stdout  "Conv=$thisparam($this,overlayanatomy)"
+	$overlaytool SetImage [ $conv_control GetObject ] 
+	set tmode 0
+    }
+    
+    
+    if { $tmode != $fmode } {
+	$overlaytool SetTransformation [[ $refx_control GetObject ] GetTransformation ]
+    } else {
+	set tr [ vtkIdentityTransform [ pxvtable::vnewobj ]]
+	$overlaytool SetTransformation $tr
+	$tr Delete
+    }
+
+}
+# ----------------------------------------------------------------------------------------------
+#  Compute Smooth maps
+# ----------------------------------------------------------------------------------------------
+
+itcl::body pxitclcsigadget::SampleElectrodes { args }  {
+
+    set control [ lindex $args 1 ]
+    puts stdout "Use smoothing control = $control, electrodetool = $electrodetool"
+
+    set electrodes [ $electrodetool GetMultiGrid ]
+    puts stdout "Electrodes = [ $electrodes GetClassName ]"
+
+    set ctrl $smooth_control1
+    if { $control == 2 } {
+	set ctrl $smooth_control2
+    }
+
+    set img [ [ $ctrl GetObject ] GetImage ]
+    puts stdout "Image Components = [ $img GetNumberOfScalarComponents ] [ [ $ctrl GetObject ] cget -filename ]"
+    $electrodes PickFunction $img 
+
+    set typelist { 
+	{"Text Files" {".txt" } }
+	{"All Files" {*}}
+    }
+    
+    set l_filename "[ file root $setupfilename ].txt"
+    set f1 $l_filename
+    set f1path [ file dirname $f1 ]
+    set f1tail [ file tail    $f1 ]
+    set fname [tk_getSaveFile -title "Export picked function in text file" -filetypes $typelist -initialfile $f1tail -initialdir $f1path ]
+    if { [ string length $fname ] > 0 } {
+	$electrodes ExportValues $fname "\#Scale Factors: \t \t \t \t $thisparam($this,csi_scalefactors)" $thisparam($this,smooth_sigma${control}) $thisparam($this,csi_categories)
+    }
+}
+# ----------------------------------------------------------------------------------------------
+itcl::body pxitclcsigadget::ComputeSmooth { } {
+
+    set ok 0
+    set err "No anatomical and no raw-csi image in memory"    
+
+    catch { if { [ [ $anat_control GetImage ] GetImageSize ] > 1 } {  incr ok }  }
+    catch { if { [ [ $raw_control GetImage ] GetImageSize ] > 1 } {  incr ok; incr ok }  }
+
+    if { $ok != 3 } {
+	if { $ok == 1 } { set err "No raw-csi image in memory" }
+	if { $ok == 2 } { set err "No 3D anatomical image in memory" }
+
+	::pxtclutil::Warning "$err\n Cannot smooth raw csi !"
+	return 0
+    }
+
+
+    WatchOn
+
+    set sigma $thisparam($this,smooth_sigma)
+
+    set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+    $resl SetInput [ [ $raw_control GetObject ] GetImage ]
+    $resl SetInformationInput [ [ $anat_control GetObject ] GetImage ]
+    $resl SetResliceTransform [ [ $refx_control GetObject ] GetTransformation ]
+    $resl SetInterpolationMode 0
+    SetFilterCallbacks $resl "Reslicing Image"
+    $resl Update
+    
+
+
+    set smooth  [ vtkpxNormalizedSmoothImage [ pxvtable::vnewobj ]  ]
+    $smooth SetSigma $sigma
+    $smooth SetInput [ $resl GetOutput ]
+    $smooth SetNormalizeScale 1000.0
+    SetFilterCallbacks $smooth "Smoothing Image"
+    $smooth Update
+    
+    set vl $thisparam($this,smooth_control)
+    set control $smooth_control1
+    if { $thisparam($this,smooth_control) == 2 } {
+	set control $smooth_control2
+    }
+
+    set n1 [ file rootname [ [ $raw_control GetObject ] cget -filename ] ]
+    set name "${n1}_sm_${sigma}.hdr"
+
+    set thisparam($this,smooth_sigma$vl) $thisparam($this,smooth_sigma)
+
+    set out [ $control GetImage ]
+    $out ShallowCopyImage [ $smooth GetOutput ]
+    $out CopyImageHeader [ [ $raw_control GetObject ] GetImageHeader ]
+    $out configure -filename $name
+    $control Update
+
+    catch { $smooth Delete }
+    catch { $resl Delete }
+    
+    WatchOff
+    return 1
+}
+
+# ----------------------------------------------------------------------------------------------
+#   Create GUI 
+# ----------------------------------------------------------------------------------------------
+
+itcl::body pxitclcsigadget::CreateSamplingControl { widget } {
+
+    $smooth_control1 Initialize $widget.1 
+    $smooth_control2 Initialize $widget.2 
+
+    frame $widget.3 -bg black -height 5
+    frame $widget.4
+
+
+    pack $widget.1 $widget.2 $widget.3  -side top -expand f -fill x -pady 2
+    pack $widget.4 -side bottom -expand f -fill x -padx 2 -pady 2
+
+    if { $parent != 0 } {
+
+	if { $second_viewer == 0 } {
+	    $smooth_control1 AddFunction "$parent SetResultsFromObject" "Display!" "$this"
+	    $smooth_control2 AddFunction "$parent SetResultsFromObject" "Display!" "$this"
+	} else {
+	    $smooth_control2 AddFunction "$second_viewer SetImageFromObject" "DTrn" "$this"
+	    $smooth_control2 AddFunction "$parent SetImageFromObject" "DRef" "$this"
+
+	    $smooth_control1 AddFunction "$parent SetImageFromObject" "DRef" "$this"
+	    $smooth_control1 AddFunction "$second_viewer SetImageFromObject" "DTrn" "$this"
+
+	}
+    }
+
+
+    $smooth_control1 AddFunction "$this SampleElectrodes" "Electrode" "1"
+    $smooth_control2 AddFunction "$this SampleElectrodes" "Electrode" "2"
+	
+
+    label $widget.3.lab2 -text "Smoothing Kernel (mm):"
+    tk_optionMenu $widget.3.res2 [ itcl::scope thisparam($this,smooth_sigma) ] "1.0" "2.0" "4.0" "8.0" "12.0" "16.0" "20.0" "24.0" "32.0"
+    pack $widget.3.lab2 $widget.3.res2 -side left -expand f -fill x	
+
+    label $widget.3.lab3 -text "Output:"
+    tk_optionMenu $widget.3.res3 [ itcl::scope thisparam($this,smooth_control) ] "1" "2"
+    pack $widget.3.lab3 $widget.3.res3 -side left -expand f -fill x	
+
+    eval "button $widget.t4 -text \"Compute Smooth Raw CSI!\" -command { $this ComputeSmooth} "
+    pack $widget.t4 -side top -expand f -fill x -padx 10 -pady 5
+
+    
+    iwidgets::entryfield  $widget.e1 -labeltext "Categories:" -textvariable [ itcl::scope  thisparam($this,csi_categories) ] -width 80 
+    iwidgets::entryfield  $widget.e2 -labeltext "Scale Factors:" -textvariable [ itcl::scope  thisparam($this,csi_scalefactors) ] -width 80 
+    pack $widget.e2 $widget.e1 -side bottom -fill x -expand true
+
+}
+# ----------------------------------------------------------------------------------------------
+itcl::body pxitclcsigadget::CreateOverlayControl { widget } {
+
+   frame $widget.t3
+   pack $widget.t3  -side top -expand f -fill x -pady 4
+    # --------------------------
+    # Visualization Output Stuff
+    # --------------------------
+    iwidgets::Labeledframe $widget.t3.a -labelpos n -labeltext "Reslice Output"
+    iwidgets::Labeledframe $widget.t3.b -labelpos n -labeltext "Output Overlay"
+    set c2 [$widget.t3.a childsite]
+    set c3 [$widget.t3.b childsite]
+    pack $widget.t3.a $widget.t3.b -side top -fill both -padx 5 -pady 2
+
+   set w2 [ frame $c3.ttop ]
+   set w  [ frame $c3.top]; 
+   pack $w2 $w -side top -expand f -fill x
+    
+   if { $second_viewer != 0 } {
+       label $w2.ml -text "Output Viewer:"
+       tk_optionMenu $w2.mopt [ itcl::scope thisparam($this,overlayviewer)] "Reference" "Transform"
+       pack $w2.ml $w2.mopt -side left -expand f -fill x
+   }
+
+    label $w.l -text "Anatomy:"
+    tk_optionMenu $w.opt [ itcl::scope thisparam($this,overlayanatomy) ] "3D Anatomical" "Conventional"
+    pack $w.l $w.opt -side left -expand f -fill x
+
+    label $w.l2 -text "Function:"
+    tk_optionMenu $w.opt2 [ itcl::scope thisparam($this,overlayfunction) ] "Raw-CSI" "PMAP-CSI" "Smooth1" "Smooth2"
+    pack $w.l2 $w.opt2 -side left -expand f -fill x
+
+
+    for { set k 0 } { $k <=1 } { incr k } {
+	eval "$w.opt.menu entryconfigure $k -command { $this SetOverlayToolInputs }"
+    }
+    for { set k 0 } { $k <=3 } { incr k } {
+	eval "$w.opt2.menu entryconfigure $k -command { $this SetOverlayToolInputs }"
+    }
+
+    $overlaytool CreateResliceControl $c2
+    $overlaytool CreateFunctionalOverlayControl $c3
+
+
+}
+
+
+# ---------------------------------------------------------------------------
+# Main GUI Body 
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclcsigadget::Initialize { widget } { 
+	
+    set basewidget [ toplevel $widget ]
+    wm geometry $basewidget 575x600
+    wm withdraw $basewidget
+
+    SetTitle "CSI Tool"
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget
+}
+
+itcl::body pxitclcsigadget::DelayedInitialize { } { 
+
+    set menubase     [ menu $basewidget.menu ]; $basewidget configure -menu $menubase
+
+    set pbar         [ frame $basewidget.pbar    -width 400 -height 20 ]
+    set notebook $basewidget.notebook
+
+    iwidgets::tabnotebook $notebook  -tabpos w
+    #    pack $menubase -side top -expand f -fill x -pady 1
+    pack $pbar     -side bottom -expand f -fill x -pady 1
+    pack $notebook -side top -expand t -fill both -pady 1
+   
+    CreateImageControl      [ $notebook add -label "Images"  ] 
+    CreateTransformControl  [ $notebook add -label "Registrations" ]
+    CreateSamplingControl   [ $notebook add -label "Sampling"   ]
+    CreateOverlayControl    [ $notebook add -label "Overlays"   ]
+    CreateImportControl     [ $notebook add -label "Import"   ]
+
+    CreateProgressBar  $pbar
+
+
+    #    menubutton $menubase.file          -text Setup      -menu $menubase.file.m -underline 0
+    #   pack $menubase.file   -side left
+    menu $menubase.filem -tearoff 0 
+    $menubase add cascade -label Setup -menu $menubase.filem
+
+    eval "$menubase.filem add command -label \"Load Setup\" -command { $this LoadSetup \"\" } -underline 0 "
+    eval "$menubase.filem add command -label \"Save Setup\" -command { $this SaveSetup \"\" } -underline 0"
+    $menubase.filem add separator
+    eval "$menubase.filem add check -variable [ itcl::scope thisparam($this,autosavesetup) ] -label \"Auto Save Setup File\" "
+    $menubase.filem add separator
+    if { $parent == 0 } {
+	eval "$menubase.filem add command -label Exit -command {  pxtkexit } -underline 1"
+    } else {
+	eval "$menubase.filem add command -label Close -command {  $this HideWindow } -underline 1"
+    }
+    
+    $notebook view "Images"
+
+    set fullyinitialized 1
+}
+
+::itcl::body pxitclcsigadget::AddToMenuButton { mb args} {
+
+    eval "$mb add command -label \"Images\" -command {$this ShowWindow \"Images\"}"
+    eval "$mb add command -label \"Registrations\" -command {$this ShowWindow \"Registrations\"}"
+    eval "$mb add command -label \"Sampling\" -command { $this ShowWindow Sampling}"
+    eval "$mb add command -label \"Overlays\" -command { $this ShowWindow Overlays}"
+    eval "$mb add command -label \"Import Raw Data\" -command { $this ShowWindow Import}"
+}
+
+::itcl::body pxitclcsigadget::AddToMenuButtonLite { mb args} {
+
+    eval "$mb add command -label \"CSI Tool\" -command {$this ShowWindow \"Images\"}"
+}
+
+
+# ---------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitcldistributiontablegadget.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitcldistributiontablegadget.tcl
new file mode 100644
index 0000000..13f4696
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitcldistributiontablegadget.tcl
@@ -0,0 +1,222 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+package provide pxitcldistributiontablegadget 1.0
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+package require  vtkpxcontrib 1.1
+package require  labelframe   1.0
+package require  pxtclutil    1.0
+package require  pxvtable     1.0
+package require  pxtclhelp    1.0
+package require  Itcl         3.2
+package require  Iwidgets     4.0
+package require  pxitclimage            1.0
+package require  pxitcltransform        1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitclbaseimageviewer  1.0
+# ----------------------------------------------------------------------------------------------
+
+itcl::class pxitcldistributiontablegadget {
+
+    inherit pxitclbasecontrol
+    
+    # Generic Stuff 
+
+    private   common   thisparam        
+    protected variable ttable_dofentry 0
+    protected variable ttable_buttonlist ""
+    protected variable viewernames ""
+    protected variable viewers
+    # public 
+
+    
+    #
+    constructor { par args } {
+	pxitclbasecontrol::constructor $par
+    } {
+	InitializeDistributionTableGadget
+    }
+
+    public method RegisterViewer { vtk_viewer name }
+    public method Initialize { widget } 
+    public method ComputeTValue { mode }
+    public method GrabTvalueFromViewer { viewerno }
+    public method SwitchZScore { } 
+    public method AddToMenuButton { mb args }
+
+    protected method InitializeDistributionTableGadget { }
+}
+
+
+
+::itcl::body pxitcldistributiontablegadget::AddToMenuButton { mb args} {
+
+    eval "$mb add command -label \"T-Distribution Table Tool\" -command {$this ShowWindow }"
+}
+
+::itcl::body pxitcldistributiontablegadget::RegisterViewer { vtk_viewer name} {
+
+    lappend viewernames   $name
+    set viewers($name) $vtk_viewer
+}
+
+itcl::body pxitcldistributiontablegadget::InitializeDistributionTableGadget { } { 
+
+    set ttable_dofentry 0
+    set thisparam($this,ttable_mathobject)  0
+    set thisparam($this,ttable_tvalue)   2.0
+    set thisparam($this,ttable_df)         21
+    set thisparam($this,ttable_x1000)        0
+    set thisparam($this,ttable_zscore)       0
+    set thisparam($this,ttable_pv1)      0.10
+    set thisparam($this,ttable_pv2)      0.20
+}
+
+itcl::body pxitcldistributiontablegadget::Initialize { widget } { 
+	
+    set basewidget [ toplevel $widget ]
+    set ttable $basewidget
+
+    wm geometry $ttable 400x100
+    wm title $ttable "Critical Points of the T-distribution"
+    eval "wm protocol $ttable WM_DELETE_WINDOW { wm withdraw $ttable }"
+    
+    frame $ttable.top
+    frame $ttable.top2
+    frame $ttable.bot
+    pack $ttable.top $ttable.top2 $ttable.bot -side top -expand false -fill x -pady 2
+    
+    lappend ttable_buttonlist [ iwidgets::entryfield $ttable.top.1 -labeltext "T-value:"  -width 6 -validate real -textvariable [ itcl::scope thisparam($this,ttable_tvalue) ] -relief sunken  ]
+    checkbutton   $ttable.top.15  -text "x1000"  -variable [ itcl::scope thisparam($this,ttable_x1000) ]
+    eval "checkbutton   $ttable.top.16  -text \"Z-score\"  -variable [ itcl::scope thisparam($this,ttable_zscore) ] -command { $this SwitchZScore }"
+    set ttable_dofentry [ iwidgets::entryfield $ttable.top.2 -labeltext "DOF"  -width 3 -validate integer -textvariable [ itcl::scope thisparam($this,ttable_df) ] -relief sunken  ]
+    iwidgets::entryfield $ttable.top2.3 -labeltext "One Tail:"  -width 6 -validate real -textvariable [ itcl::scope thisparam($this,ttable_pv1) ] -relief raised 
+    iwidgets::entryfield $ttable.top2.4 -labeltext "Two Tail:"  -width 6 -validate real -textvariable [ itcl::scope thisparam($this,ttable_pv2) ] -relief sunken
+    
+    pack $ttable.top.1 $ttable.top.15 $ttable.top.16 $ttable.top.2  -side left -expand true -fill x
+    pack $ttable.top2.3 $ttable.top2.4  -side left -expand true -fill x
+    
+
+    eval "button $ttable.bot.4 -text \"Close\"   -command { wm withdraw $ttable }"
+    pack $ttable.bot.4 -side right -padx 3
+	
+    lappend ttable_buttonlist [ eval "button $ttable.bot.1 -text  \"T-> P\" -command { $this ComputeTValue forward }" ]
+    lappend ttable_buttonlist [ eval "button $ttable.bot.15 -text \"P(2t) -> T\" -command { $this ComputeTValue  reverse }" ]
+    pack $ttable.bot.1 $ttable.bot.15 -side left -padx 1
+
+    for { set i 0 } { $i < [ llength $viewernames  ] } { incr i } {
+	set name [ lindex $viewernames $i ]
+	set w "2_$i"
+	eval "button $ttable.bot.$w -text \"Grab $name\" -command { $this GrabTvalueFromViewer $name }"
+	pack $ttable.bot.$w  -side left -padx 1
+    }
+    
+    set thisparam($this,ttable_mathobject) [ vtkpxMath [ pxvtable::vnewobj ]]
+    set fullyinitialized 1        
+    return $basewidget
+}
+
+itcl::body pxitcldistributiontablegadget::SwitchZScore { } {
+
+    if { $thisparam($this,ttable_zscore) == 1 } {
+	$ttable_dofentry configure -state disabled
+	[lindex $ttable_buttonlist 0 ] configure -labeltext "Z-Value"
+	[lindex $ttable_buttonlist 1 ] configure -text "Z->P"
+	[lindex $ttable_buttonlist 2 ] configure -text "P(2t)->Z"
+    } else {
+	$ttable_dofentry configure -state normal
+	[lindex $ttable_buttonlist 0 ] configure -labeltext "T-Value"
+	[lindex $ttable_buttonlist 1 ] configure -text "T->P"
+	[lindex $ttable_buttonlist 2 ] configure -text "P(2t)->T"
+    }
+}
+
+itcl::body pxitcldistributiontablegadget::GrabTvalueFromViewer { viewername } {
+
+    set thisviewer [  $viewers($viewername) GetViewer ]
+
+    set lv [ $thisviewer GetLastClickedPoint ] 
+    set fr [ $thisviewer GetCurrentFrame ] 
+    set px [ lindex $lv 0 ]
+    set py [ lindex $lv 1 ]
+    set pz [ lindex $lv 2 ]
+    set img [ $thisviewer GetImage ] 
+
+    if { $img != "" } {
+	set thisparam($this,ttable_tvalue) [ $img GetScalarComponentAsDouble $px $py $pz $fr ]
+	set thisparam($this,ttable_x1000)  1
+	ComputeTValue forward
+    }
+}
+
+itcl::body pxitcldistributiontablegadget::ComputeTValue { mode } {
+
+    if { $mode == "forward" } {
+	if { $thisparam($this,ttable_x1000) == 1 } {
+	    set x [ expr 0.001 * $thisparam($this,ttable_tvalue) ]
+	} else {
+	    set x  $thisparam($this,ttable_tvalue) 
+	}
+	
+	if { $thisparam($this,ttable_zscore) == 0 } {
+	    set thisparam($this,ttable_pv2) [ $thisparam($this,ttable_mathobject) TtestToPvalue_itk $x $thisparam($this,ttable_df) ]
+	} else {
+	    set thisparam($this,ttable_pv2) [ $thisparam($this,ttable_mathobject) ZscoreToPvalue $x ]
+	}
+	set thisparam($this,ttable_pv1) [ expr $thisparam($this,ttable_pv2) * 0.5 ]
+	#set thisparam($this,ttable_pv1) [ $thisparam($this,ttable_mathobject) TtestToPvalue_itk $x $thisparam($this,ttable_df) ]
+    } else {
+	set x $thisparam($this,ttable_pv2)
+	set thisparam($this,ttable_pv1) [ expr $thisparam($this,ttable_pv2) * 0.5 ]
+	if { $thisparam($this,ttable_zscore) == 0 } {
+	    set t [ $thisparam($this,ttable_mathobject) PvalueToTvalue $x $thisparam($this,ttable_df) ]
+	} else {
+	    set t [ $thisparam($this,ttable_mathobject) PvalueToZscore $x  ]
+	}
+	if { $thisparam($this,ttable_x1000) == 1 } {
+	    set t [ expr $t * 1000.0 ]
+	}
+	set thisparam($this,ttable_tvalue) $t
+    }
+   
+
+    update idletasks
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitcldualmultisubject.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitcldualmultisubject.tcl
new file mode 100755
index 0000000..75a70dd
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitcldualmultisubject.tcl
@@ -0,0 +1,67 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclbrainregister.tcl,v 1.3 2003/02/26 16:29:58 papad Exp $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package require pxitclbrainregister 1.0
+
+
+
+wm withdraw .
+set breg [ pxitclbrainregister \#auto 0 ]
+$breg configure -enable_multi2gadget 1
+$breg Initialize .[pxvtable::vnewobj ]
+    
+set argc [llength $argv]
+if { $argc > 0 } {  
+    [ $breg cget -multigadget ] LoadSetup [ lindex $argv 0 ]
+} 
+if { $argc > 1 } {
+    [ $breg cget -multi2gadget ] LoadSetup [ lindex $argv 1 ]
+}
+
+[ [ $breg GetOrthoViewer ref ] GetViewer ] SetEnableRendering 1
+[ [ $breg GetOrthoViewer ref ] GetViewer ] UpdateDisplay
+[ [ $breg GetOrthoViewer trn ] GetViewer ] SetEnableRendering 1
+[ [ $breg GetOrthoViewer trn ] GetViewer ] UpdateDisplay
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclelectrodeeditor.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclelectrodeeditor.tcl
new file mode 100755
index 0000000..9153e48
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclelectrodeeditor.tcl
@@ -0,0 +1,192 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+package provide pxitclelectrodeeditor 1.0
+
+# 	$Id: pxitclelectrodeeditor.tcl,v 1.2 2004/03/11 16:42:14 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+package require vtkpxcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+package require pxitclElectrodeMultiControl 1.0
+
+itcl::class pxitclelectrodeeditor {
+
+    inherit pxitclbaseimageviewer
+    public  variable electrode_control 0
+
+    constructor { par } {
+	::pxitclbaseimageviewer::constructor $par
+    } {
+	set appname "BioImage Suite::Electrode Editor"
+
+    }
+    
+    public method HandleMouseEvent { mouse stat x1 x2 widgetname args }
+    public method InitializeElectrodeEditor { widget standalone}
+    public method PositionWindows { }
+}
+
+itcl::body pxitclelectrodeeditor::InitializeElectrodeEditor { widget st } {
+
+    set enable_landmarkcontrol 1
+    set enable_surfaceobjectmap 0
+    set enable_multisubjectcontrol 0
+    set enable_csigadget 0
+    set enable_fmrigadget 0
+    set enable_vvlinkgadget  0
+    set enable_talairachoption 0
+    set enable_landmarkclicks  1
+    set enable_overlaytool 0
+
+    set ok [ InitializeOrthogonalViewer $widget $st ]
+    set electrode_control [ [ pxitclElectrodeMultiControl \#auto $this ]  GetThisPointer ]
+    $electrode_control Initialize $widget.[ pxvtable::vnewobj ] $vtk_viewer
+
+    #    $csigadget configure -electrodetool $electrode_control
+
+    set mb  $menubase.features 
+    $mb add separator
+    eval "$mb add command -label \"Electrode Control\" -command { $electrode_control ShowWindow; $this PositionWindows}"
+
+    $electrode_control ShowWindow
+    return $ok
+
+
+
+}
+
+itcl::body pxitclelectrodeeditor::HandleMouseEvent { mouse stat x1 x2 widgetname args} {
+    
+    if { $vtk_viewer == 0 } {
+	return
+    }
+
+    # Need to flip y-axis vtk counts from bottom tk counts from top !!!
+    set wd [ [ $widgetname GetRenderWindow ] GetSize ]
+    set x2 [ expr [lindex $wd 1 ] - $x2 ]
+    $vtk_viewer HandleMouseButtonEvent $mouse $stat $x1 $x2
+    
+    set lv "" 
+    catch { set lv [ $vtk_viewer GetLastClickedPoint ] }
+    set currentpoint $lv
+    
+    if { [ llength $lv ] > 1 } {
+	if { [ lindex $lv 0 ] > -1 } {
+	    
+	    set lv [ $vtk_viewer GetLastClickedPoint ] 
+	    set px [ lindex $lv 0 ]
+	    set py [ lindex $lv 1 ]
+	    set pz [ lindex $lv 2 ]
+	    
+	    if { $polydatacontrol != 0 } {
+		[ $polydatacontrol GetPolyDataControl ] SetLastPoint $px $py $pz
+	    }
+	    
+	    if { ( $mouse == 1 || $mouse == 4 ) && ( $electrode_control != 0 ) } {
+
+		set mode 0
+		if { $mouse == 4 || $thisparam($this,mousetolandmarks) == 0 }  {
+		    set  mode 1
+		}
+
+		$electrode_control HandleClickedPoint $px $py $pz $mode $stat
+	    }
+	    	    
+	    set upd [ $vtk_viewer GetMouseSliceChangeMode ]
+	    if { $upd ==0 } {
+		$vtk_viewer UpdateDisplay
+	    }
+	}
+	
+	if { $mousecallback != 0 } {
+	    eval "$mousecallback $this"
+	}
+    }
+}
+
+itcl::body pxitclelectrodeeditor::PositionWindows {  } {
+    
+    set geom [ winfo geometry $basewidget ] 
+    scan $geom "%dx%d+%d+%d" w0 h0 x0 y0
+
+    set ew [ $electrode_control GetBaseWidget ]
+
+    set geom [ winfo geometry $ew ] 
+    scan $geom "%dx%d+%d+%d" w1 h1 x1 y1
+    
+    set y1 [ expr $y0 + 5 ]
+    set x1 [ expr $x0 + $w0 + 10 ]
+    set newgeom "${w1}x${h1}+$x1+$y1"
+    wm geometry $ew $newgeom
+    raise $ew
+}
+
+
+# ---------------------------------------------------------------------------------
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    wm withdraw .
+    set editor [ pxitclelectrodeeditor \#auto 0 ]
+    $editor configure -show_standard_images 1
+    $editor InitializeElectrodeEditor .[pxvtable::vnewobj ] 1
+    $editor ShowWindow
+    update
+
+    $editor PositionWindows
+
+
+    set argc [llength $argv]
+    
+    if { $argc > 0 } {   
+	$editor LoadImage [lindex $argv 0]  
+    }
+
+    [ $editor GetViewer ]  AdjustViewports 6
+
+    #if { [ $editor cget -enable_overlaytool ] == 1 } {
+    #	if { $argc > 1 } {  [ $editor cget -electrode_control ] LoadElectrodeMultiGrid [lindex $argv 1] }
+    #}
+}
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclexpfit.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclexpfit.tcl
new file mode 100644
index 0000000..512554a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclexpfit.tcl
@@ -0,0 +1,709 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclexpfit 1.0
+
+# 	$Id: pxitclexpfit.tcl,v 1.0 2005/10/18 21:25:14 xenios Exp xenios $	
+
+
+
+
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxvtable   1.0
+package require vtkpxcontrib  1.1
+package require pxitclbaseimagecontrol   1.0
+
+
+itcl::class pxitclexpfit {
+
+    # Base Class
+    inherit pxitclbaseimagecontrol 
+
+    protected common thisparam
+
+    protected variable vtk_viewer 0
+
+    constructor { par } {
+	::pxitclbaseimagecontrol::constructor $par
+    } {
+	InitializeExpfit
+    }
+
+    # Initialize and Set Up
+    public method InitializeExpfit { } 
+    public method Initialize { inpwidg }
+    public method DelayedInitialize {  }
+
+    # ----------------
+    # Create GUI Stuff
+    # ----------------
+    public method CreateFitControl { parent }
+    public method CreateFitOutputControl { parent }
+    public method CreateSegmentationControl { parent }
+
+    # ------------------------------
+    # OOP Override
+    # ------------------------------
+    public    method SetImage { img } 
+    
+    # ----------------------------
+    # Real Code
+    # ----------------------------
+    public method RunExpFit { }
+    public method RunExpFitT1 { }
+    public method RunExpFitSegmentation { }
+    public method RunOldStyleExpFitSegmentation { }
+
+
+    public method GenTimePoints { }
+    public method ValidateTimePoints { }
+    public method CreateTimePointArray { }
+    public method LoadEchoList { }
+    public method SaveEchoList { }
+
+
+    # -----------------------------
+    # Morphology Operations
+    # -----------------------------
+    public method CheckImage {  image name operation verbosity } 
+
+    # ----------------------------
+    public method AddToMenuButton { mb args } 
+}
+
+# ----------------------------------------------------------------------------------------------
+itcl::body pxitclexpfit::InitializeExpfit {  } {
+
+    # ------------------------------------------------------------
+    #  Multi-echo Stuff
+    # ------------------------------------------------------------
+    set thisparam($this,expfit_timepointlist)  "15.0 30.0 45.0 60.0 75.0 90.0"
+    set thisparam($this,expfit_firsttimepoint)  15.0
+    set thisparam($this,expfit_dtimepoint)      15.0
+    set thisparam($this,expfit_maxt2)     250
+    set thisparam($this,expfit_thr)       0.02
+    set thisparam($this,expfit_noisesigma)       300
+    set thisparam($this,expfit_median)       0
+    set thisparam($this,expfit_imagenoise)  150
+    
+    set thisparam($this,expfit_densitygui) 0
+    set thisparam($this,expfit_t2mapgui) 0
+    set thisparam($this,expfit_errorgui) 0
+    set thisparam($this,expfit_t2mode) 1
+    set thisparam($this,segm_outputgui) 0
+    set thisparam($this,segm_outputgui2) 0
+
+    # -------------------------------------------------------------------
+
+    set thisparam($this,histo_numclasses) 3
+    set thisparam($this,histo_sigmaratio) 0.2
+
+    set thisparam($this,histo_iterations) 50
+    set thisparam($this,histo_numbins)   256
+    set thisparam($this,histo_epsilon)    0.05
+    set thisparam($this,histo_sigma) 0.05
+
+    
+    set thisparam($this,mrf_iterations)   10
+    set thisparam($this,mrf_smoothness)  1.0
+    set thisparam($this,mrf_convergence) 0.25
+    set thisparam($this,mrf_keychannel)    1
+    set thisparam($this,mrf_fuzzy)         0
+
+    set thisparam($this,mrf_dobiasfield) 0
+    set thisparam($this,mrf_biasfieldsigma) 5.0
+
+
+
+}
+# -------------------------------------------------------------------------------
+
+itcl::body pxitclexpfit::Initialize { inpwidg  } {
+
+    if { $initialized == 1 } { return $basewidget } 
+
+    set basewidget $inpwidg
+    toplevel $basewidget ; wm geometry $basewidget 600x450; wm withdraw $basewidget
+
+
+    SetTitle "Exponential Fit Control"
+    set initialized 1
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget
+}
+
+itcl::body pxitclexpfit::DelayedInitialize {  } {
+
+    if { $fullyinitialized == 1 } {
+	return
+    }
+
+    set notebook $basewidget.notebook
+    iwidgets::tabnotebook $notebook -width 5i -height 3i -tabpos w
+
+
+    CreateFitControl  [ $notebook add -label "Fitting" ]
+    CreateFitOutputControl  [ $notebook add -label "Fit. Output" ]
+
+    set segm 0
+    catch { 
+	set segm [ vtkpxMonoExponentialSegmentation  [ pxvtable::vnewobj ]]
+	$segm Delete
+    }
+
+    if { $segm != 0 } {
+	CreateSegmentationControl  [ $notebook add -label "Segmentation" ]
+    }
+
+    set w  [ frame $basewidget.buttonbar  ]
+    pack $w -side bottom -fill x -expand f
+    pack $notebook -side top -fill both -expand true
+
+    set canvas [ [ $notebook component tabset ] component canvas ];     set l [ AddLogoLabel $canvas ];     pack $l -side bottom -padx 1 
+
+    if { $parent != 0 } {
+	eval "button $w.l1  -text \"Copy Results To Image\" -command { $parent CopyResultsToImage }"
+	eval "button $w.l2  -text \"Undo Copy Results\" -command { $parent RevertToPreviousImage }"
+	pack $w.l1 $w.l2 -side left -padx 5
+    }
+
+    eval "button $w.close   -text Close -command { $this HideWindow } "
+    pack  $w.close -side right -fill x -padx 5 -pady 5 -expand f
+    set fullyinitialized 1
+}
+
+
+
+
+# ------------------------------------------------------------------------------------------------
+#    GUI Stuff
+# ------------------------------------------------------------------------------------------------
+
+
+itcl::body pxitclexpfit::CreateSegmentationControl { base } {
+    set thisparam($this,segm_outputgui2) [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $thisparam($this,segm_outputgui2) configure -description "Segmentation Output 2"
+    $thisparam($this,segm_outputgui2) Initialize $base.out2
+    $thisparam($this,segm_outputgui2) AddFunction "$parent SetResultsFromObject" "Display" "$this"
+
+    set thisparam($this,segm_outputgui) [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $thisparam($this,segm_outputgui) configure -description "Segmentation Output"
+    $thisparam($this,segm_outputgui) Initialize $base.out
+    $thisparam($this,segm_outputgui) AddFunction "$parent SetResultsFromObject" "Display" "$this"
+
+    pack $base.out2 $base.out -side bottom -expand false -fill x
+
+    set nt [ iwidgets::tabnotebook $base.nt -tabpos s -angle 45 -margin 2 -backdrop gray -raiseselect true ]
+    pack $nt -side top -expand t -fill both
+
+    set topbar  [ $nt add -label Standard   ]
+    set topbar2 [ $nt add -label Experimental ]
+    $topbar2 configure -bg darkgreen
+    $nt view "Standard"
+
+    set mainbar  [ frame $topbar.1 ]
+    set mrfbar   [ frame $topbar.2 ]
+    set bbar     [ frame $topbar.3 ]
+
+    set sbar     [ frame $topbar2.1 ]
+    set sbar2   [ frame $topbar2.2 ]
+
+    pack $mainbar $mrfbar  $bbar -side top -expand false -fill x -pady 0
+    pack  $sbar $sbar2 -side top -expand false -fill x -pady 0
+
+    # ----------------------- Common ---------------------------------------------
+    label         $mainbar.1  -text "Number of Classes:"
+    tk_optionMenu $mainbar.2 [ itcl::scope thisparam($this,histo_numclasses) ] "1" "2" "3" "4" "5" "6" "7"
+    iwidgets::entryfield $mainbar.3 -labeltext "sigmaratio:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,histo_sigmaratio) ] -relief sunken 
+    pack $mainbar.1 $mainbar.2 $mainbar.3 -side left -expand t -fill x -padx 2
+
+
+    iwidgets::entryfield $mrfbar.1 -labeltext "Iterations"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,mrf_iterations) ] -relief sunken 
+    iwidgets::entryfield $mrfbar.2 -labeltext "Smoothness:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,mrf_smoothness) ] -relief sunken 
+    iwidgets::entryfield $mrfbar.3 -labeltext "Convergence:"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,mrf_convergence) ] -relief sunken 
+    iwidgets::entryfield $mrfbar.4 -labeltext "Channel:"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,mrf_keychannel) ] -relief sunken 
+    pack $mrfbar.1 $mrfbar.2 $mrfbar.3 $mrfbar.4  -side left -expand t -fill x  -padx 2
+
+
+    # -------------------
+    # MRF Bar
+    # -------------------
+
+    eval "button $bbar.0 -text \"Do Exponential Segmentation\"  -command { $this RunExpFitSegmentation  }"
+    pack $bbar.0   -side left -fill x -expand false -padx 10 -pady 1
+
+    # -------------------------- Experimental ------------------------------------
+
+    iwidgets::entryfield $sbar.1 -labeltext "KMeans: Bins:"  -width 3 -validate integer -textvariable [ itcl::scope thisparam($this,histo_numbins) ] -relief sunken 
+    iwidgets::entryfield $sbar.2 -labeltext "Iterations:"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,histo_iterations) ] -relief sunken 
+    iwidgets::entryfield $sbar.3 -labeltext "Sigma:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,histo_sigma) ] -relief sunken 
+    iwidgets::entryfield $sbar.4 -labeltext "Convergence:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,histo_epsilon) ] -relief sunken 
+    pack  $sbar.1 $sbar.2 $sbar.3 $sbar.4 -side left -expand t -fill x  -padx 0
+
+    label                $sbar2.0 -text "Bias Field Correction Parameters:"
+    checkbutton          $sbar2.1 -variable [ itcl::scope thisparam($this,mrf_dobiasfield) ] -text "B1 Correction"
+    iwidgets::entryfield $sbar2.2 -labeltext "B1 Sigma:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,mrf_biasfieldsigma) ] -relief sunken 
+    pack $sbar2.0 $sbar2.1 $sbar2.2  -side left -expand t -fill x  -padx 2
+    # ---------------------------------------------------------------------------------
+
+    ::pxitclbasecontrol::SetWidgetTreeColors $topbar2 "\#aaabd7" "black"
+
+}
+
+itcl::body pxitclexpfit::CreateFitControl { base } {
+
+    #    $base configure -bg green
+
+    set   tbar [ LabelFrame:create $base.bar1  -width 300  -text "Time Course" ]
+    set   obar [ LabelFrame:create $base.bar2  -width 300  -text "Fitting Operations" ]
+    pack $base.bar1 $base.bar2 -side top -pady 4 -padx 2 -expand t -fill both
+    
+    set   midbar    [ frame $obar.1 ] 
+    set   bbar      [ frame $obar.2 ]
+    pack $midbar $bbar -side top -expand f -fill x -pady 1
+
+    set   midbar1   [ frame $tbar.1 ]
+    set   midbar2   [ frame $tbar.2 ]
+    set   midbar3   [ frame $tbar.3 ]
+
+
+    pack   $midbar1 $midbar2  $midbar3   -side top -expand false -fill x  -pady 0 -padx 2
+    
+
+    iwidgets::entryfield $midbar1.4 -labeltext "First T:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,expfit_firsttimepoint) ] -relief sunken
+    iwidgets::entryfield $midbar1.5 -labeltext "Dt:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,expfit_dtimepoint) ] -relief sunken
+
+    eval "button $midbar1.6 -text \"Generate\"  -command { $this GenTimePoints   }"
+    pack $midbar1.4 $midbar1.5 $midbar1.6  -side left -expand t -fill x 
+
+    iwidgets::entryfield $midbar2.0 -labeltext "Time Points:"  -width 30  -textvariable [ itcl::scope thisparam($this,expfit_timepointlist) ] -relief sunken
+    eval "button $midbar2.1 -text \"Validate\"  -command { $this ValidateTimePoints   }"
+    pack $midbar2.1 -side right -expand f -pady 2
+    pack $midbar2.0 -side left -expand t -fill x 
+
+
+    eval "button $midbar3.0 -text \" Load Timecourse\"  -command { $this LoadEchoList }"
+    eval "button $midbar3.1 -text \" Save Timecourse\"  -command { $this SaveEchoList }"
+    pack $midbar3.0 $midbar3.1 -side left -padx 5 -pady 1
+    
+
+
+    # Button Bar
+    # ----------
+    checkbutton   $midbar.0 -variable [ itcl::scope thisparam($this,expfit_t2mode) ] -text "Use T2" 
+    iwidgets::entryfield $midbar.1 -labeltext "Max T2"  -width 4 -validate integer -textvariable [ itcl::scope thisparam($this,expfit_maxt2) ] -relief sunken
+    iwidgets::entryfield $midbar.2 -labeltext "Threshold"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,expfit_thr) ] -relief sunken
+    iwidgets::entryfield $midbar.3 -labeltext "NoiseSigma"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,expfit_noisesigma) ] -relief sunken
+
+    checkbutton   $midbar.4 -variable [ itcl::scope thisparam($this,expfit_median) ] -text "Robust Fit"
+
+    pack $midbar.0 $midbar.1 $midbar.2 $midbar.3   -side left -expand t -fill x 
+
+    eval "button $bbar.0 -text \" Fit T2\"  -command { $this RunExpFit   }"
+
+    set fit 0
+    catch { 
+	set fit [ vtkpxExponentialFitT1  [ pxvtable::vnewobj ]]
+	$fit Delete
+    }
+
+    if { $fit !=0 } {
+	eval "button $bbar.1 -text \" Fit T1\"  -command { $this RunExpFitT1 }"
+	pack $bbar.0 $bbar.1   -side left -fill x -expand t -padx 10 -pady 2
+    } else {
+	pack $bbar.0  -side left -fill x -expand t -padx 10 -pady 2
+    }
+    
+ 
+}
+
+# ----------------------------------------------------------------------------------------
+
+itcl::body pxitclexpfit::CreateFitOutputControl { base } {
+
+    label $base.o -bg black -fg white -text "Output of Fitting Operations"
+    set   outputbar [ frame $base.4 ]
+    pack $base.o -side top -expand f -fill x -pady 2
+    pack $outputbar -side bottom -expand t -fill both
+
+    set thisparam($this,expfit_densitygui) [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $thisparam($this,expfit_densitygui) configure -description "Density Image"
+    $thisparam($this,expfit_densitygui) InitializeLite $outputbar.1 1
+    $thisparam($this,expfit_densitygui) AddFunction "$parent SetResultsFromObject" "Display" "$this"
+
+    set thisparam($this,expfit_t2mapgui) [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $thisparam($this,expfit_t2mapgui) configure -description "Relaxation Time Image"
+    $thisparam($this,expfit_t2mapgui) InitializeLite $outputbar.2 1
+    $thisparam($this,expfit_t2mapgui) AddFunction "$parent SetResultsFromObject" "Display" "$this"
+
+    set thisparam($this,expfit_errorgui) [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $thisparam($this,expfit_errorgui) configure -description "Error"
+    $thisparam($this,expfit_errorgui) InitializeLite $outputbar.3 1
+    $thisparam($this,expfit_errorgui) AddFunction "$parent SetResultsFromObject" "Display" "$this"
+
+    pack $outputbar.1 $outputbar.2 $outputbar.3 -side top -pady 0 -ipady 0 -padx 2
+}
+
+# ----------------------------------------------------------------------------
+#  Morphology Stuff 
+# ----------------------------------------------------------------------------
+itcl::body pxitclexpfit::CheckImage {  image name operation verbosity } {
+    
+    set ok 0
+    
+    catch { if { [ $image GetImageSize ] > 1 } {  set ok 1 }   }
+    
+    if { $verbosity >0 && $ok == 0 } {
+	::pxtclutil::Warning "No $name in Memory\n Cannot perform $operation !"
+    }
+
+    return $ok
+}
+
+# ------------------------------------------------------------------------------------------------
+#   GUI Support
+# ------------------------------------------------------------------------------------------------
+itcl::body pxitclexpfit::GenTimePoints {  } {
+
+    set nt [ [ $currentimage GetImage  ] GetNumberOfScalarComponents ]
+    if { $nt < 2 } {
+    	::pxtclutil::Warning "No image in Memory or currentimage has less than 2 frames\n Cannot generate valid timepoint train !"
+    }
+
+    set t0 $thisparam($this,expfit_firsttimepoint)  
+    set dt $thisparam($this,expfit_dtimepoint)     
+    
+
+    set thisparam($this,expfit_timepointlist)  ""
+
+    set t $t0
+    for { set i 0 } { $i < $nt } { incr i } {
+	lappend thisparam($this,expfit_timepointlist) $t
+	set t [ expr $t + $dt ]
+    }
+}
+
+itcl::body pxitclexpfit::ValidateTimePoints {  } {
+
+    set nt [ [ $currentimage GetImage  ] GetNumberOfScalarComponents ]
+    if { $nt < 2 } {
+    	::pxtclutil::Warning "No image in Memory or currentimage has less than 2 frames\n Cannot validate timepoint train !"
+    }
+
+    set qlist "" 
+    foreach n $thisparam($this,expfit_timepointlist) {
+	catch { lappend qlist [ expr abs($n) ] }
+    }
+
+    set thisparam($this,expfit_timepointlist) [ lsort -real $qlist ]
+
+    set np [ llength $thisparam($this,expfit_timepointlist) ]
+    if { $np < $nt } {
+	::pxtclutil::Warning "$np timepoints specified, need at least $nt to fit this image"
+    } else {
+	::pxtclutil::Info "Time Point List OK"
+    }
+	
+}
+
+itcl::body pxitclexpfit::CreateTimePointArray { } {
+
+    set fl [ vtkFloatArray [ pxvtable::vnewobj ]]
+    set vlist $thisparam($this,expfit_timepointlist)
+    $fl SetNumberOfTuples  [ llength $vlist ]
+
+    for { set i 0 } { $i < [ llength $vlist ] } { incr i } {
+	$fl SetComponent $i 0 [ lindex $vlist $i ]
+    }
+
+    return $fl
+}
+
+
+itcl::body pxitclexpfit::LoadEchoList { } {
+
+    set fname [tk_getOpenFile -title "Filename"   -filetypes { {"Echo List Text Files" {.txt}}}]
+    if { [ llength $fname ] > 0 } {
+	if { [ file exists $fname ] > 0 } {
+	    set fileid [open $fname r ]
+	    if { $fileid > 0 } {
+		gets $fileid line
+		if { $line == "\#Echo List File"  } {
+		    gets $fileid line
+		    set thisparam($this,expfit_timepointlist) $line
+		    close $fileid
+		} else {
+		    pxtclutil::Warning "Failed to Read Echo List from $fname"
+		}
+	    }
+	}
+    }
+}
+    
+    
+itcl::body pxitclexpfit::SaveEchoList { } {
+
+    set lst $thisparam($this,expfit_timepointlist)
+    set fname [tk_getSaveFile -title "Filename" -defaultextension .txt  -filetypes { {"Echo List Text Files" {.txt}}}]
+    if { [ llength $fname ] > 0 } {
+	set fileid [open $fname w]
+	puts $fileid "\#Echo List File"
+	puts $fileid $lst
+	close $fileid
+	pxtclutil::Info "Echo List Saved in $fname"
+    }
+}
+
+
+
+# ------------------------------------------------------------------------------------------------
+#    Fitting Code
+# ------------------------------------------------------------------------------------------------
+
+
+itcl::body pxitclexpfit::RunExpFit {  } {
+
+
+    if { [ CheckImage $currentimage "Image" "Mono-exponential Fitting" 1 ] == 0 } { 
+	return 0  
+    }
+
+    set tarray [ $this CreateTimePointArray ]    
+    set nc [ [ $currentimage GetImage ]  GetNumberOfScalarComponents ]
+    set np [ $tarray  GetNumberOfTuples ]
+    if { $nc < 3 || $np < $nc } {
+	::pxtclutil::Warning "Images has too few ($nc) components for mono-exponential fitting or not enough time array values ($np < $nc) !"
+	$tarray Delete
+	return 0
+    }
+
+    WatchOn    
+
+
+
+    pxtkprint ".... Monoexponential Fitting\n"
+    set fit [ vtkpxLogExponentialFit  [ pxvtable::vnewobj ]]
+    $fit SetInput [ $currentimage GetImage ] 
+    $fit SetEchoTrain $tarray
+    $fit SetMaxT2Value $thisparam($this,expfit_maxt2)
+    $fit SetMedianFit $thisparam($this,expfit_median)
+    $fit SetIntensityThreshold $thisparam($this,expfit_thr)
+    $fit SetImageNoiseSigma $thisparam($this,expfit_noisesigma)
+    pxtkconsole
+
+    SetFilterCallbacks $fit "Mono-exponential fitting"
+    $fit Update
+
+    set densityimage [ $thisparam($this,expfit_densitygui) GetObject ]
+    $densityimage  ShallowCopyImage [ $fit GetDensityMap ]
+    $densityimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "den" ]
+    $densityimage  CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,expfit_densitygui) Update
+
+
+    set t2mapimage [ $thisparam($this,expfit_t2mapgui) GetObject ]
+    if { $thisparam($this,expfit_t2mode) == 1 } {
+	$t2mapimage  ShallowCopyImage [ $fit GetOutput ]
+	$t2mapimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "t2" ]
+    } else {
+	$t2mapimage  ShallowCopyImage [ $fit GetR2Map ]
+	$t2mapimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "r2" ]
+    }
+    $t2mapimage  CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,expfit_t2mapgui) Update
+
+    set errorimage [ $thisparam($this,expfit_errorgui) GetObject ]
+    $errorimage  ShallowCopyImage [ $fit GetErrorMap ]
+    $errorimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "err" ]
+    $errorimage  CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,expfit_errorgui) Update
+
+    $fit Delete
+
+    WatchOff
+
+    $tarray Delete
+
+    $parent SetResultsFromObject $t2mapimage $this
+}
+
+# -------------------------------------------------------------------------------------------
+
+itcl::body pxitclexpfit::RunExpFitT1 {  } {
+
+
+    if { [ CheckImage $currentimage "Image" "T1-exponential Fitting" 1 ] == 0 } { 
+	return 0  
+    }
+    
+    set tarray [ $this CreateTimePointArray ]    
+    set nc [ [ $currentimage GetImage ]  GetNumberOfScalarComponents ]
+    set np [ $tarray  GetNumberOfTuples ]
+    if { $nc < 3 || $np < $nc } {
+	::pxtclutil::Warning "Images has too few ($nc) components for mono-exponential fitting or not enough time array values ($np < $nc) !"
+	$tarray Delete
+	return 0
+    }
+
+
+    WatchOn    
+
+    pxtkprint ".... Monoexponential Fitting\n"
+    set fit [ vtkpxExponentialFitT1  [ pxvtable::vnewobj ]]
+
+    $fit SetInput [ $currentimage GetImage ] 
+    $fit SetIntensityFractionalThreshold $thisparam($this,expfit_thr)
+    $fit SetThreeParameterFit $thisparam($this,expfit_median)
+    $fit SetRelaxationTimes  $tarray
+    pxtkconsole
+
+    SetFilterCallbacks $fit "T1 Mono-exponential fitting"
+    $fit Update
+
+    set densityimage [ $thisparam($this,expfit_densitygui) GetObject ]
+    $densityimage  ShallowCopyImage [ $fit GetDensityMap ]
+    $densityimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "den" ]
+    $densityimage  CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,expfit_densitygui) Update
+
+
+    set t2mapimage [ $thisparam($this,expfit_t2mapgui) GetObject ]
+    $t2mapimage  ShallowCopyImage [ $fit GetOutput ]
+    $t2mapimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "t1" ]
+    $t2mapimage  CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,expfit_t2mapgui) Update
+
+    set errorimage [ $thisparam($this,expfit_errorgui) GetObject ]
+    $errorimage  ShallowCopyImage [ $fit GetQMap ]
+    $errorimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "qmap" ]
+    $errorimage  CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,expfit_errorgui) Update
+
+    $fit Delete
+    WatchOff
+
+    $tarray Delete
+    $parent SetResultsFromObject $t2mapimage $this
+}
+
+# -------------------------------------------------------------------------------------------
+
+
+itcl::body pxitclexpfit::RunExpFitSegmentation {  } {
+
+
+    if { [ CheckImage $currentimage "Image" "Mono-exponential Fat Segmentation" 1 ] == 0 } { 
+	return 0  
+    }
+    
+    set tarray [ $this CreateTimePointArray ]    
+    set nc [ [ $currentimage GetImage ]  GetNumberOfScalarComponents ]
+    set np [ $tarray  GetNumberOfTuples ]
+    if { $nc < 4 || $np < $nc } {
+	::pxtclutil::Warning "Images has too few ($nc) components for mono-exponential fitting or not enough time array values ($np < $nc) !"
+	$tarray Delete
+	return 0
+    }
+
+
+    WatchOn    
+
+    pxtkprint ".... Monoexponential Segmentation \n"
+
+    set segm [ vtkpxMonoExponentialSegmentation  [ pxvtable::vnewobj ]]
+    $segm SetInput [ $currentimage GetImage ] 
+
+    $segm SetFuzzyClassification $thisparam($this,mrf_fuzzy) 
+    $segm SetDistributionModel 0
+    $segm SetNumberOfClasses $thisparam($this,histo_numclasses)
+    $segm SetIterations $thisparam($this,histo_iterations)
+    $segm SetNumberOfBins $thisparam($this,histo_numbins)
+    $segm SetConvergence $thisparam($this,histo_epsilon)
+    $segm SetSigma $thisparam($this,histo_sigma)
+    $segm SetOutlierDetection 0
+    $segm SetMaxSigmaRatio      $thisparam($this,histo_sigmaratio)
+    $segm SetMRFIterations $thisparam($this,mrf_iterations)
+    $segm SetSmoothness $thisparam($this,mrf_smoothness)
+    $segm SetMRFConvergencePercentage $thisparam($this,mrf_convergence)
+    $segm SetImageNoiseSigma $thisparam($this,expfit_imagenoise)
+    $segm SetTEArray  $tarray
+    $segm SetComputeBiasField  $thisparam($this,mrf_dobiasfield)
+    $segm SetBiasFieldFactor $thisparam($this,mrf_biasfieldsigma)
+
+    SetFilterCallbacks $segm   "Monoexponential MRF Segmentation of image"
+    $segm SetDebugVoxel -1
+    $segm DebugOff
+    $segm Update
+
+    pxtkconsole
+
+    if {  $thisparam($this,mrf_dobiasfield) == 1 } {
+	set densityimage [ $thisparam($this,expfit_densitygui) GetObject ]
+	$densityimage  ShallowCopyImage [ $segm GetBiasField ]
+	$densityimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "biasfield" ]
+	$densityimage  CopyImageHeader [ $currentimage GetImageHeader ]
+	$thisparam($this,expfit_densitygui) Update
+    }
+   
+    set errorimage [ $thisparam($this,segm_outputgui2) GetObject ]
+    $errorimage  ShallowCopyImage [ $segm GetMultiFrameOutput ]
+    $errorimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "msegm" ]
+    $errorimage  CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,segm_outputgui2) Update
+
+    set outputimage [ $thisparam($this,segm_outputgui) GetObject ]
+    $outputimage  ShallowCopyImage [ $segm GetOutput ]
+    $outputimage configure -filename    [ AddPrefix [ $currentimage cget -filename  ] "segm" ]
+    $outputimage  CopyImageHeader [ $currentimage GetImageHeader ]
+    $thisparam($this,segm_outputgui) Update
+
+    $segm Delete
+    WatchOff
+
+    $tarray Delete
+    $parent SetResultsFromObject $outputimage $this
+}
+    
+# -------------------------------------------------------------------------------------------
+itcl::body pxitclexpfit::SetImage { img  } {
+	
+    DelayedInitialize
+    
+    $currentimage ShallowCopy $img
+    $currentresults UnLoad
+    $currentresults CopyImageHeader [ $currentimage GetImageHeader ]
+
+}
+# ----------------------------------------------------------------------------
+itcl::body pxitclexpfit::AddToMenuButton { mb args } {
+    eval "$mb add command -command {$this ShowWindow \"Fitting\" } -label \"Exp. Fitting\" "
+    eval "$mb add command -command {$this ShowWindow \"Segmentation\" } -label \"Exp. Segmentation\" "
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclfilelistmenu.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclfilelistmenu.tcl
new file mode 100644
index 0000000..896d737
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclfilelistmenu.tcl
@@ -0,0 +1,560 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+# 	$Id: pxitclfilelistmenu.tcl,v 1.3 2005/06/22 13:01:09 xenios Exp $	
+
+package provide pxitclfilelistmenu 1.0
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+package require vtkpxcontrib  1.1
+package require pxtclutil 1.0
+package require pxtcluserprefs 1.0
+package require pxitclbasecontrol 1.0
+package require pxitcllistselector 1.0
+# -----------------------------------------------------
+#  Intialize Variables
+# -----------------------------------------------------
+
+itcl::class pxitclfilelistmenu {
+
+    # menubase is new menu
+    protected variable menubase      0
+
+    # variable for editing list
+    protected variable item_selector      0
+
+    # parent is parent menu
+    protected variable parent       0
+
+    # suffix,suffixname specify the type of file to be added
+    public variable    suffix      { .hdr .hdr.gz .nii .nii.gz }
+    public variable    suffixname  "Image Files"
+
+    # filename is the current log file
+    public    variable filename      ""
+
+    # callback is the name of the command to execute (i.e. $callback $fname)
+    protected variable callback      0
+    protected variable addcurrentnamecallback      0
+
+    # menuname is the actual label of the menu
+    protected variable menuname    "menu"
+
+    # filelist is a list of lists each having a key,value pair
+    protected variable filelist    ""
+    
+    # if this is 1 then an add button is also added to the menu
+    protected variable enableadd    1
+
+    # flag to use sqlite vs file
+    public variable usedb 1
+    protected variable dbfilename ""
+    protected variable dbase 0 
+    protected variable typename ""
+    protected variable initialized 0
+
+    # ------------------------------------------------------
+
+    constructor { par name callbackname {  currentnameclb 0 } } {
+	set parent  $par
+	set menuname $name
+	set callback $callbackname
+	set addcurrentnamecallback $currentnameclb
+    }
+
+    # Initialize Variables etc 
+    public method InitializeDisplay {  }
+    public method SetModeToImages { }
+    public method SetModeToObjectmaps { }
+    public method SetModeToDirectories { }
+    public method SetModeToStandardImages { }
+    public method SetModeToCustom { suffixname suffix filename { doadd 1 } }
+    public method SetForceFileNames { } { if { $initialized == 0 } { set usedb 0 }}
+    public method ReadData { fn }
+    protected method ReadDataBase { tpname }
+    protected method ReadFile { fname }
+    public method AddFile { } 
+    public method AddCurrent { } 
+    protected method AddItem { newitem } 
+    public method Info { }
+    public method Import { }
+    public method GetThisPointer { } { return $this }
+
+    public method ButtonPressed  { value }
+    public method AddMenuEntries { } 
+    public method DeleteItems    { } 
+    public method SaveAll    { } 
+}
+
+# ----------------------------------------------------------------------------------
+itcl::body pxitclfilelistmenu::SetModeToImages { } {
+    
+    global env
+
+
+    set    suffix      { .hdr .hdr.gz .nii .nii.gz }
+    set suffixname "Image Files"
+    
+    set fn ".pximagelist"
+    catch { set fn $env(BIODIRLIST) }
+    set fn [ file join $env(HOME) $fn ]
+    if { [ file exists $fn  ] == 0 } {
+	set fn ".bioimagelist"
+	catch { set fn $env(BIODIRLIST) }
+	set fn [ file join $env(HOME) $fn ]
+	if { [ file exists $fn ] == 0 } {
+	    set fn ".pximagelist"
+	}
+    }
+
+    set enableadd 1
+    ReadData $fn
+}
+
+
+itcl::body pxitclfilelistmenu::SetModeToObjectmaps { } {
+    
+    global env
+
+
+    set  suffix      { .hdr .hdr.gz .nii .nii.gz }
+    set  suffixname "Objectmap Files"
+    set fn ".bioobjectmaplist"
+    set fn [ file join $env(HOME) $fn ]
+    set enableadd 1
+    ReadData $fn
+}
+
+
+
+itcl::body pxitclfilelistmenu::SetModeToStandardImages { } {
+
+    global pxtcl_pref_array
+    set    suffix      { .hdr .hdr.gz .nii .nii.gz }
+    set suffixname "Image Files"
+    set filename ""
+    set enableadd 0
+    set filelist ""
+    
+    set p1 [ file dirname [ info script ]]
+    set p2 [ file normalize [ file join $p1 [ file join ".." images ] ] ]
+
+    lappend filelist [ list "MNI T1 1mm"           "[ file join $p2 MNI_T1_1mm.nii.gz ]" ]
+    lappend filelist [ list "MNI T1 1mm_stripped"  "[ file join $p2 MNI_T1_1mm_stripped.nii.gz ]" ]
+    lappend filelist [ list "MNI T1 1mm_mask"      "[ file join $p2 MNI_T1_1mm_mask.nii.gz ]" ]
+    lappend filelist [ list "MNI T1 1mm_graywhite" "[ file join $p2 MNI_T1_1mm_graywhite.nii.gz ]" ]
+    lappend filelist [ list "" "" ]
+    lappend filelist [ list "MNI T1 2mm"          "[ file join $p2 MNI_T1_2mm.nii.gz ]" ]
+    lappend filelist [ list "MNI T1 2mm_stripped" "[ file join $p2 MNI_T1_2mm_stripped.nii.gz ]" ]
+    lappend filelist [ list "MNI T1 2mm_mask"     "[ file join $p2 MNI_T1_2mm_mask.nii.gz ]" ]
+    lappend filelist [ list "MNI T1 2mm_graywhite" "[ file join $p2 MNI_T1_2mm_graywhite.nii.gz ]" ]
+    lappend filelist [ list "" "" ]
+    lappend filelist [ list "avg152_NIFTI_Test"     "[ file join $p2 avg152T1_LR_nifti.nii.gz]" ]
+    
+}
+
+itcl::body pxitclfilelistmenu::SetModeToDirectories { } {
+    
+    global env
+
+
+    set suffix ""
+    set suffixname "Directories"
+    
+    set fn ".biodirlist"
+    catch { set fn $env(BIODIRLIST) }
+    set fn [ file join $env(HOME) $fn ]
+
+    set enableadd 1
+    ReadData $fn
+}
+
+itcl::body pxitclfilelistmenu::SetModeToCustom { sfxname sfx fname { doadd 1 } } {
+    set suffix $sfx
+    set suffixname $sfxname
+    set fn $fname
+    set enableadd [ expr $doadd > 0 ]
+    ReadData $fn
+}
+
+
+itcl::body pxitclfilelistmenu::Info { } {
+    ::pxtclutil::Info "The contents of this menu are in the file $filename -- this can be edited with your favorite text editor (e.g. notepad/emacs/vi etc.)"
+}
+
+itcl::body pxitclfilelistmenu::Import { } {
+
+    if { $usedb == 0 } { 
+	return
+    }
+
+    global env
+    set fn $typename
+    catch { set fn $env(BIODIRLIST) }
+    set fn [ file join $env(HOME) $fn ]
+    ReadFile $fn
+
+    if { $menubase !=0 } {
+	$menubase delete 0 end
+	$this AddMenuEntries
+    }
+
+
+}
+
+
+itcl::body pxitclfilelistmenu::AddFile { } {
+
+    if { $suffix == "" } {
+	set dirname  [tk_chooseDirectory -title "Select Directory" ]
+	if { [ string length $dirname ] < 1 } {
+	    return 0
+	}
+	set dirname [ file normalize $dirname ]
+	set n [ llength $filelist ]
+	set newitem  [ list [ file tail $dirname ] $dirname ]
+    } else {
+	set typelist "{[ list  $suffixname  $suffix ]}"
+	lappend typelist {"All Files" {*}}
+	#puts stderr "Typelist = $typelist"
+	set fname  [tk_getOpenFile -title "Specify new  Filename"  -filetypes $typelist ]
+	if { [  string length $fname ] < 1 } {
+	    return 0 
+	}
+	set newitem [ list [ file tail [ file root $fname ] ] $fname ]
+    }
+
+    return [ $this AddItem $newitem ]
+
+}
+
+itcl::body pxitclfilelistmenu::AddCurrent { } {
+
+    set line "set fname \[ $addcurrentnamecallback \] "
+    eval $line
+    
+    if { [ file exists $fname ] == 0 } {
+	return 0
+    }
+
+    set newitem [ list [ file tail [ file root $fname ] ] $fname ]
+#    puts stderr "Adding $newitem"
+
+    return [ $this AddItem $newitem ]
+}
+
+
+itcl::body pxitclfilelistmenu::AddItem { newitem } {
+
+    if { [ llength $newitem ] !=2 } {
+	return 0
+    }
+
+    if { $usedb == 0 } {
+	if { [ file exists  $filename ] == 0  } {
+	    set fout [ open $filename w ]
+	    if { $fout !=0 } {
+		puts $fout "\#BioImage Suite File\n\# Format\n\# $suffixname : Full Filename\n\# e.g\n\# MyFile : myfile${suffix}"
+		close $fout
+	    }
+	}
+
+	if { [ file writable  $filename ] > 0 } {
+	    pxtkprint  "adding [ lindex $newitem 0 ] : [ lindex $newitem 1 ] to $filename"
+	    set fout [ open $filename a ]
+	    puts $fout "[ lindex $newitem 0 ] : [ lindex $newitem 1 ]"
+	    close $fout
+	}  else {
+	    pxtclutil::Warning "System File $filename is not writeable"
+	}
+    } else {
+	
+	$dbase AddItem $typename "[ lindex $newitem 0 ]" "[ lindex $newitem 1 ]"
+    }
+
+    
+    set key [ lindex $newitem 0 ]
+    set value [ lindex $newitem 1 ]
+    lappend filelist $newitem
+
+    eval "$menubase add command -label \"$key\" -command { $callback \"$value\" }"
+    return 1
+}
+
+
+
+
+itcl::body pxitclfilelistmenu::SaveAll { } {
+
+    if { $usedb == 1 } {
+	$dbase DeleteAll $typename 
+	for { set i 0 } { $i < [ llength $filelist ] } { incr i } {
+	    set obj [ lindex $filelist $i ]
+	    set key [ lindex $obj 0 ] 
+	    set value [ lindex $obj 1 ] 
+	    if { [ string length $key ] > 1 } {
+		#		puts stderr "AddintItem $typename $key $value "
+		$dbase AddItem $typename $key $value 
+	    }
+	}
+	return
+    }
+
+    set fout [ open $filename w ]
+    if { $fout !=0 } {
+	puts $fout "\#BioImage Suite File\n\# Format\n\# $suffixname : Full Filename\n\# e.g\n\# MyFile : myfile${suffix}"
+	for { set i 0 } { $i < [ llength $filelist ] } { incr i } {
+	    set obj [ lindex $filelist $i ]
+	    set key [ lindex $obj 0 ] 
+	    set value [ lindex $obj 1 ] 
+	    puts $fout "$key : $value"
+	}
+	close $fout
+    } else {
+	pxtclutil::Warning "System File $filename is not writeable"
+    }
+}
+# -------------------------------------------------------------
+itcl::body pxitclfilelistmenu::ReadDataBase { tpname } {
+
+    if { $tpname == "" } {
+	return 0
+    }
+
+    if { $dbase == 0 } {
+
+	global env
+	set fn ".bioimagesuite3"
+	catch { set fn $env(BIODBASE) }
+	set fn [ file join $env(HOME) $fn ]
+	
+	set connector [ vtkbisDatabase New ]
+	$connector InitializeSQLite "$fn" 
+	set ok [ $connector Connect ]
+
+	#	puts stderr "Connector $fn , ok=$ok"
+
+	if { $ok > 0 } {
+	    set dbase [ vtkbisFilenameTable New ]
+	    $dbase SetConnector $connector
+	    $dbase CreateTable
+	    #puts stdout "List=for $tpname =[ $dbase QueryAll $tpname ]\n\n"
+	    set lst [ split [ $dbase QueryAll $tpname ] "|" ]
+	    set typename $tpname
+	    
+	    set max [ expr [ llength $lst ] -1 ]
+
+	    if { $tpname == "biodirlist" } {
+		puts stdout "max=$max, lst=$lst"
+	    }
+	    if { [ llength $lst ] > 0 } {
+		for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+		    set line [ lindex $lst $i ]
+		    set lst2 [  split $line "," ]
+		    if { [ llength $lst2 ] == 3 } {
+			set key   [string trim   [ lindex $lst2 1 ] ]
+			set value [string trim   [ lindex $lst2 2 ] ]
+			lappend filelist [ list $key $value ]
+		    } else {
+			#		puts stdout "Ignoring $line ( [ llength $lst2 ])"
+		    }
+		}
+	    } else {
+		$this Import
+	    }
+	} else {
+	    puts stderr "Failed to Connect to database"
+	}
+    }
+
+#    puts stdout "Filelist=$filelist"
+    return 1
+}
+
+
+# -------------------------------------------------------------------
+itcl::body pxitclfilelistmenu::ReadData { fn } {
+
+    if { $fn == "" } {	return 0  }
+    set initialized 1
+
+    if { $usedb == 1 } {
+	return [ $this ReadDataBase [ file tail $fn ] ]
+    } 
+	
+    return [ $this ReadFile $fn ]
+}
+# -------------------------------------------------------------------
+itcl::body pxitclfilelistmenu::ReadFile { fn } {
+
+    set filelist ""
+    set filename $fn
+    
+    if { [ file exists $fn ] == 0 } {
+	return 0
+    }
+
+    set fileid [open $fn r]
+    set found 0
+
+
+    
+    while { [ gets $fileid line ] >=0 } {
+	if { [  string range $line 0 0 ] == "\#" } {
+	    
+	} else {
+	    set index [string first ":" $line]
+	    
+	    if { $index > 0 }  {
+		set len   [string length $line]
+		set key   [string trim   [string range $line 0 [expr $index - 1]]]
+		set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		lappend filelist [ list $key $value ]
+	    } elseif { $index == 0 } {
+		lappend filelist [ list "" "" ]
+	    }
+	}
+    }
+    close $fileid
+
+
+    if { $usedb == 1 } {
+	$this SaveAll
+    }
+
+    return 1
+}
+
+
+
+
+itcl::body pxitclfilelistmenu::InitializeDisplay { } {
+
+    set tmp $parent.[ pxvtable::vnewobj ]
+    
+    $parent add cascade -underline 0  -label $menuname -menu $tmp
+    set menubase [ menu $tmp -tearoff 0  ]
+
+    $this AddMenuEntries
+}
+
+itcl::body pxitclfilelistmenu::AddMenuEntries { } {
+
+    set m2 $menubase
+    set add 0
+
+    if { $usedb == 0 } {
+	if { [ string length $filename ] > 0 } {
+	    eval "$m2 add command -label Info -command { $this Info } -background white"
+	    incr add
+	}
+    } 
+    #   else {
+    #	eval "$m2 add command -label Import -command { $this Import } -background white"
+    #   }
+
+    if { $enableadd == 1 } {
+	eval "$m2 add command -label Add -command { $this AddFile } -background white"
+	if { $addcurrentnamecallback !=0 } {
+	    eval "$m2 add command -label \"Add Current\" -command { $this AddCurrent } -background white"
+	}
+	eval "$m2 add command -label Edit -command { $this DeleteItems } -background white"
+	incr add
+    }
+    if { $add > 0 } {
+	$m2 add separator
+    }
+    
+    for { set i 0 } { $i < [ llength $filelist ] } { incr i } {
+	set obj [ lindex $filelist $i ]
+	set key [ lindex $obj 0 ] 
+	set value [ lindex $obj 1 ] 
+	if { [ string length $key ] > 1 } {
+	    if { [ file exists $value ] } {
+		set cmd "$m2 add command -label \"$key\" -command { $this ButtonPressed \"$value\" }"
+		eval $cmd
+	    } 
+	} else {
+	    $m2 add separator
+	}
+    }
+}
+
+itcl::body pxitclfilelistmenu::ButtonPressed { value } {
+    eval "$callback {$value} "
+}
+
+itcl::body pxitclfilelistmenu::DeleteItems { } {
+
+    if { [ llength $filelist ] < 1 } {
+	pxtclutil::Warning "You need to only have at least one item in this list before you can delete any!"
+	return 
+    }
+
+    if { $item_selector == 0 } {
+	set item_selector [ pxitcllistselector \#auto $menubase.[ pxvtable::vnewobj ] ]
+    }
+    
+    set l ""
+    set slist ""
+    for { set i 0 } { $i < [ llength $filelist ] } { incr i } {
+	set obj [ lindex $filelist $i ]
+	set key [ lindex $obj 0 ] 
+	set value [ lindex $obj 1 ] 
+	lappend l "[expr $i+1 ]: $key : $value"
+	lappend slist $i
+    }
+    
+    $item_selector Activate $l $slist "Editing $suffixname list" "UNSELECT Items to Delete them from the list"
+    set lst [ $item_selector GetSelectedIndices ]
+
+    # Cancel Pressed
+    if { [ $item_selector  GetLastState ] == 0 } {
+	return
+    }
+
+
+    set oldlist $filelist
+
+    set filelist ""
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	set c [ lindex $lst $i ]
+	set obj [ lindex $oldlist $c ]
+	lappend filelist $obj
+    }
+
+    $this SaveAll
+    $menubase delete 0 end
+    $this AddMenuEntries
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclimageimport.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclimageimport.tcl
new file mode 100644
index 0000000..84363e1
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclimageimport.tcl
@@ -0,0 +1,1039 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclimageimport 1.0
+
+# 	$Id: pxitclimageimport.tcl,v 1.4 2003/08/20 20:46:37 xenios Exp xenios $	
+
+
+
+
+
+package require  pxitclbaseimagecontrol 1.0
+
+package require  pxtclreadsprheader 1.0
+package require  pxtcluserprefs 1.0
+package require  Iwidgets 4.0
+
+itcl::class  pxitclimageimport {
+
+    inherit pxitclbaseimagecontrol
+    
+    private common thisparam
+
+    public variable need_load 0 
+    variable selection_box 0
+    
+    private variable dimframe   0
+    private variable otherframe 0
+    private variable multiframe 0
+    private variable byteframe  0
+
+    private common filetypes [ list "DICOM" "Analyze"  "Signa LX" "Prism (SPECT)" "Binary"  "Signa Spr"  "TIFF" "PNM" "BMP" "JPEG" ] 
+    private common masks [ list  "*" "*.hdr*" "e*s*i*" "*.psm*" "*" "*.spr"  "*.tif*" "*.p?m" "*.bmp" "*.jp*" ]
+
+    private common orientations [ list "Axial" "Coronal" "Sagittal" ]
+    private common flips  [ list "None" "Slice Order(Z)" "X" "Y" "YZ" "Transpose" "FlipTranspose"]
+    private common mr_modes [ list "Conventional" "Conventional (Append)" "EchoPlanar" ]
+    
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } {	
+	InitializeImageImport 
+
+    }
+    
+
+    # ---------------------------------------------------------------------------------
+    #   Create Actual GUI
+    # ---------------------------------------------------------------------------------
+
+
+    private   method InitializeImageImport { }
+    public    method Initialize { inpwidg } 
+    protected method CreateFilenameControl { base }
+    protected method CreatePropertiesControl { base }
+    protected proc   ProcessSignaFilename { f } 
+    public    method ReadHeader { } 
+    public    method ImportImage { } 
+    public    method UpdateParent { }
+    public    method UpdateFileName { } 
+    
+    public    method UpdateFileType { } 
+    public    method GetFileType    { }
+    public    method SetFileType    { ftype }
+
+    public method SetCurrentDirectory { fname} 
+
+
+    public method ShowWindow { args }
+    public method Debug { } { puts stdout $thisparam($this,import_numbytes) }
+
+
+    public method ImportTIFF     { fname minslice maxslice comment }
+    public method ImportJPEG     { fname minslice maxslice comment }
+    public method ImportPNM      { fname minslice maxslice comment }
+    public method ImportBMP      { fname minslice maxslice comment }
+    public method ImportSignaSpr { fname minslice maxslice comment }
+    public method ImportSignaLX  { fname minslice maxslice comment }
+    public method ImportBinary   { fname minslice maxslice comment }
+    public method ImportAnalyze  { fname minslice maxslice comment }
+    public method ImportNmr47    { fname minslice maxslice comment }
+    public method ImportRawMR    { fname minslice maxslice comment }
+    public method ImportPrism    { fname minslice maxslice comment }
+    public method ImportDICOM    { fname minslice maxslice comment }
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::InitializeImageImport { } {
+
+    global pxtcl_pref_array
+    
+    #  ---------------------------------------
+    #  GUI Related Parameters
+    #  ---------------------------------------
+    set thisparam($this,import_bottomslice) -1 ; set thisparam($this,import_topslice) -1 ; 
+    set thisparam($this,import_orient) "Axial"
+    set thisparam($this,import_xsp) 1.5;      set thisparam($this,import_ysp) 1.5;     
+    set thisparam($this,import_zsp) 1.5;
+    set thisparam($this,import_width) 128 ;   set thisparam($this,import_height) 128 ;  
+    set thisparam($this,import_numbytes) 4;
+    set thisparam($this,import_skip) 0; set thisparam($this,import_flip) "None"
+    set thisparam($this,import_filename) "" ; set thisparam($this,image_type) "Signa LX"
+    set thisparam($this,num_frames) 1;
+    set thisparam($this,num_slices) 1;
+    set thisparam($this,import_swapbytes) 0
+    set thisparam($this,image_type)       $pxtcl_pref_array(DefaultImportMode)
+    set thisparam($this,import_flip) "None"
+    set thisparam($this,import_mrmode) "Conventional"
+}
+
+# ---------------------------------------------------------------------------------
+#
+# Create Import Control
+#
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::Initialize { widg } {
+	
+    if { $initialized == 1 } { return $basewidget }
+
+    set basewidget $widg
+    toplevel $basewidget ; wm withdraw $basewidget
+    wm geometry $basewidget 450x420
+    wm title $basewidget "Import Image Control"
+
+    set notebook $basewidget.notebook
+    iwidgets::tabnotebook $notebook -width 5i -height 3i -tabpos n
+    
+    CreateFilenameControl     [ $notebook add -label "Filename"  ]
+
+    set bottom [ $notebook add -label "Properties"  ]
+
+    set w [ frame $bottom.bottom -relief ridge -width 800]
+    pack $w -side bottom -fill x -expand false
+    pack $notebook -side top -fill both -expand true
+
+    eval "button $w.cp2 -text \"Load + Update\"  -command {  $this UpdateParent }"
+    eval "button $w.close   -text Close -command { $this HideWindow }"
+    pack $w.cp2 $w.close -side left -fill x -padx 15 -pady 10
+
+    
+    CreatePropertiesControl  $bottom
+    $notebook view "Filename"
+
+    set initialized 1
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+
+
+    set canvas [ [ $notebook component tabset ] component canvas ]
+    set l [ AddLogoLabel $canvas ]
+    pack $l -side right -padx 1 
+
+
+    return $basewidget
+
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::CreateFilenameControl {  base } {
+	
+    
+    label $base.o -bg black -fg white -text "Select Filename and Image Type"
+    pack  $base.o   -side top -expand f -fill x  -pady 2
+    
+    set selection_box $base.b
+    set filetype_box  $base.c
+
+    iwidgets::fileselectionbox $selection_box -width 100i -height 100i
+    set w [ [ iwidgets::labeledwidget  $filetype_box -labeltext "Image File Type:"] childsite ]
+
+    pack $filetype_box -side bottom -fill x -expand  f
+    pack $selection_box -side top -fill both -expand true
+    eval "$selection_box  configure -selectfilecommand { $this UpdateFileName }"
+   
+    set optmenu [ tk_optionMenu $w.m [ itcl::scope thisparam($this,image_type) ] [lindex $filetypes 0 ] ]
+    for { set k 1 } { $k < [ llength $filetypes ] } { incr k } {
+    	$optmenu add radio -variable [ itcl::scope thisparam($this,image_type) ]  -label [ lindex $filetypes $k ]
+    }
+    
+    for { set k 0 } { $k < [ llength $filetypes ] } { incr k } {
+    	eval "$optmenu entryconfigure $k -command { $this UpdateFileType }"
+    }
+
+    pack  $w.m -side left -padx 10
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::SetCurrentDirectory { fname}  {
+
+    $selection_box configure -directory $fname
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::UpdateFileName { } {
+
+    set fname [ $selection_box get ]
+    if { [ string length $fname ] > 1 } {
+	set thisparam($this,currentfilename) $fname
+	ReadHeader  
+	set need_load 1
+    }
+}
+
+itcl::body pxitclimageimport::UpdateFileType { } {
+
+    set ind [ lsearch -exact $filetypes $thisparam($this,image_type) ]
+    set f2  [ lindex $masks $ind ]  
+    $selection_box configure -mask $f2
+    $selection_box filter
+    update idletasks
+
+    set ft $thisparam($this,image_type) 
+
+
+    if { $ft == "Analyze" || $ft == "Nmr47"  || $ft == "Prism (SPECT)" ||  $ft == "DICOM" ||  $ft == "Varian" } {
+	DisableUI [ list $byteframe $multiframe $dimframe ]
+    } elseif { $ft == "Signa Spr" } {
+	DisableUI [ list $multiframe $dimframe ]
+	EnableUI $byteframe
+    } elseif { $ft == "Signa LX" } {
+	DisableUI [ list $dimframe $byteframe ]
+	EnableWidget $multiframe
+    } elseif { $ft == "Binary" || $ft == "Raw MR" } {
+	EnableUI [ list $dimframe $byteframe ]
+	DisableWidget $multiframe
+    } else {
+	EnableUI [ list $byteframe $multiframe $dimframe ]
+    }
+    	
+}
+
+# ---------------------------------------------------------------------------------
+
+::itcl::body pxitclimageimport::GetFileType {  } { return $thisparam($this,image_type)  }
+# ---------------------------------------------------------------------------------
+::itcl::body pxitclimageimport::SetFileType { ft } {
+
+    set ind [ lsearch -exact $filetypes $ft ] 
+    if { $ind >=0 } {
+	set thisparam($this,image_type) $ft
+    }
+
+}
+# ---------------------------------------------------------------------------------
+::itcl::body pxitclimageimport::ShowWindow { args } {
+
+    UpdateFileType
+    return [ pxitclbasecontrol::ShowWindow "Filename" ]
+}
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclimageimport::CreatePropertiesControl { base } { 
+	
+    label $base.o -bg black -fg white -text "Image Header Info" -width 50 
+    frame $base.mid ; 
+
+    set dimframe   [ frame $base.mid.bar0 ]
+    set otherframe [ frame $base.mid.bar1 ]
+
+    
+    pack  $base.o -side top -expand f -fill x  -pady 2
+    pack  $base.mid -side top -expand t -fill both -pady 2 -padx 2
+    pack  $dimframe   -side left -expand f -fill y   -pady 2 -padx 2
+    pack  $otherframe  -side left -expand true -fill both  -pady 2 -padx 2
+
+
+    label $dimframe.0a -text "Image Dimensions"
+    iwidgets::entryfield $dimframe.0 -labeltext "Width:" -fixed 10 -width 6 -validate numeric -textvariable [ itcl::scope  thisparam($this,import_width) ]
+    iwidgets::entryfield $dimframe.1 -labeltext "Height:" -fixed 10 -width 6 -validate numeric -textvariable [ itcl::scope  thisparam($this,import_height) ]
+    iwidgets::entryfield $dimframe.2 -labeltext "Depth:" -fixed 10 -width 6 -validate numeric -textvariable [ itcl::scope  thisparam($this,num_slices) ]
+    iwidgets::entryfield $dimframe.3 -labeltext "Frames:" -fixed 10 -width 6 -validate numeric -textvariable [ itcl::scope  thisparam($this,num_frames) ]
+    pack $dimframe.0a  $dimframe.0 $dimframe.1 $dimframe.2 $dimframe.3   -side top -fill x -expand t
+
+
+    label $dimframe.4 -text "Voxel Dimensions"
+    iwidgets::entryfield $dimframe.a0 -labeltext "x (mm):" -fixed 10 -width 6 -validate real -textvariable [ itcl::scope  thisparam($this,import_xsp) ]
+    iwidgets::entryfield $dimframe.a1 -labeltext "y (mm):" -fixed 10 -width 6 -validate real -textvariable [ itcl::scope  thisparam($this,import_ysp) ]
+    iwidgets::entryfield $dimframe.a2 -labeltext "z (mm):" -fixed 10 -width 6 -validate real -textvariable [ itcl::scope  thisparam($this,import_zsp) ]
+    pack  $dimframe.4 $dimframe.a0 $dimframe.a1 $dimframe.a2  -side top -fill x -expand t
+
+
+    # Series Information
+    set multiframe  [ iwidgets::Labeledframe $otherframe.top -labelpos n -labeltext "File Series"].childsite
+    pack $otherframe.top -side top -fill x -expand f
+    iwidgets::entryfield $multiframe.0 -labeltext "Begin File:" -fixed 10 -width 6 -validate numeric -textvariable [ itcl::scope  thisparam($this,import_bottomslice) ]
+    iwidgets::entryfield $multiframe.1 -labeltext "End File:"   -fixed 10 -width 6 -validate numeric -textvariable [ itcl::scope  thisparam($this,import_topslice) ]
+    pack  $multiframe.0 $multiframe.1 -side top -fill x -expand f 
+    
+    
+    set byteframe  [ iwidgets::Labeledframe $otherframe.mid -labelpos n -labeltext "File Info"].childsite
+    pack $otherframe.mid -side top -fill x -expand f
+
+    iwidgets::entryfield $byteframe.1 -labeltext "Header Offset:" -fixed 10 -width 6 -validate numeric -textvariable [ itcl::scope  thisparam($this,import_skip) ]
+    set w [ [ iwidgets::labeledwidget  $byteframe.2 -labeltext "Bytes/Voxel:"] childsite ]
+    tk_optionMenu $w.m [ itcl::scope thisparam($this,import_numbytes) ] "1" "2" "4"
+    pack $w.m -side left
+    set w [ [ iwidgets::labeledwidget  $byteframe.3 -labeltext "Swap Voxels:"] childsite ]
+    checkbutton $w.3 -variable [ itcl::scope  thisparam($this,import_swapbytes) ] -text ""
+    pack $w.3 -side left
+
+    set w [ [ iwidgets::labeledwidget  $byteframe.4 -labeltext "MR Mode:"] childsite ]
+    tk_optionMenu $w.m [ itcl::scope thisparam($this,import_mrmode)]  [ lindex $mr_modes 0 ] 
+    pack $w.m -side left
+    for { set k 0 } { $k < [ llength $mr_modes ] } { incr k } {
+	if { $k > 0 } {
+	    $w.m.menu add radio -variable [ itcl::scope thisparam($this,import_mrmode)] -label [ lindex $mr_modes $k ]
+	}
+	eval "$w.m.menu entryconfigure $k -command { $this configure -need_load 1 }"
+    }
+
+
+    pack $byteframe.1 $byteframe.2 $byteframe.3  $byteframe.4 -side top -fill x -expand f
+    
+    set mframe  [ iwidgets::Labeledframe $otherframe.bot -labelpos n -labeltext "Orientation"].childsite
+    pack $otherframe.bot -side top -fill x -expand f
+    set w [ [ iwidgets::labeledwidget  $mframe.1 -labeltext "Orientation:"] childsite ]
+    tk_optionMenu $w.m [ itcl::scope  thisparam($this,import_orient) ] "Axial" "Coronal" "Sagittal" 
+    for { set k 0 } { $k < 3 } { incr k } {
+	eval "$w.m.menu entryconfigure $k -command { $this configure -need_load 1 }"
+    }
+    pack $w.m -side left
+
+    set w [ [ iwidgets::labeledwidget  $mframe.2 -labeltext "Flip:"] childsite ]
+    tk_optionMenu $w.m [ itcl::scope thisparam($this,import_flip)]  [ lindex $flips 0 ] 
+    pack $w.m -side left
+    for { set k 0 } { $k < [ llength $flips ] } { incr k } {
+	if { $k > 0 } {
+	    $w.m.menu add radio -variable [ itcl::scope thisparam($this,import_flip)] -label [ lindex $flips $k ]
+	}
+	eval "$w.m.menu entryconfigure $k -command { $this configure -need_load 1 }"
+    }
+
+
+    
+    pack  $mframe.1 $mframe.2  -side top -fill x -expand f
+
+    
+
+    
+}
+
+# -------------------------------------------------------------------------------------------
+#  
+#    Image Load Stuff
+#
+# -------------------------------------------------------------------------------------------
+
+# ---------------------------------------------------------------------------------
+#   Signa LX Stuff
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclimageimport::ProcessSignaFilename {  f } {
+	
+    set pa(name) f
+    set pa(0) 1
+    set pa(1) 1
+    
+    set first [ string last "i" $f ] 
+    set pa(name) [ string range $f 0 $first ]
+    
+    set flag 0
+    
+    while { $flag == 0 } {
+	set tmpname "$pa(name)$pa(1)"
+	set tmpname2 "$pa(name)$pa(1).gz"
+	if { [ file exists $tmpname ] ==1 || [ file exists $tmpname2 ]==1 } {
+	    incr pa(1)
+	} else {
+	    set flag 1 
+	    set pa(1) [ expr $pa(1) -1 ]
+	}
+    }
+    
+    set pa_list [ array get  pa ]
+    return $pa_list
+}
+
+# ---------------------------------------------------------------------------------
+#   Read Header
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclimageimport::ReadHeader { }  {
+
+    global tcl_platform
+    
+    set orient 0
+    set thisparam($this,import_bottomslice) -1 ; set thisparam($this,import_topslice) -1 ; set thisparam($this,import_orient) "Axial"
+    set thisparam($this,import_xsp) 1.5;      set thisparam($this,import_ysp) 1.5;      set thisparam($this,import_zsp) 1.5;
+    set thisparam($this,import_width) 128 ;   set thisparam($this,import_height) 128 ;  set thisparam($this,import_swapbytes) 0 ; set thisparam($this,import_numbytes) 2;
+    set thisparam($this,import_skip) 0
+    set thisparam($this,import_flip) "None"
+    
+    switch -exact $thisparam($this,image_type) {
+	"Analyze" {
+	    set ana_2 [  vtkpxAnalyzeImageSourceOld [ pxvtable::vnewobj ] ]
+	    $ana_2 SetFilePrefix $thisparam($this,currentfilename)
+	    
+	    set bits [ $ana_2 ReadHeaderFile ]
+	    if { $bits != 0 } {
+			set thisparam($this,import_topslice)    -1
+			set thisparam($this,import_bottomslice) -1
+			set thisparam($this,import_xsp)         [ lindex [$ana_2 GetDataSpacing ] 0 ]
+			set thisparam($this,import_ysp)         [ lindex [$ana_2 GetDataSpacing ] 1 ]
+			set thisparam($this,import_zsp)         [ lindex [$ana_2 GetDataSpacing ] 2 ]
+			set thisparam($this,import_width)       [ lindex [$ana_2 GetDataDimensions ] 0 ]
+			set thisparam($this,import_height)       [ lindex [$ana_2 GetDataDimensions ] 1 ]
+			set thisparam($this,num_frames) [ $ana_2 GetNumTimeFrames ]
+			set thisparam($this,num_slices) [ $ana_2 GetNumSlices ]
+			set orient [ $ana_2 GetOrientation ] 
+			if { $bits < 0 } {
+				set thisparam($this,import_swapbytes) 1 
+				set bits [ expr -1.0 *bits ]
+			} else {
+				set thisparam($this,import_swapbytes) 0
+			}
+		set thisparam($this,import_numbytes) [ expr $bits /8 ]
+	    }
+	    catch {$ana_2 Delete }
+	}
+	"Varian" {
+		set varian [ vtkbisVarianSource [ pxvtable::vnewobj ] ] 
+		$varian SetFilePrefix $thisparam($this,currentfilename)
+		set varianreader [ $varian ReadHeaderFile ] 
+		if { $varianreader !=0 } {
+			set thisparam($this,import_topslice)    -1
+			set thisparam($this,import_bottomslice) -1
+			set thisparam($this,import_xsp)         [ lindex [$varian GetDataSpacing ] 0 ]
+			set thisparam($this,import_ysp)         [ lindex [$varian GetDataSpacing ] 1 ]
+			set thisparam($this,import_zsp)         [ lindex [$varian GetDataSpacing ] 2 ]
+			set thisparam($this,import_width)       [ lindex [$varian GetDataDimensions ] 0 ]
+			set thisparam($this,import_height)       [ lindex [$varian GetDataDimensions ] 1 ]
+			set thisparam($this,num_frames) [ $varian GetNumTimeFrames ]
+			set thisparam($this,num_slices) [ $varian GetNumSlices ]
+			set orient [ $varian GetOrientation ] 
+			if { $varianreader < 0 } {
+			    set thisparam($this,import_swapbytes) 1 
+			    set varianreader [ expr -1.0 *varianreader ]
+			} else {
+			    set thisparam($this,import_swapbytes) 0
+			}
+		set thisparam($this,import_numbytes) [ expr $varianreader /8 ]
+		}	    
+	    	catch {$varian Delete }					
+	}
+	"Prism (SPECT)" {
+	    set ana_2 [  vtkpxPickerPrismSource [ pxvtable::vnewobj ] ]
+	    $ana_2 SetFilePrefix $thisparam($this,currentfilename)
+	    
+	    set bits [ $ana_2 ReadHeaderFile ]
+	    if { $bits != 0 } {
+		set thisparam($this,import_topslice)    -1
+		set thisparam($this,import_bottomslice) -1
+		set thisparam($this,import_xsp)         [ lindex [$ana_2 GetSpacing ] 0 ]
+		set thisparam($this,import_ysp)         [ lindex [$ana_2 GetSpacing ] 1 ]
+		set thisparam($this,import_zsp)         [ lindex [$ana_2 GetSpacing ] 2 ]
+		set thisparam($this,import_width)       [ lindex [$ana_2 GetDimensions ] 0 ]
+		set thisparam($this,import_height)       [ lindex [$ana_2 GetDimensions ] 1 ]
+		set thisparam($this,num_frames) [ $ana_2 GetNumTimeFrames ]
+		set thisparam($this,num_slices) [ $ana_2 GetNumSlices ]
+		set orient [ $ana_2 GetOrientation ] 
+		if { $bits < 0 } {
+		    set thisparam($this,import_swapbytes) 1 
+		    set bits [ expr -1.0 *bits ]
+		} else {
+		    set thisparam($this,import_swapbytes) 0
+		}
+		set thisparam($this,import_numbytes) [ expr $bits /8 ]
+	    }
+	    catch {$ana_2 Delete }
+	    set thisparam($this,import_flip) "Slice Order(Z)"
+	}
+	"Signa Spr" {
+	    set spr  [ pxvtable::vnewobj ]
+	    
+	    if { [ ::pxtclreadsprheader::ReadHeader  $spr $thisparam($this,currentfilename) ] > 0 } {
+		
+		set thisparam($this,num_frames) [ pxvtable::getvariable $spr numframes ]
+		set thisparam($this,num_slices) [ pxvtable::getvariable $spr numslices ]
+		set thisparam($this,import_topslice)    -1
+		
+		set thisparam($this,import_bottomslice) -1
+		set thisparam($this,import_xsp)         [ pxvtable::getvariable $spr spacingx]
+		set thisparam($this,import_ysp)         [ pxvtable::getvariable $spr spacingy]
+		set thisparam($this,import_zsp)         [ pxvtable::getvariable $spr spacingz]
+		set thisparam($this,import_width)       [ pxvtable::getvariable $spr width]
+		set thisparam($this,import_height)      [ pxvtable::getvariable $spr height]
+		set thisparam($this,import_swapbytes) 1
+		if { [ pxvtable::getvariable $spr orient] == "COR" } { 
+		    set orient 1 
+		} 
+	    }
+	}
+	
+	"Nmr47" {
+	    set header [ pxvtable::vnewobj ]
+	    if { [ ::pxtclbrukerheader::ReadHeader $header $thisparam($this,currentfilename) ] > 0 } {
+		set thisparam($this,num_frames) [ pxvtable::getvariable $header dim3 ]
+		set thisparam($this,num_slices) [ pxvtable::getvariable $header dim2 ]
+		set thisparam($this,import_topslice)    -1
+		
+		set thisparam($this,import_bottomslice) -1
+		set thisparam($this,import_xsp)         [ pxvtable::getvariable $header sp0]
+		set thisparam($this,import_ysp)         [ pxvtable::getvariable $header sp1]
+		set thisparam($this,import_zsp)         [ pxvtable::getvariable $header sp2]
+		set thisparam($this,import_width)       [ pxvtable::getvariable $header dim0]
+		set thisparam($this,import_height)      [ pxvtable::getvariable $header dim1]
+		set orient 0
+	    } 
+	    unset header
+	}
+	
+	"DICOM" {
+	    set thisparam($this,import_flip) "YZ"
+	}
+	
+	
+	"Signa LX" {
+	    set lx_reader_2 [ vtkpxSignaLXImageSource [ pxvtable::vnewobj ]  ]
+	    set f $thisparam($this,currentfilename)
+	    $lx_reader_2 SetFilePrefix [ string range $f 0 [ string last "i" $f ]]
+	    if { [ $lx_reader_2 ReadHeaderFile ] !=0 } {
+		set thisparam($this,import_xsp)         [ lindex [$lx_reader_2 GetDataSpacing ] 0 ]
+		set thisparam($this,import_ysp)         [ lindex [$lx_reader_2 GetDataSpacing ] 1 ]
+		set thisparam($this,import_zsp)         [ lindex [$lx_reader_2 GetDataSpacing ] 2 ]
+		set thisparam($this,import_width)       [ lindex [$lx_reader_2 GetDataDimensions ] 0 ]
+		set thisparam($this,import_height)      [ lindex [$lx_reader_2 GetDataDimensions ] 1 ]
+		set pa_list [ pxitclimageimport::ProcessSignaFilename $f ] 
+		array set pa $pa_list
+		set thisparam($this,import_topslice)    $pa(1)
+		set thisparam($this,import_bottomslice) $pa(0)
+		set thisparam($this,num_slices) [ expr $pa(1) - $pa(0) + 1 ]
+		set thisparam($this,num_frames) 1
+		set orient [ $lx_reader_2 GetOrientation ] 
+	    }
+	    catch { $lx_reader_2 Delete }
+	}
+
+	"Raw MR" {
+	    set thisparam($this,num_frames) 1
+	    set thisparam($this,import_numbytes) 4
+	    if { $tcl_platform(byteOrder) == "littleEndian" } { 
+		set thisparam($this,import_swapbytes) 1
+	    } else {
+		set thisparam($this,import_swapbytes) 0
+	    }
+
+	    set sz [ file size $thisparam($this,currentfilename) ]
+	    set thisparam($this,num_slices) 0
+	    set sq 256
+	    while { $thisparam($this,num_slices) < 1 && $sq > 8 } {
+		set thisparam($this,import_width)  $sq 
+		set thisparam($this,import_height) $sq
+		set thisparam($this,num_slices) [ expr $sz / ($sq*$sq*8) ]
+		set sq [ expr $sq /2 ]
+	    }
+	}
+    }
+    
+    if { $orient < 0 } { set orient 0 } 
+    if { $orient > 2 } { set orient 2 }
+    set thisparam($this,import_orient) [ lindex $orientations $orient ]
+    $notebook view "Properties"
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::ImportTIFF { fname minslice maxslice comment } {
+
+    set tif_reader [ vtkTIFFReader [ pxvtable::vnewobj ]  ]
+    
+    if { $minslice == - 1 || $maxslice == - 1 } {
+	$tif_reader SetFileName $fname
+    } else {
+	set suffix ".tiff"
+	if { [ string first ".tif" $fname ] > 0 } {
+	    set suffix ".tif" 
+	}
+
+	set first [ string first "_" $fname ] 
+	if { $first > 0 } {
+	    set prefix [ string range $fname 0 [expr $first - 1] ]
+	    $tif_reader SetFilePattern "%s_%04d$suffix"
+	    $tif_reader SetFilePrefix $prefix
+	} else  {
+	    set first [ string last "." $fname ] 
+	    set prefix [ string range $fname 0 [expr $first - 1] ]
+	    $tif_reader SetFilePattern "%s.%d"
+	    $tif_reader SetFilePrefix $prefix
+	}
+
+	#	puts stderr "Prefix=$prefix, slices=$minslice:$maxslice"
+	
+	$tif_reader SetDataExtent 0 511 0 511 $minslice $maxslice
+    }
+    
+    set thisparam($this,num_frames) 1
+    set thisparam($this,num_slices) [ expr $maxslice- $minslice + 1]
+    SetFilterCallbacks $tif_reader $comment
+    $tif_reader Update
+
+    #    set dm [ [ $tif_reader GetOutput ] GetDimensions ]
+    #    puts stdout "dm=$dm"
+
+    set inf [ vtkImageChangeInformation New ]
+    $inf SetInput [ $tif_reader GetOutput ]
+    $inf SetOutputExtentStart 0 0 0
+    $inf Update
+
+    $currentresults ShallowCopyImage [$inf GetOutput]
+    $tif_reader Delete
+    $inf Delete
+    return 1
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::ImportPNM  { fname minslice maxslice comment } {
+
+    set pnm_reader [   vtkPNMReader [ pxvtable::vnewobj ] ]
+    if { $minslice == - 1 || $maxslice == - 1 } {
+	$pnm_reader SetFileName $fname
+    } else {
+	set suffix ".pnm"
+	if { [ string first ".pbm" $fname ] > 0 } {
+	    set suffix ".pbm" 
+	} else {
+	    if { [ string first ".ppm" $fname ] > 0 } {
+		set suffix ".pbm" 
+	    } else {
+		if { [ string first ".pgm" $fname ] > 0 } {
+		    set suffix ".pgm" 
+		}
+	    }
+	}
+	
+	set first [ string first "_" $fname ] 
+	if { $first > 0 } {
+	    set prefix [ string range $fname 0 [expr $first - 1] ]
+	    $pnm_reader SetFilePattern "%s_%04d$suffix"
+	    $pnm_reader SetFilePrefix $prefix
+	} else  {
+	    set first [ string last "." $fname ] 
+	    set prefix [ string range $fname 0 [expr $first - 1] ]
+	    $pnm_reader SetFilePattern "%s.%d"
+	    $pnm_reader SetFilePrefix $prefix
+	}
+	$pnm_reader SetDataExtent 0 511 0 511 $minslice $maxslice
+    }
+    SetFilterCallbacks $pnm_reader $comment
+    $pnm_reader Update
+    set thisparam($this,num_frames) 1
+    set thisparam($this,num_slices) [ expr $maxslice- $minslice + 1]
+
+    set inf [ vtkImageChangeInformation New ]
+    $inf SetInput [ $png_reader GetOutput ]
+    $inf SetOutputExtentStart 0 0 0
+    $inf Update
+
+    
+    $currentresults ShallowCopyImage [$inf_reader GetOutput]
+    $inf Delete
+    $pnm_reader Delete
+    return 1
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::ImportBMP  { fname minslice maxslice comment } {
+
+    set bmp_reader [  vtkBMPReader [ pxvtable::vnewobj ] ]
+    if { $minslice == - 1 || $maxslice == - 1 } {
+	$bmp_reader SetFileName $fname
+    } else {
+	set suffix ".BMP"
+	if { [ string first ".bmp" $fname ] > 0 } {
+	    set suffix ".bmp"
+	}
+	set first [ string first "_" $fname ] 
+	if { $first > 0 } {
+	    set prefix [ string range $fname 0 [expr $first - 1] ]
+	    $bmp_reader SetFilePattern "%s_%04d$suffix"
+	    $bmp_reader SetFilePrefix $prefix
+	} else {
+	    set first [ string last "." $fname ] 
+	    set prefix [ string range $fname 0 [expr $first - 1] ]
+	    $bmp_reader SetFilePattern "%s.%d"
+	    $bmp_reader SetFilePrefix $prefix
+	}
+	$bmp_reader SetDataExtent 0 511 0 511 $minslice $maxslice
+    }
+    $bmp_reader Update
+    set thisparam($this,num_frames) 1
+    set thisparam($this,num_slices) [ expr $maxslice- $minslice + 1]
+    
+    SetFilterCallbacks $bmp_reader $comment
+    $currentresults ShallowCopyImage [$bmp_reader GetOutput]
+    $bmp_reader Delete
+    return 1
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::ImportJPEG { fname minslice maxslice comment } {
+
+    set jpg_reader [ vtkJPEGReader [ pxvtable::vnewobj ]  ]
+    
+    if { $minslice == - 1 || $maxslice == - 1 } {
+	$jpg_reader SetFileName $fname
+    } else {
+	set suffix ".jpeg"
+	if { [ string first ".jpg" $fname ] > 0 } {
+	    set suffix ".jpg" 
+	}
+	
+	set first [ string last "_" $fname ] 
+
+	if { $first > 0 } {
+	    set prefix [ string range $fname 0 [expr $first - 1] ]
+	    $jpg_reader SetFilePattern "%s_%04d$suffix"
+	    puts stderr "%s_%04d$suffix, $prefix"
+	    $jpg_reader SetFilePrefix $prefix
+	} else  {
+	    set first [ string last "." $fname ] 
+	    set prefix [ string range $fname 0 [expr $first - 1] ]
+	    $jpg_reader SetFilePattern "%s.%d"
+	    $jpg_reader SetFilePrefix $prefix
+	}
+	
+	puts stderr "slices = $minslice:$maxslice"
+	$jpg_reader SetDataExtent 0 1023 0 1023 $minslice $maxslice
+    }
+    
+    set thisparam($this,num_frames) 1
+    set thisparam($this,num_slices) [ expr $maxslice- $minslice + 1]
+    SetFilterCallbacks $jpg_reader $comment
+    $jpg_reader Update
+    $currentresults ShallowCopyImage [$jpg_reader GetOutput]
+    $jpg_reader Delete
+    return 1
+}
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclimageimport::ImportSignaSpr  { fname minslice maxslice comment } {
+
+    set ana_reader  [  vtkpxAnalyzeImageSourceOld [ pxvtable::vnewobj ]  ]
+    set spr [ pxvtable::vnewobj ]
+    ::pxtclreadsprheader::ReadHeader  $spr $fname
+    ::pxtclreadsprheader::SetAnalyzeImageSource $spr $ana_reader
+    $ana_reader SetSwapBytes $thisparam($this,import_swapbytes)
+    SetFilterCallbacks $ana_reader $comment
+    $ana_reader Update
+    $currentresults SetFromAnalyzeSource $ana_reader
+    [ $currentresults GetImage ] SetOrigin 0.0 0.0 0.0
+    $ana_reader Delete
+    return 1
+	
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::ImportSignaLX  { fname minslice maxslice comment } {
+
+    set ok 1
+    set lx_reader [ vtkpxSignaLXImageSource [ pxvtable::vnewobj ]  ]
+    $lx_reader SetFilePrefix [ string range $fname 0 [ string last "i" $fname ]]
+    set a [ $lx_reader ReadHeaderFile ]
+    if { $a != 0 } {
+	set pa_list [ pxitclimageimport::ProcessSignaFilename $fname ] 
+	array set pa $pa_list
+	
+	SetFilterCallbacks $lx_reader $comment
+	$lx_reader Load $pa(name) $minslice $maxslice 
+	set thisparam($this,num_frames) 1
+	set thisparam($this,num_slices) [ expr $maxslice- $minslice + 1]
+	$currentresults SetFromAnalyzeSource $lx_reader 
+    } else {
+	set ok 0 
+    }
+    $lx_reader Delete
+    return $ok
+	
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::ImportBinary  { fname minslice maxslice comment } {
+
+    set ana_reader2  [  vtkpxAnalyzeImageSourceOld [ pxvtable::vnewobj ]  ]
+    $ana_reader2 SetHeaderInfo  $thisparam($this,import_width) $thisparam($this,import_height) 1 1 $thisparam($this,import_swapbytes) $thisparam($this,import_numbytes)
+    $ana_reader2 SetDataOrigin 0.0 0.0 0.0
+    
+    if { $thisparam($this,import_xsp) < 0.0 } {
+	set thisparam($this,import_xsp) [ expr abs(10.0*$thisparam($this,import_xsp)/$thisparam($this,import_width)) ]
+	set thisparam($this,import_ysp) [ expr abs(10.0*$thisparam($this,import_ysp)/$thisparam($this,import_height)) ]
+	set thisparam($this,import_zsp) [ expr abs(10.0*$thisparam($this,import_zsp)/$thisparam($this,num_slices)) ]
+	$ana_reader2 SetDataSpacing $thisparam($this,import_xsp) $thisparam($this,import_ysp) $thisparam($this,import_zsp)
+	puts stdout "Spacing = [ $ana_reader2 GetDataSpacing ]"
+    } else {
+	$ana_reader2 SetDataSpacing $thisparam($this,import_xsp) $thisparam($this,import_ysp) $thisparam($this,import_zsp)
+	puts stdout "Spacing = [ $ana_reader2 GetDataSpacing ]"
+    }
+    $ana_reader2 SetHeaderSize $thisparam($this,import_skip)
+    
+    if { $minslice != - 1 && $maxslice != - 1 } {
+	$ana_reader2 SetImageRange 1 $thisparam($this,num_slices)
+    } else {
+	set bt [ file size $fname ]
+	catch { set maxslice [ expr $bt / ( $thisparam($this,import_width)*$thisparam($this,import_height)*$thisparam($this,import_numbytes) ) ] }
+	set minslice 1
+	$ana_reader2 SetImageRange $minslice $maxslice
+    }
+    
+    set thisparam($this,num_frames) 1
+    set thisparam($this,num_slices) [ expr $maxslice- $minslice + 1]
+    $ana_reader2 SetFilePrefix $fname
+    SetFilterCallbacks $ana_reader2 $comment
+    $ana_reader2 Update
+    $currentresults SetFromAnalyzeSource  $ana_reader2 
+    $ana_reader2 Delete
+    return 1
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::ImportNmr47  { fname minslice maxslice comment } {
+
+    set ok 0
+    set header [ pxtclbrukerheader::init ]
+    ::pxtclbrukerheader::ReadHeader  $header $fname
+    set fname [ ::pxtclbrukerheader::GetFileName $header ]
+    set a [ ::pxtclbrukerheader::LoadPolarComplexProgress $header $fname [$currentresults GetImage] "Auto" "$this ProgressCallback" "$this ProgressCallback" ]
+    if { $a > 0 } {
+	set ok 1
+    }
+    return $ok
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::ImportAnalyze  { fname minslice maxslice comment } {
+
+    set ok 1
+    set ana_reader  [  vtkpxAnalyzeImageSourceOld  [ pxvtable::vnewobj ]  ]
+    $ana_reader SetFilePrefix $fname
+    set a [ $ana_reader ReadHeaderFile ]
+    if { $a != 0 } {
+	SetFilterCallbacks $ana_reader $comment
+	$ana_reader Update
+	$currentresults SetFromAnalyzeSource $ana_reader
+    } else {
+	set ok 0 
+    }
+    
+    $ana_reader Delete
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::ImportDICOM  { fname minslice maxslice comment } {
+
+    set ok 1
+    set ana_reader  [  vtkDICOMImageReader  [ pxvtable::vnewobj ]  ]
+    set dname [ file dirname $fname ]
+    $ana_reader SetDirectoryName $dname
+    SetFilterCallbacks $ana_reader $comment
+    $ana_reader Update
+
+    set dim [ [ $ana_reader GetOutput ] GetDimensions ]
+
+    if { [ lindex $dim 2 ] > 0 } {
+	$currentresults ShallowCopyImage [  $ana_reader GetOutput ]
+	$currentresults CopyImageHeader 0
+	$currentresults configure -filename [ file join $dname  "[ $ana_reader GetPatientName ]_[ $ana_reader GetStudyID ]" ]
+	pxtkprint "Name = [ $currentresults cget -filename ]"
+	set ok 1
+    } else {
+	set ok 0 
+    }
+    
+    $ana_reader Delete
+    return $ok
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::ImportPrism  { fname minslice maxslice comment } {
+
+    set ok 1
+    set ana_reader  [  vtkpxPickerPrismSource  [ pxvtable::vnewobj ]  ]
+    $ana_reader SetFilePrefix $fname
+    set a [ $ana_reader ReadHeaderFile ]
+    if { $a != 0 } {
+	SetFilterCallbacks $ana_reader $comment
+	$ana_reader Update
+	$currentresults SetFromAnalyzeSource $ana_reader
+    } else {
+	set ok 0 
+    }
+    
+    $ana_reader Delete
+    return $ok
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::ImportRawMR  { fname minslice maxslice comment } {
+
+    if { [ file exists $fname ] == 0 } { return 0 }
+    set wd $thisparam($this,import_width)
+    set ht $thisparam($this,import_height)
+    set sl $thisparam($this,num_slices)
+    set sz [ expr $wd*$ht*$sl*$thisparam($this,import_numbytes)*2 ]
+    if { [ file size $fname ] != $sz } {   return 0 }
+
+    set re [ vtkImageReader2 [ pxvtable::vnewobj ]]
+    $re SetFileName $fname
+    switch -exact $thisparam($this,import_numbytes) {
+	"1" { $re SetDataScalarTypeToChar  }
+	"2" { $re SetDataScalarTypeToShort }
+	"4" { $re SetDataScalarTypeToInt   }
+    }
+    $re SetDataExtent 0 [ expr $wd*$ht*$sl -1 ] 0 0 0 0
+    $re SetNumberOfScalarComponents 2
+    $re SetSwapBytes $thisparam($this,import_swapbytes)
+    $re SetHeaderSize $thisparam($this,import_skip)
+    $re Update
+	
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+    $img CopyStructure [ $re GetOutput ]
+    $img SetWholeExtent 0 [ expr $wd -1 ] 0 [ expr $ht -1 ] 0 [ expr $sl - 1 ]
+    $img SetExtent 0 [ expr $wd -1 ] 0 [ expr $ht -1 ] 0 [ expr $sl - 1 ]
+    $img SetDimensions  $wd $ht $sl
+    $img SetSpacing     $thisparam($this,import_xsp) $thisparam($this,import_ysp) $thisparam($this,import_zsp)
+    [ $img  GetPointData ] SetScalars  [[ [ $re GetOutput ] GetPointData ] GetScalars ]
+    $re Delete
+	
+    set pr [ vtkpxProcessRawBrukerFIDImage [ pxvtable::vnewobj ]]
+    $pr SetInput $img
+    $pr PolarComplexModeOn
+    
+    if { $thisparam($this,import_mrmode) == "EchoPlanar" } {
+	$pr SetEchoPlanarMode 1
+    } elseif { $thisparam($this,import_mrmode) == "Conventional (Append)" } {
+	$pr SetConventionalAppendMultiSliceMode 1
+    }
+    $pr SetShiftSpectrum 0
+    
+    set magn [ vtkImageExtractComponents [ pxvtable::vnewobj ]]
+    $magn SetInput [ $pr GetOutput ]
+    $magn SetComponents 1
+    $magn Update
+	
+    set r  [[[[ $magn GetOutput] GetPointData ] GetScalars ] GetRange ]
+    set r1 [ expr abs ([lindex $r 0 ])]
+    set r2 [ expr abs ([lindex $r 1 ])]
+    if { $r1 >= $r2 } { set r2 $r1 }
+    
+    set sc [ vtkImageShiftScale [ pxvtable::vnewobj ]]
+    $sc SetInput [ $magn GetOutput ]
+    $sc SetScale [ expr 4096/($r2+1.0) ]
+    $sc SetOutputScalarTypeToShort 
+    $sc Update
+
+    $currentresults ShallowCopyImage [ $sc GetOutput  ]
+    $magn Delete
+    $pr   Delete
+    $img  Delete
+    $sc   Delete
+    return 1
+}
+
+# ---------------------------------------------------------------------------------
+#   Import Image and Update Parent
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimageimport::ImportImage { } {
+ 
+    if { $thisparam($this,currentfilename) == "" } { 
+	::pxtclutil::Warning "No filename selected\n Cannot load image!"
+	return 
+    }
+    
+    set ok 1
+    set fname $thisparam($this,currentfilename)
+    set minslice $thisparam($this,import_bottomslice)
+    set maxslice $thisparam($this,import_topslice)
+    set comment "Loading Image from [ file tail $fname ] ($minslice:$maxslice)"
+    
+    
+    puts stderr "$comment"
+
+    switch -exact $thisparam($this,image_type) {
+	"TIFF"      { set ok [ ImportTIFF     $fname $minslice $maxslice $comment ] }
+	"JPEG"      { set ok [ ImportJPEG     $fname $minslice $maxslice $comment ] }
+	"BMP"       { set ok [ ImportBMP      $fname $minslice $maxslice $comment ] }
+	"PNM"       { set ok [ ImportPNM      $fname $minslice $maxslice $comment ] }
+	"Signa Spr" { set ok [ ImportSignaSpr $fname $minslice $maxslice $comment ] }
+	"Signa LX"  { set ok [ ImportSignaLX  $fname $minslice $maxslice $comment ] }
+	"Binary"    { set ok [ ImportBinary   $fname $minslice $maxslice $comment ] }
+	"Nmr47"     { set ok [ ImportNmr47    $fname $minslice $maxslice $comment ] }
+	"Analyze"   { set ok [ ImportAnalyze  $fname $minslice $maxslice $comment ] }
+	"Varian"    { set ok [ ImportVarian   $fname $minslice $maxslice $comment ] }
+	"DICOM"     { set ok [ ImportDICOM    $fname $minslice $maxslice $comment ] }
+	"Raw MR"    { set ok [ ImportRawMR    $fname $minslice $maxslice $comment ] }
+	"Prism (SPECT)" { set ok [ ImportPrism    $fname $minslice $maxslice $comment ] }
+    }
+
+    if { $ok == 0 } {
+	::pxtclutil::Warning "Failed to Import image $fname"
+	return
+    } else {
+	set need_load 0
+    }
+}
+
+itcl::body pxitclimageimport::UpdateParent { } { 
+
+    if { $thisparam($this,currentfilename) == "" } {
+	::pxtclutil::Warning "No Image Filename has been selected!"
+	return
+    }
+    
+    if { $need_load == 1 } {
+	ImportImage 
+	set orient [ lsearch -exact $orientations $thisparam($this,import_orient) ]
+	$currentresults CopyImageHeader $orient
+	$currentresults configure -filename $thisparam($this,currentfilename)
+	if { $thisparam($this,image_type) == "Signa LX" } {
+	    set fname $thisparam($this,currentfilename)
+	    $currentresults configure -filename [ string range $fname 0 [ expr [string last "s" $fname ] +1 ]]
+	}
+	$currentresults FlipImage $thisparam($this,import_flip)
+    }
+	
+    SendImageToParent
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclimagenormalization.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclimagenormalization.tcl
new file mode 100644
index 0000000..6734e33
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclimagenormalization.tcl
@@ -0,0 +1,344 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclimagenormalization 1.0
+
+# 	$Id: pxitclimagenormalization.tcl,v 1.4 2003/07/28 18:59:09 xenios Exp xenios $	
+
+
+
+
+
+package require pxitclbaseimagecontrol 1.0
+package require pxitclHistogramWidget 1.0
+
+itcl::class pxitclimagenormalization {
+
+    inherit pxitclbaseimagecontrol
+    
+    variable updatehistogram 0
+    variable histogramwidget 0
+    variable histogram 0 
+
+    private common histinput1 
+    private common histinput2 
+    private common histinput3 
+    private common histinput4 
+    private common histoutput1
+    private common histoutput2
+    private common histoutput3
+    private common histoutput4
+
+    protected variable entrylist ""
+    protected variable entrymode 0
+
+    constructor { par } { 
+	pxitclbaseimagecontrol::constructor $par 
+    } {
+
+	set histinput1($this)   -1; 	set histinput2($this)  100
+	set histinput3($this)  200;	set histinput4($this)   -1
+	set histoutput1($this) 115;	set histoutput2($this) 200
+	set histoutput3($this) 300;	set histoutput4($this)  -1
+    }
+    
+    # ---------------------------------------------------------------------------------
+    #   Create Actual GUI
+    # ---------------------------------------------------------------------------------
+
+    public method Initialize { inpwidg } 
+    public method UpdateHistogram { }
+    public method NormalizeIntensity { }
+    public method HistogramEqualization { }
+    public method ResetHistogram { }
+    public method UpdateModes { mode }
+    public method ComputeAuto { }
+
+    public method SetImage { img } 
+}
+
+
+::itcl::body pxitclimagenormalization::SetImage { img  } {
+    set ok [ pxitclbaseimagecontrol::SetImage $img ]
+    if { $ok == 0 } { return 0 }
+    set updatehistogram 1
+    UpdateHistogram
+    ResetHistogram
+}
+
+# ---------------------------------------------------------------------------------
+#
+# Create Histogram
+#
+# ---------------------------------------------------------------------------------
+itcl::body pxitclimagenormalization::Initialize { widg } {
+
+    if { $initialized == 1 } {
+	return $basewidget
+    }
+
+    set basewidget $widg
+
+    set hist $basewidget ; 	toplevel $hist ; wm withdraw $hist; 
+    wm geometry $hist 700x270 ; wm resizable $hist false false
+    wm title $hist "Histogram Control"
+    wm resizable $hist 0 0
+
+    set bottomf [ frame  $hist.b  -bd 1 -bg white] ; 	
+    set topf    [ frame  $hist.a ]
+    set middlef [ frame  $hist.c -bd 1  ]
+    
+    pack $topf $middlef $bottomf -side top -fill x -expand t -pady 0
+    
+    label $middlef.left -text "Input:" -padx 3;  	label $middlef.right -text "Output: " -padx 3
+    grid $middlef.left -row 0 -column 0; 	grid $middlef.right -column 3 -row 0
+    
+    for { set k 1 } { $k <=2 } { incr k } {
+	if { $k==1 } {
+	    set vaa "histinput"
+	    set direction "left"
+	    set offset 0
+	} else {
+	    set vaa "histoutput"
+	    set direction "right"
+	    set offset 5
+	}
+	
+	for {set i 0 }  {$i <= 3 } { incr i } {
+	    set j [expr $i +1 ]
+
+	    if { $i == 0 } {
+		if { $k == 1 } {
+		    set labname "In:"
+		} else {
+		    set labname "Out:"
+		}
+	    } else {
+		set labname ""
+	    }
+	    
+	    set vbb "${vaa}${j}"
+	    set vb [ itcl::scope ${vbb}($this) ]
+	    eval "iwidgets::entryfield $middlef.${direction}$i -labeltext \"$labname\" -textvariable  $vb -width 5 -validate real"
+	    grid $middlef.${direction}$i -column  [expr $i + $offset ]    -row 0
+
+	    if { $i==0 || $i ==3 } {
+		lappend entrylist $middlef.${direction}$i
+	    }
+	}
+	
+    }
+    
+    eval "button $middlef.bu1 -text M1 -pady 1 -padx 3 -command { $this UpdateModes  1  }"
+    eval "button $middlef.bu2 -text M2 -pady 1 -padx 1 -command { $this UpdateModes  2  }"
+    eval "button $middlef.bu3 -text M3 -pady 1 -padx 1 -command { $this UpdateModes  3  }"
+    eval "button $middlef.bu4 -text All -pady 1 -padx 1 -command { $this UpdateModes -2  }"
+
+    grid $middlef.bu1 -column 16 -row 0
+    grid $middlef.bu2 -column 17 -row 0
+    grid $middlef.bu3 -column 18 -row 0
+    grid $middlef.bu4 -column 19 -row 0
+    
+    eval "button $bottomf.btn3  -text \"Normalize\" -command { $this NormalizeIntensity }"
+    eval "button $bottomf.btn3b  -text \"Histogram Eq\" -command { $this HistogramEqualization }"
+    pack $bottomf.btn3 $bottomf.btn3b -fill x -expand f -side left -padx 2
+    if { $parent != 0 } {
+	eval "button $bottomf.l1  -text \"Copy Results To Image\" -command { $parent CopyResultsToImage }"
+	eval "button $bottomf.l2  -text \"Undo Copy \" -command { $parent RevertToPreviousImage }"
+	pack $bottomf.l1 $bottomf.l2 -side left -padx 2
+    }
+
+    eval "button $bottomf.btn2  -text  Close -command { $this HideWindow }"
+    
+
+    pack $bottomf.btn2 -fill x -expand f -side right
+    
+    set histogram [ ::pxitclHistogramWidget \#auto $this ]
+    set histogramwidget [ $histogram Initialize  $topf.r2]
+    $histogram SetImage  $currentimage 
+    pack $histogramwidget -side left -padx 3 -pady 3 -fill both -expand t	    
+    $histogram Bind  1
+    set updatehistogram 1
+    set initialized 1
+   
+    eval "$histogram configure -callback \"$this UpdateModes -1\" "
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+
+    DisableUI $entrylist
+
+    return $basewidget
+}
+
+itcl::body pxitclimagenormalization::UpdateHistogram {  } {
+	
+    if {$updatehistogram == 1 }   {
+	$histogram SetImage $currentimage 
+	set updatehistogram 0
+    }
+}
+
+# ---------------------------------------------------------------------------------
+#   Normalize Intensity
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclimagenormalization::NormalizeIntensity { } {
+	
+    set dim2 [ $currentimage GetImageSize ]
+    if { $dim2  < 2 } { 
+	::pxtclutil::Warning "No Image in Memory\n Cannot Normalize Intensity!"
+	return 
+    }
+	
+    WatchOn 
+	
+    set norm [  vtkpxImageNormalizeIntensity [ pxvtable::vnewobj ] ]
+
+    $norm SetInput [ $currentimage GetImage ]
+    $norm SetInputLevel1   $histinput1($this) ;    $norm SetInputLevel2   $histinput2($this) 
+    $norm SetInputLevel3   $histinput3($this) ;    $norm SetInputLevel4   $histinput4($this) 
+    $norm SetOutputLevel1  $histoutput1($this);    $norm SetOutputLevel2  $histoutput2($this)
+    $norm SetOutputLevel3  $histoutput3($this);    $norm SetOutputLevel4  $histoutput4($this)
+    $norm SetOutputLevel0  0
+
+    $this ProgressCallback $norm "Normalizing Intensity"
+    SetFilterCallbacks $norm "Normalizing Intensity"
+    $norm Update
+	
+    $currentresults ShallowCopyImage  [$norm GetOutput]
+    $currentresults CopyImageHeader [ $currentimage GetImageHeader ]
+    $norm Delete 
+    $currentresults configure -filename [ AddPrefix [ $currentimage cget -filename ] Norm ]
+    SendResultsToParent
+    $currentresults UnLoad
+    WatchOff
+}
+    
+itcl::body pxitclimagenormalization::ResetHistogram  { } {
+
+    if { $histogramwidget != 0 } {
+	$histogram configure -LOWER_LEVEL -1
+	$histogram configure -UPPER_LEVEL -1
+	$histogram configure -LOWER_BOUND -1
+	$histogram configure -UPPER_BOUND -1
+	$histogram Render
+	set updatehistogram 0
+    }
+}
+
+    
+itcl::body pxitclimagenormalization::UpdateModes { val } {
+    
+    set lowv  [ $histogram cget -LOWER_LEVEL ]
+    set highv [ $histogram cget -UPPER_LEVEL ]
+
+    
+    set histinput2($this) $lowv
+    set histinput3($this) $highv
+
+
+    if { $val == - 1 } {
+	return
+    }
+    
+    if { $val == -2 } {
+	EnableUI $entrylist
+	return
+    }
+
+	
+    switch -exact $val {
+	1 {
+	    set histoutput1($this) 115
+	    set histoutput2($this) 200
+	    set histoutput3($this) 275
+	    set histoutput4($this) 350
+	}
+	2 {
+	    set histoutput1($this) 115
+	    set histoutput2($this) 200
+	    set histoutput3($this) 285
+	    set histoutput4($this) 365
+	}
+	3 {
+	    set histoutput1($this) 115
+	    set histoutput2($this) 200
+	    set histoutput3($this) 300
+	    set histoutput4($this) 400
+	}
+    }
+	
+    if { $val <=3  } {
+	
+	set diffi [expr $highv - $lowv ]
+	set diffo [expr $histoutput3($this)-$histoutput2($this) ]
+	set a [ expr ( $histoutput2($this) - $histoutput1($this) ) / $diffo ]
+	set histoutput4($this) [ expr $histoutput3($this) + $diffo ]
+	set histinput1($this)  [ expr $lowv-$a*$diffi ]
+	set histinput4($this)  [ expr $highv+$diffi ]
+	DisableUI $entrylist
+    }
+}
+
+
+itcl::body pxitclimagenormalization::ComputeAuto { } {
+
+    return
+}
+
+# ---------------------------------------------------------------------------------
+#   Histogram Equalization
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclimagenormalization::HistogramEqualization { } {
+	
+    set dim2 [ $currentimage GetImageSize ]
+    if { $dim2  < 2 } { 
+	::pxtclutil::Warning "No Image in Memory\n Cannot Perform Histogram Equalization!"
+	return 
+    }
+	
+    WatchOn 
+	
+    set histeq [  vtkpxImageHistogramEqualization [ pxvtable::vnewobj ] ]
+    $histeq SetInput [ $currentimage GetImage ]
+    $histeq SetLowerThreshold   $histinput2($this) 
+    $histeq SetUpperThreshold   $histinput3($this)
+    $histeq SetNumberOfBins     256
+    $this ProgressCallback $histeq "Histogram Equalization"
+    SetFilterCallbacks $histeq "Histogram Equalization"
+    $histeq Update
+	
+    $currentresults ShallowCopyImage  [$histeq GetOutput]
+    $currentresults CopyImageHeader [ $currentimage GetImageHeader ]
+    $histeq Delete 
+    $currentresults configure -filename [ AddPrefix [ $currentimage cget -filename ] Histeq ]
+    SendResultsToParent
+    $currentresults UnLoad
+    WatchOff
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitcllistselector.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitcllistselector.tcl
new file mode 100644
index 0000000..dbf1220
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitcllistselector.tcl
@@ -0,0 +1,168 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitcllistselector 1.0
+
+# 	$Id: pxitcllistselector.tcl,v 1.2 2003/05/09 14:05:45 papad Exp papad $	
+
+
+
+
+
+
+package require  Iwidgets 4.0.0
+
+
+# ---------------------------------------------------------------------------
+#  Ancilliary Class pxitclsubject
+# ---------------------------------------------------------------------------
+itcl::class pxitcllistselector {
+
+    public variable basewidget    0 
+    public variable rightspace    0
+    public variable listbox       0
+    public variable singleoutput  0
+    protected variable laststate  0
+    protected variable textbox    0
+    protected variable buttonlist 0
+    protected variable done       0
+    protected variable selectallbutton 0
+
+    constructor { widget } {
+	Initialize $widget
+    }
+
+    destructor  { 
+
+	wm destroy $basewidget
+    }
+
+    protected method Initialize { widget } 
+    public method Cancel { } { set laststate  0 ; set done 1}
+    public method OK { }   { set laststate  1  ; set done 1}
+    public method Activate { listofobjects {defaultlist "" } { comment "" } { title "" } }
+    public method SelectAll { }   { $listbox selection set 0 end }
+    public method SelectNone { } {  $listbox selection clear 0 end }
+    public method GetSelectedIndices { }
+    public method SetSingleSelect { mode }
+    public method GetLastState { } { return $laststate }
+}
+
+# ---------------------------------------------------------------------------
+# Get Description
+# ---------------------------------------------------------------------------
+itcl::body pxitcllistselector::Initialize { widget  } {
+
+    set basewidget $widget
+    iwidgets::dialogshell $basewidget
+    $basewidget configure -modality application
+    
+    set base [ $basewidget childsite ]
+
+    set textbox [ text $base.top  -width 45 -height 6 -font { fixed 10 } ]
+    set bot [ frame $base.bot ]
+    pack $base.top -side top -expand f -fill x
+    pack $bot -side bottom -expand true -fill both
+
+    set listbox [ iwidgets::scrolledlistbox $bot.a -vscrollmode dynamic -hscrollmode none -selectmode multiple -labelpos nw -visibleitems 15x10 ]
+    set rightspace [ frame  $bot.b ]
+    pack $listbox $rightspace -side left -expand t -fill both -padx 1
+
+    set selectallbutton [ eval "button $rightspace.all -text \"Select All\" -command { $this SelectAll }" ]
+    eval "button $rightspace.none -text \"Select None\" -command { $this SelectNone }"
+    pack $rightspace.all $rightspace.none -side bottom -expand false -fill x -pady 5 -padx 2
+
+    set buttonlist [ list $rightspace.all $rightspace.none ]
+    
+    eval "$basewidget add ok -text OK -command { $this OK ; wm withdraw $basewidget }"
+    eval "$basewidget add dismiss -text Cancel -command { $this Cancel ; wm withdraw $basewidget }"
+
+    $basewidget default dismiss
+    $basewidget configure -title "Selection List"
+}
+
+# ---------------------------------------------------------------------------
+
+itcl::body pxitcllistselector::Activate { listofobjects {defaultlist "" } { comment "" } { title "" }  } {
+
+    if { [ string length $title ] > 0 } {
+	$basewidget configure -title $title
+    }
+
+    if { [ string length $comment ] > 0 } {
+	$textbox delete 1.0 end
+	$textbox insert end $comment
+	$textbox see 1.0
+    }
+
+    $listbox delete 0 end
+
+    for { set i 0 } { $i < [ llength $listofobjects ] } { incr i } {
+	$listbox insert end [ lindex $listofobjects $i ]
+    }
+
+    # Fix for single output/multiple output
+    if { $singleoutput == 1 } {
+	set mode "single"
+	set stmode "disabled"
+    } else {
+	set mode "multiple"
+	set stmode "normal"
+    }
+    
+    $listbox configure -selectmode $mode
+    for { set i 0 } { $i < [ llength $buttonlist ] } { incr i }  {
+	[ lindex $buttonlist $i ] configure -state $stmode
+    }
+
+
+    if { $defaultlist != "" } {
+	for { set i 0 } { $i < [ llength $defaultlist ] } { incr i } {
+	    set c [ lindex $defaultlist $i ]
+	    $listbox selection set $c $c
+	}
+    }
+
+
+
+    set done 0
+    wm deiconify $basewidget
+    tkwait variable [itcl::scope done ]
+    if { $laststate == 0 } {
+	$listbox selection clear 0 end
+    }
+	
+    return [ $listbox getcurselection  ]
+}
+
+# ---------------------------------------------------------------------------
+
+itcl::body pxitcllistselector::GetSelectedIndices { } {
+    return [ [ $listbox component listbox ] curselection ]
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclmanualsurfacetransformation.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclmanualsurfacetransformation.tcl
new file mode 100644
index 0000000..24dd184
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclmanualsurfacetransformation.tcl
@@ -0,0 +1,452 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclmanualsurfacetransformation 1.0
+package provide pxitclsurobj 1.0
+
+
+
+
+
+# 	$Id: pxitclmanualsurfacetransformation.tcl,v 1.1 2002/06/11 01:21:41 papad Exp papad $	
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxvtable   1.0
+package require  vtkpxcontrib 1.1
+package require  pxitcloverlaytool 1.0
+package require  pxitclbasecontrol 1.0
+
+# ------------------------------------------------------------------------------------------
+#
+# pxitclmanualsurfacetransformation control
+#
+# ------------------------------------------------------------------------------------------
+
+itcl::class pxitclmanualsurfacetransformation {
+
+    inherit pxitclbasecontrol
+
+    private   common   thisparam
+    protected variable initialized     0
+    public variable input_surface   0
+    public variable output_surface  0
+    public variable overlaytool     0
+    protected variable transformation  0
+    public variable shape_model     0
+    public variable shape_model_weights  0
+    public variable updatepolydata       0
+    protected variable parameter_names   0
+    protected variable parameter_values  0
+    public    variable energy_image      0
+    public    variable reference_image      0
+    protected variable energy_level     "no_image"
+    public    variable segmentor  0
+
+    constructor { par over } {
+	::pxitclbasecontrol::constructor $par
+    } { 
+	set overlaytool $over
+    }
+
+ 
+    public    method Initialize  { basewidget args } 
+    public    method InitializeVariables  { } 
+    public    method IdentityTransformation  { } 
+    public    method CreateSurface { }
+    public    method CopySurfaceFromClipboard { }
+    public    method PasteSurfaceFromClipboard { }
+    public    method ToggleShowHide { }
+    public    method UpdateStatus { }
+    public    method GenerateTransformation { }
+    public    method WarpSurface            { }
+    public    method GrabImage { }
+    public    method ComputeEnergyFunction  { }
+
+    public    method SendTransformationToOverlayTool { }
+    public    method GetTransformationFromOverlayTool { }
+
+    
+}
+
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclmanualsurfacetransformation::Initialize { basewidg args } {
+
+    if { $initialized == 1 } { return $basewidget }
+
+    set basewidget [ toplevel $basewidg ] 
+    wm withdraw $basewidget
+    wm geometry $basewidget 450x700
+    wm title $basewidget "Manual Surface Warp"
+
+    set w [ frame $basewidget.bottom ]
+    pack $w -side bottom -expand f -fill x -pady 2
+    
+    eval "button $w.1 -text Close -command { $this HideWindow } "
+    pack $w.1 -side right
+
+    eval "button $w.r -text \"Reset Xform\" -command { $this IdentityTransformation  }"
+    eval "button $w.g -text \"Get Xform\" -command { $this GetTransformationFromOverlayTool  }"
+    eval "button $w.s -text \"Store Xform\" -command { $this SendTransformationToOverlayTool  }"
+    
+    pack $w.r $w.g $w.s -side left -padx 2
+
+    set thisparam($this,surfacestatus) ""
+    set top [ frame $basewidget.top ]
+    set top2 [ frame $basewidget.top2 ]
+    pack $basewidget.top $top2 -side top -expand f -fill x -pady 2
+
+    label $top.l -text "Surface:"
+    entry $top.o -textvariable [ itcl::scope thisparam($this,surfacestatus) ] -relief raised -state disabled -width 45 -bg black -fg white
+    eval "button $top2.cr -text \"Create \" -command { $this CreateSurface  }"
+    eval "button $top2.c -text \"Copy \" -command { $this CopySurfaceFromClipboard  }"
+    eval "button $top2.p -text \"Paste\" -command { $this PasteSurfaceFromClipboard  }"
+    eval "button $top2.w -text \"Show/Hide\" -command { $this ToggleShowHide  }"
+    eval "button $top2.wi -text \"Get Image\" -command { $this GrabImage  }"
+    pack $top.l $top.o -side left -expand f -fill x
+    pack $top2.p $top2.c $top2.cr $top2.w $top2.wi -side right 
+
+
+    set middle [ frame $basewidget.sf  ]
+    pack $basewidget.sf -side top -expand t -fill both -padx 4 -pady 4 
+
+    set parameter_values [ list tx ty tz rx ry rz sx sy sz m1 m2 m3 m4 m5 ]
+    set parameter_names  [ list TX TY TZ RX RY RZ SX SY SZ Mode1 Mode2 Mode3 Mode4 Mode5 ]
+    set lower [ list  -64 -64 -64 -90 -90 -90 50 50 50 -2.0 -2.0 -2.0 -2.0 -2.0 ]
+    set upper [ list  64 64 64 90 90 90 200 200 200 2.0 2.0 2.0 2.0 2.0 ]
+    set initial [ list 0 0 0 0 0 0 100 100 100 0 0 0 0 0]
+    set res     [ list 1 1 1 1 1 1   2   2   2 0.1 0.1 0.1 0.1 0.1 ]
+    
+    for { set i 0 } { $i < [ llength $parameter_values ] } { incr i } {
+	set bf [ frame $middle.f$i ]
+
+	pack $bf -side top -expand f -fill x
+	label  $bf.1 -text [ lindex $parameter_names $i ]
+	set   val [ lindex $parameter_values $i ]
+	set thisparam($this,value_$val) [ lindex $initial $i ]
+	set thisparam($this,guiscale_$val) [  scale $bf.2 -orient horizontal  -from [ lindex $lower $i ] -to [ lindex $upper $i ] -resolution [ lindex $res $i ] -showvalue 1 -length 250 -variable [ itcl::scope thisparam($this,value_$val) ]]
+	pack $bf.1 -side left -expand f
+	pack $bf.2 -side left -expand t -fill x
+	eval "bind $bf.2 <ButtonRelease> { $this GenerateTransformation }"
+    }
+
+    $this InitializeVariables
+    $this UpdateStatus
+
+    SetTitle "Manual Surface Transformation"
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget
+
+}
+
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclmanualsurfacetransformation::InitializeVariables { } {
+
+    set transformation [ vtkpxComboTransform [ pxvtable::vnewobj ]]
+    $transformation SetNonLinearFirst 1
+    
+    set shape_model [ vtkpxShapePriorDistance [ pxvtable::vnewobj ]]
+    $shape_model Load "/home/xenios/vtkpxcontrib/bioimagesuite/images/kidney_shape.model"
+    
+    set shape_model_weights [ vtkFloatArray [ pxvtable::vnewobj ]]
+    $shape_model_weights SetNumberOfTuples 100
+    $shape_model_weights FillComponent 0 0 
+
+    set input_surface  [ vtkPolyData [ pxvtable::vnewobj ]]
+    set output_surface [ vtkPolyData [ pxvtable::vnewobj ]]
+
+    set source [ vtkSphereSource  [ pxvtable::vnewobj ]]
+    $source Update
+    $input_surface   ShallowCopy [ $source GetOutput ]
+    $output_surface  ShallowCopy [ $source GetOutput ]
+    $source Delete
+
+    set orthoviewer [ $parent GetViewer ]
+
+    for { set i 0 } { $i <= 3 } { incr i } {
+	set map [ vtkPolyDataMapper [ pxvtable::vnewobj ]]
+	$map SetInput $output_surface
+
+	set thisparam($this,act$i) [ vtkActor [ pxvtable::vnewobj ]]
+	$thisparam($this,act$i) SetVisibility 0
+	$thisparam($this,act$i) SetMapper $map
+	$map Delete
+
+	set ren [ [ $orthoviewer GetRenderer $i ] GetRenderer ] 
+	$ren AddActor $thisparam($this,act$i)
+	
+	if { $i != 3 } {
+	    
+	    set prop [ $thisparam($this,act$i) GetProperty ]
+	    $prop SetRepresentationToWireframe
+	    $prop SetLineWidth 2.0
+	    $prop SetAmbient  1.0
+	    $prop SetDiffuse 0.0
+	    $prop SetSpecular 0.0
+	}
+    }
+
+    set energy_image [ vtkImageData [ pxvtable::vnewobj ] ]
+    set reference_image [ vtkImageData [ pxvtable::vnewobj ] ]
+    set segmentor [ vtkpxPriorShapeModelSegmentation [ pxvtable::vnewobj ] ]
+}
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclmanualsurfacetransformation::CreateSurface { } {
+
+
+    set image_ref [ [ $overlaytool GetImage ] GetImage ]
+
+    set dim [ $image_ref GetDimensions ]
+    set ori [ $image_ref GetOrigin ]
+    set spa [ $image_ref GetSpacing ]
+
+    for { set i 0 } { $i <=2 } { incr i } {
+	set pos($i) [ expr [ lindex $ori $i ] + 0.5 * [ lindex $dim $i ] * [ lindex $spa $i ]]
+	set rad($i) [ expr 0.25 * [ lindex $dim $i ] * [ lindex $spa $i ]]
+    }
+    
+
+    set source [ vtkSphereSource  [ pxvtable::vnewobj ]]
+
+    $source SetCenter $pos(0) $pos(1) $pos(2)
+    $source SetRadius $rad(0)
+    $source SetThetaResolution 20
+    $source SetPhiResolution 20
+    $source Update
+
+
+
+    $input_surface   ShallowCopy [ $source GetOutput ]
+    $source Delete
+
+    $this WarpSurface
+
+    
+    
+
+    
+}
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclmanualsurfacetransformation::IdentityTransformation { } {
+
+    for { set i 0 } { $i < [ llength $parameter_values ] } { incr i } {
+	set   val [ lindex $parameter_values $i ]
+	if { $i < 6 || $i >8 } {
+	    set thisparam($this,value_$val) 0
+	} else {
+	    set thisparam($this,value_$val) 100
+	}
+    }
+
+    $this GenerateTransformation
+}
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclmanualsurfacetransformation::CopySurfaceFromClipboard { } {
+    
+    set cntrl [ [ $parent GetPolyDataControl ] GetPolyDataControl ]
+    $cntrl SetClipboardSurface  $output_surface "ManualXform.vtk"
+    ::pxtclutil::Info "Output surface is stored on the clipboard of the surface control\n(You must paste this into a surface before it becomes available)"
+}
+
+itcl::body pxitclmanualsurfacetransformation::PasteSurfaceFromClipboard { } {
+    set cntrl [ [ $parent GetPolyDataControl ] GetPolyDataControl ]
+    set sur [ $cntrl GetClipboardSurface ]
+    catch { $input_surface ShallowCopy $sur }
+    $this WarpSurface
+}
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclmanualsurfacetransformation::GenerateTransformation { } {
+
+    set pnamelist [ list x y z ]
+    set offsetlist [ list 0 3 6 ]
+    set image_ref [ [ $overlaytool GetImage ] GetImage ]
+    set spa [ $image_ref GetSpacing ]
+
+
+    for { set i 0 } { $i <=2 } { incr i } {
+	
+	set pname [ lindex $pnamelist $i ]
+	
+	set   val [ lindex $parameter_values [ expr 6+$i ] ]
+	set scale($pname) $thisparam($this,value_$val)
+
+	if { $scale($pname) < 10 } { 
+	    set scale($pname) 10 
+	} elseif { $scale($pname) > 1000.0 } {
+	    set scale($pname) 1000.0
+	}
+	
+	set   val [ lindex $parameter_values $i ]
+
+	set dshift($pname) [ expr $thisparam($this,value_$val) * [ lindex $spa $i ] ]
+	if { $dshift($pname) < -2000 } { 
+	    set dshift($pname) 2000
+	} elseif { $dshift($pname) > 2000.0 } {
+	    set dshift($pname) 2000.0
+	}
+				     
+	set   val [ lindex $parameter_values [ expr 3+$i ] ]
+	set drotate($pname) $thisparam($this,value_$val)
+	if { $drotate($pname) < -360 } { 
+	    set drotate($pname) 360
+	} elseif { $drotate($pname) > 360.0 } {
+	    set drotate($pname) 360.0
+	}
+
+    }
+
+    # On to non-linear part
+    for { set i 9 } { $i < 14 } { incr i } {
+	set   val [ lindex $parameter_values $i ]
+	puts stdout "$val , $thisparam($this,value_$val)"
+	set j [ expr $i -9 ]
+	$shape_model_weights SetComponent $j 0  $thisparam($this,value_$val)
+	puts stdout "Weights $j = [ $shape_model_weights GetComponent $j 0 ]"
+    }
+    
+    [ $transformation  GetGridTransform ] InitializeDisplacementGrid  [ [  $shape_model  GetAverageTransform ] GetGridTransform ] 
+    $shape_model GenerateTransformation  $transformation $shape_model_weights
+
+    # Next Linear Part
+    set image_ref [ $overlaytool GetImage ]
+    set image_trn [ $overlaytool GetFunctionalImage ]
+
+    set xform [ vtkpxLinearTransform [ pxvtable::vnewobj ]]
+    $xform ManualSetParameters $dshift(x) $dshift(y) $dshift(z) $drotate(x) $drotate(y) $drotate(z) $scale(x) $scale(y) $scale(z)  [ $image_ref GetImage ] [ $image_ref GetOrientation ] [  $image_trn GetImage ] [ $image_trn GetOrientation ] [ $transformation GetLinearTransform ]
+    $xform Delete
+
+    $shape_model DebugOn
+    set d  [ $shape_model ComputeDistance $transformation ]
+    $shape_model DebugOff
+    puts stdout "Distance to Model =  $d"
+
+    WarpSurface
+}
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclmanualsurfacetransformation::UpdateStatus { } {
+
+    set thisparam($this,surfacestatus) "points = [ $output_surface GetNumberOfPoints ] visible = [ $thisparam($this,act0) GetVisibility ] $energy_level"
+}
+
+itcl::body pxitclmanualsurfacetransformation::WarpSurface { } {
+
+    $transformation Update
+    puts stdout "Saving in sent.grd ( [ $transformation Save sent.grd ] )"
+    set filter [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ]]
+    $filter SetInput $input_surface
+    $filter SetTransform  $transformation 
+    $filter Update
+    $output_surface ShallowCopy [ $filter GetOutput ]
+    $output_surface  Update
+
+    puts stdout "Point 1 [ $input_surface GetPoint 1 ] __ [ $output_surface GetPoint 1 ]"
+    set a [ $input_surface GetPoint 1 ]
+
+
+
+    set orthoviewer [ $parent GetViewer ]
+    $orthoviewer UpdateDisplay 
+
+    $this ComputeEnergyFunction 
+
+    UpdateStatus
+}
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclmanualsurfacetransformation::SendTransformationToOverlayTool { } {
+
+
+    set tr [ vtkTransform [ pxvtable::vnewobj ]]
+    [ $tr GetMatrix ] DeepCopy [ [ $transformation GetLinearTransform ] GetMatrix ]
+    $tr Inverse
+    $overlaytool SetTransformation  $transformation "manual"
+}
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclmanualsurfacetransformation::ToggleShowHide { } {
+
+    for { set i 0 } { $i <= 3 } { incr i } {
+	set act $thisparam($this,act$i)
+	$act SetVisibility [ expr 1 - [ $act GetVisibility ] ]
+    }
+    $this UpdateStatus
+    set orthoviewer [ $parent GetViewer ]
+    $orthoviewer UpdateDisplay 
+
+}
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclmanualsurfacetransformation::GetTransformationFromOverlayTool { } {
+    
+
+    set image_ref [ $overlaytool GetImage ]
+    set image_trn [ $overlaytool GetFunctionalImage ]
+    set in_xform  [ $overlaytool GetTransformation ]
+    set spa [ [ $image_ref GetImage ] GetSpacing ]
+    
+    set xform [ vtkpxLinearTransform [ pxvtable::vnewobj ]]
+    $xform ExtractParameters $in_xform 9 [ $image_ref GetImage ] [ $image_ref GetOrientation ] [  $image_trn GetImage ] [ $image_trn GetOrientation ]
+    for { set k 9 } { $k < 15 } { incr k } {
+	$xform Put $k 0
+    }
+
+    for { set i 0 } { $i < [ llength $parameter_values ] } { incr i } {
+	set   val [ lindex $parameter_values $i ]
+	if { $i > 2 } {
+	    set  thisparam($this,value_$val)  [ $xform Get $i ]
+	} else {
+	    set  thisparam($this,value_$val)  [ expr  ([ $xform Get $i ]) / ( [ lindex $spa $i ]) ]
+	}
+    }
+
+    $xform Delete
+    GenerateTransformation
+}
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclmanualsurfacetransformation::GrabImage { } {
+
+    set img [ [ $parent GetDisplayedImage ] GetImage ]
+    $energy_image ShallowCopy $img
+
+    $reference_image ShallowCopy [  [ $overlaytool GetImage ] GetImage ]
+
+    ComputeEnergyFunction
+    UpdateStatus
+}
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclmanualsurfacetransformation::ComputeEnergyFunction  { } {
+
+    set dim [ $energy_image GetDimensions ]
+    if { [ lindex $dim 0 ] < 2 } {
+	set energy_level "no_image"
+    } else {
+	set val [ $segmentor Evaluate $output_surface $energy_image ]
+	set energy_level "dims : $dim, val=$val"
+    }
+
+}
+
+# ------------------------------------------------------------------------------------------     
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclmanualtransformation.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclmanualtransformation.tcl
new file mode 100644
index 0000000..e987f14
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclmanualtransformation.tcl
@@ -0,0 +1,604 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclmanualtransformation 1.0
+
+# 	$Id: pxitclmanualtransformation.tcl,v 1.8 2004/01/03 19:24:02 xenios Exp xenios $	
+
+
+
+
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxvtable   1.0
+package require  pxitclbasecontrol 1.0
+package require  pxitcltransform 1.0
+package require  pxitclsurface 1.0
+
+itcl::class pxitclmanualtransformation {
+
+    inherit pxitclbasecontrol
+
+    protected variable original_surface 0
+    protected variable transformed_surface 0
+    protected variable back_transformed_surface 0
+    protected variable vtk_viewer    0
+    protected variable vtk_viewer2    0
+    protected variable parent_transform_control 0
+    protected variable spinlist ""
+    
+    public    variable transformation 0
+    public    variable surface_control 0
+    private   common thisparam
+
+    constructor { par args } {
+	pxitclbasecontrol::constructor $par
+    } {
+	if { [ [ $parent GetViewer ] IsA vtkpxGUIOrthogonalViewer ] != 1}  {
+	    puts stderr "Must Have Orthogonal Viewer as parent to manual transformation"
+	    pxtkexit
+	}
+	
+	set vtk_viewer          [ $parent GetViewer ]
+	if { [ llength $args ] > 0  } {
+	    set par2 [ lindex $args 0 ]
+	    if { [ [ $par2 GetViewer ] IsA vtkpxGUIOrthogonalViewer ] != 1}  {
+		puts stderr "Must Have Orthogonal Viewer as parent to manual transformation"
+		pxtkexit
+	    }
+	    set vtk_viewer2 [ $par2 GetViewer ]
+	} else {
+	    set vtk_viewer2 $vtk_viewer
+	}
+
+	if { [ llength $args ] > 1  } {
+	    set parent_transform_control [ lindex $args 1 ]
+	}
+
+
+	InitializeManualTransformation  
+    }
+
+    # ------------ Methods --------------------
+    
+    private  method InitializeManualTransformation  { } 
+    public   method Initialize { inpwidg args }
+
+    # Transformation Related
+    # ----------------------
+    public    method GetTransformation { } 
+    public    method TransformSurface {  }
+
+    # Manual Transformation Related
+    # -----------------------------
+    protected method CreateSpinBox { par lab var rng { rng2 -1 } }
+    public    method ChangeSpinBoxIncrement { } 
+    public   method CreateManualTransformGUI { parent}
+    public   method ClearManualTransformGUI { }
+    public   method SetManualTransform { }
+
+
+    # GUI Stuff
+    # ---------
+    public    method CreateTemplateControl { parent } 
+    public    method InitializeSurfaceActors { }
+
+    # Callbacks
+    #------------
+    public    method Update { mode } 
+
+    # More Stuff
+    # ------------
+    public    method UpdateParentTransformControl { }
+    public    method AutoCreateSurface { } 
+}
+
+
+
+itcl::body pxitclmanualtransformation::InitializeManualTransformation  { } {
+	
+    global pxtcl_pref_array
+
+    # ----------------------------
+    # Transform Stuff
+    # ----------------------------
+    set transformation [ vtkTransform [ pxvtable::vnewobj ]]
+    set thisparam($this,show_surfaces) 0
+    set thisparam($this,numclasses) 3
+    set thisparam($this,minclass) 1
+    set thisparam($this,maxdim) 32
+    set thisparam($this,sigma) 2.0
+
+    set thisparam($this,show_transformedsurface) 0
+    set thisparam($this,transformmode) 1
+    set thisparam($this,actors_initialized) 0
+}
+
+# ---------------------------------------------------------------------------------------
+# Initialize
+# ---------------------------------------------------------------------------------------
+
+itcl::body pxitclmanualtransformation::Initialize { inpwidg args } {
+
+    if { $fullyinitialized == 1 } { return $basewidget }
+
+    set basewidget $inpwidg
+    toplevel $basewidget ; wm withdraw $basewidget
+    wm geometry $basewidget 600x250
+
+    wm title $basewidget "Manual Registration Tool"
+
+    CreateTemplateControl $basewidget
+    
+
+    $this InitializeSurfaceActors
+    set fullyinitialized 1
+    return $basewidget
+}
+
+
+
+# -------------------------------------------------------------
+#  Set Surface Stuff -- insert here
+# -------------------------------------------------------------
+itcl::body pxitclmanualtransformation::InitializeSurfaceActors { } {
+
+    set original_surface [ vtkPolyData [ pxvtable::vnewobj ]]
+    set transformed_surface [ vtkPolyData [ pxvtable::vnewobj ]]
+    set back_transformed_surface [ vtkPolyData [ pxvtable::vnewobj ]]
+
+    for { set sur 0 } { $sur <= 1 } { incr sur } {
+	if { $sur ==0 } {
+	    set current $back_transformed_surface
+	} else {
+	    set current $transformed_surface
+	}
+
+	$current ShallowCopy  [ [  $surface_control  GetObject ]  GetSurface ]
+
+	for { set i 0 } { $i <= 3 } { incr i } {
+	    set map [ vtkPolyDataMapper [ pxvtable::vnewobj ]]
+	    $map SetInput $current
+
+	    set thisparam($this,act${sur}_${i}) [ vtkActor [ pxvtable::vnewobj ]]
+	    set actor $thisparam($this,act${sur}_${i})
+	    $actor SetVisibility 0
+	    $actor SetMapper $map
+	    $map Delete
+
+	    if { $sur == 0 } {
+		set ren [ [ $vtk_viewer GetRenderer $i ] GetRenderer ] 
+	    } else {
+		set ren [ [ $vtk_viewer2 GetRenderer $i ] GetRenderer ] 
+	    }
+	    $ren AddActor $actor
+	    set prop [ $actor GetProperty ]
+	    
+	    if { $sur ==0 } {
+		$prop SetColor 1 0 0
+		
+		
+	    } else {
+		$prop SetColor 1 0.5 0
+	    }
+
+	    if { $i != 3 } {
+		
+		$prop SetRepresentationToWireframe
+		$prop SetLineWidth 3.0
+		$prop SetAmbient  1.0
+		$prop SetDiffuse 0.0
+		$prop SetSpecular 0.0
+
+	    }
+	}
+    }
+}
+
+# ----------------------------------------------------------------------------
+itcl::body pxitclmanualtransformation::Update { mode } {
+
+    if { $mode == "full" } {
+        TransformSurface
+    }
+
+    set visflag $thisparam($this,show_surfaces)    
+    for { set sur 0 } { $sur <= 1 } { incr sur } {
+	for { set i 0 } { $i <= 3 } { incr i } {
+	    set actor $thisparam($this,act${sur}_${i})
+	    $actor SetVisibility $visflag
+	}
+    }
+
+    $vtk_viewer2 UpdateDisplay 
+    if { $vtk_viewer != $vtk_viewer2 } {
+	$vtk_viewer UpdateDisplay
+    }
+
+}
+
+# --------------------------------------------------------
+#    Create Functional Image Control 
+# --------------------------------------------------------
+
+itcl::body pxitclmanualtransformation::CreateTemplateControl { parent } {
+
+    set base  [ frame $parent.top ]
+    set xform [ frame $parent.bot ]
+    frame $parent.mid -bg black -height 2
+    pack $base $parent.mid $xform -side top -expand false -fill x
+
+    frame $base.3; pack $base.3 -side bottom -expand false -fill x
+    frame $base.2; pack $base.2 -side bottom -expand false -fill x
+    frame $base.1; pack $base.1 -side top  -expand true -fill x
+
+    set surface_control [ [ pxitclsurfaceGUI \#auto  ] GetThisPointer ]
+    $surface_control configure -description "Edge Surface"
+    $surface_control InitializeLite $base.1.1
+    set cl [ $surface_control cget -clearbutton ]
+    pack forget $cl
+    pack $base.1.1 -side top -expand false -fill both
+    
+
+    eval "checkbutton $base.2.c1 -variable [ itcl::scope thisparam($this,show_surfaces) ] -text \"Show Surfaces\" -command { $this Update full }"
+    eval "checkbutton $base.2.c2 -variable [ itcl::scope thisparam($this,transformmode) ] -text \"Template in Transform Space\" -command { $this Update full }"
+    pack $base.2.c1 $base.2.c2  -side left -expand f -padx 5
+
+    
+    
+    label $base.3.1 -text "NumClasses:"
+    eval "spinbox $base.3.2 -from 2 -to 6 -width 2 -format %.0f -increment 1 -textvariable [ itcl::scope thisparam($this,numclasses) ]"
+    label $base.3.3 -text "Thr:"
+    eval "spinbox $base.3.4 -from 1 -to 5 -width 2 -format %.0f -increment 1 -textvariable [ itcl::scope thisparam($this,minclass) ]"
+    label $base.3.5 -text "Sigma:"
+    eval "spinbox $base.3.6 -from 1.0 -to 4.0 -width 4 -increment 0.5 -format %.1f -textvariable [ itcl::scope thisparam($this,sigma) ]"
+
+    label $base.3.61 -text "Res:"
+    eval "tk_optionMenu $base.3.62  [ itcl::scope thisparam($this,maxdim) ]  16 32 48 64 96 128 "
+    
+    eval "button $base.3.7 -text \"Auto Create Surface\" -command { $this AutoCreateSurface }"
+    pack $base.3.1 $base.3.2 $base.3.3 $base.3.4 $base.3.5 $base.3.6 $base.3.61 $base.3.62 $base.3.7 -side left -expand f -padx 1
+
+
+    CreateManualTransformGUI $xform
+
+}
+
+# -------------------------------------------------------------
+# Transform Operations
+# -------------------------------------------------------------
+
+itcl::body pxitclmanualtransformation::GetTransformation { } {
+
+    return $transformation
+}
+
+# -----------------------------------------------------------------------
+#   Manual Transform GUI
+# -----------------------------------------------------------------------
+itcl::body pxitclmanualtransformation::ClearManualTransformGUI { } {
+
+    for { set i 0 } { $i <=2 } { incr i } {
+
+	if { $i == 0 } { 
+	    set pname "x"
+	} elseif { $i == 1 } {
+	    set pname "y"
+	} else {
+	    set pname "z"
+	}
+	
+	set thisparam($this,rotate$pname) 0
+	set thisparam($this,shift$pname) 0
+    }
+    set thisparam($this,scale) 100
+}
+
+# ----------------------------------------------------------------------
+itcl::body pxitclmanualtransformation::SetManualTransform { } {
+    
+    set image_ref [ $vtk_viewer GetImage ]
+    set image_trn [ $vtk_viewer2 GetImage ]
+
+    set dim1 0; set dim2 0
+    set ori1 0; set ori2 0
+    catch {
+	set dim1 [  $image_ref GetDimensions ]
+	set dim2 [  $image_trn GetDimensions ]
+	set ori1 [  $vtk_viewer GetOrientation ]
+	set ori2 [  $vtk_viewer2 GetOrientation ]
+    }
+
+    if { $dim1 == 0 || $dim2 ==0 } {
+	return
+    }
+    
+
+    for { set i 0 } { $i <=2 } { incr i } {
+	
+	if { $i == 0 } { 
+	    set pname "x"
+	} elseif { $i == 1 } {
+	    set pname "y"
+	} else {
+	    set pname "z"
+	}
+
+	set dshift($pname) $thisparam($this,shift$pname)
+	if { $dshift($pname) < -2000 } { 
+	    set dshift($pname) 2000
+	} elseif { $dshift($pname) > 2000.0 } {
+	    set dshift($pname) 2000.0
+	}
+	
+	set drotate($pname) $thisparam($this,rotate$pname)
+	if { $drotate($pname) < -180 } { 
+	    set drotate($pname) 180
+	} elseif { $drotate($pname) > 180.0 } {
+	    set drotate($pname) 180.0
+	}
+	
+    }
+
+    if { $thisparam($this,scale) < 25 } {
+	set thisparam($this,scale) 25
+    } elseif { $thisparam($this,scale) > 400 } {
+	set thisparam($this,scale) 400
+    }
+
+
+    $transformation Identity
+    set lxform [ vtkpxLinearTransform [ pxvtable::vnewobj ]]
+    $lxform ManualSetParameters $dshift(x) $dshift(y) $dshift(z) $drotate(x) $drotate(y) $drotate(z) $thisparam($this,scale) $thisparam($this,scale) $thisparam($this,scale) $image_ref $ori1 $image_trn $ori2 $transformation
+    $lxform Delete
+
+    set thisparam($this,show_surfaces) 1
+    Update full
+}
+
+# --------------------------------------------------------------------
+itcl::body pxitclmanualtransformation::ChangeSpinBoxIncrement { } {
+
+    for { set i 0 } { $i < [ llength $spinlist ] } { incr i } {
+	set w [ lindex $spinlist $i ]
+	$w configure -increment $thisparam($this,spinincr)
+    }
+
+}
+# --------------------------------------------------------------------
+itcl::body pxitclmanualtransformation::CreateSpinBox { par lab var rng {rng2 -1 } } {
+
+    if { $rng2 == -1 } {
+	set rng2 [ expr -1.0* $rng ]
+    }
+    set minval $rng2
+    set maxval $rng
+
+    label ${par}1 -text $lab
+    eval "spinbox ${par}2 -from $minval -to $maxval -increment 5.0  -width 4 -format %.0f -textvariable [ itcl::scope  thisparam($this,$var) ] -command { $this SetManualTransform }"
+    pack ${par}1 ${par}2 -side left -padx 1
+    return ${par}2
+}
+
+itcl::body pxitclmanualtransformation::CreateManualTransformGUI { parentw  } {
+
+
+    set f2 [ frame $parentw.bot] 
+    pack $f2 -side bottom -expand false -fill x
+
+    set f [ frame $parentw.top ] ; pack $f -side top -expand false -fill x
+
+    set index 0
+    lappend spinlist [ $this CreateSpinBox $f.$index tx shiftx 100]; incr index
+    lappend spinlist [ $this CreateSpinBox $f.$index ty shifty 100; ]; incr index
+    lappend spinlist [ $this CreateSpinBox $f.$index tz shiftz 100; ]; incr index
+    lappend spinlist [ $this CreateSpinBox $f.$index rx rotatex 180; ]; incr index
+    lappend spinlist [ $this CreateSpinBox $f.$index ry rotatey 180; ]; incr index
+    lappend spinlist [ $this CreateSpinBox $f.$index rz rotatez 180; ]; incr index
+    lappend spinlist [ $this CreateSpinBox $f.$index sc scale 200 50.0; ]; incr index
+
+    label $f2.a -text "Inc:"
+    pack $f2.a -side left; incr index
+
+    set thisparam($this,spinincr) 5
+    eval "tk_optionMenu $f2.b  [ itcl::scope thisparam($this,spinincr) ] 1 3 5 10 20 "
+    update idletasks
+
+    for { set t 0 } { $t < 5 } { incr t } {
+	eval "$f2.b.menu entryconfigure $t -command { $this ChangeSpinBoxIncrement }"
+    }
+    pack $f2.b -side left -padx 2
+
+    if { $parent_transform_control != 0 } {
+	eval "button $f2.3 -text \"Update Main Application\" -command { $this UpdateParentTransformControl }"
+	pack $f2.3 -side right -padx 20 -pady 5
+    }
+    
+    eval "button $f2.1 -text \"Set Xformation\" -command { $this SetManualTransform }"
+    eval "button $f2.2 -text \"Clear Values\" -command { $this ClearManualTransformGUI; $this SetManualTransform }"
+    pack $f2.1 $f2.2 -side left 
+    
+    $this ClearManualTransformGUI
+}
+
+
+itcl::body pxitclmanualtransformation::TransformSurface { } {
+
+    WatchOn
+    set current_transform $transformation
+
+    $original_surface ShallowCopy  [ [  $surface_control  GetObject ]  GetSurface ]
+
+    set filter [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ]]
+    $filter SetInput $original_surface
+
+    if { $thisparam($this,transformmode) == 0 } {
+	$filter SetTransform  $current_transform 
+	$filter Update
+	$transformed_surface ShallowCopy [ $filter GetOutput ]
+	$back_transformed_surface ShallowCopy $original_surface
+    } else {
+	$filter SetTransform  [ $current_transform  GetLinearInverse ]
+	$filter Update
+	$back_transformed_surface ShallowCopy [ $filter GetOutput ]
+	$transformed_surface ShallowCopy $original_surface
+    }
+
+
+    $filter Delete
+
+    $back_transformed_surface  Update
+    $transformed_surface  Update
+
+    WatchOff
+    return 1
+}
+
+
+itcl::body pxitclmanualtransformation::UpdateParentTransformControl { } {
+
+    $this SetManualTransform
+    $parent_transform_control SetTransformation $transformation "add"
+    $parent_transform_control ShowWindow Transformations
+}
+
+itcl::body pxitclmanualtransformation::AutoCreateSurface { }  { 
+
+    puts stderr "In auto create"
+
+    set img [ $vtk_viewer GetImage ]
+    if { $thisparam($this,transformmode) == 1 } {
+	set img [ $vtk_viewer2 GetImage ]
+    }
+
+
+    set np 0
+    catch { set np [ $img GetNumberOfPoints ] }
+    if { $np < 10 } {
+	return 0
+    }
+    puts stderr "Canny 0"
+
+    # 1 Run Canny
+    set segm [ vtkpxHistogramSegmentation [ pxvtable::vnewobj ]]
+    $segm SetInput $img
+    $segm SetNumberOfClasses $thisparam($this,numclasses)
+    $segm SetIterations 20
+    $segm SetNumberOfBins 256
+    $segm SetConvergence 0.05
+    $segm SetSigma 0.05
+    $segm GenerateLabelsOn
+    $segm SetOutlierDetection 0
+    $segm SetPreprocessingMode 0 
+    $segm SetDistributionModel 0
+    $segm SetMaxSigmaRatio     0.2
+    $segm Update
+
+    if { $thisparam($this,minclass) >= $thisparam($this,numclasses) } {
+	set thisparam($this,minclass) [ expr $thisparam($this,numclasses) -1 ]
+    }
+
+    #    puts stderr "Canny 0"
+    set imgthr [ vtkImageThreshold [ pxvtable::vnewobj ]]
+    $imgthr SetInput [ $segm GetOutput ]
+    $imgthr ThresholdBetween $thisparam($this,minclass) $thisparam($this,numclasses)
+    $imgthr SetInValue 100
+    $imgthr SetOutValue 0
+    $imgthr ReplaceInOn
+    $imgthr ReplaceOutOn
+    $imgthr Update
+    #puts stderr "Canny 0.5"
+
+    set smooth  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+    $smooth SetInput [ $imgthr GetOutput ]
+    $smooth SetStandardDeviations $thisparam($this,sigma) $thisparam($this,sigma) $thisparam($this,sigma)
+    $smooth Update
+    #puts stderr "Canny 1"	
+
+    set dim [ [ $smooth GetOutput ] GetDimensions ]
+    set spa [ [ $smooth GetOutput ] GetSpacing ]
+    set ori [ [ $smooth GetOutput ] GetOrigin ]
+
+    for { set i 0 } { $i <=2 } { incr i } {
+	set d  [ lindex $dim $i ]
+	set sp [ lindex $spa $i ]
+	set r  [ expr double($d)*double($sp) ]
+	if { $d > $thisparam($this,maxdim) } {
+	    set outsp($i) [ expr $r/double($thisparam($this,maxdim)) ]
+	} else {
+	    set outsp($i) $sp
+	}
+	set outdim($i) [ expr int($r/$sp)+2 ]
+	set outori($i) [ expr [ lindex $ori $i ] - $outsp($i) ]
+    }
+    
+    #    set resl [ vtkImageResample [ pxvtable::vnewobj ]]
+    #    $resl SetAxisOutputSpacing 0 $outsp(0)
+    #    $resl SetAxisOutputSpacing 1 $outsp(1)
+    #    $resl SetAxisOutputSpacing 2 $outsp(2)
+
+    set resl [ vtkImageReslice [ pxvtable::vnewobj ]]
+    $resl SetOutputSpacing $outsp(0) $outsp(1) $outsp(2)
+    $resl SetOutputOrigin $outori(0) $outori(1) $outori(2)
+    $resl SetOutputExtent 0 $outdim(0) 0 $outdim(1) 0 $outdim(2)
+    $resl SetBackgroundLevel 100
+    $resl SetInterpolationModeToLinear
+    
+
+    $resl SetInput [ $smooth GetOutput ]
+    $resl Update
+
+    set dim [ [ $resl GetOutput ] GetDimensions ]
+    set spa [ [ $resl GetOutput ] GetSpacing ]
+    puts stderr "Dimensions at resl =$dim, $spa"
+
+    set cont [ vtkContourFilter [ pxvtable::vnewobj ]]
+    $cont SetInput [ $resl GetOutput ]
+    $cont SetValue 0 50.0
+    $cont ComputeScalarsOff
+    $cont ComputeGradientsOff
+    $cont ComputeNormalsOff
+    $cont Update
+    
+    #puts stderr "Canny 2"
+
+
+
+    [  $surface_control  GetObject ]  ShallowCopySurface [ $cont GetOutput ]
+    $surface_control Update
+
+    $resl Delete
+    $cont Delete
+    $imgthr Delete
+    $smooth Delete
+    $segm Delete
+    WatchOff
+    puts stderr "Canny 3"
+    $this SetManualTransform
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclmousechopper.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclmousechopper.tcl
new file mode 100644
index 0000000..8786ffd
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclmousechopper.tcl
@@ -0,0 +1,2096 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+package provide pxitclmousechopper 1.0
+package provide pxitclsurobj 1.0
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+# 	$Id: pxitclmousechopper.tcl,v 1.1 2002/06/11 01:21:41 papad Exp papad $	
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxvtable   1.0
+package require  vtkpxcontrib 1.1
+package require  pxitclobject 1.0
+package require  pxitclbasecontrol 1.0
+
+# ------------------------------------------------------------------------------------------
+#
+# pxitclmouseplanes 
+#
+# ------------------------------------------------------------------------------------------
+itcl::class pxitclmouseplanes {
+
+    inherit pxitclobject
+
+    protected variable numcomp    8
+    protected variable planearray 0
+    protected variable planenames ""
+    protected variable planeorder ""
+    protected variable firstinit  1
+
+
+    protected    variable hasfeet          0
+    protected    variable hashindlimbs     0
+    protected    variable hasforelimbs     0
+    protected    variable hashead          0
+    protected    variable taildivisions    0
+    protected    variable spinedivisions 0
+    public       variable dimensions [ list 300 250 400 ]
+    
+    constructor { maxplanes } { 	$this Initialize $maxplanes    }
+    destructor  { catch { $planearray Delete }  }
+
+
+    # --- begin method def -----
+    public method Initialize { maxplanes } 
+
+
+    # Things that must be over-ridden by derived classes
+    # --------------------------------------------------
+    public method GetObject { } { return $planearray }
+    public method GetPlanes { } { return $planearray }
+    public method GetNames { } { return $planenames  }
+    protected method AddName { name } { lappend planenames $name }
+    protected method AddPart { name nx ny nz dist above} 
+
+    public method GetType { } { return "vtkFloatArray" }
+    public method GetDescription { } 
+    public method UpdateStatus { }  { }
+    public method Copy    { obj }
+    public method Clear   { } 
+    public method InitializeModel { feet hindlimbs forelimbs head taildivisions spinedivisions }
+    public method GetModelParameters { } { return [ list $hasfeet $hashindlimbs $hasforelimbs $hashead $taildivisions $spinedivisions ] }
+
+    # Create Region Label Image
+    public method CreateRegionLabelImage { img resolution kernel threshold surface } 
+    public method GetPlaneNumber { jointno } 
+    public method GetJointNumber { planeno } 
+    public method GetAllJointNumbers { }
+
+    # Create Wireframe Model
+    # ----------------------
+    protected method AddSkeletonPart { centerno joints numparts sekeletonpts linepairs inindex pointindex length } 
+    public method CreateWireframeModel { joints spheresize tubesize }
+
+    # Procedures to Load/Save 
+    public method Load { args } 
+    public method Save { args } 
+}
+
+# ---------------------------------------------------------------------------------------------
+
+itcl::body pxitclmouseplanes::Initialize { maxplanes } {
+    catch  { $planearray Delete }
+    set planearray [ vtkFloatArray [ pxvtable::vnewobj ]]
+    $planearray SetNumberOfComponents $numcomp
+    
+    if { $maxplanes < 2 } { set maxplanes 2 } elseif { $maxplanes > 30 } { set maxplanes 30 }
+
+    $planearray SetNumberOfTuples $maxplanes
+    $this Clear
+    return $maxplanes
+}
+
+itcl::body pxitclmouseplanes::GetDescription {  } {
+    
+    return "Plane array $filename\nNumber of planes [ llength $planenames ]\n $planenames"
+}
+
+itcl::body pxitclmouseplanes::Copy { obj  } {
+    $planearray DeepCopy [ $obj GetPlanes ]
+    set planenames [ $obj GetPlaneNames ]
+}
+
+itcl::body pxitclmouseplanes::Clear {  } {
+
+
+    $planearray FillComponent 0 1.0
+    for { set i 1 } { $i < $numcomp } { incr i } {
+	$planearray FillComponent $i 0 
+    }
+    set planenames ""
+    
+}
+
+itcl::body pxitclmouseplanes::Load { args } {
+
+    set len [ llength $args ]
+    if { [ string length $filename ] == 0 && $len == 0 } { return  }
+
+    if { $len < 1 } {
+	set fname $filename
+    } else  { 
+	set fname [ lindex $args 0 ] 
+    }
+
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    } else {
+	set desc "Planes File"
+    }
+
+    if { [ string length $fname ] == 0 } {
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getOpenFile -title "Load $desc" -filetypes { {"Planes Files" {.planes}}} -initialfile $f2tail -initialdir $f2path ]   
+    }
+    
+    if { [ string length $fname ] <1 } {
+	return 0
+    }
+
+    # Load it here
+
+    if { [ file exists $fname ] == 0 } {
+	return 0
+    }
+
+    set fin [ open $fname r ]
+    gets $fin line
+    if { $line != "\#Planes Description File" } {
+	close $fin
+	return -1
+    }
+
+    set filename $fname
+
+    gets $fin line; gets $fin line; 
+    gets $fin maxplanes 
+    
+    set maxplanes [ $this Initialize $maxplanes ]
+
+    gets $fin line; gets $fin hasfeet
+    gets $fin line; gets $fin hashindlimbs
+    gets $fin line; gets $fin hasforelimbs
+    gets $fin line; gets $fin hashead
+    gets $fin line; gets $fin taildivisions
+    gets $fin line; gets $fin spinedivisions
+	
+    gets $fin line
+    
+    for { set i 0 } { $i < $maxplanes } { incr i } {
+	gets $fin line
+	lappend planenames $line
+	gets $fin line
+	scan $line "%f %f %f %f %f %f %f %d" nx ny nz dist cx cy cz abv 
+	
+	$planearray SetComponent $i 0 $nx
+	$planearray SetComponent $i 1 $ny
+	$planearray SetComponent $i 2 $nz
+	$planearray SetComponent $i 3 $dist
+	$planearray SetComponent $i 4 $cx
+	$planearray SetComponent $i 5 $cy
+	$planearray SetComponent $i 6 $cz
+	$planearray SetComponent $i 7 $abv
+
+    }
+    close $fin
+    return 1
+}
+# ----------------------------------------------------------
+itcl::body pxitclmouseplanes::Save { args } {
+
+    set len [ llength $args ]
+    if { $len < 1 } {
+	set fname $filename
+    } else  { 
+	set fname [ lindex $args 0 ] 
+    }
+
+    set desc "Planes File"
+    if { $len > 1 } { 
+	set desc [ lindex $args 1 ]
+    }
+    
+    if { [ string length $fname ] == 0 } {
+	set f2path [ file dirname $filename ]
+	set f2tail [ file tail    $filename ]
+	set fname  [tk_getSaveFile -title "Saving $desc" -filetypes { {"Planes Files" {.planes}}} -initialfile $f2tail -initialdir $f2path ]   
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    set fout [ open $fname w ]
+    puts $fout "\#Planes Description File\n\#------------------------------------"
+    puts $fout "\#Number of Planes\n [llength $planenames ]"
+
+    puts $fout "#Feet\n$hasfeet"
+    puts $fout "#Hind Limbs \n$hashindlimbs"
+    puts $fout "#Fore Limbs \n$hasforelimbs"
+    puts $fout "#Head \n$hashead"
+    puts $fout "#Tail Divisions \n$taildivisions"
+    puts $fout "#Spine Divisions \n$spinedivisions"
+
+    puts $fout "\#Planes "
+    
+    for { set i 0 } { $i < [ llength $planenames ] } { incr i } {
+	puts $fout [ lindex $planenames $i ]
+	for { set j 0 } { $j < 7 } { incr j } { 
+	    puts -nonewline $fout [ format "%.3f " [ $planearray GetComponent $i $j ]]
+	}
+	puts $fout [ format "%d " [ expr round([ $planearray GetComponent $i 7 ]) ]  ]
+    }
+    close $fout
+    set filename $fname
+    return 1
+}
+
+itcl::body pxitclmouseplanes::AddPart { name nx ny nz offset above}  {
+
+    set dist 1.0
+#    catch { 
+	set dist [ expr abs($nx) * [ lindex $dimensions 0 ] + abs($ny) * [ lindex $dimensions 1 ] + abs ($nz)*[ lindex $dimensions 2 ] ]
+
+#    }
+    set dist [ expr $dist * $offset ]
+
+    set index [ llength $planenames ]
+    
+    lappend planenames $name
+    $planearray SetComponent $index 0 $nx
+    $planearray SetComponent $index 1 $ny
+    $planearray SetComponent $index 2 $nz
+    $planearray SetComponent $index 3 $dist
+    $planearray SetComponent $index 4 [ expr 0.5* [ lindex $dimensions 0 ]]
+    $planearray SetComponent $index 5 [ expr 0.5* [ lindex $dimensions 1 ]]
+    $planearray SetComponent $index 6 [ expr 0.5* [ lindex $dimensions 2 ]]
+    $planearray SetComponent $index 7 [ expr ($above > 0 ) ]
+
+}
+
+itcl::body pxitclmouseplanes::InitializeModel { feet hindlimbs forelimbs head taildiv spinediv } {
+
+    if { $firstinit == 0 } {
+	set ok [ pxtclutil::Question "Creating a new model will erase your current model. Are you sure?" ]
+	if { $ok == "no" } {
+	    return 0
+	}
+    } else {
+	set firstinit 0
+    }
+
+    set hasfeet [ expr $feet > 0 ]
+    set hashindlimbs [ expr $hindlimbs > 0 ]
+    set hasforelimbs [ expr $forelimbs > 0 ]
+    set hashead [ expr $head > 0 ]
+
+    set taildivisions $taildiv
+    if { $taildivisions < 0 } { set taildivisions 0 } elseif { $taildivisions > 5 } { set taildivisions 5 }
+
+    set spinedivisions $spinediv
+    if { $spinedivisions < 0 } { set spinedivisions 0 } elseif { $spinedivisions > 10 } { set spinedivisions 10 }
+
+    set total [ expr 2*($hashindlimbs+$hasforelimbs)*(3+$hasfeet) + $hashead + $taildiv + $spinediv ]
+    $this Initialize $total
+
+    set dir [ list Left Right ]
+    
+    if { $hashindlimbs > 0 } {
+	for { set i 0 } { $i <=1 } { incr i } {
+	    set name [ lindex $dir $i ]
+	    AddPart "${name}-Hipp-Horizontal" 0 0 1 -0.2 1
+	    if { $i == 0 } {
+		AddPart "${name}-Hipp-Vertical"   1 0 0 0.1 1 
+	    } else {
+		AddPart "${name}-Hipp-Vertical"   1 0 0 -0.1 0
+	    }
+	    AddPart "${name}-Knee" 0 0 1 0.1 1
+
+	    if { $hasfeet > 0 } {
+		AddPart "${name}-Ankle" 0 0 1 0.3 1
+	    }
+	}
+    }
+
+    if { $taildiv > 0 } {
+	for { set i 0 } { $i < $taildiv } { incr i } { 
+	    AddPart "Tail-[ expr $i+1 ]"  0 0 1 [ expr 0.1+0.25*($i +1 )/($taildiv+1) ] 1
+	}
+    }
+
+    if { $spinediv > 0 } {
+	for { set i 0 } { $i < $spinediv } { incr i } { 
+	    AddPart "Spine-[ expr $i+1 ]"  0 0 1 [ expr -0.1-0.25*($i +1 )/($taildiv+1) ] -1
+	}
+    }
+
+    if { $hasforelimbs > 0 } {
+	for { set i 0 } { $i <=1 } { incr i } {
+	    set name [ lindex $dir $i ]
+	    AddName "${name}-Shoulder-Horizontal"
+	    AddName "${name}-Shoulder-Vertical"
+	    AddName "${name}-Elbow"
+	    if { $hasfeet > 0 } {
+		AddName "${name}-Wrist"
+	    }
+	}
+    }
+
+    if { $hashead > 0 } {
+	AddName "Neck"
+    }
+
+    return 1
+
+}
+
+itcl::body pxitclmouseplanes::CreateRegionLabelImage { img resolution kernel threshold surface } {
+
+    # First just threshold
+    # --------------------
+    set ut [ vtkpxUtil [ pxvtable::vnewobj ]]
+
+    set resl [ vtkImageResample [ pxvtable::vnewobj ] ]
+    $resl SetInput [ $img GetImage ]
+    $resl SetDimensionality 3
+    $resl InterpolateOn
+    for { set i 0 } { $i <=2 } { incr i } {
+	$resl SetAxisMagnificationFactor $i [ expr 1.0/$resolution ]
+    }
+    $resl Update
+
+    puts stderr "[ [ $resl GetOutput ] GetDimensions ] "
+
+    set thr [ vtkImageThreshold [ pxvtable::vnewobj ]]
+    $thr SetInput [ $resl GetOutput ]
+    $thr ThresholdByUpper $threshold
+    $thr ReplaceInOn
+    $thr ReplaceOutOn
+    $thr SetInValue 100.0
+    $thr SetOutValue 0.0
+    $thr SetOutputScalarTypeToShort
+    $thr Update
+
+    $resl Delete
+
+    # Next 
+    # --------------------
+    set sim [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+    set tmp [ $sim  CreateWholeBodyRegionLabelImage [ $thr GetOutput ] $planearray $hasfeet $hashindlimbs $hasforelimbs $hashead $taildivisions $spinedivisions ]
+    
+    set done 0
+    catch {
+	set done [ lindex [ $tmp GetDimensions ] 0 ]
+    }
+
+    if { $done == 0 } {
+	$thr Delete
+	return 0
+    }
+
+    #  $ut SaveAnalyze "tt_multi" $tmp 5
+
+    if { $surface !=0 } {
+	set imgout [ $sim CreateRegionLabelImage $tmp $kernel $surface ]
+    } else {
+	set imgout [ $sim CreateRegionLabelImage $tmp $kernel ]
+    }
+
+    #  $ut SaveAnalyze "tt_model" $imgout 5
+
+    $tmp Delete
+    $sim Delete
+    $thr Delete
+    $ut Delete
+    return $imgout
+}
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclmouseplanes::GetPlaneNumber { jointno }  {
+    
+    if { $jointno < 1 } {
+	return -1
+    }
+    
+    set jointno [ expr $jointno -1 ]
+
+    set legjoints  [ expr  2+$hasfeet ]
+    set legplanes  [ expr 3+$hasfeet ]
+
+    set offset 0
+    
+    set numlimbs [ expr 2*($hashindlimbs + $hasforelimbs) ]
+    set totallimbjoints  [ expr $numlimbs * $legjoints ]
+    set totallimbplanes  [ expr $numlimbs * $legplanes ]
+
+#    puts stderr "\t\t\t jointno'=$jointno Number of limbs = $numlimbs,  totallimbjoints=$totallimbjoints, totallimbplanes=$totallimbplanes"
+
+    # Step 1 is this a tail or a spine
+    if { $jointno >= $totallimbjoints } {
+	return [ expr int($jointno - $totallimbjoints + $totallimbplanes)  ]
+    }
+    
+    # Step 2 is find which limb
+    set limbno    [ expr int($jointno/$legjoints) ]
+    set limbjoint [ expr $jointno-$limbno*$legjoints ]
+
+#    puts stderr "\t\t\t limbno=$limbno limbjoint=$limbjoint"
+
+    set offset [ expr int($limbno * $legplanes) ]
+
+    return [ expr int($offset + $limbjoint +1) ]
+
+}
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclmouseplanes::GetAllJointNumbers {  }  {
+
+    for { set i 0 } { $i < [ llength $planenames ] } { incr i } {
+	set jnt [ $this GetJointNumber $i ]
+	set pla [ $this GetPlaneNumber $jnt ]
+	set pn  [ lindex $planenames $pla ]
+	puts stderr "[ lindex $planenames $i ] --> Plane $i --> Joint $jnt --> Plane $pla, $pn"
+    }
+}
+
+itcl::body pxitclmouseplanes::GetJointNumber { planeno }  {
+    
+
+    set legjoints [ expr  2+$hasfeet ]
+    set legplanes  [ expr 3+$hasfeet ]
+
+    set offset 0
+    set totalhips 0
+
+    set numlimbs [ expr 2*($hashindlimbs + $hasforelimbs) ]
+    set totallimbjoints  [ expr $numlimbs * $legjoints ]
+    set totallimbplanes  [ expr $numlimbs * $legplanes ]
+
+    #    puts stderr "\t\t\t Number of limbs = $numlimbs,  totallimbjoints=$totallimbjoints, totallimbplanes=$totallimbplanes"
+
+    # Step 1 is this a tail or a spine
+    if { $planeno >= $totallimbplanes } {
+	return [ expr $planeno - $totallimbplanes + $totallimbjoints +1 ]
+    }
+
+    # Step 2 is find which limb
+    set limbno    [ expr floor($planeno/$legplanes) ]
+    set limbplane [ expr $planeno-$limbno*$legplanes ]
+
+    #puts stderr "\t\t\t limbno=$limbno limbplane=$limbplane"
+
+    set offset [ expr int($limbno * $legjoints)+1 ]
+    if { $limbplane < 2 } {
+	return $offset 
+    } elseif { $limbplane ==2 } {
+	return [ expr $offset+1 ]
+    } else {
+	return [ expr $offset+2 ]
+    }
+}
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclmouseplanes::AddSkeletonPart { centerno joints numparts skeletonpts linepairs inindex pointindex length } {
+
+    puts stderr "\n\n---------------------------------------------------------------------"
+    puts stderr "Addining skeleton part centerno=$centerno numparts=$numparts inindex=$inindex pointindex=$pointindex\n"
+
+    for { set i 0 } { $i < $numparts } { incr i } {
+	set x [ $joints GetPoint  [ expr $inindex*3 ] ]
+	puts stderr "Inserting Point $inindex ($x)"
+	$skeletonpts InsertNextPoint [ lindex $x 0 ] [ lindex $x 1 ] [ lindex $x 2 ]
+	$linepairs InsertNextCell 2
+	if { $i == 0 } {
+	    set p1 $centerno
+	} else {
+	    set p1 [ expr $pointindex -1 ]
+	}
+	set p2 $pointindex
+	$linepairs InsertCellPoint $p1
+	$linepairs InsertCellPoint $p2
+	puts stderr "Inserted Pair $p1, $p2 ... numberofpts = [ $skeletonpts GetNumberOfPoints ]"
+	incr pointindex
+	incr inindex
+    }
+    
+    # This is the end of the leg
+    # --- Add this later
+    # --------------------------
+    
+     set x0 [ $skeletonpts GetPoint [ expr $pointindex - 2 ] ]
+     set x1 [ $skeletonpts GetPoint [ expr $pointindex - 1 ] ]
+     for { set i 0 } {$i <= 2 } { incr i } {
+ 	set x2($i) [ expr [ lindex $x1 $i ] + $length * ( [ lindex $x1 $i ] - [ lindex $x0 $i ]) ]
+     }
+     puts stderr "Inserting Point $x2(0) $x2(1) $x2(2) from x0 ( [ expr $pointindex - 2 ] )=$x0, x1 ( [ expr $pointindex - 1 ] )=$x1,   "
+     $skeletonpts InsertNextPoint $x2(0) $x2(1) $x2(2)
+     $linepairs InsertNextCell 2
+     $linepairs InsertCellPoint [ expr $pointindex - 1 ]
+     $linepairs InsertCellPoint $pointindex
+     incr pointindex
+
+    return $pointindex
+
+}
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclmouseplanes::CreateWireframeModel { joints spheresize tubesize } {
+
+    set njoints   [ expr int([ $joints GetNumberOfPoints ] /3) ]
+    set spinehead [ expr $spinedivisions + $hashead ]	
+
+    set neededjoints [ expr 2*($hashindlimbs+$hasforelimbs)*(2+$hasfeet) + $taildivisions + $spinehead + 1]
+
+    
+    if { $tubesize <=0.0 && $spheresize <=0.0 } {
+	::pxtclutil::Warning "sphereisze=0.0 and tubesize=0.0, nothing to do!"
+	return 0
+    }
+
+    if { $njoints != $neededjoints } {
+	::pxtclutil::Warning "Not enough points specified to create wireframemodel \nneed [ expr 3*$neededjoints ]"
+	return 0
+    }
+
+    
+    
+    # Two prong strategy ... define all points .... define all spheres ... define poly (connect)
+
+    # First two the joint locations --- this is easy every third point !!!
+    # --------------------------------------------------------------------
+    set jointloc [ vtkPoints [ pxvtable::vnewobj ]]
+    $jointloc Allocate [ expr $njoints +8 ] 10
+
+    for { set i 0 } { $i < $njoints } { incr i } {
+	set x [ $joints GetPoint [ expr $i *3 ] ]
+	$jointloc InsertNextPoint [ lindex $x 0 ] [ lindex $x 1 ] [ lindex $x 2 ]		
+    }
+
+    # Now The Skeleton
+    set skeletonpts [ vtkPoints [ pxvtable::vnewobj ]]
+    $skeletonpts Allocate [ expr $njoints +8 ] 10
+    set linepairs [  vtkCellArray [ pxvtable::vnewobj ]]
+    $linepairs Allocate [ expr $njoints +8 ] 10
+
+    # Add Hip Center
+    set x [ $joints GetPoint 0 ]
+    $skeletonpts InsertNextPoint [ lindex $x 0 ] [ lindex $x 1 ] [ lindex $x 2 ]
+    set center 0
+    set pointindex  1
+    set legparts [ expr 2 + $hasfeet ]
+
+    if { $hashindlimbs ==1 } {
+	for { set leg 0 } { $leg <=1 } { incr leg } {
+	    set offset [ expr 1 + ( $legparts * $leg ) ]
+	    set pointindex [ AddSkeletonPart $center $joints $legparts $skeletonpts $linepairs $offset $pointindex 0.25 ]
+	}
+    }
+
+    if { $taildivisions > 0 } {
+	set offset [ expr 1 + 2*$legparts*($hashindlimbs+$hasforelimbs) ]
+	set pointindex [ AddSkeletonPart $center $joints $taildivisions $skeletonpts $linepairs $offset $pointindex 0.5 ]
+    }
+
+    if { $spinehead > 0 } {
+	set offset [ expr 1 + 2*$legparts*($hashindlimbs+$hasforelimbs) + $taildivisions ]
+	set length 1.0
+	if { $hashead > 0 } {
+	    set length 0.25
+	}
+	set pointindex [ AddSkeletonPart $center $joints $spinehead $skeletonpts $linepairs $offset $pointindex $length ]
+	set center [ expr $pointindex -1 ]
+    }
+
+    if { $hasforelimbs ==1 } {
+	for { set leg 0 } { $leg <=1 } { incr leg } {
+	    set offset 1 
+	    if { $hashindlimbs > 0 } {
+		set offset [ expr 1 + $legparts *2 ]
+	    }
+	    set pointindex [ AddSkeletonPart $center $joints $legparts $skeletonpts $linepairs $offset $pointindex 0.25 ]
+	}
+    }
+
+
+    # ... make output ...
+
+    set append [ vtkAppendPolyData [ pxvtable::vnewobj ]]
+
+    if { $spheresize > 0.0 } {
+	# first spheres ... then tubes ... then combine
+	set glyph [ vtkGlyph3D [ pxvtable::vnewobj ]]
+	
+	set sphere [ vtkSphereSource [ pxvtable::vnewobj ]] 
+	$sphere SetRadius $spheresize
+	$sphere Update
+	$glyph SetSource [ $sphere GetOutput ]
+	$sphere Delete
+	
+	set pdata [ vtkPolyData [ pxvtable::vnewobj ]] 
+	$pdata SetPoints $jointloc; $jointloc Delete
+	
+	$glyph SetInput $pdata ; $pdata Delete
+	$glyph Update
+	$append AddInput [ $glyph GetOutput ] 
+	$glyph Delete
+    }
+
+    # then tubes ----------------------------------
+    if { $tubesize > 0.0 } {
+	set tube [ vtkTubeFilter [ pxvtable::vnewobj ]]
+	
+	set pdata [ vtkPolyData [ pxvtable::vnewobj ]] 
+	$pdata SetPoints $skeletonpts; $skeletonpts Delete
+	$pdata SetLines $linepairs   ; $linepairs Delete
+	
+	$tube SetInput $pdata 
+	$tube SetRadius $tubesize
+	$tube SetNumberOfSides 8
+	$tube SetVaryRadiusToVaryRadiusOff
+	$tube Update
+	$append AddInput [ $tube GetOutput ]
+	#$append AddInput  $pdata
+	$tube Delete
+	
+	$pdata Delete
+	
+	# then combine and we are done ---------------
+    }
+    $append Update
+    set pdata [ vtkPolyData [ pxvtable::vnewobj ]] 
+    $pdata ShallowCopy [ $append GetOutput ]; $append Delete
+    return $pdata
+}
+
+# ------------------------------------------------------------------------------------------
+#
+# pxitclmousechopper control
+#
+# ------------------------------------------------------------------------------------------
+
+itcl::class pxitclmousechopper {
+
+    inherit pxitclbasecontrol
+
+    private   common   thisparam
+    protected variable initialized       0
+    protected variable planeslistbox     0
+    public    variable oblique_slice     0
+    public    variable oblique_gui       0
+    public    variable mouse_map_gui     0
+    public    variable mouse_label_gui   0
+    public    variable planes            0
+    public    variable appname "Virtual Mouse Butcher"
+    #    protected variable fullyinitialized  0
+    # ------------------------------------------------------
+    
+    constructor { par } {
+	::pxitclbasecontrol::constructor $par
+    } { 
+	set planes [ [ pxitclmouseplanes \#auto 30 ] GetThisPointer ]
+    }
+    
+    # Initialization
+    # --------------
+    public    method AttachToBaseControl { breg { addseparator 1 } } 
+    public    method Initialize  { basewidget args } 
+    public    method DelayedInitialize  { }
+
+    
+    # Create GUI
+    # ----------
+    public    method CreateDefinitionsGUI { widget }
+    public    method CreatePlanesGUI { widget }
+    public    method CreateMapGUI { widget }
+    public    method CreateSegmentedMapGUI { widget }
+    public    method CreateOutputGUI { widget }
+
+    # Segmentation Postprocessing
+    # ---------------------------
+    public    method UpdateLabelImageRanges { }
+    public    method GrabSegmentationMapFromViewer { args }
+    public    method CreateSoftTissueVOI {  }
+    public    method CreateBoneVOI {  }
+    public    method ExtractAndResliceLabelMap { tissuelabel  tissuelabel2 suffix  { dilateerode 0 } }
+
+    #  Joint Extraction
+    # ---------------------------
+    public    method GetJoint { index map bonemap } 
+    public    method AutoJoints {  } 
+    public    method SingleJoint { } 
+    public    method ClickJoints { { mode manual } } 
+
+
+    # Model Generation
+    # ----------------
+    public    method LoadModel { fname } 
+    protected method FixPlanes {  } 
+    public    method LoadMouseMap { fname } 
+    public    method LoadSegmentedMap { fname } 
+
+    public    method SaveModel { fname } 
+    public    method InitializeModel { mode args } 
+    public    method GenerateTransformationModel { } 
+    public    method GenerateMouseMap { } 
+    public    method GenerateWireModel { } 
+
+    # Oblique Slice Interaction
+    # -------------------------
+    public    method ShowOblique { } 
+    public    method UpdateArrowColor { } 
+    public    method UpdateGUIFromPlanes { } 
+    public    method UpdatePlanesFromGUI { } 
+    public    method SelectPlane { { value -1 } { direction 0 } } 
+    public    method TestPlane { mode }
+    public    method UpdatePlane { } 
+    public    method GetObliqueSlice { } 
+    
+    # Segmentation Control
+    # --------------------
+    public method ShowSegmentationControl { }
+
+}
+
+itcl::body pxitclmousechopper::AttachToBaseControl { breg  { addseparator 1 } } { 
+    
+    $this Initialize [ $breg GetBaseWidget ].[pxvtable::vnewobj ]
+    if { $addseparator > 0 } {
+	[ $breg cget -featuremenu ] add separator
+    }
+    $this AddToMenuButton [ $breg cget -featuremenu ]  "Mouse Chopper"
+}
+
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::LoadMouseMap { fname } { 
+    set image [ $mouse_map_gui GetObject ]
+    $image Load $fname
+    $mouse_map_gui Update
+}
+
+itcl::body pxitclmousechopper::LoadSegmentedMap { fname } { 
+    set image [ $mouse_label_gui GetObject ]
+    $image Load $fname
+    $mouse_label_gui Update
+}
+
+# --------------------------------------------------------------------
+
+itcl::body pxitclmousechopper::FixPlanes { } { 
+
+    # Go to first plane
+    if { [ $this GetObliqueSlice  ] == 0 } { return }
+
+    set parray [ $planes GetPlanes ]
+    set nt [ $parray GetNumberOfTuples ]
+    set max [ expr $nt -1 ]
+
+    set ok $thisparam($this,enable_updateplane)
+    set thisparam($this,enable_updateplane) 1
+
+    for { set index $max } { $index >= 0 } { set index [ expr $index -1 ] } {
+	puts stderr "Fixing Plane $index/$nt"
+	$this SelectPlane $index 0
+	$oblique_slice UpdateImagePlane [ $parray GetComponent $index 3 ] [ $parray GetComponent $index 0 ]  [ $parray GetComponent $index 1 ]  [ $parray GetComponent $index 2 ] 
+	$oblique_gui   UpdateScales
+	$this UpdateArrowColor
+	$this UpdatePlane
+    }
+
+    set thisparam($this,enable_updateplane) $ok
+    
+}
+
+# --------------------------------------------------------------------
+
+itcl::body pxitclmousechopper::LoadModel { fname } { 
+
+    if { $fullyinitialized == 0 } { $this DelayedInitialize }
+
+    set ok [ $planes Load $fname ]
+
+    if { $ok > 0 } {
+
+	SetTitle "$appname [ file tail [ $planes cget -filename ]]"
+
+	$this FixPlanes
+
+	$this UpdateGUIFromPlanes
+    } elseif  { $ok == -1 } {
+	::pxtclutil::Warning "Failed to read planes model from [ $planes cget -filename ]"
+    }
+
+    $planes  GetAllJointNumbers
+}
+
+itcl::body pxitclmousechopper::SaveModel { fname } { 
+
+    UpdatePlanesFromGUI
+    set ok [ $planes Save $fname ]
+
+    if { $ok > 0 } {
+	SetTitle "$appname [ file tail [ $planes cget -filename ]]"
+    }
+
+}
+# -------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::ClickJoints { { mode manual } } {
+
+    set param [ $planes GetModelParameters ] 
+    
+    set hasfeet [ lindex $param 0 ]
+    set hashindlimbs [ lindex $param 1 ]
+    set hasforelimbs [ lindex $param 2 ]
+    set hashead [ lindex $param 3 ]
+    set taildivisions [ lindex $param 4 ]
+    set spinedivisions [ lindex $param 5 ]
+
+    set ok 1
+    
+    set landmarkcontrol [ $parent GetLandmarkControl ] 
+    $landmarkcontrol ShowWindow
+    [ $landmarkcontrol GetLandmarkControl ] SetArticulatedMouseSetup $hasfeet $hashindlimbs $hasforelimbs $hashead $taildivisions $spinedivisions 
+    
+    if { $mode == "manual"} {
+	::pxtclutil::Info "Follow the instructions in the landmark control to locate the joints"
+    }
+
+    return $ok
+
+}
+# -------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::GenerateWireModel { } {
+
+    set landmarkcontrol 0
+    set polydatacontrol 0
+
+    catch { set landmarkcontrol [ [ $parent GetLandmarkControl ]  GetLandmarkControl ]  }
+    catch { set  polydatacontrol [ [ $parent GetPolyDataControl ] GetPolyDataControl ] }
+
+    if { $landmarkcontrol == 0 || $polydatacontrol == 0 } { return  }
+    
+    set curve [ $landmarkcontrol GetCollection -1 ]
+    set newcurve [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    $newcurve Copy  $curve 
+    $newcurve Compact
+    set joints [ $newcurve GetPoints ]
+
+
+    set surface [ $planes CreateWireframeModel $joints $thisparam($this,sphereradius) $thisparam($this,tuberadius) ]
+    if { $surface !=0 } {
+	$polydatacontrol SetClipboardSurface $surface "wiremodel.vtk"
+	::pxtclutil::Info "Wiremodel surface wiremodel.vtk is in the clipboard of the viewer surface control"
+	[ $parent GetPolyDataControl ] ShowWindow
+	$surface Delete
+    }
+   
+    $newcurve Delete
+    return 0
+}
+
+# -------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::GenerateTransformationModel { } {
+
+    # put it all together to generate the full transformation model and save in .psim file
+    #
+    #
+    set image [ $mouse_map_gui GetObject ]
+    if { [ $image GetImageSize ] < 2 } {
+	::pxtclutil::Warning "Failed to generate transformation model, no Mouse VOI Map in memory"
+	return 0
+    }
+
+    set r [ [ [ [ $image GetImage ] GetPointData ] GetScalars ] GetRange ]
+    set rmax [ lindex $r 1 ]
+    set rmin [ lindex $r 0 ]
+
+    set param [ $planes GetModelParameters ] 
+    set hasfeet [ lindex $param 0 ]
+    set hashindlimbs [ lindex $param 1 ]
+    set hasforelimbs [ lindex $param 2 ]
+    set hashead [ lindex $param 3 ]
+    set taildivisions [ lindex $param 4 ]
+    set spinedivisions [ lindex $param 5 ]
+
+    set totallabels [ expr 1+2*($hashindlimbs+$hasforelimbs)*(2+$hasfeet) + $hashead + $taildivisions + $spinedivisions ]
+    set maxrange    [ expr $totallabels -1 ]
+
+
+    if { $rmin !=-1 || $rmax != $maxrange } {
+	::pxtclutil::Warning "Bad Mouse VOI Map. Range = ${rmin}:${rmax}, expecting something like -1:${totallabels}"
+	return 0
+    }
+    
+    set numjoints $rmax
+    set neededpoints [ expr $numjoints * 3 ]
+
+    set landmarkcontrol 0
+    catch { 
+	set landmarkcontrol [ [ $parent GetLandmarkControl ]  GetLandmarkControl ]
+    }
+
+    if { $landmarkcontrol == 0 } {
+	return
+    }
+
+    set curve [ $landmarkcontrol GetCollection -1 ]
+    set numpoints [ $curve GetNumPoints ]
+
+    if { $numpoints < $neededpoints } {
+	::pxtclutil::Warning "Bad Landmark File, not enough joint points clicked ($numpoints vs $neededpoints)"
+	return 0
+    }
+
+
+
+    set outfname  [tk_getSaveFile -title "Specify Output Filename For Transformation"  -filetypes { {"PolySimilarity Files" {.psim}} } ]
+    if { [ string length $outfname ] < 1 } {
+	return 0
+    }
+
+
+    set newcurve [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    $newcurve Copy  $curve 
+    $newcurve Compact
+    set points [ $newcurve GetPoints ]
+
+    set imgname "[ file root $outfname ]_model.hdr"
+    $image Save $imgname
+    $mouse_map_gui Update
+
+
+    set newtmodel [ vtkpxPolySimilarityTransform [ pxvtable::vnewobj ] ]
+    $newtmodel SetRegionLabelImageName $imgname
+    $newtmodel SetRegionLabel [ $image GetImage ]
+    $newtmodel SetWholeBodyPreset 0  $hasfeet $hashindlimbs $hasforelimbs $hashead $taildivisions $spinedivisions 
+    $newtmodel SetOriginAxes $points
+
+    $newtmodel CreateThinPlateSplineTransform $thisparam($this,tpspoints) 2.0 1.5 2.0
+
+
+    set ok [ $newtmodel Save $outfname ]
+
+
+
+    if { $ok == 1 } {
+	::pxtclutil::Info "Transformation saved in $outfname (model in $imgname)"
+    } else {
+	::pxtclutil::Warning "Failed to save transformation in $outfname"
+    }
+
+    $newtmodel Delete
+    $newcurve Delete
+   
+
+}
+# -------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::GenerateMouseMap { } {
+
+    set image [ $parent cget -currentimage ]
+
+    set polydatacontrol 0
+    catch { set  polydatacontrol [ [ $parent GetPolyDataControl ] GetPolyDataControl ] }
+    set surface 0 
+
+    if { $polydatacontrol != 0 } {
+	set surface [ vtkPolyData [ pxvtable::vnewobj ]]
+    }
+    
+    if { [ $image GetImageSize ] > 16 } {
+	set img [ $planes CreateRegionLabelImage $image $thisparam($this,resolution) $thisparam($this,kernelsize) $thisparam($this,threshold) $surface ]
+    }
+    
+    if { $img != 0 } {
+	[ $mouse_map_gui GetObject ] ShallowCopyImage $img
+	[ $mouse_map_gui GetObject ] configure -filename  "model.hdr"
+	[ $mouse_map_gui GetObject ] CopyImageHeader [ $image GetImageHeader ]
+	$mouse_map_gui Update
+    }
+
+    if { $surface != 0 } {
+	$polydatacontrol SetClipboardSurface $surface "model.vtk"
+	::pxtclutil::Info "Placed surface model.vtk in the clipboard of the viewer surface control"
+	[ $parent GetPolyDataControl ] ShowWindow
+	$surface Delete
+    }
+    
+    return 1
+}
+# -------------------------------------------------------------------------------
+
+itcl::body pxitclmousechopper::InitializeModel { mode args } { 
+
+    # Add requisite plane types
+
+    if { $fullyinitialized == 0 } { $this DelayedInitialize }
+
+    set img [ $parent GetDisplayedImage ]
+    if { [ $img GetImageSize ] > 16 } {
+	set dim [ [  $img  GetImage ] GetDimensions ]
+	set spa [ [  $img  GetImage ] GetSpacing ]
+	set d ""
+	for { set ia 0 } { $ia <=2 } { incr ia } {
+	    lappend d [ expr [ lindex $spa $ia ] * [ lindex $dim $ia ]]
+	}
+	$planes configure -dimensions $d
+    }
+
+    if { $mode == "hindlimbfoot" } {
+	set ok [ $planes InitializeModel 1 1 0 0 0 0 ]
+    } elseif { $mode == "hindlimb" } {
+	set ok [ $planes InitializeModel 0 1 0 0 0 0 ]
+    } elseif { $mode == "gui" } {
+	set ok [ $planes InitializeModel $thisparam($this,hasfeet) $thisparam($this,hashindlimbs) $thisparam($this,hasforelimbs) $thisparam($this,hashead) $thisparam($this,taildivisions) $thisparam($this,spinedivisions)  ]
+    }
+
+    if { $ok ==1 } { $this UpdateGUIFromPlanes }
+}
+
+itcl::body pxitclmousechopper::Initialize { basewidg args } {
+
+    if { $initialized == 1 } { return $basewidget }
+
+    set basewidget [ toplevel $basewidg ] 
+    wm withdraw $basewidget
+    wm geometry $basewidget 570x350
+
+    SetTitle $appname
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    set fullyinitialized 0
+    return $basewidget
+}
+
+itcl::body pxitclmousechopper::GetObliqueSlice {  } {
+
+    if { $oblique_slice == 0 } {
+	set orthoviewer [ $parent GetViewer ]
+	set oblique_slice [ $orthoviewer GetObliqueImageSlice ]
+	if { [ string length $oblique_slice ] < 2 } {
+	    set oblique_slice 0
+	}
+    }
+    return $oblique_slice
+}
+
+itcl::body pxitclmousechopper::DelayedInitialize {  } {
+
+
+    if { $fullyinitialized ==1 } {
+	return
+    }
+
+    set fullyinitialized 1
+
+    set orthoviewer [ $parent GetViewer ]
+    set oblique_gui [ $orthoviewer GetObliqueControl ]
+    $this GetObliqueSlice
+
+    set w [ frame $basewidget.bottom ]
+
+
+    set notebook [ iwidgets::tabnotebook $basewidget.top  -tabpos w -width 350 ]
+    pack $w -side bottom -expand f -fill x -pady 10
+    pack $notebook  -side top -expand t -fill both
+
+    $this CreateDefinitionsGUI [ $notebook add -label "Definition" ]
+    $this CreatePlanesGUI [ $notebook add -label "Planes" ]
+    $this CreateMapGUI [ $notebook add -label "VOI Map" ]
+    $this CreateSegmentedMapGUI [ $notebook add -label "Segmentation" ]
+    $this CreateOutputGUI  [ $notebook add -label "Output Model" ]
+    $notebook view "Definition"
+
+    eval "button $w.1 -text Close -command { $this HideWindow } "
+    eval "button $w.load -text \"Load Planes\" -command { $this LoadModel \"\" } "
+    eval "button $w.save -text \"Save Planes\" -command { $this SaveModel \"\" } "
+    eval "button $w.init -text Initialize -command { $this InitializeModel hindlimbfoot }"
+
+
+    pack $w.load $w.save $w.init -side left -padx 2
+    pack $w.1 -side right
+
+    $this InitializeModel "hindlimbfoot"
+
+    
+    set canvas [ [ $notebook component tabset ] component canvas ];     set l [ AddLogoLabel $canvas ];     pack $l -side bottom -padx 1 
+}
+
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclmousechopper::ShowOblique {  } {
+    
+    catch { $oblique_gui Show 1 }
+}
+
+itcl::body pxitclmousechopper::CreateDefinitionsGUI { widget } {
+
+    set thisparam($this,hashead) 0 
+    set thisparam($this,hasfeet) 1
+    set thisparam($this,hashindlimbs) 1
+    set thisparam($this,hasforelimbs) 0
+    set thisparam($this,taildivisions) 1
+    set thisparam($this,spinedivisions) 2
+
+    set b [ frame  $widget.b ] ; pack $widget.b -side bottom -expand f -fill x
+    set base  [ LabelFrame:create $widget.a -text "Model Options"]
+    pack $widget.a  -side top -fill x -expand f
+
+    checkbutton $base.1 -variable [ itcl::scope thisparam($this,hashindlimbs) ] -text "Hind Limbs"
+    checkbutton $base.2 -variable [ itcl::scope thisparam($this,hasfeet)  ] -text "Feet"
+    checkbutton $base.3 -variable [ itcl::scope thisparam($this,hasforelimbs) ] -text "Fore Limbs"
+    checkbutton $base.4 -variable [ itcl::scope thisparam($this,hashead) ] -text "Head"
+    
+    set cw [ [ iwidgets::labeledwidget $base.5  -labeltext "Tail Divisions:"  ] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,taildivisions) ] 0 1 2 3 4 5 
+    pack $cw.optmenu  -expand f
+
+    set cw [ [ iwidgets::labeledwidget $base.6 -labeltext "Spine Divisions:"  ] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,spinedivisions) ] 0 1 2 3 4 5 6 7 8 9 
+    pack $cw.optmenu  -expand f
+
+    pack $base.1 $base.2 $base.5 $base.6 $base.3 $base.4 -side top -expand f -padx 10 -pady 2
+
+
+    eval "button $b.1 -text \"Hind-Limb\" -command { $this InitializeModel hindlimb } "
+    eval "button $b.2 -text \"Hind-Limb-Foot\" -command { $this InitializeModel hindlimbfoot } "
+    eval "button $b.3 -text \"Custom\" -command { $this InitializeModel gui } "
+    pack $b.1 $b.2 $b.3 -side left -expand f -fill x
+
+}
+
+itcl::body pxitclmousechopper::CreatePlanesGUI { widget } {
+
+    set thisparam($this,enable_updateplane) 1
+    set thisparam($this,currentplaneindex) -1
+    set thisparam($this,currentplane) "None"
+    set thisparam($this,currentplane_n)    "1 0 0 "
+    set thisparam($this,currentplane_c)    "0 0 0 "
+    set thisparam($this,currentplane_dist)  "0.0"
+    set thisparam($this,currentplane_above) 0
+
+    set thisparam($this,currentplane_autoupdate) 1
+
+    frame $widget.left
+    frame $widget.right
+
+    eval "iwidgets::scrolledlistbox $widget.left.1 -labeltext \"List of Planes\" \
+			 -vscrollmode dynamic -hscrollmode none \
+			 -selectmode single -exportselection 0 \
+			 -labelpos nw -selectioncommand { $this SelectPlane -1 } "
+    set planeslistbox $widget.left.1
+    $planeslistbox  clear
+    pack $widget.left -side left -expand f -fill y
+    pack $widget.right -side right -expand t -fill both
+
+    set bbar [ frame $widget.left.2 ] ; pack $bbar -side bottom -expand f -fill x
+    pack $widget.left.1 -side top -expand t -fill both
+
+    eval "button $bbar.0 -text \"Previous\" -command { $this SelectPlane -1 -1 } "
+    eval "button $bbar.1 -text \"Next\" -command { $this SelectPlane -1 1 } "
+    pack $bbar.0 $bbar.1 -side left -expand t -padx 5 -pady 2
+
+
+    set base   [ LabelFrame:create $widget.right.1 -text "Current Plane"]
+    set base2  [ LabelFrame:create $widget.right.2 -text "Operations"]
+    pack $widget.right.2 -side bottom -expand f -fill x
+    pack $widget.right.1 -side top -expand t -fill both
+
+    set k 0
+    iwidgets::entryfield $base.$k -labeltext "Plane Name:"  -width 15 -validate real -textvariable [ itcl::scope thisparam($this,currentplane) ] -relief sunken  -state disabled
+    pack $base.$k -side top -expand f -fill x; incr k
+
+    frame $base.$k 
+    iwidgets::entryfield $base.$k.1 -labeltext "Normal:"  -width 15 -validate real -textvariable [ itcl::scope thisparam($this,currentplane_n) ] -relief sunken  -state disabled
+    eval "checkbutton $base.$k.2 -variable [ itcl::scope thisparam($this,currentplane_above) ] -text Above -command { $this UpdateArrowColor }"
+    pack $base.$k.1 $base.$k.2 -side left -expand f -fill x
+    pack $base.$k -side top -expand f -fill x; incr k
+
+    frame $base.$k 
+    iwidgets::entryfield $base.$k.1 -labeltext "Center:"  -width 15 -validate real -textvariable [ itcl::scope thisparam($this,currentplane_c) ] -relief sunken  -state disabled
+    iwidgets::entryfield $base.$k.2 -labeltext "Offset:"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,currentplane_dist) ] -relief sunken  -state disabled
+    pack $base.$k.1 $base.$k.2 -side left -expand f -fill x
+    pack $base.$k -side top -expand f -fill x; incr k
+    
+
+    checkbutton $base.$k -variable [ itcl::scope thisparam($this,currentplane_autoupdate) ] -text "Update Oblique Slice"
+    pack $base.$k -side top -expand f -fill x;  incr k
+
+    set w  [ frame $base.$k ];     pack $base.$k -side top -expand f -fill x;  incr k
+    eval "button $w.0 -text \"Update Plane\" -command { $this UpdatePlane }"
+    eval "button $w.1 -text \"Oblique Slice Control\" -command { $this ShowOblique } "
+
+    pack $w.0 $w.1 -side left -expand f -fill x -pady 2
+
+
+    set w2 [ frame $base2.$k ];     pack $base2.$k -side top -expand f -fill x;  incr k
+    set w3 [ frame $base2.$k ];     pack $base2.$k -side top -expand f -fill x;  incr k
+
+
+    eval "button $w2.1 -text \"Apply Plane\"   -command { $this TestPlane 0 }"
+#    eval "button $w2.2 -text \"Apply Plane Pair\"   -command { $this TestPlane 1 }"
+    eval "button $w2.2 -text \"Single Joint\"   -command { $this SingleJoint } "
+    pack  $w2.1 $w2.2 -side left -expand f -padx 2 -fill x
+
+    eval "button $w3.3 -text \"Extract Leg\"   -command { $this TestPlane 2 }"
+    eval "button $w3.4 -text \"Extr. Leg (no foot)\"   -command { $this TestPlane 3 }"
+    pack  $w3.3 $w3.4 -side left -expand f -padx 0 -fill x 
+    
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::CreateMapGUI { widget } {
+
+
+    set bot [ frame $widget.f1 ]
+    set f1 [ frame $widget.f2 ]
+
+    pack $f1 $bot -side bottom -expand false -fill x -pady 2
+
+    set mouse_map_gui [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+    ${mouse_map_gui} configure -description "Mouse VOI Map"
+    ${mouse_map_gui} Initialize $widget.top
+    ${mouse_map_gui} AddFunction "$parent SetMaskFromObject" "Display Mask" "$this"
+    ${mouse_map_gui} AddFunction "$parent SetResultsFromObject" "Display" "$this"
+    $widget.top configure -background darkgray
+    pack $widget.top -side top -expand f -fill x -pady 3
+
+    pack forget [ ${mouse_map_gui} cget -browsebutton ]
+
+    set thisparam($this,kernelsize) 2.0
+    set thisparam($this,threshold)  200.0
+    set thisparam($this,resolution)  2.0
+
+    eval "button $f1.d -text \"Generate Mouse Map\"   -command { $this GenerateMouseMap } "
+    pack $f1.d   -side left -padx 5 -expand f -fill x
+
+
+    label $bot.a -text "Sigma"
+    tk_optionMenu $bot.b [ itcl::scope thisparam($this,kernelsize) ]  "0.1" "0.5" "1.0" "1.5" "2.0" "3.0" "5.0" 
+    label $bot.a1 -text "Resol"
+    tk_optionMenu $bot.b1 [ itcl::scope thisparam($this,resolution) ]  "0.5" "1.0" "1.5" "2.0" "3.0" "4.0"
+    iwidgets::entryfield $bot.c -labeltext "Threshold:"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,threshold) ] -relief sunken 
+    pack $bot.a $bot.b $bot.a1 $bot.b1 $bot.c -side left -expand f -padx 2
+}
+# -----------------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::UpdateLabelImageRanges { } {
+
+    set image  [ $mouse_label_gui GetObject ] 
+    if { [ $image GetImageSize ] < 2 } {
+	return 
+    }
+
+    set r [ [ [ [ $image GetImage ] GetPointData ] GetScalars ] GetRange ]
+    set rmax [ lindex $r 1 ]
+    set rmin [ lindex $r 0 ]
+
+    if { $rmax > 20 } { 
+	set rmax 20
+    }
+
+    set thisparam($this,boneclass) $rmax
+    if { $rmax <= 2 } {
+	set thisparam($this,softtissuemin) 1
+	set thisparam($this,softtissuemax) 1
+    } else {
+	set thisparam($this,softtissuemin) 2
+	set thisparam($this,softtissuemax) [ expr $rmax -1 ]
+    }
+}
+
+itcl::body pxitclmousechopper::GrabSegmentationMapFromViewer { args } {
+
+    set img [ $parent GetDisplayedImage ]
+    if { [ $img GetImageSize ] < 16 } {
+	::pxtclutil::Warning "No Segmentation Output Image in the Viewer"
+	return
+    }
+
+    set r [ [ [ [ $img GetImage ] GetPointData ] GetScalars ] GetRange ]
+    set rmax [ lindex $r 1 ]
+    set rmin [ lindex $r 0 ]
+    if { $rmin !=0 || $rmax>10 } {
+	::pxtclutil::Warning "Bad Segmented Mask .. expecting image with three levels 0=air, 1=soft tissue, ... N=bone"
+	return
+    }
+    
+    [ $mouse_label_gui GetObject ] ShallowCopy $img
+    $mouse_label_gui Update
+    $this UpdateLabelImageRanges
+
+}
+# -----------------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::ExtractAndResliceLabelMap { tissuelabel   tissuelabel2 suffix { dilateerode 0 } } {
+
+
+    set map [ $mouse_map_gui GetImage ]
+    if { [ $map  GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No Mouse Map Image in Memory"
+	return
+    }
+
+    set lab [ $mouse_label_gui GetImage ]
+    if { [ $map  GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No Mouse Label Image in Memory"
+	return
+    }
+
+    set thr [ vtkImageThreshold [ pxvtable::vnewobj ]]
+
+    if { [ $map  GetImageSize ] != [ $lab GetImageSize ] } {
+	puts stderr "Reslicing Label Map\n"
+	set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+	$resl SetInput [ $lab GetImage ]
+	$resl SetInformationInput [ $map GetImage ]
+	$resl SetInterpolationMode 0
+	$resl Update
+	$thr SetInput [ $resl GetOutput ]
+	$resl Delete
+    } else {
+	$thr SetInput [ $lab GetImage ]
+    }
+
+    $thr DebugOn
+    puts stderr "Thresholding $tissuelabel $tissuelabel2"
+    $thr ThresholdBetween $tissuelabel $tissuelabel2
+    $thr SetOutputScalarType [ [ $map GetImage ] GetScalarType ]
+    $thr DebugOff
+    $thr ReplaceInOn
+    $thr ReplaceOutOn
+    $thr SetInValue  1.0
+    $thr SetOutValue 0.0
+    $thr Update
+
+    set image [ [ pxitclimage \#auto ] GetThisPointer ]
+
+    if { $dilateerode == 0 } {
+	$image ShallowCopyImage [ $thr GetOutput ]
+    } elseif { $dilateerode > 0 } {
+	puts stderr "Dilating $dilateerode"
+	set dilate  [  vtkImageContinuousDilate3D [ pxvtable::vnewobj ] ]
+	$dilate SetInput [ $thr GetOutput ]
+	$dilate SetKernelSize $dilateerode $dilateerode $dilateerode
+	$dilate Update
+	$image ShallowCopyImage [ $dilate GetOutput ]
+	$dilate Delete
+    } else {
+	set dilateerode [ expr -$dilateerode ]
+	puts stderr "Eroding $dilateerode"
+	set erode  [  vtkImageContinuousErode3D [ pxvtable::vnewobj ] ]
+	$erode SetInput [ $thr GetOutput ]
+	$erode SetKernelSize $dilateerode $dilateerode $dilateerode
+	$erode Update
+	$image ShallowCopyImage [ $erode GetOutput ]
+	$erode Delete
+    }
+
+    $image CopyImageHeader [  $lab GetImageHeader ]
+    set fname [  $lab cget -filename ]
+
+    set fname "[ file root $fname]_${suffix}.hdr"
+
+    puts stderr "Filename $fname"
+    $image configure -filename $fname
+    $thr Delete
+    return $image
+}
+# -----------------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::CreateSoftTissueVOI { } {
+
+    set map [ $mouse_map_gui GetImage ]
+    if { [ $map  GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No Mouse Map Image in Memory"
+	return
+    }
+
+    set lab [ $mouse_label_gui GetImage ]
+    if { [ $map  GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No Mouse Label Image in Memory"
+	return
+    }
+
+    set rmin $thisparam($this,softtissuemin) 
+    set rmax $thisparam($this,softtissuemax) 
+    
+    set resllab [ $this ExtractAndResliceLabelMap $rmin $rmax "softtisue_${rmin}_${rmax}" $thisparam($this,dilateerode) ]
+
+    set m [ vtkImageMathematics [ pxvtable::vnewobj ]]
+    $m SetInput1 [ $resllab GetImage ]
+    $m SetInput2 [ $map GetImage  ]
+    $m SetOperationToMultiply
+    $m Update
+
+    set image [ [ pxitclimage \#auto ] GetThisPointer ]
+    $image ShallowCopyImage [ $m GetOutput ]
+    $image CopyImageHeader [  $map GetImageHeader ]
+
+    set fname [  $map cget -filename ]
+    set fname "[ file root $fname]_nobone.hdr"
+
+    $image configure -filename $fname
+    $parent SetResultsFromObject $image $this
+    itcl::delete object $image
+    catch { itcl::delete object $reslab }
+
+    $m Delete
+
+    return
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::CreateBoneVOI { } {
+
+    set map [ $mouse_map_gui GetImage ]
+    if { [ $map  GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No Mouse Map Image in Memory"
+	return
+    }
+
+    set lab [ $mouse_label_gui GetImage ]
+    if { [ $map  GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No Mouse Label Image in Memory"
+	return
+    }
+
+    set rmax $thisparam($this,boneclass) 
+    set resllab [ $this ExtractAndResliceLabelMap $rmax $rmax "bone" $thisparam($this,dilateerode) ]
+
+    $parent SetResultsFromObject $resllab $this
+
+    catch { itcl::delete object $reslab }
+
+    return
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::GetJoint { jointno map bonemap } {
+
+    # First Find The plane number of the joint = $jointno
+    set planeno [ $planes GetPlaneNumber $jointno ]
+    SelectPlane  $planeno
+
+    # First Get The Oblique slice 
+    set thisparam($this,enable_updateplane) 1
+    set doupd $thisparam($this,currentplane_autoupdate) 
+    set thisparam($this,currentplane_autoupdate)  1
+
+
+    # ----------------------------------------------------------------
+    # Next --- threshold and dilate the map for the region of interest
+    # ----------------------------------------------------------------
+
+    set thr [ vtkImageThreshold [ pxvtable::vnewobj ]]
+    $thr SetInput [  $map GetImage ]
+    puts stderr "\n Extracting From map $jointno:$jointno  for planeno $planeno : $thisparam($this,currentplane) Joint=$jointno"
+    $thr ThresholdBetween $jointno $jointno
+    $thr ReplaceInOn
+    $thr ReplaceOutOn
+    $thr SetInValue  100.0
+    $thr SetOutValue 0.0
+
+    set dilate  [  vtkImageContinuousDilate3D [ pxvtable::vnewobj ] ]
+    $dilate SetInput [ $thr GetOutput ];     
+    $dilate SetKernelSize 5 5 5
+
+    set m [ vtkImageMathematics [ pxvtable::vnewobj ]]
+    $m SetInput1 [ $dilate GetOutput ]
+    $m SetInput2 [ $bonemap GetImage ]
+    $m SetOperationToMultiply
+    $m Update
+
+    # ---------------------------------------------------------------
+    # Next Display the Image
+    # ---------------------------------------------------------------
+    set tmp [ [ pxitclimage \#auto ] GetThisPointer ]
+    $tmp ShallowCopyImage [ $m GetOutput ]
+    $tmp CopyImageHeader [ $map GetImageHeader ]
+    $thr Delete
+    $dilate Delete
+    $m Delete
+
+    $parent SetResultsFromObject $tmp $this
+
+    puts stderr "Selecting plane $planeno"
+    SelectPlane  $planeno
+
+    set oblmap [ vtkImageData [ pxvtable::vnewobj ]] 
+    $oblmap ShallowCopy [ $oblique_slice GetObliqueImage ]
+
+
+    set sim [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+    set newpts [ $sim GetCentroids $oblmap $thisparam($this,axislength) ]
+    $sim Delete
+
+    
+    set xform  [ $oblique_slice GetObliqueTransform ] 
+
+
+    for { set i 0 } { $i < 3 } { incr i } {
+	set pt [ $newpts GetPoint $i ]
+	set tpt [ $xform TransformPoint [ lindex $pt 0 ] [ lindex $pt 1 ] [ lindex $pt 2 ] ]
+	$newpts SetPoint $i [ lindex $tpt 0 ] [ lindex $tpt 1 ] [ lindex $tpt 2 ]
+    }
+
+    # ----- Restore Automatic Update settings
+
+   
+    $oblmap Delete
+    itcl::delete object $tmp
+
+    set thisparam($this,currentplane_autoupdate)  $doupd
+    set thisparam($this,enable_updateplane) 1
+    
+    return $newpts
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::SingleJoint { } {
+
+    set oblique_image 0
+
+    catch {
+	set dim [  [ $oblique_slice GetObliqueImage ] GetDimensions ]
+	if { [ lindex $dim 0 ] > 1 } {
+	    set oblique_image 1
+	}
+    }
+    
+    if { $oblique_image == 0 } {
+	::pxtclutil::Warning "Oblique Slice is Uninitialized"
+	return 0
+    }
+    
+    
+    set map [ $mouse_map_gui GetImage ]
+    if { [ $map  GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No Mouse Map Image in Memory"
+	return 0
+    }
+    
+    set lab [ $mouse_label_gui GetImage ]
+    if { [ $map  GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No Mouse Label Image in Memory"
+	return 0
+    }
+
+    set rmax $thisparam($this,boneclass) 
+    set bonemap [ $this ExtractAndResliceLabelMap $rmax $rmax "bone" 0 ]
+    
+    set r [ [ [ [ $map GetImage ] GetPointData ] GetScalars ] GetRange ]
+    set rmax [ lindex $r 1 ]
+    set rmin [ lindex $r 0 ]
+    
+    set numjoints [ expr $rmax - $rmin ]
+    if { $numjoints < 1 } { 
+	::pxtclutil::Warning "Bad Label Image in Memory $rmin:$rmax"
+	return 0
+    }
+
+    set planeno $thisparam($this,currentplaneindex)
+    set jointno [ $planes GetJointNumber $planeno ]
+
+    puts stderr "\nCurrent  Joint = $thisparam($this,currentplane) (index=$planeno) --> $jointno "
+
+    set interp [ $oblique_slice GetInterpolation ]
+    $oblique_slice SetInterpolation 0
+
+
+    set newpts [ $this GetJoint $jointno $map $bonemap ]
+	
+    set curve [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    $curve SetFromPoints $newpts
+    $newpts Delete
+
+    set landmarkcontrol [ $parent GetLandmarkControl ] 
+    [ $landmarkcontrol GetLandmarkControl ]  SetCollection $curve -1
+    $landmarkcontrol ShowWindow
+
+    $curve Delete
+
+    $oblique_slice SetInterpolation $interp
+
+    #    $parent SetResultsFromObject $bonemap $this
+    #   itcl::delete object $bonemap
+
+    return 1
+}
+
+# -----------------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::AutoJoints { } {
+
+    set oblique_image 0
+
+
+    catch {
+	set dim [  [ $oblique_slice GetObliqueImage ] GetDimensions ]
+	if { [ lindex $dim 0 ] > 1 } {
+	    set oblique_image 1
+	}
+    }
+    
+    if { $oblique_image == 0 } {
+	::pxtclutil::Warning "Oblique Slice is Uninitialized"
+	return 0
+    }
+    
+    
+    set map [ $mouse_map_gui GetImage ]
+    if { [ $map  GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No Mouse Map Image in Memory"
+	return 0
+    }
+    
+    set lab [ $mouse_label_gui GetImage ]
+    if { [ $map  GetImageSize ] < 2 } {
+	::pxtclutil::Warning "No Mouse Label Image in Memory"
+	return 0
+    }
+    
+    set rmax $thisparam($this,boneclass) 
+    set bonemap [ $this ExtractAndResliceLabelMap $rmax $rmax "bone" 0 ]
+    
+    set r [ [ [ [ $map GetImage ] GetPointData ] GetScalars ] GetRange ]
+    set rmax [ lindex $r 1 ]
+    set rmin [ lindex $r 0 ]
+    
+    set numjoints [ expr $rmax - $rmin ]
+    if { $numjoints < 1 } { 
+	::pxtclutil::Warning "Bad Label Image in Memory $rmin:$rmax"
+	return 0
+    }
+
+     $this ClickJoints "auto" 
+
+    
+
+    set points [ vtkPoints [ pxvtable::vnewobj ]]
+
+    set old  $thisparam($this,currentplane_autoupdate)
+    set thisparam($this,currentplane_autoupdate) 1
+
+    set interp [ $oblique_slice GetInterpolation ]
+    $oblique_slice SetInterpolation 0
+
+    
+    $points SetNumberOfPoints [ expr $numjoints * 3 ] 
+    $points SetPoint 0 100 100 100
+    $points SetPoint 1 101 100 100
+    $points SetPoint 2 100 101 100
+    set pointindex 3
+    
+    puts stderr "Creating Joints $numjoints"
+    
+    for { set i 1 } { $i < $numjoints } { incr i } {
+	set pts [ GetJoint $i $map $bonemap ]
+	
+	for { set j 0 } { $j <= 2 } { incr j } {
+	    $points SetPoint $pointindex [ lindex [ $pts GetPoint $j ] 0 ] [ lindex [ $pts GetPoint $j ] 1 ] [ lindex [ $pts GetPoint $j ] 2 ]
+	    incr pointindex
+	}
+	$pts Delete
+    }
+    
+    set p     [ $planes GetModelParameters ]
+    set hashindlimbs [ lindex $p 1 ]
+    set hasfeet      [ lindex $p 0 ]
+    
+    set pt(0) 0.0;
+    set pt(1) 0.0;
+    set pt(2) 0.0;
+    set nump 0.001
+    
+    
+    if { $hashindlimbs == 1 } {
+	set index1 3 
+	set index2 12
+	if { $hasfeet == 0 } {
+	    set index2 9
+	}
+	
+	set pt1 [ $points GetPoint 3 ]
+	set pt2 [ $points GetPoint 12 ]
+	
+	for { set j 0 } { $j <=2 } { incr j } {
+	    set pt($j) [ expr 0.5* ( [ lindex $pt1 $j ] + [ lindex $pt2 $j ] ) ]
+	}
+	
+    } else {
+	for { set j 1 } { $j < $numjoints } { incr j } {
+	    set pt [ $points GetPoint [ expr $i * 3 ] ]
+	    for { set j 0 } { $j <=2 } { incr j } {
+		set pt($j) [ expr $pt($j) + [ lindex $pt $j ] ]
+		incr nump
+	    }
+	    for { set j 0 } { $j <=2 } { incr j } {
+		set pt($j) [ expr $pt($j) / $nump ]
+	    }
+	}
+    }
+    
+    $points SetPoint 0 $pt(0) $pt(1) $pt(2)
+    $points SetPoint 1 [ expr $thisparam($this,axislength) + $pt(0)  ] $pt(1) $pt(2)
+    $points SetPoint 2 $pt(0) [ expr $pt(1) + $thisparam($this,axislength)  ] $pt(2)
+    	
+    set curve [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    $curve SetFromPoints $points
+
+    set landmarkcontrol [ $parent GetLandmarkControl ] 
+    [ $landmarkcontrol GetLandmarkControl ]  SetCollection $curve -1
+    $landmarkcontrol ShowWindow
+
+    $curve Delete
+
+    $oblique_slice SetInterpolation $interp
+    $points Delete
+
+    set thisparam($this,currentplane_autoupdate) $old
+
+    $parent SetResultsFromObject $bonemap $this
+    SelectPlane 0
+
+    itcl::delete object $bonemap
+
+    return 1
+
+}
+# -----------------------------------------------------------------------------------------
+
+itcl::body pxitclmousechopper::CreateSegmentedMapGUI { widget } {
+
+    set thisparam($this,dilateerode) 0
+    set thisparam($this,softtissuemin) 1
+    set thisparam($this,softtissuemax) 4
+    set thisparam($this,boneclass) 5
+
+    set bot [ frame $widget.f1 ]
+    set fr1 [ frame $widget.f2 ]
+    set fr2 [ frame $widget.f3 ]
+    pack  $bot $fr2 $fr1 -side bottom -expand false -fill x -pady 2
+
+    set mouse_label_gui [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+    ${mouse_label_gui} configure -description "Mouse VOI Map"
+    ${mouse_label_gui} Initialize $widget.top
+    pack forget [ ${mouse_label_gui} cget -browsebutton ]
+
+    ${mouse_label_gui} AddFunction "$this GrabSegmentationMapFromViewer" "Grab" "$this"
+    ${mouse_label_gui} AddFunction "$parent SetMaskFromObject" "Display Mask" "$this"
+    ${mouse_label_gui} AddFunction "$parent SetResultsFromObject" "Display" "$this"
+    $widget.top configure -background darkgray
+    pack $widget.top -side top -expand f -fill x -pady 3
+    
+    set cw [ [ iwidgets::labeledwidget $bot.1  -labeltext "Erosion/Dilation:"  ] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,dilateerode) ] -5 -3 0  3  5
+    pack $cw.optmenu  -expand f
+    
+    set k 0
+    eval "button $fr2.$k -text Update -command { $this UpdateLabelImageRanges }"
+    pack $fr2.$k -side right -expand f -fill x; incr k
+
+    iwidgets::entryfield $fr2.$k -labeltext "Muscle Min:"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,softtissuemin) ] -relief sunken 
+    pack $fr2.$k -side left -expand f -fill x; incr k
+    iwidgets::entryfield $fr2.$k -labeltext "Muscle Max:"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,softtissuemax) ] -relief sunken  
+    pack $fr2.$k -side left -expand f -fill x; incr k
+    iwidgets::entryfield $fr2.$k -labeltext "Bone Class:"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,boneclass) ] -relief sunken  
+    pack $fr2.$k -side left -expand f -fill x; incr k
+
+
+
+    eval "button $fr1.1 -text \"Show Segmentation Control\" -command { $this ShowSegmentationControl }"
+    pack $fr1.1 -side left -padx 10 -expand t -fill x
+
+    eval "button $bot.2 -text \"Bone VOI\"   -command { $this CreateBoneVOI } "
+    eval "button $bot.3 -text \"Soft Tissue VOI\"   -command { $this CreateSoftTissueVOI } "
+    pack $bot.3 $bot.2 -side right -padx 1 -expand f
+    pack $bot.1  -side left -padx 1 -expand t -fill x
+}
+# -----------------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::ShowSegmentationControl { } {
+
+    set segm [ $parent cget -brainstriptool ]
+    $segm ShowWindow "Histogram Segmentation"
+    
+}
+# -----------------------------------------------------------------------------------------
+itcl::body pxitclmousechopper::CreateOutputGUI { widget } {
+
+    set thisparam($this,distanceoffset) 1.5
+    set thisparam($this,axislength) 3.0
+    set thisparam($this,tpspoints)  150
+    set thisparam($this,tuberadius)     0.5
+    set thisparam($this,sphereradius)   1.0
+
+    set base  [ LabelFrame:create $widget.a -text "Joint Locations"]
+    pack  $widget.a -side top -expand false -fill x -pady 2
+    
+    set fr1 [ frame $base.1 ]
+    set fr2 [ frame $base.2 ]
+    pack $fr1 $fr2 -side top -expand f -fill x
+    
+    label $fr1.a -text "Joint Offset (voxels)"
+    tk_optionMenu $fr1.b [ itcl::scope thisparam($this,distanceoffset) ] "0.0"  "1.0" "1.5" "2.0" "3.0" "5.0" 
+    label $fr1.c -text "Axis Length"
+    tk_optionMenu $fr1.d [ itcl::scope thisparam($this,axislength) ]  "1.0" "1.5" "2.0" "3.0" "5.0" "10" "20.0"
+
+    pack $fr1.a $fr1.b $fr1.c $fr1.d  -side left -expand f -padx 0
+
+    eval "button $fr2.1 -text \"Click Joints\"   -command { $this ClickJoints manual } "
+    eval "button $fr2.2 -text \"Set All Joints\"   -command { $this AutoJoints  } "
+    pack $fr2.1 $fr2.2  -side left -expand f -fill x -padx 5
+
+
+    set base  [ LabelFrame:create $widget.b -text "Wireframe Model"]
+    pack  $widget.b -side top -expand false -fill x -pady 2
+    
+    
+    label $base.a -text "Tube Radius"
+    tk_optionMenu $base.b [ itcl::scope thisparam($this,tuberadius) ] "0.0" "0.25" "0.5" "0.75" "1.0" "2.0" 
+    label $base.c -text "Sphere Radius"
+    tk_optionMenu $base.d [ itcl::scope thisparam($this,sphereradius) ] "0.25" "0.5" "1.0" "1.5" "2.0" "3.0" "4.0"
+    eval "button $base.e -text \"Wire Model\"   -command { $this GenerateWireModel } "
+    pack $base.a $base.b $base.c $base.d $base.e -side left -expand f -fill x -padx 1
+
+    
+    set test 0
+    catch  {  set test [ vtkpxPolySimilarityTransform [ pxvtable::vnewobj ] ] }
+    if { [ string length $test ] > 2 } {
+	set f3  [ LabelFrame:create $widget.c -text "Transformation Model"]
+	pack  $widget.c -side top -expand false -fill x -pady 2
+	
+	label $f3.1 -text "TPS Points:"
+	tk_optionMenu $f3.2 [ itcl::scope thisparam($this,tpspoints) ] "75" "100" "125" "150" "200" "250"
+	eval "button $f3.3 -text \"Create Transformation\"   -command { $this GenerateTransformationModel } "
+	pack $f3.1 $f3.2 $f3.3 -side left -padx 5 -expand f -fill x
+    }
+
+}
+# -----------------------------------------------------------------------------------------
+
+itcl::body pxitclmousechopper::UpdateGUIFromPlanes { } { 
+
+    $planeslistbox  clear
+    set names [ $planes GetNames ]
+    set p     [ $planes GetModelParameters ]
+
+    for { set i 0 } { $i < [ llength $names ] } { incr i } {
+	$planeslistbox insert end [ lindex $names $i ]
+    }
+
+    $planeslistbox selection set   0 0
+
+
+
+    set thisparam($this,hasfeet) [ lindex $p 0 ]
+    set thisparam($this,hashindlimbs) [ lindex $p 1 ]
+    set thisparam($this,hasforelimbs) [ lindex $p 2 ]
+    set thisparam($this,hashead) [ lindex $p 3 ]
+    set thisparam($this,taildivisions) [ lindex $p 4 ]
+    set thisparam($this,spinedivisions) [ lindex $p 5 ]
+   
+
+    $this SelectPlane 
+} 
+
+itcl::body pxitclmousechopper::UpdatePlanesFromGUI { } { 
+
+    if { $thisparam($this,enable_updateplane) == 1 } {
+	set oldindex $thisparam($this,currentplaneindex)
+	
+	if { $oldindex != -1 } {
+	    set parray [ $planes GetPlanes ]
+	    $parray SetComponent $oldindex 7 $thisparam($this,currentplane_above) 
+	}
+    }
+
+}
+    
+
+itcl::body pxitclmousechopper::SelectPlane { { value -1 } { direction 0 } } { 
+
+    set maxindex [ llength [ $planes GetNames ] ]
+
+    if { $value == - 1 } {
+	set index [ $planeslistbox curselection ]
+    } else {
+	set index $value
+	$planeslistbox selection clear 0 end 
+	$planeslistbox selection set $index
+    }
+
+    set newindex $index
+
+    if { $direction == -1 && $index > 0 } {
+	set newindex [ expr $index -1 ]
+    } elseif { $direction == 1 && $index < [ expr $maxindex - 1 ] } {
+	set newindex [ expr $index +1 ]
+    } else { 
+	set newindex $index
+    }
+    
+    
+    UpdatePlanesFromGUI
+    
+    if { $newindex != $index } {
+	$planeslistbox selection clear 0 end
+	$planeslistbox selection set $newindex
+	set index $newindex
+    }
+    
+    
+    set parray [ $planes GetPlanes ]
+    set thisparam($this,currentplane_n)  [ list [ $parray GetComponent $index 0 ]  [ $parray GetComponent $index 1 ]  [ $parray GetComponent $index 2 ]  ]
+    set thisparam($this,currentplane_dist)  [ $parray GetComponent $index 3 ] 
+    set thisparam($this,currentplane_c)  [ list [ $parray GetComponent $index 4 ]  [ $parray GetComponent $index 5 ]  [ $parray GetComponent $index 6 ]  ]
+
+    set thisparam($this,currentplane_above) [ expr [ $parray GetComponent $index 7 ] > 0 ]
+    set thisparam($this,currentplane) 	[ $planeslistbox getcurselection ]
+    set thisparam($this,currentplaneindex) $index
+
+    if { $thisparam($this,currentplane_autoupdate) > 0 } {
+
+	if { [ $this GetObliqueSlice  ] == 0 } { return }
+	$oblique_slice UpdateImagePlane [ $parray GetComponent $index 3 ] [ $parray GetComponent $index 0 ]  [ $parray GetComponent $index 1 ]  [ $parray GetComponent $index 2 ] 
+	$oblique_gui    UpdateScales
+	$this UpdateArrowColor
+	   
+    }
+}
+
+itcl::body pxitclmousechopper::UpdateArrowColor { } {  
+
+    if { $thisparam($this,currentplane_autoupdate) > 0 } {
+	if { [ $this GetObliqueSlice  ] == 0 } {  return }
+	$oblique_slice SetNormalArrowColor $thisparam($this,currentplane_above) 
+	$oblique_slice SetShowNormalArrow [ $oblique_slice GetShowNormalArrow ]
+	[ $parent GetViewer ]     UpdateDisplay
+    }
+}
+
+itcl::body pxitclmousechopper::TestPlane { mode } { 
+    
+    set d [ [ $parent cget -currentimage ] GetImageSize ]
+    if { $d < 2 } { 
+	return
+    }
+
+    if { [ $this GetObliqueSlice  ] == 0 } { return }
+    
+
+    if { $mode == 0 } {
+
+	set img [ $oblique_slice GetMaskImage [ [ $parent cget -currentimage ] GetImage ] $thisparam($this,currentplane_above) 0 ]
+	set image [ [ pxitclimage \#auto ] GetThisPointer ]
+	$image ShallowCopyImage $img; $img Delete
+	$image CopyImageHeader [ [ $parent cget -currentimage ] GetImageHeader ]
+	$image configure -filename "test_oblique"
+	$parent SetResultsFromObject $image $this
+	itcl::delete object $image
+	return
+    }
+
+    if { $mode == 1 } {
+
+	set test [ string first "Foot" $thisparam($this,currentplane) ]
+	if { $test != -1 } {
+	    ::pxtclutil::Warning "This operation does not apply to a foot plane"
+	    return 
+	}
+
+	set img2 [ $oblique_slice GetMaskImage [ [ $parent cget -currentimage ] GetImage ] $thisparam($this,currentplane_above) 0 ]
+	SelectPlane -1 1
+	set img [ $oblique_slice GetMaskImage  $img2 $thisparam($this,currentplane_above) 0 ]
+	SelectPlane -1 -1
+	$img2 Delete
+
+	set image [ [ pxitclimage \#auto ] GetThisPointer ]
+	$image ShallowCopyImage $img; $img Delete
+	$image CopyImageHeader [ [ $parent cget -currentimage ] GetImageHeader ]
+	$image configure -filename "test_oblique"
+	$parent SetResultsFromObject $image $this
+	itcl::delete object $image
+	return
+    }
+   
+    set test [ string first "Horizontal" $thisparam($this,currentplane) ]
+    if { $test == -1 } {
+	::pxtclutil::Warning "Please select a 'horizontal' plane before using TestPlane pair. This option is meant to be used to create a VOI based on one of the limbs. Select a 'first' hipp or shoulder plane first and try again."
+	return 
+    }
+
+    set ind $thisparam($this,currentplaneindex)
+    set indp [ expr $ind +1 ]
+
+    set sim [ vtkpxTransformationUtil [ pxvtable::vnewobj ]]
+    set img1 [ $sim GetMaskImage [ [ $parent cget -currentimage ]  GetImage ] [ $planes GetPlanes ] $ind ]
+    set img2 [ $sim GetMaskImage $img1 [ $planes GetPlanes ] $indp ]
+    $img1 Delete
+
+    set param [ $planes GetModelParameters ] 
+    set hasfeet [ lindex $param 0 ]
+    if { $mode == 3 && $hasfeet == 1 } {
+	set img3 $img2
+	set indf [ expr $ind +3 ]
+	set img2 [ $sim GetMaskImage $img3 [ $planes GetPlanes ] $indf 1 ]
+	$img3 Delete
+    }
+
+    $sim Delete
+   
+    set image [ [ pxitclimage \#auto ] GetThisPointer ]
+    $image ShallowCopyImage $img2; $img2 Delete
+    $image CopyImageHeader [ [ $parent cget -currentimage ] GetImageHeader ]
+    $image configure -filename "test_leg"
+    $parent SetResultsFromObject $image $this
+    itcl::delete object $image
+    return
+}
+	       
+
+itcl::body pxitclmousechopper::UpdatePlane { } { 
+
+    if { $thisparam($this,enable_updateplane) == 1 } {
+
+	if { [ $this GetObliqueSlice  ] == 0 } { return }
+
+	set thisparam($this,currentplane_n)    [  $oblique_slice GetNormal ]
+	set thisparam($this,currentplane_c)    [ $oblique_slice GetCenter ]
+	set thisparam($this,currentplane_dist) [ $oblique_slice GetDistance ]
+	
+	set index $thisparam($this,currentplaneindex) 
+	set parray [ $planes GetPlanes ]
+	for { set i 0 } { $i <= 2 } { incr i } {
+	    $parray SetComponent $index $i [ lindex $thisparam($this,currentplane_n) $i ]
+	    $parray SetComponent $index [ expr 4+ $i ] [ lindex $thisparam($this,currentplane_c) $i ]
+	}
+	$parray SetComponent $index 3 $thisparam($this,currentplane_dist)
+    } 
+
+}
+    
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    
+    source [ file join [ file dirname [ info script ] ] pxitclmousesegment.tcl ]
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclmouseregister.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclmouseregister.tcl
new file mode 100755
index 0000000..d51632f
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclmouseregister.tcl
@@ -0,0 +1,598 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclmouseregister.tcl,v 1.3 2003/02/26 16:29:58 papad Exp $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package provide pxitclmouseregister 1.0
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+
+package require labelframe 1.0
+package require pxtclutil 1.0
+package require pxvtable 1.0
+package require vtkpxcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+package require pxitclbasecontrol 1.0
+package require pxitclrpm 1.0
+package require pxitclmousechopper 1.0
+package require bis_guioverlayutility 1.0
+# -----------------------------------------------------
+#  Intialize Variables
+# -----------------------------------------------------
+
+itcl::class pxitclmouseregister {
+
+    inherit pxitclbasecontrol
+
+    protected variable pref_dialog 0
+    protected variable orthoviewer
+    protected variable simpleviewer 0
+    protected variable viewername
+    protected variable longviewername 
+    protected variable initialized 0
+    protected variable standalone 1
+    public    variable overlaytool 0
+
+    public    variable rpmtool 0
+    public    variable enable_rpmtool 1
+    public    variable enable_rendering_on_startup 1
+    public    variable enable_simpleviewer 1
+    public    variable ttable 0
+    public    variable menubase 0
+    private   common thisparam
+
+    constructor { par } {
+	pxitclbasecontrol::constructor $par
+    } {
+	InitializeMouseRegister
+    }
+
+    protected method InitializeMouseRegister { }
+    public method LoadImage { f transflag } 
+
+    public method HandleNewImage { viewer } 
+    public method HandleMouseEvent { viewer args } 
+    public method TransferImage { from_viewer args  } 
+    public method CreateMenu { menubase } 
+    public method PositionWindows {  } 
+    public method Initialize { basewidget } 
+    public method GetOrthoViewer { name } { return $orthoviewer($name) }
+    public method ShowTTable { }
+    public method ComputeTValue { mode }
+    public method GrabTvalueFromViewer { viewerno }
+
+}
+# -----------------------------------------------------    
+itcl::body pxitclmouseregister::InitializeMouseRegister { } {
+
+    global pxtcl_pref_array
+    
+    # -----------------------------
+    # Global Vtk Objects
+    # -----------------------------
+
+    set pref_dialog       [ ::pxtcluserprefs::CreatePreferenceEditor ]
+    set viewername(0)     "ref"
+    set viewername(1)     "trn"
+    set longviewername(0) "Reference"
+    set longviewername(1) "Transform"
+    set orthoviewer(ref) 0
+    set orthoviewer(trn) 0
+    set overlaytool 0
+
+    set ttable  0
+    set thisparam($this,ttable_mathobject)  0
+    set thisparam($this,ttable_tvalue)  1.323
+    set thisparam($this,ttable_df)         21
+    set thisparam($this,ttable_x1000)        0
+    set thisparam($this,ttable_pv1)      0.10
+    set thisparam($this,ttable_pv2)      0.20
+    set appname "BioImage Suite::MouseRegister"
+    set enable_vvlink 0
+
+}
+# ---------------------------------------------------------------------------------
+#   I/O Functions
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclmouseregister::LoadImage { f transflag } {
+    
+    $orthoviewer($transflag) LoadImage $f 
+}
+
+# ---------------------------------------------------------------------------------
+# Handle Mouse Press Callback
+# ---------------------------------------------------------------------------------
+itcl::body pxitclmouseregister::HandleNewImage { viewer } {
+
+    set img [ $viewer cget -currentimage ]
+    set fname [ $img cget -filename ]
+    set or    [ $img GetOrientation ]
+
+    if { $viewer == $orthoviewer(trn) } {
+	set thisname  "trn"
+	$overlaytool SetFunctionalImage $img 
+    } else {
+	$overlaytool SetImage $img 
+    }
+}
+
+itcl::body pxitclmouseregister::HandleMouseEvent { viewer args } {
+
+    # Assume it is the reference viewer
+    set thisname "ref"
+    set othername "trn"
+
+    # Check whether widgetname matches transform viewer
+    if { $viewer == $orthoviewer(trn) } {
+	set thisname  "trn"
+	set othername "ref"
+    }
+
+    # Label Viewers etc
+    set thisviewer   [ $orthoviewer($thisname)  GetViewer ]
+    set otherviewer  [ $orthoviewer($othername) GetViewer ]
+
+    set lv "" 
+    catch { set lv [ $thisviewer GetLastClickedPoint ] }
+
+    if { [ llength $lv ] > 1 } {
+	if { [ lindex $lv 0 ] > -1 } {
+	    # PolyData Control needs scaled points
+	    set lv [ $thisviewer GetLastClickedPointScaled ] 
+	    set px [ lindex $lv 0 ]
+	    set py [ lindex $lv 1 ]
+	    set pz [ lindex $lv 2 ]
+	    set upd0 [ $thisviewer GetMouseSliceChangeMode ]
+	    set upd1 [ $otherviewer GetMouseSliceChangeMode ]
+	    if { $upd0 == 1 && $upd1 == 1 } {
+		$otherviewer SetScaledCoordinates $px $py $pz
+	    } 
+	}
+    }
+}
+
+
+itcl::body pxitclmouseregister::TransferImage { from_viewer args  } {
+
+    if { $from_viewer == "help" } {
+	tk_messageBox -title "About Transfer Images" -type ok -message "The image transfered is the one currently displayed.\n It is stored as `image' on the target viewer"
+    }
+
+    if { $from_viewer == "swap" } {
+	set tmpimage       [  [ pxitclimage \#auto ] GetThisPointer ]
+	$tmpimage ShallowCopy [ $orthoviewer(ref) GetDisplayedImage ]
+	$orthoviewer(ref) SetImageFromObject [ $orthoviewer(trn) GetDisplayedImage ] $this
+	$orthoviewer(trn) SetImageFromObject $tmpimage $this
+	itcl::delete object $tmpimage
+	return
+    }
+	
+    if { [ llength $args ] == 0 } {
+	if { $from_viewer == "trn" || $from_viewer == "ref" } {
+	    $simpleviewer SetImageFromObject [ $orthoviewer($from_viewer) GetDisplayedImage ] $this
+	    $simpleviewer SetLookupTable [ [ $orthoviewer($from_viewer) GetViewer  ] GetLookupTable ]
+	    [ $simpleviewer GetViewer ] UpdateDisplay
+	}
+    } else {
+	set to_viewer [ lindex $args 0 ]
+	if { ( $from_viewer == "trn" || $from_viewer == "ref" ) &&
+	     ( $to_viewer == "trn" || $to_viewer == "ref" ) && 
+	     ( $from_viewer != $to_viewer) } {
+	    $orthoviewer($to_viewer) SetImageFromObject [ $orthoviewer($from_viewer) GetDisplayedImage ] $this
+	    $orthoviewer($to_viewer) SetLookupTable [ [ $orthoviewer($from_viewer) GetViewer  ] GetLookupTable ]
+	    [ $orthoviewer($to_viewer) GetViewer ] UpdateDisplay
+	}
+    }
+}
+
+# ---------------------------------------------------------------------------------
+# Create Menu
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclmouseregister::CreateMenu { menubase } {
+
+    
+    set viewm [ menu $menubase.view -tearoff 0 ];     $menubase add cascade -underline 0 -label "Viewers" -menu $viewm
+    set trm   [ menu $menubase.tr   -tearoff 0 ];     $menubase add cascade -underline 0 -label "Transfer" -menu $trm
+
+
+    if { $overlaytool !=0 } {
+	set regm [ menu $menubase.regm -tearoff 0 ] ; $menubase add cascade -underline 0 -label "Registration"    -menu $regm ;
+	$overlaytool AddToMenuButton $regm
+	
+	if {  $rpmtool !=0 } {
+	    $regm add separator
+	    eval "$regm add command -label \"Point-Based Registration\" -command { $orthoviewer(ref) HideWindow; $orthoviewer(trn) HideWindow ; $rpmtool ShowWindow }"
+	}
+    }
+    
+
+
+    eval "$trm add command  -label \"Help with Transfer Features\"  -command { $this TransferImage help help } "
+    $trm add separator
+    eval "$trm add command  -label \"Displayed Image Reference->Transform\"  -command { $this TransferImage ref trn } "
+    eval "$trm add command  -label \"Displayed Image Transform->Reference\"  -command { $this TransferImage trn ref } "
+    $trm add separator
+    eval "$trm add command  -label \"Swap Displayed Transform->Reference\"  -command  { $this TransferImage  swap } "
+
+
+    eval "$viewm add command -label \"Reference Viewer\" -command { $orthoviewer(ref) ShowWindow; $this PositionWindows}"
+    eval "$viewm add command -label \"Transform Viewer\" -command { $orthoviewer(trn) ShowWindow ; $this PositionWindows}"
+    
+    if { $enable_simpleviewer == 1 } {
+	$viewm add separator
+	eval "$viewm add command -label \"Simple Viewer\" -command { $simpleviewer ShowWindow }"
+
+	set mbar [ $simpleviewer cget -menubase ]
+	$mbar delete 0 1
+	set mb [ menu $mbar.dispm -tearoff 0 ]; $mbar add cascade -underline 0 -label Display -menu $mb
+
+	eval "$mb add command  -label \"Grab Image From Reference Viewer\"  -command { $this TransferImage ref } "
+	eval "$mb add command  -label \"Grab Image From Transform Viewer\"  -command { $this TransferImage trn } "
+	$mb add separator
+	eval "$mb add command -label Close -command {  $simpleviewer HideWindow } -underline 1"
+    }
+
+    $viewm add separator
+    if { $enable_simpleviewer == 1 } {
+	eval "$viewm add command -label \"Close Viewers\" -command { $orthoviewer(ref) HideWindow; $orthoviewer(trn) HideWindow ; $simpleviewer HideWindow }"
+    } else {
+	eval "$viewm add command -label \"Close Viewers\" -command { $orthoviewer(ref) HideWindow; $orthoviewer(trn) HideWindow  }"
+    }
+
+    $viewm add separator
+    if { $standalone == 1 } {
+	$viewm add command -label Exit -command {  pxtkcallback 0 0 } -underline 1
+    } else {
+	eval "$viewm add command -label Close -command { wm deiconify $basewidget }"
+    }
+
+    set helpm [ menu $menubase.help -tearoff 0 ];     $menubase add cascade -underline 0 -label "Help" -menu $helpm
+
+
+    eval "$helpm add command -label Preferences -command { wm deiconify $pref_dialog }"
+    $helpm add separator
+    eval "$helpm add command -label \"T-distribution table\" -command {  $this ShowTTable }"
+    $helpm add separator
+    $helpm add command -label "Console" -command {  pxtkconsole }
+
+    eval "$helpm add command -label About -command { $this AboutCommand }"
+
+}
+
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclmouseregister::PositionWindows {  } {
+    
+    set geom [ winfo geometry $basewidget ] 
+    scan $geom "%dx%d+%d+%d" w0 h0 x0 y0
+
+
+    set ref [ $orthoviewer(ref) GetBaseWidget ]
+    set trn [ $orthoviewer(trn) GetBaseWidget ]
+
+    set mult 0
+    set ok 0
+    if { $overlaytool != 0 } {
+	set mult [ $overlaytool GetBaseWidget ]
+	catch { set ok   [ winfo ismapped $mult ] }
+    } else {
+	set ok 0
+    }
+
+    if { $ok == 0 } {
+	set y0 [ expr $y0 + $h0 + 25 ]
+	set y1 $y0 
+	set x1 [ expr $x0 + 550 ]
+	set hgt 550
+    } else {
+	set y0 [ expr $y0 + $h0 + 15 ]
+	set x1 $x0
+	set y1 [ expr $y0 + 450 ]
+	set x2 [ expr $x0 + 580 ]
+	set y2 $y0
+	set hgt 450
+    }
+
+    if  { [ winfo ismapped $ref ] } {
+	wm geometry $ref "550x${hgt}+$x0+$y0"
+	raise $ref
+	if  { [ winfo ismapped $trn ] } {
+	    wm geometry $trn "550x${hgt}+$x1+$y1"
+	    raise $trn
+	}
+    } else {
+	if  { [ winfo ismapped $trn ] } {
+	    wm geometry $trn "550x${hgt}+$x0+$y0"
+	    raise $trn
+	}
+    }
+
+    if { $ok == 1 } {
+	wm geometry $mult "+$x2+$y2"
+	raise $mult
+    }
+	
+}
+
+
+itcl::body pxitclmouseregister::ShowTTable { } {
+
+    if { $ttable == 0 } {
+
+	set ttable [ toplevel $basewidget.[pxvtable::vnewobj ]]
+
+	wm geometry $ttable 400x100
+	wm title $ttable "Critical Points of the T-distribution"
+	eval "wm protocol $ttable WM_DELETE_WINDOW { wm withdraw $ttable }"
+
+	frame $ttable.top
+	frame $ttable.top2
+	frame $ttable.bot
+	pack $ttable.top $ttable.top2 $ttable.bot -side top -expand false -fill x -pady 2
+
+	iwidgets::entryfield $ttable.top.1 -labeltext "T-value:"  -width 6 -validate real -textvariable [ itcl::scope thisparam($this,ttable_tvalue) ] -relief sunken 
+	checkbutton   $ttable.top.15  -text "x1000"  -variable [ itcl::scope thisparam($this,ttable_x1000) ]
+	iwidgets::entryfield $ttable.top.2 -labeltext "Degr. of Fredom:"  -width 3 -validate integer -textvariable [ itcl::scope thisparam($this,ttable_df) ] -relief sunken 
+
+
+	iwidgets::entryfield $ttable.top2.3 -labeltext "One Tail:"  -width 6 -validate real -textvariable [ itcl::scope thisparam($this,ttable_pv1) ] -relief raised 
+	iwidgets::entryfield $ttable.top2.4 -labeltext "Two Tail:"  -width 6 -validate real -textvariable [ itcl::scope thisparam($this,ttable_pv2) ] -relief sunken
+
+	pack $ttable.top.1 $ttable.top.15 $ttable.top.2  -side left -expand true -fill x
+	pack $ttable.top2.3 $ttable.top2.4  -side left -expand true -fill x
+
+
+	eval "button $ttable.bot.1 -text  \"T-> P\" -command { $this ComputeTValue forward }"
+	eval "button $ttable.bot.15 -text \"P(2t) -> T\" -command { $this ComputeTValue  reverse }"
+	eval "button $ttable.bot.2 -text \"Grab Ref\" -command { $this GrabTvalueFromViewer ref }"
+	eval "button $ttable.bot.3 -text \"Grab Trn\" -command { $this GrabTvalueFromViewer trn }"
+	eval "button $ttable.bot.4 -text \"Close\"   -command { wm withdraw $ttable }"
+
+	pack $ttable.bot.4 -side right -padx 3
+	pack $ttable.bot.1 $ttable.bot.15 $ttable.bot.2 $ttable.bot.3 -side left -padx 1
+
+
+	set thisparam($this,ttable_mathobject) [ vtkpxMath [ pxvtable::vnewobj ]]
+    }
+
+    wm deiconify $ttable
+}
+
+itcl::body pxitclmouseregister::GrabTvalueFromViewer { viewername } {
+
+    set thisviewer [  $orthoviewer($viewername) GetViewer ]
+    set lv [ $thisviewer GetLastClickedPoint ] 
+    set fr [ $thisviewer GetCurrentFrame ] 
+    set px [ lindex $lv 0 ]
+    set py [ lindex $lv 1 ]
+    set pz [ lindex $lv 2 ]
+    set img [ $thisviewer GetImage ] 
+
+    if { $img != "" } {
+	set thisparam($this,ttable_tvalue) [ $img GetScalarComponentAsDouble $px $py $pz $fr ]
+	set thisparam($this,ttable_x1000)  1
+	ComputeTValue forward
+    }
+}
+
+itcl::body pxitclmouseregister::ComputeTValue { mode } {
+
+    if { $mode == "forward" } {
+	if { $thisparam($this,ttable_x1000) == 1 } {
+	    set x [ expr 0.001 * $thisparam($this,ttable_tvalue) ]
+	} else {
+	    set x  $thisparam($this,ttable_tvalue) 
+	}
+	
+	set thisparam($this,ttable_pv2) [ $thisparam($this,ttable_mathobject) TtestToPvalue $x $thisparam($this,ttable_df) ]
+	set thisparam($this,ttable_pv1) [ expr $thisparam($this,ttable_pv2) * 0.5 ]
+    } else {
+	set x $thisparam($this,ttable_pv2)
+	set thisparam($this,ttable_pv1) [ expr $thisparam($this,ttable_pv2) * 0.5 ]
+	
+	set t [ $thisparam($this,ttable_mathobject) PvalueToTvalue $x $thisparam($this,ttable_df) ]
+	if { $thisparam($this,ttable_x1000) == 1 } {
+	    set t [ expr $t * 1000.0 ]
+	}
+	set thisparam($this,ttable_tvalue) $t
+    }
+   
+
+    update idletasks
+}
+
+
+
+
+# ---------------
+# User Interface 
+# ---------------
+
+itcl::body pxitclmouseregister::Initialize { basewidg } {
+
+    if { $initialized == 1 } { return $basewidget }
+
+    set basewidget [ toplevel $basewidg ]; 
+    wm geometry $basewidg 700x40+10+10
+
+    
+    
+    SetTitle "BioImage Suite::Mouse Register"
+    set standalone 1
+
+
+    set menubase [ menu $basewidget.pxtclbrainreg  ]
+    $basewidget configure -menu $menubase
+    set pbar     [ frame $basewidget.status -width 400 -height 30 ]
+    pack  $pbar -side top -fill x 
+ 
+    CreateProgressBar  $pbar
+
+    set orthoviewer(ref) [ [ pxitclbaseimageviewer \#auto 0 ]  GetThisPointer ]
+    $orthoviewer(ref) configure -enable_overlaytool 0 
+    $orthoviewer(ref) configure -appname "Reference Viewer"
+    $orthoviewer(ref) configure -show_standard_images 2
+    $orthoviewer(ref) configure -enable_talaraichoption 0
+    $orthoviewer(ref) configure -enable_vvlinkgadget 0
+    $orthoviewer(ref) configure -enable_brainstriptool 2
+    $orthoviewer(ref) configure -enable_expfittool 1
+    $orthoviewer(ref) configure -enable_landmarkcontrol  1
+    $orthoviewer(ref) configure -enable_rendering_on_startup  $enable_rendering_on_startup  
+    $orthoviewer(ref) InitializeObjectmapViewer $basewidget.[pxvtable::vnewobj] 0
+    [ $orthoviewer(ref) GetViewer ] SetEnableRendering 0
+
+    eval "$orthoviewer(ref) configure -mousecallback \"$this HandleMouseEvent \""
+    #eval "$orthoviewer(ref) configure -setnewimagecallback \"$this HandleNewImage\""
+    $orthoviewer(ref) ShowWindow
+
+    set orthoviewer(trn) [ [ pxitclbaseimageviewer \#auto 0 ]  GetThisPointer ]
+    $orthoviewer(trn) configure -show_standard_images 2
+    $orthoviewer(trn) configure -enable_overlaytool 0
+    $orthoviewer(trn) configure -enable_brainstriptool 2
+    $orthoviewer(trn) configure -appname "Transform Viewer"
+    $orthoviewer(trn) configure -enable_talaraichoption 0
+    $orthoviewer(trn) configure -enable_expfittool 1
+    $orthoviewer(trn) configure -enable_vvlinkgadget 0
+    $orthoviewer(trn) configure -enable_landmarkcontrol  1
+    $orthoviewer(trn) configure -enable_rendering_on_startup  $enable_rendering_on_startup  
+    $orthoviewer(trn) InitializeObjectmapViewer .[pxvtable::vnewobj] 0
+    [ $orthoviewer(trn) GetViewer ] SetEnableRendering 0
+    eval "$orthoviewer(trn) configure -mousecallback \"$this HandleMouseEvent \""
+    $orthoviewer(trn) ShowWindow
+
+    set chopper [ [ pxitclmousechopper \#auto $orthoviewer(ref) ] GetThisPointer ]
+    $chopper configure -appname "Reference Virtual Mouse Butcher"
+    $chopper AttachToBaseControl $orthoviewer(ref)
+
+
+    set chopper2 [ [ pxitclmousechopper \#auto $orthoviewer(trn) ] GetThisPointer ]
+    $chopper2 configure -appname "Transform Virtual Mouse Butcher"
+    $chopper2 AttachToBaseControl $orthoviewer(trn)
+
+
+
+    if { $enable_simpleviewer == 1 } {
+	set simpleviewer [ [ pxitclbaseimageviewer \#auto 0 ] GetThisPointer ]
+	$simpleviewer configure -appname "Simple Viewer"
+	$simpleviewer configure -show_standard_images 0
+	$simpleviewer configure -enable_multisubjectcontrol 0
+	$simpleviewer configure -enable_csigadget 0
+	$simpleviewer configure -enable_rendering_on_startup  0
+	$simpleviewer configure -enable_headercontrol  0
+	$simpleviewer configure -enable_importcontrol  0
+	$simpleviewer configure -enable_imageutility  0
+	$simpleviewer configure -enable_landmarkcontrol  0
+	$simpleviewer configure -enable_overlaytool  0
+	$simpleviewer configure -enable_histcontrol  0
+	$simpleviewer configure -enable_displaymenu  0
+	$simpleviewer configure -enable_brainstriptool  0
+	$simpleviewer configure -enable_helpmenu  0
+	$simpleviewer configure -enable_talaraichoption 0
+	$simpleviewer InitializeMosaicViewer .[pxvtable::vnewobj ] 0
+    }
+
+    set overlaytool [ [ bis_guioverlayutility \#auto ] GetThisPointer ]
+    $overlaytool SetSecondContainerObject $orthoviewer(ref)
+    $overlaytool InitializeFromContainer $orthoviewer(trn)
+    $overlaytool CreateGUI $basewidget.[pxvtable::vnewobj ]
+    $orthoviewer(ref) AddControl $overlaytool
+    $orthoviewer(trn) AddControl $overlaytool
+
+    [ $orthoviewer(ref) GetLandmarkControl ] SetTitle "Reference Landmarks"
+    [ $orthoviewer(ref) GetPolyDataControl ] SetTitle "Reference Surfaces"
+    [ $orthoviewer(trn) GetLandmarkControl ] SetTitle "Transform Landmarks"
+    [ $orthoviewer(trn) GetPolyDataControl ] SetTitle "Transform Surfaces"
+
+
+    if { $enable_rpmtool  == 1 } {
+	set rpmtool [ [ pxitclrpm \#auto $this [ $orthoviewer(ref) GetPolyDataControl ] [ $orthoviewer(trn) GetPolyDataControl ] $overlaytool [ $orthoviewer(trn) GetLandmarkControl ] ]  GetThisPointer ] 
+	$rpmtool configure -enablearticulated 1
+	$rpmtool Initialize $basewidget.[pxvtable::vnewobj ]
+    }
+
+    CreateMenu   $menubase
+
+    update idletasks
+    PositionWindows
+    set initialized 1
+
+    eval "bind all <Control-d>  { pxtkexit }"
+    wm protocol . WM_DELETE_WINDOW pxtkexit 
+
+    return $basewidget
+
+}
+
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    wm withdraw .
+    set breg [ pxitclmouseregister \#auto 0 ]
+    $breg configure -enable_rendering_on_startup  0
+    $breg Initialize .[pxvtable::vnewobj ]
+    
+    set argc [llength $argv]; set ok 0
+    if { $argc > 0 } {  set ok [ $breg LoadImage [lindex $argv 0]  "ref" ] }
+    if { $argc > 1 } {  set ok [ $breg LoadImage [lindex $argv 1]  "trn" ] }
+    if { $argc > 2 } {  
+	[ $breg cget -overlaytool ] LoadAndAddTransformation [ lindex $argv 2 ]
+    } 
+    if { $argc > 3 } {
+	set ok [ [ [ $breg GetOrthoViewer ref ] GetPolyDataControl ] LoadSurface [lindex $argv 3] ]
+    }
+    if { $argc > 4 } {
+	set ok [ [ [ $breg GetOrthoViewer trn ] GetPolyDataControl ] LoadSurface [lindex $argv 4] ]
+    }
+
+
+    [ [ $breg GetOrthoViewer ref ] GetViewer ] SetEnableRendering 1
+    [ [ $breg GetOrthoViewer trn ] GetViewer ] SetEnableRendering 1
+    [ [ $breg GetOrthoViewer trn ] GetViewer ] UpdateDisplay
+    [ [ $breg GetOrthoViewer ref ] GetViewer ] UpdateDisplay
+
+
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclmousesegment.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclmousesegment.tcl
new file mode 100755
index 0000000..60c931d
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclmousesegment.tcl
@@ -0,0 +1,78 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclbrainsegment.tcl,v 1.2 2004/12/16 16:10:43 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+package require vtkpxcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+package require pxitclmousechopper 1.0
+wm withdraw .
+
+set breg [ pxitclbaseimageviewer \#auto 0 ]
+$breg configure -appname "BioImage Suite::Mouse Segment"
+$breg configure -show_standard_images 2
+$breg configure -enable_brainstriptool 2
+$breg configure -enable_expfittool 1
+$breg configure -enable_multisubjectcontrol 0
+$breg configure -enable_overlaytool 0
+$breg configure -enable_vvlinkgadget  0
+$breg configure -enable_talaraichoption 0
+$breg configure -enable_rendering_on_startup  0
+
+$breg InitializeObjectmapViewer .[pxvtable::vnewobj ] 1
+
+
+set argc [llength $argv]
+
+if { $argc > 0 } {   $breg LoadImage [lindex $argv 0]   }
+
+update idletasks
+[ $breg GetViewer ] SetEnableRendering 1
+
+$breg ShowWindow
+
+set chopper [ [ pxitclmousechopper \#auto $breg ] GetThisPointer ]
+$chopper AttachToBaseControl $breg
+
+if { $argc > 1 } {   $chopper LoadModel [lindex $argv  1 ]   }
+if { $argc > 2 } {   $chopper LoadMouseMap [lindex $argv  2 ]   }
+if { $argc > 3 } {   $chopper LoadSegmentedMap [lindex $argv  3 ]   }
+
+#$chopper ShowWindow
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclmultisubjectaverage.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclmultisubjectaverage.tcl
new file mode 100755
index 0000000..ddf49fb
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclmultisubjectaverage.tcl
@@ -0,0 +1,3263 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+package provide pxitclmultisubjectaverage 1.0
+
+# 	$Id: pxitclmultisubjectaverage.tcl,v 1.1 2003/07/29 14:27:36 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] bis_algorithm ]
+
+
+package require  vtkpxcontrib 1.1
+package require  labelframe   1.0
+package require  pxtclutil    1.0
+package require  pxvtable     1.0
+package require  pxtclhelp    1.0
+package require  Itcl         3.2
+package require  Iwidgets     4.0
+package require  pxitclimage            1.0
+package require  pxitcltransform        1.0
+package require  pxitclsubjectentry     1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  bis_createoverlayimage 1.0
+package require  bis_roimean            1.0
+package require  pxtcluserprefs         1.0
+package require  pxitclbaseimageviewer  1.0
+package require  pxitcllistselector  1.0
+# ----------------------------------------------------------------------------------------------
+
+itcl::class pxitclmultisubjectaverage {
+
+    inherit pxitclbaseimagecontrol
+
+    # Generic Stuff 
+    private   common   thisparam        
+    protected variable numberofstudies 0
+    protected variable numberoftasks   0
+    protected variable setupfilename   "multisubject.msb"
+    protected variable second_viewer   0
+    protected variable external_overlayutility 0
+
+    # Subject Specific
+    protected variable reference_control    0
+    protected variable voi_control    0
+    protected variable anat_control    0
+    protected variable conv_control    0
+    protected variable func_control    0
+    protected variable epi_control    0
+    protected variable field_control    0
+    protected variable task_control    0
+    protected variable refx_control    0
+    protected variable intx_control    0
+    protected variable distx_control    0
+
+    protected variable subject_tree    0
+    protected variable current_subject ""
+    protected variable subjects        0    
+    protected variable last_subject    -1
+    protected variable last_added_subject 0
+
+
+    # Task Specific
+    protected variable task_tree    0
+    protected variable current_task ""
+    protected variable tasks        0    
+    protected variable last_task    -1
+    protected variable last_added_task 0
+    protected variable task_listbox 0
+
+
+    # Output Stuff
+    protected variable output_control  0 
+    protected variable output_listbox     0
+    protected variable output_listbox_lastselected  0
+    protected variable output_list [ list "Average Anatomical" "Std Anatomical" "Average Functional" "Std Functional" "Tscore Functional" ]
+
+    protected variable overlaycreator     0
+    protected variable outputimages 
+    
+    # Batch Mode Stuff
+
+    public variable batch_selector 0
+
+
+
+
+    constructor { par args } {
+	pxitclbaseimagecontrol::constructor $par 
+    } {
+	if { [ llength $args] > 0  } {
+	    set second_viewer [ lindex $args 0 ]
+	}
+	if { [ llength $args] > 1 } {
+	    set external_overlayutility [ lindex $args 1 ]
+	}
+	InitializeMultiSubject
+	set overlaycreator [ [ bis_createoverlayimage \#auto ] GetThisPointer ]
+	$overlaycreator InitializeFromContainer $this
+	$overlaycreator SetGUIMode managed
+
+	if { $second_viewer !=0 } {
+	    set thisparam($this,overlayviewer) "Transform"
+	}
+	
+    }
+
+    private method InitializeMultiSubject { } 
+    public method Initialize { widget }
+    public method DelayedInitialize { }
+
+    public method ReorganizeData {  }
+    public method SaveSetup { args }
+    public method LoadSetup { args }
+    public method GetSetupName {  } { return $setupfilename }
+
+    public method AddDummyFunctionalName { }
+    public method NewSetup { }
+
+
+    # --------------------------------------------
+    # Generic Callbacks
+    # --------------------------------------------
+    public method FillHierarchy    { items node } 
+    public method FillSubjects     { node }  { return [ FillHierarchy $subjects $node ] }
+    public method FillTasks        { node }  { return [ FillHierarchy $tasks    $node ] }
+
+
+    public method SelectItem   { widget callbck tag status } 
+    public method SelectSubject { tag status } { return [ SelectItem $subject_tree "SetNewSubject" $tag $status ]} 
+    public method SelectTask    { tag status } { return [ SelectItem $task_tree "SetNewTask" $tag $status ]} 
+
+
+    public method ExpandAll { widget items last_item mode }
+    public method ExpandAllSubjects { mode } { return [ ExpandAll $subject_tree $subjects $last_subject $mode ] }
+    public method ExpandAllTasks { mode } { return [ ExpandAll $task_tree $tasks $last_task $mode ] }
+    
+    # ----------------------------------------------
+    # Subject Specific Callbacks
+    # ----------------------------------------------
+
+    public method ResetSubjectTree { args }
+    public method AddSubject      { } 
+    public method RemoveCurrentSubject  { } 
+    public method RemoveAllSubjects { } 
+    public method SetNewSubject   { uid } 
+    protected method CreateSubjectControl { parent }
+
+    # ----------------------------------------------
+    # Task Specific Callbacks
+    # ----------------------------------------------
+
+    public method ResetTaskTree { args }
+    public method AddTask      { } 
+    public method RemoveCurrentTask  { } 
+    public method SetNewTask   { uid } 
+    public method RemoveAllTasks { } 
+    protected method CreateBaseControl  { parent }
+
+
+    # -----------------------------------------------
+    # Results Stuff
+    # -----------------------------------------------
+    public    method ChangeCurrentTask { tasklistbox args } 
+    public    method LoadAll { functionalonly }
+
+    # Stuff from outside access
+    public    method SetInterpolationAndResolution { interp resol }
+    public    method SetCurrentTask   { number } 
+
+    public    method ComputeTscoreMap {  } 
+    public    method ComputeAverages { mode } 
+    public    method WarpTasksToCommonSpace { mode { dirname "" } { saveanatomical 1 } }
+    public    method DoVOIAnalysis { filename appendmode } 
+
+
+    public    method SetOverlayCreatorInputs { } 
+    public    method OutputListCallback { listbox args }
+    protected method CreateResultsControl { parent } 
+
+    public method VerifyRegistrationCallback { mode args }
+    #    public method ComputeRegistrationCallback { mode args }
+    public method GrabRegistrationCallback { mode args }
+
+
+    # Get Output Files
+    # 
+    public method GetMeanAnatomicalOutput {  } {  return [ [ lindex  $outputimages 0 ] GetThisPointer ]  }
+    public method GetSigmaAnatomicalOutput {  } {  return [ [ lindex  $outputimages 1 ] GetThisPointer ]  }
+    public method GetMeanFunctionalOutput {  } {  return [ [ lindex  $outputimages 2 ] GetThisPointer ]  }
+    public method GetSigmaFunctionalOutput {  } {  return [ [ lindex  $outputimages 3 ] GetThisPointer ]  }
+    public method GetTscoreFunctionalOutput { } {  return [ [ lindex  $outputimages 4 ] GetThisPointer ]  }
+
+    # -----------------------------------
+    # Batch Mode Stuff
+    # ------------------------------------
+
+    protected method SelectTasksToProcess { comment }
+    protected method SelectSubjectsToProcess { comment }
+
+    public method ComputeAllResults { mode } 
+    public method WarpAllTasks { mode } 
+
+    public method Create4DImageForSingleFrameAndCurrentTask { imglist fr  { roimeanalg 0 } } 
+    public method Create4DImagesAllTasksOld { mode }
+    public method Create4DImagesAllTasks { mode }
+
+
+    public method DoVOIAnalysisAllTasks { mode } 
+    #    public method ComputeAllRegistrations { mode secondmode } 
+
+    # -----------------------------------
+    # Compare Stuff
+    # ------------------------------------
+    public method SetInfoToCompareTool { mode2 }
+    public method ShowCompareTool { }
+    
+    # -------------------
+    # OOP Stuff
+    # --------------------
+
+    public method SetResultsFromObject { img obj }
+    public method SetValueImage        { vtkimg  }
+    public method AddToMenuButton { mb args}
+    public method SetLookupTable       { colormap }
+    public method SetLookupTableMode   { index }
+    public method GetViewer { }
+
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::SetResultsFromObject { img obj  } {
+
+    if { [ $img GetImageSize ] < 2 } {	
+	return 0    
+    }
+    
+    if { $obj == $overlaycreator && $parent !=0 } {
+	if {$thisparam($this,overlayviewer) == "Transform" && $second_viewer !=0 } {
+	    $second_viewer SetResultsFromObject $img $this
+	} else {
+	    $parent SetResultsFromObject $img $this
+	}
+    } else {
+        SetResults $img
+    }
+    return 1
+}
+
+itcl::body pxitclmultisubjectaverage::SetValueImage { vtkimg  } {
+    if {$thisparam($this,overlayviewer) == "Transform" && $second_viewer !=0 } {
+	$second_viewer SetValueImage $vtkimg
+    } else {
+	$parent SetValueImage $vtkimg
+    }
+    return 1
+}
+
+# ---------------------------------------------------------------------------
+#  Lookup Table Stuff 
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclmultisubjectaverage::SetLookupTable { colormap } {
+    
+    set v $parent
+    if {$thisparam($this,overlayviewer) == "Transform" && $second_viewer !=0 } {
+	set v $second_viewer
+    }
+    
+    if { $v != 0 } {
+	$v SetLookupTable $colormap
+    }
+}
+
+itcl::body pxitclmultisubjectaverage::GetViewer { } {
+
+    set v [  $parent GetViewer ]
+    if {$thisparam($this,overlayviewer) == "Transform" && $second_viewer !=0 } {
+	set v [  $second_viewer GetViewer ]
+    }
+    return $v
+}
+
+itcl::body pxitclmultisubjectaverage::SetLookupTableMode { index } {
+
+    set v $parent
+    if {$thisparam($this,overlayviewer) == "Transform" && $second_viewer !=0 } {
+	set v $second_viewer
+    }
+    
+    if { $v != 0 } {
+	$v SetLookupTableMode $index
+    }
+}
+
+
+# ---------------------------------------------------------------------------
+
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclmultisubjectaverage::InitializeMultiSubject { } {
+    
+
+
+    set refx_control [ [  pxitcltransformGUI \#auto ] GetThisPointer ]
+    $refx_control configure -description "Transformation Anatomical->Reference"
+
+    set intx_control [ [  pxitcltransformGUI \#auto ] GetThisPointer ]
+    $intx_control configure -description "Transformation Conventional->Anatomical"
+
+    set distx_control [ [  pxitcltransformGUI \#auto ] GetThisPointer ]
+    $distx_control configure -description "Transformation Echoplanar->Conventional"
+
+    set anat_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $anat_control configure -description "Anatomical Image"
+
+    set reference_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $reference_control configure -description "Reference Image"
+
+    set voi_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $voi_control configure -description "VOI Image"
+
+
+    set conv_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $conv_control configure -description "Conventional Image"
+
+    set func_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $func_control configure -description "Functional Image"
+
+    set epi_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $epi_control configure -description "Spin-echo Echoplanar Image"
+
+    set field_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $field_control configure -description "Fieldmap Image"
+
+    set task_control [ [ pxitcltaskGUI \#auto ] GetThisPointer ]
+
+    set output_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $output_control configure -description "Results Image"
+
+    lappend itclobjectlist $refx_control $intx_control $distx_control $reference_control $voi_control $anat_control $conv_control $func_control $task_control $output_control $epi_control $field_control
+       
+    set thisparam($this,current_subject) ""
+    set thisparam($this,current_output)  ""
+    set thisparam($this,current_task) "task1"
+    set thisparam($this,current_taskname) "New_Task_1"
+    set tt $thisparam($this,current_task)
+
+    for { set i 0 } { $i < [ llength $output_list ] } { incr i } {
+	set tmp [ [ pxitclimage \#auto ] GetThisPointer ]
+	lappend outputimages $tmp
+	lappend itclobjectlist $tmp
+
+	switch -exact -- $i {
+	    "0" { $tmp configure -filename "anat_average.hdr" }
+	    "1" { $tmp configure -filename "anat_std.hdr" }
+	    "2" { $tmp configure -filename "func_mean${tt}.hdr" }
+	    "3" { $tmp configure -filename "func_std${tt}.hdr" }
+	    "4" { $tmp configure -filename "func_tscore${tt}.hdr" }
+	}
+    }
+
+    set thisparam($this,overlayviewer) "Reference"
+    set thisparam($this,overlaybase) "Reference Image"
+    set thisparam($this,overlayfunction) "T-Map"
+    set thisparam($this,overlaysinglesubject) 0
+
+    set thisparam($this,interpolation) "Cubic"
+    set thisparam($this,outputresolution) "3.0x3.0x3.0"
+    set thisparam($this,compositethreshold) "2000"
+    set thisparam($this,compositemode) "Positive"
+    set thisparam($this,compositesigma) 0.0
+
+    set thisparam($this,autosave) 1
+
+    set debugprogress 1
+
+}
+#--------------------------------------------------------------------------------------------
+#
+#           Setup File Stuff
+#
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::SaveSetup { args } { 
+
+    set tmptask [ lindex $tasks 0 ]
+    if { $thisparam($this,current_task) != [ $tmptask cget -task_suffix ] } {
+	set ok [ ::pxtclutil::Question "The first task ([ $tmptask cget -task_name ],[$tmptask cget -task_suffix]) is not the current task. This could cause problems. It is best to cancel and switch to this task (using the \"Change Current Task\" button in the Results pane and try again! Click YES to IGNORE this warning?" ]
+	if { $ok ==0 } { 
+	    return
+	}
+    }
+
+    set len [ llength $args ]
+    
+    if { $len < 1 } {
+	set fname $setupfilename 
+    } else {
+	set fname [ lindex $args 0 ]
+    }
+
+    if { [ string length $fname  ] == 0  } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname  [tk_getSaveFile -title "Saving Setup File" -filetypes { {"Multi-Setup File" {.msb}}} -initialfile $f1tail  -initialdir $f1path ]
+    }
+
+    if { [ string length $fname ] > 0 } {
+
+	set fileid [open $fname w]
+	
+	puts $fileid "#Multisubject Description File v3"
+	if { $tasks !=0 } {
+	    puts $fileid "Tasks\n[llength $tasks]"
+	    puts $fileid "- - - - - - - - - - - - - - - - - - - -"
+	    for { set i 0 } { $i < [ llength $tasks ] } { incr i } {
+		set tmp [ lindex $tasks $i ]
+		$tmp SaveToSetupFile $fileid
+	    }
+	}
+	if { $subjects != 0 } {
+	    puts $fileid "Subjects\n[llength $subjects]"
+	    puts $fileid "- - - - - - - - - - - - - - - - - - - -"
+	    for { set i 0 } { $i < [ llength $subjects ] } { incr i } {
+		set tmp [ lindex $subjects $i ]
+		$tmp SaveToSetupFile $fileid
+	    }
+	}
+
+	puts $fileid "Reference/Output Images"
+	puts $fileid "--------------------------------------"
+
+	puts $fileid "Reference Image : [ [ $reference_control  GetObject ] cget -filename] "
+	puts $fileid "VOI Image : [ [ $voi_control  GetObject ] cget -filename] "
+	for { set i 0 } { $i < [ llength $output_list ] } { incr i } {
+	    puts $fileid "[ lindex $output_list $i ] : [ [ lindex $outputimages $i ] cget -filename ]"
+	}
+	puts $fileid "Legacy : "
+	puts $fileid "Legacy : "
+	puts $fileid "Legacy : "
+	
+	
+	close $fileid
+	set setupfilename $fname
+	SetTitle "MultiSubjectAverage $setupfilename"
+    }
+}
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::AddDummyFunctionalName {  } { 
+
+    if { $subjects != 0 } {
+	for { set i 0 } { $i < [ llength $subjects ] } { incr i } {
+	    set tmp [ lindex $subjects $i ]
+	    set fname1 [  [ $tmp cget -anatomical_image ] cget -filename ]
+	    #	    puts stdout "Fname1=$fname1"
+	    set fname2 [ file join [ file dirname $fname1 ] dummy.hdr ]
+	    [ $tmp cget -functional_image  ] configure -filename $fname2
+	}
+    }
+}
+# ------------------------------------------------------------------------------------------
+
+itcl::body pxitclmultisubjectaverage::NewSetup {  } { 
+ 
+    set ok [ ::pxtclutil::Question "This will delete your current setup information. Are you sure?" ]
+    if { $ok ==0 } { 
+	return
+    }
+
+
+    for { set i 0 } { $i < [ llength $outputimages ] } { incr i } {
+	[ lindex $outputimages $i ] UnLoad
+    }
+
+    [ $reference_control  GetObject ] UnLoad
+    [ $voi_control  GetObject ] UnLoad
+    $reference_control Update
+    $voi_control Update
+    OutputListCallback $output_listbox 0
+
+    RemoveAllTasks
+    RemoveAllSubjects
+    
+    AddSubject;    AddSubject;    AddSubject;    SetNewSubject 0
+    AddTask;    AddTask;    SetNewTask 0
+}
+
+itcl::body pxitclmultisubjectaverage::LoadSetup { args } { 
+
+    set len [ llength $args ]
+    
+    if { $len < 1 } {
+	set fname $setupfilename 
+    } else {
+	set fname [ lindex $args 0 ]
+    }
+
+    if { [ string length $fname  ] == 0 } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname  [tk_getOpenFile -title "Setup File" -filetypes { {"Multi-Setup File" {.msb}}} -initialfile $f1tail -initialdir $f1path ]
+    }
+
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    if { [ file readable $fname ] == 0 } {
+	::pxtclutil::Warning "Cannot read setupfile file from $fname\n Bad File"
+	return 0
+    }
+
+    set fileid [open $fname r]
+	
+    gets $fileid line
+
+    set setupmode 0
+
+    if { [ string compare $line "#Multisubject Description File"  ] != 0 } {
+	if { [ string compare $line "#Multisubject Description File v2"  ] != 0 } {
+	    if { [ string compare $line "#Multisubject Description File v3"  ] != 0 } {
+		close $fileid
+		::pxtclutil::Warning "Cannot read setupfile file from $fname\n Bad File Type"
+		return 0
+	    } else {
+		set setupmode 2
+	    }
+	} else {
+	    set setupmode 1
+	}
+    }
+
+    gets $fileid line ;     gets $fileid line  ;     set numtasks $line ;    gets $fileid line 
+    RemoveAllTasks
+
+    for { set i 0 } { $i < $numtasks } { incr i } {
+	set tmp [ AddTask ]
+	$tmp LoadFromSetupFile $fileid
+    }
+
+
+    gets $fileid line ;     gets $fileid line  ;     set numsub $line ;    gets $fileid line 
+    RemoveAllSubjects
+
+    for { set i 0 } { $i < $numsub } { incr i } {
+	set tmp [ AddSubject ]
+	$tmp LoadFromSetupFile $fileid $setupmode
+    }
+
+    gets $fileid line ; gets $fileid line 
+
+    # Do the Reference Separately
+    set name [ pxitclsubject::GetFileElement $fileid ]
+    set img  [ $reference_control GetObject ];     $img UnLoad  ;  $img configure -filename $name ;    $reference_control Update
+
+    # Next do the VOI Control
+    if { $setupmode == 2 } {
+	set name [ pxitclsubject::GetFileElement $fileid ]
+    } else {
+	set name ""
+    }
+    set img  [ $voi_control GetObject ];     $img UnLoad  ;  $img configure -filename $name ;    $voi_control Update
+    
+
+    for { set i 0 } { $i < [ llength $output_list ] } { incr i } {
+	set name [ pxitclsubject::GetFileElement $fileid ]
+	set img  [ lindex $outputimages $i ]
+	$img UnLoad
+	$img configure -filename $name
+    }
+	
+    close $fileid
+    set setupfilename $fname
+
+    ResetSubjectTree -1
+    ResetTaskTree -1
+
+    SetNewSubject 0
+    SetNewTask 0
+    OutputListCallback $output_listbox 0
+
+    set tmptask [ lindex $tasks 0 ]
+    set thisparam($this,current_task) [ $tmptask cget -task_suffix ]
+    set thisparam($this,current_taskname) [ $tmptask cget -task_name  ]
+
+    SetTitle "MultiSubjectAverage $setupfilename"
+    return 1
+
+}
+# ------------------------------------------------------------------------------------------
+#
+#  Can we make these generic ?
+#
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::FillHierarchy { items node } {
+
+    if { $node == "" } {
+	set slist ""
+	if { $items != 0 } {
+	    for { set i 0 } { $i < [ llength $items ] } { incr i } {
+		set tmp [ lindex $items $i ]
+		lappend slist [ list $i [ $tmp GetBaseName ]]
+	    }
+	}
+	return $slist
+    }
+    
+    if { $node >=0 && $node < [ llength $items ] && $items!=0 } {
+	return [ [  lindex $items $node ] GetNameList ]
+    }
+
+    return ""
+}
+
+# ----------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::SelectItem { widget clback uid status} {
+
+    if { [ string match "::*" $uid ] == 1 } {
+	return 0
+    }
+
+    $widget selection clear
+    $widget selection add  $uid
+    eval "$clback  $uid"
+    $this SetOverlayCreatorInputs 
+
+}
+
+
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::ExpandAll { widget items last_item mode } {
+
+    if { $items ==0  || [ llength $items ] == 0  } {
+	return
+    }
+
+    if { $mode == 2 } {
+	ExpandAll $widget $items $last_item 0
+	catch { $widget expand $last_item }
+	return 
+    }
+
+    set len [ llength $items ]
+    if { $mode == 1 } {
+	for { set i 0 } { $i < $len } { incr i } {
+	    $widget expand $i
+	}
+    } else {
+	for { set i 0 } { $i < $len } { incr i } {
+	    $widget collapse $i
+	}
+    }
+}
+
+
+# ----------------------------------------------------------------------
+#
+#           Subject Specific
+#
+# ----------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::SetNewSubject { uid} {
+
+    if { $uid >=0 && $uid < [ llength $subjects ] && $subjects!=0 } {
+	
+	set last_subject $uid	
+	set tmp [ lindex $subjects $uid ]
+		
+	$anat_control SetImage [ $tmp cget -anatomical_image ] 
+	$conv_control SetImage [ $tmp cget -conventional_image ]
+	$func_control SetImage [ $tmp cget -functional_image ]
+	$epi_control SetImage [ $tmp cget -echoplanar_image ]
+	$field_control SetImage [ $tmp cget -fieldmap_image ]
+
+	$refx_control SetTransformation [ $tmp cget -reference_transform ]
+	$intx_control SetTransformation [ $tmp cget -internal_transform ]
+	$distx_control SetTransformation [ $tmp cget -distortion_transform ]
+
+	set thisparam($this,current_subject) "[expr $uid+1 ]:[ $tmp GetBaseName ]"
+    }
+    $this SetOverlayCreatorInputs 
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::RemoveCurrentSubject  { } {
+
+    if { $last_subject == -1 || $subjects == 0 } { 
+	return 0 
+    }
+
+    if { $last_subject >= [ llength $subjects ] } {
+	return 0
+    }
+
+    set tmp [ lindex $subjects $last_subject ]
+    set name $thisparam($this,current_subject) 
+
+    if { [ pxtclutil::Question "Remove Subject $name" ] == 0 } {
+	return
+    }
+    
+
+    set subjects [ lreplace $subjects  $last_subject $last_subject ]
+    if { [ llength $subjects ] == 0  } {
+	set subjects 0
+    }
+    catch { itcl::delete object $tmp }
+    
+    ResetSubjectTree
+    SetNewSubject 0
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::RemoveAllSubjects  { } {
+
+    if { $subjects == 0 } { 
+	return 
+    }
+
+    
+    for { set i 0 } { $i < [ llength $subjects ] } { incr i } {
+	set tmp [ lindex $subjects $i ]
+	catch { itcl::delete object $tmp }
+    }
+    
+    set subjects 0
+    ResetSubjectTree
+}
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclmultisubjectaverage::AddSubject { } {
+
+    set tmp [ [ pxitclsubject \#auto ]  GetThisPointer ]
+    lappend itclobjectlist $tmp
+    if { $subjects !=0 } {
+	lappend subjects $tmp
+    } else {
+	set subjects [ list $tmp ]
+    }
+
+    incr last_added_subject
+    [ $tmp cget -anatomical_image ] configure -filename "New_Subject_${last_added_subject}"
+
+    ResetSubjectTree 
+
+    return $tmp
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::ResetSubjectTree { args } {
+
+    set mode 0
+    if { [ llength $args ] > 0 } {
+	set mode [ lindex $args 0 ]
+    }
+
+    #eval "$subject_tree configure -querycommand \"$this FillSubjects %n\" "
+    $subject_tree draw -now
+
+    catch {
+	set tmp [ lindex $subjects $last_subject ]
+	set thisparam($this,current_subject) "[expr $last_subject+1]:[ $tmp GetBaseName ]"
+    }
+
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::CreateSubjectControl { widget } {
+
+    frame $widget.left
+    frame $widget.mid -bg black -width 5
+    set wr [ frame $widget.right ]
+
+    pack $widget.right $widget.mid -side right -expand f -fill y 
+    pack $widget.left  -side left -expand f -fill y -padx 10
+
+    iwidgets::entryfield $wr.entry -labeltext "Current Subject:"  -width 25  -textvariable [ itcl::scope thisparam($this,current_subject) ] -relief sunken  
+
+
+    iwidgets::tabnotebook $wr.base  -tabpos n
+    pack $wr.entry -side top -fill x -expand f
+    pack $wr.base -side top -fill both -expand true
+    $wr.base configure -width 500
+
+    set b1 [ $wr.base add -label "Main" ]
+    set b2 [ $wr.base add -label "Distortion Correction" ]
+    $wr.base view "Main"
+
+    $anat_control InitializeLite $b1.1 3 
+    $func_control InitializeLite $b1.2 3; $b1.2 configure -background darkgray
+    $refx_control Initialize $b1.3;  $b1.3 configure -background darkgray
+    $conv_control InitializeLite $b1.4 3; 
+    $intx_control Initialize $b1.5
+    $epi_control   InitializeLite $b2.6 3  
+    $distx_control Initialize $b2.7
+    $field_control   InitializeLite $b2.8 3   ; $b2.8 configure -background darkgray
+    pack $b1.1 $b1.2 $b1.3 $b1.4 $b1.5  -side top -expand f -fill x -pady 0
+    pack $b2.6 $b2.7 $b2.8 -side top -expand false -fill x -pady 0
+
+    if { $parent != 0 } {
+	if { $second_viewer == 0 } {
+	    $anat_control AddFunction "$parent SetResultsFromObject" "Display" "$this"
+	    $conv_control AddFunction "$parent SetResultsFromObject" "Display" "$this"
+	    $func_control AddFunction "$parent SetResultsFromObject" "Display" "$this"
+	    $epi_control AddFunction "$parent SetResultsFromObject" "Display" "$this"
+	    $field_control AddFunction "$parent SetResultsFromObject" "Display" "$this"
+	} else {
+	    $anat_control AddFunction "$parent SetImageFromObject" "Display Ref" "$this"
+	    $conv_control AddFunction "$parent SetImageFromObject" "Display Ref" "$this"
+	    $func_control AddFunction "$parent SetImageFromObject" "Display Ref" "$this"
+	    $epi_control AddFunction "$parent SetImageFromObject" "Display Ref" "$this"
+	    $field_control AddFunction "$parent SetImageFromObject" "Display Ref" "$this"
+
+
+	    $anat_control AddFunction "$second_viewer SetImageFromObject" "Display Trn" "$this"
+	    $conv_control AddFunction "$second_viewer SetImageFromObject" "Display Trn" "$this"
+	    $func_control AddFunction "$second_viewer SetImageFromObject" "Display Trn" "$this"
+	    $epi_control AddFunction "$second_viewer SetImageFromObject" "Display Trn" "$this"
+	    $field_control AddFunction "$second_viewer SetImageFromObject" "Display Trn" "$this"
+
+	    $refx_control AddFunction "$this VerifyRegistrationCallback 1" "Check" "$this"
+	    $intx_control AddFunction "$this VerifyRegistrationCallback 2" "Check" "$this"
+	    $distx_control AddFunction "$this VerifyRegistrationCallback 3" "Check" "$this"
+	}
+	
+	if { $external_overlayutility != 0 } {
+#	    $refx_control AddFunction "$this ComputeRegistrationCallback 1" "Go to Compute" "showcontrols"
+#	    $intx_control AddFunction "$this ComputeRegistrationCallback 2" "Go to Compute" "showcontrols"
+#	    $distx_control AddFunction "$this ComputeRegistrationCallback 3" "Go to Compute" "showcontrols"
+	    
+	    $refx_control AddFunction "$this GrabRegistrationCallback 1 \"\"" "Grab" "$this"
+	    $intx_control AddFunction "$this GrabRegistrationCallback 2 \"\"" "Grab" "$this"
+	    $distx_control AddFunction "$this GrabRegistrationCallback 3 \"\"" "Grab" "$this"
+	}
+    }
+
+
+    
+    set subject_tree $widget.left.h
+    eval "iwidgets::hierarchy $subject_tree -querycommand \"$this FillSubjects %n\" -visibleitems 60x15 -labeltext \"Subject List\" -selectcommand \"$this SelectSubject %n %s\" "
+    $subject_tree configure -alwaysquery yes
+    pack $subject_tree -side top -expand yes -fill both
+
+    eval "$subject_tree  component itemMenu add command -label \"Reset\"           -command { $this ResetSubjectTree }"
+    eval "$subject_tree  component itemMenu add command -label \"Expand Current Only\"     -command { $this ExpandAllSubjects 2 }"
+    eval "$subject_tree  component itemMenu add command -label \"Expand All\"      -command { $this ExpandAllSubjects 1 }"
+    eval "$subject_tree  component itemMenu add command -label \"Collapse All\"    -command { $this ExpandAllSubjects 0 }"
+
+
+
+    set bot1 [ frame $widget.left.bot1 ]; 
+    pack   $bot1 -side bottom -expand f -fill x
+
+
+
+    eval "button $bot1.b1 -text \"Add Subject\"     -command { $this AddSubject}"
+    eval "button $bot1.b2 -text \"Remove Subject\"  -command { $this RemoveCurrentSubject }"
+    pack $bot1.b1 $bot1.b2  -side left
+
+
+
+}
+# ---------------------------------------------------------------------------
+#
+#           Task Specific
+#
+# ----------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::SetNewTask { uid} {
+
+    if { $uid >=0 && $uid < [ llength $tasks ] && $tasks!=0 } {
+
+	set last_task $uid	
+	set tmp [ lindex $tasks $uid ]
+	$task_control SetTask $tmp
+    }
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::RemoveCurrentTask  { } {
+
+    if { $last_task == -1 || $tasks == 0 } { 
+	return 0 
+    }
+
+    if { $last_task >= [ llength $tasks ] } {
+	return 0
+    }
+
+    set tmp [ lindex $tasks $last_task ]
+    set name [ $tmp GetBaseName ]
+
+    if { [ $tmp cget -task_suffix ] == $thisparam($this,current_task)  } {
+	pxtclutil::Warning "Cannot Remove task $name, as it is the current task!"
+	return 0
+    }
+
+
+    if { [ pxtclutil::Question "Remove Task $name" ] == 0 } {
+	return 0
+    }
+    
+    set tasks [ lreplace $tasks  $last_task $last_task ]
+    if { [ llength $tasks ] == 0  } {
+	set tasks 0
+    }
+
+    catch { itcl::delete object $tmp }
+    
+    ResetTaskTree
+    SetNewTask 0
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::RemoveAllTasks  { } {
+
+    if { $tasks == 0 } { 
+	return 
+    }
+
+    
+    for { set i 0 } { $i < [ llength $tasks ] } { incr i } {
+	set tmp [ lindex $tasks $i ]
+	catch { itcl::delete object $tmp }
+    }
+    
+    set tasks 0
+    set last_added_task 0
+    ResetTaskTree
+
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::AddTask { } {
+
+    set tmp [ [ pxitcltask \#auto ]  GetThisPointer ]
+    lappend itclobjectlist $tmp
+    if { $tasks !=0 } {
+	lappend tasks $tmp
+    } else {
+	set tasks [ list $tmp ]
+    }
+
+    incr last_added_task
+    $tmp configure -task_name "New_Task_${last_added_task}"
+    $tmp configure -task_suffix "task${last_added_task}"
+    ResetTaskTree 
+    return $tmp
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::ResetTaskTree { args } {
+
+    set mode 0
+    if { [ llength $args ] > 0 } {
+	set mode [ lindex $args 0 ]
+    }
+
+    #eval "$task_tree configure -querycommand \"$this FillTasks %n\" "
+    $task_tree draw -now
+
+    if { $task_listbox != 0 && $tasks !=0 } {
+	$task_listbox clear
+	for { set i 0 } { $i < [ llength $tasks ] } { incr i } {
+	    $task_listbox insert end [ [ lindex $tasks $i ] cget -task_name ]
+	}
+    }
+
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::CreateBaseControl { widget } {
+    # -----------
+    # Task Editor
+    # -----------
+
+    $reference_control Initialize $widget.1 
+    $voi_control Initialize $widget.11
+
+    if { $parent !=0 } {
+	if { $second_viewer == 0 } {
+	    $reference_control AddFunction "$parent SetResultsFromObject" "Display" "$this"
+	    $voi_control AddFunction "$parent SetResultsFromObject" "Display" "$this"
+	} else {
+	    $reference_control AddFunction "$parent SetImageFromObject" "Display Ref" "$this"
+	    $reference_control AddFunction "$second_viewer SetImageFromObject" "Display Trn" "$this"
+	    $voi_control AddFunction "$parent SetImageFromObject" "Display Ref" "$this"
+	    $voi_control AddFunction "$second_viewer SetImageFromObject" "Display Trn" "$this"
+	}
+    }
+    [ $reference_control GetObject ] configure -filename "reference.hdr"
+    [ $voi_control GetObject ] configure -filename "voi.hdr"
+
+    frame $widget.15 -bg black -height 15
+    pack $widget.1 $widget.11 $widget.15 -side top -expand f -fill x -padx 10 -pady 10
+    frame $widget.2 ;   pack $widget.2 -side top -expand f -fill x
+
+    set base $widget.2
+
+
+    frame $base.left
+    frame $base.mid -bg black -width 2
+    set wr [ frame $base.right ]
+
+    pack $base.left -side left -expand f -pady 20 -padx 5
+    pack $base.mid  -side left -expand f -pady 20 -fill y -padx 2
+    pack $base.right -side left -expand f -pady 20 -padx 5 
+
+    $task_control Initialize $wr.1
+    pack $wr.1 -side left -expand f -fill x
+    
+    set task_tree $base.left.h
+    eval "iwidgets::hierarchy $task_tree -querycommand \"$this FillTasks %n\" -visibleitems 20x15 -labeltext \"Task List\" -selectcommand \"$this SelectTask %n %s\" "
+    $task_tree configure -alwaysquery yes
+    eval "$task_tree component itemMenu add command -label  \"Expand Curr\"   -command { $this ExpandAllTasks 2 }"
+    eval "$task_tree component itemMenu add command -label  \"Reset\"        -command { $this ResetTaskTree }"
+    eval "$task_tree component itemMenu add command -label  \"Expand All\"   -command { $this ExpandAllTasks 1 }"
+    eval "$task_tree component itemMenu add command -label  \"Collapse All\"   -command { $this ExpandAllTasks 0 }"
+    pack $task_tree -side top -expand yes -fill both
+
+    set bot1 [ frame $base.left.bot1 ]; 
+    pack  $bot1 -side bottom -expand f -fill x
+
+    eval "button $bot1.b1 -text \"Add Task\"  -command { $this AddTask}"
+    eval "button $bot1.b2 -text \"Remove Task\"  -command { $this RemoveCurrentTask }"
+    pack $bot1.b1 $bot1.b2  -side left
+
+
+}
+# ---------------------------------------------------------------------------
+#   
+# Output Stuff
+#
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::SetOverlayCreatorInputs { } {
+
+    set tmode 0
+    set fmode 0
+    
+    switch -exact -- $thisparam($this,overlaybase) {
+	"Reference Image" { $overlaycreator SetInput [ $reference_control GetObject  ] }
+	"Average Anatomical" { $overlaycreator SetInput [ lindex $outputimages 0 ] }
+	"Individual Anatomical" { $overlaycreator SetInput [ $anat_control GetObject  ]; set tmode 1 }
+	"Individual Conventional" { $overlaycreator SetInput [ $conv_control GetObject  ]; set tmode 2 }
+	"Individual Echoplanar" { $overlaycreator SetInput [ $epi_control GetObject  ]; set tmode 3 }
+    }
+
+
+    if { $tmode >0 }  {
+	set thisparam($this,overlayfunction) "Single Map"
+	set fmode 3
+    } 
+	
+
+    switch -exact -- $thisparam($this,overlayfunction) {
+	"Average Map"  { $overlaycreator SetSecondInput [ lindex $outputimages 2 ] }
+	"T-Map" { $overlaycreator SetSecondInput [ lindex $outputimages 4 ] } 
+	"Single Map" { $overlaycreator SetSecondInput [ $func_control GetObject  ]; set fmode 3 }
+    }
+
+    $overlaycreator UpdateInputRanges
+
+
+    if { $fmode == 3 } {
+	pack $thisparam($this,overlaysinglesubject) -side right -padx 2
+    } else {
+	pack forget $thisparam($this,overlaysinglesubject) 
+    }
+
+
+
+    # ----------------------------------------
+    # Identical Space, i.e. echoplanar to indvidual (3,3) or 
+    # Global to global (0,0)
+    # -----------------------------------------
+
+    
+    #    puts stderr "Current Subjec sutff [ [ $anat_control GetImage ] cget -filename ]\n [ [ $conv_control GetImage ] cget -filename ]\n [[	$func_control GetImage ] cget -filename ]"
+    #   puts stderr "Overlays $thisparam($this,overlayfunction)\n"
+    #  puts stderr "Anatomical Image = [ [ $overlaycreator GetImage ] cget -filename ]"
+    # puts stderr "Functional Image = [ [ $overlaycreator GetFunctionalImage ] cget -filename ]"
+    #puts stderr "\t\t Range [ [ [ [ [ $overlaycreator GetFunctionalImage ] GetImage ] GetPointData ] GetScalars ] GetRange ]"
+
+    if { ($tmode == 3 && $fmode == 3) || ( $tmode==0 && $fmode==0) } {
+
+	#puts stderr "Simple mode tmode=$tmode fmode=$fmode identity transformation"
+	set tr_id [ vtkTransform [ pxvtable::vnewobj ]]
+	$tr_id Identity
+	$overlaycreator SetVTKTransformation $tr_id
+	return
+    }
+
+
+    # ----------------------------------------
+    # Otherwise Concatenate Tranforms
+    # -----------------------------------------
+
+    set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+    $trans Identity
+    $trans PostMultiply
+
+    set numt 1
+
+    switch -exact -- $tmode  {
+	0 { # Global Average or Composite Average -- we need everything
+	    $trans Concatenate [ [ $refx_control GetObject ] GetTransformation ]
+	    #puts stderr "Concatenating [ [ $refx_control GetObject ] cget -filename ]"
+	    $trans Concatenate [ [ $intx_control GetObject ] GetTransformation ]
+	    #puts stderr "Concatenating [ [ $intx_control GetObject ] cget -filename ]"
+	    $trans Concatenate [ [ $distx_control GetObject ] GetTransformation ]
+	    #puts stderr "Concatenating [ [ $distx_control GetObject ] cget -filename ]"
+	    set numt 3
+	}
+	1 { # Invdividual 3d
+	    $trans Concatenate [ [ $intx_control GetObject ] GetTransformation ]
+	    #puts stderr "Concatenating [ [ $intx_control GetObject ] cget -filename ]"
+	    $trans Concatenate [ [ $distx_control GetObject ] GetTransformation ]
+	    #puts stderr "Concatenating [ [ $distx_control GetObject ] cget -filename ]"
+	    
+	    set numt 2
+	}
+	2 { # Nothing To Add
+	}
+	3 { # Nothing To Add
+	}
+    }
+    #    puts stderr "More Complex tmode=$tmode fmode=$fmode number of concatenated transformations = $numt"
+
+
+    $overlaycreator SetVTKTransformation $trans
+    $trans Delete
+
+
+}
+
+
+itcl::body pxitclmultisubjectaverage::OutputListCallback { listbox args } {
+
+    if { [ llength  $args ] > 0 } {
+	set uid [ lindex $args 0 ]
+	$listbox selection set $uid
+    } 
+	
+    set uid [ lindex [ $listbox curselection ] 0 ]
+    if { [ llength $uid ] == 0 } {
+	set uid 0
+	$listbox selection set 0
+    }   
+
+    $output_control configure -description [ lindex $output_list $uid ]
+    $output_control SetImage [ lindex $outputimages $uid ]
+    if { $listbox == $output_listbox } {
+	set output_listbox_lastselected  $uid
+    }
+}
+
+
+
+# ------------------------------------------------------------------
+# Load All Images
+# ------------------------------------------------------------------
+
+itcl::body pxitclmultisubjectaverage::LoadAll { functionalonly } {
+	
+    set beg 3;
+    set end 4;
+    if { $functionalonly <1 } {
+	set beg 0
+	set end 4
+    }
+
+    set scalefactor [expr 1.0 / ( 1.0 + [ llength $subjects ] + [ llength $outputimages ] +1 ) ]
+    set progress 0.0
+
+    if { $functionalonly < 1 } {
+	[ $reference_control GetObject ] Load 
+	$reference_control Update
+	[ $voi_control GetObject ] Load 
+	$voi_control Update
+    }
+
+   
+    for { set i $beg } { $i <= $end } { incr i } {
+	[ lindex $outputimages $i ]  Load
+	ShowProgressVal "Loading Output Image $i" $progress
+	set progress [ expr $progress +$scalefactor ]
+    }
+    
+
+    for { set sub 0 } { $sub < [ llength $subjects ] } { incr sub } {
+	
+	set current [ lindex $subjects $sub ] 
+	
+	if { $functionalonly <1 } {
+	    
+	    [ $current cget -anatomical_image ] Load
+	    [ $current cget -conventional_image ] Load
+	    [ $current cget -echoplanar_image ] Load
+	    [ $current cget -reference_transform ] Load
+	    [ $current cget -internal_transform ] Load
+	    [ $current cget -distortion_transform ] Load
+	}
+
+	set ok [ [ $current cget -functional_image ] Load ]
+	if { $ok == 0 } {
+	    puts stdout "Failed to load functional image"
+	}
+	ShowProgressVal "Loading Subject Image(s) $sub" $progress
+	set progress [ expr $progress +$scalefactor ]
+
+    }
+
+    ShowProgressVal  "Done"  1.0
+    update idletasks
+
+    SetNewSubject 0
+
+    OutputListCallback $output_listbox $output_listbox_lastselected 
+    ShowProgressVal  "Done" 0.0
+    $this SetOverlayCreatorInputs 
+}
+
+# ------------------------------------------------------------------
+# Compute Averages
+# ------------------------------------------------------------------
+
+itcl::body pxitclmultisubjectaverage::ComputeTscoreMap {  } {
+
+    set immean [ lindex $outputimages 2 ]
+    set imvar  [ lindex $outputimages 3 ]
+    
+    if { [ $immean GetImageSize ] < 2  } {
+	::pxtclutil::Warning "No Composite Task In Memory"
+	return 0;
+    }
+
+    if { [ $imvar GetImageSize ] < 2  }  {
+	::pxtclutil::Warning "No Composite Task Standard Deviation In Memory"
+	return 0;
+    }
+    
+    set cast [ vtkImageCast [ pxvtable::vnewobj ]]
+    set cast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+
+    $cast  SetInput [ $immean GetImage ]
+    $cast2 SetInput [ $imvar  GetImage ]
+    $cast  SetOutputScalarTypeToFloat
+    $cast2 SetOutputScalarTypeToFloat
+
+    $cast  Update
+    $cast2 Update
+
+    set tcomp [  vtkpxComputeTmap [ pxvtable::vnewobj ]]
+    $tcomp SetInput [ $cast GetOutput ]
+    $tcomp SetInputStandardDeviation [ $cast2 GetOutput ]
+    $tcomp SetNumberOfInputs 1
+    $tcomp SetNumberOfSamples1 [ llength $subjects ]
+    SetFilterCallbacks $tcomp  "Computing Composite TMap"
+    $tcomp Update
+
+    set tscoreimage [ lindex $outputimages 4 ]
+    $tscoreimage ShallowCopyImage [ $tcomp GetOutput]
+    [ $tscoreimage GetImage ] SetOrigin 0.0 0.0 0.0
+
+    $tscoreimage CopyImageHeader [ $immean GetImageHeader ]
+    if { $thisparam($this,autosave) == 1 } {
+	if { [ $tscoreimage cget -filename ] == "" } {
+	    $tscoreimage Save "" "T-Score Map"
+	} else {
+	    $tscoreimage Save
+	}
+    }
+    $tcomp Delete 
+    $cast Delete
+    $cast2 Delete
+    OutputListCallback $output_listbox 0
+    $this SetOverlayCreatorInputs
+}
+
+# --------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::SetCurrentTask   { number }  {
+
+    set numtasks [llength $tasks]
+    set c $number
+    if { $c < 0 || $c >= $numtasks } {
+	set c 0
+    }
+    $task_listbox selection clear 0 [ expr $numtasks -1 ]
+    $task_listbox selection set $c $c
+    ChangeCurrentTask $task_listbox "vocal"
+    set newtname [ [ lindex $tasks $c ] cget -task_name ]
+    set newtsuffix [ [ lindex $tasks $c ] cget -task_suffix ]
+
+    return [ list $c $newtname $newtsuffix ]
+}
+
+itcl::body pxitclmultisubjectaverage::SetInterpolationAndResolution { interp resol } {
+
+    set thisparam($this,interpolation) $interp
+    switch -exact -- $resol {
+	"Ref" { set thisparam($this,outputresolution) "Ref" }
+	"1.5" { set thisparam($this,outputresolution) "1.5x1.5x1.5"}
+	"2.0" { set thisparam($this,outputresolution) "2.0x2.0x2.0"}
+	"3.0" { set thisparam($this,outputresolution) "3.0x3.0x3.0"}
+	"4.5" { set thisparam($this,outputresolution) "4.5x4.5x4.5"}
+    }
+
+    set thisparam($this,autosave) 0
+}
+
+# --------------------------------------------------------------
+# ---------------- Compute Averages ------ -------- ------------
+# --------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::ComputeAverages { mode  } {
+    
+
+    set referenceImage [ $reference_control GetObject ]
+
+    set beginsub 0
+    set endsub   [ expr [ llength $subjects ]  -1 ]
+
+    set interp 0
+    if { $thisparam($this,interpolation) == "Linear" } {
+	set interp 1 
+    } elseif { $thisparam($this,interpolation) == "Cubic" } {
+	set interp 3
+    }
+    
+    if { $endsub <= $beginsub } {
+	::pxtclutil::Warning "Cannot Average Images as specified ($beginsub:$endsub)!"
+	return;
+    }
+
+
+    set ref_image [ $referenceImage  GetImage ]
+    set delete_ref_image 0
+    
+    if { $thisparam($this,outputresolution) != "Ref" } {
+	set sp 1.0
+	if { $thisparam($this,outputresolution) == "2.0x2.0x2.0" } {
+	    set sp 2.0
+	} elseif { $thisparam($this,outputresolution) == "3.0x3.0x3.0" } {
+	    set sp 3.0
+	} elseif { $thisparam($this,outputresolution) == "4.5x4.5x4.5" } {
+	    set sp 4.5
+	} elseif { $thisparam($this,outputresolution) == "1.5x1.5x1.5" } {
+	    set sp 1.5
+	}
+	ShowProgressVal "Resampling Reference to $sp x $sp x $sp" 0.01
+	set resl [ vtkImageResample [ pxvtable::vnewobj ] ]
+	$resl SetAxisOutputSpacing 0 $sp
+	$resl SetAxisOutputSpacing 1 $sp
+	$resl SetAxisOutputSpacing 2 $sp
+	$resl InterpolateOff
+	$resl SetDimensionality 3
+	$resl SetInput $ref_image 
+	$resl Update
+
+	set ref_image [ vtkImageData [ pxvtable::vnewobj ]]
+	$ref_image ShallowCopy [ $resl GetOutput ]
+	$resl Delete
+	set delete_ref_image 1
+    }
+
+    if { $debugprogress == 1 } {
+	puts stdout "ref_image  Dimensions = [ $ref_image GetDimensions ]"
+    }
+
+    set util [ vtkpxUtil [ pxvtable::vnewobj ]]	
+    
+    set scalefactor [expr 2.0 / ( 2.0 + 2.0* ( $endsub-$beginsub +1 )) ]
+    set progress 0.0
+    
+    switch -exact -- $mode { 
+	"Images"  {
+	    set outputMean [ lindex $outputimages 0 ]
+	    set outputStd  [ lindex $outputimages 1 ]
+	    set value   -1.0
+	    set valueout 0.0
+	    set averaging "Anatomical"
+	}
+	"Functional" {
+	    set outputMean [ lindex $outputimages 2 ]
+	    set outputStd  [ lindex $outputimages 3 ]
+	    set value -32767
+	    set valueout 0.0
+	    set averaging "Functional"
+	}
+	"Composite" {
+	    set outputMean [ lindex $outputimages 5 ]
+	    set outputStd  0
+	    set value -32767
+	    set valueout -1.0
+	    set averaging "Composite"
+	}
+
+    }
+
+    set combofmri [  vtkpxAverageImages [ pxvtable::vnewobj ]]
+    $combofmri SetMedian 0
+    $combofmri SetIgnoreValue $value
+    $combofmri SetIgnoreValueOutput $valueout
+    $combofmri IgnoreFlagOn
+    
+    for { set i $beginsub } { $i <= $endsub } { incr i } {
+	
+	ShowProgressVal "Computing Averages image=$i" $progress 
+	
+	set subject [ lindex $subjects $i ]
+	set clean_trans 1
+	if { $averaging == "Functional" || $mode == "Composite" } {
+	    set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+	    $trans PostMultiply
+	    $trans Identity
+	    $trans Concatenate [ [ $subject cget -reference_transform ] GetTransformation ]
+	    $trans Concatenate [ [ $subject cget -internal_transform ] GetTransformation ]
+	    $trans Concatenate [ [ $subject cget -distortion_transform ] GetTransformation ]
+	} else {
+	    set trans [ [ $subject cget -reference_transform ] GetTransformation ]
+	    set clean_trans 0
+	}
+	
+	set clean_trn_image 0
+	
+	switch -exact -- $mode { 
+	    "Images" { 
+		set trn_image [ [ $subject cget -anatomical_image ] GetImage ] 
+	    }
+	    "Functional" { 	
+		set trn_image [ [ $subject cget -functional_image ] GetImage ] 
+	    }
+	}
+	
+	set tmp_im($i)  [ vtkImageData [pxvtable::vnewobj ] ]
+	
+	$util ResliceImage $tmp_im($i) $trn_image $ref_image $trans $interp $value
+	set progress [ expr $progress+$scalefactor ]
+
+	if { $debugprogress == 1 } {
+	    puts stdout "Image $i dimensions = [ $tmp_im($i) GetDimensions ] "
+	}
+
+	$combofmri AddInput $tmp_im($i)
+
+	if { $clean_trans == 1 } {
+	    $trans Delete
+	}
+	if { $clean_trn_image == 1 } {
+	    $trn_image Delete
+	}
+
+
+    }
+	
+    ShowProgressVal  "Computing Averages image=$i" $progress 
+    set progress [ expr $progress+$scalefactor ]
+    if { $outputStd != 0 } {
+	$combofmri ComputeStandardDeviationOn
+    }
+
+    #puts stderr "On to combofmri Update"
+    $combofmri Update
+    #puts stderr "On to combofmri Done"
+    ShowProgressVal "Computed Averages image=$i" $progress 
+
+    $outputMean ShallowCopyImage [ $combofmri GetOutput ]
+
+    [ $outputMean GetImage ] SetOrigin 0.0 0.0 0.0
+    $outputMean CopyImageHeader [ $referenceImage GetImageHeader ] 
+    if { $thisparam($this,autosave) == 1 } {
+	#puts stdout "Saving Mean"
+	if { [ $outputMean cget -filename ] == "" } {
+	    $outputMean Save "" "Average Functional Map"
+	} else {
+	    $outputMean Save 
+	}
+    }
+    
+    if { $outputStd !=0 } {
+	$outputStd ShallowCopyImage [ $combofmri GetOutputStandardDeviation ]
+	[ $outputStd GetImage ] SetOrigin 0.0 0.0 0.0
+	$outputStd CopyImageHeader [ $referenceImage GetImageHeader ] 
+        if { $thisparam($this,autosave) == 1 } {
+	    #   puts stdout "Saving STD"
+	    if { [ $outputStd cget -filename ] == "" } {
+		$outputStd Save "" "STD Functional Map"
+	    } else {
+		$outputStd Save 
+	    }
+	}
+    }
+	
+    for { set i $beginsub } { $i <= $endsub } { incr i } {
+	$tmp_im($i) Delete
+    }
+    
+    if { $mode == "Functional" } {
+	#puts stdout "Computing Tscore MAP"
+	ComputeTscoreMap
+    }
+    #puts stdout "Cleaning Up"
+    $combofmri Delete
+    ShowProgressVal  "Done"  1.0
+    #puts stdout "Cleaning Up 2"
+    if { $delete_ref_image ==  1 } {
+	$ref_image Delete 
+    }
+    
+    $util Delete 
+    #puts stdout "Cleaning Up 3"
+    $this SetOverlayCreatorInputs
+    #puts stdout "Cleaning Up 4"
+    ShowProgressVal  "Done" 0.0
+}
+
+# ---------------------------------------------------------------------------
+# mode = warp which returns a list of warped images or save which saves them!
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::WarpTasksToCommonSpace { mode { dirname "" } { saveanatomical 1 } } {
+
+    set savingfiles 1
+    set imagelist ""
+
+
+    if { $mode == "warp" } {
+	set savingfiles 0
+    } else {
+	# ------------------- Save Code ---------------------------------------
+	if { [ string length $dirname ] < 1 } {
+	    set dirname  [tk_chooseDirectory -title "Select Directory to output warped tasks Setup File" ]
+	}
+	
+	if { [ string length $dirname ] < 1 } {
+	    return 0
+	}
+	
+	if { [ file exists $dirname ] == 0 } {
+	    catch { file mkdir $dirname }
+	}
+	if { [ file exists $dirname ] == 0 } {
+	    ::pxtclutil::Warning "Cannot create directory $dirname"
+	    return 0 
+	}
+	
+	if { [ file writable $dirname ] == 0 } {
+	    ::pxtclutil::Warning "Cannot write in directory $dirname"
+	    return 0 
+	}
+
+	set tail1 "Common"
+	set fname_base [ file join $dirname $tail1 ]
+	# ------------------- End Save Code ---------------------------------------
+    }
+
+    set referenceImage  [ $reference_control GetObject ]
+
+    set beginsub 0
+    set endsub   [ expr [ llength $subjects ]  -1 ]
+
+    set interp 0
+    if { $thisparam($this,interpolation) == "Linear" } {
+	set interp 1 
+    } elseif { $thisparam($this,interpolation) == "Cubic" } {
+	set interp 3
+    }
+    
+    if { $endsub <= $beginsub } {
+	::pxtclutil::Warning "Cannot Warp Task Images as specified ($beginsub:$endsub)!"
+	return;
+    }
+
+    set ref_image [ $referenceImage  GetImage ]
+    set delete_ref_image 0
+    
+    if { $thisparam($this,outputresolution) != "Ref" } {
+	set sp 1.0
+	if { $thisparam($this,outputresolution) == "2.0x2.0x2.0" } {
+	    set sp 2.0
+	} elseif { $thisparam($this,outputresolution) == "3.0x3.0x3.0" } {
+	    set sp 3.0
+	} elseif { $thisparam($this,outputresolution) == "4.5x4.5x4.5" } {
+	    set sp 4.5
+	} elseif { $thisparam($this,outputresolution) == "1.5x1.5x1.5" } {
+	    set sp 1.5
+	}
+	ShowProgressVal "Resampling Reference to $sp x $sp x $sp" 0.01
+	set resl [ vtkImageResample [ pxvtable::vnewobj ] ]
+	$resl SetAxisOutputSpacing 0 $sp
+	$resl SetAxisOutputSpacing 1 $sp
+	$resl SetAxisOutputSpacing 2 $sp
+	$resl InterpolateOff
+	$resl SetDimensionality 3
+	$resl SetInput $ref_image 
+	$resl Update
+
+	set ref_image [ vtkImageData [ pxvtable::vnewobj ]]
+	$ref_image ShallowCopy [ $resl GetOutput ]
+	$resl Delete
+	set delete_ref_image 1
+    }
+
+    if { $debugprogress == 1 } {
+	puts stdout "ref_image  Dimensions = [ $ref_image GetDimensions ]"
+    }
+
+
+    set ctask $thisparam($this,current_task)
+
+    if { $savingfiles == 1 } {
+	# -------------------  Save Code ---------------------------------------
+	set fout [ open ${fname_base}_${ctask}_log.txt w ]
+	
+	puts $fout "Using Setup File: $setupfilename"
+	puts $fout "Saving task $thisparam($this,current_task) warped to reference space as defined by [ $referenceImage cget -filename ]"
+	puts $fout "Reference space dimensions [ $ref_image GetDimensions ], resolution [ $ref_image GetSpacing ]"
+	set anasave [ vtkpxAnalyzeImageWriter [ pxvtable::vnewobj ]]
+	$anasave SetImageHeader [ $referenceImage GetImageHeader ]
+
+	set hd [ $anasave GetImageHeader ]
+	set md [ $hd GetMode ]
+
+	#	puts stderr "ref hd=[ $hd GetMode ]"
+
+	# This is probably overkill
+	if { $md ==0 && $forceimageoutputformat == 2 } {
+	    $hd SetModeToNIFTI_HDRIMG
+	} elseif { $md > 0 && $forceimageoutputformat == 1 } {
+	    $hd SetModeToAnalyze
+	}
+	
+	set md [ $hd GetMode ]
+	switch -exact -- $md {
+	    "0" { set outmode "Analyze" }
+	    "1" { set outmode "Nifti .hdr/.img" }
+	    "2" { set outmode "Nifti .nii"}
+	}
+
+	#    $anasave SetOrientation [ $referenceImage GetOrientation ]
+
+	if { $saveanatomical == 1 } {
+	    $anasave SetInput $ref_image
+	    $anasave Save "${fname_base}_reference"
+
+	    puts $fout "Saving anatomical reference in ${fname_base}_reference (mode=$outmode)"
+	    pxtkprint "Saving anatomical reference in ${fname_base}_reference (mode=$outmode)\n"
+	} 
+	# -------------------  End Save Code ---------------------------------------
+    }
+    set util [ vtkpxUtil [ pxvtable::vnewobj ]]	
+    
+    set scalefactor [expr 1.0 / ( 1.0 + 1.0* ( $endsub-$beginsub +1 )) ]
+    set progress 0.0
+        
+    for { set i $beginsub } { $i <= $endsub } { incr i } {
+	
+	ShowProgressVal "Warping Tasks image=$i" $progress 
+	set subject [ lindex $subjects $i ]
+	set clean_trans 1
+	set value 0.0
+
+	set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+	$trans PostMultiply
+	$trans Concatenate [ [ $subject cget -reference_transform ] GetTransformation ]
+	$trans Concatenate [ [ $subject cget -internal_transform ] GetTransformation ]
+	$trans Concatenate [ [ $subject cget -distortion_transform ] GetTransformation ]
+	set trn_image [ [ $subject cget -functional_image ] GetImage ] 
+	puts stdout "\nDesc = [ [ $subject cget -functional_image ]  GetShortDescription ]"
+
+	set tmpimage($i)  [ vtkImageData [pxvtable::vnewobj ] ]
+
+	
+	set dd [ $trn_image GetNumberOfPoints ]
+	if { $dd > 2 } {
+	    set ok [ $util ResliceImage $tmpimage($i) $trn_image $ref_image $trans $interp $value ]
+	} else {
+	    set ok 0
+	    puts stderr "Bad Task image [ $trn_image GetDimensions ]"
+	}
+
+	if { $ok == 0 } {
+	    puts stderr "Making up an empty image to replace this ...."
+	    $tmpimage($i) CopyStructure $ref_image
+	    $tmpimage($i) SetNumberOfScalarComponents 1
+	    if { $i > $beginsub } {
+		$tmpimage($i) SetScalarType [ $tmpimage($beginsub) GetScalarType ]
+	    }
+	    $tmpimage($i) AllocateScalars
+	    [ [ $tmpimage($i) GetPointData ] GetScalars ] FillComponent 0 0.0 
+	}
+
+
+
+	
+	set progress [ expr $progress+$scalefactor ]
+
+	if { $debugprogress == 1 } {
+	    puts stdout "Image $i dimensions = [ $tmpimage($i) GetDimensions ] "
+	}
+
+	if { $savingfiles == 1 } {
+	    # -------------------   Save Code ---------------------------------------
+
+	    set subjnamef [ file tail [ [ $subject cget -functional_image ] cget -filename ] ]
+	    set md 2
+	    set ext [ file extension $subjnamef ]	
+	    if { $ext == ".gz" } {
+		set subjnamef [ file rootname $subjnamef ]
+		set ext [ file extension $subjnamef ]	
+		if { $ext == ".nii" } {
+		    set ext ".nii.gz"
+		}
+	    } 
+	    set subjnamef [ file rootname $subjnamef ]
+
+	    set hd [ $anasave GetImageHeader ]
+	    $hd CopyExtensionsOnly  [ [ $subject cget -functional_image ] GetImageHeader ]
+	    
+	    if { $ext ==".hdr" && $forceimageoutputformat == 2 } {
+		set md 1
+	    } elseif { $forceimageoutputformat == 1 } {
+		set md 0
+	    }  elseif { $ext == ".nii.gz"  || $forceimageoutputformat == 2 } {
+		set md 2
+	    } 
+
+	    switch -exact -- $md {
+		"0" { set outmode "Analyze"; set ext ".hdr";  $hd SetModeToAnalyze }
+		"1" { set outmode "Nifti .hdr/.img"; set ext ".hdr" ; $hd SetModeToNIFTI_HDRIMG }
+		"2" { set outmode "Nifti .nii"; set ext ".nii.gz" ; $hd SetModeToNIFTI_NII }
+	    }
+
+	    set finalname "${fname_base}_${subjnamef}_orig${ext}"
+	    
+	    $anasave SetInput $tmpimage($i)
+	    $anasave Save $finalname
+	    puts $fout "Saving warped task for subject [ expr $i +1 ]  in ${finalname} (mode=$outmode)"
+	    pxtkprint  "Saving warped task for subject [ expr $i +1 ]  in ${finalname} (mode=$outmode)\n"
+#	    puts stderr "Deleting temporary image $i"
+	    $tmpimage($i) Delete
+	    # ------------------- End Save Code ---------------------------------------
+	} else {
+	#    puts stderr "Appending temporary image $i"
+	    lappend imagelist $tmpimage($i) 
+	}
+	$trans Delete
+    }
+
+    if { $savingfiles == 1 } {
+	# ------------------- Save Code ---------------------------------------
+	close $fout
+	$anasave Delete 
+	set imagelist 0
+	# ------------------- End Save Code ---------------------------------------
+    }
+
+    if { $delete_ref_image == 1 } {
+	$ref_image Delete
+    }
+
+    $util Delete 
+    ShowProgressVal  "Done" 0.0
+
+    #    puts stderr "Returning $imagelist"
+
+    return $imagelist
+}
+
+# ------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::DoVOIAnalysis { fname appendmode } {
+    
+    if { [ string length $fname ] < 1 } {
+	set fname  [tk_getSaveFile -title "Output VOI File" -filetypes { {"VOI Text File" {.txt}}} ]
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    set referenceImage  [ $reference_control GetObject ]
+    set voiImage  [ $voi_control GetObject ]
+
+    set beginsub 0
+    set endsub   [ expr [ llength $subjects ]  -1 ]
+
+    set interp 0
+    if { $thisparam($this,interpolation) == "Linear" } {
+	set interp 1 
+    } elseif { $thisparam($this,interpolation) == "Cubic" } {
+	set interp 3
+    }
+    
+    if { [ $voiImage GetImageSize ] < 2 } {
+	::pxtclutil::Warning "Cannot Do VOI Analysis. Bad VOI Image"
+	return;
+    }
+
+    set ref_image [ $referenceImage  GetImage ]
+    if { [ $referenceImage GetImageSize ] < 2 } {
+	::pxtclutil::Warning "Cannot Do VOI Analysis. Bad Reference Image"
+	return;
+    }
+
+    
+    set util [ vtkpxUtil [ pxvtable::vnewobj ]]	
+    ShowProgressVal "Resampling VOI Image to Match Reference (using identity transform)" 0.01
+
+    set voi_img  [ vtkImageData [pxvtable::vnewobj ] ]
+    set ident    [ vtkIdentityTransform  [pxvtable::vnewobj ] ]
+    $util ResliceImage $voi_img [ $voiImage GetImage ] $ref_image $ident 0 -1
+    $ident Delete
+
+    
+    # ---------------------------------------------
+    # Somewhere here add code for voi names .......
+    # ---------------------------------------------
+
+    set mname [ $voiImage cget -filename ]
+    set tname [ ::pxtclutil::GenerateVOIFileNameFromImageName $mname ]
+    set mlist [ ::pxtclutil::LoadVOINamesList $tname 255 ]
+    array set voinames $mlist
+
+
+
+    if { $debugprogress == 1 } {
+	puts stdout "ref_image  Dimensions = [ $ref_image GetDimensions ]"
+    }
+
+    set thr [ vtkpxMergeFmriConventional [ pxvtable::vnewobj ]]
+    set arr [ vtkFloatArray [ pxvtable::vnewobj ]]
+
+    set ctask $thisparam($this,current_task) 
+    if { $fname != "_do_not_save" } {
+	if { $appendmode == 0 } {
+	    set fout [ open $fname w ]
+	    #       puts $fout "\#Subj ID\t Image Name \t Task \t Level \t Mean \t Sigma \t nvox \t volume(mm^3)\n"
+	    #       pxtkconsole
+	    #       pxtkprint "Starting VOI Analysis"
+	} else {
+	    set fout [ open $fname a ]
+	}
+    } else {
+	set fout 0
+    }
+    
+    pxtkprint "\#Doing VOI Analysis on task $thisparam($this,current_task)\n"
+    pxtkprint "\#Reference space dimensions [ $ref_image GetDimensions ], resolution [ $ref_image GetSpacing ]\n"
+    #    pxtkprint "\#Subj ID\t Image Name \t Task \t Level \t Mean \t Sigma \t nvox \t volume(mm^3)\n"
+
+
+    set scalefactor [expr 1.0 / ( 1.0 + 1.0* ( $endsub-$beginsub +1 )) ]
+    set progress 0.0
+
+    set ident [ vtkIdentityTransform [pxvtable::vnewobj ]]
+
+    set outimg [ vtkImageData New ]
+    $outimg SetScalarTypeToFloat
+
+        
+    for { set i $beginsub } { $i <= $endsub } { incr i } {
+	
+	ShowProgressVal "Warping Tasks image=$i" $progress 
+	set subject [ lindex $subjects $i ]
+	set clean_trans 1
+	set value 0.0
+
+	set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+	$trans PostMultiply
+	$trans Concatenate [ [ $subject cget -reference_transform ] GetTransformation ]
+	$trans Concatenate [ [ $subject cget -internal_transform ] GetTransformation ]
+	$trans Concatenate [ [ $subject cget -distortion_transform ] GetTransformation ]
+	set trn_image [ [ $subject cget -functional_image ] GetImage ] 
+	set name      [ $subject  GetBaseName ]
+	
+	set tmpimage($i)  [ vtkImageData [pxvtable::vnewobj ] ]
+	$util ResliceImage $tmpimage($i) $trn_image $ref_image $trans $interp $value
+	set progress [ expr $progress+$scalefactor ]
+
+	set numberofframes [ $tmpimage($i) GetNumberOfScalarComponents ]
+	
+	if { $debugprogress == 1 } {
+	    puts stdout "Image $i dimensions = [ $tmpimage($i) GetDimensions ] "
+	}
+	
+	puts stderr "Doing ROI Stats [ $tmpimage($i) GetDimensions ]"
+	set nt [  $thr ComputeROIStatistics $tmpimage($i) $voi_img $ident $arr ]
+	set subjnamef [ file root [ file tail [ [ $subject cget -functional_image ] cget -filename ] ] ]
+	
+#	for { set aa 0 } { $aa < [ $arr GetNumberOfTuples ] } { incr aa } {
+#	    for { set ab 0 } { $ab < [ $arr GetNumberOfComponents ] } { incr ab } {
+#		puts stdout "Component $aa,$ab= [ $arr GetComponent $aa $ab]"
+#	    }
+#	}
+
+
+	if { $i == $beginsub } {
+	    #	    puts stdout "Output ROI Image Dimensions = [ expr $endsub-$beginsub +1 ] $numberofframes [ $arr GetNumberOfTuples ]"
+	    $outimg SetDimensions [ expr $endsub-$beginsub + 2 ] [ expr $numberofframes + 1 ] [ expr [ $arr GetNumberOfTuples ] + 1 ]
+	    $outimg AllocateScalars 
+	    [ [ $outimg GetPointData ] GetScalars ] FillComponent 0 0.0
+	}
+
+	if { $appendmode == 0 && $i == $beginsub } {
+	    set line "\#Subj ID\t Image Name \t Task "
+	    if { $numberofframes > 1 } {
+		set line "$line\t Frame"
+	    }
+	
+	    for { set j 0 } { $j < [ $arr GetNumberOfTuples ] } { incr j } {
+		set n1 [ expr int([ $arr GetComponent $j 2 ])]
+		set a2 [ expr round([ $arr GetComponent $j 1 ])]
+		set frame [ $arr GetComponent $j 0 ]
+		set rname "Region $a2"
+		catch { set rname $voinames($a2) }
+		if { $n1 > 0 && $a2 > 0 && $frame == 0 } {
+		    set line "$line \t $rname "
+		} else {
+		    puts stderr "Ignoring VOI $rname "
+		}
+		    
+	    }
+	    if { $fout !=0 } {	    puts $fout "$line\n" }
+	    pxtkprint "$line\n"
+	}
+	
+	set front "$name \t $subjnamef \t $ctask"
+	puts stdout $front
+	
+	for { set fr 0 } { $fr < $numberofframes } { incr fr } { 
+	    pxtkprint "$front"
+	    if { $fout != 0 } {	puts -nonewline $fout $front } 
+
+	    if { $numberofframes > 1 } {
+		set line [ expr $fr +1 ]
+		if { $fout !=0 } { puts  -nonewline $fout "\t$line" }
+		pxtkprint "\t$line"
+	    }
+	    
+	    for { set j 0 } { $j < [ $arr GetNumberOfTuples ] } { incr j } {
+		set mean  [ $arr GetComponent $j 3 ]
+		set frame [ $arr GetComponent $j 0 ]
+		set n1 [ expr int([ $arr GetComponent $j 2 ])]
+		set a2 [ expr round([ $arr GetComponent $j 1 ])]
+		set rname "Region $a2"
+		catch { set rname $voinames($a2) }
+
+		if { $fr == $frame && $n1 > 0 && $a2 > 0 } {
+		    set line [ format "\t%9.4f" $mean ]
+		    if { $fout !=0 } { puts  -nonewline $fout "$line" }
+		    pxtkprint "$line"
+		    #puts "$outimg SetScalarComponentFromDouble [ expr $i - $beginsub ] $fr $j 0 $mean"
+		    $outimg SetScalarComponentFromDouble [ expr $i - $beginsub ] $fr $j 0 $mean
+		} else {
+		    puts stderr "Ignoring VOI $rname frame=$fr, n1=$n1 "
+		}
+	    }
+	    if { $fout !=0 } { puts $fout " " }
+	    pxtkprint "\n"
+	}
+	$trans Delete
+	$tmpimage($i) Delete
+    }
+    if { $fout !=0 } { 
+	close $fout
+    }
+    $ident Delete
+    $voi_img Delete
+    $util Delete 
+    $arr  Delete 
+    $thr  Delete
+    ShowProgressVal  "Done" 0.0
+
+    if { $fname == "_do_not_save" } {
+	puts stdout "Returning image dimensions = [ $outimg GetDimensions ]"
+	return $outimg
+    }
+    
+    $outimg Delete
+    return 1
+
+}
+
+# ------------------------------------------------------------------
+#   Batch Mode Operations
+# ------------------------------------------------------------------
+
+itcl::body pxitclmultisubjectaverage::SelectTasksToProcess { comment } {
+
+    set l ""
+    for { set i 0 } { $i < [ llength $tasks ] } { incr i } {
+	set tmp [ lindex $tasks $i ]
+	lappend l "[ $tmp cget -task_name ]:[$tmp cget -task_suffix ]"
+    }
+    
+    $batch_selector Activate $l "" $comment "Select Tasks"
+    return [ $batch_selector GetSelectedIndices ]
+}
+
+itcl::body pxitclmultisubjectaverage::SelectSubjectsToProcess { comment } {
+
+    set l ""
+    for { set i 0 } { $i < [ llength $subjects ] } { incr i } {
+	set tmp [ lindex $subjects $i ]
+	lappend l [ $tmp GetBaseName ]
+    }
+    
+    $batch_selector Activate $l "" $comment "Select Subjects"
+    return [ $batch_selector GetSelectedIndices ]
+}
+
+
+# ------------------------------------------------------------------------------
+
+itcl::body pxitclmultisubjectaverage::ComputeAllResults { mode } { 
+
+    LoadAll 0
+    set numtasks [llength $tasks]
+    if { $mode == 0 } {
+	set nmode Functional
+	set dmode "Average Tmaps"
+    }
+    
+    set comment  "Select taks to compute $dmode images using the current parameters. This will take a while! Are you sure?"
+    set lst [ SelectTasksToProcess $comment ]
+
+    if { [ string length $lst ] ==0 } {
+	return
+    }
+
+    set thisparam($this,autosave) 1
+    pxtkconsole
+
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	set c [ lindex $lst $i ]
+	pxtkprint "Beginning Computation for task [ expr $c +1 ] ($lst)"
+	$task_listbox selection clear 0 [ expr $numtasks -1 ]
+	$task_listbox selection set $c $c
+	ChangeCurrentTask $task_listbox "silent"
+	ComputeAverages $nmode
+    }
+}
+# ------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::Create4DImageForSingleFrameAndCurrentTask { imglist fr  { roimeanalg 0 } } {
+
+    set appnd [ vtkImageAppendComponents New ]	
+    set nc [ [ lindex $imglist 0 ] GetNumberOfScalarComponents ]
+    #    pxtkprint "\nCreating 4D Image for task [ expr $c +1 ], $ctask and frame [ expr $fr + 1 ]\n"
+    set numfiles [ llength $imglist ]
+    for { set k 0 } { $k < $numfiles } { incr k } {
+	set img [ lindex $imglist $k ]
+	if { $nc > 1 } {
+	    #		    puts stderr "fr=$fr, k=$k, nc=$nc, img=$img"
+	    #		    puts stderr "img=$img [ $img GetClassName ] [ $img GetDimensions ], [ $img GetNumberOfScalarComponents ]"
+	    set ext [ vtkImageExtractComponents  New ]
+	    $ext SetInput  $img
+	    $ext SetComponents $fr
+	    $ext Update
+	    $appnd AddInput [ $ext GetOutput ]
+	    $ext Delete
+	} else {
+	    $appnd AddInput  $img
+	}
+    }
+    $appnd Update
+    
+    set comb [ [ pxitclimage \#auto ] GetThisPointer ]
+    $comb ShallowCopyImage [ $appnd GetOutput ]
+
+    set referenceImage [ $reference_control GetObject ]
+    $comb CopyImageHeader [ $referenceImage GetImageHeader ]
+    
+    if { $roimeanalg != 0 } {
+	#	puts stdout "Here [ $comb GetShortDescription ]"
+	$roimeanalg SetInput $comb
+	set voiImage  [ $voi_control GetObject ]
+	$roimeanalg SetSecondInput $voiImage
+	$roimeanalg SetOptionValue dotextfile 0
+	$roimeanalg SetOptionValue addregion 0
+	$roimeanalg SetOptionValue fullsizeoutput 1
+	$roimeanalg Execute
+	$comb ShallowCopy [ $roimeanalg GetOutput ]
+    }
+    $appnd Delete
+    return $comb
+}
+# ------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::Create4DImagesAllTasks { mode } { 
+
+    LoadAll 0
+    set lst [ SelectTasksToProcess "Select taks to warp individual subject task images to the create common 4d images using the current transformations and resolution settings. This will take a while! Are you sure?"]
+    if { [ string length $lst ] == 0 } {
+	return 0
+    }
+
+    set dirname  [tk_chooseDirectory -title "Select Directory to output warped tasks Setup File" ]
+    if { [ string length $dirname ] < 1 } {
+	return 0
+    }
+
+    set oldmode $thisparam($this,outputresolution) 
+    set roimeanalg 0
+    if { $mode == "voi" } {
+	set thisparam($this,outputresolution) "Ref"
+	set voiImage  [ $voi_control GetObject ]
+	if { [ $voiImage GetImageSize ] < 2 } {
+	    ::pxtclutil::Warning "Cannot Do VOI Warp. Bad VOI Image"
+	    return 0
+	}
+    	set roimeanalg [ [ bis_roimean \#auto ] GetThisPointer ]
+	$roimeanalg InitializeFromContainer $this
+    }
+
+    set numtasks [llength $tasks]
+    pxtkconsole
+
+#    puts stderr "lst=$lst"
+
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	set c [ lindex $lst $i ]
+	$task_listbox selection clear 0 [ expr $numtasks -1 ]
+	$task_listbox selection set $c $c
+	ChangeCurrentTask $task_listbox "silent"
+	set imglist [ WarpTasksToCommonSpace warp $dirname 0 ]
+
+	set numfiles [ llength $imglist ]
+	set ctask $thisparam($this,current_task)	    
+
+	set nc [ [ lindex $imglist 0 ] GetNumberOfScalarComponents ]
+	set sname [  file tail [ file rootname $setupfilename ]]
+		
+	for { set fr 0 } { $fr < $nc } { incr fr } {
+	    set comb [ $this Create4DImageForSingleFrameAndCurrentTask $imglist $fr $roimeanalg ]
+	    
+	    set suffix $ctask
+	    if { $nc > 1 } {
+		set suffix [ format "%s_%03d" $ctask [ expr $fr +1 ] ]
+	    }
+
+	    if { $mode == "voi" } {
+		append suffix "_voi"
+	    }
+	    set fname [ file join $dirname "${sname}_${suffix}.nii.gz" ]
+
+	    set ok [ $comb Save $fname ]
+	    itcl::delete object $comb 
+	    
+	    if { $fr == 0 } {
+		set tname [ file join $dirname "${sname}_${ctask}.txt" ]
+		set fileid [open $tname w]
+		puts $fileid "\# Subject Order "
+		for { set k 0 } { $k < $numfiles } { incr k } {
+		    set tmp [ lindex $subjects $k ]
+		    puts $fileid "[ $tmp cget -subject_id ] \t [ [ $tmp cget -functional_image ] cget -filename ] \t [ [ [ $tmp cget -functional_image ] GetImage ] GetDimensions ]"
+		}
+		close $fileid
+		pxtkprint "\t Combined Saved in $fname, details in $tname\n"
+	    } else {
+		pxtkprint "\t Combined Saved in $fname\n"
+	    }
+	}
+	
+	# cleanup
+	for { set ai 0 } { $ai < [ llength $imglist ] } { incr ai } {
+	    [ lindex $imglist $ai ] Delete
+	}
+    }
+
+    set thisparam($this,outputresolution)  $oldmode
+    if { $roimeanalg !=0 } {
+	itcl::delete object $roimeanalg
+    }
+}
+# ------------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::Create4DImagesAllTasksOld { mode } { 
+
+#    puts stdout "Loading all ............."
+    LoadAll 0
+#    puts stdout "Loading all done ............."
+    set lst [ SelectTasksToProcess "Select taks to warp individual subject task images to the create common 4d images using the current transformations and resolution settings. This will take a while! Are you sure?"]
+    if { [ string length $lst ] == 0 } {
+	return 0
+    }
+
+    set dirname  [tk_chooseDirectory -title "Select Directory to output warped tasks Setup File" ]
+    if { [ string length $dirname ] < 1 } {
+	return 0
+    }
+
+    set oldmode $thisparam($this,outputresolution) 
+    set roimeanalg 0
+    if { $mode == "voi" } {
+	set thisparam($this,outputresolution) "Ref"
+	set voiImage  [ $voi_control GetObject ]
+	if { [ $voiImage GetImageSize ] < 2 } {
+	    ::pxtclutil::Warning "Cannot Do VOI Warp. Bad VOI Image"
+	    return 0
+	}
+    	set roimeanalg [ [ bis_roimean \#auto ] GetThisPointer ]
+	$roimeanalg InitializeFromContainer $this
+    }
+
+    set numtasks [llength $tasks]
+    pxtkconsole
+
+#    puts stderr "lst=$lst"
+
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	set c [ lindex $lst $i ]
+	$task_listbox selection clear 0 [ expr $numtasks -1 ]
+	$task_listbox selection set $c $c
+#	puts stdout "Changing task ............."
+	ChangeCurrentTask $task_listbox "silent"
+#	puts stdout "Changing task done ............."
+	set imglist [ WarpTasksToCommonSpace warp $dirname 0 ]
+#	puts stdout "Warp task done ............."
+
+	set numfiles [ llength $imglist ]
+	set ctask $thisparam($this,current_task)	    
+
+	set nc [ [ lindex $imglist 0 ] GetNumberOfScalarComponents ]
+	set sname [  file tail [ file rootname $setupfilename ]]
+		
+	for { set fr 0 } { $fr < $nc } { incr fr } {
+	    set appnd [ vtkImageAppendComponents New ]	
+	    pxtkprint "\nCreating 4D Image for task [ expr $c +1 ], $ctask and frame [ expr $fr + 1 ]\n"
+	    for { set k 0 } { $k < $numfiles } { incr k } {
+		set img [ lindex $imglist $k ]
+		if { $nc > 1 } {
+		    #		    puts stderr "img=$img [ $img GetClassName ] [ $img GetDimensions ], [ $img GetNumberOfScalarComponents ]"
+		    set ext [ vtkImageExtractComponents  New ]
+		    $ext SetInput  $img
+		    $ext SetComponents $fr
+		    $ext Update
+		    $appnd AddInput [ $ext GetOutput ]
+		    $ext Delete
+		} else {
+		    $appnd AddInput  $img
+		}
+	    }
+	    $appnd Update
+	
+	    set comb [ [ pxitclimage \#auto ] GetThisPointer ]
+	    $comb ShallowCopyImage [ $appnd GetOutput ]
+	    
+	    set referenceImage [ $reference_control GetObject ]
+	    $comb CopyImageHeader [ $referenceImage GetImageHeader ]
+	    
+	    set suffix $ctask
+	    if { $nc > 1 } {
+		set suffix [ format "%s_%03d" $ctask [ expr $fr +1 ] ]
+	    }
+
+	    if { $mode == "voi" } {
+		append suffix "_voi"
+		
+		$roimeanalg SetInput $comb
+		$roimeanalg SetSecondInput $voiImage
+		$roimeanalg SetOptionValue dotextfile 0
+		$roimeanalg SetOptionValue addregion 0
+		$roimeanalg SetOptionValue fullsizeoutput 1
+		$roimeanalg Execute
+		$comb ShallowCopy [ $roimeanalg GetOutput ]
+	    }
+	    set fname [ file join $dirname "${sname}_${suffix}.nii.gz" ]
+
+	    set ok [ $comb Save $fname ]
+	    itcl::delete object $comb 
+	    $appnd Delete
+	    
+	    if { $fr == 0 } {
+		set tname [ file join $dirname "${sname}_${ctask}.txt" ]
+		set fileid [open $tname w]
+		puts $fileid "\# Subject Order "
+		for { set k 0 } { $k < $numfiles } { incr k } {
+		    set tmp [ lindex $subjects $k ]
+		    puts $fileid "[ $tmp cget -subject_id ] \t [ [ $tmp cget -functional_image ] cget -filename ] \t [ [ [ $tmp cget -functional_image ] GetImage ] GetDimensions ]"
+		}
+		close $fileid
+		pxtkprint "\t Combined Saved in $fname, details in $tname\n"
+	    } else {
+		pxtkprint "\t Combined Saved in $fname\n"
+	    }
+	}
+	
+	# cleanup
+	for { set ai 0 } { $ai < [ llength $imglist ] } { incr ai } {
+	    [ lindex $imglist $ai ] Delete
+	}
+    }
+
+    set thisparam($this,outputresolution)  $oldmode
+    if { $roimeanalg !=0 } {
+	itcl::delete object $roimeanalg
+    }
+}
+# ------------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::WarpAllTasks { mode } { 
+
+    LoadAll 0
+    set lst [ SelectTasksToProcess "Select taks to warp individual subject task images to the common space using the current transformations and resolution settings. This will take a while! Are you sure?"]
+    if { [ string length $lst ] == 0 } {
+	return 0
+    }
+
+    set dirname  [tk_chooseDirectory -title "Select Directory to output warped tasks Setup File" ]
+    if { [ string length $dirname ] < 1 } {
+	return 0
+    }
+
+    set numtasks [llength $tasks]
+    pxtkconsole
+
+
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	set c [ lindex $lst $i ]
+	pxtkprint "Beginning Computation for task [ expr $c +1 ]"
+	$task_listbox selection clear 0 [ expr $numtasks -1 ]
+	$task_listbox selection set $c $c
+	ChangeCurrentTask $task_listbox "silent"
+	if { $i == 0 } {
+	    WarpTasksToCommonSpace save $dirname 1
+	} else {
+	    WarpTasksToCommonSpace save $dirname 0
+	}
+    }
+}
+# ------------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::DoVOIAnalysisAllTasks { mode } { 
+
+    LoadAll 0
+    set lst [ SelectTasksToProcess "Select taks to perform VOI Analysis On" ]
+    if { [ string length $lst ] == 0 } {
+	return 0
+    }
+
+    set fname  [tk_getSaveFile -title "Output VOI File" -filetypes { {"VOI Text File" {.txt}}} ]
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+
+    set numtasks [llength $tasks]
+    pxtkconsole
+
+
+    for { set i 0 } { $i < [ llength $lst ] } { incr i } {
+	set c [ lindex $lst $i ]
+	pxtkprint "Beginning Computation for task [ expr $c +1 ]"
+	$task_listbox selection clear 0 [ expr $numtasks -1 ]
+	$task_listbox selection set $c $c
+	ChangeCurrentTask $task_listbox "silent"
+	if { $i == 0 } {
+	    DoVOIAnalysis $fname 0
+	} else {
+	    DoVOIAnalysis $fname 1
+	}
+    }
+}
+# ------------------------------------------------------------------------------
+
+
+# itcl::body pxitclmultisubjectaverage::ComputeAllRegistrations { mode secondmode } { 
+
+#     LoadAll 0
+#     set lmode "inter-subject registrations"
+#     if { $mode == 2 } {
+# 	set lmode "within-subject registrations"
+#     }
+
+#     set lst [ SelectSubjectsToProcess "Select subjects to compute $lmode using the current transformations and resolution settings. This will take a long time! Are you sure? (Press Cancel to change the parameters!)"]
+#     if { [ string length $lst ] == 0 } {
+# 	$external_overlayutility DisableRegistrationButtons
+# 	if { $mode == "nonlinear" } {
+# 	    $external_overlayutility ShowWindow  "NonLinear Reg" 
+# 	} elseif { $mode == "distortion" } {
+# 	    $external_overlayutility ShowWindow  "Distortion Cor" 
+# 	} else {
+# 	    $external_overlayutility ShowWindow  "Linear Reg"	
+# 	}
+# 	return 
+#     }
+
+#     set dirname  [tk_chooseDirectory -title "Select Directory to Save Registrations In" ]
+#     if { [ string length $dirname ] < 1 } {
+# 	return 0
+#     }
+
+#     pxtkconsole
+#     pxtkprint "\n\nBeginning computation of all $lmode"
+
+#     $external_overlayutility SetAutoSave 0
+
+#     for { set sub 0 } { $sub < [ llength $lst ] } { incr sub } {
+	
+# 	SetNewSubject [ lindex $lst $sub ]
+# 	ComputeRegistrationCallback $mode "donotshowcontrols"
+	
+# 	if { $secondmode == "nonlinear" } {
+# 	    $external_overlayutility ComputeCombinedRegistration "Registration"
+# 	} elseif { $secondmode == "distortion" } {
+# 	    $external_overlayutility ComputeCombinedRegistration "Distortion"
+# 	} else {
+# 	    $external_overlayutility ComputeAffineRegistration
+# 	}
+
+# 	GrabRegistrationCallback $mode $dirname
+
+# 	pxtkprint "Done with Subject [ expr $sub +1 ] \n ---------------------------------------------------\n\n"
+#     }
+
+#     $external_overlayutility SetAutoSave 1
+# }
+
+# ------------------------------------------------------------------
+#  Verify Registration Stuff
+# ------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::VerifyRegistrationCallback { mode args } { 
+
+    switch -exact -- $mode { 
+	1 {
+	    set image_ref  [ $reference_control GetObject ]
+	    set image_trn  [ $anat_control GetObject ] 
+	    set tr         [ $refx_control GetObject ]
+	} 
+	2 {
+	    set image_ref [ $anat_control GetObject ] 
+	    set image_trn [ $conv_control GetObject ] 
+	    set tr        [  $intx_control GetObject ]
+	}
+	3 { 
+	    set image_ref [  $conv_control GetObject ] 
+	    set image_trn [  $epi_control GetObject ] 
+	    set tr        [  $distx_control GetObject ]
+	} 
+    }
+
+    set orient_ref [ $image_ref GetOrientation ]
+    set orient_trn [ $image_trn GetOrientation ]
+    
+    set dim1 [ [ $image_ref GetImage ] GetDimensions ]
+    set dim2 [ [ $image_trn GetImage ] GetDimensions ]
+    if { [lindex $dim2 0 ] <2 || [ lindex $dim1 0 ] < 2 } { 
+	::pxtclutil::Warning "No Images in Memory\n Cannot Verify Transformation!"
+	return  0
+    }
+
+    WatchOn
+
+    set ut [ vtkpxUtil [ pxvtable::vnewobj ]]
+
+    set tmp  [ [  pxitclimage \#auto ] GetThisPointer ]
+    $ut ResliceImage [ $tmp GetImage ] [ $image_trn GetImage ] [ $image_ref GetImage ] [ $tr GetTransformation ] 1 0.0
+    
+    $tmp CopyImageHeader [ $image_ref GetImageHeader ]
+    set f1 [ file tail [ file root [ $image_ref cget -filename ]]]
+
+    $tmp configure -filename "warpto_${f1}_[ file tail [$image_trn cget -filename ]]"
+
+    $parent SetImageFromObject $image_ref $this
+    $second_viewer SetImageFromObject $tmp $this
+    catch { itcl::delete object $tmp }
+    
+    WatchOff
+    return 1
+}
+
+# ------------------------------------------------------------------
+#  Compute Registration Stuff
+# ------------------------------------------------------------------
+# itcl::body pxitclmultisubjectaverage::ComputeRegistrationCallback { mode args } { 
+
+#     if { [ llength $args] > 0 } {
+# 	set smode [ lindex $args 0 ]
+#     }
+
+
+#     switch -exact -- $mode { 
+# 	1 {
+# 	    set image_ref [ $reference_control GetObject ]
+# 	    set image_trn [ $anat_control GetObject ] 
+# 	    set swindow "NonLinear Reg"
+# 	} 
+# 	2 {
+# 	    set image_ref  [ $anat_control GetObject ] 
+# 	    set image_trn [ $conv_control GetObject ]
+# 	    set swindow "Linear Reg"
+# 	}
+# 	3 {
+# 	    set image_ref [ $conv_control GetObject ]
+# 	    set image_trn  [ $epi_control GetObject ] 
+# 	    set swindow "Distortion Cor"
+# 	} 
+	
+#     }
+
+#     set dim1 [ [ $image_ref GetImage ] GetDimensions ]
+#     set dim2 [ [ $image_trn GetImage ] GetDimensions ]
+#     if { [lindex $dim2 0 ] <2 || [ lindex $dim1 0 ] < 2 } { 
+# 	::pxtclutil::Warning "No Images in Memory\n Cannot Compute Transformation!"
+# 	return  0
+#     }
+
+#     $parent SetImageFromObject $image_ref $this
+#     $second_viewer SetImageFromObject $image_trn $this
+    
+#     if { $smode != "donotshowcontrols" } {
+# 	$external_overlayutility EnableRegistrationButtons
+# 	$external_overlayutility ShowWindow $swindow
+#     }
+
+#     return 1
+# }
+# ------------------------------------------------------------------------------------------------
+
+itcl::body pxitclmultisubjectaverage::GrabRegistrationCallback { mode args } { 
+
+    set pathname ""
+    if { [ llength $args ] > 0 } {
+	set pathname [ lindex $args 0 ]
+    }
+
+    switch -exact -- $mode {
+	1 {
+	    set t_control $refx_control
+	    set image_ref [ $reference_control GetObject ]
+	    set image_trn [ $anat_control GetObject ] 
+	}
+	2 { 
+	    set t_control $intx_control
+	    set image_ref  [ $anat_control GetObject ] 
+	    set image_trn [ $conv_control GetObject ]
+	} 
+	3 {
+	    set t_control $distx_control
+	    set image_ref  [ $conv_control GetObject ] 
+	    set image_trn [ $epi_control GetObject ]
+	}
+    }
+	
+    set tr [ [ $external_overlayutility GetTransformation ] GetTransformation ]
+    [ $t_control GetObject ]  CopyTransformation $tr
+
+    if { $pathname == "" } {
+	set mname [ [ $external_overlayutility GetTransformation ] cget -filename ]
+	if { [ string length $mname  ] > 0 } {
+	    [ $t_control GetObject ]  configure -filename $mname 
+	    $t_control Update
+	    return 1
+	} 
+	set n1  [ file rootname [ $image_ref cget -filename ]]	
+    } else {
+	set n1 [ file tail [ file rootname [ $image_ref cget -filename ]]]
+    }
+    
+    set n2 [ file tail [ file rootname [ $image_trn cget -filename ]]] 
+    set suffix "matr"
+
+    if { [ $tr IsA "vtkGridTransform" ] == 1 } {
+	set suffix "grd"
+    } elseif { [ $tr IsA "vtkpxComboTransform" ] == 1 } {
+	set suffix "grd"
+    } elseif { [ $tr IsA "vtkThinPlateSplineTransform" ] == 1 } {
+	set suffix "tps"
+    }
+    
+    set mname [ file join $pathname "${n1}_${n2}.${suffix}" ]
+    
+    
+    set ok 1
+    
+    if { [ file exists $mname ] == 1} {
+	if { [ pxtclutil::Question "Saving Transformation Will overwrite existing file $mname" ] == 1 } {
+	    [ $t_control GetObject ] Save $mname 
+	} else {
+	    [ $t_control GetObject ] configure -filename $mname 
+	}
+    } else {
+	[ $t_control GetObject ] Save $mname 
+    }
+    $t_control Update
+    return 1
+}
+
+# ------------------------------------------------------------------
+# Compare Tool Stuff
+# ------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::ShowCompareTool { } {
+    $external_overlayutility ShowWindow  "Image Compare" 
+}
+
+itcl::body pxitclmultisubjectaverage::SetInfoToCompareTool { mode2 } {
+    
+
+
+    if { $mode2 ==1 || $mode2 == 2 } {
+	$external_overlayutility ShowWindow  "Image Compare" 
+	[ $external_overlayutility GetCompareUtility ]  SetCompareMean${mode2}  [ lindex $outputimages 2 ]
+	[ $external_overlayutility GetCompareUtility ] SetCompareSigma${mode2} [ lindex $outputimages 3 ]
+	[ $external_overlayutility GetCompareUtility ] SetCompareN${mode2}     [ llength $subjects ]
+	return
+    }
+
+    if { $last_subject == - 1 } {
+	::pxtclutil::Warning "No subject is currently selected!"
+	return
+    }
+
+    set referenceImage [ $reference_control GetObject ]
+    set interp 0
+    if { $thisparam($this,interpolation) == "Linear" } {
+	set interp 1 
+    } elseif { $thisparam($this,interpolation) == "Cubic" } {
+	set interp 3
+    }
+
+    set ref_image [ $referenceImage  GetImage ]
+    set delete_ref_image 0
+    
+    if { $thisparam($this,outputresolution) != "Ref" } {
+	set sp 1.0
+	if { $thisparam($this,outputresolution) == "2.0x2.0x2.0" } {
+	    set sp 2.0
+	} elseif { $thisparam($this,outputresolution) == "3.0x3.0x3.0" } {
+	    set sp 3.0
+	} elseif { $thisparam($this,outputresolution) == "4.5x4.5x4.5" } {
+	    set sp 4.5
+	} elseif { $thisparam($this,outputresolution) == "1.5x1.5x1.5" } {
+	    set sp 1.5
+	}
+	ShowProgressVal "Resampling Reference to $sp x $sp x $sp" 0.01
+	set resl [ vtkImageResample [ pxvtable::vnewobj ] ]
+	$resl SetAxisOutputSpacing 0 $sp
+	$resl SetAxisOutputSpacing 1 $sp
+	$resl SetAxisOutputSpacing 2 $sp
+	$resl InterpolateOff
+	$resl SetDimensionality 3
+	$resl SetInput $ref_image 
+	$resl Update
+
+	set ref_image [ vtkImageData [ pxvtable::vnewobj ]]
+	$ref_image ShallowCopy [ $resl GetOutput ]
+	$resl Delete
+	set delete_ref_image 1
+    }
+
+
+
+    set util [ vtkpxUtil [ pxvtable::vnewobj ]]	
+    set value    0.0
+    set valueout 0.0
+
+    
+    set subject [ lindex $subjects $last_subject ]
+    set trans [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+    $trans PostMultiply
+    $trans Identity
+    $trans Concatenate [ [ $subject cget -reference_transform ] GetTransformation ]
+    $trans Concatenate [ [ $subject cget -internal_transform ] GetTransformation ]
+    $trans Concatenate [ [ $subject cget -distortion_transform ] GetTransformation ]
+    set trn_image [ [ $subject cget -functional_image ] GetImage ] 
+
+    set tmp  [ vtkImageData [pxvtable::vnewobj ] ]
+    set tmp2  [ vtkImageData [pxvtable::vnewobj ] ]
+
+    set maskim  [ vtkImageData [pxvtable::vnewobj ] ]
+    $maskim CopyStructure $trn_image
+    $maskim AllocateScalars
+    [ [ $maskim GetPointData ] GetScalars ] FillComponent 0 0.05
+	
+    $util ResliceImage $tmp $trn_image $ref_image $trans $interp $value
+    $util ResliceImage $tmp2 $maskim  $ref_image $trans $interp 0.0
+
+    $maskim Delete
+
+    set newtmp  [ [  pxitclimage \#auto ] GetThisPointer ]
+    set newtmp2  [ [  pxitclimage \#auto ] GetThisPointer ]
+    $newtmp ShallowCopyImage $tmp
+    $newtmp CopyImageHeader [ $referenceImage GetImageHeader ]
+    $newtmp  configure -filename "Single_Subject_[ $subject GetBaseName]"
+
+
+    $newtmp2 configure -filename "None_specified"
+    $newtmp2 ShallowCopyImage $tmp2
+
+
+    $external_overlayutility ShowWindow  "Image Compare" 
+    [ $external_overlayutility GetCompareUtility ] SetCompareMean2  $newtmp
+    [ $external_overlayutility GetCompareUtility ] SetCompareSigma2 $newtmp2
+    [ $external_overlayutility GetCompareUtility ] SetCompareN2     1
+
+    catch { itcl::delete object $newtmp  }
+    catch { itcl::delete object $newtmp2 }
+
+    if { $delete_ref_image == 1 } {
+	$ref_image Delete
+    }
+    $tmp2 Delete
+    $tmp Delete
+}
+
+
+
+# ------------------------------------------------------------------
+# New Task Name
+# ------------------------------------------------------------------
+
+itcl::body pxitclmultisubjectaverage::ChangeCurrentTask { tasklistbox args }  {
+
+    set olselect $output_listbox_lastselected 
+    set newindex [ $tasklistbox curselection ]
+    if { [ llength $newindex ] < 1 } {
+	return 0
+    }
+
+    set newsuffix [ [ lindex $tasks $newindex ] cget -task_suffix ]
+    #puts stderr "New Suffix = $newsuffix, index=$newindex"
+
+    set oldsuffix $thisparam($this,current_task) 
+    set mode "vocal"
+    if { [ llength $args]  > 0 } {
+	set mode [ lindex $args 0 ]
+    }
+
+
+    if { $newsuffix == "" } {
+	if { $mode == "vocal" } {
+	    puts stderr "No new task selected!"
+	}
+	return 0
+    }
+
+    if { $newsuffix == $oldsuffix } {
+#	if { $mode == "vocal" } {
+#	    pxtclutil::Warning "New task is the same as the old task!"
+#	}
+	return 1;
+    }
+
+    if { $mode == "vocal" } {
+	puts stdout "Selecting new task: changing suffix from $oldsuffix to $newsuffix"
+    }
+    ShowProgressVal "Renaming functional images" 0.0
+
+    set progress 0.0
+    set total [ expr [ llength $subjects ] + 3 ]
+    set scalefactor [expr 1.0 / $total ]
+
+
+    for { set sub 0 } { $sub < $total} { incr sub } {
+
+	if { $sub < [ llength $subjects ] } {
+	    set current [ lindex $subjects $sub ] 
+	    set functional [ $current cget -functional_image ]
+	} else {
+	    set index [ expr $sub - [ llength $subjects ] + 2 ]
+	    set functional [ lindex $outputimages $index ]
+	}
+
+	set f   [ $functional cget -filename ]	
+	set f2  $f
+	set ind [ string last $oldsuffix $f ]
+	set load 0
+	
+	if { $ind >=0 } {
+	    regsub -start $ind $oldsuffix $f $newsuffix f2
+	    $functional configure -filename $f2
+	    pxtkprint "Renaming [ file tail $f ]  to [ file tail $f2]"
+	    set okf 0
+	    if { $mode=="vocal" } {
+		puts stdout "Renaming [ file tail $f ]  to [ file tail $f2]"
+	    }
+	    if { [ file exists $f2 ] } {
+		set okf [ $functional Load ]
+		pxtkprint " ******* and loading\n"
+		set load 1
+	    } else {
+		::pxtclutil::Warning "File $f2 does not exist"
+		$functional configure -filename $f2
+		set okf 0
+	    }
+
+	    if { $okf == 0 } {
+		set img [ vtkImageData New ]
+		$img SetDimensions 2 2 2
+		$img SetSpacing 200 200 200
+		$img AllocateScalars
+		[ [ $img  GetPointData ] GetScalars ] FillComponent 0 -100000
+		$functional ShallowCopyImage $img
+		$img Delete
+		set load 0
+	    }
+
+	    set progress [ expr $progress + $scalefactor ]
+	    ShowProgressVal "Renaming functional images [ expr $sub +1 ] (load=$load)" $progress
+	}
+    }
+    SetNewSubject 0
+
+    OutputListCallback $output_listbox $olselect 
+
+    ShowProgressVal "Done" 1.0
+    set thisparam($this,current_taskname) [ [ lindex $tasks $newindex ] cget -task_name ]
+    set thisparam($this,current_task) $newsuffix
+
+}
+
+# ----------------------------------------------------------------------------------------------
+#   Create GUI 
+# ----------------------------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::CreateResultsControl { widget } {
+
+
+    iwidgets::Labeledframe $widget.t1 -labelpos n -labeltext "Output Images"
+    frame $widget.t15 -bg black -height 5
+    iwidgets::Labeledframe $widget.t2 -labelpos n -labeltext "Compute Output"
+    frame $widget.t25 -bg black -height 5
+    iwidgets::Labeledframe $widget.t3 -labelpos n -labeltext "Output Overlay"
+    pack $widget.t2 $widget.t15 $widget.t1 $widget.t25  -side top -expand f -fill x -pady 0
+    pack $widget.t3 -side bottom -expand true -fill both -pady 0
+
+
+    # ---------------------------------------
+    # Reference/Output Images
+    # --------------------------------------
+    set c1 [$widget.t1 childsite  ]
+    set output_listbox [ listbox $c1.list -width 30 -height 8 -borderwidth 2 -relief raised -selectmode single  -takefocus 0 ]
+    $output_listbox configure -exportselection 0
+    eval "bind $output_listbox <ButtonRelease-1> { $this OutputListCallback $output_listbox }"
+
+    for { set i 0 } { $i < [ llength $output_list  ] } { incr i } {
+	$output_listbox insert end [ lindex $output_list $i ] 
+    }
+    $output_listbox see end
+    $output_control Initialize $c1.b ;
+    if { $parent != 0 } {
+	if { $second_viewer == 0 } {
+	    $output_control AddFunction "$parent SetImageFromObject" "Display" "$this"
+	} else {
+	    $output_control AddFunction "$parent SetImageFromObject" "Display Ref" "$this"
+	    $output_control AddFunction "$second_viewer SetImageFromObject" "Display Trn" "$this"
+	}
+    }
+
+    pack $output_listbox $c1.b -padx 5 -pady 3 -side left -expand f -fill y -fill x
+
+
+    # --------------------------------------
+    # Compute Output Stuff
+    # --------------------------------------
+
+    set base [ $widget.t2 childsite ]
+    iwidgets::Labeledframe $base.task -labelpos n -labeltext "Current Active Task"
+    iwidgets::Labeledframe $base.right -labelpos n -labeltext "Composite Operations"
+    pack $base.task $base.right  -side left -fill both -expand true -padx 5 -pady 1
+
+    # Do Task First ------------------------------------------------------------------
+
+    set win [ $base.task childsite ]
+    set task_listbox [ iwidgets::scrolledlistbox $win.slb -labeltext "Available Tasks" \
+			   -vscrollmode dynamic -hscrollmode none \
+			   -selectmode single \
+			   -labelpos nw -height 125]
+    $task_listbox configure -exportselection 0
+    
+    eval "button $win.but -text \"Change Current Task\" -command { $this ChangeCurrentTask $task_listbox} "
+    frame $win.bot;      pack $win.bot -side bottom  -pady 1 
+    pack $win.slb $win.but -side top -expand t -fill x  -padx 5 
+    
+    iwidgets::entryfield $win.bot.0 -labeltext "Current:"  -width 18  -textvariable [ itcl::scope thisparam($this,current_taskname) ] -relief sunken 
+    [ $win.bot.0 component entry ] configure -state disabled
+    iwidgets::entryfield $win.bot.1 -labeltext "Suffix:"  -width 8  -textvariable [ itcl::scope thisparam($this,current_task) ] -relief sunken 
+    [ $win.bot.1 component entry ] configure -state disabled
+    pack $win.bot.1 $win.bot.0 -side right -expand t -fill x -padx 2 -pady 1
+
+    # Do Results Next  ------------------------------------------------------------------
+
+    set win [ $base.right childsite ]
+
+    frame $win.m1 ; frame $win.m2 ; frame $win.m3 -height 2 -bg black
+
+    pack $win.m1 $win.m2 $win.m3  -side top -expand t -fill x -pady 2
+    label $win.m1.lab -text "Interpolation:"
+    tk_optionMenu $win.m1.opt [ itcl::scope thisparam($this,interpolation)] "NearestNeighbor" "Linear" "Cubic"
+    pack $win.m1.lab $win.m1.opt  -side left -expand t -fill x -padx 1
+    
+    label $win.m2.lab -text "Output Sampling:"
+    tk_optionMenu $win.m2.opt [ itcl::scope thisparam($this,outputresolution)] "Ref" "1.0x1.0x1.0" "1.5x1.5x1.5" "2.0x2.0x2.0" "3.0x3.0x3.0" "4.5x4.5x4.5"
+    pack $win.m2.lab $win.m2.opt  -side left -expand f -fill x -padx 1
+
+    checkbutton $win.0 -text "Autosave Results" -variable [ itcl::scope thisparam($this,autosave) ]
+
+    eval "button $win.b -text \"Compute Average Statistics\" -command { $this ComputeAverages Functional }"
+#    eval "button $win.f -text \"Warp Task to Common Space\" -command { $this WarpTasksToCommonSpace save \"\" 1 }"
+#    eval "button $win.f1 -text \"Do VOI Analysis\" -command { $this DoVOIAnalysis  \"\" 0 }"
+#    pack $win.0  $win.b  $win.f $win.f1 $win.f2 -side top -expand f -fill x -padx 2 -pady 4
+    pack $win.0  $win.b   -side top -expand f -fill x -padx 2 -pady 4
+
+#    pack $base.right.bottom.a -side left -expand f -fill x -padx 2 
+
+    # --------------------------
+    # Visualization Output Stuff
+    # --------------------------
+    set c3 [$widget.t3 childsite]
+    $c3 configure -width 600 -height 400
+    
+
+    set w [ frame $c3.top ]
+    set w2 [ frame $c3.right -height 400 ];
+
+#    grid $w -row 0 -column 0 -stick ne
+#    grid $w2 -row 0 -column 1 -sticky nes
+    pack $w -side left -expand false -fill y -padx 10
+    pack $w2 -side right -expand true -fill both
+
+#    grid columnconfigure $c3 0 -weight  100
+#    grid columnconfigure $c3 1 -weight  300
+
+
+#    $overlaycreator SetMainTabHeight 250
+# 
+#    $overlaycreator SetMainTabScrollMode 1
+    $overlaycreator CreateGUI $w2
+    pack forget [ $overlaycreator GetParameterBar ]
+
+
+    frame $w.m0 -width 200; frame $w.m15 -width 200; frame $w.m1 -width 200 ; frame $w.m2 -width 200
+    pack $w.m0 $w.m1 $w.m15 $w.m2 -side top -expand true -fill x
+
+    if { $second_viewer != 0 } {
+	label $w.m0.ml -text "Output Viewer:"
+	tk_optionMenu $w.m0.mopt [ itcl::scope thisparam($this,overlayviewer)] "Reference" "Transform"
+	pack $w.m0.ml $w.m0.mopt -side top -expand t -fill x
+    }
+
+    label $w.m1.l -text "Base (Underlay):"
+    tk_optionMenu $w.m1.opt [ itcl::scope thisparam($this,overlaybase)] "Reference Image" "Average Anatomical" "Individual Anatomical" "Individual Conventional"
+    pack $w.m1.l $w.m1.opt -side top -expand t -fill x
+    
+    label $w.m15.l -text "Function (Overlay):"
+    tk_optionMenu $w.m15.opt [ itcl::scope thisparam($this,overlayfunction) ] "Average Map" "T-Map"  "Single Map"
+    pack $w.m15.l $w.m15.opt  -side top -expand t -fill x
+
+    set thisparam($this,overlaysinglesubject) [ iwidgets::entryfield $w.m2.subj -labeltext "Current Overlay:"  -width 25  -textvariable [ itcl::scope thisparam($this,current_subject) ] -relief sunken ]
+
+
+    pack $w.m2.subj -side left -expand t -fill x
+    pack forget $w.m2.subj
+
+    for { set k 0 } { $k <=4 } { incr k } {
+	if { $k<=3} {
+	    eval "$w.m1.opt.menu entryconfigure $k -command { $this SetOverlayCreatorInputs }"
+	}
+	eval "$w.m15.opt.menu entryconfigure $k -command { $this SetOverlayCreatorInputs }"
+    }
+
+
+
+}
+# ---------------------------------------------------------------------------
+# Main GUI Body 
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclmultisubjectaverage::Initialize { widget } { 
+	
+    if { $fullyinitialized == 1 } {
+	return
+    }
+
+    set basewidget [ toplevel $widget ]
+    wm geometry $basewidget 800x800
+    wm withdraw $basewidget
+
+    SetTitle "Multi Subject Tool"
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget
+}
+
+itcl::body pxitclmultisubjectaverage::DelayedInitialize { } { 
+
+    if { $fullyinitialized == 1 } {
+	return
+    }
+
+    global pxtcl_pref_array
+
+    set menubase     [ menu $basewidget.menu ]; $basewidget configure -menu $menubase
+    set pbar         [ frame $basewidget.pbar    -width 400 -height 20 ]
+
+    set batch_selector [ pxitcllistselector \#auto $basewidget.[ pxvtable::vnewobj ] ]
+
+
+    set notebook $basewidget.notebook
+    iwidgets::tabnotebook $notebook  -tabpos w
+
+    #    pack $menubase -side top -expand f -fill x -pady 1
+    pack $pbar     -side bottom -expand f -fill x -pady 1
+    pack $notebook -side top -expand t -fill both -pady 1
+
+    CreateBaseControl    [ $notebook add -label "Base"     ]
+    CreateSubjectControl [ $notebook add -label "Subjects"  ] 
+    CreateResultsControl [ $notebook add -label "Results"   ]
+    CreateProgressBar  $pbar
+
+    $notebook view "Subjects"
+    $anat_control configure -callback "$this ResetSubjectTree -1"        
+    $conv_control configure -callback "$this ResetSubjectTree -1"        
+    $func_control configure -callback "$this ResetSubjectTree -1"        
+    $epi_control configure -callback "$this ResetSubjectTree -1"        
+    $field_control configure -callback "$this ResetSubjectTree -1"        
+    $refx_control configure -callback "$this ResetSubjectTree -1"        
+    $intx_control configure -callback "$this ResetSubjectTree -1"        
+    $distx_control configure -callback "$this ResetSubjectTree -1"        
+    $task_control configure -callback "$this ResetTaskTree -1"        
+
+    menu $menubase.filem -tearoff 0 ;      $menubase add cascade -label Setup      -menu $menubase.filem
+    menu $menubase.resultsm -tearoff 0;    $menubase add cascade -label Images     -menu $menubase.resultsm
+    menu $menubase.batchm -tearoff 0;      $menubase add cascade -label Batch     -menu $menubase.batchm 
+    menu $menubase.comparem -tearoff 0;    $menubase add cascade -label Comparisons    -menu $menubase.comparem 
+
+    if { $pxtcl_pref_array(EnableBetaFeatures) == "Enabled" } { 
+
+    }
+      
+
+
+    
+    eval "$menubase.filem add command -label \"New Setup\" -command { $this NewSetup }  "
+    $menubase.filem add separator
+    eval "$menubase.filem add command -label \"Load Setup\" -command { $this LoadSetup \"\" }  "
+    eval "$menubase.filem add command -label \"Save Setup\" -command { $this SaveSetup \"\" } "
+    $menubase.filem add separator
+
+    global env
+    set thisparam($this,custsetups)  [ pxitclfilelistmenu \#auto $menubase.filem "Setup Files" "$this LoadSetup" "$this GetSetupName" ]
+    $thisparam($this,custsetups) SetModeToCustom "Setup Files" .msb [ file join $env(HOME) .msbfiles ] 1 
+    $thisparam($this,custsetups) InitializeDisplay
+    $menubase.filem add separator
+
+
+    eval "$menubase.filem add command -label \"Reorganize Data\" -command { $this ReorganizeData } "
+
+    $menubase.filem add separator
+    if { $parent == 0 } {
+	eval "$menubase.filem add command -label Exit -command {  pxtkexit } -underline 1"
+    } else {
+	eval "$menubase.filem add command -label Close -command {  $this HideWindow } -underline 1"
+    }
+    
+    eval "$menubase.resultsm add command -label \"Load All Images\" -command { $this LoadAll 0 }  "
+    eval "$menubase.resultsm add command -label \"Load Functional Only\" -command { $this LoadAll 2 } "
+
+    eval "$menubase.batchm add command -label \"Compute VOI Analysis  for Multiple Tasks\" -command { $this DoVOIAnalysisAllTasks 0 } "
+    eval "$menubase.batchm add command -label \"Compute Average Statistics for Multiple Tasks\" -command { $this ComputeAllResults 0 }  "
+
+    eval "$menubase.batchm add command -label \"Warp To Common Space for Multiple Tasks\" -command { $this WarpAllTasks 0 } "
+    $menubase.batchm add separator
+    eval "$menubase.batchm add command -label \"Create Combined Output Image (4D, one frame per subject)\" -command { $this Create4DImagesAllTasksOld values } "
+    eval "$menubase.batchm add command -label \"Create Combined Output VOI-Averaged Image (4D, one frame per subject)\" -command { $this Create4DImagesAllTasksOld voi } "
+    $menubase.batchm add separator
+    eval "$menubase.batchm add command -label \"Compute Average Anatomical Images\" -command { $this ComputeAverages Images } "
+
+
+    eval "$menubase.comparem add command -label \"Show Compare Tool\" -command { $this ShowCompareTool }"
+    $menubase.comparem add separator
+    eval "$menubase.comparem add command -label \"Send Mean/Std Functional to Compare Tool as Set 1\" -command { $this SetInfoToCompareTool  1 }"
+    eval "$menubase.comparem add command -label \"Send Mean/Std Functional to Compare Tool as Set 2\" -command { $this SetInfoToCompareTool  2 }"
+    $menubase.comparem add separator
+    eval "$menubase.comparem add command -label \"Send Current Subject Functional to Compare Tool as Set 2\" -command { $this SetInfoToCompareTool  -1 }"
+
+    
+    AddSubject;    AddSubject;    AddSubject;    SetNewSubject 0
+    AddTask;    AddTask;    SetNewTask 0
+    OutputListCallback $output_listbox 0
+    
+    set fullyinitialized 1
+
+}
+
+::itcl::body pxitclmultisubjectaverage::AddToMenuButton { mb args} {
+
+    if { [ llength $args ] > 0 } {
+	set nxt ";[ lindex $args 0 ]"
+    } else {
+	set nxt ""
+    }
+    
+    eval "$mb add command -label \"Base\" -command {$this ShowWindow Base $nxt}"
+    eval "$mb add command -label \"Subjects\" -command {$this ShowWindow \"Subjects\" $nxt}"
+    eval "$mb add command -label \"Results\" -command {$this ShowWindow Results $nxt}"
+
+}
+
+# ---------------------------------------------------------------------------
+itcl::body pxitclmultisubjectaverage::ReorganizeData {  } {
+
+    set dirname  [tk_chooseDirectory -title "Select Directory to reorganize/relocate data" ]
+    if { [ string length $dirname ] < 1 } {
+	return 0
+    }
+    
+    if { [ file exists $dirname ] } {
+	set newtail [ file root [ file tail $setupfilename ] ]
+	set newtail "${newtail}data"
+	set dirname [ file join $dirname $newtail ] 
+    }
+    set ok [ ::pxtclutil::Question "This operation will COPY your current files from their existing locations and reorganize them under $dirname. This can use a lot of disk space. Are you sure?" ]
+    if { $ok == 0 } {
+	return
+    }
+    file mkdir $dirname
+    $this LoadAll 0
+    
+    set numtasks [llength $tasks]
+    pxtkconsole
+
+    set beginsub 0
+    set endsub   [ expr [ llength $subjects ]  -1 ]
+
+    set lasttask [ expr $numtasks -1 ]
+
+    for { set c 0 } { $c < $numtasks } { incr c } {
+	
+	pxtkprint "\n ++++++++++++++++++++++++++++++++++++++\n Migratiting Task [ expr $c +1 ]\n------------------------------------------------\n"
+	$task_listbox selection clear 0 [ expr $numtasks -1 ]
+	$task_listbox selection set $c $c
+	ChangeCurrentTask $task_listbox "silent"
+
+	for { set i $beginsub } { $i <= $endsub } { incr i } {
+	    set subject [ lindex $subjects $i ]
+	    pxtkprint "\nSubject $i\n"
+	    set newtail  [ format "%04d_%s" [expr $i+1 ] [ $subject GetBaseName ] ]
+	    set newdir [ file join $dirname $newtail ]
+#	    if { $numtasks != 1 } {
+	    if { $c == 0  } {
+		file mkdir $newdir
+	    }
+	    if { $c < $lasttask } {
+		$subject SaveToDirectory $newdir 0 0
+	    } else {
+		$subject SaveToDirectory $newdir 1 1
+	    }
+#	    } else {
+#		file mkdir $newdir
+#		$subject SaveToDirectory $newdir 1 1
+	    #	    }
+	}
+
+
+	pxtkprint "\n************ Common Files For Task\n"
+	set outlist [ list [ lindex  $outputimages 2 ] [ lindex  $outputimages 3 ] [ lindex  $outputimages 4 ] ]
+
+	if { $c==0 } {
+	    set basedir [ file join $dirname base ]
+	    set resultsdir [ file join $dirname results ]
+	    file mkdir $basedir
+	    file mkdir $resultsdir
+	}
+
+	if { $c == $lasttask } {
+	    lappend outlist [ $reference_control  GetObject ]
+	    lappend outlist [ $voi_control  GetObject ] 
+	    lappend outlist [ lindex  $outputimages 0 ]
+	    lappend outlist [ lindex  $outputimages 1 ] 
+	    
+	}
+	
+	#puts stderr "$outlist"
+
+	for { set i 0 } { $i < [ llength $outlist ] } { incr i } {
+	    
+	    set obj [ lindex $outlist $i ]
+	    set fn [ $obj cget -filename ]
+	    if { [ string length $fn ] > 1 } {
+		
+		if { $i ==3 || $i == 4 } {
+		    set newname [ file join $basedir [ file tail $fn ]]
+		} else {
+		    set newname [ file join $resultsdir [ file tail $fn ]]
+		}
+		$obj configure -filename $newname
+		$obj Save
+		pxtkprint "Mapping $fn --> $newname\n"
+		if { $c != $lasttask && $i <= 2 } {
+		    # Restore filename for next task
+		    $obj configure -filename $fn
+		}
+	    }
+	}
+    }
+    
+    $task_listbox selection clear 0 [ expr $numtasks -1 ]
+    $task_listbox selection set 0 0
+    ChangeCurrentTask $task_listbox "silent"
+
+    
+    set newfilename [ file join $dirname [ file tail $setupfilename ] ]
+    SaveSetup $newfilename
+
+    ::pxtclutil::Info "The new setupfile can be found in $dirname ($newfilename)"
+    
+    SetNewSubject 0
+    SetNewTask 0
+    $reference_control Update
+    $voi_control Update
+    OutputListCallback $output_listbox 0
+
+    return
+}
+
+# ---------------------------------------------------------------------------
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    wm withdraw .
+    set breg [ pxitclbaseimageviewer \#auto 0 ]
+    $breg configure -appname "BioImage Suite::MultiSubject Tool"
+    $breg configure -show_standard_images 1
+    $breg InitializeDisplay .[pxvtable::vnewobj ] 1
+    
+    set mult [  pxitclmultisubjectaverage \#auto $breg ]
+    $mult Initialize [ $breg GetBaseWidget].[pxvtable::vnewobj ]
+    
+    set menubase [ $breg cget -menubase ]
+    set mb [ menu $menubase.multim -tearoff 0 ]
+    $menubase add cascade -label "Multi-Subject"  -menu $mb
+
+    $mult AddToMenuButton $mb "Multi-Subject Control" 
+    $breg AddControl $mult
+    
+    set argc [llength $argv]
+    
+    if { $argc > 0 } {   $breg LoadImage [lindex $argv 0]   }
+    if { $argc > 1 } {   $mult LoadSetup [lindex $argv 1]   }
+    
+    $breg ShowWindow
+    $mult ShowWindow
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclopenigtlinkgadget.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclopenigtlinkgadget.tcl
new file mode 100644
index 0000000..1504f71
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclopenigtlinkgadget.tcl
@@ -0,0 +1,553 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+package provide pxitclopenigtlinkgadget 1.0
+
+# 	$Id: pxitclopenigtlinkgadget.tcl,v 1.4 2005/11/02 15:29:19 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+package require  vtkpxcontrib 1.1
+package require  labelframe   1.0
+package require  pxtclutil    1.0
+package require  pxvtable     1.0
+package require  pxtclhelp    1.0
+package require  Itcl         3.2
+package require  Iwidgets     4.0
+package require  pxitclimage            1.0
+package require  pxitcltransform        1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxtcluserprefs         1.0
+
+# ----------------------------------------------------------------------------------------------
+
+itcl::class pxitclopenigtlinkgadget {
+
+    inherit pxitclbaseimagecontrol
+
+    # Generic Stuff 
+    private   common   thisparam        
+
+
+    # Open IGT Link
+    protected variable igtlconnector 0
+    protected common   igtlconnected  0
+    protected variable enable_igtl 1
+    protected variable vtk_viewer 0
+    protected variable igtlserver 0
+    protected variable igtlserverloopactive 0
+    protected variable igtllastimagetime -1
+    protected variable igtllasttransformtime -1
+
+    protected variable cursor_x 0
+    protected variable cursor_y 0
+    protected variable cursor_z 0
+    protected variable cursor_xform 0
+    protected variable serverstatus ""
+    protected variable imagestatus  ""
+    protected variable pointstatus  ""
+    protected variable internalpoints 0
+    # ------------------------------------------------------------------------------
+
+    constructor { par args } {
+	pxitclbaseimagecontrol::constructor $par 
+    } {
+	InitializeOpenIGTLinkGadget
+    }
+
+    private method InitializeOpenIGTLinkGadget { } 
+
+
+
+    # Client Related
+    # --------------
+    public method OpenIGTLinkConnect { }
+    public method OpenIGTLinkDisconnect { }
+    public method OpenIGTLinkSendImage { }
+    public method ClientEventLoop { }    
+
+    # Server Related
+    # --------------
+    public method CreateServer { }
+
+    public method ServerCallback { }
+    public method ServerCallbackHandleData { mode }
+    public method ViewerUpdate {  }
+    public method CursorUpdate {  }
+    public method ImageUpdate {  }
+    public method ServerEventLoop { }
+
+    # GUI Relate
+    public method CreateServerControl { parent } 
+    public method CreateClientControl { parent } 
+    public method CreateAboutTab  { parent }
+    public method AddToMenuButton { mb args } 
+    public method Initialize { widget viewer }
+
+}
+
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclopenigtlinkgadget::InitializeOpenIGTLinkGadget { } {
+
+    set internalpoints [ vtkPoints  [ pxvtable::vnewobj ] ]
+    $internalpoints SetNumberOfPoints 1
+
+    set thisparam($this,openigtlserver) localhost
+    set thisparam($this,openigtlport)   18944
+    set thisparam($this,openigtlstatus) "Disconnected"
+    set thisparam($this,clientactivelist)   ""
+    set thisparam($this,clientinactivelist) ""
+    set thisparam($this,openigtlenablecursor)   0
+    set thisparam($this,openigtlslicermode)   0
+    set thisparam($this,openigtlslicerbugfix) 0
+    set thisparam($this,openigtltooldelay) 500
+
+
+    set thisparam($this,openigtlserverstatus) "Server Disabled"
+    set thisparam($this,serverport)         18944
+    set thisparam($this,serverdelay)        500
+    set thisparam($this,serverenablecursor) 0
+    set thisparam($this,serverenableimage) 0
+    set thisparam($this,serverimagestatus) ""
+    set thisparam($this,serverpointstatus) ""
+    set thisparam($this,serverbase)        0
+
+    set cursor_xform [ vtkTransform  [ pxvtable::vnewobj ] ]
+}
+
+# --------------------------------------------------------------------------
+itcl::body pxitclopenigtlinkgadget::ClientEventLoop { } {
+
+    #    puts stderr "In Client Event Loop"
+
+
+    
+    if { $igtlconnected == 0 } {
+	set thisparam($this,openigtlenablecursor) 0
+	return 0
+    }
+
+    if { [ $igtlconnector GetIsConnected ] == 0 } {
+	#	puts stderr "We are not connected breaking connection .....................\n\n"
+	$this OpenIGTLinkDisconnect
+	return 0
+    }
+
+    if { $thisparam($this,openigtlenablecursor) == 0 } {
+	return 0
+    }
+
+    set img [ $vtk_viewer GetImage ]
+    if  { $img == "" } { return }
+    
+    set lv [ $vtk_viewer GetLastClickedPointScaled ] 
+    set px [ lindex $lv 0 ]
+    set py [ lindex $lv 1 ]
+    set pz [ lindex $lv 2 ]
+
+    $internalpoints SetPoint 0 $px $py $pz
+    $igtlconnector SendToolLocation $internalpoints $img [ expr $thisparam($this,openigtlslicermode)  + $thisparam($this,openigtlslicerbugfix) ]
+    eval "after $thisparam($this,openigtltooldelay) $this ClientEventLoop"
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclopenigtlinkgadget::CreateServer { } { 
+
+    if { $igtlserver == 0 } {
+	set igtlserver [ vtkpxOpenIGTLinkServer  [ pxvtable::vnewobj ] ]
+    } else {
+	set act [ $igtlserver GetIsServerActive    ]
+	if { $act == 1 } {
+	    return 0
+	}
+    }
+
+    set ok [ $igtlserver InitializeConnection $thisparam($this,serverport) ]
+
+    if { $ok == 0 } {
+	::pxtclutil::Warning "Failed to Create OpenIGTLink Server on port $thisparam($this,serverport)."
+	set thisparam($this,serverenablecursor) 0
+	set thisparam($this,serverenableimage) 0
+	set thisparam($this,openigtlserverstatus) "Server Disabled"
+	return 0
+    }
+
+    while { [ $igtlserver GetThreadActive ] == 0 } { 
+	# puts stderr "Waiting for receiving thread to become active ... "
+    }
+
+    
+    set igtllasttransformtime      [ $igtlserver GetLastReceivedTransformTime ] 
+    set igtllastimagetime          [ $igtlserver GetLastReceivedImageTime ]
+
+
+    if { $igtlserverloopactive == 0 } {
+	set igtlserverloopactive 1
+	$this ServerEventLoop
+    }
+}
+
+
+
+
+# ---------------------------------------------------------------------
+itcl::body pxitclopenigtlinkgadget::ServerEventLoop { } {
+
+    set con [ $igtlserver GetIsServerConnected ]
+    set act [ $igtlserver GetIsServerActive    ]
+
+    if { $con == 1 } {
+	set st " **** STATUS: Server connected"
+    } elseif { $act ==1 } {
+	set st "Port=$thisparam($this,serverport)"
+    } else {
+	set thisparam($this,serverenablecursor) 0
+	set thisparam($this,serverenableimage) 0
+	set st "Server Disabled"
+    }
+    
+    set serverstatus "$st (img=$igtllastimagetime, tr=$igtllasttransformtime)"
+
+
+    set thisparam($this,openigtlserverstatus) $serverstatus
+    set thisparam($this,serverimagestatus)    $imagestatus
+    set thisparam($this,serverpointstatus)    $pointstatus
+
+
+    set dl 1000
+    if { $thisparam($this,serverenablecursor) == 1 || 
+	 $thisparam($this,serverenableimage) == 1 } {
+	set dl $thisparam($this,serverdelay)
+    }
+
+    # If needed start this ....
+    if { $con == 1 && $act == 1 } {
+	$igtlserver BeginReceivingDataInThread
+	$this ServerCallback
+    }
+
+    eval "after $dl $this ServerEventLoop"
+    return     
+}
+
+# ---------------------------------------------------------------------
+
+itcl::body pxitclopenigtlinkgadget::ViewerUpdate {  } {
+#    puts stderr "Viewer Update"
+    set upd [ $vtk_viewer GetMouseSliceChangeMode ]    
+    if { $thisparam($this,serverenablecursor) == 1 && $upd == 1 } {
+	$vtk_viewer SetScaledCoordinates $cursor_x $cursor_y $cursor_z 0
+    }
+}
+
+itcl::body pxitclopenigtlinkgadget::CursorUpdate {  } {
+
+    $this ServerCallbackHandleData 0
+    $vtk_viewer SetScaledCoordinates $cursor_x $cursor_y $cursor_z 0
+}
+
+itcl::body pxitclopenigtlinkgadget::ImageUpdate {  } {
+
+    if { [ $parent isa bis_viewer ] } {
+	return [ $parent SetImage $currentresults ]
+    }
+    
+    return [ $this SendResultsToParent ]
+
+}
+
+itcl::body pxitclopenigtlinkgadget::ServerCallback { } {
+
+    if { $igtllastimagetime < [ $igtlserver GetLastReceivedImageTime ] } {
+	$this ServerCallbackHandleData 1
+    }
+    
+    if { $igtllasttransformtime < [ $igtlserver GetLastReceivedTransformTime ] } {
+	$this ServerCallbackHandleData 0
+    }
+}
+
+
+
+itcl::body pxitclopenigtlinkgadget::ServerCallbackHandleData { mode } {
+    
+
+    set pointstatus ""
+    set status 0
+
+    if { $mode == 0 } {
+	set tr [ $igtlserver GetLastReceivedTransform ]
+
+	$cursor_xform Identity;
+	$cursor_xform Concatenate $tr
+
+	set tx [ $tr GetPosition ]
+
+	set cursor_x [ expr double([ lindex $tx 0 ])]
+	set cursor_y [ expr double([ lindex $tx 1 ])]
+	set cursor_z [ expr double([ lindex $tx 2 ])]
+	set pointstatus  [ format "(%.2f %.2f %.2f)" $cursor_x $cursor_y $cursor_z ]
+	set status 1
+	set igtllasttransformtime  [ $igtlserver GetLastReceivedTransformTime ] 
+	if { $thisparam($this,serverenablecursor) == 1 } {
+	    $this ViewerUpdate
+	}
+    } elseif { $mode ==1 } {
+	$currentresults ShallowCopyImage  [ $igtlserver GetLastReceivedImage ]
+	$currentresults SetOrientationDirect 0
+	$currentresults configure -filename "openigtlimage_[$igtlserver GetLastReceivedImageTime]"
+	set imagestatus  [ $currentresults GetShortDescription ]
+	set igtllastimagetime  [ $igtlserver GetLastReceivedImageTime ]
+	set status 1
+	if { $thisparam($this,serverenableimage) == 1 } {
+	    $this ImageUpdate
+	}
+    }
+
+    return $status
+    
+}
+
+
+#--------------------------------------------------------------------------------------------
+#
+#          GUI Stuff
+#
+#--------------------------------------------------------------------------------------------
+
+
+itcl::body pxitclopenigtlinkgadget::OpenIGTLinkConnect {  } {
+
+    if { $igtlconnector == 0 } {
+	set igtlconnector [ vtkpxOpenIGTLinkClient [ pxvtable::vnewobj ]]
+    }
+
+    set igtlconnected 0
+    set ok [ $igtlconnector InitializeConnection $thisparam($this,openigtlserver) $thisparam($this,openigtlport) ]
+    if { $ok == 1 } {
+
+	set igtlconnected 1
+	EnableUI $thisparam($this,clientactivelist)
+	DisableUI $thisparam($this,clientinactivelist)
+	set thisparam($this,openigtlstatus) "Connected to $thisparam($this,openigtlserver):$thisparam($this,openigtlport)"
+	::pxtclutil::Info "OpenIGTLink Connection to $thisparam($this,openigtlserver) established."
+    } else {
+	::pxtclutil::Warning "OpenIGTLink Connection to $thisparam($this,openigtlserver) failed."
+	set thisparam($this,openigtlstatus) "Disconnected"
+	DisableUI $thisparam($this,clientactivelist) 
+	EnableUI $thisparam($this,clientinactivelist)
+    }
+    
+
+    
+
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclopenigtlinkgadget::OpenIGTLinkDisconnect { } {
+
+    if { $igtlconnector == 0 } {
+	return 0
+    }
+
+    $igtlconnector CloseConnection
+    set thisparam($this,openigtlenablecursor) 0
+    DisableUI $thisparam($this,clientactivelist) 
+    EnableUI $thisparam($this,clientinactivelist)
+}
+
+
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclopenigtlinkgadget::OpenIGTLinkSendImage { } {
+
+    if { $igtlconnector != 0 && $igtlconnected == 1 } {
+	
+	if {  [ $igtlconnector GetIsConnected ] == 0 } {
+	    $this OpenIGTLinkDisconnect
+	    return
+	}
+
+	set img [ $vtk_viewer GetImage ]
+	if { $img != "" } {
+	    set ok [ $igtlconnector SendImage $img ]
+	}
+    } 
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclopenigtlinkgadget::CreateAboutTab { parent }  {
+
+    $parent configure -bg black
+    set txt [ iwidgets::scrolledtext $parent.st -labeltext "About OpenIGTLink" -vscrollmode dynamic -hscrollmode dynamic -width 5i -height 2i ]
+    pack $parent.st -side top -expand true -fill both -padx 5 -pady 5
+
+
+
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclopenigtlinkgadget::CreateClientControl { parent }  {
+
+    entry $parent.2 -width 30  -textvariable [ itcl::scope thisparam($this,openigtlstatus) ] -relief sunken  -bg black -fg white 
+    pack $parent.2 -side bottom -expand true -fill x
+
+    set top  [ LabelFrame:create $parent.a -text "OpenIGTL Server Definition"]
+    set bot  [ LabelFrame:create $parent.b -text "Additional Operations"]
+    pack $parent.a  $parent.b -side top -expand t -fill both -pady 2
+
+
+    iwidgets::entryfield $top.0 -labeltext "OpenIGTL Sever :"  -width 20  -textvariable [ itcl::scope thisparam($this,openigtlserver) ] -relief sunken 
+    iwidgets::entryfield $top.1 -labeltext "OpenIGTL Port  :"  -width 10  -textvariable [ itcl::scope thisparam($this,openigtlport) ] -relief sunken 
+    pack $top.0 $top.1 -side top -expand false -fill x
+
+    set w [ frame $top.mid ]; pack $top.mid -side top -expand false -fill x
+    
+
+    set thisparam($this,clientinactivelist)  [ eval "button $w.1  -text \"Connect\" -command { $this OpenIGTLinkConnect }" ]
+    set thisparam($this,clientactivelist) [ eval "button $w.2  -text \"Disconnect\" -command { $this OpenIGTLinkDisconnect }" ]
+    pack $w.1 $w.2   -side left -expand true -fill x
+
+    lappend thisparam($this,clientinactivelist) $top.0 $top.1
+
+
+    checkbutton $bot.o -variable [itcl::scope thisparam($this,openigtlenablecursor)]   -text "Enable OpenIGTLink Tool Link" 
+    checkbutton $bot.o2 -variable [itcl::scope thisparam($this,openigtlslicermode)]   -text "LPS to RAS Conversion" 
+    checkbutton $bot.o3 -variable [itcl::scope thisparam($this,openigtlslicerbugfix)]   -text "Slicer Centering Bug Fix" 
+
+
+    eval "$bot.o configure -command { $this ClientEventLoop }"
+    frame $bot.a
+
+    label $bot.a.2 -text "Update (ms): "
+    tk_optionMenu $bot.a.3 [ itcl::scope thisparam($this,openigtltooldelay) ]    50 100 200 500 1000 2000 5000 10000
+    pack  $bot.a.2 $bot.a.3  -side left -expand true -fill x
+
+    eval "button $bot.b -text \"Send Current Image\" -command { $this OpenIGTLinkSendImage }"
+
+    pack $bot.o $bot.o2 $bot.o3 $bot.a $bot.b -side top -expand false -fill x
+
+    lappend thisparam($this,clientactivelist) $bot
+    DisableUI $thisparam($this,clientactivelist) 
+    EnableUI $thisparam($this,clientinactivelist)
+
+}
+
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclopenigtlinkgadget::CreateServerControl { parent }  {
+
+    entry $parent.22 -width 30  -textvariable [ itcl::scope thisparam($this,serverpointstatus) ] -relief sunken  -bg black -fg white
+    entry $parent.21 -width 30  -textvariable [ itcl::scope thisparam($this,serverimagestatus) ] -relief sunken  -bg black -fg white
+    entry $parent.2 -width 30  -textvariable [ itcl::scope thisparam($this,openigtlserverstatus) ] -relief sunken  -bg black -fg white
+    pack $parent.2 $parent.21 $parent.22 -side bottom  -expand false -fill x
+
+    set top  [ LabelFrame:create $parent.a -text "OpenIGTL Server Definition"]
+    set bot  [ LabelFrame:create $parent.b -text "Additional Operations"]
+    pack $parent.a  $parent.b -side top -expand t -fill both -pady 2
+
+    iwidgets::entryfield $top.1 -labeltext "Port to Listen On  :"  -width 10  -textvariable [ itcl::scope thisparam($this,serverport) ] -relief sunken 
+    pack $top.1 -side top -expand false -fill x
+
+    set w [ frame $top.mid ]; pack $top.mid -side top -expand false -fill x
+    
+
+    lappend thisparam($this,disconnectlist)    [ eval "button $w.1  -text \"Enable Server\" -command { $this CreateServer }" ]
+
+    pack $w.1    -side left -expand true -fill x
+
+    frame $bot.o
+    label $bot.o.2 -text "Update (ms): "
+    tk_optionMenu $bot.o.3 [ itcl::scope thisparam($this,serverdelay) ] 1 10 50 100  200 500 1000 2000 5000 10000
+    pack  $bot.o.2 $bot.o.3  -side left -expand true -fill x
+
+    checkbutton $bot.a -variable [itcl::scope thisparam($this,serverenablecursor)]   -text "Enable Cursor Link"
+    checkbutton $bot.b -variable [itcl::scope thisparam($this,serverenableimage)]   -text "Enable Image Link (with care)!"
+    #    eval "$bot.a configure -command { $this ServerEventLoop }"
+
+    frame $bot.c
+
+    eval "button $bot.c.0  -text \"Update Viewer Image\" -command { $this ImageUpdate }" 
+    eval "button $bot.c.1  -text \"Update Cursor\" -command { $this CursorUpdate }" 
+
+    pack $bot.c.1 $bot.c.0 -side left -expand false -fill x
+
+    pack $bot.o $bot.a $bot.b  $bot.c -side top -expand false -fill x
+
+}
+
+#--------------------------------------------------------------------------------------------
+# Main GUI Body 
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclopenigtlinkgadget::Initialize { widget viewer } { 
+	
+    global pxtcl_pref_array
+
+    set basewidget [ toplevel $widget ]
+    wm geometry $basewidget 400x400
+    wm withdraw $basewidget
+
+    set vtk_viewer $viewer 
+    
+    set notebook $basewidget.notebook
+    set bbar    [ frame $basewidget.bot    -width 300 -height 50 ]
+
+    iwidgets::tabnotebook $notebook  -tabpos w
+    pack $bbar -side bottom -expand f -fill x -pady 2 -pady 2
+    pack $notebook -side top -expand t -fill both -pady 2 -padx 2
+    eval "button $bbar.1  -text \"Close\" -command {  $this HideWindow }"
+    pack $bbar.1 -side right -expand f -padx 10
+    
+
+    CreateServerControl             [ $notebook add -label "Server"  ] 
+    CreateClientControl             [ $notebook add -label "Client"  ] 
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+
+    set canvas [ [ $notebook component tabset ] component canvas ]
+    set l [ AddLogoLabel $canvas ]
+    pack $l -side bottom -padx 1 
+
+
+    SetTitle "Open IGTLINK Tool"
+    $basewidget configure -bg black
+    return $basewidget
+
+}
+
+::itcl::body pxitclopenigtlinkgadget::AddToMenuButton { mb args} {
+
+    eval "$mb add command -label \"Open IGT Server\" -command {$this ShowWindow \"Server\"}"
+    eval "$mb add command -label \"Open IGT Client\" -command {$this ShowWindow \"Client\"}"
+}
+
+
+# ---------------------------------------------------------------------------
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclorthoviewer.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclorthoviewer.tcl
new file mode 100755
index 0000000..2cdcd82
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclorthoviewer.tcl
@@ -0,0 +1,77 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclbrainsegment.tcl,v 1.2 2004/12/16 16:10:43 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package require vtkpxcontrib  1.1
+package require pxtcluserprefs 
+package require pxitclbaseimageviewer 1.0
+
+wm withdraw .
+set bsegm [ pxitclbaseimageviewer \#auto 0 ]
+$bsegm configure -appname "BioImage Suite::OrthoViewer"
+$bsegm configure -show_standard_images 1
+$bsegm configure -enable_multisubjectcontrol 0
+$bsegm configure -enable_overlaytool 0
+$bsegm configure -enable_vvlinkgadget  1
+$bsegm configure -enable_talaraichoption 1
+$bsegm configure -enable_rendering_on_startup  0
+$bsegm configure -enable_internaleditor 0
+$bsegm configure -enable_objectmapmenu   0
+$bsegm configure -enable_fmrigadget  0
+$bsegm InitializeOrthogonalViewer .[pxvtable::vnewobj ] 1
+
+$bsegm ShowWindow   
+
+set argc [llength $argv]
+
+if { $argc > 0 } {   $bsegm LoadImage [lindex $argv 0]   }
+
+
+update idletasks
+[ $bsegm GetViewer ] SetEnableRendering 1
+
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitcloverlaytool.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitcloverlaytool.tcl
new file mode 100644
index 0000000..ec1d6d6
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitcloverlaytool.tcl
@@ -0,0 +1,3570 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitcloverlaytool 1.0
+# 	$Id: pxitcloverlaytool.tcl,v 1.1 2005/11/28 16:01:07 xenios Exp xenios $	
+
+
+
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxvtable   1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitcltransform 1.0
+package require  vtknrcontrib 1.0
+
+itcl::class pxitcloverlaytool {
+
+    inherit pxitclbaseimagecontrol
+
+    protected variable tmap 0
+    protected variable resliced_tmap 0
+    protected variable lastjacobian 0
+    protected variable vtk_viewer    0
+    protected variable image_parent 0
+    protected variable compact_reslice_control 1
+    public    variable show_standard_images 1
+    public    variable disable_colormapchoice 0
+    public    variable transform_control 0
+
+    public    variable meanimagecontrol1 0
+    public    variable meanimagecontrol2 0
+    public    variable sigmaimagecontrol1 0
+    public    variable sigmaimagecontrol2 0
+    public    variable ref_viewer 0
+    public    variable trn_viewer 0
+    public    variable scalarbar 
+
+    public    variable fourdimagecontrol1 0
+    public    variable fourdimagecontrol2 0
+
+
+    protected common thisparam
+
+    public    variable enable_distortioncorrection 1
+
+    private common reg_measures [ list "Joint Entropy" "Correlation" "Gradient Correlation" "Mutual Information" "Normalized Mutual Information" "Sum of Squared Differences" "Correlation ratio C(X|Y)" "Correlation ratio C(Y|X)" "Product" "DifferenceEntropy" ]
+
+    private common opt_methods [ list "OldStyle" "SlowClimb" "Powell" "GradientDescent" "ConjugateGradient" "Hybrid" ]
+    private common nopt_methods [ list "GradientDescent" "ConjugateGradient" ]
+    
+    constructor { par args } {
+	pxitclbaseimagecontrol::constructor $par
+    } {
+	set tmap                  [ [ pxitclimage \#auto ] GetThisPointer ]
+	set resliced_tmap         [ [ pxitclimage \#auto ] GetThisPointer ]
+	set lastjacobian          [ [ pxitclimage \#auto ] GetThisPointer ]
+	AddImagesToLists          $tmap  $resliced_tmap  $lastjacobian
+	InitializeOverlayTool 
+
+	if { [ llength $args ] > 0 } {
+	    set image_parent [ lindex $args 0]
+	} else {
+	    set image_parent 0
+	}
+    }
+
+    # ------------ Methods --------------------
+    
+    private  method InitializeOverlayTool { } 
+    public   method Initialize { inpwidg args }
+    public   method DelayedInitialize { }
+    public   method SetViewers { ref trn } 
+
+    # ------------ Display --------------------
+    public method AddToMenuButton { mb args}
+
+    # -------- OOP Stuff ---------------------
+    public    method SetImage { img } 
+    public    method GetImage { }
+    public    method SetImageFromObject { img obj } 
+    protected method InitializeResults { } 
+    public    method ProcessResults { filter opname { doextensions 0 } } 
+    public    method ProcessResultsImage { img opname { doextensions 0 }  } 
+    public    method Update { } 
+
+
+    # Functional Image Related
+    # =-----------------------
+    public    method SetFunctionalImageFromSource { anasource } 
+    public    method SetFunctionalImage { image args} 
+    public    method GetFunctionalImage { }
+    public    method LoadFunctionalImage { args } 
+    public    method DisplayFunctionalImage { } 
+    public    method ResliceFunctionalImage { force display } 
+    public    method ComputeSimilarity { } 
+    public    method ComputeOverlap { } 
+
+    # Image Compare Tasks
+    # -------------------
+    public    method SetImageToCompareControl { ctrl image }
+    public    method SetCompareMean1  { image args } { SetImageToCompareControl $meanimagecontrol1   $image } 
+    public    method SetCompareMean2  { image args } { SetImageToCompareControl $meanimagecontrol2   $image } 
+    public    method SetCompareSigma1 { image args } { SetImageToCompareControl $sigmaimagecontrol1  $image } 
+    public    method SetCompareSigma2 { image args } { SetImageToCompareControl $sigmaimagecontrol2  $image } 
+    public    method SetCompareN1     { num } { set thisparam($this,computetmapsamples1) $num} 
+    public    method SetCompareN2     { num } { set thisparam($this,computetmapsamples2) $num}
+
+    public    method ClearCompareSigma1 {  args } { catch { $sigmaimagecontrol1 ClearObject } }
+    public    method ClearCompareSigma2 {  args } { catch { $sigmaimagecontrol2 ClearObject } }
+    public    method ComputeCompareOperations { mode }
+    public    method ComputeCompare4DOperations { mode }
+    public    method ComputeIntersection { }
+
+
+    # Transformation Related
+    # ----------------------
+    public    method SetTransformation { newtr args } 
+    public    method LoadAndAddTransformation { fname } 
+    public    method GetTransformation { } 
+    public    method GetTransformationName { } 
+    public    method SynchronizeTransformation {  } 
+
+    # Manual Transformation Related
+    public   method CreateManualTransformGUI { parent}
+    public   method ClearManualTransformGUI { }
+    public   method SetManualTransform { }
+    public   method SetManualTransformCrossHairs { }
+    public   method ShowManualTransformGUI { dummy window args }
+    public   method ExtractLinearTransform { in_xform image_ref image_trn numparam }
+    public   method SetManualTransformGUI { xform }
+
+    # Minor Stuff
+    # -----------
+    public    method CreateResliceControl { parent } 
+
+
+
+
+    # GUI Stuff
+    # ---------
+    public    method CreateInputControl { parent } 
+    public    method CreateTransformationControl { parent } 
+    public    method CreateStructuralOverlayControl { parent } 
+    public    method CreateFunctionalOverlayControl { parent }
+    public    method UpdateOverlayRange {  } 
+
+    protected method ClusterFunctionalImage { funcImage fmriOverlayCreator clusterthreshold minthreshold probscale  } 
+    public    method CreateOverlay { } 
+    public    method ToggleScalarBar { }
+    public    method CreateImageMergeControl { parent } 
+    public    method CreateImageJoinControl { parent } 
+    public    method CreateImageAffineControl { parent } 
+    public    method CreateImageNonLinearControl { parent } 
+    public    method CreateImageDistortionCorrectionControl { parent }
+    public    method CreateCombineControl { parent } 
+    public    method CreateImageCompareControl { parent } 
+    public    method CreateImageFourDCompareControl { parent } 
+
+
+
+    # Callbacks
+    #------------
+    public    method UpdateFromRegistration { mmvutil } 
+    public    method UpdateFromRegistrationDone { mmvutil } 
+    public    method DisableRegistrationButtons { } 
+    public    method EnableRegistrationButtons { } 
+    public    method SetAutoSave { mode }  
+
+
+    # Registration Stuff
+    # ------------------
+    public    method AutoSaveTransformation { } 
+    public    method AffineControlSetMode { mode } 
+    public    method ComputeAffineRegistration { } 
+    public    method ComputeReorientationRegistration { } 
+    public    method ComputeNonLinearRegistration { } 
+    public    method ComputeDistortionCorrection { } 
+    public    method ComputeCombinedRegistration { mode } 
+
+    # Various Other
+    # --------------
+    public    method CheckWhetherToUpdateBlend { } 
+    public    method CreateCheckerBoard { } 
+    public    method CreateImageBlend { } 
+    public    method CreateMaskedImage { } 
+    public    method ComputeROIStatistics { } 
+    public    method AddImages { } 
+    public    method CombineObjectMaps { } 
+    public    method StripImage { } 
+    public    method CreateGridVisualization { } 
+    public    method JoinImages { }
+
+    # Jacobian Stuff
+    # --------------
+    public    method ComputeJacobian { mode } 
+    public    method DisplayJacobian { } 
+    public    method DisplayJacobianOverlay { } 
+    public    method UpdateJacobianOverlayRange {  } 
+}
+
+
+
+itcl::body pxitcloverlaytool::InitializeOverlayTool { } {
+	
+    global pxtcl_pref_array
+
+    set thisparam($this,tmapstatus) "0 0 0"
+    
+    # ---------------------
+    # Overlay Stuff
+    # ---------------------
+    set thisparam($this,overlaymode) "Both"
+    set thisparam($this,overlaycmapmode) $pxtcl_pref_array(FmriMode)
+    set thisparam($this,overlayanatcmapmode) $pxtcl_pref_array(NormalizeAnatomical)
+    set thisparam($this,overlaymin)  2000
+    set thisparam($this,overlaymax)  5000
+    set thisparam($this,overlayinten) 5.0
+    set thisparam($this,overlaysingleframe) 1
+    set thisparam($this,overlaycurrentframe) 0
+
+    set thisparam($this,overlay_minthresholdscale) 0;
+    set thisparam($this,overlay_maxthresholdscale) 0;
+    set thisparam($this,overlay_componentscale) 0;
+    set thisparam($this,cluster_threshold) 0
+    set thisparam($this,cluster_scale) 0
+
+    
+    # --------------------------
+    # Jacobian Overlay Stuff
+    # --------------------------
+    set thisparam($this,jackoverlaymode) "Both"
+    set thisparam($this,jackoverlaycmapmode) "0"
+    if { $pxtcl_pref_array(FmriMode)!=64 } { set thisparam($this,jackoverlaycmapmode) 1   }
+    set thisparam($this,jackoverlayanatcmapmode) $pxtcl_pref_array(NormalizeAnatomical)
+    set thisparam($this,jackoverlaymin)   0.2
+    set thisparam($this,jackoverlaymax)   2.0
+    set thisparam($this,jackoverlayinten) 5.0
+    set thisparam($this,jackoverlaycurrentframe) 0
+    set thisparam($this,jacobian_threshold) 0.05
+    set thisparam($this,jacobian_resolution) 3.0
+    
+    set thisparam($this,jackoverlay_minthresholdscale) 0;
+    set thisparam($this,jackoverlay_maxthresholdscale) 0;
+    set thisparam($this,jackoverlay_componentscale) 0;
+
+
+    
+    # -------------------------
+    # Reslice Stuff
+    # -------------------------
+    set thisparam($this,resliceinterp)  $pxtcl_pref_array(Interpolation)
+    set thisparam($this,reslicewrappad) 0;
+    set thisparam($this,autoreslice)  1
+    set thisparam($this,autoreorient) 0
+    
+    # ----------------------------
+    # Transform Stuff
+    # ----------------------------
+    set thisparam($this,matrix_text) 0
+
+    # ------------------------------
+    # Image Merge Stuff
+    # ------------------------------
+    set thisparam($this,checkerboardsize) 8
+    set thisparam($this,blendopacity) 0.5
+    set thisparam($this,autoupdateblend) 0.5
+    set thisparam($this,maskdilation) 1
+    set thisparam($this,gridspacing1) 12
+    set thisparam($this,gridspacing2) 0
+    set thisparam($this,gridopacity)  0.5
+    set thisparam($this,gridintensity) 0.5
+    set thisparam($this,imagejoindirection) "x"
+    set thisparam($this,imagejoinflip)       0
+    set thisparam($this,imagejoinpad)        0
+    set thisparam($this,imagejoinboundary) "-1"
+
+    
+    # ------------------------------
+    # Mmvreg Registration Stuff
+    # ------------------------------
+    set thisparam($this,reg_usecurrent) 0
+    set thisparam($this,reg_updatecount)   0
+    set thisparam($this,reg_updatesample)  10
+    set thisparam($this,reg_autosave) 1
+    set thisparam($this,reg_autooverwrite) 0
+    
+    # ------------------------------
+    # Affine Registration Stuff
+    # ------------------------------
+    set thisparam($this,reg_measure) "Normalized Mutual Information"
+    set thisparam($this,dist_measure) "Normalized Mutual Information"
+
+    set thisparam($this,areg_positive) 1
+    set thisparam($this,areg_autonormalize) 1
+    set thisparam($this,areg_jointlynormalize) 0
+    set thisparam($this,areg_usecurrent) 0
+    set thisparam($this,areg_tx) 1 ; set thisparam($this,areg_ty) 1; set thisparam($this,areg_tz) 1 ;
+    set thisparam($this,areg_rx) 1 ; set thisparam($this,areg_ry) 1; set thisparam($this,areg_rz) 1 ;
+    set thisparam($this,areg_sx) 0 ; set thisparam($this,areg_sy) 0; set thisparam($this,areg_sz) 0 ;
+    set thisparam($this,areg_ax) 0 ; set thisparam($this,areg_ay) 0; set thisparam($this,areg_az) 0 ;
+    set thisparam($this,areg_resolution)    1.5
+    set thisparam($this,areg_numlevels)     3
+    set thisparam($this,areg_stepsize)      2.0
+    set thisparam($this,areg_autosave) 1
+    set thisparam($this,areg_autooverwrite) 0
+    set thisparam($this,areg_numlevels) 3
+    set thisparam($this,areg_numsteps) 1
+    set thisparam($this,areg_iterations) 15
+    set thisparam($this,areg_optmethod) "ConjugateGradient"
+    set thisparam($this,areg_logmode) 0
+    set thisparam($this,areg_interpmode) 1
+
+    if { $pxtcl_pref_array(RigidRegistration) == "Stitch" } {    
+	set thisparam($this,areg_optmethod) "Hybrid"
+	set thisparam($this,areg_numsteps) 4
+	set thisparam($this,areg_stepsize) 1.0
+	set thisparam($this,areg_numlevels) 2
+	set thisparam($this,areg_usecurrent) 0
+	set thisparam($this,areg_autosave) 0
+    }
+
+
+    # -------------------------------------------------------------
+    # Non Linear Registration Stuff
+    # -------------------------------------------------------------
+    set thisparam($this,nreg_resolution) 1.5 ; 
+    set thisparam($this,nreg_stepsize) 1.0 ; 
+    set thisparam($this,nreg_autosave) 1
+    set thisparam($this,nreg_autooverwrite) 0
+    set thisparam($this,nreg_spacing) 20.0;
+    set thisparam($this,nreg_spacingrate) 2.0;
+    set thisparam($this,nreg_numlevels) 3
+    set thisparam($this,nreg_numsteps) 1
+    set thisparam($this,nreg_usecurrent) 1
+    set thisparam($this,nreg_useprior) 0
+    set thisparam($this,nreg_iterations) 15
+    set thisparam($this,nreg_gscale) 1.0
+    set thisparam($this,nreg_optmethod) "ConjugateGradient"
+    set thisparam($this,nreg_smoothness) 0.001
+    set thisparam($this,nreg_positive) 0
+    set thisparam($this,nreg_autonormalize) 1
+    set thisparam($this,nreg_jointlynormalize) 0
+
+    set thisparam($this,nreg_logmode) 0
+    # -------------------------------------------------------------
+    # Distortion Correction Stuff
+    # -------------------------------------------------------------
+
+    set thisparam($this,dist_resolution) 2.0
+    set thisparam($this,dist_stepsize) 3.0 
+    set thisparam($this,dist_autosave) 1
+    set thisparam($this,dist_autooverwrite) 0
+    set thisparam($this,dist_spacing) 15.0;
+    set thisparam($this,dist_spacingrate) 2.0;
+    set thisparam($this,dist_numlevels) 3
+    set thisparam($this,dist_numsteps) 1
+    set thisparam($this,dist_usecurrent) 1
+    set thisparam($this,dist_useprior) 0
+    set thisparam($this,dist_iterations) 15
+    set thisparam($this,dist_optmethod) "ConjugateGradient"
+    set thisparam($this,dist_smoothness) 0.0005
+    set thisparam($this,dist_warp) "Y"
+    set thisparam($this,dist_logmode) 1
+    set thisparam($this,dist_jackmode) "None" 
+
+    # ------------------------------   ------------------------------
+    set thisparam($this,updateoperation) "Reslice"
+    set thisparam($this,updateviewer) "Reference"
+    # ------------------------------   ------------------------------
+}
+
+# ---------------------------------------------------------------------------------------
+# Initialize
+# ---------------------------------------------------------------------------------------
+itcl::body pxitcloverlaytool::SetViewers { ref trn } {
+    set ref_viewer $ref
+    set trn_viewer $trn
+}
+
+itcl::body pxitcloverlaytool::Initialize { inpwidg args } {
+
+    if { $initialized == 1 } { return $basewidget }
+    
+    set basewidget $inpwidg
+    toplevel $basewidget ; wm withdraw $basewidget
+    wm geometry $basewidget 650x565
+
+    SetTitle "Registration/Overlay Tool"
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    
+    set initialized 1
+    return $basewidget
+}
+
+
+itcl::body pxitcloverlaytool::DelayedInitialize {  } {
+
+    if { $fullyinitialized == 1 || $initialized == 0 } {
+	return
+    }
+    set fullyinitialized 1
+
+
+    set w  [ frame $basewidget.buttonbar  ]
+    pack $w -side bottom -fill x -expand f
+
+    if { $parent != 0 } {
+	eval "button $w.l1  -text \"Copy Results To Image\" -command { $parent CopyResultsToImage }"
+	eval "button $w.l2  -text \"Undo Copy Results\" -command { $parent RevertToPreviousImage }"
+	pack $w.l1 $w.l2 -side left -padx 5
+    }
+
+    eval "button $w.close   -text Close -command { $this HideWindow } "
+    eval "button $w.unload   -text \"Unload Results\" -command { $this UnloadImages ask }"
+    pack $w.close $w.unload -side right -fill x -padx 25 -pady 10
+
+    set notebook $basewidget.notebook
+    iwidgets::tabnotebook $notebook  -tabpos w
+	
+    #    CreateInputControl          [ $notebook add -label  "Functional Image" ]
+    CreateTransformationControl [ $notebook add -label  "Transformation" ]
+    CreateStructuralOverlayControl [ $notebook add -label  "Jacobian" ]
+    CreateFunctionalOverlayControl [ $notebook add -label  "Func. Overlay" ]
+    CreateImageCompareControl       [ $notebook add -label  "Image Compare" ]
+    CreateImageFourDCompareControl   [ $notebook add -label  "4D Image Compare" ]
+    CreateImageAffineControl    [ $notebook add -label  "Linear Reg" ]
+    CreateImageNonLinearControl [ $notebook add -label  "NonLinear Reg" ]
+    if { $enable_distortioncorrection == 1 } {
+	CreateImageDistortionCorrectionControl  [ $notebook add -label  "Distortion Cor" ]
+    }
+
+    pack $notebook -side top -fill both -expand true
+
+    set canvas [ [ $notebook component tabset ] component canvas ];     set l [ AddLogoLabel $canvas ];     pack $l -side bottom -padx 1 
+}
+
+
+# -------------------------------------------------------
+# SetCurrentImage
+# -------------------------------------------------------
+
+itcl::body pxitcloverlaytool::SetImageFromObject { img obj } {
+    if { $image_parent == 0 } {
+	return [ SetImage $img ]
+    } elseif { $obj == $parent } {
+	return [ SetFunctionalImage $img ]
+    }
+    return [ SetImage $img ]
+
+}
+
+itcl::body pxitcloverlaytool::GetImage { } {
+    return $currentimage
+}
+
+itcl::body pxitcloverlaytool::SetImage { img } {
+	
+    if { [ $img GetImageSize  ] < 2 } { return 0 }
+    $currentimage ShallowCopy $img
+    return [ InitializeResults ]
+}
+# -------------------------------------------------------
+
+itcl::body pxitcloverlaytool::InitializeResults { } {
+    
+    $resliced_tmap UnLoad
+    $lastjacobian  UnLoad
+    $resliced_tmap CopyImageHeader [ $currentimage GetImageHeader ]
+    $lastjacobian  CopyImageHeader [ $currentimage GetImageHeader ]
+    return 1
+}
+
+# -------------------------------------------------------
+# Process Results and Send to Parent
+# -------------------------------------------------------
+
+itcl::body pxitcloverlaytool::ProcessResults { filter opname { doextensions 0 }  } {
+	
+    ProcessResultsImage [ $filter GetOutput ] $opname $doextensions
+}
+
+itcl::body pxitcloverlaytool::ProcessResultsImage { img opname { doextensions 0 } } {
+	
+    $currentresults ShallowCopyImage $img
+    $currentresults CopyImageHeader [ $currentimage GetImageHeader ]
+    if { $doextensions == 1 } {
+	[ $currentresults GetImageHeader ] CopyExtensionsOnly  [ $tmap GetImageHeader ]
+    }
+    $currentresults configure -filename [ AddPrefix [ $tmap cget -filename ] $opname ]
+    
+    SendResultsToParent 
+}
+
+
+# -------------------------------------------------------------
+#  Set Transformation Routine
+# -------------------------------------------------------------
+itcl::body pxitcloverlaytool::LoadAndAddTransformation { fname } {
+
+    $transform_control AddInternalObject 
+    set basetr [ $transform_control GetCurrentObject ]
+    $basetr Load [ pxtclutil::GetAbsoluteFileName $fname ]
+    $transform_control CurrentObjectModified
+    update idletasks
+    InitializeResults
+
+}
+    
+itcl::body pxitcloverlaytool::SetTransformation { newtr args } {
+
+    set mode "modify"
+
+    if { [ llength $args ] > 0 } {
+	set mode [ lindex $args 0 ]
+    }
+
+    $this DelayedInitialize
+
+
+    if { $mode == "add" } {
+	$transform_control AddInternalObject 
+    }
+
+    set basetr [ $transform_control GetCurrentObject ]
+    $basetr CopyTransformation $newtr
+    $transform_control CurrentObjectModified
+    update idletasks
+    InitializeResults
+}
+
+# -------------------------------------------------------------
+#  Set Tmap Routine
+# -------------------------------------------------------------
+
+itcl::body pxitcloverlaytool::GetFunctionalImage { } {
+    return $tmap
+}
+
+itcl::body pxitcloverlaytool::SetFunctionalImage { image args} {
+	
+    if { [  $image GetImageSize  ] < 2 } {
+	return
+    }
+
+    $tmap ShallowCopy $image
+    set thisparam($this,tmapstatus) [ $tmap cget -status ]
+    set thisparam($this,tmapfilename) [ $tmap cget -filename ]
+    InitializeResults 
+    UpdateOverlayRange 
+    if { $image_parent != 0 } {
+	$parent SetImageFromObject $tmap $this 
+    }
+}
+
+itcl::body pxitcloverlaytool::SetFunctionalImageFromSource { anasource } {
+
+    $tmap SetFromAnalyzeSource $anasource
+    set thisparam($this,tmapstatus) [ $tmap cget -status ]
+    set thisparam($this,tmapfilename) [ $tmap cget -filename ]
+    InitializeResults 
+    UpdateOverlayRange 
+    if { $image_parent != 0 } {
+	$parent SetImageFromObject $tmap $this 
+    }
+}   
+
+# ----------------------------------------------------------------------------
+itcl::body pxitcloverlaytool::Update { } {
+
+    switch  $thisparam($this,updateoperation) {
+	"Reslice" { ResliceFunctionalImage 1 1 }
+	"Overlay" { CreateOverlay  }
+	"CheckerBoard" { CreateCheckerBoard }
+	"Blend" { CreateImageBlend }
+    }
+}
+
+# --------------------------------------------------------
+#    Create Functional Image Control 
+# --------------------------------------------------------
+
+itcl::body pxitcloverlaytool::CreateInputControl { parent } {
+
+    set base  [ LabelFrame:create $parent.a -text "Input Image"]
+    set base_upd  [ LabelFrame:create $parent.c -text "Auto Update"]
+    pack $parent.a $parent.c -side top -fill x -expand f
+
+   
+    frame $base.top; frame $base.bot; frame $base.mid
+    pack $base.top $base.mid $base.bot -side top -pady 1 -fill x -expand f
+    
+    label $base.top.l1 -text "Name:"
+    entry $base.top.t1 -textvariable [ itcl::scope thisparam($this,tmapfilename) ] -width 100 -relief sunken -font { fixed 10 }
+    pack $base.top.l1 $base.top.t1  -side left -expand t -fill x
+    
+    label $base.mid.l2 -text "Dim:"
+    entry $base.mid.t2 -textvariable [ itcl::scope thisparam($this,tmapstatus) ] -width 25  -relief sunken -font { fixed 10 }
+    pack $base.mid.l2  $base.mid.t2  -side left -expand f -fill x
+    
+    if { $image_parent == 0 } {
+	eval "button $base.bot.l -text \"Load\" -command { $this LoadFunctionalImage}  -width 6"
+	pack $base.bot.l   -side left -padx 5 -fill x -expand f    
+    }
+
+    eval "button $base.bot.d -text \"Display\" -command { $this DisplayFunctionalImage} -width 8"
+    pack  $base.bot.d  -side left -padx 5 -fill x -expand f    
+
+
+    # Update Box 
+    label ${base_upd}.1 -text "Update Type:"
+    tk_optionMenu ${base_upd}.opt [ itcl::scope thisparam($this,updateoperation) ] "Reslice" "Overlay"  "Blend"
+    pack ${base_upd}.1 ${base_upd}.opt  -side left -expand f
+
+    
+}
+# --------------------------------------------------------
+itcl::body pxitcloverlaytool::CreateImageCompareControl { origpar } {
+
+    label $origpar.top -bg black -fg white -text "Statistical Comparison"
+    pack $origpar.top -fill x -side top -expand f
+
+    set statpar $origpar
+
+    frame $statpar.bot2;     frame $statpar.bot3;
+    frame $statpar.bot -bg gray; pack $statpar.bot $statpar.bot3  $statpar.bot2 -side bottom -expand f -fill x
+   
+    set meanimagecontrol1  [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+    set sigmaimagecontrol1 [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+    
+    set meanimagecontrol2 [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+    set sigmaimagecontrol2 [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+
+    set nt1 [ iwidgets::tabnotebook $statpar.1 -tabpos n  -angle 45 -margin 2 -backdrop gray -raiseselect true  ]
+    set nt2 [ iwidgets::tabnotebook $statpar.2 -tabpos n  -angle 45 -margin 2 -backdrop gray -raiseselect true   ]
+    pack $nt1 $nt2 -side top -expand true -fill both -pady 5
+
+   
+    set clist [ list $meanimagecontrol1 $sigmaimagecontrol1 $meanimagecontrol2 $sigmaimagecontrol2 ]
+    set dlist [ list "Mean 1" "Standard Deviation 1" "Mean 2" "Standard Deviation 2" ]
+    set elist [ list $nt1 $nt1 $nt2 $nt2 ] 
+
+    for { set i 0 } { $i<=3 } { incr i } {
+	
+	set ctrl [ lindex $clist $i ]
+	set desc [ lindex $dlist $i ]
+	set nt   [ lindex $elist $i ]
+
+	set fr [ $nt add -label $desc ]
+
+	$ctrl configure -description $desc
+	$ctrl Initialize $fr.a
+	$ctrl AddFunction "$this SetFunctionalImage" "Display" "$this" 
+	if { $i == 1 || $i == 3 } { 
+	    $fr configure -background darkgray
+	}
+	pack $fr.a -side top -expand f -fill x -pady 0 -padx 0
+    }
+
+    $nt1 view "Mean 1"
+    $nt2 view "Mean 2"
+
+    set thisparam($this,computetmapsamples1) "20"
+    set thisparam($this,computetmapsamples2) "20"
+    set thisparam($this,intersectionthreshold) "5"
+    set thisparam($this,intersectionmode) "Positive"
+
+    eval "button $statpar.bot2.a -text \"Mean1 + Mean2\" -command { $this ComputeCompareOperations add}"
+    eval "button $statpar.bot2.b -text \"Mean1 - Mean2\" -command { $this ComputeCompareOperations diff}"
+    pack $statpar.bot2.a $statpar.bot2.b   -side left -expand f -fill x -pady 5 -padx 2
+
+
+    iwidgets::entryfield $statpar.bot3.0 -labeltext "Intersection Threshold:" -fixed 6 -width 6 -validate real -textvariable [ itcl::scope  thisparam($this,intersectionthreshold) ]
+    label $statpar.bot3.1 -text "Mode:"
+    tk_optionMenu $statpar.bot3.2 [ itcl::scope thisparam($this,intersectionmode) ] "Positive" "Negative" "Both"
+    eval "button $statpar.bot3.3 -text \"Compute Intrsctn\" -command { $this ComputeIntersection }"
+    pack $statpar.bot3.3  -side right -expand f -fill x -pady 2 -padx 2
+    pack $statpar.bot3.0 $statpar.bot3.1 $statpar.bot3.2  -side left -expand true -fill x -pady 2 -padx 0
+
+    iwidgets::entryfield $statpar.bot.c3 -labeltext "N1:" -fixed 6 -width 6 -validate integer -textvariable [ itcl::scope  thisparam($this,computetmapsamples1) ]
+    iwidgets::entryfield $statpar.bot.c4 -labeltext "N2:" -fixed 6 -width 6 -validate integer -textvariable [ itcl::scope  thisparam($this,computetmapsamples2) ]
+
+    eval "button $statpar.bot.d2 -text \"Compute Tmap \" -command { $this ComputeCompareOperations tmap }"
+    pack $statpar.bot.c3 $statpar.bot.c4 -side left -expand f -fill x -pady 5 -padx 2
+    pack $statpar.bot.d2   -side right -expand f -fill x -pady 5 -padx 0
+    
+}
+# --------------------------------------------------------
+itcl::body pxitcloverlaytool::CreateImageFourDCompareControl { origpar } {
+
+    label $origpar.top -bg black -fg white -text "4D Image Statistical Comparison"
+    pack $origpar.top -fill x -side top -expand f
+
+    set statpar $origpar
+
+    frame $statpar.bot -bg gray; pack $statpar.bot -side bottom -expand f -fill x
+   
+    set fourdimagecontrol1 [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+    set fourdimagecontrol2 [[ pxitclimageGUI \#auto  ] GetThisPointer ]
+
+    set clist [ list $fourdimagecontrol1 $fourdimagecontrol2 ]
+    set dlist [ list "4D Image 1" "4D Image 2" ]
+
+    for { set i 0 } { $i<=1 } { incr i } {
+	
+	set ctrl [ lindex $clist $i ]
+	set desc [ lindex $dlist $i ]
+
+	set nm $statpar.fr$i 
+
+
+	$ctrl configure -description $desc
+	$ctrl Initialize $nm
+	$ctrl AddFunction "$this SetFunctionalImage" "Display" "$this" 
+	pack $nm -side top -expand f -fill x -pady 0 -padx 0
+    }
+
+    eval "button $statpar.bot.d1 -text \"Compute T-test \" -command { $this ComputeCompare4DOperations normal }"
+    eval "button $statpar.bot.d2 -text \"Compute Paired T-test \" -command { $this ComputeCompare4DOperations paired }"
+
+    pack $statpar.bot.d1 $statpar.bot.d2  -side right -expand f -fill x -pady 5 -padx 0
+}
+# --------------------------------------------------------
+#  Transformation Control
+# --------------------------------------------------------
+itcl::body pxitcloverlaytool::CreateResliceControl { parent } {
+
+    # Reslice Controls
+    # ----------------
+    set w $parent
+    frame $w.m; frame $w.p ;  pack $w.m $w.p -side top -expand f -pady 1 -padx 5
+    label $w.m.1 -text "Interpolation Type:"
+    tk_optionMenu $w.m.opt [ itcl::scope thisparam($this,resliceinterp) ] "NearestNeighbor" "Linear" "Cubic"
+    pack $w.m.1 $w.m.opt  -side left -expand f
+
+    if { $compact_reslice_control == 1 } {
+	checkbutton   $w.m.11 -variable [ itcl::scope thisparam($this,reslicewrappad) ] -text "Wrap"
+	pack $w.m.11  -side left -expand f -fill x
+	pack forget $w.p
+    } else {
+	checkbutton   $w.p.11 -variable [ itcl::scope thisparam($this,reslicewrappad) ] -text "Wrap"
+	pack $w.p.11  -side top -expand f -fill x
+    }
+
+    frame $w.c; pack $w.c -side bottom -expand f -pady 10 -padx 5
+    eval "button  $w.c.1  -text \"Reslice!\" -command { $this ResliceFunctionalImage 1 1 } "
+    if { $compact_reslice_control == 1 } {
+	eval "button  $w.c.2  -text \"Compute Similarity!\" -command { $this ComputeSimilarity } "
+	eval "button  $w.c.3  -text \"Compute ROI Stats\" -command { $this ComputeROIStatistics } "
+	eval "button  $w.c.4 -text \"Compute Overlap\" -command { $this ComputeOverlap } "
+	pack $w.c.1 $w.c.2 $w.c.3 $w.c.4 -side left -expand f -fill x
+    } else {
+	pack $w.c.1 -side left -expand f -fill x
+    }
+
+}
+
+
+itcl::body pxitcloverlaytool::CreateTransformationControl { parent } {
+
+    set man_xform [ toplevel $parent.man ]
+    eval "wm protocol $man_xform WM_DELETE_WINDOW { wm withdraw $man_xform }"
+    wm withdraw $man_xform
+    wm title $man_xform "Manual Transformation Control"
+    CreateManualTransformGUI $man_xform
+
+    # No do the Tranformation Stuff 
+    
+
+
+    # -- Begin Old Comment Out
+    
+#     set thisparam($this,matrix_text) [ text $base.top -width 36 -height 4 -borderwidth 2 -relief raised -font { fixed 10 }]
+#     SynchronizeTransformation 
+    
+#     entry $base.mid -textvariable [ itcl::scope thisparam($this,current_transformname) ] -width 50 -justify left -relief sunken -font { fixed 10 }
+    
+
+
+    # -- End Old Comment Out
+
+    set transform_control [ [ pxitclmultiTransformGUI \#auto  ] GetThisPointer ]
+    $transform_control Initialize $parent.b
+    $transform_control AddTransformation "Default"
+
+    $transform_control  AddFunction "$this ShowManualTransformGUI" "Manual" "$man_xform"
+    pack $parent.b -side top -expand false -fill x
+    SynchronizeTransformation
+    $transform_control configure -callback "$this SynchronizeTransformation"
+
+    # Reslice Control
+    # ---------------
+    #set base_trn  [ LabelFrame:create $parent.b -text "Transformation"]
+    set base_resl [ LabelFrame:create $parent.b1 -text "Reslice Options"]
+    pack  $parent.b1  -side top -fill x -expand f
+
+
+
+    CreateResliceControl $base_resl
+    CreateImageMergeControl $parent
+    CreateImageJoinControl $parent
+
+
+    
+    #    CreateStructuralOverlayControl $w4
+
+    
+
+}
+
+# ------------------------------------------------------------
+# Load / Display Tmap
+# ------------------------------------------------------------
+itcl::body pxitcloverlaytool::LoadFunctionalImage { args } {
+
+    set f $thisparam($this,tmapfilename)
+    set name "Tmap"
+    
+    if { [ llength $args ] > 0 } {
+	set f [ lindex $args 0 ]
+    } else {
+	set f1path [ file dirname $f ]
+	set f1tail [ file tail    $f ]
+	set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+	set f  [tk_getOpenFile -title $name -initialfile $f1tail -initialdir $f1path -filetypes $typelist]
+    }
+    if { [ string length $f ] < 1 } {
+	return 0
+    }
+	
+    
+    set anasource [  vtkpxAnalyzeImageSource [ pxvtable::vnewobj ]]
+    SetFilterCallbacks $anasource "Reading $name Image"
+    WatchOn
+    $anasource Load $f
+
+    scan [ [ $anasource GetOutput ] GetDimensions ] "%d %d %d" dx dy dz
+    if { ($dx <2 || $dy < 2 || $dz < 2) } {
+	::pxtclutil::Warning "Failed to Load $name Image from $f!"
+	WatchOff
+	return 0;
+    } else {
+	SetFunctionalImageFromSource $anasource
+	set thisparam($this,tmapfilename) $f
+    }
+    catch { $anasource Delete }
+    WatchOff
+    return 1
+}
+
+itcl::body pxitcloverlaytool::DisplayFunctionalImage { } {
+
+    if { $parent == 0 } { return }    
+    set dx [ $tmap GetImageSize ]
+    if { $dx <2 } { 
+	::pxtclutil::Warning "No tmap in memory! Cannot Display!"
+	return
+    } 
+	
+    
+    $parent SetResultsFromObject $tmap $this    
+}
+
+# -------------------------------------------------------------
+# Transform Operations
+# -------------------------------------------------------------
+
+itcl::body pxitcloverlaytool::GetTransformation { } {
+
+    if { $initialized == 0 } { 
+	return 0
+    } elseif { $fullyinitialized == 0 } {
+	$this DelayedInitialize
+    }
+    set tr [ [ $transform_control GetCurrentObject ] GetTransformation ]
+    return $tr
+}
+
+itcl::body pxitcloverlaytool::GetTransformationName { } {
+
+    catch { return  [ [ $transform_control GetCurrentObject ] cget -filename ]  }
+    return ""
+}
+
+
+itcl::body pxitcloverlaytool::SynchronizeTransformation {  } {
+
+    if { $initialized == 0 } { 	return    }
+
+    $this DelayedInitialize
+    InitializeResults
+    return 
+}
+
+# -----------------------------------------------------------------------
+#   Manual Transform GUI
+# -----------------------------------------------------------------------
+itcl::body pxitcloverlaytool::ClearManualTransformGUI { } {
+
+    for { set i 0 } { $i <=2 } { incr i } {
+
+	if { $i == 0 } { 
+	    set pname "x"
+	} elseif { $i == 1 } {
+	    set pname "y"
+	} else {
+	    set pname "z"
+	}
+
+	set thisparam($this,manxf_scale$pname) 100
+	set thisparam($this,manxf_rotate$pname) 0
+	set thisparam($this,manxf_shift$pname) 0
+    }
+}
+
+itcl::body pxitcloverlaytool::ShowManualTransformGUI { dummy window args } {
+    wm deiconify $window
+}
+
+itcl::body pxitcloverlaytool::SetManualTransform { } {
+    
+    for { set i 0 } { $i <=2 } { incr i } {
+	
+	if { $i == 0 } { 
+	    set pname "x"
+	} elseif { $i == 1 } {
+	    set pname "y"
+	} else {
+	    set pname "z"
+	}
+
+	set scale($pname) $thisparam($this,manxf_scale$pname)
+	if { $scale($pname) < 10 } { 
+	    set scale($pname) 10 
+	} elseif { $scale($pname) > 1000.0 } {
+	    set scale($pname) 1000.0
+	}
+
+	set dshift($pname) $thisparam($this,manxf_shift$pname)
+	if { $dshift($pname) < -2000 } { 
+	    set dshift($pname) -2000
+	} elseif { $dshift($pname) > 2000.0 } {
+	    set dshift($pname) 2000.0
+	}
+				     
+	set drotate($pname) $thisparam($this,manxf_rotate$pname)
+	if { $drotate($pname) < -360 } { 
+	    set drotate($pname) 360
+	} elseif { $drotate($pname) > 360.0 } {
+	    set drotate($pname) 360.0
+	}
+
+    }
+
+    set image_trn  $tmap
+    set image_ref  $currentimage
+
+    set sp(x) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 0 ]
+    set sp(y) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 1 ]
+    set sp(z) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 2 ]
+
+
+
+    set tr2 [ vtkTransform [ pxvtable::vnewobj ]]
+    set xform [ vtkpxLinearTransform [ pxvtable::vnewobj ]]
+    $xform ManualSetParameters [expr $dshift(x)*$sp(x) ] [ expr $dshift(y) * $sp(y) ] [ expr $dshift(z)*$sp(z) ] $drotate(x) $drotate(y) $drotate(z) $scale(x) $scale(y) $scale(z)  [ $image_ref GetImage ] [ $image_ref GetOrientation ] [  $image_trn GetImage ] [ $image_trn GetOrientation ] $tr2
+    SetTransformation $tr2
+    $xform Delete
+    $tr2 Delete
+}
+
+itcl::body pxitcloverlaytool::SetManualTransformCrossHairs { } {
+
+    if { $ref_viewer == 0 || $trn_viewer == 0 } {
+	return 
+    }
+    
+    set lv [ [ $ref_viewer GetViewer ] GetLastClickedPointScaled ] 
+    set px(0) [ lindex $lv 0 ];   set py(0) [ lindex $lv 1 ];   set pz(0) [ lindex $lv 2 ]
+
+    set lv [ [ $trn_viewer GetViewer ] GetLastClickedPointScaled ] 
+    set px(1) [ lindex $lv 0 ];   set py(1) [ lindex $lv 1 ];   set pz(1) [ lindex $lv 2 ]
+
+    set dx [ expr $px(1) - $px(0) ]
+    set dy [ expr $py(1) - $py(0) ]
+    set dz [ expr $pz(1) - $pz(0) ]
+
+    set img [ [ $ref_viewer GetViewer ] GetImage ]
+    set spa [ $img GetSpacing ]
+
+    set thisparam($this,manxf_shiftx) [ expr $dx / [ lindex $spa 0 ]]
+    set thisparam($this,manxf_shifty) [ expr $dy / [ lindex $spa 1 ]]
+    set thisparam($this,manxf_shiftz) [ expr $dz / [ lindex $spa 2 ]]
+}
+
+itcl::body pxitcloverlaytool::CreateManualTransformGUI { parentw  } {
+
+    for { set i 0 } { $i <= 2 } { incr i } {
+
+	if { $i ==0 } { 
+	    set name "x"
+	} elseif { $i ==1 } {
+	    set name "y"
+	} else {
+	    set name "z"
+	}
+
+	set f [ frame ${parentw}.$name ] ; pack $f -side top -expand t -fill x
+
+	iwidgets::entryfield $f.1 -labeltext "${name}-Shift:" -fixed 6 -width 6 -validate real -textvariable [ itcl::scope  thisparam($this,manxf_shift${name}) ]
+	iwidgets::entryfield $f.2 -labeltext "${name}-Rotate:" -fixed 6 -width 6 -validate real -textvariable [ itcl::scope  thisparam($this,manxf_rotate${name}) ]
+	iwidgets::entryfield $f.3 -labeltext "${name}-Scale:" -fixed 6 -width 6 -validate real -textvariable [ itcl::scope  thisparam($this,manxf_scale${name}) ]
+	pack $f.1 $f.2 $f.3 -side left -expand f -fill x
+    }
+    
+    $this ClearManualTransformGUI
+    set f [ frame $parentw.bot] 
+    pack $f -side bottom -expand t -fill x
+    
+    eval "button $f.1 -text \"Set Xformation\" -command { $this SetManualTransform }"
+    eval "button $f.2 -text \"Set & Apply\" -command { $this SetManualTransform ; $this ResliceFunctionalImage 1 1}"
+    eval "button $f.3 -text \"Extract!\" -command { $this SetManualTransformGUI 0 }"
+    eval "button $f.4 -text \"Clear Values\" -command { $this ClearManualTransformGUI }"
+    eval "button $f.5 -text \"Close\" -command { wm withdraw $parentw }"
+    pack $f.5 -side right
+    pack $f.1 $f.2 $f.3 $f.4 -side left -padx 5
+
+    if { $ref_viewer !=0 && $trn_viewer !=0 } {
+	eval "button $f.45 -text \"Auto Cross Hairs\" -command { $this SetManualTransformCrossHairs }"
+	pack $f.45 -side left -padx 5
+    }
+}
+
+itcl::body pxitcloverlaytool::ExtractLinearTransform { in_xform image_ref image_trn numparam } {
+
+    set image_ref  $currentimage
+    set image_trn  $tmap
+    
+    set xform [ vtkpxLinearTransform [ pxvtable::vnewobj ]]
+    $xform ExtractParameters $in_xform 9 [ $image_ref GetImage ] [ $image_ref GetOrientation ] [  $image_trn GetImage ] [ $image_trn GetOrientation ]
+
+    for { set k $numparam } { $k < 15 } { incr k } {
+	$xform Put $k 0
+    }
+
+    return $xform
+}
+
+itcl::body pxitcloverlaytool::SetManualTransformGUI { in_xform } {
+
+    set current_transform [ $this GetTransformation ]
+
+    if { $in_xform == 0 } {
+	set in_xform $current_transform
+    }
+
+    set xform [ ExtractLinearTransform $in_xform $currentimage $tmap 9 ]
+    set or [ list [ $xform  Get 3 ] [ $xform  Get 4 ] [ $xform  Get 5 ] ]
+    set sc [ list [ $xform  Get 6 ] [ $xform  Get 7 ] [ $xform  Get 8 ] ]
+    set tr [ list [ $xform  Get 0 ] [ $xform  Get 1 ] [ $xform  Get 2 ] ]
+
+    set image_ref  $currentimage
+    set sp(x) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 0 ]
+    set sp(y) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 1 ]
+    set sp(z) [ lindex [ [  $image_ref GetImage ] GetSpacing  ] 2 ]
+    
+    for { set i 0 } { $i <=2 } { incr i } {
+	
+	if { $i == 0 } { 
+	    set pname "x"
+	} elseif { $i == 1 } {
+	    set pname "y"
+	} else {
+	    set pname "z"
+	}
+	
+	set thisparam($this,manxf_scale$pname) [lindex $sc $i ]
+	set thisparam($this,manxf_rotate$pname) [ lindex $or $i ]
+	set thisparam($this,manxf_shift$pname) [ expr [ lindex $tr $i ] / $sp($pname) ]
+    }
+    $xform Delete
+
+}
+
+
+# --------------------------------------------------------
+#     Reslice Functional Image
+# --------------------------------------------------------
+
+itcl::body pxitcloverlaytool::ComputeOverlap { } {
+
+
+    set sigma 1.0
+    set xform [ $this GetTransformation ]
+
+    set image(1) [ $currentimage GetImage ]
+    set image(2) [ $tmap GetImage ]
+
+    scan [ $image(1) GetDimensions ] "%f %f %f" x1 y1 z1
+    scan [ $image(2) GetDimensions ] "%f %f %f" x2 y2 z2
+
+    if { $x1 < 2 || $x2  < 2 } { 
+	::pxtclutil::Warning  "No  Images in Memory\n Cannot Compute Overlap!"
+	return  0
+    }
+
+
+    set n(1) [ $currentimage cget -filename ]
+    set n(2) [ $tmap cget -filename ]
+
+    set comment "[ file tail [ file rootname  $n(1) ]]_[ file tail [ file rootname  $n(2)  ]]"
+
+    # Step One Threshold both 
+    WatchOn
+
+    pxtkconsole
+
+
+
+    set range [ [ [ $image(1) GetPointData ] GetScalars ] GetRange ]
+
+    set low_thr [ expr [ lindex $range 0 ] + 1 ]
+    set high_thr  [ lindex $range 1 ]
+
+    pxtkprint "\nComputing Overlap [ GetTransformationName ] $comment range=${low_thr}:${high_thr} ( xform = [ file tail [ $this GetTransformationName ] ])\n\n"
+
+    # Step One Threshold both 
+    
+    for { set thr $low_thr } { $thr <=$high_thr } { set thr [ expr $thr +1.0 ] } {
+	
+	for { set k 1 } { $k <= 2 } { incr k } {
+	
+	    set cast($k)  [  vtkImageCast [ pxvtable::vnewobj ] ]
+	    $cast($k) SetInput $image($k)
+	    $cast($k) SetOutputScalarTypeToFloat
+	    $cast($k) Update
+
+	    set prethreshold($k)  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+	    
+	    set low  [ expr $thr - 0.1 ]
+	    set high [ expr $thr + 0.1 ]
+
+	    $prethreshold($k) SetInput [$cast($k)  GetOutput ]
+	    $prethreshold($k) ThresholdBetween  $low $high
+	    $prethreshold($k) SetInValue    100
+	    $prethreshold($k) SetOutValue   0
+	    $prethreshold($k) ReplaceInOn
+	    $prethreshold($k) ReplaceOutOn
+	    $prethreshold($k) SetOutputScalarTypeToUnsignedChar
+	    $prethreshold($k) Update
+
+	    $cast($k) Delete
+
+	    set spa [ $image($k)  GetSpacing ]
+	    
+	    for { set i 0 } { $i <= 2 } { incr i } {
+		set smsigma($i) [ expr $sigma / [ lindex $spa $i ]]
+	    }
+	    
+	    set smooth($k)  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+	    $smooth($k) SetStandardDeviations $smsigma(0) $smsigma(1) $smsigma(2)
+	    $smooth($k) SetInput [ $prethreshold($k) GetOutput ] 
+	    $smooth($k) SetRadiusFactors 1.5 1.5 1.5
+	    $smooth($k) Update
+	    $prethreshold($k) Delete
+	    
+	    set threshold($k)  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+
+	    if { $k == 2 } {
+		set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+		$resl SetInput [ $smooth($k)  GetOutput ]
+		$resl SetInformationInput [ $smooth(1) GetOutput ]
+		$resl SetInterpolationMode 1
+		$resl SetBackgroundLevel 0.0
+
+		$resl SetResliceTransform $xform
+		$resl Update
+		$threshold($k) SetInput [ $resl GetOutput ]		
+		$resl Delete
+	    } else {
+		$threshold($k) SetInput [ $smooth($k) GetOutput ]
+	    }
+	    
+
+	    set r [ [ [ [ $threshold($k) GetInput ] GetPointData ] GetScalars ] GetRange ]
+	    set lowr [ expr 0.5* ([lindex $r 0 ] + [ lindex $r 1 ]) ]
+	    set highr [ lindex $r 1 ]
+	    $threshold($k) ThresholdBetween  $lowr $highr
+	    $threshold($k) SetInValue    1
+	    $threshold($k) SetOutValue   0
+	    $threshold($k) ReplaceInOn
+	    $threshold($k) ReplaceOutOn
+	    $threshold($k) SetOutputScalarTypeToUnsignedChar
+	    $threshold($k) Update
+	    
+	    set finalimage($k) [ $threshold($k) GetOutput ]
+	
+	    set accum($k)  [  vtkImageAccumulate [ pxvtable::vnewobj ] ]
+	    
+	    $accum($k) SetInput $finalimage($k)
+	    $accum($k) SetComponentExtent 0 1 0 0 0 0
+	    $accum($k) SetComponentOrigin 0 0 0 
+	    $accum($k) SetComponentSpacing 1.0 1.0 1.0
+	    $accum($k) Update
+	    
+	    if { $k == 1 } {
+		set ve [ [ [ [ $accum($k) GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+	    } else {
+		set va [ [ [ [ $accum($k) GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+	    }
+	}
+	
+	set compare1 [ vtkImageMathematics [ pxvtable::vnewobj ]]
+	$compare1 SetInput1 $finalimage(1)
+	$compare1 SetInput2 $finalimage(2)
+	$compare1 SetOperationToMultiply
+	$compare1 Update
+	
+	set accumcompare1  [  vtkImageAccumulate [ pxvtable::vnewobj ] ]
+	$accumcompare1 SetInput [ $compare1 GetOutput ]
+	$accumcompare1 SetComponentExtent 0 1 0 0 0 0
+	$accumcompare1 SetComponentOrigin 0 0 0 
+	$accumcompare1 SetComponentSpacing 1.0 1.0 1.0
+	$accumcompare1 Update
+	
+	# vae == intesection 
+	set vae [ [ [ [ $accumcompare1 GetOutput ] GetPointData ] GetScalars ] GetComponent 1 0 ]
+	
+	set overlap [ expr 100.0 * $vae / ( $va + $ve - $vae ) ]
+	set overlap2 [ expr 100.0* $vae / ( 0.5 * ( $va + $ve )  ) ]
+
+	set line1 "thr=$thr overlap=$overlap\n"
+	catch { set line1 [ format "thr:%.1f\t Va:\t %d \t Ve:\t %d \t Vae:\t %d \t Overlap:\t %.2f \t Overlap2:\t %.2f \t Sigma:\t %.3f " $thr $va $ve $vae $overlap $overlap2 $sigma ] }
+	
+	pxtkprint  "$comment:OV\t  $line1\n"
+	
+	for { set k 1 } { $k <= 2 } { incr k } {
+	    $threshold($k) Delete
+	    $accum($k) Delete
+	    $smooth($k) Delete
+
+	}
+	
+	${compare1} Delete
+	${accumcompare1} Delete
+
+	    
+	
+    }
+
+    WatchOff
+    return 1
+
+}
+
+
+itcl::body pxitcloverlaytool::ComputeSimilarity { } {
+
+    set reg [ vtkpxRegistration [ pxvtable::vnewobj ]]
+    set current_transform [ $this GetTransformation ]
+    set image_ref [ $currentimage GetImage ]
+    set image_trn [ $tmap GetImage ]
+    
+
+    set arr [ vtkFloatArray [ pxvtable::vnewobj ]]
+    $reg ComputeAllSimilarityMetricsBetweenImages $image_ref $image_trn $current_transform $arr
+
+    pxtkconsole
+    pxtkprint "Similarity between ref and resliced transform (using current transformation)\n"
+    for { set i 0 } { $i < [ $arr GetNumberOfTuples ] } { incr i } {
+	if { $i <2 || $i==4 || $i==5 || $i==9 } {
+	    pxtkprint [ format "%40s : %8.5f \n" [ lindex $reg_measures $i ] [ $arr GetComponent $i 0 ] ]
+	}
+    }
+
+    if { [ $current_transform IsA vtkpxComboTransform  ] ==1 } {
+	set sm [ [ $current_transform GetGridTransform ] ComputeTotalBendingEnergy ]
+	pxtkprint [ format "\t\tTotal Bending Energy = %.2f \n" $sm ]
+    }
+
+    pxtkprint "\n"
+    $arr Delete
+
+}
+
+
+itcl::body pxitcloverlaytool::ResliceFunctionalImage { force display } {
+
+    set current_transform [ $this GetTransformation ]
+
+    set image_ref [ $currentimage GetImage ]
+    set image_trn [ $tmap GetImage ]
+    
+    set orient_ref [ $currentimage GetOrientation ]
+    set orient_trn [ $tmap GetOrientation ]
+
+    set dim1 [ $image_ref GetDimensions ]
+    set dim2 [ $image_trn GetDimensions ]
+    if { [lindex $dim2 0 ] <2 || [ lindex $dim1 0 ] < 2 } { 
+	::pxtclutil::Warning "No Image in Memory\n Cannot Reslice!"
+	return  0
+    }
+    
+    if { $force == 0 } {
+	
+	scan [ $image_ref GetDimensions ] "%d %d %d" dx1 dy1 dz1
+	scan [ [ $resliced_tmap GetImage ] GetDimensions ] "%d %d %d" dx2 dy2 dz2
+	
+	if { $dx1==$dx2 && $dy1==$dy2 && $dz1 == $dz2 } {
+	    return 1
+	}
+    }
+    
+	
+    WatchOn 
+
+    set reslice [  vtkbisImageReslice [ pxvtable::vnewobj ]]
+    
+    set intmode $thisparam($this,resliceinterp)
+
+    if { $intmode == "Linear" } {
+	set range [ [ [ $image_trn  GetPointData ] GetScalars ] GetRange ]
+	if { [ lindex $range 1 ] < 20.0 } {
+	    puts stderr "Switching to Cubic Interpolation to avoid 0..1 bug"
+	    set intmode "Cubic"
+	}
+    }
+
+    $reslice SetInterpolationModeTo$intmode
+    $reslice SetWrap $thisparam($this,reslicewrappad)
+    $reslice SetBackgroundLevel 0.0
+    $reslice OptimizationOff
+    
+    $reslice SetInformationInput $image_ref
+
+
+    set reorient ""
+    if {$thisparam($this,autoreorient) == 0 || $orient_trn==$orient_ref  } {
+	$reslice SetInput $image_trn
+	$reslice SetResliceTransform $current_transform
+    } else {
+	set tr2 [ vtkTransform [ pxvtable::vnewobj ]]
+	$tr2 Identity
+	scan [ $image_trn GetSpacing    ] "%f %f %f" spx spy spz
+	scan [ $image_trn GetDimensions ] "%d %d %d" dimx dimy dimz
+	$tr2 Translate [ expr -0.5*$spx*$dimx ] [ expr -0.5*$spy*$dimy ] [ expr -0.5*$spz*$dimz ]
+	
+	set imtmp [ vtkImageData [ pxvtable::vnewobj ]]
+	set ut [ vtkpxUtil [ pxvtable::vnewobj ]]
+	$ut ReOrientImage $imtmp $image_trn $orient_trn $orient_ref 
+	$ut Delete
+	
+	set tr3 [ vtkTransform [ pxvtable::vnewobj ]]
+	$tr3 Identity
+	scan [ $imtmp GetSpacing    ] "%f %f %f" spx spy spz
+	scan [ $imtmp GetDimensions ] "%d %d %d" dimx dimy dimz
+	$tr3 Translate [ expr 0.5*$spx*$dimx ] [ expr 0.5*$spy*$dimy ] [ expr 0.5*$spz*$dimz ]
+	    
+	set genetr [ vtkGeneralTransform [ pxvtable::vnewobj ]]
+	$genetr Identity
+	$genetr PostMultiply
+	$genetr Concatenate $tr2
+	$genetr Concatenate $current_transform
+	$genetr Concatenate $tr3
+	
+	$reslice SetResliceTransform $genetr
+	$reslice SetInput $imtmp
+	set reorient "With Reorientation"
+	
+	catch { $tr2 Delete }
+	catch { $tr3 Delete }
+	catch { $genetr Delete }
+	catch { $imtmp Delete }
+	
+    }
+
+    SetFilterCallbacks $reslice "Reslicing Image $reorient"
+    $reslice Update
+
+    if { $display == 1 } {
+	ProcessResults $reslice "resliced" 1
+	set thisparam($this,updateoperation) "Reslice"
+    }
+
+    $resliced_tmap ShallowCopyImage [ $reslice GetOutput ]
+    [ $resliced_tmap GetImageHeader ] CopyExtensionsOnly  [ $tmap GetImageHeader ]
+    
+    catch { $reslice Delete }
+    WatchOff
+    return 1
+}
+
+
+# --------------------------------------------------------
+#    Create Overlay Control 
+# --------------------------------------------------------
+itcl::body pxitcloverlaytool::CreateFunctionalOverlayControl { parent } {
+
+
+    if { $compact_reslice_control == 1 } {
+
+	if { $trn_viewer == 0 } {
+	    set w4  [ LabelFrame:create $parent.1 -text "Functional Image"]
+	    CreateInputControl $w4
+	    pack $parent.1 -side top -expand false -pady 10 -fill x
+	}
+	set w  [ LabelFrame:create $parent.2 -text "Overlay Control"]
+	pack $parent.2 -side top -expand true -pady 10 -fill x
+    } else {
+	set w $parent
+    }
+
+    frame $w.m;  	frame $w.m2;  	frame $w.f0 ; frame $w.f1;	frame $w.f2 ;
+    pack $w.m $w.m2 $w.f0 $w.f1 $w.f2 -side top -expand f
+    
+    label $w.m.1 -text "Overlay Type:"
+    tk_optionMenu $w.m.opt [ itcl::scope thisparam($this,overlaymode) ] "Positive" "Negative" "Both" 
+    pack $w.m.1 $w.m.opt -side left -expand f
+    
+    if { $disable_colormapchoice == 0 } {
+	
+	label $w.m.c1 -text "Colormap:"
+	tk_optionMenu $w.m.copt [ itcl::scope thisparam($this,overlaycmapmode) ] "F1" "F2" "F4" 
+	pack $w.m.c1 $w.m.copt -side left -expand f
+    } else {
+	set thisparam($this,overlaycmapmode) F1
+    }
+    
+    checkbutton $w.m.chk2 -variable [ itcl::scope thisparam($this,overlayanatcmapmode) ] -text "Normalize Anatomical" 
+    pack $w.m.chk2 -side left -expand f
+    
+    # Clustering Stuff
+    # ----------------
+     label $w.m2.1 -text "Clustering:"
+
+    set thisparam($this,cluster_threshold_scale) [ scale  $w.m2.s -orient horizontal  -from 0 -to 1000 -resolution 1.0 -showvalue 0 -length 150 -variable [ itcl::scope thisparam($this,cluster_threshold) ] ]
+    entry $w.m2.e -textvariable [ itcl::scope thisparam($this,cluster_threshold) ] -width 6 -relief sunken -font { fixed 10 }
+    checkbutton $w.m2.a -variable [ itcl::scope thisparam($this,cluster_scale) ] -text "Orig Voxels" 
+    
+#    label $w.m2.l1 -text "Prob: "
+#    set thisparam($this,cluster_threshold_prob) [ label $w.m2.l2 -text "1.0" -fg "blue" ]
+    
+    pack  $w.m2.1 $w.m2.s $w.m2.e $w.m2.a -side left -expand t -fill x
+    #$w.m2.l1  $w.m2.l2 
+
+    set thisparam($this,overlay_minthresholdscale)  [ ::pxtclutil::CreateTriple $w.f0.0  "Low Threshold"   [ itcl::scope thisparam($this,overlaymin) ]  0.0 1000.0 0.01 10 95 ]
+    set thisparam($this,overlay_maxthresholdscale)  [ ::pxtclutil::CreateTriple $w.f0.1  "High Threshold"  [ itcl::scope thisparam($this,overlaymax) ]  0.0 1000.0 0.01 10 95 ]
+    ::pxtclutil::CreateTriple $w.f0.2  "Inten. Thr"  [ itcl::scope thisparam($this,overlayinten) ]  -1.0 255.0 5 1 60
+    
+    checkbutton $w.f1.chk -variable [ itcl::scope thisparam($this,overlaysingleframe) ] -text "Single Component Only"
+    pack $w.f1.chk -side left -padx 5
+    set thisparam($this,overlay_componentscale)  [ ::pxtclutil::CreateTriple $w.f1.1  "Select Component:"  [ itcl::scope thisparam($this,overlaycurrentframe) ]  1 10 1 10 95 ]
+    eval "bind $thisparam($this,overlay_componentscale) <ButtonRelease> \"$this UpdateOverlayRange\" "
+
+    frame $w.c; pack $w.c -side bottom -expand f -pady 2
+    eval "button  $w.c.1  -text \"Force  Reslice!\" -command { $this ResliceFunctionalImage 1 1 } "
+    eval "button  $w.c.2  -text \"Create Overlay!\" -command { $this CreateOverlay   } "
+    eval "button  $w.c.3  -text \"Toggle Colorbar!\" -command { $this ToggleScalarBar   } "
+    pack $w.c.1 $w.c.2 $w.c.3 -side left -expand f -fill x
+
+
+
+}
+
+# --------------------------------------------------------
+itcl::body pxitcloverlaytool::CreateStructuralOverlayControl { parent } {
+    
+    set w3  [ LabelFrame:create $parent.0 -text "Compute Jacobian"]
+    set w4  [ LabelFrame:create $parent.1 -text "Overlay Jacobian"]
+    set w5  [ LabelFrame:create $parent.grid -text "Visualize Transform"]
+    pack $parent.0 $parent.1 $parent.grid -side top -expand f -pady 10 -fill x
+
+
+    # Compute Buttons first and flags
+
+
+    iwidgets::entryfield $w3.a -labeltext "Intensity Thresshold (fraction of max):" -fixed 6 -width 6 -validate real \
+	-textvariable [ itcl::scope  thisparam($this,jacobian_threshold) ]
+    iwidgets::entryfield $w3.b -labeltext "Resolution Reduction Factor (x native):" -fixed 6 -width 6 -validate real \
+	-textvariable [ itcl::scope  thisparam($this,jacobian_resolution) ]
+    pack $w3.a $w3.b -side top -expand f -pady 2 
+
+
+
+    frame $w3.c;  pack $w3.c -side top -expand f -pady 5 -fill x
+    eval "button $w3.c.1 -text \"Comp Jacobian\" -command { $this ComputeJacobian simple }"
+    eval "button $w3.c.2 -text \"Comp Tensor\" -command { $this ComputeJacobian tensor }"
+    eval "button $w3.c.3 -text \"Comp Strains\" -command { $this ComputeJacobian strains }"
+    pack $w3.c.1 $w3.c.2 $w3.c.3 -side left -expand true -fill x -padx 5
+
+      
+
+
+    frame $w4.m;  	frame $w4.m2;  	frame $w4.f0 ; frame $w4.f1;	frame $w4.f2 ;
+    pack $w4.m $w4.m2 $w4.f0 $w4.f1 $w4.f2 -side top -expand f
+    
+    label $w4.m.1 -text "Overlay Type:"
+    tk_optionMenu $w4.m.opt [ itcl::scope thisparam($this,jackoverlaymode) ] "Positive" "Negative" "Both" 
+    pack $w4.m.1 $w4.m.opt -side left -expand f
+    
+    checkbutton $w4.m2.chk -variable [ itcl::scope thisparam($this,jackoverlaycmapmode) ] -text "Use 256 Colors" 
+    checkbutton $w4.m2.chk2 -variable [ itcl::scope thisparam($this,jackoverlayanatcmapmode) ] -text "Normalize Anatomical" 
+    pack $w4.m2.chk $w4.m2.chk2  -side left -expand f
+	       
+    set thisparam($this,jackoverlay_minthresholdscale)  [ ::pxtclutil::CreateTriple $w4.f0.0  "Low Threshold"   [ itcl::scope thisparam($this,jackoverlaymin) ]  0.0 2.0 0.05 10 95 ]
+    set thisparam($this,jackoverlay_maxthresholdscale)  [ ::pxtclutil::CreateTriple $w4.f0.1  "High Threshold"  [ itcl::scope thisparam($this,jackoverlaymax) ]  0.0 2.0 0.05 10 95 ]
+    ::pxtclutil::CreateTriple $w4.f0.2  "Inten. Thr"  [ itcl::scope thisparam($this,jackoverlayinten) ]  -1.0 255.0 5 1 60 
+    
+
+    set thisparam($this,jackoverlay_componentscale)  [ ::pxtclutil::CreateTriple $w4.f1.1  "Select Component:"  [ itcl::scope thisparam($this,jackoverlaycurrentframe) ]  1 10 1 10 95 ]
+    eval "bind $thisparam($this,jackoverlay_componentscale) <ButtonRelease> \"$this UpdateJacobianOverlayRange\" "
+
+
+    frame $w4.c;  pack $w4.c -side top -expand f -pady 5 -fill x
+    eval "button $w4.c.p1 -text \"Display Jacobian\" -command { $this DisplayJacobian }"
+    eval "button $w4.c.p2 -text \"Overlay\" -command { $this DisplayJacobianOverlay }"
+    pack $w4.c.p1 $w4.c.p2 -side left -expand true
+
+
+    # Visualize Xform
+    #-----------------
+
+    label $w5.1 -text "Grid Spacing:"
+    tk_optionMenu $w5.opt1 [ itcl::scope thisparam($this,gridspacing1) ]  "4" "8" "12" "16" 
+    tk_optionMenu $w5.opt2 [ itcl::scope thisparam($this,gridspacing2) ] "0" "1" "2" "4" "8" "16"
+
+    label $w5.a1 -text "Grid Intensity/Opacity:"
+    tk_optionMenu $w5.opta1 [ itcl::scope thisparam($this,gridintensity) ] 0.25 0.5 0.75 1.0 1.25 1.5
+    tk_optionMenu $w5.opta2 [ itcl::scope thisparam($this,gridopacity) ]  0.1 0.3 0.5 0.7 0.9
+
+    eval "button  $w5.2  -text \"Create!\" -command { $this CreateGridVisualization  } "
+    pack $w5.1 $w5.opt1 $w5.opt2 $w5.a1 $w5.opta1 $w5.opta2 $w5.2 -side left -expand f
+
+
+}
+
+itcl::body pxitcloverlaytool::UpdateOverlayRange {  } {
+
+    if { [  $tmap GetImageSize  ] < 2 } {
+	return
+    }
+
+    DelayedInitialize
+
+
+    set nc [ [ $tmap GetImage ] GetNumberOfScalarComponents ]
+    $thisparam($this,overlay_componentscale) configure -from 1 -to $nc 
+
+    if { $thisparam($this,overlaycurrentframe) >= $nc } {
+	set thisparam($this,overlay_coponentscale) 1
+    }
+
+    set range [ [ [ [ $tmap GetImage ] GetPointData] GetScalars] GetRange [ expr $thisparam($this,overlaycurrentframe) -1 ] ]
+
+    set lowrange  [ expr  abs ([ lindex $range 0])]
+    set highrange [ expr  abs ([ lindex $range 1])]
+    
+    if { $highrange<$lowrange } {
+	set highrange $lowrange
+    }
+    
+    catch { $thisparam($this,overlay_minthresholdscale) configure -from 0 -to $highrange }
+    catch { $thisparam($this,overlay_maxthresholdscale) configure -from 0 -to $highrange }
+    
+    if { $highrange > 2000 } {
+	set thisparam($this,overlaymin) 2000
+	set thisparam($this,overlaymax) $highrange
+    } elseif { $highrange > 1000 } {
+	set thisparam($this,overlaymin) 1000
+	set thisparam($this,overlaymax) $highrange
+    } else {
+	set thisparam($this,overlaymin) [expr $highrange / 2.0 ] 
+	set thisparam($this,overlaymax) $highrange
+    } 	
+}
+
+# ---------------------------------------------
+# Compute Overlay
+# ---------------------------------------------
+itcl::body pxitcloverlaytool::ClusterFunctionalImage { funcImage fmriOverlayCreator scaledclusterthreshold minthreshold probscale } {
+
+    set prob 1.0
+    set clusterThreshold [ vtknrImageCluster [ pxvtable::vnewobj ] ]
+
+    if { [ $funcImage GetNumberOfScalarComponents ] > 1 } {
+	set extr [ vtkImageExtractComponents [ pxvtable::vnewobj ]]
+	$extr SetInput $funcImage
+	$extr SetComponents [ expr $thisparam($this,overlaycurrentframe)  -1 ]
+	$clusterThreshold SetInput [ $extr GetOutput ]
+	$extr Delete
+    } else {
+	$clusterThreshold SetInput $funcImage
+    }
+    $clusterThreshold SetIntensityThreshold $thisparam($this,overlaymin)
+    $clusterThreshold Update
+	
+    set cluster_mask_image [ vtkImageData [ pxvtable::vnewobj ] ]
+    $cluster_mask_image ShallowCopy [ $clusterThreshold GetOutput ]
+    
+    scan [ [ [ $cluster_mask_image GetPointData ] GetScalars ] GetRange ] "%f %f" size0 size1
+
+    pxtkprint "Output Range $size0 $size1" 
+    set max_cluster_size  [ expr int($size1 - 1) ]
+    if { $max_cluster_size > 400000 } {
+       set max_cluster_size 400000
+     }
+
+	
+    set imageThreshold [ vtkImageThreshold [ pxvtable::vnewobj ] ]
+    $imageThreshold SetInput [ $clusterThreshold GetOutput ]
+    $imageThreshold ThresholdByUpper $scaledclusterthreshold
+    $imageThreshold ReplaceInOn
+    $imageThreshold SetInValue 255
+    $imageThreshold ReplaceOutOn
+    $imageThreshold SetOutValue 0
+    $imageThreshold SetOutputScalarTypeToUnsignedChar
+    $imageThreshold Update
+    
+    # Multi Frame Mask
+    set imageMask [ vtkpxImageMask [ pxvtable::vnewobj ] ]
+    $imageMask SetInput $funcImage
+    $imageMask SetMask  [ $imageThreshold GetOutput ]
+    $imageMask Update
+    
+    $fmriOverlayCreator SetFmriInput [ $imageMask GetOutput ] 
+
+    $clusterThreshold Delete
+    $imageThreshold Delete 
+    $imageMask Delete
+
+    return $prob
+}
+
+# ---------------------------------------------------------------------------
+
+itcl::body pxitcloverlaytool::CreateOverlay { } {
+    
+    set upd [ ResliceFunctionalImage 0 0 ]
+    if { $upd == 0 } {
+	return 0
+    }
+    
+    WatchOn
+    set fmriOverlayCreator [ vtkpxMergeFmriConventional [ pxvtable::vnewobj ]]
+    $fmriOverlayCreator SetConventional [ $currentimage GetImage ]
+    
+    if { $thisparam($this,cluster_threshold) > 0 } {
+
+	set clustthr $thisparam($this,cluster_threshold)	
+
+	if { $thisparam($this,cluster_scale)  == 1 } {
+
+	    set sp1 [ [ $tmap GetImage ] GetSpacing ] 
+	    set sp2 [ [ $resliced_tmap GetImage ] GetSpacing ]
+	    
+	    set vox1 [ expr [ lindex $sp1 0 ] *  [ lindex $sp1 1 ] *  [ lindex $sp1 2 ]  ]
+	    set vox2 [ expr [ lindex $sp2 0 ] *  [ lindex $sp2 1 ] *  [ lindex $sp2 2 ]  ]
+	    set scale [ expr $vox1 / $vox2 ]
+	    set clustthr [ expr round($scale*$clustthr) ]
+	} 
+
+
+	set prob [ $this ClusterFunctionalImage [ $resliced_tmap GetImage ] $fmriOverlayCreator $clustthr $thisparam($this,overlaymin) $thisparam($this,cluster_threshold_scale)  ]
+	set thisparam($this,overlaysingleframe) 1    
+    } else {
+	$fmriOverlayCreator SetFmriInput    [ $resliced_tmap GetImage ]
+	set prob 1.0
+    }
+    #    catch { $thisparam($this,cluster_threshold_prob) configure -text $prob }
+
+
+    $fmriOverlayCreator SetSingleFrameMode $thisparam($this,overlaysingleframe)
+    $fmriOverlayCreator SetCurrentFrame [ expr $thisparam($this,overlaycurrentframe)  -1 ]
+    $fmriOverlayCreator SetIntensityThreshold [expr round($thisparam($this,overlayinten))]
+    $fmriOverlayCreator SetMinimumThreshold  $thisparam($this,overlaymin)
+    $fmriOverlayCreator SetMaximumThreshold  $thisparam($this,overlaymax)
+    switch -exact $thisparam($this,overlaycmapmode) {
+	"F1"  {  $fmriOverlayCreator SetOutputMode 0 }
+	"F2"  {  $fmriOverlayCreator SetOutputMode 1 }
+	"F4"  {  $fmriOverlayCreator SetOutputMode 2 }
+    }
+	    
+    $fmriOverlayCreator SetNormalizeAnatomical $thisparam($this,overlayanatcmapmode)
+    
+    switch -exact -- $thisparam($this,overlaymode) {
+	"Positive" { $fmriOverlayCreator SetThresholdMode 1}
+	"Both"     { $fmriOverlayCreator SetThresholdMode 3}
+	"Negative" { $fmriOverlayCreator SetThresholdMode 2}
+    }
+    SetFilterCallbacks $fmriOverlayCreator "Creating Overlays"
+    $fmriOverlayCreator Update
+
+    ProcessResultsImage  [ $fmriOverlayCreator GetOutput ] "Overlay" 1
+    $this SetValueImage  [ $fmriOverlayCreator GetFunctionalInput ]
+
+    WatchOff 
+    if { $parent !=0 } {
+	set md 0;
+	switch -exact $thisparam($this,overlaycmapmode) {
+	    "F1"  {  $parent SetLookupTableMode 1 ; set md 0} 
+	    "F2"  {  $parent SetLookupTableMode 2 ; set md 1} 
+	    "F4"  {  $parent SetLookupTableMode 6 ; set md 5} 
+	}
+
+	set viewer 0
+	catch { set viewer [ $parent GetViewer ] }
+	if { $viewer !=0 } {
+	    set scalarbar [ $viewer GetScalarBar ]
+	    set positive 1
+	    if { $thisparam($this,overlaymode) == "Negative"  } { set positive 0 }
+	    set pcmap [ vtkLookupTable [ pxvtable::vnewobj ]] 
+	    set cutil [ vtkpxColorMapUtil [ pxvtable::vnewobj ]] 
+	    $cutil SetScalarBarColormap $pcmap $md $thisparam($this,overlaymin) $thisparam($this,overlaymax) $positive
+	    
+	    $scalarbar SetTitle ""
+	    $scalarbar SetLookupTable $pcmap
+	    $pcmap Delete ; $cutil Delete
+	    [$scalarbar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport
+	    [$scalarbar GetPositionCoordinate] SetValue 0.1 0.1
+	    $scalarbar SetOrientationToHorizontal
+	    $scalarbar SetWidth 0.8
+	    $scalarbar SetHeight 0.9
+	    $scalarbar VisibilityOn
+	}
+    }
+
+    set thisparam($this,updateoperation) "Overlay"
+    $fmriOverlayCreator Delete
+    
+    return 1
+}
+
+itcl::body pxitcloverlaytool::ToggleScalarBar { } { 
+
+    if { $parent != 0 } {
+	[ $parent GetViewer ] ToggleKeyRenderer
+    }
+}
+
+
+# --------------------------------------------------------
+#    Create Image Merge Control 
+# --------------------------------------------------------
+
+itcl::body pxitcloverlaytool::CreateImageMergeControl { parent } {
+    
+    set par [ LabelFrame:create $parent.addp -text "Additional Procedures"]
+    set w [ frame $par.b  ]
+    set w2 [ frame $par.c  ]
+    set w3 [ frame $par.d ]
+    pack $parent.addp -side bottom -fill x -expand f -pady 5
+
+    pack $w $w2  $w3 -side top -expand f -fill x  -pady 2
+    
+    
+    # Image Checker Board
+    # -------------------
+    frame $w.m; pack $w.m  -side top -expand f
+    label $w.m.1 -text "Checker Board Spacing:"
+    tk_optionMenu $w.m.opt [ itcl::scope thisparam($this,checkerboardsize) ] "2" "5" "8" "11" "16" "23" "32"
+    checkbutton $w.m.2 -variable [ itcl::scope thisparam($this,overlayanatcmapmode) ] -text "Normalize Images" 
+    pack $w.m.1 $w.m.opt $w.m.2 -side left -expand f
+    eval "button  $w.m.b1  -text \"Create Checker Board!\" -command { $this CreateCheckerBoard  } "
+    pack $w.m.b1  -side right -expand f -fill x
+    
+    # Image Blend
+    # -------------------
+    frame $w2.top ; pack $w2.top -side top -padx 20 -pady 2
+    
+    label  $w2.top.l -text "Opacity:"
+    scale  $w2.top.s -orient horizontal  -from 0 -to 1 -resolution 0.025 -showvalue 1 -length 150 -variable [ itcl::scope thisparam($this,blendopacity) ]
+    checkbutton $w2.top.c -variable [ itcl::scope thisparam($this,autoupdateblend) ] -text "Auto Update"
+    pack $w2.top.l $w2.top.s $w2.top.c -side left
+    eval "bind $w2.top.s <ButtonRelease> { $this CheckWhetherToUpdateBlend }"
+    eval "button  $w2.top.b1  -text \"Create Blended Images!\" -command { $this CreateImageBlend  } "
+    pack $w2.top.b1  -side left -expand f -fill x
+    
+    
+    # Mask Dilation
+    # -------------------
+    label $w3.1 -text "Dilation of Mask:"
+    tk_optionMenu $w3.opt [ itcl::scope thisparam($this,maskdilation) ]  "1" "2" "3"  "5" "7" "9" "11" "15" "20"
+    eval "button  $w3.2  -text \"Mask Image!\" -command { $this CreateMaskedImage } "
+    pack $w3.1 $w3.opt $w3.2 -side left -expand t -padx 5
+    
+}
+
+
+itcl::body pxitcloverlaytool::CheckWhetherToUpdateBlend { } {
+    if { $thisparam($this,autoupdateblend) == 1 } {
+	$this CreateImageBlend
+    }
+}
+
+itcl::body pxitcloverlaytool::CreateCheckerBoard { } {
+    
+    set upd [ ResliceFunctionalImage  0 0 ]
+    if { $upd == 0 } {
+	return 0
+    }
+    
+    
+    WatchOn
+	set checkerBoardCreator [ vtkpxCreateCheckerBoardImage [ pxvtable::vnewobj ]]
+    $checkerBoardCreator SetInput   [ $currentimage GetImage ]
+    $checkerBoardCreator SetInput2  [ $resliced_tmap GetImage ]
+    $checkerBoardCreator SetSquareSize [expr round($thisparam($this,checkerboardsize))]
+    $checkerBoardCreator SetNormalizeImages  $thisparam($this,overlayanatcmapmode)
+    
+    SetFilterCallbacks $checkerBoardCreator "Creating Checker Board"
+    $checkerBoardCreator Update
+    
+    ProcessResults  $checkerBoardCreator "CheckerBoard" 
+    $checkerBoardCreator Delete
+    WatchOff 
+
+    return 1
+}
+
+itcl::body pxitcloverlaytool::CreateImageBlend { } {
+    
+    set upd [ ResliceFunctionalImage 0 0 ]
+    if { $upd == 0 } {
+	return 0
+    }
+    
+    WatchOn
+    
+    set imcast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+    $imcast2 SetInput [ $resliced_tmap GetImage ]
+    $imcast2 SetOutputScalarType [ [ $currentimage GetImage ] GetScalarType ]
+    $imcast2 Update
+
+    set blendCreator [ vtkImageBlend [ pxvtable::vnewobj ]]
+    $blendCreator AddInput [ $currentimage GetImage ]
+    $blendCreator AddInput [ $imcast2 GetOutput ]
+    $imcast2 Delete 
+    
+    $blendCreator SetOpacity 1 $thisparam($this,blendopacity)
+    SetFilterCallbacks $blendCreator "Blending Images"
+    $blendCreator Update
+    
+    ProcessResults  $blendCreator "Blend" 
+    $blendCreator Delete
+    WatchOff 
+    set thisparam($this,updateoperation) "Blend"
+    return 1
+}
+
+itcl::body pxitcloverlaytool::CreateMaskedImage { } {
+	
+    set upd [ ResliceFunctionalImage 0 0 ]
+    if { $upd == 0 } {
+	return 0
+    }
+    
+    WatchOn
+    
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+    set thr [ vtkImageThreshold [ pxvtable::vnewobj ]]
+    $thr ThresholdByUpper 1.0
+    $thr SetInput [ $resliced_tmap GetImage ]
+    $thr SetInValue 1.0
+    $thr SetOutValue 0.0
+    $thr ReplaceInOn
+    $thr ReplaceOutOn
+    
+    if { $thisparam($this,maskdilation) > 0 } {
+	set dilate  [  vtkImageContinuousDilate3D [ pxvtable::vnewobj ] ]
+	$dilate SetInput [ $thr GetOutput ] 
+	$dilate SetKernelSize $thisparam($this,maskdilation) $thisparam($this,maskdilation) $thisparam($this,maskdilation)
+	SetFilterCallbacks $dilate "Dilating Mask"
+	$dilate Update
+	$img ShallowCopy [ $dilate GetOutput ]
+	$dilate Delete
+    } else {
+	$thr Update
+	$img ShallowCopy [ $thr GetOutput ]
+    }
+    
+    
+    set mask  [  vtkpxImageMask [ pxvtable::vnewobj ] ]
+    $mask SetInput [ $currentimage GetImage ]
+    $mask SetMask  $img
+    SetFilterCallbacks $mask  "Mask x Image"
+    $mask Update
+    
+    ProcessResults  $mask "mask" 
+    $mask Delete
+    $thr Delete
+    
+    WatchOff 
+    
+    return 1
+}
+# -------------------------------------------------------------------------------
+#   Image Join
+# -------------------------------------------------------------------------------
+itcl::body pxitcloverlaytool::CreateImageJoinControl { base }  {
+
+    set basea [ frame $base.a ]
+    pack $basea -side bottom -expand true -fill both
+
+    label $basea.1 -text "Stitching Axis:"
+    radiobutton $basea.2a -variable [itcl::scope thisparam($this,imagejoindirection)] -value "x" -text "X"
+    radiobutton $basea.2b -variable [itcl::scope thisparam($this,imagejoindirection)] -value "y" -text "Y"
+    radiobutton $basea.2c -variable [itcl::scope thisparam($this,imagejoindirection)] -value "z" -text "Z" 
+    iwidgets::entryfield $basea.2d -labeltext "Seam" -fixed 4 -width 4 -validate integer -textvariable [ itcl::scope  thisparam($this,imagejoinboundary) ]
+    checkbutton   $basea.2e  -text "Flip"  -variable [ itcl::scope thisparam($this,imagejoinflip) ]
+    iwidgets::entryfield $basea.2f -labeltext "Pad" -fixed 4 -width 4 -validate integer -textvariable [ itcl::scope  thisparam($this,imagejoinpad) ]
+    eval "button $basea.but  -text \"Stitch Images\" -command { $this JoinImages }"
+    pack $basea.1 $basea.2a $basea.2b $basea.2c $basea.2d $basea.2e $basea.2f $basea.but -side left -expand f -fill x
+}
+
+itcl::body pxitcloverlaytool::JoinImages { } {
+
+    set upd [ ResliceFunctionalImage 0 0 ]
+    if { $upd == 0 } {
+	return 0
+    }
+    
+    set image(1) [ $currentimage GetImage ]
+    set image(2) [ $resliced_tmap GetImage ]
+
+    WatchOn
+    set axis 0
+    switch  $thisparam($this,imagejoindirection) {
+	"y" { set axis 1 } 
+	"z" { set axis 2 } 
+    }
+
+
+    if { $thisparam($this,imagejoinpad) == 0 } {
+	set stitch [ vtkpxImageStitch [ pxvtable::vnewobj ]]
+	$stitch SetAxis $axis
+	$stitch SetInput  $image(1)
+	$stitch SetInput2 $image(2)
+	$stitch SetSeamCoordinate $thisparam($this,imagejoinboundary)
+	$stitch SetFlipOrientation $thisparam($this,imagejoinflip)
+	SetFilterCallbacks $stitch "Stitching Images"
+	$stitch Update
+    
+	ProcessResults  $stitch "Stitched" 
+	$stitch Delete
+    } else {
+	set resl [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+	$resl OptimizationOff
+	set trans  [  vtkIdentityTransform [ pxvtable::vnewobj ] ]	
+
+	set spa [ [ $currentimage GetImage ] GetSpacing ]
+	set ori [ [ $currentimage GetImage ] GetOrigin ]
+	set dim [ [ $currentimage GetImage ] GetDimensions ]
+	set voi0 [ list   0 0 0 ]
+	set voi1 [ list   [ expr [ lindex $dim 0 ] -1 ]  [ expr [ lindex $dim 1 ] -1 ]  [ expr [ lindex $dim 2 ] -1 ]  ]
+
+	set seampoint $thisparam($this,imagejoinboundary)
+	
+	for { set i 0 } { $i <=2 } { incr i } {
+	    set x0 [ expr round([ lindex $voi0 $i ]) ]
+	    set x1 [ expr round([ lindex $voi1 $i ]) ]
+
+	    if { $axis == $i } {
+		set dpad [ expr abs($thisparam($this,imagejoinpad)) ]
+		if {  $thisparam($this,imagejoinflip) == 0 } {
+		    set x1 [ expr $x1 + $dpad ]
+		} else {
+		    set x0 [ expr $x0 - $dpad ]
+		    if { $seampoint > 0 } {
+			set seampoint [ expr $seampoint + $dpad ]
+		    }
+		}
+	    }
+
+	    if { $x1 < $x0 } { set x1 [ expr $x0 ] }
+	    
+	    set origin($i)  [ expr [lindex $ori $i ] + $x0 * [ lindex $spa $i ]]
+	    set spacing($i) [lindex $spa $i ]
+	    set ext($i)     [ expr ($x1-$x0) ]
+	}
+
+	#puts stdout "origin = $origin(0) $origin(1) $origin(2) vs  $ori "
+	#puts stdout "spacing = $spacing(0) $spacing(1) $spacing(2) vs  $spa "
+	#puts stdout "ext = $ext(0) $ext(1) $ext(2) vs  $dim "
+    
+	$resl SetInput [ $currentimage GetImage ]
+	$resl SetResliceTransform $trans
+	$resl SetOutputSpacing $spacing(0) $spacing(1) $spacing(2)
+	$resl SetOutputOrigin  $origin(0)  $origin(1)  $origin(2)
+	$resl SetOutputExtent  0 $ext(0) 0 $ext(1) 0 $ext(2)
+	$resl SetInterpolationMode 0 
+	SetFilterCallbacks $resl "Padding Reference Image"
+	$resl Update
+
+	set resl2 [ vtkbisImageReslice [ pxvtable::vnewobj ]]
+	$resl2 OptimizationOff
+	set current_transform [ $this GetTransformation ]
+	set image_trn [ $tmap GetImage ]
+	
+	$resl2 SetInformationInput [ $resl GetOutput ]
+	$resl2 SetInput $image_trn
+	$resl2 SetInterpolationModeTo$thisparam($this,resliceinterp)
+	$resl2 SetBackgroundLevel 0.0
+	$resl2 SetResliceTransform $current_transform
+	SetFilterCallbacks $resl "Reslicing Target Image"
+	$resl2 Update
+
+	set stitch [ vtkpxImageStitch [ pxvtable::vnewobj ]]
+	$stitch SetAxis            $axis
+	$stitch SetInput           [ $resl GetOutput ] 
+	$stitch SetInput2          [ $resl2 GetOutput ]
+	$stitch SetSeamCoordinate  $seampoint 
+	$stitch SetFlipOrientation $thisparam($this,imagejoinflip)
+	SetFilterCallbacks $stitch "Stitching Images"
+	$stitch Update
+    
+	ProcessResults  $stitch "Stitched" 
+	$stitch Delete
+
+	$resl Delete
+	$resl2 Delete
+	$trans Delete
+    }
+	
+    WatchOff 
+    return 1
+}
+# -------------------------------------------------------------------------------
+
+itcl::body pxitcloverlaytool::ComputeROIStatistics { } {
+	
+
+    set current_transform [ $this GetTransformation ]
+    set image_ref [ $currentimage GetImage ]
+    set image_trn [ $tmap GetImage ]
+    set dim1 [ $image_ref GetDimensions ]
+    set dim2 [ $image_trn GetDimensions ]
+    if { [lindex $dim2 0 ] <2 || [ lindex $dim1 0 ] < 2 } { 
+	::pxtclutil::Warning "No Image in Memory\n Cannot Reslice!"
+	return  0
+    }
+
+    WatchOn
+    
+    set thr [ vtkpxMergeFmriConventional [ pxvtable::vnewobj ]]
+    set arr [ vtkFloatArray [ pxvtable::vnewobj ]]
+    set nt [  $thr ComputeROIStatistics $image_ref $image_trn $current_transform $arr]
+
+    if { $nt > 0 } {
+	pxtkconsole
+	pxtkprint "ROI Statistics for reference image  (and roi image resliced using current transformation)\n"
+	set total  0
+	set totalv 0 
+
+	for { set i 0 } { $i < [ $arr GetNumberOfTuples ] } { incr i } {
+	    set a1 [ expr round([ $arr GetComponent $i 0 ])]
+	    set a2 [ expr round([ $arr GetComponent $i 1 ])]
+	    set a3 [ $arr GetComponent $i 3 ]
+	    set a4 [ $arr GetComponent $i 4 ]
+	    set n1 [ expr round([ $arr GetComponent $i 2 ])]
+	    set v1 [ expr round([ $arr GetComponent $i 6 ])]
+	    set n2 [ expr round([ $arr GetComponent $i 5 ])]
+	    set v2 [ expr round([ $arr GetComponent $i 7 ])]
+
+	    if { $n1 >  0 } {
+		pxtkprint [ format "Frame %3d\t Level=%5.1f:\t m=%5.2f s=%5.2f\t nvox=%7d (%.1f mm^3) nvox>0=%7d (%.1f mm^3)\n" $a1 $a2 $a3 $a4 $n1 $v1 $n2 $v2 ]
+	    }
+
+	    if { $a2 > 0 } {
+		set total [ expr $total + $n2 ]
+		set totalv [ expr $totalv + $v2 ]
+	    }
+	}
+	pxtkprint [ format "Total volume for levels >0  nvox>0 = %d  (%.1f mm^3)\n\n" $total $totalv ]
+    }
+
+    $thr Delete
+    $arr Delete
+    
+    WatchOff 
+    
+    return 1
+}
+
+
+
+# -------------------------------------------------------------------------------
+#  Registration Stuff
+# -------------------------------------------------------------------------------
+
+itcl::body pxitcloverlaytool::UpdateFromRegistration { current_registration } {
+
+    if { [ $current_registration GetProgress ] == 1.0 } {
+	$this UpdateFromRegistrationDone $current_registration
+	return
+    } 
+
+    puts stderr "[ $current_registration GetOutputStatus ]"
+
+    set thisparam($this,reg_updatecount)  [ expr $thisparam($this,reg_updatecount) + 1 ]
+    if { $thisparam($this,reg_updatecount) >= $thisparam($this,reg_updatesample) } {
+	SetTransformation  [ $current_registration GetUpdateTransform ]
+	Update
+	WatchOn
+	set thisparam($this,reg_updatecount) 0
+    }
+    $this ProgressCallback  $current_registration "Registering Images"
+}
+
+itcl::body pxitcloverlaytool::UpdateFromRegistrationDone { current_registration } {
+
+    pxtkprint "[ $current_registration GetOutputStatus ]"
+    if { [ $current_registration IsA "vtkpxLinearRegistration" ] == 1 } {
+	SetTransformation   [ $current_registration GetUpdateTransform ]
+    } else {
+	SetTransformation   [ $current_registration GetTransformation ]
+    }
+    eval "$this ProgressCallback  $current_registration Done" 
+    Update
+}
+
+itcl::body pxitcloverlaytool::AutoSaveTransformation { } {
+
+    set newtr [ $this GetTransformation ]
+    set n0 [ file dirname [ $tmap cget -filename ] ]
+    set n1 [ file tail [ $currentimage cget -filename ] ]
+    set n2 [ file tail [ file rootname [ $tmap cget -filename ] ] ]
+    set suffix "matr"
+
+    
+    if { [ $newtr IsA "vtkGridTransform" ] == 1 } {
+	set suffix "grd"
+    } elseif { [ $newtr IsA "vtkpxComboTransform" ] == 1 } {
+	set suffix "grd"
+    } elseif { [ $newtr IsA "vtkThinPlateSplineTransform" ] == 1 } {
+	set suffix "tps"
+    }
+
+    set mname [ file join $n0 "${n1}_${n2}.${suffix}" ]
+    set ok 1
+    
+    if { $thisparam($this,reg_autooverwrite) == 0 } {
+	if { [ file exists $mname ] ==1 } {
+	    set ok [ ::pxtclutil::Question "Saving transformation in $mname will overwrite existing file. Are you sure?"]
+	}
+    }
+
+    if { $ok == 1 } {
+
+	set ok [ [ $transform_control GetCurrentObject ] Save $mname "" ]
+    
+	if { $ok == 1 } {
+	    ::pxtclutil::Info " Transformation Saved in $mname!"
+	    $transform_control CurrentObjectModified
+	}
+    }
+}
+
+# -----------------------------------------------------
+# Affine transformation
+# -------------------------------------------------------------------------------
+
+itcl::body pxitcloverlaytool::AffineControlSetMode { mode } {
+    
+    switch $mode {
+	"rigid2d" {
+	    set thisparam($this,areg_tx) 1 ; 	set thisparam($this,areg_ty) 1; 	set thisparam($this,areg_tz) 0 ;
+	    set thisparam($this,areg_rx) 0 ; 	set thisparam($this,areg_ry) 0; 	set thisparam($this,areg_rz) 1 ;
+	    set thisparam($this,areg_sx) 0 ; 	set thisparam($this,areg_sy) 0; 	set thisparam($this,areg_sz) 0 ;
+	    set thisparam($this,areg_ax) 0 ; 	set thisparam($this,areg_ay) 0; 	set thisparam($this,areg_az) 0 ;
+	}
+	"rigid" {
+	    set thisparam($this,areg_tx) 1 ; 	set thisparam($this,areg_ty) 1; 	set thisparam($this,areg_tz) 1 ;
+	    set thisparam($this,areg_rx) 1 ; 	set thisparam($this,areg_ry) 1; 	set thisparam($this,areg_rz) 1 ;
+	    set thisparam($this,areg_sx) 0 ; 	set thisparam($this,areg_sy) 0; 	set thisparam($this,areg_sz) 0 ;
+	    set thisparam($this,areg_ax) 0 ; 	set thisparam($this,areg_ay) 0; 	set thisparam($this,areg_az) 0 ;
+	}
+	"similarity" {
+	    set thisparam($this,areg_tx) 1 ; 	set thisparam($this,areg_ty) 1; 	set thisparam($this,areg_tz) 1 ;
+	    set thisparam($this,areg_rx) 1 ; 	set thisparam($this,areg_ry) 1; 	set thisparam($this,areg_rz) 1 ;
+	    set thisparam($this,areg_sx) 1 ; 	set thisparam($this,areg_sy) 1; 	set thisparam($this,areg_sz) 1 ;
+	    set thisparam($this,areg_ax) 0 ; 	set thisparam($this,areg_ay) 0; 	set thisparam($this,areg_az) 0 ;
+	}
+	"affine" {
+	    set thisparam($this,areg_tx) 1 ; 	set thisparam($this,areg_ty) 1; 	set thisparam($this,areg_tz) 1 ;
+	    set thisparam($this,areg_rx) 1 ; 	set thisparam($this,areg_ry) 1; 	set thisparam($this,areg_rz) 1 ;
+	    set thisparam($this,areg_sx) 1 ; 	set thisparam($this,areg_sy) 1; 	set thisparam($this,areg_sz) 1 ;
+	    set thisparam($this,areg_ax) 1 ; 	set thisparam($this,areg_ay) 1; 	set thisparam($this,areg_az) 1 ;
+	}
+    }
+}
+
+itcl::body pxitcloverlaytool::CreateImageAffineControl { parent } {
+
+    label $parent.o -bg black -fg white -text "Rigid/Affine Registration"
+    pack $parent.o -side top -expand f -fill x
+    
+    set nt $parent.note 
+    iwidgets::tabnotebook $nt -tabpos n -angle 45 -margin 2 -backdrop gray -raiseselect true
+    pack $nt -side bottom -expand t -fill both
+
+    set simp [ $nt add -label "Simple" ]
+    set adv    [ $nt add -label "Advanced" ]
+
+    $nt view "Simple" 
+	     
+    # Simple Controls
+
+    set p1 [ frame $simp.top ]
+    set p2 [ frame $simp.mid ]
+    set p2a [ frame $simp.mid2 ]
+    set p3 [ frame $simp.bot ]
+    pack $p1 $p2 $p2a $p3 -side top -expand f -fill x -pady 5 -padx 10
+
+    label $p1.lab2 -text "Resolution"
+    tk_optionMenu $p1.res [ itcl::scope thisparam($this,areg_resolution) ] "-1.0" "0.5" "0.8" "1.0" "1.1" "1.2" "1.5" "2.0" "4.0" "6.0" "8.0" "10.0" "40.0"
+    pack $p1.lab2 $p1.res -side left -expand f -fill x	
+
+    checkbutton $p2.c1 -variable [ itcl::scope thisparam($this,areg_autosave) ] -text "Auto Save Results" 
+    checkbutton $p2.c2 -variable [ itcl::scope thisparam($this,areg_autooverwrite) ] -text "Overwrite Older Results" 
+    pack $p2.c1 $p2.c2 -side left -expand f -fill x -padx 5 -pady 5
+
+    checkbutton $p2a.c -variable [ itcl::scope thisparam($this,areg_usecurrent) ] -text "Use Current Transform For Initialization" 
+    pack $p2a.c -side left -expand t -fill x -padx 10
+
+    eval "button $p3.b1 -text \"Rigid\" -command { $this AffineControlSetMode rigid; $this ComputeAffineRegistration } "
+    eval "button $p3.b1n -text \"Rigid 2D\" -command { $this AffineControlSetMode rigid2d; $this ComputeAffineRegistration } "
+    #    eval "button $p3.b2 -text \"Reorient Image\" -command { $this ComputeReorientationRegistration } "
+    eval "button $p3.b3 -text \"Affine\" -command { $this AffineControlSetMode affine; $this ComputeAffineRegistration} "
+
+    pack $p3.b1 $p3.b1n $p3.b3 -side left -padx 10 -expand t -fill x 
+   
+    lappend thisparam($this,buttonlist) $p3.b1 $p3.b1n $p3.b3
+
+    # Advance Stuff 
+
+    frame $adv.m ; frame $adv.n ; frame $adv.o ;frame $adv.p ; frame $adv.p2 ; frame $adv.p3; frame $adv.u ; frame $adv.v ; frame $adv.i ;
+    pack  $adv.m -pady 20
+    pack  $adv.n $adv.o $adv.p $adv.p2 $adv.p3 $adv.i $adv.v $adv.u -side top -pady 2
+  
+    
+    checkbutton $adv.m.tx -variable [ itcl::scope thisparam($this,areg_tx) ] -text "X-Trans" ; grid $adv.m.tx -column 0 -row 0
+    checkbutton $adv.m.ty -variable [ itcl::scope thisparam($this,areg_ty) ] -text "Y-Trans" ; grid $adv.m.ty -column 0 -row 1
+    checkbutton $adv.m.tz -variable [ itcl::scope thisparam($this,areg_tz) ] -text "Z-Trans" ; grid $adv.m.tz -column 0 -row 2
+    
+    checkbutton $adv.m.rx -variable [ itcl::scope thisparam($this,areg_rx) ] -text "X-Rot" ; grid $adv.m.rx -column 1 -row 0
+    checkbutton $adv.m.ry -variable [ itcl::scope thisparam($this,areg_ry) ] -text "Y-Rot" ; grid $adv.m.ry -column 1 -row 1
+    checkbutton $adv.m.rz -variable [ itcl::scope thisparam($this,areg_rz) ] -text "Z-Rot" ; grid $adv.m.rz -column 1 -row 2
+    
+    checkbutton $adv.m.sx -variable [ itcl::scope thisparam($this,areg_sx) ] -text "X-Scale" ; grid $adv.m.sx -column 2 -row 0
+    checkbutton $adv.m.sy -variable [ itcl::scope thisparam($this,areg_sy) ] -text "Y-Scale" ; grid $adv.m.sy -column 2 -row 1
+    checkbutton $adv.m.sz -variable [ itcl::scope thisparam($this,areg_sz) ] -text "Z-Scale" ; grid $adv.m.sz -column 2 -row 2
+    
+    checkbutton $adv.m.ax -variable [ itcl::scope thisparam($this,areg_ax) ] -text "X-Shear" ; grid $adv.m.ax -column 3 -row 0
+    checkbutton $adv.m.ay -variable [ itcl::scope thisparam($this,areg_ay) ] -text "Y-Shear" ; grid $adv.m.ay -column 3 -row 1
+    checkbutton $adv.m.az -variable [ itcl::scope thisparam($this,areg_az) ] -text "Z-Shear" ; grid $adv.m.az -column 3 -row 2
+    
+    eval "button $adv.m.b1 -text Rigid -command { $this AffineControlSetMode rigid} "
+    eval "button $adv.m.b2 -text Similarity -command { $this AffineControlSetMode similarity} "
+    eval "button $adv.m.b3 -text Affine -command { $this AffineControlSetMode affine} "
+    grid $adv.m.b1 -column 4 -row 0
+    grid $adv.m.b2 -column 4 -row 1
+    grid $adv.m.b3 -column 4 -row 2
+    
+    label $adv.n.lab2 -text "Resolution"
+    tk_optionMenu $adv.n.res [ itcl::scope thisparam($this,areg_resolution) ] "-1.0" "0.5" "0.8" "1.0" "1.1" "1.2" "1.5" "2.0" "4.0" "6.0" "8.0" "10.0"
+    pack $adv.n.lab2 $adv.n.res -side left -expand f -fill x	
+    
+    
+    label $adv.n.lab3 -text "Mode:"
+    eval "tk_optionMenu $adv.n.res3 [ itcl::scope thisparam($this,reg_measure)] $reg_measures "
+    pack $adv.n.lab3 $adv.n.res3  -side left -expand f -fill x	
+
+    checkbutton $adv.o.auton  -text "Auto Normalize" -variable [ itcl::scope thisparam($this,areg_autonormalize) ]
+    checkbutton $adv.o.jointn -text "Jointly Normlz" -variable [ itcl::scope thisparam($this,areg_jointlynormalize) ]
+    checkbutton $adv.o.posm -text "Pos Inten" -variable [ itcl::scope thisparam($this,areg_positive) ]
+    checkbutton $adv.o.logm -text "Logarithm" -variable [ itcl::scope thisparam($this,areg_logmode) ]
+    pack $adv.o.auton $adv.o.jointn $adv.o.posm $adv.o.logm -side left -expand f -fill x	        
+
+
+    label $adv.p.lab -text "Number Of Levels/Steps"
+    tk_optionMenu $adv.p.res [ itcl::scope thisparam($this,areg_numlevels) ] 1 2 3
+    tk_optionMenu $adv.p.res1 [ itcl::scope thisparam($this,areg_numsteps) ] 1 2 3 4
+    label $adv.p.lab2 -text "Step Size(vx)"
+    tk_optionMenu $adv.p.res2 [ itcl::scope thisparam($this,areg_stepsize) ] 0.05 0.1 0.25 0.5 1.0 2.0 3.0 4.0
+    pack $adv.p.lab $adv.p.res $adv.p.res1 $adv.p.lab2 $adv.p.res2 -side left -expand f -fill x	
+    
+    label $adv.p2.lab2 -text "Opt Method"
+    eval "tk_optionMenu $adv.p2.res2 [ itcl::scope thisparam($this,areg_optmethod) ] $opt_methods"
+    label $adv.p2.lab3 -text "Iterations"
+    tk_optionMenu $adv.p2.res3 [ itcl::scope thisparam($this,areg_iterations) ] 5 10 15 20 25 30 
+
+    pack $adv.p2.lab2 $adv.p2.res2 $adv.p2.lab3 $adv.p2.res3  -side left -expand f -fill x	
+
+    #pack $adv.p2.lab2 $adv.p2.res2  -side left -expand f -fill x	
+
+
+    label $adv.p3.lab2 -text "Interpolation Mode"
+    tk_optionMenu $adv.p3.res2 [ itcl::scope thisparam($this,areg_interpmode) ] -5 -4 -3 -2 0 1 3
+    pack $adv.p3.lab2 $adv.p3.res2 -side left -expand f -fill x	
+    
+
+    checkbutton $adv.v.c1 -variable [ itcl::scope thisparam($this,areg_autosave) ] -text "Auto Save Results" 
+    checkbutton $adv.v.c2 -variable [ itcl::scope thisparam($this,areg_autooverwrite) ] -text "Overwrite Older Results" 
+    pack $adv.v.c1 $adv.v.c2 -side left -expand t -fill x -padx 5 -pady 5
+    
+    checkbutton $adv.i.c -variable [ itcl::scope thisparam($this,areg_usecurrent) ] -text "Use Current Transform For Initialization" 
+    pack $adv.i.c -side left -expand t -fill x -padx 10
+    
+    label $adv.u.lab1 -text "Update Display Every:"
+    tk_optionMenu $adv.u.param [ itcl::scope thisparam($this,reg_updatesample) ] "1" "2" "5" "10" "20" "100"  
+    label $adv.u.lab2 -text "Iterations"
+    pack $adv.u.lab1 $adv.u.param $adv.u.lab2 -side left -expand f -fill x -pady 5
+    
+    
+    eval "button $adv.c -text \"Compute Linear Registration\" -command { $this ComputeAffineRegistration }"
+    pack $adv.c -side bottom -expand f -fill x -padx 20
+    lappend thisparam($this,buttonlist) $adv.c
+
+    ::pxitclbasecontrol::SetWidgetTreeColors $adv "\#aaabd7" "black"
+}
+
+
+itcl::body pxitcloverlaytool::CreateImageNonLinearControl { parent } {
+
+    label $parent.o -bg black -fg white -text "Non-rigid Intensity Based-Registration"
+    pack $parent.o -side top -expand f -fill x
+    
+    set nt $parent.note 
+    iwidgets::tabnotebook $nt -tabpos n  -angle 45 -margin 2 -backdrop gray -raiseselect true
+    pack $nt -side bottom -expand t -fill both
+
+    set simp [ $nt add -label "Simple" ]
+    set w    [ $nt add -label "Advanced" ]
+    $nt view "Simple"
+    set adv $w 
+    
+    # Simple Controls
+    set p1 [ frame $simp.top ]
+    set p2 [ frame $simp.mid ]
+    set p3 [ frame $simp.bot ]
+    pack $p1 $p2 $p3 -side top -expand f -fill x -pady 5 -padx 10
+    
+
+    label $p1.lab2 -text "Resolution (vx)"
+    tk_optionMenu $p1.res2 [ itcl::scope thisparam($this,nreg_resolution) ] "0.0" "1.0" "1.1" "1.2" "1.5" "2.0" "2.5" "3.0" "3.5" "4.0" "5.0"
+    label $p1.lab1 -text "Control Spacing (mm)"
+    tk_optionMenu $p1.res1 [ itcl::scope thisparam($this,nreg_spacing) ] 1.0 1.1 1.2 1.5 2.0 3.0 5.0 6.0 8.0 10.0 12.0 15.0 20.0 24.0 30.0 32.0 40.0 45.0 50.0 
+    pack $p1.lab2 $p1.res2 $p1.lab1 $p1.res1  -side left -expand f -fill x	
+
+    checkbutton $p2.c1 -variable [ itcl::scope thisparam($this,nreg_autosave) ] -text "Auto Save" 
+    checkbutton $p2.c2 -variable [ itcl::scope thisparam($this,nreg_autooverwrite) ] -text "Overwrite Older"
+    pack $p2.c1 $p2.c2  -side left -expand t -fill x -padx 5 -pady 5
+    
+    eval "button $p3.2 -text \"Compute Linear + Non Linear Registration\" -command { $this ComputeCombinedRegistration registration }"
+    pack $p3.2   -side left -expand f -fill x -padx 5 -pady 5
+    lappend thisparam($this,buttonlist) $p3.2
+
+ 
+    # Advanced Controls
+    frame $w.m ; frame $w.n ; frame $w.o ; frame $w.p ; frame $w.p2 ; frame $w.u ; frame $w.v ; frame $w.i
+    pack $w.n $w.o $w.m $w.p $w.p2 $w.i $w.v $w.u -side top -pady 2
+    
+    label $w.n.lab2 -text "Resolution (vx)"
+    tk_optionMenu $w.n.res2 [ itcl::scope thisparam($this,nreg_resolution) ] "0.0" "1.0" "1.1" "1.2" "1.5" "2.0" "2.5" "3.0" "3.5" "4.0" "5.0"
+    label $w.n.lab1 -text "Control Spacing/Rate (mm)"
+    tk_optionMenu $w.n.res1 [ itcl::scope thisparam($this,nreg_spacing) ] 1.0 1.1 1.2 1.5 2.0 3.0 5.0 6.0 8.0 10.0 12.0 15.0 20.0 24.0 30.0 32.0 40.0 45.0 50.0 
+    tk_optionMenu $w.n.res3 [ itcl::scope thisparam($this,nreg_spacingrate) ] 1.0 1.5 2.0
+    pack $w.n.lab2 $w.n.res2 $w.n.lab1 $w.n.res1 $w.n.res3 -side left -expand f -fill x	
+    
+    checkbutton $w.o.auton  -text "Auto Normalize" -variable [ itcl::scope thisparam($this,nreg_autonormalize) ]
+    checkbutton $w.o.jointn -text "Jointly Normlz" -variable [ itcl::scope thisparam($this,nreg_jointlynormalize) ]
+    checkbutton $w.o.posm -text "Pos Inten" -variable [ itcl::scope thisparam($this,nreg_positive) ]
+    checkbutton $w.o.logm -text "Logarithm" -variable [ itcl::scope thisparam($this,nreg_logmode) ]
+    pack $w.o.auton $w.o.jointn $w.o.posm $w.o.logm -side left -expand f -fill x	        
+
+
+    label $w.m.lab3 -text "Levels/Steps"
+    tk_optionMenu $w.m.res3 [ itcl::scope thisparam($this,nreg_numlevels) ] 1 2 3
+    tk_optionMenu $w.m.res4 [ itcl::scope thisparam($this,nreg_numsteps) ] 1 2 3 4
+    label $w.m.lab5 -text "Step Size (vx)"
+    tk_optionMenu $w.m.res5 [ itcl::scope thisparam($this,nreg_stepsize) ] 0.25 0.5 1.0 2.0 3.0 4.0 8.0 12.0 16.0
+    pack $w.m.lab3 $w.m.res3 $w.m.res4  $w.m.lab5 $w.m.res5 -side left -expand f -fill x	
+    
+    label $w.p.lab3 -text "Mode:"
+    eval "tk_optionMenu $w.p.res3 [ itcl::scope thisparam($this,reg_measure) ] $reg_measures"
+
+    pack $w.p.lab3 $w.p.res3   -side left -expand f -fill x	
+    label $w.p.lab4 -text "Smoothness:"
+    entry $w.p.res4 -textvariable [ itcl::scope thisparam($this,nreg_smoothness) ] -width 5 -relief sunken
+    pack $w.p.lab4 $w.p.res4 -side left -expand f -fill x	
+   
+    label $w.p2.lab2 -text "Opt Method"
+    eval "tk_optionMenu $w.p2.res2 [ itcl::scope thisparam($this,nreg_optmethod) ] $nopt_methods"
+
+    label $w.p2.lab3 -text "Iterations"
+    tk_optionMenu $w.p2.res3 [ itcl::scope thisparam($this,nreg_iterations) ] 1 5 10 15 20 25 30 
+
+    label $w.p2.lab4 -text "GScale:"
+    tk_optionMenu $w.p2.res4 [ itcl::scope thisparam($this,nreg_gscale) ] 0.1 0.5 1.0 2.0 4.0 8.0 16.0
+
+    pack $w.p2.lab2 $w.p2.res2 $w.p2.lab3 $w.p2.res3 $w.p2.lab4 $w.p2.res4 -side left -expand f -fill x	
+       
+       
+    checkbutton $w.v.c1 -variable [ itcl::scope thisparam($this,nreg_autosave) ] -text "Auto Save Results" 
+    checkbutton $w.v.c2 -variable [ itcl::scope thisparam($this,nreg_autooverwrite) ] -text "Overwrite Older Results" 
+    pack $w.v.c1 $w.v.c2 -side left -expand t -fill x -padx 5 -pady 5
+    
+    checkbutton $w.i.c -variable [ itcl::scope thisparam($this,nreg_usecurrent) ] -text "Use Current Transform For Initialization" 
+    checkbutton $w.i.d -variable [ itcl::scope thisparam($this,nreg_useprior) ] -text "For Prior" 
+    pack $w.i.c $w.i.d -side left -expand t -fill x -padx 5
+
+
+    label $w.u.lab1 -text "Update Display Every:"
+    tk_optionMenu $w.u.param [ itcl::scope thisparam($this,reg_updatesample) ] "1" "2" "5" "10" "20" "100"  
+    label $w.u.lab2 -text "Iterations"
+    pack $w.u.lab1 $w.u.param $w.u.lab2 -side left -expand f -fill x -pady 5
+	
+    eval "button $w.c -text \"Compute Non Linear Registration\" -command { $this ComputeNonLinearRegistration  }"
+    eval "button $w.d -text \"Compute Linear + Non Linear Registration\" -command { $this ComputeCombinedRegistration registration }"
+    lappend  thisparam($this,buttonlist) $w.c
+    lappend  thisparam($this,buttonlist) $w.d
+    pack $w.d $w.c -side bottom -expand f -fill x -padx 5
+
+    ::pxitclbasecontrol::SetWidgetTreeColors $adv "\#aaabd7" "black"
+}
+
+
+itcl::body pxitcloverlaytool::CreateImageDistortionCorrectionControl { parent } {
+
+    label $parent.o -bg black -fg white -text "Distortion Correction for EPI"
+    pack $parent.o -side top -expand f -fill x
+    
+    set nt $parent.note 
+    iwidgets::tabnotebook $nt -tabpos n  -angle 45 -margin 2 -backdrop gray -raiseselect true
+    pack $nt -side bottom -expand t -fill both
+
+    set simp [ $nt add -label "Simple" ]
+    set w    [ $nt add -label "Advanced" ]
+
+    $nt view "Simple"
+    set adv $w
+    
+    # Simple Controls
+    set p1 [ frame $simp.top ]
+    set p2 [ frame $simp.mid ]
+    set p3 [ frame $simp.bot ]
+    pack $p1 $p2 $p3 -side top -expand f -fill x -pady 5 -padx 10
+    
+
+    label $p1.lab2 -text "Resolution (vx)"
+    tk_optionMenu $p1.res2 [ itcl::scope thisparam($this,dist_resolution) ] "0.0" "1.0" "1.1" "1.2" "1.5" "2.0" "2.5" "3.0" "3.5" "4.0" "5.0" "8.0"
+    label $p1.lab1 -text "Control Spacing (mm)"
+    tk_optionMenu $p1.res1 [ itcl::scope thisparam($this,dist_spacing) ] 5.0 6.0 8.0 10.0 12.0 15.0 20.0 24.0 30.0 32.0 40.0 45.0 50.0 
+    pack $p1.lab2 $p1.res2 $p1.lab1 $p1.res1 -side left -expand f -fill x	
+    
+    #    label $p1.lab5 -text "Step Size (vx)"
+    #    tk_optionMenu $p1.res5 [ itcl::scope thisparam($this,dist_stepsize) ] 0.25 0.5 1.0 2.0 3.0 4.0 8.0 12.0 16.0
+    #    pack  $p1.lab5 $p1.res5 -side left -expand f -fill x	
+    
+    checkbutton $p2.c1 -variable [ itcl::scope thisparam($this,dist_autosave) ] -text "Auto Save" 
+    checkbutton $p2.c2 -variable [ itcl::scope thisparam($this,dist_autooverwrite) ] -text "Overwrite Older"
+    pack $p2.c1 $p2.c2  -side left -expand t -fill x -padx 5 -pady 5
+    
+    #eval "button $p3.1 -text \"Compute Distortion Correction\" -command { $this ComputeDistortionCorrection  }"
+    eval "button $p3.2 -text \"Compute Linear + Distortion Correction\" -command { $this ComputeCombinedRegistration distortion }"
+    pack $p3.2   -side left -expand f -fill x -padx 5 -pady 5
+    lappend thisparam($this,buttonlist) $p3.2 
+
+    # Advanced Stuff
+    frame $w.m ; frame $w.n ; frame $w.p ; frame $w.p2 ; frame $w.u ; frame $w.v ; frame $w.i ; frame $w.j
+    pack  $w.n $w.m $w.p $w.p2 $w.j $w.i $w.v $w.u -side top -pady 2
+    
+    label $w.n.lab2 -text "Resolution (vx)"
+    tk_optionMenu $w.n.res2 [ itcl::scope thisparam($this,dist_resolution) ] "0.0" "1.0" "1.1" "1.2" "1.5" "2.0" "2.5" "3.0" "3.5" "4.0" "5.0" "8.0"
+    label $w.n.lab1 -text "Control Spacing/Rate (mm)"
+    tk_optionMenu $w.n.res1 [ itcl::scope thisparam($this,dist_spacing) ] 5.0 6.0 8.0 10.0 12.0 15.0 20.0 24.0 30.0 32.0 40.0 45.0 50.0 
+    tk_optionMenu $w.n.res3 [ itcl::scope thisparam($this,dist_spacingrate) ] 1.0 1.5 2.0
+    pack $w.n.lab2 $w.n.res2 $w.n.lab1 $w.n.res1 $w.n.res3 -side left -expand f -fill x	
+    
+    
+    label $w.m.lab3 -text "Levels/Steps"
+    tk_optionMenu $w.m.res3 [ itcl::scope thisparam($this,dist_numlevels) ] 1 2 3
+    tk_optionMenu $w.m.res4 [ itcl::scope thisparam($this,dist_numsteps) ] 1 2 3 4
+    label $w.m.lab5 -text "Step Size (vx)"
+    tk_optionMenu $w.m.res5 [ itcl::scope thisparam($this,dist_stepsize) ] 0.25 0.5 1.0 2.0 3.0 4.0 8.0 12.0 16.0
+    pack $w.m.lab3 $w.m.res3 $w.m.res4  $w.m.lab5 $w.m.res5 -side left -expand f -fill x	
+    
+    label $w.p.lab4 -text "Smoothness:"
+    entry $w.p.res4 -textvariable [ itcl::scope thisparam($this,dist_smoothness) ] -width 5 -relief sunken
+    checkbutton $w.p.chk3 -variable [ itcl::scope thisparam($this,dist_logmode) ] -text "Logarithm Mode" 
+
+    label $w.p.lab5 -text "Adjust:"
+    tk_optionMenu $w.p.res5 [ itcl::scope thisparam($this,dist_jackmode) ] "None" "Signal Conservation" 
+    #"Signal Loss"
+
+    #checkbutton $w.p.chk4 -variable [ itcl::scope thisparam($this,dist_jackmode) ] -text "Jacobian Mode" 
+    pack $w.p.lab4 $w.p.res4 $w.p.chk3 $w.p.lab5 $w.p.res5 -side left -expand f -fill x	
+   
+    label $w.p2.lab2 -text "Opt Method"
+    eval "tk_optionMenu $w.p2.res2 [ itcl::scope thisparam($this,dist_optmethod) ] $nopt_methods"
+
+    label $w.p2.lab3 -text "Iterations"
+    tk_optionMenu $w.p2.res3 [ itcl::scope thisparam($this,dist_iterations) ] 5 10 15 20 25 30 
+    pack $w.p2.lab2 $w.p2.res2 $w.p2.lab3 $w.p2.res3  -side left -expand f -fill x	
+       
+
+    label $w.j.lab2 -text "Phase - encode direction:"
+    tk_optionMenu $w.j.res2 [ itcl::scope thisparam($this,dist_warp) ] "X" "Y" "Z"
+    pack $w.j.lab2 $w.j.res2 -side left -expand f -fill x
+       
+    checkbutton $w.v.c1 -variable [ itcl::scope thisparam($this,dist_autosave) ] -text "Auto Save Results" 
+    checkbutton $w.v.c2 -variable [ itcl::scope thisparam($this,dist_autooverwrite) ] -text "Overwrite Older Results" 
+    pack $w.v.c1 $w.v.c2 -side left -expand t -fill x -padx 5 -pady 5
+    
+    checkbutton $w.i.c -variable [ itcl::scope thisparam($this,dist_usecurrent) ] -text "Use Current Transform For Initialization" 
+    checkbutton $w.i.d -variable [ itcl::scope thisparam($this,dist_useprior) ] -text "For Prior" 
+    pack $w.i.c $w.i.d -side left -expand t -fill x -padx 5
+
+
+    label $w.u.lab1 -text "Update Display Every:"
+    tk_optionMenu $w.u.param [ itcl::scope thisparam($this,reg_updatesample) ] "1" "2" "5" "10" "20" "100"  
+    label $w.u.lab2 -text "Iterations"
+    pack $w.u.lab1 $w.u.param $w.u.lab2 -side left -expand f -fill x -pady 5
+
+	
+    eval "button $w.c -text \"Compute Distortion Correction\" -command { $this ComputeDistortionCorrection  }"
+    eval "button $w.d -text \"Compute Linear + Distortion Correction\" -command { $this ComputeCombinedRegistration distortion }"
+
+    lappend  thisparam($this,buttonlist) $w.c
+    lappend  thisparam($this,buttonlist) $w.d
+    pack $w.d $w.c -side bottom -expand f -fill x -padx 5
+
+    ::pxitclbasecontrol::SetWidgetTreeColors $adv "\#aaabd7" "black"
+}
+
+itcl::body pxitcloverlaytool::EnableRegistrationButtons { }  {
+    EnableUI $thisparam($this,buttonlist)
+}
+
+itcl::body pxitcloverlaytool::DisableRegistrationButtons { } {
+    DisableUI $thisparam($this,buttonlist)
+}
+
+itcl::body pxitcloverlaytool::SetAutoSave { mode } {
+    set thisparam($this,reg_autosave) $mode
+    set thisparam($this,areg_autosave) $mode
+    set thisparam($this,nreg_autosave) $mode
+    set thisparam($this,dist_autosave) $mode
+}
+
+itcl::body pxitcloverlaytool::ComputeAffineRegistration { } {
+
+    set current_transform [ $this GetTransformation ]
+    $transform_control AddObject  "lin.[ $transform_control GetNextObjectIndex ]"
+
+    global pxtcl_pref_array
+    set image_ref $currentimage
+    set image_trn $tmap
+    
+    set orient_ref [ $currentimage GetOrientation ]
+    set orient_trn [ $tmap GetOrientation ]
+    
+    puts stderr "Orientations = ref=$orient_ref trg=$orient_trn"
+
+    set dim1 [ [ $image_ref GetImage ] GetDimensions ]
+    set dim2 [ [ $image_trn GetImage ] GetDimensions ]
+    if { [lindex $dim2 0 ] <2 || [ lindex $dim1 0 ] < 2 } { 
+	::pxtclutil::Warning "No Image in Memory\n Cannot Register!"
+	return  0
+    }
+    
+    WatchOn
+    
+    set mat [ vtkMatrix4x4 [ pxvtable::vnewobj ]]
+    $mat Identity
+    
+    set md [ lsearch -exact $reg_measures $thisparam($this,reg_measure) ]
+    incr md
+    
+    set areg [ vtkpxLinearRegistration [ pxvtable::vnewobj ]]
+    
+    if { $thisparam($this,areg_usecurrent) == 1 } {
+	set xform [ ExtractLinearTransform $current_transform $image_ref $image_trn 9 ]
+	$areg SetInitialTransform $xform
+	$xform Delete
+    }
+    
+    $areg SetTranslationX $thisparam($this,areg_tx)
+    $areg SetTranslationY $thisparam($this,areg_ty)
+    $areg SetTranslationZ $thisparam($this,areg_tz)
+    $areg SetRotationX $thisparam($this,areg_rx)
+    $areg SetRotationY $thisparam($this,areg_ry)
+    $areg SetRotationZ $thisparam($this,areg_rz)
+    $areg SetScalingX $thisparam($this,areg_sx)
+    $areg SetScalingY $thisparam($this,areg_sy)
+    $areg SetScalingZ $thisparam($this,areg_sz)
+    $areg SetShearingXY $thisparam($this,areg_ax)
+    $areg SetShearingYX $thisparam($this,areg_ax)
+    $areg SetShearingYZ $thisparam($this,areg_ay)
+    $areg SetShearingZY $thisparam($this,areg_ay)
+    $areg SetShearingZX $thisparam($this,areg_az)
+    $areg SetShearingXZ $thisparam($this,areg_az)
+    $areg SetSimilarityMeasure $md
+    $areg SetReferenceImage [ $image_ref GetImage ]
+    $areg SetTransformImage [ $image_trn GetImage ]
+    $areg SetReferenceOrientation $orient_ref
+    $areg SetTransformOrientation $orient_trn
+
+    $areg SetResolution $thisparam($this,areg_resolution)
+    $areg SetNumberOfLevels $thisparam($this,areg_numlevels)
+    $areg SetNumberOfSteps $thisparam($this,areg_numsteps)
+    $areg SetStepSize       $thisparam($this,areg_stepsize) 
+    $areg SetOptimizationMethodTo$thisparam($this,areg_optmethod)
+    $areg SetNumberOfIterations $thisparam($this,areg_iterations)
+    $areg SetPositiveIntensitiesOnly $thisparam($this,areg_positive)
+    $areg SetLogarithmMode $thisparam($this,areg_logmode)
+    $areg SetJointlyNormalizeIntensities $thisparam($this,areg_jointlynormalize)
+    $areg SetAutoNormalizeIntensities $thisparam($this,areg_autonormalize)
+    $areg SetInterpolationMode $thisparam($this,areg_interpmode)
+    $areg DebugOff
+    eval "$areg AddObserver ProgressEvent { $this UpdateFromRegistration $areg }"
+    eval "$areg AddObserver EndEvent      { $this UpdateFromRegistrationDone $areg }"
+    
+    if { $pxtcl_pref_array(MirrorConsole) == 0 } { 
+	pxtkconsole 
+	pxtksetdebugmode 0
+    } else {
+	pxtksetdebugmode 1
+    }
+
+    update idletasks
+    set thisparam($this,reg_updatecount) 0
+    pxtkprint "\n\n Beginning Affine Registration , measure = $thisparam($this,reg_measure) Mode=$md\n"
+    
+    WatchOn
+    $areg Run
+    UpdateFromRegistrationDone $areg
+    WatchOff
+
+    SetTransformation  [ $areg GetTransformation ]
+    
+    if { $thisparam($this,areg_autosave) == 1 } {
+	AutoSaveTransformation
+    }
+    
+
+    $areg Delete
+
+    WatchOff
+    return 1
+}
+
+
+# --------------------------------------------------------------
+itcl::body pxitcloverlaytool::ComputeReorientationRegistration { } {
+
+    $this AffineControlSetMode affine; 
+    $this ComputeAffineRegistration
+    $this SetManualTransformGUI 0
+    set thisparam($this,manxf_scalex) 100.0
+    set thisparam($this,manxf_scaley) 100.0
+    set thisparam($this,manxf_scalez) 100.0
+    $this SetManualTransform ; 
+    $this ResliceFunctionalImage 1 1
+}
+
+
+# --------------------------------------------------------------
+# Non - Linear Registration
+# --------------------------------------------------------------
+itcl::body pxitcloverlaytool::ComputeNonLinearRegistration { } {
+
+    set current_transform [ $this GetTransformation ]
+    $transform_control AddObject  "nreg.[ $transform_control GetNumberOfObjects ]"
+
+    global pxtcl_pref_array
+    set image_ref $currentimage
+    set image_trn $tmap
+    
+    set orient_ref [ $currentimage GetOrientation ]
+    set orient_trn [ $tmap GetOrientation ]
+    
+    set dim1 [ $image_ref GetImageSize ]
+    set dim2 [ $image_trn GetImageSize ]
+    if { $dim2 <2 ||  $dim1 < 2 } { 
+	::pxtclutil::Warning "No Image in Memory\n Cannot Register!"
+	return  0
+    }
+    
+    if { $orient_ref != $orient_trn } {
+	::pxtclutil::Warning "Different Orientations ($orient_ref, $orient_trn) ! Cannot Register Images!"
+	return 0;
+    }
+    
+    set md [ lsearch -exact $reg_measures $thisparam($this,reg_measure) ]
+    incr md
+    
+   
+    pxtkprint "\n\n ------------------------------ \n\n\nBeginning NonLinear Registration , measure = $thisparam($this,reg_measure) Mode=$md\n"
+    set nreg [ vtkpxNonLinearRegistration [ pxvtable::vnewobj ]]
+    $nreg SetSimilarityMeasure $md
+    $nreg SetLambda [ expr 0.01 * $thisparam($this,nreg_smoothness) ]
+
+
+    if { $thisparam($this,nreg_usecurrent) == 1 } {
+	$nreg SetInitialTransform $current_transform 
+	#if { [ $current_transform IsA "vtkpxComboTransform" ] == 1 } {
+	#    $nreg SetUsePrior $thisparam($this,nreg_useprior)
+	#    $nreg SetPriorTransform $current_transform
+	#    $nreg SetInternalEnergyModeToBendingEnergy
+	#}
+    } else {
+	#$nreg SetUsePrior 0
+    }
+    $nreg DebugOff
+    
+    $nreg SetReferenceImage [  $image_ref GetImage ]
+    $nreg SetTransformImage [ $image_trn GetImage  ]
+    $nreg SetNumberOfSteps  $thisparam($this,nreg_numsteps)
+    $nreg SetNumberOfLevels $thisparam($this,nreg_numlevels)
+    $nreg SetStepSize       $thisparam($this,nreg_stepsize) 
+    $nreg SetResolution  $thisparam($this,nreg_resolution) 
+    $nreg SetControlPointSpacing $thisparam($this,nreg_spacing)
+    $nreg SetControlPointSpacingRate $thisparam($this,nreg_spacingrate)
+    $nreg SetOptimizationMethodTo$thisparam($this,nreg_optmethod)
+    $nreg SetNumberOfIterations $thisparam($this,nreg_iterations)
+    $nreg SetGradientScale $thisparam($this,nreg_gscale)
+    $nreg SetPositiveIntensitiesOnly $thisparam($this,nreg_positive)
+    $nreg SetJointlyNormalizeIntensities $thisparam($this,nreg_jointlynormalize)
+    $nreg SetAutoNormalizeIntensities $thisparam($this,nreg_autonormalize)
+
+    $nreg SetLogarithmMode $thisparam($this,nreg_logmode)
+
+    eval "$nreg AddObserver ProgressEvent { $this UpdateFromRegistration $nreg }"
+    eval "$nreg AddObserver EndEvent      { $this UpdateFromRegistrationDone $nreg }"
+    
+    if { $pxtcl_pref_array(MirrorConsole) == 0 } { 
+	pxtkconsole 
+	pxtksetdebugmode 0
+    } else {
+	pxtksetdebugmode 1
+    }
+
+    set thisparam($this,reg_updatecount) 0
+    
+    WatchOn
+    set old $thisparam($this,reg_updatesample)  
+    set thisparam($this,reg_updatesample)   [ expr $old * 5 ]
+    $nreg Run
+    UpdateFromRegistrationDone $nreg
+    set thisparam($this,reg_updatesample) $old
+    WatchOff
+    
+    SetTransformation  [ $nreg GetTransformation ]
+    
+    if { $thisparam($this,nreg_autosave) == 1 } {
+	AutoSaveTransformation
+    }
+    
+    $nreg Delete
+    return 1
+}
+
+# --------------------------------------------------------------
+# Non - Linear Registration
+# --------------------------------------------------------------
+itcl::body pxitcloverlaytool::ComputeDistortionCorrection { } {
+
+    set current_transform [ $this GetTransformation ]
+    $transform_control AddObject  "dist.[ $transform_control GetNumberOfObjects ]"
+
+    global pxtcl_pref_array
+    set image_ref $currentimage
+    set image_trn $tmap
+    
+    set orient_ref [ $currentimage GetOrientation ]
+    set orient_trn [ $tmap GetOrientation ]
+    
+    set dim1 [ $image_ref GetImageSize ]
+    set dim2 [ $image_trn GetImageSize ]
+    if { $dim2 <2 ||  $dim1 < 2 } { 
+	::pxtclutil::Warning "No Image in Memory\n Cannot Register!"
+	return  0
+    }
+    
+    if { $orient_ref != $orient_trn } {
+	::pxtclutil::Warning "Different Orientations! Cannot Register Images!"
+	return 0;
+    }
+    
+    set md [ lsearch -exact $reg_measures $thisparam($this,dist_measure) ]
+    incr md
+    
+    
+    pxtkprint "\n\n ------------------------------ \n\n\nBeginning Distortion Correction , measure = $thisparam($this,reg_measure) Mode=$md\n"
+    set nreg [ vtkpxDistortionCorrection [ pxvtable::vnewobj ]]
+
+    if { $thisparam($this,dist_jackmode) != "None" } {
+	$nreg SetUseJacobian 1 
+	if { $thisparam($this,dist_jackmode) == "Signal Loss" } {
+	    $nreg SetUseSignalLossCorrection 1
+	} else {
+	    $nreg SetUseSignalLossCorrection 0
+	}
+    } else {
+	$nreg SetUseSignalLossCorrection 0
+	$nreg SetUseJacobian 0
+    }
+
+    pxtkprint "nreg jacobian [ $nreg GetUseJacobian ] signal correction [ $nreg GetUseSignalLossCorrection ]\n"
+
+    $nreg SetSimilarityMeasure $md
+    $nreg SetLambda [ expr 0.01 * $thisparam($this,dist_smoothness) ]
+    $nreg SetLogarithmMode $thisparam($this,dist_logmode)
+
+
+    if { $thisparam($this,dist_usecurrent) == 1 } {
+	$nreg SetInitialTransform $current_transform 
+	#if { [ $current_transform IsA "vtkpxComboTransform" ] == 1 } {
+	#    $nreg SetUsePrior $thisparam($this,dist_useprior)
+	#    $nreg SetPriorTransform $current_transform
+	#    $nreg SetInternalEnergyModeToBendingEnergy
+	#}
+    } else {
+	$nreg SetUsePrior 0
+    }
+    
+    $nreg SetPhaseEncodeAxisTo$thisparam($this,dist_warp)
+    $nreg SetReferenceImage [  $image_ref GetImage ]
+    $nreg SetTransformImage [ $image_trn GetImage  ]
+    $nreg SetNumberOfSteps  $thisparam($this,dist_numsteps)
+    $nreg SetNumberOfLevels $thisparam($this,dist_numlevels)
+    $nreg SetStepSize       $thisparam($this,dist_stepsize) 
+    $nreg SetResolution  $thisparam($this,dist_resolution) 
+    $nreg SetControlPointSpacing $thisparam($this,dist_spacing)
+    $nreg SetControlPointSpacingRate $thisparam($this,dist_spacingrate)
+    $nreg SetOptimizationMethodTo$thisparam($this,dist_optmethod)
+    $nreg SetNumberOfIterations $thisparam($this,dist_iterations)
+
+
+    eval "$nreg AddObserver ProgressEvent { $this UpdateFromRegistration $nreg }"
+    eval "$nreg AddObserver EndEvent      { $this UpdateFromRegistrationDone $nreg }"
+    
+    if { $pxtcl_pref_array(MirrorConsole) == 0 } { 
+	pxtkconsole 
+	pxtksetdebugmode 0
+    } else {
+	pxtksetdebugmode 1
+    }
+
+    set thisparam($this,reg_updatecount) 0
+    
+    WatchOn
+    set old $thisparam($this,reg_updatesample)  
+    set thisparam($this,reg_updatesample)   [ expr $old * 5 ]
+    $nreg Run
+    UpdateFromRegistrationDone $nreg
+    set thisparam($this,reg_updatesample) $old
+    WatchOff
+    
+    SetTransformation  [ $nreg GetTransformation ]
+    
+    if { $thisparam($this,dist_autosave) == 1 } {
+	AutoSaveTransformation
+    }
+    
+    $nreg Delete
+    return 1
+}
+# ------------------------------------------------
+# Combo Stuff
+# ------------------------------------------------
+
+itcl::body pxitcloverlaytool::ComputeCombinedRegistration { mode } {
+
+    set oldlog    $thisparam($this,areg_logmode)
+    set oldlevels $thisparam($this,areg_numlevels)  
+    set oldstep   $thisparam($this,areg_stepsize)
+    set oldres    $thisparam($this,areg_resolution) 
+
+    if { $mode == "registration" } {
+	set thisparam($this,areg_logmode) $thisparam($this,nreg_logmode)
+	AffineControlSetMode "affine"
+    } else {
+	AffineControlSetMode "rigid"
+	set thisparam($this,areg_logmode) $thisparam($this,dist_logmode)
+	set thisparam($this,areg_numlevels)  2
+	set thisparam($this,areg_stepsize)   1.0
+	set thisparam($this,areg_resolution)  $thisparam($this,dist_resolution) 
+    }
+    set  thisparam($this,areg_logmode) $oldlog
+
+    set thisparam($this,nreg_usecurrent) 1
+    set thisparam($this,areg_usecurrent) 0
+    set thisparam($this,areg_autosave) 0
+
+    ComputeAffineRegistration
+
+    if { $mode == "registration" } {
+	ComputeNonLinearRegistration
+    } else {
+	ComputeDistortionCorrection
+    }
+    
+    set thisparam($this,areg_logmode) $oldlog
+    set thisparam($this,areg_numlevels)  $oldlevels
+    set thisparam($this,areg_stepsize) $oldstep
+    set thisparam($this,areg_resolution) $oldres
+}
+
+# ------------------------------------------------
+# Combine Control   Add or Strip Images 
+# ------------------------------------------------
+
+
+itcl::body pxitcloverlaytool::CreateCombineControl { parent } {
+    
+    set w  [ LabelFrame:create $parent.b -text "Add Images"]
+    set w2  [ LabelFrame:create $parent.c -text "Strip Image"]
+    pack $parent.b $parent.c -side top -expand t -fill both -padx 10 -pady 5
+    
+    
+    frame $w.m; pack $w.m  -side top -expand f
+    eval "button $w.m.1 -text \"Add Images\" -command { $this AddImages }"
+    eval "button $w.m.2 -text \"Concatenate Object Maps\" -command { $this CombineObjectMaps }"
+    pack $w.m.1 $w.m.2 -side left -expand f
+    
+    frame $w2.top ; pack $w2.top -side top -padx 20 -pady 2
+    
+    eval "button  $w2.top.1 -text \"Non-zero strip\" -command { $this StripImage }"
+    pack $w2.top.1  -side left
+    
+}
+
+
+itcl::body pxitcloverlaytool::AddImages { } {
+
+    set upd [ ResliceFunctionalImage 0 0 ]
+    if { $upd == 0 } {
+	return 0
+    }
+    
+    set image_ref [ $currentimage GetImage ]
+    set image_trn [ $resliced_tmap GetImage ]
+
+    WatchOn
+    set math [ vtkImageMathematics [ pxvtable::vnewobj ]]
+    $math SetInput1   $image_ref
+    $math SetInput2   $image_trn
+    $math SetOperationToAdd
+    SetFilterCallbacks $math "Adding Images"
+    $math Update
+    ProcessResults  $math "Add" 
+    $math Delete
+    WatchOff 
+    return 1
+}
+
+itcl::body pxitcloverlaytool::CombineObjectMaps { } {
+    
+    set upd [ ResliceFunctionalImage 0 0 ]
+    if { $upd == 0 } {
+	return 0
+    }
+       
+    set image_ref [ $currentimage GetImage ]
+    set image_trn [ $resliced_tmap GetImage ]
+    
+    set range [[[ $image_ref  GetPointData ] GetScalars ] GetRange ]
+    set addc [ expr [ lindex $range 1 ] +1 ]
+    
+    WatchOn
+    set sh  [ vtkImageShiftScale [ pxvtable::vnewobj ]  ]
+    $sh SetInput $image_trn
+    $sh SetShift $addc
+    $sh SetScale 1
+    SetFilterCallbacks $sh "Shifing Image"
+    $sh Update
+    
+    set math [ vtkImageMathematics [ pxvtable::vnewobj ]]
+    $math SetInput1  $image_ref
+    $math SetInput2  [ $sh GetOutput ] 
+    $math SetOperationToAdd
+    SetFilterCallbacks $math "SAdding Images"
+    $math Update
+    ProcessResults  $math "Combo" 
+    $math Delete
+    $sh Delete
+    WatchOff 
+    
+    return 1
+}
+
+itcl::body pxitcloverlaytool::StripImage { } {
+
+    set upd [ ResliceFunctionalImage 0 0 ]
+    if { $upd == 0 } {
+	return 0
+    }
+    
+    set range [[[  [ $currentimage GetImage ]  GetPointData ] GetScalars ] GetRange ]
+    set addc [ expr [ lindex $range 1 ] +1 ]
+    
+    WatchOn
+    set tr  [ vtkImageThreshold [ pxvtable::vnewobj ]  ]
+    $tr SetInput [ $resliced_tmap GetImage ]
+    $tr ThresholdByUpper 1.0
+    $tr SetInValue 1.0
+    $tr SetOutValue 0.0
+    $tr ReplaceInOn
+    $tr ReplaceOutOn
+    SetFilterCallbacks $tr "Creating Mask"
+    $tr Update
+
+    
+    set math [ vtkImageMathematics [ pxvtable::vnewobj ]]
+    $math SetInput1 [ $currentimage GetImage ]
+    $math SetInput2  [ $tr GetOutput ] 
+    $math SetOperationToMultiply
+    SetFilterCallbacks $math "Multiplying Images"
+    $math Update
+    ProcessResults  $math "Strip" 
+    $math Delete
+    $tr Delete
+    WatchOff 
+    
+    return 1
+}
+
+# ----------------------------------------------------------------------------------------
+itcl::body pxitcloverlaytool::SetImageToCompareControl { ctrl image } {
+    $this DelayedInitialize
+     [ $ctrl GetObject ] ShallowCopy $image; $ctrl Update 
+}
+
+
+itcl::body pxitcloverlaytool::ComputeCompareOperations { mode } {
+
+
+    set img1 [ [ $meanimagecontrol1 GetObject ] GetImage ]
+    set img2 [ [ $meanimagecontrol2 GetObject ] GetImage ]
+    set sig1 [ [ $sigmaimagecontrol1 GetObject ] GetImage ]
+    set sig2 [ [ $sigmaimagecontrol2 GetObject ] GetImage ]
+    $currentresults CopyImageHeader [ [ $meanimagecontrol1 GetObject  ] GetImageHeader ]
+
+    if { [ $img1 GetNumberOfPoints ] != [ $img2 GetNumberOfPoints ] } {
+	::pxtclutil::Warning "Unequal Image Sizes\n Cannot Perform Compare Operation $mode!"
+	return 0
+    }
+
+    if { $mode == "tmap" } {
+	if { [ $img1 GetNumberOfPoints ] != [ $sig1 GetNumberOfPoints ] ||
+	     ( [ $img1 GetNumberOfPoints ] != [ $sig2 GetNumberOfPoints ] && $thisparam($this,computetmapsamples2) > 1 ) } {
+	    ::pxtclutil::Warning "Unequal Image Sizes\n Cannot Perform Compare Operation $mode!"
+	    return 0
+	}
+    }
+	
+    WatchOn
+
+    if { $mode == "tmap" } {
+	set math [ vtkpxComputeTmap [ pxvtable::vnewobj ]]
+	$math SetInput  $img1
+	$math SetInput2 $img2
+	$math SetInputStandardDeviation  $sig1
+	$math SetInputStandardDeviation2 $sig2
+	$math SetNumberOfSamples1 $thisparam($this,computetmapsamples1)
+	$math SetNumberOfSamples2 $thisparam($this,computetmapsamples2)
+	$math SetScaleFactor 1000.0
+	$math Update
+	$currentresults ShallowCopyImage [ $math GetOutput ]
+	if { $thisparam($this,computetmapsamples1)  >1 && $thisparam($this,computetmapsamples2) > 1 } {
+	    $currentresults configure -filename "tmap"  
+	} else {
+	    $currentresults configure -filename "zcore" 
+	}
+		
+	puts stderr " Results Range: [ [ [ [ $currentresults GetImage ] GetPointData ] GetScalars ] GetRange ]"
+	$math Delete
+    } else {
+	set imcast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+    	$imcast2 SetInput $img2
+	$imcast2 SetOutputScalarType [ $img1 GetScalarType ]
+	$imcast2 Update
+
+	set math [ vtkImageMathematics [ pxvtable::vnewobj ]]
+	$math SetInput1 $img1
+	$math SetInput2 [ $imcast2 GetOutput ]
+	
+	if { $mode == "add" } {
+	    $math SetOperationToAdd
+	} else {
+	    $math SetOperationToSubtract
+	}
+	$math Update
+	$currentresults ShallowCopyImage [ $math GetOutput ]
+	$math Delete
+	$imcast2 Delete 
+    }
+
+    SetFunctionalImage $currentresults
+    WatchOff 
+    
+    return 1
+}
+# ----------------------------------------------------------------------------------------
+itcl::body pxitcloverlaytool::ComputeCompare4DOperations { mode } {
+
+    set img1 [ [ $fourdimagecontrol1 GetObject ] GetImage ]
+    set img2 [ [ $fourdimagecontrol2 GetObject ] GetImage ]
+    $currentresults CopyImageHeader [ [ $fourdimagecontrol1 GetObject  ] GetImageHeader ]
+
+    if { [ $img1 GetNumberOfPoints ] != [ $img2 GetNumberOfPoints ] } {
+	::pxtclutil::Warning "Unequal Image Sizes\n Cannot Perform Compare $mode t-test!"
+	return 0
+    }
+
+    if { $mode == "paired" } {
+	if { [ $img1 GetNumberOfScalarComponents ] != [ $img2 GetNumberOfScalarComponents ] } {
+	    ::pxtclutil::Warning "Unequal Number of Image Frames\n Cannot Perform paired t-test!"
+	    return 0
+	}
+    }
+	
+    WatchOn
+
+    set tlist [ list $img1 $img2 ]
+
+    if { $mode == "paired" } {
+	set imcast2 [ vtkImageCast [ pxvtable::vnewobj ]]
+    	$imcast2 SetInput $img2
+	$imcast2 SetOutputScalarType [ $img1 GetScalarType ]
+	$imcast2 Update
+	
+	set math [ vtkImageMathematics [ pxvtable::vnewobj ]]
+	$math SetInput1 $img1
+	$math SetInput2 [ $imcast2 GetOutput ]
+	$math SetOperationToSubtract
+	$math Update
+
+	set timg [ vtkImageData New ]
+	$timg ShallowCopy [ $math GetOutput ]
+	$math Delete
+	$imcast2 Delete
+	set tlist $timg
+    }
+
+    set n [ llength $tlist ] 
+    #    puts stderr "tlist=$tlist n=$n"
+    set math [ vtkpxComputeTmap [ pxvtable::vnewobj ]]
+    #    $math DebugOn
+    for { set i 0 } { $i < $n } { incr i } {
+	
+	#	puts stderr "Computing average $i , [ lindex $tlist $i ], [ [ lindex $tlist $i ]  GetDimensions ]"
+
+	set ave($i) [ vtkbisImageAverageComponents New ]
+	$ave($i) SetInput [ lindex $tlist $i ]
+	$ave($i) Update
+
+	if { $i == 0 } {
+	    $math SetInput  [ $ave($i) GetOutput ]
+	    $math SetInputStandardDeviation  [ $ave($i) GetStandardDeviationImage ]
+	    $math SetNumberOfSamples1 [ $img1 GetNumberOfScalarComponents ]
+	} else {
+	    $math SetInput2  [ $ave($i) GetOutput ]
+	    $math SetInputStandardDeviation2  [ $ave($i) GetStandardDeviationImage ]
+	    $math SetNumberOfSamples2 [ $img2 GetNumberOfScalarComponents ]
+	}
+	$ave($i) Delete
+    }
+    
+    $math SetNumberOfInputs $n
+    $math SetScaleFactor 1000.0
+    $math Update
+    $currentresults ShallowCopyImage [ $math GetOutput ]
+
+    set f(1)  [ [ $fourdimagecontrol1 GetObject ]  cget -filename ]
+    set f(2)  [ [ $fourdimagecontrol2 GetObject ]  cget -filename ]
+
+    set outname ""
+    for { set i 1 } { $i <= 2 } { incr i } {
+	set tnm [ file tail $f($i) ]
+	set ext [ file extension $f($i) ]
+	set tnm [ file rootname $tnm ]
+	if { $ext == ".gz" } {
+	    set tnm [ file rootname $tnm ]
+	}
+	if { $i == 1 } {
+	    set outname $tnm
+	} else {
+	    set outname "${outname}_${tnm}"
+	}
+    }
+
+    if { $n == 1 } {
+	$currentresults configure -filename [ file join [ file dirname $f(1) ] "${outname}_paired_4D_tmap.nii.gz" ]
+    } else {
+	$currentresults configure -filename [ file join [ file dirname $f(1) ] "${outname}_4D_tmap.nii.gz" ]
+    }
+		
+    puts stderr "out = [ $currentresults cget -filename ]"
+    puts stderr "Results Range: [ [ [ [ $currentresults GetImage ] GetPointData ] GetScalars ] GetRange ]"
+    $math Delete
+
+    if { $n == 1 } {
+	[ lindex $tlist 0 ] Delete
+    }
+	
+    SetFunctionalImage $currentresults
+    WatchOff 
+    return 1
+}
+
+# ----------------------------------------------------------------------------------------
+
+
+itcl::body pxitcloverlaytool::ComputeIntersection { } {
+
+
+    set img1 [ [ $meanimagecontrol1 GetObject ] GetImage ]
+    set img2 [ [ $meanimagecontrol2 GetObject ] GetImage ]
+    $currentresults CopyImageHeader [ [ $meanimagecontrol1 GetObject  ] GetImageHeader ]
+
+    if { [ $img1 GetNumberOfPoints ] != [ $img2 GetNumberOfPoints ] } {
+	::pxtclutil::Warning "Unequal Image Sizes\n Cannot Perform Compare Operation $mode!"
+	return 0
+    }
+
+    WatchOn
+    set math [ vtkpxImageThresholdedIntersection [ pxvtable::vnewobj ]]
+    $math AddInput $img1
+    $math AddInput $img2
+    $math SetThreshold  $thisparam($this,intersectionthreshold)
+    switch -exact -- $thisparam($this,intersectionmode) {
+	"Positive" { $math SetThresholdMode 0}
+	"Negative" { $math SetThresholdMode 1}
+	"Both"     { $math SetThresholdMode 2}
+    }
+    SetFilterCallbacks $math "Computing Intersection"    
+    $math Update
+    $currentresults ShallowCopyImage [ $math GetOutput ]
+    $currentresults configure -filename "inter"  
+    
+    $math Delete
+    SetFunctionalImage $currentresults
+    WatchOff
+
+    return 1
+}
+
+
+# ----------------------------------------------------------------------------------------
+#  Create Grid Visualization
+# ----------------------------------------------------------------------------------------
+itcl::body pxitcloverlaytool::CreateGridVisualization {  } {
+
+    set current_transform [ $this GetTransformation ]    
+    set image_ref [ $currentimage GetImage ]
+    set image_trn [ $tmap GetImage ]
+
+    set dim1 [ $image_ref GetDimensions ]
+    set dim2 [ $image_trn GetDimensions ]
+    if { [lindex $dim2 0 ] <2 || [ lindex $dim1 0 ] < 2 } { 
+	::pxtclutil::Warning "No Images in Memory\n Cannot Reslice! ($dim1,$dim2)"
+	return  0
+    }
+    
+    WatchOn
+    
+    scan [ $image_trn GetExtent ]  "%d %d %d %d %d %d" e1 e2 e3 e4 e5 e6
+    scan [ $image_trn GetSpacing ] "%f %f %f" s1 s2 s3
+    scan [ $image_trn GetOrigin ]  "%f %f %f" o1 o2 o3
+    set range [ lindex [[ [ [ $currentimage GetImage ] GetPointData ] GetScalars ] GetRange ] 1]
+    
+    set grdsource [ vtkImageGridSource [ pxvtable::vnewobj ]]
+    $grdsource SetDataExtent  $e1 $e2 $e3 $e4 $e5 $e6
+    $grdsource SetDataSpacing $s1 $s2 $s3 
+    $grdsource SetDataOrigin  $o1 $o2 $o3 
+    $grdsource SetGridSpacing $thisparam($this,gridspacing1) $thisparam($this,gridspacing1) $thisparam($this,gridspacing2) 
+    $grdsource SetDataScalarType [ [ $currentimage GetImage ] GetScalarType ]
+    $grdsource SetLineValue [ expr $range * $thisparam($this,gridintensity) ]
+    $grdsource Update
+    
+    set blendCreator [ vtkImageBlend [ pxvtable::vnewobj ]]
+    $blendCreator AddInput [ $tmap GetImage ]
+    $blendCreator AddInput [ $grdsource GetOutput ]
+    $blendCreator SetOpacity 1 $thisparam($this,gridopacity)
+    SetFilterCallbacks $blendCreator "Blending Grid Images"
+    $blendCreator Update
+    
+    set reslice [  vtkbisImageReslice [ pxvtable::vnewobj ]]
+    $reslice OptimizationOff
+    $reslice SetInterpolationMode 0
+    $reslice SetBackgroundLevel 0.0
+    $reslice SetInformationInput $image_ref
+    $reslice SetResliceTransform $current_transform
+    $reslice SetInput [ $blendCreator GetOutput ]
+    SetFilterCallbacks $reslice "Reslicing Grid Source"
+    $reslice Update
+
+
+    ProcessResults  $reslice "resliced-grid" 
+    catch { $reslice   Delete }
+    catch { $grdSource Delete }
+    catch { $blendCreator Delete }
+    WatchOff
+    return 1
+}
+
+itcl::body pxitcloverlaytool::ComputeJacobian { mode } {
+    
+    set current_transform [ $this GetTransformation ]
+    set image_ref [ $currentimage GetImage ]
+    set dim1 [ $image_ref GetDimensions ]
+    if { [ lindex $dim1 0 ] < 2 } { 
+	::pxtclutil::Warning "No Image in Memory\n Cannot Compute Jacobian!"
+	return  0
+    }
+    
+    set reg [ vtkpxRegistration [ pxvtable::vnewobj ]]
+    WatchOn ; update idletasks
+
+    set thr $thisparam($this,jacobian_threshold)
+
+
+    set newimg [ vtkImageData [ pxvtable::vnewobj ]]
+
+
+    set res $thisparam($this,jacobian_resolution) 
+    if { $res > 1.0 } {
+
+	if { $res > 10.0 } {
+	    set res 10.0
+	    set thisparam($this,jacobian_resolution) $res
+	} 
+
+	set spa [ $newimg GetSpacing ]
+	for { set i 0 } { $i <=2 } { incr i } {
+	    set sp($i) [ expr $res*[ lindex $spa $i ] ]
+	}
+
+	set resl [ vtkImageResample [ pxvtable::vnewobj ] ]
+	$resl SetAxisOutputSpacing 0 $sp(0)
+	$resl SetAxisOutputSpacing 1 $sp(1)
+	$resl SetAxisOutputSpacing 2 $sp(2)
+	$resl InterpolateOff
+	$resl SetDimensionality 3
+	$resl SetInput $image_ref
+	$resl Update
+	$newimg ShallowCopy [ $resl GetOutput ]
+	$resl Delete
+    } else {
+	$newimg ShallowCopy $image_ref
+	set thisparam($this,jacobian_resolution) 1.0
+    }
+
+
+    if { $mode == "tensor" } {
+	$reg ComputeJacobianImage $newimg [ $lastjacobian GetImage ] $current_transform 1 1.0 $thr
+    } elseif { $mode == "strains" } {
+	$reg ComputePrincipalStrains    $newimg [ $lastjacobian GetImage ] $current_transform $thr
+    } else {
+	$reg ComputeSimpleJacobianImage $newimg [ $lastjacobian GetImage ] $current_transform 100.0 1.0 $thr
+    }
+
+
+    $lastjacobian CopyImageHeader [ $currentimage GetImageHeader ]
+    $newimg Delete
+    $reg Delete
+    
+    UpdateJacobianOverlayRange
+    ProcessResultsImage [ $lastjacobian GetImage ] "Jacobian"
+
+    
+
+    WatchOff
+}
+
+# ----------------------------------------------------------------
+
+itcl::body pxitcloverlaytool::UpdateJacobianOverlayRange {  } {
+    
+    set dim1 [ [ $lastjacobian GetImage ] GetDimensions ]
+    if { [ lindex $dim1 0 ] < 2 } { 
+	return  0
+    }
+
+    set nc [ [ $lastjacobian GetImage ] GetNumberOfScalarComponents ]
+    $thisparam($this,jackoverlay_componentscale) configure -from 1 -to $nc 
+
+    if { $thisparam($this,jackoverlaycurrentframe) >= $nc } {
+	set thisparam($this,jackoverlay_coponentscale) 1
+    }
+
+    set range [ [ [ [ $lastjacobian GetImage ] GetPointData] GetScalars] GetRange [ expr $thisparam($this,jackoverlaycurrentframe) -1 ] ]
+    set lowrange  [ expr  abs ([ lindex $range 0])]
+    set highrange [ expr  abs ([ lindex $range 1])]
+    
+    puts stdout "Final range = $range "
+    
+    if { $highrange<$lowrange } {
+	set highrange $lowrange
+    }
+	
+    $thisparam($this,jackoverlay_minthresholdscale) configure -from 0 -to $highrange
+    $thisparam($this,jackoverlay_maxthresholdscale) configure -from 0 -to $highrange
+
+    if { $highrange > 20 } {
+	set thisparam($this,jackoverlaymin) 20
+	set thisparam($this,jackoverlaymax) $highrange
+    } elseif { $highrange > 200 } {
+	set thisparam($this,jackoverlaymin) 50
+	set thisparam($this,jackoverlaymax) $highrange
+    } else {
+	set thisparam($this,jackoverlaymin) [expr $highrange / 2.0 ] 
+	set thisparam($this,jackoverlaymax) $highrange
+    } 	
+    
+    
+}
+
+itcl::body pxitcloverlaytool::DisplayJacobian { } {
+
+    set dim1 [ $lastjacobian GetImageSize ]
+    if {  $dim1 < 2 } { 
+	::pxtclutil::Warning "No Jacobian Image in Memory\n Cannot Display!"
+	return  0
+    }
+    
+    ProcessResultsImage [ $lastjacobian GetImage ] "Jacobian"
+}
+
+
+itcl::body pxitcloverlaytool::DisplayJacobianOverlay { } {
+    
+    set image_ref [  $currentimage GetImage ]
+    set dim2 [ $image_ref GetDimensions ]
+    set dim1 [ [ $lastjacobian GetImage ] GetDimensions ]
+    if { [ lindex $dim1 0 ] < 2 || [ lindex $dim2 0 ] < 2 } { 
+	::pxtclutil::Warning "No Image or Jacobian in Memory\n Cannot Display Overlay!"
+	return  0
+    }
+    
+    WatchOn
+    set fmriOverlayCreator [ vtkpxMergeFmriConventional [ pxvtable::vnewobj ]]
+    $fmriOverlayCreator SetConventional [ $currentimage GetImage ]
+    $fmriOverlayCreator SetFmriInput    [ $lastjacobian GetImage ]
+	
+    $fmriOverlayCreator SetIntensityThreshold [expr round($thisparam($this,jackoverlayinten))]
+    $fmriOverlayCreator SetMinimumThreshold  $thisparam($this,jackoverlaymin)
+    $fmriOverlayCreator SetMaximumThreshold  $thisparam($this,jackoverlaymax)
+    $fmriOverlayCreator SetOutputMode $thisparam($this,jackoverlaycmapmode)
+    $fmriOverlayCreator SetNormalizeAnatomical $thisparam($this,jackoverlayanatcmapmode)
+    $fmriOverlayCreator SetSingleFrameMode 0
+    
+    switch -exact -- $thisparam($this,jackoverlaymode) {
+	"Positive" { $fmriOverlayCreator SetThresholdMode 1}
+	"Both"     { $fmriOverlayCreator SetThresholdMode 3}
+	"Negative" { $fmriOverlayCreator SetThresholdMode 2}
+    }
+    SetFilterCallbacks $fmriOverlayCreator "Creating Overlays"
+    $fmriOverlayCreator Update
+    
+    ProcessResults  $fmriOverlayCreator "Overlay" 
+    $this SetValueImage  [ $fmriOverlayCreator GetFunctionalInput ]
+    $fmriOverlayCreator Delete
+    WatchOff 
+
+    if { $parent !=0 } {
+	if { $thisparam($this,jackoverlaycmapmode) == 0 } {
+	    $parent SetLookupTableMode 1 
+	} else {
+	    $parent SetLookupTableMode 2
+	}
+    }
+
+    return 1
+}
+
+# ----------------------------------------------------------------------------------------
+::itcl::body pxitcloverlaytool::AddToMenuButton { mb args} {
+
+    eval "$mb add command -label \"Transformation\" -command {$this ShowWindow Transformation}"
+    eval "$mb add command -label \"Visualize Transformation\" -command { $this ShowWindow Jacobian}"
+    $mb add separator
+    eval "$mb add command -label \"Functional Overlay\" -command { $this ShowWindow \"Func. Overlay\"}"
+    $mb add separator
+    eval "$mb add command -label \"Image Compare\" -command {$this ShowWindow \"Image Compare\"}"
+    eval "$mb add command -label \"4D Image Compare\" -command {$this ShowWindow \"4D Image Compare\"}"
+    $mb add separator
+    eval "$mb add command -label \"Linear Registration\" -command {$this ShowWindow \"Linear Reg\"}"
+    eval "$mb add command -label \"Non-Linear Registration\" -command {$this ShowWindow \"NonLinear Reg\"}"
+    if { $enable_distortioncorrection == 1 } {
+	eval "$mb add command -label \"Distortion Correction\" -command {$this ShowWindow \"Distortion Cor\"}"
+    }
+}
+    
+# ------------------------------------------------------------------------------------------
+#  Overlay tool plus is a stripped down version  -- counterintuitive perhaps but that's life
+# ------------------------------------------------------------------------------------------
+
+itcl::class pxitcloverlaytoolplus {
+
+    inherit pxitcloverlaytool
+
+    public variable inputimagescallback 0
+    public variable itcl_transform 0
+
+    constructor { par args } {
+	pxitcloverlaytool::constructor $par $args
+    } {
+	set compact_reslice_control 0
+	set itcl_transform [ [  pxitcltransform \#auto ] GetThisPointer ]
+    }
+
+    public  method ResliceFunctionalImage { force display } {
+	if { $inputimagescallback != 0 } {
+	    eval $inputimagescallback
+	}
+	return [ ::pxitcloverlaytool::ResliceFunctionalImage $force $display ]
+    }
+
+    public method CreateFunctionalOverlayControl { parent } {
+	set basewidget $parent
+	return [ ::pxitcloverlaytool::CreateFunctionalOverlayControl $parent ]
+    }
+	
+    public method CreateResliceControl { par } {
+	set basewidget $par
+	return [ ::pxitcloverlaytool::CreateResliceControl $par ]
+    }
+
+    public method GetTransformation { } {
+	return [ $itcl_transform GetTransformation ]
+    }
+
+    public method SetTransformation { newtr args } {
+	$itcl_transform CopyTransformation $newtr
+    }
+
+    public    method GetTransformationName { } {
+	return [ $itcl_transform configure -filename ]
+    }
+
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclrpm.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclrpm.tcl
new file mode 100644
index 0000000..ddcb9f6
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclrpm.tcl
@@ -0,0 +1,1334 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclrpm 1.0
+
+# 	$Id: pxitclrpm.tcl,v 1.2 2003/08/29 18:56:21 xenios Exp xenios $	
+
+
+
+
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxvtable   1.0
+package require  pxtclhelp 1.0
+package require  pxitclbasecontrol 1.0
+package require  pxitclarticulatedmodel 1.0
+
+itcl::class pxitclrpm {
+
+    inherit pxitclbasecontrol
+
+    protected variable polydatacontrol1 0
+    protected variable polydatacontrol2 0
+    protected variable landmarkcontrol  0
+    protected variable overlaytool      0
+    protected variable renWin           0
+
+    protected variable initialized      0
+    private   common   thisparam        
+    public    variable registrationmethod 0
+    public    variable enablearticulated 0
+    public    variable sourcesurface 0
+    public    variable targetsurface 0
+    public    variable vtk_viewer    0
+    public    variable renderwindow  0
+    public    variable notebook      0
+    public    variable tmodelgui     0
+    
+    protected variable parameterlist ""
+
+    constructor { par pcontrol1 pcontrol2 overlay landcontrol } {
+	pxitclbasecontrol::constructor $par 
+    } {
+	set polydatacontrol1 [ $pcontrol1 GetPolyDataControl ]
+	set polydatacontrol2 [ $pcontrol2 GetPolyDataControl ] 
+	set landmarkcontrol  [ $landcontrol GetLandmarkControl ]
+	set overlaytool      $overlay
+	InitializeRpmTool
+    }
+
+    private method InitializeRpmTool { } 
+    public method Initialize { widget }
+    public method DelayedInitialize {  }
+    public method CreateUpdateControl { par }
+    public method Continue { } 
+    public method Stop {  } 
+    public method SetSurfaceMode { sur } 
+    public method ShowSurfaces { { applytransformation 0 } }
+    public method UpdateRPMViewer { visib { mode rpm } } 
+    public method UpdateRPMProgress { } 
+
+    public method ComputeLinearRPM  {   }
+    public method ComputeNonLinearRPM  {   } 
+    public method ComputeArticulatedRPM  {   } 
+    public method ComputeCommonRPM { registrationmethod button1 }
+
+    public method InitializeArticulatedModel  { }     
+
+
+    public method ShowWindow { args }
+
+    public method SaveSetup {  fname }
+    public method LoadSetup {  fname }
+
+    # Callback Handlers
+    public method HandleUpdateEvent { args }
+    public method HandleMouseEvent { mouse stat x1 x2 widgetname args }
+    
+    # Parameter Stuff
+    public method SetDefaultParameters { mode }
+
+    # Create Initial GUIs
+    public method CreateCommonRPMGUI { widget }
+    public method CreateLinearRPMGUI { widget }
+    public method CreateNonLinearRPMGUI { widget }
+    public method CreateArticulatedRPMGUI { widget }
+
+    # Set Transformation
+    public method SetTransformationToParentControl { xform name }
+
+}
+
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclrpm::SetDefaultParameters { mode } {
+
+    if { $mode == "all" || $mode == "nonlinear" } {
+
+	set md $thisparam($this,nonlinear_transformmode) 
+	set thisparam($this,nonlinear_fastthreshold) 3.0
+	set thisparam($this,nonlinear_attributesweight) 0.05
+	set thisparam($this,nonlinear_corr_mode)  "Labels"
+	set thisparam($this,nonlinear_useinitialtransform) 1
+	set thisparam($this,nonlinear_matchmode)    "Full RPM (Fast)"
+	set thisparam($this,nonlinear_usewls) 1
+	
+	
+	if { $md == "BSpline" } {
+	    set thisparam($this,nonlinear_maxnumlandmarks) 1000
+	    set thisparam($this,nonlinear_initialtemp) 4
+	    set thisparam($this,nonlinear_finaltemp)   2
+	    set thisparam($this,nonlinear_initialcps)  24
+	    set thisparam($this,nonlinear_finalcps)    12
+	    set thisparam($this,nonlinear_annealrate) 0.9;
+	    set thisparam($this,nonlinear_initialsmoothfactor) 5.0
+	    set thisparam($this,nonlinear_finalsmoothfactor)   1.0
+	    set thisparam($this,nonlinear_uselabels)  0
+
+	} elseif { $md == "TPS" } {
+	    set thisparam($this,nonlinear_maxnumlandmarks) 70
+	    set thisparam($this,nonlinear_initialtemp) 3
+	    set thisparam($this,nonlinear_finaltemp)   1
+	    set thisparam($this,nonlinear_annealrate) 0.9;
+	    set thisparam($this,nonlinear_initialsmoothfactor) 0.25
+	    set thisparam($this,nonlinear_uselabels)  1
+	} 
+    }
+
+    if { $mode == "all" || $mode == "linear" } {
+
+	set thisparam($this,attributesweight) 0.05
+	set thisparam($this,fastthreshold) 3.0
+	set thisparam($this,matchmode)    "Full RPM (Fast)"
+	set thisparam($this,maxnumlandmarks) 600
+	set thisparam($this,initialtemp) 6
+	set thisparam($this,finaltemp)   3
+	set thisparam($this,annealrate) 0.9;
+	set thisparam($this,uselabels)  1
+	set thisparam($this,corr_mode)  "Labels"
+	set thisparam($this,useinitialtransform) 0
+	set thisparam($this,usewls) 1
+    }
+
+    if { $mode == "all" || $mode == "articulated" } {
+
+	set thisparam($this,artic_useinitialtransform) 0
+	set thisparam($this,artic_corr_mode)  "Labels"
+	set thisparam($this,artic_attributesweight) 0.05
+	set thisparam($this,artic_landmarkset) 1
+
+	set thisparam($this,artic_initialtemp) 10.0
+	set thisparam($this,artic_finaltemp)    4.0
+	set thisparam($this,artic_annealrate)   0.8
+	set thisparam($this,artic_numpoints)    1000
+	set thisparam($this,artic_matchmode)    "Full RPM (Fast)"
+	set thisparam($this,artic_tolerance)    2.0
+	set thisparam($this,artic_jointmode)    "All"
+	set thisparam($this,artic_uselandmarks) 0
+	set thisparam($this,artic_maxnumlandmarks) 600
+	set thisparam($this,artic_fastthreshold) 3.0
+
+	set thisparam($this,gui_artic_thetablend) 0.5
+	set thisparam($this,gui_artic_zblend)     5.0
+	set thisparam($this,gui_artic_convergence) 0.5
+	set thisparam($this,gui_artic_modelname) "none"
+	set thisparam($this,gui_artic_numjoints) 0
+    }
+	
+}
+
+itcl::body pxitclrpm::InitializeRpmTool { } {
+
+    set registrationmethod [ vtkpxLinearRPMRegistration  [ pxvtable::vnewobj ]]
+    
+
+    set thisparam($this,transformmode) "Rigid"
+    set thisparam($this,nonlinear_transformmode) "BSpline"
+
+    set thisparam($this,gui_actmode1) "Points"
+    set thisparam($this,gui_actmode2) "Points"
+
+    set vtk_viewer                 [ vtkpxGUIRenderer [ pxvtable::vnewobj ] ]
+    set thisparam($this,gui_actor1)    0
+    set thisparam($this,gui_actor2)    0
+    set thisparam($this,gui_util)                    [ vtkpxSurfaceUtil [ pxvtable::vnewobj]]
+    	
+    set thisparam($this,gui_match_next) 0
+    set thisparam($this,gui_match_count) 0
+    set thisparam($this,gui_match_maxcount) Never
+    set thisparam($this,gui_renfilt) 0;
+    
+    set thisparam($this,gui_control1) 0
+    set thisparam($this,gui_control2) 0
+    set thisparam($this,gui_control3) 0
+    
+    set thisparam($this,gui_polydatacontrol_ref) $polydatacontrol1
+    set thisparam($this,gui_polydatacontrol_trn) $polydatacontrol2
+    set thisparam($this,gui_landmarkcontrol) $landmarkcontrol
+    set thisparam($this,gui_overlaytool)    $overlaytool
+
+
+    set thisparam($this,gui_surface_ref) 1;     
+    set thisparam($this,gui_surface_trn) 1 ;
+    set thisparam($this,gui_pointset) 1;     
+    set thisparam($this,gui_matchmatrixmode) "Auto"
+    set thisparam($this,gui_enablefeedback) 1;
+    set thisparam($this,gui_extradebug) "Normal";
+
+    $this SetDefaultParameters all
+
+    set parameterlist [ list annealrate artic_annealrate artic_attributesweight artic_corr_mode artic_fastthreshold artic_finaltemp artic_initialtemp artic_jointmode artic_landmarkset artic_matchmode artic_maxnumlandmarks artic_numpoints artic_tolerance artic_useinitialtransform artic_uselandmarks attributesweight corr_mode fastthreshold finaltemp gui_artic_convergence gui_artic_modelname gui_artic_numjoints gui_artic_thetablend gui_artic_zblend initialtemp matchmode maxnumlandmarks nonl [...]
+
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclrpm::CreateLinearRPMGUI { w } {
+	    
+
+    frame $w.c; pack $w.c -side top -expand f -fill x
+    checkbutton $w.c.3 -variable [ itcl::scope thisparam($this,useinitialtransform) ] -text "Use Initial Transformation" 
+    checkbutton $w.c.4 -variable [ itcl::scope thisparam($this,usewls) ] -text "Weighted Least Squares" 
+    pack    $w.c.3 $w.c.4 -side top -fill x -expand f
+	
+    set base $w
+
+    # Ref/Transform - Surface
+
+    set k 0; 
+
+    # Transform Type
+    set cw [ [ iwidgets::labeledwidget $base.$k  -labeltext "Transformation:"  ] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,transformmode) ] "Rigid" "Similarity" "Affine" 
+    pack $cw.optmenu  -expand f
+    pack $base.$k -side top -expand f  ;incr k
+    for { set i 0 } { $i <= 2 } { incr i } { eval "$cw.optmenu.menu entryconfigure $i -command { $this SetDefaultParameters linear }"    }
+
+    set cw [ [ iwidgets::labeledwidget $base.$k -labeltext  "Correspondence:"  ] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,matchmode) ] "ICP" "RPM" "Full RPM" "RPM (Fast)" "Full RPM (Fast)" 
+    pack $cw.optmenu  -expand t -fill x
+    pack $base.$k -side top -expand f  ;incr k
+
+    set cw [ [ iwidgets::labeledwidget  $base.$k -labeltext "Metric:"] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,corr_mode) ] "Distance" "Labels" "Attributes"
+    tk_optionMenu $cw.weight  [ itcl::scope thisparam($this,attributesweight) ] "0.0" "0.01" "0.02" "0.05" "0.1" "0.25" "0.5" "1.0" "5.0" "10.0"
+    pack $cw.optmenu $cw.weight -expand f -fill x -side left
+    pack $base.$k -side top -expand f  ;incr k
+
+
+
+    iwidgets::entryfield $base.$k -labeltext "Max Num Landmarks:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,maxnumlandmarks) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Initial Temperature:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,initialtemp) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Final Temperature:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,finaltemp) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Anneal Rate:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,annealrate) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+
+    iwidgets::entryfield $base.$k -labeltext "Search Threshold:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,fastthreshold) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::Labeledwidget::alignlabels $base.3 $base.4 $base.5 $base.6 $base.7 
+
+    frame $w.com; 
+    pack $w.com -side bottom -fill x -pady 10
+    set thisparam($this,gui_control1) [ button $w.com.b1 -text "Start RPM" ]
+    eval "$thisparam($this,gui_control1) configure -command { $this ComputeLinearRPM }"
+
+    eval "button $w.com.load -text \"Load Setup\" -command { $this LoadSetup  \"\" } "
+    eval "button $w.com.save -text \"Save Setup\" -command { $this SaveSetup  \"\" } "
+
+    pack $w.com.b1 $w.com.load $w.com.save -side top -fill x -expand t
+}
+
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclrpm::CreateArticulatedRPMGUI { w } {
+
+    set tmodelgui [ [ pxitclarticulatedmodel \#auto $this 0  ] GetThisPointer ]
+    $tmodelgui Initialize $w.[pxvtable::vnewobj ] 
+
+
+    set b [ LabelFrame:create  $w.a -text "Model" ]
+    pack $w.a -side top -expand f -fill x
+    
+
+    #eval "button $b.1 -text \"Initialize Model\" -command { $this InitializeArticulatedModel } "
+    eval "button $b.2 -text \"Edit Model\" -command { $tmodelgui ShowWindow \"\" } "
+    #    pack $b.1 $b.2  -side left -expand f -fill x
+    pack  $b.2  -side left -expand f -fill x
+
+
+
+    frame $w.c; pack $w.c -side top -expand f -fill x
+
+    if { $landmarkcontrol !=0 } {
+	
+	set b [ LabelFrame:create  $w.c.0 -text "Initial Joint Positions" ]
+
+	eval "button $b.0 -text \"Show Landmark Control\" -command { $thisparam($this,gui_landmarkcontrol) Show 1}"
+	checkbutton $b.1 -variable [ itcl::scope thisparam($this,artic_uselandmarks) ] -text "Use Initial Joints" 
+
+	set cw [ [ iwidgets::labeledwidget  $b.2 -labeltext "Joint Landmarks:"] childsite ]
+	tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,gui_pointset) ] "1" "2" "3" "4" "5" "6" "7" 
+	pack $cw.optmenu  -expand f -fill x
+	pack $b.2 $b.1 $b.0 -side top -expand f -fill x -padx 2
+	pack $w.c.0 -side top -expand false -fill x
+    }
+    checkbutton $w.c.3 -variable [ itcl::scope thisparam($this,artic_useinitialtransform) ] -text "Use Initial Transformation" 
+    pack  $w.c.3 -side top -fill x -expand f
+	
+    set base $w
+
+    set k 0; 
+
+    # Transform Type
+    set cw [ [ iwidgets::labeledwidget $base.$k  -labeltext "Transformation:"  ] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,artic_jointmode) ] "All" "Global" "SpineTail" "Hips" "Knees" 
+    pack $cw.optmenu  -expand f
+    pack $base.$k -side top -expand f  ;incr k
+
+    set cw [ [ iwidgets::labeledwidget $base.$k -labeltext  "Correspondence:"  ] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,artic_matchmode) ] "ICP" "RPM" "Full RPM" "RPM (Fast)" "Full RPM (Fast)" 
+    pack $cw.optmenu  -expand t -fill x
+    pack $base.$k -side top -expand f  ;incr k
+
+    set cw [ [ iwidgets::labeledwidget  $base.$k -labeltext "Metric:"] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,artic_corr_mode) ] "Distance" "Labels" "Attributes"
+    tk_optionMenu $cw.weight  [ itcl::scope thisparam($this,artic_attributesweight) ] "0.0" "0.01" "0.02" "0.05" "0.1" "0.25" "0.5" "1.0" "5.0" "10.0"
+    pack $cw.optmenu $cw.weight -expand f -fill x -side left
+    pack $base.$k -side top -expand f  ;incr k
+
+
+
+    iwidgets::entryfield $base.$k -labeltext "Max Num Landmarks:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,artic_maxnumlandmarks) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Initial Temperature:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,artic_initialtemp) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Final Temperature:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,artic_finaltemp) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Anneal Rate:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,artic_annealrate) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+
+    iwidgets::entryfield $base.$k -labeltext "Search Threshold:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,artic_fastthreshold) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Tolerance:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,artic_tolerance) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+
+
+    iwidgets::Labeledwidget::alignlabels $base.3 $base.4 $base.5 $base.6 $base.7  $base.8
+
+    frame $base.$k -height 2 -bg black; pack $base.$k -side top -expand f -fill x ; incr k
+
+
+
+    frame $w.com; 
+    pack $w.com -side bottom -fill x -pady 10
+    set thisparam($this,artic_gui_control1) [ button $w.com.b1 -text "Start RPM" ]
+    eval "$thisparam($this,artic_gui_control1) configure -command { $this ComputeArticulatedRPM }"
+
+    eval "button $w.com.load -text \"Load Setup\" -command { $this LoadSetup \"\" } "
+    eval "button $w.com.save -text \"Save Setup\" -command { $this SaveSetup \"\" } "
+
+    pack $w.com.b1 $w.com.load $w.com.save -side top -fill x -expand t
+}
+# --------------------------------------------------------------------------
+itcl::body pxitclrpm::CreateNonLinearRPMGUI { w } {
+
+    frame $w.c
+    pack $w.c -side top -fill x -pady 5
+
+    set cw [ [ iwidgets::labeledwidget  $w.c.2 -labeltext "Mode:"] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,nonlinear_corr_mode) ] "None" "Labels" "Attributes"
+    tk_optionMenu $cw.weight  [ itcl::scope thisparam($this,nonlinear_attributesweight) ] "0.0" "0.01" "0.02" "0.05" "0.1" "0.25" "0.5" "1.0" "5.0" "10.0"
+    pack $cw.optmenu $cw.weight -expand f -fill x -side left
+
+    checkbutton $w.c.3 -variable [ itcl::scope thisparam($this,nonlinear_useinitialtransform) ] -text "Use Initial Transformation" 
+    checkbutton $w.c.4 -variable [ itcl::scope thisparam($this,nonlinear_usewls) ] -text "Weighted Least Squares" 
+    pack  $w.c.2  $w.c.3 $w.c.4 -side top -fill x -expand f
+	
+    set base $w
+
+    # Ref/Transform - Surface
+
+    set k 0; 
+
+    # Transform Type
+    set cw [ [ iwidgets::labeledwidget $base.$k  -labeltext "Transformation:"  ] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,nonlinear_transformmode) ] "TPS" "BSpline"
+    pack $cw.optmenu  -expand f
+    pack $base.$k -side top -expand f  ;incr k
+
+    for { set i 0 } { $i <=1 } { incr i } {
+	eval "$cw.optmenu.menu entryconfigure $i -command { $this SetDefaultParameters nonlinear }"
+    }
+    set cw [ [ iwidgets::labeledwidget $base.$k -labeltext  "Correspondence:"  ] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,nonlinear_matchmode) ] "ICP" "RPM" "ICPPlus" "Full RPM" "RPM (Fast)" "Full RPM (Fast)" 
+    pack $cw.optmenu  -expand t -fill x
+    pack $base.$k -side top -expand f  ;incr k
+
+
+    iwidgets::entryfield $base.$k -labeltext "Max Num Landmarks:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,nonlinear_maxnumlandmarks) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Initial Temperature:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,nonlinear_initialtemp) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Final Temperature:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,nonlinear_finaltemp) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Anneal Rate:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,nonlinear_annealrate) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Initial Control Spacing:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,nonlinear_initialcps) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Final Control Spacing:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,nonlinear_finalcps) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Initial Smoothness:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,nonlinear_initialsmoothfactor) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+    iwidgets::entryfield $base.$k -labeltext "Final Smoothness:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,nonlinear_finalsmoothfactor) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+
+    iwidgets::entryfield $base.$k -labeltext "Search Threshold:"  -width 10 -validate real -textvariable [ itcl::scope thisparam($this,nonlinear_fastthreshold) ] -relief sunken 
+    pack $base.$k -side top -expand f  ;incr k
+
+
+    iwidgets::Labeledwidget::alignlabels $base.3 $base.4 $base.5 $base.6 $base.7  $base.8 $base.9 $base.10
+
+    frame $w.com; 
+    pack $w.com -side bottom -fill x -pady 10
+    set thisparam($this,nonlinear_gui_control1) [ button $w.com.b1 -text "Start RPM" ]
+    eval "$thisparam($this,nonlinear_gui_control1) configure -command { $this ComputeNonLinearRPM }"
+
+    eval "button $w.com.load -text \"Load Setup\" -command { $this LoadSetup  \"\" } "
+    eval "button $w.com.save -text \"Save Setup\" -command { $this SaveSetup  \"\" } "
+
+    pack $w.com.b1 $w.com.load $w.com.save  -side top -fill x -expand t
+
+}
+
+itcl::body pxitclrpm::Initialize { widget } {
+	
+    set basewidget [ toplevel $widget ]
+    wm geometry $basewidget 820x800
+    wm withdraw $basewidget
+    SetTitle "RPM - Registration"
+    set fullyinitialized 0
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget
+
+}
+
+itcl::body pxitclrpm::DelayedInitialize {  } {
+
+    if { $fullyinitialized ==1 } {
+	return
+    }
+
+    set pbar [ frame $basewidget.bot ]
+    set mbar [ frame $basewidget.top ]
+    pack $pbar -side bottom -expand f -fill x -pady 1
+    pack $mbar -side top -expand t -fill both -pady 1
+   
+    frame $mbar.right 
+
+    frame $mbar.left -width 450
+    pack $mbar.left -side left -expand f -fill y
+    pack $mbar.right -side right -expand t -fill both -padx 2
+
+    CreateProgressBar $pbar
+    CreateUpdateControl $mbar.right
+
+    set base [ LabelFrame:create  $mbar.left.1 -text "Common" ]
+    pack $mbar.left.1 -side top -expand false -fill x
+
+    set k 0
+    set cw [ [ iwidgets::labeledwidget  $base.$k -labeltext "Reference Surface:"] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,gui_surface_ref) ] "1"
+    set  vv 0
+    catch { set vv [  $polydatacontrol1 GetNumberOfSurfaces ] }
+    for { set i 2 } { $i <= $vv } { incr i } { $cw.optmenu.menu add radio -label "$i" -variable [ itcl::scope thisparam($this,gui_surface_ref) ] }
+
+    eval "button $cw.b1 -text \"Ref Sur\" -command { $thisparam($this,gui_polydatacontrol_ref) Show 1}"
+    pack $cw.b1 -side right  -expand f -fill x;   
+    pack $cw.optmenu  -expand f -fill x;   
+    pack $base.$k -side top -expand f  ;incr k
+
+    
+
+
+    set cw [ [ iwidgets::labeledwidget  $base.$k -labeltext "Transform Surface:"] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,gui_surface_trn) ] "1" 
+    set  vv 0
+    catch { set vv [  $polydatacontrol2 GetNumberOfSurfaces ] }
+    for { set i 2 } { $i <= $vv } { incr i } { $cw.optmenu.menu add radio -label "$i" -variable [ itcl::scope thisparam($this,gui_surface_trn) ] }
+    eval "button $cw.b2 -text \"Trn Sur\" -command { $thisparam($this,gui_polydatacontrol_trn) Show 1}"
+    pack $cw.b2 -side right  -expand f -fill x;   
+    pack $cw.optmenu  -expand f -fill x
+    pack $base.$k -side top -expand f  ;incr k
+
+
+
+    set cw [ [ iwidgets::labeledwidget $base.$k -labeltext  "Match Matrix Type:"  ] childsite ]
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,gui_matchmatrixmode) ] "Auto" "Sparse" "Dense" 
+    pack $cw.optmenu  -expand f
+    pack $base.$k -side top -expand f  ;incr k
+
+    set cw [ [ iwidgets::labeledwidget $base.$k -labeltext  "Visual Feedback:"  ] childsite ]
+    pack $base.$k -side top -expand f  ;incr k
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,gui_enablefeedback) ] "1" "2" "5" "10" "None"
+    pack $cw.optmenu  -expand f -fill x
+
+    set cw [ [ iwidgets::labeledwidget $base.$k -labeltext  "Debug Mode:"  ] childsite ]
+    pack $base.$k -side top -expand f  ;incr k
+    tk_optionMenu $cw.optmenu [ itcl::scope thisparam($this,gui_extradebug) ] "None" "Normal" "Extra"
+    pack $cw.optmenu  -expand f -fill x 
+
+
+    eval "button $mbar.left.3 -text \"Close Window\" -command {  wm withdraw $basewidget } -fg red"
+    pack $mbar.left.3 -side bottom -expand false -fill x -pady 2
+    
+
+    set notebook [ iwidgets::tabnotebook $mbar.left.2  -tabpos n -width 250 ]
+    pack $notebook -side bottom -expand t -fill both
+    CreateLinearRPMGUI       [ $notebook add -label "Linear" ]
+
+    set ok 0
+    catch { set ok [ vtkpxPolySimilarityRPMRegistration [ pxvtable::vnewobj ]]; $ok Delete }
+
+    if { $ok == 0 } {
+	set enablearticulated 0
+    }
+
+    if { $enablearticulated == 1 } {
+	CreateArticulatedRPMGUI  [ $notebook add -label "Articulated" ]
+    }
+    CreateNonLinearRPMGUI    [ $notebook add -label "NonLinear" ]
+
+    $notebook view "Linear"
+
+
+    set fullyinitialized 1
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclrpm::CreateUpdateControl { par } {
+
+    set w [ frame $par.rtop -bg black ]
+    pack $w -side top -expand f -fill x -pady 1 
+    
+
+    set b [ LabelFrame:create  $w.cont -text "" ]
+    pack $w.cont -side top -fill x -pady 0 -expand true
+
+    set thisparam($this,gui_control2) [ button $b.b3 -text "Show Surfaces" ]
+    set thisparam($this,gui_control3) [ button $b.b4 -text "Apply Transformation" ]
+    eval "$thisparam($this,gui_control2) configure -command {  $this ShowSurfaces 0 }"
+    eval "$thisparam($this,gui_control3) configure -command {  $this ShowSurfaces 1 }"
+    eval "button $b.b5 -text \"Show Transform Control\" -command { $thisparam($this,gui_overlaytool) ShowWindow Transformations }"
+    pack $b.b3 $b.b4 $b.b5  -side left -fill x -padx 2 -expand true
+    
+    
+    set wtop [ LabelFrame:create  $par.top -text "Viewer" ]
+    pack $par.top -side top -fill both -expand true 
+    $par.top configure 
+
+    set ren [ vtkRenderer [ pxvtable::vnewobj ]]
+
+    frame $wtop.bot
+    pack $wtop.bot -side bottom -expand f -fill x
+    set renWidg [ vtkTkRenderWidget $wtop.r ]
+    pack $renWidg -side top -expand true -fill both
+    set renderwindow [ $renWidg GetRenderWindow ]
+    $renderwindow AddRenderer $ren
+
+    $vtk_viewer BindMouseEvents $renWidg "$this HandleMouseEvent" "$this HandleUpdateEvent"
+    $vtk_viewer SetNoPolyClipControls 1
+    $vtk_viewer Initialize $wtop.bot $ren 1
+    
+    set disp [  LabelFrame:create  $par.b1 -text "Display Controls" ]
+    pack $par.b1 -side bottom -fill x
+    set w   [ frame $disp.b1 ]
+    set w2  [ frame $disp.b2 ]
+    pack $w $w2 -side bottom -fill x 
+    
+    label $w2.m -text "Reference:"
+    tk_optionMenu $w2.opt   [ itcl::scope thisparam($this,gui_actmode1) ] "Surface" "Wireframe" "Points" "None"
+    label $w2.m2 -text "Target:"
+    tk_optionMenu $w2.opt2  [ itcl::scope thisparam($this,gui_actmode2) ] "Surface" "Wireframe" "Points" "None"
+    pack $w2.m $w2.opt $w2.m2 $w2.opt2 -side left -fill x -expand t
+    
+    for { set k 0 } { $k <=2 } { incr k } {
+	eval "$w2.opt.menu   entryconfigure $k -command { $this SetSurfaceMode 1 }"
+	eval "$w2.opt2.menu  entryconfigure $k -command { $this SetSurfaceMode 2 }"
+    }
+    
+    eval "button $w.next -text Continue -command { $this Continue }"
+    eval "button $w.stop -text Stop! -command { $this Stop }"
+    
+    label $w.m -text "Stop every:"
+    tk_optionMenu $w.opt [ itcl::scope thisparam($this,gui_match_maxcount) ] "1" "3" "5" "8" "10" "20" "Never"
+    pack $w.m $w.opt $w.next $w.stop -side left -fill x -expand t
+    
+    for { set j 1 } { $j <= 2 } { incr j } {
+	set thisparam($this,gui_actor$j) [ vtkActor [ pxvtable::vnewobj ] ]
+	set act $thisparam($this,gui_actor$j)
+	
+	set map [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+	$act SetMapper $map
+	
+	$map Delete
+	$act SetVisibility 0
+	
+	[ $act GetProperty] SetRepresentationToPoints
+	[ $act GetProperty ] SetAmbient 1.0 
+	[ $act GetProperty ] SetDiffuse 0.0
+	[ $act GetProperty ] SetOpacity 1.0
+	if { $j == 1 } {
+	    [ $act GetProperty] SetColor 1.0 0.0 0.0
+	} else {
+	    [ $act GetProperty] SetColor 0.0 1.0 0.0
+	}
+	
+	[ $vtk_viewer GetRenderer ] AddActor $act
+    }
+    [ $vtk_viewer GetRenderer ] SetBackground 0.2 0.2 0.3
+}
+# ---------------------------------------------------------------------------    
+# ------------------------
+# callback addon commands
+# ------------------------
+
+itcl::body pxitclrpm::Continue { } {
+    set  thisparam($this,gui_match_next) [ expr  1 - $thisparam($this,gui_match_next) ]
+}
+    
+itcl::body pxitclrpm::Stop {  } {
+
+    if {$thisparam($this,gui_renfilt) != 0 } {
+	$thisparam($this,gui_renfilt) SetAbortExecute 1 
+	set thisparam($this,gui_match_next) [ expr  1 - $thisparam($this,gui_match_next) ]
+    }
+}
+
+itcl::body pxitclrpm::SetSurfaceMode { sur } {
+	
+    set act $thisparam($this,gui_actor$sur)
+    set mode $thisparam($this,gui_actmode$sur)
+    
+    if { $mode != "None" } {
+	$act SetVisibility 1
+	[ $act GetProperty ] SetRepresentationTo$mode
+	if { [  [ $act GetProperty ] GetRepresentationAsString ] == "Surface" } {
+	    [ $act GetProperty ] SetAmbient 0.0 
+	    [ $act GetProperty ] SetDiffuse 1.0
+	    [ $act GetProperty ] SetOpacity 1.0
+	} else {
+	    [ $act GetProperty ] SetAmbient 1.0 
+	    [ $act GetProperty ] SetDiffuse 0.0
+	    [ $act GetProperty ] SetOpacity 1.0
+	    [ $act GetProperty ] SetLineWidth 1.0
+	    [ $act GetProperty ] SetPointSize 3.0
+	}
+    } else {
+	$act SetVisibility 0
+    }
+    [ [ $vtk_viewer GetRenderer ] GetRenderWindow ] Render 
+}
+
+
+itcl::body pxitclrpm::ShowSurfaces { { applytransformation 0 } } {
+ 
+    set sourcesurface [ $thisparam($this,gui_polydatacontrol_ref) GetSurface [expr $thisparam($this,gui_surface_ref) -1 ]]
+    set targetsurface [ $thisparam($this,gui_polydatacontrol_trn) GetSurface [expr $thisparam($this,gui_surface_trn) -1 ]]
+
+    set dat1 $sourcesurface
+    set dat2 $targetsurface
+    set dat_trn 0
+
+    [ $thisparam($this,gui_actor2) GetMapper ] SetInput $dat2
+    [ $thisparam($this,gui_actor2) GetMapper ] Update
+
+    if { $applytransformation !=0 } {
+
+	if { $applytransformation == "articulatedmodel" } {
+	    set dat_trn [ $tmodelgui GetTransformation ]
+	} else {
+	    catch { 
+		if { [ [  $overlaytool GetTransformation ] IsA vtkAbstractTransform ] ==1 } {
+		    set dat_trn [  $overlaytool GetTransformation ]
+		}
+	    }
+	}
+    }
+    
+    if { $dat_trn == 0 } {
+	[ $thisparam($this,gui_actor1) GetMapper ] SetInput $dat1
+    } else {
+	puts stderr "Using transformation $dat_trn"
+
+	set filt2m [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+	$filt2m SetInput $dat1
+	$filt2m SetTransform $dat_trn
+	$filt2m Update
+	set sur [ vtkPolyData [ pxvtable::vnewobj ]]
+	$sur ShallowCopy [ $filt2m GetOutput ]
+
+	[ $thisparam($this,gui_actor1) GetMapper ] SetInput $sur
+	$filt2m Delete 
+	$sur Delete
+    }
+    [ $thisparam($this,gui_actor1) GetMapper ] Update
+    
+    [ $thisparam($this,gui_actor2) GetMapper ]  ScalarVisibilityOn
+    [ $thisparam($this,gui_actor1) GetMapper ]  ScalarVisibilityOn
+    set r0 0
+    set r1 1
+    catch {
+	set r [ [ [ $dat1 GetPointData ] GetScalars ] GetRange ] 
+	set r0 [lindex $r 0 ]
+	set r1 [lindex $r 1 ]
+    }
+    [ $thisparam($this,gui_actor1) GetMapper ]  SetScalarRange $r0 $r1
+    [ $thisparam($this,gui_actor2) GetMapper ]  SetScalarRange $r0 $r1
+    $thisparam($this,gui_actor1) SetVisibility 1
+    $thisparam($this,gui_actor2) SetVisibility 1
+
+    [ $vtk_viewer GetRenderer ] ResetCamera
+    [ [ $vtk_viewer GetRenderer ] GetRenderWindow ] Render
+}
+
+# ------------------------
+#  Update  commands
+# -----------------------------------------------------------------------------------
+
+itcl::body pxitclrpm::UpdateRPMViewer { visib { mode rpm } } {
+
+    ShowProgress $thisparam($this,gui_renfilt) "RPM Transform"
+
+    catch {
+	if { [ $thisparam($this,gui_renfilt) IsA "vtkpxPolySimilarityRPMRegistration"  ] ==1 } {
+	    $tmodelgui UpdateGUIFromTransformation 0
+	}
+    }
+	
+    set sourcesurface [ $thisparam($this,gui_polydatacontrol_ref) GetSurface [expr $thisparam($this,gui_surface_ref) -1 ]]
+    set targetsurface [ $thisparam($this,gui_polydatacontrol_trn) GetSurface [expr $thisparam($this,gui_surface_trn) -1 ]]
+
+    set dat1 $sourcesurface
+    set dat2 $targetsurface
+
+    if { $mode == "rpm" } {
+	set dat_trn  [ $thisparam($this,gui_renfilt) GetCurrentTransformation ]
+    } elseif { $mode == "articulatedmodel" } {
+	set dat_trn [ $tmodelgui GetTransformation ]
+    } elseif { $notebook !=0 } {
+	set uset 0
+	set nt [ $notebook view ]
+
+	if { $nt == 2 } {
+	    set uset $thisparam($this,artic_useinitialtransform) 
+	} elseif { $nt ==1 } {
+	    set uset $thisparam($this,nonlinear_useinitialtransform) 
+	} else {
+	    set uset $thisparam($this,useinitialtransform) 
+	}
+
+	if { $uset == 0 } {
+	    set dat_trn 0
+	} else {
+	    set dat_trn [   $overlaytool GetTransformation ]
+	}
+    } 
+         
+    
+    [ $thisparam($this,gui_actor2) GetMapper ] SetInput $dat2
+    [ $thisparam($this,gui_actor2) GetMapper ] Update
+    
+    
+    #$thisparam($this,gui_util) AddObjectMapLookupTableToSurface $dat1
+
+    if { $dat_trn == 0 } {
+	[ $thisparam($this,gui_actor1) GetMapper ] SetInput $dat1
+    } else {
+	set filt2m [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+	$filt2m SetInput $dat1
+	$filt2m SetTransform $dat_trn
+	$filt2m Update
+	set sur [ vtkPolyData [ pxvtable::vnewobj ]]
+	$sur ShallowCopy [ $filt2m GetOutput ]
+	[ $thisparam($this,gui_actor1) GetMapper ] SetInput $sur
+	$filt2m Delete 
+	$sur Delete
+    }
+
+    [ $thisparam($this,gui_actor1) GetMapper ] Update
+    
+    if { $visib > 0 } {
+	[ $thisparam($this,gui_actor2) GetMapper ]  ScalarVisibilityOn
+	[ $thisparam($this,gui_actor1) GetMapper ]  ScalarVisibilityOn
+	
+	set r0 0
+	set r1 1
+	catch {
+	    set r [ [ [ $dat1 GetPointData ] GetScalars ] GetRange ] 
+	    set r0 [lindex $r 0 ]
+	    set r1 [lindex $r 1 ]
+	}
+	[ $thisparam($this,gui_actor1) GetMapper ]  SetScalarRange $r0 $r1
+	[ $thisparam($this,gui_actor2) GetMapper ]  SetScalarRange $r0 $r1
+    }
+    
+    $thisparam($this,gui_actor1) SetVisibility 1
+    $thisparam($this,gui_actor2) SetVisibility 1
+    
+    [ [ $vtk_viewer GetRenderer ] GetRenderWindow ] Render
+    
+}
+
+itcl::body pxitclrpm::UpdateRPMProgress { } {
+    
+    UpdateRPMViewer 0
+    update idletasks
+    
+    incr thisparam($this,gui_match_count)
+    if { $thisparam($this,gui_match_count) == $thisparam($this,gui_match_maxcount) } {
+	ShowProgress $thisparam($this,gui_renfilt) "RPM Transform -- Paused"
+	vwait  [ itcl::scope thisparam($this,gui_match_next) ]
+	set thisparam($this,gui_match_count) 0 
+	ShowProgress $thisparam($this,gui_renfilt) "RPM Transform"
+	incr thisparam($this,gui_match_count) 
+    }
+    
+    if { $thisparam($this,gui_match_count) > $thisparam($this,gui_match_maxcount) } {
+	set thisparam($this,gui_match_count) 0
+    }
+    
+    return 0
+}
+
+    
+# ---------------------------------------------------------------------------------
+#  Run RPM !!!
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclrpm::ComputeCommonRPM  { registrationmethod  button1 } { 
+
+    WatchOn 
+
+    set thisparam($this,gui_renfilt) $registrationmethod    
+    set thisparam($this,gui_match_count) 0
+
+    $registrationmethod EnableFeedbackOn
+    eval "$registrationmethod AddObserver ProgressEvent { $this UpdateRPMProgress }"
+    eval "$registrationmethod AddObserver EndEvent      { $this UpdateRPMProgress }"
+	
+    $registrationmethod SetSource [ $thisparam($this,gui_polydatacontrol_ref) GetSurface [expr $thisparam($this,gui_surface_ref) -1 ]]
+    $registrationmethod SetTarget [ $thisparam($this,gui_polydatacontrol_trn) GetSurface [expr $thisparam($this,gui_surface_trn) -1 ]]
+
+    if { $thisparam($this,gui_enablefeedback) == "None" } {
+	$registrationmethod SetEnableFeedback 0 
+    } else {
+	$registrationmethod SetEnableFeedback $thisparam($this,gui_enablefeedback)
+    }
+
+    UpdateRPMViewer 1
+    [ $vtk_viewer GetRenderer ] ResetCamera
+    [ [ $vtk_viewer GetRenderer ] GetRenderWindow ] Render
+    
+    $button1 configure -state disabled
+    $thisparam($this,gui_control2) configure -state disabled
+    $thisparam($this,gui_control3) configure -state disabled
+    
+    switch -exact $thisparam($this,gui_extradebug) {
+	"None" {
+	    $registrationmethod SetExtraDebug 0
+	    $registrationmethod DebugOff
+	}
+	"Normal" {
+	    $registrationmethod SetExtraDebug 0
+	    $registrationmethod DebugOn
+	}
+	"Extra" {
+	    $registrationmethod SetExtraDebug 1
+	    $registrationmethod DebugOn
+	}
+    }
+    
+    $registrationmethod Run
+    $button1  configure -state normal
+    $thisparam($this,gui_control2) configure -state normal
+    $thisparam($this,gui_control3) configure -state normal
+    
+    if { $thisparam($this,gui_overlaytool) != 0 } {
+	set ind [ $this SetTransformationToParentControl [ $registrationmethod GetCurrentTransformation ] rpm ]
+	if { $ind >=0 } {
+	    ::pxtclutil::Info "RPM Registration Algorithm Completed. The resulting transformation is stored on the overlay tool (index=$ind)"
+	}
+    } else {
+	::pxtclutil::Info "RPM Registration Algorithm Completed!"
+    }
+	
+    set thisparam($this,gui_renfilt) 0
+    
+    WatchOff
+}
+
+# ---------------------------------------------------------------------------------
+itcl::body pxitclrpm::SetTransformationToParentControl { xform name } {
+
+    if { $thisparam($this,gui_overlaytool) != 0 } {
+	return [ $thisparam($this,gui_overlaytool) AddTransformation $xform  $name ]
+    } 
+
+    return -1
+}
+
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclrpm::ComputeLinearRPM  {   } { 
+
+    set attrib 0
+    set attribw $thisparam($this,attributesweight) 
+
+    if { $thisparam($this,corr_mode) == "Labels" } { 
+	set thisparam($this,uselabels)  1
+    } elseif { $thisparam($this,corr_mode) == "Attributes" } { 
+	set attrib 1
+    }
+
+    catch { $registrationmethod Delete }
+
+    set registrationmethod [ vtkpxLinearRPMRegistration [ pxvtable::vnewobj ]]
+
+    switch -exact $thisparam($this,transformmode) {
+	"Rigid"      { 
+	    $registrationmethod  SetTransformModeToRigid 
+	}
+	"Similarity" { 
+	    $registrationmethod  SetTransformModeToSimilarity
+	}
+	"Affine"     { 
+	    $registrationmethod  SetTransformModeToAffine 
+	}
+    }
+
+    
+    switch -exact $thisparam($this,matchmode) {
+	"ICP"         { $registrationmethod   SetMatchModeToICP }
+	"RPM" { $registrationmethod  SetMatchModeToMixture }
+	"Full RPM"    { $registrationmethod   SetMatchModeToRPM }
+	"RPM (Fast)"       { $registrationmethod   SetMatchModeToMixtureFast }
+	"Full RPM (Fast)"    { $registrationmethod   SetMatchModeToRPMFast }
+    }
+    
+    $registrationmethod SetMaximumNumberOfLandmarks $thisparam($this,maxnumlandmarks)
+    
+    switch -exact $thisparam($this,gui_matchmatrixmode) {
+	"Auto"   {    $registrationmethod SetMatchMatrixTypeToAuto }
+	"Dense"  {    $registrationmethod SetMatchMatrixTypeToDense }
+	"Sparse" {    $registrationmethod SetMatchMatrixTypeToSparse }
+    }
+    
+    $registrationmethod SetUseSymmetricCorrespondence 0
+    $registrationmethod SetUseLabels                  $thisparam($this,uselabels)
+    $registrationmethod SetUseAttributes              $attrib
+    $registrationmethod SetAttributesWeight           $attribw
+    $registrationmethod SetUseWeightedLeastSquares    $thisparam($this,usewls)
+    $registrationmethod SetUseInitialTransform        $thisparam($this,useinitialtransform)
+    $registrationmethod SetInitialTemperature         $thisparam($this,initialtemp)
+    $registrationmethod SetFinalTemperature           $thisparam($this,finaltemp)
+    $registrationmethod SetFastThreshold              $thisparam($this,fastthreshold)
+    $registrationmethod SetAnnealRate                 $thisparam($this,annealrate)
+    
+    if { $thisparam($this,useinitialtransform) == 1 } {
+	$registrationmethod SetInitialTransform [  $overlaytool GetTransformation ]
+    }
+
+    ComputeCommonRPM $registrationmethod     $thisparam($this,gui_control1)
+
+}
+# ------------------------------------------------------------------------------------------
+
+itcl::body pxitclrpm::ComputeNonLinearRPM  {   } { 
+
+
+    set attrib 0
+    set attribw $thisparam($this,nonlinear_attributesweight) 
+
+    if { $thisparam($this,nonlinear_corr_mode) == "Labels" } { 
+	set thisparam($this,nonlinear_uselabels)  1
+    } elseif { $thisparam($this,corr_mode) == "Attributes" } { 
+	set attrib 1
+    }
+    catch { $registrationmethod Delete }
+
+    if {  $thisparam($this,transformmode) ==  "TPS" } {
+	set registrationmethod [ vtkpxTPSRPMRegistration [ pxvtable::vnewobj ]]
+    } else {
+	set registrationmethod [ vtkpxBSplineRPMRegistration [ pxvtable::vnewobj ]]
+	$registrationmethod SetInitialControlPointSpacing   $thisparam($this,nonlinear_initialcps)
+	$registrationmethod SetFinalControlPointSpacing     $thisparam($this,nonlinear_finalcps)
+    }
+
+    switch -exact $thisparam($this,nonlinear_matchmode) {
+	"ICP"         { $registrationmethod   SetMatchModeToICP }
+	"ICPPlus"     { $registrationmethod   SetMatchModeToICPPlus }
+	"RPM" { $registrationmethod  SetMatchModeToMixture }
+	"Full RPM"    { $registrationmethod   SetMatchModeToRPM }
+	"RPM (Fast)"       { $registrationmethod   SetMatchModeToMixtureFast }
+	"Full RPM (Fast)"    { $registrationmethod   SetMatchModeToRPMFast }
+    }
+    
+    $registrationmethod SetMaximumNumberOfLandmarks $thisparam($this,nonlinear_maxnumlandmarks)
+
+    switch -exact $thisparam($this,gui_matchmatrixmode) {
+	"Auto"   {    $registrationmethod SetMatchMatrixTypeToAuto }
+	"Dense"  {    $registrationmethod SetMatchMatrixTypeToDense }
+	"Sparse" {    $registrationmethod SetMatchMatrixTypeToSparse }
+    }
+    
+    $registrationmethod SetUseSymmetricCorrespondence 0
+    $registrationmethod SetUseLabels                  $thisparam($this,nonlinear_uselabels)
+    $registrationmethod SetUseAttributes              $attrib
+    $registrationmethod SetAttributesWeight           $attribw
+    $registrationmethod SetUseWeightedLeastSquares    $thisparam($this,nonlinear_usewls)
+    $registrationmethod SetUseInitialTransform        $thisparam($this,nonlinear_useinitialtransform)
+    $registrationmethod SetInitialTemperature         $thisparam($this,nonlinear_initialtemp)
+    $registrationmethod SetFinalTemperature           $thisparam($this,nonlinear_finaltemp)
+    $registrationmethod SetFastThreshold              $thisparam($this,nonlinear_fastthreshold)
+    $registrationmethod SetInitialSmoothnessFactor    $thisparam($this,nonlinear_initialsmoothfactor)
+    $registrationmethod SetFinalSmoothnessFactor      $thisparam($this,nonlinear_finalsmoothfactor)
+    $registrationmethod SetAnnealRate                 $thisparam($this,nonlinear_annealrate)
+    
+
+    if { $thisparam($this,nonlinear_useinitialtransform) == 1 } {
+	$registrationmethod SetInitialTransform [  $overlaytool GetTransformation ]
+	puts stdout "Using Initial Transform of type [ [ $overlaytool GetTransformation ] GetClassName ]\n\n\n\n"
+    } else {
+	puts stdout "********** Not Using Initial Transform of type [ [ $overlaytool GetTransformation ] GetClassName ]\n\n\n\n"
+    }
+
+    ComputeCommonRPM $registrationmethod  $thisparam($this,nonlinear_gui_control1)
+}
+
+
+::itcl::body pxitclrpm::ShowWindow { args } {
+
+    if { $fullyinitialized == 0 } {
+	$this DelayedInitialize
+    }
+    ::pxitclbasecontrol::ShowWindow $args
+    ShowSurfaces 0
+
+}
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclrpm::InitializeArticulatedModel  { } {
+
+    set curve [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    set origcurve [ $thisparam($this,gui_landmarkcontrol) GetCollection [expr $thisparam($this,gui_pointset) -1 ]]
+    $curve Copy $origcurve 
+    $curve Compact
+    set points [ $curve GetPoints ]
+    
+    set tr [  $overlaytool GetTransformation ]
+    if { [ $tr IsA "vtkLinearTransform " ] ==1 } {
+	puts stderr "Initializing Using Initial Transformation"
+	[ $tmodelgui GetTransformation ] InitializeRearLimbPresetRotations $points  $tr
+    } else {
+	[ $tmodelgui GetTransformation ] InitializeRearLimbPresetRotations $points 
+    }
+    $curve Delete
+}
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclrpm::ComputeArticulatedRPM  {   } { 
+
+
+    set tmodel [ $tmodelgui GetTransformation ] 
+    if { $tmodel == 0 } {
+	::pxtclutil::Warning "Cannot Compute Articulated RPM Registration. No Model Defined\n"
+	$tmodelgui ShowWindow \"\"
+	return
+    }
+
+
+    set attrib 0
+    set attribw $thisparam($this,artic_attributesweight) 
+
+    if { $thisparam($this,artic_corr_mode) == "Labels" } { 
+	set thisparam($this,artic_uselabels)  1
+    } elseif { $thisparam($this,artic_corr_mode) == "Attributes" } { 
+	set attrib 1
+    }
+    catch { $registrationmethod Delete }
+
+    set registrationmethod [ vtkpxPolySimilarityRPMRegistration [ pxvtable::vnewobj ]]
+
+    switch -exact $thisparam($this,artic_matchmode) {
+	"ICP"         { $registrationmethod   SetMatchModeToICP }
+	"ICPPlus"     { $registrationmethod   SetMatchModeToICPPlus }
+	"RPM" { $registrationmethod  SetMatchModeToMixture }
+	"Full RPM"    { $registrationmethod   SetMatchModeToRPM }
+	"RPM (Fast)"       { $registrationmethod   SetMatchModeToMixtureFast }
+	"Full RPM (Fast)"    { $registrationmethod   SetMatchModeToRPMFast }
+    }
+    
+    $registrationmethod SetMaximumNumberOfLandmarks $thisparam($this,artic_maxnumlandmarks)
+
+    switch -exact $thisparam($this,gui_matchmatrixmode) {
+	"Auto"   {    $registrationmethod SetMatchMatrixTypeToAuto }
+	"Dense"  {    $registrationmethod SetMatchMatrixTypeToDense }
+	"Sparse" {    $registrationmethod SetMatchMatrixTypeToSparse }
+    }
+    
+    $registrationmethod SetUseSymmetricCorrespondence 0
+    $registrationmethod SetUseLabels                  $thisparam($this,artic_uselabels)
+    $registrationmethod SetUseAttributes              $attrib
+    $registrationmethod SetAttributesWeight           $attribw
+    $registrationmethod SetUseWeightedLeastSquares    1
+
+
+    $registrationmethod SetInitialTemperature         $thisparam($this,artic_initialtemp)
+    $registrationmethod SetFinalTemperature           $thisparam($this,artic_finaltemp)
+    $registrationmethod SetFastThreshold              $thisparam($this,artic_fastthreshold)
+    $registrationmethod SetAnnealRate                 $thisparam($this,artic_annealrate)
+    $registrationmethod SetTolerance                  $thisparam($this,artic_tolerance)
+    $registrationmethod SetUseInitialTransform        $thisparam($this,artic_useinitialtransform)    
+
+    if { $thisparam($this,artic_useinitialtransform) == 1 } {
+	
+	if { $thisparam($this,artic_uselandmarks) == 1 } {
+	    $this InitializeArticulatedModel 
+	}
+
+	if { $thisparam($this,artic_useinitialtransform) == 1 } {
+	    $registrationmethod SetInitialTransform [  $overlaytool GetTransformation ]
+	}
+    } 
+   
+    set tr [ $registrationmethod GetCurrentTransformation ]
+    $tr SetRegionLabel [ $tmodel GetRegionLabel ]
+    set col [ $tr  GetTransformationCollection ]
+    $col RemoveAllItems
+
+    set numberofparts [ $tmodel GetNumberOfTransformations ]
+    set maxpart $numberofparts
+
+    $tr SetTransform 0 [ $tmodel GetTransform 0 ]
+
+    
+    for { set i 1 } { $i< $numberofparts } { incr i } {
+	set tsim [ $tmodel GetTransform $i ]
+	set name [ $tsim GetJointName ]
+	set flag "enabled"
+
+	switch -exact $thisparam($this,artic_jointmode) {
+	    "Global" {
+		set flag "disabled"
+	    }
+	    "SpineTail" {
+		if { [ string first "Spine" $name ] == -1 && 
+		     [ string first "Tail"  $name ] == - 1 } {
+		    set flag "disabled"
+		}
+	    }
+	    "Hips" {
+		if { [ string first "Knee" $name ] >=0 || 
+		     [ string first "Foot"  $name ] >=0 } {
+		    set flag "disabled"
+		}
+		
+	    }
+	    "Knees" {
+		if { [ string first "Foot"  $name ] >=0 } {
+		    set flag "disabled"
+		}
+	    }
+	}
+
+	if { $flag=="disabled" } {
+	    $tsim SetActive 0
+	}
+
+	set blend($i) [ $tsim GetBlendedMode ]
+	$tsim SetBlendedMode 0
+	$tr SetTransform $i $tsim
+	puts stderr "Name $name --> $flag  [ [ $tsim GetSimilarityTransform ] GetTranslationScale ]"
+    }
+    puts stderr "\n"
+
+    
+    
+
+    ComputeCommonRPM $registrationmethod  $thisparam($this,artic_gui_control1)
+
+
+    for { set i 1 } { $i< $numberofparts } { incr i } {
+	set tsim [ $tmodel GetTransform $i ]
+	$tsim SetActive 1
+	$tsim SetBlendedMode $blend($i)
+    }
+}
+
+
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclrpm::SaveSetup {  fname } {
+
+    set typelist { 
+	{"Rpm setup file" {.srpm}} 
+	{"All Files" {*}}
+    }
+	    
+    if { [ string length $fname ] < 2 } {
+	set fname [tk_getSaveFile -title "Save RPM Parameters" -filetypes $typelist]
+    }
+    
+    if { [string length $fname ] < 2 } {
+	return 0;
+    }
+
+    set fileid [open $fname w]
+    
+    puts $fileid "#RPM Parameter File\n-----------------------------------"
+    for { set i 0 } { $i < [ llength $parameterlist ] } { incr i } {
+	set key [ lindex $parameterlist $i ]
+	puts $fileid "$key:$thisparam($this,$key)"
+    }
+    close $fileid
+    return 1
+}
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclrpm::LoadSetup { fname } {
+
+    set typelist { 
+	{"Rpm setup file" {.srpm}} 
+	{"All Files" {*}}
+    }
+	    
+    if { [ string length $fname ] < 2 } {
+	set fname [tk_getOpenFile -title "Load RPM Parameters" -filetypes $typelist]
+    }
+    
+    if { [string length $fname ] < 2 } {
+	return 0;
+    }
+    
+    if { [ file exists $fname ] == 0 } {
+	return 0
+    }
+
+    set fileid [open $fname r]
+    set line ""
+    gets $fileid line
+
+    if { [ string compare $line "#RPM Parameter File" ] != 0 } {
+	::pxtclutil::Warning "Cannot read RPM Parameter File\n Bad Header = $line \n"
+	close $fileid
+	return 0
+    }
+    # Skip Underline !!!
+
+    while { [ gets $fileid line ] >=0 } {
+	set index [string first ":" $line]
+	if { $index > 0 }  {
+	    set len   [string length $line]
+	    set key   [string trim   [string range $line 0 [expr $index - 1]]]
+	    set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+	    set thisparam($this,$key)  $value 
+	}
+    }
+    close $fileid
+    return 1
+}
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclrpm::HandleUpdateEvent { args } {
+    
+    if {$renderwindow != 0 } {
+	$renderwindow Render
+    }
+}
+# ---------------------------------------------------------------------------------
+itcl::body pxitclrpm::HandleMouseEvent { mouse stat x1 x2 widgetname args} {
+    
+    if { $vtk_viewer == 0 } {
+	return
+    }
+    
+    # Need to flip y-axis vtk counts from bottom tk counts from top !!!
+    set wd [ $renderwindow GetSize ]
+    set x2 [ expr [lindex $wd 1 ] - $x2 ]
+    $vtk_viewer HandleMouseButtonEvent $mouse $stat $x1 $x2
+    
+}
+# ---------------------------------------------------------------------------------
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclsimpleeditor.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclsimpleeditor.tcl
new file mode 100755
index 0000000..51e8abb
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclsimpleeditor.tcl
@@ -0,0 +1,69 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxbrainregister.tcl,v 1.1 2002/02/20 18:07:50 Xenios Exp $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package require vtkpxcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+
+wm withdraw .
+set simpleviewer [ pxitclbaseimageviewer \#auto 0 ]
+$simpleviewer configure -appname "BioImage Suite::Simple Editor"
+$simpleviewer configure -show_standard_images 1
+$simpleviewer configure -enable_multisubjectcontrol 0
+$simpleviewer configure -enable_overlaytool 0
+$simpleviewer configure -enable_rendering_on_startup  0
+$simpleviewer configure -enable_talaraichoption 1
+$simpleviewer configure -enable_internaleditor 1
+$simpleviewer configure -enable_objectmapmenu   1
+$simpleviewer InitializeObjectmapMosaicViewer .[pxvtable::vnewobj ] 1
+
+
+set argc [llength $argv]
+
+if { $argc > 0 } {   $simpleviewer LoadImage [lindex $argv 0]   }
+
+
+set vr [ $simpleviewer GetViewer ]
+$simpleviewer ShowWindow
+$vr SetEnableRendering 1
+#after 100 "$vr UpdateDisplay"
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclsimpleviewer.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclsimpleviewer.tcl
new file mode 100755
index 0000000..000c160
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclsimpleviewer.tcl
@@ -0,0 +1,67 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxbrainregister.tcl,v 1.1 2002/02/20 18:07:50 Xenios Exp $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package require vtkpxcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+
+wm withdraw .
+set simpleviewer [ pxitclbaseimageviewer \#auto 0 ]
+$simpleviewer configure -appname "BioImage Suite::Simpleviewer"
+$simpleviewer configure -show_standard_images 1
+$simpleviewer configure -enable_multisubjectcontrol 0
+$simpleviewer configure -enable_overlaytool 0
+$simpleviewer configure -enable_rendering_on_startup  0
+$simpleviewer configure -enable_talaraichoption 1
+$simpleviewer InitializeMosaicViewer .[pxvtable::vnewobj ] 1
+
+
+set argc [llength $argv]
+
+if { $argc > 0 } {   $simpleviewer LoadImage [lindex $argv 0]   }
+
+
+set vr [ $simpleviewer GetViewer ]
+$simpleviewer ShowWindow
+$vr SetEnableRendering 1
+#after 100 "$vr UpdateDisplay"
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclsplineeditor.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclsplineeditor.tcl
new file mode 100755
index 0000000..5f890db
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclsplineeditor.tcl
@@ -0,0 +1,146 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclsplineeditor.tcl,v 1.2 2004/12/16 16:17:39 xenios Exp xenios $	
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package provide pxitclsplineeditor 1.0
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+package require pxtclutil 1.0
+package require vtkpxcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+package require pxitclsplineobjectmap 1.0
+
+# -----------------------------------------------------
+#  Intialize Variables
+# -----------------------------------------------------
+itcl::class pxitclsplineeditor {
+
+    inherit pxitclbaseimageviewer 
+
+    public    variable numberofsplines    5
+    protected variable objectmapcontrol   0 
+    public    variable gui_objectmapcontrol   0
+
+    constructor { par } {
+	::pxitclbaseimageviewer::constructor $par
+    } {
+	InitializeSplineEditor
+    }
+    
+    private method InitializeSplineEditor { }
+    public method SetImageFromObject { this obj } 
+    public method GetSpline { index } 
+    public method GetCurrentSlice { } 
+    
+    # Display Initialization 
+    public    method InitializeDisplay { widg standalone } 
+}
+# -----------------------------------------------------
+itcl::body pxitclsplineeditor::InitializeSplineEditor { } {
+
+    set appname "Spline Editor"
+
+    set vtk_viewer  [ vtkpxGUISplineEditor [ pxvtable::vnewobj ]]
+    set objectmapcontrol  [ [ pxitclsplineobjectmap \#auto $this ] GetThisPointer ]
+
+    set enable_headercontrol   1
+    set enable_landmarkcontrol 0
+    set enable_polydatacontrol 0
+    set enable_overlaytool     0
+}
+    
+# ---------------------------------------------------------------------------------
+#  GUI Stuff 
+# ---------------------------------------------------------------------------------
+itcl::body pxitclsplineeditor::GetSpline { index } {
+    return [ [ $vtk_viewer GetSplineControl ] GetSpline $index ]
+}
+
+itcl::body pxitclsplineeditor::GetCurrentSlice { } {
+    return [  $vtk_viewer GetBeginSlice ]
+}
+
+
+itcl::body pxitclsplineeditor::SetImageFromObject { img obj } {
+
+    set a [ pxitclbaseimageviewer::SetImageFromObject $img $obj ]
+    if { $a==0 } { return 0 }
+    
+    if { $vtk_viewer != 0 } {
+	$vtk_viewer SetImage [ $currentimage GetImage ] [ $currentimage GetOrientation ] 
+	$vtk_viewer SetSlice -1
+    }
+	
+}
+    
+# ---------------------------------------------------------------------------------
+#  Initialize Display Stuff
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclsplineeditor::InitializeDisplay { widg st } {
+    
+    if { $initialized == 1 } { return $basewidget }
+
+    $vtk_viewer SetNumberOfSplines $numberofsplines
+    set w [ InitializeInterface $widg $st ]
+    wm geometry $basewidget 800x850
+
+    set gui_objectmapcontrol [ $objectmapcontrol Initialize $widg.[pxvtable::vnewobj ] $this ]
+
+    #    menubutton $menubase.edit -text "Object Map"   -menu $menubase.edit.m -underline 0
+    set mb [ menu $menubase.editm -tearoff 0 ]
+    $menubase add cascade -label "Object Map" -menu $mb
+
+    #   pack $menubase.edit -side left
+    eval "$mb add command -label \"Object Map Control \" -command {  wm deiconify $gui_objectmapcontrol }"
+    #    $mb add separator
+    return $w
+}
+
+# ---------------------------------------------------------------------
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    wm withdraw .    
+    set imp [ pxitclsplineeditor \#auto 0 ] 
+    $imp InitializeDisplay .a 1
+    $imp ShowWindow
+    if { $argc > 0 } {  set ok [ $imp LoadImage [lindex $argv 0]  ] }
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclsplineobjectmap.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclsplineobjectmap.tcl
new file mode 100644
index 0000000..7a37130
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclsplineobjectmap.tcl
@@ -0,0 +1,155 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclsplineobjectmap.tcl,v 1.1 2003/03/03 20:17:28 papad Exp $	
+
+package provide pxitclsplineobjectmap 1.0
+
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  Iwidgets 4.0
+
+itcl::class pxitclsplineobjectmap {
+
+    inherit pxitclbaseimagecontrol
+
+    private common thisparam
+    protected variable splineeditor
+    protected variable numberofsplines
+
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } {
+    }
+
+    public method Initialize { widget splineeditor }
+    public method CreateObjectMap { }
+}
+
+
+itcl::body pxitclsplineobjectmap::Initialize { widget splineed } {
+	
+
+    set splineeditor $splineed
+    
+    if { $initialized == 1 } { return $basewidget }
+
+    set basewidget $widget
+    toplevel $basewidget -width 400 -height 250; wm withdraw $basewidget
+    wm geometry $basewidget 400x250
+
+
+    set numberofsplines [ $splineeditor cget -numberofsplines ]
+
+    for { set i 0 } { $i < $numberofsplines } { incr i } {
+	set thisparam($this,use_stack_$i) 0 
+	set thisparam($this,value_$i) [ expr $i + 1 ]
+    }
+	
+    set thisparam($this,use_stack_0) 1
+
+    set w [ frame $basewidget.top -bg darkgray -width 10 ]
+    pack $w -side top -expand t -fill both -padx 5 
+
+    for { set k 0 } { $k < $numberofsplines } { incr k } {
+	    
+	set wf [ frame $w.top$k ] ; pack $w.top$k -side top -fill both -expand t
+	set v "Use Stack [expr $k +1 ]"
+	set a "use_stack_$k"
+	set b "value_$k"
+	
+	eval "checkbutton $wf.c -variable [ itcl::scope thisparam($this,$a) ] -text \"$v\" "
+	label $wf.l -text "Object Map Value:" -width 15
+	eval  "entry $wf.t -textvariable [ itcl::scope thisparam($this,$b) ] -width 4 -relief sunken"
+	pack $wf.c $wf.l $wf.t -padx 10 -side left -expand f -fill x
+    }
+	
+    frame $w.com; 
+    pack $w.com -side top -fill x
+    eval "button $w.com.b1 -text Create! -command { $this CreateObjectMap  } "
+    eval "button $w.com.b3 -text Close -command {  wm withdraw $basewidget }"
+    pack $w.com.b1  $w.com.b3 -side left -fill x -expand t   
+
+    set initialized 1
+    SetTitle "Spline Object-map Control"
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget 
+    
+    
+}
+
+
+itcl::body pxitclsplineobjectmap::CreateObjectMap { } {
+
+    set current_image [ $splineeditor cget -currentimage ]
+    set level [ $splineeditor GetCurrentSlice ]
+
+    if { [ $current_image GetImageSize ] <1 } {
+	::pxtclutil::Warning "No Image in Memory\n Cannot Generate Spline Object Map!"
+	return  0
+    }
+	
+    WatchOn	
+    set sc [ vtkImageShiftScale [ pxvtable::vnewobj ]]
+    $sc SetInput [ $current_image GetImage ] 
+    $sc SetShift 0
+    $sc SetScale 0
+    $sc Update
+    $currentresults ShallowCopyImage [ $sc GetOutput ]
+    $sc Delete 
+
+    $currentresults CopyImageHeader [ $current_image GetImageHeader ]
+    $currentresults configure -filename    "spline_objectmap.hdr"
+    set tmp_image [ $currentresults GetImage ]
+
+    for { set i 0 } { $i < $numberofsplines } { incr i } {
+	if { $thisparam($this,use_stack_$i) > 0 } {
+	    set val $thisparam($this,value_$i) 
+	    set stack [ $splineeditor GetSpline $i ]
+	    $stack AddToObjectMap  $tmp_image $level $val 1
+	    $splineeditor ShowProgressVal "Added [expr $i+1 ]" [ expr (1+ $i )/($numberofsplines +0.01)]
+	}
+    }
+
+    $splineeditor ShowProgressVal "Done" "1.0"
+    $splineeditor SetResultsFromObject $currentresults  $this 
+    WatchOff
+    return 1
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclsplinestackobjectmap.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclsplinestackobjectmap.tcl
new file mode 100644
index 0000000..41d51a9
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclsplinestackobjectmap.tcl
@@ -0,0 +1,272 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclsplinestackobjectmap.tcl,v 1.2 2004/02/03 15:57:52 xenios Exp xenios $	
+
+package provide pxitclsplinestackobjectmap 1.0
+
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  Iwidgets 4.0
+
+itcl::class pxitclsplinestackobjectmap {
+
+    inherit pxitclbaseimagecontrol
+
+    private common thisparam
+    protected variable surfaceeditor
+    protected variable numberofsurfaces
+
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } {
+    }
+
+    public method Initialize { widget surfaceeditor }
+    public method CreateObjectMap { }
+    public method CreateDistanceMap { }
+    public method MaskImage       { mode }
+}
+
+
+itcl::body pxitclsplinestackobjectmap::Initialize { widget surfaceed } {
+	
+
+    set surfaceeditor $surfaceed
+    
+    if { $initialized == 1 } { return $basewidget }
+
+    set basewidget $widget
+    toplevel $basewidget -width 400 -height 250; wm withdraw $basewidget
+    wm geometry $basewidget 400x250
+
+
+    set numberofsurfaces [ $surfaceeditor cget -numberofsurfaces ]
+
+    for { set i 0 } { $i < $numberofsurfaces } { incr i } {
+	set thisparam($this,use_stack_$i) 0 
+	set thisparam($this,value_$i) [ expr $i + 1 ]
+    }
+    set thisparam($this,baselevel) 0
+    set thisparam($this,use_stack_0) 1
+
+    set w [ frame $basewidget.top -bg darkgray -width 10 ]
+    pack $w -side top -expand t -fill both -padx 5 
+
+    set wf [ frame $w.topbase ] ; pack $w.topbase -side top -fill both -expand t
+    label $wf.l -text "Background Value:" -width 20
+    eval "entry $wf.t -textvariable [ itcl::scope thisparam($this,baselevel) ] -width 4 -relief sunken"
+    pack $wf.l $wf.t -padx 10 -side left -expand f -fill x
+
+
+    for { set k 0 } { $k < $numberofsurfaces } { incr k } {
+	    
+	set wf [ frame $w.top$k ] ; pack $w.top$k -side top -fill both -expand t
+	set v "Use Stack [expr $k +1 ]"
+	set a "use_stack_$k"
+	set b "value_$k"
+	
+	eval "checkbutton $wf.c -variable [ itcl::scope thisparam($this,$a) ] -text \"$v\" "
+	label $wf.l -text "Object Map Value:" -width 15
+	eval  "entry $wf.t -textvariable [ itcl::scope thisparam($this,$b) ] -width 4 -relief sunken"
+	pack $wf.c $wf.l $wf.t -padx 10 -side left -expand f -fill x
+    }
+	
+    frame $w.com; 
+    pack $w.com -side top -fill x
+    eval "button $w.com.b1 -text Create! -command { $this CreateObjectMap  } "
+    eval "button $w.com.b1b -text DistanceMap! -command { $this CreateDistanceMap  } "
+    eval "button $w.com.b2 -text \"Mask\" -command { $this MaskImage 0  } "
+    eval "button $w.com.b2b -text \"Inverse\" -command { $this MaskImage 1  } "
+    eval "button $w.com.b3 -text Close -command {  wm withdraw $basewidget }"
+    pack $w.com.b1 $w.com.b1b $w.com.b2 $w.com.b2b $w.com.b3 -side left -fill x -expand t   
+
+    set initialized 1
+    SetTitle "Surface Object-map Control"
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget 
+    
+    
+}
+
+
+itcl::body pxitclsplinestackobjectmap::MaskImage { mode } {
+
+    set ok [ $this CreateObjectMap ]
+    if { $ok == 0 } {
+	return 0
+    }
+
+
+    WatchOn
+
+    set sc  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+    $sc SetInput  [ $currentresults GetImage ]
+    $sc ThresholdBetween -0.5 0.5
+    $sc ReplaceOutOn
+    $sc ReplaceInOn
+    if { $mode > 0 } {
+	$sc SetInValue  1
+	$sc SetOutValue 0
+    } else {
+	$sc SetInValue  0
+	$sc SetOutValue 1
+    }
+    $sc Update
+    $currentresults ShallowCopyImage [ $sc GetOutput ]
+    $sc Delete
+
+    set current_mask  [ $currentresults GetImage ]
+    set current_image [ [ $surfaceeditor cget -currentimage ] GetImage ]    
+
+    set ct1 [ vtkImageCast [ pxvtable::vnewobj ] ]
+    set ct2 [ vtkImageCast [ pxvtable::vnewobj ] ]
+    $ct1 SetOutputScalarTypeToShort
+    $ct2 SetOutputScalarTypeToShort
+    $ct1 SetInput $current_image
+    $ct2 SetInput $current_mask
+
+    set mask  [  vtkImageMathematics [ pxvtable::vnewobj ] ]
+    $mask SetInput1 [ $ct1 GetOutput ]
+    $mask SetInput2 [ $ct2 GetOutput ]
+    $mask SetOperationToMultiply
+    SetFilterCallbacks $mask  "Mask x Image"
+    $mask Update
+    
+    $currentresults ShallowCopyImage [ $mask GetOutput ]
+
+    $mask Delete
+    $ct1 Delete
+    $ct2 Delete
+
+    $surfaceeditor SetResultsFromObject $currentresults  $this 
+    
+    WatchOff 
+    
+    return 1
+
+}    
+
+itcl::body pxitclsplinestackobjectmap::CreateObjectMap { } {
+
+    set current_image [ $surfaceeditor cget -currentimage ]
+    
+    if { [ $current_image GetImageSize ] <1 } {
+	::pxtclutil::Warning "No Image in Memory\n Cannot Generate Surface Object Map!"
+	return  0
+    }
+	
+    WatchOn	
+    puts stdout "Baselevel = $thisparam($this,baselevel)"
+
+    set sc  [  vtkImageThreshold [ pxvtable::vnewobj ] ]
+    $sc SetInput [ $current_image GetImage ] 
+    $sc ThresholdBetween 0 1
+    $sc ReplaceOutOn
+    $sc ReplaceInOn
+    $sc SetInValue  $thisparam($this,baselevel)
+    $sc SetOutValue  $thisparam($this,baselevel)
+    $sc Update
+    $currentresults ShallowCopyImage [ $sc GetOutput ]
+    $sc Delete 
+
+    $currentresults CopyImageHeader [ $current_image GetImageHeader ]
+    $currentresults configure -filename    "surface_objectmap.hdr"
+    set tmp_image [ $currentresults GetImage ]
+
+    for { set i 0 } { $i < $numberofsurfaces } { incr i } {
+	if { $thisparam($this,use_stack_$i) > 0 } {
+	    set val $thisparam($this,value_$i) 
+	    puts stdout "Using Surface $i val=$val"
+	    set stack [ $surfaceeditor GetSurface $i ]
+	    $stack AddToObjectMap $tmp_image $val 1 $thisparam($this,baselevel)
+	    $surfaceeditor ShowProgressVal "Added [expr $i+1 ]" [ expr (1+ $i )/($numberofsurfaces +0.01)]
+	}
+    }
+    
+    $surfaceeditor ShowProgressVal "Done" "1.0"
+    $surfaceeditor SetResultsFromObject $currentresults  $this 
+    WatchOff
+    return 1
+}
+
+
+itcl::body pxitclsplinestackobjectmap::CreateDistanceMap { } {
+
+    set current_image [ $surfaceeditor cget -currentimage ]
+    
+    if { [ $current_image GetImageSize ] <1 } {
+	::pxtclutil::Warning "No Image in Memory\n Cannot Generate Surface Distance Map!"
+	return  0
+    }
+	
+
+    set sur -1
+    for { set i 0 } { $i < $numberofsurfaces } { incr i } {
+	if { $thisparam($this,use_stack_$i) > 0 } {
+	    set sur $i
+	    set i [ expr $numberofsurfaces + 1 ]
+	}
+    }
+
+    if { $sur == - 1 } {
+	::pxtclutil::Warning "No Surface Selected from which to create distance map\n"
+	return  0
+    }
+	
+    
+    WatchOn	
+
+    set img [ $currentresults GetImage ]
+    $img CopyStructure [ $current_image GetImage ]
+    $img SetScalarTypeToShort
+    $img SetNumberOfScalarComponents 1
+    $img AllocateScalars
+    
+    $currentresults CopyImageHeader [ $current_image GetImageHeader ]
+    $currentresults configure -filename    "surface_distancemap.hdr"
+    
+    set stack [ $surfaceeditor GetSurface $sur ]
+    $stack FillDistanceMap $img
+    $surfaceeditor ShowProgressVal "Done" "1.0"
+    $surfaceeditor SetResultsFromObject $currentresults  $this 
+    WatchOff
+    return 1
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclsubjectentry.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclsubjectentry.tcl
new file mode 100644
index 0000000..b0fc333
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclsubjectentry.tcl
@@ -0,0 +1,409 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclsubjectentry 1.0
+
+# 	$Id: pxitclsubjectentry.tcl,v 1.1 2002/06/11 01:21:41 papad Exp papad $	
+
+
+
+
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxvtable   1.0
+package require  vtkpxcontrib 1.1
+package require  pxitclbasecontrol 1.0
+
+
+# ---------------------------------------------------------------------------
+#  Ancilliary Class pxitclsubject
+# ---------------------------------------------------------------------------
+itcl::class pxitclsubject {
+
+    public    variable anatomical_image  0
+    public    variable conventional_image  0
+    public    variable functional_image 0
+    public    variable echoplanar_image 0
+    public    variable fieldmap_image 0
+    public    variable reference_transform 0
+    public    variable internal_transform 0
+    public    variable distortion_transform 0
+    public    common   util 0
+    public    variable subject_id ""
+
+    constructor { } {
+	set anatomical_image      [  [ pxitclimage \#auto ] GetThisPointer ]
+	set conventional_image    [  [ pxitclimage \#auto ] GetThisPointer ]
+	set functional_image       [  [ pxitclimage \#auto ] GetThisPointer ]
+	set echoplanar_image       [  [ pxitclimage \#auto ] GetThisPointer ]
+	set fieldmap_image       [  [ pxitclimage \#auto ] GetThisPointer ]
+	
+	set internal_transform  [ [ pxitcltransform \#auto ] GetThisPointer ]
+	set reference_transform [ [ pxitcltransform \#auto ] GetThisPointer ]
+	set distortion_transform [ [ pxitcltransform \#auto ] GetThisPointer ]
+
+	if { $util == 0 } { set util [ vtkpxUtil [ pxvtable::vnewobj ]] }
+    }
+
+    destructor  { 
+
+	catch { delete object $anatomical_image }
+	catch { delete object $conventional_image }
+	catch { delete object $functional_image }
+	catch { delete object $echoplanar_image }
+	catch { delete object $fieldmap_image }
+
+	catch { delete object $internal_transform }
+	catch { delete object $reference_transform }
+	catch { delete object $distortion_transform }
+    }
+
+    public method  GetThisPointer  { } { return $this }
+    public method  GetDescription { }
+    public method  RenameFunctional { oldsuffix newsuffix }
+
+    public proc    GetFileElement { fileid }
+    public method  LoadFromSetupFile { fileid { mode 0 } }
+    public method  SaveToSetupFile   { fileid }
+    public method  SaveToDirectory   { newdir { keepnewfunctionalname 1 } { notfunctionalonly 0  } }
+
+
+
+
+    public method  GetBaseName {  }
+    public method  GetNameList {  }
+
+    public method  UnloadImages { } 
+}
+
+
+# ---------------------------------------------------------------------------
+# Get Description
+# ---------------------------------------------------------------------------
+itcl::body pxitclsubject::GetDescription {  } {
+
+    set name [ $anatomical_image cget -filename ]
+    set len [ string length $name ]
+    if { [ $len > 40 ] } {
+	set name [ string range $name [ expr $len - 40 ] [ expr $len -1 ] ]
+    }
+    
+    set desc [ format "%40s : A %12s C %12s F %12s TR %10s TI %10s" $name [ $anatomical_image cget -status ] [ $conventional_image cget - status ] [ $functional_image cget -status ] [ $reference_transform GetClassName ] [ $internal_transform GetClassName ]]
+    return $desc
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclsubject::RenameFunctional { oldsuffix newsuffix } {
+
+    set f [ $functional_image cget -filename ]
+    $functional_image UnLoad
+    set ind [ string last $oldsuffix $f ]
+    if { $ind >=0 } {
+	regsub -start $ind $oldsuffix $f $newsuffix thisparam(${nm}filename)
+	$functional_image configure -filename $f
+	return 1
+    }
+    return 0
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclsubject::UnloadImages { }  {
+
+    set imlist [ list $anatomical_image $conventional_image $functional_image $echoplanar_image $fieldmap_image]
+    for { set i 0 } { $i<=2 } { incr i } {
+	set img [ lindex $imlist $i]
+	set  f [ $img cget -filename ]
+	$img UnLoad
+	$img configure -filename $f
+    }
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclsubject::GetFileElement { fileid } {
+
+    gets $fileid line 
+    set index [string first ":" $line]
+    if { $index > 0 }  {
+	set len   [string length $line]
+	set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+	return $value
+    }
+    return ""
+}
+
+itcl::body pxitclsubject::LoadFromSetupFile { fileid {mode 0} } {
+
+    UnloadImages
+    $reference_transform Clear
+    $internal_transform Clear
+    $distortion_transform Clear
+    if { $mode > 1 } {
+	set subject_id [ GetFileElement $fileid ]
+    }
+    $anatomical_image configure -filename [ GetFileElement $fileid ]
+    $conventional_image configure -filename [ GetFileElement $fileid ]
+    $functional_image configure -filename [ GetFileElement $fileid ]
+    $reference_transform configure -filename [ GetFileElement $fileid ]
+    $internal_transform configure -filename [ GetFileElement $fileid ]
+    if { $mode > 0 } {
+	$echoplanar_image configure -filename [ GetFileElement $fileid ]
+	$distortion_transform configure -filename [ GetFileElement $fileid ]
+	$fieldmap_image configure -filename [ GetFileElement $fileid ]
+    }
+    gets $fileid line
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclsubject::SaveToDirectory   { newdir { keepnewfunctionalname 1 } { notfunctionalonly 0 }  } {
+
+
+    if { $notfunctionalonly > 0 } {
+	set itlist [ list $functional_image $anatomical_image  $conventional_image    $reference_transform  $internal_transform  $echoplanar_image  $distortion_transform  $fieldmap_image ]
+    } else {
+	set itlist [ list $functional_image ]
+    }
+
+    for { set i 0 } { $i < [ llength $itlist ] } { incr i } {
+	set obj [ lindex $itlist $i ]
+	set fn [ $obj cget -filename ]
+	if { [ string length $fn ] > 1 } {
+	    set newname [ file join $newdir [ file tail $fn ]]
+	    $obj configure -filename $newname
+	    $obj Save
+	    pxtkprint "Mapping $fn --> $newname\n"
+	    if { $keepnewfunctionalname == 0 && $i == 0 } {
+		# Restore functional name back so that it can be renamed for next task
+		$obj configure -filename $fn
+	    }
+	}
+    }
+}
+
+# ---------------------------------------------------------------------------
+itcl::body pxitclsubject::SaveToSetupFile   { fileid } {
+
+    puts $fileid "Subject Id : $subject_id"
+    puts $fileid "Anatomical Image : [ $anatomical_image cget -filename ]"
+    puts $fileid "Conventional Image : [ $conventional_image cget -filename ]"
+    puts $fileid "Functional Image : [ $functional_image cget -filename ]"
+    puts $fileid "Reference Transformation : [ $reference_transform cget -filename ]"
+    puts $fileid "Internal Transformation :  [ $internal_transform cget -filename ]"
+    puts $fileid "Echoplanar Image : [ $echoplanar_image cget -filename ]"
+    puts $fileid "Distortion Transformation :  [ $distortion_transform cget -filename ]"
+    puts $fileid "Fieldmap Image : [ $fieldmap_image cget -filename ]"
+    puts $fileid "-------------------------------------------------------"
+}
+
+# ---------------------------------------------------------------------------
+itcl::body pxitclsubject::GetBaseName {  } {
+
+    set b [ $anatomical_image cget -filename ]
+    if { [ string length $b ] < 1 } {
+	set b "New_Subject"
+    }
+
+    set out [ file root [ file tail $b ] ]
+
+    if { $subject_id == "" } {
+	return  $out
+    } 
+    return ${subject_id}
+}
+
+itcl::body pxitclsubject::GetNameList {  } {
+
+    set rlist "" 
+    lappend rlist [ list $this.1  "Anat:[ file tail [ $anatomical_image cget -filename ]]" ] 
+    lappend rlist [ list $this.2  "Conv:[ file tail [ $conventional_image cget -filename ]]" ]
+    lappend rlist [ list $this.3  "Func:[ file tail [ $functional_image cget -filename ]]" ]
+    lappend rlist [ list $this.4  "RefX:[ file tail [ $reference_transform cget -filename]]" ]
+    lappend rlist [ list $this.5  "IntX:[ file tail [ $internal_transform cget -filename]]"  ]
+    lappend rlist [ list $this.6  "EPIm:[ file tail [ $echoplanar_image cget -filename]]"  ]
+    lappend rlist [ list $this.7  "DistX:[ file tail [ $distortion_transform cget -filename]]"  ]
+    lappend rlist [ list $this.8  "Fldmp:[ file tail [ $fieldmap_image cget -filename]]"  ]
+    return $rlist
+}
+# ---------------------------------------------------------------------------
+#
+#
+#
+#                     pxitcltask
+#
+#
+#
+# ---------------------------------------------------------------------------
+#  Ancilliary Class pxitclsubject
+# ---------------------------------------------------------------------------
+itcl::class pxitcltask {
+
+    public    variable   task_name ""
+    public    variable   task_suffix ""
+
+    constructor { } {
+    }
+
+    public method  LoadFromSetupFile { fileid }
+    public method  SaveToSetupFile   { fileid }
+    public method  GetThisPointer { } { return $this }
+    public method  GetDescription { } { return "Task : $task_name\nSuffix=$task_suffix\n"}
+    public method  GetBaseName {  }
+    public method  GetNameList {  }
+
+
+
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitcltask::LoadFromSetupFile { fileid } {
+
+
+    set task_name [ pxitclsubject::GetFileElement $fileid ]
+    set task_suffix [ pxitclsubject::GetFileElement $fileid ]
+    gets $fileid line
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitcltask::SaveToSetupFile   { fileid } {
+
+    puts $fileid "Task Name   : $task_name"
+    puts $fileid "Task Suffix : $task_suffix"
+    puts $fileid "-------------------------------------------------------"
+}
+
+itcl::body pxitcltask::GetBaseName {  } {
+    set b $task_name 
+    if { [ string length $task_name ] < 1 } {
+	set b "New_Task"
+    }
+    return $b
+}
+
+itcl::body pxitcltask::GetNameList {  } {
+    set rlist ""
+    lappend rlist  [ list $this.1 "Suffix: $task_suffix" ]
+    return $rlist
+}
+
+
+# -------------------------------------------------------------------------------------
+#
+#
+#
+#         task GUI stuff
+#
+#
+# -------------------------------------------------------------------------------------
+
+itcl::class pxitcltaskGUI {
+
+    public    variable  itcl_task 0
+    protected variable  basewidget  0
+    protected variable  initialized 0
+    private   common    thisparam
+    protected variable  owns_task 1
+    public variable     description "Task"
+    public variable     callback 0
+
+    constructor { } {
+	Reset
+    }
+
+    destructor {
+	if { $owns_task == 1} {
+	    catch { itcl::delete object $itcl_task }
+	}
+    }
+
+    public    method GetThisPointer { } { return $this }
+    public    method GetTask { } { return $itcl_task  }
+    public    method SetTask { task }
+    public    method Reset { } 
+    public    method Initialize { basewidg } 
+    public    method Update { }
+    public    method UpdateEntry { }
+}
+# ----------------------------------------------------------
+itcl::body pxitcltaskGUI::Reset { } {
+
+    if { $itcl_task !=0 && $owns_task == 1} {
+	itcl::delete object $itcl_task
+    }
+    
+    set itcl_task  [ [  pxitcltask \#auto ] GetThisPointer ]
+    set owns_task 1
+    Update
+}
+
+itcl::body pxitcltaskGUI::Update { } {
+    
+    set thisparam($this,name)        [ $itcl_task cget -task_suffix ]
+    set thisparam($this,description) [ $itcl_task cget -task_name ]
+}
+
+itcl::body pxitcltaskGUI::UpdateEntry { } {
+    
+    $itcl_task configure -task_name $thisparam($this,description)
+    $itcl_task configure -task_suffix $thisparam($this,name)
+    if { $callback !=0 } {
+	eval $callback
+    }
+}
+
+
+itcl::body pxitcltaskGUI::SetTask { trn } {
+    
+    if { [ $trn isa pxitcltask ] == 0 } {
+	return 0
+    }
+	
+    if { $owns_task == 1} {
+	catch { itcl::delete object $itcl_task }
+    }
+
+    set itcl_task $trn
+    set owns_task 0
+    Update
+}
+
+itcl::body pxitcltaskGUI::Initialize { basewidg } {
+
+    if { $initialized == 1 } { return $basewidget }
+    
+    set basewidget [  iwidgets::Labeledframe $basewidg -labelpos n -labeltext $description ]
+    set base [ $basewidget childsite ]
+    frame $base.mid
+
+    iwidgets::entryfield $base.0 -labeltext "Task Description:"  -width 30  -textvariable [ itcl::scope thisparam($this,description) ] -relief sunken 
+    iwidgets::entryfield $base.1 -labeltext "Task Suffix:"  -width 10  -textvariable [ itcl::scope thisparam($this,name) ] -relief sunken 
+    pack $base.0 $base.1 -side top -expand f -fill x
+
+    set w [ frame $base.bot ]
+    eval "button $w.upd -text Update -command {  $this UpdateEntry }"
+    pack  $w.upd  -side left -fill x -expand f
+    pack  $base.0 $base.1 $base.bot -side top -expand f -fill x -padx 5
+    set initialized 1
+    Update
+
+    return $basewidget
+}
+# ----------------------------------------------------------
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclsurfaceeditor.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclsurfaceeditor.tcl
new file mode 100755
index 0000000..4c41626
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclsurfaceeditor.tcl
@@ -0,0 +1,558 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclsurfaceeditor.tcl,v 1.3 2003/09/03 13:59:52 xenios Exp xenios $	
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package provide pxitclsurfaceeditor 1.0
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+package require pxtclutil 1.0
+package require vtkpxcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+package require pxitclsplinestackobjectmap 1.0
+
+# -----------------------------------------------------
+#  Intialize Variables
+# -----------------------------------------------------
+itcl::class pxitclsurfaceeditor {
+
+    inherit pxitclbaseimageviewer 
+
+    protected variable splinestackcontrol 0
+    protected variable splineobjectmapeditor       0 
+    protected variable surfaceobjectmapcontrol   0 
+    public    variable gui_splineobjectmapeditor   0
+    public    variable gui_surfaceobjectmapcontrol   0
+    public    variable numberofsurfaces   4
+    public    variable objectmapname "objectmap.hdr"
+    public    variable gui_fatobjectmap 0
+    public    variable gui_saraobjectmap 0
+    protected variable simpleviewer 0
+
+    constructor { par } {
+	::pxitclbaseimageviewer::constructor $par
+    } {
+	InitializeSurfaceEditor
+    }
+    
+    private method InitializeSurfaceEditor { }
+    public method SetImageFromObject { this obj } 
+    
+    # Display Initialization 
+    protected method InitializeViewer  {  } 
+    public    method InitializeDisplay { widg standalone } 
+
+
+    # Get Surface from Spline Stack Control
+    public    method GetSurface       { index } 
+    public    method GetSplineStackControl { } { return splinestackcontrol }
+    # Objectmap Stuff
+    public method LoadImage { f } 
+    public method GrabObjectmap  { }
+    public method SendToMorphologyMask { }
+    public method ObjectmapSurfaceFatCompute { mode }
+    public method ObjectmapHelp { }
+
+    public method SaraObjectmapCompute { mode }
+    public method SaraObjectmapHelp { }
+
+    public method ObjectmapSimpleViewer { mode } 
+
+}
+# -----------------------------------------------------
+itcl::body pxitclsurfaceeditor::InitializeSurfaceEditor { } {
+
+    set appname "BioImage Suite::Surface Editor"
+    global pxtcl_pref_array
+
+    set splinestackcontrol [ vtkpxGUIObjectmapSplineStackControl [ pxvtable::vnewobj ]]
+    set splineobjectmapeditor  [ vtkpxGUI2DSplineObjectmapViewer [ pxvtable::vnewobj ]]
+
+    set surfaceobjectmapcontrol  [ [ pxitclsplinestackobjectmap \#auto $this ] GetThisPointer ]
+    set numberofsurfaces 4
+    catch { 
+	#	puts stdout "$pxtcl_pref_array(SurfaceEditorMaxSurfaces) , $pxtcl_pref_array(SplineEditorControlPointScale)"
+	set numberofsurfaces $pxtcl_pref_array(SurfaceEditorMaxSurfaces) 
+	set defaultscale     $pxtcl_pref_array(SplineEditorControlPointScale)
+	if { $numberofsurfaces > 50 } {
+	    set numberofsurfaces 45
+	}
+	$splinestackcontrol SetNumberOfSplineStacks $numberofsurfaces
+	$splineobjectmapeditor    SetNumberOfSplines      $numberofsurfaces
+	$splineobjectmapeditor    SetDefaultScaleMode     $defaultscale
+
+    }
+
+    if { $normalize_anatomical  == 1 } {
+	$splineobjectmapeditor SetPresetLookupTableMode 0
+    } else {
+	$splineobjectmapeditor SetPresetLookupTableMode -1
+    }
+    $splinestackcontrol SetSplineEditor $splineobjectmapeditor
+
+    set enable_headercontrol   1
+    set enable_polydatacontrol 1
+    set enable_overlaytool     0
+    set enable_objectmapmenu   1
+
+    set thisparam($this,helpdialog) ""
+    set thisparam($this,autosave) 0
+    set can_accept_mask 0
+
+}
+
+    
+# ---------------------------------------------------------------------------------
+#  GUI Stuff 
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclsurfaceeditor::SetImageFromObject { img obj } {
+
+    set a [ pxitclbaseimageviewer::SetImageFromObject $img $obj ]
+    if { $a==0 } { 
+	return 0 
+    }
+    
+    if { $splinestackcontrol != 0 } {
+	$splineobjectmapeditor    LinkLookupTable [ $vtk_viewer GetLookupTable ]
+	$splinestackcontrol SetImage [ $currentimage GetImage ] [ $currentimage GetOrientation ] 0 0
+    }
+}
+    
+# ---------------------------------------------------------------------------------
+#  Update Stuff -- for change frame communication between image and splinestack
+# ---------------------------------------------------------------------------------
+itcl::body pxitclsurfaceeditor::GetSurface { index } {
+    return [ $splinestackcontrol GetSplineStack $index ]
+}
+
+itcl::body pxitclsurfaceeditor::InitializeViewer {  } {
+
+
+
+    if { $vtk_viewer ==0 } { return }
+
+    set tframe [ frame $viewerbase.top ]
+    set bframe [ frame $viewerbase.bot ]
+    pack $bframe -side bottom -expand false -fill x
+    pack $tframe -side top -expand true -fill both
+
+    set masterframe [ frame  $bframe.[pxvtable::vnewobj ] -relief raised]
+    set masterframe2 [ frame $bframe.[pxvtable::vnewobj ] ]
+    set masterframe3 [ frame $bframe.[pxvtable::vnewobj ] ]
+    $masterframe2 configure -height 3 -bg black
+    $masterframe3 configure -height 3 -bg black
+    pack $masterframe3 $masterframe $masterframe2 -side bottom -expand f -fill x
+
+    set vframe [ frame $tframe.left ]
+    set note $tframe.notebook
+    iwidgets::tabnotebook $note -tabpos n
+    pack $note -side right -expand f -fill y
+    pack $vframe -side left -expand true -fill both
+
+    set cframe [ $note add -label "Image" ] 
+    set dframe [ $note add -label "Surface" ] 
+    set eframe [ $note add -label "Surface +" ] 
+
+    $note view "Surface"
+
+
+
+    
+
+    set vr [ $vtk_viewer Initialize $vframe $cframe 1 ]
+
+    $splinestackcontrol SetBaseViewer $vtk_viewer
+    set ct [ $splinestackcontrol Initialize $dframe $eframe $masterframe 1 ]
+
+
+
+
+    set gui_splineobjectmapeditor [ $splineobjectmapeditor Initialize $viewerbase 0 ]
+    wm title $gui_splineobjectmapeditor "Objectmap/Spline Editor"
+    wm geometry $gui_splineobjectmapeditor 700x600
+
+    # SetControlsViewer $vtk_viewer $splinestackcontrol
+    $splinestackcontrol SetRenderer [ [ $vtk_viewer GetRenderer 3 ] GetRenderer ] 0 0
+    $splinestackcontrol SetRenderer [ [ $vtk_viewer GetRenderer 0 ] GetRenderer ] 1 1
+    $splinestackcontrol SetRenderer [ [ $vtk_viewer GetRenderer 1 ] GetRenderer ] 2 1
+    $splinestackcontrol SetRenderer [ [ $vtk_viewer GetRenderer 2 ] GetRenderer ] 3 1
+
+    if { $bind_mouse_events == 1 } {
+	$vtk_viewer BindMouseEvents [ $vtk_viewer GetRenderWidgetName ] "$this HandleMouseEvent" "" 
+    }
+}
+
+# ---------------------------------------------------------------------------------
+#  Objectmap GUI
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclsurfaceeditor::LoadImage { f } {
+
+    set a [ pxitclbaseimageviewer::LoadImage $f ]
+    if { $a > 0 } {
+	$this ClearObjectmap
+    }
+}
+    
+ 
+itcl::body pxitclsurfaceeditor::GrabObjectmap  { } {
+
+    set transp [ $splineobjectmapeditor  GetObjectmapTransparency ]
+    $splineobjectmapeditor SetObjectmapTransparency 0
+    
+    set mask [ $splineobjectmapeditor GetMaskImage ]
+    set ok [ $this QuestionReplaceObjectmap $mask "Grab Objectmap from current view. This will erase the current objectmap. Are you sure?" ]
+
+    if { $ok == 1 } {
+	set img [ GetDisplayedImage ]
+
+	$splineobjectmapeditor SetMaskImage [ $img GetImage ] [ $img GetOrientation ]
+
+	pxtclutil::Warning "Setting autosave to off, please enable if this is desired"
+	set thisparam($this,autosave) 0
+	$splineobjectmapeditor SetObjectmapTransparency $transp
+	$this ShowImage Image
+    } else {
+	$splineobjectmapeditor SetObjectmapTransparency $transp
+    }
+}
+
+itcl::body pxitclsurfaceeditor::SendToMorphologyMask { } {
+
+    if { $brainstriptool == 0 } {
+	return 
+    }
+
+    WatchOn
+    $brainstriptool SetMorphologyMaskImage  [ $splineobjectmapeditor GetMaskImage ]
+    WatchOff
+
+}
+
+itcl::body pxitclsurfaceeditor::ObjectmapHelp { } {
+
+    if { [ string length $thisparam($this,helpdialog) ] > 2 } { 
+	::pxtclutil::ShowWindow $thisparam($this,helpdialog)
+	return
+    }
+    
+    set w ""
+    if { [ string length $basewidget ] > 2 } { set w $basewidget }
+    
+    set thisparam($this,helpdialog)  [ toplevel $w.helpdialog ]
+    eval "wm protocol $w.hdelpdialog WM_DELETE_WINDOW { wm withdraw $w.helpdialog }"
+    
+    ::pxtclhelp::HelpDialog $thisparam($this,helpdialog)
+    wm title $thisparam($this,helpdialog) "Help on Objectmaps"
+    
+    set line "An objectmap is a binary representation of different objects taking range 0-9. These can be either manually created using\n\n"
+    set line "$line 1. The Spline/Objectmap Editor -- directly editing either with brush tools or filling splines. "
+    set line "$line (The objectmap editor can also be used to edit the appearance of the objectmap in terms of the colors assigned to each value)\n\n"
+    set line "$line 2. The \"Create from Surfaces\" option above to fill in 3D for the whole surface. This will produce a temporary image which then is stored in the actual objectmap using the \"Grab from Current Displayed Image\" option\n\n"
+    set line "$line 3. The Segmentation tool. The output of anyo of these operations
+ greats a temporary objectmap which is only made permanent when the the \"Grab from Current Displayed Image\" option is invoked \n\n"
+    set line "$line Additional processing to the objectmap can be made by sending it to the math_morphology tool using the option \"Store in Morphology Mask\" in this menu.\n\n"
+    set line "$line Naturally objectmaps can be loaded, saved and reinitialized using options in these menu (\"New Objectmap\", \"Load Objectmap\", \"Save Objectmap\")\n\n"
+    set line "$line Further the current objectmap is autosaved every 2 minutes when the \"Autosave\" checkbox on this menu is enabled\n"
+
+    ::pxtclhelp::HelpDialogAddText $thisparam($this,helpdialog) $line
+
+    wm  geometry $thisparam($this,helpdialog) 680x600
+    ::pxtclutil::ShowWindow $thisparam($this,helpdialog)
+}
+
+
+itcl::body pxitclsurfaceeditor::ObjectmapSurfaceFatCompute { mode } {
+
+    if { $mode == 0 } {
+	if { $gui_fatobjectmap == 0 } {
+	    set gui_fatobjectmap  $basewidget.[ pxvtable::vnewobj ]
+	    set w $gui_fatobjectmap
+
+	    toplevel $w -width 400 -height 250
+	    wm title $w "Fat Computation"
+	    frame $w.bot; 	    pack $w.bot -side bottom -expand f -fill x
+
+	    set thisparam($this,fat_visc) 3
+	    set thisparam($this,fat_artf) 8
+	    set thisparam($this,fat_subq) 2
+	    set thisparam($this,fat_abdsurface) 1
+	    set thisparam($this,fat_numclasses) 4
+
+	    iwidgets::entryfield $w.1 -labeltext "Visceral Fat Value:"  -width 3 -validate integer -textvariable [ itcl::scope thisparam($this,fat_visc) ] -relief sunken 
+	    iwidgets::entryfield $w.2 -labeltext "Artifact Value:"  -width 3 -validate integer -textvariable [ itcl::scope thisparam($this,fat_artf) ] -relief sunken 
+	    iwidgets::entryfield $w.3 -labeltext "Abdominal Surface Index:"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,fat_abdsurface) ] -relief sunken 
+	    iwidgets::entryfield $w.4 -labeltext "Subcutaneous Fat (Output) Value:"  -width 3 -validate integer -textvariable [ itcl::scope thisparam($this,fat_subq) ] -relief sunken 
+	    iwidgets::entryfield $w.5 -labeltext "Num Classes:"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,fat_numclasses) ] -relief sunken 
+	    pack $w.1 $w.2 $w.3 $w.4 $w.5 -side top -expand true -fill x
+
+	    eval "button $w.bot.c -text Close   -command {  wm withdraw $w }"
+	    eval "button $w.bot.b -text Compute -command { $this ObjectmapSurfaceFatCompute 1 } "
+	    pack $w.bot.c $w.bot.b -side left -padx 5
+	} else {
+	    wm deiconify $gui_fatobjectmap
+	    eval "wm protocol $gui_fatobjectmap WM_DELETE_WINDOW { grab release $gui_fatobjectmap ; wm withdraw $gui_fatobjectmap } "
+	}
+	return 
+    }
+
+
+    # Step 1 -- run Histogram Segmentation to get body
+    # Connect -- Background to 0
+
+    WatchOn
+    set hist [ vtkpxHistogramSegmentation [ pxvtable::vnewobj ]]
+    set img [ $hist ComputeFatValues [ $currentimage GetImage ] [ $splineobjectmapeditor GetMaskImage ]  [ $this GetSurface [ expr $thisparam($this,fat_abdsurface) -1 ] ] $thisparam($this,fat_visc) $thisparam($this,fat_artf) 3 $thisparam($this,fat_numclasses) ]
+    WatchOff
+
+    ObjectmapHistogram $img
+
+    $currentresults ShallowCopyImage $img
+    $img Delete
+    $hist Delete
+
+    $currentresults CopyImageHeader [ $currentimage GetImageHeader ]
+    $currentresults configure -filename    "fat_objectmap.hdr"
+    ShowImage "Results" 1
+
+    $splineobjectmapeditor SetObjectmapTransparency 0
+	      
+}
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclsurfaceeditor::SaraObjectmapCompute { mode } {
+
+    if { $mode == 0 } {
+	if { $gui_saraobjectmap == 0 } {
+	    set gui_saraobjectmap [ toplevel $basewidget.[ pxvtable::vnewobj ]  -width 400 -height 250 ]
+	    set w $gui_saraobjectmap
+	    eval "wm protocol $w WM_DELETE_WINDOW { wm withdraw $w }"
+	    
+	    wm title $w "4-Component Fat Computation"
+	    frame $w.bot;   pack $w.bot -side bottom -expand f -fill x
+
+	    set thisparam($this,sara_abdominal_surface) 1
+	    set thisparam($this,sara_visceral_surface) 2
+	    set thisparam($this,sara_fascia_surface) 3
+	    set thisparam($this,sara_skin_surface) 4
+	    set thisparam($this,sara_fat_min) -1
+	    set thisparam($this,sara_fat_max) -1
+	    set thisparam($this,sara_fat_minsubq) -1
+
+	    iwidgets::entryfield $w.1 -labeltext "Visceral Surface:"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,sara_abdominal_surface) ] -relief sunken 
+	    iwidgets::entryfield $w.2 -labeltext "Abdominal Surface:"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,sara_visceral_surface) ] -relief sunken 
+	    iwidgets::entryfield $w.3 -labeltext "Fascia Surface:"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,sara_fascia_surface) ] -relief sunken 
+	    iwidgets::entryfield $w.35 -labeltext "Skin Surface:"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,sara_skin_surface) ] -relief sunken 
+	    frame $w.4
+
+	    pack $w.1 $w.2 $w.3 $w.35 $w.4  -side top -expand true -fill x
+
+
+	    iwidgets::entryfield $w.4.1 -labeltext "Fat Min:"  -width 4 -validate integer -textvariable [ itcl::scope thisparam($this,sara_fat_min) ] -relief sunken 
+	    iwidgets::entryfield $w.4.2 -labeltext "Max:"  -width 4 -validate integer -textvariable [ itcl::scope thisparam($this,sara_fat_max) ] -relief sunken 
+	
+	    
+	    pack $w.4.1 $w.4.2   -side left -expand true -fill x -pady 2
+
+	    eval "button $w.bot.c -text Close   -command {  wm withdraw $w }"
+	    eval "button $w.bot.b -text Compute -command { $this SaraObjectmapCompute 1 } "
+	    pack $w.bot.c $w.bot.b -side left -padx 5
+	} else {
+	    wm deiconify $gui_saraobjectmap
+	    eval "wm protocol $gui_saraobjectmap WM_DELETE_WINDOW { grab release $gui_saraobjectmap ; wm withdraw $gui_saraobjectmap } "
+	}
+	return 
+    }
+
+    set ok [ pxtclutil::Question "Grab Initial Objectmap from current view. This will erase the current objectmap. Are you sure?" ]
+    if { $ok == 0 } {
+	return
+    }
+
+    set hist [ vtkpxHistogramSegmentation [ pxvtable::vnewobj ]]
+    
+    set imgin  [ [ $this GetDisplayedImage ] GetImage ]
+    set orient [ [ $this GetDisplayedImage ] GetOrientation ]
+    set sur1  [ $this GetSurface [ expr $thisparam($this,sara_abdominal_surface) -1 ] ]
+    set sur2  [ $this GetSurface [ expr $thisparam($this,sara_visceral_surface) -1 ] ]
+    set sur3  [ $this GetSurface [ expr $thisparam($this,sara_fascia_surface) -1 ] ]
+    set sur4  [ $this GetSurface [ expr $thisparam($this,sara_skin_surface) -1 ] ]
+
+    WatchOn; update idletasks
+    set img [ $hist ComputeCaprioFatValues $imgin $sur1 $sur2 $sur3 $sur4 $thisparam($this,sara_fat_min) $thisparam($this,sara_fat_max) ]
+    WatchOff
+
+    ObjectmapHistogram $img
+
+    $currentresults ShallowCopyImage $img
+
+    $splineobjectmapeditor SetMaskImage  $img  $orient
+    $splineobjectmapeditor SetObjectmapTransparency 50
+    $this ShowImage Image
+    $img Delete
+    $hist Delete
+}
+
+# ---------------------------------------------------------------------------------
+#  Initialize Display Stuff
+# ---------------------------------------------------------------------------------
+
+itcl::body pxitclsurfaceeditor::InitializeDisplay { widg st } {
+    
+    if { $initialized == 1 } { return $basewidget }
+
+    #$this configure -appname pxitclsurfaceeditor
+    $this configure -show_standard_images 1
+    $this configure -enable_helpmenu 0
+    $this configure -enable_multisubjectcontrol 0
+    $this configure -enable_overlaytool 0
+    $this configure -enable_talaraichoption 1
+    #$this configure -appname "Surface Editor"
+    $this configure -enable_rendering_on_startup  0
+
+    set vtk_viewer [ vtkpxGUIObjectmapOrthogonalViewer [ pxvtable::vnewobj ]]
+    $vtk_viewer SetSplineObjectmapEditor $splineobjectmapeditor
+    set  bind_mouse_events 1
+    
+
+    InitializeInterface $widg $st
+
+
+    set gui_surfaceobjectmapcontrol [ $surfaceobjectmapcontrol Initialize $widg.objectmap $this ]
+    wm title $gui_surfaceobjectmapcontrol "Surface Objectmap Tool"
+
+    eval "bind all <Control-e> { wm deiconify $gui_splineobjectmapeditor }"
+
+
+    set mb2 $objectmapmenu
+    eval "$mb2 add command  -label \"Store in Morphology Mask\" -command {  $this SendToMorphologyMask }"
+    $mb2 add separator
+
+    $mb2 add cascade -underline 0  -label "Create From Data" -menu $mb2.cascade1
+    set casc1 [ menu $mb2.cascade1 -tearoff 0  ]
+    
+    eval "$casc1 add command  -label \"Grab From Current Displayed Image \" -command {  $this GrabObjectmap }"
+    eval "$casc1 add command -label \"Create from Surfaces\" -command {  wm deiconify $gui_surfaceobjectmapcontrol }"
+
+    $mb2 add cascade -underline 0  -label "Fat Objectmap Operations" -menu $mb2.cascade2
+    set casc2 [ menu $mb2.cascade2 -tearoff 0  ]
+    eval "$casc2 add command -label \"Create Full Fat Objectmap\" -command {$this ObjectmapSurfaceFatCompute 0 }"
+    eval "$casc2 add command -label \"Create 4 Class Objectmap\" -command {  $this SaraObjectmapCompute 0 }"
+
+    $mb2 add separator
+    eval "$mb2 add command -label \"Display in Simple Objectmap Viewer\"  -command { $this ObjectmapSimpleViewer display }"
+
+    #   $mb2 add separator
+    #    eval "$mb2 add command -label \"Help\" -command { $this ObjectmapHelp }"
+
+    #    eval "button $masterframe.edit  -text Edit -command  {  wm deiconify $gui_splineobjectmapeditor }"
+    #    pack $masterframe.edit -side right -padx 2
+
+    wm geometry $basewidget 700x705
+    $this CreateHelpMenu
+}
+
+
+
+# ---------------------------------------------------------------------
+itcl::body pxitclsurfaceeditor::ObjectmapSimpleViewer { mode } {
+    
+    if { $simpleviewer == 0 } {
+	set simpleviewer [ [ pxitclbaseimageviewer \#auto 0 ] GetThisPointer ]
+	$simpleviewer configure -appname "Simple Objectmap Viewer"
+	$simpleviewer configure -show_standard_images 0
+	$simpleviewer configure -enable_multisubjectcontrol 0
+	$simpleviewer configure -enable_csigadget 0
+	$simpleviewer configure -enable_rendering_on_startup  1
+	$simpleviewer configure -enable_headercontrol  0
+	$simpleviewer configure -enable_importcontrol  0
+	$simpleviewer configure -enable_imageutility  0
+	$simpleviewer configure -enable_landmarkcontrol  0
+	$simpleviewer configure -enable_overlaytool  0
+	$simpleviewer configure -enable_histcontrol  0
+	$simpleviewer configure -enable_displaymenu  0
+	$simpleviewer configure -enable_brainstriptool  0
+	$simpleviewer configure -enable_helpmenu  0
+	$simpleviewer configure -enable_talaraichoption 1
+	
+	$simpleviewer InitializeObjectmapMosaicViewer ${basewidget}.[pxvtable::vnewobj ] 0
+	update idletasks
+
+	set mbar [ $simpleviewer cget -menubase ]
+	$mbar delete 0 1
+	set mb [ menu $mbar.dispm -tearoff 0 ]; $mbar add cascade -underline 0  -label Display -menu $mb
+	eval "$mb add command  -label \"Grab Image \& Objectmap From 3D Viewer\"  -command { $this ObjectmapSimpleViewer grab } "
+	$mb add separator
+	eval "$mb add command -label Close -command {  $simpleviewer HideWindow } -underline 1"
+    } 
+    
+    $simpleviewer ShowWindow
+
+    if { $mode == "grab" } {
+	set viewer [ $this GetViewer ]
+	$simpleviewer SetImageFromObject [ $this GetDisplayedImage ] $this
+	$simpleviewer SetLookupTable [ $viewer GetLookupTable ]
+	[ $simpleviewer GetViewer ] SetObjectMapImage [  $viewer GetObjectMapImage ]
+	[ $simpleviewer GetViewer ] SetObjectLookupTable  [ $viewer  GetObjectLookupTable ]
+	[ $simpleviewer GetViewer ] SetObjectmapTransparency  [ $viewer  GetObjectmapTransparency ]
+	[ $simpleviewer GetViewer ] UpdateDisplay
+    }
+}
+
+
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    wm withdraw .    
+    set imp [ pxitclsurfaceeditor \#auto 0 ] 
+    $imp InitializeDisplay .a 1
+    $imp ShowWindow
+    if { $argc > 0 } {  
+	set ok [ $imp LoadImage [lindex $argv 0]  ] ; 
+    }
+    if { $argc > 1 } {
+	set ok [ $imp LoadObjectmap [lindex $argv 1]  ] ; 
+    }
+
+    [ $imp GetViewer ] SetEnableRendering 1
+    [ $imp GetViewer ] UpdateDisplay
+
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclsurfaceobjectmap.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclsurfaceobjectmap.tcl
new file mode 100644
index 0000000..c97a22c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclsurfaceobjectmap.tcl
@@ -0,0 +1,664 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide pxitclsurfaceobjectmap 1.0
+package provide pxitclsurobj 1.0
+
+
+
+
+
+# 	$Id: pxitclsurfaceobjectmap.tcl,v 1.1 2002/06/11 01:21:41 papad Exp papad $	
+
+package require  labelframe 1.0
+package require  pxtclutil  1.0
+package require  pxvtable   1.0
+package require  vtkpxcontrib 1.1
+package require  pxitclbasecontrol 1.0
+
+
+# ---------------------------------------------------------------------------
+#  Ancilliary Class SurObj
+# ---------------------------------------------------------------------------
+itcl::class pxitclsurobj {
+
+    public    variable outsurface  0
+    protected variable surface  0
+    protected variable basewidget 0
+    protected variable initialized 0
+    public    common surfaceutil 0
+    private   common thisparam
+
+    constructor { } {
+	if { $surfaceutil == 0 } {
+	    set surfaceutil [ vtkpxSurfaceUtil [ pxvtable::vnewobj ]]
+	}
+	Reset
+    }
+
+    destructor  { 
+	{ catch $surface Delete     }
+	{ catch $outsurface Delete  }
+    }
+
+    public method  Initialize { basewidget args  } 
+    public method  Load       { fname }
+    public method  Save   { fname }
+    public method  Resample   { scalefactor }
+    public method  Update     { }
+    public method  GetThisPointer { } { return $this }
+    public method  Reset { } 
+
+    # Access for Load /Save
+    # Get Methods
+    public method  GetActive       { } { return $thisparam($this,active)       }
+    public method  GetTargetLabel  { } { return $thisparam($this,targetlabel)  }
+    public method  GetTargetSpacing { } { return $thisparam($this,targetspacing) }
+    public method  GetFileName     { } { return $thisparam($this,filename)     }
+
+    # Set Methods
+    public method  SetActive       { s } { set thisparam($this,active)       $s }
+    public method  SetTargetLabel  { s } { set thisparam($this,targetlabel)  $s }
+    public method  SetTargetSpacing { s } { set thisparam($this,targetspacing) $s }
+    public method  SetFileName     { s } { set thisparam($this,filename)     $s }
+    
+    
+    # Internal Methods to do real work
+    protected method  ResampleSurface   { scalefactor }
+    protected method  CleanSurface   { input output distance  }
+    protected method  ResampleLandmarks { scalefactor }
+
+    protected method  LoadSurface   { numpoints }
+    protected method  LoadLandmarks { numpoints }
+
+
+
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclsurobj::Reset {  } {
+
+    set thisparam($this,filename) ""
+    
+    # Input Parameters
+    if { $surface !=0 } {
+	catch { $surface Delete }
+    }
+    set surface [ vtkPolyData [ pxvtable::vnewobj ]]
+    set thisparam($this,class)  "Surface"
+    set thisparam($this,shortfilename) ""
+    set thisparam($this,inpoints)    0
+    
+    # Output Parameters
+    if { $outsurface !=0 } { 
+	catch { $outsurface Delete }
+    }
+    set outsurface [ vtkPolyData [ pxvtable::vnewobj ]]
+    set thisparam($this,label)     1
+    set thisparam($this,points)    0
+    set thisparam($this,active)    0
+    
+    # Target Parameters
+    set thisparam($this,targetlabel)    -1
+    set thisparam($this,targetspacing) "100"
+}
+# ---------------------------------------------------------------------------	
+itcl::body pxitclsurobj::Load { fname } {
+
+    set typelist { 
+	{"Landmark/Surface Files" {".land" ".vtk" } }
+	{"Landmarks" {.land}} 
+	{"Surfaces"  {.vtk}}
+	{"All Files" {*}}
+    }
+	    
+    if { [ string length $fname ] < 2 } {
+	set f1 $thisparam($this,filename)
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+
+	set fname [tk_getOpenFile -title "Load Surface/Landmark" -initialfile $f1tail -initialdir $f1path -filetypes $typelist]
+    }
+    
+    if { [string length $fname ] < 2 } {
+	return 0;
+    }
+    
+    if { [ file extension $fname  ]== ".land" } {
+	set ok [ LoadLandmarks $fname  ]
+	if { $ok == 1 } {
+	    set thisparam($this,filename) $fname  
+	}
+    } else {
+	set ok [ LoadSurface $fname ]
+	set thisparam($this,filename) $fname 
+    }
+
+    set thisparam($this,shortfilename) [ file tail $thisparam($this,filename) ]
+    Update
+    return $ok
+}
+
+itcl::body pxitclsurobj::LoadLandmarks { fname } {
+
+    if { [ $surface IsA vtkpxBaseCurve ] == 0 } {
+	$surface Delete
+	set surface [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    }
+    set thisparam($this,class)  "Landmarks"
+    return [ $surface Load $fname ]
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclsurobj::LoadSurface { fname } {
+    
+    if { [ $surface IsA vtkpxBaseCurve ] == 1 } {
+	$surface Delete
+	set surface [ vtkPolyData [ pxvtable::vnewobj ]]
+    }
+
+    set rd [ vtkPolyDataReader [ pxvtable::vnewobj ]]
+    $rd SetFileName $fname
+    $rd Update
+
+    $surface ShallowCopy [ $rd GetOutput ]
+    set thisparam($this,class)  "Surface"
+    $rd Delete
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclsurobj::Save { fname } {
+
+    set typelist { 
+	{"Surfaces"  {.vtk}}
+	{"All Files" {*}}
+    }
+	    
+    set initial [ file dirname $thisparam($this,filename) ]
+    set f2  [ file tail [ file root $thisparam($this,filename) ] ]
+    set initial [ file join $initial "re_$f2" ]
+
+    if { [ string length $fname ] < 2 } {
+	set f1path [ file dirname $initial ]
+	set f1tail [ file tail    $initial ]
+
+	set fname [tk_getSaveFile -title "Save Surface" -initialfile $f1tail -initialdir $f1path -filetypes $typelist]
+    }
+    
+    if { [string length $fname ] < 2 } {
+	return 0;
+    }
+
+    set wr [ vtkPolyDataWriter [ pxvtable::vnewobj ]]
+    $wr SetFileName $fname
+    $wr SetInput $outsurface
+    $wr  SetFileTypeToASCII
+    $wr Update
+    $wr Delete
+
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclsurobj::Update  { } {
+
+    if { [ $surface IsA vtkpxBaseCurve ] == 1 } {
+	set thisparam($this,inpoints) [ $surface GetNumPoints ]
+    } else {
+	set thisparam($this,inpoints) [ $surface GetNumberOfPoints ]
+    }
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclsurobj::Resample { scalefactor } {
+
+    Update
+
+    if { $thisparam($this,targetspacing) < 0.1 } {
+	set thisparam($this,targetspacing) 0.1
+    } elseif { $thisparam($this,targetspacing) >= 20.0 } {
+	set thisparam($this,targetspacing) 20.0
+    }
+
+
+    
+    if { $thisparam($this,inpoints) < 2 } {
+	return 0
+    }
+
+    if { [ $surface IsA vtkpxBaseCurve ] } {
+	 ResampleLandmarks $scalefactor
+    } else {
+	ResampleSurface $scalefactor
+    }
+    $surfaceutil AddObjectLabelsToSurface $outsurface [ expr -1 * ($thisparam($this,targetlabel)) ]
+    set thisparam($this,label) $thisparam($this,targetlabel)
+
+}
+
+itcl::body pxitclsurobj::ResampleLandmarks { scalefactor } {
+
+
+    set length [ $surface GetLength ]
+    #set sampl  [ expr $length / ( $thisparam($this,targetspacing) + 0.01 )]
+
+    set sampl [ expr $thisparam($this,targetspacing)  *$scalefactor ]
+
+    set newcur [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    $newcur Copy $surface
+    $newcur Equispace $sampl
+    #sampl
+    $newcur Smooth 0.33
+    set ok [ $newcur ExportToPolyData $outsurface -1.0 ]
+    set thisparam($this,points) [ $outsurface GetNumberOfPoints ]
+    $newcur Delete
+    pxtkconsole
+    pxtkprint "Resampled Curve length=$length sampl=$sampl outp=$thisparam($this,points)\t\tBounds [ $outsurface GetBounds ]\n"
+    return $ok
+}
+
+itcl::body pxitclsurobj::CleanSurface { input output distance } {
+
+    set cleanerFilter [ vtkCleanPolyData [ pxvtable::vnewobj ]]
+    $cleanerFilter SetInput $input
+    $cleanerFilter ToleranceIsAbsoluteOn
+    $cleanerFilter SetAbsoluteTolerance $distance
+    $cleanerFilter Update
+    $output ShallowCopy [ $cleanerFilter GetOutput ]
+    $cleanerFilter Delete
+}
+
+itcl::body pxitclsurobj::ResampleSurface { scalefactor } {
+    
+    #set dist 2.0 
+    #    set thisparam($this,points) [ expr $thisparam($this,targetspacing) + 100 ]
+    set dist [ expr $thisparam($this,targetspacing) * $scalefactor ]
+    pxtkconsole
+    #while { ( $dist < 15.0 ) && ( $thisparam($this,points) >  $thisparam($this,targetspacing) ) } {
+
+    CleanSurface $surface $outsurface $dist
+    #dist
+    set thisparam($this,points) [ $outsurface GetNumberOfPoints ]
+    pxtkprint "input=$thisparam($this,inpoints) --> $thisparam($this,points) dist=$dist\t\tBounds: [ $outsurface GetBounds ]\n"
+    #set dist [ expr $dist * 1.1 ]
+    #}
+
+}
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclsurobj::Initialize { basewid  args } {
+
+    set clr "darkgray"
+    if { [ llength $args ] > 0 } {
+	set clr [ lindex $args 0 ]
+    }
+
+    if { $initialized == 1 } { return $basewidget }
+    
+    set basewidget  [ frame $basewid -bg $clr -bd 4 ]
+    set initialized 1
+
+    set left   [ frame $basewidget.left   ]
+    set middle [ frame $basewidget.middle  ]
+    set right  [ frame $basewidget.right  ]
+
+    pack $left   -side left -expand t -fill both
+    pack $middle -side left -padx 10 -expand t -fill both
+    pack $right -side left  -expand t -fill both
+
+
+
+    # Left is Input Frame 
+
+    set tp [ frame $left.top ]
+    set bt [ frame $left.bot ]
+    pack $tp $bt -side top -expand t -fill both -pady 1
+
+    
+    iwidgets::entryfield $tp.name -labeltext "Fname:" -width 20 -textvariable [ itcl::scope thisparam($this,shortfilename) ]
+    iwidgets::entryfield $bt.class -labeltext "Type:"   -width 10 -textvariable [ itcl::scope thisparam($this,class) ]
+    iwidgets::entryfield $bt.pt -labeltext "Points:" -width 5 -textvariable [ itcl::scope thisparam($this,inpoints) ]
+    [ $tp.name  component entry ] configure -state disabled -bg white
+    [ $bt.pt    component entry ] configure -state disabled -bg white
+    [ $bt.class component entry ] configure -state disabled -bg white
+    eval "button $tp.load -text \"Load\" -command { $this Load \"\" } "
+    pack $tp.load -side right -padx 2
+    pack $tp.name -side left -padx 2 -expand f -fill x
+    pack $bt.class $bt.pt -side left -padx 2 -expand f 
+
+    set tp [ frame $middle.top ] ; set bt [ frame $middle.bot ] ; 
+    pack $tp $bt -side top -expand t -fill both -pady 1
+    
+    iwidgets::entryfield $tp.targ -labeltext "Target Spacing:" -width 5 -textvariable [ itcl::scope thisparam($this,targetspacing) ]
+    eval "button $tp.resamp -text \"Resample!\" -command { $this Resample 1.0 }"
+    iwidgets::entryfield $bt.targ -labeltext "Target Label:" -width 2 -textvariable [ itcl::scope thisparam($this,targetlabel) ]
+    eval "button $bt.save -text \"Save!\" -command { $this Save \"\"}"
+    pack $tp.targ  -side left -expand f 
+    pack $bt.targ -side left -expand f 
+    pack $tp.resamp -side right -expand f 
+    pack $bt.save -side right -expand f 
+
+    set tp [ frame $right.top ] ; set bt [ frame $right.bot ]
+    pack $tp $bt -side top -expand t -fill both -pady 1
+
+    iwidgets::entryfield $tp.actual -labeltext "Points:" -width 5 -textvariable [ itcl::scope thisparam($this,points) ]
+    iwidgets::entryfield $tp.lab    -labeltext "Out Label:" -width 2 -validate numeric -textvariable [ itcl::scope thisparam($this,label) ]
+    [ $tp.lab component entry ] configure -state disabled -bg white
+    [ $tp.actual component entry ] configure -state disabled -bg white
+    
+
+    checkbutton $bt.act -text "Active" -variable [ itcl::scope thisparam($this,active) ]
+    pack $tp.actual $tp.lab -side right -expand f -padx 10
+    pack $bt.act -side left -expand f 
+    return $basewidget
+}
+
+
+# ------------------------------------------------------------------------------------------
+#
+# pxitclsurfaceobjectmap control
+#
+# ------------------------------------------------------------------------------------------
+
+itcl::class pxitclsurfaceobjectmap {
+
+    inherit pxitclbasecontrol
+
+    private   common   thisparam
+    protected variable polydatacontrol 0
+    protected variable initialized 0
+    protected variable combo_surface 0
+    protected variable brain_utility 0 
+    public    variable numberofsurfaces 
+    protected common surface
+
+
+    constructor { par } {
+	::pxitclbasecontrol::constructor $par
+    } { 
+	set numberofsurfaces 15
+	set thisparam($this,outputsurface) 1
+	set thisparam($this,scalefactor) 1.0
+    }
+
+    protected method InitializeVariables  { }
+    public    method GenerateComboSurface { }
+    public    method Initialize  { basewidget args } 
+    public    method SaveSetup   { fname } 
+    public    method LoadSetup   { fname }
+    public    method ResampleAll { }
+    
+}
+
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclsurfaceobjectmap::Initialize { basewidg args } {
+
+    if { $initialized == 1 } { return $basewidget }
+
+    set basewidget [ toplevel $basewidg ] 
+    wm withdraw $basewidget
+    wm geometry $basewidget 800x400
+    wm title $basewidget "Surface Object Map Generator"
+
+    set w [ frame $basewidget.bottom ]
+    set w2 [ frame $basewidget.bottom2 ]
+    pack $w $w2 -side bottom -expand f -fill x -pady 2
+
+    
+    eval "button $w.1 -text Close -command { $this HideWindow } "
+    pack $w.1 -side right
+
+    set num 2; catch { set num [ $polydatacontrol  GetNumberOfSurfaces ]  }
+
+    eval "button $w.l -text \"Load Setup\" -command { $this LoadSetup \"\" }"
+    eval "button $w.s -text \"Save Setup\" -command { $this SaveSetup \"\" }"
+    eval "button $w.r -text \"Resample All\" -command { $this ResampleAll  }"
+    label $w.l1 -text "x"
+    tk_optionMenu $w.opt [ itcl::scope thisparam($this,scalefactor) ] 0.25 0.5 0.75 0.9 1.0 1.1 1.2 1.25 1.33 1.5 2.0 2.5 3.0 3.5 4.0
+    pack $w.l $w.s $w.r $w.l1 $w.opt  -side left -padx 5 
+
+    eval "button $w2.p -text \"Create Combo Surface\" -command { $this GenerateComboSurface }"
+    pack $w2.p -side left
+
+    if { [ llength $args ] > 0 } {
+	set polydatacontrol [ lindex $args 0 ]
+	eval "button $w2.2 -text \"Show Surface Control\" -command { $polydatacontrol Show 1 }"
+	pack $w2.2 -side left
+    } else {
+	set polydatacontrol 0
+    }
+    set l [ AddLogoLabel $w2 ];     pack $l -side right -padx 1 
+
+
+    iwidgets::scrolledframe $basewidget.sf -width 4i -height 2i -labeltext "Components"
+    pack $basewidget.sf -side top -expand t -fill both
+
+    set win [ $basewidget.sf childsite]
+
+    set a(0) "black"
+    set a(1) "white"
+    set count 0
+
+    for { set i 1 } { $i <= $numberofsurfaces } { incr i } {
+	
+	set pr [ iwidgets::Labeledframe $win.$i -labelpos w -labeltext "# $i" ]
+	pack $win.$i -side top
+
+	set surface($this,$i) [  [ pxitclsurobj \#auto ] GetThisPointer ]
+	if { $i == 1 } {
+	    $surface($this,$i) SetTargetSpacing 3.0
+	    $surface($this,$i) SetTargetLabel 1
+	} else {
+	    $surface($this,$i) SetTargetSpacing 0.33
+	    $surface($this,$i) SetTargetLabel $i
+	}
+ 
+	lappend itclobjectlist $surface($this,$i)
+	set fr [ $surface($this,$i) Initialize [ $pr childsite].1  $a($count) ]
+	pack $fr -side top -expand f -fill x -pady 10
+	set count [expr 1-$count ]
+    }
+
+    set initialized 1
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget 
+}
+
+# ------------------------------------------------------------------------------------------     
+itcl::body pxitclsurfaceobjectmap::GenerateComboSurface { } {
+
+
+    set bad -1
+
+    for { set i 1 } { $i <= $numberofsurfaces } { incr i } {
+
+	set flag [ $surface($this,$i) GetActive ]
+	if { $flag == 1 } { 
+	    set np [ [ $surface($this,$i) cget -outsurface ] GetNumberOfPoints ]
+	    if { $np < 2 } {
+		set bad $i
+		set i [ expr $numberofsurfaces+1 ]
+	    } 
+	}
+    }
+
+    if { $bad > 0 } {
+	::pxtclutil::Warning "Surface $bad has no points! Cannot Generate Combo Surface!"
+	return 0
+    }
+
+    set numinp 0
+    set appnd [ vtkAppendPolyData [ pxvtable::vnewobj ] ]
+    for { set i 1 } { $i <= $numberofsurfaces } { incr i } {
+
+	set flag [ $surface($this,$i) GetActive ]
+	if { $flag == 1 } { 
+	    set sur [ $surface($this,$i) cget -outsurface ]; 
+	    puts stdout "Adding Surface $i np = [ $sur GetNumberOfPoints ] \t\t Bounds = [ $sur GetBounds ]"
+	    $appnd AddInput [ $surface($this,$i) cget -outsurface ]
+	    incr numinp
+	}
+    }
+
+    if { $numinp > 0 } {
+
+	$appnd Update
+	[ $appnd GetOutput ] ComputeBounds
+	puts stdout "Creating Combo Surface Completed. The resulting surface is stored on the clipboard of the surface control\n(You must paste this into a surface before it becomes available) [ [ $appnd GetOutput ] GetBounds ]"
+	[ $surface($this,1) cget -surfaceutil ] AddObjectMapLookupTableToSurface [ $appnd GetOutput ] 
+	
+	if { $polydatacontrol != 0 } {
+	    $polydatacontrol  SetClipboardSurface [ $appnd GetOutput ] "combo_surface"
+	    ::pxtclutil::Info "Creating Combo Surface Completed. The resulting surface is stored on the clipboard of the surface control\n(You must paste this into a surface before it becomes available) [ [ $appnd GetOutput ] GetBounds ]"
+	}
+    }
+    $appnd Delete
+}
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclsurfaceobjectmap::SaveSetup { fname } {
+
+    set typelist { 
+	{"Surface Objectmap setup" {.sobj}} 
+	{"All Files" {*}}
+    }
+	    
+    if { [ string length $fname ] < 2 } {
+	set fname [tk_getSaveFile -title "Save Setup for Surface Objectmap" -filetypes $typelist]
+    }
+    
+    if { [string length $fname ] < 2 } {
+	return 0;
+    }
+
+    set fileid [open $fname w]
+    
+    puts $fileid "#Surface Object Map Setup File\n-----------------------------------"
+
+    set count 0
+    for { set i 1 } { $i <= $numberofsurfaces } { incr i } {
+	set fn [ $surface($this,$i) GetFileName ]
+	if { [ string length $fn ] > 1 } { 
+	    incr count
+	}
+    }
+
+    puts $fileid "#Number Of Surfaces = $count"
+    set index 1
+    for { set i 1 } { $i <= $numberofsurfaces } { incr i } {
+	set fn [ $surface($this,$i) GetFileName ]
+	if { [ string length $fn ] > 1 } { 
+	    puts $fileid "# ------------- Surface $index ----------------------------"
+	    set act [ $surface($this,$i) GetActive ]
+	    set lab [ $surface($this,$i) GetTargetLabel ]
+	    set tp  [ $surface($this,$i) GetTargetSpacing ]
+	    puts $fileid "Filename=$fn\nActive=$act\nTarget Label=$lab\nTarget Points=$tp"
+	    incr index
+	}
+    }
+    close $fileid
+    return 1
+}
+# ------------------------------------------------------------------------------------------
+itcl::body pxitclsurfaceobjectmap::LoadSetup { fname } {
+
+    set typelist { 
+	{"Surface Objectmap setup" {.sobj}} 
+	{"All Files" {*}}
+    }
+	    
+    if { [ string length $fname ] < 2 } {
+	set fname [tk_getOpenFile -title "Load Setup for Surface Objectmap" -filetypes $typelist]
+    }
+    
+    if { [string length $fname ] < 2 } {
+	return 0;
+    }
+
+    if { [ file exists $fname ] == 0 } {
+	return 0;
+    }
+
+    set fileid [open $fname r]
+    
+    set line ""
+    gets $fileid line 
+    
+    # Get Number Of Surfaces
+    if { [ string compare $line "#Surface Object Map Setup File" ] != 0} { 
+	::pxtclutil::Warning "Cannot read setup file\n Bad Header = $line \n"
+	close $fileid
+	return 0
+    }
+
+    # Skip Next Line
+    gets $fileid line ; 
+   
+    # Get Number Of Surfaces
+    gets $fileid line ; set numsur [ lindex [ split $line "=" ] 1]
+
+    if { $numsur > $numberofsurfaces } {
+	set numsur $numberofsurfaces
+    }
+
+    for { set i 1 } { $i <= $numsur } { incr i } {
+	gets $fileid line 
+
+	gets $fileid line ; set fname [ lindex [ split $line "=" ] 1 ]
+	$surface($this,$i) SetFileName $fname
+
+	
+	gets $fileid line ; set active [ lindex [ split $line "=" ] 1 ]
+	$surface($this,$i) SetActive $active
+
+
+	gets $fileid line ; set lab [ lindex [ split $line "=" ] 1 ]
+	$surface($this,$i) SetTargetLabel $lab 
+
+	gets $fileid line ; set tp [ lindex [ split $line "=" ] 1 ]
+
+	if { $tp > 10.0 && $tp < 300 } { 
+	    set tp [ expr 64.0 / ( 0.01 + $tp )  ]
+	} elseif { $tp > 500 } {
+	    set tp [ expr 15000.0 / ( 0.01+$tp) ]
+	}
+	set tp [ format "%.2f" $tp ]
+
+	$surface($this,$i) SetTargetSpacing $tp
+
+	$surface($this,$i) Load $fname
+    }
+
+    for { set i [ expr $numsur+1] } { $i <= $numberofsurfaces } { incr i } {
+	$surface($this,$i) Reset
+    }
+
+    close $fileid
+    return 1
+}
+# ------------------------------------------------------------------------------------------
+
+itcl::body pxitclsurfaceobjectmap::ResampleAll { } {
+
+    for { set i 1 } { $i <= $numberofsurfaces } { incr i } {
+	$surface($this,$i) Resample $thisparam($this,scalefactor)
+    }
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclvolumeviewer.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclvolumeviewer.tcl
new file mode 100755
index 0000000..a275248
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclvolumeviewer.tcl
@@ -0,0 +1,100 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclvolumeviewer.tcl,v 1.1 2003/05/28 16:43:26 papad Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package require vtkpxcontrib  1.1
+package require pxtcluserprefs 1.0
+package require pxitclbase4dimageviewer 1.0
+
+wm withdraw .
+set breg [ pxitclbase4dimageviewer \#auto 0 ]
+$breg configure -appname "BioImage Suite::VolumeViewer"
+set w [ $breg InitializeDisplay .[pxvtable::vnewobj ] 1 ]
+wm geometry [ $breg GetBaseWidget ] 650x600
+
+$breg CreateHelpMenu 
+
+set argc [llength $argv]
+
+if { $argc > 0 } {   $breg LoadImage [lindex $argv 0]   }
+if { $argc >1  } {  [ $breg cget -abaquscontrol ] LoadStudy [ lindex $argv 1 ]}
+
+
+$breg ShowWindow
+
+if { $argc > 2 } {
+    
+    set ortho [ $breg GetViewer ]
+    set numframes [ $ortho GetNumberOfFrames ]
+    set name [ lindex $argv 2 ]
+
+    for { set i 0 } { $i < $numframes } { incr i } {
+
+	set j [ expr $i +1 ]
+	set sphere [ vtkPolyDataReader read_$i ]
+	$sphere SetFileName "${name}_${j}.vtk"
+	$sphere Update
+
+	puts stdout "\tRead [ $sphere GetFileName ] points = [ [ $sphere GetOutput ] GetNumberOfPoints ]"
+	
+	set mapper [ vtkPolyDataMapper map_$i ]
+	$mapper SetInput [ $sphere GetOutput ]
+	
+	set act [ vtkActor act_$i ]
+	$act SetMapper $mapper
+	[ $act GetProperty ] SetColor 0.8 0.2 0.2 
+	
+	$ortho SetCurrentFrame $i
+	set ren [ [ $ortho GetRenderer 3 ] GetRenderer ]
+	$ren AddActor $act
+	
+	$mapper Delete
+	$sphere Delete
+	$act Delete
+    }
+    
+    $ortho SetCurrentFrame $i
+    $ortho SetDisplayMode3D
+}
+
+update idletasks
+[ $breg GetViewer ] SetEnableRendering 1
+[ $breg GetViewer ] UpdateDisplay
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclvvlinkgadget.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclvvlinkgadget.tcl
new file mode 100644
index 0000000..895cf3f
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclvvlinkgadget.tcl
@@ -0,0 +1,2183 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+package provide pxitclvvlinkgadget 1.0
+
+# 	$Id: pxitclvvlinkgadget.tcl,v 1.4 2005/11/02 15:29:19 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+package require  vtkpxcontrib 1.1
+package require  labelframe   1.0
+package require  pxtclutil    1.0
+package require  pxvtable     1.0
+package require  pxtclhelp    1.0
+package require  Itcl         3.2
+package require  Iwidgets     4.0
+package require  pxitclimage            1.0
+package require  pxitcltransform        1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxtcluserprefs         1.0
+package require  pxitclvvlinkprojectorgadget 1.0
+package require pxitclLandmarkControl    1.0
+package require pxitclPolyDataControl    1.0
+
+
+# ----------------------------------------------------------------------------------------------
+
+itcl::class pxitclvvlinkgadget {
+
+    inherit pxitclbaseimagecontrol
+
+    # Generic Stuff 
+    private   common   thisparam        
+    protected variable setupfilename   ""
+
+    # Other Common Stuff
+    protected common   vvlink_channel 0
+    protected common   vvlink_connected  0
+    protected common   vvlink_imagelist  ""
+
+    # Various
+    protected variable vvlink_transform  0
+    protected variable vtk_viewer 0
+    protected variable vvl_connector 0
+    protected variable igtlconnector 0
+    protected common   igtlconnected  0
+
+    protected variable oldtx 0
+    protected variable oldty 0
+    protected variable oldtz 0
+
+
+
+    protected variable enable_igtl 1
+
+    protected variable vvlink_ztouchpointlist ""
+    protected variable vvlink_xformlist       ""
+    protected variable vvlink_logfilename  "LogFile.log"
+
+    protected variable img_control      0
+    protected variable xform_control    0
+
+    protected variable vv_pointersource 
+    protected variable vv_pointermapper 
+    protected variable vv_pointeractor  
+    protected variable internalpoints
+    protected variable internaltransform
+    
+    protected variable vvlink_projector 0
+
+    protected variable advanced_gui 0
+    protected variable conecolor { 0.2 0.8 0.0 }
+    protected variable go
+    protected variable oldCenter
+    
+    protected variable addserver_gui 0
+    protected variable landmarkcontrol 0
+    protected variable polydatacontrol 0
+
+    # ------------------------------------------------------------------------------
+
+    constructor { par args } {
+	pxitclbaseimagecontrol::constructor $par 
+    } {
+	InitializeVVLinkGadget
+    }
+
+    private method InitializeVVLinkGadget { } 
+    public method Initialize { widget viewer }
+
+
+    public method VVLinkConnect {  } 
+    public method VVLinkUpdateImageList { } 
+    public method VVLinkDisconnect { } 
+    public method VVLinkServerAdd { mode } 
+
+    public method OpenIGTLinkConnect { }
+    public method OpenIGTLinkDisconnect { }
+    public method OpenIGTLinkSendTool { pts }
+    public method OpenIGTLinkSendImage { }
+    public method OpenIGTLinkSendCrossHairs { }
+
+
+    public method VVLinkSendImage { mode } 
+    public method VVLinkGetImage { index }
+    public method VVLinkGetLabeledPointsOrTools { mode }
+	public method VVLinkGetTrajectoryPointsOrTools { mode }
+    public method VVLinkMoveCamera { bx by bz tx ty tz }
+    public method VVLinkAcquireLandmark { }
+    public method VVLinkGetLabeledPointsOrToolsAsSurface { mode }
+    public method VVLinkGetToolCoordinates { mode } 
+    public method VVLinkRotateCamera { cx cy cz } 
+
+    public method VVLinkSaveLabeledPointsOrTools { mode args }
+    public method AddToMenuButton { mb args } 
+
+    public method SelectedAxial { } { set thisparam($this,flipfront) 0 ; set thisparam($this,fliptop) 1 ;  set thisparam($this,flipleft) 1 }
+    public method SelectedCoronal { } { set thisparam($this,flipfront) 1 ; set thisparam($this,fliptop) 0 ; set thisparam($this,flipleft) 1 }
+    public method WarnAboutFlipLeft { }
+    public method ShowAdvanced { }
+
+    # ----------------------------
+    # Setup Stuff
+    # ----------------------------
+    public method LoadSetup { args } 
+    public method SaveSetup { args } 
+
+    # ----------------------------
+    #  Z-Touch Parser
+    # ----------------------------
+    public method ParseLogFile { filename  }
+    public method ParseRegistrationIni { filename }
+    public method RecoverZTouchSurface { }
+
+
+    # ----------------------------
+    # Strip Control
+    # ----------------------------
+    public method PredictElectrodeStrip { }
+
+    # ---------------------------
+    # GUI Stuff
+    # ---------------------------
+
+    public method CreateConfigurationControl { parent } 
+
+    public method CreateServerControl { parent } 
+    public method CreateOpenIGTLControl { parent } 
+    public method CreateFeatureControl { parent } 
+	public method CreateTrajectoryControl { parent }
+    public method CreateZTouchControl { parent }
+    public method CreateStripControl { parent }
+    public method CreatePointerControl { parent }
+    public method CreateDataSetControl { parent }
+    public method CreateAboutControl { parent }
+
+    public method PointerColor { }
+    public method TipColor { index }
+    public method EnablePointerControls {  } 
+    public method ShowHideCone { }
+    public method ShowControl { mode }
+    public method ShowProjectorControl { }
+    public method crossProduct { list1 list2 } 
+    public method OnPoint { tip0 tip1 tip2 pt0 pt1 pt2 } 
+
+
+    public method CreateLandmarkAndSurfaceControls { }
+    public method GetLandmarkControl { }
+    public method GetPolyDataControl { }
+}
+
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkgadget::InitializeVVLinkGadget { } {
+
+    global env
+
+    set oldCenter(x) ""
+    set oldCenter(y) ""
+
+    set thisparam($this,openigtlserver) 192.168.0.22
+    set thisparam($this,openigtlport)   18944
+    set thisparam($this,openigtlstatus) "Disconnected"
+    set thisparam($this,openigtlbase)   0
+    set thisparam($this,openigtlenablecursor)   0
+    set thisparam($this,openigtlslicermode)   1
+    set thisparam($this,openigtlslicercentering) 1
+
+
+    set thisparam($this,coneradius) 2
+    set thisparam($this,conelength) 100
+    set thisparam($this,coneextension) 0
+
+    set vvl_connector [ vtkpxVVLinkConnectorNew [ pxvtable::vnewobj ]]
+
+    set thisparam($this,streamdelay) 500
+    set thisparam($this,tooldelay) 500
+    set thisparam($this,showcross) 0
+    set thisparam($this,cylinderenabled) 0
+    set thisparam($this,crosslength) 3.0
+    set thisparam($this,crossthickness) 0.3
+    set thisparam($this,rollangle) 1.0
+    set thisparam($this,showsphere) 0    
+    set thisparam($this,updateviewer) 1
+    set thisparam($this,vvlinkserver) "hostip:password"
+    set thisparam($this,listoftrajectories) ""
+    set thisparam($this,servermenu) ""
+    set fn ".vvlinkservers"
+    catch { set fn $env(VVLINKLIST) }
+    set setupfilename [ file join $env(HOME) $fn ]
+    set thisparam(thisparam,connectlist) ""
+    set thisparam(thisparam,disconnectlist) ""
+
+    set thisparam($this,vvlink_keepsendingimage)  0
+    set thisparam($this,vvlink_keepgettingcursor) 0
+    set thisparam($this,orientation) -1
+    set thisparam($this,flipleft)   1
+    set thisparam($this,flipfront)  0
+    set thisparam($this,fliptop)    1
+    set thisparam($this,forceaxial) 1
+
+    set thisparam($this,samplerate) 2
+
+
+    set thisparam($this,stripstep)       5.0
+    set thisparam($this,striplength)    50.0
+    set thisparam($this,stripsmoothness) 0.5
+
+    set thisparam($this,stripbrainsurface) 1
+    set thisparam($this,stripoutput)       2
+
+
+    set thisparam($this,striplandmarkoffset)   -1
+
+    set thisparam($this,inline) 0
+
+    set internalpoints [ vtkPoints  [ pxvtable::vnewobj ] ]
+    $internalpoints SetNumberOfPoints 2
+    set internaltransform [ vtkTransform  [ pxvtable::vnewobj ] ]
+
+
+
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::CreateLandmarkAndSurfaceControls { } {
+
+    puts stdout "Creating landmark and surface controls"
+
+    set landmarkcontrol [ [ pxitclLandmarkControl \#auto $this ]  GetThisPointer ]
+    $landmarkcontrol Initialize $basewidget $vtk_viewer
+
+    set polydatacontrol [ [ pxitclPolyDataControl \#auto $this ]  GetThisPointer ]
+    $polydatacontrol Initialize $basewidget $vtk_viewer
+    
+
+}
+
+itcl::body pxitclvvlinkgadget::GetLandmarkControl { } {
+
+    if { $landmarkcontrol !=0 } {
+	return $landmarkcontrol
+    }
+
+    catch {
+	set landmarkcontrol [ $parent GetLandmarkControl ]
+	return $landmarkcontrol
+    }
+
+    $this CreateLandmarkAndSurfaceControls
+    return $landmarkcontrol
+
+}
+
+itcl::body pxitclvvlinkgadget::GetPolyDataControl { } {
+
+    if { $polydatacontrol !=0 } {
+	return $polydatacontrol
+    }
+
+    catch {
+	set polydatacontrol [ $parent GetPolydataControl ]
+	return $polydatacontrol
+    }
+
+    $this CreateLandmarkAndSurfaceControls
+    return $polydatacontrol
+
+}
+
+#--------------------------------------------------------------------------------------------
+#
+#         VV Link Code
+#
+# ---------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::VVLinkConnect { }  {
+    
+    if { $vvlink_connected == 0 } {
+
+	if { $vvl_connector== 0 } {
+	    ::pxtclutil::Info "Cannot Connect to VVLink No vvl_connector specified\n" 
+	    return 
+	}
+	
+	set tmp  [ split $thisparam($this,vvlinkserver) : ]
+	if { [ llength $tmp ] <=2  } {
+	    set vvlink_server [ lindex $tmp 0 ]
+	    set vvlink_password [ lindex $tmp 1 ]
+	} else {
+	    set vvlink_server [ lindex $tmp 1 ]
+	    set vvlink_password [ lindex $tmp 2 ]
+	}
+    	
+	set vvlink_channel [ pid ]
+
+	set ok [ $vvl_connector InitializeVVLConnection $vvlink_server $vvlink_password $vvlink_channel ] 
+	if  { $ok == 1 } {
+	    ::pxtclutil::Info "VVLink Connection to $vvlink_server established.\nNext transfer an image to initialize the tool."
+	    set vvlink_connected 1
+	    incr vvlink_channel
+	} elseif { $ok == 2 } {
+	    ::pxtclutil::Info "VVLink Connection to $vvlink_server already established.\nNext transfer an image to initialize the tool."
+	    incr vvlink_channel
+	} else {
+	    ::pxtclutil::Warning "VVLink Connection to $vvlink_server Failed!"
+	    $vvl_connector Delete
+	    set vvl_connector [ vtkpxVVLinkConnectorNew [ pxvtable::vnewobj ]]
+	    return 0
+	}
+		
+	set namelist  [ $vvl_connector GetVVLinkImageNameList  ]
+	set length    [ string length namelist ]
+	set namelist  [ string range $namelist 0 end-1 ]
+
+	set vvlink_imagelist  [ split $namelist , ]
+	$xform_control ClearObject
+	set vvlink_transform 0
+    } else {
+	set tmp  [ split $thisparam($this,vvlinkserver) : ]
+	set vvlink_server [ lindex $tmp 0 ]
+	set vvlink_password [ lindex $tmp 1 ]
+	set ok [ $vvl_connector InitializeVVLConnection $vvlink_server $vvlink_password $vvlink_channel ] 
+	$xform_control ClearObject
+	set vvlink_transform 0
+    }
+    
+
+    if { $vvlink_connected == 1 } {
+
+	DisableUI  $thisparam($this,connectlist)
+	EnableUI $thisparam($this,disconnectlist)
+	DisableUI $thisparam($this,streamonlist)
+	DisableUI $thisparam($this,linkonlist)
+	
+	set num_trajectories [ $vvl_connector GetVVNumberOfTrajectories ] 
+	puts "num_traj is $num_trajectories"
+	
+	set ok  [$vvl_connector GetVVNamesOfTrajectories $num_trajectories ]
+	
+
+	for { set i 0 } { $i < [ llength $vvlink_imagelist ] } { incr i } {
+	    $thisparam($this,vvimagelist) insert end [ lindex $vvlink_imagelist $i ]
+	}
+	
+	$thisparam($this,vvimagelist) selection clear 0 0
+	$thisparam($this,vvimagelist) selection set   0 0
+
+
+	SetTitle "VVLINK Tool: [ $vvl_connector GetVVLinkPatientName ], $vvlink_server, Channel: [ expr [ $vvl_connector GetVVLinkChannel ] +1 ]" 
+	$basewidget configure -bg red
+    }
+
+
+    return 1
+}
+
+# ---------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::VVLinkUpdateImageList { } {
+    if { $vvlink_connected == 0 } {
+	return 0
+    }
+
+    set num [ $vvl_connector UpdateImageList ]
+    set namelist  [ $vvl_connector GetVVLinkImageNameList  ]
+    set length    [ string length namelist ]
+    set namelist  [ string range $namelist 0 end-1 ]
+    
+    $thisparam($this,vvimagelist) delete 0 end
+    $thisparam($this,vvimagelist) selection clear 0 0
+    $thisparam($this,vvimagelist) selection set   0 0
+    
+    set vvlink_imagelist  [ split $namelist , ]
+    for { set i 0 } { $i < [ llength $vvlink_imagelist ] } { incr i } {
+	$thisparam($this,vvimagelist) insert end [ lindex $vvlink_imagelist $i ]
+    }
+
+    ::pxtclutil::Info "Image List Updated from Server (numimages=$num)\n"
+
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::VVLinkDisconnect { } {
+
+    if { $vvlink_connected == 1 } {
+
+	$vvl_connector CloseVVLConnection	
+	set vvlink_channel 0
+	set vvlink_connected  0
+	set vvlink_imagelist  ""
+
+	$thisparam($this,vvimagelist) delete 0 end
+
+	EnableUI  $thisparam($this,connectlist)
+	DisableUI $thisparam($this,disconnectlist)
+
+	SetTitle "VVLINK Tool: Disconnected" 
+	$basewidget configure -bg black
+
+    }
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::VVLinkSendImage { mode } {
+
+    if { $vtk_viewer == 0 } {
+	return 0
+    }
+
+    if { $mode ==0 || $mode == 1 } {
+	$vvl_connector SendViewerToVVLChannel [ [ $vtk_viewer GetRenderWidgetName ] GetRenderWindow ]
+    }
+
+    if { $mode == 1 } { 
+	set thisparam($this,vvlink_keepsendingimage) 1
+	DisableUI $thisparam($this,streamofflist)
+	EnableUI $thisparam($this,streamonlist)
+    } elseif { $mode == 2 } {
+	set thisparam($this,vvlink_keepsendingimage) 0
+	DisableUI $thisparam($this,streamonlist)
+	EnableUI $thisparam($this,streamofflist)
+    }
+
+    if { $thisparam($this,vvlink_keepsendingimage) == 1 }  {
+	eval "after $thisparam($this,streamdelay) $this VVLinkSendImage 0"
+    }
+
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::VVLinkGetImage { index } { 
+
+    if { $vvlink_connected == 0  || [ llength $vvlink_imagelist ] == 0 } {    
+	return
+    }
+
+    if { $index == - 1 || $index >= [ llength $vvlink_imagelist ] } {
+	set fname [ $thisparam($this,vvimagelist) getcurselection ]
+	set index [ $thisparam($this,vvimagelist) curselection ]
+    } else {
+	set fname  [ lindex $vvlink_imagelist $index ]
+    }
+
+    #    puts stdout "Loading $fname as index $index\n"
+
+    
+    WatchOn
+    $parent WatchOn
+    set img [ vtkImageData [ pxvtable::vnewobj ]]
+    set lut [ vtkLookupTable [ pxvtable::vnewobj ]]
+
+    set tmp_transform [ vtkTransform [ pxvtable::vnewobj ]]
+
+#    set ok [ $vvl_connector GetVVLinkImage $fname $img $tmp_transform $lut $thisparam($this,orientation) $thisparam($this,samplerate) ]
+
+    set outputorient $thisparam($this,orientation)
+    if { $thisparam($this,forceaxial) ==1 } {
+	set outputorient 0
+    }
+
+    set ok [ $vvl_connector GetVVLinkImage $fname $img $tmp_transform $lut $thisparam($this,orientation) $thisparam($this,flipleft) $thisparam($this,flipfront) $thisparam($this,fliptop) $outputorient $thisparam($this,samplerate) ]
+    
+     if { $ok == 1 } {
+	 set tmp    [  $img_control GetObject ]
+	 $tmp ShallowCopyImage $img
+	 $tmp configure -filename    $fname
+	 $tmp CopyImageHeader $outputorient
+	 #	 puts stderr "Transfered Image = [ $tmp GetLongDescription ]"
+	 $img_control Update
+	 $parent SetImageFromObject $tmp $this
+	 $parent SetLookupTable $lut
+	 
+	 set tr [ $xform_control GetObject ]
+	 $tr CopyTransformation $tmp_transform
+	 $tr configure -filename "${fname}.matr"
+	 $xform_control Update
+	 set vvlink_transform [ $tr GetTransformation ]
+	 set failed 0
+     } else {
+	 set failed 1
+     }
+
+    
+    WatchOff
+    $parent WatchOff
+
+    if { $failed == 1 }  {
+	::pxtclutil::Warning "Image Transfer of $fname Failed\n"
+    }
+    
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::VVLinkGetLabeledPointsOrTools { mode } {
+
+    if { $vvlink_connected == 0  || $vvlink_transform == 0 } {    
+	::pxtclutil::Warning "Either VVLink is not connected or current transform is not valid! (Most likely you need to transfer an image first.)"
+	return 0
+    }
+
+    set  landmarkcontrol [ $this GetLandmarkControl ]
+   
+    if { $landmarkcontrol ==0 } {
+	return
+    }
+
+
+    set curve [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    
+    if { $mode == "tools" } {
+	set sur      [ vtkPolyData [ pxvtable::vnewobj ] ]
+	catch { set ok [ $vvl_connector GetVVLinkTrackedToolsAsPolyData $sur $vvlink_transform ] }
+	$curve SetFromPoints [ $sur GetPoints ]
+	set line " [ $sur GetNumberOfPoints ] Landmarks from the server"
+	$sur Delete
+    } else {
+	set pts [ vtkPoints [ pxvtable::vnewobj ]]
+	set ok [ $vvl_connector GetVVLabeledPoints $pts $vvlink_transform ]
+        $curve SetFromPoints $pts
+	set line " [ $pts GetNumberOfPoints ] Landmarks from the server"
+	$pts Delete
+    }
+
+    set lcontrol [ $landmarkcontrol GetLandmarkControl ]
+    $lcontrol SetClipboardCollection $curve 1
+
+    ::pxtclutil::Info "Obtained $line. These are stored in the clipboard of the landmark control"
+    
+
+    $curve Delete
+
+    set cur [ $lcontrol GetCollection -1 ]
+    $cur Update
+
+    $landmarkcontrol ShowWindow
+    return 1
+}
+
+itcl::body pxitclvvlinkgadget::VVLinkGetTrajectoryPointsOrTools { mode } {
+	
+
+    if { $vvlink_connected == 0  || $vvlink_transform == 0 } {    
+	::pxtclutil::Warning "Either VVLink is not connected or current transform is not valid! (Most likely you need to transfer an image first.)"
+	return 0
+    }
+
+    set  landmarkcontrol [ $this GetLandmarkControl ]
+   
+    if { $landmarkcontrol ==0 } {
+	return
+    }
+
+    set curve [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    
+
+	set pts [ vtkPoints [ pxvtable::vnewobj ]]
+	# set ok [ $vvl_connector GetVVTrajectoryPoints $pts $vvlink_transform ]
+	puts "in gettrajectory 1"
+	
+	catch { set ok [ $vvl_connector GetVVTrajectoryPoints $pts $vvlink_transform ] }
+
+        $curve SetFromPoints $pts
+	
+	puts "in gettrajectory 2"
+	
+	set line " [ $pts GetNumberOfPoints ] Landmarks from the server"
+	$pts Delete
+
+
+    set lcontrol [ $landmarkcontrol GetLandmarkControl ]
+    $lcontrol SetClipboardCollection $curve 1
+
+    ::pxtclutil::Info "Obtained $line. These are stored in the clipboard of the landmark control"
+
+    $curve Delete
+
+    set cur [ $lcontrol GetCollection -1 ]
+    $cur Update
+
+    $landmarkcontrol ShowWindow
+    return 1
+}
+
+# -------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::ShowHideCone { } { 
+
+    set a [ $vv_pointeractor(3) GetVisibility ]
+    for { set i 0 } { $i <=3 } { incr i } {
+	$vv_pointeractor($i) SetVisibility [ expr 1-$a ]
+    }
+    if { [ $vtk_viewer IsA "vtkpxGUIOrthogonalViewer" ] ==1 } {
+	 $vtk_viewer UpdateDisplay
+    }
+}
+
+::itcl::body pxitclvvlinkgadget::PointerColor { } {
+
+    if { $vv_pointeractor(3) == 0 } {
+	return
+    }
+
+    set c [ [ $vv_pointeractor(3) GetProperty ] GetColor ]
+    set conecolor [ pxtclutil::ColorBox "Set Active Cone display color" $c $basewidget ]
+
+    for { set i 0 } { $i <=3 } { incr i } {
+	[ $vv_pointeractor($i) GetProperty ] SetColor [ lindex $conecolor 0 ] [ lindex $conecolor 1 ] [ lindex $conecolor 2 ]
+	$vv_pointeractor($i) Modified
+    }
+    $vtk_viewer UpdateDisplay
+}
+# ---------------------------------------------------------------------------
+::itcl::body pxitclvvlinkgadget::TipColor { index } {
+
+    if { $vv_pointeractor($index) == 0 } {
+	return
+    }
+
+    set c [ [ $vv_pointeractor($index) GetProperty ] GetColor ]
+    set conecolor [ pxtclutil::ColorBox "Set Active Cone display color" $c $basewidget ]
+    
+    [ $vv_pointeractor($index) GetProperty ] SetColor [ lindex $conecolor 0 ] [ lindex $conecolor 1 ] [ lindex $conecolor 2 ]
+    $vv_pointeractor($index) Modified
+
+#    for { set i 0 } { $i <=3 } { incr i } {
+#	[ $vv_pointeractor($i) GetProperty ] SetColor [ lindex $conecolor 0 ] [ lindex $conecolor 1 ] [ lindex $conecolor 2 ]
+#	$vv_pointeractor($i) Modified
+#    }
+    $vtk_viewer UpdateDisplay
+}
+
+# ---------------------------------------------------------------------------
+::itcl::body pxitclvvlinkgadget::EnablePointerControls {  } {
+
+    set showcross_local $thisparam($this,showcross)
+    if { $showcross_local == 1 } {
+	EnableUI $thisparam($this,pointerlist)
+    } else { 
+    	DisableUI $thisparam($this,pointerlist)
+    }    
+}
+# ---------------------------------------------------------------------------
+
+
+itcl::body pxitclvvlinkgadget::VVLinkRotateCamera { cx cy cz } {
+
+    if { $oldCenter(x) == "" || $oldCenter(y) == "" } {
+	set oldCenter(x) $cx
+	set oldCenter(y) $cy
+    }
+    
+    set ren [ $vtk_viewer GetRenderer 3 ] 
+
+    if { [ expr abs($oldCenter(x) - $cx) ] > 1  } {
+	$ren Rotate [ expr $oldCenter(x) - $cx * .001 ] 0
+    }
+
+    if { [ expr abs($oldCenter(y) - $cy) ] > 1 } {
+	$ren Rotate [ expr $oldCenter(x) - $cx * .001 ] 1
+    }
+    
+    set oldCenter(y) $cy ; set oldCenter(x) $cx 
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::VVLinkMoveCamera { bx by bz tx ty tz } {
+
+
+    set cam [ [ [ $vtk_viewer GetRenderer 3 ] GetRenderer ] GetActiveCamera ]
+    set ren [ [ $vtk_viewer GetRenderer 3 ] GetRenderer ]
+#     if { $sphere1 == 0 } {
+# 	for { set i 1 } { $i <=2 } { incr i } {
+# 	    set sphere($i) [ vtkSphereSource New ]
+# 	    set map($i) [ vtkPolyDataMapper New ]
+# 	    $map($i) SetInput [ $sphere($i) GetOutput ]
+# 	    set act($i) [ vtkActor New ]
+# 	    $act($i) SetMapper $map($i)
+# 	    $ren AddActor $act($i)
+# 	}
+# 	[ $act(1) GetProperty ] SetColor 1 0 0
+# 	[ $act(2) GetProperty ] SetColor 0 1 0
+# 	set sphere1 $sphere(1)
+# 	set sphere2 $sphere(2)
+# 	$sphere1 SetRadius 2
+# 	$sphere2 SetRadius 1
+#     }
+    
+#     $sphere1 SetCenter $bx $by $bz
+#     $sphere2 SetCenter $tx $ty $tz
+    
+#  get scalevalue 
+   set rollangle_local $thisparam($this,rollangle)
+   $cam SetRoll $rollangle_local  
+		
+   set diffx [ expr  pow($oldtx  - $tx, 2) ]
+   set diffy [ expr  pow($oldty  - $ty, 2) ]
+   set diffz [ expr  pow($oldtz  - $tz, 2) ]
+    
+   set tip_difference [ expr sqrt($diffx + $diffy + $diffz) ] 
+    
+   if { $tip_difference < 2.0 } {
+   	return; 
+   }
+    
+    set scalevalue [ $cam GetParallelScale ]
+    $cam SetPosition $bx $by $bz
+    $cam SetFocalPoint $tx $ty $tz
+  
+
+    if { $thisparam($this,inline) == 2 } {
+	set dirvector [ $cam GetDirectionOfProjection ] 
+	$cam Azimuth -45.0 
+    }
+    if { $thisparam($this,inline) == 3 } {
+	set dirvector [ $cam GetDirectionOfProjection ] 
+	$cam Azimuth 45.0 
+    }
+
+    set oldtx $tx 
+    set oldty $ty 
+    set oldtz $tz
+
+     
+    $ren ResetCamera
+
+#  set scalevalue 
+    $cam SetParallelScale $scalevalue
+   
+    #$cam SetFocalPoint [ expr $tip(0)+ [lindex $nrm 0]]  [ expr $tip(1) + [lindex $nrm 1]] [ expr $tip(2) + [lindex $nrm 2]] 
+    
+
+		
+
+}
+# ---------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::OnPoint { tip0 tip1 tip2 pt0 pt1 pt2 } {
+
+    #puts "DIFF=-===[ expr $tip0 - $pt0 * 0.86 ] [ expr $tip1 - $pt1 * 0.86 ] [ expr $tip2 - $pt2 * 2]"
+    set magnitude_pt [ expr sqrt(pow(($tip0 - $pt0 * 0.86),2) + pow(($tip1 - $pt1 * 0.86),2) + pow(($tip2 - $pt2 * 2),2)) ] 
+    puts "Distance = $magnitude_pt"
+
+    if { $magnitude_pt < 3  } {
+	set go 1
+	return 1
+    } else {
+	return 0 
+    }
+}
+
+itcl::body pxitclvvlinkgadget::VVLinkGetToolCoordinates { mode } {
+
+    if { $vvlink_connected == 0 || $vtk_viewer == 0  || $vvlink_transform == 0 } {    
+	::pxtclutil::Warning "Either VVLink is not connected or current transform is not valid! (Most likely you need to transfer an image first.)"
+	return 0
+    }
+
+    if { $mode == 1 } { 
+	set thisparam($this,vvlink_keepgettingcursor) 1
+	DisableUI $thisparam($this,linkofflist)
+	EnableUI $thisparam($this,linkonlist)
+	for { set i 0 } { $i <=3 } { incr i } {
+	    [ $vv_pointeractor($i) GetProperty ] SetColor 0 1 0
+	}
+    } elseif { $mode == 2 } {
+	set thisparam($this,vvlink_keepgettingcursor) 0
+	DisableUI $thisparam($this,linkonlist)
+	EnableUI $thisparam($this,linkofflist)
+    } 
+
+    if { $thisparam($this,vvlink_keepgettingcursor) ==0 } {
+	for { set i 0 } { $i <=3 } { incr i } {
+	    [ $vv_pointeractor($i) GetProperty ] SetColor 0.8 0.8 0.8
+	}
+    }
+    
+    if { $mode ==1 || $mode == 0 } {
+	
+	if { $vvlink_transform !=0 } {
+	    $internaltransform Identity
+	    $internaltransform Concatenate $vvlink_transform
+	}
+	
+	if { $thisparam($this,coneextension) == "" } {
+	    set thisparam($this,coneextension) 0
+	}
+	set ok [ $vvl_connector GetAndDrawVVLinkPointer $internalpoints $internaltransform $thisparam($this,conelength) $thisparam($this,coneradius) $thisparam($this,coneextension) $vv_pointersource(3) $vv_pointersource(4) $vv_pointersource(5) ]
+	
+	if { $ok ==1 } {
+	
+	    if { $thisparam($this,updateviewer) == 1 } {
+ 		
+ 		# Get vv_pointersource(3) values before changing it from cone to cylinder or vice versa. 
+ 		set cheight [ $vv_pointersource(3) GetHeight ] 
+		set cradius [ $vv_pointersource(3) GetRadius ] 
+		set ccenter [ $vv_pointersource(3) GetCenter ] 
+		set cnormal [ $vv_pointersource(3) GetDirection ] 
+  			
+	    	if { $thisparam($this,cylinderenabled) == 1 } {
+		    	set vv_pointersource(3) [ vtkbisCylinderSource [ pxvtable::vnewobj]]
+	    	} else {
+		    	set vv_pointersource(3) [ vtkConeSource [ pxvtable::vnewobj] ]
+	    	}
+	    	
+	    	# Set parameters for Cone/Cylinder 
+	    	$vv_pointersource(3) SetHeight $cheight
+	    	$vv_pointersource(3) SetRadius $cradius
+		$vv_pointersource(3) SetCenter [ lindex $ccenter 0 ] [ lindex $ccenter 1 ] [ lindex $ccenter 2 ]
+	    	$vv_pointersource(3) SetDirection [ lindex $cnormal 0 ] [ lindex $cnormal 1 ] [ lindex $cnormal 2 ]
+	    	$vv_pointersource(3) Update
+	    	
+	    	set pmapper [ $vv_pointeractor(3) GetMapper ]
+		$pmapper SetInput [ $vv_pointersource(3) GetOutput ] 
+
+		$vv_pointeractor(3) SetMapper $pmapper
+		$vv_pointeractor(3)  VisibilityOn
+
+		set cnt [ $vv_pointersource(3) GetCenter ]
+		set len [ $vv_pointersource(3) GetHeight ]
+		set nrm [ $vv_pointersource(3) GetDirection ]
+
+		$vv_pointersource(4) Update
+		$vv_pointeractor(4)  VisibilityOff
+
+		set crosslength_local $thisparam($this,crosslength) 
+		$vv_pointersource(5) SetLength  $crosslength_local
+		set crossthickness_local $thisparam($this,crossthickness)
+		$vv_pointersource(5) SetThickness  $crossthickness_local
+		set showsphere_local $thisparam($this,showsphere)
+		$vv_pointersource(5) SetShowSphere $showsphere_local 
+		set showcross_local $thisparam($this,showcross)
+		
+		# [ $vv_pointeractor(5) GetProperty ] SetOpacity $thisparam($this,crossthickness)
+		
+		$vv_pointeractor(5) SetVisibility $showcross_local
+		$vv_pointersource(5) Update
+
+		set tip(0) "error"
+
+		catch { 
+		    for { set i 0 } { $i <=2 } { incr i } {
+			set tip($i)  [ expr [ lindex $cnt $i ] + 0.5* $len * [ lindex $nrm $i ] ]
+			set base($i)  [ expr $tip($i) - 1 * [ lindex $nrm $i ] ]
+		    }
+		}
+
+		if { $tip(0) != "error" } {
+
+		    # [ $vv_pointeractor($i) GetProperty ] SetColor 0 1 0
+
+		    for { set i 0 } { $i <=2 } { incr i } {
+			$vv_pointersource($i) SetPosition $tip(0) $tip(1) $tip(2)
+			$vv_pointersource($i) SetLength [ expr 2.0*$thisparam($this,coneradius)]
+			$vv_pointersource($i) Modified
+			$vv_pointeractor($i)  VisibilityOn
+			$vv_pointersource($i) Update
+		    }
+		    
+		    if { [ $internalpoints GetNumberOfPoints ] >= 2 } {
+			set px [ lindex [ $internalpoints GetPoint 0 ] 0 ]
+			set py [ lindex [ $internalpoints GetPoint 0 ] 1 ]
+			set pz [ lindex [ $internalpoints GetPoint 0 ] 2 ]
+			catch { $vtk_viewer SetScaledCoordinates $px $py $pz 0 }
+		    }
+		}
+		
+				    
+		if { $thisparam($this,inline) > 0 && $tip(0) != "error" } {
+		    
+		    #$this VVLinkRotateCamera [ lindex $cnt 0 ] [ lindex $cnt 1 ] [ lindex $cnt 2 ]
+		    $this VVLinkMoveCamera $base(0) $base(1) $base(2) $tip(0) $tip(1) $tip(2) 
+		}
+            
+        if { $vvlink_projector != 0 } {
+            $vvlink_projector Update $tip(0) $tip(1) $tip(2) [lindex $nrm 0] [lindex $nrm 1] [lindex $nrm 2]
+        }
+		
+		if { $igtlconnector != 0 && $igtlconnected == 1 } {
+		    if { $thisparam($this,openigtlenablecursor) == 1 } {
+			$this OpenIGTLinkSendTool $internalpoints
+		    }
+		}
+	    }
+	} else {
+	    for { set i 0 } { $i <= 4 } { incr i } {
+		$vv_pointeractor($i)  VisibilityOff
+		$vtk_viewer UpdateDisplay
+	    }
+
+	}		
+	
+	if { $thisparam($this,vvlink_keepgettingcursor) == 1 }  {
+	    #	puts stderr "after $thisparam($this,tooldelay) $this VVLinkGetToolCoordinates 0"
+	    eval "after $thisparam($this,tooldelay) $this VVLinkGetToolCoordinates 0"
+	}
+    }
+}
+
+itcl::body pxitclvvlinkgadget::crossProduct { list1 list2 }  {
+
+    set returnList [ list ]
+    
+    lappend returnList [ expr [ lindex $list1 1 ] * [ lindex $list2 2 ] - [ lindex $list1 2 ]  * [  lindex $list2 1 ] ]
+    lappend returnList [ expr [ lindex $list1 2 ] * [ lindex $list2 0 ] - [ lindex $list1 0 ]  * [  lindex $list2 2 ] ]
+    lappend returnList [ expr [ lindex $list1 0 ] * [ lindex $list2 1 ] - [ lindex $list1 1 ]  * [  lindex $list2 0 ] ]
+
+    return $returnList
+}
+
+# ---------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::VVLinkAcquireLandmark { } {
+
+    set  landmarkcontrol [ $this GetLandmarkControl ]
+
+    if { $vvlink_connected == 0 || $vtk_viewer == 0  || $vvlink_transform == 0  || $landmarkcontrol == 0 } {    
+	::pxtclutil::Warning "Either VVLink is not connected or current transform is not valid! (Most likely you need to transfer an image first.)"
+	return 0
+    }
+
+    set m [ vtkTransform [ pxvtable::vnewobj ]]
+    if { $vvlink_transform !=0 } {
+	$m Identity;
+	$m Concatenate $vvlink_transform
+    }
+	
+    set pts [ vtkPoints [ pxvtable::vnewobj ]]
+
+    set ok [ $vvl_connector GetVVLinkPointer $pts $m 1.0 ]
+    
+    if { [ $pts GetNumberOfPoints ] >= 2 } {
+	set px [  lindex [  $pts  GetPoint 0 ] 0 ]
+	set py [  lindex [  $pts  GetPoint 0 ] 1 ]
+	set pz [  lindex [  $pts  GetPoint 0 ] 2 ]
+	catch { $vtk_viewer SetScaledCoordinates $px $py $pz 0 }
+	[ $landmarkcontrol GetLandmarkControl ]  HandleClickedPoint $px $py $pz 1 2
+    }
+    
+    $pts Delete
+    $m Delete
+}
+
+# ---------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::VVLinkSaveLabeledPointsOrTools { mode args } {
+
+    if { $vvlink_connected == 0  || $vvlink_transform == 0 } {    
+	::pxtclutil::Warning "Either VVLink is not connected or current transform is not valid! (Most likely you need to transfer an image first.)"
+	return 0
+    }
+
+
+    set fname ""
+    set len [ llength $args ]
+    if { $len > 0 } {
+	set fname [ lindex $args 0 ]
+    }
+    
+    set name "Labeld Points"
+    if { $mode == "tools" } {
+	set name "Tracked Tools"
+    }
+
+    if { $fname == "auto" } {
+	set fname [ clock format [ clock seconds ] -format "%H%M%S_%d%b%Y" ]
+	set fname "tools_${fname}.txt"
+    } elseif { [ string length $fname  ] == 0  } {
+	set fname  [tk_getSaveFile -title "Saving $name in Text File"  -filetypes { {"Text Files" {*.txt}} { "All Files" {*.*}} } ]
+    }
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+    
+    set ok 0
+    if { $mode == "tools" } {
+	set dt [ clock format [ clock seconds ] -format "%H %M %S on %d %b %Y" ]
+	catch { set ok [ $vvl_connector SaveVVLinkTrackedTools $fname $vvlink_transform $dt ] }
+    } else {
+	catch { set ok [ $vvl_connector SaveVVLinkLabeledPoints $fname $vvlink_transform ] }
+    }
+
+    if { $ok == 0 } {
+	::pxtclutil::Warning "Failed to save $name in $fname"
+    } elseif { $mode == "tools" } {
+	pxtkconsole
+	pxtkprint "Tools Saved in $fname\n"
+    }
+    return $ok
+}
+
+# -------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::VVLinkGetLabeledPointsOrToolsAsSurface { mode } {
+
+    if { $vvlink_connected == 0  || $vvlink_transform == 0 } {    
+	::pxtclutil::Warning "Either VVLink is not connected or current transform is not valid! (Most likely you need to transfer an image first.)"
+	return 0
+    }
+
+    set pts [ vtkPoints [ pxvtable::vnewobj ]]
+
+    set ok [ $vvl_connector GetVVLabeledPoints $pts $vvlink_transform ]
+    
+    set  polydatacontrol [ $this GetPolyDataControl ]
+    
+    if { $polydatacontrol ==0 } {
+	$pts Delete
+	return
+    }
+
+    set pcontrol [ $polydatacontrol GetPolyDataControl ]
+    set sur      [ vtkPolyData [ pxvtable::vnewobj ] ]
+
+    if { $mode == "tools" } {
+	catch { set ok [ $vvl_connector GetVVLinkTrackedToolsAsPolyData $sur $vvlink_transform ] }
+    } else {
+	catch { set ok [ $vvl_connector GetVVLinkLabeledPointsAsPolyData $sur $vvlink_transform ] }
+    }
+
+    [ $polydatacontrol GetPolyDataControl ]  SetClipboardSurface $sur "vvlink_${mode}.vtk"
+    ::pxtclutil::Info "Obtained [ $sur GetNumberOfPoints ]. These are stored in the clipboard of the surface control"
+
+    $polydatacontrol ShowWindow
+
+    for { set i 0 } { $i < [ $sur GetNumberOfPoints ] } { incr i } {
+	puts stderr "Point $i [ $sur GetPoint $i ]"
+    }
+    puts stderr "\n"
+
+    $sur Delete
+    return 1
+}
+
+
+
+# ---------------------------------------------------------------------------
+# Load and Save Setup Files
+# ---------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::SaveSetup { args } { 
+
+    set len [ llength $args ]
+    
+    if { $len < 1 } {
+	set fname $setupfilename 
+    } else {
+	set fname [ lindex $args 0 ]
+    }
+
+
+    if { [ string length $fname  ] == 0  } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname  [tk_getSaveFile -title "Saving Setup File"  -initialfile $f1tail -initialdir $f1path ]
+    }
+
+    if { [ string length $fname ] > 0 } {
+
+	set fileid [open $fname w]
+	
+	puts $fileid "#VVLINK Host Description File"
+	puts $fileid "#---------------------------------------------"
+
+	set len [ $thisparam($this,servermenu) index last ]
+	#	puts stdout "Number of Servers [ expr $len+1 ]"
+	for { set i 0 } { $i <= $len } { incr i } {
+	    puts $fileid [ $thisparam($this,servermenu) entrycget $i -label ]
+	}
+	close $fileid
+
+    }
+}
+# ------------------------------------------------------------------------------------------ 
+itcl::body pxitclvvlinkgadget::VVLinkServerAdd { mode } {
+
+
+    if { $addserver_gui == 0 && $mode != 0 } {
+	return
+    }
+
+    if { $addserver_gui == 0 } {
+
+	set thisparam($this,newserverdescription) "Server Description"
+	set thisparam($this,newserverhostname) "localhost"
+	set thisparam($this,newserverpassword) "111111"
+
+	set addserver_gui  [ toplevel $basewidget.[ pxvtable::vnewobj ]]
+	eval "wm protocol $addserver_gui WM_DELETE_WINDOW { wm withdraw $addserver_gui }"
+    	
+	wm title $addserver_gui "Define New VVLink Server"
+	
+	set w $addserver_gui
+
+	iwidgets::entryfield $w.0 -labeltext "Description:"  -width 20  -textvariable [ itcl::scope thisparam($this,newserverdescription) ] -relief sunken 
+	iwidgets::entryfield $w.1 -labeltext "Hostname:"  -width 20  -textvariable [ itcl::scope thisparam($this,newserverhostname) ] -relief sunken 
+	iwidgets::entryfield $w.2 -labeltext "Password:"  -width 20  -textvariable [ itcl::scope thisparam($this,newserverpassword) ] -relief sunken 
+	eval "button $w.3  -text \"Add Server\" -command { $this VVLinkServerAdd 1 }" 
+	pack $w.3 -side bottom -expand true -fill x
+	pack $w.0 $w.1 $w.2 -side top -expand true -fill x
+
+    }
+
+    if { $mode == 0 } {
+	wm deiconify $addserver_gui
+	return
+    }
+
+    set a $thisparam($this,newserverdescription) 
+    set b $thisparam($this,newserverhostname)
+    set c $thisparam($this,newserverpassword)
+
+    wm withdraw $addserver_gui
+    set line "${a}:${b}:${c}"
+    $thisparam($this,servermenu) add radio  -label $line  -variable [ itcl::scope thisparam($this,vvlinkserver) ]
+}
+
+# ------------------------------------------------------------------------------------------ 
+itcl::body pxitclvvlinkgadget::LoadSetup { args } { 
+
+    set len [ llength $args ]
+    
+    if { $len < 1 } {
+	set fname $setupfilename 
+    } else {
+	set fname [ lindex $args 0 ]
+    }
+
+    if { [ string length $fname  ] == 0 } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	
+	set fname  [tk_getOpenFile -title "Setup File" -filetypes { {"VVLink-Setup File" {*}}} -initialfile $f1tail -initialdir $f1path ]
+    }
+
+    if { [ string length $fname ] < 1 } {
+	return
+    }
+
+    if { [ file readable $fname ] == 0 } {
+	::pxtclutil::Warning "Cannot read setupfile file from $fname\n Bad File"
+	return 0
+    }
+
+    set fileid [open $fname r]
+	
+    gets $fileid line
+    if { [ string compare $line "#VVLINK Host Description File"  ] != 0 } {
+	close $fileid
+	::pxtclutil::Warning "Cannot read setupfile file from $fname\n Bad File Type"
+	return 0
+    }
+
+    set len [ $thisparam($this,servermenu) index last ]
+    $thisparam($this,servermenu) delete 0 $len
+    set count 0 
+    while { [ gets $fileid line ] >=0 } {
+	if { [  string range $line 0 0 ] != "\#" } {
+	    $thisparam($this,servermenu) add radio  -label $line  -variable [ itcl::scope thisparam($this,vvlinkserver) ]
+	    if { $count == 0 } {
+		set thisparam($this,vvlinkserver) $line
+	    }
+	    incr count
+	}
+    }
+    close $fileid
+    set setupfilename $fname
+
+
+}
+#--------------------------------------------------------------------------------------------
+#  Point Parser
+#--------------------------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkgadget::ParseLogFile { filename } {
+
+    if { $filename == "" } { set filename  [tk_getOpenFile -title "Log File" -filetypes { {"Log Files" {*.log}} { "All Files" {*.*}} } -initialdir [ file dirname $vvlink_logfilename] -initialfile [ file tail $vvlink_logfilename ] ] }
+    if { [ string length $filename ] < 1 } { return 0  }
+    if { [ file readable $filename ] == 0 } { return 0 }
+
+    set header "ZTouch-point Registrar"
+    set fileid [open $filename r]
+    set vvlink_ztouchpointlost ""
+    set count 0
+    while { [ gets $fileid line ] >=0 } {
+	set findex [ string first $header $line ]
+	if { $findex >=0 } {
+	    gets $fileid np
+	    lappend vvlink_ztouchpointlost [ list $np $line $count ]
+	    incr count
+	}
+	incr count
+    }
+    close $fileid
+
+    if { [ llength $vvlink_ztouchpointlost ] == 0 } {
+	::pxtclutil::Warning "No ZTouch Points Found In Log File $filename"
+	return 0
+    }
+
+    set vvlink_logfilename $filename
+    $thisparam($this,vvztouchpointlist)  delete 0 end
+
+    for { set i 0 } { $i < [ llength $vvlink_ztouchpointlost ] } { incr i } {
+	set m [ lindex $vvlink_ztouchpointlost $i ]
+	#	puts stdout "Set $i: $m"
+	$thisparam($this,vvztouchpointlist) insert end $m
+    }
+
+    $thisparam($this,vvztouchpointlist) selection clear 0 0
+    $thisparam($this,vvztouchpointlist) selection set   0 0
+
+     
+    return 1
+}
+
+# ------------------------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkgadget::ParseRegistrationIni { filename  } {
+    
+#    if { $filename == "" } { set filename  [ tk_getOpenFile -title "Ini File" -filetypes { {"Ini Files" {*.ini}}} ] }
+
+    if { $filename == "" } { set filename  [tk_getOpenFile -title "Registration Ini File" -filetypes { {"Ini Files" {*.ini}} { "All Files" {*.*}} } -initialdir [ file dirname $vvlink_logfilename] -initialfile Registration.ini ] }
+
+    if { [ string length $filename ] < 1 }  {	return 0 }
+    if { [ file readable $filename ] == 0 } {	return 0 }
+    
+    set header  "VVCranialENTztouch"
+    set header2 "RefToWorldTransformation="
+    set fileid [open $filename r]
+    set vvlink_xformlist ""
+
+    set foundend 0
+    while { [ gets $fileid line ] >=0 && $foundend == 0 } {
+
+	if { [ string first $header $line ] >=0 } {
+	    set found2 0
+	    while { [ gets $fileid line ] >=0 && $foundend == 0 } {
+		if {  [ string first $header2 $line ] >=0 } {
+		    
+		    gets $fileid line2
+		    gets $fileid line3
+		    lappend vvlink_xformlist [ list $line3 $line2 $line ]
+		    set found2 1
+		}
+	    }
+	    
+	    if { $found2 == 0 } {
+		set foundend 1
+	    }
+	}
+    }
+    close $fileid
+
+    $thisparam($this,vvztouchxformlist)  delete 0 end
+
+    for { set i 0 } { $i < [ llength $vvlink_xformlist ] } { incr i } {
+	set m [ lindex $vvlink_xformlist $i ]
+	#	puts stdout "Set $i: $m"
+	$thisparam($this,vvztouchxformlist) insert end $m
+	# puts stdout "i=$i, xform=$m"
+    }
+
+    $thisparam($this,vvztouchxformlist) selection clear 0 0
+    $thisparam($this,vvztouchxformlist) selection set   0 0
+
+    return 1
+}
+
+itcl::body pxitclvvlinkgadget::RecoverZTouchSurface {  } {
+
+    set pointname [ $thisparam($this,vvztouchpointlist) getcurselection ]
+    set xformname [ $thisparam($this,vvztouchxformlist) getcurselection ]
+
+    if { $pointname == "" || $xformname == "" } {
+	::pxtclutil::Warning "Cannot reconstruct ztouch surface\n pointname=$pointname\n xformname=$xformname"
+	return 0
+    }
+
+    set lineindex [ lindex $pointname 2 ]    
+    pxtkconsole
+    pxtkprint "\nReconstructing ztouch surface\n pointname=$pointname ($lineindex), xformname=$xformname\n"
+
+
+    # Step 1 Get Points
+    #
+
+
+    set fileid [open $vvlink_logfilename r ]
+    for { set i 0 } { $i <= $lineindex } { incr i } {
+	gets $fileid line
+    }
+    
+    set numpoints 0
+    gets $fileid numpoints
+
+    pxtkprint "line=$line, Numpoints = $numpoints"
+    set pts [ vtkPoints [ pxvtable::vnewobj ]]
+    $pts SetNumberOfPoints $numpoints
+    for { set i 0 } { $i < $numpoints } { incr i } {
+	gets $fileid line
+	scan $line "%f %f %f %f %f %f" dx dy dz x y z
+	$pts SetPoint $i $x $y $z
+	pxtkprint "Point $i = ($x $y $z)\n"
+    }
+    close $fileid
+
+    # Step 2 Form Transformation 
+    set xformline [ lindex $xformname 2 ]
+    set ind [ string first "=" $xformline ]
+    set xformline [ string range $xformline [expr 1+ $ind ] end ]
+    
+    set xform  [ split $xformline , ]
+    
+    pxtkprint "\nxform ( [ llength $xform ] ) = $xform\n"
+
+    set mat [ vtkMatrix4x4 [ pxvtable::vnewobj ]]
+    set count 0
+    for { set row 0 } { $row <= 3 } { incr row } {
+	pxtkprint "  "
+	for { set column 0 } { $column <= 3 } { incr column } {
+	    $mat SetElement $row $column [ lindex $xform $count ]
+	    set m [ $mat GetElement $row $column ]
+	    set line [ format "%6.3f " $m ]
+	    incr count
+	    pxtkprint $line
+	}
+	pxtkprint "\n"
+    }
+
+    # Ref to World
+    # Image to World
+
+    set sur [ vtkPolyData [ pxvtable::vnewobj ]]
+    $sur SetPoints $pts
+    $pts Delete
+
+    set tr [ vtkTransform [ pxvtable::vnewobj ]]
+    $tr Identity
+    $tr PostMultiply
+    $tr Concatenate $mat ; $mat Delete
+    catch { $tr Concatenate [ $vvlink_transform GetLinearInverse ] }
+    
+    set trf [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ]]
+    $trf SetInput $sur;    $sur Delete
+    $trf SetTransform $tr; $tr Delete
+    $trf Update
+
+    #    puts stderr [ [ $trf GetOutput ] GetBounds ]
+
+#     set recon [ vtkSurfaceReconstructionFilter [ pxvtable::vnewobj ] ]
+#     $recon SetInput [ $trf GetOutput ]
+#     $recon DebugOn
+
+#     $recon Update
+
+#     set skinExtractor [ vtkContourFilter [ pxvtable::vnewobj ] ]
+#     $skinExtractor SetUseScalarTree 0
+#     $skinExtractor ComputeScalarsOff
+#     $skinExtractor ComputeGradientsOff
+#     $skinExtractor SetInput [  $recon GetOutput ] 
+#     $skinExtractor SetValue 0 0.0
+#     $skinExtractor Update
+
+
+#    $trf Delete
+
+    set  landmarkcontrol [ $this GetLandmarkControl ]
+    
+    if { $landmarkcontrol ==0 } {
+	$trf Delete
+	return
+    }
+
+    set lcontrol [ $landmarkcontrol GetLandmarkControl ]
+    set curve [ vtkpxBaseCurve [ pxvtable::vnewobj ]]
+    $curve SetFromPoints [ [ $trf GetOutput ] GetPoints ]
+    $lcontrol SetClipboardCollection $curve 1
+
+    ::pxtclutil::Info "Obtained [ [ $trf GetOutput ] GetNumberOfPoints ] Landmarks from the server. These are stored in the clipboard of the landmark control"
+    
+    $trf Delete
+    $curve Delete
+
+    set cur [ $lcontrol GetCollection -1 ]
+    $cur Update
+
+    $landmarkcontrol ShowWindow
+
+    #    set  polydatacontrol [ $this GetPolyDataControl ]
+    
+    #     if { $polydatacontrol !=0 } {
+    # 	[ $polydatacontrol GetPolyDataControl ]  SetClipboardSurface [ $trf GetOutput ] "ztouch_recon.vtk"
+    # 	::pxtclutil::Info "Obtained [ [ $trf GetOutput ] GetNumberOfPoints ] from z-touch points. These are stored in the clipboard of the surface control"
+    # 	$polydatacontrol ShowWindow
+    #     }
+
+    #    $skinExtractor Delete
+    #   $recon Delete
+    return 1
+}
+
+# -------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::PredictElectrodeStrip { } {
+
+    
+    set  polydatacontrol [ [ $this GetPolyDataControl ] GetPolyDataControl ]
+    set  landmarkcontrol [ [ $this GetLandmarkControl ] GetLandmarkControl ]
+    
+    set tempc_lv [ vtkpxBaseCurve [ pxvtable::vnewobj ]] 
+    $tempc_lv Copy  [ $landmarkcontrol GetCollection -1 ]
+    $tempc_lv Compact
+    set pts [ $tempc_lv GetPoints ]
+
+    set nc [ $pts GetNumberOfPoints ]
+    if { $nc < 2 } {
+	::pxtclutil::Warning "Not Enough Points ($nc) in seed point set. Need at least 2 seed points to predict electrode strip position"
+	return 0
+	catch { $tempc_lv Delete }
+    }
+    
+    set sur  [  $polydatacontrol  GetSurface [ expr $thisparam($this,stripbrainsurface) - 1 ] ]
+    set np [ $sur GetNumberOfPoints ]
+    if { $np < 1000 } {
+	::pxtclutil::Warning "Not Enough Points ($np) on Selected Brain Surface ( $thisparam($this,stripbrainsurface). Cannot predict electrode strip position"
+	return 0
+    }
+    
+    set pred [ vtkpxPredictElectrodeStrip  [ pxvtable::vnewobj ]]
+    $pred SetInputSurface $sur
+    $pred SetStep   $thisparam($this,stripstep)
+    $pred SetLength $thisparam($this,striplength)
+    $pred SetSmoothness $thisparam($this,stripsmoothness)
+
+    set thisparam($this,stripsmoothness) [ $pred GetSmoothness ]
+    set thisparam($this,stripstep)       [ $pred GetStep ]
+    set thisparam($this,striplength)     [ $pred GetLength ]
+
+    set offset $thisparam($this,striplandmarkoffset)  
+    if { $offset < 0  || $offset > [ expr $nc -2 ] } {
+	set offset [ expr $nc -2 ]
+    } 
+
+    set p1 [ $pts GetPoint $offset ] 
+    set p2 [ $pts GetPoint [ expr $offset +1 ]]
+    
+    $pred SetPoint1 [ lindex $p1 0 ] [ lindex $p1 1 ] [ lindex $p1 2 ]
+    $pred SetPoint2 [ lindex $p2 0 ] [ lindex $p2 1 ] [ lindex $p2 2 ]
+    $pred Update
+
+    $polydatacontrol SetClipboardSurface [ $pred GetOutput ] "predicted.vtk"
+    ::pxtclutil::Info "Create strip polygon with [ [ $pred GetOutput ] GetNumberOfPoints ]. These are stored in the clipboard of the surface control"
+    
+    [ $this GetPolyDataControl ] ShowWindow
+
+    catch { $tempc_lv Delete ; $pts Delete }
+    $pred Delete
+    return 1
+}
+
+
+#--------------------------------------------------------------------------------------------
+#
+#          GUI Stuff
+#
+#--------------------------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkgadget::ShowControl { mode }  {
+
+    if { $mode == "landmark" } {
+	set  landmarkcontrol [ $this GetLandmarkControl ]
+	if { $landmarkcontrol !=0 } {
+	    $landmarkcontrol ShowWindow
+	}
+    } elseif { $mode == "surface" } {
+	set  polydatacontrol [ $this GetPolyDataControl ]
+	if { $polydatacontrol !=0 } {
+	    $polydatacontrol ShowWindow
+	}
+    }
+}
+
+
+itcl::body pxitclvvlinkgadget::ShowProjectorControl { }  {
+    if { $vvlink_projector != 0 } {
+        $vvlink_projector ShowWindow
+    }
+}
+
+#--------------------------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkgadget::CreateAboutControl { parent }  {
+
+    $parent configure -bg black
+    set txt [ iwidgets::scrolledtext $parent.st -labeltext "About VectorVisionLink" -vscrollmode dynamic -hscrollmode dynamic -width 5i -height 2i ]
+    pack $parent.st -side top -expand true -fill both -padx 5 -pady 5
+
+    $txt insert end "VVLink is a network based software interface to the VectorVision navigation system that enables researchers and skilled practitioners to download medical images, segmentation results, surgical planning and real-time tool tracking data from the navigation system as well as to upload view content. It was originally developped by Markus Neff (Brainlag AG http://www.brainlab.com) during his stay at Yale Image Processing and Analysis Group (http://noodle.med.yale.edu) \n\n"
+
+    $txt insert end "This tool implements the VVLink interface between the BioImage Suite software suite and VectorVisionCranial.\n\n It was primarily authored by Xenios Papademetris (xenophon.papademetris at yale.edu) with assistance from Sven Flossman of Brainlab.\n\n"
+
+    $txt insert end "The tool also implements an optional OpenIGTLink bridge server developped with the help of Junichi Tokuda and Steve Pieper\n\n"
+
+    $txt insert end "The list of servers to connect is defined in a file .vvlinkservers place in each user's home directory. An example follows:\n\n"
+    $txt insert end "\#VVLINK Host Description File\n\#---------------------------------------------\n\#Host:Password\nOR1:192.168.1.3:7A5F81\nOR2:192.168.1.6:8F10AD\n"
+
+}
+
+
+itcl::body pxitclvvlinkgadget::CreateFeatureControl { parent }  {
+    
+    set base $parent
+    set w1 [ frame $parent.operations ]
+    set w2 [ frame $parent.tools ]
+
+    pack $parent.tools      -side bottom -expand true -fill x
+    pack $parent.operations -side top -expand true -fill both
+
+    eval "button $w1.1  -text \"Get Labeled Points As Landmarks\" -command { $this VVLinkGetLabeledPointsOrTools points }" 
+    eval "button $w1.2  -text \"Get Labeled Points As Surface\" -command { $this VVLinkGetLabeledPointsOrToolsAsSurface points }" 
+    eval "button $w1.3  -text \"Save Labeled Points in Text File \" -command { $this VVLinkSaveLabeledPointsOrTools points  }"
+    frame $w1.4 -bg black -height 5
+    eval "button $w1.51  -text \"Get Tracked Tool Tips As Landmarks\" -command { $this VVLinkGetLabeledPointsOrTools tools }" 
+    eval "button $w1.5  -text \"Get Tracked Tools As Surface\" -command { $this VVLinkGetLabeledPointsOrToolsAsSurface tools }" 
+    eval "button $w1.6  -text \"Save Tracked Tools in Text File \" -command { $this VVLinkSaveLabeledPointsOrTools tools  auto }"
+    frame $w1.7 -bg black -height 5
+    eval "button $w1.8  -text \"Acquire Landmark (Control-L)\" -command { $this VVLinkAcquireLandmark  }"	
+    eval "bind all <Control-l> { $this VVLinkAcquireLandmark } "
+
+    pack $w1.1 $w1.2 $w1.3 $w1.4 $w1.51 $w1.5 $w1.6 $w1.7 $w1.8 -side top -expand false -fill x -padx 10 -pady 2
+
+    eval "button $w2.land  -text \"Landmark Control\" -command { $this ShowControl landmark}"
+    eval "button $w2.poly  -text \"Surface Control\" -command  { $this ShowControl surface }"
+    pack $w2.land $w2.poly -side left -fill x -expand true -padx 5
+    
+    lappend thisparam($this,disconnectlist) $thisparam($this,vvimagelist) $w1
+
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::CreateTrajectoryControl { parent }  {
+    
+    set base $parent
+    set w1 [ frame $parent.operations ]
+    set w2 [ frame $parent.tools ]
+
+    pack $parent.tools      -side bottom -expand true -fill x
+    pack $parent.operations -side top -expand true -fill both
+	
+    #	eval "set nTr [ $vvl_connector GetVVNumberOfTrajectories ]"
+    #	puts stderr "The total number of tr are $nTr"
+    
+    #	if { $vvlink_connected == 1 } {
+    #		label $w45.inlinelabel -text "inline"
+    #   	tk_optionMenu $w45.inline2 [ itcl::scope thisparam($this,inline2) ] 0 
+    #}
+    
+    eval "button $w1.1  -text \"Get Trajectory Points \" -command { $this VVLinkGetTrajectoryPointsOrTools points }"
+    eval "bind all <Control-l> { $this VVLinkAcquireLandmark } "
+    
+    #eval "label $w45.inlinelabel -text \"Number of Trajectories\" -command { $this GetVVNumberOfTrajectories }" 
+    #set nTr { $this GetVVNumberOfTrajectories}
+    #tk_optionMenu $w45.inline [ itcl::scope thisparam($this,inline) ] 0 1 2 3
+    
+    
+    #tk_optionMenu $w45.inline 0 1 2 3
+    #if { $vvlink_connected == 1 } {
+    #	pack $w1.1 $w45.inlinelabel $w45.inline2 -side top -expand false -fill x -padx 10 -pady 2
+    #} else {
+    pack $w1.1 -side top -expand false -fill x -padx 10 -pady 2
+    #}
+    
+
+    eval "button $w2.land  -text \"Landmark Control\" -command { $this ShowControl landmark}"
+    eval "button $w2.poly  -text \"Surface Control\" -command  { $this ShowControl surface }"
+    pack $w2.land $w2.poly -side left -fill x -expand true -padx 5
+    
+    lappend thisparam($this,disconnectlist) $thisparam($this,vvimagelist) $w1 
+
+}
+#--------------------------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkgadget::CreateZTouchControl { parent }  { 
+
+    set base [ frame $parent.a ]
+    $parent configure -bg black 
+    pack $base -side top -expand t -fill both -padx 3 -pady 3
+    
+
+    set w5 [ frame $base.3 ];    pack $w5 -side bottom -expand true -fill x -padx 3 -pady 3
+
+    set thisparam($this,vvztouchpointlist) [ iwidgets::scrolledlistbox $base.1 -labeltext "Z-Touch Point Sets"  -vscrollmode static -hscrollmode dynamic -selectmode single -exportselection 0 -height 1i ]
+
+    
+    set thisparam($this,vvztouchxformlist) [ iwidgets::scrolledlistbox $base.2 -labeltext "Z-Touch Pre-Registrations"  -vscrollmode static -hscrollmode dynamic -selectmode single -exportselection 0 -height 1i ]
+
+    pack $base.1 $base.2 -side top -fill both -expand true -pady 5
+
+    eval "button $w5.a  -text \"Log File\" -command { $this ParseLogFile \"\"  }"
+    eval "button $w5.b  -text \"Reg Ini\" -command { $this ParseRegistrationIni \"\"  }"
+    eval "button $w5.c  -text \"Reconstruct Z-Touch Surface \" -command { $this RecoverZTouchSurface }"
+
+    pack $w5.a $w5.b $w5.c -side left -expand true -padx 3 -pady 2 -fill x 
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::CreateDataSetControl { base }  { 
+    
+    set img_control [ [ pxitclimageGUI \#auto  ] GetThisPointer ]
+    $img_control configure -description "Reference Image"
+    
+    set xform_control [ [  pxitcltransformGUI \#auto ] GetThisPointer ]
+    $xform_control configure -description "Transformation World->Reference"
+
+    $img_control Initialize $base.1
+    $img_control AddFunction "$parent SetImageFromObject" "Display" "$this "
+
+
+    $xform_control Initialize $base.2
+
+    pack $base.1 $base.2 -side top -expand false -fill x -pady 2
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::WarnAboutFlipLeft { } {
+
+    if { $thisparam($this,flipleft) == 0 } {
+	set ok [ pxtclutil::Question "Modifying Image Left/Right Flip is a dangerous operation. Are you sure?" ]
+	if { $ok == 0 } {
+	    set thisparam($this,flipleft) 1
+	}
+    }
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::ShowAdvanced { } {
+
+    if { $advanced_gui == 0 } {
+	return
+    }
+
+    wm deiconify $advanced_gui
+    scan  [ winfo geometry $basewidget ] "%dx%d+%d+%d" w1 h1 x1 y1 
+    catch {
+	set sc [ format "+%d+%d" [ expr $x1+$w1-100 ] [ expr $y1+$h1-100 ] ]
+	eval "wm geometry $advanced_gui $sc"
+    } 
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::OpenIGTLinkConnect {  } {
+
+#    if { $vvlink_connected == 0 } {
+#	return
+#    }
+
+    if { $igtlconnector == 0 } {
+	set igtlconnector [ vtkpxOpenIGTLinkClient [ pxvtable::vnewobj ]]
+    }
+
+    set igtlconnected 0
+    set ok [ $igtlconnector InitializeConnection $thisparam($this,openigtlserver) $thisparam($this,openigtlport) ]
+    if { $ok == 1 } {
+	::pxtclutil::Info "OpenIGTLink Connection to $thisparam($this,openigtlserver) established."
+	set igtlconnected 1
+	EnableUI $thisparam($this,openigtlbase) 
+	set thisparam($this,openigtlstatus) "Connected to $thisparam($this,openigtlserver):$thisparam($this,openigtlport)"
+    } else {
+	::pxtclutil::Warning "OpenIGTLink Connection to $thisparam($this,openigtlserver) failed."
+	set thisparam($this,openigtlstatus) "Disconnected"
+	DisableUI $thisparam($this,openigtlbase) 
+    }
+    
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::OpenIGTLinkDisconnect { } {
+
+    if { $igtlconnector == 0 } {
+	return 0
+    }
+    $igtlconnector CloseConnection
+    set thisparam($this,openigtlenablecursor) 0
+    DisableUI $thisparam($this,openigtlbase) 
+    set thisparam($this,openigtlstatus) "Disconnected"
+}
+
+
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::OpenIGTLinkSendTool { pts } {
+    
+    if { $igtlconnector != 0 && $igtlconnected == 1 } {
+	if {  $thisparam($this,openigtlslicermode)  == 1 } {
+	    set img [ [ $img_control GetImage ] GetImage ]
+	    if { $img != "" } {
+
+		# slicer bug
+		set numtimes 1
+		for { set i 0 } { $i < $numtimes } { incr i } {
+		    $igtlconnector SendToolLocation $pts $img [ expr $thisparam($this,openigtlslicermode)  + $thisparam($this,openigtlslicercentering) ]
+		}
+	    }
+	} else {
+	    ## puts stderr "Sending Raw Points"
+	    $igtlconnector SendToolLocation $pts
+	}
+    }
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::OpenIGTLinkSendImage { } {
+    if { $igtlconnector != 0 && $igtlconnected == 1 } {
+	set img [ [ $img_control GetImage ] GetImage ]
+	if { $img != "" } {
+	    # puts stderr "Good Image for Sending Image\n"
+	    set ok [ $igtlconnector SendImage $img ]
+	}
+    } else {
+	# puts stderr "Bad Connection for Sending Image\n"
+    }
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::OpenIGTLinkSendCrossHairs { } {
+
+    set img [ $vtk_viewer GetImage ]
+    if  { $img == "" } { return }
+
+    if { $igtlconnector != 0 && $igtlconnected == 1 } {
+	set lv  [ $vtk_viewer GetLastClickedPointScaled ]
+	set img [ $vtk_viewer GetImage ]
+	set ptt [ vtkPoints [ pxvtable::vnewobj ]]
+	$ptt SetNumberOfPoints 1
+	$ptt SetPoint 0 [ lindex $lv 0 ] [ lindex $lv 1 ] [ lindex $lv 2 ]
+	# slicer bug
+	set numtimes 1
+	for { set i 0 } { $i < $numtimes } { incr i } {
+	    $igtlconnector SendToolLocation $ptt $img [ expr $thisparam($this,openigtlslicermode)  + $thisparam($this,openigtlslicercentering) ]
+	}
+
+    } else {
+	# puts stderr "Bad Connection for Sending Image\n"
+    }
+}
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::CreateOpenIGTLControl { parent }  {
+
+    entry $parent.2 -width 30  -textvariable [ itcl::scope thisparam($this,openigtlstatus) ] -relief sunken  -bg black -fg white -state disabled
+    pack $parent.2 -side bottom 
+
+    set top  [ LabelFrame:create $parent.a -text "OpenIGTL Server Definition"]
+    set bot  [ LabelFrame:create $parent.b -text "Additional Operations"]
+    pack $parent.a  $parent.b -side top -expand t -fill both -pady 2
+
+
+    iwidgets::entryfield $top.0 -labeltext "OpenIGTL Sever :"  -width 20  -textvariable [ itcl::scope thisparam($this,openigtlserver) ] -relief sunken 
+    iwidgets::entryfield $top.1 -labeltext "OpenIGTL Port  :"  -width 10  -textvariable [ itcl::scope thisparam($this,openigtlport) ] -relief sunken 
+    pack $top.0 $top.1 -side top -expand false -fill x
+
+    set w [ frame $top.mid ]; pack $top.mid -side top -expand false -fill x
+    
+
+    eval "button $w.1  -text \"Connect\" -command { $this OpenIGTLinkConnect }" 
+    eval "button $w.2  -text \"Disconnect\" -command { $this OpenIGTLinkDisconnect }" 
+    pack $w.1 $w.2   -side left -expand true -fill x
+
+
+
+    checkbutton $bot.a -variable [itcl::scope thisparam($this,openigtlenablecursor)]   -text "Enable OpenIGTLink Tool Link"
+    checkbutton $bot.a2 -variable [itcl::scope thisparam($this,openigtlslicermode)]   -text "LPS to RAS Conversion" 
+    checkbutton $bot.a3 -variable [itcl::scope thisparam($this,openigtlslicercentering)]   -text "Slicer Centering" 
+
+    eval button "$bot.b -text \"Send Current Image to OpenIGTLink Server\" -command { $this OpenIGTLinkSendImage }"
+    eval button "$bot.c -text \"Send Cross Hairs OpenIGTLink Server\" -command { $this OpenIGTLinkSendCrossHairs }"
+
+    pack $bot.a $bot.a2 $bot.a3 $bot.b $bot.c -side top -expand false -fill x
+
+    set thisparam($this,openigtlbase) $bot
+    #DisableUI $thisparam($this,openigtlbase) 
+
+}
+
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::CreateServerControl { parent }  {
+
+    set base $parent
+
+
+    set w  [ frame $base.1 ]; pack $w -side top -expand f -fill x
+    set w2  [ frame $base.11 ]; pack $w2 -side top -expand f -fill x
+    frame $base.110 -bg black -height 3 ; pack $base.110 -side top -expand f -fill x
+    set w1  [ frame $base.111 ]; pack $w1 -side top -expand f -fill x
+    frame $base.15 -bg black -height 3 ; pack $base.15 -side top -expand f -fill x
+
+    label $w.1 -text "Server:"
+    set thisparam($this,servermenu) [ tk_optionMenu $w.2 [ itcl::scope thisparam($this,vvlinkserver) ] $thisparam($this,vvlinkserver) ]
+    pack $w.1 $w.2  -side left -expand true -fill x
+    
+    lappend thisparam($this,connectlist)    [ eval "button $w1.3  -text \"Connect\" -command { $this VVLinkConnect  }" ]
+    lappend thisparam($this,disconnectlist) [ eval "button $w1.4  -text \"Disconnect\" -command { $this VVLinkDisconnect }" ]
+    lappend thisparam($this,disconnectlist) [ eval "button $w1.5  -text \"Update ImageList\" -command { $this VVLinkUpdateImageList }" ]
+    pack $w1.3 $w1.4 $w1.5   -side left -expand true -fill x
+
+    lappend thisparam($this,connectlist) [ eval "button $w2.1  -text \"Add Server\" -command { $this VVLinkServerAdd 0 }" ]
+    lappend thisparam($this,connectlist) [ eval "button $w2.2  -text \"Re-Load Setup\" -command { $this LoadSetup }" ]
+    lappend thisparam($this,connectlist) [ eval "button $w2.3  -text \"Save Setup\" -command { $this SaveSetup }" ]
+
+    pack $w2.1 $w2.2 $w2.3 -side left -expand false -fill x -padx 2
+    
+
+    set thisparam($this,vvimagelist) [ iwidgets::scrolledlistbox $base.st -labeltext "Current VectorVision Image List"  -vscrollmode static -hscrollmode dynamic -selectmode single -exportselection 0 -height 2i ]
+    set basea [ frame $base.orient ]
+    set baseb [ frame $base.orient2 ]
+    set basec $base.orient3 
+
+    lappend thisparam($this,disconnectlist) $thisparam($this,vvimagelist) $basea $baseb
+
+    radiobutton $basea.2o -variable [itcl::scope thisparam($this,orientation)] -value "-1" -text "Auto-Detect"
+    eval "radiobutton $basea.2a -variable [itcl::scope thisparam($this,orientation)] -value 0 -text Axial -command { $this SelectedAxial }"
+    eval "radiobutton $basea.2b -variable [itcl::scope thisparam($this,orientation)] -value 1 -text Coronal -command { $this SelectedCoronal }"
+    radiobutton $basea.2c -variable [itcl::scope thisparam($this,orientation)] -value "2" -text "Sagittal" 
+    eval "button  $basea.2f -text Advanced -command { $this ShowAdvanced }"
+    pack  $basea.2o $basea.2a $basea.2b $basea.2c  $basea.2f -side left -expand t -fill x
+   
+
+
+    eval "button $baseb.1  -text \"Transfer Image\" -command { $this VVLinkGetImage -1 }" 
+    pack $baseb.1  -side left -expand t -fill x -padx 10
+
+    pack $baseb $basea -side bottom -expand false -fill x -padx 10
+    pack $base.st -side top -expand true -fill both -pady 2 
+
+    set advanced_gui $basec
+    toplevel $basec; wm withdraw $basec; 
+    eval "wm protocol $basec WM_DELETE_WINDOW { wm withdraw $basec }"
+    wm title $basec "Advanced Controls"
+
+    eval "checkbutton $basec.2a -variable [itcl::scope thisparam($this,flipleft)]   -text \"Flip Left\" -command { $this WarnAboutFlipLeft }"
+    checkbutton $basec.2b -variable [itcl::scope thisparam($this,flipfront)]  -text "Flip Anterior"
+    checkbutton $basec.2c -variable [itcl::scope thisparam($this,fliptop)]    -text "Flip Superior" 
+    checkbutton $basec.2d -variable [itcl::scope thisparam($this,forceaxial)] -text "Force Axial" 
+    eval "button  $basec.2e -text Close -command { wm withdraw $basec }"
+    set wf [ frame $basec.2f ]
+    label $wf.2d -text "Sample:"
+    tk_optionMenu $wf.2e [ itcl::scope thisparam($this,samplerate) ] 1 2 3 4 8 
+    pack $wf.2d $wf.2e -side left -expand t -fill x
+
+    pack  $basec.2a $basec.2b $basec.2c $basec.2d  $wf $basec.2e  -side top -expand t -fill x
+
+
+}
+#--------------------------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkgadget::CreateConfigurationControl { parent }  {
+
+    set base [ frame $parent.1 ]
+    pack $base -side top -expand t -fill both
+    
+    set top  [ LabelFrame:create $base.a -text "Stream Viewer"]
+    set bot  [ LabelFrame:create $base.b -text "Link Viewer Cursor With Navigational Pointer"]
+    pack $base.a $base.b -side top -expand t -fill both -pady 2
+
+    
+    set w1  [ frame $top.1 ]
+    set w2  [ frame $top.2 ]
+    pack $w1 $w2 -side top -expand true -fill x
+    
+    label $w1.1 -text "Image Update Time (ms): "
+    tk_optionMenu $w1.2 [ itcl::scope thisparam($this,streamdelay) ]  "50" "100" "200" "500" "1000" "2000" "5000" "10000"
+    pack $w1.1 $w1.2  -side left -expand true -fill x
+
+    lappend thisparam($this,disconnectlist) [ eval "button $w2.2 -text Test -command { $this VVLinkSendImage 0 }" ]
+    lappend thisparam($this,streamofflist)  $w2.2
+
+    lappend thisparam($this,disconnectlist) [ eval "button $w2.3 -text Enable -command { $this VVLinkSendImage 1 }" ]
+    lappend thisparam($this,streamofflist)  $w2.3
+
+    lappend thisparam($this,disconnectlist) [ eval "button $w2.4 -text Disable -command { $this VVLinkSendImage 2 }" ]
+    lappend thisparam($this,streamonlist)  $w2.4
+    pack $w2.2 $w2.3 $w2.4 -side left -expand true -fill x
+
+
+
+    set w3  [ frame $bot.1 ]
+    set w4  [ frame  $bot.2 ]
+    set w45 [ frame $bot.21 ]
+    set w5  [ frame $bot.3 ]
+    pack $w3 $w4 $w45 $w5 -side top -expand true -fill x
+
+    label $w3.0 -text "Update (ms): "
+    tk_optionMenu $w3.1 [ itcl::scope thisparam($this,tooldelay) ]  50 100 200 500 1000 2000 5000 10000
+    checkbutton $w3.2 -variable [itcl::scope thisparam($this,updateviewer)]   -text "Update Viewer" 
+    pack $w3.0 $w3.1 $w3.2 -side left -expand true -fill x
+
+    label $w45.1 -text "Radius: "
+    tk_optionMenu $w45.2 [ itcl::scope thisparam($this,coneradius) ]  0.25 0.5 1 2 3 5 10
+    label $w45.3 -text "Length:"
+    tk_optionMenu $w45.4 [ itcl::scope thisparam($this,conelength) ]  10 20 30 40 50 75 100 200
+    label $w45.inlinelabel -text "inline"
+    tk_optionMenu $w45.inline [ itcl::scope thisparam($this,inline) ] 0 1 2 3
+    pack $w45.1 $w45.2 $w45.3 $w45.4 $w45.inlinelabel $w45.inline -side left -expand true -fill x
+
+    iwidgets::entryfield $w4.1 -labeltext "Extension:" -width 3 -textvariable [ itcl::scope thisparam($this,coneextension) ] -relief sunken -validate real 
+    lappend thisparam($this,disconnectlist) [ eval "button $w4.2 -text \"Show/Hide\" -command { $this ShowHideCone }" ]
+
+
+    pack $w4.1  $w4.2 -side left -expand true -fill x
+
+    lappend thisparam($this,disconnectlist) [ eval "button $w5.1 -text Test -command { $this VVLinkGetToolCoordinates 0 }" ]
+    lappend thisparam($this,linkofflist)  $w5.1
+
+    lappend thisparam($this,disconnectlist) [ eval "button $w5.15 -text Color -command { $this TipColor 3 }" ]
+
+    lappend thisparam($this,disconnectlist) [ eval "button $w5.2 -text Enable -command { $this VVLinkGetToolCoordinates 1 }" ]
+    lappend thisparam($this,linkofflist)  $w5.2
+
+    lappend thisparam($this,disconnectlist) [ eval "button $w5.3 -text Disable -command { $this VVLinkGetToolCoordinates 2 }" ]
+    lappend thisparam($this,linkonlist)  $w5.3
+
+
+    # Eliminate this for now
+    set ok 0
+    #    set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary vtkjoStereoVisionTCL vtkjoProbeVisualization ]
+    if { $ok != 0 } {
+	#       lappend thisparam($this,disconnectlist) [ eval "button $w5.4 -text Projector -command { $this ShowProjectorControl }" ]
+        eval "button $w5.4 -text Projector -command { $this ShowProjectorControl }" 
+	pack $w5.4 -side right -expand false -fill x
+    }
+
+    pack $w5.1 $w5.15 $w5.2 $w5.3 -fill x -side left -expand true
+
+
+}
+## 
+#--------------------------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkgadget::CreatePointerControl { parent }  {
+
+    set base [ frame $parent.1 ]
+    pack $base -side top -expand t -fill both 
+    
+    set top  [ LabelFrame:create $base.a -text "Pointer Controls"]
+
+    pack $base.a  -side top -expand t -fill both -pady 2
+    
+    set w0  [ frame $top.1 ]
+    set w1  [ frame $top.2 ]
+    set w2  [ frame $top.3 ]
+    set w3  [ frame $top.4 ]
+    set w4  [ frame $top.5 ]
+    set w5  [ frame $top.6 ]
+    
+    pack $w0 $w5 $w4 $w1 $w2 $w3 -side top -expand true -fill both
+
+#    label $w0.1 -text "Cylinder Enable" -state disabled
+    
+    eval "checkbutton $w0.1 -variable [ itcl::scope thisparam($this,cylinderenabled) ] -text {Enable Cylinder} "
+    
+    label $w1.1 -text "Cross Length " -state disabled
+    scale $w1.2 -variable  [ itcl::scope thisparam($this,crosslength) ] -orient horizontal -length 628 -from 2.0 -to 10.0  -resolution 0.25 -state disabled
+    label $w2.1 -text "Cross Thickness " -state disabled
+    scale $w2.2 -variable  [ itcl::scope thisparam($this,crossthickness) ] -orient horizontal -length 628 -from 0.2 -to 1.0  -resolution 0.01 -state disabled
+    label $w3.1 -text "Set Roll Angle" -state disabled
+    scale $w3.2 -variable  [ itcl::scope thisparam($this,rollangle) ] -orient horizontal -length 628 -from -180.0 -to 180.0  -resolution 0.05 -state disabled
+    
+    eval "button $w4.2 -text {Cross Color} -command { $this TipColor 5 } -state disabled" 
+
+    # lappend thisparam($this,pointerlist)  $w1.1 $w1.2 $w2.1 $w2.2 $w3.1 $w3.2 $w4.1 $w4.2 # Show Sphere 
+    lappend thisparam($this,pointerlist)  $w0.1 $w1.1 $w1.2 $w2.1 $w2.2 $w3.1 $w3.2 $w4.2  
+
+    eval "checkbutton $w5.1 -variable [ itcl::scope thisparam($this,showcross) ] -command { $this EnablePointerControls  } -text {Show Cross} "
+  
+     # pack $w1.1 $w1.2 $w2.1 $w2.2 $w3.1 $w3.2 $w4.1 $w4.2 $w5.1 -side top -expand true # Show Sphere 
+     pack $w0.1 $w1.1 $w1.2 $w2.1 $w2.2 $w3.1 $w3.2 $w4.2 $w5.1 -side top -expand true  
+    
+    	    
+}
+
+##
+
+#--------------------------------------------------------------------------------------------
+itcl::body pxitclvvlinkgadget::CreateStripControl { parent }  {
+
+    set base $parent
+
+    set w  [ LabelFrame:create $base.a -text "Strip Properties"]; pack $base.a -side top -expand t -fill x
+    
+
+    iwidgets::entryfield $w.1 -labeltext "Strip Length (mm):"  -width 2 -validate integer -textvariable [ itcl::scope thisparam($this,striplength) ] -relief sunken 
+    iwidgets::entryfield $w.2 -labeltext "Step Size (mm):"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,stripstep) ] -relief sunken 
+
+    iwidgets::entryfield $w.3 -labeltext "Smoothness:"  -width 4 -validate real -textvariable [ itcl::scope thisparam($this,stripsmoothness) ] -relief sunken 
+
+    pack $w.1 $w.2 $w.3 -side top -expand t -fill x
+
+    frame $base.15 -bg black -height 3 ; pack $base.15 -side top -expand f -fill x
+
+    set w  [ LabelFrame:create $base.b -text "Surface \& Seed Points"]; pack $base.b -side top -expand t -fill x
+    
+
+    iwidgets::entryfield $w.1 -labeltext "Use Points from Current Set (-1=Last 2) First Point" -width 4 -validate integer -textvariable [ itcl::scope thisparam($this,striplandmarkoffset) ] -relief sunken 
+    iwidgets::entryfield $w.2 -labeltext "Outer Brain Surface:"  -width 1 -validate integer -textvariable [ itcl::scope thisparam($this,stripbrainsurface) ] -relief sunken 
+
+    pack $w.1 $w.2 -side top -expand true -fill x
+
+    frame $base.25 -bg black -height 3 ; pack $base.25 -side top -expand f -fill x
+
+    set w2 [ frame $base.c ] ; pack $w2 -side bottom -expand t -fill x -pady 2
+    eval "button $w2.land  -text \"Landmark Control\" -command { $this ShowControl landmark}"
+    eval "button $w2.poly  -text \"Surface Control\" -command  { $this ShowControl surface }"
+    pack $w2.poly $w2.land -side right  -expand false -padx 5
+
+    eval "button $w2.create  -text \"Create Strip\" -command  { $this PredictElectrodeStrip }"
+    pack $w2.create -side left  -expand false -padx 5
+
+}
+
+
+#--------------------------------------------------------------------------------------------
+# Main GUI Body 
+# ---------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkgadget::Initialize { widget viewer } { 
+	
+    global pxtcl_pref_array
+
+    set basewidget [ toplevel $widget ]
+    wm geometry $basewidget 500x400
+    wm withdraw $basewidget
+
+    set vtk_viewer $viewer 
+    
+    set notebook $basewidget.notebook
+    set bbar    [ frame $basewidget.bot    -width 400 -height 50 ]
+
+    iwidgets::tabnotebook $notebook  -tabpos w
+    pack $bbar -side bottom -expand f -fill x -pady 2 -pady 2
+    pack $notebook -side top -expand t -fill both -pady 2 -padx 2
+    eval "button $bbar.1  -text \"Close\" -command {  $this HideWindow }"
+    pack $bbar.1 -side right -expand f -padx 10
+    
+
+    CreateServerControl             [ $notebook add -label Server  ] 
+    CreateConfigurationControl      [ $notebook add -label "Link"  ] 
+    CreateDataSetControl            [ $notebook add -label "Data"  ] 
+    CreateFeatureControl            [ $notebook add -label "Points"  ]
+    CreatePointerControl            [ $notebook add -label "Pointer Controls"  ]  
+
+    if { $pxtcl_pref_array(EnableBetaFeatures) == "Enabled" } {
+	CreateZTouchControl             [ $notebook add -label "Z-Touch"  ] 
+	CreateStripControl              [ $notebook add -label "Strip"  ] 
+    }
+    if { $enable_igtl ==1 && $pxtcl_pref_array(OpenIGTLink)=="Enabled" } {
+	CreateOpenIGTLControl             [ $notebook add -label "IGTL Bridge"  ] 
+    }
+	CreateTrajectoryControl         [ $notebook add -label "Trajectories"  ]
+    CreateAboutControl              [ $notebook add -label "About"  ] 
+
+
+    if { $vvlink_connected == 1 } {
+	DisableUI $thisparam($this,connectlist)    
+    } else {
+	DisableUI $thisparam($this,disconnectlist)    
+    }
+
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+
+    if { [ file exists $setupfilename ] } {
+	LoadSetup $setupfilename
+    }
+
+    for { set i 0 } { $i <= 5 } { incr i } {
+	if { $i == 3 } {		
+	    	set vv_pointersource($i) [ vtkConeSource [ pxvtable::vnewobj ]]
+	    	$vv_pointersource($i) SetResolution 36
+	} elseif { $i == 4 } {
+	    set vv_pointersource($i) [ vtkSphereSource [ pxvtable::vnewobj ]]
+	    $vv_pointersource($i) SetThetaResolution 6
+	    $vv_pointersource($i) SetPhiResolution 6 	
+	} elseif { $i == 5 } {
+	    set vv_pointersource($i) [ vtkpxCrossHairSource [ pxvtable::vnewobj ]]
+	   $vv_pointersource($i) SetLength 3.0 
+	} else {
+	    set vv_pointersource($i) [ vtkpxCrossHairSource [ pxvtable::vnewobj ]]
+	    $vv_pointersource($i) SetShowSphere 1
+	    $vv_pointersource($i) SetLength 2.0
+	}
+
+	set vv_pointermapper($i) [ vtkPolyDataMapper [ pxvtable::vnewobj ]]
+	$vv_pointermapper($i) SetInput [ $vv_pointersource($i) GetOutput ]
+	
+	set vv_pointeractor($i)  [ vtkActor [ pxvtable::vnewobj ]]
+	$vv_pointeractor($i) SetMapper $vv_pointermapper($i)
+	$vv_pointeractor($i) VisibilityOff
+	
+	if { $i == 3 } {
+	    [ $vv_pointeractor($i) GetProperty ] SetSpecularPower 0.5
+	    [ $vv_pointeractor($i) GetProperty ] SetColor 0 0 1
+	} elseif { $i == 4 } {
+	    [ $vv_pointeractor($i) GetProperty ] SetSpecularPower 10.5
+	    [ $vv_pointeractor($i) GetProperty ] SetColor 0.5 0.5 1.0
+	    [ $vv_pointeractor($i) GetProperty ] SetRepresentationToWireframe
+	} elseif { $i == 5 } {
+	    [ $vv_pointeractor($i) GetProperty ] SetSpecularPower 100.5
+	    [ $vv_pointeractor($i) GetProperty ] SetColor 1.0 0.0 0.0
+	    [ $vv_pointeractor($i) GetProperty ] SetRepresentationToSurface 
+	} else {
+	    [ $vv_pointeractor($i) GetProperty ] SetSpecularPower 0.0
+	    [ $vv_pointeractor($i) GetProperty ] SetColor 1 0 0
+	    [ $vv_pointeractor($i) GetProperty ] SetAmbient 1.0
+	    [ $vv_pointeractor($i) GetProperty ] SetDiffuse 0.0
+	    [ $vv_pointeractor($i) GetProperty ] SetRepresentationToWireframe 
+	}
+	    
+	
+	if { [ $vtk_viewer IsA "vtkpxGUIOrthogonalViewer" ] ==1 } {
+	    [ [ $vtk_viewer GetRenderer $i ] GetRenderer ] AddActor $vv_pointeractor($i)
+	}
+    }
+
+    set canvas [ [ $notebook component tabset ] component canvas ]
+    set l [ AddLogoLabel $canvas ]
+    pack $l -side bottom -padx 1 
+
+    set ok 0
+    #set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary vtkjoStereoVisionTCL vtkjoProbeVisualization ]
+    #if { $vvlink_projector == 0  && $ok != 0 } {
+    #    set vvlink_projector [ pxitclvvlinkprojectorgadget [ pxvtable::vnewobj ] $this ]
+    #}
+	
+    SetTitle "VVLINK Tool: Disconnected" 
+    $basewidget configure -bg black
+
+
+
+    return $basewidget
+
+}
+
+::itcl::body pxitclvvlinkgadget::AddToMenuButton { mb args} {
+
+    eval "$mb add command -label \"VV Link Tool\" -command {$this ShowWindow \"Server\"}"
+}
+
+
+# ---------------------------------------------------------------------------
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclvvlinkprojectorgadget.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclvvlinkprojectorgadget.tcl
new file mode 100644
index 0000000..75ec326
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclvvlinkprojectorgadget.tcl
@@ -0,0 +1,453 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+package provide pxitclvvlinkprojectorgadget 1.0
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+
+package require  vtkpxcontrib 1.1
+package require  labelframe   1.0
+package require  pxtclutil    1.0
+package require  pxvtable     1.0
+package require  pxtclhelp    1.0
+package require  Itcl         3.2
+package require  Iwidgets     4.0
+package require  pxitclimage            1.0
+package require  pxitcllandmarks        1.0
+package require  pxitclsurface          1.0
+package require  pxitcltransform        1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxtcluserprefs         1.0
+
+# ----------------------------------------------------------------------------------------------
+
+itcl::class pxitclvvlinkprojectorgadget {
+
+    inherit pxitclbasecontrol
+
+    # Generic Stuff 
+    private   common   thisparam        
+
+    # VTKViewer is a vtkpxGUIOrthogonalViewer
+    protected variable VTKViewer        0
+    protected variable VVLinkGadget     0
+    protected variable RenderWindow     0
+
+    protected variable estimatecontrol  0 
+    protected variable landmarkcontrol  0 
+    protected variable surfacecontrol   0 
+    
+    # Booleans for if we should be projecting
+#    protected variable ProjectPolyData  0
+#    protected variable ProjectVolume    0
+    
+    protected variable Representation   0
+    protected variable ProbeVisualization 0
+    
+    protected variable Context          0
+    
+#    protected variable PolyDataProjectorSource  0
+#    protected variable PolyDataProjectorMapper  0
+#    protected variable PolyDataProjectorActor   0
+    
+#    protected variable VolumeProjectorSource  0
+#    protected variable VolumeProjectorMapper  0
+#    protected variable VolumeProjectorActor   0
+
+#    protected variable EllipseSource    0
+#    protected variable EllipseMapper    0
+#    protected variable EllipseActor     0
+#    protected variable EllipseTransform 0
+    
+    # parentObject is the vvlinkgadget that owns this window
+    constructor { vvlinkgadget } {
+	   ::pxitclbasecontrol::constructor $vvlinkgadget
+    } {
+        $this InitializeVVLinkProjectorGadget $vvlinkgadget
+    }
+
+    
+    private method InitializeVVLinkProjectorGadget { vvlinkgadget } 
+    public method DelayedInitialize { }
+    protected method CreateProjectorControl { parent } 
+    
+    public method UseVisualizationCallback { } 
+    public method ContextCallback { } 
+    public method DisplayContextCallback { } 
+    public method UpdateEstimateCallback { }
+    public method ContextAddPointsCallback { }
+    public method UpdateLandmarksCallback { }
+#    public method SetVisibility { isVisible } { set IsVisible $isVisible }
+    # (tx,ty,tz) are the tool tip coordinates and (bx,by,bz) are the 
+    # tool base coordinates.
+    public method Update { x y z nx ny nz }
+}
+
+# ---------------------------------------------------------------------------
+
+
+itcl::body pxitclvvlinkprojectorgadget::InitializeVVLinkProjectorGadget { vvlinkgadget } {
+    puts stderr "vvlinkprojectorgadget::InitializeVVLinkProjector"
+    
+    pxtclvtkpxcontrib::LoadLibraries { vtkjoStereoVisionTCL }
+    
+    if { $vvlinkgadget != 0 } {
+        set VVLinkGadget $vvlinkgadget
+    } else {
+        puts stderr "Cannot use ProjectorGadget with NULL parent VVLinkGadget"
+        return
+    }
+    
+    # Create the window
+    set basewidget [ toplevel [ $VVLinkGadget GetBaseWidget ].[pxvtable::vnewobj] ]
+    wm withdraw $basewidget
+    wm geometry $basewidget 350x450
+    
+    SetTitle "Projector Tool"
+    
+    # Get the base viewer so we can update the render window
+    set baseviewer [ $VVLinkGadget GetParent ]
+    
+#    set PolyDataControl [ $baseviewer GetPolyDataControl ]
+#    set thisparam($this,surface)    1
+    
+#    set thisparam($this,dovolumeproject)          0
+#    set thisparam($this,dosurfaceproject)         0
+    set thisparam($this,dovisualization)          0
+
+    set thisparam($this,projectorfocallength)     25.0
+    set thisparam($this,projectorsearchdistance)  100.0
+    set thisparam($this,projectorparallel)        0
+
+    set thisparam($this,crosshairlength)          1.0
+    set thisparam($this,crosshairresolution)      10
+    set thisparam($this,circleradius)             1.0
+    set thisparam($this,circleresolution)         36
+    
+    set thisparam($this,usecontext)               0
+    set thisparam($this,contextcapturerange)      3.0
+    set thisparam($this,displaycontext)           0
+    
+    # Create the VTK pipelines
+    
+#    set Context [ vtkjoLandmarkDistanceContext New ]
+#    set Context [ vtkjoStatisticalLandmarkDistanceContext New ]
+#    set Context [ vtkjoRegistrationErrorContext New ]
+    
+#    set VolumeProjectorSource [ vtkjoVolumeProjector New ]
+#    $VolumeProjectorSource SetTemplate $Template
+#    $VolumeProjectorSource SetContext $Context
+
+#    set lut [ vtkLookupTable New ]
+#    $lut SetNumberOfTableValues 2
+#    $lut SetTableRange 0 1 
+#    $lut SetTableValue 0 0.0 0.0 1.0 1.0
+#    $lut SetTableValue 1 1.0 0.0 0.0 1.0
+    
+#    set VolumeProjectorMapper [ vtkPolyDataMapper New ]
+#    $VolumeProjectorMapper SetInput [ $VolumeProjectorSource GetOutput ]
+#    $VolumeProjectorMapper SetLookupTable $lut
+#    $lut Delete
+#    $VolumeProjectorMapper SetScalarModeToUsePointFieldData
+#    $VolumeProjectorMapper SelectColorArray "Context"
+#    $VolumeProjectorMapper ScalarVisibilityOff
+    
+#    set VolumeProjectorActor  [ vtkActor New ]
+#    $VolumeProjectorActor SetMapper $VolumeProjectorMapper
+#    set prop [ $VolumeProjectorActor GetProperty ]
+#    $prop SetLineWidth 4.0
+#    $prop SetColor 0.0 0.0 1.0
+#    $VolumeProjectorActor VisibilityOff
+    
+    # Setup the pipeline to display the ellipsoid
+#    set EllipseSource [ vtkEllipseSource New ]
+#    $EllipseSource SetThetaResolution 15
+#    $EllipseSource SetPhiResolution 15
+#    set EllipseTransform [ vtkTransform New ]
+#    set EllipseMapper [ vtkPolyDataMapper New ]
+#    $EllipseMapper SetInput [ $EllipseSource GetOutput ]
+#    set EllipseActor [ vtkActor New ]
+#    $EllipseActor SetMapper $EllipseMapper
+#    [ $EllipseActor GetProperty ] SetColor 0.0 0.5 0.0
+#    [ $EllipseActor GetProperty ] SetOpacity 0.9
+#    [ $EllipseActor GetProperty ] SetRepresentationToWireframe
+#    $EllipseActor VisibilityOff
+    
+    set ProbeVisualization [ vtkjoProbeVisualization New ]
+    $ProbeVisualization ContextVisualizationOff
+    set Representation [ $ProbeVisualization GetProjectionRepresentation ]
+    
+    set VTKViewer [ $baseviewer GetViewer ] 
+    if { [ $VTKViewer IsA "vtkpxGUIOrthogonalViewer" ] == 1 } {
+#        [ [ $VTKViewer GetRenderer 3 ] GetRenderer ] AddActor $VolumeProjectorActor
+#        [ [ $VTKViewer GetRenderer 3 ] GetRenderer ] AddActor $EllipseActor
+        [ [ $VTKViewer GetRenderer 3 ] GetRenderer ] AddActor $ProbeVisualization
+    }
+    
+    return $basewidget
+}
+
+
+itcl::body pxitclvvlinkprojectorgadget::Update { x y z nx ny nz } {
+
+    if { $thisparam($this,dovisualization) == 1 } {
+        
+        $Representation SetLength $thisparam($this,crosshairlength)
+        $Representation SetResolution $thisparam($this,crosshairresolution)
+        
+#        if { $thisparam($this,usecontext) == 1 } {
+#            $Context SetSigmaScalar $thisparam($this,contextcapturerange)
+#            $Context SetProbeTip $x $y $z
+            
+#            if { $thisparam($this,displaycontext) == 1 } {
+#            set sigmas [ $Context GetProbeTipStd ]
+#            set scalar [ $Context GetSigmaScalar ]
+#            puts stderr "ellipse stds = $sigmas"
+#            set range [ $Context GetCaptureRange ]
+#            $EllipseSource SetRadiusX [ expr {$scalar * sqrt ( [ lindex $sigmas 0 ] ) } ]
+#            $EllipseSource SetRadiusY [ expr {$scalar * sqrt ( [ lindex $sigmas 1 ] ) } ]
+#            $EllipseSource SetRadiusZ [ expr {$scalar * sqrt ( [ lindex $sigmas 2 ] ) } ]
+            
+#            $Context GetTransformation $EllipseTransform
+#            $EllipseActor SetPosition $x $y $z
+#            $EllipseActor VisibilityOn
+#            }
+#        }
+        
+        $ProbeVisualization SetTarget [ $VTKViewer GetImage ]
+        $ProbeVisualization SetPosition $x $y $z
+        $ProbeVisualization SetOrientation $nx $ny $nz
+        catch {
+            [ $ProbeVisualization GetProjector ] SetParallelProjection $thisparam($this,projectorparallel)
+            [ $ProbeVisualization GetProjector ] SetFocalDistance $thisparam($this,projectorfocallength)
+            [ $ProbeVisualization GetProjector ] SetMaxProjectionDistance $thisparam($this,projectorsearchdistance)
+        }
+    }
+    }
+
+#----------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkprojectorgadget::UseVisualizationCallback { } {
+    if { $thisparam($this,dovisualization) == 0 } {
+        $ProbeVisualization VisibilityOff
+    } else {
+        $ProbeVisualization VisibilityOn
+    }
+}
+
+#----------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkprojectorgadget::ContextCallback { } {
+    if { $thisparam($this,usecontext) == 0 } {
+        $ProbeVisualization ContextVisualizationOff
+    } else {
+        $ProbeVisualization ContextVisualizationOn
+    }
+}
+
+#----------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkprojectorgadget::DisplayContextCallback { } {
+    if { $thisparam($this,displaycontext) == 0 } {
+        $EllipseActor VisibilityOff
+    } else {
+        $EllipseActor VisibilityOn
+    }
+}
+
+#----------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkprojectorgadget::UpdateEstimateCallback { } {
+    # Update the point estimate that the context uses.
+    set curve [[ $estimatecontrol GetLandmarks ] GetObject ]
+    $curve Compact
+    puts stderr "Updating context with estimate (uses [[ $curve GetPoints ] GetNumberOfPoints ] samples)"
+    $Context SetPointEstimate [ $curve GetPoints ]
+    $Context UpdateEstimate
+
+}
+
+#----------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkprojectorgadget::ContextAddPointsCallback { } {
+    # Update the point estimate that the context uses.
+    set curve [[ $estimatecontrol GetLandmarks ] GetObject ]
+    $curve Compact
+    puts stderr "Add points to context (uses [[ $curve GetPoints ] GetNumberOfPoints ] samples)"
+    $Context AddPoints [ $curve GetPoints ]
+    $Context UpdateEstimate
+
+}
+
+#----------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkprojectorgadget::UpdateLandmarksCallback { } {
+    # Update the point estimate that the context uses.
+    set curve [[ $landmarkcontrol GetLandmarks ] GetObject ]
+    $curve Compact
+    puts stderr "Updating landmarks (uses [[ $curve GetPoints ] GetNumberOfPoints ] samples)"
+#    $Context SetLandmarks [ $curve GetPoints ]
+    $ProbeVisualization SetContextPoints [ $curve GetPoints ]
+}
+
+#----------------------------------------------------------------------------
+
+itcl::body pxitclvvlinkprojectorgadget::CreateProjectorControl { parent } {
+    
+    # Create the projector type GUI components
+    set typeFrame [ LabelFrame:create $parent.type -text "Projector" - expand true -fill x ]
+    
+    frame $typeFrame.vis
+    frame $typeFrame.parallel
+    frame $typeFrame.options
+    
+    eval "checkbutton $typeFrame.vis.check -text \"Use\" -variable [ itcl::scope thisparam($this,dovisualization) ] \
+        -command { $this UseVisualizationCallback }"
+    pack $typeFrame.vis.check -side left -expand false -padx 5
+
+    checkbutton $typeFrame.parallel.check -text "Parallel Projection" -variable [ itcl::scope thisparam($this,projectorparallel) ] 
+    pack $typeFrame.parallel.check -side left -expand false -padx 5
+    
+    iwidgets::entryfield $typeFrame.options.focal \
+        -labeltext "Focal Length" -width 5 \
+        -textvariable [ itcl::scope thisparam($this,projectorfocallength)] \
+        -relief sunken -validate real
+    iwidgets::entryfield $typeFrame.options.search \
+        -labeltext "Search Distance" -width 5 \
+        -textvariable [ itcl::scope thisparam($this,projectorsearchdistance)] \
+        -relief sunken -validate real
+    pack $typeFrame.options.focal $typeFrame.options.search -side left -expand false -padx 5
+    
+    pack $typeFrame.vis $typeFrame.parallel $typeFrame.options -side top -expand false -fill x -pady 3
+
+    
+    # Create the template GUI components
+    set templateFrame [ LabelFrame:create $parent.template -text "Template" - expand true -fill x ]
+    frame $templateFrame.crosshair
+    frame $templateFrame.circle
+
+    iwidgets::entryfield $templateFrame.crosshair.length \
+        -labeltext "Crosshair Length" -width 5 \
+        -textvariable [ itcl::scope thisparam($this,crosshairlength)] \
+        -relief sunken -validate real
+    iwidgets::entryfield $templateFrame.crosshair.res \
+        -labeltext "Resolution" -width 5 \
+        -textvariable [ itcl::scope thisparam($this,crosshairresolution)] \
+        -relief sunken -validate integer
+    pack $templateFrame.crosshair.length $templateFrame.crosshair.res \
+        -side left -expand false -fill x -pady 3
+
+    iwidgets::entryfield $templateFrame.circle.length \
+        -labeltext "Cirlce Radius" -width 5 \
+        -textvariable [ itcl::scope thisparam($this,circleradius)] \
+        -relief sunken -validate real
+    iwidgets::entryfield $templateFrame.circle.res \
+        -labeltext "Resolution" -width 5 \
+        -textvariable [ itcl::scope thisparam($this,circleresolution)] \
+        -relief sunken -validate integer
+    pack $templateFrame.circle.length $templateFrame.circle.res \
+        -side left -expand false -fill x -pady 3
+    
+    pack $templateFrame.crosshair $templateFrame.circle -side top -expand false -fill x
+    
+    
+    # Create the context GUI components
+    set contextFrame [ LabelFrame:create $parent.context -text "Context" - expand true -fill x ]
+    frame $contextFrame.use
+    frame $contextFrame.landmarks
+    frame $contextFrame.estimate
+    frame $contextFrame.options
+
+    eval "checkbutton $contextFrame.use.check -text \"Use\" -variable [ itcl::scope thisparam($this,usecontext) ] \
+        -command { $this ContextCallback }"
+    pack $contextFrame.use.check -side left -expand false -fill x -pady 3
+    
+    eval "button $contextFrame.landmarks.button -text \"Update\" -command { $this UpdateLandmarksCallback }"
+    set landmarkcontrol [ [ pxitcllandmarksGUI \#auto ] GetThisPointer ]
+    $landmarkcontrol configure -description "Landmarks"
+    $landmarkcontrol InitializeLite $contextFrame.landmarks.1 2
+    pack $contextFrame.landmarks.1 $contextFrame.landmarks.button \
+        -side left -expand false -fill x -pady 3
+
+#    eval "button $contextFrame.estimate.button -text \"Update\" -command { $this UpdateEstimateCallback }"
+    eval "button $contextFrame.estimate.button -text \"Add\" -command { $this ContextAddPointsCallback }"
+    set estimatecontrol [ [ pxitcllandmarksGUI \#auto ] GetThisPointer ]
+    $estimatecontrol configure -description "Point Estimate"
+    $estimatecontrol InitializeLite $contextFrame.estimate.1 2
+    pack $contextFrame.estimate.1 $contextFrame.estimate.button \
+        -side left -expand false -fill x -pady 3
+
+    iwidgets::entryfield $contextFrame.options.capture \
+        -labeltext "Scalar" -width 5 \
+        -textvariable [ itcl::scope thisparam($this,contextcapturerange)] \
+        -relief sunken -validate real
+    eval "checkbutton $contextFrame.options.check -text \"Display\" -variable [ itcl::scope thisparam($this,displaycontext) ] \
+        -command { $this DisplayContextCallback }"
+    pack $contextFrame.options.capture $contextFrame.options.check \
+        -side left -expand false -fill x -pady 3
+
+     #Pack the context frames
+    pack $contextFrame.use $contextFrame.landmarks $contextFrame.estimate $contextFrame.options \
+        -side top -expand false -fill x
+
+    
+    
+    # Pack the 3 main labeled frames in the main window
+    pack $parent.type $parent.template $parent.context -side top -expand false -fill both
+}
+
+
+
+itcl::body pxitclvvlinkprojectorgadget::DelayedInitialize { } {
+    puts stderr "vvlinkprojectorgadget::DelayedInit"
+
+    if { $fullyinitialized == 1} {
+        return 
+    }
+    
+    # Create the GUI
+    set mainFrame [ frame $basewidget.main ]
+    pack $mainFrame -side top -expand t -fill both -pady 2 -padx 2
+    
+    CreateProjectorControl $mainFrame 
+    
+    set fullyinitialized 1
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclvvlinkviewer.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclvvlinkviewer.tcl
new file mode 100755
index 0000000..9e87190
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclvvlinkviewer.tcl
@@ -0,0 +1,86 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclbrainsegment.tcl,v 1.2 2004/12/16 16:10:43 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package require vtkpxcontrib  1.1
+package require pxtcluserprefs 
+#package require vtkmpjcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+#package require mpjdiffusionutility 1.0
+
+wm withdraw .
+set bsegm [ pxitclbaseimageviewer \#auto 0 ]
+$bsegm configure -appname "BioImage Suite::VVLink Viewer (for VVLink/Open IGT Link Bridge)"
+$bsegm configure -show_standard_images 1
+$bsegm configure -enable_multisubjectcontrol 0
+$bsegm configure -enable_overlaytool 0
+$bsegm configure -enable_vvlinkgadget  1
+$bsegm configure -enable_talaraichoption 0
+$bsegm configure -enable_rendering_on_startup  0
+$bsegm configure -enable_internaleditor 0
+$bsegm configure -enable_objectmapmenu   0
+$bsegm configure -enable_fmrigadget  0
+$bsegm configure -enable_brainstriptool  0
+$bsegm configure -enable_importcontrol  0
+$bsegm configure -enable_imageutility  0
+$bsegm configure -enable_histcontrol  0
+$bsegm configure -enable_surfaceobjectmap    0
+$bsegm configure -enable_animationgadget 0
+
+$bsegm InitializeOrthogonalViewer .[pxvtable::vnewobj ] 1
+
+$bsegm ShowWindow   
+
+set argc [llength $argv]
+
+if { $argc > 0 } {   $bsegm LoadImage [lindex $argv 0]   }
+
+
+update idletasks
+[ $bsegm GetViewer ] SetEnableRendering 1
+
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclwfuatlasgadget.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclwfuatlasgadget.tcl
new file mode 100644
index 0000000..0e2044c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclwfuatlasgadget.tcl
@@ -0,0 +1,474 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+# This tool loads and interogates the WFUWFU Pickatlas version 2.4 
+# It also   interogates the Yale Atlas if present
+#
+# No part of the atlas software/images is integrated by BioImage Suite, it simply
+# looks for the atlas software and loads the ROIs
+#
+#     The wfu_pickatlas toolbox and user manual can be obtained from:
+#        www.fmri.wfubmc.edu 
+
+
+package provide pxitclwfuatlasgadget 1.0
+
+# 	$Id: pxitclwfuatlasgadget.tcl,v 1.2 2004/02/03 17:36:31 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+package require  vtkpxcontrib 1.1
+package require  labelframe   1.0
+package require  pxtclutil    1.0
+package require  pxvtable     1.0
+package require  pxtclhelp    1.0
+package require  Itcl         3.2
+package require  Iwidgets     4.0
+package require  pxitclimage            1.0
+package require  pxitcltransform        1.0
+package require  pxitclbaseimagecontrol 1.0
+
+# ----------------------------------------------------------------------------------------------
+
+itcl::class pxitclwfuatlasgadget {
+
+    inherit pxitclbaseimagecontrol
+    
+    # Generic Stuff 
+
+    private   common   thisparam        
+    protected common   atlas_initialized 0
+    protected common   atlasimages
+    protected common   atlaslabels
+    protected common   atlastext ""
+    protected common   atlaspath ""
+    protected common   numatlases 0
+    protected common   atlasnotfound 0
+
+    # public 
+
+    
+    #
+    constructor { par args } {
+	pxitclbaseimagecontrol::constructor $par
+    } {
+	InitializeWFUatlasgadget
+    }
+
+    protected method InitializeWFUatlasgadget { }
+    public method Initialize { widget }
+    public method DelayedInitialize { }
+
+    public method AddToMenuButton { mb args }
+
+
+
+    public method IdentifyPoint { x y z } 
+    public method IdentifyInternalPoint { }
+
+    public method LoadAtlas { }
+    public method SetError { txt }
+
+    #Not yet implemented
+    public method FindAtlas { imagelist }
+}
+
+
+::itcl::body pxitclwfuatlasgadget::AddToMenuButton { mb args} {
+
+    eval "$mb add command -label \"WFU Atlas Tool\" -command {$this ShowWindow }"
+}
+
+itcl::body pxitclwfuatlasgadget::InitializeWFUatlasgadget { } {
+
+    set thisparam($this,cx) 91
+    set thisparam($this,cy) 110
+    set thisparam($this,cz) 91
+    set thisparam($this,textbox) 0
+    set thisparam($this,aboutbox) 0
+    set thisparam($this,wfupath) ""
+}
+
+itcl::body pxitclwfuatlasgadget::Initialize { widget } { 
+	
+    set basewidget [ toplevel $widget ]
+    wm geometry $basewidget 500x300
+    wm withdraw $basewidget
+
+    SetTitle "BioImage Suite WFU Pick::Atlas Tool"
+    
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget
+
+}
+
+itcl::body pxitclwfuatlasgadget::DelayedInitialize { } { 
+
+    set pbar         [ frame $basewidget.pbar    -width 400 -height 20 ]
+    set notebook $basewidget.notebook
+
+
+    iwidgets::tabnotebook $notebook  -tabpos n
+
+   set thisparam($this,wfupath) [ label $basewidget.bot -text "Atlas not loaded." -bg black -fg white ]
+
+    pack $pbar $basewidget.bot    -side bottom -expand f -fill x -pady 1
+    pack $notebook -side top -expand t -fill both -pady 1
+
+    set idframe    [ $notebook add -label "Identify" ]
+    set aboutframe [ $notebook add -label "About" ]
+    $notebook view "Identify"
+
+    set f1 [ frame $idframe.t] ; 
+    set f15 [ label $idframe.t2 -text "" -bg black -fg white ]
+
+    pack $idframe.t $idframe.t2 -side top -expand false -fill x 
+    $idframe.t2 configure -text "Coordinates are in mm (R->L,A->P,I->S),origin=bottom corner of image"
+    $idframe.t2 configure -font { fixed 8}
+
+    set f2 [ frame $idframe.b] ; pack $idframe.b -side bottom -expand true -fill both    
+
+
+    label $f1.l -text "Point:"
+    iwidgets::entryfield $f1.x -labeltext "X (mm):"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,cx) ] -relief sunken 
+    iwidgets::entryfield $f1.y -labeltext "Y (mm):"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,cy) ] -relief sunken 
+    iwidgets::entryfield $f1.z -labeltext "Z (mm):"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,cz) ] -relief sunken 
+    eval "button $f1.b -text Identify -command { $this IdentifyInternalPoint }"
+    pack $f1.b -side right -expand f -padx 2
+    pack $f1.l $f1.x $f1.y $f1.z  -side left -expand true -fill x
+
+    update idletasks
+
+ 
+    for { set i 0 } { $i <= 1 } { incr i } {
+	frame $f2.topframe    
+	set textbox $f2.topframe.textbox; 
+	set ybar    $f2.topframe.ybar 
+	set xbar    $f2.xbar 
+	
+	eval "scrollbar $ybar  -command { $textbox yview } -orient vertical"
+	eval "scrollbar $xbar  -command { $textbox xview } -orient horizontal"
+	eval "text $textbox  -width 60 -height 10  -wrap word -relief ridge -yscrollcommand { $ybar set} -xscrollcommand {$xbar set}"
+	pack $xbar -side bottom -expand f -fill x 
+	pack $f2.topframe -side top -expand true -fill both -padx 0 -pady 5
+	pack $ybar -side right -expand false -fill y
+	pack $textbox -side left -expand true -fill both
+	$textbox configure -font { fixed 10 } 
+	if { $i == 0 } {
+	    set thisparam($this,textbox) $textbox
+	    set f2  $aboutframe
+	} else {
+	    set thisparam($this,aboutbox) $textbox
+	}
+    }
+
+    ::pxitclbasecontrol::SetWidgetTreeColors $idframe.b  "\#ffdddd" "black"
+
+    eval "button $pbar.r -text  Close -command {  $this HideWindow }"
+    eval "button $pbar.l -text \"Load Atlas Files\" -command {  $this LoadAtlas }"
+    pack $pbar.r  -side right -padx 10
+    pack $pbar.l -side left -padx 10
+
+    set canvas [ [ $notebook component tabset ] component canvas ];     
+    set l [ AddLogoLabel $canvas ];     
+    pack $l -side right -padx 1 
+
+
+    set fullyinitialized 1
+
+    if { $atlas_initialized == 1 } {
+	# Just update the textboxes ...
+	LoadAtlas
+    }
+    
+}
+
+
+::itcl::body pxitclwfuatlasgadget::LoadAtlas { } {
+
+    if { $atlas_initialized == 1 } {
+	set textbox $thisparam($this,aboutbox)
+	if { $textbox != 0 } {
+	    $textbox configure -state normal
+	    $textbox delete 1.0 end
+	    $textbox insert end $atlastext
+	    $textbox configure -state disabled
+	    $notebook view "About"
+	    $thisparam($this,wfupath) configure -text $atlaspath
+	    update idletasks
+	}
+	return
+    }
+
+
+    set imglist {
+	TD_hemisphere  
+	TD_lobe
+	TD_label
+	TD_brodmann    
+	aal_MNI_V4
+    }
+    set imgname [ list  hemisphere lobe label broadman aal_MNI_v4 ]
+
+    set basedir [ FindAtlas $imglist ]
+    if { $basedir == "" } {
+	set  atlasnotfound 1
+	return 0
+    }
+    set atlaspath "Atlas Location: [ file root [ file normalize $basedir]]"
+    set numatlases [ llength $imgname ]
+
+    pxtkprint "Loading WFU Pick Atlas\n"
+    for { set i 0 } { $i < [ llength $imgname ] } { incr i } {
+	set atlasimages($i) [  [ pxitclimage \#auto ] GetThisPointer ]
+	set fname [ file join $basedir [ lindex $imglist $i ] ].hdr
+	$atlasimages($i) Load $fname
+	pxtkprint "Loaded [ lindex $imgname $i ] : [ $atlasimages($i) GetShortDescription ]\t"
+
+	set fname [ file join $basedir [ lindex $imglist $i ].txt ]
+	set fileid [open $fname r]
+	gets $fileid line
+	set ind [ string first "\[" $line ]; if { $ind < 0 } { set ind -1 }
+	set inp [ string first "\]" $line ]; if { $ind < 0 } { set inp [ string length $line ] }
+	set line [ string trim [ string range $line [ expr $ind +1 ] [ expr $inp -1 ]]]
+	set atlaslabels($i,description) $line
+	pxtkprint ", $atlaslabels($i,description)\n"
+	set atlaslabels($i,0) "None"
+	set atlasimagenameslen   [string length $line]
+
+	while { [ gets $fileid line ] >=0 } {
+	    regsub -all "\t" $line ":" line
+	    set index [string first ":" $line]
+	    if { $index > 0 }  {
+		set len   [string length $line]
+		set key   [string trim   [string range $line 0 [expr $index - 1]]]
+		set line [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		set index [string first ":" $line]
+		if { $index > 0 } {
+		    set len   [string length $line]
+		    set value   [string trim   [string range $line 0 [expr $index - 1]]]
+		} else {
+		    set value $line
+		}
+		set atlaslabels($i,$key) $value
+	    }
+	}
+	close $fileid
+    }
+    
+
+    set atlastext ""
+    set atlastext "$atlastext BioImage Suite relies on the WFU Pickatlas for labels.\n"
+    set atlastext "$atlastext \t The following is from the WFU documentation.\n"
+    set atlastext "$atlastext ------------------------------------------------------\n\n"
+    
+    set readme [ file join $basedir [ file join .. README.txt ]]
+    if { [ file exists $readme ] } {
+	#	set atlastext "$atlastext (File = [$readme)\n\n"
+	set fileid [open $readme r]
+	while { [ gets $fileid line ] >=0 } {
+	    set atlastext "$atlastext $line\n"
+	}
+	close $fileid
+    } else {
+	set atlastext "$atlastext WFU Pickatlas version 2.4 \nJoseph Maldjian, MD\n"
+	set atlastext "$atlastext Description\n"
+	set atlastext "$atlastext This software provides a method for generating ROI masks based on the Talairach Daemon database [1, 2].  The atlases include Brodmann area, Lobar, Hemisphere, Anatomic Label and Tissue Type.  The atlases have been extended to the vertex in MNI space (see Atlas Modifications under Technical Notes), and corrected for the precentral gyrus anomaly (see reference 7 below). Additional atlases can be added without much difficulty.  The toolbox was developed in the Fun [...]
+	set atlastext "$atlastext Downloading the Software\n\nThe wfu_pickatlas toolbox and user manual can be obtained from:\n www.fmri.wfubmc.edu"
+    }
+    set atlas_initialized 1
+
+    set textbox $thisparam($this,aboutbox)
+    if { $textbox != 0 } {
+	$textbox configure -state normal
+	$textbox delete 1.0 end
+	$textbox insert end $atlastext
+	$textbox configure -state disabled
+	$notebook view "About"
+	$thisparam($this,wfupath) configure -text $atlaspath
+	update idletasks
+    }
+    return
+}
+
+itcl::body pxitclwfuatlasgadget::IdentifyPoint { x y z }  {
+
+    set vx 0;    catch { set vx [ expr  ($x) ] }
+    set vy 0;    catch { set vy [ expr  ($y) ] }
+    set vz 0;    catch { set vz [ expr  ($z) ] }
+    set thisparam($this,cx) $vx
+    set thisparam($this,cy) $vy
+    set thisparam($this,cz) $vz
+
+    if { $atlas_initialized == 0 } { 
+	if { $atlasnotfound == 0 } {
+	    global pxtcl_pref_array
+
+	    set val $pxtcl_pref_array(WFUAtlasAutoInitialize)
+	    if { $val == "Enabled" } {
+		$this LoadAtlas
+	    }
+	}
+    }
+    return [ $this IdentifyInternalPoint ]
+}
+
+itcl::body pxitclwfuatlasgadget::IdentifyInternalPoint { } {
+
+    set textbox $thisparam($this,textbox) 
+    if { $textbox == 0 } {
+	return 0
+    }
+
+    $notebook view "Identify"
+    if { $atlas_initialized == 0 } {
+	set textbox $thisparam($this,textbox) 
+	$textbox configure -state normal
+	$textbox delete 1.0 end
+	$textbox insert end "Atlas Not Initialized!\n"
+	$textbox insert end "This tool requires that the WFU Pick Atlas be installed\n"
+	$textbox insert end "This is extenral software and not distributed with BioImage Suite\n"
+	$textbox insert end "\t\t See www.fmri.wfubmc.edu\n\n"
+
+	$textbox insert end "If it installed but cannot be found try setting the value of the\n environment variable WFUATLASDIR to point to the atlas location."
+	
+	$textbox configure -state disabled
+	return 
+    } 
+
+
+    set namelist [ list cx cy cz ]
+    set maxlist  [ list 180 216 180 ]
+    for { set i 0 } { $i <=2 } { incr i } {
+	set key [ lindex $namelist $i ]
+	set max [ lindex $maxlist  $i ]
+	if { $thisparam($this,$key) < 0 } {
+	    set thisparam($this,$key) 0
+	} elseif { $thisparam($this,$key) > $max } {
+	    set thisparam($this,$key) $max
+
+	}
+    }
+
+    set x [ expr  90 - round($thisparam($this,cx)/2.0) ]
+    set y [ expr 108 - round($thisparam($this,cy)/2.0) ]
+    set z [ expr round($thisparam($this,cz)/2.0) ]
+
+
+    $textbox configure -state normal
+    $textbox delete 1.0 end
+
+    for { set atlas 0 } { $atlas < $numatlases } { incr atlas } {
+	set v [ expr round([ [ $atlasimages($atlas) GetImage ] GetScalarComponentAsDouble $x $y $z 0 ])]
+	set lab "$atlaslabels($atlas,$v)"
+	set txt [ format "%-17s  %-35s value=%d\n" "$atlaslabels($atlas,description):" $lab $v ]
+	$textbox insert end $txt
+    }
+
+    $textbox insert end "\n(Original pick atlas location ijk=$x $y $z)\n"
+    $textbox insert end "Please note that all this is approximate .....\n"
+
+    $textbox configure -state disabled
+}
+
+itcl::body pxitclwfuatlasgadget::SetError { txt } { 
+
+    set textbox $thisparam($this,textbox) 
+    if { $textbox == 0 } {
+	return 0
+    }
+    $notebook view "Identify"
+    $textbox configure -state normal
+    $textbox delete 1.0 end
+    $textbox insert end $txt
+    $textbox configure -state disabled
+}
+
+itcl::body pxitclwfuatlasgadget::FindAtlas { imagelist } {
+
+    global tcl_platform 
+    global env
+    set pathlist ""
+
+    set base $::pxtclvtkpxcontrib::imagedir
+    set base [ file normalize "${base}/../../wfu_pickatlas" ]
+    lappend pathlist $base
+
+    set a ""
+    catch { set a $env(WFUATLASDIR) }
+    if { $a != "" } {
+	lappend pathlist $a
+    }
+
+    if { $tcl_platform(platform) == "windows" } { 
+	lappend pathlist "c:/yale/wfu_pickatlas"
+    } else {
+	lappend pathlist /usr/local/wfu_pickatlas/ 
+    }
+
+    set found 0
+    set index 0
+    set outpath ""
+
+    while { $index < [ llength $pathlist ] } {
+	set testpath [ lindex $pathlist $index ]
+	set testpath [ file join $testpath MNI_atlas_templates ]
+	
+	#puts stderr "\nSearching $testpath"
+	set numfound 0
+
+	for { set j 0 } { $j < [ llength $imagelist ] } { incr j } {
+	    set imgname [ file join $testpath [ lindex $imagelist $j].hdr ]
+	    set ok [ file exists $imgname ] 
+	    set numfound [ expr $numfound + $ok ]
+	    #puts stderr "Looking for $imgname ok =$ok, numfound=$numfound"
+
+	}
+	if { $numfound == [ llength $imagelist ] } {
+	    set found 1
+	    set outpath $testpath
+	}
+	incr index
+    }
+
+    if { $found == 0 } {
+	pxtclutil::Warning "WFU Pick Atlas Not Found in the standard places\n Looked in $pathlist\n Try Setting the value of the environment variable WFUATLASDIR to point to this."
+    }
+
+    #    puts stderr "Returning $outpath (found=$found)"
+    return $outpath
+}
diff --git a/bioimagesuite30_src/bioimagesuite/main/pxitclyaleatlasgadget.tcl b/bioimagesuite30_src/bioimagesuite/main/pxitclyaleatlasgadget.tcl
new file mode 100644
index 0000000..2c556db
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/main/pxitclyaleatlasgadget.tcl
@@ -0,0 +1,517 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+# This tool loads and interogates a custom atlas tool
+#
+# No part of the atlas software/images is integrated by BioImage Suite, it simply
+# looks for the atlas files ( bioimagesuite_atlas.txt is the master file)
+#
+
+package provide pxitclyaleatlasgadget 1.0
+
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+
+package require  vtkpxcontrib 1.1
+package require  labelframe   1.0
+package require  pxtclutil    1.0
+package require  pxvtable     1.0
+package require  pxtclhelp    1.0
+package require  Itcl         3.2
+package require  Iwidgets     4.0
+package require  pxitclimage            1.0
+package require  pxitcltransform        1.0
+package require  pxitclbaseimagecontrol 1.0
+
+# ----------------------------------------------------------------------------------------------
+
+itcl::class pxitclyaleatlasgadget {
+
+    inherit pxitclbaseimagecontrol
+    
+    # Generic Stuff 
+
+    private   common   thisparam        
+    protected common   atlas_initialized 0
+    protected common   atlasimages
+    protected common   atlaslabels
+    protected common   atlastext ""
+    protected common   atlaspath ""
+    protected common   numatlases 0
+    protected common   atlasnotfound 0
+
+    # public 
+
+    
+    #
+    constructor { par args } {
+	pxitclbaseimagecontrol::constructor $par
+    } {
+	InitializeYaleatlasgadget
+    }
+
+    protected method InitializeYaleatlasgadget { }
+    public method Initialize { widget }
+    public method DelayedInitialize { }
+
+    public method AddToMenuButton { mb args }
+
+
+
+    public method IdentifyPoint { x y z } 
+    public method IdentifyInternalPoint { }
+
+    public method LoadAtlas { }
+    public method SetError { txt }
+
+    #Not yet implemented
+    public method FindAtlas { basedir imagelist }
+    public method FindAtlasMasterPath {  }
+
+}
+
+
+::itcl::body pxitclyaleatlasgadget::AddToMenuButton { mb args} {
+
+    eval "$mb add command -label \"Yale Brodmann Areas Atlas Tool\" -command {$this ShowWindow }"
+}
+
+itcl::body pxitclyaleatlasgadget::InitializeYaleatlasgadget { } {
+
+    set thisparam($this,cx) 91
+    set thisparam($this,cy) 110
+    set thisparam($this,cz) 91
+    set thisparam($this,textbox) 0
+    set thisparam($this,aboutbox) 0
+    set thisparam($this,atlaspath) ""
+}
+
+itcl::body pxitclyaleatlasgadget::Initialize { widget } { 
+	
+    set basewidget [ toplevel $widget ]
+    wm geometry $basewidget 500x300
+    wm withdraw $basewidget
+
+    SetTitle "BioImage Suite Yale Atlas Tool"
+    
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    return $basewidget
+
+}
+
+itcl::body pxitclyaleatlasgadget::DelayedInitialize { } { 
+
+    set pbar         [ frame $basewidget.pbar    -width 400 -height 20 ]
+    set notebook $basewidget.notebook
+
+
+    iwidgets::tabnotebook $notebook  -tabpos n
+
+   set thisparam($this,atlaspath) [ label $basewidget.bot -text "Atlas not loaded." -bg black -fg white ]
+
+    pack $pbar $basewidget.bot    -side bottom -expand f -fill x -pady 1
+    pack $notebook -side top -expand t -fill both -pady 1
+
+    set idframe    [ $notebook add -label "Identify" ]
+    set aboutframe [ $notebook add -label "About" ]
+    $notebook view "Identify"
+
+    set f1 [ frame $idframe.t] ; 
+    set f15 [ label $idframe.t2 -text "" -bg black -fg white ]
+
+    pack $idframe.t $idframe.t2 -side top -expand false -fill x 
+    $idframe.t2 configure -text "Coordinates are in mm (R->L,A->P,I->S),origin=bottom corner of image"
+    $idframe.t2 configure -font { fixed 8}
+
+    set f2 [ frame $idframe.b] ; pack $idframe.b -side bottom -expand true -fill both    
+
+
+    label $f1.l -text "Point:"
+    iwidgets::entryfield $f1.x -labeltext "X (mm):"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,cx) ] -relief sunken 
+    iwidgets::entryfield $f1.y -labeltext "Y (mm):"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,cy) ] -relief sunken 
+    iwidgets::entryfield $f1.z -labeltext "Z (mm):"  -width 5 -validate real -textvariable [ itcl::scope thisparam($this,cz) ] -relief sunken 
+    eval "button $f1.b -text Identify -command { $this IdentifyInternalPoint }"
+    pack $f1.b -side right -expand f -padx 2
+    pack $f1.l $f1.x $f1.y $f1.z  -side left -expand true -fill x
+
+    update idletasks
+
+ 
+    for { set i 0 } { $i <= 1 } { incr i } {
+	frame $f2.topframe    
+	set textbox $f2.topframe.textbox; 
+	set ybar    $f2.topframe.ybar 
+	set xbar    $f2.xbar 
+	
+	eval "scrollbar $ybar  -command { $textbox yview } -orient vertical"
+	eval "scrollbar $xbar  -command { $textbox xview } -orient horizontal"
+	eval "text $textbox  -width 60 -height 10  -wrap word -relief ridge -yscrollcommand { $ybar set} -xscrollcommand {$xbar set}"
+	pack $xbar -side bottom -expand f -fill x 
+	pack $f2.topframe -side top -expand true -fill both -padx 0 -pady 5
+	pack $ybar -side right -expand false -fill y
+	pack $textbox -side left -expand true -fill both
+	$textbox configure -font { fixed 10 } 
+	if { $i == 0 } {
+	    set thisparam($this,textbox) $textbox
+	    set f2  $aboutframe
+	} else {
+	    set thisparam($this,aboutbox) $textbox
+	}
+    }
+
+    ::pxitclbasecontrol::SetWidgetTreeColors $idframe.b  "\#ffccdd" "black"
+
+    eval "button $pbar.r -text  Close -command {  $this HideWindow }"
+    eval "button $pbar.l -text \"Load Atlas Files\" -command {  $this LoadAtlas }"
+    pack $pbar.r  -side right -padx 10
+    pack $pbar.l -side left -padx 10
+
+    set canvas [ [ $notebook component tabset ] component canvas ];     
+    set l [ AddLogoLabel $canvas ];     
+    pack $l -side right -padx 1 
+
+
+    set fullyinitialized 1
+
+    if { $atlas_initialized == 1 } {
+	# Just update the textboxes ...
+	LoadAtlas
+    }
+    
+}
+
+
+::itcl::body pxitclyaleatlasgadget::LoadAtlas { } {
+
+    if { $atlas_initialized == 1 } {
+	set textbox $thisparam($this,aboutbox)
+	if { $textbox != 0 } {
+	    $textbox configure -state normal
+	    $textbox delete 1.0 end
+	    $textbox insert end $atlastext
+	    $textbox configure -state disabled
+	    $notebook view "About"
+	    $thisparam($this,atlaspath) configure -text $atlaspath
+	    update idletasks
+	}
+	return
+    }
+
+
+    set mfilename [ file normalize [ FindAtlasMasterPath ] ]
+
+    if { $mfilename == "" } {
+	set  atlasnotfound 1
+	return 0
+    }
+
+
+    set basedir [ file dirname $mfilename ]
+#    puts stderr "basedir = $basedir"
+
+    set fileid [open $mfilename r]
+    gets $fileid line
+#    puts stderr "line = $line"
+    if { [ string compare $line "#Atlas Description File"  ] != 0 } {
+	close $fileid
+	pxtclutil::Warning "Bad Atlas Description File $mfilename"
+	set  atlasnotfound 1
+	return 0
+    }
+
+
+
+    set imglist ""
+    set imgname ""
+
+
+    while { [ gets $fileid line ] >=0 } {
+#	puts stderr "line = $line"
+	if { [ string  first "#" $line ] != 0 } {
+	    set index [string first ":" $line]
+	    if { $index > 0 }  {
+		set len   [string length $line]
+		set key   [string trim   [string range $line 0 [expr $index - 1]]]
+		set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+#		puts stderr  "Parsing line $key $value"
+		lappend imglist $value
+		lappend imgname $key
+	    }
+	}
+    }
+    close $fileid
+    
+    set found 0
+    if { [ llength $imglist ] > 0 } {
+        set found [ FindAtlas $basedir $imglist ]
+    }
+    if { $found == 0 } {
+	set  atlasnotfound 1
+	return 0
+    }
+    set atlaspath "Atlas Location: [ file root [ file normalize $basedir]]"
+    set numatlases [ llength $imgname ]
+
+    pxtkprint "Loading Custom Yale Atlas\n"
+    for { set i 0 } { $i < [ llength $imgname ] } { incr i } {
+	set atlasimages($i) [  [ pxitclimage \#auto ] GetThisPointer ]
+	set fname [ file join $basedir [ lindex $imglist $i ] ]
+	$atlasimages($i) Load ${fname}.nii.gz
+	pxtkprint "Loaded [ lindex $imgname $i ] : [ $atlasimages($i) GetShortDescription ]\t"
+
+	set fname [ file join $basedir [ lindex $imglist $i ].txt ]
+	set fileid [open $fname r]
+	gets $fileid line
+	set ind [ string first "\[" $line ]; if { $ind < 0 } { set ind -1 }
+	set inp [ string first "\]" $line ]; if { $ind < 0 } { set inp [ string length $line ] }
+	set line [ string trim [ string range $line [ expr $ind +1 ] [ expr $inp -1 ]]]
+	set atlaslabels($i,description) $line
+	pxtkprint ", $atlaslabels($i,description)\n"
+	set atlaslabels($i,0) "None"
+	set atlasimagenameslen   [string length $line]
+
+	while { [ gets $fileid line ] >=0 } {
+	    regsub -all "\t" $line ":" line
+	    set index [string first ":" $line]
+	    if { $index > 0 }  {
+		set len   [string length $line]
+		set key   [string trim   [string range $line 0 [expr $index - 1]]]
+		set line [string trim [string range $line [expr $index +1] [expr $len -1]]]
+		set index [string first ":" $line]
+		if { $index > 0 } {
+		    set len   [string length $line]
+		    set value   [string trim   [string range $line 0 [expr $index - 1]]]
+		} else {
+		    set value $line
+		}
+		set atlaslabels($i,$key) $value
+	    }
+	}
+	close $fileid
+    }
+    
+    set atlastext ""
+    set atlastext "$atlastext BioImage Suite relies on a custom atlas for labels.\n"
+    set atlastext "$atlastext ------------------------------------------------------\n\n"
+    
+    set readme [ file join $basedir README.txt ]
+    if { [ file exists $readme ] } {
+	set fileid [open $readme r]
+	while { [ gets $fileid line ] >=0 } {
+	    set atlastext "$atlastext $line\n"
+	}
+	close $fileid
+    } 
+
+    set atlas_initialized 1
+
+    set textbox $thisparam($this,aboutbox)
+    if { $textbox != 0 } {
+	$textbox configure -state normal
+	$textbox delete 1.0 end
+	$textbox insert end $atlastext
+	$textbox configure -state disabled
+	$notebook view "About"
+	$thisparam($this,atlaspath) configure -text $mfilename
+	update idletasks
+    }
+    return
+}
+
+itcl::body pxitclyaleatlasgadget::IdentifyPoint { x y z }  {
+
+    set vx 0;    catch { set vx [ expr  ($x) ] }
+    set vy 0;    catch { set vy [ expr  ($y) ] }
+    set vz 0;    catch { set vz [ expr  ($z) ] }
+    set thisparam($this,cx) $vx
+    set thisparam($this,cy) $vy
+    set thisparam($this,cz) $vz
+
+    if { $atlas_initialized == 0 } { 
+	global pxtcl_pref_array
+	
+	set val $pxtcl_pref_array(YaleAtlasAutoInitialize)
+	    if { $val == "Enabled" } {
+		$this LoadAtlas
+	    }
+    }
+    return [ $this IdentifyInternalPoint ]
+}
+
+itcl::body pxitclyaleatlasgadget::IdentifyInternalPoint { } {
+
+    set textbox $thisparam($this,textbox) 
+    if { $textbox == 0 } {
+	return 0
+    }
+
+    $notebook view "Identify"
+    if { $atlas_initialized == 0 } {
+	set textbox $thisparam($this,textbox) 
+	$textbox configure -state normal
+	$textbox delete 1.0 end
+	$textbox insert end "Atlas Not Initialized!\n"
+	$textbox insert end "This tool requires that the Yale Atlas be installed\n"
+	$textbox insert end "This is extenral software and not distributed with BioImage Suite\n"
+	$textbox insert end "If it installed but cannot be found try setting the value of the\n environment variable YALEATLASDIR to point to the atlas location."
+	$textbox configure -state disabled
+	return 
+    } 
+
+
+    set namelist [ list cx cy cz ]
+    set maxlist  [ list 180 216 180 ]
+    for { set i 0 } { $i <=2 } { incr i } {
+	set key [ lindex $namelist $i ]
+	set max [ lindex $maxlist  $i ]
+	if { $thisparam($this,$key) < 0 } {
+	    set thisparam($this,$key) 0
+	} elseif { $thisparam($this,$key) > $max } {
+	    set thisparam($this,$key) $max
+
+	}
+    }
+
+    set x [ expr round($thisparam($this,cx)) ]
+    set y [ expr round($thisparam($this,cy)) ]
+    set z [ expr round($thisparam($this,cz)) ]
+
+    #    set x [ expr  90 - round($thisparam($this,cx)/2.0) ]
+    #    set y [ expr 108 - round($thisparam($this,cy)/2.0) ]
+    #    set z [ expr round($thisparam($this,cz)/2.0) ]
+
+    $textbox configure -state normal
+    $textbox delete 1.0 end
+
+    for { set atlas 0 } { $atlas < $numatlases } { incr atlas } {
+	set v [ expr round([ [ $atlasimages($atlas) GetImage ] GetScalarComponentAsDouble $x $y $z 0 ])]
+	set lab "$atlaslabels($atlas,$v)"
+	set txt [ format "%-15s  %-35s value=%d\n" "$atlaslabels($atlas,description):" $lab $v ]
+	$textbox insert end $txt
+#	puts stderr "text=*${txt}*"
+    }
+
+    $textbox insert end "\n(Original yale atlas location ijk=$x $y $z)\n"
+    $textbox insert end "Please note that all this is approximate .....\n"
+
+    $textbox configure -state disabled
+}
+
+itcl::body pxitclyaleatlasgadget::SetError { txt } { 
+
+    set textbox $thisparam($this,textbox) 
+    if { $textbox == 0 } {
+	return 0
+    }
+    $notebook view "Identify"
+    $textbox configure -state normal
+    $textbox delete 1.0 end
+    $textbox insert end $txt
+    $textbox configure -state disabled
+}
+
+itcl::body pxitclyaleatlasgadget::FindAtlas { basedir imagelist } {
+
+    set numfound 0
+    for { set j 0 } { $j < [ llength $imagelist ] } { incr j } {
+	set imgname [ file join $basedir [ lindex $imagelist $j].nii.gz ]
+	#	puts stderr "Looking for $imgname"
+
+	set ok [ file exists $imgname ] 
+	set numfound [ expr $numfound + $ok ]
+    }
+    
+    if { $numfound != [ llength $imagelist ] } {
+	pxtclutil::Warning "Custom Atlas Not Found in the standard places\n Try Setting the value of the environment variable YALEATLASDIR to point to this."
+	return 0
+    }
+
+    return 1
+}
+
+itcl::body pxitclyaleatlasgadget::FindAtlasMasterPath { } {
+
+    global tcl_platform 
+    global env
+    set pathlist ""
+
+    set a ""
+    catch { set a $env(YALEATLASDIR) }
+    if { $a != "" } {
+	lappend pathlist $a
+    }
+
+    set base $::pxtclvtkpxcontrib::imagedir
+    lappend pathlist [ file normalize $base ]
+    set base [ file normalize "${base}/../../yale_atlas" ]
+    lappend pathlist $base
+
+
+    if { $tcl_platform(platform) == "windows" } { 
+	lappend pathlist "c:/yale/yale_atlas"
+    } else {
+	lappend pathlist /usr/local/yale_atlas/ 
+    }
+
+    set found 0
+    set index 0
+    set output ""
+
+    #    puts stdout "pathlist=$pathlist, base=$base"
+
+    while { $index < [ llength $pathlist ] } {
+	set testpath [ lindex $pathlist $index ]
+	set numfound 0
+
+	set fname [ file join $testpath bioimagesuite_atlas.txt ] 
+#	puts stderr "Looking for $fname"
+	set found [ file exists $fname ] 
+	if { $found == 1 } {
+	    set output $fname
+	    set index [ llength $pathlist ]
+	}
+#	puts stderr "$fname , $found"
+	incr index
+    }
+
+    if { $found == 0 } {
+	pxtclutil::Warning "Yale Atlas Not Found in the standard places\n Looked in $pathlist\n Try Setting the value of the environment variable YALEATLASDIR to point to this."
+    }
+
+    return $output
+}
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/CMakeLists.txt b/bioimagesuite30_src/bioimagesuite/mjack/CMakeLists.txt
new file mode 100644
index 0000000..a4630a1
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/CMakeLists.txt
@@ -0,0 +1,69 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+
+
+SET(KITSCRIPTS
+    pkgIndex.tcl
+    mpjfastmarching.tcl
+    mpjfibertracking.tcl
+    mpjguiicosahedron.tcl
+    mpjguilookuptable.tcl
+    mpjguiobject.tcl
+    mpjguisphere.tcl
+    mpjmultiimagegui.tcl
+    mpjmultiobjectgui.tcl
+    mpjtensoranalysis.tcl
+    mpjtensorutility.tcl
+    mpjvesselanalysis.tcl
+    mpjvesseltracking.tcl
+    mpjvesselutility.tcl
+    mpjmultibtensorutility.tcl
+    vtkmpjcontrib.tcl
+)
+
+SET(KITAPPS
+#    mpjarithmetic.tcl
+    mpjdiffusiontool.tcl
+#    mpjextractframe.tcl
+    mpjinterleave.tcl
+#    mpjraw2analyze.tcl
+    mpjsigna2analyze.tcl
+    mpjt2relax.tcl
+    mpjvesseltool.tcl
+)
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+bis_complex_tcl(bioimagesuite/mjack ${FILELIST2} ${FILELIST})
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjdiffusiontool.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjdiffusiontool.tcl
new file mode 100755
index 0000000..6350c3c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjdiffusiontool.tcl
@@ -0,0 +1,129 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# 	$Id: pxitclbrainsegment.tcl,v 1.2 2004/12/16 16:10:43 xenios Exp xenios $	
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package require vtkpxcontrib  1.1
+package require vtkmpjcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+package require mpjtensorutility 1.2
+package require mpjmultibtensorutility 1.3
+package require mpjtensoranalysis 1.2
+package require mpjfibertracking 1.2
+#package require mpjconnectivity 1.0 
+#option add *textBackground seashell
+
+wm withdraw .
+
+set breg [ pxitclbaseimageviewer \#auto 0 ]
+$breg configure -appname "BioImage Suite::Diffusion Tool"
+$breg configure -show_standard_images 1
+$breg configure -enable_helpmenu 0
+$breg configure -enable_multisubjectcontrol 0
+$breg configure -enable_overlaytool 0
+$breg configure -enable_vvlinkgadget  1
+$breg configure -enable_talaraichoption 1
+$breg configure -enable_rendering_on_startup  0
+$breg InitializeObjectmapViewer .[pxvtable::vnewobj ] 1
+
+set menubase [ $breg cget -menubase ]
+set mb [ menu $menubase.diffusionm -tearoff 0  ]
+$menubase add cascade  -label "Diffusion" -menu $menubase.diffusionm -underline 4
+
+
+set tensorutil [ mpjtensorutility \#auto $breg ]
+$tensorutil Initialize [ $breg GetBaseWidget ].[ pxvtable::vnewobj ]
+$breg AddControl $tensorutil
+$tensorutil AddToMenuButton $mb
+### multi b value tensor
+
+
+
+global pxtcl_pref_array
+if { $pxtcl_pref_array(EnableBetaFeatures) != "Disabled" } {
+    set multibtensorutil [ mpjmultibtensorutility \#auto $breg ]
+    $multibtensorutil Initialize [ $breg GetBaseWidget].[pxvtable::vnewobj]
+    $breg AddControl $multibtensorutil
+    $multibtensorutil AddToMenuButton $mb 
+}
+
+set tensoranal [ mpjtensoranalysis \#auto $breg ]
+$tensoranal Initialize [ $breg GetBaseWidget ].[ pxvtable::vnewobj ]
+$breg AddControl $tensoranal
+$tensoranal AddToMenuButton $mb 
+
+
+set fibertrack [ mpjfibertracking \#auto $breg ]
+$fibertrack Initialize [ $breg GetBaseWidget ].[ pxvtable::vnewobj ]
+$fibertrack AddToMenuButton $mb
+$breg AddControl $fibertrack
+#set connectivity [ mpjconnectivity \#auto $breg ]
+
+
+
+
+
+
+
+$breg CreateHelpMenu
+$breg ShowWindow   
+
+
+[ $breg GetViewer ] SetEnableRendering 1
+
+if { $argc > 0 } { 
+
+    if { [ lindex $argv 0 ] == "mpjfibertracking" } {
+
+	if { $argc > 1 } {  $fibertrack LoadTensor [lindex $argv 1]   }
+	if { $argc > 2 } {  $fibertrack LoadMask [lindex $argv 2]   }
+	if { $argc > 3 } {  $fibertrack LoadMap [lindex $argv 3]; $fibertrack DisplayResult 2   
+	    $fibertrack ShowWindow
+	}
+    }
+}
+
+	    
+[ $breg GetViewer ] SetDisplayMode 2
+
+update idletasks
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjfastmarching.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjfastmarching.tcl
new file mode 100644
index 0000000..7d903bf
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjfastmarching.tcl
@@ -0,0 +1,3911 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package provide mpjfastmarching 1.2
+
+package require  Itcl 3.2
+package require  Iwidgets 4.0
+
+package require  pxitcllistselector 1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitclbaseimageviewer 1.0
+
+package require  vtkmpjcontrib 1.1
+package require  mpjguilookuptable 1.0
+
+itcl::class mpjfastmarching {
+
+    inherit pxitclbaseimagecontrol
+    
+    #-----------------------------------
+    # construction and destruction
+    #-----------------------------------
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } { InitializeControl }
+    
+    destructor { }
+
+    #-----------------------------------
+    # global variables
+    #-----------------------------------
+    private variable widget_list
+    private variable global_list
+    
+    #-----------------------------------
+    # initialization methods
+    #-----------------------------------
+    public method Initialize { inpwidg }
+    public method InitializeControl { }
+    public method DismissWindow { }
+    
+    #-----------------------------------
+    # input/output
+    #-----------------------------------
+    public method LoadMap { fname }
+    public method LoadMask { fname }
+    public method LoadSpeed { fname }
+    public method LoadBoundary { fname }
+    public method SaveAllResults { }
+    public method SaveResult { index }
+    public method ClearAllResults { }
+    public method DisplayResult { index }
+    public method ClearDisplay { }
+    public method SetResultPreffix { preffix }
+    public method GetResultPreffix { } 
+    
+    #-----------------------------------
+    # interface creation methods
+    #-----------------------------------
+    private method CreateInputControl { base }
+    private method CreatePropagationControl { base }
+    private method CreateTrackingControl { base }
+    private method CreateDisplayControl { base }
+    private method CreatePathwayControl { base }
+    private method CreateStatisticsControl { base }
+    private method CreateResultsControl { base }
+    private method CreatePathDisplayControl { base }
+    private method CreateFrontDisplayControl { base }
+    private method CreateMenu { mb }
+    public method AddToMenuButton { mb args}    
+    public method CreateViewMenu { menubase }
+ 
+    private method loadmap { }
+    private method loadspeed { }
+    private method loadmask { }
+    private method loadboundary { }
+    private method displayresult { }
+    private method saveresult { }
+    private method toggleresult { }
+    private method saveallresults { }
+ 
+    private method initialize_glyphs { }
+    private method input_updateinfo { index }    
+    private method input_selectioncommand_cb { }
+        
+    private method track_seedtype_cb { }
+    private method track_map_cb { }
+    private method track_integration_cb { }
+    private method track_regionfilter_cb { }
+    private method track_splinetype_cb { }
+    private method track_splinesubdivision_cb { }
+
+    private method view_colorbar_cb { } 
+    private method view_update_display_cb { }
+    private method view_clear_display { }
+    private method view_update_display { }
+    private method view_toggle_colorbar { }
+    private method view_toggle_contour { }
+    private method view_toggle_fiber { }
+    private method view_toggle_gradient { }
+    private method view_toggle_character { }
+
+    private method view_create_fiber_glyph { index }
+    private method view_create_paths { }
+    private method view_create_colorbar { }
+    private method view_create_contour { }
+    private method view_create_contour_glyph { scalars } 
+    private method view_create_gradient { }
+    private method view_create_gradient_glyph { scalars glyph }
+    private method view_create_character { }
+    private method view_create_character_glyph { scalars vectors glyph }
+
+    private method view_extract_roi { exts image } 
+    private method view_compute_roi_extents { orient dim levels }
+
+    private method solution_method_cb { }
+    private method solution_autospacing_cb { }
+    private method solution_stopping_cb { }
+
+    private method view_fiber_glyph_cb { }
+    private method view_fiber_tuberadius_cb { }
+    private method view_fiber_pointsize_cb { }
+    private method view_fiber_colormap_cb { }
+    private method view_fiber_filter_cb { }
+    private method view_fiber_luktype_cb { }
+      
+    private method fiber_add { polydata }
+    private method fiber_addwithname { name polydata }
+    private method fiber_remove { index } 
+    private method fiber_removeselected { }
+    private method fiber_clear { }
+    private method fiber_load { }
+    private method fiber_save { index name }
+    private method fiber_saveall { }
+    private method fiber_saveselected { }
+    private method fiber_track { }
+    private method fiber_statistics { }
+    private method fiber_error { }
+    private method fiber_threshold { }
+    private method fiber_quantize { }
+    private method fiber_addstatistics { title results tag }
+    private method fiber_beginstatistics { title overwrite }
+    private method fiber_savestatistics { }
+    private method fiber_selection_cb { }
+    private method fiber_color_cb { }
+    private method fiber_name_cb { }
+    private method fiber_display_cb { }
+    
+    private method result_clear { }
+    private method result_initneighbors { dim source new_source } 
+    private method result_propagate { }
+    private method update_list { node }    
+    public method PropagationCallback { filter comment } 
+
+    private method savedir_dialog { base initdir title }
+    private method openfile_dialog { base initdir title mask }
+}  
+
+#-------------------------------------------------------------------------------------------
+#  Close window 
+# -------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::DismissWindow { } {
+    
+    set ok "yes"
+
+    if { $global_list(speed_fname) != "" } {
+
+	set ok [ tk_messageBox -type yesnocancel -default no \
+		     -parent $basewidget -title "Think again ..." \
+		     -message "Unload all images from memory?" -icon question  ]
+    }
+    
+    if { $ok == "yes" } {	
+	
+	fiber_clear
+	
+	view_clear_display 
+	
+	$this ClearAllResults
+
+	$this SetTitle $appname
+	
+	set global_list(mask_fname) ""
+	set global_list(speed_fname) ""
+	
+    }
+    
+    if { $ok != "cancel" } {
+	$this HideWindow
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  Initialize tool
+# -------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::InitializeControl { } {
+
+    set appname "Fast Marching Utility v1.2"
+    set aboutstring "(c) Marcel Jackowski 2005"
+
+    # create list of basic colors
+    set global_list(tkcolor_list) "\#ff0000 \#ffff00 \#00ff00 \#00ffff \#0000ff \#ff00ff"
+    
+    # create image titles
+    set global_list(result_title) \
+	[ list \
+	      { "Speed image"           "fmm_speed" 0 } \
+	      { "Mask"                  "fmm_mask" 0 } \
+	      { "Propagation solution"  "fmm_solution" 1 } \
+	      { "Map image"             "fmm_map" 1 } \
+	      { "Pathway quantization"  "fmm_path" 1 }  \
+	      { "Gradient image"        "fmm_grad" 1 } ] \
+    
+    foreach item $global_list(result_title) {
+ 	lappend result_list [ pxitclimage \#auto ]
+    }  
+    
+    set global_list(result_fdir) [ pwd ]
+    set global_list(result_fpreffix) "preffix_"
+    set global_list(result_list) $result_list
+    
+    set global_list(mask_fname) ""
+    set global_list(mask_nreg) 1
+    
+    set global_list(speed_fname) ""    
+    set global_list(map_fname) ""
+
+    set global_list(speed_symm) 1
+    
+    set global_list(boundary_fname) ""
+
+    set global_list(solution_seeds) [ vtkFloatArray [ pxvtable::vnewobj ] ]
+    $global_list(solution_seeds) SetNumberOfComponents 4
+    $global_list(solution_seeds) InsertNextTuple4 0 0 0 0
+
+    set global_list(solution_useboundary) 0
+    set global_list(solution_initneighbors) 1
+    set global_list(solution_usemask) 0
+    set global_list(solution_reuse) 0
+    set global_list(solution_maxiter) 10
+    set global_list(solution_maxerror) 1.0
+    set global_list(solution_autospacing) 1
+    set global_list(solution_spacingx) 1.0
+    set global_list(solution_spacingy) 1.0
+    set global_list(solution_spacingz) 1.0
+    set global_list(solution_stopping) 0
+    set global_list(solution_stoptime) 1000.0
+    set global_list(solution_error) 0
+    set global_list(solution_errorlabel) "Error: 0.0"
+    set global_list(solution_method) 0
+    set global_list(solution_inf) 32767
+    set global_list(solution_a) 3
+    set global_list(solution_b) 2
+    set global_list(solution_c) 1
+    
+    set global_list(track_seedtype) 0
+    set global_list(track_map) 0
+    set global_list(track_seedregion) 1
+    set global_list(track_seedwidth) 3
+    set global_list(track_seedheight) 3
+    set global_list(track_seeddepth) 3
+    set global_list(track_seeddens) 1.0  
+    set global_list(track_integration) 1
+    set global_list(track_steplen) 0.25
+    set global_list(track_minspeed) 0.0
+    set global_list(track_maxdist) 100.0
+    set global_list(track_mindist) 10.0
+    set global_list(track_fitspline) 0
+    set global_list(track_splinetype) 0
+    set global_list(track_splinesubdivision) 0
+    set global_list(track_splinelength) 0.1
+    set global_list(track_splinenumber) 100
+    set global_list(track_regionfilter) 0
+    set global_list(track_regionnumber) 1
+    set global_list(track_autostat) 1
+    set global_list(track_flipping) 0
+    set global_list(track_flipx) 0
+    set global_list(track_flipy) 0
+    set global_list(track_flipz) 0
+
+    set global_list(fiber_display) 1
+    set global_list(fiber_color) "\#ff0000"
+    set global_list(fiber_list) {}
+    set global_list(fiber_color_list) {}
+    set global_list(fiber_disp_list) {}
+    set global_list(fiber_thresh_val) 0.0
+    set global_list(fiber_thresh_dist) 1.0
+    
+    set global_list(stat_overwrite) 0
+
+    set global_list(view_colorbar) 0 
+    set global_list(view_colorbar_label) "Label"
+    set global_list(view_fiber) 0
+    set global_list(view_fiber_tuberadius) 0.20
+    set global_list(view_fiber_pointsize) 1.0
+    set global_list(view_contour) 0
+    set global_list(view_contour_levels) 10
+    set global_list(view_contour_from) 0
+    set global_list(view_contour_to) 1000
+    set global_list(view_contour_width) 2.0
+    set global_list(view_gradient) 0
+    set global_list(view_character) 0
+    set global_list(view_fiber_luktype) 0
+    
+    ## create actors for visualization
+    set global_list(actor_colorbar) -1
+    set global_list(actor_fiber) {}
+    set global_list(actor_contour) [list -1 -1 -1 ]
+    set global_list(actor_gradient) [list -1 -1 -1]
+    set global_list(actor_character) [list -1 -1 -1]
+
+    ## vtk data
+    set global_list(vtk_fiber_tube) {}
+    set global_list(vtk_fiber_polydata) {}
+    
+    initialize_glyphs
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create visualization glyphs
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::initialize_glyphs { } {
+
+    ## create line source
+    set line_src [ vtkLineSource [ pxvtable::vnewobj ] ]
+    $line_src SetPoint1 0.0 0 0
+    $line_src SetPoint2 2.0 0 0    
+
+    set line_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $line_xfrm Translate -1.0 0.0 0.0
+
+    set line [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $line SetInput [ $line_src GetOutput ]
+    $line SetTransform $line_xfrm
+    lappend global_list(glyph_list) $line 
+
+    $line_src Delete
+    $line_xfrm Delete
+    
+    ## create tube source
+    set tube_src [ vtkCylinderSource [ pxvtable::vnewobj ] ]
+    $tube_src SetHeight 2.0
+    $tube_src SetRadius 0.25
+    $tube_src CappingOn
+    
+    set tube_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $tube_xfrm RotateZ -90.0
+    
+    set tube [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $tube SetInput [ $tube_src GetOutput ]
+    $tube SetTransform $tube_xfrm
+    lappend global_list(glyph_list) $tube
+
+    $tube_src Delete
+    $tube_xfrm Delete
+
+    ## create arrow source
+    set arrow_src [ vtkArrowSource [ pxvtable::vnewobj ] ]
+    $arrow_src SetTipLength 0.35
+    $arrow_src SetTipResolution 10
+    $arrow_src SetTipRadius 0.20
+    $arrow_src SetShaftResolution 10
+    $arrow_src SetShaftRadius 0.1
+
+    set arrow_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $arrow_xfrm Translate -1.0 0.0 0.0
+    $arrow_xfrm Scale 2.0 2.0 2.0
+
+    set arrow [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $arrow SetInput [ $arrow_src GetOutput ]
+    $arrow SetTransform $arrow_xfrm
+    lappend global_list(glyph_list) $arrow
+
+    $arrow_src Delete
+    $arrow_xfrm Delete
+    
+    ## create ellipsoid source
+    set ellipsoid_src [ vtkSphereSource [ pxvtable::vnewobj ] ]
+    set ellipsoid_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $ellipsoid_xfrm Scale 2.0 2.0 2.0
+
+    set ellipsoid [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $ellipsoid SetInput [ $ellipsoid_src GetOutput ]
+    $ellipsoid SetTransform $ellipsoid_xfrm
+    lappend global_list(glyph_list) $ellipsoid
+
+    $ellipsoid_src Delete
+    $ellipsoid_xfrm Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load speed
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::loadboundary { } {
+
+    ## browse for filename
+    set fname  [tk_getOpenFile -title "Select boundary conditions" -filetypes { {"Text" {.txt}}} -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadBoundary $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in speed image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::LoadBoundary { fname } {
+    
+    if { [ string length $fname ] < 1 } {
+        return
+    }
+    
+    if { [ file readable $fname ] == 0 } {
+        ::pxtclutil::Warning "Cannot read boundary conditions from file $fname\n Bad File"        
+	return 0
+    }
+
+    set fileid [open $fname r]
+
+    $global_list(solution_seeds) Reset
+    $global_list(solution_seeds) SetNumberOfComponents 4
+
+    ## read number of points
+    gets $fileid total
+    
+    for { set i 0 } { $i < $total } { incr i } {
+        
+	gets $fileid tmp_point
+	
+	scan $tmp_point "%f %f %f %f" px py pz val
+	
+	$global_list(solution_seeds) InsertNextTuple4 $px $py $pz $val
+	
+    }
+
+    close $fileid
+    
+    set global_list(boundary_fname) $fname    
+    $widget_list(boundary_fname) configure -state normal
+    $widget_list(solution_useboundary) configure -state normal
+    set global_list(solution_useboundary) 1
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load mask
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::loadmask { } {
+    
+    ## browse for filename
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select mask" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadMask $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in mask image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::LoadMask { fname } {
+
+    set MASK 1     
+    set mask [ lindex $global_list(result_list) $MASK ]
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    $this SetFilterCallbacks $ana "Reading in mask image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    ## if mask not a unsigned char image, convert it
+    set scalar_type [ [ $ana GetOutput ] GetScalarType ]    
+
+    if { $scalar_type != 3 } {	
+	
+	set imcast [ vtkImageCast [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $imcast "Converting mask to unsigned char values..."
+	$imcast SetInput [ $ana GetOutput ]
+	$imcast SetOutputScalarTypeToUnsignedChar
+	$imcast ClampOverflowOn	
+	$imcast Update
+	
+	$mask ShallowCopyImage [ $imcast GetOutput ]
+	
+	$imcast Delete
+	
+    } else {
+	
+	$mask SetFromAnalyzeSource $ana
+    }
+   
+    ## determine range of values in mask
+    set range [ [ [ [ $mask GetImage ] GetPointData ] GetScalars ] GetRange ]
+
+    ## take the maximum range as the number of regions in mask
+    set global_list(mask_nreg) [ lindex $range 1 ]    
+    $widget_list(mask_nreg) configure -range [ list 1 $global_list(mask_nreg) ]
+    
+    set global_list(mask_fname) $fname
+
+    WatchOff
+
+    $ana Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load map
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::loadmap { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select map" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load map into memory
+	LoadMap $fname
+    }    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in map image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::LoadMap { fname } {
+    
+    set SPEED 0
+    set MASK 1
+    set MAP 3
+    set PATHS 3
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in map image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    [ lindex $global_list(result_list) $MAP ] SetFromAnalyzeSource $ana
+    
+    set global_list(map_fname) $fname
+    
+    WatchOff
+    
+    $ana Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load speed
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::loadspeed { } {
+
+    ## browse for filename
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select speed image" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadSpeed $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in speed image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::LoadSpeed { fname } {
+
+    set SPEED 0
+    set MASK 1
+    set MAP 3
+    set PATHS 3
+
+    set speed [ lindex $global_list(result_list) $SPEED ]
+    set paths [ lindex $global_list(result_list) $PATHS ]
+    set map [lindex $global_list(result_list) $MAP ]
+
+    WatchOn
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in speed image..."
+    
+    ## load series 
+    $ana Load $fname 
+
+    $speed SetFromAnalyzeSource $ana
+
+    set global_list(speed_fname) $fname
+
+    ## determine coordinate transform
+    set or [ $ana GetOrientation ]
+
+    $ana Delete
+
+    scan [ [ $speed GetImage ] GetDimensions ] "%d %d %d" dx dy dz	       
+    set nc [ [ $speed GetImage ] GetNumberOfScalarComponents ]
+    set name [ file tail [ file root $fname ] ]
+        
+    set global_list(speed_symm) [ expr $nc == 6 ]
+
+    set sufpos [ string last "fmm_speed" $name ]
+    if { $sufpos != -1 } {
+	set name [ string range $name 0 [expr $sufpos - 1] ]
+    }
+
+    ## create fiber image
+    set ext [ vtkImageExtractComponents [ pxvtable::vnewobj ] ]
+    $ext SetInput [ $speed GetImage ]
+    $ext SetComponents 0
+    $ext Update
+
+    $paths CopyImageHeader [ $speed GetImageHeader ]
+    $paths ShallowCopyImage [ $ext GetOutput ]
+    $ext Delete
+
+    set global_list(result_fdir) [ file dir $fname ]
+    set global_list(result_fpreffix) [ file join $global_list(result_fdir) "${name}" ]
+
+    set global_list(speed_fname) $fname
+    
+    WatchOff
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Set result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::SetResultPreffix { preffix } {
+    set global_list(result_fpreffix) $preffix
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Get result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::GetResultPreffix { } {
+    return $global_list(result_fpreffix)
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Clear all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::ClearAllResults { } {
+    
+    foreach result $global_list(result_list) {
+	$result Clear
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::SaveAllResults { } {
+
+    foreach result $global_list(result_list) title $global_list(result_title) {
+	
+	set fname $global_list(result_fpreffix)
+	set fname "$fname[ lindex $title 1 ]"
+	
+	$result Save $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save single result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::SaveResult { index } {        
+
+    set fname $global_list(result_fpreffix)
+    set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]"
+
+    [lindex $global_list(result_list) $index] Save $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::saveallresults { } {
+
+    ## browse for directory
+    set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+    
+    if { $fdir != "" } {
+	
+	set global_list(result_fdir) $fdir
+	
+	foreach result $global_list(result_list) title $global_list(result_title) {
+	    
+	    set fname $global_list(result_fpreffix)
+	    set fname "$fname[ lindex $title 1 ]"
+	    
+	    $result Save [ file join $fdir $fname ]
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::saveresult { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(result_list) getcurselection ]
+    
+    if { $sel_item != "" } { 
+
+	## browse for directory
+	set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+	
+	if { $fdir != "" } {
+	    
+	    set global_list(result_fdir) $fdir
+	    
+	    foreach item $sel_item {
+		
+		set index [ $widget_list(result_list) index $item ]
+		set result [ lindex $global_list(result_list) $index ]
+		
+		set fname $global_list(result_fpreffix)
+		set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]"
+		
+		$result Save [ file join $fdir $fname ]
+	    }
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::DisplayResult { index } {
+    $parent SetImageFromObject \
+	[ [ lindex $global_list(result_list) $index ] GetThisPointer ] $this
+    $parent ShowWindow
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::displayresult { } {
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+	    
+    if { $sel_item != "" } {
+	set index [ $widget_list(result_list) index [ lindex $sel_item 0 ] ]
+	set result [ lindex $global_list(result_list) $index ]
+	
+	$this DisplayResult $index	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: toggle result computation on/off
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::toggleresult { } {
+   
+    set color(0) \#dcdcdc
+    set color(1) black
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+
+    if { $sel_item != "" } {
+
+	set index [ $widget_list(result_list) index [ lindex $sel_item 0 ] ]
+
+	if { $index > 2 } {
+	    set enable [expr 1 - [ lindex [ lindex $global_list(result_title) $index ] 2 ] ]
+	    
+	    $widget_list(result_list) itemconfigure $index -foreground $color($enable)
+	    
+	    set item [ lindex $global_list(result_title) $index ]
+	    set new_item [ lreplace $item 2 2 $enable ]
+	    
+	    set global_list(result_title) [ lreplace $global_list(result_title) \
+						$index $index $new_item ]
+	}
+    }
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::result_clear { } {
+    for { set i 0 } { $i < [ llength $global_list(result_list) ] } { incr i } {		
+	if { $i > 0 } {	    
+	    
+	    set title [ lindex [ lindex $global_list(result_title) $i ] 0 ]	    	    
+	    
+	    if { $title == "Region of interest mask" } {
+		if { $global_list(mask_auto) } {
+		    [ lindex $global_list(result_list) $i ] Clear
+		}
+	    } elseif { $title != "Propagation solution" } {
+		[ lindex $global_list(result_list) $i ] Clear
+	    }
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear display
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_clear_display { } {
+    
+    ## remove paths
+    foreach actor $global_list(actor_fiber) {	    
+	if { $actor != "-1" } {
+	    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+	    $actor Delete	    
+	}
+	set global_list(actor_fiber) {}
+    }
+    
+    ## remove contours
+    foreach actor $global_list(actor_contour) {	    
+	if { $actor != "-1" } {
+	    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+	    $actor Delete	    
+	}
+	set global_list(actor_contour) [list -1 -1 -1]
+    }
+
+    ## remove colorbar
+    set actor $global_list(actor_colorbar)
+    if { $actor != "-1" } {
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+	$actor Delete	   
+	set global_list(actor_colorbar) -1
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Update display
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_update_display { } {
+    
+    if { $global_list(view_colorbar) } {
+	view_create_colorbar
+    }
+    
+    if { $global_list(view_contour) } {
+	view_create_contour
+    }
+
+    if { $global_list(view_gradient) } {
+	view_create_gradient
+    }
+    
+    if { $global_list(view_character) } {
+	view_create_character
+    }    
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off colorbar visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_toggle_colorbar { } {
+    
+    if { $global_list(view_colorbar) } {
+	view_create_colorbar
+    } else {
+	set actor $global_list(actor_colorbar)
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor
+	$actor Delete
+
+	set global_list(actor_colorbar) -1
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off contour visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_toggle_contour { } {
+    
+    if { $global_list(view_contour) } {	
+	view_create_contour
+    } else { 
+	foreach actor $global_list(actor_contour) {
+	    if { $actor != "-1" } {
+		for { set j 0 } { $j < 4 } { incr j } {
+		    [ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] RemoveActor $actor
+		}
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_contour) [ list -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off gradient visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_toggle_gradient { } {
+    
+    if { $global_list(view_gradient) } {	
+	view_create_gradient
+    } else { 
+	foreach actor $global_list(actor_gradient) {
+	    if { $actor != "-1" } {
+		for { set j 0 } { $j < 4 } { incr j } {
+		    [ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] RemoveActor $actor
+		}
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_gradient) [ list -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off characteristic visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_toggle_character { } {
+    
+    if { $global_list(view_character) } {	
+	view_create_character
+    } else { 
+	foreach actor $global_list(actor_character) {
+	    if { $actor != "-1" } {
+		for { set j 0 } { $j < 4 } { incr j } {
+		    [ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] RemoveActor $actor
+		}
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_character) [ list -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  View fiber bundle
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_create_fiber_glyph { index } {
+
+    set field(0) fractani
+    set field(1) meandiff
+    set field(2) distance
+    set field(3) angle
+    set field(4) roi
+    set field(5) other
+
+    ## create mapper
+    set fiberMapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_fiber_glyph) \
+			index [ $widget_list(view_fiber_glyph) get ] ]
+    
+    ## get current fiber colormap filter    
+#    set filter [ $widget_list(view_fiber_filter) index [ $widget_list(view_fiber_filter) get ]]
+
+    if { $cur_glyph == 1 } {
+	set tube [ lindex $global_list(vtk_fiber_tube) $index ]
+	
+	$tube SetInput [ lindex $global_list(vtk_fiber_polydata) $index ]
+	$tube SetRadius $global_list(view_fiber_tuberadius)
+	$tube SetNumberOfSides 6
+	$tube Update
+
+	$fiberMapper SetInput [ $tube GetOutput ]	
+	$fiberMapper SetLookupTable [ $widget_list(view_fiberluk) GetLookupTable ]
+	$fiberMapper UseLookupTableScalarRangeOn
+	
+	if { $global_list(view_fiber_luktype) == 0 } {
+	    $fiberMapper SetScalarModeToUsePointData
+	} else {
+	    $fiberMapper SetScalarModeToUseCellData
+	}
+
+	#$fiberMapper ColorByArrayComponent $field($filter) 0
+
+	if { $global_list(view_fiber_luk) } {	    
+	    $fiberMapper ScalarVisibilityOn
+	} else {
+	    $fiberMapper ScalarVisibilityOff
+	}
+
+	
+
+    } 
+
+    if { [expr $cur_glyph == 0 || $cur_glyph == 2 ] } {
+	
+	set polydata [ lindex $global_list(vtk_fiber_polydata) $index ]
+	$fiberMapper SetInput $polydata
+	$fiberMapper SetLookupTable [ $widget_list(view_fiberluk) GetLookupTable ]
+	$fiberMapper UseLookupTableScalarRangeOn
+	
+	if { $global_list(view_fiber_luktype) == 0 } {
+	    $fiberMapper SetScalarModeToUsePointData
+	} else {
+	    $fiberMapper SetScalarModeToUseCellData
+	}
+
+	#$fiberMapper SetScalarModeToUseCellData
+	#$fiberMapper ColorByArrayComponent $field($filter) 0
+
+	if { $global_list(view_fiber_luk) } {	    
+	    $fiberMapper ScalarVisibilityOn
+	} else {
+	    $fiberMapper ScalarVisibilityOff
+	}
+    }
+
+
+    ## create actor
+    set fiberActor [ vtkActor [ pxvtable::vnewobj ] ]
+    $fiberActor SetMapper $fiberMapper
+    
+    if { $cur_glyph == 2 } {
+	[ $fiberActor GetProperty ] SetRepresentationToPoints
+	[ $fiberActor GetProperty ] SetPointSize $global_list(view_fiber_pointsize)
+    }
+    
+    $fiberMapper Delete
+    
+    ## convert tk color spec to vtk
+    set color [ lindex $global_list(fiber_color_list) $index ]
+    set red "0x[string range $color 1 2]"
+    set green "0x[string range $color 3 4]"
+    set blue "0x[string range $color 5 6]"
+    set red [ expr [ format "%d" $red ] / 255.0 ]
+    set green [ expr [ format "%d" $green ] / 255.0 ]
+    set blue [ expr [ format "%d" $blue ] / 255.0 ]
+    
+    [ $fiberActor GetProperty ] SetColor $red $green $blue
+    
+    return $fiberActor
+}
+
+#-------------------------------------------------------------------------------------------
+#  View paths
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_create_paths { } {    
+
+    set num [ llength $global_list(fiber_list) ]
+    
+    for {set j 0} {$j < $num} {incr j} {
+	
+	set actor [ view_create_fiber_glyph $j ]
+	
+	lappend global_list(actor_fiber) $actor
+	
+	## add actor if to be displayed
+	if { [ lindex $global_list(fiber_disp_list) $j ] == 1 } { 
+	    for { set j 0 } { $j < 4 } { incr j } {
+		[ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] AddActor $actor	
+	    }
+	}
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  View colorbar
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_create_colorbar { } {
+        
+#    set title [ $widget_list(view_fiber_filter) get ]
+    set title $global_list(view_colorbar_label)
+    
+    set bar [ vtkScalarBarActor [ pxvtable::vnewobj ] ]
+    $bar SetLookupTable [ $widget_list(view_fiberluk) GetLookupTable ]
+    
+    $bar SetTitle $title
+    [$bar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport
+    [$bar GetPositionCoordinate] SetValue 0.1 0.01
+    $bar SetOrientationToHorizontal
+    $bar SetWidth 0.8
+    $bar SetHeight 0.12
+    
+    set global_list(actor_colorbar) $bar
+    
+    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor2D $bar    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Compute ROI extents
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_compute_roi_extents { orient dim levels } {
+   
+    set x0(0) 0; set x0(1) 0; set x0(2) 0;
+    set x1(0) [expr [lindex $dim 0] -1]
+    set x1(1) [expr [lindex $dim 1] -1]
+    set x1(2) [expr [lindex $dim 2] -1]
+    
+    if { $orient < 3 } {
+
+	## set up slice geometry
+	for { set i 0 } { $i < 3 } { incr i } {
+	    if { $i == $orient } {
+		set x0($i) [lindex $levels $i]
+		set x1($i) [lindex $levels $i]
+	    }
+	}
+    }
+    
+    return "$x0(0) $x0(1) $x0(2) $x1(0) $x1(1) $x1(2)"
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Extract ROI given image and computed extents
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_extract_roi { exts image } {
+    
+    set dim [ [ $image GetImage ] GetDimensions ]
+    set spac [ [ $image GetImage ] GetSpacing ]
+    set orig [ [ $image GetImage ] GetOrigin ]
+    set ospac "1 1 1"
+    
+    set x0(0) [lindex $exts 0]; set x0(1) [lindex $exts 1]; set x0(2) [lindex $exts 2];
+    set x1(0) [lindex $exts 3]; set x1(1) [lindex $exts 4]; set x1(2) [lindex $exts 5];
+    
+    ## determine correct origin and spacing
+    for { set i 0 } { $i <= 2 } { incr i } {	
+ 	if { $x1($i) < $x0($i) } { set x1($i) [ expr $x0($i) +1 ] }
+ 	set dx [ lindex $ospac $i ]
+ 	if { $dx < 1 } { set dx 1 } elseif { $dx > 10 } { set dx 10 }	
+ 	set origin($i)  [ expr [lindex $orig $i ] + $x0($i) * [ lindex $spac $i ]]
+ 	set spacing($i) [ expr [lindex $spac $i ] * $dx ]
+ 	set ext($i)     [ expr ($x1($i)-$x0($i))/$dx ]
+    }
+
+    set identity [ vtkIdentityTransform [ pxvtable::vnewobj ] ]
+
+    ## extract roi
+    set roi [ vtkbisImageReslice [ pxvtable::vnewobj ] ]
+    $roi SetInput [ $image GetImage ]
+    $roi SetResliceTransform $identity
+    $roi SetOutputSpacing $spacing(0) $spacing(1) $spacing(2)
+    $roi SetOutputOrigin $origin(0)  $origin(1)  $origin(2)    
+    $roi SetOutputExtent 0 $ext(0) 0 $ext(1) 0 $ext(2)
+    $roi SetInterpolationMode 0 
+    $roi Update
+
+    $identity Delete
+
+    return $roi
+}
+
+#-------------------------------------------------------------------------------------------
+#  View contour
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_create_contour_glyph { scalars } {
+        
+    set range [ [ $widget_list(view_frontluk) GetLookupTable ] GetTableRange ]
+    set global_list(view_contour_from) [ lindex $range 0 ]
+    set global_list(view_contour_to) [ lindex $range 1 ]
+    
+    set contour [ vtkMarchingContourFilter [ pxvtable::vnewobj ] ]
+    $contour SetInput $scalars
+    $contour GenerateValues $global_list(view_contour_levels) $global_list(view_contour_from) $global_list(view_contour_to)
+    $contour Update
+    
+    set contourMapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    $contourMapper SetInput [ $contour GetOutput ]
+    $contourMapper SetLookupTable [ $widget_list(view_frontluk) GetLookupTable]
+    $contourMapper UseLookupTableScalarRangeOn
+    $contourMapper ScalarVisibilityOn
+    
+    ## create contour actor
+    set contourActor [ vtkActor [ pxvtable::vnewobj ] ]
+    $contourActor SetMapper $contourMapper
+    [ $contourActor GetProperty ] SetLineWidth $global_list(view_contour_width)
+    $contourMapper Delete
+
+    $contour Delete
+
+    return $contourActor
+}
+
+#-------------------------------------------------------------------------------------------
+#  View contour
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_create_contour { } {
+    
+    set SOLUTION 2
+    set solution [ lindex $global_list(result_list) $SOLUTION ]
+
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set dims [ [ $solution GetImage ] GetDimensions ]
+    
+    ## plot on slices
+    for { set i 0 } { $i < 3 } { incr i } {
+	
+	set ext [ view_compute_roi_extents $i $dims $levels ]
+	set scalars [ [ view_extract_roi $ext $solution ] GetOutput ]
+	
+	set actor [ view_create_contour_glyph $scalars ]
+	set global_list(actor_contour) [ lreplace $global_list(actor_contour) $i $i $actor ]
+	
+	$scalars Delete
+	
+	for { set j 0 } { $j < 4 } { incr j } {
+	    [ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] AddActor $actor	
+	}
+    }    
+}
+
+#-------------------------------------------------------------------------------------------
+#  View gradient
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_create_gradient_glyph { scalars glyph } {    
+    
+    ## compute gradient of propagation map
+#    set imgrad [ vtkImageGradient [ pxvtable::vnewobj ] ]
+#    $imgrad SetInput $scalars
+#    $imgrad SetDimensionality 3
+#    $imgrad Update
+    
+    ## convert into vector field
+    set imtovec [ vtkmpjImageToVectors [ pxvtable::vnewobj ] ]
+    $imtovec SetInput $scalars
+    $imtovec Update
+    
+    ## merge data
+    set merge [ vtkMergeFilter [ pxvtable::vnewobj ] ]
+    $merge SetGeometry $scalars
+    $merge SetVectors [ $imtovec GetOutput ]
+    $merge SetScalars $scalars
+    $merge Update
+    
+#    $imgrad Delete
+    $imtovec Delete
+    
+    ## create glypher field   
+    set glypher [ vtkGlyph3D [ pxvtable::vnewobj ] ] 
+    $glypher SetInput [ $merge GetOutput ]
+    $glypher SetSource [ $glyph GetOutput ]
+    $glypher ScalingOn
+    $glypher ClampingOn
+    #    $glypher SetScaleFactor $global_list(view_eigen_maxscale)
+    $glypher SetScaleModeToDataScalingOff
+    $glypher SetVectorModeToUseVector
+    $glypher Update
+    
+    ## set up glyph mapper
+    set glyphMapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    $glyphMapper SetInput [ $glypher GetOutput ]
+    #$glyphMapper SetLookupTable [ $widget_list(view_fiberluk) GetLookupTable ]
+    #$glyphMapper UseLookupTableScalarRangeOn
+    $glyphMapper ScalarVisibilityOff
+    
+    ## create glyph actor
+    set glyphActor [ vtkActor [ pxvtable::vnewobj ] ]
+    $glyphActor SetMapper $glyphMapper
+    [ $glyphActor GetProperty ] SetColor 0.0 1.0 1.0
+    
+    $glypher Delete
+    $glyphMapper Delete
+    
+    return $glyphActor
+}
+
+#-------------------------------------------------------------------------------------------
+#  View gradient
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_create_gradient { } {
+    
+    set GRADIENT 5
+    set gradient [ lindex $global_list(result_list) $GRADIENT ]
+
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set dims [ [ $gradient GetImage ] GetDimensions ]
+    
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_fiber_glyph) index [ $widget_list(view_fiber_glyph) get ] ]
+    set glyph_source [ lindex $global_list(glyph_list) 0 ]
+    
+    ## plot on slices
+    for { set i 0 } { $i < 3 } { incr i } {
+	
+	set ext [ view_compute_roi_extents $i $dims $levels ]
+	set scalars [ [ view_extract_roi $ext $gradient ] GetOutput ]
+	
+	set actor [ view_create_gradient_glyph $scalars $glyph_source ]
+	set global_list(actor_gradient) [ lreplace $global_list(actor_gradient) $i $i $actor ]
+	
+	$scalars Delete
+
+	for { set j 0 } { $j < 4 } { incr j } {
+	    [ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] AddActor $actor	
+	}
+    }    
+}
+
+#-------------------------------------------------------------------------------------------
+#  View characteristic
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_create_character_glyph { scalars vectors glyph } {    
+    
+    ## compute gradient of propagation map
+    #set imgrad [ vtkImageGradient [ pxvtable::vnewobj ] ]
+    #$imgrad SetInput $scalars
+    #$imgrad SetDimensionality 3
+    #$imgrad Update
+    
+    ## compute characteristics
+    #set imchar [ vtkmpjImageCharacteristics [ pxvtable::vnewobj ] ]
+    #$imchar SetInput $scalars
+    #$imchar SetGradient [ $imgrad GetOutput ]
+    #$imchar Update
+    
+    ## convert into vector field
+    set imtovec [ vtkmpjImageToVectors [ pxvtable::vnewobj ] ]
+    $imtovec SetInput $vectors
+    $imtovec Update
+    
+    ## merge data
+    set merge [ vtkMergeFilter [ pxvtable::vnewobj ] ]
+    $merge SetGeometry $scalars
+    $merge SetVectors [ $imtovec GetOutput ]
+    $merge SetScalars $scalars
+    $merge Update
+    
+    #$imchar Delete
+    $imtovec Delete
+    
+    ## create glypher field   
+    set glypher [ vtkGlyph3D [ pxvtable::vnewobj ] ] 
+    $glypher SetInput [ $merge GetOutput ]
+    $glypher SetSource [ $glyph GetOutput ]
+    $glypher ScalingOn
+    $glypher ClampingOn
+    #    $glypher SetScaleFactor $global_list(view_eigen_maxscale)
+    $glypher SetScaleModeToDataScalingOff
+    $glypher SetVectorModeToUseVector
+    $glypher Update
+    
+    ## set up glyph mapper
+    set glyphMapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    $glyphMapper SetInput [ $glypher GetOutput ]
+#    $glyphMapper SetLookupTable [ $widget_list(view_fiberluk) GetLookupTable ]
+#    $glyphMapper UseLookupTableScalarRangeOn
+    $glyphMapper ScalarVisibilityOff
+    
+    ## create glyph actor
+    set glyphActor [ vtkActor [ pxvtable::vnewobj ] ]
+    $glyphActor SetMapper $glyphMapper
+    [ $glyphActor GetProperty ] SetColor 0.0 1.0 0.0
+    
+    $glyphMapper Delete
+    
+    return $glyphActor
+}
+
+#-------------------------------------------------------------------------------------------
+#  View characteristics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_create_character { } {
+    
+    set SOLUTION 3
+    set CHARACTER 7
+    
+    set solution [ lindex $global_list(result_list) $SOLUTION ]
+    set character [ lindex $global_list(result_list) $CHARACTER ]
+    
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set dims [ [ $solution GetImage ] GetDimensions ]
+    
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_fiber_glyph) index [ $widget_list(view_fiber_glyph) get ] ]
+    set glyph_source [ lindex $global_list(glyph_list) 0 ]
+    
+    ## plot on slices
+    for { set i 0 } { $i < 3 } { incr i } {
+	
+	set ext [ view_compute_roi_extents $i $dims $levels ]
+	
+	set vectors [ [ view_extract_roi $ext $character ] GetOutput ]
+	set scalars [ [ view_extract_roi $ext $solution ] GetOutput ]
+	
+	set actor [ view_create_character_glyph $scalars $vectors $glyph_source ]
+	set global_list(actor_character) [ lreplace $global_list(actor_character) $i $i $actor ]
+	
+	$scalars Delete
+	
+	for { set j 0 } { $j < 4 } { incr j } {
+	    [ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] AddActor $actor	
+	}
+    }    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in map type
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::track_map_cb { } {    
+    set global_list(track_map) \
+	[ $widget_list(track_map) index [ $widget_list(track_map) get ] ]    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in solution methods
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::solution_method_cb { } {
+    set global_list(solution_method) \
+	[ $widget_list(solution_method) index [ $widget_list(solution_method) get ] ]    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in solution spacing
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::solution_autospacing_cb { } {
+    set state(0) disabled; set state(1) normal        
+    $widget_list(solution_spacingx) configure -state \
+	$state([expr 1 -$global_list(solution_autospacing)])     
+    $widget_list(solution_spacingy) configure -state \
+	$state([expr 1 -$global_list(solution_autospacing)]) 
+    $widget_list(solution_spacingz) configure -state \
+	$state([expr 1 -$global_list(solution_autospacing)])
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in solution spacing
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::solution_stopping_cb { } {
+    set state(0) disabled; set state(1) normal   
+    $widget_list(solution_stoptime) configure -state \
+	$state($global_list(solution_stopping)) 
+    $widget_list(solution_inf) configure -state \
+	$state($global_list(solution_stopping)) 
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in seed type
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::track_seedtype_cb { } {
+
+    set state(0) disabled; set state(1) normal    
+    set global_list(track_seedtype) \
+	[ $widget_list(track_seedtype) index [ $widget_list(track_seedtype) get ] ]
+
+    if { [expr $global_list(track_seedtype) < 2 || $global_list(track_seedtype) == 3 ]} {
+	$widget_list(track_seedwidth) configure -state disabled
+	$widget_list(track_seedheight) configure -state disabled
+	$widget_list(track_seeddepth) configure -state disabled
+	if { $global_list(track_seedtype) == 1 } {
+	    $widget_list(track_seeddens) configure -state normal
+	} else {
+	    $widget_list(track_seeddens) configure -state disabled
+	}
+    } else {
+	$widget_list(track_seedwidth) configure -state normal
+	$widget_list(track_seedheight) configure -state normal
+	$widget_list(track_seeddepth) configure -state normal
+	$widget_list(track_seeddens) configure -state normal
+    }
+    
+    if { $global_list(track_seedtype) == 1 } {
+	$widget_list(track_seedregion) configure -state normal
+    } else {
+	$widget_list(track_seedregion) configure -state disabled	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in region filtering option
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::track_regionfilter_cb { } {
+
+    set state(1) normal
+    set state(0) disabled
+
+    $widget_list(track_regionnumber) configure -state \
+	$state($global_list(track_regionfilter))
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in integration
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::track_integration_cb { } {
+    set global_list(track_integration) \
+	[ $widget_list(track_integration) index [ $widget_list(track_integration) get ] ]
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in spline types
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::track_splinetype_cb { } {
+    set global_list(track_splinetype) \
+	[ $widget_list(track_splinetype) index [ $widget_list(track_splinetype) get ] ]
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in spline subdivision
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::track_splinesubdivision_cb { } {
+    set global_list(track_splinesubdivision) \
+	[ $widget_list(track_splinesubdivision) index [ $widget_list(track_splinesubdivision) get ] ]
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon an update button press
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_update_display_cb { } { 
+    
+    view_clear_display
+    view_update_display
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in bundle radius
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_fiber_tuberadius_cb { } {
+    
+    foreach item $global_list(vtk_fiber_tube) {
+	$item SetRadius $global_list(view_fiber_tuberadius)
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in point size
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_fiber_pointsize_cb { } {
+    
+    foreach actor $global_list(actor_fiber) {
+	[ $actor GetProperty ] SetPointSize $global_list(view_fiber_pointsize)
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in colormap for paths
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_fiber_colormap_cb { } {
+    
+    foreach \
+	actor $global_list(actor_fiber) {
+	    
+	    ## create mapper
+	    set fiberMapper [ $actor GetMapper ]
+
+	    if { $global_list(view_fiber_luk) } {
+		$fiberMapper ScalarVisibilityOn
+	    } else {
+		$fiberMapper ScalarVisibilityOff
+	    }
+
+	    if { $global_list(view_fiber_luktype) == 0 } {
+		$fiberMapper SetScalarModeToUsePointData
+	    } else {
+		$fiberMapper SetScalarModeToUseCellData
+	    }
+	    
+
+	}
+    
+      [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in bundle glyph
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_fiber_glyph_cb { } {
+    
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_fiber_glyph) \
+			index [ $widget_list(view_fiber_glyph) get ] ]
+    
+    foreach \
+	actor $global_list(actor_fiber) \
+	tube $global_list(vtk_fiber_tube) \
+	polydata $global_list(vtk_fiber_polydata) {
+	    
+	    ## create mapper
+	    set fiberMapper [ $actor GetMapper ]
+	    
+	    if { $cur_glyph == 1 } {
+		
+		$tube SetInput $polydata
+		$tube SetRadius $global_list(view_fiber_tuberadius)
+		$tube SetNumberOfSides 6
+		$tube Update
+		
+		$fiberMapper SetInput [ $tube GetOutput ]
+
+		if { $global_list(view_fiber_luktype) == 0 } {
+		    $fiberMapper SetScalarModeToUsePointData
+		} else {
+		    $fiberMapper SetScalarModeToUseCellData
+		}
+	    		
+		if { $global_list(view_fiber_luk) } {
+		    $fiberMapper ScalarVisibilityOn
+		} else {
+		    $fiberMapper ScalarVisibilityOff
+		}
+
+		
+		
+	    } else {
+		
+		$fiberMapper SetInput $polydata
+
+		if { $global_list(view_fiber_luktype) == 0 } {
+		    $fiberMapper SetScalarModeToUsePointData
+		} else {
+		    $fiberMapper SetScalarModeToUseCellData
+		}
+		
+		if { $global_list(view_fiber_luk) } {
+		    $fiberMapper ScalarVisibilityOn
+		} else {
+		    $fiberMapper ScalarVisibilityOff
+		}
+				
+	    }
+	    
+	    if { $cur_glyph == 2 } {
+		[ $actor GetProperty ] SetRepresentationToPoints
+		[ $actor GetProperty ] SetPointSize $global_list(view_fiber_pointsize)
+	    } else {
+		[ $actor GetProperty ] SetRepresentationToSurface 
+	    }
+
+	}
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in fiber filter selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_fiber_filter_cb { } {
+    
+    set field(0) validity
+
+    ## current fiber colormap filter    
+    set filter [ $widget_list(view_fiber_filter) index [ $widget_list(view_fiber_filter) get ]]    
+    
+    foreach \
+	actor $global_list(actor_fiber) {	    
+	    
+	    ## create mapper
+	    #set fiberMapper [ $actor GetMapper ]	   	    
+	    #$fiberMapper SetScalarModeToUsePointFieldData
+	    #$fiberMapper ColorByArrayComponent $field($filter) 0
+	}
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in fiber filter selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_fiber_luktype_cb { } {
+    
+    ## current fiber colormap filter    
+    set filter [ $widget_list(view_fiber_luktype) index [ $widget_list(view_fiber_luktype) get ]]    
+    set global_list(view_fiber_luktype) $filter
+
+    puts "filter: $filter"
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off fiber visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::view_toggle_fiber { } {
+    
+    if { $global_list(view_fiber) } {	
+	view_create_paths	
+    } else { 
+	foreach \
+	    actor $global_list(actor_fiber) \
+	    disp $global_list(fiber_disp_list) {
+		if { $disp == 1 } {
+		    for { set j 0 } { $j < 4 } { incr j } {
+			[ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] RemoveActor $actor	
+		    }
+		}
+		$actor Delete	    
+	    }
+	set global_list(actor_fiber) {}
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in bundle color
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_color_cb { } {
+
+    set new_color [ tk_chooseColor -initialcolor $global_list(fiber_color) ]
+    
+    if { [ llength $new_color ] > 0 } {
+	
+	set global_list(fiber_color) $new_color
+	set fiber_color [ image create photo -width 15 -height 15 ]
+	$fiber_color put $global_list(fiber_color) -to 0 0 15 15	
+	$widget_list(fiber_color) configure -image $fiber_color
+	
+	## get current selection 
+	set sel_item [ $widget_list(fiber_list) getcurselection ]
+	
+	if { $sel_item != "" } {
+	    
+	    set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	    set global_list(fiber_color_list) \
+		[ lreplace $global_list(fiber_color_list) $sel_index $sel_index $new_color ]
+	    
+	    ## convert tk color spec to vtk
+	    set color $new_color
+	    set red "0x[string range $color 1 2]"
+	    set green "0x[string range $color 3 4]"
+	    set blue "0x[string range $color 5 6]"
+	    set red [ expr [ format "%d" $red ] / 255.0 ]
+	    set green [ expr [ format "%d" $green ] / 255.0 ]
+	    set blue [ expr [ format "%d" $blue ] / 255.0 ]
+	    
+	    set fiberActor [ lindex $global_list(actor_fiber) $sel_index ]
+	    [$fiberActor GetProperty] SetColor $red $green $blue
+
+	    [ $parent GetViewer ] UpdateDisplay	    
+	    
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon selection of bundles
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_selection_cb { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	set sel_input [ lindex $global_list(fiber_list) $sel_index ]
+	
+	## get number of components
+	set global_list(fiber_name) $sel_input
+	set global_list(fiber_color) [ lindex $global_list(fiber_color_list) $sel_index ]
+	set global_list(fiber_display) [ lindex $global_list(fiber_disp_list) $sel_index ]
+
+	set fiber_color [ image create photo -width 15 -height 15 ]
+	$fiber_color put $global_list(fiber_color) -to 0 0 15 15	
+	$widget_list(fiber_color) configure -image $fiber_color
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in bundle name
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_name_cb { } {
+
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	set new_name [ $widget_list(fiber_name) get ]
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	set global_list(fiber_list) \
+	    [ lreplace $global_list(fiber_list) $sel_index $sel_index $new_name ]
+	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in bundle display option
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_display_cb { } {
+
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	puts "$sel_index"
+
+	set global_list(fiber_disp_list) \
+	    [ lreplace $global_list(fiber_disp_list) $sel_index $sel_index \
+		  $global_list(fiber_display) ]
+	
+	set actor [ lindex $global_list(actor_fiber) $sel_index ]
+	
+	if { $global_list(fiber_display) } {
+	    for { set j 0 } { $j < 4 } { incr j } {
+		[ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] AddActor $actor	
+	    }
+	} else {
+	    for { set j 0 } { $j < 4 } { incr j } {
+		[ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] RemoveActor $actor	
+	    }
+	}
+	
+	[ $parent GetViewer ] UpdateDisplay	    
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Add bundle with a given name
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_addwithname { name polydata } {
+
+    ## insert new fiber set
+    set num_paths [ llength $global_list(fiber_list) ]
+    set next_color [lindex $global_list(tkcolor_list) [expr int(fmod($num_paths,6))]]
+    
+    set global_list(fiber_color) $next_color
+    set global_list(fiber_display) 1
+
+    set fiber_color [ image create photo -width 15 -height 15 ]
+    $fiber_color put $global_list(fiber_color) -to 0 0 15 15	
+    $widget_list(fiber_color) configure -image $fiber_color
+    
+    set global_list(fiber_name) $name
+    lappend global_list(fiber_list) $global_list(fiber_name)
+    lappend global_list(fiber_disp_list) $global_list(fiber_display)    
+    lappend global_list(fiber_color_list) $global_list(fiber_color)
+    lappend global_list(vtk_fiber_polydata) $polydata	    
+    lappend global_list(vtk_fiber_tube) [ vtkTubeFilter [ pxvtable::vnewobj ] ]
+ 
+    $widget_list(fiber_list) selection clear 0 end
+    $widget_list(fiber_list) selection set $num_paths $num_paths
+
+    return $num_paths
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Add fiber
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_add { polydata } {
+
+    ## insert new fiber
+    set num_paths [ llength $global_list(fiber_list) ]
+    set name "Bundle_[expr $num_paths + 1]"
+    
+    set index [ fiber_addwithname $name $polydata ]
+    
+    return $index
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear all paths
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_clear { } {
+    
+    set num_paths [ llength $global_list(fiber_list) ]
+    for { set i 0 } { $i < $num_paths } { incr i } { 
+	fiber_remove 0
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Remove fiber
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_remove { index } {
+
+    if { $global_list(view_fiber) } {
+	set display [ lindex $global_list(fiber_disp_list) $index ]
+	if { $display } {
+	    set actor [ lindex $global_list(actor_fiber) $index ]
+	    for { set j 0 } { $j < 4 } { incr j } {
+		[ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] RemoveActor $actor	
+	    }
+	    $actor Delete
+	}
+    }
+    
+    set global_list(fiber_list) \
+	[ lreplace $global_list(fiber_list) $index $index ]
+    set global_list(fiber_color_list) \
+	[ lreplace $global_list(fiber_color_list) $index $index ]
+    set global_list(fiber_disp_list) \
+	[ lreplace $global_list(fiber_disp_list) $index $index ]
+    
+    set polydata [ lindex $global_list(vtk_fiber_polydata) $index ]
+    $polydata Delete
+    
+    set tube [ lindex $global_list(vtk_fiber_tube) $index ]
+    $tube Delete
+
+    set global_list(actor_fiber) \
+	[ lreplace $global_list(actor_fiber) $index $index ]
+    set global_list(vtk_fiber_tube) \
+	[ lreplace $global_list(vtk_fiber_tube) $index $index ]
+    set global_list(vtk_fiber_polydata) \
+	[ lreplace $global_list(vtk_fiber_polydata) $index $index ]
+    
+    set num_paths [ llength $global_list(fiber_list) ]
+    
+    if { $num_paths > 0 } {
+	
+	$widget_list(fiber_list) selection clear 0 end
+	
+	if { $index < $num_paths } {
+	    $widget_list(fiber_list) selection set $index $index
+	} else {
+	    $widget_list(fiber_list) selection set \
+		[expr $num_paths -1] [expr $num_paths -1]
+	}
+	
+	fiber_selection_cb
+	
+    } else {
+	
+	set global_list(fiber_fname) ""
+	set global_list(fiber_display) 1
+	set global_list(fiber_name) ""
+	set global_list(fiber_color) [ lindex $global_list(tkcolor_list) 0 ]
+	set fiber_color [ image create photo -width 15 -height 15 ]
+	$fiber_color put $global_list(fiber_color) -to 0 0 15 15	
+	$widget_list(fiber_color) configure -image $fiber_color
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Remove selected bundle
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_removeselected { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	fiber_remove $sel_index
+	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: load fiber
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_load { } {
+    
+    set fname [ openfile_dialog $basewidget $global_list(result_fdir) "Select file" "*.fib" ]
+
+    ## browse for filename
+    if { $fname != "" } { 
+	
+	## open fiber file
+	set fibr [ vtkXMLPolyDataReader [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $fibr "Reading fiber..."
+	$fibr SetFileName $fname
+	$fibr Update
+	
+	set polydata [ vtkPolyData [ pxvtable::vnewobj ] ]
+	$polydata ShallowCopy [ $fibr GetOutput ]
+	
+	$fibr Delete
+	
+	set index [ fiber_addwithname [ file root [ file tail $fname ] ] $polydata ]
+	
+	## keep fname
+	set global_list(fiber_fname) $fname
+	
+	if { $global_list(view_fiber) } {	
+	    
+	    set actor [ view_create_fiber_glyph $index ]
+	    lappend global_list(actor_fiber) $actor
+	    
+	    ## add actor if to be displayed
+	    if { [ lindex $global_list(fiber_disp_list) $index ] == 1 } { 
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+	    }
+	}
+	
+	#if { $global_list(view_fiber) } {	
+	#    view_create_paths	
+	#} 
+    }	
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: save individual fiber 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_save { index name } {
+    
+    set polydata [ lindex $global_list(vtk_fiber_polydata) $index ]
+    
+    set fibw [ vtkXMLPolyDataWriter [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $fibw "Saving fiber..."
+
+    $fibw SetFileName $name
+    $fibw SetInput $polydata
+    $fibw Write	
+    
+    $fibw Delete    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: save selected fiber
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_saveselected { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## browse for directory
+	set fdir [ savedir_dialog $basewidget $global_list(result_fdir) "Select directory" ]
+	
+	## browse for directory
+	if { $fdir != "" } {
+	    	    
+	    ## get current index
+	    set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	    
+	    set item [ lindex $global_list(fiber_list) $sel_index ]	
+	    
+	    fiber_save $sel_index [ file join $fdir "$item.fib" ]	
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: save all paths
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_saveall { } {
+    
+    ## browse for directory
+    set fdir [ savedir_dialog $basewidget $global_list(result_fdir) "Select directory" ]
+
+    ## browse for directory
+    if { $fdir != "" } { 
+	
+	## get number of fiber bundles
+	set num [ llength $global_list(fiber_list) ]
+	
+	## save all paths
+	for { set i 0 } { $i < $num } { incr i } {	
+	    set item [ lindex $global_list(fiber_list) $i ]	
+	    fiber_save $i [ file join $fdir "$item.fib" ]	
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_savestatistics { } {
+
+    set statfname $global_list(result_fpreffix)
+    set initfname "${statfname}stat"
+    set initfname [ file join $global_list(result_fdir) $initfname ]
+
+    ## browse for filename
+    set fname  [tk_getSaveFile -title "Save statistics"\
+		    -filetypes {{"Text" {.txt*}}} \
+		    -parent $basewidget \
+		    -defaultextension ".txt" \
+		    -initialfile $initfname ]  
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+    
+    $widget_list(stat_text) export $fname
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: compute fiber statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_beginstatistics { title overwrite } {   
+    
+    if { $overwrite } {
+	$widget_list(stat_text) delete 1.0 end
+    }    
+
+    $widget_list(stat_text) insert \
+	end "-----------------------+------------+------------+------------+------------+------------\n" even
+    $widget_list(stat_text) insert \
+	end "$title      MIN          MAX         MEAN        VARIANCE      STD DEV\n" odd
+    $widget_list(stat_text) insert \
+	end "-----------------------+------------+------------+------------+------------+------------\n" even
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: compute fiber statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_addstatistics { title results tag } {   
+    
+    set min  [ format %8.4f [ lindex $results 0 ] ]
+    set max  [ format %8.4f [ lindex $results 1 ] ]
+    set mean [ format %8.4f [ lindex $results 2 ] ]
+    set var  [ format %8.4f [ lindex $results 3 ] ]
+    set dev  [ format %8.4f [ lindex $results 4 ] ]
+    
+    $widget_list(stat_text) insert end " $title |  $min  |  $max  |  $mean  |  $var  |  $dev  \n" $tag
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: compute fiber statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_error { } {
+
+    ## get current selection     
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+
+    if { $sel_item != "" } {
+	
+	## get current index
+	set target_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ]
+
+	set dist [ vtkmpjStreamlineDistance [ pxvtable::vnewobj ] ]
+	$dist SetReference [ lindex $global_list(vtk_fiber_polydata) 0 ]
+	$dist SetTarget [ lindex $global_list(vtk_fiber_polydata) $target_index ]
+	$dist SetReferenceIndex 0
+	$dist SetTargetIndex 0
+	$dist Update
+	
+	puts "Min dist: [ $dist GetMinimum ]"
+	puts "Max dist: [ $dist GetMaximum ]"
+	puts "Mean dist: [ $dist GetMean ]"
+	
+	set polydata [ vtkPolyData [ pxvtable::vnewobj ] ]
+	$polydata ShallowCopy [ $dist GetOutput ]
+	
+	$dist Delete
+	
+	set index [ fiber_addwithname "Error" $polydata ]
+
+	if { $global_list(view_fiber) } {	
+	    
+	    set actor [ view_create_fiber_glyph $index ]
+	    lappend global_list(actor_fiber) $actor
+	    
+	    ## add actor if to be displayed
+	    if { [ lindex $global_list(fiber_disp_list) $index ] == 1 } { 
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+	    }
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: threshold validity
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_threshold { } {
+
+    set SPEED 0
+    set speed [ lindex $global_list(result_list) $SPEED ]
+
+    set viewer [ $parent GetViewer ]      
+
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	## name
+	set item [ lindex $global_list(fiber_list) $sel_index ]	
+
+	puts "number of paths before=[ [ lindex $global_list(vtk_fiber_polydata) $sel_index ] GetNumberOfCells ]"
+
+	set thresh 0
+
+	set levels [ [ $viewer GetOrthoImageSlice ] GetLevels ]
+	set x [ lindex $levels 0 ]
+	set y [ lindex $levels 1 ]
+	set z [ lindex $levels 2 ]    
+
+	scan [ [ $speed GetImage ] GetSpacing ] "%f %f %f" spc0 spc1 spc2
+	scan [ [ $speed GetImage ] GetOrigin ] "%f %f %f" org0 org1 org2
+
+	set ox [expr $x * $spc0 + $org0 ]
+	set oy [expr $y * $spc1 + $org1 ]
+	set oz [expr $z * $spc2 + $org2 ]
+
+	#puts "$ox $oy $oz"
+    
+	if { $global_list(fiber_thresh_type) == 1 } {
+	    set thresh [ vtkmpjThresholdPolyData [ pxvtable::vnewobj ] ]
+	    $this SetFilterCallbacks $thresh "Filtering..."
+	    $thresh SetInput [ lindex $global_list(vtk_fiber_polydata) $sel_index ]
+	    $thresh ThresholdByUpper $global_list(fiber_thresh_val)
+	    $thresh SetAttributeModeToUseCellData
+	    $thresh Update
+	} else {
+	    set thresh [ vtkmpjThresholdPolyDataByDistance [ pxvtable::vnewobj ] ]
+	    $this SetFilterCallbacks $thresh "Filtering..."
+	    $thresh SetInput [ lindex $global_list(vtk_fiber_polydata) $sel_index ]
+	    $thresh SetMinimumDistance [expr $global_list(fiber_thresh_dist) * $global_list(fiber_thresh_dist)]
+	    $thresh SetOrigin $ox $oy $oz
+	    $thresh Update
+	}
+
+	## replace fiber
+	fiber_removeselected
+	
+	set new_fiber [ vtkPolyData [ pxvtable::vnewobj ] ]
+	$new_fiber ShallowCopy [ $thresh GetOutput ]
+	
+	puts "number of paths after threshold=[ $new_fiber GetNumberOfCells ]"
+
+	$thresh Delete
+	
+	set index [ fiber_add $new_fiber ]
+	
+	## display new bundle
+	if { $global_list(view_fiber) } {	
+	    
+	    set actor [ view_create_fiber_glyph $index ]
+	    lappend global_list(actor_fiber) $actor
+	    
+	    ## add actor if to be displayed
+	    if { [ lindex $global_list(fiber_disp_list) $index ] == 1 } { 
+		for { set j 0 } { $j < 4 } { incr j } {
+		    [ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] AddActor $actor
+		}
+	    }
+
+	    [ $parent GetViewer ] UpdateDisplay	    
+	}		
+    }
+    
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: compute fiber statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_statistics { } {
+
+    set PATHS 3
+
+    set fiber_image [ lindex $global_list(result_list) $PATHS ] 
+
+    $widget_list(notebook) view "Statistics"
+    
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	## name
+	set item [ lindex $global_list(fiber_list) $sel_index ]	
+	
+	# compute fiber statistics
+	set fstat [ vtkmpjVectorStreamlineStatistics [ pxvtable::vnewobj ] ]
+	$fstat SetInput [ lindex $global_list(vtk_fiber_polydata) $sel_index ]
+	$fstat Update
+	
+	set vol "n/a"
+	set volmm "n/a"
+
+	#if { [ $fiber_image GetImageSize ] > 1 } {
+	    
+	    ## quantize paths
+	    #set quant [ vtkmpjStreamlineQuantization [ pxvtable::vnewobj ] ]
+	    #$quant SetInput [ lindex $global_list(vtk_fiber_polydata) $sel_index ]
+	    #$quant SetImage [ $fiber_image GetImage ]
+	    #$quant SetMaskValue 1.0
+	    #$quant Update
+	    
+	    #$fiber_image ShallowCopyImage [ $quant GetOutput ]
+
+	    ## get volume 
+	    #set vol [ $quant GetNumberOfVoxels ]
+
+	    ## get spacing information
+	    #scan [ [ $fiber_image GetImage ] GetSpacing ] "%f %f %f" spc0 spc1 spc2
+
+	    ## calculate volume in mm
+	    #set volmm [ expr $vol * $spc0 * $spc1 * $spc2 ]
+	    #set volmm [ format %6.2f $volmm ]
+
+	    #$quant Delete
+	#}
+	
+	## Write out stats
+	set textlist [  $widget_list(stat_text) component text ]
+	$textlist tag configure even -background "\#e0e0ff"
+	
+	set strlen [ string length $item ]
+	if { $strlen > 23 } {
+	    set item [ string range $item 0 22 ]
+	} else {
+	    set spc [ string repeat " " [ expr (23 - $strlen) / 2 ] ] 
+	    set item [ string range "$spc$item$spc" 0 22 ]
+	}
+
+	fiber_beginstatistics $item $global_list(stat_overwrite)
+
+	set min [ $fstat GetMinimum ]
+	set max [ $fstat GetMaximum ]
+	set mean [ $fstat GetMean ]
+	set var [ $fstat GetVariance ]
+	set dev [ expr sqrt($var) ]
+
+	set result [ list $min $max $mean $var $dev ]
+	fiber_addstatistics "Validity index" $result odd
+
+	$widget_list(stat_text) insert \
+	    end "-----------------------+------------+------------+------------+------------+------------\n" even
+
+	set num [ $fstat GetNumberOfPaths ]
+
+	$widget_list(stat_text) insert end " Path Count = $num, Volume = $vol ($volmm mm^3)\n" odd
+
+	$fstat Delete
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: quantize paths
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_quantize { } {
+
+    set PATHS 3
+
+    set fiber_image [ lindex $global_list(result_list) $PATHS ] 
+
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	## name
+	set item [ lindex $global_list(fiber_list) $sel_index ]	
+
+	## quantize paths
+	set quant [ vtkmpjStreamlineQuantization [ pxvtable::vnewobj ] ]
+	$quant SetInput [ lindex $global_list(vtk_fiber_polydata) $sel_index ]
+	$quant SetImage [ $fiber_image GetImage ]
+	$quant SetMaskValue 1.0
+	$quant Update
+
+	$fiber_image ShallowCopyImage [ $quant GetOutput ]
+
+	$quant Delete
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Front propagation callback function
+# -----------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::PropagationCallback { filter comment } {
+    
+    set iter [ $filter GetIterationNumber ]
+    
+    ShowProgress $filter "$comment (Iteration $iter)"
+    
+    update idletasks
+
+    if { $comment != "Done" } {
+	set label [ format "%8.4f" [ $filter GetErrorValue ] ]
+	set global_list(solution_errorlabel) "Error: $label"
+    }
+
+    update idletasks
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Front propagation
+# -----------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::result_initneighbors { dim source new_source } {
+    
+    set total [ $source GetNumberOfTuples ]
+
+    for { set i 0 } { $i < $total } { incr i } {
+
+	set point [ $source GetTuple4 $i ]
+	scan $point "%f %f %f %f" x y z val
+
+	$new_source InsertNextTuple4 [expr $x-1] $y $z 1.0
+	$new_source InsertNextTuple4 [expr $x+1] $y $z 1.0
+	$new_source InsertNextTuple4 $x [expr $y-1] $z 1.0
+	$new_source InsertNextTuple4 $x [expr $y+1] $z 1.0
+	
+	$new_source InsertNextTuple4 [expr $x-1] [expr $y-1] $z [expr sqrt(2.0)]
+	$new_source InsertNextTuple4 [expr $x+1] [expr $y+1] $z [expr sqrt(2.0)]
+	$new_source InsertNextTuple4 [expr $x-1] [expr $y+1] $z [expr sqrt(2.0)]
+	$new_source InsertNextTuple4 [expr $x+1] [expr $y-1] $z [expr sqrt(2.0)]
+	
+	$new_source InsertNextTuple4 $x $y [expr $z-1] 1.0
+	
+	$new_source InsertNextTuple4 [expr $x-1] [expr $y-1] [expr $z-1] [expr sqrt(3.0)]
+	$new_source InsertNextTuple4 [expr $x+1] [expr $y+1] [expr $z-1] [expr sqrt(3.0)]
+	$new_source InsertNextTuple4 [expr $x-1] [expr $y+1] [expr $z-1] [expr sqrt(3.0)]
+	$new_source InsertNextTuple4 [expr $x+1] [expr $y-1] [expr $z-1] [expr sqrt(3.0)]
+	
+	$new_source InsertNextTuple4 $x [expr $y-1] [expr $z-1] [expr sqrt(2.0)]
+	$new_source InsertNextTuple4 $x [expr $y+1] [expr $z-1] [expr sqrt(2.0)]
+	$new_source InsertNextTuple4 [expr $x-1] $y [expr $z-1] [expr sqrt(2.0)]
+	$new_source InsertNextTuple4 [expr $x+1] $y [expr $z-1] [expr sqrt(2.0)]
+	
+	$new_source InsertNextTuple4 $x $y [expr $z+1] 1.0
+	
+	$new_source InsertNextTuple4 [expr $x-1] [expr $y-1] $z [expr sqrt(2.0)]
+	$new_source InsertNextTuple4 [expr $x+1] [expr $y+1] $z [expr sqrt(2.0)]
+	$new_source InsertNextTuple4 [expr $x-1] [expr $y+1] $z [expr sqrt(2.0)]
+	$new_source InsertNextTuple4 [expr $x+1] [expr $y-1] $z [expr sqrt(2.0)]
+	
+	$new_source InsertNextTuple4 [expr $x-1] [expr $y-1] [expr $z+1] [expr sqrt(3.0)]
+	$new_source InsertNextTuple4 [expr $x+1] [expr $y+1] [expr $z+1] [expr sqrt(3.0)]
+	$new_source InsertNextTuple4 [expr $x-1] [expr $y+1] [expr $z+1] [expr sqrt(3.0)]
+	$new_source InsertNextTuple4 [expr $x+1] [expr $y-1] [expr $z+1] [expr sqrt(3.0)]
+    }
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Front propagation
+# -----------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::result_propagate { }  {
+    
+    set VTK_MPJ_LARGE_FLOAT 32767
+    set VTK_MPJ_UNKNOWN     0 
+
+    set SPEED 0
+    set MASK 1
+    set SOLUTION 2
+    set MAP  3
+    set PATHS 4
+    set GRADIENT 5
+        
+    WatchOn
+
+    update idletasks
+
+    set viewer [ $parent GetViewer ]      
+    
+    set speed [ lindex $global_list(result_list) $SPEED ]
+    set solution [ lindex $global_list(result_list) $SOLUTION ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set map [ lindex $global_list(result_list) $MAP ]
+    set gradient [ lindex $global_list(result_list) $GRADIENT ]
+
+    set spc [ [ $speed GetImage ] GetSpacing ]
+    set dim [ [ $speed GetImage ] GetDimensions ]
+
+    set levels [ [ $viewer GetOrthoImageSlice ] GetLevels ]
+    set x [ lindex $levels 0 ]
+    set y [ lindex $levels 1 ]
+    set z [ lindex $levels 2 ]    
+    
+    ## set seed point
+    set seeds [ vtkFloatArray [ pxvtable::vnewobj ] ]
+    $seeds SetNumberOfComponents 4
+    $seeds InsertNextTuple4 $x $y $z 0
+    
+    ## FMM
+    set sol_method [ vtkmpjFastMarchingMethod [ pxvtable::vnewobj ] ]
+
+    ## if mask is defined, make region outside mask unreachable
+    if { [ $mask GetImageSize ] > 1 } {
+	if { $global_list(solution_usemask) } {
+	    $sol_method SetMask [ $mask GetImage ]	
+	}
+    } 
+
+    ## accuracy
+    $sol_method SetSecondOrder $global_list(solution_method)
+
+    ## set seeds
+    set source 0
+    
+    if { $global_list(solution_useboundary) } {
+	set source $global_list(solution_seeds)
+    } else {
+	set source $seeds
+    }
+    
+    set new_source 0 
+
+    ## augment seed information
+    if { $global_list(solution_initneighbors) } {
+	
+	set new_source [ vtkFloatArray [ pxvtable::vnewobj ] ]
+	
+	$new_source DeepCopy $source
+
+	result_initneighbors $dim $source $new_source
+
+	## set seeds
+	$sol_method SetKnownPoints $new_source
+
+	$new_source Delete
+
+    } else {
+
+	## set seeds
+	$sol_method SetKnownPoints $source
+    }
+
+    $sol_method SetInput [ $speed GetImage ]    
+
+    ## set spacing
+    if { $global_list(solution_autospacing) } {
+	$sol_method SetSpacing \
+	    [lindex $spc 0 ] \
+	    [lindex $spc 1 ] \
+	    [lindex $spc 2 ]
+    } else {
+	$sol_method SetSpacing \
+	    $global_list(solution_spacingx) \
+	    $global_list(solution_spacingy) \
+	    $global_list(solution_spacingz)
+    }
+    ## set propagation time
+    if { $global_list(solution_stopping) } {
+	$sol_method SetPropagationTime $global_list(solution_stoptime)
+	$sol_method SetInfinity $global_list(solution_inf)
+    }
+
+    $sol_method SetInfinity $global_list(solution_inf)
+
+    ## FMM
+    $this SetFilterCallbacks $sol_method "Propagating..."
+    
+    ## execute
+    $sol_method Update
+
+    set time [ $sol_method GetElapsedTime ]
+    
+    puts "After propagation"
+
+    ## calculate gradient
+    #set imgrad [ vtkImageGradient [ pxvtable::vnewobj ] ]
+    set imgrad [ vtkmpjLevelSetNormal [ pxvtable::vnewobj ] ]
+    $imgrad SetInput [ $sol_method GetOutput ]
+    #$imgrad SetDimensionality 3
+    $this SetFilterCallbacks $imgrad "Calculating gradient..."
+    $imgrad Update
+    
+    $gradient ShallowCopyImage [ $imgrad GetOutput ]  
+    $gradient CopyImageHeader [ $solution GetImageHeader ]
+    
+    $imgrad Delete
+    
+    ## threshold result for display purposes
+    set imthr [ vtkImageThreshold [ pxvtable::vnewobj ] ]
+    $imthr SetInput [ $sol_method GetOutput ]
+    $imthr ThresholdBetween 0 $global_list(solution_inf)
+    $imthr ReplaceOutOn  
+    $imthr SetOutValue $global_list(solution_inf)
+    $imthr SetOutputScalarTypeToFloat
+    $this SetFilterCallbacks $imthr "Thresholding solution..."
+    $imthr Update
+
+    $solution ShallowCopyImage [ $imthr GetOutput ]  
+    $solution CopyImageHeader [ $solution GetImageHeader ]
+    
+    $sol_method Delete
+    
+    $seeds Delete    
+    
+    $imthr Delete
+
+    # send currently selected result to parent
+    $widget_list(result_list) selection set $SOLUTION $SOLUTION
+    
+    puts "after gradient computation"
+
+    set sol_map [ lindex $global_list(result_list) $SOLUTION ]
+#    $parent SetImageFromObject [ $sol_map  GetThisPointer ] $this
+
+    WatchOff
+
+    $this ShowProgressVal "Done ($time secs)." 0
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: fiber track
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::fiber_track { } {
+
+    set SPEED 0
+    set MASK 1
+    set SOLUTION 2
+    set MAP 3
+    set PATHS 4
+    set GRADIENT 5
+    
+    set tensor [ lindex $global_list(result_list) $SPEED ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set map [ lindex $global_list(result_list) $MAP ]
+    set solution [ lindex $global_list(result_list) $SOLUTION ]
+    set paths [ lindex $global_list(result_list) $PATHS ] 
+    set gradient [ lindex $global_list(result_list) $GRADIENT ] 
+
+    if { [ $solution GetImageSize ] == 1 } {
+	
+	tk_messageBox -type ok \
+	    -parent $basewidget -title "Solution" \
+	    -message "You need a propagation solution to start tracking!" -icon info
+	
+	return
+    }
+     
+    if { [ $map GetImageSize ] == 1 } {
+	
+	## create dummy map
+	$map CopyImageHeader [ $paths GetImageHeader ]
+	$map ShallowCopyImage [ $paths GetImage ]
+    }
+
+    WatchOn
+
+    ## get slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set cx [ lindex $levels 0 ]
+    set cy [ lindex $levels 1 ]
+    set cz [ lindex $levels 2 ]
+
+    ## get origin and spacing information
+    scan [ [ $solution GetImage ] GetSpacing ] "%f %f %f" spc0 spc1 spc2
+    scan [ [ $solution GetImage ] GetOrigin ] "%f %f %f" org0 org1 org2
+
+    set imtovec [ vtkmpjImageToVectors [ pxvtable::vnewobj ] ]
+
+    if { $global_list(track_map) == 0 } {
+	## convert into vector field
+	$imtovec SetInput [ $gradient GetImage ]
+	$imtovec Update
+    } else {
+	$imtovec SetInput [ $character GetImage ]
+	$imtovec Update
+    }
+    
+    set merge [ vtkMergeFilter [ pxvtable::vnewobj ] ]
+    $merge SetGeometry [ $solution GetImage ]
+    $merge SetVectors [ $imtovec GetOutput ]
+    if { $global_list(track_map) == 0 } {
+	$merge SetScalars [ $solution GetImage ]
+    } else {
+	$merge SetScalars [ $map GetImage ]
+    }
+    $merge Update
+    
+#    $imgrad Delete
+    $imtovec Delete
+
+    ## initialize streamer ##
+    set streamer [ vtkmpjVectorStreamline [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $streamer "Pathway tracking..."
+    $streamer SetInput [ $merge GetOutput ]
+    
+    if { $global_list(track_seedtype) == 0 } {
+
+	## single input point
+	set ox [expr $cx * $spc0 + $org0 ]
+	set oy [expr $cy * $spc1 + $org1 ]
+	set oz [expr $cz * $spc2 + $org2 ]
+	
+	set source [ vtkPolyData [ pxvtable::vnewobj ] ] 
+	set points [ vtkPoints [ pxvtable::vnewobj ] ]
+	
+	$points InsertNextPoint $ox $oy $oz 
+	$source SetPoints $points
+	
+	$points Delete
+	
+	## assign source point
+	$streamer SetSource $source
+
+	$source Delete
+
+    } elseif { $global_list(track_seedtype) == 1 } {
+	
+	## region 
+	set region $global_list(track_seedregion)
+	
+	set imthr [ vtkImageThreshold [ pxvtable::vnewobj ] ]
+	$imthr SetInput [ $mask GetImage ]
+	$imthr ThresholdBetween $region $region
+	$imthr SetInValue 1.0
+	$imthr SetOutValue 0.0
+	$imthr SetOutputScalarTypeToUnsignedChar
+	$imthr Update
+	
+ 	set dens $global_list(track_seeddens)
+
+	set source [ vtkmpjImagePointSource [ pxvtable::vnewobj ] ]
+	$source SetMask [ $imthr GetOutput ]
+	$source SetOrigin $org0 $org1 $org2
+	$source SetSpacing $spc0 $spc1 $spc2
+	$source SetDensity $dens
+	$source Update
+	
+ 	## assign source points
+	$streamer SetSource [ $source GetOutput ]
+	$source Delete
+	
+	#	set impts [ vtkThresholdPoints [ pxvtable::vnewobj ] ]
+	#	$impts SetInput [ $imthr GetOutput ]
+	#	$impts ThresholdByUpper 1.0
+	#	$impts Update    
+	
+	$imthr Delete
+	
+	## assign region source points
+#	$streamer SetSource [ $impts GetOutput ]
+#	$impts Delete
+	
+    } elseif { $global_list(track_seedtype) == 2 } {
+	
+	## volume	
+	set ox [expr $cx * $spc0 + $org0 ]
+	set oy [expr $cy * $spc1 + $org1 ]
+	set oz [expr $cz * $spc2 + $org2 ]
+	
+	set width $global_list(track_seedwidth)
+	set height $global_list(track_seedheight)
+	set depth $global_list(track_seeddepth)
+	set dens $global_list(track_seeddens)
+	
+	#	set numx [ expr int(1.0 / $res) * $width ]
+	#	set numy [ expr int(1.0 / $res) * $height ]
+	#	set numz [ expr int(1.0 / $res) * $depth ]
+	
+	set source [ vtkmpjImagePointSource [ pxvtable::vnewobj ] ]
+	$source SetCenter $ox $oy $oz
+	$source SetSize $width $height $depth
+	$source SetOrigin $org0 $org1 $org2
+	$source SetSpacing $spc0 $spc1 $spc2
+	$source SetDensity $dens
+	$source Update
+
+	## assign source points
+	$streamer SetSource [ $source GetOutput ]
+
+	$source Delete
+    
+    } elseif { $global_list(track_seedtype) == 3 } {
+	
+	## landmark control
+	set landmarkcontrol [ [ $parent GetLandmarkControl ] GetLandmarkControl ]
+	
+	set lmarks [ $landmarkcontrol GetCollection -1 ]	
+	$lmarks Compact
+	set numlmarks [ $lmarks GetNumPoints ]
+	
+	if { $numlmarks > 0 } {
+	    
+	    set pts [ vtkPolyData [ pxvtable::vnewobj ] ]
+	    $pts SetPoints [ $lmarks GetPoints ]
+	    
+	    $streamer SetSource $pts
+	    
+	    $pts Delete
+	}
+    }
+    
+    puts "num seed points: [ [ [ $streamer GetSource ] GetPoints ] GetNumberOfPoints ]"
+    puts "min speed = $global_list(track_minspeed)"
+    
+    $streamer SetTerminalSpeed $global_list(track_minspeed)
+    $streamer SetIntegrationDirectionToBackward
+    $streamer SetMaximumPropagationTime $global_list(track_maxdist)
+    if { $global_list(track_integration) == 0 } { 
+	$streamer SetIntegrator [ vtkRungeKutta2 [ pxvtable::vnewobj ] ]
+    } else {
+	$streamer SetIntegrator [ vtkRungeKutta4 [ pxvtable::vnewobj ] ]
+    }
+    $streamer SetIntegrationStepLength $global_list(track_steplen)
+    $streamer SetStepLength $global_list(track_steplen)
+    #$streamer SpeedScalarsOn
+    $streamer Update
+
+    set new_fiber [ vtkPolyData [ pxvtable::vnewobj ] ]
+    
+    ## create new fiber set
+    if { $global_list(track_fitspline) == 1 } {
+	
+	set spline [ vtkSplineFilter [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $spline "Spline fitting..."
+	$spline SetInput [ $streamer GetOutput ]
+	$spline SetSubdivide $global_list(track_splinesubdivision)
+	$spline SetLength $global_list(track_splinelength)
+	$spline SetNumberOfSubdivisions $global_list(track_splinenumber)
+	$spline Update
+
+	$new_fiber ShallowCopy [ $spline GetOutput ]
+
+	$spline Delete
+
+    } else {	
+	
+	$new_fiber ShallowCopy [ $streamer GetOutput ]
+    }
+    
+    $streamer Delete
+    
+    set index [ fiber_add $new_fiber ]
+    
+#    puts "points: [[$new_fiber GetPoints] GetNumberOfPoints]"
+
+    ## display new bundle
+    if { $global_list(view_fiber) } {	
+	
+	set actor [ view_create_fiber_glyph $index ]
+	lappend global_list(actor_fiber) $actor
+	
+	## add actor if to be displayed
+	if { [ lindex $global_list(fiber_disp_list) $index ] == 1 } { 
+	    for { set j 0 } { $j < 4 } { incr j } {
+		[ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] AddActor $actor
+	    }
+	}
+    }
+
+    puts "before statistics"
+
+    ## compute statistics
+    #if { $global_list(track_autostat) } {
+	#fiber_statistics
+    #}
+
+    WatchOff
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create results control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::CreateInputControl { base } {   
+
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Speed image"
+    pack $base.frame1 -fill both -expand f -pady 5
+    
+    set frame1 [ $base.frame1 childsite ]
+    
+    set subframe0 [ frame $frame1.subframe0 ]
+    pack $subframe0 -side top -fill both -expand f -pady 0
+    
+    set speed_fname [ iwidgets::entryfield $subframe0.speed_fname \
+			   -textvariable [ itcl::scope global_list(speed_fname) ] \
+			   -labeltext "Filename:" ] 
+    pack $speed_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(speed_fname) $speed_fname
+    
+    set tensor_load [ iwidgets::buttonbox $subframe0.tensor_load -orient horizontal -padx 2 ]
+    $tensor_load add load -text "Load..." -command [ itcl::code $this loadspeed ] 
+    $tensor_load add disp -text "Display" -command [ itcl::code $this DisplayResult 0 ]
+    pack $tensor_load -side left
+    set widget_list(tensor_load) $tensor_load
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Region of interest mask"
+    pack $base.frame0 -fill both -expand f -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+  
+    iwidgets::labeledframe $base.frame2 \
+	-labelpos nw  \
+	-labeltext "Map for analysis"
+    pack $base.frame2 -fill both -expand f -pady 5
+    
+    set frame2 [ $base.frame2 childsite ]
+    
+    set subframe0 [ frame $frame2.subframe0 ]
+    pack $subframe0 -side top -fill x -expand f -pady 0
+    
+    set map_fname [ iwidgets::entryfield $subframe0.map_fname \
+			-textvariable [ itcl::scope global_list(map_fname) ] \
+			-labeltext "Filename:" ] 
+    pack $map_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(map_fname) $map_fname
+    
+    set map_load [ iwidgets::buttonbox $subframe0.map_load -orient horizontal -padx 2 ]
+    $map_load add load -text "Load..." -command [ itcl::code $this loadmap ] 
+    $map_load add disp -text "Display" -command [ itcl::code $this DisplayResult 3 ]
+    pack $map_load -side left 
+    set widget_list(map_load) $map_load
+
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+    
+    set mask_fname [ iwidgets::entryfield $subframe1.mask_fname \
+			 -textvariable [ itcl::scope global_list(mask_fname) ] \
+			 -labeltext "Filename:" ] 
+    pack $mask_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(mask_fname) $mask_fname
+    
+    set mask_load [ iwidgets::buttonbox $subframe1.mask_load -orient horizontal -padx 2 ]
+    $mask_load add load -text "Load..." -command [ itcl::code $this loadmask ]    
+    $mask_load add disp -text "Display" -command [ itcl::code $this DisplayResult 1 ]
+    pack $mask_load -side left 
+    set widget_list(mask_load) $mask_load
+    
+    set mask_nreg [ iwidgets::spinint $subframe1.mask_nreg \
+			-labeltext "Number of regions in mask:" \
+			-fixed 4 -width 4 -range {1 1000} -step 1 \
+			-textvariable [ itcl::scope global_list(mask_nreg) ] ]
+    pack $mask_nreg -side right -pady 5 -padx 5
+    set widget_list(mask_nreg) $mask_nreg
+
+  
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create results control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::CreateResultsControl { base } {   
+
+    set color(0) \#dcdcdc
+    set color(1) black
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Results"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+    
+    iwidgets::scrolledlistbox $subframe0.resultlist \
+	-hscrollmode dynamic \
+	-selectmode extended \
+	-dblclickcommand [ itcl::code $this toggleresult ] \
+	-visibleitems 40x10 
+    
+    pack $subframe0.resultlist -side left -fill both -expand t -padx 2 -pady 2
+    set widget_list(result_list) $subframe0.resultlist
+    
+    foreach item $global_list(result_title) {
+	set enable [ lindex $item 2 ]
+     	$widget_list(result_list) insert end "[lindex $item 0]" 
+	$widget_list(result_list) itemconfigure end -foreground $color($enable)
+    }
+
+    set subframe1 [ frame $subframe0.subframe1 ]
+    pack $subframe1 -side right -fill both -padx 0
+    
+    set resultbbox [ iwidgets::buttonbox $subframe1.input -orient vertical ]
+    $resultbbox add display -text "Display" -command [ itcl::code $this displayresult ]
+    $resultbbox add save -text "Save..." -command [ itcl::code $this saveresult ]
+    $resultbbox add saveall -text "Save all" -command [ itcl::code $this saveallresults ]    
+    $resultbbox add mark -text "On/Off" -command [ itcl::code $this toggleresult ]
+
+    pack $resultbbox -side top -fill x -expand t -padx 0
+    set widget_list(result_buttonbox) $resultbbox
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill x -padx 2 -pady 5
+
+    set result_fpreffix [ iwidgets::entryfield $subframe2.result_fpreffix \
+			      -textvariable [ itcl::scope global_list(result_fpreffix) ] \
+			      -labeltext "Preffix:" ]
+    pack $result_fpreffix -side left -fill x -expand t -padx 5 -pady 2
+    set widget_list(result_fpreffix) $result_fpreffix    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create tensor control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::CreatePropagationControl { base } {
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Boundary conditions"
+    pack $base.frame0 -fill both -expand f -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+    
+    set boundary_fname [ iwidgets::entryfield $subframe1.mask_fname \
+			     -state disabled \
+			     -textvariable [ itcl::scope global_list(boundary_fname) ] \
+			     -labeltext "Filename:" ] 
+    pack $boundary_fname -side left -expand t -fill x -padx 5 -pady 5
+    set widget_list(boundary_fname) $boundary_fname
+    
+    set boundary_load [ iwidgets::buttonbox $subframe1.boundary_load -orient horizontal -padx 2 ]
+    $boundary_load add load -text "Load..." -command [ itcl::code $this loadboundary ] 
+    pack $boundary_load -side left
+    set widget_list(boundary_load) $boundary_load
+    
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Front propagation"
+    pack $base.frame1 -fill both -expand f 
+    
+    set frame0 [ $base.frame1 childsite ]
+
+   #  set subframe0 [ frame $frame0.subframe0 ]
+#     pack $subframe0 -side top -fill both -expand f -pady 5
+
+#     set solution_reuse [ checkbutton $subframe0.tractreuse \
+# 			    -text "Reuse solution" \
+# 			    -variable [ itcl::scope global_list(solution_reuse) ]]    
+#     pack $solution_reuse -side left -padx 5  
+
+#     set solution_maxiter [ iwidgets::spinint $subframe0.solution_maxiter \
+# 			       -labeltext "Maximum number of iterations:" \
+# 			       -fixed 3 -width 4 -step 1 -range {1 1000} ]
+#     pack $solution_maxiter -side right -padx 5  
+#     $solution_maxiter configure -textvariable [ itcl::scope global_list(solution_maxiter) ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f
+    
+    set solution_usemask [ checkbutton $subframe1.solution_usemask \
+			       -text "Use mask as computational boundary" \
+			       -variable [ itcl::scope global_list(solution_usemask) ] ]
+    pack $solution_usemask -side left -padx 5 -pady 5
+    
+#     set solution_error [ checkbutton $subframe1.solution_error \
+# 			     -text "Stop when error gets below:" \
+# 			     -variable [ itcl::scope global_list(solution_error) ] ]
+#     pack $solution_error -side left -padx 5
+    
+#     set solution_maxerror [ iwidgets::entryfield $subframe1.solution_maxerror \
+# 				-validate real -width 7  \
+# 				-textvariable [ itcl::scope global_list(solution_maxerror) ] ]
+#     pack $solution_maxerror -side left -padx 0
+    
+#     set solution_errorlabel [ label $subframe1.solution_errorlabel \
+# 				  -textvariable [ itcl::scope global_list(solution_errorlabel) ] ]
+#     pack $solution_errorlabel -side right -padx 5
+			      		
+    set subframe3 [ frame $frame0.subframe3 ]
+    pack $subframe3 -side top -fill both -expand f
+
+   #  set solution_method [ iwidgets::optionmenu $subframe3.solution_method \
+# 			     -command [ itcl::code $this solution_method_cb ] \
+# 			     -labeltext "Method:" ]
+#     pack $solution_method -side left -padx 5 -pady 5
+#     $solution_method insert end "Lax-Friedrichs Sweeping"
+#     $solution_method insert end "Fast Marching Method"
+#     set widget_list(solution_method) $solution_method
+    
+    set solution_autospacing [ checkbutton $subframe3.solution_autospacing \
+				   -text "Auto grid spacing (speed image)" \
+				   -command [ itcl::code $this solution_autospacing_cb ] \
+				   -variable [ itcl::scope global_list(solution_autospacing) ] ]
+    pack $solution_autospacing -side left -padx 5 -pady 5
+    
+    set solution_spacingx [ iwidgets::entryfield $subframe3.solution_spacingx \
+				-labeltext "Custom spacing:" \
+				-validate real \
+				-width 5  \
+				-state disabled \
+				-textvariable [ itcl::scope global_list(solution_spacingx) ] ]
+    pack $solution_spacingx -side left -padx 2 -pady 5
+    set widget_list(solution_spacingx) $solution_spacingx
+
+    set solution_spacingy [ iwidgets::entryfield $subframe3.solution_spacingy \
+				-validate real \
+				-width 5  \
+				-state disabled \
+				-textvariable [ itcl::scope global_list(solution_spacingy) ] ]
+    pack $solution_spacingy -side left -padx 2 -pady 5
+    set widget_list(solution_spacingy) $solution_spacingy
+
+    set solution_spacingz [ iwidgets::entryfield $subframe3.solution_spacingz \
+				-validate real \
+				-width 5  \
+				-state disabled \
+				-textvariable [ itcl::scope global_list(solution_spacingz) ] ]
+    pack $solution_spacingz -side left -padx 2 -pady 5
+    set widget_list(solution_spacingz) $solution_spacingz
+
+    set subframe4 [ frame $frame0.subframe4 ]
+    pack $subframe4 -side top -fill both -expand f
+
+    set solution_stopping [ checkbutton $subframe4.solution_stopping \
+				-text "Stop evolution at time:" \
+				-command [ itcl::code $this solution_stopping_cb ] \
+				-variable [ itcl::scope global_list(solution_stopping) ] ]
+    pack $solution_stopping -side left -padx 5 -pady 5    
+
+    set solution_stoptime [ iwidgets::entryfield $subframe4.solution_stoptime \
+				-validate real \
+				-width 7  \
+				-state disabled \
+				-textvariable [ itcl::scope global_list(solution_stoptime) ] ]
+    pack $solution_stoptime -side left -padx 2 -pady 5
+    set widget_list(solution_stoptime) $solution_stoptime
+
+    set solution_inf [ iwidgets::entryfield $subframe4.solution_inf \
+			   -labeltext "Value for infinite arrival time: " \
+			   -validate real -width 7  \
+			   -state disabled \
+			   -textvariable [ itcl::scope global_list(solution_inf) ] ]
+    pack $solution_inf -side left -padx 10 -pady 5
+    set widget_list(solution_inf) $solution_inf
+
+    set subframe5 [ frame $frame0.subframe5 ]
+    pack $subframe5 -side top -fill both -expand f
+
+    set solution_method [ iwidgets::optionmenu $subframe5.solution_method \
+			      -command [ itcl::code $this solution_method_cb ] \
+			      -labeltext "Accuracy:" ]
+    pack $solution_method -side left -padx 5 -pady 5
+    $solution_method insert end "First-order"
+    $solution_method insert end "Second-order"
+    set widget_list(solution_method) $solution_method
+    
+    set solution_initneighbors [ checkbutton $subframe5.solution_initneighbors \
+				     -text "Initialize boundary neighborhood" \
+				     -variable \
+				     [ itcl::scope global_list(solution_initneigbors) ] ]
+    pack $solution_initneighbors -side right -padx 10 -pady 5
+    set widget_list(solution_initneighbors) $solution_initneighbors    
+
+    set subframe6 [ frame $frame0.subframe6 ]
+    pack $subframe6 -side top -fill both -expand f
+    
+    set solution_useboundary [ checkbutton $subframe6.solution_useboundary \
+				   -text "Use boundary conditions from file" \
+				   -state disabled \
+				   -command [ itcl::code $this solution_stopping_cb ] \
+				   -variable [ itcl::scope global_list(solution_useboundary) ] ]
+    pack $solution_useboundary -side left -padx 5 -pady 5
+    set widget_list(solution_useboundary) $solution_useboundary
+    
+#    set solution_inf [ iwidgets::entryfield $subframe4.solution_inf \
+#			 -labeltext "Value for infinity: " \
+#			 -validate real -width 7  \
+#			 -textvariable [ itcl::scope global_list(solution_inf) ] ]
+#   pack $solution_inf -side left -padx 5 -pady 5
+    
+    # set solution_a [ iwidgets::entryfield $subframe3.solution_a \
+# 			 -labeltext "a: " \
+# 			 -validate real -width 7  \
+# 			 -textvariable [ itcl::scope global_list(solution_a) ] ]
+#     pack $solution_a -side right -padx 0
+    
+#     set solution_b [ iwidgets::entryfield $subframe3.solution_b \
+# 			 -labeltext "b: " \
+# 			 -validate real -width 7  \
+# 			 -textvariable [ itcl::scope global_list(solution_b) ] ]
+#     pack $solution_b -side right -padx 0
+    
+#     set solution_c [ iwidgets::entryfield $subframe3.solution_c \
+# 			 -labeltext "c: " \
+# 			 -validate real -width 7  \
+# 			 -textvariable [ itcl::scope global_list(solution_c) ] ]
+#     pack $solution_c -side right -padx 0
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill both -expand f
+    
+    set solution_btn [ iwidgets::buttonbox $subframe2.solution_btn -orient horizontal -padx 2 ]
+    $solution_btn add compute -text "Compute!" -command [ itcl::code $this result_propagate ] 
+    pack $solution_btn -side left
+
+    set widget_list(compute_btn) $solution_btn
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create fiber tracking control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::CreateTrackingControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Seed points"
+    pack $base.frame0 -fill both -expand f 
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand f
+    
+    set track_seedtype [ iwidgets::optionmenu $subframe0.track_seedtype \
+			     -command [ itcl::code $this track_seedtype_cb ] \
+			     -labeltext "Seed from:" ]
+    pack $track_seedtype -side left -padx 5 -pady 5
+    $track_seedtype insert end "Single point"
+    $track_seedtype insert end "Region"
+    $track_seedtype insert end "Volume"
+    $track_seedtype insert end "Landmark control"
+    set widget_list(track_seedtype) $track_seedtype
+
+    set track_seedregion [ iwidgets::spinint $subframe0.track_seedregion \
+			       -labeltext "Region number:" \
+			       -fixed 4 -width 4 -range {1 1000} -step 1 \
+			       -textvariable \
+			       [ itcl::scope global_list(track_seedregion) ] ]
+    pack $track_seedregion -side left -pady 5 -padx 2
+    set widget_list(track_seedregion) $track_seedregion  
+    $widget_list(track_seedregion) configure -state disabled
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -expand f
+    
+    set track_seedwidth [ iwidgets::entryfield $subframe1.track_seedwidth \
+			      -labeltext "Width:" \
+			      -validate integer \
+			      -width 4 \
+			      -state disabled \
+			      -textvariable [ itcl::scope global_list(track_seedwidth) ] ]
+    pack $subframe1.track_seedwidth -side left -padx 5 -pady 5 
+    set widget_list(track_seedwidth) $track_seedwidth
+    
+    set track_seedheight [ iwidgets::entryfield $subframe1.track_seedheight \
+			       -labeltext "Height:" \
+			       -validate integer \
+			       -width 4 \
+			       -state disabled \
+			       -textvariable [ itcl::scope global_list(track_seedheight) ] ]
+    pack $subframe1.track_seedheight -side left -padx 5 -pady 5
+    set widget_list(track_seedheight) $track_seedheight
+    
+    set track_seeddepth [ iwidgets::entryfield $subframe1.track_seeddepth \
+			      -labeltext "Depth:" \
+			      -validate integer \
+			      -width 4 \
+			      -state disabled \
+			      -textvariable [ itcl::scope global_list(track_seeddepth) ] ]
+    pack $subframe1.track_seeddepth -side left -padx 5 -pady 5 
+    set widget_list(track_seeddepth) $track_seeddepth
+    
+    set track_seeddens [ iwidgets::entryfield $subframe1.track_seeddens \
+			    -labeltext "Density:" \
+			    -validate real \
+			    -width 6 \
+			    -state disabled \
+			    -textvariable [ itcl::scope global_list(track_seeddens) ] ]
+    pack $subframe1.track_seeddens -side left -padx 5 -pady 5
+    set widget_list(track_seeddens) $track_seeddens
+
+     set subframe2 [ frame $frame0.subframe2 ]
+     pack $subframe2 -fill both -expand f
+    
+#     set track_map [ iwidgets::optionmenu $subframe2.track_map \
+# 			-command [ itcl::code $this track_map_cb ] \
+# 			-labeltext "Source map:" ]
+#     pack $track_map -side left -padx 5 -pady 5
+#     $track_map insert end "Gradient"
+#     $track_map insert end "Characteristics"
+#     set widget_list(track_map) $track_map
+
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Integration parameters"
+    pack $base.frame1 -fill both -expand f
+    
+    set frame1 [ $base.frame1 childsite ]
+    
+    set subframe2 [ frame $frame1.subframe2 ]
+    pack $subframe2 -fill both -expand f
+    
+    set integration [ iwidgets::optionmenu $subframe2.integration \
+			  -command [ itcl::code $this track_integration_cb ] \
+			  -labeltext "Type:" ]	
+    pack $integration -side left -padx 5 -pady 5
+    $integration insert end "Runge-Kutta 2"
+    $integration insert end "Runge-Kutta 4"
+    set widget_list(track_integration) $integration
+    
+    iwidgets::entryfield $subframe2.track_steplen \
+	-width 5 \
+	-validate real \
+	-labeltext "Step length:" \
+	-textvariable [ itcl::scope global_list(track_steplen) ] 
+    pack $subframe2.track_steplen -side left -padx 5 -pady 5     
+
+
+    set subframe5 [ frame $frame1.subframe5 ]
+    pack $subframe5 -fill both -expand f
+
+    iwidgets::entryfield $subframe5.track_maxdist \
+	-width 5 \
+	-validate real \
+	-labeltext "Max length:" \
+	-textvariable [ itcl::scope global_list(track_maxdist) ] 
+    pack $subframe5.track_maxdist -side left -padx 5 -pady 5    
+
+    iwidgets::entryfield $subframe5.track_minspeed \
+	-width 5 \
+	-validate real \
+	-labeltext "Minimum speed:" \
+	-textvariable [ itcl::scope global_list(track_minspeed) ] 
+    pack $subframe5.track_minspeed -side left -padx 5 -pady 5  
+
+    iwidgets::labeledframe $base.frame2 \
+	-labelpos nw  \
+	-labeltext "Path representation"
+    pack $base.frame2 -fill both -expand f
+    
+    set frame2 [ $base.frame2 childsite ]
+
+    set subframe6 [ frame $frame2.subframe6 ]
+    pack $subframe6 -fill both -expand f
+    
+    set track_fitspline [ checkbutton $subframe6.track_fitspline \
+			      -text "Fit splines to paths" \
+			      -variable [ itcl::scope global_list(track_fitspline) ] ]
+    pack $track_fitspline -side left -pady 2 -padx 5 
+    
+    set splinetype [ iwidgets::optionmenu $subframe6.splinetype \
+			 -command [ itcl::code $this track_splinetype_cb ] \
+			 -labeltext "Type:" ]	
+    pack $splinetype -side left -padx 5 -pady 2
+    $splinetype insert end "Cardinal"
+    $splinetype insert end "Kochaneck"
+    set widget_list(track_splinetype) $splinetype
+ 
+    set subframe7 [ frame $frame2.subframe7 ]
+    pack $subframe7 -fill both -expand f
+    
+    set splinesubdivision [ iwidgets::optionmenu $subframe7.splinesubdivision \
+				-command [ itcl::code $this track_splinesubdivision_cb ] \
+				-labeltext "Subdivision:" ]	
+    pack $splinesubdivision -side left -padx 5 -pady 2
+    $splinesubdivision insert end "Specified"
+    $splinesubdivision insert end "Length"
+    set widget_list(track_splinesubdivision) $splinesubdivision
+
+    iwidgets::entryfield $subframe7.track_splinelength \
+	-width 5 \
+	-validate real \
+	-labeltext "Length:" \
+	-textvariable [ itcl::scope global_list(track_splinelength) ] 
+    pack $subframe7.track_splinelength -side left -pady 5  
+
+    iwidgets::entryfield $subframe7.track_splinenumber \
+	-width 4 \
+	-validate integer \
+	-labeltext "Subdivisions:" \
+	-textvariable [ itcl::scope global_list(track_splinenumber) ] 
+    pack $subframe7.track_splinenumber -side left -padx 5 -pady 5  
+
+    set trackbtn [ iwidgets::buttonbox $base.trackbtn -orient horizontal ]
+    $trackbtn add track -text "Track!" -command [ itcl::code $this fiber_track ]
+    pack $trackbtn -side left -expand f
+
+    ## auto stat
+    set track_autostat [ checkbutton $base.track_autostat \
+			     -text "Auto path statistics" \
+			     -variable [ itcl::scope global_list(track_autostat) ] ]
+    pack $track_autostat -side right -padx 5       
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create fiber tracking control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::CreatePathwayControl { base } {
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Paths"
+    pack $base.frame0 -fill both
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -expand t -side top
+
+    label $subframe1.dummy0 -text "Color:"
+    pack $subframe1.dummy0 -side left -padx 5 -pady 5
+        
+    set fiber_color [ image create photo -width 15 -height 15 ]
+    $fiber_color put $global_list(fiber_color) -to 0 0 15 15
+    
+    button $subframe1.fiber_color -image $fiber_color \
+	-command [ itcl::code $this fiber_color_cb ]
+    pack $subframe1.fiber_color -side left
+    set widget_list(fiber_color) $subframe1.fiber_color
+
+    set fiber_name [ iwidgets::entryfield $subframe1.fiber_name \
+			 -textvariable [ itcl::scope global_list(fiber_name) ] \
+			 -labeltext "Name:" \
+			 -width 30 \
+			 -command [ itcl::code $this fiber_name_cb ] ] 
+    pack $fiber_name -side left -pady 5 -padx 5 -fill x -expand t
+    set widget_list(fiber_name) $fiber_name
+    
+    checkbutton $subframe1.fiber_display \
+	-text "Display" \
+	-variable [ itcl::scope global_list(fiber_display) ] \
+	-command [ itcl::code $this fiber_display_cb ]    
+    pack $subframe1.fiber_display -side left -padx 5
+
+    set middle [ frame $frame0.middle ] 
+    pack $middle -fill x -expand t -side top -pady 2
+    
+    set subframe2 [ frame $middle.subframe2 ]
+    pack $subframe2 -fill both -expand t -side left -pady 2
+
+    iwidgets::scrolledlistbox $subframe2.fiberlist \
+	-hscrollmode dynamic \
+	-visibleitems 40x15 \
+	-listvariable [ itcl::scope global_list(fiber_list) ] \
+	-selectmode extended \
+	-selectioncommand [ itcl::code $this fiber_selection_cb ]    
+    pack $subframe2.fiberlist -side left -fill both -expand t -padx 5
+    set widget_list(fiber_list) $subframe2.fiberlist
+   
+    set subframe3 [ frame $middle.subframe3 ]
+    pack $subframe3 -expand f -side left
+    
+    checkbutton $subframe1.fiber_threshold_byval \
+	-text "By value" \
+	-variable [ itcl::scope global_list(fiber_thresh_type) ]
+    pack $subframe1.fiber_threshold_byval -side left -padx 5
+
+    iwidgets::entryfield $subframe3.fiber_thresh_val \
+	-width 4 \
+	-validate real \
+	-labeltext "Value:" \
+	-textvariable [ itcl::scope global_list(fiber_thresh_val) ]
+    pack $subframe3.fiber_thresh_val -side bottom -padx 0   
+    
+    iwidgets::entryfield $subframe3.fiber_thresh_dist \
+	-width 4 \
+	-validate real \
+	-labeltext "Dist:" \
+	-textvariable [ itcl::scope global_list(fiber_thresh_dist) ]
+    pack $subframe3.fiber_thresh_dist -side bottom -padx 0   
+
+    set fiberbbox [ iwidgets::buttonbox $subframe3.fiberbbox -orient vertical ]
+    $fiberbbox add load -text "Load" -command [ itcl::code $this fiber_load ]
+    $fiberbbox add save -text "Save" -command [ itcl::code $this fiber_saveselected ]
+    $fiberbbox add saveall -text "Save all" -command [ itcl::code $this fiber_saveall ]
+    $fiberbbox add remove -text "Remove" -command [ itcl::code $this fiber_removeselected ]
+    $fiberbbox add clear -text "Clear" -command [ itcl::code $this fiber_clear ]
+    $fiberbbox add stat -text "Statistics" -command [ itcl::code $this fiber_statistics ]
+    $fiberbbox add err -text "Error" -command [ itcl::code $this fiber_error ]
+    $fiberbbox add thresh -text "Threshold" -command [ itcl::code $this fiber_threshold ]
+    pack $fiberbbox -side left -expand t
+    set widget_list(fiber_buttonbox) $fiberbbox                   
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create statistics control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::CreateStatisticsControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Statistics"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+
+    set stat_text [iwidgets::scrolledtext $subframe0.stat_text \
+		       -visibleitems 70x19 \
+		       -foreground black \
+		       -vscrollmode static \
+		       -hscrollmode static \
+		       -wrap none ]
+    pack $stat_text -side top -expand t -fill both -padx 2 -pady 2
+    set widget_list(stat_text) $stat_text
+
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -expand t
+
+    set statbbox [ iwidgets::buttonbox $subframe1.statbbox -orient horizontal -pady 2 -padx 2 ]
+    $statbbox add save -text "Save..." -command [ itcl::code $this fiber_savestatistics ]
+    $statbbox add clear -text "Clear" -command "$stat_text delete 1.0 end"
+    pack $statbbox -side left -fill both 
+
+    set stat_overwrite [ checkbutton $subframe1.stat_overwrite -text "Overwrite" \
+			     -variable [ itcl::scope global_list(stat_overwrite) ] ]
+    pack $stat_overwrite -side right -padx 5       
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create wavefront display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::CreateFrontDisplayControl { base } {
+
+    set subframe0 [ frame $base.subframe0 ]
+    pack $subframe0 -fill x -side top -expand f -padx 5 -pady 5
+    
+    checkbutton $subframe0.view_gradient -text "View gradient" \
+	-variable [ itcl::scope global_list(view_gradient) ] \
+	-command [ itcl::code $this view_toggle_gradient ]   
+    pack $subframe0.view_gradient -side left -padx 5
+    
+#    set subframe1 [ frame $base.subframe1 ]
+#    pack $subframe1 -fill x -side top -expand f -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe0.view_contour_levels \
+	-width 4 \
+	-validate integer \
+	-labeltext "Number of levels:" \
+	-textvariable [ itcl::scope global_list(view_contour_levels) ] \
+	-command [ itcl::code $this view_update_display_cb ]
+    pack $subframe0.view_contour_levels -side left -padx 5   
+    
+    iwidgets::entryfield $subframe0.view_contour_width \
+	-width 4 \
+	-validate real \
+	-labeltext "Contour width:" \
+	-textvariable [ itcl::scope global_list(view_contour_width) ]
+    pack $subframe0.view_contour_width -side left -padx 5   
+    
+    set subframe2 [ frame $base.subframe2 ]
+    pack $subframe2 -fill x -side top -expand f -padx 5 -pady 5
+
+    set front_luk [ mpjguilookuptable \#auto 0 ]
+    $front_luk Initialize $subframe2  
+    pack forget [ $front_luk GetButtonBoxWidget ]
+    #pack forget [ $front_luk GetMenuBar ]     
+    $front_luk SetHueRange 0.5 0.92
+    $front_luk SetSaturationRange 0.75 1.0
+    $front_luk Update
+    $front_luk Show
+    
+    set widget_list(view_frontluk) $front_luk    
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  Create fiber display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::CreatePathDisplayControl { base } {
+
+    set subframe0 [ frame $base.subframe0 ]
+    pack $subframe0 -fill x -side top -expand f -padx 5 -pady 5
+    
+#    set view_fiber_filter \
+#	[ iwidgets::optionmenu $subframe0.view_fiber_filter -labeltext "Filter:" ]
+    
+#    $view_fiber_filter configure -command [ itcl::code $this view_fiber_filter_cb ]
+#    $view_fiber_filter insert end "Validity index"
+    
+#    pack $view_fiber_filter -side left -padx 5
+#    set widget_list(view_fiber_filter) $view_fiber_filter
+    
+    set view_fiber_glyph [ iwidgets::optionmenu $subframe0.view_fiber_glyph \
+				-labeltext "View paths as:"   \
+				-command [ itcl::code $this view_fiber_glyph_cb ] ] \
+	
+    pack $view_fiber_glyph -side left -padx 5
+    $view_fiber_glyph insert end "Lines"
+    $view_fiber_glyph insert end "Tubes"
+    $view_fiber_glyph insert end "Points"
+    set widget_list(view_fiber_glyph) $view_fiber_glyph
+    
+    iwidgets::entryfield $subframe0.view_fiber_tuberadius \
+	-width 5 \
+	-validate real \
+	-labeltext "Tube radius:" \
+	-textvariable [ itcl::scope global_list(view_fiber_tuberadius) ]  \
+	-command [ itcl::code $this view_fiber_tuberadius_cb ]
+    pack $subframe0.view_fiber_tuberadius -side left -padx 5    
+
+    iwidgets::entryfield $subframe0.view_fiber_pointsize \
+	-width 5 \
+	-validate real \
+	-labeltext "Point size:" \
+	-textvariable [ itcl::scope global_list(view_fiber_pointsize) ]  \
+	-command [ itcl::code $this view_fiber_pointsize_cb ]
+    pack $subframe0.view_fiber_pointsize -side left -padx 5    
+    
+    set subframe2 [ frame $base.subframe2 ]
+    pack $subframe2 -side top -fill both -padx 5 -expand f
+    
+    set view_fiber_luk [ checkbutton $subframe2.view_fiber_luk \
+			     -text "Apply colormap" \
+			     -variable [ itcl::scope global_list(view_fiber_luk) ] \
+			     -command [ itcl::code $this view_fiber_colormap_cb ] ]
+    pack $view_fiber_luk -side left -pady 5 -padx 5       
+    set widget_list(view_fiber_luk) $view_fiber_luk
+    
+    set view_fiber_luktype \
+	[ iwidgets::optionmenu $subframe2.view_fiber_luktype -labeltext "to:" ]    
+    $view_fiber_luktype configure -command [ itcl::code $this view_fiber_luktype_cb ]
+    $view_fiber_luktype insert end "Path points"
+    $view_fiber_luktype insert end "Path pathways"
+    pack $view_fiber_luktype -side left -pady 5 -padx 0       
+    set widget_list(view_fiber_luktype) $view_fiber_luktype
+
+    set subframe3 [ frame $base.subframe3 ]
+    pack $subframe3 -side left -fill both -padx 5 
+    
+    set fiber_luk [ mpjguilookuptable \#auto 0 ]
+    $fiber_luk Initialize $subframe3  
+    pack forget [ $fiber_luk GetButtonBoxWidget ]
+    pack forget [ $fiber_luk GetMenuBar ]     
+    #    [ $fiber_luk GetLookupTable ] SetVectorModeToComponent
+    #    [ $fiber_luk GetLookupTable ] SetVectorComponent 0
+    $fiber_luk SetHueRange 0.5 0.92
+    $fiber_luk SetSaturationRange 0.75 1.0
+    $fiber_luk Update
+    $fiber_luk Show
+    
+    set widget_list(view_fiberluk) $fiber_luk
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::CreateDisplayControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Properties"
+    pack $base.frame0 -fill both -expand t 
+
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -padx 5 -pady 2 -expand f
+
+    checkbutton $subframe0.view_paths -text "View paths" \
+	-variable [ itcl::scope global_list(view_fiber) ] \
+	-command [ itcl::code $this view_toggle_fiber ]   
+    pack $subframe0.view_paths -side left -padx 5
+    
+    checkbutton $subframe0.view_contour -text "View front" \
+	-variable [ itcl::scope global_list(view_contour) ] \
+	-command [ itcl::code $this view_toggle_contour ]   
+    pack $subframe0.view_contour -side left -padx 5
+
+    checkbutton $subframe0.view_colorbar -text "View colorbar" \
+	-variable [ itcl::scope global_list(view_colorbar) ] \
+	-command [ itcl::code $this view_toggle_colorbar ]   
+    pack $subframe0.view_colorbar -side left -padx 5
+    
+    iwidgets::entryfield $subframe0.view_colorbar_label \
+	-width 10 \
+	-labeltext "Label:" \
+	-textvariable [ itcl::scope global_list(view_colorbar_label) ]
+    pack $subframe0.view_colorbar_label -side left -padx 5    
+    
+    set subframe1 [ frame $frame0.subframe1 ] 
+    pack $subframe1 -fill both -expand t -padx 5 -pady 5
+    
+    set display_notebook [ iwidgets::tabnotebook $subframe1.display_notebook -tabpos n ]     
+    set widget_list(display_notebook) $display_notebook
+    pack $display_notebook -fill both -expand t -padx 5 -pady 2
+    
+    CreateFrontDisplayControl [ $display_notebook add -label "Wavefront" ]
+    CreatePathDisplayControl [ $display_notebook add -label "Paths" ]
+
+    $display_notebook view "Wavefront"   
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  Create dialog boxes
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::savedir_dialog { base initdir title } {
+    
+    ## create save directory dialog box
+    set savedir [ iwidgets::extfileselectiondialog $base._savedir \
+		      -title $title \
+		      -directory $initdir \
+		      -master $base \
+		      -fileson 0 \
+		      -selectionon 0 \
+		      -modality application ]
+
+    ## center it
+    $savedir center $base
+    
+    set dir ""
+
+    ## activate it
+    if { [ $savedir activate ] } {
+	
+	## get directory 
+	set dir [ $savedir get ] 
+	
+	if { [ llength $dir ] == 0 } {
+	    set dir $initdir
+	}	
+    }
+    
+    itcl::delete object $savedir
+
+    return $dir
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create dialog boxes
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::openfile_dialog { base initdir title mask } {
+    
+    ## create open file dialog box
+    set openfile [ iwidgets::extfileselectiondialog $base._openfile \
+		      -title $title \
+		      -directory $initdir \
+		      -master $base \
+		      -width 500 \
+		      -mask $mask \
+		      -modality application ]
+    
+    ## center it
+    $openfile center $base
+    
+    set fname ""
+
+    ## activate it
+    if { [ $openfile activate ] } {
+	
+	## get directory 
+	set fname [ $openfile get ] 
+	
+	if { [ llength $fname ] == 0 } {
+	    set fname $initdir
+	}	
+    }
+    
+    itcl::delete object $openfile
+
+    return $fname
+}
+
+# -------------------------------------------------------------------------------------------
+#  Diffusion control inititialization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::Initialize { widget } {
+    
+    if { $initialized == 1 } { return $basewidget }
+    
+    #  -------------------------------------
+    #  Create User Interface
+    #  -------------------------------------	
+    set basewidget [toplevel $widget ]
+    wm geometry $basewidget 620x500
+    wm withdraw $basewidget
+
+    set notebook $basewidget.notebook    
+    iwidgets::tabnotebook $notebook -tabpos w         
+    set widget_list(notebook) $notebook
+
+    set mb [ frame $basewidget.mb ]
+    pack $mb -side top -fill x -expand false
+
+    CreateMenu $mb
+
+    CreateInputControl       [ $notebook add -label "Input" ] 
+    CreatePropagationControl [ $notebook add -label "Propagation" ]
+    CreateTrackingControl    [ $notebook add -label "Tracking" ]
+    CreatePathwayControl     [ $notebook add -label "Pathways" ]
+    CreateStatisticsControl  [ $notebook add -label "Statistics" ]
+    CreateResultsControl     [ $notebook add -label "Results" ]
+    CreateDisplayControl     [ $notebook add -label "Display" ]
+    
+    pack $notebook -side top -fill both -expand t -padx 5
+    
+    $notebook view "Input"
+    
+    set pbar [ frame $basewidget.pbar -width 400 -height 20 ]
+    pack $pbar -side bottom -expand f -fill x
+    CreateProgressBar $pbar
+    
+    set w [ frame $basewidget.w -relief ridge -width 800]
+    pack $w -side bottom -fill x -expand false
+    
+    eval "button $w.close -text Close -command { $this DismissWindow }"
+    pack $w.close -side right -fill x -padx 5 -pady 10
+    
+    set initialized 1
+
+    SetTitle $appname
+    
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { $this DismissWindow }"
+    
+    return $basewidget
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create top level menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::CreateMenu { mb } {    
+    
+    menubutton $mb.results       -text Results     -menu $mb.results.m -underline 0
+    pack $mb.results    -side left
+    menubutton $mb.help      -text Help         -menu $mb.help.m -underline 0 -padx 4
+    pack $mb.help  -side right
+
+    menu $mb.results.m -tearoff 0 
+    $mb.results.m add command -label "Save All Results" -command [ itcl::code $this saveallresults ] -underline 0
+    $mb.results.m add separator
+    if { $parent == 0 } {
+	eval "$mb.results.m add command -label Exit -command {  pxtkexit } -underline 1"
+    } else {
+	eval "$mb.results.m add command -label Close -command {  $this HideWindow } -underline 1"
+    }
+
+    menu $mb.help.m -tearoff 0
+
+    set widget_list(menu_results) $mb.results.m    
+
+    eval "$mb.help.m add command -label About -command { $this AboutCommand }"
+   
+}
+
+#-------------------------------------------------------------------------------------------
+#  Add controls to menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfastmarching::AddToMenuButton { mb args } {
+    eval "$mb add command -label \"Fast Marching\" -command {$this ShowWindow \"Input\"}"
+}
+
+#-------------------------------------------------------------------------------------------
+#  Main function for stand-alone execution
+# ------------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+
+    puts "\n[ file rootname $argv0 ] is not a stand-alone program.\n"
+    exit
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjfibertracking.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjfibertracking.tcl
new file mode 100644
index 0000000..4b1e8ba
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjfibertracking.tcl
@@ -0,0 +1,3085 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package provide mpjfibertracking 1.2
+
+package require  Itcl 3.2
+package require  Iwidgets 4.0
+
+package require  pxitcllistselector 1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitclbaseimageviewer 1.0
+
+package require  vtkmpjcontrib 1.1
+package require  mpjguilookuptable 1.0
+
+itcl::class mpjfibertracking {
+
+    inherit pxitclbaseimagecontrol
+    
+    #-----------------------------------
+    # construction and destruction
+    #-----------------------------------
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } { InitializeControl }
+    
+    destructor { }
+    
+    #-----------------------------------
+    # common variables
+    #-----------------------------------
+
+    #-----------------------------------
+    # global variables
+    #-----------------------------------
+    private variable widget_list
+    private variable global_list
+    
+    #-----------------------------------
+    # initialization methods
+    #-----------------------------------
+    public method Initialize { inpwidg }
+    public method InitializeControl { }
+    public method DismissWindow { }
+    
+    #-----------------------------------
+    # input/output
+    #-----------------------------------
+    public method LoadMap { fname }
+    public method LoadMask { fname }
+    public method LoadTensor { fname }
+    public method SaveAllResults { }
+    public method SaveResult { index }
+    public method ClearAllResults { }
+    public method DisplayResult { index }
+    public method ClearDisplay { }
+    public method SetResultPreffix { preffix }
+    public method GetResultPreffix { } 
+    public method SetCurrentDirectory { fname } 
+    
+    #-----------------------------------
+    # interface creation methods
+    #-----------------------------------
+    private method CreateInputControl { base }
+    private method CreateDirectionControl { base }
+    private method CreateTrackingControl { base }
+    private method CreateDisplayControl { base }
+    private method CreateFiberControl { base }
+    private method CreateStatisticsControl { base }    
+    private method CreateResultsControl { base }
+    private method CreateFiberDisplayControl { base }
+    private method CreateMenu { mb }
+    public method AddToMenuButton { mb args}    
+    public method CreateViewMenu { menubase }
+ 
+    private method loadmap { }
+    private method loadtensor { }
+    private method loadmask { }
+    private method displayresult { }
+    private method saveresult { }
+    private method toggleresult { }
+    private method saveallresults { }
+ 
+    private method initialize_glyphs { }
+    private method input_updateinfo { index }    
+    private method input_selectioncommand_cb { }   
+    
+    private method track_seedtype_cb { }
+    private method track_integration_cb { }
+    private method track_eigenvector_cb { }
+    private method track_regionfilter_cb { }
+
+    private method view_colorbar_cb { } 
+    private method view_directionscheme_cb { }
+    private method view_update_display_cb { }
+
+    public method  view_update_crosshair_cb { arg }
+    private method view_toggle_trackexplore { }
+
+    private method view_clear_display { }
+    private method view_update_display { }
+    private method view_toggle_colorbar { }
+    private method view_toggle_fiber { }
+
+    private method view_create_fiber_glyph { index }
+    private method view_create_fibers { }
+    private method view_create_colorbar { }
+
+    private method view_fiber_glyph_cb { }
+    private method view_fiber_tuberadius_cb { }
+    private method view_fiber_pointsize_cb { }
+    private method view_fiber_colormap_cb { }
+    private method view_fiber_cmapresetbtn_cb { }
+    private method view_fiber_cmaploadbtn_cb { }
+    private method view_fiber_cmapsavebtn_cb { }
+    private method view_fiber_filter_cb { }
+          
+    private method fiber_add { polydata }
+    private method fiber_addwithname { name polydata }
+    private method fiber_remove { index } 
+    private method fiber_removeselected { }
+    private method fiber_clear { }
+    private method fiber_load { }
+    private method fiber_save { index name }
+    private method fiber_saveall { }
+    private method fiber_saveselected { }
+    private method fiber_track { }
+
+    private method fiber_explore { cx cy cz }
+
+    private method fiber_statistics { }
+    private method fiber_quantize { }
+    private method fiber_addstatistics { title results tag }
+    private method fiber_beginstatistics { title overwrite }
+    private method fiber_savestatistics { }
+    private method fiber_selection_cb { }
+    private method fiber_color_cb { }
+    private method fiber_name_cb { }
+    private method fiber_display_cb { }
+
+    private method result_clear { }
+    private method update_list { node }    
+
+    private method savedir_dialog { base initdir title }
+    private method openfile_dialog { base initdir title mask }
+}  
+
+#-------------------------------------------------------------------------------------------
+#  Close window 
+# -------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::DismissWindow { } {
+    
+    set ok "yes"
+
+    if { $global_list(tensor_fname) != "" } {
+
+	set ok [ tk_messageBox -type yesnocancel -default no \
+		     -parent $basewidget -title "Think again ..." \
+		     -message "Unload all images from memory?" -icon question  ]
+    }
+    
+    if { $ok == "yes" } {	
+
+	
+	fiber_clear
+	
+	view_clear_display 
+	
+	$this ClearAllResults
+	
+	$this SetTitle $global_list(appname)
+	
+	set global_list(mask_fname) ""
+	set global_list(tensor_fname) ""
+	
+    }
+    
+    if { $ok != "cancel" } {
+	$this HideWindow
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  Initialize tool
+# -------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::InitializeControl { } {
+
+    set global_list(appname) "Fiber Tracking Utility"
+    
+    set appname "$global_list(appname) $version"
+    set aboutstring "(c) Marcel Jackowski 2008"
+    
+    # create list of basic colors
+    set global_list(tkcolor_list) "\#ff0000 \#ffff00 \#00ff00 \#00ffff \#0000ff \#ff00ff"
+    
+    # create image titles
+    set global_list(result_title) \
+	[ list \
+	      { "Diffusion tensor"     "dti_tensor" 0 } \
+	      { "Regions of interest"  "dti_roi" 0 } \
+	      { "Map for analysis"     "dti_map" 0 } \
+	      { "Fiber quantization"   "dti_fiber" 1 } ]
+    
+    foreach item $global_list(result_title) {
+ 	lappend result_list [ pxitclimage \#auto ]
+    }  
+    
+    set global_list(result_fdir) [ pwd ]
+    set global_list(result_fpreffix) "preffix_"
+    set global_list(result_list) $result_list
+    
+    set global_list(mask_fname) ""
+    set global_list(mask_nreg) 1
+    
+    set global_list(tensor_fname) ""    
+    set global_list(map_fname) ""
+    
+    set global_list(track_lastpoint) { 0 0 0 }
+    set global_list(track_seedtype) 0
+    set global_list(track_seedregion) 1
+    set global_list(track_seedwidth) 3
+    set global_list(track_seedheight) 3
+    set global_list(track_seeddepth) 3
+    set global_list(track_seeddens) 1.0  
+    set global_list(track_integration) 1
+    set global_list(track_eigenvector) 0
+    set global_list(track_steplen) 0.25
+    set global_list(track_maxdist) 100.0
+    set global_list(track_mindist) 10.0
+    set global_list(track_maxangle) 45.0
+    set global_list(track_minFA) 0.2
+    set global_list(track_maxFA) 1.0
+    set global_list(track_minMD) 0.0
+    set global_list(track_maxMD) 10.0   
+    set global_list(track_regionfilter) 0
+    set global_list(track_regionnumber) 1
+    set global_list(track_clipping) 0
+    set global_list(track_autostat) 1
+    set global_list(track_flipping) 1
+    set global_list(track_explore) 0
+    set global_list(track_dec) 1
+    set global_list(track_flipx) 0
+    set global_list(track_flipy) 0
+    set global_list(track_flipz) 0
+
+    set global_list(fiber_display) 1
+    set global_list(fiber_color) "\#ff0000"
+    set global_list(fiber_list) {}
+    set global_list(fiber_color_list) {}
+    set global_list(fiber_disp_list) {}
+    
+    set global_list(stat_overwrite) 0
+
+    set global_list(view_colorbar) 0 
+    set global_list(view_colorbar_label) "Map"
+    set global_list(view_fiber) 0
+    set global_list(view_fiber_tuberadius) 0.20
+    set global_list(view_fiber_pointsize) 1.0
+    
+    set global_list(view_direction_scheme) 0
+    set global_list(view_direction_saturation) 0.5
+    set global_list(view_direction_scaling) 1.0
+    set global_list(view_direction_modulate) 0
+    set global_list(view_direction_alpha) 0
+    
+
+    ## create actors for visualization
+    set global_list(actor_colorbar) -1
+    set global_list(actor_fiber) {}
+
+    ## vtk data
+    set global_list(vtk_fiber_tube) {}
+    set global_list(vtk_fiber_polydata) {}
+    
+    initialize_glyphs
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create visualization glyphs
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::initialize_glyphs { } {
+
+    ## create line source
+    set line_src [ vtkLineSource [ pxvtable::vnewobj ] ]
+    $line_src SetPoint1 0.0 0 0
+    $line_src SetPoint2 2.0 0 0    
+
+    set line_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $line_xfrm Translate -1.0 0.0 0.0
+
+    set line [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $line SetInput [ $line_src GetOutput ]
+    $line SetTransform $line_xfrm
+    lappend global_list(glyph_list) $line 
+
+    $line_src Delete
+    $line_xfrm Delete
+    
+    ## create tube source
+    set tube_src [ vtkCylinderSource [ pxvtable::vnewobj ] ]
+    $tube_src SetHeight 2.0
+    $tube_src SetRadius 0.25
+    $tube_src CappingOn
+    
+    set tube_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $tube_xfrm RotateZ -90.0
+    
+    set tube [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $tube SetInput [ $tube_src GetOutput ]
+    $tube SetTransform $tube_xfrm
+    lappend global_list(glyph_list) $tube
+
+    $tube_src Delete
+    $tube_xfrm Delete
+
+    ## create arrow source
+    set arrow_src [ vtkArrowSource [ pxvtable::vnewobj ] ]
+    $arrow_src SetTipLength 0.35
+    $arrow_src SetTipResolution 10
+    $arrow_src SetTipRadius 0.20
+    $arrow_src SetShaftResolution 10
+    $arrow_src SetShaftRadius 0.1
+
+    set arrow_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $arrow_xfrm Translate -1.0 0.0 0.0
+    $arrow_xfrm Scale 2.0 2.0 2.0
+
+    set arrow [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $arrow SetInput [ $arrow_src GetOutput ]
+    $arrow SetTransform $arrow_xfrm
+    lappend global_list(glyph_list) $arrow
+
+    $arrow_src Delete
+    $arrow_xfrm Delete
+    
+    ## create ellipsoid source
+    set ellipsoid_src [ vtkSphereSource [ pxvtable::vnewobj ] ]
+    set ellipsoid_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $ellipsoid_xfrm Scale 2.0 2.0 2.0
+
+    set ellipsoid [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $ellipsoid SetInput [ $ellipsoid_src GetOutput ]
+    $ellipsoid SetTransform $ellipsoid_xfrm
+    lappend global_list(glyph_list) $ellipsoid
+
+    $ellipsoid_src Delete
+    $ellipsoid_xfrm Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load mask
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::loadmask { } {
+    
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select mask" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadMask $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in mask image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::LoadMask { fname } {
+
+    set MASK 1     
+    set mask [ lindex $global_list(result_list) $MASK ]
+    
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    $this SetFilterCallbacks $ana "Reading in mask image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    ## if mask not a unsigned char image, convert it
+    set scalar_type [ [ $ana GetOutput ] GetScalarType ]    
+
+    if { $scalar_type != 3 } {	
+	
+	set imcast [ vtkImageCast [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $imcast "Converting mask to unsigned char values..."
+	$imcast SetInput [ $ana GetOutput ]
+	$imcast SetOutputScalarTypeToUnsignedChar
+	$imcast ClampOverflowOn	
+	$imcast Update
+	
+	## fixed on 11/1/04
+	$mask CopyImageHeader [ $ana GetImageHeader ]
+	$mask ShallowCopyImage [ $imcast GetOutput ]
+	
+	$imcast Delete
+	
+    } else {
+	
+	$mask SetFromAnalyzeSource $ana
+    }
+   
+    ## determine range of values in mask
+    set range [ [ [ [ $mask GetImage ] GetPointData ] GetScalars ] GetRange ]
+
+    ## take the maximum range as the number of regions in mask
+    set global_list(mask_nreg) [ expr int([ lindex $range 1 ])]
+    $widget_list(mask_nreg) configure -range [ list 1 $global_list(mask_nreg) ]
+    
+    set global_list(mask_fname) $fname
+
+    WatchOff
+    
+    $ana Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load map
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::loadmap { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select map" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load map into memory
+	LoadMap $fname
+    }    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in map image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::LoadMap { fname } {
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in map image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    [ lindex $global_list(result_list) 2 ] SetFromAnalyzeSource $ana
+    
+    set global_list(map_fname) $fname
+    
+    WatchOff
+    
+    $ana Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load tensor
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::loadtensor { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select tensor" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+        
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadTensor $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in tensor image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::LoadTensor { fname } {
+
+    set TENSOR 0
+    set MASK 1
+    set MAP 2
+    set FIBERS 3
+
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    set fibers [ lindex $global_list(result_list) $FIBERS ]
+    set map [lindex $global_list(result_list) $MAP ]
+
+    WatchOn
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in tensor image..."
+    
+    ## load series 
+    $ana Load $fname 
+
+    $tensor SetFromAnalyzeSource $ana
+
+    set global_list(tensor_fname) $fname
+
+    ## determine coordinate transform
+    set or [ $ana GetOrientation ]
+#    if { $or == 0 } {
+# 	set global_list(track_flipx) 1
+# 	set global_list(track_flipy) 1
+#    } elseif { $or == 1 } {
+# 	set global_list(track_flipx) 1
+#    } 
+    
+    $ana Delete
+
+    scan [ [ $tensor GetImage ] GetDimensions ] "%d %d %d" dx dy dz	       
+    set nc [ [ $tensor GetImage ] GetNumberOfScalarComponents ]
+    set name [ file tail [ file root $fname ] ]
+        
+    set sufpos [ string last "dti_tensor" $name ]
+    if { $sufpos != -1 } {
+	set name [ string range $name 0 [expr $sufpos - 1] ]
+    }
+
+    ## create fiber image
+    set ext [ vtkImageExtractComponents [ pxvtable::vnewobj ] ]
+    $ext SetInput [ $tensor GetImage ]
+    $ext SetComponents 0
+    $ext Update
+
+    $fibers CopyImageHeader [ $tensor GetImageHeader ]
+    $fibers ShallowCopyImage [ $ext GetOutput ]
+    $ext Delete
+
+    set global_list(result_fdir) [ file dir $fname ]
+    set global_list(result_fpreffix) [ file join $global_list(result_fdir) "${name}" ]
+
+    WatchOff
+
+    $widget_list(trackbtn) buttonconfigure 0 -state normal
+    $widget_list(menu_tracking) entryconfigure 0 -state normal
+    $widget_list(menu_tracking) entryconfigure 2 -state normal
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Set result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::SetResultPreffix { preffix } {
+    set global_list(result_fpreffix) $preffix
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Get result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::GetResultPreffix { } {
+    return $global_list(result_fpreffix)
+}
+
+itcl::body mpjfibertracking::SetCurrentDirectory { fname } {
+    set global_list(result_fdir) $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Clear all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::ClearAllResults { } {
+    
+    foreach result $global_list(result_list) {
+	$result Clear
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::SaveAllResults { } {
+
+    foreach result $global_list(result_list) title $global_list(result_title) {
+	
+	set fname $global_list(result_fpreffix)
+	set fname "$fname[ lindex $title 1 ]"
+	
+	$result Save $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save single result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::SaveResult { index } {        
+
+    set fname $global_list(result_fpreffix)
+    set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]"
+
+    [lindex $global_list(result_list) $index] Save $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::saveallresults { } {
+
+    ## browse for directory
+    set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+    
+    if { $fdir != "" } {
+	
+	set global_list(result_fdir) $fdir
+	
+	foreach result $global_list(result_list) title $global_list(result_title) {
+	    
+	    set fname $global_list(result_fpreffix)
+	    set fname "$fname[ lindex $title 1 ]"
+	    
+	    $result Save [ file join $fdir $fname ]
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::saveresult { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(result_list) getcurselection ]
+    
+    if { $sel_item != "" } { 
+
+	## browse for directory
+	set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+	
+	if { $fdir != "" } {
+	    
+	    set global_list(result_fdir) $fdir
+	    
+	    foreach item $sel_item {
+		
+		set index [ $widget_list(result_list) index $item ]
+		set result [ lindex $global_list(result_list) $index ]
+		
+		set fname $global_list(result_fpreffix)
+		set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]"
+		
+		$result Save [ file join $fdir $fname ]
+	    }
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::DisplayResult { index } {
+    $parent SetImageFromObject \
+	[ [ lindex $global_list(result_list) $index ] GetThisPointer ] $this
+    $parent ShowWindow
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::displayresult { } {
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+	    
+    if { $sel_item != "" } {
+	set index [ $widget_list(result_list) index [ lindex $sel_item 0 ] ]
+	set result [ lindex $global_list(result_list) $index ]
+	
+	$this DisplayResult $index	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: toggle result computation on/off
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::toggleresult { } {
+   
+    set color(0) \#dcdcdc
+    set color(1) black
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+
+    if { $sel_item != "" } {
+
+	set index [ $widget_list(result_list) index [ lindex $sel_item 0 ] ]
+
+	if { $index > 2 } {
+	    set enable [expr 1 - [ lindex [ lindex $global_list(result_title) $index ] 2 ] ]
+	    
+	    $widget_list(result_list) itemconfigure $index -foreground $color($enable)
+	    
+	    set item [ lindex $global_list(result_title) $index ]
+	    set new_item [ lreplace $item 2 2 $enable ]
+	    
+	    set global_list(result_title) [ lreplace $global_list(result_title) \
+						$index $index $new_item ]
+	}
+    }
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::result_clear { } {
+    for { set i 0 } { $i < [ llength $global_list(result_list) ] } { incr i } {		
+	if { $i > 0 } {	    
+	    [ lindex $global_list(result_list) $i ] Clear	    
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear display
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_clear_display { } {
+    
+    ## remove fibers
+    foreach actor $global_list(actor_fiber) {	    
+	if { $actor != "-1" } {
+	    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+	    $actor Delete	    
+	}
+	set global_list(actor_fiber) {}
+    }
+    
+    ## remove colorbar
+    set actor $global_list(actor_colorbar)
+    if { $actor != "-1" } {
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+	$actor Delete	   
+	set global_list(actor_colorbar) -1
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Update display
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_update_display { } {
+    
+    if { $global_list(view_colorbar) } {
+	view_create_colorbar
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off colorbar visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_toggle_colorbar { } {
+    
+    if { $global_list(view_colorbar) } {
+	view_create_colorbar
+    } else {
+	set actor $global_list(actor_colorbar)
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor
+	$actor Delete
+
+	set global_list(actor_colorbar) -1
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  View fiber bundle
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_create_fiber_glyph { index } {
+
+    set field(0) fractani
+    set field(1) meandiff
+    set field(2) distance
+    set field(3) angle
+    set field(4) roi
+    set field(5) other
+    set field(6) rgb
+
+    ## create mapper
+    set fiberMapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_fiber_glyph) \
+			index [ $widget_list(view_fiber_glyph) get ] ]
+        
+    ## get current fiber colormap filter    
+    set filter [ $widget_list(view_fiber_filter) index [ $widget_list(view_fiber_filter) get ]]
+
+    if { $cur_glyph == 1 } {
+	set tube [ lindex $global_list(vtk_fiber_tube) $index ]
+	
+	$tube SetInput [ lindex $global_list(vtk_fiber_polydata) $index ]
+	$tube SetRadius $global_list(view_fiber_tuberadius)
+	$tube SetNumberOfSides 6
+	$tube Update
+	
+	$fiberMapper SetInput [ $tube GetOutput ]	
+	$fiberMapper SetLookupTable [ $widget_list(view_fiberluk) GetLookupTable ]
+	$fiberMapper UseLookupTableScalarRangeOn
+	$fiberMapper SetScalarModeToUsePointFieldData
+
+	if { [ [ [ $tube GetOutput ] GetPointData ] GetArray $field($filter) ] != "" } {
+	    $fiberMapper ColorByArrayComponent $field($filter) 0
+	}
+	
+	if { $global_list(view_fiber_luk) } {	    
+	    $fiberMapper ScalarVisibilityOn
+	} else {
+	    $fiberMapper ScalarVisibilityOff
+	}
+
+    } 
+
+    if { [expr $cur_glyph == 0 || $cur_glyph == 2 ] } {
+	
+	set polydata [ lindex $global_list(vtk_fiber_polydata) $index ]
+
+	$fiberMapper SetInput $polydata
+	$fiberMapper SetLookupTable [ $widget_list(view_fiberluk) GetLookupTable ]
+	$fiberMapper UseLookupTableScalarRangeOn
+	$fiberMapper SetScalarModeToUsePointFieldData
+	
+	if { [ [ $polydata GetPointData ] GetArray $field($filter) ] != "" } {
+	    $fiberMapper ColorByArrayComponent $field($filter) 0
+	}
+
+	if { $global_list(view_fiber_luk) } {	    
+	    $fiberMapper ScalarVisibilityOn
+	} else {
+	    $fiberMapper ScalarVisibilityOff
+	}
+    }
+
+
+    ## create actor
+    set fiberActor [ vtkActor [ pxvtable::vnewobj ] ]
+    $fiberActor SetMapper $fiberMapper
+    
+    if { $cur_glyph == 2 } {
+	[ $fiberActor GetProperty ] SetRepresentationToPoints
+	[ $fiberActor GetProperty ] SetPointSize $global_list(view_fiber_pointsize)
+    }
+    
+    $fiberMapper Delete
+    
+    ## convert tk color spec to vtk
+    set color [ lindex $global_list(fiber_color_list) $index ]
+    set red "0x[string range $color 1 2]"
+    set green "0x[string range $color 3 4]"
+    set blue "0x[string range $color 5 6]"
+    set red [ expr [ format "%d" $red ] / 255.0 ]
+    set green [ expr [ format "%d" $green ] / 255.0 ]
+    set blue [ expr [ format "%d" $blue ] / 255.0 ]
+    
+    [$fiberActor GetProperty] SetColor $red $green $blue
+    
+    return $fiberActor
+}
+
+#-------------------------------------------------------------------------------------------
+#  View fibers
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_create_fibers { } {    
+
+    set num [ llength $global_list(fiber_list) ]
+    
+    for {set j 0} {$j < $num} {incr j} {
+	
+	set actor [ view_create_fiber_glyph $j ]
+	
+	lappend global_list(actor_fiber) $actor
+	
+	## add actor if to be displayed
+	if { [ lindex $global_list(fiber_disp_list) $j ] == 1 } { 
+	    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+	}
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  View colorbar
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_create_colorbar { } {
+        
+    set title [ $widget_list(view_fiber_filter) get ]
+    if { $title == "Input map" } {
+	set title $global_list(view_colorbar_label)
+    }
+
+    set bar [ vtkScalarBarActor [ pxvtable::vnewobj ] ]
+    $bar SetLookupTable [ $widget_list(view_fiberluk) GetLookupTable ]
+    
+    $bar SetTitle $title
+    [$bar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport
+    [$bar GetPositionCoordinate] SetValue 0.1 0.01
+    $bar SetOrientationToHorizontal
+    $bar SetWidth 0.8
+    $bar SetHeight 0.12
+    
+    set global_list(actor_colorbar) $bar
+    
+    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor2D $bar    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in seed type
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::track_seedtype_cb { } {
+
+    set state(0) disabled; set state(1) normal    
+    set global_list(track_seedtype) \
+	[ $widget_list(track_seedtype) index [ $widget_list(track_seedtype) get ] ]
+
+    if { [expr $global_list(track_seedtype) < 2 || $global_list(track_seedtype) == 3 ]} {
+	$widget_list(track_seedwidth) configure -state disabled
+	$widget_list(track_seedheight) configure -state disabled
+	$widget_list(track_seeddepth) configure -state disabled
+	if { $global_list(track_seedtype) == 1 } {
+	    $widget_list(track_seeddens) configure -state normal
+	} else {
+	    $widget_list(track_seeddens) configure -state disabled
+	}
+    } else {
+	$widget_list(track_seedwidth) configure -state normal
+	$widget_list(track_seedheight) configure -state normal
+	$widget_list(track_seeddepth) configure -state normal
+	$widget_list(track_seeddens) configure -state normal
+    }
+    
+    if { $global_list(track_seedtype) == 1 } {
+	$widget_list(track_seedregion) configure -state normal
+    } else {
+	$widget_list(track_seedregion) configure -state disabled	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in region filtering option
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::track_regionfilter_cb { } {
+
+    set state(1) normal
+    set state(0) disabled
+
+    $widget_list(track_regionnumber) configure -state \
+	$state($global_list(track_regionfilter))
+    
+    $widget_list(track_clipping) configure -state \
+	$state($global_list(track_regionfilter))
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in color schemes
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_directionscheme_cb { } {
+    set global_list(view_direction_scheme) \
+	[ $widget_list(view_direction_scheme) index [ $widget_list(view_direction_scheme) get ] ]
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in integration
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::track_integration_cb { } {
+    set global_list(track_integration) \
+	[ $widget_list(track_integration) index [ $widget_list(track_integration) get ] ]
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in eigenvector
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::track_eigenvector_cb { } {
+    set global_list(track_eigenvector) \
+	[ $widget_list(track_eigenvector) index [ $widget_list(track_eigenvector) get ] ]
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon an crosshair update
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_update_crosshair_cb { args } {
+
+    set mousebutton [ lindex $args 1 ]
+    set mousestate  [ lindex $args 2 ]
+    
+    ## mousebutton - 1: left, 2:middle, 3:right
+    ## mousestate - 0:down, 1:move, 2:up
+    
+    ## get slice numbers
+    set levels [ [ $parent GetViewer ] GetLastClickedPoint ] 
+    if { [ llength $levels ] < 3 } {
+	return
+    }
+
+    set cx [ lindex $levels 0 ]
+    set cy [ lindex $levels 1 ]
+    set cz [ lindex $levels 2 ]
+
+    set ox [ lindex $global_list(track_lastpoint) 0 ]
+    set oy [ lindex $global_list(track_lastpoint) 1 ]
+    set oz [ lindex $global_list(track_lastpoint) 2 ]
+
+    ## we are not under rotation
+    if { $cx != -1 } {
+	
+	## puts "mouse state: $mousestate"
+
+	set changedpoint 0
+	if {  $cx != $ox || $cy != $oy || $cz != $oz   } {
+	    set changedpoint 1
+	}
+
+	if { $mousestate == 0 && $changedpoint == 1 && $mousebutton == 4 } {
+
+	    # create a new fiber if needed 
+	    # not the same seed point
+	    fiber_explore $cx $cy $cz
+
+	    ## show fibers
+	    view_update_display
+
+	    ## record last point
+	    set global_list(track_lastpoint) $cx
+	    lappend global_list(track_lastpoint) $cy
+	    lappend global_list(track_lastpoint) $cz	    
+	} 
+    }
+
+    ## if you right-click, delete the fiber
+    if { $mousebutton == 3 && $mousestate == 0 } {
+	set index [expr [ llength $global_list(fiber_list) ] -1]
+	if { $index >=0 } {
+	    fiber_remove $index
+	}
+    }
+
+}
+
+#####
+##### XENIOS LOOK BELOW FOR MOUSECALLBACK!
+#####
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Toggles display auto-update
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_toggle_trackexplore { } {
+    
+    if { $global_list(track_explore) } {
+	
+	## make fibers show up -- will be deprecated eventually
+	set global_list(view_fiber) 1
+
+	## get slice numbers and set default last point
+	set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+	set global_list(track_lastpoint) $levels
+
+	## set up mouse callback
+        eval "$parent configure -mousecallback \"$this view_update_crosshair_cb\""
+	
+	set appname "$global_list(appname) $version \[Exploration\]"
+
+	view_update_display 
+	
+    } else {
+	
+	## disable mouse callback
+	eval "$parent configure -mousecallback 0"
+	
+	set appname "$global_list(appname) $version"
+    }
+
+    SetTitle $appname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon an update button press
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_update_display_cb { } { 
+    
+    view_clear_display
+    view_update_display
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in bundle radius
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_fiber_tuberadius_cb { } {
+    
+    foreach item $global_list(vtk_fiber_tube) {
+	$item SetRadius $global_list(view_fiber_tuberadius)
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in point size
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_fiber_pointsize_cb { } {
+    
+    foreach actor $global_list(actor_fiber) {
+	[ $actor GetProperty ] SetPointSize $global_list(view_fiber_pointsize)
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon copy eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_fiber_cmapresetbtn_cb { } {
+    
+    ## current fiber filter
+    $widget_list(view_fiberluk) SetHueRange 0.5 0.0
+    $widget_list(view_fiberluk) Update
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon loading eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_fiber_cmaploadbtn_cb { } {   
+
+    $widget_list(view_fiberluk) Load
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon saving eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_fiber_cmapsavebtn_cb { } {   
+
+    $widget_list(view_fiberluk) SaveAs
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in colormap for fibers
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_fiber_colormap_cb { } {
+    
+    foreach \
+	actor $global_list(actor_fiber) {
+	    
+	    ## create mapper
+	    set fiberMapper [ $actor GetMapper ]
+
+	    if { $global_list(view_fiber_luk) } {
+		$fiberMapper ScalarVisibilityOn
+	    } else {
+		$fiberMapper ScalarVisibilityOff
+	    }
+	}
+    
+      [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in bundle glyph
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_fiber_glyph_cb { } {
+
+    set field(0) fractani
+    set field(1) meandiff
+    set field(2) distance
+    set field(3) angle
+    set field(4) roi
+    set field(5) other
+    set field(6) rgb
+
+    ## get current fiber colormap filter    
+    set filter [ $widget_list(view_fiber_filter) index [ $widget_list(view_fiber_filter) get ]]
+
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_fiber_glyph) \
+			index [ $widget_list(view_fiber_glyph) get ] ]
+    
+    foreach \
+	actor $global_list(actor_fiber) \
+	tube $global_list(vtk_fiber_tube) \
+	polydata $global_list(vtk_fiber_polydata) {
+	    
+	    ## create mapper
+	    set fiberMapper [ $actor GetMapper ]
+	    
+	    if { $cur_glyph == 1 } {
+		
+		$tube SetInput $polydata
+		$tube SetRadius $global_list(view_fiber_tuberadius)
+		$tube SetNumberOfSides 6
+		$tube Update
+		
+		if { [ [ [ $tube GetOutput ] GetPointData ] GetArray $field($filter) ] != "" } {
+		    $fiberMapper ColorByArrayComponent $field($filter) 0
+		}
+
+		$fiberMapper SetInput [ $tube GetOutput ]
+		if { $global_list(view_fiber_luk) } {
+		    $fiberMapper ScalarVisibilityOn
+		} else {
+		    $fiberMapper ScalarVisibilityOff
+		}
+		
+	    } else {
+		
+		if { [ [ $polydata GetPointData ] GetArray $field($filter) ] != "" } {
+		    $fiberMapper ColorByArrayComponent $field($filter) 0
+		}
+
+		$fiberMapper SetInput $polydata
+		if { $global_list(view_fiber_luk) } {
+		    $fiberMapper ScalarVisibilityOn
+		} else {
+		    $fiberMapper ScalarVisibilityOff
+		}
+	    }
+	    
+	    if { $cur_glyph == 2 } {
+		[ $actor GetProperty ] SetRepresentationToPoints
+		[ $actor GetProperty ] SetPointSize $global_list(view_fiber_pointsize)
+	    } else {
+		[ $actor GetProperty ] SetRepresentationToSurface 
+	    }
+
+	}
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in fiber filter selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_fiber_filter_cb { } {
+
+    set field(0) fractani
+    set field(1) meandiff
+    set field(2) distance
+    set field(3) angle
+    set field(4) roi
+    set field(5) other
+    set field(6) rgb
+
+    ## current fiber colormap filter    
+    set filter [ $widget_list(view_fiber_filter) index [ $widget_list(view_fiber_filter) get ]]
+    
+    foreach \
+	actor $global_list(actor_fiber) {
+	    
+	    ## create mapper
+	    set fiberMapper [ $actor GetMapper ]	   	    
+	    $fiberMapper SetScalarModeToUsePointFieldData
+	    
+	    if { [ [ [ $fiberMapper GetInput ] GetPointData ] GetArray $field($filter) ] != "" } {
+		$fiberMapper ColorByArrayComponent $field($filter) 0
+	    }
+
+	}
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off fiber visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::view_toggle_fiber { } {
+    
+    if { $global_list(view_fiber) } {	
+	view_create_fibers	
+    } else { 
+	foreach \
+	    actor $global_list(actor_fiber) \
+	    disp $global_list(fiber_disp_list) {
+		if { $disp == 1 } {
+		    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor
+		}
+		$actor Delete	    
+	    }
+	set global_list(actor_fiber) {}
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in bundle color
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_color_cb { } {
+
+    set new_color [ tk_chooseColor -initialcolor $global_list(fiber_color) ]
+    
+    if { [ llength $new_color ] > 0 } {
+	
+	set global_list(fiber_color) $new_color
+	set fiber_color [ image create photo -width 15 -height 15 ]
+	$fiber_color put $global_list(fiber_color) -to 0 0 15 15	
+	$widget_list(fiber_color) configure -image $fiber_color
+	
+	## get current selection 
+	set sel_item [ $widget_list(fiber_list) getcurselection ]
+	
+	if { $sel_item != "" } {
+	    
+	    set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	    set global_list(fiber_color_list) \
+		[ lreplace $global_list(fiber_color_list) $sel_index $sel_index $new_color ]
+	    
+	    ## convert tk color spec to vtk
+	    set color $new_color
+	    set red "0x[string range $color 1 2]"
+	    set green "0x[string range $color 3 4]"
+	    set blue "0x[string range $color 5 6]"
+	    set red [ expr [ format "%d" $red ] / 255.0 ]
+	    set green [ expr [ format "%d" $green ] / 255.0 ]
+	    set blue [ expr [ format "%d" $blue ] / 255.0 ]
+	    
+	    set fiberActor [ lindex $global_list(actor_fiber) $sel_index ]
+	    [$fiberActor GetProperty] SetColor $red $green $blue
+
+	    [ $parent GetViewer ] UpdateDisplay	    
+	    
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon selection of bundles
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_selection_cb { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	set sel_input [ lindex $global_list(fiber_list) $sel_index ]
+	
+	## get number of components
+	set global_list(fiber_name) $sel_input
+	set global_list(fiber_color) [ lindex $global_list(fiber_color_list) $sel_index ]
+	set global_list(fiber_display) [ lindex $global_list(fiber_disp_list) $sel_index ]
+
+	set fiber_color [ image create photo -width 15 -height 15 ]
+	$fiber_color put $global_list(fiber_color) -to 0 0 15 15	
+	$widget_list(fiber_color) configure -image $fiber_color
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in bundle name
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_name_cb { } {
+
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	set new_name [ $widget_list(fiber_name) get ]
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	set global_list(fiber_list) \
+	    [ lreplace $global_list(fiber_list) $sel_index $sel_index $new_name ]
+	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in bundle display option
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_display_cb { } {
+
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	set global_list(fiber_disp_list) \
+	    [ lreplace $global_list(fiber_disp_list) $sel_index $sel_index \
+		  $global_list(fiber_display) ]
+	
+	set fiberActor [ lindex $global_list(actor_fiber) $sel_index ]
+	
+	if { $global_list(fiber_display) } {
+	    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $fiberActor
+	} else {
+	    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $fiberActor
+	}
+	
+	[ $parent GetViewer ] UpdateDisplay	    
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Add bundle with a given name
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_addwithname { name polydata } {
+
+    ## insert new fiber set
+    set num_fibers [ llength $global_list(fiber_list) ]
+    set next_color [lindex $global_list(tkcolor_list) [expr int(fmod($num_fibers,6))]]
+    
+    set global_list(fiber_color) $next_color
+    set global_list(fiber_display) 1
+
+    set fiber_color [ image create photo -width 15 -height 15 ]
+    $fiber_color put $global_list(fiber_color) -to 0 0 15 15	
+    $widget_list(fiber_color) configure -image $fiber_color
+    
+    set global_list(fiber_name) $name
+    lappend global_list(fiber_list) $global_list(fiber_name)
+    lappend global_list(fiber_disp_list) $global_list(fiber_display)    
+    lappend global_list(fiber_color_list) $global_list(fiber_color)
+    lappend global_list(vtk_fiber_polydata) $polydata	    
+    lappend global_list(vtk_fiber_tube) [ vtkTubeFilter [ pxvtable::vnewobj ] ]
+ 
+    $widget_list(fiber_list) selection clear 0 end
+    $widget_list(fiber_list) selection set $num_fibers $num_fibers
+
+    return $num_fibers
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Add fiber
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_add { polydata } {
+
+    ## insert new fiber
+    set num_fibers [ llength $global_list(fiber_list) ]
+    set name "Bundle_[expr $num_fibers + 1]"
+    
+    set index [ fiber_addwithname $name $polydata ]
+    
+    return $index
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear all fibers
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_clear { } {
+    
+    set num_fibers [ llength $global_list(fiber_list) ]
+    for { set i 0 } { $i < $num_fibers } { incr i } { 
+	fiber_remove 0
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Remove fiber
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_remove { index } {
+
+    if { $global_list(view_fiber) } {
+	set display [ lindex $global_list(fiber_disp_list) $index ]
+	if { $display } {
+	    set actor [ lindex $global_list(actor_fiber) $index ]
+	    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor
+	    $actor Delete
+	}
+    }
+    
+    set global_list(fiber_list) \
+	[ lreplace $global_list(fiber_list) $index $index ]
+    set global_list(fiber_color_list) \
+	[ lreplace $global_list(fiber_color_list) $index $index ]
+    set global_list(fiber_disp_list) \
+	[ lreplace $global_list(fiber_disp_list) $index $index ]
+    
+    set polydata [ lindex $global_list(vtk_fiber_polydata) $index ]
+    $polydata Delete
+    
+    set tube [ lindex $global_list(vtk_fiber_tube) $index ]
+    $tube Delete
+
+    set global_list(actor_fiber) \
+	[ lreplace $global_list(actor_fiber) $index $index ]
+    set global_list(vtk_fiber_tube) \
+	[ lreplace $global_list(vtk_fiber_tube) $index $index ]
+    set global_list(vtk_fiber_polydata) \
+	[ lreplace $global_list(vtk_fiber_polydata) $index $index ]
+    
+    set num_fibers [ llength $global_list(fiber_list) ]
+    
+    if { $num_fibers > 0 } {
+	
+	$widget_list(fiber_list) selection clear 0 end
+	
+	if { $index < $num_fibers } {
+	    $widget_list(fiber_list) selection set $index $index
+	} else {
+	    $widget_list(fiber_list) selection set \
+		[expr $num_fibers -1] [expr $num_fibers -1]
+	}
+	
+	fiber_selection_cb
+	
+    } else {
+	
+	set global_list(fiber_fname) ""
+	set global_list(fiber_display) 1
+	set global_list(fiber_name) ""
+	set global_list(fiber_color) [ lindex $global_list(tkcolor_list) 0 ]
+	set fiber_color [ image create photo -width 15 -height 15 ]
+	$fiber_color put $global_list(fiber_color) -to 0 0 15 15	
+	$widget_list(fiber_color) configure -image $fiber_color
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Remove selected bundle
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_removeselected { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	fiber_remove $sel_index
+	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: load fiber
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_load { } {
+    
+    set fname  [tk_getOpenFile -title "Select fiber file" -filetypes { {"Fibers" {.fib}}} -initialdir $global_list(result_fdir) -parent $basewidget ] 
+
+    ## browse for filename
+    if { $fname != "" } { 
+	
+	## open fiber file
+	set fibr [ vtkXMLPolyDataReader [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $fibr "Reading fiber..."
+	$fibr SetFileName $fname
+	$fibr Update
+	
+	set polydata [ vtkPolyData [ pxvtable::vnewobj ] ]
+	$polydata ShallowCopy [ $fibr GetOutput ]
+	
+	$fibr Delete
+	
+	fiber_addwithname [ file root [ file tail $fname ] ] $polydata
+	
+	## keep fname
+	set global_list(fiber_fname) $fname
+	
+	if { $global_list(view_fiber) } {	
+	    view_create_fibers	
+	} 
+    }	
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: save individual fiber 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_save { index name } {
+    
+    set polydata [ lindex $global_list(vtk_fiber_polydata) $index ]
+    
+    set fibw [ vtkXMLPolyDataWriter [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $fibw "Saving fiber..."
+
+    $fibw SetFileName $name
+    $fibw SetInput $polydata
+    $fibw Write	
+    
+    $fibw Delete    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: save selected fiber
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_saveselected { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## browse for directory
+	set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+	
+	## browse for directory
+	if { $fdir != "" } {
+	    	    
+	    ## get current index
+	    set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	    
+	    set item [ lindex $global_list(fiber_list) $sel_index ]	
+	    
+	    fiber_save $sel_index [ file join $fdir "$item.fib" ]	
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: save all fibers
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_saveall { } {
+    
+    ## browse for directory    
+    set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+
+    ## browse for directory
+    if { $fdir != "" } { 
+	
+	## get number of fiber bundles
+	set num [ llength $global_list(fiber_list) ]
+	
+	## save all fibers
+	for { set i 0 } { $i < $num } { incr i } {	
+	    set item [ lindex $global_list(fiber_list) $i ]	
+	    fiber_save $i [ file join $fdir "$item.fib" ]	
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_savestatistics { } {
+
+    set statfname $global_list(result_fpreffix)
+    set initfname "${statfname}stat"
+    set initfname [ file join $global_list(result_fdir) $initfname ]
+
+    ## browse for filename
+    set fname  [tk_getSaveFile -title "Save statistics"\
+		    -filetypes {{"Text" {.txt*}}} \
+		    -parent $basewidget \
+		    -defaultextension ".txt" \
+		    -initialfile $initfname ]  
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+    
+    $widget_list(stat_text) export $fname
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: compute fiber statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_beginstatistics { title overwrite } {   
+    
+    if { $overwrite } {
+	$widget_list(stat_text) delete 1.0 end
+    }    
+
+    $widget_list(stat_text) insert \
+	end "-----------------------+------------+------------+------------+------------+------------\n" even
+    $widget_list(stat_text) insert \
+	end "$title      MIN          MAX         MEAN        VARIANCE      STD DEV\n" odd
+    $widget_list(stat_text) insert \
+	end "-----------------------+------------+------------+------------+------------+------------\n" even
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: compute fiber statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_addstatistics { title results tag } {   
+    
+    set min  [ format %8.4f [ lindex $results 0 ] ]
+    set max  [ format %8.4f [ lindex $results 1 ] ]
+    set mean [ format %8.4f [ lindex $results 2 ] ]
+    set var  [ format %8.4f [ lindex $results 3 ] ]
+    set dev  [ format %8.4f [ lindex $results 4 ] ]
+    
+    $widget_list(stat_text) insert end " $title |  $min  |  $max  |  $mean  |  $var  |  $dev  \n" $tag
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: compute fiber statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_statistics { } {
+
+    set FIBERS 3
+
+    set fiber_image [ lindex $global_list(result_list) $FIBERS ] 
+
+#    $widget_list(notebook) view "Statistics"
+    
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	## name
+	set item [ lindex $global_list(fiber_list) $sel_index ]	
+	
+	# compute fiber statistics
+	set fstat [ vtkmpjTensorStreamlineStatistics [ pxvtable::vnewobj ] ]
+	$fstat SetInput [ lindex $global_list(vtk_fiber_polydata) $sel_index ]
+	$fstat Update
+	
+	set vol "n/a"
+	set volmm "n/a"
+
+	if { [ $fiber_image GetImageSize ] > 1 } {
+	    
+	    ## quantize fibers
+	    set quant [ vtkmpjStreamlineQuantization [ pxvtable::vnewobj ] ]
+	    $quant SetInput [ lindex $global_list(vtk_fiber_polydata) $sel_index ]
+	    $quant SetImage [ $fiber_image GetImage ]
+	    $quant SetMaskValue 1.0
+	    $quant Update
+	    
+	    $fiber_image ShallowCopyImage [ $quant GetOutput ]
+
+	    ## get volume 
+	    set vol [ $quant GetNumberOfVoxels ]
+
+	    ## get spacing information
+	    scan [ [ $fiber_image GetImage ] GetSpacing ] "%f %f %f" spc0 spc1 spc2
+
+	    ## calculate volume in mm
+	    set volmm [ expr $vol * $spc0 * $spc1 * $spc2 ]
+	    set volmm [ format %6.2f $volmm ]
+
+	    $quant Delete
+	}
+	
+	## Write out stats
+	set textlist [  $widget_list(stat_text) component text ]
+	$textlist tag configure even -background "\#e0e0ff"
+	
+	set strlen [ string length $item ]
+	if { $strlen > 23 } {
+	    set item [ string range $item 0 22 ]
+	} else {
+	    set spc [ string repeat " " [ expr (23 - $strlen) / 2 ] ] 
+	    set item [ string range "$spc$item$spc" 0 22 ]
+	}
+
+	fiber_beginstatistics $item $global_list(stat_overwrite)
+
+	set fa [ $fstat GetAnisotropy ]
+	set tmpfa [ lindex $fa 3 ]
+	if { $tmpfa >= 0 } {
+	    set tmpfa [ expr sqrt($tmpfa) ]
+	} else {
+	    set tmpfa "sqrt($tmpfa)!"
+	}
+	lappend fa $tmpfa
+	fiber_addstatistics "FRACTIONAL ANISOTROPY" $fa odd
+
+	set md [ $fstat GetDiffusivity ]
+	set tmpmd [ lindex $md 3 ]
+	if { $tmpmd >= 0 } {
+	    set tmpmd [ expr sqrt($tmpmd) ]
+	} else {
+	    set tmpmd "sqrt($tmpmd)!"
+	}
+	lappend md $tmpmd
+	fiber_addstatistics "MEAN DIFFUSIVITY     " $md even	
+	
+	set dist [ $fstat GetDistance ]
+	set tmpdist [ lindex $dist 3 ]
+	if { $tmpdist >= 0 } {
+	    set tmpdist [ expr sqrt($tmpdist) ]
+	} else {
+	    set tmpdist "sqrt($tmpdist)!"
+	}
+	lappend dist $tmpdist
+	fiber_addstatistics "MEAN FIBER LENGTH    " $dist odd
+	
+	set angle [ $fstat GetAngle ]
+	set tmpangle [ lindex $angle 3 ]
+	if { $tmpangle >= 0 } {
+	    set tmpangle [ expr sqrt($tmpangle) ]
+	} else {
+	    set tmpangle "sqrt($tmpangle)!"
+	}
+	lappend angle $tmpangle
+	fiber_addstatistics "MEAN FIBER ANGLE     " $angle even	
+	
+	set other [ $fstat GetOther ]
+	set tmpother [ lindex $other 3 ]
+	if { $tmpother >= 0 } {
+	    set tmpother [ expr sqrt($tmpother) ]
+	} else {
+	    set tmpother "sqrt($tmpother)!"
+	}
+	lappend other $tmpother
+	fiber_addstatistics "MEAN INPUT MAP       " $other odd
+
+	$widget_list(stat_text) insert \
+	    end "-----------------------+------------+------------+------------+------------+------------\n" even
+
+	set num [ $fstat GetNumberOfFibers ]
+
+	$widget_list(stat_text) insert end " Fiber Count = $num, Volume = $vol ($volmm mm^3)\n" odd
+
+	$fstat Delete
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: quantize fibers
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_quantize { } {
+
+    set FIBERS 3
+
+    set fiber_image [ lindex $global_list(result_list) $FIBERS ] 
+
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	## name
+	set item [ lindex $global_list(fiber_list) $sel_index ]	
+
+	## quantize fibers
+	set quant [ vtkmpjStreamlineQuantization [ pxvtable::vnewobj ] ]
+	$quant SetInput [ lindex $global_list(vtk_fiber_polydata) $sel_index ]
+	$quant SetImage [ $fiber_image GetImage ]
+	$quant SetMaskValue 1.0
+	$quant Update
+
+	$fiber_image ShallowCopyImage [ $quant GetOutput ]
+
+	$quant Delete
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: fiber explore
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_explore { cx cy cz } {
+    
+    set TENSOR 0
+    set MASK 1
+    set MAP 2
+    set FIBERS 3
+    
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set map [ lindex $global_list(result_list) $MAP ]
+    set fibers [ lindex $global_list(result_list) $FIBERS ] 
+
+    if { [ $tensor GetImageSize ] == 1 } {
+	
+	tk_messageBox -type ok \
+	    -parent $basewidget -title "Tensor" \
+	    -message "You need a tensor image to start tracking!" -icon info
+
+	return
+    }
+     
+    if { [ $map GetImageSize ] == 1 } {
+	
+	## create dummy map
+	$map CopyImageHeader [ $fibers GetImageHeader ]
+	$map ShallowCopyImage [ $fibers GetImage ]
+    }
+
+    ## if tracking, one wants to see the fibers
+    set global_list(view_fiber) 1
+
+    WatchOn
+
+    ## get origin and spacing information
+    scan [ [ $tensor GetImage ] GetSpacing ] "%f %f %f" spc0 spc1 spc2
+    scan [ [ $tensor GetImage ] GetOrigin ] "%f %f %f" org0 org1 org2
+
+    ## initialize streamer
+    set streamer [ vtkmpjTensorStreamline [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $streamer "Fiber tracking..."
+    $streamer SetInput [ $map GetImage ]
+    $streamer SetTensor [ $tensor GetImage ]
+    
+    if { [ $mask GetImageSize ] > 1 } {
+	$streamer SetMask [ $mask GetImage ]
+    }
+    
+    ## honor only volume or single point seeds
+    if { $global_list(track_seedtype) == 2 } {
+	
+	## volume	
+	set ox [expr $cx * $spc0 + $org0 ]
+	set oy [expr $cy * $spc1 + $org1 ]
+	set oz [expr $cz * $spc2 + $org2 ]
+	
+	set width $global_list(track_seedwidth)
+	set height $global_list(track_seedheight)
+	set depth $global_list(track_seeddepth)
+	set dens $global_list(track_seeddens)
+	
+	#	set numx [ expr int(1.0 / $res) * $width ]
+	#	set numy [ expr int(1.0 / $res) * $height ]
+	#	set numz [ expr int(1.0 / $res) * $depth ]
+	
+	set source [ vtkmpjImagePointSource [ pxvtable::vnewobj ] ]
+	$source SetCenter $ox $oy $oz
+	$source SetSize $width $height $depth
+	$source SetOrigin $org0 $org1 $org2
+	$source SetSpacing $spc0 $spc1 $spc2
+	$source SetDensity $dens
+	$source Update
+
+	## assign source points
+	$streamer SetSource [ $source GetOutput ]
+
+	$source Delete
+
+    } else {
+	
+	## single input point
+	set ox [expr $cx * $spc0 + $org0 ]
+	set oy [expr $cy * $spc1 + $org1 ]
+	set oz [expr $cz * $spc2 + $org2 ]
+	
+	set source [ vtkPolyData [ pxvtable::vnewobj ] ] 
+	set points [ vtkPoints [ pxvtable::vnewobj ] ]
+	
+	$points InsertNextPoint $ox $oy $oz 
+	$source SetPoints $points
+	
+	$points Delete
+	
+	## assign source point
+	$streamer SetSource $source
+
+	$source Delete
+
+    }
+    
+#    puts "num seed points: [ [ [ $streamer GetSource ] GetPoints ] GetNumberOfPoints ]"
+    
+    ## integrate fibers
+    if { $global_list(track_flipping) } {
+	$streamer SetFlipX $global_list(track_flipx)
+	$streamer SetFlipY $global_list(track_flipy)
+	$streamer SetFlipZ $global_list(track_flipz)
+    }
+
+    ## specify eigenvector
+    if { $global_list(track_eigenvector) == 0 } { 
+	$streamer IntegrateMajorEigenvector
+    } elseif { $global_list(track_eigenvector) == 1 } {
+	$streamer IntegrateMediumEigenvector
+    } else {
+	$streamer IntegrateMinorEigenvector
+    }
+
+    $streamer SetIntegrationDirectionToIntegrateBothDirections
+    $streamer SetMaximumDistance $global_list(track_maxdist)
+    $streamer SetMinimumDistance $global_list(track_mindist)
+    $streamer SetIntegrationOrder $global_list(track_integration)
+    $streamer SetMaximumAngle $global_list(track_maxangle)
+    $streamer SetMinimumFA $global_list(track_minFA);
+    $streamer SetMaximumFA $global_list(track_maxFA);
+    $streamer SetMinimumMD $global_list(track_minMD);
+    $streamer SetMaximumMD $global_list(track_maxMD);
+    $streamer SetIntegrationStepLength $global_list(track_steplen)
+
+    $streamer SetDirectionalColormap $global_list(track_dec)
+    $streamer SetDirectionalColorScheme $global_list(view_direction_scheme)
+    $streamer SetDirectionalColorSaturation $global_list(view_direction_saturation)
+    $streamer SetDirectionalColorScaling $global_list(view_direction_scaling)
+    $streamer SetDirectionalColorModulate $global_list(view_direction_modulate)
+    $streamer SetDirectionalColorAlphaBlending $global_list(view_direction_alpha)
+    
+    $streamer Update
+    
+    ## create new fiber set
+    set new_fiber [ vtkPolyData [ pxvtable::vnewobj ] ]
+
+    ## filter fibers
+    if { $global_list(track_regionfilter) } {	
+	
+	set strfilter [ vtkmpjTensorStreamlineRegionFilter [ pxvtable::vnewobj ] ]
+	
+	$strfilter SetInput [ $streamer GetOutput ]
+	$strfilter SetRegionNumber1 $global_list(track_seedregion)
+	$strfilter SetRegionNumber2 $global_list(track_regionnumber)
+	$strfilter SetClipping $global_list(track_clipping)
+	$strfilter Update
+	
+	$new_fiber ShallowCopy [ $strfilter GetOutput ]
+
+	$strfilter Delete	
+
+    } else {
+
+	$new_fiber ShallowCopy [ $streamer GetOutput ]
+
+    }
+
+    $streamer Delete
+    
+    ## add new fiber bundle
+    set index [ fiber_add $new_fiber ]
+    
+    set actor [ view_create_fiber_glyph $index ]
+    lappend global_list(actor_fiber) $actor
+	
+    ## add actor if to be displayed
+    if { [ lindex $global_list(fiber_disp_list) $index ] == 1 } { 
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+    }
+
+    WatchOff
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: fiber track
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::fiber_track { } {
+
+    set TENSOR 0
+    set MASK 1
+    set MAP 2
+    set FIBERS 3
+    
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set map [ lindex $global_list(result_list) $MAP ]
+    set fibers [ lindex $global_list(result_list) $FIBERS ] 
+
+    if { [ $tensor GetImageSize ] == 1 } {
+	
+	tk_messageBox -type ok \
+	    -parent $basewidget -title "Tensor" \
+	    -message "You need a tensor image to start tracking!" -icon info
+
+	return
+    }
+     
+    if { [ $map GetImageSize ] == 1 } {
+	
+	## create dummy map
+	$map CopyImageHeader [ $fibers GetImageHeader ]
+	$map ShallowCopyImage [ $fibers GetImage ]
+    }
+
+    ## if tracking, one wants to see the fibers
+    set global_list(view_fiber) 1
+
+    WatchOn
+
+    ## get slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set cx [ lindex $levels 0 ]
+    set cy [ lindex $levels 1 ]
+    set cz [ lindex $levels 2 ]
+
+    ## get origin and spacing information
+    scan [ [ $tensor GetImage ] GetSpacing ] "%f %f %f" spc0 spc1 spc2
+    scan [ [ $tensor GetImage ] GetOrigin ] "%f %f %f" org0 org1 org2
+
+    ## initialize streamer
+    set streamer [ vtkmpjTensorStreamline [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $streamer "Fiber tracking..."
+    $streamer SetInput [ $map GetImage ]
+    $streamer SetTensor [ $tensor GetImage ]
+    
+    if { [ $mask GetImageSize ] > 1 } {
+	$streamer SetMask [ $mask GetImage ]
+    }
+    
+    if { $global_list(track_seedtype) == 0 } {
+
+	## single input point
+	set ox [expr $cx * $spc0 + $org0 ]
+	set oy [expr $cy * $spc1 + $org1 ]
+	set oz [expr $cz * $spc2 + $org2 ]
+	
+	set source [ vtkPolyData [ pxvtable::vnewobj ] ] 
+	set points [ vtkPoints [ pxvtable::vnewobj ] ]
+	
+	$points InsertNextPoint $ox $oy $oz 
+	$source SetPoints $points
+	
+	$points Delete
+	
+	## assign source point
+	$streamer SetSource $source
+
+	$source Delete
+
+    } elseif { $global_list(track_seedtype) == 1 } {
+	
+	## region 
+	set region $global_list(track_seedregion)
+	
+	set imthr [ vtkImageThreshold [ pxvtable::vnewobj ] ]
+	$imthr SetInput [ $mask GetImage ]
+	$imthr ThresholdBetween $region $region
+	$imthr SetInValue 1.0
+	$imthr SetOutValue 0.0
+	$imthr SetOutputScalarTypeToUnsignedChar
+	$imthr Update
+	
+ 	set dens $global_list(track_seeddens)
+
+	set source [ vtkmpjImagePointSource [ pxvtable::vnewobj ] ]
+	$source SetMask [ $imthr GetOutput ]
+	$source SetOrigin $org0 $org1 $org2
+	$source SetSpacing $spc0 $spc1 $spc2
+	$source SetDensity $dens
+	$source Update
+	
+ 	## assign source points
+	$streamer SetSource [ $source GetOutput ]
+	$source Delete
+	
+	#	set impts [ vtkThresholdPoints [ pxvtable::vnewobj ] ]
+	#	$impts SetInput [ $imthr GetOutput ]
+	#	$impts ThresholdByUpper 1.0
+	#	$impts Update    
+	
+	$imthr Delete
+	
+	## assign region source points
+#	$streamer SetSource [ $impts GetOutput ]
+#	$impts Delete
+	
+    } elseif { $global_list(track_seedtype) == 2 } {
+	
+	## volume	
+	set ox [expr $cx * $spc0 + $org0 ]
+	set oy [expr $cy * $spc1 + $org1 ]
+	set oz [expr $cz * $spc2 + $org2 ]
+	
+	set width $global_list(track_seedwidth)
+	set height $global_list(track_seedheight)
+	set depth $global_list(track_seeddepth)
+	set dens $global_list(track_seeddens)
+	
+	#	set numx [ expr int(1.0 / $res) * $width ]
+	#	set numy [ expr int(1.0 / $res) * $height ]
+	#	set numz [ expr int(1.0 / $res) * $depth ]
+	
+	set source [ vtkmpjImagePointSource [ pxvtable::vnewobj ] ]
+	$source SetCenter $ox $oy $oz
+	$source SetSize $width $height $depth
+	$source SetOrigin $org0 $org1 $org2
+	$source SetSpacing $spc0 $spc1 $spc2
+	$source SetDensity $dens
+	$source Update
+
+	## assign source points
+	$streamer SetSource [ $source GetOutput ]
+
+	$source Delete
+
+    } elseif { $global_list(track_seedtype) == 3 } {
+	
+	## landmark control
+	set landmarkcontrol [ [ $parent GetLandmarkControl ] GetLandmarkControl ]
+	
+	set lmarks [ $landmarkcontrol GetCollection -1 ]	
+	$lmarks Compact
+	set numlmarks [ $lmarks GetNumPoints ]
+	
+	if { $numlmarks > 0 } {
+	    
+	    set pts [ vtkPolyData [ pxvtable::vnewobj ] ]
+	    $pts SetPoints [ $lmarks GetPoints ]
+	    
+	    $streamer SetSource $pts
+	    
+	    $pts Delete
+	}
+    }
+    
+#    puts "num seed points: [ [ [ $streamer GetSource ] GetPoints ] GetNumberOfPoints ]"
+    
+    ## integrate fibers
+    if { $global_list(track_flipping) } {
+	$streamer SetFlipX $global_list(track_flipx)
+	$streamer SetFlipY $global_list(track_flipy)
+	$streamer SetFlipZ $global_list(track_flipz)
+    }
+
+    ## specify eigenvector
+    if { $global_list(track_eigenvector) == 0 } { 
+	$streamer IntegrateMajorEigenvector
+    } elseif { $global_list(track_eigenvector) == 1 } {
+	$streamer IntegrateMediumEigenvector
+    } else {
+	$streamer IntegrateMinorEigenvector
+    }
+
+    $streamer SetIntegrationDirectionToIntegrateBothDirections
+    $streamer SetMaximumDistance $global_list(track_maxdist)
+    $streamer SetMinimumDistance $global_list(track_mindist)
+    $streamer SetIntegrationOrder $global_list(track_integration)
+    $streamer SetMaximumAngle $global_list(track_maxangle)
+    $streamer SetMinimumFA $global_list(track_minFA);
+    $streamer SetMaximumFA $global_list(track_maxFA);
+    $streamer SetMinimumMD $global_list(track_minMD);
+    $streamer SetMaximumMD $global_list(track_maxMD);
+    $streamer SetIntegrationStepLength $global_list(track_steplen)
+
+    $streamer SetDirectionalColormap $global_list(track_dec)
+    $streamer SetDirectionalColorScheme $global_list(view_direction_scheme)
+    $streamer SetDirectionalColorSaturation $global_list(view_direction_saturation)
+    $streamer SetDirectionalColorScaling $global_list(view_direction_scaling)
+    $streamer SetDirectionalColorModulate $global_list(view_direction_modulate)
+    $streamer SetDirectionalColorAlphaBlending $global_list(view_direction_alpha)
+    
+    $streamer Update
+    
+    ## create new fiber set
+    set new_fiber [ vtkPolyData [ pxvtable::vnewobj ] ]
+
+    ## filter fibers
+    if { $global_list(track_regionfilter) } {	
+	
+	set strfilter [ vtkmpjTensorStreamlineRegionFilter [ pxvtable::vnewobj ] ]
+	
+	$strfilter SetInput [ $streamer GetOutput ]
+	$strfilter SetRegionNumber1 $global_list(track_seedregion)
+	$strfilter SetRegionNumber2 $global_list(track_regionnumber)
+	$strfilter SetClipping $global_list(track_clipping)
+	$strfilter Update
+	
+	$new_fiber ShallowCopy [ $strfilter GetOutput ]
+
+	$strfilter Delete	
+
+    } else {
+
+	$new_fiber ShallowCopy [ $streamer GetOutput ]
+
+    }
+
+    $streamer Delete
+    
+    set index [ fiber_add $new_fiber ]
+    
+#    puts "points: [[$new_fiber GetPoints] GetNumberOfPoints]"
+
+    ## display new bundle
+    if { $global_list(view_fiber) } {	
+	
+	set actor [ view_create_fiber_glyph $index ]
+	lappend global_list(actor_fiber) $actor
+	
+	## add actor if to be displayed
+	if { [ lindex $global_list(fiber_disp_list) $index ] == 1 } { 
+	    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+	}
+
+	[ $parent GetViewer ] UpdateDisplay
+    }
+
+    ## compute statistics
+    if { $global_list(track_autostat) } {
+	fiber_statistics
+    }
+
+    
+    WatchOff
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create results control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::CreateInputControl { base } {   
+
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Tensor image"
+    pack $base.frame1 -fill both -expand f -pady 5
+    
+    set frame1 [ $base.frame1 childsite ]
+    
+    set subframe0 [ frame $frame1.subframe0 ]
+    pack $subframe0 -side top -fill both -expand f -pady 0
+    
+    set tensor_fname [ iwidgets::entryfield $subframe0.tensor_fname \
+			   -textvariable [ itcl::scope global_list(tensor_fname) ] \
+			   -labeltext "Filename:" ] 
+    pack $tensor_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(tensor_fname) $tensor_fname
+    
+    set tensor_load [ iwidgets::buttonbox $subframe0.tensor_load -orient horizontal -padx 2 ]
+    $tensor_load add load -text "Load..." -command [ itcl::code $this loadtensor ] 
+    $tensor_load add disp -text "Display" -command [ itcl::code $this DisplayResult 0 ]
+    pack $tensor_load -side left
+    set widget_list(tensor_load) $tensor_load
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Region of interest mask"
+    pack $base.frame0 -fill both -expand f -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+  
+    iwidgets::labeledframe $base.frame2 \
+	-labelpos nw  \
+	-labeltext "Map for analysis"
+    pack $base.frame2 -fill both -expand f -pady 5
+    
+    set frame2 [ $base.frame2 childsite ]
+    
+    set subframe0 [ frame $frame2.subframe0 ]
+    pack $subframe0 -side top -fill x -expand f -pady 0
+    
+    set map_fname [ iwidgets::entryfield $subframe0.map_fname \
+			-textvariable [ itcl::scope global_list(map_fname) ] \
+			-labeltext "Filename:" ] 
+    pack $map_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(map_fname) $map_fname
+    
+    set map_load [ iwidgets::buttonbox $subframe0.map_load -orient horizontal -padx 2 ]
+    $map_load add load -text "Load..." -command [ itcl::code $this loadmap ] 
+    $map_load add disp -text "Display" -command [ itcl::code $this DisplayResult 2 ]
+    pack $map_load -side left 
+    set widget_list(map_load) $map_load
+
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+    
+    set mask_fname [ iwidgets::entryfield $subframe1.mask_fname \
+			 -textvariable [ itcl::scope global_list(mask_fname) ] \
+			 -labeltext "Filename:" ] 
+    pack $mask_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(mask_fname) $mask_fname
+    
+    set mask_load [ iwidgets::buttonbox $subframe1.mask_load -orient horizontal -padx 2 ]
+    $mask_load add load -text "Load..." -command [ itcl::code $this loadmask ]    
+    $mask_load add disp -text "Display" -command [ itcl::code $this DisplayResult 1 ]
+    pack $mask_load -side left 
+    set widget_list(mask_load) $mask_load
+    
+    set mask_nreg [ iwidgets::spinint $subframe1.mask_nreg \
+			-labeltext "Number of regions in mask:" \
+			-fixed 4 -width 4 -range {1 1000} -step 1 \
+			-textvariable [ itcl::scope global_list(mask_nreg) ] ]
+    pack $mask_nreg -side right -pady 5 -padx 5
+    set widget_list(mask_nreg) $mask_nreg
+
+  
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create results control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::CreateResultsControl { base } {   
+
+    set color(0) \#dcdcdc
+    set color(1) black
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Results"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+    
+    iwidgets::scrolledlistbox $subframe0.resultlist \
+	-hscrollmode dynamic \
+	-selectmode extended \
+	-dblclickcommand [ itcl::code $this toggleresult ] \
+	-visibleitems 40x10 
+    
+    pack $subframe0.resultlist -side left -fill both -expand t -padx 2 -pady 2
+    set widget_list(result_list) $subframe0.resultlist
+    
+    foreach item $global_list(result_title) {
+	set enable [ lindex $item 2 ]
+     	$widget_list(result_list) insert end "[lindex $item 0]" 
+	$widget_list(result_list) itemconfigure end -foreground $color($enable)
+    }
+
+    set subframe1 [ frame $subframe0.subframe1 ]
+    pack $subframe1 -side right -fill both -padx 0
+    
+    set resultbbox [ iwidgets::buttonbox $subframe1.input -orient vertical ]
+    $resultbbox add display -text "Display" -command [ itcl::code $this displayresult ]
+    $resultbbox add save -text "Save..." -command [ itcl::code $this saveresult ]
+    $resultbbox add saveall -text "Save all" -command [ itcl::code $this saveallresults ]    
+    $resultbbox add mark -text "On/Off" -command [ itcl::code $this toggleresult ]
+    pack $resultbbox -side top -fill x -expand t -padx 0
+    set widget_list(result_buttonbox) $resultbbox
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill x -padx 2 -pady 5
+
+    set result_fpreffix [ iwidgets::entryfield $subframe2.result_fpreffix \
+			      -textvariable [ itcl::scope global_list(result_fpreffix) ] \
+			      -labeltext "Preffix:" ]
+    pack $result_fpreffix -side left -fill x -expand t -padx 5 -pady 2
+    set widget_list(result_fpreffix) $result_fpreffix    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create directionality encoding display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::CreateDirectionControl { base } {
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Directionally encoded colormaps"
+    pack $base.frame0 -fill both -expand f
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill x -expand f -padx 5 -pady 5
+
+    ## color encoding
+    set track_dec [ checkbutton $subframe0.track_dec \
+			-text "Enable fiber direction colormaps" \
+			-variable [ itcl::scope global_list(track_dec) ] ]
+    pack $track_dec -side left -padx 5 -pady 5      
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -expand f -padx 5      
+    
+    set view_direction_modulate [ checkbutton $subframe1.view_direction_modulate \
+				      -text "Modulate intensity by fractional anisotropy" \
+				      -variable [ itcl::scope global_list(view_direction_modulate) ] ]
+    pack $view_direction_modulate -side left -padx 5 -pady 5
+
+    set view_direction_alpha [ checkbutton $subframe1.view_direction_alpha \
+				   -text "Enable transparency" \
+				   -variable [ itcl::scope global_list(view_direction_alpha) ] ]
+    pack $view_direction_alpha -side right -padx 5 -pady 5
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -fill x -expand f -padx 5 -pady 5
+  
+    set view_direction_scheme [ iwidgets::optionmenu $subframe2.view_direction_scheme \
+				    -labeltext "Color scheme:" \
+				    -command [ itcl::code $this view_directionscheme_cb ] ]
+    set widget_list(view_direction_scheme) $view_direction_scheme
+    
+    $view_direction_scheme insert 0 "Absolute value"
+    $view_direction_scheme insert 1 "Rotational symmetry"
+    $view_direction_scheme insert 2 "No symmetry"
+    $view_direction_scheme insert 3 "Mirror symmetry"
+
+    pack $view_direction_scheme -side left -padx 5
+    
+    $view_direction_scheme select 0    
+
+    set subframe4 [ frame $frame0.subframe4 ]
+    pack $subframe4 -fill x -expand f -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe4.view_direction_satscale \
+	-width 5 \
+	-validate real \
+	-labeltext "Saturation factor:" \
+	-textvariable [ itcl::scope global_list(view_direction_saturation) ]
+    pack $subframe4.view_direction_satscale -side left -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe4.view_direction_scaling \
+	-width 5 \
+	-validate real \
+	-labeltext "Brightness:" \
+	-textvariable [ itcl::scope global_list(view_direction_scaling) ]
+    pack $subframe4.view_direction_scaling -side left -padx 5 -pady 5
+
+  
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create fiber tracking control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::CreateTrackingControl { base } {
+
+    label $base.dummy -bg black -fg white -text "In Exploration mode, use Shift-LeftBtn to track; RightBtn to remove bundle"
+    pack $base.dummy -side top -fill x -expand t
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Seed points"
+    pack $base.frame0 -fill both -expand f 
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand f
+    
+    set track_seedtype [ iwidgets::optionmenu $subframe0.track_seedtype \
+			     -command [ itcl::code $this track_seedtype_cb ] \
+			     -labeltext "Seed from:" ]
+    pack $track_seedtype -side left -padx 5 -pady 5
+    $track_seedtype insert end "Single point"
+    $track_seedtype insert end "Region"
+    $track_seedtype insert end "Volume"
+    $track_seedtype insert end "Landmark control"
+    set widget_list(track_seedtype) $track_seedtype
+
+    set track_seedregion [ iwidgets::spinint $subframe0.track_seedregion \
+			       -labeltext "Region number:" \
+			       -fixed 4 -width 4 -range {1 1000} -step 1 \
+			       -textvariable \
+			       [ itcl::scope global_list(track_seedregion) ] ]
+    pack $track_seedregion -side left -pady 5 -padx 2
+    set widget_list(track_seedregion) $track_seedregion  
+    $widget_list(track_seedregion) configure -state disabled
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -expand f
+    
+    set track_seedwidth [ iwidgets::entryfield $subframe1.track_seedwidth \
+			      -labeltext "Width:" \
+			      -validate integer \
+			      -width 4 \
+			      -state disabled \
+			      -textvariable [ itcl::scope global_list(track_seedwidth) ] ]
+    pack $subframe1.track_seedwidth -side left -padx 5 -pady 5 
+    set widget_list(track_seedwidth) $track_seedwidth
+    
+    set track_seedheight [ iwidgets::entryfield $subframe1.track_seedheight \
+			       -labeltext "Height:" \
+			       -validate integer \
+			       -width 4 \
+			       -state disabled \
+			       -textvariable [ itcl::scope global_list(track_seedheight) ] ]
+    pack $subframe1.track_seedheight -side left -padx 5 -pady 5
+    set widget_list(track_seedheight) $track_seedheight
+    
+    set track_seeddepth [ iwidgets::entryfield $subframe1.track_seeddepth \
+			      -labeltext "Depth:" \
+			      -validate integer \
+			      -width 4 \
+			      -state disabled \
+			      -textvariable [ itcl::scope global_list(track_seeddepth) ] ]
+    pack $subframe1.track_seeddepth -side left -padx 5 -pady 5 
+    set widget_list(track_seeddepth) $track_seeddepth
+    
+    set track_seeddens [ iwidgets::entryfield $subframe1.track_seeddens \
+			    -labeltext "Density:" \
+			    -validate real \
+			    -width 6 \
+			    -state disabled \
+			    -textvariable [ itcl::scope global_list(track_seeddens) ] ]
+    pack $subframe1.track_seeddens -side left -padx 5 -pady 5
+    set widget_list(track_seeddens) $track_seeddens
+
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Integration parameters"
+    pack $base.frame1 -fill both -expand f
+    
+    set frame1 [ $base.frame1 childsite ]
+    
+    set subframe2 [ frame $frame1.subframe2 ]
+    pack $subframe2 -fill both -expand f
+    
+    set integration [ iwidgets::optionmenu $subframe2.integration \
+			  -command [ itcl::code $this track_integration_cb ] \
+			  -labeltext "Type:" ]	
+    pack $integration -side left -padx 2 -pady 5
+    $integration insert end "Runge-Kutta 2"
+    $integration insert end "Runge-Kutta 4"
+    set widget_list(track_integration) $integration
+    $widget_list(track_integration) select $global_list(track_integration)
+    
+    iwidgets::entryfield $subframe2.track_steplen \
+	-width 5 \
+	-validate real \
+	-labeltext "Step length:" \
+	-textvariable [ itcl::scope global_list(track_steplen) ] 
+    pack $subframe2.track_steplen -side left -padx 2 -pady 5  
+    
+    set eigenvector [ iwidgets::optionmenu $subframe2.eigenvector \
+			  -command [ itcl::code $this track_eigenvector_cb ] \
+			  -labeltext "Eigenvector:" ]	
+    pack $eigenvector -side left -padx 2 -pady 5
+    $eigenvector insert end "Primary"
+    $eigenvector insert end "Secondary"
+    $eigenvector insert end "Tertiary"
+    set widget_list(track_eigenvector) $eigenvector
+
+    set subframe3 [ frame $frame1.subframe3 ]
+    pack $subframe3 -fill both -expand f
+    
+    label $subframe3.dummy -text "Transformation:"
+    pack $subframe3.dummy -side left -expand f
+
+    checkbutton $subframe3.flipx -text "Flip X" -variable [ itcl::scope global_list(track_flipx) ]
+    pack $subframe3.flipx -pady 5 -side left
+    checkbutton $subframe3.flipy -text "Flip Y" -variable [ itcl::scope global_list(track_flipy) ]
+    pack $subframe3.flipy -pady 5 -side left
+    checkbutton $subframe3.flipz -text "Flip Z" -variable [ itcl::scope global_list(track_flipz) ]
+    pack $subframe3.flipz -pady 5 -side left
+
+    iwidgets::labeledframe $base.frame2 \
+	-labelpos nw  \
+	-labeltext "Fiber filtering"
+    pack $base.frame2 -fill both -expand f
+    
+    set frame2 [ $base.frame2 childsite ]
+
+    set subframe4 [ frame $frame2.subframe4 ]
+    pack $subframe4 -fill both -expand f
+    
+    iwidgets::entryfield $subframe4.track_minFA \
+	-width 4 \
+	-validate real \
+	-labeltext "Min FA:" \
+	-textvariable [ itcl::scope global_list(track_minFA) ] 
+    pack $subframe4.track_minFA -side left -padx 5 -pady 5  
+
+    iwidgets::entryfield $subframe4.track_maxFA \
+	-width 4 \
+	-validate real \
+	-labeltext "Max FA:" \
+	-textvariable [ itcl::scope global_list(track_maxFA) ] 
+    pack $subframe4.track_maxFA -side left -padx 5 -pady 5  
+
+    iwidgets::entryfield $subframe4.track_minMD \
+	-width 5 \
+	-validate real \
+	-labeltext "Min MD:" \
+	-textvariable [ itcl::scope global_list(track_minMD) ] 
+    pack $subframe4.track_minMD -side left -padx 5 -pady 5  
+    
+    iwidgets::entryfield $subframe4.track_maxMD \
+	-width 5 \
+	-validate real \
+	-labeltext "Max MD:" \
+	-textvariable [ itcl::scope global_list(track_maxMD) ] 
+    pack $subframe4.track_maxMD -side left -padx 5 -pady 5  
+    
+    set subframe5 [ frame $frame2.subframe5 ]
+    pack $subframe5 -fill both -expand f
+
+    iwidgets::entryfield $subframe5.track_mindist \
+	-width 5 \
+	-validate real \
+	-labeltext "Min length (mm):" \
+	-textvariable [ itcl::scope global_list(track_mindist) ] 
+    pack $subframe5.track_mindist -side left -padx 5 -pady 5        
+
+    iwidgets::entryfield $subframe5.track_maxdist \
+	-width 5 \
+	-validate real \
+	-labeltext "Max length (mm):" \
+	-textvariable [ itcl::scope global_list(track_maxdist) ] 
+    pack $subframe5.track_maxdist -side left -padx 5 -pady 5    
+
+    iwidgets::entryfield $subframe5.track_maxangle \
+	-width 5 \
+	-validate real \
+	-labeltext "Max angle (deg) :" \
+	-textvariable [ itcl::scope global_list(track_maxangle) ] 
+    pack $subframe5.track_maxangle -side left -padx 5 -pady 5  
+
+    set subframe7 [ frame $frame2.subframe7 ]
+    pack $subframe7 -fill both -expand f
+
+    checkbutton $subframe7.track_regionfilter \
+	-text "Only keep fibers that end in region" \
+	-variable [ itcl::scope global_list(track_regionfilter) ] \
+	-command [ itcl::code $this track_regionfilter_cb ]    
+    pack $subframe7.track_regionfilter -side left -padx 5
+
+    set track_regionnumber [ iwidgets::spinint $subframe7.track_regionnumber \
+				 -fixed 4 -width 4 -range {0 1000} -step 1 \
+				 -textvariable \
+				 [ itcl::scope global_list(track_regionnumber) ] ]
+    pack $track_regionnumber -side left -pady 5 -padx 0
+    set widget_list(track_regionnumber) $track_regionnumber  
+    $widget_list(track_regionnumber) configure -state disabled
+    
+    ## clipping
+    set track_clipping [ checkbutton $subframe7.track_clipping \
+			     -text "Clip fibers" -state disabled\
+			     -variable [ itcl::scope global_list(track_clipping) ] ]
+    pack $track_clipping -side left -padx 10       
+    set widget_list(track_clipping) $track_clipping  
+
+    set trackbtn [ iwidgets::buttonbox $base.trackbtn -orient horizontal ]
+    $trackbtn add track -text "Track!" -command [ itcl::code $this fiber_track ] -state disabled
+    pack $trackbtn -side left -expand f
+    set widget_list(trackbtn) $trackbtn
+
+    ## auto stat
+    set track_autostat [ checkbutton $base.track_autostat \
+			     -text "Auto fiber statistics" \
+			     -variable [ itcl::scope global_list(track_autostat) ] ]
+    pack $track_autostat -side right -padx 5  
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create fiber tracking control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::CreateFiberControl { base } {
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Fibers"
+    pack $base.frame0 -fill both
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -expand t -side top
+
+    label $subframe1.dummy0 -text "Color:"
+    pack $subframe1.dummy0 -side left -padx 5 -pady 5
+        
+    set fiber_color [ image create photo -width 15 -height 15 ]
+    $fiber_color put $global_list(fiber_color) -to 0 0 15 15
+    
+    button $subframe1.fiber_color -image $fiber_color \
+	-command [ itcl::code $this fiber_color_cb ]
+    pack $subframe1.fiber_color -side left
+    set widget_list(fiber_color) $subframe1.fiber_color
+
+    set fiber_name [ iwidgets::entryfield $subframe1.fiber_name \
+			 -textvariable [ itcl::scope global_list(fiber_name) ] \
+			 -labeltext "Label:" \
+			 -width 30 \
+			 -command [ itcl::code $this fiber_name_cb ] ] 
+    pack $fiber_name -side left -pady 5 -padx 5 -fill x -expand t
+    set widget_list(fiber_name) $fiber_name
+    
+    checkbutton $subframe1.fiber_display \
+	-text "Display" \
+	-variable [ itcl::scope global_list(fiber_display) ] \
+	-command [ itcl::code $this fiber_display_cb ]    
+    pack $subframe1.fiber_display -side left -padx 5
+
+    set middle [ frame $frame0.middle ] 
+    pack $middle -fill x -expand t -side top -pady 2
+    
+    set subframe2 [ frame $middle.subframe2 ]
+    pack $subframe2 -fill both -expand t -side left -pady 2
+
+    iwidgets::scrolledlistbox $subframe2.fiberlist \
+	-hscrollmode dynamic \
+	-visibleitems 40x15 \
+	-listvariable [ itcl::scope global_list(fiber_list) ] \
+	-selectmode extended \
+	-selectioncommand [ itcl::code $this fiber_selection_cb ]    
+    pack $subframe2.fiberlist -side left -fill both -expand t -padx 5
+    set widget_list(fiber_list) $subframe2.fiberlist
+   
+    set subframe3 [ frame $middle.subframe3 ]
+    pack $subframe3 -expand f -side left
+
+    set fiberbbox [ iwidgets::buttonbox $subframe3.fiberbbox -orient vertical ]
+    $fiberbbox add load -text "Load" -command [ itcl::code $this fiber_load ]
+    $fiberbbox add save -text "Save" -command [ itcl::code $this fiber_saveselected ]
+    $fiberbbox add saveall -text "Save all" -command [ itcl::code $this fiber_saveall ]
+    $fiberbbox add remove -text "Remove" -command [ itcl::code $this fiber_removeselected ]
+    $fiberbbox add clear -text "Clear" -command [ itcl::code $this fiber_clear ]
+    $fiberbbox add stat -text "Statistics" -command [ itcl::code $this fiber_statistics ]
+    pack $fiberbbox -side left -expand t
+    set widget_list(fiber_buttonbox) $fiberbbox        
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create statistics control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::CreateStatisticsControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Statistics"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+
+    set stat_text [iwidgets::scrolledtext $subframe0.stat_text \
+		       -visibleitems 70x19 \
+		       -foreground black \
+		       -vscrollmode static \
+		       -hscrollmode static \
+		       -wrap none ]
+    pack $stat_text -side top -expand t -fill both -padx 2 -pady 2
+    set widget_list(stat_text) $stat_text
+
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -expand t
+
+    set statbbox [ iwidgets::buttonbox $subframe1.statbbox -orient horizontal -pady 2 -padx 2 ]
+    $statbbox add save -text "Save..." -command [ itcl::code $this fiber_savestatistics ]
+    $statbbox add clear -text "Clear" -command "$stat_text delete 1.0 end"
+    pack $statbbox -side left -fill both 
+
+    set stat_overwrite [ checkbutton $subframe1.stat_overwrite -text "Overwrite" \
+			     -variable [ itcl::scope global_list(stat_overwrite) ] ]
+    pack $stat_overwrite -side right -padx 5       
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  Create fiber display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::CreateFiberDisplayControl { base } {
+
+    set subframe0 [ frame $base.subframe0 ]
+    pack $subframe0 -fill x -side top -expand f -padx 5 -pady 5
+    
+    set view_fiber_filter \
+	[ iwidgets::optionmenu $subframe0.view_fiber_filter -labeltext "Filter:" ]
+    
+    $view_fiber_filter configure -command [ itcl::code $this view_fiber_filter_cb ]
+    $view_fiber_filter insert end "Fractional anisotropy"
+    $view_fiber_filter insert end "Mean diffusivity"
+    $view_fiber_filter insert end "Fiber distance"
+    $view_fiber_filter insert end "Fiber angle"
+    $view_fiber_filter insert end "Region number"
+    $view_fiber_filter insert end "Input map"
+    $view_fiber_filter insert end "Directionality"
+    
+    pack $view_fiber_filter -side left -padx 5
+    set widget_list(view_fiber_filter) $view_fiber_filter
+    
+    set view_fiber_glyph [ iwidgets::optionmenu $subframe0.view_fiber_glyph \
+				-labeltext "View fibers as:"   \
+				-command [ itcl::code $this view_fiber_glyph_cb ] ] \
+	
+    pack $view_fiber_glyph -side left -padx 5
+    $view_fiber_glyph insert end "Lines"
+    $view_fiber_glyph insert end "Tubes"
+    $view_fiber_glyph insert end "Points"
+    set widget_list(view_fiber_glyph) $view_fiber_glyph
+    
+    set subframe1 [ frame $base.subframe1 ]
+    pack $subframe1 -side top -fill both -padx 5 -expand f
+    
+    iwidgets::entryfield $subframe1.view_fiber_tuberadius \
+	-width 5 \
+	-validate real \
+	-labeltext "Tube radius:" \
+	-textvariable [ itcl::scope global_list(view_fiber_tuberadius) ]  \
+	-command [ itcl::code $this view_fiber_tuberadius_cb ]
+    pack $subframe1.view_fiber_tuberadius -side left -padx 5    
+
+    iwidgets::entryfield $subframe1.view_fiber_pointsize \
+	-width 5 \
+	-validate real \
+	-labeltext "Point size:" \
+	-textvariable [ itcl::scope global_list(view_fiber_pointsize) ]  \
+	-command [ itcl::code $this view_fiber_pointsize_cb ]
+    pack $subframe1.view_fiber_pointsize -side left -padx 5    
+    
+    set view_fiber_luk [ checkbutton $subframe1.view_fiber_luk \
+			     -text "Apply colormap" \
+			     -variable [ itcl::scope global_list(view_fiber_luk) ] \
+			     -command [ itcl::code $this view_fiber_colormap_cb ] ]
+    pack $view_fiber_luk -side left -pady 5 -padx 5       
+    set widget_list(view_fiber_luk) $view_fiber_luk
+
+    set subframe2 [ frame $base.subframe2 ]
+    pack $subframe2 -side left -fill both -padx 5 
+    
+    set subframe21 [ frame $subframe2.subframe21 ]
+    pack $subframe21 -side top -fill both -expand t -padx 5 
+
+    set fiber_luk [ mpjguilookuptable \#auto 0 ]
+    $fiber_luk Initialize $subframe21
+    pack forget [ $fiber_luk GetButtonBoxWidget ]
+#    pack forget [ $fiber_luk GetMenuBar ]     
+    #    [ $fiber_luk GetLookupTable ] SetVectorModeToComponent
+    #    [ $fiber_luk GetLookupTable ] SetVectorComponent 0
+    $fiber_luk SetHueRange 0.5 0.92
+    $fiber_luk SetSaturationRange 0.75 1.0
+    $fiber_luk Update
+    $fiber_luk Show
+    
+
+    set widget_list(view_fiberluk) $fiber_luk
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::CreateDisplayControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Properties"
+    pack $base.frame0 -fill both -expand t 
+
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -padx 5 -pady 5 -expand f
+    
+    checkbutton $subframe0.view_fibers -text "View fibers" \
+	-variable [ itcl::scope global_list(view_fiber) ] \
+	-command [ itcl::code $this view_toggle_fiber ]   
+    pack $subframe0.view_fibers -side left -padx 5
+
+    checkbutton $subframe0.view_colorbar -text "View colorbar" \
+	-variable [ itcl::scope global_list(view_colorbar) ] \
+	-command [ itcl::code $this view_toggle_colorbar ]   
+    pack $subframe0.view_colorbar -side left -padx 5
+    
+    iwidgets::entryfield $subframe0.view_colorbar_label \
+	-width 15 \
+	-labeltext "Input Map label:" \
+	-textvariable [ itcl::scope global_list(view_colorbar_label) ]
+    pack $subframe0.view_colorbar_label -side left -padx 5    
+
+    set subframe1 [ frame $frame0.subframe1 ] 
+    pack $subframe1 -fill both -expand t -padx 2 -pady 2
+
+    CreateFiberDisplayControl $subframe1
+}
+
+# -------------------------------------------------------------------------------------------
+#  Diffusion control inititialization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::Initialize { widget } {
+    
+    if { $initialized == 1 } { return $basewidget }
+    
+    #  -------------------------------------
+    #  Create User Interface
+    #  -------------------------------------	
+    set basewidget [toplevel $widget ]
+    wm geometry $basewidget 650x480
+    wm withdraw $basewidget
+
+    set notebook $basewidget.notebook    
+    iwidgets::tabnotebook $notebook -tabpos w         
+    set widget_list(notebook) $notebook
+
+    set mb [ frame $basewidget.mb ]
+    pack $mb -side top -fill x -expand false
+    
+    CreateMenu $mb
+
+    CreateInputControl      [ $notebook add -label "Input" ] 
+    CreateDirectionControl  [ $notebook add -label "Directionality" ]    
+    CreateTrackingControl   [ $notebook add -label "Tracking" ]
+    CreateFiberControl      [ $notebook add -label "Fibers" ]
+    CreateStatisticsControl [ $notebook add -label "Statistics" ]
+    CreateResultsControl    [ $notebook add -label "Results" ]
+    CreateDisplayControl    [ $notebook add -label "Display" ]
+   
+    pack $notebook -side top -fill both -expand t -padx 5
+    
+    $notebook view "Input"
+    
+    set pbar [ frame $basewidget.pbar -width 400 -height 20 ]
+    pack $pbar -side bottom -expand f -fill x
+    CreateProgressBar $pbar
+    
+    set w [ frame $basewidget.w -relief ridge -width 800]
+    pack $w -side bottom -fill x -expand false
+    
+    eval "button $w.close -text Close -command { $this DismissWindow }"
+    pack $w.close -side right -fill x -padx 5 -pady 10
+    
+    set initialized 1
+
+    SetTitle $appname
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { $this DismissWindow }"
+ 
+    return $basewidget
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create top level menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::CreateMenu { mb } {    
+    
+    menubutton $mb.results       -text Results     -menu $mb.results.m -underline 0
+    pack $mb.results    -side left
+    menubutton $mb.tracking -text Tracking -menu $mb.tracking.m -underline 0
+    pack $mb.tracking -side left
+    menubutton $mb.help      -text Help         -menu $mb.help.m -underline 0 -padx 4
+    pack $mb.help  -side right
+
+    menu $mb.results.m -tearoff 0 
+#    eval "$mb.results.m add command -label \"Track fibers\" -command { $this fiber_track } -underline 0 -state disabled"
+    $mb.results.m add command -label "Save All Results" -command [ itcl::code $this saveallresults ] -underline 0
+    $mb.results.m add separator
+    if { $parent == 0 } {
+	eval "$mb.results.m add command -label Exit -command {  pxtkexit } -underline 1"
+    } else {
+	eval "$mb.results.m add command -label Close -command {  $this HideWindow } -underline 1"
+    }
+
+    menu $mb.tracking.m -tearoff 0
+    $mb.tracking.m add command -label "Track fibers" -command [ itcl::code $this fiber_track ] -underline 0 -state disabled
+    $mb.tracking.m add separator
+    $mb.tracking.m add check -label "Exploration" -underline 0 \
+	-variable [ itcl::scope global_list(track_explore) ] \
+	-command [ itcl::code $this view_toggle_trackexplore ]
+
+    menu $mb.help.m -tearoff 0
+
+    set widget_list(menu_results) $mb.results.m    
+    set widget_list(menu_tracking) $mb.tracking.m
+
+    eval "$mb.help.m add command -label About -command { $this AboutCommand }"
+   
+}
+
+#-------------------------------------------------------------------------------------------
+#  Add controls to menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjfibertracking::AddToMenuButton { mb args } {
+    eval "$mb add command -label \"Fiber tracking\" -command {$this ShowWindow \"Input\"}"
+}
+
+#-------------------------------------------------------------------------------------------
+#  Main function for stand-alone execution
+# ------------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    puts "\n[ file rootname $argv0 ] is not a stand-alone program.\n"
+    exit
+
+}
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjguiicosahedron.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjguiicosahedron.tcl
new file mode 100644
index 0000000..92d65b2
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjguiicosahedron.tcl
@@ -0,0 +1,455 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+ 
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package provide mpjguiicosahedron 1.0
+
+package require mpjguiobject 1.0
+
+itcl::class mpjguiicosahedron {
+
+    inherit mpjguiobject
+
+    private variable iren 0          ; ## vtkRenderWindowInteractor
+    private variable renderer 0      ; ## vtkRenderer
+    private variable renwin          ; ## vtkRenderWindow
+    private variable spheresource 0  ; ## vtkSphereSource
+    private variable spheremapper 0  ; ## vtkPolyDataMapper
+    private variable sphereactor 0   ; ## vtkSphereActor
+
+    private variable xaxis
+    private variable xaxismapper
+    private variable xaxisactor
+    private variable yaxis
+    private variable yaxismapper
+    private variable yaxisactor
+    private variable zaxis
+    private variable zaxismapper
+    private variable zaxisactor
+
+    private variable wiremapper 0    ; ## vtkPolyDataMapper
+    private variable wireactor 0     ; ## vtkSphereActor - wireframe
+    
+    private variable preview_widget 0; ## vtkTkRenderWidget
+    
+    private variable resolution 1
+    private variable radius 1.0
+    private variable numpoints 12
+
+    private variable filename "icosahedron.txt"
+
+    private variable menubase 0
+    private variable buttonbox 0
+    private variable propertybox 0
+    private variable preview 0
+    
+    ## constructor
+    constructor { args } { 
+	mpjguiobject::constructor $args
+    } {
+
+	## x - axes
+	set xaxis [ vtkArrowSource [ pxvtable::vnewobj ] ]	
+	$xaxis SetTipLength 0.1
+	
+	set xaxismapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+	$xaxismapper SetInput [ $xaxis GetOutput ]
+
+	set xaxisactor  [ vtkActor [ pxvtable::vnewobj ] ]
+	$xaxisactor SetMapper $xaxismapper
+	$xaxisactor SetScale 1.4 0.9 0.9
+	[ $xaxisactor GetProperty ] SetColor 1.0 0.0 0.0
+
+	## y - axes
+	set yaxis [ vtkArrowSource [ pxvtable::vnewobj ] ]	
+	$yaxis SetTipLength 0.1
+	
+	set yaxismapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+	$yaxismapper SetInput [ $yaxis GetOutput ]
+
+	set yaxisactor  [ vtkActor [ pxvtable::vnewobj ] ]
+	$yaxisactor SetMapper $yaxismapper
+	$yaxisactor RotateZ 90.0
+	$yaxisactor SetScale 1.4 0.9 0.9
+	[ $yaxisactor GetProperty ] SetColor 0.0 1.0 0.0
+
+	## z - axes
+	set zaxis [ vtkArrowSource [ pxvtable::vnewobj ] ]	
+	$zaxis SetTipLength 0.1
+	
+	set zaxismapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+	$zaxismapper SetInput [ $zaxis GetOutput ]
+
+	set zaxisactor  [ vtkActor [ pxvtable::vnewobj ] ]
+	$zaxisactor SetMapper $zaxismapper
+	$zaxisactor RotateY 90.0
+	$zaxisactor SetScale 1.4 0.9 0.9
+	[ $zaxisactor GetProperty ] SetColor 0.0 0.0 1.0
+
+	## sphere
+	set spheresource [ vtkmpjIcosahedronSource [ pxvtable::vnewobj ] ]
+	$spheresource SetDepth 1
+	$spheresource AllowDuplicatePointsOff
+	
+	set spheremapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+	$spheremapper SetInput [ $spheresource GetOutput ] 
+
+	set sphereactor [ vtkActor [ pxvtable::vnewobj ] ]
+	[ $sphereactor GetProperty ] SetDiffuse 0.5
+	$sphereactor SetMapper $spheremapper
+	
+	## sphere wireframe
+	set wiremapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+	$wiremapper ScalarVisibilityOff
+	$wiremapper SetResolveCoincidentTopologyToPolygonOffset
+	$wiremapper SetInput [ $spheresource GetOutput ] 
+	
+	set wireactor [ vtkActor [ pxvtable::vnewobj ] ]
+	$wireactor SetMapper $wiremapper
+	[ $wireactor GetProperty ] SetRepresentationToWireframe
+	[ $wireactor GetProperty ] SetColor 0.5 0.5 0.5
+	#$wireactor SetScale 1.0125 1.0125 1.0125	
+    }
+    
+    ## initialization
+    protected method InitializeWindow { parent } 
+    
+    public method Reset { }
+    public method Update { }
+    public method Save { }
+
+    ## sphere properties
+    public method SetSphereOn { }  { $sphereactor VisibilityOn }
+    public method SetSphereOff { }  { $sphereactor VisibilityOff }
+    public method SetSphereColor { red green blue } 
+    public method SetSphereOpacity { opacity }
+
+    public method SetDepth { res } { set resolution $res }
+    public method GetDepth { } { return $resolution }
+    public method GetPoints { } 
+    public method GetNumberOfPoints { } { return $numpoints }
+
+    ## wireframe properties
+    public method SetWireframeOn { }  { $wireactor VisibilityOn }
+    public method SetWireframeOff { }  { $wireactor VisibilityOff }
+    public method SetWireframeColor { red green blue }
+    public method SetWireframeOpacity { opacity }
+    public method SetWireframeLineWidth { width }
+    
+    ## widgets
+    public method GetButtonBoxWidget { } { return $buttonbox }
+    public method GetPropertyWidget { } { return $propertybox }
+    public method GetPreviewWidget { } { return $preview }
+    public method SetPreviewLabel { label } { $preview configure -labeltext $label }
+    
+    ## source retrieval
+    public method GetIcosahedron { } { return $spheresource }
+
+    ## actor retrieval    
+    public method GetSphereActor { } { return $sphereactor }
+    public method GetWireframeActor { } { return $wireactor }
+
+    ## import
+    public method AddActor { actor } { $renderer AddActor $actor }
+    public method AddActor2D { actor } { $renderer AddActor2D $actor }
+    public method RemoveActor { actor } { $renderer RemoveActor $actor }
+
+    ## private methods
+    private method create_preview_frame { basewidget }
+    private method create_property_box { basewidget }
+    private method create_button_box { basewidget }
+    private method create_pipeline { basewidget }
+    private method spin_int { widget direction }
+    private method save_icosahedron { fname }
+
+    destructor {
+	catch { 
+	    $spheresource Delete
+	    $spheremapper Delete
+	    $wiremapper Delete
+	    $sphereactor Delete
+	    $wireactor Delete
+	    
+	    $xaxisactor Delete
+	    $xaxismapper Delete
+	    $xaxis Delete
+	    $yaxisactor Delete
+	    $yaxismapper Delete
+	    $yaxis Delete
+	    $zaxisactor Delete
+	    $zaxismapper Delete
+	    $zaxis Delete
+
+	    $iren Delete
+	    $renwin Delete
+	    $renderer Delete	   
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::GetPoints { } {
+    
+    return [ [ $spheresource GetOutput ] GetPoints ]
+   
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::SetSphereColor { red green blue } { 
+    [ $sphereactor GetProperty ] SetColor $red $green $blue
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::SetSphereOpacity { opacity } { 
+    [ $sphereactor GetProperty ] SetOpacity $opacity
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::SetWireframeColor { red green blue } { 
+    [ $wireactor GetProperty ] SetColor $red $green $blue
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::SetWireframeOpacity { opacity } {    
+    [ $wireactor GetProperty ] SetOpacity $opacity
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::SetWireframeLineWidth { width } {
+    [ $wireactor GetProperty ] SetLineWidth $width
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::Reset { } {
+
+    set resolution 1
+    
+    $spheresource SetDepth $resolution 
+    
+    Update
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::Update { } {
+    
+    ## update sphere source
+    $spheresource SetDepth $resolution
+    $spheresource Update
+    
+    set numpoints [ [ $spheresource GetOutput ] GetNumberOfPoints ]
+    
+    $renwin Render
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::Save { } {
+    
+    set fname [tk_getSaveFile -title "Save as" -initialfile $filename \
+		   -filetypes {{"Text" {.txt}}} ]
+    if { [ string length $fname ] < 1 } {
+        return 0
+    }
+    
+    save_icosahedron $fname
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::spin_int { widget direction } {    
+
+    set new_value [expr [$widget get] + $direction]
+
+    if { $new_value > 20 } { set new_value 20 }
+    if { $new_value < 1 } { set new_value 1 }
+    
+    $widget clear
+    $widget insert 0 $new_value
+
+    Update
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::create_button_box { basewidget } {
+
+    set buttonbox [ iwidgets::buttonbox $basewidget.buttons -pady 5 ]
+    
+    $buttonbox add update -text "Reset" -command [itcl::code $this Reset ]
+    $buttonbox add print -text "Save" -command [itcl::code $this Save ]
+    $buttonbox add dismiss -text "Dismiss" -command [itcl::code $this Hide ]
+   
+    pack $buttonbox -side top
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::create_property_box { basewidget } {
+
+    set propertybox [ frame $basewidget.param ]
+    pack $propertybox -side top -fill both -pady 2 -expand f
+
+    set res $propertybox.res
+
+    iwidgets::spinint $res \
+	-labeltext "Depth: " \
+	-width 3 \
+	-range { 1 20 } \
+	-wrap no \
+	-command [ itcl::code $this Update ] \
+	-decrement [itcl::code $this spin_int $res -1] \
+	-increment [itcl::code $this spin_int $res +1] \
+   	-textvariable [ itcl::scope resolution ] 
+
+    pack $propertybox.res -side left -padx 5
+
+    $propertybox.res clear
+    $propertybox.res insert 0 1
+    
+    label $propertybox.dummy1
+    pack $propertybox.dummy1 -side left -padx 2
+
+    label $propertybox.dummy2 -text "Number of points:"
+    pack $propertybox.dummy2 -side left
+
+    set points $propertybox.points
+    label $points -textvariable [ itcl::scope numpoints ]
+    pack $points -side left
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::save_icosahedron { fname } {
+ 
+    set points [ [ $spheresource GetOutput ] GetPoints ]
+    set total [ $points GetNumberOfPoints ]
+    
+    set fileid [ open $fname w ]
+    
+    puts $fileid $total
+    
+    for { set i 0 } { $i < $total } { incr i } {
+	set pt [ $points GetPoint $i ]
+	puts $fileid "$pt"
+    }
+
+    close $fileid
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::create_preview_frame { basewidget } {
+    
+    set w 150
+    set h 150
+    
+    set preview [ iwidgets::labeledframe $basewidget.render \
+		      -relief sunken -labeltext "Preview" -labelpos nw]
+    pack $preview -side top -fill both -expand t
+    
+    set preview_widget [vtkTkRenderWidget [$preview childsite].renderwidget \
+			    -width $w -height $h -rw $renwin ]
+    pack $preview_widget -side top -fill both -expand t
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::create_pipeline { basewidget } {    
+    
+    ## create renderer
+    set renderer [ vtkRenderer [ pxvtable::vnewobj ] ]
+
+    ## add actors
+    $renderer AddActor $xaxisactor
+    $renderer AddActor $yaxisactor
+    $renderer AddActor $zaxisactor    
+    $renderer AddActor $sphereactor
+    $renderer AddActor $wireactor
+
+    ## set renderer options
+    [ $renderer GetActiveCamera ] Zoom 1.4
+    [ $renderer GetActiveCamera ] SetFocalPoint 0.0 0.0 0.0
+    $renderer SetBackground 0.1 0.2 0.4
+
+    ## create render window and interactor
+    set renwin [ vtkRenderWindow [ pxvtable::vnewobj ] ]
+    $renwin AddRenderer $renderer
+
+    set iren [ vtkRenderWindowInteractor [ pxvtable::vnewobj ] ]
+    $iren SetRenderWindow $renwin
+
+    set trackball [ vtkInteractorStyleTrackballCamera [ pxvtable::vnewobj ] ]
+    $iren SetInteractorStyle $trackball
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiicosahedron::InitializeWindow { parent } {
+
+    mpjguiobject::InitializeWindow $parent
+
+    SetTitle "mpjguiicosahedron: $filename" 
+
+    ## set graphics pipeline
+    create_pipeline $basewidget
+
+    if { $parentwidget != 0 } {
+	pack $basewidget -side left -fill both -expand t
+    }
+
+    ## construct interface
+    create_preview_frame $basewidget 
+    create_property_box $basewidget 
+    create_button_box $basewidget
+
+    $renwin Render
+    
+    if { $parentwidget == 0 } {
+	eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    }
+}
+
+# ---------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    
+    option add *textBackground seashell
+    
+    wm withdraw .
+        
+    set sph [ mpjguiicosahedron \#auto 0 ]   ; ## create object as top-level
+    $sph Initialize 0
+    
+    $sph SetPreviewLabel "test"
+
+    $sph Show ; ## map window
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjguilookuptable.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjguilookuptable.tcl
new file mode 100644
index 0000000..2e9c0f5
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjguilookuptable.tcl
@@ -0,0 +1,640 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package provide mpjguilookuptable 1.0
+
+package require mpjguiobject 1.0
+
+itcl::class mpjguilookuptable {
+
+    inherit mpjguiobject
+
+    private variable iren 0          ; ## vtkRenderWindowInteractor
+    private variable renderer 0      ; ## vtkRenderer
+    private variable renwin          ; ## vtkRenderWindow
+    private variable lookuptable 0   ; ## vtkLookupTable
+    private variable scalarbar 0     ; ## vtkScalarBarActor 
+    private variable preview_widget 0; ## vtkTkRenderWidget
+
+    private variable hue_min 0.0
+    private variable hue_max 1.0
+    private variable sat_min 1.0
+    private variable sat_max 1.0
+    private variable val_min 1.0
+    private variable val_max 1.0
+    private variable alpha_min 1.0
+    private variable alpha_max 1.0
+    private variable num_colors 256
+    private variable min_value 0.0
+    private variable max_value 1.0
+    private variable scale 0
+    private variable filename "new_lookuptable.cmap"
+
+    private variable menubase 0
+    private variable buttonbox 0
+    private variable tablerange 0
+    private variable colorrange 0
+    private variable preview 0
+    
+    constructor { args } { 
+	mpjguiobject::constructor $args
+    } {
+
+	set lookuptable [ vtkLookupTable [ pxvtable::vnewobj ] ]	
+	$lookuptable SetHueRange 0.0 1.0
+	$lookuptable Build
+	
+	set scalarbar [ vtkScalarBarActor [ pxvtable::vnewobj ] ]
+	$scalarbar SetLookupTable $lookuptable
+    }
+    
+    protected method InitializeWindow { parent } 
+    
+    public method Reset { }
+    public method Load { }
+    public method SaveAs { }
+    public method Update { }
+    public method GetLookupTable { } { return $lookuptable }
+    public method GetButtonBoxWidget { } { return $buttonbox }
+    public method GetColorRangeWidget { } { return $colorrange }
+    public method GetPreviewWidget { } { return $preview }
+    public method GetRenderWidget { } { return $preview_widget }
+    public method GetMenuBar { } { return $menubase }
+    public method SetTableRange { min max } { set min_value $min; set max_value $max; }
+    public method SetHueRange { min max } { set hue_min $min; set hue_max $max; }
+    public method SetValueRange { min max } { set val_min $min; set val_max $max; }
+    public method SetSaturationRange { min max } { set sat_min $min; set sat_max $max; }
+    public method SetLookupTable { luk } 
+    public method Copy { luk }
+
+    private method file_new { }
+    private method file_load { }
+    private method file_save { }
+    private method file_save_as { }
+    private method load_lookuptable { fname }
+    private method save_lookuptable { fname }
+    private method create_menu { basewidget }
+    private method create_menu_buttons { basewidget }
+    private method create_color_frame { basewidget }
+    private method create_preview_frame { basewidget }
+    private method create_button_box { basewidget }
+    private method create_pipeline { basewidget }
+    private method scale_select { widget }
+    private method spin_float { widget direction }
+    private method spin_validate { widget value }
+
+    destructor {
+	catch { 
+	    $iren Delete
+	    $renwin Delete
+	    $renderer Delete
+	    $lookuptable Delete
+	    $scalarbar Delete
+	}
+    }
+}
+
+itcl::body mpjguilookuptable::Reset { } {
+
+    set num_colors 256
+    set scale 0
+    set min_value 0.0; set max_value 1.0
+    set hue_min 0.0; set hue_max 1.0
+    set sat_min 1.0; set sat_max 1.0
+    set val_min 1.0; set val_max 1.0
+    set alpha_min 1.0; set alpha_max 1.0
+
+    ## unfortunately objects need to be recreated
+    $renderer RemoveActor $scalarbar    
+    $scalarbar Delete
+
+    $lookuptable Delete
+    set lookuptable [ vtkLookupTable [ pxvtable::vnewobj ] ]
+    $lookuptable ForceBuild
+
+    set scalarbar [ vtkScalarBarActor [ pxvtable::vnewobj ] ]
+    [$scalarbar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport
+    [$scalarbar GetPositionCoordinate] SetValue 0.075 0.30
+    $scalarbar SetOrientationToHorizontal
+    $scalarbar SetNumberOfLabels 3
+    $scalarbar SetLabelFormat "%5.2f"
+    $scalarbar SetWidth 0.85
+    $scalarbar SetHeight 0.75
+    $scalarbar SetLookupTable $lookuptable    
+    
+    $renderer AddActor2D $scalarbar
+
+    Update
+}
+
+itcl::body mpjguilookuptable::Update { } {
+    
+    $lookuptable Modified;  ## make sure it will update
+
+    $lookuptable SetScale $scale
+    $lookuptable SetTableRange $min_value $max_value
+    $lookuptable SetNumberOfTableValues $num_colors
+    $lookuptable SetHueRange $hue_min $hue_max
+    $lookuptable SetSaturationRange $sat_min $sat_max
+    $lookuptable SetValueRange $val_min $val_max
+    $lookuptable SetAlphaRange $alpha_min $alpha_max
+
+    $lookuptable ForceBuild
+
+    $renwin Render
+}
+
+itcl::body mpjguilookuptable::SetLookupTable { luk } {
+
+    $renderer RemoveActor $scalarbar    
+    $scalarbar Delete
+
+    $lookuptable Delete
+    set lookuptable $luk
+
+    set scalarbar [ vtkScalarBarActor [ pxvtable::vnewobj ] ]
+    [$scalarbar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport
+    [$scalarbar GetPositionCoordinate] SetValue 0.075 0.30
+    $scalarbar SetOrientationToHorizontal
+    $scalarbar SetNumberOfLabels 3
+    $scalarbar SetLabelFormat "%5.2f"
+    $scalarbar SetWidth 0.85
+    $scalarbar SetHeight 0.75
+    $scalarbar SetLookupTable $lookuptable    
+    
+    $renderer AddActor2D $scalarbar
+
+    $renwin Render
+}
+
+itcl::body mpjguilookuptable::Copy { luk } {
+    
+    #set luk [ $guiluk GetLookupTable ]
+    set num_colors [ $luk GetNumberOfTableValues ]
+
+    $lookuptable SetNumberOfTableValues $num_colors
+
+    set table_range [ $luk GetTableRange ]
+    set min_value [ lindex $table_range 0 ] 
+    set max_value [ lindex $table_range 1 ]
+    $lookuptable SetTableRange $min_value $max_value
+
+    for { set i 0} { $i < $num_colors } { incr i } {
+	set rgba [ $luk GetTableValue $i ]
+	$lookuptable SetTableValue $i \
+	    [lindex $rgba 0] [lindex $rgba 1] [lindex $rgba 2] [lindex $rgba 3]	
+    }
+    
+    $renwin Render
+    
+}
+
+itcl::body mpjguilookuptable::scale_select { widget } {
+    set scale [$widget index [$widget get]]
+    Update
+}
+
+itcl::body mpjguilookuptable::spin_validate { widget value } {    
+    ## validate if it's a real number and in [0, 1] 
+    if {[regexp {^[-+]?[0-9]*\.?[0-9]*([0-9]\.?[eE][-+]?[0-9]*)?$} $value]} {
+	return [expr $value >= 0 && $value <= 1.0]
+    } else {
+	return 0
+    }
+}
+
+itcl::body mpjguilookuptable::spin_float { widget direction } {    
+    set new_value [expr [$widget get] + $direction]
+    if { $new_value > 1.0 } { set new_value 0 }
+    if { $new_value < 0.0 } { set new_value 1.0 }
+    $widget clear
+    $widget insert 0 $new_value
+    Update
+}
+
+itcl::body mpjguilookuptable::Load { } {
+
+    $this file_load
+}
+
+itcl::body mpjguilookuptable::SaveAs { } {
+    
+    $this file_save_as
+}
+
+itcl::body mpjguilookuptable::file_new { } {
+    
+    set filename "new_lookuptable"
+    SetTitle "mpjguilookuptable: $filename"    
+    Reset
+}
+
+itcl::body mpjguilookuptable::file_load { } {
+    set fname [tk_getOpenFile -title "Load" -initialfile $filename -filetypes {{"Colormap" {.cmap}}} ]
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+    load_lookuptable $fname
+}
+
+itcl::body mpjguilookuptable::file_save { } {
+    save_lookuptable $filename
+}
+
+itcl::body mpjguilookuptable::file_save_as { } {
+    set fname [tk_getSaveFile -title "Save as" -initialfile $filename -filetypes {{"Colormap" {.cmap}}} ]
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }    
+    save_lookuptable $fname
+}
+
+itcl::body mpjguilookuptable::load_lookuptable { fname } {
+
+    if { [ string length $fname ] < 1 || [ file readable $fname ] == 0 } {
+	::pxtclutil::Warning "Cannot read color table from $fname\n Bad File"
+	return 0
+    }
+
+    set fileid [ open $fname r ]
+
+    gets $fileid line; if { $line != "#IPAGRGBAColormap" } { close $fileid; return 0 }
+    
+    gets $fileid line;  ## skip comment
+    gets $fileid num_colors 
+    $lookuptable SetNumberOfTableValues $num_colors
+    
+    gets $fileid line;  ## skip comment
+    gets $fileid table_range
+    set min_value [ lindex $table_range 0 ] 
+    set max_value [ lindex $table_range 1 ]
+    $lookuptable SetTableRange $min_value $max_value
+    
+    gets $fileid line; gets $fileid line; ## skip comments
+    for { set i 0} { $i < $num_colors } { incr i } {
+	gets $fileid rgba
+	$lookuptable SetTableValue [lindex $rgba 0] \
+	    [lindex $rgba 1] [lindex $rgba 2] [lindex $rgba 3] [lindex $rgba 4]	
+    }
+
+    close $fileid
+
+    set filename $fname
+    SetTitle "mpjguilookuptable: [file tail $filename]"
+
+    $renwin Render
+}
+
+itcl::body mpjguilookuptable::save_lookuptable { fname } {
+
+    set fileid [ open $fname w ]
+
+    puts $fileid "#IPAGRGBAColormap"
+    puts $fileid "#Number of Colors"
+    puts $fileid $num_colors
+
+    puts $fileid "\#Range"
+    puts $fileid "$min_value $max_value"
+
+    puts $fileid "\#Colors"
+    puts $fileid "\#Index  R     G     B   Alpha"
+    
+    for { set i 0} { $i < $num_colors } { incr i } {
+	set rgba [ $lookuptable GetTableValue $i ]
+	puts $fileid "$i $rgba"
+    }
+
+    close $fileid
+}
+
+itcl::body mpjguilookuptable::create_menu_buttons { basewidget } {
+
+    set menubase [ frame $basewidget.menu -width 400 -height 50 ]
+    pack $menubase -side bottom -expand f -fill x -pady 1
+
+    button $menubase.file_new -text "Reset" -command [ itcl::code $this file_new ]
+    pack $menubase.file_new -side left
+
+    button $menubase.file_load -text "Load" -command [ itcl::code $this file_load ]
+    pack $menubase.file_load -side left
+    
+    button $menubase.file_save -text "Save" -command [ itcl::code $this file_save_as ]
+    pack $menubase.file_save -side left
+    
+}
+
+itcl::body mpjguilookuptable::create_menu { basewidget } {
+
+    set menubase [ frame $basewidget.menu -width 400 -height 50 ]
+    pack $menubase -side top -expand f -fill x -pady 1
+
+    menubutton $menubase.file -text "File" -menu $menubase.file.m -underline 0
+    pack $menubase.file -side left
+
+    menu $menubase.file.m -tearoff 0
+    $menubase.file.m add command -label "New" -underline 0 \
+	-command [ itcl::code $this file_new ]
+    $menubase.file.m add separator
+    $menubase.file.m add command -label "Load..." -underline 0 \
+	-command [ itcl::code $this file_load ]
+    $menubase.file.m add command -label "Save" -underline 0 \
+	-command [ itcl::code $this file_save ]
+    $menubase.file.m add command -label "Save as..." -underline 5 \
+	-command [ itcl::code $this file_save_as ]
+    $menubase.file.m add separator
+    $menubase.file.m add command -label "Close" -underline 1 \
+	-command  [ itcl::code $this Hide ]
+
+}
+
+itcl::body mpjguilookuptable::create_button_box { basewidget } {
+
+    set buttonbox [ iwidgets::buttonbox $basewidget.buttons -pady 5 ]
+    
+    $buttonbox add update -text "Update" -command [itcl::code $this Update]
+    $buttonbox add dismiss -text "Dismiss" -command [itcl::code $this Hide ]
+   
+    pack $buttonbox -side top
+}
+
+itcl::body mpjguilookuptable::create_preview_frame { basewidget } {
+    
+    set preview [ iwidgets::labeledframe $basewidget.render \
+		      -relief sunken -labeltext "Preview" -labelpos nw]
+    pack $preview -side top -fill x -expand t
+    
+    set preview_widget [vtkTkRenderWidget [$preview childsite].renderwidget \
+			    -width 400 -height 100 ]
+    pack $preview_widget -side top -fill x -expand true
+    update idletasks
+    
+    set renwin [ $preview_widget GetRenderWindow ]
+
+    $renwin AddRenderer $renderer
+    eval "bind $preview_widget <Expose> { $renwin Render }"
+    eval "bind $preview_widget <Map> { $renwin Render }"
+
+
+}
+
+itcl::body mpjguilookuptable::create_pipeline { basewidget } {    
+    
+    [$scalarbar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport
+    [$scalarbar GetPositionCoordinate] SetValue 0.075 0.30
+    $scalarbar SetOrientationToHorizontal
+    $scalarbar SetNumberOfLabels 3
+    $scalarbar SetLabelFormat "%5.2f"
+    $scalarbar SetWidth 0.85
+    $scalarbar SetHeight 0.75
+
+    set renderer [ vtkRenderer [ pxvtable::vnewobj ] ]
+    $renderer AddActor2D $scalarbar
+    $renderer SetBackground 0.5 0.5 0.5
+    
+    #    set renwin [ vtkRenderWindow [ pxvtable::vnewobj ] ]
+    #    $renwin AddRenderer $renderer
+
+    #    set iren [ vtkRenderWindowInteractor [ pxvtable::vnewobj ] ]
+    #    $iren SetRenderWindow $renwin
+
+}
+
+itcl::body mpjguilookuptable::create_color_frame { basewidget } {
+
+    set range [ iwidgets::labeledframe $basewidget.range -labeltext "Color range" -labelpos nw]
+    pack $range -side top -fill both 
+    set colorrange $range
+
+    set buildfr [ frame [$range childsite].buildfr ]
+    pack $buildfr -side top 
+    
+    set numcolors $buildfr.numcolors
+    iwidgets::entryfield $numcolors \
+	-width 5 \
+	-validate numeric \
+	-command [ itcl::code $this Update ] \
+	-textvariable [ itcl::scope num_colors ] \
+	-labeltext "Colors:" 
+    pack $numcolors -side left -padx 5 -pady 5     
+      
+    set minscalar [ iwidgets::entryfield $buildfr.minscalar \
+			-width 7 \
+			-validate real \
+			-textvariable [ itcl::scope min_value ] \
+			-command [ itcl::code $this Update ] \
+			-labeltext "Scalars:" ] 
+    pack $minscalar -side left -padx 5 -pady 5 
+
+    set maxscalar [ iwidgets::entryfield $buildfr.maxscalar \
+			-width 7 \
+			-validate real \
+			-textvariable [ itcl::scope max_value ] \
+			-command [ itcl::code $this Update ] \
+			-labeltext "to:" ] 
+    pack $maxscalar -side left -padx 0 -pady 5 
+
+
+    set scalemenu $buildfr.scalemenu
+    iwidgets::optionmenu $scalemenu \
+	-command [itcl::code $this scale_select $scalemenu] 
+    pack $scalemenu -side left -padx 5 -pady 5
+    $scalemenu insert end Linear
+    $scalemenu insert end Log10
+    $scalemenu select Linear
+
+    set from [ frame [$range childsite].from ]   
+    pack $from -side top -fill x
+    
+    label $from.l0 -text "1:"
+    pack $from.l0 -side left -fill x -padx 5
+    
+    set spinner $from.hue
+    iwidgets::spinner $spinner \
+	-labeltext "H: " \
+	-width 6 \
+	-command [itcl::code $this Update] \
+	-validate [itcl::code $this spin_validate $spinner %P] \
+	-decrement [itcl::code $this spin_float $spinner -0.01] \
+	-increment [itcl::code $this spin_float $spinner +0.01] \
+	-textvariable [itcl::scope hue_min] 
+    pack $from.hue -side left -pady 5 -padx 2
+    $from.hue clear
+    $from.hue insert 0 0.0
+
+    set spinner $from.sat
+    iwidgets::spinint $spinner \
+	-labeltext "S: " \
+	-width 6 \
+	-command [itcl::code $this Update] \
+	-validate [itcl::code $this spin_validate $spinner %P] \
+	-decrement [itcl::code $this spin_float $spinner -0.01] \
+	-increment [itcl::code $this spin_float $spinner +0.01] \
+	-textvariable [itcl::scope sat_min]
+    pack $from.sat -side left -pady 5 -padx 2
+    $from.sat clear
+    $from.sat insert 0 1.0
+
+    set spinner $from.val
+    iwidgets::spinint $from.val \
+	-labeltext "V: " \
+	-width 6 \
+	-command [itcl::code $this Update] \
+	-validate [itcl::code $this spin_validate $spinner %P] \
+	-decrement [itcl::code $this spin_float $spinner -0.01] \
+	-increment [itcl::code $this spin_float $spinner +0.01] \
+	-textvariable [itcl::scope val_min]
+    pack $from.val -side left -pady 5 -padx 2
+    $from.val clear
+    $from.val insert 0 1.0
+  
+    set spinner $from.alpha
+    iwidgets::spinint $spinner \
+	-labeltext "A: " \
+	-width 6 \
+	-command [itcl::code $this Update] \
+	-validate [itcl::code $this spin_validate $spinner %P] \
+	-decrement [itcl::code $this spin_float $spinner -0.01] \
+	-increment [itcl::code $this spin_float $spinner +0.01] \
+	-textvariable [itcl::scope alpha_min]
+    pack $from.alpha -side left -pady 5 -padx 2
+    $from.alpha clear
+    $from.alpha insert 0 1.0
+
+    set to [ frame [$range childsite].to ]
+    pack $to -side top -fill x
+
+    label $to.l1 -text "2:" -anchor e
+    pack $to.l1 -side left -fill x -padx 5
+    
+    set spinner $to.hue
+    iwidgets::spinint $spinner \
+	-labeltext "H: " \
+	-width 6 \
+	-command [itcl::code $this Update] \
+	-validate [itcl::code $this spin_validate $spinner %P] \
+	-decrement [itcl::code $this spin_float $spinner -0.01] \
+	-increment [itcl::code $this spin_float $spinner +0.01] \
+	-textvariable [itcl::scope hue_max]
+    pack $to.hue -side left -pady 5 -padx 2
+    $to.hue clear
+    $to.hue insert 0 1.0
+
+    set spinner $to.sat
+    iwidgets::spinint $spinner \
+	-labeltext "S: " \
+	-width 6 \
+	-command [itcl::code $this Update] \
+	-validate [itcl::code $this spin_validate $spinner %P] \
+	-decrement [itcl::code $this spin_float $spinner -0.01] \
+	-increment [itcl::code $this spin_float $spinner +0.01] \
+	-textvariable [itcl::scope sat_max]
+    pack $to.sat -side left -pady 5 -padx 2
+    $to.sat clear
+    $to.sat insert 0 1.0
+
+    set spinner $to.val
+    iwidgets::spinint $spinner \
+	-labeltext "V: " \
+	-width 6 \
+	-command [itcl::code $this Update] \
+	-validate [itcl::code $this spin_validate $spinner %P] \
+	-decrement [itcl::code $this spin_float $spinner -0.01] \
+	-increment [itcl::code $this spin_float $spinner +0.01] \
+	-textvariable [itcl::scope val_max]    
+    pack $to.val -side left -pady 5 -padx 2
+    $to.val clear
+    $to.val insert 0 1.0
+
+    set spinner $to.alpha
+    iwidgets::spinint $spinner \
+	-labeltext "A: " \
+	-width 6 \
+	-command [itcl::code $this Update] \
+	-validate [itcl::code $this spin_validate $spinner %P] \
+	-decrement [itcl::code $this spin_float $spinner -0.01] \
+	-increment [itcl::code $this spin_float $spinner +0.01] \
+	-textvariable [itcl::scope alpha_max]
+    pack $to.alpha -side left -pady 5 -padx 2
+    $to.alpha clear
+    $to.alpha insert 0 1.0   
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguilookuptable::InitializeWindow { parent } {
+
+    mpjguiobject::InitializeWindow $parent
+
+    SetTitle "mpjguilookuptable: $filename" 
+
+    create_pipeline $basewidget
+
+    if { $parentwidget == 0 } {
+	create_menu $basewidget
+    } else {
+	create_menu_buttons $basewidget
+    }
+    create_color_frame $basewidget
+    create_preview_frame $basewidget
+    create_button_box $basewidget
+    
+    $renwin Render
+    
+    if { $parentwidget == 0 } {
+	eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    }
+}
+
+# ---------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    
+    option add *textBackground seashell
+
+    wm withdraw .
+        
+    set luk [ mpjguilookuptable \#auto 0 ]   ; ## create object as top-level
+    $luk Initialize 0
+
+    
+    $luk Show ; ## map window
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjguiobject.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjguiobject.tcl
new file mode 100644
index 0000000..0e4c787
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjguiobject.tcl
@@ -0,0 +1,134 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package provide mpjguiobject 1.0
+
+package require vtkmpjcontrib 1.1
+package require pxtclutil 1.0
+package require Itcl 3.2
+package require Iwidgets 4.0
+
+itcl::class mpjguiobject {
+
+    protected variable parentwidget 0
+    protected variable basewidget 0
+    
+    constructor { args } {
+    }
+    
+    destructor {}
+
+    protected method InitializeWindow { parent } ; ## redefine this in derived classes
+
+    public method Initialize { parent } { InitializeWindow $parent }
+    public method Show { }
+    public method Hide { }
+    public method Destroy { } { destroy $basewidget }
+    public method SetTitle { title }
+
+    public method GetBaseWidget { } { return $basewidget }
+    public method GetParentWidget { } { return $parentwidget }
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguiobject::InitializeWindow { parent } {
+
+    set parentwidget $parent
+
+    if { $parent == 0 } {
+
+	set basewidget [ toplevel .[ pxvtable::vnewobj ] ]
+	
+	wm withdraw $basewidget	
+	
+    } else { 
+
+	set basewidget [ frame $parent.[ pxvtable::vnewobj ] ]
+
+    }
+}
+
+itcl::body mpjguiobject::Show { } {
+
+    if { $basewidget == 0 } { 
+	return 
+    }
+
+    if { $parentwidget != 0 } {
+	pack $basewidget
+    }
+
+    if { [ winfo ismapped $basewidget ] == 1 } {
+	raise $basewidget
+	return $basewidget
+    }
+	
+    if { $parentwidget == 0 } {
+	wm deiconify $basewidget
+    }
+    return $basewidget
+}
+
+
+itcl::body mpjguiobject::Hide { } {
+    catch { wm withdraw $basewidget }
+}
+
+itcl::body mpjguiobject::SetTitle { title } {
+    if { $parentwidget == 0 } {
+	wm title $basewidget $title
+    }
+}
+
+# ---------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    
+    option add *textBackground seashell
+
+    wm withdraw .
+        
+    set guiobj [ mpjguiobject \#auto 0 ]   ; ## create object as top-level
+    $guiobj Initialize 0
+
+    $guiobj Show  ; ## map window
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjguisphere.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjguisphere.tcl
new file mode 100644
index 0000000..c4cdb43
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjguisphere.tcl
@@ -0,0 +1,406 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package provide mpjguisphere 1.0
+
+package require mpjguiobject 1.0
+package require  vtkinteraction
+
+itcl::class mpjguisphere {
+
+    inherit mpjguiobject
+
+    private variable iren 0          ; ## vtkRenderWindowInteractor
+    private variable renderer 0      ; ## vtkRenderer
+    private variable renwin          ; ## vtkRenderWindow
+    private variable spheresource 0  ; ## vtkSphereSource
+    private variable spheremapper 0  ; ## vtkPolyDataMapper
+    private variable sphereactor 0   ; ## vtkSphereActor
+    private variable wiremapper 0    ; ## vtkPolyDataMapper
+    private variable wireactor 0     ; ## vtkSphereActor - wireframe
+    
+    private variable preview_widget 0; ## vtkTkRenderWidget
+    
+    private variable resolution 10
+    private variable radius 1.0
+    private variable numpoints 12
+    private variable width 100
+    private variable height 100
+
+    private variable filename "sphere.txt"
+    
+    private variable menubase 0
+    private variable buttonbox 0
+    private variable propertybox 0
+    private variable preview 0
+    
+    ## constructor
+    constructor { args } { 
+	mpjguiobject::constructor $args
+    } {
+	
+	set spheresource [ vtkSphereSource [ pxvtable::vnewobj ] ]
+	$spheresource SetThetaResolution $resolution
+	$spheresource SetPhiResolution $resolution
+	$spheresource SetRadius 1.0
+		
+	## sphere
+	set spheremapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+	$spheremapper SetInput [ $spheresource GetOutput ] 
+	
+	## sphere actor
+	set sphereactor [ vtkActor [ pxvtable::vnewobj ] ]
+	$sphereactor SetMapper $spheremapper
+	
+	## sphere wireframe
+	set wiremapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+	$wiremapper SetInput [ $spheresource GetOutput ] 
+	
+	set wireactor [ vtkActor [ pxvtable::vnewobj ] ]
+	$wireactor SetMapper $wiremapper
+	[ $wireactor GetProperty ] SetRepresentationToWireframe
+	[ $wireactor GetProperty ] SetColor 0.5 0.5 0.5
+	$wireactor SetScale 1.0125 1.0125 1.0125
+    }
+    
+    ## initialization
+    protected method InitializeWindow { parent } 
+    
+    public method Reset { }
+    public method Update { }
+    public method Save { }
+    public method Resize { w h } { set width $w; set height $h }
+
+    ## sphere properties
+    public method SetSphereOn { }  { $sphereactor VisibilityOn }
+    public method SetSphereOff { }  { $sphereactor VisibilityOff }
+    public method SetSphereColor { red green blue } 
+    public method SetSphereOpacity { opacity }
+
+    public method SetResolution { res } { set resolution $res }
+    public method GetResolution { } { return $resolution }
+    public method GetNumberOfPoints { } { return $numpoints }
+
+    ## wireframe properties
+    public method SetWireframeOn { }  { $wireactor VisibilityOn }
+    public method SetWireframeOff { }  { $wireactor VisibilityOff }
+    public method SetWireframeColor { red green blue }
+    public method SetWireframeOpacity { opacity }
+    public method SetWireframeLineWidth { width }
+    
+    ## widgets
+    public method GetButtonBoxWidget { } { return $buttonbox }
+    public method GetPropertyWidget { } { return $propertybox }
+    public method GetPreviewWidget { } { return $preview }
+
+    ## actor retrieval
+    public method GetSphereActor { } { return $sphereactor }
+    public method GetWireframeActor { } { return $wireactor }
+
+    ## import
+    public method AddActor { actor } { $renderer AddActor $actor }
+    public method AddActor2D { actor } { $renderer AddActor2D $actor }
+    public method RemoveActor { actor } { $renderer RemoveActor $actor }
+
+    ## private methods
+    private method create_preview_frame { basewidget }
+    private method create_property_box { basewidget }
+    private method create_button_box { basewidget }
+    private method create_pipeline { basewidget }
+    private method spin_int { widget direction }
+    private method save_sphere { fname }
+    
+    destructor {
+	catch { 
+	    $spheresource Delete
+	    $spheremapper Delete
+	    $wiremapper Delete
+	    $sphereactor Delete
+	    $wireactor Delete
+	    $iren Delete
+	    $renwin Delete
+	    $renderer Delete	   
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::SetSphereColor { red green blue } { 
+    [ $sphereactor GetProperty ] SetColor $red $green $blue
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::SetSphereOpacity { opacity } { 
+    [ $sphereactor GetProperty ] SetOpacity $opacity
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::SetWireframeColor { red green blue } { 
+    [ $wireactor GetProperty ] SetColor $red $green $blue
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::SetWireframeOpacity { opacity } {    
+    [ $wireactor GetProperty ] SetOpacity $opacity
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::SetWireframeLineWidth { width } {
+    [ $wireactor GetProperty ] SetLineWidth $width
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::Reset { } {
+    
+    set resolution 10
+
+    Update
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::Update { } {
+    
+    ## update sphere source
+    $spheresource SetThetaResolution $resolution
+    $spheresource SetPhiResolution $resolution
+    $spheresource Update
+    
+    set numpoints [ [ $spheresource GetOutput ] GetNumberOfPoints ]
+    
+    $renderer ResetCamera
+    $renwin Render
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::Save { } {
+    
+    set fname [tk_getSaveFile -title "Save as" -initialfile $filename \
+		   -filetypes {{"Text" {.txt}}} ]
+    if { [ string length $fname ] < 1 } {
+        return 0
+    }
+    
+    save_sphere $fname
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::save_sphere { fname } {
+ 
+    set points [ [ $spheresource GetOutput ] GetPoints ]
+    set total [ $points GetNumberOfPoints ]
+    
+    set fileid [ open $fname w ]
+    
+    puts $fileid $total
+    
+    for { set i 0 } { $i < $total } { incr i } {
+	set pt [ $points GetPoint $i ]
+	puts $fileid "$pt"
+    }
+
+    close $fileid
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::spin_int { widget direction } {    
+    
+    set new_value [expr [$widget get] + $direction]
+    
+    if { $new_value > 20 } { set new_value 20 }
+    if { $new_value < 1 } { set new_value 1 }
+    
+    $widget clear
+    $widget insert 0 $new_value
+
+    Update
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::create_button_box { basewidget } {
+
+    set buttonbox [ iwidgets::buttonbox $basewidget.buttons -pady 5 ]
+    
+    $buttonbox add update -text "Reset" -command [itcl::code $this Reset ]
+    $buttonbox add print -text "Save" -command [itcl::code $this Save ]    
+    $buttonbox add dismiss -text "Dismiss" -command [itcl::code $this Hide ]
+    
+    pack $buttonbox -side top
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::create_property_box { basewidget } {
+
+    set propertybox [ frame $basewidget.param ]
+    pack $propertybox -side top -fill both -pady 2 -expand f
+
+    set res $propertybox.res
+
+    iwidgets::spinint $res \
+	-labeltext "Resolution: " \
+	-width 3 \
+	-range { 1 20 } \
+	-wrap no \
+	-command [ itcl::code $this Update ] \
+	-decrement [itcl::code $this spin_int $res -1] \
+	-increment [itcl::code $this spin_int $res +1] \
+   	-textvariable [ itcl::scope resolution ] 
+
+    pack $propertybox.res -side left -padx 5
+
+    $propertybox.res clear
+    $propertybox.res insert 0 10
+    
+    label $propertybox.dummy1
+    pack $propertybox.dummy1 -side left -padx 2
+
+    label $propertybox.dummy2 -text "Number of points:"
+    pack $propertybox.dummy2 -side left
+
+    set points $propertybox.points
+    label $points -textvariable [ itcl::scope numpoints ]
+    pack $points -side left
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::create_preview_frame { basewidget } {
+    
+    set preview [ iwidgets::labeledframe $basewidget.render \
+		      -relief sunken -labeltext "Preview" -labelpos nw]
+    pack $preview -side top -fill both -expand t
+    
+    set preview_widget [vtkTkRenderWidget [$preview childsite].renderwidget \
+			    -width $width -height $height ]
+    pack $preview_widget -side top -fill both -expand true
+
+
+    set renwin [ $preview_widget GetRenderWindow ]
+    $renwin AddRenderer $renderer
+
+    eval "bind $preview_widget <Expose> { $renwin Render }"
+    $renwin Render
+
+    update idletasks
+
+
+
+    ## create render window and interactor
+    #    set iren [ vtkRenderWindowInteractor [ pxvtable::vnewobj ] ]
+    #    $iren SetRenderWindow $renwin
+    set evlist { ButtonPress-2 B2-Motion ButtonRelease-2 Shift-ButtonPress-2 Shift-B2-Motion Shift-ButtonRelease-2 Control-ButtonPress-2 Control-B2-Motion Control-ButtonRelease-2 }
+
+    ::vtk::bind_tk_widget $preview_widget $renwin
+    foreach ev $evlist { 
+	set evl "<${ev}>"
+	eval "bind $preview_widget $evl { }" 
+    }
+
+
+    
+    #   set trackball [ vtkInteractorStyleTrackballCamera [ pxvtable::vnewobj ] ]
+    #    [ $renwin GetInteractor ] SetInteractorStyle $trackball
+
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::create_pipeline { basewidget } {    
+    
+    ## create renderer
+    set renderer [ vtkRenderer [ pxvtable::vnewobj ] ]
+
+    ## add actors
+    $renderer AddActor $sphereactor
+    $renderer AddActor $wireactor
+
+    ## set renderer options
+    #[ $renderer GetActiveCamera ] Azimuth -35
+    #[ $renderer GetActiveCamera ] Elevation -35
+    [ $renderer GetActiveCamera ] Zoom 1.4
+    $renderer SetBackground 0.1 0.2 0.4
+
+    ## add actors
+    $renderer AddActor $sphereactor
+    $renderer AddActor $wireactor
+
+}
+
+#-------------------------------------------------------------------------------------
+itcl::body mpjguisphere::InitializeWindow { parent } {
+
+    mpjguiobject::InitializeWindow $parent
+
+    if { $parent == 0 } {
+	SetTitle "mpjguisphere: $filename" 
+    }
+
+    ## set graphics pipeline
+    create_pipeline $basewidget
+
+    if { $parentwidget != 0 } {
+	pack $basewidget -side left -fill both -expand t
+    }
+
+    ## construct interface
+    create_preview_frame $basewidget
+    create_property_box $basewidget
+    create_button_box $basewidget
+
+    $renwin Render
+    
+    if { $parentwidget == 0 } {
+	eval "wm protocol $basewidget WM_DELETE_WINDOW { wm withdraw $basewidget }"
+    }
+}
+
+# ---------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    
+    option add *textBackground seashell
+    
+    wm withdraw .
+        
+    set sph [ mpjguisphere \#auto 0 ]   ; ## create object as top-level
+    $sph Initialize 0
+    
+    
+    $sph Show ; ## map window
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjinterleave.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjinterleave.tcl
new file mode 100755
index 0000000..7a88c08
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjinterleave.tcl
@@ -0,0 +1,96 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+#package require pxtclutil 1.0
+package require vtkpxcontrib  1.1
+package require vtkmpjcontrib 1.1
+package require pxvtable 1.0
+
+if { $argc < 3} {
+    set name [file tail [info script]]
+    puts stdout "\n Usage:"
+    puts stdout "\n $name <input_image\[.hdr\]> <\[-frame\] | \[-slice\]> <number of output frames> \[out_name\]"
+    puts stdout "       -frame: input interleaved by frame"
+    puts stdout "       -slice: input interleaved by slice"
+    exit
+}
+
+set filename1 [lindex $argv 0]
+set interleave [lindex $argv 1]
+set number [lindex $argv 2]
+set fname "[ file rootname $filename1 ]"
+set outname "${fname}_inter"
+
+if { $argc >= 4 } {
+    set outname [lindex $argv 3]
+}
+
+puts stdout "Reading in image [lindex $argv 0]"
+vtkpxAnalyzeImageSource ana1
+ana1 Load $filename1
+
+vtkmpjImageInterleaving inter
+inter SetInput [ ana1 GetOutput ]
+
+if { $interleave == "-frame" } {
+    inter SetFrameInterleave 
+} else {
+    inter SetSliceInterleave
+}
+
+inter SetNumberOfFrames $number
+inter Update
+
+puts stdout "Saving resulting image..."
+vtkpxAnalyzeImageWriter out
+out SetInput [inter GetOutput]
+out SetOrientation [ana1 GetOrientation]
+out Save $outname
+
+puts stdout "Done!\n"
+
+ana1 Delete
+inter Delete
+
+exit
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjmultibtensorutility.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjmultibtensorutility.tcl
new file mode 100644
index 0000000..706979a
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjmultibtensorutility.tcl
@@ -0,0 +1,2395 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package provide mpjmultibtensorutility 1.3
+
+package require  Itcl 3.2
+package require  Iwidgets 4.0
+
+package require  pxitcllistselector 1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitclbaseimageviewer 1.0
+
+package require  vtkmpjcontrib 1.1
+package require  mpjguilookuptable 1.0
+package require  mpjguisphere 1.0
+package require  vtkinteraction
+
+itcl::class mpjmultibtensorutility {
+
+    inherit pxitclbaseimagecontrol
+    
+    #-----------------------------------
+    # construction and descruction
+    #-----------------------------------
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } { InitializeControl }
+    
+    destructor { }
+
+    # Generic Stuff 
+    protected variable setupfilename "subject.dti"
+
+    #-----------------------------------
+    # common variables
+    #-----------------------------------
+
+    #-----------------------------------
+    # global variables
+    #-----------------------------------
+    private variable widget_list
+    private variable global_list
+    
+    #-----------------------------------
+    # initialization methods
+    #-----------------------------------
+    public method Initialize { inpwidg }
+    public method InitializeControl { }
+    public method DismissWindow { }
+      
+    # ----------------------------
+    # Setup Stuff
+    # ----------------------------
+    public method LoadSetup { args } 
+    public method SaveSetup { args } 
+    protected method GetFileElement { fileid } 
+
+    #-----------------------------------
+    # diffusion series input/output
+    #-----------------------------------
+    public method AddInput { fname }
+    public method RemoveInput { index }
+    public method RemoveAllInputs { }
+    public method DisplayInput { index frame }
+    public method LoadGradient { fname }
+    public method LoadMask { fname }
+    public method ComputeResults { }
+    public method SaveAllResults { }
+    public method SaveResult { index }
+    public method ClearAllResults { }
+    public method DisplayResult { index }
+    public method ClearDisplay { }
+    public method SetResultPreffix { preffix }
+    public method GetResultPreffix { } 
+    public method SetCurrentDirectory { fname } 
+    
+    #-----------------------------------
+    # interface creation methods
+    #-----------------------------------
+    private method CreateInputControl { base }
+    private method CreateMaskControl { base }
+    private method CreateResultsControl { base }
+    private method CreateGradientControl { base }
+    private method CreateTransformControl { base }
+    private method CreateDistributionControl { base }
+    private method CreateMenu { mb }
+    public method AddToMenuButton { mb args}    
+ 
+    private method addinput { }
+    private method removeinput { }
+    private method displayinput { }
+    private method loadgradient { }
+    private method checkgradient { }
+    private method loadmask { }
+    private method displayresult { }
+    private method saveresult { }
+    private method saveallresults { }
+
+    private method addbvalue { }
+    private method removebvalue { }
+  
+    private method input_updateinfo { index }    
+    private method input_selectioncommand_cb { } 
+    private method gradient_searchlist { dir }
+    private method gradient_populatelist { index }
+    private method gradient_increment_ndir { dir }
+    private method gradient_showantipodal { }
+    
+    private method mask_autochanged_cb { }
+    private method mask_autothreshchanged_cb { }
+
+    private method result_clear { }
+    private method result_createbaseline { }
+    private method result_createmask { } 
+    private method result_createtensor { }
+    private method result_createadc { }
+    private method result_createeigen { }
+}  
+
+#-------------------------------------------------------------------------------------------
+#  Close window 
+# -------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::DismissWindow { } {
+
+    set ok "yes"
+    
+    if { [ llength $global_list(input_list) ] > 0 } {
+	
+	set ok [ tk_messageBox -type yesnocancel -default no \
+		     -parent $basewidget -title "Think again ..." \
+		     -message "Unload all images from memory?" -icon question  ]
+
+    }
+    
+    if { $ok == "yes" } {	
+	
+	$this ClearAllResults
+	$this RemoveAllInputs
+
+	#$global_list(gradient_points) Delete
+	#$global_list(gradient_polydata) Delete
+	#$global_list(gradient_actor) Delete
+	#$global_list(gradient_anti_actor) Delete
+	    
+	$this SetTitle $global_list(appname)
+		
+	set global_list(mask_fname) "select"
+	set global_list(tensor_fname) ""
+    }
+
+    if { $ok != "cancel" } {
+	$this HideWindow
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  Initialize tool
+# -------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::InitializeControl { } {
+    
+    set global_list(appname) "(EXPERIMENTAL) Multiple b-Value Diffusion Tensor Utility"
+    
+    set appname "$global_list(appname) $version"
+    set aboutstring "(c) Marcel Jackowski 2008"
+        
+    set dir6 "{0.707 0.0 0.707} {-0.707 0.0 0.707} {0.0 0.707 0.707} {0.0 0.707 -0.707} {0.707 0.707 0.0} {-0.707 0.707 0.0}"
+
+    set dir6i "{0.000000  0.525731 -0.850651} {0.000000 -0.525731 -0.850651} \
+               {0.525731 -0.850651 0.000000} {0.525731  0.850651 0.000000} \
+               {-0.850651 0.000000 0.525731} {-0.850651 0.000000 -0.525731}"
+
+    set dir10i "{-0.577300 0.577300 0.577300} {-0.577300 0.577300 -0.577300} \
+                {0.577300 0.577300 0.577300} {0.577300 0.577300 -0.577300} \
+                {0.000000 -0.934200 0.356800} {0.000000 0.934200 0.356800} \
+                {-0.356800 0.000000 0.934200} {0.356800 0.000000 0.934200} \
+                {-0.934200 0.356800 0.000000} {0.934200 0.356800 0.000000}"
+
+    set dir15i "{1.000000 0.000000 0.000000} {0.000000 1.000000 0.000000} \
+                {0.000000 0.000000 1.000000} {0.309017 -0.809017 -0.500000} \
+                {0.309017 0.809017 -0.500000} {-0.309017 -0.809017 -0.500000} \
+                {0.309017 -0.809017 0.500000} {-0.500000 0.309017 0.809017} \
+                {0.500000 -0.309017 0.809017} {0.500000 0.309017 -0.809017} \
+                {0.500000 0.309017 0.809017} {-0.809017 0.500000 0.309017} \
+                {0.809017 -0.500000 0.309017} {0.809017 0.500000 -0.309017} \
+                {-0.809017 -0.500000 -0.309017}"
+
+    set dir21i "{1.000000 0.000000 0.000000} {0.000000 1.000000 0.000000} \
+                {0.000000 0.000000 1.000000} {0.000000 0.525731 -0.850651} \
+                {0.000000 -0.525731 -0.850651} {0.525731 -0.850651 0.000000} \
+                {0.525731 0.850651 0.000000} {-0.850651 0.000000 0.525731} \
+                {-0.850651 0.000000 -0.525731} {0.309017 -0.809017 -0.500000} \
+                {0.309017 0.809017 -0.500000} {-0.309017 -0.809017 -0.500000} \
+                {0.309017 -0.809017 0.500000} {-0.500000 0.309017 0.809017} \
+                {0.500000 -0.309017 0.809017} {0.500000 0.309017 -0.809017} \
+                {0.500000 0.309017 0.809017} {-0.809017 0.500000 0.309017} \
+                {0.809017 -0.500000 0.309017} {0.809017 0.500000 -0.309017} \
+                {-0.809017 -0.500000 -0.309017}"
+
+    set dir24 "{0.134985506170 -0.985952791173 0.098366695086} \
+               {0.650088694587 -0.462793906466 -0.602666150790} \
+               {-0.206347275695 0.662332382064 0.720233724205} \
+               {-0.435854930194 0.350113596741 -0.829126618318} \
+               {0.985232180539 0.063955280317 -0.158830955895} \ 
+               {-0.614137826481 -0.392074584561 -0.684917695951} \
+               {0.353418655052 -0.587198098366 0.728212638957} \ 
+               {-0.944785803171 0.119466198906 -0.305135401821} \ 
+               {0.021302190861 -0.808690754556 -0.587848177815} \
+               {0.090322707483 0.786736539321 -0.610645090220} \
+               {0.019144141922 0.992112273707 0.123881952644} \
+               {0.685499579269 0.715694962504 -0.133682637122} \
+               {-0.492664112126 -0.044270667252 0.869092734203} \
+               {-0.582890874715 -0.806420953907 -0.099616631511} \
+               {0.048922860209 -0.155267715919 -0.986660270885} \
+               {0.542444409187 0.622999428166 0.563582980089} \
+               {0.763772109691 -0.640056077552 0.083548680702} \
+               {-0.913538674752 -0.294880095995 0.280165698682} \
+               {-0.347061443006 -0.702169846181 0.621695956149} \
+               {0.842177009528 -0.028740243511 0.538434659941} \
+               {0.207815962624 0.070701024559 0.975609497086} \
+               {-0.578727030552 0.786414267629 -0.215934304310} \
+               {-0.804218513225 0.456634532848 0.380417515892} \
+               {0.575100475666 0.281355246534 -0.768178799588}"
+
+    set dir32 "{0.127839994324 0.905079981288 -0.405570170652} {0.160624455635 0.551408286854 0.818626096237} {-0.660076326339 -0.746272212908 0.085889624794} {0.429182719745 -0.024323513182 0.902890115008} {0.017138782122 0.483370449508 -0.875248119501} {-0.017138782496 -0.483370449559 0.875248119465} {0.879670240941 -0.126024235489 0.458582772542} {0.372449269958 -0.928034884037 0.005726719673} {-0.615867796457 -0.445295752660 0.649937343096} {-0.420650772436 0.691083196582 0.587755853 [...]
+
+    # create initial set of gradient directions
+    set global_list(gradient_list) "{6 ME6 {$dir6}} {6 ICO6 {$dir6i}} \
+                                    {10 ICO10 {$dir10i}} \
+                                    {15 ICO15 {$dir15i}} {21 ICO21 {$dir21i}} \
+                                    {24 ME24 {$dir24}} {32 ME32 {$dir32}}"
+    
+    # create image titles
+    set global_list(result_title) \
+	[ list \
+	      { "Baseline image"                    "dti_baseline" } \
+	      { "Anatomical mask"                   "dti_mask" }  \
+	      { "Diffusion tensor"                  "dti_tensor" } \
+	      { "Mean diffusion-weighted"           "dti_mean" } \
+	      { "Apparent diffusion"                "dti_adc" } ]
+
+    foreach item $global_list(result_title) {
+ 	lappend result_list [ pxitclimage \#auto ]
+    }  
+    
+    set global_list(result_fpreffix) "preffix_"
+    set global_list(result_fdir) [ pwd ]
+    set global_list(result_fmask) "*.hdr"
+    set global_list(result_list) $result_list
+    
+    set global_list(input_fname) {}   ; # list of filenames
+    set global_list(input_list) {}    ; # list of input images
+    set global_list(input_blist) {0 1000}    ; list of b factors
+    set global_list(input_ndw) 1
+    set global_list(input_dw) 6
+    set global_list(input_frameno) 0
+    set global_list(input_tensorsymm) 1
+    set global_list(input_curbvalue) 1000
+    set global_list(input_bfactorenable) 0
+    
+    set global_list(tensor_ordering) 0
+    set global_list(tensor_flipx) 0
+    set global_list(tensor_flipy) 0
+    set global_list(tensor_flipz) 0
+    set global_list(tensor_swap) 0
+    set global_list(tensor_swapdir) 0
+    set global_list(tensor_swapyz) 0
+    set global_list(tensor_swapxz) 0
+    set global_list(tensor_swapxy) 0
+
+    set global_list(tensor_rotation) 0
+    set global_list(tensor_rotx) 0.0
+    set global_list(tensor_roty) 0.0
+    set global_list(tensor_rotz) 0.0
+    
+    set global_list(gradient_fname) "select"
+    set global_list(gradient_fdir) [ pwd ]
+    set global_list(gradient_tol) 1E-6
+    set global_list(gradient_showanti) 1
+    
+    set global_list(adc_compute) 1
+
+    set global_list(mask_auto) 1
+    set global_list(mask_fname) "select"
+    set global_list(mask_autothresh) 1
+    set global_list(mask_threshval) 0
+    set global_list(mask_connected) 1
+
+    set global_list(gradient_points) [ vtkPoints [ pxvtable::vnewobj ] ]
+    set global_list(gradient_polydata) [ vtkmpjVertexSource [ pxvtable::vnewobj ] ]
+    set global_list(gradient_actor) [ vtkActor [ pxvtable::vnewobj ] ]
+    set global_list(gradient_anti_actor) [ vtkActor [ pxvtable::vnewobj ] ]
+
+    [ $global_list(gradient_anti_actor) GetProperty ] SetRepresentationToPoints
+    [ $global_list(gradient_anti_actor) GetProperty ] SetColor 0.0 0.0 1.0
+    [ $global_list(gradient_anti_actor) GetProperty ] SetPointSize 3.0
+    
+    [ $global_list(gradient_actor) GetProperty ] SetRepresentationToPoints
+    [ $global_list(gradient_actor) GetProperty ] SetColor 1.0 0.0 0.0
+    [ $global_list(gradient_actor) GetProperty ] SetPointSize 3.0
+    
+}
+
+# ---------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::SaveSetup { args } {
+
+    set len [ llength $args ]
+    
+    if { $len < 1 } {
+	set fname $setupfilename 
+    } else {
+	set fname [ lindex $args 0 ]
+    }
+
+    if { [ string length $fname  ] == 0  } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname  [tk_getSaveFile -title "Saving Setup File" -filetypes { {"DTI-Setup File" {.dti}}} -initialfile $f1tail -initialdir $global_list(result_fdir) ]
+    }
+
+    if { [ string length $fname ] > 0 } {
+	
+	set fileid [open $fname w]
+	
+	puts $fileid "#DTI Subject Description File Version 1.3"
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Images"
+	puts $fileid "#---------------------------------------------"
+
+	puts $fileid "Total : [ llength $global_list(input_fname) ]"
+	foreach item $global_list(input_fname) {	    
+	    puts $fileid "Image : $item "
+	}
+
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Gradient directions"
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "Filename : $global_list(gradient_fname)"
+		
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Parameters"
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "Number of T2 images : $global_list(input_ndw)"
+	puts $fileid "Number of DW images : $global_list(input_dw)"
+	puts $fileid "Index : [ $widget_list(gradient_ndir) cget -clientdata ]"
+	
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Mask image"
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "Filename : $global_list(mask_fname)"
+
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Transformation"
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "Swapping : $global_list(tensor_swap)"
+	puts $fileid "Swap axes : $global_list(tensor_swapdir)"
+	#	puts $fileid "Swap X-Y : [expr $global_list(tensor_swapdir) == 1]"
+	#	puts $fileid "Swap X-Z : [expr $global_list(tensor_swapdir) == 2]"
+	#	puts $fileid "Swap Y-Z : [expr $global_list(tensor_swapdir) == 3]"
+	puts $fileid "Flip X : $global_list(tensor_flipx)"
+	puts $fileid "Flip Y : $global_list(tensor_flipy)"
+	puts $fileid "Flip Z : $global_list(tensor_flipz)"
+	puts $fileid "Rotation : $global_list(tensor_rotation)"
+	puts $fileid "RotX : $global_list(tensor_rotx)"
+	puts $fileid "RotY : $global_list(tensor_roty)"
+	puts $fileid "RotZ : $global_list(tensor_rotz)"
+
+	close $fileid
+
+	set setupfilename $fname
+
+	SetTitle "(EXPERIMENTAL) Multi-B Diffusion Tensor Utility $setupfilename"
+
+    }
+}
+
+# ---------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::GetFileElement { fileid } {
+
+   gets $fileid line 
+   set index [string first ":" $line]
+   if { $index > 0 }  {
+       set len   [string length $line]
+       set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+       return $value
+   }
+   return ""
+}
+
+# ---------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::LoadSetup { args } { 
+
+    set len [ llength $args ]
+    
+    if { $len < 1 } {
+	set fname $setupfilename 
+    } else {
+	set fname [ lindex $args 0 ]
+    }
+
+    if { [ string length $fname  ] == 0 } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	
+	set fname  [tk_getOpenFile -title "Setup File" -filetypes { {"DTI-Setup File" {.dti}}} -initialfile $f1tail -initialdir $global_list(result_fdir) -parent $basewidget ]
+    }
+
+    if { [ string length $fname ] < 1 } {
+	return
+    }
+
+    if { [ file readable $fname ] == 0 } {
+	::pxtclutil::Warning "Cannot read setupfile file from $fname\n Bad File"
+	return 0
+    }
+
+    set fileid [open $fname r]
+
+    gets $fileid line
+    if { [ string compare -length 29 $line "#DTI Subject Description File"  ] != 0 } {
+	close fileid
+	::pxtclutil::Warning "Cannot read setupfile file from $fname\n Bad File Type"
+	return 0
+    }
+
+    set version 0
+    
+    ## determine version
+    if { [ string length $line ] < 30 } {
+	set version "1.2"
+    } else {
+	set version [ string range $line 38 end ]
+    }
+
+    ## read input images
+    if { [ llength $global_list(input_fname) ] > 0 } {
+	$this RemoveAllInputs
+    }
+
+    gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+
+    set total [ GetFileElement $fileid ]
+    
+    for { set i 0 } { $i < $total } { incr i } {
+	set name [ GetFileElement $fileid ]
+	if { [ string length $name ] > 0 } {
+	    $this AddInput $name
+	}
+    }
+    
+    ## read gradients
+    gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+    
+    set name [ GetFileElement $fileid ]
+    if { $name != "select" } {
+	$this LoadGradient $name
+    }
+
+    gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+    
+    ## read number of ndws, dws, index
+    set number_ndw [ GetFileElement $fileid ]
+    set number_dw [ GetFileElement $fileid ]
+    set dir_index [ GetFileElement $fileid ]
+    
+    set global_list(input_ndw) $number_ndw
+    set global_list(input_dw) $number_dw
+    
+    ## populate list of directions
+    gradient_populatelist $dir_index
+    
+    set dirset [ lindex [ lindex $global_list(gradient_list) $dir_index ] 1 ]
+
+    ## set default number of directions
+    $widget_list(gradient_ndir) delete 0 end
+    $widget_list(gradient_ndir) insert 0 $dirset
+    $widget_list(gradient_ndir) configure -clientdata $dir_index
+    
+    ## set default number of directions
+    $widget_list(gradient_ndir1) delete 0 end
+    $widget_list(gradient_ndir1) insert 0 $dirset
+    $widget_list(gradient_ndir1) configure -clientdata $dir_index
+    
+    gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+
+    ## read mask image
+    set name [ GetFileElement $fileid ]
+    if { $name != "select" } {
+	$this LoadMask $name
+    }
+    
+    gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+
+    ## read in transformations
+
+    if { $version == "1.2" } {	
+	set global_list(tensor_swapxz) [ GetFileElement $fileid ]
+	set global_list(tensor_swapyz) [ GetFileElement $fileid ]
+	if { $global_list(tensor_swapxz) == 1} {
+	    set global_list(tensor_swap) 1
+	    set global_list(tensor_swapdir) 2
+	}
+	if { $global_list(tensor_swapyz) == 1} {
+	    set global_list(tensor_swap) 1
+	    set global_list(tensor_swapdir) 3
+	}
+	set global_list(tensor_flipx) [ GetFileElement $fileid ]
+	set global_list(tensor_flipy) [ GetFileElement $fileid ]
+	set global_list(tensor_flipz) [ GetFileElement $fileid ]
+	set global_list(tensor_rotation) 0
+	set global_list(tensor_rotx) 0.0
+	set global_list(tensor_roty) 0.0
+	set global_list(tensor_rotz) 0.0
+    } else {
+	## 1.3
+	set global_list(tensor_swap) [ GetFileElement $fileid ]
+	set global_list(tensor_swapdir) [ GetFileElement $fileid ]
+	set global_list(tensor_flipx) [ GetFileElement $fileid ]
+	set global_list(tensor_flipy) [ GetFileElement $fileid ]
+	set global_list(tensor_flipz) [ GetFileElement $fileid ]
+	set global_list(tensor_rotation) [ GetFileElement $fileid ]
+	set global_list(tensor_rotx) [ GetFileElement $fileid ]
+	set global_list(tensor_roty) [ GetFileElement $fileid ]
+	set global_list(tensor_rotz) [ GetFileElement $fileid ]
+    }
+    
+    
+    close $fileid
+    set setupfilename $fname
+    
+    SetTitle "Diffusion Tensor Utility $setupfilename"
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon input selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::input_selectioncommand_cb { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(input_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(input_list) index [ lindex $sel_item 0 ] ] 
+	set sel_input [ lindex $global_list(input_list) $sel_index ]
+	
+	## get number of components
+	set nc [ expr [ [ $sel_input GetImage ] GetNumberOfScalarComponents ] -1 ]
+	$widget_list(input_frameno) configure -range [ list 0 $nc ]
+	
+	## update information
+	input_updateinfo $sel_index	
+    }
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Update input information on title bar
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::input_updateinfo { index } {
+
+    set sel_input [ [ lindex $global_list(input_list) $index ] GetImage ]
+    set sel_fname [ lindex $global_list(input_fname) $index ]
+    
+    scan [ $sel_input GetDimensions ] "%d %d %d" dx dy dz	       
+    set nc [  $sel_input GetNumberOfScalarComponents ]
+    set name [ file tail [ file root $sel_fname ] ]
+    
+    set global_list(result_fpreffix) "${name}_"
+
+    $this SetTitle "$global_list(appname): $name (${dx}x${dy}x${dz}, $nc frames)"
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Add input
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::addinput { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Add diffusion images" -filetypes $typelist -initialdir $global_list(result_fdir) -multiple yes -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	foreach item $fname {
+	    
+	    ## load series into memory
+	    AddInput $item 
+	}
+
+	set global_list(result_fdir) [ file dirname [ lindex $fname 0 ]]
+	set global_list(result_fmask) "*[ file extension [ lindex $fname 0]]"
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Remove selected input
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::removeinput { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(input_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(input_list) index [ lindex $sel_item 0 ] ] 
+	
+	## remove series
+	RemoveInput $sel_index
+	
+    }    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Display selected input
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::displayinput { } {
+
+    ## get current selection 
+    set sel_item [ $widget_list(input_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(input_list) index [ lindex $sel_item 0 ] ] 
+	
+	## display series
+	DisplayInput $sel_index $global_list(input_frameno)
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Display specific image and frame, use frame value -1 to display all frames
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::DisplayInput { index frame } {
+
+    set input [ lindex $global_list(input_list) $index ]
+    
+    ## display multi-frame image
+    if { $frame == -1 } {
+	
+	$parent SetImageFromObject [ $input GetThisPointer ] $this
+
+    } else {
+	
+	set ncm [ [ $input GetImage ] GetNumberOfScalarComponents ]
+
+	## display single-frame image
+	if { [expr $frame >= 0 && $frame < $ncm] } { 
+	    
+	    set fex [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+	    $fex SetInput [ $input GetImage ]
+	    $fex SetFrameNumber $frame
+	    $fex Update
+	    
+	    set new_img [ pxitclimage \#auto ]
+	    $new_img CopyImage [ $fex GetOutput ] 0
+	    
+	    $fex Delete
+	    
+	    $new_img CopyImageHeader [ $input GetImageHeader ]	    
+	    $parent SetImageFromObject [ $new_img GetThisPointer ] $this
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Add diffusion image series
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::AddInput { fname } {
+
+    ## load series into memory
+    set input [ pxitclimage \#auto ]    
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+
+    $this SetFilterCallbacks $ana "Reading input..."
+
+    WatchOn
+
+    ## load input
+    $ana Load $fname 
+    $input SetFromAnalyzeSource $ana
+
+    set nc [ [$input GetImage] GetNumberOfScalarComponents ] 
+    
+    if { $nc < 7 } {
+	
+	set ok [ tk_messageBox -type ok \
+		     -parent $basewidget -title "Adding input." \
+		     -message "This image has only $nc frames!" -icon info ]
+	
+	WatchOff
+	
+	return
+    }
+    
+    if { [ llength $global_list(input_list) ] > 0 } {
+	
+	scan [ [ $input GetImage ] GetDimensions ] "%d %d %d" dx dy dz
+	
+	if { $dx != [lindex $global_list(input_dim) 0] || 
+	     $dy != [lindex $global_list(input_dim) 1] ||
+	     $dz != [lindex $global_list(input_dim) 2] } {
+	    
+	    set ok [ tk_messageBox -type ok \
+			 -parent $basewidget -title "Reading input." \
+			 -message "This image have different dimensions than other previously loaded images!" -icon info ]
+	    
+	    WatchOff
+	    return
+	}
+    } else {
+	set global_list(input_dim) [ [$input GetImage] GetDimensions ]
+    }
+
+    ## determine coordinate transform
+    set or [ $ana GetOrientation ]
+
+    if { $or == 0 } {
+	#	set global_list(tensor_swapyz) 0
+	#	set global_list(tensor_swapxz) 0
+	set global_list(tensor_swap) 0
+	set global_list(tensor_swapdir) 0
+    } elseif { $or == 1 } {
+	set global_list(tensor_swap) 1
+	set global_list(tensor_swapdir) 3
+	#	set global_list(tensor_swapyz) 1
+	#	set global_list(tensor_swapxz) 0
+    } elseif { $or == 2 } {
+	set global_list(tensor_swap) 1
+	set global_list(tensor_swapdir) 2
+	#	set global_list(tensor_swapxz) 1
+	#	set global_list(tensor_swapyz) 0
+    }
+    
+    $ana Delete
+    
+    ## guess the number of nondiffusion components
+    set global_list(input_ndw) [expr 2 - ($nc % 2) ] 
+    set global_list(input_dw) [expr $nc - $global_list(input_ndw) ]
+
+    if { $nc == 22 } {
+	set global_list(input_ndw) 1
+	set global_list(input_dw) 21
+    }
+
+    ## populate list of directions
+    set dir_index [ gradient_searchlist $global_list(input_dw) ]
+    gradient_populatelist $dir_index
+
+    set dirset [ lindex [ lindex $global_list(gradient_list) $dir_index ] 1 ]
+
+    ## set default number of directions
+    $widget_list(gradient_ndir) delete 0 end
+    $widget_list(gradient_ndir) insert 0 $dirset
+    $widget_list(gradient_ndir) configure -clientdata $dir_index
+
+    ## set default number of directions
+    $widget_list(gradient_ndir1) delete 0 end
+    $widget_list(gradient_ndir1) insert 0 $dirset
+    $widget_list(gradient_ndir1) configure -clientdata $dir_index
+        
+    WatchOff
+    
+    ## enable interface buttons
+    $widget_list(input_buttonbox) buttonconfigure remove -state normal
+    $widget_list(input_buttonbox) buttonconfigure display -state normal
+    $widget_list(input_frameno) configure -state normal
+    
+    $widget_list(menu_results) entryconfigure 0 -state normal
+    $widget_list(computebtn) configure -state normal
+    
+    lappend global_list(input_fname) $fname
+    lappend global_list(input_list) $input
+    
+    ## set new index
+    set new_index [ expr [ llength $global_list(input_list) ] -1 ]
+    
+    ## update information
+    input_updateinfo $new_index
+    
+    ## invoke selection callback
+    input_selectioncommand_cb
+    
+    ## display input if autodisplay is on
+    $this displayinput
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Remove all diffusion image series
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::RemoveAllInputs { } {
+    
+    set num [ llength $global_list(input_list) ]
+
+    for { set i 0 } { $i < $num } { incr i } {
+
+	RemoveInput 0
+
+    }
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Remove diffusion image series
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::RemoveInput { index } {
+    
+    ## remove series into memory
+    [ lindex $global_list(input_list) $index ] Clear    
+    itcl::delete object [ lindex $global_list(input_list) $index ]
+    
+    ## update image lists
+    set global_list(input_list) [ lreplace $global_list(input_list) $index $index ]
+    set global_list(input_fname) [ lreplace $global_list(input_fname) $index $index ]
+    
+    ## disable remove button if no elements in the list 
+    if { [ llength $global_list(input_list) ] == 0 } {	
+	
+	$widget_list(input_buttonbox) buttonconfigure "remove" -state disabled	
+	$widget_list(input_buttonbox) buttonconfigure "display" -state disabled
+	$widget_list(input_frameno) configure -state disabled
+	
+	$this SetTitle $global_list(appname)
+	
+	set global_list(result_fpreffix) "preffix"
+	
+	$widget_list(computebtn) configure -state disabled
+	
+	## clear results
+	result_clear
+
+	[ $parent GetViewer ] UpdateDisplay
+    }    
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Add a b-value
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::addbvalue { } {
+
+    set index [ $widget_list(input_blist) curselection ]
+    
+    if { $index != "" } {
+
+        if { $global_list(input_curbvalue) != ""  } {        
+           
+          set global_list(input_blist) \
+              [ linsert $global_list(input_blist) $index $global_list(input_curbvalue) ]
+        }
+
+   } else {
+  
+        lappend global_list(input_blist) $global_list(input_curbvalue)
+
+   }
+     
+}
+ 
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Remove a selected b-value
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::removebvalue { } {
+
+    ## get current selection 
+    set index [ $widget_list(input_blist) curselection ]
+    
+    if { $index != "" } {
+	
+            set global_list(input_blist) [ lreplace $global_list(input_blist) $index $index ]
+
+    }
+	
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Show/hide antipodal points
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::gradient_showantipodal { } {        
+    $global_list(gradient_anti_actor) SetVisibility $global_list(gradient_showanti)
+    $widget_list(gradient_sphere) Update
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Search gradient list
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::gradient_searchlist { dir } {
+
+    set num [ llength $global_list(gradient_list) ]
+
+    for { set i 0 } { $i < $num } { incr i } {
+	set item [ lindex [lindex $global_list(gradient_list) $i ] 0]
+	if { $item == $dir } {
+	    return $i
+	}
+    }
+    
+    return 0
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Populate gradient list
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::gradient_populatelist { index } {
+
+    set vector_list [lindex [lindex $global_list(gradient_list) $index] 2]
+    set vector_length [ llength $vector_list ]
+
+    ## clear list 
+    $widget_list(gradient_list) clear
+    
+    set numpts [ $global_list(gradient_points) GetNumberOfPoints ]
+
+    ## reset number of points
+    if { $numpts > 0 } {
+	$global_list(gradient_points) Reset	
+    }
+    
+    $global_list(gradient_points) SetNumberOfPoints $vector_length
+    
+    set count 0
+
+    ## insert gradient vectors
+    foreach vector $vector_list {
+	scan $vector "%f %f %f" gx gy gz
+	$widget_list(gradient_list) insert end [format "% 2.5f % 2.5f % 2.5f" $gx $gy $gz]
+	$global_list(gradient_points) InsertPoint $count $gx $gy $gz 
+
+	incr count
+    }
+
+    ## update sphere
+    $global_list(gradient_polydata) SetPoints $global_list(gradient_points)
+    $global_list(gradient_polydata) SetNumberOfPoints $vector_length
+    $global_list(gradient_polydata) Modified
+    
+    ## update sphere
+    $widget_list(gradient_sphere) Update
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Check for colinearity
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::checkgradient { } {
+
+    set tol $global_list(gradient_tol)
+    set index [$widget_list(gradient_ndir) cget -clientdata]
+    set vector_list [lindex [lindex $global_list(gradient_list) $index] 2]
+    set vector_length [ llength $vector_list ]
+    
+    WatchOn
+    
+    set numcol 0
+    
+    ## check list
+    for { set i 0 } { $i < $vector_length } { incr i } {
+	set vector1 [ lindex $vector_list $i ]
+	scan $vector1 "%f %f %f" gx1 gy1 gz1
+	for { set j 0 } { $j < $vector_length } { incr j } {
+	    if { $i != $j } {
+		set vector2 [ lindex $vector_list $j ]
+		scan $vector2 "%f %f %f" gx2 gy2 gz2
+		if { [expr abs($gx1+$gx2)<$tol && abs($gy1+$gy2)<$tol && abs($gz1+$gz2)<$tol] } {
+		    puts "Pairs ($i) \[$gx1 $gy1 $gz1\] and ($j) \[$gx2 $gy2 $gz2\] are colinear!"
+		    incr numcol
+		}
+	    }
+	}
+    }
+
+    WatchOff
+
+    set numcol [ expr $numcol / 2 ]
+
+    if { $numcol > 0 } {
+	set ok [ tk_messageBox -type ok \
+		     -parent $basewidget -title "Colinearity check" \
+		     -message "This set of gradient directions\nhas $numcol colinear vectors!" \
+		     -icon info ]
+    } else {
+	set ok [ tk_messageBox -type ok \
+		     -parent $basewidget -title "Colinearity check" \
+		     -message "No colinear vectors were found." \
+		     -icon info ]
+	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Increment number of directions
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::gradient_increment_ndir { dir } {
+    
+    set max [expr [llength $global_list(gradient_list)] - 1 ]
+    set index [expr [$widget_list(gradient_ndir) cget -clientdata] + $dir ]
+
+    ## check for boundary values
+    if { $index < 0 } { set index 0 }
+    if { $index > $max } { set index $max }
+
+    ## Replace number
+    $widget_list(gradient_ndir1) delete 0 end
+    $widget_list(gradient_ndir1) insert 0 [lindex [lindex $global_list(gradient_list) $index] 1]
+    $widget_list(gradient_ndir1) configure -clientdata $index    
+    
+    ## Replace number - again
+    $widget_list(gradient_ndir) delete 0 end
+    $widget_list(gradient_ndir) insert 0 [lindex [lindex $global_list(gradient_list) $index] 1]
+    $widget_list(gradient_ndir) configure -clientdata $index    
+    
+    ## Record number of DW images the same as number of gradient directions
+    set global_list(input_dw) [lindex [lindex $global_list(gradient_list) $index] 0 ] 
+    
+    ## populate list of directions
+    gradient_populatelist $index
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load gradient list
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::loadgradient { } {
+
+    ## browse for filename
+    set fname  [tk_getOpenFile -title "Select file" -filetypes { {"Gradient directions" {.dat}} {"Text file" {*.txt}}} -initialdir $global_list(gradient_fdir) -parent $basewidget] 
+     
+    if { $fname != "" } {
+	
+	set global_list(gradient_fdir) [ file dirname $fname ]
+
+	## load gradients into memory
+	set result [ LoadGradient $fname ]
+	
+	if { $result == 0 } { 
+	    ::pxtclutil::Warning "Cannot read gradient file from $fname\n Bad File"
+	}	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load gradient list
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::LoadGradient { fname } {
+
+    ## check if file is ready for reading
+    if { [ string length $fname ] < 1 || [ file readable $fname ] == 0 } {
+	return 0
+    }
+    
+    ## open file for reading 
+    set fileid [open $fname r]
+    
+    ## clear current gradient directons
+    set global_list(gradient_list) ""
+
+    ## read in gradient vectors 
+    while { [ eof $fileid ] == 0 } {
+
+	## read line
+	gets $fileid line
+	
+	## skip any comments
+	while { [string index $line 0] == "\#"} {
+	    gets $fileid line
+	}
+
+	## attempt to read number of directions
+	set numdir $line
+	
+	if { [string is integer $numdir ] == 0 } break
+	if { $numdir < 3 } break 
+
+	## read in gradient directions
+	for {set i 0} { $i < $numdir } {incr i} {
+	    gets $fileid line
+	    lappend grad$numdir $line
+	} 
+
+	set gradname grad$numdir
+	eval "lappend global_list(gradient_list) \"$numdir $numdir {$$gradname} \""
+    }
+
+    ## close file
+    close $fileid
+
+    ## set default number of directions
+    $widget_list(gradient_ndir) delete 0 end
+    $widget_list(gradient_ndir) insert 0 [lindex [lindex $global_list(gradient_list) 0] 1]
+    $widget_list(gradient_ndir) configure -clientdata 0
+
+    ## set default number of directions
+    $widget_list(gradient_ndir1) delete 0 end
+    $widget_list(gradient_ndir1) insert 0 [lindex [lindex $global_list(gradient_list) 0] 1]
+    $widget_list(gradient_ndir1) configure -clientdata 0
+
+    set global_list(gradient_fname) $fname
+
+    ## populate list of directions
+    gradient_populatelist 0
+
+    ## Record number of DW images the same as number of gradient directions
+    set global_list(input_dw) [lindex [lindex $global_list(gradient_list) 0] 1 ] 
+
+    ## Enabled filename entry
+    $widget_list(gradient_fname) configure -state normal
+    
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in mask auto status
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::mask_autochanged_cb { } {
+    set state(0) disabled; set state(1) normal        
+    $widget_list(mask_load) buttonconfigure load -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_fname) configure -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_connected) configure -state $state($global_list(mask_auto))
+    $widget_list(mask_autothresh) configure -state $state($global_list(mask_auto))
+    $widget_list(mask_threshval) configure -state \
+	$state([expr $global_list(mask_auto) && $global_list(mask_autothresh)==0])
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in mask threshold auto status
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::mask_autothreshchanged_cb { } {
+    set state(0) disabled; set state(1) normal
+    $widget_list(mask_threshval) configure -state $state([expr 1 - $global_list(mask_autothresh)])
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load mask
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::loadmask { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select mask" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	set global_list(result_fmask) "*[ file extension $fname ]"
+	
+	## load mask into memory
+	LoadMask $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in mask image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::LoadMask { fname } {
+    
+    set MASK 1     
+    set mask [ lindex $global_list(result_list) $MASK ]
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in mask image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+
+     ## if mask not a unsigned char image, convert it
+    set scalar_type [ [ $ana GetOutput ] GetScalarType ]    
+
+    if { $scalar_type != 3 } {	
+	
+	set imcast [ vtkImageCast [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $imcast "Converting mask to unsigned char values..."
+	$imcast SetInput [ $ana GetOutput ]
+	$imcast SetOutputScalarTypeToUnsignedChar
+	$imcast ClampOverflowOn	
+	$imcast Update
+	
+    ## fixed on 11/1/04
+	$mask CopyImageHeader [ $ana GetImageHeader ]
+	$mask ShallowCopyImage [ $imcast GetOutput ]
+	
+	$imcast Delete
+	
+    } else {
+	
+	$mask SetFromAnalyzeSource $ana
+    }
+    
+    set global_list(mask_fname) $fname
+
+    WatchOff
+
+    $ana Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Set result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::SetResultPreffix { preffix } {
+    set global_list(result_fpreffix) $preffix
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Get result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::GetResultPreffix { } {
+    return $global_list(result_fpreffix)
+}
+
+itcl::body mpjmultibtensorutility::SetCurrentDirectory { fname } {
+    set global_list(result_fdir) $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Clear all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::ClearAllResults { } {
+    
+    foreach result $global_list(result_list) {
+	$result Clear
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::SaveAllResults { } {
+
+    foreach result $global_list(result_list) title $global_list(result_title) {
+	
+	set fname $global_list(result_fpreffix)
+	set fname "$fname[ lindex $title 1 ]"
+	
+	$result Save $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save single result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::SaveResult { index } {        
+
+    set fname $global_list(result_fpreffix)
+    set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]"
+
+    [lindex $global_list(result_list) $index] Save $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::saveallresults { } {
+
+    ## browse for directory    
+    set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+
+    if { $fdir != "" } {
+	
+	set global_list(result_fdir) $fdir
+	
+	foreach result $global_list(result_list) title $global_list(result_title) {
+	    
+	    set fname $global_list(result_fpreffix)
+	    set fname "$fname[ lindex $title 1 ]"
+	    
+	    $result Save [ file join $fdir $fname ]
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::saveresult { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(result_list) getcurselection ]
+    
+    if { $sel_item != "" } { 
+	
+	## browse for directory
+	set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+
+	if { $fdir != "" } {
+	    
+	    set global_list(result_fdir) $fdir
+
+	    foreach item $sel_item {
+		
+		set index [ $widget_list(result_list) index $item ]
+		set result [ lindex $global_list(result_list) $index ]
+		
+		set fname $global_list(result_fpreffix)
+		set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]"
+		
+		$result Save [ file join $fdir $fname ]		
+	    }	    
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::DisplayResult { index } {
+    $parent SetResultsFromObject \
+	[ [ lindex $global_list(result_list) $index ] GetThisPointer ] $this
+    $parent ShowWindow
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::displayresult { } {
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	set index [ $widget_list(result_list) index [lindex $sel_item 0] ]
+	set result [ lindex $global_list(result_list) $index ]
+
+	$this DisplayResult $index	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::result_clear { } {
+
+    for { set i 0 } { $i < [ llength $global_list(result_list) ] } { incr i } {	
+
+	set title [ lindex [ lindex $global_list(result_title) $i ] 0 ]	    
+
+	if { $title == "Anatomical mask" } {
+	    if { $global_list(mask_auto) } {
+		[ lindex $global_list(result_list) $i ] Clear
+	    }
+	} else { 
+	    [ lindex $global_list(result_list) $i ] Clear
+	}
+    }
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create baseline image
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::result_createbaseline { }  {
+    
+    set BASELINE 0
+    set MASK 1
+    set TENSOR 2
+    set MEAN 3
+    set ADC 4
+
+    ## the baseline repository
+    set baseline [ lindex $global_list(result_list) $BASELINE ]  
+    $baseline CopyImageHeader \
+	[ [ lindex $global_list(input_list) 0 ] GetImageHeader ]
+    
+    ## the mean image
+    set mean [ lindex $global_list(result_list) $MEAN ]  
+    $mean CopyImageHeader [ $baseline GetImageHeader ]
+        
+    set avg_filter1 [ vtkmpjFrameAverage [ pxvtable::vnewobj ] ]    
+    
+    $this SetFilterCallbacks $avg_filter1 "Extracting baseline image..."
+    
+    ## add images into average filter
+    set num [ llength $global_list(input_list) ]
+    
+    for { set i 0 } { $i < $num } { incr i } {
+	set input [ lindex $global_list(input_list) $i ]		
+	$avg_filter1 AddInput [ $input GetImage ]	
+    }
+    
+    ## compute average
+    $avg_filter1 Update
+
+    ##
+    ## Testing
+    $mean ShallowCopyImage [ $avg_filter1 GetOutput ]
+
+    ## count number of diffusion (b-value > 0)
+    ## and non-diffusion components (b-value == 0)
+    set input_dw 0
+    set input_ndw 0
+    foreach item $global_list(input_blist) {
+	if { $item > 0 } {
+		incr input_dw
+	    } else {
+		incr input_ndw
+	    }
+    }
+    
+    set global_list(input_ndw) $input_ndw
+    set global_list(input_dw) $input_dw
+
+    ##puts stderr "bvalues=0 ($input_ndw), bvalues>0 ($input_dw)"
+
+    ## get average diffusion components
+    set frm_filter [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $frm_filter "Extracting mean diffusion components..."
+    $frm_filter SetInput [ $avg_filter1 GetOutput ]
+    $frm_filter SetStartFrame $global_list(input_ndw)
+    $frm_filter SetEndFrame [expr $global_list(input_dw) + $global_list(input_ndw) - 1 ]
+    $frm_filter Update
+    
+    ## save average
+    #$mean ShallowCopyImage [ $frm_filter GetOutput ]
+
+    ## get rid off the filter
+    $frm_filter Delete
+    
+    ## if more than one nondiffusion image per series, average all them out too
+    if { $global_list(input_ndw) > 1 } {
+	
+	set avg_filter2 [ vtkmpjFrameAverage [ pxvtable::vnewobj ] ]
+	
+	for { set j 0 } { $j < $global_list(input_ndw) } { incr j } {
+	    
+	    set frm_filter [ vtkImageExtractComponents [ pxvtable::vnewobj ] ]
+	    $frm_filter SetInput [ $avg_filter1 GetOutput ]
+	    $frm_filter SetComponents $j
+	    $frm_filter Update
+	    
+	    $avg_filter2 AddInput [ $frm_filter GetOutput ]
+	    
+	    $frm_filter Delete
+	}
+	
+	## get average nondiffusion image
+	$avg_filter2 Update
+	
+	$baseline ShallowCopyImage [ $avg_filter2 GetOutput ]
+	
+	## discard filter
+	$avg_filter2 Delete
+	
+    } else {
+	
+	set frm_filter [ vtkImageExtractComponents [ pxvtable::vnewobj ] ]
+	$frm_filter SetInput [ $avg_filter1 GetOutput ]
+	$frm_filter SetComponents 0
+	$frm_filter Update
+	
+	$baseline ShallowCopyImage [ $frm_filter GetOutput ]
+	
+	## discard filter
+	$frm_filter Delete
+    }
+
+    ## get rid off mean filter
+    $avg_filter1 Delete
+
+    update idletasks
+
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create mask image
+#-------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::result_createmask { }  {
+
+    set BASELINE 0
+    set MASK 1
+    set TENSOR 2
+    set MEAN 3
+    set ADC 4
+    
+    ## get baseline image
+    set baseline [ lindex $global_list(result_list) $BASELINE ]
+    
+    ## determine threshold value    
+    if { $global_list(mask_autothresh) == 1 } {
+	
+	set hist [ vtkImageAccumulate [ pxvtable::vnewobj ] ]    
+	
+	$hist SetInput [ $baseline GetImage ]
+	$hist Update
+	
+	## determine threshold value
+	set min [ lindex [ $hist GetMin ] 0 ]
+	set max [ lindex [ $hist GetMax ] 0 ]
+	set global_list(mask_threshval) [ expr int($min + (($max - $min) * 0.04)) ]
+	
+	$hist Delete
+    }
+
+    update idletasks
+
+    ## threshold baseline image
+    set thresh [ vtkImageThreshold [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $thresh "Creating anatomical mask..."
+    $thresh SetInput [ $baseline GetImage ]
+    $thresh ThresholdByUpper $global_list(mask_threshval)
+    $thresh SetInValue 1
+    $thresh SetOutValue 0
+    $thresh SetOutputScalarTypeToUnsignedChar
+    $thresh Update
+    
+    set mask [ lindex $global_list(result_list) $MASK ]    
+    $mask CopyImageHeader \
+	[ [ lindex $global_list(result_list) $BASELINE ] GetImageHeader ]
+    
+    ## remove unconnected voxels
+    if { $global_list(mask_connected) == 1 } {
+	
+	set loc [ $parent cget -currentpoint ] 
+	scan $loc "%d %d %d" lx ly lz
+	if { $lx<=0 || $ly<=0 || $lz<=0 } {
+	    scan [ [$baseline GetImage] GetDimensions ] "%d %d %d" dx dy dz
+	    set lx [expr $dx / 2] 
+	    set ly [expr $dy / 2]
+	    set lz [expr $dz / 2]
+	}
+
+	set seedc [ vtkImageSeedConnectivity [ pxvtable::vnewobj ] ]
+	$seedc SetInput [ $thresh GetOutput ]
+	$seedc AddSeed $lx $ly $lz
+	$seedc SetInputConnectValue 1
+	$seedc SetOutputConnectedValue 1
+	$seedc SetOutputUnconnectedValue 0 
+	$seedc SetDimensionality 3
+	
+	SetFilterCallbacks $seedc "Tracing connectivity..."
+	$seedc Update	
+	
+	$mask ShallowCopyImage [ $seedc GetOutput ] 	
+
+    } else {
+	
+	$mask ShallowCopyImage [ $thresh GetOutput ] 
+    }
+    
+    set global_list(mask_fname) " "
+    
+    $thresh Delete
+    
+    update idletasks
+    
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create tensor image
+#-------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::result_createadc { } {
+
+    set BASELINE 0
+    set MASK 1
+    set TENSOR 2
+    set MEAN 3
+    set ADC 4
+    
+    set baseline [ lindex $global_list(result_list) $BASELINE ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set mean [ lindex $global_list(result_list) $MEAN ]
+    set adc [ lindex $global_list(result_list) $ADC ]
+    $adc CopyImageHeader [ [ lindex $global_list(result_list) $BASELINE ] GetImageHeader ]
+    
+    set adc_filter [ vtkmpjApparentDiffusion [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $adc_filter "Computing apparent diffusion coefficient..."
+    $adc_filter SetInput [ $mean GetImage ]
+    $adc_filter SetBaseline [ $baseline GetImage ]
+    $adc_filter SetMask [ $mask GetImage ]
+    if { $global_list(input_bfactorenable) == 1 } {
+	$adc_filter SetbValue $global_list(input_bfactor)
+    } else {
+	$adc_filter SetbValue 1.0
+    }
+    
+    $adc_filter SetShift 1E-12
+    $adc_filter Update
+    
+    $adc ShallowCopyImage [ $adc_filter GetOutput ]
+    
+    $adc_filter Delete
+    
+    update idletasks   
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create tensor image
+#-------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::result_createtensor { }  {
+    
+    set BASELINE 0
+    set MASK 1
+    set TENSOR 2
+    set MEAN 3
+    set ADC 4
+    
+    set baseline [ lindex $global_list(result_list) $BASELINE ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set mean [ lindex $global_list(result_list) $MEAN ]
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    $tensor CopyImageHeader \
+	[ [ lindex $global_list(result_list) $BASELINE ] GetImageHeader ]
+    
+    set index [ $widget_list(gradient_ndir) cget -clientdata ]
+    set table [ lindex [ lindex $global_list(gradient_list) $index ] 2 ]
+
+    ## populate the b list of values
+    set bvalues [ vtkDoubleArray [ pxvtable::vnewobj ] ]
+    
+    set count 0
+    for { set i 0 } { $i < [llength $global_list(input_blist)] } { incr i } {
+
+        set btuple [ lindex $global_list(input_blist) $i ]
+
+        if { $btuple == 0 } {	    
+	    $bvalues InsertTuple1 $count $btuple
+            ##puts "$btuple"
+	    incr count
+	} else {
+	    ## b-factor > 0
+	    for { set j 0 } { $j < [llength $table] } { incr j } {
+
+		$bvalues InsertTuple1 $count $btuple
+                ##puts "$btuple"
+		incr count
+	    }
+	}           
+    }
+    
+    ## populate the gradient direction array
+    set gradients [ vtkDoubleArray [ pxvtable::vnewobj ] ]
+    $gradients SetNumberOfComponents 3
+    $gradients SetNumberOfTuples [ llength $table ]
+    
+    set flipx [ expr $global_list(tensor_flipx) > 0 ? -1 : 1 ]
+    set flipy [ expr $global_list(tensor_flipy) > 0 ? -1 : 1 ]
+    set flipz [ expr $global_list(tensor_flipz) > 0 ? -1 : 1 ]
+    
+    set gx 0; set gy 0; set gz 0;
+    
+    for {set i 0} {$i < [llength $table]} {incr i} {
+	
+	set tuple [ lindex $table $i ]
+	
+	if { $global_list(tensor_swap) == 1 } {
+	    if { $global_list(tensor_swapdir) == 1 } {
+		set gx [expr [lindex $tuple 1] * $flipy ]
+		set gy [expr [lindex $tuple 0] * $flipx ]
+		set gz [expr [lindex $tuple 2] * $flipz ]
+	    }
+	    if { $global_list(tensor_swapdir) == 2 } {
+		set gx [expr [lindex $tuple 2] * $flipz ]
+		set gy [expr [lindex $tuple 1] * $flipy ]
+		set gz [expr [lindex $tuple 0] * $flipx ]
+	    }
+	    if { $global_list(tensor_swapdir) == 3 } {
+		set gx [expr [lindex $tuple 0] * $flipx ]
+		set gy [expr [lindex $tuple 2] * $flipz ]
+		set gz [expr [lindex $tuple 1] * $flipy ]
+	    }	   
+	} else {
+	    set gx [expr [lindex $tuple 0] * $flipx ]
+	    set gy [expr [lindex $tuple 1] * $flipy ]
+	    set gz [expr [lindex $tuple 2] * $flipz ]
+	}
+	
+	#if { $global_list(tensor_swapyz) > 0 } {
+	#	    set gx [expr [lindex $tuple 0] * $flipx ]
+	#	    set gy [expr [lindex $tuple 2] * $flipz ]
+	#	    set gz [expr [lindex $tuple 1] * $flipy ]
+	#	} elseif { $global_list(tensor_swapxz) > 0 } {
+	#	    set gx [expr [lindex $tuple 2] * $flipz ]
+	#	    set gy [expr [lindex $tuple 1] * $flipy ]
+	#	    set gz [expr [lindex $tuple 0] * $flipx ]
+	#	} else {
+	#	    set gx [expr [lindex $tuple 0] * $flipx ]
+	#	    set gy [expr [lindex $tuple 1] * $flipy ]
+	#	    set gz [expr [lindex $tuple 2] * $flipz ]
+	#	}
+		
+	$gradients SetTuple3 $i $gx $gy $gz
+    }
+ 
+    set baseline [ lindex $global_list(result_list) $BASELINE ]
+    set mask [ lindex $global_list(result_list) $MASK ]   
+
+    ## compute tensor
+    set tensor_filter [ vtkmpjTensorBMatrixLeastSquares [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $tensor_filter "Computing diffusion tensor..."
+    $tensor_filter SetGradients $gradients
+    $tensor_filter SetNumberOfDirections [ $gradients GetNumberOfTuples ]
+    $tensor_filter SetInput [ $mean GetImage ]   
+    $tensor_filter SetBaseline [ $baseline GetImage ]
+    $tensor_filter SetbValues $bvalues
+    $tensor_filter SetMask [ $mask GetImage ]
+    #if { $global_list(input_bfactorenable) == 1 } {
+	#$tensor_filter SetbValue $global_list(input_bfactor) 
+    #} else {
+	#$tensor_filter SetbValue 1.0
+    #}
+    $tensor_filter SetSymmetricTensor $global_list(input_tensorsymm)
+    
+    $gradients Delete
+    
+    ## compute tensor
+    $tensor_filter Update
+    
+    if { $global_list(tensor_rotation) == 1 } {
+	
+	## rotate tensor
+	set tensor_xform [ vtkmpjImageTensorTransform [ pxvtable::vnewobj ] ]
+	$tensor_xform SetInput [ $tensor_filter GetOutput ]
+	$tensor_xform SetRotation $global_list(tensor_rotx) $global_list(tensor_roty) $global_list(tensor_rotz) 
+	$this SetFilterCallbacks $tensor_xform "Transforming tensor..."
+	
+	# rotate tensor
+	$tensor_xform Update
+	
+	$tensor ShallowCopyImage [ $tensor_xform GetOutput ]
+	
+	$tensor_xform Delete
+
+    } else {	
+	
+	$tensor ShallowCopyImage [ $tensor_filter GetOutput ]
+	
+    }
+
+    $tensor_filter Delete
+
+    update idletasks   
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Compute results
+# -----------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::ComputeResults { } {
+
+    set BASELINE 0
+    set MASK 1
+    set TENSOR 2
+    set MEAN 3
+    set ADC 4
+
+    WatchOn
+    
+    ## clear results
+    result_clear
+    
+    ## create baseline image
+    set result [ result_createbaseline ]
+    
+    if { $result == 0 } {
+	WatchOff; return
+    }
+    
+    ## create mask if not loaded in
+    if { $global_list(mask_auto) } {
+	
+	set result [ result_createmask ]
+	
+	if { $result == 0 } {
+	    WatchOff; return
+	}
+    }
+
+    ## create adc
+    if { $global_list(adc_compute) } {	
+	set result [ result_createadc ]   
+    } 
+    
+    ## create tensor 
+    set result [ result_createtensor ]
+    
+    if { $result == 0 } {
+	WatchOff; return
+    }
+    
+    set tensor_map [ lindex $global_list(result_list) $TENSOR ]
+    $parent SetResultsFromObject [ $tensor_map GetThisPointer ] $this
+    
+    $widget_list(notebook) view "Results"; update
+    
+    WatchOff
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create diffusion input control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::CreateInputControl { base } {      
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Diffusion-weighted images and b-values (s/mm^2)"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+   
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t -side top
+
+    set subframe0left [ frame $subframe0.subframeleft ]
+    pack $subframe0left -side left -fill both -expand t -padx 0
+
+    iwidgets::scrolledlistbox $subframe0left.inputlist \
+	-hscrollmode dynamic \
+	-visibleitems 30x10 \
+	-listvariable [ itcl::scope global_list(input_fname) ] \
+	-selectmode extended \
+	-selectioncommand [ itcl::code $this input_selectioncommand_cb ]    
+    pack $subframe0left.inputlist -side left -fill both -expand t -padx 2 -pady 2
+    set widget_list(input_list) $subframe0left.inputlist
+
+    set subframe0right [ frame $subframe0.subframeright ]
+    pack $subframe0right -side right -fill y -expand f -padx 0
+
+#    iwidgets::scrolledlistbox $subframe0right.bvaluelist 
+    set bvaluelist [ listbox $subframe0right.bvaluelist \
+                         -listvariable [ itcl::scope global_list(input_blist) ] ]
+    pack $bvaluelist -side top -fill both -expand t -padx 2 -pady 2    
+    set widget_list(input_blist) $subframe0right.bvaluelist
+
+    button $subframe0right.addbvalue -text "+" -command [ itcl::code $this addbvalue ]
+    pack $subframe0right.addbvalue -side left -padx 2 -pady 2
+
+
+    iwidgets::entryfield $subframe0right.bvalcur \
+	-width 5 \
+        -labeltext "b:" \
+	-validate numeric \
+	-textvariable [ itcl::scope global_list(input_curbvalue) ]
+    pack $subframe0right.bvalcur -side left -pady 2
+
+    button $subframe0right.removebvalue -text "-" -command [ itcl::code $this removebvalue ] 
+    pack $subframe0right.removebvalue -side left -padx 2 -pady 2
+
+    
+#    set inputbbox [ iwidgets::buttonbox $subframe0right.input -orient vertical ]
+#    $inputbbox add add -text "Add..." -command [ itcl::code $this addinput ]
+#    $inputbbox add remove -text "Remove" -command [ itcl::code $this removeinput ] -state disabled
+#    $inputbbox add display -text "Display" -command [ itcl::code $this displayinput ] -state disabled   
+#    pack $inputbbox -side top -fill x -expand f -padx 0
+#    set widget_list(input_buttonbox) $inputbbox    
+      
+#    iwidgets::spinint $subframe0right.input_dispframe -labeltext "Frame:"  \
+#	-fixed 2 -width 3 -step 1 -range {0 100} -state disabled \
+#	-textvariable [ itcl::scope global_list(input_frameno) ] 
+#    pack $subframe0right.input_dispframe -side top -padx 5 -pady 0
+#    set widget_list(input_frameno) $subframe0right.input_dispframe     
+    
+#    set tensorsymm [ checkbutton $subframe0right.tensor_symm \
+#			 -text "Symmetric" \
+#			 -variable [ itcl::scope global_list(input_tensorsymm) ] ]
+#    pack $tensorsymm -side top -padx 5 -pady 10
+#    set widget_list(tensorsymm) $subframe0right.tensorsymm
+
+#    set computeadc [ checkbutton $subframe0right.computeadc \
+#			 -text "Compute ADC" \
+#			 -variable [ itcl::scope global_list(adc_compute) ] ]
+#    pack $computeadc -side top -padx 5 -pady 5
+    
+
+    set subframe3 [ frame $frame0.subframe3 ]
+    pack $subframe3 -side top -fill x -expand f
+
+    set inputbbox [ iwidgets::buttonbox $subframe3.inputbbox -orient horizontal ]
+    $inputbbox add add -text "Add..." -command [ itcl::code $this addinput ]
+    $inputbbox add remove -text "Remove" -command [ itcl::code $this removeinput ] -state disabled
+    $inputbbox add display -text "Display" -command [ itcl::code $this displayinput ] -state disabled   
+    pack $inputbbox -side left -fill both -expand f -padx 0
+    set widget_list(input_buttonbox) $inputbbox     
+
+    iwidgets::spinint $subframe3.input_dispframe -labeltext "Frame:"  \
+	-fixed 2 -width 3 -step 1 -range {0 100} -state disabled \
+	-textvariable [ itcl::scope global_list(input_frameno) ] 
+    pack $subframe3.input_dispframe -side left -padx 5 -pady 2
+    set widget_list(input_frameno) $subframe3.input_dispframe        
+       
+
+
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill x -expand f
+     
+#    iwidgets::spinint $subframe1.input_ndw -labeltext "Number of T2 images:" \
+#	-fixed 2 -width 3 -step 1 -range {1 10} \
+#	-textvariable [ itcl::scope global_list(input_ndw) ]
+#
+#    pack $subframe1.input_ndw -side left -padx 5 -pady 5  
+#    set widget_list(input_ndw) $frame0.input_ndw
+#    $subframe1.input_ndw up
+
+    set gradient_ndir1 [ iwidgets::spinner $subframe1.gradient_ndir1 \
+			    -labeltext "Set of gradient directions:" \
+			    -width 6 \
+			    -clientdata 0 \
+			    -decrement [itcl::code $this gradient_increment_ndir -1 ] \
+			    -increment [itcl::code $this gradient_increment_ndir +1 ] ]
+    pack $gradient_ndir1 -side left -padx 5
+    set widget_list(gradient_ndir1) $gradient_ndir1       
+    $gradient_ndir1 clear
+    $gradient_ndir1 insert 0 "ME6" 
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill x -expand f
+    
+    set widget_list(computebtn) [ button $subframe2.compute -text "Compute!" \
+				      -state disabled \
+				      -command [ itcl::code $this ComputeResults ] ]    
+    pack $subframe2.compute -side left -fill x -padx 5 -pady 10    
+
+
+#    iwidgets::entryfield $subframe2.input_bfactor \
+#	-width 6 \
+#	-validate real \
+#	-textvariable [ itcl::scope global_list(input_bfactor) ]
+#    pack $subframe2.input_bfactor -side right -padx 5 -pady 5  
+
+#
+#    checkbutton $subframe2.input_bfactorenable \
+#	-text "b-value (s/mm^2):" \
+#	-variable [ itcl::scope global_list(input_bfactorenable) ]
+#    pack $subframe2.input_bfactorenable -side right -padx 2 -pady 5
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create gradient control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::CreateGradientControl { base } {   
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Diffusion gradient directions "
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand f
+
+    ## create gradient file gadget
+    set gradient_fname [ iwidgets::entryfield $subframe0.gradient_fname -state disabled \
+			     -labeltext "Filename:"  \
+			     -textvariable [ itcl::scope global_list(gradient_fname) ] ]
+    pack $gradient_fname -side left -expand t -fill x -padx 5 -pady 0
+    set widget_list(gradient_fname) $gradient_fname
+    
+    set gradient_load [ iwidgets::buttonbox $subframe0.gradient_load -orient horizontal -padx 2 -pady 2 ]
+    $gradient_load add load -text "Load..." -command [ itcl::code $this loadgradient ]
+    pack $gradient_load -side left -fill x -pady 0
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -pady 0
+
+    set gradient_ndir [ iwidgets::spinner $subframe1.gradient_ndir \
+			    -labeltext "Set of directions:" \
+			    -width 6 \
+			    -clientdata 0 \
+			    -decrement [itcl::code $this gradient_increment_ndir -1 ] \
+			    -increment [itcl::code $this gradient_increment_ndir +1 ] ]
+    pack $gradient_ndir -side left -padx 5 -pady 0
+    set widget_list(gradient_ndir) $gradient_ndir
+
+    set gradient_check [ iwidgets::buttonbox $subframe1.gradient_check -orient horizontal -padx 2 -pady 2]
+    $gradient_check add load -text "Check" -command [ itcl::code $this checkgradient ]
+    pack $gradient_check -side right -fill x -pady 0
+ 
+    iwidgets::entryfield $subframe1.gradient_tol \
+	-width 5 \
+	-validate real \
+	-labeltext "Colinearity tolerance:" \
+	-textvariable [ itcl::scope global_list(gradient_tol) ]
+    pack $subframe1.gradient_tol -side right -fill x -pady 5
+    
+    set subframe15 [ frame $frame0.subframe15 ]
+    pack $subframe15 -fill both -side top -expand f
+    
+    set subframe15l [ frame $subframe15.subframe15l ]
+    pack $subframe15l -fill both -side left -expand f
+
+    set subframe15r [ frame $subframe15.subframe15r ]
+    pack $subframe15r -fill both -side left -expand t
+    
+    ## initialize number of directions
+    $gradient_ndir clear
+    $gradient_ndir insert 0 "ME6"
+    
+    ## create list box 
+    set gradient_list [ iwidgets::scrolledlistbox $subframe15l.gradient_list -visibleitems 42x15 -textfont {fixed 8} ]
+    pack $gradient_list -side left -expand f -fill both -pady 0 -padx 2    
+    set widget_list(gradient_list) $gradient_list
+    
+    set grad_showanti [ checkbutton $subframe15r.grad_showanti \
+			    -text "Show antipodal directions" \
+			    -command [itcl::code $this gradient_showantipodal ] \
+			    -variable [ itcl::scope global_list(gradient_showanti) ] ]
+    pack $grad_showanti -side top -anchor w -padx 5 -pady 2         
+    
+    ## create gradient points
+    set grad_mapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    $grad_mapper SetResolveCoincidentTopologyToPolygonOffset
+    $grad_mapper SetInput [ $global_list(gradient_polydata) GetOutput ]
+    $global_list(gradient_actor) SetMapper $grad_mapper
+    $global_list(gradient_anti_actor) SetVisibility $global_list(gradient_showanti)
+    $global_list(gradient_anti_actor) SetMapper $grad_mapper
+    $global_list(gradient_anti_actor) SetScale -1 -1 -1
+    $grad_mapper Delete
+            
+    ## create gradient sphere
+    set grad_sphere [ mpjguisphere \#auto 0 ]
+    $grad_sphere Resize 150 150
+    $grad_sphere Initialize $subframe15r
+    pack forget [ $grad_sphere GetButtonBoxWidget ]
+    pack forget [ $grad_sphere GetPropertyWidget ] 
+    [ [ $grad_sphere GetWireframeActor ] GetProperty ] SetColor 0.5 0.5 0.5
+    [ [ $grad_sphere GetWireframeActor ] GetProperty ] SetLineWidth 1.0
+    [ [ $grad_sphere GetWireframeActor ] GetProperty ] SetOpacity 0.05
+    $grad_sphere SetResolution 20
+    $grad_sphere AddActor $global_list(gradient_actor)
+    $grad_sphere AddActor $global_list(gradient_anti_actor)
+    $grad_sphere Update
+    $grad_sphere Show
+    
+    set widget_list(gradient_sphere) $grad_sphere   
+
+    ## populate list of directions
+    gradient_populatelist 0    
+    
+ 
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -fill both -expand t
+   
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create input mask control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::CreateMaskControl { base } {        
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Mask image (Anatomy)"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -side top -fill both -expand f -pady 5
+    
+    set mask_auto [ checkbutton $subframe0.mask_auto \
+			-text "Compute from unweighted diffusion series (T2 images)" \
+			-variable [ itcl::scope global_list(mask_auto) ] \
+			-command [ itcl::code $this mask_autochanged_cb ] ]
+    pack $mask_auto -side left -fill both -padx 5 -pady 2
+
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+  
+    set mask_fname [ iwidgets::entryfield $subframe1.mask_fname \
+			 -textvariable [ itcl::scope global_list(mask_fname) ] \
+			 -state disabled -labeltext "Filename:" ] 
+    pack $mask_fname -side left -expand t -fill x -padx 5 -pady 2
+    set widget_list(mask_fname) $mask_fname
+
+    set mask_load [ iwidgets::buttonbox $subframe1.mask_load -orient horizontal -padx 2 ]
+    $mask_load add load -text "Load..." -command [ itcl::code $this loadmask ] -state disabled
+    pack $mask_load -side left -fill x -pady 2
+    set widget_list(mask_load) $mask_load
+    
+    set subframe3 [ frame $frame0.subframe3 ]
+    pack $subframe3 -side top -fill both -expand f -padx 2
+
+    set mask_autothresh [ checkbutton $subframe3.mask_autothresh \
+			      -text "Auto-threshold" \
+			      -variable [ itcl::scope global_list(mask_autothresh) ] \
+			      -command [ itcl::code $this mask_autothreshchanged_cb ] ]    
+    pack $mask_autothresh -side left -padx 5 -pady 4
+    set widget_list(mask_autothresh) $mask_autothresh
+    
+    set mask_threshval [ iwidgets::spinint $subframe3.mask_threshval \
+			     -labeltext "Threshold value for T2 image:" \
+			     -fixed 5 -width 5 -range {1 10000} -step 1 \
+			     -textvariable [ itcl::scope global_list(mask_threshval) ] \
+			     -state disabled ]
+    pack $mask_threshval -side right -pady 5 -padx 10
+    set widget_list(mask_threshval) $mask_threshval
+    
+    set subframe4 [ frame $frame0.subframe4 ]
+    pack $subframe4 -side top -fill both -expand f -padx 2
+    
+    set mask_connected [ checkbutton $subframe4.mask_connected -text "Trace connectivity" \
+			     -variable [ itcl::scope global_list(mask_connected) ] ]    
+    pack $mask_connected -side left -pady 5 -padx 4       
+    set widget_list(mask_connected) $mask_connected
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create transform control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::CreateTransformControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Tensor transformation"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -fill both -expand f -padx 5 -pady 5
+        
+    set tensorflipx [ checkbutton $subframe2.tensorflipx \
+			  -text "Flip X" \
+			  -variable [ itcl::scope global_list(tensor_flipx) ] ]
+    pack $tensorflipx -side left -padx 5 -pady 2
+    set widget_list(tensor_flipx) $tensorflipx
+    
+    set tensorflipy [ checkbutton $subframe2.tensorflipy \
+			  -text "Flip Y" \
+			  -variable [ itcl::scope global_list(tensor_flipy) ] ]
+    pack $tensorflipy -side left -padx 5 -pady 2
+    set widget_list(tensor_flipy) $tensorflipy   
+    
+    set tensorflipz [ checkbutton $subframe2.tensorflipz \
+			  -text "Flip Z" \
+			  -variable [ itcl::scope global_list(tensor_flipz) ] ]
+    pack $tensorflipz -side left -padx 5 -pady 2
+    set widget_list(tensor_flipz) $tensorflipz
+
+
+    set subframe3 [ frame $frame0.subframe3 ]
+    pack $subframe3 -fill both -expand f -padx 5 -pady 5
+    
+    set tensor_swap [ checkbutton $subframe3.tensor_swap \
+			  -text "Swap axes" \
+			  -variable [ itcl::scope global_list(tensor_swap) ] ]
+    pack $tensor_swap -side left -padx 5 -pady 4
+    set widget_list(tensor_swap) $tensor_swap
+
+    set tensorswapxy [ radiobutton $subframe3.tensorswapxy \
+			   -text "Swap X-Y" \
+			   -value 1 \
+			   -variable [ itcl::scope global_list(tensor_swapdir) ] ]
+    pack $tensorswapxy -side left -padx 5 -pady 2
+    set widget_list(tensor_swapxy) $tensorswapxy
+
+    set tensorswapxz [ radiobutton $subframe3.tensorswapxz \
+			   -text "Swap X-Z" \
+			   -value 2 \
+			   -variable [ itcl::scope global_list(tensor_swapdir) ] ]
+    pack $tensorswapxz -side left -padx 5 -pady 2
+    set widget_list(tensor_swapxz) $tensorswapxz
+
+    set tensorswapyz [ radiobutton $subframe3.tensorswapyz \
+			   -text "Swap Y-Z" \
+			   -value 3 \
+			   -variable [ itcl::scope global_list(tensor_swapdir) ] ]
+    pack $tensorswapyz -side left -padx 5 -pady 2
+    set widget_list(tensor_swapyz) $tensorswapyz
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill x -expand f -padx 5 -pady 5
+
+    set tensor_rotation [ checkbutton $subframe0.tensor_rotation \
+			      -text "Rotate tensor" \
+			      -variable [ itcl::scope global_list(tensor_rotation) ] ]
+    pack $tensor_rotation -side left -padx 5 -pady 4
+    set widget_list(tensor_rotation) $tensor_rotation
+
+    iwidgets::entryfield $subframe0.tensor_rotx \
+	-width 5 \
+	-validate real \
+	-labeltext "Rx:" \
+	-textvariable [ itcl::scope global_list(tensor_rotx) ]
+    pack $subframe0.tensor_rotx -side left -fill x -pady 5
+    
+    iwidgets::entryfield $subframe0.tensor_roty \
+	-width 5 \
+	-validate real \
+	-labeltext "Ry:" \
+	-textvariable [ itcl::scope global_list(tensor_roty) ]
+    pack $subframe0.tensor_roty -side left -fill x -pady 5
+    
+    iwidgets::entryfield $subframe0.tensor_rotz \
+	-width 5 \
+	-validate real \
+	-labeltext "Rz:" \
+	-textvariable [ itcl::scope global_list(tensor_rotz) ]
+    pack $subframe0.tensor_rotz -side left -fill x -pady 5
+
+    label $subframe0.dummy -text "degrees"
+    pack $subframe0.dummy -side left
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create results control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::CreateResultsControl { base } {   
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Results"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+    
+    iwidgets::scrolledlistbox $subframe0.resultlist \
+	-hscrollmode dynamic \
+	-selectmode extended \
+	-visibleitems 40x10 
+    
+    pack $subframe0.resultlist -side left -fill both -expand t -padx 2 -pady 2
+    set widget_list(result_list) $subframe0.resultlist
+    
+    foreach item $global_list(result_title) {
+	$widget_list(result_list) insert end [lindex $item 0]
+    }
+    
+    set subframe1 [ frame $subframe0.subframe1 ]
+    pack $subframe1 -side right -fill both -padx 0
+    
+    set resultbbox [ iwidgets::buttonbox $subframe1.input -orient vertical ]
+    $resultbbox add display -text "Display" -command [ itcl::code $this displayresult ]
+    $resultbbox add save -text "Save..." -command [ itcl::code $this saveresult ]
+    $resultbbox add saveall -text "Save all" -command [ itcl::code $this saveallresults ]    
+    pack $resultbbox -side top -fill x -expand t -padx 0
+    set widget_list(result_buttonbox) $resultbbox
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill x -padx 2 -pady 5
+
+    set result_fpreffix [ iwidgets::entryfield $subframe2.result_fpreffix \
+			      -textvariable [ itcl::scope global_list(result_fpreffix) ] \
+			      -labeltext "Preffix:" ]
+    pack $result_fpreffix -side left -expand t -fill x -padx 5 -pady 2
+    set widget_list(result_fpreffix) $result_fpreffix    
+}
+
+# -------------------------------------------------------------------------------------------
+#  Diffusion control inititialization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::Initialize { widget } {
+    
+    if { $initialized == 1 } { return $basewidget }
+    
+    #  -------------------------------------
+    #  Create User Interface
+    #  -------------------------------------	
+    set basewidget [toplevel $widget ]
+    wm geometry $basewidget 600x480
+    wm withdraw $basewidget
+    
+    set notebook $basewidget.notebook    
+    iwidgets::tabnotebook $notebook -tabpos w         
+    set widget_list(notebook) $notebook
+
+    set mb [ frame $basewidget.mb ]
+    pack $mb -side top -fill x -expand false
+    
+    CreateMenu $mb
+    
+    CreateInputControl        [ $notebook add -label "Diffusion" ]
+    CreateMaskControl         [ $notebook add -label "Mask" ]    
+    CreateGradientControl     [ $notebook add -label "Gradients" ]
+    CreateTransformControl    [ $notebook add -label "Transform" ]
+    CreateResultsControl      [ $notebook add -label "Results" ] 
+
+    pack $notebook -side top -fill both -expand t -padx 5
+    $notebook view "Diffusion"
+
+    set bottom [ frame $basewidget.bottom -relief ridge]
+    pack $bottom -side top -fill x -expand false
+    
+    set pbar [ frame $basewidget.pbar -width 400 -height 20 ]
+    pack $pbar -side bottom -expand f -fill x
+    CreateProgressBar $pbar
+    
+    set w [ frame $basewidget.w -relief ridge -width 800 ]
+    pack $w -side bottom -fill x -expand false
+    
+    eval "button $w.close -text Close -command { $this DismissWindow }"
+
+    pack $w.close -side right -fill x -padx 5 -pady 10
+    
+    set initialized 1
+
+    SetTitle $appname
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { $this DismissWindow }"
+
+    return $basewidget 
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create top level menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::CreateMenu { mb } {    
+    
+    menubutton $mb.file          -text Setup       -menu $mb.file.m -underline 0
+     pack $mb.file $mb.file    -side left
+    menubutton $mb.results       -text Results     -menu $mb.results.m -underline 0
+    pack $mb.file $mb.results    -side left
+    menubutton $mb.help      -text Help         -menu $mb.help.m -underline 0 -padx 4
+    pack $mb.help  -side right
+
+    
+    menu $mb.file.m -tearoff 0 
+    eval "$mb.file.m add command -label \"Load Setup\" -command { $this LoadSetup \"\" } -underline 0 "
+    eval "$mb.file.m add command -label \"Save Setup\" -command { $this SaveSetup \"\" } -underline 0"
+    $mb.file.m add separator
+    if { $parent == 0 } {
+	eval "$mb.file.m add command -label Exit -command {  pxtkexit } -underline 1"
+    } else {
+	eval "$mb.file.m add command -label Close -command {  $this HideWindow } -underline 1"
+    }
+
+    menu $mb.results.m -tearoff 0 
+    eval "$mb.results.m add command -label \"Compute All\" -command { $this ComputeResults } -underline 0 -state disabled"
+    $mb.results.m add command -label "Save All Results" -command [ itcl::code $this saveallresults ] -underline 0
+
+    menu $mb.help.m -tearoff 0
+
+    set widget_list(menu_results) $mb.results.m    
+
+    eval "$mb.help.m add command -label About -command { $this AboutCommand }"
+}
+
+#-------------------------------------------------------------------------------------------
+#  Add controls to menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjmultibtensorutility::AddToMenuButton { mb args } {
+    eval "$mb add command -label \"Multi-b Tensor utility\" -command {$this ShowWindow \"Diffusion\"}"
+}
+
+#-------------------------------------------------------------------------------------------
+#  Main function for stand-alone execution
+# ------------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    puts "\n[ file rootname $argv0 ] is not a stand-alone program.\n"
+    exit
+}
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjmultiimagegui.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjmultiimagegui.tcl
new file mode 100644
index 0000000..b7a5036
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjmultiimagegui.tcl
@@ -0,0 +1,118 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide mpjmultiimagegui 1.0
+
+package require pxitclimage 1.0
+
+
+
+
+
+# ----------------------------------------------------------
+#  GUI for multiple image object
+# ----------------------------------------------------------
+itcl::class mpjmultiimageGUI {
+
+    inherit mpjmultiobjectGUI
+
+    constructor { } {
+	mpjmultiobjectGUI::constructor
+    } {
+    }
+    
+    destructor { }
+    
+    public    method Initialize { basewidg } 
+
+    public    method AddImage { descr }
+    public    method SetImage { index } 
+    public    method GetImage { index } { return [ GetObject $index ] }
+    public    method GetCurSelection { } 
+    public    method DeleteImage { index } { DeleteObject $index }
+
+    public    method SetDisplayCommand { cmd }
+
+    protected method CreateNewObject { }
+    protected method CreateNewObjectGUI { widget }
+
+}
+
+# ----------------------------------------------------------
+itcl::body mpjmultiimageGUI::CreateNewObject { } {
+
+    return  [ [  pxitclimage \#auto ] GetThisPointer ]
+}
+
+itcl::body mpjmultiimageGUI::CreateNewObjectGUI { widget } {
+    set itclimageGUI [ [ pxitclimageGUI \#auto ] GetThisPointer ]
+    pack [ $itclimageGUI Initialize $widget.[ pxvtable::vnewobj ] ] -side left -fill x
+    return $itclimageGUI
+}
+
+itcl::body mpjmultiimageGUI::AddImage { descr } {
+    
+    set newobj [ $this AddObject $descr ]
+    $this SetImage [ expr [ llength $itclobjectlist ] -1 ]    
+    return $newobj
+}
+
+itcl::body mpjmultiimageGUI::SetImage { index } {
+
+    $this SetObject $index
+    $objectGUI configure -description [ $listwidget get $currentobject ]
+    $objectGUI Update
+}
+
+itcl::body mpjmultiimageGUI::SetDisplayCommand { cmd } {
+    $objectGUI configure -displaycommand $cmd
+}
+
+itcl::body mpjmultiimageGUI::GetCurSelection { } {    
+    return [ $listwidget index [ $listwidget get ]]
+}
+
+itcl::body mpjmultiimageGUI::Initialize { basewidg } {
+    
+    if { $initialized == 1 } { 
+	return $basewidget 
+    }
+    
+    mpjmultiobjectGUI::Initialize $basewidg
+
+    #$listbox configure -selectmode single
+    $listwidget configure -command [itcl::code $this SetImage -1]
+    
+    set initialized 1
+    
+    return $basewidget
+}
+ 
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjmultiobjectgui.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjmultiobjectgui.tcl
new file mode 100644
index 0000000..0595a05
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjmultiobjectgui.tcl
@@ -0,0 +1,185 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide mpjmultiobjectgui 1.0
+
+package require pxitclobject 1.0
+
+
+
+
+
+# --------------------------------------------------------------
+#  abstract base GUI Class for mpjmultiimageGUI
+# --------------------------------------------------------------
+
+itcl::class mpjmultiobjectGUI {
+
+    public    variable  itclobjectlist "" 
+    public    variable  currentobject -1
+    protected variable  objectGUI 0
+    protected variable  basewidget  0
+    protected variable  initialized 0
+    private   common    thisparam
+    public    variable  description "Object"
+    public    variable  callback 0
+    public    variable  listwidget 0
+
+    constructor { } {
+    }
+    
+    destructor {
+	set l [ llength $itclobjectlist ]
+	for { set a 0 } { $a < $l } { incr a } {
+	    catch { itcl::delete object [ lindex $itclobjectlist $a ] }
+	}
+    }
+    
+    public    method GetThisPointer { } { return $this }
+    public    method Initialize { basewidg } 
+
+    public    method GetObjectGUI { } { return $objectGUI }
+
+    public    method AddObject { descr }    
+    public    method SetObject { index }
+    public    method GetObject { index }     
+    public    method DeleteObject { index }
+
+    public    method Update {}
+
+    public    method AddFunction { command name post }	    
+    # -----------------------------------------
+    # Function that must be overriden
+    protected method CreateNewObject { } { puts stdout "Error!"}
+    protected method CreateNewObjectGUI { widget } { puts stdout "Error!"}
+
+}
+
+itcl::body mpjmultiobjectGUI::GetObject { index } {
+
+    if { $initialized == 0 } { 	return 0  }
+    
+    if { $index == - 1} {
+	set index [ $listwidget index [ $listwidget get] ]
+    }
+    
+    return [ lindex $itclobjectlist $index ]
+}
+
+itcl::body mpjmultiobjectGUI::SetObject { index } {
+    
+    if { $initialized == 0 } { 	return 0  }
+    
+    if { $index == -1 } {
+	set index [$listwidget index [ $listwidget get ]]
+    }
+    
+    set ln [ llength $itclobjectlist  ]
+    if { $index < 0 || $index >= $ln } { return 0 } 
+
+#    $listbox selection clear 0 [ expr $ln -1 ]
+#    $listbox selection set $index $index
+    
+    $listwidget select $index
+
+    $objectGUI SetObject [ lindex $itclobjectlist $index ]
+    set currentobject $index
+    return $index 
+}
+
+itcl::body mpjmultiobjectGUI::AddObject { descr } {
+
+    if { $initialized == 0 } { return 0 }
+
+    set new_itclobject [ $this CreateNewObject ]    
+        
+    $listwidget insert [llength $itclobjectlist] $descr
+
+    lappend itclobjectlist $new_itclobject
+
+    return $new_itclobject
+}
+
+itcl::body mpjmultiobjectGUI::DeleteObject { index } {
+    
+    if { $initialized == 0 } { return 0 }
+    
+    set ln [ llength $itclobjectlist ]
+    
+    if { $index < 0 || $index >= $ln } { return 0 } 
+
+    catch { itcl::delete object [ lindex $itclobjectlist $index ] }
+    set itclobjectlist [ lreplace $itclobjectlist $index $index ]
+    
+    $listwidget delete $index $index
+}
+
+itcl::body mpjmultiobjectGUI::Update {} {
+    if { $basewidget !=0 } {
+	set a [ $basewidget cget -labeltext ]
+	if { $a != $description } {
+	    $basewidget configure -labeltext  $description
+	}
+	SetObject $currentobject
+    }
+}
+
+itcl::body mpjmultiobjectGUI::AddFunction { command name post }	{
+    $objectGUI AddFunction $command $name $post
+}
+
+itcl::body mpjmultiobjectGUI::Initialize { basewidg } {
+    
+    if { $initialized == 1 } { 
+	return $basewidget 
+    }
+    
+    set basewidget [ iwidgets::Labeledframe $basewidg -labelpos nw -labeltext $description ]
+    set base [ $basewidget childsite ]
+    
+#    frame $base.left; 
+#    frame $base.right;
+#    pack $base.left -side left -expand true -fill both -padx 5 -pady 5
+#    pack $base.right -side right -expand true -fill both -padx 5 -pady 5
+
+    set listwidget [ iwidgets::optionmenu $base.lw \
+		      -command "itcl::code $this SetObject -1"]
+    pack $listwidget -side top -expand t
+    
+    set objectGUI [ $this CreateNewObjectGUI $base ]
+	     
+#    set listbox [ iwidgets::scrolledlistbox $base.left.slb -vscrollmode \
+#dynamic -hscrollmode dynamic -selectmode single -labelpos nw ]
+#    eval "$listbox configure -selectioncommand { $this SetObject -1 }"
+    
+    return $basewidget
+}
+    
+
+		
+    
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjsigna2analyze.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjsigna2analyze.tcl
new file mode 100755
index 0000000..2d29e65
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjsigna2analyze.tcl
@@ -0,0 +1,156 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+package require pxtclutil 1.0
+package require vtkpxcontrib  1.1
+package require pxvtable 1.0
+
+set utilobj [ vtkpxUtil util ]
+
+set orient_name(0) "axial"
+set orient_name(1) "coronal"
+set orient_name(2) "sagittal"
+
+set import_topslice 1
+set import_bottomslice 1
+set num_slices 1
+set num_frames 1
+set num_slicesperframe 1
+
+proc GetNumberofSlices { prefix } {
+
+    set pa(name) f
+    set pa(0) 1
+    set pa(1) 1
+    
+    set pa(name) $prefix  
+    set flag 0
+    
+    while { $flag == 0 } {
+	set tmpname "$pa(name)$pa(1)"
+	set tmpname2 "$pa(name)$pa(1).gz"
+	if { [ file exists $tmpname ] ==1 || [ file exists $tmpname2 ]==1 } {
+	    incr pa(1)
+	} else {
+	    set flag 1 
+	    set pa(1) [ expr $pa(1) -1 ]
+	}
+    }
+    
+    set pa_list [ array get pa ]
+    return $pa_list
+
+}
+
+if { $argc == 0} {
+    set name [file tail [info script]]
+    puts stdout "\nUsage:\n      $name <prefix> <start-slice> <end-slice> <slices/frame> \[outname\]" 
+    puts stdout "\nMarcel Jackowski\nmjack at noodle.med.yale.edu\nSeptember 2002"
+    puts stdout [lindex $argv 0] 
+    exit
+}
+
+set prefix [ lindex $argv 0 ]
+
+set lx_reader [ vtkpxSignaLXImageSource [ pxvtable::vnewobj ]  ]
+$lx_reader SetFilePrefix [lindex $argv 0]
+
+if { [ $lx_reader ReadHeaderFile ] != 0 } {
+
+	set import_xsp    [ lindex [$lx_reader GetDataSpacing ] 0 ]
+	set import_ysp    [ lindex [$lx_reader GetDataSpacing ] 1 ]
+	set import_zsp    [ lindex [$lx_reader GetDataSpacing ] 2 ]
+	set import_width  [ lindex [$lx_reader GetDataDimensions ] 0 ]
+	set import_height [ lindex [$lx_reader GetDataDimensions ] 1 ]
+		
+	set pa_list [ GetNumberofSlices [lindex $argv 0] ]
+	array set pa $pa_list
+	set import_topslice    $pa(1)
+	set import_bottomslice $pa(0)
+	
+	set import_topslice    [ lindex $argv 2 ]
+	set import_bottomslice [ lindex $argv 1 ]
+	set num_slicesperframe [ lindex $argv 3 ] 
+	set num_slices [ expr $import_topslice - $import_bottomslice + 1 ]
+	set num_frames [ expr $num_slices / $num_slicesperframe ]
+
+	set orient [ $lx_reader GetOrientation ] 
+	
+	puts stdout "Reading $prefix slices"
+	puts stdout "dimensions: $import_width\x$import_height"
+	puts stdout "orientation: $orient_name($orient)"
+	puts stdout "x resolution: $import_xsp"
+	puts stdout "y resolution: $import_ysp"
+	puts stdout "z resolution: $import_zsp"
+	puts stdout "start slice: $import_bottomslice"
+	puts stdout "end slice: $import_topslice"
+	puts stdout "num slices: $num_slices"
+	puts stdout "num frames: $num_frames"
+	
+	$lx_reader Load [lindex $argv 0] $import_bottomslice $import_topslice
+
+} 
+
+set outp [ $lx_reader GetOutput ]
+
+vtkpxAnalyzeImageWriter ana
+
+ana SetInput $outp
+ana SetOrientation $orient
+ana SetCompression 0
+ana SetNumFrames $num_frames
+
+set first [ string last "i" $prefix ] 
+if { $argc < 5 } {
+    set outfname [ string range $prefix 0 [ expr $first - 1 ] ]
+} else {
+    set outfname [ lindex $argv 4 ]
+} 
+
+ana Save $outfname
+
+$lx_reader Delete
+ana Delete
+
+exit
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjt2relax.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjt2relax.tcl
new file mode 100755
index 0000000..40a9de2
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjt2relax.tcl
@@ -0,0 +1,148 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [file join [file join [ file dirname [ info script ]] ".."] base ]
+
+#package require pxtclutil 1.0
+package require vtkpxcontrib  1.1
+package require vtkmpjcontrib 1.1
+package require pxvtable 1.0
+
+
+if { $argc < 4} {
+    set name [file tail [info script]]
+    puts stdout "\n Usage:"
+    puts stdout "\n $name <input_image> <echo1> <echo2> <thresh> \[-w\]"
+    puts stdout "\n where <input_image> is the Analyze/NIFTI file containing the images acquired at the two echo times"
+    puts stdout "       <echo1> is the echo time for first image"
+    puts stdout "       <echo2> is the echo time for second image"
+    puts stdout "       <thresh> is the value for thresholding anatomy"
+    puts stdout "       -w: outputs the two echo images\n"
+    puts stdout "e.g. $name /images/example1.hdr 30 80 40\n"
+    exit
+}
+
+set filename1 [lindex $argv 0]
+set TE1 [lindex $argv 1]
+set TE2 [lindex $argv 2]
+set thresh [lindex $argv 3]
+set write_echos 0
+set thresh 40
+
+if { $argc > 4 } {
+    set write_echos 1
+}
+
+puts stdout "Reading in image [lindex $argv 0]"
+puts stdout "Threshold value is $thresh"
+vtkpxAnalyzeImageSource ana1
+ana1 Load $filename1
+
+vtkmpjImageInterleaving inter
+inter SetInput [ ana1 GetOutput ]
+inter SetSliceInterleave 
+inter SetNumberOfFrames 2
+inter Update
+
+vtkImageShiftScale shsc
+shsc SetShift 0.1
+shsc SetOutputScalarTypeToFloat
+shsc SetInput [inter GetOutput]
+shsc Update
+
+puts stdout "Calculating T2 times image"
+vtkmpjImageT2Relax t2relax
+t2relax SetInput [shsc GetOutput]
+t2relax SetThresholdValue $thresh
+t2relax SetEchoTime1 $TE1
+t2relax SetEchoTime2 $TE2
+t2relax Update
+
+vtkpxAnalyzeImageWriter out
+out SetInput [t2relax GetOutput]
+out SetImageHeader [ana1 GetImageHeader]
+set fname "[ file rootname $filename1 ]"
+set fname0 "${fname}_t2t"
+puts "Saving $fname0..."
+out Save $fname0
+
+if { $write_echos } {
+
+    vtkImageExtractComponents comp1
+    comp1 SetInput [ inter GetOutput ]
+    comp1 SetComponents 0
+    comp1 Update
+    
+    vtkpxAnalyzeImageWriter out1
+    out1 SetInput [comp1 GetOutput]
+    out1 SetImageHeader [ana1 GetImageHeader]
+    set fname1 "${fname}_$TE1"
+    puts stdout "Saving $fname1..."
+    out1 Save $fname1
+    
+    comp1 Delete
+    out1 Delete
+    
+    vtkImageExtractComponents comp2
+    comp2 SetInput [ inter GetOutput ]
+    comp2 SetComponents 1
+    comp2 Update
+    
+    vtkpxAnalyzeImageWriter out2
+    out2 SetInput [comp2 GetOutput]
+    out2 SetImageHeader [ana1 GetImageHeader]
+    set fname2 "${fname}_$TE2"
+    puts "Saving $fname2..."
+    out2 Save $fname2
+    
+    comp2 Delete
+    out2 Delete
+}
+
+puts stdout "Done!\n"
+
+ana1 Delete
+shsc Delete
+inter Delete
+t2relax Delete
+
+exit
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjtensoranalysis.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjtensoranalysis.tcl
new file mode 100644
index 0000000..a77073e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjtensoranalysis.tcl
@@ -0,0 +1,3457 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package provide mpjtensoranalysis 1.3
+
+package require  Itcl 3.2
+package require  Iwidgets 4.0
+
+package require  pxitcllistselector 1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitclbaseimageviewer 1.0
+
+package require  vtkmpjcontrib 1.1
+package require  mpjguilookuptable 1.0
+
+itcl::class mpjtensoranalysis {
+
+    inherit pxitclbaseimagecontrol
+    
+    #-----------------------------------
+    # construction and descruction
+    #-----------------------------------
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } { InitializeControl }
+    
+    destructor { }
+
+    #-----------------------------------
+    # common variables
+    #-----------------------------------
+
+    #-----------------------------------
+    # global variables
+    #-----------------------------------
+    private variable widget_list
+    private variable global_list
+    protected variable bis_algorithmmode 0
+    protected variable bis_orientationimage 0
+    
+    #-----------------------------------
+    # initialization methods
+    #-----------------------------------
+    public method Initialize { inpwidg }
+    public method InitializeControl { }
+    public method DismissWindow { }
+      
+    #-----------------------------------
+    # diffusion series input/output
+    #-----------------------------------
+    public method LoadMask { fname }
+    public method LoadTensor { fname }
+    public method ComputeResults { }
+    public method SaveAllResults { }
+    public method SaveResult { index }
+    public method ClearAllResults { }
+    public method DisplayResult { index { mode image } }
+    public method ClearDisplay { }
+    public method SetResultPreffix { preffix }
+    public method GetResultPreffix { } 
+    public method SetCurrentDirectory { fname } 
+    public method SaveStatistics { fname }
+
+    public method UpdateLookupControlsOnMap { }
+
+    #-----------------------------------
+    # interface creation methods
+    #-----------------------------------
+    private method CreateDialogs { base }
+    private method CreateStatisticsControl { base }
+    private method CreateTransformControl { base }
+    private method CreateResultsControl { base }
+    private method CreateTensorControl { base }
+    private method CreateDisplayControl { base }
+    private method CreateEigenDisplayControl { base }
+    private method CreateTensorDisplayControl { base }
+    private method CreateResultDisplayControl { base }
+    private method CreateDirectionDisplayControl { base }
+    private method CreateDisplayTypeMenu { menubase }
+    private method CreateDisplayModeMenu { menubase }
+    private method CreateDisplayTransformMenu { menubase }
+    private method CreateDisplayColorbarMenu { menubase }
+    private method CreateDisplayUpdateMenu { menubase }
+    private method CreateMenu { mb }
+    private method Clone { }
+    public method AddToMenuButton { mb args }    
+ 
+    private method loadmask { }
+    private method loadtensor { }
+    private method displayresult { { mode image } }
+    private method saveresult { }
+    private method toggleresult { }
+    private method saveallresults { }
+    private method savestatistics { }
+ 
+    private method mask_autochanged_cb { }
+
+    private method initialize_glyphs { }
+    private method input_updateinfo { index }    
+
+    private method tensor_ordering_cb { }
+    private method view_mode_cb { } 
+    private method view_eigen_filter_cb { }
+    private method view_eigen_glyph_cb { }
+    private method view_eigen_maxscale_cb { }
+    private method view_eigen_fromto_cb { }
+    private method view_eigen_cmapcopy_cb { }
+    private method view_eigen_cmapcopybtn_cb { }
+    private method view_eigen_cmapresetbtn_cb { }
+    private method view_eigen_cmaploadbtn_cb { }
+    private method view_eigen_cmapsavebtn_cb { }
+    private method view_tensor_filter_cb { }
+    private method view_tensor_glyph_cb { }
+    private method view_tensor_fromto_cb { }
+    private method view_tensor_maxscale_cb { }
+    private method view_tensor_cmapcopy_cb { }
+    private method view_tensor_cmapcopybtn_cb { }
+    private method view_tensor_cmapresetbtn_cb { }
+    private method view_tensor_cmaploadbtn_cb { }
+    private method view_tensor_cmapsavebtn_cb { }
+    private method view_direction_filter_cb { }
+    private method view_direction_scheme_cb { }
+    private method view_direction_update_cb { }
+    private method view_colorbar_cb { } 
+    private method view_update_display_cb { }
+    public method view_update_crosshair_cb { args }
+    private method view_results_colormap_cb { }
+    private method view_clear_display { }
+    private method view_update_display { }
+    private method view_toggle_autoupdate { }
+    private method view_type_toggle_slow_eigenvector { }
+    private method view_type_toggle_med_eigenvector { }
+    private method view_type_toggle_fast_eigenvector { }
+    private method view_type_toggle_tensor { }
+    private method view_type_toggle_colorbar { }
+    private method view_extract_roi { exts image } 
+    private method view_compute_roi_extents { orient dim levels }
+    private method view_create_eigenvector_glyph { index vectors scalar glyph where }
+    private method view_create_eigenvector { index title }    
+    private method view_create_tensor_glyph { tensor scalar glyph where }
+    private method view_create_tensor { }
+    private method view_create_colorbar { }
+
+    private method result_clear { start end }
+    private method result_createmask { }
+    private method result_createeigen { }
+    private method result_createmaps { }
+    private method result_rotatetensor { }
+    private method result_add_stat { title fmt tag results }
+    private method result_statistics { image mask title } 
+
+    # Methods for bis_algorithm
+    # -------------------------
+    public method SetParametersFromBisAlgorithmAndCompute { cscheme satfactor brightness usemask } 
+    public method GetOutputImage { index }
+    public method GetBisDirectionImage { } { return $bis_orientationimage }
+    public method SetBisAlgorithmMode { } { set bis_algorithmmode 1 }
+    public method BisComputeDirectionMaps { } { set bis_algorithmmode 1; $this view_direction_update_cb; set bis_algorithmmode 0 }
+
+}  
+
+
+#-------------------------------------------------------------------------------------------
+#  Close window 
+# -------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::DismissWindow { } {
+    
+    if { $bis_algorithmmode == 1 } {
+	$this HideWindow
+	return
+    }
+
+
+    set TENSOR 0
+    set MASK 1
+
+    set ok "yes"
+    
+    set tensorsz [ [ lindex $global_list(result_list) $TENSOR ] GetImageSize ]
+    set masksz [ [ lindex $global_list(result_list) $MASK ] GetImageSize ]
+
+    if { [expr ($tensorsz > 1) || ($masksz > 1) ] } {
+	
+	set ok [ tk_messageBox -type yesnocancel -default no \
+		     -parent $basewidget -title "Think again ..." \
+		     -message "Unload all images from memory?" -icon question  ]
+    }
+    
+    if { $ok == "yes" } {	
+	
+	$this view_clear_display
+	$this ClearAllResults
+	
+	$this SetTitle $global_list(appname)
+	
+	set global_list(mask_fname) ""
+	set global_list(tensor_fname) ""
+    }
+    
+    if { $ok != "cancel" } {
+	$this HideWindow
+    }
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Initialize tool
+# -------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::InitializeControl { } {
+
+    set appname "Diffusion Tensor Analysis $version"
+    set aboutstring "(c) Marcel Jackowski 2008"
+
+    set global_list(appname) "Diffusion Tensor Analysis"
+
+    # create image titles
+    set global_list(result_title) \
+	[ list \
+	      { "Diffusion tensor"        "dti_tensor" 1 } \
+	      { "Region of interest mask" "dti_mask" 1 } \
+	      { "Eigenvalues"             "dti_eigenval" 1 } \
+	      { "Eigenvectors"            "dti_eigenvec" 1 } \
+	      { "Negative eigenvalues"    "dti_neigenval" 1 } \
+	      { "Fractional anisotropy"   "dti_fractani" 1 } \
+	      { "Relative anisotropy"     "dti_relani" 1 } \
+	      { "Mean diffusivity"        "dti_meandiff" 1 } \
+	      { "Volume ratio"            "dti_volratio" 1 } \
+	      { "Fiber coherence"         "dti_fiberci" 1 } \
+	      { "Lattice index"           "dti_lattindex" 0 } \
+	      { "Lattice anisotropy"      "dti_lattani" 0 } \
+	      { "Directionality"          "dti_dec" 0 } \
+	      { "Fiber angle"             "dti_fiberang" 0 } \
+	      { "Sheet angle"             "dti_sheetang" 0 } ]
+
+    ## create empty images
+    foreach item $global_list(result_title) {
+ 	lappend result_list [ pxitclimage \#auto ]
+	set global_list(enable_list,[lindex $item 1]) 0
+    }
+    
+    set global_list(result_fpreffix) "preffix_"
+    set global_list(result_fsuffix) ".nii.gz"
+    set global_list(result_fdir) [ pwd ] 
+    set global_list(result_list) $result_list
+    
+    set global_list(mask_fname) ""
+    set global_list(mask_auto) 1
+    set global_list(mask_nreg) 1
+    set global_list(mask_threshval) 1E-12
+    set global_list(mask_negative) 0
+    
+    set global_list(tensor_fname) ""
+    set global_list(tensor_symm) 1
+    set global_list(tensor_ordering) 0
+    set global_list(tensor_flipx) 0
+    set global_list(tensor_flipy) 0
+    set global_list(tensor_flipz) 0
+    set global_list(tensor_rotation) 0
+    set global_list(tensor_rotx) 0.0
+    set global_list(tensor_roty) 0.0
+    set global_list(tensor_rotz) 0.0
+    
+    set global_list(eigen_recompute) 1
+
+    set global_list(stat_overwrite) 1
+
+    set global_list(view_mode) "3-slice"
+    set global_lisr(view_autoupdate) 0
+    set global_list(view_mode_index) 3
+    set global_list(view_type_fast) 0
+    set global_list(view_type_medium) 0
+    set global_list(view_type_slow) 0
+    set global_list(view_type_tensor) 0
+    set global_list(view_type_colorbar) 0
+    set global_list(view_colorbar) "Eigenvectors"
+    set global_list(view_colorbar_label) "Results"
+    set global_list(view_eigen_to) 1.0
+    set global_list(view_eigen_from) 0.5
+    set global_list(view_eigen_between) 1
+    set global_list(view_eigen_maxscale) 1.0
+    set global_list(view_eigen_flip) 1
+    set global_list(view_eigen_cmapcopy) 0
+    set global_list(view_tensor_to) 1.0
+    set global_list(view_tensor_from) 0.5
+    set global_list(view_tensor_between) 1
+    set global_list(view_tensor_maxscale) 1.0
+    set global_list(view_tensor_scale) 1.0
+    set global_list(view_tensor_clampscale) 1
+    set global_list(view_tensor_cmapcopy) 0
+    set global_list(view_direction_satscale) 0.5
+    set global_list(view_direction_scaling) 1.0
+    set global_list(view_direction_numcolors) 256
+    set global_list(view_direction_mask) 1
+    set global_list(view_transparent) 1
+    set global_list(view_transpcolor) 0.0
+    
+    ## create actors for visualization
+    set global_list(actor_fast) [ list -1 -1 -1 -1 ]
+    set global_list(actor_med) [ list -1 -1 -1 -1 ]
+    set global_list(actor_slow) [ list -1 -1 -1 -1 ]
+    set global_list(actor_tensor) [ list -1 -1 -1 -1 ]
+    set global_list(actor_colorbar) -1
+
+    for { set i 0 } { $i < 3 } { incr i } { ## fast med slow
+	for { set j 0 } { $j < 4 } { incr j } { ## xy xz yz vol
+	    set global_list(vtk_eigen_glypher,$i,$j) [ vtkGlyph3D [ pxvtable::vnewobj ] ]
+	    set global_list(vtk_eigen_threshold,$i,$j) [ vtkThresholdPoints [ pxvtable::vnewobj ] ]
+	    set global_list(vtk_eigen_merge,$i,$j) [ vtkMergeFilter [ pxvtable::vnewobj ] ]
+	}
+    }
+    
+    for { set i 0 } { $i < 4 } { incr i } {
+	set global_list(vtk_tensor_glypher,$i) [ vtkTensorGlyph [ pxvtable::vnewobj ] ]
+	set global_list(vtk_tensor_threshold,$i) [ vtkThresholdPoints [ pxvtable::vnewobj ] ]
+	set global_list(vtk_tensor_merge,$i) [ vtkMergeFilter [ pxvtable::vnewobj ] ]
+    }
+    
+    initialize_glyphs
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create visualization glyphs
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::initialize_glyphs { } {
+
+    ## create line source
+    set line_src [ vtkLineSource [ pxvtable::vnewobj ] ]
+    $line_src SetPoint1 0.0 0 0
+    $line_src SetPoint2 2.0 0 0    
+
+    set line_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $line_xfrm Translate -1.0 0.0 0.0
+
+    set line [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $line SetInput [ $line_src GetOutput ]
+    $line SetTransform $line_xfrm
+    lappend global_list(glyph_list) $line 
+
+    $line_src Delete
+    $line_xfrm Delete
+    
+    # create tube source
+    set tube_src [ vtkCylinderSource [ pxvtable::vnewobj ] ]
+    $tube_src SetHeight 2.0
+    $tube_src SetRadius 0.35
+    $tube_src CappingOn
+    
+    set tube_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $tube_xfrm RotateZ -90.0
+    
+    set tube [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $tube SetInput [ $tube_src GetOutput ]
+    $tube SetTransform $tube_xfrm
+    lappend global_list(glyph_list) $tube
+    
+    $tube_src Delete
+    $tube_xfrm Delete
+    
+    ## create arrow source
+    set arrow_src [ vtkArrowSource [ pxvtable::vnewobj ] ]
+    $arrow_src SetTipLength 0.35
+    $arrow_src SetTipResolution 10
+    $arrow_src SetTipRadius 0.20
+    $arrow_src SetShaftResolution 10
+    $arrow_src SetShaftRadius 0.1
+
+    set arrow_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $arrow_xfrm Translate -1.0 0.0 0.0
+    $arrow_xfrm Scale 2.0 2.0 2.0
+
+    set arrow [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $arrow SetInput [ $arrow_src GetOutput ]
+    $arrow SetTransform $arrow_xfrm
+    lappend global_list(glyph_list) $arrow
+
+    $arrow_src Delete
+    $arrow_xfrm Delete
+    
+    ## create ellipsoid source
+    set ellipsoid_src [ vtkSphereSource [ pxvtable::vnewobj ] ]
+    set ellipsoid_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    #$ellipsoid_xfrm Scale -2.0 -2.0 2.0
+    
+    set ellipsoid [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $ellipsoid SetInput [ $ellipsoid_src GetOutput ]
+    $ellipsoid SetTransform $ellipsoid_xfrm
+    lappend global_list(glyph_list) $ellipsoid
+    
+    $ellipsoid_src Delete
+    $ellipsoid_xfrm Delete
+    
+    ## create cuboid source
+    set cuboid_src [ vtkCubeSource [ pxvtable::vnewobj ] ]
+    set cuboid_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    
+    set cuboid [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $cuboid SetInput [ $cuboid_src GetOutput ]
+    $cuboid SetTransform $cuboid_xfrm
+    lappend global_list(glyph_list) $cuboid
+    
+    $cuboid_src Delete
+    $cuboid_xfrm Delete
+
+    ## create sheet source
+    set sheet_src [ vtkCubeSource [ pxvtable::vnewobj ] ]
+    set sheet_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $sheet_xfrm Scale 1.0 1.0 0.0
+    
+    set sheet [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $sheet SetInput [ $sheet_src GetOutput ]
+    $sheet SetTransform $sheet_xfrm
+    lappend global_list(glyph_list) $sheet
+    
+    $sheet_src Delete
+    $sheet_xfrm Delete
+  
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in mask auto status
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::mask_autochanged_cb { } {
+    set state(0) disabled; set state(1) normal        
+    $widget_list(mask_load) buttonconfigure load -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_load) buttonconfigure disp -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_fname) configure -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_threshval) configure -state \
+	$state($global_list(mask_auto))
+    $widget_list(mask_nreg) configure -state $state([expr 1 - $global_list(mask_auto)])
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Update input information on title bar
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::input_updateinfo { index } {
+
+    set sel_input [ [ lindex $global_list(input_list) $index ] GetImage ]
+    set sel_fname [ lindex $global_list(input_fname) $index ]
+    
+    scan [ $sel_input GetDimensions ] "%d %d %d" dx dy dz	       
+    set nc [  $sel_input GetNumberOfScalarComponents ]
+    set name [ file tail [ file root $sel_fname ] ]
+    
+    if { [ file extension $name ] == ".gz" } {
+	set name [ file rootname $name ]
+    }
+    if { [ file extension $name ] == ".hdr" } {
+	set name [ file rootname $name ]
+	set global_list(result_fsuffix) ".hdr"
+    } elseif { [ file extension $name ] == ".nii" } {
+	set name [ file rootname $name ]
+	set global_list(result_fsuffix) ".nii.gz"
+    }
+    
+    set global_list(result_fpreffix) "${name}_"
+
+    $this SetTitle "$global_list(appname): $name (${dx}x${dy}x${dz}, $nc frames)"
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load mask
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::loadmask { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select mask" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadMask $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in mask image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::LoadMask { fname } {
+
+    set MASK 1     
+    set mask [ lindex $global_list(result_list) $MASK ]
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    $this SetFilterCallbacks $ana "Reading in mask image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    ## if mask not a unsigned char image, convert it
+    set scalar_type [ [ $ana GetOutput ] GetScalarType ]    
+
+    if { $scalar_type != 3 } {	
+	
+	set imcast [ vtkImageCast [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $imcast "Converting mask to unsigned char values..."
+	$imcast SetInput [ $ana GetOutput ]
+	$imcast SetOutputScalarTypeToUnsignedChar
+	$imcast ClampOverflowOn	
+	$imcast Update
+	
+    ## fixed on 11/1/04
+	$mask CopyImageHeader [ $ana GetImageHeader ]
+	$mask ShallowCopyImage [ $imcast GetOutput ]
+	
+	$imcast Delete
+	
+    } else {
+	
+	$mask SetFromAnalyzeSource $ana
+    }
+   
+    ## determine range of values in mask
+    set range [ [ [ [ $mask GetImage ] GetPointData ] GetScalars ] GetRange ]
+
+    ## take the maximum range as the number of regions in mask
+    # -- force integer!
+    set global_list(mask_nreg) [ expr int([ lindex $range 1 ])]
+    $widget_list(mask_nreg) configure -range [ list 1 $global_list(mask_nreg) ]
+    
+    set global_list(mask_fname) $fname
+
+    WatchOff
+
+    $ana Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in tensor component ordering
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::tensor_ordering_cb { } {
+    
+    ## current ordering
+    set global_list(tensor_ordering) [ $widget_list(tensor_ordering) index [ $widget_list(tensor_ordering) get ] ]   
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load tensor
+# -----------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::loadtensor { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select tensor" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadTensor $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in tensor image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::LoadTensor { fname } {
+
+    set TENSOR 0
+
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in tensor image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    $tensor SetFromAnalyzeSource $ana
+    
+    # determine coordinate transform
+    set or [ $ana GetOrientation ]
+    if { $or == 0 } {
+     	set global_list(tensor_flipx) 1
+     	set global_list(tensor_flipy) 1
+    } elseif { $or == 1 } {
+     	set global_list(tensor_flipx) 1
+    } 
+    
+    set nc [ [ $tensor GetImage ] GetNumberOfScalarComponents ]
+
+    set global_list(tensor_fname) $fname
+
+
+    set name $fname
+    if { [ file extension $name ] == ".gz" } {
+	set name [ file rootname $name ]
+    }
+    if { [ file extension $name ] == ".hdr" } {
+	set name [ file rootname $name ]
+	set global_list(result_fsuffix) ".hdr"
+    } elseif { [ file extension $name ] == ".nii" } {
+	set name [ file rootname $name ]
+	set global_list(result_fsuffix) ".nii.gz"
+    }
+    
+    set global_list(result_fpreffix) "[file tail $name ]"
+    set global_list(tensor_symm) [ expr $nc == 6 ]
+    
+    WatchOff
+    
+    $ana Delete
+    
+    $widget_list(computebtn) configure -state normal
+    $widget_list(menu_results) entryconfigure 0 -state normal
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Set result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::SetResultPreffix { preffix } {
+    set global_list(result_fpreffix) $preffix
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Get result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::GetResultPreffix { } {
+    return $global_list(result_fpreffix)
+}
+
+itcl::body mpjtensoranalysis::SetCurrentDirectory { fname } {
+    set global_list(result_fdir) $fname
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Clear all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::ClearAllResults { } {
+    
+    foreach result $global_list(result_list) {
+	$result Clear
+    }
+
+    if { $bis_orientationimage != 0 } {
+	$bis_orientationimage Clear
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::SaveAllResults { } {
+
+    foreach result $global_list(result_list) title $global_list(result_title) {
+	
+
+	set fname $global_list(result_fpreffix)
+	set suffix $global_list(result_fsuffix)	
+	set fname "$fname[ lindex $title 1 ]${suffix}"
+	set dim [ lindex [ [ $result GetImage ] GetDimensions ] 0 ]
+	if { $dim >1 } {
+	    $result Save $fname
+	}
+
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save single result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::SaveResult { index } {        
+
+    set fname $global_list(result_fpreffix)
+    set suffix $global_list(result_fsuffix)	
+    set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]${suffix}"
+
+    [lindex $global_list(result_list) $index] Save $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::saveallresults { } {
+
+    ## browse for directory
+    set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+
+    if { $fdir != "" } {
+	
+	set global_list(result_fdir) $fdir
+	
+	foreach result $global_list(result_list) title $global_list(result_title) {
+	    
+	    set fname $global_list(result_fpreffix)
+	    set suffix $global_list(result_fsuffix)	
+	    set fname "$fname[ lindex $title 1 ]${suffix}"
+	    
+	    set dim [ lindex [ [ $result GetImage ] GetDimensions ] 0 ]
+	    if { $dim >1 } {
+		$result Save [ file join $fdir $fname ]
+	    }
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::saveresult { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(result_list) getcurselection ]
+    
+    if { $sel_item != "" } { 
+
+	## browse for directory
+	set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+	
+	if { $fdir != "" } {
+	    
+	    set global_list(result_fdir) $fdir
+	    
+	    foreach item $sel_item {
+		
+		set index [ $widget_list(result_list) index $item ]
+		set result [ lindex $global_list(result_list) $index ]
+		
+		set fname $global_list(result_fpreffix)
+		set suffix $global_list(result_fsuffix)	
+		set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]${suffix}"
+		
+		$result Save [ file join $fdir $fname ]
+	    }
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::DisplayResult { index { mode image } } {
+
+    # ----------------------------------------
+    # Xenios -- this is the image display part
+    # ----------------------------------------
+
+    set imgtodisplay [ [ lindex $global_list(result_list) $index ] GetThisPointer]
+    set rawimg  [ $imgtodisplay GetImage ] 
+    set r [ [ [ $rawimg GetPointData ] GetScalars ] GetRange ]
+
+    set rmin [ lindex $r 0 ]
+    set rmax [ lindex $r 1 ]
+
+
+    # Step 1.
+    # Update Lookup table range and lookup table
+    
+    # this is in the object resultluk -- see roughly line 2893
+    # SetSaturationRange -- use this from image range!
+    # Update
+
+    set resultluk  $widget_list(view_resultluk) 
+
+    $resultluk SetSaturationRange $rmin $rmax
+    $resultluk Update
+
+
+    # Step 2.
+    # Ship Image and Lookup Table 
+
+    if { $mode == "image" } {
+	$parent SetImageFromObject $imgtodisplay $this
+	#$parent SetLookupTable [ $resultluk GetLookupTable ]
+	[ $parent GetViewer ] UpdateDisplay
+	return
+    }
+
+    
+    $parent SetMaskFromObject $imgtodisplay $this
+    [ $parent GetViewer ]  SetObjectLookupTable [ $resultluk GetLookupTable ]
+    [ $parent GetViewer ] UpdateDisplay
+    return
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::displayresult { { mode image } } {
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+	    
+    if { $sel_item != "" } {
+	set index [ $widget_list(result_list) index [ lindex $sel_item 0 ] ]
+	set result [ lindex $global_list(result_list) $index ]
+
+	set range [ [ [ [ $result GetImage ] GetPointData ] GetScalars ] GetRange ]
+	$widget_list(view_resultluk) SetTableRange [ lindex $range 0 ] [ lindex $range 1 ]
+	#	$widget_list(view_resultluk) Update
+
+	$this DisplayResult $index $mode
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: toggle result computation on/off
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::toggleresult { } {
+   
+    set color(0) \#dcdcdc
+    set color(1) black
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+
+    if { $sel_item != "" } {
+
+	set index [ $widget_list(result_list) index [ lindex $sel_item 0 ] ]
+
+	if { $index > 4 } {
+	    set enable [expr 1 - [ lindex [ lindex $global_list(result_title) $index ] 2 ] ]
+	    
+	    $widget_list(result_list) itemconfigure $index -foreground $color($enable)
+	    
+	    set item [ lindex $global_list(result_title) $index ]
+	    set new_item [ lreplace $item 2 2 $enable ]
+	    
+	    set global_list(result_title) [ lreplace $global_list(result_title) \
+						$index $index $new_item ]
+	}
+    }
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::SaveStatistics { fname } {
+      $widget_list(stat_text) export $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::savestatistics { } {
+
+    set statfname $global_list(result_fpreffix)
+    set initfname "${statfname}stat"
+    set initfname [ file join $global_list(result_fdir) $initfname ]
+
+    ## browse for filename
+    set fname  [tk_getSaveFile -title "Save statistics"\
+		    -filetypes {{"Text" {.txt*}}} \
+		    -parent $basewidget \
+		    -defaultextension ".txt" \
+		    -initialfile $initfname ]  
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+    
+    $this SaveStatistics $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: add statistics line
+#-------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::result_add_stat { title fmt tag results } {   
+    
+    set line " $title |"
+    
+    foreach item $results {
+	set fitem [ format $fmt $item ] 
+	set line "$line $fitem |"
+    }
+
+    $widget_list(stat_text) insert end " $line\n" $tag
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Compute statistics
+#-------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::result_statistics { image mask title } {
+    
+    ## compute statitics from given image and mask
+    set stat [ vtkmpjImageStatistics [ pxvtable::vnewobj ] ]
+    $stat SetMask $mask
+    $stat SetInput $image
+    $stat SetNumberOfRegions $global_list(mask_nreg)
+    $stat Update
+    
+    ## write header information
+    set border [ string repeat "----------+" $global_list(mask_nreg) ] 
+    
+    set regions ""
+    for { set i 1 } { $i <= $global_list(mask_nreg) } { incr i } {	
+	set regions "$regions|Region \#[format %2d $i]"	
+    }
+
+    $widget_list(stat_text) insert \
+	end "-----------------------+$border\n" even
+    $widget_list(stat_text) insert \
+	end " $title $regions|\n" odd
+    $widget_list(stat_text) insert \
+	end "-----------------------+$border\n" even
+
+    ## Write out stats
+    set textlist [  $widget_list(stat_text) component text ]
+    $textlist tag configure even -background "\#d0ffd0"
+
+    set results ""
+    for { set i 0 } { $i < $global_list(mask_nreg) } { incr i } {	
+	lappend results [ $stat GetRegionMin $i ]
+    }    
+    result_add_stat " MINIMUM            " "%8.4f" odd $results
+    
+    set results ""
+    for { set i 0 } { $i < $global_list(mask_nreg) } { incr i } {	
+	lappend results [ $stat GetRegionMax $i ]
+    }    
+    result_add_stat " MAXIMUM            " "%8.4f" even $results
+    
+    set results ""
+    for { set i 0 } { $i < $global_list(mask_nreg) } { incr i } {	
+	lappend results [ $stat GetRegionMean $i ]
+    }    
+    result_add_stat " MEAN               " "%8.4f" odd $results
+    
+    set results ""
+    for { set i 0 } { $i < $global_list(mask_nreg) } { incr i } {	
+	lappend results [ $stat GetRegionVariance $i ]
+    }    
+    result_add_stat " VARIANCE           " "%8.4f" even $results
+    
+    $widget_list(stat_text) insert end "\n" odd 
+
+    set results ""
+    for { set i 0 } { $i < $global_list(mask_nreg) } { incr i } {	
+	lappend results [ $stat GetRegionVoxelCount $i ]
+    }    
+
+    $stat Delete
+
+    return $results
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::result_clear { start end } {
+    
+    for { set i $start } { $i <= $end } { incr i } {
+	
+	set title [ lindex [ lindex $global_list(result_title) $i ] 0 ]	    
+	
+	if { $title == "Region of interest mask" } {
+	    if { $global_list(mask_auto) } {
+		[ lindex $global_list(result_list) $i ] Clear
+	    }
+	} else { 
+	    [ lindex $global_list(result_list) $i ] Clear
+	}
+
+    }
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Rotate tensor
+#-------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::result_rotatetensor { } {
+
+    set TENSOR 0
+    
+    ## get tensor image
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    
+    ## rotate tensor
+    set tensor_xform [ vtkmpjImageTensorTransform [ pxvtable::vnewobj ] ]
+    $tensor_xform SetInput [ $tensor GetImage ]
+    $tensor_xform SetRotation $global_list(tensor_rotx) $global_list(tensor_roty) $global_list(tensor_rotz) 
+    $this SetFilterCallbacks $tensor_xform "Transforming tensor..."
+    
+    # rotate tensor
+    $tensor_xform Update
+    
+    # replace tensor
+    $tensor ShallowCopyImage [ $tensor_xform GetOutput ]
+    
+    $tensor_xform Delete
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create mask image
+#-------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::result_createmask { }  {
+
+    set TENSOR 0
+    set MASK 1
+    
+    ## get tensor image
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    
+    set mask [ lindex $global_list(result_list) $MASK ]    
+    $mask CopyImageHeader \
+	[ [ lindex $global_list(result_list) $TENSOR ] GetImageHeader ]
+    
+    set frm_filter [ vtkImageExtractComponents [ pxvtable::vnewobj ] ]
+    $frm_filter SetInput [ $tensor GetImage ]
+    $frm_filter SetComponents 0
+    $frm_filter Update
+
+#    puts stderr "Spacing [ [ $frm_filter GetOutput ] GetSpacing ]"
+    
+    ## threshold tensor image
+    set thresh [ vtkImageThreshold [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $thresh "Creating mask..."
+    $thresh SetInput [ $frm_filter GetOutput ]
+    $thresh ThresholdByUpper $global_list(mask_threshval)
+    $thresh SetInValue 1
+    $thresh SetOutValue 0
+    $thresh SetOutputScalarTypeToUnsignedChar
+    $thresh Update
+
+#    puts stderr "Spacing [ [ $thresh GetOutput ] GetSpacing ]"
+    
+    $frm_filter Delete
+
+    ## save mask
+    $mask ShallowCopyImage [ $thresh GetOutput ] 
+    $mask CopyImageHeader  [ $tensor GetImageHeader ]
+#    puts stderr "Mask = [ $mask GetDescription ]"
+    $thresh Delete    
+    
+    update idletasks
+    
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create eigensystem
+#-------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::result_createeigen { } {
+
+    set TENSOR 0
+    set MASK 1
+    set EIGENVALUES 2
+    set EIGENVECTORS 3
+    set NEGATIVEMASK 4
+
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set eigenvalues [ lindex $global_list(result_list) $EIGENVALUES ]
+    set eigenvectors [ lindex $global_list(result_list) $EIGENVECTORS ]
+    set negative [ lindex $global_list(result_list) $NEGATIVEMASK ]
+    
+
+    if { [expr ([ $mask GetImageSize ] == 1) || ([ $tensor GetImageSize ] == 1) ] } {
+	return 0
+    }
+
+    ## compute eigenvalues and eigenvectors
+    set eigen [ vtkmpjImageTensorEigenAnalysis [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $eigen "Computing eigenvalues and eigenvectors..."
+    $eigen SetInput [ $tensor GetImage ]
+    $eigen SetOrdering $global_list(tensor_ordering)
+    $eigen SetMask [ $mask GetImage ]
+    $eigen SetOutputTypeToBoth    
+    $eigen MaskNegativeOn
+    $eigen SetMaskNegativeInValue 0
+    $eigen SetMaskNegativeOutValue 255
+    $eigen Update
+    
+    ## extract mask with negative eigenvalues
+    $negative ShallowCopyImage [ $eigen GetNegativeMask ]
+    
+    ## extract eigenvalues
+    set fex [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $fex "Extracting eigenvalues..."
+    $fex SetInput [ $eigen GetOutput ]
+    $fex SetStartFrame 0
+    $fex SetEndFrame 2
+    $fex Update
+
+    $eigenvalues ShallowCopyImage [ $fex GetOutput ]
+    
+    $fex Delete
+    
+    ## extract eigenvectors
+    set fex [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $fex "Extracting eigenvectors..."
+    $fex SetInput [ $eigen GetOutput ]
+    $fex SetStartFrame 3
+    $fex SetEndFrame 11
+    $fex Update
+    
+    #### TEMP CHANGE #####
+    #set center [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    #set cx [ lindex $center 0 ]
+    #set cy [ lindex $center 1 ]
+    #set cz [ lindex $center 2 ]
+
+    #set rad [ vtkmpjRadialCoordinates [ pxvtable::vnewobj ] ]
+    #$rad SetInput [ $fex GetOutput ]
+    #$rad SetMask [ $mask GetImage ]
+    #$rad SetCenter $cx $cy $cz
+    #$rad Update
+
+    #$eigenvectors ShallowCopyImage [ $rad GetOutput ]
+
+    #$rad Delete
+    $eigenvectors ShallowCopyImage [ $fex GetOutput ]
+
+    #### END TEMP CHANGE
+
+    $eigenvalues CopyImageHeader [ $mask GetImageHeader ]
+    $eigenvectors CopyImageHeader [ $mask GetImageHeader ]
+    $negative CopyImageHeader [ $mask GetImageHeader ]
+
+
+    $fex Delete
+
+    $eigen Delete
+
+    update idletasks
+
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create maps
+#-------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::result_createmaps { } {
+    
+    set TENSOR 0
+    set MASK 1
+    set EIGENVALUES 2
+    set EIGENVECTORS 3
+    set NEGATIVEMASK 4
+    set FA_MAP 5
+    set RA_MAP 6
+    set MD_MAP 7
+    set VR_MAP 8
+    set CI_MAP 9
+    set LI_MAP 10
+    set ADD_MAP 11
+    set DIR_MAP 12
+    set FIBER_MAP 13
+    set SHEET_MAP 14
+
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set eigenvalues [ lindex $global_list(result_list) $EIGENVALUES ]
+    set eigenvectors [ lindex $global_list(result_list) $EIGENVECTORS ]
+    set negative [ lindex $global_list(result_list) $NEGATIVEMASK ]
+
+
+#    puts stderr "Tensor spacing = [  [ $tensor GetImage ] GetSpacing ]"
+#    puts stderr "Tensor description = [ $tensor GetDescription ]\n Mask = [ $mask GetDescription ]\n"
+
+    set famap [ lindex $global_list(result_list) $FA_MAP ]
+    set ramap [ lindex $global_list(result_list) $RA_MAP ]
+    set mdmap [ lindex $global_list(result_list) $MD_MAP ]
+    set vrmap [ lindex $global_list(result_list) $VR_MAP ]
+    set cimap [ lindex $global_list(result_list) $CI_MAP ]
+    set limap [ lindex $global_list(result_list) $LI_MAP ]
+    set addmap [ lindex $global_list(result_list) $ADD_MAP ]
+    set fibmap [ lindex $global_list(result_list) $FIBER_MAP ]
+    set sheetmap [ lindex $global_list(result_list) $SHEET_MAP ]
+
+    
+    set deletemapmask 0
+    set mapmask 0 
+    #    $mapmask CopyImageHeader [ $mask GetImageHeader ]    
+    
+
+    if { $global_list(mask_negative) == 1 } {	
+	
+	#	puts stderr  "In Imlogic mask = [ [ $mask GetImage ] GetSpacing ], negative= [ [ $negative GetImage ] GetSpacing ]"
+
+	## compute mask and void pixels in the mask having negative eigenvalues
+	set imlogic [ vtkImageLogic [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $imlogic "Combining mask (step 1)..."
+	$imlogic SetInput1 [ $mask GetImage ]
+	$imlogic SetInput2 [ $negative GetImage ]
+	$imlogic SetOperationToAnd
+	$imlogic SetOutputTrueValue 1
+	$imlogic Update	
+	
+#	puts stderr  "In New imlogic = [ [ $imlogic GetOutput ] GetSpacing ], mask [ [ $mask GetImage ] GetSpacing ]"
+
+	set newmask [ vtkImageMathematics [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $imlogic "Combining mask (step 2)..."
+	$newmask SetInput1 [ $imlogic GetOutput ]
+	$newmask SetInput2 [ $mask GetImage ]
+	$newmask SetOperationToMultiply
+	$newmask Update
+
+	$imlogic Delete
+	
+	set mapmask [ pxitclimage \#auto ]
+	$mapmask ShallowCopyImage [ $newmask GetOutput ]
+	set deletemapmask 1
+	$newmask Delete
+
+    } else {
+	set mapmask $mask
+#	puts stderr "Here we are done ....."
+	set deletemapmask 0
+    }
+
+#    puts stderr "Eigenvalues = [ $eigenvalues GetDescription ] , spa=[ [ $eigenvalues GetImage ] GetSpacing ]"
+#    puts stderr "MapMask     = [ $mapmask GetDescription ] , spa= [ [ $mapmask GetImage ] GetSpacing ]"
+
+    
+    ## compute invariants
+    set invar [ vtkmpjImageTensorInvariants [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $invar "Computing tensor maps..."
+    $invar SetInput [ $eigenvalues GetImage ]
+    $invar SetMask [ $mapmask GetImage ]
+    $invar Update
+
+    ## clear textbox
+    if { $global_list(stat_overwrite) } { 
+	$widget_list(stat_text) delete 1.0 end
+    }
+    
+    set results 0
+
+    set enable [ lindex [ lindex $global_list(result_title) $FA_MAP ] 2 ]
+    if { $enable } {
+	################### extract Fractional Anisotropy map #####################
+	set fa [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+	$this ShowProgressVal "Computing statistics..." [expr 2.0 / 9]
+	$fa SetInput [ $invar GetOutput ]
+	$fa SetFrameNumber 0
+	$fa Update
+	
+	$famap ShallowCopyImage [ $fa GetOutput ]
+	$famap CopyImageHeader [ $mask GetImageHeader ]
+	$fa Delete
+	
+	set results [ result_statistics [ $famap GetImage ] [ $mapmask GetImage ] "FRACTIONAL ANISOTROPY" ]
+    }
+    
+
+    set enable [ lindex [ lindex $global_list(result_title) $RA_MAP ] 2 ]
+    if { $enable } {
+	################### extract Relative Anisotropy map #####################
+	set ra [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+	$this ShowProgressVal "Computing statistics..." [expr 3.0 / 9]
+	$ra SetInput [ $invar GetOutput ]
+	$ra SetFrameNumber 1
+	$ra Update    
+	
+	$ramap ShallowCopyImage [ $ra GetOutput ]
+	$ramap CopyImageHeader [ $mask GetImageHeader ]
+
+    
+	
+	$ra Delete
+	
+	set results [ result_statistics [ $ramap GetImage ] [ $mapmask GetImage ] "RELATIVE ANISOTROPY  " ]
+    }
+
+    set enable [ lindex [ lindex $global_list(result_title) $MD_MAP ] 2 ]
+    if { $enable } {
+	##################### extract Mean diffusity map #####################
+	set md [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+	$this ShowProgressVal "Computing statistics..." [expr 4.0 / 9]
+	$md SetInput [ $invar GetOutput ]
+	$md SetFrameNumber 3
+	$md Update    
+	
+	$mdmap ShallowCopyImage [ $md GetOutput ]
+	$mdmap CopyImageHeader [ $mask GetImageHeader ]
+	$md Delete
+	
+	set results [ result_statistics [ $mdmap GetImage ] [ $mapmask GetImage ] "MEAN DIFFUSIVITY     " ]
+    }
+
+    set enable [ lindex [ lindex $global_list(result_title) $VR_MAP ] 2 ]
+    if { $enable } {
+
+	##################### extract Volume Ratio map ###################
+	set vr [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+	$this ShowProgressVal "Computing statistics..." [expr 5.0 / 9]
+	$vr SetInput [ $invar GetOutput ]
+	$vr SetFrameNumber 2
+	$vr Update    
+	
+	$vrmap ShallowCopyImage [ $vr GetOutput ]
+	$vrmap CopyImageHeader [ $mask GetImageHeader ]
+	$vr Delete
+	
+	set results [ result_statistics [ $vrmap GetImage ] [ $mapmask GetImage ] "VOLUME RATIO         " ]
+    }
+    
+    set enable [ lindex [ lindex $global_list(result_title) $CI_MAP ] 2 ]
+    if { $enable } {
+	##################### extract Intervoxel Coherence map ########################
+	set ci [ vtkmpjImageTensorCoherence [ pxvtable::vnewobj ] ]
+	$this ShowProgressVal "Computing statistics..." [expr 6.0 / 9]
+	$ci SetInput [ $eigenvectors GetImage ]
+	$ci SetMask [ $mapmask GetImage ]
+	$ci SetKernelSize 3 3 3
+	$ci Update
+	
+	$cimap ShallowCopyImage [ $ci GetOutput ]
+	$cimap CopyImageHeader [ $mask GetImageHeader ]
+	$ci Delete
+	
+	set results [ result_statistics [ $cimap GetImage ] [ $mapmask GetImage ] "COHERENCE INDEX      " ]
+    }
+
+    set enable1 [ lindex [ lindex $global_list(result_title) $LI_MAP ] 2 ]
+    set enable2 [ lindex [ lindex $global_list(result_title) $ADD_MAP ] 2 ]
+    if { [expr $enable1 || $enable2 ] } {
+	
+	if { $enable1 } {
+	    ##################### Lattice anisotropy ########################
+	    set la [ vtkmpjLatticeAnisotropy [ pxvtable::vnewobj ] ]
+	    $this ShowProgressVal "Computing statistics..." [expr 9.0 / 9]
+	    $la SetEigenvectors [ $eigenvectors GetImage ]
+	    $la SetEigenvalues [ $eigenvalues GetImage ]
+	    $la SetMask [ $mapmask GetImage ]
+	    $la SetKernelSize 3 3 3
+	    $la SetMethodToBasserAndSkare
+	    $la Update
+	    
+	    set li [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+	    $li SetInput [ $la GetOutput ]
+	    $li SetFrameNumber 0
+	    $li Update    
+	    
+	    $limap ShallowCopyImage [ $li GetOutput ]
+	    $limap CopyImageHeader [ $mask GetImageHeader ]
+	    $li Delete
+	    
+	    set results [ result_statistics [ $limap GetImage ] [ $mapmask GetImage ] "LATT ANISOTROPY (LI) " ]
+	}
+	
+	if { $enable2 } {
+	    ##################### Add #######################################
+	    set add [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+	    $add SetInput [ $la GetOutput ]
+	    $add SetFrameNumber 1
+	    $add Update    
+	    
+	    $addmap ShallowCopyImage [ $add GetOutput ]
+	    $addmap CopyImageHeader [ $mask GetImageHeader ]
+	    $add Delete
+	    
+	    $la Delete
+	    
+	    set results [ result_statistics [ $addmap GetImage ] [ $mapmask GetImage ] "LATT ANISOTROPY (Add)" ]
+	}
+    }
+    
+    set slice 0
+
+    
+    set center 0
+    catch {
+	set slice [ [ $parent GetViewer ] GetOrthoImageSlice ]
+	set center [ $slice GetLevels ]
+    } 
+
+    if { $center == 0 } {
+	set dim [ [ $tensor GetImage ] GetDimensions ]
+	set center "[expr [lindex $dim 0] / 2] [expr [lindex $dim 1] / 2] [expr [lindex $dim 2] / 2]"
+    }
+
+    set cx [ lindex $center 0 ]
+    set cy [ lindex $center 1 ]
+    set cz [ lindex $center 2 ]
+    
+    ########### Heart fiber angle
+
+    set fib [ vtkmpjHeartFiberAngle [  pxvtable::vnewobj ] ]
+    $fib SetInput [ $eigenvectors GetImage ]
+    $fib SetMask [ $mask GetImage ]
+    $fib SetCenter $cx $cy $cz
+    $fib Update
+    
+    $fibmap ShallowCopyImage [ $fib GetOutput ]
+    $fibmap CopyImageHeader [ $mask GetImageHeader ]
+    $fib Delete
+
+    ########### Heart sheet angle
+
+    set sheet [ vtkmpjHeartSheetAngle [  pxvtable::vnewobj ] ]
+    $sheet SetInput [ $eigenvectors GetImage ]
+    $sheet SetMask [ $mask GetImage ]
+    $sheet SetCenter $cx $cy $cz
+    $sheet Update
+    
+    $sheetmap ShallowCopyImage [ $sheet GetOutput ]
+    $sheetmap CopyImageHeader [ $mask GetImageHeader ]
+    $sheet Delete
+
+    ##################### Voxel count ###############################
+    set border [ string repeat "==========+" $global_list(mask_nreg) ] 
+    $widget_list(stat_text) insert end "=======================+$border\n" even
+    
+    result_add_stat " TOTAL VOXELS       " "%8d" odd $results  
+
+    $invar Delete
+
+    #    $mapmask Clear
+    if { $deletemapmask > 0 } {
+	itcl::delete object $mapmask
+    }
+
+    $this ShowProgressVal "Done." 0
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Compute results
+# -----------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::ComputeResults { } {
+    
+    set MASK 1
+    set FA_MAP 5
+
+    WatchOn
+    
+    ## clear display
+    view_clear_display
+    
+    ## clear results
+    if { $global_list(eigen_recompute) } {
+	result_clear $MASK [ expr [ llength $global_list(result_list) ] -1 ]
+    } else {
+	result_clear $FA_MAP [ expr [ llength $global_list(result_list) ] -1 ]
+    }
+
+    $widget_list(notebook) view "Statistics"; update
+
+    ## create mask if not loaded in
+    if { $global_list(mask_auto) } {
+	
+	set result [ result_createmask ]
+	
+	if { $result == 0 } {
+	    WatchOff; return
+	}
+    }
+    
+    if { $global_list(eigen_recompute) } {
+
+	## compute eigevalues and eigenvectors
+	set result [ result_createeigen ]
+ 
+	if { $result == 0 } {
+	    WatchOff; return
+	}
+    }
+
+    ## create maps
+    result_createmaps
+    
+    # send currently selected result to parent
+    $widget_list(result_list) selection set $FA_MAP $FA_MAP
+    
+    set fa_map [ lindex $global_list(result_list) $FA_MAP ]
+    $parent SetImageFromObject [ $fa_map  GetThisPointer ] $this
+
+    set range [ [ [ [ $fa_map GetImage ] GetPointData ] GetScalars ] GetRange ]
+    $widget_list(view_resultluk) SetTableRange [ lindex $range 0 ] [ lindex $range 1 ]
+    $widget_list(view_resultluk) Update
+    
+    ## update display
+    view_update_display
+
+    WatchOff
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear display
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_clear_display { } {
+    
+    ## remove eigenvectors and tensors
+    foreach item "slow med fast tensor" {
+	foreach actor $global_list(actor_${item}) {	    
+	    if { $actor != "-1" } {
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_${item}) [list -1 -1 -1 -1 ]	
+    }
+    
+    ## remove colorbars
+    set actor $global_list(actor_colorbar)
+    if { $actor != "-1" } {
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+	$actor Delete	   
+	set global_list(actor_colorbar) -1
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Update display
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_update_display { } {
+
+    if { $global_list(view_type_fast) } {	
+	view_create_eigenvector fast 0
+    }
+    
+    if { $global_list(view_type_medium) } {	
+	view_create_eigenvector med 1
+    }
+    
+    if { $global_list(view_type_slow) } { 
+	view_create_eigenvector slow 2
+    }    
+    
+    if { $global_list(view_type_tensor) } {
+	view_create_tensor 
+    }
+    
+    if { $global_list(view_type_colorbar) } {
+	view_create_colorbar
+    }
+
+    if { $bis_algorithmmode == 0 } {
+	[ $parent GetViewer ] SetDisplayMode3DIfNeeded
+        [ $parent GetViewer ] UpdateDisplay
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Compute ROI extents
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_compute_roi_extents { orient dim levels } {
+   
+    set x0(0) 0; set x0(1) 0; set x0(2) 0;
+    set x1(0) [expr [lindex $dim 0] -1]
+    set x1(1) [expr [lindex $dim 1] -1]
+    set x1(2) [expr [lindex $dim 2] -1]
+    
+    if { $orient < 3 } {
+
+	## set up slice geometry
+	for { set i 0 } { $i < 3 } { incr i } {
+	    if { $i == $orient } {
+		set x0($i) [lindex $levels $i]
+		set x1($i) [lindex $levels $i]
+	    }
+	}
+    }
+    
+    return "$x0(0) $x0(1) $x0(2) $x1(0) $x1(1) $x1(2)"
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Extract ROI given image and computed extents
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_extract_roi { exts image } {
+    
+    set dim [ [ $image GetImage ] GetDimensions ]
+    set spac [ [ $image GetImage ] GetSpacing ]
+    set orig [ [ $image GetImage ] GetOrigin ]
+    set ospac "1 1 1"
+    
+    set x0(0) [lindex $exts 0]; set x0(1) [lindex $exts 1]; set x0(2) [lindex $exts 2];
+    set x1(0) [lindex $exts 3]; set x1(1) [lindex $exts 4]; set x1(2) [lindex $exts 5];
+    
+    ## determine correct origin and spacing
+    for { set i 0 } { $i <= 2 } { incr i } {	
+ 	if { $x1($i) < $x0($i) } { set x1($i) [ expr $x0($i) +1 ] }
+ 	set dx [ lindex $ospac $i ]
+ 	if { $dx < 1 } { set dx 1 } elseif { $dx > 10 } { set dx 10 }	
+ 	set origin($i)  [ expr [lindex $orig $i ] + $x0($i) * [ lindex $spac $i ]]
+ 	set spacing($i) [ expr [lindex $spac $i ] * $dx ]
+ 	set ext($i)     [ expr ($x1($i)-$x0($i))/$dx ]
+    }
+
+    set identity [ vtkIdentityTransform [ pxvtable::vnewobj ] ]
+
+    ## extract roi
+    set roi [ vtkbisImageReslice [ pxvtable::vnewobj ] ]
+    $roi SetInput [ $image GetImage ]
+    $roi SetResliceTransform $identity
+    $roi SetOutputSpacing $spacing(0) $spacing(1) $spacing(2)
+    $roi SetOutputOrigin $origin(0)  $origin(1)  $origin(2)    
+    $roi SetOutputExtent 0 $ext(0) 0 $ext(1) 0 $ext(2)
+    $roi SetInterpolationMode 0 
+    $roi Update
+
+    $identity Delete
+
+    return $roi
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create tensor glyphs
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_create_tensor_glyph { tensor scalar glyph where } {
+
+    ## convert image into tensor attribute
+    set imtoten [ vtkmpjImageToTensors [ pxvtable::vnewobj ] ]
+    $imtoten SetInput $tensor
+    $imtoten SetSymmetricTensor $global_list(tensor_symm)
+#    $imtoten SetFlipX $global_list(tensor_flipx)
+#    $imtoten SetFlipY $global_list(tensor_flipy)
+#    $imtoten SetFlipZ $global_list(tensor_flipz)
+    $imtoten Update
+    
+    ## combine geometry information
+    set merge $global_list(vtk_tensor_merge,$where)
+    $merge SetGeometry $tensor
+    $merge SetScalars $scalar
+    $merge SetTensors [ $imtoten GetOutput ]
+    $merge Update
+    
+    $imtoten Delete
+    
+    ## threshold resulting dataset 
+    set thresh $global_list(vtk_tensor_threshold,$where)
+    $thresh SetInput [ $merge GetOutput ]
+    if { $global_list(view_tensor_between) == 1 } {
+	$thresh ThresholdBetween $global_list(view_tensor_from) $global_list(view_tensor_to)
+    } else {
+	$thresh ThresholdByUpper $global_list(view_tensor_from)
+    }
+    $thresh Update
+
+    ## create glyph field
+    set glypher $global_list(vtk_tensor_glypher,$where)
+    $glypher SetInput [ $thresh GetOutput ]
+    $glypher SetSource [ $glyph GetOutput ]
+    $glypher SymmetricOn
+    #$glypher ExtractEigenvaluesOff
+    $glypher SetScaleFactor $global_list(view_tensor_scale)
+    $glypher SetClampScaling $global_list(view_tensor_clampscale)
+    $glypher SetMaxScaleFactor $global_list(view_tensor_maxscale)
+    $glypher Update
+
+    ## compute surface normals
+    set glyphNormals [ vtkPolyDataNormals [ pxvtable::vnewobj ] ]
+    $glyphNormals SetInput [ $glypher GetOutput ]
+
+    ## set up glyph mapper
+    set glyphMapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    $glyphMapper SetInput [ $glyphNormals GetOutput ]
+    $glyphMapper SetLookupTable [ $widget_list(view_tensorluk) GetLookupTable ]
+    $glyphMapper UseLookupTableScalarRangeOn
+    $glyphMapper SetColorModeToMapScalars
+    $glyphMapper ScalarVisibilityOn
+
+    $glyphNormals Delete
+
+    ## create glyph actor
+    set glyphActor [ vtkActor [ pxvtable::vnewobj ] ]
+    $glyphActor SetMapper $glyphMapper
+    
+    $glyphMapper Delete
+    
+    return $glyphActor
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create eigenvector glyphs
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_create_eigenvector_glyph { index vectors scalar glyph where } {
+
+    ## extract eigenvector subset 
+    set subset [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+    $subset SetInput $vectors
+    $subset SetStartFrame [expr $index * 3]
+    $subset SetEndFrame [expr $index * 3 + 2]
+    $subset Update
+    
+    ## convert image into vector attribute
+    set imtovec [ vtkmpjImageToVectors [ pxvtable::vnewobj ] ]
+    $imtovec SetInput [ $subset GetOutput ]
+    if { $global_list(view_eigen_flip) } {
+	$imtovec SetFlipX $global_list(tensor_flipx)
+	$imtovec SetFlipY $global_list(tensor_flipy)
+	$imtovec SetFlipZ $global_list(tensor_flipz)
+    }
+    $imtovec Update
+
+    $subset Delete
+    
+    ## combine geometry information
+    set merge $global_list(vtk_eigen_merge,$index,$where)
+    $merge SetGeometry $vectors
+    $merge SetScalars $scalar
+    $merge SetVectors [ $imtovec GetOutput ]
+    $merge Update
+    
+    $imtovec Delete
+    
+    ## threshold resulting dataset 
+    set thresh $global_list(vtk_eigen_threshold,$index,$where)
+    $thresh SetInput [ $merge GetOutput ]
+    if { $global_list(view_eigen_between) == 1 } {
+	$thresh ThresholdBetween $global_list(view_eigen_from) $global_list(view_eigen_to)
+    } else {
+	$thresh ThresholdByUpper $global_list(view_eigen_from)
+    }
+    $thresh Update
+    
+    ## create glypher field   
+    set glypher $global_list(vtk_eigen_glypher,$index,$where)
+    $glypher SetInput [ $thresh GetOutput ]
+    $glypher SetSource [ $glyph GetOutput ]
+    $glypher ScalingOn
+    $glypher ClampingOn
+    $glypher SetScaleFactor $global_list(view_eigen_maxscale)
+    $glypher SetScaleModeToDataScalingOff
+    $glypher SetColorModeToColorByScalar
+    $glypher SetVectorModeToUseVector
+    $glypher Update
+
+    ## set up glyph mapper
+    set glyphMapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    $glyphMapper SetInput [ $glypher GetOutput ]
+    $glyphMapper SetLookupTable [ $widget_list(view_vectorluk) GetLookupTable ]
+    $glyphMapper UseLookupTableScalarRangeOn
+    $glyphMapper SetColorModeToMapScalars
+    $glyphMapper ScalarVisibilityOn
+
+    ## create glyph actor
+    set glyphActor [ vtkActor [ pxvtable::vnewobj ] ]
+    $glyphActor SetMapper $glyphMapper
+    
+    $glyphMapper Delete
+    
+    return $glyphActor
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off fast eigenvector visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_type_toggle_fast_eigenvector { } {                
+    
+    if { $global_list(view_type_fast) } {	
+	view_create_eigenvector fast 0
+    } else {
+	foreach actor $global_list(actor_fast) {	    
+	    if { $actor != "-1" } {
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_fast) [ list -1 -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off medium-speed eigenvector visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_type_toggle_med_eigenvector { } {                
+
+    if { $global_list(view_type_medium) } {	
+	view_create_eigenvector med 1
+    } else {
+	foreach actor $global_list(actor_med) {	    
+	    if { $actor != "-1" } {
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_med) [ list -1 -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off medium-speed eigenvector visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_type_toggle_slow_eigenvector { } {                
+
+    if { $global_list(view_type_slow) } {	
+	view_create_eigenvector slow 2
+    } else { 
+	foreach actor $global_list(actor_slow) {	    
+	    if { $actor != "-1" } {
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_slow) [list -1 -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off tensor visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_type_toggle_tensor { } {                
+
+    if { $global_list(view_type_tensor) } {	
+	view_create_tensor
+    } else { 
+	foreach actor $global_list(actor_tensor) {
+	    if { $actor != "-1" } {
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_tensor) [ list -1 -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off colorbar visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_type_toggle_colorbar { } {
+    
+    if { $global_list(view_type_colorbar) } {
+	view_create_colorbar
+    } else {
+	set actor $global_list(actor_colorbar)
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor
+	$actor Delete
+
+	set global_list(actor_colorbar) -1
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  View tensors
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_create_tensor { } {
+    
+    set TENSOR 0
+    set EIGENVECTORS 3
+
+    ## get tensor information
+    set tensor_image [ lindex $global_list(result_list) $TENSOR ]
+    
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set dims [ [ $tensor_image GetImage ] GetDimensions ]
+    
+    ## get current eigenvector scalar filter
+    set filter [ $widget_list(view_tensor_filter) index [ $widget_list(view_tensor_filter) get ] ]
+    set tensor_filter [ lindex $global_list(result_list) $filter ] 
+
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_tensor_glyph) index [ $widget_list(view_tensor_glyph) get ] ]
+    set glyph_source [ lindex $global_list(glyph_list) [ expr $cur_glyph + 3 ] ]
+    #    set glyph_source [ lindex $global_list(glyph_list) 3 ]
+    
+    if { $global_list(view_mode_index) < 4 } {
+	    
+	    ## plot on slices
+	    for { set i 0 } { $i < 3 } { incr i } {
+
+		if { [expr ($global_list(view_mode_index) == $i) || \
+			  ($global_list(view_mode_index) == 3) ] } {
+		    
+		    set ext [ view_compute_roi_extents $i $dims $levels ]
+		    set tensors [ [ view_extract_roi $ext $tensor_image ] GetOutput ]
+		    set scalars [ [ view_extract_roi $ext $tensor_filter ] GetOutput ]
+		    
+		    set actor [ view_create_tensor_glyph $tensors $scalars $glyph_source $i ]
+		    set global_list(actor_tensor) [ lreplace $global_list(actor_tensor) $i $i $actor ]
+		    
+		    $tensors Delete
+		    $scalars Delete
+		    
+		    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+		    
+		}
+		
+	    }
+    
+    } else {
+	
+	## plot on entire volume
+	set tensors [ $tensor_image GetImage ]
+	set scalars [ $tensor_filter GetImage ]
+
+	## create glyph
+	set actor [ view_create_tensor_glyph $tensors $scalars $glyph_source 3 ]
+	
+	set global_list(actor_tensor) [ lreplace $global_list(actor_tensor) 3 3 $actor ]
+	
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  View eigenvectors
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_create_eigenvector { title index } {
+    
+    ## which: (0) view_type_fast, (1) view_type_med, (2) view_type_slow, (3) view_type_tensor
+    set TENSOR 0
+    set MASK 1
+    set EIGENVALUES 2
+    set EIGENVECTORS 3
+    
+    set actornm "actor_$title"
+        
+    ## get eigenvalues and eigenvectors
+    set eigenvalues [ lindex $global_list(result_list) $EIGENVALUES ]
+    set eigenvectors [ lindex $global_list(result_list) $EIGENVECTORS ]
+
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set dims [ [ $eigenvalues GetImage ] GetDimensions ]
+    
+    ## get current eigenvector scalar filter
+    set filter [ $widget_list(view_eigen_filter) index [ $widget_list(view_eigen_filter) get ] ]
+    set eigenfilter [ lindex $global_list(result_list) $filter ] 
+    
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_eigen_glyph) index [ $widget_list(view_eigen_glyph) get ] ]
+    set glyph_source [ lindex $global_list(glyph_list) $cur_glyph ]
+    
+    if { $global_list(view_mode_index) < 4 } {
+	
+	## plot on slices
+	for { set i 0 } { $i < 3 } { incr i } {
+	    
+	    if { [ expr ($global_list(view_mode_index) == $i) || \
+		       ($global_list(view_mode_index) == 3) ] } {
+		
+		set ext [ view_compute_roi_extents $i $dims $levels ]
+		set vectors [ [ view_extract_roi $ext $eigenvectors ] GetOutput ]
+		set scalars [ [ view_extract_roi $ext $eigenfilter ] GetOutput ]
+		
+		set actor [ view_create_eigenvector_glyph $index $vectors $scalars $glyph_source $i ]
+		set global_list($actornm) [ lreplace $global_list($actornm) $i $i $actor ]
+		
+		$vectors Delete
+		$scalars Delete
+		
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+	    }
+	    
+	}
+    
+    } else {
+
+	## plot on entire volume
+	set vectors [ $eigenvectors GetImage ]
+	set scalars [ $eigenfilter GetImage ]
+
+	## create glyph
+	set actor [ view_create_eigenvector_glyph $index $vectors $scalars $glyph_source 3 ]
+	
+	set global_list($actornm) [ lreplace $global_list($actornm) 3 3 $actor ]
+	
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+	
+    }       
+}
+
+#-------------------------------------------------------------------------------------------
+#  View colorbar
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_create_colorbar { } {
+    
+    set cbar(Eigenvectors) 0
+    set cbar(Tensor) 1
+    set cbar(Results) 2
+
+    set title "colorbar"
+
+    set colorbar $cbar($global_list(view_colorbar))
+        
+    set filter 0
+    if { $colorbar == 0 } {
+	set filter [ $widget_list(view_eigen_filter) index [ $widget_list(view_eigen_filter) get ] ]
+    } elseif { $colorbar == 1 } {
+	set filter [ $widget_list(view_tensor_filter) index [ $widget_list(view_tensor_filter) get ] ]
+    } 
+
+    if { $colorbar < 2 } {
+	set title [ lindex [ lindex $global_list(result_title) $filter ] 0 ] 
+    } else {
+	set title $global_list(view_colorbar_label)
+    }
+    
+    set bar [ vtkScalarBarActor [ pxvtable::vnewobj ] ]
+    
+    if { $colorbar == 0 } {
+	$bar SetLookupTable [ $widget_list(view_vectorluk) GetLookupTable ]
+    } elseif { $colorbar == 1 } { 
+	$bar SetLookupTable [ $widget_list(view_tensorluk) GetLookupTable ]
+    } elseif { $colorbar == 2 } {
+	$bar SetLookupTable [ $widget_list(view_resultluk) GetLookupTable ]
+    }
+    
+    $bar SetTitle $title
+    [$bar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport
+    [$bar GetPositionCoordinate] SetValue 0.1 0.01
+    $bar SetOrientationToHorizontal
+    $bar SetWidth 0.8
+    $bar SetHeight 0.12
+    
+    set global_list(actor_colorbar) $bar
+    
+    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor2D $bar    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in display type
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_mode_cb { } {
+        
+    set mode(XZ-plane) 0
+    set mode(YZ-plane) 1
+    set mode(XY-plane) 2
+    set mode(3-slice) 3
+    set mode(Volume) 4
+    set mode(None) 5
+    
+    set global_list(view_mode_index) $mode($global_list(view_mode))
+
+    view_clear_display
+
+    view_update_display
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in tensor colormap selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_tensor_cmapcopy_cb { } {
+    
+    ## current tensor filter
+    set cpfrom [ $widget_list(view_tensor_cmapcopy) index [ $widget_list(view_tensor_cmapcopy) get ] ]
+
+    set global_list(view_tensor_cmapcopy) $cpfrom
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon copy eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_tensor_cmapcopybtn_cb { } {
+    
+    if { $global_list(view_tensor_cmapcopy) == 0 } {
+	$widget_list(view_tensorluk) Copy [ $widget_list(view_vectorluk) GetLookupTable ]
+    } else {
+	$widget_list(view_tensorluk) Copy [ $widget_list(view_resultluk) GetLookupTable ]
+    }
+        
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon copy eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_tensor_cmapresetbtn_cb { } {
+    
+    ## current tensor filter
+    $widget_list(view_tensorluk) SetHueRange 0.5 0.0
+    $widget_list(view_tensorluk) Update
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon loading eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_tensor_cmaploadbtn_cb { } {   
+
+    $widget_list(view_tensorluk) Load
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon saving eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_tensor_cmapsavebtn_cb { } {   
+
+    $widget_list(view_tensorluk) SaveAs
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in tensor filter selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_tensor_filter_cb { } {
+    
+    set TENSOR 0
+    
+    ## current eigenvector filter
+    set filter [ $widget_list(view_tensor_filter) index [ $widget_list(view_tensor_filter) get ] ]   
+    set tensor_filter [ lindex $global_list(result_list) $filter ] 
+
+    ## get eigenvalues and eigenvectors
+    set tensor_image [ lindex $global_list(result_list) $TENSOR ]
+    
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set dims [ [ $tensor_image GetImage ] GetDimensions ]
+    
+    if { $global_list(view_mode_index) < 4 } {	
+	
+	## plot on slices
+	for { set i 0 } { $i < 3 } { incr i } {
+	    
+	    if { [expr ($global_list(view_mode_index) == $i ) || \
+		      ($global_list(view_mode_index) == 3) ] } {		
+		
+		set ext [ view_compute_roi_extents $i $dims $levels ]
+		set scalar [ [ view_extract_roi $ext $tensor_filter ] GetOutput ]
+		
+		set merge $global_list(vtk_tensor_merge,$i)
+		$merge SetScalars $scalar
+		
+		$scalar Delete	    	    
+	    }
+	}	
+	
+    } else {
+	
+	## plot on entire volume
+	set scalar [ [ lindex $global_list(result_list) $filter ] GetImage ]
+	
+	set merge $global_list(vtk_tensor_merge,3)
+	$merge SetScalars $scalar
+    }
+    
+    set result [ [ lindex $global_list(result_list) $filter ] GetImage ]
+    set range [ [ [ $result GetPointData ] GetScalars ] GetRange ]
+    $widget_list(view_tensorluk) SetTableRange [ lindex $range 0 ] [ lindex $range 1 ]
+#    $widget_list(view_tensorluk) Update
+    
+    ## update scalar bar    
+    if { $global_list(view_colorbar) == "Tensor" } {
+	set title [ lindex [ lindex $global_list(result_title) $filter ] 0 ] 
+	if { $global_list(actor_colorbar) != -1 } { 
+	    $global_list(actor_colorbar) SetTitle $title
+	}
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in eigen colormap selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_eigen_cmapcopy_cb { } {
+    
+    ## current eigenvector filter
+    set cpfrom [ $widget_list(view_eigen_cmapcopy) index [ $widget_list(view_eigen_cmapcopy) get ] ]
+
+    set global_list(view_eigen_cmapcopy) $cpfrom
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon copy eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_eigen_cmapcopybtn_cb { } {
+    
+    if { $global_list(view_eigen_cmapcopy) == 0 } {
+	$widget_list(view_vectorluk) Copy [ $widget_list(view_tensorluk) GetLookupTable ]
+    } else {
+	$widget_list(view_vectorluk) Copy [ $widget_list(view_resultluk) GetLookupTable ]
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon resetting eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_eigen_cmapresetbtn_cb { } {
+    
+    ## current tensor filter
+    $widget_list(view_vectorluk) SetHueRange 0.75 0.0
+    $widget_list(view_vectorluk) Update
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon loading eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_eigen_cmaploadbtn_cb { } {
+
+    $widget_list(view_vectorluk) Load
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon saving eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_eigen_cmapsavebtn_cb { } {
+
+    $widget_list(view_vectorluk) SaveAs
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in vector filter selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_eigen_filter_cb { } {    
+      
+    set EIGENVALUES 2
+    set EIGENVECTORS 3
+
+    ## current eigenvector filter
+    set filter [ $widget_list(view_eigen_filter) index [ $widget_list(view_eigen_filter) get ] ]   
+    
+    ## get eigenvalues and eigenvectors
+    set eigenvalues [ lindex $global_list(result_list) $EIGENVALUES ]
+    set eigenvectors [ lindex $global_list(result_list) $EIGENVECTORS ]
+
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set dims [ [ $eigenvalues GetImage ] GetDimensions ]
+
+    if { $global_list(view_mode_index) < 4 } {
+	
+	## plot on slices
+	for { set i 0 } { $i < 3 } { incr i } {
+	    
+	    if { [expr ($global_list(view_mode_index) == $i ) || \
+		      ($global_list(view_mode_index) == 3) ] } {
+		
+		set ext [ view_compute_roi_extents $i $dims $levels ]
+		set scalar [ view_extract_roi $ext [ lindex $global_list(result_list) $filter ] ]
+	    
+		## loop through eigenvectors
+		for { set j 0 } { $j < 3 } { incr j } {
+		    set merge $global_list(vtk_eigen_merge,$j,$i)
+		    $merge SetScalars [ $scalar GetOutput ]
+		}
+		
+		$scalar Delete
+	    }
+	}
+    } else {
+	
+	## plot on entire volume
+	#	set ext [ view_compute_roi_extents 3 $dims $levels ]
+	set scalar [ [ lindex $global_list(result_list) $filter ] GetImage ]
+	
+	## loop through eigenvectors
+	for { set j 0 } { $j < 3 } { incr j } {
+	    set merge $global_list(vtk_eigen_merge,$j,3)
+	    $merge SetScalars $scalar
+	}		
+    }
+
+    set result [ [ lindex $global_list(result_list) $filter ] GetImage ]
+    set range [ [ [ $result GetPointData ] GetScalars ] GetRange ]
+    $widget_list(view_vectorluk) SetTableRange [ lindex $range 0 ] [ lindex $range 1 ]
+#    $widget_list(view_vectorluk) Modified
+    #$widget_list(view_vectorluk) Update
+
+    ## update scalar bar    
+    if { $global_list(view_colorbar) == "Eigenvectors" } {
+	set title [ lindex [ lindex $global_list(result_title) $filter ] 0 ] 
+	if { $global_list(actor_colorbar) != -1 } { 
+	    $global_list(actor_colorbar) SetTitle $title
+	}
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in threshold values
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_tensor_fromto_cb { } {
+    for { set j 0 } { $j < 4 } { incr j } { 
+	if { $global_list(view_tensor_between) == 1 } {
+	    $global_list(vtk_tensor_threshold,$j) ThresholdBetween \
+		$global_list(view_tensor_from) $global_list(view_tensor_to)
+	} else {
+	    $global_list(vtk_tensor_threshold,$j) ThresholdByUpper \
+		$global_list(view_tensor_from)
+	}
+    }
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in threshold values
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_eigen_fromto_cb { } {
+    for { set i 0 } { $i < 3 } { incr i } {	
+	for { set j 0 } { $j < 4 } { incr j } { 
+	    if { $global_list(view_eigen_between) == 1 } {
+		$global_list(vtk_eigen_threshold,$i,$j) ThresholdBetween \
+		    $global_list(view_eigen_from) $global_list(view_eigen_to)
+	    } else {
+		$global_list(vtk_eigen_threshold,$i,$j) ThresholdByUpper \
+		    $global_list(view_eigen_from)
+	    }
+	}
+    }
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in glyph type
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_eigen_glyph_cb { } {    
+    set index [ $widget_list(view_eigen_glyph) index [ $widget_list(view_eigen_glyph) get ] ]
+    set glyph [ lindex $global_list(glyph_list) $index ]
+    for { set i 0 } { $i < 3 } { incr i } {
+	for { set j 0 } { $j < 4 } { incr j } { 
+	    $global_list(vtk_eigen_glypher,$i,$j) SetSource [ $glyph GetOutput ]
+	}
+    }
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in glyph type
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_tensor_glyph_cb { } {    
+    set index [ $widget_list(view_tensor_glyph) index [ $widget_list(view_tensor_glyph) get ] ]
+    set glyph [ lindex $global_list(glyph_list) [expr $index + 3 ] ]
+    for { set j 0 } { $j < 4 } { incr j } { 
+	$global_list(vtk_tensor_glypher,$j) SetSource [ $glyph GetOutput ]
+    }
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in threshold values
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_tensor_maxscale_cb { } {
+    for { set j 0 } { $j < 4 } { incr j } {
+	$global_list(vtk_tensor_glypher,$j) \
+	    SetScaleFactor $global_list(view_tensor_scale)
+	$global_list(vtk_tensor_glypher,$j) \
+	    SetMaxScaleFactor $global_list(view_tensor_maxscale)
+	$global_list(vtk_tensor_glypher,$j) \
+	    SetClampScaling $global_list(view_tensor_clampscale)
+    }
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in threshold values
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_eigen_maxscale_cb { } {
+    for { set i 0 } { $i < 3 } { incr i } {
+	for { set j 0 } { $j < 4 } { incr j } {
+	    $global_list(vtk_eigen_glypher,$i,$j) \
+		SetScaleFactor $global_list(view_eigen_maxscale)
+	}
+    }
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in colorbar selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_colorbar_cb { } {
+
+    ## recreate colorbar
+    set actor $global_list(actor_colorbar)
+    if { $actor != -1 } {
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor
+	$actor Delete
+    }
+
+    if { $global_list(view_type_colorbar) } {
+	view_create_colorbar
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Toggles display auto-update
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_toggle_autoupdate { } {
+    
+    if { $global_list(view_autoupdate) } {
+	
+        eval "$parent configure -mousecallback \"$this view_update_crosshair_cb\""
+	
+	view_update_display_cb 
+	
+    } else {
+	
+	eval "$parent configure -mousecallback 0"
+	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC CALLBACK: Invoked upon an crosshair update from viewer
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_update_crosshair_cb { args } {
+
+    set mousebutton [ lindex $args 1 ]
+    set mousestate  [ lindex $args 2 ]
+
+    if { $global_list(view_mode_index) < 4 } {
+
+         ## get last clicked point in the viewer
+	 set lv [ lindex [ [ $parent GetViewer ] GetLastClickedPointScaled ] 0 ]
+	    
+         ##puts stderr "mouse = $mousebutton / $mousestate , point = $lv "
+	    
+	 if { $lv != -1 } {	    
+
+	     view_clear_display
+		 
+	     view_update_display
+	 }
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC CALLBACK: Invoked upon an update button press
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_update_display_cb { } { 
+    
+       view_clear_display
+
+       view_update_display
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in colormaps for result images
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_results_colormap_cb { } {
+
+    set luk [ $widget_list(view_resultluk) GetLookupTable ]
+    
+    if { $global_list(view_transparent) } {
+#	set rgba [ $luk GetTableValue 0 ]
+	set index [ $luk GetIndex $global_list(view_transpcolor) ]
+#	puts "color: $global_list(view_transpcolor) $index"
+	set rgba [ $luk GetTableValue $index ]
+	$luk SetTableValue $index [ lindex $rgba 0 ] [ lindex $rgba 1 ] [ lindex $rgba 2 ] 0.0
+    } else {
+	$widget_list(view_resultluk) Update
+	set luk [ $widget_list(view_resultluk) GetLookupTable ]
+    }
+
+    # --------------------------
+    # Update Image Lookup Table
+    # --------------------------
+
+    # Manipulate luk on the fly to set the range
+    #    [ $parent GetViewer ] SetLookupTable $luk
+    # Send this to overlay lookup table
+    [ $parent GetViewer ]  SetObjectLookupTable $luk
+    [ $parent GetViewer ] UpdateDisplay
+
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon selection of tensor direction coloring
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::view_direction_update_cb { } {
+    
+    set TENSOR 0
+    set MASK 1
+    set EIGENVECTORS 3
+    set DEC_MAP 12
+    
+    set filter [ $widget_list(view_direction_filter) index \
+		     [ $widget_list(view_direction_filter) get ] ]   
+    
+    set scheme [ $widget_list(view_direction_scheme) index \
+		     [ $widget_list(view_direction_scheme) get ] ]   
+    
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set eigenvectors [ lindex $global_list(result_list) $EIGENVECTORS ]
+    
+    set magmap [ lindex $global_list(result_list) $filter ]
+    
+    set imct [ vtkmpjImageTensorColor [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $imct "Computing colormap..."
+    $imct SetInput [ $eigenvectors GetImage ]
+    $imct SetColorSchemeType $scheme
+    $imct SetSaturationScale $global_list(view_direction_satscale)
+    $imct SetScaling $global_list(view_direction_scaling)
+    $imct SetMagnitude [ $magmap GetImage ]
+    
+    if { $global_list(view_direction_mask) == 1 } {
+	$imct SetMask [ $mask GetImage ]
+    }
+    
+    $imct Update
+
+    set imctmap [ lindex $global_list(result_list) $DEC_MAP ]
+    $imctmap ShallowCopyImage [ $imct GetOutput ]    
+    $imctmap CopyImageHeader [ $tensor GetImageHeader ]
+
+    if { $bis_orientationimage == 0 } {
+	set bis_orientationimage [ [ pxitclimage \#auto ] GetThisPointer ]
+    }
+    $bis_orientationimage ShallowCopyImage [ $imct GetOutput ]    
+    $bis_orientationimage CopyImageHeader [ $tensor GetImageHeader ]
+
+
+    $parent SetImageFromObject	[ $imctmap GetThisPointer ] $this
+    $imct Delete  
+
+
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create tensor control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateTensorControl { base } {
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Tensor image"
+    pack $base.frame0 -fill both -expand f -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+  
+    set tensor_fname [ iwidgets::entryfield $subframe1.mask_fname \
+			   -textvariable [ itcl::scope global_list(tensor_fname) ] \
+			   -labeltext "Filename:" ] 
+    pack $tensor_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(tensor_fname) $tensor_fname
+    
+    set tensor_load [ iwidgets::buttonbox $subframe1.tensor_load -orient horizontal -padx 2 ]
+    $tensor_load add load -text "Load..." -command [ itcl::code $this loadtensor ] 
+    $tensor_load add disp -text "Display" -command [ itcl::code $this DisplayResult 0 ]
+    pack $tensor_load -side left
+    set widget_list(tensor_load) $tensor_load  
+
+    set tensor_ordering \
+	[ iwidgets::optionmenu $subframe1.tensor_ordering -labeltext "Components:" ]
+    $tensor_ordering configure -command [ itcl::code $this tensor_ordering_cb ]
+    $tensor_ordering insert 0 "xx-xy-xz-yy-yz-zz"
+    $tensor_ordering insert 1 "xx-yy-zz-xy-yz-xz"
+    pack $tensor_ordering -side right -padx 5
+    set widget_list(tensor_ordering) $tensor_ordering
+
+
+
+
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Region of interest mask"
+    pack $base.frame1 -fill both -expand f
+    
+    set frame1 [ $base.frame1 childsite ]
+    
+    set subframe0 [ frame $frame1.subframe0 ]
+    pack $subframe0 -side top -fill both -expand f -pady 5
+    
+    set mask_auto [ checkbutton $subframe0.mask_auto \
+			-text "Estimate from tensor" \
+			-variable [ itcl::scope global_list(mask_auto) ] \
+			-command [ itcl::code $this mask_autochanged_cb ] ]
+    pack $mask_auto -side left -fill both -padx 5 -pady 2
+    
+    set mask_threshval [ iwidgets::entryfield $subframe0.mask_threshval \
+			     -labeltext "Threshold tensor at:" \
+			     -validate real -width 5  \
+			     -textvariable [ itcl::scope global_list(mask_threshval) ] ]
+    pack $mask_threshval -side right -pady 5 -padx 5
+    set widget_list(mask_threshval) $mask_threshval
+
+    set subframe1 [ frame $frame1.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+    
+    set mask_fname [ iwidgets::entryfield $subframe1.mask_fname \
+			 -textvariable [ itcl::scope global_list(mask_fname) ] \
+			 -state disabled \
+			 -labeltext "Filename:" ] 
+    pack $mask_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(mask_fname) $mask_fname
+
+    set mask_load [ iwidgets::buttonbox $subframe1.mask_load -orient horizontal -padx 2 ]
+    $mask_load add load -text "Load..." -command [ itcl::code $this loadmask ]    
+    $mask_load add disp -text "Display" -command [ itcl::code $this DisplayResult 1 ]
+    pack $mask_load -side left 
+    $mask_load buttonconfigure load -state disabled
+    $mask_load buttonconfigure disp -state disabled
+    set widget_list(mask_load) $mask_load
+    
+    set mask_nreg [ iwidgets::spinint $subframe1.mask_nreg \
+			-labeltext "Number of regions in mask:" \
+			-fixed 4 -width 4 -range {1 1000} -step 1 \
+			-textvariable [ itcl::scope global_list(mask_nreg) ] \
+			-state disabled ]
+    pack $mask_nreg -side right -padx 5 -pady 5
+    set widget_list(mask_nreg) $mask_nreg
+
+    set subframe2 [ frame $frame1.subframe2 ]
+    pack $subframe2 -side top -fill both -expand f -pady 0
+
+    set mask_negative [ checkbutton $subframe2.mask_negative \
+			    -text "Mask out regions with negative eigenvalues" \
+			    -variable [ itcl::scope global_list(mask_negative) ] ]
+    pack $mask_negative -side left -fill both -padx 5 -pady 5
+ 
+    set frame2 [ frame $base.frame2 ]
+    pack $frame2 -side top -fill both -expand f 
+
+    set widget_list(computebtn) [ button $frame2.compute -text "Compute!" \
+				      -state disabled \
+				      -command [ itcl::code $this ComputeResults ] ]    
+    pack $frame2.compute -side left -fill x -expand f -padx 5 -pady 10  
+    
+    set eigen_recompute [ checkbutton $frame2.eigen_recompute \
+			      -text "Always recompute eigensystem" \
+			      -variable [ itcl::scope global_list(eigen_recompute) ] ]
+    pack $eigen_recompute -side right -fill both -padx 5 -pady 5
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create transform control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateTransformControl { base } {
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Tensor transformation"
+    pack $base.frame0 -fill both -expand t -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+
+    set tensorflipx [ checkbutton $subframe1.tensorflipx \
+			  -text "Flip X" \
+			  -command [ itcl::code $this view_update_display_cb ] \
+			  -variable [ itcl::scope global_list(tensor_flipx) ] ]
+    pack $tensorflipx -side left -padx 5 -pady 7
+    set widget_list(tensor_flipx) $tensorflipx
+    
+    set tensorflipy [ checkbutton $subframe1.tensorflipy \
+			  -text "Flip Y" \
+			  -command [ itcl::code $this view_update_display_cb ] \
+			  -variable [ itcl::scope global_list(tensor_flipy) ] ]
+    pack $tensorflipy -side left -padx 5 -pady 7
+    set widget_list(tensor_flipy) $tensorflipy   
+    
+    set tensorflipz [ checkbutton $subframe1.tensorflipz \
+			  -text "Flip Z" \
+			  -command [ itcl::code $this view_update_display_cb ] \
+			  -variable [ itcl::scope global_list(tensor_flipz) ] ]
+    pack $tensorflipz -side left -padx 5 -pady 7
+    set widget_list(tensor_flipz) $tensorflipz
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill both -expand f -pady 0
+
+    iwidgets::entryfield $subframe2.tensor_rotx \
+	-width 5 \
+	-validate real \
+	-labeltext "Tensor rotation  Rx:" \
+	-textvariable [ itcl::scope global_list(tensor_rotx) ]
+    pack $subframe2.tensor_rotx -side left -fill x -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe2.tensor_roty \
+	-width 5 \
+	-validate real \
+	-labeltext "Ry:" \
+	-textvariable [ itcl::scope global_list(tensor_roty) ]
+    pack $subframe2.tensor_roty -side left -fill x -pady 5
+    
+    iwidgets::entryfield $subframe2.tensor_rotz \
+	-width 5 \
+	-validate real \
+	-labeltext "Rz:" \
+	-textvariable [ itcl::scope global_list(tensor_rotz) ]
+    pack $subframe2.tensor_rotz -side left -fill x -pady 5
+
+    label $subframe2.dummy -text "degrees"
+    pack $subframe2.dummy -side left
+        
+    set tensor_rotation [ button $subframe2.tensor_rotation \
+			      -command [ itcl::code $this result_rotatetensor ] \
+			      -text "Rotate!" ]
+    pack $tensor_rotation -side left -fill both -padx 5 -pady 5
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create results control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateResultsControl { base } {   
+
+    set color(0) \#dcdcdc
+    set color(1) black
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Results"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+    
+    iwidgets::scrolledlistbox $subframe0.resultlist \
+	-hscrollmode dynamic \
+	-selectmode extended \
+	-dblclickcommand [ itcl::code $this toggleresult ] \
+	-visibleitems 40x10 
+    
+    pack $subframe0.resultlist -side left -fill both -expand t -padx 2 -pady 2
+    set widget_list(result_list) $subframe0.resultlist
+    
+    foreach item $global_list(result_title) {
+	set enable [ lindex $item 2 ]
+     	$widget_list(result_list) insert end "[lindex $item 0]" 
+	$widget_list(result_list) itemconfigure end -foreground $color($enable)
+    }
+
+    set subframe1 [ frame $subframe0.subframe1 ]
+    pack $subframe1 -side right -fill both -padx 0
+    
+    set resultbbox [ iwidgets::buttonbox $subframe1.input -orient vertical ]
+    $resultbbox add display -text "Display" -command [ itcl::code $this displayresult image ]
+    $resultbbox add odisplay -text "Overlay" -command [ itcl::code $this displayresult overlay ]
+    $resultbbox add save -text "Save..." -command [ itcl::code $this saveresult ]
+    $resultbbox add saveall -text "Save all" -command [ itcl::code $this saveallresults ]    
+    $resultbbox add mark -text "On/Off" -command [ itcl::code $this toggleresult ]
+    pack $resultbbox -side top -fill x -expand t -padx 0
+    set widget_list(result_buttonbox) $resultbbox
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill x -padx 2 -pady 5
+
+    set result_fpreffix [ iwidgets::entryfield $subframe2.result_fpreffix \
+			      -textvariable [ itcl::scope global_list(result_fpreffix) ] \
+			      -labeltext "Preffix:" ]
+    pack $result_fpreffix -side left -fill x -expand t -padx 5 -pady 2
+    set widget_list(result_fpreffix) $result_fpreffix    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create statistics control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateStatisticsControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Statistics"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+
+    set stat_text [iwidgets::scrolledtext $subframe0.stat_text \
+		       -visibleitems 70x19 \
+		       -foreground black \
+		       -vscrollmode static \
+		       -hscrollmode dynamic \
+		       -wrap none ]
+    pack $stat_text -side top -expand t -fill both -padx 2 -pady 2
+    set widget_list(stat_text) $stat_text
+
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -expand t
+
+    set statbbox [ iwidgets::buttonbox $subframe1.statbbox -orient horizontal -pady 2 -padx 2 ]
+    $statbbox add save -text "Save..." -command [ itcl::code $this savestatistics ]
+    $statbbox add clear -text "Clear" -command "$stat_text delete 1.0 end"
+    pack $statbbox -side left -fill both 
+
+    set stat_overwrite [ checkbutton $subframe1.stat_overwrite -text "Overwrite" \
+			     -variable [ itcl::scope global_list(stat_overwrite) ] ]
+    pack $stat_overwrite -side right -padx 5       
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create eigenvector display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateEigenDisplayControl { base } {
+
+    set FA_MAP 5
+
+    set subframe0 [ frame $base.subframe0 ]
+    pack $subframe0 -fill x -side top -padx 5 -expand f -pady 5
+        
+    set view_eigen_filter \
+	[ iwidgets::optionmenu $subframe0.view_eigen_filter -labeltext "Filter:" ]
+    $view_eigen_filter configure -command [ itcl::code $this view_eigen_filter_cb ]
+    for { set i 0 } { $i < [ llength $global_list(result_title) ] } { incr i } {
+	$view_eigen_filter insert $i [ lindex [ lindex $global_list(result_title) $i ] 0 ]
+    }
+    pack $view_eigen_filter -side left -padx 5
+    set widget_list(view_eigen_filter) $view_eigen_filter
+
+    $view_eigen_filter select $FA_MAP
+    
+    iwidgets::entryfield $subframe0.view_eigen_from \
+	-width 5 \
+	-validate real \
+	-labeltext "From:" \
+	-textvariable [ itcl::scope global_list(view_eigen_from) ] \
+	-command [ itcl::code $this view_eigen_fromto_cb ]
+    pack $subframe0.view_eigen_from -side left -fill x -padx 5
+    
+    checkbutton $subframe0.view_eigen_between \
+	-text "to:"  \
+	-variable [ itcl::scope global_list(view_eigen_between) ] \
+	-command [ itcl::code $this view_eigen_fromto_cb ]
+    pack $subframe0.view_eigen_between -side left -fill x -padx 0
+    
+    iwidgets::entryfield $subframe0.view_eigen_to \
+	-width 5 \
+	-validate real \
+	-textvariable [ itcl::scope global_list(view_eigen_to) ] \
+	-command [ itcl::code $this view_eigen_fromto_cb ]
+    pack $subframe0.view_eigen_to -side left -fill x -padx 0
+    
+    set subframe1 [ frame $base.subframe1 ]
+    pack $subframe1 -side top -fill both -padx 5 
+    
+    set view_eigen_glyph [ iwidgets::optionmenu $subframe1.view_eigen_glyph \
+			       -command [ itcl::code $this view_eigen_glyph_cb ] \
+			       -labeltext "View eigenvector as:" ]
+    pack $view_eigen_glyph -side left -padx 5
+    $view_eigen_glyph insert end "Lines"
+    $view_eigen_glyph insert end "Tubes"
+    $view_eigen_glyph insert end "Arrows"
+    set widget_list(view_eigen_glyph) $view_eigen_glyph
+
+    iwidgets::entryfield $subframe1.view_eigen_maxscale \
+	-width 5 \
+	-validate real \
+	-labeltext "Glyph scale factor:" \
+	-textvariable [ itcl::scope global_list(view_eigen_maxscale) ] \
+	-command [ itcl::code $this view_eigen_maxscale_cb ]
+    pack $subframe1.view_eigen_maxscale -side left -padx 5 
+    
+    #    checkbutton $subframe1.view_eigen_flip \
+	#	-text "Flip"  \
+	#	-variable [ itcl::scope global_list(view_eigen_flip) ] \
+	#	-command [ itcl::code $this view_update_display_cb ]
+    #    pack $subframe1.view_eigen_flip -side left -fill x -padx 0
+    
+    set subframe2 [ frame $base.subframe2 -relief flat ]
+    pack $subframe2 -side left -padx 5 -pady 5 
+    
+    update idletasks
+
+    set vector_luk [ mpjguilookuptable \#auto 0 ]
+    $vector_luk Initialize $subframe2
+    pack forget [ $vector_luk GetButtonBoxWidget ]
+#    pack forget [ $vector_luk GetMenuBar ]     
+    $vector_luk SetHueRange 0.75 0.0
+    $vector_luk Update
+    $vector_luk Show
+    
+
+
+    set widget_list(view_vectorluk) $vector_luk
+        
+    set view_eigen_cmap_copy [ iwidgets::optionmenu [ $vector_luk GetMenuBar ].copy_cmap \
+				   -labeltext "from:" \
+				   -command [ itcl::code $this view_eigen_cmapcopy_cb ] ]
+    pack $view_eigen_cmap_copy  -side right -padx 2 -pady 2
+    $view_eigen_cmap_copy insert end "Tensors"
+    $view_eigen_cmap_copy insert end "Results"
+    
+    set widget_list(view_eigen_cmapcopy) $view_eigen_cmap_copy
+
+    set view_eigen_cmap_copybtn [ button [ $vector_luk GetMenuBar ].copybtn -text "Copy" \
+				      -command [ itcl::code $this view_eigen_cmapcopybtn_cb ] ]
+    pack $view_eigen_cmap_copybtn -side right -padx 0 -pady 5 
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create tensor display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateTensorDisplayControl { base } {
+
+    set FA_MAP 5
+
+    set subframe0 [ frame $base.subframe0 ]
+    pack $subframe0 -fill both -padx 5 -expand f -pady 5
+        
+    set view_tensor_filter \
+	[ iwidgets::optionmenu $subframe0.view_tensor_filter -labeltext "Filter:" ]
+    $view_tensor_filter configure -command [ itcl::code $this view_tensor_filter_cb ]
+    for { set i 0 } { $i < [ llength $global_list(result_title) ] } { incr i } {
+	$view_tensor_filter insert $i [ lindex [ lindex $global_list(result_title) $i ] 0 ]
+    }
+    pack $view_tensor_filter -side left -padx 5
+    set widget_list(view_tensor_filter) $view_tensor_filter
+
+    $view_tensor_filter select $FA_MAP
+    
+    iwidgets::entryfield $subframe0.view_tensor_from \
+	-width 5 \
+	-validate real \
+	-labeltext "From:" \
+	-textvariable [ itcl::scope global_list(view_tensor_from) ] \
+	-command [ itcl::code $this view_tensor_fromto_cb ]
+    pack $subframe0.view_tensor_from -side left -fill x -padx 5
+    
+    checkbutton $subframe0.view_tensor_between \
+	-text "to:"  \
+	-variable [ itcl::scope global_list(view_tensor_between) ] \
+	-command [ itcl::code $this view_tensor_fromto_cb ]
+    pack $subframe0.view_tensor_between -side left -fill x -padx 0
+    
+    iwidgets::entryfield $subframe0.view_tensor_to \
+	-width 5 \
+	-validate real \
+	-textvariable [ itcl::scope global_list(view_tensor_to) ] \
+	-command [ itcl::code $this view_tensor_fromto_cb ]
+    pack $subframe0.view_tensor_to -side left -fill x -padx 0
+    
+    set subframe1 [ frame $base.subframe1 ]
+    pack $subframe1 -side top -fill both -padx 5 
+
+    set view_tensor_glyph [ iwidgets::optionmenu $subframe1.view_tensor_glyph \
+				-command [ itcl::code $this view_tensor_glyph_cb ] \
+				-labeltext "View tensor as:" ]
+    pack $view_tensor_glyph -side left -padx 5
+    $view_tensor_glyph insert end "Ellipsoids"
+    $view_tensor_glyph insert end "Cuboids"
+    $view_tensor_glyph insert end "Sheets"
+    set widget_list(view_tensor_glyph) $view_tensor_glyph
+
+    iwidgets::entryfield $subframe1.view_tensor_scale \
+	-width 5 \
+	-validate real \
+	-labeltext "Scale:" \
+	-textvariable [ itcl::scope global_list(view_tensor_scale) ] \
+	-command [ itcl::code $this view_tensor_maxscale_cb ]
+    pack $subframe1.view_tensor_scale -side left -padx 5 -pady 5
+    
+    set view_tensor_clampscale [ checkbutton $subframe1.view_tensor_clampscale \
+				     -text "Clamp at:" \
+				     -variable \
+				     [ itcl::scope global_list(view_tensor_clampscale) ] \
+				     -command [ itcl::code $this view_tensor_maxscale_cb ] ]
+    pack $view_tensor_clampscale -side left -pady 5 -padx 5       
+    set widget_list(view_tensor_clampscale) $view_tensor_clampscale
+
+    iwidgets::entryfield $subframe1.view_tensor_maxscale \
+	-width 5 \
+	-validate real \
+	-textvariable [ itcl::scope global_list(view_tensor_maxscale) ] \
+	-command [ itcl::code $this view_tensor_maxscale_cb ]
+    pack $subframe1.view_tensor_maxscale -side left -padx 2 -pady 5
+    
+    set subframe2 [ frame $base.subframe2 -relief flat ]
+    pack $subframe2 -side left -padx 5 -pady 5
+
+    set tensor_luk [ mpjguilookuptable \#auto 0 ]
+    $tensor_luk Initialize $subframe2
+    pack forget [ $tensor_luk GetButtonBoxWidget ]
+#    pack forget [ $tensor_luk GetMenuBar ] 
+    $tensor_luk SetHueRange 0.5 0.0
+    $tensor_luk Update
+    $tensor_luk Show
+    
+    set widget_list(view_tensorluk) $tensor_luk
+    
+    set view_tensor_cmap_copy [ iwidgets::optionmenu [ $tensor_luk GetMenuBar ].copy_cmap \
+				    -labeltext "from:" \
+				    -command [ itcl::code $this view_tensor_cmapcopy_cb ] ]
+    pack $view_tensor_cmap_copy  -side right -padx 2 -pady 5
+    $view_tensor_cmap_copy insert end "Eigenvectors"
+    $view_tensor_cmap_copy insert end "Results"
+    
+    set widget_list(view_tensor_cmapcopy) $view_tensor_cmap_copy
+    
+    set view_tensor_cmap_copybtn [ button [ $tensor_luk GetMenuBar ].copybtn -text "Copy" \
+				       -command [ itcl::code $this view_tensor_cmapcopybtn_cb ] ]
+    pack $view_tensor_cmap_copybtn -side right -padx 0 -pady 5 
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create result display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateResultDisplayControl { base } {
+    
+    set subframe1 [ frame $base.subframe1 ]
+    pack $subframe1 -side bottom -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe1.view_colorbar_label \
+	-width 15 \
+	-labeltext "Colormap label:" \
+	-textvariable [ itcl::scope global_list(view_colorbar_label) ]
+    pack $subframe1.view_colorbar_label -side top -padx 5    
+
+    set resultluk [ mpjguilookuptable \#auto 0 ]
+    $resultluk Initialize $subframe1
+    pack forget [ $resultluk GetButtonBoxWidget ]
+#    pack forget [ $resultluk GetMenuBar ]
+    $resultluk SetHueRange 0.0 0.2
+    $resultluk SetSaturationRange 1.0 0.5
+    $resultluk SetValueRange 0.5 1.0
+    $resultluk Update
+    $resultluk Show
+
+    set widget_list(view_resultluk) $resultluk    
+    
+    set resultdisplaybtn [ button [ $resultluk GetMenuBar ].resultdisplaybtn \
+			       -text "Apply!" \
+			       -command [ itcl::code $this view_results_colormap_cb ]  ]
+    pack $resultdisplaybtn -side left -padx 5 -pady 5
+    
+
+    set subframe0 [ frame [ $resultluk GetMenuBar ].subframe0 ]
+    pack $subframe0 -fill x -side bottom -expand f -padx 5 -pady 5
+
+    set transparent [ checkbutton $subframe0.transparent \
+			  -variable [ itcl::scope global_list(view_transparent) ] ]    
+    pack $transparent -side left -pady 5       
+    set widget_list(view_transparent) $transparent
+
+    iwidgets::entryfield $subframe0.view_transpcolor \
+	-width 5 \
+	-validate real \
+	-labeltext "Transparent color:" \
+	-textvariable [ itcl::scope global_list(view_transpcolor) ]
+    pack $subframe0.view_transpcolor -side left -pady 5
+    
+     
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create directionality encoding display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateDirectionDisplayControl { base } {
+    
+    set FA_MAP 5
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Directionally encoded colormaps"
+    pack $base.frame0 -fill both -pady 5 -expand f
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill x -expand f -padx 5 -pady 5
+  
+    set view_direction_filter \
+	[ iwidgets::optionmenu $subframe0.view_direction_filter \
+	      -labeltext "Modulate intensity by:" ]
+    for { set i 0 } { $i < [ llength $global_list(result_title) ] } { incr i } {
+	$view_direction_filter insert $i [ lindex [ lindex $global_list(result_title) $i ] 0 ]
+    }
+    pack $view_direction_filter -side left -padx 5
+    set widget_list(view_direction_filter) $view_direction_filter
+
+    $view_direction_filter select $FA_MAP
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -fill x -expand f -padx 5 -pady 5
+  
+    set view_direction_scheme \
+	[ iwidgets::optionmenu $subframe2.view_direction_scheme -labeltext "Color scheme:" ]
+    set widget_list(view_direction_scheme) $view_direction_scheme
+
+    $view_direction_scheme insert 0 "Absolute value"
+    $view_direction_scheme insert 1 "Rotational symmetry"
+    $view_direction_scheme insert 2 "No symmetry"
+    $view_direction_scheme insert 3 "Mirror symmetry"
+
+    pack $view_direction_scheme -side left -padx 5
+    
+    $view_direction_scheme select 0    
+
+    set subframe3 [ frame $frame0.subframe3 ]
+    pack $subframe3 -fill x -expand f -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe3.view_direction_numcolors \
+	-width 4 \
+	-validate integer \
+	-labeltext "Number of colors for quantization:" \
+	-textvariable [ itcl::scope global_list(view_direction_numcolors) ]
+    pack $subframe3.view_direction_numcolors -side left -padx 5 -pady 5
+
+    set subframe4 [ frame $frame0.subframe4 ]
+    pack $subframe4 -fill x -expand f -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe4.view_direction_satscale \
+	-width 5 \
+	-validate real \
+	-labeltext "Saturation factor:" \
+	-textvariable [ itcl::scope global_list(view_direction_satscale) ]
+    pack $subframe4.view_direction_satscale -side left -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe4.view_direction_scaling \
+	-width 5 \
+	-validate real \
+	-labeltext "Brightness:" \
+	-textvariable [ itcl::scope global_list(view_direction_scaling) ]
+    pack $subframe4.view_direction_scaling -side left -padx 5 -pady 5
+
+    set view_direction_mask [ checkbutton $subframe4.view_direction_mask \
+				  -text "Use anatomical mask" \
+				  -variable [ itcl::scope global_list(view_direction_mask) ] ]
+    pack $view_direction_mask -side right -pady 5 -padx 5       
+    set widget_list(view_direction_mask) $view_direction_mask
+
+    set subframe1 [ frame $base.subframe1 ]
+    pack $subframe1 -fill both -expand f -padx 5   
+
+    iwidgets::buttonbox $subframe1.decdisplaybbox -orient vertical 
+    $subframe1.decdisplaybbox add display -text "Apply!" -command \
+	[ itcl::code $this view_direction_update_cb ]
+    pack $subframe1.decdisplaybbox -side left -fill x -expand f
+   
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::UpdateLookupControlsOnMap { } {
+
+    set mlist [ list  [ $widget_list(view_resultluk) GetRenderWidget ]  [ $widget_list(view_vectorluk) GetRenderWidget ]  [ $widget_list(view_tensorluk) GetRenderWidget ] ]
+
+    foreach widg $mlist {
+	[ $widg GetRenderWindow ] Render
+	update idletasks
+    }
+}
+
+itcl::body mpjtensoranalysis::CreateDisplayControl { base } {
+        
+#    frame $base.dummy -relief sunken -borderwidth 1 -height 2
+#    pack $base.dummy -side top -fill x -expand f -padx 12 -pady 0
+
+    set frame0 [ frame $base.frame0 ]
+    pack $base.frame0 -pady 0 -fill both -expand t 
+    
+    set display_notebook [ iwidgets::tabnotebook $frame0.display_notebook -tabpos n ]     
+    set widget_list(display_notebook) $display_notebook
+    pack $display_notebook -fill both -expand t -pady 5 -padx 5
+    
+    CreateEigenDisplayControl [ $display_notebook add -label "Eigenvectors" ]
+    CreateTensorDisplayControl [ $display_notebook add -label "Tensors" ]
+    CreateDirectionDisplayControl [ $display_notebook add -label "Directionality" ]
+    CreateResultDisplayControl [ $display_notebook add -label "Results" ]
+
+    eval "bind $base <Map> { $this UpdateLookupControlsOnMap }"
+
+    $display_notebook view "Eigenvectors"   
+}
+
+# ------------------------------------------------------------------------------------------
+#  Create Transform Menu
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateDisplayTransformMenu { menubase } {
+
+    menubutton $menubase.transform -text "Transform" -menu $menubase.transform.m -underline 0
+    pack $menubase.transform -side left
+
+    menu $menubase.transform.m -tearoff 0
+
+    $menubase.transform.m add check -label "Flip X" -underline 0 \
+	-variable [ itcl::scope global_list(tensor_flipx) ] \
+	-command [ itcl::code $this view_update_display_cb ]
+    $menubase.transform.m add check -label "Flip Y" -underline 0 \
+	-variable [ itcl::scope global_list(tensor_flipy) ] \
+	-command [ itcl::code $this view_update_display_cb ]
+    $menubase.transform.m add check -label "Flip Z" -underline 0 \
+	-variable [ itcl::scope global_list(tensor_flipz) ] \
+	-command [ itcl::code $this view_update_display_cb ]
+
+}
+
+# ------------------------------------------------------------------------------------------
+#  Create Colorbar Menu
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateDisplayColorbarMenu { menubase } {  
+
+    menubutton $menubase.colorbar -text "Colorbar" -menu $menubase.colorbar.m -underline 0
+    pack $menubase.colorbar -side left
+
+    menu $menubase.colorbar.m -tearoff 0
+
+    $menubase.colorbar.m add radio -label "Eigenvectors" -underline 0 \
+	-variable [ itcl::scope global_list(view_colorbar) ] \
+	-command [ itcl::code $this view_colorbar_cb ]
+    $menubase.colorbar.m add radio -label "Tensor" -underline 0 \
+	-variable [ itcl::scope global_list(view_colorbar) ] \
+	-command [ itcl::code $this view_colorbar_cb ]
+    $menubase.colorbar.m add radio -label "Results" -underline 0 \
+	-variable [ itcl::scope global_list(view_colorbar) ] \
+	-command [ itcl::code $this view_colorbar_cb ]
+}
+
+# ------------------------------------------------------------------------------------------
+#  Create Visualization Menu
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateDisplayModeMenu { menubase } {  
+    
+    menubutton $menubase.mode -text "Location" -menu $menubase.mode.m -underline 0
+    pack $menubase.mode -side left 
+
+    menu $menubase.mode.m -tearoff 0
+
+    $menubase.mode.m add radio -label "XZ-plane" -underline 0 \
+	-variable [ itcl::scope global_list(view_mode) ] \
+	-command [ itcl::code $this view_mode_cb ]
+    $menubase.mode.m add radio -label "YZ-plane" -underline 0 \
+	-variable [ itcl::scope global_list(view_mode) ] \
+	-command [ itcl::code $this view_mode_cb ]
+    $menubase.mode.m add radio -label "XY-plane" -underline 0 \
+	-variable [ itcl::scope global_list(view_mode) ] \
+	-command [ itcl::code $this view_mode_cb ]
+    $menubase.mode.m add radio -label "3-slice" -underline 0 \
+	-variable [ itcl::scope global_list(view_mode) ] \
+	-command [ itcl::code $this view_mode_cb ]    
+    $menubase.mode.m add separator
+    $menubase.mode.m add radio -label "Volume" -underline 0 \
+	-variable [ itcl::scope global_list(view_mode) ] \
+	-command [ itcl::code $this view_mode_cb ]
+    $menubase.mode.m add separator
+    $menubase.mode.m add radio -label "None" -underline 0 \
+	-variable [ itcl::scope global_list(view_mode) ] \
+	-command [ itcl::code $this view_mode_cb ]
+
+}
+
+# ------------------------------------------------------------------------------------------
+#  Create Visualization Menu
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateDisplayTypeMenu { menubase } {  
+    
+    menubutton $menubase.type -text "Display" -menu $menubase.type.m -underline 0
+    pack $menubase.type -side left
+
+    menu $menubase.type.m -tearoff 0
+
+    $menubase.type.m add check -label "Fast eigenvector" -underline 0 \
+	-variable [ itcl::scope global_list(view_type_fast) ] \
+	-command [ itcl::code $this view_type_toggle_fast_eigenvector ]
+    $menubase.type.m add check -label "Medium eigenvector" -underline 0 \
+	-variable [ itcl::scope global_list(view_type_medium) ] \
+	-command [ itcl::code $this view_type_toggle_med_eigenvector ]
+    $menubase.type.m add check -label "Slow eigenvector" -underline 0 \
+	-variable [ itcl::scope global_list(view_type_slow) ] \
+	-command [ itcl::code $this view_type_toggle_slow_eigenvector ]
+    $menubase.type.m add check -label "Tensor" -underline 0 \
+	-variable [ itcl::scope global_list(view_type_tensor) ] \
+	-command [ itcl::code $this view_type_toggle_tensor ]    
+    $menubase.type.m add separator
+    $menubase.type.m add check -label "Colorbar" -underline 0 \
+	-variable [ itcl::scope global_list(view_type_colorbar) ] \
+	-command [ itcl::code $this view_type_toggle_colorbar ]
+}
+
+# ------------------------------------------------------------------------------------------
+#  Create Update Menu
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateDisplayUpdateMenu { menubase } {
+
+    menubutton $menubase.update -text "Update" -menu $menubase.update.m -underline 0
+    pack $menubase.update -side left
+
+    menu $menubase.update.m -tearoff 0
+
+    $menubase.update.m add command -label "Now" -underline 0 \
+	-command [ itcl::code $this view_update_display_cb ] 
+    $menubase.update.m add separator
+    $menubase.update.m add check -label "Auto update" -underline 0 \
+	-variable [ itcl::scope global_list(view_autoupdate) ] \
+	-command [ itcl::code $this view_toggle_autoupdate ]
+
+}
+
+# -------------------------------------------------------------------------------------------
+#  Diffusion control inititialization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::Initialize { widget } {
+    
+    if { $initialized == 1 } { return $basewidget }
+    
+    #  -------------------------------------
+    #  Create User Interface
+    #  -------------------------------------	
+    set basewidget [toplevel $widget ]
+    wm geometry $basewidget 600x480
+    wm withdraw $basewidget
+
+    set notebook $basewidget.notebook    
+    iwidgets::tabnotebook $notebook -tabpos w         
+    set widget_list(notebook) $notebook
+
+    set mb [ frame $basewidget.mb ]
+    pack $mb -side top -fill x -expand false
+    
+    CreateMenu $mb
+    CreateDisplayTypeMenu $mb
+    CreateDisplayModeMenu $mb
+#    CreateDisplayTransformMenu $mb
+    CreateDisplayColorbarMenu $mb
+    CreateDisplayUpdateMenu $mb
+    
+    #button $mb.refresh -text "Refresh" -borderwidth 0 \
+    #	-command [ itcl::code $this view_update_display_cb ] -underline 2
+    #pack $mb.refresh -side left -padx 0
+
+    CreateTensorControl     [ $notebook add -label "Tensor" ]
+    CreateTransformControl  [ $notebook add -label "Transform" ]
+    CreateResultsControl    [ $notebook add -label "Results" ] 
+    CreateStatisticsControl [ $notebook add -label "Statistics" ]
+    CreateDisplayControl [ $notebook add -label "Display" ]
+
+    
+    pack $notebook -side top -fill both -expand t -padx 5
+    $notebook view "Tensor"
+
+    set bottom [ frame $basewidget.bottom -relief ridge]
+    pack $bottom -side top -fill x -expand false
+    
+    set pbar [ frame $basewidget.pbar -width 400 -height 20 ]
+    pack $pbar -side bottom -expand f -fill x
+    CreateProgressBar $pbar
+    
+    set w [ frame $basewidget.w -relief ridge -width 800 ]
+    pack $w -side bottom -fill x -expand false
+    
+    eval "button $w.close -text Close -command { $this DismissWindow }"
+
+    pack $w.close -side right -fill x -padx 5 -pady 10
+    
+    set initialized 1
+    
+    SetTitle $appname
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { $this DismissWindow }"
+
+    return $basewidget 
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create top level menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::CreateMenu { mb } {    
+    
+    menubutton $mb.results       -text Results     -menu $mb.results.m -underline 0
+    pack $mb.results    -side left
+    menubutton $mb.help      -text Help         -menu $mb.help.m -underline 0 -padx 4
+    pack $mb.help  -side right
+
+    menu $mb.results.m -tearoff 0 
+    eval "$mb.results.m add command -label \"Compute All\" -command { $this ComputeResults } -underline 0 -state disabled"
+    $mb.results.m add command -label "Save All Results" -command [ itcl::code $this saveallresults ] -underline 0
+    $mb.results.m add separator
+    if { $parent == 0 } {
+	eval "$mb.results.m add command -label Exit -command {  pxtkexit } -underline 1"
+    } else {
+	eval "$mb.results.m add command -label Close -command {  $this HideWindow } -underline 1"
+    }
+
+    menu $mb.help.m -tearoff 0
+
+    set widget_list(menu_results) $mb.results.m    
+
+    eval "$mb.help.m add command -label About -command { $this AboutCommand }"
+   
+}
+
+#-------------------------------------------------------------------------------------------
+#  Add controls to menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::AddToMenuButton { mb args } {
+    eval "$mb add command -label \"Tensor analysis\" -command {$this ShowWindow \"Tensor\"}"
+}
+#-------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::SetParametersFromBisAlgorithmAndCompute { cscheme satfactor brightness usemask } {
+
+    $this SetBisAlgorithmMode
+    set lst [ list AbsoluteValue RotSymmetry NoSymmetry MirrorSymmetry ]
+    set cf [ lsearch -exact $lst $cscheme ]
+    if { $cf > -1 } {
+	$widget_list(view_direction_scheme) select $cf
+    }
+    set global_list(view_direction_satscale) $satfactor
+    set global_list(view_direction_scaling)  $brightness
+    set global_list(view_direction_mask) $usemask
+    set global_list(view_mode_index) 5
+    $this ComputeResults
+    set bis_algorithmmode 0
+}
+
+#-------------------------------------------------------------------------------------------
+itcl::body mpjtensoranalysis::GetOutputImage { index } {
+    return [ [ lindex $global_list(result_list) $index ] GetThisPointer]
+}
+
+#-------------------------------------------------------------------------------------------
+#  Main function for stand-alone execution
+# ------------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    puts "\n[ file rootname $argv0 ] is not a stand-alone program.\n"
+    exit
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjtensorutility.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjtensorutility.tcl
new file mode 100644
index 0000000..e3a5b73
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjtensorutility.tcl
@@ -0,0 +1,2407 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package provide mpjtensorutility 1.3
+
+package require  Itcl 3.2
+package require  Iwidgets 4.0
+
+package require  pxitcllistselector 1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitclbaseimageviewer 1.0
+
+package require  vtkmpjcontrib 1.1
+package require  mpjguilookuptable 1.0
+package require  mpjguisphere 1.0
+package require  vtkinteraction
+
+itcl::class mpjtensorutility {
+
+    inherit pxitclbaseimagecontrol
+    
+    #-----------------------------------
+    # construction and descruction
+    #-----------------------------------
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } { InitializeControl }
+    
+    destructor { }
+
+    # Generic Stuff 
+    protected variable setupfilename "subject.dti"
+
+    #-----------------------------------
+    # common variables
+    #-----------------------------------
+
+    #-----------------------------------
+    # global variables
+    #-----------------------------------
+    private variable widget_list
+    private variable global_list
+    protected variable bis_algorithmmode 0
+    
+    #-----------------------------------
+    # initialization methods
+    #-----------------------------------
+    public method Initialize { inpwidg }
+    public method InitializeControl { }
+    public method DismissWindow { }
+      
+    # ----------------------------
+    # Setup Stuff
+    # ----------------------------
+    public method LoadSetup { args } 
+    public method SaveSetup { args } 
+    protected method GetFileElement { fileid } 
+
+    #-----------------------------------
+    # diffusion series input/output
+    #-----------------------------------
+    public method AddInput { fname { guimode 1 } }
+    public method RemoveInput { index }
+    public method RemoveAllInputs { }
+    public method DisplayInput { index frame }
+    public method LoadGradient { fname }
+    public method LoadMask { fname }
+    public method ComputeResults { }
+    public method SaveAllResults { }
+    public method SaveResult { index }
+    public method ClearAllResults { }
+    public method DisplayResult { index }
+    public method ClearDisplay { }
+    public method SetResultPreffix { preffix }
+    public method GetResultPreffix { } 
+    public method SetCurrentDirectory { fname } 
+    
+
+    # Methods for bis_algorithm
+    # -------------------------
+    public method SetParametersFromBisAlgorithm { ndw bval dname dfname flipx flipy flipz }
+    public method GetOutputImage { index }
+
+    #-----------------------------------
+    # interface creation methods
+    #-----------------------------------
+    private method CreateInputControl { base }
+    private method CreateMaskControl { base }
+    private method CreateResultsControl { base }
+    private method CreateGradientControl { base }
+    private method CreateTransformControl { base }
+    private method CreateDistributionControl { base }
+    private method CreateMenu { mb }
+    public method AddToMenuButton { mb args}    
+ 
+    private method addinput { }
+    private method removeinput { }
+    private method displayinput { }
+    private method loadgradient { }
+    private method checkgradient { }
+    private method loadmask { }
+    private method displayresult { }
+    private method saveresult { }
+    private method saveallresults { }
+ 
+    private method input_updateinfo { index }    
+    private method input_selectioncommand_cb { } 
+    private method gradient_searchlist { dir }
+    private method gradient_populatelist { index }
+    private method gradient_increment_ndir { dir }
+    private method gradient_showantipodal { }
+    
+    private method mask_autochanged_cb { }
+    private method mask_autothreshchanged_cb { }
+
+    private method result_clear { }
+    private method result_createbaseline { }
+    private method result_createmask { } 
+    private method result_createtensor { }
+    private method result_createadc { }
+    private method result_createeigen { }
+
+}  
+
+#-------------------------------------------------------------------------------------------
+#  Close window 
+# -------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::DismissWindow { } {
+
+    if { $bis_algorithmmode > 0 } {
+	$this HideWindow
+	return
+    }
+
+    set ok "yes"
+    
+    if { [ llength $global_list(input_list) ] > 0 } {
+	
+	set ok [ tk_messageBox -type yesnocancel -default no \
+		     -parent $basewidget -title "Think again ..." \
+		     -message "Unload all images from memory?" -icon question  ]
+
+    }
+    
+    if { $ok == "yes" } {	
+	
+	$this ClearAllResults
+	$this RemoveAllInputs
+
+	#$global_list(gradient_points) Delete
+	#$global_list(gradient_polydata) Delete
+	#$global_list(gradient_actor) Delete
+	#$global_list(gradient_anti_actor) Delete
+	    
+	$this SetTitle $global_list(appname)
+		
+	set global_list(mask_fname) "select"
+	set global_list(tensor_fname) ""
+    }
+
+    if { $ok != "cancel" } {
+	$this HideWindow
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  Initialize tool
+# -------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::InitializeControl { } {
+
+    set global_list(appname) "Diffusion Tensor Utility"
+    
+    set appname "$global_list(appname) $version"
+    set aboutstring "(c) Marcel Jackowski 2008"
+        
+    set dir6 "{0.707 0.0 0.707} {-0.707 0.0 0.707} {0.0 0.707 0.707} {0.0 0.707 -0.707} {0.707 0.707 0.0} {-0.707 0.707 0.0}"
+
+    set dir6i "{0.000000  0.525731 -0.850651} {0.000000 -0.525731 -0.850651} \
+               {0.525731 -0.850651 0.000000} {0.525731  0.850651 0.000000} \
+               {-0.850651 0.000000 0.525731} {-0.850651 0.000000 -0.525731}"
+
+    set dir10i "{-0.577300 0.577300 0.577300} {-0.577300 0.577300 -0.577300} \
+                {0.577300 0.577300 0.577300} {0.577300 0.577300 -0.577300} \
+                {0.000000 -0.934200 0.356800} {0.000000 0.934200 0.356800} \
+                {-0.356800 0.000000 0.934200} {0.356800 0.000000 0.934200} \
+                {-0.934200 0.356800 0.000000} {0.934200 0.356800 0.000000}"
+
+    set dir15i "{1.000000 0.000000 0.000000} {0.000000 1.000000 0.000000} \
+                {0.000000 0.000000 1.000000} {0.309017 -0.809017 -0.500000} \
+                {0.309017 0.809017 -0.500000} {-0.309017 -0.809017 -0.500000} \
+                {0.309017 -0.809017 0.500000} {-0.500000 0.309017 0.809017} \
+                {0.500000 -0.309017 0.809017} {0.500000 0.309017 -0.809017} \
+                {0.500000 0.309017 0.809017} {-0.809017 0.500000 0.309017} \
+                {0.809017 -0.500000 0.309017} {0.809017 0.500000 -0.309017} \
+                {-0.809017 -0.500000 -0.309017}"
+
+    set dir21i "{1.000000 0.000000 0.000000} {0.000000 1.000000 0.000000} \
+                {0.000000 0.000000 1.000000} {0.000000 0.525731 -0.850651} \
+                {0.000000 -0.525731 -0.850651} {0.525731 -0.850651 0.000000} \
+                {0.525731 0.850651 0.000000} {-0.850651 0.000000 0.525731} \
+                {-0.850651 0.000000 -0.525731} {0.309017 -0.809017 -0.500000} \
+                {0.309017 0.809017 -0.500000} {-0.309017 -0.809017 -0.500000} \
+                {0.309017 -0.809017 0.500000} {-0.500000 0.309017 0.809017} \
+                {0.500000 -0.309017 0.809017} {0.500000 0.309017 -0.809017} \
+                {0.500000 0.309017 0.809017} {-0.809017 0.500000 0.309017} \
+                {0.809017 -0.500000 0.309017} {0.809017 0.500000 -0.309017} \
+                {-0.809017 -0.500000 -0.309017}"
+
+    set dir24 "{0.134985506170 -0.985952791173 0.098366695086} \
+               {0.650088694587 -0.462793906466 -0.602666150790} \
+               {-0.206347275695 0.662332382064 0.720233724205} \
+               {-0.435854930194 0.350113596741 -0.829126618318} \
+               {0.985232180539 0.063955280317 -0.158830955895} \ 
+               {-0.614137826481 -0.392074584561 -0.684917695951} \
+               {0.353418655052 -0.587198098366 0.728212638957} \ 
+               {-0.944785803171 0.119466198906 -0.305135401821} \ 
+               {0.021302190861 -0.808690754556 -0.587848177815} \
+               {0.090322707483 0.786736539321 -0.610645090220} \
+               {0.019144141922 0.992112273707 0.123881952644} \
+               {0.685499579269 0.715694962504 -0.133682637122} \
+               {-0.492664112126 -0.044270667252 0.869092734203} \
+               {-0.582890874715 -0.806420953907 -0.099616631511} \
+               {0.048922860209 -0.155267715919 -0.986660270885} \
+               {0.542444409187 0.622999428166 0.563582980089} \
+               {0.763772109691 -0.640056077552 0.083548680702} \
+               {-0.913538674752 -0.294880095995 0.280165698682} \
+               {-0.347061443006 -0.702169846181 0.621695956149} \
+               {0.842177009528 -0.028740243511 0.538434659941} \
+               {0.207815962624 0.070701024559 0.975609497086} \
+               {-0.578727030552 0.786414267629 -0.215934304310} \
+               {-0.804218513225 0.456634532848 0.380417515892} \
+               {0.575100475666 0.281355246534 -0.768178799588}"
+
+    set dir32 "{0.127839994324 0.905079981288 -0.405570170652} {0.160624455635 0.551408286854 0.818626096237} {-0.660076326339 -0.746272212908 0.085889624794} {0.429182719745 -0.024323513182 0.902890115008} {0.017138782122 0.483370449508 -0.875248119501} {-0.017138782496 -0.483370449559 0.875248119465} {0.879670240941 -0.126024235489 0.458582772542} {0.372449269958 -0.928034884037 0.005726719673} {-0.615867796457 -0.445295752660 0.649937343096} {-0.420650772436 0.691083196582 0.587755853 [...]
+
+    set dirvarian "{ 0.000000 0.000000 -1.000000} {-0.436300 0.076600 -0.896600} {-0.232800 -0.506600 -0.830100} {0.396700 -0.509200 -0.763700} {0.715600 0.040100 -0.697300} {0.459600 0.625000 -0.630900} {-0.153300 0.811100 -0.564500} {-0.712100 0.494800 -0.498100} {-0.893700 -0.122000 -0.431700} {-0.612400 -0.701100 -0.365300} {-0.019700 -0.954100 -0.298900} {0.597500 -0.767400 -0.232400} {0.958300 -0.232600 -0.166000} {0.906300 0.410700 -0.099600} {0.467100 0.883600 -0.033200 } "
+
+
+    # create initial set of gradient directions
+    set global_list(gradient_list) "{6 ME6 {$dir6}} {6 ICO6 {$dir6i}} \
+                                    {10 ICO10 {$dir10i}} \
+                                    {15 ICO15 {$dir15i}} {21 ICO21 {$dir21i}} \
+                                    {24 ME24 {$dir24}} {32 ME32 {$dir32}} { 15 VAR15 {$dirvarian}}"
+    
+    # create image titles
+    set global_list(result_title) \
+	[ list \
+	      { "Baseline image"                    "dti_baseline" } \
+	      { "Anatomical mask"                   "dti_mask" }  \
+	      { "Diffusion tensor"                  "dti_tensor" } \
+	      { "Mean diffusion-weighted"           "dti_mean" } \
+	      { "Apparent diffusion"                "dti_adc" } ]
+
+    foreach item $global_list(result_title) {
+ 	lappend result_list [ pxitclimage \#auto ]
+    }  
+    
+    set global_list(result_fpreffix) "preffix_"
+    set global_list(result_fsuffix) ".nii.gz"
+    set global_list(result_fdir) [ pwd ]
+    set global_list(result_fmask) "*.hdr"
+    set global_list(result_list) $result_list
+    
+    set global_list(input_fname) {}   ; # list of filenames
+    set global_list(input_list) {}    ; # list of input images
+    set global_list(input_ndw) 1
+    set global_list(input_dw) 6
+    set global_list(input_frameno) 0
+    set global_list(input_tensorsymm) 1
+    set global_list(input_bfactor) 1000.0
+    set global_list(input_bfactorenable) 0
+    
+    set global_list(tensor_ordering) 0
+    set global_list(tensor_flipx) 0
+    set global_list(tensor_flipy) 0
+    set global_list(tensor_flipz) 0
+    set global_list(tensor_swap) 0
+    set global_list(tensor_swapdir) 0
+    set global_list(tensor_swapyz) 0
+    set global_list(tensor_swapxz) 0
+    set global_list(tensor_swapxy) 0
+
+    set global_list(tensor_rotation) 0
+    set global_list(tensor_rotx) 0.0
+    set global_list(tensor_roty) 0.0
+    set global_list(tensor_rotz) 0.0
+    
+    set global_list(gradient_fname) "select"
+    set global_list(gradient_fdir) [ pwd ]
+    set global_list(gradient_tol) 1E-6
+    set global_list(gradient_showanti) 1
+    
+    set global_list(adc_compute) 1
+
+    set global_list(mask_auto) 1
+    set global_list(mask_fname) "select"
+    set global_list(mask_autothresh) 1
+    set global_list(mask_threshval) 0
+    set global_list(mask_connected) 1
+
+    set global_list(gradient_points) [ vtkPoints [ pxvtable::vnewobj ] ]
+    set global_list(gradient_polydata) [ vtkmpjVertexSource [ pxvtable::vnewobj ] ]
+    set global_list(gradient_actor) [ vtkActor [ pxvtable::vnewobj ] ]
+    set global_list(gradient_anti_actor) [ vtkActor [ pxvtable::vnewobj ] ]
+
+    [ $global_list(gradient_anti_actor) GetProperty ] SetRepresentationToPoints
+    [ $global_list(gradient_anti_actor) GetProperty ] SetColor 0.0 0.0 1.0
+    [ $global_list(gradient_anti_actor) GetProperty ] SetPointSize 3.0
+    
+    [ $global_list(gradient_actor) GetProperty ] SetRepresentationToPoints
+    [ $global_list(gradient_actor) GetProperty ] SetColor 1.0 0.0 0.0
+    [ $global_list(gradient_actor) GetProperty ] SetPointSize 3.0
+    
+}
+
+# ---------------------------------------------------------------------------
+itcl::body mpjtensorutility::SaveSetup { args } {
+
+    set len [ llength $args ]
+    
+    if { $len < 1 } {
+	set fname $setupfilename 
+    } else {
+	set fname [ lindex $args 0 ]
+    }
+
+    if { [ string length $fname  ] == 0  } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	set fname  [tk_getSaveFile -title "Saving Setup File" -filetypes { {"DTI-Setup File" {.dti}}} -initialfile $f1tail -initialdir $global_list(result_fdir) ]
+    }
+
+    if { [ string length $fname ] > 0 } {
+	
+	set fileid [open $fname w]
+	
+	puts $fileid "#DTI Subject Description File Version 1.3"
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Images"
+	puts $fileid "#---------------------------------------------"
+
+	puts $fileid "Total : [ llength $global_list(input_fname) ]"
+	foreach item $global_list(input_fname) {	    
+	    puts $fileid "Image : $item "
+	}
+
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Gradient directions"
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "Filename : $global_list(gradient_fname)"
+		
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Parameters"
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "Number of T2 images : $global_list(input_ndw)"
+	puts $fileid "Number of DW images : $global_list(input_dw)"
+	puts $fileid "Index : [ $widget_list(gradient_ndir) cget -clientdata ]"
+	
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Mask image"
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "Filename : $global_list(mask_fname)"
+
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "# Transformation"
+	puts $fileid "#---------------------------------------------"
+	puts $fileid "Swapping : $global_list(tensor_swap)"
+	puts $fileid "Swap axes : $global_list(tensor_swapdir)"
+	#	puts $fileid "Swap X-Y : [expr $global_list(tensor_swapdir) == 1]"
+	#	puts $fileid "Swap X-Z : [expr $global_list(tensor_swapdir) == 2]"
+	#	puts $fileid "Swap Y-Z : [expr $global_list(tensor_swapdir) == 3]"
+	puts $fileid "Flip X : $global_list(tensor_flipx)"
+	puts $fileid "Flip Y : $global_list(tensor_flipy)"
+	puts $fileid "Flip Z : $global_list(tensor_flipz)"
+	puts $fileid "Rotation : $global_list(tensor_rotation)"
+	puts $fileid "RotX : $global_list(tensor_rotx)"
+	puts $fileid "RotY : $global_list(tensor_roty)"
+	puts $fileid "RotZ : $global_list(tensor_rotz)"
+
+	close $fileid
+
+	set setupfilename $fname
+
+	SetTitle "Diffusion Tensor Utility $setupfilename"
+
+    }
+}
+
+# ---------------------------------------------------------------------------
+itcl::body mpjtensorutility::GetFileElement { fileid } {
+
+   gets $fileid line 
+   set index [string first ":" $line]
+   if { $index > 0 }  {
+       set len   [string length $line]
+       set value [string trim [string range $line [expr $index +1] [expr $len -1]]]
+       return $value
+   }
+   return ""
+}
+
+# ---------------------------------------------------------------------------
+itcl::body mpjtensorutility::LoadSetup { args } { 
+
+    set len [ llength $args ]
+    
+    if { $len < 1 } {
+	set fname $setupfilename 
+    } else {
+	set fname [ lindex $args 0 ]
+    }
+
+    if { [ string length $fname  ] == 0 } {
+	set f1 $setupfilename
+	set f1path [ file dirname $f1 ]
+	set f1tail [ file tail    $f1 ]
+	
+	set fname  [tk_getOpenFile -title "Setup File" -filetypes { {"DTI-Setup File" {.dti}}} -initialfile $f1tail -initialdir $global_list(result_fdir) -parent $basewidget ]
+    }
+
+    if { [ string length $fname ] < 1 } {
+	return
+    }
+
+    if { [ file readable $fname ] == 0 } {
+	::pxtclutil::Warning "Cannot read setupfile file from $fname\n Bad File"
+	return 0
+    }
+
+    set fileid [open $fname r]
+
+    gets $fileid line
+    if { [ string compare -length 29 $line "#DTI Subject Description File"  ] != 0 } {
+	close fileid
+	::pxtclutil::Warning "Cannot read setupfile file from $fname\n Bad File Type"
+	return 0
+    }
+
+    set version 0
+    
+    ## determine version
+    if { [ string length $line ] < 30 } {
+	set version "1.2"
+    } else {
+	set version [ string range $line 38 end ]
+    }
+
+    ## read input images
+    if { [ llength $global_list(input_fname) ] > 0 } {
+	$this RemoveAllInputs
+    }
+
+    gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+
+    set total [ GetFileElement $fileid ]
+    
+    for { set i 0 } { $i < $total } { incr i } {
+	set name [ GetFileElement $fileid ]
+	if { [ string length $name ] > 0 } {
+	    $this AddInput $name
+	}
+    }
+    
+    ## read gradients
+    gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+    
+    set name [ GetFileElement $fileid ]
+    if { $name != "select" } {
+	$this LoadGradient $name
+    }
+
+    gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+    
+    ## read number of ndws, dws, index
+    set number_ndw [ GetFileElement $fileid ]
+    set number_dw [ GetFileElement $fileid ]
+    set dir_index [ GetFileElement $fileid ]
+    
+    set global_list(input_ndw) $number_ndw
+    set global_list(input_dw) $number_dw
+    
+    ## populate list of directions
+    gradient_populatelist $dir_index
+    
+    set dirset [ lindex [ lindex $global_list(gradient_list) $dir_index ] 1 ]
+
+    ## set default number of directions
+    $widget_list(gradient_ndir) delete 0 end
+    $widget_list(gradient_ndir) insert 0 $dirset
+    $widget_list(gradient_ndir) configure -clientdata $dir_index
+    
+    ## set default number of directions
+    $widget_list(gradient_ndir1) delete 0 end
+    $widget_list(gradient_ndir1) insert 0 $dirset
+    $widget_list(gradient_ndir1) configure -clientdata $dir_index
+    
+    gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+
+    ## read mask image
+    set name [ GetFileElement $fileid ]
+    if { $name != "select" } {
+	$this LoadMask $name
+    }
+    
+    gets $fileid line ;     gets $fileid line  ;   gets $fileid line
+
+    ## read in transformations
+
+    if { $version == "1.2" } {	
+	set global_list(tensor_swapxz) [ GetFileElement $fileid ]
+	set global_list(tensor_swapyz) [ GetFileElement $fileid ]
+	if { $global_list(tensor_swapxz) == 1} {
+	    set global_list(tensor_swap) 1
+	    set global_list(tensor_swapdir) 2
+	}
+	if { $global_list(tensor_swapyz) == 1} {
+	    set global_list(tensor_swap) 1
+	    set global_list(tensor_swapdir) 3
+	}
+	set global_list(tensor_flipx) [ GetFileElement $fileid ]
+	set global_list(tensor_flipy) [ GetFileElement $fileid ]
+	set global_list(tensor_flipz) [ GetFileElement $fileid ]
+	set global_list(tensor_rotation) 0
+	set global_list(tensor_rotx) 0.0
+	set global_list(tensor_roty) 0.0
+	set global_list(tensor_rotz) 0.0
+    } else {
+	## 1.3
+	set global_list(tensor_swap) [ GetFileElement $fileid ]
+	set global_list(tensor_swapdir) [ GetFileElement $fileid ]
+	set global_list(tensor_flipx) [ GetFileElement $fileid ]
+	set global_list(tensor_flipy) [ GetFileElement $fileid ]
+	set global_list(tensor_flipz) [ GetFileElement $fileid ]
+	set global_list(tensor_rotation) [ GetFileElement $fileid ]
+	set global_list(tensor_rotx) [ GetFileElement $fileid ]
+	set global_list(tensor_roty) [ GetFileElement $fileid ]
+	set global_list(tensor_rotz) [ GetFileElement $fileid ]
+    }
+    
+    
+    close $fileid
+    set setupfilename $fname
+    
+    SetTitle "Diffusion Tensor Utility $setupfilename"
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon input selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::input_selectioncommand_cb { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(input_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(input_list) index [ lindex $sel_item 0 ] ] 
+	set sel_input [ lindex $global_list(input_list) $sel_index ]
+	
+	## get number of components
+	set nc [ expr [ [ $sel_input GetImage ] GetNumberOfScalarComponents ] -1 ]
+	$widget_list(input_frameno) configure -range [ list 0 $nc ]
+	
+	## update information
+	input_updateinfo $sel_index	
+    }
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Update input information on title bar
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::input_updateinfo { index } {
+
+    set sel_input [ [ lindex $global_list(input_list) $index ] GetImage ]
+    set sel_fname [ lindex $global_list(input_fname) $index ]
+    
+    scan [ $sel_input GetDimensions ] "%d %d %d" dx dy dz	       
+    set nc [  $sel_input GetNumberOfScalarComponents ]
+    set name [ file tail [ file root $sel_fname ] ]
+    
+    
+    if { [ file extension $name ] == ".gz" } {
+	set name [ file rootname $name ]
+    }
+    if { [ file extension $name ] == ".hdr" } {
+	set name [ file rootname $name ]
+	set global_list(result_fsuffix) ".hdr"
+    } elseif { [ file extension $name ] == ".nii" } {
+	set name [ file rootname $name ]
+	set global_list(result_fsuffix) ".nii.gz"
+    }
+    
+
+    set global_list(result_fpreffix) "${name}_"
+
+    $this SetTitle "$global_list(appname): $name (${dx}x${dy}x${dz}, $nc frames)"
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Add input
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::addinput { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Add diffusion images" -filetypes $typelist -initialdir $global_list(result_fdir) -multiple yes -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	foreach item $fname {
+	    
+	    ## load series into memory
+	    AddInput $item 
+	}
+
+	set global_list(result_fdir) [ file dirname [ lindex $fname 0 ]]
+	set global_list(result_fmask) "*[ file extension [ lindex $fname 0]]"
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Remove selected input
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::removeinput { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(input_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(input_list) index [ lindex $sel_item 0 ] ] 
+	
+	## remove series
+	RemoveInput $sel_index
+	
+    }    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Display selected input
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::displayinput { } {
+
+    ## get current selection 
+    set sel_item [ $widget_list(input_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(input_list) index [ lindex $sel_item 0 ] ] 
+	
+	## display series
+	DisplayInput $sel_index $global_list(input_frameno)
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Display specific image and frame, use frame value -1 to display all frames
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::DisplayInput { index frame } {
+
+    set input [ lindex $global_list(input_list) $index ]
+ 
+    ## display multi-frame image
+    if { $frame == -1 } {
+	
+	$parent SetImageFromObject [ $input GetThisPointer ] $this
+
+    } else {
+	
+	set ncm [ [ $input GetImage ] GetNumberOfScalarComponents ]
+
+	## display single-frame image
+	if { [expr $frame >= 0 && $frame < $ncm] } { 
+	    
+	    set fex [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+	    $fex SetInput [ $input GetImage ]
+	    $fex SetFrameNumber $frame
+	    $fex Update
+	    
+	    set new_img [ pxitclimage \#auto ]
+	    $new_img CopyImage [ $fex GetOutput ] 0
+	    
+	    $fex Delete
+	    
+	    $new_img CopyImageHeader [ $input GetImageHeader ]	    
+	    $parent SetImageFromObject [ $new_img GetThisPointer ] $this
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Add diffusion image series
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::AddInput { fname { guimode 1 } } {
+
+    ## load series into memory
+    set input [ pxitclimage \#auto ]    
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+
+    $this SetFilterCallbacks $ana "Reading input..."
+
+    WatchOn
+
+    ## load input
+    $ana Load $fname 
+    $input SetFromAnalyzeSource $ana
+
+    set nc [ [$input GetImage] GetNumberOfScalarComponents ] 
+    
+    if { $nc < 7 } {
+	
+	WatchOff
+	if { $guimode ==1 } {
+	    set ok [ tk_messageBox -type ok \
+			 -parent $basewidget -title "Adding input." \
+			 -message "This image has only $nc frames!" -icon info ]
+	    
+	    return 0
+	} 
+	return [ list 0 "Bad input image $fname, image has only $nc frames!" ]
+    }
+    
+    if { [ llength $global_list(input_list) ] > 0 } {
+	
+	scan [ [ $input GetImage ] GetDimensions ] "%d %d %d" dx dy dz
+	
+	if { $dx != [lindex $global_list(input_dim) 0] || 
+	     $dy != [lindex $global_list(input_dim) 1] ||
+	     $dz != [lindex $global_list(input_dim) 2] } {
+	
+	    WatchOff
+	    if { $guimode == 1 } {
+		set ok [ tk_messageBox -type ok \
+			     -parent $basewidget -title "Reading input." \
+			     -message "This image has different dimensions than other previously loaded images!" -icon info ]
+		return 0
+	    } else {
+		return [ list 0 "This image ($fname) has different dimensions than other previously loaded images!" ]
+		return 0
+	    }
+	}
+    } else {
+	set global_list(input_dim) [ [$input GetImage] GetDimensions ]
+    }
+
+    ## determine coordinate transform
+    set or [ $ana GetOrientation ]
+
+    if { $or == 0 } {
+	#	set global_list(tensor_swapyz) 0
+	#	set global_list(tensor_swapxz) 0
+	set global_list(tensor_swap) 0
+	set global_list(tensor_swapdir) 0
+    } elseif { $or == 1 } {
+	set global_list(tensor_swap) 1
+	set global_list(tensor_swapdir) 3
+	#	set global_list(tensor_swapyz) 1
+	#	set global_list(tensor_swapxz) 0
+    } elseif { $or == 2 } {
+	set global_list(tensor_swap) 1
+	set global_list(tensor_swapdir) 2
+	#	set global_list(tensor_swapxz) 1
+	#	set global_list(tensor_swapyz) 0
+    }
+    
+    $ana Delete
+    
+    ## guess the number of nondiffusion components
+    set global_list(input_ndw) [expr 2 - ($nc % 2) ] 
+    set global_list(input_dw) [expr $nc - $global_list(input_ndw) ]
+
+    if { $nc == 22 } {
+	set global_list(input_ndw) 1
+	set global_list(input_dw) 21
+    }
+
+    ## populate list of directions
+    set dir_index [ gradient_searchlist $global_list(input_dw) ]
+    gradient_populatelist $dir_index
+
+    set dirset [ lindex [ lindex $global_list(gradient_list) $dir_index ] 1 ]
+
+    ## set default number of directions
+    $widget_list(gradient_ndir) delete 0 end
+    $widget_list(gradient_ndir) insert 0 $dirset
+    $widget_list(gradient_ndir) configure -clientdata $dir_index
+
+    ## set default number of directions
+    $widget_list(gradient_ndir1) delete 0 end
+    $widget_list(gradient_ndir1) insert 0 $dirset
+    $widget_list(gradient_ndir1) configure -clientdata $dir_index
+        
+    WatchOff
+    
+    ## enable interface buttons
+    $widget_list(input_buttonbox) buttonconfigure remove -state normal
+    $widget_list(input_buttonbox) buttonconfigure display -state normal
+    $widget_list(input_frameno) configure -state normal
+    
+    $widget_list(menu_results) entryconfigure 0 -state normal
+    $widget_list(computebtn) configure -state normal
+    
+    lappend global_list(input_fname) $fname
+    lappend global_list(input_list) $input
+    
+    ## set new index
+    set new_index [ expr [ llength $global_list(input_list) ] -1 ]
+    
+    ## update information
+    input_updateinfo $new_index
+    
+    ## invoke selection callback
+    input_selectioncommand_cb
+    
+    ## display input if autodisplay is on
+    
+    if { $guimode == 1 } {
+	$this displayinput
+    }
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Remove all diffusion image series
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::RemoveAllInputs { } {
+    
+    set num [ llength $global_list(input_list) ]
+
+    for { set i 0 } { $i < $num } { incr i } {
+
+	RemoveInput 0
+
+    }
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Remove diffusion image series
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::RemoveInput { index } {
+    
+    ## remove series into memory
+    [ lindex $global_list(input_list) $index ] Clear    
+    itcl::delete object [ lindex $global_list(input_list) $index ]
+    
+    ## update image lists
+    set global_list(input_list) [ lreplace $global_list(input_list) $index $index ]
+    set global_list(input_fname) [ lreplace $global_list(input_fname) $index $index ]
+    
+    ## disable remove button if no elements in the list 
+    if { [ llength $global_list(input_list) ] == 0 } {	
+	
+	$widget_list(input_buttonbox) buttonconfigure "remove" -state disabled	
+	$widget_list(input_buttonbox) buttonconfigure "display" -state disabled
+	$widget_list(input_frameno) configure -state disabled
+	
+	$this SetTitle $global_list(appname)
+	
+	set global_list(result_fpreffix) "preffix"
+	
+	$widget_list(computebtn) configure -state disabled
+	
+	## clear results
+	result_clear
+
+	catch { 	[ $parent GetViewer ] UpdateDisplay }
+    }    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Show/hide antipodal points
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::gradient_showantipodal { } {        
+    $global_list(gradient_anti_actor) SetVisibility $global_list(gradient_showanti)
+    $widget_list(gradient_sphere) Update
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Search gradient list
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::gradient_searchlist { dir } {
+
+    set num [ llength $global_list(gradient_list) ]
+
+    for { set i 0 } { $i < $num } { incr i } {
+	set item [ lindex [lindex $global_list(gradient_list) $i ] 0]
+	if { $item == $dir } {
+	    return $i
+	}
+    }
+    
+    return 0
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Populate gradient list
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::gradient_populatelist { index } {
+
+    set vector_list [lindex [lindex $global_list(gradient_list) $index] 2]
+    set vector_length [ llength $vector_list ]
+
+    ## clear list 
+    $widget_list(gradient_list) clear
+    
+    set numpts [ $global_list(gradient_points) GetNumberOfPoints ]
+
+    ## reset number of points
+    if { $numpts > 0 } {
+	$global_list(gradient_points) Reset	
+    }
+    
+    $global_list(gradient_points) SetNumberOfPoints $vector_length
+    
+    set count 0
+
+    ## insert gradient vectors
+    foreach vector $vector_list {
+	scan $vector "%f %f %f" gx gy gz
+	$widget_list(gradient_list) insert end [format "% 2.5f % 2.5f % 2.5f" $gx $gy $gz]
+	$global_list(gradient_points) InsertPoint $count $gx $gy $gz 
+
+	incr count
+    }
+
+    ## update sphere
+    $global_list(gradient_polydata) SetPoints $global_list(gradient_points)
+    $global_list(gradient_polydata) SetNumberOfPoints $vector_length
+    $global_list(gradient_polydata) Modified
+    
+    ## update sphere
+    $widget_list(gradient_sphere) Update
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Check for colinearity
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::checkgradient { } {
+
+    set tol $global_list(gradient_tol)
+    set index [$widget_list(gradient_ndir) cget -clientdata]
+    set vector_list [lindex [lindex $global_list(gradient_list) $index] 2]
+    set vector_length [ llength $vector_list ]
+    
+    WatchOn
+    
+    set numcol 0
+    
+    ## check list
+    for { set i 0 } { $i < $vector_length } { incr i } {
+	set vector1 [ lindex $vector_list $i ]
+	scan $vector1 "%f %f %f" gx1 gy1 gz1
+	for { set j 0 } { $j < $vector_length } { incr j } {
+	    if { $i != $j } {
+		set vector2 [ lindex $vector_list $j ]
+		scan $vector2 "%f %f %f" gx2 gy2 gz2
+		if { [expr abs($gx1+$gx2)<$tol && abs($gy1+$gy2)<$tol && abs($gz1+$gz2)<$tol] } {
+		    puts "Pairs ($i) \[$gx1 $gy1 $gz1\] and ($j) \[$gx2 $gy2 $gz2\] are colinear!"
+		    incr numcol
+		}
+	    }
+	}
+    }
+
+    WatchOff
+
+    set numcol [ expr $numcol / 2 ]
+
+    if { $numcol > 0 } {
+	set ok [ tk_messageBox -type ok \
+		     -parent $basewidget -title "Colinearity check" \
+		     -message "This set of gradient directions\nhas $numcol colinear vectors!" \
+		     -icon info ]
+    } else {
+	set ok [ tk_messageBox -type ok \
+		     -parent $basewidget -title "Colinearity check" \
+		     -message "No colinear vectors were found." \
+		     -icon info ]
+	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Increment number of directions
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::gradient_increment_ndir { dir } {
+    
+    set max [expr [llength $global_list(gradient_list)] - 1 ]
+    set index [expr [$widget_list(gradient_ndir) cget -clientdata] + $dir ]
+
+    ## check for boundary values
+    if { $index < 0 } { set index 0 }
+    if { $index > $max } { set index $max }
+
+    ## Replace number
+    $widget_list(gradient_ndir1) delete 0 end
+    $widget_list(gradient_ndir1) insert 0 [lindex [lindex $global_list(gradient_list) $index] 1]
+    $widget_list(gradient_ndir1) configure -clientdata $index    
+    
+    ## Replace number - again
+    $widget_list(gradient_ndir) delete 0 end
+    $widget_list(gradient_ndir) insert 0 [lindex [lindex $global_list(gradient_list) $index] 1]
+    $widget_list(gradient_ndir) configure -clientdata $index    
+    
+    ## Record number of DW images the same as number of gradient directions
+    set global_list(input_dw) [lindex [lindex $global_list(gradient_list) $index] 0 ] 
+    
+    ## populate list of directions
+    gradient_populatelist $index
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load gradient list
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::loadgradient { } {
+
+    ## browse for filename
+    set fname  [tk_getOpenFile -title "Select file" -filetypes { {"Gradient directions" {.dat}} {"Text file" {*.txt}}} -initialdir $global_list(gradient_fdir) -parent $basewidget] 
+     
+    if { $fname != "" } {
+	
+	set global_list(gradient_fdir) [ file dirname $fname ]
+
+	## load gradients into memory
+	set result [ LoadGradient $fname ]
+	
+	if { $result == 0 } { 
+	    ::pxtclutil::Warning "Cannot read gradient file from $fname\n Bad File"
+	}	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load gradient list
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::LoadGradient { fname } {
+
+    ## check if file is ready for reading
+    if { [ string length $fname ] < 1 || [ file readable $fname ] == 0 } {
+	return 0
+    }
+    
+    ## open file for reading 
+    set fileid [open $fname r]
+    
+    ## clear current gradient directons
+    set global_list(gradient_list) ""
+
+    ## read in gradient vectors 
+    while { [ eof $fileid ] == 0 } {
+
+	## read line
+	gets $fileid line
+	
+	## skip any comments
+	while { [string index $line 0] == "\#"} {
+	    gets $fileid line
+	}
+
+	## attempt to read number of directions
+	set numdir $line
+	
+	if { [string is integer $numdir ] == 0 } break
+	if { $numdir < 3 } break 
+
+	## read in gradient directions
+	for {set i 0} { $i < $numdir } {incr i} {
+	    gets $fileid line
+	    # Map commas to spaces
+	    regsub -all "," $line " " line
+	    lappend grad$numdir $line
+	} 
+
+	set gradname grad$numdir
+	eval "lappend global_list(gradient_list) \"$numdir $numdir {$$gradname} \""
+    }
+
+    ## close file
+    close $fileid
+
+    ## set default number of directions
+    $widget_list(gradient_ndir) delete 0 end
+    $widget_list(gradient_ndir) insert 0 [lindex [lindex $global_list(gradient_list) 0] 1]
+    $widget_list(gradient_ndir) configure -clientdata 0
+
+    ## set default number of directions
+    $widget_list(gradient_ndir1) delete 0 end
+    $widget_list(gradient_ndir1) insert 0 [lindex [lindex $global_list(gradient_list) 0] 1]
+    $widget_list(gradient_ndir1) configure -clientdata 0
+
+    set global_list(gradient_fname) $fname
+
+    ## populate list of directions
+    gradient_populatelist 0
+
+    ## Record number of DW images the same as number of gradient directions
+    set global_list(input_dw) [lindex [lindex $global_list(gradient_list) 0] 1 ] 
+
+    ## Enabled filename entry
+    $widget_list(gradient_fname) configure -state normal
+    
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in mask auto status
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::mask_autochanged_cb { } {
+    set state(0) disabled; set state(1) normal        
+    $widget_list(mask_load) buttonconfigure load -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_fname) configure -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_connected) configure -state $state($global_list(mask_auto))
+    $widget_list(mask_autothresh) configure -state $state($global_list(mask_auto))
+    $widget_list(mask_threshval) configure -state \
+	$state([expr $global_list(mask_auto) && $global_list(mask_autothresh)==0])
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in mask threshold auto status
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::mask_autothreshchanged_cb { } {
+    set state(0) disabled; set state(1) normal
+    $widget_list(mask_threshval) configure -state $state([expr 1 - $global_list(mask_autothresh)])
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load mask
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::loadmask { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select mask" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	set global_list(result_fmask) "*[ file extension $fname ]"
+	
+	## load mask into memory
+	LoadMask $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in mask image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::LoadMask { fname } {
+    
+    set MASK 1     
+    set mask [ lindex $global_list(result_list) $MASK ]
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in mask image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+
+     ## if mask not a unsigned char image, convert it
+    set scalar_type [ [ $ana GetOutput ] GetScalarType ]    
+
+    if { $scalar_type != 3 } {	
+	
+	set imcast [ vtkImageCast [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $imcast "Converting mask to unsigned char values..."
+	$imcast SetInput [ $ana GetOutput ]
+	$imcast SetOutputScalarTypeToUnsignedChar
+	$imcast ClampOverflowOn	
+	$imcast Update
+	
+    ## fixed on 11/1/04
+	$mask ShallowCopyImage [ $imcast GetOutput ]
+	$mask CopyImageHeader [ $ana GetImageHeader ]	
+
+	$imcast Delete
+	
+    } else {
+	
+	$mask SetFromAnalyzeSource $ana
+    }
+    
+    set global_list(mask_fname) $fname
+
+    WatchOff
+
+    $ana Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Set result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::SetResultPreffix { preffix } {
+    set global_list(result_fpreffix) $preffix
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Get result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::GetResultPreffix { } {
+    return $global_list(result_fpreffix)
+}
+
+itcl::body mpjtensorutility::SetCurrentDirectory { fname } {
+    set global_list(result_fdir) $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Clear all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::ClearAllResults { } {
+    
+    foreach result $global_list(result_list) {
+	$result Clear
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::SaveAllResults { } {
+
+    foreach result $global_list(result_list) title $global_list(result_title) {
+	
+	set fname $global_list(result_fpreffix)
+	set suffix $global_list(result_fsuffix)	
+	set fname "$fname[ lindex $title 1 ]${suffix}"
+
+
+	$result Save $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save single result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::SaveResult { index } {        
+
+    set fname $global_list(result_fpreffix)
+    set suffix $global_list(result_fsuffix)	
+    set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]${suffix}"
+
+    [lindex $global_list(result_list) $index] Save $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::saveallresults { } {
+
+    ## browse for directory    
+    set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+
+    if { $fdir != "" } {
+	
+	set global_list(result_fdir) $fdir
+	set suffix $global_list(result_fsuffix)
+	
+	foreach result $global_list(result_list) title $global_list(result_title) {
+	    
+	    set fname $global_list(result_fpreffix)
+	    set fname "$fname[ lindex $title 1 ]$suffix"
+	    
+#	    puts stderr "Saving in $fname"
+	    $result Save [ file join $fdir $fname ]
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::saveresult { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(result_list) getcurselection ]
+    
+    if { $sel_item != "" } { 
+	
+	## browse for directory
+	set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+	set suffix $global_list(result_fsuffix)
+	if { $fdir != "" } {
+	    
+	    set global_list(result_fdir) $fdir
+
+	    foreach item $sel_item {
+		
+		set index [ $widget_list(result_list) index $item ]
+		set result [ lindex $global_list(result_list) $index ]
+		
+		set fname $global_list(result_fpreffix)
+		set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]${suffix}"
+		
+		$result Save [ file join $fdir $fname ]		
+	    }	    
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::DisplayResult { index } {
+    $parent SetResultsFromObject \
+	[ [ lindex $global_list(result_list) $index ] GetThisPointer ] $this
+    $parent ShowWindow
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::displayresult { } {
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	set index [ $widget_list(result_list) index [lindex $sel_item 0] ]
+	set result [ lindex $global_list(result_list) $index ]
+
+	$this DisplayResult $index	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::result_clear { } {
+
+    for { set i 0 } { $i < [ llength $global_list(result_list) ] } { incr i } {	
+
+	set title [ lindex [ lindex $global_list(result_title) $i ] 0 ]	    
+
+	if { $title == "Anatomical mask" } {
+	    if { $global_list(mask_auto) } {
+		[ lindex $global_list(result_list) $i ] Clear
+	    }
+	} else { 
+	    [ lindex $global_list(result_list) $i ] Clear
+	}
+    }
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create baseline image
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::result_createbaseline { }  {
+    
+    set BASELINE 0
+    set MASK 1
+    set TENSOR 2
+    set MEAN 3
+    set ADC 4
+
+    ## the baseline repository
+    set baseline [ lindex $global_list(result_list) $BASELINE ]  
+    
+    ## the mean image
+    set mean [ lindex $global_list(result_list) $MEAN ]  
+        
+    set avg_filter1 [ vtkmpjFrameAverage [ pxvtable::vnewobj ] ]    
+    
+    $this SetFilterCallbacks $avg_filter1 "Extracting baseline image..."
+    
+    ## add images into average filter
+    set num [ llength $global_list(input_list) ]
+    
+    for { set i 0 } { $i < $num } { incr i } {
+	set input [ lindex $global_list(input_list) $i ]		
+	$avg_filter1 AddInput [ $input GetImage ]	
+    }
+    
+    ## compute average
+    $avg_filter1 Update
+
+    ## get average diffusion components
+    set frm_filter [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $frm_filter "Extracting mean diffusion components..."
+    $frm_filter SetInput [ $avg_filter1 GetOutput ]
+    $frm_filter SetStartFrame $global_list(input_ndw)
+    $frm_filter SetEndFrame [expr $global_list(input_dw) + $global_list(input_ndw) - 1 ]
+    $frm_filter Update
+    
+    ## save average
+    $mean ShallowCopyImage [ $frm_filter GetOutput ]
+    $mean CopyImageHeader [ $baseline GetImageHeader ]
+
+    ## get rid off the filter
+    $frm_filter Delete
+    
+    ## if more than one nondiffusion image per series, average all them out too
+    if { $global_list(input_ndw) > 1 } {
+	
+	set avg_filter2 [ vtkmpjFrameAverage [ pxvtable::vnewobj ] ]
+	
+	for { set j 0 } { $j < $global_list(input_ndw) } { incr j } {
+	    
+	    set frm_filter [ vtkImageExtractComponents [ pxvtable::vnewobj ] ]
+	    $frm_filter SetInput [ $avg_filter1 GetOutput ]
+	    $frm_filter SetComponents $j
+	    $frm_filter Update
+	    
+	    $avg_filter2 AddInput [ $frm_filter GetOutput ]
+	    
+	    $frm_filter Delete
+	}
+	
+	## get average nondiffusion image
+	$avg_filter2 Update
+	
+	$baseline ShallowCopyImage [ $avg_filter2 GetOutput ]
+
+	## discard filter
+	$avg_filter2 Delete
+	
+    } else {
+	
+	set frm_filter [ vtkImageExtractComponents [ pxvtable::vnewobj ] ]
+	$frm_filter SetInput [ $avg_filter1 GetOutput ]
+	$frm_filter SetComponents 0
+	$frm_filter Update
+	
+	$baseline ShallowCopyImage [ $frm_filter GetOutput ]
+
+	
+	## discard filter
+	$frm_filter Delete
+    }
+    $baseline CopyImageHeader [ $mean GetImageHeader ]
+
+
+    ## get rid off mean filter
+    $avg_filter1 Delete
+
+    update idletasks
+
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create mask image
+#-------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::result_createmask { }  {
+
+    set BASELINE 0
+    set MASK 1
+    set TENSOR 2
+    set MEAN 3
+    set ADC 4
+    
+    ## get baseline image
+    set baseline [ lindex $global_list(result_list) $BASELINE ]
+    
+    ## determine threshold value    
+    if { $global_list(mask_autothresh) == 1 } {
+	
+	set hist [ vtkImageAccumulate [ pxvtable::vnewobj ] ]    
+	
+	$hist SetInput [ $baseline GetImage ]
+	$hist Update
+	
+	## determine threshold value
+	set min [ lindex [ $hist GetMin ] 0 ]
+	set max [ lindex [ $hist GetMax ] 0 ]
+	set global_list(mask_threshval) [ expr int($min + (($max - $min) * 0.04)) ]
+	
+	$hist Delete
+    }
+
+    update idletasks
+
+    ## threshold baseline image
+    set thresh [ vtkImageThreshold [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $thresh "Creating anatomical mask..."
+    $thresh SetInput [ $baseline GetImage ]
+    $thresh ThresholdByUpper $global_list(mask_threshval)
+    $thresh SetInValue 1
+    $thresh SetOutValue 0
+    $thresh SetOutputScalarTypeToUnsignedChar
+    $thresh Update
+    
+    set mask [ lindex $global_list(result_list) $MASK ]    
+    
+    ## remove unconnected voxels
+    if { $global_list(mask_connected) == 1 } {
+	
+	set loc [ $parent cget -currentpoint ] 
+	#	puts "location = $loc"
+	set lx -1
+	set ly -1
+	set lz -1
+
+	if { [ llength $loc ] == 3 } {
+	    scan $loc "%f %f %f" lx ly lz
+	} 
+
+	if { $lx <= 0 || $ly <= 0 || $lz <= 0 } {
+	    scan [ [$baseline GetImage] GetDimensions ] "%d %d %d" dx dy dz
+	    set lx [expr $dx / 2] 
+	    set ly [expr $dy / 2]
+	    set lz [expr $dz / 2]
+	} else {
+	    set lx [ expr int($lx) ]
+	    set ly [ expr int($ly) ]
+	    set lz [ expr int($lz) ]
+	}
+
+	set seedc [ vtkImageSeedConnectivity [ pxvtable::vnewobj ] ]
+	$seedc SetInput [ $thresh GetOutput ]
+	$seedc AddSeed $lx $ly $lz
+	$seedc SetInputConnectValue 1
+	$seedc SetOutputConnectedValue 1
+	$seedc SetOutputUnconnectedValue 0 
+	$seedc SetDimensionality 3
+	
+	SetFilterCallbacks $seedc "Tracing connectivity..."
+	$seedc Update	
+	
+	$mask ShallowCopyImage [ $seedc GetOutput ] 	
+
+    } else {
+	
+	$mask ShallowCopyImage [ $thresh GetOutput ] 
+    }
+
+
+    $mask CopyImageHeader [ $baseline GetImageHeader ]
+    
+    set global_list(mask_fname) " "
+    
+    $thresh Delete
+    
+    update idletasks
+    
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create tensor image
+#-------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::result_createadc { } {
+
+    set BASELINE 0
+    set MASK 1
+    set TENSOR 2
+    set MEAN 3
+    set ADC 4
+    
+    set baseline [ lindex $global_list(result_list) $BASELINE ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set mean [ lindex $global_list(result_list) $MEAN ]
+    set adc [ lindex $global_list(result_list) $ADC ]
+
+    
+    set adc_filter [ vtkmpjApparentDiffusion [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $adc_filter "Computing apparent diffusion coefficient..."
+    $adc_filter SetInput [ $mean GetImage ]
+    $adc_filter SetBaseline [ $baseline GetImage ]
+    $adc_filter SetMask [ $mask GetImage ]
+    if { $global_list(input_bfactorenable) == 1 } {
+	$adc_filter SetbValue $global_list(input_bfactor)
+    } else {
+	$adc_filter SetbValue 1.0
+    }
+    
+    $adc_filter SetShift 1E-12
+    $adc_filter Update
+    
+    $adc ShallowCopyImage [ $adc_filter GetOutput ]
+    $adc CopyImageHeader [ $mean GetImageHeader ]
+    
+    $adc_filter Delete
+    
+    update idletasks   
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create tensor image
+#-------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::result_createtensor { }  {
+    
+    set BASELINE 0
+    set MASK 1
+    set TENSOR 2
+    set MEAN 3
+    set ADC 4
+    
+    set baseline [ lindex $global_list(result_list) $BASELINE ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set mean [ lindex $global_list(result_list) $MEAN ]
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    
+    set index [ $widget_list(gradient_ndir) cget -clientdata ]
+    set table [ lindex [ lindex $global_list(gradient_list) $index ] 2 ]
+    
+    ## populate the gradient direction array
+    set gradients [ vtkDoubleArray [ pxvtable::vnewobj ] ]
+    $gradients SetNumberOfComponents 3
+    $gradients SetNumberOfTuples [ llength $table ]
+    
+    set flipx [ expr $global_list(tensor_flipx) > 0 ? -1 : 1 ]
+    set flipy [ expr $global_list(tensor_flipy) > 0 ? -1 : 1 ]
+    set flipz [ expr $global_list(tensor_flipz) > 0 ? -1 : 1 ]
+    
+    set gx 0; set gy 0; set gz 0;
+    
+    for {set i 0} {$i < [llength $table]} {incr i} {
+	
+	set tuple [ lindex $table $i ]
+	
+	if { $global_list(tensor_swap) == 1 } {
+	    if { $global_list(tensor_swapdir) == 1 } {
+		set gx [expr [lindex $tuple 1] * $flipy ]
+		set gy [expr [lindex $tuple 0] * $flipx ]
+		set gz [expr [lindex $tuple 2] * $flipz ]
+	    }
+	    if { $global_list(tensor_swapdir) == 2 } {
+		set gx [expr [lindex $tuple 2] * $flipz ]
+		set gy [expr [lindex $tuple 1] * $flipy ]
+		set gz [expr [lindex $tuple 0] * $flipx ]
+	    }
+	    if { $global_list(tensor_swapdir) == 3 } {
+		set gx [expr [lindex $tuple 0] * $flipx ]
+		set gy [expr [lindex $tuple 2] * $flipz ]
+		set gz [expr [lindex $tuple 1] * $flipy ]
+	    }	   
+	} else {
+	    set gx [expr [lindex $tuple 0] * $flipx ]
+	    set gy [expr [lindex $tuple 1] * $flipy ]
+	    set gz [expr [lindex $tuple 2] * $flipz ]
+	}
+	
+	#if { $global_list(tensor_swapyz) > 0 } {
+	#	    set gx [expr [lindex $tuple 0] * $flipx ]
+	#	    set gy [expr [lindex $tuple 2] * $flipz ]
+	#	    set gz [expr [lindex $tuple 1] * $flipy ]
+	#	} elseif { $global_list(tensor_swapxz) > 0 } {
+	#	    set gx [expr [lindex $tuple 2] * $flipz ]
+	#	    set gy [expr [lindex $tuple 1] * $flipy ]
+	#	    set gz [expr [lindex $tuple 0] * $flipx ]
+	#	} else {
+	#	    set gx [expr [lindex $tuple 0] * $flipx ]
+	#	    set gy [expr [lindex $tuple 1] * $flipy ]
+	#	    set gz [expr [lindex $tuple 2] * $flipz ]
+	#	}
+		
+	$gradients SetTuple3 $i $gx $gy $gz
+    }
+ 
+    set baseline [ lindex $global_list(result_list) $BASELINE ]
+    set mask [ lindex $global_list(result_list) $MASK ]   
+
+    ## compute tensor
+    set tensor_filter [ vtkmpjTensorLeastSquares [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $tensor_filter "Computing diffusion tensor..."
+    $tensor_filter SetGradients $gradients
+    $tensor_filter SetNumberOfDirections [ $gradients GetNumberOfTuples ]
+    $tensor_filter SetInput [ $mean GetImage ]   
+    $tensor_filter SetBaseline [ $baseline GetImage ]
+    $tensor_filter SetMask [ $mask GetImage ]
+    if { $global_list(input_bfactorenable) == 1 } {
+	$tensor_filter SetbValue $global_list(input_bfactor) 
+    } else {
+	$tensor_filter SetbValue 1.0
+    }
+    $tensor_filter SetSymmetricTensor $global_list(input_tensorsymm)
+    
+    $gradients Delete
+    
+    ## compute tensor
+    $tensor_filter Update
+    
+    if { $global_list(tensor_rotation) == 1 } {
+	
+	## rotate tensor
+	set tensor_xform [ vtkmpjImageTensorTransform [ pxvtable::vnewobj ] ]
+	$tensor_xform SetInput [ $tensor_filter GetOutput ]
+	$tensor_xform SetRotation $global_list(tensor_rotx) $global_list(tensor_roty) $global_list(tensor_rotz) 
+	$this SetFilterCallbacks $tensor_xform "Transforming tensor..."
+	
+	# rotate tensor
+	$tensor_xform Update
+	
+	$tensor ShallowCopyImage [ $tensor_xform GetOutput ]
+	$tensor CopyImageHeader [ $mean GetImageHeader ]
+	$tensor_xform Delete
+
+    } else {	
+	
+	$tensor ShallowCopyImage [ $tensor_filter GetOutput ]
+	$tensor CopyImageHeader [ $mean GetImageHeader ]
+    }
+
+    $tensor_filter Delete
+
+    update idletasks   
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Compute results
+# -----------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::ComputeResults { } {
+
+    set BASELINE 0
+    set MASK 1
+    set TENSOR 2
+    set MEAN 3
+    set ADC 4
+
+    WatchOn
+    
+    ## clear results
+    result_clear
+    
+    ## create baseline image
+    set result [ result_createbaseline ]
+    
+    if { $result == 0 } {
+	WatchOff; return
+    }
+    
+    ## create mask if not loaded in
+    if { $global_list(mask_auto) } {
+	
+	set result [ result_createmask ]
+	
+	if { $result == 0 } {
+	    WatchOff; return
+	}
+    }
+
+    ## create adc
+    if { $global_list(adc_compute) } {	
+	set result [ result_createadc ]   
+    } 
+    
+    ## create tensor 
+    set result [ result_createtensor ]
+    
+    if { $result == 0 } {
+	WatchOff; return
+    }
+    
+    set tensor_map [ lindex $global_list(result_list) $TENSOR ]
+    $parent SetResultsFromObject [ $tensor_map GetThisPointer ] $this
+    
+    $widget_list(notebook) view "Results"; update
+    
+    WatchOff
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create diffusion input control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::CreateInputControl { base } {      
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Diffusion image series"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+   
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t -side top
+
+    set subframe0left [ frame $subframe0.subframeleft ]
+    pack $subframe0left -side left -fill both -expand t -padx 0
+
+    iwidgets::scrolledlistbox $subframe0left.inputlist \
+	-hscrollmode dynamic \
+	-visibleitems 40x12 \
+	-listvariable [ itcl::scope global_list(input_fname) ] \
+	-selectmode extended \
+	-selectioncommand [ itcl::code $this input_selectioncommand_cb ]    
+    pack $subframe0left.inputlist -side left -fill both -expand t -padx 2 -pady 2
+    set widget_list(input_list) $subframe0left.inputlist
+    
+    set subframe0right [ frame $subframe0.subframeright ]
+    pack $subframe0right -side right -fill y -expand f -padx 0
+    
+    set inputbbox [ iwidgets::buttonbox $subframe0right.input -orient vertical ]
+    $inputbbox add add -text "Add..." -command [ itcl::code $this addinput ]
+    $inputbbox add remove -text "Remove" -command [ itcl::code $this removeinput ] -state disabled
+    $inputbbox add display -text "Display" -command [ itcl::code $this displayinput ] -state disabled   
+    pack $inputbbox -side top -fill x -expand f -padx 0
+    set widget_list(input_buttonbox) $inputbbox    
+      
+    iwidgets::spinint $subframe0right.input_dispframe -labeltext "Frame:"  \
+	-fixed 2 -width 3 -step 1 -range {0 100} -state disabled \
+	-textvariable [ itcl::scope global_list(input_frameno) ] 
+    pack $subframe0right.input_dispframe -side top -padx 5 -pady 0
+    set widget_list(input_frameno) $subframe0right.input_dispframe     
+    
+#    set tensorsymm [ checkbutton $subframe0right.tensor_symm \
+#			 -text "Symmetric" \
+#			 -variable [ itcl::scope global_list(input_tensorsymm) ] ]
+#    pack $tensorsymm -side top -padx 5 -pady 10
+#    set widget_list(tensorsymm) $subframe0right.tensorsymm
+
+#    set computeadc [ checkbutton $subframe0right.computeadc \
+#			 -text "Compute ADC" \
+#			 -variable [ itcl::scope global_list(adc_compute) ] ]
+#    pack $computeadc -side top -padx 5 -pady 5
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill x -expand f
+     
+    iwidgets::spinint $subframe1.input_ndw -labeltext "Number of T2 images:" \
+	-fixed 2 -width 3 -step 1 -range {1 10} \
+	-textvariable [ itcl::scope global_list(input_ndw) ]
+    pack $subframe1.input_ndw -side left -padx 5 -pady 5  
+    set widget_list(input_ndw) $frame0.input_ndw
+    $subframe1.input_ndw up
+
+    set gradient_ndir1 [ iwidgets::spinner $subframe1.gradient_ndir1 \
+			    -labeltext "Set of gradient directions:" \
+			    -width 6 \
+			    -clientdata 0 \
+			    -decrement [itcl::code $this gradient_increment_ndir -1 ] \
+			    -increment [itcl::code $this gradient_increment_ndir +1 ] ]
+    pack $gradient_ndir1 -side right -padx 5
+    set widget_list(gradient_ndir1) $gradient_ndir1       
+    $gradient_ndir1 clear
+    $gradient_ndir1 insert 0 "ME6" 
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill x -expand f
+    
+    set widget_list(computebtn) [ button $subframe2.compute -text "Compute!" \
+				      -state disabled \
+				      -command [ itcl::code $this ComputeResults ] ]    
+    pack $subframe2.compute -side left -fill x -padx 5 -pady 10    
+
+    iwidgets::entryfield $subframe2.input_bfactor \
+	-width 6 \
+	-validate real \
+	-textvariable [ itcl::scope global_list(input_bfactor) ]
+    pack $subframe2.input_bfactor -side right -padx 5 -pady 5  
+
+    checkbutton $subframe2.input_bfactorenable \
+	-text "b-value (s/mm^2):" \
+	-variable [ itcl::scope global_list(input_bfactorenable) ]
+    pack $subframe2.input_bfactorenable -side right -padx 2 -pady 5
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create gradient control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::CreateGradientControl { base } {   
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Diffusion gradient directions "
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand f
+
+    ## create gradient file gadget
+    set gradient_fname [ iwidgets::entryfield $subframe0.gradient_fname -state disabled \
+			     -labeltext "Filename:"  \
+			     -textvariable [ itcl::scope global_list(gradient_fname) ] ]
+    pack $gradient_fname -side left -expand t -fill x -padx 5 -pady 0
+    set widget_list(gradient_fname) $gradient_fname
+    
+    set gradient_load [ iwidgets::buttonbox $subframe0.gradient_load -orient horizontal -padx 2 -pady 2 ]
+    $gradient_load add load -text "Load..." -command [ itcl::code $this loadgradient ]
+    pack $gradient_load -side left -fill x -pady 0
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -pady 0
+
+    set gradient_ndir [ iwidgets::spinner $subframe1.gradient_ndir \
+			    -labeltext "Set of directions:" \
+			    -width 6 \
+			    -clientdata 0 \
+			    -decrement [itcl::code $this gradient_increment_ndir -1 ] \
+			    -increment [itcl::code $this gradient_increment_ndir +1 ] ]
+    pack $gradient_ndir -side left -padx 5 -pady 0
+    set widget_list(gradient_ndir) $gradient_ndir
+
+    set gradient_check [ iwidgets::buttonbox $subframe1.gradient_check -orient horizontal -padx 2 -pady 2]
+    $gradient_check add load -text "Check" -command [ itcl::code $this checkgradient ]
+    pack $gradient_check -side right -fill x -pady 0
+ 
+    iwidgets::entryfield $subframe1.gradient_tol \
+	-width 5 \
+	-validate real \
+	-labeltext "Colinearity tolerance:" \
+	-textvariable [ itcl::scope global_list(gradient_tol) ]
+    pack $subframe1.gradient_tol -side right -fill x -pady 5
+    
+    set subframe15 [ frame $frame0.subframe15 ]
+    pack $subframe15 -fill both -side top -expand f
+    
+    set subframe15l [ frame $subframe15.subframe15l ]
+    pack $subframe15l -fill both -side left -expand f
+
+    set subframe15r [ frame $subframe15.subframe15r ]
+    pack $subframe15r -fill both -side left -expand t
+    
+    ## initialize number of directions
+    $gradient_ndir clear
+    $gradient_ndir insert 0 "ME6"
+    
+    ## create list box 
+    set gradient_list [ iwidgets::scrolledlistbox $subframe15l.gradient_list -visibleitems 42x15 -textfont {fixed 8} ]
+    pack $gradient_list -side left -expand f -fill both -pady 0 -padx 2    
+    set widget_list(gradient_list) $gradient_list
+    
+    set grad_showanti [ checkbutton $subframe15r.grad_showanti \
+			    -text "Show antipodal directions" \
+			    -command [itcl::code $this gradient_showantipodal ] \
+			    -variable [ itcl::scope global_list(gradient_showanti) ] ]
+    pack $grad_showanti -side top -anchor w -padx 5 -pady 2         
+    
+    ## create gradient points
+    set grad_mapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    $grad_mapper SetResolveCoincidentTopologyToPolygonOffset
+    $grad_mapper SetInput [ $global_list(gradient_polydata) GetOutput ]
+    $global_list(gradient_actor) SetMapper $grad_mapper
+    $global_list(gradient_anti_actor) SetVisibility $global_list(gradient_showanti)
+    $global_list(gradient_anti_actor) SetMapper $grad_mapper
+    $global_list(gradient_anti_actor) SetScale -1 -1 -1
+    $grad_mapper Delete
+            
+    ## create gradient sphere
+    set grad_sphere [ mpjguisphere \#auto 0 ]
+    $grad_sphere Resize 150 150
+    $grad_sphere Initialize $subframe15r
+    pack forget [ $grad_sphere GetButtonBoxWidget ]
+    pack forget [ $grad_sphere GetPropertyWidget ] 
+    [ [ $grad_sphere GetWireframeActor ] GetProperty ] SetColor 0.5 0.5 0.5
+    [ [ $grad_sphere GetWireframeActor ] GetProperty ] SetLineWidth 1.0
+    [ [ $grad_sphere GetWireframeActor ] GetProperty ] SetOpacity 0.05
+    $grad_sphere SetResolution 20
+    $grad_sphere AddActor $global_list(gradient_actor)
+    $grad_sphere AddActor $global_list(gradient_anti_actor)
+    $grad_sphere Update
+    $grad_sphere Show
+    
+    set widget_list(gradient_sphere) $grad_sphere   
+
+    ## populate list of directions
+    gradient_populatelist 0    
+    
+ 
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -fill both -expand t
+   
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create input mask control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::CreateMaskControl { base } {        
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Mask image (Anatomy)"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -side top -fill both -expand f -pady 5
+    
+    set mask_auto [ checkbutton $subframe0.mask_auto \
+			-text "Compute from unweighted diffusion series (T2 images)" \
+			-variable [ itcl::scope global_list(mask_auto) ] \
+			-command [ itcl::code $this mask_autochanged_cb ] ]
+    pack $mask_auto -side left -fill both -padx 5 -pady 2
+
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+  
+    set mask_fname [ iwidgets::entryfield $subframe1.mask_fname \
+			 -textvariable [ itcl::scope global_list(mask_fname) ] \
+			 -state disabled -labeltext "Filename:" ] 
+    pack $mask_fname -side left -expand t -fill x -padx 5 -pady 2
+    set widget_list(mask_fname) $mask_fname
+
+    set mask_load [ iwidgets::buttonbox $subframe1.mask_load -orient horizontal -padx 2 ]
+    $mask_load add load -text "Load..." -command [ itcl::code $this loadmask ] -state disabled
+    pack $mask_load -side left -fill x -pady 2
+    set widget_list(mask_load) $mask_load
+    
+    set subframe3 [ frame $frame0.subframe3 ]
+    pack $subframe3 -side top -fill both -expand f -padx 2
+
+    set mask_autothresh [ checkbutton $subframe3.mask_autothresh \
+			      -text "Auto-threshold" \
+			      -variable [ itcl::scope global_list(mask_autothresh) ] \
+			      -command [ itcl::code $this mask_autothreshchanged_cb ] ]    
+    pack $mask_autothresh -side left -padx 5 -pady 4
+    set widget_list(mask_autothresh) $mask_autothresh
+    
+    set mask_threshval [ iwidgets::spinint $subframe3.mask_threshval \
+			     -labeltext "Threshold value for T2 image:" \
+			     -fixed 5 -width 5 -range {1 10000} -step 1 \
+			     -textvariable [ itcl::scope global_list(mask_threshval) ] \
+			     -state disabled ]
+    pack $mask_threshval -side right -pady 5 -padx 10
+    set widget_list(mask_threshval) $mask_threshval
+    
+    set subframe4 [ frame $frame0.subframe4 ]
+    pack $subframe4 -side top -fill both -expand f -padx 2
+    
+    set mask_connected [ checkbutton $subframe4.mask_connected -text "Trace connectivity" \
+			     -variable [ itcl::scope global_list(mask_connected) ] ]    
+    pack $mask_connected -side left -pady 5 -padx 4       
+    set widget_list(mask_connected) $mask_connected
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create transform control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::CreateTransformControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Tensor transformation"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -fill both -expand f -padx 5 -pady 5
+        
+    set tensorflipx [ checkbutton $subframe2.tensorflipx \
+			  -text "Flip X" \
+			  -variable [ itcl::scope global_list(tensor_flipx) ] ]
+    pack $tensorflipx -side left -padx 5 -pady 2
+    set widget_list(tensor_flipx) $tensorflipx
+    
+    set tensorflipy [ checkbutton $subframe2.tensorflipy \
+			  -text "Flip Y" \
+			  -variable [ itcl::scope global_list(tensor_flipy) ] ]
+    pack $tensorflipy -side left -padx 5 -pady 2
+    set widget_list(tensor_flipy) $tensorflipy   
+    
+    set tensorflipz [ checkbutton $subframe2.tensorflipz \
+			  -text "Flip Z" \
+			  -variable [ itcl::scope global_list(tensor_flipz) ] ]
+    pack $tensorflipz -side left -padx 5 -pady 2
+    set widget_list(tensor_flipz) $tensorflipz
+
+
+    set subframe3 [ frame $frame0.subframe3 ]
+    pack $subframe3 -fill both -expand f -padx 5 -pady 5
+    
+    set tensor_swap [ checkbutton $subframe3.tensor_swap \
+			  -text "Swap axes" \
+			  -variable [ itcl::scope global_list(tensor_swap) ] ]
+    pack $tensor_swap -side left -padx 5 -pady 4
+    set widget_list(tensor_swap) $tensor_swap
+
+    set tensorswapxy [ radiobutton $subframe3.tensorswapxy \
+			   -text "Swap X-Y" \
+			   -value 1 \
+			   -variable [ itcl::scope global_list(tensor_swapdir) ] ]
+    pack $tensorswapxy -side left -padx 5 -pady 2
+    set widget_list(tensor_swapxy) $tensorswapxy
+
+    set tensorswapxz [ radiobutton $subframe3.tensorswapxz \
+			   -text "Swap X-Z" \
+			   -value 2 \
+			   -variable [ itcl::scope global_list(tensor_swapdir) ] ]
+    pack $tensorswapxz -side left -padx 5 -pady 2
+    set widget_list(tensor_swapxz) $tensorswapxz
+
+    set tensorswapyz [ radiobutton $subframe3.tensorswapyz \
+			   -text "Swap Y-Z" \
+			   -value 3 \
+			   -variable [ itcl::scope global_list(tensor_swapdir) ] ]
+    pack $tensorswapyz -side left -padx 5 -pady 2
+    set widget_list(tensor_swapyz) $tensorswapyz
+
+
+  
+    
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill x -expand f -padx 5 -pady 5
+
+    set tensor_rotation [ checkbutton $subframe0.tensor_rotation \
+			      -text "Rotate tensor" \
+			      -variable [ itcl::scope global_list(tensor_rotation) ] ]
+    pack $tensor_rotation -side left -padx 5 -pady 4
+    set widget_list(tensor_rotation) $tensor_rotation
+
+    iwidgets::entryfield $subframe0.tensor_rotx \
+	-width 5 \
+	-validate real \
+	-labeltext "Rx:" \
+	-textvariable [ itcl::scope global_list(tensor_rotx) ]
+    pack $subframe0.tensor_rotx -side left -fill x -pady 5
+    
+    iwidgets::entryfield $subframe0.tensor_roty \
+	-width 5 \
+	-validate real \
+	-labeltext "Ry:" \
+	-textvariable [ itcl::scope global_list(tensor_roty) ]
+    pack $subframe0.tensor_roty -side left -fill x -pady 5
+    
+    iwidgets::entryfield $subframe0.tensor_rotz \
+	-width 5 \
+	-validate real \
+	-labeltext "Rz:" \
+	-textvariable [ itcl::scope global_list(tensor_rotz) ]
+    pack $subframe0.tensor_rotz -side left -fill x -pady 5
+
+    label $subframe0.dummy -text "degrees"
+    pack $subframe0.dummy -side left
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create results control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::CreateResultsControl { base } {   
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Results"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+    
+    iwidgets::scrolledlistbox $subframe0.resultlist \
+	-hscrollmode dynamic \
+	-selectmode extended \
+	-visibleitems 40x10 
+    
+    pack $subframe0.resultlist -side left -fill both -expand t -padx 2 -pady 2
+    set widget_list(result_list) $subframe0.resultlist
+    
+    foreach item $global_list(result_title) {
+	$widget_list(result_list) insert end [lindex $item 0]
+    }
+    
+    set subframe1 [ frame $subframe0.subframe1 ]
+    pack $subframe1 -side right -fill both -padx 0
+    
+    set resultbbox [ iwidgets::buttonbox $subframe1.input -orient vertical ]
+    $resultbbox add display -text "Display" -command [ itcl::code $this displayresult ]
+    $resultbbox add save -text "Save..." -command [ itcl::code $this saveresult ]
+    $resultbbox add saveall -text "Save all" -command [ itcl::code $this saveallresults ]    
+    pack $resultbbox -side top -fill x -expand t -padx 0
+    set widget_list(result_buttonbox) $resultbbox
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill x -padx 2 -pady 5
+
+    set result_fpreffix [ iwidgets::entryfield $subframe2.result_fpreffix \
+			      -textvariable [ itcl::scope global_list(result_fpreffix) ] \
+			      -labeltext "Preffix:" ]
+    pack $result_fpreffix -side left -expand t -fill x -padx 5 -pady 2
+    set widget_list(result_fpreffix) $result_fpreffix    
+}
+
+# -------------------------------------------------------------------------------------------
+#  Diffusion control inititialization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::Initialize { widget } {
+    
+    if { $initialized == 1 } { return $basewidget }
+    
+    #  -------------------------------------
+    #  Create User Interface
+    #  -------------------------------------	
+    set basewidget [toplevel $widget ]
+    wm geometry $basewidget 600x480
+    wm withdraw $basewidget
+    
+    set notebook $basewidget.notebook    
+    iwidgets::tabnotebook $notebook -tabpos w         
+    set widget_list(notebook) $notebook
+
+    set mb [ frame $basewidget.mb ]
+    pack $mb -side top -fill x -expand false
+    
+    CreateMenu $mb
+    
+    CreateInputControl        [ $notebook add -label "Diffusion" ]
+    CreateMaskControl         [ $notebook add -label "Mask" ]    
+    CreateGradientControl     [ $notebook add -label "Gradients" ]
+    CreateTransformControl    [ $notebook add -label "Transform" ]
+    CreateResultsControl      [ $notebook add -label "Results" ] 
+
+    pack $notebook -side top -fill both -expand t -padx 5
+    $notebook view "Diffusion"
+
+    set bottom [ frame $basewidget.bottom -relief ridge]
+    pack $bottom -side top -fill x -expand false
+    
+    set pbar [ frame $basewidget.pbar -width 400 -height 20 ]
+    pack $pbar -side bottom -expand f -fill x
+    CreateProgressBar $pbar
+    
+    set w [ frame $basewidget.w -relief ridge -width 800 ]
+    pack $w -side bottom -fill x -expand false
+    
+    eval "button $w.close -text Close -command { $this DismissWindow }"
+
+    pack $w.close -side right -fill x -padx 5 -pady 10
+    
+    set initialized 1
+
+    SetTitle $appname
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { $this DismissWindow }"
+
+    return $basewidget 
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create top level menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::CreateMenu { mb } {    
+    
+    menubutton $mb.file          -text Setup       -menu $mb.file.m -underline 0
+     pack $mb.file $mb.file    -side left
+    menubutton $mb.results       -text Results     -menu $mb.results.m -underline 0
+    pack $mb.file $mb.results    -side left
+    menubutton $mb.help      -text Help         -menu $mb.help.m -underline 0 -padx 4
+    pack $mb.help  -side right
+
+    
+    menu $mb.file.m -tearoff 0 
+    eval "$mb.file.m add command -label \"Load Setup\" -command { $this LoadSetup \"\" } -underline 0 "
+    eval "$mb.file.m add command -label \"Save Setup\" -command { $this SaveSetup \"\" } -underline 0"
+    $mb.file.m add separator
+    if { $parent == 0 } {
+	eval "$mb.file.m add command -label Exit -command {  pxtkexit } -underline 1"
+    } else {
+	eval "$mb.file.m add command -label Close -command {  $this HideWindow } -underline 1"
+    }
+
+    menu $mb.results.m -tearoff 0 
+    eval "$mb.results.m add command -label \"Compute All\" -command { $this ComputeResults } -underline 0 -state disabled"
+    $mb.results.m add command -label "Save All Results" -command [ itcl::code $this saveallresults ] -underline 0
+
+    menu $mb.help.m -tearoff 0
+
+    set widget_list(menu_results) $mb.results.m    
+
+    eval "$mb.help.m add command -label About -command { $this AboutCommand }"
+}
+
+#-------------------------------------------------------------------------------------------
+#  Add controls to menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::AddToMenuButton { mb args } {
+    eval "$mb add command -label \"Tensor utility\" -command {$this ShowWindow \"Diffusion\"}"
+}
+#-------------------------------------------------------------------------------------------
+#
+#   Bis Algorithm Interface
+#
+#-------------------------------------------------------------------------------------------
+itcl::body mpjtensorutility::SetParametersFromBisAlgorithm { ndw bval dname dfname flipx flipy flipz } {
+
+    set global_list(input_ndw) $ndw
+    set global_list(input_bfactor) $bval
+    set global_list(input_bfactorenable) 1
+    set global_list(mask_connected) 0
+
+    set lst $global_list(gradient_list)
+    set i 0; set found 0
+    while { $i < [ llength $lst ] && $found == 0 } {
+	set t [ lindex [ lindex $lst $i ] 1 ]
+	if  { $dname == [ lindex [ lindex $lst $i ] 1 ]  } {
+	    set found 1
+	    set dir_index $i 
+	    set dirset $dname
+	}
+	incr i
+    }
+
+    if { $found == 1 } {
+	gradient_populatelist $dir_index
+	
+	set dirset [ lindex [ lindex $global_list(gradient_list) $dir_index ] 1 ]
+	
+	## set default number of directions
+	$widget_list(gradient_ndir) delete 0 end
+	$widget_list(gradient_ndir) insert 0 $dirset
+	$widget_list(gradient_ndir) configure -clientdata $dir_index
+	
+	## set default number of directions
+	$widget_list(gradient_ndir1) delete 0 end
+	$widget_list(gradient_ndir1) insert 0 $dirset
+	$widget_list(gradient_ndir1) configure -clientdata $dir_index
+    } else {
+	set ok [ $this LoadGradient $dfname ]
+	if { $ok == 0 } {
+	    set errormeesage "Failed to load gradients from $dfname"
+	    return 0
+	}
+	set global_list(gradient_fdir) [ file dirname $dfname ]
+    }
+	
+    set bis_algorithmmode 1
+
+    if { $flipx !=0 } {
+	set global_list(tensor_flipx) 1
+    } else {
+	set global_list(tensor_flipx) 0
+    }
+
+    if { $flipy !=0 } {
+	set global_list(tensor_flipy) 1
+    } else {
+	set global_list(tensor_flipy) 0
+    }
+
+    if { $flipz !=0 } {
+	set global_list(tensor_flipz) 1
+    } else {
+	set global_list(tensor_flipz) 0
+    }
+}
+
+
+
+itcl::body mpjtensorutility::GetOutputImage { index } {
+
+    if { $index < 0 || $index > 4 } {
+	set index 0
+    }
+
+    set img [ lindex $global_list(result_list) $index ]
+    return [ $img GetThisPointer ]
+}
+
+#-------------------------------------------------------------------------------------------
+#  Main function for stand-alone execution
+# ------------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    puts "\n[ file rootname $argv0 ] is not a stand-alone program.\n"
+    exit
+}
+
+
+# public method UpdatePosition { args }
+#eval "$parent configure -mousecallback \"$this UpdatePosition\"
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjvesselanalysis.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjvesselanalysis.tcl
new file mode 100644
index 0000000..f6cd0ed
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjvesselanalysis.tcl
@@ -0,0 +1,3351 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package provide mpjvesselanalysis 1.3
+
+package require  Itcl 3.2
+package require  Iwidgets 4.0
+
+package require  pxitcllistselector 1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitclbaseimageviewer 1.0
+
+package require  vtkmpjcontrib 1.1
+package require  mpjguilookuptable 1.0
+
+itcl::class mpjvesselanalysis {
+
+    inherit pxitclbaseimagecontrol
+    
+    #-----------------------------------
+    # construction and descruction
+    #-----------------------------------
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } { InitializeControl }
+    
+    destructor { }
+
+    #-----------------------------------
+    # common variables
+    #-----------------------------------
+
+    #-----------------------------------
+    # global variables
+    #-----------------------------------
+    private variable widget_list
+    private variable global_list
+    
+    #-----------------------------------
+    # initialization methods
+    #-----------------------------------
+    public method Initialize { inpwidg }
+    public method InitializeControl { }
+    public method DismissWindow { }
+      
+    #-----------------------------------
+    # diffusion series input/output
+    #-----------------------------------
+    public method LoadMask { fname }
+    public method LoadTensor { fname }
+    public method LoadEigenvalues { fname } 
+    public method LoadEigenvectors { fname }
+    public method ComputeResults { }
+    public method SaveAllResults { }
+    public method SaveResult { index }
+    public method ClearAllResults { }
+    public method DisplayResult { index }
+    public method ClearDisplay { }
+    public method SetResultPreffix { preffix }
+    public method GetResultPreffix { } 
+    public method SetCurrentDirectory { fname } 
+    public method SaveStatistics { fname }
+    
+    #-----------------------------------
+    # interface creation methods
+    #-----------------------------------
+    private method CreateDialogs { base }
+    private method CreateStatisticsControl { base }
+    private method CreateTransformControl { base }
+    private method CreateResultsControl { base }
+    private method CreateEigenControl { base }
+    private method CreateTensorControl { base }
+    private method CreateVesselControl { base }
+    private method CreateDisplayControl { base }
+    private method CreateEigenDisplayControl { base }
+    private method CreateTensorDisplayControl { base }
+    private method CreateResultDisplayControl { base }
+    private method CreateDirectionDisplayControl { base }
+    private method CreateDisplayTypeMenu { menubase }
+    private method CreateDisplayModeMenu { menubase }
+    private method CreateDisplayTransformMenu { menubase }
+    private method CreateDisplayColorbarMenu { menubase }
+    private method CreateMenu { mb }
+    private method Clone { }
+    public method AddToMenuButton { mb args }    
+ 
+    private method loadmask { }
+    private method loadtensor { }
+    private method loadeigenval { }
+    private method loadeigenvec { }
+    private method displayresult { }
+    private method saveresult { }
+    private method toggleresult { }
+    private method saveallresults { }
+    private method savestatistics { }
+ 
+    private method mask_autochanged_cb { }
+    private method eigen_autochanged_cb { }
+
+    private method initialize_glyphs { }
+    private method input_updateinfo { index }    
+
+    private method vessel_intensity_cb { }
+
+    private method tensor_ordering_cb { }
+    private method view_mode_cb { } 
+    private method view_eigen_filter_cb { }
+    private method view_eigen_glyph_cb { }
+    private method view_eigen_maxscale_cb { }
+    private method view_eigen_fromto_cb { }
+    private method view_eigen_cmapcopy_cb { }
+    private method view_eigen_cmapcopybtn_cb { }
+    private method view_eigen_cmapresetbtn_cb { }
+    private method view_eigen_cmaploadbtn_cb { }
+    private method view_eigen_cmapsavebtn_cb { }
+    private method view_tensor_filter_cb { }
+    private method view_tensor_glyph_cb { }
+    private method view_tensor_fromto_cb { }
+    private method view_tensor_maxscale_cb { }
+    private method view_tensor_cmapcopy_cb { }
+    private method view_tensor_cmapcopybtn_cb { }
+    private method view_tensor_cmapresetbtn_cb { }
+    private method view_tensor_cmaploadbtn_cb { }
+    private method view_tensor_cmapsavebtn_cb { }
+    private method view_direction_filter_cb { }
+    private method view_direction_scheme_cb { }
+    private method view_direction_update_cb { }
+    private method view_colorbar_cb { } 
+    private method view_update_display_cb { }
+    private method view_results_colormap_cb { }
+    private method view_clear_display { }
+    private method view_update_display { }
+    private method view_type_toggle_slow_eigenvector { }
+    private method view_type_toggle_med_eigenvector { }
+    private method view_type_toggle_fast_eigenvector { }
+    private method view_type_toggle_tensor { }
+    private method view_type_toggle_colorbar { }
+    private method view_extract_roi { exts image } 
+    private method view_compute_roi_extents { orient dim levels }
+    private method view_create_eigenvector_glyph { index vectors scalar glyph where }
+    private method view_create_eigenvector { index title }    
+    private method view_create_tensor_glyph { tensor scalar glyph where }
+    private method view_create_tensor { }
+    private method view_create_colorbar { }
+
+    private method result_clear { start end }
+    private method result_createmask { }
+    private method result_createeigen { }
+    private method result_createmaps { }
+    private method result_rotatetensor { }
+    private method result_add_stat { title fmt tag results }
+    private method result_statistics { image mask title } 
+}  
+
+#-------------------------------------------------------------------------------------------
+#  Close window 
+# -------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::DismissWindow { } {
+    
+    set TENSOR 0
+    set MASK 1
+
+    set ok "yes"
+    
+    set tensorsz [ [ lindex $global_list(result_list) $TENSOR ] GetImageSize ]
+    set masksz [ [ lindex $global_list(result_list) $MASK ] GetImageSize ]
+
+    if { [expr ($tensorsz > 1) || ($masksz > 1) ] } {
+	
+	set ok [ tk_messageBox -type yesnocancel -default no \
+		     -parent $basewidget -title "Think again ..." \
+		     -message "Unload all images from memory?" -icon question  ]
+    }
+    
+    if { $ok == "yes" } {	
+	
+	$this view_clear_display
+	$this ClearAllResults
+	
+	$this SetTitle $global_list(appname)
+	
+	set global_list(mask_fname) ""
+	set global_list(tensor_fname) ""
+    }
+    
+    if { $ok != "cancel" } {
+	$this HideWindow
+    }
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Initialize tool
+# -------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::InitializeControl { } {
+
+    set appname "Vessel Analysis v1.0"
+    set aboutstring "(c) Marcel Jackowski 2006"
+
+    set global_list(appname) "Vessel Analysis"
+
+    # create image titles
+    set global_list(result_title) \
+	[ list \
+	      { "Hessian matrix"          "hessian" 1 } \
+	      { "Region of interest mask" "mask" 1 } \
+	      { "Eigenvalues"             "eigenval" 1 } \
+	      { "Eigenvectors"            "eigenvec" 1 } \
+	      { "Trace"                   "trace" 1 } \
+	      { "Vessel likelihood"       "tubular" 1 } \
+	      { "Plate likelihood"        "plate" 1 } \
+	      { "Blob likelihood"         "blob" 1 } ]
+
+    ## create empty images
+    foreach item $global_list(result_title) {
+ 	lappend result_list [ pxitclimage \#auto ]
+	set global_list(enable_list,[lindex $item 1]) 0
+    }
+    
+    set global_list(result_fpreffix) "preffix_"
+    set global_list(result_fdir) [ pwd ] 
+    set global_list(result_list) $result_list
+    
+    set global_list(mask_fname) ""
+    set global_list(mask_auto) 1
+    set global_list(mask_nreg) 1
+    set global_list(mask_negative) 0
+    
+    set global_list(tensor_fname) ""
+    set global_list(tensor_symm) 1
+    set global_list(tensor_ordering) 0
+    set global_list(tensor_flipx) 0
+    set global_list(tensor_flipy) 0
+    set global_list(tensor_flipz) 0
+    set global_list(tensor_rotation) 0
+    set global_list(tensor_rotx) 0.0
+    set global_list(tensor_roty) 0.0
+    set global_list(tensor_rotz) 0.0
+    
+    set global_list(vessel_alpha) 0.5
+    set global_list(vessel_beta) 0.5
+    set global_list(vessel_gamma) 0.25
+    set global_list(vessel_intensity) 1
+    set global_list(vessel_maxintensity) 100.0
+
+    set global_list(eigenval_fname) ""
+    set global_list(eigenvec_fname) ""
+    set global_list(eigen_auto) 1
+    set global_list(eigen_positive) 0
+    set global_list(eigen_sortbymagnitude) 0
+    set global_list(eigen_recompute) 1
+
+    set global_list(stat_overwrite) 1
+
+    set global_list(view_mode) "3-slice"
+    set global_list(view_mode_index) 3
+    set global_list(view_type_fast) 0
+    set global_list(view_type_medium) 0
+    set global_list(view_type_slow) 0
+    set global_list(view_type_tensor) 0
+    set global_list(view_type_colorbar) 0
+    set global_list(view_colorbar) "Eigenvectors"
+    set global_list(view_colorbar_label) "Results"
+    set global_list(view_eigen_to) 1.0
+    set global_list(view_eigen_from) 0.5
+    set global_list(view_eigen_between) 1
+    set global_list(view_eigen_maxscale) 1.0
+    set global_list(view_eigen_flip) 1
+    set global_list(view_eigen_cmapcopy) 0
+    set global_list(view_tensor_to) 1.0
+    set global_list(view_tensor_from) 0.5
+    set global_list(view_tensor_between) 1
+    set global_list(view_tensor_maxscale) 1.0
+    set global_list(view_tensor_scale) 1.0
+    set global_list(view_tensor_clampscale) 1
+    set global_list(view_tensor_cmapcopy) 0
+    set global_list(view_direction_satscale) 0.5
+    set global_list(view_direction_scaling) 1.0
+    set global_list(view_direction_numcolors) 256
+    set global_list(view_direction_mask) 1
+    set global_list(view_transparent) 1
+    set global_list(view_transpcolor) 0.0
+    
+    ## create actors for visualization
+    set global_list(actor_fast) [ list -1 -1 -1 -1 ]
+    set global_list(actor_med) [ list -1 -1 -1 -1 ]
+    set global_list(actor_slow) [ list -1 -1 -1 -1 ]
+    set global_list(actor_tensor) [ list -1 -1 -1 -1 ]
+    set global_list(actor_colorbar) -1
+
+    for { set i 0 } { $i < 3 } { incr i } { ## fast med slow
+	for { set j 0 } { $j < 4 } { incr j } { ## xy xz yz vol
+	    set global_list(vtk_eigen_glypher,$i,$j) [ vtkGlyph3D [ pxvtable::vnewobj ] ]
+	    set global_list(vtk_eigen_threshold,$i,$j) [ vtkThresholdPoints [ pxvtable::vnewobj ] ]
+	    set global_list(vtk_eigen_merge,$i,$j) [ vtkMergeFilter [ pxvtable::vnewobj ] ]
+	}
+    }
+    
+    for { set i 0 } { $i < 4 } { incr i } {
+	set global_list(vtk_tensor_glypher,$i) [ vtkTensorGlyph [ pxvtable::vnewobj ] ]
+	set global_list(vtk_tensor_threshold,$i) [ vtkThresholdPoints [ pxvtable::vnewobj ] ]
+	set global_list(vtk_tensor_merge,$i) [ vtkMergeFilter [ pxvtable::vnewobj ] ]
+    }
+    
+    initialize_glyphs
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create visualization glyphs
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::initialize_glyphs { } {
+
+    ## create line source
+    set line_src [ vtkLineSource [ pxvtable::vnewobj ] ]
+    $line_src SetPoint1 0.0 0 0
+    $line_src SetPoint2 2.0 0 0    
+
+    set line_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $line_xfrm Translate -1.0 0.0 0.0
+
+    set line [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $line SetInput [ $line_src GetOutput ]
+    $line SetTransform $line_xfrm
+    lappend global_list(glyph_list) $line 
+
+    $line_src Delete
+    $line_xfrm Delete
+    
+    # create tube source
+    set tube_src [ vtkCylinderSource [ pxvtable::vnewobj ] ]
+    $tube_src SetHeight 2.0
+    $tube_src SetRadius 0.35
+    $tube_src CappingOn
+    
+    set tube_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $tube_xfrm RotateZ -90.0
+    
+    set tube [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $tube SetInput [ $tube_src GetOutput ]
+    $tube SetTransform $tube_xfrm
+    lappend global_list(glyph_list) $tube
+    
+    $tube_src Delete
+    $tube_xfrm Delete
+    
+    ## create arrow source
+    set arrow_src [ vtkArrowSource [ pxvtable::vnewobj ] ]
+    $arrow_src SetTipLength 0.35
+    $arrow_src SetTipResolution 10
+    $arrow_src SetTipRadius 0.20
+    $arrow_src SetShaftResolution 10
+    $arrow_src SetShaftRadius 0.1
+
+    set arrow_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $arrow_xfrm Translate -1.0 0.0 0.0
+    $arrow_xfrm Scale 2.0 2.0 2.0
+
+    set arrow [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $arrow SetInput [ $arrow_src GetOutput ]
+    $arrow SetTransform $arrow_xfrm
+    lappend global_list(glyph_list) $arrow
+
+    $arrow_src Delete
+    $arrow_xfrm Delete
+    
+    ## create ellipsoid source
+    set ellipsoid_src [ vtkSphereSource [ pxvtable::vnewobj ] ]
+    set ellipsoid_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    #$ellipsoid_xfrm Scale -2.0 -2.0 2.0
+    
+    set ellipsoid [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $ellipsoid SetInput [ $ellipsoid_src GetOutput ]
+    $ellipsoid SetTransform $ellipsoid_xfrm
+    lappend global_list(glyph_list) $ellipsoid
+    
+    $ellipsoid_src Delete
+    $ellipsoid_xfrm Delete
+    
+    ## create cuboid source
+    set cuboid_src [ vtkCubeSource [ pxvtable::vnewobj ] ]
+    set cuboid_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    
+    set cuboid [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $cuboid SetInput [ $cuboid_src GetOutput ]
+    $cuboid SetTransform $cuboid_xfrm
+    lappend global_list(glyph_list) $cuboid
+    
+    $cuboid_src Delete
+    $cuboid_xfrm Delete
+
+    ## create sheet source
+    set sheet_src [ vtkCubeSource [ pxvtable::vnewobj ] ]
+    set sheet_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $sheet_xfrm Scale 1.0 1.0 0.0
+    
+    set sheet [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $sheet SetInput [ $sheet_src GetOutput ]
+    $sheet SetTransform $sheet_xfrm
+    lappend global_list(glyph_list) $sheet
+    
+    $sheet_src Delete
+    $sheet_xfrm Delete  
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in mask auto status
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::mask_autochanged_cb { } {
+    set state(0) disabled; set state(1) normal        
+    $widget_list(mask_load) buttonconfigure load -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_load) buttonconfigure disp -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_fname) configure -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_nreg) configure -state $state([expr 1 - $global_list(mask_auto)])
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in mask auto status
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::eigen_autochanged_cb { } {
+    set state(0) disabled; set state(1) normal        
+    $widget_list(eigenval_load) buttonconfigure load -state \
+	$state([expr 1 - $global_list(eigen_auto)])
+    $widget_list(eigenvec_load) buttonconfigure load -state \
+	$state([expr 1 - $global_list(eigen_auto)])    
+
+    if { $global_list(eigen_auto) == 0 } {
+	set global_list(mask_negative) 0
+    }
+
+    if { $global_list(eigen_auto) == 1 } {
+	set global_list(eigen_totalinput) 0
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in structure intensity
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::vessel_intensity_cb { } {
+    set index [ $widget_list(vessel_intensity) index [ $widget_list(vessel_intensity) get ] ]
+    set global_list(vessel_intensity) $index
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Update input information on title bar
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::input_updateinfo { index } {
+
+    set sel_input [ [ lindex $global_list(input_list) $index ] GetImage ]
+    set sel_fname [ lindex $global_list(input_fname) $index ]
+    
+    scan [ $sel_input GetDimensions ] "%d %d %d" dx dy dz	       
+    set nc [  $sel_input GetNumberOfScalarComponents ]
+    set name [ file tail [ file root $sel_fname ] ]
+    
+    set global_list(result_fpreffix) "${name}_"
+
+    $this SetTitle "$global_list(appname): $name (${dx}x${dy}x${dz}, $nc frames)"
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load mask
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::loadmask { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select mask" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadMask $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in mask image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::LoadMask { fname } {
+
+    set MASK 1     
+    set mask [ lindex $global_list(result_list) $MASK ]
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    $this SetFilterCallbacks $ana "Reading in mask image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    ## if mask not a unsigned char image, convert it
+    set scalar_type [ [ $ana GetOutput ] GetScalarType ]    
+
+    if { $scalar_type != 3 } {	
+	
+	set imcast [ vtkImageCast [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $imcast "Converting mask to unsigned char values..."
+	$imcast SetInput [ $ana GetOutput ]
+	$imcast SetOutputScalarTypeToUnsignedChar
+	$imcast ClampOverflowOn	
+	$imcast Update
+	
+	$mask ShallowCopyImage [ $imcast GetOutput ]
+	
+	$imcast Delete
+	
+    } else {
+	
+	$mask SetFromAnalyzeSource $ana
+    }
+   
+    ## determine range of values in mask
+    set range [ [ [ [ $mask GetImage ] GetPointData ] GetScalars ] GetRange ]
+
+    ## take the maximum range as the number of regions in mask
+    set global_list(mask_nreg) [ lindex $range 1 ]    
+    $widget_list(mask_nreg) configure -range [ list 1 $global_list(mask_nreg) ]
+    
+    set global_list(mask_fname) $fname
+
+    WatchOff
+
+    $ana Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in tensor component ordering
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::tensor_ordering_cb { } {
+    
+    ## current ordering
+    set global_list(tensor_ordering) [ $widget_list(tensor_ordering) index [ $widget_list(tensor_ordering) get ] ]   
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load tensor
+# -----------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::loadtensor { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select tensor" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadTensor $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in tensor image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::LoadTensor { fname } {
+
+    set TENSOR 0
+
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in tensor image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    $tensor SetFromAnalyzeSource $ana
+    
+    # determine coordinate transform
+    set or [ $ana GetOrientation ]
+    if { $or == 0 } {
+     	set global_list(tensor_flipx) 1
+     	set global_list(tensor_flipy) 1
+    } elseif { $or == 1 } {
+     	set global_list(tensor_flipx) 1
+    } 
+    
+    set nc [ [ $tensor GetImage ] GetNumberOfScalarComponents ]
+
+    set global_list(tensor_fname) $fname
+    set global_list(result_fpreffix) "[file root [file tail $fname] ]_"
+    set global_list(tensor_symm) [ expr $nc == 6 ]
+    
+    WatchOff
+    
+    $ana Delete
+    
+    $widget_list(computebtn) configure -state normal
+    $widget_list(menu_results) entryconfigure 0 -state normal
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load eigenvalues
+# -----------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::loadeigenval { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select eigenvalues" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadEigenvalues $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in eigenvalue image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::LoadEigenvalues { fname } {
+
+    set EIGENVALUES 2
+
+    set eigenval [ lindex $global_list(result_list) $EIGENVALUES ]
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in eigenvalue image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    $eigenval SetFromAnalyzeSource $ana
+    
+    # determine coordinate transform
+    #    set or [ $ana GetOrientation ]   
+    #    set nc [ [ $tensor GetImage ] GetNumberOfScalarComponents ]
+    
+    set global_list(eigenval_fname) $fname
+    set global_list(result_fpreffix) "[file root [file tail $fname] ]_"
+
+    #    set global_list(tensor_symm) [ expr $nc == 6 ]
+    
+    WatchOff
+    
+    $ana Delete
+    
+    $widget_list(eigenval_fname) configure -state normal
+
+    #    $widget_list(computebtn) configure -state normal
+    #    $widget_list(menu_results) entryconfigure 0 -state normal
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load eigenvectors
+# -----------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::loadeigenvec { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select eigenvectors" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadEigenvectors $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in eigenvalue image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::LoadEigenvectors { fname } {
+
+    set EIGENVECTORS 3
+
+    set eigenvec [ lindex $global_list(result_list) $EIGENVECTORS ]
+    
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in eigenvector image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    $eigenvec SetFromAnalyzeSource $ana
+    
+    # determine coordinate transform
+    #    set or [ $ana GetOrientation ]   
+    #    set nc [ [ $tensor GetImage ] GetNumberOfScalarComponents ]
+    
+    set global_list(eigenvec_fname) $fname
+    set global_list(result_fpreffix) "[file root [file tail $fname] ]_"
+    
+    WatchOff
+    
+    $ana Delete
+    
+    $widget_list(eigenvec_fname) configure -state normal
+
+    #    $widget_list(computebtn) configure -state normal
+    #    $widget_list(menu_results) entryconfigure 0 -state normal
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Set result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::SetResultPreffix { preffix } {
+    set global_list(result_fpreffix) $preffix
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Get result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::GetResultPreffix { } {
+    return $global_list(result_fpreffix)
+}
+
+itcl::body mpjvesselanalysis::SetCurrentDirectory { fname } {
+    set global_list(result_fdir) $fname
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Clear all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::ClearAllResults { } {
+    
+    foreach result $global_list(result_list) {
+	$result Clear
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::SaveAllResults { } {
+
+    foreach result $global_list(result_list) title $global_list(result_title) {
+	
+	set fname $global_list(result_fpreffix)
+	set fname "$fname[ lindex $title 1 ]"
+	
+	$result Save $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save single result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::SaveResult { index } {        
+
+    set fname $global_list(result_fpreffix)
+    set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]"
+
+    [lindex $global_list(result_list) $index] Save $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::saveallresults { } {
+
+    ## browse for directory
+    set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+
+    if { $fdir != "" } {
+	
+	set global_list(result_fdir) $fdir
+	
+	foreach result $global_list(result_list) title $global_list(result_title) {
+	    
+	    set fname $global_list(result_fpreffix)
+	    set fname "$fname[ lindex $title 1 ]"
+	    
+	    $result Save [ file join $fdir $fname ]
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::saveresult { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(result_list) getcurselection ]
+    
+    if { $sel_item != "" } { 
+
+	## browse for directory
+	set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+	
+	if { $fdir != "" } {
+	    
+	    set global_list(result_fdir) $fdir
+	    
+	    foreach item $sel_item {
+		
+		set index [ $widget_list(result_list) index $item ]
+		set result [ lindex $global_list(result_list) $index ]
+		
+		set fname $global_list(result_fpreffix)
+		set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]"
+		
+		$result Save [ file join $fdir $fname ]
+	    }
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::DisplayResult { index } {
+    $parent SetImageFromObject \
+	[ [ lindex $global_list(result_list) $index ] GetThisPointer ] $this
+    $parent ShowWindow
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::displayresult { } {
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+	    
+    if { $sel_item != "" } {
+	set index [ $widget_list(result_list) index [ lindex $sel_item 0 ] ]
+	set result [ lindex $global_list(result_list) $index ]
+
+	set range [ [ [ [ $result GetImage ] GetPointData ] GetScalars ] GetRange ]
+	$widget_list(view_resultluk) SetTableRange [ lindex $range 0 ] [ lindex $range 1 ]
+	#	$widget_list(view_resultluk) Update
+
+	$this DisplayResult $index
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: toggle result computation on/off
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::toggleresult { } {
+   
+    set color(0) \#dcdcdc
+    set color(1) black
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+
+    if { $sel_item != "" } {
+
+	set index [ $widget_list(result_list) index [ lindex $sel_item 0 ] ]
+
+	if { $index > 4 } {
+	    set enable [expr 1 - [ lindex [ lindex $global_list(result_title) $index ] 2 ] ]
+	    
+	    $widget_list(result_list) itemconfigure $index -foreground $color($enable)
+	    
+	    set item [ lindex $global_list(result_title) $index ]
+	    set new_item [ lreplace $item 2 2 $enable ]
+	    
+	    set global_list(result_title) [ lreplace $global_list(result_title) \
+						$index $index $new_item ]
+	}
+    }
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::SaveStatistics { fname } {
+      $widget_list(stat_text) export $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::savestatistics { } {
+
+    set statfname $global_list(result_fpreffix)
+    set initfname "${statfname}stat"
+    set initfname [ file join $global_list(result_fdir) $initfname ]
+
+    ## browse for filename
+    set fname  [tk_getSaveFile -title "Save statistics"\
+		    -filetypes {{"Text" {.txt*}}} \
+		    -parent $basewidget \
+		    -defaultextension ".txt" \
+		    -initialfile $initfname ]  
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+    
+    $this SaveStatistics $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: add statistics line
+#-------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::result_add_stat { title fmt tag results } {   
+    
+    set line " $title |"
+    
+    foreach item $results {
+	set fitem [ format $fmt $item ] 
+	set line "$line $fitem |"
+    }
+
+    $widget_list(stat_text) insert end " $line\n" $tag
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Compute statistics
+#-------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::result_statistics { image mask title } {
+    
+    ## compute statitics from given image and mask
+    set stat [ vtkmpjImageStatistics [ pxvtable::vnewobj ] ]
+    $stat SetMask $mask
+    $stat SetInput $image
+    $stat SetNumberOfRegions $global_list(mask_nreg)
+    $stat Update
+    
+    ## write header information
+    set border [ string repeat "----------+" $global_list(mask_nreg) ] 
+    
+    set regions ""
+    for { set i 1 } { $i <= $global_list(mask_nreg) } { incr i } {	
+	set regions "$regions|Region \#[format %2d $i]"	
+    }
+
+    $widget_list(stat_text) insert \
+	end "-----------------------+$border\n" even
+    $widget_list(stat_text) insert \
+	end " $title $regions|\n" odd
+    $widget_list(stat_text) insert \
+	end "-----------------------+$border\n" even
+
+    ## Write out stats
+    set textlist [  $widget_list(stat_text) component text ]
+    $textlist tag configure even -background "\#d0ffd0"
+
+    set results ""
+    for { set i 0 } { $i < $global_list(mask_nreg) } { incr i } {	
+	lappend results [ $stat GetRegionMin $i ]
+    }    
+    result_add_stat " MINIMUM            " "%8.4f" odd $results
+    
+    set results ""
+    for { set i 0 } { $i < $global_list(mask_nreg) } { incr i } {	
+	lappend results [ $stat GetRegionMax $i ]
+    }    
+    result_add_stat " MAXIMUM            " "%8.4f" even $results
+    
+    set results ""
+    for { set i 0 } { $i < $global_list(mask_nreg) } { incr i } {	
+	lappend results [ $stat GetRegionMean $i ]
+    }    
+    result_add_stat " MEAN               " "%8.4f" odd $results
+    
+    set results ""
+    for { set i 0 } { $i < $global_list(mask_nreg) } { incr i } {	
+	lappend results [ $stat GetRegionVariance $i ]
+    }    
+    result_add_stat " VARIANCE           " "%8.4f" even $results
+    
+    $widget_list(stat_text) insert end "\n" odd 
+
+    set results ""
+    for { set i 0 } { $i < $global_list(mask_nreg) } { incr i } {	
+	lappend results [ $stat GetRegionVoxelCount $i ]
+    }    
+
+    $stat Delete
+
+    return $results
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::result_clear { start end } {
+    
+    for { set i $start } { $i <= $end } { incr i } {
+	
+	set title [ lindex [ lindex $global_list(result_title) $i ] 0 ]	    
+	
+	if { $title == "Region of interest mask" } {
+	    if { $global_list(mask_auto) } {
+		[ lindex $global_list(result_list) $i ] Clear
+	    }
+	} else { 
+	    [ lindex $global_list(result_list) $i ] Clear
+	}
+
+    }
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Rotate tensor
+#-------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::result_rotatetensor { } {
+
+    set TENSOR 0
+    
+    ## get tensor image
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    
+    ## rotate tensor
+    set tensor_xform [ vtkmpjImageTensorTransform [ pxvtable::vnewobj ] ]
+    $tensor_xform SetInput [ $tensor GetImage ]
+    $tensor_xform SetRotation $global_list(tensor_rotx) $global_list(tensor_roty) $global_list(tensor_rotz) 
+    $this SetFilterCallbacks $tensor_xform "Transforming tensor..."
+    
+    # rotate tensor
+    $tensor_xform Update
+    
+    # replace tensor
+    $tensor ShallowCopyImage [ $tensor_xform GetOutput ]
+    
+    $tensor_xform Delete
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create mask image
+#-------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::result_createmask { }  {
+
+    set TENSOR 0
+    set MASK 1
+    set EIGENVALUES 2
+    
+    ## get tensor image    
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    
+    set mask [ lindex $global_list(result_list) $MASK ]    
+    $mask CopyImageHeader \
+	[ [ lindex $global_list(result_list) $TENSOR ] GetImageHeader ]
+
+    ## create sigma
+    set maskimg [ vtkImageData [ pxvtable::vnewobj ] ]
+    $maskimg CopyStructure [ $tensor GetImage ]   
+    $maskimg SetScalarTypeToUnsignedChar
+    $maskimg SetNumberOfScalarComponents 1
+    $maskimg AllocateScalars
+    [ [ $maskimg GetPointData ] GetScalars ] \
+	FillComponent 0 1
+    
+    ## save mask
+    $mask ShallowCopyImage $maskimg
+    
+    $maskimg Delete    
+    
+    update idletasks
+    
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create eigensystem
+#-------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::result_createeigen { } {
+
+    set TENSOR 0
+    set MASK 1
+    set EIGENVALUES 2
+    set EIGENVECTORS 3
+
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set eigenvalues [ lindex $global_list(result_list) $EIGENVALUES ]
+    set eigenvectors [ lindex $global_list(result_list) $EIGENVECTORS ]
+    
+    $eigenvalues CopyImageHeader [ $tensor GetImageHeader ]
+    $eigenvectors CopyImageHeader [ $tensor GetImageHeader ]
+
+    if { [expr ([ $mask GetImageSize ] == 1) || ([ $tensor GetImageSize ] == 1) ] } {
+	return 0
+    }
+
+    ## compute eigenvalues and eigenvectors
+    set eigen [ vtkmpjImageTensorEigenAnalysis [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $eigen "Computing eigenvalues and eigenvectors..."
+    $eigen SetInput [ $tensor GetImage ]
+    $eigen SetOrdering $global_list(tensor_ordering)
+    $eigen SetMask [ $mask GetImage ]
+    $eigen SetOutputTypeToBoth    
+    $eigen MaskNegativeOn
+    $eigen SetMaskNegativeInValue 0
+    $eigen SetMaskNegativeOutValue 255
+    $eigen SetOutputAbsoluteEigenvalues 1
+#$global_list(eigen_positive)
+    $eigen SetSortByMagnitude 0
+#$global_list(eigen_sortbymagnitude)
+    $eigen FixZeroEigenvaluesOn
+    $eigen Update
+    
+    ## extract eigenvalues
+    set fex [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $fex "Extracting eigenvalues..."
+    $fex SetInput [ $eigen GetOutput ]
+    $fex SetStartFrame 0
+    $fex SetEndFrame 2
+    $fex Update
+
+    $eigenvalues ShallowCopyImage [ $fex GetOutput ]
+    
+    $fex Delete
+    
+    ## extract eigenvectors
+    set fex [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $fex "Extracting eigenvectors..."
+    $fex SetInput [ $eigen GetOutput ]
+    $fex SetStartFrame 3
+    $fex SetEndFrame 11
+    $fex Update
+    
+    #$rad Delete
+    $eigenvectors ShallowCopyImage [ $fex GetOutput ]
+
+    $fex Delete
+
+    $eigen Delete
+
+    update idletasks
+
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create maps
+#-------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::result_createmaps { } {
+    
+    set TENSOR 0
+    set MASK 1
+    set EIGENVALUES 2
+    set EIGENVECTORS 3
+    set TRACE 4
+    set TUBE 5
+    set PLATE 6
+    set BLOB 7
+
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set eigenvalues [ lindex $global_list(result_list) $EIGENVALUES ]
+    set eigenvectors [ lindex $global_list(result_list) $EIGENVECTORS ]
+
+    set tracemap [ lindex $global_list(result_list) $TRACE ]
+    $tracemap CopyImageHeader [ $tensor GetImageHeader ]
+    
+    set tubemap [ lindex $global_list(result_list) $TUBE ]
+    $tubemap CopyImageHeader [ $tensor GetImageHeader ]
+   
+    set platemap [ lindex $global_list(result_list) $PLATE ]
+    $platemap CopyImageHeader [ $tensor GetImageHeader ]
+
+    set blobmap [ lindex $global_list(result_list) $BLOB ]
+    $blobmap CopyImageHeader [ $tensor GetImageHeader ]
+
+    set mapmask [ pxitclimage \#auto ]
+    $mapmask CopyImageHeader [ $tensor GetImageHeader ]
+    
+    $mapmask ShallowCopyImage [ $mask GetImage ]
+    
+    ## compute invariants
+    set invar [ vtkmpjImageTensorInvariants [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $invar "Computing hessian maps..."
+    $invar SetInput [ $eigenvalues GetImage ]
+    $invar SetMask [ $mapmask GetImage ]
+    $invar Update
+
+    ## clear textbox
+    if { $global_list(stat_overwrite) } { 
+	$widget_list(stat_text) delete 1.0 end
+    }
+    
+    set results 0
+
+    set enable [ lindex [ lindex $global_list(result_title) $TRACE ] 2 ]
+    if { $enable } {
+	################### extract Trace 
+	set trace [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+	$this ShowProgressVal "Extracting maps..." [expr 2.0 / 6]
+	$trace SetInput [ $invar GetOutput ]
+	$trace SetFrameNumber 3
+	$trace Update
+	
+	$tracemap ShallowCopyImage [ $trace GetOutput ]
+	$trace Delete
+	
+	set results [ result_statistics [ $tracemap GetImage ] [ $mapmask GetImage ] "TRACE" ]
+    }
+    
+    set enable1 [ lindex [ lindex $global_list(result_title) $TUBE ] 2 ]
+    set enable2 [ lindex [ lindex $global_list(result_title) $PLATE ] 2 ]
+    set enable3 [ lindex [ lindex $global_list(result_title) $BLOB ] 2 ]
+    
+    if { [expr $enable1 || $enable2 || $enable3 ] } {
+	
+	##################### compute vessel indices #######################
+	set vessel [ vtkmpjImageVesselEnhancement [ pxvtable::vnewobj ] ]
+	$this ShowProgressVal "Extracting maps..." [expr 3.0 / 6]
+	$vessel SetInput [ $tensor GetImage ]
+	$vessel SetMask [ $mapmask GetImage ]
+	$vessel SetAlpha $global_list(vessel_alpha)
+	$vessel SetBeta $global_list(vessel_beta)
+	$vessel SetGamma \
+	    [ expr $global_list(vessel_gamma) * $global_list(vessel_maxintensity) ]
+	$vessel SetStructureTypeToAll
+	$vessel SetBrightStructure [ expr 1 - $global_list(vessel_intensity) ]
+	$vessel Update
+
+	if { $enable1 } {
+	    set tube [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+	    $this ShowProgressVal "Extracting maps..." [expr 4.0 / 6]
+	    $tube SetInput [ $vessel GetOutput ]
+	    $tube SetFrameNumber 0
+	    $tube Update  
+
+	    $tubemap ShallowCopyImage [ $tube GetOutput ]
+	    $tube Delete
+	    
+	    set results [ result_statistics [ $tubemap GetImage ] [ $mapmask GetImage ] "TUBE LIKELIHOOD   "]
+	}
+
+	if { $enable2 } {
+	    set plate [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+	    $this ShowProgressVal "Extracting maps..." [expr 5.0 / 6]
+	    $plate SetInput [ $vessel GetOutput ]
+	    $plate SetFrameNumber 1
+	    $plate Update  
+	    
+	    $platemap ShallowCopyImage [ $plate GetOutput ]
+	    $plate Delete
+	    
+	    set results [ result_statistics [ $platemap GetImage ] [ $mapmask GetImage ] "PLATE LIKELIHOOD   "]
+	}
+
+	if { $enable3 } {
+	    set blob [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+	    $this ShowProgressVal "Extracting maps..." [expr 6.0 / 6]
+	    $blob SetInput [ $vessel GetOutput ]
+	    $blob SetFrameNumber 2
+	    $blob Update  
+	    
+	    $blobmap ShallowCopyImage [ $blob GetOutput ]
+	    $blob Delete
+	    
+	    set results [ result_statistics [ $blobmap GetImage ] [ $mapmask GetImage ] "BLOB LIKELIHOOD   "]
+	}
+
+	$vessel Delete
+	
+    }
+    
+    ##################### Voxel count ###############################
+    set border [ string repeat "==========+" $global_list(mask_nreg) ] 
+    $widget_list(stat_text) insert end "=======================+$border\n" even
+    
+    result_add_stat " TOTAL VOXELS       " "%8d" odd $results  
+
+    $invar Delete
+
+    $mapmask Clear
+    itcl::delete object $mapmask
+
+    $this ShowProgressVal "Done." 0
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Compute results
+# -----------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::ComputeResults { } {
+    
+    set MASK 1
+    set TRACE 4
+    set TUBE 5
+
+    WatchOn
+    
+    ## clear display
+    view_clear_display
+    
+    ## clear results
+    if { $global_list(eigen_recompute) } {
+	if { $global_list(eigen_auto) == 1 } { 
+	    result_clear $MASK [ expr [ llength $global_list(result_list) ] -1 ]
+	} else {
+	    result_clear $TRACE [ expr [ llength $global_list(result_list) ] -1 ]
+	}
+    } else {
+	result_clear $TRACE [ expr [ llength $global_list(result_list) ] -1 ]
+    }
+
+    $widget_list(notebook) view "Statistics"; update
+
+    ## create mask if not loaded in
+    if { $global_list(mask_auto) } {
+	
+	set result [ result_createmask ]
+
+	if { $result == 0 } {
+	    WatchOff; return
+	}
+    }
+
+    if { $global_list(eigen_auto) == 1 } {
+
+	if { $global_list(eigen_recompute) } {
+
+	    ## compute eigevalues and eigenvectors
+	    set result [ result_createeigen ]
+	    
+	    if { $result == 0 } {
+		WatchOff; return
+	    }
+	}
+    }
+
+    ## create maps
+    result_createmaps
+    
+    # send currently selected result to parent
+    $widget_list(result_list) selection set $TUBE $TUBE
+    
+    set tubemap [ lindex $global_list(result_list) $TUBE ]
+    $parent SetImageFromObject [ $tubemap  GetThisPointer ] $this
+
+    set range [ [ [ [ $tubemap GetImage ] GetPointData ] GetScalars ] GetRange ]
+    $widget_list(view_resultluk) SetTableRange [ lindex $range 0 ] [ lindex $range 1 ]
+    $widget_list(view_resultluk) Update
+    
+    ## update display
+    view_update_display
+
+    WatchOff
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear display
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_clear_display { } {
+    
+    ## remove eigenvectors and tensors
+    foreach item "slow med fast tensor" {
+	foreach actor $global_list(actor_${item}) {	    
+	    if { $actor != "-1" } {
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_${item}) [list -1 -1 -1 -1 ]	
+    }
+    
+    ## remove colorbars
+    set actor $global_list(actor_colorbar)
+    if { $actor != "-1" } {
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+	$actor Delete	   
+	set global_list(actor_colorbar) -1
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Update display
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_update_display { } {
+
+    if { $global_list(view_type_fast) } {	
+	view_create_eigenvector fast 0
+    }
+    
+    if { $global_list(view_type_medium) } {	
+	view_create_eigenvector med 1
+    }
+    
+    if { $global_list(view_type_slow) } { 
+	view_create_eigenvector slow 2
+    }    
+    
+    if { $global_list(view_type_tensor) } {
+	view_create_tensor 
+    }
+    
+    if { $global_list(view_type_colorbar) } {
+	view_create_colorbar
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Compute ROI extents
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_compute_roi_extents { orient dim levels } {
+   
+    set x0(0) 0; set x0(1) 0; set x0(2) 0;
+    set x1(0) [expr [lindex $dim 0] -1]
+    set x1(1) [expr [lindex $dim 1] -1]
+    set x1(2) [expr [lindex $dim 2] -1]
+    
+    if { $orient < 3 } {
+
+	## set up slice geometry
+	for { set i 0 } { $i < 3 } { incr i } {
+	    if { $i == $orient } {
+		set x0($i) [lindex $levels $i]
+		set x1($i) [lindex $levels $i]
+	    }
+	}
+    }
+    
+    return "$x0(0) $x0(1) $x0(2) $x1(0) $x1(1) $x1(2)"
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Extract ROI given image and computed extents
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_extract_roi { exts image } {
+    
+    set dim [ [ $image GetImage ] GetDimensions ]
+    set spac [ [ $image GetImage ] GetSpacing ]
+    set orig [ [ $image GetImage ] GetOrigin ]
+    set ospac "1 1 1"
+    
+    set x0(0) [lindex $exts 0]; set x0(1) [lindex $exts 1]; set x0(2) [lindex $exts 2];
+    set x1(0) [lindex $exts 3]; set x1(1) [lindex $exts 4]; set x1(2) [lindex $exts 5];
+    
+    ## determine correct origin and spacing
+    for { set i 0 } { $i <= 2 } { incr i } {	
+ 	if { $x1($i) < $x0($i) } { set x1($i) [ expr $x0($i) +1 ] }
+ 	set dx [ lindex $ospac $i ]
+ 	if { $dx < 1 } { set dx 1 } elseif { $dx > 10 } { set dx 10 }	
+ 	set origin($i)  [ expr [lindex $orig $i ] + $x0($i) * [ lindex $spac $i ]]
+ 	set spacing($i) [ expr [lindex $spac $i ] * $dx ]
+ 	set ext($i)     [ expr ($x1($i)-$x0($i))/$dx ]
+    }
+
+    set identity [ vtkIdentityTransform [ pxvtable::vnewobj ] ]
+
+    ## extract roi
+    set roi [ vtkbisImageReslice [ pxvtable::vnewobj ] ]
+    $roi SetInput [ $image GetImage ]
+    $roi SetResliceTransform $identity
+    $roi SetOutputSpacing $spacing(0) $spacing(1) $spacing(2)
+    $roi SetOutputOrigin $origin(0)  $origin(1)  $origin(2)    
+    $roi SetOutputExtent 0 $ext(0) 0 $ext(1) 0 $ext(2)
+    $roi SetInterpolationMode 0 
+    $roi Update
+
+    $identity Delete
+
+    return $roi
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create tensor glyphs
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_create_tensor_glyph { tensor scalar glyph where } {
+
+    ## convert image into tensor attribute
+    set imtoten [ vtkmpjImageToTensors [ pxvtable::vnewobj ] ]
+    $imtoten SetInput $tensor
+    $imtoten SetSymmetricTensor $global_list(tensor_symm)
+#    $imtoten SetFlipX $global_list(tensor_flipx)
+#    $imtoten SetFlipY $global_list(tensor_flipy)
+#    $imtoten SetFlipZ $global_list(tensor_flipz)
+    $imtoten Update
+    
+    ## combine geometry information
+    set merge $global_list(vtk_tensor_merge,$where)
+    $merge SetGeometry $tensor
+    $merge SetScalars $scalar
+    $merge SetTensors [ $imtoten GetOutput ]
+    $merge Update
+    
+    $imtoten Delete
+    
+    ## threshold resulting dataset 
+    set thresh $global_list(vtk_tensor_threshold,$where)
+    $thresh SetInput [ $merge GetOutput ]
+    if { $global_list(view_tensor_between) == 1 } {
+	$thresh ThresholdBetween $global_list(view_tensor_from) $global_list(view_tensor_to)
+    } else {
+	$thresh ThresholdByUpper $global_list(view_tensor_from)
+    }
+    $thresh Update
+
+    ## create glyph field
+    set glypher $global_list(vtk_tensor_glypher,$where)
+    $glypher SetInput [ $thresh GetOutput ]
+    $glypher SetSource [ $glyph GetOutput ]
+    $glypher SymmetricOn
+    #$glypher ExtractEigenvaluesOff
+    $glypher SetScaleFactor $global_list(view_tensor_scale)
+    $glypher SetClampScaling $global_list(view_tensor_clampscale)
+    $glypher SetMaxScaleFactor $global_list(view_tensor_maxscale)
+    $glypher Update
+
+    ## compute surface normals
+    set glyphNormals [ vtkPolyDataNormals [ pxvtable::vnewobj ] ]
+    $glyphNormals SetInput [ $glypher GetOutput ]
+
+    ## set up glyph mapper
+    set glyphMapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    $glyphMapper SetInput [ $glyphNormals GetOutput ]
+    $glyphMapper SetLookupTable [ $widget_list(view_tensorluk) GetLookupTable ]
+    $glyphMapper UseLookupTableScalarRangeOn
+    $glyphMapper SetColorModeToMapScalars
+    $glyphMapper ScalarVisibilityOn
+
+    $glyphNormals Delete
+
+    ## create glyph actor
+    set glyphActor [ vtkActor [ pxvtable::vnewobj ] ]
+    $glyphActor SetMapper $glyphMapper
+    
+    $glyphMapper Delete
+    
+    return $glyphActor
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create eigenvector glyphs
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_create_eigenvector_glyph { index vectors scalar glyph where } {
+
+    ## extract eigenvector subset 
+    set subset [ vtkmpjFrameExtract [ pxvtable::vnewobj ] ]
+    $subset SetInput $vectors
+    $subset SetStartFrame [expr $index * 3]
+    $subset SetEndFrame [expr $index * 3 + 2]
+    $subset Update
+    
+    ## convert image into vector attribute
+    set imtovec [ vtkmpjImageToVectors [ pxvtable::vnewobj ] ]
+    $imtovec SetInput [ $subset GetOutput ]
+    if { $global_list(view_eigen_flip) } {
+	$imtovec SetFlipX $global_list(tensor_flipx)
+	$imtovec SetFlipY $global_list(tensor_flipy)
+	$imtovec SetFlipZ $global_list(tensor_flipz)
+    }
+    $imtovec Update
+
+    $subset Delete
+    
+    ## combine geometry information
+    set merge $global_list(vtk_eigen_merge,$index,$where)
+    $merge SetGeometry $vectors
+    $merge SetScalars $scalar
+    $merge SetVectors [ $imtovec GetOutput ]
+    $merge Update
+    
+    $imtovec Delete
+    
+    ## threshold resulting dataset 
+    set thresh $global_list(vtk_eigen_threshold,$index,$where)
+    $thresh SetInput [ $merge GetOutput ]
+    if { $global_list(view_eigen_between) == 1 } {
+	$thresh ThresholdBetween $global_list(view_eigen_from) $global_list(view_eigen_to)
+    } else {
+	$thresh ThresholdByUpper $global_list(view_eigen_from)
+    }
+    $thresh Update
+    
+    ## create glypher field   
+    set glypher $global_list(vtk_eigen_glypher,$index,$where)
+    $glypher SetInput [ $thresh GetOutput ]
+    $glypher SetSource [ $glyph GetOutput ]
+    $glypher ScalingOn
+    $glypher ClampingOn
+    $glypher SetScaleFactor $global_list(view_eigen_maxscale)
+    $glypher SetScaleModeToDataScalingOff
+    $glypher SetColorModeToColorByScalar
+    $glypher SetVectorModeToUseVector
+    $glypher Update
+
+    ## set up glyph mapper
+    set glyphMapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    $glyphMapper SetInput [ $glypher GetOutput ]
+    $glyphMapper SetLookupTable [ $widget_list(view_vectorluk) GetLookupTable ]
+    $glyphMapper UseLookupTableScalarRangeOn
+    $glyphMapper SetColorModeToMapScalars
+    $glyphMapper ScalarVisibilityOn
+
+    ## create glyph actor
+    set glyphActor [ vtkActor [ pxvtable::vnewobj ] ]
+    $glyphActor SetMapper $glyphMapper
+    
+    $glyphMapper Delete
+    
+    return $glyphActor
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off fast eigenvector visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_type_toggle_fast_eigenvector { } {                
+    
+    if { $global_list(view_type_fast) } {	
+	view_create_eigenvector fast 0
+    } else {
+	foreach actor $global_list(actor_fast) {	    
+	    if { $actor != "-1" } {
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_fast) [ list -1 -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off medium-speed eigenvector visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_type_toggle_med_eigenvector { } {                
+
+    if { $global_list(view_type_medium) } {	
+	view_create_eigenvector med 1
+    } else {
+	foreach actor $global_list(actor_med) {	    
+	    if { $actor != "-1" } {
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_med) [ list -1 -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off medium-speed eigenvector visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_type_toggle_slow_eigenvector { } {                
+
+    if { $global_list(view_type_slow) } {	
+	view_create_eigenvector slow 2
+    } else { 
+	foreach actor $global_list(actor_slow) {	    
+	    if { $actor != "-1" } {
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_slow) [list -1 -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off tensor visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_type_toggle_tensor { } {                
+
+    if { $global_list(view_type_tensor) } {	
+	view_create_tensor
+    } else { 
+	foreach actor $global_list(actor_tensor) {
+	    if { $actor != "-1" } {
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_tensor) [ list -1 -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off colorbar visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_type_toggle_colorbar { } {
+    
+    if { $global_list(view_type_colorbar) } {
+	view_create_colorbar
+    } else {
+	set actor $global_list(actor_colorbar)
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor
+	$actor Delete
+
+	set global_list(actor_colorbar) -1
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  View tensors
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_create_tensor { } {
+    
+    set TENSOR 0
+    set EIGENVECTORS 3
+
+    ## get tensor information
+    set tensor_image [ lindex $global_list(result_list) $TENSOR ]
+    
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set dims [ [ $tensor_image GetImage ] GetDimensions ]
+    
+    ## get current eigenvector scalar filter
+    set filter [ $widget_list(view_tensor_filter) index [ $widget_list(view_tensor_filter) get ] ]
+    set tensor_filter [ lindex $global_list(result_list) $filter ] 
+
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_tensor_glyph) index [ $widget_list(view_tensor_glyph) get ] ]
+    set glyph_source [ lindex $global_list(glyph_list) [ expr $cur_glyph + 3 ] ]
+    #    set glyph_source [ lindex $global_list(glyph_list) 3 ]
+    
+    if { $global_list(view_mode_index) < 4 } {
+	    
+	    ## plot on slices
+	    for { set i 0 } { $i < 3 } { incr i } {
+
+		if { [expr ($global_list(view_mode_index) == $i) || \
+			  ($global_list(view_mode_index) == 3) ] } {
+		    
+		    set ext [ view_compute_roi_extents $i $dims $levels ]
+		    set tensors [ [ view_extract_roi $ext $tensor_image ] GetOutput ]
+		    set scalars [ [ view_extract_roi $ext $tensor_filter ] GetOutput ]
+		    
+		    set actor [ view_create_tensor_glyph $tensors $scalars $glyph_source $i ]
+		    set global_list(actor_tensor) [ lreplace $global_list(actor_tensor) $i $i $actor ]
+		    
+		    $tensors Delete
+		    $scalars Delete
+		    
+		    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+		    
+		}
+		
+	    }
+    
+    } else {
+	
+	## plot on entire volume
+	set tensors [ $tensor_image GetImage ]
+	set scalars [ $tensor_filter GetImage ]
+
+	## create glyph
+	set actor [ view_create_tensor_glyph $tensors $scalars $glyph_source 3 ]
+	
+	set global_list(actor_tensor) [ lreplace $global_list(actor_tensor) 3 3 $actor ]
+	
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  View eigenvectors
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_create_eigenvector { title index } {
+    
+    ## which: (0) view_type_fast, (1) view_type_med, (2) view_type_slow, (3) view_type_tensor
+    set TENSOR 0
+    set MASK 1
+    set EIGENVALUES 2
+    set EIGENVECTORS 3
+    
+    set actornm "actor_$title"
+        
+    ## get eigenvalues and eigenvectors
+    set eigenvalues [ lindex $global_list(result_list) $EIGENVALUES ]
+    set eigenvectors [ lindex $global_list(result_list) $EIGENVECTORS ]
+
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set dims [ [ $eigenvalues GetImage ] GetDimensions ]
+    
+    ## get current eigenvector scalar filter
+    set filter [ $widget_list(view_eigen_filter) index [ $widget_list(view_eigen_filter) get ] ]
+    set eigenfilter [ lindex $global_list(result_list) $filter ] 
+    
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_eigen_glyph) index [ $widget_list(view_eigen_glyph) get ] ]
+    set glyph_source [ lindex $global_list(glyph_list) $cur_glyph ]
+    
+    if { $global_list(view_mode_index) < 4 } {
+	
+	## plot on slices
+	for { set i 0 } { $i < 3 } { incr i } {
+	    
+	    if { [ expr ($global_list(view_mode_index) == $i) || \
+		       ($global_list(view_mode_index) == 3) ] } {
+		
+		set ext [ view_compute_roi_extents $i $dims $levels ]
+		set vectors [ [ view_extract_roi $ext $eigenvectors ] GetOutput ]
+		set scalars [ [ view_extract_roi $ext $eigenfilter ] GetOutput ]
+		
+		set actor [ view_create_eigenvector_glyph $index $vectors $scalars $glyph_source $i ]
+		set global_list($actornm) [ lreplace $global_list($actornm) $i $i $actor ]
+		
+		$vectors Delete
+		$scalars Delete
+		
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+	    }
+	    
+	}
+    
+    } else {
+
+	## plot on entire volume
+	set vectors [ $eigenvectors GetImage ]
+	set scalars [ $eigenfilter GetImage ]
+
+	## create glyph
+	set actor [ view_create_eigenvector_glyph $index $vectors $scalars $glyph_source 3 ]
+	
+	set global_list($actornm) [ lreplace $global_list($actornm) 3 3 $actor ]
+	
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+	
+    }       
+}
+
+#-------------------------------------------------------------------------------------------
+#  View colorbar
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_create_colorbar { } {
+    
+    set cbar(Eigenvectors) 0
+    set cbar(Tensor) 1
+    set cbar(Results) 2
+
+    set title "colorbar"
+
+    set colorbar $cbar($global_list(view_colorbar))
+        
+    set filter 0
+    if { $colorbar == 0 } {
+	set filter [ $widget_list(view_eigen_filter) index [ $widget_list(view_eigen_filter) get ] ]
+    } elseif { $colorbar == 1 } {
+	set filter [ $widget_list(view_tensor_filter) index [ $widget_list(view_tensor_filter) get ] ]
+    } 
+
+    if { $colorbar < 2 } {
+	set title [ lindex [ lindex $global_list(result_title) $filter ] 0 ] 
+    } else {
+	set title $global_list(view_colorbar_label)
+    }
+    
+    set bar [ vtkScalarBarActor [ pxvtable::vnewobj ] ]
+    
+    if { $colorbar == 0 } {
+	$bar SetLookupTable [ $widget_list(view_vectorluk) GetLookupTable ]
+    } elseif { $colorbar == 1 } { 
+	$bar SetLookupTable [ $widget_list(view_tensorluk) GetLookupTable ]
+    } elseif { $colorbar == 2 } {
+	$bar SetLookupTable [ $widget_list(view_resultluk) GetLookupTable ]
+    }
+    
+    $bar SetTitle $title
+    [$bar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport
+    [$bar GetPositionCoordinate] SetValue 0.1 0.01
+    $bar SetOrientationToHorizontal
+    $bar SetWidth 0.8
+    $bar SetHeight 0.12
+    
+    set global_list(actor_colorbar) $bar
+    
+    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor2D $bar    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in display type
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_mode_cb { } {
+        
+    set mode(XZ-plane) 0
+    set mode(YZ-plane) 1
+    set mode(XY-plane) 2
+    set mode(3-slice) 3
+    set mode(Volume) 4
+    
+    set global_list(view_mode_index) $mode($global_list(view_mode))
+
+    view_clear_display
+
+    view_update_display
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in tensor colormap selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_tensor_cmapcopy_cb { } {
+    
+    ## current tensor filter
+    set cpfrom [ $widget_list(view_tensor_cmapcopy) index [ $widget_list(view_tensor_cmapcopy) get ] ]
+
+    set global_list(view_tensor_cmapcopy) $cpfrom
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon copy eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_tensor_cmapcopybtn_cb { } {
+    
+    if { $global_list(view_tensor_cmapcopy) == 0 } {
+	$widget_list(view_tensorluk) Copy [ $widget_list(view_vectorluk) GetLookupTable ]
+    } else {
+	$widget_list(view_tensorluk) Copy [ $widget_list(view_resultluk) GetLookupTable ]
+    }
+        
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon copy eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_tensor_cmapresetbtn_cb { } {
+    
+    ## current tensor filter
+    $widget_list(view_tensorluk) SetHueRange 0.5 0.0
+    $widget_list(view_tensorluk) Update
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon loading eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_tensor_cmaploadbtn_cb { } {   
+
+    $widget_list(view_tensorluk) Load
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon saving eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_tensor_cmapsavebtn_cb { } {   
+
+    $widget_list(view_tensorluk) SaveAs
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in tensor filter selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_tensor_filter_cb { } {
+    
+    set TENSOR 0
+    
+    ## current eigenvector filter
+    set filter [ $widget_list(view_tensor_filter) index [ $widget_list(view_tensor_filter) get ] ]   
+    set tensor_filter [ lindex $global_list(result_list) $filter ] 
+
+    ## get eigenvalues and eigenvectors
+    set tensor_image [ lindex $global_list(result_list) $TENSOR ]
+    
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set dims [ [ $tensor_image GetImage ] GetDimensions ]
+    
+    if { $global_list(view_mode_index) < 4 } {	
+	
+	## plot on slices
+	for { set i 0 } { $i < 3 } { incr i } {
+	    
+	    if { [expr ($global_list(view_mode_index) == $i ) || \
+		      ($global_list(view_mode_index) == 3) ] } {		
+		
+		set ext [ view_compute_roi_extents $i $dims $levels ]
+		set scalar [ [ view_extract_roi $ext $tensor_filter ] GetOutput ]
+		
+		set merge $global_list(vtk_tensor_merge,$i)
+		$merge SetScalars $scalar
+		
+		$scalar Delete	    	    
+	    }
+	}	
+	
+    } else {
+	
+	## plot on entire volume
+	set scalar [ [ lindex $global_list(result_list) $filter ] GetImage ]
+	
+	set merge $global_list(vtk_tensor_merge,3)
+	$merge SetScalars $scalar
+    }
+    
+    set result [ [ lindex $global_list(result_list) $filter ] GetImage ]
+    set range [ [ [ $result GetPointData ] GetScalars ] GetRange ]
+    $widget_list(view_tensorluk) SetTableRange [ lindex $range 0 ] [ lindex $range 1 ]
+#    $widget_list(view_tensorluk) Update
+    
+    ## update scalar bar    
+    if { $global_list(view_colorbar) == "Hessian" } {
+	set title [ lindex [ lindex $global_list(result_title) $filter ] 0 ] 
+	if { $global_list(actor_colorbar) != -1 } { 
+	    $global_list(actor_colorbar) SetTitle $title
+	}
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in eigen colormap selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_eigen_cmapcopy_cb { } {
+    
+    ## current eigenvector filter
+    set cpfrom [ $widget_list(view_eigen_cmapcopy) index [ $widget_list(view_eigen_cmapcopy) get ] ]
+
+    set global_list(view_eigen_cmapcopy) $cpfrom
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon copy eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_eigen_cmapcopybtn_cb { } {
+    
+    if { $global_list(view_eigen_cmapcopy) == 0 } {
+	$widget_list(view_vectorluk) Copy [ $widget_list(view_tensorluk) GetLookupTable ]
+    } else {
+	$widget_list(view_vectorluk) Copy [ $widget_list(view_resultluk) GetLookupTable ]
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon resetting eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_eigen_cmapresetbtn_cb { } {
+    
+    ## current tensor filter
+    $widget_list(view_vectorluk) SetHueRange 0.75 0.0
+    $widget_list(view_vectorluk) Update
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon loading eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_eigen_cmaploadbtn_cb { } {
+
+    $widget_list(view_vectorluk) Load
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon saving eigen colormap 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_eigen_cmapsavebtn_cb { } {
+
+    $widget_list(view_vectorluk) SaveAs
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in vector filter selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_eigen_filter_cb { } {    
+      
+    set EIGENVALUES 2
+    set EIGENVECTORS 3
+
+    ## current eigenvector filter
+    set filter [ $widget_list(view_eigen_filter) index [ $widget_list(view_eigen_filter) get ] ]   
+    
+    ## get eigenvalues and eigenvectors
+    set eigenvalues [ lindex $global_list(result_list) $EIGENVALUES ]
+    set eigenvectors [ lindex $global_list(result_list) $EIGENVECTORS ]
+
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set dims [ [ $eigenvalues GetImage ] GetDimensions ]
+
+    if { $global_list(view_mode_index) < 4 } {
+	
+	## plot on slices
+	for { set i 0 } { $i < 3 } { incr i } {
+	    
+	    if { [expr ($global_list(view_mode_index) == $i ) || \
+		      ($global_list(view_mode_index) == 3) ] } {
+		
+		set ext [ view_compute_roi_extents $i $dims $levels ]
+		set scalar [ view_extract_roi $ext [ lindex $global_list(result_list) $filter ] ]
+	    
+		## loop through eigenvectors
+		for { set j 0 } { $j < 3 } { incr j } {
+		    set merge $global_list(vtk_eigen_merge,$j,$i)
+		    $merge SetScalars [ $scalar GetOutput ]
+		}
+		
+		$scalar Delete
+	    }
+	}
+    } else {
+	
+	## plot on entire volume
+	#	set ext [ view_compute_roi_extents 3 $dims $levels ]
+	set scalar [ [ lindex $global_list(result_list) $filter ] GetImage ]
+	
+	## loop through eigenvectors
+	for { set j 0 } { $j < 3 } { incr j } {
+	    set merge $global_list(vtk_eigen_merge,$j,3)
+	    $merge SetScalars $scalar
+	}		
+    }
+
+    set result [ [ lindex $global_list(result_list) $filter ] GetImage ]
+    set range [ [ [ $result GetPointData ] GetScalars ] GetRange ]
+    $widget_list(view_vectorluk) SetTableRange [ lindex $range 0 ] [ lindex $range 1 ]
+#    $widget_list(view_vectorluk) Modified
+    #$widget_list(view_vectorluk) Update
+
+    ## update scalar bar    
+    if { $global_list(view_colorbar) == "Eigenvectors" } {
+	set title [ lindex [ lindex $global_list(result_title) $filter ] 0 ] 
+	if { $global_list(actor_colorbar) != -1 } { 
+	    $global_list(actor_colorbar) SetTitle $title
+	}
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in threshold values
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_tensor_fromto_cb { } {
+    for { set j 0 } { $j < 4 } { incr j } { 
+	if { $global_list(view_tensor_between) == 1 } {
+	    $global_list(vtk_tensor_threshold,$j) ThresholdBetween \
+		$global_list(view_tensor_from) $global_list(view_tensor_to)
+	} else {
+	    $global_list(vtk_tensor_threshold,$j) ThresholdByUpper \
+		$global_list(view_tensor_from)
+	}
+    }
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in threshold values
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_eigen_fromto_cb { } {
+    for { set i 0 } { $i < 3 } { incr i } {	
+	for { set j 0 } { $j < 4 } { incr j } { 
+	    if { $global_list(view_eigen_between) == 1 } {
+		$global_list(vtk_eigen_threshold,$i,$j) ThresholdBetween \
+		    $global_list(view_eigen_from) $global_list(view_eigen_to)
+	    } else {
+		$global_list(vtk_eigen_threshold,$i,$j) ThresholdByUpper \
+		    $global_list(view_eigen_from)
+	    }
+	}
+    }
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in glyph type
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_eigen_glyph_cb { } {    
+    set index [ $widget_list(view_eigen_glyph) index [ $widget_list(view_eigen_glyph) get ] ]
+    set glyph [ lindex $global_list(glyph_list) $index ]
+    for { set i 0 } { $i < 3 } { incr i } {
+	for { set j 0 } { $j < 4 } { incr j } { 
+	    $global_list(vtk_eigen_glypher,$i,$j) SetSource [ $glyph GetOutput ]
+	}
+    }
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in glyph type
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_tensor_glyph_cb { } {    
+    set index [ $widget_list(view_tensor_glyph) index [ $widget_list(view_tensor_glyph) get ] ]
+    set glyph [ lindex $global_list(glyph_list) [expr $index + 3 ] ]
+    for { set j 0 } { $j < 4 } { incr j } { 
+	$global_list(vtk_tensor_glypher,$j) SetSource [ $glyph GetOutput ]
+    }
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in threshold values
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_tensor_maxscale_cb { } {
+    for { set j 0 } { $j < 4 } { incr j } {
+	$global_list(vtk_tensor_glypher,$j) \
+	    SetScaleFactor $global_list(view_tensor_scale)
+	$global_list(vtk_tensor_glypher,$j) \
+	    SetMaxScaleFactor $global_list(view_tensor_maxscale)
+	$global_list(vtk_tensor_glypher,$j) \
+	    SetClampScaling $global_list(view_tensor_clampscale)
+    }
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in threshold values
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_eigen_maxscale_cb { } {
+    for { set i 0 } { $i < 3 } { incr i } {
+	for { set j 0 } { $j < 4 } { incr j } {
+	    $global_list(vtk_eigen_glypher,$i,$j) \
+		SetScaleFactor $global_list(view_eigen_maxscale)
+	}
+    }
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in colorbar selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_colorbar_cb { } {
+
+    ## recreate colorbar
+    set actor $global_list(actor_colorbar)
+    if { $actor != -1 } {
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor
+	$actor Delete
+    }
+
+    if { $global_list(view_type_colorbar) } {
+	view_create_colorbar
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon an update button press
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_update_display_cb { } { 
+    
+    view_clear_display
+
+    view_update_display
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in colormaps for result images
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_results_colormap_cb { } {
+
+    set luk [ $widget_list(view_resultluk) GetLookupTable ]
+    
+    if { $global_list(view_transparent) } {
+#	set rgba [ $luk GetTableValue 0 ]
+	set index [ $luk GetIndex $global_list(view_transpcolor) ]
+#	puts "color: $global_list(view_transpcolor) $index"
+	set rgba [ $luk GetTableValue $index ]
+	$luk SetTableValue $index [ lindex $rgba 0 ] [ lindex $rgba 1 ] [ lindex $rgba 2 ] 0.0
+    } else {
+	$widget_list(view_resultluk) Update
+	set luk [ $widget_list(view_resultluk) GetLookupTable ]
+    }
+        
+    [ $parent GetViewer ] SetLookupTable $luk
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon selection of tensor direction coloring
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::view_direction_update_cb { } {
+    
+    set TENSOR 0
+    set MASK 1
+    set EIGENVECTORS 3
+    set DEC_MAP 12
+    
+    set filter [ $widget_list(view_direction_filter) index \
+		     [ $widget_list(view_direction_filter) get ] ]   
+    
+    set scheme [ $widget_list(view_direction_scheme) index \
+		     [ $widget_list(view_direction_scheme) get ] ]   
+    
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set eigenvectors [ lindex $global_list(result_list) $EIGENVECTORS ]
+    
+    set magmap [ lindex $global_list(result_list) $filter ]
+    
+    set imct [ vtkmpjImageTensorColor [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $imct "Computing colormap..."
+    $imct SetInput [ $eigenvectors GetImage ]
+    $imct SetColorSchemeType $scheme
+    $imct SetSaturationScale $global_list(view_direction_satscale)
+    $imct SetScaling $global_list(view_direction_scaling)
+    $imct SetMagnitude [ $magmap GetImage ]
+    
+    if { $global_list(view_direction_mask) == 1 } {
+	$imct SetMask [ $mask GetImage ]
+    }
+    
+    $imct Update
+    
+    set quant [ vtkImageQuantizeRGBToIndex [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $quant "Quantizing colormap..."
+    $quant SetInput [ $imct GetOutput ]
+    $quant SetNumberOfColors $global_list(view_direction_numcolors)
+    $quant Update
+       
+    set imcast [ vtkImageCast [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $imcast "Converting colormap to floating point..."
+    $imcast SetInput [ $quant GetOutput ]
+    $imcast SetOutputScalarTypeToFloat
+    $imcast Update
+
+    set imctmap [ lindex $global_list(result_list) $DEC_MAP ]
+    $imctmap ShallowCopyImage [ $imcast GetOutput ]    
+    set range [ [ [ [ $imcast GetOutput ] GetPointData ] GetScalars ] GetRange ]
+    $imctmap CopyImageHeader [ $tensor GetImageHeader ]
+
+    $parent SetImageFromObject \
+	[ $imctmap GetThisPointer ] $this
+
+    set temp_luk [ vtkLookupTable [ pxvtable::vnewobj ] ]
+    $temp_luk DeepCopy [ $quant GetLookupTable ]
+    
+    $quant Delete
+    
+    $widget_list(view_resultluk) SetTableRange [ lindex $range 0 ] [ lindex $range 1 ]
+    $widget_list(view_resultluk) SetLookupTable $temp_luk
+
+    #    [ $parent GetViewer ] SetLookupTable [ $quant GetLookupTable ]
+    [ $parent GetViewer ] SetLookupTable [ $widget_list(view_resultluk) GetLookupTable ]
+    [ $parent GetViewer ] UpdateDisplay
+        
+    $imct Delete  
+    $imcast Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create tensor control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateTensorControl { base } {
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Hessian image"
+    pack $base.frame0 -fill both -expand f -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+  
+    set tensor_fname [ iwidgets::entryfield $subframe1.mask_fname \
+			   -textvariable [ itcl::scope global_list(tensor_fname) ] \
+			   -labeltext "Filename:" ] 
+    pack $tensor_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(tensor_fname) $tensor_fname
+    
+    set tensor_load [ iwidgets::buttonbox $subframe1.tensor_load -orient horizontal -padx 2 ]
+    $tensor_load add load -text "Load..." -command [ itcl::code $this loadtensor ] 
+    $tensor_load add disp -text "Display" -command [ itcl::code $this DisplayResult 0 ]
+    pack $tensor_load -side left
+    set widget_list(tensor_load) $tensor_load  
+
+    set tensor_ordering \
+	[ iwidgets::optionmenu $subframe1.tensor_ordering -labeltext "Components:" ]
+    $tensor_ordering configure -command [ itcl::code $this tensor_ordering_cb ]
+    $tensor_ordering insert 0 "xx-xy-xz-yy-yz-zz"
+    $tensor_ordering insert 1 "xx-yy-zz-xy-yz-xz"
+    pack $tensor_ordering -side right -padx 5
+    set widget_list(tensor_ordering) $tensor_ordering
+
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Region of interest mask"
+    pack $base.frame1 -fill both -expand f
+    
+    set frame1 [ $base.frame1 childsite ]
+    
+    set subframe0 [ frame $frame1.subframe0 ]
+    pack $subframe0 -side top -fill both -expand f -pady 5
+    
+    set mask_auto [ checkbutton $subframe0.mask_auto \
+			-text "Use entire image for computation" \
+			-variable [ itcl::scope global_list(mask_auto) ] \
+			-command [ itcl::code $this mask_autochanged_cb ] ]
+    pack $mask_auto -side left -fill both -padx 5 -pady 2
+    
+    set subframe1 [ frame $frame1.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+    
+    set mask_fname [ iwidgets::entryfield $subframe1.mask_fname \
+			 -textvariable [ itcl::scope global_list(mask_fname) ] \
+			 -state disabled \
+			 -labeltext "Filename:" ] 
+    pack $mask_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(mask_fname) $mask_fname
+
+    set mask_load [ iwidgets::buttonbox $subframe1.mask_load -orient horizontal -padx 2 ]
+    $mask_load add load -text "Load..." -command [ itcl::code $this loadmask ]    
+    $mask_load add disp -text "Display" -command [ itcl::code $this DisplayResult 1 ]
+    pack $mask_load -side left 
+    $mask_load buttonconfigure load -state disabled
+    $mask_load buttonconfigure disp -state disabled
+    set widget_list(mask_load) $mask_load
+    
+    set mask_nreg [ iwidgets::spinint $subframe1.mask_nreg \
+			-labeltext "Number of regions in mask:" \
+			-fixed 4 -width 4 -range {1 1000} -step 1 \
+			-textvariable [ itcl::scope global_list(mask_nreg) ] \
+			-state disabled ]
+    pack $mask_nreg -side right -padx 5 -pady 5
+    set widget_list(mask_nreg) $mask_nreg
+
+    set frame2 [ frame $base.frame2 ]
+    pack $frame2 -side top -fill both -expand f 
+
+    set widget_list(computebtn) [ button $frame2.compute -text "Compute!" \
+				      -state disabled \
+				      -command [ itcl::code $this ComputeResults ] ]    
+    pack $frame2.compute -side left -fill x -expand f -padx 5 -pady 10  
+    
+    set eigen_recompute [ checkbutton $frame2.eigen_recompute \
+			      -text "Always recompute eigensystem" \
+			      -variable [ itcl::scope global_list(eigen_recompute) ] ]
+    pack $eigen_recompute -side right -fill both -padx 5 -pady 5
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create eigenvalues/vectors control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateEigenControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Eigenvalues"
+    pack $base.frame0 -fill both -expand f -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+          
+    set eigenval_fname [ iwidgets::entryfield $subframe1.eigenval_fname \
+			     -textvariable [ itcl::scope global_list(eigenval_fname) ] \
+			     -state disabled \
+			     -labeltext "Filename:" ] 
+    pack $eigenval_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(eigenval_fname) $eigenval_fname
+    
+    set eigenval_load [ iwidgets::buttonbox $subframe1.eigenval_load -orient horizontal -padx 2 ]
+    $eigenval_load add load -text "Load..." -command [ itcl::code $this loadeigenval ]    
+    $eigenval_load add disp -text "Display" -command [ itcl::code $this DisplayResult 2 ]
+    pack $eigenval_load -side left 
+    $eigenval_load buttonconfigure load -state disabled
+    set widget_list(eigenval_load) $eigenval_load
+
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Eigenvectors"
+    pack $base.frame1 -fill both -expand f -pady 5
+    
+    set frame1 [ $base.frame1 childsite ]
+    
+    set subframe1 [ frame $frame1.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+    
+    set eigenvec_fname [ iwidgets::entryfield $subframe1.eigenvec_fname \
+			     -textvariable [ itcl::scope global_list(eigenvec_fname) ] \
+			     -state disabled \
+			     -labeltext "Eigenvectors:" ] 
+    pack $eigenvec_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(eigenvec_fname) $eigenvec_fname
+    
+    set eigenvec_load [ iwidgets::buttonbox $subframe1.eigenvec_load -orient horizontal -padx 2 ]
+    $eigenvec_load add load -text "Load..." -command [ itcl::code $this loadeigenvec ]    
+    $eigenvec_load add disp -text "Display" -command [ itcl::code $this DisplayResult 3 ]
+    pack $eigenvec_load -side left 
+    $eigenvec_load buttonconfigure load -state disabled
+    set widget_list(eigenvec_load) $eigenvec_load    
+    
+    set subframe2 [ frame $base.subframe2 ]
+    pack $subframe2 -side top -fill x -expand f -pady 0
+
+    set eigen_auto [ checkbutton $subframe2.eigen_auto \
+			 -text "Compute eigenvectors from tensor" \
+			 -variable [ itcl::scope global_list(eigen_auto) ]  \
+			 -command [ itcl::code $this eigen_autochanged_cb ] ]
+    pack $eigen_auto -side left -fill both -padx 5 -pady 5
+
+    set subframe3 [ frame $base.subframe3 ]
+    pack $subframe3 -side top -fill x -expand f -pady 0
+
+    set eigen_positive [ checkbutton $subframe3.eigen_absolute \
+			     -text "Absolute eigenvalues" \
+			     -variable [ itcl::scope global_list(eigen_positive) ] ] 
+    pack $eigen_positive -side left -fill both -padx 5 -pady 5
+    
+    set subframe4 [ frame $base.subframe4 ]
+    pack $subframe4 -side top -fill x -expand f -pady 0
+
+    set eigen_sortbymagnitude [ checkbutton $subframe4.eigen_sortbymagnitude \
+				    -text "Sort by magnitude" \
+				    -variable [ itcl::scope global_list(eigen_sortbymagnitude) ] ]
+    pack $eigen_sortbymagnitude -side left -fill both -padx 5 -pady 5
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create vessel enhancement control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateVesselControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Sensitivity parameters"
+    pack $base.frame0 -fill both -expand f -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 2
+    
+    set vessel_alpha [ iwidgets::entryfield $subframe1.vessel_alpha \
+			   -labeltext "Alpha:" \
+			   -validate real \
+			   -width 4 \
+			   -textvariable [ itcl::scope global_list(vessel_alpha) ] ]
+    pack $vessel_alpha -side left -pady 7 -padx 5
+    set widget_list(vessel_alpha) $vessel_alpha
+
+    set vessel_beta [ iwidgets::entryfield $subframe1.vessel_beta \
+			   -labeltext "Beta:" \
+			   -validate real \
+			   -width 4 \
+			   -textvariable [ itcl::scope global_list(vessel_beta) ] ]
+    pack $vessel_beta -side left -pady 7 -padx 5
+    set widget_list(vessel_beta) $vessel_beta
+
+    set vessel_gamma [ iwidgets::entryfield $subframe1.vessel_gamma \
+			   -labeltext "Gamma:" \
+			   -validate real \
+			   -width 4 \
+			   -textvariable [ itcl::scope global_list(vessel_gamma) ] ]
+    pack $vessel_gamma -side left -pady 7 -padx 5
+    set widget_list(vessel_gamma) $vessel_gamma
+
+    set vessel_maxintensity [ iwidgets::entryfield $subframe1.vessel_maxintensity \
+				  -labeltext "Maximum intensity:" \
+				  -validate real \
+				  -width 7 \
+				  -textvariable [ itcl::scope global_list(vessel_maxintensity) ] ]
+    pack $vessel_maxintensity -side left -pady 7 -padx 5
+    set widget_list(vessel_maxintensity) $vessel_maxintensity
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill both -expand f -pady 2
+        
+    set vessel_intensity \
+	[ iwidgets::optionmenu $subframe2.vessel_intensity \
+	      -command [ itcl::code $this vessel_intensity_cb ] \
+	      -labeltext "Structure intensity:" ]
+    $vessel_intensity insert 1 "Dark"
+    $vessel_intensity insert 0 "Bright"
+    pack $vessel_intensity -side left -padx 5 -pady 5
+    set widget_list(vessel_intensity) $vessel_intensity
+    $vessel_intensity select 0
+       
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create transform control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateTransformControl { base } {
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Hessian transformation"
+    pack $base.frame0 -fill both -expand t -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+
+    set tensorflipx [ checkbutton $subframe1.tensorflipx \
+			  -text "Flip X" \
+			  -command [ itcl::code $this view_update_display_cb ] \
+			  -variable [ itcl::scope global_list(tensor_flipx) ] ]
+    pack $tensorflipx -side left -padx 5 -pady 7
+    set widget_list(tensor_flipx) $tensorflipx
+    
+    set tensorflipy [ checkbutton $subframe1.tensorflipy \
+			  -text "Flip Y" \
+			  -command [ itcl::code $this view_update_display_cb ] \
+			  -variable [ itcl::scope global_list(tensor_flipy) ] ]
+    pack $tensorflipy -side left -padx 5 -pady 7
+    set widget_list(tensor_flipy) $tensorflipy   
+    
+    set tensorflipz [ checkbutton $subframe1.tensorflipz \
+			  -text "Flip Z" \
+			  -command [ itcl::code $this view_update_display_cb ] \
+			  -variable [ itcl::scope global_list(tensor_flipz) ] ]
+    pack $tensorflipz -side left -padx 5 -pady 7
+    set widget_list(tensor_flipz) $tensorflipz
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill both -expand f -pady 0
+
+    iwidgets::entryfield $subframe2.tensor_rotx \
+	-width 5 \
+	-validate real \
+	-labeltext "Tensor rotation  Rx:" \
+	-textvariable [ itcl::scope global_list(tensor_rotx) ]
+    pack $subframe2.tensor_rotx -side left -fill x -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe2.tensor_roty \
+	-width 5 \
+	-validate real \
+	-labeltext "Ry:" \
+	-textvariable [ itcl::scope global_list(tensor_roty) ]
+    pack $subframe2.tensor_roty -side left -fill x -pady 5
+    
+    iwidgets::entryfield $subframe2.tensor_rotz \
+	-width 5 \
+	-validate real \
+	-labeltext "Rz:" \
+	-textvariable [ itcl::scope global_list(tensor_rotz) ]
+    pack $subframe2.tensor_rotz -side left -fill x -pady 5
+
+    label $subframe2.dummy -text "degrees"
+    pack $subframe2.dummy -side left
+        
+    set tensor_rotation [ button $subframe2.tensor_rotation \
+			      -command [ itcl::code $this result_rotatetensor ] \
+			      -text "Rotate!" ]
+    pack $tensor_rotation -side left -fill both -padx 5 -pady 5
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create results control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateResultsControl { base } {   
+
+    set color(0) \#dcdcdc
+    set color(1) black
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Results"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+    
+    iwidgets::scrolledlistbox $subframe0.resultlist \
+	-hscrollmode dynamic \
+	-selectmode extended \
+	-dblclickcommand [ itcl::code $this toggleresult ] \
+	-visibleitems 40x10 
+    
+    pack $subframe0.resultlist -side left -fill both -expand t -padx 2 -pady 2
+    set widget_list(result_list) $subframe0.resultlist
+    
+    foreach item $global_list(result_title) {
+	set enable [ lindex $item 2 ]
+     	$widget_list(result_list) insert end "[lindex $item 0]" 
+	$widget_list(result_list) itemconfigure end -foreground $color($enable)
+    }
+
+    set subframe1 [ frame $subframe0.subframe1 ]
+    pack $subframe1 -side right -fill both -padx 0
+    
+    set resultbbox [ iwidgets::buttonbox $subframe1.input -orient vertical ]
+    $resultbbox add display -text "Display" -command [ itcl::code $this displayresult ]
+    $resultbbox add save -text "Save..." -command [ itcl::code $this saveresult ]
+    $resultbbox add saveall -text "Save all" -command [ itcl::code $this saveallresults ]    
+    $resultbbox add mark -text "On/Off" -command [ itcl::code $this toggleresult ]
+    pack $resultbbox -side top -fill x -expand t -padx 0
+    set widget_list(result_buttonbox) $resultbbox
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill x -padx 2 -pady 5
+
+    set result_fpreffix [ iwidgets::entryfield $subframe2.result_fpreffix \
+			      -textvariable [ itcl::scope global_list(result_fpreffix) ] \
+			      -labeltext "Preffix:" ]
+    pack $result_fpreffix -side left -fill x -expand t -padx 5 -pady 2
+    set widget_list(result_fpreffix) $result_fpreffix    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create statistics control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateStatisticsControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Statistics"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+
+    set stat_text [iwidgets::scrolledtext $subframe0.stat_text \
+		       -visibleitems 70x19 \
+		       -foreground black \
+		       -vscrollmode static \
+		       -hscrollmode dynamic \
+		       -wrap none ]
+    pack $stat_text -side top -expand t -fill both -padx 2 -pady 2
+    set widget_list(stat_text) $stat_text
+
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -expand t
+
+    set statbbox [ iwidgets::buttonbox $subframe1.statbbox -orient horizontal -pady 2 -padx 2 ]
+    $statbbox add save -text "Save..." -command [ itcl::code $this savestatistics ]
+    $statbbox add clear -text "Clear" -command "$stat_text delete 1.0 end"
+    pack $statbbox -side left -fill both 
+
+    set stat_overwrite [ checkbutton $subframe1.stat_overwrite -text "Overwrite" \
+			     -variable [ itcl::scope global_list(stat_overwrite) ] ]
+    pack $stat_overwrite -side right -padx 5       
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create eigenvector display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateEigenDisplayControl { base } {
+
+    set FA_MAP 5
+
+    set subframe0 [ frame $base.subframe0 ]
+    pack $subframe0 -fill x -side top -padx 5 -expand f -pady 5
+        
+    set view_eigen_filter \
+	[ iwidgets::optionmenu $subframe0.view_eigen_filter -labeltext "Filter:" ]
+    $view_eigen_filter configure -command [ itcl::code $this view_eigen_filter_cb ]
+    for { set i 0 } { $i < [ llength $global_list(result_title) ] } { incr i } {
+	$view_eigen_filter insert $i [ lindex [ lindex $global_list(result_title) $i ] 0 ]
+    }
+    pack $view_eigen_filter -side left -padx 5
+    set widget_list(view_eigen_filter) $view_eigen_filter
+
+    $view_eigen_filter select $FA_MAP
+    
+    iwidgets::entryfield $subframe0.view_eigen_from \
+	-width 5 \
+	-validate real \
+	-labeltext "From:" \
+	-textvariable [ itcl::scope global_list(view_eigen_from) ] \
+	-command [ itcl::code $this view_eigen_fromto_cb ]
+    pack $subframe0.view_eigen_from -side left -fill x -padx 5
+    
+    checkbutton $subframe0.view_eigen_between \
+	-text "to:"  \
+	-variable [ itcl::scope global_list(view_eigen_between) ] \
+	-command [ itcl::code $this view_eigen_fromto_cb ]
+    pack $subframe0.view_eigen_between -side left -fill x -padx 0
+    
+    iwidgets::entryfield $subframe0.view_eigen_to \
+	-width 5 \
+	-validate real \
+	-textvariable [ itcl::scope global_list(view_eigen_to) ] \
+	-command [ itcl::code $this view_eigen_fromto_cb ]
+    pack $subframe0.view_eigen_to -side left -fill x -padx 0
+    
+    set subframe1 [ frame $base.subframe1 ]
+    pack $subframe1 -side top -fill both -padx 5 
+    
+    set view_eigen_glyph [ iwidgets::optionmenu $subframe1.view_eigen_glyph \
+			       -command [ itcl::code $this view_eigen_glyph_cb ] \
+			       -labeltext "View eigenvector as:" ]
+    pack $view_eigen_glyph -side left -padx 5
+    $view_eigen_glyph insert end "Lines"
+    $view_eigen_glyph insert end "Tubes"
+    $view_eigen_glyph insert end "Arrows"
+    set widget_list(view_eigen_glyph) $view_eigen_glyph
+
+    iwidgets::entryfield $subframe1.view_eigen_maxscale \
+	-width 5 \
+	-validate real \
+	-labeltext "Glyph scale factor:" \
+	-textvariable [ itcl::scope global_list(view_eigen_maxscale) ] \
+	-command [ itcl::code $this view_eigen_maxscale_cb ]
+    pack $subframe1.view_eigen_maxscale -side left -padx 5 
+    
+    #    checkbutton $subframe1.view_eigen_flip \
+	#	-text "Flip"  \
+	#	-variable [ itcl::scope global_list(view_eigen_flip) ] \
+	#	-command [ itcl::code $this view_update_display_cb ]
+    #    pack $subframe1.view_eigen_flip -side left -fill x -padx 0
+    
+    set subframe2 [ frame $base.subframe2 -relief flat ]
+    pack $subframe2 -side left -padx 5 -pady 5 
+    
+    set vector_luk [ mpjguilookuptable \#auto 0 ]
+    $vector_luk Initialize $subframe2
+    pack forget [ $vector_luk GetButtonBoxWidget ]
+#    pack forget [ $vector_luk GetMenuBar ]     
+    $vector_luk SetHueRange 0.75 0.0
+    $vector_luk Update
+    $vector_luk Show
+
+    set widget_list(view_vectorluk) $vector_luk
+        
+    set view_eigen_cmap_copy [ iwidgets::optionmenu [ $vector_luk GetMenuBar ].copy_cmap \
+				   -labeltext "from:" \
+				   -command [ itcl::code $this view_eigen_cmapcopy_cb ] ]
+    pack $view_eigen_cmap_copy  -side right -padx 2 -pady 2
+    $view_eigen_cmap_copy insert end "Hessians"
+    $view_eigen_cmap_copy insert end "Results"
+    
+    set widget_list(view_eigen_cmapcopy) $view_eigen_cmap_copy
+
+    set view_eigen_cmap_copybtn [ button [ $vector_luk GetMenuBar ].copybtn -text "Copy" \
+				      -command [ itcl::code $this view_eigen_cmapcopybtn_cb ] ]
+    pack $view_eigen_cmap_copybtn -side right -padx 0 -pady 5 
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create tensor display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateTensorDisplayControl { base } {
+
+    set FA_MAP 5
+
+    set subframe0 [ frame $base.subframe0 ]
+    pack $subframe0 -fill both -padx 5 -expand f -pady 5
+        
+    set view_tensor_filter \
+	[ iwidgets::optionmenu $subframe0.view_tensor_filter -labeltext "Filter:" ]
+    $view_tensor_filter configure -command [ itcl::code $this view_tensor_filter_cb ]
+    for { set i 0 } { $i < [ llength $global_list(result_title) ] } { incr i } {
+	$view_tensor_filter insert $i [ lindex [ lindex $global_list(result_title) $i ] 0 ]
+    }
+    pack $view_tensor_filter -side left -padx 5
+    set widget_list(view_tensor_filter) $view_tensor_filter
+
+    $view_tensor_filter select $FA_MAP
+    
+    iwidgets::entryfield $subframe0.view_tensor_from \
+	-width 5 \
+	-validate real \
+	-labeltext "From:" \
+	-textvariable [ itcl::scope global_list(view_tensor_from) ] \
+	-command [ itcl::code $this view_tensor_fromto_cb ]
+    pack $subframe0.view_tensor_from -side left -fill x -padx 5
+    
+    checkbutton $subframe0.view_tensor_between \
+	-text "to:"  \
+	-variable [ itcl::scope global_list(view_tensor_between) ] \
+	-command [ itcl::code $this view_tensor_fromto_cb ]
+    pack $subframe0.view_tensor_between -side left -fill x -padx 0
+    
+    iwidgets::entryfield $subframe0.view_tensor_to \
+	-width 5 \
+	-validate real \
+	-textvariable [ itcl::scope global_list(view_tensor_to) ] \
+	-command [ itcl::code $this view_tensor_fromto_cb ]
+    pack $subframe0.view_tensor_to -side left -fill x -padx 0
+    
+    set subframe1 [ frame $base.subframe1 ]
+    pack $subframe1 -side top -fill both -padx 5 
+
+    set view_tensor_glyph [ iwidgets::optionmenu $subframe1.view_tensor_glyph \
+				-command [ itcl::code $this view_tensor_glyph_cb ] \
+				-labeltext "View tensor as:" ]
+    pack $view_tensor_glyph -side left -padx 5
+    $view_tensor_glyph insert end "Ellipsoids"
+    $view_tensor_glyph insert end "Cuboids"
+    $view_tensor_glyph insert end "Sheets"
+    set widget_list(view_tensor_glyph) $view_tensor_glyph
+
+    iwidgets::entryfield $subframe1.view_tensor_scale \
+	-width 5 \
+	-validate real \
+	-labeltext "Scale:" \
+	-textvariable [ itcl::scope global_list(view_tensor_scale) ] \
+	-command [ itcl::code $this view_tensor_maxscale_cb ]
+    pack $subframe1.view_tensor_scale -side left -padx 5 -pady 5
+    
+    set view_tensor_clampscale [ checkbutton $subframe1.view_tensor_clampscale \
+				     -text "Clamp at:" \
+				     -variable \
+				     [ itcl::scope global_list(view_tensor_clampscale) ] \
+				     -command [ itcl::code $this view_tensor_maxscale_cb ] ]
+    pack $view_tensor_clampscale -side left -pady 5 -padx 5       
+    set widget_list(view_tensor_clampscale) $view_tensor_clampscale
+
+    iwidgets::entryfield $subframe1.view_tensor_maxscale \
+	-width 5 \
+	-validate real \
+	-textvariable [ itcl::scope global_list(view_tensor_maxscale) ] \
+	-command [ itcl::code $this view_tensor_maxscale_cb ]
+    pack $subframe1.view_tensor_maxscale -side left -padx 2 -pady 5
+    
+    set subframe2 [ frame $base.subframe2 -relief flat ]
+    pack $subframe2 -side left -padx 5 -pady 5
+
+    set tensor_luk [ mpjguilookuptable \#auto 0 ]
+    $tensor_luk Initialize $subframe2
+    pack forget [ $tensor_luk GetButtonBoxWidget ]
+#    pack forget [ $tensor_luk GetMenuBar ] 
+    $tensor_luk SetHueRange 0.5 0.0
+    $tensor_luk Update
+    $tensor_luk Show
+    
+    set widget_list(view_tensorluk) $tensor_luk
+    
+    set view_tensor_cmap_copy [ iwidgets::optionmenu [ $tensor_luk GetMenuBar ].copy_cmap \
+				    -labeltext "from:" \
+				    -command [ itcl::code $this view_tensor_cmapcopy_cb ] ]
+    pack $view_tensor_cmap_copy  -side right -padx 2 -pady 5
+    $view_tensor_cmap_copy insert end "Eigenvectors"
+    $view_tensor_cmap_copy insert end "Results"
+    
+    set widget_list(view_tensor_cmapcopy) $view_tensor_cmap_copy
+    
+    set view_tensor_cmap_copybtn [ button [ $tensor_luk GetMenuBar ].copybtn -text "Copy" \
+				       -command [ itcl::code $this view_tensor_cmapcopybtn_cb ] ]
+    pack $view_tensor_cmap_copybtn -side right -padx 0 -pady 5 
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create result display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateResultDisplayControl { base } {
+    
+    set subframe1 [ frame $base.subframe1 ]
+    pack $subframe1 -side bottom -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe1.view_colorbar_label \
+	-width 15 \
+	-labeltext "Colormap label:" \
+	-textvariable [ itcl::scope global_list(view_colorbar_label) ]
+    pack $subframe1.view_colorbar_label -side top -padx 5    
+
+    set resultluk [ mpjguilookuptable \#auto 0 ]
+    $resultluk Initialize $subframe1
+    pack forget [ $resultluk GetButtonBoxWidget ]
+#    pack forget [ $resultluk GetMenuBar ]
+    $resultluk SetHueRange 0.0 0.2
+    $resultluk SetSaturationRange 1.0 0.5
+    $resultluk SetValueRange 0.5 1.0
+    $resultluk Update
+    $resultluk Show
+
+    set widget_list(view_resultluk) $resultluk    
+    
+    set resultdisplaybtn [ button [ $resultluk GetMenuBar ].resultdisplaybtn \
+			       -text "Apply!" \
+			       -command [ itcl::code $this view_results_colormap_cb ]  ]
+    pack $resultdisplaybtn -side left -padx 5 -pady 5
+    
+
+    set subframe0 [ frame [ $resultluk GetMenuBar ].subframe0 ]
+    pack $subframe0 -fill x -side bottom -expand f -padx 5 -pady 5
+
+    set transparent [ checkbutton $subframe0.transparent \
+			  -variable [ itcl::scope global_list(view_transparent) ] ]    
+    pack $transparent -side left -pady 5       
+    set widget_list(view_transparent) $transparent
+
+    iwidgets::entryfield $subframe0.view_transpcolor \
+	-width 5 \
+	-validate real \
+	-labeltext "Transparent color:" \
+	-textvariable [ itcl::scope global_list(view_transpcolor) ]
+    pack $subframe0.view_transpcolor -side left -pady 5
+    
+     
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create directionality encoding display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateDirectionDisplayControl { base } {
+    
+    set FA_MAP 5
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Directionally encoded colormaps"
+    pack $base.frame0 -fill both -pady 5 -expand f
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill x -expand f -padx 5 -pady 5
+  
+    set view_direction_filter \
+	[ iwidgets::optionmenu $subframe0.view_direction_filter \
+	      -labeltext "Modulate intensity by:" ]
+    for { set i 0 } { $i < [ llength $global_list(result_title) ] } { incr i } {
+	$view_direction_filter insert $i [ lindex [ lindex $global_list(result_title) $i ] 0 ]
+    }
+    pack $view_direction_filter -side left -padx 5
+    set widget_list(view_direction_filter) $view_direction_filter
+
+    $view_direction_filter select $FA_MAP
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -fill x -expand f -padx 5 -pady 5
+  
+    set view_direction_scheme \
+	[ iwidgets::optionmenu $subframe2.view_direction_scheme -labeltext "Color scheme:" ]
+    set widget_list(view_direction_scheme) $view_direction_scheme
+
+    $view_direction_scheme insert 0 "Absolute value"
+    $view_direction_scheme insert 1 "Rotational symmetry"
+    $view_direction_scheme insert 2 "No symmetry"
+    $view_direction_scheme insert 3 "Mirror symmetry"
+
+    pack $view_direction_scheme -side left -padx 5
+    
+    $view_direction_scheme select 0    
+
+    set subframe3 [ frame $frame0.subframe3 ]
+    pack $subframe3 -fill x -expand f -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe3.view_direction_numcolors \
+	-width 4 \
+	-validate integer \
+	-labeltext "Number of colors for quantization:" \
+	-textvariable [ itcl::scope global_list(view_direction_numcolors) ]
+    pack $subframe3.view_direction_numcolors -side left -padx 5 -pady 5
+
+    set subframe4 [ frame $frame0.subframe4 ]
+    pack $subframe4 -fill x -expand f -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe4.view_direction_satscale \
+	-width 5 \
+	-validate real \
+	-labeltext "Saturation factor:" \
+	-textvariable [ itcl::scope global_list(view_direction_satscale) ]
+    pack $subframe4.view_direction_satscale -side left -padx 5 -pady 5
+    
+    iwidgets::entryfield $subframe4.view_direction_scaling \
+	-width 5 \
+	-validate real \
+	-labeltext "Brightness:" \
+	-textvariable [ itcl::scope global_list(view_direction_scaling) ]
+    pack $subframe4.view_direction_scaling -side left -padx 5 -pady 5
+
+    set view_direction_mask [ checkbutton $subframe4.view_direction_mask \
+				  -text "Use anatomical mask" \
+				  -variable [ itcl::scope global_list(view_direction_mask) ] ]
+    pack $view_direction_mask -side right -pady 5 -padx 5       
+    set widget_list(view_direction_mask) $view_direction_mask
+
+    set subframe1 [ frame $base.subframe1 ]
+    pack $subframe1 -fill both -expand f -padx 5   
+
+    iwidgets::buttonbox $subframe1.decdisplaybbox -orient vertical 
+    $subframe1.decdisplaybbox add display -text "Apply!" -command \
+	[ itcl::code $this view_direction_update_cb ]
+    pack $subframe1.decdisplaybbox -side left -fill x -expand f
+   
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateDisplayControl { base } {
+        
+#    frame $base.dummy -relief sunken -borderwidth 1 -height 2
+#    pack $base.dummy -side top -fill x -expand f -padx 12 -pady 0
+
+    set frame0 [ frame $base.frame0 ]
+    pack $base.frame0 -pady 0 -fill both -expand t 
+    
+    set display_notebook [ iwidgets::tabnotebook $frame0.display_notebook -tabpos n ]     
+    set widget_list(display_notebook) $display_notebook
+    pack $display_notebook -fill both -expand t -pady 5 -padx 5
+    
+    CreateEigenDisplayControl [ $display_notebook add -label "Eigenvectors" ]
+    CreateTensorDisplayControl [ $display_notebook add -label "Hessians" ]
+    CreateDirectionDisplayControl [ $display_notebook add -label "Directionality" ]
+    CreateResultDisplayControl [ $display_notebook add -label "Results" ]
+
+    $display_notebook view "Eigenvectors"   
+}
+
+# ------------------------------------------------------------------------------------------
+#  Create Transform Menu
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateDisplayTransformMenu { menubase } {
+
+    menubutton $menubase.transform -text "Transform" -menu $menubase.transform.m -underline 0
+    pack $menubase.transform -side left
+
+    menu $menubase.transform.m -tearoff 0
+
+    $menubase.transform.m add check -label "Flip X" -underline 0 \
+	-variable [ itcl::scope global_list(tensor_flipx) ] \
+	-command [ itcl::code $this view_update_display_cb ]
+    $menubase.transform.m add check -label "Flip Y" -underline 0 \
+	-variable [ itcl::scope global_list(tensor_flipy) ] \
+	-command [ itcl::code $this view_update_display_cb ]
+    $menubase.transform.m add check -label "Flip Z" -underline 0 \
+	-variable [ itcl::scope global_list(tensor_flipz) ] \
+	-command [ itcl::code $this view_update_display_cb ]
+
+}
+
+# ------------------------------------------------------------------------------------------
+#  Create Colorbar Menu
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateDisplayColorbarMenu { menubase } {  
+
+    menubutton $menubase.colorbar -text "Colorbar" -menu $menubase.colorbar.m -underline 0
+    pack $menubase.colorbar -side left
+
+    menu $menubase.colorbar.m -tearoff 0
+
+    $menubase.colorbar.m add radio -label "Eigenvectors" -underline 0 \
+	-variable [ itcl::scope global_list(view_colorbar) ] \
+	-command [ itcl::code $this view_colorbar_cb ]
+    $menubase.colorbar.m add radio -label "Hessian" -underline 0 \
+	-variable [ itcl::scope global_list(view_colorbar) ] \
+	-command [ itcl::code $this view_colorbar_cb ]
+    $menubase.colorbar.m add radio -label "Results" -underline 0 \
+	-variable [ itcl::scope global_list(view_colorbar) ] \
+	-command [ itcl::code $this view_colorbar_cb ]
+}
+
+# ------------------------------------------------------------------------------------------
+#  Create Visualization Menu
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateDisplayModeMenu { menubase } {  
+    
+    menubutton $menubase.mode -text "Location" -menu $menubase.mode.m -underline 0
+    pack $menubase.mode -side left 
+
+    menu $menubase.mode.m -tearoff 0
+
+    $menubase.mode.m add radio -label "XZ-plane" -underline 0 \
+	-variable [ itcl::scope global_list(view_mode) ] \
+	-command [ itcl::code $this view_mode_cb ]
+    $menubase.mode.m add radio -label "YZ-plane" -underline 0 \
+	-variable [ itcl::scope global_list(view_mode) ] \
+	-command [ itcl::code $this view_mode_cb ]
+    $menubase.mode.m add radio -label "XY-plane" -underline 0 \
+	-variable [ itcl::scope global_list(view_mode) ] \
+	-command [ itcl::code $this view_mode_cb ]
+    $menubase.mode.m add radio -label "3-slice" -underline 0 \
+	-variable [ itcl::scope global_list(view_mode) ] \
+	-command [ itcl::code $this view_mode_cb ]    
+    $menubase.mode.m add separator
+    $menubase.mode.m add radio -label "Volume" -underline 0 \
+	-variable [ itcl::scope global_list(view_mode) ] \
+	-command [ itcl::code $this view_mode_cb ]
+}
+
+# ------------------------------------------------------------------------------------------
+#  Create Visualization Menu
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateDisplayTypeMenu { menubase } {  
+    
+    menubutton $menubase.type -text "View" -menu $menubase.type.m -underline 0
+    pack $menubase.type -side left
+
+    menu $menubase.type.m -tearoff 0
+
+    $menubase.type.m add check -label "Fast eigenvector" -underline 0 \
+	-variable [ itcl::scope global_list(view_type_fast) ] \
+	-command [ itcl::code $this view_type_toggle_fast_eigenvector ]
+    $menubase.type.m add check -label "Medium eigenvector" -underline 0 \
+	-variable [ itcl::scope global_list(view_type_medium) ] \
+	-command [ itcl::code $this view_type_toggle_med_eigenvector ]
+    $menubase.type.m add check -label "Slow eigenvector" -underline 0 \
+	-variable [ itcl::scope global_list(view_type_slow) ] \
+	-command [ itcl::code $this view_type_toggle_slow_eigenvector ]
+    $menubase.type.m add check -label "Hessian" -underline 0 \
+	-variable [ itcl::scope global_list(view_type_tensor) ] \
+	-command [ itcl::code $this view_type_toggle_tensor ]    
+    $menubase.type.m add separator
+    $menubase.type.m add check -label "Colorbar" -underline 0 \
+	-variable [ itcl::scope global_list(view_type_colorbar) ] \
+	-command [ itcl::code $this view_type_toggle_colorbar ]
+}
+
+# -------------------------------------------------------------------------------------------
+#  Diffusion control inititialization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::Initialize { widget } {
+    
+    if { $initialized == 1 } { return $basewidget }
+    
+    #  -------------------------------------
+    #  Create User Interface
+    #  -------------------------------------	
+    set basewidget [toplevel $widget ]
+    wm geometry $basewidget 600x480
+    wm withdraw $basewidget
+
+    set notebook $basewidget.notebook    
+    iwidgets::tabnotebook $notebook -tabpos w         
+    set widget_list(notebook) $notebook
+
+    set mb [ frame $basewidget.mb ]
+    pack $mb -side top -fill x -expand false
+    
+    CreateMenu $mb
+    CreateDisplayTypeMenu $mb
+    CreateDisplayModeMenu $mb
+    CreateDisplayColorbarMenu $mb
+    
+    button $mb.refresh -text "Refresh" -borderwidth 0 \
+	-command [ itcl::code $this view_update_display_cb ] -underline 2
+    pack $mb.refresh -side left -padx 0
+
+    CreateTensorControl     [ $notebook add -label "Hessian" ]
+    CreateVesselControl     [ $notebook add -label "Vesselness" ]
+    CreateResultsControl    [ $notebook add -label "Results" ] 
+    CreateStatisticsControl [ $notebook add -label "Statistics" ]
+    CreateDisplayControl    [ $notebook add -label "Display" ]
+    
+    pack $notebook -side top -fill both -expand t -padx 5
+    $notebook view "Hessian"
+
+    set bottom [ frame $basewidget.bottom -relief ridge]
+    pack $bottom -side top -fill x -expand false
+    
+    set pbar [ frame $basewidget.pbar -width 400 -height 20 ]
+    pack $pbar -side bottom -expand f -fill x
+    CreateProgressBar $pbar
+    
+    set w [ frame $basewidget.w -relief ridge -width 800 ]
+    pack $w -side bottom -fill x -expand false
+    
+    eval "button $w.close -text Close -command { $this DismissWindow }"
+
+    pack $w.close -side right -fill x -padx 5 -pady 10
+    
+    set initialized 1
+    
+    SetTitle $appname
+    
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { $this DismissWindow }"
+
+    return $basewidget 
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create top level menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::CreateMenu { mb } {    
+    
+    menubutton $mb.results       -text Results     -menu $mb.results.m -underline 0
+    pack $mb.results    -side left
+    menubutton $mb.help      -text Help         -menu $mb.help.m -underline 0 -padx 4
+    pack $mb.help  -side right
+
+    menu $mb.results.m -tearoff 0 
+    eval "$mb.results.m add command -label \"Compute All\" -command { $this ComputeResults } -underline 0 -state disabled"
+    $mb.results.m add command -label "Save All Results" -command [ itcl::code $this saveallresults ] -underline 0
+    $mb.results.m add separator
+    if { $parent == 0 } {
+	eval "$mb.results.m add command -label Exit -command {  pxtkexit } -underline 1"
+    } else {
+	eval "$mb.results.m add command -label Close -command {  $this HideWindow } -underline 1"
+    }
+
+    menu $mb.help.m -tearoff 0
+
+    set widget_list(menu_results) $mb.results.m    
+
+    eval "$mb.help.m add command -label About -command { $this AboutCommand }"
+   
+}
+
+#-------------------------------------------------------------------------------------------
+#  Add controls to menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselanalysis::AddToMenuButton { mb args } {
+    eval "$mb add command -label \"Vessel analysis\" -command {$this ShowWindow \"Hessian\"}"
+}
+
+#-------------------------------------------------------------------------------------------
+#  Main function for stand-alone execution
+# ------------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    puts "\n[ file rootname $argv0 ] is not a stand-alone program.\n"
+    exit
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjvesseltool.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjvesseltool.tcl
new file mode 100755
index 0000000..607aa82
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjvesseltool.tcl
@@ -0,0 +1,92 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package require vtkpxcontrib  1.1
+package require vtkmpjcontrib  1.1
+package require pxitclbaseimageviewer 1.0
+package require mpjvesselutility 1.0
+package require mpjvesselanalysis 1.3
+package require mpjvesseltracking 1.0
+
+wm withdraw .
+
+set breg [ pxitclbaseimageviewer \#auto 0 ]
+$breg configure -appname "BioImage Suite::Vessel Tool"
+$breg configure -show_standard_images 1
+$breg configure -enable_helpmenu 0
+$breg configure -enable_multisubjectcontrol 0
+$breg configure -enable_overlaytool 0
+$breg configure -enable_vvlinkgadget  1
+$breg configure -enable_talaraichoption 1
+$breg configure -enable_rendering_on_startup  0
+$breg InitializeDisplay .[pxvtable::vnewobj ] 1
+
+set vesselutil [ mpjvesselutility \#auto $breg ]
+$vesselutil Initialize [ $breg GetBaseWidget ].[ pxvtable::vnewobj ]
+
+#set vesselanal [ mpjvesselanalysis \#auto $breg ]
+#$vesselanal Initialize [ $breg GetBaseWidget ].[ pxvtable::vnewobj ]
+
+set vesseltrack [ mpjvesseltracking \#auto $breg ]
+$vesseltrack Initialize [ $breg GetBaseWidget ].[ pxvtable::vnewobj ]
+
+set menubase [ $breg cget -menubase ]
+set mb [ menu $menubase.vesselm -tearoff 0  ]
+$menubase add cascade  -label "Vascular" -menu $menubase.vesselm -underline 0
+
+$vesselutil AddToMenuButton $mb 
+$vesseltrack AddToMenuButton $mb
+
+$breg AddControl $vesselutil
+$breg AddControl $vesseltrack
+
+$breg CreateHelpMenu
+$breg ShowWindow   
+
+set argc [llength $argv]
+
+if { $argc > 0 } {   $breg LoadImage [lindex $argv 0]   }
+
+
+update idletasks
+[ $breg GetViewer ] SetEnableRendering 1
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjvesseltracking.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjvesseltracking.tcl
new file mode 100644
index 0000000..4193c7e
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjvesseltracking.tcl
@@ -0,0 +1,3421 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package provide mpjvesseltracking 1.0
+
+package require  Itcl 3.2
+package require  Iwidgets 4.0
+
+package require  pxitcllistselector 1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitclbaseimageviewer 1.0
+
+package require  vtkmpjcontrib 1.1
+package require  mpjguilookuptable 1.0
+
+itcl::class mpjvesseltracking {
+
+    inherit pxitclbaseimagecontrol
+    
+    #-----------------------------------
+    # construction and destruction
+    #-----------------------------------
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } { InitializeControl }
+    
+    destructor { }
+
+    #-----------------------------------
+    # global variables
+    #-----------------------------------
+    private variable widget_list
+    private variable global_list
+    
+    #-----------------------------------
+    # initialization methods
+    #-----------------------------------
+    public method Initialize { inpwidg }
+    public method InitializeControl { }
+    public method DismissWindow { }
+    
+    #-----------------------------------
+    # input/output
+    #-----------------------------------
+    public method LoadMap { fname }
+    public method LoadMask { fname }
+    public method LoadTensor { fname }
+    public method LoadSolution { fname }
+    public method SaveAllResults { }
+    public method SaveResult { index }
+    public method ClearAllResults { }
+    public method DisplayResult { index }
+    public method ClearDisplay { }
+    public method SetResultPreffix { preffix }
+    public method GetResultPreffix { } 
+    public method SetCurrentDirectory { fname } 
+    
+    #-----------------------------------
+    # interface creation methods
+    #-----------------------------------
+    private method CreateInputControl { base }
+    private method CreateConnectivityControl { base }
+    private method CreateTrackingControl { base }
+    private method CreateDisplayControl { base }
+    private method CreateFiberControl { base }
+    private method CreateStatisticsControl { base }
+    private method CreateResultsControl { base }
+    private method CreateFiberDisplayControl { base }
+    private method CreateFrontDisplayControl { base }
+    public method AddToMenuButton { mb args}    
+    public method CreateViewMenu { menubase }
+ 
+    private method loadmap { }
+    private method loadtensor { }
+    private method loadmask { }
+    private method loadsolution { }
+    private method displayresult { }
+    private method saveresult { }
+    private method toggleresult { }
+    private method saveallresults { }
+ 
+    private method initialize_glyphs { }
+    private method input_updateinfo { index }    
+    private method input_selectioncommand_cb { }
+        
+    private method track_seedtype_cb { }
+    private method track_integration_cb { }
+    private method track_regionfilter_cb { }
+    private method track_splinetype_cb { }
+    private method track_splinesubdivision_cb { }
+
+    private method view_colorbar_cb { } 
+    private method view_update_display_cb { }
+    private method view_clear_display { }
+    private method view_update_display { }
+    private method view_toggle_colorbar { }
+    private method view_toggle_contour { }
+    private method view_toggle_fiber { }
+    private method view_toggle_gradient { }
+    private method view_toggle_character { }
+
+    private method view_create_fiber_glyph { index }
+    private method view_create_fibers { }
+    private method view_create_colorbar { }
+    private method view_create_contour { }
+    private method view_create_contour_glyph { scalars } 
+    private method view_create_gradient { }
+    private method view_create_gradient_glyph { scalars glyph }
+    private method view_create_character { }
+    private method view_create_character_glyph { scalars vectors glyph }
+
+    private method view_extract_roi { exts image } 
+    private method view_compute_roi_extents { orient dim levels }
+
+    private method solution_method_cb { }
+    private method solution_stopping_cb { }
+    private method solution_autospacing_cb { }
+
+    private method view_fiber_glyph_cb { }    
+    private method view_fiber_tuberadius_cb { }
+    private method view_fiber_pointsize_cb { }
+    private method view_fiber_colormap_cb { }
+    private method view_fiber_filter_cb { }
+    private method view_fiber_luktype_cb { }
+      
+    private method fiber_add { polydata }
+    private method fiber_addwithname { name polydata }
+    private method fiber_remove { index } 
+    private method fiber_removeselected { }
+    private method fiber_clear { }
+    private method fiber_load { }
+    private method fiber_save { index name }
+    private method fiber_saveall { }
+    private method fiber_saveselected { }
+    private method fiber_track { }
+    private method fiber_statistics { }
+    private method fiber_error { }
+    private method fiber_displaypoints { }
+    private method fiber_threshold { }
+    private method fiber_quantize { }
+    private method fiber_addstatistics { title results tag }
+    private method fiber_beginstatistics { title overwrite }
+    private method fiber_savestatistics { }
+    private method fiber_selection_cb { }
+    private method fiber_color_cb { }
+    private method fiber_name_cb { }
+    private method fiber_display_cb { }
+
+    private method result_clear { }
+    private method result_propagate { }
+    private method update_list { node }    
+    public method PropagationCallback { filter comment } 
+
+
+
+
+}  
+
+#-------------------------------------------------------------------------------------------
+#  Close window 
+# -------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::DismissWindow { } {
+    
+    set ok "yes"
+
+    if { $global_list(tensor_fname) != "" } {
+
+	set ok [ tk_messageBox -type yesnocancel -default no \
+		     -parent $basewidget -title "Think again ..." \
+		     -message "Unload all images from memory?" -icon question  ]
+    }
+    
+    if { $ok == "yes" } {	
+
+	fiber_clear
+	
+	view_clear_display 
+	
+	$this ClearAllResults
+	
+	$this SetTitle $global_list(appname)
+	
+	set global_list(mask_fname) ""
+	set global_list(tensor_fname) ""
+	
+    }
+    
+    if { $ok != "cancel" } {
+	$this HideWindow
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  Initialize tool
+# -------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::InitializeControl { } {
+
+    set appname "Vessel Tracking v1.0"
+    set aboutstring "(c) Marcel Jackowski 2006"
+    
+    set global_list(appname) "Vessel Tracking"
+
+    # create list of basic colors
+    set global_list(tkcolor_list) "\#ff0000 \#ffff00 \#00ff00 \#00ffff \#0000ff \#ff00ff"
+    
+    # create image titles
+    set global_list(result_title) \
+	[ list \
+	      { "Hessian matrix"        "hessian" 1 } \
+	      { "Regions of interest"   "mask" 1 } \
+	      { "Map for analysis"      "map" 1 } \
+	      { "Propagation solution"  "solution" 1 } \
+	      { "Propagation gradient"  "solutiongrad" 1 } \
+	      { "Vessel quantization"   "vessel" 1 } ]
+    
+    foreach item $global_list(result_title) {
+ 	lappend result_list [ pxitclimage \#auto ]
+    }  
+    
+    set global_list(result_fdir) [ pwd ]
+    set global_list(result_fpreffix) "preffix_"
+    set global_list(result_list) $result_list
+    
+    set global_list(mask_fname) ""
+    set global_list(mask_nreg) 1
+    
+    set global_list(tensor_fname) ""    
+    set global_list(map_fname) ""
+
+    set global_list(tensor_symm) 1
+        
+    set global_list(solution_fname) ""
+    set global_list(solution_reuse) 0
+    set global_list(solution_usemask) 0
+    set global_list(solution_maxiter) 10
+    set global_list(solution_maxerror) 1.0
+    set global_list(solution_autospacing) 1
+    set global_list(solution_spacingx) 1.0
+    set global_list(solution_spacingy) 1.0
+    set global_list(solution_spacingz) 1.0
+    set global_list(solution_stopping) 0
+    set global_list(solution_stoptime) 1000.0
+    set global_list(solution_error) 0
+    set global_list(solution_errorlabel) "Error: 0.0"
+    set global_list(solution_autospacing) 1
+    set global_list(solution_spacingx) 1.0
+    set global_list(solution_spacingy) 1.0
+    set global_list(solution_spacingz) 1.0
+    set global_list(solution_method) 0
+    set global_list(solution_inf) 32767
+    set global_list(solution_maxintensity) 100
+
+    set global_list(track_seedtype) 0
+    set global_list(track_seedregion) 1
+    set global_list(track_seedwidth) 3
+    set global_list(track_seedheight) 3
+    set global_list(track_seeddepth) 3
+    set global_list(track_seeddens) 1.0  
+    set global_list(track_integration) 0
+    set global_list(track_steplen) 0.25
+    set global_list(track_minspeed) 0.0
+    set global_list(track_maxdist) 100.0
+    set global_list(track_mindist) 10.0
+    set global_list(track_fitspline) 0
+    set global_list(track_splinetype) 0
+    set global_list(track_splinesubdivision) 0
+    set global_list(track_splinelength) 0.1
+    set global_list(track_splinenumber) 100
+    set global_list(track_regionfilter) 0
+    set global_list(track_regionnumber) 1
+    set global_list(track_autostat) 1
+    set global_list(track_flipping) 0
+    set global_list(track_flipx) 0
+    set global_list(track_flipy) 0
+    set global_list(track_flipz) 0
+
+    set global_list(fiber_display) 1
+    set global_list(fiber_color) "\#ff0000"
+    set global_list(fiber_list) {}
+    set global_list(fiber_color_list) {}
+    set global_list(fiber_disp_list) {}
+    
+    set global_list(stat_overwrite) 0
+
+    set global_list(view_colorbar) 0 
+    set global_list(view_colorbar_label) "Label"
+    set global_list(view_fiber) 0
+    set global_list(view_fiber_tuberadius) 0.20
+    set global_list(view_fiber_tuberadiusfactor) 1.0
+    set global_list(view_fiber_varytuberadius) 0
+    set global_list(view_fiber_pointsize) 1.0
+    set global_list(view_contour) 0
+    set global_list(view_contour_levels) 10
+    set global_list(view_contour_from) 0
+    set global_list(view_contour_to) 1000
+    set global_list(view_contour_width) 2.0
+    set global_list(view_gradient) 0
+    set global_list(view_fiber_luktype) 0
+    
+    ## create actors for visualization
+    set global_list(actor_colorbar) -1
+    set global_list(actor_fiber) {}
+    set global_list(actor_contour) [list -1 -1 -1 ]
+    set global_list(actor_gradient) [list -1 -1 -1]
+    set global_list(actor_character) [list -1 -1 -1]
+
+    ## vtk data
+    set global_list(vtk_fiber_tube) {}
+    set global_list(vtk_fiber_polydata) {}
+    
+    initialize_glyphs
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create visualization glyphs
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::initialize_glyphs { } {
+
+    ## create line source
+    set line_src [ vtkLineSource [ pxvtable::vnewobj ] ]
+    $line_src SetPoint1 0.0 0 0
+    $line_src SetPoint2 2.0 0 0    
+
+    set line_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $line_xfrm Translate -1.0 0.0 0.0
+
+    set line [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $line SetInput [ $line_src GetOutput ]
+    $line SetTransform $line_xfrm
+    lappend global_list(glyph_list) $line 
+
+    $line_src Delete
+    $line_xfrm Delete
+    
+    ## create tube source
+    set tube_src [ vtkCylinderSource [ pxvtable::vnewobj ] ]
+    $tube_src SetHeight 2.0
+    $tube_src SetRadius 0.25
+    $tube_src CappingOn
+    
+    set tube_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $tube_xfrm RotateZ -90.0
+    
+    set tube [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $tube SetInput [ $tube_src GetOutput ]
+    $tube SetTransform $tube_xfrm
+    lappend global_list(glyph_list) $tube
+
+    $tube_src Delete
+    $tube_xfrm Delete
+
+    ## create arrow source
+    set arrow_src [ vtkArrowSource [ pxvtable::vnewobj ] ]
+    $arrow_src SetTipLength 0.35
+    $arrow_src SetTipResolution 10
+    $arrow_src SetTipRadius 0.20
+    $arrow_src SetShaftResolution 10
+    $arrow_src SetShaftRadius 0.1
+
+    set arrow_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $arrow_xfrm Translate -1.0 0.0 0.0
+    $arrow_xfrm Scale 2.0 2.0 2.0
+
+    set arrow [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $arrow SetInput [ $arrow_src GetOutput ]
+    $arrow SetTransform $arrow_xfrm
+    lappend global_list(glyph_list) $arrow
+
+    $arrow_src Delete
+    $arrow_xfrm Delete
+    
+    ## create ellipsoid source
+    set ellipsoid_src [ vtkSphereSource [ pxvtable::vnewobj ] ]
+    set ellipsoid_xfrm [ vtkTransform [ pxvtable::vnewobj ] ]
+    $ellipsoid_xfrm Scale 2.0 2.0 2.0
+
+    set ellipsoid [ vtkTransformPolyDataFilter [ pxvtable::vnewobj ] ]
+    $ellipsoid SetInput [ $ellipsoid_src GetOutput ]
+    $ellipsoid SetTransform $ellipsoid_xfrm
+    lappend global_list(glyph_list) $ellipsoid
+
+    $ellipsoid_src Delete
+    $ellipsoid_xfrm Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load tensor
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::loadsolution { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname [tk_getOpenFile -title "Select solution" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadSolution $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in tensor image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::LoadSolution { fname } {
+    
+    set SOLUTION 3
+    set GRADIENT 4
+
+    set sol [ lindex $global_list(result_list) $SOLUTION ]
+    set gradient [ lindex $global_list(result_list) $GRADIENT ]
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in solution image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    $sol SetFromAnalyzeSource $ana    
+    set global_list(solution_fname) $fname
+    set global_list(result_fpreffix) "[file root [file tail $fname] ]_"
+    
+    ## calculate gradient
+    set imgrad [ vtkmpjLevelSetNormal [ pxvtable::vnewobj ] ]
+    $imgrad SetInput [ $sol GetImage ]
+    $this SetFilterCallbacks $imgrad "Calculating gradient..."
+    $imgrad Update
+        
+    ## copy gradient
+    $gradient ShallowCopyImage [ $imgrad GetOutput ]  
+    $gradient CopyImageHeader [ $sol GetImageHeader ]
+        
+    WatchOff
+    
+    $imgrad Delete
+    $ana Delete    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load mask
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::loadmask { } {
+    
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname [tk_getOpenFile -title "Select mask" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadMask $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in mask image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::LoadMask { fname } {
+
+ set MASK 1     
+    set mask [ lindex $global_list(result_list) $MASK ]
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    $this SetFilterCallbacks $ana "Reading in mask image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    ## if mask not a unsigned char image, convert it
+    set scalar_type [ [ $ana GetOutput ] GetScalarType ]    
+
+    if { $scalar_type != 3 } {	
+	
+	set imcast [ vtkImageCast [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $imcast "Converting mask to unsigned char values..."
+	$imcast SetInput [ $ana GetOutput ]
+	$imcast SetOutputScalarTypeToUnsignedChar
+	$imcast ClampOverflowOn	
+	$imcast Update
+	
+	$mask ShallowCopyImage [ $imcast GetOutput ]
+	
+	$imcast Delete
+	
+    } else {
+	
+	$mask SetFromAnalyzeSource $ana
+    }
+   
+    ## determine range of values in mask
+    set range [ [ [ [ $mask GetImage ] GetPointData ] GetScalars ] GetRange ]
+
+    ## take the maximum range as the number of regions in mask
+    set global_list(mask_nreg) [ lindex $range 1 ]    
+    $widget_list(mask_nreg) configure -range [ list 1 $global_list(mask_nreg) ]
+    
+    set global_list(mask_fname) $fname
+
+    WatchOff
+
+    $ana Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load map
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::loadmap { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname [ tk_getOpenFile -title "Select map" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load map into memory
+	LoadMap $fname
+    }    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in map image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::LoadMap { fname } {
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in map image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    [ lindex $global_list(result_list) 2 ] SetFromAnalyzeSource $ana
+    
+    set global_list(map_fname) $fname
+    
+    WatchOff
+    
+    $ana Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load tensor
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::loadtensor { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname [tk_getOpenFile -title "Select hessian" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadTensor $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in tensor image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::LoadTensor { fname } {
+
+    set TENSOR 0
+    set MASK 1
+    set MAP 2
+    set FIBERS 5
+
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    set fibers [ lindex $global_list(result_list) $FIBERS ]
+    set map [lindex $global_list(result_list) $MAP ]
+
+    WatchOn
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading in tensor image..."
+    
+    ## load series 
+    $ana Load $fname 
+
+    $tensor SetFromAnalyzeSource $ana
+
+    set global_list(tensor_fname) $fname
+    
+    ## determine coordinate transform
+    set or [ $ana GetOrientation ]
+    
+    $ana Delete
+
+    scan [ [ $tensor GetImage ] GetDimensions ] "%d %d %d" dx dy dz	       
+    set nc [ [ $tensor GetImage ] GetNumberOfScalarComponents ]
+    set name [ file tail [ file root $fname ] ]
+    
+    set global_list(tensor_symm) [ expr $nc == 6 ]
+    
+    set sufpos [ string last "hessian" $name ]
+    if { $sufpos != -1 } {
+	set name [ string range $name 0 [expr $sufpos - 1] ]
+    }
+
+    ## create fiber image
+    set ext [ vtkImageExtractComponents [ pxvtable::vnewobj ] ]
+    $ext SetInput [ $tensor GetImage ]
+    $ext SetComponents 0
+    $ext Update
+
+    $fibers CopyImageHeader [ $tensor GetImageHeader ]
+    $fibers ShallowCopyImage [ $ext GetOutput ]
+    $ext Delete
+
+    set global_list(result_fdir) [ file dir $fname ]
+    set global_list(result_fpreffix) [ file join $global_list(result_fdir) "${name}" ]
+
+    WatchOff
+
+    $this SetTitle "$global_list(appname): $name (${dx}x${dy}x${dz}, $nc frames)"
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Set result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::SetResultPreffix { preffix } {
+    set global_list(result_fpreffix) $preffix
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Get result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::GetResultPreffix { } {
+    return $global_list(result_fpreffix)
+}
+
+itcl::body mpjvesseltracking::SetCurrentDirectory { fname } {
+    set global_list(result_fdir) $fname
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Clear all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::ClearAllResults { } {
+    
+    foreach result $global_list(result_list) {
+	$result Clear
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::SaveAllResults { } {
+
+    foreach result $global_list(result_list) title $global_list(result_title) {
+	
+	set fname $global_list(result_fpreffix)
+	set fname "$fname[ lindex $title 1 ]"
+	
+	$result Save $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save single result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::SaveResult { index } {        
+
+    set fname $global_list(result_fpreffix)
+    set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]"
+
+    [lindex $global_list(result_list) $index] Save $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::saveallresults { } {
+
+    ## browse for directory
+    set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+    
+    if { $fdir != "" } {
+	
+	set global_list(result_fdir) $fdir
+	
+	foreach result $global_list(result_list) title $global_list(result_title) {
+	    
+	    set fname $global_list(result_fpreffix)
+	    set fname "$fname[ lindex $title 1 ]"
+	    
+	    $result Save [ file join $fdir $fname ]
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::saveresult { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(result_list) getcurselection ]
+    
+    if { $sel_item != "" } { 
+
+	## browse for directory
+	set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+	
+	if { $fdir != "" } {
+	    
+	    set global_list(result_fdir) $fdir
+	    
+	    foreach item $sel_item {
+		
+		set index [ $widget_list(result_list) index $item ]
+		set result [ lindex $global_list(result_list) $index ]
+		
+		set fname $global_list(result_fpreffix)
+		set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]"
+		
+		$result Save [ file join $fdir $fname ]
+	    }
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::DisplayResult { index } {
+    $parent SetImageFromObject \
+	[ [ lindex $global_list(result_list) $index ] GetThisPointer ] $this
+    $parent ShowWindow
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::displayresult { } {
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+	    
+    if { $sel_item != "" } {
+	set index [ $widget_list(result_list) index [ lindex $sel_item 0 ] ]
+	set result [ lindex $global_list(result_list) $index ]
+	
+	$this DisplayResult $index	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: toggle result computation on/off
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::toggleresult { } {
+   
+    set color(0) \#dcdcdc
+    set color(1) black
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+
+    if { $sel_item != "" } {
+
+	set index [ $widget_list(result_list) index [ lindex $sel_item 0 ] ]
+
+	if { $index > 2 } {
+	    set enable [expr 1 - [ lindex [ lindex $global_list(result_title) $index ] 2 ] ]
+	    
+	    $widget_list(result_list) itemconfigure $index -foreground $color($enable)
+	    
+	    set item [ lindex $global_list(result_title) $index ]
+	    set new_item [ lreplace $item 2 2 $enable ]
+	    
+	    set global_list(result_title) [ lreplace $global_list(result_title) \
+						$index $index $new_item ]
+	}
+    }
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::result_clear { } {
+    for { set i 0 } { $i < [ llength $global_list(result_list) ] } { incr i } {		
+	if { $i > 0 } {	    
+	    
+	    set title [ lindex [ lindex $global_list(result_title) $i ] 0 ]	    	    
+	    
+	    if { $title == "Region of interest mask" } {
+		if { $global_list(mask_auto) } {
+		    [ lindex $global_list(result_list) $i ] Clear
+		}
+	    } elseif { $title != "Propagation solution" } {
+		[ lindex $global_list(result_list) $i ] Clear
+	    }
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear display
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_clear_display { } {
+    
+    ## remove fibers
+    foreach actor $global_list(actor_fiber) {	    
+	if { $actor != "-1" } {
+	    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+	    $actor Delete	    
+	}
+	set global_list(actor_fiber) {}
+    }
+    
+    ## remove contours
+    foreach actor $global_list(actor_contour) {	    
+	if { $actor != "-1" } {
+	    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+	    $actor Delete	    
+	}
+	set global_list(actor_contour) [list -1 -1 -1]
+    }
+
+    ## remove colorbar
+    set actor $global_list(actor_colorbar)
+    if { $actor != "-1" } {
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor	    
+	$actor Delete	   
+	set global_list(actor_colorbar) -1
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Update display
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_update_display { } {
+    
+    if { $global_list(view_colorbar) } {
+	view_create_colorbar
+    }
+    
+    if { $global_list(view_contour) } {
+	view_create_contour
+    }
+
+    if { $global_list(view_gradient) } {
+	view_create_gradient
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off colorbar visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_toggle_colorbar { } {
+    
+    if { $global_list(view_colorbar) } {
+	view_create_colorbar
+    } else {
+	set actor $global_list(actor_colorbar)
+	[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] RemoveActor $actor
+	$actor Delete
+
+	set global_list(actor_colorbar) -1
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off contour visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_toggle_contour { } {
+    
+    if { $global_list(view_contour) } {	
+	view_create_contour
+    } else { 
+	foreach actor $global_list(actor_contour) {
+	    if { $actor != "-1" } {
+		for { set j 0 } { $j < 4 } { incr j } {
+		    [ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] RemoveActor $actor
+		}
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_contour) [ list -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off gradient visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_toggle_gradient { } {
+    
+    if { $global_list(view_gradient) } {	
+	view_create_gradient
+    } else { 
+	foreach actor $global_list(actor_gradient) {
+	    if { $actor != "-1" } {
+		for { set j 0 } { $j < 4 } { incr j } {
+		    [ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] RemoveActor $actor
+		}
+		$actor Delete	    
+	    }
+	}
+	set global_list(actor_gradient) [ list -1 -1 -1 ]
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  View fiber bundle
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_create_fiber_glyph { index } {
+
+    set field(0) fractani
+    set field(1) meandiff
+    set field(2) distance
+    set field(3) angle
+    set field(4) roi
+    set field(5) other
+
+    ## create mapper
+    set fiberMapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_fiber_glyph) \
+			index [ $widget_list(view_fiber_glyph) get ] ]
+    
+    ## get current fiber colormap filter    
+#    set filter [ $widget_list(view_fiber_filter) index [ $widget_list(view_fiber_filter) get ]]
+
+    if { $cur_glyph == 1 } {
+	set tube [ lindex $global_list(vtk_fiber_tube) $index ]
+	
+	$tube SetInput [ lindex $global_list(vtk_fiber_polydata) $index ]
+	$tube SetRadius $global_list(view_fiber_tuberadius)
+	$tube SetRadiusFactor $global_list(view_fiber_tuberadiusfactor)
+	$tube SetVaryRadius $global_list(view_fiber_varytuberadius)
+	if { $global_list(view_fiber_varytuberadius) == 1 } {
+	    $tube SetVaryRadiusToVaryRadiusByAbsoluteScalar
+	}
+	$tube SetNumberOfSides 6
+	$tube Update
+
+	$fiberMapper SetInput [ $tube GetOutput ]	
+	$fiberMapper SetLookupTable [ $widget_list(view_fiberluk) GetLookupTable ]
+	$fiberMapper UseLookupTableScalarRangeOn
+	
+	if { $global_list(view_fiber_luktype) == 0 } {
+	    $fiberMapper SetScalarModeToUsePointData
+	} else {
+	    $fiberMapper SetScalarModeToUseCellData
+	}
+
+	#$fiberMapper ColorByArrayComponent $field($filter) 0
+
+	if { $global_list(view_fiber_luk) } {	    
+	    $fiberMapper ScalarVisibilityOn
+	} else {
+	    $fiberMapper ScalarVisibilityOff
+	}
+
+	
+
+    } 
+
+    if { [expr $cur_glyph == 0 || $cur_glyph == 2 ] } {
+	
+	set polydata [ lindex $global_list(vtk_fiber_polydata) $index ]
+	$fiberMapper SetInput $polydata
+	$fiberMapper SetLookupTable [ $widget_list(view_fiberluk) GetLookupTable ]
+	$fiberMapper UseLookupTableScalarRangeOn
+	
+	if { $global_list(view_fiber_luktype) == 0 } {
+	    $fiberMapper SetScalarModeToUsePointData
+	} else {
+	    $fiberMapper SetScalarModeToUseCellData
+	}
+
+	#$fiberMapper SetScalarModeToUseCellData
+	#$fiberMapper ColorByArrayComponent $field($filter) 0
+
+	if { $global_list(view_fiber_luk) } {	    
+	    $fiberMapper ScalarVisibilityOn
+	} else {
+	    $fiberMapper ScalarVisibilityOff
+	}
+    }
+
+
+    ## create actor
+    set fiberActor [ vtkActor [ pxvtable::vnewobj ] ]
+    $fiberActor SetMapper $fiberMapper
+    
+    if { $cur_glyph == 2 } {
+	[ $fiberActor GetProperty ] SetRepresentationToPoints
+	[ $fiberActor GetProperty ] SetPointSize $global_list(view_fiber_pointsize)
+    }
+    
+    $fiberMapper Delete
+    
+    ## convert tk color spec to vtk
+    set color [ lindex $global_list(fiber_color_list) $index ]
+    set red "0x[string range $color 1 2]"
+    set green "0x[string range $color 3 4]"
+    set blue "0x[string range $color 5 6]"
+    set red [ expr [ format "%d" $red ] / 255.0 ]
+    set green [ expr [ format "%d" $green ] / 255.0 ]
+    set blue [ expr [ format "%d" $blue ] / 255.0 ]
+    
+    [ $fiberActor GetProperty ] SetColor $red $green $blue
+    
+#    puts "returning $fiberActor"
+    return $fiberActor
+}
+
+#-------------------------------------------------------------------------------------------
+#  View fibers
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_create_fibers { } {    
+
+    set num [ llength $global_list(fiber_list) ]
+    
+    for {set j 0} {$j < $num} {incr j} {
+	
+	set actor [ view_create_fiber_glyph $j ]
+	
+	lappend global_list(actor_fiber) $actor
+	
+	## add actor if to be displayed
+	if { [ lindex $global_list(fiber_disp_list) $j ] == 1 } { 
+	    for { set k 0 } { $k < 4 } { incr k } {
+		[ [ [ $parent GetViewer ] GetRenderer $k ] GetRenderer ] AddActor $actor	
+	    }
+	}
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  View colorbar
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_create_colorbar { } {
+        
+#    set title [ $widget_list(view_fiber_filter) get ]
+    set title $global_list(view_colorbar_label)
+    
+    set bar [ vtkScalarBarActor [ pxvtable::vnewobj ] ]
+    $bar SetLookupTable [ $widget_list(view_fiberluk) GetLookupTable ]
+    
+    $bar SetTitle $title
+    [$bar GetPositionCoordinate] SetCoordinateSystemToNormalizedViewport
+    [$bar GetPositionCoordinate] SetValue 0.1 0.01
+    $bar SetOrientationToHorizontal
+    $bar SetWidth 0.8
+    $bar SetHeight 0.12
+    
+    set global_list(actor_colorbar) $bar
+    
+    [ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor2D $bar    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Compute ROI extents
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_compute_roi_extents { orient dim levels } {
+   
+    set x0(0) 0; set x0(1) 0; set x0(2) 0;
+    set x1(0) [expr [lindex $dim 0] -1]
+    set x1(1) [expr [lindex $dim 1] -1]
+    set x1(2) [expr [lindex $dim 2] -1]
+    
+    if { $orient < 3 } {
+
+	## set up slice geometry
+	for { set i 0 } { $i < 3 } { incr i } {
+	    if { $i == $orient } {
+		set x0($i) [lindex $levels $i]
+		set x1($i) [lindex $levels $i]
+	    }
+	}
+    }
+    
+    return "$x0(0) $x0(1) $x0(2) $x1(0) $x1(1) $x1(2)"
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Extract ROI given image and computed extents
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_extract_roi { exts image } {
+    
+    set dim [ [ $image GetImage ] GetDimensions ]
+    set spac [ [ $image GetImage ] GetSpacing ]
+    set orig [ [ $image GetImage ] GetOrigin ]
+    set ospac "1 1 1"
+    
+    set x0(0) [lindex $exts 0]; set x0(1) [lindex $exts 1]; set x0(2) [lindex $exts 2];
+    set x1(0) [lindex $exts 3]; set x1(1) [lindex $exts 4]; set x1(2) [lindex $exts 5];
+    
+    ## determine correct origin and spacing
+    for { set i 0 } { $i <= 2 } { incr i } {	
+ 	if { $x1($i) < $x0($i) } { set x1($i) [ expr $x0($i) +1 ] }
+ 	set dx [ lindex $ospac $i ]
+ 	if { $dx < 1 } { set dx 1 } elseif { $dx > 10 } { set dx 10 }	
+ 	set origin($i)  [ expr [lindex $orig $i ] + $x0($i) * [ lindex $spac $i ]]
+ 	set spacing($i) [ expr [lindex $spac $i ] * $dx ]
+ 	set ext($i)     [ expr ($x1($i)-$x0($i))/$dx ]
+    }
+
+    set identity [ vtkIdentityTransform [ pxvtable::vnewobj ] ]
+
+    ## extract roi
+    set roi [ vtkbisImageReslice [ pxvtable::vnewobj ] ]
+    $roi SetInput [ $image GetImage ]
+    $roi SetResliceTransform $identity
+    $roi SetOutputSpacing $spacing(0) $spacing(1) $spacing(2)
+    $roi SetOutputOrigin $origin(0)  $origin(1)  $origin(2)    
+    $roi SetOutputExtent 0 $ext(0) 0 $ext(1) 0 $ext(2)
+    $roi SetInterpolationMode 0 
+    $roi Update
+
+    $identity Delete
+
+    return $roi
+}
+
+#-------------------------------------------------------------------------------------------
+#  View contour
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_create_contour_glyph { scalars } {
+        
+    set range [ [ $widget_list(view_frontluk) GetLookupTable ] GetTableRange ]
+    set global_list(view_contour_from) [ lindex $range 0 ]
+    set global_list(view_contour_to) [ lindex $range 1 ]
+    
+    set contour [ vtkMarchingContourFilter [ pxvtable::vnewobj ] ]
+    $contour SetInput $scalars
+    $contour GenerateValues $global_list(view_contour_levels) $global_list(view_contour_from) $global_list(view_contour_to)
+    $contour Update
+    
+    set contourMapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    $contourMapper SetInput [ $contour GetOutput ]
+    $contourMapper SetLookupTable [ $widget_list(view_frontluk) GetLookupTable]
+    $contourMapper UseLookupTableScalarRangeOn
+    $contourMapper ScalarVisibilityOn
+    
+    ## create contour actor
+    set contourActor [ vtkActor [ pxvtable::vnewobj ] ]
+    $contourActor SetMapper $contourMapper
+    [ $contourActor GetProperty ] SetLineWidth $global_list(view_contour_width)
+    $contourMapper Delete
+
+    $contour Delete
+
+    return $contourActor
+}
+
+#-------------------------------------------------------------------------------------------
+#  View contour
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_create_contour { } {
+    
+    set SOLUTION 3
+    set solution [ lindex $global_list(result_list) $SOLUTION ]
+
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    if { $levels == "" } {
+	::pxtclutil::Warning "No image in the viewer. The tracking algorithm uses the current viewer crossharis for initialization"
+	return
+    }
+    
+    set dims [ [ $solution GetImage ] GetDimensions ]
+    
+    ## plot on slices
+    for { set i 0 } { $i < 3 } { incr i } {
+	
+	set ext [ view_compute_roi_extents $i $dims $levels ]
+	set scalars [ [ view_extract_roi $ext $solution ] GetOutput ]
+	
+	set actor [ view_create_contour_glyph $scalars ]
+	set global_list(actor_contour) [ lreplace $global_list(actor_contour) $i $i $actor ]
+	
+	$scalars Delete
+	
+	for { set j 0 } { $j < 4 } { incr j } {
+	    [ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] AddActor $actor	
+	}
+    }    
+}
+
+#-------------------------------------------------------------------------------------------
+#  View gradient
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_create_gradient_glyph { scalars glyph } {    
+    
+    ## compute gradient of propagation map
+#    set imgrad [ vtkImageGradient [ pxvtable::vnewobj ] ]
+#    $imgrad SetInput $scalars
+#    $imgrad SetDimensionality 3
+#    $imgrad Update
+    
+    ## convert into vector field
+    set imtovec [ vtkmpjImageToVectors [ pxvtable::vnewobj ] ]
+    $imtovec SetInput $scalars
+    $imtovec Update
+    
+    ## merge data
+    set merge [ vtkMergeFilter [ pxvtable::vnewobj ] ]
+    $merge SetGeometry $scalars
+    $merge SetVectors [ $imtovec GetOutput ]
+    $merge SetScalars $scalars
+    $merge Update
+    
+#    $imgrad Delete
+    $imtovec Delete
+    
+    ## create glypher field   
+    set glypher [ vtkGlyph3D [ pxvtable::vnewobj ] ] 
+    $glypher SetInput [ $merge GetOutput ]
+    $glypher SetSource [ $glyph GetOutput ]
+    $glypher ScalingOn
+    $glypher ClampingOn
+    #    $glypher SetScaleFactor $global_list(view_eigen_maxscale)
+    $glypher SetScaleModeToDataScalingOff
+    $glypher SetVectorModeToUseVector
+    $glypher Update
+    
+    ## set up glyph mapper
+    set glyphMapper [ vtkPolyDataMapper [ pxvtable::vnewobj ] ]
+    $glyphMapper SetInput [ $glypher GetOutput ]
+    #$glyphMapper SetLookupTable [ $widget_list(view_fiberluk) GetLookupTable ]
+    #$glyphMapper UseLookupTableScalarRangeOn
+    $glyphMapper ScalarVisibilityOff
+    
+    ## create glyph actor
+    set glyphActor [ vtkActor [ pxvtable::vnewobj ] ]
+    $glyphActor SetMapper $glyphMapper
+    [ $glyphActor GetProperty ] SetColor 0.0 1.0 1.0
+    
+    $glypher Delete
+    $glyphMapper Delete
+    
+    return $glyphActor
+}
+
+#-------------------------------------------------------------------------------------------
+#  View gradient
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_create_gradient { } {
+    
+    set GRADIENT 4
+    set gradient [ lindex $global_list(result_list) $GRADIENT ]
+
+    ## get current slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set dims [ [ $gradient GetImage ] GetDimensions ]
+    
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_fiber_glyph) index [ $widget_list(view_fiber_glyph) get ] ]
+    set glyph_source [ lindex $global_list(glyph_list) 0 ]
+    
+    ## plot on slices
+    for { set i 0 } { $i < 3 } { incr i } {
+	
+	set ext [ view_compute_roi_extents $i $dims $levels ]
+	set scalars [ [ view_extract_roi $ext $gradient ] GetOutput ]
+	
+	set actor [ view_create_gradient_glyph $scalars $glyph_source ]
+	set global_list(actor_gradient) [ lreplace $global_list(actor_gradient) $i $i $actor ]
+	
+	$scalars Delete
+
+	for { set j 0 } { $j < 4 } { incr j } {
+	    [ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] AddActor $actor	
+	}
+    }    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in solution methods
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::solution_method_cb { } {
+    set global_list(solution_method) \
+	[ $widget_list(solution_method) index [ $widget_list(solution_method) get ] ]    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in solution spacing
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::solution_autospacing_cb { } {
+    set state(0) disabled; set state(1) normal        
+    $widget_list(solution_spacingx) configure -state \
+	$state([expr 1 -$global_list(solution_autospacing)])     
+    $widget_list(solution_spacingy) configure -state \
+	$state([expr 1 -$global_list(solution_autospacing)]) 
+    $widget_list(solution_spacingz) configure -state \
+	$state([expr 1 -$global_list(solution_autospacing)])
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in solution spacing
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::solution_stopping_cb { } {
+    set state(0) disabled; set state(1) normal   
+    $widget_list(solution_stoptime) configure -state \
+	$state($global_list(solution_stopping)) 
+    $widget_list(solution_inf) configure -state \
+	$state($global_list(solution_stopping)) 
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in seed type
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::track_seedtype_cb { } {
+
+    set state(0) disabled; set state(1) normal    
+    set global_list(track_seedtype) \
+	[ $widget_list(track_seedtype) index [ $widget_list(track_seedtype) get ] ]
+
+    if { $global_list(track_seedtype) < 2 } {
+	$widget_list(track_seedwidth) configure -state disabled
+	$widget_list(track_seedheight) configure -state disabled
+	$widget_list(track_seeddepth) configure -state disabled
+	if { $global_list(track_seedtype) == 1 } {
+	    $widget_list(track_seeddens) configure -state normal
+	} else {
+	    $widget_list(track_seeddens) configure -state disabled
+	}
+    } else {
+	$widget_list(track_seedwidth) configure -state normal
+	$widget_list(track_seedheight) configure -state normal
+	$widget_list(track_seeddepth) configure -state normal
+	$widget_list(track_seeddens) configure -state normal
+    }
+    
+    if { $global_list(track_seedtype) == 1 } {
+	$widget_list(track_seedregion) configure -state normal
+    } else {
+	$widget_list(track_seedregion) configure -state disabled	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in region filtering option
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::track_regionfilter_cb { } {
+
+    set state(1) normal
+    set state(0) disabled
+
+    $widget_list(track_regionnumber) configure -state \
+	$state($global_list(track_regionfilter))
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in integration
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::track_integration_cb { } {
+    set global_list(track_integration) \
+	[ $widget_list(track_integration) index [ $widget_list(track_integration) get ] ]
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in spline types
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::track_splinetype_cb { } {
+    set global_list(track_splinetype) \
+	[ $widget_list(track_splinetype) index [ $widget_list(track_splinetype) get ] ]
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in spline subdivision
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::track_splinesubdivision_cb { } {
+    set global_list(track_splinesubdivision) \
+	[ $widget_list(track_splinesubdivision) index [ $widget_list(track_splinesubdivision) get ] ]
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon an update button press
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_update_display_cb { } { 
+    
+    view_clear_display
+    view_update_display
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in bundle radius
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_fiber_tuberadius_cb { } {
+    
+    foreach item $global_list(vtk_fiber_tube) {
+	$item SetRadius $global_list(view_fiber_tuberadius)
+	$item SetRadiusFactor $global_list(view_fiber_tuberadiusfactor)
+	$item SetVaryRadius $global_list(view_fiber_varytuberadius)
+	if { $global_list(view_fiber_varytuberadius) == 1 } {
+	    $item SetVaryRadiusToVaryRadiusByAbsoluteScalar
+	}
+	$item Update
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in point size
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_fiber_pointsize_cb { } {
+    
+    foreach actor $global_list(actor_fiber) {
+	[ $actor GetProperty ] SetPointSize $global_list(view_fiber_pointsize)
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in colormap for fibers
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_fiber_colormap_cb { } {
+    
+    foreach \
+	actor $global_list(actor_fiber) {
+	    
+	    ## create mapper
+	    set fiberMapper [ $actor GetMapper ]
+
+	    if { $global_list(view_fiber_luk) } {
+		$fiberMapper ScalarVisibilityOn
+	    } else {
+		$fiberMapper ScalarVisibilityOff
+	    }
+
+	    if { $global_list(view_fiber_luktype) == 0 } {
+		$fiberMapper SetScalarModeToUsePointData
+	    } else {
+		$fiberMapper SetScalarModeToUseCellData
+	    }
+	    
+
+	}
+    
+      [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in bundle glyph
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_fiber_glyph_cb { } {
+    
+    ## get current glyph
+    set cur_glyph [ $widget_list(view_fiber_glyph) \
+			index [ $widget_list(view_fiber_glyph) get ] ]
+    
+    foreach \
+	actor $global_list(actor_fiber) \
+	tube $global_list(vtk_fiber_tube) \
+	polydata $global_list(vtk_fiber_polydata) {
+	    
+	    ## create mapper
+	    set fiberMapper [ $actor GetMapper ]
+	    
+	    if { $cur_glyph == 1 } {
+		
+		$tube SetInput $polydata
+		$tube SetRadius $global_list(view_fiber_tuberadius)
+		$tube SetRadiusFactor $global_list(view_fiber_tuberadiusfactor)
+		$tube SetVaryRadius $global_list(view_fiber_varytuberadius)
+		if { $global_list(view_fiber_varytuberadius) == 1 } {
+		    $tube SetVaryRadiusToVaryRadiusByAbsoluteScalar
+		}
+		$tube SetNumberOfSides 6
+		$tube Update
+		
+		$fiberMapper SetInput [ $tube GetOutput ]
+
+		if { $global_list(view_fiber_luktype) == 0 } {
+		    $fiberMapper SetScalarModeToUsePointData
+		} else {
+		    $fiberMapper SetScalarModeToUseCellData
+		}
+	    		
+		if { $global_list(view_fiber_luk) } {
+		    $fiberMapper ScalarVisibilityOn
+		} else {
+		    $fiberMapper ScalarVisibilityOff
+		}
+
+		
+		
+	    } else {
+		
+		$fiberMapper SetInput $polydata
+
+		if { $global_list(view_fiber_luktype) == 0 } {
+		    $fiberMapper SetScalarModeToUsePointData
+		} else {
+		    $fiberMapper SetScalarModeToUseCellData
+		}
+		
+		if { $global_list(view_fiber_luk) } {
+		    $fiberMapper ScalarVisibilityOn
+		} else {
+		    $fiberMapper ScalarVisibilityOff
+		}
+				
+	    }
+	    
+	    if { $cur_glyph == 2 } {
+		[ $actor GetProperty ] SetRepresentationToPoints
+		[ $actor GetProperty ] SetPointSize $global_list(view_fiber_pointsize)
+	    } else {
+		[ $actor GetProperty ] SetRepresentationToSurface 
+	    }
+
+	}
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in fiber filter selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_fiber_filter_cb { } {
+    
+    set field(0) validity
+
+    ## current fiber colormap filter    
+    set filter [ $widget_list(view_fiber_filter) index [ $widget_list(view_fiber_filter) get ]]    
+    
+    foreach \
+	actor $global_list(actor_fiber) {	    
+	    
+	    ## create mapper
+	    #set fiberMapper [ $actor GetMapper ]	   	    
+	    #$fiberMapper SetScalarModeToUsePointFieldData
+	    #$fiberMapper ColorByArrayComponent $field($filter) 0
+	}
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in fiber filter selection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_fiber_luktype_cb { } {
+    
+    ## current fiber colormap filter    
+    set filter [ $widget_list(view_fiber_luktype) index [ $widget_list(view_fiber_luktype) get ]]    
+    set global_list(view_fiber_luktype) $filter
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  Toggle On/Off fiber visualization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::view_toggle_fiber { } {
+    
+    if { $global_list(view_fiber) } {	
+	view_create_fibers	
+    } else { 
+	foreach \
+	    actor $global_list(actor_fiber) \
+	    disp $global_list(fiber_disp_list) {
+		if { $disp == 1 } {
+		    for { set j 0 } { $j < 4 } { incr j } {
+			[ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] RemoveActor $actor	
+		    }
+		}
+		$actor Delete	    
+	    }
+	set global_list(actor_fiber) {}
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in bundle color
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_color_cb { } {
+
+    set new_color [ tk_chooseColor -initialcolor $global_list(fiber_color) ]
+    
+    if { [ llength $new_color ] > 0 } {
+	
+	set global_list(fiber_color) $new_color
+	set fiber_color [ image create photo -width 15 -height 15 ]
+	$fiber_color put $global_list(fiber_color) -to 0 0 15 15	
+	$widget_list(fiber_color) configure -image $fiber_color
+	
+	## get current selection 
+	set sel_item [ $widget_list(fiber_list) getcurselection ]
+	
+	if { $sel_item != "" } {
+	    
+	    set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	    set global_list(fiber_color_list) \
+		[ lreplace $global_list(fiber_color_list) $sel_index $sel_index $new_color ]
+	    
+	    ## convert tk color spec to vtk
+	    set color $new_color
+	    set red "0x[string range $color 1 2]"
+	    set green "0x[string range $color 3 4]"
+	    set blue "0x[string range $color 5 6]"
+	    set red [ expr [ format "%d" $red ] / 255.0 ]
+	    set green [ expr [ format "%d" $green ] / 255.0 ]
+	    set blue [ expr [ format "%d" $blue ] / 255.0 ]
+	    
+	    set fiberActor [ lindex $global_list(actor_fiber) $sel_index ]
+	    [$fiberActor GetProperty] SetColor $red $green $blue
+
+	    [ $parent GetViewer ] UpdateDisplay	    
+	    
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon selection of bundles
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_selection_cb { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	set sel_input [ lindex $global_list(fiber_list) $sel_index ]
+	
+	## get number of components
+	set global_list(fiber_name) $sel_input
+	set global_list(fiber_color) [ lindex $global_list(fiber_color_list) $sel_index ]
+	set global_list(fiber_display) [ lindex $global_list(fiber_disp_list) $sel_index ]
+
+	set fiber_color [ image create photo -width 15 -height 15 ]
+	$fiber_color put $global_list(fiber_color) -to 0 0 15 15	
+	$widget_list(fiber_color) configure -image $fiber_color
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in bundle name
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_name_cb { } {
+
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	set new_name [ $widget_list(fiber_name) get ]
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	set global_list(fiber_list) \
+	    [ lreplace $global_list(fiber_list) $sel_index $sel_index $new_name ]
+	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon change in bundle display option
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_display_cb { } {
+
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	puts "$sel_index"
+
+	set global_list(fiber_disp_list) \
+	    [ lreplace $global_list(fiber_disp_list) $sel_index $sel_index \
+		  $global_list(fiber_display) ]
+	
+	set actor [ lindex $global_list(actor_fiber) $sel_index ]
+	
+	if { $global_list(fiber_display) } {
+	    for { set j 0 } { $j < 4 } { incr j } {
+		[ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] AddActor $actor	
+	    }
+	} else {
+	    for { set j 0 } { $j < 4 } { incr j } {
+		[ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] RemoveActor $actor	
+	    }
+	}
+	
+	[ $parent GetViewer ] UpdateDisplay	    
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Add bundle with a given name
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_addwithname { name polydata } {
+
+    ## insert new fiber set
+    set num_fibers [ llength $global_list(fiber_list) ]
+    set next_color [lindex $global_list(tkcolor_list) [expr int(fmod($num_fibers,6))]]
+    
+    set global_list(fiber_color) $next_color
+    set global_list(fiber_display) 1
+
+    set fiber_color [ image create photo -width 15 -height 15 ]
+    $fiber_color put $global_list(fiber_color) -to 0 0 15 15	
+    $widget_list(fiber_color) configure -image $fiber_color
+    
+    set global_list(fiber_name) $name
+    lappend global_list(fiber_list) $global_list(fiber_name)
+    lappend global_list(fiber_disp_list) $global_list(fiber_display)    
+    lappend global_list(fiber_color_list) $global_list(fiber_color)
+    lappend global_list(vtk_fiber_polydata) $polydata	    
+    lappend global_list(vtk_fiber_tube) [ vtkmpjTubeFilter [ pxvtable::vnewobj ] ]
+ 
+    $widget_list(fiber_list) selection clear 0 end
+    $widget_list(fiber_list) selection set $num_fibers $num_fibers
+
+    return $num_fibers
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Add fiber
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_add { polydata } {
+
+    ## insert new fiber
+    set num_fibers [ llength $global_list(fiber_list) ]
+    set name "Bundle_[expr $num_fibers + 1]"
+    
+    set index [ fiber_addwithname $name $polydata ]
+    
+    return $index
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear all fibers
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_clear { } {
+    
+    set num_fibers [ llength $global_list(fiber_list) ]
+    for { set i 0 } { $i < $num_fibers } { incr i } { 
+	fiber_remove 0
+    }
+    
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Remove fiber
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_remove { index } {
+
+    if { $global_list(view_fiber) } {
+	set display [ lindex $global_list(fiber_disp_list) $index ]
+	if { $display } {
+	    set actor [ lindex $global_list(actor_fiber) $index ]
+	    for { set j 0 } { $j < 4 } { incr j } {
+		[ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] RemoveActor $actor	
+	    }
+	    $actor Delete
+	}
+    }
+    
+    set global_list(fiber_list) \
+	[ lreplace $global_list(fiber_list) $index $index ]
+    set global_list(fiber_color_list) \
+	[ lreplace $global_list(fiber_color_list) $index $index ]
+    set global_list(fiber_disp_list) \
+	[ lreplace $global_list(fiber_disp_list) $index $index ]
+    
+    set polydata [ lindex $global_list(vtk_fiber_polydata) $index ]
+    $polydata Delete
+    
+    set tube [ lindex $global_list(vtk_fiber_tube) $index ]
+    $tube Delete
+
+    set global_list(actor_fiber) \
+	[ lreplace $global_list(actor_fiber) $index $index ]
+    set global_list(vtk_fiber_tube) \
+	[ lreplace $global_list(vtk_fiber_tube) $index $index ]
+    set global_list(vtk_fiber_polydata) \
+	[ lreplace $global_list(vtk_fiber_polydata) $index $index ]
+    
+    set num_fibers [ llength $global_list(fiber_list) ]
+    
+    if { $num_fibers > 0 } {
+	
+	$widget_list(fiber_list) selection clear 0 end
+	
+	if { $index < $num_fibers } {
+	    $widget_list(fiber_list) selection set $index $index
+	} else {
+	    $widget_list(fiber_list) selection set \
+		[expr $num_fibers -1] [expr $num_fibers -1]
+	}
+	
+	fiber_selection_cb
+	
+    } else {
+	
+	set global_list(fiber_fname) ""
+	set global_list(fiber_display) 1
+	set global_list(fiber_name) ""
+	set global_list(fiber_color) [ lindex $global_list(tkcolor_list) 0 ]
+	set fiber_color [ image create photo -width 15 -height 15 ]
+	$fiber_color put $global_list(fiber_color) -to 0 0 15 15	
+	$widget_list(fiber_color) configure -image $fiber_color
+    }
+
+    [ $parent GetViewer ] UpdateDisplay
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Remove selected bundle
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_removeselected { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	fiber_remove $sel_index
+	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: load fiber
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_load { } {
+    
+    set fname  [tk_getOpenFile -title "Select Vessel file" -filetypes { {"Vessels" {.vtk}}} -initialdir $global_list(result_fdir) -parent $basewidget ] 
+
+    ## browse for filename
+    if { $fname != "" } { 
+	
+	## open fiber file
+	set fibr [ vtkPolyDataReader [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $fibr "Reading vessel..."
+	$fibr SetFileName $fname
+	$fibr Update
+	
+	set polydata [ vtkPolyData [ pxvtable::vnewobj ] ]
+	$polydata ShallowCopy [ $fibr GetOutput ]
+	
+	$fibr Delete
+	
+	set index [ fiber_addwithname [ file root [ file tail $fname ] ] $polydata ]
+	
+	## keep fname
+	set global_list(fiber_fname) $fname
+
+	if { $global_list(view_fiber) } {	
+	    
+	    set actor [ view_create_fiber_glyph $index ]
+	    lappend global_list(actor_fiber) $actor
+	    
+	    ## add actor if to be displayed
+	    if { [ lindex $global_list(fiber_disp_list) $index ] == 1 } { 
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+	    }
+	}
+	
+#	if { $global_list(view_fiber) } {	
+#	    view_create_fibers	
+#	} 
+    }	
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: save individual fiber 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_save { index name } {
+    
+    set polydata [ lindex $global_list(vtk_fiber_polydata) $index ]
+    
+    set fibw [ vtkPolyDataWriter [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $fibw "Saving vessel..."
+
+    $fibw SetFileName $name
+    $fibw SetInput $polydata
+    $fibw Write	
+    
+    $fibw Delete    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: save selected fiber
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_saveselected { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## browse for directory
+	set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+	
+	## browse for directory
+	if { $fdir != "" } {
+	    	    
+	    ## get current index
+	    set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	    
+	    set item [ lindex $global_list(fiber_list) $sel_index ]	
+	    
+	    fiber_save $sel_index [ file join $fdir "$item.vtk" ]	
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: save all fibers
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_saveall { } {
+    
+    ## browse for directory
+    set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+    
+    ## browse for directory
+    if { $fdir != "" } { 
+	
+	## get number of fiber bundles
+	set num [ llength $global_list(fiber_list) ]
+	
+	## save all fibers
+	for { set i 0 } { $i < $num } { incr i } {	
+	    set item [ lindex $global_list(fiber_list) $i ]	
+	    fiber_save $i [ file join $fdir "$item.vtk" ]	
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_savestatistics { } {
+
+    set statfname $global_list(result_fpreffix)
+    set initfname "${statfname}stat"
+    set initfname [ file join $global_list(result_fdir) $initfname ]
+
+    ## browse for filename
+    set fname  [tk_getSaveFile -title "Save statistics"\
+		    -filetypes {{"Text" {.txt*}}} \
+		    -parent $basewidget \
+		    -defaultextension ".txt" \
+		    -initialfile $initfname ]  
+    
+    if { [ string length $fname ] < 1 } {
+	return 0
+    }
+    
+    $widget_list(stat_text) export $fname
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: compute fiber statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_beginstatistics { title overwrite } {   
+    
+    if { $overwrite } {
+	$widget_list(stat_text) delete 1.0 end
+    }    
+
+    $widget_list(stat_text) insert \
+	end "-----------------------+------------+------------+------------+------------+------------\n" even
+    $widget_list(stat_text) insert \
+	end "$title      MIN          MAX         MEAN        VARIANCE      STD DEV\n" odd
+    $widget_list(stat_text) insert \
+	end "-----------------------+------------+------------+------------+------------+------------\n" even
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: compute fiber statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_addstatistics { title results tag } {   
+    
+    set min  [ format %8.4f [ lindex $results 0 ] ]
+    set max  [ format %8.4f [ lindex $results 1 ] ]
+    set mean [ format %8.4f [ lindex $results 2 ] ]
+    set var  [ format %8.4f [ lindex $results 3 ] ]
+    set dev  [ format %8.4f [ lindex $results 4 ] ]
+    
+    $widget_list(stat_text) insert end " $title |  $min  |  $max  |  $mean  |  $var  |  $dev  \n" $tag
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: compute fiber statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_error { } {
+
+    ## get current selection     
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+
+    if { $sel_item != "" } {
+	
+	## get current index
+	set target_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ]
+
+	set dist [ vtkmpjStreamlineDistance [ pxvtable::vnewobj ] ]
+	$dist SetReference [ lindex $global_list(vtk_fiber_polydata) 0 ]
+	$dist SetTarget [ lindex $global_list(vtk_fiber_polydata) $target_index ]
+	$dist SetReferenceIndex 0
+	$dist SetTargetIndex 0
+	$dist Update
+	
+	puts "Min dist: [ $dist GetMinimum ]"
+	puts "Max dist: [ $dist GetMaximum ]"
+	puts "Mean dist: [ $dist GetMean ]"
+	
+	set polydata [ vtkPolyData [ pxvtable::vnewobj ] ]
+	$polydata ShallowCopy [ $dist GetOutput ]
+	
+	$dist Delete
+	
+	set index [ fiber_addwithname "Error" $polydata ]
+
+	if { $global_list(view_fiber) } {	
+	    
+	    set actor [ view_create_fiber_glyph $index ]
+	    lappend global_list(actor_fiber) $actor
+	    
+	    ## add actor if to be displayed
+	    if { [ lindex $global_list(fiber_disp_list) $index ] == 1 } { 
+		[ [ [ $parent GetViewer ] GetRenderer 3 ] GetRenderer ] AddActor $actor
+	    }
+	}
+    }
+}
+
+itcl::body mpjvesseltracking::fiber_displaypoints { } {
+
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	## get vessel polydata
+	set vessel [ lindex $global_list(vtk_fiber_polydata) $sel_index ] 
+
+	set num_points [[$vessel GetPoints] GetNumberOfPoints]
+
+	puts "num_points=$num_points"
+
+	for { set i 0 } { $i < $num_points } { incr i } {
+	    
+	    set point [ [ $vessel GetPoints ] GetPoint $i ]
+
+	    set x [ lindex $point 0 ]
+	    set y [ lindex $point 1 ]
+	    set z [ lindex $point 2 ]
+
+	    set dist [expr sqrt(($x-30)*($x-30)+($y-30)*($y-30)+($z-30)*($z-30))]
+
+	    puts "$dist"
+
+	}
+
+    }
+	
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: compute fiber statistics
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_statistics { } {
+
+    set FIBERS 5
+
+    set fiber_image [ lindex $global_list(result_list) $FIBERS ] 
+
+    $widget_list(notebook) view "Statistics"
+    
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	## name
+	set item [ lindex $global_list(fiber_list) $sel_index ]	
+	
+	# compute fiber statistics
+	set fstat [ vtkmpjVectorStreamlineStatistics [ pxvtable::vnewobj ] ]
+	$fstat SetInput [ lindex $global_list(vtk_fiber_polydata) $sel_index ]
+	$fstat Update
+	
+	set vol "n/a"
+	set volmm "n/a"
+
+	#if { [ $fiber_image GetImageSize ] > 1 } {
+	    
+	    ## quantize fibers
+	    #set quant [ vtkmpjStreamlineQuantization [ pxvtable::vnewobj ] ]
+	    #$quant SetInput [ lindex $global_list(vtk_fiber_polydata) $sel_index ]
+	    #$quant SetImage [ $fiber_image GetImage ]
+	    #$quant SetMaskValue 1.0
+	    #$quant Update
+	    
+	    #$fiber_image ShallowCopyImage [ $quant GetOutput ]
+
+	    ## get volume 
+	    #set vol [ $quant GetNumberOfVoxels ]
+
+	    ## get spacing information
+	    #scan [ [ $fiber_image GetImage ] GetSpacing ] "%f %f %f" spc0 spc1 spc2
+
+	    ## calculate volume in mm
+	    #set volmm [ expr $vol * $spc0 * $spc1 * $spc2 ]
+	    #set volmm [ format %6.2f $volmm ]
+
+	    #$quant Delete
+	#}
+	
+	## Write out stats
+	set textlist [  $widget_list(stat_text) component text ]
+	$textlist tag configure even -background "\#e0e0ff"
+	
+	set strlen [ string length $item ]
+	if { $strlen > 23 } {
+	    set item [ string range $item 0 22 ]
+	} else {
+	    set spc [ string repeat " " [ expr (23 - $strlen) / 2 ] ] 
+	    set item [ string range "$spc$item$spc" 0 22 ]
+	}
+
+	fiber_beginstatistics $item $global_list(stat_overwrite)
+
+	set min [ $fstat GetMinimum ]
+	set max [ $fstat GetMaximum ]
+	set mean [ $fstat GetMean ]
+	set var [ $fstat GetVariance ]
+	set dev [ expr sqrt($var) ]
+
+	set result [ list $min $max $mean $var $dev ]
+	fiber_addstatistics "Validity index" $result odd
+
+	$widget_list(stat_text) insert \
+	    end "-----------------------+------------+------------+------------+------------+------------\n" even
+
+	set num [ $fstat GetNumberOfFibers ]
+
+	$widget_list(stat_text) insert end " Vessel Count = $num, Volume = $vol ($volmm mm^3)\n" odd
+
+	$fstat Delete
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: quantize fibers
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_quantize { } {
+
+    set FIBERS 3
+
+    set fiber_image [ lindex $global_list(result_list) $FIBERS ] 
+
+    ## get current selection 
+    set sel_item [ $widget_list(fiber_list) getcurselection ]
+    
+    if { $sel_item != "" } {
+	
+	## get current index
+	set sel_index [ $widget_list(fiber_list) index [ lindex $sel_item 0 ] ] 
+	
+	## name
+	set item [ lindex $global_list(fiber_list) $sel_index ]	
+
+	## quantize fibers
+	set quant [ vtkmpjStreamlineQuantization [ pxvtable::vnewobj ] ]
+	$quant SetInput [ lindex $global_list(vtk_fiber_polydata) $sel_index ]
+	$quant SetImage [ $fiber_image GetImage ]
+	$quant SetMaskValue 1.0
+	$quant Update
+
+	$fiber_image ShallowCopyImage [ $quant GetOutput ]
+
+	$quant Delete
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Front propagation callback function
+# -----------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::PropagationCallback { filter comment } {
+    
+    set iter [ $filter GetIterationNumber ]
+    
+    ShowProgress $filter "$comment (Iteration $iter)"
+    
+    update idletasks
+
+    if { $comment != "Done" } {
+	set label [ format "%8.4f" [ $filter GetErrorValue ] ]
+	set global_list(solution_errorlabel) "Error: $label"
+    }
+
+    update idletasks
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Front propagation
+# -----------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::result_propagate { }  {
+    
+    set VTK_MPJ_LARGE_FLOAT 32767
+    set VTK_MPJ_UNKNOWN     0 
+
+    set TENSOR 0
+    set MASK 1
+    set MAP 2
+    set SOLUTION 3
+    set GRADIENT 4
+    set FIBERS 5
+        
+    WatchOn
+    
+    update idletasks
+    
+    set viewer [ $parent GetViewer ]      
+    
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    set solution [ lindex $global_list(result_list) $SOLUTION ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set gradient [ lindex $global_list(result_list) $GRADIENT ]
+    set map [ lindex $global_list(result_list) $MAP ]
+    set fibers [ lindex $global_list(result_list) $FIBERS ]
+    
+    set spc [ [ $tensor GetImage ] GetSpacing ]
+    set dim [ [ $tensor GetImage ] GetDimensions ]
+
+    set levels [ [ $viewer GetOrthoImageSlice ] GetLevels ]
+    set x [ lindex $levels 0 ]
+    set y [ lindex $levels 1 ]
+    set z [ lindex $levels 2 ]    
+    
+    ## set seed point
+    set seeds [ vtkDoubleArray [ pxvtable::vnewobj ] ]
+    $seeds SetNumberOfComponents 4
+    $seeds InsertNextTuple4 $x $y $z 0
+    
+    ## Vessel FMM
+    set sol_method [ vtkmpjFastMarchingVesselConnectivity [ pxvtable::vnewobj ] ]
+    
+    ## if mask is defined, make region outside mask unreachable
+    if { [ expr [ $mask GetImageSize ] > 1 && $global_list(solution_usemask) == 1 ] } {
+	$sol_method SetMask [ $mask GetImage ]
+    } 
+    
+    ## set seedss
+    $sol_method SetKnownPoints $seeds
+    $sol_method SetInput [ $tensor GetImage ]
+    $this SetFilterCallbacks $sol_method "Propagating..."
+
+    ## set spacing
+    if { $global_list(solution_autospacing) } {
+	$sol_method SetSpacing \
+	    [lindex $spc 0 ] \
+	    [lindex $spc 1 ] \
+	    [lindex $spc 2 ]
+    } else {
+	$sol_method SetSpacing \
+	    $global_list(solution_spacingx) \
+	    $global_list(solution_spacingy) \
+	    $global_list(solution_spacingz)
+    }
+
+    ## set propagation time
+    if { $global_list(solution_stopping) } {
+	$sol_method SetPropagationTime $global_list(solution_stoptime)
+	$sol_method SetInfinity $global_list(solution_inf)
+    }
+    
+    $sol_method SetInfinity $global_list(solution_inf)    
+    $sol_method SetMaxIntensity $global_list(solution_maxintensity)
+    
+    ## execute
+    $sol_method Update
+    
+    ## calculate gradient
+    set imgrad [ vtkmpjLevelSetNormal [ pxvtable::vnewobj ] ]
+    $imgrad SetInput [ $sol_method GetOutput ]
+    $this SetFilterCallbacks $imgrad "Calculating gradient..."
+    $imgrad Update
+    
+    $gradient ShallowCopyImage [ $imgrad GetOutput ]  
+    $gradient CopyImageHeader [ $solution GetImageHeader ]
+    
+    $imgrad Delete
+    
+    ## threshold result for display purposes
+    set imthr [ vtkImageThreshold [ pxvtable::vnewobj ] ]
+    $imthr SetInput [ $sol_method GetOutput ]
+    $imthr ThresholdBetween 0 $global_list(solution_inf)
+    $imthr ReplaceOutOn  
+    $imthr SetOutValue $global_list(solution_inf)
+    $imthr SetOutputScalarTypeToFloat
+    $this SetFilterCallbacks $imthr "Thresholding solution..."
+    $imthr Update
+    
+    $solution ShallowCopyImage [ $sol_method GetOutput ]  
+    $solution CopyImageHeader [ $solution GetImageHeader ]
+    
+    $sol_method Delete
+    
+    $seeds Delete    
+    
+    $imthr Delete
+    
+    # send currently selected result to parent
+    $widget_list(result_list) selection set $SOLUTION $SOLUTION
+    
+    set sol_map [ lindex $global_list(result_list) $SOLUTION ]
+    $parent SetImageFromObject [ $sol_map  GetThisPointer ] $this
+    
+    WatchOff
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: fiber track
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::fiber_track { } {
+
+    set TENSOR 0
+    set MASK 1
+    set MAP 2
+    set SOLUTION 3
+    set GRADIENT 4
+    set FIBERS 5
+
+    set tensor [ lindex $global_list(result_list) $TENSOR ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set map [ lindex $global_list(result_list) $MAP ]
+    set solution [ lindex $global_list(result_list) $SOLUTION ]
+    set fibers [ lindex $global_list(result_list) $FIBERS ] 
+    set gradient [ lindex $global_list(result_list) $GRADIENT ] 
+
+    if { [ $solution GetImageSize ] == 1 } {
+	
+	tk_messageBox -type ok \
+	    -parent $basewidget -title "Solution" \
+	    -message "You need a propagation solution to start tracking!" -icon info
+	
+	return
+    }
+    
+    if { [ $map GetImageSize ] == 1 } {
+	
+	## create dummy map
+	$map CopyImageHeader [ $fibers GetImageHeader ]
+	$map ShallowCopyImage [ $fibers GetImage ]
+    }
+
+    WatchOn
+
+    ## get slice numbers
+    set levels [ [ [ $parent GetViewer ] GetOrthoImageSlice ] GetLevels ]
+    set cx [ lindex $levels 0 ]
+    set cy [ lindex $levels 1 ]
+    set cz [ lindex $levels 2 ]
+
+    ## get origin and spacing information
+    scan [ [ $solution GetImage ] GetSpacing ] "%f %f %f" spc0 spc1 spc2
+    scan [ [ $solution GetImage ] GetOrigin ] "%f %f %f" org0 org1 org2
+
+    set imtovec [ vtkmpjImageToVectors [ pxvtable::vnewobj ] ]
+    
+    ## convert into vector field
+    $imtovec SetInput [ $gradient GetImage ]
+    $imtovec Update
+    
+    set merge [ vtkMergeFilter [ pxvtable::vnewobj ] ]
+    $merge SetGeometry [ $map GetImage ]
+    $merge SetVectors [ $imtovec GetOutput ]
+    $merge SetScalars [ $map GetImage ]
+    $merge Update
+    
+    #    $imgrad Delete
+    $imtovec Delete
+
+    ## initialize streamer ##
+    set streamer [ vtkmpjVectorStreamline [ pxvtable::vnewobj ] ]
+    $this SetFilterCallbacks $streamer "Vessel tracking..."
+    $streamer SetInput [ $merge GetOutput ]
+    
+    if { $global_list(track_seedtype) == 0 } {
+
+	## single input point
+	set ox [expr $cx * $spc0 + $org0 ]
+	set oy [expr $cy * $spc1 + $org1 ]
+	set oz [expr $cz * $spc2 + $org2 ]
+	
+	set source [ vtkPolyData [ pxvtable::vnewobj ] ] 
+	set points [ vtkPoints [ pxvtable::vnewobj ] ]
+	
+	$points InsertNextPoint $ox $oy $oz 
+	$source SetPoints $points
+	
+	$points Delete
+	
+	## assign source point
+	$streamer SetSource $source
+
+	$source Delete
+
+    } elseif { $global_list(track_seedtype) == 1 } {
+	
+	## region 
+	set region $global_list(track_seedregion)
+
+	set source [ vtkmpjImagePointSource [ pxvtable::vnewobj ] ]
+	
+	if { $region > 0 } {
+	    set imthr [ vtkImageThreshold [ pxvtable::vnewobj ] ]
+	    $imthr SetInput [ $mask GetImage ]
+	    $imthr ThresholdBetween $region $region
+	    $imthr SetInValue 1.0
+	    $imthr SetOutValue 0.0
+	    $imthr SetOutputScalarTypeToUnsignedChar
+	    $imthr Update
+	    $source SetMask [ $imthr GetOutput ]
+	    $imthr Delete
+	} else {
+	    $source SetMask [ $mask GetImage ]
+	}
+ 	set dens $global_list(track_seeddens)
+
+	$source SetOrigin $org0 $org1 $org2
+	$source SetSpacing $spc0 $spc1 $spc2
+	$source SetDensity $dens
+	$source Update
+	
+ 	## assign source points
+	$streamer SetSource [ $source GetOutput ]
+	$source Delete
+	
+	#	set impts [ vtkThresholdPoints [ pxvtable::vnewobj ] ]
+	#	$impts SetInput [ $imthr GetOutput ]
+	#	$impts ThresholdByUpper 1.0
+	#	$impts Update    
+	
+
+	
+	## assign region source points
+#	$streamer SetSource [ $impts GetOutput ]
+#	$impts Delete
+	
+    } elseif { $global_list(track_seedtype) == 2 } {
+	
+	## volume	
+	set ox [expr $cx * $spc0 + $org0 ]
+	set oy [expr $cy * $spc1 + $org1 ]
+	set oz [expr $cz * $spc2 + $org2 ]
+	
+	set width $global_list(track_seedwidth)
+	set height $global_list(track_seedheight)
+	set depth $global_list(track_seeddepth)
+	set dens $global_list(track_seeddens)
+	
+	#	set numx [ expr int(1.0 / $res) * $width ]
+	#	set numy [ expr int(1.0 / $res) * $height ]
+	#	set numz [ expr int(1.0 / $res) * $depth ]
+	
+	set source [ vtkmpjImagePointSource [ pxvtable::vnewobj ] ]
+	$source SetCenter $ox $oy $oz
+	$source SetSize $width $height $depth
+	$source SetOrigin $org0 $org1 $org2
+	$source SetSpacing $spc0 $spc1 $spc2
+	$source SetDensity $dens
+	$source Update
+
+	## assign source points
+	$streamer SetSource [ $source GetOutput ]
+
+	$source Delete
+    } elseif { $global_list(track_seedtype) == 3 } {
+	
+	## landmark control
+	set landmarkcontrol [ [ $parent GetLandmarkControl ] GetLandmarkControl ]
+	
+	set lmarks [ $landmarkcontrol GetCollection -1 ]	
+	$lmarks Compact
+	set numlmarks [ $lmarks GetNumPoints ]
+	
+	if { $numlmarks > 0 } {
+	    
+	    set pts [ vtkPolyData [ pxvtable::vnewobj ] ]
+	    $pts SetPoints [ $lmarks GetPoints ]
+	    
+	    $streamer SetSource $pts
+
+	    $pts Delete
+	}
+    }
+    
+#    puts "num seed points: [ [ [ $streamer GetSource ] GetPoints ] GetNumberOfPoints ]"
+#    puts "min speed = $global_list(track_minspeed)"
+    
+    $streamer SetTerminalSpeed $global_list(track_minspeed)
+    $streamer SetIntegrationDirectionToBackward
+    $streamer SetMaximumPropagationTime $global_list(track_maxdist)
+    if { $global_list(track_integration) == 0 } { 
+	$streamer SetIntegrator [ vtkRungeKutta2 [ pxvtable::vnewobj ] ]
+    } else {
+	$streamer SetIntegrator [ vtkRungeKutta4 [ pxvtable::vnewobj ] ]
+    }
+    $streamer SetIntegrationStepLength $global_list(track_steplen)
+    $streamer SetStepLength $global_list(track_steplen)
+    #$streamer SpeedScalarsOn
+    $streamer Update
+
+    set new_fiber [ vtkPolyData [ pxvtable::vnewobj ] ]
+    
+    ## create new fiber set
+    if { $global_list(track_fitspline) == 1 } {
+	
+	set spline [ vtkSplineFilter [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $spline "Spline fitting..."
+	$spline SetInput [ $streamer GetOutput ]
+	$spline SetSubdivide $global_list(track_splinesubdivision)
+	$spline SetLength $global_list(track_splinelength)
+	$spline SetNumberOfSubdivisions $global_list(track_splinenumber)
+	$spline Update
+
+	$new_fiber ShallowCopy [ $spline GetOutput ]
+
+	$spline Delete
+
+    } else {	
+	
+	$new_fiber ShallowCopy [ $streamer GetOutput ]
+    }
+    
+    $streamer Delete
+    
+    set index [ fiber_add $new_fiber ]
+    
+#    puts "points: [[$new_fiber GetPoints] GetNumberOfPoints]"
+
+    ## display new bundle
+    if { $global_list(view_fiber) } {	
+	
+	set actor [ view_create_fiber_glyph $index ]
+	lappend global_list(actor_fiber) $actor
+	
+	## add actor if to be displayed
+	if { [ lindex $global_list(fiber_disp_list) $index ] == 1 } { 
+	    for { set j 0 } { $j < 4 } { incr j } {
+		[ [ [ $parent GetViewer ] GetRenderer $j ] GetRenderer ] AddActor $actor
+	    }
+	}
+    }
+
+#    puts "before statistics"
+
+    ## compute statistics
+    #if { $global_list(track_autostat) } {
+	#fiber_statistics
+    #}
+
+    WatchOff
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create results control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::CreateInputControl { base } {   
+
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Hessian image"
+    pack $base.frame1 -fill both -expand f -pady 5
+    
+    set frame1 [ $base.frame1 childsite ]
+    
+    set subframe0 [ frame $frame1.subframe0 ]
+    pack $subframe0 -side top -fill both -expand f -pady 0
+    
+    set tensor_fname [ iwidgets::entryfield $subframe0.tensor_fname \
+			   -textvariable [ itcl::scope global_list(tensor_fname) ] \
+			   -labeltext "Filename:" ] 
+    pack $tensor_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(tensor_fname) $tensor_fname
+    
+    set tensor_load [ iwidgets::buttonbox $subframe0.tensor_load -orient horizontal -padx 2 ]
+    $tensor_load add load -text "Load..." -command [ itcl::code $this loadtensor ] 
+    $tensor_load add disp -text "Display" -command [ itcl::code $this DisplayResult 0 ]
+    pack $tensor_load -side left
+    set widget_list(tensor_load) $tensor_load
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Region of interest mask"
+    pack $base.frame0 -fill both -expand f -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+  
+    iwidgets::labeledframe $base.frame2 \
+	-labelpos nw  \
+	-labeltext "Map for analysis (e.g. vesselness, scales)"
+    pack $base.frame2 -fill both -expand f -pady 5
+    
+    set frame2 [ $base.frame2 childsite ]
+    
+    set subframe0 [ frame $frame2.subframe0 ]
+    pack $subframe0 -side top -fill x -expand f -pady 0
+    
+    set map_fname [ iwidgets::entryfield $subframe0.map_fname \
+			-textvariable [ itcl::scope global_list(map_fname) ] \
+			-labeltext "Filename:" ] 
+    pack $map_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(map_fname) $map_fname
+    
+    set map_load [ iwidgets::buttonbox $subframe0.map_load -orient horizontal -padx 2 ]
+    $map_load add load -text "Load..." -command [ itcl::code $this loadmap ] 
+    $map_load add disp -text "Display" -command [ itcl::code $this DisplayResult 2 ]
+    pack $map_load -side left 
+    set widget_list(map_load) $map_load
+
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+    
+    set mask_fname [ iwidgets::entryfield $subframe1.mask_fname \
+			 -textvariable [ itcl::scope global_list(mask_fname) ] \
+			 -labeltext "Filename:" ] 
+    pack $mask_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(mask_fname) $mask_fname
+    
+    set mask_load [ iwidgets::buttonbox $subframe1.mask_load -orient horizontal -padx 2 ]
+    $mask_load add load -text "Load..." -command [ itcl::code $this loadmask ]    
+    $mask_load add disp -text "Display" -command [ itcl::code $this DisplayResult 1 ]
+    pack $mask_load -side left 
+    set widget_list(mask_load) $mask_load
+    
+    set mask_nreg [ iwidgets::spinint $subframe1.mask_nreg \
+			-labeltext "Number of regions in mask:" \
+			-fixed 4 -width 4 -range {1 1000} -step 1 \
+			-textvariable [ itcl::scope global_list(mask_nreg) ] ]
+    pack $mask_nreg -side right -pady 5 -padx 5
+    set widget_list(mask_nreg) $mask_nreg
+
+  
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create results control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::CreateResultsControl { base } {   
+
+    set color(0) \#dcdcdc
+    set color(1) black
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Results"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+    
+    iwidgets::scrolledlistbox $subframe0.resultlist \
+	-hscrollmode dynamic \
+	-selectmode extended \
+	-dblclickcommand [ itcl::code $this toggleresult ] \
+	-visibleitems 40x10 
+    
+    pack $subframe0.resultlist -side left -fill both -expand t -padx 2 -pady 2
+    set widget_list(result_list) $subframe0.resultlist
+    
+    foreach item $global_list(result_title) {
+	set enable [ lindex $item 2 ]
+     	$widget_list(result_list) insert end "[lindex $item 0]" 
+	$widget_list(result_list) itemconfigure end -foreground $color($enable)
+    }
+
+    set subframe1 [ frame $subframe0.subframe1 ]
+    pack $subframe1 -side right -fill both -padx 0
+    
+    set resultbbox [ iwidgets::buttonbox $subframe1.input -orient vertical ]
+    $resultbbox add display -text "Display" -command [ itcl::code $this displayresult ]
+    $resultbbox add save -text "Save..." -command [ itcl::code $this saveresult ]
+    $resultbbox add saveall -text "Save all" -command [ itcl::code $this saveallresults ]    
+    $resultbbox add mark -text "On/Off" -command [ itcl::code $this toggleresult ]
+
+    pack $resultbbox -side top -fill x -expand t -padx 0
+    set widget_list(result_buttonbox) $resultbbox
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill x -padx 2 -pady 5
+
+    set result_fpreffix [ iwidgets::entryfield $subframe2.result_fpreffix \
+			      -textvariable [ itcl::scope global_list(result_fpreffix) ] \
+			      -labeltext "Preffix:" ]
+    pack $result_fpreffix -side left -fill x -expand t -padx 5 -pady 2
+    set widget_list(result_fpreffix) $result_fpreffix    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create tensor control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::CreateConnectivityControl { base } {
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Solution"
+    pack $base.frame0 -fill both -expand f -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+  
+    set solution_fname [ iwidgets::entryfield $subframe1.mask_fname \
+			     -state disabled \
+			     -textvariable [ itcl::scope global_list(solution_fname) ] \
+			     -labeltext "Filename:" ] 
+    pack $solution_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(solution_fname) $solution_fname
+    
+    set solution_load [ iwidgets::buttonbox $subframe1.solution_load -orient horizontal -padx 2 ]
+    $solution_load add load -text "Load..." -command [ itcl::code $this loadsolution ] 
+    $solution_load add disp -text "Display" -command [ itcl::code $this DisplayResult 3 ]
+    pack $solution_load -side left
+    set widget_list(solution_load) $solution_load
+    
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Front propagation"
+    pack $base.frame1 -fill both -expand f 
+    
+    set frame0 [ $base.frame1 childsite ]
+
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f
+    
+    set solution_usemask [ checkbutton $subframe1.solution_usemask \
+			       -text "Use mask as computational boundary" \
+			       -variable [ itcl::scope global_list(solution_usemask) ] ]
+    pack $solution_usemask -side left -padx 5 -pady 5
+    
+    set subframe3 [ frame $frame0.subframe3 ]
+    pack $subframe3 -side top -fill both -expand f
+
+    set solution_autospacing [ checkbutton $subframe3.solution_autospacing \
+				   -text "Use spacing from hessian" \
+				   -command [ itcl::code $this solution_autospacing_cb ] \
+				   -variable [ itcl::scope global_list(solution_autospacing) ] ]
+    pack $solution_autospacing -side left -padx 5 -pady 5
+    
+    set solution_spacingx [ iwidgets::entryfield $subframe3.solution_spacingx \
+				-labeltext "Custom spacing:" \
+				-validate real \
+				-width 5  \
+				-state disabled \
+				-textvariable [ itcl::scope global_list(solution_spacingx) ] ]
+    pack $solution_spacingx -side left -padx 2 -pady 5
+    set widget_list(solution_spacingx) $solution_spacingx
+
+    set solution_spacingy [ iwidgets::entryfield $subframe3.solution_spacingy \
+				-validate real \
+				-width 5  \
+				-state disabled \
+				-textvariable [ itcl::scope global_list(solution_spacingy) ] ]
+    pack $solution_spacingy -side left -padx 2 -pady 5
+    set widget_list(solution_spacingy) $solution_spacingy
+
+    set solution_spacingz [ iwidgets::entryfield $subframe3.solution_spacingz \
+				-validate real \
+				-width 5  \
+				-state disabled \
+				-textvariable [ itcl::scope global_list(solution_spacingz) ] ]
+    pack $solution_spacingz -side left -padx 2 -pady 5
+    set widget_list(solution_spacingz) $solution_spacingz
+
+    set subframe4 [ frame $frame0.subframe4 ]
+    pack $subframe4 -side top -fill both -expand f
+
+    set solution_stopping [ checkbutton $subframe4.solution_stopping \
+				-text "Stop evolution at time:" \
+				-command [ itcl::code $this solution_stopping_cb ] \
+				-variable [ itcl::scope global_list(solution_stopping) ] ]
+    pack $solution_stopping -side left -padx 5 -pady 5    
+
+    set solution_stoptime [ iwidgets::entryfield $subframe4.solution_stoptime \
+				-validate real \
+				-width 7  \
+				-state disabled \
+				-textvariable [ itcl::scope global_list(solution_stoptime) ] ]
+    pack $solution_stoptime -side left -padx 2 -pady 5
+    set widget_list(solution_stoptime) $solution_stoptime
+
+    set solution_inf [ iwidgets::entryfield $subframe4.solution_inf \
+			   -labeltext "Value for infinite arrival time: " \
+			   -validate real -width 7  \
+			   -state disabled \
+			   -textvariable [ itcl::scope global_list(solution_inf) ] ]
+    pack $solution_inf -side left -padx 10 -pady 5
+    set widget_list(solution_inf) $solution_inf
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill both -expand f
+    
+    set solution_btn [ iwidgets::buttonbox $subframe2.solution_btn -orient horizontal -padx 2 ]
+    $solution_btn add compute -text "Compute!" -command [ itcl::code $this result_propagate ] 
+    pack $solution_btn -side left
+
+    set widget_list(compute_btn) $solution_btn
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create fiber tracking control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::CreateTrackingControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Seed points"
+    pack $base.frame0 -fill both -expand f 
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand f
+    
+    set track_seedtype [ iwidgets::optionmenu $subframe0.track_seedtype \
+			     -command [ itcl::code $this track_seedtype_cb ] \
+			     -labeltext "Seed from:" ]
+    pack $track_seedtype -side left -padx 5 -pady 5
+    $track_seedtype insert end "Single point"
+    $track_seedtype insert end "Region"
+    $track_seedtype insert end "Volume"
+    $track_seedtype insert end "Landmark control"
+    set widget_list(track_seedtype) $track_seedtype
+
+    set track_seedregion [ iwidgets::spinint $subframe0.track_seedregion \
+			       -labeltext "Region number (0=all):" \
+			       -fixed 4 -width 4 -range {0 1000} -step 1 \
+			       -textvariable \
+			       [ itcl::scope global_list(track_seedregion) ] ]
+    pack $track_seedregion -side left -pady 5 -padx 2
+    set widget_list(track_seedregion) $track_seedregion  
+    $widget_list(track_seedregion) configure -state disabled
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -expand f
+    
+    set track_seedwidth [ iwidgets::entryfield $subframe1.track_seedwidth \
+			      -labeltext "Width:" \
+			      -validate integer \
+			      -width 4 \
+			      -state disabled \
+			      -textvariable [ itcl::scope global_list(track_seedwidth) ] ]
+    pack $subframe1.track_seedwidth -side left -padx 5 -pady 5 
+    set widget_list(track_seedwidth) $track_seedwidth
+    
+    set track_seedheight [ iwidgets::entryfield $subframe1.track_seedheight \
+			       -labeltext "Height:" \
+			       -validate integer \
+			       -width 4 \
+			       -state disabled \
+			       -textvariable [ itcl::scope global_list(track_seedheight) ] ]
+    pack $subframe1.track_seedheight -side left -padx 5 -pady 5
+    set widget_list(track_seedheight) $track_seedheight
+    
+    set track_seeddepth [ iwidgets::entryfield $subframe1.track_seeddepth \
+			      -labeltext "Depth:" \
+			      -validate integer \
+			      -width 4 \
+			      -state disabled \
+			      -textvariable [ itcl::scope global_list(track_seeddepth) ] ]
+    pack $subframe1.track_seeddepth -side left -padx 5 -pady 5 
+    set widget_list(track_seeddepth) $track_seeddepth
+    
+    set track_seeddens [ iwidgets::entryfield $subframe1.track_seeddens \
+			    -labeltext "Density:" \
+			    -validate real \
+			    -width 6 \
+			    -state disabled \
+			    -textvariable [ itcl::scope global_list(track_seeddens) ] ]
+    pack $subframe1.track_seeddens -side left -padx 5 -pady 5
+    set widget_list(track_seeddens) $track_seeddens
+
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Integration parameters"
+    pack $base.frame1 -fill both -expand f
+    
+    set frame1 [ $base.frame1 childsite ]
+    
+    set subframe2 [ frame $frame1.subframe2 ]
+    pack $subframe2 -fill both -expand f
+    
+    set integration [ iwidgets::optionmenu $subframe2.integration \
+			  -command [ itcl::code $this track_integration_cb ] \
+			  -labeltext "Type:" ]	
+    pack $integration -side left -padx 5 -pady 5
+    $integration insert end "Runge-Kutta 2"
+    $integration insert end "Runge-Kutta 4"
+    set widget_list(track_integration) $integration
+    
+    iwidgets::entryfield $subframe2.track_steplen \
+	-width 5 \
+	-validate real \
+	-labeltext "Step length:" \
+	-textvariable [ itcl::scope global_list(track_steplen) ] 
+    pack $subframe2.track_steplen -side left -padx 5 -pady 5     
+
+
+    set subframe5 [ frame $frame1.subframe5 ]
+    pack $subframe5 -fill both -expand f
+
+    iwidgets::entryfield $subframe5.track_maxdist \
+	-width 5 \
+	-validate real \
+	-labeltext "Max length:" \
+	-textvariable [ itcl::scope global_list(track_maxdist) ] 
+    pack $subframe5.track_maxdist -side left -padx 5 -pady 5    
+
+    iwidgets::entryfield $subframe5.track_minspeed \
+	-width 5 \
+	-validate real \
+	-labeltext "Minimum speed:" \
+	-textvariable [ itcl::scope global_list(track_minspeed) ] 
+    pack $subframe5.track_minspeed -side left -padx 5 -pady 5  
+
+    iwidgets::labeledframe $base.frame2 \
+	-labelpos nw  \
+	-labeltext "Vessel representation"
+    pack $base.frame2 -fill both -expand f
+    
+    set frame2 [ $base.frame2 childsite ]
+
+    set subframe6 [ frame $frame2.subframe6 ]
+    pack $subframe6 -fill both -expand f
+    
+    set track_fitspline [ checkbutton $subframe6.track_fitspline \
+			      -text "Fit splines to vessels" \
+			      -variable [ itcl::scope global_list(track_fitspline) ] ]
+    pack $track_fitspline -side left -pady 2 -padx 5 
+    
+    set splinetype [ iwidgets::optionmenu $subframe6.splinetype \
+			 -command [ itcl::code $this track_splinetype_cb ] \
+			 -labeltext "Type:" ]	
+    pack $splinetype -side left -padx 5 -pady 2
+    $splinetype insert end "Cardinal"
+    $splinetype insert end "Kochaneck"
+    set widget_list(track_splinetype) $splinetype
+ 
+    set subframe7 [ frame $frame2.subframe7 ]
+    pack $subframe7 -fill both -expand f
+    
+    set splinesubdivision [ iwidgets::optionmenu $subframe7.splinesubdivision \
+				-command [ itcl::code $this track_splinesubdivision_cb ] \
+				-labeltext "Subdivision:" ]	
+    pack $splinesubdivision -side left -padx 5 -pady 2
+    $splinesubdivision insert end "Specified"
+    $splinesubdivision insert end "Length"
+    set widget_list(track_splinesubdivision) $splinesubdivision
+
+    iwidgets::entryfield $subframe7.track_splinelength \
+	-width 5 \
+	-validate real \
+	-labeltext "Length:" \
+	-textvariable [ itcl::scope global_list(track_splinelength) ] 
+    pack $subframe7.track_splinelength -side left -pady 5  
+
+    iwidgets::entryfield $subframe7.track_splinenumber \
+	-width 4 \
+	-validate integer \
+	-labeltext "Subdivisions:" \
+	-textvariable [ itcl::scope global_list(track_splinenumber) ] 
+    pack $subframe7.track_splinenumber -side left -padx 5 -pady 5  
+
+    set subframe3 [ frame $base.frame3 ]
+    pack $subframe3 -fill both -pady 0 -expand f
+
+    set trackbtn [ iwidgets::buttonbox $subframe3.trackbtn -orient horizontal ]
+    $trackbtn add track -text "Track!" -command [ itcl::code $this fiber_track ]
+    pack $trackbtn -side left -expand f
+
+    ## auto stat
+#    set track_autostat [ checkbutton $subframe3.track_autostat \
+#			     -text "Auto vessel statistics" \
+#			     -variable [ itcl::scope global_list(track_autostat) ] ]
+ #   pack $track_autostat -side right -padx 5       
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create fiber tracking control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::CreateFiberControl { base } {
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Vessels"
+    pack $base.frame0 -fill both
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -expand t -side top
+
+    label $subframe1.dummy0 -text "Color:"
+    pack $subframe1.dummy0 -side left -padx 5 -pady 5
+        
+    set fiber_color [ image create photo -width 15 -height 15 ]
+    $fiber_color put $global_list(fiber_color) -to 0 0 15 15
+    
+    button $subframe1.fiber_color -image $fiber_color \
+	-command [ itcl::code $this fiber_color_cb ]
+    pack $subframe1.fiber_color -side left
+    set widget_list(fiber_color) $subframe1.fiber_color
+
+    set fiber_name [ iwidgets::entryfield $subframe1.fiber_name \
+			 -textvariable [ itcl::scope global_list(fiber_name) ] \
+			 -labeltext "Name:" \
+			 -width 30 \
+			 -command [ itcl::code $this fiber_name_cb ] ] 
+    pack $fiber_name -side left -pady 5 -padx 5 -fill x -expand t
+    set widget_list(fiber_name) $fiber_name
+    
+    checkbutton $subframe1.fiber_display \
+	-text "Display" \
+	-variable [ itcl::scope global_list(fiber_display) ] \
+	-command [ itcl::code $this fiber_display_cb ]    
+    pack $subframe1.fiber_display -side left -padx 5
+
+    set middle [ frame $frame0.middle ] 
+    pack $middle -fill x -expand t -side top -pady 2
+    
+    set subframe2 [ frame $middle.subframe2 ]
+    pack $subframe2 -fill both -expand t -side left -pady 2
+
+    iwidgets::scrolledlistbox $subframe2.fiberlist \
+	-hscrollmode dynamic \
+	-visibleitems 40x15 \
+	-listvariable [ itcl::scope global_list(fiber_list) ] \
+	-selectmode extended \
+	-selectioncommand [ itcl::code $this fiber_selection_cb ]    
+    pack $subframe2.fiberlist -side left -fill both -expand t -padx 5
+    set widget_list(fiber_list) $subframe2.fiberlist
+   
+    set subframe3 [ frame $middle.subframe3 ]
+    pack $subframe3 -expand f -side left
+    
+    set fiberbbox [ iwidgets::buttonbox $subframe3.fiberbbox -orient vertical ]
+    $fiberbbox add load -text "Load" -command [ itcl::code $this fiber_load ]
+    $fiberbbox add save -text "Save" -command [ itcl::code $this fiber_saveselected ]
+    $fiberbbox add saveall -text "Save all" -command [ itcl::code $this fiber_saveall ]
+    $fiberbbox add remove -text "Remove" -command [ itcl::code $this fiber_removeselected ]
+    $fiberbbox add clear -text "Clear" -command [ itcl::code $this fiber_clear ]
+#    $fiberbbox add stat -text "Statistics" -command [ itcl::code $this fiber_statistics ]
+    pack $fiberbbox -side left -expand t
+    set widget_list(fiber_buttonbox) $fiberbbox                   
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create statistics control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::CreateStatisticsControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Statistics"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+
+    set stat_text [iwidgets::scrolledtext $subframe0.stat_text \
+		       -visibleitems 70x19 \
+		       -foreground black \
+		       -vscrollmode static \
+		       -hscrollmode static \
+		       -wrap none ]
+    pack $stat_text -side top -expand t -fill both -padx 2 -pady 2
+    set widget_list(stat_text) $stat_text
+
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -fill both -expand t
+
+    set statbbox [ iwidgets::buttonbox $subframe1.statbbox -orient horizontal -pady 2 -padx 2 ]
+    $statbbox add save -text "Save..." -command [ itcl::code $this fiber_savestatistics ]
+    $statbbox add clear -text "Clear" -command "$stat_text delete 1.0 end"
+    pack $statbbox -side left -fill both 
+
+    set stat_overwrite [ checkbutton $subframe1.stat_overwrite -text "Overwrite" \
+			     -variable [ itcl::scope global_list(stat_overwrite) ] ]
+    pack $stat_overwrite -side right -padx 5       
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create wavefront display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::CreateFrontDisplayControl { base } {
+
+    set subframe0 [ frame $base.subframe0 ]
+    pack $subframe0 -fill x -side top -expand f -padx 5 -pady 5
+    
+    checkbutton $subframe0.view_gradient -text "View gradient" \
+	-variable [ itcl::scope global_list(view_gradient) ] \
+	-command [ itcl::code $this view_toggle_gradient ]   
+    pack $subframe0.view_gradient -side left -padx 5
+    
+    iwidgets::entryfield $subframe0.view_contour_levels \
+	-width 4 \
+	-validate integer \
+	-labeltext "Number of levels:" \
+	-textvariable [ itcl::scope global_list(view_contour_levels) ] \
+	-command [ itcl::code $this view_update_display_cb ]
+    pack $subframe0.view_contour_levels -side left -padx 5   
+    
+    iwidgets::entryfield $subframe0.view_contour_width \
+	-width 4 \
+	-validate real \
+	-labeltext "Contour width:" \
+	-textvariable [ itcl::scope global_list(view_contour_width) ]
+    pack $subframe0.view_contour_width -side left -padx 5   
+    
+    set subframe2 [ frame $base.subframe2 ]
+    pack $subframe2 -fill x -side top -expand f -padx 5 -pady 5
+
+    set front_luk [ mpjguilookuptable \#auto 0 ]
+    $front_luk Initialize $subframe2  
+    pack forget [ $front_luk GetButtonBoxWidget ]
+#    pack forget [ $front_luk GetMenuBar ]     
+    $front_luk SetHueRange 0.5 0.92
+    $front_luk SetSaturationRange 0.75 1.0
+    $front_luk Update
+    $front_luk Show
+    
+    set widget_list(view_frontluk) $front_luk    
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  Create fiber display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::CreateFiberDisplayControl { base } {
+
+    set subframe0 [ frame $base.subframe0 ]
+    pack $subframe0 -fill x -side top -expand f -padx 5 -pady 5
+    
+    set view_fiber_glyph [ iwidgets::optionmenu $subframe0.view_fiber_glyph \
+				-labeltext "View vessels as:"   \
+				-command [ itcl::code $this view_fiber_glyph_cb ] ] \
+	
+    pack $view_fiber_glyph -side left -padx 5
+    $view_fiber_glyph insert end "Lines"
+    $view_fiber_glyph insert end "Tubes"
+    $view_fiber_glyph insert end "Points"
+    set widget_list(view_fiber_glyph) $view_fiber_glyph
+    
+    iwidgets::entryfield $subframe0.view_fiber_pointsize \
+	-width 5 \
+	-validate real \
+	-labeltext "Point size:" \
+	-textvariable [ itcl::scope global_list(view_fiber_pointsize) ]  \
+	-command [ itcl::code $this view_fiber_pointsize_cb ]
+    pack $subframe0.view_fiber_pointsize -side left -padx 5    
+    
+    set subframe2 [ frame $base.subframe2 ]
+    pack $subframe2 -side top -fill both -padx 5 -expand f
+    
+    set view_fiber_varytuberadius [ checkbutton $subframe2.view_fiber_varytuberadius \
+					-text "Vary tube radius" \
+					-variable [ itcl::scope global_list(view_fiber_varytuberadius) ] \
+					-command [ itcl::code $this view_fiber_tuberadius_cb ] ]
+    pack $view_fiber_varytuberadius -side left -pady 2 -padx 5       
+    set widget_list(view_fiber_varytuberadius) $view_fiber_varytuberadius  
+    
+    iwidgets::entryfield $subframe2.view_fiber_tuberadius \
+	-width 5 \
+	-validate real \
+	-labeltext "Tube radius:" \
+	-textvariable [ itcl::scope global_list(view_fiber_tuberadius) ]  \
+	-command [ itcl::code $this view_fiber_tuberadius_cb ]
+    pack $subframe2.view_fiber_tuberadius -side left -padx 5    
+    
+    iwidgets::entryfield $subframe2.view_fiber_tuberadiusfactor \
+	-width 5 \
+	-validate real \
+	-labeltext "Radius scaling:" \
+	-textvariable [ itcl::scope global_list(view_fiber_tuberadiusfactor) ]  \
+	-command [ itcl::code $this view_fiber_tuberadius_cb ]
+    pack $subframe2.view_fiber_tuberadiusfactor -side left -padx 5    
+
+
+    set subframe3 [ frame $base.subframe3 ]
+    pack $subframe3 -side left -fill both -padx 5 
+    
+    set fiber_luk [ mpjguilookuptable \#auto 0 ]
+    $fiber_luk Initialize $subframe3  
+    pack forget [ $fiber_luk GetButtonBoxWidget ]
+#    pack forget [ $fiber_luk GetMenuBar ]     
+    $fiber_luk SetHueRange 0.5 0.92
+    $fiber_luk SetSaturationRange 0.75 1.0
+    $fiber_luk Update
+    $fiber_luk Show
+    
+    set widget_list(view_fiberluk) $fiber_luk
+    
+    set view_fiber_luk [ checkbutton [ $fiber_luk GetMenuBar ].view_fiber_luk \
+			     -text "Apply to:" \
+			     -variable [ itcl::scope global_list(view_fiber_luk) ] \
+			     -command [ itcl::code $this view_fiber_colormap_cb ] ]
+    pack $view_fiber_luk -side left -pady 0 -padx 5       
+    set widget_list(view_fiber_luk) $view_fiber_luk
+    
+    set view_fiber_luktype \
+	[ iwidgets::optionmenu [ $fiber_luk GetMenuBar ].view_fiber_luktype ]
+    $view_fiber_luktype configure -command [ itcl::code $this view_fiber_luktype_cb ]
+    $view_fiber_luktype insert end "Points"
+    $view_fiber_luktype insert end "Vessels"
+    pack $view_fiber_luktype -side left -pady 0 -padx 0
+    set widget_list(view_fiber_luktype) $view_fiber_luktype
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create display control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::CreateDisplayControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Properties"
+    pack $base.frame0 -fill both -expand t 
+
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -padx 5 -pady 2 -expand f
+
+    checkbutton $subframe0.view_fibers -text "View vessels" \
+	-variable [ itcl::scope global_list(view_fiber) ] \
+	-command [ itcl::code $this view_toggle_fiber ]   
+    pack $subframe0.view_fibers -side left -padx 5
+    
+    checkbutton $subframe0.view_contour -text "View front" \
+	-variable [ itcl::scope global_list(view_contour) ] \
+	-command [ itcl::code $this view_toggle_contour ]   
+    pack $subframe0.view_contour -side left -padx 5
+
+    checkbutton $subframe0.view_colorbar -text "View colorbar" \
+	-variable [ itcl::scope global_list(view_colorbar) ] \
+	-command [ itcl::code $this view_toggle_colorbar ]   
+    pack $subframe0.view_colorbar -side left -padx 5
+    
+    iwidgets::entryfield $subframe0.view_colorbar_label \
+	-width 10 \
+	-labeltext "Label:" \
+	-textvariable [ itcl::scope global_list(view_colorbar_label) ]
+    pack $subframe0.view_colorbar_label -side left -padx 5    
+
+    set subframe1 [ frame $frame0.subframe1 ] 
+    pack $subframe1 -fill both -expand t -padx 5 -pady 5
+    
+    set display_notebook [ iwidgets::tabnotebook $subframe1.display_notebook -tabpos n ]     
+    set widget_list(display_notebook) $display_notebook
+    pack $display_notebook -fill both -expand t -padx 10 -pady 2
+    
+    CreateFrontDisplayControl [ $display_notebook add -label "Wavefront" ]
+    CreateFiberDisplayControl [ $display_notebook add -label "Vessels" ]
+
+    $display_notebook view "Vessels"   
+}
+
+# -------------------------------------------------------------------------------------------
+#  Diffusion control inititialization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::Initialize { widget } {
+    
+    if { $initialized == 1 } { return $basewidget }
+    
+    #  -------------------------------------
+    #  Create User Interface
+    #  -------------------------------------	
+    set basewidget [toplevel $widget ]
+    wm geometry $basewidget 620x480
+    wm withdraw $basewidget
+
+    set notebook $basewidget.notebook    
+    iwidgets::tabnotebook $notebook -tabpos w         
+    set widget_list(notebook) $notebook
+    
+    CreateInputControl        [ $notebook add -label "Input" ] 
+    CreateConnectivityControl [ $notebook add -label "Propagation" ]
+    CreateTrackingControl     [ $notebook add -label "Tracking" ]
+    CreateFiberControl        [ $notebook add -label "Vessels" ]
+#    CreateStatisticsControl   [ $notebook add -label "Statistics" ]
+    CreateResultsControl      [ $notebook add -label "Results" ]
+    CreateDisplayControl      [ $notebook add -label "Display" ]
+    
+    pack $notebook -side top -fill both -expand t -padx 5
+    
+    $notebook view "Input"
+    
+    set pbar [ frame $basewidget.pbar -width 400 -height 20 ]
+    pack $pbar -side bottom -expand f -fill x
+    CreateProgressBar $pbar
+    
+    set w [ frame $basewidget.w -relief ridge -width 800]
+    pack $w -side bottom -fill x -expand false
+    
+    eval "button $w.close -text Close -command { $this DismissWindow }"
+    pack $w.close -side right -fill x -padx 5 -pady 10
+    
+    set initialized 1
+
+    SetTitle $appname
+
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { $this DismissWindow }"
+
+    return $basewidget
+}
+
+#-------------------------------------------------------------------------------------------
+#  Add controls to menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesseltracking::AddToMenuButton { mb args } {
+    eval "$mb add command -label \"Vessel tracking\" -command {$this ShowWindow \"Input\"}"
+}
+
+#-------------------------------------------------------------------------------------------
+#  Main application
+# ------------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+    puts "\n[ file rootname $argv0 ] is not a stand-alone program.\n"
+    exit
+}
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/mpjvesselutility.tcl b/bioimagesuite30_src/bioimagesuite/mjack/mpjvesselutility.tcl
new file mode 100644
index 0000000..9d0d63b
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/mpjvesselutility.tcl
@@ -0,0 +1,1259 @@
+#!/bin/sh
+# the next line restarts using wish \
+    exec vtk "$0" "$@"
+
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+# -----------------------
+# Dependencies and path
+# -----------------------
+lappend auto_path [ file dirname [ info script ] ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] base ]
+lappend auto_path [ file join [file join [ file dirname [ info script ]] ".."] main ]
+
+package provide mpjvesselutility 1.0
+
+package require  Itcl 3.2
+package require  Iwidgets 4.0
+
+package require  pxitcllistselector 1.0
+package require  pxitclbaseimagecontrol 1.0
+package require  pxitclbaseimageviewer 1.0
+
+package require  vtkmpjcontrib 1.1
+package require  mpjguilookuptable 1.0
+
+itcl::class mpjvesselutility {
+
+    inherit pxitclbaseimagecontrol
+    
+    #-----------------------------------
+    # construction and descruction
+    #-----------------------------------
+    constructor { par } {
+	pxitclbaseimagecontrol::constructor $par
+    } { InitializeControl }
+    
+    destructor { }
+
+    #-----------------------------------
+    # global variables
+    #-----------------------------------
+    private variable widget_list
+    private variable global_list
+    
+    #-----------------------------------
+    # initialization methods
+    #-----------------------------------
+    public method Initialize { inpwidg }
+    public method InitializeControl { }
+    public method DismissWindow { }
+      
+    #-----------------------------------
+    # diffusion series input/output
+    #-----------------------------------
+    public method LoadMask { fname }
+    public method LoadInput { fname }
+    public method ComputeResults { }
+    public method SaveAllResults { }
+    public method SaveResult { index }
+    public method ClearAllResults { }
+    public method DisplayResult { index }
+    public method GrabImage { index }
+    public method ClearDisplay { }
+    public method SetResultPreffix { preffix }
+    public method GetResultPreffix { } 
+    public method SetCurrentDirectory { fname } 
+    
+    #-----------------------------------
+    # interface creation methods
+    #-----------------------------------
+    private method CreateDialogs { base }
+    private method CreateResultsControl { base }
+    private method CreateVesselControl { base }
+    private method CreateTensorControl { base }
+    #    private method CreateMenu { mb }
+    public method AddToMenuButton { mb args }    
+ 
+    private method linspace { x1 x2 n }
+    private method logspace { x1 x2 n }
+    private method loadmask { }
+    private method loadinput { }
+    private method displayresult { }
+    private method saveresult { }
+    private method toggleresult { }
+    private method saveallresults { }
+ 
+    private method mask_autochanged_cb { }
+    private method mask_autothreshchanged_cb { }
+
+    private method vessel_type_cb { }
+    private method vessel_intensity_cb { }
+
+    private method initialize_glyphs { }
+    private method input_updateinfo { index }    
+
+    private method result_clear { start end }
+    private method result_createhessian { }
+    protected method ResampleImage { img spacing } 
+}  
+
+#-------------------------------------------------------------------------------------------
+#  Close window 
+# -------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::DismissWindow { } {
+    
+    set INPUT 0
+    set MASK 1
+
+    set ok "yes"
+    
+    set tensorsz [ [ lindex $global_list(result_list) $INPUT ] GetImageSize ]
+    set masksz [ [ lindex $global_list(result_list) $MASK ] GetImageSize ]
+
+    if { [expr ($tensorsz > 1) || ($masksz > 1) ] } {
+	
+	set ok [ tk_messageBox -type yesnocancel -default no \
+		     -parent $basewidget -title "Think again ..." \
+		     -message "Unload all images from memory?" -icon question  ]
+    }
+    
+    if { $ok == "yes" } {	
+	
+	$this ClearAllResults
+	
+	$this SetTitle $global_list(appname)
+	
+	set global_list(mask_fname) ""
+	set global_list(tensor_fname) ""
+    }
+    
+    if { $ok != "cancel" } {
+	$this HideWindow
+    }
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Initialize tool
+# -------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::InitializeControl { } {
+
+    set appname "Vessel Utility v1.0"
+    set aboutstring "(c) Marcel Jackowski and Xenios Papademetris 2006"
+
+    set global_list(appname) "Vessel Utility"
+
+    # create image titles
+    set global_list(result_title) \
+	[ list \
+	      { "Input image"             "input" 1 } \
+	      { "Region of interest mask" "mask" 1 } \
+	      { "Hessian matrix"          "hessian" 1 }\
+	      { "Vesselness measure"      "vessel" 1 } \
+	      { "Maximum scale"           "scale" 1 } ] 
+
+    ## create empty images
+    foreach item $global_list(result_title) {
+ 	lappend result_list [ pxitclimage \#auto ]
+	set global_list(enable_list,[lindex $item 1]) 0
+    }  
+    
+    set global_list(result_fpreffix) "preffix_"
+    set global_list(result_fdir) [ pwd ] 
+    set global_list(result_list) $result_list
+    
+    set global_list(mask_fname) ""
+    set global_list(mask_threshval) 0
+    set global_list(mask_autothresh) 0
+    set global_list(mask_auto) 1
+    
+    set global_list(input_fname) ""
+    set global_list(input_numscales) 5
+    set global_list(input_fromscale) 1.0
+    set global_list(input_toscale) 5.0
+    set global_list(input_logscale) 1
+    set global_list(input_smoothsigma) 1.0
+    set global_list(input_isotropic) 1
+    set global_list(input_scale_vesselness) 1
+    
+    set global_list(vessel_alpha) 0.5
+    set global_list(vessel_beta) 0.5
+    set global_list(vessel_gamma) 0.25
+    set global_list(vessel_maxintensity) 100.0
+    set global_list(vessel_type) 0
+    set global_list(vessel_intensity) 0
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in mask auto status
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::mask_autochanged_cb { } {
+    set state(0) disabled; set state(1) normal        
+    $widget_list(mask_load) buttonconfigure load -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_load) buttonconfigure disp -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_load) buttonconfigure grab -state \
+	$state([expr 1 - $global_list(mask_auto)])
+    $widget_list(mask_fname) configure -state \
+	$state([expr 1 - $global_list(mask_auto)])
+
+    if { $global_list(mask_auto) == 0 } {
+	set global_list(mask_autothresh) 0
+    }
+	
+    $widget_list(mask_autothresh) configure -state \
+	$state($global_list(mask_auto))	
+
+    if { $global_list(mask_autothresh) == 0 } {
+	$widget_list(mask_threshval) configure -state disabled
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in mask thresh status
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::mask_autothreshchanged_cb { } {
+    set state(0) disabled; set state(1) normal
+
+    $widget_list(mask_threshval) configure -state \
+	$state($global_list(mask_autothresh))
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in structure type for detection
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::vessel_type_cb { } {
+    set index [ $widget_list(vessel_type) index [ $widget_list(vessel_type) get ] ]
+    set global_list(vessel_type) $index
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE CALLBACK: Invoked upon a change in structure intensity
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::vessel_intensity_cb { } {
+    set index [ $widget_list(vessel_intensity) index [ $widget_list(vessel_intensity) get ] ]
+    set global_list(vessel_intensity) $index
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Update input information on title bar
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::input_updateinfo { index } {
+
+    set sel_input [ [ lindex $global_list(input_list) $index ] GetImage ]
+    set sel_fname [ lindex $global_list(input_fname) $index ]
+    
+    scan [ $sel_input GetDimensions ] "%d %d %d" dx dy dz	       
+    set nc [  $sel_input GetNumberOfScalarComponents ]
+    set name [ file tail [ file root $sel_fname ] ]
+    
+    set global_list(result_fpreffix) "${name}_"
+
+    $this SetTitle "$global_list(appname): $name (${dx}x${dy}x${dz}, $nc frames)"
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load mask
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::loadmask { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname  [tk_getOpenFile -title "Select mask" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadMask $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in mask image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::LoadMask { fname } {
+
+    set MASK 1     
+    set mask [ lindex $global_list(result_list) $MASK ]
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    $this SetFilterCallbacks $ana "Reading in mask image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    ## if mask not a unsigned char image, convert it
+    set scalar_type [ [ $ana GetOutput ] GetScalarType ]    
+
+    if { $scalar_type != 3 } {	
+	
+	set imcast [ vtkImageCast [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $imcast "Converting mask to unsigned char values..."
+	$imcast SetInput [ $ana GetOutput ]
+	$imcast SetOutputScalarTypeToUnsignedChar
+	$imcast ClampOverflowOn	
+	$imcast Update
+	
+	$mask ShallowCopyImage [ $imcast GetOutput ]
+	
+	$imcast Delete
+	
+    } else {
+	
+	$mask SetFromAnalyzeSource $ana
+    }
+   
+    set global_list(mask_fname) $fname
+
+    WatchOff
+
+    $ana Delete
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Load image
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::loadinput { } {
+
+    ## browse for filename
+    set typelist { {"Analyze/NIFT1 Files" { .hdr .hdr.gz .nii .nii.gz }}}
+    set fname [tk_getOpenFile -title "Select image" -filetypes $typelist -initialdir $global_list(result_fdir) -parent $basewidget ] 
+    
+    if { $fname != "" } {
+	
+	set global_list(result_fdir) [ file dirname $fname ]
+	
+	## load mask into memory
+	LoadInput $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Load in tensor image 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::LoadInput { fname } {
+
+    set INPUT 0
+
+    set input [ lindex $global_list(result_list) $INPUT ]
+
+    ## load series into memory
+    set ana [ vtkpxAnalyzeImageSource  [ pxvtable::vnewobj ]]
+    
+    $this SetFilterCallbacks $ana "Reading input image..."
+    
+    WatchOn
+    
+    ## load series 
+    $ana Load $fname 
+    
+    $input SetFromAnalyzeSource $ana
+    
+    # determine coordinate transform
+    set or [ $ana GetOrientation ]
+    
+    set global_list(input_fname) $fname
+    set global_list(result_fpreffix) "[file root [file tail $fname] ]_"
+    
+    WatchOff
+    
+    $ana Delete
+    
+    $widget_list(computebtn) configure -state normal
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Set result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::SetResultPreffix { preffix } {
+    set global_list(result_fpreffix) $preffix
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Get result filename preffix 
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::GetResultPreffix { } {
+    return $global_list(result_fpreffix)
+}
+
+
+itcl::body mpjvesselutility::SetCurrentDirectory { fname } {
+    set global_list(result_fdir) $fname
+}
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Clear all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::ClearAllResults { } {
+    
+    foreach result $global_list(result_list) {
+	$result Clear
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::SaveAllResults { } {
+
+    foreach result $global_list(result_list) title $global_list(result_title) {
+	
+	set fname $global_list(result_fpreffix)
+	set fname "$fname[ lindex $title 1 ]"
+	
+	$result Save $fname
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Save single result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::SaveResult { index } {        
+
+    set fname $global_list(result_fpreffix)
+    set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]"
+
+    [lindex $global_list(result_list) $index] Save $fname
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save all results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::saveallresults { } {
+
+    ## browse for directory
+    set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+    
+    if { $fdir != "" } {
+	
+	set global_list(result_fdir) $fdir
+	
+	foreach result $global_list(result_list) title $global_list(result_title) {
+	    
+	    set fname $global_list(result_fpreffix)
+	    set fname "$fname[ lindex $title 1 ]"
+	    
+	    $result Save [ file join $fdir $fname ]
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Save results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::saveresult { } {
+    
+    ## get current selection 
+    set sel_item [ $widget_list(result_list) getcurselection ]
+    
+    if { $sel_item != "" } { 
+
+	## browse for directory
+	set fdir [ tk_chooseDirectory -title " Select directory" -parent $basewidget -initialdir $global_list(result_fdir) ]
+	
+	if { $fdir != "" } {
+	    
+	    set global_list(result_fdir) $fdir
+	    
+	    foreach item $sel_item {
+		
+		set index [ $widget_list(result_list) index $item ]
+		set result [ lindex $global_list(result_list) $index ]
+		
+		set fname $global_list(result_fpreffix)
+		set fname "$fname[ lindex [lindex $global_list(result_title) $index ] 1 ]"
+		
+		$result Save [ file join $fdir $fname ]
+	    }
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::DisplayResult { index } {
+    $parent SetImageFromObject \
+	[ [ lindex $global_list(result_list) $index ] GetThisPointer ] $this
+    $parent ShowWindow
+}
+
+itcl::body mpjvesselutility::GrabImage { index } {
+
+    set img [ $parent GetDisplayedImage ]
+    if { [ $img GetImageSize ] > 0 } {
+	[ [ lindex $global_list(result_list) $index ] GetThisPointer ] ShallowCopy $img
+	set fname [ $img cget -filename ]
+	if { [ string length $fname ] < 1 } {
+	    set fname "noname.hdr"
+	}
+	
+	if { $index == 0 } {
+	    set global_list(input_fname) $fname
+	    set global_list(result_fpreffix) "[file root [file tail $fname] ]_"
+	} else {
+	    set global_list(mask_fname) $fname
+	}
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Display result
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::displayresult { } {
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+	    
+    if { $sel_item != "" } {
+	set index [ $widget_list(result_list) index [ lindex $sel_item 0 ] ]
+	set result [ lindex $global_list(result_list) $index ]
+
+	set range [ [ [ [ $result GetImage ] GetPointData ] GetScalars ] GetRange ]
+
+	$this DisplayResult $index	
+    }
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: toggle result computation on/off
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::toggleresult { } {
+   
+    set color(0) \#dcdcdc
+    set color(1) black
+
+    set sel_item [ $widget_list(result_list) getcurselection ]
+
+    if { $sel_item != "" } {
+
+	set index [ $widget_list(result_list) index [ lindex $sel_item 0 ] ]
+
+	if { $index > 4 } {
+	    set enable [expr 1 - [ lindex [ lindex $global_list(result_title) $index ] 2 ] ]
+	    
+	    $widget_list(result_list) itemconfigure $index -foreground $color($enable)
+	    
+	    set item [ lindex $global_list(result_title) $index ]
+	    set new_item [ lreplace $item 2 2 $enable ]
+	    
+	    set global_list(result_title) [ lreplace $global_list(result_title) \
+						$index $index $new_item ]
+	}
+    }
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Clear results
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::result_clear { start end } {
+    
+    for { set i $start } { $i <= $end } { incr i } {
+	
+	set title [ lindex [ lindex $global_list(result_title) $i ] 0 ]	    
+	
+	if { $title == "Region of interest mask" } {
+	    if { $global_list(mask_auto) } {
+		[ lindex $global_list(result_list) $i ] Clear
+	    }
+	} else { 
+	    [ lindex $global_list(result_list) $i ] Clear
+	}
+
+    }
+
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: returns a list of n equally spaced points btwn x1 and x2 inclusive
+#-------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::linspace { x1 x2 n } {
+    
+    set linlist ""
+    
+    if { $n < 2 } { return $x1 }
+    
+    set delta [expr ($x2 - $x1) / ($n - 1) ]
+    for { set i 0 } { $i <= [expr $n - 2] } { incr i } {
+	lappend linlist [expr $x1 + $i*$delta]
+    }
+    lappend linlist $x2
+
+    return $linlist    
+}
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: returns a list of n logarithmically spaced points btwn x1 and x2 inclusive
+#-------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::logspace { x1 x2 n } {
+
+    set loglist ""
+
+    if { $n < 2 } { return $x1 }
+    
+    set linlist [ linspace [expr log10($x1)] [expr log10($x2)] $n ]
+    
+    foreach item $linlist {
+	lappend loglist [expr pow(10,$item)]
+    }
+    
+    return $loglist
+}
+
+
+#-------------------------------------------------------------------------------------------
+#  PRIVATE: Create eigensystem
+#-------------------------------------------------------------------------------------------
+
+itcl::body mpjvesselutility::ResampleImage { img spacing } {
+
+    puts stderr "Resampling at $spacing x $spacing x $spacing "
+
+    set resamp [ vtkImageResample [ pxvtable::vnewobj ]]
+    $resamp SetInput $img
+    $resamp SetAxisOutputSpacing 0 $spacing
+    $resamp SetAxisOutputSpacing 1 $spacing
+    $resamp SetAxisOutputSpacing 2 $spacing
+    $resamp Update
+    set out [ vtkImageData [ pxvtable::vnewobj ]]
+    $out ShallowCopy [ $resamp GetOutput ]
+    $resamp Delete
+
+    puts stderr " Dimensions Input [ $img GetDimensions ] --> Output [ $out GetDimensions ] "
+    return $out
+}
+
+
+itcl::body mpjvesselutility::result_createhessian { } {
+
+    set INPUT 0
+    set MASK 1
+    set HESSIAN 2
+    set VESSEL 3
+    set SIGMA 4
+
+    set input [ lindex $global_list(result_list) $INPUT ]
+    set mask [ lindex $global_list(result_list) $MASK ]
+    set hessian [ lindex $global_list(result_list) $HESSIAN ]
+    set vessel [ lindex $global_list(result_list) $VESSEL ]
+    set sigma [ lindex $global_list(result_list) $SIGMA ]
+
+    $hessian CopyImageHeader [ $input GetImageHeader ]
+    $vessel CopyImageHeader [ $input GetImageHeader ]
+    $sigma CopyImageHeader [ $input GetImageHeader ]
+    
+    set scales 0
+
+    set global_list(input_smoothsigma) [ $widget_list(input_smoothsigma) get ]
+    set smoothsigma $global_list(input_smoothsigma)
+
+    ## generate scales
+    if { $global_list(input_logscale) == 0 } {
+	set scales [ linspace \
+			 $global_list(input_fromscale) \
+			 $global_list(input_toscale)  \
+			 $global_list(input_numscales) ]
+    } else {
+	set scales [ logspace \
+			 $global_list(input_fromscale) \
+			 $global_list(input_toscale)  \
+			 $global_list(input_numscales) ]
+    }
+    
+    if { [expr ([ $input GetImageSize ] == 1) ] } {
+	puts "No image!"
+	return 0
+    }
+
+    set doresample 0
+    set newinput   0
+    set newhess    0
+
+    set cast [ vtkImageCast [ pxvtable::vnewobj ]]
+    $cast SetInput [ $input GetImage ]
+    $cast SetOutputScalarTypeToFloat
+    $cast Update
+
+    set spa [ lsort [ [ $input GetImage ] GetSpacing ] ]
+    
+    if { $global_list(input_isotropic) == 1 } {
+	
+	if { ([ lindex $spa 2 ] - [ lindex $spa 0 ]) > [ expr 0.05* [lindex $spa 1 ] ] } {
+	    set doresample 1
+	    set spx [ expr ( [ lindex $spa 0 ] + [ lindex $spa 1 ] + [ lindex $spa 2 ])/3.0 ]
+	    
+	    set newinput [ ResampleImage [ $cast GetOutput ] $spx ]
+	    if { [ $mask GetImageSize ] > 1 } {
+		set newmask [ ResampleImage [ $mask GetImage ] $spx ]
+	    } else {
+		set newmask 0
+	    }
+	}
+    }
+
+    if { $doresample == 0 } {
+	set newinput [ $cast GetOutput ]
+	if { [ $mask GetImageSize ] > 1 } {
+	    set newmask [ $mask GetImage ]
+	} else {
+	    set newmask 0
+	}
+    }
+
+    set firsttime 1
+    ## hessian filter
+       
+    ## run the filter for all scales
+    foreach sig $scales {
+
+	set hess [ vtkmpjImageHessian [ pxvtable::vnewobj ] ]
+	$hess SetInput $newinput
+	if { $newmask !=0  } {
+	    $hess SetMask $newmask
+	}
+	
+	$hess EnableSmoothingOn
+	$hess SetEnableThresholding $global_list(mask_autothresh)
+	$hess SetThresholdValue $global_list(mask_threshval)
+	$hess AppendSigmaImageOff
+
+	set sgmlabel [format "%7.4f" $sig]
+	$this SetFilterCallbacks $hess "Computing hessian at scale $sgmlabel..."
+	$hess SetSigma $sig
+	$hess Update
+
+	puts stderr "\n\n ************** Hessian Done **************************"
+	
+	## vesselness filter
+	set vess [ vtkmpjImageVesselEnhancement [ pxvtable::vnewobj ] ]
+	$this SetFilterCallbacks $vess "Computing vesselness measure..."
+	$vess SetInput [ $hess GetOutput ]
+	if { $newmask != 0 } { 
+	    $vess SetMask $newmask
+	}
+	
+	$vess SetAlpha $global_list(vessel_alpha)
+	$vess SetBeta  $global_list(vessel_beta)
+	$vess SetGamma [ expr $global_list(vessel_gamma) * $global_list(vessel_maxintensity) ]
+	$vess SetStructureType $global_list(vessel_type)
+	$vess SetBrightStructure [expr 1 - $global_list(vessel_intensity) ]
+	if { $global_list(input_scale_vesselness) == 1 } {
+	    $vess SetVesselnessScaleFactor 1000.0
+	} else {
+	    $vess SetVesselnessScaleFactor 1.0
+	}
+	
+	## compute vesselness measure
+	$vess Update
+	puts stderr "\n\n ************** Vesselness Done **************************"
+
+    
+	## store maximum
+	if { $firsttime ==1 } {
+	    
+	    ## store hessian
+	    $hessian ShallowCopyImage [ $hess GetOutput ]
+
+	    ## store vesselness
+	    $vessel ShallowCopyImage [ $vess GetOutput ]
+	    
+	    ## store sigma
+	    [ $sigma GetImage ] CopyStructure  $newinput
+	    [ $sigma GetImage ] SetScalarTypeToFloat 
+	    [ $sigma GetImage ] AllocateScalars
+	    [ [ [ $sigma GetImage ] GetPointData ] GetScalars ] FillComponent 0 $sig
+	    set firsttime 0
+	} else {
+	    $vess UpdateHessianResponse [ $hessian GetImage ] [ $vessel GetImage ] [ $sigma GetImage ] [ $hess GetOutput ] [ $vess GetOutput ] $sig
+	    puts stderr "\n\n ************** Max Done **************************"
+	}
+
+	$hess Delete
+	$vess Delete
+	puts stderr "\n\n ************** Cleanup Done **************************"
+
+    }
+
+    if { $smoothsigma > 0.0 } { 
+	
+	set s1  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+	$s1 SetStandardDeviations $smoothsigma $smoothsigma $smoothsigma
+	$s1 SetInput [ $vessel GetImage ]
+	$s1 Update
+	$vessel ShallowCopyImage [ $s1 GetOutput ]
+	$s1 Delete
+
+    	set s2  [ vtkImageGaussianSmooth [ pxvtable::vnewobj ]  ]
+	$s2 SetStandardDeviations $smoothsigma $smoothsigma $smoothsigma
+	$s2 SetInput [ $sigma GetImage ]
+	$s2 Update
+	$sigma ShallowCopyImage [ $s2 GetOutput ]
+	$s2 Delete
+    }
+
+    if { $doresample == 1 } {
+
+	puts stderr "Scaling scales by $spx "
+
+	set sc [ vtkImageShiftScale [ pxvtable::vnewobj ]]
+	$sc SetInput [ $sigma GetImage ]
+	$sc SetShift 0.0
+	$sc SetScale $spx
+	$sc Update
+	$sigma ShallowCopyImage [ $sc GetOutput ]
+	$sc Delete
+
+	catch { $newinput Delete } 
+	catch { $newmask  Delete  }
+    }
+
+    $cast Delete
+    
+    update idletasks
+
+    $parent SetResultsFromObject [ $vessel GetThisPointer ] $this
+
+
+    return 1
+}
+
+#-------------------------------------------------------------------------------------------
+#  PUBLIC: Compute results
+# -----------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::ComputeResults { } {
+    
+    set MASK 1
+    
+    WatchOn
+    
+    ## clear results
+    result_clear $MASK [ expr [ llength $global_list(result_list) ] -1 ]
+    
+    $widget_list(notebook) view "Results"; update
+
+    ## create maps
+    result_createhessian
+    
+    WatchOff
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create tensor control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::CreateTensorControl { base } {
+    
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Input image"
+    pack $base.frame0 -fill both -expand f -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+  
+    set input_fname [ iwidgets::entryfield $subframe1.input_fname \
+			   -textvariable [ itcl::scope global_list(input_fname) ] \
+			   -labeltext "Filename:" ] 
+    pack $input_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(input_fname) $input_fname
+    
+    set input_load [ iwidgets::buttonbox $subframe1.input_load -orient horizontal -padx 2 ]
+    $input_load add load -text "Load..." -command [ itcl::code $this loadinput ] 
+    $input_load add disp -text "Display" -command [ itcl::code $this DisplayResult 0 ]
+    $input_load add grab -text "Grab" -command [ itcl::code $this GrabImage 0 ]
+    pack $input_load -side left
+    set widget_list(input_load) $input_load  
+
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Region of interest mask"
+    pack $base.frame1 -fill both -expand f
+
+    set frame1 [ $base.frame1 childsite ]
+
+    set subframe0 [ frame $frame1.subframe0 ]
+    pack $subframe0 -side top -fill both -expand f -pady 5
+
+    set mask_auto [ checkbutton $subframe0.mask_auto -text "Use entire image for computation" \
+			-variable [ itcl::scope global_list(mask_auto) ] \
+			-command [ itcl::code $this mask_autochanged_cb ] ]
+    pack $mask_auto -side left -fill both -padx 5 -pady 5
+    
+    set mask_threshval [ iwidgets::entryfield $subframe0.mask_threshval \
+			     -validate real \
+			     -width 5 \
+			     -textvariable [ itcl::scope global_list(mask_threshval) ] \
+			     -state disabled ]
+    pack $mask_threshval -side right -pady 5 -padx 5
+    set widget_list(mask_threshval) $mask_threshval
+
+    set mask_autothresh [ checkbutton $subframe0.mask_autothresh \
+			      -text "Threshold image at:" \
+			      -variable [ itcl::scope global_list(mask_autothresh) ] \
+			      -command [ itcl::code $this mask_autothreshchanged_cb ] ]    
+    pack $mask_autothresh -side right -pady 5
+    set widget_list(mask_autothresh) $mask_autothresh
+
+    set subframe1 [ frame $frame1.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 0
+    
+    set mask_fname [ iwidgets::entryfield $subframe1.mask_fname \
+			 -textvariable [ itcl::scope global_list(mask_fname) ] \
+			 -labeltext "Filename:" ] 
+    pack $mask_fname -side top -expand t -fill x -padx 5 -pady 5
+    set widget_list(mask_fname) $mask_fname
+
+    set mask_load [ iwidgets::buttonbox $subframe1.mask_load -orient horizontal -padx 2 ]
+    $mask_load add load -text "Load..." -command [ itcl::code $this loadmask ] -state disabled  
+    $mask_load add disp -text "Display" -command [ itcl::code $this DisplayResult 1 ] -state disabled
+    $mask_load add grab -text "Grab" -command [ itcl::code $this GrabImage 1 ] -state disabled
+    pack $mask_load -side left 
+    set widget_list(mask_load) $mask_load
+    
+
+
+
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create vessel enhancement control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::CreateVesselControl { base } {
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Sensitivity parameters"
+    pack $base.frame0 -fill both -expand f -pady 5
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 2
+    
+    set vessel_alpha [ iwidgets::entryfield $subframe1.vessel_alpha \
+			   -labeltext "Alpha:" \
+			   -validate real \
+			   -width 4 \
+			   -textvariable [ itcl::scope global_list(vessel_alpha) ] ]
+    pack $vessel_alpha -side left -pady 7 -padx 5
+    set widget_list(vessel_alpha) $vessel_alpha
+
+    set vessel_beta [ iwidgets::entryfield $subframe1.vessel_beta \
+			   -labeltext "Beta:" \
+			   -validate real \
+			   -width 4 \
+			   -textvariable [ itcl::scope global_list(vessel_beta) ] ]
+    pack $vessel_beta -side left -pady 7 -padx 5
+    set widget_list(vessel_beta) $vessel_beta
+
+    set vessel_gamma [ iwidgets::entryfield $subframe1.vessel_gamma \
+			   -labeltext "Gamma:" \
+			   -validate real \
+			   -width 4 \
+			   -textvariable [ itcl::scope global_list(vessel_gamma) ] ]
+    pack $vessel_gamma -side left -pady 7 -padx 5
+    set widget_list(vessel_gamma) $vessel_gamma
+
+    set vessel_maxintensity [ iwidgets::entryfield $subframe1.vessel_maxintensity \
+				  -labeltext "Maximum intensity:" \
+				  -validate real \
+				  -width 7 \
+				  -textvariable [ itcl::scope global_list(vessel_maxintensity) ] ]
+    pack $vessel_maxintensity -side left -pady 7 -padx 5
+    set widget_list(vessel_maxintensity) $vessel_maxintensity
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill both -expand f -pady 2
+        
+    set vessel_type \
+	[ iwidgets::optionmenu $subframe2.vessel_type \
+	      -command [ itcl::code $this vessel_type_cb ] \
+	      -labeltext "Structure type:" ]
+    $vessel_type insert 2 "Blob"
+    $vessel_type insert 1 "Plate"
+    $vessel_type insert 0 "Tubular"
+    pack $vessel_type -side left -padx 5 -pady 5
+    set widget_list(vessel_type) $vessel_type    
+    $vessel_type select 0
+
+    set vessel_intensity \
+	[ iwidgets::optionmenu $subframe2.vessel_intensity \
+	      -command [ itcl::code $this vessel_intensity_cb ] \
+	      -labeltext "Structure intensity:" ]
+    $vessel_intensity insert 1 "Dark"
+    $vessel_intensity insert 0 "Bright"
+    pack $vessel_intensity -side left -padx 5 -pady 5
+    set widget_list(vessel_intensity) $vessel_intensity
+    $vessel_intensity select 0
+    
+
+    iwidgets::labeledframe $base.frame1 \
+	-labelpos nw  \
+	-labeltext "Multiscale analysis"
+    pack $base.frame1 -fill both -expand f -pady 0
+    
+    set frame0 [ $base.frame1 childsite ]
+    
+    set subframe1 [ frame $frame0.subframe1 ]
+    pack $subframe1 -side top -fill both -expand f -pady 5
+
+    set input_numscales [ iwidgets::spinint $subframe1.input_numscales \
+			      -labeltext "Number of scales:" \
+			      -fixed 3 -width 3 -range {1 100} -step 1 \
+			      -textvariable [ itcl::scope global_list(input_numscales) ] ]
+    pack $input_numscales -side left -pady 5 -padx 10
+    set global_list(input_numscales) 5
+    set widget_list(input_numscales) $input_numscales
+
+    label $subframe1.dummyspace0 -text ""
+    pack $subframe1.dummyspace0 -side left -padx 2
+
+    set input_fromscale [ iwidgets::entryfield $subframe1.input_fromscale \
+			      -labeltext "Range:" \
+			      -validate real \
+			      -width 4 \
+			      -textvariable [ itcl::scope global_list(input_fromscale) ] ]
+    pack $input_fromscale -side left -pady 5 -padx 0
+    set widget_list(input_fromscale) $input_fromscale
+
+    set input_toscale [ iwidgets::entryfield $subframe1.input_toscale \
+			    -labeltext ":" \
+			    -validate real \
+			    -width 4 \
+			    -textvariable [ itcl::scope global_list(input_toscale) ] ]
+    pack $input_toscale -side left -pady 5 -padx 0
+    set widget_list(input_toscale) $input_toscale
+
+    label $subframe1.dummyspace1 -text "pixels"
+    pack $subframe1.dummyspace1 -side left -padx 3
+
+    set input_logscale [ checkbutton $subframe1.input_logscale \
+			     -text "Logarithmic" \
+			     -variable [ itcl::scope global_list(input_logscale) ] ]
+    pack $input_logscale -side right -fill both -padx 10 -pady 5
+
+
+
+    iwidgets::labeledframe $base.frame2 \
+	-labelpos nw  \
+	-labeltext "Other Processing"
+    pack $base.frame2 -fill both -expand f -pady 0 -side top
+    
+    set frame2 [ $base.frame2 childsite ]
+
+    set w1 [ checkbutton $frame2.iso -text "Isotropic voxels" \
+		 -variable [ itcl::scope global_list(input_isotropic) ] ]
+    set w2 [ checkbutton $frame2.vsc -text "Vesselness x1000" \
+		 -variable [ itcl::scope global_list(input_scale_vesselness) ] ]
+
+    set w [ iwidgets::optionmenu $frame2.sigma \
+		-labeltext "Smooth Output:" ]
+    $w insert 0 "0.0"
+    $w insert 1 "0.5"
+    $w insert 2 "1.0"
+    $w insert 3 "1.5"
+    $w insert 4 "2.0"
+    pack $w2 $w1 $w -side left -padx 2 -pady 5
+    $w select 2
+
+    set widget_list(input_smoothsigma) $w
+
+
+    
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create results control
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::CreateResultsControl { base } {   
+
+    set color(0) \#dcdcdc
+    set color(1) black
+
+    iwidgets::labeledframe $base.frame0 \
+	-labelpos nw  \
+	-labeltext "Results"
+    pack $base.frame0 -fill both -expand t 
+    
+    set frame0 [ $base.frame0 childsite ]
+    
+    set subframe0 [ frame $frame0.subframe0 ]
+    pack $subframe0 -fill both -expand t
+    
+    iwidgets::scrolledlistbox $subframe0.resultlist \
+	-hscrollmode dynamic \
+	-selectmode extended \
+	-dblclickcommand [ itcl::code $this toggleresult ] \
+	-visibleitems 40x10 
+    
+    pack $subframe0.resultlist -side left -fill both -expand t -padx 2 -pady 2
+    set widget_list(result_list) $subframe0.resultlist
+    
+    foreach item $global_list(result_title) {
+	set enable [ lindex $item 2 ]
+     	$widget_list(result_list) insert end "[lindex $item 0]" 
+	$widget_list(result_list) itemconfigure end -foreground $color($enable)
+    }
+
+    set subframe1 [ frame $subframe0.subframe1 ]
+    pack $subframe1 -side right -fill both -padx 0
+    
+    set resultbbox [ iwidgets::buttonbox $subframe1.input -orient vertical ]
+    $resultbbox add display -text "Display" -command [ itcl::code $this displayresult ]
+    $resultbbox add save -text "Save..." -command [ itcl::code $this saveresult ]
+    $resultbbox add saveall -text "Save all" -command [ itcl::code $this saveallresults ]    
+    pack $resultbbox -side top -fill x -expand t -padx 0
+    set widget_list(result_buttonbox) $resultbbox
+
+    set subframe2 [ frame $frame0.subframe2 ]
+    pack $subframe2 -side top -fill x -padx 2 -pady 5
+
+    set result_fpreffix [ iwidgets::entryfield $subframe2.result_fpreffix \
+			      -textvariable [ itcl::scope global_list(result_fpreffix) ] \
+			      -labeltext "Preffix:" ]
+    pack $result_fpreffix -side left -fill x -expand t -padx 5 -pady 2
+    set widget_list(result_fpreffix) $result_fpreffix    
+}
+
+# -------------------------------------------------------------------------------------------
+#  Diffusion control inititialization
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::Initialize { widget } {
+    
+    if { $initialized == 1 } { return $basewidget }
+    
+    #  -------------------------------------
+    #  Create User Interface
+    #  -------------------------------------	
+    set basewidget [toplevel $widget ]
+    wm geometry $basewidget 610x450
+    wm withdraw $basewidget
+
+    set notebook $basewidget.notebook    
+    iwidgets::tabnotebook $notebook -tabpos w         
+    set widget_list(notebook) $notebook
+
+    set mb [ frame $basewidget.mb ]
+    pack $mb -side top -fill x -expand false
+    
+    #    CreateMenu $mb
+
+    CreateTensorControl     [ $notebook add -label "Input"  ]
+    CreateVesselControl     [ $notebook add -label "Vesselness" ]
+    CreateResultsControl    [ $notebook add -label "Results" ] 
+    
+    pack $notebook -side top -fill both -expand t -padx 5
+
+    set bottom [ frame $basewidget.bottom -relief ridge]
+    pack $bottom -side top -fill x -expand false
+    
+    set pbar [ frame $basewidget.pbar -width 400 -height 20 ]
+    pack $pbar -side bottom -expand f -fill x
+    CreateProgressBar $pbar
+    
+    set w [ frame $basewidget.w -relief ridge -width 800]
+    pack $w -side bottom -fill x -expand false
+    
+    eval "button $w.close -text Close -command { $this DismissWindow }"
+    eval "button $w.help -text About -command { $this AboutCommand }"
+    pack $w.close $w.help -side right -fill x -padx 10 -pady 10
+
+    set widget_list(computebtn) [ button $w.compute -text "Compute!" \
+				      -state normal \
+				      -command [ itcl::code $this ComputeResults ] ]    
+    pack $w.compute -side left -fill x -expand true -padx 20 -pady 10  
+   
+
+    
+
+    set initialized 1
+
+    SetTitle "Vessel Utility v1.0"
+    eval "wm protocol $basewidget WM_DELETE_WINDOW { $this DismissWindow }"
+
+    return $basewidget 
+}
+
+#-------------------------------------------------------------------------------------------
+#  Add controls to menu button
+# ------------------------------------------------------------------------------------------
+itcl::body mpjvesselutility::AddToMenuButton { mb args } {
+    eval "$mb add command -label \"Vessel utility\" -command {$this ShowWindow \"Input\"}"
+}
+
+#-------------------------------------------------------------------------------------------
+#  Create top level menu button
+# ------------------------------------------------------------------------------------------
+# itcl::body mpjvesselutility::CreateMenu { mb } {    
+    
+#     menubutton $mb.file          -text Setup       -menu $mb.file.m -underline 0
+#     pack $mb.file $mb.file    -side left
+#     menubutton $mb.results       -text Results     -menu $mb.results.m -underline 0
+#     pack $mb.file $mb.results    -side left
+#     menubutton $mb.help      -text Help         -menu $mb.help.m -underline 0 -padx 4
+#     pack $mb.help  -side right
+    
+#     menu $mb.file.m -tearoff 0 
+#     if { $parent == 0 } {
+# 	eval "$mb.file.m add command -label Exit -command {  pxtkexit } -underline 1"
+#     } else {
+# 	eval "$mb.file.m add command -label Close -command {  $this HideWindow } -underline 1"
+#     }
+
+#     menu $mb.results.m -tearoff 0 
+#     eval "$mb.results.m add command -label \"Compute All\" -command { $this ComputeResults } -underline 0 -state disabled"
+#     $mb.results.m add command -label "Save All Results" -command [ itcl::code $this saveallresults ] -underline 0
+    
+#     menu $mb.help.m -tearoff 0
+    
+#     set widget_list(menu_results) $mb.results.m    
+    
+#     eval "$mb.help.m add command -label About -command { $this AboutCommand }"
+# }
+
+#-------------------------------------------------------------------------------------------
+#  Main function for stand-alone execution
+# ------------------------------------------------------------------------------------------
+if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } {
+
+    puts "\n[ file rootname $argv0 ] is not a stand-alone program.\n"
+    exit
+}
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/pkgIndex.tcl b/bioimagesuite30_src/bioimagesuite/mjack/pkgIndex.tcl
new file mode 100644
index 0000000..99e6fbe
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/pkgIndex.tcl
@@ -0,0 +1,60 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+# Tcl package index file, version 1.1
+# This file is generated by the "pkg_mkIndex" command
+# and sourced either when an application starts up or
+
+
+
+
+# by a "package unknown" script.  It invokes the
+# "package ifneeded" command to set up package-related
+# information so that packages will be loaded automatically
+# in response to "package require" commands.  When this
+# script is sourced, the variable $dir must contain the
+# full path name of this file's directory.
+
+package ifneeded Vtktkimageviewerwidget 1.2 [list source [file join $dir vtkmpjcontrib.tcl]]
+package ifneeded Vtktkimagewindowwidget 1.2 [list source [file join $dir vtkmpjcontrib.tcl]]
+package ifneeded Vtktkrenderwidget 1.2 [list source [file join $dir vtkmpjcontrib.tcl]]
+package ifneeded mpjguiobject 1.0 [list source [file join $dir mpjguiobject.tcl]]
+package ifneeded vtkmpjcontrib 1.2 [list source [file join $dir vtkmpjcontrib.tcl]]
+package ifneeded mpjguilookuptable 1.0 [list source [file join $dir mpjguilookuptable.tcl]]
+package ifneeded mpjguisphere 1.0 [list source [file join $dir mpjguisphere.tcl]]
+package ifneeded mpjguiicosahedron 1.0 [list source [file join $dir mpjguiicosahedron.tcl]]
+package ifneeded mpjtensorutility 1.3 [list source [file join $dir mpjtensorutility.tcl]]
+package ifneeded mpjtensoranalysis 1.3 [list source [file join $dir mpjtensoranalysis.tcl]]
+package ifneeded mpjfibertracking 1.2 [list source [file join $dir mpjfibertracking.tcl]]
+package ifneeded mpjvesselutility 1.0 [list source [file join $dir mpjvesselutility.tcl]]
+package ifneeded mpjvesselanalysis 1.3 [list source [file join $dir mpjvesselanalysis.tcl]]
+package ifneeded mpjvesseltracking 1.0 [ list source [file join $dir mpjvesseltracking.tcl]]
+package ifneeded mpjfastmarching 1.2 [list source [file join $dir mpjfastmarching.tcl]]
+
+package ifneeded mpjmultibtensorutility 1.3 [list source [file join $dir mpjmultibtensorutility.tcl]]
+package ifneeded mpjconnectivity 1.0 [list source [file join $dir mpjconnectivity.tcl]]
+
diff --git a/bioimagesuite30_src/bioimagesuite/mjack/vtkmpjcontrib.tcl b/bioimagesuite30_src/bioimagesuite/mjack/vtkmpjcontrib.tcl
new file mode 100644
index 0000000..d233e9b
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/mjack/vtkmpjcontrib.tcl
@@ -0,0 +1,42 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+package provide vtkmpjcontrib 1.2
+
+# 	$Id: vtkmpjcontrib.tcl,v 1.1 2005/12/01 16:42:26 xenios Exp xenios $	
+
+
+
+
+
+lappend auto_path [ file dirname [ info script ]]
+lappend auto_path [ file join [ file join [ file join  [ file dirname [ info script ]] .. ] extensions ] lib ]
+
+package require vtkpxcontrib 1.2
+
+::pxtclvtkpxcontrib::LoadLibraries { vtkmpjCommonTCL  vtkmpjDiffusionTCL vtkmpjLevelsetTCL }
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/CMakeLists.txt b/bioimagesuite30_src/bioimagesuite/origscripts/CMakeLists.txt
new file mode 100644
index 0000000..390a772
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/CMakeLists.txt
@@ -0,0 +1,141 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+
+SET(KITSCRIPTS 
+  setpaths.sh.in
+  setpaths.csh.in  
+  setpaths_console.sh.in  
+  runscript.in
+)
+
+SET(WINAPPS
+  setpaths.bat.in
+  bisconsole.bat.in
+  bisexec.bat.in
+  biscppexec.bat.in
+  bioimagesuite.bat.in
+  runscript.bat.in
+  )
+
+SET(UNIXAPPS
+  start_bioimagesuite.in
+  bis_console.in
+  bisexec.in
+  biscppexec.in
+ )	
+
+IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+SET (UNIXAPPS
+${UNIXAPPS}
+createmenuentries.sh.in
+)
+ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+
+
+SET(KITAPPS 
+  ${WINAPPS}
+  ${UNIXAPPS}
+)
+
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+#bis_complex_tcl3src(PATHNAME SHORTPATH FILEHANDLE)
+bis_complex_tcl3src(bioimagesuite/origscripts origscripts ${FILELIST})
+
+
+
+# ---------------------------------------------------------------------------
+#  Put the main files 
+# ---------------------------------------------------------------------------
+
+
+IF (BIOIMAGESUITE_INSTALL_SOURCE)
+  install(FILES ${KITSCRIPTS} DESTINATION  ${BIOIMAGESUITE_INSTALL_SRCPATH}/bioimagesuite/origscripts)
+  install(PROGRAMS ${KITAPPS} DESTINATION  ${BIOIMAGESUITE_INSTALL_SRCPATH}/bioimagesuite/origscripts)
+ENDIF (BIOIMAGESUITE_INSTALL_SOURCE)
+
+IF (UNIX)
+  SET(KITAPPS
+    ${UNIXAPPS})
+ELSE(UNIX)
+  SET(KITAPPS
+    ${WINAPPS})
+
+  IF (BIS_UNIXBUILD)
+    SET(KITAPPS
+      ${KITAPPS}
+      setpaths.sh.in
+      bisexec.in
+      biscppexec.in
+      )
+  ENDIF (BIS_UNIXBUILD)
+    
+  SET(KITSCRIPTS )
+ENDIF(UNIX)
+
+
+
+
+SET (TMP  ${KITSCRIPTS} ${KITAPPS} )
+FOREACH (item ${TMP})
+
+  STRING (REGEX REPLACE ".in+" "" item2 ${item})
+#  MESSAGE("Mapping ${item} to ${item2}")
+  configure_file( ${BIOIMAGESUITE3_SOURCE_DIR}/bioimagesuite/origscripts/${item}
+    ${BIOIMAGESUITE3_BINARY_DIR}/${item2} @ONLY )
+  
+  install(FILES ${BIOIMAGESUITE3_BINARY_DIR}/${item2}  DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/${SHORTPATH}
+    PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE WORLD_READ WORLD_EXECUTE )
+  FILE(APPEND ${SCRIPTFILELIST} "${item2}\n")
+ENDFOREACH(item ${TMP})
+
+IF (UNIX)
+  EXECUTE_PROCESS (COMMAND chmod +x  ${BIOIMAGESUITE3_BINARY_DIR}/bisexec)
+  EXECUTE_PROCESS (COMMAND chmod +x  ${BIOIMAGESUITE3_BINARY_DIR}/biscppexec)
+ELSE (UNIX)
+  IF (BIS_UNIXBUILD)
+    EXECUTE_PROCESS (COMMAND chmod +x  ${BIOIMAGESUITE3_BINARY_DIR}/bisexec)
+    EXECUTE_PROCESS (COMMAND chmod +x  ${BIOIMAGESUITE3_BINARY_DIR}/biscppexec)
+  ENDIF (BIS_UNIXBUILD)
+ENDIF (UNIX)
+
+
+
+install(SCRIPT ${BIOIMAGESUITE3_BINARY_DIR}/bioimagesuitepostinstall.cmake )
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/bioimagesuite.bat.in b/bioimagesuite30_src/bioimagesuite/origscripts/bioimagesuite.bat.in
new file mode 100755
index 0000000..e690113
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/bioimagesuite.bat.in
@@ -0,0 +1,19 @@
+ at echo off
+REM --------------------------------------------------------------------------------------
+REM This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+REM --------------------------------------------------------------------------------------
+
+REM bis_fix_script_begin
+SET BIOIMAGESUITE=@BIOIMAGESUITE3_BINARY_DIR_BAT@
+SET BIS_VTK_DIR=@VTK_DIR_BAT@
+SET BIOIMAGESUITE3_BINARY_DIR=@BIOIMAGESUITE3_BINARY_DIR_BAT@
+SET BINPATH=@EXECUTABLE_OUTPUT_PATH_BAT@
+SET BASELIB=@LIBRARY_OUTPUT_PATH_BAT@
+REM bis_fixscript_end
+
+call %BIOIMAGESUITE%\setpaths.bat
+echo BioimageSuite menu starting
+
+
+vtk %BIOIMAGESUITE%\main\bis.tcl
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/bis_console.in b/bioimagesuite30_src/bioimagesuite/origscripts/bis_console.in
new file mode 100755
index 0000000..9041f24
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/bis_console.in
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+# --------------------------------------------------------------------------------------
+# This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+# --------------------------------------------------------------------------------------
+#bis_fix_script_begin
+BASE=@BIOIMAGESUITE3_BINARY_DIR@
+BIS_VTK_DIR=@VTK_DIR@
+#bis_fixscript_end
+
+exec xterm -fn 10x20 -bg darkblue -fg white -title "BioImage Suite Console $BASE" -e bash -rcfile ${BASE}/setpaths_console.sh
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/bisconsole.bat.in b/bioimagesuite30_src/bioimagesuite/origscripts/bisconsole.bat.in
new file mode 100755
index 0000000..9a6f906
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/bisconsole.bat.in
@@ -0,0 +1,14 @@
+ at echo off
+REM --------------------------------------------------------------------------------------
+REM This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+REM --------------------------------------------------------------------------------------
+
+REM bis_fix_script_begin
+SET BIOIMAGESUITE=@BIOIMAGESUITE3_BINARY_DIR_BAT@
+SET BIS_VTK_DIR=@VTK_DIR_BAT@
+REM bis_fixscript_end
+
+
+
+cmd.exe /k %BIOIMAGESUITE%\setpaths.bat
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/biscppexec.bat.in b/bioimagesuite30_src/bioimagesuite/origscripts/biscppexec.bat.in
new file mode 100755
index 0000000..e61119c
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/biscppexec.bat.in
@@ -0,0 +1,17 @@
+ at echo off
+REM --------------------------------------------------------------------------------------
+REM This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+REM --------------------------------------------------------------------------------------
+
+REM bis_fix_script_begin
+SET BIOIMAGESUITE=@BIOIMAGESUITE3_BINARY_DIR_BAT@
+SET BIS_VTK_DIR=@VTK_DIR_BAT@
+SET BIOIMAGESUITE3_BINARY_DIR=@BIOIMAGESUITE3_BINARY_DIR_BAT@
+SET BINPATH=@EXECUTABLE_OUTPUT_PATH_BAT@
+SET BASELIB=@LIBRARY_OUTPUT_PATH_BAT@
+REM bis_fixscript_end
+
+call %BIOIMAGESUITE%\setpaths.bat
+
+%*
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/biscppexec.in b/bioimagesuite30_src/bioimagesuite/origscripts/biscppexec.in
new file mode 100755
index 0000000..de2a8ca
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/biscppexec.in
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+
+# --------------------------------------------------------------------------------------
+# This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+# --------------------------------------------------------------------------------------
+
+#bis_fix_script_begin
+BASE=@BIOIMAGESUITE3_BINARY_DIR@
+BIS_VTK_DIR=@VTK_DIR@
+BIOIMAGESUITE3_BINARY_DIR=@BIOIMAGESUITE3_BINARY_DIR@
+BINPATH=@EXECUTABLE_OUTPUT_PATH@
+BASELIB=@LIBRARY_OUTPUT_PATH@
+#bis_fixscript_end
+
+source ${BASE}/setpaths.sh > /dev/null
+SNAME=$1
+shift 1
+echo "Executing Command = $SNAME -- $@"
+
+${SNAME}  $@
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/bisexec.bat.in b/bioimagesuite30_src/bioimagesuite/origscripts/bisexec.bat.in
new file mode 100755
index 0000000..8509aa8
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/bisexec.bat.in
@@ -0,0 +1,20 @@
+ at echo off
+REM --------------------------------------------------------------------------------------
+REM This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+REM --------------------------------------------------------------------------------------
+
+REM bis_fix_script_begin
+SET BIOIMAGESUITE=@BIOIMAGESUITE3_BINARY_DIR_BAT@
+SET BIS_VTK_DIR=@VTK_DIR_BAT@
+SET BIOIMAGESUITE3_BINARY_DIR=@BIOIMAGESUITE3_BINARY_DIR_BAT@
+SET BINPATH=@EXECUTABLE_OUTPUT_PATH_BAT@
+SET BASELIB=@LIBRARY_OUTPUT_PATH_BAT@
+REM bis_fixscript_end
+
+call %BIOIMAGESUITE%\setpaths.bat
+
+echo "Using vtk=%BIS_VTK_DIR%\..\..\bin\vtk"
+echo "Scriptname = %*"
+
+%BIS_VTK_DIR%\..\..\bin\vtk  %*
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/bisexec.in b/bioimagesuite30_src/bioimagesuite/origscripts/bisexec.in
new file mode 100755
index 0000000..4b5b3ef
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/bisexec.in
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+
+# --------------------------------------------------------------------------------------
+# This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+# --------------------------------------------------------------------------------------
+
+#bis_fix_script_begin
+BASE=@BIOIMAGESUITE3_BINARY_DIR@
+BIS_VTK_DIR=@VTK_DIR@
+BIOIMAGESUITE3_BINARY_DIR=@BIOIMAGESUITE3_BINARY_DIR@
+BINPATH=@EXECUTABLE_OUTPUT_PATH@
+BASELIB=@LIBRARY_OUTPUT_PATH@
+#bis_fixscript_end
+
+source ${BASE}/setpaths.sh > /dev/null
+SNAME=$1
+shift 1
+echo "Executing Scriptname = $SNAME -- $@"
+
+${BIS_VTK_DIR}/../../bin/vtk ${SNAME} -- $@
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/createmenuentries.sh.in b/bioimagesuite30_src/bioimagesuite/origscripts/createmenuentries.sh.in
new file mode 100755
index 0000000..cd0bf00
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/createmenuentries.sh.in
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+
+# --------------------------------------------------------------------------------------
+# This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+# --------------------------------------------------------------------------------------
+
+#bis_fix_script_begin
+BASE=@BIOIMAGESUITE3_SOURCE_DIR@/bioimagesuite
+#bis_fixscript_end
+
+# ----------------------------------
+# BIOIMAGESUITE: No edits below here
+# ----------------------------------
+
+${BASE}/installtools/bis_creategnomeentries ${BASE} 
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/runscript.bat.in b/bioimagesuite30_src/bioimagesuite/origscripts/runscript.bat.in
new file mode 100755
index 0000000..910f048
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/runscript.bat.in
@@ -0,0 +1,25 @@
+ at echo off
+REM --------------------------------------------------------------------------------------
+REM This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+REM --------------------------------------------------------------------------------------
+
+REM bis_fix_script_begin
+SET BIOIMAGESUITE=@BIOIMAGESUITE3_SOURCE_DIR_BAT@\bioimagesuite
+SET BIS_VTK_DIR=@VTK_DIR_BAT@
+SET BIOIMAGESUITE3_BINARY_DIR=@BIOIMAGESUITE3_BINARY_DIR_BAT@
+SET BINPATH=@EXECUTABLE_OUTPUT_PATH_BAT@
+SET BASELIB=@LIBRARY_OUTPUT_PATH_BAT@
+REM bis_fixscript_end
+
+ at if not exist %BIOIMAGESUITE3_BINARY_DIR%\setpaths.bat goto TAG2
+  call %BIOIMAGESUITE3_BINARY_DIR%\setpaths.bat	
+  goto TAG3
+
+:TAG2
+  call %BIOIMAGESUITE%\setpaths.bat
+
+:TAG3
+
+REM echo Invoking %BIS_VTK_DIR%\..\..\bin\vtk.exe  %BIOIMAGESUITE%\bis_algorithm\@item at .tcl 
+%BIS_VTK_DIR%\..\..\bin\vtk.exe  %BIOIMAGESUITE%\bis_algorithm\@item at .tcl -- %*
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/runscript.in b/bioimagesuite30_src/bioimagesuite/origscripts/runscript.in
new file mode 100644
index 0000000..03a4e51
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/runscript.in
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+
+# --------------------------------------------------------------------------------------
+# This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+# --------------------------------------------------------------------------------------
+
+#bis_fix_script_begin
+BASE=@BIOIMAGESUITE3_SOURCE_DIR@/bioimagesuite
+BIS_VTK_DIR=@VTK_DIR@
+BIOIMAGESUITE3_BINARY_DIR=@BIOIMAGESUITE3_BINARY_DIR@
+BINPATH=@EXECUTABLE_OUTPUT_PATH@
+BASELIB=@LIBRARY_OUTPUT_PATH@
+#bis_fixscript_end
+
+
+if [ -n "$BIOIMAGESUITE3_BINARY_DIR" ]; then
+    source ${BIOIMAGESUITE3_BINARY_DIR}/setpaths.sh > /dev/null
+else
+    source ${BASE}/setpaths.sh > /dev/null
+fi
+
+#echo "Running ${BIS_VTK_DIR}/../../bin/vtk ${BASE}/bis_algorithm/@item at .tcl"
+
+${BIS_VTK_DIR}/../../bin/vtk ${BASE}/bis_algorithm/@item at .tcl -- $@
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/setpaths.bat.in b/bioimagesuite30_src/bioimagesuite/origscripts/setpaths.bat.in
new file mode 100755
index 0000000..a45b621
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/setpaths.bat.in
@@ -0,0 +1,26 @@
+ at echo off
+REM --------------------------------------------------------------------------------------
+REM This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+REM --------------------------------------------------------------------------------------
+
+REM bis_fix_script_begin
+SET BIOIMAGESUITE=@BIOIMAGESUITE3_SOURCE_DIR_BAT@\bioimagesuite
+SET BIS_VTK_DIR=@VTK_DIR_BAT@
+SET BIOIMAGESUITE3_BINARY_DIR=@BIOIMAGESUITE3_BINARY_DIR_BAT@
+SET BINPATH=@EXECUTABLE_OUTPUT_PATH_BAT@
+SET BASELIB=@LIBRARY_OUTPUT_PATH_BAT@
+REM bis_fixscript_end
+
+call %BIS_VTK_DIR%\..\..\..\setpaths.bat	
+
+
+REM -----------------------------------
+REM Optional support for other packages
+REM -----------------------------------
+
+
+
+SET PATH=%BIOIMAGESUITE%;%BIOIMAGESUITE%\main;%BINPATH%;%BIOIMAGESUITE%\apps;%BIOIMAGESUITE%\mjack;%BIOIMAGESUITE%\bis_algorithm;%BIOIMAGESUITE%\datatree;%BASELIB%;%PATH%
+
+echo BioimageSuite ready to run. Type bioimagesuite.bat to get the starting menu
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/setpaths.csh.in b/bioimagesuite30_src/bioimagesuite/origscripts/setpaths.csh.in
new file mode 100644
index 0000000..a74d950
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/setpaths.csh.in
@@ -0,0 +1,65 @@
+# --------------------------------------------------------------------------------------
+# This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+# --------------------------------------------------------------------------------------
+#bis_fix_script_begin
+setenv BASE @BIOIMAGESUITE3_SOURCE_DIR@/bioimagesuite
+setenv BIS_VTK_DIR @VTK_DIR@
+setenv BIOIMAGESUITE3_BINARY_DIR @BIOIMAGESUITE3_BINARY_DIR@
+setenv BINPATH @EXECUTABLE_OUTPUT_PATH@
+setenv BASELIB @LIBRARY_OUTPUT_PATH@
+#bis_fixscript_end
+
+setenv BSCRIPT ${BIS_VTK_DIR}/../../../setpaths.csh
+if (-r $BSCRIPT) then
+    source  $BSCRIPT
+else
+    setenv VV `which vtk`
+    if ( -r $VV ) then
+	echo "using vtk from $VV"
+    else		
+        echo "VTK or $BSCRIPT do not exist"
+    endif
+    unsetenv VV
+endif
+
+unsetenv BSCRIPT
+unsetenv BIS_VTK_DIR
+
+# -------------------------------------------------------------------------------------
+# Compatibility with other packages
+# -------------------------------------------------------------------------------------
+setenv FSLDIR /usr/local/fsl
+setenv AFNIDIR /usr/local/afni
+setenv FSLOUTPUTTYPE NIFTI_PAIR
+
+setenv PATH ${PATH}:${FSLDIR}/bin:${AFNIDIR}
+# -------------------------------------------------------------------------------------------
+setenv PATH ${BASE}:${BASE}/main:${BINPATH}:${BASE}/apps:${BASE}/mjack:${BASE}/datatree:${BASE}/bis_algorithm:"${PATH}"
+
+setenv OS `uname`
+if ( $OS == "Darwin") then
+    if ($?DYLD_LIBRARY_PATH) then
+	setenv DYLD_LIBRARY_PATH ${BASELIB}:"${DYLD_LIBRARY_PATH}"
+    else
+	setenv DYLD_LIBRARY_PATH ${BASELIB}
+    endif
+else
+    if ($?LD_LIBRARY_PATH) then
+	setenv LD_LIBRARY_PATH ${BASELIB}:"${LD_LIBRARY_PATH}"
+    else
+	setenv LD_LIBRARY_PATH ${BASELIB}
+    endif
+endif
+unsetenv OS
+
+setenv BIOIMAGESUITE ${BASE}
+setenv BIOIMAGESUITE_DIR ${BASE}/include
+
+echo "BioimageSuite ready to run. Type bis.tcl to get the starting menu ($BIOIMAGESUITE)"
+unsetenv BASE
+unsetenv BASELIB
+
+
+
+
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/setpaths.sh.in b/bioimagesuite30_src/bioimagesuite/origscripts/setpaths.sh.in
new file mode 100644
index 0000000..b8ad9b5
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/setpaths.sh.in
@@ -0,0 +1,69 @@
+# --------------------------------------------------------------------------------------
+# This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+# --------------------------------------------------------------------------------------
+
+#bis_fix_script_begin
+BASE=@BIOIMAGESUITE3_SOURCE_DIR@/bioimagesuite
+BIS_VTK_DIR=@VTK_DIR@
+BIOIMAGESUITE3_BINARY_DIR=@BIOIMAGESUITE3_BINARY_DIR@
+BINPATH=@EXECUTABLE_OUTPUT_PATH@
+BASELIB=@LIBRARY_OUTPUT_PATH@
+#bis_fixscript_end
+
+BSCRIPT=${BIS_VTK_DIR}/../../../setpaths.sh
+
+if [ -r $BSCRIPT ]; then
+     source $BSCRIPT
+else
+   VV=`which vtk`
+   if [ -r $VV ]; then
+	echo "using vtk from $VV"
+    else		
+        echo "VTK or $BSCRIPT do not exist"
+    fi
+fi
+# -------------------------------------------------------------------------------------
+# Compatibility with other packages
+# -------------------------------------------------------------------------------------
+FSLDIR=/usr/local/fsl
+AFNIDIR=/usr/local/afni
+FSLOUTPUTTYPE=NIFTI_PAIR
+
+export FSLDIR
+export AFNIDIR
+export FSLOUTPUTTYPE
+
+PATH=${PATH}:${FSLDIR}/bin:${AFNIDIR}
+# -------------------------------------------------------------------------------------
+
+
+
+
+OS=`uname`
+if [ $OS == "Darwin" ]; then    
+    if [ -n "$DYLD_LIBRARY_PATH" ]; then
+	DYLD_LIBRARY_PATH=${BASELIB}:"${DYLD_LIBRARY_PATH}"
+    else
+	DYLD_LIBRARY_PATH=${BASELIB}
+    fi
+    export DYLD_LIBRARY_PATH
+else
+    if [ -n "$LD_LIBRARY_PATH" ]; then
+	LD_LIBRARY_PATH=${BASELIB}:"${LD_LIBRARY_PATH}"
+    else
+	LD_LIBRARY_PATH=${BASELIB}
+    fi
+    export LD_LIBRARY_PATH
+fi
+
+export PATH=${BASE}/main:${BINPATH}:${BASE}/apps:${BASE}/mjack:${BASE}/datatree:${BASE}/bis_algorithm:"${PATH}"
+
+export BIOIMAGESUITE=${BASE}
+
+if [ -n  "$BIOIMAGESUITE3_BINARY_DIR" ]; then
+    export BIOIMAGESUITE3_BINARY_DIR	
+fi
+
+
+echo "BioimageSuite ready to run. Type bis.tcl to get the starting menu ($BASE)"
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/setpaths_console.sh.in b/bioimagesuite30_src/bioimagesuite/origscripts/setpaths_console.sh.in
new file mode 100644
index 0000000..68c9c12
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/setpaths_console.sh.in
@@ -0,0 +1,28 @@
+#Script file to set paths for bioimagesuite
+
+# --------------------------------------------------------------------------------------
+# This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+# --------------------------------------------------------------------------------------
+#bis_fix_script_begin
+BASE=@BIOIMAGESUITE3_BINARY_DIR@
+#bis_fixscript_end
+
+
+source ${BASE}/setpaths.sh
+alias rm='rm -i'
+alias cp='cp -i'
+alias mv='mv -i'
+alias ll='ls -l'                              
+alias la='ls -A'                              
+PS1="\h:\w>"
+export PS1
+
+echo ""
+echo ""
+echo "----------------------"
+echo "BioImage Suite Console"
+echo "----------------------"
+echo ""
+echo "BioimageSuite CommandLine applications ready to run. Type bis.tcl to get the starting menu ($BASE)"
+echo ""
+
diff --git a/bioimagesuite30_src/bioimagesuite/origscripts/start_bioimagesuite.in b/bioimagesuite30_src/bioimagesuite/origscripts/start_bioimagesuite.in
new file mode 100755
index 0000000..d53fcd9
--- /dev/null
+++ b/bioimagesuite30_src/bioimagesuite/origscripts/start_bioimagesuite.in
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+
+# --------------------------------------------------------------------------------------
+# This file is part of the BioImage Suite Software Package. (seee www.bioimagesuite.org)
+# --------------------------------------------------------------------------------------
+
+#bis_fix_script_begin
+BASE=@BIOIMAGESUITE3_BINARY_DIR@
+#bis_fixscript_end
+
+# ----------------------------------
+# BIOIMAGESUITE: No edits below here
+# ----------------------------------
+
+source ${BASE}/setpaths.sh
+bis.tcl
+
+
diff --git a/bioimagesuite30_src/database/CMakeLists.txt b/bioimagesuite30_src/database/CMakeLists.txt
new file mode 100644
index 0000000..ae9ace5
--- /dev/null
+++ b/bioimagesuite30_src/database/CMakeLists.txt
@@ -0,0 +1,133 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+SET(KITBASE database)
+SET(KIT vtkbisDatabase)
+
+INCLUDE_DIRECTORIES(${ITK_INCLUDE_DIRS})
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/${KITBASE})
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+
+IF(BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE)
+INCLUDE_DIRECTORIES(${MYSQL_INCLUDE_DIR})
+ENDIF(BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE)
+
+
+# -------------------- Add Files Here --------------------
+SET (KITSRCS
+vtkbisDatabase.cpp
+vtkbisBaseProcedure.cpp
+vtkbisPatient.cpp
+vtkbisProtocol.cpp
+vtkbisQuery.cpp
+vtkbisVisit.cpp
+vtkbisSeries.cpp
+vtkbisStudy.cpp
+# Above tested with SQLite
+vtkbisInjection.cpp
+# Below is sqlite specific
+vtkimSQLite.cpp
+vtkbisSQLiteDatabase.cpp
+vtkbisFilenameTable.cpp
+vtkbisAlgorithmTable.cpp
+)
+  
+
+IF(BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE)
+SET (KITSRCS
+vtkbisMySQLDatabase.cpp
+vtkbisMySQLQuery.cpp
+${KITSRCS})
+ENDIF(BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE)
+
+SET(KITLIBS
+  vtkIO
+  vtkIOTCL
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+)
+
+SET(KITJAVALIBS
+  vtkIO
+  vtkIOJava
+  ${BIOIMAGESUITE3_COMMON_JAVALIBS}
+)
+
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+SET (KITEXTRAFILES)
+SET (KITTCLSRCS )
+bis_complex("database" ${KIT} ${FILELIST})
+
+
+# -------------------------------------------------------------------
+#MySQL Stuff
+# -------------------------------------------------------------------
+
+IF(BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE)
+#ADD_EXECUTABLE(addPatient addPatient.cpp)
+#TARGET_LINK_LIBRARIES(addPatient ${KIT} ${KITLIBS})
+
+#ADD_EXECUTABLE(addPatient2 addPatient2.cpp)
+#TARGET_LINK_LIBRARIES(addPatient2 ${KIT} ${KITLIBS})
+
+#ADD_EXECUTABLE(addPatient3 addPatient3.cpp)
+#TARGET_LINK_LIBRARIES(addPatient3 ${KIT} ${KITLIBS})
+
+#ADD_EXECUTABLE(searchImage searchImage.cpp)
+#TARGET_LINK_LIBRARIES(searchImage ${KIT} ${KITLIBS})
+
+#ADD_EXECUTABLE(testQuery testQuery.cpp)
+#TARGET_LINK_LIBRARIES(testQuery ${KIT} ${KITLIBS})
+
+# -----------------------------------------------------------
+# SQLite stuff
+# -----------------------------------------------------------
+
+#ADD_EXECUTABLE(mysql2sqlite mysql2sqlite.cpp)
+#TARGET_LINK_LIBRARIES(mysql2sqlite ${KIT} ${KITLIBS})
+
+#ADD_EXECUTABLE(sqlite_test2 sqlite_test2.cpp)
+#TARGET_LINK_LIBRARIES(sqlite_test2 ${KIT} ${KITLIBS})
+
+#ADD_EXECUTABLE(sqlite_test3 sqlite_test3.cpp)
+#TARGET_LINK_LIBRARIES(sqlite_test3 ${KIT} ${KITLIBS})
+
+#ADD_EXECUTABLE(sqlite_test4 sqlite_test4.cpp)
+#TARGET_LINK_LIBRARIES(sqlite_test4 ${KIT} ${KITLIBS})
+
+
+
+#ADD_EXECUTABLE(vtkimsqlite_test vtkimsqlite_test.cpp)
+#TARGET_LINK_LIBRARIES(vtkimsqlite_test ${KIT} ${KITLIBS})
+
+ENDIF(BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE)
+
diff --git a/bioimagesuite30_src/database/vtkbisAlgorithmTable.cpp b/bioimagesuite30_src/database/vtkbisAlgorithmTable.cpp
new file mode 100644
index 0000000..de3a66b
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisAlgorithmTable.cpp
@@ -0,0 +1,374 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisAlgorithmTable.cpp
+ *
+ *  Created on: Feb 19, 2009
+ *      Author: Isabella Murphy
+ */
+
+#include <vtkbisAlgorithmTable.h>
+#include <vtkObjectFactory.h>
+#include <vtkSQLQuery.h>
+#include <vtkStdString.h>
+#include <vtkVariant.h>
+
+vtkbisAlgorithmTable* vtkbisAlgorithmTable::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisAlgorithmTable");
+  if(ret)
+    {
+      return (vtkbisAlgorithmTable*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisAlgorithmTable;
+}
+// ----------------------------------------------------------------------------------------
+vtkbisAlgorithmTable::vtkbisAlgorithmTable() 
+{
+
+  this->AlgorithmName=NULL;
+  this->PresetName=NULL;
+  this->Description=NULL;
+  this->Date=NULL;
+  this->Parameter=NULL;
+  
+  this->SetAlgorithmName("");
+  this->SetPresetName("");
+  this->SetDescription("");
+  this->SetDate("");
+  this->SetParameter("");
+  
+}
+// ----------------------------------------------------------------------------------------
+vtkbisAlgorithmTable::~vtkbisAlgorithmTable() 
+{
+  if (this->AlgorithmName==NULL)  delete [] this->AlgorithmName;
+  if (this->PresetName==NULL)  delete [] this->PresetName;
+  if (this->Description==NULL)  delete [] this->Description;
+  if (this->Date==NULL)  delete [] this->Date;
+  if (this->Parameter==NULL)  delete [] this->Parameter;
+}
+// ----------------------------------------------------------------------------------------
+int vtkbisAlgorithmTable::CreateTable()
+{
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<<"Cannot connect to database. Exit."<<endl);
+      return 0;
+    }
+  vtkStdString createQuery("CREATE TABLE IF NOT EXISTS bis_algorithm_pset_table (algorithmName TEXT, presetName TEXT, description TEXT, date TEXT, parameter TEXT)");
+  //  cout << createQuery << endl;
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(createQuery.c_str());
+  
+  if (query == NULL)
+    return 0;
+
+  
+  query->Delete();
+  return 1;
+}
+// ----------------------------------------------------------------------------------------
+const char* vtkbisAlgorithmTable::SearchItem(int exact)
+{
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<<"Cannot connect to database. Exit."<<endl);
+      return "";
+    }
+
+
+
+  vtkStdString sqlstring;
+  vtkStdString qualifier="=";
+  if (exact==0)
+    qualifier="like";
+
+
+  // Somewhere here check if exact = 1, if it is this is fine,
+  // if not replace = with "Like" or "Matches" whatever sql needs
+
+  sqlstring="SELECT * from bis_algorithm_pset_table WHERE algorithmName =";
+  sqlstring+="'";
+  sqlstring+=this->AlgorithmName;
+  sqlstring+="'";
+
+  if(strlen(this->PresetName)>0)
+    {
+      sqlstring+=" AND presetName " + qualifier + " ";
+      sqlstring+="'";
+      sqlstring+=this->PresetName;
+      sqlstring+="'";
+    }
+  
+  if(strlen(this->Description)>0)
+    {
+      sqlstring+=" AND description " + qualifier + " ";
+      sqlstring+="'";
+      sqlstring+=this->Description;
+      sqlstring+="'";
+    }
+
+  if(strlen(this->Date)>0)
+    {
+      sqlstring+=" AND date " + qualifier + " ";
+      sqlstring+="'";
+      sqlstring+=this->Date;
+      sqlstring+="'";
+    }
+  
+  if(strlen(this->Parameter)>0)
+    {
+      sqlstring+=" AND parameter " + qualifier + " ";
+      sqlstring+="'";
+      sqlstring+=this->Parameter;
+      sqlstring+="'";
+    }
+  //  std::cout<<sqlstring<<endl;
+ 
+ 
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(sqlstring.c_str());
+  if (query==NULL)
+    {
+      vtkErrorMacro(<< "Query failed " <<query->GetLastErrorText()<< endl);
+      return "";
+    }
+ 
+  this->ResultString= "";
+  while ( query->NextRow())
+    {
+      for ( int field = 0; field < query->GetNumberOfFields(); field++)
+	{
+	  if ( field > 0)
+	      this->ResultString+= ",";
+	  this->ResultString+=query->DataValue( field ).ToString().c_str();
+	}
+      this->ResultString+="\n";
+    }
+  query->Delete();
+  return this->ResultString.c_str();
+}
+// ----------------------------------------------------------------------------------------
+const char* vtkbisAlgorithmTable::SearchItem(const char* algorithmName, const char* presetName, const char* description, const char* date, const char* parameter,int exact)
+{
+  if(strlen(algorithmName)<1)
+    {
+      cerr << "Please set algorithm Name\n"<<endl;
+      return "";
+    }
+  this->SetAlgorithmName(algorithmName);
+  this->SetPresetName(presetName);
+  this->SetDescription(description);
+  this->SetDate(date);
+  this->SetParameter(parameter);
+  return this->SearchItem(exact);
+
+}
+// ----------------------------------------------------------------------------------------
+int vtkbisAlgorithmTable::AddItem(const char* algorithmName, const char* presetName, const char* description, const char* date, const char* parameter)
+{
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<<"Cannot connect to database. Exit."<<endl);
+      return 0;
+    }
+  
+  if ( strlen(this->SearchItem(algorithmName,presetName,"","","")) > 0 )
+    {
+      cerr<<this->AlgorithmName<<":"<<this->PresetName<<":"<<" is in the menu already. AddItem failed"<<endl;
+      return 0;
+    }
+  
+  this->SetAlgorithmName(algorithmName);
+  this->SetPresetName(presetName);
+  this->SetDescription(description);
+  this->SetDate(date);
+  this->SetParameter(parameter);
+  
+  vtkStdString sqlstring="INSERT INTO bis_algorithm_pset_table ( algorithmName, presetName, description, date, parameter) ";
+  sqlstring+="VALUES('";
+  sqlstring+=this->AlgorithmName;
+  sqlstring+="','";
+  sqlstring+=this->PresetName;
+  sqlstring+="','";
+  sqlstring+=this->Description;
+  sqlstring+="','";
+  sqlstring+=this->Date;
+  sqlstring+="','";
+  sqlstring+=this->Parameter;
+  sqlstring+="')";
+  
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(sqlstring.c_str());
+  if (query==NULL)
+    {
+      vtkErrorMacro(<< "Insert query failed\n "<< query->GetLastErrorText()<<"\n");
+      return 0;
+    }
+  query->Delete();
+  return 1;
+}
+// ----------------------------------------------------------------------------------------
+int vtkbisAlgorithmTable::DeleteItem(const char* algorithmName, const char* presetName)
+{
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<< "Cannot connect to database. Exit."<<endl);
+      
+      return 0;
+    }
+  
+  if(strlen(this->SearchItem(algorithmName,presetName,"","",""))<1)
+    {
+      //cout<<"This item does not exist in the menu. DeleteItem failed."<<endl;
+      return 0;
+    }
+  
+  vtkStdString sqlstring= "DELETE from bis_algorithm_pset_table WHERE algorithmName = ";
+  sqlstring+="'";
+  sqlstring+=algorithmName;
+  sqlstring+="'";
+  sqlstring+=" AND presetName = ";
+  sqlstring+="'";
+  sqlstring+=presetName;
+  sqlstring+="'";
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(sqlstring.c_str());
+  
+  //	cerr << endl << "Running query: " << query->GetQuery() << endl;
+  
+  if (query==NULL)
+    {
+      vtkDebugMacro("Query " << sqlstring.c_str() << " failed\n"<<query->GetLastErrorText());
+      //cerr << "Query failed" <<query->GetLastErrorText()<< endl;
+      return 0;
+    }
+  query->Delete();
+  return 1;
+}
+// ----------------------------------------------------------------------------------------
+const char* vtkbisAlgorithmTable::QueryAll(const char* algorithmName)
+{
+  this->SetAlgorithmName(algorithmName);
+
+  vtkStdString sqlstring = "SELECT * from bis_algorithm_pset_table WHERE algorithmName = ";
+  sqlstring+="'";
+  sqlstring+=this->AlgorithmName;
+  sqlstring+="'";
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(sqlstring.c_str());
+  
+  if (query==NULL)
+    {
+      vtkDebugMacro(<< "Query " << sqlstring.c_str() << " failed\n"<<query->GetLastErrorText());
+      //cerr << "Query failed" <<query->GetLastErrorText()<< endl;
+      return 0;
+    }
+  
+  this->ResultString= "";
+  while ( query->NextRow())
+    {
+      for ( int field = 0; field < query->GetNumberOfFields(); field++)
+	{
+	  if ( field > 0)
+	    this->ResultString+= ",";
+	  this->ResultString+=query->DataValue( field ).ToString().c_str();
+	}
+      this->ResultString+="\n";
+    }
+  query->Delete();
+  return this->ResultString.c_str();
+}
+// ----------------------------------------------------------------------------------------
+int vtkbisAlgorithmTable::DeleteAll(const char* algorithmName)
+{
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<<"Cannot connect to database. Exit."<<endl);
+      return 0;
+    }
+  
+  vtkStdString sqlstring= "DELETE from bis_algorithm_pset_table WHERE algorithmName = ";
+  sqlstring+="'";
+  sqlstring+=algorithmName;
+  sqlstring+="'";
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(sqlstring.c_str());
+  
+  //	cerr << endl << "Running query: " << query->GetQuery() << endl;
+  
+  if (query==NULL)
+    {
+      vtkDebugMacro("Query " << sqlstring.c_str() << " failed\n"<<query->GetLastErrorText());
+      //cerr << "Query failed" <<query->GetLastErrorText()<< endl;
+      return 0;
+    }
+  query->Delete();
+  return 1;
+}
+// ----------------------------------------------------------------------------------------
+
+const char* vtkbisAlgorithmTable::PrintTable()
+{
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<<"Cannot connect to database. Exit."<<endl);
+      return 0;
+    }
+  vtkStdString sqlquery = "SELECT * from bis_algorithm_pset_table ";
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(sqlquery.c_str());
+  
+  this->ResultString= "ERROR";
+  
+  if (query!=NULL)
+    {
+      this->ResultString= "";
+      while ( query->NextRow())
+	{
+	  for ( int field = 0; field < query->GetNumberOfFields(); field++)
+	    {
+	      if ( field > 0)
+		this->ResultString+= ",";
+
+	      this->ResultString+=query->DataValue( field ).ToString().c_str();
+	    }
+	  this->ResultString+="\n";
+	}
+    }
+  
+  query->Delete();
+  return this->ResultString.c_str();
+}
+// ----------------------------------------------------------------------------------------
+int vtkbisAlgorithmTable::Cleanup()
+{
+  this->SetAlgorithmName("");
+  this->SetPresetName("");
+  this->SetDescription("");
+  this->SetDate("");
+  this->SetParameter("");
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/database/vtkbisAlgorithmTable.h b/bioimagesuite30_src/database/vtkbisAlgorithmTable.h
new file mode 100644
index 0000000..fb105c5
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisAlgorithmTable.h
@@ -0,0 +1,87 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisAlgorithmTable.h
+ *
+ *  Created on: Feb 19, 2009
+ *      Author: Isabella Murphy
+ */
+
+#ifndef VTKBISALGORITHMTABLE_H_
+#define VTKBISALGORITHMTABLE_H_
+
+#include "vtkbisDatabase.h"
+#include "vtkbisBaseProcedure.h"
+
+class vtkbisAlgorithmTable : public vtkbisBaseProcedure{
+public:
+	
+  static vtkbisAlgorithmTable *New();
+  vtkTypeMacro(vtkbisAlgorithmTable,vtkbisBaseProcedure);
+  
+  vtkSetStringMacro(AlgorithmName);
+  vtkGetStringMacro(AlgorithmName);
+  
+  vtkSetStringMacro(PresetName);
+  vtkGetStringMacro(PresetName);
+  
+  vtkSetStringMacro(Description);
+  vtkGetStringMacro(Description);
+  
+  vtkSetStringMacro(Date);
+  vtkGetStringMacro(Date);
+  
+  vtkSetStringMacro(Parameter);
+  vtkGetStringMacro(Parameter);
+  
+  // Creates SetConnector() and GetConnector() Methods
+  vtkGetObjectMacro(Connector,vtkbisDatabase);
+  vtkSetObjectMacro(Connector,vtkbisDatabase);
+    
+  virtual int CreateTable();
+  virtual int AddItem(const char* algorithmName, const char* presetName, const char* description, const char* date, const char* parameter);
+  virtual const char* SearchItem(const char* algorithmName, const char* presetName, const char* description, const char* date, const char* parameter,int exact=1);
+  virtual const char* SearchItem(int exact=1);
+  virtual int DeleteItem(const char* algorithmName, const char* presetName);
+  virtual int DeleteAll(const char* AlgorithmName);
+  virtual const char* QueryAll(const char* AlgorithmName);
+  virtual const char* PrintTable();
+  virtual int Cleanup();
+
+protected:
+  vtkbisAlgorithmTable();
+  virtual ~vtkbisAlgorithmTable();
+  char* AlgorithmName;
+  char* PresetName;
+  char* Description;
+  char* Date;
+  char* Parameter;
+};
+
+#endif /* VTKBISALGORITHMTABLE_H_ */
+
diff --git a/bioimagesuite30_src/database/vtkbisBaseProcedure.cpp b/bioimagesuite30_src/database/vtkbisBaseProcedure.cpp
new file mode 100644
index 0000000..70ed1b9
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisBaseProcedure.cpp
@@ -0,0 +1,75 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkbisBaseProcedure.h"
+#include "vtkObjectFactory.h"
+
+using namespace std;
+
+vtkbisBaseProcedure* vtkbisBaseProcedure::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisBaseProcedure");
+  if(ret)
+    {
+      return (vtkbisBaseProcedure*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisBaseProcedure;
+}
+
+
+
+vtkbisBaseProcedure::vtkbisBaseProcedure()
+{
+  this->Connector=NULL;
+  this->ResultString="";
+}
+
+vtkbisBaseProcedure::~vtkbisBaseProcedure()
+{
+  this->SetConnector(NULL);
+}
+
+  
+int vtkbisBaseProcedure::Connect()
+{
+  if (this->Connector==NULL)
+    return 0;
+  
+  return (this->Connector->Connect());
+}
+
+int vtkbisBaseProcedure::Disconnect()
+{
+ if (this->Connector==NULL)
+    return 0;
+  
+ this->Connector->Disconnect();
+ return 1;
+}
+
diff --git a/bioimagesuite30_src/database/vtkbisBaseProcedure.h b/bioimagesuite30_src/database/vtkbisBaseProcedure.h
new file mode 100644
index 0000000..b3f826c
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisBaseProcedure.h
@@ -0,0 +1,67 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef BaseProcedure_H
+#define BaseProcedure_H
+
+#include "vtkbisDatabase.h"
+#include "vtkVariant.h"
+#include "vtkVariantArray.h"
+#include "vtkMath.h"
+#include <string>
+
+class vtkbisBaseProcedure : public vtkObject
+{
+public:
+  static vtkbisBaseProcedure *New();
+  vtkTypeMacro(vtkbisBaseProcedure,vtkObject);
+
+  // Creates SetConnector() and GetConnector() Methods
+  vtkGetObjectMacro(Connector,vtkbisDatabase)
+  vtkSetObjectMacro(Connector,vtkbisDatabase)
+
+protected:  
+
+  vtkbisBaseProcedure();
+  virtual ~vtkbisBaseProcedure();
+
+  vtkbisBaseProcedure(const vtkbisBaseProcedure&) {};
+  void operator=(const vtkbisBaseProcedure&) {};
+
+  vtkbisDatabase* Connector;
+  
+  virtual int Connect();
+  virtual int Disconnect();
+
+  //BTX
+  std::string ResultString;
+  //ETX
+
+};
+
+#endif 
+
diff --git a/bioimagesuite30_src/database/vtkbisDatabase.cpp b/bioimagesuite30_src/database/vtkbisDatabase.cpp
new file mode 100644
index 0000000..ca6745b
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisDatabase.cpp
@@ -0,0 +1,351 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkbisDatabase.h"
+#include "vtkObjectFactory.h"
+#include <vtkSQLiteDatabase.h>
+#include "bioimagesuite_settings.h"
+#include <vtkVersion.h> // Needed for VTK_*_VERSION
+
+#ifdef BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE
+#include <vtkbisMySQLDatabase.h>
+#endif
+
+
+
+vtkbisDatabase* vtkbisDatabase::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisDatabase");
+  if(ret)
+    {
+      return (vtkbisDatabase*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisDatabase;
+}
+
+// -----------------------------------------------------------------------------------
+vtkbisDatabase::vtkbisDatabase()
+{
+  name="YaleTest";
+  host="";
+  user="";
+  password="";
+  port=3306;
+  sqliteurl="";
+  this->Mode=0;
+  this->Connection=NULL;
+
+}
+// -------------------------------------------------------------------------------------------
+
+vtkbisDatabase::~vtkbisDatabase()
+{
+  this->Connection->Delete();
+}
+
+// --------------------------------------------------------------------------------------------------------
+void vtkbisDatabase::Initialize(char* name, char* host, char* user, char* password, unsigned int port)
+{
+#ifdef BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE
+  if (this->Connection!=NULL)
+    {
+      this->Disconnect();
+      this->Connection->Delete();
+    }
+  this->Connection=vtkbisMySQLDatabase::New();
+  this->Mode=0;
+  this->name=name;
+  this->host=host;
+  this->user=user;
+  this->password=password;
+  this->port=port;
+  return;
+#endif
+}
+
+void vtkbisDatabase::InitializeSQLite(char* filename)
+{
+  this->Mode=1;
+  if (this->Connection!=NULL)
+    {
+      this->Disconnect();
+      this->Connection->Delete();
+    }
+
+
+  //  this->sqliteurl="sqlite://";
+  this->sqliteurl=filename;
+
+  //  std::cout<<"SQLIte url= " << sqliteurl.c_str() << "\n";
+  vtkDebugMacro(<<"SQLIte url= " << sqliteurl.c_str() << "\n");
+
+ vtkSQLiteDatabase* tmp=vtkSQLiteDatabase::New();
+ tmp->SetDatabaseFileName(this->sqliteurl);
+
+#if ((VTK_MAJOR_VERSION >= 5)&&(VTK_MINOR_VERSION >= 4))
+  if ( !tmp->Open("") )
+#else
+  if ( !tmp->Open() )
+#endif
+    {
+      this->sqliteurl="";
+      tmp->Delete();
+    }
+  else
+    {
+      this->Connection=tmp;
+    }
+}
+
+// --------------------------------------------------------------------------------------------------------
+
+void vtkbisDatabase::DebugPrint()
+{
+  cout <<"Mode = " << this->Mode <<endl;
+  if (!this->UsingSQLite())
+    {
+      cout << " Using MySQL " << endl;
+      cout<<"name: "<<name<<endl;
+      cout<<"host: "<<host<<endl;
+      cout<<"user: "<<user<<endl;
+      cout<<"password: "<<password<<endl;
+      cout<<"port: "<<port<<endl;
+    }
+  else
+    {
+      cout << "Using SQLite" << endl;
+      cout << "URL = " << sqliteurl.c_str() << endl;
+    }
+  cout<<"Connection: "<< this->Connection << endl;
+}
+// --------------------------------------------------------------------------------------------------------
+
+int vtkbisDatabase::Connect()
+{
+
+  //  vtkDebugMacro(<<"Attempting to Connect .... \n");
+
+  if (this->Connection==NULL)
+    {
+      vtkDebugMacro(<<"Connection is NULL\n");
+      return 0;
+    }
+
+  if (this->Connection->IsOpen())
+    {
+      //  vtkDebugMacro(<<"Connection is Open\n");
+      return 1;
+    }
+
+  int status=0;
+
+  if (!this->UsingSQLite())
+    {
+      vtkDebugMacro(<<"Attempting to Connect mySQL.... \n");
+      status=this->ConnectMySQL();
+    }
+  else
+    {
+      vtkDebugMacro(<<"Attempting to Connect SQLite.... \n");
+      status=this->ConnectSQLite();
+    }
+
+  vtkDebugMacro(<<"connection status = " << status << endl);
+  return status;
+}
+// ----------------------------------------------------------------------------------------------------
+int vtkbisDatabase::ConnectSQLite()
+{
+  if (this->Connection==NULL)
+    return 0;
+
+#if ((VTK_MAJOR_VERSION >= 5)&&(VTK_MINOR_VERSION >= 4))
+  return this->Connection->Open("");
+#else
+  return this->Connection->Open();
+#endif
+}
+// ----------------------------------------------------------------------------------------------------
+int vtkbisDatabase::ConnectMySQL()
+{
+#ifndef BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE
+  return 0;
+#else
+  char line[20];
+  sprintf(line,"%d",this->port);
+
+  vtkStdString url="mysql://";
+  url+=user.c_str();
+  url+=":";
+  url+=password.c_str();
+  url+="@";
+  url+=host.c_str();
+  url+=":";
+  url+=line;
+  url+="/";
+  url+=name.c_str();
+
+  vtkbisMySQLDatabase* con = vtkbisMySQLDatabase::New();
+  con->SetUser(user.c_str());
+  con->SetPassword(password.c_str());
+  con->SetServerPort(port);
+  con->SetHostName(host.c_str());
+  con->SetDatabaseName(name.c_str());
+
+  this->Connection=con;
+  return this->Connection->Open();
+#endif
+
+}
+// ---------------------------------------------------------------------------
+void vtkbisDatabase::Disconnect()
+{
+  if (this->Connection==NULL)
+    return;
+
+  vtkDebugMacro(<<"Attempting to Disconnect .... \n");
+
+  if (this->Connection->IsOpen())
+    this->Connection->Close();
+
+#if ((VTK_MAJOR_VERSION >= 5)&&(VTK_MINOR_VERSION >= 4))
+  if (!this->Connection->Open(""))
+#else
+  if (!this->Connection->Open())
+#endif
+    {
+      vtkDebugMacro(<<" Disconnection succeeded .... \n");
+    }
+  else
+    {
+      vtkDebugMacro(<<" Disconnection failed .... \n");
+    }
+
+}
+// ---------------------------------------------------------------------------
+//return simple string query result
+vtkStdString vtkbisDatabase::RunQuery(const char* sqlstring)
+{
+  if (this->Connect()==0)
+    return "";
+
+  std::string s=sqlstring;
+
+  vtkSQLQuery* query = this->Connection->GetQueryInstance();
+  query->SetQuery(s.c_str());
+
+  vtkStdString result="";
+
+  vtkDebugMacro(<<"Invoking Query= " << s.c_str() << "\n");
+
+  if (!query->Execute())
+    {
+      vtkDebugMacro(<<"Query= " << s.c_str() << " Failed " << query->GetLastErrorText()<< endl);
+      result="";
+    }
+  else
+    {
+      while (query->NextRow())
+	{
+	  for ( int col = 0; col < query->GetNumberOfFields(); ++ col )
+	    {
+	      if ( col > 0 )
+		result+=",";
+	      result+=query->DataValue(col).ToString().c_str() ;
+	    }
+	}
+    }
+
+  query->Delete();
+  return result;
+}
+// -------------------------------------------------------------------------------------------------
+
+//update database
+//@output: error or ok
+vtkStdString vtkbisDatabase::RunUpdate(const char* sqlstring)
+{
+  if (this->Connect()==0)
+    return "ERROR";
+
+  std::string s=sqlstring;
+  vtkSQLQuery* query = this->Connection->GetQueryInstance();
+  query->SetQuery(s.c_str());
+  vtkStdString result="OK";
+  if (!query->Execute())
+    {
+      vtkDebugMacro(<<"Query= " << s.c_str() << " Failed " << query->GetLastErrorText()<< endl);
+      result="ERROR";
+    }
+  else
+    {
+      result="OK";
+    }
+  query->Delete();
+  return result;
+}
+// -------------------------------------------------------------------------------------------------
+//return pointer to query result, for complex query
+vtkSQLQuery*  vtkbisDatabase::RunComplexQuery(const char* searchstring)
+{
+  if (this->Connect()==0){
+	  return NULL;
+	  std::cout<<"RunComplexQuery no connect"<<endl;
+  }
+
+  vtkDebugMacro(<<"About to Execute Query= " << searchstring << "\n");
+  std::string s=searchstring;
+
+  vtkSQLQuery *query = this->Connection->GetQueryInstance();
+  query->SetQuery(s.c_str());
+
+  if (!query->Execute())
+    {
+      vtkDebugMacro(<<"Query= " << searchstring << " Failed " << query->GetLastErrorText()<< endl);
+      std::cout<<"Query failed "<<query->GetLastErrorText()<<endl;
+      query->Delete();
+      query=NULL;
+
+    }
+
+  vtkDebugMacro(<<"Query  RUN OK\n");
+  return query;
+}
+// -------------------------------------------------------------------------------------------------
+
+vtkStdString vtkbisDatabase::GetQueryValueAsString(vtkSQLQuery* query,int value)
+{
+  if (query!=NULL)
+    return query->DataValue(value).ToString();
+
+  return "";
+}
+// -------------------------------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/database/vtkbisDatabase.h b/bioimagesuite30_src/database/vtkbisDatabase.h
new file mode 100644
index 0000000..fbd45cc
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisDatabase.h
@@ -0,0 +1,106 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#ifndef DATABASE_HPP
+#define DATABASE_HPP
+
+#include <vtkObject.h>
+#include <vtkSQLDatabase.h>
+#include <vtkStdString.h>
+#include "vtkSQLQuery.h"
+#include <vtkVariant.h>
+
+class vtkbisDatabase : public vtkObject
+{
+public:
+
+  static vtkbisDatabase *New();
+  vtkTypeMacro(vtkbisDatabase,vtkObject);
+
+
+  // Description:
+  // Mode = 0 = mySQL, 1 = SQLite
+  // If BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE not defined then it is always = 1
+  vtkGetMacro(Mode,int);
+  virtual int UsingSQLite() { return (this->Mode==1); }
+
+
+  // Description:
+  // Initialize as MySQL
+
+
+  virtual void Initialize(char* name, char* host, char* user, char* password, unsigned int port);
+
+  // Initialize as SQLLite
+  virtual void InitializeSQLite(char* url);
+
+  virtual void DebugPrint();
+
+  // Connect/Disconnect
+  // ------------------
+  virtual int  Connect();
+  virtual void Disconnect();
+
+  // Queries
+  // -------
+  virtual vtkStdString RunQuery(const char* searchstring);
+  virtual vtkStdString RunUpdate(const char* searchstring);
+  virtual vtkSQLQuery*  RunComplexQuery(const char* searchstring);
+
+
+  // Query
+  // Get Query Value as String
+  virtual vtkStdString GetQueryValueAsString(vtkSQLQuery* query,int value);
+
+protected:
+
+  
+  vtkbisDatabase();
+  virtual ~vtkbisDatabase();
+  vtkbisDatabase(const vtkbisDatabase&) {};
+  void operator=(const vtkbisDatabase&) {};
+
+
+  // Internal Stuff
+  virtual int ConnectMySQL();
+  virtual int ConnectSQLite();
+
+  //BTX
+  vtkStdString name;
+  vtkStdString host;
+  vtkStdString user;
+  vtkStdString password;
+  vtkStdString sqliteurl;
+  unsigned int port;
+  vtkSQLDatabase* Connection;
+  int Mode;
+  //ETX
+};
+
+#endif // DATABASE_HPP
+
diff --git a/bioimagesuite30_src/database/vtkbisFilenameTable.cpp b/bioimagesuite30_src/database/vtkbisFilenameTable.cpp
new file mode 100644
index 0000000..57894e5
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisFilenameTable.cpp
@@ -0,0 +1,323 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisFilenameTable.cpp
+ *
+ *  Created on: Jan 22, 2009
+ *      Author: isabella
+ */
+
+#include <vtkbisFilenameTable.h>
+#include <vtkObjectFactory.h>
+#include <vtkSQLQuery.h>
+#include <vtkStdString.h>
+#include <vtkVariant.h>
+
+// -------------------------------------------------------------------------------
+
+vtkbisFilenameTable* vtkbisFilenameTable::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisFilenameTable");
+  if(ret)
+    {
+      return (vtkbisFilenameTable*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisFilenameTable;
+}
+
+// -------------------------------------------------------------------------------
+vtkbisFilenameTable::vtkbisFilenameTable() 
+{
+  this->Type=NULL;
+  this->FileName=NULL;
+  this->Description=NULL;
+  
+  this->SetType("");
+  this->SetFileName("");
+  this->SetDescription("");
+  
+}
+// -------------------------------------------------------------------------------
+vtkbisFilenameTable::~vtkbisFilenameTable() 
+{
+  if (this->Type==NULL)  delete [] this->Type;
+  if (this->FileName==NULL)  delete [] this->FileName;
+  if (this->Description==NULL)  delete [] this->Description;
+}
+// -------------------------------------------------------------------------------
+int vtkbisFilenameTable::CreateTable()
+{
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<<"Cannot connect to database. Exit."<<endl);
+      return 0;
+    }
+
+  vtkStdString createQuery("CREATE TABLE IF NOT EXISTS imSQLite_FilenameTable (type TEXT, filename TEXT, description TEXT)");
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(createQuery.c_str());
+  
+  if (query==NULL)
+    {
+      cerr << "Create query failed ............. \n";
+      return 0;
+    }
+  query->Delete();
+  return 1;
+}
+// -------------------------------------------------------------------------------
+int vtkbisFilenameTable::SearchItem()
+{
+
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<<"Cannot connect to database. Exit."<<endl);
+      return 0;
+    }
+
+
+  vtkStdString sqlstring="SELECT * from imSQLite_FilenameTable WHERE type = ";
+  sqlstring+="'";
+  sqlstring+=this->Type;
+  sqlstring+="'";
+  sqlstring+="AND filename = ";
+  sqlstring+="'";
+  sqlstring+=this->FileName;
+  sqlstring+="'";
+  sqlstring+="AND description = ";
+  sqlstring+="'";
+  sqlstring+=this->Description;
+  sqlstring+="'";
+  
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(sqlstring.c_str());
+  if (query==NULL)
+    {
+      cerr << "Query failed\n" ;
+      return 0;
+    }
+  
+  int status=0;
+
+  if (query->NextRow())
+    status=1;
+  
+  query->Delete();
+  return status;
+}
+// ------------------------------------------------------------------------------------
+int vtkbisFilenameTable::SearchItem(const char* type, const char* filename, const char* description)
+{
+  this->SetType(type);
+  this->SetFileName(filename);
+  this->SetDescription(description);
+  return this->SearchItem();
+
+}
+// -----------------------------------------------------------------------------------
+int vtkbisFilenameTable::AddItem(const char* type, const char* filename, const char* description)
+{
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<<"Cannot connect to database. Exit."<<endl);
+      return 0;
+    }
+
+  this->SetType(type);
+  this->SetFileName(filename);
+  this->SetDescription(description);
+  
+  
+  if (this->SearchItem())
+    return 0;
+
+  vtkStdString sqlstring="INSERT INTO imSQLite_FilenameTable (type, filename, description) ";
+  sqlstring+="VALUES('";
+  sqlstring+=this->Type;
+  sqlstring+="','";
+  sqlstring+=this->FileName;
+  sqlstring+="','";
+  sqlstring+=this->Description;
+  sqlstring+="')";
+  
+
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<<"Cannot connect to database. Exit."<<endl);
+      return 0;
+    }
+
+  
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(sqlstring.c_str());
+  if (query==NULL)
+    {
+      vtkDebugMacro(<< "Insert query failed\n ");
+      return 0;
+    }
+  query->Delete();
+  return 1;
+}
+
+// --------------------------------------------------------------------------------------------------
+
+int vtkbisFilenameTable::DeleteItem(const char* type, const char* filename, const char* description)
+{
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<< "Cannot connect to database. Exit."<<endl);
+      return 0;
+    }
+
+  this->SetType(type);
+  this->SetFileName(filename);
+  this->SetDescription(description);
+  
+  if(!this->SearchItem())
+      return 0;
+
+  
+  vtkStdString sqlstring= "DELETE from imSQLite_FilenameTable WHERE type = ";
+  sqlstring+="'";
+  sqlstring+=this->Type;
+  sqlstring+="'";
+  sqlstring+="AND filename = ";
+  sqlstring+="'";
+  sqlstring+=this->FileName;
+  sqlstring+="'";
+  sqlstring+="AND description = ";
+  sqlstring+="'";
+  sqlstring+=this->Description;
+  sqlstring+="'";
+
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(sqlstring.c_str());
+  
+  if (query==NULL)
+    {
+      vtkDebugMacro("Query " << sqlstring.c_str() << " failed\n");
+      return 0;
+    }
+  query->Delete();
+  return 1;
+}
+// --------------------------------------------------------------------------
+const char* vtkbisFilenameTable::QueryAll(const char* type)
+{
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<<"Cannot connect to database. Exit."<<endl);
+      return 0;
+    }
+
+  vtkStdString sqlstring = "SELECT * from imSQLite_FilenameTable WHERE type = ";
+  sqlstring+="'";
+  sqlstring+=type;
+  sqlstring+="'";
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(sqlstring.c_str());
+
+  if (query==NULL)
+    {
+      vtkDebugMacro(<< "Query " << sqlstring.c_str() << " failed\n");
+      return 0;
+    }
+  
+  this->ResultString= "";
+  while ( query->NextRow())
+    {
+      for ( int field = 0; field < query->GetNumberOfFields(); field++)
+	{
+	  if ( field > 0)
+	    {
+	      this->ResultString+= ",";
+	    }
+	  this->ResultString+=query->DataValue( field ).ToString().c_str();
+	}
+      this->ResultString+="|";
+    }
+  query->Delete();
+  return this->ResultString.c_str();
+}
+// -----------------------------------------------------------------------------
+int vtkbisFilenameTable::DeleteAll(const char* type)
+{
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<<"Cannot connect to database. Exit."<<endl);
+      return 0;
+    }
+
+  vtkStdString sqlstring= "DELETE from imSQLite_FilenameTable WHERE type = ";
+  sqlstring+="'";
+  sqlstring+=type;
+  sqlstring+="'";
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(sqlstring.c_str());
+  if (query==NULL)
+    {
+      vtkDebugMacro("Query " << sqlstring.c_str() << " failed\n");
+      return 0;
+    }
+  query->Delete();
+  return 1;
+}
+
+// ----------------------------------------------------------------------------
+const char* vtkbisFilenameTable::PrintTable()
+{
+  if (!this->Connect())
+    {
+      vtkDebugMacro(<<"Cannot connect to database. Exit."<<endl);
+      return 0;
+    }
+
+  vtkStdString sqlquery = "SELECT * from imSQLite_FilenameTable ";
+  vtkSQLQuery* query = this->Connector->RunComplexQuery(sqlquery.c_str());
+
+  this->ResultString= "ERROR";
+
+  if (query!=NULL)
+    {
+      this->ResultString= "";
+      while ( query->NextRow())
+	{
+	  if (this->ResultString !="")
+	    this->ResultString+="\n";
+	  for ( int field = 0; field < query->GetNumberOfFields(); field++)
+	    {
+	      if ( field > 0)
+		{
+		  this->ResultString+= ":";
+		}
+	      this->ResultString+=query->DataValue( field ).ToString().c_str();
+	    }
+
+	}
+    }
+  query->Delete();
+  return this->ResultString.c_str();
+}
+// --------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/database/vtkbisFilenameTable.h b/bioimagesuite30_src/database/vtkbisFilenameTable.h
new file mode 100644
index 0000000..c2dc4db
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisFilenameTable.h
@@ -0,0 +1,84 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisFilenameTable.h
+ *
+ *  Created on: Jan 22, 2009
+ *      Author: isabella
+ */
+
+#ifndef VTKBISFILENAMETABLE_H_
+#define VTKBISFILENAMETABLE_H_
+
+#include "vtkbisDatabase.h"
+#include "vtkbisBaseProcedure.h"
+
+class vtkbisFilenameTable : public vtkbisBaseProcedure {
+public:
+  static vtkbisFilenameTable *New();
+  vtkTypeMacro(vtkbisFilenameTable,vtkbisBaseProcedure);
+
+  vtkSetStringMacro(Type);
+  vtkGetStringMacro(Type);
+  
+  vtkSetStringMacro(FileName);
+  vtkGetStringMacro(FileName);
+  
+  vtkSetStringMacro(Description);
+  vtkGetStringMacro(Description);
+  
+  virtual int CreateTable();
+  virtual int AddItem(const char* type, const char* fileName, const char* description);
+  virtual int SearchItem(const char* type, const char* filename, const char* description);
+  virtual int SearchItem();
+  virtual int DeleteItem(const char* type, const char* fileName, const char* description);
+  virtual int DeleteAll(const char* type);
+  virtual const char* QueryAll(const char* type);
+  virtual const char* PrintTable();
+
+  // Creates SetConnector() and GetConnector() Methods
+  vtkGetObjectMacro(Connector,vtkbisDatabase)
+  vtkSetObjectMacro(Connector,vtkbisDatabase)
+
+
+
+protected:
+  vtkbisFilenameTable();
+  virtual ~vtkbisFilenameTable();
+  char* Type;
+  char* FileName;
+  char* Description;
+
+
+
+};
+
+
+
+#endif /* VTKBISFILENAMETABLE_H_ */
+
diff --git a/bioimagesuite30_src/database/vtkbisInjection.cpp b/bioimagesuite30_src/database/vtkbisInjection.cpp
new file mode 100644
index 0000000..5ad710e
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisInjection.cpp
@@ -0,0 +1,215 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkbisInjection.h"
+#include "vtkbisBaseProcedure.h"
+#include "vtkObjectFactory.h"
+
+
+vtkbisInjection* vtkbisInjection::New()
+{
+  return new vtkbisInjection;
+}
+
+
+
+vtkbisInjection::vtkbisInjection()
+{
+  this->VisitID=new char[10];
+  this->InjectionID=new char[10];
+  this->InjectionDateTime=new char[10];
+  
+  this->SetVisitID("");
+  this->SetInjectionID("");
+  this->SetInjectionDateTime("");
+}
+
+vtkbisInjection::~vtkbisInjection()
+{
+  if (this->VisitID!=NULL) delete [] this->VisitID;
+  if (this->InjectionID!=NULL) delete [] this->InjectionID;
+  if (this->InjectionDateTime!=NULL) delete [] InjectionDateTime;
+}
+
+
+void vtkbisInjection::DebugPrint()
+{
+  cout<<"******Print Injection Infomation******"<<endl;
+  cout<<"InjectionID: "<<InjectionID<<endl;
+  cout<<"VisitID: "<<VisitID<<endl;
+  cout<<"InjectionDateTime: "<<InjectionDateTime<<endl;
+  cout<<"******End Injection Infomation******"<<endl;
+  
+}
+
+int vtkbisInjection::InsertInjection()
+{
+  int ok=false;
+
+  
+  if(!this->Connect())
+  {
+    cout<<"Cannot connect to database. Exit."<<endl;
+    return ok;
+  }
+
+  std::string sqlstring;
+  if (this->Connector->GetMode()==0)
+    {
+      sqlstring="Insert into Injection(VisitID, InjectionDateTime)";
+      sqlstring+="Value('";
+      sqlstring+=VisitID;
+      sqlstring+=+"',NOW() )";
+    }
+  else
+    {
+      vtkStdString dt=this->Connector->RunQuery("SELECT datetime('now')");
+      sqlstring="Insert into Injection(InjectionID,VisitID,InjectionDateTime)";
+      sqlstring+="VALUES('";
+      sqlstring+=InjectionID;
+      sqlstring+="','";
+      sqlstring+=VisitID;
+      sqlstring+="','";
+      sqlstring+=dt;
+      sqlstring+="')";
+    }
+
+  //  fprintf(stderr,"adding injection %s\n",sqlstring.c_str());
+  vtkStdString s=this->Connector->RunUpdate(sqlstring.c_str());
+  if (s=="ERROR")
+    {
+      cerr << "Failed to insert Injection: " << endl;
+    }
+  else
+    {
+      ok=1;
+    }
+  return ok;
+}
+
+const char* vtkbisInjection::SearchInjectionID(const char* VisitID)
+{
+  std::string sqlstring;
+  sqlstring="Select max(InjectionID) From Injection Where VisitID='";
+  sqlstring+=VisitID;
+  sqlstring+="'";
+  
+  if (!this->Connect())
+    {
+      cout<<"Cannot connect to database. Exit."<<endl;
+      return "";
+    }
+
+  this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+  return this->ResultString.c_str();  
+}
+
+const char* vtkbisInjection::SearchInjectionDateTime(const char* InjectionID)
+{
+  std::string sqlstring;
+  sqlstring="Select InjectionDateTime From Injection Where InjectionID='";
+  sqlstring+=InjectionID;
+  sqlstring+="'";
+  
+  if (!this->Connect())
+    {
+      cout<<"Cannot connect to database. Exit."<<endl;
+      return "";
+    }
+
+  this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+  return this->ResultString.c_str();  
+
+}
+// ------------------------------------------------------------------------------------
+int vtkbisInjection::FindEmptyInjectionID()
+{
+  int done=0;
+
+  //  fprintf(stderr,"Beginning Injection ID=%s\n",this->InjectionID);
+
+  while (done == 0)
+    {
+      std::string sqlstring;
+      sqlstring="Select VisitID From Injection Where InjectionID='";
+      sqlstring+=InjectionID;
+      sqlstring+="'";
+  
+      if (!this->Connect())
+	{
+	  cout<<"Cannot connect to database. Exit."<<endl;
+	  return 0;
+	}
+      
+     this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+      if (this->ResultString.length()==0)
+	{
+	  done=1;
+	}
+      else
+	{
+	  char line[10];
+	  int newp=atoi(this->InjectionID);
+	  newp=newp+1+int(100.0*vtkMath::Random());
+	  sprintf(line,"%d",newp);
+	  this->SetInjectionID(line);
+	}
+    }
+  return done;
+}
+// ------------------------------------------------------------------------------------
+int vtkbisInjection::AddInjection()
+{
+  int ok=false;
+  std::string injectionid=this->SearchInjectionID(this->VisitID);
+  if(injectionid.length()!=0)
+    {
+      cout<<"Injection exists as injectionid "<<injectionid<<endl;
+      cout<<"Not adding injection"<<endl;
+      return ok;
+    }
+
+  if (this->Connector->GetMode()==1)
+    {
+      this->SetInjectionID("100");
+      int allset=this->FindEmptyInjectionID();
+      if (allset==0)
+	{
+	  cout << "Failed to find unique ID";
+	  return ok;
+	}
+      //      fprintf(stderr,"Proceeding, unique ID = %s\n",this->InjectionID);
+    }
+  
+  return this->InsertInjection();
+  
+}
+
+	
+  
+
+
diff --git a/bioimagesuite30_src/database/vtkbisInjection.h b/bioimagesuite30_src/database/vtkbisInjection.h
new file mode 100644
index 0000000..565f967
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisInjection.h
@@ -0,0 +1,72 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef INJECTION_HPP
+#define INJECTION_HPP
+
+#include "vtkbisBaseProcedure.h"
+#include "vtkObject.h"
+
+class vtkbisInjection : public vtkbisBaseProcedure
+{
+public:
+  static vtkbisInjection *New();
+  vtkTypeMacro(vtkbisInjection,vtkbisBaseProcedure);
+
+  virtual void DebugPrint();
+
+  virtual int   AddInjection();  
+  const char*  SearchInjectionID(const char* VisitID);
+  const char*  SearchInjectionDateTime(const char* InjectionID);
+
+  vtkSetStringMacro(InjectionID);
+  vtkGetStringMacro(InjectionID);
+
+  vtkSetStringMacro(VisitID);
+  vtkGetStringMacro(VisitID);
+
+  vtkSetStringMacro(InjectionDateTime);
+  vtkGetStringMacro(InjectionDateTime);
+
+protected:  
+
+  vtkbisInjection();
+  virtual ~vtkbisInjection();
+
+  vtkbisInjection(const vtkbisInjection&) {};
+  void operator=(const vtkbisInjection&) {};
+
+  char* InjectionID;
+  char* VisitID;
+  char* InjectionDateTime;
+
+  virtual int  InsertInjection();
+  virtual int  FindEmptyInjectionID();  
+};
+
+#endif 
+
diff --git a/bioimagesuite30_src/database/vtkbisPatient.cpp b/bioimagesuite30_src/database/vtkbisPatient.cpp
new file mode 100644
index 0000000..68bc459
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisPatient.cpp
@@ -0,0 +1,206 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkbisPatient.h"
+#include "vtkObjectFactory.h"
+#include <sstream>
+using namespace std;
+
+vtkbisPatient* vtkbisPatient::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisPatient");
+  if(ret)
+    {
+      return (vtkbisPatient*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisPatient;
+}
+
+
+
+vtkbisPatient::vtkbisPatient()
+{
+  this->PatientID=new char[10];
+  this->FirstName=new char[10];
+  this->LastName=new char[10];
+  this->BirthDate=new char[10];
+ 
+  this->SetPatientID("");
+  this->SetFirstName("");
+  this->SetLastName("");
+  this->SetBirthDate("");
+
+  
+}
+
+vtkbisPatient::~vtkbisPatient()
+{
+  if (this->PatientID==NULL)  delete [] this->PatientID;
+  if (this->FirstName==NULL)  delete [] this->FirstName;
+  if (this->LastName==NULL)   delete [] this->LastName; 
+  if (this->BirthDate==NULL)  delete [] this->BirthDate;
+}
+
+void vtkbisPatient::Initialize(const char* FirstName, const char* LastName, const char* BirthDate)
+{
+  this->SetPatientID("");
+  this->SetFirstName(FirstName);
+  this->SetLastName(LastName);
+  this->SetBirthDate(BirthDate);
+}
+
+void vtkbisPatient::DebugPrint()
+{
+  cout<<"******Print Patient Infomation******"<<endl;
+  cout<<"PatientID: "<<PatientID<<endl;
+  cout<<"FirstName: "<<FirstName<<endl;
+  cout<<"LastName: "<<LastName<<endl;
+  cout<<"BirthDate: "<<BirthDate<<endl;
+  cout<<"******End Patient Infomation******"<<endl;
+}
+// ----------------------------------------------------------------------------------
+int vtkbisPatient::InsertPatient()
+{
+  int ok=false;
+  string sqlstring="Insert into Patient(PatientID, FirstName, LastName, BirthDate) ";
+  if (this->Connector->GetMode()==0)
+    sqlstring+="Value('";
+  else
+    sqlstring+="VALUES('";
+  sqlstring+=PatientID;
+  sqlstring+="','";
+  sqlstring+=FirstName;
+  sqlstring+="','";
+  sqlstring+=LastName;
+  sqlstring+="','";
+  sqlstring+=BirthDate;
+  sqlstring+="')";
+  
+
+  if (!this->Connect())
+  {
+    cout<<"Cannot connect to database. Exit."<<endl;
+    return ok;
+  }
+  
+  vtkStdString s=this->Connector->RunUpdate(sqlstring.c_str());
+  if (s=="ERROR" || s =="" )
+    {
+      cerr << "Failed to insert Patient: " << endl;
+    }
+  else
+    {
+      ok=1;
+    }
+  return ok;
+}  
+// ------------------------------------------------------------------------------------
+const char* vtkbisPatient::SearchPatientID(const char* FirstName,const char* LastName,const char* BirthDate)
+{
+  string patientid="";
+  string sqlstring;
+  sqlstring="Select PatientID From Patient Where FirstName='";
+  sqlstring+=FirstName;
+  sqlstring+="' and LastName='";
+  sqlstring+=LastName;
+  sqlstring+="' and BirthDate='";
+  sqlstring+=BirthDate;
+  sqlstring+="'";
+  
+  if (!this->Connect())
+    {
+      cout<<"Cannot connect to database. Exit."<<endl;
+      return patientid.c_str();
+    }
+
+ this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+  return this->ResultString.c_str();
+}
+
+// --------------------------------------------------------------------------------------
+const char* vtkbisPatient::GetNewPatientID(const char* initial,int number)
+{
+  stringstream ss;
+  ss<<initial<<number;
+  string patientid=ss.str();
+  string sqlstring="Select Firstname from Patient where PatientID='";
+  sqlstring+=patientid;
+  sqlstring+="'";
+  string fname="";
+
+  if (!this->Connect())
+    {
+      //      fprintf(stderr, "Get New Patient ID  .... Cannot connect to database. Exit.\n");
+      return patientid.c_str();
+    }
+  
+  vtkSQLQuery* query=this->Connector->RunComplexQuery(sqlstring.c_str());
+  if (query==NULL)
+    return patientid.c_str();
+
+  while ( query->NextRow() )
+    {
+      vtkStdString fname=query->DataValue(0).ToString();
+      if(fname.length()!=0)
+	{
+	  number++;  
+	  patientid=GetNewPatientID(initial,number);
+	}
+    }
+  query->Delete();
+  return patientid.c_str();
+}
+
+// ----------------------------------------------------------------------------------
+int vtkbisPatient::AddPatient()
+{
+  int ok=false;
+  string patientid=SearchPatientID(FirstName,LastName,BirthDate);
+  if(patientid.length()!=0)
+    {
+      cout<<"Patient exists as patientid "<<patientid<<endl;
+      cout<<"Not add patient"<<endl;
+      return ok;
+    }
+
+  string initial="";
+  initial.append(1,FirstName[0]);
+  initial.append(1,LastName[0]);
+
+  const char* newid=this->GetNewPatientID(initial.c_str(),100);
+  this->SetPatientID(newid);
+  if(this->InsertPatient()==1)
+    {
+      ok=true;
+    }
+  return true;
+}
+	
+
+
diff --git a/bioimagesuite30_src/database/vtkbisPatient.h b/bioimagesuite30_src/database/vtkbisPatient.h
new file mode 100644
index 0000000..529cb33
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisPatient.h
@@ -0,0 +1,77 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef PATIENT_HPP
+#define PATIENT_HPP
+
+#include "vtkbisDatabase.h"
+#include "vtkbisBaseProcedure.h"
+
+
+class vtkbisPatient : public vtkbisBaseProcedure 
+{
+public:
+  static vtkbisPatient *New();
+  vtkTypeMacro(vtkbisPatient,vtkbisBaseProcedure);
+
+  virtual void Initialize(const char* FirstName, const char* LastName, const char* BirthDate);
+  virtual int AddPatient();
+  virtual const char* SearchPatientID(const char* FirstName, const char* LastName, const char* BirthDate);
+  virtual void DebugPrint();
+  
+  // Macros for all Members
+  vtkSetStringMacro(PatientID);
+  vtkGetStringMacro(PatientID);
+
+  vtkSetStringMacro(FirstName);
+  vtkGetStringMacro(FirstName);
+
+  vtkSetStringMacro(LastName);
+  vtkGetStringMacro(LastName);
+
+  vtkSetStringMacro(BirthDate);
+  vtkGetStringMacro(BirthDate);
+
+  
+protected:  
+  vtkbisPatient();
+  virtual ~vtkbisPatient();
+
+//BTX
+//  vtkbisPatient(const vtkbisPatient&) {};
+//  void operator=(const vtkbisPatient&) {};
+  char* PatientID;
+  char* FirstName;
+  char* LastName;
+  char* BirthDate;
+  const char* GetNewPatientID(const char* initial, int number);
+  virtual int InsertPatient();
+  //ETX
+};
+
+#endif 
+
diff --git a/bioimagesuite30_src/database/vtkbisProtocol.cpp b/bioimagesuite30_src/database/vtkbisProtocol.cpp
new file mode 100644
index 0000000..18242f0
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisProtocol.cpp
@@ -0,0 +1,200 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkbisProtocol.h"
+#include "vtkObjectFactory.h"
+
+using namespace std;
+
+
+vtkbisProtocol* vtkbisProtocol::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisProtocol");
+  if(ret)
+    {
+      return (vtkbisProtocol*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisProtocol;
+}
+
+
+vtkbisProtocol::vtkbisProtocol()
+{
+  this->ProtocolID=new char[10]; this->SetProtocolID("100");
+  this->ProtocolName=new char[10]; this->SetProtocolName("");
+  this->PI=new char[10]; this->SetPI("");
+}
+
+vtkbisProtocol::~vtkbisProtocol()
+{
+  if (this->ProtocolID!=NULL) delete [] this->ProtocolID;
+  if (this->ProtocolName!=NULL) delete [] this->ProtocolName;
+  if (this->PI!=NULL) delete [] this->PI;
+}
+
+
+void vtkbisProtocol::DebugPrint()
+{
+  cout<<"******Print Protocol Infomation******"<<endl;
+  cout<<"ProtocolID: "<<ProtocolID<<endl;
+  cout<<"ProtocolName: "<<ProtocolName<<endl;
+  cout<<"PI: "<<PI<<endl;
+  cout<<"******End Protocol Infomation******"<<endl;
+  
+}
+// ----------------------------------------------------------------------------------
+int vtkbisProtocol::InsertProtocol()
+{
+  int ok=false;
+  string sqlstring;
+  if (this->Connector->GetMode()==0)
+    {
+      sqlstring="Insert into Protocol(ProtocolName,PI)";
+      sqlstring+="Value('";
+    }
+  else
+    {
+      sqlstring="Insert into Protocol(ProtocolID,ProtocolName,PI)";
+      sqlstring+="VALUES('";
+      sqlstring+=ProtocolID;
+      sqlstring+="','";
+    }
+  sqlstring+=ProtocolName;
+  sqlstring+="','";
+  sqlstring+=PI;
+  sqlstring+="')";
+  
+  if (!this->Connect())
+    {
+      cout<<"Cannot connect to database. Exit."<<endl;
+      return ok;
+    }
+  
+  vtkStdString s=this->Connector->RunUpdate(sqlstring.c_str());
+  if (s=="ERROR" || s =="" )
+    {
+      cerr << "Failed to insert Protocol: " << endl;
+    }
+  else
+    {
+      ok=1;
+    }
+  return ok;
+}
+// ------------------------------------------------------------------------------------
+const char* vtkbisProtocol::SearchProtocolID(const char* Protocolname,const char* PI)
+{
+  string protocolid="";
+  string sqlstring;
+  sqlstring="Select ProtocolID From Protocol Where ProtocolName='";
+  sqlstring+=ProtocolName;
+  sqlstring+="' and PI='";
+  sqlstring+=PI;
+  sqlstring+="'";
+  
+  if (!this->Connect())
+    {
+      cout<<"Cannot connect to database. Exit."<<endl;
+      return protocolid.c_str();
+    }
+  
+ this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+  return this->ResultString.c_str();
+}
+
+// ------------------------------------------------------------------------------------
+
+int vtkbisProtocol::FindEmptyProtocolID()
+{
+  int done=0;
+
+  //  fprintf(stderr,"Beginning Protocol ID=%s\n",this->ProtocolID);
+
+  while (done == 0)
+    {
+      string sqlstring;
+      sqlstring="Select ProtocolName From Protocol Where ProtocolID='";
+      sqlstring+=ProtocolID;
+      sqlstring+="'";
+  
+      if (!this->Connect())
+	{
+	  cout<<"Cannot connect to database. Exit."<<endl;
+	  return 0;
+	}
+      
+     this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+      if (this->ResultString.length()==0)
+	{
+	  done=1;
+	}
+      else
+	{
+	  char line[10];
+	  int newp=atoi(this->ProtocolID);
+	  newp=newp+1+int(100.0*vtkMath::Random());
+	  sprintf(line,"%d",newp);
+	  this->SetProtocolID(line);
+	}
+    }
+  return done;
+}
+// ------------------------------------------------------------------------------------
+int vtkbisProtocol::AddProtocol()
+{
+  int ok=false;
+  string protocolid=this->SearchProtocolID(ProtocolName,PI);
+  if(protocolid.length()!=0)
+    {
+      cout<<"Protocol exists as protocolid "<<protocolid<<endl;
+      cout<<"Not adding protocol"<<endl;
+      return ok;
+    }
+
+  if (this->Connector->GetMode()==1)
+    {
+      this->SetProtocolID("100");
+      int allset=this->FindEmptyProtocolID();
+      if (allset==0)
+	{
+	  cout << "Failed to find unique ID";
+	  return ok;
+	}
+      //      fprintf(stderr,"Proceeding, unique ID = %s\n",this->ProtocolID);
+    }
+  
+  return this->InsertProtocol();
+  
+}
+
+	
+  
+
+
diff --git a/bioimagesuite30_src/database/vtkbisProtocol.h b/bioimagesuite30_src/database/vtkbisProtocol.h
new file mode 100644
index 0000000..641cdec
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisProtocol.h
@@ -0,0 +1,74 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef PROTOCOL_H
+#define PROTOCOL_H
+
+#include "vtkbisDatabase.h"
+#include "vtkbisBaseProcedure.h"
+
+
+class vtkbisProtocol : public vtkbisBaseProcedure
+{
+
+public:
+  static vtkbisProtocol *New();
+  vtkTypeMacro(vtkbisProtocol,vtkbisBaseProcedure);
+
+  virtual int   AddProtocol();  
+  virtual void  DebugPrint();
+  const   char* SearchProtocolID(const char* ProtocolName, const char* PI);
+
+
+  // Macros for all Members
+  vtkSetStringMacro(ProtocolID);
+  vtkGetStringMacro(ProtocolID);
+
+  vtkSetStringMacro(ProtocolName);
+  vtkGetStringMacro(ProtocolName);
+
+  vtkSetStringMacro(PI);
+  vtkGetStringMacro(PI);
+
+protected:  
+
+  vtkbisProtocol();
+  virtual ~vtkbisProtocol();
+  vtkbisProtocol(const vtkbisProtocol&) {};
+  void operator=(const vtkbisProtocol&) {};
+
+  char* ProtocolID;
+  char* ProtocolName;
+  char* PI;
+
+  virtual int  InsertProtocol();
+  virtual int  FindEmptyProtocolID();
+
+};
+
+#endif 
+
diff --git a/bioimagesuite30_src/database/vtkbisQuery.cpp b/bioimagesuite30_src/database/vtkbisQuery.cpp
new file mode 100644
index 0000000..7bd1d63
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisQuery.cpp
@@ -0,0 +1,332 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkbisQuery.h"
+#include "vtkObjectFactory.h"
+
+using namespace std;
+
+vtkbisQuery* vtkbisQuery::New()
+{
+
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisQuery");
+  if(ret)
+    {
+      return (vtkbisQuery*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisQuery;
+}
+
+
+vtkbisQuery::vtkbisQuery()
+{
+  this->QueryName=new char[2];
+  this->QueryCategory=new char[2];
+  this->QueryDescription=new char[2];
+  this->QueryArg=new char[2];
+  this->QueryTable=new char[2];
+  this->QueryLink=new char[2];
+  this->QueryField=new char[2];
+  this->QueryWhere=new char[2];
+  this->QueryOrder=new char[2];
+  this->QueryGroup=new char[2];
+  this->QueryHaving=new char[2];
+
+
+  this->SetQueryName("");
+  this->SetQueryCategory("");
+  this->SetQueryDescription("");
+  this->SetQueryArg("");
+  this->SetQueryTable("");
+  this->SetQueryLink("");
+  this->SetQueryField("");
+  this->SetQueryWhere("");
+  this->SetQueryOrder("");
+  this->SetQueryGroup("");
+  this->SetQueryHaving("");
+}
+
+vtkbisQuery::~vtkbisQuery()
+{
+  if (this->QueryName !=NULL ) delete [] this->QueryName;
+  if (this->QueryCategory !=NULL ) delete [] this->QueryCategory;
+  if (this->QueryDescription !=NULL ) delete [] this->QueryDescription;
+  if (this->QueryArg !=NULL ) delete [] this->QueryArg;
+  if (this->QueryTable !=NULL ) delete [] this->QueryTable;
+  if (this->QueryLink !=NULL ) delete [] this->QueryLink;
+  if (this->QueryField !=NULL ) delete [] this->QueryField;
+  if (this->QueryWhere !=NULL ) delete [] this->QueryWhere;
+  if (this->QueryOrder !=NULL ) delete [] this->QueryOrder;
+  if (this->QueryGroup !=NULL ) delete [] this->QueryGroup;
+  if (this->QueryHaving !=NULL ) delete [] this->QueryHaving;
+}
+
+
+void vtkbisQuery::DebugPrint()
+{
+  cout<<"******Print Query Infomation******"<<endl;
+  cout<<"QueryName: "<<QueryName<<endl;
+  cout<<"QueryCategory: "<<QueryCategory<<endl;
+  cout<<"QueryDescription: "<<QueryDescription<<endl;
+  cout<<"QueryArg: "<<QueryArg<<endl;
+  cout<<"QueryTable: "<<QueryTable<<endl;
+  cout<<"QueryLink: "<<QueryLink<<endl;
+  cout<<"QueryField: "<<QueryField<<endl;
+  cout<<"QueryWhere: "<<QueryWhere<<endl;
+  cout<<"QueryOrder: "<<QueryOrder<<endl;
+  cout<<"QueryGroup: "<<QueryGroup<<endl;
+  cout<<"QueryHaving: "<<QueryHaving<<endl;
+  cout<<"******End Query Infomation******"<<endl;
+  
+}
+int vtkbisQuery::SearchQuery(const char* QueryName, const char* QueryCategory)
+{
+
+  std::string sqlstring;
+  sqlstring="select QueryDescription,QueryArg,QueryTable,QueryLink,QueryField,QueryWhere,QueryOrder,QueryGroup,QueryHaving from Query where QueryName = '";
+  sqlstring+=QueryName;
+  sqlstring+="' and QueryCategory = '";
+  sqlstring+=QueryCategory;
+  sqlstring+="'"; 
+//cout<<sqlstring<<endl;
+  
+  if(!this->Connect())
+  {
+    cout<<"Cannot connect to database. Exit."<<endl;
+    return 0;
+  }
+
+  this->QueryName    	= (char*)QueryName;
+  this->QueryCategory   = (char*)QueryCategory;
+
+  vtkSQLQuery* query=this->Connector->RunComplexQuery(sqlstring.c_str());
+  if (query==NULL)
+    return 0;
+
+  while (query->NextRow())
+    {
+      this->SetQueryDescription(query->DataValue(0).ToString().c_str());
+      this->SetQueryArg(query->DataValue(1).ToString().c_str());
+      this->SetQueryTable(query->DataValue(2).ToString().c_str());
+      this->SetQueryLink(query->DataValue(3).ToString().c_str());
+      this->SetQueryField(query->DataValue(4).ToString().c_str());
+      this->SetQueryWhere(query->DataValue(5).ToString().c_str());
+      this->SetQueryOrder(query->DataValue(6).ToString().c_str());
+      this->SetQueryGroup(query->DataValue(7).ToString().c_str());
+      this->SetQueryHaving(query->DataValue(8).ToString().c_str());
+    }
+  
+  query->Delete();
+  return 1;
+}
+
+const char* vtkbisQuery::BuildQuery()
+{
+  std::string sqlstring;
+  string ttt;
+  sqlstring="select ";
+  sqlstring+=QueryField;
+  sqlstring+=" from ";
+  sqlstring+=QueryTable;
+ 
+  string parsedQueryWhere = QueryWhere;
+  if(strlen(QueryLink)>0)
+  {
+    parsedQueryWhere+=" | ";
+    parsedQueryWhere+=QueryLink;
+  }
+
+  ttt=parsedQueryWhere;
+  fprintf(stderr,"ttt (C++) =%s\n",ttt.c_str());
+  vector<string> v;
+  Tokenize(ttt,v,"|");
+  if(v.size()>0) 
+   sqlstring+=" where ";
+  for(int i=0;i<v.size();i++)
+  {
+    if(i>0)
+      sqlstring+=" and ";
+    sqlstring+=v[i];
+  }    
+  
+  if(strlen(QueryOrder)>0)
+  {
+    sqlstring+=" order by ";
+    sqlstring+=QueryOrder;  
+  }
+  
+  if(strlen(QueryHaving)>0)
+  {
+    sqlstring+=" having ";
+    sqlstring+=QueryHaving;  
+  }
+
+  if(strlen(QueryGroup)>0)
+  {
+    sqlstring+=" group by ";
+    sqlstring+=QueryGroup;  
+  }
+
+  ttt=QueryArg;
+  vector<string> arg_name;
+  vector<string> arg_value;  
+  Tokenize(ttt,arg_name,"|");
+  for(int i=0;i<arg_name.size();i++)
+  {
+    cout<<"Please input the value of argument "<<arg_name[i]<<endl;
+    cin>>ttt;
+    arg_value.push_back(ttt);
+  }
+  for(int i=0;i<arg_value.size();i++)
+  {
+    string s;
+    string t="$";
+    stringstream out;
+    out<<i+1;
+    s=out.str();
+    sqlstring=StringReplace(sqlstring,t+s,arg_value[i]);
+  }
+
+  return sqlstring.c_str();
+
+}
+
+
+const char* vtkbisQuery::BuildQuery(const char* inputstring)
+{
+ std::string sqlstring;
+  string ttt;
+  sqlstring="select ";
+  sqlstring+=QueryField;
+  sqlstring+=" from ";
+  sqlstring+=QueryTable;
+  
+  string parsedQueryWhere = QueryWhere;
+  if(strlen(QueryLink)>0)
+    {
+      parsedQueryWhere+=" and ";
+      parsedQueryWhere+=QueryLink;
+    }
+  
+  ttt=parsedQueryWhere;
+  
+
+  vector<string> v;
+  Tokenize(ttt,v,"|");
+  if(v.size()>0) 
+    sqlstring+=" where ";
+  for(int i=0;i<v.size();i++)
+    {
+      if(i>0)
+	sqlstring+=" and ";
+      sqlstring+=v[i];
+    }    
+  
+  if(strlen(QueryOrder)>0)
+    {
+      sqlstring+=" order by ";
+      sqlstring+=QueryOrder;  
+    }
+  
+  if(strlen(QueryHaving)>0)
+    {
+      sqlstring+=" having ";
+      sqlstring+=QueryHaving;  
+    }
+  
+  if(strlen(QueryGroup)>0)
+    {
+      sqlstring+=" group by ";
+      sqlstring+=QueryGroup;  
+    }
+  
+  ttt=QueryArg;
+  vector<string> arg_name;
+  vector<string> arg_value;  
+  Tokenize(ttt,arg_name,"|");
+
+  string ttt2=inputstring;
+  vector<string> param_name;
+  Tokenize(ttt2,param_name,"|");
+
+  if (param_name.size()!=arg_name.size())
+    {
+      fprintf(stderr,"Not Enough Arguments %d vs %d \n",param_name.size(),arg_name.size());
+      sqlstring="Error";
+      return sqlstring.c_str();
+    }
+  
+  for(int i=0;i<param_name.size();i++)
+    {
+      string s;
+      string t="$";
+      stringstream out;
+      out<<i+1;
+      s=out.str();
+      if (param_name[i]!="*")
+	sqlstring=StringReplace(sqlstring,t+s,param_name[i]);
+      else
+	sqlstring=StringReplace(sqlstring,t+s,"");
+    }
+
+  return sqlstring.c_str();
+}
+
+
+void vtkbisQuery::Tokenize(const std::string& str, vector<std::string>& tokens, const std::string& delimiters )
+{
+    // Skip delimiters at beginning.
+    std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
+    // Find first "non-delimiter".
+    std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
+
+    while (std::string::npos != pos || std::string::npos != lastPos)
+    {
+        // Found a token, add it to the vector.
+        tokens.push_back(str.substr(lastPos, pos - lastPos));
+        // Skip delimiters.  Note the "not_of"
+        lastPos = str.find_first_not_of(delimiters, pos);
+        // Find next "non-delimiter"
+        pos = str.find_first_of(delimiters, lastPos);
+    }
+}
+
+std::string vtkbisQuery::StringReplace(std::string input,std::string old_pattern,std::string new_pattern)
+{
+  string output = input;
+  string::size_type found_at = output.find( old_pattern );
+  while( string::npos != found_at )
+  {
+    output.replace( found_at, old_pattern.length(), new_pattern );
+    found_at = output.find( old_pattern, found_at + old_pattern.length() );
+  }
+ 
+  return output;
+}
+
diff --git a/bioimagesuite30_src/database/vtkbisQuery.h b/bioimagesuite30_src/database/vtkbisQuery.h
new file mode 100644
index 0000000..0b976cc
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisQuery.h
@@ -0,0 +1,111 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef bisQUERY_H
+#define bisQUERY_H
+#include <vtkstd/string>
+#include "vtkbisBaseProcedure.h"
+#include <vtkstd/vector>
+#include <sstream>
+
+class vtkbisQuery : public vtkbisBaseProcedure
+{
+public:
+  static vtkbisQuery *New();
+  vtkTypeMacro(vtkbisQuery,vtkbisBaseProcedure);
+
+  void DebugPrint();
+  int SearchQuery(const char* QueryName, const char* QueryCategory);
+  const char* BuildQuery();
+  const char* BuildQuery(const char* inputstring);
+
+ 
+  // Macros for all Members
+  vtkSetStringMacro(QueryName);
+  vtkGetStringMacro(QueryName);
+
+  vtkSetStringMacro(QueryCategory);
+  vtkGetStringMacro(QueryCategory);
+
+  vtkSetStringMacro(QueryDescription);
+  vtkGetStringMacro(QueryDescription);
+
+  vtkSetStringMacro(QueryArg);
+  vtkGetStringMacro(QueryArg);
+
+  vtkSetStringMacro(QueryTable);
+  vtkGetStringMacro(QueryTable);
+
+  vtkSetStringMacro(QueryLink);
+  vtkGetStringMacro(QueryLink);
+
+  vtkSetStringMacro(QueryField);
+  vtkGetStringMacro(QueryField);
+
+  vtkSetStringMacro(QueryWhere);
+  vtkGetStringMacro(QueryWhere);
+
+  vtkSetStringMacro(QueryOrder);
+  vtkGetStringMacro(QueryOrder);
+
+  vtkSetStringMacro(QueryGroup);
+  vtkGetStringMacro(QueryGroup);
+
+  vtkSetStringMacro(QueryHaving);
+  vtkGetStringMacro(QueryHaving);
+
+  // Tokenize 
+  //BTX
+  static void Tokenize(const std::string& str, std::vector<std::string>& tokens, const std::string& delimiters );
+  std::string StringReplace(std::string input,std::string old_pattern, std::string new_pattern);
+
+  //ETX
+
+protected:  
+  vtkbisQuery();
+  virtual ~vtkbisQuery(); 
+//BTX
+//  vtkbisStudy(const vtkbisStudy&) {};
+//  void operator=(const vtkbisStudy&) {};
+  //ETX
+
+  char* QueryName;
+  char* QueryCategory;
+  char* QueryDescription;
+  char* QueryArg;
+  char* QueryTable;
+  char* QueryLink;
+  char* QueryField;
+  char* QueryWhere;
+  char* QueryOrder;
+  char* QueryGroup;
+  char* QueryHaving;
+
+};
+
+#endif 
+
diff --git a/bioimagesuite30_src/database/vtkbisSQLiteDatabase.cpp b/bioimagesuite30_src/database/vtkbisSQLiteDatabase.cpp
new file mode 100644
index 0000000..6749844
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisSQLiteDatabase.cpp
@@ -0,0 +1,91 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisSQLiteDatabase.cpp
+ *
+ *  Created on: Jan 22, 2009
+ *      Author: Isabella Murphy
+ */
+
+#include <vtkbisSQLiteDatabase.h>
+#include <vtkObjectFactory.h>
+#include <vtkSQLiteDatabase.h>
+
+
+vtkbisSQLiteDatabase* vtkbisSQLiteDatabase::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisSQLiteDatabase");
+  if(ret)
+    {
+      return (vtkbisSQLiteDatabase*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisSQLiteDatabase;
+}
+
+vtkbisSQLiteDatabase::vtkbisSQLiteDatabase() {
+	this->Connection=NULL;
+}
+
+vtkbisSQLiteDatabase::~vtkbisSQLiteDatabase() {
+	this->Connection->Delete();
+}
+
+int vtkbisSQLiteDatabase::Connect(const char* url)
+{
+  if (this->Connection!=NULL)
+    {
+      this->Disconnect();
+      this->Connection->Delete();
+    }
+  //  this->DebugOn();
+  //  fprintf(stderr,"url=%s\n",url);
+  this->Connection = vtkSQLiteDatabase::SafeDownCast( vtkSQLDatabase::CreateFromURL( url ) );
+  //  this->DebugOff();  
+
+#if ((VTK_MAJOR_VERSION >= 5)&&(VTK_MINOR_VERSION >= 4))
+  if ( !this->Connection->Open("") )
+#else
+  if ( !this->Connection->Open() )
+#endif
+    {
+      cerr << "Couldn't open database.\n";
+      return 0;
+    }
+  return 1;
+}
+void vtkbisSQLiteDatabase::Disconnect()
+{
+	if (this->Connection==NULL)
+		return;
+
+	if (this->Connection->IsOpen())
+	    this->Connection->Close();
+}
+
diff --git a/bioimagesuite30_src/database/vtkbisSQLiteDatabase.h b/bioimagesuite30_src/database/vtkbisSQLiteDatabase.h
new file mode 100644
index 0000000..5ee9fe5
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisSQLiteDatabase.h
@@ -0,0 +1,56 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkbisSQLiteDatabase.h
+ *
+ *  Created on: Jan 22, 2009
+ *      Author: isabella
+ */
+
+#ifndef VTKBISSQLITEDATABASE_H_
+#define VTKBISSQLITEDATABASE_H_
+
+#include <vtkSQLDatabase.h>
+#include <vtkObject.h>
+
+class vtkbisSQLiteDatabase : public vtkObject{
+public:
+	static vtkbisSQLiteDatabase *New();
+	vtkTypeMacro(vtkbisSQLiteDatabase,vtkObject);
+
+	int Connect(const char* url);
+	void Disconnect();
+protected:
+	vtkbisSQLiteDatabase();
+	virtual ~vtkbisSQLiteDatabase();
+
+	vtkSQLDatabase* Connection;
+};
+
+#endif /* VTKBISSQLITEDATABASE_H_ */
+
diff --git a/bioimagesuite30_src/database/vtkbisSeries.cpp b/bioimagesuite30_src/database/vtkbisSeries.cpp
new file mode 100644
index 0000000..56db08a
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisSeries.cpp
@@ -0,0 +1,238 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkbisSeries.h"
+#include "vtkObjectFactory.h"
+
+
+
+vtkbisSeries* vtkbisSeries::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisSeries");
+  if(ret)
+    {
+      return (vtkbisSeries*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisSeries;
+}
+
+
+vtkbisSeries::vtkbisSeries()
+{
+  this->SeriesID=new char[10];       this->SetSeriesID("");
+  this->StudyID=new char[10];        this->SetStudyID("");
+  this->InjectionID=new char[10];    this->SetInjectionID("");
+  this->SeriesUID=new char[10];      this->SetSeriesUID("");
+  this->SeriesFileName=new char[10]; this->SetSeriesFileName("");
+  this->SeriesDataPath=new char[10]; this->SetSeriesDataPath("");
+  
+}
+
+
+vtkbisSeries::~vtkbisSeries()
+{
+  if (this->SeriesID==NULL)        delete [] SeriesID;
+  if (this->StudyID==NULL)         delete [] StudyID;
+  if (this->InjectionID==NULL)     delete [] InjectionID;
+  if (this->SeriesUID==NULL)       delete [] SeriesUID;
+  if (this->SeriesFileName==NULL)  delete [] SeriesFileName;
+  if (this->SeriesDataPath==NULL)  delete [] SeriesDataPath;
+}
+
+
+void vtkbisSeries::DebugPrint()
+{
+  cout<<"******Print Series Infomation******"<<endl;
+  cout<<"SeriesID: "<<SeriesID<<endl;
+  cout<<"StudyID: "<<StudyID<<endl;
+  cout<<"InjectionID: "<<InjectionID<<endl;
+  cout<<"SeriesUID: "<<SeriesUID<<endl;
+  cout<<"SeriesFileName: "<<SeriesFileName<<endl;
+  cout<<"SeriesDatapath: "<<SeriesDataPath<<endl;
+  cout<<"******End Series Infomation******"<<endl;
+  
+}
+
+int vtkbisSeries::InsertSeries()
+{
+  int ok=false;
+  if(!this->Connect())
+    {
+      cout<<"Cannot connect to database. Exit."<<endl;
+      return ok;
+    }
+
+  std::string sqlstring;
+  vtkStdString dt;
+  if (this->Connector->GetMode()==0)
+    {
+      sqlstring="Insert into Series(StudyID, InjectionID, SeriesUID, SeriesFileName,SeriesDataPath)";
+      sqlstring+="Value('";
+    }
+  else
+    {
+      dt=this->Connector->RunQuery("SELECT datetime('now')");
+      sqlstring="Insert into Series(SeriesID,StudyID, InjectionID, SeriesUID,SeriesFileName,SeriesDataPath)";
+      sqlstring+="VALUES('";
+      sqlstring+=SeriesID;
+      sqlstring+="','";
+    }
+
+  sqlstring+=StudyID;
+  sqlstring+="','";
+  sqlstring+=InjectionID;
+  if (this->Connector->GetMode()==0)
+    sqlstring+="', NOW(), '";
+  else
+    sqlstring+="','"+dt+"','";
+  sqlstring+=SeriesFileName;
+  sqlstring+="','";
+  sqlstring+=SeriesDataPath;
+  sqlstring+="')";
+
+  //  fprintf(stderr,"adding series %s\n",sqlstring.c_str());
+  vtkStdString s=this->Connector->RunUpdate(sqlstring.c_str());
+  if (s=="ERROR" || s=="")
+    {
+      cerr << "Failed to insert Series: " << endl;
+    }
+  else
+    {
+      ok=1;
+    }
+  return ok;
+}
+
+const char* vtkbisSeries::SearchSeriesID(const char* StudyID,const char* InjectionID)
+{
+  std::string seriesid="";
+  std::string sqlstring;
+  sqlstring="Select SeriesID From Series Where StudyID='";
+  sqlstring+=StudyID;
+  sqlstring+="' and InjectionID='";
+  sqlstring+=InjectionID;
+  sqlstring+="'";
+
+  if (!this->Connect())
+    {
+      cout<<"Cannot connect to database. Exit."<<endl;
+      return seriesid.c_str();
+    }
+
+ this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+  return this->ResultString.c_str();
+}
+
+const char* vtkbisSeries::SearchSeriesUID(const char* SeriesID)
+{
+  std::string seriesuid="";
+  std::string sqlstring;
+  sqlstring="Select SeriesUID From Series Where SeriesID='";
+  sqlstring+=SeriesID;
+  sqlstring+="'";
+  //cout<<"sqlstring= "<<sqlstring<<endl;
+
+  if (!this->Connect())
+    {
+      cout<<"Cannot connect to database. Exit."<<endl;
+      return seriesuid.c_str();
+    }
+
+ this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+  return this->ResultString.c_str();
+}
+
+// ------------------------------------------------------------------------------------
+int vtkbisSeries::FindEmptySeriesID()
+{
+  int done=0;
+
+  //  fprintf(stderr,"Beginning Series ID=%s\n",this->SeriesID);
+
+  while (done == 0)
+    {
+      std::string sqlstring;
+      sqlstring="Select SeriesFileName From Series Where SeriesID='";
+      sqlstring+=SeriesID;
+      sqlstring+="'";
+  
+      if (!this->Connect())
+	{
+	  cout<<"Cannot connect to database. Exit."<<endl;
+	  return 0;
+	}
+      
+     this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+      if (this->ResultString.length()==0)
+	{
+	  done=1;
+	}
+      else
+	{
+	  char line[10];
+	  int newp=atoi(this->SeriesID);
+	  newp=newp+1+int(100.0*vtkMath::Random());
+	  sprintf(line,"%d",newp);
+	  this->SetSeriesID(line);
+	}
+    }
+  return done;
+}
+// ------------------------------------------------------------------------------------
+int vtkbisSeries::AddSeries()
+{
+  int ok=false;
+  std::string seriesid=this->SearchSeriesID(this->StudyID,this->InjectionID);
+  if(seriesid.length()!=0)
+    {
+      cout<<"Series exists as seriesid "<<seriesid<<endl;
+      cout<<"Not adding series"<<endl;
+      return ok;
+    }
+
+  if (this->Connector->GetMode()==1)
+    {
+      this->SetSeriesID("100");
+      int allset=this->FindEmptySeriesID();
+      if (allset==0)
+	{
+	  cout << "Failed to find unique ID";
+	  return ok;
+	}
+      //      fprintf(stderr,"Proceeding, unique ID = %s\n",this->SeriesID);
+    }
+  
+  return this->InsertSeries();
+  
+}
+
+	
+  
+
+
diff --git a/bioimagesuite30_src/database/vtkbisSeries.h b/bioimagesuite30_src/database/vtkbisSeries.h
new file mode 100644
index 0000000..f44a09f
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisSeries.h
@@ -0,0 +1,85 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef SERIES_H
+#define SERIES_H
+#include <vtkstd/string>
+#include "vtkbisBaseProcedure.h"
+
+
+class vtkbisSeries : public vtkbisBaseProcedure
+{
+public:
+  static vtkbisSeries *New();
+  vtkTypeMacro(vtkbisSeries,vtkbisBaseProcedure);
+
+
+  virtual void DebugPrint();
+  virtual int   AddSeries();  
+  virtual const char* SearchSeriesID(const char* StudyID,const char* InjectionID);
+  virtual const char* SearchSeriesUID(const char* SeriesID);
+  
+  // Macros for all Members
+  vtkSetStringMacro(SeriesID);
+  vtkGetStringMacro(SeriesID);
+
+  vtkSetStringMacro(StudyID);
+  vtkGetStringMacro(StudyID);
+
+  vtkSetStringMacro(InjectionID);
+  vtkGetStringMacro(InjectionID);
+
+  vtkSetStringMacro(SeriesUID);
+  vtkGetStringMacro(SeriesUID);
+
+  vtkSetStringMacro(SeriesFileName);
+  vtkGetStringMacro(SeriesFileName);
+
+  vtkSetStringMacro(SeriesDataPath);
+  vtkGetStringMacro(SeriesDataPath);
+
+
+protected:  
+  vtkbisSeries();
+  virtual ~vtkbisSeries();
+  
+  vtkbisSeries(const vtkbisSeries&) {};
+  void operator=(const vtkbisSeries&) {};
+
+  char* SeriesID;
+  char* StudyID;
+  char* InjectionID;
+  char* SeriesUID;
+  char* SeriesFileName;
+  char* SeriesDataPath;
+
+  virtual int InsertSeries();
+  virtual int  FindEmptySeriesID();  
+};
+
+#endif 
+
diff --git a/bioimagesuite30_src/database/vtkbisStudy.cpp b/bioimagesuite30_src/database/vtkbisStudy.cpp
new file mode 100644
index 0000000..e377764
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisStudy.cpp
@@ -0,0 +1,236 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkbisStudy.h"
+#include "vtkObjectFactory.h"
+
+using namespace std;
+
+vtkbisStudy* vtkbisStudy::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisStudy");
+  if(ret)
+    {
+      return (vtkbisStudy*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisStudy;
+}
+
+
+vtkbisStudy::vtkbisStudy()
+{
+  this->StudyID=new char[10];
+  this->VisitID=new char[10];
+  this->PatientID=new char[10];
+  this->StudyUID=new char[10];
+
+  this->SetVisitID("");
+  this->SetPatientID("");
+  this->SetStudyID("");
+  this->SetStudyUID("");
+}
+
+vtkbisStudy::~vtkbisStudy()
+{
+  if (this->VisitID !=NULL ) delete [] this->VisitID;
+  if (this->PatientID !=NULL ) delete [] this->PatientID;
+  if (this->StudyID !=NULL ) delete [] this->StudyID;
+  if (this->StudyUID !=NULL ) delete [] this->StudyUID;
+}
+
+
+void vtkbisStudy::DebugPrint()
+{
+  cout<<"******Print Study Infomation******"<<endl;
+  cout<<"StudyID: "<<StudyID<<endl;
+  cout<<"VisitID: "<<VisitID<<endl;
+  cout<<"PatientID: "<<PatientID<<endl;
+  cout<<"StudyUID: "<<StudyUID<<endl;
+  cout<<"******End Study Infomation******"<<endl;
+  
+}
+
+int vtkbisStudy::InsertStudy()
+{
+  int ok=false;
+  std::string sqlstring;
+  if(!this->Connect())
+  {
+    cout<<"Cannot connect to database. Exit."<<endl;
+    return ok;
+  }
+
+  if (this->Connector->GetMode()==0)
+    {
+      sqlstring="Insert into Study(VisitID,PatientID,StudyUID)";
+      sqlstring+="Value('";
+      sqlstring+=VisitID;
+      sqlstring+="','";
+      sqlstring+=PatientID;
+      sqlstring+="',NOW() )";
+    }
+  else
+    {
+      vtkStdString dt=this->Connector->RunQuery("SELECT datetime('now')");
+      
+      sqlstring="Insert into Study(StudyID,VisitID,PatientID,StudyUID)";
+      sqlstring+="VALUES('";
+      sqlstring+=StudyID;
+      sqlstring+="','";
+      sqlstring+=VisitID;
+      sqlstring+="','";
+      sqlstring+=PatientID;
+      sqlstring+="','";
+      sqlstring+=dt;
+      sqlstring+="')";
+    }
+  
+  //  fprintf(stderr,"adding study %s\n",sqlstring.c_str());
+
+  vtkStdString s=this->Connector->RunUpdate(sqlstring.c_str());
+  if (s=="ERROR" || s=="")
+    {
+      cerr << "Failed to insert Study: " << endl;
+    }
+  else
+    {
+      ok=1;
+    }
+  return ok;
+}
+
+const char* vtkbisStudy::SearchStudyID(const char* VisitID, const char* PatientID)
+{
+  std::string studyid="";
+  std::string sqlstring;
+  sqlstring="Select max(StudyID) From Study Where PatientID='";
+  sqlstring+=PatientID;
+  sqlstring+="' and VisitID='";
+  sqlstring+=VisitID;
+  sqlstring+="'";
+  
+  if (!this->Connect())
+    {
+      cout<<"Cannot connect to database. Exit."<<endl;
+      return studyid.c_str();
+    }
+
+ this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+  return this->ResultString.c_str();  
+}
+
+const char* vtkbisStudy::SearchStudyUID(const char* StudyID)
+{
+  std::string studyuid="";
+  std::string sqlstring;
+  sqlstring="Select StudyUID From Study Where StudyID='";
+  sqlstring+=StudyID;
+  sqlstring+="'";
+  //cout<<"sqlstring= "<<sqlstring<<endl;
+  
+  if (!this->Connect())
+    {
+      cout<<"Cannot connect to database. Exit."<<endl;
+      return studyuid.c_str();
+    }
+
+ this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+  return this->ResultString.c_str();
+}
+
+
+
+// ------------------------------------------------------------------------------------
+int vtkbisStudy::FindEmptyStudyID()
+{
+  int done=0;
+
+  //  fprintf(stderr,"Beginning Study ID=%s\n",this->StudyID);
+
+  while (done == 0)
+    {
+      std::string sqlstring;
+      sqlstring="Select PatientID From Study Where StudyID='";
+      sqlstring+=StudyID;
+      sqlstring+="'";
+  
+      if (!this->Connect())
+	{
+	  cout<<"Cannot connect to database. Exit."<<endl;
+	  return 0;
+	}
+      
+     this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+      if (this->ResultString.length()==0)
+	{
+	  done=1;
+	}
+      else
+	{
+	  char line[10];
+	  int newp=atoi(this->StudyID);
+	  newp=newp+1+int(100.0*vtkMath::Random());
+	  sprintf(line,"%d",newp);
+	  this->SetStudyID(line);
+	}
+    }
+  return done;
+}
+// ------------------------------------------------------------------------------------
+int vtkbisStudy::AddStudy()
+{
+  int ok=false;
+  std::string studyid=this->SearchStudyID(this->VisitID,this->PatientID);
+  if(studyid.length()!=0)
+    {
+      cout<<"Study exists as studyid "<<studyid<<endl;
+      cout<<"Not adding study"<<endl;
+      return ok;
+    }
+
+  if (this->Connector->GetMode()==1)
+    {
+      this->SetStudyID("100");
+      int allset=this->FindEmptyStudyID();
+      if (allset==0)
+	{
+	  cout << "Failed to find unique ID";
+	  return ok;
+	}
+      //      fprintf(stderr,"Proceeding, unique ID = %s\n",this->StudyID);
+    }
+  
+  return this->InsertStudy();
+  
+}
+
+	
+  
+
+
diff --git a/bioimagesuite30_src/database/vtkbisStudy.h b/bioimagesuite30_src/database/vtkbisStudy.h
new file mode 100644
index 0000000..e33f418
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisStudy.h
@@ -0,0 +1,78 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef STUDY_H
+#define STUDY_H
+#include <vtkstd/string>
+#include "vtkbisBaseProcedure.h"
+
+
+class vtkbisStudy : public vtkbisBaseProcedure
+{
+public:
+  static vtkbisStudy *New();
+  vtkTypeMacro(vtkbisStudy,vtkbisBaseProcedure);
+
+  virtual void DebugPrint();
+  virtual int   AddStudy();  
+
+  virtual const char* SearchStudyID(const char* VisitID, const char* PatientID);
+  virtual const char* SearchStudyUID(const char* StudyID);
+  
+  // Macros for all Members
+  vtkSetStringMacro(VisitID);
+  vtkGetStringMacro(VisitID);
+
+  vtkSetStringMacro(StudyID);
+  vtkGetStringMacro(StudyID);
+
+  vtkSetStringMacro(PatientID);
+  vtkGetStringMacro(PatientID);
+
+  vtkSetStringMacro(StudyUID);
+  vtkGetStringMacro(StudyUID);
+
+
+protected:  
+  vtkbisStudy();
+  virtual ~vtkbisStudy(); 
+//BTX
+//  vtkbisStudy(const vtkbisStudy&) {};
+//  void operator=(const vtkbisStudy&) {};
+  //ETX
+
+  char* StudyID;
+  char* VisitID;
+  char* PatientID;
+  char* StudyUID;
+
+  int InsertStudy();
+  virtual int  FindEmptyStudyID();  
+};
+
+#endif 
+
diff --git a/bioimagesuite30_src/database/vtkbisVisit.cpp b/bioimagesuite30_src/database/vtkbisVisit.cpp
new file mode 100644
index 0000000..c18e557
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisVisit.cpp
@@ -0,0 +1,226 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkbisVisit.h"
+#include "vtkObjectFactory.h"
+
+
+
+vtkbisVisit* vtkbisVisit::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkbisVisit");
+  if(ret)
+    {
+      return (vtkbisVisit*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkbisVisit;
+}
+
+
+vtkbisVisit::vtkbisVisit()
+{
+  this->VisitID=new char[10];
+  this->PatientID=new char[10];
+  this->ProtocolID=new char[10];
+  this->VisitDate=new char[10];
+  this->Age=0;
+  this->Height=0.0;
+  this->Weight=0.0;
+  this->Notes=new char[10];
+
+
+  this->SetVisitID("");
+  this->SetPatientID("");
+  this->SetProtocolID("100");
+  this->SetVisitDate("");
+  this->SetNotes("");
+}
+
+vtkbisVisit::~vtkbisVisit()
+{
+  if (this->VisitID !=NULL ) delete [] this->VisitID;
+  if (this->PatientID !=NULL ) delete [] this->PatientID;
+  if (this->ProtocolID !=NULL ) delete [] this->ProtocolID;
+  if (this->VisitDate !=NULL ) delete [] this->VisitDate;
+  if (this->Notes !=NULL ) delete [] this->Notes;
+}
+
+void vtkbisVisit::DebugPrint()
+{
+  cout<<"******Print Visit Infomation******"<<endl;
+  cout<<"VisitID: "<<VisitID<<endl;
+  cout<<"PatientID: "<<PatientID<<endl;
+  cout<<"ProtocolID: "<<ProtocolID<<endl;
+  cout<<"VisitDate: "<<VisitDate<<endl;
+  cout<<"Age: "<<Age<<endl;
+  cout<<"Height: "<<Height<<endl;
+  cout<<"Weight: "<<Weight<<endl;
+  cout<<"Notes: "<<Notes<<endl;
+  cout<<"******End Visit Infomation******"<<endl;
+  
+}
+
+int vtkbisVisit::InsertVisit()
+{
+  int ok=false;
+  std::string sqlstring;
+  if (this->Connector->GetMode()==0)
+    {
+      sqlstring="Insert into Visit(PatientID, ProtocolID,VisitDate)";
+      sqlstring+="Value('";
+    }
+  else
+    {
+      sqlstring="Insert into Visit(VisitID, PatientID, ProtocolID,VisitDate)";
+      sqlstring+="VALUES('";
+      sqlstring+=VisitID;
+      sqlstring+="','";
+    }
+
+  sqlstring+=PatientID;
+  sqlstring+="','";
+  sqlstring+=ProtocolID;
+  sqlstring+="','";
+  sqlstring+=VisitDate;
+  sqlstring+="')";
+
+  if(!this->Connect())
+    {
+      cout<<"Cannot connect to database. Exit."<<endl;
+      return ok;
+    }
+  vtkStdString s=this->Connector->RunUpdate(sqlstring.c_str());
+  if (s=="ERROR" || s=="" )
+    {
+      cerr << "Failed to insert Visit: " << endl;
+    }
+  else
+    {
+      ok=1;
+    }
+  return ok;
+}
+
+const char* vtkbisVisit::SearchVisitID(const char* cPatientID,const char* cProtocolID,const char* cVisitDate)
+{
+  std::string visitid="";
+  std::string sqlstring;
+  this->SetPatientID(cPatientID);
+  this->SetProtocolID(cProtocolID);
+  this->SetVisitDate(cVisitDate);
+
+  sqlstring="Select VisitID From Visit Where PatientID='";
+  sqlstring+=cPatientID;
+  sqlstring+="' and ProtocolID='";
+  sqlstring+=cProtocolID;
+  sqlstring+="' and VisitDate='";
+  sqlstring+=cVisitDate;
+  sqlstring+="'";
+  
+  if (!this->Connect())
+    {
+      cout<<"Cannot connect to database. Exit."<<endl;
+      return visitid.c_str();
+    }
+
+ this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+  return this->ResultString.c_str();
+}
+
+
+  
+
+// ------------------------------------------------------------------------------------
+
+int vtkbisVisit::FindEmptyVisitID()
+{
+  int done=0;
+
+  //  fprintf(stderr,"Beginning Visit ID=%s\n",this->VisitID);
+
+  while (done == 0)
+    {
+      std::string sqlstring;
+      sqlstring="Select PatientID From Visit Where VisitID='";
+      sqlstring+=VisitID;
+      sqlstring+="'";
+  
+      if (!this->Connect())
+	{
+	  cout<<"Cannot connect to database. Exit."<<endl;
+	  return 0;
+	}
+      
+     this->ResultString=this->Connector->RunQuery(sqlstring.c_str());
+      if (this->ResultString.length()==0)
+	{
+	  done=1;
+	}
+      else
+	{
+	  char line[10];
+	  int newp=atoi(this->VisitID);
+	  newp=newp+1+int(100.0*vtkMath::Random());
+	  sprintf(line,"%d",newp);
+	  this->SetVisitID(line);
+	}
+    }
+  return done;
+}
+// ------------------------------------------------------------------------------------
+int vtkbisVisit::AddVisit()
+{
+  int ok=false;
+  std::string visitid=this->SearchVisitID(PatientID,ProtocolID,VisitDate);
+  if(visitid.length()!=0)
+    {
+      cout<<"Visit exists as visitid "<<visitid<<endl;
+      cout<<"Not adding visit"<<endl;
+      return ok;
+    }
+
+  if (this->Connector->GetMode()==1)
+    {
+      this->SetVisitID("100");
+      int allset=this->FindEmptyVisitID();
+      if (allset==0)
+	{
+	  cout << "Failed to find unique ID";
+	  return ok;
+	}
+    }
+  
+  return this->InsertVisit();
+  
+}
+
+	
+  
+
+
diff --git a/bioimagesuite30_src/database/vtkbisVisit.h b/bioimagesuite30_src/database/vtkbisVisit.h
new file mode 100644
index 0000000..2bde29c
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkbisVisit.h
@@ -0,0 +1,93 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef VISIT_H
+#define VISIT_H
+
+#include "vtkbisDatabase.h"
+#include "vtkbisBaseProcedure.h"
+
+class vtkbisVisit : public vtkbisBaseProcedure
+{
+public:
+  static vtkbisVisit *New();
+  vtkTypeMacro(vtkbisVisit,vtkbisBaseProcedure);
+
+  virtual void DebugPrint();
+
+  virtual int   AddVisit();  
+  const char* SearchVisitID(const char* PatientID,const char* ProtocolID,const char* VisitDate);
+
+  // Macros for all Members
+  vtkSetStringMacro(VisitID);
+  vtkGetStringMacro(VisitID);
+
+  vtkSetStringMacro(PatientID);
+  vtkGetStringMacro(PatientID);
+
+  vtkSetStringMacro(ProtocolID);
+  vtkGetStringMacro(ProtocolID);
+
+  vtkSetStringMacro(VisitDate);
+  vtkGetStringMacro(VisitDate);
+
+  vtkSetStringMacro(Notes);
+  vtkGetStringMacro(Notes);
+
+  // Other Members
+  vtkGetMacro(Age,int);
+  vtkGetMacro(Height,float);
+  vtkGetMacro(Weight,float);
+
+  vtkSetMacro(Age,int);
+  vtkSetMacro(Height,float);
+  vtkSetMacro(Weight,float);
+
+protected:  
+  vtkbisVisit();
+  virtual ~vtkbisVisit();
+//BTX
+  vtkbisVisit(const vtkbisVisit&) {};
+  void operator=(const vtkbisVisit&) {};
+  //ETX
+
+  char* VisitID;
+  char* PatientID;
+  char* ProtocolID;
+  char* VisitDate;
+  char* Notes;
+  int	Age;
+  float	Height;
+  float	Weight;
+
+
+  virtual int  InsertVisit();
+  virtual int  FindEmptyVisitID();  
+};
+
+#endif 
+
diff --git a/bioimagesuite30_src/database/vtkimSQLite.cpp b/bioimagesuite30_src/database/vtkimSQLite.cpp
new file mode 100644
index 0000000..cb804b7
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkimSQLite.cpp
@@ -0,0 +1,190 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkimSQLite.cpp
+ *
+ *  Created on: Jan 20, 2009
+ *      Author: Isabella Murphy
+ */
+
+#include <vtkimSQLite.h>
+#include <vtkObjectFactory.h>
+#include <vtkSQLiteDatabase.h>
+#include <vtkStdString.h>
+#include <vtkSQLQuery.h>
+#include <vtkVariant.h>
+
+vtkimSQLite::vtkimSQLite() {
+	this->Connection=NULL;
+	this->FileName=NULL;
+	this->Description=NULL;
+
+	this->SetFileName("");
+	this->SetDescription("");
+
+}
+
+vtkimSQLite::~vtkimSQLite() {
+	this->Connection->Delete();
+	if (this->FileName==NULL)  delete [] this->FileName;
+	if (this->Description==NULL)  delete [] this->Description;
+}
+
+vtkimSQLite* vtkimSQLite::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkimSQLite");
+  if(ret)
+    {
+      return (vtkimSQLite*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkimSQLite;
+}
+
+int vtkimSQLite::Connect(const char* url)
+{
+	if (this->Connection!=NULL)
+	{
+		this->Disconnect();
+	    this->Connection->Delete();
+	}
+	//this->Connection=vtkSQLiteDatabase::New();
+	this->Connection = vtkSQLiteDatabase::SafeDownCast( vtkSQLDatabase::CreateFromURL( url ) );
+#if ((VTK_MAJOR_VERSION >= 5)&&(VTK_MINOR_VERSION >= 4))
+        bool status = this->Connection->Open("");
+#else
+        bool status = this->Connection->Open();
+#endif
+
+	if ( ! status )
+	{
+		cerr << "Couldn't open database.\n";
+		return 0;
+	}
+	return 1;
+}
+
+void vtkimSQLite::Initialize(const char* filename, const char* description)
+{
+	this->SetFileName(filename);
+	this->SetDescription(description);
+}
+
+void vtkimSQLite::CreateTable()
+{
+	vtkStdString createQuery("CREATE TABLE IF NOT EXISTS imsqlite_test (filename TEXT, description TEXT)");
+	cout << createQuery << endl;
+	vtkSQLQuery* query = this->Connection->GetQueryInstance();
+	query->SetQuery( createQuery.c_str());
+	if (!query->Execute())
+	{
+		cerr << "Create query failed" << query->GetLastErrorText()<<endl;
+	}
+}
+
+void vtkimSQLite::InsertQuery()
+{
+	vtkStdString sqlstring="INSERT INTO imsqlite_test (filename, description) ";
+	sqlstring+="VALUES('";
+	sqlstring+=FileName;
+	sqlstring+="','";
+	sqlstring+=Description;
+	sqlstring+="')";
+
+	if (!this->Connection->IsOpen())
+	{
+	    cout<<"Cannot connect to database. Exit."<<endl;
+	}
+
+	vtkSQLQuery* query = this->Connection->GetQueryInstance();
+	query->SetQuery(sqlstring.c_str());
+	cout<<sqlstring<<endl;
+	if (!query->Execute())
+	{
+		cerr << "Insert query failed: " << query->GetLastErrorText()<<endl;
+	}
+}
+
+void vtkimSQLite::DeleteQuery(const char* filename)
+{
+	vtkStdString sqlstring= "DELETE from imsqlite_test WHERE filename = ";
+	sqlstring+="'";
+	sqlstring+=filename;
+	sqlstring+="'";
+	vtkSQLQuery* query = this->Connection->GetQueryInstance();
+	cout<<sqlstring<<endl;
+	query->SetQuery( sqlstring);
+	cerr << endl << "Running query: " << query->GetQuery() << endl;
+
+	if (!query->Execute())
+	{
+		cerr << "Query failed" <<query->GetLastErrorText()<< endl;
+	}
+}
+void vtkimSQLite::Disconnect()
+{
+  if (this->Connection==NULL)
+    return;
+
+  if (this->Connection->IsOpen())
+    this->Connection->Close();
+}
+void vtkimSQLite::PrintTable()
+{
+	vtkStdString queryText = "SELECT * from imsqlite_test ";
+	vtkSQLQuery* query = this->Connection->GetQueryInstance();
+	query->SetQuery( queryText );
+	if (!query->Execute())
+	{
+		cerr << "Query failed" <<query->GetLastErrorText()<< endl;
+	}
+	for ( int col = 0; col < query->GetNumberOfFields(); col++)
+	{
+		if ( col > 0)
+		{
+		    cerr << ", ";
+		}
+		cerr << query->GetFieldName( col );
+	}
+	cerr << endl;
+	while ( query->NextRow())
+	{
+		for ( int field = 0; field < query->GetNumberOfFields(); field++)
+		{
+		    if ( field > 0)
+		    {
+		    	cerr << ", ";
+		    }
+		    cerr << query->DataValue( field ).ToString().c_str();
+		}
+		    cerr << endl;
+	}
+}
+
+
diff --git a/bioimagesuite30_src/database/vtkimSQLite.h b/bioimagesuite30_src/database/vtkimSQLite.h
new file mode 100644
index 0000000..c90cc1b
--- /dev/null
+++ b/bioimagesuite30_src/database/vtkimSQLite.h
@@ -0,0 +1,68 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+ * vtkimSQLite.h
+ *
+ *  Created on: Jan 20, 2009
+ *      Author: isabella
+ */
+
+#ifndef VTKIMSQLITE_H_
+#define VTKIMSQLITE_H_
+
+#include <vtkSQLDatabase.h>
+
+class vtkimSQLite : public vtkObject{
+public:
+	static vtkimSQLite *New();
+	vtkTypeMacro(vtkimSQLite,vtkObject);
+
+	vtkSetStringMacro(FileName);
+	vtkGetStringMacro(FileName);
+
+	vtkSetStringMacro(Description);
+	vtkGetStringMacro(Description);
+	void Initialize(const char* fileName, const char* description);
+	int Connect(const char* url);
+	void Disconnect();
+	void CreateTable();
+	void InsertQuery();
+	void DeleteQuery(const char* filename);
+	void PrintTable();
+
+protected:
+	vtkimSQLite();
+	virtual ~vtkimSQLite();
+	vtkSQLDatabase* Connection;
+
+	char* FileName;
+	char* Description;
+};
+
+#endif /* VTKIMSQLITE_H_ */
+
diff --git a/bioimagesuite30_src/igtlutil/CMakeLists.txt b/bioimagesuite30_src/igtlutil/CMakeLists.txt
new file mode 100644
index 0000000..e2ab19c
--- /dev/null
+++ b/bioimagesuite30_src/igtlutil/CMakeLists.txt
@@ -0,0 +1,61 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE_BINARY_DIR})
+
+SET(IGTL_UTIL_PROTOCOL_VERSION "1")
+
+SET(IGTLUTIL_HEADS
+  igtl_header.h
+  igtl_image.h
+  igtl_transform.h
+  igtl_util.h
+  igtl_types.h
+  )
+
+SET(IGTLUTIL_SRCS
+  igtl_header.c
+  igtl_image.c
+  igtl_transform.c
+  igtl_util.c
+  )       
+
+SET(KITSRCS ${IGTLUTIL_SRCS})
+SET(KITBASE igtlutil)
+SET(KIT ${KITBASE})
+SET (KITEXTRAFILES
+igtlutil/igtl_types.h
+)
+
+bis_static(${KIT})
+bis_sourcelist("igtlutil" ${KIT} ${FILELIST})
+
+
+
+
diff --git a/bioimagesuite30_src/igtlutil/igtl_header.c b/bioimagesuite30_src/igtlutil/igtl_header.c
new file mode 100644
index 0000000..be08d1b
--- /dev/null
+++ b/bioimagesuite30_src/igtlutil/igtl_header.c
@@ -0,0 +1,57 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Open ITK Link Library
+  Module:    $RCSfile: $
+  Language:  C
+  Date:      $Date: $
+  Version:   $Revision: $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#include "igtl_util.h"
+#include "igtl_header.h"
+
+void igtl_header_convert_byte_order(igtl_header * header)
+{
+  if (igtl_is_little_endian()) {
+    header->version   = BYTE_SWAP_INT16(header->version);
+    header->timestamp = BYTE_SWAP_INT64(header->timestamp);
+    header->body_size = BYTE_SWAP_INT64(header->body_size);
+    header->crc       = BYTE_SWAP_INT64(header->crc);
+  }  
+}
+
+
diff --git a/bioimagesuite30_src/igtlutil/igtl_header.h b/bioimagesuite30_src/igtlutil/igtl_header.h
new file mode 100644
index 0000000..97b0e2c
--- /dev/null
+++ b/bioimagesuite30_src/igtlutil/igtl_header.h
@@ -0,0 +1,97 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Open ITK Link Library
+  Module:    $RCSfile: $
+  Language:  C
+  Date:      $Date: $
+  Version:   $Revision: $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#ifndef __IGTL_HEADER_H
+#define __IGTL_HEADER_H
+
+#define IGTL_HEADER_VERSION   1
+#define IGTL_HEADER_SIZE      58
+
+#define IGTL_HEADER_NAMESIZE  12
+#define IGTL_HEADER_DEVSIZE   20
+
+#include "igtl_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma pack(1)     /* For 1-byte boundary in memroy */
+
+/*
+ * Message header of OpenIGTLink message.
+ *
+ * igtl_header is an overall data header for OpenIGTLink protocol.
+ * It is transfered at beginning of every OpenIGTLink message to give
+ * type and size of following data body to a receiver.
+ * These parameters allow the receiver to parse or skip the data body.
+ */
+
+typedef struct {
+  igtl_uint16    version;          /* protocol version number */
+  char           name[IGTL_HEADER_NAMESIZE];       /* data type name          */
+  char           device_name[IGTL_HEADER_DEVSIZE]; /* device name             */
+  igtl_uint64    timestamp;        /* time stamp message      */
+  igtl_uint64    body_size;        /* size of the body        */
+  igtl_uint64    crc;              /* CRC                     */
+} igtl_header;
+
+#pragma pack()
+
+/*
+ * Byte order converter for the header structre
+ * 
+ * igtl_header_convert_byte_order convers endianness of each
+ * member variable in igtl_header structre from host byte order
+ * to network byte order, or vice versa.
+ *
+ */
+void igtl_header_convert_byte_order(igtl_header * header);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // __IGTL_HEADER_H
+
+
diff --git a/bioimagesuite30_src/igtlutil/igtl_image.c b/bioimagesuite30_src/igtlutil/igtl_image.c
new file mode 100644
index 0000000..07de53d
--- /dev/null
+++ b/bioimagesuite30_src/igtlutil/igtl_image.c
@@ -0,0 +1,192 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Open ITK Link Library
+  Module:    $RCSfile: $
+  Language:  C
+  Date:      $Date: $
+  Version:   $Revision: $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#include <string.h>
+#include <math.h>
+
+#include "igtl_image.h"
+#include "igtl_util.h"
+
+igtl_uint64 igtl_image_get_data_size(igtl_image_header * header)
+{
+  igtl_uint64 si;
+  igtl_uint64 sj;
+  igtl_uint64 sk;
+  igtl_uint64 sp;
+  igtl_uint64 data_size;
+
+  si = header->subvol_size[0];
+  sj = header->subvol_size[1];
+  sk = header->subvol_size[2];
+
+  switch (header->scalar_type) {
+  case IGTL_IMAGE_STYPE_TYPE_INT8:
+  case IGTL_IMAGE_STYPE_TYPE_UINT8:
+    sp = 1;
+    break;
+  case IGTL_IMAGE_STYPE_TYPE_INT16:
+  case IGTL_IMAGE_STYPE_TYPE_UINT16:
+    sp = 2;
+    break;
+  case IGTL_IMAGE_STYPE_TYPE_INT32:
+  case IGTL_IMAGE_STYPE_TYPE_UINT32:
+    sp = 4;
+    break;
+  default:
+    sp = 0;
+    break;
+  }
+
+  data_size = si*sj*sk*sp;
+  return data_size;
+}
+
+
+void igtl_image_set_matrix(float spacing[3], float origin[3],
+                            float norm_i[3], float norm_j[3], float norm_k[3],
+                            igtl_image_header * header)
+{
+  header->matrix[0]  = (igtl_float32) (norm_i[0] * spacing[0]);
+  header->matrix[1]  = (igtl_float32) (norm_i[1] * spacing[0]);
+  header->matrix[2]  = (igtl_float32) (norm_i[2] * spacing[0]);
+  header->matrix[3]  = (igtl_float32) (norm_j[0] * spacing[1]);
+  header->matrix[4]  = (igtl_float32) (norm_j[1] * spacing[1]);
+  header->matrix[5]  = (igtl_float32) (norm_j[2] * spacing[1]);
+  header->matrix[6]  = (igtl_float32) (norm_k[0] * spacing[2]);
+  header->matrix[7]  = (igtl_float32) (norm_k[1] * spacing[2]);
+  header->matrix[8]  = (igtl_float32) (norm_k[2] * spacing[2]);
+  header->matrix[9]  = (igtl_float32) (origin[0]);
+  header->matrix[10] = (igtl_float32) (origin[1]);
+  header->matrix[11] = (igtl_float32) (origin[2]);
+}
+
+void igtl_image_get_matrix(float spacing[3], float origin[3],
+                            float norm_i[3], float norm_j[3], float norm_k[3],
+                            igtl_image_header * header)
+{
+  float tx;
+  float ty;
+  float tz;
+  float sx;
+  float sy;
+  float sz;
+  float nx;
+  float ny;
+  float nz;
+  float px;
+  float py;
+  float pz;
+
+  tx = (float) header->matrix[0];
+  ty = (float) header->matrix[1];
+  tz = (float) header->matrix[2];
+  sx = (float) header->matrix[3];
+  sy = (float) header->matrix[4];
+  sz = (float) header->matrix[5];
+  nx = (float) header->matrix[6];
+  ny = (float) header->matrix[7];
+  nz = (float) header->matrix[8];
+  px = (float) header->matrix[9];
+  py = (float) header->matrix[10];
+  pz = (float) header->matrix[11];
+
+  spacing[0] = sqrt(tx*tx + ty*ty + tz*tz);
+  spacing[1] = sqrt(sx*sx + sy*sy + sz*sz);
+  spacing[2] = sqrt(nx*nx + ny*ny + nz*nz);
+  norm_i[0] = header->matrix[0]  / spacing[0];
+  norm_i[1] = header->matrix[1]  / spacing[0];
+  norm_i[2] = header->matrix[2]  / spacing[0];
+  norm_j[0] = - header->matrix[3] / spacing[1];
+  norm_j[1] = - header->matrix[4] / spacing[1];
+  norm_j[2] = - header->matrix[5] / spacing[1];
+  norm_k[0] = - header->matrix[6] / spacing[2];
+  norm_k[1] = - header->matrix[7] / spacing[2];
+  norm_k[2] = - header->matrix[8] / spacing[2];
+  origin[0] = header->matrix[9];
+  origin[1] = header->matrix[10];
+  origin[2] = header->matrix[11];
+
+}
+
+
+void igtl_image_convert_byte_order(igtl_image_header * header)
+{
+  int i;
+  igtl_uint32 tmp[12];
+
+  if (igtl_is_little_endian()) 
+    {
+
+    header->version = BYTE_SWAP_INT16(header->version);
+
+    for (i = 0; i < 3; i ++) 
+      {
+      header->size[i] = BYTE_SWAP_INT16(header->size[i]);
+      header->subvol_size[i] = BYTE_SWAP_INT16(header->subvol_size[i]);
+      header->subvol_offset[i] = BYTE_SWAP_INT16(header->subvol_offset[i]);
+      }
+    memcpy((void*)tmp, (void*)(header->matrix), sizeof(igtl_float32)*12);
+
+    for (i = 0; i < 12; i ++) 
+      {
+      tmp[i] = BYTE_SWAP_INT32(tmp[i]);
+      }
+
+    memcpy((void*)(header->matrix), (void*)tmp, sizeof(igtl_float32)*12);
+  }
+}
+
+
+igtl_uint64 igtl_image_get_crc(igtl_image_header * header, void* image)
+{
+  igtl_uint64   crc;
+  igtl_uint64   img_size;
+
+  img_size = igtl_image_get_data_size(header);
+  crc = crc64(0, 0, 0);
+  crc = crc64((unsigned char*) header, IGTL_IMAGE_HEADER_SIZE, crc);
+  crc = crc64((unsigned char*) image, img_size, crc);
+
+  return crc;
+}
+
diff --git a/bioimagesuite30_src/igtlutil/igtl_image.h b/bioimagesuite30_src/igtlutil/igtl_image.h
new file mode 100644
index 0000000..0622825
--- /dev/null
+++ b/bioimagesuite30_src/igtlutil/igtl_image.h
@@ -0,0 +1,167 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Open ITK Link Library
+  Module:    $RCSfile: $
+  Language:  C
+  Date:      $Date: $
+  Version:   $Revision: $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#ifndef __IGTL_IMAGE_H
+#define __IGTL_IMAGE_H
+
+#include "igtl_util.h"
+#include "igtl_types.h"
+
+#define IGTL_IMAGE_HEADER_VERSION       1
+#define IGTL_IMAGE_HEADER_SIZE          72
+
+/* Data type */
+#define IGTL_IMAGE_DTYPE_SCALAR         1
+#define IGTL_IMAGE_DTYPE_VECTOR         2
+
+/* Scalar type */
+#define IGTL_IMAGE_STYPE_TYPE_INT8      2
+#define IGTL_IMAGE_STYPE_TYPE_UINT8     3
+#define IGTL_IMAGE_STYPE_TYPE_INT16     4
+#define IGTL_IMAGE_STYPE_TYPE_UINT16    5
+#define IGTL_IMAGE_STYPE_TYPE_INT32     6
+#define IGTL_IMAGE_STYPE_TYPE_UINT32    7
+
+/* Endian */
+#define IGTL_IMAGE_ENDIAN_BIG           1
+#define IGTL_IMAGE_ENDIAN_LITTLE        2
+
+/* Image coordinate system */
+#define IGTL_IMAGE_COORD_RAS            1
+#define IGTL_IMAGE_COORD_LPS            2
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#pragma pack(1)     /* For 1-byte boundary in memroy */
+
+/*
+ * Image data header for OpenIGTLinik protocol
+ *
+ * Image data consists of image data header, which is defined in this
+ * structure, folowed by array of image pixel data.
+ * igtl_image_header helps a receiver to load array of image pixel data.
+ * The header supports "partial volume update", where a fraction of volume
+ * image is transferred from a sender to receiver. This fraction called
+ * "sub-volume" in this protocol, and its size and starting index is
+ * specified in 'subvol_size' and 'subvol_offset'.
+ * In case of transferring entire image in one message, 'size' and
+ * 'subvol_size' should be same, and 'subvol_offset' equals (0, 0, 0).
+ */
+
+typedef struct {
+  igtl_uint16    version;          /* data format version number      */
+  igtl_uint8     data_type;        /* data type (scalar or vector)    */
+  igtl_uint8     scalar_type;      /* scalar type                     */
+  igtl_uint8     endian;           /* endian type of image data       */
+  igtl_uint8     coord;            /* coordinate system (LPS or RAS)  */
+  igtl_uint16    size[3];          /* entire image volume size        */
+  igtl_float32   matrix[12];       /* orientation / origin of image   */
+                                   /*  - matrix[0-2]: norm_i * pix_i  */
+                                   /*  - matrix[3-5]: norm_j * pix_j  */
+                                   /*  - matrix[6-8]: norm_k * pix_k  */
+                                   /*  - matrix[9-11]:origin          */
+                                   /* where norm_* are normal vectors */
+                                   /* along each index, and pix_* are */
+                                   /* pixel size in each direction    */
+
+  igtl_uint16    subvol_offset[3]; /* sub volume offset               */
+  igtl_uint16    subvol_size[3];   /* sub volume size                 */
+} igtl_image_header;
+
+#pragma pack()
+
+
+/*
+ * Image data size
+ *
+ * This function calculates size of the pixel array, which will be
+ * transferred with the specified header.
+ */
+
+igtl_uint64 igtl_image_get_data_size(igtl_image_header * header);
+
+
+/*
+ * Generate matrix 
+ *
+ * This function generates image orientation/origin matrix from 
+ * spacing, origin and normal vectors.
+ */
+
+void igtl_image_set_matrix(float spacing[3], float origin[3],
+                            float norm_i[3], float norm_j[3], float norm_k[3],
+                            igtl_image_header * header);
+
+void igtl_image_get_matrix(float spacing[3], float origin[3],
+                            float norm_i[3], float norm_j[3], float norm_k[3],
+                            igtl_image_header * header);
+
+/*
+ * Byte order conversion for the header structure
+ *
+ * This function converts endianness of each member variable
+ * in igtl_image_header from host byte order to network byte order,
+ * or vice versa.
+ */
+
+void igtl_image_convert_byte_order(igtl_image_header * header);
+
+
+/*
+ * CRC calculation
+ *
+ * This function calculates CRC of image data body including header
+ * and array of pixel data.
+ *
+ */
+
+igtl_uint64 igtl_image_get_crc(igtl_image_header * header, void* image);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __IGTL_IMAGE_H */
+
diff --git a/bioimagesuite30_src/igtlutil/igtl_transform.c b/bioimagesuite30_src/igtlutil/igtl_transform.c
new file mode 100644
index 0000000..172fce9
--- /dev/null
+++ b/bioimagesuite30_src/igtlutil/igtl_transform.c
@@ -0,0 +1,73 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Open ITK Link Library
+  Module:    $RCSfile: $
+  Language:  C
+  Date:      $Date: $
+  Version:   $Revision: $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#include <string.h>
+#include "igtl_transform.h"
+#include "igtl_util.h"
+//#include "crc32.h"
+
+#include <stdio.h>
+
+void igtl_transform_convert_byte_order(igtl_float32* transform)
+{
+  int i;
+  igtl_uint32* tmp = (igtl_uint32*) transform;
+
+  if (igtl_is_little_endian()) {
+    for (i = 0; i < 12; i ++) {
+      tmp[i] = BYTE_SWAP_INT32(tmp[i]);
+    }
+  }
+}
+
+
+igtl_uint64 igtl_transform_get_crc(igtl_float32* transform)
+{
+
+  igtl_uint64 crc = crc64(0, 0, 0);
+
+  crc = crc64((unsigned char*)transform, sizeof(igtl_uint64)*12, crc);
+
+  return crc;
+}
+
diff --git a/bioimagesuite30_src/igtlutil/igtl_transform.h b/bioimagesuite30_src/igtlutil/igtl_transform.h
new file mode 100644
index 0000000..ba5ca51
--- /dev/null
+++ b/bioimagesuite30_src/igtlutil/igtl_transform.h
@@ -0,0 +1,84 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Open ITK Link Library
+  Module:    $RCSfile: $
+  Language:  C
+  Date:      $Date: $
+  Version:   $Revision: $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#ifndef __IGTL_TRANSFORM_H
+#define __IGTL_TRANSFORM_H
+
+#include "igtl_util.h"
+
+#define IGTL_TRANSFORM_SIZE   48
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+typedef igtl_float32[12] transform;
+*/
+
+/*
+ * Byte order conversion for the header structure
+ *
+ * This function converts endianness of each member variable
+ * in igtl_image_header from host byte order to network byte order,
+ * or vice versa.
+ */
+
+void igtl_transform_convert_byte_order(igtl_float32* transform);
+
+
+/*
+ * CRC calculation
+ *
+ * This function calculates CRC of transform data.
+ *
+ */
+
+igtl_uint64 igtl_transform_get_crc(igtl_float32* transform);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*__IGTL_TRANSFORM_H*/
+
+
diff --git a/bioimagesuite30_src/igtlutil/igtl_types.h b/bioimagesuite30_src/igtlutil/igtl_types.h
new file mode 100644
index 0000000..f7424ad
--- /dev/null
+++ b/bioimagesuite30_src/igtlutil/igtl_types.h
@@ -0,0 +1,115 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Open IGT Link Library
+  Module:    $RCSfile: $
+  Language:  C
+  Date:      $Date: $
+  Version:   $Revision: $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#ifndef __IGTL_TYPES_H
+#define __IGTL_TYPES_H
+
+#include "vtkConfigure.h"
+
+/* 8-bit integer type */
+#if VTK_SIZEOF_CHAR == 1
+  typedef unsigned char igtl_uint8;
+  typedef char          igtl_int8;
+#else
+  # error "No native data type can represent an 8-bit integer."
+#endif
+
+/* 16-bit integer type */
+#if VTK_SIZEOF_SHORT == 2
+  typedef unsigned short igtl_uint16;
+  typedef signed short   igtl_int16;
+#elif VTK_SIZEOF_INT == 2
+  typedef unsigned int   igtl_uint16;
+  typedef signed int     igtl_int16;
+#else
+  # error "No native data type can represent a 16-bit integer."
+#endif
+
+/* 32-bit integer type */
+#if VTK_SIZEOF_INT == 4
+  typedef unsigned int   igtl_uint32;
+  typedef signed int     igtl_int32;
+#elif VTK_SIZEOF_LONG == 4
+  typedef unsigned long  igtl_uint32;
+  typedef signed long    igtl_int32;
+#else
+  # error "No native data type can represent a 32-bit integer."
+#endif
+
+/* 64-bit integer type */
+#if defined(VTK_TYPE_USE_LONG_LONG) && VTK_SIZEOF_LONG_LONG == 8
+  typedef unsigned long long igtl_uint64;
+  typedef signed long long   igtl_int64;
+#elif VTK_SIZEOF_INT == 8
+  typedef unsigned int       igtl_uint64;
+  typedef signed int         igtl_int64;
+#elif VTK_SIZEOF_LONG == 8
+  typedef unsigned long      igtl_uint64;
+  typedef signed long        igtl_64;
+#elif defined(VTK_TYPE_USE___INT64) && VTK_SIZEOF___INT64 == 8
+  typedef unsigned __int64   igtl_uint64;
+  typedef signed __int64     igtl_int64;
+#elif defined(VTK_TYPE_USE_INT64_T) && VTK_SIZEOF_INT64_T == 8
+  typedef unsigned int64_t   igtl_uint64;
+  typedef signed int64_t     igtl_int64;
+#else
+  # error "No native data type can represent a 64-bit integer."
+#endif
+
+/* 32-bit floating point type */
+#if VTK_SIZEOF_FLOAT == 4
+  typedef float              igtl_float32;
+#else
+# error "No native data type can represent a 32-bit floating point value."
+#endif
+
+/* 64-bit floating point type */
+#if VTK_SIZEOF_DOUBLE == 8
+  typedef double             igtl_float64;
+#else
+# error "No native data type can represent a 64-bit floating point value."
+#endif
+
+
+#endif /* __VTK_TYPES_H */
+
diff --git a/bioimagesuite30_src/igtlutil/igtl_util.c b/bioimagesuite30_src/igtlutil/igtl_util.c
new file mode 100644
index 0000000..a13ccaa
--- /dev/null
+++ b/bioimagesuite30_src/igtlutil/igtl_util.c
@@ -0,0 +1,195 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Open ITK Link Library
+  Module:    $RCSfile: $
+  Language:  C
+  Date:      $Date: $
+  Version:   $Revision: $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#include "igtl_util.h"
+
+int igtl_is_little_endian()
+{
+  short a = 1; 
+  return ((char*)&a)[0];
+}
+
+
+igtl_uint64 crc64(unsigned char *data, int len, igtl_uint64 crc)
+{
+
+    static const igtl_uint64 table[256] = {
+    0x0000000000000000ULL,0x42F0E1EBA9EA3693ULL,
+    0x85E1C3D753D46D26ULL,0xC711223CFA3E5BB5ULL,
+    0x493366450E42ECDFULL,0x0BC387AEA7A8DA4CULL,
+    0xCCD2A5925D9681F9ULL,0x8E224479F47CB76AULL,
+    0x9266CC8A1C85D9BEULL,0xD0962D61B56FEF2DULL,
+    0x17870F5D4F51B498ULL,0x5577EEB6E6BB820BULL,
+    0xDB55AACF12C73561ULL,0x99A54B24BB2D03F2ULL,
+    0x5EB4691841135847ULL,0x1C4488F3E8F96ED4ULL,
+    0x663D78FF90E185EFULL,0x24CD9914390BB37CULL,
+    0xE3DCBB28C335E8C9ULL,0xA12C5AC36ADFDE5AULL,
+    0x2F0E1EBA9EA36930ULL,0x6DFEFF5137495FA3ULL,
+    0xAAEFDD6DCD770416ULL,0xE81F3C86649D3285ULL,
+    0xF45BB4758C645C51ULL,0xB6AB559E258E6AC2ULL,
+    0x71BA77A2DFB03177ULL,0x334A9649765A07E4ULL,
+    0xBD68D2308226B08EULL,0xFF9833DB2BCC861DULL,
+    0x388911E7D1F2DDA8ULL,0x7A79F00C7818EB3BULL,
+    0xCC7AF1FF21C30BDEULL,0x8E8A101488293D4DULL,
+    0x499B3228721766F8ULL,0x0B6BD3C3DBFD506BULL,
+    0x854997BA2F81E701ULL,0xC7B97651866BD192ULL,
+    0x00A8546D7C558A27ULL,0x4258B586D5BFBCB4ULL,
+    0x5E1C3D753D46D260ULL,0x1CECDC9E94ACE4F3ULL,
+    0xDBFDFEA26E92BF46ULL,0x990D1F49C77889D5ULL,
+    0x172F5B3033043EBFULL,0x55DFBADB9AEE082CULL,
+    0x92CE98E760D05399ULL,0xD03E790CC93A650AULL,
+    0xAA478900B1228E31ULL,0xE8B768EB18C8B8A2ULL,
+    0x2FA64AD7E2F6E317ULL,0x6D56AB3C4B1CD584ULL,
+    0xE374EF45BF6062EEULL,0xA1840EAE168A547DULL,
+    0x66952C92ECB40FC8ULL,0x2465CD79455E395BULL,
+    0x3821458AADA7578FULL,0x7AD1A461044D611CULL,
+    0xBDC0865DFE733AA9ULL,0xFF3067B657990C3AULL,
+    0x711223CFA3E5BB50ULL,0x33E2C2240A0F8DC3ULL,
+    0xF4F3E018F031D676ULL,0xB60301F359DBE0E5ULL,
+    0xDA050215EA6C212FULL,0x98F5E3FE438617BCULL,
+    0x5FE4C1C2B9B84C09ULL,0x1D14202910527A9AULL,
+    0x93366450E42ECDF0ULL,0xD1C685BB4DC4FB63ULL,
+    0x16D7A787B7FAA0D6ULL,0x5427466C1E109645ULL,
+    0x4863CE9FF6E9F891ULL,0x0A932F745F03CE02ULL,
+    0xCD820D48A53D95B7ULL,0x8F72ECA30CD7A324ULL,
+    0x0150A8DAF8AB144EULL,0x43A04931514122DDULL,
+    0x84B16B0DAB7F7968ULL,0xC6418AE602954FFBULL,
+    0xBC387AEA7A8DA4C0ULL,0xFEC89B01D3679253ULL,
+    0x39D9B93D2959C9E6ULL,0x7B2958D680B3FF75ULL,
+    0xF50B1CAF74CF481FULL,0xB7FBFD44DD257E8CULL,
+    0x70EADF78271B2539ULL,0x321A3E938EF113AAULL,
+    0x2E5EB66066087D7EULL,0x6CAE578BCFE24BEDULL,
+    0xABBF75B735DC1058ULL,0xE94F945C9C3626CBULL,
+    0x676DD025684A91A1ULL,0x259D31CEC1A0A732ULL,
+    0xE28C13F23B9EFC87ULL,0xA07CF2199274CA14ULL,
+    0x167FF3EACBAF2AF1ULL,0x548F120162451C62ULL,
+    0x939E303D987B47D7ULL,0xD16ED1D631917144ULL,
+    0x5F4C95AFC5EDC62EULL,0x1DBC74446C07F0BDULL,
+    0xDAAD56789639AB08ULL,0x985DB7933FD39D9BULL,
+    0x84193F60D72AF34FULL,0xC6E9DE8B7EC0C5DCULL,
+    0x01F8FCB784FE9E69ULL,0x43081D5C2D14A8FAULL,
+    0xCD2A5925D9681F90ULL,0x8FDAB8CE70822903ULL,
+    0x48CB9AF28ABC72B6ULL,0x0A3B7B1923564425ULL,
+    0x70428B155B4EAF1EULL,0x32B26AFEF2A4998DULL,
+    0xF5A348C2089AC238ULL,0xB753A929A170F4ABULL,
+    0x3971ED50550C43C1ULL,0x7B810CBBFCE67552ULL,
+    0xBC902E8706D82EE7ULL,0xFE60CF6CAF321874ULL,
+    0xE224479F47CB76A0ULL,0xA0D4A674EE214033ULL,
+    0x67C58448141F1B86ULL,0x253565A3BDF52D15ULL,
+    0xAB1721DA49899A7FULL,0xE9E7C031E063ACECULL,
+    0x2EF6E20D1A5DF759ULL,0x6C0603E6B3B7C1CAULL,
+    0xF6FAE5C07D3274CDULL,0xB40A042BD4D8425EULL,
+    0x731B26172EE619EBULL,0x31EBC7FC870C2F78ULL,
+    0xBFC9838573709812ULL,0xFD39626EDA9AAE81ULL,
+    0x3A28405220A4F534ULL,0x78D8A1B9894EC3A7ULL,
+    0x649C294A61B7AD73ULL,0x266CC8A1C85D9BE0ULL,
+    0xE17DEA9D3263C055ULL,0xA38D0B769B89F6C6ULL,
+    0x2DAF4F0F6FF541ACULL,0x6F5FAEE4C61F773FULL,
+    0xA84E8CD83C212C8AULL,0xEABE6D3395CB1A19ULL,
+    0x90C79D3FEDD3F122ULL,0xD2377CD44439C7B1ULL,
+    0x15265EE8BE079C04ULL,0x57D6BF0317EDAA97ULL,
+    0xD9F4FB7AE3911DFDULL,0x9B041A914A7B2B6EULL,
+    0x5C1538ADB04570DBULL,0x1EE5D94619AF4648ULL,
+    0x02A151B5F156289CULL,0x4051B05E58BC1E0FULL,
+    0x87409262A28245BAULL,0xC5B073890B687329ULL,
+    0x4B9237F0FF14C443ULL,0x0962D61B56FEF2D0ULL,
+    0xCE73F427ACC0A965ULL,0x8C8315CC052A9FF6ULL,
+    0x3A80143F5CF17F13ULL,0x7870F5D4F51B4980ULL,
+    0xBF61D7E80F251235ULL,0xFD913603A6CF24A6ULL,
+    0x73B3727A52B393CCULL,0x31439391FB59A55FULL,
+    0xF652B1AD0167FEEAULL,0xB4A25046A88DC879ULL,
+    0xA8E6D8B54074A6ADULL,0xEA16395EE99E903EULL,
+    0x2D071B6213A0CB8BULL,0x6FF7FA89BA4AFD18ULL,
+    0xE1D5BEF04E364A72ULL,0xA3255F1BE7DC7CE1ULL,
+    0x64347D271DE22754ULL,0x26C49CCCB40811C7ULL,
+    0x5CBD6CC0CC10FAFCULL,0x1E4D8D2B65FACC6FULL,
+    0xD95CAF179FC497DAULL,0x9BAC4EFC362EA149ULL,
+    0x158E0A85C2521623ULL,0x577EEB6E6BB820B0ULL,
+    0x906FC95291867B05ULL,0xD29F28B9386C4D96ULL,
+    0xCEDBA04AD0952342ULL,0x8C2B41A1797F15D1ULL,
+    0x4B3A639D83414E64ULL,0x09CA82762AAB78F7ULL,
+    0x87E8C60FDED7CF9DULL,0xC51827E4773DF90EULL,
+    0x020905D88D03A2BBULL,0x40F9E43324E99428ULL,
+    0x2CFFE7D5975E55E2ULL,0x6E0F063E3EB46371ULL,
+    0xA91E2402C48A38C4ULL,0xEBEEC5E96D600E57ULL,
+    0x65CC8190991CB93DULL,0x273C607B30F68FAEULL,
+    0xE02D4247CAC8D41BULL,0xA2DDA3AC6322E288ULL,
+    0xBE992B5F8BDB8C5CULL,0xFC69CAB42231BACFULL,
+    0x3B78E888D80FE17AULL,0x7988096371E5D7E9ULL,
+    0xF7AA4D1A85996083ULL,0xB55AACF12C735610ULL,
+    0x724B8ECDD64D0DA5ULL,0x30BB6F267FA73B36ULL,
+    0x4AC29F2A07BFD00DULL,0x08327EC1AE55E69EULL,
+    0xCF235CFD546BBD2BULL,0x8DD3BD16FD818BB8ULL,
+    0x03F1F96F09FD3CD2ULL,0x41011884A0170A41ULL,
+    0x86103AB85A2951F4ULL,0xC4E0DB53F3C36767ULL,
+    0xD8A453A01B3A09B3ULL,0x9A54B24BB2D03F20ULL,
+    0x5D45907748EE6495ULL,0x1FB5719CE1045206ULL,
+    0x919735E51578E56CULL,0xD367D40EBC92D3FFULL,
+    0x1476F63246AC884AULL,0x568617D9EF46BED9ULL,
+    0xE085162AB69D5E3CULL,0xA275F7C11F7768AFULL,
+    0x6564D5FDE549331AULL,0x279434164CA30589ULL,
+    0xA9B6706FB8DFB2E3ULL,0xEB46918411358470ULL,
+    0x2C57B3B8EB0BDFC5ULL,0x6EA7525342E1E956ULL,
+    0x72E3DAA0AA188782ULL,0x30133B4B03F2B111ULL,
+    0xF7021977F9CCEAA4ULL,0xB5F2F89C5026DC37ULL,
+    0x3BD0BCE5A45A6B5DULL,0x79205D0E0DB05DCEULL,
+    0xBE317F32F78E067BULL,0xFCC19ED95E6430E8ULL,
+    0x86B86ED5267CDBD3ULL,0xC4488F3E8F96ED40ULL,
+    0x0359AD0275A8B6F5ULL,0x41A94CE9DC428066ULL,
+    0xCF8B0890283E370CULL,0x8D7BE97B81D4019FULL,
+    0x4A6ACB477BEA5A2AULL,0x089A2AACD2006CB9ULL,
+    0x14DEA25F3AF9026DULL,0x562E43B4931334FEULL,
+    0x913F6188692D6F4BULL,0xD3CF8063C0C759D8ULL,
+    0x5DEDC41A34BBEEB2ULL,0x1F1D25F19D51D821ULL,
+    0xD80C07CD676F8394ULL,0x9AFCE626CE85B507ULL,
+    };
+  
+    while (len > 0)
+    {
+        crc = table[*data ^ (unsigned char)(crc >> 56)] ^ (crc << 8);
+        data++;
+        len--;
+    }
+    return crc;
+}
+
diff --git a/bioimagesuite30_src/igtlutil/igtl_util.h b/bioimagesuite30_src/igtlutil/igtl_util.h
new file mode 100644
index 0000000..df182d9
--- /dev/null
+++ b/bioimagesuite30_src/igtlutil/igtl_util.h
@@ -0,0 +1,77 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   Open ITK Link Library
+  Module:    $RCSfile: $
+  Language:  C
+  Date:      $Date: $
+  Version:   $Revision: $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+
+  This software is distributed WITHOUT ANY WARRANTY; without even
+  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+  PURPOSE.  See the above copyright notices for more information.
+
+=========================================================================*/
+
+#ifndef __IGTL_UTIL_H
+#define __IGTL_UTIL_H
+
+#include "igtl_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Byte order conversion macros
+ *
+ */
+
+#define BYTE_SWAP_INT16(S) (((S) & 0xFF) << 8 \
+                            | (((S) >> 8) & 0xFF))
+#define BYTE_SWAP_INT32(L) ((BYTE_SWAP_INT16 ((L) & 0xFFFF) << 16) \
+                            | BYTE_SWAP_INT16 (((L) >> 16) & 0xFFFF))
+#define BYTE_SWAP_INT64(LL) ((BYTE_SWAP_INT32 ((LL) & 0xFFFFFFFF) << 32) \
+                             | BYTE_SWAP_INT32 (((LL) >> 32) & 0xFFFFFFFF))
+
+/*
+ * Test endian of the host
+ */
+int igtl_is_little_endian();
+igtl_uint64 crc64(unsigned char *data, int len, igtl_uint64 crc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /*__IGTL_UTIL_H*/
+
+
diff --git a/bioimagesuite30_src/include/CMakeLists.txt b/bioimagesuite30_src/include/CMakeLists.txt
new file mode 100644
index 0000000..c2bf43d
--- /dev/null
+++ b/bioimagesuite30_src/include/CMakeLists.txt
@@ -0,0 +1,60 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+SET(KIT include)
+
+SET(KITLIBS )
+
+SET (KITSRCS 
+vtkbisConfigure.h.in
+clapack.h
+bio_f2c.h                 
+pxisinf.h                
+nifti1.h
+nifti1_io.h
+bis_znzlib.h
+)
+
+SET (KITTCLSRCS )
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+
+# Expects KITSRCS and KITLIBS defined
+#bis_static(${KIT})
+# Expects KITSRCS KITTCLSRCS KITLIBS defined
+#bis_tcl(${KIT})
+# Expects KITSRCS KITTCLSRCS and 
+bis_sourcelist("include" ${KIT} ${FILELIST})
+
diff --git a/bioimagesuite30_src/include/bio_f2c.h b/bioimagesuite30_src/include/bio_f2c.h
new file mode 100644
index 0000000..e35e8c5
--- /dev/null
+++ b/bioimagesuite30_src/include/bio_f2c.h
@@ -0,0 +1,420 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/* f2c.h  --  Standard Fortran to C header file */
+
+/**  barf  [ba:rf]  2.  "He suggested using FORTRAN, and everybody barfed."
+
+	- From The Shogakukan DICTIONARY OF NEW ENGLISH (Second edition) */
+
+
+#ifndef F2C_INCLUDE
+#define F2C_INCLUDE
+
+typedef long int integer;
+typedef unsigned long int uinteger;
+typedef char *address;
+typedef short int shortint;
+typedef float real;
+typedef double doublereal;
+typedef struct { real r, i; } complex;
+typedef struct { doublereal r, i; } doublecomplex;
+typedef long int logical;
+typedef short int shortlogical;
+typedef char logical1;
+typedef char integer1;
+#ifdef INTEGER_STAR_8	/* Adjust for integer*8. */
+typedef long long longint;		/* system-dependent */
+typedef unsigned long long ulongint;	/* system-dependent */
+#define qbit_clear(a,b)	((a) & ~((ulongint)1 << (b)))
+#define qbit_set(a,b)	((a) |  ((ulongint)1 << (b)))
+#endif
+
+#define TRUE_ (1)
+#define FALSE_ (0)
+
+/* Extern is for use with -E */
+#ifndef Extern
+#define Extern extern
+#endif
+
+/* I/O stuff */
+
+#ifdef f2c_i2
+/* for -i2 */
+typedef short flag;
+typedef short ftnlen;
+typedef short ftnint;
+#else
+typedef long int flag;
+typedef long int ftnlen;
+typedef long int ftnint;
+#endif
+
+/*external read, write*/
+typedef struct
+{	flag cierr;
+	ftnint ciunit;
+	flag ciend;
+	char *cifmt;
+	ftnint cirec;
+} cilist;
+
+/*internal read, write*/
+typedef struct
+{	flag icierr;
+	char *iciunit;
+	flag iciend;
+	char *icifmt;
+	ftnint icirlen;
+	ftnint icirnum;
+} icilist;
+
+/*open*/
+typedef struct
+{	flag oerr;
+	ftnint ounit;
+	char *ofnm;
+	ftnlen ofnmlen;
+	char *osta;
+	char *oacc;
+	char *ofm;
+	ftnint orl;
+	char *oblnk;
+} olist;
+
+/*close*/
+typedef struct
+{	flag cerr;
+	ftnint cunit;
+	char *csta;
+} cllist;
+
+/*rewind, backspace, endfile*/
+typedef struct
+{	flag aerr;
+	ftnint aunit;
+} alist;
+
+/* inquire */
+typedef struct
+{	flag inerr;
+	ftnint inunit;
+	char *infile;
+	ftnlen infilen;
+	ftnint	*inex;	/*parameters in standard's order*/
+	ftnint	*inopen;
+	ftnint	*innum;
+	ftnint	*innamed;
+	char	*inname;
+	ftnlen	innamlen;
+	char	*inacc;
+	ftnlen	inacclen;
+	char	*inseq;
+	ftnlen	inseqlen;
+	char 	*indir;
+	ftnlen	indirlen;
+	char	*infmt;
+	ftnlen	infmtlen;
+	char	*inform;
+	ftnint	informlen;
+	char	*inunf;
+	ftnlen	inunflen;
+	ftnint	*inrecl;
+	ftnint	*innrec;
+	char	*inblank;
+	ftnlen	inblanklen;
+} inlist;
+
+#define VOID void
+
+union Multitype {	/* for multiple entry points */
+	integer1 g;
+	shortint h;
+	integer i;
+	/* longint j; */
+	real r;
+	doublereal d;
+	complex c;
+	doublecomplex z;
+	};
+
+typedef union Multitype Multitype;
+
+/*typedef long int Long;*/	/* No longer used; formerly in Namelist */
+
+struct Vardesc {	/* for Namelist */
+	char *name;
+	char *addr;
+	ftnlen *dims;
+	int  type;
+	};
+typedef struct Vardesc Vardesc;
+
+struct Namelist {
+	char *name;
+	Vardesc **vars;
+	int nvars;
+	};
+typedef struct Namelist Namelist;
+
+#define f2cabs(x) ((x) >= 0 ? (x) : -(x))
+#define dabs(x) (doublereal)f2cabs(x)
+
+
+#define f2cmin(a,b) ((a) <= (b) ? (a) : (b))
+#define f2cmax(a,b) ((a) >= (b) ? (a) : (b))
+#define dmin(a,b) (doublereal)f2cmin(a,b)
+#define dmax(a,b) (doublereal)f2cmax(a,b)
+
+#define bit_test(a,b)	((a) >> (b) & 1)
+#define bit_clear(a,b)	((a) & ~((uinteger)1 << (b)))
+#define bit_set(a,b)	((a) |  ((uinteger)1 << (b)))
+
+/* procedure parameter types for -A and -C++ */
+
+#define F2C_proc_par_types 1
+#ifdef __cplusplus
+typedef int /* Unknown procedure type */ (*U_fp)(...);
+typedef shortint (*J_fp)(...);
+typedef integer (*I_fp)(...);
+typedef real (*R_fp)(...);
+typedef doublereal (*D_fp)(...), (*E_fp)(...);
+typedef /* Complex */ VOID (*C_fp)(...);
+typedef /* Double Complex */ VOID (*Z_fp)(...);
+typedef logical (*L_fp)(...);
+typedef shortlogical (*K_fp)(...);
+typedef /* Character */ VOID (*H_fp)(...);
+typedef /* Subroutine */ int (*S_fp)(...);
+#else
+typedef int /* Unknown procedure type */ (*U_fp)();
+typedef shortint (*J_fp)();
+typedef integer (*I_fp)();
+typedef real (*R_fp)();
+typedef doublereal (*D_fp)(), (*E_fp)();
+typedef /* Complex */ VOID (*C_fp)();
+typedef /* Double Complex */ VOID (*Z_fp)();
+typedef logical (*L_fp)();
+typedef shortlogical (*K_fp)();
+typedef /* Character */ VOID (*H_fp)();
+typedef /* Subroutine */ int (*S_fp)();
+#endif
+/* E_fp is for real functions when -R is not specified */
+typedef VOID C_f;	/* complex function */
+typedef VOID H_f;	/* character function */
+typedef VOID Z_f;	/* double complex function */
+typedef doublereal E_f;	/* real function with -R not specified */
+
+/* undef any lower-case symbols that your C compiler predefines, e.g.: */
+
+#ifndef Skip_f2c_Undefs
+#undef cray
+#undef gcos
+#undef mc68010
+#undef mc68020
+#undef mips
+#undef pdp11
+#undef sgi
+#undef sparc
+#undef sun
+#undef sun2
+#undef sun3
+#undef sun4
+#undef u370
+#undef u3b
+#undef u3b2
+#undef u3b5
+#undef unix
+#undef vax
+#endif
+#endif
+/* If you are using a C++ compiler, append the following to f2c.h
+   for compiling libF77 and libI77. */
+
+#ifdef __cplusplus
+extern "C" {
+extern int abort_(void);
+  //extern double c_abs(complex *);
+extern void c_cos(complex *, complex *);
+extern void c_div(complex *, complex *, complex *);
+extern void c_exp(complex *, complex *);
+extern void c_log(complex *, complex *);
+extern void c_sin(complex *, complex *);
+extern void c_sqrt(complex *, complex *);
+extern double d_abs(double *);
+extern double d_acos(double *);
+extern double d_asin(double *);
+extern double d_atan(double *);
+extern double d_atn2(double *, double *);
+extern void d_cnjg(doublecomplex *, doublecomplex *);
+extern double d_cos(double *);
+extern double d_cosh(double *);
+extern double d_dim(double *, double *);
+extern double d_exp(double *);
+extern double d_imag(doublecomplex *);
+extern double d_int(double *);
+extern double d_lg10(double *);
+extern double d_log(double *);
+extern double d_mod(double *, double *);
+extern double d_nint(double *);
+extern double d_prod(float *, float *);
+extern double d_sign(double *, double *);
+extern double d_sin(double *);
+extern double d_sinh(double *);
+extern double d_sqrt(double *);
+extern double d_tan(double *);
+extern double d_tanh(double *);
+extern double derf_(double *);
+extern double derfc_(double *);
+extern integer do_fio(ftnint *, char *, ftnlen);
+extern integer do_lio(ftnint *, ftnint *, char *, ftnlen);
+extern integer do_uio(ftnint *, char *, ftnlen);
+extern integer e_rdfe(void);
+extern integer e_rdue(void);
+extern integer e_rsfe(void);
+extern integer e_rsfi(void);
+extern integer e_rsle(void);
+extern integer e_rsli(void);
+extern integer e_rsue(void);
+extern integer e_wdfe(void);
+extern integer e_wdue(void);
+extern integer e_wsfe(void);
+extern integer e_wsfi(void);
+extern integer e_wsle(void);
+extern integer e_wsli(void);
+extern integer e_wsue(void);
+extern int ef1asc_(ftnint *, ftnlen *, ftnint *, ftnlen *);
+extern integer ef1cmc_(ftnint *, ftnlen *, ftnint *, ftnlen *);
+  //extern double erf(double);
+extern double erf_(float *);
+  //extern double erfc(double);
+extern double erfc_(float *);
+extern integer f_back(alist *);
+extern integer f_clos(cllist *);
+extern integer f_end(alist *);
+extern void f_exit(void);
+extern integer f_inqu(inlist *);
+extern integer f_open(olist *);
+extern integer f_rew(alist *);
+extern int flush_(void);
+extern void getarg_(integer *, char *, ftnlen);
+extern void getenv_(char *, char *, ftnlen, ftnlen);
+extern short h_abs(short *);
+extern short h_dim(short *, short *);
+extern short h_dnnt(double *);
+extern short h_indx(char *, char *, ftnlen, ftnlen);
+extern short h_len(char *, ftnlen);
+extern short h_mod(short *, short *);
+extern short h_nint(float *);
+extern short h_sign(short *, short *);
+extern short hl_ge(char *, char *, ftnlen, ftnlen);
+extern short hl_gt(char *, char *, ftnlen, ftnlen);
+extern short hl_le(char *, char *, ftnlen, ftnlen);
+extern short hl_lt(char *, char *, ftnlen, ftnlen);
+extern integer i_abs(integer *);
+extern integer i_dim(integer *, integer *);
+extern integer i_dnnt(double *);
+extern integer i_indx(char *, char *, ftnlen, ftnlen);
+extern integer i_len(char *, ftnlen);
+extern integer i_mod(integer *, integer *);
+extern integer i_nint(float *);
+extern integer i_sign(integer *, integer *);
+extern integer iargc_(void);
+extern ftnlen l_ge(char *, char *, ftnlen, ftnlen);
+extern ftnlen l_gt(char *, char *, ftnlen, ftnlen);
+extern ftnlen l_le(char *, char *, ftnlen, ftnlen);
+extern ftnlen l_lt(char *, char *, ftnlen, ftnlen);
+extern void pow_ci(complex *, complex *, integer *);
+extern double pow_dd(double *, double *);
+extern double pow_di(double *, integer *);
+extern short pow_hh(short *, shortint *);
+extern integer pow_ii(integer *, integer *);
+extern double pow_ri(float *, integer *);
+extern void pow_zi(doublecomplex *, doublecomplex *, integer *);
+extern void pow_zz(doublecomplex *, doublecomplex *, doublecomplex *);
+extern double r_abs(float *);
+extern double r_acos(float *);
+extern double r_asin(float *);
+extern double r_atan(float *);
+extern double r_atn2(float *, float *);
+extern void r_cnjg(complex *, complex *);
+extern double r_cos(float *);
+extern double r_cosh(float *);
+extern double r_dim(float *, float *);
+extern double r_exp(float *);
+extern double r_imag(complex *);
+extern double r_int(float *);
+extern double r_lg10(float *);
+extern double r_log(float *);
+extern double r_mod(float *, float *);
+extern double r_nint(float *);
+extern double r_sign(float *, float *);
+extern double r_sin(float *);
+extern double r_sinh(float *);
+extern double r_sqrt(float *);
+extern double r_tan(float *);
+extern double r_tanh(float *);
+extern void s_cat(char *, char **, integer *, integer *, ftnlen);
+extern integer s_cmp(char *, char *, ftnlen, ftnlen);
+extern void s_copy(char *, char *, ftnlen, ftnlen);
+extern int s_paus(char *, ftnlen);
+extern integer s_rdfe(cilist *);
+extern integer s_rdue(cilist *);
+extern integer s_rnge(char *, integer, char *, integer);
+extern integer s_rsfe(cilist *);
+extern integer s_rsfi(icilist *);
+extern integer s_rsle(cilist *);
+extern integer s_rsli(icilist *);
+extern integer s_rsne(cilist *);
+extern integer s_rsni(icilist *);
+extern integer s_rsue(cilist *);
+extern int s_stop(char *, ftnlen);
+extern integer s_wdfe(cilist *);
+extern integer s_wdue(cilist *);
+extern integer s_wsfe(cilist *);
+extern integer s_wsfi(icilist *);
+extern integer s_wsle(cilist *);
+extern integer s_wsli(icilist *);
+extern integer s_wsne(cilist *);
+extern integer s_wsni(icilist *);
+extern integer s_wsue(cilist *);
+extern void sig_die(char *, int);
+extern integer signal_(integer *, void (*)(int));
+extern integer system_(char *, ftnlen);
+extern double z_abs(doublecomplex *);
+extern void z_cos(doublecomplex *, doublecomplex *);
+extern void z_div(doublecomplex *, doublecomplex *, doublecomplex *);
+extern void z_exp(doublecomplex *, doublecomplex *);
+extern void z_log(doublecomplex *, doublecomplex *);
+extern void z_sin(doublecomplex *, doublecomplex *);
+extern void z_sqrt(doublecomplex *, doublecomplex *);
+       
+}
+
+
+#endif
+
diff --git a/bioimagesuite30_src/include/bis_znzlib.h b/bioimagesuite30_src/include/bis_znzlib.h
new file mode 100644
index 0000000..3d315a3
--- /dev/null
+++ b/bioimagesuite30_src/include/bis_znzlib.h
@@ -0,0 +1,137 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef _ZNZLIB_H_
+#define _ZNZLIB_H_
+
+/*
+znzlib.h  (zipped or non-zipped library)
+
+*****            This code is released to the public domain.            *****
+
+*****  Author: Mark Jenkinson, FMRIB Centre, University of Oxford       *****
+*****  Date:   September 2004                                           *****
+
+*****  Neither the FMRIB Centre, the University of Oxford, nor any of   *****
+*****  its employees imply any warranty of usefulness of this software  *****
+*****  for any purpose, and do not assume any liability for damages,    *****
+*****  incidental or otherwise, caused by any use of this document.     *****
+
+*/
+
+/*
+
+This library provides an interface to both compressed (gzip/zlib) and
+uncompressed (normal) file IO.  The functions are written to have the
+same interface as the standard file IO functions.  
+
+To use this library instead of normal file IO, the following changes
+are required:
+ - replace all instances of FILE* with znzFile
+ - change the name of all function calls, replacing the initial character
+   f with the znz  (e.g. fseek becomes znzseek)
+ - add a third parameter to all calls to znzopen (previously fopen)
+   that specifies whether to use compression (1) or not (0)
+ - use znz_isnull rather than any (pointer == NULL) comparisons in the code
+ 
+NB: seeks for writable files with compression are quite restricted
+
+*/
+
+
+/*=================*/
+#ifdef  __cplusplus
+extern "C" {
+#endif
+/*=================*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+  /* Hack Xenios Papademetris for BioImage Suite (where ZLIB Exists) */
+  /* Eliminated testing for zlib etc. */
+#include <vtk_zlib.h>
+  /* End of Hack */
+
+struct znzptr {
+  int withz;
+  FILE* nzfptr;
+  gzFile zfptr;
+} ;
+
+/* the type for all file pointers */
+typedef struct znzptr * znzFile;
+
+
+/* int znz_isnull(znzFile f); */
+/* int znzclose(znzFile f); */
+#define znz_isnull(f) ((f) == NULL)
+#define znzclose(f)   Xznzclose(&(f))
+
+/* Note extra argument (use_compression) where 
+   use_compression==0 is no compression
+   use_compression!=0 uses zlib (gzip) compression
+*/
+
+znzFile znzopen(const char *path, const char *mode, int use_compression);
+
+znzFile znzdopen(int fd, const char *mode, int use_compression);
+
+int Xznzclose(znzFile * file);
+
+size_t znzread(void* buf, size_t size, size_t nmemb, znzFile file);
+
+size_t znzwrite(const void* buf, size_t size, size_t nmemb, znzFile file);
+
+long znzseek(znzFile file, long offset, int whence);
+
+int znzrewind(znzFile stream);
+
+long znztell(znzFile file);
+
+int znzputs(const char *str, znzFile file);
+
+char * znzgets(char* str, int size, znzFile file);
+
+int znzputc(int c, znzFile file);
+
+int znzgetc(znzFile file);
+
+#if !defined(WIN32)
+int znzprintf(znzFile stream, const char *format, ...);
+#endif
+
+/*=================*/
+#ifdef  __cplusplus
+}
+#endif
+/*=================*/
+
+#endif
+
diff --git a/bioimagesuite30_src/include/clapack.h b/bioimagesuite30_src/include/clapack.h
new file mode 100644
index 0000000..a683832
--- /dev/null
+++ b/bioimagesuite30_src/include/clapack.h
@@ -0,0 +1,5118 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef __CLAPACK_H
+#define __CLAPACK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ 
+/* Subroutine */ int cbdsqr_(char *uplo, integer *n, integer *ncvt, integer *
+	nru, integer *ncc, real *d__, real *e, complex *vt, integer *ldvt, 
+	complex *u, integer *ldu, complex *c__, integer *ldc, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int cgbbrd_(char *vect, integer *m, integer *n, integer *ncc,
+	 integer *kl, integer *ku, complex *ab, integer *ldab, real *d__, 
+	real *e, complex *q, integer *ldq, complex *pt, integer *ldpt, 
+	complex *c__, integer *ldc, complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cgbcon_(char *norm, integer *n, integer *kl, integer *ku,
+	 complex *ab, integer *ldab, integer *ipiv, real *anorm, real *rcond, 
+	complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cgbequ_(integer *m, integer *n, integer *kl, integer *ku,
+	 complex *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real 
+	*colcnd, real *amax, integer *info);
+ 
+/* Subroutine */ int cgbrfs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, complex *ab, integer *ldab, complex *afb, integer *
+	ldafb, integer *ipiv, complex *b, integer *ldb, complex *x, integer *
+	ldx, real *ferr, real *berr, complex *work, real *rwork, integer *
+	info);
+ 
+/* Subroutine */ int cgbsv_(integer *n, integer *kl, integer *ku, integer *
+	nrhs, complex *ab, integer *ldab, integer *ipiv, complex *b, integer *
+	ldb, integer *info);
+ 
+/* Subroutine */ int cgbsvx_(char *fact, char *trans, integer *n, integer *kl,
+	 integer *ku, integer *nrhs, complex *ab, integer *ldab, complex *afb,
+	 integer *ldafb, integer *ipiv, char *equed, real *r__, real *c__, 
+	complex *b, integer *ldb, complex *x, integer *ldx, real *rcond, real 
+	*ferr, real *berr, complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cgbtf2_(integer *m, integer *n, integer *kl, integer *ku,
+	 complex *ab, integer *ldab, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int cgbtrf_(integer *m, integer *n, integer *kl, integer *ku,
+	 complex *ab, integer *ldab, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int cgbtrs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, complex *ab, integer *ldab, integer *ipiv, complex 
+	*b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int cgebak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, real *scale, integer *m, complex *v, integer *ldv, 
+	integer *info);
+ 
+/* Subroutine */ int cgebal_(char *job, integer *n, complex *a, integer *lda, 
+	integer *ilo, integer *ihi, real *scale, integer *info);
+ 
+/* Subroutine */ int cgebd2_(integer *m, integer *n, complex *a, integer *lda,
+	 real *d__, real *e, complex *tauq, complex *taup, complex *work, 
+	integer *info);
+ 
+/* Subroutine */ int cgebrd_(integer *m, integer *n, complex *a, integer *lda,
+	 real *d__, real *e, complex *tauq, complex *taup, complex *work, 
+	integer *lwork, integer *info);
+ 
+/* Subroutine */ int cgecon_(char *norm, integer *n, complex *a, integer *lda,
+	 real *anorm, real *rcond, complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cgeequ_(integer *m, integer *n, complex *a, integer *lda,
+	 real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, 
+	integer *info);
+ 
+/* Subroutine */ int cgees_(char *jobvs, char *sort, L_fp select, integer *n, 
+	complex *a, integer *lda, integer *sdim, complex *w, complex *vs, 
+	integer *ldvs, complex *work, integer *lwork, real *rwork, logical *
+	bwork, integer *info);
+ 
+/* Subroutine */ int cgeesx_(char *jobvs, char *sort, L_fp select, char *
+	sense, integer *n, complex *a, integer *lda, integer *sdim, complex *
+	w, complex *vs, integer *ldvs, real *rconde, real *rcondv, complex *
+	work, integer *lwork, real *rwork, logical *bwork, integer *info);
+ 
+/* Subroutine */ int cgeev_(char *jobvl, char *jobvr, integer *n, complex *a, 
+	integer *lda, complex *w, complex *vl, integer *ldvl, complex *vr, 
+	integer *ldvr, complex *work, integer *lwork, real *rwork, integer *
+	info);
+ 
+/* Subroutine */ int cgeevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, complex *a, integer *lda, complex *w, complex *vl, 
+	integer *ldvl, complex *vr, integer *ldvr, integer *ilo, integer *ihi,
+	 real *scale, real *abnrm, real *rconde, real *rcondv, complex *work, 
+	integer *lwork, real *rwork, integer *info);
+ 
+/* Subroutine */ int cgegs_(char *jobvsl, char *jobvsr, integer *n, complex *
+	a, integer *lda, complex *b, integer *ldb, complex *alpha, complex *
+	beta, complex *vsl, integer *ldvsl, complex *vsr, integer *ldvsr, 
+	complex *work, integer *lwork, real *rwork, integer *info);
+ 
+/* Subroutine */ int cgegv_(char *jobvl, char *jobvr, integer *n, complex *a, 
+	integer *lda, complex *b, integer *ldb, complex *alpha, complex *beta,
+	 complex *vl, integer *ldvl, complex *vr, integer *ldvr, complex *
+	work, integer *lwork, real *rwork, integer *info);
+ 
+/* Subroutine */ int cgehd2_(integer *n, integer *ilo, integer *ihi, complex *
+	a, integer *lda, complex *tau, complex *work, integer *info);
+ 
+/* Subroutine */ int cgehrd_(integer *n, integer *ilo, integer *ihi, complex *
+	a, integer *lda, complex *tau, complex *work, integer *lwork, integer 
+	*info);
+ 
+/* Subroutine */ int cgelq2_(integer *m, integer *n, complex *a, integer *lda,
+	 complex *tau, complex *work, integer *info);
+ 
+/* Subroutine */ int cgelqf_(integer *m, integer *n, complex *a, integer *lda,
+	 complex *tau, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cgels_(char *trans, integer *m, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *b, integer *ldb, complex *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cgelsx_(integer *m, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *b, integer *ldb, integer *jpvt, real *rcond,
+	 integer *rank, complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cgelsy_(integer *m, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *b, integer *ldb, integer *jpvt, real *rcond,
+	 integer *rank, complex *work, integer *lwork, real *rwork, integer *
+	info);
+ 
+/* Subroutine */ int cgeql2_(integer *m, integer *n, complex *a, integer *lda,
+	 complex *tau, complex *work, integer *info);
+ 
+/* Subroutine */ int cgeqlf_(integer *m, integer *n, complex *a, integer *lda,
+	 complex *tau, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cgeqp3_(integer *m, integer *n, complex *a, integer *lda,
+	 integer *jpvt, complex *tau, complex *work, integer *lwork, real *
+	rwork, integer *info);
+ 
+/* Subroutine */ int cgeqpf_(integer *m, integer *n, complex *a, integer *lda,
+	 integer *jpvt, complex *tau, complex *work, real *rwork, integer *
+	info);
+ 
+/* Subroutine */ int cgeqr2_(integer *m, integer *n, complex *a, integer *lda,
+	 complex *tau, complex *work, integer *info);
+ 
+/* Subroutine */ int cgeqrf_(integer *m, integer *n, complex *a, integer *lda,
+	 complex *tau, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cgerfs_(char *trans, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *af, integer *ldaf, integer *ipiv, complex *
+	b, integer *ldb, complex *x, integer *ldx, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cgerq2_(integer *m, integer *n, complex *a, integer *lda,
+	 complex *tau, complex *work, integer *info);
+ 
+/* Subroutine */ int cgerqf_(integer *m, integer *n, complex *a, integer *lda,
+	 complex *tau, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cgesc2_(integer *n, complex *a, integer *lda, complex *
+	rhs, integer *ipiv, integer *jpiv, real *scale);
+ 
+/* Subroutine */ int cgesv_(integer *n, integer *nrhs, complex *a, integer *
+	lda, integer *ipiv, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int cgesvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+	ipiv, char *equed, real *r__, real *c__, complex *b, integer *ldb, 
+	complex *x, integer *ldx, real *rcond, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cgetc2_(integer *n, complex *a, integer *lda, integer *
+	ipiv, integer *jpiv, integer *info);
+ 
+/* Subroutine */ int cgetf2_(integer *m, integer *n, complex *a, integer *lda,
+	 integer *ipiv, integer *info);
+ 
+/* Subroutine */ int cgetrf_(integer *m, integer *n, complex *a, integer *lda,
+	 integer *ipiv, integer *info);
+ 
+/* Subroutine */ int cgetri_(integer *n, complex *a, integer *lda, integer *
+	ipiv, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cgetrs_(char *trans, integer *n, integer *nrhs, complex *
+	a, integer *lda, integer *ipiv, complex *b, integer *ldb, integer *
+	info);
+ 
+/* Subroutine */ int cggbak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, real *lscale, real *rscale, integer *m, complex *v, 
+	integer *ldv, integer *info);
+ 
+/* Subroutine */ int cggbal_(char *job, integer *n, complex *a, integer *lda, 
+	complex *b, integer *ldb, integer *ilo, integer *ihi, real *lscale, 
+	real *rscale, real *work, integer *info);
+ 
+/* Subroutine */ int cgges_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	selctg, integer *n, complex *a, integer *lda, complex *b, integer *
+	ldb, integer *sdim, complex *alpha, complex *beta, complex *vsl, 
+	integer *ldvsl, complex *vsr, integer *ldvsr, complex *work, integer *
+	lwork, real *rwork, logical *bwork, integer *info);
+ 
+/* Subroutine */ int cggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	selctg, char *sense, integer *n, complex *a, integer *lda, complex *b,
+	 integer *ldb, integer *sdim, complex *alpha, complex *beta, complex *
+	vsl, integer *ldvsl, complex *vsr, integer *ldvsr, real *rconde, real 
+	*rcondv, complex *work, integer *lwork, real *rwork, integer *iwork, 
+	integer *liwork, logical *bwork, integer *info);
+ 
+/* Subroutine */ int cggev_(char *jobvl, char *jobvr, integer *n, complex *a, 
+	integer *lda, complex *b, integer *ldb, complex *alpha, complex *beta,
+	 complex *vl, integer *ldvl, complex *vr, integer *ldvr, complex *
+	work, integer *lwork, real *rwork, integer *info);
+ 
+/* Subroutine */ int cggevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, complex *a, integer *lda, complex *b, integer *ldb,
+	 complex *alpha, complex *beta, complex *vl, integer *ldvl, complex *
+	vr, integer *ldvr, integer *ilo, integer *ihi, real *lscale, real *
+	rscale, real *abnrm, real *bbnrm, real *rconde, real *rcondv, complex 
+	*work, integer *lwork, real *rwork, integer *iwork, logical *bwork, 
+	integer *info);
+ 
+/* Subroutine */ int cggglm_(integer *n, integer *m, integer *p, complex *a, 
+	integer *lda, complex *b, integer *ldb, complex *d__, complex *x, 
+	complex *y, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cgghrd_(char *compq, char *compz, integer *n, integer *
+	ilo, integer *ihi, complex *a, integer *lda, complex *b, integer *ldb,
+	 complex *q, integer *ldq, complex *z__, integer *ldz, integer *info);
+ 
+/* Subroutine */ int cgglse_(integer *m, integer *n, integer *p, complex *a, 
+	integer *lda, complex *b, integer *ldb, complex *c__, complex *d__, 
+	complex *x, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cggqrf_(integer *n, integer *m, integer *p, complex *a, 
+	integer *lda, complex *taua, complex *b, integer *ldb, complex *taub, 
+	complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cggrqf_(integer *m, integer *p, integer *n, complex *a, 
+	integer *lda, complex *taua, complex *b, integer *ldb, complex *taub, 
+	complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cggsvd_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *n, integer *p, integer *k, integer *l, complex *a, integer *
+	lda, complex *b, integer *ldb, real *alpha, real *beta, complex *u, 
+	integer *ldu, complex *v, integer *ldv, complex *q, integer *ldq, 
+	complex *work, real *rwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int cggsvp_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, complex *a, integer *lda, complex *b, integer 
+	*ldb, real *tola, real *tolb, integer *k, integer *l, complex *u, 
+	integer *ldu, complex *v, integer *ldv, complex *q, integer *ldq, 
+	integer *iwork, real *rwork, complex *tau, complex *work, integer *
+	info);
+ 
+/* Subroutine */ int cgtcon_(char *norm, integer *n, complex *dl, complex *
+	d__, complex *du, complex *du2, integer *ipiv, real *anorm, real *
+	rcond, complex *work, integer *info);
+ 
+/* Subroutine */ int cgtrfs_(char *trans, integer *n, integer *nrhs, complex *
+	dl, complex *d__, complex *du, complex *dlf, complex *df, complex *
+	duf, complex *du2, integer *ipiv, complex *b, integer *ldb, complex *
+	x, integer *ldx, real *ferr, real *berr, complex *work, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int cgtsv_(integer *n, integer *nrhs, complex *dl, complex *
+	d__, complex *du, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int cgtsvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, complex *dl, complex *d__, complex *du, complex *dlf, complex *
+	df, complex *duf, complex *du2, integer *ipiv, complex *b, integer *
+	ldb, complex *x, integer *ldx, real *rcond, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cgttrf_(integer *n, complex *dl, complex *d__, complex *
+	du, complex *du2, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int cgttrs_(char *trans, integer *n, integer *nrhs, complex *
+	dl, complex *d__, complex *du, complex *du2, integer *ipiv, complex *
+	b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int cgtts2_(integer *itrans, integer *n, integer *nrhs, 
+	complex *dl, complex *d__, complex *du, complex *du2, integer *ipiv, 
+	complex *b, integer *ldb);
+ 
+/* Subroutine */ int chbev_(char *jobz, char *uplo, integer *n, integer *kd, 
+	complex *ab, integer *ldab, real *w, complex *z__, integer *ldz, 
+	complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int chbevd_(char *jobz, char *uplo, integer *n, integer *kd, 
+	complex *ab, integer *ldab, real *w, complex *z__, integer *ldz, 
+	complex *work, integer *lwork, real *rwork, integer *lrwork, integer *
+	iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int chbevx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *kd, complex *ab, integer *ldab, complex *q, integer *ldq, 
+	real *vl, real *vu, integer *il, integer *iu, real *abstol, integer *
+	m, real *w, complex *z__, integer *ldz, complex *work, real *rwork, 
+	integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int chbgst_(char *vect, char *uplo, integer *n, integer *ka, 
+	integer *kb, complex *ab, integer *ldab, complex *bb, integer *ldbb, 
+	complex *x, integer *ldx, complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int chbgv_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, complex *ab, integer *ldab, complex *bb, integer *ldbb, 
+	real *w, complex *z__, integer *ldz, complex *work, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int chbgvx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *ka, integer *kb, complex *ab, integer *ldab, complex *bb, 
+	integer *ldbb, complex *q, integer *ldq, real *vl, real *vu, integer *
+	il, integer *iu, real *abstol, integer *m, real *w, complex *z__, 
+	integer *ldz, complex *work, real *rwork, integer *iwork, integer *
+	ifail, integer *info);
+ 
+/* Subroutine */ int chbtrd_(char *vect, char *uplo, integer *n, integer *kd, 
+	complex *ab, integer *ldab, real *d__, real *e, complex *q, integer *
+	ldq, complex *work, integer *info);
+ 
+/* Subroutine */ int checon_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *ipiv, real *anorm, real *rcond, complex *work, integer *
+	info);
+ 
+/* Subroutine */ int cheev_(char *jobz, char *uplo, integer *n, complex *a, 
+	integer *lda, real *w, complex *work, integer *lwork, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int cheevd_(char *jobz, char *uplo, integer *n, complex *a, 
+	integer *lda, real *w, complex *work, integer *lwork, real *rwork, 
+	integer *lrwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int cheevr_(char *jobz, char *range, char *uplo, integer *n, 
+	complex *a, integer *lda, real *vl, real *vu, integer *il, integer *
+	iu, real *abstol, integer *m, real *w, complex *z__, integer *ldz, 
+	integer *isuppz, complex *work, integer *lwork, real *rwork, integer *
+	lrwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int cheevx_(char *jobz, char *range, char *uplo, integer *n, 
+	complex *a, integer *lda, real *vl, real *vu, integer *il, integer *
+	iu, real *abstol, integer *m, real *w, complex *z__, integer *ldz, 
+	complex *work, integer *lwork, real *rwork, integer *iwork, integer *
+	ifail, integer *info);
+ 
+/* Subroutine */ int chegs2_(integer *itype, char *uplo, integer *n, complex *
+	a, integer *lda, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int chegst_(integer *itype, char *uplo, integer *n, complex *
+	a, integer *lda, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int chegv_(integer *itype, char *jobz, char *uplo, integer *
+	n, complex *a, integer *lda, complex *b, integer *ldb, real *w, 
+	complex *work, integer *lwork, real *rwork, integer *info);
+ 
+/* Subroutine */ int chegvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, complex *a, integer *lda, complex *b, integer *ldb, real *w, 
+	complex *work, integer *lwork, real *rwork, integer *lrwork, integer *
+	iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int chegvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, complex *a, integer *lda, complex *b, integer *ldb, 
+	real *vl, real *vu, integer *il, integer *iu, real *abstol, integer *
+	m, real *w, complex *z__, integer *ldz, complex *work, integer *lwork,
+	 real *rwork, integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int cherfs_(char *uplo, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *af, integer *ldaf, integer *ipiv, complex *
+	b, integer *ldb, complex *x, integer *ldx, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int chesv_(char *uplo, integer *n, integer *nrhs, complex *a,
+	 integer *lda, integer *ipiv, complex *b, integer *ldb, complex *work,
+	 integer *lwork, integer *info);
+ 
+/* Subroutine */ int chesvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+	ipiv, complex *b, integer *ldb, complex *x, integer *ldx, real *rcond,
+	 real *ferr, real *berr, complex *work, integer *lwork, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int chetf2_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *ipiv, integer *info);
+ 
+/* Subroutine */ int chetrd_(char *uplo, integer *n, complex *a, integer *lda,
+	 real *d__, real *e, complex *tau, complex *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int chetrf_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *ipiv, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int chetri_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *ipiv, complex *work, integer *info);
+ 
+/* Subroutine */ int chetrs_(char *uplo, integer *n, integer *nrhs, complex *
+	a, integer *lda, integer *ipiv, complex *b, integer *ldb, integer *
+	info);
+ 
+/* Subroutine */ int chgeqz_(char *job, char *compq, char *compz, integer *n, 
+	integer *ilo, integer *ihi, complex *a, integer *lda, complex *b, 
+	integer *ldb, complex *alpha, complex *beta, complex *q, integer *ldq,
+	 complex *z__, integer *ldz, complex *work, integer *lwork, real *
+	rwork, integer *info);
+ 
+/* Subroutine */ int chpcon_(char *uplo, integer *n, complex *ap, integer *
+	ipiv, real *anorm, real *rcond, complex *work, integer *info);
+ 
+/* Subroutine */ int chpev_(char *jobz, char *uplo, integer *n, complex *ap, 
+	real *w, complex *z__, integer *ldz, complex *work, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int chpevd_(char *jobz, char *uplo, integer *n, complex *ap, 
+	real *w, complex *z__, integer *ldz, complex *work, integer *lwork, 
+	real *rwork, integer *lrwork, integer *iwork, integer *liwork, 
+	integer *info);
+ 
+/* Subroutine */ int chpevx_(char *jobz, char *range, char *uplo, integer *n, 
+	complex *ap, real *vl, real *vu, integer *il, integer *iu, real *
+	abstol, integer *m, real *w, complex *z__, integer *ldz, complex *
+	work, real *rwork, integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int chpgst_(integer *itype, char *uplo, integer *n, complex *
+	ap, complex *bp, integer *info);
+ 
+/* Subroutine */ int chpgv_(integer *itype, char *jobz, char *uplo, integer *
+	n, complex *ap, complex *bp, real *w, complex *z__, integer *ldz, 
+	complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int chpgvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, complex *ap, complex *bp, real *w, complex *z__, integer *ldz, 
+	complex *work, integer *lwork, real *rwork, integer *lrwork, integer *
+	iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int chpgvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, complex *ap, complex *bp, real *vl, real *vu, 
+	integer *il, integer *iu, real *abstol, integer *m, real *w, complex *
+	z__, integer *ldz, complex *work, real *rwork, integer *iwork, 
+	integer *ifail, integer *info);
+ 
+/* Subroutine */ int chprfs_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, complex *afp, integer *ipiv, complex *b, integer *ldb, complex *x,
+	 integer *ldx, real *ferr, real *berr, complex *work, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int chpsv_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, integer *ipiv, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int chpsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *ap, complex *afp, integer *ipiv, complex *b, integer *
+	ldb, complex *x, integer *ldx, real *rcond, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int chptrd_(char *uplo, integer *n, complex *ap, real *d__, 
+	real *e, complex *tau, integer *info);
+ 
+/* Subroutine */ int chptrf_(char *uplo, integer *n, complex *ap, integer *
+	ipiv, integer *info);
+ 
+/* Subroutine */ int chptri_(char *uplo, integer *n, complex *ap, integer *
+	ipiv, complex *work, integer *info);
+ 
+/* Subroutine */ int chptrs_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, integer *ipiv, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int chsein_(char *side, char *eigsrc, char *initv, logical *
+	select, integer *n, complex *h__, integer *ldh, complex *w, complex *
+	vl, integer *ldvl, complex *vr, integer *ldvr, integer *mm, integer *
+	m, complex *work, real *rwork, integer *ifaill, integer *ifailr, 
+	integer *info);
+ 
+/* Subroutine */ int chseqr_(char *job, char *compz, integer *n, integer *ilo,
+	 integer *ihi, complex *h__, integer *ldh, complex *w, complex *z__, 
+	integer *ldz, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int clabrd_(integer *m, integer *n, integer *nb, complex *a, 
+	integer *lda, real *d__, real *e, complex *tauq, complex *taup, 
+	complex *x, integer *ldx, complex *y, integer *ldy);
+ 
+/* Subroutine */ int clacgv_(integer *n, complex *x, integer *incx);
+ 
+/* Subroutine */ int clacon_(integer *n, complex *v, complex *x, real *est, 
+	integer *kase);
+ 
+/* Subroutine */ int clacp2_(char *uplo, integer *m, integer *n, real *a, 
+	integer *lda, complex *b, integer *ldb);
+ 
+/* Subroutine */ int clacpy_(char *uplo, integer *m, integer *n, complex *a, 
+	integer *lda, complex *b, integer *ldb);
+ 
+/* Subroutine */ int clacrm_(integer *m, integer *n, complex *a, integer *lda,
+	 real *b, integer *ldb, complex *c__, integer *ldc, real *rwork);
+ 
+/* Subroutine */ int clacrt_(integer *n, complex *cx, integer *incx, complex *
+	cy, integer *incy, complex *c__, complex *s);
+ 
+/* Subroutine */ int claed0_(integer *qsiz, integer *n, real *d__, real *e, 
+	complex *q, integer *ldq, complex *qstore, integer *ldqs, real *rwork,
+	 integer *iwork, integer *info);
+ 
+/* Subroutine */ int claed7_(integer *n, integer *cutpnt, integer *qsiz, 
+	integer *tlvls, integer *curlvl, integer *curpbm, real *d__, complex *
+	q, integer *ldq, real *rho, integer *indxq, real *qstore, integer *
+	qptr, integer *prmptr, integer *perm, integer *givptr, integer *
+	givcol, real *givnum, complex *work, real *rwork, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int claed8_(integer *k, integer *n, integer *qsiz, complex *
+	q, integer *ldq, real *d__, real *rho, integer *cutpnt, real *z__, 
+	real *dlamda, complex *q2, integer *ldq2, real *w, integer *indxp, 
+	integer *indx, integer *indxq, integer *perm, integer *givptr, 
+	integer *givcol, real *givnum, integer *info);
+ 
+/* Subroutine */ int claein_(logical *rightv, logical *noinit, integer *n, 
+	complex *h__, integer *ldh, complex *w, complex *v, complex *b, 
+	integer *ldb, real *rwork, real *eps3, real *smlnum, integer *info);
+ 
+/* Subroutine */ int claesy_(complex *a, complex *b, complex *c__, complex *
+	rt1, complex *rt2, complex *evscal, complex *cs1, complex *sn1);
+ 
+/* Subroutine */ int claev2_(complex *a, complex *b, complex *c__, real *rt1, 
+	real *rt2, real *cs1, complex *sn1);
+ 
+/* Subroutine */ int clags2_(logical *upper, real *a1, complex *a2, real *a3, 
+	real *b1, complex *b2, real *b3, real *csu, complex *snu, real *csv, 
+	complex *snv, real *csq, complex *snq);
+ 
+/* Subroutine */ int clagtm_(char *trans, integer *n, integer *nrhs, real *
+	alpha, complex *dl, complex *d__, complex *du, complex *x, integer *
+	ldx, real *beta, complex *b, integer *ldb);
+ 
+/* Subroutine */ int clahef_(char *uplo, integer *n, integer *nb, integer *kb,
+	 complex *a, integer *lda, integer *ipiv, complex *w, integer *ldw, 
+	integer *info);
+ 
+/* Subroutine */ int clahqr_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, complex *h__, integer *ldh, complex *w, 
+	integer *iloz, integer *ihiz, complex *z__, integer *ldz, integer *
+	info);
+ 
+/* Subroutine */ int clahrd_(integer *n, integer *k, integer *nb, complex *a, 
+	integer *lda, complex *tau, complex *t, integer *ldt, complex *y, 
+	integer *ldy);
+ 
+/* Subroutine */ int claic1_(integer *job, integer *j, complex *x, real *sest,
+	 complex *w, complex *gamma, real *sestpr, complex *s, complex *c__);
+ 
+/* Subroutine */ int clals0_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, integer *nrhs, complex *b, integer *ldb, complex *bx, 
+	integer *ldbx, integer *perm, integer *givptr, integer *givcol, 
+	integer *ldgcol, real *givnum, integer *ldgnum, real *poles, real *
+	difl, real *difr, real *z__, integer *k, real *c__, real *s, real *
+	rwork, integer *info);
+ 
+/* Subroutine */ int clalsa_(integer *icompq, integer *smlsiz, integer *n, 
+	integer *nrhs, complex *b, integer *ldb, complex *bx, integer *ldbx, 
+	real *u, integer *ldu, real *vt, integer *k, real *difl, real *difr, 
+	real *z__, real *poles, integer *givptr, integer *givcol, integer *
+	ldgcol, integer *perm, real *givnum, real *c__, real *s, real *rwork, 
+	integer *iwork, integer *info);
+ 
+/* Subroutine */ int clapll_(integer *n, complex *x, integer *incx, complex *
+	y, integer *incy, real *ssmin);
+ 
+/* Subroutine */ int clapmt_(logical *forwrd, integer *m, integer *n, complex 
+	*x, integer *ldx, integer *k);
+ 
+/* Subroutine */ int claqgb_(integer *m, integer *n, integer *kl, integer *ku,
+	 complex *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real 
+	*colcnd, real *amax, char *equed);
+ 
+/* Subroutine */ int claqge_(integer *m, integer *n, complex *a, integer *lda,
+	 real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, char *
+	equed);
+ 
+/* Subroutine */ int claqhb_(char *uplo, integer *n, integer *kd, complex *ab,
+	 integer *ldab, real *s, real *scond, real *amax, char *equed);
+ 
+/* Subroutine */ int claqhe_(char *uplo, integer *n, complex *a, integer *lda,
+	 real *s, real *scond, real *amax, char *equed);
+ 
+/* Subroutine */ int claqhp_(char *uplo, integer *n, complex *ap, real *s, 
+	real *scond, real *amax, char *equed);
+ 
+/* Subroutine */ int claqp2_(integer *m, integer *n, integer *offset, complex 
+	*a, integer *lda, integer *jpvt, complex *tau, real *vn1, real *vn2, 
+	complex *work);
+ 
+/* Subroutine */ int claqps_(integer *m, integer *n, integer *offset, integer 
+	*nb, integer *kb, complex *a, integer *lda, integer *jpvt, complex *
+	tau, real *vn1, real *vn2, complex *auxv, complex *f, integer *ldf);
+ 
+/* Subroutine */ int claqsb_(char *uplo, integer *n, integer *kd, complex *ab,
+	 integer *ldab, real *s, real *scond, real *amax, char *equed);
+ 
+/* Subroutine */ int claqsp_(char *uplo, integer *n, complex *ap, real *s, 
+	real *scond, real *amax, char *equed);
+ 
+/* Subroutine */ int claqsy_(char *uplo, integer *n, complex *a, integer *lda,
+	 real *s, real *scond, real *amax, char *equed);
+ 
+/* Subroutine */ int clar1v_(integer *n, integer *b1, integer *bn, real *
+	sigma, real *d__, real *l, real *ld, real *lld, real *gersch, complex 
+	*z__, real *ztz, real *mingma, integer *r__, integer *isuppz, real *
+	work);
+ 
+/* Subroutine */ int clar2v_(integer *n, complex *x, complex *y, complex *z__,
+	 integer *incx, real *c__, complex *s, integer *incc);
+ 
+/* Subroutine */ int clarcm_(integer *m, integer *n, real *a, integer *lda, 
+	complex *b, integer *ldb, complex *c__, integer *ldc, real *rwork);
+ 
+/* Subroutine */ int clarf_(char *side, integer *m, integer *n, complex *v, 
+	integer *incv, complex *tau, complex *c__, integer *ldc, complex *
+	work);
+ 
+/* Subroutine */ int clarfb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, complex *v, integer *ldv, 
+	complex *t, integer *ldt, complex *c__, integer *ldc, complex *work, 
+	integer *ldwork);
+ 
+/* Subroutine */ int clarfg_(integer *n, complex *alpha, complex *x, integer *
+	incx, complex *tau);
+ 
+/* Subroutine */ int clarft_(char *direct, char *storev, integer *n, integer *
+	k, complex *v, integer *ldv, complex *tau, complex *t, integer *ldt);
+ 
+/* Subroutine */ int clarfx_(char *side, integer *m, integer *n, complex *v, 
+	complex *tau, complex *c__, integer *ldc, complex *work);
+ 
+/* Subroutine */ int clargv_(integer *n, complex *x, integer *incx, complex *
+	y, integer *incy, real *c__, integer *incc);
+ 
+/* Subroutine */ int clarnv_(integer *idist, integer *iseed, integer *n, 
+	complex *x);
+ 
+/* Subroutine */ int clarrv_(integer *n, real *d__, real *l, integer *isplit, 
+	integer *m, real *w, integer *iblock, real *gersch, real *tol, 
+	complex *z__, integer *ldz, integer *isuppz, real *work, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int clartg_(complex *f, complex *g, real *cs, complex *sn, 
+	complex *r__);
+ 
+/* Subroutine */ int clartv_(integer *n, complex *x, integer *incx, complex *
+	y, integer *incy, real *c__, complex *s, integer *incc);
+ 
+/* Subroutine */ int clarz_(char *side, integer *m, integer *n, integer *l, 
+	complex *v, integer *incv, complex *tau, complex *c__, integer *ldc, 
+	complex *work);
+ 
+/* Subroutine */ int clarzb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, integer *l, complex *v, 
+	integer *ldv, complex *t, integer *ldt, complex *c__, integer *ldc, 
+	complex *work, integer *ldwork);
+ 
+/* Subroutine */ int clarzt_(char *direct, char *storev, integer *n, integer *
+	k, complex *v, integer *ldv, complex *tau, complex *t, integer *ldt);
+ 
+/* Subroutine */ int clascl_(char *type__, integer *kl, integer *ku, real *
+	cfrom, real *cto, integer *m, integer *n, complex *a, integer *lda, 
+	integer *info);
+ 
+/* Subroutine */ int claset_(char *uplo, integer *m, integer *n, complex *
+	alpha, complex *beta, complex *a, integer *lda);
+ 
+/* Subroutine */ int clasr_(char *side, char *pivot, char *direct, integer *m,
+	 integer *n, real *c__, real *s, complex *a, integer *lda);
+ 
+/* Subroutine */ int classq_(integer *n, complex *x, integer *incx, real *
+	scale, real *sumsq);
+ 
+/* Subroutine */ int claswp_(integer *n, complex *a, integer *lda, integer *
+	k1, integer *k2, integer *ipiv, integer *incx);
+ 
+/* Subroutine */ int clasyf_(char *uplo, integer *n, integer *nb, integer *kb,
+	 complex *a, integer *lda, integer *ipiv, complex *w, integer *ldw, 
+	integer *info);
+ 
+/* Subroutine */ int clatbs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, integer *kd, complex *ab, integer *ldab, complex *
+	x, real *scale, real *cnorm, integer *info);
+ 
+/* Subroutine */ int clatdf_(integer *ijob, integer *n, complex *z__, integer 
+	*ldz, complex *rhs, real *rdsum, real *rdscal, integer *ipiv, integer 
+	*jpiv);
+ 
+/* Subroutine */ int clatps_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, complex *ap, complex *x, real *scale, real *cnorm,
+	 integer *info);
+ 
+/* Subroutine */ int clatrd_(char *uplo, integer *n, integer *nb, complex *a, 
+	integer *lda, real *e, complex *tau, complex *w, integer *ldw);
+ 
+/* Subroutine */ int clatrs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, complex *a, integer *lda, complex *x, real *scale,
+	 real *cnorm, integer *info);
+ 
+/* Subroutine */ int clatrz_(integer *m, integer *n, integer *l, complex *a, 
+	integer *lda, complex *tau, complex *work);
+ 
+/* Subroutine */ int clatzm_(char *side, integer *m, integer *n, complex *v, 
+	integer *incv, complex *tau, complex *c1, complex *c2, integer *ldc, 
+	complex *work);
+ 
+/* Subroutine */ int clauu2_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *info);
+ 
+/* Subroutine */ int clauum_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *info);
+ 
+/* Subroutine */ int cpbcon_(char *uplo, integer *n, integer *kd, complex *ab,
+	 integer *ldab, real *anorm, real *rcond, complex *work, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int cpbequ_(char *uplo, integer *n, integer *kd, complex *ab,
+	 integer *ldab, real *s, real *scond, real *amax, integer *info);
+ 
+/* Subroutine */ int cpbrfs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, complex *ab, integer *ldab, complex *afb, integer *ldafb, 
+	complex *b, integer *ldb, complex *x, integer *ldx, real *ferr, real *
+	berr, complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cpbstf_(char *uplo, integer *n, integer *kd, complex *ab,
+	 integer *ldab, integer *info);
+ 
+/* Subroutine */ int cpbsv_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, complex *ab, integer *ldab, complex *b, integer *ldb, integer *
+	info);
+ 
+/* Subroutine */ int cpbsvx_(char *fact, char *uplo, integer *n, integer *kd, 
+	integer *nrhs, complex *ab, integer *ldab, complex *afb, integer *
+	ldafb, char *equed, real *s, complex *b, integer *ldb, complex *x, 
+	integer *ldx, real *rcond, real *ferr, real *berr, complex *work, 
+	real *rwork, integer *info);
+ 
+/* Subroutine */ int cpbtf2_(char *uplo, integer *n, integer *kd, complex *ab,
+	 integer *ldab, integer *info);
+ 
+/* Subroutine */ int cpbtrf_(char *uplo, integer *n, integer *kd, complex *ab,
+	 integer *ldab, integer *info);
+ 
+/* Subroutine */ int cpbtrs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, complex *ab, integer *ldab, complex *b, integer *ldb, integer *
+	info);
+ 
+/* Subroutine */ int cpocon_(char *uplo, integer *n, complex *a, integer *lda,
+	 real *anorm, real *rcond, complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cpoequ_(integer *n, complex *a, integer *lda, real *s, 
+	real *scond, real *amax, integer *info);
+ 
+/* Subroutine */ int cporfs_(char *uplo, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *af, integer *ldaf, complex *b, integer *ldb,
+	 complex *x, integer *ldx, real *ferr, real *berr, complex *work, 
+	real *rwork, integer *info);
+ 
+/* Subroutine */ int cposv_(char *uplo, integer *n, integer *nrhs, complex *a,
+	 integer *lda, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int cposvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, char *
+	equed, real *s, complex *b, integer *ldb, complex *x, integer *ldx, 
+	real *rcond, real *ferr, real *berr, complex *work, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int cpotf2_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *info);
+ 
+/* Subroutine */ int cpotrf_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *info);
+ 
+/* Subroutine */ int cpotri_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *info);
+ 
+/* Subroutine */ int cpotrs_(char *uplo, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int cppcon_(char *uplo, integer *n, complex *ap, real *anorm,
+	 real *rcond, complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cppequ_(char *uplo, integer *n, complex *ap, real *s, 
+	real *scond, real *amax, integer *info);
+ 
+/* Subroutine */ int cpprfs_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, complex *afp, complex *b, integer *ldb, complex *x, integer *ldx, 
+	real *ferr, real *berr, complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cppsv_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int cppsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *ap, complex *afp, char *equed, real *s, complex *b, 
+	integer *ldb, complex *x, integer *ldx, real *rcond, real *ferr, real 
+	*berr, complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int cpptrf_(char *uplo, integer *n, complex *ap, integer *
+	info);
+ 
+/* Subroutine */ int cpptri_(char *uplo, integer *n, complex *ap, integer *
+	info);
+ 
+/* Subroutine */ int cpptrs_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int cptcon_(integer *n, real *d__, complex *e, real *anorm, 
+	real *rcond, real *rwork, integer *info);
+ 
+/* Subroutine */ int cptrfs_(char *uplo, integer *n, integer *nrhs, real *d__,
+	 complex *e, real *df, complex *ef, complex *b, integer *ldb, complex 
+	*x, integer *ldx, real *ferr, real *berr, complex *work, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int cptsv_(integer *n, integer *nrhs, real *d__, complex *e, 
+	complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int cptsvx_(char *fact, integer *n, integer *nrhs, real *d__,
+	 complex *e, real *df, complex *ef, complex *b, integer *ldb, complex 
+	*x, integer *ldx, real *rcond, real *ferr, real *berr, complex *work, 
+	real *rwork, integer *info);
+ 
+/* Subroutine */ int cpttrf_(integer *n, real *d__, complex *e, integer *info);
+ 
+/* Subroutine */ int cpttrs_(char *uplo, integer *n, integer *nrhs, real *d__,
+	 complex *e, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int cptts2_(integer *iuplo, integer *n, integer *nrhs, real *
+	d__, complex *e, complex *b, integer *ldb);
+ 
+/* Subroutine */ int crot_(integer *n, complex *cx, integer *incx, complex *
+	cy, integer *incy, real *c__, complex *s);
+ 
+/* Subroutine */ int cspcon_(char *uplo, integer *n, complex *ap, integer *
+	ipiv, real *anorm, real *rcond, complex *work, integer *info);
+ 
+/* Subroutine */ int cspmv_(char *uplo, integer *n, complex *alpha, complex *
+	ap, complex *x, integer *incx, complex *beta, complex *y, integer *
+	incy);
+ 
+/* Subroutine */ int cspr_(char *uplo, integer *n, complex *alpha, complex *x,
+	 integer *incx, complex *ap);
+ 
+/* Subroutine */ int csprfs_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, complex *afp, integer *ipiv, complex *b, integer *ldb, complex *x,
+	 integer *ldx, real *ferr, real *berr, complex *work, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int cspsv_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, integer *ipiv, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int cspsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *ap, complex *afp, integer *ipiv, complex *b, integer *
+	ldb, complex *x, integer *ldx, real *rcond, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int csptrf_(char *uplo, integer *n, complex *ap, integer *
+	ipiv, integer *info);
+ 
+/* Subroutine */ int csptri_(char *uplo, integer *n, complex *ap, integer *
+	ipiv, complex *work, integer *info);
+ 
+/* Subroutine */ int csptrs_(char *uplo, integer *n, integer *nrhs, complex *
+	ap, integer *ipiv, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int csrot_(integer *n, complex *cx, integer *incx, complex *
+	cy, integer *incy, real *c__, real *s);
+ 
+/* Subroutine */ int csrscl_(integer *n, real *sa, complex *sx, integer *incx);
+ 
+/* Subroutine */ int cstedc_(char *compz, integer *n, real *d__, real *e, 
+	complex *z__, integer *ldz, complex *work, integer *lwork, real *
+	rwork, integer *lrwork, integer *iwork, integer *liwork, integer *
+	info);
+ 
+/* Subroutine */ int cstein_(integer *n, real *d__, real *e, integer *m, real 
+	*w, integer *iblock, integer *isplit, complex *z__, integer *ldz, 
+	real *work, integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int csteqr_(char *compz, integer *n, real *d__, real *e, 
+	complex *z__, integer *ldz, real *work, integer *info);
+ 
+/* Subroutine */ int csycon_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *ipiv, real *anorm, real *rcond, complex *work, integer *
+	info);
+ 
+/* Subroutine */ int csymv_(char *uplo, integer *n, complex *alpha, complex *
+	a, integer *lda, complex *x, integer *incx, complex *beta, complex *y,
+	 integer *incy);
+ 
+/* Subroutine */ int csyr_(char *uplo, integer *n, complex *alpha, complex *x,
+	 integer *incx, complex *a, integer *lda);
+ 
+/* Subroutine */ int csyrfs_(char *uplo, integer *n, integer *nrhs, complex *
+	a, integer *lda, complex *af, integer *ldaf, integer *ipiv, complex *
+	b, integer *ldb, complex *x, integer *ldx, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int csysv_(char *uplo, integer *n, integer *nrhs, complex *a,
+	 integer *lda, integer *ipiv, complex *b, integer *ldb, complex *work,
+	 integer *lwork, integer *info);
+ 
+/* Subroutine */ int csysvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, complex *a, integer *lda, complex *af, integer *ldaf, integer *
+	ipiv, complex *b, integer *ldb, complex *x, integer *ldx, real *rcond,
+	 real *ferr, real *berr, complex *work, integer *lwork, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int csytf2_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *ipiv, integer *info);
+ 
+/* Subroutine */ int csytrf_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *ipiv, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int csytri_(char *uplo, integer *n, complex *a, integer *lda,
+	 integer *ipiv, complex *work, integer *info);
+ 
+/* Subroutine */ int csytrs_(char *uplo, integer *n, integer *nrhs, complex *
+	a, integer *lda, integer *ipiv, complex *b, integer *ldb, integer *
+	info);
+ 
+/* Subroutine */ int ctbcon_(char *norm, char *uplo, char *diag, integer *n, 
+	integer *kd, complex *ab, integer *ldab, real *rcond, complex *work, 
+	real *rwork, integer *info);
+ 
+/* Subroutine */ int ctbrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, complex *ab, integer *ldab, complex *b, 
+	integer *ldb, complex *x, integer *ldx, real *ferr, real *berr, 
+	complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int ctbtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, complex *ab, integer *ldab, complex *b, 
+	integer *ldb, integer *info);
+ 
+/* Subroutine */ int ctgevc_(char *side, char *howmny, logical *select, 
+	integer *n, complex *a, integer *lda, complex *b, integer *ldb, 
+	complex *vl, integer *ldvl, complex *vr, integer *ldvr, integer *mm, 
+	integer *m, complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int ctgex2_(logical *wantq, logical *wantz, integer *n, 
+	complex *a, integer *lda, complex *b, integer *ldb, complex *q, 
+	integer *ldq, complex *z__, integer *ldz, integer *j1, integer *info);
+ 
+/* Subroutine */ int ctgexc_(logical *wantq, logical *wantz, integer *n, 
+	complex *a, integer *lda, complex *b, integer *ldb, complex *q, 
+	integer *ldq, complex *z__, integer *ldz, integer *ifst, integer *
+	ilst, integer *info);
+ 
+/* Subroutine */ int ctgsen_(integer *ijob, logical *wantq, logical *wantz, 
+	logical *select, integer *n, complex *a, integer *lda, complex *b, 
+	integer *ldb, complex *alpha, complex *beta, complex *q, integer *ldq,
+	 complex *z__, integer *ldz, integer *m, real *pl, real *pr, real *
+	dif, complex *work, integer *lwork, integer *iwork, integer *liwork, 
+	integer *info);
+ 
+/* Subroutine */ int ctgsja_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, integer *k, integer *l, complex *a, integer *
+	lda, complex *b, integer *ldb, real *tola, real *tolb, real *alpha, 
+	real *beta, complex *u, integer *ldu, complex *v, integer *ldv, 
+	complex *q, integer *ldq, complex *work, integer *ncycle, integer *
+	info);
+ 
+/* Subroutine */ int ctgsna_(char *job, char *howmny, logical *select, 
+	integer *n, complex *a, integer *lda, complex *b, integer *ldb, 
+	complex *vl, integer *ldvl, complex *vr, integer *ldvr, real *s, real 
+	*dif, integer *mm, integer *m, complex *work, integer *lwork, integer 
+	*iwork, integer *info);
+ 
+/* Subroutine */ int ctgsy2_(char *trans, integer *ijob, integer *m, integer *
+	n, complex *a, integer *lda, complex *b, integer *ldb, complex *c__, 
+	integer *ldc, complex *d__, integer *ldd, complex *e, integer *lde, 
+	complex *f, integer *ldf, real *scale, real *rdsum, real *rdscal, 
+	integer *info);
+ 
+/* Subroutine */ int ctgsyl_(char *trans, integer *ijob, integer *m, integer *
+	n, complex *a, integer *lda, complex *b, integer *ldb, complex *c__, 
+	integer *ldc, complex *d__, integer *ldd, complex *e, integer *lde, 
+	complex *f, integer *ldf, real *scale, real *dif, complex *work, 
+	integer *lwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int ctpcon_(char *norm, char *uplo, char *diag, integer *n, 
+	complex *ap, real *rcond, complex *work, real *rwork, integer *info);
+ 
+/* Subroutine */ int ctprfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, complex *ap, complex *b, integer *ldb, complex *x, 
+	integer *ldx, real *ferr, real *berr, complex *work, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int ctptri_(char *uplo, char *diag, integer *n, complex *ap, 
+	integer *info);
+ 
+/* Subroutine */ int ctptrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, complex *ap, complex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int ctrcon_(char *norm, char *uplo, char *diag, integer *n, 
+	complex *a, integer *lda, real *rcond, complex *work, real *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int ctrevc_(char *side, char *howmny, logical *select, 
+	integer *n, complex *t, integer *ldt, complex *vl, integer *ldvl, 
+	complex *vr, integer *ldvr, integer *mm, integer *m, complex *work, 
+	real *rwork, integer *info);
+ 
+/* Subroutine */ int ctrexc_(char *compq, integer *n, complex *t, integer *
+	ldt, complex *q, integer *ldq, integer *ifst, integer *ilst, integer *
+	info);
+ 
+/* Subroutine */ int ctrrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, complex *a, integer *lda, complex *b, integer *ldb, 
+	complex *x, integer *ldx, real *ferr, real *berr, complex *work, real 
+	*rwork, integer *info);
+ 
+/* Subroutine */ int ctrsen_(char *job, char *compq, logical *select, integer 
+	*n, complex *t, integer *ldt, complex *q, integer *ldq, complex *w, 
+	integer *m, real *s, real *sep, complex *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int ctrsna_(char *job, char *howmny, logical *select, 
+	integer *n, complex *t, integer *ldt, complex *vl, integer *ldvl, 
+	complex *vr, integer *ldvr, real *s, real *sep, integer *mm, integer *
+	m, complex *work, integer *ldwork, real *rwork, integer *info);
+ 
+/* Subroutine */ int ctrsyl_(char *trana, char *tranb, integer *isgn, integer 
+	*m, integer *n, complex *a, integer *lda, complex *b, integer *ldb, 
+	complex *c__, integer *ldc, real *scale, integer *info);
+ 
+/* Subroutine */ int ctrti2_(char *uplo, char *diag, integer *n, complex *a, 
+	integer *lda, integer *info);
+ 
+/* Subroutine */ int ctrtri_(char *uplo, char *diag, integer *n, complex *a, 
+	integer *lda, integer *info);
+ 
+/* Subroutine */ int ctrtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, complex *a, integer *lda, complex *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int ctzrqf_(integer *m, integer *n, complex *a, integer *lda,
+	 complex *tau, integer *info);
+ 
+/* Subroutine */ int ctzrzf_(integer *m, integer *n, complex *a, integer *lda,
+	 complex *tau, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cung2l_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *info);
+ 
+/* Subroutine */ int cung2r_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *info);
+ 
+/* Subroutine */ int cungbr_(char *vect, integer *m, integer *n, integer *k, 
+	complex *a, integer *lda, complex *tau, complex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int cunghr_(integer *n, integer *ilo, integer *ihi, complex *
+	a, integer *lda, complex *tau, complex *work, integer *lwork, integer 
+	*info);
+ 
+/* Subroutine */ int cungl2_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *info);
+ 
+/* Subroutine */ int cunglq_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *lwork, integer *
+	info);
+ 
+/* Subroutine */ int cungql_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *lwork, integer *
+	info);
+ 
+/* Subroutine */ int cungqr_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *lwork, integer *
+	info);
+ 
+/* Subroutine */ int cungr2_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *info);
+ 
+/* Subroutine */ int cungrq_(integer *m, integer *n, integer *k, complex *a, 
+	integer *lda, complex *tau, complex *work, integer *lwork, integer *
+	info);
+ 
+/* Subroutine */ int cungtr_(char *uplo, integer *n, complex *a, integer *lda,
+	 complex *tau, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cunm2l_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *info);
+ 
+/* Subroutine */ int cunm2r_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *info);
+ 
+/* Subroutine */ int cunmbr_(char *vect, char *side, char *trans, integer *m, 
+	integer *n, integer *k, complex *a, integer *lda, complex *tau, 
+	complex *c__, integer *ldc, complex *work, integer *lwork, integer *
+	info);
+ 
+/* Subroutine */ int cunmhr_(char *side, char *trans, integer *m, integer *n, 
+	integer *ilo, integer *ihi, complex *a, integer *lda, complex *tau, 
+	complex *c__, integer *ldc, complex *work, integer *lwork, integer *
+	info);
+ 
+/* Subroutine */ int cunml2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *info);
+ 
+/* Subroutine */ int cunmlq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cunmql_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cunmqr_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cunmr2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *info);
+ 
+/* Subroutine */ int cunmr3_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, complex *a, integer *lda, complex *tau, 
+	complex *c__, integer *ldc, complex *work, integer *info);
+ 
+/* Subroutine */ int cunmrq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cunmrz_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, complex *a, integer *lda, complex *tau, 
+	complex *c__, integer *ldc, complex *work, integer *lwork, integer *
+	info);
+ 
+/* Subroutine */ int cunmtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, complex *a, integer *lda, complex *tau, complex *c__, 
+	integer *ldc, complex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int cupgtr_(char *uplo, integer *n, complex *ap, complex *
+	tau, complex *q, integer *ldq, complex *work, integer *info);
+ 
+/* Subroutine */ int cupmtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, complex *ap, complex *tau, complex *c__, integer *ldc, 
+	complex *work, integer *info);
+ 
+/* Subroutine */ int dbdsdc_(char *uplo, char *compq, integer *n, doublereal *
+	d__, doublereal *e, doublereal *u, integer *ldu, doublereal *vt, 
+	integer *ldvt, doublereal *q, integer *iq, doublereal *work, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int dbdsqr_(char *uplo, integer *n, integer *ncvt, integer *
+	nru, integer *ncc, doublereal *d__, doublereal *e, doublereal *vt, 
+	integer *ldvt, doublereal *u, integer *ldu, doublereal *c__, integer *
+	ldc, doublereal *work, integer *info);
+ 
+/* Subroutine */ int ddisna_(char *job, integer *m, integer *n, doublereal *
+	d__, doublereal *sep, integer *info);
+ 
+/* Subroutine */ int dgbbrd_(char *vect, integer *m, integer *n, integer *ncc,
+	 integer *kl, integer *ku, doublereal *ab, integer *ldab, doublereal *
+	d__, doublereal *e, doublereal *q, integer *ldq, doublereal *pt, 
+	integer *ldpt, doublereal *c__, integer *ldc, doublereal *work, 
+	integer *info);
+ 
+/* Subroutine */ int dgbcon_(char *norm, integer *n, integer *kl, integer *ku,
+	 doublereal *ab, integer *ldab, integer *ipiv, doublereal *anorm, 
+	doublereal *rcond, doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dgbequ_(integer *m, integer *n, integer *kl, integer *ku,
+	 doublereal *ab, integer *ldab, doublereal *r__, doublereal *c__, 
+	doublereal *rowcnd, doublereal *colcnd, doublereal *amax, integer *
+	info);
+ 
+/* Subroutine */ int dgbrfs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, doublereal *ab, integer *ldab, doublereal *afb, 
+	integer *ldafb, integer *ipiv, doublereal *b, integer *ldb, 
+	doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dgbsv_(integer *n, integer *kl, integer *ku, integer *
+	nrhs, doublereal *ab, integer *ldab, integer *ipiv, doublereal *b, 
+	integer *ldb, integer *info);
+ 
+/* Subroutine */ int dgbsvx_(char *fact, char *trans, integer *n, integer *kl,
+	 integer *ku, integer *nrhs, doublereal *ab, integer *ldab, 
+	doublereal *afb, integer *ldafb, integer *ipiv, char *equed, 
+	doublereal *r__, doublereal *c__, doublereal *b, integer *ldb, 
+	doublereal *x, integer *ldx, doublereal *rcond, doublereal *ferr, 
+	doublereal *berr, doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dgbtf2_(integer *m, integer *n, integer *kl, integer *ku,
+	 doublereal *ab, integer *ldab, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int dgbtrf_(integer *m, integer *n, integer *kl, integer *ku,
+	 doublereal *ab, integer *ldab, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int dgbtrs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, doublereal *ab, integer *ldab, integer *ipiv, 
+	doublereal *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int dgebak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, doublereal *scale, integer *m, doublereal *v, integer *
+	ldv, integer *info);
+ 
+/* Subroutine */ int dgebal_(char *job, integer *n, doublereal *a, integer *
+	lda, integer *ilo, integer *ihi, doublereal *scale, integer *info);
+ 
+/* Subroutine */ int dgebd2_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *d__, doublereal *e, doublereal *tauq, doublereal *
+	taup, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dgebrd_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *d__, doublereal *e, doublereal *tauq, doublereal *
+	taup, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dgecon_(char *norm, integer *n, doublereal *a, integer *
+	lda, doublereal *anorm, doublereal *rcond, doublereal *work, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int dgeequ_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *r__, doublereal *c__, doublereal *rowcnd, doublereal 
+	*colcnd, doublereal *amax, integer *info);
+ 
+/* Subroutine */ int dgees_(char *jobvs, char *sort, L_fp select, integer *n, 
+	doublereal *a, integer *lda, integer *sdim, doublereal *wr, 
+	doublereal *wi, doublereal *vs, integer *ldvs, doublereal *work, 
+	integer *lwork, logical *bwork, integer *info);
+ 
+/* Subroutine */ int dgeesx_(char *jobvs, char *sort, L_fp select, char *
+	sense, integer *n, doublereal *a, integer *lda, integer *sdim, 
+	doublereal *wr, doublereal *wi, doublereal *vs, integer *ldvs, 
+	doublereal *rconde, doublereal *rcondv, doublereal *work, integer *
+	lwork, integer *iwork, integer *liwork, logical *bwork, integer *info);
+ 
+/* Subroutine */ int dgeev_(char *jobvl, char *jobvr, integer *n, doublereal *
+	a, integer *lda, doublereal *wr, doublereal *wi, doublereal *vl, 
+	integer *ldvl, doublereal *vr, integer *ldvr, doublereal *work, 
+	integer *lwork, integer *info);
+ 
+/* Subroutine */ int dgeevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, doublereal *a, integer *lda, doublereal *wr, 
+	doublereal *wi, doublereal *vl, integer *ldvl, doublereal *vr, 
+	integer *ldvr, integer *ilo, integer *ihi, doublereal *scale, 
+	doublereal *abnrm, doublereal *rconde, doublereal *rcondv, doublereal 
+	*work, integer *lwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dgegs_(char *jobvsl, char *jobvsr, integer *n, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+	alphar, doublereal *alphai, doublereal *beta, doublereal *vsl, 
+	integer *ldvsl, doublereal *vsr, integer *ldvsr, doublereal *work, 
+	integer *lwork, integer *info);
+ 
+/* Subroutine */ int dgegv_(char *jobvl, char *jobvr, integer *n, doublereal *
+	a, integer *lda, doublereal *b, integer *ldb, doublereal *alphar, 
+	doublereal *alphai, doublereal *beta, doublereal *vl, integer *ldvl, 
+	doublereal *vr, integer *ldvr, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dgehd2_(integer *n, integer *ilo, integer *ihi, 
+	doublereal *a, integer *lda, doublereal *tau, doublereal *work, 
+	integer *info);
+ 
+/* Subroutine */ int dgehrd_(integer *n, integer *ilo, integer *ihi, 
+	doublereal *a, integer *lda, doublereal *tau, doublereal *work, 
+	integer *lwork, integer *info);
+ 
+/* Subroutine */ int dgelq2_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dgelqf_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dgels_(char *trans, integer *m, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dgelsd_(integer *m, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+	s, doublereal *rcond, integer *rank, doublereal *work, integer *lwork,
+	 integer *iwork, integer *info);
+ 
+/* Subroutine */ int dgelss_(integer *m, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+	s, doublereal *rcond, integer *rank, doublereal *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int dgelsx_(integer *m, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+	jpvt, doublereal *rcond, integer *rank, doublereal *work, integer *
+	info);
+ 
+/* Subroutine */ int dgelsy_(integer *m, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+	jpvt, doublereal *rcond, integer *rank, doublereal *work, integer *
+	lwork, integer *info);
+ 
+/* Subroutine */ int dgeql2_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dgeqlf_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dgeqp3_(integer *m, integer *n, doublereal *a, integer *
+	lda, integer *jpvt, doublereal *tau, doublereal *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int dgeqpf_(integer *m, integer *n, doublereal *a, integer *
+	lda, integer *jpvt, doublereal *tau, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dgeqr2_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dgeqrf_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dgerfs_(char *trans, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *af, integer *ldaf, integer *
+	ipiv, doublereal *b, integer *ldb, doublereal *x, integer *ldx, 
+	doublereal *ferr, doublereal *berr, doublereal *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int dgerq2_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dgerqf_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dgesc2_(integer *n, doublereal *a, integer *lda, 
+	doublereal *rhs, integer *ipiv, integer *jpiv, doublereal *scale);
+ 
+/* Subroutine */ int dgesdd_(char *jobz, integer *m, integer *n, doublereal *
+	a, integer *lda, doublereal *s, doublereal *u, integer *ldu, 
+	doublereal *vt, integer *ldvt, doublereal *work, integer *lwork, 
+	integer *iwork, integer *info);
+ 
+/* Subroutine */ int dgesv_(integer *n, integer *nrhs, doublereal *a, integer 
+	*lda, integer *ipiv, doublereal *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int dgesvd_(char *jobu, char *jobvt, integer *m, integer *n, 
+	doublereal *a, integer *lda, doublereal *s, doublereal *u, integer *
+	ldu, doublereal *vt, integer *ldvt, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dgesvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	integer *ipiv, char *equed, doublereal *r__, doublereal *c__, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int dgetc2_(integer *n, doublereal *a, integer *lda, integer 
+	*ipiv, integer *jpiv, integer *info);
+ 
+/* Subroutine */ int dgetf2_(integer *m, integer *n, doublereal *a, integer *
+	lda, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int dgetrf_(integer *m, integer *n, doublereal *a, integer *
+	lda, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int dgetri_(integer *n, doublereal *a, integer *lda, integer 
+	*ipiv, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dgetrs_(char *trans, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, integer *ipiv, doublereal *b, integer *
+	ldb, integer *info);
+ 
+/* Subroutine */ int dggbak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, doublereal *lscale, doublereal *rscale, integer *m, 
+	doublereal *v, integer *ldv, integer *info);
+ 
+/* Subroutine */ int dggbal_(char *job, integer *n, doublereal *a, integer *
+	lda, doublereal *b, integer *ldb, integer *ilo, integer *ihi, 
+	doublereal *lscale, doublereal *rscale, doublereal *work, integer *
+	info);
+ 
+/* Subroutine */ int dgges_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	delctg, integer *n, doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, integer *sdim, doublereal *alphar, doublereal *alphai, 
+	doublereal *beta, doublereal *vsl, integer *ldvsl, doublereal *vsr, 
+	integer *ldvsr, doublereal *work, integer *lwork, logical *bwork, 
+	integer *info);
+ 
+/* Subroutine */ int dggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	delctg, char *sense, integer *n, doublereal *a, integer *lda, 
+	doublereal *b, integer *ldb, integer *sdim, doublereal *alphar, 
+	doublereal *alphai, doublereal *beta, doublereal *vsl, integer *ldvsl,
+	 doublereal *vsr, integer *ldvsr, doublereal *rconde, doublereal *
+	rcondv, doublereal *work, integer *lwork, integer *iwork, integer *
+	liwork, logical *bwork, integer *info);
+ 
+/* Subroutine */ int dggev_(char *jobvl, char *jobvr, integer *n, doublereal *
+	a, integer *lda, doublereal *b, integer *ldb, doublereal *alphar, 
+	doublereal *alphai, doublereal *beta, doublereal *vl, integer *ldvl, 
+	doublereal *vr, integer *ldvr, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dggevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *
+	beta, doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, 
+	integer *ilo, integer *ihi, doublereal *lscale, doublereal *rscale, 
+	doublereal *abnrm, doublereal *bbnrm, doublereal *rconde, doublereal *
+	rcondv, doublereal *work, integer *lwork, integer *iwork, logical *
+	bwork, integer *info);
+ 
+/* Subroutine */ int dggglm_(integer *n, integer *m, integer *p, doublereal *
+	a, integer *lda, doublereal *b, integer *ldb, doublereal *d__, 
+	doublereal *x, doublereal *y, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dgghrd_(char *compq, char *compz, integer *n, integer *
+	ilo, integer *ihi, doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, doublereal *q, integer *ldq, doublereal *z__, integer *
+	ldz, integer *info);
+ 
+/* Subroutine */ int dgglse_(integer *m, integer *n, integer *p, doublereal *
+	a, integer *lda, doublereal *b, integer *ldb, doublereal *c__, 
+	doublereal *d__, doublereal *x, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dggqrf_(integer *n, integer *m, integer *p, doublereal *
+	a, integer *lda, doublereal *taua, doublereal *b, integer *ldb, 
+	doublereal *taub, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dggrqf_(integer *m, integer *p, integer *n, doublereal *
+	a, integer *lda, doublereal *taua, doublereal *b, integer *ldb, 
+	doublereal *taub, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dggsvd_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *n, integer *p, integer *k, integer *l, doublereal *a, 
+	integer *lda, doublereal *b, integer *ldb, doublereal *alpha, 
+	doublereal *beta, doublereal *u, integer *ldu, doublereal *v, integer 
+	*ldv, doublereal *q, integer *ldq, doublereal *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int dggsvp_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, doublereal *tola, doublereal *tolb, integer *k, integer 
+	*l, doublereal *u, integer *ldu, doublereal *v, integer *ldv, 
+	doublereal *q, integer *ldq, integer *iwork, doublereal *tau, 
+	doublereal *work, integer *info);
+ 
+/* Subroutine */ int dgtcon_(char *norm, integer *n, doublereal *dl, 
+	doublereal *d__, doublereal *du, doublereal *du2, integer *ipiv, 
+	doublereal *anorm, doublereal *rcond, doublereal *work, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int dgtrfs_(char *trans, integer *n, integer *nrhs, 
+	doublereal *dl, doublereal *d__, doublereal *du, doublereal *dlf, 
+	doublereal *df, doublereal *duf, doublereal *du2, integer *ipiv, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	ferr, doublereal *berr, doublereal *work, integer *iwork, integer *
+	info);
+ 
+/* Subroutine */ int dgtsv_(integer *n, integer *nrhs, doublereal *dl, 
+	doublereal *d__, doublereal *du, doublereal *b, integer *ldb, integer 
+	*info);
+ 
+/* Subroutine */ int dgtsvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, doublereal *dl, doublereal *d__, doublereal *du, doublereal *
+	dlf, doublereal *df, doublereal *duf, doublereal *du2, integer *ipiv, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int dgttrf_(integer *n, doublereal *dl, doublereal *d__, 
+	doublereal *du, doublereal *du2, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int dgttrs_(char *trans, integer *n, integer *nrhs, 
+	doublereal *dl, doublereal *d__, doublereal *du, doublereal *du2, 
+	integer *ipiv, doublereal *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int dgtts2_(integer *itrans, integer *n, integer *nrhs, 
+	doublereal *dl, doublereal *d__, doublereal *du, doublereal *du2, 
+	integer *ipiv, doublereal *b, integer *ldb);
+ 
+/* Subroutine */ int dhgeqz_(char *job, char *compq, char *compz, integer *n, 
+	integer *ilo, integer *ihi, doublereal *a, integer *lda, doublereal *
+	b, integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *
+	beta, doublereal *q, integer *ldq, doublereal *z__, integer *ldz, 
+	doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dhsein_(char *side, char *eigsrc, char *initv, logical *
+	select, integer *n, doublereal *h__, integer *ldh, doublereal *wr, 
+	doublereal *wi, doublereal *vl, integer *ldvl, doublereal *vr, 
+	integer *ldvr, integer *mm, integer *m, doublereal *work, integer *
+	ifaill, integer *ifailr, integer *info);
+ 
+/* Subroutine */ int dhseqr_(char *job, char *compz, integer *n, integer *ilo,
+	 integer *ihi, doublereal *h__, integer *ldh, doublereal *wr, 
+	doublereal *wi, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *lwork, integer *info);
+ 
+///* Subroutine */int dlabad_(doublereal *small, doublereal *large);
+/* Subroutine */int dlabad_(doublereal *smallnumber, doublereal *largenumber);//hirohito
+  
+/* Subroutine */ int dlabrd_(integer *m, integer *n, integer *nb, doublereal *
+	a, integer *lda, doublereal *d__, doublereal *e, doublereal *tauq, 
+	doublereal *taup, doublereal *x, integer *ldx, doublereal *y, integer 
+	*ldy);
+ 
+/* Subroutine */ int dlacon_(integer *n, doublereal *v, doublereal *x, 
+	integer *isgn, doublereal *est, integer *kase);
+ 
+/* Subroutine */ int dlacpy_(char *uplo, integer *m, integer *n, doublereal *
+	a, integer *lda, doublereal *b, integer *ldb);
+ 
+/* Subroutine */ int dladiv_(doublereal *a, doublereal *b, doublereal *c__, 
+	doublereal *d__, doublereal *p, doublereal *q);
+ 
+/* Subroutine */ int dlae2_(doublereal *a, doublereal *b, doublereal *c__, 
+	doublereal *rt1, doublereal *rt2);
+ 
+/* Subroutine */ int dlaebz_(integer *ijob, integer *nitmax, integer *n, 
+	integer *mmax, integer *minp, integer *nbmin, doublereal *abstol, 
+	doublereal *reltol, doublereal *pivmin, doublereal *d__, doublereal *
+	e, doublereal *e2, integer *nval, doublereal *ab, doublereal *c__, 
+	integer *mout, integer *nab, doublereal *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int dlaed0_(integer *icompq, integer *qsiz, integer *n, 
+	doublereal *d__, doublereal *e, doublereal *q, integer *ldq, 
+	doublereal *qstore, integer *ldqs, doublereal *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int dlaed1_(integer *n, doublereal *d__, doublereal *q, 
+	integer *ldq, integer *indxq, doublereal *rho, integer *cutpnt, 
+	doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dlaed2_(integer *k, integer *n, integer *n1, doublereal *
+	d__, doublereal *q, integer *ldq, integer *indxq, doublereal *rho, 
+	doublereal *z__, doublereal *dlamda, doublereal *w, doublereal *q2, 
+	integer *indx, integer *indxc, integer *indxp, integer *coltyp, 
+	integer *info);
+ 
+/* Subroutine */ int dlaed3_(integer *k, integer *n, integer *n1, doublereal *
+	d__, doublereal *q, integer *ldq, doublereal *rho, doublereal *dlamda,
+	 doublereal *q2, integer *indx, integer *ctot, doublereal *w, 
+	doublereal *s, integer *info);
+ 
+/* Subroutine */ int dlaed4_(integer *n, integer *i__, doublereal *d__, 
+	doublereal *z__, doublereal *delta, doublereal *rho, doublereal *dlam,
+	 integer *info);
+ 
+/* Subroutine */ int dlaed5_(integer *i__, doublereal *d__, doublereal *z__, 
+	doublereal *delta, doublereal *rho, doublereal *dlam);
+ 
+/* Subroutine */ int dlaed6_(integer *kniter, logical *orgati, doublereal *
+	rho, doublereal *d__, doublereal *z__, doublereal *finit, doublereal *
+	tau, integer *info);
+ 
+/* Subroutine */ int dlaed7_(integer *icompq, integer *n, integer *qsiz, 
+	integer *tlvls, integer *curlvl, integer *curpbm, doublereal *d__, 
+	doublereal *q, integer *ldq, integer *indxq, doublereal *rho, integer 
+	*cutpnt, doublereal *qstore, integer *qptr, integer *prmptr, integer *
+	perm, integer *givptr, integer *givcol, doublereal *givnum, 
+	doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dlaed8_(integer *icompq, integer *k, integer *n, integer 
+	*qsiz, doublereal *d__, doublereal *q, integer *ldq, integer *indxq, 
+	doublereal *rho, integer *cutpnt, doublereal *z__, doublereal *dlamda,
+	 doublereal *q2, integer *ldq2, doublereal *w, integer *perm, integer 
+	*givptr, integer *givcol, doublereal *givnum, integer *indxp, integer 
+	*indx, integer *info);
+ 
+/* Subroutine */ int dlaed9_(integer *k, integer *kstart, integer *kstop, 
+	integer *n, doublereal *d__, doublereal *q, integer *ldq, doublereal *
+	rho, doublereal *dlamda, doublereal *w, doublereal *s, integer *lds, 
+	integer *info);
+ 
+/* Subroutine */ int dlaeda_(integer *n, integer *tlvls, integer *curlvl, 
+	integer *curpbm, integer *prmptr, integer *perm, integer *givptr, 
+	integer *givcol, doublereal *givnum, doublereal *q, integer *qptr, 
+	doublereal *z__, doublereal *ztemp, integer *info);
+ 
+/* Subroutine */ int dlaein_(logical *rightv, logical *noinit, integer *n, 
+	doublereal *h__, integer *ldh, doublereal *wr, doublereal *wi, 
+	doublereal *vr, doublereal *vi, doublereal *b, integer *ldb, 
+	doublereal *work, doublereal *eps3, doublereal *smlnum, doublereal *
+	bignum, integer *info);
+ 
+/* Subroutine */ int dlaev2_(doublereal *a, doublereal *b, doublereal *c__, 
+	doublereal *rt1, doublereal *rt2, doublereal *cs1, doublereal *sn1);
+ 
+/* Subroutine */ int dlaexc_(logical *wantq, integer *n, doublereal *t, 
+	integer *ldt, doublereal *q, integer *ldq, integer *j1, integer *n1, 
+	integer *n2, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dlag2_(doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, doublereal *safmin, doublereal *scale1, doublereal *
+	scale2, doublereal *wr1, doublereal *wr2, doublereal *wi);
+ 
+/* Subroutine */ int dlags2_(logical *upper, doublereal *a1, doublereal *a2, 
+	doublereal *a3, doublereal *b1, doublereal *b2, doublereal *b3, 
+	doublereal *csu, doublereal *snu, doublereal *csv, doublereal *snv, 
+	doublereal *csq, doublereal *snq);
+ 
+/* Subroutine */ int dlagtf_(integer *n, doublereal *a, doublereal *lambda, 
+	doublereal *b, doublereal *c__, doublereal *tol, doublereal *d__, 
+	integer *in, integer *info);
+ 
+/* Subroutine */ int dlagtm_(char *trans, integer *n, integer *nrhs, 
+	doublereal *alpha, doublereal *dl, doublereal *d__, doublereal *du, 
+	doublereal *x, integer *ldx, doublereal *beta, doublereal *b, integer 
+	*ldb);
+ 
+/* Subroutine */ int dlagts_(integer *job, integer *n, doublereal *a, 
+	doublereal *b, doublereal *c__, doublereal *d__, integer *in, 
+	doublereal *y, doublereal *tol, integer *info);
+ 
+/* Subroutine */ int dlagv2_(doublereal *a, integer *lda, doublereal *b, 
+	integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *
+	beta, doublereal *csl, doublereal *snl, doublereal *csr, doublereal *
+	snr);
+ 
+/* Subroutine */ int dlahqr_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, doublereal *h__, integer *ldh, doublereal 
+	*wr, doublereal *wi, integer *iloz, integer *ihiz, doublereal *z__, 
+	integer *ldz, integer *info);
+ 
+/* Subroutine */ int dlahrd_(integer *n, integer *k, integer *nb, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *t, integer *ldt, 
+	doublereal *y, integer *ldy);
+ 
+/* Subroutine */ int dlaic1_(integer *job, integer *j, doublereal *x, 
+	doublereal *sest, doublereal *w, doublereal *gamma, doublereal *
+	sestpr, doublereal *s, doublereal *c__);
+ 
+/* Subroutine */ int dlaln2_(logical *ltrans, integer *na, integer *nw, 
+	doublereal *smin, doublereal *ca, doublereal *a, integer *lda, 
+	doublereal *d1, doublereal *d2, doublereal *b, integer *ldb, 
+	doublereal *wr, doublereal *wi, doublereal *x, integer *ldx, 
+	doublereal *scale, doublereal *xnorm, integer *info);
+ 
+/* Subroutine */ int dlals0_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, integer *nrhs, doublereal *b, integer *ldb, doublereal 
+	*bx, integer *ldbx, integer *perm, integer *givptr, integer *givcol, 
+	integer *ldgcol, doublereal *givnum, integer *ldgnum, doublereal *
+	poles, doublereal *difl, doublereal *difr, doublereal *z__, integer *
+	k, doublereal *c__, doublereal *s, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dlalsa_(integer *icompq, integer *smlsiz, integer *n, 
+	integer *nrhs, doublereal *b, integer *ldb, doublereal *bx, integer *
+	ldbx, doublereal *u, integer *ldu, doublereal *vt, integer *k, 
+	doublereal *difl, doublereal *difr, doublereal *z__, doublereal *
+	poles, integer *givptr, integer *givcol, integer *ldgcol, integer *
+	perm, doublereal *givnum, doublereal *c__, doublereal *s, doublereal *
+	work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dlalsd_(char *uplo, integer *smlsiz, integer *n, integer 
+	*nrhs, doublereal *d__, doublereal *e, doublereal *b, integer *ldb, 
+	doublereal *rcond, integer *rank, doublereal *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int dlamc1_(integer *beta, integer *t, logical *rnd, logical 
+	*ieee1);
+ 
+/* Subroutine */ int dlamc2_(integer *beta, integer *t, logical *rnd, 
+	doublereal *eps, integer *emin, doublereal *rmin, integer *emax, 
+	doublereal *rmax);
+ 
+/* Subroutine */ int dlamc4_(integer *emin, doublereal *start, integer *base);
+ 
+/* Subroutine */ int dlamc5_(integer *beta, integer *p, integer *emin, 
+	logical *ieee, integer *emax, doublereal *rmax);
+ 
+/* Subroutine */ int dlamrg_(integer *n1, integer *n2, doublereal *a, integer 
+	*dtrd1, integer *dtrd2, integer *index);
+ 
+/* Subroutine */ int dlanv2_(doublereal *a, doublereal *b, doublereal *c__, 
+	doublereal *d__, doublereal *rt1r, doublereal *rt1i, doublereal *rt2r,
+	 doublereal *rt2i, doublereal *cs, doublereal *sn);
+ 
+/* Subroutine */ int dlapll_(integer *n, doublereal *x, integer *incx, 
+	doublereal *y, integer *incy, doublereal *ssmin);
+ 
+/* Subroutine */ int dlapmt_(logical *forwrd, integer *m, integer *n, 
+	doublereal *x, integer *ldx, integer *k);
+ 
+/* Subroutine */ int dlaqgb_(integer *m, integer *n, integer *kl, integer *ku,
+	 doublereal *ab, integer *ldab, doublereal *r__, doublereal *c__, 
+	doublereal *rowcnd, doublereal *colcnd, doublereal *amax, char *equed);
+ 
+/* Subroutine */ int dlaqge_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *r__, doublereal *c__, doublereal *rowcnd, doublereal 
+	*colcnd, doublereal *amax, char *equed);
+ 
+/* Subroutine */ int dlaqp2_(integer *m, integer *n, integer *offset, 
+	doublereal *a, integer *lda, integer *jpvt, doublereal *tau, 
+	doublereal *vn1, doublereal *vn2, doublereal *work);
+ 
+/* Subroutine */ int dlaqps_(integer *m, integer *n, integer *offset, integer 
+	*nb, integer *kb, doublereal *a, integer *lda, integer *jpvt, 
+	doublereal *tau, doublereal *vn1, doublereal *vn2, doublereal *auxv, 
+	doublereal *f, integer *ldf);
+ 
+/* Subroutine */ int dlaqsb_(char *uplo, integer *n, integer *kd, doublereal *
+	ab, integer *ldab, doublereal *s, doublereal *scond, doublereal *amax,
+	 char *equed);
+ 
+/* Subroutine */ int dlaqsp_(char *uplo, integer *n, doublereal *ap, 
+	doublereal *s, doublereal *scond, doublereal *amax, char *equed);
+ 
+/* Subroutine */ int dlaqsy_(char *uplo, integer *n, doublereal *a, integer *
+	lda, doublereal *s, doublereal *scond, doublereal *amax, char *equed);
+ 
+/* Subroutine */ int dlaqtr_(logical *ltran, logical *lreal, integer *n, 
+	doublereal *t, integer *ldt, doublereal *b, doublereal *w, doublereal 
+	*scale, doublereal *x, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dlar1v_(integer *n, integer *b1, integer *bn, doublereal 
+	*sigma, doublereal *d__, doublereal *l, doublereal *ld, doublereal *
+	lld, doublereal *gersch, doublereal *z__, doublereal *ztz, doublereal 
+	*mingma, integer *r__, integer *isuppz, doublereal *work);
+ 
+/* Subroutine */ int dlar2v_(integer *n, doublereal *x, doublereal *y, 
+	doublereal *z__, integer *incx, doublereal *c__, doublereal *s, 
+	integer *incc);
+ 
+/* Subroutine */ int dlarf_(char *side, integer *m, integer *n, doublereal *v,
+	 integer *incv, doublereal *tau, doublereal *c__, integer *ldc, 
+	doublereal *work);
+ 
+/* Subroutine */ int dlarfb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, doublereal *v, integer *
+	ldv, doublereal *t, integer *ldt, doublereal *c__, integer *ldc, 
+	doublereal *work, integer *ldwork);
+ 
+/* Subroutine */ int dlarfg_(integer *n, doublereal *alpha, doublereal *x, 
+	integer *incx, doublereal *tau);
+ 
+/* Subroutine */ int dlarft_(char *direct, char *storev, integer *n, integer *
+	k, doublereal *v, integer *ldv, doublereal *tau, doublereal *t, 
+	integer *ldt);
+ 
+/* Subroutine */ int dlarfx_(char *side, integer *m, integer *n, doublereal *
+	v, doublereal *tau, doublereal *c__, integer *ldc, doublereal *work);
+ 
+/* Subroutine */ int dlargv_(integer *n, doublereal *x, integer *incx, 
+	doublereal *y, integer *incy, doublereal *c__, integer *incc);
+ 
+/* Subroutine */ int dlarnv_(integer *idist, integer *iseed, integer *n, 
+	doublereal *x);
+ 
+/* Subroutine */ int dlarrb_(integer *n, doublereal *d__, doublereal *l, 
+	doublereal *ld, doublereal *lld, integer *ifirst, integer *ilast, 
+	doublereal *sigma, doublereal *reltol, doublereal *w, doublereal *
+	wgap, doublereal *werr, doublereal *work, integer *iwork, integer *
+	info);
+ 
+/* Subroutine */ int dlarre_(integer *n, doublereal *d__, doublereal *e, 
+	doublereal *tol, integer *nsplit, integer *isplit, integer *m, 
+	doublereal *w, doublereal *woff, doublereal *gersch, doublereal *work,
+	 integer *info);
+ 
+/* Subroutine */ int dlarrf_(integer *n, doublereal *d__, doublereal *l, 
+	doublereal *ld, doublereal *lld, integer *ifirst, integer *ilast, 
+	doublereal *w, doublereal *dplus, doublereal *lplus, doublereal *work,
+	 integer *iwork, integer *info);
+ 
+/* Subroutine */ int dlarrv_(integer *n, doublereal *d__, doublereal *l, 
+	integer *isplit, integer *m, doublereal *w, integer *iblock, 
+	doublereal *gersch, doublereal *tol, doublereal *z__, integer *ldz, 
+	integer *isuppz, doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dlartg_(doublereal *f, doublereal *g, doublereal *cs, 
+	doublereal *sn, doublereal *r__);
+ 
+/* Subroutine */ int dlartv_(integer *n, doublereal *x, integer *incx, 
+	doublereal *y, integer *incy, doublereal *c__, doublereal *s, integer 
+	*incc);
+ 
+/* Subroutine */ int dlaruv_(integer *iseed, integer *n, doublereal *x);
+ 
+/* Subroutine */ int dlarz_(char *side, integer *m, integer *n, integer *l, 
+	doublereal *v, integer *incv, doublereal *tau, doublereal *c__, 
+	integer *ldc, doublereal *work);
+ 
+/* Subroutine */ int dlarzb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, integer *l, doublereal *v,
+	 integer *ldv, doublereal *t, integer *ldt, doublereal *c__, integer *
+	ldc, doublereal *work, integer *ldwork);
+ 
+/* Subroutine */ int dlarzt_(char *direct, char *storev, integer *n, integer *
+	k, doublereal *v, integer *ldv, doublereal *tau, doublereal *t, 
+	integer *ldt);
+ 
+/* Subroutine */ int dlas2_(doublereal *f, doublereal *g, doublereal *h__, 
+	doublereal *ssmin, doublereal *ssmax);
+ 
+/* Subroutine */ int dlascl_(char *type__, integer *kl, integer *ku, 
+	doublereal *cfrom, doublereal *cto, integer *m, integer *n, 
+	doublereal *a, integer *lda, integer *info);
+ 
+/* Subroutine */ int dlasd0_(integer *n, integer *sqre, doublereal *d__, 
+	doublereal *e, doublereal *u, integer *ldu, doublereal *vt, integer *
+	ldvt, integer *smlsiz, integer *iwork, doublereal *work, integer *
+	info);
+ 
+/* Subroutine */ int dlasd1_(integer *nl, integer *nr, integer *sqre, 
+	doublereal *d__, doublereal *alpha, doublereal *beta, doublereal *u, 
+	integer *ldu, doublereal *vt, integer *ldvt, integer *idxq, integer *
+	iwork, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dlasd2_(integer *nl, integer *nr, integer *sqre, integer 
+	*k, doublereal *d__, doublereal *z__, doublereal *alpha, doublereal *
+	beta, doublereal *u, integer *ldu, doublereal *vt, integer *ldvt, 
+	doublereal *dsigma, doublereal *u2, integer *ldu2, doublereal *vt2, 
+	integer *ldvt2, integer *idxp, integer *idx, integer *idxc, integer *
+	idxq, integer *coltyp, integer *info);
+ 
+/* Subroutine */ int dlasd3_(integer *nl, integer *nr, integer *sqre, integer 
+	*k, doublereal *d__, doublereal *q, integer *ldq, doublereal *dsigma, 
+	doublereal *u, integer *ldu, doublereal *u2, integer *ldu2, 
+	doublereal *vt, integer *ldvt, doublereal *vt2, integer *ldvt2, 
+	integer *idxc, integer *ctot, doublereal *z__, integer *info);
+ 
+/* Subroutine */ int dlasd4_(integer *n, integer *i__, doublereal *d__, 
+	doublereal *z__, doublereal *delta, doublereal *rho, doublereal *
+	sigma, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dlasd5_(integer *i__, doublereal *d__, doublereal *z__, 
+	doublereal *delta, doublereal *rho, doublereal *dsigma, doublereal *
+	work);
+ 
+/* Subroutine */ int dlasd6_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, doublereal *d__, doublereal *vf, doublereal *vl, 
+	doublereal *alpha, doublereal *beta, integer *idxq, integer *perm, 
+	integer *givptr, integer *givcol, integer *ldgcol, doublereal *givnum,
+	 integer *ldgnum, doublereal *poles, doublereal *difl, doublereal *
+	difr, doublereal *z__, integer *k, doublereal *c__, doublereal *s, 
+	doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dlasd7_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, integer *k, doublereal *d__, doublereal *z__, 
+	doublereal *zw, doublereal *vf, doublereal *vfw, doublereal *vl, 
+	doublereal *vlw, doublereal *alpha, doublereal *beta, doublereal *
+	dsigma, integer *idx, integer *idxp, integer *idxq, integer *perm, 
+	integer *givptr, integer *givcol, integer *ldgcol, doublereal *givnum,
+	 integer *ldgnum, doublereal *c__, doublereal *s, integer *info);
+ 
+/* Subroutine */ int dlasd8_(integer *icompq, integer *k, doublereal *d__, 
+	doublereal *z__, doublereal *vf, doublereal *vl, doublereal *difl, 
+	doublereal *difr, integer *lddifr, doublereal *dsigma, doublereal *
+	work, integer *info);
+ 
+/* Subroutine */ int dlasd9_(integer *icompq, integer *ldu, integer *k, 
+	doublereal *d__, doublereal *z__, doublereal *vf, doublereal *vl, 
+	doublereal *difl, doublereal *difr, doublereal *dsigma, doublereal *
+	work, integer *info);
+ 
+/* Subroutine */ int dlasda_(integer *icompq, integer *smlsiz, integer *n, 
+	integer *sqre, doublereal *d__, doublereal *e, doublereal *u, integer 
+	*ldu, doublereal *vt, integer *k, doublereal *difl, doublereal *difr, 
+	doublereal *z__, doublereal *poles, integer *givptr, integer *givcol, 
+	integer *ldgcol, integer *perm, doublereal *givnum, doublereal *c__, 
+	doublereal *s, doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dlasdq_(char *uplo, integer *sqre, integer *n, integer *
+	ncvt, integer *nru, integer *ncc, doublereal *d__, doublereal *e, 
+	doublereal *vt, integer *ldvt, doublereal *u, integer *ldu, 
+	doublereal *c__, integer *ldc, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dlasdt_(integer *n, integer *lvl, integer *nd, integer *
+	inode, integer *ndiml, integer *ndimr, integer *msub);
+ 
+/* Subroutine */ int dlaset_(char *uplo, integer *m, integer *n, doublereal *
+	alpha, doublereal *beta, doublereal *a, integer *lda);
+ 
+/* Subroutine */ int dlasq1_(integer *n, doublereal *d__, doublereal *e, 
+	doublereal *work, integer *info);
+ 
+/* Subroutine */ int dlasq2_(integer *n, doublereal *z__, integer *info);
+ 
+/* Subroutine */ int dlasq3_(integer *i0, integer *n0, doublereal *z__, 
+	integer *pp, doublereal *dmin__, doublereal *sigma, doublereal *desig,
+	 doublereal *qmax, integer *nfail, integer *iter, integer *ndiv, 
+	logical *ieee);
+ 
+/* Subroutine */ int dlasq4_(integer *i0, integer *n0, doublereal *z__, 
+	integer *pp, integer *n0in, doublereal *dmin__, doublereal *dmin1, 
+	doublereal *dmin2, doublereal *dn, doublereal *dn1, doublereal *dn2, 
+	doublereal *tau, integer *ttype);
+ 
+/* Subroutine */ int dlasq5_(integer *i0, integer *n0, doublereal *z__, 
+	integer *pp, doublereal *tau, doublereal *dmin__, doublereal *dmin1, 
+	doublereal *dmin2, doublereal *dn, doublereal *dnm1, doublereal *dnm2,
+	 logical *ieee);
+ 
+/* Subroutine */ int dlasq6_(integer *i0, integer *n0, doublereal *z__, 
+	integer *pp, doublereal *dmin__, doublereal *dmin1, doublereal *dmin2,
+	 doublereal *dn, doublereal *dnm1, doublereal *dnm2);
+ 
+/* Subroutine */ int dlasr_(char *side, char *pivot, char *direct, integer *m,
+	 integer *n, doublereal *c__, doublereal *s, doublereal *a, integer *
+	lda);
+ 
+/* Subroutine */ int dlasrt_(char *id, integer *n, doublereal *d__, integer *
+	info);
+ 
+/* Subroutine */ int dlassq_(integer *n, doublereal *x, integer *incx, 
+	doublereal *scale, doublereal *sumsq);
+ 
+/* Subroutine */ int dlasv2_(doublereal *f, doublereal *g, doublereal *h__, 
+	doublereal *ssmin, doublereal *ssmax, doublereal *snr, doublereal *
+	csr, doublereal *snl, doublereal *csl);
+ 
+/* Subroutine */ int dlaswp_(integer *n, doublereal *a, integer *lda, integer 
+	*k1, integer *k2, integer *ipiv, integer *incx);
+ 
+/* Subroutine */ int dlasy2_(logical *ltranl, logical *ltranr, integer *isgn, 
+	integer *n1, integer *n2, doublereal *tl, integer *ldtl, doublereal *
+	tr, integer *ldtr, doublereal *b, integer *ldb, doublereal *scale, 
+	doublereal *x, integer *ldx, doublereal *xnorm, integer *info);
+ 
+/* Subroutine */ int dlasyf_(char *uplo, integer *n, integer *nb, integer *kb,
+	 doublereal *a, integer *lda, integer *ipiv, doublereal *w, integer *
+	ldw, integer *info);
+ 
+/* Subroutine */ int dlatbs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, integer *kd, doublereal *ab, integer *ldab, 
+	doublereal *x, doublereal *scale, doublereal *cnorm, integer *info);
+ 
+/* Subroutine */ int dlatdf_(integer *ijob, integer *n, doublereal *z__, 
+	integer *ldz, doublereal *rhs, doublereal *rdsum, doublereal *rdscal, 
+	integer *ipiv, integer *jpiv);
+ 
+/* Subroutine */ int dlatps_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, doublereal *ap, doublereal *x, doublereal *scale, 
+	doublereal *cnorm, integer *info);
+ 
+/* Subroutine */ int dlatrd_(char *uplo, integer *n, integer *nb, doublereal *
+	a, integer *lda, doublereal *e, doublereal *tau, doublereal *w, 
+	integer *ldw);
+ 
+/* Subroutine */ int dlatrs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, doublereal *a, integer *lda, doublereal *x, 
+	doublereal *scale, doublereal *cnorm, integer *info);
+ 
+/* Subroutine */ int dlatrz_(integer *m, integer *n, integer *l, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work);
+ 
+/* Subroutine */ int dlatzm_(char *side, integer *m, integer *n, doublereal *
+	v, integer *incv, doublereal *tau, doublereal *c1, doublereal *c2, 
+	integer *ldc, doublereal *work);
+ 
+/* Subroutine */ int dlauu2_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *info);
+ 
+/* Subroutine */ int dlauum_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *info);
+ 
+/* Subroutine */ int dopgtr_(char *uplo, integer *n, doublereal *ap, 
+	doublereal *tau, doublereal *q, integer *ldq, doublereal *work, 
+	integer *info);
+ 
+/* Subroutine */ int dopmtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, doublereal *ap, doublereal *tau, doublereal *c__, integer 
+	*ldc, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dorg2l_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dorg2r_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dorgbr_(char *vect, integer *m, integer *n, integer *k, 
+	doublereal *a, integer *lda, doublereal *tau, doublereal *work, 
+	integer *lwork, integer *info);
+ 
+/* Subroutine */ int dorghr_(integer *n, integer *ilo, integer *ihi, 
+	doublereal *a, integer *lda, doublereal *tau, doublereal *work, 
+	integer *lwork, integer *info);
+ 
+/* Subroutine */ int dorgl2_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dorglq_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dorgql_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dorgqr_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dorgr2_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dorgrq_(integer *m, integer *n, integer *k, doublereal *
+	a, integer *lda, doublereal *tau, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dorgtr_(char *uplo, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dorm2l_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dorm2r_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dormbr_(char *vect, char *side, char *trans, integer *m, 
+	integer *n, integer *k, doublereal *a, integer *lda, doublereal *tau, 
+	doublereal *c__, integer *ldc, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dormhr_(char *side, char *trans, integer *m, integer *n, 
+	integer *ilo, integer *ihi, doublereal *a, integer *lda, doublereal *
+	tau, doublereal *c__, integer *ldc, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dorml2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dormlq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dormql_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dormqr_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dormr2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dormr3_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, doublereal *a, integer *lda, doublereal *tau, 
+	doublereal *c__, integer *ldc, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dormrq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dormrz_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, doublereal *a, integer *lda, doublereal *tau, 
+	doublereal *c__, integer *ldc, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dormtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, doublereal *a, integer *lda, doublereal *tau, doublereal *
+	c__, integer *ldc, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dpbcon_(char *uplo, integer *n, integer *kd, doublereal *
+	ab, integer *ldab, doublereal *anorm, doublereal *rcond, doublereal *
+	work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dpbequ_(char *uplo, integer *n, integer *kd, doublereal *
+	ab, integer *ldab, doublereal *s, doublereal *scond, doublereal *amax,
+	 integer *info);
+ 
+/* Subroutine */ int dpbrfs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, doublereal *ab, integer *ldab, doublereal *afb, integer *ldafb, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	ferr, doublereal *berr, doublereal *work, integer *iwork, integer *
+	info);
+ 
+/* Subroutine */ int dpbstf_(char *uplo, integer *n, integer *kd, doublereal *
+	ab, integer *ldab, integer *info);
+ 
+/* Subroutine */ int dpbsv_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, doublereal *ab, integer *ldab, doublereal *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int dpbsvx_(char *fact, char *uplo, integer *n, integer *kd, 
+	integer *nrhs, doublereal *ab, integer *ldab, doublereal *afb, 
+	integer *ldafb, char *equed, doublereal *s, doublereal *b, integer *
+	ldb, doublereal *x, integer *ldx, doublereal *rcond, doublereal *ferr,
+	 doublereal *berr, doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dpbtf2_(char *uplo, integer *n, integer *kd, doublereal *
+	ab, integer *ldab, integer *info);
+ 
+/* Subroutine */ int dpbtrf_(char *uplo, integer *n, integer *kd, doublereal *
+	ab, integer *ldab, integer *info);
+ 
+/* Subroutine */ int dpbtrs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, doublereal *ab, integer *ldab, doublereal *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int dpocon_(char *uplo, integer *n, doublereal *a, integer *
+	lda, doublereal *anorm, doublereal *rcond, doublereal *work, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int dpoequ_(integer *n, doublereal *a, integer *lda, 
+	doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+ 
+/* Subroutine */ int dporfs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	ferr, doublereal *berr, doublereal *work, integer *iwork, integer *
+	info);
+ 
+/* Subroutine */ int dposv_(char *uplo, integer *n, integer *nrhs, doublereal 
+	*a, integer *lda, doublereal *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int dposvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	char *equed, doublereal *s, doublereal *b, integer *ldb, doublereal *
+	x, integer *ldx, doublereal *rcond, doublereal *ferr, doublereal *
+	berr, doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dpotf2_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *info);
+ 
+/* Subroutine */ int dpotrf_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *info);
+ 
+/* Subroutine */ int dpotri_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *info);
+ 
+/* Subroutine */ int dpotrs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+	info);
+ 
+/* Subroutine */ int dppcon_(char *uplo, integer *n, doublereal *ap, 
+	doublereal *anorm, doublereal *rcond, doublereal *work, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int dppequ_(char *uplo, integer *n, doublereal *ap, 
+	doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+ 
+/* Subroutine */ int dpprfs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *ap, doublereal *afp, doublereal *b, integer *ldb, 
+	doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dppsv_(char *uplo, integer *n, integer *nrhs, doublereal 
+	*ap, doublereal *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int dppsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublereal *ap, doublereal *afp, char *equed, doublereal *s, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int dpptrf_(char *uplo, integer *n, doublereal *ap, integer *
+	info);
+ 
+/* Subroutine */ int dpptri_(char *uplo, integer *n, doublereal *ap, integer *
+	info);
+ 
+/* Subroutine */ int dpptrs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *ap, doublereal *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int dptcon_(integer *n, doublereal *d__, doublereal *e, 
+	doublereal *anorm, doublereal *rcond, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dpteqr_(char *compz, integer *n, doublereal *d__, 
+	doublereal *e, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *info);
+ 
+/* Subroutine */ int dptrfs_(integer *n, integer *nrhs, doublereal *d__, 
+	doublereal *e, doublereal *df, doublereal *ef, doublereal *b, integer 
+	*ldb, doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr,
+	 doublereal *work, integer *info);
+ 
+/* Subroutine */ int dptsv_(integer *n, integer *nrhs, doublereal *d__, 
+	doublereal *e, doublereal *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int dptsvx_(char *fact, integer *n, integer *nrhs, 
+	doublereal *d__, doublereal *e, doublereal *df, doublereal *ef, 
+	doublereal *b, integer *ldb, doublereal *x, integer *ldx, doublereal *
+	rcond, doublereal *ferr, doublereal *berr, doublereal *work, integer *
+	info);
+ 
+/* Subroutine */ int dpttrf_(integer *n, doublereal *d__, doublereal *e, 
+	integer *info);
+ 
+/* Subroutine */ int dpttrs_(integer *n, integer *nrhs, doublereal *d__, 
+	doublereal *e, doublereal *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int dptts2_(integer *n, integer *nrhs, doublereal *d__, 
+	doublereal *e, doublereal *b, integer *ldb);
+ 
+/* Subroutine */ int drscl_(integer *n, doublereal *sa, doublereal *sx, 
+	integer *incx);
+ 
+/* Subroutine */ int dsbev_(char *jobz, char *uplo, integer *n, integer *kd, 
+	doublereal *ab, integer *ldab, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dsbevd_(char *jobz, char *uplo, integer *n, integer *kd, 
+	doublereal *ab, integer *ldab, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *lwork, integer *iwork, 
+	integer *liwork, integer *info);
+ 
+/* Subroutine */ int dsbevx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *kd, doublereal *ab, integer *ldab, doublereal *q, integer *
+	ldq, doublereal *vl, doublereal *vu, integer *il, integer *iu, 
+	doublereal *abstol, integer *m, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *iwork, integer *ifail, 
+	integer *info);
+ 
+/* Subroutine */ int dsbgst_(char *vect, char *uplo, integer *n, integer *ka, 
+	integer *kb, doublereal *ab, integer *ldab, doublereal *bb, integer *
+	ldbb, doublereal *x, integer *ldx, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dsbgv_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, doublereal *ab, integer *ldab, doublereal *bb, integer *
+	ldbb, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *info);
+ 
+/* Subroutine */ int dsbgvd_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, doublereal *ab, integer *ldab, doublereal *bb, integer *
+	ldbb, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int dsbgvx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *ka, integer *kb, doublereal *ab, integer *ldab, doublereal *
+	bb, integer *ldbb, doublereal *q, integer *ldq, doublereal *vl, 
+	doublereal *vu, integer *il, integer *iu, doublereal *abstol, integer 
+	*m, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int dsbtrd_(char *vect, char *uplo, integer *n, integer *kd, 
+	doublereal *ab, integer *ldab, doublereal *d__, doublereal *e, 
+	doublereal *q, integer *ldq, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dspcon_(char *uplo, integer *n, doublereal *ap, integer *
+	ipiv, doublereal *anorm, doublereal *rcond, doublereal *work, integer 
+	*iwork, integer *info);
+ 
+/* Subroutine */ int dspev_(char *jobz, char *uplo, integer *n, doublereal *
+	ap, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *info);
+ 
+/* Subroutine */ int dspevd_(char *jobz, char *uplo, integer *n, doublereal *
+	ap, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int dspevx_(char *jobz, char *range, char *uplo, integer *n, 
+	doublereal *ap, doublereal *vl, doublereal *vu, integer *il, integer *
+	iu, doublereal *abstol, integer *m, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *iwork, integer *ifail, 
+	integer *info);
+ 
+/* Subroutine */ int dspgst_(integer *itype, char *uplo, integer *n, 
+	doublereal *ap, doublereal *bp, integer *info);
+ 
+/* Subroutine */ int dspgv_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublereal *ap, doublereal *bp, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dspgvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublereal *ap, doublereal *bp, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *lwork, integer *iwork, 
+	integer *liwork, integer *info);
+ 
+/* Subroutine */ int dspgvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, doublereal *ap, doublereal *bp, doublereal *vl, 
+	doublereal *vu, integer *il, integer *iu, doublereal *abstol, integer 
+	*m, doublereal *w, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int dsprfs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *ap, doublereal *afp, integer *ipiv, doublereal *b, 
+	integer *ldb, doublereal *x, integer *ldx, doublereal *ferr, 
+	doublereal *berr, doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dspsv_(char *uplo, integer *n, integer *nrhs, doublereal 
+	*ap, integer *ipiv, doublereal *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int dspsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublereal *ap, doublereal *afp, integer *ipiv, doublereal *b, 
+	integer *ldb, doublereal *x, integer *ldx, doublereal *rcond, 
+	doublereal *ferr, doublereal *berr, doublereal *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int dsptrd_(char *uplo, integer *n, doublereal *ap, 
+	doublereal *d__, doublereal *e, doublereal *tau, integer *info);
+ 
+/* Subroutine */ int dsptrf_(char *uplo, integer *n, doublereal *ap, integer *
+	ipiv, integer *info);
+ 
+/* Subroutine */ int dsptri_(char *uplo, integer *n, doublereal *ap, integer *
+	ipiv, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dsptrs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *ap, integer *ipiv, doublereal *b, integer *ldb, integer *
+	info);
+ 
+/* Subroutine */ int dstebz_(char *range, char *order, integer *n, doublereal 
+	*vl, doublereal *vu, integer *il, integer *iu, doublereal *abstol, 
+	doublereal *d__, doublereal *e, integer *m, integer *nsplit, 
+	doublereal *w, integer *iblock, integer *isplit, doublereal *work, 
+	integer *iwork, integer *info);
+ 
+/* Subroutine */ int dstedc_(char *compz, integer *n, doublereal *d__, 
+	doublereal *e, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int dstegr_(char *jobz, char *range, integer *n, doublereal *
+	d__, doublereal *e, doublereal *vl, doublereal *vu, integer *il, 
+	integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublereal *z__, integer *ldz, integer *isuppz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int dstein_(integer *n, doublereal *d__, doublereal *e, 
+	integer *m, doublereal *w, integer *iblock, integer *isplit, 
+	doublereal *z__, integer *ldz, doublereal *work, integer *iwork, 
+	integer *ifail, integer *info);
+ 
+/* Subroutine */ int dsteqr_(char *compz, integer *n, doublereal *d__, 
+	doublereal *e, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *info);
+ 
+/* Subroutine */ int dsterf_(integer *n, doublereal *d__, doublereal *e, 
+	integer *info);
+ 
+/* Subroutine */ int dstev_(char *jobz, integer *n, doublereal *d__, 
+	doublereal *e, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *info);
+ 
+/* Subroutine */ int dstevd_(char *jobz, integer *n, doublereal *d__, 
+	doublereal *e, doublereal *z__, integer *ldz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int dstevr_(char *jobz, char *range, integer *n, doublereal *
+	d__, doublereal *e, doublereal *vl, doublereal *vu, integer *il, 
+	integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublereal *z__, integer *ldz, integer *isuppz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int dstevx_(char *jobz, char *range, integer *n, doublereal *
+	d__, doublereal *e, doublereal *vl, doublereal *vu, integer *il, 
+	integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublereal *z__, integer *ldz, doublereal *work, integer *iwork, 
+	integer *ifail, integer *info);
+ 
+/* Subroutine */ int dsycon_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *ipiv, doublereal *anorm, doublereal *rcond, doublereal *
+	work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dsyev_(char *jobz, char *uplo, integer *n, doublereal *a,
+	 integer *lda, doublereal *w, doublereal *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int dsyevd_(char *jobz, char *uplo, integer *n, doublereal *
+	a, integer *lda, doublereal *w, doublereal *work, integer *lwork, 
+	integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int dsyevr_(char *jobz, char *range, char *uplo, integer *n, 
+	doublereal *a, integer *lda, doublereal *vl, doublereal *vu, integer *
+	il, integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublereal *z__, integer *ldz, integer *isuppz, doublereal *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int dsyevx_(char *jobz, char *range, char *uplo, integer *n, 
+	doublereal *a, integer *lda, doublereal *vl, doublereal *vu, integer *
+	il, integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublereal *z__, integer *ldz, doublereal *work, integer *lwork, 
+	integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int dsygs2_(integer *itype, char *uplo, integer *n, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+	info);
+ 
+/* Subroutine */ int dsygst_(integer *itype, char *uplo, integer *n, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, integer *
+	info);
+ 
+/* Subroutine */ int dsygv_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *w, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dsygvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *w, doublereal *work, integer *lwork, integer *iwork, 
+	integer *liwork, integer *info);
+ 
+/* Subroutine */ int dsygvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, doublereal *a, integer *lda, doublereal *b, integer 
+	*ldb, doublereal *vl, doublereal *vu, integer *il, integer *iu, 
+	doublereal *abstol, integer *m, doublereal *w, doublereal *z__, 
+	integer *ldz, doublereal *work, integer *lwork, integer *iwork, 
+	integer *ifail, integer *info);
+ 
+/* Subroutine */ int dsyrfs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, doublereal *af, integer *ldaf, integer *
+	ipiv, doublereal *b, integer *ldb, doublereal *x, integer *ldx, 
+	doublereal *ferr, doublereal *berr, doublereal *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int dsysv_(char *uplo, integer *n, integer *nrhs, doublereal 
+	*a, integer *lda, integer *ipiv, doublereal *b, integer *ldb, 
+	doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dsysvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublereal *a, integer *lda, doublereal *af, integer *ldaf, 
+	integer *ipiv, doublereal *b, integer *ldb, doublereal *x, integer *
+	ldx, doublereal *rcond, doublereal *ferr, doublereal *berr, 
+	doublereal *work, integer *lwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dsytd2_(char *uplo, integer *n, doublereal *a, integer *
+	lda, doublereal *d__, doublereal *e, doublereal *tau, integer *info);
+ 
+/* Subroutine */ int dsytf2_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int dsytrd_(char *uplo, integer *n, doublereal *a, integer *
+	lda, doublereal *d__, doublereal *e, doublereal *tau, doublereal *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dsytrf_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *ipiv, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dsytri_(char *uplo, integer *n, doublereal *a, integer *
+	lda, integer *ipiv, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dsytrs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *a, integer *lda, integer *ipiv, doublereal *b, integer *
+	ldb, integer *info);
+ 
+/* Subroutine */ int dtbcon_(char *norm, char *uplo, char *diag, integer *n, 
+	integer *kd, doublereal *ab, integer *ldab, doublereal *rcond, 
+	doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dtbrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, doublereal *ab, integer *ldab, doublereal 
+	*b, integer *ldb, doublereal *x, integer *ldx, doublereal *ferr, 
+	doublereal *berr, doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dtbtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, doublereal *ab, integer *ldab, doublereal 
+	*b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int dtgevc_(char *side, char *howmny, logical *select, 
+	integer *n, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, integer 
+	*mm, integer *m, doublereal *work, integer *info);
+ 
+/* Subroutine */ int dtgex2_(logical *wantq, logical *wantz, integer *n, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+	q, integer *ldq, doublereal *z__, integer *ldz, integer *j1, integer *
+	n1, integer *n2, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dtgexc_(logical *wantq, logical *wantz, integer *n, 
+	doublereal *a, integer *lda, doublereal *b, integer *ldb, doublereal *
+	q, integer *ldq, doublereal *z__, integer *ldz, integer *ifst, 
+	integer *ilst, doublereal *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int dtgsen_(integer *ijob, logical *wantq, logical *wantz, 
+	logical *select, integer *n, doublereal *a, integer *lda, doublereal *
+	b, integer *ldb, doublereal *alphar, doublereal *alphai, doublereal *
+	beta, doublereal *q, integer *ldq, doublereal *z__, integer *ldz, 
+	integer *m, doublereal *pl, doublereal *pr, doublereal *dif, 
+	doublereal *work, integer *lwork, integer *iwork, integer *liwork, 
+	integer *info);
+ 
+/* Subroutine */ int dtgsja_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, integer *k, integer *l, doublereal *a, 
+	integer *lda, doublereal *b, integer *ldb, doublereal *tola, 
+	doublereal *tolb, doublereal *alpha, doublereal *beta, doublereal *u, 
+	integer *ldu, doublereal *v, integer *ldv, doublereal *q, integer *
+	ldq, doublereal *work, integer *ncycle, integer *info);
+ 
+/* Subroutine */ int dtgsna_(char *job, char *howmny, logical *select, 
+	integer *n, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *vl, integer *ldvl, doublereal *vr, integer *ldvr, 
+	doublereal *s, doublereal *dif, integer *mm, integer *m, doublereal *
+	work, integer *lwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dtgsy2_(char *trans, integer *ijob, integer *m, integer *
+	n, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *c__, integer *ldc, doublereal *d__, integer *ldd, 
+	doublereal *e, integer *lde, doublereal *f, integer *ldf, doublereal *
+	scale, doublereal *rdsum, doublereal *rdscal, integer *iwork, integer 
+	*pq, integer *info);
+ 
+/* Subroutine */ int dtgsyl_(char *trans, integer *ijob, integer *m, integer *
+	n, doublereal *a, integer *lda, doublereal *b, integer *ldb, 
+	doublereal *c__, integer *ldc, doublereal *d__, integer *ldd, 
+	doublereal *e, integer *lde, doublereal *f, integer *ldf, doublereal *
+	scale, doublereal *dif, doublereal *work, integer *lwork, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int dtpcon_(char *norm, char *uplo, char *diag, integer *n, 
+	doublereal *ap, doublereal *rcond, doublereal *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int dtprfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublereal *ap, doublereal *b, integer *ldb, 
+	doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dtptri_(char *uplo, char *diag, integer *n, doublereal *
+	ap, integer *info);
+ 
+/* Subroutine */ int dtptrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublereal *ap, doublereal *b, integer *ldb, integer *
+	info);
+ 
+/* Subroutine */ int dtrcon_(char *norm, char *uplo, char *diag, integer *n, 
+	doublereal *a, integer *lda, doublereal *rcond, doublereal *work, 
+	integer *iwork, integer *info);
+ 
+/* Subroutine */ int dtrevc_(char *side, char *howmny, logical *select, 
+	integer *n, doublereal *t, integer *ldt, doublereal *vl, integer *
+	ldvl, doublereal *vr, integer *ldvr, integer *mm, integer *m, 
+	doublereal *work, integer *info);
+ 
+/* Subroutine */ int dtrexc_(char *compq, integer *n, doublereal *t, integer *
+	ldt, doublereal *q, integer *ldq, integer *ifst, integer *ilst, 
+	doublereal *work, integer *info);
+ 
+/* Subroutine */ int dtrrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublereal *a, integer *lda, doublereal *b, integer *
+	ldb, doublereal *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int dtrsen_(char *job, char *compq, logical *select, integer 
+	*n, doublereal *t, integer *ldt, doublereal *q, integer *ldq, 
+	doublereal *wr, doublereal *wi, integer *m, doublereal *s, doublereal 
+	*sep, doublereal *work, integer *lwork, integer *iwork, integer *
+	liwork, integer *info);
+ 
+/* Subroutine */ int dtrsna_(char *job, char *howmny, logical *select, 
+	integer *n, doublereal *t, integer *ldt, doublereal *vl, integer *
+	ldvl, doublereal *vr, integer *ldvr, doublereal *s, doublereal *sep, 
+	integer *mm, integer *m, doublereal *work, integer *ldwork, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int dtrsyl_(char *trana, char *tranb, integer *isgn, integer 
+	*m, integer *n, doublereal *a, integer *lda, doublereal *b, integer *
+	ldb, doublereal *c__, integer *ldc, doublereal *scale, integer *info);
+ 
+/* Subroutine */ int dtrti2_(char *uplo, char *diag, integer *n, doublereal *
+	a, integer *lda, integer *info);
+ 
+/* Subroutine */ int dtrtri_(char *uplo, char *diag, integer *n, doublereal *
+	a, integer *lda, integer *info);
+ 
+/* Subroutine */ int dtrtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublereal *a, integer *lda, doublereal *b, integer *
+	ldb, integer *info);
+ 
+/* Subroutine */ int dtzrqf_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, integer *info);
+ 
+/* Subroutine */ int dtzrzf_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublereal *tau, doublereal *work, integer *lwork, integer *info);
+ 
+integer icmax1_(integer *n, complex *cx, integer *incx);
+ 
+integer ieeeck_(integer *ispec, real *zero, real *one);
+ 
+integer ilaenv_(integer *ispec, char *name__, char *opts, integer *n1, 
+	integer *n2, integer *n3, integer *n4, ftnlen name_len, ftnlen 
+	opts_len);
+ 
+integer izmax1_(integer *n, doublecomplex *cx, integer *incx);
+ 
+/* Subroutine */ int sbdsdc_(char *uplo, char *compq, integer *n, real *d__, 
+	real *e, real *u, integer *ldu, real *vt, integer *ldvt, real *q, 
+	integer *iq, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sbdsqr_(char *uplo, integer *n, integer *ncvt, integer *
+	nru, integer *ncc, real *d__, real *e, real *vt, integer *ldvt, real *
+	u, integer *ldu, real *c__, integer *ldc, real *work, integer *info);
+ 
+/* Subroutine */ int sdisna_(char *job, integer *m, integer *n, real *d__, 
+	real *sep, integer *info);
+ 
+/* Subroutine */ int sgbbrd_(char *vect, integer *m, integer *n, integer *ncc,
+	 integer *kl, integer *ku, real *ab, integer *ldab, real *d__, real *
+	e, real *q, integer *ldq, real *pt, integer *ldpt, real *c__, integer 
+	*ldc, real *work, integer *info);
+ 
+/* Subroutine */ int sgbcon_(char *norm, integer *n, integer *kl, integer *ku,
+	 real *ab, integer *ldab, integer *ipiv, real *anorm, real *rcond, 
+	real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sgbequ_(integer *m, integer *n, integer *kl, integer *ku,
+	 real *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real *
+	colcnd, real *amax, integer *info);
+ 
+/* Subroutine */ int sgbrfs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, real *ab, integer *ldab, real *afb, integer *ldafb,
+	 integer *ipiv, real *b, integer *ldb, real *x, integer *ldx, real *
+	ferr, real *berr, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sgbsv_(integer *n, integer *kl, integer *ku, integer *
+	nrhs, real *ab, integer *ldab, integer *ipiv, real *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int sgbsvx_(char *fact, char *trans, integer *n, integer *kl,
+	 integer *ku, integer *nrhs, real *ab, integer *ldab, real *afb, 
+	integer *ldafb, integer *ipiv, char *equed, real *r__, real *c__, 
+	real *b, integer *ldb, real *x, integer *ldx, real *rcond, real *ferr,
+	 real *berr, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sgbtf2_(integer *m, integer *n, integer *kl, integer *ku,
+	 real *ab, integer *ldab, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int sgbtrf_(integer *m, integer *n, integer *kl, integer *ku,
+	 real *ab, integer *ldab, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int sgbtrs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, real *ab, integer *ldab, integer *ipiv, real *b, 
+	integer *ldb, integer *info);
+ 
+/* Subroutine */ int sgebak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, real *scale, integer *m, real *v, integer *ldv, integer 
+	*info);
+ 
+/* Subroutine */ int sgebal_(char *job, integer *n, real *a, integer *lda, 
+	integer *ilo, integer *ihi, real *scale, integer *info);
+ 
+/* Subroutine */ int sgebd2_(integer *m, integer *n, real *a, integer *lda, 
+	real *d__, real *e, real *tauq, real *taup, real *work, integer *info);
+ 
+/* Subroutine */ int sgebrd_(integer *m, integer *n, real *a, integer *lda, 
+	real *d__, real *e, real *tauq, real *taup, real *work, integer *
+	lwork, integer *info);
+ 
+/* Subroutine */ int sgecon_(char *norm, integer *n, real *a, integer *lda, 
+	real *anorm, real *rcond, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sgeequ_(integer *m, integer *n, real *a, integer *lda, 
+	real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, integer 
+	*info);
+ 
+/* Subroutine */ int sgees_(char *jobvs, char *sort, L_fp select, integer *n, 
+	real *a, integer *lda, integer *sdim, real *wr, real *wi, real *vs, 
+	integer *ldvs, real *work, integer *lwork, logical *bwork, integer *
+	info);
+ 
+/* Subroutine */ int sgeesx_(char *jobvs, char *sort, L_fp select, char *
+	sense, integer *n, real *a, integer *lda, integer *sdim, real *wr, 
+	real *wi, real *vs, integer *ldvs, real *rconde, real *rcondv, real *
+	work, integer *lwork, integer *iwork, integer *liwork, logical *bwork,
+	 integer *info);
+ 
+/* Subroutine */ int sgeev_(char *jobvl, char *jobvr, integer *n, real *a, 
+	integer *lda, real *wr, real *wi, real *vl, integer *ldvl, real *vr, 
+	integer *ldvr, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgeevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, real *a, integer *lda, real *wr, real *wi, real *
+	vl, integer *ldvl, real *vr, integer *ldvr, integer *ilo, integer *
+	ihi, real *scale, real *abnrm, real *rconde, real *rcondv, real *work,
+	 integer *lwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sgegs_(char *jobvsl, char *jobvsr, integer *n, real *a, 
+	integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real 
+	*beta, real *vsl, integer *ldvsl, real *vsr, integer *ldvsr, real *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgegv_(char *jobvl, char *jobvr, integer *n, real *a, 
+	integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real 
+	*beta, real *vl, integer *ldvl, real *vr, integer *ldvr, real *work, 
+	integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgehd2_(integer *n, integer *ilo, integer *ihi, real *a, 
+	integer *lda, real *tau, real *work, integer *info);
+ 
+/* Subroutine */ int sgehrd_(integer *n, integer *ilo, integer *ihi, real *a, 
+	integer *lda, real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgelq2_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *info);
+ 
+/* Subroutine */ int sgelqf_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgels_(char *trans, integer *m, integer *n, integer *
+	nrhs, real *a, integer *lda, real *b, integer *ldb, real *work, 
+	integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgelsd_(integer *m, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *b, integer *ldb, real *s, real *rcond, integer *
+	rank, real *work, integer *lwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sgelss_(integer *m, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *b, integer *ldb, real *s, real *rcond, integer *
+	rank, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgelsx_(integer *m, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *b, integer *ldb, integer *jpvt, real *rcond, 
+	integer *rank, real *work, integer *info);
+ 
+/* Subroutine */ int sgelsy_(integer *m, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *b, integer *ldb, integer *jpvt, real *rcond, 
+	integer *rank, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgeql2_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *info);
+ 
+/* Subroutine */ int sgeqlf_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgeqp3_(integer *m, integer *n, real *a, integer *lda, 
+	integer *jpvt, real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgeqpf_(integer *m, integer *n, real *a, integer *lda, 
+	integer *jpvt, real *tau, real *work, integer *info);
+ 
+/* Subroutine */ int sgeqr2_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *info);
+ 
+/* Subroutine */ int sgeqrf_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgerfs_(char *trans, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *af, integer *ldaf, integer *ipiv, real *b, 
+	integer *ldb, real *x, integer *ldx, real *ferr, real *berr, real *
+	work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sgerq2_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *info);
+ 
+/* Subroutine */ int sgerqf_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgesc2_(integer *n, real *a, integer *lda, real *rhs, 
+	integer *ipiv, integer *jpiv, real *scale);
+ 
+/* Subroutine */ int sgesdd_(char *jobz, integer *m, integer *n, real *a, 
+	integer *lda, real *s, real *u, integer *ldu, real *vt, integer *ldvt,
+	 real *work, integer *lwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sgesv_(integer *n, integer *nrhs, real *a, integer *lda, 
+	integer *ipiv, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int sgesvd_(char *jobu, char *jobvt, integer *m, integer *n, 
+	real *a, integer *lda, real *s, real *u, integer *ldu, real *vt, 
+	integer *ldvt, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgesvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, real *a, integer *lda, real *af, integer *ldaf, integer *ipiv, 
+	char *equed, real *r__, real *c__, real *b, integer *ldb, real *x, 
+	integer *ldx, real *rcond, real *ferr, real *berr, real *work, 
+	integer *iwork, integer *info);
+ 
+/* Subroutine */ int sgetc2_(integer *n, real *a, integer *lda, integer *ipiv,
+	 integer *jpiv, integer *info);
+ 
+/* Subroutine */ int sgetf2_(integer *m, integer *n, real *a, integer *lda, 
+	integer *ipiv, integer *info);
+ 
+/* Subroutine */ int sgetrf_(integer *m, integer *n, real *a, integer *lda, 
+	integer *ipiv, integer *info);
+ 
+/* Subroutine */ int sgetri_(integer *n, real *a, integer *lda, integer *ipiv,
+	 real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgetrs_(char *trans, integer *n, integer *nrhs, real *a, 
+	integer *lda, integer *ipiv, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int sggbak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, real *lscale, real *rscale, integer *m, real *v, 
+	integer *ldv, integer *info);
+ 
+/* Subroutine */ int sggbal_(char *job, integer *n, real *a, integer *lda, 
+	real *b, integer *ldb, integer *ilo, integer *ihi, real *lscale, real 
+	*rscale, real *work, integer *info);
+ 
+/* Subroutine */ int sgges_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	selctg, integer *n, real *a, integer *lda, real *b, integer *ldb, 
+	integer *sdim, real *alphar, real *alphai, real *beta, real *vsl, 
+	integer *ldvsl, real *vsr, integer *ldvsr, real *work, integer *lwork,
+	 logical *bwork, integer *info);
+ 
+/* Subroutine */ int sggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	selctg, char *sense, integer *n, real *a, integer *lda, real *b, 
+	integer *ldb, integer *sdim, real *alphar, real *alphai, real *beta, 
+	real *vsl, integer *ldvsl, real *vsr, integer *ldvsr, real *rconde, 
+	real *rcondv, real *work, integer *lwork, integer *iwork, integer *
+	liwork, logical *bwork, integer *info);
+ 
+/* Subroutine */ int sggev_(char *jobvl, char *jobvr, integer *n, real *a, 
+	integer *lda, real *b, integer *ldb, real *alphar, real *alphai, real 
+	*beta, real *vl, integer *ldvl, real *vr, integer *ldvr, real *work, 
+	integer *lwork, integer *info);
+ 
+/* Subroutine */ int sggevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, real *a, integer *lda, real *b, integer *ldb, real 
+	*alphar, real *alphai, real *beta, real *vl, integer *ldvl, real *vr, 
+	integer *ldvr, integer *ilo, integer *ihi, real *lscale, real *rscale,
+	 real *abnrm, real *bbnrm, real *rconde, real *rcondv, real *work, 
+	integer *lwork, integer *iwork, logical *bwork, integer *info);
+ 
+/* Subroutine */ int sggglm_(integer *n, integer *m, integer *p, real *a, 
+	integer *lda, real *b, integer *ldb, real *d__, real *x, real *y, 
+	real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sgghrd_(char *compq, char *compz, integer *n, integer *
+	ilo, integer *ihi, real *a, integer *lda, real *b, integer *ldb, real 
+	*q, integer *ldq, real *z__, integer *ldz, integer *info);
+ 
+/* Subroutine */ int sgglse_(integer *m, integer *n, integer *p, real *a, 
+	integer *lda, real *b, integer *ldb, real *c__, real *d__, real *x, 
+	real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sggqrf_(integer *n, integer *m, integer *p, real *a, 
+	integer *lda, real *taua, real *b, integer *ldb, real *taub, real *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sggrqf_(integer *m, integer *p, integer *n, real *a, 
+	integer *lda, real *taua, real *b, integer *ldb, real *taub, real *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sggsvd_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *n, integer *p, integer *k, integer *l, real *a, integer *lda,
+	 real *b, integer *ldb, real *alpha, real *beta, real *u, integer *
+	ldu, real *v, integer *ldv, real *q, integer *ldq, real *work, 
+	integer *iwork, integer *info);
+ 
+/* Subroutine */ int sggsvp_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, real *a, integer *lda, real *b, integer *ldb, 
+	real *tola, real *tolb, integer *k, integer *l, real *u, integer *ldu,
+	 real *v, integer *ldv, real *q, integer *ldq, integer *iwork, real *
+	tau, real *work, integer *info);
+ 
+/* Subroutine */ int sgtcon_(char *norm, integer *n, real *dl, real *d__, 
+	real *du, real *du2, integer *ipiv, real *anorm, real *rcond, real *
+	work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sgtrfs_(char *trans, integer *n, integer *nrhs, real *dl,
+	 real *d__, real *du, real *dlf, real *df, real *duf, real *du2, 
+	integer *ipiv, real *b, integer *ldb, real *x, integer *ldx, real *
+	ferr, real *berr, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sgtsv_(integer *n, integer *nrhs, real *dl, real *d__, 
+	real *du, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int sgtsvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, real *dl, real *d__, real *du, real *dlf, real *df, real *duf, 
+	real *du2, integer *ipiv, real *b, integer *ldb, real *x, integer *
+	ldx, real *rcond, real *ferr, real *berr, real *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int sgttrf_(integer *n, real *dl, real *d__, real *du, real *
+	du2, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int sgttrs_(char *trans, integer *n, integer *nrhs, real *dl,
+	 real *d__, real *du, real *du2, integer *ipiv, real *b, integer *ldb,
+	 integer *info);
+ 
+/* Subroutine */ int sgtts2_(integer *itrans, integer *n, integer *nrhs, real 
+	*dl, real *d__, real *du, real *du2, integer *ipiv, real *b, integer *
+	ldb);
+ 
+/* Subroutine */ int shgeqz_(char *job, char *compq, char *compz, integer *n, 
+	integer *ilo, integer *ihi, real *a, integer *lda, real *b, integer *
+	ldb, real *alphar, real *alphai, real *beta, real *q, integer *ldq, 
+	real *z__, integer *ldz, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int shsein_(char *side, char *eigsrc, char *initv, logical *
+	select, integer *n, real *h__, integer *ldh, real *wr, real *wi, real 
+	*vl, integer *ldvl, real *vr, integer *ldvr, integer *mm, integer *m, 
+	real *work, integer *ifaill, integer *ifailr, integer *info);
+ 
+/* Subroutine */ int shseqr_(char *job, char *compz, integer *n, integer *ilo,
+	 integer *ihi, real *h__, integer *ldh, real *wr, real *wi, real *z__,
+	 integer *ldz, real *work, integer *lwork, integer *info);
+ 
+///* Subroutine */ int slabad_(real *small, real *large);
+/* Subroutine */ int slabad_(real *smallnumber, real *largenumber);//hirohito
+
+/* Subroutine */ int slabrd_(integer *m, integer *n, integer *nb, real *a, 
+	integer *lda, real *d__, real *e, real *tauq, real *taup, real *x, 
+	integer *ldx, real *y, integer *ldy);
+ 
+/* Subroutine */ int slacon_(integer *n, real *v, real *x, integer *isgn, 
+	real *est, integer *kase);
+ 
+/* Subroutine */ int slacpy_(char *uplo, integer *m, integer *n, real *a, 
+	integer *lda, real *b, integer *ldb);
+ 
+/* Subroutine */ int sladiv_(real *a, real *b, real *c__, real *d__, real *p, 
+	real *q);
+ 
+/* Subroutine */ int slae2_(real *a, real *b, real *c__, real *rt1, real *rt2);
+ 
+/* Subroutine */ int slaebz_(integer *ijob, integer *nitmax, integer *n, 
+	integer *mmax, integer *minp, integer *nbmin, real *abstol, real *
+	reltol, real *pivmin, real *d__, real *e, real *e2, integer *nval, 
+	real *ab, real *c__, integer *mout, integer *nab, real *work, integer 
+	*iwork, integer *info);
+ 
+/* Subroutine */ int slaed0_(integer *icompq, integer *qsiz, integer *n, real 
+	*d__, real *e, real *q, integer *ldq, real *qstore, integer *ldqs, 
+	real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int slaed1_(integer *n, real *d__, real *q, integer *ldq, 
+	integer *indxq, real *rho, integer *cutpnt, real *work, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int slaed2_(integer *k, integer *n, integer *n1, real *d__, 
+	real *q, integer *ldq, integer *indxq, real *rho, real *z__, real *
+	dlamda, real *w, real *q2, integer *indx, integer *indxc, integer *
+	indxp, integer *coltyp, integer *info);
+ 
+/* Subroutine */ int slaed3_(integer *k, integer *n, integer *n1, real *d__, 
+	real *q, integer *ldq, real *rho, real *dlamda, real *q2, integer *
+	indx, integer *ctot, real *w, real *s, integer *info);
+ 
+/* Subroutine */ int slaed4_(integer *n, integer *i__, real *d__, real *z__, 
+	real *delta, real *rho, real *dlam, integer *info);
+ 
+/* Subroutine */ int slaed5_(integer *i__, real *d__, real *z__, real *delta, 
+	real *rho, real *dlam);
+ 
+/* Subroutine */ int slaed6_(integer *kniter, logical *orgati, real *rho, 
+	real *d__, real *z__, real *finit, real *tau, integer *info);
+ 
+/* Subroutine */ int slaed7_(integer *icompq, integer *n, integer *qsiz, 
+	integer *tlvls, integer *curlvl, integer *curpbm, real *d__, real *q, 
+	integer *ldq, integer *indxq, real *rho, integer *cutpnt, real *
+	qstore, integer *qptr, integer *prmptr, integer *perm, integer *
+	givptr, integer *givcol, real *givnum, real *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int slaed8_(integer *icompq, integer *k, integer *n, integer 
+	*qsiz, real *d__, real *q, integer *ldq, integer *indxq, real *rho, 
+	integer *cutpnt, real *z__, real *dlamda, real *q2, integer *ldq2, 
+	real *w, integer *perm, integer *givptr, integer *givcol, real *
+	givnum, integer *indxp, integer *indx, integer *info);
+ 
+/* Subroutine */ int slaed9_(integer *k, integer *kstart, integer *kstop, 
+	integer *n, real *d__, real *q, integer *ldq, real *rho, real *dlamda,
+	 real *w, real *s, integer *lds, integer *info);
+ 
+/* Subroutine */ int slaeda_(integer *n, integer *tlvls, integer *curlvl, 
+	integer *curpbm, integer *prmptr, integer *perm, integer *givptr, 
+	integer *givcol, real *givnum, real *q, integer *qptr, real *z__, 
+	real *ztemp, integer *info);
+ 
+/* Subroutine */ int slaein_(logical *rightv, logical *noinit, integer *n, 
+	real *h__, integer *ldh, real *wr, real *wi, real *vr, real *vi, real 
+	*b, integer *ldb, real *work, real *eps3, real *smlnum, real *bignum, 
+	integer *info);
+ 
+/* Subroutine */ int slaev2_(real *a, real *b, real *c__, real *rt1, real *
+	rt2, real *cs1, real *sn1);
+ 
+/* Subroutine */ int slaexc_(logical *wantq, integer *n, real *t, integer *
+	ldt, real *q, integer *ldq, integer *j1, integer *n1, integer *n2, 
+	real *work, integer *info);
+ 
+/* Subroutine */ int slag2_(real *a, integer *lda, real *b, integer *ldb, 
+	real *safmin, real *scale1, real *scale2, real *wr1, real *wr2, real *
+	wi);
+ 
+/* Subroutine */ int slags2_(logical *upper, real *a1, real *a2, real *a3, 
+	real *b1, real *b2, real *b3, real *csu, real *snu, real *csv, real *
+	snv, real *csq, real *snq);
+ 
+/* Subroutine */ int slagtf_(integer *n, real *a, real *lambda, real *b, real 
+	*c__, real *tol, real *d__, integer *in, integer *info);
+ 
+/* Subroutine */ int slagtm_(char *trans, integer *n, integer *nrhs, real *
+	alpha, real *dl, real *d__, real *du, real *x, integer *ldx, real *
+	beta, real *b, integer *ldb);
+ 
+/* Subroutine */ int slagts_(integer *job, integer *n, real *a, real *b, real 
+	*c__, real *d__, integer *in, real *y, real *tol, integer *info);
+ 
+/* Subroutine */ int slagv2_(real *a, integer *lda, real *b, integer *ldb, 
+	real *alphar, real *alphai, real *beta, real *csl, real *snl, real *
+	csr, real *snr);
+ 
+/* Subroutine */ int slahqr_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, real *h__, integer *ldh, real *wr, real *
+	wi, integer *iloz, integer *ihiz, real *z__, integer *ldz, integer *
+	info);
+ 
+/* Subroutine */ int slahrd_(integer *n, integer *k, integer *nb, real *a, 
+	integer *lda, real *tau, real *t, integer *ldt, real *y, integer *ldy);
+ 
+/* Subroutine */ int slaic1_(integer *job, integer *j, real *x, real *sest, 
+	real *w, real *gamma, real *sestpr, real *s, real *c__);
+ 
+/* Subroutine */ int slaln2_(logical *ltrans, integer *na, integer *nw, real *
+	smin, real *ca, real *a, integer *lda, real *d1, real *d2, real *b, 
+	integer *ldb, real *wr, real *wi, real *x, integer *ldx, real *scale, 
+	real *xnorm, integer *info);
+ 
+/* Subroutine */ int slals0_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, integer *nrhs, real *b, integer *ldb, real *bx, 
+	integer *ldbx, integer *perm, integer *givptr, integer *givcol, 
+	integer *ldgcol, real *givnum, integer *ldgnum, real *poles, real *
+	difl, real *difr, real *z__, integer *k, real *c__, real *s, real *
+	work, integer *info);
+ 
+/* Subroutine */ int slalsa_(integer *icompq, integer *smlsiz, integer *n, 
+	integer *nrhs, real *b, integer *ldb, real *bx, integer *ldbx, real *
+	u, integer *ldu, real *vt, integer *k, real *difl, real *difr, real *
+	z__, real *poles, integer *givptr, integer *givcol, integer *ldgcol, 
+	integer *perm, real *givnum, real *c__, real *s, real *work, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int slalsd_(char *uplo, integer *smlsiz, integer *n, integer 
+	*nrhs, real *d__, real *e, real *b, integer *ldb, real *rcond, 
+	integer *rank, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int slamc1_(integer *beta, integer *t, logical *rnd, logical 
+	*ieee1);
+ 
+/* Subroutine */ int slamc2_(integer *beta, integer *t, logical *rnd, real *
+	eps, integer *emin, real *rmin, integer *emax, real *rmax);
+ 
+/* Subroutine */ int slamc4_(integer *emin, real *start, integer *base);
+ 
+/* Subroutine */ int slamc5_(integer *beta, integer *p, integer *emin, 
+	logical *ieee, integer *emax, real *rmax);
+ 
+/* Subroutine */ int slamrg_(integer *n1, integer *n2, real *a, integer *
+	strd1, integer *strd2, integer *index);
+ 
+/* Subroutine */ int slanv2_(real *a, real *b, real *c__, real *d__, real *
+	rt1r, real *rt1i, real *rt2r, real *rt2i, real *cs, real *sn);
+ 
+/* Subroutine */ int slapll_(integer *n, real *x, integer *incx, real *y, 
+	integer *incy, real *ssmin);
+ 
+/* Subroutine */ int slapmt_(logical *forwrd, integer *m, integer *n, real *x,
+	 integer *ldx, integer *k);
+ 
+/* Subroutine */ int slaqgb_(integer *m, integer *n, integer *kl, integer *ku,
+	 real *ab, integer *ldab, real *r__, real *c__, real *rowcnd, real *
+	colcnd, real *amax, char *equed);
+ 
+/* Subroutine */ int slaqge_(integer *m, integer *n, real *a, integer *lda, 
+	real *r__, real *c__, real *rowcnd, real *colcnd, real *amax, char *
+	equed);
+ 
+/* Subroutine */ int slaqp2_(integer *m, integer *n, integer *offset, real *a,
+	 integer *lda, integer *jpvt, real *tau, real *vn1, real *vn2, real *
+	work);
+ 
+/* Subroutine */ int slaqps_(integer *m, integer *n, integer *offset, integer 
+	*nb, integer *kb, real *a, integer *lda, integer *jpvt, real *tau, 
+	real *vn1, real *vn2, real *auxv, real *f, integer *ldf);
+ 
+/* Subroutine */ int slaqsb_(char *uplo, integer *n, integer *kd, real *ab, 
+	integer *ldab, real *s, real *scond, real *amax, char *equed);
+ 
+/* Subroutine */ int slaqsp_(char *uplo, integer *n, real *ap, real *s, real *
+	scond, real *amax, char *equed);
+ 
+/* Subroutine */ int slaqsy_(char *uplo, integer *n, real *a, integer *lda, 
+	real *s, real *scond, real *amax, char *equed);
+ 
+/* Subroutine */ int slaqtr_(logical *ltran, logical *lreal, integer *n, real 
+	*t, integer *ldt, real *b, real *w, real *scale, real *x, real *work, 
+	integer *info);
+ 
+/* Subroutine */ int slar1v_(integer *n, integer *b1, integer *bn, real *
+	sigma, real *d__, real *l, real *ld, real *lld, real *gersch, real *
+	z__, real *ztz, real *mingma, integer *r__, integer *isuppz, real *
+	work);
+ 
+/* Subroutine */ int slar2v_(integer *n, real *x, real *y, real *z__, integer 
+	*incx, real *c__, real *s, integer *incc);
+ 
+/* Subroutine */ int slarf_(char *side, integer *m, integer *n, real *v, 
+	integer *incv, real *tau, real *c__, integer *ldc, real *work);
+ 
+/* Subroutine */ int slarfb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, real *v, integer *ldv, 
+	real *t, integer *ldt, real *c__, integer *ldc, real *work, integer *
+	ldwork);
+ 
+/* Subroutine */ int slarfg_(integer *n, real *alpha, real *x, integer *incx, 
+	real *tau);
+ 
+/* Subroutine */ int slarft_(char *direct, char *storev, integer *n, integer *
+	k, real *v, integer *ldv, real *tau, real *t, integer *ldt);
+ 
+/* Subroutine */ int slarfx_(char *side, integer *m, integer *n, real *v, 
+	real *tau, real *c__, integer *ldc, real *work);
+ 
+/* Subroutine */ int slargv_(integer *n, real *x, integer *incx, real *y, 
+	integer *incy, real *c__, integer *incc);
+ 
+/* Subroutine */ int slarnv_(integer *idist, integer *iseed, integer *n, real 
+	*x);
+ 
+/* Subroutine */ int slarrb_(integer *n, real *d__, real *l, real *ld, real *
+	lld, integer *ifirst, integer *ilast, real *sigma, real *reltol, real 
+	*w, real *wgap, real *werr, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int slarre_(integer *n, real *d__, real *e, real *tol, 
+	integer *nsplit, integer *isplit, integer *m, real *w, real *woff, 
+	real *gersch, real *work, integer *info);
+ 
+/* Subroutine */ int slarrf_(integer *n, real *d__, real *l, real *ld, real *
+	lld, integer *ifirst, integer *ilast, real *w, real *dplus, real *
+	lplus, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int slarrv_(integer *n, real *d__, real *l, integer *isplit, 
+	integer *m, real *w, integer *iblock, real *gersch, real *tol, real *
+	z__, integer *ldz, integer *isuppz, real *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int slartg_(real *f, real *g, real *cs, real *sn, real *r__);
+ 
+/* Subroutine */ int slartv_(integer *n, real *x, integer *incx, real *y, 
+	integer *incy, real *c__, real *s, integer *incc);
+ 
+/* Subroutine */ int slaruv_(integer *iseed, integer *n, real *x);
+ 
+/* Subroutine */ int slarz_(char *side, integer *m, integer *n, integer *l, 
+	real *v, integer *incv, real *tau, real *c__, integer *ldc, real *
+	work);
+ 
+/* Subroutine */ int slarzb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, integer *l, real *v, 
+	integer *ldv, real *t, integer *ldt, real *c__, integer *ldc, real *
+	work, integer *ldwork);
+ 
+/* Subroutine */ int slarzt_(char *direct, char *storev, integer *n, integer *
+	k, real *v, integer *ldv, real *tau, real *t, integer *ldt);
+ 
+/* Subroutine */ int slas2_(real *f, real *g, real *h__, real *ssmin, real *
+	ssmax);
+ 
+/* Subroutine */ int slascl_(char *type__, integer *kl, integer *ku, real *
+	cfrom, real *cto, integer *m, integer *n, real *a, integer *lda, 
+	integer *info);
+ 
+/* Subroutine */ int slasd0_(integer *n, integer *sqre, real *d__, real *e, 
+	real *u, integer *ldu, real *vt, integer *ldvt, integer *smlsiz, 
+	integer *iwork, real *work, integer *info);
+ 
+/* Subroutine */ int slasd1_(integer *nl, integer *nr, integer *sqre, real *
+	d__, real *alpha, real *beta, real *u, integer *ldu, real *vt, 
+	integer *ldvt, integer *idxq, integer *iwork, real *work, integer *
+	info);
+ 
+/* Subroutine */ int slasd2_(integer *nl, integer *nr, integer *sqre, integer 
+	*k, real *d__, real *z__, real *alpha, real *beta, real *u, integer *
+	ldu, real *vt, integer *ldvt, real *dsigma, real *u2, integer *ldu2, 
+	real *vt2, integer *ldvt2, integer *idxp, integer *idx, integer *idxc,
+	 integer *idxq, integer *coltyp, integer *info);
+ 
+/* Subroutine */ int slasd3_(integer *nl, integer *nr, integer *sqre, integer 
+	*k, real *d__, real *q, integer *ldq, real *dsigma, real *u, integer *
+	ldu, real *u2, integer *ldu2, real *vt, integer *ldvt, real *vt2, 
+	integer *ldvt2, integer *idxc, integer *ctot, real *z__, integer *
+	info);
+ 
+/* Subroutine */ int slasd4_(integer *n, integer *i__, real *d__, real *z__, 
+	real *delta, real *rho, real *sigma, real *work, integer *info);
+ 
+/* Subroutine */ int slasd5_(integer *i__, real *d__, real *z__, real *delta, 
+	real *rho, real *dsigma, real *work);
+ 
+/* Subroutine */ int slasd6_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, real *d__, real *vf, real *vl, real *alpha, real *beta,
+	 integer *idxq, integer *perm, integer *givptr, integer *givcol, 
+	integer *ldgcol, real *givnum, integer *ldgnum, real *poles, real *
+	difl, real *difr, real *z__, integer *k, real *c__, real *s, real *
+	work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int slasd7_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, integer *k, real *d__, real *z__, real *zw, real *vf, 
+	real *vfw, real *vl, real *vlw, real *alpha, real *beta, real *dsigma,
+	 integer *idx, integer *idxp, integer *idxq, integer *perm, integer *
+	givptr, integer *givcol, integer *ldgcol, real *givnum, integer *
+	ldgnum, real *c__, real *s, integer *info);
+ 
+/* Subroutine */ int slasd8_(integer *icompq, integer *k, real *d__, real *
+	z__, real *vf, real *vl, real *difl, real *difr, integer *lddifr, 
+	real *dsigma, real *work, integer *info);
+ 
+/* Subroutine */ int slasd9_(integer *icompq, integer *ldu, integer *k, real *
+	d__, real *z__, real *vf, real *vl, real *difl, real *difr, real *
+	dsigma, real *work, integer *info);
+ 
+/* Subroutine */ int slasda_(integer *icompq, integer *smlsiz, integer *n, 
+	integer *sqre, real *d__, real *e, real *u, integer *ldu, real *vt, 
+	integer *k, real *difl, real *difr, real *z__, real *poles, integer *
+	givptr, integer *givcol, integer *ldgcol, integer *perm, real *givnum,
+	 real *c__, real *s, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int slasdq_(char *uplo, integer *sqre, integer *n, integer *
+	ncvt, integer *nru, integer *ncc, real *d__, real *e, real *vt, 
+	integer *ldvt, real *u, integer *ldu, real *c__, integer *ldc, real *
+	work, integer *info);
+ 
+/* Subroutine */ int slasdt_(integer *n, integer *lvl, integer *nd, integer *
+	inode, integer *ndiml, integer *ndimr, integer *msub);
+ 
+/* Subroutine */ int slaset_(char *uplo, integer *m, integer *n, real *alpha, 
+	real *beta, real *a, integer *lda);
+ 
+/* Subroutine */ int slasq1_(integer *n, real *d__, real *e, real *work, 
+	integer *info);
+ 
+/* Subroutine */ int slasq2_(integer *n, real *z__, integer *info);
+ 
+/* Subroutine */ int slasq3_(integer *i0, integer *n0, real *z__, integer *pp,
+	 real *dmin__, real *sigma, real *desig, real *qmax, integer *nfail, 
+	integer *iter, integer *ndiv, logical *ieee);
+ 
+/* Subroutine */ int slasq4_(integer *i0, integer *n0, real *z__, integer *pp,
+	 integer *n0in, real *dmin__, real *dmin1, real *dmin2, real *dn, 
+	real *dn1, real *dn2, real *tau, integer *ttype);
+ 
+/* Subroutine */ int slasq5_(integer *i0, integer *n0, real *z__, integer *pp,
+	 real *tau, real *dmin__, real *dmin1, real *dmin2, real *dn, real *
+	dnm1, real *dnm2, logical *ieee);
+ 
+/* Subroutine */ int slasq6_(integer *i0, integer *n0, real *z__, integer *pp,
+	 real *dmin__, real *dmin1, real *dmin2, real *dn, real *dnm1, real *
+	dnm2);
+ 
+/* Subroutine */ int slasr_(char *side, char *pivot, char *direct, integer *m,
+	 integer *n, real *c__, real *s, real *a, integer *lda);
+ 
+/* Subroutine */ int slasrt_(char *id, integer *n, real *d__, integer *info);
+ 
+/* Subroutine */ int slassq_(integer *n, real *x, integer *incx, real *scale, 
+	real *sumsq);
+ 
+/* Subroutine */ int slasv2_(real *f, real *g, real *h__, real *ssmin, real *
+	ssmax, real *snr, real *csr, real *snl, real *csl);
+ 
+/* Subroutine */ int slaswp_(integer *n, real *a, integer *lda, integer *k1, 
+	integer *k2, integer *ipiv, integer *incx);
+ 
+/* Subroutine */ int slasy2_(logical *ltranl, logical *ltranr, integer *isgn, 
+	integer *n1, integer *n2, real *tl, integer *ldtl, real *tr, integer *
+	ldtr, real *b, integer *ldb, real *scale, real *x, integer *ldx, real 
+	*xnorm, integer *info);
+ 
+/* Subroutine */ int slasyf_(char *uplo, integer *n, integer *nb, integer *kb,
+	 real *a, integer *lda, integer *ipiv, real *w, integer *ldw, integer 
+	*info);
+ 
+/* Subroutine */ int slatbs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, integer *kd, real *ab, integer *ldab, real *x, 
+	real *scale, real *cnorm, integer *info);
+ 
+/* Subroutine */ int slatdf_(integer *ijob, integer *n, real *z__, integer *
+	ldz, real *rhs, real *rdsum, real *rdscal, integer *ipiv, integer *
+	jpiv);
+ 
+/* Subroutine */ int slatps_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, real *ap, real *x, real *scale, real *cnorm, 
+	integer *info);
+ 
+/* Subroutine */ int slatrd_(char *uplo, integer *n, integer *nb, real *a, 
+	integer *lda, real *e, real *tau, real *w, integer *ldw);
+ 
+/* Subroutine */ int slatrs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, real *a, integer *lda, real *x, real *scale, real 
+	*cnorm, integer *info);
+ 
+/* Subroutine */ int slatrz_(integer *m, integer *n, integer *l, real *a, 
+	integer *lda, real *tau, real *work);
+ 
+/* Subroutine */ int slatzm_(char *side, integer *m, integer *n, real *v, 
+	integer *incv, real *tau, real *c1, real *c2, integer *ldc, real *
+	work);
+ 
+/* Subroutine */ int slauu2_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *info);
+ 
+/* Subroutine */ int slauum_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *info);
+ 
+/* Subroutine */ int sopgtr_(char *uplo, integer *n, real *ap, real *tau, 
+	real *q, integer *ldq, real *work, integer *info);
+ 
+/* Subroutine */ int sopmtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, real *ap, real *tau, real *c__, integer *ldc, real *work, 
+	integer *info);
+ 
+/* Subroutine */ int sorg2l_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *info);
+ 
+/* Subroutine */ int sorg2r_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *info);
+ 
+/* Subroutine */ int sorgbr_(char *vect, integer *m, integer *n, integer *k, 
+	real *a, integer *lda, real *tau, real *work, integer *lwork, integer 
+	*info);
+ 
+/* Subroutine */ int sorghr_(integer *n, integer *ilo, integer *ihi, real *a, 
+	integer *lda, real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sorgl2_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *info);
+ 
+/* Subroutine */ int sorglq_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sorgql_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sorgqr_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sorgr2_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *info);
+ 
+/* Subroutine */ int sorgrq_(integer *m, integer *n, integer *k, real *a, 
+	integer *lda, real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sorgtr_(char *uplo, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sorm2l_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+	 real *work, integer *info);
+ 
+/* Subroutine */ int sorm2r_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+	 real *work, integer *info);
+ 
+/* Subroutine */ int sormbr_(char *vect, char *side, char *trans, integer *m, 
+	integer *n, integer *k, real *a, integer *lda, real *tau, real *c__, 
+	integer *ldc, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sormhr_(char *side, char *trans, integer *m, integer *n, 
+	integer *ilo, integer *ihi, real *a, integer *lda, real *tau, real *
+	c__, integer *ldc, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sorml2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+	 real *work, integer *info);
+ 
+/* Subroutine */ int sormlq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+	 real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sormql_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+	 real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sormqr_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+	 real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sormr2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+	 real *work, integer *info);
+ 
+/* Subroutine */ int sormr3_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, real *a, integer *lda, real *tau, real *c__, 
+	integer *ldc, real *work, integer *info);
+ 
+/* Subroutine */ int sormrq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+	 real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sormrz_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, real *a, integer *lda, real *tau, real *c__, 
+	integer *ldc, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int sormtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, real *a, integer *lda, real *tau, real *c__, integer *ldc,
+	 real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int spbcon_(char *uplo, integer *n, integer *kd, real *ab, 
+	integer *ldab, real *anorm, real *rcond, real *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int spbequ_(char *uplo, integer *n, integer *kd, real *ab, 
+	integer *ldab, real *s, real *scond, real *amax, integer *info);
+ 
+/* Subroutine */ int spbrfs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, real *ab, integer *ldab, real *afb, integer *ldafb, real *b, 
+	integer *ldb, real *x, integer *ldx, real *ferr, real *berr, real *
+	work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int spbstf_(char *uplo, integer *n, integer *kd, real *ab, 
+	integer *ldab, integer *info);
+ 
+/* Subroutine */ int spbsv_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, real *ab, integer *ldab, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int spbsvx_(char *fact, char *uplo, integer *n, integer *kd, 
+	integer *nrhs, real *ab, integer *ldab, real *afb, integer *ldafb, 
+	char *equed, real *s, real *b, integer *ldb, real *x, integer *ldx, 
+	real *rcond, real *ferr, real *berr, real *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int spbtf2_(char *uplo, integer *n, integer *kd, real *ab, 
+	integer *ldab, integer *info);
+ 
+/* Subroutine */ int spbtrf_(char *uplo, integer *n, integer *kd, real *ab, 
+	integer *ldab, integer *info);
+ 
+/* Subroutine */ int spbtrs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, real *ab, integer *ldab, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int spocon_(char *uplo, integer *n, real *a, integer *lda, 
+	real *anorm, real *rcond, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int spoequ_(integer *n, real *a, integer *lda, real *s, real 
+	*scond, real *amax, integer *info);
+ 
+/* Subroutine */ int sporfs_(char *uplo, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *af, integer *ldaf, real *b, integer *ldb, real *x,
+	 integer *ldx, real *ferr, real *berr, real *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int sposv_(char *uplo, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int sposvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, real *a, integer *lda, real *af, integer *ldaf, char *equed, 
+	real *s, real *b, integer *ldb, real *x, integer *ldx, real *rcond, 
+	real *ferr, real *berr, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int spotf2_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *info);
+ 
+/* Subroutine */ int spotrf_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *info);
+ 
+/* Subroutine */ int spotri_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *info);
+ 
+/* Subroutine */ int spotrs_(char *uplo, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int sppcon_(char *uplo, integer *n, real *ap, real *anorm, 
+	real *rcond, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sppequ_(char *uplo, integer *n, real *ap, real *s, real *
+	scond, real *amax, integer *info);
+ 
+/* Subroutine */ int spprfs_(char *uplo, integer *n, integer *nrhs, real *ap, 
+	real *afp, real *b, integer *ldb, real *x, integer *ldx, real *ferr, 
+	real *berr, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sppsv_(char *uplo, integer *n, integer *nrhs, real *ap, 
+	real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int sppsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, real *ap, real *afp, char *equed, real *s, real *b, integer *
+	ldb, real *x, integer *ldx, real *rcond, real *ferr, real *berr, real 
+	*work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int spptrf_(char *uplo, integer *n, real *ap, integer *info);
+ 
+/* Subroutine */ int spptri_(char *uplo, integer *n, real *ap, integer *info);
+ 
+/* Subroutine */ int spptrs_(char *uplo, integer *n, integer *nrhs, real *ap, 
+	real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int sptcon_(integer *n, real *d__, real *e, real *anorm, 
+	real *rcond, real *work, integer *info);
+ 
+/* Subroutine */ int spteqr_(char *compz, integer *n, real *d__, real *e, 
+	real *z__, integer *ldz, real *work, integer *info);
+ 
+/* Subroutine */ int sptrfs_(integer *n, integer *nrhs, real *d__, real *e, 
+	real *df, real *ef, real *b, integer *ldb, real *x, integer *ldx, 
+	real *ferr, real *berr, real *work, integer *info);
+ 
+/* Subroutine */ int sptsv_(integer *n, integer *nrhs, real *d__, real *e, 
+	real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int sptsvx_(char *fact, integer *n, integer *nrhs, real *d__,
+	 real *e, real *df, real *ef, real *b, integer *ldb, real *x, integer 
+	*ldx, real *rcond, real *ferr, real *berr, real *work, integer *info);
+ 
+/* Subroutine */ int spttrf_(integer *n, real *d__, real *e, integer *info);
+ 
+/* Subroutine */ int spttrs_(integer *n, integer *nrhs, real *d__, real *e, 
+	real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int sptts2_(integer *n, integer *nrhs, real *d__, real *e, 
+	real *b, integer *ldb);
+ 
+/* Subroutine */ int srscl_(integer *n, real *sa, real *sx, integer *incx);
+ 
+/* Subroutine */ int ssbev_(char *jobz, char *uplo, integer *n, integer *kd, 
+	real *ab, integer *ldab, real *w, real *z__, integer *ldz, real *work,
+	 integer *info);
+ 
+/* Subroutine */ int ssbevd_(char *jobz, char *uplo, integer *n, integer *kd, 
+	real *ab, integer *ldab, real *w, real *z__, integer *ldz, real *work,
+	 integer *lwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int ssbevx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *kd, real *ab, integer *ldab, real *q, integer *ldq, real *vl,
+	 real *vu, integer *il, integer *iu, real *abstol, integer *m, real *
+	w, real *z__, integer *ldz, real *work, integer *iwork, integer *
+	ifail, integer *info);
+ 
+/* Subroutine */ int ssbgst_(char *vect, char *uplo, integer *n, integer *ka, 
+	integer *kb, real *ab, integer *ldab, real *bb, integer *ldbb, real *
+	x, integer *ldx, real *work, integer *info);
+ 
+/* Subroutine */ int ssbgv_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, real *ab, integer *ldab, real *bb, integer *ldbb, real *
+	w, real *z__, integer *ldz, real *work, integer *info);
+ 
+/* Subroutine */ int ssbgvd_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, real *ab, integer *ldab, real *bb, integer *ldbb, real *
+	w, real *z__, integer *ldz, real *work, integer *lwork, integer *
+	iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int ssbgvx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *ka, integer *kb, real *ab, integer *ldab, real *bb, integer *
+	ldbb, real *q, integer *ldq, real *vl, real *vu, integer *il, integer 
+	*iu, real *abstol, integer *m, real *w, real *z__, integer *ldz, real 
+	*work, integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int ssbtrd_(char *vect, char *uplo, integer *n, integer *kd, 
+	real *ab, integer *ldab, real *d__, real *e, real *q, integer *ldq, 
+	real *work, integer *info);
+ 
+/* Subroutine */ int sspcon_(char *uplo, integer *n, real *ap, integer *ipiv, 
+	real *anorm, real *rcond, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sspev_(char *jobz, char *uplo, integer *n, real *ap, 
+	real *w, real *z__, integer *ldz, real *work, integer *info);
+ 
+/* Subroutine */ int sspevd_(char *jobz, char *uplo, integer *n, real *ap, 
+	real *w, real *z__, integer *ldz, real *work, integer *lwork, integer 
+	*iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int sspevx_(char *jobz, char *range, char *uplo, integer *n, 
+	real *ap, real *vl, real *vu, integer *il, integer *iu, real *abstol, 
+	integer *m, real *w, real *z__, integer *ldz, real *work, integer *
+	iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int sspgst_(integer *itype, char *uplo, integer *n, real *ap,
+	 real *bp, integer *info);
+ 
+/* Subroutine */ int sspgv_(integer *itype, char *jobz, char *uplo, integer *
+	n, real *ap, real *bp, real *w, real *z__, integer *ldz, real *work, 
+	integer *info);
+ 
+/* Subroutine */ int sspgvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, real *ap, real *bp, real *w, real *z__, integer *ldz, real *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int sspgvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, real *ap, real *bp, real *vl, real *vu, integer *il,
+	 integer *iu, real *abstol, integer *m, real *w, real *z__, integer *
+	ldz, real *work, integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int ssprfs_(char *uplo, integer *n, integer *nrhs, real *ap, 
+	real *afp, integer *ipiv, real *b, integer *ldb, real *x, integer *
+	ldx, real *ferr, real *berr, real *work, integer *iwork, integer *
+	info);
+ 
+/* Subroutine */ int sspsv_(char *uplo, integer *n, integer *nrhs, real *ap, 
+	integer *ipiv, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int sspsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, real *ap, real *afp, integer *ipiv, real *b, integer *ldb, real 
+	*x, integer *ldx, real *rcond, real *ferr, real *berr, real *work, 
+	integer *iwork, integer *info);
+ 
+/* Subroutine */ int ssptrd_(char *uplo, integer *n, real *ap, real *d__, 
+	real *e, real *tau, integer *info);
+ 
+/* Subroutine */ int ssptrf_(char *uplo, integer *n, real *ap, integer *ipiv, 
+	integer *info);
+ 
+/* Subroutine */ int ssptri_(char *uplo, integer *n, real *ap, integer *ipiv, 
+	real *work, integer *info);
+ 
+/* Subroutine */ int ssptrs_(char *uplo, integer *n, integer *nrhs, real *ap, 
+	integer *ipiv, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int sstebz_(char *range, char *order, integer *n, real *vl, 
+	real *vu, integer *il, integer *iu, real *abstol, real *d__, real *e, 
+	integer *m, integer *nsplit, real *w, integer *iblock, integer *
+	isplit, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int sstedc_(char *compz, integer *n, real *d__, real *e, 
+	real *z__, integer *ldz, real *work, integer *lwork, integer *iwork, 
+	integer *liwork, integer *info);
+ 
+/* Subroutine */ int sstegr_(char *jobz, char *range, integer *n, real *d__, 
+	real *e, real *vl, real *vu, integer *il, integer *iu, real *abstol, 
+	integer *m, real *w, real *z__, integer *ldz, integer *isuppz, real *
+	work, integer *lwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int sstein_(integer *n, real *d__, real *e, integer *m, real 
+	*w, integer *iblock, integer *isplit, real *z__, integer *ldz, real *
+	work, integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int ssteqr_(char *compz, integer *n, real *d__, real *e, 
+	real *z__, integer *ldz, real *work, integer *info);
+ 
+/* Subroutine */ int ssterf_(integer *n, real *d__, real *e, integer *info);
+ 
+/* Subroutine */ int sstev_(char *jobz, integer *n, real *d__, real *e, real *
+	z__, integer *ldz, real *work, integer *info);
+ 
+/* Subroutine */ int sstevd_(char *jobz, integer *n, real *d__, real *e, real 
+	*z__, integer *ldz, real *work, integer *lwork, integer *iwork, 
+	integer *liwork, integer *info);
+ 
+/* Subroutine */ int sstevr_(char *jobz, char *range, integer *n, real *d__, 
+	real *e, real *vl, real *vu, integer *il, integer *iu, real *abstol, 
+	integer *m, real *w, real *z__, integer *ldz, integer *isuppz, real *
+	work, integer *lwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int sstevx_(char *jobz, char *range, integer *n, real *d__, 
+	real *e, real *vl, real *vu, integer *il, integer *iu, real *abstol, 
+	integer *m, real *w, real *z__, integer *ldz, real *work, integer *
+	iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int ssycon_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *ipiv, real *anorm, real *rcond, real *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int ssyev_(char *jobz, char *uplo, integer *n, real *a, 
+	integer *lda, real *w, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int ssyevd_(char *jobz, char *uplo, integer *n, real *a, 
+	integer *lda, real *w, real *work, integer *lwork, integer *iwork, 
+	integer *liwork, integer *info);
+ 
+/* Subroutine */ int ssyevr_(char *jobz, char *range, char *uplo, integer *n, 
+	real *a, integer *lda, real *vl, real *vu, integer *il, integer *iu, 
+	real *abstol, integer *m, real *w, real *z__, integer *ldz, integer *
+	isuppz, real *work, integer *lwork, integer *iwork, integer *liwork, 
+	integer *info);
+ 
+/* Subroutine */ int ssyevx_(char *jobz, char *range, char *uplo, integer *n, 
+	real *a, integer *lda, real *vl, real *vu, integer *il, integer *iu, 
+	real *abstol, integer *m, real *w, real *z__, integer *ldz, real *
+	work, integer *lwork, integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int ssygs2_(integer *itype, char *uplo, integer *n, real *a, 
+	integer *lda, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int ssygst_(integer *itype, char *uplo, integer *n, real *a, 
+	integer *lda, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int ssygv_(integer *itype, char *jobz, char *uplo, integer *
+	n, real *a, integer *lda, real *b, integer *ldb, real *w, real *work, 
+	integer *lwork, integer *info);
+ 
+/* Subroutine */ int ssygvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, real *a, integer *lda, real *b, integer *ldb, real *w, real *work, 
+	integer *lwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int ssygvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, real *a, integer *lda, real *b, integer *ldb, real *
+	vl, real *vu, integer *il, integer *iu, real *abstol, integer *m, 
+	real *w, real *z__, integer *ldz, real *work, integer *lwork, integer 
+	*iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int ssyrfs_(char *uplo, integer *n, integer *nrhs, real *a, 
+	integer *lda, real *af, integer *ldaf, integer *ipiv, real *b, 
+	integer *ldb, real *x, integer *ldx, real *ferr, real *berr, real *
+	work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int ssysv_(char *uplo, integer *n, integer *nrhs, real *a, 
+	integer *lda, integer *ipiv, real *b, integer *ldb, real *work, 
+	integer *lwork, integer *info);
+ 
+/* Subroutine */ int ssysvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, real *a, integer *lda, real *af, integer *ldaf, integer *ipiv, 
+	real *b, integer *ldb, real *x, integer *ldx, real *rcond, real *ferr,
+	 real *berr, real *work, integer *lwork, integer *iwork, integer *
+	info);
+ 
+/* Subroutine */ int ssytd2_(char *uplo, integer *n, real *a, integer *lda, 
+	real *d__, real *e, real *tau, integer *info);
+ 
+/* Subroutine */ int ssytf2_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *ipiv, integer *info);
+ 
+/* Subroutine */ int ssytrd_(char *uplo, integer *n, real *a, integer *lda, 
+	real *d__, real *e, real *tau, real *work, integer *lwork, integer *
+	info);
+ 
+/* Subroutine */ int ssytrf_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *ipiv, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int ssytri_(char *uplo, integer *n, real *a, integer *lda, 
+	integer *ipiv, real *work, integer *info);
+ 
+/* Subroutine */ int ssytrs_(char *uplo, integer *n, integer *nrhs, real *a, 
+	integer *lda, integer *ipiv, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int stbcon_(char *norm, char *uplo, char *diag, integer *n, 
+	integer *kd, real *ab, integer *ldab, real *rcond, real *work, 
+	integer *iwork, integer *info);
+ 
+/* Subroutine */ int stbrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, real *ab, integer *ldab, real *b, integer 
+	*ldb, real *x, integer *ldx, real *ferr, real *berr, real *work, 
+	integer *iwork, integer *info);
+ 
+/* Subroutine */ int stbtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, real *ab, integer *ldab, real *b, integer 
+	*ldb, integer *info);
+ 
+/* Subroutine */ int stgevc_(char *side, char *howmny, logical *select, 
+	integer *n, real *a, integer *lda, real *b, integer *ldb, real *vl, 
+	integer *ldvl, real *vr, integer *ldvr, integer *mm, integer *m, real 
+	*work, integer *info);
+ 
+/* Subroutine */ int stgex2_(logical *wantq, logical *wantz, integer *n, real 
+	*a, integer *lda, real *b, integer *ldb, real *q, integer *ldq, real *
+	z__, integer *ldz, integer *j1, integer *n1, integer *n2, real *work, 
+	integer *lwork, integer *info);
+ 
+/* Subroutine */ int stgexc_(logical *wantq, logical *wantz, integer *n, real 
+	*a, integer *lda, real *b, integer *ldb, real *q, integer *ldq, real *
+	z__, integer *ldz, integer *ifst, integer *ilst, real *work, integer *
+	lwork, integer *info);
+ 
+/* Subroutine */ int stgsen_(integer *ijob, logical *wantq, logical *wantz, 
+	logical *select, integer *n, real *a, integer *lda, real *b, integer *
+	ldb, real *alphar, real *alphai, real *beta, real *q, integer *ldq, 
+	real *z__, integer *ldz, integer *m, real *pl, real *pr, real *dif, 
+	real *work, integer *lwork, integer *iwork, integer *liwork, integer *
+	info);
+ 
+/* Subroutine */ int stgsja_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, integer *k, integer *l, real *a, integer *lda,
+	 real *b, integer *ldb, real *tola, real *tolb, real *alpha, real *
+	beta, real *u, integer *ldu, real *v, integer *ldv, real *q, integer *
+	ldq, real *work, integer *ncycle, integer *info);
+ 
+/* Subroutine */ int stgsna_(char *job, char *howmny, logical *select, 
+	integer *n, real *a, integer *lda, real *b, integer *ldb, real *vl, 
+	integer *ldvl, real *vr, integer *ldvr, real *s, real *dif, integer *
+	mm, integer *m, real *work, integer *lwork, integer *iwork, integer *
+	info);
+ 
+/* Subroutine */ int stgsy2_(char *trans, integer *ijob, integer *m, integer *
+	n, real *a, integer *lda, real *b, integer *ldb, real *c__, integer *
+	ldc, real *d__, integer *ldd, real *e, integer *lde, real *f, integer 
+	*ldf, real *scale, real *rdsum, real *rdscal, integer *iwork, integer 
+	*pq, integer *info);
+ 
+/* Subroutine */ int stgsyl_(char *trans, integer *ijob, integer *m, integer *
+	n, real *a, integer *lda, real *b, integer *ldb, real *c__, integer *
+	ldc, real *d__, integer *ldd, real *e, integer *lde, real *f, integer 
+	*ldf, real *scale, real *dif, real *work, integer *lwork, integer *
+	iwork, integer *info);
+ 
+/* Subroutine */ int stpcon_(char *norm, char *uplo, char *diag, integer *n, 
+	real *ap, real *rcond, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int stprfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, real *ap, real *b, integer *ldb, real *x, integer *ldx,
+	 real *ferr, real *berr, real *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int stptri_(char *uplo, char *diag, integer *n, real *ap, 
+	integer *info);
+ 
+/* Subroutine */ int stptrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, real *ap, real *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int strcon_(char *norm, char *uplo, char *diag, integer *n, 
+	real *a, integer *lda, real *rcond, real *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int strevc_(char *side, char *howmny, logical *select, 
+	integer *n, real *t, integer *ldt, real *vl, integer *ldvl, real *vr, 
+	integer *ldvr, integer *mm, integer *m, real *work, integer *info);
+ 
+/* Subroutine */ int strexc_(char *compq, integer *n, real *t, integer *ldt, 
+	real *q, integer *ldq, integer *ifst, integer *ilst, real *work, 
+	integer *info);
+ 
+/* Subroutine */ int strrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, real *a, integer *lda, real *b, integer *ldb, real *x, 
+	integer *ldx, real *ferr, real *berr, real *work, integer *iwork, 
+	integer *info);
+ 
+/* Subroutine */ int strsen_(char *job, char *compq, logical *select, integer 
+	*n, real *t, integer *ldt, real *q, integer *ldq, real *wr, real *wi, 
+	integer *m, real *s, real *sep, real *work, integer *lwork, integer *
+	iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int strsna_(char *job, char *howmny, logical *select, 
+	integer *n, real *t, integer *ldt, real *vl, integer *ldvl, real *vr, 
+	integer *ldvr, real *s, real *sep, integer *mm, integer *m, real *
+	work, integer *ldwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int strsyl_(char *trana, char *tranb, integer *isgn, integer 
+	*m, integer *n, real *a, integer *lda, real *b, integer *ldb, real *
+	c__, integer *ldc, real *scale, integer *info);
+ 
+/* Subroutine */ int strti2_(char *uplo, char *diag, integer *n, real *a, 
+	integer *lda, integer *info);
+ 
+/* Subroutine */ int strtri_(char *uplo, char *diag, integer *n, real *a, 
+	integer *lda, integer *info);
+ 
+/* Subroutine */ int strtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, real *a, integer *lda, real *b, integer *ldb, integer *
+	info);
+ 
+/* Subroutine */ int stzrqf_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, integer *info);
+ 
+/* Subroutine */ int stzrzf_(integer *m, integer *n, real *a, integer *lda, 
+	real *tau, real *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int xerbla_(char *srname, integer *info);
+ 
+/* Subroutine */ int zbdsqr_(char *uplo, integer *n, integer *ncvt, integer *
+	nru, integer *ncc, doublereal *d__, doublereal *e, doublecomplex *vt, 
+	integer *ldvt, doublecomplex *u, integer *ldu, doublecomplex *c__, 
+	integer *ldc, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zdrot_(integer *n, doublecomplex *cx, integer *incx, 
+	doublecomplex *cy, integer *incy, doublereal *c__, doublereal *s);
+ 
+/* Subroutine */ int zdrscl_(integer *n, doublereal *sa, doublecomplex *sx, 
+	integer *incx);
+ 
+/* Subroutine */ int zgbbrd_(char *vect, integer *m, integer *n, integer *ncc,
+	 integer *kl, integer *ku, doublecomplex *ab, integer *ldab, 
+	doublereal *d__, doublereal *e, doublecomplex *q, integer *ldq, 
+	doublecomplex *pt, integer *ldpt, doublecomplex *c__, integer *ldc, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgbcon_(char *norm, integer *n, integer *kl, integer *ku,
+	 doublecomplex *ab, integer *ldab, integer *ipiv, doublereal *anorm, 
+	doublereal *rcond, doublecomplex *work, doublereal *rwork, integer *
+	info);
+ 
+/* Subroutine */ int zgbequ_(integer *m, integer *n, integer *kl, integer *ku,
+	 doublecomplex *ab, integer *ldab, doublereal *r__, doublereal *c__, 
+	doublereal *rowcnd, doublereal *colcnd, doublereal *amax, integer *
+	info);
+ 
+/* Subroutine */ int zgbrfs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, doublecomplex *ab, integer *ldab, doublecomplex *
+	afb, integer *ldafb, integer *ipiv, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgbsv_(integer *n, integer *kl, integer *ku, integer *
+	nrhs, doublecomplex *ab, integer *ldab, integer *ipiv, doublecomplex *
+	b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int zgbsvx_(char *fact, char *trans, integer *n, integer *kl,
+	 integer *ku, integer *nrhs, doublecomplex *ab, integer *ldab, 
+	doublecomplex *afb, integer *ldafb, integer *ipiv, char *equed, 
+	doublereal *r__, doublereal *c__, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *ferr, 
+	doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+	info);
+ 
+/* Subroutine */ int zgbtf2_(integer *m, integer *n, integer *kl, integer *ku,
+	 doublecomplex *ab, integer *ldab, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int zgbtrf_(integer *m, integer *n, integer *kl, integer *ku,
+	 doublecomplex *ab, integer *ldab, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int zgbtrs_(char *trans, integer *n, integer *kl, integer *
+	ku, integer *nrhs, doublecomplex *ab, integer *ldab, integer *ipiv, 
+	doublecomplex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int zgebak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, doublereal *scale, integer *m, doublecomplex *v, 
+	integer *ldv, integer *info);
+ 
+/* Subroutine */ int zgebal_(char *job, integer *n, doublecomplex *a, integer 
+	*lda, integer *ilo, integer *ihi, doublereal *scale, integer *info);
+ 
+/* Subroutine */ int zgebd2_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *d__, doublereal *e, doublecomplex *tauq, 
+	doublecomplex *taup, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zgebrd_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *d__, doublereal *e, doublecomplex *tauq, 
+	doublecomplex *taup, doublecomplex *work, integer *lwork, integer *
+	info);
+ 
+/* Subroutine */ int zgecon_(char *norm, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *anorm, doublereal *rcond, doublecomplex *
+	work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgeequ_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *r__, doublereal *c__, doublereal *rowcnd, 
+	doublereal *colcnd, doublereal *amax, integer *info);
+ 
+/* Subroutine */ int zgees_(char *jobvs, char *sort, L_fp select, integer *n, 
+	doublecomplex *a, integer *lda, integer *sdim, doublecomplex *w, 
+	doublecomplex *vs, integer *ldvs, doublecomplex *work, integer *lwork,
+	 doublereal *rwork, logical *bwork, integer *info);
+ 
+/* Subroutine */ int zgeesx_(char *jobvs, char *sort, L_fp select, char *
+	sense, integer *n, doublecomplex *a, integer *lda, integer *sdim, 
+	doublecomplex *w, doublecomplex *vs, integer *ldvs, doublereal *
+	rconde, doublereal *rcondv, doublecomplex *work, integer *lwork, 
+	doublereal *rwork, logical *bwork, integer *info);
+ 
+/* Subroutine */ int zgeev_(char *jobvl, char *jobvr, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *w, doublecomplex *vl, 
+	integer *ldvl, doublecomplex *vr, integer *ldvr, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgeevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, doublecomplex *a, integer *lda, doublecomplex *w, 
+	doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *ldvr, 
+	integer *ilo, integer *ihi, doublereal *scale, doublereal *abnrm, 
+	doublereal *rconde, doublereal *rcondv, doublecomplex *work, integer *
+	lwork, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgegs_(char *jobvsl, char *jobvsr, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *alpha, doublecomplex *beta, doublecomplex *vsl, 
+	integer *ldvsl, doublecomplex *vsr, integer *ldvsr, doublecomplex *
+	work, integer *lwork, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgegv_(char *jobvl, char *jobvr, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *alpha, doublecomplex *beta, doublecomplex *vl, integer 
+	*ldvl, doublecomplex *vr, integer *ldvr, doublecomplex *work, integer 
+	*lwork, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgehd2_(integer *n, integer *ilo, integer *ihi, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *info);
+ 
+/* Subroutine */ int zgehrd_(integer *n, integer *ilo, integer *ihi, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zgelq2_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zgelqf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int zgels_(char *trans, integer *m, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zgelsx_(integer *m, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	integer *jpvt, doublereal *rcond, integer *rank, doublecomplex *work, 
+	doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgelsy_(integer *m, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	integer *jpvt, doublereal *rcond, integer *rank, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgeql2_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zgeqlf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int zgeqp3_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, integer *jpvt, doublecomplex *tau, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgeqpf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, integer *jpvt, doublecomplex *tau, doublecomplex *work, 
+	doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgeqr2_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zgeqrf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int zgerfs_(char *trans, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf, 
+	integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x, 
+	integer *ldx, doublereal *ferr, doublereal *berr, doublecomplex *work,
+	 doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgerq2_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zgerqf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int zgesc2_(integer *n, doublecomplex *a, integer *lda, 
+	doublecomplex *rhs, integer *ipiv, integer *jpiv, doublereal *scale);
+ 
+/* Subroutine */ int zgesv_(integer *n, integer *nrhs, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublecomplex *b, integer *ldb, integer *
+	info);
+ 
+/* Subroutine */ int zgesvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, integer *ipiv, char *equed, doublereal *r__, doublereal *c__, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+	work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgetc2_(integer *n, doublecomplex *a, integer *lda, 
+	integer *ipiv, integer *jpiv, integer *info);
+ 
+/* Subroutine */ int zgetf2_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int zgetrf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int zgetri_(integer *n, doublecomplex *a, integer *lda, 
+	integer *ipiv, doublecomplex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zgetrs_(char *trans, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b, 
+	integer *ldb, integer *info);
+ 
+/* Subroutine */ int zggbak_(char *job, char *side, integer *n, integer *ilo, 
+	integer *ihi, doublereal *lscale, doublereal *rscale, integer *m, 
+	doublecomplex *v, integer *ldv, integer *info);
+ 
+/* Subroutine */ int zggbal_(char *job, integer *n, doublecomplex *a, integer 
+	*lda, doublecomplex *b, integer *ldb, integer *ilo, integer *ihi, 
+	doublereal *lscale, doublereal *rscale, doublereal *work, integer *
+	info);
+ 
+/* Subroutine */ int zgges_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	delctg, integer *n, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, integer *sdim, doublecomplex *alpha, doublecomplex *
+	beta, doublecomplex *vsl, integer *ldvsl, doublecomplex *vsr, integer 
+	*ldvsr, doublecomplex *work, integer *lwork, doublereal *rwork, 
+	logical *bwork, integer *info);
+ 
+/* Subroutine */ int zggesx_(char *jobvsl, char *jobvsr, char *sort, L_fp 
+	delctg, char *sense, integer *n, doublecomplex *a, integer *lda, 
+	doublecomplex *b, integer *ldb, integer *sdim, doublecomplex *alpha, 
+	doublecomplex *beta, doublecomplex *vsl, integer *ldvsl, 
+	doublecomplex *vsr, integer *ldvsr, doublereal *rconde, doublereal *
+	rcondv, doublecomplex *work, integer *lwork, doublereal *rwork, 
+	integer *iwork, integer *liwork, logical *bwork, integer *info);
+ 
+/* Subroutine */ int zggev_(char *jobvl, char *jobvr, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *alpha, doublecomplex *beta, doublecomplex *vl, integer 
+	*ldvl, doublecomplex *vr, integer *ldvr, doublecomplex *work, integer 
+	*lwork, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zggevx_(char *balanc, char *jobvl, char *jobvr, char *
+	sense, integer *n, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, doublecomplex *alpha, doublecomplex *beta, 
+	doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *ldvr, 
+	integer *ilo, integer *ihi, doublereal *lscale, doublereal *rscale, 
+	doublereal *abnrm, doublereal *bbnrm, doublereal *rconde, doublereal *
+	rcondv, doublecomplex *work, integer *lwork, doublereal *rwork, 
+	integer *iwork, logical *bwork, integer *info);
+ 
+/* Subroutine */ int zggglm_(integer *n, integer *m, integer *p, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *d__, doublecomplex *x, doublecomplex *y, doublecomplex 
+	*work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zgghrd_(char *compq, char *compz, integer *n, integer *
+	ilo, integer *ihi, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, doublecomplex *q, integer *ldq, doublecomplex *z__, 
+	integer *ldz, integer *info);
+ 
+/* Subroutine */ int zgglse_(integer *m, integer *n, integer *p, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *c__, doublecomplex *d__, doublecomplex *x, 
+	doublecomplex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zggqrf_(integer *n, integer *m, integer *p, 
+	doublecomplex *a, integer *lda, doublecomplex *taua, doublecomplex *b,
+	 integer *ldb, doublecomplex *taub, doublecomplex *work, integer *
+	lwork, integer *info);
+ 
+/* Subroutine */ int zggrqf_(integer *m, integer *p, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *taua, doublecomplex *b,
+	 integer *ldb, doublecomplex *taub, doublecomplex *work, integer *
+	lwork, integer *info);
+ 
+/* Subroutine */ int zggsvd_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *n, integer *p, integer *k, integer *l, doublecomplex *a, 
+	integer *lda, doublecomplex *b, integer *ldb, doublereal *alpha, 
+	doublereal *beta, doublecomplex *u, integer *ldu, doublecomplex *v, 
+	integer *ldv, doublecomplex *q, integer *ldq, doublecomplex *work, 
+	doublereal *rwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int zggsvp_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, doublecomplex *a, integer *lda, doublecomplex 
+	*b, integer *ldb, doublereal *tola, doublereal *tolb, integer *k, 
+	integer *l, doublecomplex *u, integer *ldu, doublecomplex *v, integer 
+	*ldv, doublecomplex *q, integer *ldq, integer *iwork, doublereal *
+	rwork, doublecomplex *tau, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zgtcon_(char *norm, integer *n, doublecomplex *dl, 
+	doublecomplex *d__, doublecomplex *du, doublecomplex *du2, integer *
+	ipiv, doublereal *anorm, doublereal *rcond, doublecomplex *work, 
+	integer *info);
+ 
+/* Subroutine */ int zgtrfs_(char *trans, integer *n, integer *nrhs, 
+	doublecomplex *dl, doublecomplex *d__, doublecomplex *du, 
+	doublecomplex *dlf, doublecomplex *df, doublecomplex *duf, 
+	doublecomplex *du2, integer *ipiv, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zgtsv_(integer *n, integer *nrhs, doublecomplex *dl, 
+	doublecomplex *d__, doublecomplex *du, doublecomplex *b, integer *ldb,
+	 integer *info);
+ 
+/* Subroutine */ int zgtsvx_(char *fact, char *trans, integer *n, integer *
+	nrhs, doublecomplex *dl, doublecomplex *d__, doublecomplex *du, 
+	doublecomplex *dlf, doublecomplex *df, doublecomplex *duf, 
+	doublecomplex *du2, integer *ipiv, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *ferr, 
+	doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+	info);
+ 
+/* Subroutine */ int zgttrf_(integer *n, doublecomplex *dl, doublecomplex *
+	d__, doublecomplex *du, doublecomplex *du2, integer *ipiv, integer *
+	info);
+ 
+/* Subroutine */ int zgttrs_(char *trans, integer *n, integer *nrhs, 
+	doublecomplex *dl, doublecomplex *d__, doublecomplex *du, 
+	doublecomplex *du2, integer *ipiv, doublecomplex *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int zgtts2_(integer *itrans, integer *n, integer *nrhs, 
+	doublecomplex *dl, doublecomplex *d__, doublecomplex *du, 
+	doublecomplex *du2, integer *ipiv, doublecomplex *b, integer *ldb);
+ 
+/* Subroutine */ int zhbev_(char *jobz, char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *w, doublecomplex *z__, 
+	integer *ldz, doublecomplex *work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zhbevd_(char *jobz, char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *w, doublecomplex *z__, 
+	integer *ldz, doublecomplex *work, integer *lwork, doublereal *rwork, 
+	integer *lrwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int zhbevx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *kd, doublecomplex *ab, integer *ldab, doublecomplex *q, 
+	integer *ldq, doublereal *vl, doublereal *vu, integer *il, integer *
+	iu, doublereal *abstol, integer *m, doublereal *w, doublecomplex *z__,
+	 integer *ldz, doublecomplex *work, doublereal *rwork, integer *iwork,
+	 integer *ifail, integer *info);
+ 
+/* Subroutine */ int zhbgst_(char *vect, char *uplo, integer *n, integer *ka, 
+	integer *kb, doublecomplex *ab, integer *ldab, doublecomplex *bb, 
+	integer *ldbb, doublecomplex *x, integer *ldx, doublecomplex *work, 
+	doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zhbgv_(char *jobz, char *uplo, integer *n, integer *ka, 
+	integer *kb, doublecomplex *ab, integer *ldab, doublecomplex *bb, 
+	integer *ldbb, doublereal *w, doublecomplex *z__, integer *ldz, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zhbgvx_(char *jobz, char *range, char *uplo, integer *n, 
+	integer *ka, integer *kb, doublecomplex *ab, integer *ldab, 
+	doublecomplex *bb, integer *ldbb, doublecomplex *q, integer *ldq, 
+	doublereal *vl, doublereal *vu, integer *il, integer *iu, doublereal *
+	abstol, integer *m, doublereal *w, doublecomplex *z__, integer *ldz, 
+	doublecomplex *work, doublereal *rwork, integer *iwork, integer *
+	ifail, integer *info);
+ 
+/* Subroutine */ int zhbtrd_(char *vect, char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *d__, doublereal *e, 
+	doublecomplex *q, integer *ldq, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zhecon_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublereal *anorm, doublereal *rcond, 
+	doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zheev_(char *jobz, char *uplo, integer *n, doublecomplex 
+	*a, integer *lda, doublereal *w, doublecomplex *work, integer *lwork, 
+	doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zheevd_(char *jobz, char *uplo, integer *n, 
+	doublecomplex *a, integer *lda, doublereal *w, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *lrwork, integer *iwork, 
+	integer *liwork, integer *info);
+ 
+/* Subroutine */ int zheevr_(char *jobz, char *range, char *uplo, integer *n, 
+	doublecomplex *a, integer *lda, doublereal *vl, doublereal *vu, 
+	integer *il, integer *iu, doublereal *abstol, integer *m, doublereal *
+	w, doublecomplex *z__, integer *ldz, integer *isuppz, doublecomplex *
+	work, integer *lwork, doublereal *rwork, integer *lrwork, integer *
+	iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int zheevx_(char *jobz, char *range, char *uplo, integer *n, 
+	doublecomplex *a, integer *lda, doublereal *vl, doublereal *vu, 
+	integer *il, integer *iu, doublereal *abstol, integer *m, doublereal *
+	w, doublecomplex *z__, integer *ldz, doublecomplex *work, integer *
+	lwork, doublereal *rwork, integer *iwork, integer *ifail, integer *
+	info);
+ 
+/* Subroutine */ int zhegs2_(integer *itype, char *uplo, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int zhegst_(integer *itype, char *uplo, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int zhegv_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublereal *w, doublecomplex *work, integer *lwork, doublereal *rwork,
+	 integer *info);
+ 
+/* Subroutine */ int zhegvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublereal *w, doublecomplex *work, integer *lwork, doublereal *rwork,
+	 integer *lrwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int zhegvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, doublereal *vl, doublereal *vu, integer *il, integer *
+	iu, doublereal *abstol, integer *m, doublereal *w, doublecomplex *z__,
+	 integer *ldz, doublecomplex *work, integer *lwork, doublereal *rwork,
+	 integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int zherfs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf, 
+	integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x, 
+	integer *ldx, doublereal *ferr, doublereal *berr, doublecomplex *work,
+	 doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zhesv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b, 
+	integer *ldb, doublecomplex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zhesvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x,
+	 integer *ldx, doublereal *rcond, doublereal *ferr, doublereal *berr, 
+	doublecomplex *work, integer *lwork, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zhetf2_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int zhetrd_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *d__, doublereal *e, doublecomplex *tau, 
+	doublecomplex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zhetrf_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublecomplex *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int zhetri_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zhetrs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b, 
+	integer *ldb, integer *info);
+ 
+/* Subroutine */ int zhgeqz_(char *job, char *compq, char *compz, integer *n, 
+	integer *ilo, integer *ihi, doublecomplex *a, integer *lda, 
+	doublecomplex *b, integer *ldb, doublecomplex *alpha, doublecomplex *
+	beta, doublecomplex *q, integer *ldq, doublecomplex *z__, integer *
+	ldz, doublecomplex *work, integer *lwork, doublereal *rwork, integer *
+	info);
+ 
+/* Subroutine */ int zhpcon_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *ipiv, doublereal *anorm, doublereal *rcond, doublecomplex *
+	work, integer *info);
+ 
+/* Subroutine */ int zhpev_(char *jobz, char *uplo, integer *n, doublecomplex 
+	*ap, doublereal *w, doublecomplex *z__, integer *ldz, doublecomplex *
+	work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zhpevd_(char *jobz, char *uplo, integer *n, 
+	doublecomplex *ap, doublereal *w, doublecomplex *z__, integer *ldz, 
+	doublecomplex *work, integer *lwork, doublereal *rwork, integer *
+	lrwork, integer *iwork, integer *liwork, integer *info);
+ 
+/* Subroutine */ int zhpevx_(char *jobz, char *range, char *uplo, integer *n, 
+	doublecomplex *ap, doublereal *vl, doublereal *vu, integer *il, 
+	integer *iu, doublereal *abstol, integer *m, doublereal *w, 
+	doublecomplex *z__, integer *ldz, doublecomplex *work, doublereal *
+	rwork, integer *iwork, integer *ifail, integer *info);
+ 
+/* Subroutine */ int zhpgst_(integer *itype, char *uplo, integer *n, 
+	doublecomplex *ap, doublecomplex *bp, integer *info);
+ 
+/* Subroutine */ int zhpgv_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublecomplex *ap, doublecomplex *bp, doublereal *w, doublecomplex 
+	*z__, integer *ldz, doublecomplex *work, doublereal *rwork, integer *
+	info);
+ 
+/* Subroutine */ int zhpgvd_(integer *itype, char *jobz, char *uplo, integer *
+	n, doublecomplex *ap, doublecomplex *bp, doublereal *w, doublecomplex 
+	*z__, integer *ldz, doublecomplex *work, integer *lwork, doublereal *
+	rwork, integer *lrwork, integer *iwork, integer *liwork, integer *
+	info);
+ 
+/* Subroutine */ int zhpgvx_(integer *itype, char *jobz, char *range, char *
+	uplo, integer *n, doublecomplex *ap, doublecomplex *bp, doublereal *
+	vl, doublereal *vu, integer *il, integer *iu, doublereal *abstol, 
+	integer *m, doublereal *w, doublecomplex *z__, integer *ldz, 
+	doublecomplex *work, doublereal *rwork, integer *iwork, integer *
+	ifail, integer *info);
+ 
+/* Subroutine */ int zhprfs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, doublecomplex *afp, integer *ipiv, doublecomplex *
+	b, integer *ldb, doublecomplex *x, integer *ldx, doublereal *ferr, 
+	doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+	info);
+ 
+/* Subroutine */ int zhpsv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, integer *ipiv, doublecomplex *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int zhpsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *ap, doublecomplex *afp, integer *ipiv, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+	work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zhptrd_(char *uplo, integer *n, doublecomplex *ap, 
+	doublereal *d__, doublereal *e, doublecomplex *tau, integer *info);
+ 
+/* Subroutine */ int zhptrf_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *ipiv, integer *info);
+ 
+/* Subroutine */ int zhptri_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *ipiv, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zhptrs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, integer *ipiv, doublecomplex *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int zhsein_(char *side, char *eigsrc, char *initv, logical *
+	select, integer *n, doublecomplex *h__, integer *ldh, doublecomplex *
+	w, doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *ldvr,
+	 integer *mm, integer *m, doublecomplex *work, doublereal *rwork, 
+	integer *ifaill, integer *ifailr, integer *info);
+ 
+/* Subroutine */ int zhseqr_(char *job, char *compz, integer *n, integer *ilo,
+	 integer *ihi, doublecomplex *h__, integer *ldh, doublecomplex *w, 
+	doublecomplex *z__, integer *ldz, doublecomplex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int zlabrd_(integer *m, integer *n, integer *nb, 
+	doublecomplex *a, integer *lda, doublereal *d__, doublereal *e, 
+	doublecomplex *tauq, doublecomplex *taup, doublecomplex *x, integer *
+	ldx, doublecomplex *y, integer *ldy);
+ 
+/* Subroutine */ int zlacgv_(integer *n, doublecomplex *x, integer *incx);
+ 
+/* Subroutine */ int zlacon_(integer *n, doublecomplex *v, doublecomplex *x, 
+	doublereal *est, integer *kase);
+ 
+/* Subroutine */ int zlacp2_(char *uplo, integer *m, integer *n, doublereal *
+	a, integer *lda, doublecomplex *b, integer *ldb);
+ 
+/* Subroutine */ int zlacpy_(char *uplo, integer *m, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb);
+ 
+/* Subroutine */ int zlacrm_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *b, integer *ldb, doublecomplex *c__, 
+	integer *ldc, doublereal *rwork);
+ 
+/* Subroutine */ int zlacrt_(integer *n, doublecomplex *cx, integer *incx, 
+	doublecomplex *cy, integer *incy, doublecomplex *c__, doublecomplex *
+	s);
+ 
+/* Subroutine */ int zlaed0_(integer *qsiz, integer *n, doublereal *d__, 
+	doublereal *e, doublecomplex *q, integer *ldq, doublecomplex *qstore, 
+	integer *ldqs, doublereal *rwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int zlaed7_(integer *n, integer *cutpnt, integer *qsiz, 
+	integer *tlvls, integer *curlvl, integer *curpbm, doublereal *d__, 
+	doublecomplex *q, integer *ldq, doublereal *rho, integer *indxq, 
+	doublereal *qstore, integer *qptr, integer *prmptr, integer *perm, 
+	integer *givptr, integer *givcol, doublereal *givnum, doublecomplex *
+	work, doublereal *rwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int zlaed8_(integer *k, integer *n, integer *qsiz, 
+	doublecomplex *q, integer *ldq, doublereal *d__, doublereal *rho, 
+	integer *cutpnt, doublereal *z__, doublereal *dlamda, doublecomplex *
+	q2, integer *ldq2, doublereal *w, integer *indxp, integer *indx, 
+	integer *indxq, integer *perm, integer *givptr, integer *givcol, 
+	doublereal *givnum, integer *info);
+ 
+/* Subroutine */ int zlaein_(logical *rightv, logical *noinit, integer *n, 
+	doublecomplex *h__, integer *ldh, doublecomplex *w, doublecomplex *v, 
+	doublecomplex *b, integer *ldb, doublereal *rwork, doublereal *eps3, 
+	doublereal *smlnum, integer *info);
+ 
+/* Subroutine */ int zlaesy_(doublecomplex *a, doublecomplex *b, 
+	doublecomplex *c__, doublecomplex *rt1, doublecomplex *rt2, 
+	doublecomplex *evscal, doublecomplex *cs1, doublecomplex *sn1);
+ 
+/* Subroutine */ int zlaev2_(doublecomplex *a, doublecomplex *b, 
+	doublecomplex *c__, doublereal *rt1, doublereal *rt2, doublereal *cs1,
+	 doublecomplex *sn1);
+ 
+/* Subroutine */ int zlags2_(logical *upper, doublereal *a1, doublecomplex *
+	a2, doublereal *a3, doublereal *b1, doublecomplex *b2, doublereal *b3,
+	 doublereal *csu, doublecomplex *snu, doublereal *csv, doublecomplex *
+	snv, doublereal *csq, doublecomplex *snq);
+ 
+/* Subroutine */ int zlagtm_(char *trans, integer *n, integer *nrhs, 
+	doublereal *alpha, doublecomplex *dl, doublecomplex *d__, 
+	doublecomplex *du, doublecomplex *x, integer *ldx, doublereal *beta, 
+	doublecomplex *b, integer *ldb);
+ 
+/* Subroutine */ int zlahef_(char *uplo, integer *n, integer *nb, integer *kb,
+	 doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *w, 
+	integer *ldw, integer *info);
+ 
+/* Subroutine */ int zlahqr_(logical *wantt, logical *wantz, integer *n, 
+	integer *ilo, integer *ihi, doublecomplex *h__, integer *ldh, 
+	doublecomplex *w, integer *iloz, integer *ihiz, doublecomplex *z__, 
+	integer *ldz, integer *info);
+ 
+/* Subroutine */ int zlahrd_(integer *n, integer *k, integer *nb, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *t, 
+	integer *ldt, doublecomplex *y, integer *ldy);
+ 
+/* Subroutine */ int zlaic1_(integer *job, integer *j, doublecomplex *x, 
+	doublereal *sest, doublecomplex *w, doublecomplex *gamma, doublereal *
+	sestpr, doublecomplex *s, doublecomplex *c__);
+ 
+/* Subroutine */ int zlals0_(integer *icompq, integer *nl, integer *nr, 
+	integer *sqre, integer *nrhs, doublecomplex *b, integer *ldb, 
+	doublecomplex *bx, integer *ldbx, integer *perm, integer *givptr, 
+	integer *givcol, integer *ldgcol, doublereal *givnum, integer *ldgnum,
+	 doublereal *poles, doublereal *difl, doublereal *difr, doublereal *
+	z__, integer *k, doublereal *c__, doublereal *s, doublereal *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int zlalsa_(integer *icompq, integer *smlsiz, integer *n, 
+	integer *nrhs, doublecomplex *b, integer *ldb, doublecomplex *bx, 
+	integer *ldbx, doublereal *u, integer *ldu, doublereal *vt, integer *
+	k, doublereal *difl, doublereal *difr, doublereal *z__, doublereal *
+	poles, integer *givptr, integer *givcol, integer *ldgcol, integer *
+	perm, doublereal *givnum, doublereal *c__, doublereal *s, doublereal *
+	rwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int zlapll_(integer *n, doublecomplex *x, integer *incx, 
+	doublecomplex *y, integer *incy, doublereal *ssmin);
+ 
+/* Subroutine */ int zlapmt_(logical *forwrd, integer *m, integer *n, 
+	doublecomplex *x, integer *ldx, integer *k);
+ 
+/* Subroutine */ int zlaqgb_(integer *m, integer *n, integer *kl, integer *ku,
+	 doublecomplex *ab, integer *ldab, doublereal *r__, doublereal *c__, 
+	doublereal *rowcnd, doublereal *colcnd, doublereal *amax, char *equed);
+ 
+/* Subroutine */ int zlaqge_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *r__, doublereal *c__, doublereal *rowcnd, 
+	doublereal *colcnd, doublereal *amax, char *equed);
+ 
+/* Subroutine */ int zlaqhb_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *s, doublereal *scond, 
+	doublereal *amax, char *equed);
+ 
+/* Subroutine */ int zlaqhe_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *s, doublereal *scond, doublereal *amax, 
+	char *equed);
+ 
+/* Subroutine */ int zlaqhp_(char *uplo, integer *n, doublecomplex *ap, 
+	doublereal *s, doublereal *scond, doublereal *amax, char *equed);
+ 
+/* Subroutine */ int zlaqp2_(integer *m, integer *n, integer *offset, 
+	doublecomplex *a, integer *lda, integer *jpvt, doublecomplex *tau, 
+	doublereal *vn1, doublereal *vn2, doublecomplex *work);
+ 
+/* Subroutine */ int zlaqps_(integer *m, integer *n, integer *offset, integer 
+	*nb, integer *kb, doublecomplex *a, integer *lda, integer *jpvt, 
+	doublecomplex *tau, doublereal *vn1, doublereal *vn2, doublecomplex *
+	auxv, doublecomplex *f, integer *ldf);
+ 
+/* Subroutine */ int zlaqsb_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *s, doublereal *scond, 
+	doublereal *amax, char *equed);
+ 
+/* Subroutine */ int zlaqsp_(char *uplo, integer *n, doublecomplex *ap, 
+	doublereal *s, doublereal *scond, doublereal *amax, char *equed);
+ 
+/* Subroutine */ int zlaqsy_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *s, doublereal *scond, doublereal *amax, 
+	char *equed);
+ 
+/* Subroutine */ int zlar1v_(integer *n, integer *b1, integer *bn, doublereal 
+	*sigma, doublereal *d__, doublereal *l, doublereal *ld, doublereal *
+	lld, doublereal *gersch, doublecomplex *z__, doublereal *ztz, 
+	doublereal *mingma, integer *r__, integer *isuppz, doublereal *work);
+ 
+/* Subroutine */ int zlar2v_(integer *n, doublecomplex *x, doublecomplex *y, 
+	doublecomplex *z__, integer *incx, doublereal *c__, doublecomplex *s, 
+	integer *incc);
+ 
+/* Subroutine */ int zlarcm_(integer *m, integer *n, doublereal *a, integer *
+	lda, doublecomplex *b, integer *ldb, doublecomplex *c__, integer *ldc,
+	 doublereal *rwork);
+ 
+/* Subroutine */ int zlarf_(char *side, integer *m, integer *n, doublecomplex 
+	*v, integer *incv, doublecomplex *tau, doublecomplex *c__, integer *
+	ldc, doublecomplex *work);
+ 
+/* Subroutine */ int zlarfb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, doublecomplex *v, integer 
+	*ldv, doublecomplex *t, integer *ldt, doublecomplex *c__, integer *
+	ldc, doublecomplex *work, integer *ldwork);
+ 
+/* Subroutine */ int zlarfg_(integer *n, doublecomplex *alpha, doublecomplex *
+	x, integer *incx, doublecomplex *tau);
+ 
+/* Subroutine */ int zlarft_(char *direct, char *storev, integer *n, integer *
+	k, doublecomplex *v, integer *ldv, doublecomplex *tau, doublecomplex *
+	t, integer *ldt);
+ 
+/* Subroutine */ int zlarfx_(char *side, integer *m, integer *n, 
+	doublecomplex *v, doublecomplex *tau, doublecomplex *c__, integer *
+	ldc, doublecomplex *work);
+ 
+/* Subroutine */ int zlargv_(integer *n, doublecomplex *x, integer *incx, 
+	doublecomplex *y, integer *incy, doublereal *c__, integer *incc);
+ 
+/* Subroutine */ int zlarnv_(integer *idist, integer *iseed, integer *n, 
+	doublecomplex *x);
+ 
+/* Subroutine */ int zlarrv_(integer *n, doublereal *d__, doublereal *l, 
+	integer *isplit, integer *m, doublereal *w, integer *iblock, 
+	doublereal *gersch, doublereal *tol, doublecomplex *z__, integer *ldz,
+	 integer *isuppz, doublereal *work, integer *iwork, integer *info);
+ 
+/* Subroutine */ int zlartg_(doublecomplex *f, doublecomplex *g, doublereal *
+	cs, doublecomplex *sn, doublecomplex *r__);
+ 
+/* Subroutine */ int zlartv_(integer *n, doublecomplex *x, integer *incx, 
+	doublecomplex *y, integer *incy, doublereal *c__, doublecomplex *s, 
+	integer *incc);
+ 
+/* Subroutine */ int zlarz_(char *side, integer *m, integer *n, integer *l, 
+	doublecomplex *v, integer *incv, doublecomplex *tau, doublecomplex *
+	c__, integer *ldc, doublecomplex *work);
+ 
+/* Subroutine */ int zlarzb_(char *side, char *trans, char *direct, char *
+	storev, integer *m, integer *n, integer *k, integer *l, doublecomplex 
+	*v, integer *ldv, doublecomplex *t, integer *ldt, doublecomplex *c__, 
+	integer *ldc, doublecomplex *work, integer *ldwork);
+ 
+/* Subroutine */ int zlarzt_(char *direct, char *storev, integer *n, integer *
+	k, doublecomplex *v, integer *ldv, doublecomplex *tau, doublecomplex *
+	t, integer *ldt);
+ 
+/* Subroutine */ int zlascl_(char *type__, integer *kl, integer *ku, 
+	doublereal *cfrom, doublereal *cto, integer *m, integer *n, 
+	doublecomplex *a, integer *lda, integer *info);
+ 
+/* Subroutine */ int zlaset_(char *uplo, integer *m, integer *n, 
+	doublecomplex *alpha, doublecomplex *beta, doublecomplex *a, integer *
+	lda);
+ 
+/* Subroutine */ int zlasr_(char *side, char *pivot, char *direct, integer *m,
+	 integer *n, doublereal *c__, doublereal *s, doublecomplex *a, 
+	integer *lda);
+ 
+/* Subroutine */ int zlassq_(integer *n, doublecomplex *x, integer *incx, 
+	doublereal *scale, doublereal *sumsq);
+ 
+/* Subroutine */ int zlaswp_(integer *n, doublecomplex *a, integer *lda, 
+	integer *k1, integer *k2, integer *ipiv, integer *incx);
+ 
+/* Subroutine */ int zlasyf_(char *uplo, integer *n, integer *nb, integer *kb,
+	 doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *w, 
+	integer *ldw, integer *info);
+ 
+/* Subroutine */ int zlatbs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, integer *kd, doublecomplex *ab, integer *ldab, 
+	doublecomplex *x, doublereal *scale, doublereal *cnorm, integer *info);
+ 
+/* Subroutine */ int zlatdf_(integer *ijob, integer *n, doublecomplex *z__, 
+	integer *ldz, doublecomplex *rhs, doublereal *rdsum, doublereal *
+	rdscal, integer *ipiv, integer *jpiv);
+ 
+/* Subroutine */ int zlatps_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, doublecomplex *ap, doublecomplex *x, doublereal *
+	scale, doublereal *cnorm, integer *info);
+ 
+/* Subroutine */ int zlatrd_(char *uplo, integer *n, integer *nb, 
+	doublecomplex *a, integer *lda, doublereal *e, doublecomplex *tau, 
+	doublecomplex *w, integer *ldw);
+ 
+/* Subroutine */ int zlatrs_(char *uplo, char *trans, char *diag, char *
+	normin, integer *n, doublecomplex *a, integer *lda, doublecomplex *x, 
+	doublereal *scale, doublereal *cnorm, integer *info);
+ 
+/* Subroutine */ int zlatrz_(integer *m, integer *n, integer *l, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work);
+ 
+/* Subroutine */ int zlatzm_(char *side, integer *m, integer *n, 
+	doublecomplex *v, integer *incv, doublecomplex *tau, doublecomplex *
+	c1, doublecomplex *c2, integer *ldc, doublecomplex *work);
+ 
+/* Subroutine */ int zlauu2_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *info);
+ 
+/* Subroutine */ int zlauum_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *info);
+ 
+/* Subroutine */ int zpbcon_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *anorm, doublereal *
+	rcond, doublecomplex *work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zpbequ_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, doublereal *s, doublereal *scond, 
+	doublereal *amax, integer *info);
+ 
+/* Subroutine */ int zpbrfs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, doublecomplex *ab, integer *ldab, doublecomplex *afb, integer *
+	ldafb, doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx,
+	 doublereal *ferr, doublereal *berr, doublecomplex *work, doublereal *
+	rwork, integer *info);
+ 
+/* Subroutine */ int zpbstf_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, integer *info);
+ 
+/* Subroutine */ int zpbsv_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, doublecomplex *ab, integer *ldab, doublecomplex *b, integer *
+	ldb, integer *info);
+ 
+/* Subroutine */ int zpbsvx_(char *fact, char *uplo, integer *n, integer *kd, 
+	integer *nrhs, doublecomplex *ab, integer *ldab, doublecomplex *afb, 
+	integer *ldafb, char *equed, doublereal *s, doublecomplex *b, integer 
+	*ldb, doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *
+	ferr, doublereal *berr, doublecomplex *work, doublereal *rwork, 
+	integer *info);
+ 
+/* Subroutine */ int zpbtf2_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, integer *info);
+ 
+/* Subroutine */ int zpbtrf_(char *uplo, integer *n, integer *kd, 
+	doublecomplex *ab, integer *ldab, integer *info);
+ 
+/* Subroutine */ int zpbtrs_(char *uplo, integer *n, integer *kd, integer *
+	nrhs, doublecomplex *ab, integer *ldab, doublecomplex *b, integer *
+	ldb, integer *info);
+ 
+/* Subroutine */ int zpocon_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublereal *anorm, doublereal *rcond, doublecomplex *
+	work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zpoequ_(integer *n, doublecomplex *a, integer *lda, 
+	doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+ 
+/* Subroutine */ int zporfs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *ferr, doublereal *berr, doublecomplex *work, doublereal *
+	rwork, integer *info);
+ 
+/* Subroutine */ int zposv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int zposvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, char *equed, doublereal *s, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *rcond, doublereal *ferr, 
+	doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+	info);
+ 
+/* Subroutine */ int zpotf2_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *info);
+ 
+/* Subroutine */ int zpotrf_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *info);
+ 
+/* Subroutine */ int zpotri_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *info);
+ 
+/* Subroutine */ int zpotrs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int zppcon_(char *uplo, integer *n, doublecomplex *ap, 
+	doublereal *anorm, doublereal *rcond, doublecomplex *work, doublereal 
+	*rwork, integer *info);
+ 
+/* Subroutine */ int zppequ_(char *uplo, integer *n, doublecomplex *ap, 
+	doublereal *s, doublereal *scond, doublereal *amax, integer *info);
+ 
+/* Subroutine */ int zpprfs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, doublecomplex *afp, doublecomplex *b, integer *ldb,
+	 doublecomplex *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zppsv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, doublecomplex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int zppsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *ap, doublecomplex *afp, char *equed, doublereal *
+	s, doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+	work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zpptrf_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *info);
+ 
+/* Subroutine */ int zpptri_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *info);
+ 
+/* Subroutine */ int zpptrs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, doublecomplex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int zptcon_(integer *n, doublereal *d__, doublecomplex *e, 
+	doublereal *anorm, doublereal *rcond, doublereal *rwork, integer *
+	info);
+ 
+/* Subroutine */ int zptrfs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *d__, doublecomplex *e, doublereal *df, doublecomplex *ef, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *ferr, doublereal *berr, doublecomplex *work, doublereal *
+	rwork, integer *info);
+ 
+/* Subroutine */ int zptsv_(integer *n, integer *nrhs, doublereal *d__, 
+	doublecomplex *e, doublecomplex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int zptsvx_(char *fact, integer *n, integer *nrhs, 
+	doublereal *d__, doublecomplex *e, doublereal *df, doublecomplex *ef, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+	work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zpttrf_(integer *n, doublereal *d__, doublecomplex *e, 
+	integer *info);
+ 
+/* Subroutine */ int zpttrs_(char *uplo, integer *n, integer *nrhs, 
+	doublereal *d__, doublecomplex *e, doublecomplex *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int zptts2_(integer *iuplo, integer *n, integer *nrhs, 
+	doublereal *d__, doublecomplex *e, doublecomplex *b, integer *ldb);
+ 
+/* Subroutine */ int zrot_(integer *n, doublecomplex *cx, integer *incx, 
+	doublecomplex *cy, integer *incy, doublereal *c__, doublecomplex *s);
+ 
+/* Subroutine */ int zspcon_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *ipiv, doublereal *anorm, doublereal *rcond, doublecomplex *
+	work, integer *info);
+ 
+/* Subroutine */ int zspmv_(char *uplo, integer *n, doublecomplex *alpha, 
+	doublecomplex *ap, doublecomplex *x, integer *incx, doublecomplex *
+	beta, doublecomplex *y, integer *incy);
+ 
+/* Subroutine */ int zspr_(char *uplo, integer *n, doublecomplex *alpha, 
+	doublecomplex *x, integer *incx, doublecomplex *ap);
+ 
+/* Subroutine */ int zsprfs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, doublecomplex *afp, integer *ipiv, doublecomplex *
+	b, integer *ldb, doublecomplex *x, integer *ldx, doublereal *ferr, 
+	doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+	info);
+ 
+/* Subroutine */ int zspsv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, integer *ipiv, doublecomplex *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int zspsvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *ap, doublecomplex *afp, integer *ipiv, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *rcond, doublereal *ferr, doublereal *berr, doublecomplex *
+	work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zsptrf_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *ipiv, integer *info);
+ 
+/* Subroutine */ int zsptri_(char *uplo, integer *n, doublecomplex *ap, 
+	integer *ipiv, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zsptrs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *ap, integer *ipiv, doublecomplex *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int zstedc_(char *compz, integer *n, doublereal *d__, 
+	doublereal *e, doublecomplex *z__, integer *ldz, doublecomplex *work, 
+	integer *lwork, doublereal *rwork, integer *lrwork, integer *iwork, 
+	integer *liwork, integer *info);
+ 
+/* Subroutine */ int zstein_(integer *n, doublereal *d__, doublereal *e, 
+	integer *m, doublereal *w, integer *iblock, integer *isplit, 
+	doublecomplex *z__, integer *ldz, doublereal *work, integer *iwork, 
+	integer *ifail, integer *info);
+ 
+/* Subroutine */ int zsteqr_(char *compz, integer *n, doublereal *d__, 
+	doublereal *e, doublecomplex *z__, integer *ldz, doublereal *work, 
+	integer *info);
+ 
+/* Subroutine */ int zsycon_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublereal *anorm, doublereal *rcond, 
+	doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zsymv_(char *uplo, integer *n, doublecomplex *alpha, 
+	doublecomplex *a, integer *lda, doublecomplex *x, integer *incx, 
+	doublecomplex *beta, doublecomplex *y, integer *incy);
+ 
+/* Subroutine */ int zsyr_(char *uplo, integer *n, doublecomplex *alpha, 
+	doublecomplex *x, integer *incx, doublecomplex *a, integer *lda);
+ 
+/* Subroutine */ int zsyrfs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, doublecomplex *af, integer *ldaf, 
+	integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x, 
+	integer *ldx, doublereal *ferr, doublereal *berr, doublecomplex *work,
+	 doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zsysv_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b, 
+	integer *ldb, doublecomplex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zsysvx_(char *fact, char *uplo, integer *n, integer *
+	nrhs, doublecomplex *a, integer *lda, doublecomplex *af, integer *
+	ldaf, integer *ipiv, doublecomplex *b, integer *ldb, doublecomplex *x,
+	 integer *ldx, doublereal *rcond, doublereal *ferr, doublereal *berr, 
+	doublecomplex *work, integer *lwork, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int zsytf2_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, integer *info);
+ 
+/* Subroutine */ int zsytrf_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublecomplex *work, integer *lwork, 
+	integer *info);
+ 
+/* Subroutine */ int zsytri_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, integer *ipiv, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zsytrs_(char *uplo, integer *n, integer *nrhs, 
+	doublecomplex *a, integer *lda, integer *ipiv, doublecomplex *b, 
+	integer *ldb, integer *info);
+ 
+/* Subroutine */ int ztbcon_(char *norm, char *uplo, char *diag, integer *n, 
+	integer *kd, doublecomplex *ab, integer *ldab, doublereal *rcond, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int ztbrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, doublecomplex *ab, integer *ldab, 
+	doublecomplex *b, integer *ldb, doublecomplex *x, integer *ldx, 
+	doublereal *ferr, doublereal *berr, doublecomplex *work, doublereal *
+	rwork, integer *info);
+ 
+/* Subroutine */ int ztbtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *kd, integer *nrhs, doublecomplex *ab, integer *ldab, 
+	doublecomplex *b, integer *ldb, integer *info);
+ 
+/* Subroutine */ int ztgevc_(char *side, char *howmny, logical *select, 
+	integer *n, doublecomplex *a, integer *lda, doublecomplex *b, integer 
+	*ldb, doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *
+	ldvr, integer *mm, integer *m, doublecomplex *work, doublereal *rwork,
+	 integer *info);
+ 
+/* Subroutine */ int ztgex2_(logical *wantq, logical *wantz, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *q, integer *ldq, doublecomplex *z__, integer *ldz, 
+	integer *j1, integer *info);
+ 
+/* Subroutine */ int ztgexc_(logical *wantq, logical *wantz, integer *n, 
+	doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *q, integer *ldq, doublecomplex *z__, integer *ldz, 
+	integer *ifst, integer *ilst, integer *info);
+ 
+/* Subroutine */ int ztgsen_(integer *ijob, logical *wantq, logical *wantz, 
+	logical *select, integer *n, doublecomplex *a, integer *lda, 
+	doublecomplex *b, integer *ldb, doublecomplex *alpha, doublecomplex *
+	beta, doublecomplex *q, integer *ldq, doublecomplex *z__, integer *
+	ldz, integer *m, doublereal *pl, doublereal *pr, doublereal *dif, 
+	doublecomplex *work, integer *lwork, integer *iwork, integer *liwork, 
+	integer *info);
+ 
+/* Subroutine */ int ztgsja_(char *jobu, char *jobv, char *jobq, integer *m, 
+	integer *p, integer *n, integer *k, integer *l, doublecomplex *a, 
+	integer *lda, doublecomplex *b, integer *ldb, doublereal *tola, 
+	doublereal *tolb, doublereal *alpha, doublereal *beta, doublecomplex *
+	u, integer *ldu, doublecomplex *v, integer *ldv, doublecomplex *q, 
+	integer *ldq, doublecomplex *work, integer *ncycle, integer *info);
+ 
+/* Subroutine */ int ztgsna_(char *job, char *howmny, logical *select, 
+	integer *n, doublecomplex *a, integer *lda, doublecomplex *b, integer 
+	*ldb, doublecomplex *vl, integer *ldvl, doublecomplex *vr, integer *
+	ldvr, doublereal *s, doublereal *dif, integer *mm, integer *m, 
+	doublecomplex *work, integer *lwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int ztgsy2_(char *trans, integer *ijob, integer *m, integer *
+	n, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *c__, integer *ldc, doublecomplex *d__, integer *ldd, 
+	doublecomplex *e, integer *lde, doublecomplex *f, integer *ldf, 
+	doublereal *scale, doublereal *rdsum, doublereal *rdscal, integer *
+	info);
+ 
+/* Subroutine */ int ztgsyl_(char *trans, integer *ijob, integer *m, integer *
+	n, doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, 
+	doublecomplex *c__, integer *ldc, doublecomplex *d__, integer *ldd, 
+	doublecomplex *e, integer *lde, doublecomplex *f, integer *ldf, 
+	doublereal *scale, doublereal *dif, doublecomplex *work, integer *
+	lwork, integer *iwork, integer *info);
+ 
+/* Subroutine */ int ztpcon_(char *norm, char *uplo, char *diag, integer *n, 
+	doublecomplex *ap, doublereal *rcond, doublecomplex *work, doublereal 
+	*rwork, integer *info);
+ 
+/* Subroutine */ int ztprfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublecomplex *ap, doublecomplex *b, integer *ldb, 
+	doublecomplex *x, integer *ldx, doublereal *ferr, doublereal *berr, 
+	doublecomplex *work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int ztptri_(char *uplo, char *diag, integer *n, 
+	doublecomplex *ap, integer *info);
+ 
+/* Subroutine */ int ztptrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublecomplex *ap, doublecomplex *b, integer *ldb, 
+	integer *info);
+ 
+/* Subroutine */ int ztrcon_(char *norm, char *uplo, char *diag, integer *n, 
+	doublecomplex *a, integer *lda, doublereal *rcond, doublecomplex *
+	work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int ztrevc_(char *side, char *howmny, logical *select, 
+	integer *n, doublecomplex *t, integer *ldt, doublecomplex *vl, 
+	integer *ldvl, doublecomplex *vr, integer *ldvr, integer *mm, integer 
+	*m, doublecomplex *work, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int ztrexc_(char *compq, integer *n, doublecomplex *t, 
+	integer *ldt, doublecomplex *q, integer *ldq, integer *ifst, integer *
+	ilst, integer *info);
+ 
+/* Subroutine */ int ztrrfs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, doublecomplex *x, integer *ldx, doublereal *ferr, 
+	doublereal *berr, doublecomplex *work, doublereal *rwork, integer *
+	info);
+ 
+/* Subroutine */ int ztrsen_(char *job, char *compq, logical *select, integer 
+	*n, doublecomplex *t, integer *ldt, doublecomplex *q, integer *ldq, 
+	doublecomplex *w, integer *m, doublereal *s, doublereal *sep, 
+	doublecomplex *work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int ztrsna_(char *job, char *howmny, logical *select, 
+	integer *n, doublecomplex *t, integer *ldt, doublecomplex *vl, 
+	integer *ldvl, doublecomplex *vr, integer *ldvr, doublereal *s, 
+	doublereal *sep, integer *mm, integer *m, doublecomplex *work, 
+	integer *ldwork, doublereal *rwork, integer *info);
+ 
+/* Subroutine */ int ztrsyl_(char *trana, char *tranb, integer *isgn, integer 
+	*m, integer *n, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, doublecomplex *c__, integer *ldc, doublereal *scale, 
+	integer *info);
+ 
+/* Subroutine */ int ztrti2_(char *uplo, char *diag, integer *n, 
+	doublecomplex *a, integer *lda, integer *info);
+ 
+/* Subroutine */ int ztrtri_(char *uplo, char *diag, integer *n, 
+	doublecomplex *a, integer *lda, integer *info);
+ 
+/* Subroutine */ int ztrtrs_(char *uplo, char *trans, char *diag, integer *n, 
+	integer *nrhs, doublecomplex *a, integer *lda, doublecomplex *b, 
+	integer *ldb, integer *info);
+ 
+/* Subroutine */ int ztzrqf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, integer *info);
+ 
+/* Subroutine */ int ztzrzf_(integer *m, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int zung2l_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *info);
+ 
+/* Subroutine */ int zung2r_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *info);
+ 
+/* Subroutine */ int zungbr_(char *vect, integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zunghr_(integer *n, integer *ilo, integer *ihi, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zungl2_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *info);
+ 
+/* Subroutine */ int zunglq_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zungql_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zungqr_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zungr2_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *info);
+ 
+/* Subroutine */ int zungrq_(integer *m, integer *n, integer *k, 
+	doublecomplex *a, integer *lda, doublecomplex *tau, doublecomplex *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zungtr_(char *uplo, integer *n, doublecomplex *a, 
+	integer *lda, doublecomplex *tau, doublecomplex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int zunm2l_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zunm2r_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zunmbr_(char *vect, char *side, char *trans, integer *m, 
+	integer *n, integer *k, doublecomplex *a, integer *lda, doublecomplex 
+	*tau, doublecomplex *c__, integer *ldc, doublecomplex *work, integer *
+	lwork, integer *info);
+ 
+/* Subroutine */ int zunmhr_(char *side, char *trans, integer *m, integer *n, 
+	integer *ilo, integer *ihi, doublecomplex *a, integer *lda, 
+	doublecomplex *tau, doublecomplex *c__, integer *ldc, doublecomplex *
+	work, integer *lwork, integer *info);
+ 
+/* Subroutine */ int zunml2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zunmlq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int zunmql_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int zunmqr_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int zunmr2_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *info);
+ 
+/* Subroutine */ int zunmr3_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, doublecomplex *a, integer *lda, doublecomplex 
+	*tau, doublecomplex *c__, integer *ldc, doublecomplex *work, integer *
+	info);
+ 
+/* Subroutine */ int zunmrq_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int zunmrz_(char *side, char *trans, integer *m, integer *n, 
+	integer *k, integer *l, doublecomplex *a, integer *lda, doublecomplex 
+	*tau, doublecomplex *c__, integer *ldc, doublecomplex *work, integer *
+	lwork, integer *info);
+ 
+/* Subroutine */ int zunmtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, doublecomplex *a, integer *lda, doublecomplex *tau, 
+	doublecomplex *c__, integer *ldc, doublecomplex *work, integer *lwork,
+	 integer *info);
+ 
+/* Subroutine */ int zupgtr_(char *uplo, integer *n, doublecomplex *ap, 
+	doublecomplex *tau, doublecomplex *q, integer *ldq, doublecomplex *
+	work, integer *info);
+ 
+/* Subroutine */ int zupmtr_(char *side, char *uplo, char *trans, integer *m, 
+	integer *n, doublecomplex *ap, doublecomplex *tau, doublecomplex *c__,
+	 integer *ldc, doublecomplex *work, integer *info);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __CLAPACK_H */
+
diff --git a/bioimagesuite30_src/include/nifti1.h b/bioimagesuite30_src/include/nifti1.h
new file mode 100644
index 0000000..8f8711e
--- /dev/null
+++ b/bioimagesuite30_src/include/nifti1.h
@@ -0,0 +1,1469 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/** \file nifti1.h
+    \brief Official definition of the nifti1 header.  Written by Bob Cox, SSCC, NIMH.
+ */
+
+#ifndef _NIFTI_HEADER_
+#define _NIFTI_HEADER_
+
+/*****************************************************************************
+      ** This file defines the "NIFTI-1" header format.               **
+      ** It is derived from 2 meetings at the NIH (31 Mar 2003 and    **
+      ** 02 Sep 2003) of the Data Format Working Group (DFWG),        **
+      ** chartered by the NIfTI (Neuroimaging Informatics Technology  **
+      ** Initiative) at the National Institutes of Health (NIH).      **
+      **--------------------------------------------------------------**
+      ** Neither the National Institutes of Health (NIH), the DFWG,   **
+      ** nor any of the members or employees of these institutions    **
+      ** imply any warranty of usefulness of this material for any    **
+      ** purpose, and do not assume any liability for damages,        **
+      ** incidental or otherwise, caused by any use of this document. **
+      ** If these conditions are not acceptable, do not use this!     **
+      **--------------------------------------------------------------**
+      ** Author:   Robert W Cox (NIMH, Bethesda)                      **
+      ** Advisors: John Ashburner (FIL, London),                      **
+      **           Stephen Smith (FMRIB, Oxford),                     **
+      **           Mark Jenkinson (FMRIB, Oxford)                     **
+******************************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Note that the ANALYZE 7.5 file header (dbh.h) is
+         (c) Copyright 1986-1995
+         Biomedical Imaging Resource
+         Mayo Foundation
+   Incorporation of components of dbh.h are by permission of the
+   Mayo Foundation.
+
+   Changes from the ANALYZE 7.5 file header in this file are released to the
+   public domain, including the functional comments and any amusing asides.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/*! INTRODUCTION TO NIFTI-1:
+   ------------------------
+   The twin (and somewhat conflicting) goals of this modified ANALYZE 7.5
+   format are:
+    (a) To add information to the header that will be useful for functional
+        neuroimaging data analysis and display.  These additions include:
+        - More basic data types.
+        - Two affine transformations to specify voxel coordinates.
+        - "Intent" codes and parameters to describe the meaning of the data.
+        - Affine scaling of the stored data values to their "true" values.
+        - Optional storage of the header and image data in one file (.nii).
+    (b) To maintain compatibility with non-NIFTI-aware ANALYZE 7.5 compatible
+        software (i.e., such a program should be able to do something useful
+        with a NIFTI-1 dataset -- at least, with one stored in a traditional
+        .img/.hdr file pair).
+
+   Most of the unused fields in the ANALYZE 7.5 header have been taken,
+   and some of the lesser-used fields have been co-opted for other purposes.
+   Notably, most of the data_history substructure has been co-opted for
+   other purposes, since the ANALYZE 7.5 format describes this substructure
+   as "not required".
+
+   NIFTI-1 FLAG (MAGIC STRINGS):
+   ----------------------------
+   To flag such a struct as being conformant to the NIFTI-1 spec, the last 4
+   bytes of the header must be either the C String "ni1" or "n+1";
+   in hexadecimal, the 4 bytes
+     6E 69 31 00   or   6E 2B 31 00
+   (in any future version of this format, the '1' will be upgraded to '2',
+   etc.).  Normally, such a "magic number" or flag goes at the start of the
+   file, but trying to avoid clobbering widely-used ANALYZE 7.5 fields led to
+   putting this marker last.  However, recall that "the last shall be first"
+   (Matthew 20:16).
+
+   If a NIFTI-aware program reads a header file that is NOT marked with a
+   NIFTI magic string, then it should treat the header as an ANALYZE 7.5
+   structure.
+
+   NIFTI-1 FILE STORAGE:
+   --------------------
+   "ni1" means that the image data is stored in the ".img" file corresponding
+   to the header file (starting at file offset 0).
+
+   "n+1" means that the image data is stored in the same file as the header
+   information.  We recommend that the combined header+data filename suffix
+   be ".nii".  When the dataset is stored in one file, the first byte of image
+   data is stored at byte location (int)vox_offset in this combined file.
+   The minimum allowed value of vox_offset is 352; for compatibility with
+   some software, vox_offset should be an integral multiple of 16.
+
+   GRACE UNDER FIRE:
+   ----------------
+   Most NIFTI-aware programs will only be able to handle a subset of the full
+   range of datasets possible with this format.  All NIFTI-aware programs
+   should take care to check if an input dataset conforms to the program's
+   needs and expectations (e.g., check datatype, intent_code, etc.).  If the
+   input dataset can't be handled by the program, the program should fail
+   gracefully (e.g., print a useful warning; not crash).
+
+   SAMPLE CODES:
+   ------------
+   The associated files nifti1_io.h and nifti1_io.c provide a sample
+   implementation in C of a set of functions to read, write, and manipulate
+   NIFTI-1 files.  The file nifti1_test.c is a sample program that uses
+   the nifti1_io.c functions.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* HEADER STRUCT DECLARATION:
+   -------------------------
+   In the comments below for each field, only NIFTI-1 specific requirements
+   or changes from the ANALYZE 7.5 format are described.  For convenience,
+   the 348 byte header is described as a single struct, rather than as the
+   ANALYZE 7.5 group of 3 substructs.
+
+   Further comments about the interpretation of various elements of this
+   header are after the data type definition itself.  Fields that are
+   marked as ++UNUSED++ have no particular interpretation in this standard.
+   (Also see the UNUSED FIELDS comment section, far below.)
+
+   The presumption below is that the various C types have particular sizes:
+     sizeof(int) = sizeof(float) = 4 ;  sizeof(short) = 2
+-----------------------------------------------------------------------------*/
+
+/*=================*/
+#ifdef  __cplusplus
+extern "C" {
+#endif
+/*=================*/
+
+/*! \struct nifti_1_header
+    \brief Data structure defining the fields in the nifti1 header.
+           This binary header should be found at the beginning of a valid
+           NIFTI-1 header file.
+ */
+                        /*************************/  /************************/
+struct nifti_1_header { /* NIFTI-1 usage         */  /* ANALYZE 7.5 field(s) */
+                        /*************************/  /************************/
+
+                                           /*--- was header_key substruct ---*/
+ int   sizeof_hdr;    /*!< MUST be 348           */  /* int sizeof_hdr;      */
+ char  data_type[10]; /*!< ++UNUSED++            */  /* char data_type[10];  */
+ char  db_name[18];   /*!< ++UNUSED++            */  /* char db_name[18];    */
+ int   extents;       /*!< ++UNUSED++            */  /* int extents;         */
+ short session_error; /*!< ++UNUSED++            */  /* short session_error; */
+ char  regular;       /*!< ++UNUSED++            */  /* char regular;        */
+ char  dim_info;      /*!< MRI slice ordering.   */  /* char hkey_un0;       */
+
+                                      /*--- was image_dimension substruct ---*/
+ short dim[8];        /*!< Data array dimensions.*/  /* short dim[8];        */
+ float intent_p1 ;    /*!< 1st intent parameter. */  /* short unused8;       */
+                                                     /* short unused9;       */
+ float intent_p2 ;    /*!< 2nd intent parameter. */  /* short unused10;      */
+                                                     /* short unused11;      */
+ float intent_p3 ;    /*!< 3rd intent parameter. */  /* short unused12;      */
+                                                     /* short unused13;      */
+ short intent_code ;  /*!< NIFTI_INTENT_* code.  */  /* short unused14;      */
+ short datatype;      /*!< Defines data type!    */  /* short datatype;      */
+ short bitpix;        /*!< Number bits/voxel.    */  /* short bitpix;        */
+ short slice_start;   /*!< First slice index.    */  /* short dim_un0;       */
+ float pixdim[8];     /*!< Grid spacings.        */  /* float pixdim[8];     */
+ float vox_offset;    /*!< Offset into .nii file */  /* float vox_offset;    */
+ float scl_slope ;    /*!< Data scaling: slope.  */  /* float funused1;      */
+ float scl_inter ;    /*!< Data scaling: offset. */  /* float funused2;      */
+ short slice_end;     /*!< Last slice index.     */  /* float funused3;      */
+ char  slice_code ;   /*!< Slice timing order.   */
+ char  xyzt_units ;   /*!< Units of pixdim[1..4] */
+ float cal_max;       /*!< Max display intensity */  /* float cal_max;       */
+ float cal_min;       /*!< Min display intensity */  /* float cal_min;       */
+ float slice_duration;/*!< Time for 1 slice.     */  /* float compressed;    */
+ float toffset;       /*!< Time axis shift.      */  /* float verified;      */
+ int   glmax;         /*!< ++UNUSED++            */  /* int glmax;           */
+ int   glmin;         /*!< ++UNUSED++            */  /* int glmin;           */
+
+                                         /*--- was data_history substruct ---*/
+ char  descrip[80];   /*!< any text you like.    */  /* char descrip[80];    */
+ char  aux_file[24];  /*!< auxiliary filename.   */  /* char aux_file[24];   */
+
+ short qform_code ;   /*!< NIFTI_XFORM_* code.   */  /*-- all ANALYZE 7.5 ---*/
+ short sform_code ;   /*!< NIFTI_XFORM_* code.   */  /*   fields below here  */
+                                                     /*   are replaced       */
+ float quatern_b ;    /*!< Quaternion b param.   */
+ float quatern_c ;    /*!< Quaternion c param.   */
+ float quatern_d ;    /*!< Quaternion d param.   */
+ float qoffset_x ;    /*!< Quaternion x shift.   */
+ float qoffset_y ;    /*!< Quaternion y shift.   */
+ float qoffset_z ;    /*!< Quaternion z shift.   */
+
+ float srow_x[4] ;    /*!< 1st row affine transform.   */
+ float srow_y[4] ;    /*!< 2nd row affine transform.   */
+ float srow_z[4] ;    /*!< 3rd row affine transform.   */
+
+ char intent_name[16];/*!< 'name' or meaning of data.  */
+
+ char magic[4] ;      /*!< MUST be "ni1\0" or "n+1\0". */
+
+} ;                   /**** 348 bytes total ****/
+
+typedef struct nifti_1_header nifti_1_header ;
+
+/*---------------------------------------------------------------------------*/
+/* HEADER EXTENSIONS:
+   -----------------
+   After the end of the 348 byte header (e.g., after the magic field),
+   the next 4 bytes are a char array field named "extension". By default,
+   all 4 bytes of this array should be set to zero. In a .nii file, these
+   4 bytes will always be present, since the earliest start point for
+   the image data is byte #352. In a separate .hdr file, these bytes may
+   or may not be present. If not present (i.e., if the length of the .hdr
+   file is 348 bytes), then a NIfTI-1 compliant program should use the
+   default value of extension={0,0,0,0}. The first byte (extension[0])
+   is the only value of this array that is specified at present. The other
+   3 bytes are reserved for future use.
+
+   If extension[0] is nonzero, it indicates that extended header information
+   is present in the bytes following the extension array. In a .nii file,
+   this extended header data is before the image data (and vox_offset
+   must be set correctly to allow for this). In a .hdr file, this extended
+   data follows extension and proceeds (potentially) to the end of the file.
+
+   The format of extended header data is weakly specified. Each extension
+   must be an integer multiple of 16 bytes long. The first 8 bytes of each
+   extension comprise 2 integers:
+      int esize , ecode ;
+   These values may need to be byte-swapped, as indicated by dim[0] for
+   the rest of the header.
+     * esize is the number of bytes that form the extended header data
+       + esize must be a positive integral multiple of 16
+       + this length includes the 8 bytes of esize and ecode themselves
+     * ecode is a non-negative integer that indicates the format of the
+       extended header data that follows
+       + different ecode values are assigned to different developer groups
+       + at present, the "registered" values for code are
+         = 0 = unknown private format (not recommended!)
+         = 2 = DICOM format (i.e., attribute tags and values)
+         = 4 = AFNI group (i.e., ASCII XML-ish elements)
+   In the interests of interoperability (a primary rationale for NIfTI),
+   groups developing software that uses this extension mechanism are
+   encouraged to document and publicize the format of their extensions.
+   To this end, the NIfTI DFWG will assign even numbered codes upon request
+   to groups submitting at least rudimentary documentation for the format
+   of their extension; at present, the contact is mailto:rwcox at nih.gov.
+   The assigned codes and documentation will be posted on the NIfTI
+   website. All odd values of ecode (and 0) will remain unassigned;
+   at least, until the even ones are used up, when we get to 2,147,483,646.
+
+   Note that the other contents of the extended header data section are
+   totally unspecified by the NIfTI-1 standard. In particular, if binary
+   data is stored in such a section, its byte order is not necessarily
+   the same as that given by examining dim[0]; it is incumbent on the
+   programs dealing with such data to determine the byte order of binary
+   extended header data.
+
+   Multiple extended header sections are allowed, each starting with an
+   esize,ecode value pair. The first esize value, as described above,
+   is at bytes #352-355 in the .hdr or .nii file (files start at byte #0).
+   If this value is positive, then the second (esize2) will be found
+   starting at byte #352+esize1 , the third (esize3) at byte #352+esize1+esize2,
+   et cetera.  Of course, in a .nii file, the value of vox_offset must
+   be compatible with these extensions. If a malformed file indicates
+   that an extended header data section would run past vox_offset, then
+   the entire extended header section should be ignored. In a .hdr file,
+   if an extended header data section would run past the end-of-file,
+   that extended header data should also be ignored.
+
+   With the above scheme, a program can successively examine the esize
+   and ecode values, and skip over each extended header section if the
+   program doesn't know how to interpret the data within. Of course, any
+   program can simply ignore all extended header sections simply by jumping
+   straight to the image data using vox_offset.
+-----------------------------------------------------------------------------*/
+   
+/*! \struct nifti1_extender
+    \brief This structure represents a 4-byte string that should follow the
+           binary nifti_1_header data in a NIFTI-1 header file.  If the char
+           values are {1,0,0,0}, the file is expected to contain extensions,
+           values of {0,0,0,0} imply the file does not contain extensions.
+           Other sequences of values are not currently defined.
+ */
+struct nifti1_extender { char extension[4] ; } ;
+typedef struct nifti1_extender nifti1_extender ;
+
+/*! \struct nifti1_extension
+    \brief Data structure defining the fields of a header extension.
+ */
+struct nifti1_extension {
+   int    esize ; /*!< size of extension, in bytes (must be multiple of 16) */
+   int    ecode ; /*!< extension code, one of the NIFTI_ECODE_ values       */
+   char * edata ; /*!< raw data, with no byte swapping                      */
+} ;
+typedef struct nifti1_extension nifti1_extension ;
+
+/*---------------------------------------------------------------------------*/
+/* DATA DIMENSIONALITY (as in ANALYZE 7.5):
+   ---------------------------------------
+     dim[0] = number of dimensions;
+              - if dim[0] is outside range 1..7, then the header information
+                needs to be byte swapped appropriately
+              - ANALYZE supports dim[0] up to 7, but NIFTI-1 reserves
+                dimensions 1,2,3 for space (x,y,z), 4 for time (t), and
+                5,6,7 for anything else needed.
+
+     dim[i] = length of dimension #i, for i=1..dim[0]  (must be positive)
+              - also see the discussion of intent_code, far below
+
+     pixdim[i] = voxel width along dimension #i, i=1..dim[0] (positive)
+                 - cf. ORIENTATION section below for use of pixdim[0]
+                 - the units of pixdim can be specified with the xyzt_units
+                   field (also described far below).
+
+   Number of bits per voxel value is in bitpix, which MUST correspond with
+   the datatype field.  The total number of bytes in the image data is
+     dim[1] * ... * dim[dim[0]] * bitpix / 8
+
+   In NIFTI-1 files, dimensions 1,2,3 are for space, dimension 4 is for time,
+   and dimension 5 is for storing multiple values at each spatiotemporal
+   voxel.  Some examples:
+     - A typical whole-brain FMRI experiment's time series:
+        - dim[0] = 4
+        - dim[1] = 64   pixdim[1] = 3.75 xyzt_units =  NIFTI_UNITS_MM
+        - dim[2] = 64   pixdim[2] = 3.75             | NIFTI_UNITS_SEC
+        - dim[3] = 20   pixdim[3] = 5.0
+        - dim[4] = 120  pixdim[4] = 2.0
+     - A typical T1-weighted anatomical volume:
+        - dim[0] = 3
+        - dim[1] = 256  pixdim[1] = 1.0  xyzt_units = NIFTI_UNITS_MM
+        - dim[2] = 256  pixdim[2] = 1.0
+        - dim[3] = 128  pixdim[3] = 1.1
+     - A single slice EPI time series:
+        - dim[0] = 4
+        - dim[1] = 64   pixdim[1] = 3.75 xyzt_units =  NIFTI_UNITS_MM
+        - dim[2] = 64   pixdim[2] = 3.75             | NIFTI_UNITS_SEC
+        - dim[3] = 1    pixdim[3] = 5.0
+        - dim[4] = 1200 pixdim[4] = 0.2
+     - A 3-vector stored at each point in a 3D volume:
+        - dim[0] = 5
+        - dim[1] = 256  pixdim[1] = 1.0  xyzt_units = NIFTI_UNITS_MM
+        - dim[2] = 256  pixdim[2] = 1.0
+        - dim[3] = 128  pixdim[3] = 1.1
+        - dim[4] = 1    pixdim[4] = 0.0
+        - dim[5] = 3                     intent_code = NIFTI_INTENT_VECTOR
+     - A single time series with a 3x3 matrix at each point:
+        - dim[0] = 5
+        - dim[1] = 1                     xyzt_units = NIFTI_UNITS_SEC
+        - dim[2] = 1
+        - dim[3] = 1
+        - dim[4] = 1200 pixdim[4] = 0.2
+        - dim[5] = 9                     intent_code = NIFTI_INTENT_GENMATRIX
+        - intent_p1 = intent_p2 = 3.0    (indicates matrix dimensions)
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DATA STORAGE:
+   ------------
+   If the magic field is "n+1", then the voxel data is stored in the
+   same file as the header.  In this case, the voxel data starts at offset
+   (int)vox_offset into the header file.  Thus, vox_offset=352.0 means that
+   the data starts immediately after the NIFTI-1 header.  If vox_offset is
+   greater than 352, the NIFTI-1 format does not say much about the
+   contents of the dataset file between the end of the header and the
+   start of the data.
+
+   FILES:
+   -----
+   If the magic field is "ni1", then the voxel data is stored in the
+   associated ".img" file, starting at offset 0 (i.e., vox_offset is not
+   used in this case, and should be set to 0.0).
+
+   When storing NIFTI-1 datasets in pairs of files, it is customary to name
+   the files in the pattern "name.hdr" and "name.img", as in ANALYZE 7.5.
+   When storing in a single file ("n+1"), the file name should be in
+   the form "name.nii" (the ".nft" and ".nif" suffixes are already taken;
+   cf. http://www.icdatamaster.com/n.html ).
+
+   BYTE ORDERING:
+   -------------
+   The byte order of the data arrays is presumed to be the same as the byte
+   order of the header (which is determined by examining dim[0]).
+
+   Floating point types are presumed to be stored in IEEE-754 format.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DETAILS ABOUT vox_offset:
+   ------------------------
+   In a .nii file, the vox_offset field value is interpreted as the start
+   location of the image data bytes in that file. In a .hdr/.img file pair,
+   the vox_offset field value is the start location of the image data
+   bytes in the .img file.
+    * If vox_offset is less than 352 in a .nii file, it is equivalent
+      to 352 (i.e., image data never starts before byte #352 in a .nii file).
+    * The default value for vox_offset in a .nii file is 352.
+    * In a .hdr file, the default value for vox_offset is 0.
+    * vox_offset should be an integer multiple of 16; otherwise, some
+      programs may not work properly (e.g., SPM). This is to allow
+      memory-mapped input to be properly byte-aligned.
+   Note that since vox_offset is an IEEE-754 32 bit float (for compatibility
+   with the ANALYZE-7.5 format), it effectively has a 24 bit mantissa. All
+   integers from 0 to 2^24 can be represented exactly in this format, but not
+   all larger integers are exactly storable as IEEE-754 32 bit floats. However,
+   unless you plan to have vox_offset be potentially larger than 16 MB, this
+   should not be an issue. (Actually, any integral multiple of 16 up to 2^27
+   can be represented exactly in this format, which allows for up to 128 MB
+   of random information before the image data.  If that isn't enough, then
+   perhaps this format isn't right for you.)
+
+   In a .img file (i.e., image data stored separately from the NIfTI-1
+   header), data bytes between #0 and #vox_offset-1 (inclusive) are completely
+   undefined and unregulated by the NIfTI-1 standard. One potential use of
+   having vox_offset > 0 in the .hdr/.img file pair storage method is to make
+   the .img file be a copy of (or link to) a pre-existing image file in some
+   other format, such as DICOM; then vox_offset would be set to the offset of
+   the image data in this file. (It may not be possible to follow the
+   "multiple-of-16 rule" with an arbitrary external file; using the NIfTI-1
+   format in such a case may lead to a file that is incompatible with software
+   that relies on vox_offset being a multiple of 16.)
+
+   In a .nii file, data bytes between #348 and #vox_offset-1 (inclusive) may
+   be used to store user-defined extra information; similarly, in a .hdr file,
+   any data bytes after byte #347 are available for user-defined extra
+   information. The (very weak) regulation of this extra header data is
+   described elsewhere.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* DATA SCALING:
+   ------------
+   If the scl_slope field is nonzero, then each voxel value in the dataset
+   should be scaled as
+      y = scl_slope * x + scl_inter
+   where x = voxel value stored
+         y = "true" voxel value
+   Normally, we would expect this scaling to be used to store "true" floating
+   values in a smaller integer datatype, but that is not required.  That is,
+   it is legal to use scaling even if the datatype is a float type (crazy,
+   perhaps, but legal).
+    - However, the scaling is to be ignored if datatype is DT_RGB24.
+    - If datatype is a complex type, then the scaling is to be
+      applied to both the real and imaginary parts.
+
+   The cal_min and cal_max fields (if nonzero) are used for mapping (possibly
+   scaled) dataset values to display colors:
+    - Minimum display intensity (black) corresponds to dataset value cal_min.
+    - Maximum display intensity (white) corresponds to dataset value cal_max.
+    - Dataset values below cal_min should display as black also, and values
+      above cal_max as white.
+    - Colors "black" and "white", of course, may refer to any scalar display
+      scheme (e.g., a color lookup table specified via aux_file).
+    - cal_min and cal_max only make sense when applied to scalar-valued
+      datasets (i.e., dim[0] < 5 or dim[5] = 1).
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* TYPE OF DATA (acceptable values for datatype field):
+   ---------------------------------------------------
+   Values of datatype smaller than 256 are ANALYZE 7.5 compatible.
+   Larger values are NIFTI-1 additions.  These are all multiples of 256, so
+   that no bits below position 8 are set in datatype.  But there is no need
+   to use only powers-of-2, as the original ANALYZE 7.5 datatype codes do.
+
+   The additional codes are intended to include a complete list of basic
+   scalar types, including signed and unsigned integers from 8 to 64 bits,
+   floats from 32 to 128 bits, and complex (float pairs) from 64 to 256 bits.
+
+   Note that most programs will support only a few of these datatypes!
+   A NIFTI-1 program should fail gracefully (e.g., print a warning message)
+   when it encounters a dataset with a type it doesn't like.
+-----------------------------------------------------------------------------*/
+
+#undef DT_UNKNOWN  /* defined in dirent.h on some Unix systems */
+
+/*! \defgroup NIFTI1_DATATYPES
+    \brief nifti1 datatype codes
+    @{
+ */
+                            /*--- the original ANALYZE 7.5 type codes ---*/
+#define DT_NONE                    0
+#define DT_UNKNOWN                 0     /* what it says, dude           */
+#define DT_BINARY                  1     /* binary (1 bit/voxel)         */
+#define DT_UNSIGNED_CHAR           2     /* unsigned char (8 bits/voxel) */
+#define DT_SIGNED_SHORT            4     /* signed short (16 bits/voxel) */
+#define DT_SIGNED_INT              8     /* signed int (32 bits/voxel)   */
+#define DT_FLOAT                  16     /* float (32 bits/voxel)        */
+#define DT_COMPLEX                32     /* complex (64 bits/voxel)      */
+#define DT_DOUBLE                 64     /* double (64 bits/voxel)       */
+#define DT_RGB                   128     /* RGB triple (24 bits/voxel)   */
+#define DT_ALL                   255     /* not very useful (?)          */
+
+                            /*----- another set of names for the same ---*/
+#define DT_UINT8                   2
+#define DT_INT16                   4
+#define DT_INT32                   8
+#define DT_FLOAT32                16
+#define DT_COMPLEX64              32
+#define DT_FLOAT64                64
+#define DT_RGB24                 128
+
+                            /*------------------- new codes for NIFTI ---*/
+#define DT_INT8                  256     /* signed char (8 bits)         */
+#define DT_UINT16                512     /* unsigned short (16 bits)     */
+#define DT_UINT32                768     /* unsigned int (32 bits)       */
+#define DT_INT64                1024     /* long long (64 bits)          */
+#define DT_UINT64               1280     /* unsigned long long (64 bits) */
+#define DT_FLOAT128             1536     /* long double (128 bits)       */
+#define DT_COMPLEX128           1792     /* double pair (128 bits)       */
+#define DT_COMPLEX256           2048     /* long double pair (256 bits)  */
+/* @} */
+
+
+                            /*------- aliases for all the above codes ---*/
+
+/*! \defgroup NIFTI1_DATATYPE_ALIASES
+    \brief aliases for the nifti1 datatype codes
+    @{
+ */
+                                       /*! unsigned char. */
+#define NIFTI_TYPE_UINT8           2
+                                       /*! signed short. */
+#define NIFTI_TYPE_INT16           4
+                                       /*! signed int. */
+#define NIFTI_TYPE_INT32           8
+                                       /*! 32 bit float. */
+#define NIFTI_TYPE_FLOAT32        16
+                                       /*! 64 bit complex = 2 32 bit floats. */
+#define NIFTI_TYPE_COMPLEX64      32
+                                       /*! 64 bit float = double. */
+#define NIFTI_TYPE_FLOAT64        64
+                                       /*! 3 8 bit bytes. */
+#define NIFTI_TYPE_RGB24         128
+                                       /*! signed char. */
+#define NIFTI_TYPE_INT8          256
+                                       /*! unsigned short. */
+#define NIFTI_TYPE_UINT16        512
+                                       /*! unsigned int. */
+#define NIFTI_TYPE_UINT32        768
+                                       /*! signed long long. */
+#define NIFTI_TYPE_INT64        1024
+                                       /*! unsigned long long. */
+#define NIFTI_TYPE_UINT64       1280
+                                       /*! 128 bit float = long double. */
+#define NIFTI_TYPE_FLOAT128     1536
+                                       /*! 128 bit complex = 2 64 bit floats. */
+#define NIFTI_TYPE_COMPLEX128   1792
+                                       /*! 256 bit complex = 2 128 bit floats */
+#define NIFTI_TYPE_COMPLEX256   2048
+/* @} */
+
+                     /*-------- sample typedefs for complicated types ---*/
+#if 0
+typedef struct { float       r,i;     } complex_float ;
+typedef struct { double      r,i;     } complex_double ;
+typedef struct { long double r,i;     } complex_longdouble ;
+typedef struct { unsigned char r,g,b; } rgb_byte ;
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* INTERPRETATION OF VOXEL DATA:
+   ----------------------------
+   The intent_code field can be used to indicate that the voxel data has
+   some particular meaning.  In particular, a large number of codes is
+   given to indicate that the the voxel data should be interpreted as
+   being drawn from a given probability distribution.
+
+   VECTOR-VALUED DATASETS:
+   ----------------------
+   The 5th dimension of the dataset, if present (i.e., dim[0]=5 and
+   dim[5] > 1), contains multiple values (e.g., a vector) to be stored
+   at each spatiotemporal location.  For example, the header values
+    - dim[0] = 5
+    - dim[1] = 64
+    - dim[2] = 64
+    - dim[3] = 20
+    - dim[4] = 1     (indicates no time axis)
+    - dim[5] = 3
+    - datatype = DT_FLOAT
+    - intent_code = NIFTI_INTENT_VECTOR
+   mean that this dataset should be interpreted as a 3D volume (64x64x20),
+   with a 3-vector of floats defined at each point in the 3D grid.
+
+   A program reading a dataset with a 5th dimension may want to reformat
+   the image data to store each voxels' set of values together in a struct
+   or array.  This programming detail, however, is beyond the scope of the
+   NIFTI-1 file specification!  Uses of dimensions 6 and 7 are also not
+   specified here.
+
+   STATISTICAL PARAMETRIC DATASETS (i.e., SPMs):
+   --------------------------------------------
+   Values of intent_code from NIFTI_FIRST_STATCODE to NIFTI_LAST_STATCODE
+   (inclusive) indicate that the numbers in the dataset should be interpreted
+   as being drawn from a given distribution.  Most such distributions have
+   auxiliary parameters (e.g., NIFTI_INTENT_TTEST has 1 DOF parameter).
+
+   If the dataset DOES NOT have a 5th dimension, then the auxiliary parameters
+   are the same for each voxel, and are given in header fields intent_p1,
+   intent_p2, and intent_p3.
+
+   If the dataset DOES have a 5th dimension, then the auxiliary parameters
+   are different for each voxel.  For example, the header values
+    - dim[0] = 5
+    - dim[1] = 128
+    - dim[2] = 128
+    - dim[3] = 1      (indicates a single slice)
+    - dim[4] = 1      (indicates no time axis)
+    - dim[5] = 2
+    - datatype = DT_FLOAT
+    - intent_code = NIFTI_INTENT_TTEST
+   mean that this is a 2D dataset (128x128) of t-statistics, with the
+   t-statistic being in the first "plane" of data and the degrees-of-freedom
+   parameter being in the second "plane" of data.
+
+   If the dataset 5th dimension is used to store the voxel-wise statistical
+   parameters, then dim[5] must be 1 plus the number of parameters required
+   by that distribution (e.g., intent_code=NIFTI_INTENT_TTEST implies dim[5]
+   must be 2, as in the example just above).
+
+   Note: intent_code values 2..10 are compatible with AFNI 1.5x (which is
+   why there is no code with value=1, which is obsolescent in AFNI).
+
+   OTHER INTENTIONS:
+   ----------------
+   The purpose of the intent_* fields is to help interpret the values
+   stored in the dataset.  Some non-statistical values for intent_code
+   and conventions are provided for storing other complex data types.
+
+   The intent_name field provides space for a 15 character (plus 0 byte)
+   'name' string for the type of data stored. Examples:
+    - intent_code = NIFTI_INTENT_ESTIMATE; intent_name = "T1";
+       could be used to signify that the voxel values are estimates of the
+       NMR parameter T1.
+    - intent_code = NIFTI_INTENT_TTEST; intent_name = "House";
+       could be used to signify that the voxel values are t-statistics
+       for the significance of 'activation' response to a House stimulus.
+    - intent_code = NIFTI_INTENT_DISPVECT; intent_name = "ToMNI152";
+       could be used to signify that the voxel values are a displacement
+       vector that transforms each voxel (x,y,z) location to the
+       corresponding location in the MNI152 standard brain.
+    - intent_code = NIFTI_INTENT_SYMMATRIX; intent_name = "DTI";
+       could be used to signify that the voxel values comprise a diffusion
+       tensor image.
+
+   If no data name is implied or needed, intent_name[0] should be set to 0.
+-----------------------------------------------------------------------------*/
+
+ /*! default: no intention is indicated in the header. */
+
+#define NIFTI_INTENT_NONE        0
+
+    /*-------- These codes are for probability distributions ---------------*/
+    /* Most distributions have a number of parameters,
+       below denoted by p1, p2, and p3, and stored in
+        - intent_p1, intent_p2, intent_p3 if dataset doesn't have 5th dimension
+        - image data array                if dataset does have 5th dimension
+
+       Functions to compute with many of the distributions below can be found
+       in the CDF library from U Texas.
+
+       Formulas for and discussions of these distributions can be found in the
+       following books:
+
+        [U] Univariate Discrete Distributions,
+            NL Johnson, S Kotz, AW Kemp.
+
+        [C1] Continuous Univariate Distributions, vol. 1,
+             NL Johnson, S Kotz, N Balakrishnan.
+
+        [C2] Continuous Univariate Distributions, vol. 2,
+             NL Johnson, S Kotz, N Balakrishnan.                            */
+    /*----------------------------------------------------------------------*/
+
+  /*! [C2, chap 32] Correlation coefficient R (1 param):
+       p1 = degrees of freedom
+       R/sqrt(1-R*R) is t-distributed with p1 DOF. */
+
+/*! \defgroup NIFTI1_INTENT_CODES
+    \brief nifti1 intent codes, to describe intended meaning of dataset contents
+    @{
+ */
+#define NIFTI_INTENT_CORREL      2
+
+  /*! [C2, chap 28] Student t statistic (1 param): p1 = DOF. */
+
+#define NIFTI_INTENT_TTEST       3
+
+  /*! [C2, chap 27] Fisher F statistic (2 params):
+       p1 = numerator DOF, p2 = denominator DOF. */
+
+#define NIFTI_INTENT_FTEST       4
+
+  /*! [C1, chap 13] Standard normal (0 params): Density = N(0,1). */
+
+#define NIFTI_INTENT_ZSCORE      5
+
+  /*! [C1, chap 18] Chi-squared (1 param): p1 = DOF.
+      Density(x) proportional to exp(-x/2) * x^(p1/2-1). */
+
+#define NIFTI_INTENT_CHISQ       6
+
+  /*! [C2, chap 25] Beta distribution (2 params): p1=a, p2=b.
+      Density(x) proportional to x^(a-1) * (1-x)^(b-1). */
+
+#define NIFTI_INTENT_BETA        7
+
+  /*! [U, chap 3] Binomial distribution (2 params):
+       p1 = number of trials, p2 = probability per trial.
+      Prob(x) = (p1 choose x) * p2^x * (1-p2)^(p1-x), for x=0,1,...,p1. */
+
+#define NIFTI_INTENT_BINOM       8
+
+  /*! [C1, chap 17] Gamma distribution (2 params):
+       p1 = shape, p2 = scale.
+      Density(x) proportional to x^(p1-1) * exp(-p2*x). */
+
+#define NIFTI_INTENT_GAMMA       9
+
+  /*! [U, chap 4] Poisson distribution (1 param): p1 = mean.
+      Prob(x) = exp(-p1) * p1^x / x! , for x=0,1,2,.... */
+
+#define NIFTI_INTENT_POISSON    10
+
+  /*! [C1, chap 13] Normal distribution (2 params):
+       p1 = mean, p2 = standard deviation. */
+
+#define NIFTI_INTENT_NORMAL     11
+
+  /*! [C2, chap 30] Noncentral F statistic (3 params):
+       p1 = numerator DOF, p2 = denominator DOF,
+       p3 = numerator noncentrality parameter.  */
+
+#define NIFTI_INTENT_FTEST_NONC 12
+
+  /*! [C2, chap 29] Noncentral chi-squared statistic (2 params):
+       p1 = DOF, p2 = noncentrality parameter.     */
+
+#define NIFTI_INTENT_CHISQ_NONC 13
+
+  /*! [C2, chap 23] Logistic distribution (2 params):
+       p1 = location, p2 = scale.
+      Density(x) proportional to sech^2((x-p1)/(2*p2)). */
+
+#define NIFTI_INTENT_LOGISTIC   14
+
+  /*! [C2, chap 24] Laplace distribution (2 params):
+       p1 = location, p2 = scale.
+      Density(x) proportional to exp(-abs(x-p1)/p2). */
+
+#define NIFTI_INTENT_LAPLACE    15
+
+  /*! [C2, chap 26] Uniform distribution: p1 = lower end, p2 = upper end. */
+
+#define NIFTI_INTENT_UNIFORM    16
+
+  /*! [C2, chap 31] Noncentral t statistic (2 params):
+       p1 = DOF, p2 = noncentrality parameter. */
+
+#define NIFTI_INTENT_TTEST_NONC 17
+
+  /*! [C1, chap 21] Weibull distribution (3 params):
+       p1 = location, p2 = scale, p3 = power.
+      Density(x) proportional to
+       ((x-p1)/p2)^(p3-1) * exp(-((x-p1)/p2)^p3) for x > p1. */
+
+#define NIFTI_INTENT_WEIBULL    18
+
+  /*! [C1, chap 18] Chi distribution (1 param): p1 = DOF.
+      Density(x) proportional to x^(p1-1) * exp(-x^2/2) for x > 0.
+       p1 = 1 = 'half normal' distribution
+       p1 = 2 = Rayleigh distribution
+       p1 = 3 = Maxwell-Boltzmann distribution.                  */
+
+#define NIFTI_INTENT_CHI        19
+
+  /*! [C1, chap 15] Inverse Gaussian (2 params):
+       p1 = mu, p2 = lambda
+      Density(x) proportional to
+       exp(-p2*(x-p1)^2/(2*p1^2*x)) / x^3  for x > 0. */
+
+#define NIFTI_INTENT_INVGAUSS   20
+
+  /*! [C2, chap 22] Extreme value type I (2 params):
+       p1 = location, p2 = scale
+      cdf(x) = exp(-exp(-(x-p1)/p2)). */
+
+#define NIFTI_INTENT_EXTVAL     21
+
+  /*! Data is a 'p-value' (no params). */
+
+#define NIFTI_INTENT_PVAL       22
+
+  /*! Data is ln(p-value) (no params).
+      To be safe, a program should compute p = exp(-abs(this_value)).
+      The nifti_stats.c library returns this_value
+      as positive, so that this_value = -log(p). */
+
+
+#define NIFTI_INTENT_LOGPVAL    23
+
+  /*! Data is log10(p-value) (no params).
+      To be safe, a program should compute p = pow(10.,-abs(this_value)).
+      The nifti_stats.c library returns this_value
+      as positive, so that this_value = -log10(p). */
+
+#define NIFTI_INTENT_LOG10PVAL  24
+
+  /*! Smallest intent_code that indicates a statistic. */
+
+#define NIFTI_FIRST_STATCODE     2
+
+  /*! Largest intent_code that indicates a statistic. */
+
+#define NIFTI_LAST_STATCODE     24
+
+ /*---------- these values for intent_code aren't for statistics ----------*/
+
+ /*! To signify that the value at each voxel is an estimate
+     of some parameter, set intent_code = NIFTI_INTENT_ESTIMATE.
+     The name of the parameter may be stored in intent_name.     */
+
+#define NIFTI_INTENT_ESTIMATE  1001
+
+ /*! To signify that the value at each voxel is an index into
+     some set of labels, set intent_code = NIFTI_INTENT_LABEL.
+     The filename with the labels may stored in aux_file.        */
+
+#define NIFTI_INTENT_LABEL     1002
+
+ /*! To signify that the value at each voxel is an index into the
+     NeuroNames labels set, set intent_code = NIFTI_INTENT_NEURONAME. */
+
+#define NIFTI_INTENT_NEURONAME 1003
+
+ /*! To store an M x N matrix at each voxel:
+       - dataset must have a 5th dimension (dim[0]=5 and dim[5]>1)
+       - intent_code must be NIFTI_INTENT_GENMATRIX
+       - dim[5] must be M*N
+       - intent_p1 must be M (in float format)
+       - intent_p2 must be N (ditto)
+       - the matrix values A[i][[j] are stored in row-order:
+         - A[0][0] A[0][1] ... A[0][N-1]
+         - A[1][0] A[1][1] ... A[1][N-1]
+         - etc., until
+         - A[M-1][0] A[M-1][1] ... A[M-1][N-1]        */
+
+#define NIFTI_INTENT_GENMATRIX 1004
+
+ /*! To store an NxN symmetric matrix at each voxel:
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_SYMMATRIX
+       - dim[5] must be N*(N+1)/2
+       - intent_p1 must be N (in float format)
+       - the matrix values A[i][[j] are stored in row-order:
+         - A[0][0]
+         - A[1][0] A[1][1]
+         - A[2][0] A[2][1] A[2][2]
+         - etc.: row-by-row                           */
+
+#define NIFTI_INTENT_SYMMATRIX 1005
+
+ /*! To signify that the vector value at each voxel is to be taken
+     as a displacement field or vector:
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_DISPVECT
+       - dim[5] must be the dimensionality of the displacment
+         vector (e.g., 3 for spatial displacement, 2 for in-plane) */
+
+#define NIFTI_INTENT_DISPVECT  1006   /* specifically for displacements */
+#define NIFTI_INTENT_VECTOR    1007   /* for any other type of vector */
+
+ /*! To signify that the vector value at each voxel is really a
+     spatial coordinate (e.g., the vertices or nodes of a surface mesh):
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_POINTSET
+       - dim[0] = 5
+       - dim[1] = number of points
+       - dim[2] = dim[3] = dim[4] = 1
+       - dim[5] must be the dimensionality of space (e.g., 3 => 3D space).
+       - intent_name may describe the object these points come from
+         (e.g., "pial", "gray/white" , "EEG", "MEG").                   */
+
+#define NIFTI_INTENT_POINTSET  1008
+
+ /*! To signify that the vector value at each voxel is really a triple
+     of indexes (e.g., forming a triangle) from a pointset dataset:
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_TRIANGLE
+       - dim[0] = 5
+       - dim[1] = number of triangles
+       - dim[2] = dim[3] = dim[4] = 1
+       - dim[5] = 3
+       - datatype should be an integer type (preferably DT_INT32)
+       - the data values are indexes (0,1,...) into a pointset dataset. */
+
+#define NIFTI_INTENT_TRIANGLE  1009
+
+ /*! To signify that the vector value at each voxel is a quaternion:
+       - dataset must have a 5th dimension
+       - intent_code must be NIFTI_INTENT_QUATERNION
+       - dim[0] = 5
+       - dim[5] = 4
+       - datatype should be a floating point type     */
+
+#define NIFTI_INTENT_QUATERNION 1010
+
+ /*! Dimensionless value - no params - although, as in _ESTIMATE 
+     the name of the parameter may be stored in intent_name.     */
+
+#define NIFTI_INTENT_DIMLESS    1011
+/* @} */
+
+/*---------------------------------------------------------------------------*/
+/* 3D IMAGE (VOLUME) ORIENTATION AND LOCATION IN SPACE:
+   ---------------------------------------------------
+   There are 3 different methods by which continuous coordinates can
+   attached to voxels.  The discussion below emphasizes 3D volumes, and
+   the continuous coordinates are referred to as (x,y,z).  The voxel
+   index coordinates (i.e., the array indexes) are referred to as (i,j,k),
+   with valid ranges:
+     i = 0 .. dim[1]-1
+     j = 0 .. dim[2]-1  (if dim[0] >= 2)
+     k = 0 .. dim[3]-1  (if dim[0] >= 3)
+   The (x,y,z) coordinates refer to the CENTER of a voxel.  In methods
+   2 and 3, the (x,y,z) axes refer to a subject-based coordinate system,
+   with
+     +x = Right  +y = Anterior  +z = Superior.
+   This is a right-handed coordinate system.  However, the exact direction
+   these axes point with respect to the subject depends on qform_code
+   (Method 2) and sform_code (Method 3).
+
+   N.B.: The i index varies most rapidly, j index next, k index slowest.
+    Thus, voxel (i,j,k) is stored starting at location
+      (i + j*dim[1] + k*dim[1]*dim[2]) * (bitpix/8)
+    into the dataset array.
+
+   N.B.: The ANALYZE 7.5 coordinate system is
+      +x = Left  +y = Anterior  +z = Superior
+    which is a left-handed coordinate system.  This backwardness is
+    too difficult to tolerate, so this NIFTI-1 standard specifies the
+    coordinate order which is most common in functional neuroimaging.
+
+   N.B.: The 3 methods below all give the locations of the voxel centers
+    in the (x,y,z) coordinate system.  In many cases, programs will wish
+    to display image data on some other grid.  In such a case, the program
+    will need to convert its desired (x,y,z) values into (i,j,k) values
+    in order to extract (or interpolate) the image data.  This operation
+    would be done with the inverse transformation to those described below.
+
+   N.B.: Method 2 uses a factor 'qfac' which is either -1 or 1; qfac is
+    stored in the otherwise unused pixdim[0].  If pixdim[0]=0.0 (which
+    should not occur), we take qfac=1.  Of course, pixdim[0] is only used
+    when reading a NIFTI-1 header, not when reading an ANALYZE 7.5 header.
+
+   N.B.: The units of (x,y,z) can be specified using the xyzt_units field.
+
+   METHOD 1 (the "old" way, used only when qform_code = 0):
+   -------------------------------------------------------
+   The coordinate mapping from (i,j,k) to (x,y,z) is the ANALYZE
+   7.5 way.  This is a simple scaling relationship:
+
+     x = pixdim[1] * i
+     y = pixdim[2] * j
+     z = pixdim[3] * k
+
+   No particular spatial orientation is attached to these (x,y,z)
+   coordinates.  (NIFTI-1 does not have the ANALYZE 7.5 orient field,
+   which is not general and is often not set properly.)  This method
+   is not recommended, and is present mainly for compatibility with
+   ANALYZE 7.5 files.
+
+   METHOD 2 (used when qform_code > 0, which should be the "normal" case):
+   ---------------------------------------------------------------------
+   The (x,y,z) coordinates are given by the pixdim[] scales, a rotation
+   matrix, and a shift.  This method is intended to represent
+   "scanner-anatomical" coordinates, which are often embedded in the
+   image header (e.g., DICOM fields (0020,0032), (0020,0037), (0028,0030),
+   and (0018,0050)), and represent the nominal orientation and location of
+   the data.  This method can also be used to represent "aligned"
+   coordinates, which would typically result from some post-acquisition
+   alignment of the volume to a standard orientation (e.g., the same
+   subject on another day, or a rigid rotation to true anatomical
+   orientation from the tilted position of the subject in the scanner).
+   The formula for (x,y,z) in terms of header parameters and (i,j,k) is:
+
+     [ x ]   [ R11 R12 R13 ] [        pixdim[1] * i ]   [ qoffset_x ]
+     [ y ] = [ R21 R22 R23 ] [        pixdim[2] * j ] + [ qoffset_y ]
+     [ z ]   [ R31 R32 R33 ] [ qfac * pixdim[3] * k ]   [ qoffset_z ]
+
+   The qoffset_* shifts are in the NIFTI-1 header.  Note that the center
+   of the (i,j,k)=(0,0,0) voxel (first value in the dataset array) is
+   just (x,y,z)=(qoffset_x,qoffset_y,qoffset_z).
+
+   The rotation matrix R is calculated from the quatern_* parameters.
+   This calculation is described below.
+
+   The scaling factor qfac is either 1 or -1.  The rotation matrix R
+   defined by the quaternion parameters is "proper" (has determinant 1).
+   This may not fit the needs of the data; for example, if the image
+   grid is
+     i increases from Left-to-Right
+     j increases from Anterior-to-Posterior
+     k increases from Inferior-to-Superior
+   Then (i,j,k) is a left-handed triple.  In this example, if qfac=1,
+   the R matrix would have to be
+
+     [  1   0   0 ]
+     [  0  -1   0 ]  which is "improper" (determinant = -1).
+     [  0   0   1 ]
+
+   If we set qfac=-1, then the R matrix would be
+
+     [  1   0   0 ]
+     [  0  -1   0 ]  which is proper.
+     [  0   0  -1 ]
+
+   This R matrix is represented by quaternion [a,b,c,d] = [0,1,0,0]
+   (which encodes a 180 degree rotation about the x-axis).
+
+   METHOD 3 (used when sform_code > 0):
+   -----------------------------------
+   The (x,y,z) coordinates are given by a general affine transformation
+   of the (i,j,k) indexes:
+
+     x = srow_x[0] * i + srow_x[1] * j + srow_x[2] * k + srow_x[3]
+     y = srow_y[0] * i + srow_y[1] * j + srow_y[2] * k + srow_y[3]
+     z = srow_z[0] * i + srow_z[1] * j + srow_z[2] * k + srow_z[3]
+
+   The srow_* vectors are in the NIFTI_1 header.  Note that no use is
+   made of pixdim[] in this method.
+
+   WHY 3 METHODS?
+   --------------
+   Method 1 is provided only for backwards compatibility.  The intention
+   is that Method 2 (qform_code > 0) represents the nominal voxel locations
+   as reported by the scanner, or as rotated to some fiducial orientation and
+   location.  Method 3, if present (sform_code > 0), is to be used to give
+   the location of the voxels in some standard space.  The sform_code
+   indicates which standard space is present.  Both methods 2 and 3 can be
+   present, and be useful in different contexts (method 2 for displaying the
+   data on its original grid; method 3 for displaying it on a standard grid).
+
+   In this scheme, a dataset would originally be set up so that the
+   Method 2 coordinates represent what the scanner reported.  Later,
+   a registration to some standard space can be computed and inserted
+   in the header.  Image display software can use either transform,
+   depending on its purposes and needs.
+
+   In Method 2, the origin of coordinates would generally be whatever
+   the scanner origin is; for example, in MRI, (0,0,0) is the center
+   of the gradient coil.
+
+   In Method 3, the origin of coordinates would depend on the value
+   of sform_code; for example, for the Talairach coordinate system,
+   (0,0,0) corresponds to the Anterior Commissure.
+
+   QUATERNION REPRESENTATION OF ROTATION MATRIX (METHOD 2)
+   -------------------------------------------------------
+   The orientation of the (x,y,z) axes relative to the (i,j,k) axes
+   in 3D space is specified using a unit quaternion [a,b,c,d], where
+   a*a+b*b+c*c+d*d=1.  The (b,c,d) values are all that is needed, since
+   we require that a = sqrt(1.0-(b*b+c*c+d*d)) be nonnegative.  The (b,c,d)
+   values are stored in the (quatern_b,quatern_c,quatern_d) fields.
+
+   The quaternion representation is chosen for its compactness in
+   representing rotations. The (proper) 3x3 rotation matrix that
+   corresponds to [a,b,c,d] is
+
+         [ a*a+b*b-c*c-d*d   2*b*c-2*a*d       2*b*d+2*a*c     ]
+     R = [ 2*b*c+2*a*d       a*a+c*c-b*b-d*d   2*c*d-2*a*b     ]
+         [ 2*b*d-2*a*c       2*c*d+2*a*b       a*a+d*d-c*c-b*b ]
+
+         [ R11               R12               R13             ]
+       = [ R21               R22               R23             ]
+         [ R31               R32               R33             ]
+
+   If (p,q,r) is a unit 3-vector, then rotation of angle h about that
+   direction is represented by the quaternion
+
+     [a,b,c,d] = [cos(h/2), p*sin(h/2), q*sin(h/2), r*sin(h/2)].
+
+   Requiring a >= 0 is equivalent to requiring -Pi <= h <= Pi.  (Note that
+   [-a,-b,-c,-d] represents the same rotation as [a,b,c,d]; there are 2
+   quaternions that can be used to represent a given rotation matrix R.)
+   To rotate a 3-vector (x,y,z) using quaternions, we compute the
+   quaternion product
+
+     [0,x',y',z'] = [a,b,c,d] * [0,x,y,z] * [a,-b,-c,-d]
+
+   which is equivalent to the matrix-vector multiply
+
+     [ x' ]     [ x ]
+     [ y' ] = R [ y ]   (equivalence depends on a*a+b*b+c*c+d*d=1)
+     [ z' ]     [ z ]
+
+   Multiplication of 2 quaternions is defined by the following:
+
+     [a,b,c,d] = a*1 + b*I + c*J + d*K
+     where
+       I*I = J*J = K*K = -1 (I,J,K are square roots of -1)
+       I*J =  K    J*K =  I    K*I =  J
+       J*I = -K    K*J = -I    I*K = -J  (not commutative!)
+     For example
+       [a,b,0,0] * [0,0,0,1] = [0,0,-b,a]
+     since this expands to
+       (a+b*I)*(K) = (a*K+b*I*K) = (a*K-b*J).
+
+   The above formula shows how to go from quaternion (b,c,d) to
+   rotation matrix and direction cosines.  Conversely, given R,
+   we can compute the fields for the NIFTI-1 header by
+
+     a = 0.5  * sqrt(1+R11+R22+R33)    (not stored)
+     b = 0.25 * (R32-R23) / a       => quatern_b
+     c = 0.25 * (R13-R31) / a       => quatern_c
+     d = 0.25 * (R21-R12) / a       => quatern_d
+
+   If a=0 (a 180 degree rotation), alternative formulas are needed.
+   See the nifti1_io.c function mat44_to_quatern() for an implementation
+   of the various cases in converting R to [a,b,c,d].
+
+   Note that R-transpose (= R-inverse) would lead to the quaternion
+   [a,-b,-c,-d].
+
+   The choice to specify the qoffset_x (etc.) values in the final
+   coordinate system is partly to make it easy to convert DICOM images to
+   this format.  The DICOM attribute "Image Position (Patient)" (0020,0032)
+   stores the (Xd,Yd,Zd) coordinates of the center of the first voxel.
+   Here, (Xd,Yd,Zd) refer to DICOM coordinates, and Xd=-x, Yd=-y, Zd=z,
+   where (x,y,z) refers to the NIFTI coordinate system discussed above.
+   (i.e., DICOM +Xd is Left, +Yd is Posterior, +Zd is Superior,
+        whereas +x is Right, +y is Anterior  , +z is Superior. )
+   Thus, if the (0020,0032) DICOM attribute is extracted into (px,py,pz), then
+     qoffset_x = -px   qoffset_y = -py   qoffset_z = pz
+   is a reasonable setting when qform_code=NIFTI_XFORM_SCANNER_ANAT.
+
+   That is, DICOM's coordinate system is 180 degrees rotated about the z-axis
+   from the neuroscience/NIFTI coordinate system.  To transform between DICOM
+   and NIFTI, you just have to negate the x- and y-coordinates.
+
+   The DICOM attribute (0020,0037) "Image Orientation (Patient)" gives the
+   orientation of the x- and y-axes of the image data in terms of 2 3-vectors.
+   The first vector is a unit vector along the x-axis, and the second is
+   along the y-axis.  If the (0020,0037) attribute is extracted into the
+   value (xa,xb,xc,ya,yb,yc), then the first two columns of the R matrix
+   would be
+              [ -xa  -ya ]
+              [ -xb  -yb ]
+              [  xc   yc ]
+   The negations are because DICOM's x- and y-axes are reversed relative
+   to NIFTI's.  The third column of the R matrix gives the direction of
+   displacement (relative to the subject) along the slice-wise direction.
+   This orientation is not encoded in the DICOM standard in a simple way;
+   DICOM is mostly concerned with 2D images.  The third column of R will be
+   either the cross-product of the first 2 columns or its negative.  It is
+   possible to infer the sign of the 3rd column by examining the coordinates
+   in DICOM attribute (0020,0032) "Image Position (Patient)" for successive
+   slices.  However, this method occasionally fails for reasons that I
+   (RW Cox) do not understand.
+-----------------------------------------------------------------------------*/
+
+   /* [qs]form_code value:  */      /* x,y,z coordinate system refers to:    */
+   /*-----------------------*/      /*---------------------------------------*/
+
+/*! \defgroup NIFTI1_XFORM_CODES
+    \brief nifti1 xform codes to describe the "standard" coordinate system
+    @{
+ */
+                                    /*! Arbitrary coordinates (Method 1). */
+
+#define NIFTI_XFORM_UNKNOWN      0
+
+                                    /*! Scanner-based anatomical coordinates */
+
+#define NIFTI_XFORM_SCANNER_ANAT 1
+
+                                    /*! Coordinates aligned to another file's,
+                                        or to anatomical "truth".            */
+
+#define NIFTI_XFORM_ALIGNED_ANAT 2
+
+                                    /*! Coordinates aligned to Talairach-
+                                        Tournoux Atlas; (0,0,0)=AC, etc. */
+
+#define NIFTI_XFORM_TALAIRACH    3
+
+                                    /*! MNI 152 normalized coordinates. */
+
+#define NIFTI_XFORM_MNI_152      4
+/* @} */
+
+/*---------------------------------------------------------------------------*/
+/* UNITS OF SPATIAL AND TEMPORAL DIMENSIONS:
+   ----------------------------------------
+   The codes below can be used in xyzt_units to indicate the units of pixdim.
+   As noted earlier, dimensions 1,2,3 are for x,y,z; dimension 4 is for
+   time (t).
+    - If dim[4]=1 or dim[0] < 4, there is no time axis.
+    - A single time series (no space) would be specified with
+      - dim[0] = 4 (for scalar data) or dim[0] = 5 (for vector data)
+      - dim[1] = dim[2] = dim[3] = 1
+      - dim[4] = number of time points
+      - pixdim[4] = time step
+      - xyzt_units indicates units of pixdim[4]
+      - dim[5] = number of values stored at each time point
+
+   Bits 0..2 of xyzt_units specify the units of pixdim[1..3]
+    (e.g., spatial units are values 1..7).
+   Bits 3..5 of xyzt_units specify the units of pixdim[4]
+    (e.g., temporal units are multiples of 8).
+
+   This compression of 2 distinct concepts into 1 byte is due to the
+   limited space available in the 348 byte ANALYZE 7.5 header.  The
+   macros XYZT_TO_SPACE and XYZT_TO_TIME can be used to mask off the
+   undesired bits from the xyzt_units fields, leaving "pure" space
+   and time codes.  Inversely, the macro SPACE_TIME_TO_XYZT can be
+   used to assemble a space code (0,1,2,...,7) with a time code
+   (0,8,16,32,...,56) into the combined value for xyzt_units.
+
+   Note that codes are provided to indicate the "time" axis units are
+   actually frequency in Hertz (_HZ), in part-per-million (_PPM)
+   or in radians-per-second (_RADS).
+
+   The toffset field can be used to indicate a nonzero start point for
+   the time axis.  That is, time point #m is at t=toffset+m*pixdim[4]
+   for m=0..dim[4]-1.
+-----------------------------------------------------------------------------*/
+
+/*! \defgroup NIFTI1_UNITS
+    \brief nifti1 units codes to describe the unit of measurement for
+           each dimension of the dataset
+    @{
+ */
+                               /*! NIFTI code for unspecified units. */
+#define NIFTI_UNITS_UNKNOWN 0
+
+                               /** Space codes are multiples of 1. **/
+                               /*! NIFTI code for meters. */
+#define NIFTI_UNITS_METER   1
+                               /*! NIFTI code for millimeters. */
+#define NIFTI_UNITS_MM      2
+                               /*! NIFTI code for micrometers. */
+#define NIFTI_UNITS_MICRON  3
+
+                               /** Time codes are multiples of 8. **/
+                               /*! NIFTI code for seconds. */
+#define NIFTI_UNITS_SEC     8
+                               /*! NIFTI code for milliseconds. */
+#define NIFTI_UNITS_MSEC   16
+                               /*! NIFTI code for microseconds. */
+#define NIFTI_UNITS_USEC   24
+
+                               /*** These units are for spectral data: ***/
+                               /*! NIFTI code for Hertz. */
+#define NIFTI_UNITS_HZ     32
+                               /*! NIFTI code for ppm. */
+#define NIFTI_UNITS_PPM    40
+                               /*! NIFTI code for radians per second. */
+#define NIFTI_UNITS_RADS   48
+/* @} */
+
+#undef  XYZT_TO_SPACE
+#undef  XYZT_TO_TIME
+#define XYZT_TO_SPACE(xyzt)       ( (xyzt) & 0x07 )
+#define XYZT_TO_TIME(xyzt)        ( (xyzt) & 0x38 )
+
+#undef  SPACE_TIME_TO_XYZT
+#define SPACE_TIME_TO_XYZT(ss,tt) (  (((char)(ss)) & 0x07)   \
+                                   | (((char)(tt)) & 0x38) )
+
+/*---------------------------------------------------------------------------*/
+/* MRI-SPECIFIC SPATIAL AND TEMPORAL INFORMATION:
+   ---------------------------------------------
+   A few fields are provided to store some extra information
+   that is sometimes important when storing the image data
+   from an FMRI time series experiment.  (After processing such
+   data into statistical images, these fields are not likely
+   to be useful.)
+
+  { freq_dim  } = These fields encode which spatial dimension (1,2, or 3)
+  { phase_dim } = corresponds to which acquisition dimension for MRI data.
+  { slice_dim } =
+    Examples:
+      Rectangular scan multi-slice EPI:
+        freq_dim = 1  phase_dim = 2  slice_dim = 3  (or some permutation)
+      Spiral scan multi-slice EPI:
+        freq_dim = phase_dim = 0  slice_dim = 3
+        since the concepts of frequency- and phase-encoding directions
+        don't apply to spiral scan
+
+    slice_duration = If this is positive, AND if slice_dim is nonzero,
+                     indicates the amount of time used to acquire 1 slice.
+                     slice_duration*dim[slice_dim] can be less than pixdim[4]
+                     with a clustered acquisition method, for example.
+
+    slice_code = If this is nonzero, AND if slice_dim is nonzero, AND
+                 if slice_duration is positive, indicates the timing
+                 pattern of the slice acquisition.  The following codes
+                 are defined:
+                   NIFTI_SLICE_SEQ_INC  == sequential increasing
+                   NIFTI_SLICE_SEQ_DEC  == sequential decreasing
+                   NIFTI_SLICE_ALT_INC  == alternating increasing
+                   NIFTI_SLICE_ALT_DEC  == alternating decreasing
+                   NIFTI_SLICE_ALT_INC2 == alternating increasing #2
+                   NIFTI_SLICE_ALT_DEC2 == alternating decreasing #2
+  { slice_start } = Indicates the start and end of the slice acquisition
+  { slice_end   } = pattern, when slice_code is nonzero.  These values
+                    are present to allow for the possible addition of
+                    "padded" slices at either end of the volume, which
+                    don't fit into the slice timing pattern.  If there
+                    are no padding slices, then slice_start=0 and
+                    slice_end=dim[slice_dim]-1 are the correct values.
+                    For these values to be meaningful, slice_start must
+                    be non-negative and slice_end must be greater than
+                    slice_start.  Otherwise, they should be ignored.
+
+  The following table indicates the slice timing pattern, relative to
+  time=0 for the first slice acquired, for some sample cases.  Here,
+  dim[slice_dim]=7 (there are 7 slices, labeled 0..6), slice_duration=0.1,
+  and slice_start=1, slice_end=5 (1 padded slice on each end).
+
+  slice
+  index  SEQ_INC SEQ_DEC ALT_INC ALT_DEC ALT_INC2 ALT_DEC2
+    6  :   n/a     n/a     n/a     n/a    n/a      n/a    n/a = not applicable
+    5  :   0.4     0.0     0.2     0.0    0.4      0.2    (slice time offset
+    4  :   0.3     0.1     0.4     0.3    0.1      0.0     doesn't apply to
+    3  :   0.2     0.2     0.1     0.1    0.3      0.3     slices outside
+    2  :   0.1     0.3     0.3     0.4    0.0      0.1     the range
+    1  :   0.0     0.4     0.0     0.2    0.2      0.4     slice_start ..
+    0  :   n/a     n/a     n/a     n/a    n/a      n/a     slice_end)
+
+  The SEQ slice_codes are sequential ordering (uncommon but not unknown),
+  either increasing in slice number or decreasing (INC or DEC), as
+  illustrated above.
+
+  The ALT slice codes are alternating ordering.  The 'standard' way for
+  these to operate (without the '2' on the end) is for the slice timing
+  to start at the edge of the slice_start .. slice_end group (at slice_start
+  for INC and at slice_end for DEC).  For the 'ALT_*2' slice_codes, the
+  slice timing instead starts at the first slice in from the edge (at
+  slice_start+1 for INC2 and at slice_end-1 for DEC2).  This latter
+  acquisition scheme is found on some Siemens scanners.
+
+  The fields freq_dim, phase_dim, slice_dim are all squished into the single
+  byte field dim_info (2 bits each, since the values for each field are
+  limited to the range 0..3).  This unpleasantness is due to lack of space
+  in the 348 byte allowance.
+
+  The macros DIM_INFO_TO_FREQ_DIM, DIM_INFO_TO_PHASE_DIM, and
+  DIM_INFO_TO_SLICE_DIM can be used to extract these values from the
+  dim_info byte.
+
+  The macro FPS_INTO_DIM_INFO can be used to put these 3 values
+  into the dim_info byte.
+-----------------------------------------------------------------------------*/
+
+#undef  DIM_INFO_TO_FREQ_DIM
+#undef  DIM_INFO_TO_PHASE_DIM
+#undef  DIM_INFO_TO_SLICE_DIM
+
+#define DIM_INFO_TO_FREQ_DIM(di)   ( ((di)     ) & 0x03 )
+#define DIM_INFO_TO_PHASE_DIM(di)  ( ((di) >> 2) & 0x03 )
+#define DIM_INFO_TO_SLICE_DIM(di)  ( ((di) >> 4) & 0x03 )
+
+#undef  FPS_INTO_DIM_INFO
+#define FPS_INTO_DIM_INFO(fd,pd,sd) ( ( ( ((char)(fd)) & 0x03)      ) |  \
+                                      ( ( ((char)(pd)) & 0x03) << 2 ) |  \
+                                      ( ( ((char)(sd)) & 0x03) << 4 )  )
+
+/*! \defgroup NIFTI1_SLICE_ORDER
+    \brief nifti1 slice order codes, describing the acquisition order
+           of the slices
+    @{
+ */
+#define NIFTI_SLICE_UNKNOWN   0
+#define NIFTI_SLICE_SEQ_INC   1
+#define NIFTI_SLICE_SEQ_DEC   2
+#define NIFTI_SLICE_ALT_INC   3
+#define NIFTI_SLICE_ALT_DEC   4
+#define NIFTI_SLICE_ALT_INC2  5  /* 05 May 2005: RWCox */
+#define NIFTI_SLICE_ALT_DEC2  6  /* 05 May 2005: RWCox */
+/* @} */
+
+/*---------------------------------------------------------------------------*/
+/* UNUSED FIELDS:
+   -------------
+   Some of the ANALYZE 7.5 fields marked as ++UNUSED++ may need to be set
+   to particular values for compatibility with other programs.  The issue
+   of interoperability of ANALYZE 7.5 files is a murky one -- not all
+   programs require exactly the same set of fields.  (Unobscuring this
+   murkiness is a principal motivation behind NIFTI-1.)
+
+   Some of the fields that may need to be set for other (non-NIFTI aware)
+   software to be happy are:
+
+     extents    dbh.h says this should be 16384
+     regular    dbh.h says this should be the character 'r'
+     glmin,   } dbh.h says these values should be the min and max voxel
+      glmax   }  values for the entire dataset
+
+   It is best to initialize ALL fields in the NIFTI-1 header to 0
+   (e.g., with calloc()), then fill in what is needed.
+-----------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------*/
+/* MISCELLANEOUS C MACROS
+-----------------------------------------------------------------------------*/
+
+/*.................*/
+/*! Given a nifti_1_header struct, check if it has a good magic number.
+    Returns NIFTI version number (1..9) if magic is good, 0 if it is not. */
+
+#define NIFTI_VERSION(h)                               \
+ ( ( (h).magic[0]=='n' && (h).magic[3]=='\0'    &&     \
+     ( (h).magic[1]=='i' || (h).magic[1]=='+' ) &&     \
+     ( (h).magic[2]>='1' && (h).magic[2]<='9' )   )    \
+ ? (h).magic[2]-'0' : 0 )
+
+/*.................*/
+/*! Check if a nifti_1_header struct says if the data is stored in the
+    same file or in a separate file.  Returns 1 if the data is in the same
+    file as the header, 0 if it is not.                                   */
+
+#define NIFTI_ONEFILE(h) ( (h).magic[1] == '+' )
+
+/*.................*/
+/*! Check if a nifti_1_header struct needs to be byte swapped.
+    Returns 1 if it needs to be swapped, 0 if it does not.     */
+
+#define NIFTI_NEEDS_SWAP(h) ( (h).dim[0] < 0 || (h).dim[0] > 7 )
+
+/*.................*/
+/*! Check if a nifti_1_header struct contains a 5th (vector) dimension.
+    Returns size of 5th dimension if > 1, returns 0 otherwise.         */
+
+#define NIFTI_5TH_DIM(h) ( ((h).dim[0]>4 && (h).dim[5]>1) ? (h).dim[5] : 0 )
+
+/*****************************************************************************/
+
+/*=================*/
+#ifdef  __cplusplus
+}
+#endif
+/*=================*/
+
+#endif /* _NIFTI_HEADER_ */
+
diff --git a/bioimagesuite30_src/include/nifti1_io.h b/bioimagesuite30_src/include/nifti1_io.h
new file mode 100644
index 0000000..c3a43ab
--- /dev/null
+++ b/bioimagesuite30_src/include/nifti1_io.h
@@ -0,0 +1,446 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/** \file nifti1_io.h
+    \brief Data structures for using nifti1_io API.
+           - Written by Bob Cox, SSCC NIMH
+           - Revisions by Rick Reynolds, SSCC NIMH
+ */
+#ifndef _NIFTI_IO_HEADER_
+#define _NIFTI_IO_HEADER_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+
+#ifndef DONT_INCLUDE_ANALYZE_STRUCT
+#define DONT_INCLUDE_ANALYZE_STRUCT  /*** not needed herein ***/
+#endif
+#include "nifti1.h"                  /*** NIFTI-1 header specification ***/
+
+#include <bis_znzlib.h>
+
+/*=================*/
+#ifdef  __cplusplus
+extern "C" {
+#endif
+/*=================*/
+
+/*****===================================================================*****/
+/*****         File nifti1_io.h == Declarations for nifti1_io.c          *****/
+/*****...................................................................*****/
+/*****            This code is released to the public domain.            *****/
+/*****...................................................................*****/
+/*****  Author: Robert W Cox, SSCC/DIRP/NIMH/NIH/DHHS/USA/EARTH          *****/
+/*****  Date:   August 2003                                              *****/
+/*****...................................................................*****/
+/*****  Neither the National Institutes of Health (NIH), nor any of its  *****/
+/*****  employees imply any warranty of usefulness of this software for  *****/
+/*****  any purpose, and do not assume any liability for damages,        *****/
+/*****  incidental or otherwise, caused by any use of this document.     *****/
+/*****===================================================================*****/
+
+/* 
+   Modified by: Mark Jenkinson (FMRIB Centre, University of Oxford, UK)
+   Date: July/August 2004 
+
+      Mainly adding low-level IO and changing things to allow gzipped files
+      to be read and written
+      Full backwards compatability should have been maintained
+
+   Modified by: Rick Reynolds (SSCC/DIRP/NIMH, National Institutes of Health)
+   Date: December 2004
+
+      Modified and added many routines for I/O.
+*/
+
+/********************** Some sample data structures **************************/
+
+typedef struct {                   /** 4x4 matrix struct **/
+  float m[4][4] ;
+} mat44 ;
+
+typedef struct {                   /** 3x3 matrix struct **/
+  float m[3][3] ;
+} mat33 ;
+
+/*...........................................................................*/
+
+/*! \struct nifti_image
+    \brief High level data structure for open nifti datasets in the
+           nifti1_io API.  Note that this structure is not part of the
+           nifti1 format definition; it is used to implement one API
+           for reading/writing formats in the nifti1 format.
+ */
+typedef struct {                /*!< Image storage struct **/
+
+  int ndim ;                    /*!< last dimension greater than 1 (1..7) */
+  int nx ;                      /*!< dimensions of grid array             */
+  int ny ;                      /*!< dimensions of grid array             */
+  int nz ;                      /*!< dimensions of grid array             */
+  int nt ;                      /*!< dimensions of grid array             */
+  int nu ;                      /*!< dimensions of grid array             */
+  int nv ;                      /*!< dimensions of grid array             */
+  int nw ;                      /*!< dimensions of grid array             */
+  int dim[8] ;                  /*!< dim[0]=ndim, dim[1]=nx, etc.         */
+  int nvox ;                    /*!< number of voxels = nx*ny*nz*...*nw   */
+  int nbyper ;                  /*!< bytes per voxel, matches datatype    */
+  int datatype ;                /*!< type of data in voxels: DT_* code    */
+
+  float dx ;                    /*!< grid spacings      */
+  float dy ;                    /*!< grid spacings      */
+  float dz ;                    /*!< grid spacings      */
+  float dt ;                    /*!< grid spacings      */
+  float du ;                    /*!< grid spacings      */
+  float dv ;                    /*!< grid spacings      */
+  float dw ;                    /*!< grid spacings      */
+  float pixdim[8] ;             /*!< pixdim[1]=dx, etc. */
+
+  float scl_slope ;             /*!< scaling parameter - slope        */
+  float scl_inter ;             /*!< scaling parameter - intercept    */
+
+  float cal_min ;               /*!< calibration parameter, minimum   */
+  float cal_max ;               /*!< calibration parameter, maximum   */
+
+  int qform_code ;              /*!< codes for (x,y,z) space meaning  */
+  int sform_code ;              /*!< codes for (x,y,z) space meaning  */
+
+  int freq_dim  ;               /*!< indexes (1,2,3, or 0) for MRI    */
+  int phase_dim ;               /*!< directions in dim[]/pixdim[]     */
+  int slice_dim ;               /*!< directions in dim[]/pixdim[]     */
+
+  int   slice_code  ;           /*!< code for slice timing pattern    */
+  int   slice_start ;           /*!< index for start of slices        */
+  int   slice_end   ;           /*!< index for end of slices          */
+  float slice_duration ;        /*!< time between individual slices   */
+
+  /*! quaternion transform parameters
+    [when writing a dataset, these are used for qform, NOT qto_xyz]   */
+  float quatern_b , quatern_c , quatern_d ,
+        qoffset_x , qoffset_y , qoffset_z ,
+        qfac      ;
+
+  mat44 qto_xyz ;               /*!< qform: transform (i,j,k) to (x,y,z) */
+  mat44 qto_ijk ;               /*!< qform: transform (x,y,z) to (i,j,k) */
+
+  mat44 sto_xyz ;               /*!< sform: transform (i,j,k) to (x,y,z) */
+  mat44 sto_ijk ;               /*!< sform: transform (x,y,z) to (i,j,k) */
+
+  float toffset ;               /*!< time coordinate offset */
+
+  int xyz_units  ;              /*!< dx,dy,dz units: NIFTI_UNITS_* code  */
+  int time_units ;              /*!< dt       units: NIFTI_UNITS_* code  */
+
+  int nifti_type ;              /*!< 0==ANALYZE, 1==NIFTI-1 (1 file),
+                                                 2==NIFTI-1 (2 files),
+                                                 3==NIFTI-ASCII (1 file) */
+  int   intent_code ;           /*!< statistic type (or something)       */
+  float intent_p1 ;             /*!< intent parameters                   */
+  float intent_p2 ;             /*!< intent parameters                   */
+  float intent_p3 ;             /*!< intent parameters                   */
+  char  intent_name[16] ;       /*!< optional description of intent data */
+
+  char descrip[80]  ;           /*!< optional text to describe dataset   */
+  char aux_file[24] ;           /*!< auxiliary filename                  */
+
+  char *fname ;                 /*!< header filename (.hdr or .nii)         */
+  char *iname ;                 /*!< image filename  (.img or .nii)         */
+  int   iname_offset ;          /*!< offset into iname where data starts    */
+  int   swapsize ;              /*!< swap unit in image data (might be 0)   */
+  int   byteorder ;             /*!< byte order on disk (MSB_ or LSB_FIRST) */
+  void *data ;                  /*!< pointer to data: nbyper*nvox bytes     */
+
+  int                num_ext ;  /*!< number of extensions in ext_list       */
+  nifti1_extension * ext_list ; /*!< array of extension structs (with data) */
+
+} nifti_image ;
+
+
+
+/* struct for return from nifti_image_read_bricks() */
+typedef struct {
+  int     nbricks;    /* the number of allocated pointers in 'bricks' */
+  int     bsize;      /* the length of each data block, in bytes      */
+  void ** bricks;     /* array of pointers to data blocks             */
+} nifti_brick_list;
+
+
+/*****************************************************************************/
+/*--------------- Prototypes of functions defined in this file --------------*/
+
+char *nifti_datatype_string   ( int dt ) ;
+char *nifti_units_string      ( int uu ) ;
+char *nifti_intent_string     ( int ii ) ;
+char *nifti_xform_string      ( int xx ) ;
+char *nifti_slice_string      ( int ss ) ;
+char *nifti_orientation_string( int ii ) ;
+
+int   nifti_is_inttype( int dt ) ;
+
+mat44 nifti_mat44_inverse( mat44 R ) ;
+
+mat33 nifti_mat33_inverse( mat33 R ) ;
+mat33 nifti_mat33_polar  ( mat33 A ) ;
+float nifti_mat33_rownorm( mat33 A ) ;
+float nifti_mat33_colnorm( mat33 A ) ;
+float nifti_mat33_determ ( mat33 R ) ;
+mat33 nifti_mat33_mul    ( mat33 A , mat33 B ) ;
+
+void  nifti_swap_2bytes ( int n , void *ar ) ;
+void  nifti_swap_4bytes ( int n , void *ar ) ;
+void  nifti_swap_8bytes ( int n , void *ar ) ;
+void  nifti_swap_16bytes( int n , void *ar ) ;
+void  nifti_swap_Nbytes ( int n , int siz , void *ar ) ;
+
+void  swap_nifti_header ( struct nifti_1_header *h , int is_nifti ) ;
+int   nifti_get_filesize( const char *pathname ) ;
+
+/* main read/write routines */
+
+nifti_image *nifti_image_read_bricks(const char *hname , int nbricks,
+                                     const int *blist, nifti_brick_list * NBL);
+int          nifti_image_load_bricks(nifti_image *nim , int nbricks,
+                                     const int *blist, nifti_brick_list * NBL);
+void         nifti_free_NBL( nifti_brick_list * NBL );
+
+nifti_image *nifti_image_read    ( const char *hname , int read_data ) ;
+int          nifti_image_load    ( nifti_image *nim ) ;
+void         nifti_image_unload  ( nifti_image *nim ) ;
+void         nifti_image_free    ( nifti_image *nim ) ;
+
+int          nifti_read_collapsed_image( nifti_image * nim, const int dims [8],
+                                         void ** data );
+
+void         nifti_image_write   ( nifti_image * nim ) ;
+void         nifti_image_write_bricks(nifti_image * nim, 
+                                      const nifti_brick_list * NBL);
+void         nifti_image_infodump( const nifti_image * nim ) ;
+
+void         nifti_disp_lib_hist( void ) ;     /* to display library history */
+void         nifti_disp_lib_version( void ) ;  /* to display library version */
+int          nifti_disp_matrix_orient( const char * mesg, mat44 mat );
+
+char *       nifti_image_to_ascii  ( const nifti_image * nim ) ;
+nifti_image *nifti_image_from_ascii( const char * str, int * bytes_read ) ;
+
+size_t       nifti_get_volsize(const nifti_image *nim) ;
+
+/* basic file operations */
+int    nifti_set_filenames(nifti_image * nim, const char * prefix, int check,
+                           int set_byte_order);
+char * nifti_makehdrname  (const char * prefix, int nifti_type, int check,
+                           int comp);
+char * nifti_makeimgname  (const char * prefix, int nifti_type, int check,
+                           int comp);
+int    is_nifti_file      (const char *hname);
+char * nifti_find_file_extension(const char * name);
+int    nifti_is_complete_filename(const char* fname);
+int    nifti_validfilename(const char* fname);
+
+int    disp_nifti_1_header(const char * info, const nifti_1_header * hp ) ;
+void   nifti_set_debug_level( int level ) ;
+void   nifti_set_skip_blank_ext( int skip ) ;
+
+int    valid_nifti_brick_list(nifti_image * nim , int nbricks,
+                              const int * blist, int disp_error);
+
+/* znzFile operations */
+znzFile nifti_image_open(const char * hname, char * opts, nifti_image ** nim);
+znzFile nifti_image_write_hdr_img(nifti_image *nim, int write_data,
+                                  const char* opts);
+znzFile nifti_image_write_hdr_img2( nifti_image *nim , int write_opts ,
+               const char* opts, znzFile imgfile, const nifti_brick_list * NBL);
+size_t  nifti_read_buffer(znzFile fp, void* datatptr, size_t ntot,
+                         nifti_image *nim);
+int     nifti_write_all_data(znzFile fp, nifti_image * nim,
+                             const nifti_brick_list * NBL);
+size_t  nifti_write_buffer(znzFile fp, const void * buffer, size_t numbytes);
+nifti_image *nifti_read_ascii_image(znzFile fp, char *fname, int flen,
+                         int read_data);
+znzFile nifti_write_ascii_image(nifti_image *nim, const nifti_brick_list * NBL,
+                         const char * opts, int write_data, int leave_open);
+
+
+void nifti_datatype_sizes( int datatype , int *nbyper, int *swapsize ) ;
+
+void nifti_mat44_to_quatern( mat44 R ,
+                             float *qb, float *qc, float *qd,
+                             float *qx, float *qy, float *qz,
+                             float *dx, float *dy, float *dz, float *qfac ) ;
+
+mat44 nifti_quatern_to_mat44( float qb, float qc, float qd,
+                              float qx, float qy, float qz,
+                              float dx, float dy, float dz, float qfac );
+
+mat44 nifti_make_orthog_mat44( float r11, float r12, float r13 ,
+                               float r21, float r22, float r23 ,
+                               float r31, float r32, float r33  ) ;
+
+int nifti_short_order(void) ;              /* CPU byte order */
+
+
+/* Orientation codes that might be returned from nifti_mat44_to_orientation().*/
+
+#define NIFTI_L2R  1    /* Left to Right         */
+#define NIFTI_R2L  2    /* Right to Left         */
+#define NIFTI_P2A  3    /* Posterior to Anterior */
+#define NIFTI_A2P  4    /* Anterior to Posterior */
+#define NIFTI_I2S  5    /* Inferior to Superior  */
+#define NIFTI_S2I  6    /* Superior to Inferior  */
+
+void nifti_mat44_to_orientation( mat44 R , int *icod, int *jcod, int *kcod ) ;
+
+/*--------------------- Low level IO routines ------------------------------*/
+
+char * nifti_findhdrname (const char* fname);
+char * nifti_findimgname (const char* fname , int nifti_type);
+int    nifti_is_gzfile   (const char* fname);
+
+char * nifti_makebasename(const char* fname);
+
+
+/* other routines */
+struct nifti_1_header   nifti_convert_nim2nhdr(const nifti_image* nim);
+nifti_1_header * nifti_read_header(const char *hname, int *swapped, int check);
+nifti_image    * nifti_copy_nim_info(const nifti_image * src);
+nifti_image    * nifti_simple_init_nim(void);
+nifti_image    * nifti_convert_nhdr2nim(struct nifti_1_header nhdr,
+                                        const char * fname);
+
+int    nifti_hdr_looks_good        (const nifti_1_header * hdr);
+int    nifti_is_valid_ecode        (int ecode);
+int    nifti_nim_is_valid          (nifti_image * nim, int complain);
+int    nifti_nim_has_valid_dims    (nifti_image * nim, int complain);
+int    is_valid_nifti_type         (int nifti_type);
+int    nifti_type_and_names_match  (nifti_image * nim, int show_warn);
+int    nifti_update_dims_from_array(nifti_image * nim);
+void   nifti_set_iname_offset      (nifti_image *nim);
+int    nifti_set_type_from_names   (nifti_image * nim);
+int    nifti_add_extension(nifti_image * nim, const char * data, int len,
+                           int ecode );
+int    nifti_copy_extensions (nifti_image *nim_dest,const nifti_image *nim_src);
+int    nifti_free_extensions (nifti_image *nim);
+int  * nifti_get_intlist     (int nvals , const char *str);
+char * nifti_strdup          (const char *str);
+int    valid_nifti_extensions(const nifti_image *nim);
+
+
+/*-------------------- Some C convenience macros ----------------------------*/
+
+/* NIfTI-1.1 extension codes:
+   see http://nifti.nimh.nih.gov/nifti-1/documentation/faq#Q21 */
+
+#define NIFTI_ECODE_IGNORE           0  /* changed from UNKNOWN, 29 June 2005 */
+
+#define NIFTI_ECODE_DICOM            2  /* intended for raw DICOM attributes  */
+
+#define NIFTI_ECODE_AFNI             4  /* Robert W Cox: rwcox at nih.gov
+                                           http://afni.nimh.nih.gov/afni      */
+
+#define NIFTI_ECODE_COMMENT          6  /* plain ASCII text only              */
+
+#define NIFTI_ECODE_XCEDE            8  /* David B Keator: dbkeator at uci.edu 
+                                           http://www.nbirn.net/Resources
+                                                /Users/Applications/
+                                                /xcede/index.htm              */
+
+#define NIFTI_ECODE_JIMDIMINFO      10  /* Mark A Horsfield:
+                                           mah5 at leicester.ac.uk
+                                           http://someplace/something         */
+
+#define NIFTI_ECODE_WORKFLOW_FWDS   12  /* Kate Fissell: fissel+ at pitt.edu
+                                           http://kraepelin.wpic.pitt.edu
+                                            /~fissell/NIFTI_ECODE_WORKFLOW_FWDS
+                                            /NIFTI_ECODE_WORKFLOW_FWDS.html   */
+
+#define NIFTI_MAX_ECODE             12  /******* maximum extension code *******/
+
+/* nifti_type file codes */
+#define NIFTI_FTYPE_ANALYZE   0
+#define NIFTI_FTYPE_NIFTI1_1  1
+#define NIFTI_FTYPE_NIFTI1_2  2
+#define NIFTI_FTYPE_ASCII     3
+#define NIFTI_MAX_FTYPE       3    /* this should match the maximum code */
+
+/*------------------------------------------------------------------------*/
+/*-- the rest of these apply only to nifti1_io.c, check for _NIFTI1_IO_C_ */
+/*                                                    Feb 9, 2005 [rickr] */
+#ifdef _NIFTI1_IO_C_
+
+typedef struct {
+    int debug;               /*!< debug level for status reports */
+    int skip_blank_ext;      /*!< skip extender if no extensions */
+} nifti_global_options;
+
+#undef  LNI_FERR /* local nifti file error, to be compact and repetative */
+#define LNI_FERR(func,msg,file)                                      \
+            fprintf(stderr,"** ERROR (%s): %s '%s'\n",func,msg,file)
+
+#undef  swap_2
+#undef  swap_4
+#define swap_2(s) nifti_swap_2bytes(1,&(s)) /* s: 2-byte short; swap in place */
+#define swap_4(v) nifti_swap_4bytes(1,&(v)) /* v: 4-byte value; swap in place */
+
+                        /***** isfinite() is a C99 macro, which is
+                               present in many C implementations already *****/
+
+#undef IS_GOOD_FLOAT
+#undef FIXED_FLOAT
+
+#ifdef isfinite       /* use isfinite() to check floats/doubles for goodness */
+#  define IS_GOOD_FLOAT(x) isfinite(x)       /* check if x is a "good" float */
+#  define FIXED_FLOAT(x)   (isfinite(x) ? (x) : 0)           /* fixed if bad */
+#else
+#  define IS_GOOD_FLOAT(x) 1                               /* don't check it */
+#  define FIXED_FLOAT(x)   (x)                               /* don't fix it */
+#endif
+
+#undef  ASSIF                                 /* assign v to *p, if possible */
+#define ASSIF(p,v) if( (p)!=NULL ) *(p) = (v)
+
+#undef  MSB_FIRST
+#undef  LSB_FIRST
+#undef  REVERSE_ORDER
+#define LSB_FIRST 1
+#define MSB_FIRST 2
+#define REVERSE_ORDER(x) (3-(x))    /* convert MSB_FIRST <--> LSB_FIRST */
+
+#define LNI_MAX_NIA_EXT_LEN 100000  /* consider a longer extension invalid */
+
+#endif  /* _NIFTI1_IO_C_ section */
+/*------------------------------------------------------------------------*/
+
+/*=================*/
+#ifdef  __cplusplus
+}
+#endif
+/*=================*/
+
+#endif /* _NIFTI_IO_HEADER_ */
+
diff --git a/bioimagesuite30_src/include/pxisinf.h b/bioimagesuite30_src/include/pxisinf.h
new file mode 100644
index 0000000..2947a7d
--- /dev/null
+++ b/bioimagesuite30_src/include/pxisinf.h
@@ -0,0 +1,80 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//BTX
+/*
+  Compatibility Hacks for MacOSX and SGI IRIX
+*/
+
+#ifndef PXISINF_INCLUDE
+#define PXISINF_INCLUDE
+
+
+#ifdef __APPLE__
+
+  #if ( __GNUC__ >=4 ) 
+    #include <cmath>
+    #define isnan(x) std::isnan(x)
+    #define isinf(x) std::isinf(x)
+  #elif (( __GNUC__ ==3 ) && ( __GNUC_MINOR__ >3 ))
+    #include  <math.h>
+  #else
+    extern "C" {  int isnan(double); }
+    extern "C" {  int isinf(double);  }
+  #endif
+#endif
+
+#ifndef __APPLE__
+    #ifndef isnan
+       # define isnan(x) \
+           (sizeof (x) == sizeof (long double) ? isnan_ld (x) \
+           : sizeof (x) == sizeof (double) ? isnan_d (x) \
+           : isnan_f (x))
+       static inline int isnan_f  (float       x) { return x != x; }
+       static inline int isnan_d  (double      x) { return x != x; }
+       static inline int isnan_ld (long double x) { return x != x; }
+     #endif
+
+     #ifndef isinf
+        # define isinf(x) \
+          (sizeof (x) == sizeof (long double) ? isinf_ld (x) \
+           : sizeof (x) == sizeof (double) ? isinf_d (x) \
+           : isinf_f (x))
+       static inline int isinf_f  (float       x) { return isnan (x - x); }
+       static inline int isinf_d  (double      x) { return isnan (x - x); }
+       static inline int isinf_ld (long double x) { return isnan (x - x); }
+     #endif
+#endif
+
+#ifndef M_PI
+#define M_PI 3.1415926854
+#endif
+
+#endif /* PXISINF_INCLUDE */
+
+//ETX
+
diff --git a/bioimagesuite30_src/include/vtkbisConfigure.h.in b/bioimagesuite30_src/include/vtkbisConfigure.h.in
new file mode 100644
index 0000000..1d102fd
--- /dev/null
+++ b/bioimagesuite30_src/include/vtkbisConfigure.h.in
@@ -0,0 +1,59 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/* 
+ * Here is where system computed values get stored.
+ * These values should only change when the target compile platform changes.
+ */
+
+#cmakedefine BIOIMAGESUITE_USE_NUMERICAL_RECIPES
+#ifdef BIOIMAGESUITE_USE_NUMERICAL_RECIPES
+#define BIS_USE_NR 1
+#endif
+
+#cmakedefine BIOIMAGESUITE_EXPERIMENTAL
+#cmakedefine BIOIMAGESUITE3_USE_CUDA
+#cmakedefine BIOIMAGESUITE3_USE_CUDA_ADVANCED
+#cmakedefine BIOIMAGESUITE3_USE_PYTHON
+
+#ifdef BIOIMAGESUITE3_USE_CUDA
+#cmakedefine BIOIMAGESUITE3_USE_CUDA_VOLUME_RENDERING
+#define BIOIMAGESUITE3_CUDA_VERSION "@CUDA_VERSION@"
+#endif
+
+// This is the version of BioImage Suite !!!
+#define BIOIMAGESUITE_STRING_VERSION "@BIOIMAGESUITE3_VERSION_MAJOR at .@BIOIMAGESUITE3_VERSION_MINOR@@BIOIMAGESUITE3_VERSION_PATCH@"
+
+#define BIOIMAGESUITE_PACK_VERSION "@CPACK_PACKAGE_VERSION@"
+
+#cmakedefine CMAKE_COMPILER_2005 1
+
+#cmakedefine BIOIMAGESUITE3_USE_MYSQL_DATABASE_MODULE
+
+#cmakedefine BIOIMAGESUITE3_EXCLUDE_CODE
+
+
diff --git a/bioimagesuite30_src/installtools/CMakeLists.txt b/bioimagesuite30_src/installtools/CMakeLists.txt
new file mode 100644
index 0000000..76801d7
--- /dev/null
+++ b/bioimagesuite30_src/installtools/CMakeLists.txt
@@ -0,0 +1,101 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+# --------------------------------------------------------
+#
+# Various tools to make install and package tasks possible
+#
+# --------------------------------------------------------
+
+SET(KIT installtools )
+SET(KITLIBS )
+
+SET (KITSRCS 
+  #bis_createpipefiles.cpp
+  bis_fixscripts_base.cpp
+  bis_fixscripts.cpp
+)
+
+# Excluded TCL Code 
+
+IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+SET (KITSRCS
+${KITSRCS}
+bis_creategnomeentries.cpp
+)
+ENDIF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+
+
+SET (KITTCLSRCS )
+
+SET (KITEXTRASFILES
+  installtools/CPack.STGZ_Header.sh.in
+  installtools/NSIS.template.in
+  installtools/bisvtk.tcl
+  installtools/bis_fix.tcl
+)
+
+
+# Create binaries/targets etc
+bis_executable_list(installtools)
+bis_sourcelist("installtools" ${KIT} ${FILELIST})
+
+
+# -------------------------------------------------------------------
+#
+# On windows we also need this little thing to fix registry paths
+
+IF (BIS_UNIXBUILD)
+
+ELSE (BIS_UNIXBUILD)
+
+#MESSAGE(INFO,"Looking to build bisvtk")
+
+FIND_PROGRAM(FREEWRAP
+    NAMES 
+    freewrapTCLSH.exe	
+    freewrapTCLSH
+    )			
+
+ADD_CUSTOM_COMMAND(
+OUTPUT ${EXECUTABLE_OUTPUT_PATH}/bisvtk.exe
+DEPENDS ${BIOIMAGESUITE3_SOURCE_DIR}/installtools/bisvtk.tcl
+COMMENT "Creating bisvtk.exe using ${FREEWRAP}"
+COMMAND ${FREEWRAP} 
+ARGS ${BIOIMAGESUITE3_SOURCE_DIR}/installtools/bisvtk.tcl -o ${EXECUTABLE_OUTPUT_PATH}/bisvtk.exe)
+
+add_custom_target(bisvtk
+DEPENDS ${EXECUTABLE_OUTPUT_PATH}/bisvtk.exe)
+
+install (PROGRAMS ${EXECUTABLE_OUTPUT_PATH}/bisvtk.exe DESTINATION ${BIOIMAGESUITE3_INSTALL_EXTRAPATH}/bin
+    PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE WORLD_READ WORLD_EXECUTE )
+ENDIF (BIS_UNIXBUILD)
+
+#
+# -------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/installtools/bis_creategnomeentries.cpp b/bioimagesuite30_src/installtools/bis_creategnomeentries.cpp
new file mode 100644
index 0000000..29dff15
--- /dev/null
+++ b/bioimagesuite30_src/installtools/bis_creategnomeentries.cpp
@@ -0,0 +1,113 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include "bioimagesuite_settings.h"
+
+
+
+void usage(char* cmdname)
+{
+  fprintf(stdout,"\n%s usage\n %s pathname [ version ] \n\n",
+	  cmdname);
+  exit(0);
+}
+
+
+
+int creategnomefile(std::string fname,std::string pathname,std::string command,std::string realname,std::string version)
+{
+  std::string buffer="";
+
+  buffer+="[Desktop Entry]\n";
+  buffer+="Encoding=UTF-8\n";
+  buffer+="Name="+ realname + "v" + version +"\n";
+  buffer+="Comment=Start " + realname +"\n";
+  buffer+="Exec=" + pathname +"/" + command + "\n";
+  buffer+="Terminal=true\n";
+  buffer+="Type=Application\n";
+  buffer+="Icon=" + pathname + "/images/bioimagesuite.png\n";
+  buffer+="StartupNotify=true\n";
+  buffer+="Categories=Application;Yale BioImage Suite\n";
+  buffer+="X-Desktop-File-Install-Version="+version+"\n";
+  buffer+="MimeType=\n";
+
+  std::ofstream fout(fname.c_str());
+  if (fout.is_open())
+    {
+      fout << buffer;
+      fout.close();
+      fprintf(stderr,"Created %s\n",fname.c_str());
+    }
+  else
+    {
+      fprintf(stdout,"Failed to open %s\n",fname.c_str());
+    }
+  return 1;
+}
+
+int main(int argc,char *argv[])
+{
+  if (argc<=1)
+    {
+      fprintf(stdout,"Not Enough Arguments");
+      usage(argv[0]);
+    }
+
+  std::string pathname=argv[1];
+  std::string version=BIOIMAGESUITE_STRING_VERSION;
+  
+  if (argc>2)
+    version=argv[2];
+
+  int sz=sizeof(void*);
+
+  if (sz==8)
+    version+="_64-bit";
+
+  creategnomefile("/usr/share/applications/bis_console_"+version+".desktop",pathname,"bis_console","BioImage Suite Console ",version);
+  creategnomefile("/usr/share/applications/bis_menu_"+version+".desktop",pathname,"bis_console_menu","BioImage Suite Menu ",version);
+  
+  std::string fname=pathname+"/cleanmenuentries.sh";
+  std::ofstream fout(fname.c_str());
+  std::string buffer="";
+  buffer+="rm /usr/share/applications/bis_console_"+version+".desktop\n";
+  buffer+="rm /usr/share/applications/bis_menu_"+version+".desktop\n";
+  fout << buffer;
+  fout.close();
+  fprintf(stderr,"Created cleanup file %s\n",fname.c_str());
+
+  std::string cmd="chmod +x "+fname;
+  system(cmd.c_str());
+
+}
+    
+
diff --git a/bioimagesuite30_src/installtools/bis_fixlicense.cpp b/bioimagesuite30_src/installtools/bis_fixlicense.cpp
new file mode 100644
index 0000000..d379a29
--- /dev/null
+++ b/bioimagesuite30_src/installtools/bis_fixlicense.cpp
@@ -0,0 +1,306 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <cstring>
+#include "bioimagesuite_settings.h"
+// ----------------------------------------------------------------------------------------------------
+
+int findextension(const char* orig,const char* lookfor,const char* lookfor2)
+{
+  if (lookfor==NULL)
+    return 0;
+
+  
+  int l_orig=strlen(orig);
+  int l_lookfor=strlen(lookfor);
+
+  //fprintf(stdout,"\n\n Looking for %s in %s (%s) \n",lookfor, orig,&orig[l_orig-l_lookfor]);
+
+  if (l_lookfor>l_orig)
+      return 0;
+  
+  if (strcmp(&orig[l_orig-l_lookfor],lookfor)==0)
+    {
+      //fprintf(stdout,"Found %s in %s\n",lookfor,orig);
+      return 1;
+    }
+
+  if (lookfor2==NULL)
+    return 0;
+
+  int l_lookfor2=strlen(lookfor2);  
+  //fprintf(stdout,"\t\t Take 2 looking for %s in %s (%s)\n",lookfor2, orig,&orig[l_orig-l_lookfor2]);
+
+  if (l_lookfor2>l_orig)
+      return 0;
+
+
+  //  fprintf(stdout,"Looking for %s in %s\n",lookfor2, &orig[l_orig-l_lookfor2]);
+
+
+  if (strcmp(&orig[l_orig-l_lookfor2],lookfor2)==0)
+    {
+      //fprintf(stdout,"Found %s in %s\n",lookfor2,orig);
+      return 1;
+    }
+
+  return 0;
+}
+
+// ----------------------------------------------------------------------------------------------------
+int fixandcleancodefile(const char* fname,std::string buffer,std::string licensecpp,std::string licensetcl)
+{
+  std::string fn=fname;
+  int ignorenr=0;
+
+  if (findextension(fname,".sqlite",".db3"))
+    return 0;
+
+
+  if (fn.find("bis_fixlicense")!=std::string::npos)
+    {
+      //      fprintf(stdout," -- Ignoring NumRecipes code in %s\n",fname);
+      ignorenr=1;
+    }
+
+  int tclmode=findextension(fname,".tcl",".txt");
+  if (tclmode==0)
+    tclmode=findextension(fname,".cmake",".cmake");
+
+
+
+
+
+  int cppmode=0;
+  if (tclmode==0)
+    {
+      if (findextension(fname,".cpp",".h"))
+	cppmode=1;
+      else if (findextension(fname,".c",".txx"))
+	cppmode=1;
+      else if (findextension(fname,".h.in",".cc"))
+	cppmode=1;
+      else if (findextension(fname,".cxx",".hpp"))
+	cppmode=1;
+    }
+
+  if (cppmode==0 && tclmode==0)
+    {
+      //      fprintf(stdout,"-- Ignoring file %s (not a text file most likely)\n",fname,tclmode);
+      return 0;
+    }
+
+
+
+  
+  buffer="";
+
+  std::string commentcode="//";
+  if (tclmode)
+    commentcode="#";
+  
+  fprintf(stdout,"-- Fixing License for filename %s (tclmode=%d)\n",fname,tclmode);
+
+  std::ifstream myfile (fname);
+  if (!myfile.is_open())
+    {
+      //      fprintf(stdout,"File %s does not exist\n",fname);
+      return 0;
+    }
+
+
+  std::string line;
+  int count=0,goodcount=0;
+  while ( !myfile.eof())
+    {
+      getline(myfile,line);
+      if (count==0)
+	{
+	  if (line.find("#!/bin")!=std::string::npos)
+	    goodcount=4;
+	}
+      
+      if (count==goodcount)
+	{
+	  if (tclmode==1)
+	    buffer+=licensetcl;
+	  else
+	    buffer+=licensecpp;
+	}
+
+      if (ok==std::string::npos)
+	{
+	  if (!ignorenr)
+	    {
+	      ok=line.find("//BEGINNR");
+#ifdef BIOIMAGESUITE3_EXCLUDE_CODE
+	      if (ok==std::string::npos)	  
+		{
+		  ok=line.find("//BEGIN_EXCLUDE");
+		}
+#endif
+	    }
+	  else
+	    ok=std::string::npos;
+
+	  if (ok==std::string::npos)
+	    {
+	      buffer+=line;
+	      buffer+="\n";
+	    } 
+	  else
+	    {
+	      if (cppmode)
+		{
+		  buffer+="\t\t" + commentcode + "BEGIN OMITTED\n";
+		  buffer+="\t\t" + commentcode + " Some lines of  code have been removed as they\n";
+		  buffer+="\t\t" + commentcode + " derive/depend on the presence of code from the book Numerical Recipes in C\n";
+		  buffer+="\t\t" + commentcode + " which can not be distributed in source form.\n";
+		  buffer+="\t\t" + commentcode + " We have REPLACED the missing code with an alternative version\n";
+		  buffer+="\t\t" + commentcode + " ... see below. The missing code is not mostly OBSOLETE.\n";
+		  buffer+="\t\t" + commentcode + "END OMITTED\n\n";
+		}
+	      else
+		{
+		  //fprintf(stderr,"Line = %s\n",line.c_str());
+		  buffer+="# Excluded TCL Code \n";
+		  //fprintf(stderr,"%s\n",buffer.c_str());
+		}
+
+	      int foundendnr=0;
+	      while ( foundendnr == 0 )
+		{
+		  getline(myfile,line);
+		  if (line.find("//ENDNR")!=std::string::npos)
+		    foundendnr=1;
+#ifdef BIOIMAGESUITE3_EXCLUDE_CODE
+		  else if (line.find("//END_EXCLUDE")!=std::string::npos)
+		    foundendnr=1;
+#endif
+		}
+	    }
+	}
+      ++count;
+    }
+  myfile.close();
+
+  std::ofstream fout(fname);
+  if (fout.is_open())
+    {
+      fout << buffer;
+      fout.close();
+    }
+  else
+    {
+      //      fprintf(stdout,"Failed to open %s\n",fname);
+    }
+  return 1;
+}
+
+// ----------------------------------------------------------------------------------------------------
+void usage(char* cmdname)
+{
+  fprintf(stdout,"\n%s usage\n %s file1 file2 file3\t or\t %s -list filelist.txt [ pathname ] \n",
+	  cmdname,cmdname,cmdname);
+  exit(0);
+}
+// ----------------------------------------------------------------------------------------------------
+int main(int argc,char *argv[])
+{
+  std::string licensecpp;
+
+  std::string licensetcl;
+
+
+  if (argc<=1)
+    {
+      usage(argv[0]);
+    }
+
+  std::string buffer;
+  
+  if (strcmp(argv[1],"-list")!=0)
+    {
+      for(int i=1;i<argc;i++)
+	fixandcleancodefile(argv[i],buffer,licensecpp,licensetcl);
+      return(0);
+    }
+
+  if (argc<=2)
+    {
+      usage(argv[0]);
+    }
+  fprintf(stdout,"\n++ Fixing Licenses\n");
+  fprintf(stdout,"++ Reading Filelist from %s\n",argv[2]);
+  std::ifstream myfile (argv[2]);
+  if (!myfile.is_open())
+    {
+      fprintf(stdout,"File %s does not exist -- perhaps in make package mode\n",argv[2]);
+      exit(0);
+    }
+
+  std::string line;
+  std::string pathname;
+  std::string tmp;
+
+  getline(myfile,line);
+  getline(myfile,line);
+  getline(myfile,line);
+  if (argc>3)
+    pathname=argv[3];
+  else
+    pathname=line;
+
+  fprintf(stdout,"++ Path = %s\n",pathname.c_str());
+
+  getline(myfile,line);
+
+  while ( !myfile.eof())
+    {
+      std::string fname;
+      fname=pathname;
+      fname+="/";
+      getline(myfile,line);
+      if (line.find("#")!=0 && line.length()>1)
+	{
+	  fname+=line;
+	  fixandcleancodefile(fname.c_str(),buffer,licensecpp,licensetcl);
+	}
+      /*      else
+	{
+	  fprintf(stdout,"\t ** Ignoring %s\n",line.c_str());
+	  }*/
+    }
+  myfile.close();
+  exit(0);
+}
+
diff --git a/bioimagesuite30_src/installtools/bis_fixscripts.cpp b/bioimagesuite30_src/installtools/bis_fixscripts.cpp
new file mode 100644
index 0000000..58f8b2d
--- /dev/null
+++ b/bioimagesuite30_src/installtools/bis_fixscripts.cpp
@@ -0,0 +1,370 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include "bioimagesuite_settings.h"
+
+std::string fixpathforwindows(std::string path)
+{
+  int done=0;
+  std::string newpath=path;
+
+  while ( done==0)
+    {
+      int f=newpath.rfind("/");
+      if (f==std::string::npos)
+	{
+	  done=1;
+	}
+      else
+	{
+	  newpath.replace(f,1,"\\");
+	}
+    }
+  return newpath;
+}
+
+std::string fixpathformsys(std::string path)
+{
+  int done=0;
+  std::string newpath=path;
+
+  while ( done==0)
+    {
+      int f=newpath.rfind(":");
+      if (f==std::string::npos)
+	{
+	  done=1;
+	}
+      else
+	{
+	  newpath.replace(f,1,"");
+	}
+    }
+
+  newpath="/"+newpath;
+  return newpath;
+}
+
+// --------------------------------------------------------------------------------------
+
+int fixscript(std::string fname,std::string pathname,std::string buffer,
+	      std::string vtk_dir,std::string itk_dir)
+{
+  buffer="";
+
+  std::ifstream myfile (fname.c_str());
+  if (!myfile.is_open())
+    {
+      fprintf(stdout,"File %s does not exist\n",fname.c_str());
+      return 0;
+    }
+
+  int isbatchfile=0;
+  int iscshfile=0;
+
+  if (fname.rfind(".bat")!=std::string::npos)
+    isbatchfile=1;
+  else if (fname.rfind(".csh")!=std::string::npos)
+    iscshfile=1;
+
+  fprintf(stdout,"-- Fixing Paths for filename %s (windows batchfile=%d,cshfile=%d)\n",fname.c_str(),isbatchfile,iscshfile);
+
+  std::string line;
+  int foundendnr=0;
+  while ( !myfile.eof())
+    {
+      getline(myfile,line);
+      int first=0;
+      if (line.find("bis_fix_script_begin")==std::string::npos || foundendnr==1)
+	{
+	  buffer+=line;
+	  buffer+="\n";
+	}
+      else
+	{
+	  if (iscshfile==1)
+	    {
+	      buffer+="#bis_fix_script_begin\n";
+	      buffer+="setenv BASE " +  pathname +"\n";
+	      buffer+="setenv BIS_VTK_DIR " + vtk_dir + "\n";
+	      buffer+="setenv BINPATH " + pathname + "/bin\n";
+	      buffer+="setenv BASELIB " + pathname + "/lib\n";
+	      buffer+="#bis_fixscript_end\n";
+	    }
+	  else if (isbatchfile==1)
+	    {
+	      buffer +="REM bis_fix_script_begin\n";
+	      buffer +="@set BIOIMAGESUITE=" + pathname + "\n";
+	      buffer +="@set BIS_VTK_DIR=" + vtk_dir +"\n";
+	      buffer +="REM bis_fixscript_end\n";
+	    }
+	  else
+	    {
+#ifdef _WIN32
+	      std::string tmp=pathname;	      pathname=fixpathformsys(tmp);
+	      tmp=vtk_dir;	      vtk_dir=fixpathformsys(tmp);
+#endif
+	      buffer+="#bis_fix_script_begin\n";
+	      buffer+="BASE=" +  pathname +"\n";
+	      buffer+="BIS_VTK_DIR=" + vtk_dir + "\n";
+	      buffer+="BINPATH=" + pathname + "/bin\n";
+	      buffer+="BASELIB=" + pathname + "/lib\n";
+
+	      buffer+="#bis_fixscript_end\n";
+	    }
+	  
+
+	  while ( foundendnr == 0 )
+	    {
+	      getline(myfile,line);
+	      if (line.find("bis_fixscript_end")!=std::string::npos)
+		foundendnr=1;
+	    }
+	}
+    }
+  myfile.close();
+
+  std::ofstream fout(fname.c_str());
+  if (fout.is_open())
+    {
+      fout << buffer;
+      fout.close();
+    }
+  else
+    {
+      fprintf(stdout,"Failed to open %s\n",fname.c_str());
+    }
+  return 1;
+}
+
+
+void usage(char* cmdname)
+{
+  fprintf(stdout,"This script is used to modify shell scripts in BioImage Suite\n\t to use correct paths after installation or as a post-packaging step");
+  fprintf(stdout,"\n%s usage\n %s  mode scriptlist.txt [ newpath ]\n",
+	  cmdname,cmdname);
+  fprintf(stdout,"mode is one of -install or -package\n");
+  fprintf(stdout,"if mode is -package then the newpath argument is mandatory\n");
+  fprintf(stdout,"scriptlist.txt usually sits in bioimagesuite30/lib after installation\n");
+  exit(0);
+}
+// ----------------------------------------------------------------------------------------------------------
+
+int createregistryfile(std::string fname,std::string pathname,std::string buffer)
+{
+  fprintf(stdout," ++ Fixing registry path %s -->",pathname.c_str());
+  std::string newpath=fixpathforwindows(pathname);
+  fprintf(stdout,"%s\n",newpath.c_str());
+
+  buffer="";
+  buffer+="REGEDIT\n";
+  buffer+="HKEY_CLASSES_ROOT\\.tcl = TclScript\n";
+  buffer+="HKEY_CLASSES_ROOT\\TclScript = BioImage Suite tcl script file\n";
+  buffer+="HKEY_CLASSES_ROOT\\TclScript\\DefaultIcon =" + newpath + "\\images\\bioimagesuite.ico\n";
+  buffer+="HKEY_CLASSES_ROOT\\TclScript\\shell\\open\\command = " + newpath + "\\bin\\bisvtk.exe";
+  buffer+=" \"%1\" %* \n";
+
+  fprintf(stdout,"++ Creating Registry File %s\n",fname.c_str());
+      
+
+  std::ofstream fout(fname.c_str());
+  if (fout.is_open())
+    {
+      fout << buffer;
+      fout.close();
+    }
+  else
+    {
+      fprintf(stdout,"Failed to open %s\n",fname.c_str());
+    }
+  return 1;
+}
+
+// ----------------------------------------------------------------------------------------------------------
+
+int main(int argc,char *argv[])
+{
+  int error=0,mode=0;
+  std::string modestr;
+
+  if (argc<2)
+    {
+      error=1;
+    }
+  else
+    {
+      modestr=argv[1];
+      if (modestr=="-package") 
+	{
+	  mode=1;
+	  if (argc==2)
+	    error=1;
+	}
+    }
+
+  if (error==1)
+    {
+      fprintf(stdout,"Not Enough Arguments");
+      usage(argv[0]);
+    }
+
+  std::string vtk_dir="";
+  std::string itk_dir="";
+  std::string pathname="";
+  std::string buffer;
+
+  fprintf(stdout,"\n++ Fixing Script Paths argc=%d, this=%s\n",argc,argv[0]);
+
+  int onwin=0, onmac=0, onunix=1, usingvs2005=0;
+  
+#ifdef _WIN32
+  onwin=1;
+  onunix=0;
+#  ifdef CMAKE_COMPILER_2005
+  usingvs2005=1;
+#  endif
+#endif
+
+#ifdef __APPLE__
+  onmac=1;
+  onunix=1;
+#endif
+
+  int sixtyfourbitlinux=0;
+  if (onmac==0 && onwin==0)
+    {
+      int sz=sizeof(void*);
+      if (sz==8)
+	sixtyfourbitlinux=1;
+    }
+  // End of Configuration
+
+
+  
+    
+
+  fprintf(stdout,"++ Reading Filelist from %s\n",argv[2]);
+  std::ifstream myfile (argv[2]);
+  if (!myfile.is_open())
+    {
+      fprintf(stdout,"File %s does not exist -- perhaps in make package mode\n",argv[2]);
+      exit(0);
+    }
+  
+  std::string line;
+  std::string tmp;
+  
+  getline(myfile,line);  getline(myfile,line);  getline(myfile,line);
+  if (argc>3)
+    pathname=argv[3];
+  else
+    pathname=line;
+
+  
+  getline(myfile,line);  getline(myfile,line);  vtk_dir=line;
+  getline(myfile,line);  getline(myfile,line);  itk_dir=line;
+  getline(myfile,line);
+  
+  if (mode==1)
+    {
+      //fprintf(stdout,"\n++ Fixing Scripts package mode: onunix=%d onmac=%d onwin=%d usingvs2005=%d sixtyfourbitlinux=%d\n",
+      //	      onunix,onmac,onwin,usingvs2005,sixtyfourbitlinux);
+      vtk_dir=pathname+"/../bioimagesuite3_base/vtk52/lib/vtk-5.2";
+      itk_dir=pathname+"/../bioimagesuite3_base/itk30/lib/InsightToolkit";  
+      
+      if (sixtyfourbitlinux)
+	{
+	  vtk_dir=pathname+"/../bioimagesuite3_base64/vtk52/lib/vtk-5.2";
+	  itk_dir=pathname+"/../bioimagesuite3_base64/itk30/lib/InsightToolkit";  
+	}
+      
+      //      fprintf(stderr,"vtk_dir=%s\nitk_dir=%s\npathname=%s\n",vtk_dir.c_str(),itk_dir.c_str(),pathname.c_str());
+    }
+  
+  if (modestr!="-package")
+    modestr="-install";
+
+  fprintf(stdout,"++ Mode = %s \n",modestr.c_str());
+  fprintf(stdout,"++ Using Pathname %s\n",pathname.c_str());
+  fprintf(stdout,"++ Using VTK Pathname %s\n",vtk_dir.c_str());
+
+
+  while ( !myfile.eof())
+    {
+      std::string fname;
+      fname=pathname;
+      fname+="/";
+      getline(myfile,line);
+      if (line.length()>1)
+	{
+	  fname+=line;
+	  fixscript(fname,pathname,buffer,vtk_dir,itk_dir);
+	}
+    }
+  myfile.close();
+  
+#ifdef _WIN32
+  createregistryfile(pathname+"/bin/bisvtkreg.reg",pathname,buffer);
+#endif
+  
+  exit(0);
+}
+/*
+  // Auto mode based on path -- used for cpack postinstall
+  pathname=argv[1];
+
+
+  
+  if (!onwin)
+    {
+      fixscript(pathname+"/setpaths.sh",pathname,buffer,vtk_dir,itk_dir);
+      fixscript(pathname+"/setpaths.csh",pathname,buffer,vtk_dir,itk_dir);
+      fixscript(pathname+"/start_bioimagesuite",pathname,buffer,vtk_dir,itk_dir);
+      fixscript(pathname+"/setpaths_console.sh",pathname,buffer,vtk_dir,itk_dir);
+      fixscript(pathname+"/bis_console",pathname,buffer,vtk_dir,itk_dir);
+      fixscript(pathname+"/bis_console_menu",pathname,buffer,vtk_dir,itk_dir);
+      if (!onmac)
+	fixscript(pathname+"/createmenuentries.sh",pathname,buffer,vtk_dir,itk_dir);
+    }
+  else
+    {
+      createregistryfile(pathname+"/bin/bisvtkreg.reg",pathname,buffer);
+      fixscript(pathname+"/setpaths.bat",pathname,buffer,vtk_dir,itk_dir);
+      fixscript(pathname+"/bioimagesuite_console.bat",pathname,buffer,vtk_dir,itk_dir);
+      fixscript(pathname+"/bioimagesuite.bat",pathname,buffer,vtk_dir,itk_dir);
+      fixscript(pathname+"/setassociations.bat",pathname,buffer,vtk_dir,itk_dir);
+      fixscript(pathname+"/bisexec.bat",pathname,buffer,vtk_dir,itk_dir);
+      fixscript(pathname+"/setpaths.sh",pathname,buffer,vtk_dir,itk_dir);
+    }
+}
+*/
+
diff --git a/bioimagesuite30_src/installtools/bis_fixscripts_base.cpp b/bioimagesuite30_src/installtools/bis_fixscripts_base.cpp
new file mode 100644
index 0000000..8751ef3
--- /dev/null
+++ b/bioimagesuite30_src/installtools/bis_fixscripts_base.cpp
@@ -0,0 +1,345 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string>
+#include <iostream>
+#include <fstream>
+#include "bioimagesuite_settings.h"
+
+std::string fixpathforwindows(std::string path)
+{
+  int done=0;
+  std::string newpath=path;
+
+  while ( done==0)
+    {
+      int f=newpath.rfind("/");
+      if (f==std::string::npos)
+	{
+	  done=1;
+	}
+      else
+	{
+	  newpath.replace(f,1,"\\");
+	}
+    }
+  return newpath;
+}
+
+std::string fixpathformsys(std::string path)
+{
+  int done=0;
+  std::string newpath=path;
+
+  while ( done==0)
+    {
+      int f=newpath.rfind(":");
+      if (f==std::string::npos)
+	{
+	  done=1;
+	}
+      else
+	{
+	  newpath.replace(f,1,"");
+	}
+    }
+
+  newpath="/"+newpath;
+  return newpath;
+}
+
+
+int fixscript(std::string scriptname,std::string in_newpath,std::string variablename,
+	      std::string buffer)
+{
+  fprintf(stdout,"\n++ Scriptname = %s (path=%s) (variablename=%s)\n",
+	  scriptname.c_str(),
+	  in_newpath.c_str(),
+	  variablename.c_str());
+
+
+  std::string newpath=in_newpath;
+
+
+
+
+
+  buffer="";
+
+  std::ifstream myfile (scriptname.c_str());
+  if (!myfile.is_open())
+    {
+      fprintf(stdout,"File %s does not exist\n",scriptname.c_str());
+      return 0;
+    }
+
+  int isbatchfile=0;
+  int iscshfile=0;
+
+  std::string tolookfor= variablename+"=";
+
+  if (scriptname.rfind(".bat")!=std::string::npos)
+    {
+      isbatchfile=1;
+      tolookfor= "@SET "+variablename+"=";
+    }
+  else if (scriptname.rfind(".csh")!=std::string::npos)
+    {
+      iscshfile=1;
+      tolookfor= "setenv "+variablename;
+    }
+
+  fprintf(stdout,"-- Looking for %s (windows batchfile=%d,cshfile=%d)\n",tolookfor.c_str(),isbatchfile,iscshfile);
+
+  std::string line;
+  int foundvariable=0;
+  while ( !myfile.eof())
+    {
+      getline(myfile,line);
+      int first=0;
+
+      if (line.find(tolookfor)==std::string::npos || foundvariable==1)
+	{
+	  buffer+=line;
+	  buffer+="\n";
+	}
+      else
+	{
+	  if (iscshfile==1)
+	    {
+	      buffer+="setenv " + variablename + " " + newpath +"\n";
+	    }
+	  else if (isbatchfile==1)
+	    {
+	      std::string wnewpath=fixpathforwindows(in_newpath);
+	      buffer +="@SET " + variablename + "=" + wnewpath + "\n";
+	    }
+	  else
+	    {
+#ifdef _WIN32
+	      newpath=fixpathformsys(in_newpath);
+#endif
+	      buffer+= variablename +"=" +  newpath +"\n";
+	    }
+
+	  foundvariable=1;
+	}
+    }
+  myfile.close();
+
+  std::ofstream fout(scriptname.c_str());
+  if (fout.is_open())
+    {
+      fout << buffer;
+      fout.close();
+      return 1;
+    }
+
+  
+  fprintf(stdout,"Failed to open %s\n",scriptname.c_str());
+  return(0);
+}
+
+// ----------------------------------------------------------------------------------------
+int fixcmakepaths(std::string in_newpath,std::string oldpath,std::string cmakename)
+{
+  std::string scriptname=in_newpath+"/"+cmakename;
+  std::string searchString=oldpath;
+  //  std::string replaceString=in_newpath;
+
+
+  std::string replaceString =fixpathformsys(in_newpath);
+
+
+  fprintf(stdout,"\n++ Build Config File Name = %s (newpath=%s) (oldpath=%s)\n",
+	  scriptname.c_str(),
+	  in_newpath.c_str(),
+	  oldpath.c_str());
+
+  if ( searchString == replaceString )
+    {
+      fprintf(stdout,"\n ++++++  Nothing to do (%s=%s)\n",in_newpath.c_str(),oldpath.c_str());
+      return 1;
+    }
+  
+
+  
+  std::string buffer="";
+
+  std::ifstream myfile (scriptname.c_str());
+  if (!myfile.is_open())
+    {
+      fprintf(stdout,"File %s does not exist\n",scriptname.c_str());
+      return 0;
+    }
+
+  std::string line;
+  while ( !myfile.eof())
+    {
+      getline(myfile,line);
+      buffer+=line;
+      buffer+="\n";
+    }
+  myfile.close();
+
+
+  std::string::size_type pos = 0;
+  while ( (pos = buffer.find(searchString, pos)) != std::string::npos ) 
+    {
+      buffer.replace( pos, searchString.size(), replaceString );
+      pos++;
+    }
+  
+  std::ofstream fout(scriptname.c_str());
+  if (fout.is_open())
+    {
+      fout << buffer;
+      fout.close();
+      return 1;
+    }
+
+  fprintf(stdout,"Failed to open %s\n",scriptname.c_str());
+  return(0);
+}
+// ----------------------------------------------------------------------------------------
+
+void usage(char* cmdname)
+{
+  fprintf(stdout,"\n%s usage\n %s newpath \n or %s scriptname newpath variablename\n",
+	  cmdname,cmdname,cmdname);
+  exit(0);
+}
+
+int main(int argc,char *argv[])
+{
+  if (argc<2)
+    {
+      usage(argv[0]);
+    }
+
+  std::string buffer="";
+
+  if (argc>4)
+    {
+      std::string scriptname=argv[1];
+      std::string newpath=argv[2];
+      std::string variablename=argv[3];
+      fixscript(scriptname,newpath,variablename,buffer);
+      return(0);
+    }
+
+  std::string newpath=argv[1];
+
+  int onwin=0;
+  int onmac=0;
+  int onunix=1;
+  
+#ifdef _WIN32
+  onwin=1;
+  onunix=0;
+#endif
+
+#ifdef __APPLE__
+  onmac=1;
+  onunix=1;
+#endif
+
+  int sixtyfourbitlinux=0;
+  if (onmac==0 && onwin==0)
+    {
+      int sz=sizeof(void*);
+      fprintf(stdout,"Sz=%d\n",sz);
+      if (sz==8)
+	sixtyfourbitlinux=1;
+    }
+
+
+  fprintf(stdout,"\n++ Fixing Base Scripts: onunix=%d onmac=%d onwin=%d 	sixtyfourbitlinux=%d\n",
+	  onunix,onmac,onwin,sixtyfourbitlinux);
+
+
+  if (sixtyfourbitlinux)
+    {
+      fixscript(newpath+"/bioimagesuite3_base64/setpaths.csh",newpath+"/bioimagesuite3_base64","BASEROOT",buffer);
+      fixscript(newpath+"/bioimagesuite3_base64/setpaths.sh", newpath+"/bioimagesuite3_base64","BASEROOT",buffer);
+    }
+  else if (onunix)
+    {
+      fixscript(newpath+"/bioimagesuite3_base/setpaths.csh",newpath+"/bioimagesuite3_base","BASEROOT",buffer);
+      fixscript(newpath+"/bioimagesuite3_base/setpaths.sh", newpath+"/bioimagesuite3_base","BASEROOT",buffer);
+    }
+  else
+    {
+      fixscript(newpath+"/bioimagesuite3_base/setpaths.bat",newpath+"/bioimagesuite3_base","BASEROOT",buffer);
+      // This is for msys
+      fixscript(newpath+"/bioimagesuite3_base/setpaths.sh",newpath+"/bioimagesuite3_base","BASEROOT",buffer);
+    }
+
+
+  std::string cmakefiles[11];
+  cmakefiles[0]="gdcm2/lib/gdcm-2.0/GDCMBuildSettings.cmake";
+  cmakefiles[1]="gdcm2/lib/gdcm-2.0/GDCMConfig.cmake";
+  cmakefiles[2]="gdcm2/lib/gdcm-2.0/GDCMLibraryDepends.cmake";
+  cmakefiles[3]="itk310/lib/InsightToolkit/ITKBuildSettings.cmake";
+  cmakefiles[4]="itk310/lib/InsightToolkit/ITKConfig.cmake";
+  cmakefiles[5]="vtk52/lib/vtk-5.2/VTKBuildSettings.cmake";
+  cmakefiles[6]="vtk52/lib/vtk-5.2/VTKConfig.cmake";
+  cmakefiles[7]="vtk52/lib/vtk-5.2/VTKLibraryDepends.cmake";
+  if (!onmac)
+    {
+      cmakefiles[8]="tcl84/lib/itclConfig.sh";
+      cmakefiles[9]="tcl84/lib/tclConfig.sh";
+      cmakefiles[10]="tcl84/lib/tkConfig.sh";
+    }
+  else
+    {
+      cmakefiles[8]="tcl84_x11/lib/itclConfig.sh";
+      cmakefiles[9]="tcl84_x11/lib/tclConfig.sh";
+      cmakefiles[10]="tcl84_x11/lib/tkConfig.sh";
+    }
+
+
+  /*  for (int i=0;i<11;i++)
+    {
+      if (sixtyfourbitlinux)
+	{
+	  fixcmakepaths(newpath+"/bioimagesuite3_base64","/usr/local/bioimagesuite3_base_64",cmakefiles[i]);
+	}
+      else if (onunix)
+	{
+	  fixcmakepaths(newpath+"/bioimagesuite3_base","/usr/local/bioimagesuite3_base",cmakefiles[i]);
+	}
+      else
+	{
+	  fixcmakepaths(newpath+"/bioimagesuite3_base","c:/yale/bioimagesuite3_base",cmakefiles[i]);
+	  fixcmakepaths(newpath+"/bioimagesuite3_base","c:/unix/msys/1.0/yale/bioimagesuite3_base",cmakefiles[i]);
+	}
+	}*/
+}
+
diff --git a/bioimagesuite30_src/mpjCommon/CMakeLists.txt b/bioimagesuite30_src/mpjCommon/CMakeLists.txt
new file mode 100644
index 0000000..c99e7ed
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/CMakeLists.txt
@@ -0,0 +1,111 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+#  Modified
+#
+# Here is where you can add the name of your local common classes.
+#
+SET(KIT vtkmpjCommon)
+
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/mpjCommon)
+
+SET (KITSRCS
+    vtkmpjFrameExtract.cpp
+    vtkmpjFrameAppend.cpp
+    vtkmpjFrameAverage.cpp
+    vtkmpjFramePermutation.cpp
+    vtkmpjImageInterleaving.cpp
+    vtkmpjImageTwoNorm.cpp
+    vtkmpjImageStatistics.cpp
+    vtkmpjPriorityQueue.cpp
+    vtkmpjTestOptimizer.cpp
+    vtkmpjTensorStreamline.cpp
+    vtkmpjImageBoundary.cpp
+    vtkmpjTensorStreamlineRegionFilter.cpp
+    vtkmpjTensorStreamlineStatistics.cpp
+    vtkmpjStreamlineQuantization.cpp
+    vtkmpjImagePointSource.cpp
+    vtkmpjScalarsToFieldData.cpp
+    vtkmpjStreamer.cpp
+    vtkmpjVectorStreamline.cpp
+    vtkmpjImageSignalToNoiseRatio.cpp
+    vtkmpjStreamlineDistance.cpp
+    vtkmpjThresholdPolyData.cpp
+    vtkmpjThresholdPolyDataByDistance.cpp
+    vtkmpjVectorStreamlineStatistics.cpp
+    vtkmpjImageHessian.cpp
+    vtkmpjImageVesselEnhancement.cpp
+    vtkmpjImageVesselMaximum.cpp
+    vtkmpjDiffusionProfile.cpp
+    vtkmpjTubeFilter.cpp
+    vtkmpjVertexSource.cpp
+    vtkmpjSphereSubdivisionSource.cpp
+    vtkmpjIcosahedronSource.cpp
+    vtkmpjImageT2Relax.cpp
+)
+
+SET_SOURCE_FILES_PROPERTIES(
+vtkmpjStreamer
+ABSTRACT
+)
+
+SET(KITLIBS
+  vtkmpjCommon
+  numerics
+  vtkpxCommon
+  vtkpxCommonTCL
+  vtkCommonTCL
+   ${BIOIMAGESUITE3_COMMON_LIBS}
+)
+
+SET(KITJAVALIBS
+  vtkpxCommonJava
+  vtkpxCommon
+  numerics
+   ${BIOIMAGESUITE3_COMMON_JAVALIBS}
+)
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+SET (KITEXTRAFILES)
+SET (KITTCLSRCS )
+
+
+bis_complex("mpjCommon" ${KIT} ${FILELIST})
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjDiffusionProfile.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjDiffusionProfile.cpp
new file mode 100644
index 0000000..dac8c9e
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjDiffusionProfile.cpp
@@ -0,0 +1,284 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjDiffusionProfile.h"
+#include "vtkPointSet.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkDoubleArray.h"
+#include "vtkUnstructuredGrid.h"
+
+vtkStandardNewMacro(vtkmpjDiffusionProfile);
+
+// Construct object with scaling on and scale factor 1.0. 
+vtkmpjDiffusionProfile::vtkmpjDiffusionProfile()
+{
+  this->ScaleFactor = 1.0;
+  this->ColorMode = COLOR_BY_SCALARS;
+  this->ShapeMode = SHAPE_SPHERE;
+  this->ClampScaling = 0;
+  this->MaxScaleFactor = 100;
+  this->ArrayName = NULL;
+}
+
+vtkmpjDiffusionProfile::~vtkmpjDiffusionProfile()
+{
+  if (this->ArrayName)
+    delete []ArrayName;
+  
+  this->SetSource(NULL);
+}
+
+void vtkmpjDiffusionProfile::Execute()
+{
+  vtkDataSet *input = this->GetInput();
+  vtkPolyData *output = this->GetOutput();
+  
+  vtkPointData *pd = input->GetPointData();
+  vtkPointData *outPD = output->GetPointData();
+  vtkDataArray *inScalars = pd->GetScalars();
+  vtkDataArray *inArray = inScalars;
+
+  vtkIdType ptIncr, subIncr, cellId;
+  vtkCellArray *sourceCells, *cells;
+  vtkCell *cell;
+  vtkIdList *cellPts;
+  vtkIdType npts;
+
+  // make sure source geometry has been specified.
+  if (this->GetSource() == NULL)
+    {
+      vtkErrorMacro("No source.");
+      return;
+    }
+
+  //printf("input=%d, pd=%d, inscalars=%d, inAdcs=%d\n",input,pd,inScalars,inADCs);
+  if (this->ArrayName != NULL) {
+    inArray = pd->GetArray(this->ArrayName);
+  }
+
+  vtkIdType numPts = input->GetNumberOfPoints();  
+  vtkIdType numComp = inArray->GetNumberOfComponents();
+  
+  vtkPoints *newPts = vtkPoints::New();  
+  vtkCellArray *newCells = vtkCellArray::New();
+  
+  // get source geometry information
+  vtkPoints *sourcePts = this->GetSource()->GetPoints();
+  vtkIdType numSourcePts = sourcePts->GetNumberOfPoints();
+  vtkIdType numSourceCells = this->GetSource()->GetNumberOfCells();
+  
+  newPts = vtkPoints::New();
+  newPts->Allocate(numPts*numSourcePts);
+
+  // Setting up for calls to PolyData::InsertNextCell()
+  if ( (sourceCells=this->GetSource()->GetPolys())->GetNumberOfCells() > 0 )
+    {
+      cells = vtkCellArray::New();
+      cells->Allocate(numPts*sourceCells->GetSize());
+      output->SetPolys(cells);
+      cells->Delete();
+    }
+  
+  //newScalars = vtkFloatArray::New();
+  //newScalars = vtkUnsignedCharArray::New();
+
+  printf("ColorByOrientation=%d\n",this->ColorMode);
+  
+  vtkDataArray *newScalars;
+
+  if (this->ColorMode == COLOR_BY_ORIENTATION) {
+    newScalars = vtkUnsignedCharArray::New();
+    newScalars->SetNumberOfComponents(3);
+  } else {
+    newScalars = vtkDoubleArray::New();
+    newScalars->SetNumberOfComponents(1);
+  }
+  
+  printf("numPts=%d,%d\n",numPts,numSourcePts);
+  printf("result from alloc=%d\n",newScalars->Allocate(numPts*numSourcePts));
+  
+  double max_val = -VTK_LARGE_FLOAT;
+  double min_val = VTK_LARGE_FLOAT;
+  double *norm_val = new double[numComp];
+  int numNewPts=0;
+  int index=0;
+  
+  double *scalar=NULL;
+  double *values=NULL;
+
+  vtkIdType *pts;
+  pts = new vtkIdType[this->GetSource()->GetMaxCellSize()];
+  
+  printf("traverse points\n");
+
+  // Traverse all points and copy topology
+  for (vtkIdType inPtId=0; inPtId < numPts; inPtId++)    
+    {	  
+      ptIncr = inPtId * numSourcePts;
+      
+      for (cellId=0; cellId < numSourceCells; cellId++)
+	{
+	  cell = this->GetSource()->GetCell(cellId);
+	  
+	  cellPts = cell->GetPointIds();
+	  npts = cellPts->GetNumberOfIds();
+	  
+	  // This variable may be removed, but that
+	  // will not improve readability
+	  subIncr = ptIncr + numSourcePts;
+	  
+	  for (int i=0; i < npts; i++)
+	    {
+	      pts[i] = cellPts->GetId(i) + subIncr;
+	    }
+	  
+	  output->InsertNextCell(cell->GetCellType(),npts,pts);
+	}
+    }
+
+  printf("creating scalars\n");
+  
+  for (vtkIdType inPtId=0; inPtId < numPts; inPtId++)
+    {
+      ptIncr = inPtId * numSourcePts;
+      
+      // populate vector
+      scalar = inScalars->GetTuple(inPtId);       
+      values = inArray->GetTuple(inPtId); 
+      
+      // determine minimum/maximum value from profile
+      max_val = -VTK_LARGE_FLOAT;
+      min_val =  VTK_LARGE_FLOAT;
+      for (int i=0; i<numComp; i++) {
+	norm_val[i] = values[i];
+	if (values[i] > max_val) {
+	  max_val = values[i];
+	}	
+	if (values[i] < min_val) {
+	  min_val = values[i];
+	}	
+      }
+      
+      // normalize numbers 
+      for (int i=0; i<numComp; i++) {
+	norm_val[i] = (norm_val[i] - min_val) / (max_val - min_val);
+      }       
+      
+      // translate Source to Input point
+      double *x = input->GetPoint(inPtId);
+
+      index = numNewPts;
+      
+      double np[3];
+      
+      // for each of the 32 directions insert position
+      for (int i=0; i<numComp; i++) {
+	
+	double *p = sourcePts->GetPoint(i);
+
+	if (this->ShapeMode == SHAPE_DEFORMATION) {
+	  np[0] = p[0] * norm_val[i]*this->ScaleFactor + x[0];
+	  np[1] = p[1] * norm_val[i]*this->ScaleFactor + x[1];	  
+	  np[2] = p[2] * norm_val[i]*this->ScaleFactor + x[2];
+	} else {
+	  np[0] = p[0] * this->ScaleFactor + x[0];
+	  np[1] = p[1] * this->ScaleFactor + x[1];	  
+	  np[2] = p[2] * this->ScaleFactor + x[2];
+	}
+	
+	// insert point
+	newPts->InsertNextPoint(np);
+
+	// insert scalar
+	if (this->ColorMode == COLOR_BY_DIFFUSIVITIES) {
+	  newScalars->InsertNextTuple(&norm_val[i]); 	
+	} else if (this->ColorMode == COLOR_BY_ORIENTATION) {
+	  // TO DO:
+	  float rgb[3]={fabs(p[0])*255, fabs(p[1])*255, fabs(p[2])*255};
+	  newScalars->InsertNextTuple(rgb);
+	} else {
+	  newScalars->InsertNextTuple(&scalar[0]);
+	} 
+
+	//printf("numNewScalars=%d,numNewPts=%d\n",numPts*numSourcePts,numNewPts);
+
+	numNewPts++;
+	
+      }
+
+    }
+  
+  printf ("out of loop\n");
+
+  delete [] norm_val;
+  delete [] pts;
+
+  output->SetPoints(newPts);
+  newPts->Delete();
+
+  printf("before setting scalars\n");
+
+  outPD->SetScalars(newScalars);
+  newScalars->Delete();
+
+  printf("before setting point\n");
+
+ 
+
+  printf("before the end\n");
+  
+}
+
+void vtkmpjDiffusionProfile::SetSource(vtkPolyData *source)
+{
+  this->vtkProcessObject::SetNthInput(1, source);
+}
+ 
+vtkPolyData *vtkmpjDiffusionProfile::GetSource()
+{
+  if (this->NumberOfInputs < 2)
+    {
+    return NULL;
+    }
+  return (vtkPolyData *)(this->Inputs[1]);
+   
+}
+
+void vtkmpjDiffusionProfile::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+  
+  os << indent << "Scale Factor: " << this->ScaleFactor << "\n";
+  os << indent << "Color Mode: " << this->ColorMode << endl;
+  os << indent << "Clamp Scaling: " << (this->ClampScaling ? "On\n" : "Off\n");
+  os << indent << "Max Scale Factor: " << this->MaxScaleFactor << "\n";
+}
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjDiffusionProfile.h b/bioimagesuite30_src/mpjCommon/vtkmpjDiffusionProfile.h
new file mode 100644
index 0000000..a337d94
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjDiffusionProfile.h
@@ -0,0 +1,140 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjDiffusionProfile_h
+#define __vtkmpjDiffusionProfile_h
+
+#include "vtkDataSetToPolyDataFilter.h"
+#include "vtkCell.h"
+#include "vtkCellArray.h"
+#include "vtkDataSet.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkTransform.h"
+#include "vtkDoubleArray.h"
+
+//BTX
+enum
+  {
+    COLOR_BY_SCALARS,
+    COLOR_BY_DIFFUSIVITIES,
+    COLOR_BY_ORIENTATION
+  };
+//ETX
+
+enum
+  {
+    SHAPE_SPHERE,
+    SHAPE_DEFORMATION
+  };
+
+class vtkmpjDiffusionProfile : public vtkDataSetToPolyDataFilter
+{
+public:
+  vtkTypeMacro(vtkmpjDiffusionProfile,vtkDataSetToPolyDataFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  static vtkmpjDiffusionProfile *New();
+
+  // Description:
+  // Specify the geometry to copy to each point.
+  void SetSource(vtkPolyData *source);
+  vtkPolyData *GetSource();
+
+  // Description:
+  // Specify scale factor to scale object by. (Scale factor always affects
+  // output even if scaling is off.)
+  vtkSetMacro(ScaleFactor,float);
+  vtkGetMacro(ScaleFactor,float);
+
+  // Description:
+  // Set the color mode to be used for the glyphs.  This can be set to
+  // use the input scalars (default) or to use the apparent diffusion
+  // coefficients for each direction.
+  // The recognized values are:
+  // COLOR_BY_SCALARS = 0 (default)
+  // COLOR_BY_DIFFUSIVITIES = 1
+  // COLOR_BY_ORIENTATION = 2
+  vtkSetClampMacro(ColorMode, int, COLOR_BY_SCALARS, COLOR_BY_ORIENTATION);
+  vtkGetMacro(ColorMode, int);
+  void SetColorModeToScalars() {this->SetColorMode(COLOR_BY_SCALARS);};
+  void SetColorModeToDiffusivities() { this->SetColorMode(COLOR_BY_DIFFUSIVITIES);};
+  void SetColorModeToOrientation() { this->SetColorMode(COLOR_BY_ORIENTATION);};
+  
+  vtkSetClampMacro(ShapeMode, int, SHAPE_SPHERE, SHAPE_DEFORMATION);
+  vtkGetMacro(ShapeMode, int);
+  void SetShapeModeToSphere() {this->SetColorMode(SHAPE_SPHERE);};
+  void SetShapeModeToDeformation() { this->SetColorMode(SHAPE_DEFORMATION);};
+    
+  // Description:
+  // Turn on/off scalar clamping. If scalar clamping is on, the ivar
+  // MaxScaleFactor is used to control the maximum scale factor. (This is
+  // useful to prevent uncontrolled scaling near singularities.)
+  vtkSetMacro(ClampScaling,int);
+  vtkGetMacro(ClampScaling,int);
+  vtkBooleanMacro(ClampScaling,int);
+  
+  // Description:
+  // Set/Get the maximum allowable scale factor. 
+  // The boolean ClampScaling has to 
+  // be "on" for this to work.
+  vtkSetMacro(MaxScaleFactor,float);
+  vtkGetMacro(MaxScaleFactor,float);
+
+  // Description
+  // Sets/Gets the array of data
+  vtkSetStringMacro(ArrayName);
+  vtkGetStringMacro(ArrayName);
+
+protected:
+  char *ArrayName;
+  
+  float ScaleFactor; // Scale factor to use to scale geometry
+  int ColorMode; // The coloring mode to use for the glyphs.
+  int ShapeMode; // Shape mode to use when drawing the profile
+  int ClampScaling; // Boolean controls whether scaling is clamped.
+  float MaxScaleFactor; // Maximum scale factor (ScaleFactor*eigenvalue)
+   
+  vtkmpjDiffusionProfile();
+  ~vtkmpjDiffusionProfile();
+
+  void Execute();
+
+private:
+  vtkmpjDiffusionProfile(const vtkmpjDiffusionProfile&);  // Not implemented.
+  void operator=(const vtkmpjDiffusionProfile&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjFrameAppend.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjFrameAppend.cpp
new file mode 100644
index 0000000..7d59899
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjFrameAppend.cpp
@@ -0,0 +1,159 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjFrameAppend.h"
+
+//------------------------------------------------------------------------------
+vtkmpjFrameAppend* vtkmpjFrameAppend::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjFrameAppend");
+  if(ret)
+    {
+      return (vtkmpjFrameAppend*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjFrameAppend;
+}
+
+// Construct object with no children.
+vtkmpjFrameAppend::vtkmpjFrameAppend()
+{
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjFrameAppend::~vtkmpjFrameAppend()
+{
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFrameAppend::AddInput(vtkImageData *input)
+{
+  this->vtkProcessObject::AddInput(input);
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjFrameAppend::SetInput(int idx, vtkImageData *input)
+{
+  this->vtkProcessObject::SetNthInput(idx, input);
+}
+
+//----------------------------------------------------------------------------
+vtkImageData *vtkmpjFrameAppend::GetInput()
+{
+  return this->GetInput(0);
+}
+
+//----------------------------------------------------------------------------
+vtkImageData *vtkmpjFrameAppend::GetInput(int idx)
+{
+  if (this->NumberOfInputs <= idx)
+    {
+      return NULL;
+    }
+  
+  return (vtkImageData*)(this->Inputs[idx]);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFrameAppend::ExecuteInformation()
+{
+  if (this->NumberOfInputs==0 || this->GetInput(0)==NULL) {
+    vtkErrorMacro(<<"No Input Image Data !!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  int ncomp=0;
+  for(int i=0; i<this->NumberOfInputs; i++) 
+      ncomp += this->GetInput(i)->GetNumberOfScalarComponents();
+  
+  vtkImageData *output=this->GetOutput();
+  int dim[3];  this->GetInput(0)->GetDimensions(dim);
+  
+  output->CopyStructure(this->GetInput(0));
+  output->SetNumberOfScalarComponents(ncomp);
+}
+
+// ----------------------------------------------------------------------------
+
+void vtkmpjFrameAppend::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim_0[3];
+  this->GetInput(0)->GetDimensions(dim_0);
+  
+  for (int i=1;i<this->NumberOfInputs;i++)
+    {
+      if (this->GetInput(i)==NULL)
+	{
+	  vtkErrorMacro(<<"No Input Image Data " << i << " !!");
+	  return;
+	}
+      else
+	{
+	  int dim_1[3];
+	  this->GetInput(i)->GetDimensions(dim_1);
+	  int sum=0;
+	  for (int kk=0;kk<=2;kk++)
+	    sum+=abs(dim_1[kk]-dim_0[kk]);
+	  if (sum!=0)
+	    {
+	      vtkErrorMacro(<<"Images have different Dimensions !!");
+	      return;
+	    }
+	}
+    }
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  int numcomp=output->GetNumberOfScalarComponents();
+
+  this->UpdateProgress(0.01);
+
+  int noutcomp = 0;
+  for (int i=0; i<this->NumberOfInputs; i++) 
+    {
+      vtkDataArray *in=this->GetInput(i)->GetPointData()->GetScalars();
+      int nc = this->GetInput(i)->GetNumberOfScalarComponents();
+    
+      for (int comp=0;comp<nc;comp++) 
+	{
+	  out->CopyComponent(noutcomp,in,comp);
+	  noutcomp++;
+	}
+    }
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjFrameAppend.h b/bioimagesuite30_src/mpjCommon/vtkmpjFrameAppend.h
new file mode 100644
index 0000000..db1dbed
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjFrameAppend.h
@@ -0,0 +1,77 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkmpjFrameAppend_h
+#define __vtkmpjFrameAppend_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjFrameAppend : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjFrameAppend *New();
+  vtkTypeMacro(vtkmpjFrameAppend,vtkpxSimpleImageToImageFilter);
+  
+  // Multiple Input Stuff
+  // --------------------
+  // Description:
+  // Set an Input of this filter. 
+  virtual void SetInput(int num, vtkImageData *input);
+  
+  // Description:
+  // Adds an input to the first null position in the input list.
+  // Expands the list memory if necessary
+  virtual void AddInput(vtkImageData *input);
+  
+  // Description:
+  // Get one input to this filter
+  vtkImageData *GetInput(int num);
+  vtkImageData *GetInput();
+  
+protected:
+  vtkmpjFrameAppend();
+  virtual ~vtkmpjFrameAppend();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  vtkmpjFrameAppend(const vtkmpjFrameAppend&); // Not implemented
+  void operator=(const vtkmpjFrameAppend&); // Not implemented
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjFrameAverage.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjFrameAverage.cpp
new file mode 100644
index 0000000..75408af
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjFrameAverage.cpp
@@ -0,0 +1,186 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjFrameAverage.h"
+
+//------------------------------------------------------------------------------
+vtkmpjFrameAverage* vtkmpjFrameAverage::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjFrameAverage");
+  if(ret)
+    {
+      return (vtkmpjFrameAverage*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjFrameAverage;
+}
+
+// Construct object with no children.
+vtkmpjFrameAverage::vtkmpjFrameAverage()
+{
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjFrameAverage::~vtkmpjFrameAverage()
+{
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFrameAverage::AddInput(vtkImageData *input)
+{
+  this->vtkProcessObject::AddInput(input);
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjFrameAverage::SetInput(int idx, vtkImageData *input)
+{
+  this->vtkProcessObject::SetNthInput(idx, input);
+}
+
+//----------------------------------------------------------------------------
+vtkImageData *vtkmpjFrameAverage::GetInput()
+{
+  return this->GetInput(0);
+}
+
+//----------------------------------------------------------------------------
+vtkImageData *vtkmpjFrameAverage::GetInput(int idx)
+{
+  if (this->NumberOfInputs <= idx)
+    {
+      return NULL;
+    }
+  
+  return (vtkImageData*)(this->Inputs[idx]);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFrameAverage::ExecuteInformation()
+ {   
+   this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+   this->GetOutput()->SetScalarType(VTK_FLOAT);
+ }
+
+// ----------------------------------------------------------------------------
+
+void vtkmpjFrameAverage::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if (this->NumberOfInputs==0 || this->GetInput(0)==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+  
+  int dim_0[3];
+  this->GetInput(0)->GetDimensions(dim_0);
+  
+  for (int i=1;i<this->NumberOfInputs;i++)
+    {
+      if (this->GetInput(i)==NULL)
+	{
+	  vtkErrorMacro(<<"No Input Image Data " << i << " !!");
+	  return;
+	}
+      else
+	{
+	  int dim_1[3];
+	  this->GetInput(i)->GetDimensions(dim_1);
+	  int sum=0;
+	  for (int kk=0;kk<=2;kk++)
+	    sum+=abs(dim_1[kk]-dim_0[kk]);
+	  if (sum!=0)
+	    {
+	      vtkErrorMacro(<<"Multiple Images have different Dimensions !!");
+	      return;
+	    }
+	}
+    }
+  
+
+  // Create Output Array
+  // -------------------
+  int dim[3];  
+  input->GetDimensions(dim);
+  int numframes = input->GetNumberOfScalarComponents();
+  
+  vtkDebugMacro(<< "Averaging Frames\n" <<  "Dimensions " << dim[0] <<","<< dim[1] <<","<< dim[2] << "\n");
+  
+  /*vtkStructuredPoints* output=this->GetOutput();
+    output->SetSpacing(this->GetInput(0)->GetSpacing());
+    output->SetOrigin(this->GetInput(0)->GetOrigin());
+    output->SetScalarType(VTK_FLOAT);
+    output->SetNumberOfScalarComponents(numframes);
+    output->SetDimensions(dim[0],dim[1],dim[2]);
+    output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+    output->AllocateScalars();*/
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  int numscalars=out->GetNumberOfTuples();
+  int count = 0;
+  float pog = 0.0;
+  int tenth= (int)(numscalars*numframes / 10.0);
+
+  this->UpdateProgress(0.01);
+
+  for (int comp=0;comp<numframes;comp++)
+    for (int n=0;n<numscalars;n++)      
+      {
+	float sum=0.0;
+	float v;
+	//int c=0;
+	
+	for (int series=0;series<this->NumberOfInputs;series++)
+	  {
+	      v = GetInput(series)->GetPointData()->GetScalars()->GetComponent(n,comp);	    
+	      sum += v;
+	  }
+	
+	float mean = sum / float(this->NumberOfInputs);
+
+	out->SetComponent(n,comp,mean);
+     	
+	count++;
+	if (count==tenth)
+	  {
+	    pog+=0.1;
+	    this->UpdateProgress(pog);
+	    count=0;
+	  }
+      }
+  
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjFrameAverage.h b/bioimagesuite30_src/mpjCommon/vtkmpjFrameAverage.h
new file mode 100644
index 0000000..4158920
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjFrameAverage.h
@@ -0,0 +1,77 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkmpjFrameAverage_h
+#define __vtkmpjFrameAverage_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjFrameAverage : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjFrameAverage *New();
+  vtkTypeMacro(vtkmpjFrameAverage,vtkpxSimpleImageToImageFilter);
+  
+  // Multiple Input Stuff
+  // --------------------
+  // Description:
+  // Set an Input of this filter. 
+  virtual void SetInput(int num, vtkImageData *input);
+  
+  // Description:
+  // Adds an input to the first null position in the input list.
+  // Expands the list memory if necessary
+  virtual void AddInput(vtkImageData *input);
+  
+  // Description:
+  // Get one input to this filter
+  vtkImageData *GetInput(int num);
+  vtkImageData *GetInput();
+  
+protected:
+  vtkmpjFrameAverage();
+  virtual ~vtkmpjFrameAverage();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  vtkmpjFrameAverage(const vtkmpjFrameAverage&); // Not implemented
+  void operator=(const vtkmpjFrameAverage&); // Not implemented
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjFrameExtract.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjFrameExtract.cpp
new file mode 100644
index 0000000..a88a499
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjFrameExtract.cpp
@@ -0,0 +1,207 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkmpjFrameExtract.h"
+
+#include "vtkImageData.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkObjectFactory.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+
+#include <math.h>
+
+vtkStandardNewMacro(vtkmpjFrameExtract);
+
+//----------------------------------------------------------------------------
+vtkmpjFrameExtract::vtkmpjFrameExtract()
+{
+  this->SetNumberOfInputPorts(1);
+  this->SetNumberOfOutputPorts(1);
+
+  this->StartFrame = 0;
+  this->EndFrame = 0;
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjFrameExtract::SetFrameInterval(int start, int end)
+{
+  if (this->StartFrame != start && this->EndFrame != end)
+    {
+      this->StartFrame = start;
+      this->EndFrame = end;
+      this->Modified();
+    }
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjFrameExtract::SetFrameNumber(int frame)
+{
+  if (this->StartFrame != frame && this->EndFrame != frame)
+    {
+      this->StartFrame = this->EndFrame = frame;
+      this->Modified();
+    }
+}   
+
+//----------------------------------------------------------------------------
+// This method tells the superclass that only one component will remain.
+int vtkmpjFrameExtract::RequestInformation (
+  vtkInformation       * vtkNotUsed( request ),
+  vtkInformationVector ** vtkNotUsed( inputVector ), 
+  vtkInformationVector * outputVector)
+{
+  vtkDataObject::SetPointDataActiveScalarInfo(
+    outputVector->GetInformationObject(0), -1, this->EndFrame - this->StartFrame + 1);
+  return 1;
+}
+
+//----------------------------------------------------------------------------
+template <class T>
+void vtkmpjFrameExtractExecute(vtkmpjFrameExtract *self,
+                                      vtkImageData *inData, T *inPtr,
+                                      vtkImageData *outData, T *outPtr,
+                                      int outExt[6], int id)
+{
+  int idxR, idxY, idxZ;
+  int maxX, maxY, maxZ;
+  vtkIdType inIncX, inIncY, inIncZ;
+  vtkIdType outIncX, outIncY, outIncZ;
+  int cnt, inCnt;
+  int start, end, offset;
+  unsigned long count = 0;
+  unsigned long target;
+  
+  // find the region to loop over
+  maxX = outExt[1] - outExt[0];
+  maxY = outExt[3] - outExt[2]; 
+  maxZ = outExt[5] - outExt[4];
+  target = static_cast<unsigned long>((maxZ+1)*(maxY+1)/50.0);
+  target++;
+  
+  // Get increments to march through data 
+  inData->GetContinuousIncrements(outExt, inIncX, inIncY, inIncZ);
+  outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
+
+  cnt = outData->GetNumberOfScalarComponents();
+  inCnt = inData->GetNumberOfScalarComponents();
+  
+  // Loop through output pixels
+  start = self->GetStartFrame();
+  end = self->GetEndFrame();
+
+  for (idxZ = 0; idxZ <= maxZ; idxZ++)
+    {
+      for (idxY = 0; !self->AbortExecute && idxY <= maxY; idxY++)
+	{
+	  if (!id) 
+	    {
+	      if (!(count%target))
+		{
+		  self->UpdateProgress(count/(50.0*target));
+		}
+	      count++;
+	    }
+	  	  
+	  for (idxR = 0; idxR <= maxX; idxR++)
+	    {
+	      // Pixel operation
+	      offset = start; // starting component
+	      while (offset <= end)
+		{
+		  *outPtr = *(inPtr + offset);
+		  outPtr++;
+		  offset++;
+		}
+	      inPtr += inCnt;
+	    }
+      
+	  outPtr += outIncY;
+	  inPtr += inIncY;
+	}
+      outPtr += outIncZ;
+      inPtr += inIncZ;
+    }
+}
+
+
+//----------------------------------------------------------------------------
+// This method is passed input and output datas, and executes the
+// ExtractComponents function on each line.  
+void vtkmpjFrameExtract::ThreadedExecute (vtkImageData *inData, 
+                                                vtkImageData *outData,
+                                                int outExt[6], int id)
+{
+  int max, idx;
+  void *inPtr = inData->GetScalarPointerForExtent(outExt);
+  void *outPtr = outData->GetScalarPointerForExtent(outExt);
+  
+  // this filter expects that input is the same type as output.
+  if (inData->GetScalarType() != outData->GetScalarType())
+    {
+    vtkErrorMacro(<< "Execute: input ScalarType, " 
+                  << inData->GetScalarType()
+                  << ", must match out ScalarType " 
+                  << outData->GetScalarType());
+    return;
+    }
+  
+  // make sure we can get all of the components.
+  max = inData->GetNumberOfScalarComponents();
+  for (idx = this->StartFrame; idx <= this->EndFrame; ++idx)
+    {
+    if (idx >= max || idx < 0)
+      {
+      vtkErrorMacro("Execute: Component " << idx
+                    << " is not in input.");
+      return;
+      }
+    }
+  
+  // choose which templated function to call.
+  switch (inData->GetScalarType())
+    {
+    vtkTemplateMacro(
+      vtkmpjFrameExtractExecute(this, inData, 
+                                       static_cast<VTK_TT *>(inPtr), outData, 
+                                       static_cast<VTK_TT *>(outPtr),
+                                       outExt, id));
+    default:
+      vtkErrorMacro(<< "Execute: Unknown ScalarType");
+      return;
+    }
+}
+
+void vtkmpjFrameExtract::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+
+  os << indent << "StartFrame: " << this->StartFrame << endl;
+  os << indent << "EndFrame: " << this->EndFrame << endl;
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjFrameExtract.h b/bioimagesuite30_src/mpjCommon/vtkmpjFrameExtract.h
new file mode 100644
index 0000000..1503d78
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjFrameExtract.h
@@ -0,0 +1,84 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#ifndef __vtkmpjFrameExtract_h
+#define __vtkmpjFrameExtract_h
+
+
+#include "vtkThreadedImageAlgorithm.h"
+
+class vtkmpjFrameExtract : public vtkThreadedImageAlgorithm
+{
+public:
+  static vtkmpjFrameExtract *New();
+  vtkTypeMacro(vtkmpjFrameExtract,vtkThreadedImageAlgorithm);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Set subset of frames to extract
+  vtkSetMacro(StartFrame, int);
+  vtkGetMacro(StartFrame, int);
+  vtkSetMacro(EndFrame, int);
+  vtkGetMacro(EndFrame, int);
+
+  // Description:
+  // Set subset of frames to extract
+  void SetFrameInterval(int start, int end);
+
+  // Convenience method for extracting only one frame
+  void SetFrameNumber(int frame);
+
+protected:
+  vtkmpjFrameExtract();
+  ~vtkmpjFrameExtract() {};
+
+  int StartFrame;
+  int EndFrame;
+
+  virtual int RequestInformation (vtkInformation *, vtkInformationVector**,
+                                  vtkInformationVector *);
+  
+  void ThreadedExecute (vtkImageData *inData, vtkImageData *outData, 
+                       int ext[6], int id);
+private:
+  vtkmpjFrameExtract(const vtkmpjFrameExtract&);  // Not implemented.
+  void operator=(const vtkmpjFrameExtract&);  // Not implemented.
+};
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjFramePermutation.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjFramePermutation.cpp
new file mode 100644
index 0000000..a8b4b7d
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjFramePermutation.cpp
@@ -0,0 +1,105 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjFramePermutation.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+
+//------------------------------------------------------------------------------
+vtkmpjFramePermutation* vtkmpjFramePermutation::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjFramePermutation");
+  if(ret)
+    {
+    return (vtkmpjFramePermutation*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjFramePermutation;
+}
+
+// Construct object with no children.
+vtkmpjFramePermutation::vtkmpjFramePermutation()
+{
+  this->Permutation = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjFramePermutation::~vtkmpjFramePermutation()
+{
+  if (this->Permutation != NULL)
+    this->Permutation->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFramePermutation::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+
+  vtkDataArray* in=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  int numscalars=in->GetNumberOfTuples();
+
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+
+  float pog = 0.0;
+  int tenth=(int)(numscalars * nc / 10.0);
+  
+  int count = 0;
+  for(int c=0; c<this->Permutation->GetNumberOfTuples(); c++) {
+    int target = (int)this->Permutation->GetTuple1(c);
+    //    fprintf(stderr,"%d to target=%d\n",c,target);
+    for(int n=0;n<numscalars;n++) {
+      out->SetComponent(n,c,in->GetComponent(n,target));
+      
+      count++;
+      if (count==tenth) {
+	pog+=0.1;
+	this->UpdateProgress(pog);
+	count=0;
+      }
+    }
+  }
+
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjFramePermutation.h b/bioimagesuite30_src/mpjCommon/vtkmpjFramePermutation.h
new file mode 100644
index 0000000..927dfab
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjFramePermutation.h
@@ -0,0 +1,67 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkmpjFramePermutation_h
+#define __vtkmpjFramePermutation_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkIntArray.h"
+
+class vtkmpjFramePermutation : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkmpjFramePermutation *New();
+  vtkTypeMacro(vtkmpjFramePermutation,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // target frame permutation
+  vtkGetObjectMacro(Permutation, vtkIntArray);
+  vtkSetObjectMacro(Permutation, vtkIntArray);
+
+protected:
+  vtkIntArray *Permutation;
+
+  vtkmpjFramePermutation();
+  virtual ~vtkmpjFramePermutation();
+  
+  virtual void SimpleExecute(vtkImageData *in, vtkImageData *out);
+
+ private:
+  vtkmpjFramePermutation(const vtkmpjFramePermutation&) {};
+  void operator=(const vtkmpjFramePermutation&) {};
+  
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjIcosahedronSource.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjIcosahedronSource.cpp
new file mode 100644
index 0000000..54e96f6
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjIcosahedronSource.cpp
@@ -0,0 +1,465 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjIcosahedronSource.h"
+
+#include "vtkCellArray.h"
+#include "vtkFloatArray.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+
+#include <math.h>
+
+#define VTK_MPJ_EQTOL 1E-6
+
+//----------------------------------------------------------------------------
+
+#define tau 0.8506508084 /* t=(1+sqrt(5))/2, tau=t/sqrt(1+t^2) */ 
+#define one 0.5257311121 /* one=1/sqrt(1+t^2) , unit sphere */
+
+#define ZA  0
+#define ZB  1
+#define ZC  2
+#define ZD  3
+#define YA  4
+#define YB  5
+#define YC  6
+#define YD  7
+#define XA  8
+#define XB  9
+#define XC 10
+#define XD 11
+
+/* Twelve vertices of icosahedron on unit sphere */
+float vtkmpjIcosahedronSource_icosahedron[12][3] = {
+  {  tau,  one, 0.0 },  // ZA
+  { -tau,  one, 0.0 },  // ZB
+  { -tau, -one, 0.0 },  // ZC
+  {  tau, -one, 0.0 },  // ZD
+  {  one, 0.0,  tau },  // YA
+  {  one, 0.0, -tau },  // YB
+  { -one, 0.0, -tau },  // YC
+  { -one, 0.0 , tau },  // YD
+  { 0.0,  tau,  one },  // XA
+  { 0.0, -tau,  one },  // XB
+  { 0.0, -tau, -one },  // XC
+  { 0.0,  tau, -one }}; // XD
+
+/* Twelve colors of icosahedron on unit sphere */
+float vtkmpjIcosahedronSource_icosahedron_color[12][4] = {
+  {  tau*255,  one*255, 0.0, 255 },  // ZA
+  {  tau*255,  one*255, 0.0, 255 },  // ZB
+  {  tau*255, one*255, 0.0, 255 },  // ZC
+  {  tau*255, one*255, 0.0, 255 },  // ZD
+  {  one*255, 0.0,  tau*255, 255 },  // YA
+  {  one*255, 0.0,  tau*255, 255 },  // YB
+  {  one*255, 0.0,  tau*255, 255 },  // YC
+  {  one*255, 0.0 , tau*255, 255 },  // YD
+  { 0.0,  tau*255,  one*255, 255 },  // XA
+  { 0.0,  tau*255,  one*255, 255 },  // XB
+  { 0.0,  tau*255, one*255, 255 },  // XC
+  { 0.0,  tau*255, one*255, 255 }}; // XD
+
+/* Structure for unit icosahedron */
+vtkIdType vtkmpjIcosahedronSource_ico[20][3] = {
+  { YA, XA, YD },
+  { YA, YD, XB },
+  { YB, YC, XD }, 
+  { YB, XC, YC }, 
+  { ZA, YA, ZD },
+  { ZA, ZD, YB }, 
+  { ZC, YD, ZB }, 
+  { ZC, ZB, YC }, 
+  { XA, ZA, XD },
+  { XA, XD, ZB },
+  { XB, XC, ZD }, 
+  { XB, ZC, XC },
+  { XA, YA, ZA },
+  { XD, ZA, YB }, 
+  { YA, XB, ZD },
+  { YB, ZD, XC },
+  { YD, XA, ZB }, 
+  { YC, ZB, XD },
+  { YD, ZC, XB },
+  { YC, XC, ZC }};
+
+vtkStandardNewMacro(vtkmpjIcosahedronSource);
+
+//----------------------------------------------------------------------------
+vtkmpjIcosahedronSource::vtkmpjIcosahedronSource()
+{
+  this->Depth = 1;
+  this->AllowDuplicatePoints = 1;
+}
+ 
+//----------------------------------------------------------------------------
+void vtkmpjIcosahedronSource::InitializePolys(vtkPoints *pts, vtkCellArray *polys, vtkUnsignedCharArray *scalars)
+{
+  // Create icosahedron
+  for (int i=0;i<12;i++) {
+    pts->InsertNextPoint((float *)&vtkmpjIcosahedronSource_icosahedron[i]);
+    
+    // insert scalars
+    scalars->InsertNextTuple((float *)&vtkmpjIcosahedronSource_icosahedron_color[i]);
+  }
+  
+  // Generate mesh connectivity
+  for (int i=0;i<20;i++)
+    polys->InsertNextCell(3, (vtkIdType *)&vtkmpjIcosahedronSource_ico[i]);
+  
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjIcosahedronSource::FindOrInsert1Point(vtkPoints *newPoints, vtkUnsignedCharArray *newScalars, float a[3], vtkIdType &ra)
+{
+  int numpts = newPoints->GetNumberOfPoints();
+  int found = 0;
+  double *x;
+  
+  // initialize
+  ra = -1;
+  
+  // compare
+  for (int i=numpts-1; i>=0; i--) {    
+
+    x = newPoints->GetPoint(i);    
+
+    // if point is found, return
+    if ((fabs(a[0]-x[0])<VTK_MPJ_EQTOL) && (fabs(a[1]-x[1])<VTK_MPJ_EQTOL) && (fabs(a[2]-x[2])<VTK_MPJ_EQTOL)) {
+      
+      ra = i;
+      
+      found = 1;
+      
+      break;
+    }
+    
+  }
+  
+  // append new point
+  if (found == 0) {
+    float ca[4];
+    ra = newPoints->InsertNextPoint(a[0], a[1], a[2]);
+    ca[0] = 255*fabs(a[0]); ca[1]=255*fabs(a[1]); ca[2]=255*fabs(a[2]); ca[3]=255;
+    newScalars->InsertNextTuple(ca);
+  }
+
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjIcosahedronSource::FindOrInsert3Points(vtkPoints *newPoints, vtkUnsignedCharArray *newScalars, float a[3], float b[3], float c[3], vtkIdType &ra, vtkIdType &rb, vtkIdType &rc)
+{
+  int numpts = newPoints->GetNumberOfPoints();
+  int found[3] = {0, 0, 0};
+  double *x;
+  
+  // initialize
+  ra = rb = rc = -1;
+  
+  // compare points
+  for (int i=numpts-1; i>=0; i--) {
+
+    x = newPoints->GetPoint(i);
+    
+    if ((fabs(a[0]-x[0])<VTK_MPJ_EQTOL) && (fabs(a[1]-x[1])<VTK_MPJ_EQTOL) && (fabs(a[2]-x[2])<VTK_MPJ_EQTOL)) 
+      { ra = i; found[0] = 1; }
+    if ((fabs(b[0]-x[0])<VTK_MPJ_EQTOL) && (fabs(b[1]-x[1])<VTK_MPJ_EQTOL) && (fabs(b[2]-x[2])<VTK_MPJ_EQTOL)) 
+      { rb = i; found[1] = 1; }
+    if ((fabs(c[0]-x[0])<VTK_MPJ_EQTOL) && (fabs(c[1]-x[1])<VTK_MPJ_EQTOL) && (fabs(c[2]-x[2])<VTK_MPJ_EQTOL)) 
+      { rc = i; found[2] = 1; }
+
+    // if all points were found, break out
+    if (found[0] && found[1] && found[2])
+      break;
+    
+  }
+
+  // append new point(s)
+  if (found[0] == 0) {
+    float ca[4];
+    ra = newPoints->InsertNextPoint(a[0], a[1], a[2]);
+    ca[0] = 255*fabs(a[0]); ca[1]=255*fabs(a[1]); ca[2]=255*fabs(a[2]); ca[3]=255;
+    newScalars->InsertNextTuple(ca);
+  }
+  if (found[1] == 0) {
+    float cb[3];
+    rb = newPoints->InsertNextPoint(b[0], b[1], b[2]);
+    cb[0] = 255*fabs(b[0]); cb[1]=255*fabs(b[1]); cb[2]=255*fabs(b[2]); cb[3]=255;
+    newScalars->InsertNextTuple(cb);
+  }
+  if (found[2] == 0) {
+    float cc[3];
+    rc = newPoints->InsertNextPoint(c[0], c[1], c[2]);
+    cc[0] = 255*fabs(c[0]); cc[1]=255*fabs(c[1]); cc[2]=255*fabs(c[2]); cc[3]=255;
+    newScalars->InsertNextTuple(cc);
+  }
+
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjIcosahedronSource::SubdividePolys(vtkPoints *newPoints, vtkCellArray *oldCells, vtkCellArray *newCells, vtkUnsignedCharArray *newScalars)
+{
+  vtkIdType numPts, numCells, *pts;
+  float *v;
+  float x0[3], x1[3], x2[3], x3[3], x4[3];
+  float a[3], b[3], c[3], pa[3], pb[3], pc[3];
+   
+  numPts = newPoints->GetNumberOfPoints();
+  numCells = oldCells->GetNumberOfCells();
+  
+  // initiate triangle traversal
+  oldCells->InitTraversal();  
+  
+  int count=-1;
+
+  // traverse each triangle 
+  while(oldCells->GetNextCell(numPts, pts) != 0) {
+    
+    count++;
+    
+    // fetch cells
+    this->conn[0][this->Depth]=pts[0];
+    this->conn[0][0]=pts[1];
+    this->conn[this->Depth][0]=pts[2];
+
+    // fetch cell points
+    for(int i=0;i<3;i++) {
+      x0[i] = (newPoints->GetPoint(pts[0]))[i]; 
+      x1[i] = (newPoints->GetPoint(pts[1]))[i];
+      x2[i] = (newPoints->GetPoint(pts[2]))[i];
+    }
+    
+    // compute edge increment
+    for(int i=0;i<3;i++) {
+      a[i] = -(x0[i] - x2[i]) * (1.0 / (float)this->Depth);
+      b[i] = -(x0[i] - x1[i]) * (1.0 / (float)this->Depth);
+      c[i] = -(x1[i] - x2[i]) * (1.0 / (float)this->Depth);
+    }
+    
+    // subdivide each edge of the current triangle
+    for(int k=1;k<this->Depth;k++) {
+      for(int i=0;i<3;i++) {
+	pa[i] = x0[i] + a[i]*k;
+	pb[i] = x0[i] + b[i]*k;
+	pc[i] = x1[i] + c[i]*k; 
+      }
+      
+      // normalize coordinates
+      (void)vtkMath::Normalize(pa);
+      (void)vtkMath::Normalize(pb);
+      (void)vtkMath::Normalize(pc);
+      
+      // insert points
+      if (this->AllowDuplicatePoints) {
+
+	// allow point duplicates
+	this->conn[k][this->Depth-k] = newPoints->InsertNextPoint(pa[0],pa[1],pa[2]);
+	this->conn[0][this->Depth-k] = newPoints->InsertNextPoint(pb[0],pb[1],pb[2]);
+	this->conn[k][0] = newPoints->InsertNextPoint(pc[0],pc[1],pc[2]);
+
+	// insert new scalars
+	float sc[4]={0.0,0.0,0.0,255};
+
+	sc[0] = fabs(pa[0])*255; sc[1] = fabs(pa[1])*255; sc[2] = fabs(pa[2])*255;
+	newScalars->InsertNextTuple(sc);
+
+	sc[0] = fabs(pb[0])*255; sc[1] = fabs(pb[1])*255; sc[2] = fabs(pb[2])*255;
+	newScalars->InsertNextTuple(sc);
+
+	sc[0] = fabs(pc[0])*255; sc[1] = fabs(pc[1])*255; sc[2] = fabs(pc[2])*255;
+	newScalars->InsertNextTuple(sc);
+
+      } else {
+
+	// non-duplication employs linear search - slow
+	vtkIdType ra, rb, rc;
+	
+	FindOrInsert3Points(newPoints, newScalars, pa, pb, pc, ra, rb, rc);
+	
+	this->conn[k][this->Depth-k] = ra;
+	this->conn[0][this->Depth-k] = rb;
+	this->conn[k][0] = rc;
+	
+      }     
+    }
+    
+    // compute points inside the triangle
+    for(int l=2;l<this->Depth;l++) {
+
+      for(int i=0;i<3;i++) {
+	x3[i] = (newPoints->GetPoint(this->conn[0][l]))[i];
+	x4[i] = (newPoints->GetPoint(this->conn[l][0]))[i];
+      }
+      
+      // compute increment
+      for(int i=0;i<3;i++) {
+	a[i] = -(x3[i] - x4[i]) * (1.0 / (float)l);
+      }
+      
+      // compute point coordinates
+      for(int k=1;k<l;k++) {
+	for(int i=0;i<3;i++) {
+	  pa[i] = x3[i] + a[i]*k;	  
+	} 
+	
+	// normalize coordinates
+	(void)vtkMath::Normalize(pa);
+	
+	// insert points
+	if (this->AllowDuplicatePoints) {
+	  
+	  // allow point duplicates
+	  this->conn[k][l-k] = newPoints->InsertNextPoint(pa[0],pa[1],pa[2]);
+
+	  // insert new scalars
+	  float sc[4] = {0,0,0,255};
+
+	  sc[0] = fabs(pa[0])*255; sc[1] = fabs(pa[1])*255; sc[2] = fabs(pa[2])*255;
+	  newScalars->InsertNextTuple(sc);
+	  
+	} else {
+
+	  // non-duplication employs linear search - slow
+	  vtkIdType ra;
+	  
+	  FindOrInsert1Point(newPoints, newScalars, pa, ra);
+	  
+	  this->conn[k][l-k] = ra;
+	}
+      }      
+    }
+    
+    // create new triangle cells
+
+    // insert first batch of new triangles
+    for(int i=0;i<this->Depth;i++)
+      for(int j=this->Depth-i;j>0;j--) {
+	// triangle [ij,ij-1,i+1j-1]
+	newCells->InsertNextCell(3);
+	newCells->InsertCellPoint(this->conn[i][j]);
+	newCells->InsertCellPoint(this->conn[i][j-1]);
+	newCells->InsertCellPoint(this->conn[i+1][j-1]);
+      }
+
+    // insert second batch of new triangles
+    for(int i=1;i<this->Depth;i++)
+      for(int j=this->Depth-i;j>0;j--) {
+	// triangle [ij,i-1j,ij-1]
+	newCells->InsertNextCell(3);
+	newCells->InsertCellPoint(this->conn[i][j]);
+	newCells->InsertCellPoint(this->conn[i-1][j]);
+	newCells->InsertCellPoint(this->conn[i][j-1]);
+      }  
+    
+  }
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjIcosahedronSource::Execute()
+{
+  int i, j;
+  int numPts, numPolys;
+  vtkPoints *newPoints; 
+  vtkUnsignedCharArray *newScalars;
+  vtkCellArray *newPolys, *oldPolys;
+  vtkPolyData *output = this->GetOutput();
+  vtkPointData *outPD = output->GetPointData();
+
+  // Set things up; allocate memory
+  //
+  vtkDebugMacro("vtkmpjIcosahedronSource Executing");
+  
+  // allocate space for connectivity information
+  this->conn = new vtkIdType*[this->Depth+1];
+  for (int i=0;i<this->Depth+1;i++)
+    this->conn[i] = new vtkIdType[this->Depth+1-i];
+
+  newPolys = vtkCellArray::New();
+  newPoints = vtkPoints::New();
+
+  // create scalars
+  newScalars = vtkUnsignedCharArray::New();
+  newScalars->SetNumberOfComponents(4);
+  
+  // create intial polyhedron
+  this->InitializePolys(newPoints, newPolys, newScalars);
+  
+  oldPolys = newPolys;
+  numPolys = oldPolys->GetNumberOfCells();
+  numPts = newPoints->GetNumberOfPoints();
+  
+  newPolys = vtkCellArray::New();
+  
+  // subdivide polygons
+  this->SubdividePolys(newPoints, oldPolys, newPolys, newScalars);
+  
+  oldPolys->Delete();
+  
+  numPolys = newPolys->GetNumberOfCells();
+  numPts = newPoints->GetNumberOfPoints();
+  
+  //  printf("level=%d, points=%d, cells=%d\n",this->Depth,numPts,numPolys);  
+  
+  // Update ourselves and release memeory
+  newPoints->Squeeze();
+  output->SetPoints(newPoints);
+  newPoints->Delete();
+
+  newPolys->Squeeze();
+
+  output->SetPolys(newPolys);
+  newPolys->Delete();
+
+  outPD->SetScalars(newScalars);
+  newScalars->Delete();
+
+  // deleting connectivity information
+  for (int i=0;i<this->Depth+1;i++)
+    delete[] this->conn[i];
+  
+  delete[] this->conn;
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjIcosahedronSource::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+  
+  os << indent << "Depth: " << this->Depth << "\n";
+  os << indent << "AllowDuplicatePoints: " << this->AllowDuplicatePoints << "\n";
+
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjIcosahedronSource.h b/bioimagesuite30_src/mpjCommon/vtkmpjIcosahedronSource.h
new file mode 100644
index 0000000..939e8be
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjIcosahedronSource.h
@@ -0,0 +1,94 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// 
+// Creates an icosahedron of an arbitrary depth (frequency).
+// With depth=1, it will have 20 faces and 12 vertices.
+// 
+
+#ifndef __vtkmpjIcosahedronSource_h
+#define __vtkmpjIcosahedronSource_h
+
+#include "vtkPolyDataSource.h"
+#include "vtkPoints.h"
+#include "vtkCellArray.h"
+#include "vtkUnsignedCharArray.h"
+#include "vtkFloatArray.h"
+
+#define VTK_MPJ_MAX_DEPTH 100
+
+class vtkmpjIcosahedronSource : public vtkPolyDataSource 
+{
+public:
+  vtkTypeMacro(vtkmpjIcosahedronSource,vtkPolyDataSource);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Construct an icosahedron of depth=1
+  static vtkmpjIcosahedronSource *New();
+
+  // Description:
+  // Set the depth of the sphere subdivision
+  vtkSetClampMacro(Depth,int,1,VTK_MPJ_MAX_DEPTH);
+  vtkGetMacro(Depth,int);
+
+  // Description:
+  // Set whether the list of points should contain duplicates
+  vtkSetClampMacro(AllowDuplicatePoints,int,0,1);
+  vtkBooleanMacro(AllowDuplicatePoints,int);
+  vtkGetMacro(AllowDuplicatePoints,int);
+
+protected:
+  vtkmpjIcosahedronSource();
+  ~vtkmpjIcosahedronSource() {}
+
+  void Execute();
+  
+  int Depth;
+  int AllowDuplicatePoints;
+  
+  void InitializePolys(vtkPoints *pts, vtkCellArray *polys, vtkUnsignedCharArray *scalars);
+  void SubdividePolys(vtkPoints *newPoints, vtkCellArray *oldCells, vtkCellArray *newCells, vtkUnsignedCharArray *newScalars);
+  void FindOrInsert1Point(vtkPoints *newPoints, vtkUnsignedCharArray *newScalars, float a[3], vtkIdType &ra);
+  void FindOrInsert3Points(vtkPoints *newPoints, vtkUnsignedCharArray *newScalars, float a[3], float b[3], float c[3], vtkIdType &ra, vtkIdType &rb, vtkIdType &rc);
+  
+ private:    
+  
+  vtkIdType **conn;
+  
+  vtkmpjIcosahedronSource(const vtkmpjIcosahedronSource&);  // Not implemented.
+  void operator=(const vtkmpjIcosahedronSource&);  // Not implemented.
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageBoundary.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjImageBoundary.cpp
new file mode 100644
index 0000000..c0fd619
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageBoundary.cpp
@@ -0,0 +1,175 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageBoundary.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageBoundary* vtkmpjImageBoundary::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageBoundary");
+  if(ret)
+    {
+      return (vtkmpjImageBoundary*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageBoundary;
+}
+
+// Construct object with no children.
+vtkmpjImageBoundary::vtkmpjImageBoundary()
+{
+  this->Mask = NULL;
+  this->BoundaryOutValue = 200;
+  this->MaskOutValue = 100;
+  this->BoundaryPoints = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageBoundary::~vtkmpjImageBoundary()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageBoundary::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  int dim[3];  input->GetDimensions(dim);
+  //int nc=input->GetNumberOfScalarComponents();
+  
+  output->SetNumberOfScalarComponents(1);
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageBoundary::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+ 
+  int dim[3];  input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  //int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  if (this->BoundaryPoints) 
+    this->BoundaryPoints->SetNumberOfComponents(3);
+
+  int index=0;
+  float value, neighbor[6];
+  
+  for (int k=0;k<dim[2];k++) 
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{		    
+	  value = in->GetComponent(index, 0);
+	  float coord[3] = {i, j, k};
+	  
+	  // check if it is a boundary point
+	  if (value > 0.0) {
+	    
+	    if (k > 0)
+	      neighbor[0] = in->GetComponent(dim0Tdim1*(k-1) + dim[0]*j + i, 0);
+	    else neighbor[0] = 0.0;	    
+	    if (k < dim[2]-1)
+	      neighbor[1] = in->GetComponent(dim0Tdim1*(k+1) + dim[0]*j + i, 0);	    
+	    else neighbor[1] = 0.0;
+	    
+	    if (j > 0) 
+	      neighbor[2] = in->GetComponent(dim0Tdim1*k + dim[0]*(j-1) + i, 0);
+	    else neighbor[2] = 0.0;	    
+	    if (j < dim[1]-1)
+	      neighbor[3] = in->GetComponent(dim0Tdim1*k + dim[0]*(j+1) + i, 0);	    
+	    else neighbor[3] = 0.0;
+	    
+	    if (i > 0) 
+	      neighbor[4] = in->GetComponent(dim0Tdim1*k + dim[0]*j + i-1, 0);
+	    else neighbor[4] = 0.0;
+	    if (i < dim[0]-1)
+	      neighbor[5] = in->GetComponent(dim0Tdim1*k + dim[0]*j + i+1, 0);
+	    else neighbor[5] = 0.0;
+	    
+	    int num_neighbors=0;
+	    for(int r=0;r<6;r++) {
+	      num_neighbors += ( neighbor[r]>0 );
+	    }
+	    
+	    switch(num_neighbors) 
+	      {
+	      case 0: out->SetComponent(index, 0, 0.0);
+		break;
+	      case 6: out->SetComponent(index, 0, this->MaskOutValue);
+		break;
+	      default:
+		out->SetComponent(index, 0, this->BoundaryOutValue);
+		this->BoundaryPoints != NULL ? this->BoundaryPoints->InsertNextTuple(coord) : 0;
+	      };
+	  }
+	  
+	  ++index;	  
+	  
+	  float pog=float(k)/float(dim[2]);
+	  this->UpdateProgress(pog);	
+	  
+	}
+  
+  this->UpdateProgress(1.0);
+  
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageBoundary.h b/bioimagesuite30_src/mpjCommon/vtkmpjImageBoundary.h
new file mode 100644
index 0000000..a98a333
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageBoundary.h
@@ -0,0 +1,92 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjImageBoundary.h 
+   
+      Marcel Jackowski, Feb. 2004.
+
+*/
+
+#ifndef __vtkmpjImageBoundary_h
+#define __vtkmpjImageBoundary_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjImageBoundary : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageBoundary *New();
+  vtkTypeMacro(vtkmpjImageBoundary,vtkpxSimpleImageToImageFilter);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents for invariants
+  // computation. If a mask is not provided, invariants are
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+  
+  // Description:
+  // Set/Get the value for boundary results
+  vtkSetMacro(BoundaryOutValue,float);
+  vtkGetMacro(BoundaryOutValue,float);
+
+  // Description:
+  // Set/Get the value for boundary results
+  vtkSetMacro(MaskOutValue,float);
+  vtkGetMacro(MaskOutValue,float);
+
+  // Description:
+  // Set/Get Array of boundary positions
+  vtkSetObjectMacro(BoundaryPoints,vtkFloatArray);
+  vtkGetObjectMacro(BoundaryPoints,vtkFloatArray);
+  
+ protected:
+  float BoundaryOutValue; 
+  float MaskOutValue;
+  vtkFloatArray *BoundaryPoints;
+  vtkImageData *Mask;
+  
+  vtkmpjImageBoundary();
+  virtual ~vtkmpjImageBoundary();
+  
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+  
+ private:
+  vtkmpjImageBoundary(const vtkmpjImageBoundary&); // Not implemented
+  void operator=(const vtkmpjImageBoundary&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageHessian.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjImageHessian.cpp
new file mode 100644
index 0000000..f0032b6
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageHessian.cpp
@@ -0,0 +1,184 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkmpjImageHessian.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkImageGaussianSmooth.h"
+#include "vtkImageGradient.h"
+#include "vtkImageExtractComponents.h"
+//#include "vtkpxAppendComponents.h"
+#include "vtkImageShiftScale.h"
+#include "vtkImageMathematics.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageHessian* vtkmpjImageHessian::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageHessian");
+  if(ret)
+    {
+      return (vtkmpjImageHessian*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageHessian;
+}
+
+// Construct object with no children.
+vtkmpjImageHessian::vtkmpjImageHessian()
+{
+  this->EnableSmoothing = 0;
+  this->EnableThresholding = 0;
+  this->ThresholdValue = 0.0;
+  this->AppendSigmaImage = 0;
+  this->Sigma=1.0;
+  this->Mask=NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageHessian::~vtkmpjImageHessian()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageHessian::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+  output->SetScalarTypeToFloat();
+  output->SetNumberOfScalarComponents(6 + this->AppendSigmaImage);
+}
+
+void vtkmpjImageHessian::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+  
+  if (input->GetNumberOfScalarComponents()!=1)
+    {
+      vtkErrorMacro(<<"Only Single Component Images are valid inputs\n");
+      return;
+    }
+
+  for (int c=0+this->AppendSigmaImage;c<(6+this->AppendSigmaImage);c++) 
+    {
+      output->GetPointData()->GetScalars()->FillComponent(c,0.0);
+      if (this->AppendSigmaImage) 
+	output->GetPointData()->GetScalars()->FillComponent(0,this->Sigma);
+    }
+  
+  
+  double sp[3]; input->GetSpacing(sp);
+  double sig[3];
+  for (int ia=0;ia<=2;ia++)
+    sig[ia]=this->Sigma*sp[0]/sp[ia];      
+
+  vtkImageGaussianSmooth *sm = NULL;
+
+  if (this->EnableSmoothing) 
+    {
+      printf("Smoothing: sigmas=%f %f %f\n",sig[0],sig[1],sig[2]);
+      sm=vtkImageGaussianSmooth::New();
+      sm->SetInput(input);
+      sm->SetStandardDeviations(sig);
+      sm->SetDimensionality(3);
+      sm->Update();
+    }
+  
+  this->UpdateProgress(0.25);
+
+  vtkImageGradient* gradient=vtkImageGradient::New();
+  if (this->EnableSmoothing) 
+    gradient->SetInput(sm->GetOutput());
+  else
+    gradient->SetInput(input);
+  
+  //gradient->HandleBoundariesOff();
+  gradient->SetDimensionality(3);
+  gradient->Update();
+  
+  this->UpdateProgress(0.5);
+  
+  vtkImageData* grad=gradient->GetOutput();
+  int dim[3]; grad->GetDimensions(dim);
+
+  // gcomp -- component of gradient
+  // gdiff -- direction of second derivative
+
+  int outcomp=0;
+  double d, val;
+
+  double sp2[3];
+  for (int ia=0;ia<=2;ia++)
+    sp2[ia]=sp[ia]*2.0;
+
+  for (int gcomp=0;gcomp<=2;gcomp++)
+    for (int gdiff=gcomp;gdiff<=2;gdiff++)
+      {
+	for (int i=1;i<dim[0]-1;i++)
+	  for (int j=1;j<dim[1]-1;j++)
+	    for (int k=1;k<dim[2]-1;k++)
+	      {
+		d=0.0;
+		val = input->GetScalarComponentAsDouble(i,j,k,0);
+		if ((this->EnableThresholding) && (val < this->ThresholdValue)) 
+		  continue;
+		if ( ((this->Mask != NULL)?(this->Mask->GetScalarComponentAsDouble(i,j,k, 0) > 0) : 1) < 1)
+		  continue;
+		switch (gdiff)
+		  {
+		  case 0:
+		    d=(grad->GetScalarComponentAsDouble(i+1,j,k,gcomp)-grad->GetScalarComponentAsDouble(i-1,j,k,gcomp))/(sp2[0]);
+		    break;
+		  case 1:
+		    d=(grad->GetScalarComponentAsDouble(i,j+1,k,gcomp)-grad->GetScalarComponentAsDouble(i,j-1,k,gcomp))/(sp2[1]);
+		    break;
+		  case 2:
+		    d=(grad->GetScalarComponentAsDouble(i,j,k+1,gcomp)-grad->GetScalarComponentAsDouble(i,j,k-1,gcomp))/(sp2[2]);
+		    break;
+		  }
+		output->SetScalarComponentFromDouble(i,j,k,outcomp+this->AppendSigmaImage,d*this->Sigma*this->Sigma);
+	      }
+	++outcomp;
+	this->UpdateProgress(0.5+0.1*double(outcomp));
+      }
+
+  gradient->Delete();
+  if (this->EnableSmoothing) 
+    sm->Delete();
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageHessian.h b/bioimagesuite30_src/mpjCommon/vtkmpjImageHessian.h
new file mode 100644
index 0000000..302e699
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageHessian.h
@@ -0,0 +1,100 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+/* Computes the Hessian image */
+
+#ifndef __vtkmpjImageHessian_h
+#define __vtkmpjImageHessian_h
+
+#include "vtkImageData.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+
+class vtkmpjImageHessian : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkmpjImageHessian *New();
+  vtkTypeMacro(vtkmpjImageHessian,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set Scale Sigma
+  vtkGetMacro(Sigma,float);
+  vtkSetMacro(Sigma,float);
+
+  // Description:
+  // Sets/Gets mask where hessian is to be computed
+  vtkGetObjectMacro(Mask, vtkImageData);
+  vtkSetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Set/Get Enable Gaussian Smoothing
+  vtkGetMacro(EnableSmoothing, int);
+  vtkSetMacro(EnableSmoothing, int);
+  vtkBooleanMacro(EnableSmoothing, int);
+
+  // Description:
+  // Set/Get Enable Thresholding
+  vtkGetMacro(EnableThresholding, int);
+  vtkSetMacro(EnableThresholding, int);
+  vtkBooleanMacro(EnableThresholding, int);
+
+  // Description:
+  // Set Scale Sigma
+  vtkGetMacro(ThresholdValue,float);
+  vtkSetMacro(ThresholdValue,float);
+
+  // Description:
+  // Set/Get Append Sigma
+  vtkGetMacro(AppendSigmaImage, int);
+  vtkSetMacro(AppendSigmaImage, int);
+  vtkBooleanMacro(AppendSigmaImage, int);
+
+protected:
+
+  //BTX
+  vtkmpjImageHessian();
+  virtual ~vtkmpjImageHessian();
+  vtkmpjImageHessian(const vtkmpjImageHessian&) {};
+  void operator=(const vtkmpjImageHessian&) {};
+  //ETX
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual void ExecuteInformation();
+
+  vtkImageData *Mask;
+
+  float Sigma;
+  float ThresholdValue;
+  int EnableSmoothing;
+  int EnableThresholding;
+  int AppendSigmaImage;
+
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageInterleaving.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjImageInterleaving.cpp
new file mode 100644
index 0000000..7933abd
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageInterleaving.cpp
@@ -0,0 +1,158 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkmpjImageInterleaving.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+
+//------------------------------------------------------------------------------
+vtkmpjImageInterleaving* vtkmpjImageInterleaving::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageInterleaving");
+  if(ret)
+    {
+    return (vtkmpjImageInterleaving*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageInterleaving;
+}
+
+// Construct object with no children.
+vtkmpjImageInterleaving::vtkmpjImageInterleaving()
+{
+  this->Interleaving = VTK_MPJ_FRAMEINTERLEAVE;
+  this->NumberOfFrames = 1;
+}
+// ----------------------------------------------------------------------------
+vtkmpjImageInterleaving::~vtkmpjImageInterleaving()
+{
+}
+// ----------------------------------------------------------------------------
+
+void vtkmpjImageInterleaving::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+
+  if (input==NULL)
+    {
+	vtkErrorMacro(<<"No Input Specified!!");
+	return;
+      }
+
+  vtkImageData *output=this->GetOutput();
+  vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+
+  if (this->Interleaving == VTK_MPJ_SLICEINTERLEAVE ) {    
+    output->SetNumberOfScalarComponents(1);
+    output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]*nc-1);
+  } else {    
+    output->SetNumberOfScalarComponents(this->NumberOfFrames);
+    output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]/this->NumberOfFrames-1);
+  }
+    
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageInterleaving::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+
+  if (input==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+  
+
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+
+  output->CopyStructure(input);
+  
+  //  if (this->Interleaving == VTK_MPJ_SLICEINTERLEAVE ) {    
+  // output->SetNumberOfScalarComponents(this->NumberOfFrames);
+  // output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]nc-1);
+  // output->SetDimensions(dim[0],dim[1],dim[2]*nc);
+  //} else {    
+  output->SetNumberOfScalarComponents(this->NumberOfFrames);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]/this->NumberOfFrames-1);
+  output->SetDimensions(dim[0],dim[1],dim[2]/this->NumberOfFrames);
+  //}
+  
+  output->AllocateScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  
+  if (this->Interleaving == VTK_MPJ_SLICEINTERLEAVE) {
+    // VTK_MPJ_SLICEINTERLEAVE    
+    
+    for (int k=0;k<dim[2];k++) {
+      int offset = k*dim[0]*dim[1];
+      int noffset = (k / this->NumberOfFrames)*dim[0]*dim[1];
+      int index = 0;
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {		    
+	    out->SetComponent(noffset+index, k % this->NumberOfFrames, 
+			      in->GetComponent(offset+index,0));
+	    ++index;
+	  }
+    }
+    
+  } else {
+    
+    int count = 0;
+    int size = dim[0]*dim[1]*(dim[2] / this->NumberOfFrames);    
+    for (int k=0;k<dim[2];k++) { 
+      for (int j=0;j<dim[1];j++)
+	for (int i=0;i<dim[0];i++)
+	  {
+	    out->SetComponent(count % size,count / size,in->GetComponent(count,0));
+	    count++;
+	  }
+    }
+    
+    // VTK_MPJ_FRAMEINTERLEAVE
+  }
+  
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageInterleaving.h b/bioimagesuite30_src/mpjCommon/vtkmpjImageInterleaving.h
new file mode 100644
index 0000000..8e3c9a8
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageInterleaving.h
@@ -0,0 +1,79 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkmpjImageInterleaving_h
+#define __vtkmpjImageInterleaving_h
+
+// Input Interleaving options
+#define VTK_MPJ_FRAMEINTERLEAVE 0
+#define VTK_MPJ_SLICEINTERLEAVE 1
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjImageInterleaving : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkmpjImageInterleaving *New();
+  vtkTypeMacro(vtkmpjImageInterleaving,vtkpxSimpleImageToImageFilter);
+
+  // Set number of frames in case of frame interleaving
+  vtkSetMacro(NumberOfFrames, int);
+  vtkGetMacro(NumberOfFrames, int);
+
+  // Set input interleaving type:
+  //
+  // FRAME: XXXXYYYYZZZZ ... 
+  // SLICE: XYZXYZXYZXYZ ..
+  void SetFrameInterleave() {this->Interleaving = VTK_MPJ_FRAMEINTERLEAVE;}
+  void SetSliceInterleave() {this->Interleaving = VTK_MPJ_SLICEINTERLEAVE;}
+
+protected:
+
+  vtkmpjImageInterleaving();
+  virtual ~vtkmpjImageInterleaving();
+  vtkmpjImageInterleaving(const vtkmpjImageInterleaving&) {};
+  void operator=(const vtkmpjImageInterleaving&) {};
+
+  int Interleaving;
+  int NumberOfFrames;
+
+  virtual void SimpleExecute(vtkImageData* in,vtkImageData* out);
+  virtual void ExecuteInformation();
+
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImagePointSource.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjImagePointSource.cpp
new file mode 100644
index 0000000..afe35e0
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImagePointSource.cpp
@@ -0,0 +1,193 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjImagePointSource.h"
+
+#include "vtkCellArray.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkTransform.h"
+
+vtkStandardNewMacro(vtkmpjImagePointSource);
+
+vtkmpjImagePointSource::vtkmpjImagePointSource()
+{
+  this->Density = 1.0;
+
+  this->Center[0] = 0.0;
+  this->Center[1] = 0.0;
+  this->Center[2] = 0.0;
+
+  this->Size[0] = 3;
+  this->Size[1] = 3;
+  this->Size[2] = 3;
+
+  this->Origin[0] = 0.0;
+  this->Origin[1] = 0.0;
+  this->Origin[2] = 0.0;
+
+  this->Spacing[0] = 1.0;
+  this->Spacing[1] = 1.0;
+  this->Spacing[2] = 1.0;
+
+  this->Mask = NULL;
+}
+
+vtkmpjImagePointSource::~vtkmpjImagePointSource()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+}
+
+void vtkmpjImagePointSource::Execute()
+{
+  double x1, y1, z1;
+  double x[3];
+  int i, j, k;
+  vtkPoints *newPoints; 
+  vtkPolyData *output = this->GetOutput();
+  newPoints = vtkPoints::New();
+  vtkDataArray *mask = NULL;
+
+  double incx = (double)this->Spacing[0] / (double)this->Density;
+  double incy = (double)this->Spacing[1] / (double)this->Density;
+  double incz = (double)this->Spacing[2] / (double)this->Density;
+
+  //printf("incx=%lf, incy=%lf, incz=%lf\n",incx,incy,incz);
+
+  double xmin, ymin, zmin;
+  double xmax, ymax, zmax;
+  int pos, count = 0;
+
+  // determine bounding box of mask
+  if (this->Mask != NULL) {
+    
+    int dim[3];
+    this->Mask->GetDimensions(dim);
+    mask = this->Mask->GetPointData()->GetScalars();
+    
+    //printf("dim=%d,dim=%d,dim=%d\n",dim[0],dim[1],dim[2]);
+
+    xmin = dim[0]-1;
+    ymin = dim[1]-1;
+    zmin = dim[2]-1;
+    xmax = 0;
+    ymax = 0;
+    zmax = 0;
+    
+    double val;
+    int index = 0;
+    
+    for(k=0; k<dim[2]; k++) 
+      for(j=0; j<dim[1]; j++)
+	for(i=0; i<dim[0]; i++) {
+	  	  
+	  val = mask->GetComponent(index, 0);
+	  
+	  if (val > 0) {	   
+	    if (i < xmin) xmin = i;
+	    if (j < ymin) ymin = j;
+	    if (k < zmin) zmin = k;	    
+	    if (i > xmax) xmax = i;
+	    if (j > ymax) ymax = j;
+	    if (k > zmax) zmax = k;
+	    //printf("%d %d %d = %f, min=%f,%f,%f max=%f,%f,%f\n",i,j,k,val,xmin,ymin,zmin,xmax,ymax,zmax);
+	  }
+	  
+	  ++index;
+	}
+    
+    //printf("min=%f,%f,%f, max=%f,%f,%f\n",xmin,ymin,zmin,xmax,ymax,zmax);
+
+    // convert into point coords
+    xmin = this->Origin[0] + this->Spacing[0]*xmin;
+    ymin = this->Origin[1] + this->Spacing[1]*ymin;
+    zmin = this->Origin[2] + this->Spacing[2]*zmin;    
+    xmax = this->Origin[0] + this->Spacing[0]*xmax;
+    ymax = this->Origin[1] + this->Spacing[1]*ymax;
+    zmax = this->Origin[2] + this->Spacing[2]*zmax;
+ 
+    //printf("min=%f,%f,%f, max=%f,%f,%f\n",xmin,ymin,zmin,xmax,ymax,zmax);
+
+  } else {
+
+    xmin = this->Center[0] - ((this->Size[0]-1)/2.0)*this->Spacing[0];
+    ymin = this->Center[1] - ((this->Size[1]-1)/2.0)*this->Spacing[1];
+    zmin = this->Center[2] - ((this->Size[2]-1)/2.0)*this->Spacing[2];
+    xmax = xmin + (this->Size[0]-1)*this->Spacing[0];
+    ymax = ymin + (this->Size[1]-1)*this->Spacing[1];
+    zmax = zmin + (this->Size[2]-1)*this->Spacing[2];
+  }
+  
+	for(x1 = xmin; x1 <= xmax; x1 += incx) 
+	for(y1 = ymin; y1 <= ymax; y1 += incy)
+	for(z1 = zmin; z1 <= zmax; z1 += incz) {
+	
+	x[0] = x1; 
+	x[1] = y1;
+	x[2] = z1;
+        //printf("%lf %lf %lf\n",x[0],x[1],x[2]);	
+	if (this->Mask) {
+	  pos = this->Mask->FindPoint(x);
+	  if (pos >= 0) {
+	    if ((mask->GetComponent(pos, 0) > 0)) {
+	      newPoints->InsertNextPoint(x);
+	      count++;
+	    }
+	  }
+	} else {
+	  newPoints->InsertNextPoint(x);
+	  count++;
+	}
+
+	//	if ((this->Mask ? this->Mask->FindPoint(x)) : 1) >= 0) {
+	//newPoints->InsertNextPoint(x);
+	//count++;
+	//}
+     }
+  
+  //  printf("total of seed points=%d\n",count);
+
+  // Update ourselves and release memory
+  output->SetPoints(newPoints);
+  newPoints->Delete();
+  
+}
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImagePointSource.h b/bioimagesuite30_src/mpjCommon/vtkmpjImagePointSource.h
new file mode 100644
index 0000000..51114b7
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImagePointSource.h
@@ -0,0 +1,96 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjImagePointSource_h
+#define __vtkmpjImagePointSource_h
+
+#include "vtkPolyDataSource.h"
+#include "vtkImageData.h"
+
+class vtkmpjImagePointSource : public vtkPolyDataSource 
+{
+public:
+  vtkTypeMacro(vtkmpjImagePointSource,vtkPolyDataSource);
+
+  // Description:
+  // Construct volume with resolution 1x1x1, width
+  // height and depth 1.0, and centered at the origin.
+  static vtkmpjImagePointSource *New();
+
+  vtkSetVector3Macro(Size,float);
+  vtkGetVectorMacro(Size,float,3);
+
+  // Description: Set/Get the density of points
+  vtkSetMacro(Density,float);
+  vtkGetMacro(Density,float);
+
+  // Description:
+  // Specify a point defining the origin of the volume
+  vtkSetVector3Macro(Center,float);
+  vtkGetVectorMacro(Center,float,3);
+
+  // Description:
+  // Specify the origin of the coord system
+  vtkSetVector3Macro(Origin,float);
+  vtkGetVectorMacro(Origin,float,3);
+
+  // Description:
+  // Specify the spacing between points
+  vtkSetVector3Macro(Spacing,float);
+  vtkGetVectorMacro(Spacing,float,3);
+
+  // Description:
+  // Set/Get Mask of points
+  vtkSetObjectMacro(Mask,vtkImageData);
+  vtkGetObjectMacro(Mask,vtkImageData);
+
+protected:
+  vtkmpjImagePointSource();
+  ~vtkmpjImagePointSource();
+
+  void Execute();
+
+  vtkImageData *Mask;
+  float Density;
+  float Center[3];
+  float Origin[3];
+  float Spacing[3];
+  float Size[3];
+
+private:
+  vtkmpjImagePointSource(const vtkmpjImagePointSource&);  // Not implemented.
+  void operator=(const vtkmpjImagePointSource&);  // Not implemented.
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageSignalToNoiseRatio.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjImageSignalToNoiseRatio.cpp
new file mode 100644
index 0000000..3581f26
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageSignalToNoiseRatio.cpp
@@ -0,0 +1,163 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageSignalToNoiseRatio.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageSignalToNoiseRatio* vtkmpjImageSignalToNoiseRatio::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageSignalToNoiseRatio");
+  if(ret)
+    {
+    return (vtkmpjImageSignalToNoiseRatio*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageSignalToNoiseRatio;
+}
+
+// Construct object with no children.
+vtkmpjImageSignalToNoiseRatio::vtkmpjImageSignalToNoiseRatio()
+{
+  this->SNR = 0.0;
+  this->SignalCount = 0;
+  this->SignalSum = 0.0;
+  this->NoiseCount = 0;
+  this->NoiseSum = 0.0;
+  this->Mask = NULL;
+  this->RatioType = VTK_MPJ_SNR_MEAN;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageSignalToNoiseRatio::~vtkmpjImageSignalToNoiseRatio()
+{ 
+  if (this->Mask != NULL)
+    this->Mask->Delete();  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageSignalToNoiseRatio::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  int numscalars=in->GetNumberOfTuples();
+  
+  vtkDataArray *mask=NULL;
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  // Progress computation
+  int count = 0;
+  float pog = 0.0;
+  int tenth= (int)(numscalars / 10.0);
+  
+  int count_signal = 0;
+  int count_noise = 0;  
+  double sum_signal = 0.0;
+  double sum_noise = 0.0;
+  double sum_sqr_signal = 0.0;
+  double sum_sqr_noise = 0.0;
+  
+  this->UpdateProgress(0.01);
+  
+  for (int n=0;n<numscalars;n++)      
+    {      
+      int inmask = (int)((mask != NULL)?(mask->GetComponent(n, 0) > 0):0);
+      
+      double value = (double)in->GetComponent(n, 0);
+
+      if (inmask) {	
+	sum_signal += value;
+	sum_sqr_signal += value * value;
+	count_signal++;	
+	out->SetComponent(n, 0, value);
+      } else {	
+	sum_noise += value;
+	sum_sqr_noise += value * value;
+	count_noise++;
+	out->SetComponent(n, 0, 0);
+      }
+      
+      count++;
+      if (count==tenth)
+	{
+	  pog+=0.1;
+	  this->UpdateProgress(pog);
+	  count=0;
+	}
+    }
+
+  this->SignalSum = sum_signal;
+  this->SignalCount = count_signal;
+  this->NoiseSum = sum_noise;
+  this->NoiseCount = count_noise;
+
+  double mean_signal = sum_signal / (double)count_signal;
+  double mean_noise = sum_noise / (double)count_noise;
+
+  double signal_var = (sum_sqr_signal - (((double)count_signal)*mean_signal*mean_signal))/((double)count_signal-1);
+  double noise_var = (sum_sqr_noise - (((double)count_noise)*mean_noise*mean_noise))/((double)count_noise-1);
+  
+  switch(this->RatioType) {
+  case VTK_MPJ_SNR_MEANVAR:
+    if (count_noise > 0 && count_signal > 0) {
+      this->SNR = mean_signal / sqrt(noise_var);
+    }
+    break;
+  case VTK_MPJ_SNR_VARIANCE:
+    if (count_noise > 0 && count_signal > 0) {
+      this->SNR = sqrt(signal_var) / sqrt(noise_var);
+    }
+    break;
+  case VTK_MPJ_SNR_MEAN:
+  default:
+    if (mean_noise != 0) {
+      this->SNR = mean_signal / mean_noise;
+    };
+  };
+  
+  this->SignalVariance = signal_var;
+  this->NoiseVariance = noise_var;
+
+  this->UpdateProgress(1.0);
+}
+
+void vtkmpjImageSignalToNoiseRatio::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkpxSimpleImageToImageFilter::PrintSelf(os,indent);
+
+  os << indent << "SNR: " << this->SNR << "\n";
+  
+}
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageSignalToNoiseRatio.h b/bioimagesuite30_src/mpjCommon/vtkmpjImageSignalToNoiseRatio.h
new file mode 100644
index 0000000..e535ce2
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageSignalToNoiseRatio.h
@@ -0,0 +1,107 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkmpjImageSignalToNoiseRatio_h
+#define __vtkmpjImageSignalToNoiseRatio_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+// Options
+#define VTK_MPJ_SNR_MEAN      0     
+#define VTK_MPJ_SNR_VARIANCE  1
+#define VTK_MPJ_SNR_MEANVAR   2
+
+class vtkmpjImageSignalToNoiseRatio : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageSignalToNoiseRatio *New();
+  vtkTypeMacro(vtkmpjImageSignalToNoiseRatio,vtkpxSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description: 
+  // Sets/Gets mask for computing statistics.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+  
+  // Description:
+  // Get SNR between mask and background.
+  vtkGetMacro(SignalSum, float);
+  vtkGetMacro(SignalCount, int);
+  vtkGetMacro(SignalVariance, float);
+  
+  vtkGetMacro(NoiseSum, float);
+  vtkGetMacro(NoiseCount, int);
+  vtkGetMacro(NoiseVariance, float);
+    
+  // Description:
+  // Set/Get the type of SNR ratio to be calculated
+  vtkSetMacro(RatioType,int);
+  vtkGetMacro(RatioType,int);
+
+  // Description: set ratio type
+  void SetRatioTypeToMeanRatio() {this->SetRatioType(VTK_MPJ_SNR_MEAN);};  // M(S)/M(N)
+  void SetRatioTypeToVarianceRatio() {this->SetRatioType(VTK_MPJ_SNR_VARIANCE);}; // sqrt(V(S))/sqrt(V(N))
+  void SetRatioTypeToMeanAndVarianceRatio() {this->SetRatioType(VTK_MPJ_SNR_MEANVAR);}; // M(S)/sqrt(V(N))
+  void SetRatioTypeToDefault() {this->SetRatioType(VTK_MPJ_SNR_MEAN);};
+  
+  // Description:
+  // Get resulting SNR
+  vtkGetMacro(SNR, float);
+
+ protected:
+  vtkImageData *Mask;
+  float SNR;
+  float NoiseSum;
+  float NoiseVariance;
+  float SignalSum;
+  float SignalVariance;
+  int SignalCount;
+  int NoiseCount;
+  int RatioType;
+
+  vtkmpjImageSignalToNoiseRatio();
+  virtual ~vtkmpjImageSignalToNoiseRatio();
+  
+  virtual void SimpleExecute(vtkImageData* in, vtkImageData* out);
+  //  virtual void ExecuteInformation();
+
+ private:
+  vtkmpjImageSignalToNoiseRatio(const vtkmpjImageSignalToNoiseRatio&); // Not implemented
+  void operator=(const vtkmpjImageSignalToNoiseRatio&); // Not implemented
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageStatistics.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjImageStatistics.cpp
new file mode 100644
index 0000000..ae2b26b
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageStatistics.cpp
@@ -0,0 +1,187 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageStatistics.h"
+#include "pxisinf.h"
+
+
+//------------------------------------------------------------------------------
+vtkmpjImageStatistics* vtkmpjImageStatistics::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageStatistics");
+  if(ret)
+    {
+    return (vtkmpjImageStatistics*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageStatistics;
+}
+
+// Construct object with no children.
+vtkmpjImageStatistics::vtkmpjImageStatistics()
+{
+  this->NumberOfRegions = 1;
+  this->RegionMax = NULL;
+  this->RegionMin = NULL;
+  this->RegionMean = NULL;
+  this->RegionVariance = NULL;
+  this->RegionVoxelCount = NULL;
+  this->Min = this->Max = this->Mean = this->Variance = 0.0;
+  this->VoxelCount = 0;
+  this->Mask = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageStatistics::~vtkmpjImageStatistics()
+{ 
+  if (this->Mask != NULL)
+    this->Mask->Delete();  
+  if (this->RegionMax != NULL)
+    delete[] this->RegionMax;
+  if (this->RegionMin != NULL)
+    delete[] this->RegionMin;
+  if (this->RegionMean != NULL)
+    delete[] this->RegionMean;
+  if (this->RegionVariance != NULL)
+    delete[] this->RegionVariance;
+  if (this->RegionVoxelCount != NULL)
+    delete[] this->RegionVoxelCount;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageStatistics::SimpleExecute(vtkImageData* input, vtkImageData* output)
+{
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  int numscalars=in->GetNumberOfTuples();
+   
+  vtkDataArray *mask=NULL;
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  // make sure number of regions is at least 1
+  if (this->NumberOfRegions <= 0)
+    this->NumberOfRegions = 1;
+  
+  // reset statistics
+  this->RegionSum = new double[this->NumberOfRegions];
+  this->RegionSumSqr = new double[this->NumberOfRegions];
+  this->RegionMax = new double[this->NumberOfRegions];
+  this->RegionMin = new double[this->NumberOfRegions];
+  this->RegionMean = new double[this->NumberOfRegions];
+  this->RegionVariance = new double[this->NumberOfRegions];
+  this->RegionVoxelCount = new long[this->NumberOfRegions];
+
+  for(int j=0; j<this->NumberOfRegions; j++) {
+    this->RegionSum[j] = 0.0;
+    this->RegionSumSqr[j] = 0.0;
+    this->RegionMax[j] = VTK_DOUBLE_MIN;
+    this->RegionMin[j] = VTK_DOUBLE_MAX;
+    this->RegionMean[j] = 0.0;
+    this->RegionVariance[j] = 0.0;
+    this->RegionVoxelCount[j] = 0;
+  }
+  
+  // Progress computation
+  int count = 0;
+  float pog = 0.0;
+  int tenth= (int)(numscalars / 10.0);
+    
+  this->UpdateProgress(0.01);
+  
+  for (int n=0;n<numscalars;n++)      
+    {      
+      int index = (int)((mask != NULL)?(mask->GetComponent(n, 0)):0);
+      index--;
+
+      if (index >= 0 && index < this->NumberOfRegions) {
+	
+	double value = (double)in->GetComponent(n, 0);
+	
+	if (!isnan(value)) {
+	  
+	  this->RegionSum[index] += value;
+	  this->RegionSumSqr[index] += value*value;
+	  
+	  if (value > this->RegionMax[index]) {
+	    this->RegionMax[index] = value;
+	  } else if (value < this->RegionMin[index]) {
+	    this->RegionMin[index] = value;
+	  }
+	  
+	  this->RegionVoxelCount[index]++;
+	}
+      }
+      
+      count++;
+      if (count==tenth)
+	{
+	  pog+=0.1;
+	  this->UpdateProgress(pog);
+	  count=0;
+	}
+    }
+  
+  
+  // compute statistics
+  for(int j=0; j<this->NumberOfRegions; j++) {
+    
+    if (this->RegionVoxelCount[j]) {
+      this->RegionMean[j]=this->RegionSum[j] / (double)this->RegionVoxelCount[j];
+      this->RegionVariance[j]=(this->RegionSumSqr[j] - ((double)this->RegionVoxelCount[j] * this->RegionMean[j] * this->RegionMean[j]))  / (double)(this->RegionVoxelCount[j]-1);
+    } else {
+      this->RegionMean[j] = this->RegionVariance[j] = 0.0;
+    }
+  }
+  
+  this->Min = this->RegionMin[0];
+  this->Max = this->RegionMax[0];
+  this->Mean = this->RegionMean[0];
+  this->Variance = this->RegionVariance[0];
+  this->VoxelCount = this->RegionVoxelCount[0];
+
+  this->UpdateProgress(1.0);
+}
+
+void vtkmpjImageStatistics::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkpxSimpleImageToImageFilter::PrintSelf(os,indent);
+
+  os << indent << "Mean: " << this->Mean << "\n";
+  os << indent << "Minimum: " << this->Min << "\n";
+  os << indent << "Maximum: " << this->Max << "\n";
+  os << indent << "Variance: " << this->Variance << "\n";
+  os << indent << "VoxelCount: " << this->VoxelCount << "\n";
+  
+}
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageStatistics.h b/bioimagesuite30_src/mpjCommon/vtkmpjImageStatistics.h
new file mode 100644
index 0000000..be7f905
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageStatistics.h
@@ -0,0 +1,108 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkmpjImageStatistics_h
+#define __vtkmpjImageStatistics_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkFloatArray.h"
+#include "vtkPointData.h"
+
+class vtkmpjImageStatistics : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageStatistics *New();
+  vtkTypeMacro(vtkmpjImageStatistics,vtkpxSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Get single-region statistics information for the data
+  vtkGetMacro(Min, double);
+  vtkGetMacro(Max, double);
+  vtkGetMacro(Mean, double);
+  vtkGetMacro(Variance, double);
+  vtkGetMacro(VoxelCount, long int);
+  
+  // Description::
+  // Get/Set Number of regions in the mask
+  vtkGetMacro(NumberOfRegions,int);
+  vtkSetMacro(NumberOfRegions,int);
+  
+  // Description: 
+  // Sets/Gets mask for computing statistics.
+  // If a mask is not provided, tensor is
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+  
+  // Gets region statistics
+  double GetRegionMax(int index) { return this->RegionMax[index]; }
+  double GetRegionMin(int index) { return this->RegionMin[index]; }
+  double GetRegionMean(int index) { return this->RegionMean[index]; }
+  double GetRegionVariance(int index) { return this->RegionVariance[index]; }
+  long GetRegionVoxelCount(int index) { return this->RegionVoxelCount[index]; }
+
+ protected:
+  int NumberOfRegions;  
+  vtkFloatArray *RegionValues;
+  vtkImageData *Mask;
+
+  double *RegionMax;
+  double *RegionMin;
+  double *RegionMean;
+  double *RegionVariance;
+  double *RegionSum;
+  double *RegionSumSqr;
+  long *RegionVoxelCount;
+
+  double Min;
+  double Max;
+  double Mean;
+  double Variance;
+  long int VoxelCount;
+  
+  vtkmpjImageStatistics();
+  virtual ~vtkmpjImageStatistics();
+  
+  virtual void SimpleExecute(vtkImageData* in, vtkImageData* out);
+  //  virtual void ExecuteInformation();
+
+ private:
+  vtkmpjImageStatistics(const vtkmpjImageStatistics&); // Not implemented
+  void operator=(const vtkmpjImageStatistics&); // Not implemented
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageT2Relax.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjImageT2Relax.cpp
new file mode 100644
index 0000000..5583c27
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageT2Relax.cpp
@@ -0,0 +1,206 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkmpjImageT2Relax.h"
+
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+//------------------------------------------------------------------------------
+vtkmpjImageT2Relax* vtkmpjImageT2Relax::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageT2Relax");
+  if(ret)
+    {
+    return (vtkmpjImageT2Relax*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageT2Relax;
+}
+
+// Construct object with no children.
+vtkmpjImageT2Relax::vtkmpjImageT2Relax()
+{
+  this->EchoTime1=0.0;
+  this->EchoTime2=0.0;
+  this->ThresholdValue=0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageT2Relax::~vtkmpjImageT2Relax()
+{
+}
+//----------------------------------------------------------------------------
+void vtkmpjImageT2Relax::SetInput1(vtkImageData *input)
+{
+  this->vtkProcessObject::SetNthInput(0, input);
+}
+//----------------------------------------------------------------------------
+void vtkmpjImageT2Relax::SetInput2(vtkImageData *input)
+{
+  this->vtkProcessObject::SetNthInput(1, input);
+}
+//----------------------------------------------------------------------------
+vtkImageData *vtkmpjImageT2Relax::GetInput1()
+{ 
+  return (vtkImageData*)(this->Inputs[0]);
+}
+//----------------------------------------------------------------------------
+vtkImageData *vtkmpjImageT2Relax::GetInput2()
+{
+  return (vtkImageData*)(this->Inputs[1]);
+}
+// ----------------------------------------------------------------------------
+void vtkmpjImageT2Relax::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput1();
+
+  if (input==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+
+  vtkImageData *output=this->GetOutput();
+
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+ 
+  int wholeExtent[6];
+  input->GetWholeExtent( wholeExtent );
+  output->SetWholeExtent( wholeExtent );
+  output->SetNumberOfScalarComponents(1);
+}
+
+// ----------------------------------------------------------------------------
+
+void vtkmpjImageT2Relax::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{  
+  if (this->GetInput1()!=NULL) {        
+    
+    int nc = this->GetInput1()->GetNumberOfScalarComponents();    
+    if (nc == 1) {      
+      
+      // In case the number of components is one, we need a second input
+      if (this->GetInput2()!=NULL) {    
+	
+	int dim_0[3]; int dim_1[3];
+	this->GetInput1()->GetDimensions(dim_0);
+	this->GetInput2()->GetDimensions(dim_1);
+	
+	int sum=0;
+	for (int kk=0;kk<=2;kk++)
+	  sum+=abs(dim_1[kk]-dim_0[kk]);
+	if (sum!=0)
+	  {
+	    vtkErrorMacro(<<"Multiple Images have different Dimensions !!");
+	    return;
+	  } 
+      	
+      } else {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+    }
+      
+  } else {
+    vtkErrorMacro(<<"No Input Image Data !!");
+    return;
+  }
+  
+  // Create Output Array
+  // -------------------
+  int nc = this->GetInput1()->GetNumberOfScalarComponents();
+  int dim[3];  this->GetInput1()->GetDimensions(dim);
+  
+  //vtkImageData* output=this->GetOutput();
+  output->SetSpacing(this->GetInput1()->GetSpacing());
+  output->SetOrigin(this->GetInput1()->GetOrigin());
+  output->SetScalarType(VTK_FLOAT);
+  output->SetNumberOfScalarComponents(1);
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  output->AllocateScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  int numscalars=out->GetNumberOfTuples();
+
+  this->UpdateProgress(0.01);
+  float pog=0.00;
+
+  float tenth=numscalars/10.0;
+  int count=0;
+
+  int count1=0; // number of voxels processed
+  int count2=0; // number of voxels where PD == T2
+  
+  for (int n=0;n<numscalars;n++)
+    {
+      float outv = 0.0;
+      float v1, v2;
+      
+      v1=this->GetInput1()->GetPointData()->GetScalars()->GetComponent(n,0);
+      v2=(nc==1)?this->GetInput2()->GetPointData()->GetScalars()->GetComponent(n,0):
+	this->GetInput1()->GetPointData()->GetScalars()->GetComponent(n,1);
+      
+      if (MIN(v1,v2) >= this->ThresholdValue) {
+	
+	if (v1 != v2) 	
+	  outv = fabs(this->EchoTime1-this->EchoTime2) / fabs(log(v1 / v2));
+	else {
+	  count2++;
+	  outv = 5000.0;	  
+	}
+
+	count1++;
+      }
+      
+      out->SetComponent(n,0,outv);
+      
+      count++;
+      if (count==tenth)
+	{
+	  pog+=0.1;
+	  this->UpdateProgress(pog);
+	  count=0;
+	}
+    }
+
+  fprintf(stdout,"A total of %d image voxels (%4.2f%%) were processed,\n",
+	  count1,(float)count1/numscalars*100);
+  fprintf(stdout,"where %d voxels (%4.2f%%) had IPDW equal to IT2W.\n",
+	  count2,(float)count2/count1*100);
+  
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageT2Relax.h b/bioimagesuite30_src/mpjCommon/vtkmpjImageT2Relax.h
new file mode 100644
index 0000000..fce4d39
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageT2Relax.h
@@ -0,0 +1,88 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkmpjImageT2Relax_h
+#define __vtkmpjImageT2Relax_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+
+class vtkmpjImageT2Relax : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkmpjImageT2Relax *New();
+  vtkTypeMacro(vtkmpjImageT2Relax,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set subset of frames to extract
+  vtkSetMacro(EchoTime1, float);
+  vtkGetMacro(EchoTime1, float);
+  vtkSetMacro(EchoTime2, float);
+  vtkGetMacro(EchoTime2, float);
+
+// Threshold value for retaining high-intensity pixels.
+  vtkSetMacro(ThresholdValue, int);
+  vtkGetMacro(ThresholdValue, int);
+
+  // Multiple Input Stuff
+  // --------------------
+  // Description:
+  // Set an Input of this filter. 
+  virtual void SetInput1(vtkImageData *input);
+  virtual void SetInput2(vtkImageData *input);
+  
+  // Description:
+  // Get one input to this filter.
+  vtkImageData *GetInput1();
+  vtkImageData *GetInput2();
+
+protected:
+
+  vtkmpjImageT2Relax();
+  virtual ~vtkmpjImageT2Relax();
+  vtkmpjImageT2Relax(const vtkmpjImageT2Relax&) {};
+  void operator=(const vtkmpjImageT2Relax&) {};
+
+  float EchoTime1;
+  float EchoTime2;
+
+  int ThresholdValue;
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageTwoNorm.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjImageTwoNorm.cpp
new file mode 100644
index 0000000..8f805e8
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageTwoNorm.cpp
@@ -0,0 +1,183 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkpxStructuredPointsToStructuredPointsFilter.h"
+#include "vtkmpjImageTwoNorm.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageTwoNorm* vtkmpjImageTwoNorm::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageTwoNorm");
+  if(ret)
+    {
+    return (vtkmpjImageTwoNorm*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageTwoNorm;
+}
+
+// Construct object with no children.
+vtkmpjImageTwoNorm::vtkmpjImageTwoNorm()
+{
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageTwoNorm::~vtkmpjImageTwoNorm()
+{
+}
+//----------------------------------------------------------------------------
+void vtkmpjImageTwoNorm::SetInput1(vtkStructuredPoints *input)
+{
+  this->vtkProcessObject::SetNthInput(0, input);
+}
+//----------------------------------------------------------------------------
+void vtkmpjImageTwoNorm::SetInput2(vtkStructuredPoints *input)
+{
+  this->vtkProcessObject::SetNthInput(1, input);
+}
+//----------------------------------------------------------------------------
+vtkStructuredPoints *vtkmpjImageTwoNorm::GetInput1()
+{ 
+  return (vtkStructuredPoints*)(this->Inputs[0]);
+}
+//----------------------------------------------------------------------------
+vtkStructuredPoints *vtkmpjImageTwoNorm::GetInput2()
+{
+  return (vtkStructuredPoints*)(this->Inputs[1]);
+}
+// ----------------------------------------------------------------------------
+void vtkmpjImageTwoNorm::ExecuteInformation()
+{
+  vtkStructuredPoints *input=this->GetInput1();
+
+  if (input==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+
+  vtkStructuredPoints *output=this->GetOutput();
+
+  this->vtkpxStructuredPointsToStructuredPointsFilter::ExecuteInformation();
+ 
+  int wholeExtent[6];
+  input->GetWholeExtent( wholeExtent );
+  output->SetWholeExtent( wholeExtent );
+  output->SetNumberOfScalarComponents(1);
+}
+
+// ----------------------------------------------------------------------------
+
+void vtkmpjImageTwoNorm::Execute()
+{  
+  if (this->GetInput1()!=NULL && this->GetInput2()!=NULL) {        
+    
+    int nc1 = this->GetInput1()->GetNumberOfScalarComponents();    
+    int nc2 = this->GetInput2()->GetNumberOfScalarComponents();
+
+    if (nc1 != nc2) {
+      vtkErrorMacro(<<"Multiple Images have different number of components !!");
+      return;
+    }
+
+    int dim_0[3]; int dim_1[3];
+    this->GetInput1()->GetDimensions(dim_0);
+    this->GetInput2()->GetDimensions(dim_1);
+	
+    int sum=0;
+    for (int kk=0;kk<=2;kk++)
+      sum+=abs(dim_1[kk]-dim_0[kk]);
+    if (sum!=0)
+      {
+	vtkErrorMacro(<<"Multiple Images have different Dimensions !!");
+	return;
+      } 
+    
+  } else {
+    vtkErrorMacro(<<"Two images are required as input!!");
+    return;
+  }
+  
+  // Create Output Array
+  // -------------------
+  int nc = this->GetInput1()->GetNumberOfScalarComponents();
+  int dim[3];  this->GetInput1()->GetDimensions(dim);
+  
+  vtkStructuredPoints* output=this->GetOutput();
+  output->SetSpacing(this->GetInput1()->GetSpacing());
+  output->SetOrigin(this->GetInput1()->GetOrigin());
+  output->SetScalarType(VTK_FLOAT);
+  output->SetNumberOfScalarComponents(1);
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  output->AllocateScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  int numscalars=out->GetNumberOfTuples();
+
+  this->UpdateProgress(0.01);
+  float pog=0.00;
+
+  float tenth=numscalars/10.0;
+  int count=0;
+
+  for (int n=0;n<numscalars;n++)
+    {
+      float v1, v2, vout;
+      float sum2=0.0;      
+      
+      for (int i=0;i<nc;i++) {
+	v1=this->GetInput1()->GetPointData()->GetScalars()->GetComponent(n,i);
+	v2=this->GetInput2()->GetPointData()->GetScalars()->GetComponent(n,i);	
+	vout = (v1-v2)*(v1-v2);
+	sum2 += vout;
+      }
+      
+      vout = sqrt(sum2);
+      
+      out->SetComponent(n,0,vout);
+      
+      count++;
+      if (count==tenth)
+	{
+	  pog+=0.1;
+	  this->UpdateProgress(pog);
+	  count=0;
+	}
+    }
+  
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageTwoNorm.h b/bioimagesuite30_src/mpjCommon/vtkmpjImageTwoNorm.h
new file mode 100644
index 0000000..9c2696b
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageTwoNorm.h
@@ -0,0 +1,72 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkmpjImageTwoNorm_h
+#define __vtkmpjImageTwoNorm_h
+
+#include "vtkpxStructuredPointsToStructuredPointsFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjImageTwoNorm : public vtkpxStructuredPointsToStructuredPointsFilter
+{
+public:
+  static vtkmpjImageTwoNorm *New();
+  vtkTypeMacro(vtkmpjImageTwoNorm,vtkpxStructuredPointsToStructuredPointsFilter);
+
+  // Multiple Input Stuff
+  // --------------------
+  // Description:
+  // Set an Input of this filter. 
+  virtual void SetInput1(vtkStructuredPoints *input);
+  virtual void SetInput2(vtkStructuredPoints *input);
+  
+  // Description:
+  // Get one input to this filter.
+  vtkStructuredPoints *GetInput1();
+  vtkStructuredPoints *GetInput2();
+
+protected:
+
+  vtkmpjImageTwoNorm();
+  virtual ~vtkmpjImageTwoNorm();
+  vtkmpjImageTwoNorm(const vtkmpjImageTwoNorm&) {};
+  void operator=(const vtkmpjImageTwoNorm&) {};
+
+  void Execute();
+  void ExecuteInformation();
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageVesselEnhancement.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjImageVesselEnhancement.cpp
new file mode 100644
index 0000000..e1a7c0a
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageVesselEnhancement.cpp
@@ -0,0 +1,354 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#include "vtkObjectFactory.h"
+#include "vtkSource.h"
+#include "vtkmpjImageVesselEnhancement.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkMath.h"
+#include "vtkpxMath.h"
+#include "vtkmpjImageHessian.h"
+//#include "nrutil.h"
+#include "math.h"
+#include "pxisinf.h"
+//------------------------------------------------------------------------------
+vtkmpjImageVesselEnhancement* vtkmpjImageVesselEnhancement::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageVesselEnhancement");
+  if(ret)
+    {
+    return (vtkmpjImageVesselEnhancement*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageVesselEnhancement;
+}
+
+// Construct object with no children.
+vtkmpjImageVesselEnhancement::vtkmpjImageVesselEnhancement()
+{
+  this->Alpha=0.5;
+  this->Beta=0.5;
+  this->Gamma=0.25;
+  this->VesselnessScaleFactor=1.0;
+  this->Sigma=1.0;
+  this->Mask = NULL;
+  this->BrightStructure=1;
+  this->StructureType=0;
+
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageVesselEnhancement::~vtkmpjImageVesselEnhancement()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageVesselEnhancement::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  vtkImageData *output=this->GetOutput();
+  output->SetScalarTypeToFloat();
+  if (this->StructureType==3)
+    output->SetNumberOfScalarComponents(6);
+  else if (this->StructureType==4)
+    output->SetNumberOfScalarComponents(3);
+  else
+    output->SetNumberOfScalarComponents(1);
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjImageVesselEnhancement::ComputeVesselLikelihood(float lambda[3],int bright,double a2,double b2,double c2)
+{
+  if (lambda[1]>0.0 || lambda[2]>0.0)
+    return 0.0;
+
+  double RA= fabs(lambda[1]/lambda[2]);
+  double RB= fabs(lambda[0]/sqrt(fabs(lambda[1]*lambda[2])));
+  double S= sqrt(lambda[0]*lambda[0]+lambda[1]*lambda[1]+lambda[2]*lambda[2]);
+  
+  double V1=(1.0-exp(RA*RA*a2));
+  double V2=exp(RB*RB*b2);
+  double V3=(1.0-exp(S*S*c2));
+  double V=V1*V2*V3;
+  return V;
+}
+// --------------------------------------------------------------------------------------------
+
+double vtkmpjImageVesselEnhancement::ComputePlateLikelihood(float lambda[3],int bright,double a2,double b2,double c2)
+{
+  double V=exp(-lambda[2]/lambda[1]);
+  if (V<0.0)
+    return 0.0;
+  if (V>40.0)
+    return 40.0;
+  return V;
+}
+
+// --------------------------------------------------------------------------------------------
+double vtkmpjImageVesselEnhancement::ComputeBlobLikelihood(float lambda[3],int bright,double a2,double b2,double c2)
+{
+
+  double v1=(lambda[0]+lambda[1]+lambda[2]);
+  double m1=(lambda[0]/lambda[1]-1.0);
+  double m2=(lambda[0]/lambda[2]-1.0);
+  double m3=(lambda[1]/lambda[2]-1.0);
+
+  double v=exp(-m2*m2/b2)*exp(-m3*m3/b2)*exp(-m1*m1/b2)*v1;
+  return (lambda[0]/lambda[1])*(lambda[0]/lambda[2])*(lambda[1]/lambda[2]);
+}
+
+// --------------------------------------------------------------------------------------------
+void vtkmpjImageVesselEnhancement::SimpleExecute(vtkImageData* input,vtkImageData* output)
+{
+  if (input==NULL)
+      {
+	vtkErrorMacro(<<"No Input Image Data !!");
+	return;
+      }
+
+  int nimpc=input->GetNumberOfScalarComponents();
+
+  if (nimpc!=1 && nimpc!=6)
+    {
+      vtkErrorMacro(<<"Either One or Six Component Images are valid inputs (i.e. Hessians)\n ****** \n\n\n\n\n\n");
+      return;
+    }
+
+  vtkImageData* hessian=vtkImageData::New();
+  if (nimpc==6)
+    {
+      hessian->ShallowCopy(input);
+    }
+  else
+    {
+      vtkmpjImageHessian* hes=vtkmpjImageHessian::New();
+      hes->SetInput(input);
+      hes->SetSigma(this->Sigma);
+      hes->Update();
+      hessian->ShallowCopy(hes->GetOutput());
+      hes->Delete();
+    }
+
+  this->UpdateProgress(0.5);
+
+  vtkDataArray* data=hessian->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  float A[3][3],lambda[3],W[3][3];
+
+  int nc=out->GetNumberOfComponents();
+  for (int i=0;i<nc;i++)
+    out->FillComponent(i,0.0);
+
+  int np=data->GetNumberOfTuples();
+
+  //  fprintf(stderr,"Beginning Alpha=%.2f, Beta=%.2f Gamma=%.2f\n",Alpha,Beta,Gamma);
+
+  double a2=-1.0/(this->Alpha*this->Alpha*2.0);
+  double b2=-1.0/(this->Beta*this->Beta*2.0);
+  double c2=-1.0/(this->Gamma*this->Gamma*2.0);
+
+  vtkDataArray *mask=NULL;
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  int count=0;
+  int tenth=np/10;
+  for (int i=0;i<np;i++)
+    {
+      if (!((mask != NULL)?(mask->GetComponent(i, 0) > 0):1))
+	continue;
+      
+      A[0][0]=data->GetComponent(i,0);
+      A[0][1]=data->GetComponent(i,1);
+      A[1][0]=A[0][1];
+
+      A[0][2]=data->GetComponent(i,2);
+      A[2][0]=A[0][2];
+
+      A[1][1]=data->GetComponent(i,3);
+      A[1][2]=data->GetComponent(i,4);
+      A[2][1]=A[1][2];
+      
+      A[2][2]=data->GetComponent(i,5);
+      
+      vtkMath::Diagonalize3x3(A,lambda,W);
+
+      for (int ia=0;ia<=1;ia++)
+	{
+	  double min=fabs(lambda[ia]);
+	  int best=ia;
+	  for (int ib=ia+1;ib<=2;ib++)
+	    {
+	      if (fabs(lambda[ib]) < min )
+		{
+		  min=fabs(lambda[ib]);
+		  best=ib;
+		}
+	    }
+	  if (best!=ia)
+	    {
+	      double tmp=lambda[ia];
+	      lambda[ia]=lambda[best];
+	      lambda[best]=tmp;
+	    }
+	}
+
+      double V=0.0,V3=0.0,V2=0.0;
+      int offset=-1;
+
+      if (!isinf(lambda[0]) && !isinf(lambda[1]) && !isinf(lambda[2]))
+	{
+	  switch (this->StructureType)
+	    {
+	    case 0:
+	      V=this->ComputeVesselLikelihood(lambda,this->BrightStructure,a2,b2,c2)*this->VesselnessScaleFactor;
+	      break;
+	    case 1:
+	      V=this->ComputePlateLikelihood(lambda,this->BrightStructure,a2,b2,c2);
+	      break;
+	    case 2:
+	      V=this->ComputeBlobLikelihood(lambda,this->BrightStructure,a2,b2,c2);
+	      break;
+	    case 3:
+	      V=this->ComputeVesselLikelihood(lambda,this->BrightStructure,a2,b2,c2)*this->VesselnessScaleFactor;
+	      V2=this->ComputePlateLikelihood(lambda,this->BrightStructure,a2,b2,c2);
+	      V3=this->ComputeBlobLikelihood(lambda,this->BrightStructure,a2,b2,c2);
+	      offset=3;
+	      break;
+	    case 4:
+	      offset=0;
+	    }
+	  
+
+	  if (!isinf(V))
+	    out->SetComponent(i,0,V);
+
+	  if (this->StructureType==3)
+	    {
+	      offset=3;
+	      if (!isinf(V2))
+		out->SetComponent(i,1,V2);
+	      if (!isinf(V3))
+		out->SetComponent(i,2,V3);
+	    }
+
+	  if (offset>-1)
+	    {
+	      out->SetComponent(i,offset,lambda[0]);
+	      out->SetComponent(i,offset+1,lambda[1]);
+	      out->SetComponent(i,offset+2,lambda[2]);
+	    }
+	}
+      
+      ++count;
+      if (count==tenth)
+	{
+	  this->UpdateProgress(this->GetProgress()+0.05);
+	  count=0;
+	}
+    }
+  
+  hessian->Delete();
+}
+
+// -----------------------------------------------------------------------------------------------------------
+
+int vtkmpjImageVesselEnhancement::UpdateHessianResponse(vtkImageData* hessian1,vtkImageData* vessel1,vtkImageData* sigma1,
+							vtkImageData* hessian2,vtkImageData* vessel2,double newsigma)
+{
+
+  if (hessian1==NULL || vessel1==NULL || sigma1==NULL || hessian2 == NULL || vessel2==NULL)
+    {
+      fprintf(stderr,"Bad Inputs to Update Hessian Response (NULL)\n");
+      return 0;
+    }
+
+  vtkDataArray* array[3][2];
+  array[0][0]=hessian1->GetPointData()->GetScalars();
+  array[1][0]=vessel1->GetPointData()->GetScalars();
+  array[2][0]=sigma1->GetPointData()->GetScalars();
+
+  array[0][1]=hessian2->GetPointData()->GetScalars();
+  array[1][1]=vessel2->GetPointData()->GetScalars();
+
+
+  int numvoxels=array[0][0]->GetNumberOfTuples();
+
+  int flag=0;
+  int nc[3];
+  for (int ia=0;ia<=2;ia++)
+    {
+      int nt1=array[ia][0]->GetNumberOfTuples();
+      int nc1=array[ia][0]->GetNumberOfComponents();
+
+      int nt2=nt1,nc2=1;
+      if (ia!=2)
+	{
+	  nt2=array[ia][1]->GetNumberOfTuples();
+	  nc2=array[ia][1]->GetNumberOfComponents();
+	}
+
+      //      fprintf(stderr,"Checking row=%d   set1=%d x %d  set2=%d x %d\n",ia,nt1,nc1,nt2,nc2);
+
+      if (nt1!=nt2 || nt1!=numvoxels || nc1!=nc2)
+	{
+	  flag=1;
+	  ia=4;
+	}
+      nc[ia]=nc1;
+    }
+
+  if (flag==1)
+    {
+      fprintf(stderr,"Bad Inputs (Dimensions) to Update Hessian Response\n");
+      return 0;
+    }
+
+  for (int voxel=0;voxel<numvoxels;voxel++)
+    {
+      double v1=array[1][0]->GetComponent(voxel,0);
+      double v2=array[1][1]->GetComponent(voxel,0);
+      if (v2>v1)
+	{
+	  for (int row=0;row<=1;row++)
+	    for (int ia=0;ia<nc[row];ia++)
+	      array[row][0]->SetComponent(voxel,ia,array[row][1]->GetComponent(voxel,ia));
+	  array[2][0]->SetComponent(voxel,0,newsigma);
+	}
+    }
+
+  for (int ia=0;ia<=2;ia++)
+    array[ia][0]->Modified();
+
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageVesselEnhancement.h b/bioimagesuite30_src/mpjCommon/vtkmpjImageVesselEnhancement.h
new file mode 100644
index 0000000..adc8662
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageVesselEnhancement.h
@@ -0,0 +1,154 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*=========================================================================
+
+  Program:   vtkpxcontrib library file
+  Module:    $RCSfile: vtkmpjImageVesselEnhancement.h,v $
+  Language:  C++
+  Date:      $Date: 2002/09/26 18:08:12 $
+  Version:   $Revision: 1.1 $
+
+
+Copyright (c) 1995-2001 Xenios Papademetris papad at noodle.med.yale.edu
+All rights reserved.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+
+=========================================================================*/
+// .NAME vtkmpjImageVesselEnhancement -- combines images to form either mean or median
+// .SECTION Description
+// <br> <br> <EM>Copyright (c) 1995-2001 Xenios Papademetris <a href="mailto:papad at noodle.med.yale.edu">papad at noodle.med.yale.edu</a></EM>
+// Implements Vessel Enhancement Filter from Frangi Niessen Hoogeveen and Viergever TMI October 1999
+
+#ifndef __vtkmpjImageVesselEnhancement_h
+#define __vtkmpjImageVesselEnhancement_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkFloatArray.h"
+
+class vtkmpjImageVesselEnhancement : public vtkpxSimpleImageToImageFilter
+{
+public:
+  static vtkmpjImageVesselEnhancement *New();
+  vtkTypeMacro(vtkmpjImageVesselEnhancement,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set Parameters Alpha, Beta and Gamma
+  vtkGetMacro(Alpha,double);
+  vtkSetClampMacro(Alpha,double,0.05,10.0);
+
+  vtkGetMacro(Beta,double);
+  vtkSetClampMacro(Beta,double,0.05,10.0);
+
+  vtkGetMacro(Gamma,double);
+  vtkSetMacro(Gamma,double);
+
+  // Description:
+  // Set Vessneless Scale Factor
+  vtkGetMacro(VesselnessScaleFactor,double);
+  vtkSetClampMacro(VesselnessScaleFactor,double,1.0,1000.0);
+  
+
+  // Description:
+  // Set Smoothing Sigma for Hessian Computation
+  vtkGetMacro(Sigma,double);
+  vtkSetMacro(Sigma,double);
+
+  // Description:
+  // Bright Structure
+  vtkSetClampMacro(BrightStructure,int,0,2);
+  vtkGetMacro(BrightStructure,int);
+  virtual void SetBrightStructureToDark()   { this->SetBrightStructure(0); }
+  virtual void SetBrightStructureToBright() { this->SetBrightStructure(1); }
+  virtual void SetBrightStructureToBoth()   { this->SetBrightStructure(2); }
+
+  // Description: 
+  // Sets/Gets mask for computing statistics.
+  // If a mask is not provided, tensor is
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+  
+  // Description:
+  // Bright Structure
+  vtkSetClampMacro(StructureType,int,0,4);
+  vtkGetMacro(StructureType,int);
+  virtual void SetStructureTypeToTubular() { this->SetStructureType(0); }
+  virtual void SetStructureTypeToPlate()   { this->SetStructureType(1); }
+  virtual void SetStructureTypeToBlob()    { this->SetStructureType(2); }
+  virtual void SetStructureTypeToAll()     { this->SetStructureType(3); }
+  virtual void SetStructureTypeToNone()    { this->SetStructureType(4); }
+
+  // Description:
+  // This a messy function that takes as inputs
+  // Hessian1, Vessel1, Sigma1, Hessian2, Vessel2, Sigma2, and spits out a corrected Set 1 by using the maximum of the vessel number
+  static int UpdateHessianResponse(vtkImageData* hessian1,vtkImageData* vessel1,vtkImageData* sigma,
+				   vtkImageData* hessian2,vtkImageData* vessel2,double newsigma);
+  
+protected:
+
+  //BTX
+  vtkmpjImageVesselEnhancement();
+  virtual ~vtkmpjImageVesselEnhancement();
+  vtkmpjImageVesselEnhancement(const vtkmpjImageVesselEnhancement&) {};
+  void operator=(const vtkmpjImageVesselEnhancement&) {};
+  //ETX
+  virtual void SimpleExecute(vtkImageData* input,vtkImageData* output);
+  virtual void ExecuteInformation();
+
+  // Description:
+  // Workhorse Functions
+  virtual double ComputeVesselLikelihood(float lambda[3],int bright,double a2,double b2,double c2);
+  virtual double ComputePlateLikelihood(float lambda[3],int bright,double a2,double b2,double c2);
+  virtual double ComputeBlobLikelihood(float lambda[3],int bright,double a2,double b2,double c2);
+
+  vtkImageData *Mask;
+
+  double Alpha;
+  double Beta;
+  double Gamma;
+  double Sigma;
+  double VesselnessScaleFactor;
+  int    BrightStructure;
+  int    StructureType;
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageVesselMaximum.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjImageVesselMaximum.cpp
new file mode 100644
index 0000000..5903972
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageVesselMaximum.cpp
@@ -0,0 +1,190 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageVesselMaximum.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageVesselMaximum* vtkmpjImageVesselMaximum::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageVesselMaximum");
+  if(ret)
+    {
+      return (vtkmpjImageVesselMaximum*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageVesselMaximum;
+}
+
+// Construct object with no children.
+vtkmpjImageVesselMaximum::vtkmpjImageVesselMaximum()
+{
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageVesselMaximum::~vtkmpjImageVesselMaximum()
+{
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageVesselMaximum::AddInput(vtkImageData *input)
+{
+  this->vtkProcessObject::AddInput(input);
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjImageVesselMaximum::SetInput(int idx, vtkImageData *input)
+{
+  this->vtkProcessObject::SetNthInput(idx, input);
+}
+
+//----------------------------------------------------------------------------
+vtkImageData *vtkmpjImageVesselMaximum::GetInput()
+{
+  return this->GetInput(0);
+}
+
+//----------------------------------------------------------------------------
+vtkImageData *vtkmpjImageVesselMaximum::GetInput(int idx)
+{
+  if (this->NumberOfInputs <= idx)
+    {
+      return NULL;
+    }
+  
+  return (vtkImageData*)(this->Inputs[idx]);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageVesselMaximum::ExecuteInformation()
+{
+  if (this->NumberOfInputs==0 || this->GetInput(0)==NULL) {
+    vtkErrorMacro(<<"No Input Image Data !!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();  
+}
+
+// ----------------------------------------------------------------------------
+
+void vtkmpjImageVesselMaximum::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim_0[3];
+  this->GetInput(0)->GetDimensions(dim_0);
+
+  for (int i=1;i<this->NumberOfInputs;i++)
+    {
+      if (this->GetInput(i)==NULL)
+	{
+	  vtkErrorMacro(<<"No Input Image Data " << i << " !!");
+	  return;
+	}
+      else
+	{
+	  int dim_1[3];
+	  this->GetInput(i)->GetDimensions(dim_1);
+	  int sum=0;
+	  for (int kk=0;kk<=2;kk++)
+	    sum+=abs(dim_1[kk]-dim_0[kk]);
+	  if (sum!=0)
+	    {
+	      vtkErrorMacro(<<"Images have different Dimensions !!");
+	      return;
+	    }
+	}
+    }
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();  
+
+  int numscalars=out->GetNumberOfTuples();
+  int numcomp=output->GetNumberOfScalarComponents();
+  int nc = this->GetInput(0)->GetNumberOfScalarComponents();
+  
+  int count = 0;
+  float pog = 0.0;
+  int tenth= (int)(numscalars / 10.0);
+  
+  this->UpdateProgress(0.01);
+  
+  vtkDataArray *in0 = this->GetInput(0)->GetPointData()->GetScalars();
+  
+  for(int n=0; n<numscalars; n++) 
+    {
+      double max = in0->GetComponent(n, 0);    
+      int sermax = 0;
+      for(int series=1; series<this->NumberOfInputs; series++) 
+	{            
+	  double v = this->GetInput(series)->GetPointData()->GetScalars()->GetComponent(n, 0);      
+	  
+	  if (v > max) 
+	    {
+	      max=v; 
+	      sermax=series;   
+	    }
+	}
+    
+      // save maximum
+      out->SetComponent(n, 0, max);
+      
+      if ( max > 0 ) 
+	{
+	  // save corresponding sigma
+	  out->SetComponent(n, 1, this->GetInput(sermax)->GetPointData()->GetScalars()->GetComponent(n,1));
+      
+	  // save tensor
+	  for(int i=2; i<8; i++) 
+	    out->SetComponent(n, i, this->GetInput(sermax)->GetPointData()->GetScalars()->GetComponent(n,i));
+	} 
+      else 
+	{
+	  // save sigma
+	  out->SetComponent(n, 1, 0.0);
+	  // save tensor
+	  for(int i=2; i<8; i++) 
+	    out->SetComponent(n, i, 0.0);
+	}
+
+      count++;
+      if (count==tenth)
+	{
+	  pog+=0.1;
+	  this->UpdateProgress(pog);
+	  count=0;
+	}
+    }
+  
+  this->UpdateProgress(1.0);
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjImageVesselMaximum.h b/bioimagesuite30_src/mpjCommon/vtkmpjImageVesselMaximum.h
new file mode 100644
index 0000000..6d8e1ad
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjImageVesselMaximum.h
@@ -0,0 +1,77 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkmpjImageVesselMaximum_h
+#define __vtkmpjImageVesselMaximum_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjImageVesselMaximum : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageVesselMaximum *New();
+  vtkTypeMacro(vtkmpjImageVesselMaximum,vtkpxSimpleImageToImageFilter);
+  
+  // Multiple Input Stuff
+  // --------------------
+  // Description:
+  // Set an Input of this filter. 
+  virtual void SetInput(int num, vtkImageData *input);
+  
+  // Description:
+  // Adds an input to the first null position in the input list.
+  // Expands the list memory if necessary
+  virtual void AddInput(vtkImageData *input);
+  
+  // Description:
+  // Get one input to this filter
+  vtkImageData *GetInput(int num);
+  vtkImageData *GetInput();
+  
+protected:
+  vtkmpjImageVesselMaximum();
+  virtual ~vtkmpjImageVesselMaximum();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  vtkmpjImageVesselMaximum(const vtkmpjImageVesselMaximum&); // Not implemented
+  void operator=(const vtkmpjImageVesselMaximum&); // Not implemented
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjPriorityQueue.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjPriorityQueue.cpp
new file mode 100644
index 0000000..ef01650
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjPriorityQueue.cpp
@@ -0,0 +1,266 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjPriorityQueue.h"
+#include "vtkObjectFactory.h"
+
+//------------------------------------------------------------------------
+vtkmpjPriorityQueue* vtkmpjPriorityQueue::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjPriorityQueue");
+  if(ret)
+    {
+    return (vtkmpjPriorityQueue*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjPriorityQueue;
+}
+
+// Instantiate priority queue with default size and extension size of 1000.
+vtkmpjPriorityQueue::vtkmpjPriorityQueue()
+{
+  this->Size = 0;
+  this->Extend = 1000;
+  this->Array = NULL;
+  this->MaxId = -1;
+  this->ItemLocation = NULL;
+}
+
+// Allocate priority queue with specified size and amount to extend
+// queue (if reallocation required).
+void vtkmpjPriorityQueue::Allocate(const vtkIdType sz, const vtkIdType ext)
+{
+  this->ItemLocation = vtkIdTypeArray::New();
+  this->ItemLocation->Allocate(sz,ext);
+  for (vtkIdType i=0; i < sz; i++)
+    {
+    this->ItemLocation->SetValue(i,-1);
+    }
+
+  this->Size = ( sz > 0 ? sz : 1);
+  if ( this->Array != NULL )
+    {
+    delete [] this->Array;
+    }
+  this->Array = new vtkmpjPriorityItem[sz];
+  this->Extend = ( ext > 0 ? ext : 1);
+  this->MaxId = -1;
+}
+
+// Destructor for the vtkmpjPriorityQueue class
+vtkmpjPriorityQueue::~vtkmpjPriorityQueue()
+{
+  if ( this->ItemLocation )
+    {
+    this->ItemLocation->Delete();
+    }
+  if ( this->Array )
+    {
+    delete [] this->Array;
+    }
+}
+
+// Insert id with priority specified.
+void vtkmpjPriorityQueue::Insert(double priority, vtkIdType id)
+{
+  vtkIdType i, idx;
+  vtkmpjPriorityItem temp;
+
+  // check and make sure item hasn't been inserted before
+  if ( id <= this->ItemLocation->GetMaxId() && 
+       this->ItemLocation->GetValue(id) != -1 )
+    {
+    return;
+    }
+
+  // start by placing new entry at bottom of tree
+  if ( ++this->MaxId >= this->Size )
+    {
+    this->Resize(this->MaxId + 1);
+    }
+  this->Array[this->MaxId].priority = priority;
+  this->Array[this->MaxId].id = id;
+  if ( id >= this->ItemLocation->GetSize() ) //might have to resize and initialize
+    {
+    vtkIdType oldSize = this->ItemLocation->GetSize();
+    this->ItemLocation->InsertValue(id,this->MaxId); 
+    for (i=oldSize; i < this->ItemLocation->GetSize(); i++) 
+      {
+      this->ItemLocation->SetValue(i, -1);
+      }
+    this->ItemLocation->SetValue(id,this->MaxId);
+    }
+
+  this->ItemLocation->InsertValue(id,this->MaxId);
+
+  // now begin percolating towards top of tree
+  for ( i=this->MaxId; 
+  i > 0 && this->Array[i].priority < this->Array[(idx=(i-1)/2)].priority; 
+  i=idx)
+    {
+    temp = this->Array[i];
+
+    this->ItemLocation->SetValue(temp.id,idx);
+    this->Array[i] = this->Array[idx];
+
+    this->ItemLocation->SetValue(this->Array[idx].id,i);
+    this->Array[idx] = temp;
+    }
+}
+
+// Simplified call for easier wrapping for Tcl.
+vtkIdType vtkmpjPriorityQueue::Pop(vtkIdType location)
+{
+  double priority;
+  return this->Pop(priority, location);
+}
+
+// Removes item at specified location from tree; then reorders and
+// balances tree. The location == 0 is the root of the tree.
+vtkIdType vtkmpjPriorityQueue::Pop(double &priority, vtkIdType location)
+{
+  vtkIdType id, i, j, idx;
+  vtkmpjPriorityItem temp;
+
+  if ( this->MaxId < 0 )
+    {
+    return -1;
+    }
+ 
+  id = this->Array[location].id;
+  priority = this->Array[location].priority;
+
+  // move the last item to the location specified and push into the tree
+  this->Array[location].id = this->Array[this->MaxId].id;
+  this->Array[location].priority = this->Array[this->MaxId].priority;
+
+  this->ItemLocation->SetValue(this->Array[location].id,location);
+  this->ItemLocation->SetValue(id,-1);
+
+  if ( --this->MaxId <= 0 )
+    {
+    return id;
+    }
+
+  // percolate into the tree
+  for ( j=0, i=location; i <= (this->MaxId-1)/2; i=j )
+    {
+    idx = 2*i + 1;
+
+    if ( this->Array[idx].priority < this->Array[idx+1].priority || 
+         idx == this->MaxId )
+      {
+      j = idx;
+      }
+    else
+      {
+      j = idx + 1;
+      }
+
+    if ( this->Array[i].priority > this->Array[j].priority )
+      {
+      temp = this->Array[i];
+
+      this->ItemLocation->SetValue(temp.id,j);
+      this->Array[i] = this->Array[j];
+
+      this->ItemLocation->SetValue(this->Array[j].id,i);
+      this->Array[j] = temp;
+      }
+    else
+      {
+      break;
+      }
+    }
+  
+  return id;
+}
+
+// Protected method reallocates queue.
+vtkmpjPriorityItem *vtkmpjPriorityQueue::Resize(const vtkIdType sz)
+{
+  vtkmpjPriorityItem *newArray;
+  vtkIdType newSize;
+
+  if (sz >= this->Size)
+    {
+    newSize = this->Size + sz;
+    }
+  else
+    {
+    newSize = sz;
+    }
+
+  if (newSize <= 0)
+    {
+    newSize = 1;
+    }
+
+  newArray = new vtkmpjPriorityItem[newSize];
+
+  if (this->Array)
+    {
+    memcpy(newArray, this->Array,
+           (sz < this->Size ? sz : this->Size) * sizeof(vtkmpjPriorityItem));
+    delete [] this->Array;
+    }
+
+  this->Size = newSize;
+  this->Array = newArray;
+
+  return this->Array;
+}
+
+// Reset all of the entries in the queue so they don not have a priority
+void vtkmpjPriorityQueue::Reset()
+{
+  this->MaxId = -1;
+  if ( this->ItemLocation != NULL )
+    {
+    for (int i=0; i <= this->ItemLocation->GetMaxId(); i++)
+      {
+      this->ItemLocation->SetValue(i,-1);
+      }
+    this->ItemLocation->Reset();
+    }
+}
+
+void vtkmpjPriorityQueue::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkObject::PrintSelf(os,indent);
+
+  os << indent << "Number Of Entries: " << this->MaxId + 1 << "\n";
+  os << indent << "Size: " << this->Size << "\n";
+  os << indent << "Extend size: " << this->Extend << "\n";
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjPriorityQueue.h b/bioimagesuite30_src/mpjCommon/vtkmpjPriorityQueue.h
new file mode 100644
index 0000000..1bcb6ad
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjPriorityQueue.h
@@ -0,0 +1,194 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// .NAME vtkmpjPriorityQueue - an list of ids arranged in priority order
+// .SECTION Description
+// vtkmpjPriorityQueue is a general object for creating and manipulating lists
+// of object ids (e.g., point or cell ids). Object ids are sorted according
+// to a user-specified priority, where entries at the top of the queue have
+// the smallest values.
+//
+// This implementation provides a feature beyond the usual ability to insert
+// and retrieve (or pop) values from the queue. It is also possible to
+// pop any item in the queue given its id number. This allows you to delete
+// entries in the queue which can useful for reinserting an item into the
+// queue. 
+//
+// .SECTION Caveats
+// This implementation is a variation of the priority queue described in
+// "Data Structures & Algorithms" by Aho, Hopcroft, Ullman. It creates 
+// a balanced, partially ordered binary tree implemented as an ordered
+// array. This avoids the overhead associated with parent/child pointers,
+// and frequent memory allocation and deallocation.
+
+#ifndef __vtkmpjPriorityQueue_h
+#define __vtkmpjPriorityQueue_h
+
+#include "vtkObject.h"
+#include "vtkIdTypeArray.h"
+
+//BTX
+typedef struct _vtkmpjPriorityItem
+  {
+    double priority;
+    vtkIdType id;
+} vtkmpjPriorityItem;
+//ETX
+
+class vtkmpjPriorityQueue : public vtkObject
+{
+public:
+  // Description:
+  // Instantiate priority queue with default size and extension size of 1000.
+  static vtkmpjPriorityQueue *New();
+
+  vtkTypeMacro(vtkmpjPriorityQueue,vtkObject);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Allocate initial space for priority queue.
+  void Allocate(const vtkIdType sz, const vtkIdType ext=1000);
+
+  // Description:
+  // Insert id with priority specified. The id is generally an
+  // index like a point id or cell id.
+  void Insert(double priority, vtkIdType id);
+
+  // Description:
+  // Removes item at specified location from tree; then reorders and
+  // balances tree. The location == 0 is the root of the tree. If queue
+  // is exhausted, then a value < 0 is returned. (Note: the location
+  // is not the same as deleting an id; id is mapped to location.)
+
+  vtkIdType Pop(double &priority, vtkIdType location=0);
+
+  // Description:
+  // Same as above but simplified for easier wrapping into interpreted
+  // languages.
+  vtkIdType Pop(vtkIdType location=0);
+
+  // Description:
+  // Peek into the queue without actually removing anything. Returns the
+  // id and the priority.
+  vtkIdType Peek(double &priority, vtkIdType location=0);
+  
+  // Description:
+  // Peek into the queue without actually removing anything. Returns the
+  // id.
+  vtkIdType Peek(vtkIdType location=0);
+
+  // Description:
+  // Delete entry in queue with specified id. Returns priority value
+  // associated with that id; or VTK_DOUBLE_MAX if not in queue.
+  double DeleteId(vtkIdType id);
+
+  // Description:
+  // Get the priority of an entry in the queue with specified id. Returns
+  // priority value of that id or VTK_DOUBLE_MAX if not in queue.
+  double GetPriority(vtkIdType id);
+
+  // Description:
+  // Return the number of items in this queue.
+  vtkIdType GetNumberOfItems() {return this->MaxId+1;};
+
+  // Description:
+  // Empty the queue but without releasing memory. This avoids the
+  // overhead of memory allocation/deletion.
+  void Reset();
+
+protected:
+  vtkmpjPriorityQueue();
+  ~vtkmpjPriorityQueue();
+  
+  vtkmpjPriorityItem *Resize(const vtkIdType sz);
+
+  vtkIdTypeArray *ItemLocation;
+  vtkmpjPriorityItem *Array;
+  vtkIdType Size;
+  vtkIdType MaxId;
+  vtkIdType Extend;
+private:
+  vtkmpjPriorityQueue(const vtkmpjPriorityQueue&);  // Not implemented.
+  void operator=(const vtkmpjPriorityQueue&);  // Not implemented.
+};
+
+inline double vtkmpjPriorityQueue::DeleteId(vtkIdType id)
+{
+  double priority=VTK_DOUBLE_MAX;
+  int loc;
+
+  if ( id <= this->ItemLocation->GetMaxId() &&  
+  (loc=this->ItemLocation->GetValue(id)) != -1 )
+    {
+    this->Pop(priority,loc);
+    }
+  return priority;
+}
+
+inline double vtkmpjPriorityQueue::GetPriority(vtkIdType id)
+{
+  int loc;
+
+  if ( id <= this->ItemLocation->GetMaxId() &&  
+  (loc=this->ItemLocation->GetValue(id)) != -1 )
+    {
+    return this->Array[loc].priority;
+    }
+  return VTK_DOUBLE_MAX;
+}
+
+inline vtkIdType vtkmpjPriorityQueue::Peek(double &priority, vtkIdType location)
+{
+  if ( this->MaxId < 0 )
+    {
+    return -1;
+    }
+  else
+    {
+    priority = this->Array[location].priority;
+    return this->Array[location].id;
+    }
+}
+
+inline vtkIdType vtkmpjPriorityQueue::Peek(vtkIdType location)
+{
+  if ( this->MaxId < 0 )
+    {
+    return -1;
+    }
+  else
+    {
+    return this->Array[location].id;
+    }
+}
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjScalarsToFieldData.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjScalarsToFieldData.cpp
new file mode 100644
index 0000000..4f7c27a
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjScalarsToFieldData.cpp
@@ -0,0 +1,104 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjScalarsToFieldData.h"
+#include "vtkFloatArray.h"
+
+//------------------------------------------------------------------------------
+vtkmpjScalarsToFieldData* vtkmpjScalarsToFieldData::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjScalarsToFieldData");
+  if(ret)
+    {
+      return (vtkmpjScalarsToFieldData*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjScalarsToFieldData;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjScalarsToFieldData::vtkmpjScalarsToFieldData()
+{
+  this->FieldName = NULL;
+} 
+
+vtkmpjScalarsToFieldData::~vtkmpjScalarsToFieldData()
+{
+} 
+
+// ----------------------------------------------------------------------------
+void vtkmpjScalarsToFieldData::Execute()
+{ 
+  vtkIdType numTuples;
+  vtkIdType numComp;
+
+  vtkDataSet *input=this->GetInput();
+  vtkDataSet *output=this->GetOutput();
+
+  vtkPointData *inPD=input->GetPointData();
+  vtkPointData *outPD=output->GetPointData();
+
+  vtkDataArray *in=inPD->GetScalars();
+  
+  output->CopyStructure(input);
+  //  output->SetNumberOfScalarComponents(input->GetNumberOfScalarComponents());
+  
+  numTuples = in->GetNumberOfTuples();
+  numComp = in->GetNumberOfComponents(); 
+
+  vtkFloatArray *diffusion = vtkFloatArray::New();
+  diffusion->SetName(this->FieldName);
+  diffusion->SetNumberOfComponents(numComp);
+  diffusion->SetNumberOfTuples(numTuples);
+  
+  for(int index=0; index<numTuples; index++) {
+    
+    for(int n=0; n<numComp; n++)
+      diffusion->SetComponent(index, n, in->GetComponent(index, n));
+    
+    float pog=float(index)/float(numTuples);
+    this->UpdateProgress(pog);	
+  }
+  
+  outPD->AddArray(diffusion);
+  diffusion->Delete();
+  
+  outPD->CopyScalarsOff();
+  outPD->PassData(inPD);
+
+  this->UpdateProgress(1.0);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjScalarsToFieldData.h b/bioimagesuite30_src/mpjCommon/vtkmpjScalarsToFieldData.h
new file mode 100644
index 0000000..0180135
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjScalarsToFieldData.h
@@ -0,0 +1,64 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjScalarsToFieldData_h
+#define __vtkmpjScalarsToFieldData_h
+
+#include "vtkDataSetToDataSetFilter.h"
+#include "vtkDataSet.h"
+#include "vtkPointData.h"
+
+class vtkmpjScalarsToFieldData : public vtkDataSetToDataSetFilter
+{
+ public:
+  static vtkmpjScalarsToFieldData *New();
+  vtkTypeMacro(vtkmpjScalarsToFieldData,vtkDataSetToDataSetFilter);
+
+  // Description
+  // Sets/Gets the name of the new field to hold the scalars
+  vtkSetStringMacro(FieldName);
+  vtkGetStringMacro(FieldName);
+
+ protected:  
+  vtkmpjScalarsToFieldData();
+  virtual ~vtkmpjScalarsToFieldData();
+  
+  char *FieldName;
+
+  void Execute();
+  
+ private:
+  vtkmpjScalarsToFieldData(const vtkmpjScalarsToFieldData&); // Not implemented
+  void operator=(const vtkmpjScalarsToFieldData&); // Not implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjSphereSubdivisionSource.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjSphereSubdivisionSource.cpp
new file mode 100644
index 0000000..cb90521
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjSphereSubdivisionSource.cpp
@@ -0,0 +1,371 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjSphereSubdivisionSource.h"
+
+#include "vtkCellArray.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+
+#include <math.h>
+
+#define PPP 0
+#define MMP 1
+#define MPM 2
+#define PMM 3
+
+/* Structure describing a tetrahedron */
+vtkIdType tetra[4][3] = {
+  { PPP, MMP, MPM },
+  { PPP, PMM, MMP },
+  { MPM, MMP, PMM },
+  { PMM, PPP, MPM }};
+
+/* Vertices of a tetrahedron */
+#define sqrt_3 0.5773502692
+
+float tetrahedron[4][3] = {
+  {  sqrt_3,  sqrt_3,  sqrt_3 },  /* +X, +Y, +Z */
+  { -sqrt_3, -sqrt_3,  sqrt_3 },  /* -X, -Y, +Z */
+  { -sqrt_3,  sqrt_3, -sqrt_3 },  /* -X, +Y, -Z */
+  {  sqrt_3, -sqrt_3, -sqrt_3 }}; /* +X, -Y, -Z */
+
+//----------------------------------------------------------------------------
+
+#define XPLUS 0
+#define XMIN  1
+#define YPLUS 2
+#define YMIN  3
+#define ZPLUS 4
+#define ZMIN  5
+
+/* Vertices of a unit octahedron */
+vtkIdType octagon[8][3] = {
+  {XPLUS, ZPLUS, YPLUS},
+  {YPLUS, ZPLUS, XMIN},
+  {XMIN,  ZPLUS, YMIN},
+  {YMIN,  ZPLUS, XPLUS},
+  {XPLUS, YPLUS, ZMIN},
+  {YPLUS, XMIN,  ZMIN},
+  {XMIN,  YMIN,  ZMIN},
+  {YMIN,  XPLUS, ZMIN}};
+
+/* Six equidistant points lying on the unit sphere */
+float octahedron[8][3] = {
+  {+1.0,  0.0,  0.0},  // +x 
+  {-1.0,  0.0,  0.0},  // -x
+  { 0.0, +1.0,  0.0},  // +y
+  { 0.0, -1.0,  0.0},  // -y
+  { 0.0,  0.0, +1.0},  // +z
+  { 0.0,  0.0, -1.0}}; // -z
+
+//----------------------------------------------------------------------------
+
+#define tau 0.8506508084 /* t=(1+sqrt(5))/2, tau=t/sqrt(1+t^2) */ 
+#define one 0.5257311121 /* one=1/sqrt(1+t^2) , unit sphere */
+
+#define ZA  0
+#define ZB  1
+#define ZC  2
+#define ZD  3
+#define YA  4
+#define YB  5
+#define YC  6
+#define YD  7
+#define XA  8
+#define XB  9
+#define XC 10
+#define XD 11
+
+/* Twelve vertices of icosahedron on unit sphere */
+float icosahedron[12][3] = {
+  {  tau,  one, 0.0 },  // ZA
+  { -tau,  one, 0.0 },  // ZB
+  { -tau, -one, 0.0 },  // ZC
+  {  tau, -one, 0.0 },  // ZD
+  {  one, 0.0,  tau },  // YA
+  {  one, 0.0, -tau },  // YB
+  { -one, 0.0, -tau },  // YC
+  { -one, 0.0 , tau },  // YD
+  { 0.0,  tau,  one },  // XA
+  { 0.0, -tau,  one },  // XB
+  { 0.0, -tau, -one },  // XC
+  { 0.0,  tau, -one }}; // XD
+
+/* Structure for unit icosahedron */
+vtkIdType ico[20][3] = {
+  { YA, XA, YD },
+  { YA, YD, XB },
+  { YB, YC, XD }, 
+  { YB, XC, YC }, 
+  { ZA, YA, ZD },
+  { ZA, ZD, YB }, 
+  { ZC, YD, ZB }, 
+  { ZC, ZB, YC }, 
+  { XA, ZA, XD },
+  { XA, XD, ZB },
+  { XB, XC, ZD }, 
+  { XB, ZC, XC },
+  { XA, YA, ZA },
+  { XD, ZA, YB }, 
+  { YA, XB, ZD },
+  { YB, ZD, XC },
+  { YD, XA, ZB }, 
+  { YC, ZB, XD },
+  { YD, ZC, XB },
+  { YC, XC, ZC }};
+
+vtkStandardNewMacro(vtkmpjSphereSubdivisionSource);
+
+//----------------------------------------------------------------------------
+vtkmpjSphereSubdivisionSource::vtkmpjSphereSubdivisionSource()
+{
+  this->Depth = 1;
+  this->DuplicatePoints = 1;
+  this->SubdivisionType = 0;
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjSphereSubdivisionSource::InitializePolys(vtkPoints *pts, vtkCellArray *polys)
+{
+  // Create initial polyhedron
+  switch(this->SubdivisionType) {
+    
+  case OCTAHEDRON:
+    
+    // Create octahedron
+    for (int i=0;i<6;i++) {
+      pts->InsertNextPoint((float *)&octahedron[i]);
+    }
+    
+    // Generate mesh connectivity
+    for (int i=0;i<8;i++)
+      polys->InsertNextCell(3, (vtkIdType *)&octagon[i]);
+    
+    break;
+    
+  case TETRAHEDRON:
+
+    // Create tetrahedron
+    for (int i=0;i<4;i++) {
+      pts->InsertNextPoint((float *)&tetrahedron[i]);
+    }
+    
+    // Generate mesh connectivity
+    for (int i=0;i<4;i++)
+      polys->InsertNextCell(3, (vtkIdType *)&tetra[i]);
+    
+    break;
+    
+  case ICOSAHEDRON:
+    
+    // Create icosahedron
+    for (int i=0;i<12;i++) {
+      pts->InsertNextPoint((float *)&icosahedron[i]);
+    }
+    
+    // Generate mesh connectivity
+    for (int i=0;i<20;i++)
+      polys->InsertNextCell(3, (vtkIdType *)&ico[i]);
+    
+  };
+
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjSphereSubdivisionSource::FindPoints(vtkPoints *pts, double a[3], double b[3], double c[3], vtkIdType &pa, vtkIdType &pb, vtkIdType &pc)
+{
+  int numpts = pts->GetNumberOfPoints();
+  double *x;
+  
+  pa = pb = pc = -1;
+  
+  for (int i=numpts-1; i>=0; i--) {
+    x = pts->GetPoint(i);
+    if ((a[0]==x[0]) && (a[1]==x[1]) && (a[2]==x[2])) pa = i;
+    if ((b[0]==x[0]) && (b[1]==x[1]) && (b[2]==x[2])) pb = i;
+    if ((c[0]==x[0]) && (c[1]==x[1]) && (c[2]==x[2])) pc = i;
+  }
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjSphereSubdivisionSource::SubdividePolys(vtkPoints *newPoints, vtkCellArray *oldCells, vtkCellArray *newCells)
+{
+  vtkIdType numPts, numCells, *pts, pa, pb, pc;
+  double *x0, *x1, *x2;
+  double a[3], b[3], c[3];
+  
+  numPts = newPoints->GetNumberOfPoints();
+  numCells = oldCells->GetNumberOfCells();
+
+  // initiate triangle traversal
+  oldCells->InitTraversal();  
+  
+  // traverse each triangle 
+  while(oldCells->GetNextCell(numPts, pts) != 0) {
+    
+    // fetch cell points
+    x0 = newPoints->GetPoint(pts[0]);
+    x1 = newPoints->GetPoint(pts[1]);
+    x2 = newPoints->GetPoint(pts[2]);
+
+    // compute midpoint coordinates
+    for(int i=0;i<3;i++) {
+      a[i] = (x0[i] + x2[i]) * 0.5;
+      b[i] = (x0[i] + x1[i]) * 0.5;
+      c[i] = (x1[i] + x2[i]) * 0.5;
+    }
+    
+    // normalize coordinates
+    (void)vtkMath::Normalize(a);
+    (void)vtkMath::Normalize(b);
+    (void)vtkMath::Normalize(c);
+
+    // try finding midpoints
+    if (this->DuplicatePoints == 0) {
+
+      this->FindPoints(newPoints, a, b, c, pa, pb, pc);      
+
+      // insert midpoints      
+      if (pa < 0) pa = newPoints->InsertNextPoint(a);
+      if (pb < 0) pb = newPoints->InsertNextPoint(b);
+      if (pc < 0) pc = newPoints->InsertNextPoint(c);
+    } else {
+      pa = newPoints->InsertNextPoint(a);
+      pb = newPoints->InsertNextPoint(b);
+      pc = newPoints->InsertNextPoint(c);
+    }
+
+    // triangle [0,b,a]
+    newCells->InsertNextCell(3);
+    newCells->InsertCellPoint(pts[0]);
+    newCells->InsertCellPoint(pb);
+    newCells->InsertCellPoint(pa);
+
+    // triangle [b,1,c]
+    newCells->InsertNextCell(3);
+    newCells->InsertCellPoint(pb);
+    newCells->InsertCellPoint(pts[1]);
+    newCells->InsertCellPoint(pc);
+    
+    // triangle [a,b,c]
+    newCells->InsertNextCell(3);
+    newCells->InsertCellPoint(pa);
+    newCells->InsertCellPoint(pb);
+    newCells->InsertCellPoint(pc);
+
+    // triangle [a,c,2]
+    newCells->InsertNextCell(3);
+    newCells->InsertCellPoint(pa);
+    newCells->InsertCellPoint(pc);
+    newCells->InsertCellPoint(pts[2]);
+    
+  }
+
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjSphereSubdivisionSource::Execute()
+{
+  int i, j;
+  //int jStart, jEnd, numOffset;
+  int numPts, numPolys;
+  vtkPoints *newPoints; 
+  vtkCellArray *newPolys, *oldPolys;
+  vtkPolyData *output = this->GetOutput();
+  
+  // Set things up; allocate memory
+  //
+  vtkDebugMacro("vtkmpjSphereSubdivisionSource Executing");
+  
+  // number of creating triangles
+  // n'th approximation is 8 * 4^(n-1)
+  //  numPolys = 8;
+  newPolys = vtkCellArray::New();
+  //newPolys->Allocate(newPolys->EstimateSize(numPolys, 3));
+  
+  newPoints = vtkPoints::New();
+    
+  // create intial polyhedron
+  this->InitializePolys(newPoints, newPolys);
+
+  // subdivide polyhedron
+  for (int level = 1; level<this->Depth; level++) {
+    
+    oldPolys = newPolys;
+    numPolys = oldPolys->GetNumberOfCells();
+    numPts = newPoints->GetNumberOfPoints();
+    
+    //printf("level=%d, points=%d, cells=%d\n",level,numPts,numPolys);
+    
+    newPolys = vtkCellArray::New();
+    newPolys->Allocate(newPolys->EstimateSize(numPolys*4, 3));
+    
+    this->SubdividePolys(newPoints, oldPolys, newPolys);
+    
+    oldPolys->Delete();
+  }
+  
+  numPolys = newPolys->GetNumberOfCells();
+  numPts = newPoints->GetNumberOfPoints();
+  
+  printf("level=%d, points=%d, cells=%d\n",this->Depth,numPts,numPolys);
+  
+  //for(int i=0;i<numPts;i++) {
+  //float *x = newPoints->GetPoint(i);
+  // printf("x=%f,%f,%f\n",x[0],x[1],x[2]);
+  //}
+    
+  // Update ourselves and release memeory
+  newPoints->Squeeze();
+  output->SetPoints(newPoints);
+  newPoints->Delete();
+
+  newPolys->Squeeze();
+  output->SetPolys(newPolys);
+  newPolys->Delete();
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjSphereSubdivisionSource::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+  
+  os << indent << "Depth: " << this->Depth << "\n";
+  os << indent << "DuplicatePoints: " << this->DuplicatePoints << "\n";
+
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjSphereSubdivisionSource.h b/bioimagesuite30_src/mpjCommon/vtkmpjSphereSubdivisionSource.h
new file mode 100644
index 0000000..c44c4cc
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjSphereSubdivisionSource.h
@@ -0,0 +1,117 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// 
+// Generates a triangle mesh approximating a sphere by 
+// recursive subdivision. First approximation is a platonic solid; 
+// each level of refinement increases the number of 
+// triangles by a factor of 4.
+//
+// Level 3 (128 triangles for an octahedron) is a good tradeoff if 
+// gouraud shading is used to render the database.
+// 
+// Jon Leech (leech @ cs.unc.edu) 3/24/89 * http://www.cs.unc.edu/~jon
+// 
+
+#ifndef __vtkmpjSphereSubdivisionSource_h
+#define __vtkmpjSphereSubdivisionSource_h
+
+#include "vtkPolyDataSource.h"
+#include "vtkPoints.h"
+#include "vtkCellArray.h"
+#include "vtkFloatArray.h"
+
+#define VTK_MPJ_MAX_DEPTH 10
+
+class vtkmpjSphereSubdivisionSource : public vtkPolyDataSource 
+{
+public:
+  vtkTypeMacro(vtkmpjSphereSubdivisionSource,vtkPolyDataSource);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Construct sphere with radius=0.5 and default resolution 8 in both Phi
+  // and Theta directions. Theta ranges from (0,360) and phi (0,180) degrees.
+  static vtkmpjSphereSubdivisionSource *New();
+
+  // Description:
+  // Set the depth of the sphere subdivision
+  vtkSetClampMacro(Depth,int,1,VTK_MPJ_MAX_DEPTH);
+  vtkGetMacro(Depth,int);
+
+  // Description:
+  // Set whether the list of points should contain duplicates
+  vtkSetClampMacro(DuplicatePoints,int,0,1);
+  vtkBooleanMacro(DuplicatePoints,int);
+  vtkGetMacro(DuplicatePoints,int);
+
+  // Description:
+  // Set initial polyhedron for subdivision
+  //BTX
+  enum
+    {
+      OCTAHEDRON,    // 8F, 6V, 12E
+      TETRAHEDRON,   // 4F, 4V
+      ICOSAHEDRON    // 20F, 12V, 30E
+    };
+  //ETX
+  vtkSetClampMacro(SubdivisionType, int, OCTAHEDRON, ICOSAHEDRON);
+  vtkGetMacro(SubdivisionType, int);
+  void SetSubdivisionTypeToOctahedron()
+    {this->SetSubdivisionType(OCTAHEDRON);};
+  void SetSubdivisionTypeToTetrahedron()
+    {this->SetSubdivisionType(TETRAHEDRON);};
+  void SetSubdivisionTypeToIcosahedron()
+    {this->SetSubdivisionType(ICOSAHEDRON);};
+
+protected:
+  vtkmpjSphereSubdivisionSource();
+  ~vtkmpjSphereSubdivisionSource() {}
+
+  void Execute();
+  
+  int Depth;
+  int DuplicatePoints;
+  int SubdivisionType;
+  
+  void InitializePolys(vtkPoints *pts, vtkCellArray *polys);
+  void SubdividePolys(vtkPoints *newPoints, vtkCellArray *oldCells, vtkCellArray *newCells);
+  void FindPoints(vtkPoints *pts, double a[3], double b[3], double c[3], vtkIdType &pa, vtkIdType &pb, vtkIdType &pc);
+  
+private:
+  vtkmpjSphereSubdivisionSource(const vtkmpjSphereSubdivisionSource&);  // Not implemented.
+  void operator=(const vtkmpjSphereSubdivisionSource&);  // Not implemented.
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjStreamer.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjStreamer.cpp
new file mode 100644
index 0000000..6ce93b5
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjStreamer.cpp
@@ -0,0 +1,771 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjStreamer.h"
+
+// #include "vtkCell.h"
+// #include "vtkDataSet.h"
+// #include "vtkFloatArray.h"
+// #include "vtkGenericCell.h"
+// #include "vtkInterpolatedVelocityField.h"
+// #include "vtkMath.h"
+// #include "vtkMultiThreader.h"
+// #include "vtkObjectFactory.h"
+// #include "vtkPointData.h"
+// #include "vtkRungeKutta2.h"
+
+//vtkCxxRevisionMacro(vtkmpjStreamer, "$Revision: 1.83 $");
+vtkCxxSetObjectMacro(vtkmpjStreamer,Integrator,vtkInitialValueProblemSolver);
+//vtkStandardNewMacro(vtkmpjStreamer);
+
+#define VTK_START_FROM_POSITION 0
+#define VTK_START_FROM_LOCATION 1
+
+vtkmpjStreamer::mpjStreamArray::mpjStreamArray()
+{
+  this->MaxId = -1; 
+  this->Array = new vtkmpjStreamer::mpjStreamPoint[1000];
+  this->Size = 1000;
+  this->Extend = 5000;
+  this->Direction = VTK_INTEGRATE_FORWARD;
+}
+
+vtkmpjStreamer::mpjStreamPoint *vtkmpjStreamer::mpjStreamArray::Resize(vtkIdType sz)
+{
+  vtkmpjStreamer::mpjStreamPoint *newArray;
+  vtkIdType newSize;
+
+  if (sz >= this->Size)
+    {
+    newSize = this->Size + 
+      this->Extend*(((sz-this->Size)/this->Extend)+1);
+    }
+  else
+    {
+    newSize = sz;
+    }
+
+  newArray = new vtkmpjStreamer::mpjStreamPoint[newSize];
+
+  memcpy(newArray, this->Array,
+         (sz < this->Size ? sz : this->Size) * sizeof(vtkmpjStreamer::mpjStreamPoint));
+
+  this->Size = newSize;
+  delete [] this->Array;
+  this->Array = newArray;
+
+  return this->Array;
+}
+
+// Construct object to start from position (0,0,0); integrate forward; terminal
+// speed 0.0; vorticity computation off; integrations step length 0.2; and
+// maximum propagation time 100.0.
+vtkmpjStreamer::vtkmpjStreamer()
+{
+  this->StartFrom = VTK_START_FROM_POSITION;
+
+  this->StartCell = 0;
+  this->StartSubId = 0;
+  this->StartPCoords[0] = this->StartPCoords[1] = this->StartPCoords[2] = 0.5;
+  this->StartPosition[0] = this->StartPosition[1] = this->StartPosition[2] = 0.0;
+  this->Streamers = NULL;
+  this->MaximumPropagationTime = 100.0;
+  this->IntegrationDirection = VTK_INTEGRATE_FORWARD;
+  this->IntegrationStepLength = 0.2;
+  this->Vorticity = 0;
+  this->TerminalSpeed = 0.0;
+  this->SpeedScalars = 0;
+  this->OrientationScalars = 0;
+  this->NumberOfStreamers = 0;
+  this->Threader = vtkMultiThreader::New();
+  this->NumberOfThreads = this->Threader->GetNumberOfThreads();
+  this->Integrator = vtkRungeKutta2::New();
+  this->SavePointInterval = 0.00001;
+}
+
+vtkmpjStreamer::~vtkmpjStreamer()
+{
+  delete [] this->Streamers;
+
+  //  fprintf(stderr,"This far \n");
+  //  this->SetSource(0);
+  //  fprintf(stderr,"This far 2\n");
+  if (this->Threader)
+    {
+      //  fprintf(stderr,"This far 3\n");
+      this->Threader->Delete();
+    }
+  //  fprintf(stderr,"This far 4\n");
+  this->SetIntegrator(0);
+}
+
+void vtkmpjStreamer::SetSource(vtkDataSet *source)
+{
+  this->vtkProcessObject::SetNthInput(1, source);
+}
+
+vtkDataSet *vtkmpjStreamer::GetSource()
+{
+  if (this->NumberOfInputs < 2)
+    {
+    return NULL;
+    }
+  return (vtkDataSet *)(this->Inputs[1]);
+}
+
+// Specify the start of the streamline in the cell coordinate system. That is,
+// cellId and subId (if composite cell), and parametric coordinates.
+void vtkmpjStreamer::SetStartLocation(vtkIdType cellId, int subId,
+                                   float pcoords[3])
+{
+  if ( cellId != this->StartCell || subId != this->StartSubId ||
+       pcoords[0] !=  this->StartPCoords[0] || 
+       pcoords[1] !=  this->StartPCoords[1] || 
+       pcoords[2] !=  this->StartPCoords[2] )
+    {
+    this->Modified();
+    this->StartFrom = VTK_START_FROM_LOCATION;
+
+    this->StartCell = cellId;
+    this->StartSubId = subId;
+    this->StartPCoords[0] = pcoords[0];
+    this->StartPCoords[1] = pcoords[1];
+    this->StartPCoords[2] = pcoords[2];
+    }
+}
+
+// Specify the start of the streamline in the cell coordinate system. That is,
+// cellId and subId (if composite cell), and parametric coordinates.
+void vtkmpjStreamer::SetStartLocation(vtkIdType cellId, int subId, float r,
+                                   float s, float t)
+{
+  float pcoords[3];
+  pcoords[0] = r;
+  pcoords[1] = s;
+  pcoords[2] = t;
+
+  this->SetStartLocation(cellId, subId, pcoords);
+}
+
+// Get the starting location of the streamline in the cell coordinate system.
+vtkIdType vtkmpjStreamer::GetStartLocation(int& subId, float pcoords[3])
+{
+  subId = this->StartSubId;
+  pcoords[0] = this->StartPCoords[0];
+  pcoords[1] = this->StartPCoords[1];
+  pcoords[2] = this->StartPCoords[2];
+  return this->StartCell;
+}
+
+// Specify the start of the streamline in the global coordinate system. Search
+// must be performed to find initial cell to start integration from.
+void vtkmpjStreamer::SetStartPosition(double x[3])
+{
+  if ( x[0] != this->StartPosition[0] || x[1] != this->StartPosition[1] || 
+       x[2] != this->StartPosition[2] )
+    {
+    this->Modified();
+    this->StartFrom = VTK_START_FROM_POSITION;
+
+    this->StartPosition[0] = x[0];
+    this->StartPosition[1] = x[1];
+    this->StartPosition[2] = x[2];
+    }
+}
+
+// Specify the start of the streamline in the global coordinate system. Search
+// must be performed to find initial cell to start integration from.
+void vtkmpjStreamer::SetStartPosition(double x, double y, double z)
+{
+  double pos[3];
+  pos[0] = x;
+  pos[1] = y;
+  pos[2] = z;
+
+  this->SetStartPosition(pos);
+}
+
+// Get the start position in global x-y-z coordinates.
+double *vtkmpjStreamer::GetStartPosition()
+{
+  return this->StartPosition;
+}
+
+static const float VTK_EPSILON=1E-12;
+
+VTK_THREAD_RETURN_TYPE vtkmpjStreamer::ThreadedIntegrate( void *arg )
+{
+  vtkmpjStreamer              *self;
+  int                      thread_count;
+  int                      thread_id;
+  vtkmpjStreamer::mpjStreamArray           *streamer;
+  vtkmpjStreamer::mpjStreamPoint *sNext = 0, *sPtr;
+  vtkmpjStreamer::mpjStreamPoint pt1, pt2;
+  int                      i;
+  vtkIdType                idxNext, ptId;
+  double                    d, step, dir;
+  double                    xNext[3], vel[3];
+  double *cellVel;
+  double derivs[9];
+  double                    *w, pcoords[3];
+  double                    coords[4];
+  vtkDataSet               *input;
+  vtkGenericCell           *cell;
+  vtkPointData             *pd;
+  vtkDataArray             *inScalars;
+  vtkDataArray             *inVectors;
+  vtkDoubleArray            *cellVectors;
+  vtkDataArray             *cellScalars=0;
+  double tOffset, vort[3];
+  double err;
+  int nSavePts = 0, counter=0;
+
+  thread_id = ((vtkMultiThreader::ThreadInfo *)(arg))->ThreadID;
+  thread_count = ((vtkMultiThreader::ThreadInfo *)(arg))->NumberOfThreads;
+  self = (vtkmpjStreamer *)(((vtkMultiThreader::ThreadInfo *)(arg))->UserData);
+
+  input     = self->GetInput();
+  pd        = input->GetPointData();
+  inScalars = pd->GetScalars();
+  inVectors = pd->GetVectors();
+
+  cell = vtkGenericCell::New();
+  cellVectors = vtkDoubleArray::New();
+  cellVectors->SetNumberOfComponents(3);
+  cellVectors->Allocate(3*VTK_CELL_SIZE);
+  if (inScalars)
+    {
+    cellScalars = inScalars->NewInstance();
+    cellScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents());
+    cellScalars->Allocate(inScalars->GetNumberOfComponents()*VTK_CELL_SIZE);
+    }
+
+  w = new double[input->GetMaxCellSize()];
+
+  // Set the function set to be integrated
+  vtkInterpolatedVelocityField* func = vtkInterpolatedVelocityField::New();
+  func->AddDataSet(input);
+
+  if (self->GetIntegrator() == 0)
+    {
+    vtkGenericWarningMacro("No integrator is specified.");
+    return VTK_THREAD_RETURN_VALUE;
+    }
+
+  // Create a new integrator, the type is the same as Integrator
+  vtkInitialValueProblemSolver* integrator = 
+    self->GetIntegrator()->NewInstance();
+  integrator->SetFunctionSet(func);
+
+  // Used to avoid calling these function many times during
+  // the integration
+  float termspeed = self->GetTerminalSpeed();
+  float maxtime = self->GetMaximumPropagationTime();
+  float savePointInterval = self->GetSavePointInterval();
+
+  // For each streamer, integrate in appropriate direction
+  // Do only the streamers that this thread should handle.
+  for (ptId=0; ptId < self->GetNumberOfStreamers(); ptId++)
+    {
+    if ( ptId % thread_count == thread_id )
+      {
+      // Get starting step
+      streamer = self->GetStreamers() + ptId;
+      sPtr = streamer->GetmpjStreamPoint(0);
+      if ( sPtr->cellId < 0 )
+        {
+        continue;
+        }
+      // Set the last cell id in the vtkInterpolatedVelocityField
+      // object to speed up FindCell calls
+      func->SetLastCellId(sPtr->cellId);
+
+      dir = streamer->Direction;
+
+      // Copy the first point
+      pt1 = *sPtr;
+      pt2 = *sPtr;
+      tOffset = pt1.t;
+
+      //integrate until time has been exceeded
+      while ( pt1.cellId >= 0 && pt1.speed > termspeed && pt1.t <  maxtime )
+        {
+	  
+	  //printf("pt1.cellId=%d, pt1.speed=%f, pt1.time=%f\n",pt1.cellId,pt1.speed,pt1.t);
+	  
+	  if ( counter++ % 1000 == 0 )
+	    {
+	      if (!thread_id)
+		{
+		  self->UpdateProgress((float)ptId/self->GetNumberOfStreamers()
+				       +pt1.t/maxtime/self->GetNumberOfStreamers());
+		}
+	      if (self->GetAbortExecute())
+		{
+		  break;
+		}
+	    }
+	  
+	  // Set the integration step to be characteristic cell length
+	  // time IntegrationStepLength
+	  input->GetCell(pt1.cellId, cell);
+	  step = dir*self->GetIntegrationStepLength() * sqrt((double)cell->GetLength2());///pt1.speed;
+
+        // Calculate the next step using the integrator provided
+        if (integrator->ComputeNextStep(pt1.x, pt1.v, xNext, 0, step, 0, err)
+            != 0)
+          {
+	    //printf("out of integration\n");
+	    break;
+          }
+
+        for(i=0; i<3; i++)
+          {
+          coords[i] = xNext[i];
+          }
+
+        // Interpolate the velocity field at coords
+        if ( !func->FunctionValues(coords, vel) )
+          {
+	    //printf("out of interpolation with coords=%f,%f,%f,%f\n",coords[0],coords[1],coords[2],coords[3]);
+	    break;
+          }
+
+        for(i=0; i<3; i++)
+          {
+          pt2.v[i] = vel[i];
+          }
+
+        for (i=0; i<3; i++)
+          {
+          pt2.x[i] = xNext[i];
+          }
+        
+        pt2.cellId = func->GetLastCellId();
+        func->GetLastWeights(w);
+        func->GetLastLocalCoordinates(pcoords);
+        input->GetCell(pt2.cellId, cell);
+        
+        if ( inScalars )
+          {
+          // Interpolate scalars
+          inScalars->GetTuples(cell->PointIds, cellScalars);
+          for (pt2.s=0.0, i=0; i < cell->GetNumberOfPoints(); i++)
+            {
+            pt2.s += cellScalars->GetComponent(i,0) * w[i];
+            }
+          }
+
+        pt2.speed = vtkMath::Norm(pt2.v);
+	//printf("pt2.v=%f, %f, %f\n",pt2.v[0],pt2.v[1],pt2.v[2]);
+	(void)vtkMath::Normalize(pt2.v);
+
+        d = sqrt((double)vtkMath::Distance2BetweenPoints(pt1.x,pt2.x));
+        pt2.d = pt1.d + d;
+
+	//printf("d=%f, total=%f\n",d,pt2.d);
+        // If at stagnation region, stop the integration
+        if ( d <= 1E-3 || (pt1.speed + pt2.speed) < VTK_EPSILON )
+          {
+	    //printf("stagnation point: d=%f, pt1.speed=%f, pt2.speed=%f\n",d,pt1.speed,pt2.speed);
+	    pt2.t = pt1.t;
+	    break;
+          }
+        pt2.t = pt1.t + (2.0 * d / (pt1.speed + pt2.speed));
+	//printf("d=%f, pt1.speed=%f, pt2.speed=%f\n",d,pt1.speed,pt2.speed);
+        if (self->GetVorticity() && inVectors)
+          {
+	    // compute vorticity
+          inVectors->GetTuples(cell->PointIds, cellVectors);
+          cellVel = cellVectors->GetPointer(0);
+          cell->Derivatives(0, pcoords, cellVel, 3, derivs);
+          vort[0] = derivs[7] - derivs[5];
+          vort[1] = derivs[2] - derivs[6];
+          vort[2] = derivs[3] - derivs[1];
+          // rotation
+          pt2.omega = vtkMath::Dot(vort, pt2.v);
+          pt2.omega /= pt2.speed;
+          pt2.theta += (pt1.omega+pt2.omega)/2 * (pt2.t - pt1.t);
+          }
+                
+        // Store only points which have a point to be displayed
+        // between them
+        if (tOffset >= pt1.t && tOffset <= pt2.t)
+          {
+          // Do not store if same as the last point.
+          // To avoid storing some points twice.
+          if ( !sNext || sNext->x[0] != pt1.x[0] || sNext->x[1] != pt1.x[1]
+               || sNext->x[2] != pt1.x[2] )
+            {
+            idxNext = streamer->InsertNextmpjStreamPoint();
+            sNext = streamer->GetmpjStreamPoint(idxNext);
+            *sNext = pt1;
+            nSavePts++;
+            }
+          idxNext = streamer->InsertNextmpjStreamPoint();
+          sNext = streamer->GetmpjStreamPoint(idxNext);
+          *sNext = pt2;
+          nSavePts++;
+          }
+        if (tOffset < pt2.t)
+          {
+          tOffset += ((int)(( pt2.t - tOffset) / savePointInterval) + 1)
+            * savePointInterval;
+          }
+        pt1 = pt2;
+	//printf("pt1.cellId=%d, pt1.speed=%f, pt1.time=%f\n",pt1.cellId,pt1.speed,pt1.t);
+        } 
+      //printf("out\n");
+      // Store the last point anyway.
+      if ( !sNext || sNext->x[0] != pt2.x[0] || sNext->x[1] != pt2.x[1]
+           || sNext->x[2] != pt2.x[2] )
+        {
+        idxNext = streamer->InsertNextmpjStreamPoint();
+        sNext = streamer->GetmpjStreamPoint(idxNext);
+        *sNext = pt2;
+        nSavePts++;
+        }
+      // Clear the last cell to avoid starting a search from
+      // the last point in the streamline
+      func->ClearLastCellId();
+      }
+
+    }
+
+  integrator->Delete();
+  func->Delete();
+
+  cell->Delete();
+  cellVectors->Delete();
+  if (cellScalars)
+    {
+    cellScalars->Delete();
+    }
+  delete[] w;
+
+  return VTK_THREAD_RETURN_VALUE;
+}
+
+void vtkmpjStreamer::Integrate()
+{
+  vtkDataSet *input = this->GetInput();
+  vtkDataSet *source = this->GetSource();
+  vtkPointData *pd=input->GetPointData();
+  vtkDataArray *inScalars;
+  vtkDataArray *inVectors;
+  vtkIdType numSourcePts, idx, idxNext;
+  vtkmpjStreamer::mpjStreamPoint *sNext, *sPtr;
+  vtkIdType ptId, i;
+  int j, offset;
+  vtkCell *cell;
+  double *v; 
+  double *cellVel;
+  double derivs[9], xNext[3], vort[3];
+  double tol2;
+  double *w=new double[input->GetMaxCellSize()];
+  vtkDoubleArray *cellVectors;
+  vtkDataArray *cellScalars=0;
+
+  vtkDebugMacro(<<"Generating streamers");
+  this->NumberOfStreamers = 0;
+
+// reexecuting - delete old stuff
+  delete [] this->Streamers;
+  this->Streamers = NULL;
+
+  if ( ! (inVectors=pd->GetVectors()) )
+    {
+    delete [] w;
+    vtkErrorMacro(<<"No vector data defined!");
+    return;
+    }
+
+  cellVectors = vtkDoubleArray::New();
+  cellVectors->SetNumberOfComponents(3);
+  cellVectors->Allocate(3*VTK_CELL_SIZE);
+
+  inScalars = pd->GetScalars();
+
+  if (inScalars)
+    {
+    cellScalars = inScalars->NewInstance();
+    cellScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents());
+    cellScalars->Allocate(cellScalars->GetNumberOfComponents()*VTK_CELL_SIZE);
+    }
+  
+  tol2 = input->GetLength()/1000; 
+  tol2 = tol2*tol2;
+
+  //
+  // Create starting points
+  //
+  this->NumberOfStreamers = numSourcePts = offset = 1;
+  if ( this->GetSource() )
+    {
+    this->NumberOfStreamers = numSourcePts = source->GetNumberOfPoints();
+    }
+ 
+  if ( this->IntegrationDirection == VTK_INTEGRATE_BOTH_DIRECTIONS )
+    {
+    offset = 2;
+    this->NumberOfStreamers *= 2;
+    }
+
+  this->Streamers = new vtkmpjStreamer::mpjStreamArray[this->NumberOfStreamers];
+
+  if ( this->StartFrom == VTK_START_FROM_POSITION && !this->GetSource() )
+    {
+    idx = this->Streamers[0].InsertNextmpjStreamPoint();
+    sPtr = this->Streamers[0].GetmpjStreamPoint(idx);
+    sPtr->subId = 0;
+    for (i=0; i<3; i++)
+      {
+      sPtr->x[i] = this->StartPosition[i];
+      }
+    sPtr->cellId = input->FindCell(this->StartPosition, NULL, -1, 0.0, 
+                                   sPtr->subId, sPtr->p, w);
+    }
+
+  else if ( this->StartFrom == VTK_START_FROM_LOCATION && !this->GetSource() )
+    {
+    idx = this->Streamers[0].InsertNextmpjStreamPoint();
+    sPtr = this->Streamers[0].GetmpjStreamPoint(idx);
+    sPtr->subId = 0;
+    cell =  input->GetCell(sPtr->cellId);
+    cell->EvaluateLocation(sPtr->subId, sPtr->p, sPtr->x, w);
+    }
+
+  else //VTK_START_FROM_SOURCE
+    {
+    for (ptId=0; ptId < numSourcePts; ptId++)
+      {
+      idx = this->Streamers[offset*ptId].InsertNextmpjStreamPoint();
+      sPtr = this->Streamers[offset*ptId].GetmpjStreamPoint(idx);
+      sPtr->subId = 0;
+      source->GetPoint(ptId,sPtr->x);
+      sPtr->cellId = input->FindCell(sPtr->x, NULL, -1, tol2,
+                                     sPtr->subId, sPtr->p, w);
+      }
+    }
+
+  // Finish initializing each streamer
+  //
+  for (idx=0, ptId=0; ptId < numSourcePts; ptId++)
+    {
+    this->Streamers[offset*ptId].Direction = 1.0;
+    sPtr = this->Streamers[offset*ptId].GetmpjStreamPoint(idx);
+    sPtr->d = 0.0;
+    sPtr->t = 0.0;
+    sPtr->s = 0.0;
+    sPtr->theta = 0.0;
+    sPtr->omega = 0.0;
+    
+    if ( sPtr->cellId >= 0 ) //starting point in dataset
+      {
+      cell = input->GetCell(sPtr->cellId);
+      cell->EvaluateLocation(sPtr->subId, sPtr->p, xNext, w);
+
+      inVectors->GetTuples(cell->PointIds, cellVectors);
+      sPtr->v[0]  = sPtr->v[1] = sPtr->v[2] = 0.0;
+      for (i=0; i < cell->GetNumberOfPoints(); i++)
+        {
+        v =  cellVectors->GetTuple(i);
+        for (j=0; j<3; j++)
+          {
+          sPtr->v[j] += v[j] * w[i];
+          }
+        }
+    
+      sPtr->speed = vtkMath::Norm(sPtr->v);
+      //printf("sPtr->speed=%f\n",sPtr->speed);
+
+      (void)vtkMath::Normalize(sPtr->v);
+
+      if (this->GetVorticity() && inVectors)
+        {
+          // compute vorticity
+        inVectors->GetTuples(cell->PointIds, cellVectors);
+        cellVel = cellVectors->GetPointer(0);
+        cell->Derivatives(0, sPtr->p, cellVel, 3, derivs);
+        vort[0] = derivs[7] - derivs[5];
+        vort[1] = derivs[2] - derivs[6];
+        vort[2] = derivs[3] - derivs[1];
+        // rotation
+        sPtr->omega = vtkMath::Dot(vort, sPtr->v);
+        sPtr->omega /= sPtr->speed;
+        sPtr->theta = 0;
+        }
+
+      if ( inScalars ) 
+        {
+        inScalars->GetTuples(cell->PointIds, cellScalars);
+        for (sPtr->s=0, i=0; i < cell->GetNumberOfPoints(); i++)
+          {
+          sPtr->s += cellScalars->GetComponent(i,0) * w[i];
+          }
+        }
+      }
+    else
+      {
+      for (j=0; j<3; j++)
+        {
+        sPtr->p[j] = 0.0;
+        sPtr->v[j] = 0.0;
+        }
+      sPtr->speed = 0;
+      }
+
+    if ( this->IntegrationDirection == VTK_INTEGRATE_BOTH_DIRECTIONS )
+      {
+      this->Streamers[offset*ptId+1].Direction = -1.0;
+      idxNext = this->Streamers[offset*ptId+1].InsertNextmpjStreamPoint();
+      sNext = this->Streamers[offset*ptId+1].GetmpjStreamPoint(idxNext);
+      sPtr = this->Streamers[offset*ptId].GetmpjStreamPoint(idx);
+      *sNext = *sPtr;
+      }
+    else if ( this->IntegrationDirection == VTK_INTEGRATE_BACKWARD )
+      {
+      this->Streamers[offset*ptId].Direction = -1.0;
+      }
+
+
+    } //for each streamer
+
+  // Some data access methods must be called once from a single thread before they
+  // can safely be used. Call those now
+  vtkGenericCell *gcell = vtkGenericCell::New();
+  input->GetCell(0,gcell);
+  gcell->Delete();
+  
+  // Set up and execute the thread
+  this->Threader->SetNumberOfThreads( this->NumberOfThreads );
+  this->Threader->SetSingleMethod( vtkmpjStreamer::ThreadedIntegrate, (void *)this );
+  this->Threader->SingleMethodExecute();
+
+  //
+  // Now create appropriate representation
+  //
+  if ( this->OrientationScalars && !this->SpeedScalars)
+    {
+    for (ptId=0; ptId < this->NumberOfStreamers; ptId++)
+      {
+      for ( sPtr=this->Streamers[ptId].GetmpjStreamPoint(0), i=0; 
+            i < this->Streamers[ptId].GetNumberOfPoints() && sPtr->cellId >= 0; 
+            i++, sPtr=this->Streamers[ptId].GetmpjStreamPoint(i) )
+        {
+        sPtr->s = sPtr->theta;
+        }
+      }
+    }
+
+  if ( this->SpeedScalars )
+    {
+    for (ptId=0; ptId < this->NumberOfStreamers; ptId++)
+      {
+      for ( sPtr=this->Streamers[ptId].GetmpjStreamPoint(0), i=0; 
+            i < this->Streamers[ptId].GetNumberOfPoints() && sPtr->cellId >= 0; 
+            i++, sPtr=this->Streamers[ptId].GetmpjStreamPoint(i) )
+        {
+        sPtr->s = sPtr->speed;
+        }
+      }
+    }
+  delete [] w;
+  cellVectors->Delete();
+  if (cellScalars)
+    {
+    cellScalars->Delete();
+    }
+}
+
+void vtkmpjStreamer::ComputeVorticity()
+{
+}
+
+void vtkmpjStreamer::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+
+  if ( this->StartFrom == VTK_START_FROM_POSITION && !this->GetSource())
+    {
+    os << indent << "Starting Position: (" << this->StartPosition[0] << ","
+       << this->StartPosition[1] << ", " << this->StartPosition[2] << ")\n";
+    }
+  else if ( this->StartFrom == VTK_START_FROM_LOCATION && !this->GetSource())
+    {
+    os << indent << "Starting Location:\n\tCell: " << this->StartCell 
+       << "\n\tSubId: " << this->StartSubId << "\n\tP.Coordinates: ("
+       << this->StartPCoords[0] << ", " 
+       << this->StartPCoords[1] << ", " 
+       << this->StartPCoords[2] << ")\n";
+    }
+  else
+    {
+    os << indent << "Starting Source: " << (void *)this->GetSource() << "\n";
+    }
+
+  os << indent << "Maximum Propagation Time: " 
+     << this->MaximumPropagationTime << "\n";
+
+  if ( this->IntegrationDirection == VTK_INTEGRATE_FORWARD )
+    {
+    os << indent << "Integration Direction: FORWARD\n";
+    }
+  else if ( this->IntegrationDirection == VTK_INTEGRATE_BACKWARD )
+    {
+    os << indent << "Integration Direction: BACKWARD\n";
+    }
+  else
+    {
+    os << indent << "Integration Direction: FORWARD & BACKWARD\n";
+    }
+
+  os << indent << "Integration Step Length: " << this->IntegrationStepLength << "\n";
+
+  os << indent << "Vorticity: " << (this->Vorticity ? "On\n" : "Off\n");
+
+  os << indent << "Terminal Speed: " << this->TerminalSpeed << "\n";
+
+  os << indent << "Speed Scalars: " << (this->SpeedScalars ? "On\n" : "Off\n");
+
+  os << indent << "Orientation Scalars: " << (this->OrientationScalars ? "On\n" : "Off\n");
+
+  os << indent << "Interval with which points are stored:" 
+     << this->SavePointInterval << endl;
+
+  os << indent << "Integrator: " << this->Integrator << endl;
+
+  os << indent << "Number Of Streamers: " << this->NumberOfStreamers << "\n";
+  os << indent << "Number Of Threads: " << this->NumberOfThreads << "\n";
+}
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjStreamer.h b/bioimagesuite30_src/mpjCommon/vtkmpjStreamer.h
new file mode 100644
index 0000000..83738e9
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjStreamer.h
@@ -0,0 +1,319 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkmpjStreamer_h
+#define __vtkmpjStreamer_h
+
+#include "vtkDataSetToPolyDataFilter.h"
+
+#include "vtkCell.h"
+#include "vtkDataSet.h"
+#include "vtkFloatArray.h"
+#include "vtkDoubleArray.h"
+#include "vtkGenericCell.h"
+#include "vtkInterpolatedVelocityField.h"
+#include "vtkMath.h"
+#include "vtkMultiThreader.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkRungeKutta2.h"
+
+class vtkInitialValueProblemSolver;
+class vtkMultiThreader;
+
+#define VTK_INTEGRATE_FORWARD 0
+#define VTK_INTEGRATE_BACKWARD 1
+#define VTK_INTEGRATE_BOTH_DIRECTIONS 2
+
+class vtkmpjStreamer : public vtkDataSetToPolyDataFilter
+{
+public:
+  vtkTypeMacro(vtkmpjStreamer,vtkDataSetToPolyDataFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Specify the start of the streamline in the cell coordinate system. That
+  // is, cellId and subId (if composite cell), and parametric coordinates.
+  void SetStartLocation(vtkIdType cellId, int subId, float pcoords[3]);
+
+  // Description:
+  // Specify the start of the streamline in the cell coordinate system. That
+  // is, cellId and subId (if composite cell), and parametric coordinates.
+  void SetStartLocation(vtkIdType cellId, int subId, float r, float s,
+                        float t);
+
+  // Description:
+  // Get the starting location of the streamline in the cell coordinate system.
+  vtkIdType GetStartLocation(int& subId, float pcoords[3]);
+
+  // Description:
+  // Specify the start of the streamline in the global coordinate
+  // system. Search must be performed to find initial cell to start
+  // integration from.
+  void SetStartPosition(double x[3]);
+
+  // Description:
+  // Specify the start of the streamline in the global coordinate
+  // system. Search must be performed to find initial cell to start
+  // integration from.
+  void SetStartPosition(double x, double y, double z);
+
+  // Description:
+  // Get the start position in global x-y-z coordinates.
+  double *GetStartPosition();
+
+  // Description:
+  // Specify the source object used to generate starting points.
+  void SetSource(vtkDataSet *source);
+  vtkDataSet *GetSource();
+
+  // Description:
+  // Specify the maximum length of the Streamer expressed in elapsed time.
+  vtkSetClampMacro(MaximumPropagationTime,float,0.0,VTK_LARGE_FLOAT);
+  vtkGetMacro(MaximumPropagationTime,float);
+
+  // Description:
+  // Specify the direction in which to integrate the Streamer.
+  vtkSetClampMacro(IntegrationDirection,int,
+                   VTK_INTEGRATE_FORWARD,VTK_INTEGRATE_BOTH_DIRECTIONS);
+  vtkGetMacro(IntegrationDirection,int);
+  void SetIntegrationDirectionToForward()
+    {this->SetIntegrationDirection(VTK_INTEGRATE_FORWARD);};
+  void SetIntegrationDirectionToBackward()
+    {this->SetIntegrationDirection(VTK_INTEGRATE_BACKWARD);};
+  void SetIntegrationDirectionToIntegrateBothDirections()
+    {this->SetIntegrationDirection(VTK_INTEGRATE_BOTH_DIRECTIONS);};
+  const char *GetIntegrationDirectionAsString();
+
+  // Description:
+  // Specify a nominal integration step size (expressed as a fraction of
+  // the size of each cell). This value can be larger than 1.
+  vtkSetClampMacro(IntegrationStepLength,float,0.0000001,VTK_LARGE_FLOAT);
+  vtkGetMacro(IntegrationStepLength,float);
+
+  // Description:
+  // Turn on/off the creation of scalar data from velocity magnitude. If off,
+  // and input dataset has scalars, input dataset scalars are used.
+  vtkSetMacro(SpeedScalars,int);
+  vtkGetMacro(SpeedScalars,int);
+  vtkBooleanMacro(SpeedScalars,int);
+
+  // Description:
+  // Turn on/off the creation of scalar data from vorticity information. 
+  // The scalar information is currently the orientation value "theta"
+  // used in rotating stream tubes. If off, and input dataset has scalars,
+  // then input dataset scalars are used, unless SpeedScalars is also on.
+  // SpeedScalars takes precedence over OrientationScalars.
+  vtkSetMacro(OrientationScalars, int);
+  vtkGetMacro(OrientationScalars, int);
+  vtkBooleanMacro(OrientationScalars, int);
+
+  // Description:
+  // Set/get terminal speed (i.e., speed is velocity magnitude).  Terminal 
+  // speed is speed at which streamer will terminate propagation.
+  vtkSetClampMacro(TerminalSpeed,float,0.0,VTK_LARGE_FLOAT);
+  vtkGetMacro(TerminalSpeed,float);
+
+  // Description:
+  // Turn on/off the computation of vorticity. Vorticity is an indication of
+  // the rotation of the flow. In combination with vtkStreamLine and 
+  // vtkTubeFilter can be used to create rotated tubes. 
+  // If vorticity is turned on, in the output, the velocity vectors 
+  // are replaced by vorticity vectors.
+  vtkSetMacro(Vorticity,int);
+  vtkGetMacro(Vorticity,int);
+  vtkBooleanMacro(Vorticity,int);
+
+  vtkSetMacro( NumberOfThreads, int );
+  vtkGetMacro( NumberOfThreads, int );
+
+  vtkSetMacro( SavePointInterval, float );
+  vtkGetMacro( SavePointInterval, float );
+
+  // Description:
+  // Set/get the integrator type to be used in the stream line
+  // calculation. The object passed is not actually used but
+  // is cloned with NewInstance by each thread/process in the
+  // process of integration (prototype pattern). The default is 
+  // 2nd order Runge Kutta.
+  void SetIntegrator(vtkInitialValueProblemSolver *);
+  vtkGetObjectMacro ( Integrator, vtkInitialValueProblemSolver );
+
+protected:
+  // Description:
+  // Construct object to start from position (0,0,0); integrate forward;
+  // terminal speed 0.0; vorticity computation off; integrations step length
+  // 0.2; and maximum propagation time 100.0.
+  vtkmpjStreamer();
+  virtual ~vtkmpjStreamer();
+
+  // Integrate data
+  void Integrate();
+
+  // Special method for computing streamer vorticity
+  void ComputeVorticity();
+
+  // Controls where streamlines start from (either position or location).
+  int StartFrom;
+
+  // Starting from cell location
+  vtkIdType StartCell;
+  int StartSubId;
+  float StartPCoords[3];
+
+  // starting from global x-y-z position
+  double StartPosition[3];
+
+  //
+  // Special classes for manipulating data
+  //
+  //BTX - begin tcl exclude
+  //
+  class mpjStreamPoint {
+  public:
+    double   x[3];    // position 
+    vtkIdType     cellId;  // cell
+    int     subId;   // cell sub id
+    double   p[3];    // parametric coords in cell 
+    double   v[3];    // velocity 
+    float   speed;   // velocity norm 
+    float   s;       // scalar value 
+    float   t;       // time travelled so far 
+    float   d;       // distance travelled so far 
+    float   omega;   // stream vorticity, if computed
+    float   theta;    // rotation angle, if vorticity is computed
+  };
+
+  class mpjStreamArray;
+  friend class mpjStreamArray;
+  class mpjStreamArray { //;prevent man page generation
+  public:
+    mpjStreamArray();
+    ~mpjStreamArray()    {     if (this->Array)
+	{
+          delete [] this->Array;
+	}
+    };
+    vtkIdType GetNumberOfPoints() {return this->MaxId + 1;};
+    mpjStreamPoint *GetmpjStreamPoint(vtkIdType i) {return this->Array + i;};
+    vtkIdType InsertNextmpjStreamPoint() 
+    {
+      if ( ++this->MaxId >= this->Size )
+	{
+          this->Resize(this->MaxId);
+	}
+      return this->MaxId; //return offset from array
+    }
+    mpjStreamPoint *Resize(vtkIdType sz); //reallocates data
+    void Reset() {this->MaxId = -1;};
+
+    mpjStreamPoint *Array;  // pointer to data
+    vtkIdType MaxId;        // maximum index inserted thus far
+    vtkIdType Size;         // allocated size of data
+    vtkIdType Extend;       // grow array by this amount
+    float Direction;        // integration direction
+  };
+  //ETX
+  //
+
+  //array of streamers
+  mpjStreamArray *Streamers;
+  vtkIdType NumberOfStreamers;
+
+  // length of Streamer is generated by time, or by MaximumSteps
+  float MaximumPropagationTime;
+
+  // integration direction
+  int IntegrationDirection;
+
+  // the length (fraction of cell size) of integration steps
+  float IntegrationStepLength;
+
+  // boolean controls whether vorticity is computed
+  int Vorticity;
+
+  // terminal propagation speed
+  float TerminalSpeed;
+
+  // boolean controls whether data scalars or velocity magnitude are used
+  int SpeedScalars;
+
+  // boolean controls whether data scalars or vorticity orientation are used
+  int OrientationScalars;
+
+  // Prototype showing the integrator type to be set by the user.
+  vtkInitialValueProblemSolver* Integrator;
+
+  // Interval with which the stream points will be stored.
+  // Useful in reducing the memory footprint. Since the initial
+  // value is small, by default, it will store all/most points.
+  float SavePointInterval;
+
+  static  VTK_THREAD_RETURN_TYPE ThreadedIntegrate( void *arg );
+
+  // Description:
+  // These methods were added to allow access to these variables from the
+  // threads. 
+  vtkGetMacro( NumberOfStreamers, int );
+  mpjStreamArray *GetStreamers() { return this->Streamers; };
+
+  void InitializeThreadedIntegrate();
+  vtkMultiThreader           *Threader;
+  int                        NumberOfThreads;
+
+private:
+  vtkmpjStreamer(const vtkmpjStreamer&);  // Not implemented.
+  void operator=(const vtkmpjStreamer&);  // Not implemented.
+};
+
+// Description:
+// Return the integration direction as a character string.
+inline const char *vtkmpjStreamer::GetIntegrationDirectionAsString(void)
+{
+  if ( this->IntegrationDirection == VTK_INTEGRATE_FORWARD ) 
+    {
+    return "IntegrateForward";
+    }
+  else if ( this->IntegrationDirection == VTK_INTEGRATE_BACKWARD ) 
+    {
+    return "IntegrateBackward";
+    }
+  else 
+    {
+    return "IntegrateBothDirections";
+    }
+}
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjStreamlineDistance.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjStreamlineDistance.cpp
new file mode 100644
index 0000000..b9f4cd0
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjStreamlineDistance.cpp
@@ -0,0 +1,213 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjStreamlineDistance.h"
+
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkPolyLine.h"
+
+vtkStandardNewMacro(vtkmpjStreamlineDistance);
+
+// Construct object 
+vtkmpjStreamlineDistance::vtkmpjStreamlineDistance()
+{
+  this->ReferenceIndex = 0;
+  this->TargetIndex = 0;
+  this->Minimum = 0;
+  this->Maximum = 0;
+  this->Mean = 0;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjStreamlineDistance::SetReference(vtkDataSet *input)
+{
+  this->vtkProcessObject::SetNthInput(0, input);  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjStreamlineDistance::SetTarget(vtkDataSet *input)
+{
+  this->vtkProcessObject::SetNthInput(1, input);  
+}
+
+// ----------------------------------------------------------------------------
+vtkPolyData *vtkmpjStreamlineDistance::GetInput(int index)
+{
+  if (this->NumberOfInputs <= index)
+    {
+      return NULL;
+    }
+    
+  return (vtkPolyData *)(this->Inputs[index]);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjStreamlineDistance::Execute()
+{
+  vtkPolyData *input1 = GetInput(0);
+  vtkPolyData *input2 = GetInput(1);
+  vtkPointData *pd1=input1->GetPointData();
+  vtkPointData *pd2=input2->GetPointData();
+  
+  vtkPolyData *output = this->GetOutput();
+  vtkPointData *outPD = output->GetPointData();
+  vtkFloatArray *disterr = vtkFloatArray::New();
+  disterr->SetName("fractani");
+  disterr->SetNumberOfComponents(1);
+
+  //vtkPointData *outPD=output->GetPointData();
+  vtkCellArray *inLines1 = NULL;
+  vtkCellArray *inLines2 = NULL;
+  
+  vtkPoints *inPts1;
+  vtkPoints *inPts2;
+
+  vtkIdType numPts1 = 0, numPts2 = 0;
+  vtkIdType numLines1, numLines2;
+  
+  int abort=0;
+  vtkIdType id,inCellId;
+  
+  // Check input and initialize
+  //  
+  if ( !(inPts1=input1->GetPoints()) || 
+       (numPts1 = inPts1->GetNumberOfPoints()) < 1 ||
+       !(inLines1 = input1->GetLines()) || 
+       (numLines1 = inLines1->GetNumberOfCells()) < 1 )
+    {
+      return;
+    }
+
+  if ( !(inPts2=input2->GetPoints()) || 
+       (numPts2 = inPts2->GetNumberOfPoints()) < 1 ||
+       !(inLines2 = input2->GetLines()) || 
+       (numLines2 = inLines2->GetNumberOfCells()) < 1 )
+    {
+      return;
+    }
+  
+  vtkIdType npts;
+  vtkIdType npts1=0, *pts1=NULL;
+  vtkIdType npts2=0, *pts2=NULL;
+
+  inLines1->GetCell(this->ReferenceIndex, npts1, pts1);
+  inLines2->GetCell(this->TargetIndex, npts2, pts2);
+  
+  printf("Reference: npts1=%d\n",npts1);
+  printf("Target: npts2=%d\n",npts2);
+  
+  vtkPoints *newPts = vtkPoints::New();
+  vtkCellArray *newCells = vtkCellArray::New();
+
+  if (npts1 < npts2)
+    npts = npts1;
+  else npts = npts2;
+  
+  double x1[3], x2[3], x3[3];
+  double dist, dist2;
+  double distsum=0.0; 
+  double dist2sum=0.0;
+
+
+  if (npts > 1) {
+    
+    distsum = 0.0;
+    
+    newCells->InsertNextCell(npts);
+
+    // compute statistics for fiber
+    for(int i=0; i<npts; i++) {	
+      
+      // fetch point
+      inPts1->GetPoint(pts1[i],x1);
+            
+      // find closest point
+      inPts2->GetPoint(pts2[i],x2);
+      float min = vtkMath::Distance2BetweenPoints(x1,x2);
+      vtkIdType minpos = pts2[i];
+      
+      for(int j=0; j<npts; j++) {
+	inPts2->GetPoint(pts2[j],x2);
+	dist2 = vtkMath::Distance2BetweenPoints(x1,x2);
+	if (dist2 < min) {
+	  min = dist2; minpos = pts2[j];
+	}
+      }
+
+      inPts2->GetPoint(minpos,x2);
+      
+      x3[0] = (x1[0] + x2[0]) / 2.0;
+      x3[1] = (x1[1] + x2[1]) / 2.0;
+      x3[2] = (x1[2] + x2[2]) / 2.0;
+
+      // compute distance
+      dist2 = vtkMath::Distance2BetweenPoints(x1,x2);
+      dist = sqrt(dist2);
+      
+      if (dist < this->Minimum) this->Minimum = dist;
+      if (dist > this->Maximum) this->Maximum = dist;
+      
+      dist2sum += dist2;
+      distsum += sqrt(dist2);
+
+      // insert distance
+      disterr->InsertNextTuple(&dist);
+
+      id = newPts->InsertNextPoint(x3);
+
+      newCells->InsertCellPoint(id);
+
+    }
+    
+    // compute mean distance
+    this->Mean = distsum / (float)npts;
+    
+  } else {
+    printf("npts=%d\n",npts);
+  }
+  
+  outPD->AddArray(disterr);
+  disterr->Delete();
+  
+  output->SetPoints(newPts);
+  newPts->Delete();
+  
+  output->SetLines(newCells);
+  newCells->Delete();
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjStreamlineDistance.h b/bioimagesuite30_src/mpjCommon/vtkmpjStreamlineDistance.h
new file mode 100644
index 0000000..b7f7567
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjStreamlineDistance.h
@@ -0,0 +1,90 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjStreamlineDistance_h
+#define __vtkmpjStreamlineDistance_h
+
+#include "vtkPolyDataToPolyDataFilter.h"
+#include "vtkDataSet.h"
+#include "vtkPolyData.h"
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkDataArray.h"
+#include "vtkFloatArray.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+
+class vtkmpjStreamlineDistance : public vtkPolyDataToPolyDataFilter
+{
+public:
+  vtkTypeMacro(vtkmpjStreamlineDistance,vtkPolyDataToPolyDataFilter);
+
+  // Description:
+  // Construct object 
+  static vtkmpjStreamlineDistance *New();
+  
+  void SetReference(vtkDataSet *input); 
+  void SetTarget(vtkDataSet *input);
+  vtkPolyData *GetInput(int index);
+
+  // Get/Set reference polyline
+  vtkGetMacro(ReferenceIndex, int);
+  vtkSetMacro(ReferenceIndex, int);
+
+  // Get/Set target polyline
+  vtkGetMacro(TargetIndex, int);
+  vtkSetMacro(TargetIndex, int);
+  
+  // Get/Set stats
+  vtkGetMacro(Mean, float);
+  vtkGetMacro(Minimum, float);
+  vtkGetMacro(Maximum, float);
+
+ protected:
+  vtkmpjStreamlineDistance();
+  ~vtkmpjStreamlineDistance() {}
+  
+  // Usual data generation method
+  void Execute();
+  
+  int ReferenceIndex;
+  int TargetIndex;
+  float Mean;
+  float Minimum;
+  float Maximum;
+  
+ private:
+  vtkmpjStreamlineDistance(const vtkmpjStreamlineDistance&);// Not implemented.
+  void operator=(const vtkmpjStreamlineDistance&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjStreamlineQuantization.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjStreamlineQuantization.cpp
new file mode 100644
index 0000000..fd7bab6
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjStreamlineQuantization.cpp
@@ -0,0 +1,179 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjStreamlineQuantization.h"
+#include "vtkCellArray.h"
+#include "vtkPoints.h"
+#include "vtkPolyData.h"
+#include "vtkFloatArray.h"
+
+//------------------------------------------------------------------------------
+vtkmpjStreamlineQuantization* vtkmpjStreamlineQuantization::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjStreamlineQuantization");
+  if(ret)
+    {
+      return (vtkmpjStreamlineQuantization*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjStreamlineQuantization;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjStreamlineQuantization::vtkmpjStreamlineQuantization()
+{
+  this->Image = NULL;
+  this->MaskValue = 1;
+  this->BackgroundValue = 0;
+} 
+
+vtkmpjStreamlineQuantization::~vtkmpjStreamlineQuantization()
+{
+  if (this->Image != NULL)
+    this->Image->Delete();
+} 
+
+// ----------------------------------------------------------------------------
+void vtkmpjStreamlineQuantization::Execute()
+{ 
+  vtkPolyData *input=(vtkPolyData *)this->GetInput();
+  //  vtkDataSet *output=this->GetOutput();
+
+  vtkPointData *pd=this->Image->GetPointData();
+  vtkDataArray *out=pd->GetScalars();
+
+  vtkCellArray *inLines = NULL;
+
+  vtkPoints *inPts;
+  vtkIdType numPts = 0;
+  vtkIdType numLines;
+
+  vtkIdType npts=0, *pts=NULL;
+  int abort=0;
+  vtkIdType inCellId;
+  
+  float val;
+
+  // zero out background
+  out->FillComponent(0, this->BackgroundValue);
+
+  long count = 0;
+
+  // Check input and initialize
+  //  
+  if ( !(inPts=input->GetPoints()) || 
+       (numPts = inPts->GetNumberOfPoints()) < 1 ||
+       !(inLines = input->GetLines()) || 
+       (numLines = inLines->GetNumberOfCells()) < 1 )
+    {
+      return;
+    }
+
+  for (inCellId=0, inLines->InitTraversal(); 
+       inLines->GetNextCell(npts,pts) && !abort; inCellId++)
+    {
+      this->UpdateProgress((float)inCellId/numLines);
+      abort = this->GetAbortExecute();
+      
+      if (npts < 2)
+	{
+	  vtkWarningMacro(<< "Less than two points in line!");
+	  continue; //skip filtering this line
+	}
+      
+      int index=-1;
+      
+      for(int i=1;i<npts;i++)
+	{
+	  double x1[3],x2[3],p[3],d[3],grad[3];
+	  double maxdist=0.0;
+	  int maxindex=0;
+	  int k;
+	  
+	  inPts->GetPoint(pts[i-1],x1);
+	  inPts->GetPoint(pts[i], x2);
+	  
+	  for (k=0;k<=2;k++)
+	    {
+	      d[k]=x2[k]-x1[k];
+	      if (fabs(d[k])>fabs(maxdist))
+		{
+		  maxdist=d[k];
+		  maxindex=k;
+		}
+	    }
+	  
+	  for (k=0;k<=2;k++)
+	    {
+	      if (d[k]!=0.0)
+		grad[k]=d[k]/maxdist;
+	      else
+		grad[k]=0.0;
+	    }
+      
+	  for (float dt=0.0;dt<fabs(maxdist);dt+=0.25)
+	    {
+	      if (maxdist==0)
+		{
+		  for (k=0;k<=2;k++)
+		    p[k]=x1[k];
+		}
+	      else
+		{
+		  for (k=0;k<=2;k++)
+		    p[k]=x1[k]+(dt/fabs(maxdist))*d[k];
+		}
+	      
+	      //trans->TransformPoint(p,tx);
+
+	      // find point location
+	      index = this->Image->FindPoint(p);
+	      
+	      if (index >= 0) {
+		val = out->GetComponent(index, 0);
+		if (val != this->MaskValue) {
+		  count++;
+		  out->SetComponent(index, 0, this->MaskValue);
+		}
+	      }
+	      
+	    }
+	}
+    }
+
+  this->NumberOfVoxels = count;
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjStreamlineQuantization.h b/bioimagesuite30_src/mpjCommon/vtkmpjStreamlineQuantization.h
new file mode 100644
index 0000000..58a039d
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjStreamlineQuantization.h
@@ -0,0 +1,81 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjStreamlineQuantization_h
+#define __vtkmpjStreamlineQuantization_h
+
+#include "vtkDataSetToDataSetFilter.h"
+#include "vtkDataSet.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjStreamlineQuantization : public vtkDataSetToDataSetFilter
+{
+ public:
+  static vtkmpjStreamlineQuantization *New();
+  vtkTypeMacro(vtkmpjStreamlineQuantization,vtkDataSetToDataSetFilter);
+  
+  // Description: 
+  // Sets/Gets image for streamline quantization
+  vtkSetObjectMacro(Image, vtkImageData);
+  vtkGetObjectMacro(Image, vtkImageData);
+
+  // Description: Set/Gets background value
+  vtkSetMacro(BackgroundValue,float);
+  vtkGetMacro(BackgroundValue,float);
+
+  // Description: Set/Gets foreground value
+  vtkSetMacro(MaskValue,float);
+  vtkGetMacro(MaskValue,float);
+
+  // Description: Get number of quantized points
+  vtkGetMacro(NumberOfVoxels, long int);
+
+ protected:  
+ 
+  float BackgroundValue;
+  float MaskValue;  
+  long NumberOfVoxels;
+  vtkImageData *Image;
+ 
+  vtkmpjStreamlineQuantization();
+  virtual ~vtkmpjStreamlineQuantization();
+    
+  void Execute();
+  
+ private:
+
+  vtkmpjStreamlineQuantization(const vtkmpjStreamlineQuantization&); // Not implemented
+  void operator=(const vtkmpjStreamlineQuantization&); // Not implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamline.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamline.cpp
new file mode 100644
index 0000000..11c2729
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamline.cpp
@@ -0,0 +1,1333 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjTensorStreamline.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkFloatArray.h"
+#include "pxisinf.h"
+
+//------------------------------------------------------------------------------
+vtkmpjTensorStreamline* vtkmpjTensorStreamline::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjTensorStreamline");
+  if(ret)
+    {
+    return (vtkmpjTensorStreamline*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjTensorStreamline;
+}
+
+//
+// Special classes for manipulating data
+//BTX
+class vtkmpjTensorPoint { //;prevent man page generation
+public:
+  vtkmpjTensorPoint(); // method sets up storage
+  vtkmpjTensorPoint &operator=(const vtkmpjTensorPoint& hp); //for resizing
+  
+  double X[3];        // position 
+  vtkIdType CellId;  // cell
+  int SubId;         // cell sub id
+  //  vtkIdType PointId; // approx point id
+  double P[3];        // parametric coords in cell 
+  double W[3];        // eigenvalues (sorted in decreasing value)
+  double *V[3];       // pointers to eigenvectors (also sorted)
+  double V0[3];       // storage for eigenvectors
+  double V1[3];
+  double V2[3];
+  float S;           // input scalar
+  float Angle;       // angle between eigenvectors
+  float FA;          // fractional anisotropy 
+  float MD;          // mean diffusivity
+  float M;           // mask value
+  float D;           // distance travelled so far 
+};
+//ETX
+
+class vtkmpjTensorArray { //;prevent man page generation
+public:
+  vtkmpjTensorArray();
+  ~vtkmpjTensorArray()
+  {
+    if (this->Array)
+      {
+        delete [] this->Array;
+      }
+  };
+  vtkIdType GetNumberOfPoints() {return this->MaxId + 1;};
+  vtkmpjTensorPoint *GetmpjTensorPoint(vtkIdType i) {return this->Array + i;};
+  vtkmpjTensorPoint *InsertNextmpjTensorPoint() 
+  {
+    if ( ++this->MaxId >= this->Size )
+      {
+	this->Resize(this->MaxId);
+      }
+    return this->Array + this->MaxId;
+  }
+  vtkmpjTensorPoint *Resize(vtkIdType sz); //reallocates data
+  void Reset() {this->MaxId = -1;};
+  
+  vtkmpjTensorPoint *Array;  // pointer to data
+  vtkIdType MaxId;          // maximum index inserted thus far
+  vtkIdType Size;          // allocated size of data
+  vtkIdType Extend;       // grow array by this amount
+  float Direction;       // integration direction
+};
+
+#define VTK_START_FROM_POSITION 0
+#define VTK_START_FROM_LOCATION 1
+
+vtkmpjTensorPoint::vtkmpjTensorPoint()
+{
+  this->V[0] = this->V0;
+  this->V[1] = this->V1;
+  this->V[2] = this->V2;
+}
+
+vtkmpjTensorPoint& vtkmpjTensorPoint::operator=(const vtkmpjTensorPoint& hp)
+{
+  int i, j;
+
+  for (i=0; i<3; i++) 
+    {
+      this->X[i] = hp.X[i];
+      this->P[i] = hp.P[i];
+      this->W[i] = hp.W[i];
+      for (j=0; j<3; j++)
+	{
+	  this->V[j][i] = hp.V[j][i];
+	}
+    }
+  
+  this->S = hp.S;
+  this->CellId = hp.CellId;
+  //  this->PointId = hp.PointId;
+  this->SubId = hp.SubId;
+  
+  this->D = hp.D;  
+  this->Angle = hp.Angle;
+  this->MD = hp.MD;
+  this->FA = hp.FA;
+  this->M = hp.M;
+  
+  return *this;
+}
+
+vtkmpjTensorArray::vtkmpjTensorArray()
+{
+  this->MaxId = -1; 
+  this->Array = new vtkmpjTensorPoint[1000];
+  this->Size = 1000;
+  this->Extend = 5000;
+  this->Direction = VTK_MPJ_INTEGRATE_FORWARD;
+}
+
+vtkmpjTensorPoint *vtkmpjTensorArray::Resize(vtkIdType sz)
+{
+  vtkmpjTensorPoint *newArray;
+  vtkIdType newSize, i;
+
+  if (sz >= this->Size)
+    {
+    newSize = this->Size + 
+      this->Extend*(((sz-this->Size)/this->Extend)+1);
+    }
+  else
+    {
+      newSize = sz;
+    }
+  
+  newArray = new vtkmpjTensorPoint[newSize];
+
+  for (i=0; i<sz; i++)
+    {
+    newArray[i] = this->Array[i];
+    }
+
+  this->Size = newSize;
+  delete [] this->Array;
+  this->Array = newArray;
+
+  return this->Array;
+}
+
+// Construct object with initial starting position (0,0,0); 
+vtkmpjTensorStreamline::vtkmpjTensorStreamline()
+{
+  this->StartFrom = VTK_START_FROM_POSITION;
+  this->StartPosition[0] = this->StartPosition[1] = this->StartPosition[2] = 0.0;
+  this->StartCell = 0;  
+  this->StartSubId = 0;
+  this->StartPCoords[0] = this->StartPCoords[1] = this->StartPCoords[2] = 0.5;
+
+  this->Streamers = NULL;
+
+  this->MaximumDistance = 100.0;
+  this->MinimumDistance = 5;
+  this->IntegrationStepLength = 0.2;
+  this->StepLength = 0.01;
+  this->IntegrationDirection = VTK_MPJ_INTEGRATE_FORWARD;
+
+  this->MaximumAngle = 90.0;
+  this->MinimumFA = 0.1;
+  this->MaximumFA = 1.0;
+  this->MinimumMD = 0.0;
+  this->MaximumMD = VTK_LARGE_FLOAT;
+  
+  this->FlipX = 0;
+  this->FlipY = 0;
+  this->FlipZ = 0;
+
+  this->IntegrationEigenvector = 0; //Major eigenvector
+  this->IntegrationOrder = VTK_MPJ_RUNGE_KUTTA2;
+
+  this->DirectionalColormap = 0;
+  this->DirectionalColorScheme = 0;
+  this->DirectionalColorSaturation = 0.5;
+  this->DirectionalColorScaling = 1.0;
+  this->DirectionalColorModulate = 0;
+  this->DirectionalColorAlphaBlending = 0;
+
+  this->Tensor = NULL;
+  this->Source = NULL;
+  this->Mask = NULL;
+}
+
+vtkmpjTensorStreamline::~vtkmpjTensorStreamline()
+{
+  if ( this->Streamers )
+    {
+      delete [] this->Streamers;
+    }
+  
+  // destroy source as well as inputs  
+  if (this->Tensor != NULL)
+    this->Tensor->Delete();
+  
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+  
+  if (this->Source != NULL)
+    this->Source->Delete();
+}
+
+// ----------------------------------------------------------------------------
+vtkDataSet *vtkmpjTensorStreamline::GetInput()
+{
+  return (vtkDataSet *)(this->Inputs[0]);
+}
+
+// Specify the start of the hyperstreamline in the cell coordinate system. 
+// That is, cellId and subId (if composite cell), and parametric coordinates.
+void vtkmpjTensorStreamline::SetStartLocation(vtkIdType cellId, int subId,
+                                          float pcoords[3])
+{
+  if ( cellId != this->StartCell || subId != this->StartSubId ||
+       pcoords[0] !=  this->StartPCoords[0] || 
+       pcoords[1] !=  this->StartPCoords[1] || 
+       pcoords[2] !=  this->StartPCoords[2] )
+    {
+    this->Modified();
+    this->StartFrom = VTK_START_FROM_LOCATION;
+
+    this->StartCell = cellId;
+    this->StartSubId = subId;
+    this->StartPCoords[0] = pcoords[0];
+    this->StartPCoords[1] = pcoords[1];
+    this->StartPCoords[2] = pcoords[2];
+    }
+}
+
+// Specify the start of the hyperstreamline in the cell coordinate system. 
+// That is, cellId and subId (if composite cell), and parametric coordinates.
+void vtkmpjTensorStreamline::SetStartLocation(vtkIdType cellId, int subId,
+                                          float r, float s, float t)
+{
+  float pcoords[3];
+  pcoords[0] = r;
+  pcoords[1] = s;
+  pcoords[2] = t;
+
+  this->SetStartLocation(cellId, subId, pcoords);
+}
+
+// Get the starting location of the hyperstreamline in the cell coordinate
+// system. Returns the cell that the starting point is in.
+vtkIdType vtkmpjTensorStreamline::GetStartLocation(int& subId, float pcoords[3])
+{
+  subId = this->StartSubId;
+  pcoords[0] = this->StartPCoords[0];
+  pcoords[1] = this->StartPCoords[1];
+  pcoords[2] = this->StartPCoords[2];
+  return this->StartCell;
+}
+
+// Specify the start of the hyperstreamline in the global coordinate system. 
+// Starting from position implies that a search must be performed to find 
+// initial cell to start integration from.
+void vtkmpjTensorStreamline::SetStartPosition(double x[3])
+{
+  if ( x[0] != this->StartPosition[0] || x[1] != this->StartPosition[1] || 
+  x[2] != this->StartPosition[2] )
+    {
+    this->Modified();
+    this->StartFrom = VTK_START_FROM_POSITION;
+
+    this->StartPosition[0] = x[0];
+    this->StartPosition[1] = x[1];
+    this->StartPosition[2] = x[2];
+    }
+}
+
+// Specify the start of the hyperstreamline in the global coordinate system. 
+// Starting from position implies that a search must be performed to find 
+// initial cell to start integration from.
+void vtkmpjTensorStreamline::SetStartPosition(double x, double y, double z)
+{
+  double pos[3];
+  pos[0] = x;
+  pos[1] = y;
+  pos[2] = z;
+
+  this->SetStartPosition(pos);
+}
+
+// Get the start position of the hyperstreamline in global x-y-z coordinates.
+double *vtkmpjTensorStreamline::GetStartPosition()
+{
+  return this->StartPosition;
+}
+
+// Use the major eigenvector field as the vector field through which to 
+// integrate. The major eigenvector is the eigenvector whose corresponding
+// eigenvalue is closest to positive infinity.
+void vtkmpjTensorStreamline::IntegrateMajorEigenvector()
+{
+  if ( this->IntegrationEigenvector != 0 )
+    {
+    this->Modified();
+    this->IntegrationEigenvector = 0;
+  }
+}
+
+// Use the major eigenvector field as the vector field through which to 
+// integrate. The major eigenvector is the eigenvector whose corresponding
+// eigenvalue is between the major and minor eigenvalues.
+void vtkmpjTensorStreamline::IntegrateMediumEigenvector()
+{
+  if ( this->IntegrationEigenvector != 1 )
+    {
+    this->Modified();
+    this->IntegrationEigenvector = 1;
+  }
+}
+
+// Use the major eigenvector field as the vector field through which to 
+// integrate. The major eigenvector is the eigenvector whose corresponding
+// eigenvalue is closest to negative infinity.
+void vtkmpjTensorStreamline::IntegrateMinorEigenvector()
+{
+  if ( this->IntegrationEigenvector != 2 )
+    {
+    this->Modified();
+    this->IntegrationEigenvector = 2;
+  }
+}
+
+// Make sure coordinate systems are consistent
+void vtkmpjTensorStreamline::FixVectors(double **prev, double **current, int iv, int ix, int iy)
+{
+  double p0[3], p1[3], p2[3];
+  double v0[3], v1[3], v2[3];
+  double temp[3];
+  int i;
+
+  float flip[3];
+  flip[0] = this->FlipX ? -1.0 : 1.0;
+  flip[1] = this->FlipY ? -1.0 : 1.0;
+  flip[2] = this->FlipZ ? -1.0 : 1.0;
+
+  for (i=0; i<3; i++)
+    {
+      v0[i] = (current[i][iv] *= flip[i]); 
+      v1[i] = (current[i][ix] *= flip[i]);
+      v2[i] = (current[i][iy] *= flip[i]);
+    }
+  
+  if ( prev == NULL ) //make sure coord system is right handed
+    {
+      vtkMath::Cross(v0,v1,temp);
+      if ( vtkMath::Dot(v2,temp) < 0.0 )
+	{
+	  for (i=0; i<3; i++)
+	    {
+	      current[i][iy] *= -1.0;
+	    }
+	}
+    }
+  
+  else //make sure vectors consistent from one point to the next
+    {
+      for (i=0; i<3; i++)
+	{
+	  p0[i] = prev[i][iv];
+	  p1[i] = prev[i][ix];
+	  p2[i] = prev[i][iy];
+	}
+      if ( vtkMath::Dot(p0,v0) < 0.0 )
+	{
+	  for (i=0; i<3; i++)
+	    {
+	      current[i][iv] *= -1.0;
+	    }
+	}
+      if ( vtkMath::Dot(p1,v1) < 0.0 )
+	{
+	  for (i=0; i<3; i++)
+	    {
+	      current[i][ix] *= -1.0;
+	    }
+	}
+      if ( vtkMath::Dot(p2,v2) < 0.0 )
+	{
+	  for (i=0; i<3; i++)
+	    {
+	      current[i][iy] *= -1.0;
+	    }
+	}
+    }
+}
+
+void vtkmpjTensorStreamline::Execute()
+{
+  vtkDataSet *input = this->GetInput();
+  vtkDataSet *source = this->Source;
+
+  vtkPointData *pdt=this->Tensor->GetPointData();
+
+  //  float *tensor;
+  vtkmpjTensorPoint *sNext, *sPtr;
+  int i, ptId, subId, offset, index, iv, ix, iy;
+  //int j, k;
+  vtkIdType numSourcePts, idx;
+  vtkCell *cell;
+  double ev[3], xNext[3];
+  float k1[3], k2[3], k3[3], k4[3];
+  //  float vort[3], derivs[9];
+  float d, step, dir, tol2;
+  double p[3];
+  double *w;
+  double dist2;
+  float angle;
+  float w0,w1,w2;
+  double closestPoint[3];
+  double *m[3], *v[3];
+  double m0[3], m1[3], m2[3];
+  double v0[3], v1[3], v2[3];
+
+  vtkDataArray *inMask = NULL;
+  vtkDataArray *cellMask = NULL;
+
+  if (this->Mask != NULL) {
+    inMask = this->Mask->GetPointData()->GetScalars();
+    cellMask = vtkDataArray::CreateDataArray(inMask->GetDataType());
+    cellMask->SetNumberOfComponents(1);
+    cellMask->SetNumberOfTuples(VTK_CELL_SIZE);
+  }
+  
+  vtkDataArray *inTensors;
+  vtkDataArray *inScalars;
+  vtkDataArray *cellTensors;
+  vtkDataArray *cellScalars;
+  
+  // set up working matrices
+  v[0] = v0; v[1] = v1; v[2] = v2; 
+  m[0] = m0; m[1] = m1; m[2] = m2; 
+  float rad2deg = 180.0 / vtkMath::Pi();
+  
+  this->NumberOfStreamers = 0;
+  w = new double[input->GetMaxCellSize()];
+  
+  inTensors = pdt->GetScalars();
+  cellTensors = vtkDataArray::CreateDataArray(inTensors->GetDataType());
+  
+  //    vtkPointData *pd = ((vtkDataSet *)this->Inputs[n])->GetPointData();
+  inScalars = this->GetInput()->GetPointData()->GetScalars();
+  cellScalars = vtkDataArray::CreateDataArray(inScalars->GetDataType());
+  cellScalars->SetNumberOfComponents(inScalars->GetNumberOfComponents());
+  cellScalars->SetNumberOfTuples(VTK_CELL_SIZE);
+  
+  int numTComp;
+  numTComp = inTensors->GetNumberOfComponents();
+  cellTensors->SetNumberOfComponents(numTComp);
+  cellTensors->SetNumberOfTuples(VTK_CELL_SIZE);
+  
+  tol2 = input->GetLength() / 1000.0;
+  tol2 = tol2 * tol2;
+  iv = this->IntegrationEigenvector;
+  ix = (iv + 1) % 3;
+  iy = (iv + 2) % 3;
+
+  //
+  // Create starting points
+  //
+  this->NumberOfStreamers = numSourcePts = offset = 1;
+  
+  if ( this->Source )
+    {
+      this->NumberOfStreamers = numSourcePts = this->Source->GetNumberOfPoints();
+    }
+  
+  if ( this->IntegrationDirection == VTK_MPJ_INTEGRATE_BOTH_DIRECTIONS )
+    {
+      offset = 2;
+      this->NumberOfStreamers *= 2;
+    }
+  
+  this->Streamers = new vtkmpjTensorArray[this->NumberOfStreamers];
+  
+  if ( this->StartFrom == VTK_START_FROM_POSITION && !this->Source )
+    {
+      sPtr = this->Streamers[0].InsertNextmpjTensorPoint();
+      for (i=0; i<3; i++)
+	{
+	  sPtr->X[i] = this->StartPosition[i];
+	}
+
+      sPtr->CellId = input->FindCell(this->StartPosition, NULL, -1, 0.0, 
+				     sPtr->SubId, sPtr->P, w);
+    }
+  else if ( this->StartFrom == VTK_START_FROM_LOCATION && !this->Source )
+    {
+      sPtr = this->Streamers[0].InsertNextmpjTensorPoint();
+      cell =  input->GetCell(sPtr->CellId);
+      cell->EvaluateLocation(sPtr->SubId, sPtr->P, sPtr->X, w);
+    }
+  
+  else //VTK_START_FROM_SOURCE
+    {      
+      for (ptId=0; ptId < numSourcePts; ptId++)
+	{
+	  sPtr = this->Streamers[offset*ptId].InsertNextmpjTensorPoint();
+	  source->GetPoint(ptId,sPtr->X);	  
+	  sPtr->CellId = input->FindCell(sPtr->X, NULL, -1, tol2, 
+					 sPtr->SubId, sPtr->P, w);
+	}
+    }
+  
+  //
+  // Finish initializing each hyperstreamline
+  //
+  for (idx=0, ptId=0; ptId < numSourcePts; ptId++)
+    {
+      this->Streamers[offset*ptId].Direction = 1.0;
+      sPtr = this->Streamers[offset*ptId].GetmpjTensorPoint(idx);
+      
+      sPtr->S = 0.0;
+      sPtr->D = 0.0;      
+      sPtr->Angle = 0.0;
+      
+      if ( sPtr->CellId >= 0 ) //starting point in dataset
+	{
+	  cell = input->GetCell(sPtr->CellId);
+	  cell->EvaluateLocation(sPtr->SubId, sPtr->P, xNext, w);
+	  
+	  inTensors->GetTuples(cell->PointIds, cellTensors);	  
+	  
+	  InterpolateTensor(cell, cellTensors, w, m);	  
+	  vtkMath::Jacobi(m, sPtr->W, sPtr->V);
+	  FixVectors(NULL, sPtr->V, iv, ix, iy);
+	  
+	  // compute MD and FA
+	  sPtr->MD = (sPtr->W[0] + sPtr->W[1] + sPtr->W[2]) / 3.0;
+	  w0 = sPtr->W[0] - sPtr->MD;
+	  w1 = sPtr->W[1] - sPtr->MD;
+	  w2 = sPtr->W[2] - sPtr->MD;
+	  sPtr->FA = sqrt(3*(w0*w0 + w1*w1 + w2*w2)) /
+	    sqrt(2*((sPtr->W[0])*(sPtr->W[0]) + 
+		    (sPtr->W[1])*(sPtr->W[1]) + 
+		    (sPtr->W[2])*(sPtr->W[2])));
+	  if (isnan(sPtr->FA)) {
+	    sPtr->FA = 0.0;
+	  }
+	  
+	  // compute scalar
+	  inScalars->GetTuples(cell->PointIds, cellScalars);
+
+	  for (sPtr->S=0, i=0; i < cell->GetNumberOfPoints(); i++)
+	    {
+	      sPtr->S += cellScalars->GetComponent(i,0) * w[i];
+	    }
+	  
+	  // select weight
+	  int wi=0;
+	  float wmax=0;
+	  for (i=0;i<cell->GetNumberOfPoints();i++)
+	    if (w[i] > wmax) {
+	      wi = i;  wmax = w[i];
+	    }
+	  
+	  // compute point id
+	  //	  sPtr->PointId = cell->GetPointId(wi);
+
+	  // compute mask value
+	  if (inMask != NULL) {	    
+	    inMask->GetTuples(cell->PointIds, cellMask);
+	    sPtr->M = cellMask->GetComponent(wi, 0);
+	  } else sPtr->M = 0;
+	  
+	} else {
+	  // zero it out
+	}
+      
+      if ( this->IntegrationDirection == VTK_MPJ_INTEGRATE_BOTH_DIRECTIONS )
+	{
+	  this->Streamers[offset*ptId+1].Direction = -1.0;
+	  sNext = this->Streamers[offset*ptId+1].InsertNextmpjTensorPoint();
+	  *sNext = *sPtr;
+	}
+      else if ( this->IntegrationDirection == VTK_MPJ_INTEGRATE_BACKWARD )
+	{
+	  this->Streamers[offset*ptId].Direction = -1.0;
+	}
+      
+    } //for hyperstreamline in dataset
+  
+  // Progress computation
+  int count = 0;
+  float pog = 0.0;
+  int tenth= (int)(this->NumberOfStreamers / 10.0);
+  
+  this->UpdateProgress(0.01);
+  
+  //
+  // For each hyperstreamline, integrate in appropriate direction (using RK2).
+  //
+  for (ptId=0; ptId < this->NumberOfStreamers; ptId++)
+    {
+      
+      // progress computation
+      count++;
+      if (count==tenth)
+        {
+          pog+=0.1;
+          this->UpdateProgress(pog);
+          count=0;
+        }
+
+      //get starting step
+      sPtr = this->Streamers[ptId].GetmpjTensorPoint(0);
+      if ( sPtr->CellId < 0 )
+	{
+	  continue;
+	}
+      
+      dir = this->Streamers[ptId].Direction;
+      cell = input->GetCell(sPtr->CellId);
+      cell->EvaluateLocation(sPtr->SubId, sPtr->P, xNext, w);
+      step = this->IntegrationStepLength * sqrt((double)cell->GetLength2());
+      inTensors->GetTuples(cell->PointIds, cellTensors);
+      inScalars->GetTuples(cell->PointIds, cellScalars);
+
+      //integrate until distance has been exceeded
+      while ( ( sPtr->CellId >= 0 ) && 
+	      ( sPtr->D < this->MaximumDistance ) &&
+	      ( sPtr->FA >= this->MinimumFA ) && ( sPtr->FA < this->MaximumFA ) &&
+	      ( sPtr->MD >= this->MinimumMD ) && ( sPtr->MD < this->MaximumMD ) &&
+	      ( sPtr->Angle < this->MaximumAngle ) )	
+	{	  
+
+	  // evaluate k2
+	  for (i=0; i<3; i++) {
+	    k1[i] = dir * step * sPtr->V[i][iv];
+	    xNext[i] = sPtr->X[i] + 0.5 * k1[i];
+	  }
+
+	  cell->EvaluatePosition(xNext, closestPoint, subId, p, dist2, w);
+	  
+	  InterpolateTensor(cell, cellTensors, w, m);
+	  vtkMath::Jacobi(m, ev, v);
+	  FixVectors(sPtr->V, v, iv, ix, iy);
+	  
+	  // evaluate k3
+	  for (i=0; i<3; i++) {
+	    k2[i] = dir * step * v[i][iv];
+	    xNext[i] = sPtr->X[i] + 0.5 * k2[i];
+	  }
+	  
+	  if ( this->IntegrationOrder == VTK_MPJ_RUNGE_KUTTA4 ) {	    
+	    cell->EvaluatePosition(xNext, closestPoint, subId, p, dist2, w);
+	    InterpolateTensor(cell, cellTensors, w, m);
+	    vtkMath::Jacobi(m, ev, v);
+	    FixVectors(sPtr->V, v, iv, ix, iy);
+	    
+	    // evaluate k4
+	    for (i=0; i<3; i++) {
+	      k3[i] = dir * step * v[i][iv];
+	      xNext[i] = sPtr->X[i] + 0.5 * k3[i];
+	    }
+	    
+	    cell->EvaluatePosition(xNext, closestPoint, subId, p, dist2, w);
+	    InterpolateTensor(cell, cellTensors, w, m);
+	    vtkMath::Jacobi(m, ev, v);
+	    FixVectors(sPtr->V, v, iv, ix, iy);
+	    
+	    for (i=0; i<3; i++) {
+	      k4[i] = dir * step * v[i][iv];
+	      
+	      //now compute final position
+	      xNext[i] = sPtr->X[i] + k1[i]/6.0 + k2[i]/3.0 + k3[i]/3.0 + k4[i]/6.0;
+	    }	    
+	  }
+	  
+	  // get a hold of the current index
+	  index = this->Streamers[ptId].GetNumberOfPoints();	  
+	  
+	  // insert next point
+	  sNext = this->Streamers[ptId].InsertNextmpjTensorPoint();
+	  
+	  // make sure sPtr is still valid after possible Resizing
+	  sPtr = this->Streamers[ptId].GetmpjTensorPoint(index-1);
+
+	  if ( cell->EvaluatePosition(xNext, closestPoint, sNext->SubId, 
+				      sNext->P, dist2, w) )
+	    { 
+	      //integration still in cell
+	      for (i=0; i<3; i++)
+		{
+		  sNext->X[i] = closestPoint[i];
+		}
+	      sNext->CellId = sPtr->CellId;
+	      sNext->SubId = sPtr->SubId;
+	    }
+	  else
+	    { //integration has passed out of cell
+	      sNext->CellId = input->FindCell(xNext, cell, sPtr->CellId, tol2, 
+					      sNext->SubId, sNext->P, w);
+	      if ( sNext->CellId >= 0 ) //make sure not out of dataset
+		{
+		  for (i=0; i<3; i++)
+		    {
+		      sNext->X[i] = xNext[i];
+		    }
+		  cell = input->GetCell(sNext->CellId);
+		  inTensors->GetTuples(cell->PointIds, cellTensors);
+		  inScalars->GetTuples(cell->PointIds, cellScalars);
+		  step = this->IntegrationStepLength * sqrt((double)cell->GetLength2());
+		} else {
+		}
+	    }
+	  
+	  if ( sNext->CellId >= 0 )
+	    {
+	      cell->EvaluateLocation(sNext->SubId, sNext->P, xNext, w);
+	      InterpolateTensor(cell, cellTensors, w, m);
+	      vtkMath::Jacobi(m, sNext->W, sNext->V);
+	      FixVectors(sPtr->V, sNext->V, iv, ix, iy);
+	      
+	      // interpolate scalars
+	      inScalars->GetTuples(cell->PointIds, cellScalars);
+	      for (sNext->S=0, i=0; i < cell->GetNumberOfPoints(); i++)
+		{
+		  sNext->S += cellScalars->GetComponent(i,0) * w[i];
+		}
+	      
+	      // select weight
+	      int wi=0;
+	      float wmax=0;
+	      for (i=0;i<cell->GetNumberOfPoints();i++)
+		if (w[i] > wmax) {
+		  wi = i;  wmax = w[i];
+		}
+
+	      // compute point id
+	      //	      sPtr->PointId = cell->GetPointId(wi);
+
+	      // interpolate mask value
+	      if (inMask != NULL) {
+		inMask->GetTuples(cell->PointIds, cellMask);
+		sNext->M = cellMask->GetComponent(wi, 0);
+	      }
+	      
+	      d = sqrt((double)vtkMath::Distance2BetweenPoints(sPtr->X,sNext->X));
+	      sNext->D = sPtr->D + d;   
+	      
+	      float v_old[3], v_new[3];;
+	      
+	      for (i=0;i<3;i++) {
+		v_old[i] = sPtr->V[i][iv];
+		v_new[i] = sNext->V[i][iv];
+	      }	      
+	      vtkMath::Normalize(v_old);
+	      vtkMath::Normalize(v_new);
+	      angle = vtkMath::Dot(v_old, v_new);	      
+	      if (angle > 1.0) angle = 1.0; 
+	      if (angle < -1.0) angle = -1.0;	      
+	      sNext->Angle = acos(angle) * rad2deg;
+	      
+	      // compute MD and FA
+	      sNext->MD = (sNext->W[0] + sNext->W[1] + sNext->W[2]) / 3.0;
+	      w0 = sNext->W[0] - sNext->MD;
+	      w1 = sNext->W[1] - sNext->MD;
+	      w2 = sNext->W[2] - sNext->MD;
+	      sNext->FA = sqrt(3*(w0*w0 + w1*w1 + w2*w2)) /
+		sqrt(2*((sNext->W[0])*(sNext->W[0]) + 
+			(sNext->W[1])*(sNext->W[1]) + 
+			(sNext->W[2])*(sNext->W[2])));	      	   
+	      if (isnan(sNext->FA)) {
+		sNext->FA = 0.0;
+		//printf("w0=%f,w1=%f,w1=%f,W0=%f,W1=%f,W2=%f\n",w0,w1,w2,sNext->W[0],sNext->W[1],sNext->W[2]);
+	      }
+
+	    } else {
+	      
+	      /* copy information from last point */
+	      *sNext = *sPtr;
+	      sNext->CellId = -1;
+	    }
+	  
+	  sPtr = sNext;
+	  
+	  /* printf("cellid=%d\n",sPtr->CellId);
+	     printf("S1[%d]=%f\n",this->TerminalScalarComponent1,sPtr->S[this->TerminalScalarComponent1]);
+	     printf("S2[%d]=%f\n",this->TerminalScalarComponent2,sPtr->S[this->TerminalScalarComponent2]);
+	     printf("TS1=%f\n",this->TerminalScalar1);
+	     printf("TS2=%f\n",this->TerminalScalar2);
+	     printf("D=%f, max=%f \n",sPtr->D,this->MaximumDistance);
+	     printf("Angle=%f max=%f\n",sPtr->Angle, this->MaximumAngle);*/
+
+	  
+	} //for elapsed time
+      
+    } //for each hyperstreamline
+
+  this->BuildPolylines();
+  
+  delete [] w;
+  cellTensors->Delete();
+  
+  cellScalars->Delete();    
+}
+
+void vtkmpjTensorStreamline::BuildPolylines()
+{
+  vtkPolyData *output = this->GetOutput();
+  vtkPointData *outPD = output->GetPointData();
+  
+  vtkPoints *newPts = vtkPoints::New();
+  vtkCellArray *newCells = vtkCellArray::New();
+  //vtkFloatArray *newScalars = vtkFloatArray::New();
+
+  vtkFloatArray *fa = vtkFloatArray::New();
+  fa->SetName("fractani");
+  fa->SetNumberOfComponents(1);
+
+  vtkFloatArray *md = vtkFloatArray::New();
+  md->SetName("meandiff");
+  md->SetNumberOfComponents(1);
+
+  vtkFloatArray *dist = vtkFloatArray::New();
+  dist->SetName("distance");
+  dist->SetNumberOfComponents(1);
+
+  vtkFloatArray *angle = vtkFloatArray::New();
+  angle->SetName("angle");
+  angle->SetNumberOfComponents(1);
+
+  vtkFloatArray *roi = vtkFloatArray::New();
+  roi->SetName("roi");
+  roi->SetNumberOfComponents(1);
+  
+  vtkFloatArray *other = vtkFloatArray::New();
+  other->SetName("other");
+  other->SetNumberOfComponents(1);
+  
+  vtkUnsignedCharArray *dec = vtkUnsignedCharArray::New();
+  dec->SetName("rgb");
+  dec->SetNumberOfComponents(this->DirectionalColorAlphaBlending ? 4 : 3);
+
+  int ptId, id, iv;
+  vtkmpjTensorPoint *sPtr, *sPtr2, *sNext;
+  double v[3];
+  float rgb[4];
+
+  iv = this->IntegrationEigenvector;
+
+  //newScalars->SetNumberOfComponents(1);
+  
+  for (ptId=0; ptId < this->NumberOfStreamers; ptId+=2)
+    {     
+      int numPts = this->Streamers[ptId].GetNumberOfPoints();
+      int numPts2 = this->Streamers[ptId+1].GetNumberOfPoints();
+      
+      //sPtr = this->Streamers[ptId].GetmpjTensorPoint(0);	
+      //if (ptId < this->NumberOfStreamers-1) {
+      //sNext = this->Streamers[ptId+1].GetmpjTensorPoint(0);	
+      //printf("pos1=%f,%f,%f\n",sPtr->X[0],sPtr->X[1],sPtr->X[2]);
+      //	printf("pos2=%f,%f,%f\n",sNext->X[0],sNext->X[1],sNext->X[2]);
+      //}
+
+      int numTotal = numPts + numPts2;
+      if ( numTotal >= 2 ) {
+	
+	// only keep fibers with minimum distance from seed
+	sPtr = this->Streamers[ptId].GetmpjTensorPoint(numPts-1);
+	sPtr2 = this->Streamers[ptId+1].GetmpjTensorPoint(numPts2-1);
+	
+	if ( (sPtr->D + sPtr2->D ) >= this->MinimumDistance ) {
+	  
+	  // allocate next cell
+	  newCells->InsertNextCell(numTotal-1);
+	  
+
+	  // first segment of the fiber
+	  //	  for(int i=0; i<numPts; i++) {
+	  for (int i=numPts-1; i>=0; i--) {
+	    
+	    sPtr = this->Streamers[ptId].GetmpjTensorPoint(i);	
+	  //	    sNext = this->Streamers[ptId].GetmpjTensorPoint(i+1);
+	    
+	    // insert next point
+	    id = newPts->InsertNextPoint(sPtr->X);
+	    
+	    // insert next cell
+	    newCells->InsertCellPoint(id);
+	    
+	    // insert scalars(s)
+	    //newScalars->InsertNextTuple(&sPtr->S);
+	    
+	    // insert fields
+	    fa->InsertNextTuple(&sPtr->FA);
+	    md->InsertNextTuple(&sPtr->MD);
+	    dist->InsertNextTuple(&sPtr->D);
+	    angle->InsertNextTuple(&sPtr->Angle);
+	    roi->InsertNextTuple(&sPtr->M);
+	    other->InsertNextTuple(&sPtr->S);	 
+
+	    // insert color coding
+	    if (this->DirectionalColormap) {
+	      
+	      v[0] = sPtr->V[0][iv]; 
+	      v[1] = sPtr->V[1][iv]; 
+	      v[2] = sPtr->V[2][iv];
+	      
+	      switch(this->DirectionalColorScheme) {
+	      case 1: 
+		this->RotationalSymmetryScheme(sPtr->FA, v, rgb);
+		break;
+	      case 2:
+		this->NoSymmetryScheme(sPtr->FA, v, rgb);
+		break;
+	      case 3:
+		this->MirrorSymmetryScheme(sPtr->FA, v, rgb);
+		break;
+	      default:		
+		this->AbsoluteValueScheme(sPtr->FA, v, rgb);
+	      }	
+	      
+	      if (this->DirectionalColorAlphaBlending)
+		rgb[3] = sPtr->FA*255;
+
+	      dec->InsertNextTuple(rgb);
+	    }
+	    
+	  }
+
+	  // second segment of the fiber
+	  for(int i=1; i<numPts2; i++) {
+
+	    sPtr = this->Streamers[ptId+1].GetmpjTensorPoint(i);
+
+	    // insert next point
+	    id = newPts->InsertNextPoint(sPtr->X);
+	    
+	    // insert next cell
+	    newCells->InsertCellPoint(id);
+	    
+	    // insert scalars(s)
+	    //newScalars->InsertNextTuple(&sPtr->S);
+	    
+	    // insert fields
+	    fa->InsertNextTuple(&sPtr->FA);
+	    md->InsertNextTuple(&sPtr->MD);
+	    dist->InsertNextTuple(&sPtr->D);
+	    angle->InsertNextTuple(&sPtr->Angle);
+	    roi->InsertNextTuple(&sPtr->M);
+	    other->InsertNextTuple(&sPtr->S);	 
+
+	    // insert color coding
+	    if (this->DirectionalColormap) {
+	      
+	      v[0] = sPtr->V[0][iv]; 
+	      v[1] = sPtr->V[1][iv]; 
+	      v[2] = sPtr->V[2][iv];
+
+	      switch(this->DirectionalColorScheme) {
+	      case 1: 
+		this->RotationalSymmetryScheme(sPtr->FA, v, rgb);
+		break;
+	      case 2:
+		this->NoSymmetryScheme(sPtr->FA, v, rgb);
+		break;
+	      case 3:
+		this->MirrorSymmetryScheme(sPtr->FA, v, rgb);
+		break;
+	      default:		
+		this->AbsoluteValueScheme(sPtr->FA, v, rgb);
+	      }
+	      
+	      if (this->DirectionalColorAlphaBlending) 
+		rgb[3] = sPtr->FA*255;
+
+	      dec->InsertNextTuple(rgb);
+	    }
+	    
+	  }
+	  
+	}
+      }
+    }
+    
+  //outPD->SetScalars(newScalars);
+  //  newScalars->Delete();
+  
+  outPD->AddArray(fa);
+  fa->Delete();
+
+  outPD->AddArray(md);
+  md->Delete();
+
+  outPD->AddArray(dist);
+  dist->Delete();
+
+  outPD->AddArray(angle);
+  angle->Delete();
+
+  outPD->AddArray(roi);
+  roi->Delete();
+  
+  outPD->AddArray(other);
+  other->Delete();
+
+  // insert color coding
+  if (this->DirectionalColormap) {
+    outPD->AddArray(dec);
+  }
+  dec->Delete();
+
+  output->SetPoints(newPts);
+  newPts->Delete();
+
+  output->SetLines(newCells);
+  newCells->Delete();
+}
+
+void vtkmpjTensorStreamline::InterpolateTensor(vtkCell *cell, vtkDataArray *cellTensors, double *w, double *m[3])
+{
+  int i, j, k;
+  double *tensor;
+    
+  // reset tensor
+  for (j=0; j<3; j++)
+    for (i=0; i<3; i++)
+      {
+	m[i][j] = 0.0;
+      }
+  
+  int numcomp=cellTensors->GetNumberOfComponents();
+
+  // interpolate tensor
+  for (k=0; k < cell->GetNumberOfPoints(); k++)
+    {
+      tensor = cellTensors->GetTuple(k);
+      
+      if (numcomp == 6) {
+
+	m[0][0] += tensor[0] * w[k];
+	m[1][0] += tensor[1] * w[k]; 
+	m[0][1] += tensor[1] * w[k];
+	m[2][0] += tensor[2] * w[k]; 
+	m[0][2] += tensor[2] * w[k];		
+	m[1][1] += tensor[3] * w[k]; 
+	m[2][1] += tensor[4] * w[k]; 
+	m[1][2] += tensor[4] * w[k];
+	m[2][2] += tensor[5] * w[k];			
+
+	//printf("%f %f %f %f %f %f -- ",m[0][0],m[1][0],m[2][0],m[1][1],m[2][1],m[2][2]);	
+
+      } else {
+	
+	m[0][0] += tensor[0] * w[k];
+	m[1][0] += tensor[1] * w[k]; 
+	m[0][1] += tensor[1] * w[k];
+	m[2][0] += tensor[2] * w[k]; 
+	m[0][2] += tensor[2] * w[k];	
+	m[1][1] += tensor[4] * w[k]; 
+	m[2][1] += tensor[5] * w[k]; 
+	m[1][2] += tensor[5] * w[k];
+	m[2][2] += tensor[8] * w[k];			
+
+	//printf("%f %f %f %f %f %f -- ",m[0][0],m[1][0],m[2][0],m[1][1],m[2][1],m[2][2]);	
+      } 	
+    }
+}
+
+void vtkmpjTensorStreamline::AbsoluteValueScheme(float FA, double v[3], float nrgb[3])
+{
+  float mgn;
+  float rgb[3];
+  float scale = this->DirectionalColorScaling;
+
+  rgb[0] = rgb[1] = rgb[2] = 0;
+  
+  rgb[0] = fabs(v[0]);
+  rgb[1] = fabs(v[1]);
+  rgb[2] = fabs(v[2]);
+  
+  /* compute color */
+  mgn = (this->DirectionalColorModulate ? FA : 1.0);
+
+  rgb[0] *= mgn;
+  rgb[1] *= mgn;
+  rgb[2] *= mgn;
+  
+  /* RGBs have to be in [0,255] */
+  nrgb[0] = rgb[0]*255*scale;
+  nrgb[1] = rgb[1]*255*scale;
+  nrgb[2] = rgb[2]*255*scale;
+  
+  nrgb[0] = nrgb[0] < 256 ? nrgb[0] : 255;
+  nrgb[1] = nrgb[1] < 256 ? nrgb[1] : 255;
+  nrgb[2] = nrgb[2] < 256 ? nrgb[2] : 255;
+  
+}
+
+void vtkmpjTensorStreamline::RotationalSymmetryScheme(float FA, double v[3], float nrgb[3])
+{
+
+  float rgb[3], hsv[3];
+  float theta, phi;
+  float vlenxy, vlen;
+  float pi = vtkMath::Pi();
+  float ps = this->DirectionalColorSaturation;
+  float scale = this->DirectionalColorScaling;
+
+  rgb[0] = rgb[1] = rgb[2] = 0;
+  
+  nrgb[0] = v[0];
+  nrgb[1] = v[1];
+  nrgb[2] = v[2];
+  
+  /* normalize vector */
+  vlenxy = vtkMath::Norm2D(v);
+
+  /* compute hue */
+  if (v[0] > 0)
+    phi = asin(v[1] / vlenxy);
+  else
+    phi = pi - asin(v[1] / vlenxy);
+  hsv[0] = fmod((phi+2*pi+pi/2)*2,2*pi) / (2*pi);
+  if (hsv[0] > 1.0) hsv[0] = 1.0;
+  
+  /* compute saturation */
+  vlen = vtkMath::Norm(v);
+  theta = asin(vlenxy / vlen);
+  if (theta > 1) theta = 1.0;
+  hsv[1] = sin(ps*theta) / sin(ps*pi/2);
+  
+  /* compute value */
+  hsv[2] = (this->DirectionalColorModulate ? FA : 1.0);
+  
+  vtkMath::HSVToRGB(hsv, rgb);
+
+  /* RGBs have to be in [0,255] */
+  nrgb[0] = rgb[0]*255+scale*nrgb[0];
+  nrgb[1] = rgb[1]*255+scale*nrgb[1];
+  nrgb[2] = rgb[2]*255+scale*nrgb[2];
+  
+  nrgb[0] = nrgb[0] < 256 ? nrgb[0] : 255;
+  nrgb[1] = nrgb[1] < 256 ? nrgb[1] : 255;
+  nrgb[2] = nrgb[2] < 256 ? nrgb[2] : 255;
+}
+
+
+void vtkmpjTensorStreamline::NoSymmetryScheme(float FA, double v[3], float nrgb[3])
+{
+  float rgb[3], hsv[3];
+  float theta, phi;
+  float vlenxy, vlen;
+  float pi = vtkMath::Pi();
+  float ps = this->DirectionalColorSaturation;
+  float scale = this->DirectionalColorScaling;
+  
+  rgb[0] = rgb[1] = rgb[2] = 0;
+  
+  nrgb[0] = v[0];
+  nrgb[1] = v[1];
+  nrgb[2] = v[2];
+
+  /* normalize vector */
+  vlenxy = vtkMath::Norm2D(v);
+  
+  /* compute hue */
+  if (v[0] > 0)
+    phi = asin(v[1] / vlenxy);
+  else
+    phi = pi - asin(v[1] / vlenxy);
+  hsv[0] = fmod(phi+2*pi,2*pi) / (2*pi);
+  if (hsv[0] > 1.0) hsv[0] = 1.0;
+  
+  /* compute saturation */
+  vlen = vtkMath::Norm(v);
+  theta = asin(vlenxy / vlen);
+  if (theta > 1) theta = 1.0;
+  hsv[1] = sin(ps*theta) / sin(ps*pi/2);
+    
+  /* compute value */
+  hsv[2] = (this->DirectionalColorModulate ? FA : 1.0);
+  
+  vtkMath::HSVToRGB(hsv, rgb);
+  
+  /* RGBs have to be in [0,255] */
+  nrgb[0] = rgb[0]*255+scale*nrgb[0];
+  nrgb[1] = rgb[1]*255+scale*nrgb[1];
+  nrgb[2] = rgb[2]*255+scale*nrgb[2];
+  
+  nrgb[0] = nrgb[0] < 256 ? nrgb[0] : 255;
+  nrgb[1] = nrgb[1] < 256 ? nrgb[1] : 255;
+  nrgb[2] = nrgb[2] < 256 ? nrgb[2] : 255;
+  
+}
+
+
+void vtkmpjTensorStreamline::MirrorSymmetryScheme(float FA, double v[3], float nrgb[3])
+{
+  float rgb[3], hsv[3];
+  float theta, phi;
+  float vlenxy, vlen;
+  float pi = vtkMath::Pi();
+  float ps = this->DirectionalColorSaturation;
+  float scale = this->DirectionalColorScaling;
+
+  rgb[0] = rgb[1] = rgb[2] = 0;
+  
+  nrgb[0] = v[0];
+  nrgb[1] = v[1];
+  nrgb[2] = v[2];
+  
+  /* normalize vector */
+  vlenxy = vtkMath::Norm2D(v);
+  
+  /* compute hue */
+  if (v[0] > 0)
+    phi = asin(v[1] / vlenxy);
+  else
+    phi = pi + asin(v[1] / vlenxy);
+  hsv[0] = 2 * fmod(phi + pi, pi) / (2*pi);
+  if (hsv[0] > 1.0) hsv[0] = 1.0;
+  
+  /* compute saturation */
+  vlen = vtkMath::Norm(v);
+  theta = asin(vlenxy / vlen);
+  if (theta > 1) theta = 1.0;
+  hsv[1] = sin(ps*theta) / sin(ps*pi/2);
+  
+  /* compute value */
+  hsv[2] = (this->DirectionalColorModulate ? FA : 1.0);
+  
+  vtkMath::HSVToRGB(hsv, rgb);
+  
+  /* RGBs have to be in [0,255] */
+  nrgb[0] = rgb[0]*255+scale*nrgb[0];
+  nrgb[1] = rgb[1]*255+scale*nrgb[1];
+  nrgb[2] = rgb[2]*255+scale*nrgb[2];
+  
+  nrgb[0] = nrgb[0] < 256 ? nrgb[0] : 255;
+  nrgb[1] = nrgb[1] < 256 ? nrgb[1] : 255;
+  nrgb[2] = nrgb[2] < 256 ? nrgb[2] : 255;
+}
+
+void vtkmpjTensorStreamline::PrintSelf(ostream& os, vtkIndent indent)
+{
+  vtkDataSetToPolyDataFilter::PrintSelf(os,indent);
+
+  if ( this->StartFrom == VTK_START_FROM_POSITION )
+    {
+    os << indent << "Starting Position: (" << this->StartPosition[0] << ","
+       << this->StartPosition[1] << ", " << this->StartPosition[2] << ")\n";
+    }
+  else 
+    {
+    os << indent << "Starting Location:\n\tCell: " << this->StartCell 
+       << "\n\tSubId: " << this->StartSubId << "\n\tP.Coordinates: ("
+       << this->StartPCoords[0] << ", " 
+       << this->StartPCoords[1] << ", " 
+       << this->StartPCoords[2] << ")\n";
+    }
+
+  os << indent << "Maximum Propagation Distance: " 
+     << this->MaximumDistance << "\n";
+
+  if ( this->IntegrationDirection == VTK_MPJ_INTEGRATE_FORWARD )
+    {
+    os << indent << "Integration Direction: FORWARD\n";
+    }
+  else if ( this->IntegrationDirection == VTK_MPJ_INTEGRATE_BACKWARD )
+    {
+    os << indent << "Integration Direction: BACKWARD\n";
+    }
+  else
+    {
+    os << indent << "Integration Direction: FORWARD & BACKWARD\n";
+    }
+
+  os << indent << "Integration Step Length: " << this->IntegrationStepLength << "\n";
+  os << indent << "Step Length: " << this->StepLength << "\n";
+
+  if ( this->IntegrationEigenvector == 0 )
+    {
+    os << indent << "Integrate Along Major Eigenvector\n";
+    }
+  else if ( this->IntegrationEigenvector == 1 )
+    {
+    os << indent << "Integrate Along Medium Eigenvector\n";
+    }
+  else
+    {
+    os << indent << "Integrate Along Minor Eigenvector\n";
+    }
+}
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamline.h b/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamline.h
new file mode 100644
index 0000000..2635827
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamline.h
@@ -0,0 +1,334 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjTensorStreamline_h
+#define __vtkmpjTensorStreamline_h
+
+#include "vtkDataSetToPolyDataFilter.h"
+#include "vtkPolyData.h"
+#include "vtkDataSet.h"
+#include "vtkPointData.h"
+#include "vtkCellArray.h"
+#include "vtkImageData.h"
+
+#define VTK_MPJ_RUNGE_KUTTA2 0
+#define VTK_MPJ_RUNGE_KUTTA4 1
+
+#define VTK_MPJ_INTEGRATE_FORWARD 0
+#define VTK_MPJ_INTEGRATE_BACKWARD 1
+#define VTK_MPJ_INTEGRATE_BOTH_DIRECTIONS 2
+
+class vtkmpjTensorArray;
+
+class vtkmpjTensorStreamline : public vtkDataSetToPolyDataFilter
+{
+public:
+  vtkTypeMacro(vtkmpjTensorStreamline,vtkDataSetToPolyDataFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Construct object with initial starting position (0,0,0); integration
+  // step length 0.2; step length 0.01; forward integration; terminal
+  // eigenvalue 0.0; number of sides 6; radius 0.5; and logarithmic scaling
+  // off.
+  static vtkmpjTensorStreamline *New();
+  
+  // Description:
+  // Get one input to this filter
+  vtkDataSet *GetInput();
+
+  // Description:
+  // Specify the start of the hyperstreamline in the cell coordinate system. 
+  // That is, cellId and subId (if composite cell), and parametric coordinates.
+  void SetStartLocation(vtkIdType cellId, int subId, float pcoords[3]);
+ 
+  // Description:
+  // Specify the start of the hyperstreamline in the cell coordinate system. 
+  // That is, cellId and subId (if composite cell), and parametric coordinates.
+  void SetStartLocation(vtkIdType cellId, int subId, float r, float s,
+                        float t);
+
+  // Description:
+  // Get the starting location of the hyperstreamline in the cell coordinate
+  // system. Returns the cell that the starting point is in.
+  vtkIdType GetStartLocation(int& subId, float pcoords[3]);
+
+  // Description:
+  // Specify the start of the hyperstreamline in the global coordinate system. 
+  // Starting from position implies that a search must be performed to find 
+  // initial cell to start integration from.
+  void SetStartPosition(double x[3]);
+
+  // Description:
+  // Specify the start of the hyperstreamline in the global coordinate system. 
+  // Starting from position implies that a search must be performed to find 
+  // initial cell to start integration from.
+  void SetStartPosition(double x, double y, double z);
+
+  // Description:
+  // Get the start position of the hyperstreamline in global x-y-z coordinates.
+  double *GetStartPosition();
+
+  // Description:
+  // Use the major eigenvector field as the vector field through which to 
+  // integrate. The major eigenvector is the eigenvector whose corresponding
+  // eigenvalue is closest to positive infinity.
+  void IntegrateMajorEigenvector();
+
+  // Description:
+  // Use the major eigenvector field as the vector field through which to 
+  // integrate. The major eigenvector is the eigenvector whose corresponding
+  // eigenvalue is between the major and minor eigenvalues.
+  void IntegrateMediumEigenvector();
+
+  // Description:
+  // Use the major eigenvector field as the vector field through which to 
+  // integrate. The major eigenvector is the eigenvector whose corresponding
+  // eigenvalue is closest to negative infinity.
+  void IntegrateMinorEigenvector();
+
+  // Description:
+  // Set / get the maximum length of the hyperstreamline expressed as absolute
+  // distance (i.e., arc length) value.
+  vtkSetClampMacro(MaximumDistance,float,0.0,VTK_LARGE_FLOAT);
+  vtkGetMacro(MaximumDistance,float);
+  
+  // Description:
+  // Set / get the minimum length of the hyperstreamline expressed as absolute
+  // distance (i.e., arc length) value.
+  vtkSetClampMacro(MinimumDistance,float,0.0,VTK_LARGE_FLOAT);
+  vtkGetMacro(MinimumDistance,float);
+
+  // Description:
+  // Set / Get the maximum angle of streamline.
+  vtkSetClampMacro(MaximumAngle,float,0.0,VTK_LARGE_FLOAT);
+  vtkGetMacro(MaximumAngle,float);
+
+  // Description:
+  // Set/Get Integration order
+  vtkSetClampMacro(IntegrationOrder,int,0,1);
+  vtkGetMacro(IntegrationOrder,int);
+  
+  // Description:
+  // Set / get a nominal integration step size (expressed as a fraction of
+  // the size of each cell).
+  vtkSetClampMacro(IntegrationStepLength,float,0.001,0.5);
+  vtkGetMacro(IntegrationStepLength,float);
+
+  // Description:
+  // Set / get the length of a tube segment composing the hyperstreamline. The
+  // length is specified as a fraction of the diagonal length of the input
+  // bounding box.
+  vtkSetClampMacro(StepLength,float,0.000001,1.0);
+  vtkGetMacro(StepLength,float);
+  
+  // Description:
+  // Set/Get Min FA
+  vtkSetClampMacro(MinimumFA,float,0.0,1.0);
+  vtkGetMacro(MinimumFA,float);
+  
+  // Description:
+  // Set/Get Max FA
+  vtkSetClampMacro(MaximumFA,float,0.0,1.0);
+  vtkGetMacro(MaximumFA,float);
+  
+  // Description:
+  // Set/Get Min MD
+  vtkSetClampMacro(MinimumMD,float,0.0,VTK_LARGE_FLOAT);
+  vtkGetMacro(MinimumMD,float);
+  
+  // Description:
+  // Set/Get Max MD
+  vtkSetClampMacro(MaximumMD,float,0.0,VTK_LARGE_FLOAT);
+  vtkGetMacro(MaximumMD,float);
+  
+  // Description: whether to flip the sign of the x-coordinate 
+  vtkSetMacro(FlipX,int);
+  vtkGetMacro(FlipX,int);
+  vtkBooleanMacro(FlipX,int);
+  
+  // Description: whether to flip the sign of the y-coordinate
+  vtkSetMacro(FlipY,int);
+  vtkGetMacro(FlipY,int);
+  vtkBooleanMacro(FlipY,int);
+  
+  // Description: whether to flip the sign of the z-coordinate
+  vtkSetMacro(FlipZ,int);
+  vtkGetMacro(FlipZ,int);
+  vtkBooleanMacro(FlipZ,int);
+ 
+
+  // Description: enable/disable directional color coding
+  vtkSetMacro(DirectionalColormap, int);
+  vtkGetMacro(DirectionalColormap, int);
+  vtkBooleanMacro(DirectionalColormap, int);
+  
+  // Description: determine type of color scheme to use
+  vtkSetMacro(DirectionalColorScheme, int);
+  vtkGetMacro(DirectionalColorScheme, int);
+
+  // Description: color saturation
+  vtkSetMacro(DirectionalColorSaturation, float);
+  vtkGetMacro(DirectionalColorSaturation, float);
+  
+  // Description: intensity scaling
+  vtkSetMacro(DirectionalColorScaling, float);
+  vtkGetMacro(DirectionalColorScaling, float);
+
+  // Description: magnitude component
+  vtkSetMacro(DirectionalColorModulate, int);
+  vtkGetMacro(DirectionalColorModulate, int);
+   	      
+  // Description: enable/disable fiber transparency
+  vtkSetMacro(DirectionalColorAlphaBlending, int);
+  vtkGetMacro(DirectionalColorAlphaBlending, int);
+  
+  // Description:
+  // Specify the direction in which to integrate the hyperstreamline.
+  vtkSetClampMacro(IntegrationDirection,int,
+		   VTK_MPJ_INTEGRATE_FORWARD,VTK_MPJ_INTEGRATE_BOTH_DIRECTIONS);
+  vtkGetMacro(IntegrationDirection,int);
+
+  void SetIntegrationDirectionToForward()
+    {this->SetIntegrationDirection(VTK_MPJ_INTEGRATE_FORWARD);};
+  void SetIntegrationDirectionToBackward()
+    {this->SetIntegrationDirection(VTK_MPJ_INTEGRATE_BACKWARD);};
+  void SetIntegrationDirectionToIntegrateBothDirections()
+    {this->SetIntegrationDirection(VTK_MPJ_INTEGRATE_BOTH_DIRECTIONS);};
+  
+  void SetIntegrationOrderToRungeKutta2() {this->SetIntegrationOrder(VTK_MPJ_RUNGE_KUTTA2);};
+  void SetIntegrationOrderToRungeKutta4() {this->SetIntegrationOrder(VTK_MPJ_RUNGE_KUTTA4);};
+  
+  // Description:
+  // Set/Get Tensor
+  vtkSetObjectMacro(Tensor, vtkImageData);
+  vtkGetObjectMacro(Tensor, vtkImageData);
+
+  // Description:
+  // Set/Get Mask
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+  
+  // Description:
+  // Set/Get Source points
+  vtkGetObjectMacro(Source, vtkDataSet);
+  vtkSetObjectMacro(Source, vtkDataSet);
+  
+protected:
+  vtkDataSet *Source;
+  vtkImageData *Tensor;
+  vtkImageData *Mask;
+   
+  vtkmpjTensorStreamline();
+  ~vtkmpjTensorStreamline();
+
+  // Integrate data
+  void Execute();
+  void BuildPolylines();
+  void InterpolateTensor(vtkCell *cell, vtkDataArray *cellTensors, double *w, double *m[3]);
+  void FixVectors(double **prev, double **current, int iv, int ix, int iy);
+
+
+  // Directional colormap support functions
+  void AbsoluteValueScheme(float FA, double v[3], float nrgb[3]);
+  void RotationalSymmetryScheme(float FA, double v[3], float nrgb[3]);
+  void NoSymmetryScheme(float FA, double v[3], float nrgb[3]);
+  void MirrorSymmetryScheme(float FA, double v[3], float nrgb[3]);
+
+  // Flag indicates where streamlines start from (either position or location)
+  int StartFrom;
+  
+  // Starting from cell location
+  vtkIdType StartCell;
+  int StartSubId;
+
+  float StartPCoords[3];
+
+  // starting from global x-y-z position
+  double StartPosition[3];
+
+  //array of hyperstreamlines
+  vtkmpjTensorArray *Streamers;
+  int NumberOfStreamers;
+  
+  // max length of hyperstreamline in absolute distance
+  float MaximumDistance;
+  
+  // min length of hyperstreamline
+  float MinimumDistance;
+  
+  // integration direction
+  int IntegrationDirection;
+
+  // colorcoding
+  int DirectionalColormap;
+  int DirectionalColorScheme;
+  float DirectionalColorSaturation;
+  float DirectionalColorScaling;
+  int DirectionalColorModulate;
+  int DirectionalColorAlphaBlending;
+
+  // the length (fraction of cell size) of integration steps
+  float IntegrationStepLength;
+  
+  // Runge-Kutta integration order
+  int IntegrationOrder;
+
+  // the length of the tube segments composing the hyperstreamline
+  float StepLength;
+
+  // minimum and maximum anisotropy
+  float MinimumFA;
+  float MaximumFA;
+
+  // minimum and maximum mean diffusivity
+  float MinimumMD;
+  float MaximumMD;
+  
+  // maximum streamline angle
+  float MaximumAngle;
+  
+  // which eigenvector to use as integration vector field
+  int IntegrationEigenvector;
+
+  int FlipX;
+  int FlipY;
+  int FlipZ;
+
+ private:
+  vtkmpjTensorStreamline(const vtkmpjTensorStreamline&);  // Not implemented.
+  void operator=(const vtkmpjTensorStreamline&);  // Not implemented.
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamlineRegionFilter.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamlineRegionFilter.cpp
new file mode 100644
index 0000000..e0b3224
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamlineRegionFilter.cpp
@@ -0,0 +1,235 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjTensorStreamlineRegionFilter.h"
+
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkPolyLine.h"
+
+vtkStandardNewMacro(vtkmpjTensorStreamlineRegionFilter);
+
+// Construct object 
+vtkmpjTensorStreamlineRegionFilter::vtkmpjTensorStreamlineRegionFilter()
+{
+  this->RegionNumber1 = 0;
+  this->RegionNumber2 = 0;
+  this->Clipping = 0;
+}
+
+void vtkmpjTensorStreamlineRegionFilter::Execute()
+{
+  vtkPolyData *input = this->GetInput();
+  vtkPolyData *output = this->GetOutput();
+  vtkPointData *pd=input->GetPointData();
+
+  vtkPointData *outPD=output->GetPointData();
+  vtkCellArray *inLines = NULL;
+
+  vtkPoints *inPts;
+  vtkIdType numPts = 0;
+  vtkIdType numLines;
+    
+  float faval;
+  float mdval;
+  float distval;
+  float angleval;
+  float roival;
+  float otherval;
+
+  vtkIdType npts=0, *pts=NULL;
+  int id, abort=0;
+  vtkIdType inCellId;
+
+  vtkDataArray *fa = pd->GetArray("fractani");
+  vtkDataArray *md = pd->GetArray("meandiff");
+  vtkDataArray *dist = pd->GetArray("distance");
+  vtkDataArray *angle = pd->GetArray("angle");  
+  vtkDataArray *roi = pd->GetArray("roi");
+  vtkDataArray *other = pd->GetArray("other");
+ 
+  // Check input and initialize
+  //  
+  if ( !(inPts=input->GetPoints()) || 
+       (numPts = inPts->GetNumberOfPoints()) < 1 ||
+       !(inLines = input->GetLines()) || 
+       (numLines = inLines->GetNumberOfCells()) < 1 )
+    {
+      return;
+    }
+  
+  // Create output data
+  vtkPoints *newPts = vtkPoints::New();
+  vtkCellArray *newCells = vtkCellArray::New();
+
+  vtkFloatArray *newfa = vtkFloatArray::New();
+  newfa->SetName("fractani");
+  newfa->SetNumberOfComponents(1);
+
+  vtkFloatArray *newmd = vtkFloatArray::New();
+  newmd->SetName("meandiff");
+  newmd->SetNumberOfComponents(1);
+
+  vtkFloatArray *newdist = vtkFloatArray::New();
+  newdist->SetName("distance");
+  newdist->SetNumberOfComponents(1);
+
+  vtkFloatArray *newangle = vtkFloatArray::New();
+  newangle->SetName("angle");
+  newangle->SetNumberOfComponents(1);
+
+  vtkFloatArray *newroi = vtkFloatArray::New();
+  newroi->SetName("roi");
+  newroi->SetNumberOfComponents(1);
+
+  vtkFloatArray *newother = vtkFloatArray::New();
+  newother->SetName("other");
+  newother->SetNumberOfComponents(1);
+
+  for (inCellId=0, inLines->InitTraversal(); 
+       inLines->GetNextCell(npts,pts) && !abort; inCellId++)
+    {
+      this->UpdateProgress((float)inCellId/numLines);
+      abort = this->GetAbortExecute();
+      
+      if (npts < 2)
+	{
+	  vtkWarningMacro(<< "Less than two points in line!");
+	  continue; //skip filtering this line
+	}
+
+      //      int index=-1;
+      
+      // traverse polyline and search for roi crossing
+      /*for(int i=0; i<npts; i++) {	  
+ 	roival = roi->GetTuple1(pts[i]);	  
+	if (roival == this->RegionNumber)
+	{ index=i; break; }
+	}*/
+      
+      // back-traverse polyline searching for ROI crossing
+      //for(int i=npts-1; i>=0; i--) {	  
+      //roival = roi->GetTuple1(pts[i]);	  
+      //if (roival == this->RegionNumber)
+      //  { index=i; break; }
+      //}
+      
+      int index1=-1, index2=-1;
+
+      // navigate polylines
+      for(int i=0; i<npts; i++) {	  
+ 	roival = roi->GetTuple1(pts[i]);	  
+	if (roival == this->RegionNumber1)
+	  { index1=i; }
+	if (roival == this->RegionNumber2)
+	  { index2=i; }
+      }
+
+      // check if fiber crosses both ROIs
+      if ((index1 >= 0) && (index2 >= 0)) {
+	
+	int startindex = 0;
+	int endindex = npts-1;
+	int NumNewPts = npts;
+	
+	if (this->Clipping) {
+	  if (index1 > index2) {
+	    startindex=index2; endindex=index1;
+	    NumNewPts = index1 - index2 + 1;
+	  } else {
+	    startindex=index1; endindex=index2;	    
+	    NumNewPts = index2 - index1 + 1;
+	  }	    
+	}	
+	
+	// allocate next cell
+	newCells->InsertNextCell(NumNewPts);
+	
+	// create new polyline
+	for(int i=startindex; i<=endindex; i++) {
+	  
+	  faval = fa->GetTuple1(pts[i]);
+	  mdval = md->GetTuple1(pts[i]);
+	  distval = dist->GetTuple1(pts[i]);
+	  angleval = angle->GetTuple1(pts[i]);
+	  roival = roi->GetTuple1(pts[i]);
+	  otherval = other->GetTuple1(pts[i]);
+	  
+	  id = newPts->InsertNextPoint(inPts->GetPoint(pts[i]));
+	  
+	  // insert next cell
+	  newCells->InsertCellPoint(id);
+	  
+	  // insert fields
+	  newfa->InsertNextTuple(&faval);
+	  newmd->InsertNextTuple(&mdval);
+	  newdist->InsertNextTuple(&distval);
+	  newangle->InsertNextTuple(&angleval);
+	  newroi->InsertNextTuple(&roival);
+	  newother->InsertNextTuple(&otherval);	 
+	}
+	
+      } // end if(index >= 0) ...
+
+    }
+
+  outPD->AddArray(newfa);
+  newfa->Delete();
+  
+  outPD->AddArray(md);
+  newmd->Delete();
+  
+  outPD->AddArray(newdist);
+  newdist->Delete();
+
+  outPD->AddArray(newangle);
+  newangle->Delete();
+
+  outPD->AddArray(newroi);
+  newroi->Delete();
+  
+  outPD->AddArray(newother);
+  newother->Delete();
+
+  output->SetPoints(newPts);
+  newPts->Delete();
+
+  output->SetLines(newCells);
+  newCells->Delete();
+
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamlineRegionFilter.h b/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamlineRegionFilter.h
new file mode 100644
index 0000000..bad8ec0
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamlineRegionFilter.h
@@ -0,0 +1,82 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjTensorStreamlineRegionFilter_h
+#define __vtkmpjTensorStreamlineRegionFilter_h
+
+#include "vtkPolyDataToPolyDataFilter.h"
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkDataArray.h"
+#include "vtkFloatArray.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+
+class vtkmpjTensorStreamlineRegionFilter : public vtkPolyDataToPolyDataFilter
+{
+public:
+  vtkTypeMacro(vtkmpjTensorStreamlineRegionFilter,vtkPolyDataToPolyDataFilter);
+
+  // Description:
+  // Construct object 
+  static vtkmpjTensorStreamlineRegionFilter *New();
+
+  // Set/Get ROI 1 constraint
+  vtkSetClampMacro(RegionNumber1,int,0,100);
+  vtkGetMacro(RegionNumber1,int);
+
+  // Set/Get ROI 2 constraint
+  vtkSetClampMacro(RegionNumber2,int,0,100);
+  vtkGetMacro(RegionNumber2,int);
+
+  // Set/Get Clipping
+  vtkSetClampMacro(Clipping,int,0,1);
+  vtkGetMacro(Clipping,int);
+  vtkBooleanMacro(Clipping,int);
+  
+ protected:
+  vtkmpjTensorStreamlineRegionFilter();
+  ~vtkmpjTensorStreamlineRegionFilter() {}
+  
+  // Usual data generation method
+  void Execute();
+
+  int RegionNumber1;
+  int RegionNumber2;
+  int Clipping;
+
+private:
+  vtkmpjTensorStreamlineRegionFilter(const vtkmpjTensorStreamlineRegionFilter&);// Not implemented.
+  void operator=(const vtkmpjTensorStreamlineRegionFilter&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamlineStatistics.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamlineStatistics.cpp
new file mode 100644
index 0000000..dce7af9
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamlineStatistics.cpp
@@ -0,0 +1,274 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjTensorStreamlineStatistics.h"
+
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkPolyLine.h"
+
+vtkStandardNewMacro(vtkmpjTensorStreamlineStatistics);
+
+// Construct object 
+vtkmpjTensorStreamlineStatistics::vtkmpjTensorStreamlineStatistics()
+{
+  this->NumberOfFibers = 0;
+
+  // min/max/mean/variance
+  for(int i=0;i<4;i++) {
+    this->Anisotropy[i] = 0.0;
+    this->Diffusivity[i] = 0.0;
+    this->Distance[i] = 0.0;
+    this->Angle[i] = 0.0;
+    this->Other[i] = 0.0;
+  }
+  
+}
+
+void vtkmpjTensorStreamlineStatistics::Execute()
+{
+  vtkPolyData *input = this->GetInput();
+  //vtkPolyData *output = this->GetOutput();
+  vtkPointData *pd=input->GetPointData();
+  
+  //vtkPointData *outPD=output->GetPointData();
+  vtkCellArray *inLines = NULL;
+  
+  vtkPoints *inPts;
+  vtkIdType numPts = 0;
+  vtkIdType numLines;
+  
+  float fractanisum, fractanisumsqr;
+  float meandiffsum, meandiffsumsqr;
+  float distancesum, distancesumsqr;
+  float anglesum, anglesumsqr;
+  float othersum, othersumsqr;
+
+  vtkIdType npts=0, *pts=NULL;
+  int abort=0;
+  vtkIdType inCellId;
+
+  vtkDataArray *fa = pd->GetArray("fractani");
+  vtkDataArray *md = pd->GetArray("meandiff");
+  vtkDataArray *dist = pd->GetArray("distance");
+  vtkDataArray *angle = pd->GetArray("angle");  
+  vtkDataArray *other = pd->GetArray("other");
+ 
+  // Check input and initialize
+  //  
+  if ( !(inPts=input->GetPoints()) || 
+       (numPts = inPts->GetNumberOfPoints()) < 1 ||
+       !(inLines = input->GetLines()) || 
+       (numLines = inLines->GetNumberOfCells()) < 1 )
+    {
+      return;
+    }
+  
+  float* fractani_array = new float[numLines];
+  float* meandiff_array = new float[numLines];
+  float* distance_array = new float[numLines];
+  float* angle_array = new float[numLines];
+  float* other_array = new float[numLines]; 
+  
+  for (inCellId=0, inLines->InitTraversal(); 
+       inLines->GetNextCell(npts,pts) && !abort; inCellId++)
+    {
+      this->UpdateProgress((float)inCellId/numLines);
+      abort = this->GetAbortExecute();
+
+      if (npts > 1) {
+	
+	fractanisum = 0.0; 
+	meandiffsum = 0.0; 
+	anglesum = 0.0; 
+	othersum = 0.0;
+	
+	// compute statistics for fiber
+	for(int i=0; i<npts; i++) {	
+		  
+	  fractanisum += fa->GetTuple1(pts[i]);
+	  meandiffsum += md->GetTuple1(pts[i]);
+	  anglesum += angle->GetTuple1(pts[i]);
+	  othersum += other->GetTuple1(pts[i]);	  
+
+	  //	  printf("fasum=%f, osum=%f\n",fractanisum, othersum);
+
+	  //	  printf("anglesum=%f,%f\n",anglesum,angle->GetTuple1(pts[i]));
+
+	}
+	
+	// compute mean values for fiber
+	fractanisum /= (float)npts;
+	meandiffsum /= (float)npts;
+	anglesum /= (float)npts;
+	othersum /= (float)npts;
+	
+	// store values
+	fractani_array[inCellId] = fractanisum;
+	meandiff_array[inCellId] = meandiffsum;
+	distance_array[inCellId] = dist->GetTuple1(pts[npts-1]);
+	angle_array[inCellId] = anglesum;
+	other_array[inCellId] = othersum;
+
+      } else {
+	printf("npts=%d\n",npts);
+      }
+      
+    }
+  
+  this->NumberOfFibers = numLines;
+
+  fractanisum = 0.0; fractanisumsqr = 0.0;
+  meandiffsum = 0.0; meandiffsumsqr = 0.0;
+  distancesum = 0.0; distancesumsqr = 0.0;
+  anglesum = 0.0; anglesumsqr = 0.0;
+  othersum = 0.0; othersumsqr = 0;
+  
+  this->Anisotropy[0] = fractani_array[0];  // min FA
+  this->Anisotropy[1] = fractani_array[0];  // max FA
+  
+  this->Diffusivity[0] = meandiff_array[0];  // min MD
+  this->Diffusivity[1] = meandiff_array[0];  // max MD
+  
+  this->Distance[0] = distance_array[0];  // min distance
+  this->Distance[1] = distance_array[0];  // max distance
+  
+  this->Angle[0] = angle_array[0];  // min angle
+  this->Angle[1] = angle_array[0];  // max angle
+
+  this->Other[0] = other_array[0];  // min other
+  this->Other[1] = other_array[0];  // max other
+
+  // compute statistics for the bundle
+  for(int i=0; i<numLines; i++) {
+    
+    // min/max
+    if ( fractani_array[i] < this->Anisotropy[0]) {
+      this->Anisotropy[0] = fractani_array[i];
+    } 
+    if (fractani_array[i] > this->Anisotropy[1]) {
+      this->Anisotropy[1] = fractani_array[i];
+    }
+    
+    // min/max
+    if ( meandiff_array[i] < this->Diffusivity[0]) {
+      this->Diffusivity[0] = meandiff_array[i];
+    } 
+    if (meandiff_array[i] > this->Diffusivity[1]) {
+      this->Diffusivity[1] = meandiff_array[i];
+    }
+
+    // min/max
+    if ( distance_array[i] < this->Distance[0]) {
+      this->Distance[0] = distance_array[i];
+    } 
+    if (distance_array[i] > this->Distance[1]) {
+      this->Distance[1] = distance_array[i];
+    }
+    
+    // min/max
+    if (angle_array[i] < this->Angle[0]) {
+      this->Angle[0] = angle_array[i];
+    } 
+    if (angle_array[i] > this->Angle[1]) {
+      this->Angle[1] = angle_array[i];
+    }
+    
+    // min/max
+    if ( other_array[i] < this->Other[0]) {
+      this->Other[0] = other_array[i];
+    } 
+    if (other_array[i] > this->Other[1]) {
+      this->Other[1] = other_array[i];
+    }
+    
+    // sum/sumsqr
+    fractanisum += fractani_array[i];
+    fractanisumsqr += fractani_array[i]*fractani_array[i];
+    //printf("fractanisum=%f,%f\n",fractanisum,fractani_array[i]);
+
+    // sum/sumsqr
+    meandiffsum += meandiff_array[i];
+    meandiffsumsqr += meandiff_array[i]*meandiff_array[i];
+
+    // sum/sumsqr
+    distancesum += distance_array[i];
+    distancesumsqr += distance_array[i]*distance_array[i];
+    
+    // sum/sumsqr
+    anglesum += angle_array[i];
+    anglesumsqr += angle_array[i]*angle_array[i];
+    //printf("anglesum=%f,%f\n",anglesum,angle_array[i]);
+ 
+    // sum/sumsqr
+    othersum += other_array[i];
+    othersumsqr += other_array[i]*other_array[i];
+  }
+  
+  delete [] fractani_array;
+  delete [] meandiff_array;
+  delete [] distance_array;
+  delete [] angle_array;
+  delete [] other_array;
+
+  // compute mean
+  this->Anisotropy[2] = fractanisum / (float)numLines;
+  this->Diffusivity[2] = meandiffsum / (float)numLines;
+  this->Distance[2] = distancesum / (float)numLines;
+  this->Angle[2] = anglesum / (float)numLines;
+  this->Other[2] = othersum / (float)numLines;
+
+  //printf("numLines=%d\n",numLines);
+  //printf("stats1: %f %f %f %f %f\n",fractanisum,meandiffsum,distancesum,anglesum,othersum);
+  //printf("stats2: %f %f %f %f %f\n",fractanisumsqr,meandiffsumsqr,distancesumsqr,anglesumsqr,othersumsqr);
+  
+  // compute variance
+  if (numLines > 1) {
+    this->Anisotropy[3] = (fractanisumsqr - 
+			   (((float)numLines)*this->Anisotropy[2]*this->Anisotropy[2]))/((float)numLines-1);
+    this->Diffusivity[3] = (meandiffsumsqr - 
+			    (((float)numLines)*this->Diffusivity[2]*this->Diffusivity[2]))/((float)numLines-1);
+    this->Distance[3] = (distancesumsqr - 
+			 (((float)numLines)*this->Distance[2]*this->Distance[2]))/((float)numLines-1);
+    this->Angle[3] = (anglesumsqr - 
+		      (((float)numLines)*this->Angle[2]*this->Angle[2]))/((float)numLines-1);
+    this->Other[3] = (othersumsqr - 
+		      (((float)numLines)*this->Other[2]*this->Other[2]))/((float)numLines-1);
+  }
+ 
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamlineStatistics.h b/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamlineStatistics.h
new file mode 100644
index 0000000..26e7c18
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjTensorStreamlineStatistics.h
@@ -0,0 +1,82 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjTensorStreamlineStatistics_h
+#define __vtkmpjTensorStreamlineStatistics_h
+
+#include "vtkPolyDataToPolyDataFilter.h"
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkDataArray.h"
+#include "vtkFloatArray.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+
+class vtkmpjTensorStreamlineStatistics : public vtkPolyDataToPolyDataFilter
+{
+public:
+  vtkTypeMacro(vtkmpjTensorStreamlineStatistics,vtkPolyDataToPolyDataFilter);
+
+  // Description:
+  // Construct object 
+  static vtkmpjTensorStreamlineStatistics *New();
+
+  // Get statistics across fibers
+  // min, max, mean, variance
+  vtkGetVectorMacro(Anisotropy,float,4);
+  vtkGetVectorMacro(Diffusivity,float,4);
+  vtkGetVectorMacro(Distance,float,4);
+  vtkGetVectorMacro(Angle,float,4);
+  vtkGetVectorMacro(Other,float,4);
+
+  vtkGetMacro(NumberOfFibers, int);
+  
+ protected:
+  vtkmpjTensorStreamlineStatistics();
+  ~vtkmpjTensorStreamlineStatistics() {}
+  
+  // Usual data generation method
+  void Execute();
+  
+  int NumberOfFibers;
+  float Anisotropy[4];
+  float Diffusivity[4];
+  float Distance[4];
+  float Angle[4];
+  float Other[4];
+
+private:
+  vtkmpjTensorStreamlineStatistics(const vtkmpjTensorStreamlineStatistics&);// Not implemented.
+  void operator=(const vtkmpjTensorStreamlineStatistics&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjTestOptimizer.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjTestOptimizer.cpp
new file mode 100644
index 0000000..c5689ff
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjTestOptimizer.cpp
@@ -0,0 +1,187 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+// vtk includes
+#include "pxutil.h"
+#include "vtkObjectFactory.h"
+#include "vtkmpjTestOptimizer.h"
+#include "vtkMath.h"
+#include "vtkpxUtil.h"
+#include "vtkpxOptimizer.h"
+
+vtkmpjTestOptimizer* vtkmpjTestOptimizer::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjTestOptimizer");
+  if(ret)
+    {
+      return (vtkmpjTestOptimizer*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjTestOptimizer;
+}
+
+
+vtkmpjTestOptimizer::vtkmpjTestOptimizer()
+{
+  this->OptimizationMethod=0;
+  this->FunctionIndex=0;
+  this->parameters=vtkDoubleArray::New();
+  this->parameters->SetNumberOfComponents(1);
+  this->parameters->SetNumberOfTuples(2);
+  this->parameters->SetComponent(0,0,5);
+  this->parameters->SetComponent(1,0,5);
+  this->FunctionEvaluation=0;
+  this->DerivEvaluation=0;
+
+}
+
+vtkmpjTestOptimizer::~vtkmpjTestOptimizer()
+{
+  this->parameters->Delete();
+}
+
+//-------------------------------------------------------------------------
+void vtkmpjTestOptimizer::SetOutputStatus(const char* line,double v)
+{
+  fprintf(stderr,"**Opt=%s (%.5f)\n",line,v);
+}
+
+//-------------------------------------------------------------------------
+double vtkmpjTestOptimizer::CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output)
+{
+  return ((vtkmpjTestOptimizer*)self)->OptimizerGradient(position,output);
+}
+
+double vtkmpjTestOptimizer::CalculateFunction(vtkObject* self,vtkDoubleArray* position)
+{
+  return ((vtkmpjTestOptimizer*)self)->OptimizerValue(position);
+}
+
+void vtkmpjTestOptimizer::OptimizerFeedback(vtkObject* self,const char* line,double val)
+{
+  ((vtkmpjTestOptimizer*)self)->SetOutputStatus(line,val);
+}
+//-------------------------------------------------------------------------
+void vtkmpjTestOptimizer::SetCurrentParameters(vtkDoubleArray* par)
+{
+  this->parameters->DeepCopy(par);
+}
+ 
+void vtkmpjTestOptimizer::GetCurrentParameters(vtkDoubleArray* par)
+{
+  par->DeepCopy(this->parameters);
+}
+
+double vtkmpjTestOptimizer::OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad)
+{
+  if (grad->GetNumberOfTuples()!=params->GetNumberOfTuples())
+    grad->SetNumberOfTuples(params->GetNumberOfTuples());
+
+  double x=params->GetComponent(0,0);
+  double y=params->GetComponent(1,0);
+
+  double dx=2*(x-1);
+  double dy=2*y;
+  double s=dx*dx+dy*dy;
+
+  s=sqrt(s);
+  grad->SetComponent(0,0,dx/s);
+  grad->SetComponent(1,0,dy/s);
+  ++this->DerivEvaluation;
+  fprintf(stderr,"\t x=%.2f y=%.2f --> dx=%.2f dy=%.2f --> v=[%.2f %.2f]\n",x,y,dx,dy,dx/s,dy/s);
+  return (s);
+
+}
+ 
+double vtkmpjTestOptimizer::OptimizerValue(vtkDoubleArray* params)
+{
+  double x=params->GetComponent(0,0);
+  double y=params->GetComponent(1,0);
+  double v=(x-1)*(x-1)+y*y;
+  ++this->FunctionEvaluation;
+
+  //  fprintf(stderr,"\t x=%.2f y=%.2f --> v=%.2f\n",x,y,v);
+  return v;
+
+}
+
+void vtkmpjTestOptimizer::Run()
+{
+  vtkpxOptimizer* optimizer=vtkpxOptimizer::New();
+  vtkDoubleArray* position=vtkDoubleArray::New();
+  vtkDoubleArray* temp=vtkDoubleArray::New();
+  this->GetCurrentParameters(position);
+  optimizer->SetMasterObject(this);
+
+  optimizer->SetEvaluateFunctionMethod(&vtkmpjTestOptimizer::CalculateFunction);
+  optimizer->SetEvaluateGradientMethod(&vtkmpjTestOptimizer::CalculateGradient);
+  optimizer->SetFeedbackMethod(&vtkmpjTestOptimizer::OptimizerFeedback);
+
+  fprintf(stderr,"Starting meth=%d\n",this->OptimizationMethod);
+  this->FunctionEvaluation=0;
+  this->DerivEvaluation=0;
+
+  switch (this->OptimizationMethod)
+    {
+    case -1:
+    case 0:
+      optimizer->ComputeOldGradientDescent(position,0.5,0.0001);
+      break;
+    case 2:
+      optimizer->ComputeGradientDescent(position,50,0.0001);
+      break;
+    case 1:
+      optimizer->DebugOn();
+      optimizer->ComputeSlowClimb(position,0.25,50);
+      optimizer->DebugOff();
+      break;
+    case 3:
+      optimizer->ComputePowell(position,temp,50,0.001);
+      break;
+    case 4:
+      optimizer->ComputeConjugateGradient(position,50,0.001);
+      break;
+    }
+
+  fprintf(stderr,"\n\n Final Output = (%.2f %.2f) func=%.5f eval= f=%d d=%d\n",
+	  position->GetComponent(0,0),
+	  position->GetComponent(1,0),
+	  this->OptimizerValue(position),
+	  this->FunctionEvaluation,
+	  this->DerivEvaluation);
+  optimizer->Delete();
+  position->Delete();
+  temp->Delete();
+  
+}
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjTestOptimizer.h b/bioimagesuite30_src/mpjCommon/vtkmpjTestOptimizer.h
new file mode 100644
index 0000000..a7ceecc
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjTestOptimizer.h
@@ -0,0 +1,107 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjTestOptimizer_h
+#define __vtkmpjTestOptimizer_h
+
+#include "vtkProcessObject.h"
+#include "vtkDoubleArray.h"
+
+class vtkmpjTestOptimizer : public vtkProcessObject {
+
+public:
+
+  vtkTypeMacro(vtkmpjTestOptimizer,vtkProcessObject);
+
+  // Description:
+  // This one also 
+  static vtkmpjTestOptimizer* New();
+  
+  // Description:
+  // These are needed for the Optimizer 
+  static void  OptimizerFeedback(vtkObject* self,const char* line,double val);
+  static double CalculateGradient(vtkObject* self,vtkDoubleArray* position,vtkDoubleArray* output);
+  static double CalculateFunction(vtkObject* self,vtkDoubleArray* position);
+
+  // Description:
+  // Optimization Method
+  vtkSetMacro(OptimizationMethod,int);
+  vtkGetMacro(OptimizationMethod,int);
+
+  // Description:
+  // Optimization Method
+  vtkSetMacro(FunctionIndex,int);
+  vtkGetMacro(FunctionIndex,int);
+
+  // Description:
+  // Shorthand for different optimization methods 
+  virtual void SetOptimizationMethodToOldStyle() { this->SetOptimizationMethod(-1); }
+  virtual void SetOptimizationMethodToDefault() { this->SetOptimizationMethod(0); }
+  virtual void SetOptimizationMethodToSlowClimb() { this->SetOptimizationMethod(1); }
+  virtual void SetOptimizationMethodToGradientDescent() { this->SetOptimizationMethod(2); }
+
+  // Description:
+  // Run Test
+  virtual void Run();
+
+protected:
+
+  // Description:
+  // Make all these protected 
+  // Constructor
+  vtkmpjTestOptimizer();
+  virtual ~vtkmpjTestOptimizer();
+  vtkmpjTestOptimizer(const vtkmpjTestOptimizer&) {};
+  void operator=(const vtkmpjTestOptimizer&) {};
+
+
+  // Description:
+  // Various Control Parameters
+  int   OptimizationMethod;
+  int   FunctionIndex;
+  vtkDoubleArray* parameters;
+  int   FunctionEvaluation;
+  int   DerivEvaluation;
+
+  // Description:
+  // Needed for Optimizer -- set,get,optimizer,optimizervalue
+  virtual void SetCurrentParameters(vtkDoubleArray* par);
+  virtual void GetCurrentParameters(vtkDoubleArray* par);
+  virtual double OptimizerGradient(vtkDoubleArray* params,vtkDoubleArray* grad);
+  virtual double OptimizerValue(vtkDoubleArray* params);
+  virtual void  SetOutputStatus(const char* line,double v);
+};
+
+
+
+#endif
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjThresholdPolyData.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjThresholdPolyData.cpp
new file mode 100644
index 0000000..a9c1eef
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjThresholdPolyData.cpp
@@ -0,0 +1,301 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkmpjThresholdPolyData.h"
+ 
+#include "vtkCell.h"
+#include "vtkCellData.h"
+#include "vtkIdList.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+
+vtkStandardNewMacro(vtkmpjThresholdPolyData);
+
+// Construct with lower threshold=0, upper threshold=1, and threshold 
+// function=upper AllScalars=1.
+vtkmpjThresholdPolyData::vtkmpjThresholdPolyData()
+{
+  this->LowerThreshold = 0.0;
+  this->UpperThreshold = 1.0;
+  this->AllScalars = 1;
+  this->AttributeMode = VTK_ATTRIBUTE_MODE_USE_POINT_DATA;
+  this->ThresholdFunction = &vtkmpjThresholdPolyData::Upper;
+  this->InputScalarsSelection = NULL;
+}
+
+vtkmpjThresholdPolyData::~vtkmpjThresholdPolyData()
+{
+  // This frees the string
+  this->SetInputScalarsSelection(NULL);
+}
+
+// Criterion is cells whose scalars are less or equal to lower threshold.
+void vtkmpjThresholdPolyData::ThresholdByLower(float lower) 
+{
+  if ( this->LowerThreshold != lower || 
+       this->ThresholdFunction != &vtkmpjThresholdPolyData::Lower)
+    {
+    this->LowerThreshold = lower; 
+    this->ThresholdFunction = &vtkmpjThresholdPolyData::Lower;
+    this->Modified();
+    }
+}
+                           
+// Criterion is cells whose scalars are greater or equal to upper threshold.
+void vtkmpjThresholdPolyData::ThresholdByUpper(float upper)
+{
+  if ( this->UpperThreshold != upper ||
+       this->ThresholdFunction != &vtkmpjThresholdPolyData::Upper)
+    {
+    this->UpperThreshold = upper; 
+    this->ThresholdFunction = &vtkmpjThresholdPolyData::Upper;
+    this->Modified();
+    }
+}
+                           
+// Criterion is cells whose scalars are between lower and upper thresholds.
+void vtkmpjThresholdPolyData::ThresholdBetween(float lower, float upper)
+{
+  if ( this->LowerThreshold != lower || this->UpperThreshold != upper ||
+       this->ThresholdFunction != &vtkmpjThresholdPolyData::Between)
+    {
+    this->LowerThreshold = lower; 
+    this->UpperThreshold = upper;
+    this->ThresholdFunction = &vtkmpjThresholdPolyData::Between;
+    this->Modified();
+    }
+}
+  
+void vtkmpjThresholdPolyData::Execute()
+{
+  vtkIdType cellId, newCellId;
+  vtkIdList *cellPts, *pointMap;
+  vtkIdList *newCellPts;
+  vtkCell *cell;
+  vtkPoints *newPoints;
+  int i, ptId, newId, numPts;
+  int numCellPts;
+  double *x;
+  vtkDataSet *input = this->GetInput();
+  
+  if (!input)
+    {
+    vtkErrorMacro(<<"No input, Can't Execute");
+    }
+  vtkPolyData *output = this->GetOutput();
+  vtkPointData *pd=input->GetPointData(), *outPD=output->GetPointData();
+  vtkCellData *cd=input->GetCellData(), *outCD=output->GetCellData();
+  vtkDataArray *pointScalars;
+  vtkDataArray *cellScalars;
+  int keepCell, usePointScalars;
+
+  vtkDebugMacro(<< "Executing threshold filter");
+  
+  // I am explicitly checking to avoid a warning if the array is not found.
+  if (this->InputScalarsSelection)
+    {
+    pointScalars=pd->GetArray(this->InputScalarsSelection);
+    cellScalars=cd->GetArray(this->InputScalarsSelection);
+    }
+  else
+    {
+    pointScalars=pd->GetScalars();
+    cellScalars=cd->GetScalars();
+    }
+
+  outPD->CopyAllocate(pd);
+  outCD->CopyAllocate(cd);
+
+  if ( !(pointScalars || cellScalars) )
+    {
+    vtkErrorMacro(<<"No scalar data to threshold");
+    return;
+    }
+
+  numPts = input->GetNumberOfPoints();
+  output->Allocate(input->GetNumberOfCells());
+  newPoints = vtkPoints::New();
+  newPoints->Allocate(numPts);
+
+  pointMap = vtkIdList::New(); //maps old point ids into new
+  pointMap->SetNumberOfIds(numPts);
+  for (i=0; i < numPts; i++)
+    {
+    pointMap->SetId(i,-1);
+    }
+
+  // Determine which scalar data to use for thresholding
+  if ( this->AttributeMode == VTK_ATTRIBUTE_MODE_DEFAULT )
+    {
+    if ( pointScalars != NULL)
+      {
+      usePointScalars = 1;
+      }
+    else
+      {
+      usePointScalars = 0;
+      }
+    }
+  else if ( this->AttributeMode == VTK_ATTRIBUTE_MODE_USE_POINT_DATA )
+    {
+    usePointScalars = 1;
+    }
+  else
+    {
+    usePointScalars = 0;
+    }
+
+  // Check on scalar consistency
+  if ( usePointScalars && !pointScalars )
+    {
+    vtkErrorMacro(<<"Can't use point scalars because there are none");
+    return;
+    }
+  else if ( !usePointScalars && !cellScalars )
+    {
+    vtkErrorMacro(<<"Can't use cell scalars because there are none");
+    return;
+    }
+
+  newCellPts = vtkIdList::New();     
+
+  // Check that the scalars of each cell satisfy the threshold criterion
+  for (cellId=0; cellId < input->GetNumberOfCells(); cellId++)
+    {
+    cell = input->GetCell(cellId);
+    cellPts = cell->GetPointIds();
+    numCellPts = cell->GetNumberOfPoints();
+    
+    if ( usePointScalars )
+      {
+      if (this->AllScalars)
+        {
+        keepCell = 1;
+        for ( i=0; keepCell && (i < numCellPts); i++)
+          {
+          ptId = cellPts->GetId(i);
+          keepCell = 
+            (this->*(this->ThresholdFunction))(pointScalars->GetComponent(ptId,0));
+          }
+        }
+      else
+        {
+        keepCell = 0;
+        for ( i=0; (!keepCell) && (i < numCellPts); i++)
+          {
+          ptId = cellPts->GetId(i);
+          keepCell = 
+            (this->*(this->ThresholdFunction))(pointScalars->GetComponent(ptId,0));
+          }
+        }
+      }
+    else //use cell scalars
+      {
+      keepCell = (this->*(this->ThresholdFunction))(cellScalars->GetComponent(cellId,0));
+      }
+    
+    if ( keepCell ) // satisfied thresholding
+      {
+      for (i=0; i < numCellPts; i++)
+        {
+        ptId = cellPts->GetId(i);
+        if ( (newId = pointMap->GetId(ptId)) < 0 )
+          {
+          x = input->GetPoint(ptId);
+          newId = newPoints->InsertNextPoint(x);
+          pointMap->SetId(ptId,newId);
+          outPD->CopyData(pd,ptId,newId);
+          }
+        newCellPts->InsertId(i,newId);
+        }
+      newCellId = output->InsertNextCell(cell->GetCellType(),newCellPts);
+      outCD->CopyData(cd,cellId,newCellId);
+      newCellPts->Reset();
+      } // satisfied thresholding
+    } // for all cells
+
+  vtkDebugMacro(<< "Extracted " << output->GetNumberOfCells() 
+                << " number of cells.");
+
+  // now clean up / update ourselves
+  pointMap->Delete();
+  newCellPts->Delete();
+  
+  output->SetPoints(newPoints);
+  newPoints->Delete();
+
+  output->Squeeze();
+}
+
+// Return the method for manipulating scalar data as a string.
+const char *vtkmpjThresholdPolyData::GetAttributeModeAsString(void)
+{
+  if ( this->AttributeMode == VTK_ATTRIBUTE_MODE_DEFAULT )
+    {
+    return "Default";
+    }
+  else if ( this->AttributeMode == VTK_ATTRIBUTE_MODE_USE_POINT_DATA )
+    {
+    return "UsePointData";
+    }
+  else 
+    {
+    return "UseCellData";
+    }
+}
+
+void vtkmpjThresholdPolyData::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+
+  os << indent << "Attribute Mode: " << this->GetAttributeModeAsString() << endl;
+  if (this->InputScalarsSelection)
+    {
+    os << indent << "InputScalarsSelection: " << this->InputScalarsSelection;
+    } 
+
+  os << indent << "All Scalars: " << this->AllScalars << "\n";
+  if ( this->ThresholdFunction == &vtkmpjThresholdPolyData::Upper )
+    {
+    os << indent << "Threshold By Upper\n";
+    }
+
+  else if ( this->ThresholdFunction == &vtkmpjThresholdPolyData::Lower )
+    {
+    os << indent << "Threshold By Lower\n";
+    }
+
+  else if ( this->ThresholdFunction == &vtkmpjThresholdPolyData::Between )
+    {
+    os << indent << "Threshold Between\n";
+    }
+
+  os << indent << "Lower Threshold: " << this->LowerThreshold << "\n";
+  os << indent << "Upper Threshold: " << this->UpperThreshold << "\n";
+}
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjThresholdPolyData.h b/bioimagesuite30_src/mpjCommon/vtkmpjThresholdPolyData.h
new file mode 100644
index 0000000..a5ee3a3
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjThresholdPolyData.h
@@ -0,0 +1,130 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#ifndef __vtkmpjThresholdPolyData_h
+#define __vtkmpjThresholdPolyData_h
+
+#include "vtkDataSetToPolyDataFilter.h"
+
+#define VTK_ATTRIBUTE_MODE_DEFAULT 0
+#define VTK_ATTRIBUTE_MODE_USE_POINT_DATA 1
+#define VTK_ATTRIBUTE_MODE_USE_CELL_DATA 2
+
+class vtkmpjThresholdPolyData : public vtkDataSetToPolyDataFilter
+{
+public:
+  static vtkmpjThresholdPolyData *New();
+  vtkTypeMacro(vtkmpjThresholdPolyData,vtkDataSetToPolyDataFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Criterion is cells whose scalars are less or equal to lower threshold.
+  void ThresholdByLower(float lower);
+
+  // Description:
+  // Criterion is cells whose scalars are greater or equal to upper threshold.
+  void ThresholdByUpper(float upper);
+
+  // Description:
+  // Criterion is cells whose scalars are between lower and upper thresholds.
+  void ThresholdBetween(float lower, float upper);
+
+  // Description:
+  // Get the Upper and Lower thresholds.
+  vtkGetMacro(UpperThreshold,float);
+  vtkGetMacro(LowerThreshold,float);
+
+  // Description:
+  // Control how the filter works with scalar point data and cell attribute
+  // data.  By default (AttributeModeToDefault), the filter will use point
+  // data, and if no point data is available, then cell data is
+  // used. Alternatively you can explicitly set the filter to use point data
+  // (AttributeModeToUsePointData) or cell data (AttributeModeToUseCellData).
+  vtkSetMacro(AttributeMode,int);
+  vtkGetMacro(AttributeMode,int);
+  void SetAttributeModeToDefault() 
+    {this->SetAttributeMode(VTK_ATTRIBUTE_MODE_DEFAULT);};
+  void SetAttributeModeToUsePointData() 
+    {this->SetAttributeMode(VTK_ATTRIBUTE_MODE_USE_POINT_DATA);};
+  void SetAttributeModeToUseCellData() 
+    {this->SetAttributeMode(VTK_ATTRIBUTE_MODE_USE_CELL_DATA);};
+  const char *GetAttributeModeAsString();
+
+  // Description:
+  // If using scalars from point data, all scalars for all points in a cell 
+  // must satisfy the threshold criterion if AllScalars is set. Otherwise, 
+  // just a single scalar value satisfying the threshold criterion enables
+  // will extract the cell.
+  vtkSetMacro(AllScalars,int);
+  vtkGetMacro(AllScalars,int);
+  vtkBooleanMacro(AllScalars,int);
+  
+protected:
+  vtkmpjThresholdPolyData();
+  ~vtkmpjThresholdPolyData();
+
+//BTX
+  // This is temporary solution. The vtkCutMaterial must be able
+  // to call SelectInputScalars().
+  friend class vtkCutMaterial;
+
+  // Description:
+  // If you want to threshold by an arbitrary array, then set its name here.
+  // By default this in NULL and the filter will use the active scalar array.
+  vtkGetStringMacro(InputScalarsSelection);
+  virtual void SelectInputScalars(const char *fieldName) 
+    {this->SetInputScalarsSelection(fieldName);}
+//ETX
+  
+  // Usual data generation method
+  void Execute();
+
+  int   AllScalars;
+  float LowerThreshold;
+  float UpperThreshold;
+  int   AttributeMode;
+
+  //BTX
+  int (vtkmpjThresholdPolyData::*ThresholdFunction)(float s);
+  //ETX
+
+  int Lower(float s) {return ( s <= this->LowerThreshold ? 1 : 0 );};
+  int Upper(float s) {return ( s >= this->UpperThreshold ? 1 : 0 );};
+  int Between(float s) {return ( s >= this->LowerThreshold ? 
+                               ( s <= this->UpperThreshold ? 1 : 0 ) : 0 );};
+
+  char *InputScalarsSelection;
+  vtkSetStringMacro(InputScalarsSelection);
+
+private:
+  vtkmpjThresholdPolyData(const vtkmpjThresholdPolyData&);  // Not implemented.
+  void operator=(const vtkmpjThresholdPolyData&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjThresholdPolyDataByDistance.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjThresholdPolyDataByDistance.cpp
new file mode 100644
index 0000000..b137a90
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjThresholdPolyDataByDistance.cpp
@@ -0,0 +1,157 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkmpjThresholdPolyDataByDistance.h"
+
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkPolyLine.h"
+
+vtkStandardNewMacro(vtkmpjThresholdPolyDataByDistance);
+
+// Construct object 
+vtkmpjThresholdPolyDataByDistance::vtkmpjThresholdPolyDataByDistance()
+{
+  this->Origin[0] = 0;
+  this->Origin[1] = 0;
+  this->Origin[2] = 0;
+  this->MinimumDistance = 1.0;
+}
+
+void vtkmpjThresholdPolyDataByDistance::Execute()
+{
+  vtkPolyData *input = this->GetInput();
+  vtkPolyData *output = this->GetOutput();
+  vtkPointData *pd=input->GetPointData();
+  vtkCellData *cd=input->GetCellData();
+
+  vtkPointData *outPD=output->GetPointData();
+  vtkCellData *outCD=output->GetCellData();
+  vtkCellArray *inLines = NULL;
+
+  vtkPoints *inPts;
+  vtkIdType numPts = 0;
+  vtkIdType numLines;
+    
+  vtkIdType npts=0, *pts=NULL;
+  int id, abort=0;
+  vtkIdType inCellId;
+  double *x, dist;
+  
+  vtkDataArray *Scalars = pd->GetScalars();
+  vtkDataArray *cellScalars = cd->GetScalars();
+
+  // Check input and initialize
+  //  
+  if ( !(inPts=input->GetPoints()) || 
+       (numPts = inPts->GetNumberOfPoints()) < 1 ||
+       !(inLines = input->GetLines()) || 
+       (numLines = inLines->GetNumberOfCells()) < 1 )
+    {
+      return;
+    }
+  
+  // Create output data
+  vtkPoints *newPts = vtkPoints::New();
+  vtkCellArray *newCells = vtkCellArray::New();
+  vtkFloatArray *newScalars = vtkFloatArray::New();
+  vtkFloatArray *newCellScalars = vtkFloatArray::New();
+
+  for (inCellId=0, inLines->InitTraversal(); 
+       inLines->GetNextCell(npts,pts) && !abort; inCellId++)
+    {
+      this->UpdateProgress((float)inCellId/numLines);
+      abort = this->GetAbortExecute();
+      
+      if (npts < 2)
+	{
+	  vtkWarningMacro(<< "Less than two points in line!");
+	  continue; //skip filtering this line
+	}
+
+     float mindist = VTK_LARGE_FLOAT;
+      
+      // traverse polyline
+      for(int i = 0; i <npts; i++) {
+
+	x = inPts->GetPoint(pts[i]);
+
+	/* compute distance */
+	dist = vtkMath::Distance2BetweenPoints(x,this->Origin);
+	if (dist < mindist) {
+	  mindist = dist;
+	}
+	
+      }
+
+      //      printf("mindist=%f\n",mindist);
+
+      // if dist between threshold, it's OK to copy
+      if (mindist <= this->MinimumDistance) {
+	
+	// allocate next cell
+	newCells->InsertNextCell(npts);
+	newCellScalars->InsertNextTuple(cellScalars->GetTuple(inCellId));
+        	
+	// create new polyline
+	for(int i=0; i<npts; i++) {
+
+	  id = newPts->InsertNextPoint(inPts->GetPoint(pts[i]));
+	  
+	  // insert next point id
+	  newCells->InsertCellPoint(id);
+
+	  // insert point scalars
+	  newScalars->InsertNextTuple(Scalars->GetTuple(pts[i]));
+	}
+	
+      } 
+
+    }
+
+  output->GetPointData()->SetScalars(newScalars);
+  newScalars->Delete();
+
+  output->GetCellData()->SetScalars(newCellScalars);
+  newCellScalars->Delete();
+
+  output->SetPoints(newPts);
+  newPts->Delete();
+
+  output->SetLines(newCells);
+  newCells->Delete();
+
+  output->Squeeze();
+
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjThresholdPolyDataByDistance.h b/bioimagesuite30_src/mpjCommon/vtkmpjThresholdPolyDataByDistance.h
new file mode 100644
index 0000000..701cf96
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjThresholdPolyDataByDistance.h
@@ -0,0 +1,72 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef __vtkmpjThresholdPolyDataByDistance_h
+#define __vtkmpjThresholdPolyDataByDistance_h
+
+#include "vtkPolyDataToPolyDataFilter.h"
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkDataArray.h"
+#include "vtkFloatArray.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+
+class vtkmpjThresholdPolyDataByDistance : public vtkPolyDataToPolyDataFilter
+{
+public:
+  vtkTypeMacro(vtkmpjThresholdPolyDataByDistance,vtkPolyDataToPolyDataFilter);
+
+  // Description:
+  // Construct object 
+  static vtkmpjThresholdPolyDataByDistance *New();
+
+  // Set/Get minimum distance
+  vtkGetMacro(MinimumDistance,double);
+  vtkSetMacro(MinimumDistance,double);
+
+  // Set/Get Origin value
+  vtkGetVectorMacro(Origin,double,3);
+  vtkSetVectorMacro(Origin,double,3);
+
+ protected:
+  vtkmpjThresholdPolyDataByDistance();
+  ~vtkmpjThresholdPolyDataByDistance() {}
+  
+  // Usual data generation method
+  void Execute();
+
+  double Origin[3];
+  double MinimumDistance;
+
+private:
+  vtkmpjThresholdPolyDataByDistance(const vtkmpjThresholdPolyDataByDistance&);// Not implemented.
+  void operator=(const vtkmpjThresholdPolyDataByDistance&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjTubeFilter.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjTubeFilter.cpp
new file mode 100644
index 0000000..a20ea10
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjTubeFilter.cpp
@@ -0,0 +1,801 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjTubeFilter.h"
+
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkPolyLine.h"
+
+vtkStandardNewMacro(vtkmpjTubeFilter);
+
+// Construct object with radius 0.5, radius variation turned off, the number 
+// of sides set to 3, and radius factor of 10.
+vtkmpjTubeFilter::vtkmpjTubeFilter()
+{
+  this->Radius = 0.5;
+  this->VaryRadius = VTK_VARY_RADIUS_OFF;
+  this->NumberOfSides = 3;
+  this->RadiusFactor = 10;
+
+  this->DefaultNormal[0] = this->DefaultNormal[1] = 0.0;
+  this->DefaultNormal[2] = 1.0;
+  
+  this->UseDefaultNormal = 0;
+  this->SidesShareVertices = 1;
+  this->Capping = 0;
+  this->OnRatio = 1;
+  this->Offset = 0;
+
+  this->GenerateTCoords = VTK_TCOORDS_OFF;
+  this->TextureLength = 1.0;
+}
+
+void vtkmpjTubeFilter::Execute()
+{
+  vtkPolyData *input = this->GetInput();
+  vtkPolyData *output = this->GetOutput();
+  vtkPointData *pd=input->GetPointData();
+  vtkPointData *outPD=output->GetPointData();
+  vtkCellData *cd=input->GetCellData();
+  vtkCellData *outCD=output->GetCellData();
+  vtkCellArray *inLines = NULL;
+  vtkDataArray *inNormals;
+  vtkDataArray *inScalars=pd->GetScalars();
+  vtkDataArray *inVectors=pd->GetVectors();
+
+  vtkPoints *inPts;
+  vtkIdType numPts = 0;
+  vtkIdType numLines;
+  vtkIdType numNewPts, numNewCells;
+  vtkPoints *newPts;
+  int deleteNormals=0;
+  vtkFloatArray *newNormals;
+  vtkIdType i;
+  double range[2], maxSpeed=0;
+  vtkCellArray *newStrips;
+  vtkIdType npts=0, *pts=NULL;
+  vtkIdType offset=0;
+  vtkFloatArray *newTCoords=NULL;
+  int abort=0;
+  vtkIdType inCellId;
+  float oldRadius=1.0;
+
+  // Check input and initialize
+  //
+  vtkDebugMacro(<<"Creating tube");
+
+  if ( !(inPts=input->GetPoints()) || 
+      (numPts = inPts->GetNumberOfPoints()) < 1 ||
+      !(inLines = input->GetLines()) || 
+       (numLines = inLines->GetNumberOfCells()) < 1 )
+    {
+    return;
+    }
+
+  // Create the geometry and topology
+  numNewPts = numPts * this->NumberOfSides;
+  newPts = vtkPoints::New();
+  newPts->Allocate(numNewPts);
+  newNormals = vtkFloatArray::New();
+  newNormals->SetName("TubeNormals");
+  newNormals->SetNumberOfComponents(3);
+  newNormals->Allocate(3*numNewPts);
+  newStrips = vtkCellArray::New();
+  newStrips->Allocate(newStrips->EstimateSize(1,numNewPts));
+  vtkCellArray *singlePolyline = vtkCellArray::New();
+
+  // Point data: copy scalars, vectors, tcoords. Normals may be computed here.
+  outPD->CopyNormalsOff();
+  if ( (this->GenerateTCoords == VTK_TCOORDS_FROM_SCALARS && inScalars) ||
+       this->GenerateTCoords == VTK_TCOORDS_FROM_LENGTH ||
+       this->GenerateTCoords == VTK_TCOORDS_FROM_NORMALIZED_LENGTH )
+    {
+    newTCoords = vtkFloatArray::New();
+    newTCoords->SetNumberOfComponents(2);
+    newTCoords->Allocate(numNewPts);
+    outPD->CopyTCoordsOff();
+    }
+  outPD->CopyAllocate(pd,numNewPts);
+
+  int generateNormals = 0;
+  if ( !(inNormals=pd->GetNormals()) || this->UseDefaultNormal )
+    {
+    deleteNormals = 1;
+    inNormals = vtkFloatArray::New();
+    inNormals->SetNumberOfComponents(3);
+    inNormals->SetNumberOfTuples(numPts);
+
+    if ( this->UseDefaultNormal )
+      {
+      for ( i=0; i < numPts; i++)
+        {
+        inNormals->SetTuple(i,this->DefaultNormal);
+        }
+      }
+    else
+      {
+      // Normal generation has been moved to lower in the function.
+      // This allows each different polylines to share vertices, but have
+      // their normals (and hence their tubes) calculated independently
+      generateNormals = 1;
+      }      
+    }
+
+  // If varying width, get appropriate info.
+  //
+  if ( inScalars )
+    {
+    inScalars->GetRange(range,0);
+    if ((range[1] - range[0]) == 0.0)
+      {
+      if (this->VaryRadius == VTK_VARY_RADIUS_BY_SCALAR )
+        {
+        vtkWarningMacro(<< "Scalar range is zero!");
+        }
+      range[1] = range[0] + 1.0;
+      }
+    if (this->VaryRadius == VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR)
+      {
+      // temporarily set the radius to 1.0 so that radius*scalar = scalar
+      oldRadius = this->Radius;
+      this->Radius = 1.0;
+      if (range[0] < 0.0)
+        {
+        vtkWarningMacro(<< "Scalar values fall below zero when using absolute radius values!");
+        }
+      }
+    }
+  if ( inVectors )
+    {
+    maxSpeed = inVectors->GetMaxNorm();
+    }
+
+  // Copy selected parts of cell data; certainly don't want normals
+  //
+  numNewCells = inLines->GetNumberOfCells() * this->NumberOfSides + 2;
+  outCD->CopyNormalsOff();
+  outPD->CopyAllocate(pd,numNewCells);
+
+  //  Create points along each polyline that are connected into NumberOfSides
+  //  triangle strips. Texture coordinates are optionally generated.
+  //
+  this->Theta = 2.0*vtkMath::Pi() / this->NumberOfSides;
+  vtkPolyLine *lineNormalGenerator = vtkPolyLine::New();
+  for (inCellId=0, inLines->InitTraversal(); 
+       inLines->GetNextCell(npts,pts) && !abort; inCellId++)
+    {
+    this->UpdateProgress((float)inCellId/numLines);
+    abort = this->GetAbortExecute();
+
+    if (npts < 2)
+      {
+      vtkWarningMacro(<< "Less than two points in line!");
+      continue; //skip tubing this polyline
+      }
+
+    // If necessary calculate normals, each polyline calculates its
+    // normals independently, avoiding conflicts at shared vertices.
+    if (generateNormals) 
+      {
+      singlePolyline->Reset(); //avoid instantiation
+      singlePolyline->InsertNextCell(npts,pts);
+      if ( !lineNormalGenerator->GenerateSlidingNormals(inPts,singlePolyline,
+                                                        inNormals) )
+        {
+        vtkWarningMacro(<< "No normals for line!");
+        continue; //skip tubing this polyline
+        }
+      }
+
+    // Generate the points around the polyline. The tube is not stripped
+    // if the polyline is bad.
+    //
+    if ( !this->GeneratePoints(offset,npts,pts,inPts,newPts,pd,outPD,
+                               newNormals,inScalars,range,inVectors,
+                               maxSpeed,inNormals) )
+      {
+      vtkWarningMacro(<< "Could not generate points!");
+      continue; //skip tubing this polyline
+      }
+      
+    // Generate the strips for this polyline (including caps)
+    //
+    this->GenerateStrips(offset,npts,pts,inCellId,cd,outCD,newStrips);
+
+    // Generate the texture coordinates for this polyline
+    //
+    if ( newTCoords )
+      {
+      this->GenerateTextureCoords(offset,npts,pts,inPts,inScalars,newTCoords);
+      }
+
+    // Compute the new offset for the next polyline
+    offset = this->ComputeOffset(offset,npts);
+
+    }//for all polylines
+
+  singlePolyline->Delete();
+  
+  // reset the radius to ite orginal value if necessary
+  if (this->VaryRadius == VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR)
+    {
+    this->Radius = oldRadius;
+    }
+
+  // Update ourselves
+  //
+  if ( deleteNormals )
+    {
+    inNormals->Delete();
+    }
+
+  if ( newTCoords )
+    {
+    outPD->SetTCoords(newTCoords);
+    newTCoords->Delete();
+    }
+
+  output->SetPoints(newPts);
+  newPts->Delete();
+
+  output->SetStrips(newStrips);
+  newStrips->Delete();
+
+  outPD->SetNormals(newNormals);
+  newNormals->Delete();
+  lineNormalGenerator->Delete();
+
+  output->Squeeze();
+}
+
+int vtkmpjTubeFilter::GeneratePoints(vtkIdType offset, 
+                                  vtkIdType npts, vtkIdType *pts,
+                                  vtkPoints *inPts, vtkPoints *newPts, 
+                                  vtkPointData *pd, vtkPointData *outPD,
+                                  vtkFloatArray *newNormals,
+                                  vtkDataArray *inScalars, double range[2],
+                                  vtkDataArray *inVectors, double maxSpeed,
+                                  vtkDataArray *inNormals)
+{
+  vtkIdType j;
+  int i, k;
+  double p[3];
+  double pNext[3];
+  double sNext[3];
+  double sPrev[3];
+  double startCapNorm[3], endCapNorm[3];
+  double *n;
+  double s[3];
+  double bevelAngle;
+  double w[3];
+  double nP[3];
+  double sFactor=1.0;
+  double normal[3];
+  vtkIdType ptId=offset;
+
+  // Use "averaged" segment to create beveled effect. 
+  // Watch out for first and last points.
+  //
+  for (j=0; j < npts; j++)
+    {
+    if ( j == 0 ) //first point
+      {
+      inPts->GetPoint(pts[0],p);
+      inPts->GetPoint(pts[1],pNext);
+      for (i=0; i<3; i++) 
+        {
+        sNext[i] = pNext[i] - p[i];
+        sPrev[i] = sNext[i];
+        startCapNorm[i] = -sPrev[i];
+        }
+      vtkMath::Normalize(startCapNorm);
+      }
+    else if ( j == (npts-1) ) //last point
+      {
+      for (i=0; i<3; i++)
+        {
+        sPrev[i] = sNext[i];
+        p[i] = pNext[i];
+        endCapNorm[i] = sNext[i];
+        }
+      vtkMath::Normalize(endCapNorm);
+      }
+    else
+      {
+      for (i=0; i<3; i++)
+        {
+        p[i] = pNext[i];
+        }
+      inPts->GetPoint(pts[j+1],pNext);
+      for (i=0; i<3; i++)
+        {
+        sPrev[i] = sNext[i];
+        sNext[i] = pNext[i] - p[i];
+        }
+      }
+
+    n = inNormals->GetTuple(pts[j]);
+
+    if ( vtkMath::Normalize(sNext) == 0.0 )
+      {
+      vtkWarningMacro(<<"Coincident points!");
+      return 0;
+      }
+
+    for (i=0; i<3; i++)
+      {
+      s[i] = (sPrev[i] + sNext[i]) / 2.0; //average vector
+      }
+    // if s is zero then just use sPrev cross n
+    if (vtkMath::Normalize(s) == 0.0)
+      {
+      vtkDebugMacro(<< "Using alternate bevel vector");
+      vtkMath::Cross(sPrev,n,s);
+      if (vtkMath::Normalize(s) == 0.0)
+        {
+        vtkDebugMacro(<< "Using alternate bevel vector");
+        }
+      }
+
+    if ( (bevelAngle = vtkMath::Dot(sNext,sPrev)) > 1.0 )
+      {
+      bevelAngle = 1.0;
+      }
+    if ( bevelAngle < -1.0 )
+      {
+      bevelAngle = -1.0;
+      }
+    bevelAngle = acos((double)bevelAngle) / 2.0; //(0->90 degrees)
+    if ( (bevelAngle = cos(bevelAngle)) == 0.0 )
+      {
+      bevelAngle = 1.0;
+      }
+
+    bevelAngle = this->Radius / bevelAngle; //keep tube constant radius
+
+    vtkMath::Cross(s,n,w);
+    if ( vtkMath::Normalize(w) == 0.0)
+      {
+      vtkWarningMacro(<<"Bad normal s = " <<s[0]<<" "<<s[1]<<" "<< s[2] 
+                      << " n = " << n[0] << " " << n[1] << " " << n[2]);
+      return 0;
+      }
+
+    vtkMath::Cross(w,s,nP); //create orthogonal coordinate system
+    vtkMath::Normalize(nP);
+
+    // Compute a scale factor based on scalars or vectors
+    if ( inScalars && this->VaryRadius == VTK_VARY_RADIUS_BY_SCALAR )
+      {
+      sFactor = 1.0 + ((this->RadiusFactor - 1.0) * 
+                (inScalars->GetComponent(pts[j],0) - range[0]) 
+                       / (range[1]-range[0]));
+      }
+    else if ( inVectors && this->VaryRadius == VTK_VARY_RADIUS_BY_VECTOR )
+      {
+      sFactor = 
+        sqrt((double)maxSpeed/vtkMath::Norm(inVectors->GetTuple(pts[j])));
+      if ( sFactor > this->RadiusFactor )
+        {
+        sFactor = this->RadiusFactor;
+        }
+      }
+    else if ( inScalars && 
+              this->VaryRadius == VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR )
+      {
+      sFactor = inScalars->GetComponent(pts[j],0);
+      if (sFactor < 0.0) 
+        {
+        vtkWarningMacro(<<"Scalar value less than zero, skipping line");
+        return 0;
+        }
+      }
+
+    //create points around line
+    if (this->SidesShareVertices)
+      {
+      for (k=0; k < this->NumberOfSides; k++)
+        {
+        for (i=0; i<3; i++) 
+          {
+          normal[i] = w[i]*cos((double)k*this->Theta) + 
+            nP[i]*sin((double)k*this->Theta);
+          s[i] = p[i] + this->Radius * sFactor * normal[i];
+          }
+        newPts->InsertPoint(ptId,s);
+        newNormals->InsertTuple(ptId,normal);
+        outPD->CopyData(pd,pts[j],ptId);
+        ptId++;
+        }//for each side
+      } 
+    else
+      {
+      float n_left[3], n_right[3];
+      for (k=0; k < this->NumberOfSides; k++)
+        {
+        for (i=0; i<3; i++)
+          {
+          // Create duplicate vertices at each point
+          // and adjust the associated normals so that they are
+          // oriented with the facets. This preserves the tube's
+          // polygonal appearance, as if by flat-shading around the tube,
+          // while still allowing smooth (gouraud) shading along the
+          // tube as it bends.
+          normal[i]  = w[i]*cos((double)(k+0.0)*this->Theta) + 
+            nP[i]*sin((double)(k+0.0)*this->Theta);
+          n_right[i] = w[i]*cos((double)(k-0.5)*this->Theta) + 
+            nP[i]*sin((double)(k-0.5)*this->Theta);
+          n_left[i]  = w[i]*cos((double)(k+0.5)*this->Theta) + 
+            nP[i]*sin((double)(k+0.5)*this->Theta);
+          s[i] = p[i] + this->Radius * sFactor * normal[i];
+          }
+        newPts->InsertPoint(ptId,s);
+        newNormals->InsertTuple(ptId,n_right);
+        outPD->CopyData(pd,pts[j],ptId);
+        newPts->InsertPoint(ptId+1,s);
+        newNormals->InsertTuple(ptId+1,n_left);
+        outPD->CopyData(pd,pts[j],ptId+1);
+        ptId += 2;
+        }//for each side
+      }//else separate vertices
+    }//for all points in polyline
+  
+  //Produce end points for cap. They are placed at tail end of points.
+  if (this->Capping)
+    {
+    int numCapSides = this->NumberOfSides;
+    int capIncr = 1;
+    if ( ! this->SidesShareVertices )
+      {
+      numCapSides = 2 * this->NumberOfSides;
+      capIncr = 2;
+      }
+
+    //the start cap
+    for (k=0; k < numCapSides; k+=capIncr)
+      {
+      newPts->GetPoint(offset+k,s);
+      newPts->InsertPoint(ptId,s);
+      newNormals->InsertTuple(ptId,startCapNorm);
+      outPD->CopyData(pd,pts[0],ptId);
+      ptId++;
+      }
+    //the end cap
+    int endOffset = offset + (npts-1)*this->NumberOfSides;
+    if ( ! this->SidesShareVertices )
+      {
+      endOffset = offset + 2*(npts-1)*this->NumberOfSides;      
+      }
+    for (k=0; k < numCapSides; k+=capIncr)
+      {
+      newPts->GetPoint(endOffset+k,s);
+      newPts->InsertPoint(ptId,s);
+      newNormals->InsertTuple(ptId,endCapNorm);
+      outPD->CopyData(pd,pts[npts-1],ptId);
+      ptId++;
+      }
+    }//if capping
+  
+  return 1;
+}
+
+void vtkmpjTubeFilter::GenerateStrips(vtkIdType offset, vtkIdType npts, 
+                                   vtkIdType* vtkNotUsed(pts), 
+                                   vtkIdType inCellId,
+                                   vtkCellData *cd, vtkCellData *outCD,
+                                   vtkCellArray *newStrips)
+{
+  vtkIdType i, outCellId;
+  int k;
+  int i1, i2, i3;
+
+  if (this->SidesShareVertices)
+    {
+    for (k=this->Offset; k<(this->NumberOfSides+this->Offset); 
+         k+=this->OnRatio)
+      {
+      i1 = k % this->NumberOfSides;
+      i2 = (k+1) % this->NumberOfSides;
+      outCellId = newStrips->InsertNextCell(npts*2);
+      outCD->CopyData(cd,inCellId,outCellId);
+      for (i=0; i < npts; i++) 
+        {
+        i3 = i*this->NumberOfSides;
+        newStrips->InsertCellPoint(offset+i2+i3);
+        newStrips->InsertCellPoint(offset+i1+i3);
+        }
+      } //for each side of the tube
+    }
+  else
+    {
+    for (k=this->Offset; k<(this->NumberOfSides+this->Offset); 
+         k+=this->OnRatio)
+      {
+      i1 = 2*(k % this->NumberOfSides) + 1;
+      i2 = 2*((k+1) % this->NumberOfSides);
+      outCellId = newStrips->InsertNextCell(npts*2);
+      outCD->CopyData(cd,inCellId,outCellId);
+      for (i=0; i < npts; i++) 
+        {
+        i3 = i*2*this->NumberOfSides;
+        newStrips->InsertCellPoint(offset+i2+i3);
+        newStrips->InsertCellPoint(offset+i1+i3);
+        }
+      } //for each side of the tube
+    }
+
+  // Take care of capping. The caps are n-sided polygons that can be
+  // easily triangle stripped.
+  if (this->Capping)
+    {
+    vtkIdType startIdx = offset + npts*this->NumberOfSides;
+    vtkIdType idx;
+    
+    if ( ! this->SidesShareVertices )
+      {
+      startIdx = offset + 2*npts*this->NumberOfSides;
+      }
+
+    //The start cap
+    outCellId = newStrips->InsertNextCell(this->NumberOfSides);
+    outCD->CopyData(cd,inCellId,outCellId);
+    newStrips->InsertCellPoint(startIdx);
+    newStrips->InsertCellPoint(startIdx+1);
+    for (i1=this->NumberOfSides-1, i2=2, k=0; k<(this->NumberOfSides-2); k++)
+      {
+      if ( (k%2) )
+        {
+        idx = startIdx + i2;
+        newStrips->InsertCellPoint(idx);
+        i2++;
+        }
+      else
+        {
+        idx = startIdx + i1;
+        newStrips->InsertCellPoint(idx);
+        i1--;
+        }
+      }
+    
+    //The end cap - reversed order to be consistent with normal
+    startIdx += this->NumberOfSides;
+    outCellId = newStrips->InsertNextCell(this->NumberOfSides);
+    outCD->CopyData(cd,inCellId,outCellId);
+    newStrips->InsertCellPoint(startIdx);
+    newStrips->InsertCellPoint(startIdx+this->NumberOfSides-1);
+    for (i1=this->NumberOfSides-2, i2=1, k=0; k<(this->NumberOfSides-2); k++)
+      {
+      if ( (k%2) )
+        {
+        idx = startIdx + i1;
+        newStrips->InsertCellPoint(idx);
+        i1--;
+        }
+      else
+        {
+        idx = startIdx + i2;
+        newStrips->InsertCellPoint(idx);
+        i2++;
+        }
+      }
+    }
+}
+
+void vtkmpjTubeFilter::GenerateTextureCoords(vtkIdType offset,
+                                          vtkIdType npts, vtkIdType *pts, 
+                                          vtkPoints *inPts, 
+                                          vtkDataArray *inScalars,
+                                          vtkFloatArray *newTCoords)
+{
+  vtkIdType i;
+  int k;
+  float tc=0.0;
+
+  int numSides = this->NumberOfSides;
+  if ( ! this->SidesShareVertices )
+    {
+    numSides = 2 * this->NumberOfSides;
+    }
+
+  float s0, s;
+  //The first texture coordinate is always 0.
+  for ( k=0; k < numSides; k++)
+    {
+    newTCoords->InsertTuple2(offset+k,0.0,0.0);
+    }
+  if ( this->GenerateTCoords == VTK_TCOORDS_FROM_SCALARS )
+    {
+    s0 = inScalars->GetTuple1(pts[0]);
+    for (i=1; i < npts; i++)
+      {
+      s = inScalars->GetTuple1(pts[i]);
+      tc = (s - s0) / this->TextureLength;
+      for ( k=0; k < numSides; k++)
+        {
+        newTCoords->InsertTuple2(offset+i*numSides+k,tc,0.0);
+        }
+      }
+    }
+  else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_LENGTH )
+    {
+    double xPrev[3], x[3], len=0.0;
+    inPts->GetPoint(pts[0],xPrev);
+    for (i=1; i < npts; i++)
+      {
+      inPts->GetPoint(pts[i],x);
+      len += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev));
+      tc = len / this->TextureLength;
+      for ( k=0; k < numSides; k++)
+        {
+        newTCoords->InsertTuple2(offset+i*numSides+k,tc,0.0);
+        }
+      xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2];
+      }
+    }
+  else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_NORMALIZED_LENGTH )
+    {
+    double xPrev[3], x[3], length=0.0, len=0.0;
+    inPts->GetPoint(pts[0],xPrev);
+    for (i=1; i < npts; i++)
+      {
+      inPts->GetPoint(pts[i],x);
+      length += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev));
+      xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2];
+      }
+
+    inPts->GetPoint(pts[0],xPrev);
+    for (i=1; i < npts; i++)
+      {
+      inPts->GetPoint(pts[i],x);
+      len += sqrt(vtkMath::Distance2BetweenPoints(x,xPrev));
+      tc = len / length;
+      for ( k=0; k < numSides; k++)
+        {
+        newTCoords->InsertTuple2(offset+i*2+k,tc,0.0);
+        }
+      xPrev[0]=x[0]; xPrev[1]=x[1]; xPrev[2]=x[2];
+      }
+    }
+  
+  // Capping, set the endpoints as appropriate
+  if ( this->Capping )
+    {
+    int ik;
+    vtkIdType startIdx = offset + npts*numSides;
+
+    //start cap
+    for (ik=0; ik < this->NumberOfSides; ik++)
+      {
+      newTCoords->InsertTuple2(startIdx+ik,0.0,0.0);
+      }
+
+    //end cap
+    for (ik=0; ik < this->NumberOfSides; ik++)
+      {
+      newTCoords->InsertTuple2(startIdx+this->NumberOfSides+ik,tc,0.0);
+      }
+    }
+}
+
+// Compute the number of points in this tube
+vtkIdType vtkmpjTubeFilter::ComputeOffset(vtkIdType offset, vtkIdType npts)
+{
+  if ( this->SidesShareVertices )
+    {
+    offset += this->NumberOfSides * npts;
+    }
+  else
+    {
+    offset += 2 * this->NumberOfSides * npts; //points are duplicated
+    }
+    
+  if ( this->Capping )
+    {
+    offset += 2*this->NumberOfSides; //cap points are duplicated
+    }
+
+  return offset;
+}
+
+// Description:
+// Return the method of varying tube radius descriptive character string.
+const char *vtkmpjTubeFilter::GetVaryRadiusAsString(void)
+{
+  if ( this->VaryRadius == VTK_VARY_RADIUS_OFF )
+    {
+    return "VaryRadiusOff";
+    }
+  else if ( this->VaryRadius == VTK_VARY_RADIUS_BY_SCALAR ) 
+    {
+    return "VaryRadiusByScalar";
+    }
+  else if ( this->VaryRadius == VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR )
+    {
+    return "VaryRadiusByAbsoluteScalar";
+    }
+  else 
+    {
+    return "VaryRadiusByVector";
+    }
+}
+
+// Description:
+// Return the method of generating the texture coordinates.
+const char *vtkmpjTubeFilter::GetGenerateTCoordsAsString(void)
+{
+  if ( this->GenerateTCoords == VTK_TCOORDS_OFF )
+    {
+    return "GenerateTCoordsOff";
+    }
+  else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_SCALARS ) 
+    {
+    return "GenerateTCoordsFromScalar";
+    }
+  else if ( this->GenerateTCoords == VTK_TCOORDS_FROM_LENGTH ) 
+    {
+    return "GenerateTCoordsFromLength";
+    }
+  else 
+    {
+    return "GenerateTCoordsFromNormalizedLength";
+    }
+}
+
+void vtkmpjTubeFilter::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+
+  os << indent << "Radius: " << this->Radius << "\n";
+  os << indent << "Vary Radius: " << this->GetVaryRadiusAsString() << endl;
+  os << indent << "Radius Factor: " << this->RadiusFactor << "\n";
+  os << indent << "Number Of Sides: " << this->NumberOfSides << "\n";
+  os << indent << "On Ratio: " << this->OnRatio << "\n";
+  os << indent << "Offset: " << this->Offset << "\n";
+
+  os << indent << "Use Default Normal: " 
+     << (this->UseDefaultNormal ? "On\n" : "Off\n");
+  os << indent << "Sides Share Vertices: " 
+     << (this->SidesShareVertices ? "On\n" : "Off\n");
+  os << indent << "Default Normal: " << "( " << this->DefaultNormal[0] <<
+     ", " << this->DefaultNormal[1] << ", " << this->DefaultNormal[2] <<
+     " )\n";
+  os << indent << "Capping: " << (this->Capping ? "On\n" : "Off\n");
+  os << indent << "Generate TCoords: " 
+     << this->GetGenerateTCoordsAsString() << endl;
+  os << indent << "Texture Length: " << this->TextureLength << endl;
+}
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjTubeFilter.h b/bioimagesuite30_src/mpjCommon/vtkmpjTubeFilter.h
new file mode 100644
index 0000000..d18dcfc
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjTubeFilter.h
@@ -0,0 +1,207 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjTubeFilter_h
+#define __vtkmpjTubeFilter_h
+
+#include "vtkPolyDataToPolyDataFilter.h"
+
+#define VTK_VARY_RADIUS_OFF 0
+#define VTK_VARY_RADIUS_BY_SCALAR 1
+#define VTK_VARY_RADIUS_BY_VECTOR 2
+#define VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR 3
+
+#define VTK_TCOORDS_OFF                    0
+#define VTK_TCOORDS_FROM_NORMALIZED_LENGTH 1
+#define VTK_TCOORDS_FROM_LENGTH            2
+#define VTK_TCOORDS_FROM_SCALARS           3
+
+class vtkCellArray;
+class vtkCellData;
+class vtkDataArray;
+class vtkFloatArray;
+class vtkDoubleArray;
+class vtkPointData;
+class vtkPoints;
+
+class vtkmpjTubeFilter : public vtkPolyDataToPolyDataFilter
+{
+public:
+  vtkTypeMacro(vtkmpjTubeFilter,vtkPolyDataToPolyDataFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Construct object with radius 0.5, radius variation turned off, the
+  // number of sides set to 3, and radius factor of 10.
+  static vtkmpjTubeFilter *New();
+
+  // Description:
+  // Set the minimum tube radius (minimum because the tube radius may vary).
+  vtkSetClampMacro(Radius,float,0.0,VTK_LARGE_FLOAT);
+  vtkGetMacro(Radius,float);
+
+  // Description:
+  // Turn on/off the variation of tube radius with scalar value.
+  vtkSetClampMacro(VaryRadius,int,
+                   VTK_VARY_RADIUS_OFF,VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR);
+  vtkGetMacro(VaryRadius,int);
+  void SetVaryRadiusToVaryRadiusOff()
+    {this->SetVaryRadius(VTK_VARY_RADIUS_OFF);};
+  void SetVaryRadiusToVaryRadiusByScalar()
+    {this->SetVaryRadius(VTK_VARY_RADIUS_BY_SCALAR);};
+  void SetVaryRadiusToVaryRadiusByVector()
+    {this->SetVaryRadius(VTK_VARY_RADIUS_BY_VECTOR);};
+  void SetVaryRadiusToVaryRadiusByAbsoluteScalar()
+    {this->SetVaryRadius(VTK_VARY_RADIUS_BY_ABSOLUTE_SCALAR);};
+  const char *GetVaryRadiusAsString();
+
+  // Description:
+  // Set the number of sides for the tube. At a minimum, number of sides is 3.
+  vtkSetClampMacro(NumberOfSides,int,3,VTK_LARGE_INTEGER);
+  vtkGetMacro(NumberOfSides,int);
+
+  // Description:
+  // Set the maximum tube radius in terms of a multiple of the minimum radius.
+  vtkSetMacro(RadiusFactor,float);
+  vtkGetMacro(RadiusFactor,float);
+
+  // Description:
+  // Set the default normal to use if no normals are supplied, and the
+  // DefaultNormalOn is set.
+  vtkSetVector3Macro(DefaultNormal,float);
+  vtkGetVectorMacro(DefaultNormal,float,3);
+
+  // Description:
+  // Set a boolean to control whether to use default normals.
+  // DefaultNormalOn is set.
+  vtkSetMacro(UseDefaultNormal,int);
+  vtkGetMacro(UseDefaultNormal,int);
+  vtkBooleanMacro(UseDefaultNormal,int);
+
+  // Description:
+  // Set a boolean to control whether tube sides should share vertices.
+  // This creates independent strips, with constant normals so the
+  // tube is always faceted in appearance.
+  vtkSetMacro(SidesShareVertices, int);
+  vtkGetMacro(SidesShareVertices, int);
+  vtkBooleanMacro(SidesShareVertices, int);
+
+  // Description:
+  // Turn on/off whether to cap the ends with polygons.
+  vtkSetMacro(Capping,int);
+  vtkGetMacro(Capping,int);
+  vtkBooleanMacro(Capping,int);
+
+  // Description:
+  // Control the striping of the tubes. If OnRatio is greater than 1,
+  // then every nth tube side is turned on, beginning with the Offset
+  // side.
+  vtkSetClampMacro(OnRatio,int,1,VTK_LARGE_INTEGER);
+  vtkGetMacro(OnRatio,int);
+
+  // Description:
+  // Control the striping of the tubes. The offset sets the
+  // first tube side that is visible. Offset is generally used with
+  // OnRatio to create nifty striping effects.
+  vtkSetClampMacro(Offset,int,0,VTK_LARGE_INTEGER);
+  vtkGetMacro(Offset,int);
+
+  // Description:
+  // Control whether and how texture coordinates are produced. This is
+  // useful for striping the tube with length textures, etc. If you
+  // use scalars to create the texture, the scalars are assumed to be
+  // monotonically increasing (or decreasing).
+  vtkSetClampMacro(GenerateTCoords,int,VTK_TCOORDS_OFF,
+                   VTK_TCOORDS_FROM_SCALARS);
+  vtkGetMacro(GenerateTCoords,int);
+  void SetGenerateTCoordsToOff()
+    {this->SetGenerateTCoords(VTK_TCOORDS_OFF);}
+  void SetGenerateTCoordsToNormalizedLength()
+    {this->SetGenerateTCoords(VTK_TCOORDS_FROM_NORMALIZED_LENGTH);}
+  void SetGenerateTCoordsToUseLength()
+    {this->SetGenerateTCoords(VTK_TCOORDS_FROM_LENGTH);}
+  void SetGenerateTCoordsToUseScalars()
+    {this->SetGenerateTCoords(VTK_TCOORDS_FROM_SCALARS);}
+  const char *GetGenerateTCoordsAsString();
+
+  // Description:
+  // Control the conversion of units during the texture coordinates
+  // calculation. The TextureLength indicates what length (whether 
+  // calculated from scalars or length) is mapped to the [0,1)
+  // texture space.
+  vtkSetClampMacro(TextureLength,float,0.000001,VTK_LARGE_INTEGER);
+  vtkGetMacro(TextureLength,float);
+
+protected:
+  vtkmpjTubeFilter();
+  ~vtkmpjTubeFilter() {}
+
+  // Usual data generation method
+  void Execute();
+
+  float Radius; //minimum radius of tube
+  int VaryRadius; //controls radius variation
+  int NumberOfSides; //number of sides to create tube
+  float RadiusFactor; //maxium allowablew radius
+  float DefaultNormal[3];
+  int UseDefaultNormal;
+  int SidesShareVertices;
+  int Capping; //control whether tubes are capped
+  int OnRatio; //control the generation of the sides of the tube
+  int Offset;  //control the generation of the sides
+  int GenerateTCoords; //control texture coordinate generation
+  float TextureLength; //this length is mapped to [0,1) texture space
+  
+  // Helper methods
+  int GeneratePoints(vtkIdType offset, vtkIdType npts, vtkIdType *pts,
+                     vtkPoints *inPts, vtkPoints *newPts, 
+                     vtkPointData *pd, vtkPointData *outPD,
+                     vtkFloatArray *newNormals, vtkDataArray *inScalars,
+                     double range[2], vtkDataArray *inVectors, double maxNorm, 
+                     vtkDataArray *inNormals);
+  void GenerateStrips(vtkIdType offset, vtkIdType npts, vtkIdType *pts, 
+                      vtkIdType inCellId, vtkCellData *cd, vtkCellData *outCD,
+                      vtkCellArray *newStrips);
+  void GenerateTextureCoords(vtkIdType offset, vtkIdType npts, vtkIdType *pts, 
+                             vtkPoints *inPts, vtkDataArray *inScalars,
+                            vtkFloatArray *newTCoords);
+  vtkIdType ComputeOffset(vtkIdType offset,vtkIdType npts);
+  
+  // Helper data members
+  float Theta;
+
+private:
+  vtkmpjTubeFilter(const vtkmpjTubeFilter&);  // Not implemented.
+  void operator=(const vtkmpjTubeFilter&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjVectorStreamline.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjVectorStreamline.cpp
new file mode 100644
index 0000000..1205de1
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjVectorStreamline.cpp
@@ -0,0 +1,303 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjVectorStreamline.h"
+
+#include "vtkCellArray.h"
+#include "vtkDataSet.h"
+#include "vtkDoubleArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkCellData.h"
+#include "vtkPolyData.h"
+#include "vtkPolyLine.h"
+
+//vtkCxxRevisionMacro(vtkmpjVectorStreamline, "$Revision: 1.54 $");
+vtkStandardNewMacro(vtkmpjVectorStreamline);
+
+// Construct object with step size set to 1.0.
+vtkmpjVectorStreamline::vtkmpjVectorStreamline()
+{
+  this->StepLength = 1.0;
+  this->NumberOfStreamers = 0;
+}
+
+void vtkmpjVectorStreamline::Execute()
+{
+  if ( !this->GetInput() )
+    {
+    vtkErrorMacro("Input not set");
+    return;
+    }
+
+  vtkmpjStreamer::mpjStreamPoint *sPrev, *sPtr;
+  vtkPoints *newPts;
+  vtkDoubleArray *newVectors;
+  vtkDoubleArray *newScalars=NULL;
+  vtkDoubleArray *newCellScalars=NULL;
+  vtkCellArray *newLines;
+  vtkIdType ptId, i, id;
+  int j;
+  vtkIdList *pts;
+  double tOffset, x[3], v[3], s, ssum, r;
+  double theta;
+  vtkPolyLine* lineNormalGenerator = NULL;
+  vtkDoubleArray* normals = NULL;
+  vtkDoubleArray* rotation = 0;
+  vtkPolyData *output=this->GetOutput();
+
+  this->SavePointInterval = this->StepLength;
+  this->vtkmpjStreamer::Integrate();
+  if ( this->NumberOfStreamers <= 0 ) {return;}
+
+  pts = vtkIdList::New();
+  pts->Allocate(2500);
+
+  //
+  //  Convert streamer into lines. Lines may be dashed.
+  //
+  newPts  = vtkPoints::New();
+  newPts->Allocate(1000);
+  newVectors  = vtkDoubleArray::New();
+  newVectors->SetNumberOfComponents(3);
+  newVectors->Allocate(3000);
+  if ( this->Vorticity )
+    {
+      lineNormalGenerator = vtkPolyLine::New();
+      normals = vtkDoubleArray::New();
+      normals->SetNumberOfComponents(3);
+      normals->Allocate(3000);
+      rotation = vtkDoubleArray::New();
+      rotation->SetNumberOfComponents(1);
+      rotation->Allocate(1000);
+      rotation->SetName("Thetas");
+      output->GetPointData()->AddArray(rotation);
+    }
+  
+  if ( this->GetInput()->GetPointData()->GetScalars() || this->SpeedScalars
+       || this->OrientationScalars)
+    {
+      newScalars = vtkDoubleArray::New();
+      newScalars->Allocate(1000);
+      
+      // Allocate cell scalars
+      newCellScalars = vtkDoubleArray::New();
+      newCellScalars->Allocate(1000);
+    }
+  
+  newLines = vtkCellArray::New();
+  newLines->Allocate(newLines->EstimateSize(2*this->NumberOfStreamers,
+                                            VTK_CELL_SIZE));
+  //
+  // Loop over all streamers generating points
+  //  fprintf(stderr,"Looping over all streamers generating points\n");
+  //
+  for (ptId=0; ptId < this->NumberOfStreamers; ptId++)
+    {
+      //      fprintf(stderr,"Streamer=%d\n",ptId);
+
+      if ( this->Streamers[ptId].GetNumberOfPoints() < 2 )
+	{
+	  continue;
+	}
+      sPrev = this->Streamers[ptId].GetmpjStreamPoint(0);
+      sPtr = this->Streamers[ptId].GetmpjStreamPoint(1);
+      
+      if ( this->Streamers[ptId].GetNumberOfPoints() == 2 && sPtr->cellId >= 0 )
+	{
+	  continue;
+	}
+      
+      tOffset = sPrev->t;
+      ssum = 0.0;
+      
+      for ( i=1; 
+	    i < this->Streamers[ptId].GetNumberOfPoints() && sPtr->cellId >= 0;
+	    i++, sPrev=sPtr, sPtr=this->Streamers[ptId].GetmpjStreamPoint(i) )
+	{
+	  //
+	  // Create points for line
+	  //
+	  while ( tOffset >= sPrev->t && tOffset < sPtr->t )
+	    {
+	      r = (tOffset - sPrev->t) / (sPtr->t - sPrev->t);
+	      
+	      for (j=0; j<3; j++)
+		{
+		  x[j] = sPrev->x[j] + r * (sPtr->x[j] - sPrev->x[j]);
+		  v[j] = sPrev->v[j] + r * (sPtr->v[j] - sPrev->v[j]);
+		}
+	      
+	      // add point to line
+	      id = newPts->InsertNextPoint(x);
+	      //printf("%f %f %f\n",x[0],x[1],x[2]);
+	      
+	      pts->InsertNextId(id);
+	      newVectors->InsertTuple(id,v);
+	      
+	      if ( newScalars ) 
+		{
+		  s = sPrev->s + r * (sPtr->s - sPrev->s);
+		  newScalars->InsertTuple(id,&s);
+		  ssum += s;
+		  //printf("acc ssum=%f, %f\n",ssum, s);
+		}
+	      
+	      if ( this->Vorticity )
+		{
+		  // Store the rotation values. Used after all the streamlines
+		  // are generated.
+		  theta = sPrev->theta + r * (sPtr->theta - sPrev->theta);
+		  rotation->InsertTuple(id, &theta);
+		}
+	      
+	      tOffset += this->StepLength;
+	      
+	    } // while
+	} //for this streamer
+      
+      if ( pts->GetNumberOfIds() > 1 )
+	{
+	  vtkIdType cellid = newLines->InsertNextCell(pts);
+	  
+	  ssum = ssum / (double)pts->GetNumberOfIds();
+	  
+	  // insert cell scalars
+	  if ( newCellScalars ) {
+	    newCellScalars->InsertTuple(cellid,&ssum);				      
+	    //printf("ssum=%f, count=%d\n",ssum,pts->GetNumberOfIds());
+	  }
+	  
+	  pts->Reset();	
+	}
+      
+    } //for all streamers
+
+  //  fprintf(stderr,"On to next point\n");
+  
+  vtkDebugMacro(<<"Created " << newPts->GetNumberOfPoints() << " points, "
+		<< newLines->GetNumberOfCells() << " lines");
+  
+  if (this->Vorticity)
+    {
+      //      fprintf(stderr,"In Vorticity\n");
+      // Rotate the normal vectors with stream vorticity
+      int nPts=newPts->GetNumberOfPoints();
+      double normal[3], local1[3], local2[3], length, costheta, sintheta;
+      
+      lineNormalGenerator->GenerateSlidingNormals(newPts,newLines,normals);
+      
+
+      //      fprintf(stderr,"Creating Points\n");
+
+      for(i=0; i<nPts; i++)
+	{
+	  normals->GetTuple(i, normal);
+	  newVectors->GetTuple(i, v);
+	  // obtain two unit orthogonal vectors on the plane perpendicular to
+	  // the streamline
+
+	  //	  fprintf(stderr,"Dealing with Point %d (%.2f,%.2f,%.2f)\n",normal[0],normal[1],normal[2]);
+
+	  for(j=0; j<3; j++) { local1[j] = normal[j]; }
+	  length = vtkMath::Normalize(local1);
+	  vtkMath::Cross(local1, v, local2);
+	  vtkMath::Normalize(local2);
+	  // Rotate the normal with theta
+	  rotation->GetTuple(i, &theta);
+	  costheta = cos(theta);
+	  sintheta = sin(theta);
+	  for(j=0; j<3; j++)
+	    {
+	      normal[j] = length* (costheta*local1[j] + sintheta*local2[j]);
+	    }
+	  normals->SetTuple(i, normal);
+	}
+      output->GetPointData()->SetNormals(normals);
+      normals->Delete();
+      lineNormalGenerator->Delete();
+      rotation->Delete();
+    }
+
+  //  fprintf(stderr,"Clean up time .. which where the problem is most likely to be ...\n");
+  
+  output->SetPoints(newPts);
+  newPts->Delete();
+  
+  //  fprintf(stderr,"Clean up time 2\n");
+  output->GetPointData()->SetVectors(newVectors);
+  newVectors->Delete();
+  
+  if ( newScalars ) 
+    {
+      output->GetPointData()->SetScalars(newScalars);
+      newScalars->Delete();
+    }
+  
+  //  fprintf(stderr,"Clean up time 3\n");
+
+  if ( newCellScalars )
+    {
+      output->GetCellData()->SetScalars(newCellScalars);
+      newCellScalars->Delete();
+    }
+  
+  //  fprintf(stderr,"Clean up time 4\n");
+  pts->Delete();
+  //  fprintf(stderr,"Clean up time 41\n");
+  output->SetLines(newLines);
+  //  fprintf(stderr,"Clean up time 42\n");
+  newLines->Delete();
+  //  fprintf(stderr,"Clean up time 43\n");
+
+  // Delete the streamers since they are no longer needed
+  delete [] this->Streamers;
+  this->Streamers = 0;
+  this->NumberOfStreamers = 0;
+  
+  //fprintf(stderr,"Clean up time 45\n");
+
+  output->Squeeze();
+  //  fprintf(stderr,"Clean up time 46\n");
+
+}
+
+void vtkmpjVectorStreamline::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+
+  os << indent << "Step Length: " << this->StepLength << "\n";
+
+}
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjVectorStreamline.h b/bioimagesuite30_src/mpjCommon/vtkmpjVectorStreamline.h
new file mode 100644
index 0000000..1ba294e
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjVectorStreamline.h
@@ -0,0 +1,73 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __vtkmpjVectorStreamline_h
+#define __vtkmpjVectorStreamline_h
+
+#include "vtkmpjStreamer.h"
+
+class vtkmpjVectorStreamline : public vtkmpjStreamer
+{
+public:
+  vtkTypeMacro(vtkmpjVectorStreamline,vtkmpjStreamer);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Construct object with step size set to 1.0.
+  static vtkmpjVectorStreamline *New();
+
+  // Description:
+  // Specify the length of a line segment. The length is expressed in terms of
+  // elapsed time. Smaller values result in smoother appearing streamlines, but
+  // greater numbers of line primitives.
+  vtkSetClampMacro(StepLength,double,0.000001,VTK_LARGE_FLOAT);
+  vtkGetMacro(StepLength,double);
+
+protected:
+  vtkmpjVectorStreamline();
+  virtual ~vtkmpjVectorStreamline() {}
+
+  // Convert streamer array into vtkPolyData
+  void Execute();
+
+  // the length of line primitives
+  double StepLength;
+
+private:
+  vtkmpjVectorStreamline(const vtkmpjVectorStreamline&);  // Not implemented.
+  void operator=(const vtkmpjVectorStreamline&);  // Not implemented.
+};
+
+#endif
+
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjVectorStreamlineStatistics.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjVectorStreamlineStatistics.cpp
new file mode 100644
index 0000000..ac5b929
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjVectorStreamlineStatistics.cpp
@@ -0,0 +1,105 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjVectorStreamlineStatistics.h"
+
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkPolyLine.h"
+
+vtkStandardNewMacro(vtkmpjVectorStreamlineStatistics);
+
+// Construct object 
+vtkmpjVectorStreamlineStatistics::vtkmpjVectorStreamlineStatistics()
+{
+  this->NumberOfFibers = 0;
+  this->Minimum = this->Maximum = this->Mean = this->Variance = 0.0;
+}
+
+void vtkmpjVectorStreamlineStatistics::Execute()
+{
+  vtkPolyData *input = this->GetInput();
+  //vtkPolyData *output = this->GetOutput();
+  vtkPointData *pd=input->GetPointData();
+  vtkCellData *cd=input->GetCellData();
+  
+  //vtkPointData *outPD=output->GetPointData();
+  //vtkCellArray *inLines = NULL;
+  
+
+  vtkIdType numCells = input->GetNumberOfCells();
+
+  vtkDataArray *scalars = cd->GetScalars();
+  
+  double sum = 0.0, sum2=0.0;
+  double min = 0.0, max=0.0;
+  double val = 0.0, var = 0.0, mean=0.0;
+
+  if (numCells > 0) {
+
+    min = scalars->GetComponent(0, 0);
+    max = min;
+    
+    for (int i=0; i<numCells; i++) {
+      
+      val = scalars->GetComponent(0, i);
+      if (val < min) min = val;
+      if (val > max) max = val;
+      
+      sum += val;
+      sum2 += val*val;      
+    }
+
+    mean = sum / (float)numCells;
+
+    if (numCells > 1) {
+      var = (sum2 - (((float)numCells)*mean*mean))/((float)numCells-1);
+    }
+  }
+
+  printf("sum=%f\n", sum);
+  printf("sum2=%f\n",sum2);
+  printf("mean=%f\n",mean);
+  printf("variance=%f\n",var);
+
+  this->NumberOfFibers = numCells;
+  this->Minimum = min;
+  this->Maximum = max;
+  this->Mean = mean;
+  this->Variance = var;
+}
+
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjVectorStreamlineStatistics.h b/bioimagesuite30_src/mpjCommon/vtkmpjVectorStreamlineStatistics.h
new file mode 100644
index 0000000..b3cb6e1
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjVectorStreamlineStatistics.h
@@ -0,0 +1,79 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjVectorStreamlineStatistics_h
+#define __vtkmpjVectorStreamlineStatistics_h
+
+#include "vtkPolyDataToPolyDataFilter.h"
+#include "vtkCellArray.h"
+#include "vtkCellData.h"
+#include "vtkDataArray.h"
+#include "vtkFloatArray.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+
+class vtkmpjVectorStreamlineStatistics : public vtkPolyDataToPolyDataFilter
+{
+public:
+  vtkTypeMacro(vtkmpjVectorStreamlineStatistics,vtkPolyDataToPolyDataFilter);
+
+  // Description:
+  // Construct object 
+  static vtkmpjVectorStreamlineStatistics *New();
+
+  // Get statistics across fibers
+  vtkGetMacro(NumberOfFibers, int);
+
+  vtkGetMacro(Minimum, float);
+  vtkGetMacro(Maximum, float);
+  vtkGetMacro(Mean, float);
+  vtkGetMacro(Variance, float);
+  
+ protected:
+  vtkmpjVectorStreamlineStatistics();
+  ~vtkmpjVectorStreamlineStatistics() {}
+  
+  // Usual data generation method
+  void Execute();
+  
+  int NumberOfFibers;
+  float Minimum;
+  float Maximum;
+  float Variance;
+  float Mean;
+ 
+private:
+  vtkmpjVectorStreamlineStatistics(const vtkmpjVectorStreamlineStatistics&);// Not implemented.
+  void operator=(const vtkmpjVectorStreamlineStatistics&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjVertexSource.cpp b/bioimagesuite30_src/mpjCommon/vtkmpjVertexSource.cpp
new file mode 100644
index 0000000..c02c762
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjVertexSource.cpp
@@ -0,0 +1,99 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjVertexSource.h"
+#include "vtkPointSet.h"
+
+vtkStandardNewMacro(vtkmpjVertexSource);
+
+// Construct object with scaling on and scale factor 1.0. 
+vtkmpjVertexSource::vtkmpjVertexSource()
+{
+  this->NumberOfPoints = 0;
+  this->Points = NULL;
+  this->ScaleFactor = 1.0;
+}
+
+vtkmpjVertexSource::~vtkmpjVertexSource()
+{
+  if (this->Points != NULL)
+    this->Points->Delete();
+}
+
+void vtkmpjVertexSource::Execute()
+{
+  double *pt, x[3];
+  vtkIdType i;
+
+  vtkPoints *newPoints;
+  vtkCellArray *newVerts;
+  vtkPolyData *output = this->GetOutput();
+
+  if (this->Points == NULL) 
+    return;
+  
+  int numpts = this->Points->GetNumberOfPoints();
+ 
+  newPoints = vtkPoints::New();
+  newPoints->Allocate(numpts);
+  newVerts = vtkCellArray::New();
+  newVerts->Allocate(newVerts->EstimateSize(1,numpts));
+  
+  newVerts->InsertNextCell(numpts);
+  
+  for (i=0; i<numpts; i++)
+    {
+      pt = this->Points->GetPoint(i);
+      
+      x[0] = pt[0] * this->ScaleFactor;
+      x[1] = pt[1] * this->ScaleFactor;
+      x[2] = pt[2] * this->ScaleFactor;
+      
+      newVerts->InsertCellPoint(newPoints->InsertNextPoint(x));
+    }
+  
+  //
+  // Update ourselves and release memory
+  //
+  output->SetPoints(newPoints);
+  newPoints->Delete();
+  
+  output->SetVerts(newVerts);
+  newVerts->Delete();
+}
+
+void vtkmpjVertexSource::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+  
+  os << indent << "Scale Factor: " << this->ScaleFactor << "\n";
+}
+
diff --git a/bioimagesuite30_src/mpjCommon/vtkmpjVertexSource.h b/bioimagesuite30_src/mpjCommon/vtkmpjVertexSource.h
new file mode 100644
index 0000000..7e8d940
--- /dev/null
+++ b/bioimagesuite30_src/mpjCommon/vtkmpjVertexSource.h
@@ -0,0 +1,88 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjVertexSource_h
+#define __vtkmpjVertexSource_h
+
+#include "vtkPolyDataSource.h"
+#include "vtkCell.h"
+#include "vtkCellArray.h"
+#include "vtkDataSet.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPolyData.h"
+#include "vtkTransform.h"
+#include "vtkPoints.h"
+
+class vtkmpjVertexSource : public vtkPolyDataSource
+{
+public:
+  vtkTypeMacro(vtkmpjVertexSource,vtkPolyDataSource);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  static vtkmpjVertexSource *New();
+
+  // Description:
+  // Specify scale factor to scale object by. (Scale factor always affects
+  // output even if scaling is off.)
+  vtkSetMacro(ScaleFactor,float);
+  vtkGetMacro(ScaleFactor,float);
+
+  // Description:
+  // Specify number of points
+  vtkSetMacro(NumberOfPoints,int);
+  vtkGetMacro(NumberOfPoints,int);
+
+  // Description:
+  // Sets/Gets the array of points
+  vtkSetObjectMacro(Points, vtkPoints);
+  vtkGetObjectMacro(Points, vtkPoints);
+
+protected:
+  int NumberOfPoints;
+  vtkPoints *Points;
+  
+  float ScaleFactor; // Scale factor to use to scale geometry
+   
+  vtkmpjVertexSource();
+  ~vtkmpjVertexSource();
+
+  void Execute();
+
+private:
+  vtkmpjVertexSource(const vtkmpjVertexSource&);  // Not implemented.
+  void operator=(const vtkmpjVertexSource&);  // Not implemented.
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/CMakeLists.txt b/bioimagesuite30_src/mpjDiffusion/CMakeLists.txt
new file mode 100644
index 0000000..238cef8
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/CMakeLists.txt
@@ -0,0 +1,95 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+SET(KIT vtkmpjDiffusion)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/mpjCommon)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/mpjDiffusion)
+
+
+SET (KITSRCS
+     vtkmpjTensorLeastSquares.cpp
+     vtkmpjImageTensorInvariants.cpp
+     vtkmpjImageTensorCoherence.cpp
+     vtkmpjImageTensorProduct.cpp
+     vtkmpjLatticeAnisotropy.cpp
+     vtkmpjImageToTensors.cpp
+     vtkmpjImageToVectors.cpp
+     vtkmpjImageSymmetricTensor.cpp
+     vtkmpjTensorGeometryMetrics.cpp
+     vtkmpjImageTensorMultiply.cpp
+     vtkmpjApparentDiffusion.cpp
+     vtkmpjTensorToApparentDiffusion.cpp
+     vtkmpjImageTensorColor.cpp
+     vtkmpjImageDotProduct.cpp
+     vtkmpjImageTensorSimilarity.cpp
+     vtkmpjImageTensorVariance.cpp
+     vtkmpjQBallImaging.cpp
+     vtkmpjImageTensorTransform.cpp
+     vtkmpjHeartFiberAngle.cpp
+     vtkmpjHeartSheetAngle.cpp
+     vtkmpjTensorBMatrixLeastSquares.cpp
+     vtkmpjImageTensorEigenAnalysis.cpp
+)
+
+
+SET(KITLIBS
+  vtkmpjCommonTCL
+  vtkpxCommonTCL
+  vtkCommonTCL
+  ${BIOIMAGESUITE3_COMMON_LIBS}
+)
+
+SET(KITJAVALIBS
+  vtkmpjCommonJava
+  vtkmpjCommon
+  vtkpxCommonJava
+  vtkpxCommon
+  ${BIOIMAGESUITE3_COMMON_JAVALIBS}
+)
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+SET (KITEXTRAFILES)
+SET (KITTCLSRCS )
+
+
+bis_complex("mpjDiffusion" ${KIT} ${FILELIST})
+
+
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjApparentDiffusion.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjApparentDiffusion.cpp
new file mode 100644
index 0000000..be18f2f
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjApparentDiffusion.cpp
@@ -0,0 +1,195 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjApparentDiffusion.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjApparentDiffusion* vtkmpjApparentDiffusion::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjApparentDiffusion");
+  if(ret)
+    {
+      return (vtkmpjApparentDiffusion*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjApparentDiffusion;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjApparentDiffusion::vtkmpjApparentDiffusion()
+{
+  this->ReplaceScalars = 1;
+  this->Baseline = NULL;
+  this->Mask = NULL;
+  this->Shift = 0.0;
+  this->bValue = 1.0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjApparentDiffusion::~vtkmpjApparentDiffusion()
+{
+  if (this->Baseline != NULL)
+  this->Baseline->Delete();
+  if (this->Mask != NULL)
+    this->Mask->Delete();  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjApparentDiffusion::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  if (this->Baseline == NULL) {
+   vtkErrorMacro(<<"No baseline (S0) image specified!");
+   return;
+  }
+  
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+    
+  output->SetNumberOfScalarComponents(nc);
+  output->SetScalarType(VTK_FLOAT);
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjApparentDiffusion::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  vtkPointData *inPD = input->GetPointData();
+  vtkDataArray* in = input->GetPointData()->GetScalars();
+  vtkIdType numTuples = in->GetNumberOfTuples();
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkPointData *outPD=output->GetPointData();
+  vtkDataArray *out=outPD->GetScalars();
+  vtkFloatArray *diffusion=NULL;
+  vtkDataArray* baseline=NULL;
+  vtkDataArray* mask=NULL;
+  
+  if (this->ReplaceScalars == 0) {
+    diffusion = vtkFloatArray::New();
+    diffusion->SetName("diffusion");
+    diffusion->SetNumberOfComponents(in->GetNumberOfComponents());
+    diffusion->SetNumberOfTuples(numTuples);
+  }
+  
+  if (this->Baseline != NULL) 
+    baseline = this->Baseline->GetPointData()->GetScalars();
+  
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  int nc=in->GetNumberOfComponents();
+  
+  int index=0;
+
+  for (int k=0;k<dim[2];k++) {    
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  int output = 1;
+	  float baseln;
+	  
+	  baseln = float(baseline->GetComponent(index, 0)) + this->Shift;
+	  output = (mask != NULL)?(mask->GetComponent(index, 0) > 0) : 1;
+	  
+	  if (output) {
+	    
+	    int abort = 0;	    	 
+
+	    // Calculate ADCs
+	    for(int n=0; n<nc && !abort; n++) {	      
+	      float value = float(in->GetComponent(index, n)) + this->Shift;
+	      abort = (value <= 0);
+	      float adc = log(baseln / value) / this->bValue; 
+	      if (this->ReplaceScalars) {
+		out->SetComponent(index, n, adc);
+	      } else {
+		diffusion->SetComponent(index, n, adc);
+	      }
+	    }
+	    
+	    if (abort) {
+	      for(int n=0; n<nc; n++) {
+		if (this->ReplaceScalars) {
+		  out->SetComponent(index, n, 0);
+		} else {
+		  diffusion->SetComponent(index, n, 0);
+		}
+	      }
+	    }
+
+	  }	  
+	  
+	  ++index;	  
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+
+  // If not to replace data, simply add the new field
+  if (this->ReplaceScalars == 0) {
+
+    outPD->AddArray(diffusion);
+    diffusion->Delete();
+
+    outPD->PassData(inPD);
+  }
+
+
+  this->UpdateProgress(1.0);
+   
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjApparentDiffusion.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjApparentDiffusion.h
new file mode 100644
index 0000000..424b222
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjApparentDiffusion.h
@@ -0,0 +1,95 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjTensorLeastSquares_h
+#define __vtkmpjTensorLeastSquares_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkDoubleArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjApparentDiffusion : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjApparentDiffusion *New();
+  vtkTypeMacro(vtkmpjApparentDiffusion,vtkpxSimpleImageToImageFilter);
+  
+  // Sets/Gets the baseline image A(b=0); the echo amplitude without any
+  // diffusion attenuation
+  vtkSetObjectMacro(Baseline, vtkImageData);
+  vtkGetObjectMacro(Baseline, vtkImageData);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents of tensor
+  // computation. If a mask is not provided, tensor is
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Set/Get Shift Factor so that S(b)/S(0) can be computed when S(0)=0
+  // ADC = (S(b)+shift)/(S(0)+shift), shift ~= 0
+  vtkSetMacro(Shift,float);
+  vtkGetMacro(Shift,float);
+  
+  // Description:
+  // Set/Get the b-Value
+  vtkSetMacro(bValue,float);
+  vtkGetMacro(bValue,float);
+  
+  // Description: Replace DWs with the computed ADCs or keep DWs as 
+  // scalars and add a new "diffusion" ADC field to the dataset
+  vtkGetMacro(ReplaceScalars,int);
+  vtkSetClampMacro(ReplaceScalars,int,0,1);
+  vtkBooleanMacro(ReplaceScalars,int);
+
+ protected:
+  float Shift;
+  float bValue;
+  int ReplaceScalars;
+  vtkImageData *Baseline;
+  vtkImageData *Mask;
+
+  vtkmpjApparentDiffusion();
+  virtual ~vtkmpjApparentDiffusion();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  
+  vtkmpjApparentDiffusion(const vtkmpjApparentDiffusion&); // Not implemented
+  void operator=(const vtkmpjApparentDiffusion&); // Not implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjHeartFiberAngle.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjHeartFiberAngle.cpp
new file mode 100644
index 0000000..7782842
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjHeartFiberAngle.cpp
@@ -0,0 +1,180 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjHeartFiberAngle.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjHeartFiberAngle* vtkmpjHeartFiberAngle::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjHeartFiberAngle");
+  if(ret)
+    {
+      return (vtkmpjHeartFiberAngle*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjHeartFiberAngle;
+}
+
+// Construct object with no children.
+vtkmpjHeartFiberAngle::vtkmpjHeartFiberAngle()
+{
+  this->Mask = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjHeartFiberAngle::~vtkmpjHeartFiberAngle()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjHeartFiberAngle::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+  
+  output->SetNumberOfScalarComponents(1);
+  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjHeartFiberAngle::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int nc = input->GetNumberOfScalarComponents();
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* in=input->GetPointData()->GetScalars(); 
+  vtkDataArray* out=output->GetPointData()->GetScalars();  
+  
+  vtkDataArray* mask=NULL;
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  float sum, dot, angle, dot2;
+  float v1[3], v2[3], v3[3], temp[3];
+  float vp[3], vf[3], nvf[3], sign, theta;
+  float Rz[3][3];
+  int index=0;
+  int inmask;
+  
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  inmask = (mask != NULL)?(mask->GetComponent(index, 0) > 0) : 1;
+	  
+	  if (inmask) {
+	    
+	    // calculate lv coordinate system
+	    // radial vector
+	    v1[0]=i-this->Center[0]; 
+	    v1[1]=j-this->Center[1]; 
+	    v1[2]=0;
+	    (void)vtkMath::Normalize(v1);
+	    
+	    // longitudinal vector
+	    v3[0]=0.0;
+	    v3[1]=0.0;
+	    v3[2]=1.0;
+	    
+	    // get circumferential by cross-product
+	    vtkMath::Cross(v1,v3,v2);	
+
+	    // get fiber vector
+	    vf[0] = in->GetComponent(index, 0);
+	    vf[1] = in->GetComponent(index, 1);
+	    vf[2] = in->GetComponent(index, 2);
+	    (void)vtkMath::Normalize(vf);
+	    if (vf[2] > 0) {
+	      vf[0]=-vf[0]; vf[1]=-vf[1]; vf[2]=-vf[2];
+	    }
+	    
+	    // projected fiber vector
+	    vp[0] = vf[0];
+	    vp[1] = vf[1];
+	    vp[2] = 0;
+	    (void)vtkMath::Normalize(vp);
+	    
+	    dot = vtkMath::Dot(v2,vp);
+	    dot2 = vtkMath::Dot(v1,vp);
+	    theta = acos(dot);
+
+	    if (dot2 > 0) theta*=-1;
+	    if (dot < 0) theta += 3.14159;
+
+	    Rz[0][0] = cos(theta);  Rz[0][1] = -sin(theta);  Rz[0][2] = 0;
+	    Rz[1][0] = sin(theta);  Rz[1][1] = cos(theta);   Rz[1][2] = 0;
+	    Rz[2][0] = 0;           Rz[2][1] = 0;            Rz[2][2] = 1;
+	    (void)vtkMath::Multiply3x3(Rz,vf,nvf);
+
+	    dot = vtkMath::Dot(v2,nvf);
+#if ((VTK_MAJOR_VERSION >= 5)&&(VTK_MINOR_VERSION >= 4))
+            angle = vtkMath::DegreesFromRadians(acos(dot));
+#else
+            angle = acos(dot) * vtkMath::RadiansToDegrees();
+#endif
+
+	    if (angle > 90) angle -= 180;	    
+	    out->SetComponent(index, 0, angle);
+
+	  } else {
+	    out->SetComponent(index, 0, 180.0);
+	  }
+	  
+	  ++index;	   	 
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjHeartFiberAngle.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjHeartFiberAngle.h
new file mode 100644
index 0000000..22d15a1
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjHeartFiberAngle.h
@@ -0,0 +1,81 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjHeartFiberAngle.h 
+   
+      Marcel Jackowski, 2006
+
+      This class computes the fiber angle.
+
+*/
+
+#ifndef __vtkmpjHeartFiberAngle_h
+#define __vtkmpjHeartFiberAngle_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkMath.h"
+
+class vtkmpjHeartFiberAngle : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjHeartFiberAngle *New();
+  vtkTypeMacro(vtkmpjHeartFiberAngle,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Sets/Gets mask where eigenvalues are to be computed
+  vtkGetObjectMacro(Mask, vtkImageData);
+  vtkSetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Center of rotation
+  vtkGetVectorMacro(Center, float, 3);
+  vtkSetVectorMacro(Center, float, 3);
+
+ protected:
+  float Center[3];
+  vtkImageData *Mask;
+  
+  vtkmpjHeartFiberAngle();
+  virtual ~vtkmpjHeartFiberAngle();
+  
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+  
+ private:
+  vtkmpjHeartFiberAngle(const vtkmpjHeartFiberAngle&); // Not implemented
+  void operator=(const vtkmpjHeartFiberAngle&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjHeartSheetAngle.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjHeartSheetAngle.cpp
new file mode 100644
index 0000000..32327a8
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjHeartSheetAngle.cpp
@@ -0,0 +1,184 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjHeartSheetAngle.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjHeartSheetAngle* vtkmpjHeartSheetAngle::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjHeartSheetAngle");
+  if(ret)
+    {
+      return (vtkmpjHeartSheetAngle*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjHeartSheetAngle;
+}
+
+// Construct object with no children.
+vtkmpjHeartSheetAngle::vtkmpjHeartSheetAngle()
+{
+  this->Mask = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjHeartSheetAngle::~vtkmpjHeartSheetAngle()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjHeartSheetAngle::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+  
+  output->SetNumberOfScalarComponents(1);
+  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjHeartSheetAngle::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int nc = input->GetNumberOfScalarComponents();
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* in=input->GetPointData()->GetScalars(); 
+  vtkDataArray* out=output->GetPointData()->GetScalars();  
+  
+  vtkDataArray* mask=NULL;
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  float sum, dot, angle, dot2;
+  float v1[3], v2[3], v3[3], temp[3];
+  float vp[3], vf[3], nvf[3], sign, theta;
+  float Rz[3][3];
+  int index=0;
+  int inmask;
+  
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  inmask = (mask != NULL)?(mask->GetComponent(index, 0) > 0) : 1;
+	  
+	  if (inmask) {
+	    
+	    // calculate lv coordinate system
+	    // radial vector
+	    v1[0]=i-this->Center[0]; 
+	    v1[1]=j-this->Center[1]; 
+	    v1[2]=0;
+	    (void)vtkMath::Normalize(v1);
+	    
+	    // longitudinal vector
+	    v3[0]=0.0;
+	    v3[1]=0.0;
+	    v3[2]=1.0;
+	    
+	    // get circumferential by cross-product
+	    vtkMath::Cross(v1,v3,v2);	
+
+	    // get secondary eigenvector
+	    vf[0] = in->GetComponent(index, 6);
+	    vf[1] = in->GetComponent(index, 7);
+	    vf[2] = in->GetComponent(index, 8);
+	    (void)vtkMath::Normalize(vf);
+	    if (vf[2] > 0) {
+	      vf[0]=-vf[0]; vf[1]=-vf[1]; vf[2]=-vf[2];
+	    }
+	    
+	    // projected fiber vector
+	    vp[0] = vf[0];
+	    vp[1] = vf[1];
+	    vp[2] = 0;
+	    (void)vtkMath::Normalize(vp);
+	    
+	    dot = vtkMath::Dot(v1,vp);
+	    dot2 = vtkMath::Dot(v2,vp);
+	    theta = acos(dot);
+	    
+	    if (dot2 < 0) theta*=-1;
+	    //if (dot > 0) theta += 3.14159;
+	    
+	    Rz[0][0] = cos(theta);  Rz[0][1] = -sin(theta);  Rz[0][2] = 0;
+	    Rz[1][0] = sin(theta);  Rz[1][1] = cos(theta);   Rz[1][2] = 0;
+	    Rz[2][0] = 0;           Rz[2][1] = 0;            Rz[2][2] = 1;
+
+	    (void)vtkMath::Multiply3x3(Rz,vf,nvf);
+	    (void)vtkMath::Normalize(nvf);
+
+	    dot = vtkMath::Dot(v1,nvf);
+#if ((VTK_MAJOR_VERSION >= 5)&&(VTK_MINOR_VERSION >= 4))
+            angle = vtkMath::DegreesFromRadians(acos(dot));
+#else
+            angle = acos(dot) * vtkMath::RadiansToDegrees();
+#endif
+
+	    if (angle > 90) angle -= 180;
+	    //if (angle > 0) angle-=90; else angle+=90;
+
+	    out->SetComponent(index, 0, angle);
+
+	  } else {
+	    out->SetComponent(index, 0, 180.0);
+	  }
+	  
+	  ++index;	   	 
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjHeartSheetAngle.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjHeartSheetAngle.h
new file mode 100644
index 0000000..4d252ce
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjHeartSheetAngle.h
@@ -0,0 +1,81 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjHeartSheetAngle.h 
+   
+      Marcel Jackowski, 2006
+
+      This class computes the fiber angle.
+
+*/
+
+#ifndef __vtkmpjHeartSheetAngle_h
+#define __vtkmpjHeartSheetAngle_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkMath.h"
+
+class vtkmpjHeartSheetAngle : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjHeartSheetAngle *New();
+  vtkTypeMacro(vtkmpjHeartSheetAngle,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Sets/Gets mask where eigenvalues are to be computed
+  vtkGetObjectMacro(Mask, vtkImageData);
+  vtkSetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Center of rotation
+  vtkGetVectorMacro(Center, float, 3);
+  vtkSetVectorMacro(Center, float, 3);
+
+ protected:
+  float Center[3];
+  vtkImageData *Mask;
+  
+  vtkmpjHeartSheetAngle();
+  virtual ~vtkmpjHeartSheetAngle();
+  
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+  
+ private:
+  vtkmpjHeartSheetAngle(const vtkmpjHeartSheetAngle&); // Not implemented
+  void operator=(const vtkmpjHeartSheetAngle&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageDotProduct.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageDotProduct.cpp
new file mode 100644
index 0000000..4462b22
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageDotProduct.cpp
@@ -0,0 +1,172 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageDotProduct.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageDotProduct* vtkmpjImageDotProduct::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageDotProduct");
+  if(ret)
+    {
+      return (vtkmpjImageDotProduct*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageDotProduct;
+}
+
+// Construct object with no children.
+vtkmpjImageDotProduct::vtkmpjImageDotProduct()
+{
+  this->Mask = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageDotProduct::~vtkmpjImageDotProduct()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageDotProduct::SetInput1(vtkImageData *input)
+{
+  this->vtkProcessObject::SetNthInput(0, input);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageDotProduct::SetInput2(vtkImageData *input)
+{
+  this->vtkProcessObject::SetNthInput(1, input);
+}
+
+//----------------------------------------------------------------------------
+vtkImageData *vtkmpjImageDotProduct::GetInput(int index)
+{
+  if (this->NumberOfInputs <= index)
+    {
+      return NULL;
+    }
+  
+  return (vtkImageData *)(this->Inputs[index]);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageDotProduct::ExecuteInformation()
+{
+  vtkImageData *input1=this->GetInput(0);
+  vtkImageData *input2=this->GetInput(1);
+  vtkImageData *output=this->GetOutput();
+  
+  if ((input1==NULL) || (input2==NULL)) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  int dim[3];  input1->GetDimensions(dim);
+  int nc1=input1->GetNumberOfScalarComponents();
+  int nc2=input2->GetNumberOfScalarComponents();
+  
+  output->SetNumberOfScalarComponents(1);
+  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageDotProduct::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  vtkImageData *input1 = this->GetInput(0);
+  vtkImageData *input2 = this->GetInput(1);
+  int nc = input1->GetNumberOfScalarComponents();
+  int dim[3];  input1->GetDimensions(dim);
+  
+  vtkDataArray* in1=input1->GetPointData()->GetScalars(); 
+  vtkDataArray* in2=input2->GetPointData()->GetScalars(); 
+  vtkDataArray* out=output->GetPointData()->GetScalars();  
+  
+  vtkDataArray* mask=NULL;
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  float v1[3], v2[3], sum, dot, angle;
+  int index=0;
+  int inmask;
+  
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  inmask = (mask != NULL)?(mask->GetComponent(index, 0) > 0) : 1;
+	  
+	  if (inmask) {
+	    
+	    v1[0] = in1->GetComponent(index, 0);
+	    v1[1] = in1->GetComponent(index, 1);
+	    v1[2] = in1->GetComponent(index, 2);
+
+	    v2[0] = in2->GetComponent(index, 0);
+	    v2[1] = in2->GetComponent(index, 1);
+	    v2[2] = in2->GetComponent(index, 2);
+
+	    (void)vtkMath::Normalize(v1);
+	    (void)vtkMath::Normalize(v2);
+
+	    dot = v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
+
+	    //angle = (acos(dot) / (2.0*vtkMath::Pi())) * 360.0;
+	    //if (angle > 90) angle -= 90.0;
+
+	    out->SetComponent(index, 0, fabs(dot));
+
+	  } else {
+	    out->SetComponent(index, 0, 0.0);
+	  }
+	  
+	  ++index;	   	 
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageDotProduct.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageDotProduct.h
new file mode 100644
index 0000000..7d696eb
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageDotProduct.h
@@ -0,0 +1,79 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjImageDotProduct.h 
+   
+      Marcel Jackowski, 2002
+
+      This class computes the dot product of two vector images.
+
+*/
+
+#ifndef __vtkmpjImageDotProduct_h
+#define __vtkmpjImageDotProduct_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkMath.h"
+
+class vtkmpjImageDotProduct : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageDotProduct *New();
+  vtkTypeMacro(vtkmpjImageDotProduct,vtkpxSimpleImageToImageFilter);
+
+  void SetInput1(vtkImageData *input);
+  void SetInput2(vtkImageData *input);
+  vtkImageData *GetInput(int index);
+  
+  // Description:
+  // Sets/Gets mask where eigenvalues are to be computed
+  vtkGetObjectMacro(Mask, vtkImageData);
+  vtkSetObjectMacro(Mask, vtkImageData);
+
+ protected:
+  vtkImageData *Mask;
+
+  vtkmpjImageDotProduct();
+  virtual ~vtkmpjImageDotProduct();
+  
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+  
+ private:
+  vtkmpjImageDotProduct(const vtkmpjImageDotProduct&); // Not implemented
+  void operator=(const vtkmpjImageDotProduct&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageSymmetricTensor.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageSymmetricTensor.cpp
new file mode 100644
index 0000000..51d23bb
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageSymmetricTensor.cpp
@@ -0,0 +1,314 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageSymmetricTensor.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageSymmetricTensor* vtkmpjImageSymmetricTensor::New() 
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageSymmetricTensor");
+  
+  if(ret) {
+    return (vtkmpjImageSymmetricTensor*)ret;
+  }
+  
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageSymmetricTensor;
+}
+
+// Construct object with no children.
+vtkmpjImageSymmetricTensor::vtkmpjImageSymmetricTensor()
+{  
+  Angle = 0.0;
+  AddNoise = 0;
+  NoiseLevel = 10.0;
+  Eigenvalues[0]=1.0;
+  Eigenvalues[1]=1.0;
+  Eigenvalues[2]=1.0;
+  Direction[0]=1.0;
+  Direction[1]=0.0;
+  Direction[2]=0.0;
+  Mask = NULL;
+  InverseMask = 0;
+  UseInputForDirection = 0;
+  OutputType = VTK_MPJ_OUTPUT_FULL_TENSOR;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageSymmetricTensor::~vtkmpjImageSymmetricTensor()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();  
+}
+
+// ----------------------------------------------------------------------------
+float vtkmpjImageSymmetricTensor::GetGaussianDeviate()
+{
+  static int iset=0;
+  static float gset;
+  float fac,rsq,v1,v2;
+
+  if  (iset == 0) 
+    {
+      do 
+	{
+	  v1=2.0*vtkMath::Random()-1.0;
+	  v2=2.0*vtkMath::Random()-1.0;
+	  rsq=v1*v1+v2*v2;
+	} 
+      while (rsq >= 1.0 || rsq == 0.0);
+      
+      fac=sqrt(-2.0*log(rsq)/rsq);
+      gset=v1*fac;
+      iset=1;
+      return v2*fac;
+    } 
+  else
+    {
+      iset=0;
+      return gset;
+    }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageSymmetricTensor::PrintMatrix3x3(char *title, float M[3][3])
+{
+  printf("%s",title);
+  printf("%f %f %f\n",M[0][0],M[0][1],M[0][2]);
+  printf("%f %f %f\n",M[1][0],M[1][1],M[1][2]);
+  printf("%f %f %f\n",M[2][0],M[2][1],M[2][2]);
+  printf("===============================\n");
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageSymmetricTensor::ExecuteInformation()
+{
+  // start with defaults
+  vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  vtkImageData *output = this->GetOutput();
+  vtkImageData *input = this->GetInput();
+  int dim[3];  input->GetDimensions(dim);
+  
+  if (this->OutputType == VTK_MPJ_OUTPUT_FULL_TENSOR) {
+    output->SetNumberOfScalarComponents(9);
+  } else {
+    output->SetNumberOfScalarComponents(6);
+  }
+    
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageSymmetricTensor::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* in=input->GetPointData()->GetScalars(); 
+  vtkDataArray* out=output->GetPointData()->GetScalars();  
+
+  int nc = input->GetNumberOfScalarComponents();
+  
+  vtkDataArray* mask = (this->Mask != NULL) ? 
+    this->Mask->GetPointData()->GetScalars() : NULL;
+  
+  float D[3][3]={{0,0,0},{0,0,0},{0,0,0}};  /* matrix of eigenvalues in mask */
+  float V[3][3];                            /* matrix of eigenvectors in mask */
+  float v1[3], v2[3], v3[3];
+  float R1[3][3], R2[3][3];
+  float T[3][3];                            /* tensor matrix */
+
+  float Dxx;
+  float Dyy;
+  float Dzz;
+  float Dxy;
+  float Dxz;
+  float Dyz;
+
+  int index=0;
+
+  D[0][0] = this->Eigenvalues[0];
+  D[1][1] = this->Eigenvalues[1];
+  D[2][2] = this->Eigenvalues[2];
+
+  this->Direction[0] = 1.0;
+  this->Direction[1] = 0.0;
+  this->Direction[2] = 0.0;
+ 
+  //  (void) vtkMath::Normalize(this->Direction);
+  
+  //printf("Direction=%f %f %f\n",this->Direction[0],this->Direction[1],this->Direction[2]);
+  //printf("Eigenvalues=%f %f %f\n",this->Eigenvalues[0],this->Eigenvalues[1],this->Eigenvalues[2]);
+
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{		
+	  float noise[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
+	  
+	  /* generate noise */
+	  if (this->AddNoise) {
+	    for(int p=0; p<6; p++)
+	      noise[p] = this->NoiseLevel * this->GetGaussianDeviate();
+	  }	    	    
+
+	  if ((k > 24) && (k < 40) && (j > 24) && (j < 40) && (i > 8) && (i < 56)) {	   	    
+	    D[0][0] = this->Eigenvalues[0] + noise[0];
+	    D[1][1] = this->Eigenvalues[1] + noise[1];
+	    D[2][2] = this->Eigenvalues[2] + noise[2];
+	  } else {
+	    D[0][0] = this->Eigenvalues[2] + noise[0];
+	    D[1][1] = this->Eigenvalues[2] + noise[1];
+	    D[2][2] = this->Eigenvalues[2] + noise[2];
+	  }
+	  
+	  //float maskval = mask->GetComponent(index, 0);
+	  //int output = (mask != NULL)?((this->InverseMask ? maskval <= 0 : maskval > 0)):1;
+	  //	  int output=1;
+
+// 	  if (this->UseInputForDirection) {	   
+// 	    v1[0] = in->GetComponent(index, 0);
+// 	    v1[1] = in->GetComponent(index, 1);
+// 	    v1[2] = in->GetComponent(index, 2);
+// 	    (void) vtkMath::Normalize(v1);
+// 	    V[0][0] =  v1[0];
+// 	    V[1][0] =  v1[1];
+// 	    V[2][0] =  v1[2];
+// 	    } else {
+	    V[0][0] =  v1[0] = this->Direction[0];
+	    V[1][0] =  v1[1] = this->Direction[1];
+	    V[2][0] =  v1[2] = this->Direction[2];
+	    //	  }
+	  
+	    //if (v1[0] == 0 && v1[1] == 0 && v1[2] == 0)
+	    //output = 0;
+	    //else {
+	    // printf("%f %f %f\n",v1[0],v1[1],v1[2]);
+	    //}
+
+	    //if (output) {	    	  	    
+
+	    //if (nc == 3) {
+	      /* get two perpendicular vectors */
+	      (void) vtkMath::Perpendiculars(v1,v2,v3,this->Angle);
+
+	      //} else {
+
+	      /* get other two perpendicular vectors */
+	      //v2[0] = in->GetComponent(index, 3);
+	      //v2[1] = in->GetComponent(index, 4);
+	      //v2[2] = in->GetComponent(index, 5);
+	      //(void) vtkMath::Normalize(v2);
+	      
+	      //v3[0] = in->GetComponent(index, 6);
+	      //v3[1] = in->GetComponent(index, 7);
+	      //v3[2] = in->GetComponent(index, 8);
+	      //(void) vtkMath::Normalize(v3);	  
+	      
+	      //}
+	    
+	    
+	    V[0][1]=v2[0]=0.0; 
+	    V[1][1]=v2[1]=1.0;    /* second eigenvector */
+	    V[2][1]=v2[2]=0.0;
+	    
+	    V[0][2]=v3[0]=0.0; 
+	    V[1][2]=v3[1]=0.0;    /* third eigenvector */
+	    V[2][2]=v3[2]=1.0;   	    
+	    
+	    /* Tensor = V * D * V' */
+	    (void) vtkMath::Transpose3x3(V,R1);
+	    (void) vtkMath::Multiply3x3(D,R1,R2);
+	    (void) vtkMath::Multiply3x3(V,R2,T);
+	    
+	    // (this->Debug)
+	    //this->PrintMatrix3x3("T=\n",T);
+	    
+	    /* generate noise */
+	    //if (this->AddNoise) {
+	    //for(int p=0; p<6; p++)
+	    //noise[p] = this->NoiseLevel * this->GetGaussianDeviate();
+	    //}	    	    
+	 	  
+	    Dxx = T[0][0]; //+ noise[0];
+	    Dyy = T[1][1]; //+ noise[3];
+	    Dzz = T[2][2];// + noise[5];
+	    Dxy = T[1][0];// + noise[1];
+	    Dxz = T[2][0];// + noise[2];
+	    Dyz = T[2][1];// + noise[4];
+
+	    //} else {
+	    
+	    //Dxx = 0 + noise[0];
+	    //Dyy = 0 + noise[3];
+	    //Dzz = 0 + noise[5];
+	    //Dxy = 0 + noise[1];
+	    //Dxz = 0 + noise[2];
+	    //Dyz = 0 + noise[4];
+	    
+	    //}
+
+	  if (this->OutputType == VTK_MPJ_OUTPUT_FULL_TENSOR) {
+	    out->SetComponent(index, 0, Dxx);
+	    out->SetComponent(index, 1, Dxy);
+	    out->SetComponent(index, 2, Dxz);
+	    out->SetComponent(index, 3, Dxy);
+	    out->SetComponent(index, 4, Dyy);
+	    out->SetComponent(index, 5, Dyz);
+	    out->SetComponent(index, 6, Dxz);
+	    out->SetComponent(index, 7, Dyz);
+	    out->SetComponent(index, 8, Dzz); 
+
+	  } else {
+	    out->SetComponent(index, 0, Dxx);
+	    out->SetComponent(index, 1, Dxy);
+	    out->SetComponent(index, 2, Dxz);
+	    out->SetComponent(index, 3, Dyy);
+	    out->SetComponent(index, 4, Dyz);
+	    out->SetComponent(index, 5, Dzz);	    
+	  }
+
+	  ++index;	   	  
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageSymmetricTensor.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageSymmetricTensor.h
new file mode 100644
index 0000000..fa8a53b
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageSymmetricTensor.h
@@ -0,0 +1,128 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjImageSymmetricTensor.h 
+
+      Marcel Jackowski, 2003.
+*/
+
+#ifndef __vtkmpjImageSymmetricTensor_h 
+#define __vtkmpjImageSymmetricTensor_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+
+#define VTK_MPJ_OUTPUT_FULL_TENSOR      0
+#define VTK_MPJ_OUTPUT_SYMMETRIC_TENSOR 1
+
+class vtkmpjImageSymmetricTensor : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageSymmetricTensor *New();
+  vtkTypeMacro(vtkmpjImageSymmetricTensor,vtkpxSimpleImageToImageFilter);
+  
+  // Description: Set/Get eigenvalues
+  vtkSetVector3Macro(Eigenvalues,float);
+  vtkGetVector3Macro(Eigenvalues,float);
+  
+  // Description: Set/Get direction
+  vtkSetVector3Macro(Direction,float);
+  vtkGetVector3Macro(Direction,float);
+  
+  // Description: Turn noise on/off
+  vtkGetMacro(AddNoise,int);
+  vtkSetClampMacro(AddNoise,int,0,1);
+  vtkBooleanMacro(AddNoise,int);
+
+  // Description: Enable inverse mask
+  vtkGetMacro(InverseMask,int);
+  vtkSetClampMacro(InverseMask,int,0,1);
+  vtkBooleanMacro(InverseMask,int);
+
+  // Description: Use input vector
+  vtkGetMacro(UseInputForDirection, int);
+  vtkSetClampMacro(UseInputForDirection, int,0,1);
+  vtkBooleanMacro(UseInputForDirection, int);
+
+  // Description: Output type
+  vtkGetMacro(OutputType,int);
+  vtkSetClampMacro(OutputType,int,VTK_MPJ_OUTPUT_FULL_TENSOR,VTK_MPJ_OUTPUT_SYMMETRIC_TENSOR);
+
+  void SetOutputTypeToFullTensor() { this->OutputType=VTK_MPJ_OUTPUT_FULL_TENSOR; };
+  void SetOutputTypeToSymmetricTensor() { this->OutputType=VTK_MPJ_OUTPUT_SYMMETRIC_TENSOR; };
+
+  // Description:
+  // Set/Get noise % level 
+  vtkGetMacro(NoiseLevel,float);
+  vtkSetClampMacro(NoiseLevel,float,0.0001,100.0);
+
+  // Description:
+  // Set/Get Angle to construct perpendicular vectors for tensor
+  vtkGetMacro(Angle,float);
+  vtkSetMacro(Angle,float);
+
+  // Description: 
+  // Sets/Gets mask for determining the extents of tensor
+  // computation. If a mask is not provided, tensor is
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+  
+ protected: 
+  float Angle;
+  int AddNoise;
+  int OutputType;
+  int InverseMask;
+  int UseInputForDirection;
+  float Eigenvalues[3];
+  float Direction[3];
+  float NoiseLevel;
+  vtkImageData *Mask;
+  
+  vtkmpjImageSymmetricTensor();
+  ~vtkmpjImageSymmetricTensor();
+  
+  float GetGaussianDeviate();
+  void PrintMatrix3x3(char *title, float M[3][3]);
+
+  virtual void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  
+ private:
+  vtkmpjImageSymmetricTensor(const vtkmpjImageSymmetricTensor&); // Not implemented
+  void operator=(const vtkmpjImageSymmetricTensor&); // Not implemented
+}; 
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorCoherence.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorCoherence.cpp
new file mode 100644
index 0000000..bc606a2
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorCoherence.cpp
@@ -0,0 +1,196 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageTensorCoherence.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageTensorCoherence* vtkmpjImageTensorCoherence::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageTensorCoherence");
+  if(ret)
+    {
+      return (vtkmpjImageTensorCoherence*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageTensorCoherence;
+}
+
+// Construct object with no children.
+vtkmpjImageTensorCoherence::vtkmpjImageTensorCoherence()
+{
+  this->KernelSize[0] = 3;
+  this->KernelSize[1] = 3;
+  this->KernelSize[2] = 3;
+  this->Mask = NULL;
+  this->MaskOutValue = 0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageTensorCoherence::~vtkmpjImageTensorCoherence()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorCoherence::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+  
+  if (nc < 9) {
+    vtkErrorMacro(<< "Three eigenvalues and three eigenvectors per voxel are required as input!");
+    return;
+  }
+  
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorCoherence::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+ 
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  int mink = this->KernelSize[2] / 2;
+  int minj = this->KernelSize[1] / 2;
+  int mini = this->KernelSize[0] / 2;
+  int total_ij = dim[0]*dim[1];
+  int index = 0;
+  float v[3], r[3];
+
+  /*  printf("mini=%d,minj=%d,mink=%d\n",mini,minj,mink);*/
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  if ((mask != NULL)?(mask->GetComponent(index, 0) > 0):1)
+	    {
+	      r[0] = in->GetComponent(index, 0);
+	      r[1] = in->GetComponent(index, 1);
+	      r[2] = in->GetComponent(index, 2);
+	      (void)vtkMath::Normalize(r);
+
+	      int count = 0;
+	      float sum=0;
+
+	      /* calculate neghborhood coherence */
+	      for (int nk=-mink; nk<=mink; nk++) {
+		int total_k = (k + nk) * total_ij;
+
+		for (int nj=-minj; nj<=minj; nj++) {
+		  int total_jk = total_k + (j + nj)*dim[0];
+
+		  for (int ni=-mini; ni<=mini; ni++) {
+
+		    /* skip center voxel */
+		    if (nk==0 && nj==0 && ni==0) continue;
+		    
+		    /* determine neighbor's address in image array */
+		    int nindex = total_jk + (i + ni);
+		    
+		    /* handle boundaries */
+		    if ((k+nk)>=0 && (j+nj)>=0 && (i+ni)>=0 &&
+			(k+nk)<dim[2] && (j+nj)<dim[1] && (i+ni)<dim[0] ) {
+		      
+		      /* if neighbor is in mask */
+		      if ((mask != NULL)?(mask->GetComponent(nindex, 0) > 0):1) {
+			
+			v[0] = in->GetComponent(nindex, 0);
+			v[1] = in->GetComponent(nindex, 1);
+			v[2] = in->GetComponent(nindex, 2);
+			(void)vtkMath::Normalize(v);
+			
+			float cossine = fabs(r[0]*v[0] + r[1]*v[1] + r[2]*v[2]);
+			
+			sum = sum + exp(cossine*cossine*cossine)-1.0;
+			
+			++count;
+		      }
+		    }
+		  }
+		}
+	      }
+	      
+	      if ( count > 0 ) {
+		sum = sum / (float)count; 
+		out->SetComponent(index, 0, sum);
+	      } else {
+		out->SetComponent(index, 0, this->MaskOutValue);
+	      }
+	      
+	    } else {
+	      out->SetComponent(index, 0, this->MaskOutValue);
+	    }
+	  
+	  ++index;
+	 
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+  }
+  
+  this->UpdateProgress(1.0);
+
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorCoherence.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorCoherence.h
new file mode 100644
index 0000000..0e1b7f5
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorCoherence.h
@@ -0,0 +1,87 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjImageTensorCoherence.h 
+   
+  Computes the intervoxel coherence index (CI) as
+  proposed by Klingberg et al, 1999.
+
+  Essentially the mean dot product of the principal eigenvector
+  in the neighborhood.
+
+  Marcel Jackowski, December 2002
+
+*/
+
+#ifndef __vtkmpjImageTensorCoherence_h
+#define __vtkmpjImageTensorCoherence_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjImageTensorCoherence : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageTensorCoherence *New();
+  vtkTypeMacro(vtkmpjImageTensorCoherence,vtkpxSimpleImageToImageFilter);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents for invariants
+  // computation. If a mask is not provided, invariants are
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Set/Get the kernel size for computations;
+  vtkSetVector3Macro(KernelSize,int);
+  vtkGetVector3Macro(KernelSize,int);
+  
+protected:
+  int KernelSize[3];
+  float MaskOutValue; 
+  vtkImageData *Mask;
+  
+  vtkmpjImageTensorCoherence();
+  virtual ~vtkmpjImageTensorCoherence();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  vtkmpjImageTensorCoherence(const vtkmpjImageTensorCoherence&); // Not implemented
+  void operator=(const vtkmpjImageTensorCoherence&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorColor.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorColor.cpp
new file mode 100644
index 0000000..d8e41fa
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorColor.cpp
@@ -0,0 +1,482 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageTensorColor.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageTensorColor* vtkmpjImageTensorColor::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageTensorColor");
+  if(ret)
+    {
+      return (vtkmpjImageTensorColor*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageTensorColor;
+}
+
+// Construct object with no children.
+vtkmpjImageTensorColor::vtkmpjImageTensorColor()
+{
+  this->Mask = NULL;
+  this->Magnitude = NULL;
+  this->MaskOutValue[0] = 0;
+  this->MaskOutValue[1] = 0;
+  this->MaskOutValue[2] = 0;
+  this->SaturationScale = 0.5;
+  this->Scaling = 1.0;
+  this->ColorSchemeType = VTK_MPJ_DEC_ABSOLUTE;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageTensorColor::~vtkmpjImageTensorColor()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+  if (this->Magnitude != NULL)
+    this->Magnitude->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorColor::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+  
+  if (nc < 9) {
+    vtkErrorMacro(<< "Three eigenvalues and three eigenvectors per voxel are required as input!");
+    return;
+  }
+  
+  output->SetNumberOfScalarComponents(3);  
+  output->SetScalarType(VTK_UNSIGNED_CHAR);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+
+void vtkmpjImageTensorColor::AbsoluteValueScheme(vtkImageData *input, vtkImageData *output)
+{
+  vtkDataArray* in =input->GetPointData()->GetScalars();  
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  vtkDataArray *mag = NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  double mrange[2];
+  if (this->Magnitude != NULL) {
+    mag = this->Magnitude->GetPointData()->GetScalars();
+    mag->GetRange(mrange);
+  }
+
+  int index = 0;
+  float v[3], mgn;
+  float rgb[3], nrgb[3];
+  float scale = this->Scaling;
+  
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  rgb[0] = rgb[1] = rgb[2] = 0;
+	  
+	  if ((mask != NULL)?(mask->GetComponent(index, 0) > 0):1)
+	    {
+	      v[0] = in->GetComponent(index, 0);
+	      v[1] = in->GetComponent(index, 1);
+	      v[2] = in->GetComponent(index, 2);
+
+	      vtkMath::Normalize(v);
+	      
+	      rgb[0] = fabs(v[0]);
+	      rgb[1] = fabs(v[1]);
+	      rgb[2] = fabs(v[2]);
+	      
+	      /* compute color */
+	      mgn = (mag != NULL) ? \
+		((mag->GetComponent(index, 0) - mrange[0]) / mrange[1]): 1.0;	 
+
+	      rgb[0] *= mgn;
+	      rgb[1] *= mgn;
+	      rgb[2] *= mgn;
+
+	      /* RGBs have to be in [0,255] */
+	      nrgb[0] = rgb[0]*255*scale;
+	      nrgb[1] = rgb[1]*255*scale;
+	      nrgb[2] = rgb[2]*255*scale;
+	      
+	      out->SetComponent(index, 0, nrgb[0] < 256 ? nrgb[0] : 255);
+	      out->SetComponent(index, 1, nrgb[1] < 256 ? nrgb[1] : 255);
+	      out->SetComponent(index, 2, nrgb[2] < 256 ? nrgb[2] : 255);
+	      
+	    } else {
+	      
+	      /* RGBs have to be in [0,255] */
+	      out->SetComponent(index, 0, MaskOutValue[0]);
+	      out->SetComponent(index, 1, MaskOutValue[1]);
+	      out->SetComponent(index, 2, MaskOutValue[2]);
+	      
+	    }
+	  
+	  ++index;
+	  
+	}
+     
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+  }
+  
+  this->UpdateProgress(1.0);
+}
+
+void vtkmpjImageTensorColor::RotationalSymmetryScheme(vtkImageData *input, vtkImageData *output)
+{
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+  
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  vtkDataArray *mag = NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  double mrange[2];
+  if (this->Magnitude != NULL) {
+    mag = this->Magnitude->GetPointData()->GetScalars();
+    mag->GetRange(mrange);
+  }
+  
+  int index = 0;
+  float v[3];
+  float rgb[3], nrgb[3], hsv[3];
+  float theta, phi;
+  float vlenxy, vlen;
+  float pi = vtkMath::Pi();
+  float ps = this->SaturationScale;
+  float scale = this->Scaling;
+
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  rgb[0] = rgb[1] = rgb[2] = 0;
+	  
+	  if ((mask != NULL)?(mask->GetComponent(index, 0) > 0):1)
+	    {
+	      nrgb[0] = v[0] = in->GetComponent(index, 0);
+	      nrgb[1] = v[1] = in->GetComponent(index, 1);
+	      nrgb[2] = v[2] = in->GetComponent(index, 2);
+	      
+	      /* normalize vector */
+	      vlenxy = vtkMath::Norm2D(v);
+
+	      /* compute hue */
+	      if (v[0] > 0) 
+		phi = asin(v[1] / vlenxy);
+	      else
+		phi = pi - asin(v[1] / vlenxy);	      
+	      hsv[0] = fmod((phi+2*pi+pi/2)*2,2*pi) / (2*pi);
+	      if (hsv[0] > 1.0) hsv[0] = 1.0;
+	      
+	      /* compute saturation */
+	      vlen = vtkMath::Norm(v);
+	      theta = asin(vlenxy / vlen);
+	      if (theta > 1) theta = 1.0;
+	      hsv[1] = sin(ps*theta) / sin(ps*pi/2);
+
+	      /* compute value */
+	      hsv[2] = (mag != NULL) ? \
+		((mag->GetComponent(index, 0) - mrange[0]) / mrange[1]): 1.0;	 
+	      
+	      vtkMath::HSVToRGB(hsv, rgb);
+	     	        
+	      /* RGBs have to be in [0,255] */
+	      nrgb[0] = rgb[0]*255+scale*nrgb[0];
+	      nrgb[1] = rgb[1]*255+scale*nrgb[1];
+	      nrgb[2] = rgb[2]*255+scale*nrgb[2];
+	      
+	      out->SetComponent(index, 0, nrgb[0] < 256 ? nrgb[0] : 255);
+	      out->SetComponent(index, 1, nrgb[1] < 256 ? nrgb[1] : 255);
+	      out->SetComponent(index, 2, nrgb[2] < 256 ? nrgb[2] : 255);
+	      
+	    } else {
+	      
+	      /* RGBs have to be in [0,255] */
+	      out->SetComponent(index, 0, MaskOutValue[0]);
+	      out->SetComponent(index, 1, MaskOutValue[1]);
+	      out->SetComponent(index, 2, MaskOutValue[2]);
+	      
+	    }
+	  
+	  ++index;
+	  
+	}
+     
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+  }
+  
+  this->UpdateProgress(1.0);
+}
+
+void vtkmpjImageTensorColor::NoSymmetryScheme(vtkImageData *input, vtkImageData *output) {
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+  
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  vtkDataArray *mag = NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+      
+  double mrange[2];
+  if (this->Magnitude != NULL) {
+    mag = this->Magnitude->GetPointData()->GetScalars();
+    mag->GetRange(mrange);
+  }
+  
+  int index = 0;
+  float v[3];
+  float rgb[3], nrgb[3], hsv[3];
+  float theta, phi;
+  float vlenxy, vlen;
+  float pi = vtkMath::Pi();
+  float ps = this->SaturationScale;
+  float scale = this->Scaling;
+  
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  rgb[0] = rgb[1] = rgb[2] = 0;
+	  
+	  if ((mask != NULL)?(mask->GetComponent(index, 0) > 0):1)
+	    {
+	      nrgb[0] = v[0] = in->GetComponent(index, 0);
+	      nrgb[1] = v[1] = in->GetComponent(index, 1);
+	      nrgb[2] = v[2] = in->GetComponent(index, 2);
+	      
+	      /* normalize vector */
+	      vlenxy = vtkMath::Norm2D(v);
+
+	      /* compute hue */
+	      if (v[0] > 0) 
+		phi = asin(v[1] / vlenxy);
+	      else
+		phi = pi - asin(v[1] / vlenxy);	      
+	      hsv[0] = fmod(phi+2*pi,2*pi) / (2*pi);
+	      if (hsv[0] > 1.0) hsv[0] = 1.0;
+	      
+	      /* compute saturation */
+	      vlen = vtkMath::Norm(v);
+	      theta = asin(vlenxy / vlen);
+	      if (theta > 1) theta = 1.0;
+	      hsv[1] = sin(ps*theta) / sin(ps*pi/2);
+
+	      /* compute value */
+	      hsv[2] = (mag != NULL) ? \
+		((mag->GetComponent(index, 0) - mrange[0]) / mrange[1]): 1.0;	 
+	      
+	      vtkMath::HSVToRGB(hsv, rgb);
+
+	      /* RGBs have to be in [0,255] */
+	      nrgb[0] = rgb[0]*255+scale*nrgb[0];
+	      nrgb[1] = rgb[1]*255+scale*nrgb[1];
+	      nrgb[2] = rgb[2]*255+scale*nrgb[2];
+	      
+	      out->SetComponent(index, 0, nrgb[0] < 256 ? nrgb[0] : 255);
+	      out->SetComponent(index, 1, nrgb[1] < 256 ? nrgb[1] : 255);
+	      out->SetComponent(index, 2, nrgb[2] < 256 ? nrgb[2] : 255);
+	      
+	    } else {
+	  
+	      /* RGBs have to be in [0,255] */
+	      out->SetComponent(index, 0, MaskOutValue[0]);
+	      out->SetComponent(index, 1, MaskOutValue[1]);
+	      out->SetComponent(index, 2, MaskOutValue[2]);
+	      
+	    }
+	  
+	  ++index;
+	  
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+  }
+  
+  this->UpdateProgress(1.0);
+}
+
+void vtkmpjImageTensorColor::MirrorSymmetryScheme(vtkImageData *input, vtkImageData *output)
+{
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+  
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  vtkDataArray *mag = NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  double mrange[2];
+  if (this->Magnitude != NULL) {
+    mag = this->Magnitude->GetPointData()->GetScalars();
+    mag->GetRange(mrange);
+  }
+
+  int index = 0;
+  float v[3];
+  float rgb[3], nrgb[3], hsv[3];
+  float theta, phi;
+  float vlenxy, vlen;
+  float pi = vtkMath::Pi();
+  float ps = this->SaturationScale;
+  float scale = this->Scaling;
+  
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  rgb[0] = rgb[1] = rgb[2] = 0;
+	  
+	  if ((mask != NULL)?(mask->GetComponent(index, 0) > 0):1)
+	    {
+	      nrgb[0] = v[0] = in->GetComponent(index, 0);
+	      nrgb[1] = v[1] = in->GetComponent(index, 1);
+	      nrgb[2] = v[2] = in->GetComponent(index, 2);
+	      
+	      /* normalize vector */
+	      vlenxy = vtkMath::Norm2D(v);
+
+	      /* compute hue */
+	      if (v[0] > 0) 
+		phi = asin(v[1] / vlenxy);
+	      else
+		phi = pi + asin(v[1] / vlenxy);	      
+	      hsv[0] = 2 * fmod(phi + pi, pi) / (2*pi);
+	      if (hsv[0] > 1.0) hsv[0] = 1.0;
+	      
+	      /* compute saturation */
+	      vlen = vtkMath::Norm(v);
+	      theta = asin(vlenxy / vlen);
+	      if (theta > 1) theta = 1.0;
+	      hsv[1] = sin(ps*theta) / sin(ps*pi/2);
+
+	      /* compute value */
+	      hsv[2] = (mag != NULL) ? \
+		((mag->GetComponent(index, 0) - mrange[0]) / mrange[1]): 1.0;	 
+	      
+	      vtkMath::HSVToRGB(hsv, rgb);
+
+	      /* RGBs have to be in [0,255] */
+	      nrgb[0] = rgb[0]*255+scale*nrgb[0];
+	      nrgb[1] = rgb[1]*255+scale*nrgb[1];
+	      nrgb[2] = rgb[2]*255+scale*nrgb[2];
+	      
+	      out->SetComponent(index, 0, nrgb[0] < 256 ? nrgb[0] : 255);
+	      out->SetComponent(index, 1, nrgb[1] < 256 ? nrgb[1] : 255);
+	      out->SetComponent(index, 2, nrgb[2] < 256 ? nrgb[2] : 255);
+
+	    } else {
+	  
+	      /* RGBs have to be in [0,255] */
+	      out->SetComponent(index, 0, MaskOutValue[0]);
+	      out->SetComponent(index, 1, MaskOutValue[1]);
+	      out->SetComponent(index, 2, MaskOutValue[2]);
+	      
+	    }
+
+	  ++index;
+	  
+	}
+     
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+  }
+  
+  this->UpdateProgress(1.0);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorColor::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  switch(this->ColorSchemeType) 
+    {
+    case VTK_MPJ_DEC_SYMMETRY:
+      this->RotationalSymmetryScheme(input, output);
+      break;
+    case VTK_MPJ_DEC_NOSYMMETRY:
+      this->NoSymmetryScheme(input, output);
+      break;
+    case VTK_MPJ_DEC_MIRROR:
+      this->MirrorSymmetryScheme(input, output);
+      break;
+    case VTK_MPJ_DEC_ABSOLUTE:
+    default:
+      this->AbsoluteValueScheme(input, output);
+  }
+
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorColor.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorColor.h
new file mode 100644
index 0000000..4c1531b
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorColor.h
@@ -0,0 +1,120 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjImageTensorColor.h 
+   
+*/
+
+#ifndef __vtkmpjImageTensorColor_h
+#define __vtkmpjImageTensorColor_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+// Color schemes
+#define VTK_MPJ_DEC_ABSOLUTE    0
+#define VTK_MPJ_DEC_SYMMETRY    1
+#define VTK_MPJ_DEC_NOSYMMETRY  2
+#define VTK_MPJ_DEC_MIRROR      3
+
+class vtkmpjImageTensorColor : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageTensorColor *New();
+  vtkTypeMacro(vtkmpjImageTensorColor,vtkpxSimpleImageToImageFilter);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents for invariants
+  // computation. If a mask is not provided, invariants are
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+  
+  // Description::
+  // Sets/Gets magnitude image. Magnitude values have to be in [0,1]
+  // Final color is modulated by this image.
+  vtkSetObjectMacro(Magnitude, vtkImageData);
+  vtkGetObjectMacro(Magnitude, vtkImageData);
+  
+  // Description:
+  // Set/Get the color scheme
+  vtkSetMacro(ColorSchemeType,int);
+  vtkGetMacro(ColorSchemeType,int);
+  
+  void SetColorSchemeTypeToSymmetry() {this->SetColorSchemeType(VTK_MPJ_DEC_SYMMETRY);};
+  void SetColorSchemeTypeToNoSymmetry() {this->SetColorSchemeType(VTK_MPJ_DEC_NOSYMMETRY);};
+  void SetColorSchemeTypeToMirror() {this->SetColorSchemeType(VTK_MPJ_DEC_MIRROR);};
+  void SetColorSchemeTypeToAbsolute() {this->SetColorSchemeType(VTK_MPJ_DEC_ABSOLUTE);};
+  void SetColorSchemeTypeToDefault() {this->SetColorSchemeType(VTK_MPJ_DEC_ABSOLUTE);};
+  
+  // Description:
+  // Set/Get the RGB value for results falling outside the mask
+  vtkSetVectorMacro(MaskOutValue,float,3);
+  vtkGetVectorMacro(MaskOutValue,float,3);
+  
+  // Description:
+  // Set/Get saturation scale
+  vtkSetMacro(SaturationScale,float);
+  vtkGetMacro(SaturationScale,float);
+  
+  // Description:
+  // Set/Get the scaling
+  vtkSetMacro(Scaling,float);
+  vtkGetMacro(Scaling,float);
+  
+ protected:
+  int ColorSchemeType;
+  float SaturationScale;
+  float Scaling;
+  float MaskOutValue[3]; 
+  vtkImageData *Mask;
+  vtkImageData *Magnitude;
+  
+  vtkmpjImageTensorColor();
+  virtual ~vtkmpjImageTensorColor();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  void AbsoluteValueScheme(vtkImageData *input, vtkImageData *output);
+  void RotationalSymmetryScheme(vtkImageData *input, vtkImageData *output);
+  void NoSymmetryScheme(vtkImageData *input, vtkImageData *output);
+  void MirrorSymmetryScheme(vtkImageData *input, vtkImageData *output);
+
+  vtkmpjImageTensorColor(const vtkmpjImageTensorColor&); // Not implemented
+  void operator=(const vtkmpjImageTensorColor&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorEigenAnalysis.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorEigenAnalysis.cpp
new file mode 100644
index 0000000..d386bf1
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorEigenAnalysis.cpp
@@ -0,0 +1,523 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageTensorEigenAnalysis.h"
+#include "vtkMath.h"
+#include "math.h"
+
+#define VTK_MPJ_SIGN(x) (( (x) < 0 )?( -1 ):( 1 ))
+
+//------------------------------------------------------------------------------
+vtkmpjImageTensorEigenAnalysis* vtkmpjImageTensorEigenAnalysis::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageTensorEigenAnalysis");
+  if(ret)
+    {
+      return (vtkmpjImageTensorEigenAnalysis*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageTensorEigenAnalysis;
+}
+
+// Construct object with no children.
+vtkmpjImageTensorEigenAnalysis::vtkmpjImageTensorEigenAnalysis()
+{
+  this->OutputType = VTK_MPJ_TENSOREIG_VALUES;
+  this->MaskNegative = 0; 
+  this->Mask = NULL;
+  this->NegativeMask = NULL;
+  this->MaskNegativeInValue = 1;
+  this->MaskNegativeOutValue = 0;
+  this->Ordering = VTK_MPJ_TENSOR_XXXYXZYYYZZZ;
+  this->OutputAbsoluteEigenvalues = 1;
+  this->SortByMagnitude = 0;
+  this->FixZeroEigenvalues = 0;
+  this->NormalizeEigenvectors = 0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageTensorEigenAnalysis::~vtkmpjImageTensorEigenAnalysis()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+  if (this->NegativeMask != NULL)
+    this->NegativeMask->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorEigenAnalysis::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+  
+  if ((nc != 6)&&(nc != 9)) {
+    vtkErrorMacro(<<"A total of 6 (symmetric) or 9 tensor elements are required in the dataset!");
+    return;
+  }
+  
+  switch(this->OutputType) {
+  case VTK_MPJ_TENSOREIG_VALUES:
+    output->SetNumberOfScalarComponents(3);
+    break;
+  case VTK_MPJ_TENSOREIG_VECTORS:
+    output->SetNumberOfScalarComponents(9);
+    break;
+  case VTK_MPJ_TENSOREIG_BOTH:
+    output->SetNumberOfScalarComponents(12);
+    break;
+  };
+  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorEigenAnalysis::SortEigenvectorsByMagnitude(float *w, float **v)
+{
+  int i, j, k;
+  float tmp, tmp2;
+  
+  // sort eigenfunctions
+  for (j=0; j<3; j++) 
+    {
+      k = j;
+      tmp = w[k];
+      tmp2 = fabs(tmp);
+      for (i=j; i<3; i++)
+	{
+	  if (fabs(w[i]) >= tmp2) 
+	    {
+	      k = i;
+	      tmp = w[k];
+	      tmp2 = fabs(tmp);
+	    }
+	}
+      if (k != j) 
+	{
+	  w[k] = w[j];
+	  w[j] = tmp;
+	  for (i=0; i<3; i++) 
+	    {
+	      tmp = v[i][j];
+	      v[i][j] = v[i][k];
+	      v[i][k] = tmp;
+	    }
+	}
+    }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorEigenAnalysis::ExecuteWithReducedTensor(vtkImageData *input, vtkImageData *output)
+{
+  float **t = new float *[3]; /* allocate space for tensor matrix */
+  t[0] = new float[3];
+  t[1] = new float[3];
+  t[2] = new float[3];
+
+  float **v = new float *[3]; /* allocate space for eigenvector matrix */
+  v[0] = new float[3];
+  v[1] = new float[3];
+  v[2] = new float[3];
+
+  float *w = new float[3];    /* allocate space for eigenvalues */
+
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  // Get number of tensor elements
+  int nc = input->GetNumberOfScalarComponents();
+  int ncout = output->GetNumberOfScalarComponents();
+
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+  
+  int dim[3];  input->GetDimensions(dim);
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  vtkDataArray* mask=NULL;
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  vtkDataArray* negmask=NULL;
+
+  if (this->MaskNegative) {
+    if (this->NegativeMask == NULL)
+      this->NegativeMask=vtkImageData::New();
+    this->NegativeMask->SetSpacing(input->GetSpacing());
+    this->NegativeMask->SetOrigin(input->GetOrigin());
+    this->NegativeMask->SetScalarTypeToUnsignedChar();//(input->GetScalarType());
+    this->NegativeMask->SetNumberOfScalarComponents(1);
+    this->NegativeMask->SetDimensions(dim[0],dim[1],dim[2]);
+    this->NegativeMask->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+    this->NegativeMask->AllocateScalars();
+    negmask=this->NegativeMask->GetPointData()->GetScalars();
+  }
+
+  int inmask;
+  int index=0;
+
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  inmask = (mask != NULL)?(mask->GetComponent(index, 0) > 0) : 1;
+	  
+	  if (inmask) {
+	    
+	    // set tensor matrix 
+	    if (this->Ordering == VTK_MPJ_TENSOR_XXXYXZYYYZZZ) {
+
+	      t[0][0] = in->GetComponent(index, 0);           /* Dxx */
+	      t[1][0] = t[0][1] = in->GetComponent(index, 1); /* Dxy */
+	      t[2][0] = t[0][2] = in->GetComponent(index, 2); /* Dxz */	      
+	      t[1][1] = in->GetComponent(index, 3);           /* Dyy */
+	      t[2][1] = t[1][2] = in->GetComponent(index, 4); /* Dyz */	      
+	      t[2][2] = in->GetComponent(index, 5);           /* Dzz */
+
+	    } else {
+	      
+	      t[0][0] = in->GetComponent(index, 0);           /* Dxx */
+	      t[1][0] = t[0][1] = in->GetComponent(index, 3); /* Dxy */
+	      t[2][0] = t[0][2] = in->GetComponent(index, 5); /* Dxz */	      
+	      t[1][1] = in->GetComponent(index, 1);           /* Dyy */
+	      t[2][1] = t[1][2] = in->GetComponent(index, 4); /* Dyz */	      
+	      t[2][2] = in->GetComponent(index, 2);           /* Dzz */
+
+	    }
+	    
+	    // determine its eigenvectors and eigenvalues	      
+	    (void) vtkMath::Jacobi(t,w,v);
+	    	   
+	    int ccount = -1;
+	    
+	    // create mask for negative eigenvalues
+	    if (this->MaskNegative) { 
+	      if (w[0]<0 || w[1]<0 || w[2]<0)
+		negmask->SetComponent(index, 0, MaskNegativeInValue);
+	      else negmask->SetComponent(index, 0, MaskNegativeOutValue);
+	    }
+
+	    // this is for use in hessian matrices only
+	    if (this->FixZeroEigenvalues) {
+	      if (fabs(w[0]) < 1E-4) w[0] = VTK_MPJ_SIGN(w[0]);
+	      if (fabs(w[1]) < 1E-4) w[1] = VTK_MPJ_SIGN(w[1]);
+	      if (fabs(w[2]) < 1E-4) w[2] = VTK_MPJ_SIGN(w[2]);
+	    }
+	      
+	    // re-sort eigenvectors instead by their absolute value	    
+	    if (this->SortByMagnitude)
+	      this->SortEigenvectorsByMagnitude(w,v);	    
+	    
+	    if (this->OutputAbsoluteEigenvalues) {
+	      for (int i=0; i<3; i++) {
+		if (w[i] < 0) {
+		  v[0][i] = -v[0][i];
+		  v[1][i] = -v[1][i];
+		  v[2][i] = -v[2][i];
+		  w[i] = -w[i];
+		}
+	      }
+	    }
+	    
+	    // save eigenvalues
+	    if (this->OutputType == VTK_MPJ_TENSOREIG_VALUES || 
+		this->OutputType == VTK_MPJ_TENSOREIG_BOTH) {
+	      
+	      out->SetComponent(index, ++ccount, w[0]); /* 0 */
+	      out->SetComponent(index, ++ccount, w[1]); /* 1 */
+	      out->SetComponent(index, ++ccount, w[2]); /* 2 */
+	      
+	    }
+	    
+	    // save eigenvectors
+	    if (this->OutputType == VTK_MPJ_TENSOREIG_VECTORS || 
+		this->OutputType == VTK_MPJ_TENSOREIG_BOTH) {
+	      
+	      // normalize eigenvector
+	      w[0] = this->NormalizeEigenvectors ? 1.0 : w[0];
+	      w[1] = this->NormalizeEigenvectors ? 1.0 : w[1];
+	      w[2] = this->NormalizeEigenvectors ? 1.0 : w[2];
+
+	      // save 1st eigenvector
+	      out->SetComponent(index, ++ccount, v[0][0]*w[0]); /* 0 */
+	      out->SetComponent(index, ++ccount, v[1][0]*w[0]); /* 0 */
+	      out->SetComponent(index, ++ccount, v[2][0]*w[0]); /* 0 */
+	      
+	      // save 2nd eigenvector
+	      out->SetComponent(index, ++ccount, v[0][1]*w[1]); /* 1 */
+	      out->SetComponent(index, ++ccount, v[1][1]*w[1]); /* 1 */
+	      out->SetComponent(index, ++ccount, v[2][1]*w[1]); /* 1 */
+	      
+	      // save 3rd eigenvector
+	      out->SetComponent(index, ++ccount, v[0][2]*w[2]); /* 2 */
+	      out->SetComponent(index, ++ccount, v[1][2]*w[2]); /* 2 */
+	      out->SetComponent(index, ++ccount, v[2][2]*w[2]); /* 2 */	  
+	      
+	    }
+	    
+	  } else {
+	    
+	    // zero out points not in the mask
+	    if (this->MaskNegative) { 
+	      negmask->SetComponent(index, 0, MaskNegativeOutValue);
+	    } 
+	    
+	    for(int l=0; l<ncout; l++) {
+	      out->SetComponent(index, l, 0);
+	    }
+	    
+	  }
+	  
+	  ++index;	  	  
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+  
+  // free tensor memory
+  delete[] t[0];
+  delete[] t[1];
+  delete[] t[2];
+  delete[] t;
+  
+  // free eigenvectors memory
+  delete[] v[0];
+  delete[] v[1];
+  delete[] v[2];
+  delete[] v;
+
+  // free eigenvalue memory
+  delete[] w;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorEigenAnalysis::ExecuteWithFullTensor(vtkImageData *input, vtkImageData *output)
+{
+  float **t = new float *[3]; /* allocate space for tensor matrix */
+  t[0] = new float[3];
+  t[1] = new float[3];
+  t[2] = new float[3];
+
+  float **v = new float *[3]; /* allocate space for eigenvector matrix */
+  v[0] = new float[3];
+  v[1] = new float[3];
+  v[2] = new float[3];
+
+  float *w = new float[3];    /* allocate space for eigenvalues */
+
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+
+  // Get number of tensor elements
+  int nc = input->GetNumberOfScalarComponents();
+  int ncout = output->GetNumberOfScalarComponents();
+
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+  
+  int dim[3];  input->GetDimensions(dim);
+
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  vtkDataArray* mask=NULL;
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  vtkDataArray* negmask=NULL;
+
+  if (this->MaskNegative) {
+    if (this->NegativeMask == NULL)
+      this->NegativeMask=vtkImageData::New();
+    this->NegativeMask->SetSpacing(input->GetSpacing());
+    this->NegativeMask->SetOrigin(input->GetOrigin());
+    this->NegativeMask->SetScalarTypeToUnsignedChar();//(input->GetScalarType());
+    this->NegativeMask->SetNumberOfScalarComponents(1);
+    this->NegativeMask->SetDimensions(dim[0],dim[1],dim[2]);
+    this->NegativeMask->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+    this->NegativeMask->AllocateScalars();
+    negmask=this->NegativeMask->GetPointData()->GetScalars();
+  }
+
+  int inmask;
+  int index=0;
+
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  inmask = (mask != NULL)?(mask->GetComponent(index, 0) > 0) : 1;
+	  
+	  if (inmask) {
+
+	    t[0][0] = in->GetComponent(index, 0); /* Dxx */
+	    t[1][0] = in->GetComponent(index, 1); /* Dxy */
+	    t[2][0] = in->GetComponent(index, 2); /* Dxz */
+	    t[0][1] = in->GetComponent(index, 3); /* Dyx */
+	    t[1][1] = in->GetComponent(index, 4); /* Dyy */
+	    t[2][1] = in->GetComponent(index, 5); /* Dyz */	    
+	    t[0][2] = in->GetComponent(index, 6); /* Dzx */
+	    t[1][2] = in->GetComponent(index, 7); /* Dzy */
+	    t[2][2] = in->GetComponent(index, 8); /* Dzz */
+	    
+	    // determine its eigenvectors and eigenvalues	      
+	    (void) vtkMath::Jacobi(t,w,v);
+	    
+	    int ccount = -1;
+	    
+	    // create mask for negative eigenvalues
+	    if (this->MaskNegative) { 
+	      if (w[0]<0 || w[1]<0 || w[2]<0)
+		negmask->SetComponent(index, 0, MaskNegativeInValue);
+	      else negmask->SetComponent(index, 0, MaskNegativeOutValue);
+	    }
+
+	    // re-sort eigenvectors instead by their absolute value	    
+	    if (this->SortByMagnitude)
+	      this->SortEigenvectorsByMagnitude(w,v);	    
+	    
+	    if (this->OutputAbsoluteEigenvalues) {
+	      for (int i=0; i<3; i++) {
+		if (w[i] < 0) {
+		  v[0][i] = -v[0][i];
+		  v[1][i] = -v[1][i];
+		  v[2][i] = -v[2][i];
+		  w[i] = -w[i];
+		}
+	      }
+	    }
+	    
+	    // save eigenvalues
+	    if (this->OutputType == VTK_MPJ_TENSOREIG_VALUES || 
+		this->OutputType == VTK_MPJ_TENSOREIG_BOTH) {
+	      
+	      out->SetComponent(index, ++ccount, w[0]); /* 0 */
+	      out->SetComponent(index, ++ccount, w[1]); /* 1 */
+	      out->SetComponent(index, ++ccount, w[2]); /* 2 */
+	      
+	    }
+	    
+	    // save eigenvectors
+	    if (this->OutputType == VTK_MPJ_TENSOREIG_VECTORS || 
+		this->OutputType == VTK_MPJ_TENSOREIG_BOTH) {
+	      
+	      // save 1st eigenvector
+	      out->SetComponent(index, ++ccount, v[0][0]*w[0]); /* 0 */
+	      out->SetComponent(index, ++ccount, v[1][0]*w[0]); /* 0 */
+	      out->SetComponent(index, ++ccount, v[2][0]*w[0]); /* 0 */
+	      
+	      // save 2nd eigenvector
+	      out->SetComponent(index, ++ccount, v[0][1]*w[1]); /* 1 */
+	      out->SetComponent(index, ++ccount, v[1][1]*w[1]); /* 1 */
+	      out->SetComponent(index, ++ccount, v[2][1]*w[1]); /* 1 */
+	      
+	      // save 3rd eigenvector
+	      out->SetComponent(index, ++ccount, v[0][2]*w[2]); /* 2 */
+	      out->SetComponent(index, ++ccount, v[1][2]*w[2]); /* 2 */
+	      out->SetComponent(index, ++ccount, v[2][2]*w[2]); /* 2 */	  
+	      
+	    }
+	    
+	  } else {
+	    
+	    // zero out points not in the mask
+	    if (this->MaskNegative) { 
+	      negmask->SetComponent(index, 0, MaskNegativeOutValue);
+	    } 
+	    
+	    for(int l=0; l<ncout; l++) {
+	      out->SetComponent(index, l, 0);
+	    }
+	    
+	  }
+	  
+	  ++index;	  	  
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+  
+  // free tensor memory
+  delete[] t[0];
+  delete[] t[1];
+  delete[] t[2];
+  delete[] t;
+  
+  // free eigenvectors memory
+  delete[] v[0];
+  delete[] v[1];
+  delete[] v[2];
+  delete[] v;
+
+  // free eigenvalue memory
+  delete[] w;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorEigenAnalysis::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  
+  // Get number of tensor elements
+  int nc = input->GetNumberOfScalarComponents();
+  
+  if (nc > 6) 
+    this->ExecuteWithFullTensor(input, output);
+  else
+    this->ExecuteWithReducedTensor(input, output);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorEigenAnalysis.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorEigenAnalysis.h
new file mode 100644
index 0000000..05ce2db
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorEigenAnalysis.h
@@ -0,0 +1,160 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjImageTensorEigenAnalysis.h 
+   
+      Marcel Jackowski, 2002
+
+      This class computes the eigenvalues and eigenvectors of a
+      symmetric tensor image.
+      
+      It expects as the input a vtkImageData structure
+      containing 6 frames containing the 6 tensor elements.
+      See component ordering information below.
+
+      It will output 12 frames; the first three frames containing the
+      eigenvalues for each one of the 3 columns of the eigenvector matrix 
+      and the remaining 9 frames containing the eigenvector elements 
+      stored in row-wise fashion.      
+*/
+
+#ifndef __vtkmpjImageTensorEigenAnalysis_h
+#define __vtkmpjImageTensorEigenAnalysis_h
+
+// Output types
+#define VTK_MPJ_TENSOREIG_VALUES  0    
+#define VTK_MPJ_TENSOREIG_VECTORS 1
+#define VTK_MPJ_TENSOREIG_BOTH    2
+
+// Ordering
+#define VTK_MPJ_TENSOR_XXXYXZYYYZZZ 0 
+#define VTK_MPJ_TENSOR_XXYYZZXYYZXZ 1
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjImageTensorEigenAnalysis : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageTensorEigenAnalysis *New();
+  vtkTypeMacro(vtkmpjImageTensorEigenAnalysis,vtkpxSimpleImageToImageFilter);
+
+  // Description:
+  // Set/Get the component ordering information
+  vtkSetMacro(Ordering,int);
+  vtkGetMacro(Ordering,int);
+  
+  // Description:
+  // Set/Get the Output type: eigenvalues only (default), eigenvectors only or both 
+  vtkSetMacro(OutputType,int);
+  vtkGetMacro(OutputType,int);
+
+  // Description: Create or not a mask depicting places where eigenvalues are negative
+  vtkSetMacro(MaskNegative,int);
+  vtkGetMacro(MaskNegative,int);
+  vtkBooleanMacro(MaskNegative,int);
+
+  // Description: Set/Get whether eigenvalues should always be positive. Default is true
+  vtkSetMacro(OutputAbsoluteEigenvalues,int);
+  vtkGetMacro(OutputAbsoluteEigenvalues,int);
+  vtkBooleanMacro(OutputAbsoluteEigenvalues,int);
+
+  // Description: Set/Get reordering of eigenvalues
+  vtkSetMacro(SortByMagnitude,int);
+  vtkGetMacro(SortByMagnitude,int);
+  vtkBooleanMacro(SortByMagnitude,int);
+
+  // Description: Set/Get reordering of eigenvalues
+  vtkSetMacro(FixZeroEigenvalues,int);
+  vtkGetMacro(FixZeroEigenvalues,int);
+  vtkBooleanMacro(FixZeroEigenvalues,int);
+
+  // Description: Set/Get eigenvector normalization
+  vtkSetMacro(NormalizeEigenvectors,int);
+  vtkGetMacro(NormalizeEigenvectors,int);
+  vtkBooleanMacro(NormalizeEigenvectors,int);
+
+  // Description:
+  // Set/Get the outside value for the mask
+  vtkSetMacro(MaskNegativeOutValue,float);
+  vtkGetMacro(MaskNegativeOutValue,float);
+  
+  // Description:
+  // Set/Get the inside value for the mask
+  vtkSetMacro(MaskNegativeInValue,float);
+  vtkGetMacro(MaskNegativeInValue,float);
+
+  // Description:
+  // Sets/Gets mask where eigenvalues are to be computed
+  vtkGetObjectMacro(Mask, vtkImageData);
+  vtkSetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Gets mask where eigenvalues are negative
+  vtkGetObjectMacro(NegativeMask, vtkImageData);
+  vtkSetObjectMacro(NegativeMask, vtkImageData);
+  
+  void SetOutputTypeToEigenvalues() {this->SetOutputType(VTK_MPJ_TENSOREIG_VALUES);};
+  void SetOutputTypeToEigenvectors() {this->SetOutputType(VTK_MPJ_TENSOREIG_VECTORS);};
+  void SetOutputTypeToBoth() {this->SetOutputType(VTK_MPJ_TENSOREIG_BOTH);};
+  
+ protected:
+  int Ordering;
+  int OutputType;
+  int MaskNegative;
+  int SortByMagnitude;
+  int NormalizeEigenvectors;
+  int OutputAbsoluteEigenvalues;
+  int FixZeroEigenvalues;
+  vtkImageData *Mask;
+  vtkImageData *NegativeMask;
+  float MaskNegativeInValue;
+  float MaskNegativeOutValue;
+
+  vtkmpjImageTensorEigenAnalysis();
+  virtual ~vtkmpjImageTensorEigenAnalysis();
+  
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+  
+ private:
+  vtkmpjImageTensorEigenAnalysis(const vtkmpjImageTensorEigenAnalysis&); // Not implemented
+  void operator=(const vtkmpjImageTensorEigenAnalysis&); // Not Implemented
+  
+  void SortEigenvectorsByMagnitude(float *w, float **v);
+  void ExecuteWithReducedTensor(vtkImageData *input, vtkImageData *output);
+  void ExecuteWithFullTensor(vtkImageData *input, vtkImageData *output);
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorInvariants.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorInvariants.cpp
new file mode 100644
index 0000000..f9c49cc
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorInvariants.cpp
@@ -0,0 +1,188 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageTensorInvariants.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageTensorInvariants* vtkmpjImageTensorInvariants::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageTensorInvariants");
+  if(ret)
+    {
+      return (vtkmpjImageTensorInvariants*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageTensorInvariants;
+}
+
+// Construct object with no children.
+vtkmpjImageTensorInvariants::vtkmpjImageTensorInvariants()
+{
+  this->Mask = NULL;
+  this->Operation = VTK_MPJ_TENSORINV_ALL;
+  this->MaskOutValue = 0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageTensorInvariants::~vtkmpjImageTensorInvariants()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorInvariants::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+  
+  if (nc < 3) {
+    vtkErrorMacro(<< "Three eigenvalues per voxel are required as input!");
+    return;
+  }
+  
+  if (this->Operation == VTK_MPJ_TENSORINV_ALL) 
+    output->SetNumberOfScalarComponents(5);
+  else output->SetNumberOfScalarComponents(1);
+  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorInvariants::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+ 
+  int dim[3];  input->GetDimensions(dim);
+  int op = this->GetOperation();
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  int index=0;
+  
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	
+	  float l1 = in->GetComponent(index, 0);
+	  float l2 = in->GetComponent(index, 1);
+	  float l3 = in->GetComponent(index, 2);
+	  float ml = (l1 + l2 + l3) / 3.0;
+	  float l1m = l1 - ml;
+	  float l2m = l2 - ml;
+	  float l3m = l3 - ml;
+	  float FA, RA, VR, MD, SK;
+	  int output=1;
+	
+	  if (l1 < 0 || l2 < 0 || l3 < 0) {
+	    printf("l1=%f, l2=%f, l3=%f @ %d,%d,%d\n",l1,l2,l3,i,j,k);
+	  }
+
+	  output = (mask != NULL)?(mask->GetComponent(index, 0) > 0):1;
+	  
+	  if (output)
+	    {
+	      FA = 
+		sqrt(3*(l1m*l1m + l2m*l2m + l3m*l3m)) / 
+		sqrt(2*(l1*l1 + l2*l2 + l3*l3));	    
+	      RA = sqrt(l1m*l1m + l2m*l2m + l3m*l3m) / (sqrt(double(3.0))*ml);
+	      VR = 1.0 - ((l1*l2*l3) / (ml*ml*ml));
+	      SK = (l1m*l1m*l1m + l2m*l2m*l2m + l3m*l3m*l3m) / (l1+l2+l3);
+	      MD = ml;
+	    } else {
+	      FA = RA = VR = MD = SK = this->MaskOutValue;	      
+	    }
+	  
+	  // Invariant information
+	  switch(op) 
+	    {
+	    case VTK_MPJ_TENSORINV_FA:
+	      out->SetComponent(index, 0, FA);	   
+	      break;
+	    case VTK_MPJ_TENSORINV_RA:
+	      out->SetComponent(index, 0, RA);
+	      break;
+	    case VTK_MPJ_TENSORINV_VR:
+	      out->SetComponent(index, 0, VR);
+	      break;
+	    case VTK_MPJ_TENSORINV_MD:
+	      out->SetComponent(index, 0, MD);
+	      break;
+	    case VTK_MPJ_TENSORINV_SK:
+	      out->SetComponent(index, 0, SK);
+	    default:
+	      out->SetComponent(index, 0, FA);     /* fractional anisotropy*/
+	      out->SetComponent(index, 1, RA);     /* relative anisotropy */
+	      out->SetComponent(index, 2, VR);     /* 1 - volume ratio */
+	      out->SetComponent(index, 3, MD);     /* mean diffusity */
+	      out->SetComponent(index, 4, SK);
+	    };
+	  
+	  ++index;	  
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorInvariants.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorInvariants.h
new file mode 100644
index 0000000..4dce4b0
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorInvariants.h
@@ -0,0 +1,100 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjImageTensorInvariants.h 
+   
+      Marcel Jackowski, November 2002
+
+*/
+
+#ifndef __vtkmpjImageTensorInvariants_h
+#define __vtkmpjImageTensorInvariants_h
+
+// Invariant options
+#define VTK_MPJ_TENSORINV_ALL   0    
+#define VTK_MPJ_TENSORINV_FA    1
+#define VTK_MPJ_TENSORINV_RA    2
+#define VTK_MPJ_TENSORINV_VR    3
+#define VTK_MPJ_TENSORINV_MD    4
+#define VTK_MPJ_TENSORINV_SK    5
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjImageTensorInvariants : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageTensorInvariants *New();
+  vtkTypeMacro(vtkmpjImageTensorInvariants,vtkpxSimpleImageToImageFilter);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents for invariants
+  // computation. If a mask is not provided, invariants are
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Set/Get the Operation to perform.
+  vtkSetMacro(Operation,int);
+  vtkGetMacro(Operation,int);
+
+  void SetOperationToFractionalAnisotropy() {this->SetOperation(VTK_MPJ_TENSORINV_FA);};
+  void SetOperationToRelativeAnisotropy() {this->SetOperation(VTK_MPJ_TENSORINV_RA);};
+  void SetOperationToVolumeRatio() {this->SetOperation(VTK_MPJ_TENSORINV_VR);};
+  void SetOperationToMeanDiffusivity() {this->SetOperation(VTK_MPJ_TENSORINV_MD);};
+  void SetOperationToDefault() {this->SetOperation(VTK_MPJ_TENSORINV_ALL);};
+
+  // Description:
+  // Set/Get the value for results falling outside the mask
+  vtkSetMacro(MaskOutValue,float);
+  vtkGetMacro(MaskOutValue,float);
+  
+protected:
+  int Operation;  /* Invariant to be computed */
+  float MaskOutValue; 
+  vtkImageData *Mask;
+  
+  vtkmpjImageTensorInvariants();
+  virtual ~vtkmpjImageTensorInvariants();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  vtkmpjImageTensorInvariants(const vtkmpjImageTensorInvariants&); // Not implemented
+  void operator=(const vtkmpjImageTensorInvariants&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorMultiply.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorMultiply.cpp
new file mode 100644
index 0000000..f5f3cb1
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorMultiply.cpp
@@ -0,0 +1,261 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageTensorMultiply.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageTensorMultiply* vtkmpjImageTensorMultiply::New() 
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageTensorMultiply");
+  
+  if(ret) {
+    return (vtkmpjImageTensorMultiply*)ret;
+  }
+  
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageTensorMultiply;
+}
+
+// Construct object with no children.
+vtkmpjImageTensorMultiply::vtkmpjImageTensorMultiply()
+{  
+  this->NoiseLevel = 5.0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageTensorMultiply::~vtkmpjImageTensorMultiply()
+{
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorMultiply::SetInput1(vtkImageData *input)
+{
+  this->vtkProcessObject::SetNthInput(0, input);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorMultiply::SetInput2(vtkImageData *input)
+{
+  this->vtkProcessObject::SetNthInput(1, input);
+}
+
+//----------------------------------------------------------------------------
+vtkImageData *vtkmpjImageTensorMultiply::GetInput(int index)
+{
+  if (this->NumberOfInputs <= index)
+    {
+      return NULL;
+    }
+   
+  return (vtkImageData *)(this->Inputs[index]);
+}
+
+// ----------------------------------------------------------------------------
+float vtkmpjImageTensorMultiply::GetGaussianDeviate()
+{
+  static int iset=0;
+  static float gset;
+  float fac,rsq,v1,v2;
+
+  if  (iset == 0) 
+    {
+      do 
+	{
+	  v1=2.0*vtkMath::Random()-1.0;
+	  v2=2.0*vtkMath::Random()-1.0;
+	  rsq=v1*v1+v2*v2;
+	} 
+      while (rsq >= 1.0 || rsq == 0.0);
+      
+      fac=sqrt(-2.0*log(rsq)/rsq);
+      gset=v1*fac;
+      iset=1;
+      return v2*fac;
+    } 
+  else
+    {
+      iset=0;
+      return gset;
+    }
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjImageTensorMultiply::PrintMatrix3x3(char *title, float M[3][3])
+{
+  printf("%s",title);
+  printf("%f %f %f\n",M[0][0],M[0][1],M[0][2]);
+  printf("%f %f %f\n",M[1][0],M[1][1],M[1][2]);
+  printf("%f %f %f\n",M[2][0],M[2][1],M[2][2]);
+  printf("===============================\n");
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorMultiply::ExecuteInformation()
+{
+  // start with defaults
+  vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  vtkImageData *output = this->GetOutput();
+  vtkImageData *input = this->GetInput(0);
+  int dim[3];  input->GetDimensions(dim);
+  
+  if (input->GetNumberOfScalarComponents() == 9) {
+    output->SetNumberOfScalarComponents(9);
+  } else {
+    output->SetNumberOfScalarComponents(6);
+  }
+    
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorMultiply::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  vtkImageData *input1 = this->GetInput(0);
+  vtkImageData *input2 = this->GetInput(1);
+  int numcomp = input1->GetNumberOfScalarComponents();
+  int dim[3];  input1->GetDimensions(dim);
+
+  vtkDataArray* in1=input1->GetPointData()->GetScalars(); 
+  vtkDataArray* in2=input2->GetPointData()->GetScalars(); 
+  vtkDataArray* out=output->GetPointData()->GetScalars();  
+
+  float T1[3][3], T2[3][3];                            /* tensor matrix */
+  float R[3][3];
+  float noise[6];
+
+  float Dxx;
+  float Dyy;
+  float Dzz;
+  float Dxy;
+  float Dxz;
+  float Dyz;
+
+  int index=0;
+
+  printf("number of components=%d\n", numcomp);
+
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{		
+	  if (numcomp == 9) {
+
+	    T1[0][0] = Dxx = in1->GetComponent(index, 0);
+	    T1[1][0] = Dxy = in1->GetComponent(index, 1);
+	    T1[2][0] = Dxz = in1->GetComponent(index, 2);
+	    T1[0][1] = Dxy = in1->GetComponent(index, 3);
+	    T1[1][1] = Dyy = in1->GetComponent(index, 4);
+	    T1[2][1] = Dyz = in1->GetComponent(index, 5);
+	    T1[0][2] = Dxz = in1->GetComponent(index, 6);
+	    T1[1][2] = Dyz = in1->GetComponent(index, 7);
+	    T1[2][2] = Dzz = in1->GetComponent(index, 8);
+
+	    
+	    T2[0][0] = Dxx = in2->GetComponent(index, 0);
+	    T2[1][0] = Dxy = in2->GetComponent(index, 1);
+	    T2[2][0] = Dxz = in2->GetComponent(index, 2);
+	    T2[0][1] = Dxy = in2->GetComponent(index, 3);
+	    T2[1][1] = Dyy = in2->GetComponent(index, 4);
+	    T2[2][1] = Dyz = in2->GetComponent(index, 5);
+	    T2[0][2] = Dxz = in2->GetComponent(index, 6);
+	    T2[1][2] = Dyz = in2->GetComponent(index, 7);
+	    T2[2][2] = Dzz = in2->GetComponent(index, 8);
+
+	  } else {
+	  
+	    T1[0][0] = Dxx = in1->GetComponent(index, 0);
+	    T1[1][0] = T1[0][1] = Dxy = in1->GetComponent(index, 1);
+	    T1[2][0] = T1[0][2] = Dxz = in1->GetComponent(index, 2);
+	    T1[1][1] = Dyy = in1->GetComponent(index, 3);
+	    T1[2][1] = T1[1][2] = Dyz = in1->GetComponent(index, 4);
+	    T1[2][2] = Dzz = in1->GetComponent(index, 5);
+	    
+	    T2[0][0] = Dxx = in2->GetComponent(index, 0);
+	    T2[1][0] = T2[0][1] = Dxy = in2->GetComponent(index, 1);
+	    T2[2][0] = T2[0][2] = Dxz = in2->GetComponent(index, 2);
+	    T2[1][1] = Dyy = in2->GetComponent(index, 3);
+	    T2[2][1] = T2[1][2] = Dyz = in1->GetComponent(index, 4);
+	    T2[2][2] = Dzz = in2->GetComponent(index, 5);
+	    
+	  }
+	  
+	  (void) vtkMath::Multiply3x3(T1,T2,R);
+
+	   for(int l=0; l<6; l++)
+	     noise[l] = this->NoiseLevel * this->GetGaussianDeviate();
+
+	   if (R[0][0]==1.0 && R[1][1]==1.0 && R[2][2]==1.0) {
+	     R[0][0]=0; R[1][1]=0; R[2][2]=0;
+	   }
+
+	  Dxx = R[0][0] + noise[0];
+	  Dyy = R[1][1] + noise[3];
+	  Dzz = R[2][2] + noise[5];
+	  Dxy = R[0][1] + noise[1];
+	  Dxz = R[0][2] + noise[2];
+	  Dyz = R[1][2] + noise[4];
+	  
+	  if (numcomp == 9) {
+	    out->SetComponent(index, 0, Dxx);
+	    out->SetComponent(index, 1, Dxy);
+	    out->SetComponent(index, 2, Dxz);
+	    out->SetComponent(index, 3, Dxy);
+	    out->SetComponent(index, 4, Dyy);
+	    out->SetComponent(index, 5, Dyz);
+	    out->SetComponent(index, 6, Dxz);
+	    out->SetComponent(index, 7, Dyz);
+	    out->SetComponent(index, 8, Dzz);
+	  } else {
+	    out->SetComponent(index, 0, Dxx);
+	    out->SetComponent(index, 1, Dxy);
+	    out->SetComponent(index, 2, Dxz);
+	    out->SetComponent(index, 3, Dyy);
+	    out->SetComponent(index, 4, Dyz);
+	    out->SetComponent(index, 5, Dzz);	    
+	  }
+	  
+	  ++index;	   	  
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorMultiply.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorMultiply.h
new file mode 100644
index 0000000..4dcda6b
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorMultiply.h
@@ -0,0 +1,76 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjImageTensorMultiply.h 
+
+      Marcel Jackowski, 2003.
+*/
+
+#ifndef __vtkmpjImageTensorMultiply_h 
+#define __vtkmpjImageTensorMultiply_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+
+class vtkmpjImageTensorMultiply : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageTensorMultiply *New();
+  vtkTypeMacro(vtkmpjImageTensorMultiply,vtkpxSimpleImageToImageFilter);
+  
+  void SetInput1(vtkImageData *input);
+  void SetInput2(vtkImageData *input);
+  vtkImageData *GetInput(int index);
+
+  vtkGetMacro(NoiseLevel, float);
+  vtkSetMacro(NoiseLevel, float);
+
+ protected: 
+  float NoiseLevel;
+
+  vtkmpjImageTensorMultiply();
+  ~vtkmpjImageTensorMultiply();
+
+  float GetGaussianDeviate();
+  virtual void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  
+ private:
+  void PrintMatrix3x3(char *title, float M[3][3]);
+  vtkmpjImageTensorMultiply(const vtkmpjImageTensorMultiply&); // Not implemented
+  void operator=(const vtkmpjImageTensorMultiply&); // Not implemented
+}; 
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorProduct.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorProduct.cpp
new file mode 100644
index 0000000..04d9dcf
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorProduct.cpp
@@ -0,0 +1,232 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageTensorProduct.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageTensorProduct* vtkmpjImageTensorProduct::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageTensorProduct");
+  if(ret)
+    {
+      return (vtkmpjImageTensorProduct*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageTensorProduct;
+}
+
+// Construct object with no children.
+vtkmpjImageTensorProduct::vtkmpjImageTensorProduct()
+{
+  this->KernelSize[0] = 3;
+  this->KernelSize[1] = 3;
+  this->KernelSize[2] = 3;
+  this->Mask = NULL;
+  this->Eigenvalues = NULL;
+  this->MaskOutValue = 0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageTensorProduct::~vtkmpjImageTensorProduct()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+  if (this->Eigenvalues != NULL)
+    this->Eigenvalues->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorProduct::ExecuteInformation()
+{
+  vtkImageData *eigvec=this->GetEigenvectors();
+  vtkImageData *eigval=this->GetEigenvalues();
+  vtkImageData *output=this->GetOutput();
+  
+  if (eigvec==NULL || eigval==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  eigvec->GetDimensions(dim);
+  int ncv=eigvec->GetNumberOfScalarComponents();
+  int ncd=eigval->GetNumberOfScalarComponents();
+  
+  if (ncv < 9 || ncd < 3) {
+    vtkErrorMacro(<< "Three eigenvectors and three eigenvalues are required as input!");
+    return;
+  }
+
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorProduct::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  vtkImageData *eigvec=input;
+  vtkImageData *eigval=this->GetEigenvalues();
+  vtkDataArray* inv =eigvec->GetPointData()->GetScalars();
+  vtkDataArray *ind =eigval->GetPointData()->GetScalars();
+ 
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  int mink = this->KernelSize[2] / 2;
+  int minj = this->KernelSize[1] / 2;
+  int mini = this->KernelSize[0] / 2;
+  int total_ij = dim[0]*dim[1];
+  int index = 0;
+
+  /*  printf("mini=%d,minj=%d,mink=%d\n",mini,minj,mink);*/
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  if ((mask != NULL)?(mask->GetComponent(index, 0) > 0):1)
+	    {
+	      float v[3][3];	      
+	      v[0][0] = inv->GetComponent(index, 0);
+	      v[1][0] = inv->GetComponent(index, 1);
+	      v[2][0] = inv->GetComponent(index, 2);		      	      
+	      v[0][1] = inv->GetComponent(index, 3);
+	      v[1][1] = inv->GetComponent(index, 4);
+	      v[2][1] = inv->GetComponent(index, 5);	      
+	      v[0][2] = inv->GetComponent(index, 6);
+	      v[1][2] = inv->GetComponent(index, 7);
+	      v[2][2] = inv->GetComponent(index, 8);
+	      
+	      float d[3];
+	      d[0]=ind->GetComponent(index, 0);
+	      d[1]=ind->GetComponent(index, 1);
+	      d[2]=ind->GetComponent(index, 2);
+
+	      float md=(d[0]+d[1]+d[2]) / 3;
+
+	      int count = 0;
+	      float sum=0;
+
+	      /* calculate neghborhood coherence */
+	      for (int nk=-mink; nk<=mink; nk++) {
+		int total_k = (k + nk) * total_ij;
+
+		for (int nj=-minj; nj<=minj; nj++) {
+		  int total_jk = total_k + (j + nj)*dim[0];
+
+		  for (int ni=-mini; ni<=mini; ni++) {
+
+		    /* skip center voxel */
+		    if (nk==0 && nj==0 && ni==0) continue;
+		    
+		    /* determine neighbor's address in image array */
+		    int nindex = total_jk + (i + ni);
+		    
+		    /* handle boundaries */
+		    if ((k+nk)>=0 && (j+nj)>=0 && (i+ni)>=0 &&
+			(k+nk)<dim[2] && (j+nj)<dim[1] && (i+ni)<dim[0] ) {
+		      
+		      /* if neighbor is in mask */
+		      if ((mask != NULL)?(mask->GetComponent(nindex, 0) > 0):1) {
+					
+			float w[3][3];
+			
+			w[0][0] = inv->GetComponent(nindex, 0);
+			w[1][0] = inv->GetComponent(nindex, 1);
+			w[2][0] = inv->GetComponent(nindex, 2);		      
+			
+			w[0][1] = inv->GetComponent(nindex, 3);
+			w[1][1] = inv->GetComponent(nindex, 4);
+			w[2][1] = inv->GetComponent(nindex, 5);
+
+			w[0][2] = inv->GetComponent(nindex, 6);
+			w[1][2] = inv->GetComponent(nindex, 7);
+			w[2][2] = inv->GetComponent(nindex, 8);
+			
+			float u[3];
+			u[0] = ind->GetComponent(nindex, 0);
+			u[1] = ind->GetComponent(nindex, 1);
+			u[2] = ind->GetComponent(nindex, 2);
+			
+			float tp=0.0;	
+			float dp=0.0;
+			float mu=(u[0]+u[1]+u[2]) / 3;
+			
+			for(int s=0; s<3; s++)
+			  for(int t=0; t<3; t++) {
+			    dp = v[0][s]*w[0][t] + v[1][s]*w[1][t] + v[2][s]*w[2][t];
+			    tp = tp + ((d[s]*u[t]*dp*dp) / (mu*md));
+			  }
+			
+			sum = sum + tp;
+			
+			++count;
+		      }
+		    }
+		  }
+		}
+	      }
+	      
+	      if ( count > 0 ) {
+		sum = sum / (float)count; 
+		out->SetComponent(index, 0, sum);
+	      } else {
+		out->SetComponent(index, 0, this->MaskOutValue);
+	      }
+	      
+	    } else {
+	      out->SetComponent(index, 0, this->MaskOutValue);
+	    }
+	  
+	  ++index;
+	 
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+  }
+  
+  this->UpdateProgress(1.0);
+
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorProduct.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorProduct.h
new file mode 100644
index 0000000..64f6484
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorProduct.h
@@ -0,0 +1,96 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjImageTensorProduct.h 
+   
+  Computes the tensor product as in Basser and Pierpaoli's 
+  paper "Microstructural and Physiological Features of Tissues
+  Elucidated by Quantitative Diffusion Tensor MRI, 1996.
+
+  Essentially the mean tensor product within in a prescribed 
+  neighborhood.
+
+  Marcel Jackowski, February 2003
+
+*/
+
+#ifndef __vtkmpjImageTensorProduct_h
+#define __vtkmpjImageTensorProduct_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjImageTensorProduct : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageTensorProduct *New();
+  vtkTypeMacro(vtkmpjImageTensorProduct,vtkpxSimpleImageToImageFilter);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents for invariants
+  // computation. If a mask is not provided, invariants are
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Sets/Gets eigenvalues
+  vtkSetObjectMacro(Eigenvalues, vtkImageData);
+  vtkGetObjectMacro(Eigenvalues, vtkImageData);
+
+  // Description:
+  // Set/Get the kernel size for computations;
+  vtkSetVector3Macro(KernelSize,int);
+  vtkGetVector3Macro(KernelSize,int);
+  
+  void SetEigenvectors(vtkImageData *input) { this->SetInput(input); }
+  vtkImageData* GetEigenvectors() { return this->GetInput(); }
+
+protected:
+  int KernelSize[3];
+  float MaskOutValue; 
+  vtkImageData *Mask;
+  vtkImageData *Eigenvalues;
+  
+  vtkmpjImageTensorProduct();
+  virtual ~vtkmpjImageTensorProduct();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  vtkmpjImageTensorProduct(const vtkmpjImageTensorProduct&); // Not implemented
+  void operator=(const vtkmpjImageTensorProduct&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorSimilarity.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorSimilarity.cpp
new file mode 100644
index 0000000..bb618e4
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorSimilarity.cpp
@@ -0,0 +1,360 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageTensorSimilarity.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageTensorSimilarity* vtkmpjImageTensorSimilarity::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageTensorSimilarity");
+  if(ret)
+    {
+      return (vtkmpjImageTensorSimilarity*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageTensorSimilarity;
+}
+
+// Construct object with no children.
+vtkmpjImageTensorSimilarity::vtkmpjImageTensorSimilarity()
+{
+  this->KernelSize[0] = 3;
+  this->KernelSize[1] = 3;
+  this->KernelSize[2] = 3;
+  this->Mask = NULL;
+  this->MaskOutValue = 0;
+  this->Ordering = VTK_MPJ_TENSOR_XXXYXZYYYZZZ;   
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageTensorSimilarity::~vtkmpjImageTensorSimilarity()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorSimilarity::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+  
+  if (nc < 9) {
+    if (nc < 6) {
+      vtkErrorMacro(<< "A tensor image is required as input!\n");
+      return;
+    }
+  }
+  
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorSimilarity::TensorDifference(float T[3][3], float U[3][3], float R[3][3])
+{
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++)
+      R[i][j]=T[i][j]-U[i][j];
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorSimilarity::GetReducedTensor(vtkDataArray *in, int index, float T[3][3]) 
+{
+  // set tensor matrix
+  if (this->Ordering == VTK_MPJ_TENSOR_XXXYXZYYYZZZ) {
+    
+    T[0][0] = in->GetComponent(index, 0);           /* Dxx */
+    T[1][0] = T[0][1] = in->GetComponent(index, 1); /* Dxy */
+    T[2][0] = T[0][2] = in->GetComponent(index, 2); /* Dxz */
+    T[1][1] = in->GetComponent(index, 3);           /* Dyy */
+    T[2][1] = T[1][2] = in->GetComponent(index, 4); /* Dyz */
+    T[2][2] = in->GetComponent(index, 5);           /* Dzz */
+    
+  } else {
+    
+    T[0][0] = in->GetComponent(index, 0);           /* Dxx */
+    T[1][0] = T[0][1] = in->GetComponent(index, 3); /* Dxy */
+    T[2][0] = T[0][2] = in->GetComponent(index, 5); /* Dxz */
+    T[1][1] = in->GetComponent(index, 1);           /* Dyy */
+    T[2][1] = T[1][2] = in->GetComponent(index, 4); /* Dyz */
+    T[2][2] = in->GetComponent(index, 2);           /* Dzz */
+    
+  }  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorSimilarity::GetFullTensor(vtkDataArray *in, int index, float T[3][3])
+{
+  T[0][0] = in->GetComponent(index, 0); /* Dxx */
+  T[1][0] = in->GetComponent(index, 1); /* Dxy */
+  T[2][0] = in->GetComponent(index, 2); /* Dxz */
+  T[0][1] = in->GetComponent(index, 3); /* Dyx */
+  T[1][1] = in->GetComponent(index, 4); /* Dyy */
+  T[2][1] = in->GetComponent(index, 5); /* Dyz */
+  T[0][2] = in->GetComponent(index, 6); /* Dzx */
+  T[1][2] = in->GetComponent(index, 7); /* Dzy */
+  T[2][2] = in->GetComponent(index, 8); /* Dzz */
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorSimilarity::ExecuteWithFullTensor(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+ 
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  int mink = this->KernelSize[2] / 2;
+  int minj = this->KernelSize[1] / 2;
+  int mini = this->KernelSize[0] / 2;
+  int total_ij = dim[0]*dim[1];
+  int index = 0;
+  float T[3][3], U[3][3], R[3][3];
+  float dist;
+
+  /*  printf("mini=%d,minj=%d,mink=%d\n",mini,minj,mink);*/
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  if ((mask != NULL)?(mask->GetComponent(index, 0) > 0):1)
+	    {
+	      this->GetFullTensor(in, index, T);
+
+	      int count = 0;
+	      float sum=0;
+
+	      /* calculate neghborhood coherence */
+	      for (int nk=-mink; nk<=mink; nk++) {
+		int total_k = (k + nk) * total_ij;
+
+		for (int nj=-minj; nj<=minj; nj++) {
+		  int total_jk = total_k + (j + nj)*dim[0];
+
+		  for (int ni=-mini; ni<=mini; ni++) {
+
+		    /* skip center voxel */
+		    if (nk==0 && nj==0 && ni==0) continue;
+		    
+		    /* determine neighbor's address in image array */
+		    int nindex = total_jk + (i + ni);
+		    
+		    /* handle boundaries */
+		    if ((k+nk)>=0 && (j+nj)>=0 && (i+ni)>=0 &&
+			(k+nk)<dim[2] && (j+nj)<dim[1] && (i+ni)<dim[0] ) {
+		      
+		      /* if neighbor is in mask */
+		      if ((mask != NULL)?(mask->GetComponent(nindex, 0) > 0):1) {
+			
+			// get neighboring tensor
+			this->GetReducedTensor(in, nindex, U);
+			
+			// compute tensor difference
+			this->TensorDifference(T, U, R);
+			
+			dist = R[0][0]*R[0][0] + R[1][1]*R[1][1] + R[2][2]*R[2][2];
+			
+			sum = sum + sqrt(dist);
+
+			++count;
+		      }
+		    }
+		  }
+		}
+	      }
+	      
+	      if ( count > 0 ) {
+		sum = sum / (float)count; 
+		out->SetComponent(index, 0, sum == 0.0 ? 100.0 : 1.0 / sum);
+	      } else {
+		out->SetComponent(index, 0, this->MaskOutValue);
+	      }
+	      
+	    } else {
+	      out->SetComponent(index, 0, this->MaskOutValue);
+	    }
+	  
+	  ++index;
+	 
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+  }
+  
+  this->UpdateProgress(1.0);
+
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorSimilarity::ExecuteWithReducedTensor(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+ 
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  int mink = this->KernelSize[2] / 2;
+  int minj = this->KernelSize[1] / 2;
+  int mini = this->KernelSize[0] / 2;
+  int total_ij = dim[0]*dim[1];
+  int index = 0;
+  float T[3][3], U[3][3], R[3][3];
+  float dist;
+
+  /*  printf("mini=%d,minj=%d,mink=%d\n",mini,minj,mink);*/
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  if ((mask != NULL)?(mask->GetComponent(index, 0) > 0):1)
+	    {
+	      this->GetReducedTensor(in, index, T);
+
+	      int count = 0;
+	      float sum=0;
+
+	      /* calculate neghborhood coherence */
+	      for (int nk=-mink; nk<=mink; nk++) {
+		int total_k = (k + nk) * total_ij;
+
+		for (int nj=-minj; nj<=minj; nj++) {
+		  int total_jk = total_k + (j + nj)*dim[0];
+
+		  for (int ni=-mini; ni<=mini; ni++) {
+
+		    /* skip center voxel */
+		    if (nk==0 && nj==0 && ni==0) continue;
+		    
+		    /* determine neighbor's address in image array */
+		    int nindex = total_jk + (i + ni);
+		    
+		    /* handle boundaries */
+		    if ((k+nk)>=0 && (j+nj)>=0 && (i+ni)>=0 &&
+			(k+nk)<dim[2] && (j+nj)<dim[1] && (i+ni)<dim[0] ) {
+		      
+		      /* if neighbor is in mask */
+		      if ((mask != NULL)?(mask->GetComponent(nindex, 0) > 0):1) {
+			
+			// get neighboring tensor
+			this->GetReducedTensor(in, nindex, U);
+			
+			// compute tensor difference
+			this->TensorDifference(T, U, R);
+			
+			dist = R[0][0]*R[0][0] + R[1][1]*R[1][1] + R[2][2]*R[2][2];
+			
+			sum = sum + sqrt(dist);
+			
+			++count;
+		      }
+		    }
+		  }
+		}
+	      }
+	      
+	      if ( count > 0 ) {
+		sum = sum / (float)count; 
+		out->SetComponent(index, 0, sum == 0.0 ? 100.0 : 1.0 / sum);
+	      } else {
+		out->SetComponent(index, 0, this->MaskOutValue);
+	      }
+	      
+	    } else {
+	      out->SetComponent(index, 0, this->MaskOutValue);
+	    }
+	  
+	  ++index;
+	 
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+  }
+  
+  this->UpdateProgress(1.0);
+
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorSimilarity::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+   
+  // Get number of tensor elements
+  int nc = input->GetNumberOfScalarComponents();
+  
+  if (nc > 6)
+    this->ExecuteWithFullTensor(input, output);
+  else
+    this->ExecuteWithReducedTensor(input, output);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorSimilarity.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorSimilarity.h
new file mode 100644
index 0000000..a7970b0
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorSimilarity.h
@@ -0,0 +1,100 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjImageTensorSimilarity.h 
+   
+  Tensor Similarity Indices
+
+  Marcel Jackowski, June 2005
+
+*/
+
+#ifndef __vtkmpjImageTensorSimilarity_h
+#define __vtkmpjImageTensorSimilarity_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkDataArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+// Ordering
+#define VTK_MPJ_TENSOR_XXXYXZYYYZZZ 0
+#define VTK_MPJ_TENSOR_XXYYZZXYYZXZ 1
+
+class vtkmpjImageTensorSimilarity : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageTensorSimilarity *New();
+  vtkTypeMacro(vtkmpjImageTensorSimilarity,vtkpxSimpleImageToImageFilter);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents for invariants
+  // computation. If a mask is not provided, invariants are
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Set/Get the component ordering information
+  vtkSetMacro(Ordering,int);
+  vtkGetMacro(Ordering,int);
+
+  // Description:
+  // Set/Get the kernel size for computations;
+  vtkSetVector3Macro(KernelSize,int);
+  vtkGetVector3Macro(KernelSize,int);
+  
+protected:
+  int Ordering;
+  int KernelSize[3];
+  float MaskOutValue; 
+  vtkImageData *Mask;
+  
+  vtkmpjImageTensorSimilarity();
+  virtual ~vtkmpjImageTensorSimilarity();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  vtkmpjImageTensorSimilarity(const vtkmpjImageTensorSimilarity&); // Not implemented
+  void operator=(const vtkmpjImageTensorSimilarity&); // Not Implemented
+
+  void ExecuteWithReducedTensor(vtkImageData *input, vtkImageData *output);
+  void ExecuteWithFullTensor(vtkImageData *input, vtkImageData *output);
+  void GetReducedTensor(vtkDataArray *in, int index, float T[3][3]);
+  void GetFullTensor(vtkDataArray *in, int index, float T[3][3]);
+  void TensorDifference(float T[3][3], float U[3][3], float R[3][3]);
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorTransform.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorTransform.cpp
new file mode 100644
index 0000000..50d3696
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorTransform.cpp
@@ -0,0 +1,232 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageTensorTransform.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageTensorTransform* vtkmpjImageTensorTransform::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageTensorTransform");
+
+  if(ret) {
+    return (vtkmpjImageTensorTransform*)ret;
+  }
+
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageTensorTransform;
+}
+
+// Construct object with no children.
+vtkmpjImageTensorTransform::vtkmpjImageTensorTransform()
+{
+  this->Rotation[0]=0.0;
+  this->Rotation[1]=0.0;
+  this->Rotation[2]=0.0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageTensorTransform::~vtkmpjImageTensorTransform()
+{
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjImageTensorTransform::PrintMatrix3x3(char *title, float M[3][3])
+{
+  printf("%s",title);
+  printf("%f %f %f\n",M[0][0],M[0][1],M[0][2]);
+  printf("%f %f %f\n",M[1][0],M[1][1],M[1][2]);
+  printf("%f %f %f\n",M[2][0],M[2][1],M[2][2]);
+  printf("===============================\n");
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorTransform::ExecuteInformation()
+{
+  // start with defaults
+  vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  vtkImageData *output = this->GetOutput();
+  vtkImageData *input = this->GetInput();
+  int dim[3];  input->GetDimensions(dim);
+
+  if (input->GetNumberOfScalarComponents() == 9) {
+    output->SetNumberOfScalarComponents(9);
+  } else {
+    output->SetNumberOfScalarComponents(6);
+  }
+
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorTransform::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int numcomp = input->GetNumberOfScalarComponents();
+  int dim[3];  input->GetDimensions(dim);
+
+  vtkDataArray* in=input->GetPointData()->GetScalars();
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+
+  float T[3][3];                            /* tensor matrix */
+  float R[3][3];                            /* aggregate rotation */
+  float RT[3][3];                           /* its transpose */
+  float D[3][3];                            /* transformed tensor */
+
+  float Rx[3][3];
+  float Ry[3][3];
+  float Rz[3][3];
+
+  float Temp[3][3];
+
+  float Dxx;
+  float Dyy;
+  float Dzz;
+  float Dxy;
+  float Dxz;
+  float Dyz;
+
+  //float twopi= 2.0 * vtkMath::Pi();
+  float theta;
+
+  //printf("Rotation=%f,%f,%f\n",this->Rotation[0],this->Rotation[1],this->Rotation[2]);
+
+  // rotation about x
+#if ((VTK_MAJOR_VERSION >= 5)&&(VTK_MINOR_VERSION >= 4))
+  theta = vtkMath::RadiansFromDegrees(Rotation[0]);
+#else
+  theta = Rotation[0] * vtkMath::DegreesToRadians();
+#endif
+  Rx[0][0] = 1;  Rx[0][1] = 0;           Rx[0][2] = 0;
+  Rx[1][0] = 0;  Rx[1][1] = cos(theta);  Rx[1][2] = -sin(theta);
+  Rx[2][0] = 0;  Rx[2][1] = sin(theta);  Rx[2][2] = cos(theta);
+
+  // rotation about y
+#if ((VTK_MAJOR_VERSION >= 5)&&(VTK_MINOR_VERSION >= 4))
+  theta = vtkMath::RadiansFromDegrees(Rotation[1]);
+#else
+  theta = Rotation[1] * vtkMath::DegreesToRadians();
+#endif
+  Ry[0][0] = cos(theta);   Ry[0][1] = 0;  Ry[0][2] = sin(theta);
+  Ry[1][0] = 0;            Ry[1][1] = 1;  Ry[1][2] = 0;
+  Ry[2][0] = -sin(theta);  Ry[2][1] = 0;  Ry[2][2] = cos(theta);
+
+  // rotation about z
+#if ((VTK_MAJOR_VERSION >= 5)&&(VTK_MINOR_VERSION >= 4))
+  theta = vtkMath::RadiansFromDegrees(Rotation[2]);
+#else
+  theta = Rotation[0] * vtkMath::DegreesToRadians();
+#endif
+  Rz[0][0] = cos(theta);  Rz[0][1] = -sin(theta);  Rz[0][2] = 0;
+  Rz[1][0] = sin(theta);  Rz[1][1] = cos(theta);   Rz[1][2] = 0;
+  Rz[2][0] = 0;           Rz[2][1] = 0;            Rz[2][2] = 1;
+
+  // compute aggregate rotation matrix
+  (void) vtkMath::Multiply3x3(Rz,Rx,Temp);
+  (void) vtkMath::Multiply3x3(Temp,Ry,R);
+  (void) vtkMath::Transpose3x3(R,RT);
+
+  int index=0;
+
+  //printf("number of components=%d\n", numcomp);
+
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  if (numcomp == 9) {
+
+	    T[0][0] = Dxx = in->GetComponent(index, 0);
+	    T[1][0] = Dxy = in->GetComponent(index, 1);
+	    T[2][0] = Dxz = in->GetComponent(index, 2);
+	    T[0][1] = Dxy = in->GetComponent(index, 3);
+	    T[1][1] = Dyy = in->GetComponent(index, 4);
+	    T[2][1] = Dyz = in->GetComponent(index, 5);
+	    T[0][2] = Dxz = in->GetComponent(index, 6);
+	    T[1][2] = Dyz = in->GetComponent(index, 7);
+	    T[2][2] = Dzz = in->GetComponent(index, 8);
+
+	  } else {
+	    
+	    T[0][0] = Dxx = in->GetComponent(index, 0);
+	    T[1][0] = T[0][1] = Dxy = in->GetComponent(index, 1);
+	    T[2][0] = T[0][2] = Dxz = in->GetComponent(index, 2);
+	    T[1][1] = Dyy = in->GetComponent(index, 3);
+	    T[2][1] = T[1][2] = Dyz = in->GetComponent(index, 4);
+	    T[2][2] = Dzz = in->GetComponent(index, 5);
+
+	  }
+	  
+	  // multiply tensor
+	  (void) vtkMath::Multiply3x3(T,R,Temp);
+	  (void) vtkMath::Multiply3x3(RT,Temp,D);
+
+	  Dxx = D[0][0];
+	  Dyy = D[1][1];
+	  Dzz = D[2][2];
+	  Dxy = D[0][1];
+	  Dxz = D[0][2];
+	  Dyz = D[1][2];
+	  
+	  if (numcomp == 9) {
+	    out->SetComponent(index, 0, Dxx);
+	    out->SetComponent(index, 1, Dxy);
+	    out->SetComponent(index, 2, Dxz);
+	    out->SetComponent(index, 3, Dxy);
+	    out->SetComponent(index, 4, Dyy);
+	    out->SetComponent(index, 5, Dyz);
+	    out->SetComponent(index, 6, Dxz);
+	    out->SetComponent(index, 7, Dyz);
+	    out->SetComponent(index, 8, Dzz);
+	  } else {
+	    out->SetComponent(index, 0, Dxx);
+	    out->SetComponent(index, 1, Dxy);
+	    out->SetComponent(index, 2, Dxz);
+	    out->SetComponent(index, 3, Dyy);
+	    out->SetComponent(index, 4, Dyz);
+	    out->SetComponent(index, 5, Dzz);
+	  }
+	  
+	  ++index;
+	}
+
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);
+
+  }
+
+  this->UpdateProgress(1.0);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorTransform.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorTransform.h
new file mode 100644
index 0000000..918a790
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorTransform.h
@@ -0,0 +1,72 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjImageTensorTransform.h 
+
+      Marcel Jackowski, 2006.
+*/
+
+#ifndef __vtkmpjImageTensorTransform_h 
+#define __vtkmpjImageTensorTransform_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "vtkpxMath.h"
+
+class vtkmpjImageTensorTransform : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageTensorTransform *New();
+  vtkTypeMacro(vtkmpjImageTensorTransform,vtkpxSimpleImageToImageFilter);
+  
+  vtkGetVectorMacro(Rotation, float, 3);
+  vtkSetVectorMacro(Rotation, float, 3);
+  
+ protected: 
+  float Rotation[3];
+  
+  vtkmpjImageTensorTransform();
+  ~vtkmpjImageTensorTransform();
+  
+  virtual void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  
+ private:
+  void PrintMatrix3x3(char *title, float M[3][3]);
+  vtkmpjImageTensorTransform(const vtkmpjImageTensorTransform&); // Not implemented
+  void operator=(const vtkmpjImageTensorTransform&); // Not implemented
+}; 
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorVariance.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorVariance.cpp
new file mode 100644
index 0000000..e4ef90f
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorVariance.cpp
@@ -0,0 +1,212 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageTensorVariance.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageTensorVariance* vtkmpjImageTensorVariance::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageTensorVariance");
+  if(ret)
+    {
+      return (vtkmpjImageTensorVariance*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageTensorVariance;
+}
+
+// Construct object with no children.
+vtkmpjImageTensorVariance::vtkmpjImageTensorVariance()
+{
+  this->KernelSize[0] = 3;
+  this->KernelSize[1] = 3;
+  this->KernelSize[2] = 3;
+  this->Mask = NULL;
+  this->MaskOutValue = 0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageTensorVariance::~vtkmpjImageTensorVariance()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorVariance::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+  
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageTensorVariance::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+ 
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  int mink = this->KernelSize[2] / 2;
+  int minj = this->KernelSize[1] / 2;
+  int mini = this->KernelSize[0] / 2;
+  int total_ij = dim[0]*dim[1];
+  int index = 0;
+  float v[3], r[3];
+
+  float *vals = new float[this->KernelSize[2]*this->KernelSize[1]*this->KernelSize[0]]; 
+
+  /*  printf("mini=%d,minj=%d,mink=%d\n",mini,minj,mink);*/
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  if ((mask != NULL)?(mask->GetComponent(index, 0) > 0):1)
+	    {
+	      r[0] = in->GetComponent(index, 0);
+	      r[1] = in->GetComponent(index, 1);
+	      r[2] = in->GetComponent(index, 2);
+	      (void)vtkMath::Normalize(r);
+
+	      int count = 0;
+
+	      /* calculate neghborhood variance */
+	      for (int nk=-mink; nk<=mink; nk++) {
+		int total_k = (k + nk) * total_ij;
+
+		for (int nj=-minj; nj<=minj; nj++) {
+		  int total_jk = total_k + (j + nj)*dim[0];
+
+		  for (int ni=-mini; ni<=mini; ni++) {
+
+		    /* skip center voxel */
+		    if (nk==0 && nj==0 && ni==0) continue;
+		    
+		    /* determine neighbor's address in image array */
+		    int nindex = total_jk + (i + ni);
+		    
+		    /* handle boundaries */
+		    if ((k+nk)>=0 && (j+nj)>=0 && (i+ni)>=0 &&
+			(k+nk)<dim[2] && (j+nj)<dim[1] && (i+ni)<dim[0] ) {
+		      
+		      /* if neighbor is in mask */
+		      if ((mask != NULL)?(mask->GetComponent(nindex, 0) > 0):1) {
+			
+			v[0] = in->GetComponent(nindex, 0);
+			v[1] = in->GetComponent(nindex, 1);
+			v[2] = in->GetComponent(nindex, 2);
+			(void)vtkMath::Normalize(v);
+
+			float cossine = fabs(r[0]*v[0] + r[1]*v[1] + r[2]*v[2]);
+			//			printf("g\n");
+			vals[count++] = cossine;
+		      }
+		    }
+		  }
+		}
+	      }	      
+	      
+	      //	      printf("count=%d\n",count);
+
+	      // calculate variance
+	      if ( count > 0 ) {
+		
+		// calc mean
+		float sum = 0;
+
+		for(int n=0;n<count;n++)
+		  sum += vals[n];		
+
+		float mean = sum / (float)count;
+		
+		//printf("h!\n");
+		sum = 0;
+		for(int n=0; n<count;n++){
+		  sum += (vals[n]-mean)*(vals[n]-mean);
+		}
+		
+		sum = sum / ((float)count-1.0); 
+		
+		out->SetComponent(index, 0, sqrt(sum));
+		
+		
+	      } else {
+		out->SetComponent(index, 0, this->MaskOutValue);
+	      }
+	      
+	    } else {
+	      out->SetComponent(index, 0, this->MaskOutValue);
+	    }
+	  
+	  ++index;
+	 
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+  }
+  
+  this->UpdateProgress(1.0);
+
+  delete[] vals;
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorVariance.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorVariance.h
new file mode 100644
index 0000000..19da000
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageTensorVariance.h
@@ -0,0 +1,86 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjImageTensorVariance.h 
+   
+  Computes the intervoxel variance
+
+  Essentially the variance of the dot product of the principal eigenvector
+  in a neighborhood.
+
+  Marcel Jackowski, December 2005.
+
+*/
+
+#ifndef __vtkmpjImageTensorVariance_h
+#define __vtkmpjImageTensorVariance_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjImageTensorVariance : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjImageTensorVariance *New();
+  vtkTypeMacro(vtkmpjImageTensorVariance,vtkpxSimpleImageToImageFilter);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents for invariants
+  // computation. If a mask is not provided, invariants are
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Set/Get the kernel size for computations;
+  vtkSetVector3Macro(KernelSize,int);
+  vtkGetVector3Macro(KernelSize,int);
+  
+protected:
+  int KernelSize[3];
+  float MaskOutValue; 
+  vtkImageData *Mask;
+  
+  vtkmpjImageTensorVariance();
+  virtual ~vtkmpjImageTensorVariance();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  vtkmpjImageTensorVariance(const vtkmpjImageTensorVariance&); // Not implemented
+  void operator=(const vtkmpjImageTensorVariance&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageToTensors.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageToTensors.cpp
new file mode 100644
index 0000000..1250686
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageToTensors.cpp
@@ -0,0 +1,138 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageToTensors.h"
+#include "vtkFloatArray.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageToTensors* vtkmpjImageToTensors::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageToTensors");
+  if(ret)
+    {
+      return (vtkmpjImageToTensors*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageToTensors;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageToTensors::vtkmpjImageToTensors()
+{
+  this->SymmetricTensor = 0;
+  this->FlipX = this->FlipY = this->FlipZ = 0;
+} 
+
+vtkmpjImageToTensors::~vtkmpjImageToTensors()
+{
+} 
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageToTensors::Execute()
+{ 
+  vtkIdType numTensors;
+
+  vtkDataSet *input=this->GetInput();
+  vtkDataSet *output=this->GetOutput();
+
+  vtkPointData *inPD=input->GetPointData();
+  vtkPointData *outPD=output->GetPointData();
+
+  vtkDataArray *in=inPD->GetScalars();
+  vtkDataArray *tensors;
+  
+  output->CopyStructure(input);
+  //  output->SetNumberOfScalarComponents(input->GetNumberOfScalarComponents());
+
+  numTensors = in->GetNumberOfTuples();
+
+  tensors = vtkFloatArray::New();
+  tensors->SetNumberOfComponents(9);
+  tensors->SetNumberOfTuples(numTensors);
+  
+  float Txx, Tyx, Tzx;
+  float Txy, Tyy, Tzy;
+  float Txz, Tyz, Tzz;
+  
+  float flipx = this->FlipX ? -1.0: 1.0;
+  float flipy = this->FlipY ? -1.0: 1.0;
+  float flipz = this->FlipZ ? -1.0: 1.0;
+  
+  for(int index=0; index<numTensors; index++) {
+  
+    if (this->SymmetricTensor) {
+      
+      Txx = inPD->GetComponent(index, 0);
+      Txy = inPD->GetComponent(index, 1);
+      Txz = inPD->GetComponent(index, 2);
+      
+      Tyx = Txy;
+      Tyy = inPD->GetComponent(index, 3);
+      Tyz = inPD->GetComponent(index, 4);
+      
+      Tzx = Txz * flipx;
+      Tzy = Tyz * flipy;
+      Tzz = inPD->GetComponent(index, 5);
+
+    } else {
+
+      Txx = inPD->GetComponent(index, 0);
+      Txy = inPD->GetComponent(index, 1);
+      Txz = inPD->GetComponent(index, 2);
+      
+      Tyx = inPD->GetComponent(index, 3);
+      Tyy = inPD->GetComponent(index, 4);
+      Tyz = inPD->GetComponent(index, 5);
+      
+      Tzx = inPD->GetComponent(index, 6);
+      Tzy = inPD->GetComponent(index, 7);
+      Tzz = inPD->GetComponent(index, 8);
+
+    }
+    
+    tensors->InsertTuple9(index,Txx*flipx,Txy*flipy,Txz*flipz,
+			  Tyx*flipx,Tyy*flipy,Tyz*flipz,
+			  Tzx*flipx,Tzy*flipy,Tzz*flipz);
+
+  }
+  
+  outPD->SetTensors(tensors);
+  tensors->Delete();
+  
+  outPD->CopyTensorsOff();
+  outPD->PassData(inPD);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageToTensors.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageToTensors.h
new file mode 100644
index 0000000..ef98c5c
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageToTensors.h
@@ -0,0 +1,82 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjImageToTensors_h
+#define __vtkmpjImageToTensors_h
+
+#include "vtkDataSetToDataSetFilter.h"
+#include "vtkDataSet.h"
+#include "vtkPointData.h"
+
+class vtkmpjImageToTensors : public vtkDataSetToDataSetFilter
+{
+ public:
+  static vtkmpjImageToTensors *New();
+  vtkTypeMacro(vtkmpjImageToTensors,vtkDataSetToDataSetFilter);
+
+  // Description: turn on/off symmetric tensor flag
+  vtkGetMacro(SymmetricTensor, int);  
+  vtkSetClampMacro(SymmetricTensor, int, 0, 1);
+  vtkBooleanMacro(SymmetricTensor, int);
+
+  // Description: whether to flip the sign of the x-coordinate 
+  vtkSetMacro(FlipX,int);
+  vtkGetMacro(FlipX,int);
+  vtkBooleanMacro(FlipX,int);
+  
+  // Description: whether to flip the sign of the y-coordinate
+  vtkSetMacro(FlipY,int);
+  vtkGetMacro(FlipY,int);
+  vtkBooleanMacro(FlipY,int);
+  
+  // Description: whether to flip the sign of the z-coordinate
+  vtkSetMacro(FlipZ,int);
+  vtkGetMacro(FlipZ,int);
+  vtkBooleanMacro(FlipZ,int);
+
+ protected:  
+  vtkmpjImageToTensors();
+  virtual ~vtkmpjImageToTensors();
+  int SymmetricTensor;  
+
+  int FlipX;
+  int FlipY;
+  int FlipZ;
+
+  void Execute();
+  
+ private:
+  vtkmpjImageToTensors(const vtkmpjImageToTensors&); // Not implemented
+  void operator=(const vtkmpjImageToTensors&); // Not implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageToVectors.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageToVectors.cpp
new file mode 100644
index 0000000..ce6b8f3
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageToVectors.cpp
@@ -0,0 +1,102 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjImageToVectors.h"
+#include "vtkFloatArray.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageToVectors* vtkmpjImageToVectors::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageToVectors");
+  if(ret)
+    {
+      return (vtkmpjImageToVectors*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageToVectors;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageToVectors::vtkmpjImageToVectors()
+{
+  this->FlipX = this->FlipY = this->FlipZ = 0;
+} 
+
+vtkmpjImageToVectors::~vtkmpjImageToVectors()
+{
+} 
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageToVectors::Execute()
+{ 
+  vtkIdType numVectors;
+
+  vtkDataSet *input=this->GetInput();
+  vtkDataSet *output=this->GetOutput();
+
+  vtkPointData *inPD=input->GetPointData();
+  vtkPointData *outPD=output->GetPointData();
+
+  vtkDataArray *in=inPD->GetScalars();
+  vtkDataArray *vectors;
+  
+  output->CopyStructure(input);
+
+  numVectors = in->GetNumberOfTuples();
+
+  vectors = vtkFloatArray::New();
+  vectors->SetNumberOfComponents(3);
+  vectors->SetNumberOfTuples(numVectors);
+
+  float flipx = this->FlipX ? -1.0 : 1.0;
+  float flipy = this->FlipY ? -1.0 : 1.0;
+  float flipz = this->FlipZ ? -1.0 : 1.0;
+
+  for(int index=0; index<numVectors; index++) {
+    
+    //    fprintf(stderr,"%f %f %f\n",inPD->GetComponent(index, 0),inPD->GetComponent(index, 1),inPD->GetComponent(index, 2));
+    vectors->SetComponent(index, 0, flipx * in->GetComponent(index, 0));
+    vectors->SetComponent(index, 1, flipy * in->GetComponent(index, 1));
+    vectors->SetComponent(index, 2, flipz * in->GetComponent(index, 2));
+  }
+  
+  outPD->SetVectors(vectors);
+  vectors->Delete();
+  
+  outPD->CopyVectorsOff();
+  outPD->PassData(inPD);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjImageToVectors.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageToVectors.h
new file mode 100644
index 0000000..d34faf7
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjImageToVectors.h
@@ -0,0 +1,77 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjImageToVectors_h
+#define __vtkmpjImageToVectors_h
+
+#include "vtkDataSetToDataSetFilter.h"
+#include "vtkDataSet.h"
+#include "vtkPointData.h"
+
+class vtkmpjImageToVectors : public vtkDataSetToDataSetFilter
+{
+ public:
+  static vtkmpjImageToVectors *New();
+  vtkTypeMacro(vtkmpjImageToVectors,vtkDataSetToDataSetFilter);
+  
+  // Description: whether to flip the sign of the x-coordinate 
+  vtkSetMacro(FlipX,int);
+  vtkGetMacro(FlipX,int);
+  vtkBooleanMacro(FlipX,int);
+  
+  // Description: whether to flip the sign of the y-coordinate
+  vtkSetMacro(FlipY,int);
+  vtkGetMacro(FlipY,int);
+  vtkBooleanMacro(FlipY,int);
+  
+  // Description: whether to flip the sign of the z-coordinate
+  vtkSetMacro(FlipZ,int);
+  vtkGetMacro(FlipZ,int);
+  vtkBooleanMacro(FlipZ,int);
+  
+ protected:
+  
+  vtkmpjImageToVectors();
+  virtual ~vtkmpjImageToVectors();
+  
+  int FlipX;
+  int FlipY;
+  int FlipZ;
+  
+  void Execute();
+  
+ private:
+  vtkmpjImageToVectors(const vtkmpjImageToVectors&); // Not implemented
+  void operator=(const vtkmpjImageToVectors&); // Not implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjLatticeAnisotropy.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjLatticeAnisotropy.cpp
new file mode 100644
index 0000000..d49b544
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjLatticeAnisotropy.cpp
@@ -0,0 +1,264 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjLatticeAnisotropy.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjLatticeAnisotropy* vtkmpjLatticeAnisotropy::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjLatticeAnisotropy");
+  if(ret)
+    {
+      return (vtkmpjLatticeAnisotropy*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjLatticeAnisotropy;
+}
+
+// Construct object with no children.
+vtkmpjLatticeAnisotropy::vtkmpjLatticeAnisotropy()
+{
+  this->KernelSize[0] = 3;
+  this->KernelSize[1] = 3;
+  this->KernelSize[2] = 3;
+  this->Mask = NULL;
+  this->Eigenvalues = NULL;
+  this->MaskOutValue = 0;
+  this->Method=VTK_MPJ_LATTICEANISO_BASSER;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjLatticeAnisotropy::~vtkmpjLatticeAnisotropy()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+  if (this->Eigenvalues != NULL)
+    this->Eigenvalues->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLatticeAnisotropy::ExecuteInformation()
+{
+  vtkImageData *eigvec=this->GetEigenvectors();
+  vtkImageData *eigval=this->GetEigenvalues();
+  vtkImageData *output=this->GetOutput();
+  
+  if (eigvec==NULL || eigval==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  eigvec->GetDimensions(dim);
+  int ncv=eigvec->GetNumberOfScalarComponents();
+  int ncd=eigval->GetNumberOfScalarComponents();
+  
+  if (ncv < 9 || ncd < 3) {
+    vtkErrorMacro(<< "Three eigenvectors and three eigenvalues are required as input!");
+    return;
+  }
+
+  if (this->Method == VTK_MPJ_LATTICEANISO_BOTH)
+    output->SetNumberOfScalarComponents(2);
+  else output->SetNumberOfScalarComponents(1);  
+
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+float vtkmpjLatticeAnisotropy::TensorProduct(float ru[3], float nu[3], float rv[3][3], float nv[3][3])
+{
+  float tp=0.0;
+  for(int s=0; s<3; s++)
+    for(int t=0; t<3; t++) {
+      float dp = rv[0][s]*nv[0][t] + rv[1][s]*nv[1][t] + rv[2][s]*nv[2][t];
+      tp = tp + ru[s]*nu[t] * dp*dp;
+    }
+  return tp;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLatticeAnisotropy::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  vtkImageData *eigvec=input;
+  vtkImageData *eigval=this->GetEigenvalues();
+  vtkDataArray* invec =eigvec->GetPointData()->GetScalars();
+  vtkDataArray *inval =eigval->GetPointData()->GetScalars();
+ 
+  int dim[3];  input->GetDimensions(dim);
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  int mink = this->KernelSize[2] / 2;
+  int minj = this->KernelSize[1] / 2;
+  int mini = this->KernelSize[0] / 2;
+  int total_ij = dim[0]*dim[1];
+  int index = 0;
+
+  /*  printf("mini=%d,minj=%d,mink=%d\n",mini,minj,mink);*/
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	  if ((mask != NULL)?(mask->GetComponent(index, 0) > 0):1)
+	    {
+	      float rv[3][3];  /* reference eigenvectors */
+	      rv[0][0] = invec->GetComponent(index, 0);
+	      rv[1][0] = invec->GetComponent(index, 1);
+	      rv[2][0] = invec->GetComponent(index, 2);		      	      
+	      rv[0][1] = invec->GetComponent(index, 3);
+	      rv[1][1] = invec->GetComponent(index, 4);
+	      rv[2][1] = invec->GetComponent(index, 5);	      
+	      rv[0][2] = invec->GetComponent(index, 6);
+	      rv[1][2] = invec->GetComponent(index, 7);
+	      rv[2][2] = invec->GetComponent(index, 8);
+	      
+	      float ru[3];   /* reference eigenvalues */
+	      ru[0]=inval->GetComponent(index, 0);
+	      ru[1]=inval->GetComponent(index, 1);
+	      ru[2]=inval->GetComponent(index, 2);
+
+	      float tracer=ru[0]+ru[1]+ru[2];
+	      float tpr = TensorProduct(ru, ru, rv, rv);
+	      int count = 0;
+	      float sumLI=0;
+	      float sumAdd=0.0;
+	      float sumdist=0;
+	      
+	      /* calculate neghborhood coherence */
+	      for (int nk=-mink; nk<=mink; nk++) {
+		int total_k = (k + nk) * total_ij;
+		
+		for (int nj=-minj; nj<=minj; nj++) {
+		  int total_jk = total_k + (j + nj)*dim[0];
+		  
+		  for (int ni=-mini; ni<=mini; ni++) {
+
+		    /* skip center voxel */
+		    if (nk==0 && nj==0 && ni==0) continue;
+		    
+		    /* determine neighbor's address in image array */
+		    int nindex = total_jk + (i + ni);
+		    
+		    /* handle boundaries */
+		    if ((k+nk)>=0 && (j+nj)>=0 && (i+ni)>=0 &&
+			(k+nk)<dim[2] && (j+nj)<dim[1] && (i+ni)<dim[0]) {
+		      
+		      /* if neighbor is in mask */
+		      if ((mask != NULL)?(mask->GetComponent(nindex, 0) > 0):1) {
+					
+			float dist = 1.0 / sqrt(float(nk*nk + nj*nj + ni*ni));
+			//			fprintf(stderr,"dist=%f\n",dist);
+
+			float nv[3][3];  /* neighbor eigenvectors */
+			
+			nv[0][0] = invec->GetComponent(nindex, 0);
+			nv[1][0] = invec->GetComponent(nindex, 1);
+			nv[2][0] = invec->GetComponent(nindex, 2);		      
+			
+			nv[0][1] = invec->GetComponent(nindex, 3);
+			nv[1][1] = invec->GetComponent(nindex, 4);
+			nv[2][1] = invec->GetComponent(nindex, 5);
+
+			nv[0][2] = invec->GetComponent(nindex, 6);
+			nv[1][2] = invec->GetComponent(nindex, 7);
+			nv[2][2] = invec->GetComponent(nindex, 8);
+			
+			float nu[3];    /* neighbor eigenvalues */
+			nu[0] = inval->GetComponent(nindex, 0);
+			nu[1] = inval->GetComponent(nindex, 1);
+			nu[2] = inval->GetComponent(nindex, 2);
+			
+			float tracen = nu[0]+nu[1]+nu[2];
+			float tpn = TensorProduct(nu, nu, nv, nv);
+			float tp = TensorProduct(ru, nu, rv, nv);
+			float atp = fabs(tp - (1.0/3.0)*tracer*tracen);  /* aniso tensor product */
+			float a = sqrt(atp) / sqrt(tp);
+			float b = atp / (sqrt(tpr)*sqrt(tpn));
+			float LI = sqrt(3.0/8.0)*a + 3.0/4.0*b;
+			float Add = atp / tp;
+
+			//printf("atp=%f, tp=%f, tpn=%f, tpr=%f, a=%f, b=%f\n",atp,tp,tpn,tpr,a,b);
+			sumLI = sumLI + dist*LI;
+			sumAdd = sumAdd + dist*Add;
+
+			sumdist = sumdist + dist;
+ 
+			++count;
+		      } // within boundaries
+		    } // if in mask
+		  } //for ni
+		} // for nj
+	      } // for nk
+	      	      
+	      if ( count > 0 ) {
+		switch(this->Method) {
+		case VTK_MPJ_LATTICEANISO_BASSER:
+		  out->SetComponent(index, 0, sumLI/sumdist); 
+		  break;
+		case VTK_MPJ_LATTICEANISO_SKARE:
+		  out->SetComponent(index, 0, sumAdd/sumdist);
+		  break;
+		default:
+		  out->SetComponent(index, 0, sumLI/sumdist); 
+		  out->SetComponent(index, 1, sumAdd/sumdist); 
+		}
+	      } else {
+		out->SetComponent(index, 0, this->MaskOutValue);
+	      }
+	      
+	    } else {
+	      out->SetComponent(index, 0, this->MaskOutValue);
+	    }
+	  
+	  ++index;
+	 
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+  }
+  
+  this->UpdateProgress(1.0);
+
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjLatticeAnisotropy.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjLatticeAnisotropy.h
new file mode 100644
index 0000000..ee08f80
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjLatticeAnisotropy.h
@@ -0,0 +1,114 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjLatticeAnisotropy.h 
+  
+ Implements both Add and LI intervoxel anisotropy indices.
+
+A description of the Add coherence index was just recently published in 
+Skare S et al: "Noise considerations in the determination of diffusion tensor 
+anisotropy", MRI, 18(6):659-69, 2000. ( Medline citation). 
+The Add coherence index is similar to the Lattice Anisotropy (LI) defined in 
+Pierpaoli C. and Basser P.J.: "Toward a Quantitative Assessment of Diffusion
+Anisotropy", MRM 36, 893-906 (1996) (Medline citation). 
+  
+  Marcel Jackowski, February 2003
+
+*/
+
+#ifndef __vtkmpjLatticeAnisotropy_h
+#define __vtkmpjLatticeAnisotropy_h
+
+// Intervoxel anisotropy methods
+#define VTK_MPJ_LATTICEANISO_BOTH    0    
+#define VTK_MPJ_LATTICEANISO_BASSER  1
+#define VTK_MPJ_LATTICEANISO_SKARE   2
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjLatticeAnisotropy : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjLatticeAnisotropy *New();
+  vtkTypeMacro(vtkmpjLatticeAnisotropy,vtkpxSimpleImageToImageFilter);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents for invariants
+  // computation. If a mask is not provided, invariants are
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Sets/Gets eigenvalues
+  vtkSetObjectMacro(Eigenvalues, vtkImageData);
+  vtkGetObjectMacro(Eigenvalues, vtkImageData);
+
+  // Description:
+  // Set/Get the kernel size for computations;
+  vtkSetVector3Macro(KernelSize,int);
+  vtkGetVector3Macro(KernelSize,int);
+
+  // Description:
+  // Set/Get the Method to employ
+  vtkSetMacro(Method,int);
+  vtkGetMacro(Method,int);
+
+  void SetMethodToBasser() { this->SetMethod(VTK_MPJ_LATTICEANISO_BASSER);};
+  void SetMethodToSkare() { this->SetMethod(VTK_MPJ_LATTICEANISO_SKARE);};
+  void SetMethodToBasserAndSkare() {this->SetMethod(VTK_MPJ_LATTICEANISO_BOTH);};
+
+  void SetEigenvectors(vtkImageData *input) { this->SetInput(input); }
+  vtkImageData* GetEigenvectors() { return this->GetInput(); }
+
+protected:
+  int Method;
+  int KernelSize[3];
+  float MaskOutValue; 
+  vtkImageData *Mask;
+  vtkImageData *Eigenvalues;
+  
+  vtkmpjLatticeAnisotropy();
+  virtual ~vtkmpjLatticeAnisotropy();
+
+  float TensorProduct(float ru[3], float nu[3], float rv[3][3], float nv[3][3]);
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  vtkmpjLatticeAnisotropy(const vtkmpjLatticeAnisotropy&); // Not implemented
+  void operator=(const vtkmpjLatticeAnisotropy&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjQBallImaging.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjQBallImaging.cpp
new file mode 100644
index 0000000..0f6f1ae
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjQBallImaging.cpp
@@ -0,0 +1,315 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjQBallImaging.h"
+#include "vtkMath.h"
+#include "math.h"
+
+
+//------------------------------------------------------------------------------
+vtkmpjQBallImaging* vtkmpjQBallImaging::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjQBallImaging");
+  if(ret)
+    {
+      return (vtkmpjQBallImaging*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjQBallImaging;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjQBallImaging::vtkmpjQBallImaging()
+{
+  this->Baseline = NULL;
+  this->Mask = NULL;
+  this->Gradients = NULL;
+  this->Reconstruction = NULL;
+  this->Shift = 0.0;
+  this->bValue = 1.0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjQBallImaging::~vtkmpjQBallImaging()
+{
+  if (this->Baseline != NULL)
+    this->Baseline->Delete();
+
+  if (this->Mask != NULL)
+    this->Mask->Delete();  
+
+  printf("before gradients!\n");
+
+  if (this->Gradients != NULL)
+    this->Gradients->Delete();
+
+  if (this->Reconstruction != NULL)
+    this->Reconstruction->Delete();
+
+  printf("destruction complete!\n");
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjQBallImaging::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  if (this->Baseline == NULL) {
+    vtkErrorMacro(<<"No baseline (S0) image specified!");
+    return;
+  }
+  
+  if (this->Gradients == NULL) {
+    vtkErrorMacro(<<"No gradient directions specified!");
+    return;
+  }
+  
+  if (this->Reconstruction == NULL) {
+    vtkErrorMacro(<<"No reconstruction points specified!");
+    return;
+  }
+
+  int gnc = this->Gradients->GetNumberOfComponents();
+  int gnt = this->Gradients->GetNumberOfTuples();
+
+  if (gnc < 3) {
+    vtkErrorMacro(<<"There should be exactly 3 (gx,gy,gz) components for each gradient direction!");
+    return;
+  }
+
+  int rnt = this->Reconstruction->GetNumberOfPoints();
+    
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+    
+  if (nc < 6) {
+    vtkErrorMacro(<<"There should be at least 6 diffusion-weighted images in the dataset!");
+    return;
+  }
+  
+  if (gnt != nc) {
+    vtkErrorMacro(<<"There should be exactly the same number of DWs (" <<nc<<") as the number of gradient directions ("<<gnt<<") !");
+    return;
+  }
+  
+  // number of components in the result equals the number of 
+  // reconstruction points
+  output->SetNumberOfScalarComponents(rnt);
+
+  printf("number of components=%d\n",rnt);
+
+  output->SetScalarType(VTK_FLOAT);
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjQBallImaging::Smooth(double x, double sigma)
+{
+  return exp(-(x*x) / (sigma*sigma));
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjQBallImaging::ComputeReconstructionMatrix(double **A, double **B, double **C, int n, int m, int p) 
+{
+  // C[n,p] = A[n,m] * B[m,p]
+  for (int i=0;i<n;i++)
+    for (int j=0;j<p;j++) {
+      C[i][j] = 0;
+      for (int k=0;k<m;k++)
+	C[i][j] += A[i][k] * B[k][j];
+      C[i][j] = this->Smooth(acos(fabs(C[i][j])),1.0);
+    }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjQBallImaging::VectorMultiply(double **A, double *b, double *c, int n, int m)
+{
+  // c[n] = A[n,m] * b[m,1]
+  for (int i=0;i<n;i++) {
+    c[i] = 0;
+    for (int j=0;j<m;j++) {
+      c[i] += A[i][j] * b[j];
+    }
+  }        
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjQBallImaging::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+  
+  int dim[3];  input->GetDimensions(dim);
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  
+  vtkDataArray* baseline=NULL;
+  vtkDataArray* mask=NULL;
+  
+  if (this->Baseline != NULL) 
+    baseline = this->Baseline->GetPointData()->GetScalars();
+  
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  int m = this->Gradients->GetNumberOfTuples();
+  int n = this->Reconstruction->GetNumberOfPoints();
+  
+  /* set up reconstruction matrix */  
+  double** U = new double* [n];
+  for (int i=0; i<n; i++) {
+    double *p = this->Reconstruction->GetPoint(i);
+    double x = p[0];
+    double y = p[1];
+    double z = p[2];
+    U[i] = new double[3];
+    U[i][0] = x;
+    U[i][1] = y;
+    U[i][2] = z;
+  }
+  
+  /* set up gradient matrix */
+  double** Q = new double* [3];
+  for (int i=0; i<3; i++) {
+    Q[i] = new double[m];
+    for(int j=0; j<m; j++) {
+      double x = this->Gradients->GetComponent(j, i);
+      Q[i][j] = x;
+    }
+  }
+  
+  /* set up reconstruction matrix */
+  double **A = new double* [n];
+  for (int i=0; i<n; i++) {
+    A[i] = new double[m];
+  }
+
+  /* set up wavevectors */
+  double *e = new double[m];
+
+  /* set up odf vector */
+  double *odf = new double[n];
+
+  /* compute reconstruction matrix */
+  this->ComputeReconstructionMatrix(U,Q,A,n,3,m);
+  
+  /* build reconstruction matrix A = phi(arccos(|U'*Q|)) */
+  int nc = output->GetNumberOfScalarComponents();
+  
+  
+  int inmask;
+  int index=0;
+  
+  for (int k=0;k<dim[2];k++) {    
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  float baseln;
+	  
+	  baseln = float(baseline->GetComponent(index, 0)) + this->Shift;
+	  inmask = (mask != NULL)?(mask->GetComponent(index, 0) > 0) : 1;
+	  
+	  if (inmask) {
+	    
+	    int abort = 0;	    	 
+	    
+	    // Calculate ADCs
+	    for(int l=0; l<m && !abort; l++) {
+	      
+	      float value = float(in->GetComponent(index, l)) + this->Shift;
+	      abort = (value <= 0);
+	      e[l] = log(baseln / value) / this->bValue; 
+	      
+	    }
+	    
+	    if (abort == 0) {
+	      
+	      // Compute ODF
+	      this->VectorMultiply(A,e,odf,n,m);
+	      
+	      for (int z=0;z<n;z++) 
+		out->SetComponent(index, z, odf[z]);
+	      
+	    } else {
+	      
+	      for(int z=0;z<n;z++) 
+		out->SetComponent(index, z, (float)0);
+	      
+	    }
+	    
+	  } else {
+	    
+	    for(int z=0;z<n;z++) 
+	      out->SetComponent(index, z, (float)0);
+	  }	  
+	  
+	  ++index;	  
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+  
+  // free storage
+  delete[] odf;
+  delete[] e;
+  
+  for (int i=0; i<n; i++) {
+    delete[] U[i];
+    delete[] A[i];
+  }
+  
+  for (int i=0; i<3; i++) {
+    delete[] Q[i];
+  }
+
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjQBallImaging.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjQBallImaging.h
new file mode 100644
index 0000000..aadd547
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjQBallImaging.h
@@ -0,0 +1,111 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjQBallImaging.h 
+   
+      Marcel Jackowski, 2003
+
+      Q-Ball Imaging. (D. Tuch, MRM 52, 2004)
+
+*/
+
+#ifndef __vtkmpjQBallImaging_h
+#define __vtkmpjQBallImaging_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkPoints.h"
+#include "vtkDoubleArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjQBallImaging : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjQBallImaging *New();
+  vtkTypeMacro(vtkmpjQBallImaging,vtkpxSimpleImageToImageFilter);
+  
+  // Sets/Gets the baseline image A(b=0); the echo amplitude without any
+  // diffusion attenuation
+  vtkSetObjectMacro(Baseline, vtkImageData);
+  vtkGetObjectMacro(Baseline, vtkImageData);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents of tensor
+  // computation. If a mask is not provided, tensor is
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Sets/Gets the array of gradient directions (wavevectors)
+  vtkSetObjectMacro(Gradients, vtkDoubleArray);
+  vtkGetObjectMacro(Gradients, vtkDoubleArray);
+  
+  // Description
+  // Sets/Gets the array of reconstruction points
+  vtkSetObjectMacro(Reconstruction, vtkPoints);
+  vtkGetObjectMacro(Reconstruction, vtkPoints);
+
+  // Set/Get Shift Factor so that S(b)/S(0) can be computed when S(0)=0
+  // ADC = (S(b)+shift)/(S(0)+shift), shift ~= 0
+  vtkSetMacro(Shift,float);
+  vtkGetMacro(Shift,float);
+  
+  // Description:
+  // Set/Get the b-Value
+  vtkSetMacro(bValue,float);
+  vtkGetMacro(bValue,float);
+  
+ protected:
+  float Shift;
+  float bValue;
+  vtkImageData *Baseline;
+  vtkImageData *Mask;
+  vtkDoubleArray *Gradients;
+  vtkPoints *Reconstruction;
+
+  vtkmpjQBallImaging();
+  virtual ~vtkmpjQBallImaging();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+  double Smooth(double x, double sigma);
+  void ComputeReconstructionMatrix(double **a, double **b, double **c, int n, int m, int p);
+  void VectorMultiply(double **A, double *b, double *c, int n, int m);
+
+ private:  
+  vtkmpjQBallImaging(const vtkmpjQBallImaging&); // Not implemented
+  void operator=(const vtkmpjQBallImaging&); // Not implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorBMatrixLeastSquares.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorBMatrixLeastSquares.cpp
new file mode 100644
index 0000000..66ef81a
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorBMatrixLeastSquares.cpp
@@ -0,0 +1,295 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjTensorBMatrixLeastSquares.h"
+#include "vtkMath.h"
+#include "math.h"
+
+
+//------------------------------------------------------------------------------
+vtkmpjTensorBMatrixLeastSquares* vtkmpjTensorBMatrixLeastSquares::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjTensorBMatrixLeastSquares");
+  if(ret)
+    {
+      return (vtkmpjTensorBMatrixLeastSquares*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjTensorBMatrixLeastSquares;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjTensorBMatrixLeastSquares::vtkmpjTensorBMatrixLeastSquares()
+{
+  this->Baseline = NULL;
+  this->Mask = NULL;
+  this->Gradients = NULL;
+  this->Shift = 0.0;
+  this->bValues = NULL;
+  this->NumberOfDirections = 6;
+  this->NumberOfbValues = 7;
+  this->SymmetricTensor = 0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjTensorBMatrixLeastSquares::~vtkmpjTensorBMatrixLeastSquares()
+{
+  if (this->Baseline != NULL)
+    this->Baseline->Delete();
+  if (this->Mask != NULL)
+    this->Mask->Delete();  
+  if (this->Gradients != NULL)
+    this->Gradients->Delete();
+  if (this->bValues != NULL)
+    this->bValues->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjTensorBMatrixLeastSquares::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  if (this->Baseline == NULL) {
+    vtkErrorMacro(<<"No baseline (S0) image specified!");
+    return;
+  }
+  
+  if (this->Gradients == NULL) {
+    vtkErrorMacro(<<"No gradient directions specified!");
+    return;
+  }
+  
+  int gnc = this->Gradients->GetNumberOfComponents();
+  int gnt = this->Gradients->GetNumberOfTuples();
+  int bnt = this->bValues->GetNumberOfTuples();
+
+  if (gnc < 3) {
+    vtkErrorMacro(<<"There should be exactly 3 (gx,gy,gz) components for each gradient direction!");
+    return;
+  }
+  
+  if (bnt < 7) {
+    vtkErrorMacro(<<"There should be at least 7 b-values (one b==0 + six b>0" );
+    return;
+  }
+
+  int dim[3];  input->GetDimensions(dim);
+  int nc = input->GetNumberOfScalarComponents();
+
+  if (this->SymmetricTensor) {
+    output->SetNumberOfScalarComponents(6);
+  } else {
+    output->SetNumberOfScalarComponents(9);
+  }
+
+  if (nc != bnt) {
+    vtkErrorMacro(<<"Number of DWs is not enough");
+    return;
+  }
+  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjTensorBMatrixLeastSquares::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+  
+  int dim[3];  input->GetDimensions(dim);
+    vtkDataArray* out=output->GetPointData()->GetScalars();
+    
+  vtkDataArray* baseline=NULL;
+  vtkDataArray* mask=NULL;
+    
+  if (this->Baseline != NULL) 
+    baseline = this->Baseline->GetPointData()->GetScalars();
+  
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+
+  int nc = input->GetNumberOfScalarComponents();
+  
+  /* compute B Matrix */
+  double** B = new double* [nc];
+  
+  int k = 0;
+  
+  for (int i=0; i<this->NumberOfbValues; i++) {
+    
+    // single b-value
+    double bvalue = this->bValues->GetComponent(i, 0);
+
+    for (int j = 0; j<this->NumberOfDirections && k<nc; j++) {
+      
+      double gx = this->Gradients->GetComponent(j, 0);
+      double gy = this->Gradients->GetComponent(j, 1);
+      double gz = this->Gradients->GetComponent(j, 2);
+      
+      B[k] = new double[7];
+      B[k][0] = -bvalue * gx*gx;
+      B[k][1] = -bvalue * gy*gy;
+      B[k][2] = -bvalue * gz*gz;
+      B[k][3] = -2.0 * bvalue * gx*gy;
+      B[k][4] = -2.0 * bvalue * gx*gz;
+      B[k][5] = -2.0 * bvalue * gy*gz;
+      B[k][6] = 1.0;
+    
+      k++;
+
+      if (bvalue == 0)
+	break;
+
+    }
+
+  }
+
+  if (k != nc)
+    printf("Oops! something is wrong with the B Matrix!\n" );
+  
+  /* allocate space for Nx1 vector x */
+  double **x = new double* [nc];
+  for (int i=0; i<nc; i++) {
+    x[i] = new double[1];
+  }
+  
+  /* allocate memory for tensor */
+  double **t = new double* [7];
+  for (int i=0; i<7; i++) {
+    t[i] = new double[1];  
+  
+  }
+
+  int inmask;
+  int index=0;
+
+  for (int k=0;k<dim[2];k++) {    
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  float baseln;
+	  
+	  //	  baseln = float(baseline->GetComponent(index, 0)) + this->Shift;
+	  inmask = (mask != NULL)?(mask->GetComponent(index, 0) > 0) : 1;
+	  
+	  if (inmask) {
+	    
+	    int abort = 0;	    	 
+
+	    // Calculate ln(Si), 1<=i<=N
+	    for(int n=0; n<nc; n++) {
+	      
+	      float value = float(in->GetComponent(index, n)) + this->Shift;
+	      abort = (value <= 0);
+	      x[n][0] = log(value);
+
+	    }
+
+	    if (abort == 0) {
+	      
+	      // Solve system of equations by least-squares	      
+	      (void) vtkMath::SolveLeastSquares(nc,B,7,x,1,t);
+	      
+	      float Dxx = t[0][0];
+	      float Dyy = t[1][0];
+	      float Dzz = t[2][0];
+	      float Dxy = t[3][0];
+	      float Dxz = t[4][0];
+	      float Dyz = t[5][0]; 
+              float lnS0 = t[6][0];
+	      	      	      	      	    
+	      if (this->SymmetricTensor) {
+		out->SetComponent(index, 0, Dxx);
+		out->SetComponent(index, 1, Dxy);
+		out->SetComponent(index, 2, Dxz);
+		out->SetComponent(index, 3, Dyy);
+		out->SetComponent(index, 4, Dyz);
+		out->SetComponent(index, 5, Dzz);
+	      } else {
+		out->SetComponent(index, 0, Dxx);
+		out->SetComponent(index, 1, Dxy);
+		out->SetComponent(index, 2, Dxz);
+		out->SetComponent(index, 3, Dxy);
+		out->SetComponent(index, 4, Dyy);
+		out->SetComponent(index, 5, Dyz);
+		out->SetComponent(index, 6, Dxz);
+		out->SetComponent(index, 7, Dyz);
+		out->SetComponent(index, 8, Dzz);
+	      }
+	      
+	    } else {
+	      for(int z=0;z<(this->SymmetricTensor?6:9);z++) 
+		out->SetComponent(index, z, (float)0);
+	      
+	    }
+	    
+	  } else {
+	    
+	    for(int z=0;z<(this->SymmetricTensor?6:9);z++) 
+	      out->SetComponent(index, z, (float)0);
+	  }	  
+	  
+	  ++index;	  
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+
+  // free storage
+  delete[] B;
+  delete[] x;  
+  delete[] t;
+  
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorBMatrixLeastSquares.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorBMatrixLeastSquares.h
new file mode 100644
index 0000000..d86ac66
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorBMatrixLeastSquares.h
@@ -0,0 +1,139 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjTensorBMatrixLeastSquares.h 
+   
+      Marcel Jackowski, 2007
+
+      Given N total measurements, M for b > 0 and M-N for b == 0
+      fits a tensor using least squares.
+
+      x = B * d
+
+      x = [ ln(S1) ln(S2) ... ln (SN) ]' 
+      B = [ [ -bxx1 -byy1 -bzz1 -2bxy1 -2bxz1 -2byz1 1 ] ...
+            [ -bxx2 -byy2 -bzz2 -2bxy2 -2bxz2 -2byz2 1 ] ...
+                               ....
+            [ -bxxN -byyN -bzzN -2bxyN -2bxzN -2byzN 1 ] ]
+
+      d = [ Dxx Dyy Dzz Dxy Dxz Dyz ln(S0) ]' 
+ 
+      It expects an vtkImageData structure containing
+      N DWIs. There should also be a b-value associated with
+      every DWI.
+      
+      The symmetric tensor component information is stored in 6 
+      different frames. The frames contain the elements
+      Dxx, Dxy, Dxz, Dyy, Dyz and  Dzz, respectively.
+      
+*/
+
+#ifndef __vtkmpjTensorBMatrixLeastSquares_h
+#define __vtkmpjTensorBMatrixLeastSquares_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkDoubleArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjTensorBMatrixLeastSquares : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjTensorBMatrixLeastSquares *New();
+  vtkTypeMacro(vtkmpjTensorBMatrixLeastSquares,vtkpxSimpleImageToImageFilter);
+  
+  // Sets/Gets the baseline image A(b=0); the echo amplitude without any
+  // diffusion attenuation
+  vtkSetObjectMacro(Baseline, vtkImageData);
+  vtkGetObjectMacro(Baseline, vtkImageData);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents of tensor
+  // computation. If a mask is not provided, tensor is
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Sets/Gets the array of gradient directions
+  vtkSetObjectMacro(Gradients, vtkDoubleArray);
+  vtkGetObjectMacro(Gradients, vtkDoubleArray);
+
+  // Description:
+  // Set/Get the number of directions
+  vtkSetMacro(NumberOfDirections,int);
+  vtkGetMacro(NumberOfDirections,int);
+
+  // Description:
+  // Set/Get Shift Factor so that S(b)/S(0) can be computed when S(0)=0
+  // ADC = (S(b)+shift)/(S(0)+shift), shift ~= 0
+  vtkSetMacro(Shift,float);
+  vtkGetMacro(Shift,float);
+  
+  // Description:
+  // Set/Get the b-Value list
+  vtkSetObjectMacro(bValues,vtkDoubleArray);
+  vtkGetObjectMacro(bValues,vtkDoubleArray);
+  
+  // Description
+  // Set/Get the number of b-values
+  vtkSetMacro(NumberOfbValues,int);
+  vtkGetMacro(NumberOfbValues,int);
+
+  // Description: turn on/off symmetric tensor flag
+  vtkGetMacro(SymmetricTensor, int);
+  vtkSetClampMacro(SymmetricTensor, int, 0, 1);
+  vtkBooleanMacro(SymmetricTensor, int);
+
+ protected:
+  float Shift;
+  int NumberOfDirections;
+  int NumberOfbValues;
+  int SymmetricTensor;
+  vtkImageData *Baseline;
+  vtkImageData *Mask;
+  vtkDoubleArray *Gradients;
+  vtkDoubleArray *bValues;
+
+  vtkmpjTensorBMatrixLeastSquares();
+  virtual ~vtkmpjTensorBMatrixLeastSquares();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  
+  vtkmpjTensorBMatrixLeastSquares(const vtkmpjTensorBMatrixLeastSquares&); // Not implemented
+  void operator=(const vtkmpjTensorBMatrixLeastSquares&); // Not implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorGeometryMetrics.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorGeometryMetrics.cpp
new file mode 100644
index 0000000..f9ce0db
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorGeometryMetrics.cpp
@@ -0,0 +1,169 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjTensorGeometryMetrics.h"
+#include "vtkMath.h"
+#include "math.h"
+
+//------------------------------------------------------------------------------
+vtkmpjTensorGeometryMetrics* vtkmpjTensorGeometryMetrics::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjTensorGeometryMetrics");
+  if(ret)
+    {
+      return (vtkmpjTensorGeometryMetrics*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjTensorGeometryMetrics;
+}
+
+// Construct object with no children.
+vtkmpjTensorGeometryMetrics::vtkmpjTensorGeometryMetrics()
+{
+  this->Mask = NULL;
+  this->Operation = VTK_MPJ_TENSOR_GEOM_ALL;
+  this->MaskOutValue = 0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjTensorGeometryMetrics::~vtkmpjTensorGeometryMetrics()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjTensorGeometryMetrics::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+  
+  if (nc < 3) {
+    vtkErrorMacro(<< "Three eigenvalues per voxel are required as input!");
+    return;
+  }
+  
+  if (this->Operation == VTK_MPJ_TENSOR_GEOM_ALL) 
+    output->SetNumberOfScalarComponents(3);
+  else output->SetNumberOfScalarComponents(1);
+  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjTensorGeometryMetrics::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+ 
+  int dim[3];  input->GetDimensions(dim);
+  int op = this->GetOperation();
+  
+  vtkDataArray* out=output->GetPointData()->GetScalars();
+  vtkDataArray* mask =NULL;
+  
+  if (this->Mask != NULL)
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  int index=0;
+  
+  for (int k=0;k<dim[2];k++) {
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{	
+	
+	  float l1 = in->GetComponent(index, 0);
+	  float l2 = in->GetComponent(index, 1);
+	  float l3 = in->GetComponent(index, 2);
+	  float TR = l1 + l2 + l3;
+	  float L, P, S;
+	  int output=1;
+	  
+	  output = (mask != NULL)?(mask->GetComponent(index, 0) > 0):1;
+	  if (output)
+	    {
+	      L = (l1 - l2) / TR;
+	      P = (2.0 * (l2 - l3)) / TR;
+	      S = (3.0 * l3) / TR;
+	    } else {
+	      L = P = S = this->MaskOutValue;	      
+	    }
+	  
+	  // Invariant information
+	  switch(op) 
+	    {
+	    case VTK_MPJ_TENSOR_GEOM_L:
+	      out->SetComponent(index, 0, L);	   
+	      break;
+	    case VTK_MPJ_TENSOR_GEOM_P:
+	      out->SetComponent(index, 0, P);
+	      break;
+	    case VTK_MPJ_TENSOR_GEOM_S:
+	      out->SetComponent(index, 0, S);
+	      break;
+	    default:
+	      out->SetComponent(index, 0, L);     /* linear diffusion */
+	      out->SetComponent(index, 1, P);     /* planar diffusion */
+	      out->SetComponent(index, 2, S);     /* spherical diffusion */
+	    };
+	  
+	  ++index;	  
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorGeometryMetrics.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorGeometryMetrics.h
new file mode 100644
index 0000000..cd295d6
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorGeometryMetrics.h
@@ -0,0 +1,99 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjTensorGeometryMetrics.h 
+   
+   Description: Computes geometrical measures of diffusion (Westin '97).
+
+   Marcel Jackowski, February 2003
+
+*/
+
+#ifndef __vtkmpjTensorGeometryMetrics_h
+#define __vtkmpjTensorGeometryMetrics_h
+
+// Invariant options
+#define VTK_MPJ_TENSOR_GEOM_ALL 0    
+#define VTK_MPJ_TENSOR_GEOM_L   1
+#define VTK_MPJ_TENSOR_GEOM_P   2
+#define VTK_MPJ_TENSOR_GEOM_S   3
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjTensorGeometryMetrics : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjTensorGeometryMetrics *New();
+  vtkTypeMacro(vtkmpjTensorGeometryMetrics,vtkpxSimpleImageToImageFilter);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents for invariants
+  // computation. If a mask is not provided, invariants are
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Set/Get the Operation to perform.
+  vtkSetMacro(Operation,int);
+  vtkGetMacro(Operation,int);
+
+  void SetOperationToLinear() {this->SetOperation(VTK_MPJ_TENSOR_GEOM_L);};
+  void SetOperationToPlanar() {this->SetOperation(VTK_MPJ_TENSOR_GEOM_P);};
+  void SetOperationToSpherical() {this->SetOperation(VTK_MPJ_TENSOR_GEOM_S);};
+  void SetOperationToDefault() {this->SetOperation(VTK_MPJ_TENSOR_GEOM_ALL);};
+
+  // Description:
+  // Set/Get the value for results falling outside the mask
+  vtkSetMacro(MaskOutValue,float);
+  vtkGetMacro(MaskOutValue,float);
+  
+protected:
+  int Operation;  /* Invariant to be computed */
+  float MaskOutValue; 
+  vtkImageData *Mask;
+  
+ vtkmpjTensorGeometryMetrics();
+  virtual ~vtkmpjTensorGeometryMetrics();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+ vtkmpjTensorGeometryMetrics(const vtkmpjTensorGeometryMetrics&); // Not implemented
+  void operator=(const vtkmpjTensorGeometryMetrics&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorLeastSquares.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorLeastSquares.cpp
new file mode 100644
index 0000000..79966da
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorLeastSquares.cpp
@@ -0,0 +1,295 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjTensorLeastSquares.h"
+#include "vtkMath.h"
+#include "math.h"
+
+
+//------------------------------------------------------------------------------
+vtkmpjTensorLeastSquares* vtkmpjTensorLeastSquares::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjTensorLeastSquares");
+  if(ret)
+    {
+      return (vtkmpjTensorLeastSquares*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjTensorLeastSquares;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjTensorLeastSquares::vtkmpjTensorLeastSquares()
+{
+  this->Baseline = NULL;
+  this->Mask = NULL;
+  this->Gradients = NULL;
+  this->Shift = 0.0;
+  this->bValue = 1.0;
+  this->NumberOfDirections = 6;
+  this->SymmetricTensor = 0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjTensorLeastSquares::~vtkmpjTensorLeastSquares()
+{
+  if (this->Baseline != NULL)
+    this->Baseline->Delete();
+  if (this->Mask != NULL)
+    this->Mask->Delete();  
+  if (this->Gradients != NULL)
+    this->Gradients->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjTensorLeastSquares::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  if (this->Baseline == NULL) {
+    vtkErrorMacro(<<"No baseline (S0) image specified!");
+    return;
+  }
+  
+  if (this->Gradients == NULL) {
+    vtkErrorMacro(<<"No gradient directions specified!");
+    return;
+  }
+  
+  int gnc = this->Gradients->GetNumberOfComponents();
+  int gnt = this->Gradients->GetNumberOfTuples();
+
+  if (gnc < 3) {
+    vtkErrorMacro(<<"There should be exactly 3 (gx,gy,gz) components for each gradient direction!");
+    return;
+  }
+  
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+    
+  if (nc < 6) {
+    vtkErrorMacro(<<"There should be at least 6 diffusion-weighted images in the dataset!");
+    return;
+  }
+  
+  if (gnt != nc) {
+    vtkErrorMacro(<<"There should be exactly the same number of DWs (" <<nc<<") as the number of gradient directions ("<<gnt<<") !");
+    return;
+  }
+  
+  if (this->SymmetricTensor) {
+    output->SetNumberOfScalarComponents(6);
+  } else {
+    output->SetNumberOfScalarComponents(9);
+  }
+  output->SetScalarType(VTK_FLOAT);
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjTensorLeastSquares::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+  
+  int dim[3];  input->GetDimensions(dim);
+    vtkDataArray* out=output->GetPointData()->GetScalars();
+    
+  vtkDataArray* baseline=NULL;
+  vtkDataArray* mask=NULL;
+    
+  if (this->Baseline != NULL) 
+    baseline = this->Baseline->GetPointData()->GetScalars();
+  
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  /* compute gradient matrix */
+  double** alpha = new double* [this->NumberOfDirections];
+  for (int i=0; i<this->NumberOfDirections; i++) {
+    double gx = this->Gradients->GetComponent(i, 0);
+    double gy = this->Gradients->GetComponent(i, 1);
+    double gz = this->Gradients->GetComponent(i, 2);
+    alpha[i] = new double[6];
+    alpha[i][0] = gx*gx;
+    alpha[i][1] = gy*gy;
+    alpha[i][2] = gz*gz;
+    alpha[i][3] = 2*gx*gy;
+    alpha[i][4] = 2*gx*gz;
+    alpha[i][5] = 2*gy*gz;
+  }
+  
+  /* allocate space for adc components */
+  double **adc = new double* [this->NumberOfDirections];
+  for (int i=0; i<this->NumberOfDirections; i++) {
+    adc[i] = new double[1];    
+  }
+  
+  /* allocate memory for tensor */
+  double **t = new double* [6];
+  for (int i=0; i<6; i++) {
+    t[i] = new double[1];    
+  }
+
+  int nc = output->GetNumberOfScalarComponents();
+
+  int inmask;
+  int index=0;
+
+  for (int k=0;k<dim[2];k++) {    
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  float baseln;
+	  
+	  baseln = float(baseline->GetComponent(index, 0)) + this->Shift;
+	  inmask = (mask != NULL)?(mask->GetComponent(index, 0) > 0) : 1;
+	  
+	  if (inmask) {
+	    
+	    int abort = 0;	    	 
+
+	    // Calculate ADCs
+	    for(int n=0; n<this->NumberOfDirections && !abort; n++) {
+	      
+	      float value = float(in->GetComponent(index, n)) + this->Shift;
+	      abort = (value <= 0);
+	      adc[n][0] = log(baseln / value) / this->bValue; 
+	      //printf("%f ",adc[n][0]);	     
+	    }
+
+	    /*	    if (k==19 && ((i==58)||(i==75)) && ((j==58)||(j==75))) {
+		    float *p = input->GetPoint(index);
+		    printf("[%f, %f, %f]:",p[0],p[1],p[2]);
+		    for(int n=0; n<this->NumberOfDirections; n++) {
+		    printf("%f ",adc[n][0]);
+		    }
+		    printf("\n");
+		    }*/
+
+	    //printf("\n");
+
+	    if (abort == 0) {
+	      
+	      // Solve system of equations by least-squares	      
+	      (void) vtkMath::SolveLeastSquares(this->NumberOfDirections,alpha,6,adc,1,t);
+	      
+	      float Dxx = t[0][0];
+	      float Dyy = t[1][0];
+	      float Dzz = t[2][0];
+	      float Dxy = t[3][0];
+	      float Dxz = t[4][0];
+	      float Dyz = t[5][0]; 
+	      	      	      	      	    
+	      /*if ((k==21) && (i==120) && (j==132)) {
+ 		printf("==========\n");
+	 	printf("%f %f %f\n",Dxx,Dxy,Dxz);
+		printf("%f %f %f\n",Dxy,Dyy,Dyz);
+		printf("%f %f %f\n",Dxz,Dyz,Dzz);
+		printf("==========\n");
+		}	*/    
+	      
+	      if (this->SymmetricTensor) {
+		out->SetComponent(index, 0, Dxx);
+		out->SetComponent(index, 1, Dxy);
+		out->SetComponent(index, 2, Dxz);
+		out->SetComponent(index, 3, Dyy);
+		out->SetComponent(index, 4, Dyz);
+		out->SetComponent(index, 5, Dzz);
+	      } else {
+		out->SetComponent(index, 0, Dxx);
+		out->SetComponent(index, 1, Dxy);
+		out->SetComponent(index, 2, Dxz);
+		out->SetComponent(index, 3, Dxy);
+		out->SetComponent(index, 4, Dyy);
+		out->SetComponent(index, 5, Dyz);
+		out->SetComponent(index, 6, Dxz);
+		out->SetComponent(index, 7, Dyz);
+		out->SetComponent(index, 8, Dzz);
+	      }
+	      
+	    } else {
+	      for(int z=0;z<nc;z++) 
+		out->SetComponent(index, z, (float)0);
+	      
+	    }
+	    
+	  } else {
+	    
+	    for(int z=0;z<nc;z++) 
+	      out->SetComponent(index, z, (float)0);
+	  }	  
+	  
+	  ++index;	  
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+
+  // free storage
+  //for (int i=0; i<this->NumberOfDirections; i++) {
+  //delete[] alpha[i];
+  // delete[] adc[i];
+  //}
+
+  delete[] alpha;
+  delete[] adc;
+  
+  //for (int i=0; i<6; i++) {
+  // delete[] t[i];
+  //}
+  
+  delete[] t;
+  
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorLeastSquares.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorLeastSquares.h
new file mode 100644
index 0000000..abcbfe5
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorLeastSquares.h
@@ -0,0 +1,131 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjTensorLeastSquares.h 
+   
+      Marcel Jackowski, 2002
+
+      Fits a tensor from N given directions (DWIs), using the least
+      squares formulation. 
+      
+      A * X = ADC
+
+      where ADC_i = Si(0)/S(b) and
+      A_i = [gx_i^2 gy_i^2 gz_i^2 2*gxgy_i 2*gxgz_i 2*gygz_i]
+
+      size(A) = 6 x N
+      size(X) = 1 x 6
+      size(ADC) = N x 1
+
+      It expects an vtkImageData structure containing
+      DWIs acquired in the N different directions. 
+      
+      The symmetric tensor component information is stored in 6 
+      different frames. The frames contain the elements
+      Dxx, Dxy, Dxz, Dyy, Dyz and  Dzz, respectively.
+      
+*/
+
+#ifndef __vtkmpjTensorLeastSquares_h
+#define __vtkmpjTensorLeastSquares_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkDoubleArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjTensorLeastSquares : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjTensorLeastSquares *New();
+  vtkTypeMacro(vtkmpjTensorLeastSquares,vtkpxSimpleImageToImageFilter);
+  
+  // Sets/Gets the baseline image A(b=0); the echo amplitude without any
+  // diffusion attenuation
+  vtkSetObjectMacro(Baseline, vtkImageData);
+  vtkGetObjectMacro(Baseline, vtkImageData);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents of tensor
+  // computation. If a mask is not provided, tensor is
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Sets/Gets the array of gradient directions
+  vtkSetObjectMacro(Gradients, vtkDoubleArray);
+  vtkGetObjectMacro(Gradients, vtkDoubleArray);
+
+  // Description:
+  // Set/Get Shift Factor so that S(b)/S(0) can be computed when S(0)=0
+  // ADC = (S(b)+shift)/(S(0)+shift), shift ~= 0
+  vtkSetMacro(Shift,float);
+  vtkGetMacro(Shift,float);
+  
+  // Description:
+  // Set/Get the b-Value
+  vtkSetMacro(bValue,float);
+  vtkGetMacro(bValue,float);
+  
+  // Description:
+  // Set/Get the b-Value
+  vtkSetMacro(NumberOfDirections,int);
+  vtkGetMacro(NumberOfDirections,int);
+
+  // Description: turn on/off symmetric tensor flag
+  vtkGetMacro(SymmetricTensor, int);
+  vtkSetClampMacro(SymmetricTensor, int, 0, 1);
+  vtkBooleanMacro(SymmetricTensor, int);
+
+ protected:
+  float Shift;
+  float bValue;
+  int NumberOfDirections;
+  int SymmetricTensor;
+  vtkImageData *Baseline;
+  vtkImageData *Mask;
+  vtkDoubleArray *Gradients;
+
+  vtkmpjTensorLeastSquares();
+  virtual ~vtkmpjTensorLeastSquares();
+
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  
+  vtkmpjTensorLeastSquares(const vtkmpjTensorLeastSquares&); // Not implemented
+  void operator=(const vtkmpjTensorLeastSquares&); // Not implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorToApparentDiffusion.cpp b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorToApparentDiffusion.cpp
new file mode 100644
index 0000000..bc56e22
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorToApparentDiffusion.cpp
@@ -0,0 +1,324 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkObjectFactory.h"
+#include "vtkmpjTensorToApparentDiffusion.h"
+#include "vtkMath.h"
+#include "math.h"
+
+
+//------------------------------------------------------------------------------
+vtkmpjTensorToApparentDiffusion* vtkmpjTensorToApparentDiffusion::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjTensorToApparentDiffusion");
+  if(ret)
+    {
+      return (vtkmpjTensorToApparentDiffusion*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjTensorToApparentDiffusion;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjTensorToApparentDiffusion::vtkmpjTensorToApparentDiffusion()
+{
+  this->Baseline = NULL;
+  this->Mask = NULL;
+  this->Gradients = NULL;
+  this->Shift = 0.0;
+  this->bValue = 1.0;
+  this->NumberOfDirections = 6;
+  this->SymmetricTensor = 0;
+  this->BaselineValue = 10;
+  this->AddNoise = 0;
+  this->NoiseLevel = 0.1;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjTensorToApparentDiffusion::~vtkmpjTensorToApparentDiffusion()
+{
+  if (this->Baseline != NULL)
+    this->Baseline->Delete();
+  if (this->Mask != NULL)
+    this->Mask->Delete();  
+  if (this->Gradients != NULL)
+    this->Gradients->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjTensorToApparentDiffusion::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  if (this->Gradients == NULL) {
+    vtkErrorMacro(<<"No gradient directions specified!");
+    return;
+  }
+  
+  int gnc = this->Gradients->GetNumberOfComponents();
+  int gnt = this->Gradients->GetNumberOfTuples();
+
+  if (gnc < 3) {
+    vtkErrorMacro(<<"There should be exactly 3 (gx,gy,gz) components for each gradient direction!");
+    return;
+  }
+  
+  int dim[3];  input->GetDimensions(dim);
+  int nc=input->GetNumberOfScalarComponents();
+    
+  if (nc < 6) {
+    vtkErrorMacro(<<"There should be at least 6 elements in the dataset!");
+    return;
+  }
+  
+  output->SetNumberOfScalarComponents(gnt + 1);
+  output->SetScalarType(VTK_FLOAT);
+  output->SetDimensions(dim[0],dim[1],dim[2]);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+float vtkmpjTensorToApparentDiffusion::GaussianDeviate()
+{
+  static int iset=0;
+  static float gset;
+  float fac,rsq,v1,v2;
+
+  if  (iset == 0) 
+    {
+      do 
+	{
+	  v1=2.0*vtkMath::Random()-1.0;
+	  v2=2.0*vtkMath::Random()-1.0;
+	  rsq=v1*v1+v2*v2;
+	} 
+      while (rsq >= 1.0 || rsq == 0.0);
+      
+      fac=sqrt(-2.0*log(rsq)/rsq);
+      gset=v1*fac;
+      iset=1;
+      return v2*fac;
+    } 
+  else
+    {
+      iset=0;
+      return gset;
+    }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjTensorToApparentDiffusion::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  vtkDataArray* in =input->GetPointData()->GetScalars();
+  
+  int dim[3];  input->GetDimensions(dim);
+    vtkDataArray* out=output->GetPointData()->GetScalars();
+    
+  vtkDataArray* baseline=NULL;
+  vtkDataArray* mask=NULL;
+    
+  if (this->Baseline != NULL) 
+    baseline = this->Baseline->GetPointData()->GetScalars();
+  
+  if (this->Mask != NULL) 
+    mask = this->Mask->GetPointData()->GetScalars();
+  
+  /* compute gradient matrix */
+  double** alpha = new double* [this->NumberOfDirections];
+  for (int i=0; i<this->NumberOfDirections; i++) {
+    double gx = this->Gradients->GetComponent(i, 0);
+    double gy = this->Gradients->GetComponent(i, 1);
+    double gz = this->Gradients->GetComponent(i, 2);
+    alpha[i] = new double[6];
+    alpha[i][0] = gx*gx;
+    alpha[i][1] = gy*gy;
+    alpha[i][2] = gz*gz;
+    alpha[i][3] = 2*gx*gy;
+    alpha[i][4] = 2*gx*gz;
+    alpha[i][5] = 2*gy*gz;
+  }
+  
+  /* allocate space for adc components */
+  double **adc = new double* [this->NumberOfDirections];
+  for (int i=0; i<this->NumberOfDirections; i++) {
+    adc[i] = new double[1];    
+  }
+  
+  /* allocate memory for tensor */
+  double **t = new double* [6];
+  for (int i=0; i<6; i++) {
+    t[i] = new double[1];    
+  }
+
+  int nc = output->GetNumberOfScalarComponents();
+
+  int index=0;
+
+  for (int k=0;k<dim[2];k++) {    
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  int inmask = 1;
+	  float baseln;
+	  float noise = 0.0;
+
+	  // read in tensor
+	  if (this->SymmetricTensor) {
+	    t[0][0] = in->GetComponent(index, 0); /* xx */
+	    t[1][0] = in->GetComponent(index, 3); /* yy */
+	    t[2][0] = in->GetComponent(index, 5); /* zz */
+	    t[3][0] = in->GetComponent(index, 1); /* xy */
+	    t[4][0] = in->GetComponent(index, 2); /* xz */
+	    t[5][0] = in->GetComponent(index, 4); /* yz */
+	  } else {
+	    t[0][0] = in->GetComponent(index, 0); /* xx */
+	    t[1][0] = in->GetComponent(index, 4); /* yy */
+	    t[2][0] = in->GetComponent(index, 8); /* zz */
+	    t[3][0] = in->GetComponent(index, 1); /* xy */
+	    t[4][0] = in->GetComponent(index, 2); /* xz */
+	    t[5][0] = in->GetComponent(index, 5); /* yz */
+	  }
+	  
+	  baseln = (baseline != NULL) ? 
+	    (baseline->GetComponent(index, 0) + this->Shift) : this->BaselineValue;
+
+	  inmask = (mask != NULL)?(mask->GetComponent(index, 0) > 0) : 1;
+
+	  // write out baseline image
+	  if (this->AddNoise) 
+	    noise = this->NoiseLevel * this->GaussianDeviate(); 
+	  else noise = 0;
+	  
+	  if (inmask)
+	    baseln = 1+noise;
+	  else baseln = 0+fabs(noise);
+
+	  out->SetComponent(index, 0, 1.0);
+
+	  float total = 0;
+
+	  //if (output) {
+	    
+	    float sum; 
+
+	    // calculate ADCs
+	    for(int n=0; n<this->NumberOfDirections; n++) {
+	      
+	      // write out ADCs
+	      if (this->AddNoise) {
+	      	noise = this->NoiseLevel * this->GaussianDeviate();
+	      }	else noise = 0.0;
+
+	      sum = 0.0;
+	      for(int m=0; m<6; m++) 
+		sum += alpha[n][m] * t[m][0];// * (noise);
+	      	   	      
+	      //adc[n][0] = baseln * exp(-(sum + noise));
+	      adc[n][0] = baseln * exp(-sum); // + noise);
+
+	      //printf("%f ",adc[n][0]);
+	      
+	      //out->SetComponent(index, n+1, adc[n][0] + noise*adc[n][0]);
+	      //printf("%f ", exp(sum));
+	      out->SetComponent(index, n+1, adc[n][0]);
+	    }
+	    	    
+	    // printf("\n*");
+
+	    //printf("\n");
+
+	    // calculate baseline
+	    //baseln = total / (float)this->NumberOfDirections;
+	    
+	    //printf("baseln=%f \n",baseln);
+	    
+	    // write out baseline image
+	    //if (this->AddNoise) 
+	    //noise = this->NoiseLevel * this->GaussianDeviate(); 
+	    //else noise = 0;
+	    
+	    //out->SetComponent(index, 0, baseln + noise*baseln);
+	    
+	    // write out normalized ADCs
+	    //for(int n=0; n<this->NumberOfDirections; n++) 
+	    //out->SetComponent(index, n+1, out->GetComponent(index, n+1)*baseln);
+	    
+	    // } else {
+	    
+	    //for(int m=0; m<=this->NumberOfDirections; m++) 
+	    //out->SetComponent(index, m, (float)0);	    
+	    
+	    //}
+		  
+	  ++index;	  
+	}
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+  
+  this->UpdateProgress(1.0);
+  
+  // free storage
+  //for (int i=0; i<this->NumberOfDirections; i++) {
+  //delete[] alpha[i];
+  // delete[] adc[i];
+  //}
+  
+  delete[] alpha;
+  delete[] adc;
+  
+  //for (int i=0; i<6; i++) {
+  // delete[] t[i];
+  //}
+  
+  delete[] t;
+  
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorToApparentDiffusion.h b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorToApparentDiffusion.h
new file mode 100644
index 0000000..c555f47
--- /dev/null
+++ b/bioimagesuite30_src/mpjDiffusion/vtkmpjTensorToApparentDiffusion.h
@@ -0,0 +1,142 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* -- vtkmpjTensorToApparentDiffusion.h 
+   
+      Marcel Jackowski, 2002
+
+      Given tensor, and N given gradient directions, determine ADCS:
+
+      A * X = ADC
+
+      where ADC_i = Si(0)/S(b) and
+      A_i = [gx_i^2 gy_i^2 gz_i^2 2*gxgy_i 2*gxgz_i 2*gygz_i]
+
+      size(A) = 6 x N
+      size(X) = 1 x 6
+      size(ADC) = N x 1
+      
+*/
+
+#ifndef __vtkmpjTensorToApparentDiffusion_h
+#define __vtkmpjTensorToApparentDiffusion_h
+
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkDoubleArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+
+class vtkmpjTensorToApparentDiffusion : public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjTensorToApparentDiffusion *New();
+  vtkTypeMacro(vtkmpjTensorToApparentDiffusion,vtkpxSimpleImageToImageFilter);
+  
+  // Sets/Gets the baseline image A(b=0); the echo amplitude without any
+  // diffusion attenuation
+  vtkSetObjectMacro(Baseline, vtkImageData);
+  vtkGetObjectMacro(Baseline, vtkImageData);
+  
+  // Description: 
+  // Sets/Gets mask for determining the extents of tensor
+  // computation. If a mask is not provided, ADCs 
+  // computed for every voxel in the image.
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Sets/Gets the array of gradient directions
+  vtkSetObjectMacro(Gradients, vtkDoubleArray);
+  vtkGetObjectMacro(Gradients, vtkDoubleArray);
+
+  // Description:
+  // Set/Get Shift Factor so that S(b)/S(0) can be computed when S(0)=0
+  // ADC = (S(b)+shift)/(S(0)+shift), shift ~= 0
+  vtkSetMacro(Shift,float);
+  vtkGetMacro(Shift,float);
+  
+  // Description:
+  // Set/Get the b-Value
+  vtkSetMacro(bValue,float);
+  vtkGetMacro(bValue,float);
+  
+  // Description:
+  // Set/Get constant baseline value
+  vtkSetMacro(BaselineValue,float);
+  vtkGetMacro(BaselineValue,float);
+
+  // Description:
+  // Set/Get the b-Value
+  vtkSetMacro(NumberOfDirections,int);
+  vtkGetMacro(NumberOfDirections,int);
+
+  // Description: turn on/off symmetric tensor flag
+  vtkGetMacro(SymmetricTensor, int);
+  vtkSetClampMacro(SymmetricTensor, int, 0, 1);
+  vtkBooleanMacro(SymmetricTensor, int);
+
+  // Description: turn on/off addition of noise
+  vtkGetMacro(AddNoise, int);
+  vtkSetClampMacro(AddNoise, int, 0, 1);
+  vtkBooleanMacro(AddNoise, int);
+
+  // Description:
+  // Set/Get noise level
+  vtkSetMacro(NoiseLevel,float);
+  vtkGetMacro(NoiseLevel,float);
+
+ protected:
+  float Shift;
+  float bValue;
+  float BaselineValue;
+  int NumberOfDirections;
+  int SymmetricTensor;
+  int AddNoise;
+  float NoiseLevel;
+  vtkImageData *Baseline;
+  vtkImageData *Mask;
+  vtkDoubleArray *Gradients;
+
+  vtkmpjTensorToApparentDiffusion();
+  virtual ~vtkmpjTensorToApparentDiffusion();
+
+  float GaussianDeviate();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  void ExecuteInformation();
+
+ private:
+  
+  vtkmpjTensorToApparentDiffusion(const vtkmpjTensorToApparentDiffusion&); // Not implemented
+  void operator=(const vtkmpjTensorToApparentDiffusion&); // Not implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/CMakeLists.txt b/bioimagesuite30_src/mpjLevelset/CMakeLists.txt
new file mode 100644
index 0000000..357ac8e
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/CMakeLists.txt
@@ -0,0 +1,89 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local common classes.
+#
+SET(KIT vtkmpjLevelset)
+
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/Common)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/mpjCommon)
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/mpjLevelset)
+
+SET (KITSRCS
+     vtkmpjExtractLevelSet.cpp
+     vtkmpjFastMarchingMethod.cpp
+     vtkmpjFastMarchingExtension.cpp
+     vtkmpjLevelSetNormal.cpp
+     vtkmpjLevelSetNarrowBandFilter.cpp
+     vtkmpjLevelSetSignedDistance.cpp
+     vtkmpjLevelSetMethod.cpp
+     vtkmpjLevelSetTest.cpp
+     vtkmpjFastSweepingMethod.cpp
+     vtkmpjLaxFriedrichSweepingMethod.cpp
+     vtkmpjImageCharacteristics.cpp
+     vtkmpjLaxFriedrichEuclidean.cpp
+     vtkmpjLaxFriedrichTest.cpp
+     vtkmpjLaxConnectivity.cpp
+     vtkmpjLaxFriedrichSweeping.cpp
+     vtkmpjFastMarchingConnectivity.cpp
+     vtkmpjFastMarchingImageFilter.cpp
+     vtkmpjLevelSetNeighborhoodExtractor.cpp
+     vtkmpjReinitializeLevelSetImageFilter.cpp
+     vtkmpjFastMarchingVesselConnectivity.cpp
+)
+
+SET(KITLIBS
+  vtkpxCommonTCL
+  vtkmpjCommon
+  vtkmpjCommonTCL
+  vtkCommonTCL
+   ${BIOIMAGESUITE3_COMMON_LIBS}
+)
+
+SET(KITJAVALIBS
+  vtkpxCommonJava
+  vtkpxCommon
+  numerics
+   ${BIOIMAGESUITE3_COMMON_JAVALIBS}
+)
+
+# --------------------------------------------------------------------------
+SET (KITEXTRAFILES)
+SET (KITTCLSRCS )
+
+
+bis_complex("mpjLevelset" ${KIT} ${FILELIST})
+
+
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjExtractLevelSet.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjExtractLevelSet.cpp
new file mode 100644
index 0000000..1f46288
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjExtractLevelSet.cpp
@@ -0,0 +1,230 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjExtractLevelSet.h"
+
+vtkStandardNewMacro(vtkmpjExtractLevelSet);
+
+// Construct object with no children.
+vtkmpjExtractLevelSet::vtkmpjExtractLevelSet()
+{
+  this->LevelSetValue = 0.0;
+  this->InValue = -1.0;
+  this->OutValue = 1.0;
+  this->InsidePoints = NULL;
+  this->OutsidePoints = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjExtractLevelSet::~vtkmpjExtractLevelSet()
+{
+  if (this->InsidePoints != NULL) 
+    this->InsidePoints->Delete();
+  if (this->OutsidePoints != NULL) 
+    this->OutsidePoints->Delete();
+}
+
+// ----------------------------------------------------------------------------
+//void vtkmpjExtractLevelSet::ExecuteInformation()
+//{
+//this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+//}
+
+// ----------------------------------------------------------------------------
+void vtkmpjExtractLevelSet::Sort(double values[3]) 
+{
+  double tmp[3];
+  
+  if (values[0] < values[1]) {
+    if (values[0] < values[2]) {
+      if (values[1] < values[2]) {
+	tmp[0] = values[0]; tmp[1] = values[1]; tmp[2] = values[2]; 
+      } else {
+	tmp[0] = values[0]; tmp[1] = values[2]; tmp[2] = values[1]; 
+      }
+    } else 
+      {
+	tmp[0] = values[2]; tmp[1] = values[0]; tmp[2] = values[1];
+      }
+  } else {
+    if (values[1] < values[2]) {
+      if (values[0] < values[2]) {
+	tmp[0] = values[1]; tmp[1] = values[0]; tmp[2] = values[2];
+      } else {
+	tmp[0] = values[1]; tmp[1] = values[2]; tmp[2] = values[0];
+      }
+    } else
+      {
+	tmp[0] = values[2]; tmp[1] = values[1]; tmp[2] = values[0];
+      }    
+  }
+
+  values[0] = tmp[0];
+  values[1] = tmp[1];
+  values[2] = tmp[2];
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjExtractLevelSet::ComputeDistance(vtkImageData *input, int coord[3], int index)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *in = input->GetPointData()->GetScalars();
+  
+  double center = in->GetComponent(index, 0) - this->LevelSetValue;
+  
+  if (center == 0.0) {
+    return 0.0;
+  }
+
+  int neigh_index[3];
+  double neigh_dist[3];
+  double distance = VTK_LARGE_FLOAT;
+  
+  for(int j=0; j<3; j++) {
+    
+    neigh_dist[j] = VTK_LARGE_FLOAT;
+    
+    for(int i=-1; i<2; i+=2) {
+      
+      int neighbor = index + i * factor[j];
+      
+      if (((coord[j]+i) >= 0) && ((coord[j]+i) < dim[j])) {
+	
+	double neigh_val = in->GetComponent(neighbor, 0) - this->LevelSetValue;
+	
+	if (((neigh_val > 0) && (center <= 0.0)) || ((neigh_val < 0) && (center > 0.0))) {
+	  distance = center / (center - neigh_val);
+	}
+	
+	if (neigh_dist[j] > distance) {
+	  neigh_dist[j] = distance;
+	  neigh_index[j] = neighbor;
+	}
+      }
+    }
+  }
+  
+  this->Sort(neigh_dist);
+
+  distance = 0.0;
+  
+  for (int j=0; j<3; j++) { 
+    if (neigh_dist[j] >= VTK_LARGE_FLOAT) 
+      break;
+    distance += 1.0 / neigh_dist[j]*neigh_dist[j];    
+  }
+  
+  if (distance == 0.0) 
+    return VTK_LARGE_FLOAT;
+  
+  distance = sqrt(1.0 / distance);
+  
+  return distance;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjExtractLevelSet::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  vtkDataArray *in = input->GetPointData()->GetScalars();
+  vtkDataArray *out = output->GetPointData()->GetScalars();
+
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int total = in->GetNumberOfTuples();
+  
+  // create array of inside points
+  if (this->InsidePoints != NULL) 
+    this->InsidePoints->Delete();  
+  
+  this->InsidePoints = vtkFloatArray::New(); 
+  this->InsidePoints->SetNumberOfComponents(4);
+  
+  // create array of outside points
+  if (this->OutsidePoints != NULL) 
+    this->OutsidePoints->Delete();  
+  
+  this->OutsidePoints = vtkFloatArray::New(); 
+  this->OutsidePoints->SetNumberOfComponents(4);
+    
+  this->pog = 0.0;
+  this->tenth=(int)(total / 10.0);
+  this->count=0;
+  
+  this->UpdateProgress(0.01);
+  
+  int coord[3];
+  for(int index=0; index<total; index++) {
+    
+    this->count++;
+    if (this->count==this->tenth)
+      {
+	this->pog+=0.1;
+	this->UpdateProgress(this->pog);
+	this->count=0;
+      }
+    
+    // decompose index into point coordinates
+    coord[2] = index / dim0Tdim1; 
+    coord[1] = (index % dim0Tdim1) / dim[0];
+    coord[0] = (index % dim0Tdim1) % dim[0];
+
+    // determine if point is inside or outside the leveset
+    int inside = (in->GetComponent(index, 0) - this->LevelSetValue) <= 0;
+
+    // compute distance to the level set          
+    double dist = ComputeDistance(input, coord, index);
+    
+    // write out distances
+    if (inside) {
+      
+      // write out mask
+      out->SetComponent(index, 0, (float)InValue);
+      
+      if (dist != VTK_LARGE_FLOAT) 
+	this->InsidePoints->InsertNextTuple4((float)coord[0], (float)coord[1], 
+					     (float)coord[2], dist);
+    } else {
+      
+      // write out mask
+      out->SetComponent(index, 0, (float)OutValue);
+      
+      if (dist != VTK_LARGE_FLOAT)
+	this->OutsidePoints->InsertNextTuple4((float)coord[0], (float)coord[1], 
+					      (float)coord[2], dist);
+    }
+  }
+  
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjExtractLevelSet.h b/bioimagesuite30_src/mpjLevelset/vtkmpjExtractLevelSet.h
new file mode 100644
index 0000000..3b55d6a
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjExtractLevelSet.h
@@ -0,0 +1,105 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+   -- vtkmpjExtractLevelSet.h --
+   
+   Extracts a levelset from a phi image.
+
+   Marcel Jackowski, June 2003.
+*/
+
+#ifndef __vtkmpjExtractLevelSet_h
+#define __vtkmpjExtractLevelSet_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjExtractLevelSet : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjExtractLevelSet *New();
+  vtkTypeMacro(vtkmpjExtractLevelSet,vtkpxSimpleImageToImageFilter);
+  
+  // Set/Get the levelset to be extracted
+  vtkGetMacro(LevelSetValue,float);
+  vtkSetMacro(LevelSetValue,float);  
+
+  // Get/Set output value for points inside levelset
+  vtkGetMacro(InValue,float);
+  vtkSetMacro(InValue,float);  
+  
+  // Get/Set output value for points outside levelset
+  vtkGetMacro(OutValue,float);
+  vtkSetMacro(OutValue,float);  
+
+  // Get/Set inside points
+  vtkGetObjectMacro(InsidePoints,vtkFloatArray);
+  vtkSetObjectMacro(InsidePoints,vtkFloatArray);
+
+  // Get/Set outside points
+  vtkGetObjectMacro(OutsidePoints,vtkFloatArray);
+  vtkSetObjectMacro(OutsidePoints,vtkFloatArray);
+
+ protected:
+  float InValue;                // output value for point on/inside levelset
+  float OutValue;               // output value for point outside levelset
+  float LevelSetValue;          // levelset to extract
+  vtkFloatArray *InsidePoints;  // array of points on/immediately inside the levelset
+  vtkFloatArray *OutsidePoints; // array of points immediately outside the levelset 
+  
+  vtkmpjExtractLevelSet();
+  virtual ~vtkmpjExtractLevelSet();
+    
+  // void ExecuteInformation();
+  
+  void Sort(double values[3]);
+  
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  virtual double ComputeDistance(vtkImageData *input, int coord[3], int index);
+  
+ private:
+  //BTX
+  float pog;
+  int count, tenth;  
+  //ETX
+  
+  vtkmpjExtractLevelSet(const vtkmpjExtractLevelSet&);// Not implemented
+  void operator=(const vtkmpjExtractLevelSet&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingConnectivity.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingConnectivity.cpp
new file mode 100644
index 0000000..d2adda4
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingConnectivity.cpp
@@ -0,0 +1,752 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjFastMarchingConnectivity.h"
+
+#define VTK_MPJ_LARGE_FLOAT 32767
+
+//------------------------------------------------------------------------------
+vtkmpjFastMarchingConnectivity* vtkmpjFastMarchingConnectivity::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjFastMarchingConnectivity");
+  if(ret)
+    {
+      return (vtkmpjFastMarchingConnectivity*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjFastMarchingConnectivity;
+}
+
+// Construct object with no children.
+vtkmpjFastMarchingConnectivity::vtkmpjFastMarchingConnectivity()
+{ 
+  this->Mask = NULL;
+  this->KnownPoints = NULL;
+  this->KnownValues = 1;
+  this->LabelImage = NULL;
+  this->FrontPoints = NULL;
+  this->PropagationTime = VTK_MPJ_LARGE_FLOAT;
+  this->Spacing[0] = this->Spacing[1] = this->Spacing[2] = 1.0;
+  this->SymmetricTensor = 1;
+  this->queue = NULL;
+  this->label = NULL;
+  this->Infinity = 32767;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjFastMarchingConnectivity::~vtkmpjFastMarchingConnectivity()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+  if (this->KnownPoints != NULL)
+    this->KnownPoints->Delete();
+  if (this->LabelImage != NULL)
+    this->LabelImage->Delete();
+  if (this->FrontPoints != NULL)
+    this->FrontPoints->Delete();
+  if (this->queue != NULL)    
+    this->queue->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingConnectivity::SetSpeedImage(vtkImageData *speed)
+{
+  this->SetInput(speed);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingConnectivity::ExecuteInformation()
+{
+  vtkImageData *input = this->GetInput();
+  vtkImageData *output = this->GetOutput();
+   
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Speed Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  int dim[3]; input->GetDimensions(dim);
+  
+  if (this->KnownPoints==NULL) {
+    vtkErrorMacro(<<"Set of known points is empty!");
+    return;
+  }
+
+  printf("dims=%d %d %d\n", dim[0],dim[1],dim[2]);
+
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_DOUBLE);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+int vtkmpjFastMarchingConnectivity::InMask(int index)
+{
+  return (this->mask != NULL)?(this->mask->GetComponent(index, 0) > 0) : 1;
+}
+
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingConnectivity::SortTerms(double term[3]) 
+{
+  double tmp[3];
+
+  if (term[0] < term[1]) {
+    if (term[0] < term[2]) {
+      if (term[1] < term[2]) {
+	tmp[0] = term[0]; tmp[1] = term[1]; tmp[2] = term[2]; 
+      } else {
+	tmp[0] = term[0]; tmp[1] = term[2]; tmp[2] = term[1]; 
+      }
+    } else 
+      {
+	tmp[0] = term[2]; tmp[1] = term[0]; tmp[2] = term[1];
+      }
+  } else {
+    if (term[1] < term[2]) {
+      if (term[0] < term[2]) {
+	tmp[0] = term[1]; tmp[1] = term[0]; tmp[2] = term[2];
+      } else {
+	tmp[0] = term[1]; tmp[1] = term[2]; tmp[2] = term[0];
+      }
+    } else
+      {
+	tmp[0] = term[2]; tmp[1] = term[1]; tmp[2] = term[0];
+      }    
+  }
+
+  term[0] = tmp[0];
+  term[1] = tmp[1];
+  term[2] = tmp[2];
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingConnectivity::Solve2(double a, double b, double rhs)
+{  
+  double amb = a - b;
+  if (fabs(amb) >= rhs) {
+    return (a < b ? a : b) + rhs;
+  } else {
+    double amb2 = amb*amb;
+    return (a+b+sqrt(2.0*rhs*rhs-amb2)) / 2.0;
+  }
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingConnectivity::SolveN(int number, double term[3], double rhs)
+{
+  double coeff[3] = {-rhs*rhs, 0.0, 0.0};
+
+  for (int j=0; j<3; j++) {
+    if (term[j] != VTK_MPJ_LARGE_FLOAT) {
+      coeff[2] += 1.0;
+      coeff[1] -= 2*term[j];
+      coeff[0] += term[j]*term[j];
+    }
+  }
+  
+  int no_solutions = 1;
+  double max_sol = VTK_MPJ_LARGE_FLOAT;
+  double sol[2] = {VTK_MPJ_LARGE_FLOAT, VTK_MPJ_LARGE_FLOAT};
+  double discr = coeff[1]*coeff[1] - 4.0*coeff[2]*coeff[0];
+  
+  if (discr < 0) {
+    printf("Solution is not differentiable! terms=%f, %f, %f, coeffs=%f, %f, %f\n", term[0], term[1], term[2], coeff[2], coeff[1], coeff[0]);
+  }
+  
+  // solve quadratic equation
+  vtkMath::SolveQuadratic(coeff[2], coeff[1], coeff[0], 
+			  &sol[0], &sol[1], &no_solutions);
+  if (no_solutions == 2) {
+    max_sol = sol[0]>=sol[1]?sol[0]:sol[1];
+  } else {
+    max_sol = sol[0];
+  }
+  
+  return max_sol;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingConnectivity::SolveQuadratic(int number, double term[3], double rhs)
+{  
+  double result;
+  
+  switch(number) {
+  case 1:
+    result = term[0] + rhs;
+    break;
+  case 2:
+    result = Solve2(term[0], term[1], rhs);
+    break;
+  case 3:
+  default:
+    if ((term[0] + rhs) > term[1]) {
+      result = term[0] + rhs;      
+    } else {
+      result = Solve2(term[0], term[1], rhs);
+    }
+    if (result > term[2])
+      result = SolveN(number, term, rhs);
+    break;
+  };
+      
+  return(result);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingConnectivity::ComputeNormal(vtkImageData *input, vtkImageData *output, 
+					     int coord[3], int index, float result[3])
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  //vtkDataArray *in = input->GetPointData()->GetScalars(); 
+  //vtkDataArray *out = output->GetPointData()->GetScalars();
+  
+  float normal[3];
+  result[0]=normal[0]=0.0;
+  result[1]=normal[1]=0.0;
+  result[2]=normal[2]=0.0;
+  
+  // process each one of the 26 neighbors
+  //int count = 0;
+  for(int i=-1;i<2;i++)
+    for(int j=-1;j<2;j++)
+      for(int k=-1;k<2;k++) {
+	if ((coord[0]+i)>=0 && ((coord[0]+i)<dim[0]) &&
+	    (coord[1]+j)>=0 && ((coord[1]+j)<dim[1]) &&
+	    (coord[2]+k)>=0 && ((coord[2]+k)<dim[2]))
+	  {	  	    
+	    int neighbor=index + i*factor[0] + j*factor[1] + k*factor[2];
+	    if (this->InMask(neighbor) && this->label->GetComponent(neighbor, 0) == VTK_MPJ_FROZEN) {
+	      normal[0]+=i; normal[1]+=j; normal[2]+=k;	      
+	    }
+	  }	
+      }
+  
+  result[0]=normal[0];
+  result[1]=normal[1];
+  result[2]=normal[2];
+  
+  (void) vtkMath::Normalize(result);  
+
+  //printf("normal at %d is [%f,%f,%f], [%f,%f,%f]\n",index,result[0],result[1],result[2],normal[0],normal[1],normal[2]);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingConnectivity::Jacobi3x3(float a[3][3], float w[3], float v[3][3])
+{
+  float **aa = new float *[3]; /* allocate space for tensor matrix */
+  aa[0] = new float[3];
+  aa[1] = new float[3];
+  aa[2] = new float[3];
+   
+  float **vv = new float *[3]; /* allocate space for eigenvector matrix */
+  vv[0] = new float[3];
+  vv[1] = new float[3];
+  vv[2] = new float[3];
+  
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++) 
+      aa[i][j] = a[i][j];
+
+  // call the real method
+  (void) vtkMath::Jacobi(aa,w,vv);
+
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++) 
+      v[i][j] = vv[i][j];
+
+  // free aa
+  delete[] aa[0];
+  delete[] aa[1];
+  delete[] aa[2];
+  delete[] aa;
+   
+  delete[] vv[0];
+  delete[] vv[1];
+  delete[] vv[2];
+  delete[] vv;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingConnectivity::NormalizeTensor3x3(float T[3][3], float W[3], float V[3][3], float N[3][3])
+{
+  float R[3][3], S[3][3];
+  float D[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
+
+  // diagonalize tensor
+  this->Jacobi3x3(T,W,V);
+
+  // force eigenvalues be positive
+  for (int i=0; i<3; i++) {
+    if (W[i] < 0) {
+      V[0][i] = -V[0][i];
+      V[1][i] = -V[1][i];
+      V[2][i] = -V[2][i];
+      W[i] = -W[i];
+    }
+  }
+
+  // make tensor unit size
+  D[0][0] = 1.0; D[1][1] = W[1]/W[0]; D[2][2] = W[2]/W[0];
+
+  // normalized tensor = V * D * V' 
+  (void) vtkMath::Transpose3x3(V,R);
+  (void) vtkMath::Multiply3x3(D,R,S);
+  (void) vtkMath::Multiply3x3(V,S,N);
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingConnectivity::ComputeSpeed(vtkImageData *input, vtkImageData *output, 
+					    int parent, int coord[3], int index, 
+					    float normal[3])
+{
+  vtkDataArray *in = input->GetPointData()->GetScalars();
+
+  //float D[3][3];
+  double result;
+  //float result,result0,result1;
+  
+  float T[3][3], N[3][3];
+  float V[3][3], V0[3];
+  float W[3]; //, R[3];
+
+  if (this->SymmetricTensor) {
+    T[0][0] = in->GetComponent(index, 0);           /* Dxx */
+    T[1][0] = T[0][1] = in->GetComponent(index, 1); /* Dxy */
+    T[2][0] = T[0][2] = in->GetComponent(index, 2); /* Dxz */
+    T[1][1] =  in->GetComponent(index, 3);          /* Dyy */
+    T[2][1] = T[1][2] = in->GetComponent(index, 4); /* Dyz */
+    T[2][2] = in->GetComponent(index, 5);           /* Dzz */
+  } else {
+    T[0][0] = in->GetComponent(index, 0);           /* Dxx */
+    T[1][0] = T[0][1] = in->GetComponent(index, 1); /* Dxy */
+    T[2][0] = T[0][2] = in->GetComponent(index, 2); /* Dxz */
+    T[1][1] =  in->GetComponent(index, 4);          /* Dyy */
+    T[2][1] = T[1][2] = in->GetComponent(index, 5); /* Dyz */
+    T[2][2] = in->GetComponent(index, 8);           /* Dzz */
+  }
+
+  // diagonalize and normalize tensor 
+  this->NormalizeTensor3x3(T,W,V,N);
+  
+  // calculate FA
+  float md = (W[0] + W[1] + W[2]) / 3.0;
+  float a=W[0]-md;
+  float b=W[1]-md;
+  float c=W[2]-md;
+  float FA = sqrt(3*(a*a + b*b + c*c)) / sqrt(2*(W[0]*W[0] + W[1]*W[1] + W[2]*W[2]));
+  
+  if (FA < 0.10) {
+    FA = 0.10;
+  }
+
+  // if eigenvalues are all zero, return 0
+  //if (W[0]==0 && W[1]==0 && W[2]==0)
+  //result = 0.01;
+  
+  // get major eigenvector
+  V0[0] = V[0][0]; 
+  V0[1] = V[1][0]; 
+  V0[2] = V[2][0];
+
+  double eps=1E-12;
+  double p = normal[0];
+  double q = normal[1];
+  double r = normal[2];
+  double grad = p*p + q*q + r*r;
+  //double prod = (p*V[0][0] + q*V[0][1] + r*V[0][2]) / (sqrt(grad)+eps);
+  double tdiff = (p*p*T[0][0]+q*q*T[1][1]+r*r*T[2][2]+2*p*q*T[0][1]+2*p*r*T[0][2]+2*q*r*T[1][2]);
+  //double diff = (p*p*N[0][0]+q*q*N[1][1]+r*r*N[2][2]+2*p*q*N[0][1]+2*p*r*N[0][2]+2*q*r*N[1][2]);
+  //double ndiff = diff / (grad+eps);
+  
+  //result = sqrt(grad) * FA*FA * exp(ndiff * ndiff);
+
+  // latest:
+  //result = FA * FA * (diff / sqrt(grad + eps));
+  result = sqrt(grad) * tdiff;
+
+  //double prod = p*V[0][0] + q*V[0][1] + r*V[0][2];
+  //result = sqrt(grad) * FA * FA * exp(prod*prod);
+  
+  // compute tensor product
+  //(void) vtkMath::Multiply3x3(N, direction, R);
+  //result0 = fabs(vtkMath::Dot(V0, direction));
+  //if (result0 > 1.0) printf("result0=%f\n",result0);
+  
+  // dot product of directions
+  //float V1[3] = {0.0, 1.0, 0.0};
+  //result1 = fabs(vtkMath::Dot(V1, direction));
+        
+  //if (FA >= 0.10) {
+  //result = exp(result*result*result);
+  //result =  exp(result*result);
+  //  result = FA * ((result < 0.99) ? (1.0 / (1.0 - result)) : 1000);
+  //result = tan(result*result) + 0.2;
+  //} else
+  //result = 0.0;
+  //result = sqrt(FA) * exp(result0*result0);
+  //  printf("FA=%f\n",FA);
+  //result =  FA*FA*exp(result0*result0*result0);
+
+  //result = FA * (1./(1.+exp(-10*(FA-0.5)))) * (result1*result1 + 0.1);
+  //result = FA * (1./(1.+exp(-10*(FA-0.5)))) * exp(pow(result0,3));
+  //result = exp(result0*result0);
+  //result = (result1*result1);
+  //result = result1;
+  
+  //result = FA*FA * exp(result*result);
+
+  //result = tan(result)+1.0;  
+  //else result=0.0;
+  //if (FA >= 0.2)  
+  //result = 1.0 / (1.0 - result*result);
+  //else result = 0.0;
+  
+  //if (this->Debug) {
+    //printf("direction=[%f,%f,%f],e1=[%f,%f,%f], result=%f\n",
+    //   direction[0], direction[1], direction[2], V0[0], V0[1], V0[2], result);
+  //}
+  
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingConnectivity::ComputeFirstOrder(vtkImageData *input, vtkImageData *output,
+						  int parent, int coord[3], int index)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  //vtkDataArray *in = input->GetPointData()->GetScalars(); 
+  vtkDataArray *out = output->GetPointData()->GetScalars();
+  
+  // estimate normal
+  float normal[3];
+  this->ComputeNormal(input, output, coord, index, normal);
+
+  // get speed value
+  double F = this->ComputeSpeed(input, output, parent, coord, index, normal);
+  //double F = 1.0;
+
+  if (F == 0.0) {
+    return this->Infinity;
+  }
+    
+  int num_terms = 0;
+  double direction[3];
+  double term[3];
+  int term_index[3];
+  
+  // process each one of the six neighbors
+  for (int j=0; j<3; j++) { // axis  
+    
+    direction[0] = 0.0;
+    direction[1] = 0.0;
+    direction[2] = 0.0;
+    
+    term[j] = VTK_MPJ_LARGE_FLOAT;
+    
+    for (int i=-1; i<2; i+=2) { // direction 
+      if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  
+	
+	direction[j] = (double)i;
+	
+	int neighbor=index + i*factor[j];
+	
+	// if value is frozen get its time
+	if (this->InMask(neighbor) && this->label->GetComponent(neighbor, 0) == VTK_MPJ_FROZEN) {
+	  
+	  double time = (double)out->GetComponent(neighbor, 0);
+	  
+	  if (time < term[j]) {
+	    term[j] = time;
+	    term_index[j] = neighbor;
+	  }
+
+	} // if
+      } // if       
+    } // for direction 
+    
+
+    // accumulate number of quadratic terms
+    //    printf("term[%d]=%f\n",j,term[j]);
+    num_terms += (term[j] != VTK_MPJ_LARGE_FLOAT);
+  
+  } // for axis
+  
+  //printf("num_terms=%d\n",num_terms);
+  
+  // sort terms
+  this->SortTerms(term);
+
+  double solution = this->Infinity;//VTK_MPJ_LARGE_FLOAT;
+
+  /*  if (num_terms == 3) { 
+      double sum_terms = term[0] + term[1] + term[2];
+      double termsq0 = term[0]*term[0];
+      double termsq1 = term[1]*term[1];
+      double termsq2 = term[2]*term[2];
+      double aux = 3.0 * ((1.0 / F*F) - termsq0 - termsq1 - termsq2);
+      solution = (sum_terms + sqrt(aux + sum_terms*sum_terms)) / 3.0;
+      } else if (num_terms == 2) {
+      double sum_terms = term[0] + term[1];
+      double aux = term[0] - term[1];
+      solution = (sum_terms + sqrt(2.0 * (1.0 / F*F) - aux*aux)) / 2.0;
+      } else {
+      solution = term[0] + (1.0 / F);
+      }*/
+
+//this->SortTerms(diff);
+  
+  //double F = diffusion;
+  //  printf("diffusion=%f\n",diffusion);
+  //if (F == 0.0)
+  //return VTK_MPJ_LARGE_FLOAT;
+
+  //printf("F=%f / %f=%f\n",sum_diff,(float)num_terms,F);
+  
+// F = diff[0];
+//if (this->Debug) { 
+//  printf("F=%f\n",F);
+//}
+
+  // solve quadratic for maximum solution
+  solution = this->SolveQuadratic(num_terms, term, this->Spacing[0] / F);
+
+  //if (this->Debug)
+  //printf("sol=%f\n",solution);
+
+  //double old_solution = (double)out->GetComponent(index, 0);
+  //if (old_solution < solution) 
+  //return old_solution;
+  //else    
+    return solution;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingConnectivity::ComputeTime(vtkImageData *input, vtkImageData *output,
+					   int parent, int coord[3], int index) 
+{
+  // vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  // compute time of arrival at neighbor
+  double time = this->ComputeFirstOrder(input, output, parent, coord, index);
+  
+  // insert neighbor in the narrow band
+  if (this->label->GetComponent(index, 0) != VTK_MPJ_NARROW_BAND) {
+    this->label->SetComponent(index, 0, VTK_MPJ_NARROW_BAND);
+    this->queue->Insert(time, index);
+  } else {
+    // if already in the narrow band, store new time
+    this->queue->DeleteId(index);
+    this->queue->Insert(time, index);
+  }
+
+  return time;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingConnectivity::InitializeFront(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  // Create priority queue
+  this->queue = vtkmpjPriorityQueue::New();
+  this->queue->Allocate(1000);
+
+  // Create label image
+  this->LabelImage = vtkImageData::New();
+  this->LabelImage->SetSpacing(input->GetSpacing());
+  this->LabelImage->SetOrigin(input->GetOrigin());
+  this->LabelImage->SetDimensions(input->GetDimensions());
+  this->LabelImage->SetScalarType(VTK_SHORT);
+  this->LabelImage->SetNumberOfScalarComponents(1);
+  this->LabelImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->LabelImage->AllocateScalars();
+  this->label = this->LabelImage->GetPointData()->GetScalars();
+  this->label->FillComponent(0, VTK_MPJ_UNVISITED);
+
+  out->FillComponent(0, this->Infinity);
+  
+  int index, coord[3], ncoord[3];
+  int dim0Tdim1 = dim[0]*dim[1];
+  //int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  // Freeze known points
+  int num_known = this->KnownPoints->GetNumberOfTuples();
+  for(int i=0; i<num_known; i++) {
+    
+    coord[0] = ncoord[0] = (int)this->KnownPoints->GetComponent(i, 0);
+    coord[1] = ncoord[1] = (int)this->KnownPoints->GetComponent(i, 1);
+    coord[2] = ncoord[2] = (int)this->KnownPoints->GetComponent(i, 2);
+    float value = this->KnownPoints->GetComponent(i, 3);
+    
+    index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+
+    // Tag initial points as trial points
+    this->label->SetComponent(index, 0, VTK_MPJ_NARROW_BAND);   
+
+    out->SetComponent(index, 0, this->KnownValues ? value : 0.0);              
+
+    // Insert into narrow band queue
+    this->queue->Insert(0, index);
+   
+    this->count++;
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingConnectivity::PropagateFront(vtkImageData *input, vtkImageData *output)
+{
+  double time;
+  int index, coord[3], ncoord[3];
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  while ((index = this->queue->Pop(time, 0)) != -1) {
+    
+    this->label->SetComponent(index, 0, VTK_MPJ_FROZEN);    
+    out->SetComponent(index, 0, (float)time);
+
+    this->count++;
+    if (this->count==this->tenth)
+      {
+	this->pog+=0.1;
+	this->UpdateProgress(this->pog);
+	this->count=0;
+      }
+    
+    // stop if arrival time is greater or equal to max time
+    if ((time == VTK_MPJ_LARGE_FLOAT) || 
+	((this->PropagationTime != VTK_MPJ_LARGE_FLOAT) && (time >= this->PropagationTime))) {
+      continue;
+    }
+
+    // decompose index into x, y, z coordinates
+    coord[2] = ncoord[2] = index / dim0Tdim1; 
+    int r = index % dim0Tdim1;
+    coord[1] = ncoord[1] = r / dim[0];
+    coord[0] = ncoord[0] = r % dim[0];
+    
+    // process each one of the six neighbors
+    for (int j=0; j<3; j++)  // axis  
+      for (int i=-1; i<2; i+=2)  { // direction 
+	
+	if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  
+	  int neighbor=index + i*factor[j];
+	  
+	  if (this->InMask(neighbor) && this->label->GetComponent(neighbor, 0) != VTK_MPJ_FROZEN) { 
+	   
+	    ncoord[j] = coord[j] + i;   // update coordinate
+	    this->ComputeTime(input, output, index, ncoord, neighbor);
+	    ncoord[j] = coord[j]; // reset
+	  }	  
+	}
+      }
+    } // while  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingConnectivity::SaveFrontPoints(vtkImageData *input)
+{
+  int total = this->queue->GetNumberOfItems();
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int index, coord[3];
+  double value;
+  
+  if (this->FrontPoints != NULL) 
+    this->FrontPoints->Delete();
+  
+  this->FrontPoints = vtkFloatArray::New(); 
+  this->FrontPoints->SetNumberOfComponents(4);
+  
+  for(int j=0; j<total; j++) {
+    
+    // get point index
+    index = queue->Peek(value, j);
+    
+    // decompose index
+    coord[2] = index / dim0Tdim1; 
+    int r = index % dim0Tdim1;
+    coord[1] = r / dim[0];
+    coord[0] = r % dim[0];
+    
+    // insert point
+    this->FrontPoints->InsertNextTuple4((float)coord[0], (float)coord[1], (float)coord[2], 
+					(float)value);
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingConnectivity::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  
+  if (this->GetInput()==NULL) {
+    vtkErrorMacro(<<"No Speed Image\n Exiting\n");
+    return;
+  }
+
+  symmetric = (input->GetNumberOfScalarComponents() == 6);
+
+  int total = input->GetPointData()->GetScalars()->GetNumberOfTuples();  
+  this->pog = 0.0;  
+  this->tenth = (int)(total / 10.0);
+  this->count = 0;
+  
+  this->UpdateProgress(0.01);
+  
+  // Get pointer to mask array
+  this->mask = (this->Mask != NULL) ? this->Mask->GetPointData()->GetScalars() : NULL;
+
+  // initialize
+  this->InitializeFront(input, output);  
+  
+  // propagate front
+  this->PropagateFront(input, output);
+
+  // save front points
+  this->SaveFrontPoints(input);
+
+  this->UpdateProgress(1.0);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingConnectivity.h b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingConnectivity.h
new file mode 100644
index 0000000..cb84da6
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingConnectivity.h
@@ -0,0 +1,166 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+  -- vtkmpjFastMarchingConnectivity.h --
+
+  Marcel Jackowski, Dec 2004.
+*/
+
+#define VTK_MPJ_FROZEN       -1     
+#define VTK_MPJ_NARROW_BAND   0
+#define VTK_MPJ_UNVISITED    +1
+
+#ifndef __vtkmpjFastMarchingConnectivity_h
+#define __vtkmpjFastMarchingConnectivity_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkmpjPriorityQueue.h"
+#include "vtkImageAccumulate.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjFastMarchingConnectivity : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjFastMarchingConnectivity *New();
+  vtkTypeMacro(vtkmpjFastMarchingConnectivity,vtkpxSimpleImageToImageFilter);
+  
+  // Description: Sets speed image
+  void SetSpeedImage(vtkImageData *speed);
+
+  // Description:
+  // Set/Get boundary conditions for the propagation
+  vtkSetObjectMacro(KnownPoints, vtkFloatArray);
+  vtkGetObjectMacro(KnownPoints, vtkFloatArray);
+
+  // Description:
+  // Turn on/off values for known points
+  vtkGetMacro(KnownValues,int);
+  vtkSetClampMacro(KnownValues,int,0,1);
+  vtkBooleanMacro(KnownValues,int);
+
+  // Description:
+  // Set/Get maximum propagation time
+  vtkGetMacro(PropagationTime,float);
+  vtkSetMacro(PropagationTime,float);
+  
+  // Description:
+  // Set/Get infinity value
+  vtkGetMacro(Infinity,float);
+  vtkSetMacro(Infinity,float);
+
+  // Description:
+  // Get/Set grid spacing
+  vtkGetVector3Macro(Spacing,float);
+  vtkSetVector3Macro(Spacing,float);
+
+  // Front label image. Points interior to the front have value -1, points 
+  // on the front boundary have value 0, and points outside have value +1.
+  vtkGetObjectMacro(LabelImage, vtkImageData);
+  
+  // Return an array containing front point vertices and their values
+  vtkGetObjectMacro(FrontPoints, vtkFloatArray);
+  
+  // Description: 
+  // Sets/Gets mask for determining propagation extents
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+    
+  // Description:
+  // Set/Get tensor symmetry flag
+  vtkSetMacro(SymmetricTensor, int);
+  vtkGetMacro(SymmetricTensor, int);
+  vtkBooleanMacro(SymmetricTensor, int);
+
+ protected:
+  int SymmetricTensor;
+  float Spacing[3];
+  float PropagationTime;
+  int KnownValues;
+  float Infinity;
+  vtkImageData *Speed;
+  vtkImageData *LabelImage;
+  vtkImageData *Mask;
+  vtkFloatArray *KnownPoints;
+  vtkFloatArray *FrontPoints;
+
+  vtkDataArray *label;
+  vtkmpjPriorityQueue *queue;     
+
+  vtkmpjFastMarchingConnectivity();
+  virtual ~vtkmpjFastMarchingConnectivity();
+  
+  void ExecuteInformation();  
+  virtual int InMask(int neighbor);
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  virtual void InitializeFront(vtkImageData *input, vtkImageData *output);
+  virtual void PropagateFront(vtkImageData *input, vtkImageData *output);
+  virtual void SaveFrontPoints(vtkImageData *input);  
+  virtual double ComputeSpeed(vtkImageData *input, vtkImageData *output,
+			      int parent, int coord[3], int index, float normal[3]);  
+  virtual double ComputeFirstOrder(vtkImageData *input, vtkImageData *output,
+				   int parent, int coord[3], int index);
+  virtual void ComputeNormal(vtkImageData *input, vtkImageData *output,
+			     int coord[3], int index, float result[3]);
+  
+  void SortTerms(double term[3]);
+  double Solve2(double a, double b, double rhs);
+  double SolveN(int number, double term[3], double rhs);
+  double SolveQuadratic(int number, double term[3], double rhs);
+  
+  double ComputeTime(vtkImageData *input, vtkImageData *output,
+		     int parent, int coord[3], int index);  
+  
+  void Jacobi3x3(float a[3][3], float w[3], float v[3][3]);
+  void NormalizeTensor3x3(float T[3][3], float W[3], float V[3][3], float N[3][3]);
+		 
+		 
+
+ private:
+  //BTX
+  float pog;
+  int count, tenth; 
+  vtkDataArray *mask;
+  int symmetric;
+  //ETX
+  
+  vtkmpjFastMarchingConnectivity(const vtkmpjFastMarchingConnectivity&);// Not implemented
+  void operator=(const vtkmpjFastMarchingConnectivity&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingExtension.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingExtension.cpp
new file mode 100644
index 0000000..912d496
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingExtension.cpp
@@ -0,0 +1,555 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjFastMarchingExtension.h"
+
+//------------------------------------------------------------------------------
+vtkmpjFastMarchingExtension* vtkmpjFastMarchingExtension::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjFastMarchingExtension");
+  if(ret)
+    {
+      return (vtkmpjFastMarchingExtension*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjFastMarchingExtension;
+}
+
+// Construct object with no children.
+vtkmpjFastMarchingExtension::vtkmpjFastMarchingExtension()
+{
+  this->KnownPoints = NULL;
+  this->KnownValues = 1;
+  this->LabelImage = NULL;
+  this->ExtensionImage = NULL;
+  this->FrontPoints = NULL;
+  this->PropagationTime = VTK_LARGE_FLOAT;
+  this->Spacing = 1.0;
+  this->queue = NULL;
+  this->label = NULL;
+  this->neighbor_index[0]=0;
+  this->neighbor_index[1]=0;
+  this->neighbor_index[2]=0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjFastMarchingExtension::~vtkmpjFastMarchingExtension()
+{
+  if (this->KnownPoints != NULL)
+    this->KnownPoints->Delete();
+  if (this->ExtensionImage != NULL)
+    this->ExtensionImage->Delete();
+  if (this->LabelImage != NULL)
+    this->LabelImage->Delete();
+  if (this->FrontPoints != NULL)
+    this->FrontPoints->Delete();
+  if (this->queue != NULL)    
+    this->queue->Delete();
+}
+
+// ----------------------------------------------------------------------------
+int vtkmpjFastMarchingExtension::GetNeighborIndex(int j)
+{
+  return this->neighbor_index[j];
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingExtension::SetSpeedImage(vtkImageData *speed)
+{
+  this->SetInput(speed);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingExtension::ExecuteInformation()
+{
+  vtkImageData *input = this->GetInput();
+  vtkImageData *output = this->GetOutput();
+   
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Speed Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  int dim[3]; input->GetDimensions(dim);
+  
+  if (this->KnownPoints==NULL) {
+    vtkErrorMacro(<<"Set of known points is empty!");
+    return;
+  }
+
+  printf("dims=%d %d %d\n", dim[0],dim[1],dim[2]);
+
+  if (this->ExtensionImage==NULL) {
+    vtkErrorMacro(<<"No extension image!");
+    return;
+  }
+
+  int nc = this->ExtensionImage->GetNumberOfScalarComponents();
+
+  printf("nc1=%d\n",nc);
+  output->SetNumberOfScalarComponents(1+nc);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingExtension::SortTerms(double term[3]) 
+{
+  double tmp[3];
+
+  if (term[0] < term[1]) {
+    if (term[0] < term[2]) {
+      if (term[1] < term[2]) {
+	tmp[0] = term[0]; tmp[1] = term[1]; tmp[2] = term[2]; 
+      } else {
+	tmp[0] = term[0]; tmp[1] = term[2]; tmp[2] = term[1]; 
+      }
+    } else 
+      {
+	tmp[0] = term[2]; tmp[1] = term[0]; tmp[2] = term[1];
+      }
+  } else {
+    if (term[1] < term[2]) {
+      if (term[0] < term[2]) {
+	tmp[0] = term[1]; tmp[1] = term[0]; tmp[2] = term[2];
+      } else {
+	tmp[0] = term[1]; tmp[1] = term[2]; tmp[2] = term[0];
+      }
+    } else
+      {
+	tmp[0] = term[2]; tmp[1] = term[1]; tmp[2] = term[0];
+      }    
+  }
+
+  term[0] = tmp[0];
+  term[1] = tmp[1];
+  term[2] = tmp[2];
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingExtension::Solve2(double a, double b, double rhs)
+{  
+  double amb = a - b;
+  if (fabs(amb) >= rhs) {
+    return (a < b ? a : b) + rhs;
+  } else {
+    double amb2 = amb*amb;
+    return (a+b+sqrt(2.0*rhs*rhs-amb2)) / 2.0;
+  }
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingExtension::SolveN(int number, double term[3], double rhs)
+{
+  double coeff[3] = {-rhs*rhs, 0.0, 0.0};
+
+  for (int j=0; j<3; j++) {
+    if (term[j] != VTK_LARGE_FLOAT) {
+      coeff[2] += 1.0;
+      coeff[1] -= 2*term[j];
+      coeff[0] += term[j]*term[j];
+    }
+  }
+  
+  int no_solutions = 1;
+  double max_sol = VTK_LARGE_FLOAT;
+  double sol[2] = {VTK_LARGE_FLOAT, VTK_LARGE_FLOAT};
+  double discr = coeff[1]*coeff[1] - 4.0*coeff[2]*coeff[0];
+  
+  if (discr < 0) {
+    printf("Solution is not differentiable! terms=%f, %f, %f, coeffs=%f, %f, %f\n", term[0], term[1], term[2], coeff[2], coeff[1], coeff[0]);
+  }
+  
+  // solve quadratic equation
+  vtkMath::SolveQuadratic(coeff[2], coeff[1], coeff[0], 
+			  &sol[0], &sol[1], &no_solutions);
+  if (no_solutions == 2) {
+    max_sol = sol[0]>=sol[1]?sol[0]:sol[1];
+  } else {
+    max_sol = sol[0];
+  }
+  
+  return max_sol;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingExtension::SolveQuadratic(int number, double term[3], double rhs)
+{  
+  double result;
+  
+  switch(number) {
+  case 1:
+    result = term[0] + rhs;
+    break;
+  case 2:
+    result = Solve2(term[0], term[1], rhs);
+    break;
+  case 3:
+  default:
+    if ((term[0] + rhs) > term[1]) {
+      result = term[0] + rhs;      
+    } else {
+      result = Solve2(term[0], term[1], rhs);
+    }
+    if (result > term[2])
+      result = SolveN(number, term, rhs);
+    break;
+  };
+      
+  return(result);
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingExtension::ComputeSpeed(vtkImageData *input, vtkImageData *output, 
+					      int coord[3], int index)
+{
+  vtkDataArray *in = input->GetPointData()->GetScalars();
+  return in->GetComponent(index, 0);
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingExtension::ComputeFirstOrder(vtkImageData *input, vtkImageData *output,
+						  int coord[3], int index)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *in = input->GetPointData()->GetScalars(); 
+  vtkDataArray *out = output->GetPointData()->GetScalars();
+  
+  // get speed value
+  double F = this->ComputeSpeed(input, output, coord, index);
+  
+  if (F == 0.0) 
+    return VTK_LARGE_FLOAT;
+    
+  int num_terms = 0;
+  double term[3];
+  
+  // process each one of the six neighbors
+  for (int j=0; j<3; j++) { // axis  
+    
+    term[j] = VTK_LARGE_FLOAT;
+    
+    for (int i=-1; i<2; i+=2) { // direction 
+      if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  
+	
+	int neighbor=index + i*factor[j];
+	
+	// if value is frozen get its time
+	if (this->label->GetComponent(neighbor, 0) == VTK_MPJ_FROZEN) {
+
+	  double time = (double)out->GetComponent(neighbor, 0);
+	  
+	  if (time < term[j]) {
+	    term[j] = time;
+	    this->neighbor_index[j] = neighbor;
+	  }
+	  		  
+	} // if
+      } // if       
+    } // for direction 
+ 
+    // accumulate number of quadratic terms
+    num_terms += (term[j] != VTK_LARGE_FLOAT);
+
+  } // for axis
+  
+  // sort terms
+  this->SortTerms(term);
+
+  // solve quadratic for maximum solution
+  double solution = this->SolveQuadratic(num_terms, term, this->Spacing / F);
+
+  // extend values
+  vtkDataArray *ext = this->ExtensionImage->GetPointData()->GetScalars();
+  int nc = ext->GetNumberOfComponents();
+
+  for(int k=0; k<nc; k++) {
+    
+    double numer = 0.0;
+    double denom = 0.0;
+    
+    // for all dimensions
+    for(int j=0; j<3; j++) {
+      
+      int neighbor = this->neighbor_index[j];
+      float time = out->GetComponent(neighbor, 0);	
+      
+      //if (solution < time) {
+      //break;
+      //}
+      
+      float extval = ext->GetComponent(neighbor, k);
+      numer += extval * (solution - time);
+      denom += (solution - time);
+    }
+    
+    //printf("numer=%f,denom=%f\n",numer,denom);
+
+    if (denom > 0)
+      out->SetComponent(index, 1+k, (float)(numer / denom));
+    else 
+      out->SetComponent(index, 1+k, 0.0);
+    
+  }
+
+  return solution;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingExtension::ComputeTime(vtkImageData *input, vtkImageData *output,
+					     int coord[3], int index)
+{
+  // compute time of arrival at neighbor
+  double time = this->ComputeFirstOrder(input, output, coord, index);
+  
+  // insert neighbor in the narrow band
+  if (this->label->GetComponent(index, 0) != VTK_MPJ_NARROW_BAND) {
+    this->label->SetComponent(index, 0, VTK_MPJ_NARROW_BAND);
+    this->queue->Insert(time, index);
+  } else {
+    // if already in the narrow band, store new time
+    this->queue->DeleteId(index);
+    this->queue->Insert(time, index);
+  }
+
+  return time;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingExtension::InitializeFront(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  // Create priority queue
+  this->queue = vtkmpjPriorityQueue::New();
+  this->queue->Allocate(1000);
+
+  // Create label image
+  this->LabelImage = vtkImageData::New();
+  this->LabelImage->SetSpacing(input->GetSpacing());
+  this->LabelImage->SetOrigin(input->GetOrigin());
+  this->LabelImage->SetDimensions(input->GetDimensions());
+  this->LabelImage->SetScalarType(VTK_SHORT);
+  this->LabelImage->SetNumberOfScalarComponents(1);
+  this->LabelImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->LabelImage->AllocateScalars();
+  this->label = this->LabelImage->GetPointData()->GetScalars();
+  this->label->FillComponent(0, VTK_MPJ_UNVISITED);
+
+  out->FillComponent(0, VTK_LARGE_FLOAT);
+  
+  int index, coord[3], ncoord[3];
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+
+  // Freeze known points
+  int num_known = this->KnownPoints->GetNumberOfTuples();
+
+  vtkDataArray *ext = this->ExtensionImage->GetPointData()->GetScalars();
+  int ext_nc = ext->GetNumberOfComponents();
+
+  for(int i=0; i<num_known; i++) {
+    
+    coord[0] = ncoord[0] = (int)this->KnownPoints->GetComponent(i, 0);
+    coord[1] = ncoord[1] = (int)this->KnownPoints->GetComponent(i, 1);
+    coord[2] = ncoord[2] = (int)this->KnownPoints->GetComponent(i, 2);
+    float value = this->KnownPoints->GetComponent(i, 3);
+    
+    index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+    
+    this->label->SetComponent(index, 0, VTK_MPJ_FROZEN);   // Freeze voxel
+
+    out->SetComponent(index, 0, this->KnownValues ? value : 0.0);              
+
+    for(int k=0;k<ext_nc;k++) {
+      out->SetComponent(index, k+1, ext->GetComponent(index, k));
+    }
+
+    this->count++;
+  }
+
+  // Process boundary neighbors
+  for(int i=0; i<this->KnownPoints->GetNumberOfTuples(); i++) {
+  
+    coord[0] = ncoord[0] = (int)KnownPoints->GetComponent(i, 0);
+    coord[1] = ncoord[1] = (int)KnownPoints->GetComponent(i, 1);
+    coord[2] = ncoord[2] = (int)KnownPoints->GetComponent(i, 2);
+    index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+
+    // process each one of the six neighbors
+    for (int j=0; j<3; j++) { // axis  
+      for (int i=-1; i<2; i+=2)  { // direction	  	
+	
+	if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  	    
+	  
+	  int neighbor=index + i*factor[j];
+	  ncoord[j] = coord[j] + i;   // update coordinate
+	  
+	  // compute arrival time
+	  if (this->label->GetComponent(neighbor, 0) != VTK_MPJ_FROZEN)
+	    this->ComputeTime(input, output, ncoord, neighbor);
+	  
+	  ncoord[j] = coord[j]; // reset
+	}
+      }
+    }
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingExtension::PropagateFront(vtkImageData *input, vtkImageData *output)
+{
+  double time;
+  int index, coord[3], ncoord[3];
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  while ((index = this->queue->Pop(time, 0)) != -1) {
+    
+    this->label->SetComponent(index, 0, VTK_MPJ_FROZEN);    
+    out->SetComponent(index, 0, (float)time);
+
+    this->count++;
+    if (this->count==this->tenth)
+      {
+	this->pog+=0.1;
+	this->UpdateProgress(this->pog);
+	this->count=0;
+      }
+    
+    // stop if arrival time is greater or equal to max time
+    if ((time == VTK_LARGE_FLOAT) || 
+	(this->PropagationTime != VTK_LARGE_FLOAT) && (time >= this->PropagationTime)) {
+      break;
+    }
+
+    // decompose index into x, y, z coordinates
+    coord[2] = ncoord[2] = index / dim0Tdim1; 
+    int r = index % dim0Tdim1;
+    coord[1] = ncoord[1] = r / dim[0];
+    coord[0] = ncoord[0] = r % dim[0];
+    
+    //    if (time == VTK_LARGE_FLOAT) {
+      /*printf("%d %d %d\n",coord[0],coord[1],coord[2]);*/
+      //continue;
+    //}
+    
+    // process each one of the six neighbors
+    for (int j=0; j<3; j++)  // axis  
+      for (int i=-1; i<2; i+=2)  { // direction 
+	
+	if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  
+	  int neighbor=index + i*factor[j];
+	  
+	  if (this->label->GetComponent(neighbor, 0) != VTK_MPJ_FROZEN) { 
+	   
+	    ncoord[j] = coord[j] + i;   // update coordinate
+
+	    this->ComputeTime(input, output, ncoord, neighbor);
+
+	    ncoord[j] = coord[j]; // reset
+	  }	  
+	}
+      }
+    } // while  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingExtension::SaveFrontPoints(vtkImageData *input)
+{
+  int total = this->queue->GetNumberOfItems();
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int index, coord[3];
+  double value;
+  
+  if (this->FrontPoints != NULL) 
+    this->FrontPoints->Delete();
+  
+  this->FrontPoints = vtkFloatArray::New(); 
+  this->FrontPoints->SetNumberOfComponents(4);
+  
+  for(int j=0; j<total; j++) {
+    
+    // get point index
+    index = queue->Peek(value, j);
+    
+    // decompose index
+    coord[2] = index / dim0Tdim1; 
+    int r = index % dim0Tdim1;
+    coord[1] = r / dim[0];
+    coord[0] = r % dim[0];
+    
+    // insert point
+    this->FrontPoints->InsertNextTuple4((float)coord[0], (float)coord[1], (float)coord[2], 
+					(float)value);
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingExtension::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  
+  if (this->GetInput()==NULL) {
+    vtkErrorMacro(<<"No Speed Image\n Exiting\n");
+    return;
+  }
+  
+  int total = input->GetPointData()->GetScalars()->GetNumberOfTuples();  
+  this->pog = 0.0;  
+  this->tenth = (int)(total / 10.0);
+  this->count = 0;
+  
+  this->UpdateProgress(0.01);
+  
+  // initialize
+  this->InitializeFront(input, output);  
+  
+  // propagate front
+  this->PropagateFront(input, output);
+
+  // save front points
+  this->SaveFrontPoints(input);
+
+  this->UpdateProgress(1.0);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingExtension.h b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingExtension.h
new file mode 100644
index 0000000..5697896
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingExtension.h
@@ -0,0 +1,141 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+  -- vtkmpjFastMarchingExtension.h --
+   
+  Marcel Jackowski, June 2003
+*/
+
+#define VTK_MPJ_FROZEN       -1     
+#define VTK_MPJ_NARROW_BAND   0
+#define VTK_MPJ_UNVISITED    +1
+
+#ifndef __vtkmpjFastMarchingExtension_h
+#define __vtkmpjFastMarchingExtension_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkmpjPriorityQueue.h"
+#include "vtkImageAccumulate.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjFastMarchingExtension : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjFastMarchingExtension *New();
+  vtkTypeMacro(vtkmpjFastMarchingExtension,vtkpxSimpleImageToImageFilter);
+  
+  // Description: Sets speed image
+  void SetSpeedImage(vtkImageData *speed);
+
+  // Description: Set/Get extension image
+  vtkSetObjectMacro(ExtensionImage, vtkImageData);
+  vtkGetObjectMacro(ExtensionImage, vtkImageData);
+
+  // Description:
+  // Set/Get boundary conditions for the propagation
+  vtkSetObjectMacro(KnownPoints, vtkFloatArray);
+  vtkGetObjectMacro(KnownPoints, vtkFloatArray);
+
+  // Description:
+  // Turn on/off values for known points
+  vtkGetMacro(KnownValues,int);
+  vtkSetClampMacro(KnownValues,int,0,1);
+  vtkBooleanMacro(KnownValues,int);
+
+  // Description:
+  // Set/Get maximum propagation time
+  vtkGetMacro(PropagationTime,float);
+  vtkSetMacro(PropagationTime,float);
+  
+  // Description:
+  // Set/Get grid spacing
+  vtkGetMacro(Spacing,float);
+  vtkSetMacro(Spacing,float);
+  
+  // Front label image. Points interior to the front have value -1, points 
+  // on the front boundary have value 0, and points outside have value +1.
+  vtkGetObjectMacro(LabelImage, vtkImageData);
+  
+  // Return an array containing front point vertices and their values
+  vtkGetObjectMacro(FrontPoints, vtkFloatArray);
+  
+ protected:
+  float Spacing;
+  float PropagationTime;
+  int KnownValues;
+  vtkImageData *Speed;
+  vtkImageData *LabelImage;
+  vtkImageData *ExtensionImage;
+  vtkFloatArray *KnownPoints;
+  vtkFloatArray *FrontPoints;
+
+  vtkDataArray *label;
+  vtkmpjPriorityQueue *queue;     
+
+  vtkmpjFastMarchingExtension();
+  virtual ~vtkmpjFastMarchingExtension();
+  
+  void ExecuteInformation();  
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  virtual void InitializeFront(vtkImageData *input, vtkImageData *output);
+  virtual void PropagateFront(vtkImageData *input, vtkImageData *output);
+  virtual void SaveFrontPoints(vtkImageData *input);  
+  virtual double ComputeSpeed(vtkImageData *input, vtkImageData *output, int coord[3], int index);
+  virtual double ComputeFirstOrder(vtkImageData *input, vtkImageData *output, int coord[3], int index);
+
+  int GetNeighborIndex(int j);
+  void SortTerms(double term[3]);
+  double Solve2(double a, double b, double rhs);
+  double SolveN(int number, double term[3], double rhs);
+  double SolveQuadratic(int number, double term[3], double rhs);
+  
+  double ComputeTime(vtkImageData *input, vtkImageData *output,
+		     int coord[3], int index);  
+ private:
+  //BTX
+  float pog;
+  int count, tenth; 
+  int neighbor_index[3];
+  //ETX
+  
+  vtkmpjFastMarchingExtension(const vtkmpjFastMarchingExtension&);// Not implemented
+  void operator=(const vtkmpjFastMarchingExtension&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingImageFilter.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingImageFilter.cpp
new file mode 100644
index 0000000..ed3ba5d
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingImageFilter.cpp
@@ -0,0 +1,596 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjFastMarchingImageFilter.h"
+
+vtkStandardNewMacro(vtkmpjFastMarchingImageFilter);
+
+// Construct object 
+vtkmpjFastMarchingImageFilter::vtkmpjFastMarchingImageFilter()
+{  
+  
+  this->OutputExtent[0] = this->OutputExtent[2] = this->OutputExtent[4] = 0;
+  this->OutputExtent[1] = this->OutputExtent[3] = this->OutputExtent[5] = 63;
+  this->OutputSpacing[0] = this->OutputSpacing[1] = this->OutputSpacing[2] = 1.0;
+
+  this->OverrideOutputInformation = 0;
+  
+  this->AlivePoints = NULL;
+  this->TrialPoints = NULL;
+  
+  this->CollectPoints = 0;
+  this->ProcessedPoints = NULL;
+
+  this->SpeedConstant = 1.0;
+  this->InverseSpeed = -1.0;
+  
+  this->LargeValue = VTK_LARGE_FLOAT / 2.0;
+  this->StoppingValue = this->LargeValue;
+
+  this->NormalizationFactor = 1.0;
+
+  this->LabelImage = NULL;
+
+  this->NumberOfRequiredInputs = 0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjFastMarchingImageFilter::~vtkmpjFastMarchingImageFilter()
+{
+  if (this->ProcessedPoints != NULL)
+    this->ProcessedPoints->Delete();
+  
+  if (this->AlivePoints != NULL)
+    this->AlivePoints->Delete();
+  
+  if (this->TrialPoints != NULL)
+    this->TrialPoints->Delete();
+  
+  if (this->LabelImage != NULL)
+    this->LabelImage->Delete();  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingImageFilter::SetOutputExtent(int minX, int maxX,
+						    int minY, int maxY,
+						    int minZ, int maxZ)
+{
+  this->OutputExtent[0] = minX;
+  this->OutputExtent[1] = maxX;
+  this->OutputExtent[2] = minY;
+  this->OutputExtent[3] = maxY;
+  this->OutputExtent[4] = minZ;
+  this->OutputExtent[5] = maxZ;
+  this->Modified();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingImageFilter::Initialize(vtkImageData *output)
+{
+  int dim[3]; output->GetDimensions(dim);
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  
+  // set all output values to infinity
+  out->FillComponent(0, this->LargeValue);
+  
+  // create label image
+  this->LabelImage = vtkImageData::New();
+  this->LabelImage->SetSpacing(output->GetSpacing());
+  this->LabelImage->SetOrigin(output->GetOrigin());
+  this->LabelImage->SetDimensions(output->GetDimensions());
+  this->LabelImage->SetScalarType(VTK_SHORT);
+  this->LabelImage->SetNumberOfScalarComponents(1);
+  this->LabelImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->LabelImage->AllocateScalars();
+  
+  // set all points type to FarPoint
+  vtkDataArray *label = this->LabelImage->GetPointData()->GetScalars();
+  label->FillComponent(0, FarPoint);
+
+
+  int index, coord[3];
+  int dim0xdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0xdim1};
+   
+  // process input alive points
+  if ( this->AlivePoints ) {
+    
+    int total = this->AlivePoints->GetNumberOfTuples();
+    int nc = this->AlivePoints->GetNumberOfComponents();
+    double value = 0.0;
+    
+    for(int i=0; i<total; i++) {
+      
+      // get coordinates
+      coord[0] = (int)this->AlivePoints->GetComponent(i, 0);
+      coord[1] = (int)this->AlivePoints->GetComponent(i, 1);
+      coord[2] = (int)this->AlivePoints->GetComponent(i, 2);
+      index = dim0xdim1*coord[2] + dim[0]*coord[1] + coord[0];
+      
+      // get output value
+      if (nc > 3)
+	value = (double)this->AlivePoints->GetComponent(i, 3);
+      
+      // make this an alive point
+      label->SetComponent(index, 0, AlivePoint);
+      
+      // initialize output value
+      out->SetComponent(index, 0, value);  
+      
+    }
+    
+  }
+  
+  // make sure the heap is empty
+  while ( !this->TrialHeap.empty() )
+    {
+      this->TrialHeap.pop();
+    }
+    
+  // process the input trial points
+  if ( this->TrialPoints )
+    {
+      int total = this->TrialPoints->GetNumberOfTuples();
+      int nc = this->TrialPoints->GetNumberOfComponents();
+      double value = 0.0;
+      
+      for(int i=0; i<total; i++) {
+	
+	// get point coordinates
+	coord[0] = (int)this->TrialPoints->GetComponent(i, 0);
+	coord[1] = (int)this->TrialPoints->GetComponent(i, 1);
+	coord[2] = (int)this->TrialPoints->GetComponent(i, 2);
+	index = dim0xdim1*coord[2] + dim[0]*coord[1] + coord[0];
+
+	// get output value
+	if (nc > 3)
+	  value = (double)this->TrialPoints->GetComponent(i, 3);
+	
+	// make this a trial point
+	label->SetComponent(index, 0, TrialPoint);
+	
+	// initialize output value
+	out->SetComponent(index, 0, value);
+	
+	// insert point into queue
+	this->TrialHeap.push ( new NodeType(value, index) );
+      }
+      
+    }
+
+  vtkDebugMacro(<< "reached end of Initialize()");
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingImageFilter::GenerateData(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; output->GetDimensions(dim);
+  int dim0xdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0xdim1};
+  int coord[3];
+
+  vtkDebugMacro(<< "in GenerateData()");
+
+  vtkDataArray *in=NULL;
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  vtkDataArray *label;
+
+  vtkDebugMacro(<< "calling Initialize()");
+
+  this->Initialize( output );
+
+  if (input != NULL) {
+    in = input->GetPointData()->GetScalars();
+  }
+
+  label = this->LabelImage->GetPointData()->GetScalars();
+  
+  if (this->CollectPoints) {
+    this->ProcessedPoints = vtkDoubleArray::New();
+    this->ProcessedPoints->SetNumberOfComponents(4);
+    this->ProcessedPoints->Allocate(500);
+  }
+  
+  int index;
+  double value;
+  double currentValue;
+  double oldValue = -this->LargeValue;
+
+  double oldProgress = 0;
+  unsigned long NumPoints = 0;
+  unsigned long InvalidPoints = 0;
+  
+  this->UpdateProgress( 0.0 ); // Send first progress event
+
+  // process points on the heap
+  while ( !this->TrialHeap.empty () ) {
+    
+    // get the node with the smallest value
+    NodeType *node = this->TrialHeap.top();
+    this->TrialHeap.pop();
+
+    index = node->index;
+    value = node->value;
+
+    if ( this->GetDebug() ) { NumPoints++; }
+    
+    // does this node contain the current value ?
+    currentValue = (double) out->GetComponent(index, 0);
+
+    if ( (float(value)) != currentValue )
+      {
+	if ( this->GetDebug() ) { InvalidPoints++; }
+	printf("value=%f, currentValue=%f\n",value,currentValue);
+	continue;
+      } 
+    
+    // is this node already alive ?
+    if ( label->GetComponent(index, 0) != TrialPoint ) 
+      {
+	if ( this->GetDebug() ) { InvalidPoints++; }
+	continue;
+      }    
+    
+    if ( currentValue > this->StoppingValue )
+      {
+	vtkDebugMacro(<< "stopping value reached");
+	break;
+      }
+    
+    if ( this->GetDebug() && currentValue < oldValue) 
+      {
+	vtkDebugMacro(<< "error value decrease at:" << index );
+      }
+    
+    oldValue = currentValue;
+
+    // decompose index
+    coord[2] = index / dim0xdim1;
+    int r = index % dim0xdim1;
+    coord[1] = r / dim[0];
+    coord[0] = r % dim[0];
+
+    if ( this->CollectPoints )
+      {	
+	this->ProcessedPoints->InsertNextTuple4((double)coord[0], 
+						(double)coord[1], 
+						(double)coord[2],
+						(double)value);
+      }
+
+    // set this node as alive
+    label->SetComponent( index, 0, AlivePoint );
+    
+    // update its neighbors
+    this->UpdateNeighbors( index, coord, input, output );
+
+    // Send events every certain number of points.
+    const double newProgress = currentValue / this->StoppingValue;
+    if( newProgress - oldProgress > 0.01 )  // update every 1%
+      {
+	this->UpdateProgress( newProgress );
+	oldProgress = newProgress;
+	if ( this->GetAbortExecute() )
+	  {
+	    break;
+	  }
+      }
+    
+  }
+  
+  vtkDebugMacro(<< "No. points processed: " << NumPoints);
+  vtkDebugMacro(<< "No. invalid points: " << InvalidPoints);
+  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingImageFilter::UpdateNeighbors( int index, int coord[3], vtkImageData *input, vtkImageData *output )
+{
+  vtkDataArray *label=this->LabelImage->GetPointData()->GetScalars();
+
+  int dim[3]; output->GetDimensions(dim);
+  int dim0xdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0xdim1};
+  int neighCoord[3] = {coord[0], coord[1], coord[2]};
+  int neighIndex = index;
+  
+  for ( int j = 0; j < 3; j++ ) // for each dimension
+    { 
+
+      // update left neighbor
+      if ( (coord[j] - 1) >= 0 )
+	{
+	  neighIndex = index - factor[j];
+	  neighCoord[j] = coord[j] - 1;	  
+	}
+      
+      if ( label->GetComponent( neighIndex, 0 ) != AlivePoint )
+	{
+	  this->UpdateValue( neighIndex, neighCoord, input, output );
+	}
+      
+      // update right neighbor
+      if ( (coord[j] + 1) < dim[j] ) 
+	{
+	  neighIndex = index + factor[j];	  
+	  neighCoord[j] = coord[j] + 1;
+	}
+      
+      if ( label->GetComponent( neighIndex, 0 ) != AlivePoint )
+	{
+	  this->UpdateValue( neighIndex, neighCoord, input, output );
+	}
+
+      //reset neighCoord
+      neighCoord[j] = coord[j];
+      neighIndex = index;
+      
+    }
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingImageFilter::UpdateValue( int index, int coord[3], vtkImageData *input, vtkImageData *output )
+{
+  vtkDataArray *in=NULL;
+  vtkDataArray *out = output->GetPointData()->GetScalars();
+  vtkDataArray *label=this->LabelImage->GetPointData()->GetScalars();
+    
+  if (input != NULL) 
+    in = input->GetPointData()->GetScalars();
+
+  int dim[3]; output->GetDimensions(dim);
+  int dim0xdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0xdim1};
+  int neighIndex = index;
+  int neighCoord[3] = {coord[0], coord[1], coord[2]}; 
+  
+  double neighValue, minValue, values[3];
+  int minIndex;
+
+  for ( int j = 0; j < 3; j++ ) // for each dimension
+    {
+      minValue = this->LargeValue;
+      
+      // find smallest valued neighbor in this dimension
+      for( int s = -1; s < 2; s = s + 2 )
+	{
+	  neighIndex = index + s*factor[j];
+	  
+	  if ( (coord[j] + s) < 0 || (coord[j] + s) > dim[j] ) 
+	    {
+	      continue;
+	    }
+	  
+	  if (label->GetComponent( neighIndex, 0 ) == AlivePoint )
+	    {
+	      neighValue = out->GetComponent( neighIndex, 0 );
+	      
+	      if( minValue > neighValue )
+		{
+		  minValue = neighValue;
+		  minIndex = neighIndex;
+		}
+	    }	  	  
+	}
+      
+      // store minimum value in each dimension
+      values[j] = minValue;           
+    }
+  
+  // sort the local list
+  this->SortThreeValues(values); 
+  
+  // solve quadratic equation
+  double aa, bb, cc;
+  double solution = this->LargeValue;
+  
+  aa = 0.0;
+  bb = 0.0;
+  if ( input != NULL )
+    {
+      cc = (double) in->GetComponent(index, 0) / this->NormalizationFactor;
+      cc = -1.0 * ( 1.0 / cc ) * ( 1.0 / cc);
+    }
+  else 
+    {
+      cc = this->InverseSpeed;
+    }
+ 
+  double discrim;
+  
+  for ( int j = 0; j < 3; j++ ) // for each dimension
+    {
+      if ( solution >= values[j] )
+	{
+	  aa += 1.0;
+	  bb += values[j];
+	  cc += values[j] * values[j];
+	  
+	  discrim = bb * bb - aa * cc;
+	  if ( discrim < 0.0 )
+	    {
+	      // Discriminant of quadratic eqn. is negative
+	      vtkErrorMacro(<<"Discriminant of quadratic equation is negative");
+	      solution = this->LargeValue;
+	    }
+	  
+	  solution = ( sqrt( discrim ) + bb ) / aa;
+	}
+      else
+	{
+	  break;
+	}      
+    }
+
+  if ( solution < this->LargeValue )
+    {
+      // write solution to m_OutputLevelSet
+      out->SetComponent(index, 0, solution);  
+      
+      // insert point into trial heap
+      label->SetComponent(index, 0, TrialPoint);
+      
+      // insert point into queue
+      this->TrialHeap.push ( new NodeType(solution, index) );
+    }
+
+  return solution;
+  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingImageFilter::SortThreeValues(double value[3]) 
+{
+  double tmp[3];
+
+  if (value[0] < value[1]) {
+    if (value[0] < value[2]) {
+      if (value[1] < value[2]) {
+	tmp[0] = value[0]; tmp[1] = value[1]; tmp[2] = value[2]; 
+      } else {
+	tmp[0] = value[0]; tmp[1] = value[2]; tmp[2] = value[1]; 
+      }
+    } else 
+      {
+	tmp[0] = value[2]; tmp[1] = value[0]; tmp[2] = value[1];
+      }
+  } else {
+    if (value[1] < value[2]) {
+      if (value[0] < value[2]) {
+	tmp[0] = value[1]; tmp[1] = value[0]; tmp[2] = value[2];
+      } else {
+	tmp[0] = value[1]; tmp[1] = value[2]; tmp[2] = value[0];
+      }
+    } else
+      {
+	tmp[0] = value[2]; tmp[1] = value[1]; tmp[2] = value[0];
+      }    
+  }
+
+  value[0] = tmp[0];
+  value[1] = tmp[1];
+  value[2] = tmp[2];
+}
+
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingImageFilter::SetSpeedConstant( double value )      
+{
+  this->SpeedConstant = value;
+  this->InverseSpeed = -1.0 * ( 1.0 / this->SpeedConstant ) * ( 1.0 / this->SpeedConstant );
+  this->Modified();
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjFastMarchingImageFilter::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);
+  
+  os << indent << "Alive points: " << this->AlivePoints << "\n";
+  os << indent << "Trial points: " << this->TrialPoints << "\n";
+  os << indent << "Speed constant: " << this->SpeedConstant << "\n";
+  os << indent << "Stopping value: " << this->StoppingValue << "\n";
+  os << indent << "Large Value: " << this->LargeValue << "\n";
+  os << indent << "Normalization Factor: " << this->NormalizationFactor << "\n";
+  os << indent << "Collect points: " << this->CollectPoints << "\n";
+  os << indent << "OverrideOutputInformation: " << this->OverrideOutputInformation << "\n";
+  os << indent << "OutputExtent: " << 
+    this->OutputExtent[0] << "," << 
+    this->OutputExtent[1] << "," <<
+    this->OutputExtent[2] << "," <<
+    this->OutputExtent[3] << "," <<
+    this->OutputExtent[4] << "," <<
+    this->OutputExtent[5] << "\n";
+  os << indent << "OutputSpacing: " <<
+    this->OutputSpacing[0] << "," << 
+    this->OutputSpacing[1] << "," << 
+    this->OutputSpacing[2] << "\n";
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingImageFilter::ExecuteInformation()
+{
+  vtkImageData *input = this->GetInput();
+  vtkImageData *output = this->GetOutput();
+   
+  if (input == NULL || this->OverrideOutputInformation) {
+    output->SetNumberOfScalarComponents(1);  
+    output->SetScalarType(VTK_FLOAT);
+    output->SetSpacing(this->OutputSpacing[0], 
+		       this->OutputSpacing[1], 
+		       this->OutputSpacing[2]);
+    output->SetWholeExtent(this->OutputExtent[0],this->OutputExtent[1],
+			   this->OutputExtent[2],this->OutputExtent[3],
+			   this->OutputExtent[4],this->OutputExtent[5]);
+  } else {    
+    output->CopyTypeSpecificInformation(input);
+    output->SetScalarType(VTK_FLOAT);
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingImageFilter::ComputeInputUpdateExtent( int inExt[6], 
+							      int vtkNotUsed(outExt)[6] )
+{
+  vtkImageData *input = this->GetInput();
+  // Make sure the Input has been set.
+  if ( input == NULL )
+    {
+      memcpy(inExt,this->OutputExtent,sizeof(int)*6);
+    } else {      
+      int* wholeExtent = input->GetWholeExtent();
+      memcpy(inExt,wholeExtent,sizeof(int)*6);
+    }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingImageFilter::ExecuteData(vtkDataObject *vtkNotUsed(out))
+{  
+  vtkDebugMacro("Executing.");
+  vtkImageData* output = this->GetOutput();
+  vtkImageData* input = this->GetInput();
+  
+  // Set the extent of the output and allocate memory.
+  output->SetExtent(output->GetWholeExtent());
+  output->AllocateScalars();
+
+  vtkDebugMacro("Calling SimpleExecute.");
+  this->SimpleExecute(input, output);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingImageFilter::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  this->GenerateData(input, output);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingImageFilter.h b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingImageFilter.h
new file mode 100644
index 0000000..6a12d4e
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingImageFilter.h
@@ -0,0 +1,289 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  vtkmpjFastMarchingImageFilter.h
+  
+  Marcel Jackowski, March 2005.
+  
+  This is a VTK translation of the itkFastMarchingImageFilter from the 
+  Insight Segmentation & Registration Toolkit.
+  
+  Notes: A vtkDataArray object is used to store points coordinates and values.
+         SetOutputSize has been translated into SetOutputExtent.
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+  
+=========================================================================*/
+#ifndef __vtkmpjFastMarchingImageFilter_h
+#define __vtkmpjFastMarchingImageFilter_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageSource.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkImageAccumulate.h"
+#include "vtkDataArray.h"
+#include "vtkDoubleArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+#include <queue>
+
+/** \class FastMarchingImageFilter
+ * \brief Solve an Eikonal equation using Fast Marching
+ *
+ * Fast marching solves an Eikonal equation where the speed is always
+ * non-negative and depends on the position only. Starting from an 
+ * initial position on the front, fast marching systematically moves the
+ * front forward one grid point at a time.
+ *
+ * Updates are preformed using an entropy satisfy scheme where only
+ * "upwind" neighborhoods are used. This implementation of Fast Marching
+ * uses a std::priority_queue to locate the next proper grid position to
+ * update. 
+ * 
+ * Fast Marching sweeps through N grid points in (N log N) steps to obtain
+ * the arrival time value as the front propagates through the grid.
+ *
+ * Implementation of this class is based on Chapter 8 of
+ * "Level Set Methods and Fast Marching Methods", J.A. Sethian,
+ * Cambridge Press, Second edition, 1999.
+ *
+ * This class is templated over the level set image type and the speed
+ * image type. The initial front is specified by two containers: one
+ * containing the known points and one containing the trial
+ * points. The speed function can be specified as a speed image or a
+ * speed constant. The speed image is set using the method
+ * SetInput(). If the speed image is NULL, a constant speed function
+ * is used and is specified using method the SetSpeedConstant().
+ *
+ * If the speed function is constant and of value one, fast marching results
+ * in an approximate distance function from the initial alive points.
+ * FastMarchingImageFilter is used in the ReinitializeLevelSetImageFilter
+ * object to create a signed distance function from the zero level set.
+ *
+ * The algorithm can be terminated early by setting an appropriate stopping
+ * value. The algorithm terminates when the current arrival time being
+ * processed is greater than the stopping value.
+ *
+ * There are two ways to specify the output image information 
+ * ( Extent, Spacing ): (a) it is copied directly from
+ * the input speed image or (b) it is specified by the user. Default values
+ * are used if the user does not specify all the information.
+ *
+ * The output information is computed as follows.
+ * If the speed image is NULL or if the OverrideOutputInformation is set to
+ * true, the output information is set from user specified parameters. These 
+ * parameters can be specified using methods SetOutputExtent() and SetOutputSpacing()
+ * Else if the speed image is not NULL, the output information
+ * is copied from the input speed image.
+ *
+ * Possible Improvements:
+ * In the current implemenation, std::priority_queue only allows 
+ * taking nodes out from the front and putting nodes in from the back.
+ * To update a value already on the heap, a new node is added to the heap.
+ * The defunct old node is left on the heap. When it is removed from the
+ * top, it will be recognized as invalid and not used.
+ * Future implementations can implement the heap in a different way
+ * allowing the values to be updated. This will generally require 
+ * some sift-up and sift-down functions and  
+ * an image of back-pointers going from the image to heap in order
+ * to locate the node which is to be updated.
+ *
+ * \sa LevelSetTypeDefault
+ * \ingroup LevelSetSegmentation 
+ */
+class vtkmpjFastMarchingImageFilter : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+
+  /** Enum of Fast Marching algorithm point types. FarPoints represent far
+   * away points; TrialPoints represent points within a narrowband of the
+   * propagating front; and AlivePoints represent points which have already
+   * been processed. */
+  //BTX
+  enum LabelType { FarPoint, AlivePoint, TrialPoint };
+  //ETX
+  
+  static vtkmpjFastMarchingImageFilter *New();
+  vtkTypeMacro(vtkmpjFastMarchingImageFilter,vtkpxSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Set/Get the container of Alive Points representing the initial front
+  vtkSetObjectMacro(AlivePoints, vtkDataArray);
+  vtkGetObjectMacro(AlivePoints, vtkDataArray);
+
+  // Description:
+  // Set/Get the container of Trial Points representing the initial front
+  vtkSetObjectMacro(TrialPoints, vtkDataArray);
+  vtkGetObjectMacro(TrialPoints, vtkDataArray);
+  
+  // Description:
+  // Get label image
+  vtkGetObjectMacro(LabelImage, vtkImageData);
+  
+  // Description:
+  // Set the Speed Constant. If the Speed Image is NULL,
+  // the SpeedConstant value is used for the whole level set.
+  // By default, the SpeedConstant is set to 1.0.
+  void SetSpeedConstant( double value );
+  
+  // Description:
+  // Get the Speed Constant
+  vtkGetMacro(SpeedConstant, double);
+  
+  // Set/Get the Normalization Factor for the Speed Image.
+  // The values in the Speed Image is divided by this
+  // factor. This allows the use of images with
+  // integer pixel types to represent the speed. 
+  vtkGetMacro(NormalizationFactor, double);
+  vtkSetMacro(NormalizationFactor, double);
+
+  // Description:
+  // Set/Get the Fast Marching algorithm Stopping Value. The Fast Marching
+  // algorithm is terminated when the value of the smallest trial point
+  // is greater than the stopping value.
+  vtkGetMacro(StoppingValue, double);
+  vtkSetMacro(StoppingValue, double);
+
+  // Description:
+  // Set/Get the Collect Points flag. Instrument the algorithm to collect
+  // a container of all nodes which it has visited. Useful for
+  // creating Narrowbands for level set algorithms that supports 
+  // narrow banding. 
+  vtkGetMacro(CollectPoints, int);
+  vtkSetMacro(CollectPoints, int);
+  vtkBooleanMacro(CollectPoints, int);
+  
+  // Description:
+  // Get the container of Processed Points. If the CollectPoints flag
+  // is set, the algorithm collects a container of all processed nodes.
+  // This is useful for defining creating Narrowbands for level
+  // set algorithms that supports narrow banding.
+  vtkGetObjectMacro(ProcessedPoints, vtkDoubleArray);
+
+  // Description:
+  // The output extents and spacing is computed as follows.
+  // If the speed image is NULL or if the OverrideOutputInformation is true, 
+  // the output information is set from user specified parameters. These 
+  // parameters can be specified using methods SetOutputExtent(), SetOutputSpacing().
+  // Else if the speed image is not NULL, the output information
+  // is copied from the input speed image. 
+  void SetOutputExtent(int minX, int maxX, int minY, int maxY, int minZ, int maxZ);
+  void SetOutputSpacing(double si, double sj, double sk) {
+    OutputSpacing[0]=si; OutputSpacing[1]=sj; OutputSpacing[2]=sk;
+  }
+  vtkGetVectorMacro(OutputSpacing, double, 3);
+  vtkSetVectorMacro(OutputSpacing, double, 3);
+  
+  vtkGetMacro(OverrideOutputInformation, int);
+  vtkSetMacro(OverrideOutputInformation, int);
+  vtkBooleanMacro(OverrideOutputInformation, int);
+  
+  // Description:
+  // Set/Get value for infinity
+  vtkGetMacro(LargeValue, double);
+  vtkSetMacro(LargeValue, double);
+
+ protected:
+
+  vtkDataArray *AlivePoints;
+  vtkDataArray *TrialPoints;
+  
+  vtkImageData *LabelImage;
+  
+  double SpeedConstant;
+  double InverseSpeed;
+  double StoppingValue;
+  
+  int CollectPoints;
+  vtkDoubleArray *ProcessedPoints;
+  
+  int OutputExtent[6];
+  double OutputSpacing[3];
+  int OverrideOutputInformation;
+
+  double NormalizationFactor;
+
+  double LargeValue;
+
+  //BTX
+  /** Trial points are stored in a min-heap. This allow efficient access
+   * to the trial point with minimum value which is the next grid point
+   * the algorithm processes. */
+  struct NodeType {
+    double value;
+    int index;
+    NodeType(double value, int index) { this->index=index; this->value=value; };
+  }; 
+  
+  struct NodeTypeCmp {
+    bool operator()(const NodeType* x, const NodeType* y) 
+	 const { return x->value > y->value; }
+  };
+  
+  typedef std::priority_queue<NodeType*,std::vector<NodeType *>,NodeTypeCmp> HeapType;
+  //ETX
+
+  HeapType TrialHeap;
+
+  vtkmpjFastMarchingImageFilter();
+  virtual ~vtkmpjFastMarchingImageFilter();
+  
+  void ExecuteInformation();  
+  virtual void ComputeInputUpdateExtent(int inExt[6], int outExt[6]);
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  virtual void ExecuteData(vtkDataObject *output);
+
+  virtual void Initialize(vtkImageData *output);  
+  virtual void GenerateData(vtkImageData *input, vtkImageData *output);
+  virtual void UpdateNeighbors(int index, int coord[3], vtkImageData *input, vtkImageData *output);
+  virtual double UpdateValue(int index, int coord[3], vtkImageData *input, vtkImageData *output);
+
+ private:
+  void SortThreeValues(double value[3]);
+    
+  vtkmpjFastMarchingImageFilter(const vtkmpjFastMarchingImageFilter&);// Not implemented
+  void operator=(const vtkmpjFastMarchingImageFilter&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingMethod.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingMethod.cpp
new file mode 100644
index 0000000..a6bc720
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingMethod.cpp
@@ -0,0 +1,741 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#include "vtkmpjFastMarchingMethod.h"
+#include <time.h>
+
+//------------------------------------------------------------------------------
+vtkmpjFastMarchingMethod* vtkmpjFastMarchingMethod::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjFastMarchingMethod");
+  if(ret)
+    {
+      return (vtkmpjFastMarchingMethod*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjFastMarchingMethod;
+}
+
+// Construct object with no children.
+vtkmpjFastMarchingMethod::vtkmpjFastMarchingMethod()
+{
+  this->KnownPoints = NULL;
+  this->KnownValues = 1;
+  this->SecondOrder = 0;
+  this->LabelImage = NULL;
+  this->FrontPoints = NULL;
+  this->PropagationTime = VTK_LARGE_FLOAT;
+  this->Infinity = VTK_LARGE_FLOAT;
+  this->Spacing[0] = 1.0;
+  this->Spacing[1] = 1.0;
+  this->Spacing[2] = 1.0;
+  this->queue = NULL;
+  this->label = NULL;
+  this->neighbor_index[0]=0;
+  this->neighbor_index[1]=0;
+  this->neighbor_index[2]=0;
+  this->ElapsedTime = 0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjFastMarchingMethod::~vtkmpjFastMarchingMethod()
+{
+  if (this->KnownPoints != NULL)
+    this->KnownPoints->Delete();
+  if (this->LabelImage != NULL)
+    this->LabelImage->Delete();
+  if (this->FrontPoints != NULL)
+    this->FrontPoints->Delete();
+  if (this->queue != NULL)    
+    this->queue->Delete();
+}
+
+// ----------------------------------------------------------------------------
+int vtkmpjFastMarchingMethod::GetNeighborIndex(int j)
+{
+  return this->neighbor_index[j];
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingMethod::SetSpeedImage(vtkImageData *speed)
+{
+  this->SetInput(speed);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingMethod::ExecuteInformation()
+{
+  vtkImageData *input = this->GetInput();
+  vtkImageData *output = this->GetOutput();
+   
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Speed Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  int dim[3]; input->GetDimensions(dim);
+  
+  if (this->KnownPoints==NULL) {
+    vtkErrorMacro(<<"Set of known points is empty!");
+    return;
+  }
+
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingMethod::SortTerms(double term[3], double spc[3]) 
+{
+  double tmp[3];
+  double tmp_spc[3];
+
+  if (term[0] < term[1]) {
+    if (term[0] < term[2]) {
+      if (term[1] < term[2]) {
+	tmp[0] = term[0]; tmp[1] = term[1]; tmp[2] = term[2]; 
+	tmp_spc[0] = spc[0]; tmp_spc[1] = spc[1]; tmp_spc[2] = spc[2]; 
+      } else {
+	tmp[0] = term[0]; tmp[1] = term[2]; tmp[2] = term[1]; 
+	tmp_spc[0] = spc[0]; tmp_spc[1] = spc[2]; tmp_spc[2] = spc[1]; 
+      }
+    } else 
+      {
+	tmp[0] = term[2]; tmp[1] = term[0]; tmp[2] = term[1];
+	tmp_spc[0] = spc[2]; tmp_spc[1] = spc[0]; tmp_spc[2] = spc[1];
+      }
+  } else {
+    if (term[1] < term[2]) {
+      if (term[0] < term[2]) {
+	tmp[0] = term[1]; tmp[1] = term[0]; tmp[2] = term[2];
+	tmp_spc[0] = spc[1]; tmp_spc[1] = spc[0]; tmp_spc[2] = spc[2];
+      } else {
+	tmp[0] = term[1]; tmp[1] = term[2]; tmp[2] = term[0];
+	tmp_spc[0] = spc[1]; tmp_spc[1] = spc[2]; tmp_spc[2] = spc[0];
+      }
+    } else
+      {
+	tmp[0] = term[2]; tmp[1] = term[1]; tmp[2] = term[0];
+	tmp_spc[0] = spc[2]; tmp_spc[1] = spc[1]; tmp_spc[2] = spc[0];
+      }    
+  }
+
+  term[0] = tmp[0];
+  term[1] = tmp[1];
+  term[2] = tmp[2];
+
+  spc[0] = tmp_spc[0];
+  spc[1] = tmp_spc[1];
+  spc[2] = tmp_spc[2];
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingMethod::Solve2(double a, double b, double spc[3], double rhs)
+{  
+  double amb = a - b;
+  if (fabs(amb) >= (rhs*spc[0])) {
+    return (a < b ? a : b) + rhs*spc[0];
+  } else {
+    double amb2 = amb*amb;
+    return (a+b+sqrt(2.0*rhs*rhs*spc[0]-amb2)) / 2.0;
+  }
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingMethod::SolveN(int number, double term[3], double spc[3], double rhs)
+{
+  double coeff[3] = {-rhs*rhs, 0.0, 0.0};
+  double spc2;
+
+  for (int j=0; j<3; j++) {
+    if (term[j] != VTK_LARGE_FLOAT) {
+      spc2 = spc[j];
+      coeff[2] += 1.0 / spc2;
+      coeff[1] -= (2*term[j]) / spc2;
+      coeff[0] += (term[j]*term[j]) / spc2;
+    }
+  }
+  
+  int no_solutions = 1;
+  double max_sol = VTK_LARGE_FLOAT;
+  double sol[2] = {VTK_LARGE_FLOAT, VTK_LARGE_FLOAT};
+  double discr = coeff[1]*coeff[1] - 4.0*coeff[2]*coeff[0];
+  
+  if (discr < 0) {
+    printf("Solution is not differentiable! terms=%f, %f, %f, coeffs=%f, %f, %f\n", term[0], term[1], term[2], coeff[2], coeff[1], coeff[0]);
+  }
+  
+  // solve quadratic equation
+  vtkMath::SolveQuadratic(coeff[2], coeff[1], coeff[0], 
+			  &sol[0], &sol[1], &no_solutions);
+  if (no_solutions == 2) {
+    max_sol = sol[0]>=sol[1]?sol[0]:sol[1];
+  } else {
+    max_sol = sol[0];
+  }
+  
+  return max_sol;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingMethod::RegularSolve(double coeff[3])
+{ 
+  int no_solutions = 1;
+  double max_sol = VTK_LARGE_FLOAT;
+  double sol[2] = {VTK_LARGE_FLOAT, VTK_LARGE_FLOAT};
+  double discr = coeff[1]*coeff[1] - 4.0*coeff[2]*coeff[0];
+  
+  if (discr < 0) {
+    printf("Solution is not differentiable! coeffs=%f, %f, %f\n",coeff[2], coeff[1], coeff[0]);
+  }
+  
+  // solve quadratic equation
+  vtkMath::SolveQuadratic(coeff[2], coeff[1], coeff[0], 
+			  &sol[0], &sol[1], &no_solutions);
+  if (no_solutions == 2) {
+    max_sol = sol[0]>=sol[1]?sol[0]:sol[1];
+  } else {
+    max_sol = sol[0];
+  }
+  
+  return max_sol;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingMethod::SolveQuadratic(int number, double term[3], double spc[3], double rhs)
+{  
+  double result;
+  
+  switch(number) {
+  case 1:
+    //result = term[0] + rhs*spc[0];
+    //break;
+    // case 2:
+    //result = Solve2(term[0], term[1], spc, rhs);
+    //break;
+  case 3:
+  default:
+    //if ((term[0] + rhs*spc[0]) > term[1]) {
+    //result = term[0] + rhs*spc[0];      
+    //} else {
+    //result = Solve2(term[0], term[1], spc, rhs);
+    //}
+    //if (result > term[2])
+      result = SolveN(number, term, spc, rhs);
+    break;
+  };
+      
+  return(result);
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingMethod::ComputeSpeed(vtkImageData *input, vtkImageData *output, 
+					      int coord[3], int index)
+{
+  vtkDataArray *in = input->GetPointData()->GetScalars();
+  return in->GetComponent(index, 0);
+}
+
+// ----------------------------------------------------------------------------
+// double vtkmpjFastMarchingMethod::ComputeFirstOrder(vtkImageData *input, vtkImageData *output,
+// 						  int coord[3], int index)
+// {
+//   int dim[3]; input->GetDimensions(dim);
+//   double spc[3]; input->GetSpacing(spc);
+//   int dim0Tdim1 = dim[0]*dim[1];
+//   int factor[3] = {1, dim[0], dim0Tdim1};
+//   vtkDataArray *in = input->GetPointData()->GetScalars(); 
+//   vtkDataArray *out = output->GetPointData()->GetScalars();
+  
+//   // get speed value
+//   double F = this->ComputeSpeed(input, output, coord, index);
+  
+//   if (F == 0.0) 
+//     return VTK_LARGE_FLOAT;
+    
+//   int num_terms = 0;
+//   double term[3];
+  
+//   // process each one of the six neighbors
+//   for (int j=0; j<3; j++) { // axis  
+    
+//     term[j] = VTK_LARGE_FLOAT;
+    
+//     for (int i=-1; i<2; i+=2) { // direction 
+//       if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  
+	
+// 	int neighbor=index + i*factor[j];
+	
+// 	// if value is frozen get its time
+// 	if (this->label->GetComponent(neighbor, 0) == VTK_MPJ_FROZEN) {
+	  
+// 	  double time = (double)out->GetComponent(neighbor, 0);
+	  
+// 	  if (time < term[j]) {
+// 	    term[j] = time;
+// 	    this->neighbor_index[j] = neighbor;
+// 	  }
+	  
+// 	} // if
+//       } // if
+      
+      
+//     } // for direction 
+    
+//     term[j] /= spc[j];
+
+//     // accumulate number of quadratic terms
+//     num_terms += (term[j] != VTK_LARGE_FLOAT);
+    
+//   } // for axis
+  
+//   // sort terms
+//   /this->SortTerms(term);
+
+//   // solve quadratic for maximum solution
+//   double solution = this->SolveQuadratic(num_terms, term, 1.0 / F);   // this->Spacing / F
+
+//   return solution;
+// }
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingMethod::ComputeFirstOrder(vtkImageData *input, vtkImageData *output,
+						  int coord[3], int index)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *in = input->GetPointData()->GetScalars(); 
+  vtkDataArray *out = output->GetPointData()->GetScalars();
+  
+  // get speed value
+  double F = this->ComputeSpeed(input, output, coord, index);
+  
+  if (F == 0.0) 
+    return this->Infinity;//VTK_LARGE_FLOAT;
+    
+  int num_terms = 0;
+  double term[3];
+  double rhs = 1.0 / F;
+  double spc[3] = {this->Spacing[0],this->Spacing[1],this->Spacing[2]};
+  double coeff[3] = {-rhs*rhs, 0, 0};
+
+  // process each one of the six neighbors
+  for (int j=0; j<3; j++) { // axis  
+    
+    term[j] = VTK_LARGE_FLOAT;
+    
+    for (int i=-1; i<2; i+=2) { // direction 
+      if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  
+	
+	int neighbor=index + i*factor[j];
+	
+	// if value is frozen get its time
+	if (this->label->GetComponent(neighbor, 0) == VTK_MPJ_FROZEN) {
+	  
+	  double time = (double)out->GetComponent(neighbor, 0);
+	  
+	  if (time < term[j]) {
+	
+	    term[j] = time;	    
+	    this->neighbor_index[j] = neighbor;
+	    
+	  }	  
+	} // if
+      } // if
+      
+      
+    } // for direction 
+    
+    double value1 = term[j];
+    //double spc2 = this->Spacing[j] * this->Spacing[j];
+    
+    num_terms += (value1 != VTK_LARGE_FLOAT);
+    
+    //if (value1 != VTK_LARGE_FLOAT) {
+    //coeff[2] += 1 / spc2;
+    // coeff[1] -= (2*value1) / spc2;
+    //coeff[0] += (value1*value1) / spc2;
+    //}
+    
+  } // for axis
+    
+  // solve quadratic for maximum solution
+  this->SortTerms(term, spc);
+  
+  //for(int j=0;j<3;j++) {  
+  //double value1 = term[j];
+  //double spc2 = spc[j] * spc[j];    
+  //if (value1 != VTK_LARGE_FLOAT) {
+  //  coeff[2] += 1 / spc2;
+  //  coeff[1] -= (2*value1) / spc2;
+  //  coeff[0] += (value1*value1) / spc2;
+  //}
+  //}
+
+  double solution = this->SolveQuadratic(num_terms, term, spc, 1.0 / F);  
+
+  // this->Spacing / F;
+  //double solution = this->RegularSolve(coeff);
+
+  return solution;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingMethod::ComputeSecondOrder(vtkImageData *input, vtkImageData *output,
+						    int coord[3], int index)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *in = input->GetPointData()->GetScalars(); 
+  vtkDataArray *out = output->GetPointData()->GetScalars();
+  
+  // get speed value
+  double F = this->ComputeSpeed(input, output, coord, index);
+
+  if (F == 0.0) 
+    return this->Infinity;//VTK_LARGE_FLOAT;
+    
+  int num_terms = 0;
+  int num_2ndterms = 0;
+  double term[3], term2[3];
+  double spc[3] = {this->Spacing[0],this->Spacing[1],this->Spacing[2]};
+  double value1, value2;
+  double rhs = 1.0 / F;
+  double coeff[3] = {-rhs*rhs, 0, 0};
+  
+  // process each one of the six neighbors
+  for (int j=0; j<3; j++) { // axis  
+    
+    value1 = VTK_LARGE_FLOAT;
+    value2 = VTK_LARGE_FLOAT;
+    
+    for (int i=-1; i<2; i+=2) { // direction 
+      if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  
+	
+	int neighbor=index + i*factor[j];
+	
+	// if value is frozen get its time
+	if (this->label->GetComponent(neighbor, 0) == VTK_MPJ_FROZEN) {
+	  
+	  double tmp1 = (double)out->GetComponent(neighbor, 0);
+	  
+	  if (tmp1 < value1) {
+	    
+	    term[j] = value1 = tmp1;
+	    
+	    this->neighbor_index[j] = neighbor;
+	    
+	    // examine 2nd order neighbor
+	    if ((coord[j]+2*i)>=0 && (coord[j]+2*i)<dim[j]) {
+	      
+	      // pick 2nd order neighbor
+	      int neighbor2=index + 2*i*factor[j];
+	      
+	      // read time
+	      double tmp2 = (double)out->GetComponent(neighbor2, 0);
+	      
+	      if ((this->label->GetComponent(neighbor2, 0) == VTK_MPJ_FROZEN) && (tmp2 <= tmp1)) 
+		value2 = tmp2;
+	      else
+		value2 = VTK_LARGE_FLOAT;
+	    } // if ((coord
+	  }	  		  
+	} // if
+      } // if 
+      
+    } // direction
+    
+    double spc2 = this->Spacing[j] * this->Spacing[j];
+    
+    if (value2 != VTK_LARGE_FLOAT) {
+      
+      num_2ndterms++;
+      
+      double tp = (1.0/3.0)*(4.0*value1-value2);
+      double a = 9.0/4.0;
+      
+      coeff[2] += a / spc2;
+      coeff[1] -= (2*a*tp) / spc2;
+      coeff[0] += (a*tp*tp) / spc2;
+      
+    } else  
+      if (value1 != VTK_LARGE_FLOAT) {
+	
+	num_terms++;
+
+	coeff[2] += 1 / spc2;
+	coeff[1] -= (2*value1) / spc2;
+	coeff[0] += (value1*value1) / spc2;
+      }
+    
+  } // for axis
+  
+  double solution;
+
+  // solve quadratic for maximum solution
+  solution = this->RegularSolve(coeff);
+  
+  return solution;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingMethod::ComputeTime(vtkImageData *input, vtkImageData *output,
+					     int coord[3], int index)
+{
+  double time;
+
+  // compute time of arrival at neighbor
+  if (this->SecondOrder == 0)
+    time = this->ComputeFirstOrder(input, output, coord, index);
+  else 
+    time = this->ComputeSecondOrder(input, output, coord, index);
+  
+  // insert neighbor in the narrow band
+  if (this->label->GetComponent(index, 0) != VTK_MPJ_NARROW_BAND) {
+    this->label->SetComponent(index, 0, VTK_MPJ_NARROW_BAND);
+    this->queue->Insert(time, index);
+  } else {
+    // if already in the narrow band, store new time
+    this->queue->DeleteId(index);
+    this->queue->Insert(time, index);
+  }
+
+  return time;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingMethod::InitializeFront(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  // Create priority queue
+  this->queue = vtkmpjPriorityQueue::New();
+  this->queue->Allocate(1000);
+
+  // Create label image
+  this->LabelImage = vtkImageData::New();
+  this->LabelImage->SetSpacing(input->GetSpacing());
+  this->LabelImage->SetOrigin(input->GetOrigin());
+  this->LabelImage->SetDimensions(input->GetDimensions());
+  this->LabelImage->SetScalarType(VTK_SHORT);
+  this->LabelImage->SetNumberOfScalarComponents(1);
+  this->LabelImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->LabelImage->AllocateScalars();
+  this->label = this->LabelImage->GetPointData()->GetScalars();
+  this->label->FillComponent(0, VTK_MPJ_UNVISITED);
+
+  out->FillComponent(0, this->Infinity);
+  
+  int index, coord[3], ncoord[3];
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  // Freeze known points
+  int num_known = this->KnownPoints->GetNumberOfTuples();
+  for(int i=0; i<num_known; i++) {
+    
+    coord[0] = ncoord[0] = (int)this->KnownPoints->GetComponent(i, 0);
+    coord[1] = ncoord[1] = (int)this->KnownPoints->GetComponent(i, 1);
+    coord[2] = ncoord[2] = (int)this->KnownPoints->GetComponent(i, 2);
+    float value = this->KnownPoints->GetComponent(i, 3);
+    
+    index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+    
+    this->label->SetComponent(index, 0, VTK_MPJ_FROZEN);   // Freeze voxel
+
+    out->SetComponent(index, 0, this->KnownValues ? value : 0.0);              
+    
+    this->count++;
+  }
+
+  // Process boundary neighbors
+  for(int i=0; i<this->KnownPoints->GetNumberOfTuples(); i++) {
+  
+    coord[0] = ncoord[0] = (int)KnownPoints->GetComponent(i, 0);
+    coord[1] = ncoord[1] = (int)KnownPoints->GetComponent(i, 1);
+    coord[2] = ncoord[2] = (int)KnownPoints->GetComponent(i, 2);
+    index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+
+    // process each one of the six neighbors
+    for (int j=0; j<3; j++) { // axis  
+      for (int i=-1; i<2; i+=2)  { // direction	  	
+	
+	if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  	    
+	  
+	  int neighbor=index + i*factor[j];
+	  ncoord[j] = coord[j] + i;   // update coordinate
+	  
+	  // compute arrival time
+	  if (this->label->GetComponent(neighbor, 0) != VTK_MPJ_FROZEN)
+	    this->ComputeTime(input, output, ncoord, neighbor);
+	  
+	  ncoord[j] = coord[j]; // reset
+	}
+      }
+    }
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingMethod::PropagateFront(vtkImageData *input, vtkImageData *output)
+{
+  double time;
+  int index, coord[3], ncoord[3];
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  while ((index = this->queue->Pop(time, 0)) != -1) {
+    
+    this->label->SetComponent(index, 0, VTK_MPJ_FROZEN);    
+    out->SetComponent(index, 0, (float)time);
+
+    this->count++;
+    if (this->count==this->tenth)
+      {
+	this->pog+=0.1;
+	this->UpdateProgress(this->pog);
+	this->count=0;
+      }
+    
+    // stop if arrival time is greater or equal to max time
+    if ((time == VTK_LARGE_FLOAT) || 
+	(this->PropagationTime != VTK_LARGE_FLOAT) && (time >= this->PropagationTime)) {
+      break;
+    }
+
+    // decompose index into x, y, z coordinates
+    coord[2] = ncoord[2] = index / dim0Tdim1; 
+    int r = index % dim0Tdim1;
+    coord[1] = ncoord[1] = r / dim[0];
+    coord[0] = ncoord[0] = r % dim[0];
+    
+    //    if (time == VTK_LARGE_FLOAT) {
+      /*printf("%d %d %d\n",coord[0],coord[1],coord[2]);*/
+      //continue;
+    //}
+    
+    // process each one of the six neighbors
+    for (int j=0; j<3; j++)  // axis  
+      for (int i=-1; i<2; i+=2)  { // direction 
+	
+	if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  
+	  int neighbor=index + i*factor[j];
+	  
+	  if (this->label->GetComponent(neighbor, 0) != VTK_MPJ_FROZEN) { 
+	   
+	    ncoord[j] = coord[j] + i;   // update coordinate
+
+	    this->ComputeTime(input, output, ncoord, neighbor);
+
+	    ncoord[j] = coord[j]; // reset
+	  }	  
+	}
+      }
+    } // while  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingMethod::SaveFrontPoints(vtkImageData *input)
+{
+  int total = this->queue->GetNumberOfItems();
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int index, coord[3];
+  double value;
+  
+  if (this->FrontPoints != NULL) 
+    this->FrontPoints->Delete();
+  
+  this->FrontPoints = vtkFloatArray::New(); 
+  this->FrontPoints->SetNumberOfComponents(4);
+  
+  for(int j=0; j<total; j++) {
+    
+    // get point index
+    index = queue->Peek(value, j);
+    
+    // decompose index
+    coord[2] = index / dim0Tdim1; 
+    int r = index % dim0Tdim1;
+    coord[1] = r / dim[0];
+    coord[0] = r % dim[0];
+    
+    // insert point
+    this->FrontPoints->InsertNextTuple4((float)coord[0], (float)coord[1], (float)coord[2], 
+					(float)value);
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingMethod::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  
+  if (this->GetInput()==NULL) {
+    vtkErrorMacro(<<"No Speed Image\n Exiting\n");
+    return;
+  }
+  
+  int total = input->GetPointData()->GetScalars()->GetNumberOfTuples();  
+  this->pog = 0.0;  
+  this->tenth = (int)(total / 10.0);
+  this->count = 0;
+  
+  this->UpdateProgress(0.01);
+
+  clock_t start = clock();
+
+  // initialize
+  this->InitializeFront(input, output);  
+  
+  // propagate front
+  this->PropagateFront(input, output);
+
+  clock_t end = clock();
+
+  this->ElapsedTime = (end-start)/(double)CLOCKS_PER_SEC;
+
+  //printf("time1=%f\n",end-start);
+  //  printf("time=%f\n",(end-start)/(double)CLOCKS_PER_SEC);
+
+  // save front points
+  this->SaveFrontPoints(input);
+
+  this->UpdateProgress(1.0);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingMethod.h b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingMethod.h
new file mode 100644
index 0000000..b40d2b1
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingMethod.h
@@ -0,0 +1,159 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/* 
+  -- vtkmpjFastMarchingMethod.h --
+   
+  Implements Sethian's Fast Marching Method on 3D uniform lattice domains.
+
+  Solves the Eikonal equation |grad(T)| = h / F, where T is the
+  arrival time of the front, F is the speed and h is the grid
+  spacing.
+
+  Marcel Jackowski, May 2003.
+*/
+
+
+#ifndef __vtkmpjFastMarchingMethod_h
+#define __vtkmpjFastMarchingMethod_h
+
+#include "vtkObjectFactory.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkmpjPriorityQueue.h"
+#include "vtkImageAccumulate.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+
+#define VTK_MPJ_FROZEN       -1     
+#define VTK_MPJ_NARROW_BAND   0
+#define VTK_MPJ_UNVISITED    +1
+
+class vtkmpjFastMarchingMethod : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjFastMarchingMethod *New();
+  vtkTypeMacro(vtkmpjFastMarchingMethod,vtkpxSimpleImageToImageFilter);
+  
+  // Description: Sets speed image
+  void SetSpeedImage(vtkImageData *speed);
+
+  // Description:
+  // Set/Get boundary conditions for the propagation
+  vtkSetObjectMacro(KnownPoints, vtkFloatArray);
+  vtkGetObjectMacro(KnownPoints, vtkFloatArray);
+
+  // Description:
+  // Turn on/off values for known points
+  vtkGetMacro(KnownValues,int);
+  vtkSetClampMacro(KnownValues,int,0,1);
+  vtkBooleanMacro(KnownValues,int);
+
+  // Description:
+  // Set/Get maximum propagation time
+  vtkGetMacro(PropagationTime,float);
+  vtkSetMacro(PropagationTime,float);
+
+  // Description:
+  // Set/Get infinity value
+  vtkGetMacro(Infinity,float);
+  vtkSetMacro(Infinity,float);
+
+  // Description:
+  // Set/Get grid spacing
+  vtkGetVectorMacro(Spacing,double,3);
+  vtkSetVectorMacro(Spacing,double,3);
+  
+  // Description:
+  // Set/Get grid accuracy of the solution
+  vtkGetMacro(SecondOrder,int);
+  vtkSetMacro(SecondOrder,int);
+  vtkBooleanMacro(SecondOrder,int);
+
+  // Front label image. Points interior to the front have value -1, points 
+  // on the front boundary have value 0, and points outside have value +1.
+  vtkGetObjectMacro(LabelImage, vtkImageData);
+  
+  // Return an array containing front point vertices and their values
+  vtkGetObjectMacro(FrontPoints, vtkFloatArray);
+  
+  // Return the filter's elapsed time
+  vtkGetMacro(ElapsedTime, double);
+
+
+ protected:
+  double Spacing[3];
+  float PropagationTime;
+  double Infinity;
+  double ElapsedTime;
+  int KnownValues;  
+  int SecondOrder;
+  vtkImageData *Speed;
+  vtkImageData *LabelImage;
+  vtkFloatArray *KnownPoints;
+  vtkFloatArray *FrontPoints;
+
+  vtkDataArray *label;
+  vtkmpjPriorityQueue *queue;     
+
+  vtkmpjFastMarchingMethod();
+  virtual ~vtkmpjFastMarchingMethod();
+  
+  void ExecuteInformation();  
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  virtual void InitializeFront(vtkImageData *input, vtkImageData *output);
+  virtual void PropagateFront(vtkImageData *input, vtkImageData *output);
+  virtual void SaveFrontPoints(vtkImageData *input);  
+  virtual double ComputeSpeed(vtkImageData *input, vtkImageData *output, int coord[3], int index);
+  virtual double ComputeFirstOrder(vtkImageData *input, vtkImageData *output, int coord[3], int index);
+  virtual double ComputeSecondOrder(vtkImageData *input, vtkImageData *output, int coord[3], int index);
+  
+  int GetNeighborIndex(int j);
+  void SortTerms(double term[3], double spc[3]);
+  double Solve2(double a, double b, double spc[3], double rhs);
+  double SolveN(int number, double term[3], double spc[3], double rhs);
+  double RegularSolve(double coeff[3]);
+  double SolveQuadratic(int number, double term[3], double spc[3], double rhs);
+  
+  double ComputeTime(vtkImageData *input, vtkImageData *output,
+		     int coord[3], int index);  
+ private:
+  //BTX
+  float pog;
+  int count, tenth; 
+  int neighbor_index[3];
+  //ETX
+  
+  vtkmpjFastMarchingMethod(const vtkmpjFastMarchingMethod&);// Not implemented
+  void operator=(const vtkmpjFastMarchingMethod&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingVesselConnectivity.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingVesselConnectivity.cpp
new file mode 100644
index 0000000..38d79b4
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingVesselConnectivity.cpp
@@ -0,0 +1,786 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjFastMarchingVesselConnectivity.h"
+
+#define VTK_MPJ_LARGE_DOUBLE 32767
+
+#ifndef VTK_MPJ_SIGN
+#define VTK_MPJ_SIGN(x) (x < 0 ? -1 : (x > 0 ? 1 : 0))
+#endif
+
+//------------------------------------------------------------------------------
+vtkmpjFastMarchingVesselConnectivity* vtkmpjFastMarchingVesselConnectivity::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjFastMarchingVesselConnectivity");
+  if(ret)
+    {
+      return (vtkmpjFastMarchingVesselConnectivity*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjFastMarchingVesselConnectivity;
+}
+
+// Construct object with no children.
+vtkmpjFastMarchingVesselConnectivity::vtkmpjFastMarchingVesselConnectivity()
+{ 
+  this->Mask = NULL;
+  this->KnownPoints = NULL;
+  this->KnownValues = 1;
+  this->LabelImage = NULL;
+  this->FrontPoints = NULL;
+  this->PropagationTime = VTK_MPJ_LARGE_DOUBLE;
+  this->Spacing[0] = 1.0;
+  this->Spacing[1] = 1.0;
+  this->Spacing[2] = 1.0;
+  this->queue = NULL;
+  this->label = NULL;
+  this->Infinity = 32767;
+  this->MaxIntensity = 100;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjFastMarchingVesselConnectivity::~vtkmpjFastMarchingVesselConnectivity()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+  if (this->KnownPoints != NULL)
+    this->KnownPoints->Delete();
+  if (this->LabelImage != NULL)
+    this->LabelImage->Delete();
+  if (this->FrontPoints != NULL)
+    this->FrontPoints->Delete();
+  if (this->queue != NULL)    
+    this->queue->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingVesselConnectivity::SetSpeedImage(vtkImageData *speed)
+{
+  this->SetInput(speed);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingVesselConnectivity::ExecuteInformation()
+{
+  vtkImageData *input = this->GetInput();
+  vtkImageData *output = this->GetOutput();
+   
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Speed Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  int dim[3]; input->GetDimensions(dim);
+  
+  if (this->KnownPoints==NULL) {
+    vtkErrorMacro(<<"Set of known points is empty!");
+    return;
+  }
+
+  printf("dims=%d %d %d\n", dim[0],dim[1],dim[2]);
+
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_DOUBLE);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+int vtkmpjFastMarchingVesselConnectivity::InMask(int index)
+{
+  return (this->mask != NULL)?(this->mask->GetComponent(index, 0) > 0) : 1;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingVesselConnectivity::PrintMatrix3x3(char *title, double M[3][3])
+{
+  printf("%s",title);
+  printf("%f %f %f\n",M[0][0],M[0][1],M[0][2]);
+  printf("%f %f %f\n",M[1][0],M[1][1],M[1][2]);
+  printf("%f %f %f\n",M[2][0],M[2][1],M[2][2]);
+  printf("===============================\n");
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingVesselConnectivity::SortTerms(double term[3]) 
+{
+  double tmp[3];
+
+  if (term[0] < term[1]) {
+    if (term[0] < term[2]) {
+      if (term[1] < term[2]) {
+	tmp[0] = term[0]; tmp[1] = term[1]; tmp[2] = term[2]; 
+      } else {
+	tmp[0] = term[0]; tmp[1] = term[2]; tmp[2] = term[1]; 
+      }
+    } else 
+      {
+	tmp[0] = term[2]; tmp[1] = term[0]; tmp[2] = term[1];
+      }
+  } else {
+    if (term[1] < term[2]) {
+      if (term[0] < term[2]) {
+	tmp[0] = term[1]; tmp[1] = term[0]; tmp[2] = term[2];
+      } else {
+	tmp[0] = term[1]; tmp[1] = term[2]; tmp[2] = term[0];
+      }
+    } else
+      {
+	tmp[0] = term[2]; tmp[1] = term[1]; tmp[2] = term[0];
+      }    
+  }
+
+  term[0] = tmp[0];
+  term[1] = tmp[1];
+  term[2] = tmp[2];
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingVesselConnectivity::Solve2(double a, double b, double rhs)
+{  
+  double amb = a - b;
+  if (fabs(amb) >= rhs) {
+    return (a < b ? a : b) + rhs;
+  } else {
+    double amb2 = amb*amb;
+    return (a+b+sqrt(2.0*rhs*rhs-amb2)) / 2.0;
+  }
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingVesselConnectivity::SolveN(int number, double term[3], double rhs)
+{
+  double coeff[3] = {-rhs*rhs, 0.0, 0.0};
+
+  for (int j=0; j<3; j++) {
+    if (term[j] != (double)VTK_MPJ_LARGE_DOUBLE) {
+      coeff[2] += 1.0;
+      coeff[1] -= 2*term[j];
+      coeff[0] += term[j]*term[j];
+    }
+  }
+  
+  int no_solutions = 1;
+  double max_sol = (double)VTK_MPJ_LARGE_DOUBLE;
+  double sol[2] = {(double)VTK_MPJ_LARGE_DOUBLE, (double)VTK_MPJ_LARGE_DOUBLE};
+  double discr = coeff[1]*coeff[1] - 4.0*coeff[2]*coeff[0];
+  
+  if (discr < 0) {
+    printf("Solution is not differentiable! terms=%f, %f, %f, coeffs=%f, %f, %f\n", term[0], term[1], term[2], coeff[2], coeff[1], coeff[0]);
+  }
+  
+  // solve quadratic equation
+  vtkMath::SolveQuadratic(coeff[2], coeff[1], coeff[0], &sol[0], &sol[1], &no_solutions);
+  if (no_solutions == 2) {
+    max_sol = sol[0]>=sol[1]?sol[0]:sol[1];
+  } else {
+    max_sol = sol[0];
+  }
+  
+  return max_sol;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingVesselConnectivity::SolveQuadratic(int number, double term[3], double rhs)
+{  
+  double result;
+  
+  switch(number) {
+  case 1:
+    result = term[0] + rhs;
+    break;
+  case 2:
+    result = Solve2(term[0], term[1], rhs);
+    break;
+  case 3:
+  default:
+    if ((term[0] + rhs) > term[1]) {
+      result = term[0] + rhs;      
+    } else {
+      result = Solve2(term[0], term[1], rhs);
+    }
+    if (result > term[2])
+      result = SolveN(number, term, rhs);
+    break;
+  };
+      
+  return(result);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingVesselConnectivity::ComputeNormal(vtkImageData *input, vtkImageData *output, 
+					     int coord[3], int index, double result[3])
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  //vtkDataArray *in = input->GetPointData()->GetScalars(); 
+  //vtkDataArray *out = output->GetPointData()->GetScalars();
+  
+  double normal[3];
+  result[0]=normal[0]=0.0;
+  result[1]=normal[1]=0.0;
+  result[2]=normal[2]=0.0;
+  
+  // process each one of the 26 neighbors
+  //int count = 0;
+  for(int i=-1;i<2;i++)
+    for(int j=-1;j<2;j++)
+      for(int k=-1;k<2;k++) {
+	if ((coord[0]+i)>=0 && ((coord[0]+i)<dim[0]) &&
+	    (coord[1]+j)>=0 && ((coord[1]+j)<dim[1]) &&
+	    (coord[2]+k)>=0 && ((coord[2]+k)<dim[2]))
+	  {	  	    
+	    int neighbor=index + i*factor[0] + j*factor[1] + k*factor[2];
+	    if (this->InMask(neighbor) && this->label->GetComponent(neighbor, 0) == (double)VTK_MPJ_FROZEN) {
+	      normal[0]+=i; normal[1]+=j; normal[2]+=k;	      
+	    }
+	  }	
+      }
+  
+  result[0]=normal[0];
+  result[1]=normal[1];
+  result[2]=normal[2];
+  
+  (void) vtkMath::Normalize(result);  
+
+  //printf("normal at %d is [%f,%f,%f], [%f,%f,%f]\n",index,result[0],result[1],result[2],normal[0],normal[1],normal[2]);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingVesselConnectivity::Jacobi3x3(double a[3][3], double w[3], double v[3][3])
+{
+  double **aa = new double *[3]; /* allocate space for tensor matrix */
+  aa[0] = new double[3];
+  aa[1] = new double[3];
+  aa[2] = new double[3];
+   
+  double **vv = new double *[3]; /* allocate space for eigenvector matrix */
+  vv[0] = new double[3];
+  vv[1] = new double[3];
+  vv[2] = new double[3];
+  
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++) 
+      aa[i][j] = a[i][j];
+
+  // call the real method
+  (void) vtkMath::Jacobi(aa,w,vv);
+
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++) 
+      v[i][j] = vv[i][j];
+
+  // free aa
+  delete[] aa[0];
+  delete[] aa[1];
+  delete[] aa[2];
+  delete[] aa;
+   
+  delete[] vv[0];
+  delete[] vv[1];
+  delete[] vv[2];
+  delete[] vv;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingVesselConnectivity::SortEigenvectors(double w[3], double V[3][3])
+{
+  int i, j, k;
+  double tmp, tmp2;
+  
+  // sort eigenfunctions by decreasing magnitude
+  for (j=0; j<3; j++)
+    {
+      k = j;
+      tmp = w[k];
+      tmp2 = fabs(tmp);
+      for (i=j; i<3; i++)
+        {
+          if (fabs(w[i]) < tmp2)
+            {
+              k = i;
+              tmp = w[k];
+              tmp2 = fabs(tmp);
+            }
+        }
+      if (k != j)
+        {
+          w[k] = w[j];
+          w[j] = tmp;
+          for (i=0; i<3; i++)
+            {
+              tmp = V[i][j];
+              V[i][j] = V[i][k];
+              V[i][k] = tmp;
+            }
+        }
+    }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingVesselConnectivity::NormalizeTensor3x3(double T[3][3], double W[3], double V[3][3], double N[3][3])
+{
+  double R[3][3], S[3][3];
+  double D[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
+
+  // diagonalize tensor
+  vtkMath::Diagonalize3x3(T,W,V);
+  //this->Jacobi3x3(T,W,V);
+ 
+  // sort eigenvectors by decreasing absolute magnitude
+  this->SortEigenvectors(W,V);
+  
+  // force eigenvalues be positive
+  //for (int i=0; i<3; i++) {
+  //if (W[i] < 0) {
+  //  V[0][i] = -V[0][i];
+  //  V[1][i] = -V[1][i];
+  //  V[2][i] = -V[2][i];
+  //  W[i] = -W[i];
+  //}
+  //}
+
+  // make tensor unit size
+  //D[0][0] = 1.0*VTK_MPJ_SIGN(W[0]); 
+  //D[1][1] = fabs(W[1]/W[0])*VTK_MPJ_SIGN(W[1]);  
+  //D[2][2] = fabs(W[2]/W[0])*VTK_MPJ_SIGN(W[2]);
+
+  //printf("W=%f, %f, %f, D=%f, %f, %f\n",W[0],W[1],W[2],D[0][0],D[1][1],D[2][2]);
+
+  // normalized tensor = V * D * V' 
+  //(void) vtkMath::Transpose3x3(V,R);
+  //(void) vtkMath::Multiply3x3(D,R,S);
+  //(void) vtkMath::Multiply3x3(V,S,N);
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingVesselConnectivity::ComputeWeight(double value, double max, 
+							   double steepness, double center)
+{
+  // compute weight
+  return (1.0 / ( (1.0 / max) + exp(-steepness * (value - center))));
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingVesselConnectivity::ComputeSpeed(vtkImageData *input, vtkImageData *output, 
+							  int parent, int coord[3], int index, 
+							  double normal[3])
+{
+  vtkDataArray *in = input->GetPointData()->GetScalars();
+
+  double result;
+  
+  double T[3][3], N[3][3];
+  double V[3][3], V0[3];
+  double W[3]; 
+
+  double eps=1E-12;
+
+  T[0][0] = in->GetComponent(index, 0);           /* Dxx */
+  T[1][0] = T[0][1] = in->GetComponent(index, 1); /* Dxy */
+  T[2][0] = T[0][2] = in->GetComponent(index, 2); /* Dxz */
+  T[1][1] =  in->GetComponent(index, 3);          /* Dyy */
+  T[2][1] = T[1][2] = in->GetComponent(index, 4); /* Dyz */
+  T[2][2] = in->GetComponent(index, 5);           /* Dzz */
+
+  // diagonalize and normalize tensor 
+  this->NormalizeTensor3x3(T,W,V,N);
+  
+  // if eigenvalues are all zero, return 0
+  if (fabs(W[0])<eps && fabs(W[1])<eps && fabs(W[2])<eps) {
+    return 1E-6;
+  }
+  
+  // get major eigenvector
+  V0[0] = V[0][0]; 
+  V0[1] = V[1][0]; 
+  V0[2] = V[2][0];
+  
+  double p = normal[0];
+  double q = normal[1];
+  double r = normal[2];
+  double grad = p*p + q*q + r*r;
+  
+  //if (W[2] == 0.0)
+  //this->PrintMatrix3x3("N=",V);  
+
+  //double diff = (p*p*T[0][0]+q*q*T[1][1]+r*r*T[2][2]+2*p*q*T[0][1]+2*p*r*T[0][2]+2*q*r*T[1][2]);  
+  //double diff = (p*p*T[0][0]+q*q*T[1][1]+r*r*T[2][2]+2*p*q*T[0][1]+2*p*r*T[0][2]+2*q*r*T[1][2]);
+  //double ndiff = (p*p*N[0][0]+q*q*N[1][1]+r*r*N[2][2]+2*p*q*N[0][1]+2*p*r*N[0][2]+2*q*r*N[1][2]);
+  //  printf("W=%f, %f, %f; diff=%f, ndiff=%f, true=%f\n",W[0],W[1],W[2],diff,ndiff,1-fabs(ndiff));
+
+  double diff = p*V0[0] + q*V0[1] + r*V0[2];
+
+  //printf("diff=%f\n",diff);
+
+  //if (fabs(diff) > 1e-12) 
+  // diff = log(1.0 / fabs(diff));
+  //else 
+  //diff = this->Infinity;
+   
+
+  //printf("diff=%f\n",diff);
+
+  //double diff = (p*p*N[0][0]+q*q*N[1][1]+r*r*N[2][2]+2*p*q*N[0][1]+2*p*r*N[0][2]+2*q*r*N[1][2]);
+  //double ndiff = diff / (grad+eps);  
+  //result = sqrt(grad) * FA*FA * exp(ndiff * ndiff);
+  // latest:
+  //result = FA * FA * (diff / sqrt(grad + eps));
+  
+  double Alpha = 0.5;
+  double Beta = 0.5; 
+  double Gamma = 0.25 * this->MaxIntensity;
+  
+  double Ra = fabs(W[1]/W[2]);
+  double Rb = fabs(W[0]/sqrt(fabs(W[1]*W[2])));
+  double Rs = sqrt(W[0]*W[0] + W[1]*W[1] + W[2]*W[2]);
+
+  //printf("W[0]=%f, W[1]=%f, W[2]=%f, Ra=%f,Rb=%f,Rc=%f\n",W[0],W[1],W[2],Ra,Rb,Rs);
+  
+  double a2=-1.0/(Alpha*Alpha*2.0);
+  double b2=-1.0/(Beta*Beta*2.0);
+  double c2=-1.0/(Gamma*Gamma*2.0);
+  
+  double vessel;
+  
+  if (W[1] > eps || W[2] > eps) {
+    vessel = 0.0;
+  } else {  
+    vessel = (1.0-exp(Ra*Ra*a2));
+    vessel *= exp(Rb*Rb*b2);
+    vessel *= (1.0-exp(Rs*Rs*c2));
+  }
+  
+  //printf("vessel=%f,diff=%f\n",vessel,diff);
+
+  double a = this->ComputeWeight(vessel, 1.0, 20.0, 0.4);
+  double b = this->ComputeWeight(diff, 1.0, 20.0, 0.5);
+
+  result = sqrt(grad) * a + b;
+
+  //printf("result=%f, a=%f, b=%f, diff=%f, vessel=%f\n",result,a,b,diff,vessel);
+
+  //result =  FA*FA*exp(result0*result0*result0);
+
+  //result = FA * (1./(1.+exp(-10*(FA-0.5)))) * (result1*result1 + 0.1);
+  //result = FA * (1./(1.+exp(-10*(FA-0.5)))) * exp(pow(result0,3));
+  //result = exp(result0*result0);
+  //result = (result1*result1);
+  //result = result1;
+
+  //result = FA*FA * exp(result*result);
+
+  //result = tan(result)+1.0;  
+  //else result=0.0;
+  //if (FA >= 0.2)  
+  //result = 1.0 / (1.0 - result*result);
+  //else result = 0.0;
+  
+  //if (this->Debug) {
+    //printf("direction=[%f,%f,%f],e1=[%f,%f,%f], result=%f\n",
+    //   direction[0], direction[1], direction[2], V0[0], V0[1], V0[2], result);
+  //}
+  
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingVesselConnectivity::ComputeFirstOrder(vtkImageData *input, vtkImageData *output,
+						  int parent, int coord[3], int index)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  //vtkDataArray *in = input->GetPointData()->GetScalars(); 
+  vtkDataArray *out = output->GetPointData()->GetScalars();
+  
+  // estimate normal
+  double normal[3];
+  this->ComputeNormal(input, output, coord, index, normal);
+
+  // get speed value
+  double F = this->ComputeSpeed(input, output, parent, coord, index, normal);
+  //double F = 1.0;
+
+  if (F == 0.0) {
+    return this->Infinity;
+  }
+    
+  int num_terms = 0;
+  double direction[3];
+  double term[3];
+  int term_index[3];
+  
+  // process each one of the six neighbors
+  for (int j=0; j<3; j++) { // axis  
+    
+    direction[0] = 0.0;
+    direction[1] = 0.0;
+    direction[2] = 0.0;
+    
+    term[j] = (double)VTK_MPJ_LARGE_DOUBLE;
+    
+    for (int i=-1; i<2; i+=2) { // direction 
+      if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  
+	
+	direction[j] = (double)i;
+	
+	int neighbor=index + i*factor[j];
+	
+	// if value is frozen get its time
+	if (this->InMask(neighbor) && this->label->GetComponent(neighbor, 0) == (double)VTK_MPJ_FROZEN) {
+	  
+	  double time = (double)out->GetComponent(neighbor, 0);
+	  
+	  if (time < term[j]) {
+	    term[j] = time;
+	    term_index[j] = neighbor;
+	  }
+
+	} // if
+      } // if       
+    } // for direction 
+    
+
+    // accumulate number of quadratic terms
+    num_terms += (term[j] < (double)VTK_MPJ_LARGE_DOUBLE);
+  
+  } // for axis
+  
+  // sort terms
+  this->SortTerms(term);
+
+  double solution = this->Infinity;//VTK_MPJ_LARGE_DOUBLE;
+
+  // solve quadratic for maximum solution
+  solution = this->SolveQuadratic(num_terms, term, this->Spacing[0] / F);
+
+  return (solution < this->Infinity ? solution : this->Infinity);
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastMarchingVesselConnectivity::ComputeTime(vtkImageData *input, vtkImageData *output,
+					   int parent, int coord[3], int index) 
+{
+  // vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  // compute time of arrival at neighbor
+  double time = this->ComputeFirstOrder(input, output, parent, coord, index);
+  
+  // insert neighbor in the narrow band
+  if (this->label->GetComponent(index, 0) != (double)VTK_MPJ_NARROW_BAND) {
+    this->label->SetComponent(index, 0, (double)VTK_MPJ_NARROW_BAND);
+    this->queue->Insert(time, index);
+  } else {
+    // if already in the narrow band, store new time
+    this->queue->DeleteId(index);
+    this->queue->Insert(time, index);
+  }
+
+  return time;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingVesselConnectivity::InitializeFront(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  // Create priority queue
+  this->queue = vtkmpjPriorityQueue::New();
+  this->queue->Allocate(1000);
+
+  // Create label image
+  this->LabelImage = vtkImageData::New();
+  this->LabelImage->SetSpacing(input->GetSpacing());
+  this->LabelImage->SetOrigin(input->GetOrigin());
+  this->LabelImage->SetDimensions(input->GetDimensions());
+  this->LabelImage->SetScalarType(VTK_SHORT);
+  this->LabelImage->SetNumberOfScalarComponents(1);
+  this->LabelImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->LabelImage->AllocateScalars();
+  this->label = this->LabelImage->GetPointData()->GetScalars();
+  this->label->FillComponent(0, (double)VTK_MPJ_UNVISITED);
+
+  out->FillComponent(0, this->Infinity);
+  
+  int index, coord[3], ncoord[3];
+  int dim0Tdim1 = dim[0]*dim[1];
+  //int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  // Freeze known points
+  int num_known = this->KnownPoints->GetNumberOfTuples();
+  for(int i=0; i<num_known; i++) {
+    
+    coord[0] = ncoord[0] = (int)this->KnownPoints->GetComponent(i, 0);
+    coord[1] = ncoord[1] = (int)this->KnownPoints->GetComponent(i, 1);
+    coord[2] = ncoord[2] = (int)this->KnownPoints->GetComponent(i, 2);
+    double value = this->KnownPoints->GetComponent(i, 3);
+    
+    index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+
+    // Tag initial points as trial points
+    this->label->SetComponent(index, 0, (double)VTK_MPJ_NARROW_BAND);   
+
+    out->SetComponent(index, 0, this->KnownValues ? value : 0.0);              
+
+    // Insert into narrow band queue
+    this->queue->Insert(0, index);
+   
+    this->count++;
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingVesselConnectivity::PropagateFront(vtkImageData *input, vtkImageData *output)
+{
+  double time;
+  int index, coord[3], ncoord[3];
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  while ((index = this->queue->Pop(time, 0)) != -1) {
+    
+    this->label->SetComponent(index, 0, (double)VTK_MPJ_FROZEN);    
+    out->SetComponent(index, 0, (double)time);
+
+    this->count++;
+    if (this->count==this->tenth)
+      {
+	this->pog+=0.1;
+	this->UpdateProgress(this->pog);
+	this->count=0;
+      }
+    
+    // stop if arrival time is greater or equal to max time
+    if ((time >= VTK_MPJ_LARGE_DOUBLE) || 
+	((this->PropagationTime < (double)VTK_MPJ_LARGE_DOUBLE) && (time >= this->PropagationTime))) {
+      continue;
+    }
+
+    // decompose index into x, y, z coordinates
+    coord[2] = ncoord[2] = index / dim0Tdim1; 
+    int r = index % dim0Tdim1;
+    coord[1] = ncoord[1] = r / dim[0];
+    coord[0] = ncoord[0] = r % dim[0];
+    
+    // process each one of the six neighbors
+    for (int j=0; j<3; j++)  // axis  
+      for (int i=-1; i<2; i+=2)  { // direction 
+	
+	if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  
+	  int neighbor=index + i*factor[j];
+	  
+	  if (this->InMask(neighbor) && this->label->GetComponent(neighbor, 0) != (double)VTK_MPJ_FROZEN) { 
+	   
+	    ncoord[j] = coord[j] + i;   // update coordinate
+	    this->ComputeTime(input, output, index, ncoord, neighbor);
+	    ncoord[j] = coord[j]; // reset
+	  }	  
+	}
+      }
+    } // while  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingVesselConnectivity::SaveFrontPoints(vtkImageData *input)
+{
+  int total = this->queue->GetNumberOfItems();
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int index, coord[3];
+  double value;
+  
+  if (this->FrontPoints != NULL) 
+    this->FrontPoints->Delete();
+  
+  this->FrontPoints = vtkDoubleArray::New(); 
+  this->FrontPoints->SetNumberOfComponents(4);
+  
+  for(int j=0; j<total; j++) {
+    
+    // get point index
+    index = queue->Peek(value, j);
+    
+    // decompose index
+    coord[2] = index / dim0Tdim1; 
+    int r = index % dim0Tdim1;
+    coord[1] = r / dim[0];
+    coord[0] = r % dim[0];
+    
+    // insert point
+    this->FrontPoints->InsertNextTuple4((double)coord[0], (double)coord[1], (double)coord[2], 
+					(double)value);
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastMarchingVesselConnectivity::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  
+  if (this->GetInput()==NULL) {
+    vtkErrorMacro(<<"No Speed Image\n Exiting\n");
+    return;
+  }
+
+  symmetric = (input->GetNumberOfScalarComponents() == 6);
+
+  int total = input->GetPointData()->GetScalars()->GetNumberOfTuples();  
+  this->pog = 0.0;  
+  this->tenth = (int)(total / 10.0);
+  this->count = 0;
+  
+  this->UpdateProgress(0.01);
+  
+  // Get pointer to mask array
+  this->mask = (this->Mask != NULL) ? this->Mask->GetPointData()->GetScalars() : NULL;
+
+  // initialize
+  this->InitializeFront(input, output);  
+  
+  // propagate front
+  this->PropagateFront(input, output);
+
+  // save front points
+  this->SaveFrontPoints(input);
+
+  this->UpdateProgress(1.0);
+}
+
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingVesselConnectivity.h b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingVesselConnectivity.h
new file mode 100644
index 0000000..450af78
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjFastMarchingVesselConnectivity.h
@@ -0,0 +1,173 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+  -- vtkmpjFastMarchingVesselConnectivity.h --
+
+  Marcel Jackowski, Mar 2005.
+
+*/
+
+#define VTK_MPJ_FROZEN       -1     
+#define VTK_MPJ_NARROW_BAND   0
+#define VTK_MPJ_UNVISITED    +1
+
+#ifndef __vtkmpjFastMarchingVesselConnectivity_h
+#define __vtkmpjFastMarchingVesselConnectivity_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkmpjPriorityQueue.h"
+#include "vtkImageAccumulate.h"
+#include "vtkDoubleArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjFastMarchingVesselConnectivity : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjFastMarchingVesselConnectivity *New();
+  vtkTypeMacro(vtkmpjFastMarchingVesselConnectivity,vtkpxSimpleImageToImageFilter);
+  
+  // Description: Sets speed image
+  void SetSpeedImage(vtkImageData *speed);
+
+  // Description:
+  // Set/Get boundary conditions for the propagation
+  vtkSetObjectMacro(KnownPoints, vtkDoubleArray);
+  vtkGetObjectMacro(KnownPoints, vtkDoubleArray);
+
+  // Description:
+  // Turn on/off values for known points
+  vtkGetMacro(KnownValues,int);
+  vtkSetClampMacro(KnownValues,int,0,1);
+  vtkBooleanMacro(KnownValues,int);
+
+  // Description:
+  // Set/Get maximum propagation time
+  vtkGetMacro(PropagationTime,double);
+  vtkSetMacro(PropagationTime,double);
+  
+  // Description:
+  // Set/Get infinity value
+  vtkGetMacro(Infinity,double);
+  vtkSetMacro(Infinity,double);
+
+  // Description:
+  // Get/Set grid spacing
+  vtkGetVector3Macro(Spacing,double);
+  vtkSetVector3Macro(Spacing,double);
+
+  vtkGetMacro(MaxIntensity,double);
+  vtkSetMacro(MaxIntensity,double);
+  
+  // Front label image. Points interior to the front have value -1, points 
+  // on the front boundary have value 0, and points outside have value +1.
+  vtkGetObjectMacro(LabelImage, vtkImageData);
+  
+  // Return an array containing front point vertices and their values
+  vtkGetObjectMacro(FrontPoints, vtkDoubleArray);
+  
+  // Description: 
+  // Sets/Gets mask for determining propagation extents
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+
+  // Description:
+  // Sets/Gets propagation scaling
+  vtkSetObjectMacro(ScaleImage, vtkImageData);
+  vtkGetObjectMacro(ScaleImage, vtkImageData);
+
+ protected:
+  double MaxIntensity;
+  double Spacing[3];
+  double PropagationTime;
+  int KnownValues;
+  double Infinity;
+  vtkImageData *Speed;
+  vtkImageData *LabelImage;
+  vtkImageData *Mask;
+  vtkImageData *ScaleImage;
+  vtkDoubleArray *KnownPoints;
+  vtkDoubleArray *FrontPoints;
+
+  vtkDataArray *label;
+  vtkmpjPriorityQueue *queue;     
+
+  vtkmpjFastMarchingVesselConnectivity();
+  virtual ~vtkmpjFastMarchingVesselConnectivity();
+  
+  void ExecuteInformation();  
+  virtual int InMask(int neighbor);
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  virtual void InitializeFront(vtkImageData *input, vtkImageData *output);
+  virtual void PropagateFront(vtkImageData *input, vtkImageData *output);
+  virtual void SaveFrontPoints(vtkImageData *input);  
+  virtual double ComputeSpeed(vtkImageData *input, vtkImageData *output,
+			      int parent, int coord[3], int index, double normal[3]);  
+  virtual double ComputeFirstOrder(vtkImageData *input, vtkImageData *output,
+				   int parent, int coord[3], int index);
+  virtual void ComputeNormal(vtkImageData *input, vtkImageData *output,
+			     int coord[3], int index, double result[3]);
+  
+  void SortTerms(double term[3]);
+  double Solve2(double a, double b, double rhs);
+  double SolveN(int number, double term[3], double rhs);
+  double SolveQuadratic(int number, double term[3], double rhs);
+  
+  double ComputeTime(vtkImageData *input, vtkImageData *output,
+		     int parent, int coord[3], int index);  
+
+  double ComputeWeight(double value, double max, 
+		       double steepness, double center);
+    
+  void Jacobi3x3(double a[3][3], double w[3], double v[3][3]);
+  void NormalizeTensor3x3(double T[3][3], double W[3], double V[3][3], double N[3][3]);
+  void SortEigenvectors(double W[3], double T[3][3]);
+  void PrintMatrix3x3(char *title, double M[3][3]);
+
+ private:
+  //BTX
+  double pog;
+  int count, tenth; 
+  vtkDataArray *mask;
+  int symmetric;
+  //ETX
+  
+  vtkmpjFastMarchingVesselConnectivity(const vtkmpjFastMarchingVesselConnectivity&);// Not implemented
+  void operator=(const vtkmpjFastMarchingVesselConnectivity&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjFastSweepingMethod.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjFastSweepingMethod.cpp
new file mode 100644
index 0000000..3d02278
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjFastSweepingMethod.cpp
@@ -0,0 +1,605 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjFastSweepingMethod.h"
+
+//------------------------------------------------------------------------------
+vtkmpjFastSweepingMethod* vtkmpjFastSweepingMethod::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjFastSweepingMethod");
+  if(ret) {
+    return (vtkmpjFastSweepingMethod*)ret;
+  }
+  
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjFastSweepingMethod;
+}
+
+// Construct object with no children.
+vtkmpjFastSweepingMethod::vtkmpjFastSweepingMethod()
+{
+  this->SecondOrder = 0;
+  this->KnownPoints = NULL;
+  this->KnownValues = 1;
+  this->NumberOfIterations = 2;
+  this->Speed = NULL;  
+  this->label = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjFastSweepingMethod::~vtkmpjFastSweepingMethod()
+{
+  if (this->KnownPoints != NULL)
+    this->KnownPoints->Delete();
+  if (this->LabelImage != NULL)
+    this->LabelImage->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastSweepingMethod::SetSpeedImage(vtkImageData *speed)
+{
+  this->SetInput(speed);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastSweepingMethod::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+   
+  if (this->KnownPoints==NULL) {
+    vtkErrorMacro(<<"Set of known points is empty!");
+    return;
+  }
+
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastSweepingMethod::SortTerms(double values[3]) 
+{
+  double tmp[3];
+  
+  if (values[0] < values[1]) {
+    if (values[0] < values[2]) {
+      if (values[1] < values[2]) {
+	tmp[0] = values[0]; tmp[1] = values[1]; tmp[2] = values[2]; 
+      } else {
+	tmp[0] = values[0]; tmp[1] = values[2]; tmp[2] = values[1]; 
+      }
+    } else 
+      {
+	tmp[0] = values[2]; tmp[1] = values[0]; tmp[2] = values[1];
+      }
+  } else {
+    if (values[1] < values[2]) {
+      if (values[0] < values[2]) {
+	tmp[0] = values[1]; tmp[1] = values[0]; tmp[2] = values[2];
+      } else {
+	tmp[0] = values[1]; tmp[1] = values[2]; tmp[2] = values[0];
+      }
+    } else
+      {
+	tmp[0] = values[2]; tmp[1] = values[1]; tmp[2] = values[0];
+      }    
+  }
+
+  values[0] = tmp[0];
+  values[1] = tmp[1];
+  values[2] = tmp[2];
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastSweepingMethod::Initialize(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  // Create label image
+  this->LabelImage = vtkImageData::New();
+  this->LabelImage->SetSpacing(input->GetSpacing());
+  this->LabelImage->SetOrigin(input->GetOrigin());
+  this->LabelImage->SetDimensions(input->GetDimensions());
+  this->LabelImage->SetScalarType(VTK_SHORT);
+  this->LabelImage->SetNumberOfScalarComponents(1);
+  this->LabelImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->LabelImage->AllocateScalars();
+  this->label = this->LabelImage->GetPointData()->GetScalars();
+  this->label->FillComponent(0, VTK_MPJ_UNKNOWN);
+
+  // Initialize values to infinity
+  out->FillComponent(0, VTK_LARGE_FLOAT);
+  
+  int coord[3]; 
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  // Set initial conditions
+  for(int i=0; i<this->KnownPoints->GetNumberOfTuples(); i++) {
+    
+    coord[0] = (int)this->KnownPoints->GetComponent(i, 0);
+    coord[1] = (int)this->KnownPoints->GetComponent(i, 1);
+    coord[2] = (int)this->KnownPoints->GetComponent(i, 2);
+    float value = this->KnownValues ? this->KnownPoints->GetComponent(i, 3) : 0.0;
+    
+    int index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+    
+    this->label->SetComponent(index, 0, VTK_MPJ_KNOWN);  // Freeze voxel      
+    out->SetComponent(index, 0, (float)value);        // Set arrival time
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastSweepingMethod::Iterate(vtkImageData *input, vtkImageData *output)
+{
+  for(int s1=-1; s1<2; s1+=2)
+    for(int s2=-1; s2<2; s2+=2)
+      for(int s3=-1; s3<2; s3+=2) {
+
+	int dir[3] = {s1, s2, s3};
+
+	printf("sweeping %d %d %d\n",s1,s2,s3);
+	
+	this->Sweep(input, output, dir);
+	
+	this->count++;
+	if (this->count==this->tenth)
+	  {
+	    this->pog+=0.1;
+	    this->UpdateProgress(this->pog);
+	    this->count=0;
+	  }
+      }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastSweepingMethod::Sweep(vtkImageData *input, vtkImageData *output, int dir[3])
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  // Sweep image
+  for(int k=(dir[2]<0?dim[2]-2:1);(dir[2]<0?k>0:k<dim[2]-1);k+=dir[2])     
+    for(int j=(dir[1]<0?dim[1]-2:1);(dir[1]<0?j>0:j<dim[1]-1);j+=dir[1])
+      for(int i=(dir[0]<0?dim[0]-2:1);(dir[0]<0?i>0:i<dim[0]-1);i+=dir[0]) {
+	
+	int index = dim0Tdim1*k + dim[0]*j + i;
+	int coord[3] = {i, j, k};
+	
+	//if (this->label->GetComponent(index, 0) == VTK_MPJ_UNKNOWN) { 
+
+	  double new_value = this->ComputeFirstOrder(input, output, coord, index);
+	  
+	  if (new_value < out->GetComponent(index, 0))
+	    out->SetComponent(index, 0, (float)new_value);
+	  //}
+	
+      } 
+}
+
+double vtkmpjFastSweepingMethod::Solve(double a, double b)
+{  
+  if (fabs(a - b) >= 1) {
+    double min_ab = a < b ? a : b;
+    return min_ab + 1;
+  } else {
+    double amb2 = (a-b)*(a-b);
+    double result = (a+b+sqrt(2*1-amb2)) / 2.0;
+    return result;
+  }
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastSweepingMethod::Solve2(double a, double b, double rhs)
+{  
+  double amb = a - b;
+  if (fabs(amb) >= rhs) {
+    return (a < b ? a : b) + rhs;
+  } else {
+    double amb2 = amb*amb;
+    return (a+b+sqrt(2.0*rhs*rhs-amb2)) / 2.0;
+  }
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastSweepingMethod::SolveN(int number, double term[3], double rhs)
+{
+  double coeff[3] = {-rhs*rhs, 0.0, 0.0};
+
+  for (int j=0; j<3; j++) {
+    if (term[j] != VTK_LARGE_FLOAT) {
+      coeff[2] += 1.0;
+      coeff[1] -= 2*term[j];
+      coeff[0] += term[j]*term[j];
+    }
+  }
+  
+  int no_solutions = 1;
+  double max_sol = VTK_LARGE_FLOAT;
+  double sol[2] = {VTK_LARGE_FLOAT, VTK_LARGE_FLOAT};
+  double discr = coeff[1]*coeff[1] - 4.0*coeff[2]*coeff[0];
+  
+  if (discr < 0) {
+    printf("Solution is not differentiable! terms=%f, %f, %f, coeffs=%f, %f, %f\n", term[0], term[1], term[2], coeff[2], coeff[1], coeff[0]);
+  }
+  
+  // solve quadratic equation
+  vtkMath::SolveQuadratic(coeff[2], coeff[1], coeff[0], 
+			  &sol[0], &sol[1], &no_solutions);
+  if (no_solutions == 2) {
+    max_sol = sol[0]>=sol[1]?sol[0]:sol[1];
+  } else {
+    max_sol = sol[0];
+  }
+  
+  return max_sol;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastSweepingMethod::SolveQuadratic(int number, double term[3], double rhs)
+{  
+  double result;
+  
+  switch(number) {
+  case 1:
+    result = term[0] + rhs;
+    break;
+  case 2:
+    result = Solve2(term[0], term[1], rhs);
+    break;
+  case 3:
+  default:
+    if ((term[0] + rhs) > term[1]) {
+      result = term[0] + rhs;      
+    } else {
+      result = Solve2(term[0], term[1], rhs);
+    }
+    if (result > term[2])
+      result = SolveN(number, term, rhs);
+    break;
+  };
+      
+  return(result);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastSweepingMethod::ComputeNormal(vtkImageData *input, vtkImageData *output, 
+					    int coord[3], int index, double result[3])
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *in = input->GetPointData()->GetScalars(); 
+  vtkDataArray *out = output->GetPointData()->GetScalars();
+  
+  double normal[3];
+  result[0]=normal[0]=0.0;
+  result[1]=normal[1]=0.0;
+  result[2]=normal[2]=0.0;
+  
+  // process each one of the 26 neighbors
+  int count = 0;
+  for(int i=-1;i<2;i++)
+    for(int j=-1;j<2;j++)
+      for(int k=-1;k<2;k++) {
+	if ((coord[0]+i)>=0 && ((coord[0]+i)<dim[0]) &&
+	    (coord[1]+j)>=0 && ((coord[1]+j)<dim[1]) &&
+	    (coord[2]+k)>=0 && ((coord[2]+k)<dim[2]))
+	  {	  	    
+	    int neighbor=index + i*factor[0] + j*factor[1] + k*factor[2];
+	    if (this->label->GetComponent(neighbor, 0) == VTK_MPJ_KNOWN) {
+	      normal[0]+=i; normal[1]+=j; normal[2]+=k;	      
+	    }
+	  }	
+      }
+  
+  result[0]=normal[0];
+  result[1]=normal[1];
+  result[2]=normal[2];
+  
+  (void) vtkMath::Normalize(result);  
+
+  //printf("normal at %d is [%f,%f,%f], [%f,%f,%f]\n",index,result[0],result[1],result[2],normal[0],normal[1],normal[2]);
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastSweepingMethod::ComputeFirstOrder(vtkImageData *input, vtkImageData *output,
+						  int coord[3], int index)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *in = input->GetPointData()->GetScalars(); 
+  vtkDataArray *out = output->GetPointData()->GetScalars();
+  
+  // get speed value
+  //double F = this->ComputeSpeed(input, output, coord, index);
+
+  // estimate normal
+  double normal[3];
+  //this->ComputeNormal(input, output, coord, index, normal);
+  //double F = ComputeDiffusion(input, index, normal);
+
+  double F = 1.0;
+
+  if (F == 0.0) 
+    return VTK_LARGE_FLOAT;
+    
+  int num_terms = 0;
+  double direction[3];
+  double term[3];
+  int term_index[3];
+  
+  // process each one of the six neighbors
+  for (int j=0; j<3; j++) { // axis  
+    
+    direction[0] = 0.0;
+    direction[1] = 0.0;
+    direction[2] = 0.0;
+    
+    term[j] = VTK_LARGE_FLOAT;
+    
+    for (int i=-1; i<2; i+=2) { // direction 
+      if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  
+	
+	direction[j] = (double)i;
+	
+	int neighbor=index + i*factor[j];
+	
+	// if value is frozen get its time
+	//if (this->label->GetComponent(neighbor, 0) == VTK_MPJ_FROZEN) {
+	  
+	  double time = (double)out->GetComponent(neighbor, 0);
+	  
+	  if (time < term[j]) {
+	    term[j] = time;
+	    term_index[j] = neighbor;
+	  }
+
+	  //} // if
+      } // if       
+    } // for direction 
+    
+
+    // accumulate number of quadratic terms
+    //    printf("term[%d]=%f\n",j,term[j]);
+    num_terms += (term[j] != VTK_LARGE_FLOAT);
+  
+  } // for axis
+  
+  //printf("num_terms=%d\n",num_terms);
+  
+  // sort terms
+  this->SortTerms(term);
+
+  double solution = VTK_LARGE_FLOAT;
+
+  /*  if (num_terms == 3) { 
+      double sum_terms = term[0] + term[1] + term[2];
+      double termsq0 = term[0]*term[0];
+      double termsq1 = term[1]*term[1];
+      double termsq2 = term[2]*term[2];
+      double aux = 3.0 * ((1.0 / F*F) - termsq0 - termsq1 - termsq2);
+      solution = (sum_terms + sqrt(aux + sum_terms*sum_terms)) / 3.0;
+      } else if (num_terms == 2) {
+      double sum_terms = term[0] + term[1];
+      double aux = term[0] - term[1];
+      solution = (sum_terms + sqrt(2.0 * (1.0 / F*F) - aux*aux)) / 2.0;
+      } else {
+      solution = term[0] + (1.0 / F);
+      }*/
+
+//this->SortTerms(diff);
+  
+  //double F = diffusion;
+  //  printf("diffusion=%f\n",diffusion);
+  //if (F == 0.0)
+  //return VTK_LARGE_FLOAT;
+
+  //printf("F=%f / %f=%f\n",sum_diff,(float)num_terms,F);
+  
+// F = diff[0];
+//if (this->Debug) { 
+//  printf("F=%f\n",F);
+//}
+
+  // solve quadratic for maximum solution
+  solution = this->SolveQuadratic(num_terms, term, 1.0 / F);
+
+  if (this->Debug)
+    printf("sol=%f\n",solution);
+
+  //double old_solution = (double)out->GetComponent(index, 0);
+  //if (old_solution < solution) 
+  //return old_solution;
+  //else    
+    return solution;
+}
+
+
+// ----------------------------------------------------------------------------
+double vtkmpjFastSweepingMethod::Update(vtkImageData *input, vtkImageData *output, int coord[3], int index)
+{
+  int dim[3]; input->GetDimensions(dim);
+  // float spc[3]; input->GetSpacing(spc);
+  float spc[3] = {1.0, 1.0, 1.0};
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  
+  double min_value[3];
+  double f = 1.0;
+  double coeff[3] = {-1.0 / (f*f), 0.0, 0.0};        // coefficient array
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  if ( f == 0.0 ) {
+    return VTK_LARGE_FLOAT; 
+    printf("Warning: F is %lf at %d,%d,%d\n",f,coord[0],coord[1],coord[2]); 
+  }
+  
+  // process each one of the six neighbors
+  for (int j=0; j<3; j++) { // axis  
+    
+    min_value[j] = VTK_LARGE_FLOAT;
+    
+    for (int i=-1; i<2; i+=2) { // direction 
+      if ((coord[j]+i)>=0 && (coord[j]+i)<dim[j]) {	  
+	
+	int neighbor=index + i*factor[j];
+	
+	double value = (double)out->GetComponent(neighbor, 0);
+	
+	if (value < min_value[j]) 
+	  min_value[j] = value;
+	
+      } // if
+    } // for     
+    
+    // accumulate quadratic coefficients 
+    /*if (min_value[j] != VTK_LARGE_FLOAT) {
+      coeff[2] += 1.0;
+      coeff[1] -= 2*min_value[j];
+      coeff[0] += min_value[j]*min_value[j];
+      }*/
+  }
+  
+  double max_sol = VTK_LARGE_FLOAT;
+  double sol[2] = {VTK_LARGE_FLOAT, VTK_LARGE_FLOAT};
+  double discr = coeff[1]*coeff[1] - 4.0*coeff[2]*coeff[0];  /* discr = b^2-4ac */
+
+  /* if discriminant is zero, shift center of sphere */
+  /*  if (discr < 0) {*/
+    
+    //    printf("---Discriminant is negative---\n");
+    //  printf("1: coeffs=%lf,%lf,%lf\n",coeff[2],coeff[1],coeff[0]);
+    //  printf("1: sol=%lf  f=%lf\n",max_sol,f);
+    //  printf("1:discr=%f\n",discr);
+    //  printf("---------------\n");
+    
+    // sort values in increasing order
+    //int order[3];
+    //this->Sort(min_value,order);
+    
+  /*    if (min_value[0] > min_value[1]) {
+	min_value[0] = min_value[1] + spc[0];
+	} else {
+	min_value[1] = min_value[0] + spc[1];
+	}
+	
+	coeff[0]= -1.0 / (f*f); coeff[1]=coeff[2]=0.0;
+	for (int j=0; j<2; j++) {
+	coeff[2] += 1.0 / spc[j];
+	coeff[1] -= 2*min_value[j] / spc[j];
+	coeff[0] += min_value[j]*min_value[j] / spc[j];
+	}
+	
+	}*/
+
+  // needs reordering
+  this->SortTerms(min_value);
+
+  double r1 = Solve(min_value[0], min_value[1]);
+  if (r1 <= min_value[2]) return r1;
+  double r2 = Solve(min_value[1], min_value[2]);
+  return r2;
+
+  /*  double result = min_value[0] + 1;
+  if (result <= min_value[1]) {
+    return result;
+  }
+  
+  if (fabs(min_value[0] - min_value[1]) >= 1) {
+    double minab = min_value[0] < min_value[1] ? min_value[0] : min_value[1];
+    return minab + 1;
+  } else {
+    double amb2 = (min_value[0]-min_value[1])*(min_value[0]-min_value[1]);
+    double result = (min_value[0]+min_value[1]+sqrt(2-amb2)) / 2;
+    return result;
+    }*/
+  
+  /*else {*/
+  
+  // solve quadratic equation
+  /*int no_solutions;
+    vtkMath::SolveQuadratic(coeff[2], coeff[1], coeff[0], 
+    &sol[0], &sol[1], &no_solutions);
+    if (no_solutions == 2) {
+    max_sol = sol[0]>=sol[1]?sol[0]:sol[1];
+    } else {
+    max_sol = sol[0];
+    }
+  
+  return max_sol;*/
+ 
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjFastSweepingMethod::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3];  input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  
+  if (this->GetInput()==NULL) {
+    vtkErrorMacro(<<"No Input Image\n Exiting\n");
+    return;
+  }
+  
+  this->pog = 0.0;  
+  this->tenth=(int)((8*this->NumberOfIterations) / 8.0);
+  this->count=0;
+
+  this->Initialize(input, output);
+  this->UpdateProgress(0.01);
+  
+  for(int j=0; j<this->NumberOfIterations; j++) {
+    printf("iteration %d\n", j);
+    this->Iterate(input, output);
+  }
+  
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjFastSweepingMethod.h b/bioimagesuite30_src/mpjLevelset/vtkmpjFastSweepingMethod.h
new file mode 100644
index 0000000..c95da38
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjFastSweepingMethod.h
@@ -0,0 +1,126 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+   -- vtkmpjFastSweepingMethod.h --
+   
+   Implements Stanley Osher's Fast Sweeping method for solving
+   the Eikonal equation |grad(T)|*F= 1.
+   
+   Marcel Jackowski, October 2003.
+   
+*/
+
+#define VTK_MPJ_KNOWN   100   
+#define VTK_MPJ_UNKNOWN   0   
+
+#ifndef __vtkmpjFastSweepingMethod_h
+#define __vtkmpjFastSweepingMethod_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageAccumulate.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjFastSweepingMethod : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjFastSweepingMethod *New();
+  vtkTypeMacro(vtkmpjFastSweepingMethod,vtkpxSimpleImageToImageFilter);
+  
+  // Description: Sets speed image
+  void SetSpeedImage(vtkImageData *speed);
+
+  // Description:
+  // Set/Get boundary conditions for the propagation
+  vtkSetObjectMacro(KnownPoints, vtkFloatArray);
+  vtkGetObjectMacro(KnownPoints, vtkFloatArray);
+
+  // Description: Turns on/off second order approximation to the gradient
+  vtkGetMacro(SecondOrder,int);
+  vtkSetClampMacro(SecondOrder,int,0,1);
+  vtkBooleanMacro(SecondOrder,int);
+
+  vtkGetMacro(NumberOfIterations,int);
+  vtkSetMacro(NumberOfIterations,int);
+
+  // Front label image. Points interior to the front have value -1, points 
+  // on the front boundary have value 0, and points outside have value +1.
+  vtkGetObjectMacro(LabelImage, vtkImageData);
+
+ protected:
+  int SecondOrder;
+  int NumberOfIterations;
+  int KnownValues;
+  vtkImageData *Speed;
+  vtkFloatArray *KnownPoints;
+  vtkImageData *LabelImage;
+  vtkDataArray *label;
+
+  vtkmpjFastSweepingMethod();
+  virtual ~vtkmpjFastSweepingMethod();
+  
+  void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+
+  void Initialize(vtkImageData *input, vtkImageData *output);
+  void Iterate(vtkImageData *input, vtkImageData *output);
+  void Sweep(vtkImageData *input, vtkImageData *output, int dir[3]);
+  double Update(vtkImageData *input, vtkImageData *output, int coord[3], int index);
+
+  void Sort(double values[3]);
+  double Solve(double a, double b);
+
+  virtual double ComputeFirstOrder(vtkImageData *input, vtkImageData *output, int coord[3], int index);
+  virtual void ComputeNormal(vtkImageData *input, vtkImageData *output, int coord[3], int index, double result[3]);
+  virtual void SortTerms(double term[3]);
+
+  double Solve2(double a, double b, double rhs);
+  double SolveN(int number, double term[3], double rhs);
+  double SolveQuadratic(int number, double term[3], double rhs);
+
+ private: 
+  //BTX
+  float pog;
+  int count, tenth; 
+  //ETX
+  
+  vtkmpjFastSweepingMethod(const vtkmpjFastSweepingMethod&);// Not implemented
+  void operator=(const vtkmpjFastSweepingMethod&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjImageCharacteristics.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjImageCharacteristics.cpp
new file mode 100644
index 0000000..7b22113
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjImageCharacteristics.cpp
@@ -0,0 +1,323 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjImageCharacteristics.h"
+
+//------------------------------------------------------------------------------
+vtkmpjImageCharacteristics* vtkmpjImageCharacteristics::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjImageCharacteristics");
+  if(ret)
+    {
+      return (vtkmpjImageCharacteristics*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjImageCharacteristics;
+}
+
+// Construct object with no children.
+vtkmpjImageCharacteristics::vtkmpjImageCharacteristics()
+{
+  this->Mask = NULL;
+  this->Tensor = NULL;
+  this->Gradient = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjImageCharacteristics::~vtkmpjImageCharacteristics()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+  if (this->Tensor != NULL)
+    this->Tensor->Delete();
+  if (this->Gradient != NULL)
+    this->Gradient->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageCharacteristics::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+
+  output->SetNumberOfScalarComponents(3);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+int vtkmpjImageCharacteristics::InsideMask(int index)
+{
+  return (this->mask != NULL)?(this->mask->GetComponent(index, 0) > 0) : 1;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageCharacteristics::Jacobi3x3(float a[3][3], float w[3], float v[3][3])
+{
+  float **aa = new float *[3]; /* allocate space for tensor matrix */
+  aa[0] = new float[3];
+  aa[1] = new float[3];
+  aa[2] = new float[3];
+   
+  float **vv = new float *[3]; /* allocate space for eigenvector matrix */
+  vv[0] = new float[3];
+  vv[1] = new float[3];
+  vv[2] = new float[3];
+  
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++) 
+      aa[i][j] = a[i][j];
+
+  // call the real method
+  (void) vtkMath::Jacobi(aa,w,vv);
+
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++) 
+      v[i][j] = vv[i][j];
+
+  // free aa
+  delete[] aa[0];
+  delete[] aa[1];
+  delete[] aa[2];
+  delete[] aa;
+   
+  delete[] vv[0];
+  delete[] vv[1];
+  delete[] vv[2];
+  delete[] vv;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageCharacteristics::NormalizeTensor3x3(float T[3][3], float W[3], float V[3][3], float N[3][3])
+{
+  float R[3][3], S[3][3];
+  float D[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
+
+  // diagonalize tensor
+  this->Jacobi3x3(T,W,V);
+
+  // force eigenvalues be positive
+  for (int i=0; i<3; i++) {
+    if (W[i] < 0) {
+      V[0][i] = -V[0][i];
+      V[1][i] = -V[1][i];
+      V[2][i] = -V[2][i];
+      W[i] = -W[i];
+    }
+  }
+
+  // make tensor unit size
+  D[0][0] = 1.0; D[1][1] = W[1]/W[0]; D[2][2] = W[2]/W[0];
+
+  // normalized tensor = V * D * V' 
+  (void) vtkMath::Transpose3x3(V,R);
+  (void) vtkMath::Multiply3x3(D,R,S);
+  (void) vtkMath::Multiply3x3(V,S,N);
+}
+
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageCharacteristics::FindEllipsoidPoint(float n[3], float w[3], float T[3][3], float N[3][3], float V[3][3], float FA)
+{
+  float eps = 1E-12;
+
+  double u, v, av;
+  double a = this->CoefficientA;
+  double b = this->CoefficientB;
+  double c = this->CoefficientC;
+  //double a = 3, b = 2, c = 1;
+  double aux;// = (n[1]*b) / (n[0]*a);
+
+  if ((n[0] == 0) && (n[1] == 0) && (n[2] == 0)) {
+    w[0] = 0;
+    w[1] = 0;
+    w[2] = 0;
+  }
+
+  // calculate u
+  //aux = (n[1]*b) / (n[0]*a+eps);
+  // u = atan(aux);
+
+  //if (n[0] <= 0) 
+  //  u += M_PI; 
+  //else if(n[1] < 0)
+  //  u += 2*M_PI;
+  
+  //if (n[0] <= 0) u += M_PI;
+  //if (n[0] > 0 && n[1] <= 0) u += 2*M_PI;
+  //if (u < 0 || u>2*M_PI) printf("PROBLEM=%f!, n0=%f, n1=%f a=%f, b=%f\n",u,n[0],n[1],w[0],w[1]);
+  
+  //  aux = sqrt(n[0] / (cos(u)*b*c+eps));
+  //  if ((aux < -1) || (aux > 1)) printf("v=%f\n",aux);
+  //v = acos(aux);
+  
+  //if (u < M_PI) av = -v; else av = v;
+  //if ((u > M_PI/2.) && (u < 3*M_PI/2.))
+  //av = -v;
+  //else av = v;
+
+  //p[0] = a*cos(v)*cos(u);
+  //p[1] = b*cos(v)*sin(u);
+  //p[2] = c*sin(v);
+
+  //printf("speed=%f\n",speed);
+  double p=n[0], q=n[1], r=n[2];
+  double FA2 = FA * FA;
+  double grad = sqrt(p*p+q*q+r*r) + eps;
+  double grad23 = pow(p*p + q*q + r*r, 3.0/2.0);
+  double diff = (p*p*N[0][0]+q*q*N[1][1]+r*r*N[2][2]+2*p*q*N[0][1]+2*p*r*N[0][2]+2*q*r*N[1][2]);
+
+  w[0] = -(FA2/grad23)*diff*p + (FA2/grad)*(2*p*N[0][0] + 2*q*N[0][1] + 2*r*N[0][2]);
+  w[1] = -(FA2/grad23)*diff*q + (FA2/grad)*(2*p*N[0][1] + 2*q*N[1][1] + 2*r*N[1][2]);
+  w[2] = -(FA2/grad23)*diff*r + (FA2/grad)*(2*p*N[0][2] + 2*q*N[1][2] + 2*r*N[2][2]);
+  
+  //p[0] = p[0] / sqrt(a*n[0]*n[0]+b*n[1]*n[1]+c*n[2]*n[2]);
+  //p[1] = p[1] / sqrt(a*n[0]*n[0]+b*n[1]*n[1]+c*n[2]*n[2]);
+  //p[2] = p[2] / sqrt(a*n[0]*n[0]+b*n[1]*n[1]+c*n[2]*n[2]);
+
+  //if (n[2] < 0) p[2] = -p[2];
+
+  //  printf("u=%f, v=%f, a=%f,%f,%f\n",u,v,a,b,c);
+  //(void) vtkMath::Multiply3x3(T, p, a);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageCharacteristics::ComputeCharacteristics(vtkImageData *input, vtkImageData *output, int coord[3], int index)
+{
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  //vtkDataArray *tensor=this->Tensor->GetPointData()->GetScalars();
+  vtkDataArray *gradient=this->Gradient->GetPointData()->GetScalars();
+
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+
+  // number of voxels in a row and slice
+  int factor[3] = {1, dim[0], dim0Tdim1};
+
+  float w[3], n[3], p[3];
+  float T[3][3], V[3][3], N[3][3];
+  float W[3];
+
+  T[0][0] = in->GetComponent(index, 0);           /* Dxx */
+  T[1][0] = T[0][1] = in->GetComponent(index, 1); /* Dxy */
+  T[2][0] = T[0][2] = in->GetComponent(index, 2); /* Dxz */
+  T[1][1] =  in->GetComponent(index, 4);          /* Dyy */
+  T[2][1] = T[1][2] = in->GetComponent(index, 5); /* Dyz */
+  T[2][2] = in->GetComponent(index, 8);           /* Dzz */
+
+  // diagonalize and normalize tensor 
+  this->NormalizeTensor3x3(T,W,V,N);
+   
+  // calculate FA
+  float md = (W[0] + W[1] + W[2]) / 3.0;
+  float a=W[0]-md;
+  float b=W[1]-md;
+  float c=W[2]-md;
+  float FA = sqrt(3*(a*a + b*b + c*c)) / sqrt(2*(W[0]*W[0] + W[1]*W[1] + W[2]*W[2]));
+
+  //D[0][0] = tensor->GetComponent(index, 0);           /* Dxx */
+  //D[1][0] = D[0][1] = tensor->GetComponent(index, 1); /* Dxy */
+  //D[2][0] = D[0][2] = tensor->GetComponent(index, 2); /* Dxz */
+  //D[1][1] = tensor->GetComponent(index, 4);           /* Dyy */
+  //D[2][1] = D[1][2] = tensor->GetComponent(index, 5); /* Dyz */
+  //D[2][2] = tensor->GetComponent(index, 8);           /* Dzz */
+
+  // diagonalize and normalize tensor 
+  //this->DiagonalizeTensor3x3(D,w,V,T);
+
+  //double speed = in->GetComponent(index, 0);
+
+  // determin coordinates of point on the ellipsoid
+  n[0]= gradient->GetComponent(index, 0);
+  n[1]= gradient->GetComponent(index, 1);
+  n[2]= gradient->GetComponent(index, 2);
+  
+  // normalize normal
+  double nm = vtkMath::Normalize(n);
+  
+  this->FindEllipsoidPoint(n,p,T,N,V,FA);
+  //  this->EllipsoidPoint(w,n,V,a);
+
+  double nmp = vtkMath::Normalize(p);
+
+  //printf("w=%f %f %f, n= %f %f %f char= %f %f %f\n",w[0],w[1],w[2],n[0],n[1],n[2],a[0],a[1],a[2]);
+    
+  out->SetComponent(index, 0, nm*p[0]);
+  out->SetComponent(index, 1, nm*p[1]);
+  out->SetComponent(index, 2, nm*p[2]);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjImageCharacteristics::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int index=0;
+    
+  if (this->GetInput()==NULL)
+    {
+      vtkErrorMacro(<<"No Input Image\n Exiting\n");
+      return;
+    }
+  
+  // Get pointer to mask array
+  this->mask = (this->Mask != NULL) ? this->Mask->GetPointData()->GetScalars() : NULL;
+  
+  for (int k=0;k<dim[2];k++) {    
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  int coord[3]={i, j, k};
+	  ComputeCharacteristics(input, output, coord, index);
+	  
+	  ++index;	  
+	}  	  
+    
+    float pog=float(k)/float(dim[2]);
+    this->UpdateProgress(pog);	
+    
+  }
+
+  printf("Done with map!\n");
+
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjImageCharacteristics.h b/bioimagesuite30_src/mpjLevelset/vtkmpjImageCharacteristics.h
new file mode 100644
index 0000000..2634e7c
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjImageCharacteristics.h
@@ -0,0 +1,98 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjImageCharacteristics_h
+#define __vtkmpjImageCharacteristics_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkFloatArray.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjImageCharacteristics : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjImageCharacteristics *New();
+  vtkTypeMacro(vtkmpjImageCharacteristics,vtkpxSimpleImageToImageFilter);
+  
+  // Description: 
+  // Sets/Gets mask for determining propagation extents
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+  
+  // Sets/Gets tensor information
+  vtkSetObjectMacro(Tensor, vtkImageData);
+  vtkGetObjectMacro(Tensor, vtkImageData);
+
+  // Sets/Gets gradient of u-map
+  vtkSetObjectMacro(Gradient, vtkImageData);
+  vtkGetObjectMacro(Gradient, vtkImageData);
+
+  vtkSetMacro(CoefficientA, float);
+  vtkGetMacro(CoefficientA, float);
+  
+  vtkSetMacro(CoefficientB, float);
+  vtkGetMacro(CoefficientB, float);
+  
+  vtkSetMacro(CoefficientC, float);
+  vtkGetMacro(CoefficientC, float);
+
+ protected:
+  vtkImageData *Mask;
+  vtkImageData *Tensor;
+  vtkImageData *Gradient;
+  float CoefficientA;
+  float CoefficientB;
+  float CoefficientC;
+  vtkmpjImageCharacteristics();
+  virtual ~vtkmpjImageCharacteristics();
+  
+  void Jacobi3x3(float a[3][3], float w[3], float v[3][3]);
+  void NormalizeTensor3x3(float T[3][3], float w[3], float V[3][3], float N[3][3]);
+  void FindEllipsoidPoint(float n[3], float w[3], float T[3][3], float N[3][3], float V[3][3], float FA);
+  void ComputeCharacteristics(vtkImageData *input, vtkImageData *output, int coord[3], int index);
+  void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  int InsideMask(int index);
+  
+ private: 
+  //BTX
+  vtkDataArray *mask;
+  //ETX
+  vtkmpjImageCharacteristics(const vtkmpjImageCharacteristics&);// Not implemented
+  void operator=(const vtkmpjImageCharacteristics&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLaxConnectivity.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxConnectivity.cpp
new file mode 100644
index 0000000..e38e03c
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxConnectivity.cpp
@@ -0,0 +1,741 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjLaxConnectivity.h"
+
+//------------------------------------------------------------------------------
+vtkmpjLaxConnectivity* vtkmpjLaxConnectivity::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjLaxConnectivity");
+  if(ret) {
+    return (vtkmpjLaxConnectivity*)ret;
+  }
+  
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjLaxConnectivity;
+}
+
+// Construct object with no children.
+vtkmpjLaxConnectivity::vtkmpjLaxConnectivity()
+{
+  this->KnownPoints = NULL;
+  this->KnownValues = 1;
+  this->NumberOfIterations = 2;
+  this->SymmetricTensor = 1;
+  this->label = NULL;
+  this->LabelImage = NULL;
+  this->Solution = NULL;
+  this->ConvergenceImage = NULL;
+  this->convergence = NULL;
+  this->ErrorValue = 0.0;
+  this->MaximumError = 1.0;
+  this->StopOnMaximumError = 0;
+  this->IterationNumber = 0;
+  this->Spacing[0] = 1.0;
+  this->Spacing[1] = 1.0;
+  this->Spacing[2] = 1.0;
+  this->Infinity = 32767;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxConnectivity::PrintMatrix3x3(char *title, float M[3][3])
+{
+  printf("%s",title);
+  printf("%f %f %f\n",M[0][0],M[0][1],M[0][2]);
+  printf("%f %f %f\n",M[1][0],M[1][1],M[1][2]);
+  printf("%f %f %f\n",M[2][0],M[2][1],M[2][2]);
+  printf("===============================\n");
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjLaxConnectivity::~vtkmpjLaxConnectivity()
+{
+  if (this->KnownPoints != NULL)
+    this->KnownPoints->Delete();
+  if (this->LabelImage != NULL)
+    this->LabelImage->Delete();
+  if (this->ConvergenceImage != NULL) 
+    this->ConvergenceImage->Delete();
+  if (this->Solution != NULL)
+    this->Solution->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxConnectivity::Jacobi3x3(float a[3][3], float w[3], float v[3][3])
+{
+  float **aa = new float *[3]; /* allocate space for tensor matrix */
+  aa[0] = new float[3];
+  aa[1] = new float[3];
+  aa[2] = new float[3];
+   
+  float **vv = new float *[3]; /* allocate space for eigenvector matrix */
+  vv[0] = new float[3];
+  vv[1] = new float[3];
+  vv[2] = new float[3];
+  
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++) 
+      aa[i][j] = a[i][j];
+
+  // call the real method
+  (void) vtkMath::Jacobi(aa,w,vv);
+
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++) 
+      v[i][j] = vv[i][j];
+
+  // free aa
+  delete[] aa[0];
+  delete[] aa[1];
+  delete[] aa[2];
+  delete[] aa;
+   
+  delete[] vv[0];
+  delete[] vv[1];
+  delete[] vv[2];
+  delete[] vv;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxConnectivity::NormalizeTensor3x3(float T[3][3], float W[3], float V[3][3], float N[3][3])
+{
+  float R[3][3], S[3][3], U[3][3];
+  float D[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
+  
+  // diagonalize tensor
+  this->Jacobi3x3(T,W,V);
+  
+  // force eigenvalues be positive
+  if (W[0]<0 || W[1]<0 || W[2]<0) {
+    
+    for (int i=0; i<3; i++) {
+      if (W[i] < 0) {
+	V[0][i] = -V[0][i];
+	V[1][i] = -V[1][i];
+	V[2][i] = -V[2][i];
+	W[i] = -W[i];
+      }
+    }
+  
+    D[0][0]=W[0]; D[1][1]=W[1]; D[2][2]=W[2];
+
+    // build new positive tensor
+    (void) vtkMath::Transpose3x3(V,R);
+    (void) vtkMath::Multiply3x3(D,R,S);
+    (void) vtkMath::Multiply3x3(V,S,U);
+    
+    // diagonalize it once more
+    this->Jacobi3x3(U,W,V);    
+  }
+  
+  // make tensor unit size
+  D[0][0] = 1.0; D[1][1] = W[1]/W[0]; D[2][2] = W[2]/W[0];
+  
+  // normalized tensor = V * D * V' 
+  (void) vtkMath::Transpose3x3(V,R);
+  (void) vtkMath::Multiply3x3(D,R,S);
+  (void) vtkMath::Multiply3x3(V,S,N);  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxConnectivity::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+   
+  if (this->KnownPoints==NULL) {
+    vtkErrorMacro(<<"Set of known points is empty!");
+    return;
+  }
+  
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxConnectivity::Initialize(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  
+  // Create label image
+  if (this->LabelImage == NULL) {
+    printf("initializing label...\n");
+    this->LabelImage = vtkImageData::New();
+    this->LabelImage->SetSpacing(input->GetSpacing());
+    this->LabelImage->SetOrigin(input->GetOrigin());
+    this->LabelImage->SetDimensions(input->GetDimensions());
+    this->LabelImage->SetScalarType(VTK_SHORT);
+    this->LabelImage->SetNumberOfScalarComponents(1);
+    this->LabelImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+    this->LabelImage->AllocateScalars();
+    this->label = this->LabelImage->GetPointData()->GetScalars();    
+    this->label->FillComponent(0, VTK_MPJ_UNKNOWN);
+  } else {
+    this->label = this->LabelImage->GetPointData()->GetScalars();    
+  }
+  
+  // Create convergence image
+  this->ConvergenceImage = vtkImageData::New();
+  this->ConvergenceImage->SetSpacing(input->GetSpacing());
+  this->ConvergenceImage->SetOrigin(input->GetOrigin());
+  this->ConvergenceImage->SetDimensions(input->GetDimensions());
+  this->ConvergenceImage->SetScalarType(VTK_FLOAT);
+  this->ConvergenceImage->SetNumberOfScalarComponents(1);
+  this->ConvergenceImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->ConvergenceImage->AllocateScalars();
+  this->convergence = this->ConvergenceImage->GetPointData()->GetScalars();
+  this->convergence->FillComponent(0, 0);
+  
+  // Initialize values to infinity if initial solution is not given
+  if (this->Solution == NULL) {
+    out->FillComponent(0, this->Infinity);
+  } else {
+    // otherwise initialize with given values
+    vtkDataArray *sol = this->Solution->GetPointData()->GetScalars();
+    int numtuples = sol->GetNumberOfTuples();
+    for(int i=0; i<numtuples; i++)
+      out->SetComponent(i, 0, sol->GetComponent(i, 0));
+  }
+  
+  int coord[3]; 
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  // Set initial conditions
+  if (this->KnownPoints != NULL) {
+    
+    int nc = this->KnownPoints->GetNumberOfComponents();    
+    int num = this->KnownPoints->GetNumberOfTuples();
+    
+    for(int i=0; i<num; i++) {
+      
+      coord[0] = (int)this->KnownPoints->GetComponent(i, 0);
+      coord[1] = (int)this->KnownPoints->GetComponent(i, 1);
+      coord[2] = (int)this->KnownPoints->GetComponent(i, 2);
+      float value = (nc > 3) ? this->KnownPoints->GetComponent(i, 3) : 0.0;
+      
+      int index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+      
+      this->label->SetComponent(index, 0, VTK_MPJ_KNOWN);// Freeze voxel    
+      this->convergence->SetComponent(index, 0, 0.0); // Boundary point has exact value
+      out->SetComponent(index, 0, (float)value);  // Set arrival time
+    }
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxConnectivity::Iterate(vtkImageData *input, vtkImageData *output)
+{
+  for(int s1=-1; s1<2; s1+=2)
+    for(int s2=-1; s2<2; s2+=2)
+      for(int s3=-1; s3<2; s3+=2) {
+
+	int dir[3] = {s1, s2, s3};
+
+	//printf("sweeping at direction: %d %d %d\n",s1,s2,s3);
+	this->Sweep(input, output, dir);
+	this->SweepBoundaries(input, output);
+	
+	this->count++;
+
+	if (this->count==this->tenth)
+	  {
+	    this->pog+=(4.0/(this->NumberOfIterations*8));
+	    this->UpdateProgress(this->pog);
+	    this->count=0;
+	  }
+      }
+}
+
+void vtkmpjLaxConnectivity::SweepBoundaries(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  
+  int index;
+  float val0, val1, val2, result;
+  float error;
+  
+  // rows
+  for(int k=0; k<dim[2]; k++)  // for all slices
+    for(int i=0; i<dim[0]; i++)  // for all columns in this row
+      {
+	// top row
+	index = dim0Tdim1*k + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + dim[0]*1, 0);
+	val2 = out->GetComponent(index + dim[0]*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  error = fabs(result - val0);
+	  if (error > this->ErrorValue) this->ErrorValue = error;
+	  this->convergence->SetComponent(index, 0, error);
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+	
+	// bottom row
+	index = dim0Tdim1*k + dim[0]*(dim[1]-1) + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - dim[0]*1, 0);
+	val2 = out->GetComponent(index - dim[0]*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  error = fabs(result - val0);
+	  if (error > this->ErrorValue) this->ErrorValue = error;
+	  this->convergence->SetComponent(index, 0, error);
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+  
+  // for columns
+  for(int k=0; k<dim[2]; k++)  // for all slices
+    for(int j=0; j<dim[1]; j++)  // for all rows
+      {
+	// left column
+	index = dim0Tdim1*k + dim[0]*j;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + 1, 0);
+	val2 = out->GetComponent(index + 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  error = fabs(result - val0);
+	  if (error > this->ErrorValue) this->ErrorValue = error;
+	  this->convergence->SetComponent(index, 0, error);
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+	
+	// right column
+	index = dim0Tdim1*k + dim[0]*j + dim[0]-1;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - 1, 0);
+	val2 = out->GetComponent(index - 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  error = fabs(result - val0);
+	  if (error > this->ErrorValue) this->ErrorValue = error;
+	  this->convergence->SetComponent(index, 0, error);
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+  
+  // for slices
+  for(int i=0; i<dim[0]; i++)  // for all columns
+    for(int j=0; j<dim[1]; j++) // for all rows      
+      { 
+	// first slice
+	index = dim[0]*j + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index + dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  error = fabs(result - val0);
+	  if (error > this->ErrorValue) this->ErrorValue = error;
+	  this->convergence->SetComponent(index, 0, error);
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+	
+	// last slice
+	index = dim0Tdim1*(dim[2]-1) + dim[0]*j + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index - dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  error = fabs(result - val0);
+	  if (error > this->ErrorValue) this->ErrorValue = error;
+	  this->convergence->SetComponent(index, 0, error);
+	} else 
+	  this->convergence->SetComponent(index, 0, 0.0);	
+      }  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxConnectivity::Sweep(vtkImageData *input, vtkImageData *output, int dir[3])
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  vtkDataArray *domain = NULL;
+
+  // Sweep image
+  for(int k=(dir[2]<0?dim[2]-2:1);(dir[2]<0?k>0:k<dim[2]-1);k+=dir[2])     
+    for(int j=(dir[1]<0?dim[1]-2:1);(dir[1]<0?j>0:j<dim[1]-1);j+=dir[1])
+      for(int i=(dir[0]<0?dim[0]-2:1);(dir[0]<0?i>0:i<dim[0]-1);i+=dir[0]) {
+	
+	int index = dim0Tdim1*k + dim[0]*j + i;
+	int coord[3] = {i, j, k};
+	
+	// only update point if value is unknown and is part of the
+	// computational domain
+	if (this->label->GetComponent(index, 0) == VTK_MPJ_UNKNOWN) {
+	  
+	  double new_value = this->Update(input, output, coord, index);
+	  
+	  // only update if it's value is less than before
+	  if (new_value < out->GetComponent(index, 0)) {
+	    
+	    // compute convergence 
+	    double old_value = out->GetComponent(index, 0);	    
+	    double error = fabs(new_value - old_value);
+	    if (error > this->ErrorValue) this->ErrorValue = error;
+	    this->convergence->SetComponent(index, 0, error);
+	    out->SetComponent(index, 0, (float)new_value);	    
+	    
+	  } else 
+	    this->convergence->SetComponent(index, 0, 0.0);
+	}	
+      }   
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxConnectivity::SolveHp(int coord[3], int index, double p, double q, double r, float T[3][3], float N[3][3], float V[3][3], float FA)
+{
+  double FA2 = FA*FA;
+  double eps = 1E-12;
+  double grad = sqrt(p*p + q*q + r*r) + eps;
+  double dot = (p*V[0][0] + q*V[0][1] + r*V[0][2]);
+  double grad23 = pow(p*p + q*q + r*r, 3.0/2.0);
+  double prod = (p*V[0][0] + q*V[0][1] + r*V[0][2]) / (sqrt(grad)+eps);
+  //double diff = (p*p*N[0][0]+q*q*N[1][1]+r*r*N[2][2]+2*p*q*N[0][1]+2*p*r*N[0][2]+2*q*r*N[1][2]);
+  double tdiff = (p*p*T[0][0]+q*q*T[1][1]+r*r*T[2][2]+2*p*q*T[0][1]+2*p*r*T[0][2]+2*q*r*T[1][2]);
+  //double ndiff = diff / (grad+eps);  
+  //double result = FA * FA * exp(ndiff * ndiff);
+  //double result = diff + p;
+  //double result = 1;//FA * FA * diff;
+  //double result = /*-(FA2/grad23)*diff*p;*/ (FA2/grad)*(2*p*N[0][0] + 2*q*N[0][1] + 2*r*N[0][2]);
+  //double result = (2*V[0][0]*dot) + (p/sqrt(grad));
+  //double result = p;//p / grad;
+  //  double result = (p*T[0][0] + q*T[0][1] + r*T[0][2]) / (sqrt(tdiff) + eps);
+  double result = (p/grad)*tdiff + grad*(p*T[0][0] + q*T[0][1] + r*T[0][2]);
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxConnectivity::SolveHq(int coord[3], int index, double p, double q, double r,
+				      float T[3][3], float N[3][3], float V[3][3], float FA)
+{ 
+  double FA2 = FA*FA;
+  double eps = 1E-12;
+  double grad = sqrt(p*p + q*q + r*r) + eps;
+  double dot = (p*V[0][0] + q*V[0][1] + r*V[0][2]);
+  double grad23 = pow(p*p + q*q + r*r, 3.0/2.0);
+  //double diff = (p*p*N[0][0]+q*q*N[1][1]+r*r*N[2][2]+2*p*q*N[0][1]+2*p*r*N[0][2]+2*q*r*N[1][2]);
+  double tdiff = (p*p*T[0][0]+q*q*T[1][1]+r*r*T[2][2]+2*p*q*T[0][1]+2*p*r*T[0][2]+2*q*r*T[1][2]);
+  //double ndiff = diff / (grad+eps);  
+  //double result = FA * FA * exp(ndiff * ndiff);
+  //double result = diff + q;
+  //double result = 1;//FA * FA * diff;
+  //double result = /*-(FA2/grad23)*diff*q;*/ (FA2/grad)*(2*p*N[0][1] + 2*q*N[1][1] + 2*r*N[1][2]);
+  //double result = (2*V[0][1]*dot) + (q/sqrt(grad));
+  //double result = 0.5*q;//q / grad;
+  //double result = (FA2/grad)*(2*q*T[1][1] + 2*p*T[0][1] + 2*r*T[1][2]);
+  //double result = (q*T[1][1] + p*T[0][1] + r*T[1][2]) / (sqrt(tdiff) + eps);
+  double result = (q/grad)*tdiff + grad*(q*T[1][1] + p*T[0][1] + r*T[1][2]);
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxConnectivity::SolveHr(int coord[3], int index, double p, double q, double r,
+				      float T[3][3], float N[3][3], float V[3][3], float FA)
+{
+  double FA2=FA*FA;
+  double eps = 1E-12;
+  double grad = sqrt(p*p + q*q + r*r) + eps;
+  double dot = (p*V[0][0] + q*V[0][1] + r*V[0][2]);
+  double grad23 = pow(p*p + q*q + r*r, 3.0/2.0);
+  double prod = (p*V[0][0] + q*V[0][1] + r*V[0][2]) / (sqrt(grad)+eps);
+  //double diff = (p*p*N[0][0]+q*q*N[1][1]+r*r*N[2][2]+2*p*q*N[0][1]+2*p*r*N[0][2]+2*q*r*N[1][2]);
+  double tdiff = (p*p*T[0][0]+q*q*T[1][1]+r*r*T[2][2]+2*p*q*T[0][1]+2*p*r*T[0][2]+2*q*r*T[1][2]);
+  //double ndiff = diff / (grad+eps);  
+  //double result = FA * FA * exp(ndiff * ndiff);
+  //double result = 1;//FA * FA * diff;
+  //double result = /*-(FA2/grad23)*diff*r;*/ (FA2/grad)*(2*p*N[0][2] + 2*q*N[1][2] + 2*r*N[2][2]);
+  //double result = (2*V[0][2]*dot) + (r/sqrt(grad));
+  //double result = (FA2/grad)*(2*r*T[2][2] + 2*p*T[0][2] + 2*q*T[1][2]);
+  //double result = (r*T[2][2] + p*T[0][2] + q*T[1][2]) / (sqrt(tdiff) + eps);
+  double result = (r/grad)*tdiff + grad*(r*T[2][2] + p*T[0][2] + q*T[1][2]);
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxConnectivity::SolveH(int coord[3], int index, double p, double q, double r,
+				     float T[3][3], float N[3][3], float V[3][3], float FA)
+{
+  double FA2 = FA*FA;
+  double eps = 1E-12;
+  double grad = p*p + q*q + r*r;
+  double dot = (p*V[0][0] + q*V[0][1] + r*V[0][2]);
+  double prod = (p*V[0][0] + q*V[0][1] + r*V[0][2]) / (sqrt(grad)+eps);
+  
+  double diff = (p*p*N[0][0]+q*q*N[1][1]+r*r*N[2][2]+2*p*q*N[0][1]+2*p*r*N[0][2]+2*q*r*N[1][2]);
+  double tdiff = (p*p*T[0][0]+q*q*T[1][1]+r*r*T[2][2]+2*p*q*T[0][1]+2*p*r*T[0][2]+2*q*r*T[1][2]);
+  double ndiff = diff / (grad+eps);  
+  //double result = sqrt(grad) * FA*FA * exp(ndiff * ndiff);
+  
+  //latest:
+  //double result = FA * FA * (tdiff / sqrt(grad) + eps);
+  //double result = (tdiff / sqrt(grad) + eps);
+  double result = sqrt(grad) * (T[0][0]+q*q*T[1][1]+r*r*T[2][2]+2*p*q*T[0][1]+2*p*r*T[0][2]+2*q*r*T[1][2]);
+  
+  //double result = FA * FA * ndiff;  
+  //double result = dot * dot + sqrt(grad);  
+  //double result = FA * FA * ndiff / (sqrt(grad) + eps);
+  
+  //if (FA <0.5) {
+  // PrintMatrix3x3("N=\n",N);
+  // PrintMatrix3x3("T=\n",T);
+  //}
+  //printf("ndiff=%f\n",ndiff);
+  // }
+  //  printf("result=%f\n",result);
+  // if (result == 0) {
+  // printf("%d %d %d FA=%f, ndiff=%f, grad=%f, [p,q,r]=%f,%f,%f\n",coord[0],coord[1],coord[2],FA,ndiff,grad,p,q,r);
+  //}
+
+  //double result = FA*FA * sqrt(grad) * exp(prod * prod * prod * prod);
+  //double result = FA*FA * sqrt(grad) * exp(prod * prod * prod);
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxConnectivity::Update(vtkImageData *input, vtkImageData *output, int coord[3], int index)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  
+  float T[3][3], N[3][3], V[3][3];
+  float W[3], R[3];
+  float FA;
+
+  // compute tensor
+  if (this->SymmetricTensor) {
+    T[0][0] = in->GetComponent(index, 0);           /* Dxx */
+    T[1][0] = T[0][1] = in->GetComponent(index, 1); /* Dxy */
+    T[2][0] = T[0][2] = in->GetComponent(index, 2); /* Dxz */
+    T[1][1] = in->GetComponent(index, 3);           /* Dyy */
+    T[2][1] = T[1][2] = in->GetComponent(index, 4); /* Dyz */
+    T[2][2] = in->GetComponent(index, 5);           /* Dzz */
+  } else {
+    T[0][0] = in->GetComponent(index, 0);           /* Dxx */
+    T[1][0] = T[0][1] = in->GetComponent(index, 1); /* Dxy */
+    T[2][0] = T[0][2] = in->GetComponent(index, 2); /* Dxz */
+    T[1][1] = in->GetComponent(index, 4);           /* Dyy */
+    T[2][1] = T[1][2] = in->GetComponent(index, 5); /* Dyz */
+    T[2][2] = in->GetComponent(index, 8);           /* Dzz */
+  }
+  this->NormalizeTensor3x3(T,W,V,N);
+  
+  //PrintMatrix3x3("normT=",N);
+
+  // calculate FA
+  float md = (W[0] + W[1] + W[2]) / 3.0;
+  float a=W[0]-md;
+  float b=W[1]-md;
+  float c=W[2]-md;
+  FA = sqrt(3.0/2.0) * sqrt((a*a + b*b + c*c) / (W[0]*W[0] + W[1]*W[1] + W[2]*W[2]));
+  //if (FA == 0.0) FA = 0.15;
+  //  printf("FA=%f,%f,%f,%f\n",FA,W[0],W[1],W[2]);
+ 
+  //  printf("FA=%f\n",FA);
+
+  // Lax-Friedrichs Method
+  double hx = this->Spacing[0]; //(float) (dim[0]-2) / (dim[0]-1);
+  double hy = this->Spacing[1]; //(float) (dim[1]-2) / (dim[1]-1);
+  double hz = this->Spacing[2]; //(float) (dim[2]-2) / (dim[2]-1);
+
+  double pp, pm, qp, qm, rp, rm;
+  double phi_p, phi_q, phi_r;
+  int neighbor[3];
+  
+  // for p
+  neighbor[0] = index - factor[0];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[0];
+  
+  pp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hx;
+  pm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hx;
+  phi_p = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) / hx;
+
+  // for q
+  neighbor[0] = index - factor[1];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[1];
+  
+  qp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hy;
+  qm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hy;
+  phi_q = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) /hy;
+  
+  // for r
+  neighbor[0] = index - factor[2];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[2];
+  
+  rp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hz;
+  rm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hz;
+  phi_r = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) /hz;
+
+  double pmin, pmax;
+  if (fabs(pp) > fabs(pm)) {   /* >= */
+    pmax = fabs(pp); pmin = fabs(pm);
+  } else {
+    pmax = fabs(pm); pmin = fabs(pp);
+  }
+  
+  double qmin, qmax;
+  if (fabs(qp) > fabs(qm)) {   /* >= */
+    qmax = fabs(qp); qmin = fabs(qm);
+  } else {
+    qmax = fabs(qm); qmin = fabs(qp);
+  }
+  
+  double rmin, rmax;
+  if (fabs(rp) > fabs(rm)) {   /* >= */
+    rmax = fabs(rp); rmin = fabs(rm);
+  } else {
+    rmax = fabs(rm); rmin = fabs(rp);
+  }
+
+  //PrintMatrix3x3("N=",T);
+  //printf("W=%f,%f,%f\n",W[0],W[1],W[2]);
+  //if (coord[0]==42 && coord[1]==80 && coord[2]==17) {
+  //FA = 0.28;
+  //}
+
+  if (FA > 1.0)
+    printf("Fa=%f at %d,%d,%d\n",FA,coord[0],coord[1],coord[2]);
+
+  if (FA < 0.10) {
+    FA = 1E-12;
+  }   
+
+  double H = SolveH(coord, index, (fabs(pp)+fabs(pm))/2.0, (fabs(qp)+fabs(qm))/2.0, (fabs(rp)+fabs(rm))/2.0, 
+		    T, N, V, FA);
+
+  double ox = SolveHp(coord, index, pmax, qmin, rmin, T, N, V, FA);
+  double oy = SolveHq(coord, index, pmin, qmax, rmin, T, N, V, FA);
+  double oz = SolveHr(coord, index, pmin, qmin, rmax, T, N, V, FA);
+  
+  double visc = 1.0 / (ox/hx + oy/hy + oz/hz);
+  double phi = visc * ( 1.0 - H + (ox/2)*phi_p + (oy/2)*phi_q + (oz/2)*phi_r );
+  
+  //printf("pm=%f,pp=%f,qm=%f,qp=%f,rm=%f,rp=%f\n",pm,pp,qm,qp,rm,rp);
+  if (coord[0]==42 && coord[1]==80 && coord[2]==17) {
+    //printf("17: H=%f c=%f, ox=%f, oy=%f, oz=%f, phi=%f, visc=%f, phi_p=%f, phi_q=%f, phi_r=%f, rp=%f, rm=%f, FA=%f\n\n",H,c,ox,oy,oz,phi,visc,phi_p,phi_q,phi_r,rp,rm,FA);
+  }  
+  if (coord[0]==42 && coord[1]==80 && coord[2]==18) {
+    // printf("18: H=%f c=%f, ox=%f, oy=%f, oz=%f, phi=%f, visc=%f, phi_p=%f, phi_q=%f, phi_r=%f, rp=%f, rm=%f, FA=%f\n\n",H,c,ox,oy,oz,phi,visc,phi_p,phi_q,phi_r,rp,rm,FA);
+  }  
+  //printf("phi=%f\n",phi);
+
+  //  if (coord[0]==8 && coord[1]==24 && coord[2]==28)
+  // printf("phi=%f, FA=%f, H=%f\n",phi,FA,H);
+
+  return phi;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxConnectivity::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3];  input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  
+  if (this->GetInput()==NULL) {
+    vtkErrorMacro(<<"No Input Image\n Exiting\n");
+    return;
+  }
+  
+  this->pog = 0.0; 
+  this->tenth=4;//(int)(this->NumberOfIterations*8);
+  this->count=0;
+  
+  this->Initialize(input, output);
+  
+  for(int j=0; j<this->NumberOfIterations; j++) {
+    
+    // reset error and iteration number
+    this->ErrorValue = 0;
+    this->IterationNumber = j+1;   
+    
+    this->Iterate(input, output);
+    
+    if ((this->StopOnMaximumError) && (this->ErrorValue <= this->MaximumError))
+      break;    
+  }
+  
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLaxConnectivity.h b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxConnectivity.h
new file mode 100644
index 0000000..652d3d8
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxConnectivity.h
@@ -0,0 +1,186 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+   -- vtkmpjLaxConnectivity.h --
+   
+   Implements Stanley Osher's Fast Sweeping Scheme for solving
+   Static Hamilton-Jacobi Equations
+   
+   Marcel Jackowski, Feb. 2004.
+   
+*/
+
+#define VTK_MPJ_KNOWN   100   
+#define VTK_MPJ_UNKNOWN   0   
+
+#ifndef __vtkmpjLaxConnectivity_h
+#define __vtkmpjLaxConnectivity_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageAccumulate.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjLaxConnectivity : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjLaxConnectivity *New();
+  vtkTypeMacro(vtkmpjLaxConnectivity,vtkpxSimpleImageToImageFilter);
+  
+  // Description:
+  // Set/Get boundary conditions for the propagation. You can also
+  // set the boundary points in the label image. See below.
+  vtkSetObjectMacro(KnownPoints, vtkFloatArray);
+  vtkGetObjectMacro(KnownPoints, vtkFloatArray);
+  
+  // Description:
+  // Get/Set total number of Iterations
+  vtkGetMacro(NumberOfIterations,int);
+  vtkSetMacro(NumberOfIterations,int);
+  
+  // Description:
+  // Set/Get the label image. If KnownPoints is not set, then
+  // LabelImage must have values >0 for initialized (boundary) points,
+  // and 0 for points on the grid to be calculated. 
+  vtkGetObjectMacro(LabelImage, vtkImageData);
+  vtkSetObjectMacro(LabelImage, vtkImageData);
+  
+  // Description:
+  // Set initial solution for boundary points.
+  vtkSetObjectMacro(Solution, vtkImageData);
+  
+  // Description:
+  // Get convergence image
+  vtkGetObjectMacro(ConvergenceImage, vtkImageData);
+  
+  // Description:
+  // Set/Get tensor symmetry flag
+  vtkSetMacro(SymmetricTensor, int);
+  vtkGetMacro(SymmetricTensor, int);
+  vtkBooleanMacro(SymmetricTensor, int);
+
+  // Description:
+  // Enables/disables stopping at maximum error
+  vtkSetMacro(StopOnMaximumError, int);
+  vtkGetMacro(StopOnMaximumError, int);
+  vtkBooleanMacro(StopOnMaximumError, int);
+
+  // Description:
+  // Get/Set maximum error value
+  vtkGetMacro(MaximumError,float);
+  vtkSetMacro(MaximumError,float);
+
+  // Description:
+  // Get/Set error value
+  vtkGetMacro(ErrorValue,float);
+  vtkSetMacro(ErrorValue,float);
+
+  // Description:
+  // Get/Set error value
+  vtkGetMacro(IterationNumber,int);
+  vtkSetMacro(IterationNumber,int);
+  
+  // Description:
+  // Get/Set grid spacing
+  vtkGetVector3Macro(Spacing,float);
+  vtkSetVector3Macro(Spacing,float);
+
+  // Description:
+  // Set/Get infinity value
+  vtkGetMacro(Infinity,float);
+  vtkSetMacro(Infinity,float);
+
+ protected:
+  float Infinity;
+  int SymmetricTensor;
+  int NumberOfIterations;
+  int KnownValues;
+  float ErrorValue;
+  int StopOnMaximumError;
+  float MaximumError;
+  int IterationNumber;
+  float Spacing[3];
+  vtkFloatArray *KnownPoints;
+  vtkImageData *Mask;
+  vtkImageData *Solution;
+  vtkImageData *LabelImage;
+  vtkDataArray *label;
+  vtkImageData *ConvergenceImage;
+  vtkDataArray *convergence;
+    
+  vtkmpjLaxConnectivity();
+  ~vtkmpjLaxConnectivity();
+  
+  virtual void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+
+  void Initialize(vtkImageData *input, vtkImageData *output);
+  void Iterate(vtkImageData *input, vtkImageData *output);
+
+  void Sweep(vtkImageData *input, vtkImageData *output, int dir[3]);
+  void SweepBoundaries(vtkImageData *input, vtkImageData *output);
+
+  double Update(vtkImageData *input, vtkImageData *output, 
+		int coord[3], int index);
+  
+  double SolveH(int coord[3], int index, double p, double q, double r, 
+		float T[3][3], float N[3][3], float V[3][3], float FA);
+  double SolveHp(int coord[3], int index, double p, double q, double r, 
+		 float T[3][3], float N[3][3], float V[3][3], float FA); 
+  double SolveHq(int coord[3], int index, double p, double q, double r, 
+		 float T[3][3], float N[3][3], float V[3][3], float FA);
+  double SolveHr(int coord[3], int index, double p, double q, double r, 
+		 float T[3][3], float N[3][3], float V[3][3], float FA);
+  
+  void NormalizeTensor3x3(float T[3][3], float W[3], float V[3][3], 
+			  float N[3][3]);
+  void Jacobi3x3(float a[3][3], float w[3], float v[3][3]);
+ 
+
+ private: 
+  //BTX
+  float pog;
+  int count, tenth; 
+  //ETX
+  void PrintMatrix3x3(char *title, float M[3][3]);
+
+  vtkmpjLaxConnectivity(const vtkmpjLaxConnectivity&);// Not implemented
+  void operator=(const vtkmpjLaxConnectivity&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichEuclidean.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichEuclidean.cpp
new file mode 100644
index 0000000..837c423
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichEuclidean.cpp
@@ -0,0 +1,491 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjLaxFriedrichEuclidean.h"
+
+#define VTK_MPJ_LARGE_FLOAT 32767
+
+//------------------------------------------------------------------------------
+vtkmpjLaxFriedrichEuclidean* vtkmpjLaxFriedrichEuclidean::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjLaxFriedrichEuclidean");
+  if(ret) {
+    return (vtkmpjLaxFriedrichEuclidean*)ret;
+  }
+  
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjLaxFriedrichEuclidean;
+}
+
+// Construct object with no children.
+vtkmpjLaxFriedrichEuclidean::vtkmpjLaxFriedrichEuclidean()
+{
+  this->KnownPoints = NULL;
+  this->KnownValues = 1;
+  this->NumberOfIterations = 2;
+  this->Speed = NULL;  
+  this->label = NULL;
+  this->Solution=NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjLaxFriedrichEuclidean::~vtkmpjLaxFriedrichEuclidean()
+{
+  if (this->KnownPoints != NULL)
+    this->KnownPoints->Delete();
+  if (this->LabelImage != NULL)
+    this->LabelImage->Delete();
+  if (this->ConvergenceImage != NULL) 
+    this->ConvergenceImage->Delete();
+  if (this->Solution != NULL)
+    this->Solution->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichEuclidean::SetSpeedImage(vtkImageData *speed)
+{
+  this->SetInput(speed);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichEuclidean::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+   
+  if (this->KnownPoints==NULL) {
+    vtkErrorMacro(<<"Set of known points is empty!");
+    return;
+  }
+
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichEuclidean::Initialize(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  vtkDataArray *sol = NULL;
+  if (this->Solution != NULL) {
+    sol = this->Solution->GetPointData()->GetScalars();
+  }
+
+  // Create label image
+  this->LabelImage = vtkImageData::New();
+  this->LabelImage->SetSpacing(input->GetSpacing());
+  this->LabelImage->SetOrigin(input->GetOrigin());
+  this->LabelImage->SetDimensions(input->GetDimensions());
+  this->LabelImage->SetScalarType(VTK_SHORT);
+  this->LabelImage->SetNumberOfScalarComponents(1);
+  this->LabelImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->LabelImage->AllocateScalars();
+  this->label = this->LabelImage->GetPointData()->GetScalars();
+  this->label->FillComponent(0, VTK_MPJ_UNKNOWN);
+
+  // Create convergence image
+  this->ConvergenceImage = vtkImageData::New();
+  this->ConvergenceImage->SetSpacing(input->GetSpacing());
+  this->ConvergenceImage->SetOrigin(input->GetOrigin());
+  this->ConvergenceImage->SetDimensions(input->GetDimensions());
+  this->ConvergenceImage->SetScalarType(VTK_FLOAT);
+  this->ConvergenceImage->SetNumberOfScalarComponents(1);
+  this->ConvergenceImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->ConvergenceImage->AllocateScalars();
+  this->convergence = this->ConvergenceImage->GetPointData()->GetScalars();
+  this->convergence->FillComponent(0, VTK_MPJ_LARGE_FLOAT);
+
+  // Initialize values to infinity
+  if (this->Solution == NULL)
+    out->FillComponent(0, VTK_MPJ_LARGE_FLOAT);
+  else {
+    int numtuples = sol->GetNumberOfTuples();
+    for(int i=0; i<numtuples; i++)
+      out->SetComponent(i, 0, sol->GetComponent(i, 0));
+  }
+  
+  int coord[3]; 
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  // Set initial conditions
+  for(int i=0; i<this->KnownPoints->GetNumberOfTuples(); i++) {
+    
+    coord[0] = (int)this->KnownPoints->GetComponent(i, 0);
+    coord[1] = (int)this->KnownPoints->GetComponent(i, 1);
+    coord[2] = (int)this->KnownPoints->GetComponent(i, 2);
+    float value = this->KnownValues ? this->KnownPoints->GetComponent(i, 3) : 0.0;
+    
+    int index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+    
+    this->label->SetComponent(index, 0, VTK_MPJ_KNOWN);  // Freeze voxel    
+    this->convergence->SetComponent(index, 0, 0.0);      // Boundary point has exact value
+    out->SetComponent(index, 0, (float)value);           // Set arrival time
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichEuclidean::Iterate(vtkImageData *input, vtkImageData *output)
+{
+  for(int s1=-1; s1<2; s1+=2)
+    for(int s2=-1; s2<2; s2+=2)
+      for(int s3=-1; s3<2; s3+=2) {
+
+	int dir[3] = {s1, s2, s3};
+
+	//printf("sweeping at direction: %d %d %d\n",s1,s2,s3);
+	
+	this->Sweep(input, output, dir);
+	this->SweepBoundaries(input, output);
+	
+	this->count++;
+	if (this->count==this->tenth)
+	  {
+	    this->pog+=0.1;
+	    this->UpdateProgress(this->pog);
+	    this->count=0;
+	  }
+      }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichEuclidean::SweepBoundaries(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  int index;
+  float val0, val1, val2, result;
+
+  // rows
+  for(int k=0; k<dim[2]; k++)  // for all slices
+    for(int i=0; i<dim[0]; i++)  // for all columns in this row
+      {
+	// top row
+	index = dim0Tdim1*k + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + dim[0]*1, 0);
+	val2 = out->GetComponent(index + dim[0]*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+
+	// bottom row
+	index = dim0Tdim1*k + dim[0]*(dim[1]-1) + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - dim[0]*1, 0);
+	val2 = out->GetComponent(index - dim[0]*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+
+  // for columns
+  for(int k=0; k<dim[2]; k++)  // for all slices
+    for(int j=0; j<dim[1]; j++)  // for all rows
+      {
+	// left column
+	index = dim0Tdim1*k + dim[0]*j;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + 1, 0);
+	val2 = out->GetComponent(index + 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+
+	// right column
+	index = dim0Tdim1*k + dim[0]*j + dim[0]-1;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - 1, 0);
+	val2 = out->GetComponent(index - 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+  
+  // for slices
+  for(int i=0; i<dim[0]; i++)  // for all columns
+    for(int j=0; j<dim[1]; j++) // for all rows      
+      { 
+	// first slice
+	index = dim[0]*j + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index + dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+	
+	// last slice
+	index = dim0Tdim1*(dim[2]-1) + dim[0]*j + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index - dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else 
+	  this->convergence->SetComponent(index, 0, 0.0);
+					  
+      }  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichEuclidean::Sweep(vtkImageData *input, vtkImageData *output, int dir[3])
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  // Sweep image
+  for(int k=(dir[2]<0?dim[2]-2:1);(dir[2]<0?k>0:k<dim[2]-1);k+=dir[2])     
+    for(int j=(dir[1]<0?dim[1]-2:1);(dir[1]<0?j>0:j<dim[1]-1);j+=dir[1])
+      for(int i=(dir[0]<0?dim[0]-2:1);(dir[0]<0?i>0:i<dim[0]-1);i+=dir[0]) {
+	
+	int index = dim0Tdim1*k + dim[0]*j + i;
+	int coord[3] = {i, j, k};
+	
+	if (this->label->GetComponent(index, 0) == VTK_MPJ_UNKNOWN) { 
+	  
+	  double new_value = this->Update(input, output, coord, index);
+	  
+	  if (new_value < out->GetComponent(index, 0)) {
+	    
+	    // compute convergence 
+	    double old_value = out->GetComponent(index, 0);
+	    this->convergence->SetComponent(index, 0, fabs(new_value - old_value));
+	    
+	    out->SetComponent(index, 0, (float)new_value);	    
+
+	  } else 
+	    this->convergence->SetComponent(index, 0, 0.0);
+	}	
+      }   
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichEuclidean::SolveHp(int coord[3], int index, double p, double q, double r)
+{
+  double eps = 1E-12;
+  double grad = p*p + q*q + r*r;
+  double result = p/(sqrt(grad)+eps);
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichEuclidean::SolveHq(int coord[3], int index, double p, double q, double r)
+{
+  double eps = 1E-12;
+  double grad = p*p + q*q + r*r;
+  double result = q/(sqrt(grad)+eps);
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichEuclidean::SolveHr(int coord[3], int index, double p, double q, double r)
+{
+  double eps = 1E-12;
+  double grad = p*p + q*q + r*r;
+  double result = r/(sqrt(grad)+eps); 
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichEuclidean::SolveH(int coord[3], int index, double p, double q, double r)
+{
+  // 3D Eikonal
+  double result = sqrt(p*p + q*q + r*r);
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichEuclidean::Update(vtkImageData *input, vtkImageData *output, int coord[3], int index)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  
+  // Lax-Friedrichs Method
+  double hx = 0.25; //(float) (dim[0]-2) / (dim[0]-1);
+  double hy = 0.25; //(float) (dim[1]-2) / (dim[1]-1);
+  double hz = 0.25; //(float) (dim[2]-2) / (dim[2]-1);
+
+  double pp, pm, qp, qm, rp, rm;
+  double phi_p, phi_q, phi_r;
+  int neighbor[3];
+  
+  // for p
+  neighbor[0] = index - factor[0];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[0];
+  
+  pp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hx;
+  pm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hx;
+  phi_p = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) / hx;
+
+  // for q
+  neighbor[0] = index - factor[1];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[1];
+  
+  qp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hy;
+  qm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hy;
+  phi_q = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) /hy;
+  
+  // for r
+  neighbor[0] = index - factor[2];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[2];
+  
+  rp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hz;
+  rm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hz;
+  phi_r = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) /hz;
+
+  double pmin, pmax;
+  if (fabs(pp) >= fabs(pm)) {
+    pmax = fabs(pp); pmin = fabs(pm);
+  } else {
+    pmax = fabs(pm); pmin = fabs(pp);
+  }
+  
+  double qmin, qmax;
+  if (fabs(qp) >= fabs(qm)) {
+    qmax = fabs(qp); qmin = fabs(qm);
+  } else {
+    qmax = fabs(qm); qmin = fabs(qp);
+  }
+  
+  double rmin, rmax;
+  if (fabs(rp) >= fabs(rm)) {
+    rmax = fabs(rp); rmin = fabs(rm);
+  } else {
+    rmax = fabs(rm); rmin = fabs(rp);
+  }
+
+  double H = SolveH(coord, index, (pp+pm)/2.0, (qp+qm)/2.0, (rp+rm)/2.0);   
+  double ox = SolveHp(coord, index, pmax, qmin, rmin);
+  double oy = SolveHq(coord, index, pmin, qmax, rmin);
+  double oz = SolveHr(coord, index, pmin, qmin, rmax);
+  
+  double visc = 1.0 / (ox/hx + oy/hy + oz/hz);
+  double phi = visc * ( 1.0 - H + (ox/2)*phi_p + (oy/2)*phi_q + (oz/2)*phi_r );
+  
+  //printf("pm=%f,pp=%f,qm=%f,qp=%f,rm=%f,rp=%f\n",pm,pp,qm,qp,rm,rp);
+  //if (coord[0]==15 && coord[1]==16 && coord[2]==16) {
+  //printf("H=%f c=%f, ox=%f, oy=%f, oz=%f, hx=%f, hy=%f, hz=%f, phi=%f\n",H,c,ox,oy,oz,hx,hy,hz,phi);
+  //}  
+  //printf("phi=%f\n",phi);
+
+  return phi;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichEuclidean::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3];  input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  
+  if (this->GetInput()==NULL) {
+    vtkErrorMacro(<<"No Input Image\n Exiting\n");
+    return;
+  }
+  
+  this->pog = 0.0;  
+  this->tenth=(int)((8*this->NumberOfIterations) / 8.0);
+  this->count=0;
+
+  printf("initializing...\n");
+  this->Initialize(input, output);
+
+  this->UpdateProgress(0.01);
+  
+  for(int j=0; j<this->NumberOfIterations; j++) {
+    printf("sweeping iteration %d\n", j);
+    this->Iterate(input, output);
+  }
+  
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichEuclidean.h b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichEuclidean.h
new file mode 100644
index 0000000..fc12698
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichEuclidean.h
@@ -0,0 +1,132 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+   -- vtkmpjLaxFriedrichEuclidean.h --
+   
+   Implements Stanley Osher's Fast Sweeping Scheme for solving
+   Static Hamilton-Jacobi Equations
+   
+   Formulation for 3-D Euclidean distance.
+
+   Marcel Jackowski, Feb. 2004.
+   
+*/
+
+#define VTK_MPJ_KNOWN   100   
+#define VTK_MPJ_UNKNOWN   0   
+
+#ifndef __vtkmpjLaxFriedrichEuclidean_h
+#define __vtkmpjLaxFriedrichEuclidean_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageAccumulate.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjLaxFriedrichEuclidean : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjLaxFriedrichEuclidean *New();
+  vtkTypeMacro(vtkmpjLaxFriedrichEuclidean,vtkpxSimpleImageToImageFilter);
+  
+  // Description: Sets speed image
+  void SetSpeedImage(vtkImageData *speed);
+  
+  // Description:
+  // Set/Get boundary conditions for the propagation
+  vtkSetObjectMacro(KnownPoints, vtkFloatArray);
+  vtkGetObjectMacro(KnownPoints, vtkFloatArray);
+  
+  // Description:
+  // Get/Set Number of Iterations
+  vtkGetMacro(NumberOfIterations,int);
+  vtkSetMacro(NumberOfIterations,int);
+
+  // Front label image. Points interior to the front have value -1, points 
+  // on the front boundary have value 0, and points outside have value +1.
+  vtkGetObjectMacro(LabelImage, vtkImageData);
+  vtkGetObjectMacro(ConvergenceImage, vtkImageData);
+  
+  // Description:
+  // Set/Get Solution
+  vtkSetObjectMacro(Solution, vtkImageData);
+  vtkGetObjectMacro(Solution, vtkImageData);
+    
+ protected:
+  int SecondOrder;
+  int NumberOfIterations;
+  int KnownValues;
+  vtkImageData *Speed;
+  vtkImageData *Solution;
+  vtkFloatArray *KnownPoints;
+  vtkImageData *LabelImage;
+  vtkImageData *ConvergenceImage;
+  vtkDataArray *label;
+  vtkDataArray *convergence;
+
+  vtkmpjLaxFriedrichEuclidean();
+  virtual ~vtkmpjLaxFriedrichEuclidean();
+  
+  void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+
+  void Initialize(vtkImageData *input, vtkImageData *output);
+  void Iterate(vtkImageData *input, vtkImageData *output);
+
+  void Sweep(vtkImageData *input, vtkImageData *output, int dir[3]);
+  void SweepBoundaries(vtkImageData *input, vtkImageData *output);
+
+  double Update(vtkImageData *input, vtkImageData *output, 
+		int coord[3], int index);
+  
+  double SolveH(int coord[3], int index, double p, double q, double r);
+  double SolveHp(int coord[3], int index, double p, double q, double r);
+  double SolveHq(int coord[3], int index, double p, double q, double r);
+  double SolveHr(int coord[3], int index, double p, double q, double r);
+
+ private: 
+  //BTX
+  float pog;
+  int count, tenth; 
+  //ETX
+  
+  vtkmpjLaxFriedrichEuclidean(const vtkmpjLaxFriedrichEuclidean&);// Not implemented
+  void operator=(const vtkmpjLaxFriedrichEuclidean&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichSweeping.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichSweeping.cpp
new file mode 100644
index 0000000..3a063cc
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichSweeping.cpp
@@ -0,0 +1,560 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjLaxFriedrichSweeping.h"
+
+#define VTK_MPJ_LARGE_FLOAT 32767
+
+//------------------------------------------------------------------------------
+vtkmpjLaxFriedrichSweeping* vtkmpjLaxFriedrichSweeping::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjLaxFriedrichSweeping");
+  if(ret) {
+    return (vtkmpjLaxFriedrichSweeping*)ret;
+  }
+  
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjLaxFriedrichSweeping;
+}
+
+// Construct object with no children.
+vtkmpjLaxFriedrichSweeping::vtkmpjLaxFriedrichSweeping()
+{
+  this->KnownPoints = NULL;
+  this->KnownValues = 1;
+  this->NumberOfIterations = 2;
+  this->SymmetricTensor = 1;
+  this->label = NULL;
+  this->LabelImage = NULL;
+  this->Solution = NULL;
+  this->ConvergenceImage = NULL;
+  this->convergence = NULL;
+  this->Gradient = NULL;
+  this->gradient = NULL;
+  this->ErrorValue = 0.0;
+  this->MaximumError = 1.0;
+  this->StopOnMaximumError = 0;
+  this->IterationNumber = 0;
+  this->Spacing[0] = 1.0;
+  this->Spacing[1] = 1.0;
+  this->Spacing[2] = 1.0;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjLaxFriedrichSweeping::~vtkmpjLaxFriedrichSweeping()
+{
+  if (this->KnownPoints != NULL)
+    this->KnownPoints->Delete();
+  if (this->LabelImage != NULL)
+    this->LabelImage->Delete();
+  if (this->ConvergenceImage != NULL) 
+    this->ConvergenceImage->Delete();
+  if (this->Solution != NULL)
+    this->Solution->Delete();
+  if (this->Gradient != NULL) 
+    this->Gradient->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweeping::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+   
+  if (this->KnownPoints==NULL) {
+    vtkErrorMacro(<<"Set of known points is empty!");
+    return;
+  }
+  
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweeping::Initialize(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  
+  // Create label image
+  if (this->LabelImage == NULL) {
+    printf("initializing label...\n");
+    this->LabelImage = vtkImageData::New();
+    this->LabelImage->SetSpacing(input->GetSpacing());
+    this->LabelImage->SetOrigin(input->GetOrigin());
+    this->LabelImage->SetDimensions(input->GetDimensions());
+    this->LabelImage->SetScalarType(VTK_SHORT);
+    this->LabelImage->SetNumberOfScalarComponents(1);
+    this->LabelImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+    this->LabelImage->AllocateScalars();
+    this->label = this->LabelImage->GetPointData()->GetScalars();    
+    this->label->FillComponent(0, VTK_MPJ_UNKNOWN);
+  } else {
+    this->label = this->LabelImage->GetPointData()->GetScalars();    
+  }
+  
+  // Create convergence image
+  this->ConvergenceImage = vtkImageData::New();
+  this->ConvergenceImage->SetSpacing(input->GetSpacing());
+  this->ConvergenceImage->SetOrigin(input->GetOrigin());
+  this->ConvergenceImage->SetDimensions(input->GetDimensions());
+  this->ConvergenceImage->SetScalarType(VTK_FLOAT);
+  this->ConvergenceImage->SetNumberOfScalarComponents(1);
+  this->ConvergenceImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->ConvergenceImage->AllocateScalars();
+  this->convergence = this->ConvergenceImage->GetPointData()->GetScalars();
+  this->convergence->FillComponent(0, 0);
+  
+  // Create gradient image
+  this->Gradient = vtkImageData::New();
+  this->Gradient->SetSpacing(input->GetSpacing());
+  this->Gradient->SetOrigin(input->GetOrigin());
+  this->Gradient->SetDimensions(input->GetDimensions());
+  this->Gradient->SetScalarType(VTK_FLOAT);
+  this->Gradient->SetNumberOfScalarComponents(3);
+  this->Gradient->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->Gradient->AllocateScalars();
+  this->gradient = this->Gradient->GetPointData()->GetScalars();
+  this->gradient->FillComponent(0, 0); 
+  this->gradient->FillComponent(1, 0);
+  this->gradient->FillComponent(2, 0);
+
+  // Initialize values to infinity if initial solution is not given
+  if (this->Solution == NULL) {
+    out->FillComponent(0, VTK_MPJ_LARGE_FLOAT);
+  } else {
+    // otherwise initialize with given values
+    vtkDataArray *sol = this->Solution->GetPointData()->GetScalars();
+    int numtuples = sol->GetNumberOfTuples();
+    for(int i=0; i<numtuples; i++)
+      out->SetComponent(i, 0, sol->GetComponent(i, 0));
+  }
+  
+  int coord[3]; 
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  // Set initial conditions
+  if (this->KnownPoints != NULL) {
+    
+    int nc = this->KnownPoints->GetNumberOfComponents();    
+    int num = this->KnownPoints->GetNumberOfTuples();
+    
+    for(int i=0; i<num; i++) {
+      
+      coord[0] = (int)this->KnownPoints->GetComponent(i, 0);
+      coord[1] = (int)this->KnownPoints->GetComponent(i, 1);
+      coord[2] = (int)this->KnownPoints->GetComponent(i, 2);
+      float value = (nc > 3) ? this->KnownPoints->GetComponent(i, 3) : 0.0;
+      
+      int index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+      
+      this->label->SetComponent(index, 0, VTK_MPJ_KNOWN);// Freeze voxel    
+      this->convergence->SetComponent(index, 0, 0.0); // Boundary point has exact value
+      out->SetComponent(index, 0, (float)value);  // Set arrival time
+    }
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweeping::Iterate(vtkImageData *input, vtkImageData *output)
+{
+  for(int s1=-1; s1<2; s1+=2)
+    for(int s2=-1; s2<2; s2+=2)
+      for(int s3=-1; s3<2; s3+=2) {
+
+	int dir[3] = {s1, s2, s3};
+
+	//printf("sweeping at direction: %d %d %d\n",s1,s2,s3);
+	this->Sweep(input, output, dir);
+	this->SweepBoundaries(input, output);
+	
+	this->count++;
+
+	if (this->count==this->tenth)
+	  {
+	    this->pog+=(4.0/(this->NumberOfIterations*8));
+	    this->UpdateProgress(this->pog);
+	    this->count=0;
+	  }
+      }
+}
+
+void vtkmpjLaxFriedrichSweeping::SweepBoundaries(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  
+  int index;
+  float val0, val1, val2, result;
+  float error;
+  
+  // rows
+  for(int k=0; k<dim[2]; k++)  // for all slices
+    for(int i=0; i<dim[0]; i++)  // for all columns in this row
+      {
+	// top row
+	index = dim0Tdim1*k + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + dim[0]*1, 0);
+	val2 = out->GetComponent(index + dim[0]*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  error = fabs(result - val0);
+	  if (error > this->ErrorValue) this->ErrorValue = error;
+	  this->convergence->SetComponent(index, 0, error);
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+	
+	// bottom row
+	index = dim0Tdim1*k + dim[0]*(dim[1]-1) + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - dim[0]*1, 0);
+	val2 = out->GetComponent(index - dim[0]*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  error = fabs(result - val0);
+	  if (error > this->ErrorValue) this->ErrorValue = error;
+	  this->convergence->SetComponent(index, 0, error);
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+  
+  // for columns
+  for(int k=0; k<dim[2]; k++)  // for all slices
+    for(int j=0; j<dim[1]; j++)  // for all rows
+      {
+	// left column
+	index = dim0Tdim1*k + dim[0]*j;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + 1, 0);
+	val2 = out->GetComponent(index + 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  error = fabs(result - val0);
+	  if (error > this->ErrorValue) this->ErrorValue = error;
+	  this->convergence->SetComponent(index, 0, error);
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+	
+	// right column
+	index = dim0Tdim1*k + dim[0]*j + dim[0]-1;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - 1, 0);
+	val2 = out->GetComponent(index - 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  error = fabs(result - val0);
+	  if (error > this->ErrorValue) this->ErrorValue = error;
+	  this->convergence->SetComponent(index, 0, error);
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+  
+  // for slices
+  for(int i=0; i<dim[0]; i++)  // for all columns
+    for(int j=0; j<dim[1]; j++) // for all rows      
+      { 
+	// first slice
+	index = dim[0]*j + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index + dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  error = fabs(result - val0);
+	  if (error > this->ErrorValue) this->ErrorValue = error;
+	  this->convergence->SetComponent(index, 0, error);
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+	
+	// last slice
+	index = dim0Tdim1*(dim[2]-1) + dim[0]*j + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index - dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  error = fabs(result - val0);
+	  if (error > this->ErrorValue) this->ErrorValue = error;
+	  this->convergence->SetComponent(index, 0, error);
+	} else 
+	  this->convergence->SetComponent(index, 0, 0.0);	
+      }  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweeping::Sweep(vtkImageData *input, vtkImageData *output, int dir[3])
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  double n[3];
+  vtkDataArray *domain = NULL;
+
+  // Sweep image
+  for(int k=(dir[2]<0?dim[2]-2:1);(dir[2]<0?k>0:k<dim[2]-1);k+=dir[2])     
+    for(int j=(dir[1]<0?dim[1]-2:1);(dir[1]<0?j>0:j<dim[1]-1);j+=dir[1])
+      for(int i=(dir[0]<0?dim[0]-2:1);(dir[0]<0?i>0:i<dim[0]-1);i+=dir[0]) {
+	
+	int index = dim0Tdim1*k + dim[0]*j + i;
+	int coord[3] = {i, j, k};
+	
+	// only update point if value is unknown and is part of the
+	// computational domain
+	if (this->label->GetComponent(index, 0) == VTK_MPJ_UNKNOWN) {
+	  
+	  double new_value = this->Update(input, output, coord, index, n);
+	  
+	  // only update if it's value is less than before
+	  if (new_value < out->GetComponent(index, 0)) {
+	    
+	    // compute convergence 
+	    double old_value = out->GetComponent(index, 0);	    
+	    double error = fabs(new_value - old_value);
+
+	    if (error > this->ErrorValue) this->ErrorValue = error;
+	    this->convergence->SetComponent(index, 0, error);
+	    
+	    out->SetComponent(index, 0, (float)new_value);	    
+	    
+	    gradient->SetComponent(index, 0, -n[0]);
+	    gradient->SetComponent(index, 1, -n[1]);
+	    gradient->SetComponent(index, 2, -n[2]);	    
+	    
+	  } else 
+	    this->convergence->SetComponent(index, 0, 0.0);
+	}	
+      }   
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichSweeping::SolveHp(int coord[3], int index, double p, double q, double r,double v)
+{
+  double eps = 1E-12;
+  double a = 1.0, b=1, c=1;
+  //double a = 1.0, b=0.5, c=0.1;
+  double result = 1+a*v; //1+3*a;
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichSweeping::SolveHq(int coord[3], int index, double p, double q, double r, double v)
+{
+  double eps = 1E-12;
+  double a = 1.0, b=1, c=1;
+  //double a = 1.0, b=0.5, c=0.1;
+  double result = 1+b*v; //1+3*b;
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichSweeping::SolveHr(int coord[3], int index, double p, double q, double r, double v)
+{
+  double eps = 1E-12;
+  double a = 1.0, b=1, c=1;
+  //double a = 1.0, b=0.5, c=0.1;
+  double result = 1+c*v; //1+3*c;
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichSweeping::SolveH(int coord[3], int index, double p, double q, double r, double v)
+{
+  double a = 1.0, b=1, c=1;
+  //double a = 1.0, b=0.5, c=0.1;
+  //double a=1.0/1, b=1.0/4, c=1.0/9;
+  //double a=9.0/(9+4+1), b=4.0/(9+4+1), c=1.0/(9+4+1);
+  double eps = 1E-12;
+  double grad = p*p + q*q + r*r;
+  
+  
+  //double result = p*p + sqrt(grad) / (sqrt(grad)+eps);
+  double result = sqrt(a*p*p + b*q*q + c*r*r) * v;
+ 
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichSweeping::Update(vtkImageData *input, vtkImageData *output, int coord[3], int index, double n[3])
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  
+  // Lax-Friedrichs Method
+  double hx = this->Spacing[0]; //(float) (dim[0]-2) / (dim[0]-1);
+  double hy = this->Spacing[1]; //(float) (dim[1]-2) / (dim[1]-1);
+  double hz = this->Spacing[2]; //(float) (dim[2]-2) / (dim[2]-1);
+
+  double pp, pm, qp, qm, rp, rm;
+  double phi_p, phi_q, phi_r;
+  int neighbor[3];
+  
+  // for p
+  neighbor[0] = index - factor[0];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[0];
+  
+  pp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hx;
+  pm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hx;
+  phi_p = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) / hx;
+
+  // for q
+  neighbor[0] = index - factor[1];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[1];
+  
+  qp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hy;
+  qm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hy;
+  phi_q = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) /hy;
+  
+  // for r
+  neighbor[0] = index - factor[2];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[2];
+  
+  rp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hz;
+  rm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hz;
+  phi_r = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) /hz;
+
+  double pmin, pmax;
+  if (fabs(pp) > fabs(pm)) {   /* >= */
+    pmax = fabs(pp); pmin = fabs(pm);
+  } else {
+    pmax = fabs(pm); pmin = fabs(pp);
+  }
+  
+  double qmin, qmax;
+  if (fabs(qp) > fabs(qm)) {   /* >= */
+    qmax = fabs(qp); qmin = fabs(qm);
+  } else {
+    qmax = fabs(qm); qmin = fabs(qp);
+  }
+  
+  double rmin, rmax;
+  if (fabs(rp) > fabs(rm)) {   /* >= */
+    rmax = fabs(rp); rmin = fabs(rm);
+  } else {
+    rmax = fabs(rm); rmin = fabs(rp);
+  }
+
+  double speed = in->GetComponent(index, 0);
+  double H = SolveH(coord, index, (fabs(pp)+fabs(pm))/2.0, (fabs(qp)+fabs(qm))/2.0, (fabs(rp)+fabs(rm))/2.0, speed);
+  double ox = SolveHp(coord, index, pmax, qmin, rmin, speed);
+  double oy = SolveHq(coord, index, pmin, qmax, rmin, speed);
+  double oz = SolveHr(coord, index, pmin, qmin, rmax, speed);
+  
+  double visc = 1.0 / (ox/hx + oy/hy + oz/hz);
+  double phi = visc * ( 1.0 - H + (ox/2)*phi_p + (oy/2)*phi_q + (oz/2)*phi_r );
+  
+  n[0] = (fabs(pp)+fabs(pm))/2.0;
+  n[1] = (fabs(qp)+fabs(qm))/2.0;
+  n[2] = (fabs(rp)+fabs(rm))/2.0;
+
+  return phi;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweeping::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3];  input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  
+  if (this->GetInput()==NULL) {
+    vtkErrorMacro(<<"No Input Image\n Exiting\n");
+    return;
+  }
+  
+  this->pog = 0.0; 
+  this->tenth=4;//(int)(this->NumberOfIterations*8);
+  this->count=0;
+  
+  this->Initialize(input, output);
+  
+  for(int j=0; j<this->NumberOfIterations; j++) {
+    
+    // reset error and iteration number
+    this->ErrorValue = 0;
+    this->IterationNumber = j+1;   
+    
+    this->Iterate(input, output);
+    
+    if ((this->StopOnMaximumError) && (this->ErrorValue <= this->MaximumError))
+      break;    
+  }
+  
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichSweeping.h b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichSweeping.h
new file mode 100644
index 0000000..b305443
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichSweeping.h
@@ -0,0 +1,177 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+   -- vtkmpjLaxFriedrichSweeping.h --
+   
+   Implements Stanley Osher's Fast Sweeping Scheme for solving
+   Static Hamilton-Jacobi Equations
+   
+   Marcel Jackowski, Feb. 2004.
+   
+*/
+
+#define VTK_MPJ_KNOWN   100   
+#define VTK_MPJ_UNKNOWN   0   
+
+#ifndef __vtkmpjLaxFriedrichSweeping_h
+#define __vtkmpjLaxFriedrichSweeping_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageAccumulate.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjLaxFriedrichSweeping : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjLaxFriedrichSweeping *New();
+  vtkTypeMacro(vtkmpjLaxFriedrichSweeping,vtkpxSimpleImageToImageFilter);
+  
+  // Description:
+  // Set/Get boundary conditions for the propagation. You can also
+  // set the boundary points in the label image. See below.
+  vtkSetObjectMacro(KnownPoints, vtkFloatArray);
+  vtkGetObjectMacro(KnownPoints, vtkFloatArray);
+  
+  // Description:
+  // Get/Set total number of Iterations
+  vtkGetMacro(NumberOfIterations,int);
+  vtkSetMacro(NumberOfIterations,int);
+  
+  // Description:
+  // Set/Get the label image. If KnownPoints is not set, then
+  // LabelImage must have values >0 for initialized (boundary) points,
+  // and 0 for points on the grid to be calculated. 
+  vtkGetObjectMacro(LabelImage, vtkImageData);
+  vtkSetObjectMacro(LabelImage, vtkImageData);
+  
+  // Description:
+  // Set initial solution for boundary points.
+  vtkSetObjectMacro(Solution, vtkImageData);
+  
+  // Description:
+  // Get convergence image
+  vtkGetObjectMacro(ConvergenceImage, vtkImageData);
+  
+  // Description:
+  // Get convergence image
+  vtkGetObjectMacro(Gradient, vtkImageData);
+  
+  // Description:
+  // Set/Get tensor symmetry flag
+  vtkSetMacro(SymmetricTensor, int);
+  vtkGetMacro(SymmetricTensor, int);
+  vtkBooleanMacro(SymmetricTensor, int);
+
+  // Description:
+  // Enables/disables stopping at maximum error
+  vtkSetMacro(StopOnMaximumError, int);
+  vtkGetMacro(StopOnMaximumError, int);
+  vtkBooleanMacro(StopOnMaximumError, int);
+
+  // Description:
+  // Get/Set maximum error value
+  vtkGetMacro(MaximumError,float);
+  vtkSetMacro(MaximumError,float);
+
+  // Description:
+  // Get/Set error value
+  vtkGetMacro(ErrorValue,float);
+  vtkSetMacro(ErrorValue,float);
+
+  // Description:
+  // Get/Set error value
+  vtkGetMacro(IterationNumber,int);
+  vtkSetMacro(IterationNumber,int);
+  
+  // Description:
+  // Get/Set grid spacing
+  vtkGetVector3Macro(Spacing,float);
+  vtkSetVector3Macro(Spacing,float);
+
+ protected:
+  int SymmetricTensor;
+  int NumberOfIterations;
+  int KnownValues;
+  float ErrorValue;
+  int StopOnMaximumError;
+  float MaximumError;
+  int IterationNumber;
+  float Spacing[3];
+
+  vtkFloatArray *KnownPoints;
+  vtkImageData *Mask;
+  vtkImageData *Solution;
+  vtkImageData *LabelImage;
+  vtkDataArray *label;
+  vtkImageData *ConvergenceImage;
+  vtkDataArray *convergence;
+  vtkImageData *Gradient;
+  vtkDataArray *gradient;
+  
+  vtkmpjLaxFriedrichSweeping();
+  ~vtkmpjLaxFriedrichSweeping();
+  
+  virtual void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  
+  void Initialize(vtkImageData *input, vtkImageData *output);
+  void Iterate(vtkImageData *input, vtkImageData *output);
+
+  void Sweep(vtkImageData *input, vtkImageData *output, int dir[3]);
+  void SweepBoundaries(vtkImageData *input, vtkImageData *output);
+  
+  double Update(vtkImageData *input, vtkImageData *output, 
+		int coord[3], int index, double n[3]);
+  
+  double SolveH(int coord[3], int index, double p, double q, double r, double v);
+  double SolveHp(int coord[3], int index, double p, double q, double r, double v);
+  double SolveHq(int coord[3], int index, double p, double q, double r, double v); 
+  double SolveHr(int coord[3], int index, double p, double q, double r, double v); 
+
+ private: 
+  //BTX
+  float pog;
+  int count, tenth; 
+  //ETX
+  
+  vtkmpjLaxFriedrichSweeping(const vtkmpjLaxFriedrichSweeping&);// Not implemented
+  void operator=(const vtkmpjLaxFriedrichSweeping&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichSweepingMethod.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichSweepingMethod.cpp
new file mode 100644
index 0000000..910c13a
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichSweepingMethod.cpp
@@ -0,0 +1,675 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjLaxFriedrichSweepingMethod.h"
+
+#define VTK_MPJ_LARGE_FLOAT 32767
+
+//------------------------------------------------------------------------------
+vtkmpjLaxFriedrichSweepingMethod* vtkmpjLaxFriedrichSweepingMethod::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjLaxFriedrichSweepingMethod");
+  if(ret) {
+    return (vtkmpjLaxFriedrichSweepingMethod*)ret;
+  }
+  
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjLaxFriedrichSweepingMethod;
+}
+
+// Construct object with no children.
+vtkmpjLaxFriedrichSweepingMethod::vtkmpjLaxFriedrichSweepingMethod()
+{
+  this->SecondOrder = 0;
+  this->KnownPoints = NULL;
+  this->KnownValues = 1;
+  this->NumberOfIterations = 2;
+  this->Speed = NULL;  
+  this->label = NULL;
+  this->Solution=NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjLaxFriedrichSweepingMethod::~vtkmpjLaxFriedrichSweepingMethod()
+{
+  if (this->KnownPoints != NULL)
+    this->KnownPoints->Delete();
+  if (this->LabelImage != NULL)
+    this->LabelImage->Delete();
+  if (this->ConvergenceImage != NULL) 
+    this->ConvergenceImage->Delete();
+  if (this->Solution != NULL)
+    this->Solution->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void PrintMatrix3x3(char *title, double *M[3])
+{
+  printf("%s",title);
+  printf("%f %f %f\n",M[0][0],M[0][1],M[0][2]);
+  printf("%f %f %f\n",M[1][0],M[1][1],M[1][2]);
+  printf("%f %f %f\n",M[2][0],M[2][1],M[2][2]);
+  printf("===============================\n");
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweepingMethod::Jacobi3x3(float a[3][3], float w[3], float v[3][3])
+{
+  float **aa = new float *[3]; /* allocate space for tensor matrix */
+  aa[0] = new float[3];
+  aa[1] = new float[3];
+  aa[2] = new float[3];
+   
+  float **vv = new float *[3]; /* allocate space for eigenvector matrix */
+  vv[0] = new float[3];
+  vv[1] = new float[3];
+  vv[2] = new float[3];
+  
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++) 
+      aa[i][j] = a[i][j];
+
+  // call the real method
+  (void) vtkMath::Jacobi(aa,w,vv);
+
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++) 
+      v[i][j] = vv[i][j];
+
+  // free aa
+  delete[] aa[0];
+  delete[] aa[1];
+  delete[] aa[2];
+  delete[] aa;
+   
+  delete[] vv[0];
+  delete[] vv[1];
+  delete[] vv[2];
+  delete[] vv;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweepingMethod::NormalizeTensor3x3(float T[3][3], float W[3], float V[3][3], float N[3][3])
+{
+  float R[3][3], S[3][3];
+  float D[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
+
+  // diagonalize tensor
+  this->Jacobi3x3(T,W,V);
+
+  // force eigenvalues be positive
+  for (int i=0; i<3; i++) {
+    if (W[i] < 0) {
+      V[0][i] = -V[0][i];
+      V[1][i] = -V[1][i];
+      V[2][i] = -V[2][i];
+      W[i] = -W[i];
+    }
+  }
+
+  // make tensor unit size
+  D[0][0] = 1.0; D[1][1] = W[1]/W[0]; D[2][2] = W[2]/W[0];
+
+  // normalized tensor = V * D * V' 
+  (void) vtkMath::Transpose3x3(V,R);
+  (void) vtkMath::Multiply3x3(D,R,S);
+  (void) vtkMath::Multiply3x3(V,S,N);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweepingMethod::SetSpeedImage(vtkImageData *speed)
+{
+  this->SetInput(speed);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweepingMethod::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+   
+  if (this->KnownPoints==NULL) {
+    vtkErrorMacro(<<"Set of known points is empty!");
+    return;
+  }
+
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweepingMethod::Initialize(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  vtkDataArray *sol = NULL;
+  if (this->Solution != NULL) {
+    sol = this->Solution->GetPointData()->GetScalars();
+  }
+
+  // Create label image
+  this->LabelImage = vtkImageData::New();
+  this->LabelImage->SetSpacing(input->GetSpacing());
+  this->LabelImage->SetOrigin(input->GetOrigin());
+  this->LabelImage->SetDimensions(input->GetDimensions());
+  this->LabelImage->SetScalarType(VTK_SHORT);
+  this->LabelImage->SetNumberOfScalarComponents(1);
+  this->LabelImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->LabelImage->AllocateScalars();
+  this->label = this->LabelImage->GetPointData()->GetScalars();
+  this->label->FillComponent(0, VTK_MPJ_UNKNOWN);
+
+  // Create convergence image
+  this->ConvergenceImage = vtkImageData::New();
+  this->ConvergenceImage->SetSpacing(input->GetSpacing());
+  this->ConvergenceImage->SetOrigin(input->GetOrigin());
+  this->ConvergenceImage->SetDimensions(input->GetDimensions());
+  this->ConvergenceImage->SetScalarType(VTK_FLOAT);
+  this->ConvergenceImage->SetNumberOfScalarComponents(1);
+  this->ConvergenceImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->ConvergenceImage->AllocateScalars();
+  this->convergence = this->ConvergenceImage->GetPointData()->GetScalars();
+  this->convergence->FillComponent(0, VTK_MPJ_LARGE_FLOAT);
+
+  // Initialize values to infinity
+  if (this->Solution == NULL)
+    out->FillComponent(0, VTK_MPJ_LARGE_FLOAT);
+  else {
+    int numtuples = sol->GetNumberOfTuples();
+    for(int i=0; i<numtuples; i++)
+      out->SetComponent(i, 0, sol->GetComponent(i, 0));
+  }
+  
+  int coord[3]; 
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  // Set initial conditions
+  for(int i=0; i<this->KnownPoints->GetNumberOfTuples(); i++) {
+    
+    coord[0] = (int)this->KnownPoints->GetComponent(i, 0);
+    coord[1] = (int)this->KnownPoints->GetComponent(i, 1);
+    coord[2] = (int)this->KnownPoints->GetComponent(i, 2);
+    float value = this->KnownValues ? this->KnownPoints->GetComponent(i, 3) : 0.0;
+    
+    int index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+    
+    this->label->SetComponent(index, 0, VTK_MPJ_KNOWN);  // Freeze voxel    
+    this->convergence->SetComponent(index, 0, 0.0);      // Boundary point has exact value
+    out->SetComponent(index, 0, (float)value);           // Set arrival time
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweepingMethod::Iterate(vtkImageData *input, vtkImageData *output)
+{
+  for(int s1=-1; s1<2; s1+=2)
+    for(int s2=-1; s2<2; s2+=2)
+      for(int s3=-1; s3<2; s3+=2) {
+
+	int dir[3] = {s1, s2, s3};
+
+	//printf("sweeping at direction: %d %d %d\n",s1,s2,s3);
+	
+	this->Sweep(input, output, dir);
+	this->SweepBoundaries(input, output);
+	
+	this->count++;
+	if (this->count==this->tenth)
+	  {
+	    this->pog+=0.1;
+	    this->UpdateProgress(this->pog);
+	    this->count=0;
+	  }
+      }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweepingMethod::SweepBoundaries(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  int index;
+  float val0, val1, val2, result;
+
+  // rows
+  for(int k=0; k<dim[2]; k++)  // for all slices
+    for(int i=0; i<dim[0]; i++)  // for all columns in this row
+      {
+	// top row
+	index = dim0Tdim1*k + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + dim[0]*1, 0);
+	val2 = out->GetComponent(index + dim[0]*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+
+	// bottom row
+	index = dim0Tdim1*k + dim[0]*(dim[1]-1) + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - dim[0]*1, 0);
+	val2 = out->GetComponent(index - dim[0]*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+
+  // for columns
+  for(int k=0; k<dim[2]; k++)  // for all slices
+    for(int j=0; j<dim[1]; j++)  // for all rows
+      {
+	// left column
+	index = dim0Tdim1*k + dim[0]*j;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + 1, 0);
+	val2 = out->GetComponent(index + 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+
+	// right column
+	index = dim0Tdim1*k + dim[0]*j + dim[0]-1;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - 1, 0);
+	val2 = out->GetComponent(index - 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+  
+  // for slices
+  for(int i=0; i<dim[0]; i++)  // for all columns
+    for(int j=0; j<dim[1]; j++) // for all rows      
+      { 
+	// first slice
+	index = dim[0]*j + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index + dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+	
+	// last slice
+	index = dim0Tdim1*(dim[2]-1) + dim[0]*j + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index - dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else 
+	  this->convergence->SetComponent(index, 0, 0.0);
+					  
+      }  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweepingMethod::Sweep(vtkImageData *input, vtkImageData *output, int dir[3])
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  // Sweep image
+  for(int k=(dir[2]<0?dim[2]-2:1);(dir[2]<0?k>0:k<dim[2]-1);k+=dir[2])     
+    for(int j=(dir[1]<0?dim[1]-2:1);(dir[1]<0?j>0:j<dim[1]-1);j+=dir[1])
+      for(int i=(dir[0]<0?dim[0]-2:1);(dir[0]<0?i>0:i<dim[0]-1);i+=dir[0]) {
+	
+	int index = dim0Tdim1*k + dim[0]*j + i;
+	int coord[3] = {i, j, k};
+	
+	if (this->label->GetComponent(index, 0) == VTK_MPJ_UNKNOWN) { 
+	  
+	  double new_value = this->Update(input, output, coord, index);
+
+	  
+	  if (new_value < out->GetComponent(index, 0)) {
+	    
+	    // compute convergence 
+	    double old_value = out->GetComponent(index, 0);
+	    this->convergence->SetComponent(index, 0, fabs(new_value - old_value));
+	    
+	    out->SetComponent(index, 0, (float)new_value);	    
+
+	  } else 
+	    this->convergence->SetComponent(index, 0, 0.0);
+	}	
+      }   
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichSweepingMethod::SolveHp(int coord[3], int index, double p, double q, double r, float N[3][3], float V[3][3], float FA)
+{
+  double eps = 1E-12;
+
+  double grad = p*p + q*q + r*r;
+  double prod = (p*V[0][0] + q*V[0][1] + r*V[0][2]) / (sqrt(grad)+eps);
+  double diff = (p*p*N[0][0] + q*q*N[1][1] + r*r*N[2][2] + 2*p*q*N[0][1] + 2*p*r*N[0][2] + 2*q*r*N[1][2]);
+  double ndiff = diff / (grad+eps);
+  double e = exp(ndiff * ndiff * ndiff);
+  
+  double rest = (grad * (2*N[0][0]*p + 2*N[0][1]*q + 2*N[0][2]*r) - (2*p * diff)) / ((grad * grad)+eps);
+  double term = e * 3.0 * ndiff * ndiff * rest;
+
+  double result = FA*FA*exp(prod*prod*prod);//*(3*V[0][0]*prod*prod/grad); // + 3*p*prod*prod*prod/pow(grad,2));
+  //double result = FA*FA * ((sqrt(grad)*term));// + e*(p/(sqrt(grad)+eps)));
+  //  double result =  (FA*FA*exp(pow(ndiff,15)));// + e*(p/(sqrt(grad)+eps)));
+  //double f = (p*p) / sqrt(grad);
+  //double g = sqrt(grad);
+  //double df = (sqrt(grad)*2*p - p*p*p)/(grad+eps);
+  //double dg = p/(sqrt(grad)+eps);
+  //  double result = p*(3*q*q + 3*r*r + 2*p*p) / (pow(p*p+q*q+r*r, 1.5)+eps);
+    
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichSweepingMethod::SolveHq(int coord[3], int index, double p, double q, double r, float N[3][3], float V[3][3], float FA)
+{
+   double eps = 1E-12;
+   double grad = p*p + q*q + r*r;
+   double prod = (p*V[0][0] + q*V[0][1] + r*V[0][2]) / (sqrt(grad)+eps);
+   
+   double diff = (p*p*N[0][0] + q*q*N[1][1] + r*r*N[2][2] + 2*p*q*N[0][1] + 2*p*r*N[0][2] + 2*q*r*N[1][2]);
+   double ndiff = diff / (grad+eps);
+   double e = exp(ndiff * ndiff * ndiff);
+
+   double rest = (grad * (2*N[1][1]*q + 2*N[0][1]*p+ 2*N[1][2]*r) - (2*q * diff)) / ((grad * grad)+eps);
+   double term = e * 3.0 * ndiff * ndiff * rest;
+   
+   //   double result = FA*FA * ((sqrt(grad)*term));// + e*(q/(sqrt(grad)+eps)));
+   //   double result = (FA*FA*exp(pow(ndiff,15)));
+   double result = FA*FA*exp(prod*prod*prod);//*(3*V[0][1]*prod*prod/grad); // + 3*q*prod*prod*prod/pow(grad,2));
+
+   //double f = (p*p) / sqrt(grad);
+   //double g = sqrt(grad);
+   //double df = (sqrt(grad)*2*p - p*p*q/(grad+eps));
+   //double dg = q/(sqrt(grad)+eps);
+   //double result = q*(q*q + r*r) / (pow(p*p+q*q+r*r, 1.5)+eps);
+
+   return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichSweepingMethod::SolveHr(int coord[3], int index, double p, double q, double r, float N[3][3], float V[3][3], float FA)
+{
+  double eps = 1E-12;
+  double grad = p*p + q*q + r*r;
+  double prod = (p*V[0][0] + q*V[0][1] + r*V[0][2]) / (sqrt(grad)+eps);
+  double diff = (p*p*N[0][0] + q*q*N[1][1] + r*r*N[2][2] + 2*p*q*N[0][1] + 2*p*r*N[0][2] + 2*q*r*N[1][2]);
+  double ndiff = diff / (grad+eps);
+  double e = exp(ndiff * ndiff * ndiff);
+
+  double rest = (grad * (2*N[2][2]*r + 2*N[0][2]*p + 2*N[1][2]*q) - (2*r * diff)) / ((grad * grad)+eps);
+  double term = e * 3.0 * ndiff * ndiff * rest;
+  
+  //  double result = FA*FA * ((sqrt(grad)*term));// + e*(r/(sqrt(grad)+eps)));
+  //double result =  (FA*FA*exp(pow(ndiff,15)));
+  
+  double result = FA*FA*exp(prod*prod*prod);//*(3*V[0][2]*prod*prod/grad);// + 3*r*prod*prod*prod/pow(grad,2));
+
+  //double f = (p*p) / sqrt(grad);
+  //double g = sqrt(grad);
+  //double df = (sqrt(grad)*2*p - p*p*r/(grad+eps));
+  //double dg = r/(sqrt(grad)+eps);
+  //double result = g*df + f*dg;
+  //double result = r*(r*r + q*q) / (pow(p*p+q*q+r*r, 1.5) + eps);
+ 
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichSweepingMethod::SolveH(int coord[3], int index, double p, double q, double r, float N[3][3], float V[3][3], float FA)
+{
+  double eps = 1E-12;
+  double grad = p*p + q*q + r*r;
+  double prod = (p*V[0][0] + q*V[0][1] + r*V[0][2]) / (sqrt(grad)+eps);
+  double diff = (p*p*N[0][0] + q*q*N[1][1] + r*r*N[2][2] + 2*p*q*N[0][1] + 2*p*r*N[0][2] + 2*q*r*N[1][2]);
+  double ndiff = diff / (grad+eps);
+  //double result = sqrt(grad) * FA*FA * exp(ndiff * ndiff *ndiff);
+  double result = FA*FA * sqrt(grad) * exp(prod * prod * prod);
+
+  //  double result = (p*p / sqrt(grad)) + sqrt(grad);
+
+  //double dot = (V0[0]*p + V0[1]*q + V0[2]*r) / norm;
+  //double result = norm * exp(dot * dot);
+  //  double result = norm + ((dot * dot) / norm);
+  //  double result = norm * fabs(dot) / norm;  
+  // 3-d eikonal
+  //double result = sqrt(p*p + q*q + r*r);  
+  // 3-d full tensor
+  //double a=1, b=1, c=1, d=1, e=1, f=1;
+  // double result = (a*p*p + b*q*q + c*r*r + 2*d*p*q + 2*e*p*r + 2*f*q*r) / norm;  
+  //double result = (sqrt(p*p + q*q + r*r) + 2*fabs(r))*(1 + fabs(2*p*q) / (p*p + q*q));    
+  //if (coord[0]==15 && coord[1]==16 && coord[2]==16) {
+  //printf("%d %d %d ",coord[0],coord[1],coord[2]);
+  // printf("%f %f %f = %f\n",p,q,r,result);
+  //}
+  return result;
+}
+
+int cmpfunc(const void *a, const void *b)
+{
+  double *x=(double *)a;
+  double *y=(double *)b;
+  if (*x < *y) return -1;
+  if (*x == *y) return 0; else return 1;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichSweepingMethod::Update(vtkImageData *input, vtkImageData *output, int coord[3], int index)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  
+  float T[3][3], N[3][3], V[3][3];
+  float W[3], R[3];
+  float FA;
+
+  // compute tensor
+  T[0][0] = in->GetComponent(index, 0);           /* Dxx */
+  T[1][0] = T[0][1] = in->GetComponent(index, 1); /* Dxy */
+  T[2][0] = T[0][2] = in->GetComponent(index, 2); /* Dxz */
+  T[1][1] = in->GetComponent(index, 4);           /* Dyy */
+  T[2][1] = T[1][2] = in->GetComponent(index, 5); /* Dyz */
+  T[2][2] = in->GetComponent(index, 8);           /* Dzz */
+  
+  // diagonalize and normalize tensor 
+  this->NormalizeTensor3x3(T,W,V,N);
+
+  // calculate FA
+  float md = (W[0] + W[1] + W[2]) / 3.0;
+  float a=W[0]-md;
+  float b=W[0]-md;
+  float c=W[1]-md;
+  FA = sqrt(3*(a*a + b*b + c*c)) / sqrt(2*(W[0]*W[0] + W[1]*W[1] + W[2]*W[2]));
+
+  // Lax-Friedrichs method
+  double hx = 1.0; //(float) (dim[0]-2) / (dim[0]-1);
+  double hy = 1.0; //(float) (dim[1]-2) / (dim[1]-1);
+  double hz = 1.0; //(float) (dim[2]-2) / (dim[2]-1);
+
+  double pp, pm, qp, qm, rp, rm;
+  double phi_p, phi_q, phi_r;
+  int neighbor[3];
+
+  // for p
+  neighbor[0] = index - factor[0];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[0];
+  
+  pp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hx;
+  pm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hx;
+  phi_p = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) / hx;
+
+  // for q
+  neighbor[0] = index - factor[1];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[1];
+  
+  qp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hy;
+  qm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hy;
+  phi_q = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) /hy;
+  
+  // for r
+  neighbor[0] = index - factor[2];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[2];
+  
+  rp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hz;
+  rm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hz;
+  phi_r = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) /hz;
+
+  double pmin, pmax;
+  if (fabs(pp) >= fabs(pm)) {
+    pmax = fabs(pp); pmin = fabs(pm);
+  } else {
+    pmax = fabs(pm); pmin = fabs(pp);
+  }
+
+  double qmin, qmax;
+  if (fabs(qp) >= fabs(qm)) {
+    qmax = fabs(qp); qmin = fabs(qm);
+  } else {
+    qmax = fabs(qm); qmin = fabs(qp);
+  }
+  
+  double rmin, rmax;
+  if (fabs(rp) >= fabs(rm)) {
+    rmax = fabs(rp); rmin = fabs(rm);
+  } else {
+    rmax = fabs(rm); rmin = fabs(rp);
+  }
+
+  double H = SolveH(coord, index, (pp+pm)/2.0, (qp+qm)/2.0, (rp+rm)/2.0, N, V, FA); 
+
+  double ox = SolveHp(coord, index, pmax, qmin, rmin, N, V, FA);
+  double oy = SolveHq(coord, index, pmin, qmax, rmin, N, V, FA);
+  double oz = SolveHr(coord, index, pmin, qmin, rmax, N, V, FA);
+
+  double visc = 1.0 / (ox/hx + oy/hy + oz/hz);
+  double phi = visc * ( 1.0 - H + (ox/2)*phi_p + (oy/2)*phi_q + (oz/2)*phi_r );
+
+  //printf("pm=%f,pp=%f,qm=%f,qp=%f,rm=%f,rp=%f\n",pm,pp,qm,qp,rm,rp);
+  //if (coord[0]==15 && coord[1]==16 && coord[2]==16) {
+  //printf("H=%f c=%f, ox=%f, oy=%f, oz=%f, hx=%f, hy=%f, hz=%f, phi=%f\n",H,c,ox,oy,oz,hx,hy,hz,phi);
+  //}
+
+  //printf("phi=%f\n",phi);
+  return phi;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichSweepingMethod::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3];  input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  
+  if (this->GetInput()==NULL) {
+    vtkErrorMacro(<<"No Input Image\n Exiting\n");
+    return;
+  }
+  
+  this->pog = 0.0;  
+  this->tenth=(int)((8*this->NumberOfIterations) / 8.0);
+  this->count=0;
+
+  printf("before init\n");
+  this->Initialize(input, output);
+
+  printf("after init\n");
+  this->UpdateProgress(0.01);
+  
+  for(int j=0; j<this->NumberOfIterations; j++) {
+    printf("iteration %d\n", j);
+    this->Iterate(input, output);
+  }
+  
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichSweepingMethod.h b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichSweepingMethod.h
new file mode 100644
index 0000000..1ae59e5
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichSweepingMethod.h
@@ -0,0 +1,136 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+   -- vtkmpjLaxFriedrichSweepingMethod.h --
+   
+   Implements Stanley Osher's Fast Sweeping Scheme for solving
+   Static Hamilton-Jacobi Equations
+   
+   Marcel Jackowski, October 2003.
+   
+*/
+
+#define VTK_MPJ_KNOWN   100   
+#define VTK_MPJ_UNKNOWN   0   
+
+#ifndef __vtkmpjLaxFriedrichSweepingMethod_h
+#define __vtkmpjLaxFriedrichSweepingMethod_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageAccumulate.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjLaxFriedrichSweepingMethod : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjLaxFriedrichSweepingMethod *New();
+  vtkTypeMacro(vtkmpjLaxFriedrichSweepingMethod,vtkpxSimpleImageToImageFilter);
+  
+  // Description: Sets speed image
+  void SetSpeedImage(vtkImageData *speed);
+
+  // Description:
+  // Set/Get boundary conditions for the propagation
+  vtkSetObjectMacro(KnownPoints, vtkFloatArray);
+  vtkGetObjectMacro(KnownPoints, vtkFloatArray);
+
+  // Description: Turns on/off second order approximation to the gradient
+  vtkGetMacro(SecondOrder,int);
+  vtkSetClampMacro(SecondOrder,int,0,1);
+  vtkBooleanMacro(SecondOrder,int);
+
+  vtkGetMacro(NumberOfIterations,int);
+  vtkSetMacro(NumberOfIterations,int);
+
+  // Front label image. Points interior to the front have value -1, points 
+  // on the front boundary have value 0, and points outside have value +1.
+  vtkGetObjectMacro(LabelImage, vtkImageData);
+  vtkGetObjectMacro(ConvergenceImage, vtkImageData);
+  
+  vtkSetObjectMacro(Solution, vtkImageData);
+  vtkGetObjectMacro(Solution, vtkImageData);
+    
+ protected:
+  int SecondOrder;
+  int NumberOfIterations;
+  int KnownValues;
+  vtkImageData *Speed;
+  vtkImageData *Solution;
+  vtkFloatArray *KnownPoints;
+  vtkImageData *LabelImage;
+  vtkImageData *ConvergenceImage;
+  vtkDataArray *label;
+  vtkDataArray *convergence;
+
+  vtkmpjLaxFriedrichSweepingMethod();
+  virtual ~vtkmpjLaxFriedrichSweepingMethod();
+  
+  void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+
+  void Initialize(vtkImageData *input, vtkImageData *output);
+  void Iterate(vtkImageData *input, vtkImageData *output);
+  void Sweep(vtkImageData *input, vtkImageData *output, int dir[3]);
+  void SweepBoundaries(vtkImageData *input, vtkImageData *output);
+  double Update(vtkImageData *input, vtkImageData *output, int coord[3], 
+		int index);
+  double SolveH(int coord[3], int index, double p, double q, double r, 
+		float N[3][3], float V[3][3], float FA);
+  double SolveHp(int coord[3], int index, double p, double q, double r, 
+		float N[3][3], float V[3][3], float FA); 
+  double SolveHq(int coord[3], int index, double p, double q, double r, 
+		float N[3][3], float V[3][3], float FA);
+  double SolveHr(int coord[3], int index, double p, double q, double r, 
+		float N[3][3], float V[3][3], float FA);
+  
+  void NormalizeTensor3x3(float T[3][3], float W[3], float V[3][3], 
+			  float N[3][3]);
+  void Jacobi3x3(float a[3][3], float w[3], float v[3][3]);
+  
+ private: 
+  //BTX
+  float pog;
+  int count, tenth; 
+  //ETX
+  
+  vtkmpjLaxFriedrichSweepingMethod(const vtkmpjLaxFriedrichSweepingMethod&);// Not implemented
+  void operator=(const vtkmpjLaxFriedrichSweepingMethod&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichTest.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichTest.cpp
new file mode 100644
index 0000000..430e511
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichTest.cpp
@@ -0,0 +1,947 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjLaxFriedrichTest.h"
+
+#define VTK_MPJ_LARGE_FLOAT 32767
+
+//------------------------------------------------------------------------------
+vtkmpjLaxFriedrichTest* vtkmpjLaxFriedrichTest::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjLaxFriedrichTest");
+  if(ret) {
+    return (vtkmpjLaxFriedrichTest*)ret;
+  }
+  
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjLaxFriedrichTest;
+}
+
+// Construct object with no children.
+vtkmpjLaxFriedrichTest::vtkmpjLaxFriedrichTest()
+{
+  this->KnownPoints = NULL;
+  this->KnownValues = 1;
+  this->NumberOfIterations = 2;
+  this->Speed = NULL;  
+  this->label = NULL;
+  this->Solution=NULL;
+  this->DomainImage = NULL;
+  this->BoundaryPoints = NULL;
+  this->BoundaryValue = 200;
+  this->DomainValue = 100;
+}
+
+// ----------------------------------------------------------------------------
+void PrintMatrix3x3(const char *title, float M[3][3])
+{
+  printf("%s",title);
+  printf("%f %f %f\n",M[0][0],M[0][1],M[0][2]);
+  printf("%f %f %f\n",M[1][0],M[1][1],M[1][2]);
+  printf("%f %f %f\n",M[2][0],M[2][1],M[2][2]);
+  printf("===============================\n");
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjLaxFriedrichTest::~vtkmpjLaxFriedrichTest()
+{
+  if (this->KnownPoints != NULL)
+    this->KnownPoints->Delete();
+  if (this->LabelImage != NULL)
+    this->LabelImage->Delete();
+  if (this->ConvergenceImage != NULL) 
+    this->ConvergenceImage->Delete();
+  if (this->Solution != NULL)
+    this->Solution->Delete();
+  if (this->DomainImage != NULL)
+    this->DomainImage->Delete();
+  if (this->BoundaryPoints != NULL) 
+    this->BoundaryPoints->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichTest::Jacobi3x3(float a[3][3], float w[3], float v[3][3])
+{
+  float **aa = new float *[3]; /* allocate space for tensor matrix */
+  aa[0] = new float[3];
+  aa[1] = new float[3];
+  aa[2] = new float[3];
+   
+  float **vv = new float *[3]; /* allocate space for eigenvector matrix */
+  vv[0] = new float[3];
+  vv[1] = new float[3];
+  vv[2] = new float[3];
+  
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++) 
+      aa[i][j] = a[i][j];
+
+  // call the real method
+  (void) vtkMath::Jacobi(aa,w,vv);
+
+  for(int i=0;i<3;i++)
+    for(int j=0;j<3;j++) 
+      v[i][j] = vv[i][j];
+
+  // free aa
+  delete[] aa[0];
+  delete[] aa[1];
+  delete[] aa[2];
+  delete[] aa;
+   
+  delete[] vv[0];
+  delete[] vv[1];
+  delete[] vv[2];
+  delete[] vv;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichTest::NormalizeTensor3x3(float T[3][3], float W[3], float V[3][3], float N[3][3])
+{
+  float R[3][3], S[3][3], U[3][3];
+  float D[3][3] = {{0,0,0},{0,0,0},{0,0,0}};
+  
+  // diagonalize tensor
+  this->Jacobi3x3(T,W,V);
+  
+  // force eigenvalues be positive
+  if (W[0]<0 || W[1]<0 || W[2]<0) {
+    for (int i=0; i<3; i++) {
+      if (W[i] < 0) {
+	V[0][i] = -V[0][i];
+	V[1][i] = -V[1][i];
+	V[2][i] = -V[2][i];
+	W[i] = -W[i];
+      }
+    }
+  
+    D[0][0]=W[0]; D[1][1]=W[1]; D[2][2]=W[2];
+
+    // build new positive tensor
+    (void) vtkMath::Transpose3x3(V,R);
+    (void) vtkMath::Multiply3x3(D,R,S);
+    (void) vtkMath::Multiply3x3(V,S,U);
+    
+    // diagonalize it once more
+    this->Jacobi3x3(U,W,V);    
+  }
+  
+  // make tensor unit size
+  D[0][0] = 1.0; D[1][1] = W[1]/W[0]; D[2][2] = W[2]/W[0];
+
+  // normalized tensor = V * D * V' 
+  (void) vtkMath::Transpose3x3(V,R);
+  (void) vtkMath::Multiply3x3(D,R,S);
+  (void) vtkMath::Multiply3x3(V,S,N);
+
+  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichTest::SetSpeedImage(vtkImageData *speed)
+{
+  this->SetInput(speed);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichTest::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+   
+  if (this->KnownPoints==NULL) {
+    vtkErrorMacro(<<"Set of known points is empty!");
+    return;
+  }
+
+  output->SetNumberOfScalarComponents(1);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichTest::Initialize(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  vtkDataArray *sol = NULL;
+  if (this->Solution != NULL) {
+    sol = this->Solution->GetPointData()->GetScalars();
+  }
+
+  // Create label image
+  this->LabelImage = vtkImageData::New();
+  this->LabelImage->SetSpacing(input->GetSpacing());
+  this->LabelImage->SetOrigin(input->GetOrigin());
+  this->LabelImage->SetDimensions(input->GetDimensions());
+  this->LabelImage->SetScalarType(VTK_SHORT);
+  this->LabelImage->SetNumberOfScalarComponents(1);
+  this->LabelImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->LabelImage->AllocateScalars();
+  this->label = this->LabelImage->GetPointData()->GetScalars();
+  this->label->FillComponent(0, VTK_MPJ_UNKNOWN);
+  
+  // Create convergence image
+  this->ConvergenceImage = vtkImageData::New();
+  this->ConvergenceImage->SetSpacing(input->GetSpacing());
+  this->ConvergenceImage->SetOrigin(input->GetOrigin());
+  this->ConvergenceImage->SetDimensions(input->GetDimensions());
+  this->ConvergenceImage->SetScalarType(VTK_FLOAT);
+  this->ConvergenceImage->SetNumberOfScalarComponents(1);
+  this->ConvergenceImage->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+  this->ConvergenceImage->AllocateScalars();
+  this->convergence = this->ConvergenceImage->GetPointData()->GetScalars();
+  this->convergence->FillComponent(0, VTK_MPJ_LARGE_FLOAT);
+
+  // Initialize values to infinity
+  if (this->Solution == NULL)
+    out->FillComponent(0, VTK_MPJ_LARGE_FLOAT);
+  else {
+    int numtuples = sol->GetNumberOfTuples();
+    for(int i=0; i<numtuples; i++)
+      out->SetComponent(i, 0, sol->GetComponent(i, 0));
+  }
+  
+  int coord[3]; 
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  // Set initial conditions
+  for(int i=0; i<this->KnownPoints->GetNumberOfTuples(); i++) {
+    
+    coord[0] = (int)this->KnownPoints->GetComponent(i, 0);
+    coord[1] = (int)this->KnownPoints->GetComponent(i, 1);
+    coord[2] = (int)this->KnownPoints->GetComponent(i, 2);
+    float value = this->KnownValues ? this->KnownPoints->GetComponent(i, 3) : 0.0;
+    
+    int index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+    
+    this->label->SetComponent(index, 0, VTK_MPJ_KNOWN);  // Freeze voxel    
+    this->convergence->SetComponent(index, 0, 0.0);      // Boundary point has exact value
+    out->SetComponent(index, 0, (float)value);           // Set arrival time
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichTest::Iterate(vtkImageData *input, vtkImageData *output)
+{
+  for(int s1=-1; s1<2; s1+=2)
+    for(int s2=-1; s2<2; s2+=2)
+      for(int s3=-1; s3<2; s3+=2) {
+
+	int dir[3] = {s1, s2, s3};
+
+	//printf("sweeping at direction: %d %d %d\n",s1,s2,s3);
+	
+	this->Sweep(input, output, dir);
+	this->SweepBoundaries(input, output);
+	
+	this->count++;
+	if (this->count==this->tenth)
+	  {
+	    this->pog+=0.1;
+	    this->UpdateProgress(this->pog);
+	    this->count=0;
+	  }
+      }
+}
+
+void vtkmpjLaxFriedrichTest::SweepSliceBoundary(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  vtkDataArray *domain=this->DomainImage->GetPointData()->GetScalars();
+  
+  int index, coord[3];
+  float val0, val1, val2, result;  
+  
+  int num_tuples = this->BoundaryPoints->GetNumberOfComponents();
+  
+  // top and bottom row checks
+  for(int i=0;i<num_tuples;i++) {          
+    
+    // fetch coordinates of boundary point
+    coord[0] = (int)this->BoundaryPoints->GetComponent(i, 0);
+    coord[1] = (int)this->BoundaryPoints->GetComponent(i, 1);
+    coord[2] = (int)this->BoundaryPoints->GetComponent(i, 2);
+    
+    index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+
+    val0 = out->GetComponent(index, 0);
+    
+    // first slice
+    if ((coord[2]+1 < dim[2]) && (coord[2]+2 < dim[2]))
+      if ((domain->GetComponent(index + dim0Tdim1*1, 0) == this->DomainValue) && 
+	  (domain->GetComponent(index + dim0Tdim1*2, 0) == this->DomainValue)) {
+
+	val1 = out->GetComponent(index + dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index + dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+
+      }
+    
+    // last slice
+    if ((coord[2]-1 < dim[2]) && (coord[2]-2 < dim[2]))
+      if ((domain->GetComponent(index - dim0Tdim1*1, 0) == this->DomainValue) && 
+	  (domain->GetComponent(index - dim0Tdim1*2, 0) == this->DomainValue)) {
+	
+	val1 = out->GetComponent(index - dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index - dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else 
+	  this->convergence->SetComponent(index, 0, 0.0);
+      }
+  }
+}
+
+void vtkmpjLaxFriedrichTest::SweepColumnBoundary(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  vtkDataArray *domain=this->DomainImage->GetPointData()->GetScalars();
+
+  int index, coord[3];
+  float val0, val1, val2, result;  
+  
+  int num_tuples = this->BoundaryPoints->GetNumberOfComponents();
+  
+  // top and bottom row checks
+  for(int i=0;i<num_tuples;i++) {          
+    
+    // fetch coordinates of boundary point
+    coord[0] = (int)this->BoundaryPoints->GetComponent(i, 0);
+    coord[1] = (int)this->BoundaryPoints->GetComponent(i, 1);
+    coord[2] = (int)this->BoundaryPoints->GetComponent(i, 2);
+    
+    index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+    
+    val0 = out->GetComponent(index, 0);
+    
+    // left column
+    if ((coord[0]+1 < dim[0]) && (coord[0]+2 < dim[0]))
+      if ((domain->GetComponent(index + 1, 0) == this->DomainValue) && 
+	  (domain->GetComponent(index + 2, 0) == this->DomainValue)) {
+
+	val1 = out->GetComponent(index + 1, 0);
+	val2 = out->GetComponent(index + 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+
+    // right column
+    if ((coord[0]-1 >=0) && (coord[0]-2 >=0))
+      if ((domain->GetComponent(index - 1, 0) == this->DomainValue) && 
+	  (domain->GetComponent(index - 2, 0) == this->DomainValue)) {
+	
+	val1 = out->GetComponent(index - 1, 0);
+	val2 = out->GetComponent(index - 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+  }
+}
+
+void vtkmpjLaxFriedrichTest::SweepRowBoundary(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  vtkDataArray *domain=this->DomainImage->GetPointData()->GetScalars();
+
+  int index, coord[3];
+  float val0, val1, val2, result;  
+  
+  int num_tuples = this->BoundaryPoints->GetNumberOfComponents();
+  
+  // top and bottom row checks
+  for(int i=0;i<num_tuples;i++) {          
+    
+    // fetch coordinates of boundary point
+    coord[0] = (int)this->BoundaryPoints->GetComponent(i, 0);
+    coord[1] = (int)this->BoundaryPoints->GetComponent(i, 1);
+    coord[2] = (int)this->BoundaryPoints->GetComponent(i, 2);
+    
+    index = dim0Tdim1*coord[2] + dim[0]*coord[1] + coord[0];
+
+    val0 = out->GetComponent(index, 0);
+    
+    // top row    
+    if ((coord[1]+1 < dim[1]) && (coord[1]+2 < dim[1]))
+      if ((domain->GetComponent(index + dim[0]*1, 0) == this->DomainValue) && 
+	  (domain->GetComponent(index + dim[0]*2, 0) == this->DomainValue)) {
+	
+	val1 = out->GetComponent(index + dim[0]*1, 0);
+	val2 = out->GetComponent(index + dim[0]*2, 0);
+	
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}      
+      };
+    
+    // bottom row
+    if ((coord[1]-1 >= 0) && (coord[1]-2 >= 0))
+      if ((domain->GetComponent(index - dim[0]*1, 0) == this->DomainValue) && 
+	  (domain->GetComponent(index - dim[0]*2, 0) == this->DomainValue)) {
+	
+	val1 = out->GetComponent(index - dim[0]*1, 0);
+	val2 = out->GetComponent(index - dim[0]*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}	
+      }
+
+      
+    // left column
+    if ((coord[0]+1 < dim[0]) && (coord[0]+2 < dim[0]))
+      if ((domain->GetComponent(index + 1, 0) == this->DomainValue) && 
+	  (domain->GetComponent(index + 2, 0) == this->DomainValue)) {
+
+	val1 = out->GetComponent(index + 1, 0);
+	val2 = out->GetComponent(index + 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+
+    // right column
+    if ((coord[0]-1 >=0) && (coord[0]-2 >=0))
+      if ((domain->GetComponent(index - 1, 0) == this->DomainValue) && 
+	  (domain->GetComponent(index - 2, 0) == this->DomainValue)) {
+	
+	val1 = out->GetComponent(index - 1, 0);
+	val2 = out->GetComponent(index - 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+
+      // first slice
+    if ((coord[2]+1 < dim[2]) && (coord[2]+2 < dim[2]))
+      if ((domain->GetComponent(index + dim0Tdim1*1, 0) == this->DomainValue) && 
+	  (domain->GetComponent(index + dim0Tdim1*2, 0) == this->DomainValue)) {
+
+	val1 = out->GetComponent(index + dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index + dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+
+      }
+    
+    // last slice
+    if ((coord[2]-1 < dim[2]) && (coord[2]-2 < dim[2]))
+      if ((domain->GetComponent(index - dim0Tdim1*1, 0) == this->DomainValue) && 
+	  (domain->GetComponent(index - dim0Tdim1*2, 0) == this->DomainValue)) {
+	
+	val1 = out->GetComponent(index - dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index - dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else 
+	  this->convergence->SetComponent(index, 0, 0.0);
+      }
+  }
+}
+
+void vtkmpjLaxFriedrichTest::SweepOldBoundaries(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  
+  int index;
+  float val0, val1, val2, result;
+  
+  // rows
+  for(int k=0; k<dim[2]; k++)  // for all slices
+    for(int i=0; i<dim[0]; i++)  // for all columns in this row
+      {
+	// top row
+	index = dim0Tdim1*k + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + dim[0]*1, 0);
+	val2 = out->GetComponent(index + dim[0]*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+	
+	// bottom row
+	index = dim0Tdim1*k + dim[0]*(dim[1]-1) + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - dim[0]*1, 0);
+	val2 = out->GetComponent(index - dim[0]*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+  
+  // for columns
+  for(int k=0; k<dim[2]; k++)  // for all slices
+    for(int j=0; j<dim[1]; j++)  // for all rows
+      {
+	// left column
+	index = dim0Tdim1*k + dim[0]*j;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + 1, 0);
+	val2 = out->GetComponent(index + 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+	
+	// right column
+	index = dim0Tdim1*k + dim[0]*j + dim[0]-1;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - 1, 0);
+	val2 = out->GetComponent(index - 2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+      }
+  
+  // for slices
+  for(int i=0; i<dim[0]; i++)  // for all columns
+    for(int j=0; j<dim[1]; j++) // for all rows      
+      { 
+	// first slice
+	index = dim[0]*j + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index + dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index + dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else {
+	  this->convergence->SetComponent(index, 0, 0.0);
+	}
+	
+	// last slice
+	index = dim0Tdim1*(dim[2]-1) + dim[0]*j + i;
+	val0 = out->GetComponent(index, 0);
+	val1 = out->GetComponent(index - dim0Tdim1*1, 0);
+	val2 = out->GetComponent(index - dim0Tdim1*2, 0);
+	result = 2.0*val1 - val2;
+	if (result <= val2) 
+	  result = val2;
+	if (result < val0) {
+	  out->SetComponent(index, 0, result);
+	  this->convergence->SetComponent(index, 0, fabs(result - val0));
+	} else 
+	  this->convergence->SetComponent(index, 0, 0.0);	
+      }  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichTest::SweepBoundaries(vtkImageData *input, vtkImageData *output)
+{
+  //printf("sweep boundaries\n");
+  if (this->DomainImage != NULL) {
+    this->SweepRowBoundary(input, output);
+    //this->SweepColumnBoundary(input, output);
+    //this->SweepSliceBoundary(input, output);
+  } else {
+    SweepOldBoundaries(input, output);
+  }  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichTest::Sweep(vtkImageData *input, vtkImageData *output, int dir[3])
+{
+  int dim[3]; input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  int dim0Tdim1 = dim[0]*dim[1];
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  vtkDataArray *domain = NULL;
+
+  if (this->DomainImage != NULL) {
+    domain=this->DomainImage->GetPointData()->GetScalars(); 
+    //printf("domain is not null %d %d\n",this->DomainImage, domain);
+  }
+  
+  //printf("domain=%d\n",domain);
+
+  // Sweep image
+  for(int k=(dir[2]<0?dim[2]-2:1);(dir[2]<0?k>0:k<dim[2]-1);k+=dir[2])     
+    for(int j=(dir[1]<0?dim[1]-2:1);(dir[1]<0?j>0:j<dim[1]-1);j+=dir[1])
+      for(int i=(dir[0]<0?dim[0]-2:1);(dir[0]<0?i>0:i<dim[0]-1);i+=dir[0]) {
+	
+	int index = dim0Tdim1*k + dim[0]*j + i;
+	int coord[3] = {i, j, k};
+	
+	// only update point if value is unknown and is part of the
+	// computational domain
+	if (this->label->GetComponent(index, 0) == VTK_MPJ_UNKNOWN) {
+	  
+	  //printf("here index=%d\n",index);
+	  //printf("%f\n",domain->GetComponent(index, 0));
+	  int cond = this->DomainImage != NULL ? (domain->GetComponent(index, 0) == this->DomainValue) : 1;
+	  //printf("after\n");
+	  if (cond) {
+	    
+	    double new_value = this->Update(input, output, coord, index);
+	    
+	    // only update if it's value is less than before
+	    if (new_value < out->GetComponent(index, 0)) {
+	      
+	      // compute convergence 
+	      double old_value = out->GetComponent(index, 0);
+	      
+	      this->convergence->SetComponent(index, 0, fabs(new_value - old_value));	    
+	      out->SetComponent(index, 0, (float)new_value);	    
+	      
+	    } else 
+	      this->convergence->SetComponent(index, 0, 0.0);
+	  }	
+	}	
+      }   
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichTest::SolveHp(int coord[3], int index, double p, double q, double r,
+				       float N[3][3], float V[3][3], float FA)
+{
+  double eps = 1E-12;
+  double grad = p*p + q*q + r*r;
+  double prod = (p*V[0][0] + q*V[0][1] + r*V[0][2]) / (sqrt(grad)+eps);
+  double diff = (p*p*N[0][0]+q*q*N[1][1]+r*r*N[2][2]+2*p*q*N[0][1]+2*p*r*N[0][2]+2*q*r*N[1][2]);
+  double ndiff = diff / (grad+eps);  
+  double result = FA*FA * exp(ndiff * ndiff);
+  //double result = FA*FA * exp(prod * prod * prod * prod);
+
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichTest::SolveHq(int coord[3], int index, double p, double q, double r,
+				       float N[3][3], float V[3][3], float FA)
+{
+  double eps = 1E-12;
+  double grad = p*p + q*q + r*r;
+  double prod = (p*V[0][0] + q*V[0][1] + r*V[0][2]) / (sqrt(grad)+eps);
+  double diff = (p*p*N[0][0]+q*q*N[1][1]+r*r*N[2][2]+2*p*q*N[0][1]+2*p*r*N[0][2]+2*q*r*N[1][2]);
+  double ndiff = diff / (grad+eps);  
+  double result = FA*FA * exp(ndiff * ndiff);
+  //double result = FA*FA * exp(prod * prod * prod * prod);
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichTest::SolveHr(int coord[3], int index, double p, double q, double r,
+				       float N[3][3], float V[3][3], float FA)
+{
+  double eps = 1E-12;
+  double grad = p*p + q*q + r*r;
+  double prod = (p*V[0][0] + q*V[0][1] + r*V[0][2]) / (sqrt(grad)+eps);
+  double diff = (p*p*N[0][0]+q*q*N[1][1]+r*r*N[2][2]+2*p*q*N[0][1]+2*p*r*N[0][2]+2*q*r*N[1][2]);
+  double ndiff = diff / (grad+eps);  
+  double result = FA*FA * exp(ndiff * ndiff);
+  //double result = FA*FA * exp(prod * prod * prod * prod);
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichTest::SolveH(int coord[3], int index, double p, double q, double r,
+				      float T[3][3], float N[3][3], float V[3][3], float FA)
+{
+  double eps = 1E-12;
+  double grad = p*p + q*q + r*r;
+  double prod = (p*V[0][0] + q*V[0][1] + r*V[0][2]) / (sqrt(grad)+eps);
+  double diff = (p*p*N[0][0]+q*q*N[1][1]+r*r*N[2][2]+2*p*q*N[0][1]+2*p*r*N[0][2]+2*q*r*N[1][2]);
+  double ndiff = diff / (grad+eps);
+  
+  double result = sqrt(grad) * FA*FA * exp(ndiff * ndiff);
+  if (ndiff > 1.0) {
+    PrintMatrix3x3("N=\n",N);
+    PrintMatrix3x3("T=\n",T);
+    printf("ndiff=%f\n",ndiff);
+  }
+  //  printf("result=%f\n",result);
+
+  // if (result == 0) {
+  // printf("%d %d %d FA=%f, ndiff=%f, grad=%f, [p,q,r]=%f,%f,%f\n",coord[0],coord[1],coord[2],FA,ndiff,grad,p,q,r);
+  //}
+
+  //double result = FA*FA * sqrt(grad) * exp(prod * prod * prod * prod);
+  //double result = FA*FA * sqrt(grad) * exp(prod * prod * prod);
+  return result;
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLaxFriedrichTest::Update(vtkImageData *input, vtkImageData *output, int coord[3], int index)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  
+  float T[3][3], N[3][3], V[3][3];
+  float W[3], R[3];
+  float FA;
+
+  // compute tensor
+  T[0][0] = in->GetComponent(index, 0);           /* Dxx */
+  T[1][0] = T[0][1] = in->GetComponent(index, 1); /* Dxy */
+  T[2][0] = T[0][2] = in->GetComponent(index, 2); /* Dxz */
+  T[1][1] = in->GetComponent(index, 4);           /* Dyy */
+  T[2][1] = T[1][2] = in->GetComponent(index, 5); /* Dyz */
+  T[2][2] = in->GetComponent(index, 8);           /* Dzz */
+  this->NormalizeTensor3x3(T,W,V,N);
+  
+  //PrintMatrix3x3("normT=",N);
+
+  // calculate FA
+  float md = (W[0] + W[1] + W[2]) / 3.0;
+  float a=W[0]-md;
+  float b=W[1]-md;
+  float c=W[2]-md;
+  FA = sqrt(3.0/2.0) * sqrt((a*a + b*b + c*c) / (W[0]*W[0] + W[1]*W[1] + W[2]*W[2]));
+  //if (FA == 0.0) FA = 0.15;
+  if (FA < 0.15) FA = 0.15;
+
+  //  printf("FA=%f\n",FA);
+
+  // Lax-Friedrichs Method
+  double hx = 0.25; //(float) (dim[0]-2) / (dim[0]-1);
+  double hy = 0.25; //(float) (dim[1]-2) / (dim[1]-1);
+  double hz = 0.25; //(float) (dim[2]-2) / (dim[2]-1);
+
+  double pp, pm, qp, qm, rp, rm;
+  double phi_p, phi_q, phi_r;
+  int neighbor[3];
+  
+  // for p
+  neighbor[0] = index - factor[0];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[0];
+  
+  pp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hx;
+  pm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hx;
+  phi_p = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) / hx;
+
+  // for q
+  neighbor[0] = index - factor[1];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[1];
+  
+  qp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hy;
+  qm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hy;
+  phi_q = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) /hy;
+  
+  // for r
+  neighbor[0] = index - factor[2];
+  neighbor[1] = index; 
+  neighbor[2] = index + factor[2];
+  
+  rp = ((double)out->GetComponent(neighbor[2], 0) - (double)out->GetComponent(neighbor[1], 0)) / hz;
+  rm = ((double)out->GetComponent(neighbor[1], 0) - (double)out->GetComponent(neighbor[0], 0)) / hz;
+  phi_r = ((double)out->GetComponent(neighbor[0], 0) + (double)out->GetComponent(neighbor[2], 0)) /hz;
+
+  double pmin, pmax;
+  if (fabs(pp) >= fabs(pm)) {
+    pmax = fabs(pp); pmin = fabs(pm);
+  } else {
+    pmax = fabs(pm); pmin = fabs(pp);
+  }
+  
+  double qmin, qmax;
+  if (fabs(qp) >= fabs(qm)) {
+    qmax = fabs(qp); qmin = fabs(qm);
+  } else {
+    qmax = fabs(qm); qmin = fabs(qp);
+  }
+  
+  double rmin, rmax;
+  if (fabs(rp) >= fabs(rm)) {
+    rmax = fabs(rp); rmin = fabs(rm);
+  } else {
+    rmax = fabs(rm); rmin = fabs(rp);
+  }
+
+  //  PrintMatrix3x3("N=",T);
+  //printf("W=%f,%f,%f\n",W[0],W[1],W[2]);
+  
+  double H = SolveH(coord, index, (pp+pm)/2.0, (qp+qm)/2.0, (rp+rm)/2.0, T, N, V, FA);
+  double ox = SolveHp(coord, index, pmax, qmin, rmin, N, V, FA);
+  double oy = SolveHq(coord, index, pmin, qmax, rmin, N, V, FA);
+  double oz = SolveHr(coord, index, pmin, qmin, rmax, N, V, FA);
+  
+  double visc = 1.0 / (ox/hx + oy/hy + oz/hz);
+  double phi = visc * ( 1.0 - H + (ox/2)*phi_p + (oy/2)*phi_q + (oz/2)*phi_r );
+  
+  //printf("pm=%f,pp=%f,qm=%f,qp=%f,rm=%f,rp=%f\n",pm,pp,qm,qp,rm,rp);
+  //if (coord[0]==15 && coord[1]==16 && coord[2]==16) {
+  //printf("H=%f c=%f, ox=%f, oy=%f, oz=%f, hx=%f, hy=%f, hz=%f, phi=%f\n",H,c,ox,oy,oz,hx,hy,hz,phi);
+  //}  
+  //printf("phi=%f\n",phi);
+
+  //  if (coord[0]==8 && coord[1]==24 && coord[2]==28)
+  // printf("phi=%f, FA=%f, H=%f\n",phi,FA,H);
+
+  return phi;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLaxFriedrichTest::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3];  input->GetDimensions(dim);
+  double spc[3]; input->GetSpacing(spc);
+  
+  if (this->GetInput()==NULL) {
+    vtkErrorMacro(<<"No Input Image\n Exiting\n");
+    return;
+  }
+  
+  this->pog = 0.0;  
+  this->tenth=(int)((8*this->NumberOfIterations) / 8.0);
+  this->count=0;
+  
+  printf("initializing...\n");
+  this->Initialize(input, output);
+  
+  this->UpdateProgress(0.01);
+  
+  for(int j=0; j<this->NumberOfIterations; j++) {
+    printf("sweeping iteration %d\n", j);
+    this->Iterate(input, output);
+  }
+  
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichTest.h b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichTest.h
new file mode 100644
index 0000000..dca95d4
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLaxFriedrichTest.h
@@ -0,0 +1,167 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+   -- vtkmpjLaxFriedrichTest.h --
+   
+   Implements Stanley Osher's Fast Sweeping Scheme for solving
+   Static Hamilton-Jacobi Equations
+   
+   Marcel Jackowski, Feb. 2004.
+   
+*/
+
+#define VTK_MPJ_KNOWN   100   
+#define VTK_MPJ_UNKNOWN   0   
+
+#ifndef __vtkmpjLaxFriedrichTest_h
+#define __vtkmpjLaxFriedrichTest_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageAccumulate.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjLaxFriedrichTest : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjLaxFriedrichTest *New();
+  vtkTypeMacro(vtkmpjLaxFriedrichTest,vtkpxSimpleImageToImageFilter);
+  
+  // Description: Sets speed image
+  void SetSpeedImage(vtkImageData *speed);
+  
+  // Description:
+  // Set/Get boundary conditions for the propagation
+  vtkSetObjectMacro(KnownPoints, vtkFloatArray);
+  vtkGetObjectMacro(KnownPoints, vtkFloatArray);
+  
+  // Description
+  // Set/Get boundary points of the computational domain
+  vtkSetObjectMacro(BoundaryPoints, vtkFloatArray);
+  vtkGetObjectMacro(BoundaryPoints, vtkFloatArray);
+
+  // Description:
+  // Get/Set Number of Iterations
+  vtkGetMacro(NumberOfIterations,int);
+  vtkSetMacro(NumberOfIterations,int);
+
+  // Front label image. Points interior to the front have value -1, points 
+  // on the front boundary have value 0, and points outside have value +1.
+  vtkGetObjectMacro(LabelImage, vtkImageData);
+  vtkGetObjectMacro(ConvergenceImage, vtkImageData);
+  
+  // Description:
+  // Set/Get Solution
+  vtkSetObjectMacro(Solution, vtkImageData);
+  vtkGetObjectMacro(Solution, vtkImageData);
+  
+  // Description:
+  // Set/Get domain points
+  vtkSetObjectMacro(DomainImage, vtkImageData);
+  vtkGetObjectMacro(DomainImage, vtkImageData);
+
+  // Description:
+  // Get/Set Number of Iterations
+  vtkGetMacro(BoundaryValue,float);
+  vtkSetMacro(BoundaryValue,float);
+
+  // Description:
+  // Get/Set Number of Iterations
+  vtkGetMacro(DomainValue,float);
+  vtkSetMacro(DomainValue,float);
+
+ protected:
+  int SecondOrder;
+  int NumberOfIterations;
+  int KnownValues;
+  float BoundaryValue;
+  float DomainValue;
+  vtkImageData *Speed;
+  vtkImageData *DomainImage;
+  vtkDataArray *domain;
+  vtkImageData *Solution;
+  vtkFloatArray *KnownPoints;
+  vtkFloatArray *BoundaryPoints;
+  vtkImageData *LabelImage;
+  vtkImageData *ConvergenceImage;
+  vtkDataArray *label;
+  vtkDataArray *convergence;
+
+  vtkmpjLaxFriedrichTest();
+  virtual ~vtkmpjLaxFriedrichTest();
+  
+  void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+
+  void Initialize(vtkImageData *input, vtkImageData *output);
+  void Iterate(vtkImageData *input, vtkImageData *output);
+
+  void Sweep(vtkImageData *input, vtkImageData *output, int dir[3]);
+  void SweepBoundaries(vtkImageData *input, vtkImageData *output);
+  void SweepOldBoundaries(vtkImageData *input, vtkImageData *output);
+  void SweepSliceBoundary(vtkImageData *input, vtkImageData *output);
+  void SweepRowBoundary(vtkImageData *input, vtkImageData *output);
+  void SweepColumnBoundary(vtkImageData *input, vtkImageData *output);
+
+  double Update(vtkImageData *input, vtkImageData *output, 
+		int coord[3], int index);
+  
+  double SolveH(int coord[3], int index, double p, double q, double r, 
+		float T[3][3], float N[3][3], float V[3][3], float FA);
+  double SolveHp(int coord[3], int index, double p, double q, double r, 
+		 float N[3][3], float V[3][3], float FA); 
+  double SolveHq(int coord[3], int index, double p, double q, double r, 
+		 float N[3][3], float V[3][3], float FA);
+  double SolveHr(int coord[3], int index, double p, double q, double r, 
+		 float N[3][3], float V[3][3], float FA);
+  
+  void NormalizeTensor3x3(float T[3][3], float W[3], float V[3][3], 
+			  float N[3][3]);
+  void Jacobi3x3(float a[3][3], float w[3], float v[3][3]);
+
+ private: 
+  //BTX
+  float pog;
+  int count, tenth; 
+  //ETX
+  
+  vtkmpjLaxFriedrichTest(const vtkmpjLaxFriedrichTest&);// Not implemented
+  void operator=(const vtkmpjLaxFriedrichTest&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetMethod.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetMethod.cpp
new file mode 100644
index 0000000..300f676
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetMethod.cpp
@@ -0,0 +1,293 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjLevelSetMethod.h"
+
+//------------------------------------------------------------------------------
+vtkmpjLevelSetMethod* vtkmpjLevelSetMethod::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjLevelSetMethod");
+  if (ret) {
+    return (vtkmpjLevelSetMethod*)ret;
+  }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjLevelSetMethod;
+}
+
+// Construct object with no children.
+vtkmpjLevelSetMethod::vtkmpjLevelSetMethod()
+{
+  this->TimeStepSize = 0.5;
+  this->NarrowBandwidth = 12;
+  this->PropagationTime = VTK_LARGE_FLOAT;
+  this->Spacing = 1.0;
+  this->InputImage = NULL;
+  this->OutputImage = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjLevelSetMethod::~vtkmpjLevelSetMethod()
+{
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetMethod::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  //output->SetNumberOfScalarComponents(1);  
+  //output->SetScalarType(VTK_FLOAT);
+  //output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLevelSetMethod::ComputeEntropyGradientMagnitude(vtkImageData *input, double speed,
+							     int index, int coord[3])
+{
+  vtkDataArray *phi = input->GetPointData()->GetScalars();  
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  double magnitude = 0.0;    
+  double value = input->GetPointData()->GetScalars()->GetComponent(index, 0);
+  double diff_val = 0.0;
+  
+  for(int j=0; j<3; j++) {
+    
+    // compute backward differences
+    if (coord[j] > 0) {      
+
+      diff_val = value - phi->GetComponent(index-factor[j], 0);
+      
+      if ((speed > 0 && diff_val > 0) ||
+	  (speed < 0 && diff_val < 0)) {
+	
+	magnitude += diff_val * diff_val;
+      }
+    }
+
+    // compute forward differences
+    if (coord[j] < dim[j]-1) {
+      
+      diff_val = phi->GetComponent(index+factor[j], 0) - value;
+      
+      if ((speed > 0 && diff_val < 0) ||
+	  (speed < 0 && diff_val > 0)) {
+	
+	magnitude += diff_val * diff_val;
+      }
+    }
+  }
+
+  magnitude = sqrt(magnitude);
+
+  return magnitude;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetMethod::ComputeNormal(vtkImageData *input, int index, int coord[3], float result[3])
+{
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  
+  // number of voxels in a row and slice
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  float D[3][2];
+  
+  // phi value and position index
+  float value1 = in->GetComponent(index, 0);
+
+  for (int j=0; j<3; j++)  // axis  
+    for (int i=-1; i<2; i+=2) // direction 
+      {		
+	int neighbor=index + (int)i*factor[j];	
+	int i1 = i<0?0:i;
+
+	D[j][i1] = VTK_LARGE_FLOAT;
+	
+	if ((coord[j]+i >= 0) && (coord[j]+i < dim[j])) {	  
+	  float value2 = in->GetComponent(neighbor, 0);
+	  D[j][i1] = ((float)-i)*value1 + ((float)i)*value2;
+	}
+	
+      }
+
+  float Dxm = D[0][0];
+  float Dxp = D[0][1];
+  float Dym = D[1][0];
+  float Dyp = D[1][1];
+  float Dzm = D[2][0];
+  float Dzp = D[2][1];
+  
+  float n[8][3] ={{Dxp, Dyp, Dzp},
+		  {Dxp, Dym, Dzp},
+		  {Dxm, Dyp, Dzp},
+		  {Dxm, Dym, Dzp},
+		  {Dxp, Dyp, Dzm},
+		  {Dxp, Dym, Dzm},
+		  {Dxm, Dyp, Dzm},
+		  {Dxm, Dym, Dzm}};
+  
+  float aux[3];
+  float normal[3];
+  
+  normal[0]=0.0; normal[1]=0.0; normal[2]=0.0;
+
+  int count = 0;
+  for(int k=0; k<8; k++) {
+   
+    if (n[k][0] == VTK_LARGE_FLOAT || 
+	n[k][1] == VTK_LARGE_FLOAT ||
+	n[k][2] == VTK_LARGE_FLOAT)
+      continue;
+
+    aux[0]=n[k][0]; 
+    aux[1]=n[k][1]; 
+    aux[2]=n[k][2];
+    
+    vtkMath::Normalize(aux);
+    
+    normal[0] += aux[0];
+    normal[1] += aux[1];
+    normal[2] += aux[2];
+
+    count++;
+  }
+
+  // average normal 
+  normal[0] /= (float)count;
+  normal[1] /= (float)count;
+  normal[2] /= (float)count;
+    
+  result[0] = normal[0];
+  result[1] = normal[1];
+  result[2] = normal[2];
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLevelSetMethod::ComputeSpeed(vtkImageData *input, int index, int coord[3])
+{
+  double speed = this->ComputeEntropyGradientMagnitude(input, 1.0, index, coord);
+  return speed;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetMethod::Initialize(vtkImageData *input, vtkImageData *output)
+{    
+  this->InputImage = input;
+  this->OutputImage = output;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetMethod::Propagate(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  //int factor[3] = {1, dim[0], dim0Tdim1};
+  int total = input->GetPointData()->GetScalars()->GetNumberOfTuples();
+  int coord[3];
+
+  double time = 0.0;
+
+  while (time <= this->PropagationTime) {
+    
+    vtkDataArray *in = this->InputImage->GetPointData()->GetScalars();
+    vtkDataArray *out = this->OutputImage->GetPointData()->GetScalars();
+    
+    this->UpdateProgress(time * this->tenth);
+    
+    printf("time=%f\n",time);
+
+    for(int index=0; index < total; index++) {
+
+      // decompose index into point coordinates
+      coord[2] = index / dim0Tdim1; 
+      coord[1] = (index % dim0Tdim1) / dim[0];
+      coord[0] = (index % dim0Tdim1) % dim[0];
+
+      // compute propagation speed
+      double speed = this->ComputeSpeed(this->InputImage, index, coord);
+      
+      // compute new phi value
+      double newphi =  in->GetComponent(index, 0) - this->TimeStepSize * speed;
+      out->SetComponent(index, 0, (float)newphi);
+      
+    }
+    
+    // advance time
+    time += this->TimeStepSize;
+    
+    this->SwapImages();
+  }
+  
+  this->SwapImages();
+
+  this->CopyImage(this->OutputImage, output);
+  //  output->DeepCopy(this->OutputImage);  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetMethod::CopyImage(vtkImageData *source, vtkImageData *dest)
+{
+  vtkDataArray *src = source->GetPointData()->GetScalars();
+  vtkDataArray *dst = dest->GetPointData()->GetScalars();
+  int total = src->GetNumberOfTuples();
+  for (int j=0; j<total; j++) {
+    dst->SetComponent(j, 0, src->GetComponent(j, 0));
+  }
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetMethod::SwapImages()
+{
+  vtkImageData *temp = this->OutputImage;
+  this->OutputImage = this->InputImage;
+  this->InputImage = temp;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetMethod::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  this->UpdateProgress(0.01);
+  
+  this->tenth=(int)(this->PropagationTime / this->TimeStepSize);
+
+  this->Initialize(input, output);  
+  this->Propagate(input, output);
+
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetMethod.h b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetMethod.h
new file mode 100644
index 0000000..4530efc
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetMethod.h
@@ -0,0 +1,113 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+  -- vtkmpjLevelSetMethod.h --
+   
+  Implements Sethian's Level Set Method on 3D uniform lattice domains.
+
+  Marcel Jackowski, May 2003.
+*/
+
+#ifndef __vtkmpjLevelSetMethod_h
+#define __vtkmpjLevelSetMethod_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkmpjPriorityQueue.h"
+#include "vtkImageAccumulate.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjLevelSetMethod : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjLevelSetMethod *New();
+  vtkTypeMacro(vtkmpjLevelSetMethod,vtkpxSimpleImageToImageFilter);
+  
+  // Set/Get time step size
+  vtkGetMacro(TimeStepSize,float);
+  vtkSetMacro(TimeStepSize,float);  
+
+  // Set/Get narrow band size
+  vtkGetMacro(NarrowBandwidth,float);
+  vtkSetMacro(NarrowBandwidth,float);  
+
+  // Set/Get maximum propagation time
+  vtkGetMacro(PropagationTime,float);
+  vtkSetMacro(PropagationTime,float);  
+  
+  // Set/Get grid spacing
+  vtkGetMacro(Spacing,float);
+  vtkSetMacro(Spacing,float);
+  
+ protected:
+  vtkFloatArray *NarrowBandPoints;
+  float TimeStepSize;    // default 0.5
+  float NarrowBandwidth; // default 12
+  float PropagationTime;
+  float Spacing;
+
+  vtkmpjLevelSetMethod();
+  virtual ~vtkmpjLevelSetMethod();
+    
+  void ExecuteInformation();
+  
+  void ComputeNormal(vtkImageData *input, int index, int coord[3], float result[3]);
+  double ComputeEntropyGradientMagnitude(vtkImageData *input, double speed, int index, int coord[3]);
+  
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  virtual void Initialize(vtkImageData *input, vtkImageData *output);
+  virtual void Propagate(vtkImageData *input, vtkImageData *output);
+  virtual double ComputeSpeed(vtkImageData *input, int index, int coord[3]);
+  
+ private:
+  //BTX
+  float pog;
+  int count, tenth;  
+  vtkImageData *InputImage;
+  vtkImageData *OutputImage;
+
+  void CopyImage(vtkImageData *source, vtkImageData *dest);
+  void SwapImages();
+
+  //ETX
+  
+  vtkmpjLevelSetMethod(const vtkmpjLevelSetMethod&);// Not implemented
+  void operator=(const vtkmpjLevelSetMethod&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNarrowBandFilter.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNarrowBandFilter.cpp
new file mode 100644
index 0000000..fb9094e
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNarrowBandFilter.cpp
@@ -0,0 +1,122 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjLevelSetNarrowBandFilter.h"
+
+//------------------------------------------------------------------------------
+vtkmpjLevelSetNarrowBandFilter* vtkmpjLevelSetNarrowBandFilter::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjLevelSetNarrowBandFilter");
+  if (ret) {
+    return (vtkmpjLevelSetNarrowBandFilter*)ret;
+  }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjLevelSetNarrowBandFilter;
+}
+
+// Construct object with no children.
+vtkmpjLevelSetNarrowBandFilter::vtkmpjLevelSetNarrowBandFilter()
+{
+  this->NarrowBandwidth = 12;
+  this->LevelSetValue = 0;
+  this->NarrowBandPoints = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjLevelSetNarrowBandFilter::~vtkmpjLevelSetNarrowBandFilter()
+{
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetNarrowBandFilter::ExecuteInformation()
+{
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetNarrowBandFilter::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  //  int factor[3] = {1, dim[0], dim0Tdim1};
+  float maxwidth = this->NarrowBandwidth / 2.0;
+  
+  vtkDataArray *in = input->GetPointData()->GetScalars();
+  vtkDataArray *out = output->GetPointData()->GetScalars();
+
+  int total = in->GetNumberOfTuples();
+  int coord[3];
+
+  if (this->NarrowBandPoints != NULL) {
+    this->NarrowBandPoints->Delete();
+  }
+  this->NarrowBandPoints = vtkFloatArray::New();
+  this->NarrowBandPoints->SetNumberOfComponents(4);
+
+  this->pog = 0.0;  
+  this->tenth=(int)(total / 10.0);
+  this->count = 0;
+  
+  this->UpdateProgress(0.01);
+  
+  for (int index=0; index<total; index++) {
+    
+    if (this->count==this->tenth)
+      {
+	this->pog+=0.1;
+	this->UpdateProgress(this->pog);
+	this->count=0;
+      }
+    
+    // decompose linear index into point coordinates
+    coord[2] = index / dim0Tdim1; 
+    coord[1] = (index % dim0Tdim1) / dim[0];
+    coord[0] = (index % dim0Tdim1) % dim[0];
+    
+    // get level set value
+    float value = in->GetComponent(index, 0);
+    
+    // keep narrow band values
+    if ((value >= -maxwidth) && (value <= maxwidth)) {     
+      
+      out->SetComponent(index, 0, 1.0);     
+      
+      this->NarrowBandPoints->InsertNextTuple4((float)coord[0], (float)coord[1], 
+					       (float)coord[2], (float)value);
+    }
+    
+  }
+
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNarrowBandFilter.h b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNarrowBandFilter.h
new file mode 100644
index 0000000..bb1e069
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNarrowBandFilter.h
@@ -0,0 +1,96 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+  -- vtkmpjLevelSetNarrowBandFilter.h --
+  
+  Given an input level set, creates a narrow band of a given size.
+  Returns an image mask of the narrow band as well as a list of
+  locations and level set values.
+  
+  Marcel Jackowski, June 2003.
+*/
+
+#ifndef __vtkmpjLevelSetNarrowBandFilter_h
+#define __vtkmpjLevelSetNarrowBandFilter_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkmpjPriorityQueue.h"
+#include "vtkImageAccumulate.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjLevelSetNarrowBandFilter : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjLevelSetNarrowBandFilter *New();
+  vtkTypeMacro(vtkmpjLevelSetNarrowBandFilter,vtkpxSimpleImageToImageFilter);
+  
+  // Set/Get narrow bandwidth 
+  vtkGetMacro(NarrowBandwidth,float);
+  vtkSetMacro(NarrowBandwidth,float);
+
+  // Set/Get level set to extract
+  vtkGetMacro(LevelSetValue, float);
+  vtkSetMacro(LevelSetValue, float);
+
+  // Get extracted narrow band points
+  vtkGetObjectMacro(NarrowBandPoints, vtkFloatArray);
+
+ protected:
+  vtkFloatArray *NarrowBandPoints;
+  float NarrowBandwidth; // default 12
+  float LevelSetValue;   // default 0
+
+  vtkmpjLevelSetNarrowBandFilter();
+  virtual ~vtkmpjLevelSetNarrowBandFilter();
+  
+  void ExecuteInformation();
+  
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  
+ private:
+  //BTX
+  float pog;
+  int count, tenth;
+  //ETX
+
+  vtkmpjLevelSetNarrowBandFilter(const vtkmpjLevelSetNarrowBandFilter&);// Not implemented
+  void operator=(const vtkmpjLevelSetNarrowBandFilter&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNeighborhoodExtractor.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNeighborhoodExtractor.cpp
new file mode 100644
index 0000000..b0b38ca
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNeighborhoodExtractor.cpp
@@ -0,0 +1,397 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjLevelSetNeighborhoodExtractor.h"
+
+vtkStandardNewMacro(vtkmpjLevelSetNeighborhoodExtractor);
+
+// Construct object 
+vtkmpjLevelSetNeighborhoodExtractor::vtkmpjLevelSetNeighborhoodExtractor()
+{
+  this->LevelSetValue = 0.0;
+  this->InsidePoints = NULL;
+  this->OutsidePoints = NULL;
+  this->LargeValue = VTK_LARGE_FLOAT;
+  this->NarrowBanding = 0;
+  this->NarrowBandwidth = 12.0;
+  this->InputNarrowBand = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjLevelSetNeighborhoodExtractor::~vtkmpjLevelSetNeighborhoodExtractor()
+{  
+  if (this->InsidePoints != NULL)
+    this->InsidePoints->Delete();
+
+  if (this->OutsidePoints != NULL)
+    this->OutsidePoints->Delete();
+  
+  if (this->InputNarrowBand != NULL)
+    this->InputNarrowBand->Delete();  
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjLevelSetNeighborhoodExtractor::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);  
+  os << indent << "Input level set: " << this->GetInput() << "\n";
+  os << indent << "Level set value: " << this->LevelSetValue << "\n";
+  os << indent << "Narrow bandwidth: " << this->NarrowBandwidth << "\n";
+  os << indent << "Narrowbanding: " << this->NarrowBanding << "\n";
+  os << indent << "Input narrow band: ";
+  os << this->InputNarrowBand << "\n";  
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjLevelSetNeighborhoodExtractor::SortNodesUsed() 
+{
+  int tmpIndex[3];
+  double tmpValue[3];
+  
+  if (this->NodesUsedValue[0] < this->NodesUsedValue[1]) {
+    if (this->NodesUsedValue[0] < this->NodesUsedValue[2]) {
+      if (this->NodesUsedValue[1] < this->NodesUsedValue[2]) {
+	tmpValue[0] = this->NodesUsedValue[0]; tmpIndex[0] = this->NodesUsedIndex[0];  
+	tmpValue[1] = this->NodesUsedValue[1]; tmpIndex[1] = this->NodesUsedIndex[1];  
+	tmpValue[2] = this->NodesUsedValue[2]; tmpIndex[2] = this->NodesUsedIndex[2];  
+      } else {
+	tmpValue[0] = this->NodesUsedValue[0]; tmpIndex[0] = this->NodesUsedIndex[0];  
+	tmpValue[1] = this->NodesUsedValue[2]; tmpIndex[1] = this->NodesUsedIndex[2];  
+	tmpValue[2] = this->NodesUsedValue[1]; tmpIndex[2] = this->NodesUsedIndex[1];  
+      }
+    } else 
+      {
+	tmpValue[0] = this->NodesUsedValue[2]; tmpIndex[0] = this->NodesUsedIndex[2];  
+	tmpValue[1] = this->NodesUsedValue[0]; tmpIndex[1] = this->NodesUsedIndex[0];  
+	tmpValue[2] = this->NodesUsedValue[1]; tmpIndex[2] = this->NodesUsedIndex[1];  
+      }
+  } else {
+    if (this->NodesUsedValue[1] < this->NodesUsedValue[2]) {
+      if (this->NodesUsedValue[0] < this->NodesUsedValue[2]) {
+	tmpValue[0] = this->NodesUsedValue[1]; tmpIndex[0] = this->NodesUsedIndex[1];  
+	tmpValue[1] = this->NodesUsedValue[0]; tmpIndex[1] = this->NodesUsedIndex[0];  
+	tmpValue[2] = this->NodesUsedValue[2]; tmpIndex[2] = this->NodesUsedIndex[2];  
+      } else {
+	tmpValue[0] = this->NodesUsedValue[1]; tmpIndex[0] = this->NodesUsedIndex[1];  
+	tmpValue[1] = this->NodesUsedValue[2]; tmpIndex[1] = this->NodesUsedIndex[2];  
+	tmpValue[2] = this->NodesUsedValue[0]; tmpIndex[2] = this->NodesUsedIndex[0];  
+      }
+    } else
+      {
+	tmpValue[0] = this->NodesUsedValue[2]; tmpIndex[0] = this->NodesUsedIndex[2];  
+	tmpValue[1] = this->NodesUsedValue[1]; tmpIndex[1] = this->NodesUsedIndex[1];  
+	tmpValue[2] = this->NodesUsedValue[0]; tmpIndex[2] = this->NodesUsedIndex[0];  
+      }    
+  }
+  
+  this->NodesUsedValue[0] = tmpValue[0];
+  this->NodesUsedValue[1] = tmpValue[1];
+  this->NodesUsedValue[2] = tmpValue[2];
+
+  this->NodesUsedIndex[0] = tmpIndex[0];
+  this->NodesUsedIndex[1] = tmpIndex[1];
+  this->NodesUsedIndex[2] = tmpIndex[2];
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjLevelSetNeighborhoodExtractor::Initialize()
+{
+  this->InsidePoints = vtkDoubleArray::New();
+  this->InsidePoints->SetNumberOfComponents(4);
+  
+  this->OutsidePoints = vtkDoubleArray::New();
+  this->OutsidePoints->SetNumberOfComponents(4);
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjLevelSetNeighborhoodExtractor::GenerateDataFull(vtkImageData *input, vtkImageData *output)
+{  
+  int dim[3]; input->GetDimensions(dim);
+  int dim0xdim1 = dim[0]*dim[1];
+  unsigned long index;
+  int coord[3];
+
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  double distance;
+  
+  unsigned long totalPixels = 
+    input->GetPointData()->GetScalars()->GetNumberOfTuples(); 
+  
+  unsigned long updateVisits = totalPixels / 10;
+  if ( updateVisits < 1) { updateVisits = 1; }
+  
+  unsigned long i;
+  for ( index = 0; index < totalPixels; index++ )
+    {
+      // update progress
+      if ( !(index % updateVisits) )
+	{
+	  this->UpdateProgress( (float) index/ (float) totalPixels );
+	}
+      
+      // decompose index
+      coord[2] = index / dim0xdim1; 
+      int r = index % dim0xdim1;
+      coord[1] = r / dim[0];
+      coord[0] = r % dim[0];
+      
+      distance = this->CalculateDistance( index, coord );
+      
+      // write out distance to the levelset
+      out->SetComponent(index, 0, distance);      
+    }
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjLevelSetNeighborhoodExtractor::GenerateDataNarrowBand(vtkImageData *input, vtkImageData *output)
+{
+  if ( !this->InputNarrowBand ) {
+    vtkErrorMacro(<< "InputNarrowBand has not been set" );
+    return;
+  }
+  
+  if (this->InputNarrowBand->GetNumberOfComponents() < 4) {
+    vtkErrorMacro(<< "InputNarrowBand should contain tuples with 4 components " );
+    return;
+  }
+
+  int dim[3]; input->GetDimensions(dim);
+  int dim0xdim1 = dim[0]*dim[1];
+  int index=0, coord[3];
+  
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  double maxValue = this->NarrowBandwidth / 2.0;
+  double nodeValue;
+  double distance;
+
+  int nc = this->InputNarrowBand->GetNumberOfComponents();
+  unsigned long totalPixels  = this->InputNarrowBand->GetNumberOfTuples();
+  unsigned long updateVisits = totalPixels / 10;
+  if ( updateVisits < 1) { updateVisits = 1; }
+
+  unsigned int i;
+  for ( i = 0; i < totalPixels; i++ )
+    {
+      
+      // update progress
+      if ( !(i % updateVisits) )
+	{
+	  this->UpdateProgress( (float) i/ (float) totalPixels );
+	}
+      
+      coord[0] = (int)this->InputNarrowBand->GetComponent(index, 0);
+      coord[1] = (int)this->InputNarrowBand->GetComponent(index, 1);
+      coord[2] = (int)this->InputNarrowBand->GetComponent(index, 2);
+      
+      if (nc > 3)
+	nodeValue = (double)this->InputNarrowBand->GetComponent(index, 3);
+      else nodeValue = 0.0;
+      
+      if ( fabs(nodeValue) <= maxValue )
+	{
+	  index = dim0xdim1*coord[2] + dim[0]*coord[1] + coord[0];
+	 
+	  distance = this->CalculateDistance( index, coord );
+
+	  // write out distance to the levelset
+	  out->SetComponent(index, 0, distance);
+	}
+    }
+}
+
+//----------------------------------------------------------------------------
+double vtkmpjLevelSetNeighborhoodExtractor::CalculateDistance( int index, int coord[3] )
+{  
+  vtkImageData *input = this->GetInput();
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+
+  int dim[3]; input->GetDimensions(dim);
+  int dim0xdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0xdim1};
+
+  this->LastPointIsInside = 0;
+
+  double centerValue = (double) in->GetComponent(index, 0);
+  centerValue -= this->LevelSetValue;
+
+  double centerNodeValue;
+  
+  int centerNodeIndex = index;
+  int centerNodeCoord[3] = {coord[0], coord[1], coord[2]};
+  
+  if( centerValue == 0.0 )
+    { 
+      centerNodeValue = 0.0;
+      this->InsidePoints->InsertNextTuple4( centerNodeCoord[0], 
+					    centerNodeCoord[1], 
+					    centerNodeCoord[2],
+					    centerNodeValue);
+      this->LastPointIsInside = 1;
+      return 0.0;
+    }
+  
+  int inside = ( centerValue <= 0.0 );
+
+  int neighIndex = index;
+  double neighValue;
+  
+  int neighNodeIndex;
+  double neighNodeValue;
+  
+  double distance;
+
+  // In each dimension, find the distance to the zero set
+  // by linear interpolating along the grid line.
+  for( unsigned int j = 0; j < 3; j++ )
+    {
+      neighNodeValue = this->LargeValue;
+
+      for( int s = -1; s < 2; s = s + 2 )
+	{
+	  neighIndex = index + s*factor[j];
+	  
+	  if ( (coord[j] + s) < 0 || (coord[j] + s) >= dim[j] ) 
+	    {
+	      continue;
+	    }
+	  
+	  neighValue = (double) in->GetComponent( neighIndex, 0 );
+	  neighValue -= this->LevelSetValue;
+	  
+	  if( ( neighValue > 0 && inside ) ||
+	      ( neighValue < 0 && !inside ) )
+	    {
+	      distance = centerValue / ( centerValue - neighValue );
+	      
+	      if( neighNodeValue > distance )
+		{
+		  neighNodeValue = distance;
+		  neighNodeIndex = neighIndex;
+		}
+	    }
+	  
+	} // end one dim loop
+      
+      // put the minimum distance neighbor onto the heap
+      this->NodesUsedIndex[j] = neighNodeIndex;
+      this->NodesUsedValue[j] = neighNodeValue;
+      
+      // reset neighIndex
+      
+    } // end dimension loop
+  
+    
+  // sort the neighbors according to distance
+  this->SortNodesUsed();
+  //  std::sort( m_NodesUsed.begin(), m_NodesUsed.end() );
+  
+  // The final distance is given by the minimum distance to the plane
+  // crossing formed by the zero set crossing points.
+  distance = 0.0;
+  for( unsigned int j = 0; j < 3; j++ )
+    {
+      neighNodeIndex = this->NodesUsedIndex[j];
+      neighNodeValue = this->NodesUsedValue[j];
+
+      if( neighNodeValue >= this->LargeValue )
+	{ 
+	  break;
+	}
+      
+      distance += (double) 1.0 / ( neighNodeValue * neighNodeValue );
+    }
+  
+  if( distance == 0.0 )
+    {
+      return this->LargeValue;
+    }
+  
+  distance = sqrt( (double) 1.0 / distance );
+  centerNodeValue = distance;
+
+  if( inside )
+    {
+      this->InsidePoints->InsertNextTuple4( centerNodeCoord[0],
+					    centerNodeCoord[1],
+					    centerNodeCoord[2],
+					    centerNodeValue );
+      this->LastPointIsInside = 1;
+    }
+  else
+    {
+      this->OutsidePoints->InsertNextTuple4( centerNodeCoord[0],
+					     centerNodeCoord[1],
+					     centerNodeCoord[2],
+					     centerNodeValue );      
+      this->LastPointIsInside = 0;
+    }
+  
+  return distance;
+  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetNeighborhoodExtractor::ExecuteInformation()
+{
+  vtkImageData *output = this->GetOutput();  
+  
+  vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  output->SetScalarType(VTK_FLOAT);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetNeighborhoodExtractor::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if( this->GetInput() == NULL ) 
+    { 
+      vtkErrorMacro( << "Input level set is NULL" );
+      return;
+    }
+  
+  this->Initialize();
+  
+  if( this->NarrowBanding )
+    {
+      this->GenerateDataNarrowBand(input, output);
+    }
+  else
+    {
+      this->GenerateDataFull(input, output);
+    }
+  
+  vtkDebugMacro(<< "No. inside points: " << InsidePoints->GetNumberOfTuples());
+  vtkDebugMacro(<< "No. outside points: " << OutsidePoints->GetNumberOfTuples());
+}
+
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNeighborhoodExtractor.h b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNeighborhoodExtractor.h
new file mode 100644
index 0000000..8cefb20
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNeighborhoodExtractor.h
@@ -0,0 +1,183 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  vtkmpjLevelSetNeighborhoodExtractor.h
+  
+  Marcel Jackowski, Feb. 2005.
+  
+  This is a VTK translation of the itkLevelSetNeighborhoodExtractor from the 
+  Insight Segmentation & Registration Toolkit.
+  
+  Notes: converted to take vtkDoubleArrays
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+  
+=========================================================================*/
+#ifndef _vtkmpjLevelSetNeighborhoodExtractor_h
+#define _vtkmpjLevelSetNeighborhoodExtractor_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageSource.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkImageAccumulate.h"
+#include "vtkDataArray.h"
+#include "vtkDoubleArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+/** \class LevelSetNeighborhoodExtractor
+ * \brief Locate pixels of a particular level set.
+ *
+ * LevelSetNeighborhoodExtractor locates a particular level set in the input
+ * level set. Specifically, the method Locate() fills two containers: one
+ * containing pixels immediately inside the contour defined by the level set
+ * and the other containing pixels immediately outside.  For each located
+ * pixel, an estimated distance to the particular level set is also
+ * calculated.
+ *
+ * The containers InsidePoints and OutsidePoints can then be used 
+ * in FastMarchingImageFilter to produce a signed distance map from 
+ * the specified level set.
+ *
+ * This class is templated over the image type representing
+ * the level set.
+ *
+ * This class supports narrowbanding. If a input narrowband is
+ * provided, the alogrithm will only search pixels within the
+ * narrowband.
+ *
+ * Implemenation of this class is based on Chapter 11 of
+ * "Level Set Methods and Fast Marching Methods", J.A. Sethian,
+ * Cambridge Press, Second edition, 1999.
+ *
+ * \ingroup LevelSetSegmentation 
+ * 
+ */
+
+class vtkmpjLevelSetNeighborhoodExtractor: public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjLevelSetNeighborhoodExtractor *New();
+  vtkTypeMacro(vtkmpjLevelSetNeighborhoodExtractor,vtkpxSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  void SetInputLevelSet(vtkImageData *ptr) { SetInput(ptr); }
+
+  // Description:
+  // Set/Get Set the value of the level set to be located. Default is 0.
+  vtkSetMacro(LevelSetValue, double);
+  vtkGetMacro(LevelSetValue, double);
+
+  // Description:
+  // Set/Get the narrow band width. Default is 12.
+  vtkSetMacro(NarrowBandwidth, double);
+  vtkGetMacro(NarrowBandwidth, double);
+  
+  // Description:
+  // Set/Get the narrowbanding flag. 
+  vtkGetMacro(NarrowBanding, int);
+  vtkSetMacro(NarrowBanding, int);
+  vtkBooleanMacro(NarrowBanding, int);
+  
+  // Description:
+  // Set/Get the input narrowband. 
+  vtkSetObjectMacro(InputNarrowBand, vtkDataArray);
+  vtkGetObjectMacro(InputNarrowBand, vtkDataArray);
+  
+  // Description:
+  // Get the container of inside points.
+  vtkGetObjectMacro(InsidePoints, vtkDoubleArray);
+
+  // Description:
+  // Get the container of outside points.
+  vtkGetObjectMacro(OutsidePoints, vtkDoubleArray);
+
+  // Description:
+  // Set/Get Set value for infinity
+  vtkSetMacro(LargeValue, double);
+  vtkGetMacro(LargeValue, double);
+  
+  // Description:
+  // Locate the level set. This method evokes the level set
+  // location algorithm
+  void Locate() { this->Update(); }
+
+protected:
+  vtkmpjLevelSetNeighborhoodExtractor();
+  virtual ~vtkmpjLevelSetNeighborhoodExtractor();
+
+  double LevelSetValue;
+
+  vtkDoubleArray *InsidePoints;
+  vtkDoubleArray *OutsidePoints;
+
+  int NarrowBanding;
+  double NarrowBandwidth;
+  vtkDataArray *InputNarrowBand;
+
+  double LargeValue;
+
+  int LastPointIsInside;
+ 
+  int NodesUsedIndex[3];
+  double NodesUsedValue[3];
+
+  int GetNodeIndexUsedInComputation(unsigned int idx) { return NodesUsedIndex[idx]; }
+  double GetNodeValueUsedInComputation(unsigned int idx) { return NodesUsedValue[idx]; }
+
+  virtual void Initialize();
+  virtual double CalculateDistance( int index, int coord[3] );
+  
+  void ExecuteInformation();  
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  
+private:  
+  vtkmpjLevelSetNeighborhoodExtractor(const vtkmpjLevelSetNeighborhoodExtractor&); //purposely not implemented
+  void operator=(const vtkmpjLevelSetNeighborhoodExtractor&); //purposely not implemented
+  
+  void SortNodesUsed();
+  void GenerateDataFull(vtkImageData *input, vtkImageData *output);
+  void GenerateDataNarrowBand(vtkImageData *input, vtkImageData *output);
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNormal.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNormal.cpp
new file mode 100644
index 0000000..06d6c21
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNormal.cpp
@@ -0,0 +1,207 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjLevelSetNormal.h"
+
+//------------------------------------------------------------------------------
+vtkmpjLevelSetNormal* vtkmpjLevelSetNormal::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjLevelSetNormal");
+  if(ret)
+    {
+      return (vtkmpjLevelSetNormal*)ret;
+    }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjLevelSetNormal;
+}
+
+// Construct object with no children.
+vtkmpjLevelSetNormal::vtkmpjLevelSetNormal()
+{
+  this->Mask = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjLevelSetNormal::~vtkmpjLevelSetNormal()
+{
+  if (this->Mask != NULL)
+    this->Mask->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetNormal::ExecuteInformation()
+{
+  vtkImageData *input=this->GetInput();
+  vtkImageData *output=this->GetOutput();
+  
+  if (input==NULL) {
+    vtkErrorMacro(<<"No Input Specified!!");
+    return;
+  }
+  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  int dim[3];  input->GetDimensions(dim);
+
+  output->SetNumberOfScalarComponents(3);  
+  output->SetScalarType(VTK_DOUBLE);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+int vtkmpjLevelSetNormal::InsideMask(int index)
+{
+  return (this->mask != NULL)?(this->mask->GetComponent(index, 0) > 0) : 1;
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetNormal::ComputeNormal(vtkImageData *input, vtkImageData *output,
+					 int coord[3], int index, double result[3])
+{
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  
+  int dim[3]; input->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  
+  // number of voxels in a row and slice
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  double D[3][2];
+  
+  // phi value and position index
+  double value1 = in->GetComponent(index, 0);
+
+  for (int j=0; j<3; j++)  // axis  
+    for (int i=-1; i<2; i+=2) // direction 
+      {		
+	int neighbor=index + (int)i*factor[j];	
+	int i1 = i<0?0:i;
+
+	D[j][i1] = VTK_LARGE_FLOAT;
+	
+	if ((coord[j]+i >= 0) && (coord[j]+i < dim[j]) && (this->InsideMask(neighbor))) {	  
+	  double value2 = in->GetComponent(neighbor, 0);
+	  D[j][i1] = ((double)-i)*value1 + ((double)i)*value2;
+	}
+	
+      }
+
+  double Dxm = D[0][0];
+  double Dxp = D[0][1];
+  double Dym = D[1][0];
+  double Dyp = D[1][1];
+  double Dzm = D[2][0];
+  double Dzp = D[2][1];
+  
+  double n[8][3] ={{Dxp, Dyp, Dzp},
+		  {Dxp, Dym, Dzp},
+		  {Dxm, Dyp, Dzp},
+		  {Dxm, Dym, Dzp},
+		  {Dxp, Dyp, Dzm},
+		  {Dxp, Dym, Dzm},
+		  {Dxm, Dyp, Dzm},
+		  {Dxm, Dym, Dzm}};
+  
+  double aux[3];
+  double normal[3];
+  
+  normal[0]=0.0; normal[1]=0.0; normal[2]=0.0;
+
+  int count = 0;
+  for(int k=0; k<8; k++) {
+   
+    if (n[k][0] == VTK_LARGE_FLOAT || 
+	n[k][1] == VTK_LARGE_FLOAT ||
+	n[k][2] == VTK_LARGE_FLOAT)
+      continue;
+
+    aux[0]=n[k][0]; 
+    aux[1]=n[k][1]; 
+    aux[2]=n[k][2];
+
+    vtkMath::Normalize(aux);
+    
+    normal[0] += aux[0];
+    normal[1] += aux[1];
+    normal[2] += aux[2];
+    
+    count++;
+  }
+
+  // average normal 
+  normal[0] /= (double)count;
+  normal[1] /= (double)count;
+  normal[2] /= (double)count;
+    
+  //printf("normal= %f,%f,%f\n",normal[0],normal[1],normal[2]);
+
+  result[0] = normal[0];
+  result[1] = normal[1];
+  result[2] = normal[2];
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetNormal::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{  
+  int dim[3]; input->GetDimensions(dim);
+  vtkDataArray *out = output->GetPointData()->GetScalars();
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+
+  // Get pointer to mask array
+  this->mask = (this->Mask != NULL) ? this->Mask->GetPointData()->GetScalars() : NULL;
+  
+  int index = 0;
+  int coord[3];
+  double normal[3];
+
+  for (int k=0;k<dim[2];k++) {    
+    for (int j=0;j<dim[1];j++)
+      for (int i=0;i<dim[0];i++)
+	{
+	  coord[0]=i; coord[1]=j; coord[2]=k;
+	  normal[0]=0; normal[1]=0; normal[2]=0;
+
+	  // compute normal
+	  this->ComputeNormal(input, output, coord, index, normal);
+	  
+	  out->SetComponent(index, 0, normal[0]);
+	  out->SetComponent(index, 1, normal[1]);
+	  out->SetComponent(index, 2, normal[2]);
+	  
+	  ++index;	  
+	}  	  
+    
+    double pog=double(k)/double(dim[2]);
+    this->UpdateProgress(pog);	    
+  }
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNormal.h b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNormal.h
new file mode 100644
index 0000000..ab0886e
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetNormal.h
@@ -0,0 +1,75 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#ifndef __vtkmpjLevelSetNormal_h
+#define __vtkmpjLevelSetNormal_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjLevelSetNormal : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjLevelSetNormal *New();
+  vtkTypeMacro(vtkmpjLevelSetNormal,vtkpxSimpleImageToImageFilter);
+  
+  // Description: 
+  // Sets/Gets mask for determining propagation extents
+  vtkSetObjectMacro(Mask, vtkImageData);
+  vtkGetObjectMacro(Mask, vtkImageData);
+  
+ protected:
+  vtkImageData *Mask;
+
+  vtkmpjLevelSetNormal();
+  virtual ~vtkmpjLevelSetNormal();
+  
+  int InsideMask(int index);
+  void ComputeNormal(vtkImageData *input, vtkImageData *output, 
+		     int coord[3], int index, double result[3]);
+  
+  void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+    
+ private: 
+  //BTX
+  vtkDataArray *mask;
+  //ETX
+  vtkmpjLevelSetNormal(const vtkmpjLevelSetNormal&);// Not implemented
+  void operator=(const vtkmpjLevelSetNormal&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetSignedDistance.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetSignedDistance.cpp
new file mode 100644
index 0000000..9e303e7
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetSignedDistance.cpp
@@ -0,0 +1,228 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjLevelSetSignedDistance.h"
+
+//------------------------------------------------------------------------------
+vtkmpjLevelSetSignedDistance* vtkmpjLevelSetSignedDistance::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjLevelSetSignedDistance");
+  if (ret) {
+    return (vtkmpjLevelSetSignedDistance*)ret;
+  }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjLevelSetSignedDistance;
+}
+
+// Construct object with no children.
+vtkmpjLevelSetSignedDistance::vtkmpjLevelSetSignedDistance()
+{
+  this->LevelSetValue = 0.0;
+  this->PropagationTime = 0;
+  this->ExtensionImage = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjLevelSetSignedDistance::~vtkmpjLevelSetSignedDistance()
+{
+  if (this->ExtensionImage != NULL)
+    this->ExtensionImage->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetSignedDistance::ExecuteInformation()
+{
+  vtkImageData *output = this->GetOutput();
+  vtkImageData *input = this->GetInput();
+  
+  int dim[3]; input->GetDimensions(dim);
+
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  int ext_nc = 0;
+
+  if (this->ExtensionImage != NULL) {
+    ext_nc = this->ExtensionImage->GetNumberOfScalarComponents();
+  }
+  
+  output->SetNumberOfScalarComponents(ext_nc+1);  
+  output->SetScalarType(VTK_FLOAT);
+  output->SetWholeExtent(0,dim[0]-1,0,dim[1]-1,0,dim[2]-1);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetSignedDistance::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  //vtkDataArray *in = input->GetPointData()->GetScalars();
+  //vtkDataArray *out = output->GetPointData()->GetScalars();
+  vtkDataArray *ext = NULL;
+  
+  if (this->ExtensionImage != NULL) {
+    ext = this->ExtensionImage->GetPointData()->GetScalars();
+  }
+  
+  this->UpdateProgress(0.01);
+
+  // step 1: extract level set 
+  vtkmpjExtractLevelSet *xls = vtkmpjExtractLevelSet::New();
+  xls->SetInput(input);
+  xls->SetLevelSetValue(0.0);
+  xls->Update();
+  
+  this->UpdateProgress(0.125);
+
+  // step 2: get inner and outer level set mask 
+  vtkImageThreshold *thresh1 = vtkImageThreshold::New();
+  thresh1->SetInput(xls->GetOutput());
+  thresh1->SetOutputScalarTypeToFloat();
+  thresh1->ThresholdByLower(-1.0);
+  thresh1->SetInValue(1.0);
+  thresh1->SetOutValue(0.0);
+  thresh1->Update();
+
+  // step 3: march inwards and outwards
+  vtkmpjFastMarchingExtension *fmm1;
+  //  if (ext == NULL) {
+  //fmm1 = vtkmpjFastMarchingMethod::New();
+  //} else {
+  fmm1 = vtkmpjFastMarchingExtension::New();
+  fmm1->SetExtensionImage(this->ExtensionImage);
+  //}
+  fmm1->SetInput(thresh1->GetOutput());
+  fmm1->SetKnownPoints(xls->GetInsidePoints());
+  fmm1->Update();
+  
+  thresh1->Delete();
+
+  this->UpdateProgress(0.25);
+
+  vtkImageThreshold *thresh2 = vtkImageThreshold::New();
+  thresh2->SetInput(xls->GetOutput());
+  thresh2->SetOutputScalarTypeToFloat();
+  thresh2->ThresholdByUpper(1.0);
+  thresh2->SetInValue(1.0);
+  thresh2->SetOutValue(0.0);
+  thresh2->Update();
+
+  vtkmpjFastMarchingExtension *fmm2;
+  //  if (ext == NULL) {
+  //  fmm2 = vtkmpjFastMarchingMethod::New();
+  //} else {
+  fmm2 = vtkmpjFastMarchingExtension::New();
+  fmm2->SetExtensionImage(this->ExtensionImage);
+  //}
+  fmm2->SetInput(thresh2->GetOutput());
+  fmm2->SetKnownPoints(xls->GetOutsidePoints());
+  fmm2->Update();
+  
+  thresh2->Delete();
+  
+  xls->Delete();
+
+  this->UpdateProgress(0.375);
+
+  // step 4: threshold marching result to get rid of infinity values
+  vtkImageThreshold *thresh3 = vtkImageThreshold::New();
+  thresh3->SetInput(fmm1->GetOutput());
+  thresh3->SetOutputScalarTypeToFloat();
+  thresh3->ThresholdByLower(1000);
+  thresh3->SetOutValue(0);
+  thresh3->Update();
+  
+  fmm1->Delete();
+
+  vtkImageThreshold *thresh4 = vtkImageThreshold::New();
+  thresh4->SetInput(fmm2->GetOutput());
+  thresh4->SetOutputScalarTypeToFloat();
+  thresh4->ThresholdByLower(1000);
+  thresh4->SetOutValue(0);
+  thresh4->Update();
+
+  fmm2->Delete();
+
+  this->UpdateProgress(0.50);
+
+  // step 5: combine inner and outer propagation results
+  vtkmpjFrameExtract *frame0 = vtkmpjFrameExtract::New();
+  frame0->SetInput(thresh3->GetOutput());
+  frame0->SetStartFrame(0);
+  frame0->SetEndFrame(0);
+  frame0->Update();
+
+  thresh3->Delete();
+
+  this->UpdateProgress(0.625);
+
+  vtkImageMathematics *math1 = vtkImageMathematics::New();
+  math1->SetInput1(frame0->GetOutput());
+  math1->SetOperationToMultiplyByK();
+  math1->SetConstantK(-1.0);
+  math1->Update();
+
+  frame0->Delete();
+
+  this->UpdateProgress(0.75);
+
+  vtkmpjFrameExtract *frame1 = vtkmpjFrameExtract::New();
+  frame1->SetInput(thresh3->GetOutput());
+  frame1->SetStartFrame(1);
+  frame1->SetEndFrame(1);
+  frame1->Update();
+
+  vtkImageAppendComponents *appnd = vtkImageAppendComponents::New();
+  appnd->AddInput(math1->GetOutput());
+  appnd->AddInput(frame1->GetOutput());
+  appnd->Update();
+
+  math1->Delete();
+  frame1->Delete();
+
+  this->UpdateProgress(0.875);
+
+  vtkImageMathematics *math2 = vtkImageMathematics::New();
+  math2->SetInput1(appnd->GetOutput());
+  math2->SetInput2(thresh4->GetOutput());
+  math2->SetOperationToAdd();
+  math2->Update();
+
+  appnd->Delete();
+  thresh4->Delete();
+
+  // step 5: copy output
+  output->ShallowCopy(math2->GetOutput());
+
+  math2->Delete();
+
+  this->UpdateProgress(1.0);
+}
+// ----------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetSignedDistance.h b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetSignedDistance.h
new file mode 100644
index 0000000..6c416dd
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetSignedDistance.h
@@ -0,0 +1,96 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+   -- vtkmpjLevelSetSignedDistance.h --
+   
+   Marcel Jackowski, June 2003.
+*/
+
+#ifndef __vtkmpjLevelSetSignedDistance_h
+#define __vtkmpjLevelSetSignedDistance_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageAppendComponents.h"
+#include "vtkImageThreshold.h"
+#include "vtkImageMathematics.h"
+#include "vtkmpjFastMarchingMethod.h"
+#include "vtkmpjFastMarchingExtension.h"
+#include "vtkmpjExtractLevelSet.h"
+#include "vtkmpjFrameExtract.h"
+#include "vtkFloatArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjLevelSetSignedDistance : public vtkpxSimpleImageToImageFilter
+{
+ public: 
+  static vtkmpjLevelSetSignedDistance *New();
+  vtkTypeMacro(vtkmpjLevelSetSignedDistance,vtkpxSimpleImageToImageFilter);
+  
+  // Set/Get maximum propagation time
+  vtkGetMacro(LevelSetValue,float);
+  vtkSetMacro(LevelSetValue,float);  
+  
+  // Description:
+  // Set/Get maximum propagation time
+  vtkGetMacro(PropagationTime,float);
+  vtkSetMacro(PropagationTime,float);
+
+  // Description:
+  // Set/Get Extension velocities
+  vtkGetObjectMacro(ExtensionImage, vtkImageData);
+  vtkSetObjectMacro(ExtensionImage, vtkImageData);
+
+ protected:
+  float LevelSetValue;
+  float PropagationTime;
+  vtkImageData *ExtensionImage;
+
+  vtkmpjLevelSetSignedDistance();
+  virtual ~vtkmpjLevelSetSignedDistance();
+    
+  void ExecuteInformation();
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+
+ private:
+  //BTX
+  float pog;
+  int count, tenth;  
+  //ETX
+  
+  vtkmpjLevelSetSignedDistance(const vtkmpjLevelSetSignedDistance&);// Not implemented
+  void operator=(const vtkmpjLevelSetSignedDistance&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetTest.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetTest.cpp
new file mode 100644
index 0000000..5869d89
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetTest.cpp
@@ -0,0 +1,141 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjLevelSetTest.h"
+
+//------------------------------------------------------------------------------
+vtkmpjLevelSetTest* vtkmpjLevelSetTest::New()
+{
+  // First try to create the object from the vtkObjectFactory
+  vtkObject* ret = vtkObjectFactory::CreateInstance("vtkmpjLevelSetTest");
+  if (ret) {
+    return (vtkmpjLevelSetTest*)ret;
+  }
+  // If the factory was unable to create the object, then create it here.
+  return new vtkmpjLevelSetTest;
+}
+
+// Construct object with no children.
+vtkmpjLevelSetTest::vtkmpjLevelSetTest()
+{
+  this->SpeedImage = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjLevelSetTest::~vtkmpjLevelSetTest()
+{
+  if (this->SpeedImage != NULL)
+    this->SpeedImage->Delete();
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjLevelSetTest::ExecuteInformation()
+{  
+  this->vtkpxSimpleImageToImageFilter::ExecuteInformation();
+
+  if (this->SpeedImage == NULL) {
+    vtkErrorMacro(<<"no speed image!");
+    return;
+  }
+}
+
+// ----------------------------------------------------------------------------
+double vtkmpjLevelSetTest::ComputeAdvection(vtkImageData *image, double v[3], 
+					    int index, int coord[3])
+{
+  vtkDataArray *phi = image->GetPointData()->GetScalars();  
+  int dim[3]; image->GetDimensions(dim);
+  int dim0Tdim1 = dim[0]*dim[1];
+  int factor[3] = {1, dim[0], dim0Tdim1};
+  
+  double advection = 0.0;    
+  double value = image->GetPointData()->GetScalars()->GetComponent(index, 0);
+  double diff_val = 0.0;
+  
+  for(int j=0; j<3; j++) {
+    
+    // compute backward differences
+    if (coord[j] > 0) {      
+
+      diff_val = value - phi->GetComponent(index-factor[j], 0);
+      
+      if (v[j] >= 0) {	
+	advection += v[j] * diff_val;
+      }
+    }
+
+    // compute forward differences
+    if (coord[j] < dim[j]-1) {
+      
+      diff_val = phi->GetComponent(index+factor[j], 0) - value;
+      
+      if (v[j] < 0) {
+	advection += v[j] * diff_val;
+      }
+    }
+  }
+
+  return advection;
+}
+
+
+// ----------------------------------------------------------------------------
+double vtkmpjLevelSetTest::ComputeSpeed(vtkImageData *image, int index, int coord[3])
+{
+  vtkDataArray *speed = this->SpeedImage->GetPointData()->GetScalars();
+  
+  double v[3] ={1.0, 0.0, 0.0};
+  
+  //v[0] = speed->GetComponent(index, 0);
+  //v[1] = speed->GetComponent(index, 1);
+  //v[2] = speed->GetComponent(index, 2);  
+  //(void)vtkMath::Normalize(v);  
+  //double fa = speed->GetComponent(index, 0);  
+  //printf("fa=%f\n",fa);  
+  //  double entropy = ComputeEntropyGradientMagnitude(image, advection, index, coord);
+  
+  float normal[3];
+  
+  this->ComputeNormal(image, index, coord, normal);
+  double dot = v[0]*normal[0] + v[1]*normal[1] + v[2]*normal[2];
+  
+  //double advection = ComputeAdvection(image, dot, index, coord);   
+  
+  //double entropy = ComputeEntropyGradientMagnitude(image, fabs(dot), index, coord);
+
+  //  printf("entropy=%f\n",entropy); 
+
+  return dot;
+
+}
+
+
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetTest.h b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetTest.h
new file mode 100644
index 0000000..9ed222a
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjLevelSetTest.h
@@ -0,0 +1,83 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/* 
+  -- vtkmpjLevelSetTest.h --
+   
+  Marcel Jackowski, June 2003.
+*/
+
+#ifndef __vtkmpjLevelSetTest_h
+#define __vtkmpjLevelSetTest_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkmpjLevelSetMethod.h"
+#include "vtkImageAccumulate.h"
+#include "vtkFloatArray.h"
+#include "vtkIntArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+class vtkmpjLevelSetTest : public vtkmpjLevelSetMethod
+{
+ public: 
+  static vtkmpjLevelSetTest *New();
+  vtkTypeMacro(vtkmpjLevelSetTest,vtkpxSimpleImageToImageFilter);
+
+  // Description: sets/gets front advection speed
+  vtkSetObjectMacro(SpeedImage, vtkImageData);
+  vtkGetObjectMacro(SpeedImage, vtkImageData);
+
+ protected:
+  vtkImageData *SpeedImage;
+  
+  vtkmpjLevelSetTest();
+  virtual ~vtkmpjLevelSetTest();
+    
+  void ExecuteInformation();
+  
+  virtual double ComputeSpeed(vtkImageData *image, int index, int coord[3]);
+  virtual double ComputeAdvection(vtkImageData *image, double v[3], int index, int coord[3]);
+  //virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+
+ private:
+  //BTX
+  float pog;
+  int count, tenth;
+  //ETX
+  
+  vtkmpjLevelSetTest(const vtkmpjLevelSetTest&);// Not implemented
+  void operator=(const vtkmpjLevelSetTest&); // Not Implemented
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjReinitializeLevelSetImageFilter.cpp b/bioimagesuite30_src/mpjLevelset/vtkmpjReinitializeLevelSetImageFilter.cpp
new file mode 100644
index 0000000..f8951e8
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjReinitializeLevelSetImageFilter.cpp
@@ -0,0 +1,295 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "vtkmpjReinitializeLevelSetImageFilter.h"
+
+vtkStandardNewMacro(vtkmpjReinitializeLevelSetImageFilter);
+
+// Construct object 
+vtkmpjReinitializeLevelSetImageFilter::vtkmpjReinitializeLevelSetImageFilter()
+{
+  this->LevelSetValue = 0.0;
+
+  this->Locator = vtkmpjLevelSetNeighborhoodExtractor::New();
+  this->Marcher = vtkmpjFastMarchingImageFilter::New();
+  
+  this->NarrowBanding = 0;
+  this->InputNarrowBandwidth = 12.0;
+  this->OutputNarrowBandwidth = 12.0;
+  
+  this->InputNarrowBand = NULL;
+  this->OutputNarrowBand = NULL;
+}
+
+// ----------------------------------------------------------------------------
+vtkmpjReinitializeLevelSetImageFilter::~vtkmpjReinitializeLevelSetImageFilter()
+{  
+  if (this->Locator != NULL)
+    this->Locator->Delete();
+  
+  if (this->Marcher != NULL)
+    this->Marcher->Delete();
+  
+  if (this->InputNarrowBand != NULL)
+    this->InputNarrowBand->Delete();  
+  
+  if (this->OutputNarrowBand != NULL)
+    this->OutputNarrowBand->Delete();      
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjReinitializeLevelSetImageFilter::PrintSelf(ostream& os, vtkIndent indent)
+{
+  this->Superclass::PrintSelf(os,indent);  
+  os << indent << "Level set value: " << this->LevelSetValue << "\n";
+  os << indent << "Narrowbanding: " << this->NarrowBanding << "\n";
+  os << indent << "Input narrow bandwidth: " << this->InputNarrowBandwidth;
+  os << "\n";
+  os << indent << "Output narrow bandwidth: " << this->OutputNarrowBandwidth;
+  os << "\n";
+  os << indent << "Input narrow band: " << this->InputNarrowBand;
+  os << "\n";
+  os << indent << "Output narrow band: " << this->OutputNarrowBand;
+  os << "\n";
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjReinitializeLevelSetImageFilter::GenerateDataFull(vtkImageData *input, vtkImageData *output)
+{  
+  int dim[3]; input->GetDimensions(dim);
+
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  unsigned long numtuples = out->GetNumberOfTuples();
+
+  this->UpdateProgress( 0.0 );
+
+  // locate the level set
+  this->Locator->SetInputLevelSet( input );
+  this->Locator->SetLevelSetValue( this->LevelSetValue );
+  this->Locator->Locate();
+  
+  this->UpdateProgress( 0.33 );
+  
+  // march outward
+  this->Marcher->SetOutputExtent( 0, dim[0]-1, 0, dim[1]-1, 0, dim[2]-1 );
+  this->Marcher->SetTrialPoints( this->Locator->GetOutsidePoints() );
+  this->Marcher->Update();
+
+  double value;
+  vtkDataArray *tmpLevelSet=this->Marcher->GetOutput()->GetPointData()->GetScalars();
+  
+  for (unsigned long index = 0; index < numtuples; index++) {    
+    value = (double) in->GetComponent(index, 0);    
+    if ( value - this->LevelSetValue > 0 ) {      
+      out->SetComponent(index, 0, tmpLevelSet->GetComponent(index, 0));      
+    }    
+  }
+  
+  this->UpdateProgress( 0.66 );
+  
+  // march inward
+  this->Marcher->SetTrialPoints( this->Locator->GetInsidePoints() );
+  this->Marcher->Update();
+
+  tmpLevelSet=this->Marcher->GetOutput()->GetPointData()->GetScalars();
+
+  for (unsigned long index = 0; index < numtuples; index++) {    
+    value = (double) in->GetComponent(index, 0);    
+    if ( value - this->LevelSetValue <= 0 ) {
+      value = (double) tmpLevelSet->GetComponent(index, 0);
+      out->SetComponent(index, 0, -1.0 * value);
+    }    
+  }
+
+  this->UpdateProgress( 1.0 );
+}
+
+//----------------------------------------------------------------------------
+void vtkmpjReinitializeLevelSetImageFilter::GenerateDataNarrowBand(vtkImageData *input, vtkImageData *output)
+{
+  int dim[3]; input->GetDimensions(dim);
+  int dim0xdim1 = dim[0]*dim[1];
+  int coord[3];
+
+  vtkDataArray *in=input->GetPointData()->GetScalars();
+  vtkDataArray *out=output->GetPointData()->GetScalars();
+
+  unsigned long numtuples = out->GetNumberOfTuples();
+
+  double posInfinity = VTK_DOUBLE_MAX;
+  double negInfinity = VTK_DOUBLE_MIN;
+
+  // set all internal pixels to minus infinity and 
+  // all external pixels to positive infinity
+  double value;
+
+  for (unsigned long index = 0; index < numtuples; index++) {    
+    value = in->GetComponent(index, 0);
+    if ( value - this->LevelSetValue <= 0 ) {
+      out->SetComponent(index, 0, negInfinity);
+    } else {
+      out->SetComponent(index, 0, posInfinity);
+    }
+  }
+  
+  // create a new output narrowband container
+  if (this->OutputNarrowBand != NULL) {
+    this->OutputNarrowBand->Delete();
+  }
+  this->OutputNarrowBand = vtkDoubleArray::New();
+  this->OutputNarrowBand->SetNumberOfComponents(4);
+  this->OutputNarrowBand->Allocate(100);
+  
+  this->UpdateProgress( 0.0 );
+  
+  // locate the level set
+  this->Locator->SetInputLevelSet( input );
+  this->Locator->SetLevelSetValue( this->LevelSetValue );
+
+  if( this->NarrowBanding && this->InputNarrowBand )
+    {
+      this->Locator->NarrowBandingOn();
+      this->Locator->SetNarrowBandwidth( this->InputNarrowBandwidth );
+      this->Locator->SetInputNarrowBand( this->InputNarrowBand );
+    }
+  else
+    { 
+      this->Locator->NarrowBandingOff();
+    }
+  
+  this->Locator->Locate();
+  
+  this->UpdateProgress( 0.33 );
+
+  // march outward
+  double stoppingValue = ( this->OutputNarrowBandwidth / 2.0 ) + 2.0;
+  this->Marcher->SetStoppingValue( stoppingValue );
+  this->Marcher->CollectPointsOn();
+  this->Marcher->SetTrialPoints( this->Locator->GetOutsidePoints() );
+  this->Marcher->Update();
+  
+  vtkDataArray *tmpLevelSet=this->Marcher->GetOutput()->GetPointData()->GetScalars();
+  vtkDoubleArray *procPoints = this->Marcher->GetProcessedPoints();
+  
+  double inPixel;
+  unsigned long pointIndex;
+
+  unsigned long numpoints = procPoints->GetNumberOfTuples();
+
+  for (unsigned long index = 0; index < numpoints; index++) {    
+    
+    coord[0] = (int)procPoints->GetComponent(index, 0);
+    coord[1] = (int)procPoints->GetComponent(index, 1);
+    coord[2] = (int)procPoints->GetComponent(index, 2);    
+    pointIndex = dim0xdim1*coord[2] + dim[0]*coord[1] + coord[0];
+    
+    inPixel = value = in->GetComponent(pointIndex, 0);
+    
+    if ( value - this->LevelSetValue > 0 ) 
+      {
+	inPixel = tmpLevelSet->GetComponent(pointIndex, 0);	
+	out->SetComponent(pointIndex, 0, inPixel);	
+	this->OutputNarrowBand->InsertNextTuple4(coord[0],
+						 coord[1],
+						 coord[2],
+						 procPoints->GetComponent(index, 3));
+      }
+    
+  } // end for loop
+  
+  this->UpdateProgress( 0.66 );
+ 
+  // march inward
+  this->Marcher->SetTrialPoints( this->Locator->GetInsidePoints() );
+  this->Marcher->Update();
+
+  tmpLevelSet=this->Marcher->GetOutput()->GetPointData()->GetScalars();
+  procPoints = this->Marcher->GetProcessedPoints();
+  numpoints = procPoints->GetNumberOfTuples();
+
+  for (unsigned long index = 0; index < numpoints; index++) {    
+    
+    coord[0] = (int)procPoints->GetComponent(index, 0);
+    coord[1] = (int)procPoints->GetComponent(index, 1);
+    coord[2] = (int)procPoints->GetComponent(index, 2);    
+    pointIndex = dim0xdim1*coord[2] + dim[0]*coord[1] + coord[0];
+    
+    inPixel = value = in->GetComponent(pointIndex, 0);
+    
+    if( value - this->LevelSetValue <= 0 )
+      {
+	inPixel = value = tmpLevelSet->GetComponent(pointIndex, 0);
+	inPixel = -1.0 * value;
+	out->SetComponent(pointIndex, 0, inPixel);
+	this->OutputNarrowBand->InsertNextTuple4(coord[0],
+						 coord[1],
+						 coord[2],
+						 -1.0 * procPoints->GetComponent(index, 3));
+      }
+    
+  } // end for loop
+
+  this->UpdateProgress( 1.0 );
+  
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjReinitializeLevelSetImageFilter::ExecuteInformation()
+{
+  vtkImageData *output = this->GetOutput();  
+  
+  vtkpxSimpleImageToImageFilter::ExecuteInformation();
+  
+  output->SetScalarType(VTK_FLOAT);
+}
+
+// ----------------------------------------------------------------------------
+void vtkmpjReinitializeLevelSetImageFilter::SimpleExecute(vtkImageData *input, vtkImageData *output)
+{
+  if( this->GetInput() == NULL ) 
+    { 
+      vtkErrorMacro( << "Input level set is NULL" );
+      return;
+    }
+  
+  if( this->NarrowBanding )
+    {
+      this->GenerateDataNarrowBand(input, output);
+    }
+  else
+    {
+      this->GenerateDataFull(input, output);
+    }
+}
+
+
diff --git a/bioimagesuite30_src/mpjLevelset/vtkmpjReinitializeLevelSetImageFilter.h b/bioimagesuite30_src/mpjLevelset/vtkmpjReinitializeLevelSetImageFilter.h
new file mode 100644
index 0000000..cfd03f2
--- /dev/null
+++ b/bioimagesuite30_src/mpjLevelset/vtkmpjReinitializeLevelSetImageFilter.h
@@ -0,0 +1,166 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+/*=========================================================================
+
+  Program:   Insight Segmentation & Registration Toolkit
+  Module:    $RCSfile: itkReinitializeLevelSetImageFilter.h,v $
+  Language:  C++
+  Date:      $Date: 2003/09/10 14:28:38 $
+  Version:   $Revision: 1.16 $
+
+  Copyright (c) Insight Software Consortium. All rights reserved.
+  See ITKCopyright.txt or http://www.itk.org/HTML/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 notices for more information.
+
+=========================================================================*/
+#ifndef _vtkmpjReinitializeLevelSetImageFilter_h
+#define _vtkmpjReinitializeLevelSetImageFilter_h
+
+#include "vtkObjectFactory.h"
+#include "vtkpxSimpleImageToImageFilter.h"
+#include "vtkImageSource.h"
+#include "vtkImageData.h"
+#include "vtkPointData.h"
+#include "vtkDoubleArray.h"
+#include "vtkMath.h"
+#include "math.h"
+
+#include "vtkmpjFastMarchingImageFilter.h"
+#include "vtkmpjLevelSetNeighborhoodExtractor.h"
+
+/** \class ReinitializeLevelSetImageFilter
+ *  \brief Reinitialize the level set to the signed distance function.
+ *
+ * ReinitializeLevelSetImageFilter reinitializes the input level set to
+ * the approximated signed distance function from a particular 
+ * level set. The output is a level set of the same type as the input.
+ *
+ * For some level set algorithms, it is useful to periodically
+ * reinitialize the level set function to prevent numerical accuracy
+ * problems in computing derivatives and curvature values where level
+ * sets are densely bunched together.
+ *
+ * This class supports narrowbanding. If the input narrowband is provided,
+ * the algorithm will only locate the level set within the input narrowband.
+ * For the output, the reinitialize level set is only valid for a distance
+ * of OutputNarrowBandwidth / 2 of either side of the level set of interest.
+ *
+ * Implementation of this class is based on Chapter 11 of
+ * "Level Set Methods and Fast Marching Methods", J.A. Sethian,
+ * Cambridge Press, Second edition, 1999.
+ *
+ * \ingroup LevelSetSegmentation 
+ *
+ */
+class vtkmpjReinitializeLevelSetImageFilter: public vtkpxSimpleImageToImageFilter
+{
+ public:
+  static vtkmpjReinitializeLevelSetImageFilter *New();
+  vtkTypeMacro(vtkmpjReinitializeLevelSetImageFilter,vtkpxSimpleImageToImageFilter);
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  // Description:
+  // Set/Get Set the value of the level set to be located. Default is 0.
+  vtkSetMacro(LevelSetValue, double);
+  vtkGetMacro(LevelSetValue, double);
+  
+  // Description:
+  // Set/Get the narrowbanding flag. By default, narrowbanding is switched off
+  vtkGetMacro(NarrowBanding, int);
+  vtkSetMacro(NarrowBanding, int);
+  vtkBooleanMacro(NarrowBanding, int);
+  
+  // Description:
+  // Set/Get the input narrow bandwidth. Default is 12.
+  vtkSetMacro(InputNarrowBandwidth, double);
+  vtkGetMacro(InputNarrowBandwidth, double);
+  
+  // Description:
+  // Set/Get the output narrow bandwidth. Default is 12.
+  vtkSetMacro(OutputNarrowBandwidth, double);
+  vtkGetMacro(OutputNarrowBandwidth, double);
+  
+  /** Set the bandwidth for both the input and output narrowband,
+   * By default, both the input and output are set to 12. */
+  void SetNarrowBandwidth( double value )
+    {
+      this->InputNarrowBandwidth=value;
+      this->OutputNarrowBandwidth=value;
+    }
+  
+  // Description:
+  // Set the input narrowband.
+  vtkSetObjectMacro(InputNarrowBand, vtkDataArray);
+  
+  // Description:
+  // Get the input narrowband.
+  vtkGetObjectMacro(OutputNarrowBand, vtkDataArray);
+  
+protected:
+  vtkmpjReinitializeLevelSetImageFilter();
+  virtual ~vtkmpjReinitializeLevelSetImageFilter();
+
+  double LevelSetValue;
+
+  vtkmpjLevelSetNeighborhoodExtractor *Locator;
+  vtkmpjFastMarchingImageFilter *Marcher;
+  
+  vtkDoubleArray *InsidePoints;
+  vtkDoubleArray *OutsidePoints;
+
+  int NarrowBanding;
+  double InputNarrowBandwidth;
+  double OutputNarrowBandwidth;
+  vtkDataArray *InputNarrowBand;
+  vtkDataArray *OutputNarrowBand;
+  
+  void SetOutputNarrowBand( vtkDataArray *ptr )
+    { OutputNarrowBand = ptr; }
+  
+  void ExecuteInformation();  
+  virtual void SimpleExecute(vtkImageData *input, vtkImageData *output);
+  
+private:  
+  vtkmpjReinitializeLevelSetImageFilter(const vtkmpjReinitializeLevelSetImageFilter&); //purposely not implemented
+  void operator=(const vtkmpjReinitializeLevelSetImageFilter&); //purposely not implemented
+  
+  //void SortNodesUsed();
+  void GenerateDataFull(vtkImageData *input, vtkImageData *output);
+  void GenerateDataNarrowBand(vtkImageData *input, vtkImageData *output);
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/CMakeLists.txt b/bioimagesuite30_src/numerics/CMakeLists.txt
new file mode 100644
index 0000000..aa7139b
--- /dev/null
+++ b/bioimagesuite30_src/numerics/CMakeLists.txt
@@ -0,0 +1,119 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local imaging classes.
+#
+
+SET(KITBASE numerics)
+SET(KIT ${KITBASE})
+
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/${KITBASE})
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/include)
+INCLUDE_DIRECTORIES(${ITK_INCLUDE_DIRS})
+
+#MESSAGE("DIRS =  ${ITK_INCLUDE_DIRS}")
+
+SET (KITSRCS
+  # Fitpack
+  #
+  fitpack.c
+  #
+  # Legacy Stuff
+  #
+  linsystems.cpp
+  pxabaqusstructures.cpp
+  pxtriangulatedstack.cpp
+  nrutil.cpp
+  pxchamferdistancemap.cpp
+  pxutil.cpp
+  peng_cheng_util.cpp
+  pxcontour.cpp
+  pxgeometrystruct.cpp
+  px3dimage.cpp
+  pxcontourstack.cpp
+  pximage.cpp
+  pxabaqussolid.cpp
+  pxshapetrackingclass.cpp
+  pxmarkerclass.cpp
+  pxcrystalabaqus.cpp
+  pxfloatimage.cpp
+  pxfloatmatrix.cpp
+  pxfpbspline.cpp
+  pxfpbsplinestack.cpp
+  pxregion.cpp
+  # 
+  # libf2c fix
+  #
+  f2cfix.c
+  )
+
+
+SET (KITEXTRAFILES
+numerics/tnt/jama_cholesky.h
+numerics/tnt/tnt_array1d.h
+numerics/tnt/tnt_array3d_utils.h
+numerics/tnt/tnt_fortran_array2d_utils.h
+numerics/tnt/tnt_sparse_matrix_csr.h
+numerics/tnt/jama_eig.h
+numerics/tnt/tnt_array1d_utils.h
+numerics/tnt/tnt_cmat.h
+numerics/tnt/tnt_fortran_array3d.h
+numerics/tnt/tnt_stopwatch.h
+numerics/tnt/jama_lu.h
+numerics/tnt/tnt_array2d.h
+numerics/tnt/tnt_fortran_array1d.h
+numerics/tnt/tnt_fortran_array3d_utils.h
+numerics/tnt/tnt_subscript.h
+numerics/tnt/jama_qr.h
+numerics/tnt/tnt_array2d_utils.h
+numerics/tnt/tnt_fortran_array1d_utils.h
+numerics/tnt/tnt.h
+numerics/tnt/tnt_vec.h
+numerics/tnt/jama_svd.h
+numerics/tnt/tnt_array3d.h
+numerics/tnt/tnt_fortran_array2d.h
+numerics/tnt/tnt_math_utils.h
+numerics/tnt/tnt_version.h
+numerics/nr.h
+)
+
+SET (KITTCLSRCS )
+
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+bis_static(${KIT})
+bis_sourcelist("numerics" ${KIT} ${FILELIST})
+
diff --git a/bioimagesuite30_src/numerics/f2cfix.c b/bioimagesuite30_src/numerics/f2cfix.c
new file mode 100644
index 0000000..cf05e3b
--- /dev/null
+++ b/bioimagesuite30_src/numerics/f2cfix.c
@@ -0,0 +1,41 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/* because libf2c.so has an undefined symbol MAIN__
+ * Matt McCormick (thewtex) <matt at mmmccormick.com>
+ * created 2008 May 30
+ */
+
+#include "f2cfix.h"
+
+int MAIN__()
+{
+  return 0;
+}
+
+
+
diff --git a/bioimagesuite30_src/numerics/f2cfix.h b/bioimagesuite30_src/numerics/f2cfix.h
new file mode 100644
index 0000000..0f42ec0
--- /dev/null
+++ b/bioimagesuite30_src/numerics/f2cfix.h
@@ -0,0 +1,43 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/* because libf2c.so has an undefined symbol MAIN__
+ * Matt McCormick (thewtex) <matt at mmmccormick.com>
+ * created 2008 May 30
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int MAIN__();
+
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/bioimagesuite30_src/numerics/fitpack.c b/bioimagesuite30_src/numerics/fitpack.c
new file mode 100644
index 0000000..e20050e
--- /dev/null
+++ b/bioimagesuite30_src/numerics/fitpack.c
@@ -0,0 +1,27140 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/* fitpack.f -- translated by f2c (version 20000704).
+   You must link the resulting object file with the libraries:
+	-lf2c -lm   (in that order)
+*/
+
+#include "bio_f2c.h"
+
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define max(a,b) ((a) >= (b) ? (a) : (b))
+
+
+/* Table of constant values */
+
+static integer c__3 = 3;
+static integer c__1 = 1;
+static integer c__8 = 8;
+static integer c__2 = 2;
+static integer c__0 = 0;
+static integer c__5 = 5;
+static integer c__4 = 4;
+
+/* Subroutine */ int bispev_(tx, nx, ty, ny, c__, kx, ky, x, mx, y, my, z__, 
+	wrk, lwrk, iwrk, kwrk, ier)
+real *tx;
+integer *nx;
+real *ty;
+integer *ny;
+real *c__;
+integer *kx, *ky;
+real *x;
+integer *mx;
+real *y;
+integer *my;
+real *z__, *wrk;
+integer *lwrk, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__, lwest, iw;
+    extern /* Subroutine */ int fpbisp_();
+
+/*  subroutine bispev evaluates on a grid (x(i),y(j)),i=1,...,mx; j=1,... */
+/*  ,my a bivariate spline s(x,y) of degrees kx and ky, given in the */
+/*  b-spline representation. */
+
+/*  calling sequence: */
+/*     call bispev(tx,nx,ty,ny,c,kx,ky,x,mx,y,my,z,wrk,lwrk, */
+/*    * iwrk,kwrk,ier) */
+
+/*  input parameters: */
+/*   tx    : real array, length nx, which contains the position of the */
+/*           knots in the x-direction. */
+/*   nx    : integer, giving the total number of knots in the x-direction */
+/*   ty    : real array, length ny, which contains the position of the */
+/*           knots in the y-direction. */
+/*   ny    : integer, giving the total number of knots in the y-direction */
+/*   c     : real array, length (nx-kx-1)*(ny-ky-1), which contains the */
+/*           b-spline coefficients. */
+/*   kx,ky : integer values, giving the degrees of the spline. */
+/*   x     : real array of dimension (mx). */
+/*           before entry x(i) must be set to the x co-ordinate of the */
+/*           i-th grid point along the x-axis. */
+/*           tx(kx+1)<=x(i-1)<=x(i)<=tx(nx-kx), i=2,...,mx. */
+/*   mx    : on entry mx must specify the number of grid points along */
+/*           the x-axis. mx >=1. */
+/*   y     : real array of dimension (my). */
+/*           before entry y(j) must be set to the y co-ordinate of the */
+/*           j-th grid point along the y-axis. */
+/*           ty(ky+1)<=y(j-1)<=y(j)<=ty(ny-ky), j=2,...,my. */
+/*   my    : on entry my must specify the number of grid points along */
+/*           the y-axis. my >=1. */
+/*   wrk   : real array of dimension lwrk. used as workspace. */
+/*   lwrk  : integer, specifying the dimension of wrk. */
+/*           lwrk >= mx*(kx+1)+my*(ky+1) */
+/*   iwrk  : integer array of dimension kwrk. used as workspace. */
+/*   kwrk  : integer, specifying the dimension of iwrk. kwrk >= mx+my. */
+
+/*  output parameters: */
+/*   z     : real array of dimension (mx*my). */
+/*           on succesful exit z(my*(i-1)+j) contains the value of s(x,y) */
+/*           at the point (x(i),y(j)),i=1,...,mx;j=1,...,my. */
+/*   ier   : integer error flag */
+/*    ier=0 : normal return */
+/*    ier=10: invalid input data (see restrictions) */
+
+/*  restrictions: */
+/*   mx >=1, my >=1, lwrk>=mx*(kx+1)+my*(ky+1), kwrk>=mx+my */
+/*   tx(kx+1) <= x(i-1) <= x(i) <= tx(nx-kx), i=2,...,mx */
+/*   ty(ky+1) <= y(j-1) <= y(j) <= ty(ny-ky), j=2,...,my */
+
+/*  other subroutines required: */
+/*    fpbisp,fpbspl */
+
+/*  references : */
+/*    de boor c : on calculating with b-splines, j. approximation theory */
+/*                6 (1972) 50-62. */
+/*    cox m.g.  : the numerical evaluation of b-splines, j. inst. maths */
+/*                applics 10 (1972) 134-149. */
+/*    dierckx p. : curve and surface fitting with splines, monographs on */
+/*                 numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1987 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid control is immediately repassed to the calling program. */
+    /* Parameter adjustments */
+    --tx;
+    --ty;
+    --c__;
+    --x;
+    --z__;
+    --y;
+    --wrk;
+    --iwrk;
+
+    /* Function Body */
+    *ier = 10;
+    lwest = (*kx + 1) * *mx + (*ky + 1) * *my;
+    if (*lwrk < lwest) {
+	goto L100;
+    }
+    if (*kwrk < *mx + *my) {
+	goto L100;
+    }
+    if ((i__1 = *mx - 1) < 0) {
+	goto L100;
+    } else if (i__1 == 0) {
+	goto L30;
+    } else {
+	goto L10;
+    }
+L10:
+    i__1 = *mx;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (x[i__] < x[i__ - 1]) {
+	    goto L100;
+	}
+/* L20: */
+    }
+L30:
+    if ((i__1 = *my - 1) < 0) {
+	goto L100;
+    } else if (i__1 == 0) {
+	goto L60;
+    } else {
+	goto L40;
+    }
+L40:
+    i__1 = *my;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (y[i__] < y[i__ - 1]) {
+	    goto L100;
+	}
+/* L50: */
+    }
+L60:
+    *ier = 0;
+    iw = *mx * (*kx + 1) + 1;
+    fpbisp_(&tx[1], nx, &ty[1], ny, &c__[1], kx, ky, &x[1], mx, &y[1], my, &
+	    z__[1], &wrk[1], &wrk[iw], &iwrk[1], &iwrk[*mx + 1]);
+L100:
+    return 0;
+} /* bispev_ */
+
+/* Subroutine */ int clocur_(iopt, ipar, idim, m, u, mx, x, w, k, s, nest, n, 
+	t, nc, c__, fp, wrk, lwrk, iwrk, ier)
+integer *iopt, *ipar, *idim, *m;
+real *u;
+integer *mx;
+real *x, *w;
+integer *k;
+real *s;
+integer *nest, *n;
+real *t;
+integer *nc;
+real *c__, *fp, *wrk;
+integer *lwrk, *iwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+    real r__1;
+
+    /* Builtin functions */
+    double sqrt();
+
+    /* Local variables */
+    static integer nmin;
+    static real dist;
+    static integer i__, j, maxit, i1, i2, j1, j2, k1, k2, lwest, m1, ib, iq, 
+	    iz;
+    extern /* Subroutine */ int fpchep_(), fpclos_();
+    static integer ia1, ia2, ig1, ig2, ncc, ifp;
+    static real per, tol;
+
+/*  given the ordered set of m points x(i) in the idim-dimensional space */
+/*  with x(1)=x(m), and given also a corresponding set of strictly in- */
+/*  creasing values u(i) and the set of positive numbers w(i),i=1,2,...,m */
+/*  subroutine clocur determines a smooth approximating closed spline */
+/*  curve s(u), i.e. */
+/*      x1 = s1(u) */
+/*      x2 = s2(u)       u(1) <= u <= u(m) */
+/*      ......... */
+/*      xidim = sidim(u) */
+/*  with sj(u),j=1,2,...,idim periodic spline functions of degree k with */
+/*  common knots t(j),j=1,2,...,n. */
+/*  if ipar=1 the values u(i),i=1,2,...,m must be supplied by the user. */
+/*  if ipar=0 these values are chosen automatically by clocur as */
+/*      v(1) = 0 */
+/*      v(i) = v(i-1) + dist(x(i),x(i-1)) ,i=2,3,...,m */
+/*      u(i) = v(i)/v(m) ,i=1,2,...,m */
+/*  if iopt=-1 clocur calculates the weighted least-squares closed spline */
+/*  curve according to a given set of knots. */
+/*  if iopt>=0 the number of knots of the splines sj(u) and the position */
+/*  t(j),j=1,2,...,n is chosen automatically by the routine. the smooth- */
+/*  ness of s(u) is then achieved by minimalizing the discontinuity */
+/*  jumps of the k-th derivative of s(u) at the knots t(j),j=k+2,k+3,..., */
+/*  n-k-1. the amount of smoothness is determined by the condition that */
+/*  f(p)=sum((w(i)*dist(x(i),s(u(i))))**2) be <= s, with s a given non- */
+/*  negative constant, called the smoothing factor. */
+/*  the fit s(u) is given in the b-spline representation and can be */
+/*  evaluated by means of subroutine curev. */
+
+/*  calling sequence: */
+/*     call clocur(iopt,ipar,idim,m,u,mx,x,w,k,s,nest,n,t,nc,c, */
+/*    * fp,wrk,lwrk,iwrk,ier) */
+
+/*  parameters: */
+/*   iopt  : integer flag. on entry iopt must specify whether a weighted */
+/*           least-squares closed spline curve (iopt=-1) or a smoothing */
+/*           closed spline curve (iopt=0 or 1) must be determined. if */
+/*           iopt=0 the routine will start with an initial set of knots */
+/*           t(i)=u(1)+(u(m)-u(1))*(i-k-1),i=1,2,...,2*k+2. if iopt=1 the */
+/*           routine will continue with the knots found at the last call. */
+/*           attention: a call with iopt=1 must always be immediately */
+/*           preceded by another call with iopt=1 or iopt=0. */
+/*           unchanged on exit. */
+/*   ipar  : integer flag. on entry ipar must specify whether (ipar=1) */
+/*           the user will supply the parameter values u(i),or whether */
+/*           (ipar=0) these values are to be calculated by clocur. */
+/*           unchanged on exit. */
+/*   idim  : integer. on entry idim must specify the dimension of the */
+/*           curve. 0 < idim < 11. */
+/*           unchanged on exit. */
+/*   m     : integer. on entry m must specify the number of data points. */
+/*           m > 1. unchanged on exit. */
+/*   u     : real array of dimension at least (m). in case ipar=1,before */
+/*           entry, u(i) must be set to the i-th value of the parameter */
+/*           variable u for i=1,2,...,m. these values must then be */
+/*           supplied in strictly ascending order and will be unchanged */
+/*           on exit. in case ipar=0, on exit,the array will contain the */
+/*           values u(i) as determined by clocur. */
+/*   mx    : integer. on entry mx must specify the actual dimension of */
+/*           the array x as declared in the calling (sub)program. mx must */
+/*           not be too small (see x). unchanged on exit. */
+/*   x     : real array of dimension at least idim*m. */
+/*           before entry, x(idim*(i-1)+j) must contain the j-th coord- */
+/*           inate of the i-th data point for i=1,2,...,m and j=1,2,..., */
+/*           idim. since first and last data point must coincide it */
+/*           means that x(j)=x(idim*(m-1)+j),j=1,2,...,idim. */
+/*           unchanged on exit. */
+/*   w     : real array of dimension at least (m). before entry, w(i) */
+/*           must be set to the i-th value in the set of weights. the */
+/*           w(i) must be strictly positive. w(m) is not used. */
+/*           unchanged on exit. see also further comments. */
+/*   k     : integer. on entry k must specify the degree of the splines. */
+/*           1<=k<=5. it is recommended to use cubic splines (k=3). */
+/*           the user is strongly dissuaded from choosing k even,together */
+/*           with a small s-value. unchanged on exit. */
+/*   s     : real.on entry (in case iopt>=0) s must specify the smoothing */
+/*           factor. s >=0. unchanged on exit. */
+/*           for advice on the choice of s see further comments. */
+/*   nest  : integer. on entry nest must contain an over-estimate of the */
+/*           total number of knots of the splines returned, to indicate */
+/*           the storage space available to the routine. nest >=2*k+2. */
+/*           in most practical situation nest=m/2 will be sufficient. */
+/*           always large enough is nest=m+2*k, the number of knots */
+/*           needed for interpolation (s=0). unchanged on exit. */
+/*   n     : integer. */
+/*           unless ier = 10 (in case iopt >=0), n will contain the */
+/*           total number of knots of the smoothing spline curve returned */
+/*           if the computation mode iopt=1 is used this value of n */
+/*           should be left unchanged between subsequent calls. */
+/*           in case iopt=-1, the value of n must be specified on entry. */
+/*   t     : real array of dimension at least (nest). */
+/*           on succesful exit, this array will contain the knots of the */
+/*           spline curve,i.e. the position of the interior knots t(k+2), */
+/*           t(k+3),..,t(n-k-1) as well as the position of the additional */
+/*           t(1),t(2),..,t(k+1)=u(1) and u(m)=t(n-k),...,t(n) needed for */
+/*           the b-spline representation. */
+/*           if the computation mode iopt=1 is used, the values of t(1), */
+/*           t(2),...,t(n) should be left unchanged between subsequent */
+/*           calls. if the computation mode iopt=-1 is used, the values */
+/*           t(k+2),...,t(n-k-1) must be supplied by the user, before */
+/*           entry. see also the restrictions (ier=10). */
+/*   nc    : integer. on entry nc must specify the actual dimension of */
+/*           the array c as declared in the calling (sub)program. nc */
+/*           must not be too small (see c). unchanged on exit. */
+/*   c     : real array of dimension at least (nest*idim). */
+/*           on succesful exit, this array will contain the coefficients */
+/*           in the b-spline representation of the spline curve s(u),i.e. */
+/*           the b-spline coefficients of the spline sj(u) will be given */
+/*           in c(n*(j-1)+i),i=1,2,...,n-k-1 for j=1,2,...,idim. */
+/*   fp    : real. unless ier = 10, fp contains the weighted sum of */
+/*           squared residuals of the spline curve returned. */
+/*   wrk   : real array of dimension at least m*(k+1)+nest*(7+idim+5*k). */
+/*           used as working space. if the computation mode iopt=1 is */
+/*           used, the values wrk(1),...,wrk(n) should be left unchanged */
+/*           between subsequent calls. */
+/*   lwrk  : integer. on entry,lwrk must specify the actual dimension of */
+/*           the array wrk as declared in the calling (sub)program. lwrk */
+/*           must not be too small (see wrk). unchanged on exit. */
+/*   iwrk  : integer array of dimension at least (nest). */
+/*           used as working space. if the computation mode iopt=1 is */
+/*           used,the values iwrk(1),...,iwrk(n) should be left unchanged */
+/*           between subsequent calls. */
+/*   ier   : integer. unless the routine detects an error, ier contains a */
+/*           non-positive value on exit, i.e. */
+/*    ier=0  : normal return. the close curve returned has a residual */
+/*             sum of squares fp such that abs(fp-s)/s <= tol with tol a */
+/*             relative tolerance set to 0.001 by the program. */
+/*    ier=-1 : normal return. the curve returned is an interpolating */
+/*             spline curve (fp=0). */
+/*    ier=-2 : normal return. the curve returned is the weighted least- */
+/*             squares point,i.e. each spline sj(u) is a constant. in */
+/*             this extreme case fp gives the upper bound fp0 for the */
+/*             smoothing factor s. */
+/*    ier=1  : error. the required storage space exceeds the available */
+/*             storage space, as specified by the parameter nest. */
+/*             probably causes : nest too small. if nest is already */
+/*             large (say nest > m/2), it may also indicate that s is */
+/*             too small */
+/*             the approximation returned is the least-squares closed */
+/*             curve according to the knots t(1),t(2),...,t(n). (n=nest) */
+/*             the parameter fp gives the corresponding weighted sum of */
+/*             squared residuals (fp>s). */
+/*    ier=2  : error. a theoretically impossible result was found during */
+/*             the iteration proces for finding a smoothing curve with */
+/*             fp = s. probably causes : s too small. */
+/*             there is an approximation returned but the corresponding */
+/*             weighted sum of squared residuals does not satisfy the */
+/*             condition abs(fp-s)/s < tol. */
+/*    ier=3  : error. the maximal number of iterations maxit (set to 20 */
+/*             by the program) allowed for finding a smoothing curve */
+/*             with fp=s has been reached. probably causes : s too small */
+/*             there is an approximation returned but the corresponding */
+/*             weighted sum of squared residuals does not satisfy the */
+/*             condition abs(fp-s)/s < tol. */
+/*    ier=10 : error. on entry, the input data are controlled on validity */
+/*             the following restrictions must be satisfied. */
+/*             -1<=iopt<=1, 1<=k<=5, m>1, nest>2*k+2, w(i)>0,i=1,2,...,m */
+/*             0<=ipar<=1, 0<idim<=10, lwrk>=(k+1)*m+nest*(7+idim+5*k), */
+/*             nc>=nest*idim, x(j)=x(idim*(m-1)+j), j=1,2,...,idim */
+/*             if ipar=0: sum j=1,idim (x(i*idim+j)-x((i-1)*idim+j))**2>0 */
+/*                        i=1,2,...,m-1. */
+/*             if ipar=1: u(1)<u(2)<...<u(m) */
+/*             if iopt=-1: 2*k+2<=n<=min(nest,m+2*k) */
+/*                         u(1)<t(k+2)<t(k+3)<...<t(n-k-1)<u(m) */
+/*                            (u(1)=0 and u(m)=1 in case ipar=0) */
+/*                       the schoenberg-whitney conditions, i.e. there */
+/*                       must be a subset of data points uu(j) with */
+/*                       uu(j) = u(i) or u(i)+(u(m)-u(1)) such that */
+/*                         t(j) < uu(j) < t(j+k+1), j=k+1,...,n-k-1 */
+/*             if iopt>=0: s>=0 */
+/*                         if s=0 : nest >= m+2*k */
+/*             if one of these conditions is found to be violated,control */
+/*             is immediately repassed to the calling program. in that */
+/*             case there is no approximation returned. */
+
+/*  further comments: */
+/*   by means of the parameter s, the user can control the tradeoff */
+/*   between closeness of fit and smoothness of fit of the approximation. */
+/*   if s is too large, the curve will be too smooth and signal will be */
+/*   lost ; if s is too small the curve will pick up too much noise. in */
+/*   the extreme cases the program will return an interpolating curve if */
+/*   s=0 and the weighted least-squares point if s is very large. */
+/*   between these extremes, a properly chosen s will result in a good */
+/*   compromise between closeness of fit and smoothness of fit. */
+/*   to decide whether an approximation, corresponding to a certain s is */
+/*   satisfactory the user is highly recommended to inspect the fits */
+/*   graphically. */
+/*   recommended values for s depend on the weights w(i). if these are */
+/*   taken as 1/d(i) with d(i) an estimate of the standard deviation of */
+/*   x(i), a good s-value should be found in the range (m-sqrt(2*m),m+ */
+/*   sqrt(2*m)). if nothing is known about the statistical error in x(i) */
+/*   each w(i) can be set equal to one and s determined by trial and */
+/*   error, taking account of the comments above. the best is then to */
+/*   start with a very large value of s ( to determine the weighted */
+/*   least-squares point and the upper bound fp0 for s) and then to */
+/*   progressively decrease the value of s ( say by a factor 10 in the */
+/*   beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the */
+/*   approximating curve shows more detail) to obtain closer fits. */
+/*   to economize the search for a good s-value the program provides with */
+/*   different modes of computation. at the first call of the routine, or */
+/*   whenever he wants to restart with the initial set of knots the user */
+/*   must set iopt=0. */
+/*   if iopt=1 the program will continue with the set of knots found at */
+/*   the last call of the routine. this will save a lot of computation */
+/*   time if clocur is called repeatedly for different values of s. */
+/*   the number of knots of the spline returned and their location will */
+/*   depend on the value of s and on the complexity of the shape of the */
+/*   curve underlying the data. but, if the computation mode iopt=1 is */
+/*   used, the knots returned may also depend on the s-values at previous */
+/*   calls (if these were smaller). therefore, if after a number of */
+/*   trials with different s-values and iopt=1, the user can finally */
+/*   accept a fit as satisfactory, it may be worthwhile for him to call */
+/*   clocur once more with the selected value for s but now with iopt=0. */
+/*   indeed, clocur may then return an approximation of the same quality */
+/*   of fit but with fewer knots and therefore better if data reduction */
+/*   is also an important objective for the user. */
+
+/*   the form of the approximating curve can strongly be affected  by */
+/*   the choice of the parameter values u(i). if there is no physical */
+/*   reason for choosing a particular parameter u, often good results */
+/*   will be obtained with the choice of clocur(in case ipar=0), i.e. */
+/*        v(1)=0, v(i)=v(i-1)+q(i), i=2,...,m, u(i)=v(i)/v(m), i=1,..,m */
+/*   where */
+/*        q(i)= sqrt(sum j=1,idim (xj(i)-xj(i-1))**2 ) */
+/*   other possibilities for q(i) are */
+/*        q(i)= sum j=1,idim (xj(i)-xj(i-1))**2 */
+/*        q(i)= sum j=1,idim abs(xj(i)-xj(i-1)) */
+/*        q(i)= max j=1,idim abs(xj(i)-xj(i-1)) */
+/*        q(i)= 1 */
+
+
+/*  other subroutines required: */
+/*    fpbacp,fpbspl,fpchep,fpclos,fpdisc,fpgivs,fpknot,fprati,fprota */
+
+/*  references: */
+/*   dierckx p. : algorithms for smoothing data with periodic and */
+/*                parametric splines, computer graphics and image */
+/*                processing 20 (1982) 171-184. */
+/*   dierckx p. : algorithms for smoothing data with periodic and param- */
+/*                etric splines, report tw55, dept. computer science, */
+/*                k.u.leuven, 1981. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*    p.dierckx */
+/*    dept. computer science, k.u. leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : may 1979 */
+/*  latest update : march 1987 */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..function references.. */
+/*  we set up the parameters tol and maxit */
+    /* Parameter adjustments */
+    --w;
+    --u;
+    --x;
+    --iwrk;
+    --t;
+    --c__;
+    --wrk;
+
+    /* Function Body */
+    maxit = 20;
+    tol = (float).001;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*iopt < -1 || *iopt > 1) {
+	goto L90;
+    }
+    if (*ipar < 0 || *ipar > 1) {
+	goto L90;
+    }
+    if (*idim <= 0 || *idim > 10) {
+	goto L90;
+    }
+    if (*k <= 0 || *k > 5) {
+	goto L90;
+    }
+    k1 = *k + 1;
+    k2 = k1 + 1;
+    nmin = k1 << 1;
+    if (*m < 2 || *nest < nmin) {
+	goto L90;
+    }
+    ncc = *nest * *idim;
+    if (*mx < *m * *idim || *nc < ncc) {
+	goto L90;
+    }
+    lwest = *m * k1 + *nest * (*idim + 7 + *k * 5);
+    if (*lwrk < lwest) {
+	goto L90;
+    }
+    i1 = *idim;
+    i2 = *m * *idim;
+    i__1 = *idim;
+    for (j = 1; j <= i__1; ++j) {
+	if (x[i1] != x[i2]) {
+	    goto L90;
+	}
+	--i1;
+	--i2;
+/* L5: */
+    }
+    if (*ipar != 0 || *iopt > 0) {
+	goto L40;
+    }
+    i1 = 0;
+    i2 = *idim;
+    u[1] = (float)0.;
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	dist = (float)0.;
+	i__2 = *idim;
+	for (j1 = 1; j1 <= i__2; ++j1) {
+	    ++i1;
+	    ++i2;
+/* Computing 2nd power */
+	    r__1 = x[i2] - x[i1];
+	    dist += r__1 * r__1;
+/* L10: */
+	}
+	u[i__] = u[i__ - 1] + sqrt(dist);
+/* L20: */
+    }
+    if (u[*m] <= (float)0.) {
+	goto L90;
+    }
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	u[i__] /= u[*m];
+/* L30: */
+    }
+    u[*m] = (float)1.;
+L40:
+    if (w[1] <= (float)0.) {
+	goto L90;
+    }
+    m1 = *m - 1;
+    i__1 = m1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (u[i__] >= u[i__ + 1] || w[i__] <= (float)0.) {
+	    goto L90;
+	}
+/* L50: */
+    }
+    if (*iopt >= 0) {
+	goto L70;
+    }
+    if (*n <= nmin || *n > *nest) {
+	goto L90;
+    }
+    per = u[*m] - u[1];
+    j1 = k1;
+    t[j1] = u[1];
+    i1 = *n - *k;
+    t[i1] = u[*m];
+    j2 = j1;
+    i2 = i1;
+    i__1 = *k;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	++i1;
+	--i2;
+	++j1;
+	--j2;
+	t[j2] = t[i2] - per;
+	t[i1] = t[j1] + per;
+/* L60: */
+    }
+    fpchep_(&u[1], m, &t[1], n, k, ier);
+    if (*ier != 0) {
+	goto L90;
+    } else {
+	goto L80;
+    }
+L70:
+    if (*s < (float)0.) {
+	goto L90;
+    }
+    if (*s == (float)0. && *nest < *m + (*k << 1)) {
+	goto L90;
+    }
+    *ier = 0;
+/* we partition the working space and determine the spline approximation. */
+L80:
+    ifp = 1;
+    iz = ifp + *nest;
+    ia1 = iz + ncc;
+    ia2 = ia1 + *nest * k1;
+    ib = ia2 + *nest * *k;
+    ig1 = ib + *nest * k2;
+    ig2 = ig1 + *nest * k2;
+    iq = ig2 + *nest * k1;
+    fpclos_(iopt, idim, m, &u[1], mx, &x[1], &w[1], k, s, nest, &tol, &maxit, 
+	    &k1, &k2, n, &t[1], &ncc, &c__[1], fp, &wrk[ifp], &wrk[iz], &wrk[
+	    ia1], &wrk[ia2], &wrk[ib], &wrk[ig1], &wrk[ig2], &wrk[iq], &iwrk[
+	    1], ier);
+L90:
+    return 0;
+} /* clocur_ */
+
+/* Subroutine */ int cocosp_(m, x, y, w, n, t, e, maxtr, maxbin, c__, sq, sx, 
+	bind, wrk, lwrk, iwrk, kwrk, ier)
+integer *m;
+real *x, *y, *w;
+integer *n;
+real *t, *e;
+integer *maxtr, *maxbin;
+real *c__, *sq, *sx;
+logical *bind;
+real *wrk;
+integer *lwrk, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__, kwest, lwest, n6, ia, ib, ic, mb, ji, jl;
+    extern /* Subroutine */ int fpchec_();
+    static integer iq, nm, jr, iu, ju, iz;
+    extern /* Subroutine */ int fpcosp_();
+    static integer jib, jjb;
+    static real one;
+    static integer izz;
+
+/*  given the set of data points (x(i),y(i)) and the set of positive */
+/*  numbers w(i),i=1,2,...,m, subroutine cocosp determines the weighted */
+/*  least-squares cubic spline s(x) with given knots t(j),j=1,2,...,n */
+/*  which satisfies the following concavity/convexity conditions */
+/*      s''(t(j+3))*e(j) <= 0, j=1,2,...n-6 */
+/*  the fit is given in the b-spline representation( b-spline coef- */
+/*  ficients c(j),j=1,2,...n-4) and can be evaluated by means of */
+/*  subroutine splev. */
+
+/*  calling sequence: */
+/*     call cocosp(m,x,y,w,n,t,e,maxtr,maxbin,c,sq,sx,bind,wrk, */
+/*    * lwrk,iwrk,kwrk,ier) */
+
+/*  parameters: */
+/*    m   : integer. on entry m must specify the number of data points. */
+/*          m > 3. unchanged on exit. */
+/*    x   : real array of dimension at least (m). before entry, x(i) */
+/*          must be set to the i-th value of the independent variable x, */
+/*          for i=1,2,...,m. these values must be supplied in strictly */
+/*          ascending order. unchanged on exit. */
+/*    y   : real array of dimension at least (m). before entry, y(i) */
+/*          must be set to the i-th value of the dependent variable y, */
+/*          for i=1,2,...,m. unchanged on exit. */
+/*    w   : real array of dimension at least (m). before entry, w(i) */
+/*          must be set to the i-th value in the set of weights. the */
+/*          w(i) must be strictly positive. unchanged on exit. */
+/*    n   : integer. on entry n must contain the total number of knots */
+/*          of the cubic spline. m+4>=n>=8. unchanged on exit. */
+/*    t   : real array of dimension at least (n). before entry, this */
+/*          array must contain the knots of the spline, i.e. the position */
+/*          of the interior knots t(5),t(6),...,t(n-4) as well as the */
+/*          position of the boundary knots t(1),t(2),t(3),t(4) and t(n-3) */
+/*          t(n-2),t(n-1),t(n) needed for the b-spline representation. */
+/*          unchanged on exit. see also the restrictions (ier=10). */
+/*    e   : real array of dimension at least (n). before entry, e(j) */
+/*          must be set to 1 if s(x) must be locally concave at t(j+3), */
+/*          to (-1) if s(x) must be locally convex at t(j+3) and to 0 */
+/*          if no convexity constraint is imposed at t(j+3),j=1,2,..,n-6. */
+/*          e(n-5),...,e(n) are not used. unchanged on exit. */
+/*  maxtr : integer. on entry maxtr must contain an over-estimate of the */
+/*          total number of records in the used tree structure, to indic- */
+/*          ate the storage space available to the routine. maxtr >=1 */
+/*          in most practical situation maxtr=100 will be sufficient. */
+/*          always large enough is */
+/*                         n-5       n-6 */
+/*              maxtr =  (     ) + (     )  with l the greatest */
+/*                          l        l+1 */
+/*          integer <= (n-6)/2 . unchanged on exit. */
+/*  maxbin: integer. on entry maxbin must contain an over-estimate of the */
+/*          number of knots where s(x) will have a zero second derivative */
+/*          maxbin >=1. in most practical situation maxbin = 10 will be */
+/*          sufficient. always large enough is maxbin=n-6. */
+/*          unchanged on exit. */
+/*    c   : real array of dimension at least (n). */
+/*          on succesful exit, this array will contain the coefficients */
+/*          c(1),c(2),..,c(n-4) in the b-spline representation of s(x) */
+/*    sq  : real. on succesful exit, sq contains the weighted sum of */
+/*          squared residuals of the spline approximation returned. */
+/*    sx  : real array of dimension at least m. on succesful exit */
+/*          this array will contain the spline values s(x(i)),i=1,...,m */
+/*   bind : logical array of dimension at least (n). on succesful exit */
+/*          this array will indicate the knots where s''(x)=0, i.e. */
+/*                s''(t(j+3)) .eq. 0 if  bind(j) = .true. */
+/*                s''(t(j+3)) .ne. 0 if  bind(j) = .false., j=1,2,...,n-6 */
+/*   wrk  : real array of dimension at least  m*4+n*7+maxbin*(maxbin+n+1) */
+/*          used as working space. */
+/*   lwrk : integer. on entry,lwrk must specify the actual dimension of */
+/*          the array wrk as declared in the calling (sub)program.lwrk */
+/*          must not be too small (see wrk). unchanged on exit. */
+/*   iwrk : integer array of dimension at least (maxtr*4+2*(maxbin+1)) */
+/*          used as working space. */
+/*   kwrk : integer. on entry,kwrk must specify the actual dimension of */
+/*          the array iwrk as declared in the calling (sub)program. kwrk */
+/*          must not be too small (see iwrk). unchanged on exit. */
+/*   ier   : integer. error flag */
+/*      ier=0 : succesful exit. */
+/*      ier>0 : abnormal termination: no approximation is returned */
+/*        ier=1  : the number of knots where s''(x)=0 exceeds maxbin. */
+/*                 probably causes : maxbin too small. */
+/*        ier=2  : the number of records in the tree structure exceeds */
+/*                 maxtr. */
+/*                 probably causes : maxtr too small. */
+/*        ier=3  : the algoritm finds no solution to the posed quadratic */
+/*                 programming problem. */
+/*                 probably causes : rounding errors. */
+/*        ier=10 : on entry, the input data are controlled on validity. */
+/*                 the following restrictions must be satisfied */
+/*                   m>3, maxtr>=1, maxbin>=1, 8<=n<=m+4,w(i) > 0, */
+/*                   x(1)<x(2)<...<x(m), t(1)<=t(2)<=t(3)<=t(4)<=x(1), */
+/*                   x(1)<t(5)<t(6)<...<t(n-4)<x(m)<=t(n-3)<=...<=t(n), */
+/*                   kwrk>=maxtr*4+2*(maxbin+1), */
+/*                   lwrk>=m*4+n*7+maxbin*(maxbin+n+1), */
+/*                   the schoenberg-whitney conditions, i.e. there must */
+/*                   be a subset of data points xx(j) such that */
+/*                     t(j) < xx(j) < t(j+4), j=1,2,...,n-4 */
+/*                 if one of these restrictions is found to be violated */
+/*                 control is immediately repassed to the calling program */
+
+
+/*  other subroutines required: */
+/*    fpcosp,fpbspl,fpadno,fpdeno,fpseno,fpfrno,fpchec */
+
+/*  references: */
+/*   dierckx p. : an algorithm for cubic spline fitting with convexity */
+/*                constraints, computing 24 (1980) 349-371. */
+/*   dierckx p. : an algorithm for least-squares cubic spline fitting */
+/*                with convexity and concavity constraints, report tw39, */
+/*                dept. computer science, k.u.leuven, 1978. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*   p. dierckx */
+/*   dept. computer science, k.u.leuven */
+/*   celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*   e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : march 1978 */
+/*  latest update : march 1987. */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+/*  set constant */
+    /* Parameter adjustments */
+    --sx;
+    --w;
+    --y;
+    --x;
+    --bind;
+    --c__;
+    --e;
+    --t;
+    --wrk;
+    --iwrk;
+
+    /* Function Body */
+    one = (float)1.;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*m < 4 || *n < 8) {
+	goto L40;
+    }
+    if (*maxtr < 1 || *maxbin < 1) {
+	goto L40;
+    }
+    lwest = *n * 7 + (*m << 2) + *maxbin * (*n + 1 + *maxbin);
+    kwest = (*maxtr << 2) + (*maxbin + 1 << 1);
+    if (*lwrk < lwest || *kwrk < kwest) {
+	goto L40;
+    }
+    if (w[1] <= (float)0.) {
+	goto L40;
+    }
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (x[i__ - 1] >= x[i__] || w[i__] <= (float)0.) {
+	    goto L40;
+	}
+/* L10: */
+    }
+    fpchec_(&x[1], m, &t[1], n, &c__3, ier);
+    if (*ier != 0) {
+	goto L40;
+    } else {
+	goto L20;
+    }
+/*  set numbers e(i) */
+L20:
+    n6 = *n - 6;
+    i__1 = n6;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (e[i__] > (float)0.) {
+	    e[i__] = one;
+	}
+	if (e[i__] < (float)0.) {
+	    e[i__] = -one;
+	}
+/* L30: */
+    }
+/*  we partition the working space and determine the spline approximation */
+    nm = *n + *maxbin;
+    mb = *maxbin + 1;
+    ia = 1;
+    ib = ia + (*n << 2);
+    ic = ib + nm * *maxbin;
+    iz = ic + *n;
+    izz = iz + *n;
+    iu = izz + *n;
+    iq = iu + *maxbin;
+    ji = 1;
+    ju = ji + *maxtr;
+    jl = ju + *maxtr;
+    jr = jl + *maxtr;
+    jjb = jr + *maxtr;
+    jib = jjb + mb;
+    fpcosp_(m, &x[1], &y[1], &w[1], n, &t[1], &e[1], maxtr, maxbin, &c__[1], 
+	    sq, &sx[1], &bind[1], &nm, &mb, &wrk[ia], &wrk[ib], &wrk[ic], &
+	    wrk[iz], &wrk[izz], &wrk[iu], &wrk[iq], &iwrk[ji], &iwrk[ju], &
+	    iwrk[jl], &iwrk[jr], &iwrk[jjb], &iwrk[jib], ier);
+L40:
+    return 0;
+} /* cocosp_ */
+
+/* Subroutine */ int concon_(iopt, m, x, y, w, v, s, nest, maxtr, maxbin, n, 
+	t, c__, sq, sx, bind, wrk, lwrk, iwrk, kwrk, ier)
+integer *iopt, *m;
+real *x, *y, *w, *v, *s;
+integer *nest, *maxtr, *maxbin, *n;
+real *t, *c__, *sq, *sx;
+logical *bind;
+real *wrk;
+integer *lwrk, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__, kwest, lwest, ie, iw;
+    extern /* Subroutine */ int fpcoco_();
+    static real one;
+    static integer lww;
+
+/*  given the set of data points (x(i),y(i)) and the set of positive */
+/*  numbers w(i), i=1,2,...,m,subroutine concon determines a cubic spline */
+/*  approximation s(x) which satisfies the following local convexity */
+/*  constraints  s''(x(i))*v(i) <= 0, i=1,2,...,m. */
+/*  the number of knots n and the position t(j),j=1,2,...n is chosen */
+/*  automatically by the routine in a way that */
+/*       sq = sum((w(i)*(y(i)-s(x(i))))**2) be <= s. */
+/*  the fit is given in the b-spline representation (b-spline coef- */
+/*  ficients c(j),j=1,2,...n-4) and can be evaluated by means of */
+/*  subroutine splev. */
+
+/*  calling sequence: */
+
+/*     call concon(iopt,m,x,y,w,v,s,nest,maxtr,maxbin,n,t,c,sq, */
+/*    * sx,bind,wrk,lwrk,iwrk,kwrk,ier) */
+
+/*  parameters: */
+/*    iopt: integer flag. */
+/*          if iopt=0, the routine will start with the minimal number of */
+/*          knots to guarantee that the convexity conditions will be */
+/*          satisfied. if iopt=1, the routine will continue with the set */
+/*          of knots found at the last call of the routine. */
+/*          attention: a call with iopt=1 must always be immediately */
+/*          preceded by another call with iopt=1 or iopt=0. */
+/*          unchanged on exit. */
+/*    m   : integer. on entry m must specify the number of data points. */
+/*          m > 3. unchanged on exit. */
+/*    x   : real array of dimension at least (m). before entry, x(i) */
+/*          must be set to the i-th value of the independent variable x, */
+/*          for i=1,2,...,m. these values must be supplied in strictly */
+/*          ascending order. unchanged on exit. */
+/*    y   : real array of dimension at least (m). before entry, y(i) */
+/*          must be set to the i-th value of the dependent variable y, */
+/*          for i=1,2,...,m. unchanged on exit. */
+/*    w   : real array of dimension at least (m). before entry, w(i) */
+/*          must be set to the i-th value in the set of weights. the */
+/*          w(i) must be strictly positive. unchanged on exit. */
+/*    v   : real array of dimension at least (m). before entry, v(i) */
+/*          must be set to 1 if s(x) must be locally concave at x(i), */
+/*          to (-1) if s(x) must be locally convex at x(i) and to 0 */
+/*          if no convexity constraint is imposed at x(i). */
+/*    s   : real. on entry s must specify an over-estimate for the */
+/*          the weighted sum of squared residuals sq of the requested */
+/*          spline. s >=0. unchanged on exit. */
+/*   nest : integer. on entry nest must contain an over-estimate of the */
+/*          total number of knots of the spline returned, to indicate */
+/*          the storage space available to the routine. nest >=8. */
+/*          in most practical situation nest=m/2 will be sufficient. */
+/*          always large enough is  nest=m+4. unchanged on exit. */
+/*  maxtr : integer. on entry maxtr must contain an over-estimate of the */
+/*          total number of records in the used tree structure, to indic- */
+/*          ate the storage space available to the routine. maxtr >=1 */
+/*          in most practical situation maxtr=100 will be sufficient. */
+/*          always large enough is */
+/*                         nest-5      nest-6 */
+/*              maxtr =  (       ) + (        )  with l the greatest */
+/*                           l          l+1 */
+/*          integer <= (nest-6)/2 . unchanged on exit. */
+/*  maxbin: integer. on entry maxbin must contain an over-estimate of the */
+/*          number of knots where s(x) will have a zero second derivative */
+/*          maxbin >=1. in most practical situation maxbin = 10 will be */
+/*          sufficient. always large enough is maxbin=nest-6. */
+/*          unchanged on exit. */
+/*    n   : integer. */
+/*          on exit with ier <=0, n will contain the total number of */
+/*          knots of the spline approximation returned. if the comput- */
+/*          ation mode iopt=1 is used this value of n should be left */
+/*          unchanged between subsequent calls. */
+/*    t   : real array of dimension at least (nest). */
+/*          on exit with ier<=0, this array will contain the knots of the */
+/*          spline,i.e. the position of the interior knots t(5),t(6),..., */
+/*          t(n-4) as well as the position of the additional knots */
+/*          t(1)=t(2)=t(3)=t(4)=x(1) and t(n-3)=t(n-2)=t(n-1)=t(n)=x(m) */
+/*          needed for the the b-spline representation. */
+/*          if the computation mode iopt=1 is used, the values of t(1), */
+/*          t(2),...,t(n) should be left unchanged between subsequent */
+/*          calls. */
+/*    c   : real array of dimension at least (nest). */
+/*          on succesful exit, this array will contain the coefficients */
+/*          c(1),c(2),..,c(n-4) in the b-spline representation of s(x) */
+/*    sq  : real. unless ier>0 , sq contains the weighted sum of */
+/*          squared residuals of the spline approximation returned. */
+/*    sx  : real array of dimension at least m. on exit with ier<=0 */
+/*          this array will contain the spline values s(x(i)),i=1,...,m */
+/*          if the computation mode iopt=1 is used, the values of sx(1), */
+/*          sx(2),...,sx(m) should be left unchanged between subsequent */
+/*          calls. */
+/*    bind: logical array of dimension at least nest. on exit with ier<=0 */
+/*          this array will indicate the knots where s''(x)=0, i.e. */
+/*                s''(t(j+3)) .eq. 0 if  bind(j) = .true. */
+/*                s''(t(j+3)) .ne. 0 if  bind(j) = .false., j=1,2,...,n-6 */
+/*          if the computation mode iopt=1 is used, the values of bind(1) */
+/*          ,...,bind(n-6) should be left unchanged between subsequent */
+/*          calls. */
+/*   wrk  : real array of dimension at least (m*4+nest*8+maxbin*(maxbin+ */
+/*          nest+1)). used as working space. */
+/*   lwrk : integer. on entry,lwrk must specify the actual dimension of */
+/*          the array wrk as declared in the calling (sub)program.lwrk */
+/*          must not be too small (see wrk). unchanged on exit. */
+/*   iwrk : integer array of dimension at least (maxtr*4+2*(maxbin+1)) */
+/*          used as working space. */
+/*   kwrk : integer. on entry,kwrk must specify the actual dimension of */
+/*          the array iwrk as declared in the calling (sub)program. kwrk */
+/*          must not be too small (see iwrk). unchanged on exit. */
+/*   ier   : integer. error flag */
+/*      ier=0 : normal return, s(x) satisfies the concavity/convexity */
+/*              constraints and sq <= s. */
+/*      ier<0 : abnormal termination: s(x) satisfies the concavity/ */
+/*              convexity constraints but sq > s. */
+/*        ier=-3 : the requested storage space exceeds the available */
+/*                 storage space as specified by the parameter nest. */
+/*                 probably causes: nest too small. if nest is already */
+/*                 large (say nest > m/2), it may also indicate that s */
+/*                 is too small. */
+/*                 the approximation returned is the least-squares cubic */
+/*                 spline according to the knots t(1),...,t(n) (n=nest) */
+/*                 which satisfies the convexity constraints. */
+/*        ier=-2 : the maximal number of knots n=m+4 has been reached. */
+/*                 probably causes: s too small. */
+/*        ier=-1 : the number of knots n is less than the maximal number */
+/*                 m+4 but concon finds that adding one or more knots */
+/*                 will not further reduce the value of sq. */
+/*                 probably causes : s too small. */
+/*      ier>0 : abnormal termination: no approximation is returned */
+/*        ier=1  : the number of knots where s''(x)=0 exceeds maxbin. */
+/*                 probably causes : maxbin too small. */
+/*        ier=2  : the number of records in the tree structure exceeds */
+/*                 maxtr. */
+/*                 probably causes : maxtr too small. */
+/*        ier=3  : the algoritm finds no solution to the posed quadratic */
+/*                 programming problem. */
+/*                 probably causes : rounding errors. */
+/*        ier=4  : the minimum number of knots (given by n) to guarantee */
+/*                 that the concavity/convexity conditions will be */
+/*                 satisfied is greater than nest. */
+/*                 probably causes: nest too small. */
+/*        ier=5  : the minimum number of knots (given by n) to guarantee */
+/*                 that the concavity/convexity conditions will be */
+/*                 satisfied is greater than m+4. */
+/*                 probably causes: strongly alternating convexity and */
+/*                 concavity conditions. normally the situation can be */
+/*                 coped with by adding n-m-4 extra data points (found */
+/*                 by linear interpolation e.g.) with a small weight w(i) */
+/*                 and a v(i) number equal to zero. */
+/*        ier=10 : on entry, the input data are controlled on validity. */
+/*                 the following restrictions must be satisfied */
+/*                   0<=iopt<=1, m>3, nest>=8, s>=0, maxtr>=1, maxbin>=1, */
+/*                   kwrk>=maxtr*4+2*(maxbin+1), w(i)>0, x(i) < x(i+1), */
+/*                   lwrk>=m*4+nest*8+maxbin*(maxbin+nest+1) */
+/*                 if one of these restrictions is found to be violated */
+/*                 control is immediately repassed to the calling program */
+
+/*  further comments: */
+/*    as an example of the use of the computation mode iopt=1, the */
+/*    following program segment will cause concon to return control */
+/*    each time a spline with a new set of knots has been computed. */
+/*     ............. */
+/*     iopt = 0 */
+/*     s = 0.1e+60  (s very large) */
+/*     do 10 i=1,m */
+/*       call concon(iopt,m,x,y,w,v,s,nest,maxtr,maxbin,n,t,c,sq,sx, */
+/*    *  bind,wrk,lwrk,iwrk,kwrk,ier) */
+/*       ...... */
+/*       s = sq */
+/*       iopt=1 */
+/* 10  continue */
+/*     ............. */
+
+/*  other subroutines required: */
+/*    fpcoco,fpcosp,fpbspl,fpadno,fpdeno,fpseno,fpfrno */
+
+/*  references: */
+/*   dierckx p. : an algorithm for cubic spline fitting with convexity */
+/*                constraints, computing 24 (1980) 349-371. */
+/*   dierckx p. : an algorithm for least-squares cubic spline fitting */
+/*                with convexity and concavity constraints, report tw39, */
+/*                dept. computer science, k.u.leuven, 1978. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*   p. dierckx */
+/*   dept. computer science, k.u.leuven */
+/*   celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*   e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : march 1978 */
+/*  latest update : march 1987. */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+/*  set constant */
+    /* Parameter adjustments */
+    --sx;
+    --v;
+    --w;
+    --y;
+    --x;
+    --bind;
+    --c__;
+    --t;
+    --wrk;
+    --iwrk;
+
+    /* Function Body */
+    one = (float)1.;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*iopt < 0 || *iopt > 1) {
+	goto L30;
+    }
+    if (*m < 4 || *nest < 8) {
+	goto L30;
+    }
+    if (*s < (float)0.) {
+	goto L30;
+    }
+    if (*maxtr < 1 || *maxbin < 1) {
+	goto L30;
+    }
+    lwest = (*nest << 3) + (*m << 2) + *maxbin * (*nest + 1 + *maxbin);
+    kwest = (*maxtr << 2) + (*maxbin + 1 << 1);
+    if (*lwrk < lwest || *kwrk < kwest) {
+	goto L30;
+    }
+    if (*iopt > 0) {
+	goto L20;
+    }
+    if (w[1] <= (float)0.) {
+	goto L30;
+    }
+    if (v[1] > (float)0.) {
+	v[1] = one;
+    }
+    if (v[1] < (float)0.) {
+	v[1] = -one;
+    }
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (x[i__ - 1] >= x[i__] || w[i__] <= (float)0.) {
+	    goto L30;
+	}
+	if (v[i__] > (float)0.) {
+	    v[i__] = one;
+	}
+	if (v[i__] < (float)0.) {
+	    v[i__] = -one;
+	}
+/* L10: */
+    }
+L20:
+    *ier = 0;
+/*  we partition the working space and determine the spline approximation */
+    ie = 1;
+    iw = ie + *nest;
+    lww = *lwrk - *nest;
+    fpcoco_(iopt, m, &x[1], &y[1], &w[1], &v[1], s, nest, maxtr, maxbin, n, &
+	    t[1], &c__[1], sq, &sx[1], &bind[1], &wrk[ie], &wrk[iw], &lww, &
+	    iwrk[1], kwrk, ier);
+L30:
+    return 0;
+} /* concon_ */
+
+/* Subroutine */ int concur_(iopt, idim, m, u, mx, x, xx, w, ib, db, nb, ie, 
+	de, ne, k, s, nest, n, t, nc, c__, np, cp, fp, wrk, lwrk, iwrk, ier)
+integer *iopt, *idim, *m;
+real *u;
+integer *mx;
+real *x, *xx, *w;
+integer *ib;
+real *db;
+integer *nb, *ie;
+real *de;
+integer *ne, *k;
+real *s;
+integer *nest, *n;
+real *t;
+integer *nc;
+real *c__;
+integer *np;
+real *cp, *fp, *wrk;
+integer *lwrk, *iwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static integer mmin, nmin, nmax, i__, j, maxit;
+    extern /* Subroutine */ int curev_();
+    static integer k1, k2, lwest, ja, jb, jg, kk;
+    extern /* Subroutine */ int fpched_();
+    static integer jq, jz;
+    extern /* Subroutine */ int fpadpo_(), fpcons_();
+    static integer ib1;
+    extern /* Subroutine */ int fppocu_();
+    static integer ie1, ncc, jfp;
+    static real tol;
+    static integer mxx;
+
+/*  given the ordered set of m points x(i) in the idim-dimensional space */
+/*  and given also a corresponding set of strictly increasing values u(i) */
+/*  and the set of positive numbers w(i),i=1,2,...,m, subroutine concur */
+/*  determines a smooth approximating spline curve s(u), i.e. */
+/*      x1 = s1(u) */
+/*      x2 = s2(u)      ub = u(1) <= u <= u(m) = ue */
+/*      ......... */
+/*      xidim = sidim(u) */
+/*  with sj(u),j=1,2,...,idim spline functions of odd degree k with */
+/*  common knots t(j),j=1,2,...,n. */
+/*  in addition these splines will satisfy the following boundary */
+/*  constraints        (l) */
+/*      if ib > 0 :  sj   (u(1)) = db(idim*l+j) ,l=0,1,...,ib-1 */
+/*  and                (l) */
+/*      if ie > 0 :  sj   (u(m)) = de(idim*l+j) ,l=0,1,...,ie-1. */
+/*  if iopt=-1 concur calculates the weighted least-squares spline curve */
+/*  according to a given set of knots. */
+/*  if iopt>=0 the number of knots of the splines sj(u) and the position */
+/*  t(j),j=1,2,...,n is chosen automatically by the routine. the smooth- */
+/*  ness of s(u) is then achieved by minimalizing the discontinuity */
+/*  jumps of the k-th derivative of s(u) at the knots t(j),j=k+2,k+3,..., */
+/*  n-k-1. the amount of smoothness is determined by the condition that */
+/*  f(p)=sum((w(i)*dist(x(i),s(u(i))))**2) be <= s, with s a given non- */
+/*  negative constant, called the smoothing factor. */
+/*  the fit s(u) is given in the b-spline representation and can be */
+/*  evaluated by means of subroutine curev. */
+
+/*  calling sequence: */
+/*     call concur(iopt,idim,m,u,mx,x,xx,w,ib,db,nb,ie,de,ne,k,s,nest,n, */
+/*    * t,nc,c,np,cp,fp,wrk,lwrk,iwrk,ier) */
+
+/*  parameters: */
+/*   iopt  : integer flag. on entry iopt must specify whether a weighted */
+/*           least-squares spline curve (iopt=-1) or a smoothing spline */
+/*           curve (iopt=0 or 1) must be determined.if iopt=0 the routine */
+/*           will start with an initial set of knots t(i)=ub,t(i+k+1)=ue, */
+/*           i=1,2,...,k+1. if iopt=1 the routine will continue with the */
+/*           knots found at the last call of the routine. */
+/*           attention: a call with iopt=1 must always be immediately */
+/*           preceded by another call with iopt=1 or iopt=0. */
+/*           unchanged on exit. */
+/*   idim  : integer. on entry idim must specify the dimension of the */
+/*           curve. 0 < idim < 11. */
+/*           unchanged on exit. */
+/*   m     : integer. on entry m must specify the number of data points. */
+/*           m > k-max(ib-1,0)-max(ie-1,0). unchanged on exit. */
+/*   u     : real array of dimension at least (m). before entry, */
+/*           u(i) must be set to the i-th value of the parameter variable */
+/*           u for i=1,2,...,m. these values must be supplied in */
+/*           strictly ascending order and will be unchanged on exit. */
+/*   mx    : integer. on entry mx must specify the actual dimension of */
+/*           the arrays x and xx as declared in the calling (sub)program */
+/*           mx must not be too small (see x). unchanged on exit. */
+/*   x     : real array of dimension at least idim*m. */
+/*           before entry, x(idim*(i-1)+j) must contain the j-th coord- */
+/*           inate of the i-th data point for i=1,2,...,m and j=1,2,..., */
+/*           idim. unchanged on exit. */
+/*   xx    : real array of dimension at least idim*m. */
+/*           used as working space. on exit xx contains the coordinates */
+/*           of the data points to which a spline curve with zero deriv- */
+/*           ative constraints has been determined. */
+/*           if the computation mode iopt =1 is used xx should be left */
+/*           unchanged between calls. */
+/*   w     : real array of dimension at least (m). before entry, w(i) */
+/*           must be set to the i-th value in the set of weights. the */
+/*           w(i) must be strictly positive. unchanged on exit. */
+/*           see also further comments. */
+/*   ib    : integer. on entry ib must specify the number of derivative */
+/*           constraints for the curve at the begin point. 0<=ib<=(k+1)/2 */
+/*           unchanged on exit. */
+/*   db    : real array of dimension nb. before entry db(idim*l+j) must */
+/*           contain the l-th order derivative of sj(u) at u=u(1) for */
+/*           j=1,2,...,idim and l=0,1,...,ib-1 (if ib>0). */
+/*           unchanged on exit. */
+/*   nb    : integer, specifying the dimension of db. nb>=max(1,idim*ib) */
+/*           unchanged on exit. */
+/*   ie    : integer. on entry ie must specify the number of derivative */
+/*           constraints for the curve at the end point. 0<=ie<=(k+1)/2 */
+/*           unchanged on exit. */
+/*   de    : real array of dimension ne. before entry de(idim*l+j) must */
+/*           contain the l-th order derivative of sj(u) at u=u(m) for */
+/*           j=1,2,...,idim and l=0,1,...,ie-1 (if ie>0). */
+/*           unchanged on exit. */
+/*   ne    : integer, specifying the dimension of de. ne>=max(1,idim*ie) */
+/*           unchanged on exit. */
+/*   k     : integer. on entry k must specify the degree of the splines. */
+/*           k=1,3 or 5. */
+/*           unchanged on exit. */
+/*   s     : real.on entry (in case iopt>=0) s must specify the smoothing */
+/*           factor. s >=0. unchanged on exit. */
+/*           for advice on the choice of s see further comments. */
+/*   nest  : integer. on entry nest must contain an over-estimate of the */
+/*           total number of knots of the splines returned, to indicate */
+/*           the storage space available to the routine. nest >=2*k+2. */
+/*           in most practical situation nest=m/2 will be sufficient. */
+/*           always large enough is nest=m+k+1+max(0,ib-1)+max(0,ie-1), */
+/*           the number of knots needed for interpolation (s=0). */
+/*           unchanged on exit. */
+/*   n     : integer. */
+/*           unless ier = 10 (in case iopt >=0), n will contain the */
+/*           total number of knots of the smoothing spline curve returned */
+/*           if the computation mode iopt=1 is used this value of n */
+/*           should be left unchanged between subsequent calls. */
+/*           in case iopt=-1, the value of n must be specified on entry. */
+/*   t     : real array of dimension at least (nest). */
+/*           on succesful exit, this array will contain the knots of the */
+/*           spline curve,i.e. the position of the interior knots t(k+2), */
+/*           t(k+3),..,t(n-k-1) as well as the position of the additional */
+/*           t(1)=t(2)=...=t(k+1)=ub and t(n-k)=...=t(n)=ue needed for */
+/*           the b-spline representation. */
+/*           if the computation mode iopt=1 is used, the values of t(1), */
+/*           t(2),...,t(n) should be left unchanged between subsequent */
+/*           calls. if the computation mode iopt=-1 is used, the values */
+/*           t(k+2),...,t(n-k-1) must be supplied by the user, before */
+/*           entry. see also the restrictions (ier=10). */
+/*   nc    : integer. on entry nc must specify the actual dimension of */
+/*           the array c as declared in the calling (sub)program. nc */
+/*           must not be too small (see c). unchanged on exit. */
+/*   c     : real array of dimension at least (nest*idim). */
+/*           on succesful exit, this array will contain the coefficients */
+/*           in the b-spline representation of the spline curve s(u),i.e. */
+/*           the b-spline coefficients of the spline sj(u) will be given */
+/*           in c(n*(j-1)+i),i=1,2,...,n-k-1 for j=1,2,...,idim. */
+/*   cp    : real array of dimension at least 2*(k+1)*idim. */
+/*           on exit cp will contain the b-spline coefficients of a */
+/*           polynomial curve which satisfies the boundary constraints. */
+/*           if the computation mode iopt =1 is used cp should be left */
+/*           unchanged between calls. */
+/*   np    : integer. on entry np must specify the actual dimension of */
+/*           the array cp as declared in the calling (sub)program. np */
+/*           must not be too small (see cp). unchanged on exit. */
+/*   fp    : real. unless ier = 10, fp contains the weighted sum of */
+/*           squared residuals of the spline curve returned. */
+/*   wrk   : real array of dimension at least m*(k+1)+nest*(6+idim+3*k). */
+/*           used as working space. if the computation mode iopt=1 is */
+/*           used, the values wrk(1),...,wrk(n) should be left unchanged */
+/*           between subsequent calls. */
+/*   lwrk  : integer. on entry,lwrk must specify the actual dimension of */
+/*           the array wrk as declared in the calling (sub)program. lwrk */
+/*           must not be too small (see wrk). unchanged on exit. */
+/*   iwrk  : integer array of dimension at least (nest). */
+/*           used as working space. if the computation mode iopt=1 is */
+/*           used,the values iwrk(1),...,iwrk(n) should be left unchanged */
+/*           between subsequent calls. */
+/*   ier   : integer. unless the routine detects an error, ier contains a */
+/*           non-positive value on exit, i.e. */
+/*    ier=0  : normal return. the curve returned has a residual sum of */
+/*             squares fp such that abs(fp-s)/s <= tol with tol a relat- */
+/*             ive tolerance set to 0.001 by the program. */
+/*    ier=-1 : normal return. the curve returned is an interpolating */
+/*             spline curve, satisfying the constraints (fp=0). */
+/*    ier=-2 : normal return. the curve returned is the weighted least- */
+/*             squares polynomial curve of degree k, satisfying the */
+/*             constraints. in this extreme case fp gives the upper */
+/*             bound fp0 for the smoothing factor s. */
+/*    ier=1  : error. the required storage space exceeds the available */
+/*             storage space, as specified by the parameter nest. */
+/*             probably causes : nest too small. if nest is already */
+/*             large (say nest > m/2), it may also indicate that s is */
+/*             too small */
+/*             the approximation returned is the least-squares spline */
+/*             curve according to the knots t(1),t(2),...,t(n). (n=nest) */
+/*             the parameter fp gives the corresponding weighted sum of */
+/*             squared residuals (fp>s). */
+/*    ier=2  : error. a theoretically impossible result was found during */
+/*             the iteration proces for finding a smoothing spline curve */
+/*             with fp = s. probably causes : s too small. */
+/*             there is an approximation returned but the corresponding */
+/*             weighted sum of squared residuals does not satisfy the */
+/*             condition abs(fp-s)/s < tol. */
+/*    ier=3  : error. the maximal number of iterations maxit (set to 20 */
+/*             by the program) allowed for finding a smoothing curve */
+/*             with fp=s has been reached. probably causes : s too small */
+/*             there is an approximation returned but the corresponding */
+/*             weighted sum of squared residuals does not satisfy the */
+/*             condition abs(fp-s)/s < tol. */
+/*    ier=10 : error. on entry, the input data are controlled on validity */
+/*             the following restrictions must be satisfied. */
+/*             -1<=iopt<=1, k = 1,3 or 5, m>k-max(0,ib-1)-max(0,ie-1), */
+/*             nest>=2k+2, 0<idim<=10, lwrk>=(k+1)*m+nest*(6+idim+3*k), */
+/*             nc >=nest*idim ,u(1)<u(2)<...<u(m),w(i)>0 i=1,2,...,m, */
+/*             mx>=idim*m,0<=ib<=(k+1)/2,0<=ie<=(k+1)/2,nb>=1,ne>=1, */
+/*             nb>=ib*idim,ne>=ib*idim,np>=2*(k+1)*idim, */
+/*             if iopt=-1:2*k+2<=n<=min(nest,mmax) with mmax = m+k+1+ */
+/*                        max(0,ib-1)+max(0,ie-1) */
+/*                        u(1)<t(k+2)<t(k+3)<...<t(n-k-1)<u(m) */
+/*                       the schoenberg-whitney conditions, i.e. there */
+/*                       must be a subset of data points uu(j) such that */
+/*                         t(j) < uu(j) < t(j+k+1), j=1+max(0,ib-1),... */
+/*                                                   ,n+k-1-max(0,ie-1) */
+/*             if iopt>=0: s>=0 */
+/*                         if s=0 : nest >=mmax (see above) */
+/*             if one of these conditions is found to be violated,control */
+/*             is immediately repassed to the calling program. in that */
+/*             case there is no approximation returned. */
+
+/*  further comments: */
+/*   by means of the parameter s, the user can control the tradeoff */
+/*   between closeness of fit and smoothness of fit of the approximation. */
+/*   if s is too large, the curve will be too smooth and signal will be */
+/*   lost ; if s is too small the curve will pick up too much noise. in */
+/*   the extreme cases the program will return an interpolating curve if */
+/*   s=0 and the least-squares polynomial curve of degree k if s is */
+/*   very large. between these extremes, a properly chosen s will result */
+/*   in a good compromise between closeness of fit and smoothness of fit. */
+/*   to decide whether an approximation, corresponding to a certain s is */
+/*   satisfactory the user is highly recommended to inspect the fits */
+/*   graphically. */
+/*   recommended values for s depend on the weights w(i). if these are */
+/*   taken as 1/d(i) with d(i) an estimate of the standard deviation of */
+/*   x(i), a good s-value should be found in the range (m-sqrt(2*m),m+ */
+/*   sqrt(2*m)). if nothing is known about the statistical error in x(i) */
+/*   each w(i) can be set equal to one and s determined by trial and */
+/*   error, taking account of the comments above. the best is then to */
+/*   start with a very large value of s ( to determine the least-squares */
+/*   polynomial curve and the upper bound fp0 for s) and then to */
+/*   progressively decrease the value of s ( say by a factor 10 in the */
+/*   beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the */
+/*   approximating curve shows more detail) to obtain closer fits. */
+/*   to economize the search for a good s-value the program provides with */
+/*   different modes of computation. at the first call of the routine, or */
+/*   whenever he wants to restart with the initial set of knots the user */
+/*   must set iopt=0. */
+/*   if iopt=1 the program will continue with the set of knots found at */
+/*   the last call of the routine. this will save a lot of computation */
+/*   time if concur is called repeatedly for different values of s. */
+/*   the number of knots of the spline returned and their location will */
+/*   depend on the value of s and on the complexity of the shape of the */
+/*   curve underlying the data. but, if the computation mode iopt=1 is */
+/*   used, the knots returned may also depend on the s-values at previous */
+/*   calls (if these were smaller). therefore, if after a number of */
+/*   trials with different s-values and iopt=1, the user can finally */
+/*   accept a fit as satisfactory, it may be worthwhile for him to call */
+/*   concur once more with the selected value for s but now with iopt=0. */
+/*   indeed, concur may then return an approximation of the same quality */
+/*   of fit but with fewer knots and therefore better if data reduction */
+/*   is also an important objective for the user. */
+
+/*   the form of the approximating curve can strongly be affected by */
+/*   the choice of the parameter values u(i). if there is no physical */
+/*   reason for choosing a particular parameter u, often good results */
+/*   will be obtained with the choice */
+/*        v(1)=0, v(i)=v(i-1)+q(i), i=2,...,m, u(i)=v(i)/v(m), i=1,..,m */
+/*   where */
+/*        q(i)= sqrt(sum j=1,idim (xj(i)-xj(i-1))**2 ) */
+/*   other possibilities for q(i) are */
+/*        q(i)= sum j=1,idim (xj(i)-xj(i-1))**2 */
+/*        q(i)= sum j=1,idim abs(xj(i)-xj(i-1)) */
+/*        q(i)= max j=1,idim abs(xj(i)-xj(i-1)) */
+/*        q(i)= 1 */
+
+/*  other subroutines required: */
+/*    fpback,fpbspl,fpched,fpcons,fpdisc,fpgivs,fpknot,fprati,fprota */
+/*    curev,fppocu,fpadpo,fpinst */
+
+/*  references: */
+/*   dierckx p. : algorithms for smoothing data with periodic and */
+/*                parametric splines, computer graphics and image */
+/*                processing 20 (1982) 171-184. */
+/*   dierckx p. : algorithms for smoothing data with periodic and param- */
+/*                etric splines, report tw55, dept. computer science, */
+/*                k.u.leuven, 1981. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*    p.dierckx */
+/*    dept. computer science, k.u. leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : may 1979 */
+/*  latest update : march 1987 */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/* ..function references */
+/*  .. */
+/*  we set up the parameters tol and maxit */
+    /* Parameter adjustments */
+    --w;
+    --u;
+    --xx;
+    --x;
+    --db;
+    --de;
+    --iwrk;
+    --t;
+    --c__;
+    --cp;
+    --wrk;
+
+    /* Function Body */
+    maxit = 20;
+    tol = (float).001;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*iopt < -1 || *iopt > 1) {
+	goto L90;
+    }
+    if (*idim <= 0 || *idim > 10) {
+	goto L90;
+    }
+    if (*k <= 0 || *k > 5) {
+	goto L90;
+    }
+    k1 = *k + 1;
+    kk = k1 / 2;
+    if (kk << 1 != k1) {
+	goto L90;
+    }
+    k2 = k1 + 1;
+    if (*ib < 0 || *ib > kk) {
+	goto L90;
+    }
+    if (*ie < 0 || *ie > kk) {
+	goto L90;
+    }
+    nmin = k1 << 1;
+/* Computing MAX */
+    i__1 = 0, i__2 = *ib - 1;
+    ib1 = max(i__1,i__2);
+/* Computing MAX */
+    i__1 = 0, i__2 = *ie - 1;
+    ie1 = max(i__1,i__2);
+    mmin = k1 - ib1 - ie1;
+    if (*m < mmin || *nest < nmin) {
+	goto L90;
+    }
+    if (*nb < *idim * *ib || *ne < *idim * *ie) {
+	goto L90;
+    }
+    if (*np < (k1 << 1) * *idim) {
+	goto L90;
+    }
+    mxx = *m * *idim;
+    ncc = *nest * *idim;
+    if (*mx < mxx || *nc < ncc) {
+	goto L90;
+    }
+    lwest = *m * k1 + *nest * (*idim + 6 + *k * 3);
+    if (*lwrk < lwest) {
+	goto L90;
+    }
+    if (w[1] <= (float)0.) {
+	goto L90;
+    }
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (u[i__ - 1] >= u[i__] || w[i__] <= (float)0.) {
+	    goto L90;
+	}
+/* L10: */
+    }
+    if (*iopt >= 0) {
+	goto L30;
+    }
+    if (*n < nmin || *n > *nest) {
+	goto L90;
+    }
+    j = *n;
+    i__1 = k1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	t[i__] = u[1];
+	t[j] = u[*m];
+	--j;
+/* L20: */
+    }
+    fpched_(&u[1], m, &t[1], n, k, ib, ie, ier);
+    if (*ier != 0) {
+	goto L90;
+    } else {
+	goto L40;
+    }
+L30:
+    if (*s < (float)0.) {
+	goto L90;
+    }
+    nmax = *m + k1 + ib1 + ie1;
+    if (*s == (float)0. && *nest < nmax) {
+	goto L90;
+    }
+    *ier = 0;
+    if (*iopt > 0) {
+	goto L70;
+    }
+/*  we determine a polynomial curve satisfying the boundary constraints. */
+L40:
+    fppocu_(idim, k, &u[1], &u[*m], ib, &db[1], nb, ie, &de[1], ne, &cp[1], 
+	    np);
+/*  we generate new data points which will be approximated by a spline */
+/*  with zero derivative constraints. */
+    j = nmin;
+    i__1 = k1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	wrk[i__] = u[1];
+	wrk[j] = u[*m];
+	--j;
+/* L50: */
+    }
+/*  evaluate the polynomial curve */
+    curev_(idim, &wrk[1], &nmin, &cp[1], np, k, &u[1], m, &xx[1], &mxx, ier);
+/*  substract from the old data, the values of the polynomial curve */
+    i__1 = mxx;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	xx[i__] = x[i__] - xx[i__];
+/* L60: */
+    }
+/* we partition the working space and determine the spline curve. */
+L70:
+    jfp = 1;
+    jz = jfp + *nest;
+    ja = jz + ncc;
+    jb = ja + *nest * k1;
+    jg = jb + *nest * k2;
+    jq = jg + *nest * k2;
+    fpcons_(iopt, idim, m, &u[1], &mxx, &xx[1], &w[1], ib, ie, k, s, nest, &
+	    tol, &maxit, &k1, &k2, n, &t[1], &ncc, &c__[1], fp, &wrk[jfp], &
+	    wrk[jz], &wrk[ja], &wrk[jb], &wrk[jg], &wrk[jq], &iwrk[1], ier);
+/*  add the polynomial curve to the calculated spline. */
+    fpadpo_(idim, &t[1], n, &c__[1], &ncc, k, &cp[1], np, &wrk[jz], &wrk[ja], 
+	    &wrk[jb]);
+L90:
+    return 0;
+} /* concur_ */
+
+/* Subroutine */ int cualde_(idim, t, n, c__, nc, k1, u, d__, nd, ier)
+integer *idim;
+real *t;
+integer *n;
+real *c__;
+integer *nc, *k1;
+real *u, *d__;
+integer *nd, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static real h__[6];
+    static integer i__, j, l, m, kk;
+    extern /* Subroutine */ int fpader_();
+    static integer nk1;
+
+/*  subroutine cualde evaluates at the point u all the derivatives */
+/*                     (l) */
+/*     d(idim*l+j) = sj   (u) ,l=0,1,...,k, j=1,2,...,idim */
+/*  of a spline curve s(u) of order k1 (degree k=k1-1) and dimension idim */
+/*  given in its b-spline representation. */
+
+/*  calling sequence: */
+/*     call cualde(idim,t,n,c,nc,k1,u,d,nd,ier) */
+
+/*  input parameters: */
+/*    idim : integer, giving the dimension of the spline curve. */
+/*    t    : array,length n, which contains the position of the knots. */
+/*    n    : integer, giving the total number of knots of s(u). */
+/*    c    : array,length nc, which contains the b-spline coefficients. */
+/*    nc   : integer, giving the total number of coefficients of s(u). */
+/*    k1   : integer, giving the order of s(u) (order=degree+1). */
+/*    u    : real, which contains the point where the derivatives must */
+/*           be evaluated. */
+/*    nd   : integer, giving the dimension of the array d. nd >= k1*idim */
+
+/*  output parameters: */
+/*    d    : array,length nd,giving the different curve derivatives. */
+/*           d(idim*l+j) will contain the j-th coordinate of the l-th */
+/*           derivative of the curve at the point u. */
+/*    ier  : error flag */
+/*      ier = 0 : normal return */
+/*      ier =10 : invalid input data (see restrictions) */
+
+/*  restrictions: */
+/*    nd >= k1*idim */
+/*    t(k1) <= u <= t(n-k1+1) */
+
+/*  further comments: */
+/*    if u coincides with a knot, right derivatives are computed */
+/*    ( left derivatives if u = t(n-k1+1) ). */
+
+/*  other subroutines required: fpader. */
+
+/*  references : */
+/*    de boor c : on calculating with b-splines, j. approximation theory */
+/*                6 (1972) 50-62. */
+/*    cox m.g.  : the numerical evaluation of b-splines, j. inst. maths */
+/*                applics 10 (1972) 134-149. */
+/*    dierckx p. : curve and surface fitting with splines, monographs on */
+/*                 numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1987 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local array.. */
+/*  .. */
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid control is immediately repassed to the calling program. */
+    /* Parameter adjustments */
+    --t;
+    --c__;
+    --d__;
+
+    /* Function Body */
+    *ier = 10;
+    if (*nd < *k1 * *idim) {
+	goto L500;
+    }
+    nk1 = *n - *k1;
+    if (*u < t[*k1] || *u > t[nk1 + 1]) {
+	goto L500;
+    }
+/*  search for knot interval t(l) <= u < t(l+1) */
+    l = *k1;
+L100:
+    if (*u < t[l + 1] || l == nk1) {
+	goto L200;
+    }
+    ++l;
+    goto L100;
+L200:
+    if (t[l] >= t[l + 1]) {
+	goto L500;
+    }
+    *ier = 0;
+/*  calculate the derivatives. */
+    j = 1;
+    i__1 = *idim;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	fpader_(&t[1], n, &c__[j], k1, u, &l, h__);
+	m = i__;
+	i__2 = *k1;
+	for (kk = 1; kk <= i__2; ++kk) {
+	    d__[m] = h__[kk - 1];
+	    m += *idim;
+/* L300: */
+	}
+	j += *n;
+/* L400: */
+    }
+L500:
+    return 0;
+} /* cualde_ */
+
+/* Subroutine */ int curev_(idim, t, n, c__, nc, k, u, m, x, mx, ier)
+integer *idim;
+real *t;
+integer *n;
+real *c__;
+integer *nc, *k;
+real *u;
+integer *m;
+real *x;
+integer *mx, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Local variables */
+    static real h__[6];
+    static integer i__, j, l, j1, k1, l1, jj;
+    static real tb;
+    static integer ll;
+    static real te;
+    static integer mm;
+    static real sp;
+    extern /* Subroutine */ int fpbspl_();
+    static integer nk1;
+    static real arg;
+
+/*  subroutine curev evaluates in a number of points u(i),i=1,2,...,m */
+/*  a spline curve s(u) of degree k and dimension idim, given in its */
+/*  b-spline representation. */
+
+/*  calling sequence: */
+/*     call curev(idim,t,n,c,nc,k,u,m,x,mx,ier) */
+
+/*  input parameters: */
+/*    idim : integer, giving the dimension of the spline curve. */
+/*    t    : array,length n, which contains the position of the knots. */
+/*    n    : integer, giving the total number of knots of s(u). */
+/*    c    : array,length nc, which contains the b-spline coefficients. */
+/*    nc   : integer, giving the total number of coefficients of s(u). */
+/*    k    : integer, giving the degree of s(u). */
+/*    u    : array,length m, which contains the points where s(u) must */
+/*           be evaluated. */
+/*    m    : integer, giving the number of points where s(u) must be */
+/*           evaluated. */
+/*    mx   : integer, giving the dimension of the array x. mx >= m*idim */
+
+/*  output parameters: */
+/*    x    : array,length mx,giving the value of s(u) at the different */
+/*           points. x(idim*(i-1)+j) will contain the j-th coordinate */
+/*           of the i-th point on the curve. */
+/*    ier  : error flag */
+/*      ier = 0 : normal return */
+/*      ier =10 : invalid input data (see restrictions) */
+
+/*  restrictions: */
+/*    m >= 1 */
+/*    mx >= m*idim */
+/*    t(k+1) <= u(i) <= u(i+1) <= t(n-k) , i=1,2,...,m-1. */
+
+/*  other subroutines required: fpbspl. */
+
+/*  references : */
+/*    de boor c : on calculating with b-splines, j. approximation theory */
+/*                6 (1972) 50-62. */
+/*    cox m.g.  : the numerical evaluation of b-splines, j. inst. maths */
+/*                applics 10 (1972) 134-149. */
+/*    dierckx p. : curve and surface fitting with splines, monographs on */
+/*                 numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1987 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local array.. */
+/*  .. */
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid control is immediately repassed to the calling program. */
+    /* Parameter adjustments */
+    --t;
+    --c__;
+    --u;
+    --x;
+
+    /* Function Body */
+    *ier = 10;
+    if ((i__1 = *m - 1) < 0) {
+	goto L100;
+    } else if (i__1 == 0) {
+	goto L30;
+    } else {
+	goto L10;
+    }
+L10:
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (u[i__] < u[i__ - 1]) {
+	    goto L100;
+	}
+/* L20: */
+    }
+L30:
+    if (*mx < *m * *idim) {
+	goto L100;
+    }
+    *ier = 0;
+/*  fetch tb and te, the boundaries of the approximation interval. */
+    k1 = *k + 1;
+    nk1 = *n - k1;
+    tb = t[k1];
+    te = t[nk1 + 1];
+    l = k1;
+    l1 = l + 1;
+/*  main loop for the different points. */
+    mm = 0;
+    i__1 = *m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+/*  fetch a new u-value arg. */
+	arg = u[i__];
+	if (arg < tb) {
+	    arg = tb;
+	}
+	if (arg > te) {
+	    arg = te;
+	}
+/*  search for knot interval t(l) <= arg < t(l+1) */
+L40:
+	if (arg < t[l1] || l == nk1) {
+	    goto L50;
+	}
+	l = l1;
+	l1 = l + 1;
+	goto L40;
+/*  evaluate the non-zero b-splines at arg. */
+L50:
+	fpbspl_(&t[1], n, k, &arg, &l, h__);
+/*  find the value of s(u) at u=arg. */
+	ll = l - k1;
+	i__2 = *idim;
+	for (j1 = 1; j1 <= i__2; ++j1) {
+	    jj = ll;
+	    sp = (float)0.;
+	    i__3 = k1;
+	    for (j = 1; j <= i__3; ++j) {
+		++jj;
+		sp += c__[jj] * h__[j - 1];
+/* L60: */
+	    }
+	    ++mm;
+	    x[mm] = sp;
+	    ll += *n;
+/* L70: */
+	}
+/* L80: */
+    }
+L100:
+    return 0;
+} /* curev_ */
+
+/* Subroutine */ int curfit_(iopt, m, x, y, w, xb, xe, k, s, nest, n, t, c__, 
+	fp, wrk, lwrk, iwrk, ier)
+integer *iopt, *m;
+real *x, *y, *w, *xb, *xe;
+integer *k;
+real *s;
+integer *nest, *n;
+real *t, *c__, *fp, *wrk;
+integer *lwrk, *iwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer nmin, i__, j, maxit, k1, k2, lwest, ia, ib, ig;
+    extern /* Subroutine */ int fpchec_();
+    static integer iq, iz;
+    extern /* Subroutine */ int fpcurf_();
+    static integer ifp;
+    static real tol;
+
+/*  given the set of data points (x(i),y(i)) and the set of positive */
+/*  numbers w(i),i=1,2,...,m,subroutine curfit determines a smooth spline */
+/*  approximation of degree k on the interval xb <= x <= xe. */
+/*  if iopt=-1 curfit calculates the weighted least-squares spline */
+/*  according to a given set of knots. */
+/*  if iopt>=0 the number of knots of the spline s(x) and the position */
+/*  t(j),j=1,2,...,n is chosen automatically by the routine. the smooth- */
+/*  ness of s(x) is then achieved by minimalizing the discontinuity */
+/*  jumps of the k-th derivative of s(x) at the knots t(j),j=k+2,k+3,..., */
+/*  n-k-1. the amount of smoothness is determined by the condition that */
+/*  f(p)=sum((w(i)*(y(i)-s(x(i))))**2) be <= s, with s a given non- */
+/*  negative constant, called the smoothing factor. */
+/*  the fit s(x) is given in the b-spline representation (b-spline coef- */
+/*  ficients c(j),j=1,2,...,n-k-1) and can be evaluated by means of */
+/*  subroutine splev. */
+
+/*  calling sequence: */
+/*     call curfit(iopt,m,x,y,w,xb,xe,k,s,nest,n,t,c,fp,wrk, */
+/*    * lwrk,iwrk,ier) */
+
+/*  parameters: */
+/*   iopt  : integer flag. on entry iopt must specify whether a weighted */
+/*           least-squares spline (iopt=-1) or a smoothing spline (iopt= */
+/*           0 or 1) must be determined. if iopt=0 the routine will start */
+/*           with an initial set of knots t(i)=xb, t(i+k+1)=xe, i=1,2,... */
+/*           k+1. if iopt=1 the routine will continue with the knots */
+/*           found at the last call of the routine. */
+/*           attention: a call with iopt=1 must always be immediately */
+/*           preceded by another call with iopt=1 or iopt=0. */
+/*           unchanged on exit. */
+/*   m     : integer. on entry m must specify the number of data points. */
+/*           m > k. unchanged on exit. */
+/*   x     : real array of dimension at least (m). before entry, x(i) */
+/*           must be set to the i-th value of the independent variable x, */
+/*           for i=1,2,...,m. these values must be supplied in strictly */
+/*           ascending order. unchanged on exit. */
+/*   y     : real array of dimension at least (m). before entry, y(i) */
+/*           must be set to the i-th value of the dependent variable y, */
+/*           for i=1,2,...,m. unchanged on exit. */
+/*   w     : real array of dimension at least (m). before entry, w(i) */
+/*           must be set to the i-th value in the set of weights. the */
+/*           w(i) must be strictly positive. unchanged on exit. */
+/*           see also further comments. */
+/*   xb,xe : real values. on entry xb and xe must specify the boundaries */
+/*           of the approximation interval. xb<=x(1), xe>=x(m). */
+/*           unchanged on exit. */
+/*   k     : integer. on entry k must specify the degree of the spline. */
+/*           1<=k<=5. it is recommended to use cubic splines (k=3). */
+/*           the user is strongly dissuaded from choosing k even,together */
+/*           with a small s-value. unchanged on exit. */
+/*   s     : real.on entry (in case iopt>=0) s must specify the smoothing */
+/*           factor. s >=0. unchanged on exit. */
+/*           for advice on the choice of s see further comments. */
+/*   nest  : integer. on entry nest must contain an over-estimate of the */
+/*           total number of knots of the spline returned, to indicate */
+/*           the storage space available to the routine. nest >=2*k+2. */
+/*           in most practical situation nest=m/2 will be sufficient. */
+/*           always large enough is  nest=m+k+1, the number of knots */
+/*           needed for interpolation (s=0). unchanged on exit. */
+/*   n     : integer. */
+/*           unless ier =10 (in case iopt >=0), n will contain the */
+/*           total number of knots of the spline approximation returned. */
+/*           if the computation mode iopt=1 is used this value of n */
+/*           should be left unchanged between subsequent calls. */
+/*           in case iopt=-1, the value of n must be specified on entry. */
+/*   t     : real array of dimension at least (nest). */
+/*           on succesful exit, this array will contain the knots of the */
+/*           spline,i.e. the position of the interior knots t(k+2),t(k+3) */
+/*           ...,t(n-k-1) as well as the position of the additional knots */
+/*           t(1)=t(2)=...=t(k+1)=xb and t(n-k)=...=t(n)=xe needed for */
+/*           the b-spline representation. */
+/*           if the computation mode iopt=1 is used, the values of t(1), */
+/*           t(2),...,t(n) should be left unchanged between subsequent */
+/*           calls. if the computation mode iopt=-1 is used, the values */
+/*           t(k+2),...,t(n-k-1) must be supplied by the user, before */
+/*           entry. see also the restrictions (ier=10). */
+/*   c     : real array of dimension at least (nest). */
+/*           on succesful exit, this array will contain the coefficients */
+/*           c(1),c(2),..,c(n-k-1) in the b-spline representation of s(x) */
+/*   fp    : real. unless ier=10, fp contains the weighted sum of */
+/*           squared residuals of the spline approximation returned. */
+/*   wrk   : real array of dimension at least (m*(k+1)+nest*(7+3*k)). */
+/*           used as working space. if the computation mode iopt=1 is */
+/*           used, the values wrk(1),...,wrk(n) should be left unchanged */
+/*           between subsequent calls. */
+/*   lwrk  : integer. on entry,lwrk must specify the actual dimension of */
+/*           the array wrk as declared in the calling (sub)program.lwrk */
+/*           must not be too small (see wrk). unchanged on exit. */
+/*   iwrk  : integer array of dimension at least (nest). */
+/*           used as working space. if the computation mode iopt=1 is */
+/*           used,the values iwrk(1),...,iwrk(n) should be left unchanged */
+/*           between subsequent calls. */
+/*   ier   : integer. unless the routine detects an error, ier contains a */
+/*           non-positive value on exit, i.e. */
+/*    ier=0  : normal return. the spline returned has a residual sum of */
+/*             squares fp such that abs(fp-s)/s <= tol with tol a relat- */
+/*             ive tolerance set to 0.001 by the program. */
+/*    ier=-1 : normal return. the spline returned is an interpolating */
+/*             spline (fp=0). */
+/*    ier=-2 : normal return. the spline returned is the weighted least- */
+/*             squares polynomial of degree k. in this extreme case fp */
+/*             gives the upper bound fp0 for the smoothing factor s. */
+/*    ier=1  : error. the required storage space exceeds the available */
+/*             storage space, as specified by the parameter nest. */
+/*             probably causes : nest too small. if nest is already */
+/*             large (say nest > m/2), it may also indicate that s is */
+/*             too small */
+/*             the approximation returned is the weighted least-squares */
+/*             spline according to the knots t(1),t(2),...,t(n). (n=nest) */
+/*             the parameter fp gives the corresponding weighted sum of */
+/*             squared residuals (fp>s). */
+/*    ier=2  : error. a theoretically impossible result was found during */
+/*             the iteration proces for finding a smoothing spline with */
+/*             fp = s. probably causes : s too small. */
+/*             there is an approximation returned but the corresponding */
+/*             weighted sum of squared residuals does not satisfy the */
+/*             condition abs(fp-s)/s < tol. */
+/*    ier=3  : error. the maximal number of iterations maxit (set to 20 */
+/*             by the program) allowed for finding a smoothing spline */
+/*             with fp=s has been reached. probably causes : s too small */
+/*             there is an approximation returned but the corresponding */
+/*             weighted sum of squared residuals does not satisfy the */
+/*             condition abs(fp-s)/s < tol. */
+/*    ier=10 : error. on entry, the input data are controlled on validity */
+/*             the following restrictions must be satisfied. */
+/*             -1<=iopt<=1, 1<=k<=5, m>k, nest>2*k+2, w(i)>0,i=1,2,...,m */
+/*             xb<=x(1)<x(2)<...<x(m)<=xe, lwrk>=(k+1)*m+nest*(7+3*k) */
+/*             if iopt=-1: 2*k+2<=n<=min(nest,m+k+1) */
+/*                         xb<t(k+2)<t(k+3)<...<t(n-k-1)<xe */
+/*                       the schoenberg-whitney conditions, i.e. there */
+/*                       must be a subset of data points xx(j) such that */
+/*                         t(j) < xx(j) < t(j+k+1), j=1,2,...,n-k-1 */
+/*             if iopt>=0: s>=0 */
+/*                         if s=0 : nest >= m+k+1 */
+/*             if one of these conditions is found to be violated,control */
+/*             is immediately repassed to the calling program. in that */
+/*             case there is no approximation returned. */
+
+/*  further comments: */
+/*   by means of the parameter s, the user can control the tradeoff */
+/*   between closeness of fit and smoothness of fit of the approximation. */
+/*   if s is too large, the spline will be too smooth and signal will be */
+/*   lost ; if s is too small the spline will pick up too much noise. in */
+/*   the extreme cases the program will return an interpolating spline if */
+/*   s=0 and the weighted least-squares polynomial of degree k if s is */
+/*   very large. between these extremes, a properly chosen s will result */
+/*   in a good compromise between closeness of fit and smoothness of fit. */
+/*   to decide whether an approximation, corresponding to a certain s is */
+/*   satisfactory the user is highly recommended to inspect the fits */
+/*   graphically. */
+/*   recommended values for s depend on the weights w(i). if these are */
+/*   taken as 1/d(i) with d(i) an estimate of the standard deviation of */
+/*   y(i), a good s-value should be found in the range (m-sqrt(2*m),m+ */
+/*   sqrt(2*m)). if nothing is known about the statistical error in y(i) */
+/*   each w(i) can be set equal to one and s determined by trial and */
+/*   error, taking account of the comments above. the best is then to */
+/*   start with a very large value of s ( to determine the least-squares */
+/*   polynomial and the corresponding upper bound fp0 for s) and then to */
+/*   progressively decrease the value of s ( say by a factor 10 in the */
+/*   beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the */
+/*   approximation shows more detail) to obtain closer fits. */
+/*   to economize the search for a good s-value the program provides with */
+/*   different modes of computation. at the first call of the routine, or */
+/*   whenever he wants to restart with the initial set of knots the user */
+/*   must set iopt=0. */
+/*   if iopt=1 the program will continue with the set of knots found at */
+/*   the last call of the routine. this will save a lot of computation */
+/*   time if curfit is called repeatedly for different values of s. */
+/*   the number of knots of the spline returned and their location will */
+/*   depend on the value of s and on the complexity of the shape of the */
+/*   function underlying the data. but, if the computation mode iopt=1 */
+/*   is used, the knots returned may also depend on the s-values at */
+/*   previous calls (if these were smaller). therefore, if after a number */
+/*   of trials with different s-values and iopt=1, the user can finally */
+/*   accept a fit as satisfactory, it may be worthwhile for him to call */
+/*   curfit once more with the selected value for s but now with iopt=0. */
+/*   indeed, curfit may then return an approximation of the same quality */
+/*   of fit but with fewer knots and therefore better if data reduction */
+/*   is also an important objective for the user. */
+
+/*  other subroutines required: */
+/*    fpback,fpbspl,fpchec,fpcurf,fpdisc,fpgivs,fpknot,fprati,fprota */
+
+/*  references: */
+/*   dierckx p. : an algorithm for smoothing, differentiation and integ- */
+/*                ration of experimental data using spline functions, */
+/*                j.comp.appl.maths 1 (1975) 165-184. */
+/*   dierckx p. : a fast algorithm for smoothing data on a rectangular */
+/*                grid while using spline functions, siam j.numer.anal. */
+/*                19 (1982) 1286-1304. */
+/*   dierckx p. : an improved algorithm for curve fitting with spline */
+/*                functions, report tw54, dept. computer science,k.u. */
+/*                leuven, 1981. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*    p.dierckx */
+/*    dept. computer science, k.u. leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : may 1979 */
+/*  latest update : march 1987 */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+/*  we set up the parameters tol and maxit */
+    /* Parameter adjustments */
+    --w;
+    --y;
+    --x;
+    --iwrk;
+    --c__;
+    --t;
+    --wrk;
+
+    /* Function Body */
+    maxit = 20;
+    tol = (float).001;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*k <= 0 || *k > 5) {
+	goto L50;
+    }
+    k1 = *k + 1;
+    k2 = k1 + 1;
+    if (*iopt < -1 || *iopt > 1) {
+	goto L50;
+    }
+    nmin = k1 << 1;
+    if (*m < k1 || *nest < nmin) {
+	goto L50;
+    }
+    lwest = *m * k1 + *nest * (*k * 3 + 7);
+    if (*lwrk < lwest) {
+	goto L50;
+    }
+    if (*xb > x[1] || *xe < x[*m] || w[1] <= (float)0.) {
+	goto L50;
+    }
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (x[i__ - 1] >= x[i__] || w[i__] <= (float)0.) {
+	    goto L50;
+	}
+/* L10: */
+    }
+    if (*iopt >= 0) {
+	goto L30;
+    }
+    if (*n < nmin || *n > *nest) {
+	goto L50;
+    }
+    j = *n;
+    i__1 = k1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	t[i__] = *xb;
+	t[j] = *xe;
+	--j;
+/* L20: */
+    }
+    fpchec_(&x[1], m, &t[1], n, k, ier);
+    if (*ier != 0) {
+	goto L50;
+    } else {
+	goto L40;
+    }
+L30:
+    if (*s < (float)0.) {
+	goto L50;
+    }
+    if (*s == (float)0. && *nest < *m + k1) {
+	goto L50;
+    }
+    *ier = 0;
+/* we partition the working space and determine the spline approximation. */
+L40:
+    ifp = 1;
+    iz = ifp + *nest;
+    ia = iz + *nest;
+    ib = ia + *nest * k1;
+    ig = ib + *nest * k2;
+    iq = ig + *nest * k2;
+    fpcurf_(iopt, &x[1], &y[1], &w[1], m, xb, xe, k, s, nest, &tol, &maxit, &
+	    k1, &k2, n, &t[1], &c__[1], fp, &wrk[ifp], &wrk[iz], &wrk[ia], &
+	    wrk[ib], &wrk[ig], &wrk[iq], &iwrk[1], ier);
+L50:
+    return 0;
+} /* curfit_ */
+
+doublereal dblint_(tx, nx, ty, ny, c__, kx, ky, xb, xe, yb, ye, wrk)
+real *tx;
+integer *nx;
+real *ty;
+integer *ny;
+real *c__;
+integer *kx, *ky;
+real *xb, *xe, *yb, *ye, *wrk;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+    real ret_val;
+
+    /* Local variables */
+    static integer i__, j, l, m;
+    extern /* Subroutine */ int fpintb_();
+    static real res;
+    static integer nkx1, nky1;
+
+/*  function dblint calculates the double integral */
+/*         / xe  / ye */
+/*        |     |      s(x,y) dx dy */
+/*    xb /  yb / */
+/*  with s(x,y) a bivariate spline of degrees kx and ky, given in the */
+/*  b-spline representation. */
+
+/*  calling sequence: */
+/*     aint = dblint(tx,nx,ty,ny,c,kx,ky,xb,xe,yb,ye,wrk) */
+
+/*  input parameters: */
+/*   tx    : real array, length nx, which contains the position of the */
+/*           knots in the x-direction. */
+/*   nx    : integer, giving the total number of knots in the x-direction */
+/*   ty    : real array, length ny, which contains the position of the */
+/*           knots in the y-direction. */
+/*   ny    : integer, giving the total number of knots in the y-direction */
+/*   c     : real array, length (nx-kx-1)*(ny-ky-1), which contains the */
+/*           b-spline coefficients. */
+/*   kx,ky : integer values, giving the degrees of the spline. */
+/*   xb,xe : real values, containing the boundaries of the integration */
+/*   yb,ye   domain. s(x,y) is considered to be identically zero out- */
+/*           side the rectangle (tx(kx+1),tx(nx-kx))*(ty(ky+1),ty(ny-ky)) */
+
+/*  output parameters: */
+/*   aint  : real , containing the double integral of s(x,y). */
+/*   wrk   : real array of dimension at least (nx+ny-kx-ky-2). */
+/*           used as working space. */
+/*           on exit, wrk(i) will contain the integral */
+/*                / xe */
+/*               | ni,kx+1(x) dx , i=1,2,...,nx-kx-1 */
+/*           xb / */
+/*           with ni,kx+1(x) the normalized b-spline defined on */
+/*           the knots tx(i),...,tx(i+kx+1) */
+/*           wrk(j+nx-kx-1) will contain the integral */
+/*                / ye */
+/*               | nj,ky+1(y) dy , j=1,2,...,ny-ky-1 */
+/*           yb / */
+/*           with nj,ky+1(y) the normalized b-spline defined on */
+/*           the knots ty(j),...,ty(j+ky+1) */
+
+/*  other subroutines required: fpintb */
+
+/*  references : */
+/*    gaffney p.w. : the calculation of indefinite integrals of b-splines */
+/*                   j. inst. maths applics 17 (1976) 37-41. */
+/*    dierckx p. : curve and surface fitting with splines, monographs on */
+/*                 numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1989 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --tx;
+    --ty;
+    --wrk;
+    --c__;
+
+    /* Function Body */
+    nkx1 = *nx - *kx - 1;
+    nky1 = *ny - *ky - 1;
+/*  we calculate the integrals of the normalized b-splines ni,kx+1(x) */
+    fpintb_(&tx[1], nx, &wrk[1], &nkx1, xb, xe);
+/*  we calculate the integrals of the normalized b-splines nj,ky+1(y) */
+    fpintb_(&ty[1], ny, &wrk[nkx1 + 1], &nky1, yb, ye);
+/*  calculate the integral of s(x,y) */
+    ret_val = (float)0.;
+    i__1 = nkx1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	res = wrk[i__];
+	if (res == (float)0.) {
+	    goto L200;
+	}
+	m = (i__ - 1) * nky1;
+	l = nkx1;
+	i__2 = nky1;
+	for (j = 1; j <= i__2; ++j) {
+	    ++m;
+	    ++l;
+	    ret_val += res * wrk[l] * c__[m];
+/* L100: */
+	}
+L200:
+	;
+    }
+    return ret_val;
+} /* dblint_ */
+
+doublereal evapol_(tu, nu, tv, nv, c__, rad, x, y)
+real *tu;
+integer *nu;
+real *tv;
+integer *nv;
+real *c__;
+doublereal (*rad) ();
+real *x, *y;
+{
+    /* System generated locals */
+    real ret_val, r__1, r__2;
+
+    /* Builtin functions */
+    double atan2(), sqrt();
+
+    /* Local variables */
+    static real dist;
+    static integer iwrk[2];
+    static real f, r__, u, v;
+    extern /* Subroutine */ int bispev_();
+    static integer ier;
+    static real one, wrk[8];
+
+/*  function program evacir evaluates the function f(x,y) = s(u,v), */
+/*  defined through the transformation */
+/*      x = u*rad(v)*cos(v)    y = u*rad(v)*sin(v) */
+/*  and where s(u,v) is a bicubic spline ( 0<=u<=1 , -pi<=v<=pi ), given */
+/*  in its standard b-spline representation. */
+
+/*  calling sequence: */
+/*     f = evapol(tu,nu,tv,nv,c,rad,x,y) */
+
+/*  input parameters: */
+/*   tu    : real array, length nu, which contains the position of the */
+/*           knots in the u-direction. */
+/*   nu    : integer, giving the total number of knots in the u-direction */
+/*   tv    : real array, length nv, which contains the position of the */
+/*           knots in the v-direction. */
+/*   nv    : integer, giving the total number of knots in the v-direction */
+/*   c     : real array, length (nu-4)*(nv-4), which contains the */
+/*           b-spline coefficients. */
+/*   rad   : real function subprogram, defining the boundary of the */
+/*           approximation domain. must be declared external in the */
+/*           calling (sub)-program */
+/*   x,y   : real values. */
+/*           before entry x and y must be set to the co-ordinates of */
+/*           the point where f(x,y) must be evaluated. */
+
+/*  output parameter: */
+/*   f     : real */
+/*           on exit f contains the value of f(x,y) */
+
+/*  other subroutines required: */
+/*    bispev,fpbisp,fpbspl */
+
+/*  references : */
+/*    de boor c : on calculating with b-splines, j. approximation theory */
+/*                6 (1972) 50-62. */
+/*    cox m.g.  : the numerical evaluation of b-splines, j. inst. maths */
+/*                applics 10 (1972) 134-149. */
+/*    dierckx p. : curve and surface fitting with splines, monographs on */
+/*                 numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1989 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..user specified function */
+/*  ..local scalars.. */
+/*  ..local arrays */
+/*  ..function references */
+/*  .. */
+/*  calculate the (u,v)-coordinates of the given point. */
+    /* Parameter adjustments */
+    --tu;
+    --c__;
+    --tv;
+
+    /* Function Body */
+    one = (float)1.;
+    u = (float)0.;
+    v = (float)0.;
+/* Computing 2nd power */
+    r__1 = *x;
+/* Computing 2nd power */
+    r__2 = *y;
+    dist = r__1 * r__1 + r__2 * r__2;
+    if (dist <= (float)0.) {
+	goto L10;
+    }
+    v = atan2(*y, *x);
+    r__ = (*rad)(&v);
+    if (r__ <= (float)0.) {
+	goto L10;
+    }
+    u = sqrt(dist) / r__;
+    if (u > one) {
+	u = one;
+    }
+/*  evaluate s(u,v) */
+L10:
+    bispev_(&tu[1], nu, &tv[1], nv, &c__[1], &c__3, &c__3, &u, &c__1, &v, &
+	    c__1, &f, wrk, &c__8, iwrk, &c__2, &ier);
+    ret_val = f;
+    return ret_val;
+} /* evapol_ */
+
+/* Subroutine */ int fourco_(t, n, c__, alfa, m, ress, resc, wrk1, wrk2, ier)
+real *t;
+integer *n;
+real *c__, *alfa;
+integer *m;
+real *ress, *resc, *wrk1, *wrk2;
+integer *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static integer i__, j, n4;
+    static real rc, rs;
+    extern /* Subroutine */ int fpbfou_();
+
+/*  subroutine fourco calculates the integrals */
+/*                    /t(n-3) */
+/*    ress(i) =      !        s(x)*sin(alfa(i)*x) dx    and */
+/*              t(4)/ */
+/*                    /t(n-3) */
+/*    resc(i) =      !        s(x)*cos(alfa(i)*x) dx, i=1,...,m, */
+/*              t(4)/ */
+/*  where s(x) denotes a cubic spline which is given in its */
+/*  b-spline representation. */
+
+/*  calling sequence: */
+/*     call fourco(t,n,c,alfa,m,ress,resc,wrk1,wrk2,ier) */
+
+/*  input parameters: */
+/*    t    : real array,length n, containing the knots of s(x). */
+/*    n    : integer, containing the total number of knots. n>=10. */
+/*    c    : real array,length n, containing the b-spline coefficients. */
+/*    alfa : real array,length m, containing the parameters alfa(i). */
+/*    m    : integer, specifying the number of integrals to be computed. */
+/*    wrk1 : real array,length n. used as working space */
+/*    wrk2 : real array,length n. used as working space */
+
+/*  output parameters: */
+/*    ress : real array,length m, containing the integrals ress(i). */
+/*    resc : real array,length m, containing the integrals resc(i). */
+/*    ier  : error flag: */
+/*      ier=0 : normal return. */
+/*      ier=10: invalid input data (see restrictions). */
+
+/*  restrictions: */
+/*    n >= 10 */
+/*    t(4) < t(5) < ... < t(n-4) < t(n-3). */
+/*    t(1) <= t(2) <= t(3) <= t(4). */
+/*    t(n-3) <= t(n-2) <= t(n-1) <= t(n). */
+
+/*  other subroutines required: fpbfou,fpcsin */
+
+/*  references : */
+/*    dierckx p. : calculation of fouriercoefficients of discrete */
+/*                 functions using cubic splines. j. computational */
+/*                 and applied mathematics 3 (1977) 207-209. */
+/*    dierckx p. : curve and surface fitting with splines, monographs on */
+/*                 numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1987 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --wrk2;
+    --wrk1;
+    --c__;
+    --t;
+    --resc;
+    --ress;
+    --alfa;
+
+    /* Function Body */
+    n4 = *n - 4;
+/*  before starting computations a data check is made. in the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*n < 10) {
+	goto L50;
+    }
+    j = *n;
+    for (i__ = 1; i__ <= 3; ++i__) {
+	if (t[i__] > t[i__ + 1]) {
+	    goto L50;
+	}
+	if (t[j] < t[j - 1]) {
+	    goto L50;
+	}
+	--j;
+/* L10: */
+    }
+    i__1 = n4;
+    for (i__ = 4; i__ <= i__1; ++i__) {
+	if (t[i__] >= t[i__ + 1]) {
+	    goto L50;
+	}
+/* L20: */
+    }
+    *ier = 0;
+/*  main loop for the different alfa(i). */
+    i__1 = *m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+/*  calculate the integrals */
+/*    wrk1(j) = integral(nj,4(x)*sin(alfa*x))    and */
+/*    wrk2(j) = integral(nj,4(x)*cos(alfa*x)),  j=1,2,...,n-4, */
+/*  where nj,4(x) denotes the normalised cubic b-spline defined on the */
+/*  knots t(j),t(j+1),...,t(j+4). */
+	fpbfou_(&t[1], n, &alfa[i__], &wrk1[1], &wrk2[1]);
+/*  calculate the integrals ress(i) and resc(i). */
+	rs = (float)0.;
+	rc = (float)0.;
+	i__2 = n4;
+	for (j = 1; j <= i__2; ++j) {
+	    rs += c__[j] * wrk1[j];
+	    rc += c__[j] * wrk2[j];
+/* L30: */
+	}
+	ress[i__] = rs;
+	resc[i__] = rc;
+/* L40: */
+    }
+L50:
+    return 0;
+} /* fourco_ */
+
+/* Subroutine */ int fpader_(t, n, c__, k1, x, l, d__)
+real *t;
+integer *n;
+real *c__;
+integer *k1;
+real *x;
+integer *l;
+real *d__;
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Local variables */
+    static real h__[6];
+    static integer i__, j, j1, j2;
+    static real ak;
+    static integer ik, jj, ki, kj, li, lj, lk;
+    static real fac, one;
+
+/*  subroutine fpader calculates the derivatives */
+/*             (j-1) */
+/*     d(j) = s     (x) , j=1,2,...,k1 */
+/*  of a spline of order k1 at the point t(l)<=x<t(l+1), using the */
+/*  stable recurrence scheme of de boor */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local array.. */
+/*  .. */
+    /* Parameter adjustments */
+    --c__;
+    --t;
+    --d__;
+
+    /* Function Body */
+    one = (float)1.;
+    lk = *l - *k1;
+    i__1 = *k1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	ik = i__ + lk;
+	h__[i__ - 1] = c__[ik];
+/* L100: */
+    }
+    kj = *k1;
+    fac = one;
+    i__1 = *k1;
+    for (j = 1; j <= i__1; ++j) {
+	ki = kj;
+	j1 = j + 1;
+	if (j == 1) {
+	    goto L300;
+	}
+	i__ = *k1;
+	i__2 = *k1;
+	for (jj = j; jj <= i__2; ++jj) {
+	    li = i__ + lk;
+	    lj = li + kj;
+	    h__[i__ - 1] = (h__[i__ - 1] - h__[i__ - 2]) / (t[lj] - t[li]);
+	    --i__;
+/* L200: */
+	}
+L300:
+	i__2 = *k1;
+	for (i__ = j; i__ <= i__2; ++i__) {
+	    d__[i__] = h__[i__ - 1];
+/* L400: */
+	}
+	if (j == *k1) {
+	    goto L600;
+	}
+	i__2 = *k1;
+	for (jj = j1; jj <= i__2; ++jj) {
+	    --ki;
+	    i__ = *k1;
+	    i__3 = *k1;
+	    for (j2 = jj; j2 <= i__3; ++j2) {
+		li = i__ + lk;
+		lj = li + ki;
+		d__[i__] = ((*x - t[li]) * d__[i__] + (t[lj] - *x) * d__[i__ 
+			- 1]) / (t[lj] - t[li]);
+		--i__;
+/* L500: */
+	    }
+	}
+L600:
+	d__[j] = d__[*k1] * fac;
+	ak = (real) (*k1 - j);
+	fac *= ak;
+	--kj;
+/* L700: */
+    }
+    return 0;
+} /* fpader_ */
+
+/* Subroutine */ int fpadno_(maxtr, up, left, right, info, count, merk, jbind,
+	 n1, ier)
+integer *maxtr, *up, *left, *right, *info, *count, *merk, *jbind, *n1, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static logical bool;
+    static integer k, point, niveau;
+    extern /* Subroutine */ int fpfrno_();
+
+/*  subroutine fpadno adds a branch of length n1 to the triply linked */
+/*  tree,the information of which is kept in the arrays up,left,right */
+/*  and info. the information field of the nodes of this new branch is */
+/*  given in the array jbind. in linking the new branch fpadno takes */
+/*  account of the property of the tree that */
+/*    info(k) < info(right(k)) ; info(k) < info(left(k)) */
+/*  if necessary the subroutine calls subroutine fpfrno to collect the */
+/*  free nodes of the tree. if no computer words are available at that */
+/*  moment, the error parameter ier is set to 1. */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..subroutine references.. */
+/*    fpfrno */
+/*  .. */
+    /* Parameter adjustments */
+    --info;
+    --right;
+    --left;
+    --up;
+    --jbind;
+
+    /* Function Body */
+    point = 1;
+    niveau = 1;
+L10:
+    k = left[point];
+    bool = TRUE_;
+L20:
+    if (k == 0) {
+	goto L50;
+    }
+    if ((i__1 = info[k] - jbind[niveau]) < 0) {
+	goto L30;
+    } else if (i__1 == 0) {
+	goto L40;
+    } else {
+	goto L50;
+    }
+L30:
+    point = k;
+    k = right[point];
+    bool = FALSE_;
+    goto L20;
+L40:
+    point = k;
+    ++niveau;
+    goto L10;
+L50:
+    if (niveau > *n1) {
+	goto L90;
+    }
+    ++(*count);
+    if (*count <= *maxtr) {
+	goto L60;
+    }
+    fpfrno_(maxtr, &up[1], &left[1], &right[1], &info[1], &point, merk, n1, 
+	    count, ier);
+    if (*ier != 0) {
+	goto L100;
+    }
+L60:
+    info[*count] = jbind[niveau];
+    left[*count] = 0;
+    right[*count] = k;
+    if (bool) {
+	goto L70;
+    }
+    bool = TRUE_;
+    right[point] = *count;
+    up[*count] = up[point];
+    goto L80;
+L70:
+    up[*count] = point;
+    left[point] = *count;
+L80:
+    point = *count;
+    ++niveau;
+    k = 0;
+    goto L50;
+L90:
+    *ier = 0;
+L100:
+    return 0;
+} /* fpadno_ */
+
+/* Subroutine */ int fpadpo_(idim, t, n, c__, nc, k, cp, np, cc, t1, t2)
+integer *idim;
+real *t;
+integer *n;
+real *c__;
+integer *nc, *k;
+real *cp;
+integer *np;
+real *cc, *t1, *t2;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static integer i__, j, l, k1, l1, n1, n2, ii, jj;
+    extern /* Subroutine */ int fpinst_();
+    static integer nk1, nk2;
+
+/*  given a idim-dimensional spline curve of degree k, in its b-spline */
+/*  representation ( knots t(j),j=1,...,n , b-spline coefficients c(j), */
+/*  j=1,...,nc) and given also a polynomial curve in its b-spline */
+/*  representation ( coefficients cp(j), j=1,...,np), subroutine fpadpo */
+/*  calculates the b-spline representation (coefficients c(j),j=1,...,nc) */
+/*  of the sum of the two curves. */
+
+/*  other subroutine required : fpinst */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --t2;
+    --t1;
+    --t;
+    --cc;
+    --c__;
+    --cp;
+
+    /* Function Body */
+    k1 = *k + 1;
+    nk1 = *n - k1;
+/*  initialization */
+    j = 1;
+    l = 1;
+    i__1 = *idim;
+    for (jj = 1; jj <= i__1; ++jj) {
+	l1 = j;
+	i__2 = k1;
+	for (ii = 1; ii <= i__2; ++ii) {
+	    cc[l1] = cp[l];
+	    ++l1;
+	    ++l;
+/* L10: */
+	}
+	j += *n;
+	l += k1;
+/* L20: */
+    }
+    if (nk1 == k1) {
+	goto L70;
+    }
+    n1 = k1 << 1;
+    j = *n;
+    l = n1;
+    i__1 = k1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	t1[i__] = t[i__];
+	t1[l] = t[j];
+	--l;
+	--j;
+/* L30: */
+    }
+/*  find the b-spline representation of the given polynomial curve */
+/*  according to the given set of knots. */
+    nk2 = nk1 - 1;
+    i__1 = nk2;
+    for (l = k1; l <= i__1; ++l) {
+	l1 = l + 1;
+	j = 1;
+	i__2 = *idim;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    fpinst_(&c__0, &t1[1], &n1, &cc[j], k, &t[l1], &l, &t2[1], &n2, &
+		    cc[j], n);
+	    j += *n;
+/* L40: */
+	}
+	i__2 = n2;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    t1[i__] = t2[i__];
+/* L50: */
+	}
+	n1 = n2;
+/* L60: */
+    }
+/*  find the b-spline representation of the resulting curve. */
+L70:
+    j = 1;
+    i__1 = *idim;
+    for (jj = 1; jj <= i__1; ++jj) {
+	l = j;
+	i__2 = nk1;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    c__[l] = cc[l] + c__[l];
+	    ++l;
+/* L80: */
+	}
+	j += *n;
+/* L90: */
+    }
+    return 0;
+} /* fpadpo_ */
+
+/* Subroutine */ int fpback_(a, z__, n, k, c__, nest)
+real *a, *z__;
+integer *n, *k;
+real *c__;
+integer *nest;
+{
+    /* System generated locals */
+    integer a_dim1, a_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, j, l, m, i1;
+    static real store;
+    static integer k1;
+
+/*  subroutine fpback calculates the solution of the system of */
+/*  equations a*c = z with a a n x n upper triangular matrix */
+/*  of bandwidth k. */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --c__;
+    --z__;
+    a_dim1 = *nest;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+
+    /* Function Body */
+    k1 = *k - 1;
+    c__[*n] = z__[*n] / a[*n + a_dim1];
+    i__ = *n - 1;
+    if (i__ == 0) {
+	goto L30;
+    }
+    i__1 = *n;
+    for (j = 2; j <= i__1; ++j) {
+	store = z__[i__];
+	i1 = k1;
+	if (j <= k1) {
+	    i1 = j - 1;
+	}
+	m = i__;
+	i__2 = i1;
+	for (l = 1; l <= i__2; ++l) {
+	    ++m;
+	    store -= c__[m] * a[i__ + (l + 1) * a_dim1];
+/* L10: */
+	}
+	c__[i__] = store / a[i__ + a_dim1];
+	--i__;
+/* L20: */
+    }
+L30:
+    return 0;
+} /* fpback_ */
+
+/* Subroutine */ int fpbacp_(a, b, z__, n, k, c__, k1, nest)
+real *a, *b, *z__;
+integer *n, *k;
+real *c__;
+integer *k1, *nest;
+{
+    /* System generated locals */
+    integer a_dim1, a_offset, b_dim1, b_offset, i__1, i__2;
+
+    /* Local variables */
+    static integer i__, j, l, i1, l0, l1;
+    static real store;
+    static integer n2;
+
+/*  subroutine fpbacp calculates the solution of the system of equations */
+/*  g * c = z  with g  a n x n upper triangular matrix of the form */
+/*            ! a '   ! */
+/*        g = !   ' b ! */
+/*            ! 0 '   ! */
+/*  with b a n x k matrix and a a (n-k) x (n-k) upper triangular */
+/*  matrix of bandwidth k1. */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --c__;
+    --z__;
+    b_dim1 = *nest;
+    b_offset = 1 + b_dim1 * 1;
+    b -= b_offset;
+    a_dim1 = *nest;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+
+    /* Function Body */
+    n2 = *n - *k;
+    l = *n;
+    i__1 = *k;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	store = z__[l];
+	j = *k + 2 - i__;
+	if (i__ == 1) {
+	    goto L20;
+	}
+	l0 = l;
+	i__2 = *k;
+	for (l1 = j; l1 <= i__2; ++l1) {
+	    ++l0;
+	    store -= c__[l0] * b[l + l1 * b_dim1];
+/* L10: */
+	}
+L20:
+	c__[l] = store / b[l + (j - 1) * b_dim1];
+	--l;
+	if (l == 0) {
+	    goto L80;
+	}
+/* L30: */
+    }
+    i__1 = n2;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	store = z__[i__];
+	l = n2;
+	i__2 = *k;
+	for (j = 1; j <= i__2; ++j) {
+	    ++l;
+	    store -= c__[l] * b[i__ + j * b_dim1];
+/* L40: */
+	}
+	c__[i__] = store;
+/* L50: */
+    }
+    i__ = n2;
+    c__[i__] /= a[i__ + a_dim1];
+    if (i__ == 1) {
+	goto L80;
+    }
+    i__1 = n2;
+    for (j = 2; j <= i__1; ++j) {
+	--i__;
+	store = c__[i__];
+	i1 = *k;
+	if (j <= *k) {
+	    i1 = j - 1;
+	}
+	l = i__;
+	i__2 = i1;
+	for (l0 = 1; l0 <= i__2; ++l0) {
+	    ++l;
+	    store -= c__[l] * a[i__ + (l0 + 1) * a_dim1];
+/* L60: */
+	}
+	c__[i__] = store / a[i__ + a_dim1];
+/* L70: */
+    }
+L80:
+    return 0;
+} /* fpbacp_ */
+
+/* Subroutine */ int fpbfou_(t, n, par, ress, resc)
+real *t;
+integer *n;
+real *par, *ress, *resc;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Builtin functions */
+    double cos(), sin();
+
+    /* Local variables */
+    static real beta, sign, term;
+    static integer i__, j, k;
+    static real delta, c1, c2, f1, f2, f3, quart, s1, s2, hc[5];
+    static integer ic;
+    static real ak, co[5];
+    static integer jj, li, lj;
+    static real rc[3];
+    static integer ll;
+    static real hs[5];
+    static integer is;
+    static real si[5], rs[3];
+    extern /* Subroutine */ int fpcsin_();
+    static integer jp1, jp4, nm3, nm7;
+    static real fac, one;
+    static integer ipj, nmj;
+    static real eps, six, con1, con2;
+
+/*  subroutine fpbfou calculates the integrals */
+/*                    /t(n-3) */
+/*    ress(j) =      !        nj,4(x)*sin(par*x) dx    and */
+/*              t(4)/ */
+/*                    /t(n-3) */
+/*    resc(j) =      !        nj,4(x)*cos(par*x) dx ,  j=1,2,...n-4 */
+/*              t(4)/ */
+/*  where nj,4(x) denotes the cubic b-spline defined on the knots */
+/*  t(j),t(j+1),...,t(j+4). */
+
+/*  calling sequence: */
+/*     call fpbfou(t,n,par,ress,resc) */
+
+/*  input parameters: */
+/*    t    : real array,length n, containing the knots. */
+/*    n    : integer, containing the number of knots. */
+/*    par  : real, containing the value of the parameter par. */
+
+/*  output parameters: */
+/*    ress  : real array,length n, containing the integrals ress(j). */
+/*    resc  : real array,length n, containing the integrals resc(j). */
+
+/*  restrictions: */
+/*    n >= 10, t(4) < t(5) < ... < t(n-4) < t(n-3). */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references.. */
+/*  .. */
+/*  initialization. */
+    /* Parameter adjustments */
+    --resc;
+    --ress;
+    --t;
+
+    /* Function Body */
+    one = (float)1.;
+    six = (float)6.;
+    eps = (float)1e-8;
+    quart = (float).25;
+    con1 = (float).05;
+    con2 = (float)120.;
+    nm3 = *n - 3;
+    nm7 = *n - 7;
+    if (*par != (float)0.) {
+	term = six / *par;
+    }
+    beta = *par * t[4];
+    co[0] = cos(beta);
+    si[0] = sin(beta);
+/*  calculate the integrals ress(j) and resc(j), j=1,2,3 by setting up */
+/*  a divided difference table. */
+    for (j = 1; j <= 3; ++j) {
+	jp1 = j + 1;
+	jp4 = j + 4;
+	beta = *par * t[jp4];
+	co[jp1 - 1] = cos(beta);
+	si[jp1 - 1] = sin(beta);
+	fpcsin_(&t[4], &t[jp4], par, si, co, &si[jp1 - 1], &co[jp1 - 1], &rs[
+		j - 1], &rc[j - 1]);
+	i__ = 5 - j;
+	hs[i__ - 1] = (float)0.;
+	hc[i__ - 1] = (float)0.;
+	i__1 = j;
+	for (jj = 1; jj <= i__1; ++jj) {
+	    ipj = i__ + jj;
+	    hs[ipj - 1] = rs[jj - 1];
+	    hc[ipj - 1] = rc[jj - 1];
+/* L10: */
+	}
+	for (jj = 1; jj <= 3; ++jj) {
+	    if (i__ < jj) {
+		i__ = jj;
+	    }
+	    k = 5;
+	    li = jp4;
+	    for (ll = i__; ll <= 4; ++ll) {
+		lj = li - jj;
+		fac = t[li] - t[lj];
+		hs[k - 1] = (hs[k - 1] - hs[k - 2]) / fac;
+		hc[k - 1] = (hc[k - 1] - hc[k - 2]) / fac;
+		--k;
+		--li;
+/* L20: */
+	    }
+	}
+	ress[j] = hs[4] - hs[3];
+	resc[j] = hc[4] - hc[3];
+/* L30: */
+    }
+    if (nm7 < 4) {
+	goto L160;
+    }
+/*  calculate the integrals ress(j) and resc(j),j=4,5,...,n-7. */
+    i__1 = nm7;
+    for (j = 4; j <= i__1; ++j) {
+	jp4 = j + 4;
+	beta = *par * t[jp4];
+	co[4] = cos(beta);
+	si[4] = sin(beta);
+	delta = t[jp4] - t[j];
+/*  the way of computing ress(j) and resc(j) depends on the value of */
+/*  beta = par*(t(j+4)-t(j)). */
+	beta = delta * *par;
+	if (dabs(beta) <= one) {
+	    goto L60;
+	}
+/*  if !beta! > 1 the integrals are calculated by setting up a divided */
+/*  difference table. */
+	for (k = 1; k <= 5; ++k) {
+	    hs[k - 1] = si[k - 1];
+	    hc[k - 1] = co[k - 1];
+/* L40: */
+	}
+	for (jj = 1; jj <= 3; ++jj) {
+	    k = 5;
+	    li = jp4;
+	    for (ll = jj; ll <= 4; ++ll) {
+		lj = li - jj;
+		fac = *par * (t[li] - t[lj]);
+		hs[k - 1] = (hs[k - 1] - hs[k - 2]) / fac;
+		hc[k - 1] = (hc[k - 1] - hc[k - 2]) / fac;
+		--k;
+		--li;
+/* L50: */
+	    }
+	}
+	s2 = (hs[4] - hs[3]) * term;
+	c2 = (hc[4] - hc[3]) * term;
+	goto L130;
+/*  if !beta! <= 1 the integrals are calculated by evaluating a series */
+/*  expansion. */
+L60:
+	f3 = (float)0.;
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    ipj = i__ + j;
+	    hs[i__ - 1] = *par * (t[ipj] - t[j]);
+	    hc[i__ - 1] = hs[i__ - 1];
+	    f3 += hs[i__ - 1];
+/* L70: */
+	}
+	f3 *= con1;
+	c1 = quart;
+	s1 = f3;
+	if (dabs(f3) <= eps) {
+	    goto L120;
+	}
+	sign = one;
+	fac = con2;
+	k = 5;
+	is = 0;
+	for (ic = 1; ic <= 20; ++ic) {
+	    ++k;
+	    ak = (real) k;
+	    fac *= ak;
+	    f1 = (float)0.;
+	    f3 = (float)0.;
+	    for (i__ = 1; i__ <= 4; ++i__) {
+		f1 += hc[i__ - 1];
+		f2 = f1 * hs[i__ - 1];
+		hc[i__ - 1] = f2;
+		f3 += f2;
+/* L80: */
+	    }
+	    f3 = f3 * six / fac;
+	    if (is == 0) {
+		goto L90;
+	    }
+	    is = 0;
+	    s1 += f3 * sign;
+	    goto L100;
+L90:
+	    sign = -sign;
+	    is = 1;
+	    c1 += f3 * sign;
+L100:
+	    if (dabs(f3) <= eps) {
+		goto L120;
+	    }
+/* L110: */
+	}
+L120:
+	s2 = delta * (co[0] * s1 + si[0] * c1);
+	c2 = delta * (co[0] * c1 - si[0] * s1);
+L130:
+	ress[j] = s2;
+	resc[j] = c2;
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    co[i__ - 1] = co[i__];
+	    si[i__ - 1] = si[i__];
+/* L140: */
+	}
+/* L150: */
+    }
+/*  calculate the integrals ress(j) and resc(j),j=n-6,n-5,n-4 by setting */
+/*  up a divided difference table. */
+L160:
+    for (j = 1; j <= 3; ++j) {
+	nmj = nm3 - j;
+	i__ = 5 - j;
+	fpcsin_(&t[nm3], &t[nmj], par, &si[3], &co[3], &si[i__ - 2], &co[i__ 
+		- 2], &rs[j - 1], &rc[j - 1]);
+	hs[i__ - 1] = (float)0.;
+	hc[i__ - 1] = (float)0.;
+	i__1 = j;
+	for (jj = 1; jj <= i__1; ++jj) {
+	    ipj = i__ + jj;
+	    hc[ipj - 1] = rc[jj - 1];
+	    hs[ipj - 1] = rs[jj - 1];
+/* L170: */
+	}
+	for (jj = 1; jj <= 3; ++jj) {
+	    if (i__ < jj) {
+		i__ = jj;
+	    }
+	    k = 5;
+	    li = nmj;
+	    for (ll = i__; ll <= 4; ++ll) {
+		lj = li + jj;
+		fac = t[lj] - t[li];
+		hs[k - 1] = (hs[k - 2] - hs[k - 1]) / fac;
+		hc[k - 1] = (hc[k - 2] - hc[k - 1]) / fac;
+		--k;
+		++li;
+/* L180: */
+	    }
+	}
+	ress[nmj] = hs[3] - hs[4];
+	resc[nmj] = hc[3] - hc[4];
+/* L190: */
+    }
+    return 0;
+} /* fpbfou_ */
+
+/* Subroutine */ int fpbisp_(tx, nx, ty, ny, c__, kx, ky, x, mx, y, my, z__, 
+	wx, wy, lx, ly)
+real *tx;
+integer *nx;
+real *ty;
+integer *ny;
+real *c__;
+integer *kx, *ky;
+real *x;
+integer *mx;
+real *y;
+integer *my;
+real *z__, *wx, *wy;
+integer *lx, *ly;
+{
+    /* System generated locals */
+    integer wx_dim1, wx_offset, wy_dim1, wy_offset, i__1, i__2, i__3, i__4;
+
+    /* Local variables */
+    static real h__[6];
+    static integer i__, j, l, m, i1, j1, l1, l2;
+    static real tb, te, sp;
+    extern /* Subroutine */ int fpbspl_();
+    static integer kx1, ky1;
+    static real arg;
+    static integer nkx1, nky1;
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..subroutine references.. */
+/*    fpbspl */
+/*  .. */
+    /* Parameter adjustments */
+    --tx;
+    --ty;
+    --c__;
+    --lx;
+    wx_dim1 = *mx;
+    wx_offset = 1 + wx_dim1 * 1;
+    wx -= wx_offset;
+    --x;
+    --ly;
+    wy_dim1 = *my;
+    wy_offset = 1 + wy_dim1 * 1;
+    wy -= wy_offset;
+    --z__;
+    --y;
+
+    /* Function Body */
+    kx1 = *kx + 1;
+    nkx1 = *nx - kx1;
+    tb = tx[kx1];
+    te = tx[nkx1 + 1];
+    l = kx1;
+    l1 = l + 1;
+    i__1 = *mx;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	arg = x[i__];
+	if (arg < tb) {
+	    arg = tb;
+	}
+	if (arg > te) {
+	    arg = te;
+	}
+L10:
+	if (arg < tx[l1] || l == nkx1) {
+	    goto L20;
+	}
+	l = l1;
+	l1 = l + 1;
+	goto L10;
+L20:
+	fpbspl_(&tx[1], nx, kx, &arg, &l, h__);
+	lx[i__] = l - kx1;
+	i__2 = kx1;
+	for (j = 1; j <= i__2; ++j) {
+	    wx[i__ + j * wx_dim1] = h__[j - 1];
+/* L30: */
+	}
+/* L40: */
+    }
+    ky1 = *ky + 1;
+    nky1 = *ny - ky1;
+    tb = ty[ky1];
+    te = ty[nky1 + 1];
+    l = ky1;
+    l1 = l + 1;
+    i__1 = *my;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	arg = y[i__];
+	if (arg < tb) {
+	    arg = tb;
+	}
+	if (arg > te) {
+	    arg = te;
+	}
+L50:
+	if (arg < ty[l1] || l == nky1) {
+	    goto L60;
+	}
+	l = l1;
+	l1 = l + 1;
+	goto L50;
+L60:
+	fpbspl_(&ty[1], ny, ky, &arg, &l, h__);
+	ly[i__] = l - ky1;
+	i__2 = ky1;
+	for (j = 1; j <= i__2; ++j) {
+	    wy[i__ + j * wy_dim1] = h__[j - 1];
+/* L70: */
+	}
+/* L80: */
+    }
+    m = 0;
+    i__1 = *mx;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	l = lx[i__] * nky1;
+	i__2 = kx1;
+	for (i1 = 1; i1 <= i__2; ++i1) {
+	    h__[i1 - 1] = wx[i__ + i1 * wx_dim1];
+/* L90: */
+	}
+	i__2 = *my;
+	for (j = 1; j <= i__2; ++j) {
+	    l1 = l + ly[j];
+	    sp = (float)0.;
+	    i__3 = kx1;
+	    for (i1 = 1; i1 <= i__3; ++i1) {
+		l2 = l1;
+		i__4 = ky1;
+		for (j1 = 1; j1 <= i__4; ++j1) {
+		    ++l2;
+		    sp += c__[l2] * h__[i1 - 1] * wy[j + j1 * wy_dim1];
+/* L100: */
+		}
+		l1 += nky1;
+/* L110: */
+	    }
+	    ++m;
+	    z__[m] = sp;
+/* L120: */
+	}
+/* L130: */
+    }
+    return 0;
+} /* fpbisp_ */
+
+/* Subroutine */ int fpbspl_(t, n, k, x, l, h__)
+real *t;
+integer *n, *k;
+real *x;
+integer *l;
+real *h__;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static real f;
+    static integer i__, j;
+    static real hh[5];
+    static integer li, lj;
+    static real one;
+
+/*  subroutine fpbspl evaluates the (k+1) non-zero b-splines of */
+/*  degree k at t(l) <= x < t(l+1) using the stable recurrence */
+/*  relation of de boor and cox. */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  .. */
+    /* Parameter adjustments */
+    --t;
+    --h__;
+
+    /* Function Body */
+    one = (float)1.;
+    h__[1] = one;
+    i__1 = *k;
+    for (j = 1; j <= i__1; ++j) {
+	i__2 = j;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    hh[i__ - 1] = h__[i__];
+/* L10: */
+	}
+	h__[1] = (float)0.;
+	i__2 = j;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    li = *l + i__;
+	    lj = li - j;
+	    f = hh[i__ - 1] / (t[li] - t[lj]);
+	    h__[i__] += f * (t[li] - *x);
+	    h__[i__ + 1] = f * (*x - t[lj]);
+/* L20: */
+	}
+    }
+    return 0;
+} /* fpbspl_ */
+
+/* Subroutine */ int fpchec_(x, m, t, n, k, ier)
+real *x;
+integer *m;
+real *t;
+integer *n, *k, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__, j, l, k1, k2;
+    static real tj, tl;
+    static integer nk1, nk2, nk3;
+
+/*  subroutine fpchec verifies the number and the position of the knots */
+/*  t(j),j=1,2,...,n of a spline of degree k, in relation to the number */
+/*  and the position of the data points x(i),i=1,2,...,m. if all of the */
+/*  following conditions are fulfilled, the error parameter ier is set */
+/*  to zero. if one of the conditions is violated ier is set to ten. */
+/*      1) k+1 <= n-k-1 <= m */
+/*      2) t(1) <= t(2) <= ... <= t(k+1) */
+/*         t(n-k) <= t(n-k+1) <= ... <= t(n) */
+/*      3) t(k+1) < t(k+2) < ... < t(n-k) */
+/*      4) t(k+1) <= x(i) <= t(n-k) */
+/*      5) the conditions specified by schoenberg and whitney must hold */
+/*         for at least one subset of data points, i.e. there must be a */
+/*         subset of data points y(j) such that */
+/*             t(j) < y(j) < t(j+k+1), j=1,2,...,n-k-1 */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --x;
+    --t;
+
+    /* Function Body */
+    k1 = *k + 1;
+    k2 = k1 + 1;
+    nk1 = *n - k1;
+    nk2 = nk1 + 1;
+    *ier = 10;
+/*  check condition no 1 */
+    if (nk1 < k1 || nk1 > *m) {
+	goto L80;
+    }
+/*  check condition no 2 */
+    j = *n;
+    i__1 = *k;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (t[i__] > t[i__ + 1]) {
+	    goto L80;
+	}
+	if (t[j] < t[j - 1]) {
+	    goto L80;
+	}
+	--j;
+/* L20: */
+    }
+/*  check condition no 3 */
+    i__1 = nk2;
+    for (i__ = k2; i__ <= i__1; ++i__) {
+	if (t[i__] <= t[i__ - 1]) {
+	    goto L80;
+	}
+/* L30: */
+    }
+/*  check condition no 4 */
+    if (x[1] < t[k1] || x[*m] > t[nk2]) {
+	goto L80;
+    }
+/*  check condition no 5 */
+    if (x[1] >= t[k2] || x[*m] <= t[nk1]) {
+	goto L80;
+    }
+    i__ = 1;
+    l = k2;
+    nk3 = nk1 - 1;
+    if (nk3 < 2) {
+	goto L70;
+    }
+    i__1 = nk3;
+    for (j = 2; j <= i__1; ++j) {
+	tj = t[j];
+	++l;
+	tl = t[l];
+L40:
+	++i__;
+	if (i__ >= *m) {
+	    goto L80;
+	}
+	if (x[i__] <= tj) {
+	    goto L40;
+	}
+	if (x[i__] >= tl) {
+	    goto L80;
+	}
+/* L60: */
+    }
+L70:
+    *ier = 0;
+L80:
+    return 0;
+} /* fpchec_ */
+
+/* Subroutine */ int fpched_(x, m, t, n, k, ib, ie, ier)
+real *x;
+integer *m;
+real *t;
+integer *n, *k, *ib, *ie, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__, j, l, k1, k2, jj;
+    static real tj, tl;
+    static integer ib1, ie1, nk1, nk2, nk3;
+
+/*  subroutine fpched verifies the number and the position of the knots */
+/*  t(j),j=1,2,...,n of a spline of degree k,with ib derative constraints */
+/*  at x(1) and ie constraints at x(m), in relation to the number and */
+/*  the position of the data points x(i),i=1,2,...,m. if all of the */
+/*  following conditions are fulfilled, the error parameter ier is set */
+/*  to zero. if one of the conditions is violated ier is set to ten. */
+/*      1) k+1 <= n-k-1 <= m + max(0,ib-1) + max(0,ie-1) */
+/*      2) t(1) <= t(2) <= ... <= t(k+1) */
+/*         t(n-k) <= t(n-k+1) <= ... <= t(n) */
+/*      3) t(k+1) < t(k+2) < ... < t(n-k) */
+/*      4) t(k+1) <= x(i) <= t(n-k) */
+/*      5) the conditions specified by schoenberg and whitney must hold */
+/*         for at least one subset of data points, i.e. there must be a */
+/*         subset of data points y(j) such that */
+/*             t(j) < y(j) < t(j+k+1), j=1+ib1,2+ib1,...,n-k-1-ie1 */
+/*               with ib1 = max(0,ib-1), ie1 = max(0,ie-1) */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --x;
+    --t;
+
+    /* Function Body */
+    k1 = *k + 1;
+    k2 = k1 + 1;
+    nk1 = *n - k1;
+    nk2 = nk1 + 1;
+    ib1 = *ib - 1;
+    if (ib1 < 0) {
+	ib1 = 0;
+    }
+    ie1 = *ie - 1;
+    if (ie1 < 0) {
+	ie1 = 0;
+    }
+    *ier = 10;
+/*  check condition no 1 */
+    if (nk1 < k1 || nk1 > *m + ib1 + ie1) {
+	goto L80;
+    }
+/*  check condition no 2 */
+    j = *n;
+    i__1 = *k;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (t[i__] > t[i__ + 1]) {
+	    goto L80;
+	}
+	if (t[j] < t[j - 1]) {
+	    goto L80;
+	}
+	--j;
+/* L20: */
+    }
+/*  check condition no 3 */
+    i__1 = nk2;
+    for (i__ = k2; i__ <= i__1; ++i__) {
+	if (t[i__] <= t[i__ - 1]) {
+	    goto L80;
+	}
+/* L30: */
+    }
+/*  check condition no 4 */
+    if (x[1] < t[k1] || x[*m] > t[nk2]) {
+	goto L80;
+    }
+/*  check condition no 5 */
+    if (x[1] >= t[k2] || x[*m] <= t[nk1]) {
+	goto L80;
+    }
+    i__ = 1;
+    jj = ib1 + 2;
+    l = jj + *k;
+    nk3 = nk1 - 1 - ie1;
+    if (nk3 < jj) {
+	goto L70;
+    }
+    i__1 = nk3;
+    for (j = jj; j <= i__1; ++j) {
+	tj = t[j];
+	++l;
+	tl = t[l];
+L40:
+	++i__;
+	if (i__ >= *m) {
+	    goto L80;
+	}
+	if (x[i__] <= tj) {
+	    goto L40;
+	}
+	if (x[i__] >= tl) {
+	    goto L80;
+	}
+/* L60: */
+    }
+L70:
+    *ier = 0;
+L80:
+    return 0;
+} /* fpched_ */
+
+/* Subroutine */ int fpchep_(x, m, t, n, k, ier)
+real *x;
+integer *m;
+real *t;
+integer *n, *k, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static integer i__, j, l, i1, i2, j1, k1, k2, l1, l2, m1, mm;
+    static real tj, tl, xi;
+    static integer nk1, nk2;
+    static real per;
+
+/*  subroutine fpchep verifies the number and the position of the knots */
+/*  t(j),j=1,2,...,n of a periodic spline of degree k, in relation to */
+/*  the number and the position of the data points x(i),i=1,2,...,m. */
+/*  if all of the following conditions are fulfilled, ier is set */
+/*  to zero. if one of the conditions is violated ier is set to ten. */
+/*      1) k+1 <= n-k-1 <= m+k-1 */
+/*      2) t(1) <= t(2) <= ... <= t(k+1) */
+/*         t(n-k) <= t(n-k+1) <= ... <= t(n) */
+/*      3) t(k+1) < t(k+2) < ... < t(n-k) */
+/*      4) t(k+1) <= x(i) <= t(n-k) */
+/*      5) the conditions specified by schoenberg and whitney must hold */
+/*         for at least one subset of data points, i.e. there must be a */
+/*         subset of data points y(j) such that */
+/*             t(j) < y(j) < t(j+k+1), j=k+1,...,n-k-1 */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --x;
+    --t;
+
+    /* Function Body */
+    k1 = *k + 1;
+    k2 = k1 + 1;
+    nk1 = *n - k1;
+    nk2 = nk1 + 1;
+    m1 = *m - 1;
+    *ier = 10;
+/*  check condition no 1 */
+    if (nk1 < k1 || *n > *m + (*k << 1)) {
+	goto L130;
+    }
+/*  check condition no 2 */
+    j = *n;
+    i__1 = *k;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (t[i__] > t[i__ + 1]) {
+	    goto L130;
+	}
+	if (t[j] < t[j - 1]) {
+	    goto L130;
+	}
+	--j;
+/* L20: */
+    }
+/*  check condition no 3 */
+    i__1 = nk2;
+    for (i__ = k2; i__ <= i__1; ++i__) {
+	if (t[i__] <= t[i__ - 1]) {
+	    goto L130;
+	}
+/* L30: */
+    }
+/*  check condition no 4 */
+    if (x[1] < t[k1] || x[*m] > t[nk2]) {
+	goto L130;
+    }
+/*  check condition no 5 */
+    l1 = k1;
+    l2 = 1;
+    i__1 = *m;
+    for (l = 1; l <= i__1; ++l) {
+	xi = x[l];
+L40:
+	if (xi < t[l1 + 1] || l == nk1) {
+	    goto L50;
+	}
+	++l1;
+	++l2;
+	if (l2 > k1) {
+	    goto L60;
+	}
+	goto L40;
+L50:
+	;
+    }
+    l = *m;
+L60:
+    per = t[nk2] - t[k1];
+    i__1 = l;
+    for (i1 = 2; i1 <= i__1; ++i1) {
+	i__ = i1 - 1;
+	mm = i__ + m1;
+	i__2 = nk1;
+	for (j = k1; j <= i__2; ++j) {
+	    tj = t[j];
+	    j1 = j + k1;
+	    tl = t[j1];
+L70:
+	    ++i__;
+	    if (i__ > mm) {
+		goto L120;
+	    }
+	    i2 = i__ - m1;
+	    if (i2 <= 0) {
+		goto L80;
+	    } else {
+		goto L90;
+	    }
+L80:
+	    xi = x[i__];
+	    goto L100;
+L90:
+	    xi = x[i2] + per;
+L100:
+	    if (xi <= tj) {
+		goto L70;
+	    }
+	    if (xi >= tl) {
+		goto L120;
+	    }
+/* L110: */
+	}
+	*ier = 0;
+	goto L130;
+L120:
+	;
+    }
+L130:
+    return 0;
+} /* fpchep_ */
+
+/* Subroutine */ int fpclos_(iopt, idim, m, u, mx, x, w, k, s, nest, tol, 
+	maxit, k1, k2, n, t, nc, c__, fp, fpint, z__, a1, a2, b, g1, g2, q, 
+	nrdata, ier)
+integer *iopt, *idim, *m;
+real *u;
+integer *mx;
+real *x, *w;
+integer *k;
+real *s;
+integer *nest;
+real *tol;
+integer *maxit, *k1, *k2, *n;
+real *t;
+integer *nc;
+real *c__, *fp, *fpint, *z__, *a1, *a2, *b, *g1, *g2, *q;
+integer *nrdata, *ier;
+{
+    /* System generated locals */
+    integer a1_dim1, a1_offset, a2_dim1, a2_offset, b_dim1, b_offset, g1_dim1,
+	     g1_offset, g2_dim1, g2_offset, q_dim1, q_offset, i__1, i__2, 
+	    i__3, i__4, i__5;
+    real r__1;
+
+    /* Local variables */
+    static real half;
+    static integer jper, nmin, iter, nmax;
+    static real fpms, term, pinv, h__[6];
+    static integer i__, j, l;
+    static real p, fpold, fpart, d1, f1, f2, f3, store;
+    static integer i1, i2;
+    static real p1, p2, p3;
+    static integer i3, j1, j2, k3, l0, l1, l5, m1, nplus, nrint, n7, n8;
+    static real h1[7], h2[6];
+    static integer n10, n11, ij, ik, jj, jk, kk, mm;
+    extern /* Subroutine */ int fpbacp_();
+    static integer it;
+    static real ui, wi, rn, xi[10];
+    extern /* Subroutine */ int fpdisc_();
+    extern doublereal fprati_();
+    extern /* Subroutine */ int fpbspl_(), fprota_(), fpgivs_(), fpknot_();
+    static real fp0;
+    static integer kk1, nk1, nk2;
+    static real acc, fac, one, cos__, per, sin__;
+    static integer new__;
+    static real piv;
+    static integer ich1, ich3;
+    static real con1, con4, con9;
+    static integer npl1;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpbacp,fpbspl,fpgivs,fpdisc,fpknot,fprota */
+/*  .. */
+/*  set constants */
+    /* Parameter adjustments */
+    --w;
+    --u;
+    --x;
+    --nrdata;
+    a2_dim1 = *nest;
+    a2_offset = 1 + a2_dim1 * 1;
+    a2 -= a2_offset;
+    --fpint;
+    --t;
+    q_dim1 = *m;
+    q_offset = 1 + q_dim1 * 1;
+    q -= q_offset;
+    g2_dim1 = *nest;
+    g2_offset = 1 + g2_dim1 * 1;
+    g2 -= g2_offset;
+    a1_dim1 = *nest;
+    a1_offset = 1 + a1_dim1 * 1;
+    a1 -= a1_offset;
+    g1_dim1 = *nest;
+    g1_offset = 1 + g1_dim1 * 1;
+    g1 -= g1_offset;
+    b_dim1 = *nest;
+    b_offset = 1 + b_dim1 * 1;
+    b -= b_offset;
+    --z__;
+    --c__;
+
+    /* Function Body */
+    one = (float)1.;
+    con1 = (float).1;
+    con9 = (float).9;
+    con4 = (float).04;
+    half = (float).5;
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  part 1: determination of the number of knots and their position     c */
+/*  **************************************************************      c */
+/*  given a set of knots we compute the least-squares closed curve      c */
+/*  sinf(u). if the sum f(p=inf) <= s we accept the choice of knots.    c */
+/*  if iopt=-1 sinf(u) is the requested curve                           c */
+/*  if iopt=0 or iopt=1 we check whether we can accept the knots:       c */
+/*    if fp <=s we will continue with the current set of knots.         c */
+/*    if fp > s we will increase the number of knots and compute the    c */
+/*       corresponding least-squares curve until finally fp<=s.         c */
+/*  the initial choice of knots depends on the value of s and iopt.     c */
+/*    if s=0 we have spline interpolation; in that case the number of   c */
+/*    knots equals nmax = m+2*k.                                        c */
+/*    if s > 0 and                                                      c */
+/*      iopt=0 we first compute the least-squares polynomial curve of   c */
+/*      degree k; n = nmin = 2*k+2. since s(u) must be periodic we      c */
+/*      find that s(u) reduces to a fixed point.                        c */
+/*      iopt=1 we start with the set of knots found at the last         c */
+/*      call of the routine, except for the case that s > fp0; then     c */
+/*      we compute directly the least-squares polynomial curve.         c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+    m1 = *m - 1;
+    kk = *k;
+    kk1 = *k1;
+    k3 = *k * 3 + 1;
+    nmin = *k1 << 1;
+/*  determine the length of the period of the splines. */
+    per = u[*m] - u[1];
+    if (*iopt < 0) {
+	goto L50;
+    }
+/*  calculation of acc, the absolute tolerance for the root of f(p)=s. */
+    acc = *tol * *s;
+/*  determine nmax, the number of knots for periodic spline interpolation */
+    nmax = *m + (*k << 1);
+    if (*s > (float)0. || nmax == nmin) {
+	goto L30;
+    }
+/*  if s=0, s(u) is an interpolating curve. */
+    *n = nmax;
+/*  test whether the required storage space exceeds the available one. */
+    if (*n > *nest) {
+	goto L620;
+    }
+/*  find the position of the interior knots in case of interpolation. */
+L5:
+    if (*k / 2 << 1 == *k) {
+	goto L20;
+    }
+    i__1 = m1;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	j = i__ + *k;
+	t[j] = u[i__];
+/* L10: */
+    }
+    if (*s > (float)0.) {
+	goto L50;
+    }
+    kk = *k - 1;
+    kk1 = *k;
+    if (kk > 0) {
+	goto L50;
+    }
+    t[1] = t[*m] - per;
+    t[2] = u[1];
+    t[*m + 1] = u[*m];
+    t[*m + 2] = t[3] + per;
+    jj = 0;
+    i__1 = m1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	j = i__;
+	i__2 = *idim;
+	for (j1 = 1; j1 <= i__2; ++j1) {
+	    ++jj;
+	    c__[j] = x[jj];
+	    j += *n;
+/* L12: */
+	}
+/* L15: */
+    }
+    jj = 1;
+    j = *m;
+    i__1 = *idim;
+    for (j1 = 1; j1 <= i__1; ++j1) {
+	c__[j] = c__[jj];
+	j += *n;
+	jj += *n;
+/* L17: */
+    }
+    *fp = (float)0.;
+    fpint[*n] = fp0;
+    fpint[*n - 1] = (float)0.;
+    nrdata[*n] = 0;
+    goto L630;
+L20:
+    i__1 = m1;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	j = i__ + *k;
+	t[j] = (u[i__] + u[i__ - 1]) * half;
+/* L25: */
+    }
+    goto L50;
+/*  if s > 0 our initial choice depends on the value of iopt. */
+/*  if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares */
+/*  polynomial curve. (i.e. a constant point). */
+/*  if iopt=1 and fp0>s we start computing the least-squares closed */
+/*  curve according the set of knots found at the last call of the */
+/*  routine. */
+L30:
+    if (*iopt == 0) {
+	goto L35;
+    }
+    if (*n == nmin) {
+	goto L35;
+    }
+    fp0 = fpint[*n];
+    fpold = fpint[*n - 1];
+    nplus = nrdata[*n];
+    if (fp0 > *s) {
+	goto L50;
+    }
+/*  the case that s(u) is a fixed point is treated separetely. */
+/*  fp0 denotes the corresponding sum of squared residuals. */
+L35:
+    fp0 = (float)0.;
+    d1 = (float)0.;
+    i__1 = *idim;
+    for (j = 1; j <= i__1; ++j) {
+	z__[j] = (float)0.;
+/* L37: */
+    }
+    jj = 0;
+    i__1 = m1;
+    for (it = 1; it <= i__1; ++it) {
+	wi = w[it];
+	fpgivs_(&wi, &d1, &cos__, &sin__);
+	i__2 = *idim;
+	for (j = 1; j <= i__2; ++j) {
+	    ++jj;
+	    fac = wi * x[jj];
+	    fprota_(&cos__, &sin__, &fac, &z__[j]);
+/* Computing 2nd power */
+	    r__1 = fac;
+	    fp0 += r__1 * r__1;
+/* L40: */
+	}
+/* L45: */
+    }
+    i__1 = *idim;
+    for (j = 1; j <= i__1; ++j) {
+	z__[j] /= d1;
+/* L47: */
+    }
+/*  test whether that fixed point is a solution of our problem. */
+    fpms = fp0 - *s;
+    if (fpms < acc || nmax == nmin) {
+	goto L640;
+    }
+    fpold = fp0;
+/*  test whether the required storage space exceeds the available one. */
+    if (*n >= *nest) {
+	goto L620;
+    }
+/*  start computing the least-squares closed curve with one */
+/*  interior knot. */
+    nplus = 1;
+    *n = nmin + 1;
+    mm = (*m + 1) / 2;
+    t[*k2] = u[mm];
+    nrdata[1] = mm - 2;
+    nrdata[2] = m1 - mm;
+/*  main loop for the different sets of knots. m is a save upper */
+/*  bound for the number of trials. */
+L50:
+    i__1 = *m;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  find nrint, the number of knot intervals. */
+	nrint = *n - nmin + 1;
+/*  find the position of the additional knots which are needed for */
+/*  the b-spline representation of s(u). if we take */
+/*      t(k+1) = u(1), t(n-k) = u(m) */
+/*      t(k+1-j) = t(n-k-j) - per, j=1,2,...k */
+/*      t(n-k+j) = t(k+1+j) + per, j=1,2,...k */
+/*  then s(u) will be a smooth closed curve if the b-spline */
+/*  coefficients satisfy the following conditions */
+/*      c((i-1)*n+n7+j) = c((i-1)*n+j), j=1,...k,i=1,2,...,idim (**) */
+/*  with n7=n-2*k-1. */
+	t[*k1] = u[1];
+	nk1 = *n - *k1;
+	nk2 = nk1 + 1;
+	t[nk2] = u[*m];
+	i__2 = *k;
+	for (j = 1; j <= i__2; ++j) {
+	    i1 = nk2 + j;
+	    i2 = nk2 - j;
+	    j1 = *k1 + j;
+	    j2 = *k1 - j;
+	    t[i1] = t[j1] + per;
+	    t[j2] = t[i2] - per;
+/* L60: */
+	}
+/*  compute the b-spline coefficients of the least-squares closed curve */
+/*  sinf(u). the observation matrix a is built up row by row while */
+/*  taking into account condition (**) and is reduced to triangular */
+/*  form by givens transformations . */
+/*  at the same time fp=f(p=inf) is computed. */
+/*  the n7 x n7 triangularised upper matrix a has the form */
+/*            ! a1 '    ! */
+/*        a = !    ' a2 ! */
+/*            ! 0  '    ! */
+/*  with a2 a n7 x k matrix and a1 a n10 x n10 upper triangular */
+/*  matrix of bandwith k+1 ( n10 = n7-k). */
+/*  initialization. */
+	i__2 = *nc;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    z__[i__] = (float)0.;
+/* L65: */
+	}
+	i__2 = nk1;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    i__3 = kk1;
+	    for (j = 1; j <= i__3; ++j) {
+		a1[i__ + j * a1_dim1] = (float)0.;
+/* L70: */
+	    }
+	}
+	n7 = nk1 - *k;
+	n10 = n7 - kk;
+	jper = 0;
+	*fp = (float)0.;
+	l = *k1;
+	jj = 0;
+	i__3 = m1;
+	for (it = 1; it <= i__3; ++it) {
+/*  fetch the current data point u(it),x(it) */
+	    ui = u[it];
+	    wi = w[it];
+	    i__2 = *idim;
+	    for (j = 1; j <= i__2; ++j) {
+		++jj;
+		xi[j - 1] = x[jj] * wi;
+/* L75: */
+	    }
+/*  search for knot interval t(l) <= ui < t(l+1). */
+L80:
+	    if (ui < t[l + 1]) {
+		goto L85;
+	    }
+	    ++l;
+	    goto L80;
+/*  evaluate the (k+1) non-zero b-splines at ui and store them in q. */
+L85:
+	    fpbspl_(&t[1], n, k, &ui, &l, h__);
+	    i__2 = *k1;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		q[it + i__ * q_dim1] = h__[i__ - 1];
+		h__[i__ - 1] *= wi;
+/* L90: */
+	    }
+	    l5 = l - *k1;
+/*  test whether the b-splines nj,k+1(u),j=1+n7,...nk1 are all zero at ui */
+	    if (l5 < n10) {
+		goto L285;
+	    }
+	    if (jper != 0) {
+		goto L160;
+	    }
+/*  initialize the matrix a2. */
+	    i__2 = n7;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		i__4 = kk;
+		for (j = 1; j <= i__4; ++j) {
+		    a2[i__ + j * a2_dim1] = (float)0.;
+/* L95: */
+		}
+	    }
+	    jk = n10 + 1;
+	    i__4 = kk;
+	    for (i__ = 1; i__ <= i__4; ++i__) {
+		ik = jk;
+		i__2 = kk1;
+		for (j = 1; j <= i__2; ++j) {
+		    if (ik <= 0) {
+			goto L105;
+		    }
+		    a2[ik + i__ * a2_dim1] = a1[ik + j * a1_dim1];
+		    --ik;
+/* L100: */
+		}
+L105:
+		++jk;
+/* L110: */
+	    }
+	    jper = 1;
+/*  if one of the b-splines nj,k+1(u),j=n7+1,...nk1 is not zero at ui */
+/*  we take account of condition (**) for setting up the new row */
+/*  of the observation matrix a. this row is stored in the arrays h1 */
+/*  (the part with respect to a1) and h2 (the part with */
+/*  respect to a2). */
+L160:
+	    i__4 = kk;
+	    for (i__ = 1; i__ <= i__4; ++i__) {
+		h1[i__ - 1] = (float)0.;
+		h2[i__ - 1] = (float)0.;
+/* L170: */
+	    }
+	    h1[kk1 - 1] = (float)0.;
+	    j = l5 - n10;
+	    i__4 = kk1;
+	    for (i__ = 1; i__ <= i__4; ++i__) {
+		++j;
+		l0 = j;
+L180:
+		l1 = l0 - kk;
+		if (l1 <= 0) {
+		    goto L200;
+		}
+		if (l1 <= n10) {
+		    goto L190;
+		}
+		l0 = l1 - n10;
+		goto L180;
+L190:
+		h1[l1 - 1] = h__[i__ - 1];
+		goto L210;
+L200:
+		h2[l0 - 1] += h__[i__ - 1];
+L210:
+		;
+	    }
+/*  rotate the new row of the observation matrix into triangle */
+/*  by givens transformations. */
+	    if (n10 <= 0) {
+		goto L250;
+	    }
+/*  rotation with the rows 1,2,...n10 of matrix a. */
+	    i__4 = n10;
+	    for (j = 1; j <= i__4; ++j) {
+		piv = h1[0];
+		if (piv != (float)0.) {
+		    goto L214;
+		}
+		i__2 = kk;
+		for (i__ = 1; i__ <= i__2; ++i__) {
+		    h1[i__ - 1] = h1[i__];
+/* L212: */
+		}
+		h1[kk1 - 1] = (float)0.;
+		goto L240;
+/*  calculate the parameters of the givens transformation. */
+L214:
+		fpgivs_(&piv, &a1[j + a1_dim1], &cos__, &sin__);
+/*  transformation to the right hand side. */
+		j1 = j;
+		i__2 = *idim;
+		for (j2 = 1; j2 <= i__2; ++j2) {
+		    fprota_(&cos__, &sin__, &xi[j2 - 1], &z__[j1]);
+		    j1 += *n;
+/* L217: */
+		}
+/*  transformations to the left hand side with respect to a2. */
+		i__2 = kk;
+		for (i__ = 1; i__ <= i__2; ++i__) {
+		    fprota_(&cos__, &sin__, &h2[i__ - 1], &a2[j + i__ * 
+			    a2_dim1]);
+/* L220: */
+		}
+		if (j == n10) {
+		    goto L250;
+		}
+/* Computing MIN */
+		i__2 = n10 - j;
+		i2 = min(i__2,kk);
+/*  transformations to the left hand side with respect to a1. */
+		i__2 = i2;
+		for (i__ = 1; i__ <= i__2; ++i__) {
+		    i1 = i__ + 1;
+		    fprota_(&cos__, &sin__, &h1[i1 - 1], &a1[j + i1 * a1_dim1]
+			    );
+		    h1[i__ - 1] = h1[i1 - 1];
+/* L230: */
+		}
+		h1[i1 - 1] = (float)0.;
+L240:
+		;
+	    }
+/*  rotation with the rows n10+1,...n7 of matrix a. */
+L250:
+	    i__4 = kk;
+	    for (j = 1; j <= i__4; ++j) {
+		ij = n10 + j;
+		if (ij <= 0) {
+		    goto L270;
+		}
+		piv = h2[j - 1];
+		if (piv == (float)0.) {
+		    goto L270;
+		}
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &a2[ij + j * a2_dim1], &cos__, &sin__);
+/*  transformations to right hand side. */
+		j1 = ij;
+		i__2 = *idim;
+		for (j2 = 1; j2 <= i__2; ++j2) {
+		    fprota_(&cos__, &sin__, &xi[j2 - 1], &z__[j1]);
+		    j1 += *n;
+/* L255: */
+		}
+		if (j == kk) {
+		    goto L280;
+		}
+		j1 = j + 1;
+/*  transformations to left hand side. */
+		i__2 = kk;
+		for (i__ = j1; i__ <= i__2; ++i__) {
+		    fprota_(&cos__, &sin__, &h2[i__ - 1], &a2[ij + i__ * 
+			    a2_dim1]);
+/* L260: */
+		}
+L270:
+		;
+	    }
+/*  add contribution of this row to the sum of squares of residual */
+/*  right hand sides. */
+L280:
+	    i__4 = *idim;
+	    for (j2 = 1; j2 <= i__4; ++j2) {
+/* Computing 2nd power */
+		r__1 = xi[j2 - 1];
+		*fp += r__1 * r__1;
+/* L282: */
+	    }
+	    goto L290;
+/*  rotation of the new row of the observation matrix into */
+/*  triangle in case the b-splines nj,k+1(u),j=n7+1,...n-k-1 are all zero */
+/*  at ui. */
+L285:
+	    j = l5;
+	    i__4 = kk1;
+	    for (i__ = 1; i__ <= i__4; ++i__) {
+		++j;
+		piv = h__[i__ - 1];
+		if (piv == (float)0.) {
+		    goto L140;
+		}
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &a1[j + a1_dim1], &cos__, &sin__);
+/*  transformations to right hand side. */
+		j1 = j;
+		i__2 = *idim;
+		for (j2 = 1; j2 <= i__2; ++j2) {
+		    fprota_(&cos__, &sin__, &xi[j2 - 1], &z__[j1]);
+		    j1 += *n;
+/* L125: */
+		}
+		if (i__ == kk1) {
+		    goto L150;
+		}
+		i2 = 1;
+		i3 = i__ + 1;
+/*  transformations to left hand side. */
+		i__2 = kk1;
+		for (i1 = i3; i1 <= i__2; ++i1) {
+		    ++i2;
+		    fprota_(&cos__, &sin__, &h__[i1 - 1], &a1[j + i2 * 
+			    a1_dim1]);
+/* L130: */
+		}
+L140:
+		;
+	    }
+/*  add contribution of this row to the sum of squares of residual */
+/*  right hand sides. */
+L150:
+	    i__4 = *idim;
+	    for (j2 = 1; j2 <= i__4; ++j2) {
+/* Computing 2nd power */
+		r__1 = xi[j2 - 1];
+		*fp += r__1 * r__1;
+/* L155: */
+	    }
+L290:
+	    ;
+	}
+	fpint[*n] = fp0;
+	fpint[*n - 1] = fpold;
+	nrdata[*n] = nplus;
+/*  backward substitution to obtain the b-spline coefficients . */
+	j1 = 1;
+	i__3 = *idim;
+	for (j2 = 1; j2 <= i__3; ++j2) {
+	    fpbacp_(&a1[a1_offset], &a2[a2_offset], &z__[j1], &n7, &kk, &c__[
+		    j1], &kk1, nest);
+	    j1 += *n;
+/* L292: */
+	}
+/*  calculate from condition (**) the remaining coefficients. */
+	i__3 = *k;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    j1 = i__;
+	    i__4 = *idim;
+	    for (j = 1; j <= i__4; ++j) {
+		j2 = j1 + n7;
+		c__[j2] = c__[j1];
+		j1 += *n;
+/* L295: */
+	    }
+/* L297: */
+	}
+	if (*iopt < 0) {
+	    goto L660;
+	}
+/*  test whether the approximation sinf(u) is an acceptable solution. */
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L660;
+	}
+/*  if f(p=inf) < s accept the choice of knots. */
+	if (fpms < (float)0.) {
+	    goto L350;
+	}
+/*  if n=nmax, sinf(u) is an interpolating curve. */
+	if (*n == nmax) {
+	    goto L630;
+	}
+/*  increase the number of knots. */
+/*  if n=nest we cannot increase the number of knots because of the */
+/*  storage capacity limitation. */
+	if (*n == *nest) {
+	    goto L620;
+	}
+/*  determine the number of knots nplus we are going to add. */
+	npl1 = nplus << 1;
+	rn = (real) nplus;
+	if (fpold - *fp > acc) {
+	    npl1 = rn * fpms / (fpold - *fp);
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__2 = npl1, i__5 = nplus / 2, i__2 = max(i__2,i__5);
+	i__3 = nplus << 1, i__4 = max(i__2,1);
+	nplus = min(i__3,i__4);
+	fpold = *fp;
+/*  compute the sum of squared residuals for each knot interval */
+/*  t(j+k) <= ui <= t(j+k+1) and store it in fpint(j),j=1,2,...nrint. */
+	fpart = (float)0.;
+	i__ = 1;
+	l = *k1;
+	jj = 0;
+	i__3 = m1;
+	for (it = 1; it <= i__3; ++it) {
+	    if (u[it] < t[l]) {
+		goto L300;
+	    }
+	    new__ = 1;
+	    ++l;
+L300:
+	    term = (float)0.;
+	    l0 = l - *k2;
+	    i__4 = *idim;
+	    for (j2 = 1; j2 <= i__4; ++j2) {
+		fac = (float)0.;
+		j1 = l0;
+		i__2 = *k1;
+		for (j = 1; j <= i__2; ++j) {
+		    ++j1;
+		    fac += c__[j1] * q[it + j * q_dim1];
+/* L305: */
+		}
+		++jj;
+/* Computing 2nd power */
+		r__1 = w[it] * (fac - x[jj]);
+		term += r__1 * r__1;
+		l0 += *n;
+/* L310: */
+	    }
+	    fpart += term;
+	    if (new__ == 0) {
+		goto L320;
+	    }
+	    if (l > *k2) {
+		goto L315;
+	    }
+	    fpint[nrint] = term;
+	    new__ = 0;
+	    goto L320;
+L315:
+	    store = term * half;
+	    fpint[i__] = fpart - store;
+	    ++i__;
+	    fpart = store;
+	    new__ = 0;
+L320:
+	    ;
+	}
+	fpint[nrint] += fpart;
+	i__3 = nplus;
+	for (l = 1; l <= i__3; ++l) {
+/*  add a new knot */
+	    fpknot_(&u[1], m, &t[1], n, &fpint[1], &nrdata[1], &nrint, nest, &
+		    c__1);
+/*  if n=nmax we locate the knots as for interpolation */
+	    if (*n == nmax) {
+		goto L5;
+	    }
+/*  test whether we cannot further increase the number of knots. */
+	    if (*n == *nest) {
+		goto L340;
+	    }
+/* L330: */
+	}
+/*  restart the computations with the new set of knots. */
+L340:
+	;
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  part 2: determination of the smoothing closed curve sp(u).          c */
+/*  **********************************************************          c */
+/*  we have determined the number of knots and their position.          c */
+/*  we now compute the b-spline coefficients of the smoothing curve     c */
+/*  sp(u). the observation matrix a is extended by the rows of matrix   c */
+/*  b expressing that the kth derivative discontinuities of sp(u) at    c */
+/*  the interior knots t(k+2),...t(n-k-1) must be zero. the corres-     c */
+/*  ponding weights of these additional rows are set to 1/p.            c */
+/*  iteratively we then have to determine the value of p such that f(p),c */
+/*  the sum of squared residuals be = s. we already know that the least-c */
+/*  squares polynomial curve corresponds to p=0, and that the least-    c */
+/*  squares periodic spline curve corresponds to p=infinity. the        c */
+/*  iteration process which is proposed here, makes use of rational     c */
+/*  interpolation. since f(p) is a convex and strictly decreasing       c */
+/*  function of p, it can be approximated by a rational function        c */
+/*  r(p) = (u*p+v)/(p+w). three values of p(p1,p2,p3) with correspond-  c */
+/*  ing values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used      c */
+/*  to calculate the new value of p such that r(p)=s. convergence is    c */
+/*  guaranteed by taking f1>0 and f3<0.                                 c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  evaluate the discontinuity jump of the kth derivative of the */
+/*  b-splines at the knots t(l),l=k+2,...n-k-1 and store in b. */
+L350:
+    fpdisc_(&t[1], n, k2, &b[b_offset], nest);
+/*  initial value for p. */
+    p1 = (float)0.;
+    f1 = fp0 - *s;
+    p3 = -one;
+    f3 = fpms;
+    n11 = n10 - 1;
+    n8 = n7 - 1;
+    p = (float)0.;
+    l = n7;
+    i__1 = *k;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	j = *k + 1 - i__;
+	p += a2[l + j * a2_dim1];
+	--l;
+	if (l == 0) {
+	    goto L356;
+	}
+/* L352: */
+    }
+    i__1 = n10;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	p += a1[i__ + a1_dim1];
+/* L354: */
+    }
+L356:
+    rn = (real) n7;
+    p = rn / p;
+    ich1 = 0;
+    ich3 = 0;
+/*  iteration process to find the root of f(p) = s. */
+    i__1 = *maxit;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  form the matrix g  as the matrix a extended by the rows of matrix b. */
+/*  the rows of matrix b with weight 1/p are rotated into */
+/*  the triangularised observation matrix a. */
+/*  after triangularisation our n7 x n7 matrix g takes the form */
+/*            ! g1 '    ! */
+/*        g = !    ' g2 ! */
+/*            ! 0  '    ! */
+/*  with g2 a n7 x (k+1) matrix and g1 a n11 x n11 upper triangular */
+/*  matrix of bandwidth k+2. ( n11 = n7-k-1) */
+	pinv = one / p;
+/*  store matrix a into g */
+	i__3 = *nc;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    c__[i__] = z__[i__];
+/* L358: */
+	}
+	i__3 = n7;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    g1[i__ + *k1 * g1_dim1] = a1[i__ + *k1 * a1_dim1];
+	    g1[i__ + *k2 * g1_dim1] = (float)0.;
+	    g2[i__ + g2_dim1] = (float)0.;
+	    i__4 = *k;
+	    for (j = 1; j <= i__4; ++j) {
+		g1[i__ + j * g1_dim1] = a1[i__ + j * a1_dim1];
+		g2[i__ + (j + 1) * g2_dim1] = a2[i__ + j * a2_dim1];
+/* L360: */
+	    }
+	}
+	l = n10;
+	i__4 = *k1;
+	for (j = 1; j <= i__4; ++j) {
+	    if (l <= 0) {
+		goto L375;
+	    }
+	    g2[l + g2_dim1] = a1[l + j * a1_dim1];
+	    --l;
+/* L370: */
+	}
+L375:
+	i__4 = n8;
+	for (it = 1; it <= i__4; ++it) {
+/*  fetch a new row of matrix b and store it in the arrays h1 (the part */
+/*  with respect to g1) and h2 (the part with respect to g2). */
+	    i__3 = *idim;
+	    for (j = 1; j <= i__3; ++j) {
+		xi[j - 1] = (float)0.;
+/* L380: */
+	    }
+	    i__3 = *k1;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		h1[i__ - 1] = (float)0.;
+		h2[i__ - 1] = (float)0.;
+/* L385: */
+	    }
+	    h1[*k2 - 1] = (float)0.;
+	    if (it > n11) {
+		goto L420;
+	    }
+	    l = it;
+	    l0 = it;
+	    i__3 = *k2;
+	    for (j = 1; j <= i__3; ++j) {
+		if (l0 == n10) {
+		    goto L400;
+		}
+		h1[j - 1] = b[it + j * b_dim1] * pinv;
+		++l0;
+/* L390: */
+	    }
+	    goto L470;
+L400:
+	    l0 = 1;
+	    i__3 = *k2;
+	    for (l1 = j; l1 <= i__3; ++l1) {
+		h2[l0 - 1] = b[it + l1 * b_dim1] * pinv;
+		++l0;
+/* L410: */
+	    }
+	    goto L470;
+L420:
+	    l = 1;
+	    i__ = it - n10;
+	    i__3 = *k2;
+	    for (j = 1; j <= i__3; ++j) {
+		++i__;
+		l0 = i__;
+L430:
+		l1 = l0 - *k1;
+		if (l1 <= 0) {
+		    goto L450;
+		}
+		if (l1 <= n11) {
+		    goto L440;
+		}
+		l0 = l1 - n11;
+		goto L430;
+L440:
+		h1[l1 - 1] = b[it + j * b_dim1] * pinv;
+		goto L460;
+L450:
+		h2[l0 - 1] += b[it + j * b_dim1] * pinv;
+L460:
+		;
+	    }
+	    if (n11 <= 0) {
+		goto L510;
+	    }
+/*  rotate this row into triangle by givens transformations */
+/*  rotation with the rows l,l+1,...n11. */
+L470:
+	    i__3 = n11;
+	    for (j = l; j <= i__3; ++j) {
+		piv = h1[0];
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &g1[j + g1_dim1], &cos__, &sin__);
+/*  transformation to right hand side. */
+		j1 = j;
+		i__2 = *idim;
+		for (j2 = 1; j2 <= i__2; ++j2) {
+		    fprota_(&cos__, &sin__, &xi[j2 - 1], &c__[j1]);
+		    j1 += *n;
+/* L475: */
+		}
+/*  transformation to the left hand side with respect to g2. */
+		i__2 = *k1;
+		for (i__ = 1; i__ <= i__2; ++i__) {
+		    fprota_(&cos__, &sin__, &h2[i__ - 1], &g2[j + i__ * 
+			    g2_dim1]);
+/* L480: */
+		}
+		if (j == n11) {
+		    goto L510;
+		}
+/* Computing MIN */
+		i__2 = n11 - j;
+		i2 = min(i__2,*k1);
+/*  transformation to the left hand side with respect to g1. */
+		i__2 = i2;
+		for (i__ = 1; i__ <= i__2; ++i__) {
+		    i1 = i__ + 1;
+		    fprota_(&cos__, &sin__, &h1[i1 - 1], &g1[j + i1 * g1_dim1]
+			    );
+		    h1[i__ - 1] = h1[i1 - 1];
+/* L490: */
+		}
+		h1[i1 - 1] = (float)0.;
+/* L500: */
+	    }
+/*  rotation with the rows n11+1,...n7 */
+L510:
+	    i__3 = *k1;
+	    for (j = 1; j <= i__3; ++j) {
+		ij = n11 + j;
+		if (ij <= 0) {
+		    goto L530;
+		}
+		piv = h2[j - 1];
+/*  calculate the parameters of the givens transformation */
+		fpgivs_(&piv, &g2[ij + j * g2_dim1], &cos__, &sin__);
+/*  transformation to the right hand side. */
+		j1 = ij;
+		i__2 = *idim;
+		for (j2 = 1; j2 <= i__2; ++j2) {
+		    fprota_(&cos__, &sin__, &xi[j2 - 1], &c__[j1]);
+		    j1 += *n;
+/* L515: */
+		}
+		if (j == *k1) {
+		    goto L540;
+		}
+		j1 = j + 1;
+/*  transformation to the left hand side. */
+		i__2 = *k1;
+		for (i__ = j1; i__ <= i__2; ++i__) {
+		    fprota_(&cos__, &sin__, &h2[i__ - 1], &g2[ij + i__ * 
+			    g2_dim1]);
+/* L520: */
+		}
+L530:
+		;
+	    }
+L540:
+	    ;
+	}
+/*  backward substitution to obtain the b-spline coefficients */
+	j1 = 1;
+	i__4 = *idim;
+	for (j2 = 1; j2 <= i__4; ++j2) {
+	    fpbacp_(&g1[g1_offset], &g2[g2_offset], &c__[j1], &n7, k1, &c__[
+		    j1], k2, nest);
+	    j1 += *n;
+/* L542: */
+	}
+/*  calculate from condition (**) the remaining b-spline coefficients. */
+	i__4 = *k;
+	for (i__ = 1; i__ <= i__4; ++i__) {
+	    j1 = i__;
+	    i__3 = *idim;
+	    for (j = 1; j <= i__3; ++j) {
+		j2 = j1 + n7;
+		c__[j2] = c__[j1];
+		j1 += *n;
+/* L545: */
+	    }
+/* L547: */
+	}
+/*  computation of f(p). */
+	*fp = (float)0.;
+	l = *k1;
+	jj = 0;
+	i__4 = m1;
+	for (it = 1; it <= i__4; ++it) {
+	    if (u[it] < t[l]) {
+		goto L550;
+	    }
+	    ++l;
+L550:
+	    l0 = l - *k2;
+	    term = (float)0.;
+	    i__3 = *idim;
+	    for (j2 = 1; j2 <= i__3; ++j2) {
+		fac = (float)0.;
+		j1 = l0;
+		i__2 = *k1;
+		for (j = 1; j <= i__2; ++j) {
+		    ++j1;
+		    fac += c__[j1] * q[it + j * q_dim1];
+/* L560: */
+		}
+		++jj;
+/* Computing 2nd power */
+		r__1 = fac - x[jj];
+		term += r__1 * r__1;
+		l0 += *n;
+/* L565: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[it];
+	    *fp += term * (r__1 * r__1);
+/* L570: */
+	}
+/*  test whether the approximation sp(u) is an acceptable solution. */
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L660;
+	}
+/*  test whether the maximal number of iterations is reached. */
+	if (iter == *maxit) {
+	    goto L600;
+	}
+/*  carry out one more step of the iteration process. */
+	p2 = p;
+	f2 = fpms;
+	if (ich3 != 0) {
+	    goto L580;
+	}
+	if (f2 - f3 > acc) {
+	    goto L575;
+	}
+/*  our initial choice of p is too large. */
+	p3 = p2;
+	f3 = f2;
+	p *= con4;
+	if (p <= p1) {
+	    p = p1 * con9 + p2 * con1;
+	}
+	goto L595;
+L575:
+	if (f2 < (float)0.) {
+	    ich3 = 1;
+	}
+L580:
+	if (ich1 != 0) {
+	    goto L590;
+	}
+	if (f1 - f2 > acc) {
+	    goto L585;
+	}
+/*  our initial choice of p is too small */
+	p1 = p2;
+	f1 = f2;
+	p /= con4;
+	if (p3 < (float)0.) {
+	    goto L595;
+	}
+	if (p >= p3) {
+	    p = p2 * con1 + p3 * con9;
+	}
+	goto L595;
+L585:
+	if (f2 > (float)0.) {
+	    ich1 = 1;
+	}
+/*  test whether the iteration process proceeds as theoretically */
+/*  expected. */
+L590:
+	if (f2 >= f1 || f2 <= f3) {
+	    goto L610;
+	}
+/*  find the new value for p. */
+	p = fprati_(&p1, &f1, &p2, &f2, &p3, &f3);
+L595:
+	;
+    }
+/*  error codes and messages. */
+L600:
+    *ier = 3;
+    goto L660;
+L610:
+    *ier = 2;
+    goto L660;
+L620:
+    *ier = 1;
+    goto L660;
+L630:
+    *ier = -1;
+    goto L660;
+L640:
+    *ier = -2;
+/*  the point (z(1),z(2),...,z(idim)) is a solution of our problem. */
+/*  a constant function is a spline of degree k with all b-spline */
+/*  coefficients equal to that constant. */
+    i__1 = *k1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	rn = (real) (*k1 - i__);
+	t[i__] = u[1] - rn * per;
+	j = i__ + *k1;
+	rn = (real) (i__ - 1);
+	t[j] = u[*m] + rn * per;
+/* L650: */
+    }
+    *n = nmin;
+    j1 = 0;
+    i__1 = *idim;
+    for (j = 1; j <= i__1; ++j) {
+	fac = z__[j];
+	j2 = j1;
+	i__4 = *k1;
+	for (i__ = 1; i__ <= i__4; ++i__) {
+	    ++j2;
+	    c__[j2] = fac;
+/* L654: */
+	}
+	j1 += *n;
+/* L658: */
+    }
+    *fp = fp0;
+    fpint[*n] = fp0;
+    fpint[*n - 1] = (float)0.;
+    nrdata[*n] = 0;
+L660:
+    return 0;
+} /* fpclos_ */
+
+/* Subroutine */ int fpcoco_(iopt, m, x, y, w, v, s, nest, maxtr, maxbin, n, 
+	t, c__, sq, sx, bind, e, wrk, lwrk, iwrk, kwrk, ier)
+integer *iopt, *m;
+real *x, *y, *w, *v, *s;
+integer *nest, *maxtr, *maxbin, *n;
+real *t, *c__, *sq, *sx;
+logical *bind;
+real *e, *wrk;
+integer *lwrk, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+    real r__1;
+
+    /* Local variables */
+    static real half;
+    static integer nmax;
+    static real term;
+    static integer i__, j, k, l;
+    static real sqmax;
+    static integer i1, l1, m1, n4, n6, n8, ia, ib, ic, mb, ji, jl, iq, nm, jr,
+	     iu, ju, nr;
+    static real tj, xi;
+    static integer iz;
+    extern /* Subroutine */ int fpcosp_();
+    static integer jib, jjb;
+    static real sql;
+    static integer izz;
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..subroutine references.. */
+/*    fpcosp,fpbspl,fpadno,fpdeno,fpseno,fpfrno */
+/*  .. */
+/*  set constant */
+    /* Parameter adjustments */
+    --sx;
+    --v;
+    --w;
+    --y;
+    --x;
+    --e;
+    --bind;
+    --c__;
+    --t;
+    --wrk;
+    --iwrk;
+
+    /* Function Body */
+    half = (float).5;
+/*  determine the maximal admissible number of knots. */
+    nmax = *m + 4;
+/*  the initial choice of knots depends on the value of iopt. */
+/*    if iopt=0 the program starts with the minimal number of knots */
+/*    so that can be guarantied that the concavity/convexity constraints */
+/*    will be satisfied. */
+/*    if iopt = 1 the program will continue from the point on where she */
+/*    left at the foregoing call. */
+    if (*iopt > 0) {
+	goto L80;
+    }
+/*  find the minimal number of knots. */
+/*  a knot is located at the data point x(i), i=2,3,...m-1 if */
+/*    1) v(i) ^= 0    and */
+/*    2) v(i)*v(i-1) <= 0  or  v(i)*v(i+1) <= 0. */
+    m1 = *m - 1;
+    *n = 4;
+    i__1 = m1;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (v[i__] == (float)0. || v[i__] * v[i__ - 1] > (float)0. && v[i__] *
+		 v[i__ + 1] > (float)0.) {
+	    goto L20;
+	}
+	++(*n);
+/*  test whether the required storage space exceeds the available one. */
+	if (*n + 4 > *nest) {
+	    goto L200;
+	}
+	t[*n] = x[i__];
+L20:
+	;
+    }
+/*  find the position of the knots t(1),...t(4) and t(n-3),...t(n) which */
+/*  are needed for the b-spline representation of s(x). */
+    for (i__ = 1; i__ <= 4; ++i__) {
+	t[i__] = x[1];
+	++(*n);
+	t[*n] = x[*m];
+/* L30: */
+    }
+/*  test whether the minimum number of knots exceeds the maximum number. */
+    if (*n > nmax) {
+	goto L210;
+    }
+/*  main loop for the different sets of knots. */
+/*  find corresponding values e(j) to the knots t(j+3),j=1,2,...n-6 */
+/*    e(j) will take the value -1,1, or 0 according to the requirement */
+/*    that s(x) must be locally convex or concave at t(j+3) or that the */
+/*    sign of s''(x) is unrestricted at that point. */
+L40:
+    i__ = 1;
+    xi = x[1];
+    j = 4;
+    tj = t[4];
+    n6 = *n - 6;
+    i__1 = n6;
+    for (l = 1; l <= i__1; ++l) {
+L50:
+	if (xi == tj) {
+	    goto L60;
+	}
+	++i__;
+	xi = x[i__];
+	goto L50;
+L60:
+	e[l] = v[i__];
+	++j;
+	tj = t[j];
+/* L70: */
+    }
+/*  we partition the working space */
+    nm = *n + *maxbin;
+    mb = *maxbin + 1;
+    ia = 1;
+    ib = ia + (*n << 2);
+    ic = ib + nm * *maxbin;
+    iz = ic + *n;
+    izz = iz + *n;
+    iu = izz + *n;
+    iq = iu + *maxbin;
+    ji = 1;
+    ju = ji + *maxtr;
+    jl = ju + *maxtr;
+    jr = jl + *maxtr;
+    jjb = jr + *maxtr;
+    jib = jjb + mb;
+/*  given the set of knots t(j),j=1,2,...n, find the least-squares cubic */
+/*  spline which satisfies the imposed concavity/convexity constraints. */
+    fpcosp_(m, &x[1], &y[1], &w[1], n, &t[1], &e[1], maxtr, maxbin, &c__[1], 
+	    sq, &sx[1], &bind[1], &nm, &mb, &wrk[ia], &wrk[ib], &wrk[ic], &
+	    wrk[iz], &wrk[izz], &wrk[iu], &wrk[iq], &iwrk[ji], &iwrk[ju], &
+	    iwrk[jl], &iwrk[jr], &iwrk[jjb], &iwrk[jib], ier);
+/*  if sq <= s or in case of abnormal exit from fpcosp, control is */
+/*  repassed to the driver program. */
+    if (*sq <= *s || *ier > 0) {
+	goto L300;
+    }
+/*  calculate for each knot interval t(l-1) <= xi <= t(l) the */
+/*  sum((wi*(yi-s(xi)))**2). */
+/*  find the interval t(k-1) <= x <= t(k) for which this sum is maximal */
+/*  on the condition that this interval contains at least one interior */
+/*  data point x(nr) and that s(x) is not given there by a straight line. */
+L80:
+    sqmax = (float)0.;
+    sql = (float)0.;
+    l = 5;
+    nr = 0;
+    i1 = 1;
+    n4 = *n - 4;
+    i__1 = *m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+/* Computing 2nd power */
+	r__1 = w[i__] * (sx[i__] - y[i__]);
+	term = r__1 * r__1;
+	if (x[i__] < t[l] || l > n4) {
+	    goto L100;
+	}
+	term *= half;
+	sql += term;
+	if (i__ - i1 <= 1 || bind[l - 4] && bind[l - 3]) {
+	    goto L90;
+	}
+	if (sql <= sqmax) {
+	    goto L90;
+	}
+	k = l;
+	sqmax = sql;
+	nr = i1 + (i__ - i1) / 2;
+L90:
+	++l;
+	i1 = i__;
+	sql = (float)0.;
+L100:
+	sql += term;
+/* L110: */
+    }
+    if (*m - i1 <= 1 || bind[l - 4] && bind[l - 3]) {
+	goto L120;
+    }
+    if (sql <= sqmax) {
+	goto L120;
+    }
+    k = l;
+    nr = i1 + (*m - i1) / 2;
+/*  if no such interval is found, control is repassed to the driver */
+/*  program (ier = -1). */
+L120:
+    if (nr == 0) {
+	goto L190;
+    }
+/*  if s(x) is given by the same straight line in two succeeding knot */
+/*  intervals t(l-1) <= x <= t(l) and t(l) <= x <= t(l+1),delete t(l) */
+    n8 = *n - 8;
+    l1 = 0;
+    if (n8 <= 0) {
+	goto L150;
+    }
+    i__1 = n8;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (! (bind[i__] && bind[i__ + 1] && bind[i__ + 2])) {
+	    goto L140;
+	}
+	l = i__ + 4 - l1;
+	if (k > l) {
+	    --k;
+	}
+	--(*n);
+	++l1;
+	i__2 = *n;
+	for (j = l; j <= i__2; ++j) {
+	    t[j] = t[j + 1];
+/* L130: */
+	}
+L140:
+	;
+    }
+/*  test whether we cannot further increase the number of knots. */
+L150:
+    if (*n == nmax) {
+	goto L180;
+    }
+    if (*n == *nest) {
+	goto L170;
+    }
+/*  locate an additional knot at the point x(nr). */
+    j = *n;
+    i__1 = *n;
+    for (i__ = k; i__ <= i__1; ++i__) {
+	t[j + 1] = t[j];
+	--j;
+/* L160: */
+    }
+    t[k] = x[nr];
+    ++(*n);
+/*  restart the computations with the new set of knots. */
+    goto L40;
+/*  error codes and messages. */
+L170:
+    *ier = -3;
+    goto L300;
+L180:
+    *ier = -2;
+    goto L300;
+L190:
+    *ier = -1;
+    goto L300;
+L200:
+    *ier = 4;
+    goto L300;
+L210:
+    *ier = 5;
+L300:
+    return 0;
+} /* fpcoco_ */
+
+/* Subroutine */ int fpcons_(iopt, idim, m, u, mx, x, w, ib, ie, k, s, nest, 
+	tol, maxit, k1, k2, n, t, nc, c__, fp, fpint, z__, a, b, g, q, nrdata,
+	 ier)
+integer *iopt, *idim, *m;
+real *u;
+integer *mx;
+real *x, *w;
+integer *ib, *ie, *k;
+real *s;
+integer *nest;
+real *tol;
+integer *maxit, *k1, *k2, *n;
+real *t;
+integer *nc;
+real *c__, *fp, *fpint, *z__, *a, *b, *g, *q;
+integer *nrdata, *ier;
+{
+    /* System generated locals */
+    integer a_dim1, a_offset, b_dim1, b_offset, g_dim1, g_offset, q_dim1, 
+	    q_offset, i__1, i__2, i__3, i__4, i__5;
+    real r__1;
+
+    /* Local variables */
+    static real half;
+    static integer mmin, nmin, iter, nmax;
+    static real fpms, term, pinv, h__[7];
+    static integer i__, j, l;
+    static real p, fpold, fpart, f1, f2, f3;
+    static integer i1, i2;
+    static real store;
+    static integer i3, j1;
+    static real p1, p2, p3;
+    static integer j2, j3, l0, nplus, nrint, n8, jb, je, mb, me, jj, li, lj;
+    extern /* Subroutine */ int fpback_();
+    static integer mm, nn, it;
+    static real ui, rn, wi, xi[10];
+    extern /* Subroutine */ int fpdisc_();
+    extern doublereal fprati_();
+    extern /* Subroutine */ int fpbspl_(), fprota_(), fpgivs_(), fpknot_();
+    static real fp0;
+    static integer nk1;
+    static real acc, fac;
+    static integer kbe;
+    static real one, cos__, sin__;
+    static integer new__;
+    static real piv;
+    static integer ich1, ich3;
+    static real con1, con4, con9;
+    static integer npl1;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references */
+/*  ..subroutine references.. */
+/*    fpbacp,fpbspl,fpgivs,fpdisc,fpknot,fprota */
+/*  .. */
+/*  set constants */
+    /* Parameter adjustments */
+    --w;
+    --u;
+    --x;
+    --nrdata;
+    --fpint;
+    --t;
+    q_dim1 = *m;
+    q_offset = 1 + q_dim1 * 1;
+    q -= q_offset;
+    a_dim1 = *nest;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+    g_dim1 = *nest;
+    g_offset = 1 + g_dim1 * 1;
+    g -= g_offset;
+    b_dim1 = *nest;
+    b_offset = 1 + b_dim1 * 1;
+    b -= b_offset;
+    --z__;
+    --c__;
+
+    /* Function Body */
+    one = (float)1.;
+    con1 = (float).1;
+    con9 = (float).9;
+    con4 = (float).04;
+    half = (float).5;
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  part 1: determination of the number of knots and their position     c */
+/*  **************************************************************      c */
+/*  given a set of knots we compute the least-squares curve sinf(u),    c */
+/*  and the corresponding sum of squared residuals fp=f(p=inf).         c */
+/*  if iopt=-1 sinf(u) is the requested curve.                          c */
+/*  if iopt=0 or iopt=1 we check whether we can accept the knots:       c */
+/*    if fp <=s we will continue with the current set of knots.         c */
+/*    if fp > s we will increase the number of knots and compute the    c */
+/*       corresponding least-squares curve until finally fp<=s.         c */
+/*    the initial choice of knots depends on the value of s and iopt.   c */
+/*    if s=0 we have spline interpolation; in that case the number of   c */
+/*    knots equals nmax = m+k+1-max(0,ib-1)-max(0,ie-1)                 c */
+/*    if s > 0 and                                                      c */
+/*      iopt=0 we first compute the least-squares polynomial curve of   c */
+/*      degree k; n = nmin = 2*k+2                                      c */
+/*      iopt=1 we start with the set of knots found at the last         c */
+/*      call of the routine, except for the case that s > fp0; then     c */
+/*      we compute directly the polynomial curve of degree k.           c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  determine nmin, the number of knots for polynomial approximation. */
+    nmin = *k1 << 1;
+/*  find which data points are to be concidered. */
+    mb = 2;
+    jb = *ib;
+    if (*ib > 0) {
+	goto L10;
+    }
+    mb = 1;
+    jb = 1;
+L10:
+    me = *m - 1;
+    je = *ie;
+    if (*ie > 0) {
+	goto L20;
+    }
+    me = *m;
+    je = 1;
+L20:
+    if (*iopt < 0) {
+	goto L60;
+    }
+/*  calculation of acc, the absolute tolerance for the root of f(p)=s. */
+    acc = *tol * *s;
+/*  determine nmax, the number of knots for spline interpolation. */
+    kbe = *k1 - jb - je;
+    mmin = kbe + 2;
+    mm = *m - mmin;
+    nmax = nmin + mm;
+    if (*s > (float)0.) {
+	goto L40;
+    }
+/*  if s=0, s(u) is an interpolating curve. */
+/*  test whether the required storage space exceeds the available one. */
+    *n = nmax;
+    if (nmax > *nest) {
+	goto L420;
+    }
+/*  find the position of the interior knots in case of interpolation. */
+    if (mm == 0) {
+	goto L60;
+    }
+L25:
+    i__ = *k2;
+    j = 3 - jb + *k / 2;
+    i__1 = mm;
+    for (l = 1; l <= i__1; ++l) {
+	t[i__] = u[j];
+	++i__;
+	++j;
+/* L30: */
+    }
+    goto L60;
+/*  if s>0 our initial choice of knots depends on the value of iopt. */
+/*  if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares */
+/*  polynomial curve which is a spline curve without interior knots. */
+/*  if iopt=1 and fp0>s we start computing the least squares spline curve */
+/*  according to the set of knots found at the last call of the routine. */
+L40:
+    if (*iopt == 0) {
+	goto L50;
+    }
+    if (*n == nmin) {
+	goto L50;
+    }
+    fp0 = fpint[*n];
+    fpold = fpint[*n - 1];
+    nplus = nrdata[*n];
+    if (fp0 > *s) {
+	goto L60;
+    }
+L50:
+    *n = nmin;
+    fpold = (float)0.;
+    nplus = 0;
+    nrdata[1] = *m - 2;
+/*  main loop for the different sets of knots. m is a save upper bound */
+/*  for the number of trials. */
+L60:
+    i__1 = *m;
+    for (iter = 1; iter <= i__1; ++iter) {
+	if (*n == nmin) {
+	    *ier = -2;
+	}
+/*  find nrint, tne number of knot intervals. */
+	nrint = *n - nmin + 1;
+/*  find the position of the additional knots which are needed for */
+/*  the b-spline representation of s(u). */
+	nk1 = *n - *k1;
+	i__ = *n;
+	i__2 = *k1;
+	for (j = 1; j <= i__2; ++j) {
+	    t[j] = u[1];
+	    t[i__] = u[*m];
+	    --i__;
+/* L70: */
+	}
+/*  compute the b-spline coefficients of the least-squares spline curve */
+/*  sinf(u). the observation matrix a is built up row by row and */
+/*  reduced to upper triangular form by givens transformations. */
+/*  at the same time fp=f(p=inf) is computed. */
+	*fp = (float)0.;
+/*  nn denotes the dimension of the splines */
+	nn = nk1 - *ib - *ie;
+/*  initialize the b-spline coefficients and the observation matrix a. */
+	i__2 = *nc;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    z__[i__] = (float)0.;
+	    c__[i__] = (float)0.;
+/* L75: */
+	}
+	if (me < mb) {
+	    goto L134;
+	}
+	if (nn == 0) {
+	    goto L82;
+	}
+	i__2 = nn;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    i__3 = *k1;
+	    for (j = 1; j <= i__3; ++j) {
+		a[i__ + j * a_dim1] = (float)0.;
+/* L80: */
+	    }
+	}
+L82:
+	l = *k1;
+	jj = (mb - 1) * *idim;
+	i__3 = me;
+	for (it = mb; it <= i__3; ++it) {
+/*  fetch the current data point u(it),x(it). */
+	    ui = u[it];
+	    wi = w[it];
+	    i__2 = *idim;
+	    for (j = 1; j <= i__2; ++j) {
+		++jj;
+		xi[j - 1] = x[jj] * wi;
+/* L84: */
+	    }
+/*  search for knot interval t(l) <= ui < t(l+1). */
+L86:
+	    if (ui < t[l + 1] || l == nk1) {
+		goto L90;
+	    }
+	    ++l;
+	    goto L86;
+/*  evaluate the (k+1) non-zero b-splines at ui and store them in q. */
+L90:
+	    fpbspl_(&t[1], n, k, &ui, &l, h__);
+	    i__2 = *k1;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		q[it + i__ * q_dim1] = h__[i__ - 1];
+		h__[i__ - 1] *= wi;
+/* L92: */
+	    }
+/*  take into account that certain b-spline coefficients must be zero. */
+	    lj = *k1;
+	    j = nk1 - l - *ie;
+	    if (j >= 0) {
+		goto L94;
+	    }
+	    lj += j;
+L94:
+	    li = 1;
+	    j = l - *k1 - *ib;
+	    if (j >= 0) {
+		goto L96;
+	    }
+	    li -= j;
+	    j = 0;
+L96:
+	    if (li > lj) {
+		goto L120;
+	    }
+/*  rotate the new row of the observation matrix into triangle. */
+	    i__2 = lj;
+	    for (i__ = li; i__ <= i__2; ++i__) {
+		++j;
+		piv = h__[i__ - 1];
+		if (piv == (float)0.) {
+		    goto L110;
+		}
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &a[j + a_dim1], &cos__, &sin__);
+/*  transformations to right hand side. */
+		j1 = j;
+		i__4 = *idim;
+		for (j2 = 1; j2 <= i__4; ++j2) {
+		    fprota_(&cos__, &sin__, &xi[j2 - 1], &z__[j1]);
+		    j1 += *n;
+/* L98: */
+		}
+		if (i__ == lj) {
+		    goto L120;
+		}
+		i2 = 1;
+		i3 = i__ + 1;
+		i__4 = lj;
+		for (i1 = i3; i1 <= i__4; ++i1) {
+		    ++i2;
+/*  transformations to left hand side. */
+		    fprota_(&cos__, &sin__, &h__[i1 - 1], &a[j + i2 * a_dim1])
+			    ;
+/* L100: */
+		}
+L110:
+		;
+	    }
+/*  add contribution of this row to the sum of squares of residual */
+/*  right hand sides. */
+L120:
+	    i__2 = *idim;
+	    for (j2 = 1; j2 <= i__2; ++j2) {
+/* Computing 2nd power */
+		r__1 = xi[j2 - 1];
+		*fp += r__1 * r__1;
+/* L125: */
+	    }
+/* L130: */
+	}
+	if (*ier == -2) {
+	    fp0 = *fp;
+	}
+	fpint[*n] = fp0;
+	fpint[*n - 1] = fpold;
+	nrdata[*n] = nplus;
+/*  backward substitution to obtain the b-spline coefficients. */
+	if (nn == 0) {
+	    goto L134;
+	}
+	j1 = 1;
+	i__3 = *idim;
+	for (j2 = 1; j2 <= i__3; ++j2) {
+	    j3 = j1 + *ib;
+	    fpback_(&a[a_offset], &z__[j1], &nn, k1, &c__[j3], nest);
+	    j1 += *n;
+/* L132: */
+	}
+/*  test whether the approximation sinf(u) is an acceptable solution. */
+L134:
+	if (*iopt < 0) {
+	    goto L440;
+	}
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  if f(p=inf) < s accept the choice of knots. */
+	if (fpms < (float)0.) {
+	    goto L250;
+	}
+/*  if n = nmax, sinf(u) is an interpolating spline curve. */
+	if (*n == nmax) {
+	    goto L430;
+	}
+/*  increase the number of knots. */
+/*  if n=nest we cannot increase the number of knots because of */
+/*  the storage capacity limitation. */
+	if (*n == *nest) {
+	    goto L420;
+	}
+/*  determine the number of knots nplus we are going to add. */
+	if (*ier == 0) {
+	    goto L140;
+	}
+	nplus = 1;
+	*ier = 0;
+	goto L150;
+L140:
+	npl1 = nplus << 1;
+	rn = (real) nplus;
+	if (fpold - *fp > acc) {
+	    npl1 = rn * fpms / (fpold - *fp);
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__4 = npl1, i__5 = nplus / 2, i__4 = max(i__4,i__5);
+	i__3 = nplus << 1, i__2 = max(i__4,1);
+	nplus = min(i__3,i__2);
+L150:
+	fpold = *fp;
+/*  compute the sum of squared residuals for each knot interval */
+/*  t(j+k) <= u(i) <= t(j+k+1) and store it in fpint(j),j=1,2,...nrint. */
+	fpart = (float)0.;
+	i__ = 1;
+	l = *k2;
+	new__ = 0;
+	jj = (mb - 1) * *idim;
+	i__3 = me;
+	for (it = mb; it <= i__3; ++it) {
+	    if (u[it] < t[l] || l > nk1) {
+		goto L160;
+	    }
+	    new__ = 1;
+	    ++l;
+L160:
+	    term = (float)0.;
+	    l0 = l - *k2;
+	    i__2 = *idim;
+	    for (j2 = 1; j2 <= i__2; ++j2) {
+		fac = (float)0.;
+		j1 = l0;
+		i__4 = *k1;
+		for (j = 1; j <= i__4; ++j) {
+		    ++j1;
+		    fac += c__[j1] * q[it + j * q_dim1];
+/* L170: */
+		}
+		++jj;
+/* Computing 2nd power */
+		r__1 = w[it] * (fac - x[jj]);
+		term += r__1 * r__1;
+		l0 += *n;
+/* L175: */
+	    }
+	    fpart += term;
+	    if (new__ == 0) {
+		goto L180;
+	    }
+	    store = term * half;
+	    fpint[i__] = fpart - store;
+	    ++i__;
+	    fpart = store;
+	    new__ = 0;
+L180:
+	    ;
+	}
+	fpint[nrint] = fpart;
+	i__3 = nplus;
+	for (l = 1; l <= i__3; ++l) {
+/*  add a new knot. */
+	    fpknot_(&u[1], m, &t[1], n, &fpint[1], &nrdata[1], &nrint, nest, &
+		    c__1);
+/*  if n=nmax we locate the knots as for interpolation */
+	    if (*n == nmax) {
+		goto L25;
+	    }
+/*  test whether we cannot further increase the number of knots. */
+	    if (*n == *nest) {
+		goto L200;
+	    }
+/* L190: */
+	}
+/*  restart the computations with the new set of knots. */
+L200:
+	;
+    }
+/*  test whether the least-squares kth degree polynomial curve is a */
+/*  solution of our approximation problem. */
+L250:
+    if (*ier == -2) {
+	goto L440;
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  part 2: determination of the smoothing spline curve sp(u).          c */
+/*  **********************************************************          c */
+/*  we have determined the number of knots and their position.          c */
+/*  we now compute the b-spline coefficients of the smoothing curve     c */
+/*  sp(u). the observation matrix a is extended by the rows of matrix   c */
+/*  b expressing that the kth derivative discontinuities of sp(u) at    c */
+/*  the interior knots t(k+2),...t(n-k-1) must be zero. the corres-     c */
+/*  ponding weights of these additional rows are set to 1/p.            c */
+/*  iteratively we then have to determine the value of p such that f(p),c */
+/*  the sum of squared residuals be = s. we already know that the least c */
+/*  squares kth degree polynomial curve corresponds to p=0, and that    c */
+/*  the least-squares spline curve corresponds to p=infinity. the       c */
+/*  iteration process which is proposed here, makes use of rational     c */
+/*  interpolation. since f(p) is a convex and strictly decreasing       c */
+/*  function of p, it can be approximated by a rational function        c */
+/*  r(p) = (u*p+v)/(p+w). three values of p(p1,p2,p3) with correspond-  c */
+/*  ing values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used      c */
+/*  to calculate the new value of p such that r(p)=s. convergence is    c */
+/*  guaranteed by taking f1>0 and f3<0.                                 c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  evaluate the discontinuity jump of the kth derivative of the */
+/*  b-splines at the knots t(l),l=k+2,...n-k-1 and store in b. */
+    fpdisc_(&t[1], n, k2, &b[b_offset], nest);
+/*  initial value for p. */
+    p1 = (float)0.;
+    f1 = fp0 - *s;
+    p3 = -one;
+    f3 = fpms;
+    p = (float)0.;
+    i__1 = nn;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	p += a[i__ + a_dim1];
+/* L252: */
+    }
+    rn = (real) nn;
+    p = rn / p;
+    ich1 = 0;
+    ich3 = 0;
+    n8 = *n - nmin;
+/*  iteration process to find the root of f(p) = s. */
+    i__1 = *maxit;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  the rows of matrix b with weight 1/p are rotated into the */
+/*  triangularised observation matrix a which is stored in g. */
+	pinv = one / p;
+	i__3 = *nc;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    c__[i__] = z__[i__];
+/* L255: */
+	}
+	i__3 = nn;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    g[i__ + *k2 * g_dim1] = (float)0.;
+	    i__2 = *k1;
+	    for (j = 1; j <= i__2; ++j) {
+		g[i__ + j * g_dim1] = a[i__ + j * a_dim1];
+/* L260: */
+	    }
+	}
+	i__2 = n8;
+	for (it = 1; it <= i__2; ++it) {
+/*  the row of matrix b is rotated into triangle by givens transformation */
+	    i__3 = *k2;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		h__[i__ - 1] = b[it + i__ * b_dim1] * pinv;
+/* L264: */
+	    }
+	    i__3 = *idim;
+	    for (j = 1; j <= i__3; ++j) {
+		xi[j - 1] = (float)0.;
+/* L268: */
+	    }
+/*  take into account that certain b-spline coefficients must be zero. */
+	    if (it > *ib) {
+		goto L274;
+	    }
+	    j1 = *ib - it + 2;
+	    j2 = 1;
+	    i__3 = *k2;
+	    for (i__ = j1; i__ <= i__3; ++i__) {
+		h__[j2 - 1] = h__[i__ - 1];
+		++j2;
+/* L270: */
+	    }
+	    i__3 = *k2;
+	    for (i__ = j2; i__ <= i__3; ++i__) {
+		h__[i__ - 1] = (float)0.;
+/* L272: */
+	    }
+L274:
+/* Computing MAX */
+	    i__3 = 1, i__4 = it - *ib;
+	    jj = max(i__3,i__4);
+	    i__3 = nn;
+	    for (j = jj; j <= i__3; ++j) {
+		piv = h__[0];
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &g[j + g_dim1], &cos__, &sin__);
+/*  transformations to right hand side. */
+		j1 = j;
+		i__4 = *idim;
+		for (j2 = 1; j2 <= i__4; ++j2) {
+		    fprota_(&cos__, &sin__, &xi[j2 - 1], &c__[j1]);
+		    j1 += *n;
+/* L277: */
+		}
+		if (j == nn) {
+		    goto L300;
+		}
+/* Computing MIN */
+		i__4 = nn - j;
+		i2 = min(i__4,*k1);
+		i__4 = i2;
+		for (i__ = 1; i__ <= i__4; ++i__) {
+/*  transformations to left hand side. */
+		    i1 = i__ + 1;
+		    fprota_(&cos__, &sin__, &h__[i1 - 1], &g[j + i1 * g_dim1])
+			    ;
+		    h__[i__ - 1] = h__[i1 - 1];
+/* L280: */
+		}
+		h__[i2] = (float)0.;
+/* L290: */
+	    }
+L300:
+	    ;
+	}
+/*  backward substitution to obtain the b-spline coefficients. */
+	j1 = 1;
+	i__2 = *idim;
+	for (j2 = 1; j2 <= i__2; ++j2) {
+	    j3 = j1 + *ib;
+	    fpback_(&g[g_offset], &c__[j1], &nn, k2, &c__[j3], nest);
+	    if (*ib == 0) {
+		goto L306;
+	    }
+	    j3 = j1;
+	    i__3 = *ib;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		c__[j3] = (float)0.;
+		++j3;
+/* L304: */
+	    }
+L306:
+	    j1 += *n;
+/* L308: */
+	}
+/*  computation of f(p). */
+	*fp = (float)0.;
+	l = *k2;
+	jj = (mb - 1) * *idim;
+	i__2 = me;
+	for (it = mb; it <= i__2; ++it) {
+	    if (u[it] < t[l] || l > nk1) {
+		goto L310;
+	    }
+	    ++l;
+L310:
+	    l0 = l - *k2;
+	    term = (float)0.;
+	    i__3 = *idim;
+	    for (j2 = 1; j2 <= i__3; ++j2) {
+		fac = (float)0.;
+		j1 = l0;
+		i__4 = *k1;
+		for (j = 1; j <= i__4; ++j) {
+		    ++j1;
+		    fac += c__[j1] * q[it + j * q_dim1];
+/* L320: */
+		}
+		++jj;
+/* Computing 2nd power */
+		r__1 = fac - x[jj];
+		term += r__1 * r__1;
+		l0 += *n;
+/* L325: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[it];
+	    *fp += term * (r__1 * r__1);
+/* L330: */
+	}
+/*  test whether the approximation sp(u) is an acceptable solution. */
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  test whether the maximal number of iterations is reached. */
+	if (iter == *maxit) {
+	    goto L400;
+	}
+/*  carry out one more step of the iteration process. */
+	p2 = p;
+	f2 = fpms;
+	if (ich3 != 0) {
+	    goto L340;
+	}
+	if (f2 - f3 > acc) {
+	    goto L335;
+	}
+/*  our initial choice of p is too large. */
+	p3 = p2;
+	f3 = f2;
+	p *= con4;
+	if (p <= p1) {
+	    p = p1 * con9 + p2 * con1;
+	}
+	goto L360;
+L335:
+	if (f2 < (float)0.) {
+	    ich3 = 1;
+	}
+L340:
+	if (ich1 != 0) {
+	    goto L350;
+	}
+	if (f1 - f2 > acc) {
+	    goto L345;
+	}
+/*  our initial choice of p is too small */
+	p1 = p2;
+	f1 = f2;
+	p /= con4;
+	if (p3 < (float)0.) {
+	    goto L360;
+	}
+	if (p >= p3) {
+	    p = p2 * con1 + p3 * con9;
+	}
+	goto L360;
+L345:
+	if (f2 > (float)0.) {
+	    ich1 = 1;
+	}
+/*  test whether the iteration process proceeds as theoretically */
+/*  expected. */
+L350:
+	if (f2 >= f1 || f2 <= f3) {
+	    goto L410;
+	}
+/*  find the new value for p. */
+	p = fprati_(&p1, &f1, &p2, &f2, &p3, &f3);
+L360:
+	;
+    }
+/*  error codes and messages. */
+L400:
+    *ier = 3;
+    goto L440;
+L410:
+    *ier = 2;
+    goto L440;
+L420:
+    *ier = 1;
+    goto L440;
+L430:
+    *ier = -1;
+L440:
+    return 0;
+} /* fpcons_ */
+
+/* Subroutine */ int fpcosp_(m, x, y, w, n, t, e, maxtr, maxbin, c__, sq, sx, 
+	bind, nm, mb, a, b, const__, z__, zz, u, q, info, up, left, right, 
+	jbind, ibind, ier)
+integer *m;
+real *x, *y, *w;
+integer *n;
+real *t, *e;
+integer *maxtr, *maxbin;
+real *c__, *sq, *sx;
+logical *bind;
+integer *nm, *mb;
+real *a, *b, *const__, *z__, *zz, *u, *q;
+integer *info, *up, *left, *right, *jbind, *ibind, *ier;
+{
+    /* System generated locals */
+    integer a_dim1, a_offset, b_dim1, b_offset, q_dim1, q_offset, i__1, i__2, 
+	    i__3;
+    real r__1;
+
+    /* Local variables */
+    static integer kdim, merk;
+    static real f, h__[4];
+    static integer i__, j, k, l, nbind, count, i1, j1, j2, j3, k1, k2, k3, k4,
+	     k5, k6, l1, l2, l3, n1, n4, n6;
+    static real wi, xi;
+    extern /* Subroutine */ int fpadno_(), fpdeno_(), fpbspl_();
+    static integer number;
+    extern /* Subroutine */ int fpseno_();
+    static integer lp1;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local array.. */
+/*  ..subroutine references.. */
+/*    fpbspl,fpadno,fpdeno,fpfrno,fpseno */
+/*  .. */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  if we use the b-spline representation of s(x) our approximation     c */
+/*  problem results in a quadratic programming problem:                 c */
+/*    find the b-spline coefficients c(j),j=1,2,...n-4 such that        c */
+/*        (1) sumi((wi*(yi-sumj(cj*nj(xi))))**2),i=1,2,...m is minimal  c */
+/*        (2) sumj(cj*n''j(t(l+3)))*e(l) <= 0, l=1,2,...n-6.            c */
+/*  to solve this problem we use the theil-van de panne procedure.      c */
+/*  if the inequality constraints (2) are numbered from 1 to n-6,       c */
+/*  this algorithm finds a subset of constraints ibind(1)..ibind(nbind) c */
+/*  such that the solution of the minimization problem (1) with these   c */
+/*  constraints in equality form, satisfies all constraints. such a     c */
+/*  feasible solution is optimal if the lagrange parameters associated  c */
+/*  with that problem with equality constraints, are all positive.      c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  determine n6, the number of inequality constraints. */
+    /* Parameter adjustments */
+    q_dim1 = *m;
+    q_offset = 1 + q_dim1 * 1;
+    q -= q_offset;
+    --sx;
+    --w;
+    --y;
+    --x;
+    --zz;
+    --z__;
+    --const__;
+    a_dim1 = *n;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+    --bind;
+    --c__;
+    --e;
+    --t;
+    --right;
+    --left;
+    --up;
+    --info;
+    --u;
+    b_dim1 = *nm;
+    b_offset = 1 + b_dim1 * 1;
+    b -= b_offset;
+    --ibind;
+    --jbind;
+
+    /* Function Body */
+    n6 = *n - 6;
+/*  fix the parameters which determine these constraints. */
+    i__1 = n6;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	const__[i__] = e[i__] * (t[i__ + 4] - t[i__ + 1]) / (t[i__ + 5] - t[
+		i__ + 2]);
+/* L10: */
+    }
+/*  initialize the triply linked tree which is used to find the subset */
+/*  of constraints ibind(1),...ibind(nbind). */
+    count = 1;
+    info[1] = 0;
+    left[1] = 0;
+    right[1] = 0;
+    up[1] = 1;
+    merk = 1;
+/*  set up the normal equations  n'nc=n'y  where n denotes the m x (n-4) */
+/*  observation matrix with elements ni,j = wi*nj(xi)  and y is the */
+/*  column vector with elements yi*wi. */
+/*  from the properties of the b-splines nj(x),j=1,2,...n-4, it follows */
+/*  that  n'n  is a (n-4) x (n-4)  positive definit bandmatrix of */
+/*  bandwidth 7. the matrices n'n and n'y are built up in a and z. */
+    n4 = *n - 4;
+/*  initialization */
+    i__1 = n4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	z__[i__] = (float)0.;
+	for (j = 1; j <= 4; ++j) {
+	    a[i__ + j * a_dim1] = (float)0.;
+/* L20: */
+	}
+    }
+    l = 4;
+    lp1 = l + 1;
+    i__1 = *m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+/*  fetch the current row of the observation matrix. */
+	xi = x[i__];
+/* Computing 2nd power */
+	r__1 = w[i__];
+	wi = r__1 * r__1;
+/*  search for knot interval  t(l) <= xi < t(l+1) */
+L30:
+	if (xi < t[lp1] || l == n4) {
+	    goto L40;
+	}
+	l = lp1;
+	lp1 = l + 1;
+	goto L30;
+/*  evaluate the four non-zero cubic b-splines nj(xi),j=l-3,...l. */
+L40:
+	fpbspl_(&t[1], n, &c__3, &xi, &l, h__);
+/*  store in q these values h(1),h(2),...h(4). */
+	for (j = 1; j <= 4; ++j) {
+	    q[i__ + j * q_dim1] = h__[j - 1];
+/* L50: */
+	}
+/*  add the contribution of the current row of the observation matrix */
+/*  n to the normal equations. */
+	l3 = l - 3;
+	k1 = 0;
+	i__2 = l;
+	for (j1 = l3; j1 <= i__2; ++j1) {
+	    ++k1;
+	    f = h__[k1 - 1];
+	    z__[j1] += f * wi * y[i__];
+	    k2 = k1;
+	    j2 = 4;
+	    i__3 = l;
+	    for (j3 = j1; j3 <= i__3; ++j3) {
+		a[j3 + j2 * a_dim1] += f * wi * h__[k2 - 1];
+		++k2;
+		--j2;
+/* L60: */
+	    }
+	}
+/* L70: */
+    }
+/*  since n'n is a symmetric matrix it can be factorized as */
+/*        (3)  n'n = (r1)'(d1)(r1) */
+/*  with d1 a diagonal matrix and r1 an (n-4) x (n-4)  unit upper */
+/*  triangular matrix of bandwidth 4. the matrices r1 and d1 are built */
+/*  up in a. at the same time we solve the systems of equations */
+/*        (4)  (r1)'(z2) = n'y */
+/*        (5)  (d1) (z1) = (z2) */
+/*  the vectors z2 and z1 are kept in zz and z. */
+    i__1 = n4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	k1 = 1;
+	if (i__ < 4) {
+	    k1 = 5 - i__;
+	}
+	k2 = i__ - 4 + k1;
+	k3 = k2;
+	for (j = k1; j <= 4; ++j) {
+	    k4 = j - 1;
+	    k5 = 4 - j + k1;
+	    f = a[i__ + j * a_dim1];
+	    if (k1 > k4) {
+		goto L90;
+	    }
+	    k6 = k2;
+	    i__3 = k4;
+	    for (k = k1; k <= i__3; ++k) {
+		f -= a[i__ + k * a_dim1] * a[k3 + k5 * a_dim1] * a[k6 + (
+			a_dim1 << 2)];
+		++k5;
+		++k6;
+/* L80: */
+	    }
+L90:
+	    if (j == 4) {
+		goto L110;
+	    }
+	    a[i__ + j * a_dim1] = f / a[k3 + (a_dim1 << 2)];
+	    ++k3;
+/* L100: */
+	}
+L110:
+	a[i__ + (a_dim1 << 2)] = f;
+	f = z__[i__];
+	if (i__ == 1) {
+	    goto L130;
+	}
+	k4 = i__;
+	for (j = k1; j <= 3; ++j) {
+	    k = k1 + 3 - j;
+	    --k4;
+	    f -= a[i__ + k * a_dim1] * z__[k4] * a[k4 + (a_dim1 << 2)];
+/* L120: */
+	}
+L130:
+	z__[i__] = f / a[i__ + (a_dim1 << 2)];
+	zz[i__] = f;
+/* L140: */
+    }
+/*  start computing the least-squares cubic spline without taking account */
+/*  of any constraint. */
+    nbind = 0;
+    n1 = 1;
+    ibind[1] = 0;
+/*  main loop for the least-squares problems with different subsets of */
+/*  the constraints (2) in equality form. the resulting b-spline coeff. */
+/*  c and lagrange parameters u are the solution of the system */
+/*            ! n'n  b' ! ! c !   ! n'y ! */
+/*        (6) !         ! !   ! = !     ! */
+/*            !  b   0  ! ! u !   !  0  ! */
+/*  z1 is stored into array c. */
+L150:
+    i__1 = n4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = z__[i__];
+/* L160: */
+    }
+/*  if there are no equality constraints, compute the coeff. c directly. */
+    if (nbind == 0) {
+	goto L370;
+    }
+/*  initialization */
+    kdim = n4 + nbind;
+    i__1 = nbind;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	i__3 = kdim;
+	for (j = 1; j <= i__3; ++j) {
+	    b[j + i__ * b_dim1] = (float)0.;
+/* L170: */
+	}
+    }
+/*  matrix b is built up,expressing that the constraints nrs ibind(1),... */
+/*  ibind(nbind) must be satisfied in equality form. */
+    i__3 = nbind;
+    for (i__ = 1; i__ <= i__3; ++i__) {
+	l = ibind[i__];
+	b[l + i__ * b_dim1] = e[l];
+	b[l + 1 + i__ * b_dim1] = -(e[l] + const__[l]);
+	b[l + 2 + i__ * b_dim1] = const__[l];
+/* L180: */
+    }
+/*  find the matrix (b1) as the solution of the system of equations */
+/*        (7)  (r1)'(d1)(b1) = b' */
+/*  (b1) is built up in the upper part of the array b(rows 1,...n-4). */
+    i__3 = nbind;
+    for (k1 = 1; k1 <= i__3; ++k1) {
+	l = ibind[k1];
+	i__1 = n4;
+	for (i__ = l; i__ <= i__1; ++i__) {
+	    f = b[i__ + k1 * b_dim1];
+	    if (i__ == 1) {
+		goto L200;
+	    }
+	    k2 = 3;
+	    if (i__ < 4) {
+		k2 = i__ - 1;
+	    }
+	    i__2 = k2;
+	    for (k3 = 1; k3 <= i__2; ++k3) {
+		l1 = i__ - k3;
+		l2 = 4 - k3;
+		f -= b[l1 + k1 * b_dim1] * a[i__ + l2 * a_dim1] * a[l1 + (
+			a_dim1 << 2)];
+/* L190: */
+	    }
+L200:
+	    b[i__ + k1 * b_dim1] = f / a[i__ + (a_dim1 << 2)];
+/* L210: */
+	}
+/* L220: */
+    }
+/*  factorization of the symmetric matrix  -(b1)'(d1)(b1) */
+/*        (8)  -(b1)'(d1)(b1) = (r2)'(d2)(r2) */
+/*  with (d2) a diagonal matrix and (r2) an nbind x nbind unit upper */
+/*  triangular matrix. the matrices r2 and d2 are built up in the lower */
+/*  part of the array b (rows n-3,n-2,...n-4+nbind). */
+    i__3 = nbind;
+    for (i__ = 1; i__ <= i__3; ++i__) {
+	i1 = i__ - 1;
+	i__1 = nbind;
+	for (j = i__; j <= i__1; ++j) {
+	    f = (float)0.;
+	    i__2 = n4;
+	    for (k = 1; k <= i__2; ++k) {
+		f += b[k + i__ * b_dim1] * b[k + j * b_dim1] * a[k + (a_dim1 
+			<< 2)];
+/* L230: */
+	    }
+	    k1 = n4 + 1;
+	    if (i1 == 0) {
+		goto L250;
+	    }
+	    i__2 = i1;
+	    for (k = 1; k <= i__2; ++k) {
+		f += b[k1 + i__ * b_dim1] * b[k1 + j * b_dim1] * b[k1 + k * 
+			b_dim1];
+		++k1;
+/* L240: */
+	    }
+L250:
+	    b[k1 + j * b_dim1] = -f;
+	    if (j == i__) {
+		goto L260;
+	    }
+	    b[k1 + j * b_dim1] /= b[k1 + i__ * b_dim1];
+L260:
+	    ;
+	}
+/* L270: */
+    }
+/*  according to (3),(7) and (8) the system of equations (6) becomes */
+/*         ! (r1)'    0  ! ! (d1)    0  ! ! (r1)  (b1) ! ! c !   ! n'y ! */
+/*    (9)  !             ! !            ! !            ! !   ! = !     ! */
+/*         ! (b1)'  (r2)'! !   0   (d2) ! !   0   (r2) ! ! u !   !  0  ! */
+/*  backward substitution to obtain the b-spline coefficients c(j),j=1,.. */
+/*  n-4 and the lagrange parameters u(j),j=1,2,...nbind. */
+/*  first step of the backward substitution: solve the system */
+/*             ! (r1)'(d1)      0     ! ! (c1) !   ! n'y ! */
+/*        (10) !                      ! !      ! = !     ! */
+/*             ! (b1)'(d1)  (r2)'(d2) ! ! (u1) !   !  0  ! */
+/*  from (4) and (5) we know that this is equivalent to */
+/*        (11)  (c1) = (z1) */
+/*        (12)  (r2)'(d2)(u1) = -(b1)'(z2) */
+    i__3 = nbind;
+    for (i__ = 1; i__ <= i__3; ++i__) {
+	f = (float)0.;
+	i__1 = n4;
+	for (j = 1; j <= i__1; ++j) {
+	    f += b[j + i__ * b_dim1] * zz[j];
+/* L280: */
+	}
+	i1 = i__ - 1;
+	k1 = n4 + 1;
+	if (i1 == 0) {
+	    goto L300;
+	}
+	i__1 = i1;
+	for (j = 1; j <= i__1; ++j) {
+	    f += u[j] * b[k1 + i__ * b_dim1] * b[k1 + j * b_dim1];
+	    ++k1;
+/* L290: */
+	}
+L300:
+	u[i__] = -f / b[k1 + i__ * b_dim1];
+/* L310: */
+    }
+/*  second step of the backward substitution: solve the system */
+/*             ! (r1)  (b1) ! ! c !   ! c1 ! */
+/*        (13) !            ! !   ! = !    ! */
+/*             !   0   (r2) ! ! u !   ! u1 ! */
+    k1 = nbind;
+    k2 = kdim;
+/*  find the lagrange parameters u. */
+    i__3 = nbind;
+    for (i__ = 1; i__ <= i__3; ++i__) {
+	f = u[k1];
+	if (i__ == 1) {
+	    goto L330;
+	}
+	k3 = k1 + 1;
+	i__1 = nbind;
+	for (j = k3; j <= i__1; ++j) {
+	    f -= u[j] * b[k2 + j * b_dim1];
+/* L320: */
+	}
+L330:
+	u[k1] = f;
+	--k1;
+	--k2;
+/* L340: */
+    }
+/*  find the b-spline coefficients c. */
+    i__3 = n4;
+    for (i__ = 1; i__ <= i__3; ++i__) {
+	f = c__[i__];
+	i__1 = nbind;
+	for (j = 1; j <= i__1; ++j) {
+	    f -= u[j] * b[i__ + j * b_dim1];
+/* L350: */
+	}
+	c__[i__] = f;
+/* L360: */
+    }
+L370:
+    k1 = n4;
+    i__3 = n4;
+    for (i__ = 2; i__ <= i__3; ++i__) {
+	--k1;
+	f = c__[k1];
+	k2 = 1;
+	if (i__ < 5) {
+	    k2 = 5 - i__;
+	}
+	k3 = k1;
+	l = 3;
+	for (j = k2; j <= 3; ++j) {
+	    ++k3;
+	    f -= a[k3 + l * a_dim1] * c__[k3];
+	    --l;
+/* L380: */
+	}
+	c__[k1] = f;
+/* L390: */
+    }
+/*  test whether the solution of the least-squares problem with the */
+/*  constraints ibind(1),...ibind(nbind) in equality form, satisfies */
+/*  all of the constraints (2). */
+    k = 1;
+/*  number counts the number of violated inequality constraints. */
+    number = 0;
+    i__3 = n6;
+    for (j = 1; j <= i__3; ++j) {
+	l = ibind[k];
+	++k;
+	if (j == l) {
+	    goto L440;
+	}
+	--k;
+/*  test whether constraint j is satisfied */
+	f = e[j] * (c__[j] - c__[j + 1]) + const__[j] * (c__[j + 2] - c__[j + 
+		1]);
+	if (f <= (float)0.) {
+	    goto L440;
+	}
+/*  if constraint j is not satisfied, add a branch of length nbind+1 */
+/*  to the tree. the nodes of this branch contain in their information */
+/*  field the number of the constraints ibind(1),...ibind(nbind) and j, */
+/*  arranged in increasing order. */
+	++number;
+	k1 = k - 1;
+	if (k1 == 0) {
+	    goto L410;
+	}
+	i__1 = k1;
+	for (i__ = 1; i__ <= i__1; ++i__) {
+	    jbind[i__] = ibind[i__];
+/* L400: */
+	}
+L410:
+	jbind[k] = j;
+	if (l == 0) {
+	    goto L430;
+	}
+	i__1 = nbind;
+	for (i__ = k; i__ <= i__1; ++i__) {
+	    jbind[i__ + 1] = ibind[i__];
+/* L420: */
+	}
+L430:
+	fpadno_(maxtr, &up[1], &left[1], &right[1], &info[1], &count, &merk, &
+		jbind[1], &n1, ier);
+/*  test whether the storage space which is required for the tree,exceeds */
+/*  the available storage space. */
+	if (*ier != 0) {
+	    goto L560;
+	}
+L440:
+	;
+    }
+/*  test whether the solution of the least-squares problem with equality */
+/*  constraints is a feasible solution. */
+    if (number == 0) {
+	goto L470;
+    }
+/*  test whether there are still cases with nbind constraints in */
+/*  equality form to be considered. */
+L450:
+    if (merk > 1) {
+	goto L460;
+    }
+    nbind = n1;
+/*  test whether the number of knots where s''(x)=0 exceeds maxbin. */
+    if (nbind > *maxbin) {
+	goto L550;
+    }
+    ++n1;
+    ibind[n1] = 0;
+/*  search which cases with nbind constraints in equality form */
+/*  are going to be considered. */
+    fpdeno_(maxtr, &up[1], &left[1], &right[1], &nbind, &merk);
+/*  test whether the quadratic programming problem has a solution. */
+    if (merk == 1) {
+	goto L570;
+    }
+/*  find a new case with nbind constraints in equality form. */
+L460:
+    fpseno_(maxtr, &up[1], &left[1], &right[1], &info[1], &merk, &ibind[1], &
+	    nbind);
+    goto L150;
+/*  test whether the feasible solution is optimal. */
+L470:
+    *ier = 0;
+    i__3 = n6;
+    for (i__ = 1; i__ <= i__3; ++i__) {
+	bind[i__] = FALSE_;
+/* L480: */
+    }
+    if (nbind == 0) {
+	goto L500;
+    }
+    i__3 = nbind;
+    for (i__ = 1; i__ <= i__3; ++i__) {
+	if (u[i__] <= (float)0.) {
+	    goto L450;
+	}
+	j = ibind[i__];
+	bind[j] = TRUE_;
+/* L490: */
+    }
+/*  evaluate s(x) at the data points x(i) and calculate the weighted */
+/*  sum of squared residual right hand sides sq. */
+L500:
+    *sq = (float)0.;
+    l = 4;
+    lp1 = 5;
+    i__3 = *m;
+    for (i__ = 1; i__ <= i__3; ++i__) {
+L510:
+	if (x[i__] < t[lp1] || l == n4) {
+	    goto L520;
+	}
+	l = lp1;
+	lp1 = l + 1;
+	goto L510;
+L520:
+	sx[i__] = c__[l - 3] * q[i__ + q_dim1] + c__[l - 2] * q[i__ + (q_dim1 
+		<< 1)] + c__[l - 1] * q[i__ + q_dim1 * 3] + c__[l] * q[i__ + (
+		q_dim1 << 2)];
+/* Computing 2nd power */
+	r__1 = w[i__] * (y[i__] - sx[i__]);
+	*sq += r__1 * r__1;
+/* L530: */
+    }
+    goto L600;
+/*  error codes and messages. */
+L550:
+    *ier = 1;
+    goto L600;
+L560:
+    *ier = 2;
+    goto L600;
+L570:
+    *ier = 3;
+L600:
+    return 0;
+} /* fpcosp_ */
+
+/* Subroutine */ int fpcsin_(a, b, par, sia, coa, sib, cob, ress, resc)
+real *a, *b, *par, *sia, *coa, *sib, *cob, *ress, *resc;
+{
+    /* System generated locals */
+    real r__1;
+
+    /* Local variables */
+    static real alfa, beta;
+    static integer i__, j;
+    static real three, b2, b4, f1, f2, quart, ab, ai, ab4, fac, one, eps, six,
+	     two;
+
+/*  fpcsin calculates the integrals ress=integral((b-x)**3*sin(par*x)) */
+/*  and resc=integral((b-x)**3*cos(par*x)) over the interval (a,b), */
+/*  given sia=sin(par*a),coa=cos(par*a),sib=sin(par*b) and cob=cos(par*b) */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..local scalars.. */
+/*  ..function references.. */
+/*  .. */
+    one = (float)1.;
+    two = (float)2.;
+    three = (float)3.;
+    six = (float)6.;
+    quart = (float).25;
+    eps = (float)1e-10;
+    ab = *b - *a;
+/* Computing 4th power */
+    r__1 = ab, r__1 *= r__1;
+    ab4 = r__1 * r__1;
+    alfa = ab * *par;
+/* the way of calculating the integrals ress and resc depends on */
+/* the value of alfa = (b-a)*par. */
+    if (dabs(alfa) <= one) {
+	goto L100;
+    }
+/* integration by parts. */
+    beta = one / alfa;
+/* Computing 2nd power */
+    r__1 = beta;
+    b2 = r__1 * r__1;
+/* Computing 2nd power */
+    r__1 = b2;
+    b4 = six * (r__1 * r__1);
+    f1 = three * b2 * (one - two * b2);
+    f2 = beta * (one - six * b2);
+    *ress = ab4 * (*coa * f2 + *sia * f1 + *sib * b4);
+    *resc = ab4 * (*coa * f1 - *sia * f2 + *cob * b4);
+    goto L400;
+/* ress and resc are found by evaluating a series expansion. */
+L100:
+    fac = quart;
+    f1 = fac;
+    f2 = (float)0.;
+    i__ = 4;
+    for (j = 1; j <= 5; ++j) {
+	++i__;
+	ai = (real) i__;
+	fac = fac * alfa / ai;
+	f2 += fac;
+	if (dabs(fac) <= eps) {
+	    goto L300;
+	}
+	++i__;
+	ai = (real) i__;
+	fac = -fac * alfa / ai;
+	f1 += fac;
+	if (dabs(fac) <= eps) {
+	    goto L300;
+	}
+/* L200: */
+    }
+L300:
+    *ress = ab4 * (*coa * f2 + *sia * f1);
+    *resc = ab4 * (*coa * f1 - *sia * f2);
+L400:
+    return 0;
+} /* fpcsin_ */
+
+/* Subroutine */ int fpcurf_(iopt, x, y, w, m, xb, xe, k, s, nest, tol, maxit,
+	 k1, k2, n, t, c__, fp, fpint, z__, a, b, g, q, nrdata, ier)
+integer *iopt;
+real *x, *y, *w;
+integer *m;
+real *xb, *xe;
+integer *k;
+real *s;
+integer *nest;
+real *tol;
+integer *maxit, *k1, *k2, *n;
+real *t, *c__, *fp, *fpint, *z__, *a, *b, *g, *q;
+integer *nrdata, *ier;
+{
+    /* System generated locals */
+    integer a_dim1, a_offset, b_dim1, b_offset, g_dim1, g_offset, q_dim1, 
+	    q_offset, i__1, i__2, i__3, i__4, i__5;
+    real r__1;
+
+    /* Local variables */
+    static real half;
+    static integer nmin, iter, nmax;
+    static real fpms, term, pinv, h__[7];
+    static integer i__, j, l;
+    static real p, fpold, fpart, f1, f2, f3;
+    static integer i1, i2;
+    static real store;
+    static integer i3, k3;
+    static real p1, p2, p3;
+    static integer l0, nplus, nrint, n8;
+    extern /* Subroutine */ int fpback_();
+    static integer it;
+    static real rn, wi, xi, yi;
+    extern /* Subroutine */ int fpdisc_();
+    extern doublereal fprati_();
+    extern /* Subroutine */ int fpbspl_(), fprota_(), fpgivs_(), fpknot_();
+    static real fp0;
+    static integer mk1, nk1;
+    static real acc, one, cos__, sin__;
+    static integer new__;
+    static real piv;
+    static integer ich1, ich3;
+    static real con1, con4, con9;
+    static integer npl1;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references */
+/*  ..subroutine references.. */
+/*    fpback,fpbspl,fpgivs,fpdisc,fpknot,fprota */
+/*  .. */
+/*  set constants */
+    /* Parameter adjustments */
+    --w;
+    --y;
+    --x;
+    --nrdata;
+    --z__;
+    --fpint;
+    --c__;
+    --t;
+    q_dim1 = *m;
+    q_offset = 1 + q_dim1 * 1;
+    q -= q_offset;
+    a_dim1 = *nest;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+    g_dim1 = *nest;
+    g_offset = 1 + g_dim1 * 1;
+    g -= g_offset;
+    b_dim1 = *nest;
+    b_offset = 1 + b_dim1 * 1;
+    b -= b_offset;
+
+    /* Function Body */
+    one = (float)1.;
+    con1 = (float).1;
+    con9 = (float).9;
+    con4 = (float).04;
+    half = (float).5;
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  part 1: determination of the number of knots and their position     c */
+/*  **************************************************************      c */
+/*  given a set of knots we compute the least-squares spline sinf(x),   c */
+/*  and the corresponding sum of squared residuals fp=f(p=inf).         c */
+/*  if iopt=-1 sinf(x) is the requested approximation.                  c */
+/*  if iopt=0 or iopt=1 we check whether we can accept the knots:       c */
+/*    if fp <=s we will continue with the current set of knots.         c */
+/*    if fp > s we will increase the number of knots and compute the    c */
+/*       corresponding least-squares spline until finally fp<=s.        c */
+/*    the initial choice of knots depends on the value of s and iopt.   c */
+/*    if s=0 we have spline interpolation; in that case the number of   c */
+/*    knots equals nmax = m+k+1.                                        c */
+/*    if s > 0 and                                                      c */
+/*      iopt=0 we first compute the least-squares polynomial of         c */
+/*      degree k; n = nmin = 2*k+2                                      c */
+/*      iopt=1 we start with the set of knots found at the last         c */
+/*      call of the routine, except for the case that s > fp0; then     c */
+/*      we compute directly the least-squares polynomial of degree k.   c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  determine nmin, the number of knots for polynomial approximation. */
+    nmin = *k1 << 1;
+    if (*iopt < 0) {
+	goto L60;
+    }
+/*  calculation of acc, the absolute tolerance for the root of f(p)=s. */
+    acc = *tol * *s;
+/*  determine nmax, the number of knots for spline interpolation. */
+    nmax = *m + *k1;
+    if (*s > (float)0.) {
+	goto L45;
+    }
+/*  if s=0, s(x) is an interpolating spline. */
+/*  test whether the required storage space exceeds the available one. */
+    *n = nmax;
+    if (nmax > *nest) {
+	goto L420;
+    }
+/*  find the position of the interior knots in case of interpolation. */
+L10:
+    mk1 = *m - *k1;
+    if (mk1 == 0) {
+	goto L60;
+    }
+    k3 = *k / 2;
+    i__ = *k2;
+    j = k3 + 2;
+    if (k3 << 1 == *k) {
+	goto L30;
+    }
+    i__1 = mk1;
+    for (l = 1; l <= i__1; ++l) {
+	t[i__] = x[j];
+	++i__;
+	++j;
+/* L20: */
+    }
+    goto L60;
+L30:
+    i__1 = mk1;
+    for (l = 1; l <= i__1; ++l) {
+	t[i__] = (x[j] + x[j - 1]) * half;
+	++i__;
+	++j;
+/* L40: */
+    }
+    goto L60;
+/*  if s>0 our initial choice of knots depends on the value of iopt. */
+/*  if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares */
+/*  polynomial of degree k which is a spline without interior knots. */
+/*  if iopt=1 and fp0>s we start computing the least squares spline */
+/*  according to the set of knots found at the last call of the routine. */
+L45:
+    if (*iopt == 0) {
+	goto L50;
+    }
+    if (*n == nmin) {
+	goto L50;
+    }
+    fp0 = fpint[*n];
+    fpold = fpint[*n - 1];
+    nplus = nrdata[*n];
+    if (fp0 > *s) {
+	goto L60;
+    }
+L50:
+    *n = nmin;
+    fpold = (float)0.;
+    nplus = 0;
+    nrdata[1] = *m - 2;
+/*  main loop for the different sets of knots. m is a save upper bound */
+/*  for the number of trials. */
+L60:
+    i__1 = *m;
+    for (iter = 1; iter <= i__1; ++iter) {
+	if (*n == nmin) {
+	    *ier = -2;
+	}
+/*  find nrint, tne number of knot intervals. */
+	nrint = *n - nmin + 1;
+/*  find the position of the additional knots which are needed for */
+/*  the b-spline representation of s(x). */
+	nk1 = *n - *k1;
+	i__ = *n;
+	i__2 = *k1;
+	for (j = 1; j <= i__2; ++j) {
+	    t[j] = *xb;
+	    t[i__] = *xe;
+	    --i__;
+/* L70: */
+	}
+/*  compute the b-spline coefficients of the least-squares spline */
+/*  sinf(x). the observation matrix a is built up row by row and */
+/*  reduced to upper triangular form by givens transformations. */
+/*  at the same time fp=f(p=inf) is computed. */
+	*fp = (float)0.;
+/*  initialize the observation matrix a. */
+	i__2 = nk1;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    z__[i__] = (float)0.;
+	    i__3 = *k1;
+	    for (j = 1; j <= i__3; ++j) {
+		a[i__ + j * a_dim1] = (float)0.;
+/* L80: */
+	    }
+	}
+	l = *k1;
+	i__3 = *m;
+	for (it = 1; it <= i__3; ++it) {
+/*  fetch the current data point x(it),y(it). */
+	    xi = x[it];
+	    wi = w[it];
+	    yi = y[it] * wi;
+/*  search for knot interval t(l) <= xi < t(l+1). */
+L85:
+	    if (xi < t[l + 1] || l == nk1) {
+		goto L90;
+	    }
+	    ++l;
+	    goto L85;
+/*  evaluate the (k+1) non-zero b-splines at xi and store them in q. */
+L90:
+	    fpbspl_(&t[1], n, k, &xi, &l, h__);
+	    i__2 = *k1;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		q[it + i__ * q_dim1] = h__[i__ - 1];
+		h__[i__ - 1] *= wi;
+/* L95: */
+	    }
+/*  rotate the new row of the observation matrix into triangle. */
+	    j = l - *k1;
+	    i__2 = *k1;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		++j;
+		piv = h__[i__ - 1];
+		if (piv == (float)0.) {
+		    goto L110;
+		}
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &a[j + a_dim1], &cos__, &sin__);
+/*  transformations to right hand side. */
+		fprota_(&cos__, &sin__, &yi, &z__[j]);
+		if (i__ == *k1) {
+		    goto L120;
+		}
+		i2 = 1;
+		i3 = i__ + 1;
+		i__4 = *k1;
+		for (i1 = i3; i1 <= i__4; ++i1) {
+		    ++i2;
+/*  transformations to left hand side. */
+		    fprota_(&cos__, &sin__, &h__[i1 - 1], &a[j + i2 * a_dim1])
+			    ;
+/* L100: */
+		}
+L110:
+		;
+	    }
+/*  add contribution of this row to the sum of squares of residual */
+/*  right hand sides. */
+L120:
+/* Computing 2nd power */
+	    r__1 = yi;
+	    *fp += r__1 * r__1;
+/* L130: */
+	}
+	if (*ier == -2) {
+	    fp0 = *fp;
+	}
+	fpint[*n] = fp0;
+	fpint[*n - 1] = fpold;
+	nrdata[*n] = nplus;
+/*  backward substitution to obtain the b-spline coefficients. */
+	fpback_(&a[a_offset], &z__[1], &nk1, k1, &c__[1], nest);
+/*  test whether the approximation sinf(x) is an acceptable solution. */
+	if (*iopt < 0) {
+	    goto L440;
+	}
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  if f(p=inf) < s accept the choice of knots. */
+	if (fpms < (float)0.) {
+	    goto L250;
+	}
+/*  if n = nmax, sinf(x) is an interpolating spline. */
+	if (*n == nmax) {
+	    goto L430;
+	}
+/*  increase the number of knots. */
+/*  if n=nest we cannot increase the number of knots because of */
+/*  the storage capacity limitation. */
+	if (*n == *nest) {
+	    goto L420;
+	}
+/*  determine the number of knots nplus we are going to add. */
+	if (*ier == 0) {
+	    goto L140;
+	}
+	nplus = 1;
+	*ier = 0;
+	goto L150;
+L140:
+	npl1 = nplus << 1;
+	rn = (real) nplus;
+	if (fpold - *fp > acc) {
+	    npl1 = rn * fpms / (fpold - *fp);
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__4 = npl1, i__5 = nplus / 2, i__4 = max(i__4,i__5);
+	i__3 = nplus << 1, i__2 = max(i__4,1);
+	nplus = min(i__3,i__2);
+L150:
+	fpold = *fp;
+/*  compute the sum((w(i)*(y(i)-s(x(i))))**2) for each knot interval */
+/*  t(j+k) <= x(i) <= t(j+k+1) and store it in fpint(j),j=1,2,...nrint. */
+	fpart = (float)0.;
+	i__ = 1;
+	l = *k2;
+	new__ = 0;
+	i__3 = *m;
+	for (it = 1; it <= i__3; ++it) {
+	    if (x[it] < t[l] || l > nk1) {
+		goto L160;
+	    }
+	    new__ = 1;
+	    ++l;
+L160:
+	    term = (float)0.;
+	    l0 = l - *k2;
+	    i__2 = *k1;
+	    for (j = 1; j <= i__2; ++j) {
+		++l0;
+		term += c__[l0] * q[it + j * q_dim1];
+/* L170: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[it] * (term - y[it]);
+	    term = r__1 * r__1;
+	    fpart += term;
+	    if (new__ == 0) {
+		goto L180;
+	    }
+	    store = term * half;
+	    fpint[i__] = fpart - store;
+	    ++i__;
+	    fpart = store;
+	    new__ = 0;
+L180:
+	    ;
+	}
+	fpint[nrint] = fpart;
+	i__3 = nplus;
+	for (l = 1; l <= i__3; ++l) {
+/*  add a new knot. */
+	    fpknot_(&x[1], m, &t[1], n, &fpint[1], &nrdata[1], &nrint, nest, &
+		    c__1);
+/*  if n=nmax we locate the knots as for interpolation. */
+	    if (*n == nmax) {
+		goto L10;
+	    }
+/*  test whether we cannot further increase the number of knots. */
+	    if (*n == *nest) {
+		goto L200;
+	    }
+/* L190: */
+	}
+/*  restart the computations with the new set of knots. */
+L200:
+	;
+    }
+/*  test whether the least-squares kth degree polynomial is a solution */
+/*  of our approximation problem. */
+L250:
+    if (*ier == -2) {
+	goto L440;
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  part 2: determination of the smoothing spline sp(x).                c */
+/*  ***************************************************                 c */
+/*  we have determined the number of knots and their position.          c */
+/*  we now compute the b-spline coefficients of the smoothing spline    c */
+/*  sp(x). the observation matrix a is extended by the rows of matrix   c */
+/*  b expressing that the kth derivative discontinuities of sp(x) at    c */
+/*  the interior knots t(k+2),...t(n-k-1) must be zero. the corres-     c */
+/*  ponding weights of these additional rows are set to 1/p.            c */
+/*  iteratively we then have to determine the value of p such that      c */
+/*  f(p)=sum((w(i)*(y(i)-sp(x(i))))**2) be = s. we already know that    c */
+/*  the least-squares kth degree polynomial corresponds to p=0, and     c */
+/*  that the least-squares spline corresponds to p=infinity. the        c */
+/*  iteration process which is proposed here, makes use of rational     c */
+/*  interpolation. since f(p) is a convex and strictly decreasing       c */
+/*  function of p, it can be approximated by a rational function        c */
+/*  r(p) = (u*p+v)/(p+w). three values of p(p1,p2,p3) with correspond-  c */
+/*  ing values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used      c */
+/*  to calculate the new value of p such that r(p)=s. convergence is    c */
+/*  guaranteed by taking f1>0 and f3<0.                                 c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  evaluate the discontinuity jump of the kth derivative of the */
+/*  b-splines at the knots t(l),l=k+2,...n-k-1 and store in b. */
+    fpdisc_(&t[1], n, k2, &b[b_offset], nest);
+/*  initial value for p. */
+    p1 = (float)0.;
+    f1 = fp0 - *s;
+    p3 = -one;
+    f3 = fpms;
+    p = (float)0.;
+    i__1 = nk1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	p += a[i__ + a_dim1];
+/* L255: */
+    }
+    rn = (real) nk1;
+    p = rn / p;
+    ich1 = 0;
+    ich3 = 0;
+    n8 = *n - nmin;
+/*  iteration process to find the root of f(p) = s. */
+    i__1 = *maxit;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  the rows of matrix b with weight 1/p are rotated into the */
+/*  triangularised observation matrix a which is stored in g. */
+	pinv = one / p;
+	i__3 = nk1;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    c__[i__] = z__[i__];
+	    g[i__ + *k2 * g_dim1] = (float)0.;
+	    i__2 = *k1;
+	    for (j = 1; j <= i__2; ++j) {
+		g[i__ + j * g_dim1] = a[i__ + j * a_dim1];
+/* L260: */
+	    }
+	}
+	i__2 = n8;
+	for (it = 1; it <= i__2; ++it) {
+/*  the row of matrix b is rotated into triangle by givens transformation */
+	    i__3 = *k2;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		h__[i__ - 1] = b[it + i__ * b_dim1] * pinv;
+/* L270: */
+	    }
+	    yi = (float)0.;
+	    i__3 = nk1;
+	    for (j = it; j <= i__3; ++j) {
+		piv = h__[0];
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &g[j + g_dim1], &cos__, &sin__);
+/*  transformations to right hand side. */
+		fprota_(&cos__, &sin__, &yi, &c__[j]);
+		if (j == nk1) {
+		    goto L300;
+		}
+		i2 = *k1;
+		if (j > n8) {
+		    i2 = nk1 - j;
+		}
+		i__4 = i2;
+		for (i__ = 1; i__ <= i__4; ++i__) {
+/*  transformations to left hand side. */
+		    i1 = i__ + 1;
+		    fprota_(&cos__, &sin__, &h__[i1 - 1], &g[j + i1 * g_dim1])
+			    ;
+		    h__[i__ - 1] = h__[i1 - 1];
+/* L280: */
+		}
+		h__[i2] = (float)0.;
+/* L290: */
+	    }
+L300:
+	    ;
+	}
+/*  backward substitution to obtain the b-spline coefficients. */
+	fpback_(&g[g_offset], &c__[1], &nk1, k2, &c__[1], nest);
+/*  computation of f(p). */
+	*fp = (float)0.;
+	l = *k2;
+	i__2 = *m;
+	for (it = 1; it <= i__2; ++it) {
+	    if (x[it] < t[l] || l > nk1) {
+		goto L310;
+	    }
+	    ++l;
+L310:
+	    l0 = l - *k2;
+	    term = (float)0.;
+	    i__3 = *k1;
+	    for (j = 1; j <= i__3; ++j) {
+		++l0;
+		term += c__[l0] * q[it + j * q_dim1];
+/* L320: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[it] * (term - y[it]);
+	    *fp += r__1 * r__1;
+/* L330: */
+	}
+/*  test whether the approximation sp(x) is an acceptable solution. */
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  test whether the maximal number of iterations is reached. */
+	if (iter == *maxit) {
+	    goto L400;
+	}
+/*  carry out one more step of the iteration process. */
+	p2 = p;
+	f2 = fpms;
+	if (ich3 != 0) {
+	    goto L340;
+	}
+	if (f2 - f3 > acc) {
+	    goto L335;
+	}
+/*  our initial choice of p is too large. */
+	p3 = p2;
+	f3 = f2;
+	p *= con4;
+	if (p <= p1) {
+	    p = p1 * con9 + p2 * con1;
+	}
+	goto L360;
+L335:
+	if (f2 < (float)0.) {
+	    ich3 = 1;
+	}
+L340:
+	if (ich1 != 0) {
+	    goto L350;
+	}
+	if (f1 - f2 > acc) {
+	    goto L345;
+	}
+/*  our initial choice of p is too small */
+	p1 = p2;
+	f1 = f2;
+	p /= con4;
+	if (p3 < (float)0.) {
+	    goto L360;
+	}
+	if (p >= p3) {
+	    p = p2 * con1 + p3 * con9;
+	}
+	goto L360;
+L345:
+	if (f2 > (float)0.) {
+	    ich1 = 1;
+	}
+/*  test whether the iteration process proceeds as theoretically */
+/*  expected. */
+L350:
+	if (f2 >= f1 || f2 <= f3) {
+	    goto L410;
+	}
+/*  find the new value for p. */
+	p = fprati_(&p1, &f1, &p2, &f2, &p3, &f3);
+L360:
+	;
+    }
+/*  error codes and messages. */
+L400:
+    *ier = 3;
+    goto L440;
+L410:
+    *ier = 2;
+    goto L440;
+L420:
+    *ier = 1;
+    goto L440;
+L430:
+    *ier = -1;
+L440:
+    return 0;
+} /* fpcurf_ */
+
+/* Subroutine */ int fpcuro_(a, b, c__, d__, x, n)
+real *a, *b, *c__, *d__, *x;
+integer *n;
+{
+    /* System generated locals */
+    integer i__1;
+    real r__1, r__2;
+    doublereal d__1, d__2, d__3, d__4;
+
+    /* Builtin functions */
+    double atan(), sqrt(), atan2(), cos(), pow_dd(), r_sign();
+
+    /* Local variables */
+    static real half, disc, ovfl, tent, four, step, f;
+    static integer i__;
+    static real q, r__, u, y, three, a1, b1, c1, d1, e3, p3, u1, u2, df, pi3, 
+	    two;
+
+/*  subroutine fpcuro finds the real zeros of a cubic polynomial */
+/*  p(x) = a*x**3+b*x**2+c*x+d. */
+
+/*  calling sequence: */
+/*     call fpcuro(a,b,c,d,x,n) */
+
+/*  input parameters: */
+/*    a,b,c,d: real values, containing the coefficients of p(x). */
+
+/*  output parameters: */
+/*    x      : real array,length 3, which contains the real zeros of p(x) */
+/*    n      : integer, giving the number of real zeros of p(x). */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array argument.. */
+/*  ..local scalars.. */
+/*  ..function references.. */
+/*  set constants */
+    /* Parameter adjustments */
+    --x;
+
+    /* Function Body */
+    two = (float)2.;
+    three = (float)3.;
+    four = (float)4.;
+    ovfl = (float)1e4;
+    half = (float).5;
+    tent = (float).1;
+    e3 = tent / (float).3;
+    pi3 = atan((float)1.) / (float).75;
+    a1 = dabs(*a);
+    b1 = dabs(*b);
+    c1 = dabs(*c__);
+    d1 = dabs(*d__);
+/*  test whether p(x) is a third degree polynomial. */
+/* Computing MAX */
+    r__1 = max(b1,c1);
+    if (dmax(r__1,d1) < a1 * ovfl) {
+	goto L300;
+    }
+/*  test whether p(x) is a second degree polynomial. */
+    if (dmax(c1,d1) < b1 * ovfl) {
+	goto L200;
+    }
+/*  test whether p(x) is a first degree polynomial. */
+    if (d1 < c1 * ovfl) {
+	goto L100;
+    }
+/*  p(x) is a constant function. */
+    *n = 0;
+    goto L800;
+/*  p(x) is a first degree polynomial. */
+L100:
+    *n = 1;
+    x[1] = -(*d__) / *c__;
+    goto L500;
+/*  p(x) is a second degree polynomial. */
+L200:
+    disc = *c__ * *c__ - four * *b * *d__;
+    *n = 0;
+    if (disc < (float)0.) {
+	goto L800;
+    }
+    *n = 2;
+    u = sqrt(disc);
+    b1 = *b + *b;
+    x[1] = (-(*c__) + u) / b1;
+    x[2] = (-(*c__) - u) / b1;
+    goto L500;
+/*  p(x) is a third degree polynomial. */
+L300:
+    b1 = *b / *a * e3;
+    c1 = *c__ / *a;
+    d1 = *d__ / *a;
+    q = c1 * e3 - b1 * b1;
+    r__ = b1 * b1 * b1 + (d1 - b1 * c1) * half;
+    disc = q * q * q + r__ * r__;
+    if (disc > (float)0.) {
+	goto L400;
+    }
+    u = sqrt((dabs(q)));
+    if (r__ < (float)0.) {
+	u = -u;
+    }
+    p3 = atan2(sqrt(-disc), (dabs(r__))) * e3;
+    u2 = u + u;
+    *n = 3;
+    x[1] = -u2 * cos(p3) - b1;
+    x[2] = u2 * cos(pi3 - p3) - b1;
+    x[3] = u2 * cos(pi3 + p3) - b1;
+    goto L500;
+L400:
+    u = sqrt(disc);
+    u1 = -r__ + u;
+    u2 = -r__ - u;
+    *n = 1;
+    d__1 = (doublereal) dabs(u1);
+    d__2 = (doublereal) e3;
+    r__1 = pow_dd(&d__1, &d__2);
+    d__3 = (doublereal) dabs(u2);
+    d__4 = (doublereal) e3;
+    r__2 = pow_dd(&d__3, &d__4);
+    x[1] = r_sign(&r__1, &u1) + r_sign(&r__2, &u2) - b1;
+/*  apply a newton iteration to improve the accuracy of the roots. */
+L500:
+    i__1 = *n;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	y = x[i__];
+	f = ((*a * y + *b) * y + *c__) * y + *d__;
+	df = (three * *a * y + two * *b) * y + *c__;
+	step = (float)0.;
+	if (dabs(f) < dabs(df) * tent) {
+	    step = f / df;
+	}
+	x[i__] = y - step;
+/* L700: */
+    }
+L800:
+    return 0;
+} /* fpcuro_ */
+
+/* Subroutine */ int fpcyt1_(a, n, nn)
+real *a;
+integer *n, *nn;
+{
+    /* System generated locals */
+    integer a_dim1, a_offset, i__1;
+
+    /* Local variables */
+    static real beta, teta;
+    static integer i__;
+    static real gamma, v;
+    static integer n1, n2;
+    static real aa, one, sum;
+
+/* (l u)-decomposition of a cyclic tridiagonal matrix with the non-zero */
+/* elements stored as follows */
+
+/*    | a(1,2) a(1,3)                                    a(1,1)  | */
+/*    | a(2,1) a(2,2) a(2,3)                                     | */
+/*    |        a(3,1) a(3,2) a(3,3)                              | */
+/*    |               ...............                            | */
+/*    |                               a(n-1,1) a(n-1,2) a(n-1,3) | */
+/*    | a(n,3)                                  a(n,1)   a(n,2)  | */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+/*  set constant */
+    /* Parameter adjustments */
+    a_dim1 = *nn;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+
+    /* Function Body */
+    one = (float)1.;
+    n2 = *n - 2;
+    beta = one / a[(a_dim1 << 1) + 1];
+    gamma = a[*n + a_dim1 * 3];
+    teta = a[a_dim1 + 1] * beta;
+    a[(a_dim1 << 2) + 1] = beta;
+    a[a_dim1 * 5 + 1] = gamma;
+    a[a_dim1 * 6 + 1] = teta;
+    sum = gamma * teta;
+    i__1 = n2;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	v = a[i__ - 1 + a_dim1 * 3] * beta;
+	aa = a[i__ + a_dim1];
+	beta = one / (a[i__ + (a_dim1 << 1)] - aa * v);
+	gamma = -gamma * v;
+	teta = -teta * aa * beta;
+	a[i__ + (a_dim1 << 2)] = beta;
+	a[i__ + a_dim1 * 5] = gamma;
+	a[i__ + a_dim1 * 6] = teta;
+	sum += gamma * teta;
+/* L10: */
+    }
+    n1 = *n - 1;
+    v = a[n2 + a_dim1 * 3] * beta;
+    aa = a[n1 + a_dim1];
+    beta = one / (a[n1 + (a_dim1 << 1)] - aa * v);
+    gamma = a[*n + a_dim1] - gamma * v;
+    teta = (a[n1 + a_dim1 * 3] - teta * aa) * beta;
+    a[n1 + (a_dim1 << 2)] = beta;
+    a[n1 + a_dim1 * 5] = gamma;
+    a[n1 + a_dim1 * 6] = teta;
+    a[*n + (a_dim1 << 2)] = one / (a[*n + (a_dim1 << 1)] - (sum + gamma * 
+	    teta));
+    return 0;
+} /* fpcyt1_ */
+
+/* Subroutine */ int fpcyt2_(a, n, b, c__, nn)
+real *a;
+integer *n;
+real *b, *c__;
+integer *nn;
+{
+    /* System generated locals */
+    integer a_dim1, a_offset, i__1;
+
+    /* Local variables */
+    static integer i__, j, j1, n1;
+    static real cc, sum;
+
+/* subroutine fpcyt2 solves a linear n x n system */
+/*         a * c = b */
+/* where matrix a is a cyclic tridiagonal matrix, decomposed */
+/* using subroutine fpsyt1. */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --c__;
+    --b;
+    a_dim1 = *nn;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+
+    /* Function Body */
+    c__[1] = b[1] * a[(a_dim1 << 2) + 1];
+    sum = c__[1] * a[a_dim1 * 5 + 1];
+    n1 = *n - 1;
+    i__1 = n1;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	c__[i__] = (b[i__] - a[i__ + a_dim1] * c__[i__ - 1]) * a[i__ + (
+		a_dim1 << 2)];
+	sum += c__[i__] * a[i__ + a_dim1 * 5];
+/* L10: */
+    }
+    cc = (b[*n] - sum) * a[*n + (a_dim1 << 2)];
+    c__[*n] = cc;
+    c__[n1] -= cc * a[n1 + a_dim1 * 6];
+    j = n1;
+    i__1 = *n;
+    for (i__ = 3; i__ <= i__1; ++i__) {
+	j1 = j - 1;
+	c__[j1] = c__[j1] - c__[j] * a[j1 + a_dim1 * 3] * a[j1 + (a_dim1 << 2)
+		] - cc * a[j1 + a_dim1 * 6];
+	j = j1;
+/* L20: */
+    }
+    return 0;
+} /* fpcyt2_ */
+
+/* Subroutine */ int fpdeno_(maxtr, up, left, right, nbind, merk)
+integer *maxtr, *up, *left, *right, *nbind, *merk;
+{
+    static integer i__, j, k, l, point, niveau;
+
+/*  subroutine fpdeno frees the nodes of all branches of a triply linked */
+/*  tree with length < nbind by putting to zero their up field. */
+/*  on exit the parameter merk points to the terminal node of the */
+/*  most left branch of length nbind or takes the value 1 if there */
+/*  is no such branch. */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars .. */
+/*  .. */
+    /* Parameter adjustments */
+    --right;
+    --left;
+    --up;
+
+    /* Function Body */
+    i__ = 1;
+    niveau = 0;
+L10:
+    point = i__;
+    i__ = left[point];
+    if (i__ == 0) {
+	goto L20;
+    }
+    ++niveau;
+    goto L10;
+L20:
+    if (niveau == *nbind) {
+	goto L70;
+    }
+L30:
+    i__ = right[point];
+    j = up[point];
+    up[point] = 0;
+    k = left[j];
+    if (point != k) {
+	goto L50;
+    }
+    if (i__ != 0) {
+	goto L40;
+    }
+    --niveau;
+    if (niveau == 0) {
+	goto L80;
+    }
+    point = j;
+    goto L30;
+L40:
+    left[j] = i__;
+    goto L10;
+L50:
+    l = right[k];
+    if (point == l) {
+	goto L60;
+    }
+    k = l;
+    goto L50;
+L60:
+    right[k] = i__;
+    point = k;
+L70:
+    i__ = right[point];
+    if (i__ != 0) {
+	goto L10;
+    }
+    i__ = up[point];
+    --niveau;
+    if (niveau == 0) {
+	goto L80;
+    }
+    point = i__;
+    goto L70;
+L80:
+    k = 1;
+    l = left[k];
+    if (up[l] == 0) {
+	return 0;
+    }
+L90:
+    *merk = k;
+    k = left[k];
+    if (k != 0) {
+	goto L90;
+    }
+    return 0;
+} /* fpdeno_ */
+
+/* Subroutine */ int fpdisc_(t, n, k2, b, nest)
+real *t;
+integer *n, *k2;
+real *b;
+integer *nest;
+{
+    /* System generated locals */
+    integer b_dim1, b_offset, i__1, i__2, i__3;
+
+    /* Local variables */
+    static real prod, h__[12];
+    static integer i__, j, k, l, nrint, k1;
+    static real an;
+    static integer ik, jk, lj, lk, lp, nk1;
+    static real fac;
+    static integer lmk;
+
+/*  subroutine fpdisc calculates the discontinuity jumps of the kth */
+/*  derivative of the b-splines of degree k at the knots t(k+2)..t(n-k-1) */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local array.. */
+/*  .. */
+    /* Parameter adjustments */
+    --t;
+    b_dim1 = *nest;
+    b_offset = 1 + b_dim1 * 1;
+    b -= b_offset;
+
+    /* Function Body */
+    k1 = *k2 - 1;
+    k = k1 - 1;
+    nk1 = *n - k1;
+    nrint = nk1 - k;
+    an = (real) nrint;
+    fac = an / (t[nk1 + 1] - t[k1]);
+    i__1 = nk1;
+    for (l = *k2; l <= i__1; ++l) {
+	lmk = l - k1;
+	i__2 = k1;
+	for (j = 1; j <= i__2; ++j) {
+	    ik = j + k1;
+	    lj = l + j;
+	    lk = lj - *k2;
+	    h__[j - 1] = t[l] - t[lk];
+	    h__[ik - 1] = t[l] - t[lj];
+/* L10: */
+	}
+	lp = lmk;
+	i__2 = *k2;
+	for (j = 1; j <= i__2; ++j) {
+	    jk = j;
+	    prod = h__[j - 1];
+	    i__3 = k;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		++jk;
+		prod = prod * h__[jk - 1] * fac;
+/* L20: */
+	    }
+	    lk = lp + k1;
+	    b[lmk + j * b_dim1] = (t[lk] - t[lp]) / prod;
+	    ++lp;
+/* L30: */
+	}
+/* L40: */
+    }
+    return 0;
+} /* fpdisc_ */
+
+/* Subroutine */ int fpfrno_(maxtr, up, left, right, info, point, merk, n1, 
+	count, ier)
+integer *maxtr, *up, *left, *right, *info, *point, *merk, *n1, *count, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__, j, k, l, n, niveau;
+
+/*  subroutine fpfrno collects the free nodes (up field zero) of the */
+/*  triply linked tree the information of which is kept in the arrays */
+/*  up,left,right and info. the maximal length of the branches of the */
+/*  tree is given by n1. if no free nodes are found, the error flag */
+/*  ier is set to 1. */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars */
+/*  .. */
+    /* Parameter adjustments */
+    --info;
+    --right;
+    --left;
+    --up;
+
+    /* Function Body */
+    *ier = 1;
+    if (*n1 == 2) {
+	goto L140;
+    }
+    niveau = 1;
+    *count = 2;
+L10:
+    j = 0;
+    i__ = 1;
+L20:
+    if (j == niveau) {
+	goto L30;
+    }
+    k = 0;
+    l = left[i__];
+    if (l == 0) {
+	goto L110;
+    }
+    i__ = l;
+    ++j;
+    goto L20;
+L30:
+    if ((i__1 = i__ - *count) < 0) {
+	goto L110;
+    } else if (i__1 == 0) {
+	goto L100;
+    } else {
+	goto L40;
+    }
+L40:
+    if (up[*count] == 0) {
+	goto L50;
+    }
+    ++(*count);
+    goto L30;
+L50:
+    up[*count] = up[i__];
+    left[*count] = left[i__];
+    right[*count] = right[i__];
+    info[*count] = info[i__];
+    if (*merk == i__) {
+	*merk = *count;
+    }
+    if (*point == i__) {
+	*point = *count;
+    }
+    if (k == 0) {
+	goto L60;
+    }
+    right[k] = *count;
+    goto L70;
+L60:
+    n = up[i__];
+    left[n] = *count;
+L70:
+    l = left[i__];
+L80:
+    if (l == 0) {
+	goto L90;
+    }
+    up[l] = *count;
+    l = right[l];
+    goto L80;
+L90:
+    up[i__] = 0;
+    i__ = *count;
+L100:
+    ++(*count);
+L110:
+    l = right[i__];
+    k = i__;
+    if (l == 0) {
+	goto L120;
+    }
+    i__ = l;
+    goto L20;
+L120:
+    l = up[i__];
+    --j;
+    if (j == 0) {
+	goto L130;
+    }
+    i__ = l;
+    goto L110;
+L130:
+    ++niveau;
+    if (niveau <= *n1) {
+	goto L10;
+    }
+    if (*count > *maxtr) {
+	goto L140;
+    }
+    *ier = 0;
+L140:
+    return 0;
+} /* fpfrno_ */
+
+/* Subroutine */ int fpgivs_(piv, ww, cos__, sin__)
+real *piv, *ww, *cos__, *sin__;
+{
+    /* System generated locals */
+    real r__1;
+
+    /* Builtin functions */
+    double sqrt();
+
+    /* Local variables */
+    static real store, dd, one;
+
+/*  subroutine fpgivs calculates the parameters of a givens */
+/*  transformation . */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..local scalars.. */
+/*  ..function references.. */
+/*  .. */
+    one = (float)1.;
+    store = dabs(*piv);
+    if (store >= *ww) {
+/* Computing 2nd power */
+	r__1 = *ww / *piv;
+	dd = store * sqrt(one + r__1 * r__1);
+    }
+    if (store < *ww) {
+/* Computing 2nd power */
+	r__1 = *piv / *ww;
+	dd = *ww * sqrt(one + r__1 * r__1);
+    }
+    *cos__ = *ww / dd;
+    *sin__ = *piv / dd;
+    *ww = dd;
+    return 0;
+} /* fpgivs_ */
+
+/* Subroutine */ int fpgrdi_(ifsu, ifsv, ifbu, ifbv, iback, u, mu, v, mv, z__,
+	 mz, dz, iop0, iop1, tu, nu, tv, nv, p, c__, nc, sq, fp, fpu, fpv, mm,
+	 mvnu, spu, spv, right, q, au, av1, av2, bu, bv, aa, bb, cc, cosi, 
+	nru, nrv)
+integer *ifsu, *ifsv, *ifbu, *ifbv, *iback;
+real *u;
+integer *mu;
+real *v;
+integer *mv;
+real *z__;
+integer *mz;
+real *dz;
+integer *iop0, *iop1;
+real *tu;
+integer *nu;
+real *tv;
+integer *nv;
+real *p, *c__;
+integer *nc;
+real *sq, *fp, *fpu, *fpv;
+integer *mm, *mvnu;
+real *spu, *spv, *right, *q, *au, *av1, *av2, *bu, *bv, *aa, *bb, *cc, *cosi;
+integer *nru, *nrv;
+{
+    /* System generated locals */
+    integer spu_dim1, spu_offset, spv_dim1, spv_offset, au_dim1, au_offset, 
+	    av1_dim1, av1_offset, av2_dim1, av2_offset, bu_dim1, bu_offset, 
+	    bv_dim1, bv_offset, i__1, i__2, i__3;
+    real r__1;
+
+    /* Builtin functions */
+    double cos(), sin();
+
+    /* Local variables */
+    static real half;
+    static integer ncof, jper;
+    static real term, pinv;
+    static integer irot, numu, numv, numu1, numv1;
+    static real h__[5];
+    static integer i__, j, k, l;
+    static real three;
+    static integer nrold, i0, i1, i2, i3, j0, j1, k1, k2, l0, l1, l2, n1;
+    static real h1[5], h2[4];
+    extern /* Subroutine */ int fpcyt1_(), fpcyt2_();
+    static integer ic;
+    static real co;
+    static integer ii, ij, ik, iq;
+    static real si;
+    static integer it, jj, jk;
+    extern /* Subroutine */ int fpbacp_();
+    static integer iz;
+    extern /* Subroutine */ int fpdisc_(), fpback_(), fpbspl_();
+    static integer number;
+    extern /* Subroutine */ int fprota_(), fpgivs_();
+    static integer nroldu, nroldv;
+    static real dz1, dz2, dz3;
+    static integer nu4, nv4, nu7, nu8, nu9, nv7, nv8;
+    static real fac, arg, one;
+    static integer nv11;
+    static real piv, fac0;
+    static integer mvv, nuu;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpback,fpbspl,fpgivs,fpcyt1,fpcyt2,fpdisc,fpbacp,fprota */
+/*  .. */
+/*  let */
+/*               |   (spu)    |            |   (spv)    | */
+/*        (au) = | ---------- |     (av) = | ---------- | */
+/*               | (1/p) (bu) |            | (1/p) (bv) | */
+
+/*                                | z  ' 0 | */
+/*                            q = | ------ | */
+/*                                | 0  ' 0 | */
+
+/*  with c      : the (nu-4) x (nv-4) matrix which contains the b-spline */
+/*                coefficients. */
+/*       z      : the mu x mv matrix which contains the function values. */
+/*       spu,spv: the mu x (nu-4), resp. mv x (nv-4) observation matrices */
+/*                according to the least-squares problems in the u-,resp. */
+/*                v-direction. */
+/*       bu,bv  : the (nu-7) x (nu-4),resp. (nv-7) x (nv-4) matrices */
+/*                containing the discontinuity jumps of the derivatives */
+/*                of the b-splines in the u-,resp.v-variable at the knots */
+/*  the b-spline coefficients of the smoothing spline are then calculated */
+/*  as the least-squares solution of the following over-determined linear */
+/*  system of equations */
+
+/*    (1)  (av) c (au)' = q */
+
+/*  subject to the constraints */
+
+/*    (2)  c(i,nv-3+j) = c(i,j), j=1,2,3 ; i=1,2,...,nu-4 */
+
+/*    (3)  if iop0 = 0  c(1,j) = dz(1) */
+/*            iop0 = 1  c(1,j) = dz(1) */
+/*                      c(2,j) = dz(1)+(dz(2)*cosi(1,j)+dz(3)*cosi(2,j))* */
+/*                               tu(5)/3. = cc(j) , j=1,2,...nv-4 */
+
+/*    (4)  if iop1 = 1  c(nu-4,j) = 0, j=1,2,...,nv-4. */
+
+/*  set constants */
+    /* Parameter adjustments */
+    --nru;
+    spu_dim1 = *mu;
+    spu_offset = 1 + spu_dim1 * 1;
+    spu -= spu_offset;
+    --u;
+    --nrv;
+    aa -= 3;
+    spv_dim1 = *mv;
+    spv_offset = 1 + spv_dim1 * 1;
+    spv -= spv_offset;
+    --v;
+    --z__;
+    --dz;
+    bu_dim1 = *nu;
+    bu_offset = 1 + bu_dim1 * 1;
+    bu -= bu_offset;
+    au_dim1 = *nu;
+    au_offset = 1 + au_dim1 * 1;
+    au -= au_offset;
+    --fpu;
+    --tu;
+    cosi -= 3;
+    --cc;
+    bb -= 3;
+    bv_dim1 = *nv;
+    bv_offset = 1 + bv_dim1 * 1;
+    bv -= bv_offset;
+    av2_dim1 = *nv;
+    av2_offset = 1 + av2_dim1 * 1;
+    av2 -= av2_offset;
+    av1_dim1 = *nv;
+    av1_offset = 1 + av1_dim1 * 1;
+    av1 -= av1_offset;
+    --fpv;
+    --tv;
+    --c__;
+    --right;
+    --q;
+
+    /* Function Body */
+    one = (float)1.;
+    three = (float)3.;
+    half = (float).5;
+/*  initialization */
+    nu4 = *nu - 4;
+    nu7 = *nu - 7;
+    nu8 = *nu - 8;
+    nu9 = *nu - 9;
+    nv4 = *nv - 4;
+    nv7 = *nv - 7;
+    nv8 = *nv - 8;
+    nv11 = *nv - 11;
+    nuu = nu4 - *iop0 - *iop1 - 1;
+    if (*p > (float)0.) {
+	pinv = one / *p;
+    }
+/*  it depends on the value of the flags ifsu,ifsv,ifbu,ifbv and iop0 and */
+/*  on the value of p whether the matrices (spu), (spv), (bu), (bv) and */
+/*  (cosi) still must be determined. */
+    if (*ifsu != 0) {
+	goto L30;
+    }
+/*  calculate the non-zero elements of the matrix (spu) which is the ob- */
+/*  servation matrix according to the least-squares spline approximation */
+/*  problem in the u-direction. */
+    l = 4;
+    l1 = 5;
+    number = 0;
+    i__1 = *mu;
+    for (it = 1; it <= i__1; ++it) {
+	arg = u[it];
+L10:
+	if (arg < tu[l1] || l == nu4) {
+	    goto L15;
+	}
+	l = l1;
+	l1 = l + 1;
+	++number;
+	goto L10;
+L15:
+	fpbspl_(&tu[1], nu, &c__3, &arg, &l, h__);
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    spu[it + i__ * spu_dim1] = h__[i__ - 1];
+/* L20: */
+	}
+	nru[it] = number;
+/* L25: */
+    }
+    *ifsu = 1;
+/*  calculate the non-zero elements of the matrix (spv) which is the ob- */
+/*  servation matrix according to the least-squares spline approximation */
+/*  problem in the v-direction. */
+L30:
+    if (*ifsv != 0) {
+	goto L85;
+    }
+    l = 4;
+    l1 = 5;
+    number = 0;
+    i__1 = *mv;
+    for (it = 1; it <= i__1; ++it) {
+	arg = v[it];
+L35:
+	if (arg < tv[l1] || l == nv4) {
+	    goto L40;
+	}
+	l = l1;
+	l1 = l + 1;
+	++number;
+	goto L35;
+L40:
+	fpbspl_(&tv[1], nv, &c__3, &arg, &l, h__);
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    spv[it + i__ * spv_dim1] = h__[i__ - 1];
+/* L45: */
+	}
+	nrv[it] = number;
+/* L50: */
+    }
+    *ifsv = 1;
+    if (*iop0 == 0) {
+	goto L85;
+    }
+/*  calculate the coefficients of the interpolating splines for cos(v) */
+/*  and sin(v). */
+    i__1 = nv4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	cosi[(i__ << 1) + 1] = (float)0.;
+	cosi[(i__ << 1) + 2] = (float)0.;
+/* L55: */
+    }
+    if (nv7 < 4) {
+	goto L85;
+    }
+    i__1 = nv7;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	l = i__ + 3;
+	arg = tv[l];
+	fpbspl_(&tv[1], nv, &c__3, &arg, &l, h__);
+	for (j = 1; j <= 3; ++j) {
+	    av1[i__ + j * av1_dim1] = h__[j - 1];
+/* L60: */
+	}
+	cosi[(i__ << 1) + 1] = cos(arg);
+	cosi[(i__ << 1) + 2] = sin(arg);
+/* L65: */
+    }
+    fpcyt1_(&av1[av1_offset], &nv7, nv);
+    for (j = 1; j <= 2; ++j) {
+	i__1 = nv7;
+	for (i__ = 1; i__ <= i__1; ++i__) {
+	    right[i__] = cosi[j + (i__ << 1)];
+/* L70: */
+	}
+	fpcyt2_(&av1[av1_offset], &nv7, &right[1], &right[1], nv);
+	i__1 = nv7;
+	for (i__ = 1; i__ <= i__1; ++i__) {
+	    cosi[j + (i__ + 1 << 1)] = right[i__];
+/* L75: */
+	}
+	cosi[j + 2] = cosi[j + (nv7 + 1 << 1)];
+	cosi[j + (nv7 + 2 << 1)] = cosi[j + 4];
+	cosi[j + (nv4 << 1)] = cosi[j + 6];
+/* L80: */
+    }
+L85:
+    if (*p <= (float)0.) {
+	goto L150;
+    }
+/*  calculate the non-zero elements of the matrix (bu). */
+    if (*ifbu != 0 || nu8 == 0) {
+	goto L90;
+    }
+    fpdisc_(&tu[1], nu, &c__5, &bu[bu_offset], nu);
+    *ifbu = 1;
+/*  calculate the non-zero elements of the matrix (bv). */
+L90:
+    if (*ifbv != 0 || nv8 == 0) {
+	goto L150;
+    }
+    fpdisc_(&tv[1], nv, &c__5, &bv[bv_offset], nv);
+    *ifbv = 1;
+/*  substituting (2),(3) and (4) into (1), we obtain the overdetermined */
+/*  system */
+/*         (5)  (avv) (cr) (auu)' = (qq) */
+/*  from which the nuu*nv7 remaining coefficients */
+/*         c(i,j) , i=2+iop0,3+iop0,...,nu-4-iop1 ; j=1,2,...,nv-7 , */
+/*  the elements of (cr), are then determined in the least-squares sense. */
+/*  simultaneously, we compute the resulting sum of squared residuals sq. */
+L150:
+    dz1 = dz[1];
+    i__1 = *mv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	aa[(i__ << 1) + 1] = dz1;
+/* L155: */
+    }
+    if (nv8 == 0 || *p <= (float)0.) {
+	goto L165;
+    }
+    i__1 = nv8;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	bb[(i__ << 1) + 1] = (float)0.;
+/* L160: */
+    }
+L165:
+    mvv = *mv;
+    if (*iop0 == 0) {
+	goto L220;
+    }
+    fac = tu[5] / three;
+    dz2 = dz[2] * fac;
+    dz3 = dz[3] * fac;
+    i__1 = nv4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	cc[i__] = dz1 + dz2 * cosi[(i__ << 1) + 1] + dz3 * cosi[(i__ << 1) + 
+		2];
+/* L170: */
+    }
+    i__1 = *mv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	number = nrv[i__];
+	fac = (float)0.;
+	for (j = 1; j <= 4; ++j) {
+	    ++number;
+	    fac += cc[number] * spv[i__ + j * spv_dim1];
+/* L180: */
+	}
+	aa[(i__ << 1) + 2] = fac;
+/* L190: */
+    }
+    if (nv8 == 0 || *p <= (float)0.) {
+	goto L220;
+    }
+    i__1 = nv8;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	number = i__;
+	fac = (float)0.;
+	for (j = 1; j <= 5; ++j) {
+	    fac += cc[number] * bv[i__ + j * bv_dim1];
+	    ++number;
+/* L200: */
+	}
+	bb[(i__ << 1) + 2] = fac * pinv;
+/* L210: */
+    }
+    mvv += nv8;
+/*  we first determine the matrices (auu) and (qq). then we reduce the */
+/*  matrix (auu) to upper triangular form (ru) using givens rotations. */
+/*  we apply the same transformations to the rows of matrix qq to obtain */
+/*  the (mv+nv8) x nuu matrix g. */
+/*  we store matrix (ru) into au and g into q. */
+L220:
+    l = mvv * nuu;
+/*  initialization. */
+    *sq = (float)0.;
+    i__1 = l;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	q[i__] = (float)0.;
+/* L230: */
+    }
+    i__1 = nuu;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	for (j = 1; j <= 5; ++j) {
+	    au[i__ + j * au_dim1] = (float)0.;
+/* L240: */
+	}
+    }
+    l = 0;
+    nrold = 0;
+    n1 = nrold + 1;
+    i__1 = *mu;
+    for (it = 1; it <= i__1; ++it) {
+	number = nru[it];
+/*  find the appropriate column of q. */
+L250:
+	i__2 = mvv;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] = (float)0.;
+/* L260: */
+	}
+	if (nrold == number) {
+	    goto L280;
+	}
+	if (*p <= (float)0.) {
+	    goto L410;
+	}
+/*  fetch a new row of matrix (bu). */
+	for (j = 1; j <= 5; ++j) {
+	    h__[j - 1] = bu[n1 + j * bu_dim1] * pinv;
+/* L270: */
+	}
+	i0 = 1;
+	i1 = 5;
+	goto L310;
+/*  fetch a new row of matrix (spu). */
+L280:
+	for (j = 1; j <= 4; ++j) {
+	    h__[j - 1] = spu[it + j * spu_dim1];
+/* L290: */
+	}
+/*  find the appropriate column of q. */
+	i__2 = *mv;
+	for (j = 1; j <= i__2; ++j) {
+	    ++l;
+	    right[j] = z__[l];
+/* L300: */
+	}
+	i0 = 1;
+	i1 = 4;
+L310:
+	if (nu7 - number == *iop1) {
+	    --i1;
+	}
+	j0 = n1;
+/*  take into account that we eliminate the constraints (3) */
+L320:
+	if (j0 - 1 > *iop0) {
+	    goto L360;
+	}
+	fac0 = h__[i0 - 1];
+	i__2 = *mv;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] -= fac0 * aa[j0 + (j << 1)];
+/* L330: */
+	}
+	if (*mv == mvv) {
+	    goto L350;
+	}
+	j = *mv;
+	i__2 = nv8;
+	for (jj = 1; jj <= i__2; ++jj) {
+	    ++j;
+	    right[j] -= fac0 * bb[j0 + (jj << 1)];
+/* L340: */
+	}
+L350:
+	++j0;
+	++i0;
+	goto L320;
+L360:
+	irot = nrold - *iop0 - 1;
+	if (irot < 0) {
+	    irot = 0;
+	}
+/*  rotate the new row of matrix (auu) into triangle. */
+	i__2 = i1;
+	for (i__ = i0; i__ <= i__2; ++i__) {
+	    ++irot;
+	    piv = h__[i__ - 1];
+	    if (piv == (float)0.) {
+		goto L390;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &au[irot + au_dim1], &co, &si);
+/*  apply that transformation to the rows of matrix (qq). */
+	    iq = (irot - 1) * mvv;
+	    i__3 = mvv;
+	    for (j = 1; j <= i__3; ++j) {
+		++iq;
+		fprota_(&co, &si, &right[j], &q[iq]);
+/* L370: */
+	    }
+/*  apply that transformation to the columns of (auu). */
+	    if (i__ == i1) {
+		goto L390;
+	    }
+	    i2 = 1;
+	    i3 = i__ + 1;
+	    i__3 = i1;
+	    for (j = i3; j <= i__3; ++j) {
+		++i2;
+		fprota_(&co, &si, &h__[j - 1], &au[irot + i2 * au_dim1]);
+/* L380: */
+	    }
+L390:
+	    ;
+	}
+/* we update the sum of squared residuals */
+	i__2 = mvv;
+	for (j = 1; j <= i__2; ++j) {
+/* Computing 2nd power */
+	    r__1 = right[j];
+	    *sq += r__1 * r__1;
+/* L395: */
+	}
+/* L400: */
+	if (nrold == number) {
+	    goto L420;
+	}
+L410:
+	nrold = n1;
+	++n1;
+	goto L250;
+L420:
+	;
+    }
+/*  we determine the matrix (avv) and then we reduce her to */
+/*  upper triangular form (rv) using givens rotations. */
+/*  we apply the same transformations to the columns of matrix */
+/*  g to obtain the (nv-7) x (nu-5-iop0-iop1) matrix h. */
+/*  we store matrix (rv) into av1 and av2, h into c. */
+/*  the nv7 x nv7 upper triangular matrix (rv) has the form */
+/*              | av1 '     | */
+/*       (rv) = |     ' av2 | */
+/*              |  0  '     | */
+/*  with (av2) a nv7 x 4 matrix and (av1) a nv11 x nv11 upper */
+/*  triangular matrix of bandwidth 5. */
+    ncof = nuu * nv7;
+/*  initialization. */
+    i__1 = ncof;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = (float)0.;
+/* L430: */
+    }
+    i__1 = nv4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	av1[i__ + av1_dim1 * 5] = (float)0.;
+	for (j = 1; j <= 4; ++j) {
+	    av1[i__ + j * av1_dim1] = (float)0.;
+	    av2[i__ + j * av2_dim1] = (float)0.;
+/* L440: */
+	}
+    }
+    jper = 0;
+    nrold = 0;
+    i__1 = *mv;
+    for (it = 1; it <= i__1; ++it) {
+	number = nrv[it];
+L450:
+	if (nrold == number) {
+	    goto L480;
+	}
+	if (*p <= (float)0.) {
+	    goto L760;
+	}
+/*  fetch a new row of matrix (bv). */
+	n1 = nrold + 1;
+	for (j = 1; j <= 5; ++j) {
+	    h__[j - 1] = bv[n1 + j * bv_dim1] * pinv;
+/* L460: */
+	}
+/*  find the appropiate row of g. */
+	i__2 = nuu;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] = (float)0.;
+/* L465: */
+	}
+	if (*mv == mvv) {
+	    goto L510;
+	}
+	l = *mv + n1;
+	i__2 = nuu;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] = q[l];
+	    l += mvv;
+/* L470: */
+	}
+	goto L510;
+/*  fetch a new row of matrix (spv) */
+L480:
+	h__[4] = (float)0.;
+	for (j = 1; j <= 4; ++j) {
+	    h__[j - 1] = spv[it + j * spv_dim1];
+/* L490: */
+	}
+/*  find the appropiate row of g. */
+	l = it;
+	i__2 = nuu;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] = q[l];
+	    l += mvv;
+/* L500: */
+	}
+/*  test whether there are non-zero values in the new row of (avv) */
+/*  corresponding to the b-splines n(j,v),j=nv7+1,...,nv4. */
+L510:
+	if (nrold < nv11) {
+	    goto L710;
+	}
+	if (jper != 0) {
+	    goto L550;
+	}
+/*  initialize the matrix (av2). */
+	jk = nv11 + 1;
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    ik = jk;
+	    for (j = 1; j <= 5; ++j) {
+		if (ik <= 0) {
+		    goto L530;
+		}
+		av2[ik + i__ * av2_dim1] = av1[ik + j * av1_dim1];
+		--ik;
+/* L520: */
+	    }
+L530:
+	    ++jk;
+/* L540: */
+	}
+	jper = 1;
+/*  if one of the non-zero elements of the new row corresponds to one of */
+/*  the b-splines n(j;v),j=nv7+1,...,nv4, we take account of condition */
+/*  (2) for setting up this row of (avv). the row is stored in h1( the */
+/*  part with respect to av1) and h2 (the part with respect to av2). */
+L550:
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    h1[i__ - 1] = (float)0.;
+	    h2[i__ - 1] = (float)0.;
+/* L560: */
+	}
+	h1[4] = (float)0.;
+	j = nrold - nv11;
+	for (i__ = 1; i__ <= 5; ++i__) {
+	    ++j;
+	    l0 = j;
+L570:
+	    l1 = l0 - 4;
+	    if (l1 <= 0) {
+		goto L590;
+	    }
+	    if (l1 <= nv11) {
+		goto L580;
+	    }
+	    l0 = l1 - nv11;
+	    goto L570;
+L580:
+	    h1[l1 - 1] = h__[i__ - 1];
+	    goto L600;
+L590:
+	    h2[l0 - 1] += h__[i__ - 1];
+L600:
+	    ;
+	}
+/*  rotate the new row of (avv) into triangle. */
+	if (nv11 <= 0) {
+	    goto L670;
+	}
+/*  rotations with the rows 1,2,...,nv11 of (avv). */
+	i__2 = nv11;
+	for (j = 1; j <= i__2; ++j) {
+	    piv = h1[0];
+/* Computing MIN */
+	    i__3 = nv11 - j;
+	    i2 = min(i__3,4);
+	    if (piv == (float)0.) {
+		goto L640;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &av1[j + av1_dim1], &co, &si);
+/*  apply that transformation to the columns of matrix g. */
+	    ic = j;
+	    i__3 = nuu;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		fprota_(&co, &si, &right[i__], &c__[ic]);
+		ic += nv7;
+/* L610: */
+	    }
+/*  apply that transformation to the rows of (avv) with respect to av2. */
+	    for (i__ = 1; i__ <= 4; ++i__) {
+		fprota_(&co, &si, &h2[i__ - 1], &av2[j + i__ * av2_dim1]);
+/* L620: */
+	    }
+/*  apply that transformation to the rows of (avv) with respect to av1. */
+	    if (i2 == 0) {
+		goto L670;
+	    }
+	    i__3 = i2;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		i1 = i__ + 1;
+		fprota_(&co, &si, &h1[i1 - 1], &av1[j + i1 * av1_dim1]);
+/* L630: */
+	    }
+L640:
+	    i__3 = i2;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		h1[i__ - 1] = h1[i__];
+/* L650: */
+	    }
+	    h1[i2] = (float)0.;
+/* L660: */
+	}
+/*  rotations with the rows nv11+1,...,nv7 of avv. */
+L670:
+	for (j = 1; j <= 4; ++j) {
+	    ij = nv11 + j;
+	    if (ij <= 0) {
+		goto L700;
+	    }
+	    piv = h2[j - 1];
+	    if (piv == (float)0.) {
+		goto L700;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &av2[ij + j * av2_dim1], &co, &si);
+/*  apply that transformation to the columns of matrix g. */
+	    ic = ij;
+	    i__2 = nuu;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		fprota_(&co, &si, &right[i__], &c__[ic]);
+		ic += nv7;
+/* L680: */
+	    }
+	    if (j == 4) {
+		goto L700;
+	    }
+/*  apply that transformation to the rows of (avv) with respect to av2. */
+	    j1 = j + 1;
+	    for (i__ = j1; i__ <= 4; ++i__) {
+		fprota_(&co, &si, &h2[i__ - 1], &av2[ij + i__ * av2_dim1]);
+/* L690: */
+	    }
+L700:
+	    ;
+	}
+/* we update the sum of squared residuals */
+	i__2 = nuu;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+/* Computing 2nd power */
+	    r__1 = right[i__];
+	    *sq += r__1 * r__1;
+/* L705: */
+	}
+	goto L750;
+/*  rotation into triangle of the new row of (avv), in case the elements */
+/*  corresponding to the b-splines n(j;v),j=nv7+1,...,nv4 are all zero. */
+L710:
+	irot = nrold;
+	for (i__ = 1; i__ <= 5; ++i__) {
+	    ++irot;
+	    piv = h__[i__ - 1];
+	    if (piv == (float)0.) {
+		goto L740;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &av1[irot + av1_dim1], &co, &si);
+/*  apply that transformation to the columns of matrix g. */
+	    ic = irot;
+	    i__2 = nuu;
+	    for (j = 1; j <= i__2; ++j) {
+		fprota_(&co, &si, &right[j], &c__[ic]);
+		ic += nv7;
+/* L720: */
+	    }
+/*  apply that transformation to the rows of (avv). */
+	    if (i__ == 5) {
+		goto L740;
+	    }
+	    i2 = 1;
+	    i3 = i__ + 1;
+	    for (j = i3; j <= 5; ++j) {
+		++i2;
+		fprota_(&co, &si, &h__[j - 1], &av1[irot + i2 * av1_dim1]);
+/* L730: */
+	    }
+L740:
+	    ;
+	}
+/* we update the sum of squared residuals */
+	i__2 = nuu;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+/* Computing 2nd power */
+	    r__1 = right[i__];
+	    *sq += r__1 * r__1;
+/* L745: */
+	}
+L750:
+	if (nrold == number) {
+	    goto L770;
+	}
+L760:
+	++nrold;
+	goto L450;
+L770:
+	;
+    }
+/*  test whether the b-spline coefficients must be determined. */
+    if (*iback != 0) {
+	return 0;
+    }
+/*  backward substitution to obtain the b-spline coefficients as the */
+/*  solution of the linear system    (rv) (cr) (ru)' = h. */
+/*  first step: solve the system  (rv) (c1) = h. */
+    k = 1;
+    i__1 = nuu;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	fpbacp_(&av1[av1_offset], &av2[av2_offset], &c__[k], &nv7, &c__4, &
+		c__[k], &c__5, nv);
+	k += nv7;
+/* L780: */
+    }
+/*  second step: solve the system  (cr) (ru)' = (c1). */
+    k = 0;
+    i__1 = nv7;
+    for (j = 1; j <= i__1; ++j) {
+	++k;
+	l = k;
+	i__2 = nuu;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    right[i__] = c__[l];
+	    l += nv7;
+/* L790: */
+	}
+	fpback_(&au[au_offset], &right[1], &nuu, &c__5, &right[1], nu);
+	l = k;
+	i__2 = nuu;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    c__[l] = right[i__];
+	    l += nv7;
+/* L795: */
+	}
+/* L800: */
+    }
+/*  calculate from the conditions (2)-(3)-(4), the remaining b-spline */
+/*  coefficients. */
+    ncof = nu4 * nv4;
+    i__ = nv4;
+    j = 0;
+    i__1 = nv4;
+    for (l = 1; l <= i__1; ++l) {
+	q[l] = dz1;
+/* L805: */
+    }
+    if (*iop0 == 0) {
+	goto L815;
+    }
+    i__1 = nv4;
+    for (l = 1; l <= i__1; ++l) {
+	++i__;
+	q[i__] = cc[l];
+/* L810: */
+    }
+L815:
+    if (nuu == 0) {
+	goto L850;
+    }
+    i__1 = nuu;
+    for (l = 1; l <= i__1; ++l) {
+	ii = i__;
+	i__2 = nv7;
+	for (k = 1; k <= i__2; ++k) {
+	    ++i__;
+	    ++j;
+	    q[i__] = c__[j];
+/* L820: */
+	}
+	for (k = 1; k <= 3; ++k) {
+	    ++ii;
+	    ++i__;
+	    q[i__] = q[ii];
+/* L830: */
+	}
+/* L840: */
+    }
+L850:
+    if (*iop1 == 0) {
+	goto L870;
+    }
+    i__1 = nv4;
+    for (l = 1; l <= i__1; ++l) {
+	++i__;
+	q[i__] = (float)0.;
+/* L860: */
+    }
+L870:
+    i__1 = ncof;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = q[i__];
+/* L880: */
+    }
+/*  calculate the quantities */
+/*    res(i,j) = (z(i,j) - s(u(i),v(j)))**2 , i=1,2,..,mu;j=1,2,..,mv */
+/*    fp = sumi=1,mu(sumj=1,mv(res(i,j))) */
+/*    fpu(r) = sum''i(sumj=1,mv(res(i,j))) , r=1,2,...,nu-7 */
+/*                  tu(r+3) <= u(i) <= tu(r+4) */
+/*    fpv(r) = sumi=1,mu(sum''j(res(i,j))) , r=1,2,...,nv-7 */
+/*                  tv(r+3) <= v(j) <= tv(r+4) */
+    *fp = (float)0.;
+    i__1 = *nu;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	fpu[i__] = (float)0.;
+/* L890: */
+    }
+    i__1 = *nv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	fpv[i__] = (float)0.;
+/* L900: */
+    }
+    iz = 0;
+    nroldu = 0;
+/*  main loop for the different grid points. */
+    i__1 = *mu;
+    for (i1 = 1; i1 <= i__1; ++i1) {
+	numu = nru[i1];
+	numu1 = numu + 1;
+	nroldv = 0;
+	i__2 = *mv;
+	for (i2 = 1; i2 <= i__2; ++i2) {
+	    numv = nrv[i2];
+	    numv1 = numv + 1;
+	    ++iz;
+/*  evaluate s(u,v) at the current grid point by making the sum of the */
+/*  cross products of the non-zero b-splines at (u,v), multiplied with */
+/*  the appropiate b-spline coefficients. */
+	    term = (float)0.;
+	    k1 = numu * nv4 + numv;
+	    for (l1 = 1; l1 <= 4; ++l1) {
+		k2 = k1;
+		fac = spu[i1 + l1 * spu_dim1];
+		for (l2 = 1; l2 <= 4; ++l2) {
+		    ++k2;
+		    term += fac * spv[i2 + l2 * spv_dim1] * c__[k2];
+/* L910: */
+		}
+		k1 += nv4;
+/* L920: */
+	    }
+/*  calculate the squared residual at the current grid point. */
+/* Computing 2nd power */
+	    r__1 = z__[iz] - term;
+	    term = r__1 * r__1;
+/*  adjust the different parameters. */
+	    *fp += term;
+	    fpu[numu1] += term;
+	    fpv[numv1] += term;
+	    fac = term * half;
+	    if (numv == nroldv) {
+		goto L930;
+	    }
+	    fpv[numv1] -= fac;
+	    fpv[numv] += fac;
+L930:
+	    nroldv = numv;
+	    if (numu == nroldu) {
+		goto L940;
+	    }
+	    fpu[numu1] -= fac;
+	    fpu[numu] += fac;
+L940:
+	    ;
+	}
+	nroldu = numu;
+/* L950: */
+    }
+    return 0;
+} /* fpgrdi_ */
+
+/* Subroutine */ int fpgrpa_(ifsu, ifsv, ifbu, ifbv, idim, ipar, u, mu, v, mv,
+	 z__, mz, tu, nu, tv, nv, p, c__, nc, fp, fpu, fpv, mm, mvnu, spu, 
+	spv, right, q, au, au1, av, av1, bu, bv, nru, nrv)
+integer *ifsu, *ifsv, *ifbu, *ifbv, *idim, *ipar;
+real *u;
+integer *mu;
+real *v;
+integer *mv;
+real *z__;
+integer *mz;
+real *tu;
+integer *nu;
+real *tv;
+integer *nv;
+real *p, *c__;
+integer *nc;
+real *fp, *fpu, *fpv;
+integer *mm, *mvnu;
+real *spu, *spv, *right, *q, *au, *au1, *av, *av1, *bu, *bv;
+integer *nru, *nrv;
+{
+    /* System generated locals */
+    integer spu_dim1, spu_offset, spv_dim1, spv_offset, au_dim1, au_offset, 
+	    au1_dim1, au1_offset, av_dim1, av_offset, av1_dim1, av1_offset, 
+	    bu_dim1, bu_offset, bv_dim1, bv_offset, i__1, i__2, i__3;
+    real r__1;
+
+    /* Local variables */
+    static real half;
+    static integer ncof;
+    static real term;
+    static integer numu, numv, numu1, numv1;
+    static real h__[5];
+    static integer i__, j, k, l;
+    static real value;
+    static integer i1, i2, k1, k2, l1, l2, k0, id, ii, n33;
+    extern /* Subroutine */ int fpback_();
+    static integer it;
+    extern /* Subroutine */ int fpbacp_();
+    static integer iz, jz;
+    extern /* Subroutine */ int fpdisc_(), fpbspl_();
+    static integer number;
+    extern /* Subroutine */ int fptrpe_();
+    static integer nroldu, nroldv;
+    extern /* Subroutine */ int fptrnp_();
+    static integer nu4, nv4, nu7, nu8, nv7, nv8;
+    static real fac, arg;
+    static integer nmd;
+    static real one;
+    static integer muu, mvv, nuu, nvv;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..subroutine references.. */
+/*    fpback,fpbspl,fpdisc,fpbacp,fptrnp,fptrpe */
+/*  .. */
+/*  let */
+/*               |   (spu)    |            |   (spv)    | */
+/*        (au) = | ---------- |     (av) = | ---------- | */
+/*               | (1/p) (bu) |            | (1/p) (bv) | */
+
+/*                                | z  ' 0 | */
+/*                            q = | ------ | */
+/*                                | 0  ' 0 | */
+
+/*  with c      : the (nu-4) x (nv-4) matrix which contains the b-spline */
+/*                coefficients. */
+/*       z      : the mu x mv matrix which contains the function values. */
+/*       spu,spv: the mu x (nu-4), resp. mv x (nv-4) observation matrices */
+/*                according to the least-squares problems in the u-,resp. */
+/*                v-direction. */
+/*       bu,bv  : the (nu-7) x (nu-4),resp. (nv-7) x (nv-4) matrices */
+/*                containing the discontinuity jumps of the derivatives */
+/*                of the b-splines in the u-,resp.v-variable at the knots */
+/*  the b-spline coefficients of the smoothing spline are then calculated */
+/*  as the least-squares solution of the following over-determined linear */
+/*  system of equations */
+
+/*    (1)  (av) c (au)' = q */
+
+/*  subject to the constraints */
+
+/*    (2)  c(nu-3+i,j) = c(i,j), i=1,2,3 ; j=1,2,...,nv-4 */
+/*            if(ipar(1).ne.0) */
+
+/*    (3)  c(i,nv-3+j) = c(i,j), j=1,2,3 ; i=1,2,...,nu-4 */
+/*            if(ipar(2).ne.0) */
+
+/*  set constants */
+    /* Parameter adjustments */
+    --ipar;
+    --nru;
+    spu_dim1 = *mu;
+    spu_offset = 1 + spu_dim1 * 1;
+    spu -= spu_offset;
+    --u;
+    --nrv;
+    spv_dim1 = *mv;
+    spv_offset = 1 + spv_dim1 * 1;
+    spv -= spv_offset;
+    --v;
+    --z__;
+    bu_dim1 = *nu;
+    bu_offset = 1 + bu_dim1 * 1;
+    bu -= bu_offset;
+    au1_dim1 = *nu;
+    au1_offset = 1 + au1_dim1 * 1;
+    au1 -= au1_offset;
+    au_dim1 = *nu;
+    au_offset = 1 + au_dim1 * 1;
+    au -= au_offset;
+    --fpu;
+    --tu;
+    bv_dim1 = *nv;
+    bv_offset = 1 + bv_dim1 * 1;
+    bv -= bv_offset;
+    av1_dim1 = *nv;
+    av1_offset = 1 + av1_dim1 * 1;
+    av1 -= av1_offset;
+    av_dim1 = *nv;
+    av_offset = 1 + av_dim1 * 1;
+    av -= av_offset;
+    --fpv;
+    --tv;
+    --c__;
+    --right;
+    --q;
+
+    /* Function Body */
+    one = (float)1.;
+    half = (float).5;
+/*  initialization */
+    nu4 = *nu - 4;
+    nu7 = *nu - 7;
+    nu8 = *nu - 8;
+    nv4 = *nv - 4;
+    nv7 = *nv - 7;
+    nv8 = *nv - 8;
+    muu = *mu;
+    if (ipar[1] != 0) {
+	muu = *mu - 1;
+    }
+    mvv = *mv;
+    if (ipar[2] != 0) {
+	mvv = *mv - 1;
+    }
+/*  it depends on the value of the flags ifsu,ifsv,ifbu  and ibvand */
+/*  on the value of p whether the matrices (spu), (spv), (bu) and (bv) */
+/*  still must be determined. */
+    if (*ifsu != 0) {
+	goto L50;
+    }
+/*  calculate the non-zero elements of the matrix (spu) which is the ob- */
+/*  servation matrix according to the least-squares spline approximation */
+/*  problem in the u-direction. */
+    l = 4;
+    l1 = 5;
+    number = 0;
+    i__1 = muu;
+    for (it = 1; it <= i__1; ++it) {
+	arg = u[it];
+L10:
+	if (arg < tu[l1] || l == nu4) {
+	    goto L20;
+	}
+	l = l1;
+	l1 = l + 1;
+	++number;
+	goto L10;
+L20:
+	fpbspl_(&tu[1], nu, &c__3, &arg, &l, h__);
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    spu[it + i__ * spu_dim1] = h__[i__ - 1];
+/* L30: */
+	}
+	nru[it] = number;
+/* L40: */
+    }
+    *ifsu = 1;
+/*  calculate the non-zero elements of the matrix (spv) which is the ob- */
+/*  servation matrix according to the least-squares spline approximation */
+/*  problem in the v-direction. */
+L50:
+    if (*ifsv != 0) {
+	goto L100;
+    }
+    l = 4;
+    l1 = 5;
+    number = 0;
+    i__1 = mvv;
+    for (it = 1; it <= i__1; ++it) {
+	arg = v[it];
+L60:
+	if (arg < tv[l1] || l == nv4) {
+	    goto L70;
+	}
+	l = l1;
+	l1 = l + 1;
+	++number;
+	goto L60;
+L70:
+	fpbspl_(&tv[1], nv, &c__3, &arg, &l, h__);
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    spv[it + i__ * spv_dim1] = h__[i__ - 1];
+/* L80: */
+	}
+	nrv[it] = number;
+/* L90: */
+    }
+    *ifsv = 1;
+L100:
+    if (*p <= (float)0.) {
+	goto L150;
+    }
+/*  calculate the non-zero elements of the matrix (bu). */
+    if (*ifbu != 0 || nu8 == 0) {
+	goto L110;
+    }
+    fpdisc_(&tu[1], nu, &c__5, &bu[bu_offset], nu);
+    *ifbu = 1;
+/*  calculate the non-zero elements of the matrix (bv). */
+L110:
+    if (*ifbv != 0 || nv8 == 0) {
+	goto L150;
+    }
+    fpdisc_(&tv[1], nv, &c__5, &bv[bv_offset], nv);
+    *ifbv = 1;
+/*  substituting (2)  and (3) into (1), we obtain the overdetermined */
+/*  system */
+/*         (4)  (avv) (cr) (auu)' = (qq) */
+/*  from which the nuu*nvv remaining coefficients */
+/*         c(i,j) , i=1,...,nu-4-3*ipar(1) ; j=1,...,nv-4-3*ipar(2) , */
+/*  the elements of (cr), are then determined in the least-squares sense. */
+/*  we first determine the matrices (auu) and (qq). then we reduce the */
+/*  matrix (auu) to upper triangular form (ru) using givens rotations. */
+/*  we apply the same transformations to the rows of matrix qq to obtain */
+/*  the (mv) x nuu matrix g. */
+/*  we store matrix (ru) into au (and au1 if ipar(1)=1) and g into q. */
+L150:
+    if (ipar[1] != 0) {
+	goto L160;
+    }
+    nuu = nu4;
+    fptrnp_(mu, mv, idim, nu, &nru[1], &spu[spu_offset], p, &bu[bu_offset], &
+	    z__[1], &au[au_offset], &q[1], &right[1]);
+    goto L180;
+L160:
+    nuu = nu7;
+    fptrpe_(mu, mv, idim, nu, &nru[1], &spu[spu_offset], p, &bu[bu_offset], &
+	    z__[1], &au[au_offset], &au1[au1_offset], &q[1], &right[1]);
+/*  we determine the matrix (avv) and then we reduce this matrix to */
+/*  upper triangular form (rv) using givens rotations. */
+/*  we apply the same transformations to the columns of matrix */
+/*  g to obtain the (nvv) x (nuu) matrix h. */
+/*  we store matrix (rv) into av (and av1 if ipar(2)=1) and h into c. */
+L180:
+    if (ipar[2] != 0) {
+	goto L190;
+    }
+    nvv = nv4;
+    fptrnp_(mv, &nuu, idim, nv, &nrv[1], &spv[spv_offset], p, &bv[bv_offset], 
+	    &q[1], &av[av_offset], &c__[1], &right[1]);
+    goto L200;
+L190:
+    nvv = nv7;
+    fptrpe_(mv, &nuu, idim, nv, &nrv[1], &spv[spv_offset], p, &bv[bv_offset], 
+	    &q[1], &av[av_offset], &av1[av1_offset], &c__[1], &right[1]);
+/*  backward substitution to obtain the b-spline coefficients as the */
+/*  solution of the linear system    (rv) (cr) (ru)' = h. */
+/*  first step: solve the system  (rv) (c1) = h. */
+L200:
+    ncof = nuu * nvv;
+    k = 1;
+    if (ipar[2] != 0) {
+	goto L240;
+    }
+    i__1 = *idim;
+    for (ii = 1; ii <= i__1; ++ii) {
+	i__2 = nuu;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    fpback_(&av[av_offset], &c__[k], &nvv, &c__5, &c__[k], nv);
+	    k += nvv;
+/* L220: */
+	}
+    }
+    goto L300;
+L240:
+    i__2 = *idim;
+    for (ii = 1; ii <= i__2; ++ii) {
+	i__1 = nuu;
+	for (i__ = 1; i__ <= i__1; ++i__) {
+	    fpbacp_(&av[av_offset], &av1[av1_offset], &c__[k], &nvv, &c__4, &
+		    c__[k], &c__5, nv);
+	    k += nvv;
+/* L260: */
+	}
+    }
+/*  second step: solve the system  (cr) (ru)' = (c1). */
+L300:
+    if (ipar[1] != 0) {
+	goto L400;
+    }
+    i__1 = *idim;
+    for (ii = 1; ii <= i__1; ++ii) {
+	k = (ii - 1) * ncof;
+	i__2 = nvv;
+	for (j = 1; j <= i__2; ++j) {
+	    ++k;
+	    l = k;
+	    i__3 = nuu;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		right[i__] = c__[l];
+		l += nvv;
+/* L320: */
+	    }
+	    fpback_(&au[au_offset], &right[1], &nuu, &c__5, &right[1], nu);
+	    l = k;
+	    i__3 = nuu;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		c__[l] = right[i__];
+		l += nvv;
+/* L340: */
+	    }
+/* L360: */
+	}
+    }
+    goto L500;
+L400:
+    i__2 = *idim;
+    for (ii = 1; ii <= i__2; ++ii) {
+	k = (ii - 1) * ncof;
+	i__1 = nvv;
+	for (j = 1; j <= i__1; ++j) {
+	    ++k;
+	    l = k;
+	    i__3 = nuu;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		right[i__] = c__[l];
+		l += nvv;
+/* L420: */
+	    }
+	    fpbacp_(&au[au_offset], &au1[au1_offset], &right[1], &nuu, &c__4, 
+		    &right[1], &c__5, nu);
+	    l = k;
+	    i__3 = nuu;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		c__[l] = right[i__];
+		l += nvv;
+/* L440: */
+	    }
+/* L460: */
+	}
+    }
+/*  calculate from the conditions (2)-(3), the remaining b-spline */
+/*  coefficients. */
+L500:
+    if (ipar[2] == 0) {
+	goto L600;
+    }
+    i__ = 0;
+    j = 0;
+    i__1 = *idim;
+    for (id = 1; id <= i__1; ++id) {
+	i__2 = nuu;
+	for (l = 1; l <= i__2; ++l) {
+	    ii = i__;
+	    i__3 = nvv;
+	    for (k = 1; k <= i__3; ++k) {
+		++i__;
+		++j;
+		q[i__] = c__[j];
+/* L520: */
+	    }
+	    for (k = 1; k <= 3; ++k) {
+		++ii;
+		++i__;
+		q[i__] = q[ii];
+/* L540: */
+	    }
+/* L560: */
+	}
+    }
+    ncof = nv4 * nuu;
+    nmd = ncof * *idim;
+    i__2 = nmd;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	c__[i__] = q[i__];
+/* L580: */
+    }
+L600:
+    if (ipar[1] == 0) {
+	goto L700;
+    }
+    i__ = 0;
+    j = 0;
+    n33 = nv4 * 3;
+    i__2 = *idim;
+    for (id = 1; id <= i__2; ++id) {
+	ii = i__;
+	i__1 = ncof;
+	for (k = 1; k <= i__1; ++k) {
+	    ++i__;
+	    ++j;
+	    q[i__] = c__[j];
+/* L620: */
+	}
+	i__1 = n33;
+	for (k = 1; k <= i__1; ++k) {
+	    ++ii;
+	    ++i__;
+	    q[i__] = q[ii];
+/* L640: */
+	}
+/* L660: */
+    }
+    ncof = nv4 * nu4;
+    nmd = ncof * *idim;
+    i__2 = nmd;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	c__[i__] = q[i__];
+/* L680: */
+    }
+/*  calculate the quantities */
+/*    res(i,j) = (z(i,j) - s(u(i),v(j)))**2 , i=1,2,..,mu;j=1,2,..,mv */
+/*    fp = sumi=1,mu(sumj=1,mv(res(i,j))) */
+/*    fpu(r) = sum''i(sumj=1,mv(res(i,j))) , r=1,2,...,nu-7 */
+/*                  tu(r+3) <= u(i) <= tu(r+4) */
+/*    fpv(r) = sumi=1,mu(sum''j(res(i,j))) , r=1,2,...,nv-7 */
+/*                  tv(r+3) <= v(j) <= tv(r+4) */
+L700:
+    *fp = (float)0.;
+    i__2 = *nu;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	fpu[i__] = (float)0.;
+/* L720: */
+    }
+    i__2 = *nv;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	fpv[i__] = (float)0.;
+/* L740: */
+    }
+    nroldu = 0;
+/*  main loop for the different grid points. */
+    i__2 = muu;
+    for (i1 = 1; i1 <= i__2; ++i1) {
+	numu = nru[i1];
+	numu1 = numu + 1;
+	nroldv = 0;
+	iz = (i1 - 1) * *mv;
+	i__1 = mvv;
+	for (i2 = 1; i2 <= i__1; ++i2) {
+	    numv = nrv[i2];
+	    numv1 = numv + 1;
+	    ++iz;
+/*  evaluate s(u,v) at the current grid point by making the sum of the */
+/*  cross products of the non-zero b-splines at (u,v), multiplied with */
+/*  the appropiate b-spline coefficients. */
+	    term = (float)0.;
+	    k0 = numu * nv4 + numv;
+	    jz = iz;
+	    i__3 = *idim;
+	    for (id = 1; id <= i__3; ++id) {
+		k1 = k0;
+		value = (float)0.;
+		for (l1 = 1; l1 <= 4; ++l1) {
+		    k2 = k1;
+		    fac = spu[i1 + l1 * spu_dim1];
+		    for (l2 = 1; l2 <= 4; ++l2) {
+			++k2;
+			value += fac * spv[i2 + l2 * spv_dim1] * c__[k2];
+/* L760: */
+		    }
+		    k1 += nv4;
+/* L780: */
+		}
+/*  calculate the squared residual at the current grid point. */
+/* Computing 2nd power */
+		r__1 = z__[jz] - value;
+		term += r__1 * r__1;
+		jz += *mz;
+		k0 += ncof;
+/* L800: */
+	    }
+/*  adjust the different parameters. */
+	    *fp += term;
+	    fpu[numu1] += term;
+	    fpv[numv1] += term;
+	    fac = term * half;
+	    if (numv == nroldv) {
+		goto L820;
+	    }
+	    fpv[numv1] -= fac;
+	    fpv[numv] += fac;
+L820:
+	    nroldv = numv;
+	    if (numu == nroldu) {
+		goto L840;
+	    }
+	    fpu[numu1] -= fac;
+	    fpu[numu] += fac;
+L840:
+	    ;
+	}
+	nroldu = numu;
+/* L860: */
+    }
+    return 0;
+} /* fpgrpa_ */
+
+/* Subroutine */ int fpgrre_(ifsx, ifsy, ifbx, ifby, x, mx, y, my, z__, mz, 
+	kx, ky, tx, nx, ty, ny, p, c__, nc, fp, fpx, fpy, mm, mynx, kx1, kx2, 
+	ky1, ky2, spx, spy, right, q, ax, ay, bx, by, nrx, nry)
+integer *ifsx, *ifsy, *ifbx, *ifby;
+real *x;
+integer *mx;
+real *y;
+integer *my;
+real *z__;
+integer *mz, *kx, *ky;
+real *tx;
+integer *nx;
+real *ty;
+integer *ny;
+real *p, *c__;
+integer *nc;
+real *fp, *fpx, *fpy;
+integer *mm, *mynx, *kx1, *kx2, *ky1, *ky2;
+real *spx, *spy, *right, *q, *ax, *ay, *bx, *by;
+integer *nrx, *nry;
+{
+    /* System generated locals */
+    integer spx_dim1, spx_offset, spy_dim1, spy_offset, ax_dim1, ax_offset, 
+	    bx_dim1, bx_offset, ay_dim1, ay_offset, by_dim1, by_offset, i__1, 
+	    i__2, i__3, i__4;
+    real r__1;
+
+    /* Local variables */
+    static real half;
+    static integer ncof;
+    static real term, pinv;
+    static integer irot, numx, numy, numx1, i__, j, k, l, numy1;
+    static real h__[7];
+    static integer nrold, i1, i2, i3, k1, k2, l1, l2, n1, ic;
+    extern /* Subroutine */ int fpback_();
+    static integer iq, it, ibandx, ibandy, iz;
+    extern /* Subroutine */ int fpdisc_(), fpbspl_();
+    static integer number;
+    extern /* Subroutine */ int fprota_(), fpgivs_();
+    static integer nroldx, nroldy;
+    static real fac, arg, one, cos__, sin__, piv;
+    static integer nk1x, nk1y;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..subroutine references.. */
+/*    fpback,fpbspl,fpgivs,fpdisc,fprota */
+/*  .. */
+/*  the b-spline coefficients of the smoothing spline are calculated as */
+/*  the least-squares solution of the over-determined linear system of */
+/*  equations  (ay) c (ax)' = q       where */
+
+/*               |   (spx)    |            |   (spy)    | */
+/*        (ax) = | ---------- |     (ay) = | ---------- | */
+/*               | (1/p) (bx) |            | (1/p) (by) | */
+
+/*                                | z  ' 0 | */
+/*                            q = | ------ | */
+/*                                | 0  ' 0 | */
+
+/*  with c      : the (ny-ky-1) x (nx-kx-1) matrix which contains the */
+/*                b-spline coefficients. */
+/*       z      : the my x mx matrix which contains the function values. */
+/*       spx,spy: the mx x (nx-kx-1) and  my x (ny-ky-1) observation */
+/*                matrices according to the least-squares problems in */
+/*                the x- and y-direction. */
+/*       bx,by  : the (nx-2*kx-1) x (nx-kx-1) and (ny-2*ky-1) x (ny-ky-1) */
+/*                matrices which contain the discontinuity jumps of the */
+/*                derivatives of the b-splines in the x- and y-direction. */
+    /* Parameter adjustments */
+    --nrx;
+    --x;
+    --nry;
+    --y;
+    --z__;
+    --fpx;
+    --tx;
+    --fpy;
+    --ty;
+    --c__;
+    --right;
+    --q;
+    spx_dim1 = *mx;
+    spx_offset = 1 + spx_dim1 * 1;
+    spx -= spx_offset;
+    bx_dim1 = *nx;
+    bx_offset = 1 + bx_dim1 * 1;
+    bx -= bx_offset;
+    ax_dim1 = *nx;
+    ax_offset = 1 + ax_dim1 * 1;
+    ax -= ax_offset;
+    spy_dim1 = *my;
+    spy_offset = 1 + spy_dim1 * 1;
+    spy -= spy_offset;
+    by_dim1 = *ny;
+    by_offset = 1 + by_dim1 * 1;
+    by -= by_offset;
+    ay_dim1 = *ny;
+    ay_offset = 1 + ay_dim1 * 1;
+    ay -= ay_offset;
+
+    /* Function Body */
+    one = (float)1.;
+    half = (float).5;
+    nk1x = *nx - *kx1;
+    nk1y = *ny - *ky1;
+    if (*p > (float)0.) {
+	pinv = one / *p;
+    }
+/*  it depends on the value of the flags ifsx,ifsy,ifbx and ifby and on */
+/*  the value of p whether the matrices (spx),(spy),(bx) and (by) still */
+/*  must be determined. */
+    if (*ifsx != 0) {
+	goto L50;
+    }
+/*  calculate the non-zero elements of the matrix (spx) which is the */
+/*  observation matrix according to the least-squares spline approximat- */
+/*  ion problem in the x-direction. */
+    l = *kx1;
+    l1 = *kx2;
+    number = 0;
+    i__1 = *mx;
+    for (it = 1; it <= i__1; ++it) {
+	arg = x[it];
+L10:
+	if (arg < tx[l1] || l == nk1x) {
+	    goto L20;
+	}
+	l = l1;
+	l1 = l + 1;
+	++number;
+	goto L10;
+L20:
+	fpbspl_(&tx[1], nx, kx, &arg, &l, h__);
+	i__2 = *kx1;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    spx[it + i__ * spx_dim1] = h__[i__ - 1];
+/* L30: */
+	}
+	nrx[it] = number;
+/* L40: */
+    }
+    *ifsx = 1;
+L50:
+    if (*ifsy != 0) {
+	goto L100;
+    }
+/*  calculate the non-zero elements of the matrix (spy) which is the */
+/*  observation matrix according to the least-squares spline approximat- */
+/*  ion problem in the y-direction. */
+    l = *ky1;
+    l1 = *ky2;
+    number = 0;
+    i__1 = *my;
+    for (it = 1; it <= i__1; ++it) {
+	arg = y[it];
+L60:
+	if (arg < ty[l1] || l == nk1y) {
+	    goto L70;
+	}
+	l = l1;
+	l1 = l + 1;
+	++number;
+	goto L60;
+L70:
+	fpbspl_(&ty[1], ny, ky, &arg, &l, h__);
+	i__2 = *ky1;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    spy[it + i__ * spy_dim1] = h__[i__ - 1];
+/* L80: */
+	}
+	nry[it] = number;
+/* L90: */
+    }
+    *ifsy = 1;
+L100:
+    if (*p <= (float)0.) {
+	goto L120;
+    }
+/*  calculate the non-zero elements of the matrix (bx). */
+    if (*ifbx != 0 || *nx == *kx1 << 1) {
+	goto L110;
+    }
+    fpdisc_(&tx[1], nx, kx2, &bx[bx_offset], nx);
+    *ifbx = 1;
+/*  calculate the non-zero elements of the matrix (by). */
+L110:
+    if (*ifby != 0 || *ny == *ky1 << 1) {
+	goto L120;
+    }
+    fpdisc_(&ty[1], ny, ky2, &by[by_offset], ny);
+    *ifby = 1;
+/*  reduce the matrix (ax) to upper triangular form (rx) using givens */
+/*  rotations. apply the same transformations to the rows of matrix q */
+/*  to obtain the my x (nx-kx-1) matrix g. */
+/*  store matrix (rx) into (ax) and g into q. */
+L120:
+    l = *my * nk1x;
+/*  initialization. */
+    i__1 = l;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	q[i__] = (float)0.;
+/* L130: */
+    }
+    i__1 = nk1x;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	i__2 = *kx2;
+	for (j = 1; j <= i__2; ++j) {
+	    ax[i__ + j * ax_dim1] = (float)0.;
+/* L140: */
+	}
+    }
+    l = 0;
+    nrold = 0;
+/*  ibandx denotes the bandwidth of the matrices (ax) and (rx). */
+    ibandx = *kx1;
+    i__2 = *mx;
+    for (it = 1; it <= i__2; ++it) {
+	number = nrx[it];
+L150:
+	if (nrold == number) {
+	    goto L180;
+	}
+	if (*p <= (float)0.) {
+	    goto L260;
+	}
+	ibandx = *kx2;
+/*  fetch a new row of matrix (bx). */
+	n1 = nrold + 1;
+	i__1 = *kx2;
+	for (j = 1; j <= i__1; ++j) {
+	    h__[j - 1] = bx[n1 + j * bx_dim1] * pinv;
+/* L160: */
+	}
+/*  find the appropriate column of q. */
+	i__1 = *my;
+	for (j = 1; j <= i__1; ++j) {
+	    right[j] = (float)0.;
+/* L170: */
+	}
+	irot = nrold;
+	goto L210;
+/*  fetch a new row of matrix (spx). */
+L180:
+	h__[ibandx - 1] = (float)0.;
+	i__1 = *kx1;
+	for (j = 1; j <= i__1; ++j) {
+	    h__[j - 1] = spx[it + j * spx_dim1];
+/* L190: */
+	}
+/*  find the appropriate column of q. */
+	i__1 = *my;
+	for (j = 1; j <= i__1; ++j) {
+	    ++l;
+	    right[j] = z__[l];
+/* L200: */
+	}
+	irot = number;
+/*  rotate the new row of matrix (ax) into triangle. */
+L210:
+	i__1 = ibandx;
+	for (i__ = 1; i__ <= i__1; ++i__) {
+	    ++irot;
+	    piv = h__[i__ - 1];
+	    if (piv == (float)0.) {
+		goto L240;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &ax[irot + ax_dim1], &cos__, &sin__);
+/*  apply that transformation to the rows of matrix q. */
+	    iq = (irot - 1) * *my;
+	    i__3 = *my;
+	    for (j = 1; j <= i__3; ++j) {
+		++iq;
+		fprota_(&cos__, &sin__, &right[j], &q[iq]);
+/* L220: */
+	    }
+/*  apply that transformation to the columns of (ax). */
+	    if (i__ == ibandx) {
+		goto L250;
+	    }
+	    i2 = 1;
+	    i3 = i__ + 1;
+	    i__3 = ibandx;
+	    for (j = i3; j <= i__3; ++j) {
+		++i2;
+		fprota_(&cos__, &sin__, &h__[j - 1], &ax[irot + i2 * ax_dim1])
+			;
+/* L230: */
+	    }
+L240:
+	    ;
+	}
+L250:
+	if (nrold == number) {
+	    goto L270;
+	}
+L260:
+	++nrold;
+	goto L150;
+L270:
+	;
+    }
+/*  reduce the matrix (ay) to upper triangular form (ry) using givens */
+/*  rotations. apply the same transformations to the columns of matrix g */
+/*  to obtain the (ny-ky-1) x (nx-kx-1) matrix h. */
+/*  store matrix (ry) into (ay) and h into c. */
+    ncof = nk1x * nk1y;
+/*  initialization. */
+    i__2 = ncof;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	c__[i__] = (float)0.;
+/* L280: */
+    }
+    i__2 = nk1y;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	i__1 = *ky2;
+	for (j = 1; j <= i__1; ++j) {
+	    ay[i__ + j * ay_dim1] = (float)0.;
+/* L290: */
+	}
+    }
+    nrold = 0;
+/*  ibandy denotes the bandwidth of the matrices (ay) and (ry). */
+    ibandy = *ky1;
+    i__1 = *my;
+    for (it = 1; it <= i__1; ++it) {
+	number = nry[it];
+L300:
+	if (nrold == number) {
+	    goto L330;
+	}
+	if (*p <= (float)0.) {
+	    goto L410;
+	}
+	ibandy = *ky2;
+/*  fetch a new row of matrix (by). */
+	n1 = nrold + 1;
+	i__2 = *ky2;
+	for (j = 1; j <= i__2; ++j) {
+	    h__[j - 1] = by[n1 + j * by_dim1] * pinv;
+/* L310: */
+	}
+/*  find the appropiate row of g. */
+	i__2 = nk1x;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] = (float)0.;
+/* L320: */
+	}
+	irot = nrold;
+	goto L360;
+/*  fetch a new row of matrix (spy) */
+L330:
+	h__[ibandy - 1] = (float)0.;
+	i__2 = *ky1;
+	for (j = 1; j <= i__2; ++j) {
+	    h__[j - 1] = spy[it + j * spy_dim1];
+/* L340: */
+	}
+/*  find the appropiate row of g. */
+	l = it;
+	i__2 = nk1x;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] = q[l];
+	    l += *my;
+/* L350: */
+	}
+	irot = number;
+/*  rotate the new row of matrix (ay) into triangle. */
+L360:
+	i__2 = ibandy;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ++irot;
+	    piv = h__[i__ - 1];
+	    if (piv == (float)0.) {
+		goto L390;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &ay[irot + ay_dim1], &cos__, &sin__);
+/*  apply that transformation to the colums of matrix g. */
+	    ic = irot;
+	    i__3 = nk1x;
+	    for (j = 1; j <= i__3; ++j) {
+		fprota_(&cos__, &sin__, &right[j], &c__[ic]);
+		ic += nk1y;
+/* L370: */
+	    }
+/*  apply that transformation to the columns of matrix (ay). */
+	    if (i__ == ibandy) {
+		goto L400;
+	    }
+	    i2 = 1;
+	    i3 = i__ + 1;
+	    i__3 = ibandy;
+	    for (j = i3; j <= i__3; ++j) {
+		++i2;
+		fprota_(&cos__, &sin__, &h__[j - 1], &ay[irot + i2 * ay_dim1])
+			;
+/* L380: */
+	    }
+L390:
+	    ;
+	}
+L400:
+	if (nrold == number) {
+	    goto L420;
+	}
+L410:
+	++nrold;
+	goto L300;
+L420:
+	;
+    }
+/*  backward substitution to obtain the b-spline coefficients as the */
+/*  solution of the linear system    (ry) c (rx)' = h. */
+/*  first step: solve the system  (ry) (c1) = h. */
+    k = 1;
+    i__1 = nk1x;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	fpback_(&ay[ay_offset], &c__[k], &nk1y, &ibandy, &c__[k], ny);
+	k += nk1y;
+/* L450: */
+    }
+/*  second step: solve the system  c (rx)' = (c1). */
+    k = 0;
+    i__1 = nk1y;
+    for (j = 1; j <= i__1; ++j) {
+	++k;
+	l = k;
+	i__2 = nk1x;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    right[i__] = c__[l];
+	    l += nk1y;
+/* L460: */
+	}
+	fpback_(&ax[ax_offset], &right[1], &nk1x, &ibandx, &right[1], nx);
+	l = k;
+	i__2 = nk1x;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    c__[l] = right[i__];
+	    l += nk1y;
+/* L470: */
+	}
+/* L480: */
+    }
+/*  calculate the quantities */
+/*    res(i,j) = (z(i,j) - s(x(i),y(j)))**2 , i=1,2,..,mx;j=1,2,..,my */
+/*    fp = sumi=1,mx(sumj=1,my(res(i,j))) */
+/*    fpx(r) = sum''i(sumj=1,my(res(i,j))) , r=1,2,...,nx-2*kx-1 */
+/*                  tx(r+kx) <= x(i) <= tx(r+kx+1) */
+/*    fpy(r) = sumi=1,mx(sum''j(res(i,j))) , r=1,2,...,ny-2*ky-1 */
+/*                  ty(r+ky) <= y(j) <= ty(r+ky+1) */
+    *fp = (float)0.;
+    i__1 = *nx;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	fpx[i__] = (float)0.;
+/* L490: */
+    }
+    i__1 = *ny;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	fpy[i__] = (float)0.;
+/* L500: */
+    }
+    nk1y = *ny - *ky1;
+    iz = 0;
+    nroldx = 0;
+/*  main loop for the different grid points. */
+    i__1 = *mx;
+    for (i1 = 1; i1 <= i__1; ++i1) {
+	numx = nrx[i1];
+	numx1 = numx + 1;
+	nroldy = 0;
+	i__2 = *my;
+	for (i2 = 1; i2 <= i__2; ++i2) {
+	    numy = nry[i2];
+	    numy1 = numy + 1;
+	    ++iz;
+/*  evaluate s(x,y) at the current grid point by making the sum of the */
+/*  cross products of the non-zero b-splines at (x,y), multiplied with */
+/*  the appropiate b-spline coefficients. */
+	    term = (float)0.;
+	    k1 = numx * nk1y + numy;
+	    i__3 = *kx1;
+	    for (l1 = 1; l1 <= i__3; ++l1) {
+		k2 = k1;
+		fac = spx[i1 + l1 * spx_dim1];
+		i__4 = *ky1;
+		for (l2 = 1; l2 <= i__4; ++l2) {
+		    ++k2;
+		    term += fac * spy[i2 + l2 * spy_dim1] * c__[k2];
+/* L510: */
+		}
+		k1 += nk1y;
+/* L520: */
+	    }
+/*  calculate the squared residual at the current grid point. */
+/* Computing 2nd power */
+	    r__1 = z__[iz] - term;
+	    term = r__1 * r__1;
+/*  adjust the different parameters. */
+	    *fp += term;
+	    fpx[numx1] += term;
+	    fpy[numy1] += term;
+	    fac = term * half;
+	    if (numy == nroldy) {
+		goto L530;
+	    }
+	    fpy[numy1] -= fac;
+	    fpy[numy] += fac;
+L530:
+	    nroldy = numy;
+	    if (numx == nroldx) {
+		goto L540;
+	    }
+	    fpx[numx1] -= fac;
+	    fpx[numx] += fac;
+L540:
+	    ;
+	}
+	nroldx = numx;
+/* L550: */
+    }
+    return 0;
+} /* fpgrre_ */
+
+/* Subroutine */ int fpgrsp_(ifsu, ifsv, ifbu, ifbv, iback, u, mu, v, mv, r__,
+	 mr, dr, iop0, iop1, tu, nu, tv, nv, p, c__, nc, sq, fp, fpu, fpv, mm,
+	 mvnu, spu, spv, right, q, au, av1, av2, bu, bv, a0, a1, b0, b1, c0, 
+	c1, cosi, nru, nrv)
+integer *ifsu, *ifsv, *ifbu, *ifbv, *iback;
+real *u;
+integer *mu;
+real *v;
+integer *mv;
+real *r__;
+integer *mr;
+real *dr;
+integer *iop0, *iop1;
+real *tu;
+integer *nu;
+real *tv;
+integer *nv;
+real *p, *c__;
+integer *nc;
+real *sq, *fp, *fpu, *fpv;
+integer *mm, *mvnu;
+real *spu, *spv, *right, *q, *au, *av1, *av2, *bu, *bv, *a0, *a1, *b0, *b1, *
+	c0, *c1, *cosi;
+integer *nru, *nrv;
+{
+    /* System generated locals */
+    integer spu_dim1, spu_offset, spv_dim1, spv_offset, au_dim1, au_offset, 
+	    av1_dim1, av1_offset, av2_dim1, av2_offset, bu_dim1, bu_offset, 
+	    bv_dim1, bv_offset, i__1, i__2, i__3;
+    real r__1;
+
+    /* Builtin functions */
+    double cos(), sin();
+
+    /* Local variables */
+    static real half;
+    static integer ncof, jper;
+    static real term, pinv;
+    static integer irot, numu, numv, numu1, numv1;
+    static real h__[5];
+    static integer i__, j, k, l;
+    static real three;
+    static integer nrold, i0, i1, i2, i3, j0, j1, k1, k2, l0, l1, l2, n1;
+    static real h1[5], h2[4];
+    extern /* Subroutine */ int fpcyt1_(), fpcyt2_();
+    static integer ic;
+    static real co;
+    static integer ii, ij, ik;
+    static real si;
+    static integer iq, it, ir, jj, jk;
+    extern /* Subroutine */ int fpdisc_(), fpbacp_(), fpback_(), fpbspl_();
+    static integer number;
+    extern /* Subroutine */ int fprota_(), fpgivs_();
+    static integer nroldu, nroldv, nu4, nv4, nu7, nu8, nu9, nv7, nv8;
+    static real fac, dr01, dr02, dr03, arg, dr11, dr12, dr13, one;
+    static integer nv11;
+    static real piv, fac0, fac1;
+    static integer mvv, nuu;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpback,fpbspl,fpgivs,fpcyt1,fpcyt2,fpdisc,fpbacp,fprota */
+/*  .. */
+/*  let */
+/*               |     (spu)      |            |     (spv)      | */
+/*        (au) = | -------------- |     (av) = | -------------- | */
+/*               | sqrt(1/p) (bu) |            | sqrt(1/p) (bv) | */
+
+/*                                | r  ' 0 | */
+/*                            q = | ------ | */
+/*                                | 0  ' 0 | */
+
+/*  with c      : the (nu-4) x (nv-4) matrix which contains the b-spline */
+/*                coefficients. */
+/*       r      : the mu x mv matrix which contains the function values. */
+/*       spu,spv: the mu x (nu-4), resp. mv x (nv-4) observation matrices */
+/*                according to the least-squares problems in the u-,resp. */
+/*                v-direction. */
+/*       bu,bv  : the (nu-7) x (nu-4),resp. (nv-7) x (nv-4) matrices */
+/*                containing the discontinuity jumps of the derivatives */
+/*                of the b-splines in the u-,resp.v-variable at the knots */
+/*  the b-spline coefficients of the smoothing spline are then calculated */
+/*  as the least-squares solution of the following over-determined linear */
+/*  system of equations */
+
+/*  (1)  (av) c (au)' = q */
+
+/*  subject to the constraints */
+
+/*  (2)  c(i,nv-3+j) = c(i,j), j=1,2,3 ; i=1,2,...,nu-4 */
+
+/*  (3)  if iop0 = 0  c(1,j) = dr(1) */
+/*          iop0 = 1  c(1,j) = dr(1) */
+/*                    c(2,j) = dr(1)+(dr(2)*cosi(1,j)+dr(3)*cosi(2,j))* */
+/*                            tu(5)/3. = c0(j) , j=1,2,...nv-4 */
+
+/*  (4)  if iop1 = 0  c(nu-4,j) = dr(4) */
+/*          iop1 = 1  c(nu-4,j) = dr(4) */
+/*                    c(nu-5,j) = dr(4)+(dr(5)*cosi(1,j)+dr(6)*cosi(2,j)) */
+/*                                *(tu(nu-4)-tu(nu-3))/3. = c1(j) */
+
+/*  set constants */
+    /* Parameter adjustments */
+    --nru;
+    spu_dim1 = *mu;
+    spu_offset = 1 + spu_dim1 * 1;
+    spu -= spu_offset;
+    --u;
+    --nrv;
+    a1 -= 3;
+    a0 -= 3;
+    spv_dim1 = *mv;
+    spv_offset = 1 + spv_dim1 * 1;
+    spv -= spv_offset;
+    --v;
+    --r__;
+    --dr;
+    bu_dim1 = *nu;
+    bu_offset = 1 + bu_dim1 * 1;
+    bu -= bu_offset;
+    au_dim1 = *nu;
+    au_offset = 1 + au_dim1 * 1;
+    au -= au_offset;
+    --fpu;
+    --tu;
+    cosi -= 3;
+    --c1;
+    --c0;
+    b1 -= 3;
+    b0 -= 3;
+    bv_dim1 = *nv;
+    bv_offset = 1 + bv_dim1 * 1;
+    bv -= bv_offset;
+    av2_dim1 = *nv;
+    av2_offset = 1 + av2_dim1 * 1;
+    av2 -= av2_offset;
+    av1_dim1 = *nv;
+    av1_offset = 1 + av1_dim1 * 1;
+    av1 -= av1_offset;
+    --fpv;
+    --tv;
+    --c__;
+    --right;
+    --q;
+
+    /* Function Body */
+    one = (float)1.;
+    three = (float)3.;
+    half = (float).5;
+/*  initialization */
+    nu4 = *nu - 4;
+    nu7 = *nu - 7;
+    nu8 = *nu - 8;
+    nu9 = *nu - 9;
+    nv4 = *nv - 4;
+    nv7 = *nv - 7;
+    nv8 = *nv - 8;
+    nv11 = *nv - 11;
+    nuu = nu4 - *iop0 - *iop1 - 2;
+    if (*p > (float)0.) {
+	pinv = one / *p;
+    }
+/*  it depends on the value of the flags ifsu,ifsv,ifbu,ifbv,iop0,iop1 */
+/*  and on the value of p whether the matrices (spu), (spv), (bu), (bv), */
+/*  (cosi) still must be determined. */
+    if (*ifsu != 0) {
+	goto L30;
+    }
+/*  calculate the non-zero elements of the matrix (spu) which is the ob- */
+/*  servation matrix according to the least-squares spline approximation */
+/*  problem in the u-direction. */
+    l = 4;
+    l1 = 5;
+    number = 0;
+    i__1 = *mu;
+    for (it = 1; it <= i__1; ++it) {
+	arg = u[it];
+L10:
+	if (arg < tu[l1] || l == nu4) {
+	    goto L15;
+	}
+	l = l1;
+	l1 = l + 1;
+	++number;
+	goto L10;
+L15:
+	fpbspl_(&tu[1], nu, &c__3, &arg, &l, h__);
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    spu[it + i__ * spu_dim1] = h__[i__ - 1];
+/* L20: */
+	}
+	nru[it] = number;
+/* L25: */
+    }
+    *ifsu = 1;
+/*  calculate the non-zero elements of the matrix (spv) which is the ob- */
+/*  servation matrix according to the least-squares spline approximation */
+/*  problem in the v-direction. */
+L30:
+    if (*ifsv != 0) {
+	goto L85;
+    }
+    l = 4;
+    l1 = 5;
+    number = 0;
+    i__1 = *mv;
+    for (it = 1; it <= i__1; ++it) {
+	arg = v[it];
+L35:
+	if (arg < tv[l1] || l == nv4) {
+	    goto L40;
+	}
+	l = l1;
+	l1 = l + 1;
+	++number;
+	goto L35;
+L40:
+	fpbspl_(&tv[1], nv, &c__3, &arg, &l, h__);
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    spv[it + i__ * spv_dim1] = h__[i__ - 1];
+/* L45: */
+	}
+	nrv[it] = number;
+/* L50: */
+    }
+    *ifsv = 1;
+    if (*iop0 == 0 && *iop1 == 0) {
+	goto L85;
+    }
+/*  calculate the coefficients of the interpolating splines for cos(v) */
+/*  and sin(v). */
+    i__1 = nv4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	cosi[(i__ << 1) + 1] = (float)0.;
+	cosi[(i__ << 1) + 2] = (float)0.;
+/* L55: */
+    }
+    if (nv7 < 4) {
+	goto L85;
+    }
+    i__1 = nv7;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	l = i__ + 3;
+	arg = tv[l];
+	fpbspl_(&tv[1], nv, &c__3, &arg, &l, h__);
+	for (j = 1; j <= 3; ++j) {
+	    av1[i__ + j * av1_dim1] = h__[j - 1];
+/* L60: */
+	}
+	cosi[(i__ << 1) + 1] = cos(arg);
+	cosi[(i__ << 1) + 2] = sin(arg);
+/* L65: */
+    }
+    fpcyt1_(&av1[av1_offset], &nv7, nv);
+    for (j = 1; j <= 2; ++j) {
+	i__1 = nv7;
+	for (i__ = 1; i__ <= i__1; ++i__) {
+	    right[i__] = cosi[j + (i__ << 1)];
+/* L70: */
+	}
+	fpcyt2_(&av1[av1_offset], &nv7, &right[1], &right[1], nv);
+	i__1 = nv7;
+	for (i__ = 1; i__ <= i__1; ++i__) {
+	    cosi[j + (i__ + 1 << 1)] = right[i__];
+/* L75: */
+	}
+	cosi[j + 2] = cosi[j + (nv7 + 1 << 1)];
+	cosi[j + (nv7 + 2 << 1)] = cosi[j + 4];
+	cosi[j + (nv4 << 1)] = cosi[j + 6];
+/* L80: */
+    }
+L85:
+    if (*p <= (float)0.) {
+	goto L150;
+    }
+/*  calculate the non-zero elements of the matrix (bu). */
+    if (*ifbu != 0 || nu8 == 0) {
+	goto L90;
+    }
+    fpdisc_(&tu[1], nu, &c__5, &bu[bu_offset], nu);
+    *ifbu = 1;
+/*  calculate the non-zero elements of the matrix (bv). */
+L90:
+    if (*ifbv != 0 || nv8 == 0) {
+	goto L150;
+    }
+    fpdisc_(&tv[1], nv, &c__5, &bv[bv_offset], nv);
+    *ifbv = 1;
+/*  substituting (2),(3) and (4) into (1), we obtain the overdetermined */
+/*  system */
+/*         (5)  (avv) (cc) (auu)' = (qq) */
+/*  from which the nuu*nv7 remaining coefficients */
+/*         c(i,j) , i=2+iop0,3+iop0,...,nu-5-iop1,j=1,2,...,nv-7. */
+/*  the elements of (cc), are then determined in the least-squares sense. */
+/*  simultaneously, we compute the resulting sum of squared residuals sq. */
+L150:
+    dr01 = dr[1];
+    dr11 = dr[4];
+    i__1 = *mv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	a0[(i__ << 1) + 1] = dr01;
+	a1[(i__ << 1) + 1] = dr11;
+/* L155: */
+    }
+    if (nv8 == 0 || *p <= (float)0.) {
+	goto L165;
+    }
+    i__1 = nv8;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	b0[(i__ << 1) + 1] = (float)0.;
+	b1[(i__ << 1) + 1] = (float)0.;
+/* L160: */
+    }
+L165:
+    mvv = *mv;
+    if (*iop0 == 0) {
+	goto L195;
+    }
+    fac = (tu[5] - tu[4]) / three;
+    dr02 = dr[2] * fac;
+    dr03 = dr[3] * fac;
+    i__1 = nv4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c0[i__] = dr01 + dr02 * cosi[(i__ << 1) + 1] + dr03 * cosi[(i__ << 1) 
+		+ 2];
+/* L170: */
+    }
+    i__1 = *mv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	number = nrv[i__];
+	fac = (float)0.;
+	for (j = 1; j <= 4; ++j) {
+	    ++number;
+	    fac += c0[number] * spv[i__ + j * spv_dim1];
+/* L175: */
+	}
+	a0[(i__ << 1) + 2] = fac;
+/* L180: */
+    }
+    if (nv8 == 0 || *p <= (float)0.) {
+	goto L195;
+    }
+    i__1 = nv8;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	number = i__;
+	fac = (float)0.;
+	for (j = 1; j <= 5; ++j) {
+	    fac += c0[number] * bv[i__ + j * bv_dim1];
+	    ++number;
+/* L185: */
+	}
+	b0[(i__ << 1) + 2] = fac * pinv;
+/* L190: */
+    }
+    mvv = *mv + nv8;
+L195:
+    if (*iop1 == 0) {
+	goto L225;
+    }
+    fac = (tu[nu4] - tu[nu4 + 1]) / three;
+    dr12 = dr[5] * fac;
+    dr13 = dr[6] * fac;
+    i__1 = nv4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c1[i__] = dr11 + dr12 * cosi[(i__ << 1) + 1] + dr13 * cosi[(i__ << 1) 
+		+ 2];
+/* L200: */
+    }
+    i__1 = *mv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	number = nrv[i__];
+	fac = (float)0.;
+	for (j = 1; j <= 4; ++j) {
+	    ++number;
+	    fac += c1[number] * spv[i__ + j * spv_dim1];
+/* L205: */
+	}
+	a1[(i__ << 1) + 2] = fac;
+/* L210: */
+    }
+    if (nv8 == 0 || *p <= (float)0.) {
+	goto L225;
+    }
+    i__1 = nv8;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	number = i__;
+	fac = (float)0.;
+	for (j = 1; j <= 5; ++j) {
+	    fac += c1[number] * bv[i__ + j * bv_dim1];
+	    ++number;
+/* L215: */
+	}
+	b1[(i__ << 1) + 2] = fac * pinv;
+/* L220: */
+    }
+    mvv = *mv + nv8;
+/*  we first determine the matrices (auu) and (qq). then we reduce the */
+/*  matrix (auu) to an unit upper triangular form (ru) using givens */
+/*  rotations without square roots. we apply the same transformations to */
+/*  the rows of matrix qq to obtain the mv x nuu matrix g. */
+/*  we store matrix (ru) into au and g into q. */
+L225:
+    l = mvv * nuu;
+/*  initialization. */
+    *sq = (float)0.;
+    if (l == 0) {
+	goto L245;
+    }
+    i__1 = l;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	q[i__] = (float)0.;
+/* L230: */
+    }
+    i__1 = nuu;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	for (j = 1; j <= 5; ++j) {
+	    au[i__ + j * au_dim1] = (float)0.;
+/* L240: */
+	}
+    }
+    l = 0;
+L245:
+    nrold = 0;
+    n1 = nrold + 1;
+    i__1 = *mu;
+    for (it = 1; it <= i__1; ++it) {
+	number = nru[it];
+/*  find the appropriate column of q. */
+L250:
+	i__2 = mvv;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] = (float)0.;
+/* L260: */
+	}
+	if (nrold == number) {
+	    goto L280;
+	}
+	if (*p <= (float)0.) {
+	    goto L410;
+	}
+/*  fetch a new row of matrix (bu). */
+	for (j = 1; j <= 5; ++j) {
+	    h__[j - 1] = bu[n1 + j * bu_dim1] * pinv;
+/* L270: */
+	}
+	i0 = 1;
+	i1 = 5;
+	goto L310;
+/*  fetch a new row of matrix (spu). */
+L280:
+	for (j = 1; j <= 4; ++j) {
+	    h__[j - 1] = spu[it + j * spu_dim1];
+/* L290: */
+	}
+/*  find the appropriate column of q. */
+	i__2 = *mv;
+	for (j = 1; j <= i__2; ++j) {
+	    ++l;
+	    right[j] = r__[l];
+/* L300: */
+	}
+	i0 = 1;
+	i1 = 4;
+L310:
+	j0 = n1;
+	j1 = nu7 - number;
+/*  take into account that we eliminate the constraints (3) */
+L315:
+	if (j0 - 1 > *iop0) {
+	    goto L335;
+	}
+	fac0 = h__[i0 - 1];
+	i__2 = *mv;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] -= fac0 * a0[j0 + (j << 1)];
+/* L320: */
+	}
+	if (*mv == mvv) {
+	    goto L330;
+	}
+	j = *mv;
+	i__2 = nv8;
+	for (jj = 1; jj <= i__2; ++jj) {
+	    ++j;
+	    right[j] -= fac0 * b0[j0 + (jj << 1)];
+/* L325: */
+	}
+L330:
+	++j0;
+	++i0;
+	goto L315;
+/*  take into account that we eliminate the constraints (4) */
+L335:
+	if (j1 - 1 > *iop1) {
+	    goto L360;
+	}
+	fac1 = h__[i1 - 1];
+	i__2 = *mv;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] -= fac1 * a1[j1 + (j << 1)];
+/* L340: */
+	}
+	if (*mv == mvv) {
+	    goto L350;
+	}
+	j = *mv;
+	i__2 = nv8;
+	for (jj = 1; jj <= i__2; ++jj) {
+	    ++j;
+	    right[j] -= fac1 * b1[j1 + (jj << 1)];
+/* L345: */
+	}
+L350:
+	++j1;
+	--i1;
+	goto L335;
+L360:
+	irot = nrold - *iop0 - 1;
+	if (irot < 0) {
+	    irot = 0;
+	}
+/*  rotate the new row of matrix (auu) into triangle. */
+	if (i0 > i1) {
+	    goto L390;
+	}
+	i__2 = i1;
+	for (i__ = i0; i__ <= i__2; ++i__) {
+	    ++irot;
+	    piv = h__[i__ - 1];
+	    if (piv == (float)0.) {
+		goto L385;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &au[irot + au_dim1], &co, &si);
+/*  apply that transformation to the rows of matrix (qq). */
+	    iq = (irot - 1) * mvv;
+	    i__3 = mvv;
+	    for (j = 1; j <= i__3; ++j) {
+		++iq;
+		fprota_(&co, &si, &right[j], &q[iq]);
+/* L370: */
+	    }
+/*  apply that transformation to the columns of (auu). */
+	    if (i__ == i1) {
+		goto L385;
+	    }
+	    i2 = 1;
+	    i3 = i__ + 1;
+	    i__3 = i1;
+	    for (j = i3; j <= i__3; ++j) {
+		++i2;
+		fprota_(&co, &si, &h__[j - 1], &au[irot + i2 * au_dim1]);
+/* L380: */
+	    }
+L385:
+	    ;
+	}
+/*  we update the sum of squared residuals. */
+L390:
+	i__2 = mvv;
+	for (j = 1; j <= i__2; ++j) {
+/* Computing 2nd power */
+	    r__1 = right[j];
+	    *sq += r__1 * r__1;
+/* L395: */
+	}
+/* L400: */
+	if (nrold == number) {
+	    goto L420;
+	}
+L410:
+	nrold = n1;
+	++n1;
+	goto L250;
+L420:
+	;
+    }
+    if (nuu == 0) {
+	goto L800;
+    }
+/*  we determine the matrix (avv) and then we reduce her to an unit */
+/*  upper triangular form (rv) using givens rotations without square */
+/*  roots. we apply the same transformations to the columns of matrix */
+/*  g to obtain the (nv-7) x (nu-6-iop0-iop1) matrix h. */
+/*  we store matrix (rv) into av1 and av2, h into c. */
+/*  the nv7 x nv7 triangular unit upper matrix (rv) has the form */
+/*              | av1 '     | */
+/*       (rv) = |     ' av2 | */
+/*              |  0  '     | */
+/*  with (av2) a nv7 x 4 matrix and (av1) a nv11 x nv11 unit upper */
+/*  triangular matrix of bandwidth 5. */
+    ncof = nuu * nv7;
+/*  initialization. */
+    i__1 = ncof;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = (float)0.;
+/* L430: */
+    }
+    i__1 = nv4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	av1[i__ + av1_dim1 * 5] = (float)0.;
+	for (j = 1; j <= 4; ++j) {
+	    av1[i__ + j * av1_dim1] = (float)0.;
+	    av2[i__ + j * av2_dim1] = (float)0.;
+/* L440: */
+	}
+    }
+    jper = 0;
+    nrold = 0;
+    i__1 = *mv;
+    for (it = 1; it <= i__1; ++it) {
+	number = nrv[it];
+L450:
+	if (nrold == number) {
+	    goto L480;
+	}
+	if (*p <= (float)0.) {
+	    goto L760;
+	}
+/*  fetch a new row of matrix (bv). */
+	n1 = nrold + 1;
+	for (j = 1; j <= 5; ++j) {
+	    h__[j - 1] = bv[n1 + j * bv_dim1] * pinv;
+/* L460: */
+	}
+/*  find the appropiate row of g. */
+	i__2 = nuu;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] = (float)0.;
+/* L465: */
+	}
+	if (*mv == mvv) {
+	    goto L510;
+	}
+	l = *mv + n1;
+	i__2 = nuu;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] = q[l];
+	    l += mvv;
+/* L470: */
+	}
+	goto L510;
+/*  fetch a new row of matrix (spv) */
+L480:
+	h__[4] = (float)0.;
+	for (j = 1; j <= 4; ++j) {
+	    h__[j - 1] = spv[it + j * spv_dim1];
+/* L490: */
+	}
+/*  find the appropiate row of g. */
+	l = it;
+	i__2 = nuu;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] = q[l];
+	    l += mvv;
+/* L500: */
+	}
+/*  test whether there are non-zero values in the new row of (avv) */
+/*  corresponding to the b-splines n(j;v),j=nv7+1,...,nv4. */
+L510:
+	if (nrold < nv11) {
+	    goto L710;
+	}
+	if (jper != 0) {
+	    goto L550;
+	}
+/*  initialize the matrix (av2). */
+	jk = nv11 + 1;
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    ik = jk;
+	    for (j = 1; j <= 5; ++j) {
+		if (ik <= 0) {
+		    goto L530;
+		}
+		av2[ik + i__ * av2_dim1] = av1[ik + j * av1_dim1];
+		--ik;
+/* L520: */
+	    }
+L530:
+	    ++jk;
+/* L540: */
+	}
+	jper = 1;
+/*  if one of the non-zero elements of the new row corresponds to one of */
+/*  the b-splines n(j;v),j=nv7+1,...,nv4, we take account of condition */
+/*  (2) for setting up this row of (avv). the row is stored in h1( the */
+/*  part with respect to av1) and h2 (the part with respect to av2). */
+L550:
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    h1[i__ - 1] = (float)0.;
+	    h2[i__ - 1] = (float)0.;
+/* L560: */
+	}
+	h1[4] = (float)0.;
+	j = nrold - nv11;
+	for (i__ = 1; i__ <= 5; ++i__) {
+	    ++j;
+	    l0 = j;
+L570:
+	    l1 = l0 - 4;
+	    if (l1 <= 0) {
+		goto L590;
+	    }
+	    if (l1 <= nv11) {
+		goto L580;
+	    }
+	    l0 = l1 - nv11;
+	    goto L570;
+L580:
+	    h1[l1 - 1] = h__[i__ - 1];
+	    goto L600;
+L590:
+	    h2[l0 - 1] += h__[i__ - 1];
+L600:
+	    ;
+	}
+/*  rotate the new row of (avv) into triangle. */
+	if (nv11 <= 0) {
+	    goto L670;
+	}
+/*  rotations with the rows 1,2,...,nv11 of (avv). */
+	i__2 = nv11;
+	for (j = 1; j <= i__2; ++j) {
+	    piv = h1[0];
+/* Computing MIN */
+	    i__3 = nv11 - j;
+	    i2 = min(i__3,4);
+	    if (piv == (float)0.) {
+		goto L640;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &av1[j + av1_dim1], &co, &si);
+/*  apply that transformation to the columns of matrix g. */
+	    ic = j;
+	    i__3 = nuu;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		fprota_(&co, &si, &right[i__], &c__[ic]);
+		ic += nv7;
+/* L610: */
+	    }
+/*  apply that transformation to the rows of (avv) with respect to av2. */
+	    for (i__ = 1; i__ <= 4; ++i__) {
+		fprota_(&co, &si, &h2[i__ - 1], &av2[j + i__ * av2_dim1]);
+/* L620: */
+	    }
+/*  apply that transformation to the rows of (avv) with respect to av1. */
+	    if (i2 == 0) {
+		goto L670;
+	    }
+	    i__3 = i2;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		i1 = i__ + 1;
+		fprota_(&co, &si, &h1[i1 - 1], &av1[j + i1 * av1_dim1]);
+/* L630: */
+	    }
+L640:
+	    i__3 = i2;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		h1[i__ - 1] = h1[i__];
+/* L650: */
+	    }
+	    h1[i2] = (float)0.;
+/* L660: */
+	}
+/*  rotations with the rows nv11+1,...,nv7 of avv. */
+L670:
+	for (j = 1; j <= 4; ++j) {
+	    ij = nv11 + j;
+	    if (ij <= 0) {
+		goto L700;
+	    }
+	    piv = h2[j - 1];
+	    if (piv == (float)0.) {
+		goto L700;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &av2[ij + j * av2_dim1], &co, &si);
+/*  apply that transformation to the columns of matrix g. */
+	    ic = ij;
+	    i__2 = nuu;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		fprota_(&co, &si, &right[i__], &c__[ic]);
+		ic += nv7;
+/* L680: */
+	    }
+	    if (j == 4) {
+		goto L700;
+	    }
+/*  apply that transformation to the rows of (avv) with respect to av2. */
+	    j1 = j + 1;
+	    for (i__ = j1; i__ <= 4; ++i__) {
+		fprota_(&co, &si, &h2[i__ - 1], &av2[ij + i__ * av2_dim1]);
+/* L690: */
+	    }
+L700:
+	    ;
+	}
+/*  we update the sum of squared residuals. */
+	i__2 = nuu;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+/* Computing 2nd power */
+	    r__1 = right[i__];
+	    *sq += r__1 * r__1;
+/* L705: */
+	}
+	goto L750;
+/*  rotation into triangle of the new row of (avv), in case the elements */
+/*  corresponding to the b-splines n(j;v),j=nv7+1,...,nv4 are all zero. */
+L710:
+	irot = nrold;
+	for (i__ = 1; i__ <= 5; ++i__) {
+	    ++irot;
+	    piv = h__[i__ - 1];
+	    if (piv == (float)0.) {
+		goto L740;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &av1[irot + av1_dim1], &co, &si);
+/*  apply that transformation to the columns of matrix g. */
+	    ic = irot;
+	    i__2 = nuu;
+	    for (j = 1; j <= i__2; ++j) {
+		fprota_(&co, &si, &right[j], &c__[ic]);
+		ic += nv7;
+/* L720: */
+	    }
+/*  apply that transformation to the rows of (avv). */
+	    if (i__ == 5) {
+		goto L740;
+	    }
+	    i2 = 1;
+	    i3 = i__ + 1;
+	    for (j = i3; j <= 5; ++j) {
+		++i2;
+		fprota_(&co, &si, &h__[j - 1], &av1[irot + i2 * av1_dim1]);
+/* L730: */
+	    }
+L740:
+	    ;
+	}
+/*  we update the sum of squared residuals. */
+	i__2 = nuu;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+/* Computing 2nd power */
+	    r__1 = right[i__];
+	    *sq += r__1 * r__1;
+/* L745: */
+	}
+L750:
+	if (nrold == number) {
+	    goto L770;
+	}
+L760:
+	++nrold;
+	goto L450;
+L770:
+	;
+    }
+/*  test whether the b-spline coefficients must be determined. */
+    if (*iback != 0) {
+	return 0;
+    }
+/*  backward substitution to obtain the b-spline coefficients as the */
+/*  solution of the linear system    (rv) (cr) (ru)' = h. */
+/*  first step: solve the system  (rv) (c1) = h. */
+    k = 1;
+    i__1 = nuu;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	fpbacp_(&av1[av1_offset], &av2[av2_offset], &c__[k], &nv7, &c__4, &
+		c__[k], &c__5, nv);
+	k += nv7;
+/* L780: */
+    }
+/*  second step: solve the system  (cr) (ru)' = (c1). */
+    k = 0;
+    i__1 = nv7;
+    for (j = 1; j <= i__1; ++j) {
+	++k;
+	l = k;
+	i__2 = nuu;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    right[i__] = c__[l];
+	    l += nv7;
+/* L785: */
+	}
+	fpback_(&au[au_offset], &right[1], &nuu, &c__5, &right[1], nu);
+	l = k;
+	i__2 = nuu;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    c__[l] = right[i__];
+	    l += nv7;
+/* L790: */
+	}
+/* L795: */
+    }
+/*  calculate from the conditions (2)-(3)-(4), the remaining b-spline */
+/*  coefficients. */
+L800:
+    ncof = nu4 * nv4;
+    j = ncof;
+    i__1 = nv4;
+    for (l = 1; l <= i__1; ++l) {
+	q[l] = dr01;
+	q[j] = dr11;
+	--j;
+/* L805: */
+    }
+    i__ = nv4;
+    j = 0;
+    if (*iop0 == 0) {
+	goto L815;
+    }
+    i__1 = nv4;
+    for (l = 1; l <= i__1; ++l) {
+	++i__;
+	q[i__] = c0[l];
+/* L810: */
+    }
+L815:
+    if (nuu == 0) {
+	goto L835;
+    }
+    i__1 = nuu;
+    for (l = 1; l <= i__1; ++l) {
+	ii = i__;
+	i__2 = nv7;
+	for (k = 1; k <= i__2; ++k) {
+	    ++i__;
+	    ++j;
+	    q[i__] = c__[j];
+/* L820: */
+	}
+	for (k = 1; k <= 3; ++k) {
+	    ++ii;
+	    ++i__;
+	    q[i__] = q[ii];
+/* L825: */
+	}
+/* L830: */
+    }
+L835:
+    if (*iop1 == 0) {
+	goto L845;
+    }
+    i__1 = nv4;
+    for (l = 1; l <= i__1; ++l) {
+	++i__;
+	q[i__] = c1[l];
+/* L840: */
+    }
+L845:
+    i__1 = ncof;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = q[i__];
+/* L850: */
+    }
+/*  calculate the quantities */
+/*    res(i,j) = (r(i,j) - s(u(i),v(j)))**2 , i=1,2,..,mu;j=1,2,..,mv */
+/*    fp = sumi=1,mu(sumj=1,mv(res(i,j))) */
+/*    fpu(r) = sum''i(sumj=1,mv(res(i,j))) , r=1,2,...,nu-7 */
+/*                  tu(r+3) <= u(i) <= tu(r+4) */
+/*    fpv(r) = sumi=1,mu(sum''j(res(i,j))) , r=1,2,...,nv-7 */
+/*                  tv(r+3) <= v(j) <= tv(r+4) */
+    *fp = (float)0.;
+    i__1 = *nu;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	fpu[i__] = (float)0.;
+/* L890: */
+    }
+    i__1 = *nv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	fpv[i__] = (float)0.;
+/* L900: */
+    }
+    ir = 0;
+    nroldu = 0;
+/*  main loop for the different grid points. */
+    i__1 = *mu;
+    for (i1 = 1; i1 <= i__1; ++i1) {
+	numu = nru[i1];
+	numu1 = numu + 1;
+	nroldv = 0;
+	i__2 = *mv;
+	for (i2 = 1; i2 <= i__2; ++i2) {
+	    numv = nrv[i2];
+	    numv1 = numv + 1;
+	    ++ir;
+/*  evaluate s(u,v) at the current grid point by making the sum of the */
+/*  cross products of the non-zero b-splines at (u,v), multiplied with */
+/*  the appropiate b-spline coefficients. */
+	    term = (float)0.;
+	    k1 = numu * nv4 + numv;
+	    for (l1 = 1; l1 <= 4; ++l1) {
+		k2 = k1;
+		fac = spu[i1 + l1 * spu_dim1];
+		for (l2 = 1; l2 <= 4; ++l2) {
+		    ++k2;
+		    term += fac * spv[i2 + l2 * spv_dim1] * c__[k2];
+/* L910: */
+		}
+		k1 += nv4;
+/* L920: */
+	    }
+/*  calculate the squared residual at the current grid point. */
+/* Computing 2nd power */
+	    r__1 = r__[ir] - term;
+	    term = r__1 * r__1;
+/*  adjust the different parameters. */
+	    *fp += term;
+	    fpu[numu1] += term;
+	    fpv[numv1] += term;
+	    fac = term * half;
+	    if (numv == nroldv) {
+		goto L930;
+	    }
+	    fpv[numv1] -= fac;
+	    fpv[numv] += fac;
+L930:
+	    nroldv = numv;
+	    if (numu == nroldu) {
+		goto L940;
+	    }
+	    fpu[numu1] -= fac;
+	    fpu[numu] += fac;
+L940:
+	    ;
+	}
+	nroldu = numu;
+/* L950: */
+    }
+    return 0;
+} /* fpgrsp_ */
+
+/* Subroutine */ int fpinst_(iopt, t, n, c__, k, x, l, tt, nn, cc, nest)
+integer *iopt;
+real *t;
+integer *n;
+real *c__;
+integer *k;
+real *x;
+integer *l;
+real *tt;
+integer *nn;
+real *cc;
+integer *nest;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__, j, m, i1, k1, mk, nk, nl, ll, nk1;
+    static real fac, one, per;
+
+/*  given the b-spline representation (knots t(j),j=1,2,...,n, b-spline */
+/*  coefficients c(j),j=1,2,...,n-k-1) of a spline of degree k, fpinst */
+/*  calculates the b-spline representation (knots tt(j),j=1,2,...,nn, */
+/*  b-spline coefficients cc(j),j=1,2,...,nn-k-1) of the same spline if */
+/*  an additional knot is inserted at the point x situated in the inter- */
+/*  val t(l)<=x<t(l+1). iopt denotes whether (iopt.ne.0) or not (iopt=0) */
+/*  the given spline is periodic. in case of a periodic spline at least */
+/*  one of the following conditions must be fulfilled: l>2*k or l<n-2*k. */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --cc;
+    --tt;
+    --c__;
+    --t;
+
+    /* Function Body */
+    one = (float)1.;
+    k1 = *k + 1;
+    nk1 = *n - k1;
+/*  the new knots */
+    ll = *l + 1;
+    i__ = *n;
+    i__1 = *n;
+    for (j = ll; j <= i__1; ++j) {
+	tt[i__ + 1] = t[i__];
+	--i__;
+/* L10: */
+    }
+    tt[ll] = *x;
+    i__1 = *l;
+    for (j = 1; j <= i__1; ++j) {
+	tt[j] = t[j];
+/* L20: */
+    }
+/*  the new b-spline coefficients */
+    i__ = nk1;
+    i__1 = nk1;
+    for (j = *l; j <= i__1; ++j) {
+	cc[i__ + 1] = c__[i__];
+	--i__;
+/* L30: */
+    }
+    i__ = *l;
+    i__1 = *k;
+    for (j = 1; j <= i__1; ++j) {
+	m = i__ + k1;
+	fac = (*x - tt[i__]) / (tt[m] - tt[i__]);
+	i1 = i__ - 1;
+	cc[i__] = fac * c__[i__] + (one - fac) * c__[i1];
+	i__ = i1;
+/* L40: */
+    }
+    i__1 = i__;
+    for (j = 1; j <= i__1; ++j) {
+	cc[j] = c__[j];
+/* L50: */
+    }
+    *nn = *n + 1;
+    if (*iopt == 0) {
+	return 0;
+    }
+/*   incorporate the boundary conditions for a periodic spline. */
+    nk = *nn - *k;
+    nl = nk - k1;
+    per = tt[nk] - tt[k1];
+    i__ = k1;
+    j = nk;
+    if (ll <= nl) {
+	goto L70;
+    }
+    i__1 = *k;
+    for (m = 1; m <= i__1; ++m) {
+	mk = m + nl;
+	cc[m] = cc[mk];
+	--i__;
+	--j;
+	tt[i__] = tt[j] - per;
+/* L60: */
+    }
+    return 0;
+L70:
+    if (ll > k1 + *k) {
+	return 0;
+    }
+    i__1 = *k;
+    for (m = 1; m <= i__1; ++m) {
+	mk = m + nl;
+	cc[mk] = cc[m];
+	++i__;
+	++j;
+	tt[j] = tt[i__] + per;
+/* L80: */
+    }
+    return 0;
+} /* fpinst_ */
+
+/* Subroutine */ int fpintb_(t, n, bint, nk1, x, y)
+real *t;
+integer *n;
+real *bint;
+integer *nk1;
+real *x, *y;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+    real r__1;
+
+    /* Local variables */
+    static real aint[6], a, b, f, h__[6];
+    static integer i__, j, k, l;
+    static real h1[6];
+    static integer j1, k1, l0, ia, ib;
+    static real ak;
+    static integer li, lj, lk, it;
+    static real arg, one;
+    static integer min__;
+
+/*  subroutine fpintb calculates integrals of the normalized b-splines */
+/*  nj,k+1(x) of degree k, defined on the set of knots t(j),j=1,2,...n. */
+/*  it makes use of the formulae of gaffney for the calculation of */
+/*  indefinite integrals of b-splines. */
+
+/*  calling sequence: */
+/*     call fpintb(t,n,bint,nk1,x,y) */
+
+/*  input parameters: */
+/*    t    : real array,length n, containing the position of the knots. */
+/*    n    : integer value, giving the number of knots. */
+/*    nk1  : integer value, giving the number of b-splines of degree k, */
+/*           defined on the set of knots ,i.e. nk1 = n-k-1. */
+/*    x,y  : real values, containing the end points of the integration */
+/*           interval. */
+/*  output parameter: */
+/*    bint : array,length nk1, containing the integrals of the b-splines. */
+/*  .. */
+/*  ..scalars arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  initialization. */
+    /* Parameter adjustments */
+    --t;
+    --bint;
+
+    /* Function Body */
+    one = (float)1.;
+    k1 = *n - *nk1;
+    ak = (real) k1;
+    k = k1 - 1;
+    i__1 = *nk1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	bint[i__] = (float)0.;
+/* L10: */
+    }
+/*  the integration limits are arranged in increasing order. */
+    a = *x;
+    b = *y;
+    min__ = 0;
+    if ((r__1 = a - b) < (float)0.) {
+	goto L30;
+    } else if (r__1 == 0) {
+	goto L160;
+    } else {
+	goto L20;
+    }
+L20:
+    a = *y;
+    b = *x;
+    min__ = 1;
+L30:
+    if (a < t[k1]) {
+	a = t[k1];
+    }
+    if (b > t[*nk1 + 1]) {
+	b = t[*nk1 + 1];
+    }
+/*  using the expression of gaffney for the indefinite integral of a */
+/*  b-spline we find that */
+/*  bint(j) = (t(j+k+1)-t(j))*(res(j,b)-res(j,a))/(k+1) */
+/*    where for t(l) <= x < t(l+1) */
+/*    res(j,x) = 0, j=1,2,...,l-k-1 */
+/*             = 1, j=l+1,l+2,...,nk1 */
+/*             = aint(j+k-l+1), j=l-k,l-k+1,...,l */
+/*               = sumi((x-t(j+i))*nj+i,k+1-i(x)/(t(j+k+1)-t(j+i))) */
+/*                 i=0,1,...,k */
+    l = k1;
+    l0 = l + 1;
+/*  set arg = a. */
+    arg = a;
+    for (it = 1; it <= 2; ++it) {
+/*  search for the knot interval t(l) <= arg < t(l+1). */
+L40:
+	if (arg < t[l0] || l == *nk1) {
+	    goto L50;
+	}
+	l = l0;
+	l0 = l + 1;
+	goto L40;
+/*  calculation of aint(j), j=1,2,...,k+1. */
+/*  initialization. */
+L50:
+	i__1 = k1;
+	for (j = 1; j <= i__1; ++j) {
+	    aint[j - 1] = (float)0.;
+/* L55: */
+	}
+	aint[0] = (arg - t[l]) / (t[l + 1] - t[l]);
+	h1[0] = one;
+	i__1 = k;
+	for (j = 1; j <= i__1; ++j) {
+/*  evaluation of the non-zero b-splines of degree j at arg,i.e. */
+/*    h(i+1) = nl-j+i,j(arg), i=0,1,...,j. */
+	    h__[0] = (float)0.;
+	    i__2 = j;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		li = l + i__;
+		lj = li - j;
+		f = h1[i__ - 1] / (t[li] - t[lj]);
+		h__[i__ - 1] += f * (t[li] - arg);
+		h__[i__] = f * (arg - t[lj]);
+/* L60: */
+	    }
+/*  updating of the integrals aint. */
+	    j1 = j + 1;
+	    i__2 = j1;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		li = l + i__;
+		lj = li - j1;
+		aint[i__ - 1] += h__[i__ - 1] * (arg - t[lj]) / (t[li] - t[lj]
+			);
+		h1[i__ - 1] = h__[i__ - 1];
+/* L70: */
+	    }
+	}
+	if (it == 2) {
+	    goto L100;
+	}
+/*  updating of the integrals bint */
+	lk = l - k;
+	ia = lk;
+	i__2 = k1;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    bint[lk] = -aint[i__ - 1];
+	    ++lk;
+/* L80: */
+	}
+/*  set arg = b. */
+	arg = b;
+/* L90: */
+    }
+/*  updating of the integrals bint. */
+L100:
+    lk = l - k;
+    ib = lk - 1;
+    i__2 = k1;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	bint[lk] += aint[i__ - 1];
+	++lk;
+/* L110: */
+    }
+    if (ib < ia) {
+	goto L130;
+    }
+    i__2 = ib;
+    for (i__ = ia; i__ <= i__2; ++i__) {
+	bint[i__] += one;
+/* L120: */
+    }
+/*  the scaling factors are taken into account. */
+L130:
+    f = one / ak;
+    i__2 = *nk1;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	j = i__ + k1;
+	bint[i__] = bint[i__] * (t[j] - t[i__]) * f;
+/* L140: */
+    }
+/*  the order of the integration limits is taken into account. */
+    if (min__ == 0) {
+	goto L160;
+    }
+    i__2 = *nk1;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	bint[i__] = -bint[i__];
+/* L150: */
+    }
+L160:
+    return 0;
+} /* fpintb_ */
+
+/* Subroutine */ int fpknot_(x, m, t, n, fpint, nrdata, nrint, nest, istart)
+real *x;
+integer *m;
+real *t;
+integer *n;
+real *fpint;
+integer *nrdata, *nrint, *nest, *istart;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer next, j, k, ihalf;
+    static real fpmax;
+    static integer maxpt;
+    static real am, an;
+    static integer jj, jk, jbegin, maxbeg, number, jpoint, nrx;
+
+/*  subroutine fpknot locates an additional knot for a spline of degree */
+/*  k and adjusts the corresponding parameters,i.e. */
+/*    t     : the position of the knots. */
+/*    n     : the number of knots. */
+/*    nrint : the number of knotintervals. */
+/*    fpint : the sum of squares of residual right hand sides */
+/*            for each knot interval. */
+/*    nrdata: the number of data points inside each knot interval. */
+/*  istart indicates that the smallest data point at which the new knot */
+/*  may be added is x(istart+1) */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --x;
+    --nrdata;
+    --fpint;
+    --t;
+
+    /* Function Body */
+    k = (*n - *nrint - 1) / 2;
+/*  search for knot interval t(number+k) <= x <= t(number+k+1) where */
+/*  fpint(number) is maximal on the condition that nrdata(number) */
+/*  not equals zero. */
+    fpmax = (float)0.;
+    jbegin = *istart;
+    i__1 = *nrint;
+    for (j = 1; j <= i__1; ++j) {
+	jpoint = nrdata[j];
+	if (fpmax >= fpint[j] || jpoint == 0) {
+	    goto L10;
+	}
+	fpmax = fpint[j];
+	number = j;
+	maxpt = jpoint;
+	maxbeg = jbegin;
+L10:
+	jbegin = jbegin + jpoint + 1;
+/* L20: */
+    }
+/*  let coincide the new knot t(number+k+1) with a data point x(nrx) */
+/*  inside the old knot interval t(number+k) <= x <= t(number+k+1). */
+    ihalf = maxpt / 2 + 1;
+    nrx = maxbeg + ihalf;
+    next = number + 1;
+    if (next > *nrint) {
+	goto L40;
+    }
+/*  adjust the different parameters. */
+    i__1 = *nrint;
+    for (j = next; j <= i__1; ++j) {
+	jj = next + *nrint - j;
+	fpint[jj + 1] = fpint[jj];
+	nrdata[jj + 1] = nrdata[jj];
+	jk = jj + k;
+	t[jk + 1] = t[jk];
+/* L30: */
+    }
+L40:
+    nrdata[number] = ihalf - 1;
+    nrdata[next] = maxpt - ihalf;
+    am = (real) maxpt;
+    an = (real) nrdata[number];
+    fpint[number] = fpmax * an / am;
+    an = (real) nrdata[next];
+    fpint[next] = fpmax * an / am;
+    jk = next + k;
+    t[jk] = x[nrx];
+    ++(*n);
+    ++(*nrint);
+    return 0;
+} /* fpknot_ */
+
+/* Subroutine */ int fpopdi_(ifsu, ifsv, ifbu, ifbv, u, mu, v, mv, z__, mz, 
+	z0, dz, iopt, ider, tu, nu, tv, nv, nuest, nvest, p, step, c__, nc, 
+	fp, fpu, fpv, nru, nrv, wrk, lwrk)
+integer *ifsu, *ifsv, *ifbu, *ifbv;
+real *u;
+integer *mu;
+real *v;
+integer *mv;
+real *z__;
+integer *mz;
+real *z0, *dz;
+integer *iopt, *ider;
+real *tu;
+integer *nu;
+real *tv;
+integer *nv, *nuest, *nvest;
+real *p, *step, *c__;
+integer *nc;
+real *fp, *fpu, *fpv;
+integer *nru, *nrv;
+real *wrk;
+integer *lwrk;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+    real r__1;
+
+    /* Local variables */
+    static integer mvnu;
+    static real step1, step2, a[36]	/* was [6][6] */, g[6];
+    static integer i__, j, l;
+    static real delta[3], three;
+    static integer i1, l1, l2, mm, lq, nr[3];
+    static real sq;
+    extern /* Subroutine */ int fpgrdi_();
+    static integer number, id0;
+    extern /* Subroutine */ int fpsysy_();
+    static integer laa, lbb, lcc, lau, lbu, lbv, lcs, lri;
+    static real res, sqq;
+    static integer lsu, lsv;
+    static real dzz[3], sum[3];
+    static integer lav1, lav2, iop0, iop1;
+
+/*  given the set of function values z(i,j) defined on the rectangular */
+/*  grid (u(i),v(j)),i=1,2,...,mu;j=1,2,...,mv, fpopdi determines a */
+/*  smooth bicubic spline approximation with given knots tu(i),i=1,..,nu */
+/*  in the u-direction and tv(j),j=1,2,...,nv in the v-direction. this */
+/*  spline sp(u,v) will be periodic in the variable v and will satisfy */
+/*  the following constraints */
+
+/*     s(tu(1),v) = dz(1) , tv(4) <=v<= tv(nv-3) */
+
+/*  and (if iopt(2) = 1) */
+
+/*     d s(tu(1),v) */
+/*     ------------ =  dz(2)*cos(v)+dz(3)*sin(v) , tv(4) <=v<= tv(nv-3) */
+/*     d u */
+
+/*  and (if iopt(3) = 1) */
+
+/*     s(tu(nu),v)  =  0   tv(4) <=v<= tv(nv-3) */
+
+/*  where the parameters dz(i) correspond to the derivative values g(i,j) */
+/*  as defined in subroutine pogrid. */
+
+/*  the b-spline coefficients of sp(u,v) are determined as the least- */
+/*  squares solution  of an overdetermined linear system which depends */
+/*  on the value of p and on the values dz(i),i=1,2,3. the correspond- */
+/*  ing sum of squared residuals sq is a simple quadratic function in */
+/*  the variables dz(i). these may or may not be provided. the values */
+/*  dz(i) which are not given will be determined so as to minimize the */
+/*  resulting sum of squared residuals sq. in that case the user must */
+/*  provide some initial guess dz(i) and some estimate (dz(i)-step, */
+/*  dz(i)+step) of the range of possible values for these latter. */
+
+/*  sp(u,v) also depends on the parameter p (p>0) in such a way that */
+/*    - if p tends to infinity, sp(u,v) becomes the least-squares spline */
+/*      with given knots, satisfying the constraints. */
+/*    - if p tends to zero, sp(u,v) becomes the least-squares polynomial, */
+/*      satisfying the constraints. */
+/*    - the function  f(p)=sumi=1,mu(sumj=1,mv((z(i,j)-sp(u(i),v(j)))**2) */
+/*      is continuous and strictly decreasing for p>0. */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpgrdi,fpsysy */
+/*  .. */
+/*  set constant */
+    /* Parameter adjustments */
+    --nru;
+    --u;
+    --nrv;
+    --v;
+    --z__;
+    --dz;
+    --iopt;
+    --ider;
+    --fpu;
+    --tu;
+    --fpv;
+    --tv;
+    --c__;
+    --wrk;
+
+    /* Function Body */
+    three = (float)3.;
+/*  we partition the working space */
+    lsu = 1;
+    lsv = lsu + (*mu << 2);
+    lri = lsv + (*mv << 2);
+/* Computing MAX */
+    i__1 = *nuest, i__2 = *mv + *nvest;
+    mm = max(i__1,i__2);
+    lq = lri + mm;
+    mvnu = *nuest * (*mv + *nvest - 8);
+    lau = lq + mvnu;
+    lav1 = lau + *nuest * 5;
+    lav2 = lav1 + *nvest * 6;
+    lbu = lav2 + (*nvest << 2);
+    lbv = lbu + *nuest * 5;
+    laa = lbv + *nvest * 5;
+    lbb = laa + (*mv << 1);
+    lcc = lbb + (*nvest << 1);
+    lcs = lcc + *nvest;
+/*  we calculate the smoothing spline sp(u,v) according to the input */
+/*  values dz(i),i=1,2,3. */
+    iop0 = iopt[2];
+    iop1 = iopt[3];
+    fpgrdi_(ifsu, ifsv, ifbu, ifbv, &c__0, &u[1], mu, &v[1], mv, &z__[1], mz, 
+	    &dz[1], &iop0, &iop1, &tu[1], nu, &tv[1], nv, p, &c__[1], nc, &sq,
+	     fp, &fpu[1], &fpv[1], &mm, &mvnu, &wrk[lsu], &wrk[lsv], &wrk[lri]
+	    , &wrk[lq], &wrk[lau], &wrk[lav1], &wrk[lav2], &wrk[lbu], &wrk[
+	    lbv], &wrk[laa], &wrk[lbb], &wrk[lcc], &wrk[lcs], &nru[1], &nrv[1]
+	    );
+    id0 = ider[1];
+    if (id0 != 0) {
+	goto L5;
+    }
+/* Computing 2nd power */
+    r__1 = *z0 - dz[1];
+    res = r__1 * r__1;
+    *fp += res;
+    sq += res;
+/* in case all derivative values dz(i) are given (step<=0) or in case */
+/* we have spline interpolation, we accept this spline as a solution. */
+L5:
+    if (*step <= (float)0. || sq <= (float)0.) {
+	return 0;
+    }
+    dzz[0] = dz[1];
+    dzz[1] = dz[2];
+    dzz[2] = dz[3];
+/* number denotes the number of derivative values dz(i) that still must */
+/* be optimized. let us denote these parameters by g(j),j=1,...,number. */
+    number = 0;
+    if (id0 > 0) {
+	goto L10;
+    }
+    number = 1;
+    nr[0] = 1;
+    delta[0] = *step;
+L10:
+    if (iop0 == 0) {
+	goto L20;
+    }
+    if (ider[2] != 0) {
+	goto L20;
+    }
+    step2 = *step * three / tu[5];
+    nr[number] = 2;
+    nr[number + 1] = 3;
+    delta[number] = step2;
+    delta[number + 1] = step2;
+    number += 2;
+L20:
+    if (number == 0) {
+	return 0;
+    }
+/* the sum of squared residuals sq is a quadratic polynomial in the */
+/* parameters g(j). we determine the unknown coefficients of this */
+/* polymomial by calculating (number+1)*(number+2)/2 different splines */
+/* according to specific values for g(j). */
+    i__1 = number;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	l = nr[i__ - 1];
+	step1 = delta[i__ - 1];
+	dzz[l - 1] = dz[l] + step1;
+	fpgrdi_(ifsu, ifsv, ifbu, ifbv, &c__1, &u[1], mu, &v[1], mv, &z__[1], 
+		mz, dzz, &iop0, &iop1, &tu[1], nu, &tv[1], nv, p, &c__[1], nc,
+		 &sum[i__ - 1], fp, &fpu[1], &fpv[1], &mm, &mvnu, &wrk[lsu], &
+		wrk[lsv], &wrk[lri], &wrk[lq], &wrk[lau], &wrk[lav1], &wrk[
+		lav2], &wrk[lbu], &wrk[lbv], &wrk[laa], &wrk[lbb], &wrk[lcc], 
+		&wrk[lcs], &nru[1], &nrv[1]);
+	if (id0 == 0) {
+/* Computing 2nd power */
+	    r__1 = *z0 - dzz[0];
+	    sum[i__ - 1] += r__1 * r__1;
+	}
+	dzz[l - 1] = dz[l] - step1;
+	fpgrdi_(ifsu, ifsv, ifbu, ifbv, &c__1, &u[1], mu, &v[1], mv, &z__[1], 
+		mz, dzz, &iop0, &iop1, &tu[1], nu, &tv[1], nv, p, &c__[1], nc,
+		 &sqq, fp, &fpu[1], &fpv[1], &mm, &mvnu, &wrk[lsu], &wrk[lsv],
+		 &wrk[lri], &wrk[lq], &wrk[lau], &wrk[lav1], &wrk[lav2], &wrk[
+		lbu], &wrk[lbv], &wrk[laa], &wrk[lbb], &wrk[lcc], &wrk[lcs], &
+		nru[1], &nrv[1]);
+	if (id0 == 0) {
+/* Computing 2nd power */
+	    r__1 = *z0 - dzz[0];
+	    sqq += r__1 * r__1;
+	}
+/* Computing 2nd power */
+	r__1 = step1;
+	a[i__ + i__ * 6 - 7] = (sum[i__ - 1] + sqq - sq - sq) / (r__1 * r__1);
+	if (a[i__ + i__ * 6 - 7] <= (float)0.) {
+	    goto L80;
+	}
+	g[i__ - 1] = (sqq - sum[i__ - 1]) / (step1 + step1);
+	dzz[l - 1] = dz[l];
+/* L30: */
+    }
+    if (number == 1) {
+	goto L60;
+    }
+    i__1 = number;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	l1 = nr[i__ - 1];
+	step1 = delta[i__ - 1];
+	dzz[l1 - 1] = dz[l1] + step1;
+	i1 = i__ - 1;
+	i__2 = i1;
+	for (j = 1; j <= i__2; ++j) {
+	    l2 = nr[j - 1];
+	    step2 = delta[j - 1];
+	    dzz[l2 - 1] = dz[l2] + step2;
+	    fpgrdi_(ifsu, ifsv, ifbu, ifbv, &c__1, &u[1], mu, &v[1], mv, &z__[
+		    1], mz, dzz, &iop0, &iop1, &tu[1], nu, &tv[1], nv, p, &
+		    c__[1], nc, &sqq, fp, &fpu[1], &fpv[1], &mm, &mvnu, &wrk[
+		    lsu], &wrk[lsv], &wrk[lri], &wrk[lq], &wrk[lau], &wrk[
+		    lav1], &wrk[lav2], &wrk[lbu], &wrk[lbv], &wrk[laa], &wrk[
+		    lbb], &wrk[lcc], &wrk[lcs], &nru[1], &nrv[1]);
+	    if (id0 == 0) {
+/* Computing 2nd power */
+		r__1 = *z0 - dzz[0];
+		sqq += r__1 * r__1;
+	    }
+	    a[i__ + j * 6 - 7] = (sq + sqq - sum[i__ - 1] - sum[j - 1]) / (
+		    step1 * step2);
+	    dzz[l2 - 1] = dz[l2];
+/* L40: */
+	}
+	dzz[l1 - 1] = dz[l1];
+/* L50: */
+    }
+/* the optimal values g(j) are found as the solution of the system */
+/* d (sq) / d (g(j)) = 0 , j=1,...,number. */
+L60:
+    fpsysy_(a, &number, g);
+    i__1 = number;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	l = nr[i__ - 1];
+	dz[l] += g[i__ - 1];
+/* L70: */
+    }
+/* we determine the spline sp(u,v) according to the optimal values g(j). */
+L80:
+    fpgrdi_(ifsu, ifsv, ifbu, ifbv, &c__0, &u[1], mu, &v[1], mv, &z__[1], mz, 
+	    &dz[1], &iop0, &iop1, &tu[1], nu, &tv[1], nv, p, &c__[1], nc, &sq,
+	     fp, &fpu[1], &fpv[1], &mm, &mvnu, &wrk[lsu], &wrk[lsv], &wrk[lri]
+	    , &wrk[lq], &wrk[lau], &wrk[lav1], &wrk[lav2], &wrk[lbu], &wrk[
+	    lbv], &wrk[laa], &wrk[lbb], &wrk[lcc], &wrk[lcs], &nru[1], &nrv[1]
+	    );
+    if (id0 == 0) {
+/* Computing 2nd power */
+	r__1 = *z0 - dz[1];
+	*fp += r__1 * r__1;
+    }
+    return 0;
+} /* fpopdi_ */
+
+/* Subroutine */ int fpopsp_(ifsu, ifsv, ifbu, ifbv, u, mu, v, mv, r__, mr, 
+	r0, r1, dr, iopt, ider, tu, nu, tv, nv, nuest, nvest, p, step, c__, 
+	nc, fp, fpu, fpv, nru, nrv, wrk, lwrk)
+integer *ifsu, *ifsv, *ifbu, *ifbv;
+real *u;
+integer *mu;
+real *v;
+integer *mv;
+real *r__;
+integer *mr;
+real *r0, *r1, *dr;
+integer *iopt, *ider;
+real *tu;
+integer *nu;
+real *tv;
+integer *nv, *nuest, *nvest;
+real *p, *step, *c__;
+integer *nc;
+real *fp, *fpu, *fpv;
+integer *nru, *nrv;
+real *wrk;
+integer *lwrk;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+    real r__1;
+
+    /* Local variables */
+    static integer mvnu;
+    static real step1, step2, a[36]	/* was [6][6] */, g[6];
+    static integer i__, j, l;
+    static real delta[6], three;
+    static integer i1, l1, l2, mm, lq, nr[6];
+    static real sq;
+    static integer number, id0, la0, la1, lb0, lb1, lc0, lc1, id1;
+    extern /* Subroutine */ int fpgrsp_();
+    static real sq0, sq1;
+    extern /* Subroutine */ int fpsysy_();
+    static integer lau, lbu, lbv, lcs, lri;
+    static real drr[6], sqq;
+    static integer lsu, lsv;
+    static real sum[6];
+    static integer lav1, lav2, iop0, iop1;
+
+/*  given the set of function values r(i,j) defined on the rectangular */
+/*  grid (u(i),v(j)),i=1,2,...,mu;j=1,2,...,mv, fpopsp determines a */
+/*  smooth bicubic spline approximation with given knots tu(i),i=1,..,nu */
+/*  in the u-direction and tv(j),j=1,2,...,nv in the v-direction. this */
+/*  spline sp(u,v) will be periodic in the variable v and will satisfy */
+/*  the following constraints */
+
+/*     s(tu(1),v) = dr(1) , tv(4) <=v<= tv(nv-3) */
+
+/*     s(tu(nu),v) = dr(4) , tv(4) <=v<= tv(nv-3) */
+
+/*  and (if iopt(2) = 1) */
+
+/*     d s(tu(1),v) */
+/*     ------------ =  dr(2)*cos(v)+dr(3)*sin(v) , tv(4) <=v<= tv(nv-3) */
+/*     d u */
+
+/*  and (if iopt(3) = 1) */
+
+/*     d s(tu(nu),v) */
+/*     ------------- =  dr(5)*cos(v)+dr(6)*sin(v) , tv(4) <=v<= tv(nv-3) */
+/*     d u */
+
+/*  where the parameters dr(i) correspond to the derivative values at the */
+/*  poles as defined in subroutine spgrid. */
+
+/*  the b-spline coefficients of sp(u,v) are determined as the least- */
+/*  squares solution  of an overdetermined linear system which depends */
+/*  on the value of p and on the values dr(i),i=1,...,6. the correspond- */
+/*  ing sum of squared residuals sq is a simple quadratic function in */
+/*  the variables dr(i). these may or may not be provided. the values */
+/*  dr(i) which are not given will be determined so as to minimize the */
+/*  resulting sum of squared residuals sq. in that case the user must */
+/*  provide some initial guess dr(i) and some estimate (dr(i)-step, */
+/*  dr(i)+step) of the range of possible values for these latter. */
+
+/*  sp(u,v) also depends on the parameter p (p>0) in such a way that */
+/*    - if p tends to infinity, sp(u,v) becomes the least-squares spline */
+/*      with given knots, satisfying the constraints. */
+/*    - if p tends to zero, sp(u,v) becomes the least-squares polynomial, */
+/*      satisfying the constraints. */
+/*    - the function  f(p)=sumi=1,mu(sumj=1,mv((r(i,j)-sp(u(i),v(j)))**2) */
+/*      is continuous and strictly decreasing for p>0. */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpgrsp,fpsysy */
+/*  .. */
+/*  set constant */
+    /* Parameter adjustments */
+    --nru;
+    --u;
+    --nrv;
+    --v;
+    --r__;
+    --dr;
+    --iopt;
+    --ider;
+    --fpu;
+    --tu;
+    --fpv;
+    --tv;
+    --step;
+    --c__;
+    --wrk;
+
+    /* Function Body */
+    three = (float)3.;
+/*  we partition the working space */
+    lsu = 1;
+    lsv = lsu + (*mu << 2);
+    lri = lsv + (*mv << 2);
+/* Computing MAX */
+    i__1 = *nuest, i__2 = *mv + *nvest;
+    mm = max(i__1,i__2);
+    lq = lri + mm;
+    mvnu = *nuest * (*mv + *nvest - 8);
+    lau = lq + mvnu;
+    lav1 = lau + *nuest * 5;
+    lav2 = lav1 + *nvest * 6;
+    lbu = lav2 + (*nvest << 2);
+    lbv = lbu + *nuest * 5;
+    la0 = lbv + *nvest * 5;
+    la1 = la0 + (*mv << 1);
+    lb0 = la1 + (*mv << 1);
+    lb1 = lb0 + (*nvest << 1);
+    lc0 = lb1 + (*nvest << 1);
+    lc1 = lc0 + *nvest;
+    lcs = lc1 + *nvest;
+/*  we calculate the smoothing spline sp(u,v) according to the input */
+/*  values dr(i),i=1,...,6. */
+    iop0 = iopt[2];
+    iop1 = iopt[3];
+    id0 = ider[1];
+    id1 = ider[3];
+    fpgrsp_(ifsu, ifsv, ifbu, ifbv, &c__0, &u[1], mu, &v[1], mv, &r__[1], mr, 
+	    &dr[1], &iop0, &iop1, &tu[1], nu, &tv[1], nv, p, &c__[1], nc, &sq,
+	     fp, &fpu[1], &fpv[1], &mm, &mvnu, &wrk[lsu], &wrk[lsv], &wrk[lri]
+	    , &wrk[lq], &wrk[lau], &wrk[lav1], &wrk[lav2], &wrk[lbu], &wrk[
+	    lbv], &wrk[la0], &wrk[la1], &wrk[lb0], &wrk[lb1], &wrk[lc0], &wrk[
+	    lc1], &wrk[lcs], &nru[1], &nrv[1]);
+    sq0 = (float)0.;
+    sq1 = (float)0.;
+    if (id0 == 0) {
+/* Computing 2nd power */
+	r__1 = *r0 - dr[1];
+	sq0 = r__1 * r__1;
+    }
+    if (id1 == 0) {
+/* Computing 2nd power */
+	r__1 = *r1 - dr[4];
+	sq1 = r__1 * r__1;
+    }
+    sq = sq + sq0 + sq1;
+/* in case all derivative values dr(i) are given (step<=0) or in case */
+/* we have spline interpolation, we accept this spline as a solution. */
+    if (sq <= (float)0.) {
+	return 0;
+    }
+    if (step[1] <= (float)0. && step[2] <= (float)0.) {
+	return 0;
+    }
+    for (i__ = 1; i__ <= 6; ++i__) {
+	drr[i__ - 1] = dr[i__];
+/* L10: */
+    }
+/* number denotes the number of derivative values dr(i) that still must */
+/* be optimized. let us denote these parameters by g(j),j=1,...,number. */
+    number = 0;
+    if (id0 > 0) {
+	goto L20;
+    }
+    number = 1;
+    nr[0] = 1;
+    delta[0] = step[1];
+L20:
+    if (iop0 == 0) {
+	goto L30;
+    }
+    if (ider[2] != 0) {
+	goto L30;
+    }
+    step2 = step[1] * three / (tu[5] - tu[4]);
+    nr[number] = 2;
+    nr[number + 1] = 3;
+    delta[number] = step2;
+    delta[number + 1] = step2;
+    number += 2;
+L30:
+    if (id1 > 0) {
+	goto L40;
+    }
+    ++number;
+    nr[number - 1] = 4;
+    delta[number - 1] = step[2];
+L40:
+    if (iop1 == 0) {
+	goto L50;
+    }
+    if (ider[4] != 0) {
+	goto L50;
+    }
+    step2 = step[2] * three / (tu[*nu] - tu[*nu - 4]);
+    nr[number] = 5;
+    nr[number + 1] = 6;
+    delta[number] = step2;
+    delta[number + 1] = step2;
+    number += 2;
+L50:
+    if (number == 0) {
+	return 0;
+    }
+/* the sum of squared residulas sq is a quadratic polynomial in the */
+/* parameters g(j). we determine the unknown coefficients of this */
+/* polymomial by calculating (number+1)*(number+2)/2 different splines */
+/* according to specific values for g(j). */
+    i__1 = number;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	l = nr[i__ - 1];
+	step1 = delta[i__ - 1];
+	drr[l - 1] = dr[l] + step1;
+	fpgrsp_(ifsu, ifsv, ifbu, ifbv, &c__1, &u[1], mu, &v[1], mv, &r__[1], 
+		mr, drr, &iop0, &iop1, &tu[1], nu, &tv[1], nv, p, &c__[1], nc,
+		 &sum[i__ - 1], fp, &fpu[1], &fpv[1], &mm, &mvnu, &wrk[lsu], &
+		wrk[lsv], &wrk[lri], &wrk[lq], &wrk[lau], &wrk[lav1], &wrk[
+		lav2], &wrk[lbu], &wrk[lbv], &wrk[la0], &wrk[la1], &wrk[lb0], 
+		&wrk[lb1], &wrk[lc0], &wrk[lc1], &wrk[lcs], &nru[1], &nrv[1]);
+	if (id0 == 0) {
+/* Computing 2nd power */
+	    r__1 = *r0 - drr[0];
+	    sq0 = r__1 * r__1;
+	}
+	if (id1 == 0) {
+/* Computing 2nd power */
+	    r__1 = *r1 - drr[3];
+	    sq1 = r__1 * r__1;
+	}
+	sum[i__ - 1] = sum[i__ - 1] + sq0 + sq1;
+	drr[l - 1] = dr[l] - step1;
+	fpgrsp_(ifsu, ifsv, ifbu, ifbv, &c__1, &u[1], mu, &v[1], mv, &r__[1], 
+		mr, drr, &iop0, &iop1, &tu[1], nu, &tv[1], nv, p, &c__[1], nc,
+		 &sqq, fp, &fpu[1], &fpv[1], &mm, &mvnu, &wrk[lsu], &wrk[lsv],
+		 &wrk[lri], &wrk[lq], &wrk[lau], &wrk[lav1], &wrk[lav2], &wrk[
+		lbu], &wrk[lbv], &wrk[la0], &wrk[la1], &wrk[lb0], &wrk[lb1], &
+		wrk[lc0], &wrk[lc1], &wrk[lcs], &nru[1], &nrv[1]);
+	if (id0 == 0) {
+/* Computing 2nd power */
+	    r__1 = *r0 - drr[0];
+	    sq0 = r__1 * r__1;
+	}
+	if (id1 == 0) {
+/* Computing 2nd power */
+	    r__1 = *r1 - drr[3];
+	    sq1 = r__1 * r__1;
+	}
+	sqq = sqq + sq0 + sq1;
+	drr[l - 1] = dr[l];
+/* Computing 2nd power */
+	r__1 = step1;
+	a[i__ + i__ * 6 - 7] = (sum[i__ - 1] + sqq - sq - sq) / (r__1 * r__1);
+	if (a[i__ + i__ * 6 - 7] <= (float)0.) {
+	    goto L110;
+	}
+	g[i__ - 1] = (sqq - sum[i__ - 1]) / (step1 + step1);
+/* L60: */
+    }
+    if (number == 1) {
+	goto L90;
+    }
+    i__1 = number;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	l1 = nr[i__ - 1];
+	step1 = delta[i__ - 1];
+	drr[l1 - 1] = dr[l1] + step1;
+	i1 = i__ - 1;
+	i__2 = i1;
+	for (j = 1; j <= i__2; ++j) {
+	    l2 = nr[j - 1];
+	    step2 = delta[j - 1];
+	    drr[l2 - 1] = dr[l2] + step2;
+	    fpgrsp_(ifsu, ifsv, ifbu, ifbv, &c__1, &u[1], mu, &v[1], mv, &r__[
+		    1], mr, drr, &iop0, &iop1, &tu[1], nu, &tv[1], nv, p, &
+		    c__[1], nc, &sqq, fp, &fpu[1], &fpv[1], &mm, &mvnu, &wrk[
+		    lsu], &wrk[lsv], &wrk[lri], &wrk[lq], &wrk[lau], &wrk[
+		    lav1], &wrk[lav2], &wrk[lbu], &wrk[lbv], &wrk[la0], &wrk[
+		    la1], &wrk[lb0], &wrk[lb1], &wrk[lc0], &wrk[lc1], &wrk[
+		    lcs], &nru[1], &nrv[1]);
+	    if (id0 == 0) {
+/* Computing 2nd power */
+		r__1 = *r0 - drr[0];
+		sq0 = r__1 * r__1;
+	    }
+	    if (id1 == 0) {
+/* Computing 2nd power */
+		r__1 = *r1 - drr[3];
+		sq1 = r__1 * r__1;
+	    }
+	    sqq = sqq + sq0 + sq1;
+	    a[i__ + j * 6 - 7] = (sq + sqq - sum[i__ - 1] - sum[j - 1]) / (
+		    step1 * step2);
+	    drr[l2 - 1] = dr[l2];
+/* L70: */
+	}
+	drr[l1 - 1] = dr[l1];
+/* L80: */
+    }
+/* the optimal values g(j) are found as the solution of the system */
+/* d (sq) / d (g(j)) = 0 , j=1,...,number. */
+L90:
+    fpsysy_(a, &number, g);
+    i__1 = number;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	l = nr[i__ - 1];
+	dr[l] += g[i__ - 1];
+/* L100: */
+    }
+/* we determine the spline sp(u,v) according to the optimal values g(j). */
+L110:
+    fpgrsp_(ifsu, ifsv, ifbu, ifbv, &c__0, &u[1], mu, &v[1], mv, &r__[1], mr, 
+	    &dr[1], &iop0, &iop1, &tu[1], nu, &tv[1], nv, p, &c__[1], nc, &sq,
+	     fp, &fpu[1], &fpv[1], &mm, &mvnu, &wrk[lsu], &wrk[lsv], &wrk[lri]
+	    , &wrk[lq], &wrk[lau], &wrk[lav1], &wrk[lav2], &wrk[lbu], &wrk[
+	    lbv], &wrk[la0], &wrk[la1], &wrk[lb0], &wrk[lb1], &wrk[lc0], &wrk[
+	    lc1], &wrk[lcs], &nru[1], &nrv[1]);
+    if (id0 == 0) {
+/* Computing 2nd power */
+	r__1 = *r0 - dr[1];
+	sq0 = r__1 * r__1;
+    }
+    if (id1 == 0) {
+/* Computing 2nd power */
+	r__1 = *r1 - dr[4];
+	sq1 = r__1 * r__1;
+    }
+    sq = sq + sq0 + sq1;
+    return 0;
+} /* fpopsp_ */
+
+/* Subroutine */ int fporde_(x, y, m, kx, ky, tx, nx, ty, ny, nummer, index, 
+	nreg)
+real *x, *y;
+integer *m, *kx, *ky;
+real *tx;
+integer *nx;
+real *ty;
+integer *ny, *nummer, *index, *nreg;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__, k, l, k1, l1, im;
+    static real xi, yi;
+    static integer kx1, ky1, num, nyy, nk1x, nk1y;
+
+/*  subroutine fporde sorts the data points (x(i),y(i)),i=1,2,...,m */
+/*  according to the panel tx(l)<=x<tx(l+1),ty(k)<=y<ty(k+1), they belong */
+/*  to. for each panel a stack is constructed  containing the numbers */
+/*  of data points lying inside; index(j),j=1,2,...,nreg points to the */
+/*  first data point in the jth panel while nummer(i),i=1,2,...,m gives */
+/*  the number of the next data point in the panel. */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --nummer;
+    --y;
+    --x;
+    --tx;
+    --ty;
+    --index;
+
+    /* Function Body */
+    kx1 = *kx + 1;
+    ky1 = *ky + 1;
+    nk1x = *nx - kx1;
+    nk1y = *ny - ky1;
+    nyy = nk1y - *ky;
+    i__1 = *nreg;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	index[i__] = 0;
+/* L10: */
+    }
+    i__1 = *m;
+    for (im = 1; im <= i__1; ++im) {
+	xi = x[im];
+	yi = y[im];
+	l = kx1;
+	l1 = l + 1;
+L20:
+	if (xi < tx[l1] || l == nk1x) {
+	    goto L30;
+	}
+	l = l1;
+	l1 = l + 1;
+	goto L20;
+L30:
+	k = ky1;
+	k1 = k + 1;
+L40:
+	if (yi < ty[k1] || k == nk1y) {
+	    goto L50;
+	}
+	k = k1;
+	k1 = k + 1;
+	goto L40;
+L50:
+	num = (l - kx1) * nyy + k - *ky;
+	nummer[im] = index[num];
+	index[num] = im;
+/* L60: */
+    }
+    return 0;
+} /* fporde_ */
+
+/* Subroutine */ int fppara_(iopt, idim, m, u, mx, x, w, ub, ue, k, s, nest, 
+	tol, maxit, k1, k2, n, t, nc, c__, fp, fpint, z__, a, b, g, q, nrdata,
+	 ier)
+integer *iopt, *idim, *m;
+real *u;
+integer *mx;
+real *x, *w, *ub, *ue;
+integer *k;
+real *s;
+integer *nest;
+real *tol;
+integer *maxit, *k1, *k2, *n;
+real *t;
+integer *nc;
+real *c__, *fp, *fpint, *z__, *a, *b, *g, *q;
+integer *nrdata, *ier;
+{
+    /* System generated locals */
+    integer a_dim1, a_offset, b_dim1, b_offset, g_dim1, g_offset, q_dim1, 
+	    q_offset, i__1, i__2, i__3, i__4, i__5;
+    real r__1;
+
+    /* Local variables */
+    static real half;
+    static integer nmin, iter, nmax;
+    static real fpms, term, pinv, h__[7];
+    static integer i__, j, l;
+    static real p, fpold, fpart, f1, f2, f3;
+    static integer i1, i2;
+    static real store;
+    static integer i3, j1;
+    static real p1, p2, p3;
+    static integer j2, k3, l0, nplus, nrint, n8, jj;
+    extern /* Subroutine */ int fpback_();
+    static integer it;
+    static real ui, rn, wi, xi[10];
+    extern /* Subroutine */ int fpdisc_();
+    extern doublereal fprati_();
+    extern /* Subroutine */ int fpbspl_(), fprota_(), fpgivs_(), fpknot_();
+    static real fp0;
+    static integer mk1, nk1;
+    static real acc, fac, one, cos__, sin__;
+    static integer new__;
+    static real piv;
+    static integer ich1, ich3;
+    static real con1, con4, con9;
+    static integer npl1;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references */
+/*  ..subroutine references.. */
+/*    fpback,fpbspl,fpgivs,fpdisc,fpknot,fprota */
+/*  .. */
+/*  set constants */
+    /* Parameter adjustments */
+    --w;
+    --u;
+    --x;
+    --nrdata;
+    --fpint;
+    --t;
+    q_dim1 = *m;
+    q_offset = 1 + q_dim1 * 1;
+    q -= q_offset;
+    a_dim1 = *nest;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+    g_dim1 = *nest;
+    g_offset = 1 + g_dim1 * 1;
+    g -= g_offset;
+    b_dim1 = *nest;
+    b_offset = 1 + b_dim1 * 1;
+    b -= b_offset;
+    --z__;
+    --c__;
+
+    /* Function Body */
+    one = (float)1.;
+    con1 = (float).1;
+    con9 = (float).9;
+    con4 = (float).04;
+    half = (float).5;
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  part 1: determination of the number of knots and their position     c */
+/*  **************************************************************      c */
+/*  given a set of knots we compute the least-squares curve sinf(u),    c */
+/*  and the corresponding sum of squared residuals fp=f(p=inf).         c */
+/*  if iopt=-1 sinf(u) is the requested curve.                          c */
+/*  if iopt=0 or iopt=1 we check whether we can accept the knots:       c */
+/*    if fp <=s we will continue with the current set of knots.         c */
+/*    if fp > s we will increase the number of knots and compute the    c */
+/*       corresponding least-squares curve until finally fp<=s.         c */
+/*    the initial choice of knots depends on the value of s and iopt.   c */
+/*    if s=0 we have spline interpolation; in that case the number of   c */
+/*    knots equals nmax = m+k+1.                                        c */
+/*    if s > 0 and                                                      c */
+/*      iopt=0 we first compute the least-squares polynomial curve of   c */
+/*      degree k; n = nmin = 2*k+2                                      c */
+/*      iopt=1 we start with the set of knots found at the last         c */
+/*      call of the routine, except for the case that s > fp0; then     c */
+/*      we compute directly the polynomial curve of degree k.           c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  determine nmin, the number of knots for polynomial approximation. */
+    nmin = *k1 << 1;
+    if (*iopt < 0) {
+	goto L60;
+    }
+/*  calculation of acc, the absolute tolerance for the root of f(p)=s. */
+    acc = *tol * *s;
+/*  determine nmax, the number of knots for spline interpolation. */
+    nmax = *m + *k1;
+    if (*s > (float)0.) {
+	goto L45;
+    }
+/*  if s=0, s(u) is an interpolating curve. */
+/*  test whether the required storage space exceeds the available one. */
+    *n = nmax;
+    if (nmax > *nest) {
+	goto L420;
+    }
+/*  find the position of the interior knots in case of interpolation. */
+L10:
+    mk1 = *m - *k1;
+    if (mk1 == 0) {
+	goto L60;
+    }
+    k3 = *k / 2;
+    i__ = *k2;
+    j = k3 + 2;
+    if (k3 << 1 == *k) {
+	goto L30;
+    }
+    i__1 = mk1;
+    for (l = 1; l <= i__1; ++l) {
+	t[i__] = u[j];
+	++i__;
+	++j;
+/* L20: */
+    }
+    goto L60;
+L30:
+    i__1 = mk1;
+    for (l = 1; l <= i__1; ++l) {
+	t[i__] = (u[j] + u[j - 1]) * half;
+	++i__;
+	++j;
+/* L40: */
+    }
+    goto L60;
+/*  if s>0 our initial choice of knots depends on the value of iopt. */
+/*  if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares */
+/*  polynomial curve which is a spline curve without interior knots. */
+/*  if iopt=1 and fp0>s we start computing the least squares spline curve */
+/*  according to the set of knots found at the last call of the routine. */
+L45:
+    if (*iopt == 0) {
+	goto L50;
+    }
+    if (*n == nmin) {
+	goto L50;
+    }
+    fp0 = fpint[*n];
+    fpold = fpint[*n - 1];
+    nplus = nrdata[*n];
+    if (fp0 > *s) {
+	goto L60;
+    }
+L50:
+    *n = nmin;
+    fpold = (float)0.;
+    nplus = 0;
+    nrdata[1] = *m - 2;
+/*  main loop for the different sets of knots. m is a save upper bound */
+/*  for the number of trials. */
+L60:
+    i__1 = *m;
+    for (iter = 1; iter <= i__1; ++iter) {
+	if (*n == nmin) {
+	    *ier = -2;
+	}
+/*  find nrint, tne number of knot intervals. */
+	nrint = *n - nmin + 1;
+/*  find the position of the additional knots which are needed for */
+/*  the b-spline representation of s(u). */
+	nk1 = *n - *k1;
+	i__ = *n;
+	i__2 = *k1;
+	for (j = 1; j <= i__2; ++j) {
+	    t[j] = *ub;
+	    t[i__] = *ue;
+	    --i__;
+/* L70: */
+	}
+/*  compute the b-spline coefficients of the least-squares spline curve */
+/*  sinf(u). the observation matrix a is built up row by row and */
+/*  reduced to upper triangular form by givens transformations. */
+/*  at the same time fp=f(p=inf) is computed. */
+	*fp = (float)0.;
+/*  initialize the b-spline coefficients and the observation matrix a. */
+	i__2 = *nc;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    z__[i__] = (float)0.;
+/* L75: */
+	}
+	i__2 = nk1;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    i__3 = *k1;
+	    for (j = 1; j <= i__3; ++j) {
+		a[i__ + j * a_dim1] = (float)0.;
+/* L80: */
+	    }
+	}
+	l = *k1;
+	jj = 0;
+	i__3 = *m;
+	for (it = 1; it <= i__3; ++it) {
+/*  fetch the current data point u(it),x(it). */
+	    ui = u[it];
+	    wi = w[it];
+	    i__2 = *idim;
+	    for (j = 1; j <= i__2; ++j) {
+		++jj;
+		xi[j - 1] = x[jj] * wi;
+/* L83: */
+	    }
+/*  search for knot interval t(l) <= ui < t(l+1). */
+L85:
+	    if (ui < t[l + 1] || l == nk1) {
+		goto L90;
+	    }
+	    ++l;
+	    goto L85;
+/*  evaluate the (k+1) non-zero b-splines at ui and store them in q. */
+L90:
+	    fpbspl_(&t[1], n, k, &ui, &l, h__);
+	    i__2 = *k1;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		q[it + i__ * q_dim1] = h__[i__ - 1];
+		h__[i__ - 1] *= wi;
+/* L95: */
+	    }
+/*  rotate the new row of the observation matrix into triangle. */
+	    j = l - *k1;
+	    i__2 = *k1;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		++j;
+		piv = h__[i__ - 1];
+		if (piv == (float)0.) {
+		    goto L110;
+		}
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &a[j + a_dim1], &cos__, &sin__);
+/*  transformations to right hand side. */
+		j1 = j;
+		i__4 = *idim;
+		for (j2 = 1; j2 <= i__4; ++j2) {
+		    fprota_(&cos__, &sin__, &xi[j2 - 1], &z__[j1]);
+		    j1 += *n;
+/* L97: */
+		}
+		if (i__ == *k1) {
+		    goto L120;
+		}
+		i2 = 1;
+		i3 = i__ + 1;
+		i__4 = *k1;
+		for (i1 = i3; i1 <= i__4; ++i1) {
+		    ++i2;
+/*  transformations to left hand side. */
+		    fprota_(&cos__, &sin__, &h__[i1 - 1], &a[j + i2 * a_dim1])
+			    ;
+/* L100: */
+		}
+L110:
+		;
+	    }
+/*  add contribution of this row to the sum of squares of residual */
+/*  right hand sides. */
+L120:
+	    i__2 = *idim;
+	    for (j2 = 1; j2 <= i__2; ++j2) {
+/* Computing 2nd power */
+		r__1 = xi[j2 - 1];
+		*fp += r__1 * r__1;
+/* L125: */
+	    }
+/* L130: */
+	}
+	if (*ier == -2) {
+	    fp0 = *fp;
+	}
+	fpint[*n] = fp0;
+	fpint[*n - 1] = fpold;
+	nrdata[*n] = nplus;
+/*  backward substitution to obtain the b-spline coefficients. */
+	j1 = 1;
+	i__3 = *idim;
+	for (j2 = 1; j2 <= i__3; ++j2) {
+	    fpback_(&a[a_offset], &z__[j1], &nk1, k1, &c__[j1], nest);
+	    j1 += *n;
+/* L135: */
+	}
+/*  test whether the approximation sinf(u) is an acceptable solution. */
+	if (*iopt < 0) {
+	    goto L440;
+	}
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  if f(p=inf) < s accept the choice of knots. */
+	if (fpms < (float)0.) {
+	    goto L250;
+	}
+/*  if n = nmax, sinf(u) is an interpolating spline curve. */
+	if (*n == nmax) {
+	    goto L430;
+	}
+/*  increase the number of knots. */
+/*  if n=nest we cannot increase the number of knots because of */
+/*  the storage capacity limitation. */
+	if (*n == *nest) {
+	    goto L420;
+	}
+/*  determine the number of knots nplus we are going to add. */
+	if (*ier == 0) {
+	    goto L140;
+	}
+	nplus = 1;
+	*ier = 0;
+	goto L150;
+L140:
+	npl1 = nplus << 1;
+	rn = (real) nplus;
+	if (fpold - *fp > acc) {
+	    npl1 = rn * fpms / (fpold - *fp);
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__4 = npl1, i__5 = nplus / 2, i__4 = max(i__4,i__5);
+	i__3 = nplus << 1, i__2 = max(i__4,1);
+	nplus = min(i__3,i__2);
+L150:
+	fpold = *fp;
+/*  compute the sum of squared residuals for each knot interval */
+/*  t(j+k) <= u(i) <= t(j+k+1) and store it in fpint(j),j=1,2,...nrint. */
+	fpart = (float)0.;
+	i__ = 1;
+	l = *k2;
+	new__ = 0;
+	jj = 0;
+	i__3 = *m;
+	for (it = 1; it <= i__3; ++it) {
+	    if (u[it] < t[l] || l > nk1) {
+		goto L160;
+	    }
+	    new__ = 1;
+	    ++l;
+L160:
+	    term = (float)0.;
+	    l0 = l - *k2;
+	    i__2 = *idim;
+	    for (j2 = 1; j2 <= i__2; ++j2) {
+		fac = (float)0.;
+		j1 = l0;
+		i__4 = *k1;
+		for (j = 1; j <= i__4; ++j) {
+		    ++j1;
+		    fac += c__[j1] * q[it + j * q_dim1];
+/* L170: */
+		}
+		++jj;
+/* Computing 2nd power */
+		r__1 = w[it] * (fac - x[jj]);
+		term += r__1 * r__1;
+		l0 += *n;
+/* L175: */
+	    }
+	    fpart += term;
+	    if (new__ == 0) {
+		goto L180;
+	    }
+	    store = term * half;
+	    fpint[i__] = fpart - store;
+	    ++i__;
+	    fpart = store;
+	    new__ = 0;
+L180:
+	    ;
+	}
+	fpint[nrint] = fpart;
+	i__3 = nplus;
+	for (l = 1; l <= i__3; ++l) {
+/*  add a new knot. */
+	    fpknot_(&u[1], m, &t[1], n, &fpint[1], &nrdata[1], &nrint, nest, &
+		    c__1);
+/*  if n=nmax we locate the knots as for interpolation */
+	    if (*n == nmax) {
+		goto L10;
+	    }
+/*  test whether we cannot further increase the number of knots. */
+	    if (*n == *nest) {
+		goto L200;
+	    }
+/* L190: */
+	}
+/*  restart the computations with the new set of knots. */
+L200:
+	;
+    }
+/*  test whether the least-squares kth degree polynomial curve is a */
+/*  solution of our approximation problem. */
+L250:
+    if (*ier == -2) {
+	goto L440;
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  part 2: determination of the smoothing spline curve sp(u).          c */
+/*  **********************************************************          c */
+/*  we have determined the number of knots and their position.          c */
+/*  we now compute the b-spline coefficients of the smoothing curve     c */
+/*  sp(u). the observation matrix a is extended by the rows of matrix   c */
+/*  b expressing that the kth derivative discontinuities of sp(u) at    c */
+/*  the interior knots t(k+2),...t(n-k-1) must be zero. the corres-     c */
+/*  ponding weights of these additional rows are set to 1/p.            c */
+/*  iteratively we then have to determine the value of p such that f(p),c */
+/*  the sum of squared residuals be = s. we already know that the least c */
+/*  squares kth degree polynomial curve corresponds to p=0, and that    c */
+/*  the least-squares spline curve corresponds to p=infinity. the       c */
+/*  iteration process which is proposed here, makes use of rational     c */
+/*  interpolation. since f(p) is a convex and strictly decreasing       c */
+/*  function of p, it can be approximated by a rational function        c */
+/*  r(p) = (u*p+v)/(p+w). three values of p(p1,p2,p3) with correspond-  c */
+/*  ing values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used      c */
+/*  to calculate the new value of p such that r(p)=s. convergence is    c */
+/*  guaranteed by taking f1>0 and f3<0.                                 c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  evaluate the discontinuity jump of the kth derivative of the */
+/*  b-splines at the knots t(l),l=k+2,...n-k-1 and store in b. */
+    fpdisc_(&t[1], n, k2, &b[b_offset], nest);
+/*  initial value for p. */
+    p1 = (float)0.;
+    f1 = fp0 - *s;
+    p3 = -one;
+    f3 = fpms;
+    p = (float)0.;
+    i__1 = nk1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	p += a[i__ + a_dim1];
+/* L252: */
+    }
+    rn = (real) nk1;
+    p = rn / p;
+    ich1 = 0;
+    ich3 = 0;
+    n8 = *n - nmin;
+/*  iteration process to find the root of f(p) = s. */
+    i__1 = *maxit;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  the rows of matrix b with weight 1/p are rotated into the */
+/*  triangularised observation matrix a which is stored in g. */
+	pinv = one / p;
+	i__3 = *nc;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    c__[i__] = z__[i__];
+/* L255: */
+	}
+	i__3 = nk1;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    g[i__ + *k2 * g_dim1] = (float)0.;
+	    i__2 = *k1;
+	    for (j = 1; j <= i__2; ++j) {
+		g[i__ + j * g_dim1] = a[i__ + j * a_dim1];
+/* L260: */
+	    }
+	}
+	i__2 = n8;
+	for (it = 1; it <= i__2; ++it) {
+/*  the row of matrix b is rotated into triangle by givens transformation */
+	    i__3 = *k2;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		h__[i__ - 1] = b[it + i__ * b_dim1] * pinv;
+/* L270: */
+	    }
+	    i__3 = *idim;
+	    for (j = 1; j <= i__3; ++j) {
+		xi[j - 1] = (float)0.;
+/* L275: */
+	    }
+	    i__3 = nk1;
+	    for (j = it; j <= i__3; ++j) {
+		piv = h__[0];
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &g[j + g_dim1], &cos__, &sin__);
+/*  transformations to right hand side. */
+		j1 = j;
+		i__4 = *idim;
+		for (j2 = 1; j2 <= i__4; ++j2) {
+		    fprota_(&cos__, &sin__, &xi[j2 - 1], &c__[j1]);
+		    j1 += *n;
+/* L277: */
+		}
+		if (j == nk1) {
+		    goto L300;
+		}
+		i2 = *k1;
+		if (j > n8) {
+		    i2 = nk1 - j;
+		}
+		i__4 = i2;
+		for (i__ = 1; i__ <= i__4; ++i__) {
+/*  transformations to left hand side. */
+		    i1 = i__ + 1;
+		    fprota_(&cos__, &sin__, &h__[i1 - 1], &g[j + i1 * g_dim1])
+			    ;
+		    h__[i__ - 1] = h__[i1 - 1];
+/* L280: */
+		}
+		h__[i2] = (float)0.;
+/* L290: */
+	    }
+L300:
+	    ;
+	}
+/*  backward substitution to obtain the b-spline coefficients. */
+	j1 = 1;
+	i__2 = *idim;
+	for (j2 = 1; j2 <= i__2; ++j2) {
+	    fpback_(&g[g_offset], &c__[j1], &nk1, k2, &c__[j1], nest);
+	    j1 += *n;
+/* L305: */
+	}
+/*  computation of f(p). */
+	*fp = (float)0.;
+	l = *k2;
+	jj = 0;
+	i__2 = *m;
+	for (it = 1; it <= i__2; ++it) {
+	    if (u[it] < t[l] || l > nk1) {
+		goto L310;
+	    }
+	    ++l;
+L310:
+	    l0 = l - *k2;
+	    term = (float)0.;
+	    i__3 = *idim;
+	    for (j2 = 1; j2 <= i__3; ++j2) {
+		fac = (float)0.;
+		j1 = l0;
+		i__4 = *k1;
+		for (j = 1; j <= i__4; ++j) {
+		    ++j1;
+		    fac += c__[j1] * q[it + j * q_dim1];
+/* L320: */
+		}
+		++jj;
+/* Computing 2nd power */
+		r__1 = fac - x[jj];
+		term += r__1 * r__1;
+		l0 += *n;
+/* L325: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[it];
+	    *fp += term * (r__1 * r__1);
+/* L330: */
+	}
+/*  test whether the approximation sp(u) is an acceptable solution. */
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  test whether the maximal number of iterations is reached. */
+	if (iter == *maxit) {
+	    goto L400;
+	}
+/*  carry out one more step of the iteration process. */
+	p2 = p;
+	f2 = fpms;
+	if (ich3 != 0) {
+	    goto L340;
+	}
+	if (f2 - f3 > acc) {
+	    goto L335;
+	}
+/*  our initial choice of p is too large. */
+	p3 = p2;
+	f3 = f2;
+	p *= con4;
+	if (p <= p1) {
+	    p = p1 * con9 + p2 * con1;
+	}
+	goto L360;
+L335:
+	if (f2 < (float)0.) {
+	    ich3 = 1;
+	}
+L340:
+	if (ich1 != 0) {
+	    goto L350;
+	}
+	if (f1 - f2 > acc) {
+	    goto L345;
+	}
+/*  our initial choice of p is too small */
+	p1 = p2;
+	f1 = f2;
+	p /= con4;
+	if (p3 < (float)0.) {
+	    goto L360;
+	}
+	if (p >= p3) {
+	    p = p2 * con1 + p3 * con9;
+	}
+	goto L360;
+L345:
+	if (f2 > (float)0.) {
+	    ich1 = 1;
+	}
+/*  test whether the iteration process proceeds as theoretically */
+/*  expected. */
+L350:
+	if (f2 >= f1 || f2 <= f3) {
+	    goto L410;
+	}
+/*  find the new value for p. */
+	p = fprati_(&p1, &f1, &p2, &f2, &p3, &f3);
+L360:
+	;
+    }
+/*  error codes and messages. */
+L400:
+    *ier = 3;
+    goto L440;
+L410:
+    *ier = 2;
+    goto L440;
+L420:
+    *ier = 1;
+    goto L440;
+L430:
+    *ier = -1;
+L440:
+    return 0;
+} /* fppara_ */
+
+/* Subroutine */ int fppasu_(iopt, ipar, idim, u, mu, v, mv, z__, mz, s, 
+	nuest, nvest, tol, maxit, nc, nu, tu, nv, tv, c__, fp, fp0, fpold, 
+	reducu, reducv, fpintu, fpintv, lastdi, nplusu, nplusv, nru, nrv, 
+	nrdatu, nrdatv, wrk, lwrk, ier)
+integer *iopt, *ipar, *idim;
+real *u;
+integer *mu;
+real *v;
+integer *mv;
+real *z__;
+integer *mz;
+real *s;
+integer *nuest, *nvest;
+real *tol;
+integer *maxit, *nc, *nu;
+real *tu;
+integer *nv;
+real *tv, *c__, *fp, *fp0, *fpold, *reducu, *reducv, *fpintu, *fpintv;
+integer *lastdi, *nplusu, *nplusv, *nru, *nrv, *nrdatu, *nrdatv;
+real *wrk;
+integer *lwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3, i__4, i__5;
+
+    /* Local variables */
+    static integer ifbu, ifbv, ncof, iter;
+    static real fpms;
+    static integer ifsu, ifsv;
+    static real peru, perv;
+    static integer nplu, nplv, mvnu, i__, j, l;
+    static real p;
+    static integer nminu;
+    static real f1, f2, f3;
+    static integer nmaxu, nmaxv, nminv, l1, l2;
+    static real p1, p2, p3;
+    static integer l3, l4;
+    static real ub, vb, ue, ve;
+    static integer mm, lq;
+    static real rn;
+    extern /* Subroutine */ int fpgrpa_();
+    extern doublereal fprati_();
+    extern /* Subroutine */ int fpknot_();
+    static integer nrintu, nrintv;
+    static real acc;
+    static integer laa;
+    static real one;
+    static integer lau, lav, lbu, lbv, lri, nue, nve, mpm, nuk, lsu, lsv, nuu,
+	     nvv, ich1, ich3;
+    static real con1;
+    static integer lau1;
+    static real con4;
+    static integer lav1;
+    static real con9;
+    static integer npl1, nk1u, nk1v;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpgrpa,fpknot */
+/*  .. */
+/*   set constants */
+    /* Parameter adjustments */
+    --ipar;
+    --nru;
+    --u;
+    --nrv;
+    --v;
+    --z__;
+    --nrdatu;
+    --fpintu;
+    --tu;
+    --nrdatv;
+    --fpintv;
+    --tv;
+    --c__;
+    --wrk;
+
+    /* Function Body */
+    one = (float)1.;
+    con1 = (float).1;
+    con9 = (float).9;
+    con4 = (float).04;
+/*  set boundaries of the approximation domain */
+    ub = u[1];
+    ue = u[*mu];
+    vb = v[1];
+    ve = v[*mv];
+/*  we partition the working space. */
+    lsu = 1;
+    lsv = lsu + (*mu << 2);
+    lri = lsv + (*mv << 2);
+    mm = max(*nuest,*mv);
+    lq = lri + mm * *idim;
+    mvnu = *nuest * *mv * *idim;
+    lau = lq + mvnu;
+    nuk = *nuest * 5;
+    lbu = lau + nuk;
+    lav = lbu + nuk;
+    nuk = *nvest * 5;
+    lbv = lav + nuk;
+    laa = lbv + nuk;
+    lau1 = lau;
+    if (ipar[1] == 0) {
+	goto L10;
+    }
+    peru = ue - ub;
+    lau1 = laa;
+    laa += *nuest << 2;
+L10:
+    lav1 = lav;
+    if (ipar[2] == 0) {
+	goto L20;
+    }
+    perv = ve - vb;
+    lav1 = laa;
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/* part 1: determination of the number of knots and their position.     c */
+/* ****************************************************************     c */
+/*  given a set of knots we compute the least-squares spline sinf(u,v), c */
+/*  and the corresponding sum of squared residuals fp=f(p=inf).         c */
+/*  if iopt=-1  sinf(u,v) is the requested approximation.               c */
+/*  if iopt=0 or iopt=1 we check whether we can accept the knots:       c */
+/*    if fp <=s we will continue with the current set of knots.         c */
+/*    if fp > s we will increase the number of knots and compute the    c */
+/*       corresponding least-squares spline until finally fp<=s.        c */
+/*    the initial choice of knots depends on the value of s and iopt.   c */
+/*    if s=0 we have spline interpolation; in that case the number of   c */
+/*    knots equals nmaxu = mu+4+2*ipar(1) and  nmaxv = mv+4+2*ipar(2)   c */
+/*    if s>0 and                                                        c */
+/*     *iopt=0 we first compute the least-squares polynomial            c */
+/*          nu=nminu=8 and nv=nminv=8                                   c */
+/*     *iopt=1 we start with the knots found at the last call of the    c */
+/*      routine, except for the case that s > fp0; then we can compute  c */
+/*      the least-squares polynomial directly.                          c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  determine the number of knots for polynomial approximation. */
+L20:
+    nminu = 8;
+    nminv = 8;
+    if (*iopt < 0) {
+	goto L100;
+    }
+/*  acc denotes the absolute tolerance for the root of f(p)=s. */
+    acc = *tol * *s;
+/*  find nmaxu and nmaxv which denote the number of knots in u- and v- */
+/*  direction in case of spline interpolation. */
+    nmaxu = *mu + 4 + (ipar[1] << 1);
+    nmaxv = *mv + 4 + (ipar[2] << 1);
+/*  find nue and nve which denote the maximum number of knots */
+/*  allowed in each direction */
+    nue = min(nmaxu,*nuest);
+    nve = min(nmaxv,*nvest);
+    if (*s > (float)0.) {
+	goto L60;
+    }
+/*  if s = 0, s(u,v) is an interpolating spline. */
+    *nu = nmaxu;
+    *nv = nmaxv;
+/*  test whether the required storage space exceeds the available one. */
+    if (*nv > *nvest || *nu > *nuest) {
+	goto L420;
+    }
+/*  find the position of the interior knots in case of interpolation. */
+/*  the knots in the u-direction. */
+    nuu = *nu - 8;
+    if (nuu == 0) {
+	goto L40;
+    }
+    i__ = 5;
+    j = 3 - ipar[1];
+    i__1 = nuu;
+    for (l = 1; l <= i__1; ++l) {
+	tu[i__] = u[j];
+	++i__;
+	++j;
+/* L30: */
+    }
+/*  the knots in the v-direction. */
+L40:
+    nvv = *nv - 8;
+    if (nvv == 0) {
+	goto L60;
+    }
+    i__ = 5;
+    j = 3 - ipar[2];
+    i__1 = nvv;
+    for (l = 1; l <= i__1; ++l) {
+	tv[i__] = v[j];
+	++i__;
+	++j;
+/* L50: */
+    }
+    goto L100;
+/*  if s > 0 our initial choice of knots depends on the value of iopt. */
+L60:
+    if (*iopt == 0) {
+	goto L90;
+    }
+    if (*fp0 <= *s) {
+	goto L90;
+    }
+/*  if iopt=1 and fp0 > s we start computing the least- squares spline */
+/*  according to the set of knots found at the last call of the routine. */
+/*  we determine the number of grid coordinates u(i) inside each knot */
+/*  interval (tu(l),tu(l+1)). */
+    l = 5;
+    j = 1;
+    nrdatu[1] = 0;
+    mpm = *mu - 1;
+    i__1 = mpm;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	++nrdatu[j];
+	if (u[i__] < tu[l]) {
+	    goto L70;
+	}
+	--nrdatu[j];
+	++l;
+	++j;
+	nrdatu[j] = 0;
+L70:
+	;
+    }
+/*  we determine the number of grid coordinates v(i) inside each knot */
+/*  interval (tv(l),tv(l+1)). */
+    l = 5;
+    j = 1;
+    nrdatv[1] = 0;
+    mpm = *mv - 1;
+    i__1 = mpm;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	++nrdatv[j];
+	if (v[i__] < tv[l]) {
+	    goto L80;
+	}
+	--nrdatv[j];
+	++l;
+	++j;
+	nrdatv[j] = 0;
+L80:
+	;
+    }
+    goto L100;
+/*  if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares */
+/*  polynomial (which is a spline without interior knots). */
+L90:
+    *nu = nminu;
+    *nv = nminv;
+    nrdatu[1] = *mu - 2;
+    nrdatv[1] = *mv - 2;
+    *lastdi = 0;
+    *nplusu = 0;
+    *nplusv = 0;
+    *fp0 = (float)0.;
+    *fpold = (float)0.;
+    *reducu = (float)0.;
+    *reducv = (float)0.;
+L100:
+    mpm = *mu + *mv;
+    ifsu = 0;
+    ifsv = 0;
+    ifbu = 0;
+    ifbv = 0;
+    p = -one;
+/*  main loop for the different sets of knots.mpm=mu+mv is a save upper */
+/*  bound for the number of trials. */
+    i__1 = mpm;
+    for (iter = 1; iter <= i__1; ++iter) {
+	if (*nu == nminu && *nv == nminv) {
+	    *ier = -2;
+	}
+/*  find nrintu (nrintv) which is the number of knot intervals in the */
+/*  u-direction (v-direction). */
+	nrintu = *nu - nminu + 1;
+	nrintv = *nv - nminv + 1;
+/*  find ncof, the number of b-spline coefficients for the current set */
+/*  of knots. */
+	nk1u = *nu - 4;
+	nk1v = *nv - 4;
+	ncof = nk1u * nk1v;
+/*  find the position of the additional knots which are needed for the */
+/*  b-spline representation of s(u,v). */
+	if (ipar[1] != 0) {
+	    goto L110;
+	}
+	i__ = *nu;
+	for (j = 1; j <= 4; ++j) {
+	    tu[j] = ub;
+	    tu[i__] = ue;
+	    --i__;
+/* L105: */
+	}
+	goto L120;
+L110:
+	l1 = 4;
+	l2 = l1;
+	l3 = *nu - 3;
+	l4 = l3;
+	tu[l2] = ub;
+	tu[l3] = ue;
+	for (j = 1; j <= 3; ++j) {
+	    ++l1;
+	    --l2;
+	    ++l3;
+	    --l4;
+	    tu[l2] = tu[l4] - peru;
+	    tu[l3] = tu[l1] + peru;
+/* L115: */
+	}
+L120:
+	if (ipar[2] != 0) {
+	    goto L130;
+	}
+	i__ = *nv;
+	for (j = 1; j <= 4; ++j) {
+	    tv[j] = vb;
+	    tv[i__] = ve;
+	    --i__;
+/* L125: */
+	}
+	goto L140;
+L130:
+	l1 = 4;
+	l2 = l1;
+	l3 = *nv - 3;
+	l4 = l3;
+	tv[l2] = vb;
+	tv[l3] = ve;
+	for (j = 1; j <= 3; ++j) {
+	    ++l1;
+	    --l2;
+	    ++l3;
+	    --l4;
+	    tv[l2] = tv[l4] - perv;
+	    tv[l3] = tv[l1] + perv;
+/* L135: */
+	}
+/*  find the least-squares spline sinf(u,v) and calculate for each knot */
+/*  interval tu(j+3)<=u<=tu(j+4) (tv(j+3)<=v<=tv(j+4)) the sum */
+/*  of squared residuals fpintu(j),j=1,2,...,nu-7 (fpintv(j),j=1,2,... */
+/*  ,nv-7) for the data points having their absciss (ordinate)-value */
+/*  belonging to that interval. */
+/*  fp gives the total sum of squared residuals. */
+L140:
+	fpgrpa_(&ifsu, &ifsv, &ifbu, &ifbv, idim, &ipar[1], &u[1], mu, &v[1], 
+		mv, &z__[1], mz, &tu[1], nu, &tv[1], nv, &p, &c__[1], nc, fp, 
+		&fpintu[1], &fpintv[1], &mm, &mvnu, &wrk[lsu], &wrk[lsv], &
+		wrk[lri], &wrk[lq], &wrk[lau], &wrk[lau1], &wrk[lav], &wrk[
+		lav1], &wrk[lbu], &wrk[lbv], &nru[1], &nrv[1]);
+	if (*ier == -2) {
+	    *fp0 = *fp;
+	}
+/*  test whether the least-squares spline is an acceptable solution. */
+	if (*iopt < 0) {
+	    goto L440;
+	}
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  if f(p=inf) < s, we accept the choice of knots. */
+	if (fpms < (float)0.) {
+	    goto L300;
+	}
+/*  if nu=nmaxu and nv=nmaxv, sinf(u,v) is an interpolating spline. */
+	if (*nu == nmaxu && *nv == nmaxv) {
+	    goto L430;
+	}
+/*  increase the number of knots. */
+/*  if nu=nue and nv=nve we cannot further increase the number of knots */
+/*  because of the storage capacity limitation. */
+	if (*nu == nue && *nv == nve) {
+	    goto L420;
+	}
+	*ier = 0;
+/*  adjust the parameter reducu or reducv according to the direction */
+/*  in which the last added knots were located. */
+	if (*lastdi < 0) {
+	    goto L150;
+	} else if (*lastdi == 0) {
+	    goto L170;
+	} else {
+	    goto L160;
+	}
+L150:
+	*reducu = *fpold - *fp;
+	goto L170;
+L160:
+	*reducv = *fpold - *fp;
+/*  store the sum of squared residuals for the current set of knots. */
+L170:
+	*fpold = *fp;
+/*  find nplu, the number of knots we should add in the u-direction. */
+	nplu = 1;
+	if (*nu == nminu) {
+	    goto L180;
+	}
+	npl1 = *nplusu << 1;
+	rn = (real) (*nplusu);
+	if (*reducu > acc) {
+	    npl1 = rn * fpms / *reducu;
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__4 = npl1, i__5 = *nplusu / 2, i__4 = max(i__4,i__5);
+	i__2 = *nplusu << 1, i__3 = max(i__4,1);
+	nplu = min(i__2,i__3);
+/*  find nplv, the number of knots we should add in the v-direction. */
+L180:
+	nplv = 1;
+	if (*nv == nminv) {
+	    goto L190;
+	}
+	npl1 = *nplusv << 1;
+	rn = (real) (*nplusv);
+	if (*reducv > acc) {
+	    npl1 = rn * fpms / *reducv;
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__4 = npl1, i__5 = *nplusv / 2, i__4 = max(i__4,i__5);
+	i__2 = *nplusv << 1, i__3 = max(i__4,1);
+	nplv = min(i__2,i__3);
+L190:
+	if ((i__2 = nplu - nplv) < 0) {
+	    goto L210;
+	} else if (i__2 == 0) {
+	    goto L200;
+	} else {
+	    goto L230;
+	}
+L200:
+	if (*lastdi < 0) {
+	    goto L230;
+	}
+L210:
+	if (*nu == nue) {
+	    goto L230;
+	}
+/*  addition in the u-direction. */
+	*lastdi = -1;
+	*nplusu = nplu;
+	ifsu = 0;
+	i__2 = *nplusu;
+	for (l = 1; l <= i__2; ++l) {
+/*  add a new knot in the u-direction */
+	    fpknot_(&u[1], mu, &tu[1], nu, &fpintu[1], &nrdatu[1], &nrintu, 
+		    nuest, &c__1);
+/*  test whether we cannot further increase the number of knots in the */
+/*  u-direction. */
+	    if (*nu == nue) {
+		goto L250;
+	    }
+/* L220: */
+	}
+	goto L250;
+L230:
+	if (*nv == nve) {
+	    goto L210;
+	}
+/*  addition in the v-direction. */
+	*lastdi = 1;
+	*nplusv = nplv;
+	ifsv = 0;
+	i__2 = *nplusv;
+	for (l = 1; l <= i__2; ++l) {
+/*  add a new knot in the v-direction. */
+	    fpknot_(&v[1], mv, &tv[1], nv, &fpintv[1], &nrdatv[1], &nrintv, 
+		    nvest, &c__1);
+/*  test whether we cannot further increase the number of knots in the */
+/*  v-direction. */
+	    if (*nv == nve) {
+		goto L250;
+	    }
+/* L240: */
+	}
+/*  restart the computations with the new set of knots. */
+L250:
+	;
+    }
+/*  test whether the least-squares polynomial is a solution of our */
+/*  approximation problem. */
+L300:
+    if (*ier == -2) {
+	goto L440;
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/* part 2: determination of the smoothing spline sp(u,v)                c */
+/* *****************************************************                c */
+/*  we have determined the number of knots and their position. we now   c */
+/*  compute the b-spline coefficients of the smoothing spline sp(u,v).  c */
+/*  this smoothing spline varies with the parameter p in such a way thatc */
+/*  f(p)=suml=1,idim(sumi=1,mu(sumj=1,mv((z(i,j,l)-sp(u(i),v(j),l))**2) c */
+/*  is a continuous, strictly decreasing function of p. moreover the    c */
+/*  least-squares polynomial corresponds to p=0 and the least-squares   c */
+/*  spline to p=infinity. iteratively we then have to determine the     c */
+/*  positive value of p such that f(p)=s. the process which is proposed c */
+/*  here makes use of rational interpolation. f(p) is approximated by a c */
+/*  rational function r(p)=(u*p+v)/(p+w); three values of p (p1,p2,p3)  c */
+/*  with corresponding values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s)c */
+/*  are used to calculate the new value of p such that r(p)=s.          c */
+/*  convergence is guaranteed by taking f1 > 0 and f3 < 0.              c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  initial value for p. */
+    p1 = (float)0.;
+    f1 = *fp0 - *s;
+    p3 = -one;
+    f3 = fpms;
+    p = one;
+    ich1 = 0;
+    ich3 = 0;
+/*  iteration process to find the root of f(p)=s. */
+    i__1 = *maxit;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  find the smoothing spline sp(u,v) and the corresponding sum of */
+/*  squared residuals fp. */
+	fpgrpa_(&ifsu, &ifsv, &ifbu, &ifbv, idim, &ipar[1], &u[1], mu, &v[1], 
+		mv, &z__[1], mz, &tu[1], nu, &tv[1], nv, &p, &c__[1], nc, fp, 
+		&fpintu[1], &fpintv[1], &mm, &mvnu, &wrk[lsu], &wrk[lsv], &
+		wrk[lri], &wrk[lq], &wrk[lau], &wrk[lau1], &wrk[lav], &wrk[
+		lav1], &wrk[lbu], &wrk[lbv], &nru[1], &nrv[1]);
+/*  test whether the approximation sp(u,v) is an acceptable solution. */
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  test whether the maximum allowable number of iterations has been */
+/*  reached. */
+	if (iter == *maxit) {
+	    goto L400;
+	}
+/*  carry out one more step of the iteration process. */
+	p2 = p;
+	f2 = fpms;
+	if (ich3 != 0) {
+	    goto L320;
+	}
+	if (f2 - f3 > acc) {
+	    goto L310;
+	}
+/*  our initial choice of p is too large. */
+	p3 = p2;
+	f3 = f2;
+	p *= con4;
+	if (p <= p1) {
+	    p = p1 * con9 + p2 * con1;
+	}
+	goto L350;
+L310:
+	if (f2 < (float)0.) {
+	    ich3 = 1;
+	}
+L320:
+	if (ich1 != 0) {
+	    goto L340;
+	}
+	if (f1 - f2 > acc) {
+	    goto L330;
+	}
+/*  our initial choice of p is too small */
+	p1 = p2;
+	f1 = f2;
+	p /= con4;
+	if (p3 < (float)0.) {
+	    goto L350;
+	}
+	if (p >= p3) {
+	    p = p2 * con1 + p3 * con9;
+	}
+	goto L350;
+/*  test whether the iteration process proceeds as theoretically */
+/*  expected. */
+L330:
+	if (f2 > (float)0.) {
+	    ich1 = 1;
+	}
+L340:
+	if (f2 >= f1 || f2 <= f3) {
+	    goto L410;
+	}
+/*  find the new value of p. */
+	p = fprati_(&p1, &f1, &p2, &f2, &p3, &f3);
+L350:
+	;
+    }
+/*  error codes and messages. */
+L400:
+    *ier = 3;
+    goto L440;
+L410:
+    *ier = 2;
+    goto L440;
+L420:
+    *ier = 1;
+    goto L440;
+L430:
+    *ier = -1;
+    *fp = (float)0.;
+L440:
+    return 0;
+} /* fppasu_ */
+
+/* Subroutine */ int fpperi_(iopt, x, y, w, m, k, s, nest, tol, maxit, k1, k2,
+	 n, t, c__, fp, fpint, z__, a1, a2, b, g1, g2, q, nrdata, ier)
+integer *iopt;
+real *x, *y, *w;
+integer *m, *k;
+real *s;
+integer *nest;
+real *tol;
+integer *maxit, *k1, *k2, *n;
+real *t, *c__, *fp, *fpint, *z__, *a1, *a2, *b, *g1, *g2, *q;
+integer *nrdata, *ier;
+{
+    /* System generated locals */
+    integer a1_dim1, a1_offset, a2_dim1, a2_offset, b_dim1, b_offset, g1_dim1,
+	     g1_offset, g2_dim1, g2_offset, q_dim1, q_offset, i__1, i__2, 
+	    i__3, i__4, i__5;
+    real r__1;
+
+    /* Local variables */
+    static real half;
+    static integer jper, nmin, iter, nmax;
+    static real fpms, term, pinv, h__[6];
+    static integer i__, j, l;
+    static real p, fpold, fpart, c1, d1, f1, f2, f3, store;
+    static integer i1, i2;
+    static real p1, p2, p3;
+    static integer i3, j1, j2, k3, l0, l1, l5, m1, nplus, nrint, n7, n8;
+    static real h1[7], h2[6];
+    static integer n10, n11, ij, ik, jk, kk, mm;
+    extern /* Subroutine */ int fpbacp_();
+    static integer it;
+    static real wi, xi, yi, rn;
+    extern /* Subroutine */ int fpdisc_();
+    extern doublereal fprati_();
+    extern /* Subroutine */ int fpbspl_(), fprota_(), fpgivs_(), fpknot_();
+    static real fp0;
+    static integer kk1, nk1, nk2;
+    static real acc, one, cos__, per, sin__;
+    static integer new__;
+    static real piv;
+    static integer ich1, ich3;
+    static real con1, con4, con9;
+    static integer npl1;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpbacp,fpbspl,fpgivs,fpdisc,fpknot,fprota */
+/*  .. */
+/*  set constants */
+    /* Parameter adjustments */
+    --w;
+    --y;
+    --x;
+    --nrdata;
+    a2_dim1 = *nest;
+    a2_offset = 1 + a2_dim1 * 1;
+    a2 -= a2_offset;
+    --z__;
+    --fpint;
+    --c__;
+    --t;
+    q_dim1 = *m;
+    q_offset = 1 + q_dim1 * 1;
+    q -= q_offset;
+    g2_dim1 = *nest;
+    g2_offset = 1 + g2_dim1 * 1;
+    g2 -= g2_offset;
+    a1_dim1 = *nest;
+    a1_offset = 1 + a1_dim1 * 1;
+    a1 -= a1_offset;
+    g1_dim1 = *nest;
+    g1_offset = 1 + g1_dim1 * 1;
+    g1 -= g1_offset;
+    b_dim1 = *nest;
+    b_offset = 1 + b_dim1 * 1;
+    b -= b_offset;
+
+    /* Function Body */
+    one = (float)1.;
+    con1 = (float).1;
+    con9 = (float).9;
+    con4 = (float).04;
+    half = (float).5;
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  part 1: determination of the number of knots and their position     c */
+/*  **************************************************************      c */
+/*  given a set of knots we compute the least-squares periodic spline   c */
+/*  sinf(x). if the sum f(p=inf) <= s we accept the choice of knots.    c */
+/*  the initial choice of knots depends on the value of s and iopt.     c */
+/*    if s=0 we have spline interpolation; in that case the number of   c */
+/*    knots equals nmax = m+2*k.                                        c */
+/*    if s > 0 and                                                      c */
+/*      iopt=0 we first compute the least-squares polynomial of         c */
+/*      degree k; n = nmin = 2*k+2. since s(x) must be periodic we      c */
+/*      find that s(x) is a constant function.                          c */
+/*      iopt=1 we start with the set of knots found at the last         c */
+/*      call of the routine, except for the case that s > fp0; then     c */
+/*      we compute directly the least-squares periodic polynomial.      c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+    m1 = *m - 1;
+    kk = *k;
+    kk1 = *k1;
+    k3 = *k * 3 + 1;
+    nmin = *k1 << 1;
+/*  determine the length of the period of s(x). */
+    per = x[*m] - x[1];
+    if (*iopt < 0) {
+	goto L50;
+    }
+/*  calculation of acc, the absolute tolerance for the root of f(p)=s. */
+    acc = *tol * *s;
+/*  determine nmax, the number of knots for periodic spline interpolation */
+    nmax = *m + (*k << 1);
+    if (*s > (float)0. || nmax == nmin) {
+	goto L30;
+    }
+/*  if s=0, s(x) is an interpolating spline. */
+    *n = nmax;
+/*  test whether the required storage space exceeds the available one. */
+    if (*n > *nest) {
+	goto L620;
+    }
+/*  find the position of the interior knots in case of interpolation. */
+L5:
+    if (*k / 2 << 1 == *k) {
+	goto L20;
+    }
+    i__1 = m1;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	j = i__ + *k;
+	t[j] = x[i__];
+/* L10: */
+    }
+    if (*s > (float)0.) {
+	goto L50;
+    }
+    kk = *k - 1;
+    kk1 = *k;
+    if (kk > 0) {
+	goto L50;
+    }
+    t[1] = t[*m] - per;
+    t[2] = x[1];
+    t[*m + 1] = x[*m];
+    t[*m + 2] = t[3] + per;
+    i__1 = m1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = y[i__];
+/* L15: */
+    }
+    c__[*m] = c__[1];
+    *fp = (float)0.;
+    fpint[*n] = fp0;
+    fpint[*n - 1] = (float)0.;
+    nrdata[*n] = 0;
+    goto L630;
+L20:
+    i__1 = m1;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	j = i__ + *k;
+	t[j] = (x[i__] + x[i__ - 1]) * half;
+/* L25: */
+    }
+    goto L50;
+/*  if s > 0 our initial choice depends on the value of iopt. */
+/*  if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares */
+/*  periodic polynomial. (i.e. a constant function). */
+/*  if iopt=1 and fp0>s we start computing the least-squares periodic */
+/*  spline according the set of knots found at the last call of the */
+/*  routine. */
+L30:
+    if (*iopt == 0) {
+	goto L35;
+    }
+    if (*n == nmin) {
+	goto L35;
+    }
+    fp0 = fpint[*n];
+    fpold = fpint[*n - 1];
+    nplus = nrdata[*n];
+    if (fp0 > *s) {
+	goto L50;
+    }
+/*  the case that s(x) is a constant function is treated separetely. */
+/*  find the least-squares constant c1 and compute fp0 at the same time. */
+L35:
+    fp0 = (float)0.;
+    d1 = (float)0.;
+    c1 = (float)0.;
+    i__1 = m1;
+    for (it = 1; it <= i__1; ++it) {
+	wi = w[it];
+	yi = y[it] * wi;
+	fpgivs_(&wi, &d1, &cos__, &sin__);
+	fprota_(&cos__, &sin__, &yi, &c1);
+/* Computing 2nd power */
+	r__1 = yi;
+	fp0 += r__1 * r__1;
+/* L40: */
+    }
+    c1 /= d1;
+/*  test whether that constant function is a solution of our problem. */
+    fpms = fp0 - *s;
+    if (fpms < acc || nmax == nmin) {
+	goto L640;
+    }
+    fpold = fp0;
+/*  test whether the required storage space exceeds the available one. */
+    if (nmin >= *nest) {
+	goto L620;
+    }
+/*  start computing the least-squares periodic spline with one */
+/*  interior knot. */
+    nplus = 1;
+    *n = nmin + 1;
+    mm = (*m + 1) / 2;
+    t[*k2] = x[mm];
+    nrdata[1] = mm - 2;
+    nrdata[2] = m1 - mm;
+/*  main loop for the different sets of knots. m is a save upper */
+/*  bound for the number of trials. */
+L50:
+    i__1 = *m;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  find nrint, the number of knot intervals. */
+	nrint = *n - nmin + 1;
+/*  find the position of the additional knots which are needed for */
+/*  the b-spline representation of s(x). if we take */
+/*      t(k+1) = x(1), t(n-k) = x(m) */
+/*      t(k+1-j) = t(n-k-j) - per, j=1,2,...k */
+/*      t(n-k+j) = t(k+1+j) + per, j=1,2,...k */
+/*  then s(x) is a periodic spline with period per if the b-spline */
+/*  coefficients satisfy the following conditions */
+/*      c(n7+j) = c(j), j=1,...k   (**)   with n7=n-2*k-1. */
+	t[*k1] = x[1];
+	nk1 = *n - *k1;
+	nk2 = nk1 + 1;
+	t[nk2] = x[*m];
+	i__2 = *k;
+	for (j = 1; j <= i__2; ++j) {
+	    i1 = nk2 + j;
+	    i2 = nk2 - j;
+	    j1 = *k1 + j;
+	    j2 = *k1 - j;
+	    t[i1] = t[j1] + per;
+	    t[j2] = t[i2] - per;
+/* L60: */
+	}
+/*  compute the b-spline coefficients c(j),j=1,...n7 of the least-squares */
+/*  periodic spline sinf(x). the observation matrix a is built up row */
+/*  by row while taking into account condition (**) and is reduced to */
+/*  triangular form by givens transformations . */
+/*  at the same time fp=f(p=inf) is computed. */
+/*  the n7 x n7 triangularised upper matrix a has the form */
+/*            ! a1 '    ! */
+/*        a = !    ' a2 ! */
+/*            ! 0  '    ! */
+/*  with a2 a n7 x k matrix and a1 a n10 x n10 upper triangular */
+/*  matrix of bandwith k+1 ( n10 = n7-k). */
+/*  initialization. */
+	i__2 = nk1;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    z__[i__] = (float)0.;
+	    i__3 = kk1;
+	    for (j = 1; j <= i__3; ++j) {
+		a1[i__ + j * a1_dim1] = (float)0.;
+/* L70: */
+	    }
+	}
+	n7 = nk1 - *k;
+	n10 = n7 - kk;
+	jper = 0;
+	*fp = (float)0.;
+	l = *k1;
+	i__3 = m1;
+	for (it = 1; it <= i__3; ++it) {
+/*  fetch the current data point x(it),y(it) */
+	    xi = x[it];
+	    wi = w[it];
+	    yi = y[it] * wi;
+/*  search for knot interval t(l) <= xi < t(l+1). */
+L80:
+	    if (xi < t[l + 1]) {
+		goto L85;
+	    }
+	    ++l;
+	    goto L80;
+/*  evaluate the (k+1) non-zero b-splines at xi and store them in q. */
+L85:
+	    fpbspl_(&t[1], n, k, &xi, &l, h__);
+	    i__2 = *k1;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		q[it + i__ * q_dim1] = h__[i__ - 1];
+		h__[i__ - 1] *= wi;
+/* L90: */
+	    }
+	    l5 = l - *k1;
+/*  test whether the b-splines nj,k+1(x),j=1+n7,...nk1 are all zero at xi */
+	    if (l5 < n10) {
+		goto L285;
+	    }
+	    if (jper != 0) {
+		goto L160;
+	    }
+/*  initialize the matrix a2. */
+	    i__2 = n7;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		i__4 = kk;
+		for (j = 1; j <= i__4; ++j) {
+		    a2[i__ + j * a2_dim1] = (float)0.;
+/* L95: */
+		}
+	    }
+	    jk = n10 + 1;
+	    i__4 = kk;
+	    for (i__ = 1; i__ <= i__4; ++i__) {
+		ik = jk;
+		i__2 = kk1;
+		for (j = 1; j <= i__2; ++j) {
+		    if (ik <= 0) {
+			goto L105;
+		    }
+		    a2[ik + i__ * a2_dim1] = a1[ik + j * a1_dim1];
+		    --ik;
+/* L100: */
+		}
+L105:
+		++jk;
+/* L110: */
+	    }
+	    jper = 1;
+/*  if one of the b-splines nj,k+1(x),j=n7+1,...nk1 is not zero at xi */
+/*  we take account of condition (**) for setting up the new row */
+/*  of the observation matrix a. this row is stored in the arrays h1 */
+/*  (the part with respect to a1) and h2 (the part with */
+/*  respect to a2). */
+L160:
+	    i__4 = kk;
+	    for (i__ = 1; i__ <= i__4; ++i__) {
+		h1[i__ - 1] = (float)0.;
+		h2[i__ - 1] = (float)0.;
+/* L170: */
+	    }
+	    h1[kk1 - 1] = (float)0.;
+	    j = l5 - n10;
+	    i__4 = kk1;
+	    for (i__ = 1; i__ <= i__4; ++i__) {
+		++j;
+		l0 = j;
+L180:
+		l1 = l0 - kk;
+		if (l1 <= 0) {
+		    goto L200;
+		}
+		if (l1 <= n10) {
+		    goto L190;
+		}
+		l0 = l1 - n10;
+		goto L180;
+L190:
+		h1[l1 - 1] = h__[i__ - 1];
+		goto L210;
+L200:
+		h2[l0 - 1] += h__[i__ - 1];
+L210:
+		;
+	    }
+/*  rotate the new row of the observation matrix into triangle */
+/*  by givens transformations. */
+	    if (n10 <= 0) {
+		goto L250;
+	    }
+/*  rotation with the rows 1,2,...n10 of matrix a. */
+	    i__4 = n10;
+	    for (j = 1; j <= i__4; ++j) {
+		piv = h1[0];
+		if (piv != (float)0.) {
+		    goto L214;
+		}
+		i__2 = kk;
+		for (i__ = 1; i__ <= i__2; ++i__) {
+		    h1[i__ - 1] = h1[i__];
+/* L212: */
+		}
+		h1[kk1 - 1] = (float)0.;
+		goto L240;
+/*  calculate the parameters of the givens transformation. */
+L214:
+		fpgivs_(&piv, &a1[j + a1_dim1], &cos__, &sin__);
+/*  transformation to the right hand side. */
+		fprota_(&cos__, &sin__, &yi, &z__[j]);
+/*  transformations to the left hand side with respect to a2. */
+		i__2 = kk;
+		for (i__ = 1; i__ <= i__2; ++i__) {
+		    fprota_(&cos__, &sin__, &h2[i__ - 1], &a2[j + i__ * 
+			    a2_dim1]);
+/* L220: */
+		}
+		if (j == n10) {
+		    goto L250;
+		}
+/* Computing MIN */
+		i__2 = n10 - j;
+		i2 = min(i__2,kk);
+/*  transformations to the left hand side with respect to a1. */
+		i__2 = i2;
+		for (i__ = 1; i__ <= i__2; ++i__) {
+		    i1 = i__ + 1;
+		    fprota_(&cos__, &sin__, &h1[i1 - 1], &a1[j + i1 * a1_dim1]
+			    );
+		    h1[i__ - 1] = h1[i1 - 1];
+/* L230: */
+		}
+		h1[i1 - 1] = (float)0.;
+L240:
+		;
+	    }
+/*  rotation with the rows n10+1,...n7 of matrix a. */
+L250:
+	    i__4 = kk;
+	    for (j = 1; j <= i__4; ++j) {
+		ij = n10 + j;
+		if (ij <= 0) {
+		    goto L270;
+		}
+		piv = h2[j - 1];
+		if (piv == (float)0.) {
+		    goto L270;
+		}
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &a2[ij + j * a2_dim1], &cos__, &sin__);
+/*  transformations to right hand side. */
+		fprota_(&cos__, &sin__, &yi, &z__[ij]);
+		if (j == kk) {
+		    goto L280;
+		}
+		j1 = j + 1;
+/*  transformations to left hand side. */
+		i__2 = kk;
+		for (i__ = j1; i__ <= i__2; ++i__) {
+		    fprota_(&cos__, &sin__, &h2[i__ - 1], &a2[ij + i__ * 
+			    a2_dim1]);
+/* L260: */
+		}
+L270:
+		;
+	    }
+/*  add contribution of this row to the sum of squares of residual */
+/*  right hand sides. */
+L280:
+/* Computing 2nd power */
+	    r__1 = yi;
+	    *fp += r__1 * r__1;
+	    goto L290;
+/*  rotation of the new row of the observation matrix into */
+/*  triangle in case the b-splines nj,k+1(x),j=n7+1,...n-k-1 are all zero */
+/*  at xi. */
+L285:
+	    j = l5;
+	    i__4 = kk1;
+	    for (i__ = 1; i__ <= i__4; ++i__) {
+		++j;
+		piv = h__[i__ - 1];
+		if (piv == (float)0.) {
+		    goto L140;
+		}
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &a1[j + a1_dim1], &cos__, &sin__);
+/*  transformations to right hand side. */
+		fprota_(&cos__, &sin__, &yi, &z__[j]);
+		if (i__ == kk1) {
+		    goto L150;
+		}
+		i2 = 1;
+		i3 = i__ + 1;
+/*  transformations to left hand side. */
+		i__2 = kk1;
+		for (i1 = i3; i1 <= i__2; ++i1) {
+		    ++i2;
+		    fprota_(&cos__, &sin__, &h__[i1 - 1], &a1[j + i2 * 
+			    a1_dim1]);
+/* L130: */
+		}
+L140:
+		;
+	    }
+/*  add contribution of this row to the sum of squares of residual */
+/*  right hand sides. */
+L150:
+/* Computing 2nd power */
+	    r__1 = yi;
+	    *fp += r__1 * r__1;
+L290:
+	    ;
+	}
+	fpint[*n] = fp0;
+	fpint[*n - 1] = fpold;
+	nrdata[*n] = nplus;
+/*  backward substitution to obtain the b-spline coefficients c(j),j=1,.n */
+	fpbacp_(&a1[a1_offset], &a2[a2_offset], &z__[1], &n7, &kk, &c__[1], &
+		kk1, nest);
+/*  calculate from condition (**) the coefficients c(j+n7),j=1,2,...k. */
+	i__3 = *k;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    j = i__ + n7;
+	    c__[j] = c__[i__];
+/* L295: */
+	}
+	if (*iopt < 0) {
+	    goto L660;
+	}
+/*  test whether the approximation sinf(x) is an acceptable solution. */
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L660;
+	}
+/*  if f(p=inf) < s accept the choice of knots. */
+	if (fpms < (float)0.) {
+	    goto L350;
+	}
+/*  if n=nmax, sinf(x) is an interpolating spline. */
+	if (*n == nmax) {
+	    goto L630;
+	}
+/*  increase the number of knots. */
+/*  if n=nest we cannot increase the number of knots because of the */
+/*  storage capacity limitation. */
+	if (*n == *nest) {
+	    goto L620;
+	}
+/*  determine the number of knots nplus we are going to add. */
+	npl1 = nplus << 1;
+	rn = (real) nplus;
+	if (fpold - *fp > acc) {
+	    npl1 = rn * fpms / (fpold - *fp);
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__2 = npl1, i__5 = nplus / 2, i__2 = max(i__2,i__5);
+	i__3 = nplus << 1, i__4 = max(i__2,1);
+	nplus = min(i__3,i__4);
+	fpold = *fp;
+/*  compute the sum(wi*(yi-s(xi))**2) for each knot interval */
+/*  t(j+k) <= xi <= t(j+k+1) and store it in fpint(j),j=1,2,...nrint. */
+	fpart = (float)0.;
+	i__ = 1;
+	l = *k1;
+	i__3 = m1;
+	for (it = 1; it <= i__3; ++it) {
+	    if (x[it] < t[l]) {
+		goto L300;
+	    }
+	    new__ = 1;
+	    ++l;
+L300:
+	    term = (float)0.;
+	    l0 = l - *k2;
+	    i__4 = *k1;
+	    for (j = 1; j <= i__4; ++j) {
+		++l0;
+		term += c__[l0] * q[it + j * q_dim1];
+/* L310: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[it] * (term - y[it]);
+	    term = r__1 * r__1;
+	    fpart += term;
+	    if (new__ == 0) {
+		goto L320;
+	    }
+	    if (l > *k2) {
+		goto L315;
+	    }
+	    fpint[nrint] = term;
+	    new__ = 0;
+	    goto L320;
+L315:
+	    store = term * half;
+	    fpint[i__] = fpart - store;
+	    ++i__;
+	    fpart = store;
+	    new__ = 0;
+L320:
+	    ;
+	}
+	fpint[nrint] += fpart;
+	i__3 = nplus;
+	for (l = 1; l <= i__3; ++l) {
+/*  add a new knot */
+	    fpknot_(&x[1], m, &t[1], n, &fpint[1], &nrdata[1], &nrint, nest, &
+		    c__1);
+/*  if n=nmax we locate the knots as for interpolation. */
+	    if (*n == nmax) {
+		goto L5;
+	    }
+/*  test whether we cannot further increase the number of knots. */
+	    if (*n == *nest) {
+		goto L340;
+	    }
+/* L330: */
+	}
+/*  restart the computations with the new set of knots. */
+L340:
+	;
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  part 2: determination of the smoothing periodic spline sp(x).       c */
+/*  *************************************************************       c */
+/*  we have determined the number of knots and their position.          c */
+/*  we now compute the b-spline coefficients of the smoothing spline    c */
+/*  sp(x). the observation matrix a is extended by the rows of matrix   c */
+/*  b expressing that the kth derivative discontinuities of sp(x) at    c */
+/*  the interior knots t(k+2),...t(n-k-1) must be zero. the corres-     c */
+/*  ponding weights of these additional rows are set to 1/sqrt(p).      c */
+/*  iteratively we then have to determine the value of p such that      c */
+/*  f(p)=sum(w(i)*(y(i)-sp(x(i)))**2) be = s. we already know that      c */
+/*  the least-squares constant function corresponds to p=0, and that    c */
+/*  the least-squares periodic spline corresponds to p=infinity. the    c */
+/*  iteration process which is proposed here, makes use of rational     c */
+/*  interpolation. since f(p) is a convex and strictly decreasing       c */
+/*  function of p, it can be approximated by a rational function        c */
+/*  r(p) = (u*p+v)/(p+w). three values of p(p1,p2,p3) with correspond-  c */
+/*  ing values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used      c */
+/*  to calculate the new value of p such that r(p)=s. convergence is    c */
+/*  guaranteed by taking f1>0 and f3<0.                                 c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  evaluate the discontinuity jump of the kth derivative of the */
+/*  b-splines at the knots t(l),l=k+2,...n-k-1 and store in b. */
+L350:
+    fpdisc_(&t[1], n, k2, &b[b_offset], nest);
+/*  initial value for p. */
+    p1 = (float)0.;
+    f1 = fp0 - *s;
+    p3 = -one;
+    f3 = fpms;
+    n11 = n10 - 1;
+    n8 = n7 - 1;
+    p = (float)0.;
+    l = n7;
+    i__1 = *k;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	j = *k + 1 - i__;
+	p += a2[l + j * a2_dim1];
+	--l;
+	if (l == 0) {
+	    goto L356;
+	}
+/* L352: */
+    }
+    i__1 = n10;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	p += a1[i__ + a1_dim1];
+/* L354: */
+    }
+L356:
+    rn = (real) n7;
+    p = rn / p;
+    ich1 = 0;
+    ich3 = 0;
+/*  iteration process to find the root of f(p) = s. */
+    i__1 = *maxit;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  form the matrix g  as the matrix a extended by the rows of matrix b. */
+/*  the rows of matrix b with weight 1/p are rotated into */
+/*  the triangularised observation matrix a. */
+/*  after triangularisation our n7 x n7 matrix g takes the form */
+/*            ! g1 '    ! */
+/*        g = !    ' g2 ! */
+/*            ! 0  '    ! */
+/*  with g2 a n7 x (k+1) matrix and g1 a n11 x n11 upper triangular */
+/*  matrix of bandwidth k+2. ( n11 = n7-k-1) */
+	pinv = one / p;
+/*  store matrix a into g */
+	i__3 = n7;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    c__[i__] = z__[i__];
+	    g1[i__ + *k1 * g1_dim1] = a1[i__ + *k1 * a1_dim1];
+	    g1[i__ + *k2 * g1_dim1] = (float)0.;
+	    g2[i__ + g2_dim1] = (float)0.;
+	    i__4 = *k;
+	    for (j = 1; j <= i__4; ++j) {
+		g1[i__ + j * g1_dim1] = a1[i__ + j * a1_dim1];
+		g2[i__ + (j + 1) * g2_dim1] = a2[i__ + j * a2_dim1];
+/* L360: */
+	    }
+	}
+	l = n10;
+	i__4 = *k1;
+	for (j = 1; j <= i__4; ++j) {
+	    if (l <= 0) {
+		goto L375;
+	    }
+	    g2[l + g2_dim1] = a1[l + j * a1_dim1];
+	    --l;
+/* L370: */
+	}
+L375:
+	i__4 = n8;
+	for (it = 1; it <= i__4; ++it) {
+/*  fetch a new row of matrix b and store it in the arrays h1 (the part */
+/*  with respect to g1) and h2 (the part with respect to g2). */
+	    yi = (float)0.;
+	    i__3 = *k1;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		h1[i__ - 1] = (float)0.;
+		h2[i__ - 1] = (float)0.;
+/* L380: */
+	    }
+	    h1[*k2 - 1] = (float)0.;
+	    if (it > n11) {
+		goto L420;
+	    }
+	    l = it;
+	    l0 = it;
+	    i__3 = *k2;
+	    for (j = 1; j <= i__3; ++j) {
+		if (l0 == n10) {
+		    goto L400;
+		}
+		h1[j - 1] = b[it + j * b_dim1] * pinv;
+		++l0;
+/* L390: */
+	    }
+	    goto L470;
+L400:
+	    l0 = 1;
+	    i__3 = *k2;
+	    for (l1 = j; l1 <= i__3; ++l1) {
+		h2[l0 - 1] = b[it + l1 * b_dim1] * pinv;
+		++l0;
+/* L410: */
+	    }
+	    goto L470;
+L420:
+	    l = 1;
+	    i__ = it - n10;
+	    i__3 = *k2;
+	    for (j = 1; j <= i__3; ++j) {
+		++i__;
+		l0 = i__;
+L430:
+		l1 = l0 - *k1;
+		if (l1 <= 0) {
+		    goto L450;
+		}
+		if (l1 <= n11) {
+		    goto L440;
+		}
+		l0 = l1 - n11;
+		goto L430;
+L440:
+		h1[l1 - 1] = b[it + j * b_dim1] * pinv;
+		goto L460;
+L450:
+		h2[l0 - 1] += b[it + j * b_dim1] * pinv;
+L460:
+		;
+	    }
+	    if (n11 <= 0) {
+		goto L510;
+	    }
+/*  rotate this row into triangle by givens transformations without */
+/*  square roots. */
+/*  rotation with the rows l,l+1,...n11. */
+L470:
+	    i__3 = n11;
+	    for (j = l; j <= i__3; ++j) {
+		piv = h1[0];
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &g1[j + g1_dim1], &cos__, &sin__);
+/*  transformation to right hand side. */
+		fprota_(&cos__, &sin__, &yi, &c__[j]);
+/*  transformation to the left hand side with respect to g2. */
+		i__2 = *k1;
+		for (i__ = 1; i__ <= i__2; ++i__) {
+		    fprota_(&cos__, &sin__, &h2[i__ - 1], &g2[j + i__ * 
+			    g2_dim1]);
+/* L480: */
+		}
+		if (j == n11) {
+		    goto L510;
+		}
+/* Computing MIN */
+		i__2 = n11 - j;
+		i2 = min(i__2,*k1);
+/*  transformation to the left hand side with respect to g1. */
+		i__2 = i2;
+		for (i__ = 1; i__ <= i__2; ++i__) {
+		    i1 = i__ + 1;
+		    fprota_(&cos__, &sin__, &h1[i1 - 1], &g1[j + i1 * g1_dim1]
+			    );
+		    h1[i__ - 1] = h1[i1 - 1];
+/* L490: */
+		}
+		h1[i1 - 1] = (float)0.;
+/* L500: */
+	    }
+/*  rotation with the rows n11+1,...n7 */
+L510:
+	    i__3 = *k1;
+	    for (j = 1; j <= i__3; ++j) {
+		ij = n11 + j;
+		if (ij <= 0) {
+		    goto L530;
+		}
+		piv = h2[j - 1];
+/*  calculate the parameters of the givens transformation */
+		fpgivs_(&piv, &g2[ij + j * g2_dim1], &cos__, &sin__);
+/*  transformation to the right hand side. */
+		fprota_(&cos__, &sin__, &yi, &c__[ij]);
+		if (j == *k1) {
+		    goto L540;
+		}
+		j1 = j + 1;
+/*  transformation to the left hand side. */
+		i__2 = *k1;
+		for (i__ = j1; i__ <= i__2; ++i__) {
+		    fprota_(&cos__, &sin__, &h2[i__ - 1], &g2[ij + i__ * 
+			    g2_dim1]);
+/* L520: */
+		}
+L530:
+		;
+	    }
+L540:
+	    ;
+	}
+/*  backward substitution to obtain the b-spline coefficients */
+/*  c(j),j=1,2,...n7 of sp(x). */
+	fpbacp_(&g1[g1_offset], &g2[g2_offset], &c__[1], &n7, k1, &c__[1], k2,
+		 nest);
+/*  calculate from condition (**) the b-spline coefficients c(n7+j),j=1,. */
+	i__4 = *k;
+	for (i__ = 1; i__ <= i__4; ++i__) {
+	    j = i__ + n7;
+	    c__[j] = c__[i__];
+/* L545: */
+	}
+/*  computation of f(p). */
+	*fp = (float)0.;
+	l = *k1;
+	i__4 = m1;
+	for (it = 1; it <= i__4; ++it) {
+	    if (x[it] < t[l]) {
+		goto L550;
+	    }
+	    ++l;
+L550:
+	    l0 = l - *k2;
+	    term = (float)0.;
+	    i__3 = *k1;
+	    for (j = 1; j <= i__3; ++j) {
+		++l0;
+		term += c__[l0] * q[it + j * q_dim1];
+/* L560: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[it] * (term - y[it]);
+	    *fp += r__1 * r__1;
+/* L570: */
+	}
+/*  test whether the approximation sp(x) is an acceptable solution. */
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L660;
+	}
+/*  test whether the maximal number of iterations is reached. */
+	if (iter == *maxit) {
+	    goto L600;
+	}
+/*  carry out one more step of the iteration process. */
+	p2 = p;
+	f2 = fpms;
+	if (ich3 != 0) {
+	    goto L580;
+	}
+	if (f2 - f3 > acc) {
+	    goto L575;
+	}
+/*  our initial choice of p is too large. */
+	p3 = p2;
+	f3 = f2;
+	p *= con4;
+	if (p <= p1) {
+	    p = p1 * con9 + p2 * con1;
+	}
+	goto L595;
+L575:
+	if (f2 < (float)0.) {
+	    ich3 = 1;
+	}
+L580:
+	if (ich1 != 0) {
+	    goto L590;
+	}
+	if (f1 - f2 > acc) {
+	    goto L585;
+	}
+/*  our initial choice of p is too small */
+	p1 = p2;
+	f1 = f2;
+	p /= con4;
+	if (p3 < (float)0.) {
+	    goto L595;
+	}
+	if (p >= p3) {
+	    p = p2 * con1 + p3 * con9;
+	}
+	goto L595;
+L585:
+	if (f2 > (float)0.) {
+	    ich1 = 1;
+	}
+/*  test whether the iteration process proceeds as theoretically */
+/*  expected. */
+L590:
+	if (f2 >= f1 || f2 <= f3) {
+	    goto L610;
+	}
+/*  find the new value for p. */
+	p = fprati_(&p1, &f1, &p2, &f2, &p3, &f3);
+L595:
+	;
+    }
+/*  error codes and messages. */
+L600:
+    *ier = 3;
+    goto L660;
+L610:
+    *ier = 2;
+    goto L660;
+L620:
+    *ier = 1;
+    goto L660;
+L630:
+    *ier = -1;
+    goto L660;
+L640:
+    *ier = -2;
+/*  the least-squares constant function c1 is a solution of our problem. */
+/*  a constant function is a spline of degree k with all b-spline */
+/*  coefficients equal to that constant c1. */
+    i__1 = *k1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	rn = (real) (*k1 - i__);
+	t[i__] = x[1] - rn * per;
+	c__[i__] = c1;
+	j = i__ + *k1;
+	rn = (real) (i__ - 1);
+	t[j] = x[*m] + rn * per;
+/* L650: */
+    }
+    *n = nmin;
+    *fp = fp0;
+    fpint[*n] = fp0;
+    fpint[*n - 1] = (float)0.;
+    nrdata[*n] = 0;
+L660:
+    return 0;
+} /* fpperi_ */
+
+/* Subroutine */ int fppocu_(idim, k, a, b, ib, db, nb, ie, de, ne, cp, np)
+integer *idim, *k;
+real *a, *b;
+integer *ib;
+real *db;
+integer *nb, *ie;
+real *de;
+integer *ne;
+real *cp;
+integer *np;
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Local variables */
+    static real work[36]	/* was [6][6] */;
+    static integer i__, j, l, k1, k2;
+    static real ab;
+    static integer id, jj, ll;
+    static real aki;
+
+/*  subroutine fppocu finds a idim-dimensional polynomial curve p(u) = */
+/*  (p1(u),p2(u),...,pidim(u)) of degree k, satisfying certain derivative */
+/*  constraints at the end points a and b, i.e. */
+/*                  (l) */
+/*    if ib > 0 : pj   (a) = db(idim*l+j), l=0,1,...,ib-1 */
+/*                  (l) */
+/*    if ie > 0 : pj   (b) = de(idim*l+j), l=0,1,...,ie-1 */
+
+/*  the polynomial curve is returned in its b-spline representation */
+/*  ( coefficients cp(j), j=1,2,...,np ) */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local array.. */
+/*  .. */
+    /* Parameter adjustments */
+    --db;
+    --de;
+    --cp;
+
+    /* Function Body */
+    k1 = *k + 1;
+    k2 = k1 << 1;
+    ab = *b - *a;
+    i__1 = *idim;
+    for (id = 1; id <= i__1; ++id) {
+	i__2 = k1;
+	for (j = 1; j <= i__2; ++j) {
+	    work[j - 1] = (float)0.;
+/* L10: */
+	}
+	if (*ib == 0) {
+	    goto L50;
+	}
+	l = id;
+	i__2 = *ib;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    work[i__ * 6 - 6] = db[l];
+	    l += *idim;
+/* L20: */
+	}
+	if (*ib == 1) {
+	    goto L50;
+	}
+	ll = *ib;
+	i__2 = *ib;
+	for (j = 2; j <= i__2; ++j) {
+	    --ll;
+	    i__3 = ll;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		aki = (real) (k1 - i__);
+		work[j + i__ * 6 - 7] = ab * work[j - 1 + (i__ + 1) * 6 - 7] /
+			 aki + work[j - 1 + i__ * 6 - 7];
+/* L30: */
+	    }
+/* L40: */
+	}
+L50:
+	if (*ie == 0) {
+	    goto L90;
+	}
+	l = id;
+	j = k1;
+	i__2 = *ie;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    work[j + i__ * 6 - 7] = de[l];
+	    l += *idim;
+	    --j;
+/* L60: */
+	}
+	if (*ie == 1) {
+	    goto L90;
+	}
+	ll = *ie;
+	i__2 = *ie;
+	for (jj = 2; jj <= i__2; ++jj) {
+	    --ll;
+	    j = k1 + 1 - jj;
+	    i__3 = ll;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		aki = (real) (k1 - i__);
+		work[j + i__ * 6 - 7] = work[j + 1 + i__ * 6 - 7] - ab * work[
+			j + (i__ + 1) * 6 - 7] / aki;
+		--j;
+/* L70: */
+	    }
+/* L80: */
+	}
+L90:
+	l = (id - 1) * k2;
+	i__2 = k1;
+	for (j = 1; j <= i__2; ++j) {
+	    ++l;
+	    cp[l] = work[j - 1];
+/* L100: */
+	}
+/* L110: */
+    }
+    return 0;
+} /* fppocu_ */
+
+/* Subroutine */ int fppogr_(iopt, ider, u, mu, v, mv, z__, mz, z0, r__, s, 
+	nuest, nvest, tol, maxit, nc, nu, tu, nv, tv, c__, fp, fp0, fpold, 
+	reducu, reducv, fpintu, fpintv, dz, step, lastdi, nplusu, nplusv, 
+	lasttu, nru, nrv, nrdatu, nrdatv, wrk, lwrk, ier)
+integer *iopt, *ider;
+real *u;
+integer *mu;
+real *v;
+integer *mv;
+real *z__;
+integer *mz;
+real *z0, *r__, *s;
+integer *nuest, *nvest;
+real *tol;
+integer *maxit, *nc, *nu;
+real *tu;
+integer *nv;
+real *tv, *c__, *fp, *fp0, *fpold, *reducu, *reducv, *fpintu, *fpintv, *dz, *
+	step;
+integer *lastdi, *nplusu, *nplusv, *lasttu, *nru, *nrv, *nrdatu, *nrdatv;
+real *wrk;
+integer *lwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3, i__4, i__5;
+    real r__1;
+
+    /* Builtin functions */
+    double atan2();
+
+    /* Local variables */
+    static integer ifbu, ifbv, iter;
+    static real fpms;
+    static integer ifsu, ifsv;
+    static real zmin;
+    static integer nplu;
+    static real zmax;
+    static integer nplv, i__, j, l;
+    static real p;
+    static integer mumin;
+    static real f1, f2, f3;
+    static integer i1, i2, numax, l1, l2;
+    static real p1, p2, p3;
+    static integer l3, l4, nvmax;
+    static real vb, pi, ve;
+    static integer nn, ju;
+    static real rn;
+    extern /* Subroutine */ int fpopdi_();
+    extern doublereal fprati_();
+    extern /* Subroutine */ int fpknot_();
+    static integer istart, nrintu, nrintv, mu0, mu1;
+    static real acc;
+    static integer idd[2];
+    static real one, per;
+    static integer nue, nve, mpm, ktu;
+    static real dzz[3];
+    static integer ich1, ich3;
+    static real con1, con4, con9;
+    static integer npl1;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpknot,fpopdi */
+/*  .. */
+/*   set constants */
+    /* Parameter adjustments */
+    --iopt;
+    --ider;
+    --nru;
+    --u;
+    --nrv;
+    --v;
+    --z__;
+    --nrdatu;
+    --fpintu;
+    --tu;
+    --nrdatv;
+    --fpintv;
+    --tv;
+    --c__;
+    --dz;
+    --wrk;
+
+    /* Function Body */
+    one = (float)1.;
+    con1 = (float).1;
+    con9 = (float).9;
+    con4 = (float).04;
+/*   initialization */
+    ifsu = 0;
+    ifsv = 0;
+    ifbu = 0;
+    ifbv = 0;
+    p = -one;
+    mumin = 4 - iopt[3];
+    if (ider[1] >= 0) {
+	--mumin;
+    }
+    if (iopt[2] == 1 && ider[2] == 1) {
+	--mumin;
+    }
+    pi = atan2((float)0., -one);
+    per = pi + pi;
+    vb = v[1];
+    ve = vb + per;
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/* part 1: determination of the number of knots and their position.     c */
+/* ****************************************************************     c */
+/*  given a set of knots we compute the least-squares spline sinf(u,v)  c */
+/*  and the corresponding sum of squared residuals fp = f(p=inf).       c */
+/*  if iopt(1)=-1  sinf(u,v) is the requested approximation.            c */
+/*  if iopt(1)>=0  we check whether we can accept the knots:            c */
+/*    if fp <= s we will continue with the current set of knots.        c */
+/*    if fp >  s we will increase the number of knots and compute the   c */
+/*       corresponding least-squares spline until finally fp <= s.      c */
+/*    the initial choice of knots depends on the value of s and iopt.   c */
+/*    if s=0 we have spline interpolation; in that case the number of   c */
+/*     knots in the u-direction equals nu=numax=mu+5+iopt(2)+iopt(3)    c */
+/*     and in the v-direction nv=nvmax=mv+7.                            c */
+/*    if s>0 and                                                        c */
+/*      iopt(1)=0 we first compute the least-squares polynomial,i.e. a  c */
+/*       spline without interior knots : nu=8 ; nv=8.                   c */
+/*      iopt(1)=1 we start with the set of knots found at the last call c */
+/*       of the routine, except for the case that s > fp0; then we      c */
+/*       compute the least-squares polynomial directly.                 c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+    if (iopt[1] < 0) {
+	goto L120;
+    }
+/*  acc denotes the absolute tolerance for the root of f(p)=s. */
+    acc = *tol * *s;
+/*  numax and nvmax denote the number of knots needed for interpolation. */
+    numax = *mu + 5 + iopt[2] + iopt[3];
+    nvmax = *mv + 7;
+    nue = min(numax,*nuest);
+    nve = min(nvmax,*nvest);
+    if (*s > (float)0.) {
+	goto L100;
+    }
+/*  if s = 0, s(u,v) is an interpolating spline. */
+    *nu = numax;
+    *nv = nvmax;
+/*  test whether the required storage space exceeds the available one. */
+    if (*nu > *nuest || *nv > *nvest) {
+	goto L420;
+    }
+/*  find the position of the knots in the v-direction. */
+    i__1 = *mv;
+    for (l = 1; l <= i__1; ++l) {
+	tv[l + 3] = v[l];
+/* L10: */
+    }
+    tv[*mv + 4] = ve;
+    l1 = *mv - 2;
+    l2 = *mv + 5;
+    for (i__ = 1; i__ <= 3; ++i__) {
+	tv[i__] = v[l1] - per;
+	tv[l2] = v[i__ + 1] + per;
+	++l1;
+	++l2;
+/* L20: */
+    }
+/*  if not all the derivative values g(i,j) are given, we will first */
+/*  estimate these values by computing a least-squares spline */
+    idd[0] = ider[1];
+    if (idd[0] == 0) {
+	idd[0] = 1;
+    }
+    if (idd[0] > 0) {
+	dz[1] = *z0;
+    }
+    idd[1] = ider[2];
+    if (ider[1] < 0) {
+	goto L30;
+    }
+    if (iopt[2] == 0 || ider[2] != 0) {
+	goto L70;
+    }
+/* we set up the knots in the u-direction for computing the least-squares */
+/* spline. */
+L30:
+    i1 = 3;
+    i2 = *mu - 2;
+    *nu = 4;
+    i__1 = *mu;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (i1 > i2) {
+	    goto L50;
+	}
+	++(*nu);
+	tu[*nu] = u[i1];
+	i1 += 2;
+/* L40: */
+    }
+L50:
+    for (i__ = 1; i__ <= 4; ++i__) {
+	tu[i__] = (float)0.;
+	++(*nu);
+	tu[*nu] = *r__;
+/* L60: */
+    }
+/* we compute the least-squares spline for estimating the derivatives. */
+    fpopdi_(&ifsu, &ifsv, &ifbu, &ifbv, &u[1], mu, &v[1], mv, &z__[1], mz, z0,
+	     &dz[1], &iopt[1], idd, &tu[1], nu, &tv[1], nv, nuest, nvest, &p, 
+	    step, &c__[1], nc, fp, &fpintu[1], &fpintv[1], &nru[1], &nrv[1], &
+	    wrk[1], lwrk);
+    ifsu = 0;
+/* if all the derivatives at the origin are known, we compute the */
+/* interpolating spline. */
+/* we set up the knots in the u-direction, needed for interpolation. */
+L70:
+    nn = numax - 8;
+    if (nn == 0) {
+	goto L95;
+    }
+    ju = 2 - iopt[2];
+    i__1 = nn;
+    for (l = 1; l <= i__1; ++l) {
+	tu[l + 4] = u[ju];
+	++ju;
+/* L80: */
+    }
+    *nu = numax;
+    l = *nu;
+    for (i__ = 1; i__ <= 4; ++i__) {
+	tu[i__] = (float)0.;
+	tu[l] = *r__;
+	--l;
+/* L90: */
+    }
+/* we compute the interpolating spline. */
+L95:
+    fpopdi_(&ifsu, &ifsv, &ifbu, &ifbv, &u[1], mu, &v[1], mv, &z__[1], mz, z0,
+	     &dz[1], &iopt[1], idd, &tu[1], nu, &tv[1], nv, nuest, nvest, &p, 
+	    step, &c__[1], nc, fp, &fpintu[1], &fpintv[1], &nru[1], &nrv[1], &
+	    wrk[1], lwrk);
+    goto L430;
+/*  if s>0 our initial choice of knots depends on the value of iopt(1). */
+L100:
+    *ier = 0;
+    if (iopt[1] == 0) {
+	goto L115;
+    }
+    *step = -(*step);
+    if (*fp0 <= *s) {
+	goto L115;
+    }
+/*  if iopt(1)=1 and fp0 > s we start computing the least-squares spline */
+/*  according to the set of knots found at the last call of the routine. */
+/*  we determine the number of grid coordinates u(i) inside each knot */
+/*  interval (tu(l),tu(l+1)). */
+    l = 5;
+    j = 1;
+    nrdatu[1] = 0;
+    mu0 = 2 - iopt[2];
+    mu1 = *mu - 2 + iopt[3];
+    i__1 = mu1;
+    for (i__ = mu0; i__ <= i__1; ++i__) {
+	++nrdatu[j];
+	if (u[i__] < tu[l]) {
+	    goto L105;
+	}
+	--nrdatu[j];
+	++l;
+	++j;
+	nrdatu[j] = 0;
+L105:
+	;
+    }
+/*  we determine the number of grid coordinates v(i) inside each knot */
+/*  interval (tv(l),tv(l+1)). */
+    l = 5;
+    j = 1;
+    nrdatv[1] = 0;
+    i__1 = *mv;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	++nrdatv[j];
+	if (v[i__] < tv[l]) {
+	    goto L110;
+	}
+	--nrdatv[j];
+	++l;
+	++j;
+	nrdatv[j] = 0;
+L110:
+	;
+    }
+    idd[0] = ider[1];
+    idd[1] = ider[2];
+    goto L120;
+/*  if iopt(1)=0 or iopt(1)=1 and s >= fp0,we start computing the least- */
+/*  squares polynomial (which is a spline without interior knots). */
+L115:
+    *ier = -2;
+    idd[0] = ider[1];
+    idd[1] = 1;
+    *nu = 8;
+    *nv = 8;
+    nrdatu[1] = *mu - 3 + iopt[2] + iopt[3];
+    nrdatv[1] = *mv - 1;
+    *lastdi = 0;
+    *nplusu = 0;
+    *nplusv = 0;
+    *fp0 = (float)0.;
+    *fpold = (float)0.;
+    *reducu = (float)0.;
+    *reducv = (float)0.;
+/*  main loop for the different sets of knots.mpm=mu+mv is a save upper */
+/*  bound for the number of trials. */
+L120:
+    mpm = *mu + *mv;
+    i__1 = mpm;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  find nrintu (nrintv) which is the number of knot intervals in the */
+/*  u-direction (v-direction). */
+	nrintu = *nu - 7;
+	nrintv = *nv - 7;
+/*  find the position of the additional knots which are needed for the */
+/*  b-spline representation of s(u,v). */
+	i__ = *nu;
+	for (j = 1; j <= 4; ++j) {
+	    tu[j] = (float)0.;
+	    tu[i__] = *r__;
+	    --i__;
+/* L130: */
+	}
+	l1 = 4;
+	l2 = l1;
+	l3 = *nv - 3;
+	l4 = l3;
+	tv[l2] = vb;
+	tv[l3] = ve;
+	for (j = 1; j <= 3; ++j) {
+	    ++l1;
+	    --l2;
+	    ++l3;
+	    --l4;
+	    tv[l2] = tv[l4] - per;
+	    tv[l3] = tv[l1] + per;
+/* L140: */
+	}
+/*  find an estimate of the range of possible values for the optimal */
+/*  derivatives at the origin. */
+	ktu = nrdatu[1] + 2 - iopt[2];
+	if (nrintu == 1) {
+	    ktu = *mu;
+	}
+	if (ktu < mumin) {
+	    ktu = mumin;
+	}
+	if (ktu == *lasttu) {
+	    goto L150;
+	}
+	zmin = *z0;
+	zmax = *z0;
+	l = *mv * ktu;
+	i__2 = l;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    if (z__[i__] < zmin) {
+		zmin = z__[i__];
+	    }
+	    if (z__[i__] > zmax) {
+		zmax = z__[i__];
+	    }
+/* L145: */
+	}
+	*step = zmax - zmin;
+	*lasttu = ktu;
+/*  find the least-squares spline sinf(u,v). */
+L150:
+	fpopdi_(&ifsu, &ifsv, &ifbu, &ifbv, &u[1], mu, &v[1], mv, &z__[1], mz,
+		 z0, &dz[1], &iopt[1], idd, &tu[1], nu, &tv[1], nv, nuest, 
+		nvest, &p, step, &c__[1], nc, fp, &fpintu[1], &fpintv[1], &
+		nru[1], &nrv[1], &wrk[1], lwrk);
+	if (*step < (float)0.) {
+	    *step = -(*step);
+	}
+	if (*ier == -2) {
+	    *fp0 = *fp;
+	}
+/*  test whether the least-squares spline is an acceptable solution. */
+	if (iopt[1] < 0) {
+	    goto L440;
+	}
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  if f(p=inf) < s, we accept the choice of knots. */
+	if (fpms < (float)0.) {
+	    goto L300;
+	}
+/*  if nu=numax and nv=nvmax, sinf(u,v) is an interpolating spline */
+	if (*nu == numax && *nv == nvmax) {
+	    goto L430;
+	}
+/*  increase the number of knots. */
+/*  if nu=nue and nv=nve we cannot further increase the number of knots */
+/*  because of the storage capacity limitation. */
+	if (*nu == nue && *nv == nve) {
+	    goto L420;
+	}
+	if (ider[1] == 0) {
+/* Computing 2nd power */
+	    r__1 = *z0 - c__[1];
+	    fpintu[1] += r__1 * r__1;
+	}
+	*ier = 0;
+/*  adjust the parameter reducu or reducv according to the direction */
+/*  in which the last added knots were located. */
+	if (*lastdi < 0) {
+	    goto L160;
+	} else if (*lastdi == 0) {
+	    goto L155;
+	} else {
+	    goto L170;
+	}
+L155:
+	nplv = 3;
+	idd[1] = ider[2];
+	*fpold = *fp;
+	goto L230;
+L160:
+	*reducu = *fpold - *fp;
+	goto L175;
+L170:
+	*reducv = *fpold - *fp;
+/*  store the sum of squared residuals for the current set of knots. */
+L175:
+	*fpold = *fp;
+/*  find nplu, the number of knots we should add in the u-direction. */
+	nplu = 1;
+	if (*nu == 8) {
+	    goto L180;
+	}
+	npl1 = *nplusu << 1;
+	rn = (real) (*nplusu);
+	if (*reducu > acc) {
+	    npl1 = rn * fpms / *reducu;
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__4 = npl1, i__5 = *nplusu / 2, i__4 = max(i__4,i__5);
+	i__2 = *nplusu << 1, i__3 = max(i__4,1);
+	nplu = min(i__2,i__3);
+/*  find nplv, the number of knots we should add in the v-direction. */
+L180:
+	nplv = 3;
+	if (*nv == 8) {
+	    goto L190;
+	}
+	npl1 = *nplusv << 1;
+	rn = (real) (*nplusv);
+	if (*reducv > acc) {
+	    npl1 = rn * fpms / *reducv;
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__4 = npl1, i__5 = *nplusv / 2, i__4 = max(i__4,i__5);
+	i__2 = *nplusv << 1, i__3 = max(i__4,1);
+	nplv = min(i__2,i__3);
+/*  test whether we are going to add knots in the u- or v-direction. */
+L190:
+	if ((i__2 = nplu - nplv) < 0) {
+	    goto L210;
+	} else if (i__2 == 0) {
+	    goto L200;
+	} else {
+	    goto L230;
+	}
+L200:
+	if (*lastdi < 0) {
+	    goto L230;
+	}
+L210:
+	if (*nu == nue) {
+	    goto L230;
+	}
+/*  addition in the u-direction. */
+	*lastdi = -1;
+	*nplusu = nplu;
+	ifsu = 0;
+	istart = 0;
+	if (iopt[2] == 0) {
+	    istart = 1;
+	}
+	i__2 = *nplusu;
+	for (l = 1; l <= i__2; ++l) {
+/*  add a new knot in the u-direction */
+	    fpknot_(&u[1], mu, &tu[1], nu, &fpintu[1], &nrdatu[1], &nrintu, 
+		    nuest, &istart);
+/*  test whether we cannot further increase the number of knots in the */
+/*  u-direction. */
+	    if (*nu == nue) {
+		goto L270;
+	    }
+/* L220: */
+	}
+	goto L270;
+L230:
+	if (*nv == nve) {
+	    goto L210;
+	}
+/*  addition in the v-direction. */
+	*lastdi = 1;
+	*nplusv = nplv;
+	ifsv = 0;
+	i__2 = *nplusv;
+	for (l = 1; l <= i__2; ++l) {
+/*  add a new knot in the v-direction. */
+	    fpknot_(&v[1], mv, &tv[1], nv, &fpintv[1], &nrdatv[1], &nrintv, 
+		    nvest, &c__1);
+/*  test whether we cannot further increase the number of knots in the */
+/*  v-direction. */
+	    if (*nv == nve) {
+		goto L270;
+	    }
+/* L240: */
+	}
+/*  restart the computations with the new set of knots. */
+L270:
+	;
+    }
+/*  test whether the least-squares polynomial is a solution of our */
+/*  approximation problem. */
+L300:
+    if (*ier == -2) {
+	goto L440;
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/* part 2: determination of the smoothing spline sp(u,v)                c */
+/* *****************************************************                c */
+/*  we have determined the number of knots and their position. we now   c */
+/*  compute the b-spline coefficients of the smoothing spline sp(u,v).  c */
+/*  this smoothing spline depends on the parameter p in such a way that c */
+/*    f(p) = sumi=1,mu(sumj=1,mv((z(i,j)-sp(u(i),v(j)))**2)             c */
+/*  is a continuous, strictly decreasing function of p. moreover the    c */
+/*  least-squares polynomial corresponds to p=0 and the least-squares   c */
+/*  spline to p=infinity. then iteratively we have to determine the     c */
+/*  positive value of p such that f(p)=s. the process which is proposed c */
+/*  here makes use of rational interpolation. f(p) is approximated by a c */
+/*  rational function r(p)=(u*p+v)/(p+w); three values of p (p1,p2,p3)  c */
+/*  with corresponding values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s)c */
+/*  are used to calculate the new value of p such that r(p)=s.          c */
+/*  convergence is guaranteed by taking f1 > 0 and f3 < 0.              c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  initial value for p. */
+    p1 = (float)0.;
+    f1 = *fp0 - *s;
+    p3 = -one;
+    f3 = fpms;
+    p = one;
+    dzz[0] = dz[1];
+    dzz[1] = dz[2];
+    dzz[2] = dz[3];
+    ich1 = 0;
+    ich3 = 0;
+/*  iteration process to find the root of f(p)=s. */
+    i__1 = *maxit;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  find the smoothing spline sp(u,v) and the corresponding sum f(p). */
+	fpopdi_(&ifsu, &ifsv, &ifbu, &ifbv, &u[1], mu, &v[1], mv, &z__[1], mz,
+		 z0, dzz, &iopt[1], idd, &tu[1], nu, &tv[1], nv, nuest, nvest,
+		 &p, step, &c__[1], nc, fp, &fpintu[1], &fpintv[1], &nru[1], &
+		nrv[1], &wrk[1], lwrk);
+/*  test whether the approximation sp(u,v) is an acceptable solution. */
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  test whether the maximum allowable number of iterations has been */
+/*  reached. */
+	if (iter == *maxit) {
+	    goto L400;
+	}
+/*  carry out one more step of the iteration process. */
+	p2 = p;
+	f2 = fpms;
+	if (ich3 != 0) {
+	    goto L320;
+	}
+	if (f2 - f3 > acc) {
+	    goto L310;
+	}
+/*  our initial choice of p is too large. */
+	p3 = p2;
+	f3 = f2;
+	p *= con4;
+	if (p <= p1) {
+	    p = p1 * con9 + p2 * con1;
+	}
+	goto L350;
+L310:
+	if (f2 < (float)0.) {
+	    ich3 = 1;
+	}
+L320:
+	if (ich1 != 0) {
+	    goto L340;
+	}
+	if (f1 - f2 > acc) {
+	    goto L330;
+	}
+/*  our initial choice of p is too small */
+	p1 = p2;
+	f1 = f2;
+	p /= con4;
+	if (p3 < (float)0.) {
+	    goto L350;
+	}
+	if (p >= p3) {
+	    p = p2 * con1 + p3 * con9;
+	}
+	goto L350;
+/*  test whether the iteration process proceeds as theoretically */
+/*  expected. */
+L330:
+	if (f2 > (float)0.) {
+	    ich1 = 1;
+	}
+L340:
+	if (f2 >= f1 || f2 <= f3) {
+	    goto L410;
+	}
+/*  find the new value of p. */
+	p = fprati_(&p1, &f1, &p2, &f2, &p3, &f3);
+L350:
+	;
+    }
+/*  error codes and messages. */
+L400:
+    *ier = 3;
+    goto L440;
+L410:
+    *ier = 2;
+    goto L440;
+L420:
+    *ier = 1;
+    goto L440;
+L430:
+    *ier = -1;
+    *fp = (float)0.;
+L440:
+    return 0;
+} /* fppogr_ */
+
+/* Subroutine */ int fppola_(iopt1, iopt2, iopt3, m, u, v, z__, w, rad, s, 
+	nuest, nvest, eta, tol, maxit, ib1, ib3, nc, ncc, intest, nrest, nu, 
+	tu, nv, tv, c__, fp, sup, fpint, coord, f, ff, row, cs, cosi, a, q, 
+	bu, bv, spu, spv, h__, index, nummer, wrk, lwrk, ier)
+integer *iopt1, *iopt2, *iopt3, *m;
+real *u, *v, *z__, *w;
+doublereal (*rad) ();
+real *s;
+integer *nuest, *nvest;
+real *eta, *tol;
+integer *maxit, *ib1, *ib3, *nc, *ncc, *intest, *nrest, *nu;
+real *tu;
+integer *nv;
+real *tv, *c__, *fp, *sup, *fpint, *coord, *f, *ff, *row, *cs, *cosi, *a, *q, 
+	*bu, *bv, *spu, *spv, *h__;
+integer *index, *nummer;
+real *wrk;
+integer *lwrk, *ier;
+{
+    /* System generated locals */
+    integer a_dim1, a_offset, q_dim1, q_offset, bu_dim1, bu_offset, bv_dim1, 
+	    bv_offset, spu_dim1, spu_offset, spv_dim1, spv_offset, i__1, i__2,
+	     i__3, i__4, i__5, i__6;
+    real r__1;
+
+    /* Builtin functions */
+    double atan(), sqrt(), cos(), sin();
+
+    /* Local variables */
+    static real half;
+    static integer ncof;
+    static real dmax__;
+    static integer ipar, nreg, rank, iter;
+    static real fpms, pinv;
+    static integer irot, jrot, ipar1, i__, j, k, l, iband;
+    static real p, r__;
+    static integer ncoff;
+    static real sigma, three, fpmax, ratio, c1, c2, c3, c4, f1, f2, f3, store;
+    static integer i1, iband3;
+    static real p1, p2, p3;
+    static integer iband4, i2, i3;
+    static real u2, u3;
+    static integer j1, j2, lwest, l1, l2, l3, l4, nrint, numin, nvmin, iband1,
+	     la;
+    static real co;
+    static integer ii, lf, il;
+    static real pi;
+    static integer in;
+    static real si;
+    static integer lh, ll;
+    static real wi, rn;
+    static integer lu;
+    static real sq, zi;
+    static integer lv;
+    static real hu[4], uu, hv[4];
+    extern /* Subroutine */ int fpback_(), fpdisc_(), fporde_(), fprank_();
+    extern doublereal fprati_();
+    extern /* Subroutine */ int fpbspl_(), fprota_(), fpgivs_(), fprppo_();
+    static real pi2;
+    static integer nr1, nu4, nv4;
+    static real acc, fac, arg, one, hui, huj, eps, ten;
+    static integer jlu;
+    static real piv;
+    static integer num, nrr;
+    static real fac1, fac2, two;
+    static integer nvv, nuu, ich1, ich3;
+    static real con1, con4, con9;
+    static integer num1;
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..user supplied function.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fporde,fpbspl,fpback,fpgivs,fprota,fprank,fpdisc,fprppo */
+/*  .. */
+/*  set constants */
+    /* Parameter adjustments */
+    --nummer;
+    spv_dim1 = *m;
+    spv_offset = 1 + spv_dim1 * 1;
+    spv -= spv_offset;
+    spu_dim1 = *m;
+    spu_offset = 1 + spu_dim1 * 1;
+    spu -= spu_offset;
+    --w;
+    --z__;
+    --v;
+    --u;
+    bu_dim1 = *nuest;
+    bu_offset = 1 + bu_dim1 * 1;
+    bu -= bu_offset;
+    --tu;
+    bv_dim1 = *nvest;
+    bv_offset = 1 + bv_dim1 * 1;
+    bv -= bv_offset;
+    cosi -= 6;
+    --cs;
+    --row;
+    --tv;
+    --h__;
+    --ff;
+    --c__;
+    q_dim1 = *ncc;
+    q_offset = 1 + q_dim1 * 1;
+    q -= q_offset;
+    a_dim1 = *ncc;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+    --f;
+    --coord;
+    --fpint;
+    --index;
+    --wrk;
+
+    /* Function Body */
+    one = (float)1.;
+    two = (float)2.;
+    three = (float)3.;
+    ten = (float)10.;
+    half = (float).5;
+    con1 = (float).1;
+    con9 = (float).9;
+    con4 = (float).04;
+    pi = atan(one) * 4;
+    pi2 = pi + pi;
+    ipar = *iopt2 * (*iopt2 + 3) / 2;
+    ipar1 = ipar + 1;
+    eps = sqrt(*eta);
+    if (*iopt1 < 0) {
+	goto L90;
+    }
+    numin = 9;
+    nvmin = *iopt2 * (*iopt2 + 1) + 9;
+/*  calculation of acc, the absolute tolerance for the root of f(p)=s. */
+    acc = *tol * *s;
+    if (*iopt1 == 0) {
+	goto L10;
+    }
+    if (*s < *sup) {
+	if (*nv - nvmin >= 0) {
+	    goto L90;
+	} else {
+	    goto L70;
+	}
+    }
+/*  if iopt1 = 0 we begin by computing the weighted least-squares */
+/*  polymomial of the form */
+/*     s(u,v) = f(1)*(1-u**3)+f(2)*u**3+f(3)*(u**2-u**3)+f(4)*(u-u**3) */
+/*  where f(4) = 0 if iopt2> 0 , f(3) = 0 if iopt2 > 1 and */
+/*        f(2) = 0 if iopt3> 0. */
+/*  the corresponding weighted sum of squared residuals gives the upper */
+/*  bound sup for the smoothing factor s. */
+L10:
+    *sup = (float)0.;
+    for (i__ = 1; i__ <= 4; ++i__) {
+	f[i__] = (float)0.;
+	for (j = 1; j <= 4; ++j) {
+	    a[i__ + j * a_dim1] = (float)0.;
+/* L20: */
+	}
+    }
+    i__1 = *m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	wi = w[i__];
+	zi = z__[i__] * wi;
+	uu = u[i__];
+	u2 = uu * uu;
+	u3 = uu * u2;
+	h__[1] = (one - u3) * wi;
+	h__[2] = u3 * wi;
+	h__[3] = u2 * (one - uu) * wi;
+	h__[4] = uu * (one - u2) * wi;
+	if (*iopt3 != 0) {
+	    h__[2] = (float)0.;
+	}
+	if (*iopt2 > 1) {
+	    h__[3] = (float)0.;
+	}
+	if (*iopt2 > 0) {
+	    h__[4] = (float)0.;
+	}
+	for (j = 1; j <= 4; ++j) {
+	    piv = h__[j];
+	    if (piv == (float)0.) {
+		goto L40;
+	    }
+	    fpgivs_(&piv, &a[j + a_dim1], &co, &si);
+	    fprota_(&co, &si, &zi, &f[j]);
+	    if (j == 4) {
+		goto L40;
+	    }
+	    j1 = j + 1;
+	    j2 = 1;
+	    for (l = j1; l <= 4; ++l) {
+		++j2;
+		fprota_(&co, &si, &h__[l], &a[j + j2 * a_dim1]);
+/* L30: */
+	    }
+L40:
+	    ;
+	}
+	*sup += zi * zi;
+/* L50: */
+    }
+    if (a[a_dim1 + 4] != (float)0.) {
+	f[4] /= a[a_dim1 + 4];
+    }
+    if (a[a_dim1 + 3] != (float)0.) {
+	f[3] = (f[3] - a[(a_dim1 << 1) + 3] * f[4]) / a[a_dim1 + 3];
+    }
+    if (a[a_dim1 + 2] != (float)0.) {
+	f[2] = (f[2] - a[(a_dim1 << 1) + 2] * f[3] - a[a_dim1 * 3 + 2] * f[4])
+		 / a[a_dim1 + 2];
+    }
+    if (a[a_dim1 + 1] != (float)0.) {
+	f[1] = (f[1] - a[(a_dim1 << 1) + 1] * f[2] - a[a_dim1 * 3 + 1] * f[3] 
+		- a[(a_dim1 << 2) + 1] * f[4]) / a[a_dim1 + 1];
+    }
+/*  find the b-spline representation of this least-squares polynomial */
+    c1 = f[1];
+    c4 = f[2];
+    c2 = f[4] / three + c1;
+    c3 = (f[3] + two * f[4]) / three + c1;
+    *nu = 8;
+    *nv = 8;
+    for (i__ = 1; i__ <= 4; ++i__) {
+	c__[i__] = c1;
+	c__[i__ + 4] = c2;
+	c__[i__ + 8] = c3;
+	c__[i__ + 12] = c4;
+	tu[i__] = (float)0.;
+	tu[i__ + 4] = one;
+	rn = (real) ((i__ << 1) - 9);
+	tv[i__] = rn * pi;
+	rn = (real) ((i__ << 1) - 1);
+	tv[i__ + 4] = rn * pi;
+/* L60: */
+    }
+    *fp = *sup;
+/*  test whether the least-squares polynomial is an acceptable solution */
+    fpms = *sup - *s;
+    if (fpms < acc) {
+	goto L960;
+    }
+/*  test whether we cannot further increase the number of knots. */
+L70:
+    if (*nuest < numin || *nvest < nvmin) {
+	goto L950;
+    }
+/*  find the initial set of interior knots of the spline in case iopt1=0. */
+    *nu = numin;
+    *nv = nvmin;
+    tu[5] = half;
+    nvv = *nv - 8;
+    rn = (real) (nvv + 1);
+    fac = pi2 / rn;
+    i__1 = nvv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	rn = (real) i__;
+	tv[i__ + 4] = rn * fac - pi;
+/* L80: */
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  part 1 : computation of least-squares bicubic splines.              c */
+/*  ******************************************************              c */
+/*  if iopt1<0 we compute the least-squares bicubic spline according    c */
+/*  to the given set of knots.                                          c */
+/*  if iopt1>=0 we compute least-squares bicubic splines with in-       c */
+/*  creasing numbers of knots until the corresponding sum f(p=inf)<=s.  c */
+/*  the initial set of knots then depends on the value of iopt1         c */
+/*    if iopt1=0 we start with one interior knot in the u-direction     c */
+/*              (0.5) and 1+iopt2*(iopt2+1) in the v-direction.         c */
+/*    if iopt1>0 we start with the set of knots found at the last       c */
+/*              call of the routine.                                    c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  main loop for the different sets of knots. m is a save upper bound */
+/*  for the number of trials. */
+L90:
+    i__1 = *m;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  find the position of the additional knots which are needed for the */
+/*  b-spline representation of s(u,v). */
+	l1 = 4;
+	l2 = l1;
+	l3 = *nv - 3;
+	l4 = l3;
+	tv[l2] = -pi;
+	tv[l3] = pi;
+	for (i__ = 1; i__ <= 3; ++i__) {
+	    ++l1;
+	    --l2;
+	    ++l3;
+	    --l4;
+	    tv[l2] = tv[l4] - pi2;
+	    tv[l3] = tv[l1] + pi2;
+/* L120: */
+	}
+	l = *nu;
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    tu[i__] = (float)0.;
+	    tu[l] = one;
+	    --l;
+/* L130: */
+	}
+/*  find nrint, the total number of knot intervals and nreg, the number */
+/*  of panels in which the approximation domain is subdivided by the */
+/*  intersection of knots. */
+	nuu = *nu - 7;
+	nvv = *nv - 7;
+	nrr = nvv / 2;
+	nr1 = nrr + 1;
+	nrint = nuu + nvv;
+	nreg = nuu * nvv;
+/*  arrange the data points according to the panel they belong to. */
+	fporde_(&u[1], &v[1], m, &c__3, &c__3, &tu[1], nu, &tv[1], nv, &
+		nummer[1], &index[1], &nreg);
+	if (*iopt2 == 0) {
+	    goto L195;
+	}
+/*  find the b-spline coefficients cosi of the cubic spline */
+/*  approximations for cr(v)=rad(v)*cos(v) and sr(v) = rad(v)*sin(v) */
+/*  if iopt2=1, and additionally also for cr(v)**2,sr(v)**2 and */
+/*  2*cr(v)*sr(v) if iopt2=2 */
+	i__2 = nvv;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    i__3 = ipar;
+	    for (j = 1; j <= i__3; ++j) {
+		cosi[j + i__ * 5] = (float)0.;
+/* L135: */
+	    }
+	    i__3 = nvv;
+	    for (j = 1; j <= i__3; ++j) {
+		a[i__ + j * a_dim1] = (float)0.;
+/* L140: */
+	    }
+	}
+/*  the coefficients cosi are obtained from interpolation conditions */
+/*  at the knots tv(i),i=4,5,...nv-4. */
+	i__3 = nvv;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    l2 = i__ + 3;
+	    arg = tv[l2];
+	    fpbspl_(&tv[1], nv, &c__3, &arg, &l2, hv);
+	    i__2 = nvv;
+	    for (j = 1; j <= i__2; ++j) {
+		row[j] = (float)0.;
+/* L145: */
+	    }
+	    ll = i__;
+	    for (j = 1; j <= 3; ++j) {
+		if (ll > nvv) {
+		    ll = 1;
+		}
+		row[ll] += hv[j - 1];
+		++ll;
+/* L150: */
+	    }
+	    co = cos(arg);
+	    si = sin(arg);
+	    r__ = (*rad)(&arg);
+	    cs[1] = co * r__;
+	    cs[2] = si * r__;
+	    if (*iopt2 == 1) {
+		goto L155;
+	    }
+	    cs[3] = cs[1] * cs[1];
+	    cs[4] = cs[2] * cs[2];
+	    cs[5] = cs[1] * cs[2];
+L155:
+	    i__2 = nvv;
+	    for (j = 1; j <= i__2; ++j) {
+		piv = row[j];
+		if (piv == (float)0.) {
+		    goto L170;
+		}
+		fpgivs_(&piv, &a[j + a_dim1], &co, &si);
+		i__4 = ipar;
+		for (l = 1; l <= i__4; ++l) {
+		    fprota_(&co, &si, &cs[l], &cosi[l + j * 5]);
+/* L160: */
+		}
+		if (j == nvv) {
+		    goto L175;
+		}
+		j1 = j + 1;
+		j2 = 1;
+		i__4 = nvv;
+		for (l = j1; l <= i__4; ++l) {
+		    ++j2;
+		    fprota_(&co, &si, &row[l], &a[j + j2 * a_dim1]);
+/* L165: */
+		}
+L170:
+		;
+	    }
+L175:
+	    ;
+	}
+	i__3 = ipar;
+	for (l = 1; l <= i__3; ++l) {
+	    i__2 = nvv;
+	    for (j = 1; j <= i__2; ++j) {
+		cs[j] = cosi[l + j * 5];
+/* L180: */
+	    }
+	    fpback_(&a[a_offset], &cs[1], &nvv, &nvv, &cs[1], ncc);
+	    i__2 = nvv;
+	    for (j = 1; j <= i__2; ++j) {
+		cosi[l + j * 5] = cs[j];
+/* L185: */
+	    }
+/* L190: */
+	}
+/*  find ncof, the dimension of the spline and ncoff, the number */
+/*  of coefficients in the standard b-spline representation. */
+L195:
+	nu4 = *nu - 4;
+	nv4 = *nv - 4;
+	ncoff = nu4 * nv4;
+	ncof = ipar1 + nvv * (nu4 - 1 - *iopt2 - *iopt3);
+/*  find the bandwidth of the observation matrix a. */
+	iband = nvv << 2;
+	if (nuu - *iopt2 - *iopt3 <= 1) {
+	    iband = ncof;
+	}
+	iband1 = iband - 1;
+/*  initialize the observation matrix a. */
+	i__3 = ncof;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    f[i__] = (float)0.;
+	    i__2 = iband;
+	    for (j = 1; j <= i__2; ++j) {
+		a[i__ + j * a_dim1] = (float)0.;
+/* L200: */
+	    }
+	}
+/*  initialize the sum of squared residuals. */
+	*fp = (float)0.;
+	ratio = one + tu[6] / tu[5];
+/*  fetch the data points in the new order. main loop for the */
+/*  different panels. */
+	i__2 = nreg;
+	for (num = 1; num <= i__2; ++num) {
+/*  fix certain constants for the current panel; jrot records the column */
+/*  number of the first non-zero element in a row of the observation */
+/*  matrix according to a data point of the panel. */
+	    num1 = num - 1;
+	    lu = num1 / nvv;
+	    l1 = lu + 4;
+	    lv = num1 - lu * nvv + 1;
+	    l2 = lv + 3;
+	    jrot = 0;
+	    if (lu > *iopt2) {
+		jrot = ipar1 + (lu - *iopt2 - 1) * nvv;
+	    }
+	    ++lu;
+/*  test whether there are still data points in the current panel. */
+	    in = index[num];
+L210:
+	    if (in == 0) {
+		goto L380;
+	    }
+/*  fetch a new data point. */
+	    wi = w[in];
+	    zi = z__[in] * wi;
+/*  evaluate for the u-direction, the 4 non-zero b-splines at u(in) */
+	    fpbspl_(&tu[1], nu, &c__3, &u[in], &l1, hu);
+/*  evaluate for the v-direction, the 4 non-zero b-splines at v(in) */
+	    fpbspl_(&tv[1], nv, &c__3, &v[in], &l2, hv);
+/*  store the value of these b-splines in spu and spv resp. */
+	    for (i__ = 1; i__ <= 4; ++i__) {
+		spu[in + i__ * spu_dim1] = hu[i__ - 1];
+		spv[in + i__ * spv_dim1] = hv[i__ - 1];
+/* L220: */
+	    }
+/*  initialize the new row of observation matrix. */
+	    i__3 = iband;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		h__[i__] = (float)0.;
+/* L240: */
+	    }
+/*  calculate the non-zero elements of the new row by making the cross */
+/*  products of the non-zero b-splines in u- and v-direction and */
+/*  by taking into account the conditions of the splines. */
+	    i__3 = nvv;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		row[i__] = (float)0.;
+/* L250: */
+	    }
+/*  take into account the periodicity condition of the bicubic splines. */
+	    ll = lv;
+	    for (i__ = 1; i__ <= 4; ++i__) {
+		if (ll > nvv) {
+		    ll = 1;
+		}
+		row[ll] += hv[i__ - 1];
+		++ll;
+/* L260: */
+	    }
+/*  take into account the other conditions of the splines. */
+	    if (*iopt2 == 0 || lu > *iopt2 + 1) {
+		goto L280;
+	    }
+	    i__3 = ipar;
+	    for (l = 1; l <= i__3; ++l) {
+		cs[l] = (float)0.;
+		i__4 = nvv;
+		for (i__ = 1; i__ <= i__4; ++i__) {
+		    cs[l] += row[i__] * cosi[l + i__ * 5];
+/* L270: */
+		}
+	    }
+/*  fill in the non-zero elements of the new row. */
+L280:
+	    j1 = 0;
+	    for (j = 1; j <= 4; ++j) {
+		jlu = j + lu;
+		huj = hu[j - 1];
+		if (jlu > *iopt2 + 2) {
+		    goto L320;
+		}
+		switch ((int)jlu) {
+		    case 1:  goto L290;
+		    case 2:  goto L290;
+		    case 3:  goto L300;
+		    case 4:  goto L310;
+		}
+L290:
+		h__[1] = huj;
+		j1 = 1;
+		goto L330;
+L300:
+		h__[1] += huj;
+		h__[2] = huj * cs[1];
+		h__[3] = huj * cs[2];
+		j1 = 3;
+		goto L330;
+L310:
+		h__[1] += huj;
+		h__[2] += huj * ratio * cs[1];
+		h__[3] += huj * ratio * cs[2];
+		h__[4] = huj * cs[3];
+		h__[5] = huj * cs[4];
+		h__[6] = huj * cs[5];
+		j1 = 6;
+		goto L330;
+L320:
+		if (jlu > nu4 && *iopt3 != 0) {
+		    goto L330;
+		}
+		i__4 = nvv;
+		for (i__ = 1; i__ <= i__4; ++i__) {
+		    ++j1;
+		    h__[j1] = row[i__] * huj;
+/* L325: */
+		}
+L330:
+		;
+	    }
+	    i__4 = iband;
+	    for (i__ = 1; i__ <= i__4; ++i__) {
+		h__[i__] *= wi;
+/* L335: */
+	    }
+/*  rotate the row into triangle by givens transformations. */
+	    irot = jrot;
+	    i__4 = iband;
+	    for (i__ = 1; i__ <= i__4; ++i__) {
+		++irot;
+		piv = h__[i__];
+		if (piv == (float)0.) {
+		    goto L350;
+		}
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &a[irot + a_dim1], &co, &si);
+/*  apply that transformation to the right hand side. */
+		fprota_(&co, &si, &zi, &f[irot]);
+		if (i__ == iband) {
+		    goto L360;
+		}
+/*  apply that transformation to the left hand side. */
+		i2 = 1;
+		i3 = i__ + 1;
+		i__3 = iband;
+		for (j = i3; j <= i__3; ++j) {
+		    ++i2;
+		    fprota_(&co, &si, &h__[j], &a[irot + i2 * a_dim1]);
+/* L340: */
+		}
+L350:
+		;
+	    }
+/*  add the contribution of the row to the sum of squares of residual */
+/*  right hand sides. */
+L360:
+/* Computing 2nd power */
+	    r__1 = zi;
+	    *fp += r__1 * r__1;
+/*  find the number of the next data point in the panel. */
+/* L370: */
+	    in = nummer[in];
+	    goto L210;
+L380:
+	    ;
+	}
+/*  find dmax, the maximum value for the diagonal elements in the reduced */
+/*  triangle. */
+	dmax__ = (float)0.;
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    if (a[i__ + a_dim1] <= dmax__) {
+		goto L390;
+	    }
+	    dmax__ = a[i__ + a_dim1];
+L390:
+	    ;
+	}
+/*  check whether the observation matrix is rank deficient. */
+	sigma = eps * dmax__;
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    if (a[i__ + a_dim1] <= sigma) {
+		goto L410;
+	    }
+/* L400: */
+	}
+/*  backward substitution in case of full rank. */
+	fpback_(&a[a_offset], &f[1], &ncof, &iband, &c__[1], ncc);
+	rank = ncof;
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    q[i__ + q_dim1] = a[i__ + a_dim1] / dmax__;
+/* L405: */
+	}
+	goto L430;
+/*  in case of rank deficiency, find the minimum norm solution. */
+L410:
+	lwest = ncof * iband + ncof + iband;
+	if (*lwrk < lwest) {
+	    goto L925;
+	}
+	lf = 1;
+	lh = lf + ncof;
+	la = lh + iband;
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ff[i__] = f[i__];
+	    i__4 = iband;
+	    for (j = 1; j <= i__4; ++j) {
+		q[i__ + j * q_dim1] = a[i__ + j * a_dim1];
+/* L420: */
+	    }
+	}
+	fprank_(&q[q_offset], &ff[1], &ncof, &iband, ncc, &sigma, &c__[1], &
+		sq, &rank, &wrk[la], &wrk[lf], &wrk[lh]);
+	i__4 = ncof;
+	for (i__ = 1; i__ <= i__4; ++i__) {
+	    q[i__ + q_dim1] /= dmax__;
+/* L425: */
+	}
+/*  add to the sum of squared residuals, the contribution of reducing */
+/*  the rank. */
+	*fp += sq;
+/*  find the coefficients in the standard b-spline representation of */
+/*  the spline. */
+L430:
+	fprppo_(nu, nv, iopt2, iopt3, &cosi[6], &ratio, &c__[1], &ff[1], &
+		ncoff);
+/*  test whether the least-squares spline is an acceptable solution. */
+	if (*iopt1 < 0) {
+	    if (*fp <= (float)0.) {
+		goto L970;
+	    } else {
+		goto L980;
+	    }
+	}
+	fpms = *fp - *s;
+	if (dabs(fpms) <= acc) {
+	    if (*fp <= (float)0.) {
+		goto L970;
+	    } else {
+		goto L980;
+	    }
+	}
+/*  if f(p=inf) < s, accept the choice of knots. */
+	if (fpms < (float)0.) {
+	    goto L580;
+	}
+/*  test whether we cannot further increase the number of knots */
+	if (*m < ncof) {
+	    goto L935;
+	}
+/*  search where to add a new knot. */
+/*  find for each interval the sum of squared residuals fpint for the */
+/*  data points having the coordinate belonging to that knot interval. */
+/*  calculate also coord which is the same sum, weighted by the position */
+/*  of the data points considered. */
+/* L440: */
+	i__4 = nrint;
+	for (i__ = 1; i__ <= i__4; ++i__) {
+	    fpint[i__] = (float)0.;
+	    coord[i__] = (float)0.;
+/* L450: */
+	}
+	i__4 = nreg;
+	for (num = 1; num <= i__4; ++num) {
+	    num1 = num - 1;
+	    lu = num1 / nvv;
+	    l1 = lu + 1;
+	    lv = num1 - lu * nvv;
+	    l2 = lv + 1 + nuu;
+	    jrot = lu * nv4 + lv;
+	    in = index[num];
+L460:
+	    if (in == 0) {
+		goto L490;
+	    }
+	    store = (float)0.;
+	    i1 = jrot;
+	    for (i__ = 1; i__ <= 4; ++i__) {
+		hui = spu[in + i__ * spu_dim1];
+		j1 = i1;
+		for (j = 1; j <= 4; ++j) {
+		    ++j1;
+		    store += hui * spv[in + j * spv_dim1] * c__[j1];
+/* L470: */
+		}
+		i1 += nv4;
+/* L480: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[in] * (z__[in] - store);
+	    store = r__1 * r__1;
+	    fpint[l1] += store;
+	    coord[l1] += store * u[in];
+	    fpint[l2] += store;
+	    coord[l2] += store * v[in];
+	    in = nummer[in];
+	    goto L460;
+L490:
+	    ;
+	}
+/* bring together the information concerning knot panels which are */
+/* symmetric with respect to the origin. */
+	i__4 = nrr;
+	for (i__ = 1; i__ <= i__4; ++i__) {
+	    l1 = nuu + i__;
+	    l2 = l1 + nrr;
+	    fpint[l1] += fpint[l2];
+	    coord[l1] = coord[l1] + coord[l2] - pi * fpint[l2];
+/* L495: */
+	}
+/*  find the interval for which fpint is maximal on the condition that */
+/*  there still can be added a knot. */
+	l1 = 1;
+	l2 = nuu + nrr;
+	if (*nuest < *nu + 1) {
+	    l1 = nuu + 1;
+	}
+	if (*nvest < *nv + 2) {
+	    l2 = nuu;
+	}
+/*  test whether we cannot further increase the number of knots. */
+	if (l1 > l2) {
+	    goto L950;
+	}
+L500:
+	fpmax = (float)0.;
+	l = 0;
+	i__4 = l2;
+	for (i__ = l1; i__ <= i__4; ++i__) {
+	    if (fpmax >= fpint[i__]) {
+		goto L510;
+	    }
+	    l = i__;
+	    fpmax = fpint[i__];
+L510:
+	    ;
+	}
+	if (l == 0) {
+	    goto L930;
+	}
+/*  calculate the position of the new knot. */
+	arg = coord[l] / fpint[l];
+/*  test in what direction the new knot is going to be added. */
+	if (l > nuu) {
+	    goto L530;
+	}
+/*  addition in the u-direction */
+	l4 = l + 4;
+	fpint[l] = (float)0.;
+	fac1 = tu[l4] - arg;
+	fac2 = arg - tu[l4 - 1];
+	if (fac1 > ten * fac2 || fac2 > ten * fac1) {
+	    goto L500;
+	}
+	j = *nu;
+	i__4 = *nu;
+	for (i__ = l4; i__ <= i__4; ++i__) {
+	    tu[j + 1] = tu[j];
+	    --j;
+/* L520: */
+	}
+	tu[l4] = arg;
+	++(*nu);
+	goto L570;
+/*  addition in the v-direction */
+L530:
+	l4 = l + 4 - nuu;
+	fpint[l] = (float)0.;
+	fac1 = tv[l4] - arg;
+	fac2 = arg - tv[l4 - 1];
+	if (fac1 > ten * fac2 || fac2 > ten * fac1) {
+	    goto L500;
+	}
+	ll = nrr + 4;
+	j = ll;
+	i__4 = ll;
+	for (i__ = l4; i__ <= i__4; ++i__) {
+	    tv[j + 1] = tv[j];
+	    --j;
+/* L550: */
+	}
+	tv[l4] = arg;
+	*nv += 2;
+	++nrr;
+	i__4 = ll;
+	for (i__ = 5; i__ <= i__4; ++i__) {
+	    j = i__ + nrr;
+	    tv[j] = tv[i__] + pi;
+/* L560: */
+	}
+/*  restart the computations with the new set of knots. */
+L570:
+	;
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/* part 2: determination of the smoothing bicubic spline.               c */
+/* ******************************************************               c */
+/* we have determined the number of knots and their position. we now    c */
+/* compute the coefficients of the smoothing spline sp(u,v).            c */
+/* the observation matrix a is extended by the rows of a matrix, expres-c */
+/* sing that sp(u,v) must be a constant function in the variable        c */
+/* v and a cubic polynomial in the variable u. the corresponding        c */
+/* weights of these additional rows are set to 1/(p). iteratively       c */
+/* we than have to determine the value of p such that f(p) = sum((w(i)* c */
+/* (z(i)-sp(u(i),v(i))))**2)  be = s.                                   c */
+/* we already know that the least-squares polynomial corresponds to p=0,c */
+/* and that the least-squares bicubic spline corresponds to p=infin.    c */
+/* the iteration process makes use of rational interpolation. since f(p)c */
+/* is a convex and strictly decreasing function of p, it can be approx- c */
+/* imated by a rational function of the form r(p) = (u*p+v)/(p+w).      c */
+/* three values of p (p1,p2,p3) with corresponding values of f(p) (f1=  c */
+/* f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used to calculate the new value   c */
+/* of p such that r(p)=s. convergence is guaranteed by taking f1>0,f3<0.c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  evaluate the discontinuity jumps of the 3-th order derivative of */
+/*  the b-splines at the knots tu(l),l=5,...,nu-4. */
+L580:
+    fpdisc_(&tu[1], nu, &c__5, &bu[bu_offset], nuest);
+/*  evaluate the discontinuity jumps of the 3-th order derivative of */
+/*  the b-splines at the knots tv(l),l=5,...,nv-4. */
+    fpdisc_(&tv[1], nv, &c__5, &bv[bv_offset], nvest);
+/*  initial value for p. */
+    p1 = (float)0.;
+    f1 = *sup - *s;
+    p3 = -one;
+    f3 = fpms;
+    p = (float)0.;
+    i__1 = ncof;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	p += a[i__ + a_dim1];
+/* L590: */
+    }
+    rn = (real) ncof;
+    p = rn / p;
+/*  find the bandwidth of the extended observation matrix. */
+    iband4 = iband + ipar1;
+    if (iband4 > ncof) {
+	iband4 = ncof;
+    }
+    iband3 = iband4 - 1;
+    ich1 = 0;
+    ich3 = 0;
+    nuu = nu4 - *iopt3 - 1;
+/*  iteration process to find the root of f(p)=s. */
+    i__1 = *maxit;
+    for (iter = 1; iter <= i__1; ++iter) {
+	pinv = one / p;
+/*  store the triangularized observation matrix into q. */
+	i__4 = ncof;
+	for (i__ = 1; i__ <= i__4; ++i__) {
+	    ff[i__] = f[i__];
+	    i__2 = iband4;
+	    for (j = 1; j <= i__2; ++j) {
+		q[i__ + j * q_dim1] = (float)0.;
+/* L620: */
+	    }
+	    i__2 = iband;
+	    for (j = 1; j <= i__2; ++j) {
+		q[i__ + j * q_dim1] = a[i__ + j * a_dim1];
+/* L630: */
+	    }
+	}
+/*  extend the observation matrix with the rows of a matrix, expressing */
+/*  that for u=constant sp(u,v) must be a constant function. */
+	i__2 = nv4;
+	for (i__ = 5; i__ <= i__2; ++i__) {
+	    ii = i__ - 4;
+	    i__4 = nvv;
+	    for (l = 1; l <= i__4; ++l) {
+		row[l] = (float)0.;
+/* L635: */
+	    }
+	    ll = ii;
+	    for (l = 1; l <= 5; ++l) {
+		if (ll > nvv) {
+		    ll = 1;
+		}
+		row[ll] += bv[ii + l * bv_dim1];
+		++ll;
+/* L640: */
+	    }
+	    i__4 = nuu;
+	    for (j = 1; j <= i__4; ++j) {
+/*  initialize the new row. */
+		i__3 = iband;
+		for (l = 1; l <= i__3; ++l) {
+		    h__[l] = (float)0.;
+/* L645: */
+		}
+/*  fill in the non-zero elements of the row. jrot records the column */
+/*  number of the first non-zero element in the row. */
+		if (j > *iopt2) {
+		    goto L665;
+		}
+		if (j == 2) {
+		    goto L655;
+		}
+		for (k = 1; k <= 2; ++k) {
+		    cs[k] = (float)0.;
+		    i__3 = nvv;
+		    for (l = 1; l <= i__3; ++l) {
+			cs[k] += cosi[k + l * 5] * row[l];
+/* L650: */
+		    }
+		}
+		h__[1] = cs[1];
+		h__[2] = cs[2];
+		jrot = 2;
+		goto L675;
+L655:
+		for (k = 3; k <= 5; ++k) {
+		    cs[k] = (float)0.;
+		    i__3 = nvv;
+		    for (l = 1; l <= i__3; ++l) {
+			cs[k] += cosi[k + l * 5] * row[l];
+/* L660: */
+		    }
+		}
+		h__[1] = cs[1] * ratio;
+		h__[2] = cs[2] * ratio;
+		h__[3] = cs[3];
+		h__[4] = cs[4];
+		h__[5] = cs[5];
+		jrot = 2;
+		goto L675;
+L665:
+		i__3 = nvv;
+		for (l = 1; l <= i__3; ++l) {
+		    h__[l] = row[l];
+/* L670: */
+		}
+		jrot = ipar1 + 1 + (j - *iopt2 - 1) * nvv;
+L675:
+		i__3 = iband;
+		for (l = 1; l <= i__3; ++l) {
+		    h__[l] *= pinv;
+/* L677: */
+		}
+		zi = (float)0.;
+/*  rotate the new row into triangle by givens transformations. */
+		i__3 = ncof;
+		for (irot = jrot; irot <= i__3; ++irot) {
+		    piv = h__[1];
+/* Computing MIN */
+		    i__5 = iband1, i__6 = ncof - irot;
+		    i2 = min(i__5,i__6);
+		    if (piv == (float)0.) {
+			if (i2 <= 0) {
+			    goto L720;
+			} else {
+			    goto L690;
+			}
+		    }
+/*  calculate the parameters of the givens transformation. */
+		    fpgivs_(&piv, &q[irot + q_dim1], &co, &si);
+/*  apply that givens transformation to the right hand side. */
+		    fprota_(&co, &si, &zi, &ff[irot]);
+		    if (i2 == 0) {
+			goto L720;
+		    }
+/*  apply that givens transformation to the left hand side. */
+		    i__5 = i2;
+		    for (l = 1; l <= i__5; ++l) {
+			l1 = l + 1;
+			fprota_(&co, &si, &h__[l1], &q[irot + l1 * q_dim1]);
+/* L680: */
+		    }
+L690:
+		    i__5 = i2;
+		    for (l = 1; l <= i__5; ++l) {
+			h__[l] = h__[l + 1];
+/* L700: */
+		    }
+		    h__[i2 + 1] = (float)0.;
+/* L710: */
+		}
+L720:
+		;
+	    }
+	}
+/*  extend the observation matrix with the rows of a matrix expressing */
+/*  that for v=constant. sp(u,v) must be a cubic polynomial. */
+	i__4 = nu4;
+	for (i__ = 5; i__ <= i__4; ++i__) {
+	    ii = i__ - 4;
+	    i__2 = nvv;
+	    for (j = 1; j <= i__2; ++j) {
+/*  initialize the new row */
+		i__3 = iband4;
+		for (l = 1; l <= i__3; ++l) {
+		    h__[l] = (float)0.;
+/* L730: */
+		}
+/*  fill in the non-zero elements of the row. jrot records the column */
+/*  number of the first non-zero element in the row. */
+		j1 = 1;
+		for (l = 1; l <= 5; ++l) {
+		    il = ii + l - 1;
+		    if (il == nu4 && *iopt3 != 0) {
+			goto L760;
+		    }
+		    if (il > *iopt2 + 1) {
+			goto L750;
+		    }
+		    switch ((int)il) {
+			case 1:  goto L735;
+			case 2:  goto L740;
+			case 3:  goto L745;
+		    }
+L735:
+		    h__[1] = bu[ii + l * bu_dim1];
+		    j1 = j + 1;
+		    goto L760;
+L740:
+		    h__[1] += bu[ii + l * bu_dim1];
+		    h__[2] = bu[ii + l * bu_dim1] * cosi[j * 5 + 1];
+		    h__[3] = bu[ii + l * bu_dim1] * cosi[j * 5 + 2];
+		    j1 = j + 3;
+		    goto L760;
+L745:
+		    h__[1] += bu[ii + l * bu_dim1];
+		    h__[2] = bu[ii + l * bu_dim1] * cosi[j * 5 + 1] * ratio;
+		    h__[3] = bu[ii + l * bu_dim1] * cosi[j * 5 + 2] * ratio;
+		    h__[4] = bu[ii + l * bu_dim1] * cosi[j * 5 + 3];
+		    h__[5] = bu[ii + l * bu_dim1] * cosi[j * 5 + 4];
+		    h__[6] = bu[ii + l * bu_dim1] * cosi[j * 5 + 5];
+		    j1 = j + 6;
+		    goto L760;
+L750:
+		    h__[j1] = bu[ii + l * bu_dim1];
+		    j1 += nvv;
+L760:
+		    ;
+		}
+		i__3 = iband4;
+		for (l = 1; l <= i__3; ++l) {
+		    h__[l] *= pinv;
+/* L765: */
+		}
+		zi = (float)0.;
+		jrot = 1;
+		if (ii > *iopt2 + 1) {
+		    jrot = ipar1 + (ii - *iopt2 - 2) * nvv + j;
+		}
+/*  rotate the new row into triangle by givens transformations. */
+		i__3 = ncof;
+		for (irot = jrot; irot <= i__3; ++irot) {
+		    piv = h__[1];
+/* Computing MIN */
+		    i__5 = iband3, i__6 = ncof - irot;
+		    i2 = min(i__5,i__6);
+		    if (piv == (float)0.) {
+			if (i2 <= 0) {
+			    goto L810;
+			} else {
+			    goto L780;
+			}
+		    }
+/*  calculate the parameters of the givens transformation. */
+		    fpgivs_(&piv, &q[irot + q_dim1], &co, &si);
+/*  apply that givens transformation to the right hand side. */
+		    fprota_(&co, &si, &zi, &ff[irot]);
+		    if (i2 == 0) {
+			goto L810;
+		    }
+/*  apply that givens transformation to the left hand side. */
+		    i__5 = i2;
+		    for (l = 1; l <= i__5; ++l) {
+			l1 = l + 1;
+			fprota_(&co, &si, &h__[l1], &q[irot + l1 * q_dim1]);
+/* L770: */
+		    }
+L780:
+		    i__5 = i2;
+		    for (l = 1; l <= i__5; ++l) {
+			h__[l] = h__[l + 1];
+/* L790: */
+		    }
+		    h__[i2 + 1] = (float)0.;
+/* L800: */
+		}
+L810:
+		;
+	    }
+	}
+/*  find dmax, the maximum value for the diagonal elements in the */
+/*  reduced triangle. */
+	dmax__ = (float)0.;
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    if (q[i__ + q_dim1] <= dmax__) {
+		goto L820;
+	    }
+	    dmax__ = q[i__ + q_dim1];
+L820:
+	    ;
+	}
+/*  check whether the matrix is rank deficient. */
+	sigma = eps * dmax__;
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    if (q[i__ + q_dim1] <= sigma) {
+		goto L840;
+	    }
+/* L830: */
+	}
+/*  backward substitution in case of full rank. */
+	fpback_(&q[q_offset], &ff[1], &ncof, &iband4, &c__[1], ncc);
+	rank = ncof;
+	goto L845;
+/*  in case of rank deficiency, find the minimum norm solution. */
+L840:
+	lwest = ncof * iband4 + ncof + iband4;
+	if (*lwrk < lwest) {
+	    goto L925;
+	}
+	lf = 1;
+	lh = lf + ncof;
+	la = lh + iband4;
+	fprank_(&q[q_offset], &ff[1], &ncof, &iband4, ncc, &sigma, &c__[1], &
+		sq, &rank, &wrk[la], &wrk[lf], &wrk[lh]);
+L845:
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    q[i__ + q_dim1] /= dmax__;
+/* L850: */
+	}
+/*  find the coefficients in the standard b-spline representation of */
+/*  the polar spline. */
+	fprppo_(nu, nv, iopt2, iopt3, &cosi[6], &ratio, &c__[1], &ff[1], &
+		ncoff);
+/*  compute f(p). */
+	*fp = (float)0.;
+	i__2 = nreg;
+	for (num = 1; num <= i__2; ++num) {
+	    num1 = num - 1;
+	    lu = num1 / nvv;
+	    lv = num1 - lu * nvv;
+	    jrot = lu * nv4 + lv;
+	    in = index[num];
+L860:
+	    if (in == 0) {
+		goto L890;
+	    }
+	    store = (float)0.;
+	    i1 = jrot;
+	    for (i__ = 1; i__ <= 4; ++i__) {
+		hui = spu[in + i__ * spu_dim1];
+		j1 = i1;
+		for (j = 1; j <= 4; ++j) {
+		    ++j1;
+		    store += hui * spv[in + j * spv_dim1] * c__[j1];
+/* L870: */
+		}
+		i1 += nv4;
+/* L880: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[in] * (z__[in] - store);
+	    *fp += r__1 * r__1;
+	    in = nummer[in];
+	    goto L860;
+L890:
+	    ;
+	}
+/*  test whether the approximation sp(u,v) is an acceptable solution */
+	fpms = *fp - *s;
+	if (dabs(fpms) <= acc) {
+	    goto L980;
+	}
+/*  test whether the maximum allowable number of iterations has been */
+/*  reached. */
+	if (iter == *maxit) {
+	    goto L940;
+	}
+/*  carry out one more step of the iteration process. */
+	p2 = p;
+	f2 = fpms;
+	if (ich3 != 0) {
+	    goto L900;
+	}
+	if (f2 - f3 > acc) {
+	    goto L895;
+	}
+/*  our initial choice of p is too large. */
+	p3 = p2;
+	f3 = f2;
+	p *= con4;
+	if (p <= p1) {
+	    p = p1 * con9 + p2 * con1;
+	}
+	goto L920;
+L895:
+	if (f2 < (float)0.) {
+	    ich3 = 1;
+	}
+L900:
+	if (ich1 != 0) {
+	    goto L910;
+	}
+	if (f1 - f2 > acc) {
+	    goto L905;
+	}
+/*  our initial choice of p is too small */
+	p1 = p2;
+	f1 = f2;
+	p /= con4;
+	if (p3 < (float)0.) {
+	    goto L920;
+	}
+	if (p >= p3) {
+	    p = p2 * con1 + p3 * con9;
+	}
+	goto L920;
+L905:
+	if (f2 > (float)0.) {
+	    ich1 = 1;
+	}
+/*  test whether the iteration process proceeds as theoretically */
+/*  expected. */
+L910:
+	if (f2 >= f1 || f2 <= f3) {
+	    goto L945;
+	}
+/*  find the new value of p. */
+	p = fprati_(&p1, &f1, &p2, &f2, &p3, &f3);
+L920:
+	;
+    }
+/*  error codes and messages. */
+L925:
+    *ier = lwest;
+    goto L990;
+L930:
+    *ier = 5;
+    goto L990;
+L935:
+    *ier = 4;
+    goto L990;
+L940:
+    *ier = 3;
+    goto L990;
+L945:
+    *ier = 2;
+    goto L990;
+L950:
+    *ier = 1;
+    goto L990;
+L960:
+    *ier = -2;
+    goto L990;
+L970:
+    *ier = -1;
+    *fp = (float)0.;
+L980:
+    if (ncof != rank) {
+	*ier = -rank;
+    }
+L990:
+    return 0;
+} /* fppola_ */
+
+/* Subroutine */ int fprank_(a, f, n, m, na, tol, c__, sq, rank, aa, ff, h__)
+real *a, *f;
+integer *n, *m, *na;
+real *tol, *c__, *sq;
+integer *rank;
+real *aa, *ff, *h__;
+{
+    /* System generated locals */
+    integer a_dim1, a_offset, aa_dim1, aa_offset, i__1, i__2, i__3;
+    real r__1;
+
+    /* Local variables */
+    static integer i__, j, k;
+    static doublereal stor1, stor2, stor3;
+    static integer i1, i2, j1, j2, j3, m1;
+    static doublereal store;
+    static integer ii, ij, jj, kk, nl;
+    static real yi;
+    extern /* Subroutine */ int fprota_(), fpgivs_();
+    static real fac, cos__, sin__, piv;
+
+/*  subroutine fprank finds the minimum norm solution of a least- */
+/*  squares problem in case of rank deficiency. */
+
+/*  input parameters: */
+/*    a : array, which contains the non-zero elements of the observation */
+/*        matrix after triangularization by givens transformations. */
+/*    f : array, which contains the transformed right hand side. */
+/*    n : integer,wich contains the dimension of a. */
+/*    m : integer, which denotes the bandwidth of a. */
+/*  tol : real value, giving a threshold to determine the rank of a. */
+
+/*  output parameters: */
+/*    c : array, which contains the minimum norm solution. */
+/*   sq : real value, giving the contribution of reducing the rank */
+/*        to the sum of squared residuals. */
+/* rank : integer, which contains the rank of matrix a. */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpgivs,fprota */
+/*  .. */
+    /* Parameter adjustments */
+    --ff;
+    --c__;
+    --f;
+    --h__;
+    aa_dim1 = *n;
+    aa_offset = 1 + aa_dim1 * 1;
+    aa -= aa_offset;
+    a_dim1 = *na;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+
+    /* Function Body */
+    m1 = *m - 1;
+/*  the rank deficiency nl is considered to be the number of sufficient */
+/*  small diagonal elements of a. */
+    nl = 0;
+    *sq = (float)0.;
+    i__1 = *n;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (a[i__ + a_dim1] > *tol) {
+	    goto L90;
+	}
+/*  if a sufficient small diagonal element is found, we put it to */
+/*  zero. the remainder of the row corresponding to that zero diagonal */
+/*  element is then rotated into triangle by givens rotations . */
+/*  the rank deficiency is increased by one. */
+	++nl;
+	if (i__ == *n) {
+	    goto L90;
+	}
+	yi = f[i__];
+	i__2 = m1;
+	for (j = 1; j <= i__2; ++j) {
+	    h__[j] = a[i__ + (j + 1) * a_dim1];
+/* L10: */
+	}
+	h__[*m] = (float)0.;
+	i1 = i__ + 1;
+	i__2 = *n;
+	for (ii = i1; ii <= i__2; ++ii) {
+/* Computing MIN */
+	    i__3 = *n - ii;
+	    i2 = min(i__3,m1);
+	    piv = h__[1];
+	    if (piv == (float)0.) {
+		goto L30;
+	    }
+	    fpgivs_(&piv, &a[ii + a_dim1], &cos__, &sin__);
+	    fprota_(&cos__, &sin__, &yi, &f[ii]);
+	    if (i2 == 0) {
+		goto L70;
+	    }
+	    i__3 = i2;
+	    for (j = 1; j <= i__3; ++j) {
+		j1 = j + 1;
+		fprota_(&cos__, &sin__, &h__[j1], &a[ii + j1 * a_dim1]);
+		h__[j] = h__[j1];
+/* L20: */
+	    }
+	    goto L50;
+L30:
+	    if (i2 == 0) {
+		goto L70;
+	    }
+	    i__3 = i2;
+	    for (j = 1; j <= i__3; ++j) {
+		h__[j] = h__[j + 1];
+/* L40: */
+	    }
+L50:
+	    h__[i2 + 1] = (float)0.;
+/* L60: */
+	}
+/*  add to the sum of squared residuals the contribution of deleting */
+/*  the row with small diagonal element. */
+L70:
+/* Computing 2nd power */
+	r__1 = yi;
+	*sq += r__1 * r__1;
+L90:
+	;
+    }
+/*  rank denotes the rank of a. */
+    *rank = *n - nl;
+/*  let b denote the (rank*n) upper trapezoidal matrix which can be */
+/*  obtained from the (n*n) upper triangular matrix a by deleting */
+/*  the rows and interchanging the columns corresponding to a zero */
+/*  diagonal element. if this matrix is factorized using givens */
+/*  transformations as  b = (r) (u)  where */
+/*    r is a (rank*rank) upper triangular matrix, */
+/*    u is a (rank*n) orthonormal matrix */
+/*  then the minimal least-squares solution c is given by c = b' v, */
+/*  where v is the solution of the system  (r) (r)' v = g  and */
+/*  g denotes the vector obtained from the old right hand side f, by */
+/*  removing the elements corresponding to a zero diagonal element of a. */
+/*  initialization. */
+    i__1 = *rank;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	i__2 = *m;
+	for (j = 1; j <= i__2; ++j) {
+	    aa[i__ + j * aa_dim1] = (float)0.;
+/* L100: */
+	}
+    }
+/*  form in aa the upper triangular matrix obtained from a by */
+/*  removing rows and columns with zero diagonal elements. form in ff */
+/*  the new right hand side by removing the elements of the old right */
+/*  hand side corresponding to a deleted row. */
+    ii = 0;
+    i__2 = *n;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	if (a[i__ + a_dim1] <= *tol) {
+	    goto L120;
+	}
+	++ii;
+	ff[ii] = f[i__];
+	aa[ii + aa_dim1] = a[i__ + a_dim1];
+	jj = ii;
+	kk = 1;
+	j = i__;
+/* Computing MIN */
+	i__1 = j - 1;
+	j1 = min(i__1,m1);
+	if (j1 == 0) {
+	    goto L120;
+	}
+	i__1 = j1;
+	for (k = 1; k <= i__1; ++k) {
+	    --j;
+	    if (a[j + a_dim1] <= *tol) {
+		goto L110;
+	    }
+	    ++kk;
+	    --jj;
+	    aa[jj + kk * aa_dim1] = a[j + (k + 1) * a_dim1];
+L110:
+	    ;
+	}
+L120:
+	;
+    }
+/*  form successively in h the columns of a with a zero diagonal element. */
+    ii = 0;
+    i__2 = *n;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	++ii;
+	if (a[i__ + a_dim1] > *tol) {
+	    goto L200;
+	}
+	--ii;
+	if (ii == 0) {
+	    goto L200;
+	}
+	jj = 1;
+	j = i__;
+/* Computing MIN */
+	i__1 = j - 1;
+	j1 = min(i__1,m1);
+	i__1 = j1;
+	for (k = 1; k <= i__1; ++k) {
+	    --j;
+	    if (a[j + a_dim1] <= *tol) {
+		goto L130;
+	    }
+	    h__[jj] = a[j + (k + 1) * a_dim1];
+	    ++jj;
+L130:
+	    ;
+	}
+	i__1 = *m;
+	for (kk = jj; kk <= i__1; ++kk) {
+	    h__[kk] = (float)0.;
+/* L140: */
+	}
+/*  rotate this column into aa by givens transformations. */
+	jj = ii;
+	i__1 = ii;
+	for (i1 = 1; i1 <= i__1; ++i1) {
+/* Computing MIN */
+	    i__3 = jj - 1;
+	    j1 = min(i__3,m1);
+	    piv = h__[1];
+	    if (piv != (float)0.) {
+		goto L160;
+	    }
+	    if (j1 == 0) {
+		goto L200;
+	    }
+	    i__3 = j1;
+	    for (j2 = 1; j2 <= i__3; ++j2) {
+		j3 = j2 + 1;
+		h__[j2] = h__[j3];
+/* L150: */
+	    }
+	    goto L180;
+L160:
+	    fpgivs_(&piv, &aa[jj + aa_dim1], &cos__, &sin__);
+	    if (j1 == 0) {
+		goto L200;
+	    }
+	    kk = jj;
+	    i__3 = j1;
+	    for (j2 = 1; j2 <= i__3; ++j2) {
+		j3 = j2 + 1;
+		--kk;
+		fprota_(&cos__, &sin__, &h__[j3], &aa[kk + j3 * aa_dim1]);
+		h__[j2] = h__[j3];
+/* L170: */
+	    }
+L180:
+	    --jj;
+	    h__[j3] = (float)0.;
+/* L190: */
+	}
+L200:
+	;
+    }
+/*  solve the system (aa) (f1) = ff */
+    ff[*rank] /= aa[*rank + aa_dim1];
+    i__ = *rank - 1;
+    if (i__ == 0) {
+	goto L230;
+    }
+    i__2 = *rank;
+    for (j = 2; j <= i__2; ++j) {
+	store = ff[i__];
+/* Computing MIN */
+	i__1 = j - 1;
+	i1 = min(i__1,m1);
+	k = i__;
+	i__1 = i1;
+	for (ii = 1; ii <= i__1; ++ii) {
+	    ++k;
+	    stor1 = ff[k];
+	    stor2 = aa[i__ + (ii + 1) * aa_dim1];
+	    store -= stor1 * stor2;
+/* L210: */
+	}
+	stor1 = aa[i__ + aa_dim1];
+	ff[i__] = store / stor1;
+	--i__;
+/* L220: */
+    }
+/*  solve the system  (aa)' (f2) = f1 */
+L230:
+    ff[1] /= aa[aa_dim1 + 1];
+    if (*rank == 1) {
+	goto L260;
+    }
+    i__2 = *rank;
+    for (j = 2; j <= i__2; ++j) {
+	store = ff[j];
+/* Computing MIN */
+	i__1 = j - 1;
+	i1 = min(i__1,m1);
+	k = j;
+	i__1 = i1;
+	for (ii = 1; ii <= i__1; ++ii) {
+	    --k;
+	    stor1 = ff[k];
+	    stor2 = aa[k + (ii + 1) * aa_dim1];
+	    store -= stor1 * stor2;
+/* L240: */
+	}
+	stor1 = aa[j + aa_dim1];
+	ff[j] = store / stor1;
+/* L250: */
+    }
+/*  premultiply f2 by the transpoze of a. */
+L260:
+    k = 0;
+    i__2 = *n;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	store = (float)0.;
+	if (a[i__ + a_dim1] > *tol) {
+	    ++k;
+	}
+	j1 = min(i__,*m);
+	kk = k;
+	ij = i__ + 1;
+	i__1 = j1;
+	for (j = 1; j <= i__1; ++j) {
+	    --ij;
+	    if (a[ij + a_dim1] <= *tol) {
+		goto L270;
+	    }
+	    stor1 = a[ij + j * a_dim1];
+	    stor2 = ff[kk];
+	    store += stor1 * stor2;
+	    --kk;
+L270:
+	    ;
+	}
+	c__[i__] = store;
+/* L280: */
+    }
+/*  add to the sum of squared residuals the contribution of putting */
+/*  to zero the small diagonal elements of matrix (a). */
+    stor3 = (float)0.;
+    i__2 = *n;
+    for (i__ = 1; i__ <= i__2; ++i__) {
+	if (a[i__ + a_dim1] > *tol) {
+	    goto L310;
+	}
+	store = f[i__];
+/* Computing MIN */
+	i__1 = *n - i__;
+	i1 = min(i__1,m1);
+	if (i1 == 0) {
+	    goto L300;
+	}
+	i__1 = i1;
+	for (j = 1; j <= i__1; ++j) {
+	    ij = i__ + j;
+	    stor1 = c__[ij];
+	    stor2 = a[i__ + (j + 1) * a_dim1];
+	    store -= stor1 * stor2;
+/* L290: */
+	}
+L300:
+	fac = a[i__ + a_dim1] * c__[i__];
+	stor1 = a[i__ + a_dim1];
+	stor2 = c__[i__];
+	stor1 *= stor2;
+	stor3 += stor1 * (stor1 - store - store);
+L310:
+	;
+    }
+    fac = stor3;
+    *sq += fac;
+    return 0;
+} /* fprank_ */
+
+doublereal fprati_(p1, f1, p2, f2, p3, f3)
+real *p1, *f1, *p2, *f2, *p3, *f3;
+{
+    /* System generated locals */
+    real ret_val;
+
+    /* Local variables */
+    static real p, h1, h2, h3;
+
+/*  given three points (p1,f1),(p2,f2) and (p3,f3), function fprati */
+/*  gives the value of p such that the rational interpolating function */
+/*  of the form r(p) = (u*p+v)/(p+w) equals zero at p. */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    if (*p3 > (float)0.) {
+	goto L10;
+    }
+/*  value of p in case p3 = infinity. */
+    p = (*p1 * (*f1 - *f3) * *f2 - *p2 * (*f2 - *f3) * *f1) / ((*f1 - *f2) * *
+	    f3);
+    goto L20;
+/*  value of p in case p3 ^= infinity. */
+L10:
+    h1 = *f1 * (*f2 - *f3);
+    h2 = *f2 * (*f3 - *f1);
+    h3 = *f3 * (*f1 - *f2);
+    p = -(*p1 * *p2 * h3 + *p2 * *p3 * h1 + *p3 * *p1 * h2) / (*p1 * h1 + *p2 
+	    * h2 + *p3 * h3);
+/*  adjust the value of p1,f1,p3 and f3 such that f1 > 0 and f3 < 0. */
+L20:
+    if (*f2 < (float)0.) {
+	goto L30;
+    }
+    *p1 = *p2;
+    *f1 = *f2;
+    goto L40;
+L30:
+    *p3 = *p2;
+    *f3 = *f2;
+L40:
+    ret_val = p;
+    return ret_val;
+} /* fprati_ */
+
+/* Subroutine */ int fpregr_(iopt, x, mx, y, my, z__, mz, xb, xe, yb, ye, kx, 
+	ky, s, nxest, nyest, tol, maxit, nc, nx, tx, ny, ty, c__, fp, fp0, 
+	fpold, reducx, reducy, fpintx, fpinty, lastdi, nplusx, nplusy, nrx, 
+	nry, nrdatx, nrdaty, wrk, lwrk, ier)
+integer *iopt;
+real *x;
+integer *mx;
+real *y;
+integer *my;
+real *z__;
+integer *mz;
+real *xb, *xe, *yb, *ye;
+integer *kx, *ky;
+real *s;
+integer *nxest, *nyest;
+real *tol;
+integer *maxit, *nc, *nx;
+real *tx;
+integer *ny;
+real *ty, *c__, *fp, *fp0, *fpold, *reducx, *reducy, *fpintx, *fpinty;
+integer *lastdi, *nplusx, *nplusy, *nrx, *nry, *nrdatx, *nrdaty;
+real *wrk;
+integer *lwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3, i__4, i__5;
+
+    /* Local variables */
+    static real half;
+    static integer ncof, ifbx, ifby, iter;
+    static real fpms;
+    static integer ifsx, ifsy, nplx, nply, mynx, i__, j, l;
+    static real p, f1, f2, f3;
+    static integer nminx, nmaxx, nmaxy, nminy, k3;
+    static real p1, p2, p3;
+    static integer mm, lq;
+    static real rn;
+    extern doublereal fprati_();
+    extern /* Subroutine */ int fpgrre_(), fpknot_();
+    static integer mk1, nrintx, nrinty, kx1, kx2, ky1, ky2;
+    static real acc, one;
+    static integer lax, lay, lbx, lby, lri, mpm, nxe, nye, nxk, lsx, lsy, 
+	    ich1, ich3;
+    static real con1, con4, con9;
+    static integer npl1, nk1x, nk1y;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpgrre,fpknot */
+/*  .. */
+/*   set constants */
+    /* Parameter adjustments */
+    --nrx;
+    --x;
+    --nry;
+    --y;
+    --z__;
+    --nrdatx;
+    --fpintx;
+    --tx;
+    --nrdaty;
+    --fpinty;
+    --ty;
+    --c__;
+    --wrk;
+
+    /* Function Body */
+    one = (float)1.;
+    half = (float).5;
+    con1 = (float).1;
+    con9 = (float).9;
+    con4 = (float).04;
+/*  we partition the working space. */
+    kx1 = *kx + 1;
+    ky1 = *ky + 1;
+    kx2 = kx1 + 1;
+    ky2 = ky1 + 1;
+    lsx = 1;
+    lsy = lsx + *mx * kx1;
+    lri = lsy + *my * ky1;
+    mm = max(*nxest,*my);
+    lq = lri + mm;
+    mynx = *nxest * *my;
+    lax = lq + mynx;
+    nxk = *nxest * kx2;
+    lbx = lax + nxk;
+    lay = lbx + nxk;
+    lby = lay + *nyest * ky2;
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/* part 1: determination of the number of knots and their position.     c */
+/* ****************************************************************     c */
+/*  given a set of knots we compute the least-squares spline sinf(x,y), c */
+/*  and the corresponding sum of squared residuals fp=f(p=inf).         c */
+/*  if iopt=-1  sinf(x,y) is the requested approximation.               c */
+/*  if iopt=0 or iopt=1 we check whether we can accept the knots:       c */
+/*    if fp <=s we will continue with the current set of knots.         c */
+/*    if fp > s we will increase the number of knots and compute the    c */
+/*       corresponding least-squares spline until finally fp<=s.        c */
+/*    the initial choice of knots depends on the value of s and iopt.   c */
+/*    if s=0 we have spline interpolation; in that case the number of   c */
+/*    knots equals nmaxx = mx+kx+1  and  nmaxy = my+ky+1.               c */
+/*    if s>0 and                                                        c */
+/*     *iopt=0 we first compute the least-squares polynomial of degree  c */
+/*      kx in x and ky in y; nx=nminx=2*kx+2 and ny=nymin=2*ky+2.       c */
+/*     *iopt=1 we start with the knots found at the last call of the    c */
+/*      routine, except for the case that s > fp0; then we can compute  c */
+/*      the least-squares polynomial directly.                          c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  determine the number of knots for polynomial approximation. */
+    nminx = kx1 << 1;
+    nminy = ky1 << 1;
+    if (*iopt < 0) {
+	goto L120;
+    }
+/*  acc denotes the absolute tolerance for the root of f(p)=s. */
+    acc = *tol * *s;
+/*  find nmaxx and nmaxy which denote the number of knots in x- and y- */
+/*  direction in case of spline interpolation. */
+    nmaxx = *mx + kx1;
+    nmaxy = *my + ky1;
+/*  find nxe and nye which denote the maximum number of knots */
+/*  allowed in each direction */
+    nxe = min(nmaxx,*nxest);
+    nye = min(nmaxy,*nyest);
+    if (*s > (float)0.) {
+	goto L100;
+    }
+/*  if s = 0, s(x,y) is an interpolating spline. */
+    *nx = nmaxx;
+    *ny = nmaxy;
+/*  test whether the required storage space exceeds the available one. */
+    if (*ny > *nyest || *nx > *nxest) {
+	goto L420;
+    }
+/*  find the position of the interior knots in case of interpolation. */
+/*  the knots in the x-direction. */
+    mk1 = *mx - kx1;
+    if (mk1 == 0) {
+	goto L60;
+    }
+    k3 = *kx / 2;
+    i__ = kx1 + 1;
+    j = k3 + 2;
+    if (k3 << 1 == *kx) {
+	goto L40;
+    }
+    i__1 = mk1;
+    for (l = 1; l <= i__1; ++l) {
+	tx[i__] = x[j];
+	++i__;
+	++j;
+/* L30: */
+    }
+    goto L60;
+L40:
+    i__1 = mk1;
+    for (l = 1; l <= i__1; ++l) {
+	tx[i__] = (x[j] + x[j - 1]) * half;
+	++i__;
+	++j;
+/* L50: */
+    }
+/*  the knots in the y-direction. */
+L60:
+    mk1 = *my - ky1;
+    if (mk1 == 0) {
+	goto L120;
+    }
+    k3 = *ky / 2;
+    i__ = ky1 + 1;
+    j = k3 + 2;
+    if (k3 << 1 == *ky) {
+	goto L80;
+    }
+    i__1 = mk1;
+    for (l = 1; l <= i__1; ++l) {
+	ty[i__] = y[j];
+	++i__;
+	++j;
+/* L70: */
+    }
+    goto L120;
+L80:
+    i__1 = mk1;
+    for (l = 1; l <= i__1; ++l) {
+	ty[i__] = (y[j] + y[j - 1]) * half;
+	++i__;
+	++j;
+/* L90: */
+    }
+    goto L120;
+/*  if s > 0 our initial choice of knots depends on the value of iopt. */
+L100:
+    if (*iopt == 0) {
+	goto L115;
+    }
+    if (*fp0 <= *s) {
+	goto L115;
+    }
+/*  if iopt=1 and fp0 > s we start computing the least- squares spline */
+/*  according to the set of knots found at the last call of the routine. */
+/*  we determine the number of grid coordinates x(i) inside each knot */
+/*  interval (tx(l),tx(l+1)). */
+    l = kx2;
+    j = 1;
+    nrdatx[1] = 0;
+    mpm = *mx - 1;
+    i__1 = mpm;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	++nrdatx[j];
+	if (x[i__] < tx[l]) {
+	    goto L105;
+	}
+	--nrdatx[j];
+	++l;
+	++j;
+	nrdatx[j] = 0;
+L105:
+	;
+    }
+/*  we determine the number of grid coordinates y(i) inside each knot */
+/*  interval (ty(l),ty(l+1)). */
+    l = ky2;
+    j = 1;
+    nrdaty[1] = 0;
+    mpm = *my - 1;
+    i__1 = mpm;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	++nrdaty[j];
+	if (y[i__] < ty[l]) {
+	    goto L110;
+	}
+	--nrdaty[j];
+	++l;
+	++j;
+	nrdaty[j] = 0;
+L110:
+	;
+    }
+    goto L120;
+/*  if iopt=0 or iopt=1 and s>=fp0, we start computing the least-squares */
+/*  polynomial of degree kx in x and ky in y (which is a spline without */
+/*  interior knots). */
+L115:
+    *nx = nminx;
+    *ny = nminy;
+    nrdatx[1] = *mx - 2;
+    nrdaty[1] = *my - 2;
+    *lastdi = 0;
+    *nplusx = 0;
+    *nplusy = 0;
+    *fp0 = (float)0.;
+    *fpold = (float)0.;
+    *reducx = (float)0.;
+    *reducy = (float)0.;
+L120:
+    mpm = *mx + *my;
+    ifsx = 0;
+    ifsy = 0;
+    ifbx = 0;
+    ifby = 0;
+    p = -one;
+/*  main loop for the different sets of knots.mpm=mx+my is a save upper */
+/*  bound for the number of trials. */
+    i__1 = mpm;
+    for (iter = 1; iter <= i__1; ++iter) {
+	if (*nx == nminx && *ny == nminy) {
+	    *ier = -2;
+	}
+/*  find nrintx (nrinty) which is the number of knot intervals in the */
+/*  x-direction (y-direction). */
+	nrintx = *nx - nminx + 1;
+	nrinty = *ny - nminy + 1;
+/*  find ncof, the number of b-spline coefficients for the current set */
+/*  of knots. */
+	nk1x = *nx - kx1;
+	nk1y = *ny - ky1;
+	ncof = nk1x * nk1y;
+/*  find the position of the additional knots which are needed for the */
+/*  b-spline representation of s(x,y). */
+	i__ = *nx;
+	i__2 = kx1;
+	for (j = 1; j <= i__2; ++j) {
+	    tx[j] = *xb;
+	    tx[i__] = *xe;
+	    --i__;
+/* L130: */
+	}
+	i__ = *ny;
+	i__2 = ky1;
+	for (j = 1; j <= i__2; ++j) {
+	    ty[j] = *yb;
+	    ty[i__] = *ye;
+	    --i__;
+/* L140: */
+	}
+/*  find the least-squares spline sinf(x,y) and calculate for each knot */
+/*  interval tx(j+kx)<=x<=tx(j+kx+1) (ty(j+ky)<=y<=ty(j+ky+1)) the sum */
+/*  of squared residuals fpintx(j),j=1,2,...,nx-2*kx-1 (fpinty(j),j=1,2, */
+/*  ...,ny-2*ky-1) for the data points having their absciss (ordinate)- */
+/*  value belonging to that interval. */
+/*  fp gives the total sum of squared residuals. */
+	fpgrre_(&ifsx, &ifsy, &ifbx, &ifby, &x[1], mx, &y[1], my, &z__[1], mz,
+		 kx, ky, &tx[1], nx, &ty[1], ny, &p, &c__[1], nc, fp, &fpintx[
+		1], &fpinty[1], &mm, &mynx, &kx1, &kx2, &ky1, &ky2, &wrk[lsx],
+		 &wrk[lsy], &wrk[lri], &wrk[lq], &wrk[lax], &wrk[lay], &wrk[
+		lbx], &wrk[lby], &nrx[1], &nry[1]);
+	if (*ier == -2) {
+	    *fp0 = *fp;
+	}
+/*  test whether the least-squares spline is an acceptable solution. */
+	if (*iopt < 0) {
+	    goto L440;
+	}
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  if f(p=inf) < s, we accept the choice of knots. */
+	if (fpms < (float)0.) {
+	    goto L300;
+	}
+/*  if nx=nmaxx and ny=nmaxy, sinf(x,y) is an interpolating spline. */
+	if (*nx == nmaxx && *ny == nmaxy) {
+	    goto L430;
+	}
+/*  increase the number of knots. */
+/*  if nx=nxe and ny=nye we cannot further increase the number of knots */
+/*  because of the storage capacity limitation. */
+	if (*nx == nxe && *ny == nye) {
+	    goto L420;
+	}
+	*ier = 0;
+/*  adjust the parameter reducx or reducy according to the direction */
+/*  in which the last added knots were located. */
+	if (*lastdi < 0) {
+	    goto L150;
+	} else if (*lastdi == 0) {
+	    goto L170;
+	} else {
+	    goto L160;
+	}
+L150:
+	*reducx = *fpold - *fp;
+	goto L170;
+L160:
+	*reducy = *fpold - *fp;
+/*  store the sum of squared residuals for the current set of knots. */
+L170:
+	*fpold = *fp;
+/*  find nplx, the number of knots we should add in the x-direction. */
+	nplx = 1;
+	if (*nx == nminx) {
+	    goto L180;
+	}
+	npl1 = *nplusx << 1;
+	rn = (real) (*nplusx);
+	if (*reducx > acc) {
+	    npl1 = rn * fpms / *reducx;
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__4 = npl1, i__5 = *nplusx / 2, i__4 = max(i__4,i__5);
+	i__2 = *nplusx << 1, i__3 = max(i__4,1);
+	nplx = min(i__2,i__3);
+/*  find nply, the number of knots we should add in the y-direction. */
+L180:
+	nply = 1;
+	if (*ny == nminy) {
+	    goto L190;
+	}
+	npl1 = *nplusy << 1;
+	rn = (real) (*nplusy);
+	if (*reducy > acc) {
+	    npl1 = rn * fpms / *reducy;
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__4 = npl1, i__5 = *nplusy / 2, i__4 = max(i__4,i__5);
+	i__2 = *nplusy << 1, i__3 = max(i__4,1);
+	nply = min(i__2,i__3);
+L190:
+	if ((i__2 = nplx - nply) < 0) {
+	    goto L210;
+	} else if (i__2 == 0) {
+	    goto L200;
+	} else {
+	    goto L230;
+	}
+L200:
+	if (*lastdi < 0) {
+	    goto L230;
+	}
+L210:
+	if (*nx == nxe) {
+	    goto L230;
+	}
+/*  addition in the x-direction. */
+	*lastdi = -1;
+	*nplusx = nplx;
+	ifsx = 0;
+	i__2 = *nplusx;
+	for (l = 1; l <= i__2; ++l) {
+/*  add a new knot in the x-direction */
+	    fpknot_(&x[1], mx, &tx[1], nx, &fpintx[1], &nrdatx[1], &nrintx, 
+		    nxest, &c__1);
+/*  test whether we cannot further increase the number of knots in the */
+/*  x-direction. */
+	    if (*nx == nxe) {
+		goto L250;
+	    }
+/* L220: */
+	}
+	goto L250;
+L230:
+	if (*ny == nye) {
+	    goto L210;
+	}
+/*  addition in the y-direction. */
+	*lastdi = 1;
+	*nplusy = nply;
+	ifsy = 0;
+	i__2 = *nplusy;
+	for (l = 1; l <= i__2; ++l) {
+/*  add a new knot in the y-direction. */
+	    fpknot_(&y[1], my, &ty[1], ny, &fpinty[1], &nrdaty[1], &nrinty, 
+		    nyest, &c__1);
+/*  test whether we cannot further increase the number of knots in the */
+/*  y-direction. */
+	    if (*ny == nye) {
+		goto L250;
+	    }
+/* L240: */
+	}
+/*  restart the computations with the new set of knots. */
+L250:
+	;
+    }
+/*  test whether the least-squares polynomial is a solution of our */
+/*  approximation problem. */
+L300:
+    if (*ier == -2) {
+	goto L440;
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/* part 2: determination of the smoothing spline sp(x,y)                c */
+/* *****************************************************                c */
+/*  we have determined the number of knots and their position. we now   c */
+/*  compute the b-spline coefficients of the smoothing spline sp(x,y).  c */
+/*  this smoothing spline varies with the parameter p in such a way thatc */
+/*    f(p) = sumi=1,mx(sumj=1,my((z(i,j)-sp(x(i),y(j)))**2)             c */
+/*  is a continuous, strictly decreasing function of p. moreover the    c */
+/*  least-squares polynomial corresponds to p=0 and the least-squares   c */
+/*  spline to p=infinity. iteratively we then have to determine the     c */
+/*  positive value of p such that f(p)=s. the process which is proposed c */
+/*  here makes use of rational interpolation. f(p) is approximated by a c */
+/*  rational function r(p)=(u*p+v)/(p+w); three values of p (p1,p2,p3)  c */
+/*  with corresponding values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s)c */
+/*  are used to calculate the new value of p such that r(p)=s.          c */
+/*  convergence is guaranteed by taking f1 > 0 and f3 < 0.              c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  initial value for p. */
+    p1 = (float)0.;
+    f1 = *fp0 - *s;
+    p3 = -one;
+    f3 = fpms;
+    p = one;
+    ich1 = 0;
+    ich3 = 0;
+/*  iteration process to find the root of f(p)=s. */
+    i__1 = *maxit;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  find the smoothing spline sp(x,y) and the corresponding sum of */
+/*  squared residuals fp. */
+	fpgrre_(&ifsx, &ifsy, &ifbx, &ifby, &x[1], mx, &y[1], my, &z__[1], mz,
+		 kx, ky, &tx[1], nx, &ty[1], ny, &p, &c__[1], nc, fp, &fpintx[
+		1], &fpinty[1], &mm, &mynx, &kx1, &kx2, &ky1, &ky2, &wrk[lsx],
+		 &wrk[lsy], &wrk[lri], &wrk[lq], &wrk[lax], &wrk[lay], &wrk[
+		lbx], &wrk[lby], &nrx[1], &nry[1]);
+/*  test whether the approximation sp(x,y) is an acceptable solution. */
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  test whether the maximum allowable number of iterations has been */
+/*  reached. */
+	if (iter == *maxit) {
+	    goto L400;
+	}
+/*  carry out one more step of the iteration process. */
+	p2 = p;
+	f2 = fpms;
+	if (ich3 != 0) {
+	    goto L320;
+	}
+	if (f2 - f3 > acc) {
+	    goto L310;
+	}
+/*  our initial choice of p is too large. */
+	p3 = p2;
+	f3 = f2;
+	p *= con4;
+	if (p <= p1) {
+	    p = p1 * con9 + p2 * con1;
+	}
+	goto L350;
+L310:
+	if (f2 < (float)0.) {
+	    ich3 = 1;
+	}
+L320:
+	if (ich1 != 0) {
+	    goto L340;
+	}
+	if (f1 - f2 > acc) {
+	    goto L330;
+	}
+/*  our initial choice of p is too small */
+	p1 = p2;
+	f1 = f2;
+	p /= con4;
+	if (p3 < (float)0.) {
+	    goto L350;
+	}
+	if (p >= p3) {
+	    p = p2 * con1 + p3 * con9;
+	}
+	goto L350;
+/*  test whether the iteration process proceeds as theoretically */
+/*  expected. */
+L330:
+	if (f2 > (float)0.) {
+	    ich1 = 1;
+	}
+L340:
+	if (f2 >= f1 || f2 <= f3) {
+	    goto L410;
+	}
+/*  find the new value of p. */
+	p = fprati_(&p1, &f1, &p2, &f2, &p3, &f3);
+L350:
+	;
+    }
+/*  error codes and messages. */
+L400:
+    *ier = 3;
+    goto L440;
+L410:
+    *ier = 2;
+    goto L440;
+L420:
+    *ier = 1;
+    goto L440;
+L430:
+    *ier = -1;
+    *fp = (float)0.;
+L440:
+    return 0;
+} /* fpregr_ */
+
+/* Subroutine */ int fprota_(cos__, sin__, a, b)
+real *cos__, *sin__, *a, *b;
+{
+    static real stor1, stor2;
+
+/*  subroutine fprota applies a givens rotation to a and b. */
+/*  .. */
+/*  ..scalar arguments.. */
+/* ..local scalars.. */
+/*  .. */
+    stor1 = *a;
+    stor2 = *b;
+    *b = *cos__ * stor2 + *sin__ * stor1;
+    *a = *cos__ * stor1 - *sin__ * stor2;
+    return 0;
+} /* fprota_ */
+
+/* Subroutine */ int fprppo_(nu, nv, if1, if2, cosi, ratio, c__, f, ncoff)
+integer *nu, *nv, *if1, *if2;
+real *cosi, *ratio, *c__, *f;
+integer *ncoff;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static integer iopt, i__, j, k, l, ii, nu4, nvv;
+
+/*  given the coefficients of a constrained bicubic spline, as determined */
+/*  in subroutine fppola, subroutine fprppo calculates the coefficients */
+/*  in the standard b-spline representation of bicubic splines. */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    cosi -= 6;
+    --f;
+    --c__;
+
+    /* Function Body */
+    nu4 = *nu - 4;
+    nvv = *nv - 7;
+    iopt = *if1 + 1;
+    i__1 = *ncoff;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	f[i__] = (float)0.;
+/* L10: */
+    }
+    i__ = 0;
+    i__1 = nu4;
+    for (l = 1; l <= i__1; ++l) {
+	ii = i__;
+	if (l > iopt) {
+	    goto L80;
+	}
+	switch ((int)l) {
+	    case 1:  goto L20;
+	    case 2:  goto L40;
+	    case 3:  goto L60;
+	}
+L20:
+	i__2 = nvv;
+	for (k = 1; k <= i__2; ++k) {
+	    ++i__;
+	    f[i__] = c__[1];
+/* L30: */
+	}
+	j = 1;
+	goto L100;
+L40:
+	i__2 = nvv;
+	for (k = 1; k <= i__2; ++k) {
+	    ++i__;
+	    f[i__] = c__[1] + c__[2] * cosi[k * 5 + 1] + c__[3] * cosi[k * 5 
+		    + 2];
+/* L50: */
+	}
+	j = 3;
+	goto L100;
+L60:
+	i__2 = nvv;
+	for (k = 1; k <= i__2; ++k) {
+	    ++i__;
+	    f[i__] = c__[1] + *ratio * (c__[2] * cosi[k * 5 + 1] + c__[3] * 
+		    cosi[k * 5 + 2]) + c__[4] * cosi[k * 5 + 3] + c__[5] * 
+		    cosi[k * 5 + 4] + c__[6] * cosi[k * 5 + 5];
+/* L70: */
+	}
+	j = 6;
+	goto L100;
+L80:
+	if (l == nu4 && *if2 != 0) {
+	    goto L120;
+	}
+	i__2 = nvv;
+	for (k = 1; k <= i__2; ++k) {
+	    ++i__;
+	    ++j;
+	    f[i__] = c__[j];
+/* L90: */
+	}
+L100:
+	for (k = 1; k <= 3; ++k) {
+	    ++ii;
+	    ++i__;
+	    f[i__] = f[ii];
+/* L110: */
+	}
+L120:
+	;
+    }
+    i__1 = *ncoff;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = f[i__];
+/* L130: */
+    }
+    return 0;
+} /* fprppo_ */
+
+/* Subroutine */ int fprpsp_(nt, np, co, si, c__, f, ncoff)
+integer *nt, *np;
+real *co, *si, *c__, *f;
+integer *ncoff;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static integer ncof, i__, j, k, l;
+    static real c1, c2, c3, cn;
+    static integer ii, np4, nt4, npp;
+
+/*  given the coefficients of a spherical spline function, subroutine */
+/*  fprpsp calculates the coefficients in the standard b-spline re- */
+/*  presentation of this bicubic spline. */
+/*  .. */
+/*  ..scalar arguments */
+/*  ..array arguments */
+/*  ..local scalars */
+/*  .. */
+    /* Parameter adjustments */
+    --si;
+    --co;
+    --f;
+    --c__;
+
+    /* Function Body */
+    nt4 = *nt - 4;
+    np4 = *np - 4;
+    npp = np4 - 3;
+    ncof = npp * (nt4 - 4) + 6;
+    c1 = c__[1];
+    cn = c__[ncof];
+    j = *ncoff;
+    i__1 = np4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	f[i__] = c1;
+	f[j] = cn;
+	--j;
+/* L10: */
+    }
+    i__ = np4;
+    j = 1;
+    i__1 = nt4;
+    for (l = 3; l <= i__1; ++l) {
+	ii = i__;
+	if (l == 3 || l == nt4) {
+	    goto L30;
+	}
+	i__2 = npp;
+	for (k = 1; k <= i__2; ++k) {
+	    ++i__;
+	    ++j;
+	    f[i__] = c__[j];
+/* L20: */
+	}
+	goto L50;
+L30:
+	if (l == nt4) {
+	    c1 = cn;
+	}
+	c2 = c__[j + 1];
+	c3 = c__[j + 2];
+	j += 2;
+	i__2 = npp;
+	for (k = 1; k <= i__2; ++k) {
+	    ++i__;
+	    f[i__] = c1 + c2 * co[k] + c3 * si[k];
+/* L40: */
+	}
+L50:
+	for (k = 1; k <= 3; ++k) {
+	    ++ii;
+	    ++i__;
+	    f[i__] = f[ii];
+/* L60: */
+	}
+/* L70: */
+    }
+    i__1 = *ncoff;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	c__[i__] = f[i__];
+/* L80: */
+    }
+    return 0;
+} /* fprpsp_ */
+
+/* Subroutine */ int fpseno_(maxtr, up, left, right, info, merk, ibind, nbind)
+integer *maxtr, *up, *left, *right, *info, *merk, *ibind, *nbind;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__, j, k;
+
+/*  subroutine fpseno fetches a branch of a triply linked tree the */
+/*  information of which is kept in the arrays up,left,right and info. */
+/*  the branch has a specified length nbind and is determined by the */
+/*  parameter merk which points to its terminal node. the information */
+/*  field of the nodes of this branch is stored in the array ibind. on */
+/*  exit merk points to a new branch of length nbind or takes the value */
+/*  1 if no such branch was found. */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..scalar arguments.. */
+/*  .. */
+    /* Parameter adjustments */
+    --info;
+    --right;
+    --left;
+    --up;
+    --ibind;
+
+    /* Function Body */
+    k = *merk;
+    j = *nbind;
+    i__1 = *nbind;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	ibind[j] = info[k];
+	k = up[k];
+	--j;
+/* L10: */
+    }
+L20:
+    k = right[*merk];
+    if (k != 0) {
+	goto L30;
+    }
+    *merk = up[*merk];
+    if (*merk - 1 <= 0) {
+	goto L40;
+    } else {
+	goto L20;
+    }
+L30:
+    *merk = k;
+    k = left[*merk];
+    if (k != 0) {
+	goto L30;
+    }
+L40:
+    return 0;
+} /* fpseno_ */
+
+/* Subroutine */ int fpspgr_(iopt, ider, u, mu, v, mv, r__, mr, r0, r1, s, 
+	nuest, nvest, tol, maxit, nc, nu, tu, nv, tv, c__, fp, fp0, fpold, 
+	reducu, reducv, fpintu, fpintv, dr, step, lastdi, nplusu, nplusv, 
+	lastu0, lastu1, nru, nrv, nrdatu, nrdatv, wrk, lwrk, ier)
+integer *iopt, *ider;
+real *u;
+integer *mu;
+real *v;
+integer *mv;
+real *r__;
+integer *mr;
+real *r0, *r1, *s;
+integer *nuest, *nvest;
+real *tol;
+integer *maxit, *nc, *nu;
+real *tu;
+integer *nv;
+real *tv, *c__, *fp, *fp0, *fpold, *reducu, *reducv, *fpintu, *fpintv, *dr, *
+	step;
+integer *lastdi, *nplusu, *nplusv, *lastu0, *lastu1, *nru, *nrv, *nrdatu, *
+	nrdatv;
+real *wrk;
+integer *lwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3, i__4, i__5;
+    real r__1;
+
+    /* Builtin functions */
+    double atan2();
+
+    /* Local variables */
+    static integer ifbu, ifbv, iter;
+    static real fpms, rmin, rmax;
+    static integer ifsu, ifsv, nplu, nplv, i__, j, l;
+    static real p;
+    static integer mumin;
+    static real f1, f2, f3;
+    static integer i1, i2, numax, l1, l2;
+    static real p1, p2, p3;
+    static integer l3, l4, nvmax;
+    static real vb, pi, ve;
+    static integer nn;
+    static real rn;
+    static integer ju;
+    extern doublereal fprati_();
+    extern /* Subroutine */ int fpknot_();
+    static integer istart;
+    extern /* Subroutine */ int fpopsp_();
+    static integer nrintu, nrintv, mu0, mu1;
+    static real acc;
+    static integer idd[4];
+    static real one, per;
+    static integer nue, nve, mpm;
+    static real drr[6];
+    static integer ktu, ich1, ich3;
+    static real con1, con4, con9;
+    static integer npl1;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpknot,fpopsp */
+/*  .. */
+/*   set constants */
+    /* Parameter adjustments */
+    --iopt;
+    --ider;
+    --nru;
+    --u;
+    --nrv;
+    --v;
+    --r__;
+    --nrdatu;
+    --fpintu;
+    --tu;
+    --nrdatv;
+    --fpintv;
+    --tv;
+    --c__;
+    --dr;
+    --step;
+    --wrk;
+
+    /* Function Body */
+    one = (float)1.;
+    con1 = (float).1;
+    con9 = (float).9;
+    con4 = (float).04;
+/*   initialization */
+    ifsu = 0;
+    ifsv = 0;
+    ifbu = 0;
+    ifbv = 0;
+    p = -one;
+    mumin = 4;
+    if (ider[1] >= 0) {
+	--mumin;
+    }
+    if (iopt[2] == 1 && ider[2] == 1) {
+	--mumin;
+    }
+    if (ider[3] >= 0) {
+	--mumin;
+    }
+    if (iopt[3] == 1 && ider[4] == 1) {
+	--mumin;
+    }
+    if (mumin == 0) {
+	mumin = 1;
+    }
+    pi = atan2((float)0., -one);
+    per = pi + pi;
+    vb = v[1];
+    ve = vb + per;
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/* part 1: determination of the number of knots and their position.     c */
+/* ****************************************************************     c */
+/*  given a set of knots we compute the least-squares spline sinf(u,v)  c */
+/*  and the corresponding sum of squared residuals fp = f(p=inf).       c */
+/*  if iopt(1)=-1  sinf(u,v) is the requested approximation.            c */
+/*  if iopt(1)>=0  we check whether we can accept the knots:            c */
+/*    if fp <= s we will continue with the current set of knots.        c */
+/*    if fp >  s we will increase the number of knots and compute the   c */
+/*       corresponding least-squares spline until finally fp <= s.      c */
+/*    the initial choice of knots depends on the value of s and iopt.   c */
+/*    if s=0 we have spline interpolation; in that case the number of   c */
+/*     knots in the u-direction equals nu=numax=mu+6+iopt(2)+iopt(3)    c */
+/*     and in the v-direction nv=nvmax=mv+7.                            c */
+/*    if s>0 and                                                        c */
+/*      iopt(1)=0 we first compute the least-squares polynomial,i.e. a  c */
+/*       spline without interior knots : nu=8 ; nv=8.                   c */
+/*      iopt(1)=1 we start with the set of knots found at the last call c */
+/*       of the routine, except for the case that s > fp0; then we      c */
+/*       compute the least-squares polynomial directly.                 c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+    if (iopt[1] < 0) {
+	goto L120;
+    }
+/*  acc denotes the absolute tolerance for the root of f(p)=s. */
+    acc = *tol * *s;
+/*  numax and nvmax denote the number of knots needed for interpolation. */
+    numax = *mu + 6 + iopt[2] + iopt[3];
+    nvmax = *mv + 7;
+    nue = min(numax,*nuest);
+    nve = min(nvmax,*nvest);
+    if (*s > (float)0.) {
+	goto L100;
+    }
+/*  if s = 0, s(u,v) is an interpolating spline. */
+    *nu = numax;
+    *nv = nvmax;
+/*  test whether the required storage space exceeds the available one. */
+    if (*nu > *nuest || *nv > *nvest) {
+	goto L420;
+    }
+/*  find the position of the knots in the v-direction. */
+    i__1 = *mv;
+    for (l = 1; l <= i__1; ++l) {
+	tv[l + 3] = v[l];
+/* L10: */
+    }
+    tv[*mv + 4] = ve;
+    l1 = *mv - 2;
+    l2 = *mv + 5;
+    for (i__ = 1; i__ <= 3; ++i__) {
+	tv[i__] = v[l1] - per;
+	tv[l2] = v[i__ + 1] + per;
+	++l1;
+	++l2;
+/* L20: */
+    }
+/*  if not all the derivative values g(i,j) are given, we will first */
+/*  estimate these values by computing a least-squares spline */
+    idd[0] = ider[1];
+    if (idd[0] == 0) {
+	idd[0] = 1;
+    }
+    if (idd[0] > 0) {
+	dr[1] = *r0;
+    }
+    idd[1] = ider[2];
+    idd[2] = ider[3];
+    if (idd[2] == 0) {
+	idd[2] = 1;
+    }
+    if (idd[2] > 0) {
+	dr[4] = *r1;
+    }
+    idd[3] = ider[4];
+    if (ider[1] < 0 || ider[3] < 0) {
+	goto L30;
+    }
+    if (iopt[2] != 0 && ider[2] == 0) {
+	goto L30;
+    }
+    if (iopt[3] == 0 || ider[4] != 0) {
+	goto L70;
+    }
+/* we set up the knots in the u-direction for computing the least-squares */
+/* spline. */
+L30:
+    i1 = 3;
+    i2 = *mu - 2;
+    *nu = 4;
+    i__1 = *mu;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (i1 > i2) {
+	    goto L50;
+	}
+	++(*nu);
+	tu[*nu] = u[i1];
+	i1 += 2;
+/* L40: */
+    }
+L50:
+    for (i__ = 1; i__ <= 4; ++i__) {
+	tu[i__] = (float)0.;
+	++(*nu);
+	tu[*nu] = pi;
+/* L60: */
+    }
+/* we compute the least-squares spline for estimating the derivatives. */
+    fpopsp_(&ifsu, &ifsv, &ifbu, &ifbv, &u[1], mu, &v[1], mv, &r__[1], mr, r0,
+	     r1, &dr[1], &iopt[1], idd, &tu[1], nu, &tv[1], nv, nuest, nvest, 
+	    &p, &step[1], &c__[1], nc, fp, &fpintu[1], &fpintv[1], &nru[1], &
+	    nrv[1], &wrk[1], lwrk);
+    ifsu = 0;
+/* if all the derivatives at the origin are known, we compute the */
+/* interpolating spline. */
+/* we set up the knots in the u-direction, needed for interpolation. */
+L70:
+    nn = numax - 8;
+    if (nn == 0) {
+	goto L95;
+    }
+    ju = 2 - iopt[2];
+    i__1 = nn;
+    for (l = 1; l <= i__1; ++l) {
+	tu[l + 4] = u[ju];
+	++ju;
+/* L80: */
+    }
+    *nu = numax;
+    l = *nu;
+    for (i__ = 1; i__ <= 4; ++i__) {
+	tu[i__] = (float)0.;
+	tu[l] = pi;
+	--l;
+/* L90: */
+    }
+/* we compute the interpolating spline. */
+L95:
+    fpopsp_(&ifsu, &ifsv, &ifbu, &ifbv, &u[1], mu, &v[1], mv, &r__[1], mr, r0,
+	     r1, &dr[1], &iopt[1], idd, &tu[1], nu, &tv[1], nv, nuest, nvest, 
+	    &p, &step[1], &c__[1], nc, fp, &fpintu[1], &fpintv[1], &nru[1], &
+	    nrv[1], &wrk[1], lwrk);
+    goto L430;
+/*  if s>0 our initial choice of knots depends on the value of iopt(1). */
+L100:
+    *ier = 0;
+    if (iopt[1] == 0) {
+	goto L115;
+    }
+    step[1] = -step[1];
+    step[2] = -step[2];
+    if (*fp0 <= *s) {
+	goto L115;
+    }
+/*  if iopt(1)=1 and fp0 > s we start computing the least-squares spline */
+/*  according to the set of knots found at the last call of the routine. */
+/*  we determine the number of grid coordinates u(i) inside each knot */
+/*  interval (tu(l),tu(l+1)). */
+    l = 5;
+    j = 1;
+    nrdatu[1] = 0;
+    mu0 = 2 - iopt[2];
+    mu1 = *mu - 1 + iopt[3];
+    i__1 = mu1;
+    for (i__ = mu0; i__ <= i__1; ++i__) {
+	++nrdatu[j];
+	if (u[i__] < tu[l]) {
+	    goto L105;
+	}
+	--nrdatu[j];
+	++l;
+	++j;
+	nrdatu[j] = 0;
+L105:
+	;
+    }
+/*  we determine the number of grid coordinates v(i) inside each knot */
+/*  interval (tv(l),tv(l+1)). */
+    l = 5;
+    j = 1;
+    nrdatv[1] = 0;
+    i__1 = *mv;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	++nrdatv[j];
+	if (v[i__] < tv[l]) {
+	    goto L110;
+	}
+	--nrdatv[j];
+	++l;
+	++j;
+	nrdatv[j] = 0;
+L110:
+	;
+    }
+    idd[0] = ider[1];
+    idd[1] = ider[2];
+    idd[2] = ider[3];
+    idd[3] = ider[4];
+    goto L120;
+/*  if iopt(1)=0 or iopt(1)=1 and s >= fp0,we start computing the least- */
+/*  squares polynomial (which is a spline without interior knots). */
+L115:
+    *ier = -2;
+    idd[0] = ider[1];
+    idd[1] = 1;
+    idd[2] = ider[3];
+    idd[3] = 1;
+    *nu = 8;
+    *nv = 8;
+    nrdatu[1] = *mu - 2 + iopt[2] + iopt[3];
+    nrdatv[1] = *mv - 1;
+    *lastdi = 0;
+    *nplusu = 0;
+    *nplusv = 0;
+    *fp0 = (float)0.;
+    *fpold = (float)0.;
+    *reducu = (float)0.;
+    *reducv = (float)0.;
+/*  main loop for the different sets of knots.mpm=mu+mv is a save upper */
+/*  bound for the number of trials. */
+L120:
+    mpm = *mu + *mv;
+    i__1 = mpm;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  find nrintu (nrintv) which is the number of knot intervals in the */
+/*  u-direction (v-direction). */
+	nrintu = *nu - 7;
+	nrintv = *nv - 7;
+/*  find the position of the additional knots which are needed for the */
+/*  b-spline representation of s(u,v). */
+	i__ = *nu;
+	for (j = 1; j <= 4; ++j) {
+	    tu[j] = (float)0.;
+	    tu[i__] = pi;
+	    --i__;
+/* L125: */
+	}
+	l1 = 4;
+	l2 = l1;
+	l3 = *nv - 3;
+	l4 = l3;
+	tv[l2] = vb;
+	tv[l3] = ve;
+	for (j = 1; j <= 3; ++j) {
+	    ++l1;
+	    --l2;
+	    ++l3;
+	    --l4;
+	    tv[l2] = tv[l4] - per;
+	    tv[l3] = tv[l1] + per;
+/* L130: */
+	}
+/*  find an estimate of the range of possible values for the optimal */
+/*  derivatives at the origin. */
+	ktu = nrdatu[1] + 2 - iopt[2];
+	if (ktu < mumin) {
+	    ktu = mumin;
+	}
+	if (ktu == *lastu0) {
+	    goto L140;
+	}
+	rmin = *r0;
+	rmax = *r0;
+	l = *mv * ktu;
+	i__2 = l;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    if (r__[i__] < rmin) {
+		rmin = r__[i__];
+	    }
+	    if (r__[i__] > rmax) {
+		rmax = r__[i__];
+	    }
+/* L135: */
+	}
+	step[1] = rmax - rmin;
+	*lastu0 = ktu;
+L140:
+	ktu = nrdatu[nrintu] + 2 - iopt[3];
+	if (ktu < mumin) {
+	    ktu = mumin;
+	}
+	if (ktu == *lastu1) {
+	    goto L150;
+	}
+	rmin = *r1;
+	rmax = *r1;
+	l = *mv * ktu;
+	j = *mr;
+	i__2 = l;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    if (r__[j] < rmin) {
+		rmin = r__[j];
+	    }
+	    if (r__[j] > rmax) {
+		rmax = r__[j];
+	    }
+	    --j;
+/* L145: */
+	}
+	step[2] = rmax - rmin;
+	*lastu1 = ktu;
+/*  find the least-squares spline sinf(u,v). */
+L150:
+	fpopsp_(&ifsu, &ifsv, &ifbu, &ifbv, &u[1], mu, &v[1], mv, &r__[1], mr,
+		 r0, r1, &dr[1], &iopt[1], idd, &tu[1], nu, &tv[1], nv, nuest,
+		 nvest, &p, &step[1], &c__[1], nc, fp, &fpintu[1], &fpintv[1],
+		 &nru[1], &nrv[1], &wrk[1], lwrk);
+	if (step[1] < (float)0.) {
+	    step[1] = -step[1];
+	}
+	if (step[2] < (float)0.) {
+	    step[2] = -step[2];
+	}
+	if (*ier == -2) {
+	    *fp0 = *fp;
+	}
+/*  test whether the least-squares spline is an acceptable solution. */
+	if (iopt[1] < 0) {
+	    goto L440;
+	}
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  if f(p=inf) < s, we accept the choice of knots. */
+	if (fpms < (float)0.) {
+	    goto L300;
+	}
+/*  if nu=numax and nv=nvmax, sinf(u,v) is an interpolating spline */
+	if (*nu == numax && *nv == nvmax) {
+	    goto L430;
+	}
+/*  increase the number of knots. */
+/*  if nu=nue and nv=nve we cannot further increase the number of knots */
+/*  because of the storage capacity limitation. */
+	if (*nu == nue && *nv == nve) {
+	    goto L420;
+	}
+	if (ider[1] == 0) {
+/* Computing 2nd power */
+	    r__1 = *r0 - dr[1];
+	    fpintu[1] += r__1 * r__1;
+	}
+	if (ider[3] == 0) {
+/* Computing 2nd power */
+	    r__1 = *r1 - dr[4];
+	    fpintu[nrintu] += r__1 * r__1;
+	}
+	*ier = 0;
+/*  adjust the parameter reducu or reducv according to the direction */
+/*  in which the last added knots were located. */
+	if (*lastdi < 0) {
+	    goto L160;
+	} else if (*lastdi == 0) {
+	    goto L155;
+	} else {
+	    goto L170;
+	}
+L155:
+	nplv = 3;
+	idd[1] = ider[2];
+	idd[3] = ider[4];
+	*fpold = *fp;
+	goto L230;
+L160:
+	*reducu = *fpold - *fp;
+	goto L175;
+L170:
+	*reducv = *fpold - *fp;
+/*  store the sum of squared residuals for the current set of knots. */
+L175:
+	*fpold = *fp;
+/*  find nplu, the number of knots we should add in the u-direction. */
+	nplu = 1;
+	if (*nu == 8) {
+	    goto L180;
+	}
+	npl1 = *nplusu << 1;
+	rn = (real) (*nplusu);
+	if (*reducu > acc) {
+	    npl1 = rn * fpms / *reducu;
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__4 = npl1, i__5 = *nplusu / 2, i__4 = max(i__4,i__5);
+	i__2 = *nplusu << 1, i__3 = max(i__4,1);
+	nplu = min(i__2,i__3);
+/*  find nplv, the number of knots we should add in the v-direction. */
+L180:
+	nplv = 3;
+	if (*nv == 8) {
+	    goto L190;
+	}
+	npl1 = *nplusv << 1;
+	rn = (real) (*nplusv);
+	if (*reducv > acc) {
+	    npl1 = rn * fpms / *reducv;
+	}
+/* Computing MIN */
+/* Computing MAX */
+	i__4 = npl1, i__5 = *nplusv / 2, i__4 = max(i__4,i__5);
+	i__2 = *nplusv << 1, i__3 = max(i__4,1);
+	nplv = min(i__2,i__3);
+/*  test whether we are going to add knots in the u- or v-direction. */
+L190:
+	if ((i__2 = nplu - nplv) < 0) {
+	    goto L210;
+	} else if (i__2 == 0) {
+	    goto L200;
+	} else {
+	    goto L230;
+	}
+L200:
+	if (*lastdi < 0) {
+	    goto L230;
+	}
+L210:
+	if (*nu == nue) {
+	    goto L230;
+	}
+/*  addition in the u-direction. */
+	*lastdi = -1;
+	*nplusu = nplu;
+	ifsu = 0;
+	istart = 0;
+	if (iopt[2] == 0) {
+	    istart = 1;
+	}
+	i__2 = *nplusu;
+	for (l = 1; l <= i__2; ++l) {
+/*  add a new knot in the u-direction */
+	    fpknot_(&u[1], mu, &tu[1], nu, &fpintu[1], &nrdatu[1], &nrintu, 
+		    nuest, &istart);
+/*  test whether we cannot further increase the number of knots in the */
+/*  u-direction. */
+	    if (*nu == nue) {
+		goto L270;
+	    }
+/* L220: */
+	}
+	goto L270;
+L230:
+	if (*nv == nve) {
+	    goto L210;
+	}
+/*  addition in the v-direction. */
+	*lastdi = 1;
+	*nplusv = nplv;
+	ifsv = 0;
+	i__2 = *nplusv;
+	for (l = 1; l <= i__2; ++l) {
+/*  add a new knot in the v-direction. */
+	    fpknot_(&v[1], mv, &tv[1], nv, &fpintv[1], &nrdatv[1], &nrintv, 
+		    nvest, &c__1);
+/*  test whether we cannot further increase the number of knots in the */
+/*  v-direction. */
+	    if (*nv == nve) {
+		goto L270;
+	    }
+/* L240: */
+	}
+/*  restart the computations with the new set of knots. */
+L270:
+	;
+    }
+/*  test whether the least-squares polynomial is a solution of our */
+/*  approximation problem. */
+L300:
+    if (*ier == -2) {
+	goto L440;
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/* part 2: determination of the smoothing spline sp(u,v)                c */
+/* *****************************************************                c */
+/*  we have determined the number of knots and their position. we now   c */
+/*  compute the b-spline coefficients of the smoothing spline sp(u,v).  c */
+/*  this smoothing spline depends on the parameter p in such a way that c */
+/*    f(p) = sumi=1,mu(sumj=1,mv((z(i,j)-sp(u(i),v(j)))**2)             c */
+/*  is a continuous, strictly decreasing function of p. moreover the    c */
+/*  least-squares polynomial corresponds to p=0 and the least-squares   c */
+/*  spline to p=infinity. then iteratively we have to determine the     c */
+/*  positive value of p such that f(p)=s. the process which is proposed c */
+/*  here makes use of rational interpolation. f(p) is approximated by a c */
+/*  rational function r(p)=(u*p+v)/(p+w); three values of p (p1,p2,p3)  c */
+/*  with corresponding values of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s)c */
+/*  are used to calculate the new value of p such that r(p)=s.          c */
+/*  convergence is guaranteed by taking f1 > 0 and f3 < 0.              c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  initial value for p. */
+    p1 = (float)0.;
+    f1 = *fp0 - *s;
+    p3 = -one;
+    f3 = fpms;
+    p = one;
+    for (i__ = 1; i__ <= 6; ++i__) {
+	drr[i__ - 1] = dr[i__];
+/* L305: */
+    }
+    ich1 = 0;
+    ich3 = 0;
+/*  iteration process to find the root of f(p)=s. */
+    i__1 = *maxit;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  find the smoothing spline sp(u,v) and the corresponding sum f(p). */
+	fpopsp_(&ifsu, &ifsv, &ifbu, &ifbv, &u[1], mu, &v[1], mv, &r__[1], mr,
+		 r0, r1, drr, &iopt[1], idd, &tu[1], nu, &tv[1], nv, nuest, 
+		nvest, &p, &step[1], &c__[1], nc, fp, &fpintu[1], &fpintv[1], 
+		&nru[1], &nrv[1], &wrk[1], lwrk);
+/*  test whether the approximation sp(u,v) is an acceptable solution. */
+	fpms = *fp - *s;
+	if (dabs(fpms) < acc) {
+	    goto L440;
+	}
+/*  test whether the maximum allowable number of iterations has been */
+/*  reached. */
+	if (iter == *maxit) {
+	    goto L400;
+	}
+/*  carry out one more step of the iteration process. */
+	p2 = p;
+	f2 = fpms;
+	if (ich3 != 0) {
+	    goto L320;
+	}
+	if (f2 - f3 > acc) {
+	    goto L310;
+	}
+/*  our initial choice of p is too large. */
+	p3 = p2;
+	f3 = f2;
+	p *= con4;
+	if (p <= p1) {
+	    p = p1 * con9 + p2 * con1;
+	}
+	goto L350;
+L310:
+	if (f2 < (float)0.) {
+	    ich3 = 1;
+	}
+L320:
+	if (ich1 != 0) {
+	    goto L340;
+	}
+	if (f1 - f2 > acc) {
+	    goto L330;
+	}
+/*  our initial choice of p is too small */
+	p1 = p2;
+	f1 = f2;
+	p /= con4;
+	if (p3 < (float)0.) {
+	    goto L350;
+	}
+	if (p >= p3) {
+	    p = p2 * con1 + p3 * con9;
+	}
+	goto L350;
+/*  test whether the iteration process proceeds as theoretically */
+/*  expected. */
+L330:
+	if (f2 > (float)0.) {
+	    ich1 = 1;
+	}
+L340:
+	if (f2 >= f1 || f2 <= f3) {
+	    goto L410;
+	}
+/*  find the new value of p. */
+	p = fprati_(&p1, &f1, &p2, &f2, &p3, &f3);
+L350:
+	;
+    }
+/*  error codes and messages. */
+L400:
+    *ier = 3;
+    goto L440;
+L410:
+    *ier = 2;
+    goto L440;
+L420:
+    *ier = 1;
+    goto L440;
+L430:
+    *ier = -1;
+    *fp = (float)0.;
+L440:
+    return 0;
+} /* fpspgr_ */
+
+/* Subroutine */ int fpsphe_(iopt, m, teta, phi, r__, w, s, ntest, npest, eta,
+	 tol, maxit, ib1, ib3, nc, ncc, intest, nrest, nt, tt, np, tp, c__, 
+	fp, sup, fpint, coord, f, ff, row, coco, cosi, a, q, bt, bp, spt, spp,
+	 h__, index, nummer, wrk, lwrk, ier)
+integer *iopt, *m;
+real *teta, *phi, *r__, *w, *s;
+integer *ntest, *npest;
+real *eta, *tol;
+integer *maxit, *ib1, *ib3, *nc, *ncc, *intest, *nrest, *nt;
+real *tt;
+integer *np;
+real *tp, *c__, *fp, *sup, *fpint, *coord, *f, *ff, *row, *coco, *cosi, *a, *
+	q, *bt, *bp, *spt, *spp, *h__;
+integer *index, *nummer;
+real *wrk;
+integer *lwrk, *ier;
+{
+    /* System generated locals */
+    integer a_dim1, a_offset, q_dim1, q_offset, bt_dim1, bt_offset, bp_dim1, 
+	    bp_offset, spt_dim1, spt_offset, spp_dim1, spp_offset, i__1, i__2,
+	     i__3, i__4, i__5, i__6;
+    real r__1;
+
+    /* Builtin functions */
+    double atan(), sqrt(), cos(), sin();
+
+    /* Local variables */
+    static real half, facs;
+    static integer ncof;
+    static real dmax__;
+    static integer nreg, rank, iter;
+    static real fpms, pinv;
+    static integer irot, jrot, i__, j, l, iband;
+    static real p;
+    static integer ncoff;
+    static real sigma, fpmax, c1, d1, d2, f1, f2, f3, store;
+    static integer iband1, i1, iband3;
+    static real p1, p2, p3;
+    static integer iband4, i2, i3, j1, j2, lwest, l1, l2, l3, l4, nrint;
+    static real aa;
+    static integer la;
+    static real cn, co, fn;
+    static integer ii;
+    static real pi;
+    static integer ij;
+    static real ri, si;
+    static integer il, in;
+    static real wi, rn;
+    static integer lf;
+    static real sq;
+    static integer lh, ll, lp, lt;
+    static real ht[4], hp[4];
+    extern /* Subroutine */ int fpback_(), fpdisc_(), fporde_(), fprank_();
+    extern doublereal fprati_();
+    extern /* Subroutine */ int fpbspl_(), fprota_(), fpgivs_(), fprpsp_();
+    static real pi2;
+    static integer nr1, np4, nt4, nt6;
+    static real acc, arg, one, hti, htj, ten, eps;
+    static integer jlt, npp;
+    static real piv;
+    static integer num, nrr, ntt;
+    static real fac1, fac2;
+    static integer ich1, ich3;
+    static real con1, con4, con9;
+    static integer num1;
+    static real facc;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*   fpback,fpbspl,fpgivs,fpdisc,fporde,fprank,fprota,fprpsp */
+/*  .. */
+/*  set constants */
+    /* Parameter adjustments */
+    --nummer;
+    spp_dim1 = *m;
+    spp_offset = 1 + spp_dim1 * 1;
+    spp -= spp_offset;
+    spt_dim1 = *m;
+    spt_offset = 1 + spt_dim1 * 1;
+    spt -= spt_offset;
+    --w;
+    --r__;
+    --phi;
+    --teta;
+    bt_dim1 = *ntest;
+    bt_offset = 1 + bt_dim1 * 1;
+    bt -= bt_offset;
+    --tt;
+    bp_dim1 = *npest;
+    bp_offset = 1 + bp_dim1 * 1;
+    bp -= bp_offset;
+    --cosi;
+    --coco;
+    --row;
+    --tp;
+    --h__;
+    --ff;
+    --c__;
+    q_dim1 = *ncc;
+    q_offset = 1 + q_dim1 * 1;
+    q -= q_offset;
+    a_dim1 = *ncc;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+    --f;
+    --coord;
+    --fpint;
+    --index;
+    --wrk;
+
+    /* Function Body */
+    one = (float)1.;
+    con1 = (float).1;
+    con9 = (float).9;
+    con4 = (float).04;
+    half = (float).5;
+    ten = (float)10.;
+    pi = atan(one) * 4;
+    pi2 = pi + pi;
+    eps = sqrt(*eta);
+    if (*iopt < 0) {
+	goto L70;
+    }
+/*  calculation of acc, the absolute tolerance for the root of f(p)=s. */
+    acc = *tol * *s;
+    if (*iopt == 0) {
+	goto L10;
+    }
+    if (*s < *sup) {
+	if (*np - 11 >= 0) {
+	    goto L70;
+	} else {
+	    goto L60;
+	}
+    }
+/*  if iopt=0 we begin by computing the weighted least-squares polynomial */
+/*  of the form */
+/*     s(teta,phi) = c1*f1(teta) + cn*fn(teta) */
+/*  where f1(teta) and fn(teta) are the cubic polynomials satisfying */
+/*     f1(0) = 1, f1(pi) = f1'(0) = f1'(pi) = 0 ; fn(teta) = 1-f1(teta). */
+/*  the corresponding weighted sum of squared residuals gives the upper */
+/*  bound sup for the smoothing factor s. */
+L10:
+    *sup = (float)0.;
+    d1 = (float)0.;
+    d2 = (float)0.;
+    c1 = (float)0.;
+    cn = (float)0.;
+    fac1 = pi * (one + half);
+/* Computing 3rd power */
+    r__1 = pi;
+    fac2 = (one + one) / (r__1 * (r__1 * r__1));
+    aa = (float)0.;
+    i__1 = *m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	wi = w[i__];
+	ri = r__[i__] * wi;
+	arg = teta[i__];
+	fn = fac2 * arg * arg * (fac1 - arg);
+	f1 = (one - fn) * wi;
+	fn *= wi;
+	if (fn == (float)0.) {
+	    goto L20;
+	}
+	fpgivs_(&fn, &d1, &co, &si);
+	fprota_(&co, &si, &f1, &aa);
+	fprota_(&co, &si, &ri, &cn);
+L20:
+	if (f1 == (float)0.) {
+	    goto L30;
+	}
+	fpgivs_(&f1, &d2, &co, &si);
+	fprota_(&co, &si, &ri, &c1);
+L30:
+	*sup += ri * ri;
+/* L40: */
+    }
+    if (d2 != (float)0.) {
+	c1 /= d2;
+    }
+    if (d1 != (float)0.) {
+	cn = (cn - aa * c1) / d1;
+    }
+/*  find the b-spline representation of this least-squares polynomial */
+    *nt = 8;
+    *np = 8;
+    for (i__ = 1; i__ <= 4; ++i__) {
+	c__[i__] = c1;
+	c__[i__ + 4] = c1;
+	c__[i__ + 8] = cn;
+	c__[i__ + 12] = cn;
+	tt[i__] = (float)0.;
+	tt[i__ + 4] = pi;
+	tp[i__] = (float)0.;
+	tp[i__ + 4] = pi2;
+/* L50: */
+    }
+    *fp = *sup;
+/*  test whether the least-squares polynomial is an acceptable solution */
+    fpms = *sup - *s;
+    if (fpms < acc) {
+	goto L960;
+    }
+/*  test whether we cannot further increase the number of knots. */
+L60:
+    if (*npest < 11 || *ntest < 9) {
+	goto L950;
+    }
+/*  find the initial set of interior knots of the spherical spline in */
+/*  case iopt = 0. */
+    *np = 11;
+    tp[5] = pi * half;
+    tp[6] = pi;
+    tp[7] = tp[5] + pi;
+    *nt = 9;
+    tt[5] = tp[5];
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  part 1 : computation of least-squares spherical splines.            c */
+/*  ********************************************************            c */
+/*  if iopt < 0 we compute the least-squares spherical spline according c */
+/*  to the given set of knots.                                          c */
+/*  if iopt >=0 we compute least-squares spherical splines with increas-c */
+/*  ing numbers of knots until the corresponding sum f(p=inf)<=s.       c */
+/*  the initial set of knots then depends on the value of iopt:         c */
+/*    if iopt=0 we start with one interior knot in the teta-direction   c */
+/*              (pi/2) and three in the phi-direction (pi/2,pi,3*pi/2). c */
+/*    if iopt>0 we start with the set of knots found at the last call   c */
+/*              of the routine.                                         c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  main loop for the different sets of knots. m is a save upper bound */
+/*  for the number of trials. */
+L70:
+    i__1 = *m;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  find the position of the additional knots which are needed for the */
+/*  b-spline representation of s(teta,phi). */
+	l1 = 4;
+	l2 = l1;
+	l3 = *np - 3;
+	l4 = l3;
+	tp[l2] = (float)0.;
+	tp[l3] = pi2;
+	for (i__ = 1; i__ <= 3; ++i__) {
+	    ++l1;
+	    --l2;
+	    ++l3;
+	    --l4;
+	    tp[l2] = tp[l4] - pi2;
+	    tp[l3] = tp[l1] + pi2;
+/* L80: */
+	}
+	l = *nt;
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    tt[i__] = (float)0.;
+	    tt[l] = pi;
+	    --l;
+/* L90: */
+	}
+/*  find nrint, the total number of knot intervals and nreg, the number */
+/*  of panels in which the approximation domain is subdivided by the */
+/*  intersection of knots. */
+	ntt = *nt - 7;
+	npp = *np - 7;
+	nrr = npp / 2;
+	nr1 = nrr + 1;
+	nrint = ntt + npp;
+	nreg = ntt * npp;
+/*  arrange the data points according to the panel they belong to. */
+	fporde_(&teta[1], &phi[1], m, &c__3, &c__3, &tt[1], nt, &tp[1], np, &
+		nummer[1], &index[1], &nreg);
+/*  find the b-spline coefficients coco and cosi of the cubic spline */
+/*  approximations sc(phi) and ss(phi) for cos(phi) and sin(phi). */
+	i__2 = npp;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    coco[i__] = (float)0.;
+	    cosi[i__] = (float)0.;
+	    i__3 = npp;
+	    for (j = 1; j <= i__3; ++j) {
+		a[i__ + j * a_dim1] = (float)0.;
+/* L100: */
+	    }
+	}
+/*  the coefficients coco and cosi are obtained from the conditions */
+/*  sc(tp(i))=cos(tp(i)),resp. ss(tp(i))=sin(tp(i)),i=4,5,...np-4. */
+	i__3 = npp;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    l2 = i__ + 3;
+	    arg = tp[l2];
+	    fpbspl_(&tp[1], np, &c__3, &arg, &l2, hp);
+	    i__2 = npp;
+	    for (j = 1; j <= i__2; ++j) {
+		row[j] = (float)0.;
+/* L110: */
+	    }
+	    ll = i__;
+	    for (j = 1; j <= 3; ++j) {
+		if (ll > npp) {
+		    ll = 1;
+		}
+		row[ll] += hp[j - 1];
+		++ll;
+/* L120: */
+	    }
+	    facc = cos(arg);
+	    facs = sin(arg);
+	    i__2 = npp;
+	    for (j = 1; j <= i__2; ++j) {
+		piv = row[j];
+		if (piv == (float)0.) {
+		    goto L140;
+		}
+		fpgivs_(&piv, &a[j + a_dim1], &co, &si);
+		fprota_(&co, &si, &facc, &coco[j]);
+		fprota_(&co, &si, &facs, &cosi[j]);
+		if (j == npp) {
+		    goto L150;
+		}
+		j1 = j + 1;
+		i2 = 1;
+		i__4 = npp;
+		for (l = j1; l <= i__4; ++l) {
+		    ++i2;
+		    fprota_(&co, &si, &row[l], &a[j + i2 * a_dim1]);
+/* L130: */
+		}
+L140:
+		;
+	    }
+L150:
+	    ;
+	}
+	fpback_(&a[a_offset], &coco[1], &npp, &npp, &coco[1], ncc);
+	fpback_(&a[a_offset], &cosi[1], &npp, &npp, &cosi[1], ncc);
+/*  find ncof, the dimension of the spherical spline and ncoff, the */
+/*  number of coefficients in the standard b-spline representation. */
+	nt4 = *nt - 4;
+	np4 = *np - 4;
+	ncoff = nt4 * np4;
+	ncof = npp * (ntt - 1) + 6;
+/*  find the bandwidth of the observation matrix a. */
+	iband = npp << 2;
+	if (ntt == 4) {
+	    iband = (npp + 1) * 3;
+	}
+	if (ntt < 4) {
+	    iband = ncof;
+	}
+	iband1 = iband - 1;
+/*  initialize the observation matrix a. */
+	i__3 = ncof;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    f[i__] = (float)0.;
+	    i__2 = iband;
+	    for (j = 1; j <= i__2; ++j) {
+		a[i__ + j * a_dim1] = (float)0.;
+/* L160: */
+	    }
+	}
+/*  initialize the sum of squared residuals. */
+	*fp = (float)0.;
+/*  fetch the data points in the new order. main loop for the */
+/*  different panels. */
+	i__2 = nreg;
+	for (num = 1; num <= i__2; ++num) {
+/*  fix certain constants for the current panel; jrot records the column */
+/*  number of the first non-zero element in a row of the observation */
+/*  matrix according to a data point of the panel. */
+	    num1 = num - 1;
+	    lt = num1 / npp;
+	    l1 = lt + 4;
+	    lp = num1 - lt * npp + 1;
+	    l2 = lp + 3;
+	    ++lt;
+	    jrot = 0;
+	    if (lt > 2) {
+		jrot = (lt - 3) * npp + 3;
+	    }
+/*  test whether there are still data points in the current panel. */
+	    in = index[num];
+L170:
+	    if (in == 0) {
+		goto L340;
+	    }
+/*  fetch a new data point. */
+	    wi = w[in];
+	    ri = r__[in] * wi;
+/*  evaluate for the teta-direction, the 4 non-zero b-splines at teta(in) */
+	    fpbspl_(&tt[1], nt, &c__3, &teta[in], &l1, ht);
+/*  evaluate for the phi-direction, the 4 non-zero b-splines at phi(in) */
+	    fpbspl_(&tp[1], np, &c__3, &phi[in], &l2, hp);
+/*  store the value of these b-splines in spt and spp resp. */
+	    for (i__ = 1; i__ <= 4; ++i__) {
+		spp[in + i__ * spp_dim1] = hp[i__ - 1];
+		spt[in + i__ * spt_dim1] = ht[i__ - 1];
+/* L180: */
+	    }
+/*  initialize the new row of observation matrix. */
+	    i__3 = iband;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		h__[i__] = (float)0.;
+/* L190: */
+	    }
+/*  calculate the non-zero elements of the new row by making the cross */
+/*  products of the non-zero b-splines in teta- and phi-direction and */
+/*  by taking into account the conditions of the spherical splines. */
+	    i__3 = npp;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		row[i__] = (float)0.;
+/* L200: */
+	    }
+/*  take into account the condition (3) of the spherical splines. */
+	    ll = lp;
+	    for (i__ = 1; i__ <= 4; ++i__) {
+		if (ll > npp) {
+		    ll = 1;
+		}
+		row[ll] += hp[i__ - 1];
+		++ll;
+/* L210: */
+	    }
+/*  take into account the other conditions of the spherical splines. */
+	    if (lt > 2 && lt < ntt - 1) {
+		goto L230;
+	    }
+	    facc = (float)0.;
+	    facs = (float)0.;
+	    i__3 = npp;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		facc += row[i__] * coco[i__];
+		facs += row[i__] * cosi[i__];
+/* L220: */
+	    }
+/*  fill in the non-zero elements of the new row. */
+L230:
+	    j1 = 0;
+	    for (j = 1; j <= 4; ++j) {
+		jlt = j + lt;
+		htj = ht[j - 1];
+		if (jlt > 2 && jlt <= nt4) {
+		    goto L240;
+		}
+		++j1;
+		h__[j1] += htj;
+		goto L280;
+L240:
+		if (jlt == 3 || jlt == nt4) {
+		    goto L260;
+		}
+		i__3 = npp;
+		for (i__ = 1; i__ <= i__3; ++i__) {
+		    ++j1;
+		    h__[j1] = row[i__] * htj;
+/* L250: */
+		}
+		goto L280;
+L260:
+		if (jlt == 3) {
+		    goto L270;
+		}
+		h__[j1 + 1] = facc * htj;
+		h__[j1 + 2] = facs * htj;
+		h__[j1 + 3] = htj;
+		j1 += 2;
+		goto L280;
+L270:
+		h__[1] += htj;
+		h__[2] = facc * htj;
+		h__[3] = facs * htj;
+		j1 = 3;
+L280:
+		;
+	    }
+	    i__3 = iband;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		h__[i__] *= wi;
+/* L290: */
+	    }
+/*  rotate the row into triangle by givens transformations. */
+	    irot = jrot;
+	    i__3 = iband;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		++irot;
+		piv = h__[i__];
+		if (piv == (float)0.) {
+		    goto L310;
+		}
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &a[irot + a_dim1], &co, &si);
+/*  apply that transformation to the right hand side. */
+		fprota_(&co, &si, &ri, &f[irot]);
+		if (i__ == iband) {
+		    goto L320;
+		}
+/*  apply that transformation to the left hand side. */
+		i2 = 1;
+		i3 = i__ + 1;
+		i__4 = iband;
+		for (j = i3; j <= i__4; ++j) {
+		    ++i2;
+		    fprota_(&co, &si, &h__[j], &a[irot + i2 * a_dim1]);
+/* L300: */
+		}
+L310:
+		;
+	    }
+/*  add the contribution of the row to the sum of squares of residual */
+/*  right hand sides. */
+L320:
+/* Computing 2nd power */
+	    r__1 = ri;
+	    *fp += r__1 * r__1;
+/*  find the number of the next data point in the panel. */
+/* L330: */
+	    in = nummer[in];
+	    goto L170;
+L340:
+	    ;
+	}
+/*  find dmax, the maximum value for the diagonal elements in the reduced */
+/*  triangle. */
+	dmax__ = (float)0.;
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    if (a[i__ + a_dim1] <= dmax__) {
+		goto L350;
+	    }
+	    dmax__ = a[i__ + a_dim1];
+L350:
+	    ;
+	}
+/*  check whether the observation matrix is rank deficient. */
+	sigma = eps * dmax__;
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    if (a[i__ + a_dim1] <= sigma) {
+		goto L370;
+	    }
+/* L360: */
+	}
+/*  backward substitution in case of full rank. */
+	fpback_(&a[a_offset], &f[1], &ncof, &iband, &c__[1], ncc);
+	rank = ncof;
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    q[i__ + q_dim1] = a[i__ + a_dim1] / dmax__;
+/* L365: */
+	}
+	goto L390;
+/*  in case of rank deficiency, find the minimum norm solution. */
+L370:
+	lwest = ncof * iband + ncof + iband;
+	if (*lwrk < lwest) {
+	    goto L925;
+	}
+	lf = 1;
+	lh = lf + ncof;
+	la = lh + iband;
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ff[i__] = f[i__];
+	    i__3 = iband;
+	    for (j = 1; j <= i__3; ++j) {
+		q[i__ + j * q_dim1] = a[i__ + j * a_dim1];
+/* L380: */
+	    }
+	}
+	fprank_(&q[q_offset], &ff[1], &ncof, &iband, ncc, &sigma, &c__[1], &
+		sq, &rank, &wrk[la], &wrk[lf], &wrk[lh]);
+	i__3 = ncof;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    q[i__ + q_dim1] /= dmax__;
+/* L385: */
+	}
+/*  add to the sum of squared residuals, the contribution of reducing */
+/*  the rank. */
+	*fp += sq;
+/*  find the coefficients in the standard b-spline representation of */
+/*  the spherical spline. */
+L390:
+	fprpsp_(nt, np, &coco[1], &cosi[1], &c__[1], &ff[1], &ncoff);
+/*  test whether the least-squares spline is an acceptable solution. */
+	if (*iopt < 0) {
+	    if (*fp <= (float)0.) {
+		goto L970;
+	    } else {
+		goto L980;
+	    }
+	}
+	fpms = *fp - *s;
+	if (dabs(fpms) <= acc) {
+	    if (*fp <= (float)0.) {
+		goto L970;
+	    } else {
+		goto L980;
+	    }
+	}
+/*  if f(p=inf) < s, accept the choice of knots. */
+	if (fpms < (float)0.) {
+	    goto L580;
+	}
+/*  test whether we cannot further increase the number of knots. */
+	if (ncof > *m) {
+	    goto L935;
+	}
+/*  search where to add a new knot. */
+/*  find for each interval the sum of squared residuals fpint for the */
+/*  data points having the coordinate belonging to that knot interval. */
+/*  calculate also coord which is the same sum, weighted by the position */
+/*  of the data points considered. */
+/* L440: */
+	i__3 = nrint;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    fpint[i__] = (float)0.;
+	    coord[i__] = (float)0.;
+/* L450: */
+	}
+	i__3 = nreg;
+	for (num = 1; num <= i__3; ++num) {
+	    num1 = num - 1;
+	    lt = num1 / npp;
+	    l1 = lt + 1;
+	    lp = num1 - lt * npp;
+	    l2 = lp + 1 + ntt;
+	    jrot = lt * np4 + lp;
+	    in = index[num];
+L460:
+	    if (in == 0) {
+		goto L490;
+	    }
+	    store = (float)0.;
+	    i1 = jrot;
+	    for (i__ = 1; i__ <= 4; ++i__) {
+		hti = spt[in + i__ * spt_dim1];
+		j1 = i1;
+		for (j = 1; j <= 4; ++j) {
+		    ++j1;
+		    store += hti * spp[in + j * spp_dim1] * c__[j1];
+/* L470: */
+		}
+		i1 += np4;
+/* L480: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[in] * (r__[in] - store);
+	    store = r__1 * r__1;
+	    fpint[l1] += store;
+	    coord[l1] += store * teta[in];
+	    fpint[l2] += store;
+	    coord[l2] += store * phi[in];
+	    in = nummer[in];
+	    goto L460;
+L490:
+	    ;
+	}
+/*  find the interval for which fpint is maximal on the condition that */
+/*  there still can be added a knot. */
+	l1 = 1;
+	l2 = nrint;
+	if (*ntest < *nt + 1) {
+	    l1 = ntt + 1;
+	}
+	if (*npest < *np + 2) {
+	    l2 = ntt;
+	}
+/*  test whether we cannot further increase the number of knots. */
+	if (l1 > l2) {
+	    goto L950;
+	}
+L500:
+	fpmax = (float)0.;
+	l = 0;
+	i__3 = l2;
+	for (i__ = l1; i__ <= i__3; ++i__) {
+	    if (fpmax >= fpint[i__]) {
+		goto L510;
+	    }
+	    l = i__;
+	    fpmax = fpint[i__];
+L510:
+	    ;
+	}
+	if (l == 0) {
+	    goto L930;
+	}
+/*  calculate the position of the new knot. */
+	arg = coord[l] / fpint[l];
+/*  test in what direction the new knot is going to be added. */
+	if (l > ntt) {
+	    goto L530;
+	}
+/*  addition in the teta-direction */
+	l4 = l + 4;
+	fpint[l] = (float)0.;
+	fac1 = tt[l4] - arg;
+	fac2 = arg - tt[l4 - 1];
+	if (fac1 > ten * fac2 || fac2 > ten * fac1) {
+	    goto L500;
+	}
+	j = *nt;
+	i__3 = *nt;
+	for (i__ = l4; i__ <= i__3; ++i__) {
+	    tt[j + 1] = tt[j];
+	    --j;
+/* L520: */
+	}
+	tt[l4] = arg;
+	++(*nt);
+	goto L570;
+/*  addition in the phi-direction */
+L530:
+	l4 = l + 4 - ntt;
+	if (arg < pi) {
+	    goto L540;
+	}
+	arg -= pi;
+	l4 -= nrr;
+L540:
+	fpint[l] = (float)0.;
+	fac1 = tp[l4] - arg;
+	fac2 = arg - tp[l4 - 1];
+	if (fac1 > ten * fac2 || fac2 > ten * fac1) {
+	    goto L500;
+	}
+	ll = nrr + 4;
+	j = ll;
+	i__3 = ll;
+	for (i__ = l4; i__ <= i__3; ++i__) {
+	    tp[j + 1] = tp[j];
+	    --j;
+/* L550: */
+	}
+	tp[l4] = arg;
+	*np += 2;
+	++nrr;
+	i__3 = ll;
+	for (i__ = 5; i__ <= i__3; ++i__) {
+	    j = i__ + nrr;
+	    tp[j] = tp[i__] + pi;
+/* L560: */
+	}
+/*  restart the computations with the new set of knots. */
+L570:
+	;
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/* part 2: determination of the smoothing spherical spline.             c */
+/* ********************************************************             c */
+/* we have determined the number of knots and their position. we now    c */
+/* compute the coefficients of the smoothing spline sp(teta,phi).       c */
+/* the observation matrix a is extended by the rows of a matrix, expres-c */
+/* sing that sp(teta,phi) must be a constant function in the variable   c */
+/* phi and a cubic polynomial in the variable teta. the corresponding   c */
+/* weights of these additional rows are set to 1/(p). iteratively       c */
+/* we than have to determine the value of p such that f(p) = sum((w(i)* c */
+/* (r(i)-sp(teta(i),phi(i))))**2)  be = s.                              c */
+/* we already know that the least-squares polynomial corresponds to p=0,c */
+/* and that the least-squares spherical spline corresponds to p=infin.  c */
+/* the iteration process makes use of rational interpolation. since f(p)c */
+/* is a convex and strictly decreasing function of p, it can be approx- c */
+/* imated by a rational function of the form r(p) = (u*p+v)/(p+w).      c */
+/* three values of p (p1,p2,p3) with corresponding values of f(p) (f1=  c */
+/* f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used to calculate the new value   c */
+/* of p such that r(p)=s. convergence is guaranteed by taking f1>0,f3<0.c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  evaluate the discontinuity jumps of the 3-th order derivative of */
+/*  the b-splines at the knots tt(l),l=5,...,nt-4. */
+L580:
+    fpdisc_(&tt[1], nt, &c__5, &bt[bt_offset], ntest);
+/*  evaluate the discontinuity jumps of the 3-th order derivative of */
+/*  the b-splines at the knots tp(l),l=5,...,np-4. */
+    fpdisc_(&tp[1], np, &c__5, &bp[bp_offset], npest);
+/*  initial value for p. */
+    p1 = (float)0.;
+    f1 = *sup - *s;
+    p3 = -one;
+    f3 = fpms;
+    p = (float)0.;
+    i__1 = ncof;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	p += a[i__ + a_dim1];
+/* L585: */
+    }
+    rn = (real) ncof;
+    p = rn / p;
+/*  find the bandwidth of the extended observation matrix. */
+    iband4 = iband + 3;
+    if (ntt <= 4) {
+	iband4 = ncof;
+    }
+    iband3 = iband4 - 1;
+    ich1 = 0;
+    ich3 = 0;
+/*  iteration process to find the root of f(p)=s. */
+    i__1 = *maxit;
+    for (iter = 1; iter <= i__1; ++iter) {
+	pinv = one / p;
+/*  store the triangularized observation matrix into q. */
+	i__3 = ncof;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    ff[i__] = f[i__];
+	    i__2 = iband4;
+	    for (j = 1; j <= i__2; ++j) {
+		q[i__ + j * q_dim1] = (float)0.;
+/* L590: */
+	    }
+	    i__2 = iband;
+	    for (j = 1; j <= i__2; ++j) {
+		q[i__ + j * q_dim1] = a[i__ + j * a_dim1];
+/* L600: */
+	    }
+	}
+/*  extend the observation matrix with the rows of a matrix, expressing */
+/*  that for teta=cst. sp(teta,phi) must be a constant function. */
+	nt6 = *nt - 6;
+	i__2 = np4;
+	for (i__ = 5; i__ <= i__2; ++i__) {
+	    ii = i__ - 4;
+	    i__3 = npp;
+	    for (l = 1; l <= i__3; ++l) {
+		row[l] = (float)0.;
+/* L610: */
+	    }
+	    ll = ii;
+	    for (l = 1; l <= 5; ++l) {
+		if (ll > npp) {
+		    ll = 1;
+		}
+		row[ll] += bp[ii + l * bp_dim1];
+		++ll;
+/* L620: */
+	    }
+	    facc = (float)0.;
+	    facs = (float)0.;
+	    i__3 = npp;
+	    for (l = 1; l <= i__3; ++l) {
+		facc += row[l] * coco[l];
+		facs += row[l] * cosi[l];
+/* L630: */
+	    }
+	    i__3 = nt6;
+	    for (j = 1; j <= i__3; ++j) {
+/*  initialize the new row. */
+		i__4 = iband;
+		for (l = 1; l <= i__4; ++l) {
+		    h__[l] = (float)0.;
+/* L640: */
+		}
+/*  fill in the non-zero elements of the row. jrot records the column */
+/*  number of the first non-zero element in the row. */
+		jrot = (j - 2) * npp + 4;
+		if (j > 1 && j < nt6) {
+		    goto L650;
+		}
+		h__[1] = facc;
+		h__[2] = facs;
+		if (j == 1) {
+		    jrot = 2;
+		}
+		goto L670;
+L650:
+		i__4 = npp;
+		for (l = 1; l <= i__4; ++l) {
+		    h__[l] = row[l];
+/* L660: */
+		}
+L670:
+		i__4 = iband;
+		for (l = 1; l <= i__4; ++l) {
+		    h__[l] *= pinv;
+/* L675: */
+		}
+		ri = (float)0.;
+/*  rotate the new row into triangle by givens transformations. */
+		i__4 = ncof;
+		for (irot = jrot; irot <= i__4; ++irot) {
+		    piv = h__[1];
+/* Computing MIN */
+		    i__5 = iband1, i__6 = ncof - irot;
+		    i2 = min(i__5,i__6);
+		    if (piv == (float)0.) {
+			if (i2 <= 0) {
+			    goto L720;
+			} else {
+			    goto L690;
+			}
+		    }
+/*  calculate the parameters of the givens transformation. */
+		    fpgivs_(&piv, &q[irot + q_dim1], &co, &si);
+/*  apply that givens transformation to the right hand side. */
+		    fprota_(&co, &si, &ri, &ff[irot]);
+		    if (i2 == 0) {
+			goto L720;
+		    }
+/*  apply that givens transformation to the left hand side. */
+		    i__5 = i2;
+		    for (l = 1; l <= i__5; ++l) {
+			l1 = l + 1;
+			fprota_(&co, &si, &h__[l1], &q[irot + l1 * q_dim1]);
+/* L680: */
+		    }
+L690:
+		    i__5 = i2;
+		    for (l = 1; l <= i__5; ++l) {
+			h__[l] = h__[l + 1];
+/* L700: */
+		    }
+		    h__[i2 + 1] = (float)0.;
+/* L710: */
+		}
+L720:
+		;
+	    }
+	}
+/*  extend the observation matrix with the rows of a matrix expressing */
+/*  that for phi=cst. sp(teta,phi) must be a cubic polynomial. */
+	i__3 = nt4;
+	for (i__ = 5; i__ <= i__3; ++i__) {
+	    ii = i__ - 4;
+	    i__2 = npp;
+	    for (j = 1; j <= i__2; ++j) {
+/*  initialize the new row */
+		i__4 = iband4;
+		for (l = 1; l <= i__4; ++l) {
+		    h__[l] = (float)0.;
+/* L730: */
+		}
+/*  fill in the non-zero elements of the row. jrot records the column */
+/*  number of the first non-zero element in the row. */
+		j1 = 1;
+		for (l = 1; l <= 5; ++l) {
+		    il = ii + l;
+		    ij = npp;
+		    if (il != 3 && il != nt4) {
+			goto L750;
+		    }
+		    j1 = j1 + 3 - j;
+		    j2 = j1 - 2;
+		    ij = 0;
+		    if (il != 3) {
+			goto L740;
+		    }
+		    j1 = 1;
+		    j2 = 2;
+		    ij = j + 2;
+L740:
+		    h__[j2] = bt[ii + l * bt_dim1] * coco[j];
+		    h__[j2 + 1] = bt[ii + l * bt_dim1] * cosi[j];
+L750:
+		    h__[j1] += bt[ii + l * bt_dim1];
+		    j1 += ij;
+/* L760: */
+		}
+		i__4 = iband4;
+		for (l = 1; l <= i__4; ++l) {
+		    h__[l] *= pinv;
+/* L765: */
+		}
+		ri = (float)0.;
+		jrot = 1;
+		if (ii > 2) {
+		    jrot = j + 3 + (ii - 3) * npp;
+		}
+/*  rotate the new row into triangle by givens transformations. */
+		i__4 = ncof;
+		for (irot = jrot; irot <= i__4; ++irot) {
+		    piv = h__[1];
+/* Computing MIN */
+		    i__5 = iband3, i__6 = ncof - irot;
+		    i2 = min(i__5,i__6);
+		    if (piv == (float)0.) {
+			if (i2 <= 0) {
+			    goto L810;
+			} else {
+			    goto L780;
+			}
+		    }
+/*  calculate the parameters of the givens transformation. */
+		    fpgivs_(&piv, &q[irot + q_dim1], &co, &si);
+/*  apply that givens transformation to the right hand side. */
+		    fprota_(&co, &si, &ri, &ff[irot]);
+		    if (i2 == 0) {
+			goto L810;
+		    }
+/*  apply that givens transformation to the left hand side. */
+		    i__5 = i2;
+		    for (l = 1; l <= i__5; ++l) {
+			l1 = l + 1;
+			fprota_(&co, &si, &h__[l1], &q[irot + l1 * q_dim1]);
+/* L770: */
+		    }
+L780:
+		    i__5 = i2;
+		    for (l = 1; l <= i__5; ++l) {
+			h__[l] = h__[l + 1];
+/* L790: */
+		    }
+		    h__[i2 + 1] = (float)0.;
+/* L800: */
+		}
+L810:
+		;
+	    }
+	}
+/*  find dmax, the maximum value for the diagonal elements in the */
+/*  reduced triangle. */
+	dmax__ = (float)0.;
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    if (q[i__ + q_dim1] <= dmax__) {
+		goto L820;
+	    }
+	    dmax__ = q[i__ + q_dim1];
+L820:
+	    ;
+	}
+/*  check whether the matrix is rank deficient. */
+	sigma = eps * dmax__;
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    if (q[i__ + q_dim1] <= sigma) {
+		goto L840;
+	    }
+/* L830: */
+	}
+/*  backward substitution in case of full rank. */
+	fpback_(&q[q_offset], &ff[1], &ncof, &iband4, &c__[1], ncc);
+	rank = ncof;
+	goto L845;
+/*  in case of rank deficiency, find the minimum norm solution. */
+L840:
+	lwest = ncof * iband4 + ncof + iband4;
+	if (*lwrk < lwest) {
+	    goto L925;
+	}
+	lf = 1;
+	lh = lf + ncof;
+	la = lh + iband4;
+	fprank_(&q[q_offset], &ff[1], &ncof, &iband4, ncc, &sigma, &c__[1], &
+		sq, &rank, &wrk[la], &wrk[lf], &wrk[lh]);
+L845:
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    q[i__ + q_dim1] /= dmax__;
+/* L850: */
+	}
+/*  find the coefficients in the standard b-spline representation of */
+/*  the spherical spline. */
+	fprpsp_(nt, np, &coco[1], &cosi[1], &c__[1], &ff[1], &ncoff);
+/*  compute f(p). */
+	*fp = (float)0.;
+	i__2 = nreg;
+	for (num = 1; num <= i__2; ++num) {
+	    num1 = num - 1;
+	    lt = num1 / npp;
+	    lp = num1 - lt * npp;
+	    jrot = lt * np4 + lp;
+	    in = index[num];
+L860:
+	    if (in == 0) {
+		goto L890;
+	    }
+	    store = (float)0.;
+	    i1 = jrot;
+	    for (i__ = 1; i__ <= 4; ++i__) {
+		hti = spt[in + i__ * spt_dim1];
+		j1 = i1;
+		for (j = 1; j <= 4; ++j) {
+		    ++j1;
+		    store += hti * spp[in + j * spp_dim1] * c__[j1];
+/* L870: */
+		}
+		i1 += np4;
+/* L880: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[in] * (r__[in] - store);
+	    *fp += r__1 * r__1;
+	    in = nummer[in];
+	    goto L860;
+L890:
+	    ;
+	}
+/*  test whether the approximation sp(teta,phi) is an acceptable solution */
+	fpms = *fp - *s;
+	if (dabs(fpms) <= acc) {
+	    goto L980;
+	}
+/*  test whether the maximum allowable number of iterations has been */
+/*  reached. */
+	if (iter == *maxit) {
+	    goto L940;
+	}
+/*  carry out one more step of the iteration process. */
+	p2 = p;
+	f2 = fpms;
+	if (ich3 != 0) {
+	    goto L900;
+	}
+	if (f2 - f3 > acc) {
+	    goto L895;
+	}
+/*  our initial choice of p is too large. */
+	p3 = p2;
+	f3 = f2;
+	p *= con4;
+	if (p <= p1) {
+	    p = p1 * con9 + p2 * con1;
+	}
+	goto L920;
+L895:
+	if (f2 < (float)0.) {
+	    ich3 = 1;
+	}
+L900:
+	if (ich1 != 0) {
+	    goto L910;
+	}
+	if (f1 - f2 > acc) {
+	    goto L905;
+	}
+/*  our initial choice of p is too small */
+	p1 = p2;
+	f1 = f2;
+	p /= con4;
+	if (p3 < (float)0.) {
+	    goto L920;
+	}
+	if (p >= p3) {
+	    p = p2 * con1 + p3 * con9;
+	}
+	goto L920;
+L905:
+	if (f2 > (float)0.) {
+	    ich1 = 1;
+	}
+/*  test whether the iteration process proceeds as theoretically */
+/*  expected. */
+L910:
+	if (f2 >= f1 || f2 <= f3) {
+	    goto L945;
+	}
+/*  find the new value of p. */
+	p = fprati_(&p1, &f1, &p2, &f2, &p3, &f3);
+L920:
+	;
+    }
+/*  error codes and messages. */
+L925:
+    *ier = lwest;
+    goto L990;
+L930:
+    *ier = 5;
+    goto L990;
+L935:
+    *ier = 4;
+    goto L990;
+L940:
+    *ier = 3;
+    goto L990;
+L945:
+    *ier = 2;
+    goto L990;
+L950:
+    *ier = 1;
+    goto L990;
+L960:
+    *ier = -2;
+    goto L990;
+L970:
+    *ier = -1;
+    *fp = (float)0.;
+L980:
+    if (ncof != rank) {
+	*ier = -rank;
+    }
+L990:
+    return 0;
+} /* fpsphe_ */
+
+/* Subroutine */ int fpsuev_(idim, tu, nu, tv, nv, c__, u, mu, v, mv, f, wu, 
+	wv, lu, lv)
+integer *idim;
+real *tu;
+integer *nu;
+real *tv;
+integer *nv;
+real *c__, *u;
+integer *mu;
+real *v;
+integer *mv;
+real *f, *wu, *wv;
+integer *lu, *lv;
+{
+    /* System generated locals */
+    integer wu_dim1, wu_offset, wv_dim1, wv_offset, i__1, i__2, i__3;
+
+    /* Local variables */
+    static real h__[4];
+    static integer i__, j, k, l, m, i1, j1, l1, l2, l3;
+    static real tb, te, sp;
+    extern /* Subroutine */ int fpbspl_();
+    static integer nu4, nv4;
+    static real arg;
+    static integer nuv;
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..subroutine references.. */
+/*    fpbspl */
+/*  .. */
+    /* Parameter adjustments */
+    --tu;
+    --c__;
+    --tv;
+    --lu;
+    wu_dim1 = *mu;
+    wu_offset = 1 + wu_dim1 * 1;
+    wu -= wu_offset;
+    --u;
+    --lv;
+    wv_dim1 = *mv;
+    wv_offset = 1 + wv_dim1 * 1;
+    wv -= wv_offset;
+    --f;
+    --v;
+
+    /* Function Body */
+    nu4 = *nu - 4;
+    tb = tu[4];
+    te = tu[nu4 + 1];
+    l = 4;
+    l1 = l + 1;
+    i__1 = *mu;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	arg = u[i__];
+	if (arg < tb) {
+	    arg = tb;
+	}
+	if (arg > te) {
+	    arg = te;
+	}
+L10:
+	if (arg < tu[l1] || l == nu4) {
+	    goto L20;
+	}
+	l = l1;
+	l1 = l + 1;
+	goto L10;
+L20:
+	fpbspl_(&tu[1], nu, &c__3, &arg, &l, h__);
+	lu[i__] = l - 4;
+	for (j = 1; j <= 4; ++j) {
+	    wu[i__ + j * wu_dim1] = h__[j - 1];
+/* L30: */
+	}
+/* L40: */
+    }
+    nv4 = *nv - 4;
+    tb = tv[4];
+    te = tv[nv4 + 1];
+    l = 4;
+    l1 = l + 1;
+    i__1 = *mv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	arg = v[i__];
+	if (arg < tb) {
+	    arg = tb;
+	}
+	if (arg > te) {
+	    arg = te;
+	}
+L50:
+	if (arg < tv[l1] || l == nv4) {
+	    goto L60;
+	}
+	l = l1;
+	l1 = l + 1;
+	goto L50;
+L60:
+	fpbspl_(&tv[1], nv, &c__3, &arg, &l, h__);
+	lv[i__] = l - 4;
+	for (j = 1; j <= 4; ++j) {
+	    wv[i__ + j * wv_dim1] = h__[j - 1];
+/* L70: */
+	}
+/* L80: */
+    }
+    m = 0;
+    nuv = nu4 * nv4;
+    i__1 = *idim;
+    for (k = 1; k <= i__1; ++k) {
+	l3 = (k - 1) * nuv;
+	i__2 = *mu;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    l = lu[i__] * nv4 + l3;
+	    for (i1 = 1; i1 <= 4; ++i1) {
+		h__[i1 - 1] = wu[i__ + i1 * wu_dim1];
+/* L90: */
+	    }
+	    i__3 = *mv;
+	    for (j = 1; j <= i__3; ++j) {
+		l1 = l + lv[j];
+		sp = (float)0.;
+		for (i1 = 1; i1 <= 4; ++i1) {
+		    l2 = l1;
+		    for (j1 = 1; j1 <= 4; ++j1) {
+			++l2;
+			sp += c__[l2] * h__[i1 - 1] * wv[j + j1 * wv_dim1];
+/* L100: */
+		    }
+		    l1 += nv4;
+/* L110: */
+		}
+		++m;
+		f[m] = sp;
+/* L120: */
+	    }
+/* L130: */
+	}
+/* L140: */
+    }
+    return 0;
+} /* fpsuev_ */
+
+/* Subroutine */ int fpsurf_(iopt, m, x, y, z__, w, xb, xe, yb, ye, kxx, kyy, 
+	s, nxest, nyest, eta, tol, maxit, nmax, km1, km2, ib1, ib3, nc, 
+	intest, nrest, nx0, tx, ny0, ty, c__, fp, fp0, fpint, coord, f, ff, a,
+	 q, bx, by, spx, spy, h__, index, nummer, wrk, lwrk, ier)
+integer *iopt, *m;
+real *x, *y, *z__, *w, *xb, *xe, *yb, *ye;
+integer *kxx, *kyy;
+real *s;
+integer *nxest, *nyest;
+real *eta, *tol;
+integer *maxit, *nmax, *km1, *km2, *ib1, *ib3, *nc, *intest, *nrest, *nx0;
+real *tx;
+integer *ny0;
+real *ty, *c__, *fp, *fp0, *fpint, *coord, *f, *ff, *a, *q, *bx, *by, *spx, *
+	spy, *h__;
+integer *index, *nummer;
+real *wrk;
+integer *lwrk, *ier;
+{
+    /* System generated locals */
+    integer a_dim1, a_offset, q_dim1, q_offset, bx_dim1, bx_offset, by_dim1, 
+	    by_offset, spx_dim1, spx_offset, spy_dim1, spy_offset, i__1, i__2,
+	     i__3, i__4, i__5, i__6;
+    real r__1;
+
+    /* Builtin functions */
+    double sqrt();
+
+    /* Local variables */
+    static real half;
+    static integer ncof;
+    static real dmax__;
+    static integer nreg, rank, iter;
+    static real fpms, pinv;
+    static integer irot, jrot, i__, j, l, iband, n;
+    static real p, sigma, fpmax, f1, f2, f3;
+    static integer i1;
+    static real store;
+    static integer i2, iband1, i3, iband3;
+    static real p1, p2, p3;
+    static integer iband4, j1;
+    static real x0, x1, y0, y1;
+    static integer lwest, l1, l2, nminx, nminy, nrint, n1, la, ii, lf, lh, in;
+    extern /* Subroutine */ int fpback_();
+    static integer ichang;
+    static real wi, rn, hx[6], zi, sq;
+    static integer kx, ky, lx, ly, nx, ny;
+    static real hy[6];
+    extern /* Subroutine */ int fpdisc_(), fporde_(), fprank_();
+    extern doublereal fprati_();
+    extern /* Subroutine */ int fpbspl_(), fprota_(), fpgivs_();
+    static integer kx1, kx2, ky1, ky2;
+    static real acc;
+    static integer ibb;
+    static real arg, one, cos__, ten, eps, hxi, sin__;
+    static integer nxe, nye;
+    static real piv;
+    static integer num;
+    static real fac1, fac2;
+    static integer jxy, nxx, nyy, ich1, ich3;
+    static real con1, con4, con9;
+    static integer num1, nk1x, nk1y;
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpback,fpbspl,fpgivs,fpdisc,fporde,fprank,fprota */
+/*  .. */
+/*  set constants */
+    /* Parameter adjustments */
+    --nummer;
+    --w;
+    --z__;
+    --y;
+    --x;
+    --ty;
+    --tx;
+    spy_dim1 = *m;
+    spy_offset = 1 + spy_dim1 * 1;
+    spy -= spy_offset;
+    spx_dim1 = *m;
+    spx_offset = 1 + spx_dim1 * 1;
+    spx -= spx_offset;
+    by_dim1 = *nmax;
+    by_offset = 1 + by_dim1 * 1;
+    by -= by_offset;
+    bx_dim1 = *nmax;
+    bx_offset = 1 + bx_dim1 * 1;
+    bx -= bx_offset;
+    --h__;
+    q_dim1 = *nc;
+    q_offset = 1 + q_dim1 * 1;
+    q -= q_offset;
+    a_dim1 = *nc;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+    --ff;
+    --f;
+    --c__;
+    --coord;
+    --fpint;
+    --index;
+    --wrk;
+
+    /* Function Body */
+    one = (float)1.;
+    con1 = (float).1;
+    con9 = (float).9;
+    con4 = (float).04;
+    half = (float).5;
+    ten = (float)10.;
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/* part 1: determination of the number of knots and their position.     c */
+/* ****************************************************************     c */
+/* given a set of knots we compute the least-squares spline sinf(x,y),  c */
+/* and the corresponding weighted sum of squared residuals fp=f(p=inf). c */
+/* if iopt=-1  sinf(x,y) is the requested approximation.                c */
+/* if iopt=0 or iopt=1 we check whether we can accept the knots:        c */
+/*   if fp <=s we will continue with the current set of knots.          c */
+/*   if fp > s we will increase the number of knots and compute the     c */
+/*      corresponding least-squares spline until finally  fp<=s.        c */
+/* the initial choice of knots depends on the value of s and iopt.      c */
+/*   if iopt=0 we first compute the least-squares polynomial of degree  c */
+/*     kx in x and ky in y; nx=nminx=2*kx+2 and ny=nminy=2*ky+2.        c */
+/*     fp0=f(0) denotes the corresponding weighted sum of squared       c */
+/*     residuals                                                        c */
+/*   if iopt=1 we start with the knots found at the last call of the    c */
+/*     routine, except for the case that s>=fp0; then we can compute    c */
+/*     the least-squares polynomial directly.                           c */
+/* eventually the independent variables x and y (and the corresponding  c */
+/* parameters) will be switched if this can reduce the bandwidth of the c */
+/* system to be solved.                                                 c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/*  ichang denotes whether(1) or not(-1) the directions have been inter- */
+/*  changed. */
+    ichang = -1;
+    x0 = *xb;
+    x1 = *xe;
+    y0 = *yb;
+    y1 = *ye;
+    kx = *kxx;
+    ky = *kyy;
+    kx1 = kx + 1;
+    ky1 = ky + 1;
+    nxe = *nxest;
+    nye = *nyest;
+    eps = sqrt(*eta);
+    if (*iopt < 0) {
+	goto L20;
+    }
+/*  calculation of acc, the absolute tolerance for the root of f(p)=s. */
+    acc = *tol * *s;
+    if (*iopt == 0) {
+	goto L10;
+    }
+    if (*fp0 > *s) {
+	goto L20;
+    }
+/*  initialization for the least-squares polynomial. */
+L10:
+    nminx = kx1 << 1;
+    nminy = ky1 << 1;
+    nx = nminx;
+    ny = nminy;
+    *ier = -2;
+    goto L30;
+L20:
+    nx = *nx0;
+    ny = *ny0;
+/*  main loop for the different sets of knots. m is a save upper bound */
+/*  for the number of trials. */
+L30:
+    i__1 = *m;
+    for (iter = 1; iter <= i__1; ++iter) {
+/*  find the position of the additional knots which are needed for the */
+/*  b-spline representation of s(x,y). */
+	l = nx;
+	i__2 = kx1;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    tx[i__] = x0;
+	    tx[l] = x1;
+	    --l;
+/* L40: */
+	}
+	l = ny;
+	i__2 = ky1;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ty[i__] = y0;
+	    ty[l] = y1;
+	    --l;
+/* L50: */
+	}
+/*  find nrint, the total number of knot intervals and nreg, the number */
+/*  of panels in which the approximation domain is subdivided by the */
+/*  intersection of knots. */
+	nxx = nx - (kx1 << 1) + 1;
+	nyy = ny - (ky1 << 1) + 1;
+	nrint = nxx + nyy;
+	nreg = nxx * nyy;
+/*  find the bandwidth of the observation matrix a. */
+/*  if necessary, interchange the variables x and y, in order to obtain */
+/*  a minimal bandwidth. */
+	iband1 = kx * (ny - ky1) + ky;
+	l = ky * (nx - kx1) + kx;
+	if (iband1 <= l) {
+	    goto L130;
+	}
+	iband1 = l;
+	ichang = -ichang;
+	i__2 = *m;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    store = x[i__];
+	    x[i__] = y[i__];
+	    y[i__] = store;
+/* L60: */
+	}
+	store = x0;
+	x0 = y0;
+	y0 = store;
+	store = x1;
+	x1 = y1;
+	y1 = store;
+	n = min(nx,ny);
+	i__2 = n;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    store = tx[i__];
+	    tx[i__] = ty[i__];
+	    ty[i__] = store;
+/* L70: */
+	}
+	n1 = n + 1;
+	if ((i__2 = nx - ny) < 0) {
+	    goto L80;
+	} else if (i__2 == 0) {
+	    goto L120;
+	} else {
+	    goto L100;
+	}
+L80:
+	i__2 = ny;
+	for (i__ = n1; i__ <= i__2; ++i__) {
+	    tx[i__] = ty[i__];
+/* L90: */
+	}
+	goto L120;
+L100:
+	i__2 = nx;
+	for (i__ = n1; i__ <= i__2; ++i__) {
+	    ty[i__] = tx[i__];
+/* L110: */
+	}
+L120:
+	l = nx;
+	nx = ny;
+	ny = l;
+	l = nxe;
+	nxe = nye;
+	nye = l;
+	l = nxx;
+	nxx = nyy;
+	nyy = l;
+	l = kx;
+	kx = ky;
+	ky = l;
+	kx1 = kx + 1;
+	ky1 = ky + 1;
+L130:
+	iband = iband1 + 1;
+/*  arrange the data points according to the panel they belong to. */
+	fporde_(&x[1], &y[1], m, &kx, &ky, &tx[1], &nx, &ty[1], &ny, &nummer[
+		1], &index[1], &nreg);
+/*  find ncof, the number of b-spline coefficients. */
+	nk1x = nx - kx1;
+	nk1y = ny - ky1;
+	ncof = nk1x * nk1y;
+/*  initialize the observation matrix a. */
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    f[i__] = (float)0.;
+	    i__3 = iband;
+	    for (j = 1; j <= i__3; ++j) {
+		a[i__ + j * a_dim1] = (float)0.;
+/* L140: */
+	    }
+	}
+/*  initialize the sum of squared residuals. */
+	*fp = (float)0.;
+/*  fetch the data points in the new order. main loop for the */
+/*  different panels. */
+	i__3 = nreg;
+	for (num = 1; num <= i__3; ++num) {
+/*  fix certain constants for the current panel; jrot records the column */
+/*  number of the first non-zero element in a row of the observation */
+/*  matrix according to a data point of the panel. */
+	    num1 = num - 1;
+	    lx = num1 / nyy;
+	    l1 = lx + kx1;
+	    ly = num1 - lx * nyy;
+	    l2 = ly + ky1;
+	    jrot = lx * nk1y + ly;
+/*  test whether there are still data points in the panel. */
+	    in = index[num];
+L150:
+	    if (in == 0) {
+		goto L250;
+	    }
+/*  fetch a new data point. */
+	    wi = w[in];
+	    zi = z__[in] * wi;
+/*  evaluate for the x-direction, the (kx+1) non-zero b-splines at x(in). */
+	    fpbspl_(&tx[1], &nx, &kx, &x[in], &l1, hx);
+/*  evaluate for the y-direction, the (ky+1) non-zero b-splines at y(in). */
+	    fpbspl_(&ty[1], &ny, &ky, &y[in], &l2, hy);
+/*  store the value of these b-splines in spx and spy respectively. */
+	    i__2 = kx1;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		spx[in + i__ * spx_dim1] = hx[i__ - 1];
+/* L160: */
+	    }
+	    i__2 = ky1;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		spy[in + i__ * spy_dim1] = hy[i__ - 1];
+/* L170: */
+	    }
+/*  initialize the new row of observation matrix. */
+	    i__2 = iband;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		h__[i__] = (float)0.;
+/* L180: */
+	    }
+/*  calculate the non-zero elements of the new row by making the cross */
+/*  products of the non-zero b-splines in x- and y-direction. */
+	    i1 = 0;
+	    i__2 = kx1;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		hxi = hx[i__ - 1];
+		j1 = i1;
+		i__4 = ky1;
+		for (j = 1; j <= i__4; ++j) {
+		    ++j1;
+		    h__[j1] = hxi * hy[j - 1] * wi;
+/* L190: */
+		}
+		i1 += nk1y;
+/* L200: */
+	    }
+/*  rotate the row into triangle by givens transformations . */
+	    irot = jrot;
+	    i__2 = iband;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		++irot;
+		piv = h__[i__];
+		if (piv == (float)0.) {
+		    goto L220;
+		}
+/*  calculate the parameters of the givens transformation. */
+		fpgivs_(&piv, &a[irot + a_dim1], &cos__, &sin__);
+/*  apply that transformation to the right hand side. */
+		fprota_(&cos__, &sin__, &zi, &f[irot]);
+		if (i__ == iband) {
+		    goto L230;
+		}
+/*  apply that transformation to the left hand side. */
+		i2 = 1;
+		i3 = i__ + 1;
+		i__4 = iband;
+		for (j = i3; j <= i__4; ++j) {
+		    ++i2;
+		    fprota_(&cos__, &sin__, &h__[j], &a[irot + i2 * a_dim1]);
+/* L210: */
+		}
+L220:
+		;
+	    }
+/*  add the contribution of the row to the sum of squares of residual */
+/*  right hand sides. */
+L230:
+/* Computing 2nd power */
+	    r__1 = zi;
+	    *fp += r__1 * r__1;
+/*  find the number of the next data point in the panel. */
+/* L240: */
+	    in = nummer[in];
+	    goto L150;
+L250:
+	    ;
+	}
+/*  find dmax, the maximum value for the diagonal elements in the reduced */
+/*  triangle. */
+	dmax__ = (float)0.;
+	i__3 = ncof;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    if (a[i__ + a_dim1] <= dmax__) {
+		goto L260;
+	    }
+	    dmax__ = a[i__ + a_dim1];
+L260:
+	    ;
+	}
+/*  check whether the observation matrix is rank deficient. */
+	sigma = eps * dmax__;
+	i__3 = ncof;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    if (a[i__ + a_dim1] <= sigma) {
+		goto L280;
+	    }
+/* L270: */
+	}
+/*  backward substitution in case of full rank. */
+	fpback_(&a[a_offset], &f[1], &ncof, &iband, &c__[1], nc);
+	rank = ncof;
+	i__3 = ncof;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    q[i__ + q_dim1] = a[i__ + a_dim1] / dmax__;
+/* L275: */
+	}
+	goto L300;
+/*  in case of rank deficiency, find the minimum norm solution. */
+/*  check whether there is sufficient working space */
+L280:
+	lwest = ncof * iband + ncof + iband;
+	if (*lwrk < lwest) {
+	    goto L780;
+	}
+	i__3 = ncof;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    ff[i__] = f[i__];
+	    i__2 = iband;
+	    for (j = 1; j <= i__2; ++j) {
+		q[i__ + j * q_dim1] = a[i__ + j * a_dim1];
+/* L290: */
+	    }
+	}
+	lf = 1;
+	lh = lf + ncof;
+	la = lh + iband;
+	fprank_(&q[q_offset], &ff[1], &ncof, &iband, nc, &sigma, &c__[1], &sq,
+		 &rank, &wrk[la], &wrk[lf], &wrk[lh]);
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    q[i__ + q_dim1] /= dmax__;
+/* L295: */
+	}
+/*  add to the sum of squared residuals, the contribution of reducing */
+/*  the rank. */
+	*fp += sq;
+L300:
+	if (*ier == -2) {
+	    *fp0 = *fp;
+	}
+/*  test whether the least-squares spline is an acceptable solution. */
+	if (*iopt < 0) {
+	    goto L820;
+	}
+	fpms = *fp - *s;
+	if (dabs(fpms) <= acc) {
+	    if (*fp <= (float)0.) {
+		goto L815;
+	    } else {
+		goto L820;
+	    }
+	}
+/*  test whether we can accept the choice of knots. */
+	if (fpms < (float)0.) {
+	    goto L430;
+	}
+/*  test whether we cannot further increase the number of knots. */
+	if (ncof > *m) {
+	    goto L790;
+	}
+	*ier = 0;
+/*  search where to add a new knot. */
+/*  find for each interval the sum of squared residuals fpint for the */
+/*  data points having the coordinate belonging to that knot interval. */
+/*  calculate also coord which is the same sum, weighted by the position */
+/*  of the data points considered. */
+/* L310: */
+	i__2 = nrint;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    fpint[i__] = (float)0.;
+	    coord[i__] = (float)0.;
+/* L320: */
+	}
+	i__2 = nreg;
+	for (num = 1; num <= i__2; ++num) {
+	    num1 = num - 1;
+	    lx = num1 / nyy;
+	    l1 = lx + 1;
+	    ly = num1 - lx * nyy;
+	    l2 = ly + 1 + nxx;
+	    jrot = lx * nk1y + ly;
+	    in = index[num];
+L330:
+	    if (in == 0) {
+		goto L360;
+	    }
+	    store = (float)0.;
+	    i1 = jrot;
+	    i__3 = kx1;
+	    for (i__ = 1; i__ <= i__3; ++i__) {
+		hxi = spx[in + i__ * spx_dim1];
+		j1 = i1;
+		i__4 = ky1;
+		for (j = 1; j <= i__4; ++j) {
+		    ++j1;
+		    store += hxi * spy[in + j * spy_dim1] * c__[j1];
+/* L340: */
+		}
+		i1 += nk1y;
+/* L350: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[in] * (z__[in] - store);
+	    store = r__1 * r__1;
+	    fpint[l1] += store;
+	    coord[l1] += store * x[in];
+	    fpint[l2] += store;
+	    coord[l2] += store * y[in];
+	    in = nummer[in];
+	    goto L330;
+L360:
+	    ;
+	}
+/*  find the interval for which fpint is maximal on the condition that */
+/*  there still can be added a knot. */
+L370:
+	l = 0;
+	fpmax = (float)0.;
+	l1 = 1;
+	l2 = nrint;
+	if (nx == nxe) {
+	    l1 = nxx + 1;
+	}
+	if (ny == nye) {
+	    l2 = nxx;
+	}
+	if (l1 > l2) {
+	    goto L810;
+	}
+	i__2 = l2;
+	for (i__ = l1; i__ <= i__2; ++i__) {
+	    if (fpmax >= fpint[i__]) {
+		goto L380;
+	    }
+	    l = i__;
+	    fpmax = fpint[i__];
+L380:
+	    ;
+	}
+/*  test whether we cannot further increase the number of knots. */
+	if (l == 0) {
+	    goto L785;
+	}
+/*  calculate the position of the new knot. */
+	arg = coord[l] / fpint[l];
+/*  test in what direction the new knot is going to be added. */
+	if (l > nxx) {
+	    goto L400;
+	}
+/*  addition in the x-direction. */
+	jxy = l + kx1;
+	fpint[l] = (float)0.;
+	fac1 = tx[jxy] - arg;
+	fac2 = arg - tx[jxy - 1];
+	if (fac1 > ten * fac2 || fac2 > ten * fac1) {
+	    goto L370;
+	}
+	j = nx;
+	i__2 = nx;
+	for (i__ = jxy; i__ <= i__2; ++i__) {
+	    tx[j + 1] = tx[j];
+	    --j;
+/* L390: */
+	}
+	tx[jxy] = arg;
+	++nx;
+	goto L420;
+/*  addition in the y-direction. */
+L400:
+	jxy = l + ky1 - nxx;
+	fpint[l] = (float)0.;
+	fac1 = ty[jxy] - arg;
+	fac2 = arg - ty[jxy - 1];
+	if (fac1 > ten * fac2 || fac2 > ten * fac1) {
+	    goto L370;
+	}
+	j = ny;
+	i__2 = ny;
+	for (i__ = jxy; i__ <= i__2; ++i__) {
+	    ty[j + 1] = ty[j];
+	    --j;
+/* L410: */
+	}
+	ty[jxy] = arg;
+	++ny;
+/*  restart the computations with the new set of knots. */
+L420:
+	;
+    }
+/*  test whether the least-squares polynomial is a solution of our */
+/*  approximation problem. */
+L430:
+    if (*ier == -2) {
+	goto L830;
+    }
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+/* part 2: determination of the smoothing spline sp(x,y)                c */
+/* *****************************************************                c */
+/* we have determined the number of knots and their position. we now    c */
+/* compute the b-spline coefficients of the smoothing spline sp(x,y).   c */
+/* the observation matrix a is extended by the rows of a matrix,        c */
+/* expressing that sp(x,y) must be a polynomial of degree kx in x and   c */
+/* ky in y. the corresponding weights of these additional rows are set  c */
+/* to 1./p.  iteratively we than have to determine the value of p       c */
+/* such that f(p)=sum((w(i)*(z(i)-sp(x(i),y(i))))**2) be = s.           c */
+/* we already know that the least-squares polynomial corresponds to     c */
+/* p=0  and that the least-squares spline corresponds to p=infinity.    c */
+/* the iteration process which is proposed here makes use of rational   c */
+/* interpolation. since f(p) is a convex and strictly decreasing        c */
+/* function of p, it can be approximated by a rational function r(p)=   c */
+/* (u*p+v)/(p+w). three values of p(p1,p2,p3) with corresponding values c */
+/* of f(p) (f1=f(p1)-s,f2=f(p2)-s,f3=f(p3)-s) are used to calculate the c */
+/* new value of p such that r(p)=s. convergence is guaranteed by taking c */
+/* f1 > 0 and f3 < 0.                                                   c */
+/* ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc */
+    kx2 = kx1 + 1;
+/*  test whether there are interior knots in the x-direction. */
+    if (nk1x == kx1) {
+	goto L440;
+    }
+/*  evaluate the discotinuity jumps of the kx-th order derivative of */
+/*  the b-splines at the knots tx(l),l=kx+2,...,nx-kx-1. */
+    fpdisc_(&tx[1], &nx, &kx2, &bx[bx_offset], nmax);
+L440:
+    ky2 = ky1 + 1;
+/*  test whether there are interior knots in the y-direction. */
+    if (nk1y == ky1) {
+	goto L450;
+    }
+/*  evaluate the discontinuity jumps of the ky-th order derivative of */
+/*  the b-splines at the knots ty(l),l=ky+2,...,ny-ky-1. */
+    fpdisc_(&ty[1], &ny, &ky2, &by[by_offset], nmax);
+/*  initial value for p. */
+L450:
+    p1 = (float)0.;
+    f1 = *fp0 - *s;
+    p3 = -one;
+    f3 = fpms;
+    p = (float)0.;
+    i__1 = ncof;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	p += a[i__ + a_dim1];
+/* L460: */
+    }
+    rn = (real) ncof;
+    p = rn / p;
+/*  find the bandwidth of the extended observation matrix. */
+    iband3 = kx1 * nk1y;
+    iband4 = iband3 + 1;
+    ich1 = 0;
+    ich3 = 0;
+/*  iteration process to find the root of f(p)=s. */
+    i__1 = *maxit;
+    for (iter = 1; iter <= i__1; ++iter) {
+	pinv = one / p;
+/*  store the triangularized observation matrix into q. */
+	i__2 = ncof;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ff[i__] = f[i__];
+	    i__3 = iband;
+	    for (j = 1; j <= i__3; ++j) {
+		q[i__ + j * q_dim1] = a[i__ + j * a_dim1];
+/* L470: */
+	    }
+	    ibb = iband + 1;
+	    i__3 = iband4;
+	    for (j = ibb; j <= i__3; ++j) {
+		q[i__ + j * q_dim1] = (float)0.;
+/* L480: */
+	    }
+	}
+	if (nk1y == ky1) {
+	    goto L560;
+	}
+/*  extend the observation matrix with the rows of a matrix, expressing */
+/*  that for x=cst. sp(x,y) must be a polynomial in y of degree ky. */
+	i__3 = nk1y;
+	for (i__ = ky2; i__ <= i__3; ++i__) {
+	    ii = i__ - ky1;
+	    i__2 = nk1x;
+	    for (j = 1; j <= i__2; ++j) {
+/*  initialize the new row. */
+		i__4 = iband;
+		for (l = 1; l <= i__4; ++l) {
+		    h__[l] = (float)0.;
+/* L490: */
+		}
+/*  fill in the non-zero elements of the row. jrot records the column */
+/*  number of the first non-zero element in the row. */
+		i__4 = ky2;
+		for (l = 1; l <= i__4; ++l) {
+		    h__[l] = by[ii + l * by_dim1] * pinv;
+/* L500: */
+		}
+		zi = (float)0.;
+		jrot = (j - 1) * nk1y + ii;
+/*  rotate the new row into triangle by givens transformations without */
+/*  square roots. */
+		i__4 = ncof;
+		for (irot = jrot; irot <= i__4; ++irot) {
+		    piv = h__[1];
+/* Computing MIN */
+		    i__5 = iband1, i__6 = ncof - irot;
+		    i2 = min(i__5,i__6);
+		    if (piv == (float)0.) {
+			if (i2 <= 0) {
+			    goto L550;
+			} else {
+			    goto L520;
+			}
+		    }
+/*  calculate the parameters of the givens transformation. */
+		    fpgivs_(&piv, &q[irot + q_dim1], &cos__, &sin__);
+/*  apply that givens transformation to the right hand side. */
+		    fprota_(&cos__, &sin__, &zi, &ff[irot]);
+		    if (i2 == 0) {
+			goto L550;
+		    }
+/*  apply that givens transformation to the left hand side. */
+		    i__5 = i2;
+		    for (l = 1; l <= i__5; ++l) {
+			l1 = l + 1;
+			fprota_(&cos__, &sin__, &h__[l1], &q[irot + l1 * 
+				q_dim1]);
+/* L510: */
+		    }
+L520:
+		    i__5 = i2;
+		    for (l = 1; l <= i__5; ++l) {
+			h__[l] = h__[l + 1];
+/* L530: */
+		    }
+		    h__[i2 + 1] = (float)0.;
+/* L540: */
+		}
+L550:
+		;
+	    }
+	}
+L560:
+	if (nk1x == kx1) {
+	    goto L640;
+	}
+/*  extend the observation matrix with the rows of a matrix expressing */
+/*  that for y=cst. sp(x,y) must be a polynomial in x of degree kx. */
+	i__2 = nk1x;
+	for (i__ = kx2; i__ <= i__2; ++i__) {
+	    ii = i__ - kx1;
+	    i__3 = nk1y;
+	    for (j = 1; j <= i__3; ++j) {
+/*  initialize the new row */
+		i__4 = iband4;
+		for (l = 1; l <= i__4; ++l) {
+		    h__[l] = (float)0.;
+/* L570: */
+		}
+/*  fill in the non-zero elements of the row. jrot records the column */
+/*  number of the first non-zero element in the row. */
+		j1 = 1;
+		i__4 = kx2;
+		for (l = 1; l <= i__4; ++l) {
+		    h__[j1] = bx[ii + l * bx_dim1] * pinv;
+		    j1 += nk1y;
+/* L580: */
+		}
+		zi = (float)0.;
+		jrot = (i__ - kx2) * nk1y + j;
+/*  rotate the new row into triangle by givens transformations . */
+		i__4 = ncof;
+		for (irot = jrot; irot <= i__4; ++irot) {
+		    piv = h__[1];
+/* Computing MIN */
+		    i__5 = iband3, i__6 = ncof - irot;
+		    i2 = min(i__5,i__6);
+		    if (piv == (float)0.) {
+			if (i2 <= 0) {
+			    goto L630;
+			} else {
+			    goto L600;
+			}
+		    }
+/*  calculate the parameters of the givens transformation. */
+		    fpgivs_(&piv, &q[irot + q_dim1], &cos__, &sin__);
+/*  apply that givens transformation to the right hand side. */
+		    fprota_(&cos__, &sin__, &zi, &ff[irot]);
+		    if (i2 == 0) {
+			goto L630;
+		    }
+/*  apply that givens transformation to the left hand side. */
+		    i__5 = i2;
+		    for (l = 1; l <= i__5; ++l) {
+			l1 = l + 1;
+			fprota_(&cos__, &sin__, &h__[l1], &q[irot + l1 * 
+				q_dim1]);
+/* L590: */
+		    }
+L600:
+		    i__5 = i2;
+		    for (l = 1; l <= i__5; ++l) {
+			h__[l] = h__[l + 1];
+/* L610: */
+		    }
+		    h__[i2 + 1] = (float)0.;
+/* L620: */
+		}
+L630:
+		;
+	    }
+	}
+/*  find dmax, the maximum value for the diagonal elements in the */
+/*  reduced triangle. */
+L640:
+	dmax__ = (float)0.;
+	i__3 = ncof;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    if (q[i__ + q_dim1] <= dmax__) {
+		goto L650;
+	    }
+	    dmax__ = q[i__ + q_dim1];
+L650:
+	    ;
+	}
+/*  check whether the matrix is rank deficient. */
+	sigma = eps * dmax__;
+	i__3 = ncof;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    if (q[i__ + q_dim1] <= sigma) {
+		goto L670;
+	    }
+/* L660: */
+	}
+/*  backward substitution in case of full rank. */
+	fpback_(&q[q_offset], &ff[1], &ncof, &iband4, &c__[1], nc);
+	rank = ncof;
+	goto L675;
+/*  in case of rank deficiency, find the minimum norm solution. */
+L670:
+	lwest = ncof * iband4 + ncof + iband4;
+	if (*lwrk < lwest) {
+	    goto L780;
+	}
+	lf = 1;
+	lh = lf + ncof;
+	la = lh + iband4;
+	fprank_(&q[q_offset], &ff[1], &ncof, &iband4, nc, &sigma, &c__[1], &
+		sq, &rank, &wrk[la], &wrk[lf], &wrk[lh]);
+L675:
+	i__3 = ncof;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    q[i__ + q_dim1] /= dmax__;
+/* L680: */
+	}
+/*  compute f(p). */
+	*fp = (float)0.;
+	i__3 = nreg;
+	for (num = 1; num <= i__3; ++num) {
+	    num1 = num - 1;
+	    lx = num1 / nyy;
+	    ly = num1 - lx * nyy;
+	    jrot = lx * nk1y + ly;
+	    in = index[num];
+L690:
+	    if (in == 0) {
+		goto L720;
+	    }
+	    store = (float)0.;
+	    i1 = jrot;
+	    i__2 = kx1;
+	    for (i__ = 1; i__ <= i__2; ++i__) {
+		hxi = spx[in + i__ * spx_dim1];
+		j1 = i1;
+		i__4 = ky1;
+		for (j = 1; j <= i__4; ++j) {
+		    ++j1;
+		    store += hxi * spy[in + j * spy_dim1] * c__[j1];
+/* L700: */
+		}
+		i1 += nk1y;
+/* L710: */
+	    }
+/* Computing 2nd power */
+	    r__1 = w[in] * (z__[in] - store);
+	    *fp += r__1 * r__1;
+	    in = nummer[in];
+	    goto L690;
+L720:
+	    ;
+	}
+/*  test whether the approximation sp(x,y) is an acceptable solution. */
+	fpms = *fp - *s;
+	if (dabs(fpms) <= acc) {
+	    goto L820;
+	}
+/*  test whether the maximum allowable number of iterations has been */
+/*  reached. */
+	if (iter == *maxit) {
+	    goto L795;
+	}
+/*  carry out one more step of the iteration process. */
+	p2 = p;
+	f2 = fpms;
+	if (ich3 != 0) {
+	    goto L740;
+	}
+	if (f2 - f3 > acc) {
+	    goto L730;
+	}
+/*  our initial choice of p is too large. */
+	p3 = p2;
+	f3 = f2;
+	p *= con4;
+	if (p <= p1) {
+	    p = p1 * con9 + p2 * con1;
+	}
+	goto L770;
+L730:
+	if (f2 < (float)0.) {
+	    ich3 = 1;
+	}
+L740:
+	if (ich1 != 0) {
+	    goto L760;
+	}
+	if (f1 - f2 > acc) {
+	    goto L750;
+	}
+/*  our initial choice of p is too small */
+	p1 = p2;
+	f1 = f2;
+	p /= con4;
+	if (p3 < (float)0.) {
+	    goto L770;
+	}
+	if (p >= p3) {
+	    p = p2 * con1 + p3 * con9;
+	}
+	goto L770;
+L750:
+	if (f2 > (float)0.) {
+	    ich1 = 1;
+	}
+/*  test whether the iteration process proceeds as theoretically */
+/*  expected. */
+L760:
+	if (f2 >= f1 || f2 <= f3) {
+	    goto L800;
+	}
+/*  find the new value of p. */
+	p = fprati_(&p1, &f1, &p2, &f2, &p3, &f3);
+L770:
+	;
+    }
+/*  error codes and messages. */
+L780:
+    *ier = lwest;
+    goto L830;
+L785:
+    *ier = 5;
+    goto L830;
+L790:
+    *ier = 4;
+    goto L830;
+L795:
+    *ier = 3;
+    goto L830;
+L800:
+    *ier = 2;
+    goto L830;
+L810:
+    *ier = 1;
+    goto L830;
+L815:
+    *ier = -1;
+    *fp = (float)0.;
+L820:
+    if (ncof != rank) {
+	*ier = -rank;
+    }
+/*  test whether x and y are in the original order. */
+L830:
+    if (ichang < 0) {
+	goto L930;
+    }
+/*  if not, interchange x and y once more. */
+    l1 = 1;
+    i__1 = nk1x;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	l2 = i__;
+	i__3 = nk1y;
+	for (j = 1; j <= i__3; ++j) {
+	    f[l2] = c__[l1];
+	    ++l1;
+	    l2 += nk1x;
+/* L840: */
+	}
+    }
+    i__3 = ncof;
+    for (i__ = 1; i__ <= i__3; ++i__) {
+	c__[i__] = f[i__];
+/* L850: */
+    }
+    i__3 = *m;
+    for (i__ = 1; i__ <= i__3; ++i__) {
+	store = x[i__];
+	x[i__] = y[i__];
+	y[i__] = store;
+/* L860: */
+    }
+    n = min(nx,ny);
+    i__3 = n;
+    for (i__ = 1; i__ <= i__3; ++i__) {
+	store = tx[i__];
+	tx[i__] = ty[i__];
+	ty[i__] = store;
+/* L870: */
+    }
+    n1 = n + 1;
+    if ((i__3 = nx - ny) < 0) {
+	goto L880;
+    } else if (i__3 == 0) {
+	goto L920;
+    } else {
+	goto L900;
+    }
+L880:
+    i__3 = ny;
+    for (i__ = n1; i__ <= i__3; ++i__) {
+	tx[i__] = ty[i__];
+/* L890: */
+    }
+    goto L920;
+L900:
+    i__3 = nx;
+    for (i__ = n1; i__ <= i__3; ++i__) {
+	ty[i__] = tx[i__];
+/* L910: */
+    }
+L920:
+    l = nx;
+    nx = ny;
+    ny = l;
+L930:
+    if (*iopt < 0) {
+	goto L940;
+    }
+    *nx0 = nx;
+    *ny0 = ny;
+L940:
+    return 0;
+} /* fpsurf_ */
+
+/* Subroutine */ int fpsysy_(a, n, g)
+real *a;
+integer *n;
+real *g;
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Local variables */
+    static integer i__, j, k, i1;
+    static real fac;
+
+/* subroutine fpsysy solves a linear n x n symmetric system */
+/*    (a) * (b) = (g) */
+/* on input, vector g contains the right hand side ; on output it will */
+/* contain the solution (b). */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --g;
+    a -= 7;
+
+    /* Function Body */
+    g[1] /= a[7];
+    if (*n == 1) {
+	return 0;
+    }
+/*  decomposition of the symmetric matrix (a) = (l) * (d) *(l)' */
+/*  with (l) a unit lower triangular matrix and (d) a diagonal */
+/*  matrix */
+    i__1 = *n;
+    for (k = 2; k <= i__1; ++k) {
+	a[k + 6] /= a[7];
+/* L10: */
+    }
+    i__1 = *n;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	i1 = i__ - 1;
+	i__2 = *n;
+	for (k = i__; k <= i__2; ++k) {
+	    fac = a[k + i__ * 6];
+	    i__3 = i1;
+	    for (j = 1; j <= i__3; ++j) {
+		fac -= a[j + j * 6] * a[k + j * 6] * a[i__ + j * 6];
+/* L20: */
+	    }
+	    a[k + i__ * 6] = fac;
+	    if (k > i__) {
+		a[k + i__ * 6] = fac / a[i__ + i__ * 6];
+	    }
+/* L30: */
+	}
+/* L40: */
+    }
+/*  solve the system (l)*(d)*(l)'*(b) = (g). */
+/*  first step : solve (l)*(d)*(c) = (g). */
+    i__1 = *n;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	i1 = i__ - 1;
+	fac = g[i__];
+	i__2 = i1;
+	for (j = 1; j <= i__2; ++j) {
+	    fac -= g[j] * a[j + j * 6] * a[i__ + j * 6];
+/* L50: */
+	}
+	g[i__] = fac / a[i__ + i__ * 6];
+/* L60: */
+    }
+/*  second step : solve (l)'*(b) = (c) */
+    i__ = *n;
+    i__1 = *n;
+    for (j = 2; j <= i__1; ++j) {
+	i1 = i__;
+	--i__;
+	fac = g[i__];
+	i__2 = *n;
+	for (k = i1; k <= i__2; ++k) {
+	    fac -= g[k] * a[k + i__ * 6];
+/* L70: */
+	}
+	g[i__] = fac;
+/* L80: */
+    }
+    return 0;
+} /* fpsysy_ */
+
+/* Subroutine */ int fptrnp_(m, mm, idim, n, nr, sp, p, b, z__, a, q, right)
+integer *m, *mm, *idim, *n, *nr;
+real *sp, *p, *b, *z__, *a, *q, *right;
+{
+    /* System generated locals */
+    integer sp_dim1, sp_offset, b_dim1, b_offset, a_dim1, a_offset, i__1, 
+	    i__2, i__3, i__4;
+
+    /* Local variables */
+    static real pinv;
+    static integer irot;
+    static real h__[7];
+    static integer i__, j, l, iband, nrold, i2, i3, m2, m3, n1, n4, ii, jj, 
+	    it, number;
+    extern /* Subroutine */ int fprota_(), fpgivs_();
+    static integer mid, nmd;
+    static real one, cos__, sin__, piv;
+
+/*  subroutine fptrnp reduces the (m+n-7) x (n-4) matrix a to upper */
+/*  triangular form and applies the same givens transformations to */
+/*  the (m) x (mm) x (idim) matrix z to obtain the (n-4) x (mm) x */
+/*  (idim) matrix q */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..subroutine references.. */
+/*    fpgivs,fprota */
+/*  .. */
+    /* Parameter adjustments */
+    sp_dim1 = *m;
+    sp_offset = 1 + sp_dim1 * 1;
+    sp -= sp_offset;
+    --nr;
+    --right;
+    --z__;
+    --q;
+    a_dim1 = *n;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+    b_dim1 = *n;
+    b_offset = 1 + b_dim1 * 1;
+    b -= b_offset;
+
+    /* Function Body */
+    one = (float)1.;
+    if (*p > (float)0.) {
+	pinv = one / *p;
+    }
+    n4 = *n - 4;
+    mid = *mm * *idim;
+    m2 = *m * *mm;
+    m3 = n4 * *mm;
+/*  reduce the matrix (a) to upper triangular form (r) using givens */
+/*  rotations. apply the same transformations to the rows of matrix z */
+/*  to obtain the mm x (n-4) matrix g. */
+/*  store matrix (r) into (a) and g into q. */
+/*  initialization. */
+    nmd = n4 * mid;
+    i__1 = nmd;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	q[i__] = (float)0.;
+/* L50: */
+    }
+    i__1 = n4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	for (j = 1; j <= 5; ++j) {
+	    a[i__ + j * a_dim1] = (float)0.;
+/* L100: */
+	}
+    }
+    nrold = 0;
+/*  iband denotes the bandwidth of the matrices (a) and (r). */
+    iband = 4;
+    i__1 = *m;
+    for (it = 1; it <= i__1; ++it) {
+	number = nr[it];
+L150:
+	if (nrold == number) {
+	    goto L300;
+	}
+	if (*p <= (float)0.) {
+	    goto L700;
+	}
+	iband = 5;
+/*  fetch a new row of matrix (b). */
+	n1 = nrold + 1;
+	for (j = 1; j <= 5; ++j) {
+	    h__[j - 1] = b[n1 + j * b_dim1] * pinv;
+/* L200: */
+	}
+/*  find the appropriate column of q. */
+	i__2 = mid;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] = (float)0.;
+/* L250: */
+	}
+	irot = nrold;
+	goto L450;
+/*  fetch a new row of matrix (sp). */
+L300:
+	h__[iband - 1] = (float)0.;
+	for (j = 1; j <= 4; ++j) {
+	    h__[j - 1] = sp[it + j * sp_dim1];
+/* L350: */
+	}
+/*  find the appropriate column of q. */
+	j = 0;
+	i__2 = *idim;
+	for (ii = 1; ii <= i__2; ++ii) {
+	    l = (ii - 1) * m2 + (it - 1) * *mm;
+	    i__3 = *mm;
+	    for (jj = 1; jj <= i__3; ++jj) {
+		++j;
+		++l;
+		right[j] = z__[l];
+/* L400: */
+	    }
+	}
+	irot = number;
+/*  rotate the new row of matrix (a) into triangle. */
+L450:
+	i__3 = iband;
+	for (i__ = 1; i__ <= i__3; ++i__) {
+	    ++irot;
+	    piv = h__[i__ - 1];
+	    if (piv == (float)0.) {
+		goto L600;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &a[irot + a_dim1], &cos__, &sin__);
+/*  apply that transformation to the rows of matrix q. */
+	    j = 0;
+	    i__2 = *idim;
+	    for (ii = 1; ii <= i__2; ++ii) {
+		l = (ii - 1) * m3 + irot;
+		i__4 = *mm;
+		for (jj = 1; jj <= i__4; ++jj) {
+		    ++j;
+		    fprota_(&cos__, &sin__, &right[j], &q[l]);
+		    l += n4;
+/* L500: */
+		}
+	    }
+/*  apply that transformation to the columns of (a). */
+	    if (i__ == iband) {
+		goto L650;
+	    }
+	    i2 = 1;
+	    i3 = i__ + 1;
+	    i__4 = iband;
+	    for (j = i3; j <= i__4; ++j) {
+		++i2;
+		fprota_(&cos__, &sin__, &h__[j - 1], &a[irot + i2 * a_dim1]);
+/* L550: */
+	    }
+L600:
+	    ;
+	}
+L650:
+	if (nrold == number) {
+	    goto L750;
+	}
+L700:
+	++nrold;
+	goto L150;
+L750:
+	;
+    }
+    return 0;
+} /* fptrnp_ */
+
+/* Subroutine */ int fptrpe_(m, mm, idim, n, nr, sp, p, b, z__, a, aa, q, 
+	right)
+integer *m, *mm, *idim, *n, *nr;
+real *sp, *p, *b, *z__, *a, *aa, *q, *right;
+{
+    /* System generated locals */
+    integer sp_dim1, sp_offset, b_dim1, b_offset, a_dim1, a_offset, aa_dim1, 
+	    aa_offset, i__1, i__2, i__3, i__4;
+
+    /* Local variables */
+    static integer jper;
+    static real pinv;
+    static integer irot;
+    static real h__[5];
+    static integer i__, j, l, nrold;
+    static real h1[5], h2[4];
+    static integer i2, i3, l0, m1, m2, m3, n1, n4, l1, i1, n7, j1, n11;
+    static real co;
+    static integer ii, jj, jk, ik, ij;
+    static real si;
+    static integer it, number;
+    extern /* Subroutine */ int fprota_(), fpgivs_();
+    static integer mid, nmd;
+    static real one, piv;
+
+/*  subroutine fptrpe reduces the (m+n-7) x (n-7) cyclic bandmatrix a */
+/*  to upper triangular form and applies the same givens transformations */
+/*  to the (m) x (mm) x (idim) matrix z to obtain the (n-7) x (mm) x */
+/*  (idim) matrix q. */
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays.. */
+/*  ..subroutine references.. */
+/*    fpgivs,fprota */
+/*  .. */
+    /* Parameter adjustments */
+    sp_dim1 = *m;
+    sp_offset = 1 + sp_dim1 * 1;
+    sp -= sp_offset;
+    --nr;
+    --right;
+    --z__;
+    --q;
+    aa_dim1 = *n;
+    aa_offset = 1 + aa_dim1 * 1;
+    aa -= aa_offset;
+    a_dim1 = *n;
+    a_offset = 1 + a_dim1 * 1;
+    a -= a_offset;
+    b_dim1 = *n;
+    b_offset = 1 + b_dim1 * 1;
+    b -= b_offset;
+
+    /* Function Body */
+    one = (float)1.;
+    if (*p > (float)0.) {
+	pinv = one / *p;
+    }
+    n4 = *n - 4;
+    n7 = *n - 7;
+    n11 = *n - 11;
+    mid = *mm * *idim;
+    m2 = *m * *mm;
+    m3 = n7 * *mm;
+    m1 = *m - 1;
+/*  we determine the matrix (a) and then we reduce her to */
+/*  upper triangular form (r) using givens rotations. */
+/*  we apply the same transformations to the rows of matrix */
+/*  z to obtain the (mm) x (n-7) matrix g. */
+/*  we store matrix (r) into a and aa, g into q. */
+/*  the n7 x n7 upper triangular matrix (r) has the form */
+/*             | a1 '     | */
+/*       (r) = |    ' a2  | */
+/*             |  0 '     | */
+/*  with (a2) a n7 x 4 matrix and (a1) a n11 x n11 upper */
+/*  triangular matrix of bandwidth 5. */
+/*  initialization. */
+    nmd = n7 * mid;
+    i__1 = nmd;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	q[i__] = (float)0.;
+/* L50: */
+    }
+    i__1 = n4;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	a[i__ + a_dim1 * 5] = (float)0.;
+	for (j = 1; j <= 4; ++j) {
+	    a[i__ + j * a_dim1] = (float)0.;
+	    aa[i__ + j * aa_dim1] = (float)0.;
+/* L100: */
+	}
+    }
+    jper = 0;
+    nrold = 0;
+    i__1 = m1;
+    for (it = 1; it <= i__1; ++it) {
+	number = nr[it];
+L120:
+	if (nrold == number) {
+	    goto L180;
+	}
+	if (*p <= (float)0.) {
+	    goto L740;
+	}
+/*  fetch a new row of matrix (b). */
+	n1 = nrold + 1;
+	for (j = 1; j <= 5; ++j) {
+	    h__[j - 1] = b[n1 + j * b_dim1] * pinv;
+/* L140: */
+	}
+/*  find the appropiate row of q. */
+	i__2 = mid;
+	for (j = 1; j <= i__2; ++j) {
+	    right[j] = (float)0.;
+/* L160: */
+	}
+	goto L240;
+/*  fetch a new row of matrix (sp) */
+L180:
+	h__[4] = (float)0.;
+	for (j = 1; j <= 4; ++j) {
+	    h__[j - 1] = sp[it + j * sp_dim1];
+/* L200: */
+	}
+/*  find the appropiate row of q. */
+	j = 0;
+	i__2 = *idim;
+	for (ii = 1; ii <= i__2; ++ii) {
+	    l = (ii - 1) * m2 + (it - 1) * *mm;
+	    i__3 = *mm;
+	    for (jj = 1; jj <= i__3; ++jj) {
+		++j;
+		++l;
+		right[j] = z__[l];
+/* L220: */
+	    }
+	}
+/*  test whether there are non-zero values in the new row of (a) */
+/*  corresponding to the b-splines n(j,*),j=n7+1,...,n4. */
+L240:
+	if (nrold < n11) {
+	    goto L640;
+	}
+	if (jper != 0) {
+	    goto L320;
+	}
+/*  initialize the matrix (aa). */
+	jk = n11 + 1;
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    ik = jk;
+	    for (j = 1; j <= 5; ++j) {
+		if (ik <= 0) {
+		    goto L280;
+		}
+		aa[ik + i__ * aa_dim1] = a[ik + j * a_dim1];
+		--ik;
+/* L260: */
+	    }
+L280:
+	    ++jk;
+/* L300: */
+	}
+	jper = 1;
+/*  if one of the non-zero elements of the new row corresponds to one of */
+/*  the b-splines n(j;*),j=n7+1,...,n4,we take account of the periodicity */
+/*  conditions for setting up this row of (a). */
+L320:
+	for (i__ = 1; i__ <= 4; ++i__) {
+	    h1[i__ - 1] = (float)0.;
+	    h2[i__ - 1] = (float)0.;
+/* L340: */
+	}
+	h1[4] = (float)0.;
+	j = nrold - n11;
+	for (i__ = 1; i__ <= 5; ++i__) {
+	    ++j;
+	    l0 = j;
+L360:
+	    l1 = l0 - 4;
+	    if (l1 <= 0) {
+		goto L400;
+	    }
+	    if (l1 <= n11) {
+		goto L380;
+	    }
+	    l0 = l1 - n11;
+	    goto L360;
+L380:
+	    h1[l1 - 1] = h__[i__ - 1];
+	    goto L420;
+L400:
+	    h2[l0 - 1] += h__[i__ - 1];
+L420:
+	    ;
+	}
+/*  rotate the new row of (a) into triangle. */
+	if (n11 <= 0) {
+	    goto L560;
+	}
+/*  rotations with the rows 1,2,...,n11 of (a). */
+	i__3 = n11;
+	for (irot = 1; irot <= i__3; ++irot) {
+	    piv = h1[0];
+/* Computing MIN */
+	    i__2 = n11 - irot;
+	    i2 = min(i__2,4);
+	    if (piv == (float)0.) {
+		goto L500;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &a[irot + a_dim1], &co, &si);
+/*  apply that transformation to the columns of matrix q. */
+	    j = 0;
+	    i__2 = *idim;
+	    for (ii = 1; ii <= i__2; ++ii) {
+		l = (ii - 1) * m3 + irot;
+		i__4 = *mm;
+		for (jj = 1; jj <= i__4; ++jj) {
+		    ++j;
+		    fprota_(&co, &si, &right[j], &q[l]);
+		    l += n7;
+/* L440: */
+		}
+	    }
+/*  apply that transformation to the rows of (a) with respect to aa. */
+	    for (i__ = 1; i__ <= 4; ++i__) {
+		fprota_(&co, &si, &h2[i__ - 1], &aa[irot + i__ * aa_dim1]);
+/* L460: */
+	    }
+/*  apply that transformation to the rows of (a) with respect to a. */
+	    if (i2 == 0) {
+		goto L560;
+	    }
+	    i__4 = i2;
+	    for (i__ = 1; i__ <= i__4; ++i__) {
+		i1 = i__ + 1;
+		fprota_(&co, &si, &h1[i1 - 1], &a[irot + i1 * a_dim1]);
+/* L480: */
+	    }
+L500:
+	    i__4 = i2;
+	    for (i__ = 1; i__ <= i__4; ++i__) {
+		h1[i__ - 1] = h1[i__];
+/* L520: */
+	    }
+	    h1[i2] = (float)0.;
+/* L540: */
+	}
+/*  rotations with the rows n11+1,...,n7 of a. */
+L560:
+	for (irot = 1; irot <= 4; ++irot) {
+	    ij = n11 + irot;
+	    if (ij <= 0) {
+		goto L620;
+	    }
+	    piv = h2[irot - 1];
+	    if (piv == (float)0.) {
+		goto L620;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &aa[ij + irot * aa_dim1], &co, &si);
+/*  apply that transformation to the columns of matrix q. */
+	    j = 0;
+	    i__3 = *idim;
+	    for (ii = 1; ii <= i__3; ++ii) {
+		l = (ii - 1) * m3 + ij;
+		i__4 = *mm;
+		for (jj = 1; jj <= i__4; ++jj) {
+		    ++j;
+		    fprota_(&co, &si, &right[j], &q[l]);
+		    l += n7;
+/* L580: */
+		}
+	    }
+	    if (irot == 4) {
+		goto L620;
+	    }
+/*  apply that transformation to the rows of (a) with respect to aa. */
+	    j1 = irot + 1;
+	    for (i__ = j1; i__ <= 4; ++i__) {
+		fprota_(&co, &si, &h2[i__ - 1], &aa[ij + i__ * aa_dim1]);
+/* L600: */
+	    }
+L620:
+	    ;
+	}
+	goto L720;
+/*  rotation into triangle of the new row of (a), in case the elements */
+/*  corresponding to the b-splines n(j;*),j=n7+1,...,n4 are all zero. */
+L640:
+	irot = nrold;
+	for (i__ = 1; i__ <= 5; ++i__) {
+	    ++irot;
+	    piv = h__[i__ - 1];
+	    if (piv == (float)0.) {
+		goto L700;
+	    }
+/*  calculate the parameters of the givens transformation. */
+	    fpgivs_(&piv, &a[irot + a_dim1], &co, &si);
+/*  apply that transformation to the columns of matrix g. */
+	    j = 0;
+	    i__4 = *idim;
+	    for (ii = 1; ii <= i__4; ++ii) {
+		l = (ii - 1) * m3 + irot;
+		i__3 = *mm;
+		for (jj = 1; jj <= i__3; ++jj) {
+		    ++j;
+		    fprota_(&co, &si, &right[j], &q[l]);
+		    l += n7;
+/* L660: */
+		}
+	    }
+/*  apply that transformation to the rows of (a). */
+	    if (i__ == 5) {
+		goto L700;
+	    }
+	    i2 = 1;
+	    i3 = i__ + 1;
+	    for (j = i3; j <= 5; ++j) {
+		++i2;
+		fprota_(&co, &si, &h__[j - 1], &a[irot + i2 * a_dim1]);
+/* L680: */
+	    }
+L700:
+	    ;
+	}
+L720:
+	if (nrold == number) {
+	    goto L760;
+	}
+L740:
+	++nrold;
+	goto L120;
+L760:
+	;
+    }
+    return 0;
+} /* fptrpe_ */
+
+/* Subroutine */ int insert_(iopt, t, n, c__, k, x, tt, nn, cc, nest, ier)
+integer *iopt;
+real *t;
+integer *n;
+real *c__;
+integer *k;
+real *x, *tt;
+integer *nn;
+real *cc;
+integer *nest, *ier;
+{
+    static integer l, k1, kk, nk;
+    extern /* Subroutine */ int fpinst_();
+    static integer nk1;
+
+/*  subroutine insert inserts a new knot x into a spline function s(x) */
+/*  of degree k and calculates the b-spline representation of s(x) with */
+/*  respect to the new set of knots. in addition, if iopt.ne.0, s(x) */
+/*  will be considered as a periodic spline with period per=t(n-k)-t(k+1) */
+/*  satisfying the boundary constraints */
+/*       t(i+n-2*k-1) = t(i)+per  ,i=1,2,...,2*k+1 */
+/*       c(i+n-2*k-1) = c(i)      ,i=1,2,...,k */
+/*  in that case, the knots and b-spline coefficients returned will also */
+/*  satisfy these boundary constraints, i.e. */
+/*       tt(i+nn-2*k-1) = tt(i)+per  ,i=1,2,...,2*k+1 */
+/*       cc(i+nn-2*k-1) = cc(i)      ,i=1,2,...,k */
+
+/*  calling sequence: */
+/*     call insert(iopt,t,n,c,k,x,tt,nn,cc,nest,ier) */
+
+/*  input parameters: */
+/*    iopt : integer flag, specifying whether (iopt.ne.0) or not (iopt=0) */
+/*           the given spline must be considered as being periodic. */
+/*    t    : array,length nest, which contains the position of the knots. */
+/*    n    : integer, giving the total number of knots of s(x). */
+/*    c    : array,length nest, which contains the b-spline coefficients. */
+/*    k    : integer, giving the degree of s(x). */
+/*    x    : real, which gives the location of the knot to be inserted. */
+/*    nest : integer specifying the dimension of the arrays t,c,tt and cc */
+/*           nest > n. */
+
+/*  output parameters: */
+/*    tt   : array,length nest, which contains the position of the knots */
+/*           after insertion. */
+/*    nn   : integer, giving the total number of knots after insertion */
+/*    cc   : array,length nest, which contains the b-spline coefficients */
+/*           of s(x) with respect to the new set of knots. */
+/*    ier  : error flag */
+/*      ier = 0 : normal return */
+/*      ier =10 : invalid input data (see restrictions) */
+
+/*  restrictions: */
+/*    nest > n */
+/*    t(k+1) <= x <= t(n-k) */
+/*    in case of a periodic spline (iopt.ne.0) there must be */
+/*       either at least k interior knots t(j) satisfying t(k+1)<t(j)<=x */
+/*       or at least k interior knots t(j) satisfying x<=t(j)<t(n-k) */
+
+/*  other subroutines required: fpinst. */
+
+/*  further comments: */
+/*   subroutine insert may be called as follows */
+/*        call insert(iopt,t,n,c,k,x,t,n,c,nest,ier) */
+/*   in which case the new representation will simply replace the old one */
+
+/*  references : */
+/*    boehm w : inserting new knots into b-spline curves. computer aided */
+/*              design 12 (1980) 199-201. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1987 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid control is immediately repassed to the calling program. */
+    /* Parameter adjustments */
+    --cc;
+    --tt;
+    --c__;
+    --t;
+
+    /* Function Body */
+    *ier = 10;
+    if (*nest <= *n) {
+	goto L40;
+    }
+    k1 = *k + 1;
+    nk = *n - *k;
+    if (*x < t[k1] || *x > t[nk]) {
+	goto L40;
+    }
+/*  search for knot interval t(l) <= x < t(l+1). */
+    nk1 = nk - 1;
+    l = k1;
+L10:
+    if (*x < t[l + 1] || l == nk1) {
+	goto L20;
+    }
+    ++l;
+    goto L10;
+L20:
+    if (t[l] >= t[l + 1]) {
+	goto L40;
+    }
+    if (*iopt == 0) {
+	goto L30;
+    }
+    kk = *k << 1;
+    if (l <= kk && l >= *n - kk) {
+	goto L40;
+    }
+L30:
+    *ier = 0;
+/*  insert the new knot. */
+    fpinst_(iopt, &t[1], n, &c__[1], k, x, &l, &tt[1], nn, &cc[1], nest);
+L40:
+    return 0;
+} /* insert_ */
+
+/* Subroutine */ int parcur_(iopt, ipar, idim, m, u, mx, x, w, ub, ue, k, s, 
+	nest, n, t, nc, c__, fp, wrk, lwrk, iwrk, ier)
+integer *iopt, *ipar, *idim, *m;
+real *u;
+integer *mx;
+real *x, *w, *ub, *ue;
+integer *k;
+real *s;
+integer *nest, *n;
+real *t;
+integer *nc;
+real *c__, *fp, *wrk;
+integer *lwrk, *iwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+    real r__1;
+
+    /* Builtin functions */
+    double sqrt();
+
+    /* Local variables */
+    static integer nmin;
+    static real dist;
+    static integer i__, j, maxit, i1, i2, k1, k2, lwest, ia, ib, ig;
+    extern /* Subroutine */ int fpchec_();
+    static integer iq, iz;
+    extern /* Subroutine */ int fppara_();
+    static integer ncc, ifp;
+    static real tol;
+
+/*  given the ordered set of m points x(i) in the idim-dimensional space */
+/*  and given also a corresponding set of strictly increasing values u(i) */
+/*  and the set of positive numbers w(i),i=1,2,...,m, subroutine parcur */
+/*  determines a smooth approximating spline curve s(u), i.e. */
+/*      x1 = s1(u) */
+/*      x2 = s2(u)       ub <= u <= ue */
+/*      ......... */
+/*      xidim = sidim(u) */
+/*  with sj(u),j=1,2,...,idim spline functions of degree k with common */
+/*  knots t(j),j=1,2,...,n. */
+/*  if ipar=1 the values ub,ue and u(i),i=1,2,...,m must be supplied by */
+/*  the user. if ipar=0 these values are chosen automatically by parcur */
+/*  as  v(1) = 0 */
+/*      v(i) = v(i-1) + dist(x(i),x(i-1)) ,i=2,3,...,m */
+/*      u(i) = v(i)/v(m) ,i=1,2,...,m */
+/*      ub = u(1) = 0, ue = u(m) = 1. */
+/*  if iopt=-1 parcur calculates the weighted least-squares spline curve */
+/*  according to a given set of knots. */
+/*  if iopt>=0 the number of knots of the splines sj(u) and the position */
+/*  t(j),j=1,2,...,n is chosen automatically by the routine. the smooth- */
+/*  ness of s(u) is then achieved by minimalizing the discontinuity */
+/*  jumps of the k-th derivative of s(u) at the knots t(j),j=k+2,k+3,..., */
+/*  n-k-1. the amount of smoothness is determined by the condition that */
+/*  f(p)=sum((w(i)*dist(x(i),s(u(i))))**2) be <= s, with s a given non- */
+/*  negative constant, called the smoothing factor. */
+/*  the fit s(u) is given in the b-spline representation and can be */
+/*  evaluated by means of subroutine curev. */
+
+/*  calling sequence: */
+/*     call parcur(iopt,ipar,idim,m,u,mx,x,w,ub,ue,k,s,nest,n,t,nc,c, */
+/*    * fp,wrk,lwrk,iwrk,ier) */
+
+/*  parameters: */
+/*   iopt  : integer flag. on entry iopt must specify whether a weighted */
+/*           least-squares spline curve (iopt=-1) or a smoothing spline */
+/*           curve (iopt=0 or 1) must be determined.if iopt=0 the routine */
+/*           will start with an initial set of knots t(i)=ub,t(i+k+1)=ue, */
+/*           i=1,2,...,k+1. if iopt=1 the routine will continue with the */
+/*           knots found at the last call of the routine. */
+/*           attention: a call with iopt=1 must always be immediately */
+/*           preceded by another call with iopt=1 or iopt=0. */
+/*           unchanged on exit. */
+/*   ipar  : integer flag. on entry ipar must specify whether (ipar=1) */
+/*           the user will supply the parameter values u(i),ub and ue */
+/*           or whether (ipar=0) these values are to be calculated by */
+/*           parcur. unchanged on exit. */
+/*   idim  : integer. on entry idim must specify the dimension of the */
+/*           curve. 0 < idim < 11. */
+/*           unchanged on exit. */
+/*   m     : integer. on entry m must specify the number of data points. */
+/*           m > k. unchanged on exit. */
+/*   u     : real array of dimension at least (m). in case ipar=1,before */
+/*           entry, u(i) must be set to the i-th value of the parameter */
+/*           variable u for i=1,2,...,m. these values must then be */
+/*           supplied in strictly ascending order and will be unchanged */
+/*           on exit. in case ipar=0, on exit,array u will contain the */
+/*           values u(i) as determined by parcur. */
+/*   mx    : integer. on entry mx must specify the actual dimension of */
+/*           the array x as declared in the calling (sub)program. mx must */
+/*           not be too small (see x). unchanged on exit. */
+/*   x     : real array of dimension at least idim*m. */
+/*           before entry, x(idim*(i-1)+j) must contain the j-th coord- */
+/*           inate of the i-th data point for i=1,2,...,m and j=1,2,..., */
+/*           idim. unchanged on exit. */
+/*   w     : real array of dimension at least (m). before entry, w(i) */
+/*           must be set to the i-th value in the set of weights. the */
+/*           w(i) must be strictly positive. unchanged on exit. */
+/*           see also further comments. */
+/*   ub,ue : real values. on entry (in case ipar=1) ub and ue must */
+/*           contain the lower and upper bound for the parameter u. */
+/*           ub <=u(1), ue>= u(m). if ipar = 0 these values will */
+/*           automatically be set to 0 and 1 by parcur. */
+/*   k     : integer. on entry k must specify the degree of the splines. */
+/*           1<=k<=5. it is recommended to use cubic splines (k=3). */
+/*           the user is strongly dissuaded from choosing k even,together */
+/*           with a small s-value. unchanged on exit. */
+/*   s     : real.on entry (in case iopt>=0) s must specify the smoothing */
+/*           factor. s >=0. unchanged on exit. */
+/*           for advice on the choice of s see further comments. */
+/*   nest  : integer. on entry nest must contain an over-estimate of the */
+/*           total number of knots of the splines returned, to indicate */
+/*           the storage space available to the routine. nest >=2*k+2. */
+/*           in most practical situation nest=m/2 will be sufficient. */
+/*           always large enough is nest=m+k+1, the number of knots */
+/*           needed for interpolation (s=0). unchanged on exit. */
+/*   n     : integer. */
+/*           unless ier = 10 (in case iopt >=0), n will contain the */
+/*           total number of knots of the smoothing spline curve returned */
+/*           if the computation mode iopt=1 is used this value of n */
+/*           should be left unchanged between subsequent calls. */
+/*           in case iopt=-1, the value of n must be specified on entry. */
+/*   t     : real array of dimension at least (nest). */
+/*           on succesful exit, this array will contain the knots of the */
+/*           spline curve,i.e. the position of the interior knots t(k+2), */
+/*           t(k+3),..,t(n-k-1) as well as the position of the additional */
+/*           t(1)=t(2)=...=t(k+1)=ub and t(n-k)=...=t(n)=ue needed for */
+/*           the b-spline representation. */
+/*           if the computation mode iopt=1 is used, the values of t(1), */
+/*           t(2),...,t(n) should be left unchanged between subsequent */
+/*           calls. if the computation mode iopt=-1 is used, the values */
+/*           t(k+2),...,t(n-k-1) must be supplied by the user, before */
+/*           entry. see also the restrictions (ier=10). */
+/*   nc    : integer. on entry nc must specify the actual dimension of */
+/*           the array c as declared in the calling (sub)program. nc */
+/*           must not be too small (see c). unchanged on exit. */
+/*   c     : real array of dimension at least (nest*idim). */
+/*           on succesful exit, this array will contain the coefficients */
+/*           in the b-spline representation of the spline curve s(u),i.e. */
+/*           the b-spline coefficients of the spline sj(u) will be given */
+/*           in c(n*(j-1)+i),i=1,2,...,n-k-1 for j=1,2,...,idim. */
+/*   fp    : real. unless ier = 10, fp contains the weighted sum of */
+/*           squared residuals of the spline curve returned. */
+/*   wrk   : real array of dimension at least m*(k+1)+nest*(6+idim+3*k). */
+/*           used as working space. if the computation mode iopt=1 is */
+/*           used, the values wrk(1),...,wrk(n) should be left unchanged */
+/*           between subsequent calls. */
+/*   lwrk  : integer. on entry,lwrk must specify the actual dimension of */
+/*           the array wrk as declared in the calling (sub)program. lwrk */
+/*           must not be too small (see wrk). unchanged on exit. */
+/*   iwrk  : integer array of dimension at least (nest). */
+/*           used as working space. if the computation mode iopt=1 is */
+/*           used,the values iwrk(1),...,iwrk(n) should be left unchanged */
+/*           between subsequent calls. */
+/*   ier   : integer. unless the routine detects an error, ier contains a */
+/*           non-positive value on exit, i.e. */
+/*    ier=0  : normal return. the curve returned has a residual sum of */
+/*             squares fp such that abs(fp-s)/s <= tol with tol a relat- */
+/*             ive tolerance set to 0.001 by the program. */
+/*    ier=-1 : normal return. the curve returned is an interpolating */
+/*             spline curve (fp=0). */
+/*    ier=-2 : normal return. the curve returned is the weighted least- */
+/*             squares polynomial curve of degree k.in this extreme case */
+/*             fp gives the upper bound fp0 for the smoothing factor s. */
+/*    ier=1  : error. the required storage space exceeds the available */
+/*             storage space, as specified by the parameter nest. */
+/*             probably causes : nest too small. if nest is already */
+/*             large (say nest > m/2), it may also indicate that s is */
+/*             too small */
+/*             the approximation returned is the least-squares spline */
+/*             curve according to the knots t(1),t(2),...,t(n). (n=nest) */
+/*             the parameter fp gives the corresponding weighted sum of */
+/*             squared residuals (fp>s). */
+/*    ier=2  : error. a theoretically impossible result was found during */
+/*             the iteration proces for finding a smoothing spline curve */
+/*             with fp = s. probably causes : s too small. */
+/*             there is an approximation returned but the corresponding */
+/*             weighted sum of squared residuals does not satisfy the */
+/*             condition abs(fp-s)/s < tol. */
+/*    ier=3  : error. the maximal number of iterations maxit (set to 20 */
+/*             by the program) allowed for finding a smoothing curve */
+/*             with fp=s has been reached. probably causes : s too small */
+/*             there is an approximation returned but the corresponding */
+/*             weighted sum of squared residuals does not satisfy the */
+/*             condition abs(fp-s)/s < tol. */
+/*    ier=10 : error. on entry, the input data are controlled on validity */
+/*             the following restrictions must be satisfied. */
+/*             -1<=iopt<=1, 1<=k<=5, m>k, nest>2*k+2, w(i)>0,i=1,2,...,m */
+/*             0<=ipar<=1, 0<idim<=10, lwrk>=(k+1)*m+nest*(6+idim+3*k), */
+/*             nc>=nest*idim */
+/*             if ipar=0: sum j=1,idim (x(idim*i+j)-x(idim*(i-1)+j))**2>0 */
+/*                        i=1,2,...,m-1. */
+/*             if ipar=1: ub<=u(1)<u(2)<...<u(m)<=ue */
+/*             if iopt=-1: 2*k+2<=n<=min(nest,m+k+1) */
+/*                         ub<t(k+2)<t(k+3)<...<t(n-k-1)<ue */
+/*                            (ub=0 and ue=1 in case ipar=0) */
+/*                       the schoenberg-whitney conditions, i.e. there */
+/*                       must be a subset of data points uu(j) such that */
+/*                         t(j) < uu(j) < t(j+k+1), j=1,2,...,n-k-1 */
+/*             if iopt>=0: s>=0 */
+/*                         if s=0 : nest >= m+k+1 */
+/*             if one of these conditions is found to be violated,control */
+/*             is immediately repassed to the calling program. in that */
+/*             case there is no approximation returned. */
+
+/*  further comments: */
+/*   by means of the parameter s, the user can control the tradeoff */
+/*   between closeness of fit and smoothness of fit of the approximation. */
+/*   if s is too large, the curve will be too smooth and signal will be */
+/*   lost ; if s is too small the curve will pick up too much noise. in */
+/*   the extreme cases the program will return an interpolating curve if */
+/*   s=0 and the least-squares polynomial curve of degree k if s is */
+/*   very large. between these extremes, a properly chosen s will result */
+/*   in a good compromise between closeness of fit and smoothness of fit. */
+/*   to decide whether an approximation, corresponding to a certain s is */
+/*   satisfactory the user is highly recommended to inspect the fits */
+/*   graphically. */
+/*   recommended values for s depend on the weights w(i). if these are */
+/*   taken as 1/d(i) with d(i) an estimate of the standard deviation of */
+/*   x(i), a good s-value should be found in the range (m-sqrt(2*m),m+ */
+/*   sqrt(2*m)). if nothing is known about the statistical error in x(i) */
+/*   each w(i) can be set equal to one and s determined by trial and */
+/*   error, taking account of the comments above. the best is then to */
+/*   start with a very large value of s ( to determine the least-squares */
+/*   polynomial curve and the upper bound fp0 for s) and then to */
+/*   progressively decrease the value of s ( say by a factor 10 in the */
+/*   beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the */
+/*   approximating curve shows more detail) to obtain closer fits. */
+/*   to economize the search for a good s-value the program provides with */
+/*   different modes of computation. at the first call of the routine, or */
+/*   whenever he wants to restart with the initial set of knots the user */
+/*   must set iopt=0. */
+/*   if iopt=1 the program will continue with the set of knots found at */
+/*   the last call of the routine. this will save a lot of computation */
+/*   time if parcur is called repeatedly for different values of s. */
+/*   the number of knots of the spline returned and their location will */
+/*   depend on the value of s and on the complexity of the shape of the */
+/*   curve underlying the data. but, if the computation mode iopt=1 is */
+/*   used, the knots returned may also depend on the s-values at previous */
+/*   calls (if these were smaller). therefore, if after a number of */
+/*   trials with different s-values and iopt=1, the user can finally */
+/*   accept a fit as satisfactory, it may be worthwhile for him to call */
+/*   parcur once more with the selected value for s but now with iopt=0. */
+/*   indeed, parcur may then return an approximation of the same quality */
+/*   of fit but with fewer knots and therefore better if data reduction */
+/*   is also an important objective for the user. */
+
+/*   the form of the approximating curve can strongly be affected by */
+/*   the choice of the parameter values u(i). if there is no physical */
+/*   reason for choosing a particular parameter u, often good results */
+/*   will be obtained with the choice of parcur (in case ipar=0), i.e. */
+/*        v(1)=0, v(i)=v(i-1)+q(i), i=2,...,m, u(i)=v(i)/v(m), i=1,..,m */
+/*   where */
+/*        q(i)= sqrt(sum j=1,idim (xj(i)-xj(i-1))**2 ) */
+/*   other possibilities for q(i) are */
+/*        q(i)= sum j=1,idim (xj(i)-xj(i-1))**2 */
+/*        q(i)= sum j=1,idim abs(xj(i)-xj(i-1)) */
+/*        q(i)= max j=1,idim abs(xj(i)-xj(i-1)) */
+/*        q(i)= 1 */
+
+/*  other subroutines required: */
+/*    fpback,fpbspl,fpchec,fppara,fpdisc,fpgivs,fpknot,fprati,fprota */
+
+/*  references: */
+/*   dierckx p. : algorithms for smoothing data with periodic and */
+/*                parametric splines, computer graphics and image */
+/*                processing 20 (1982) 171-184. */
+/*   dierckx p. : algorithms for smoothing data with periodic and param- */
+/*                etric splines, report tw55, dept. computer science, */
+/*                k.u.leuven, 1981. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*    p.dierckx */
+/*    dept. computer science, k.u. leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : may 1979 */
+/*  latest update : march 1987 */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/* ..function references */
+/*  .. */
+/*  we set up the parameters tol and maxit */
+    /* Parameter adjustments */
+    --w;
+    --u;
+    --x;
+    --iwrk;
+    --t;
+    --c__;
+    --wrk;
+
+    /* Function Body */
+    maxit = 20;
+    tol = (float).001;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*iopt < -1 || *iopt > 1) {
+	goto L90;
+    }
+    if (*ipar < 0 || *ipar > 1) {
+	goto L90;
+    }
+    if (*idim <= 0 || *idim > 10) {
+	goto L90;
+    }
+    if (*k <= 0 || *k > 5) {
+	goto L90;
+    }
+    k1 = *k + 1;
+    k2 = k1 + 1;
+    nmin = k1 << 1;
+    if (*m < k1 || *nest < nmin) {
+	goto L90;
+    }
+    ncc = *nest * *idim;
+    if (*mx < *m * *idim || *nc < ncc) {
+	goto L90;
+    }
+    lwest = *m * k1 + *nest * (*idim + 6 + *k * 3);
+    if (*lwrk < lwest) {
+	goto L90;
+    }
+    if (*ipar != 0 || *iopt > 0) {
+	goto L40;
+    }
+    i1 = 0;
+    i2 = *idim;
+    u[1] = (float)0.;
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	dist = (float)0.;
+	i__2 = *idim;
+	for (j = 1; j <= i__2; ++j) {
+	    ++i1;
+	    ++i2;
+/* Computing 2nd power */
+	    r__1 = x[i2] - x[i1];
+	    dist += r__1 * r__1;
+/* L10: */
+	}
+	u[i__] = u[i__ - 1] + sqrt(dist);
+/* L20: */
+    }
+    if (u[*m] <= (float)0.) {
+	goto L90;
+    }
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	u[i__] /= u[*m];
+/* L30: */
+    }
+    *ub = (float)0.;
+    *ue = (float)1.;
+    u[*m] = *ue;
+L40:
+    if (*ub > u[1] || *ue < u[*m] || w[1] <= (float)0.) {
+	goto L90;
+    }
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (u[i__ - 1] >= u[i__] || w[i__] <= (float)0.) {
+	    goto L90;
+	}
+/* L50: */
+    }
+    if (*iopt >= 0) {
+	goto L70;
+    }
+    if (*n < nmin || *n > *nest) {
+	goto L90;
+    }
+    j = *n;
+    i__1 = k1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	t[i__] = *ub;
+	t[j] = *ue;
+	--j;
+/* L60: */
+    }
+    fpchec_(&u[1], m, &t[1], n, k, ier);
+    if (*ier != 0) {
+	goto L90;
+    } else {
+	goto L80;
+    }
+L70:
+    if (*s < (float)0.) {
+	goto L90;
+    }
+    if (*s == (float)0. && *nest < *m + k1) {
+	goto L90;
+    }
+    *ier = 0;
+/* we partition the working space and determine the spline curve. */
+L80:
+    ifp = 1;
+    iz = ifp + *nest;
+    ia = iz + ncc;
+    ib = ia + *nest * k1;
+    ig = ib + *nest * k2;
+    iq = ig + *nest * k2;
+    fppara_(iopt, idim, m, &u[1], mx, &x[1], &w[1], ub, ue, k, s, nest, &tol, 
+	    &maxit, &k1, &k2, n, &t[1], &ncc, &c__[1], fp, &wrk[ifp], &wrk[iz]
+	    , &wrk[ia], &wrk[ib], &wrk[ig], &wrk[iq], &iwrk[1], ier);
+L90:
+    return 0;
+} /* parcur_ */
+
+/* Subroutine */ int parder_(tx, nx, ty, ny, c__, kx, ky, nux, nuy, x, mx, y, 
+	my, z__, wrk, lwrk, iwrk, kwrk, ier)
+real *tx;
+integer *nx;
+real *ty;
+integer *ny;
+real *c__;
+integer *kx, *ky, *nux, *nuy;
+real *x;
+integer *mx;
+real *y;
+integer *my;
+real *z__, *wrk;
+integer *lwrk, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2, i__3;
+
+    /* Local variables */
+    static integer i__, j, m, l1, lwest, l2, m0, m1;
+    static real ak;
+    static integer nc, lx, ly;
+    extern /* Subroutine */ int fpbisp_();
+    static integer kx1, ky1;
+    static real fac;
+    static integer kkx, kky, iwx, iwy, nxx, nyy, nkx1, nky1;
+
+/*  subroutine parder evaluates on a grid (x(i),y(j)),i=1,...,mx; j=1,... */
+/*  ,my the partial derivative ( order nux,nuy) of a bivariate spline */
+/*  s(x,y) of degrees kx and ky, given in the b-spline representation. */
+
+/*  calling sequence: */
+/*     call parder(tx,nx,ty,ny,c,kx,ky,nux,nuy,x,mx,y,my,z,wrk,lwrk, */
+/*    * iwrk,kwrk,ier) */
+
+/*  input parameters: */
+/*   tx    : real array, length nx, which contains the position of the */
+/*           knots in the x-direction. */
+/*   nx    : integer, giving the total number of knots in the x-direction */
+/*   ty    : real array, length ny, which contains the position of the */
+/*           knots in the y-direction. */
+/*   ny    : integer, giving the total number of knots in the y-direction */
+/*   c     : real array, length (nx-kx-1)*(ny-ky-1), which contains the */
+/*           b-spline coefficients. */
+/*   kx,ky : integer values, giving the degrees of the spline. */
+/*   nux   : integer values, specifying the order of the partial */
+/*   nuy     derivative. 0<=nux<kx, 0<=nuy<ky. */
+/*   x     : real array of dimension (mx). */
+/*           before entry x(i) must be set to the x co-ordinate of the */
+/*           i-th grid point along the x-axis. */
+/*           tx(kx+1)<=x(i-1)<=x(i)<=tx(nx-kx), i=2,...,mx. */
+/*   mx    : on entry mx must specify the number of grid points along */
+/*           the x-axis. mx >=1. */
+/*   y     : real array of dimension (my). */
+/*           before entry y(j) must be set to the y co-ordinate of the */
+/*           j-th grid point along the y-axis. */
+/*           ty(ky+1)<=y(j-1)<=y(j)<=ty(ny-ky), j=2,...,my. */
+/*   my    : on entry my must specify the number of grid points along */
+/*           the y-axis. my >=1. */
+/*   wrk   : real array of dimension lwrk. used as workspace. */
+/*   lwrk  : integer, specifying the dimension of wrk. */
+/*           lwrk >= mx*(kx+1-nux)+my*(ky+1-nuy)+(nx-kx-1)*(ny-ky-1) */
+/*   iwrk  : integer array of dimension kwrk. used as workspace. */
+/*   kwrk  : integer, specifying the dimension of iwrk. kwrk >= mx+my. */
+
+/*  output parameters: */
+/*   z     : real array of dimension (mx*my). */
+/*           on succesful exit z(my*(i-1)+j) contains the value of the */
+/*           specified partial derivative of s(x,y) at the point */
+/*           (x(i),y(j)),i=1,...,mx;j=1,...,my. */
+/*   ier   : integer error flag */
+/*    ier=0 : normal return */
+/*    ier=10: invalid input data (see restrictions) */
+
+/*  restrictions: */
+/*   mx >=1, my >=1, 0 <= nux < kx, 0 <= nuy < ky, kwrk>=mx+my */
+/*   lwrk>=mx*(kx+1-nux)+my*(ky+1-nuy)+(nx-kx-1)*(ny-ky-1), */
+/*   tx(kx+1) <= x(i-1) <= x(i) <= tx(nx-kx), i=2,...,mx */
+/*   ty(ky+1) <= y(j-1) <= y(j) <= ty(ny-ky), j=2,...,my */
+
+/*  other subroutines required: */
+/*    fpbisp,fpbspl */
+
+/*  references : */
+/*    de boor c : on calculating with b-splines, j. approximation theory */
+/*                6 (1972) 50-62. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1989 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid control is immediately repassed to the calling program. */
+    /* Parameter adjustments */
+    --tx;
+    --ty;
+    --c__;
+    --x;
+    --z__;
+    --y;
+    --wrk;
+    --iwrk;
+
+    /* Function Body */
+    *ier = 10;
+    kx1 = *kx + 1;
+    ky1 = *ky + 1;
+    nkx1 = *nx - kx1;
+    nky1 = *ny - ky1;
+    nc = nkx1 * nky1;
+    if (*nux < 0 || *nux >= *kx) {
+	goto L400;
+    }
+    if (*nuy < 0 || *nuy >= *ky) {
+	goto L400;
+    }
+    lwest = nc + (kx1 - *nux) * *mx + (ky1 - *nuy) * *my;
+    if (*lwrk < lwest) {
+	goto L400;
+    }
+    if (*kwrk < *mx + *my) {
+	goto L400;
+    }
+    if ((i__1 = *mx - 1) < 0) {
+	goto L400;
+    } else if (i__1 == 0) {
+	goto L30;
+    } else {
+	goto L10;
+    }
+L10:
+    i__1 = *mx;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (x[i__] < x[i__ - 1]) {
+	    goto L400;
+	}
+/* L20: */
+    }
+L30:
+    if ((i__1 = *my - 1) < 0) {
+	goto L400;
+    } else if (i__1 == 0) {
+	goto L60;
+    } else {
+	goto L40;
+    }
+L40:
+    i__1 = *my;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (y[i__] < y[i__ - 1]) {
+	    goto L400;
+	}
+/* L50: */
+    }
+L60:
+    *ier = 0;
+    nxx = nkx1;
+    nyy = nky1;
+    kkx = *kx;
+    kky = *ky;
+/*  the partial derivative of order (nux,nuy) of a bivariate spline of */
+/*  degrees kx,ky is a bivariate spline of degrees kx-nux,ky-nuy. */
+/*  we calculate the b-spline coefficients of this spline */
+    i__1 = nc;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	wrk[i__] = c__[i__];
+/* L70: */
+    }
+    if (*nux == 0) {
+	goto L200;
+    }
+    lx = 1;
+    i__1 = *nux;
+    for (j = 1; j <= i__1; ++j) {
+	ak = (real) kkx;
+	--nxx;
+	l1 = lx;
+	m0 = 1;
+	i__2 = nxx;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ++l1;
+	    l2 = l1 + kkx;
+	    fac = tx[l2] - tx[l1];
+	    if (fac <= (float)0.) {
+		goto L90;
+	    }
+	    i__3 = nyy;
+	    for (m = 1; m <= i__3; ++m) {
+		m1 = m0 + nyy;
+		wrk[m0] = (wrk[m1] - wrk[m0]) * ak / fac;
+		++m0;
+/* L80: */
+	    }
+L90:
+	    ;
+	}
+	++lx;
+	--kkx;
+/* L100: */
+    }
+L200:
+    if (*nuy == 0) {
+	goto L300;
+    }
+    ly = 1;
+    i__1 = *nuy;
+    for (j = 1; j <= i__1; ++j) {
+	ak = (real) kky;
+	--nyy;
+	l1 = ly;
+	i__2 = nyy;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ++l1;
+	    l2 = l1 + kky;
+	    fac = ty[l2] - ty[l1];
+	    if (fac <= (float)0.) {
+		goto L220;
+	    }
+	    m0 = i__;
+	    i__3 = nxx;
+	    for (m = 1; m <= i__3; ++m) {
+		m1 = m0 + 1;
+		wrk[m0] = (wrk[m1] - wrk[m0]) * ak / fac;
+		m0 += nky1;
+/* L210: */
+	    }
+L220:
+	    ;
+	}
+	++ly;
+	--kky;
+/* L230: */
+    }
+    m0 = nyy;
+    m1 = nky1;
+    i__1 = nxx;
+    for (m = 2; m <= i__1; ++m) {
+	i__2 = nyy;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ++m0;
+	    ++m1;
+	    wrk[m0] = wrk[m1];
+/* L240: */
+	}
+	m1 += *nuy;
+/* L250: */
+    }
+/*  we partition the working space and evaluate the partial derivative */
+L300:
+    iwx = nxx * nyy + 1;
+    iwy = iwx + *mx * (kx1 - *nux);
+    i__1 = *nx - (*nux << 1);
+    i__2 = *ny - (*nuy << 1);
+    fpbisp_(&tx[*nux + 1], &i__1, &ty[*nuy + 1], &i__2, &wrk[1], &kkx, &kky, &
+	    x[1], mx, &y[1], my, &z__[1], &wrk[iwx], &wrk[iwy], &iwrk[1], &
+	    iwrk[*mx + 1]);
+L400:
+    return 0;
+} /* parder_ */
+
+/* Subroutine */ int parsur_(iopt, ipar, idim, mu, u, mv, v, f, s, nuest, 
+	nvest, nu, tu, nv, tv, c__, fp, wrk, lwrk, iwrk, kwrk, ier)
+integer *iopt, *ipar, *idim, *mu;
+real *u;
+integer *mv;
+real *v, *f, *s;
+integer *nuest, *nvest, *nu;
+real *tu;
+integer *nv;
+real *tv, *c__, *fp, *wrk;
+integer *lwrk, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer kndu, kndv, lfpu, lfpv;
+    static real peru, perv;
+    static integer jwrk, knru, knrv, i__, j, maxit, mumin, mvmin, kwest, l1, 
+	    l2, l3, l4, lwest, nc, mf;
+    static real ub, vb;
+    extern /* Subroutine */ int fpchec_();
+    static real ue, ve;
+    extern /* Subroutine */ int fpchep_(), fppasu_();
+    static real tol;
+    static integer lww;
+
+/*  given the set of ordered points f(i,j) in the idim-dimensional space, */
+/*  corresponding to grid values (u(i),v(j)) ,i=1,...,mu ; j=1,...,mv, */
+/*  parsur determines a smooth approximating spline surface s(u,v) , i.e. */
+/*    f1 = s1(u,v) */
+/*      ...                u(1) <= u <= u(mu) ; v(1) <= v <= v(mv) */
+/*    fidim = sidim(u,v) */
+/*  with sl(u,v), l=1,2,...,idim bicubic spline functions with common */
+/*  knots tu(i),i=1,...,nu in the u-variable and tv(j),j=1,...,nv in the */
+/*  v-variable. */
+/*  in addition, these splines will be periodic in the variable u if */
+/*  ipar(1) = 1 and periodic in the variable v if ipar(2) = 1. */
+/*  if iopt=-1, parsur determines the least-squares bicubic spline */
+/*  surface according to a given set of knots. */
+/*  if iopt>=0, the number of knots of s(u,v) and their position */
+/*  is chosen automatically by the routine. the smoothness of s(u,v) is */
+/*  achieved by minimalizing the discontinuity jumps of the derivatives */
+/*  of the splines at the knots. the amount of smoothness of s(u,v) is */
+/*  determined by the condition that */
+/*  fp=sumi=1,mu(sumj=1,mv(dist(f(i,j)-s(u(i),v(j)))**2))<=s, */
+/*  with s a given non-negative constant. */
+/*  the fit s(u,v) is given in its b-spline representation and can be */
+/*  evaluated by means of routine surev. */
+
+/* calling sequence: */
+/*     call parsur(iopt,ipar,idim,mu,u,mv,v,f,s,nuest,nvest,nu,tu, */
+/*    *  nv,tv,c,fp,wrk,lwrk,iwrk,kwrk,ier) */
+
+/* parameters: */
+/*  iopt  : integer flag. unchanged on exit. */
+/*          on entry iopt must specify whether a least-squares surface */
+/*          (iopt=-1) or a smoothing surface (iopt=0 or 1)must be */
+/*          determined. */
+/*          if iopt=0 the routine will start with the initial set of */
+/*          knots needed for determining the least-squares polynomial */
+/*          surface. */
+/*          if iopt=1 the routine will continue with the set of knots */
+/*          found at the last call of the routine. */
+/*          attention: a call with iopt=1 must always be immediately */
+/*          preceded by another call with iopt = 1 or iopt = 0. */
+/*  ipar  : integer array of dimension 2. unchanged on exit. */
+/*          on entry ipar(1) must specify whether (ipar(1)=1) or not */
+/*          (ipar(1)=0) the splines must be periodic in the variable u. */
+/*          on entry ipar(2) must specify whether (ipar(2)=1) or not */
+/*          (ipar(2)=0) the splines must be periodic in the variable v. */
+/*  idim  : integer. on entry idim must specify the dimension of the */
+/*          surface. 1 <= idim <= 3. unchanged on exit. */
+/*  mu    : integer. on entry mu must specify the number of grid points */
+/*          along the u-axis. unchanged on exit. */
+/*          mu >= mumin where mumin=4-2*ipar(1) */
+/*  u     : real array of dimension at least (mu). before entry, u(i) */
+/*          must be set to the u-co-ordinate of the i-th grid point */
+/*          along the u-axis, for i=1,2,...,mu. these values must be */
+/*          supplied in strictly ascending order. unchanged on exit. */
+/*  mv    : integer. on entry mv must specify the number of grid points */
+/*          along the v-axis. unchanged on exit. */
+/*          mv >= mvmin where mvmin=4-2*ipar(2) */
+/*  v     : real array of dimension at least (mv). before entry, v(j) */
+/*          must be set to the v-co-ordinate of the j-th grid point */
+/*          along the v-axis, for j=1,2,...,mv. these values must be */
+/*          supplied in strictly ascending order. unchanged on exit. */
+/*  f     : real array of dimension at least (mu*mv*idim). */
+/*          before entry, f(mu*mv*(l-1)+mv*(i-1)+j) must be set to the */
+/*          l-th co-ordinate of the data point corresponding to the */
+/*          the grid point (u(i),v(j)) for l=1,...,idim ,i=1,...,mu */
+/*          and j=1,...,mv. unchanged on exit. */
+/*          if ipar(1)=1 it is expected that f(mu*mv*(l-1)+mv*(mu-1)+j) */
+/*          = f(mu*mv*(l-1)+j), l=1,...,idim ; j=1,...,mv */
+/*          if ipar(2)=1 it is expected that f(mu*mv*(l-1)+mv*(i-1)+mv) */
+/*          = f(mu*mv*(l-1)+mv*(i-1)+1), l=1,...,idim ; i=1,...,mu */
+/*  s     : real. on entry (if iopt>=0) s must specify the smoothing */
+/*          factor. s >=0. unchanged on exit. */
+/*          for advice on the choice of s see further comments */
+/*  nuest : integer. unchanged on exit. */
+/*  nvest : integer. unchanged on exit. */
+/*          on entry, nuest and nvest must specify an upper bound for the */
+/*          number of knots required in the u- and v-directions respect. */
+/*          these numbers will also determine the storage space needed by */
+/*          the routine. nuest >= 8, nvest >= 8. */
+/*          in most practical situation nuest = mu/2, nvest=mv/2, will */
+/*          be sufficient. always large enough are nuest=mu+4+2*ipar(1), */
+/*          nvest = mv+4+2*ipar(2), the number of knots needed for */
+/*          interpolation (s=0). see also further comments. */
+/*  nu    : integer. */
+/*          unless ier=10 (in case iopt>=0), nu will contain the total */
+/*          number of knots with respect to the u-variable, of the spline */
+/*          surface returned. if the computation mode iopt=1 is used, */
+/*          the value of nu should be left unchanged between subsequent */
+/*          calls. in case iopt=-1, the value of nu should be specified */
+/*          on entry. */
+/*  tu    : real array of dimension at least (nuest). */
+/*          on succesful exit, this array will contain the knots of the */
+/*          splines with respect to the u-variable, i.e. the position of */
+/*          the interior knots tu(5),...,tu(nu-4) as well as the position */
+/*          of the additional knots tu(1),...,tu(4) and tu(nu-3),..., */
+/*          tu(nu) needed for the b-spline representation. */
+/*          if the computation mode iopt=1 is used,the values of tu(1) */
+/*          ...,tu(nu) should be left unchanged between subsequent calls. */
+/*          if the computation mode iopt=-1 is used, the values tu(5), */
+/*          ...tu(nu-4) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  nv    : integer. */
+/*          unless ier=10 (in case iopt>=0), nv will contain the total */
+/*          number of knots with respect to the v-variable, of the spline */
+/*          surface returned. if the computation mode iopt=1 is used, */
+/*          the value of nv should be left unchanged between subsequent */
+/*          calls. in case iopt=-1, the value of nv should be specified */
+/*          on entry. */
+/*  tv    : real array of dimension at least (nvest). */
+/*          on succesful exit, this array will contain the knots of the */
+/*          splines with respect to the v-variable, i.e. the position of */
+/*          the interior knots tv(5),...,tv(nv-4) as well as the position */
+/*          of the additional knots tv(1),...,tv(4) and tv(nv-3),..., */
+/*          tv(nv) needed for the b-spline representation. */
+/*          if the computation mode iopt=1 is used,the values of tv(1) */
+/*          ...,tv(nv) should be left unchanged between subsequent calls. */
+/*          if the computation mode iopt=-1 is used, the values tv(5), */
+/*          ...tv(nv-4) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  c     : real array of dimension at least (nuest-4)*(nvest-4)*idim. */
+/*          on succesful exit, c contains the coefficients of the spline */
+/*          approximation s(u,v) */
+/*  fp    : real. unless ier=10, fp contains the sum of squared */
+/*          residuals of the spline surface returned. */
+/*  wrk   : real array of dimension (lwrk). used as workspace. */
+/*          if the computation mode iopt=1 is used the values of */
+/*          wrk(1),...,wrk(4) should be left unchanged between subsequent */
+/*          calls. */
+/*  lwrk  : integer. on entry lwrk must specify the actual dimension of */
+/*          the array wrk as declared in the calling (sub)program. */
+/*          lwrk must not be too small. */
+/*           lwrk >= 4+nuest*(mv*idim+11+4*ipar(1))+nvest*(11+4*ipar(2))+ */
+/*           4*(mu+mv)+q*idim where q is the larger of mv and nuest. */
+/*  iwrk  : integer array of dimension (kwrk). used as workspace. */
+/*          if the computation mode iopt=1 is used the values of */
+/*          iwrk(1),.,iwrk(3) should be left unchanged between subsequent */
+/*          calls. */
+/*  kwrk  : integer. on entry kwrk must specify the actual dimension of */
+/*          the array iwrk as declared in the calling (sub)program. */
+/*          kwrk >= 3+mu+mv+nuest+nvest. */
+/*  ier   : integer. unless the routine detects an error, ier contains a */
+/*          non-positive value on exit, i.e. */
+/*   ier=0  : normal return. the surface returned has a residual sum of */
+/*            squares fp such that abs(fp-s)/s <= tol with tol a relat- */
+/*            ive tolerance set to 0.001 by the program. */
+/*   ier=-1 : normal return. the spline surface returned is an */
+/*            interpolating surface (fp=0). */
+/*   ier=-2 : normal return. the surface returned is the least-squares */
+/*            polynomial surface. in this extreme case fp gives the */
+/*            upper bound for the smoothing factor s. */
+/*   ier=1  : error. the required storage space exceeds the available */
+/*            storage space, as specified by the parameters nuest and */
+/*            nvest. */
+/*            probably causes : nuest or nvest too small. if these param- */
+/*            eters are already large, it may also indicate that s is */
+/*            too small */
+/*            the approximation returned is the least-squares surface */
+/*            according to the current set of knots. the parameter fp */
+/*            gives the corresponding sum of squared residuals (fp>s). */
+/*   ier=2  : error. a theoretically impossible result was found during */
+/*            the iteration proces for finding a smoothing surface with */
+/*            fp = s. probably causes : s too small. */
+/*            there is an approximation returned but the corresponding */
+/*            sum of squared residuals does not satisfy the condition */
+/*            abs(fp-s)/s < tol. */
+/*   ier=3  : error. the maximal number of iterations maxit (set to 20 */
+/*            by the program) allowed for finding a smoothing surface */
+/*            with fp=s has been reached. probably causes : s too small */
+/*            there is an approximation returned but the corresponding */
+/*            sum of squared residuals does not satisfy the condition */
+/*            abs(fp-s)/s < tol. */
+/*   ier=10 : error. on entry, the input data are controlled on validity */
+/*            the following restrictions must be satisfied. */
+/*            -1<=iopt<=1, 0<=ipar(1)<=1, 0<=ipar(2)<=1, 1 <=idim<=3 */
+/*            mu >= 4-2*ipar(1),mv >= 4-2*ipar(2), nuest >=8, nvest >= 8, */
+/*            kwrk>=3+mu+mv+nuest+nvest, */
+/*            lwrk >= 4+nuest*(mv*idim+11+4*ipar(1))+nvest*(11+4*ipar(2)) */
+/*             +4*(mu+mv)+max(nuest,mv)*idim */
+/*            u(i-1)<u(i),i=2,..,mu, v(i-1)<v(i),i=2,...,mv */
+/*            if iopt=-1: 8<=nu<=min(nuest,mu+4+2*ipar(1)) */
+/*                        u(1)<tu(5)<tu(6)<...<tu(nu-4)<u(mu) */
+/*                        8<=nv<=min(nvest,mv+4+2*ipar(2)) */
+/*                        v(1)<tv(5)<tv(6)<...<tv(nv-4)<v(mv) */
+/*                    the schoenberg-whitney conditions, i.e. there must */
+/*                    be subset of grid co-ordinates uu(p) and vv(q) such */
+/*                    that   tu(p) < uu(p) < tu(p+4) ,p=1,...,nu-4 */
+/*                           tv(q) < vv(q) < tv(q+4) ,q=1,...,nv-4 */
+/*                     (see fpchec or fpchep) */
+/*            if iopt>=0: s>=0 */
+/*                       if s=0: nuest>=mu+4+2*ipar(1) */
+/*                               nvest>=mv+4+2*ipar(2) */
+/*            if one of these conditions is found to be violated,control */
+/*            is immediately repassed to the calling program. in that */
+/*            case there is no approximation returned. */
+
+/* further comments: */
+/*   by means of the parameter s, the user can control the tradeoff */
+/*   between closeness of fit and smoothness of fit of the approximation. */
+/*   if s is too large, the surface will be too smooth and signal will be */
+/*   lost ; if s is too small the surface will pick up too much noise. in */
+/*   the extreme cases the program will return an interpolating surface */
+/*   if s=0 and the constrained least-squares polynomial surface if s is */
+/*   very large. between these extremes, a properly chosen s will result */
+/*   in a good compromise between closeness of fit and smoothness of fit. */
+/*   to decide whether an approximation, corresponding to a certain s is */
+/*   satisfactory the user is highly recommended to inspect the fits */
+/*   graphically. */
+/*   recommended values for s depend on the accuracy of the data values. */
+/*   if the user has an idea of the statistical errors on the data, he */
+/*   can also find a proper estimate for s. for, by assuming that, if he */
+/*   specifies the right s, parsur will return a surface s(u,v) which */
+/*   exactly reproduces the surface underlying the data he can evaluate */
+/*   the sum(dist(f(i,j)-s(u(i),v(j)))**2) to find a good estimate for s. */
+/*   for example, if he knows that the statistical errors on his f(i,j)- */
+/*   values is not greater than 0.1, he may expect that a good s should */
+/*   have a value not larger than mu*mv*(0.1)**2. */
+/*   if nothing is known about the statistical error in f(i,j), s must */
+/*   be determined by trial and error, taking account of the comments */
+/*   above. the best is then to start with a very large value of s (to */
+/*   determine the le-sq polynomial surface and the corresponding upper */
+/*   bound fp0 for s) and then to progressively decrease the value of s */
+/*   ( say by a factor 10 in the beginning, i.e. s=fp0/10,fp0/100,... */
+/*   and more carefully as the approximation shows more detail) to */
+/*   obtain closer fits. */
+/*   to economize the search for a good s-value the program provides with */
+/*   different modes of computation. at the first call of the routine, or */
+/*   whenever he wants to restart with the initial set of knots the user */
+/*   must set iopt=0. */
+/*   if iopt = 1 the program will continue with the knots found at */
+/*   the last call of the routine. this will save a lot of computation */
+/*   time if parsur is called repeatedly for different values of s. */
+/*   the number of knots of the surface returned and their location will */
+/*   depend on the value of s and on the complexity of the shape of the */
+/*   surface underlying the data. if the computation mode iopt = 1 */
+/*   is used, the knots returned may also depend on the s-values at */
+/*   previous calls (if these were smaller). therefore, if after a number */
+/*   of trials with different s-values and iopt=1,the user can finally */
+/*   accept a fit as satisfactory, it may be worthwhile for him to call */
+/*   parsur once more with the chosen value for s but now with iopt=0. */
+/*   indeed, parsur may then return an approximation of the same quality */
+/*   of fit but with fewer knots and therefore better if data reduction */
+/*   is also an important objective for the user. */
+/*   the number of knots may also depend on the upper bounds nuest and */
+/*   nvest. indeed, if at a certain stage in parsur the number of knots */
+/*   in one direction (say nu) has reached the value of its upper bound */
+/*   (nuest), then from that moment on all subsequent knots are added */
+/*   in the other (v) direction. this may indicate that the value of */
+/*   nuest is too small. on the other hand, it gives the user the option */
+/*   of limiting the number of knots the routine locates in any direction */
+/*   for example, by setting nuest=8 (the lowest allowable value for */
+/*   nuest), the user can indicate that he wants an approximation with */
+/*   splines which are simple cubic polynomials in the variable u. */
+
+/*  other subroutines required: */
+/*    fppasu,fpchec,fpchep,fpknot,fprati,fpgrpa,fptrnp,fpback, */
+/*    fpbacp,fpbspl,fptrpe,fpdisc,fpgivs,fprota */
+
+/*  author: */
+/*    p.dierckx */
+/*    dept. computer science, k.u. leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1989 */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fppasu,fpchec,fpchep */
+/*  .. */
+/*  we set up the parameters tol and maxit. */
+    /* Parameter adjustments */
+    --ipar;
+    --u;
+    --f;
+    --v;
+    --tu;
+    --c__;
+    --tv;
+    --wrk;
+    --iwrk;
+
+    /* Function Body */
+    maxit = 20;
+    tol = (float).001;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*iopt < -1 || *iopt > 1) {
+	goto L200;
+    }
+    if (ipar[1] < 0 || ipar[1] > 1) {
+	goto L200;
+    }
+    if (ipar[2] < 0 || ipar[2] > 1) {
+	goto L200;
+    }
+    if (*idim <= 0 || *idim > 3) {
+	goto L200;
+    }
+    mumin = 4 - (ipar[1] << 1);
+    if (*mu < mumin || *nuest < 8) {
+	goto L200;
+    }
+    mvmin = 4 - (ipar[2] << 1);
+    if (*mv < mvmin || *nvest < 8) {
+	goto L200;
+    }
+    mf = *mu * *mv;
+    nc = (*nuest - 4) * (*nvest - 4);
+    lwest = *nuest * (*mv * *idim + 11 + (ipar[1] << 2)) + 4 + *nvest * ((
+	    ipar[2] << 2) + 11) + (*mu + *mv << 2) + max(*nuest,*mv) * *idim;
+    kwest = *mu + 3 + *mv + *nuest + *nvest;
+    if (*lwrk < lwest || *kwrk < kwest) {
+	goto L200;
+    }
+    i__1 = *mu;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (u[i__ - 1] >= u[i__]) {
+	    goto L200;
+	}
+/* L10: */
+    }
+    i__1 = *mv;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (v[i__ - 1] >= v[i__]) {
+	    goto L200;
+	}
+/* L20: */
+    }
+    if (*iopt >= 0) {
+	goto L100;
+    }
+    if (*nu < 8 || *nu > *nuest) {
+	goto L200;
+    }
+    ub = u[1];
+    ue = u[*mu];
+    if (ipar[1] != 0) {
+	goto L40;
+    }
+    j = *nu;
+    for (i__ = 1; i__ <= 4; ++i__) {
+	tu[i__] = ub;
+	tu[j] = ue;
+	--j;
+/* L30: */
+    }
+    fpchec_(&u[1], mu, &tu[1], nu, &c__3, ier);
+    if (*ier != 0) {
+	goto L200;
+    }
+    goto L60;
+L40:
+    l1 = 4;
+    l2 = l1;
+    l3 = *nu - 3;
+    l4 = l3;
+    peru = ue - ub;
+    tu[l2] = ub;
+    tu[l3] = ue;
+    for (j = 1; j <= 3; ++j) {
+	++l1;
+	--l2;
+	++l3;
+	--l4;
+	tu[l2] = tu[l4] - peru;
+	tu[l3] = tu[l1] + peru;
+/* L50: */
+    }
+    fpchep_(&u[1], mu, &tu[1], nu, &c__3, ier);
+    if (*ier != 0) {
+	goto L200;
+    }
+L60:
+    if (*nv < 8 || *nv > *nvest) {
+	goto L200;
+    }
+    vb = v[1];
+    ve = v[*mv];
+    if (ipar[2] != 0) {
+	goto L80;
+    }
+    j = *nv;
+    for (i__ = 1; i__ <= 4; ++i__) {
+	tv[i__] = vb;
+	tv[j] = ve;
+	--j;
+/* L70: */
+    }
+    fpchec_(&v[1], mv, &tv[1], nv, &c__3, ier);
+    if (*ier != 0) {
+	goto L200;
+    }
+    goto L150;
+L80:
+    l1 = 4;
+    l2 = l1;
+    l3 = *nv - 3;
+    l4 = l3;
+    perv = ve - vb;
+    tv[l2] = vb;
+    tv[l3] = ve;
+    for (j = 1; j <= 3; ++j) {
+	++l1;
+	--l2;
+	++l3;
+	--l4;
+	tv[l2] = tv[l4] - perv;
+	tv[l3] = tv[l1] + perv;
+/* L90: */
+    }
+    fpchep_(&v[1], mv, &tv[1], nv, &c__3, ier);
+    if (*ier != 0) {
+	goto L200;
+    } else {
+	goto L150;
+    }
+L100:
+    if (*s < (float)0.) {
+	goto L200;
+    }
+    if (*s == (float)0. && (*nuest < *mu + 4 + (ipar[1] << 1) || *nvest < *mv 
+	    + 4 + (ipar[2] << 1))) {
+	goto L200;
+    }
+    *ier = 0;
+/*  we partition the working space and determine the spline approximation */
+L150:
+    lfpu = 5;
+    lfpv = lfpu + *nuest;
+    lww = lfpv + *nvest;
+    jwrk = *lwrk - 4 - *nuest - *nvest;
+    knru = 4;
+    knrv = knru + *mu;
+    kndu = knrv + *mv;
+    kndv = kndu + *nuest;
+    fppasu_(iopt, &ipar[1], idim, &u[1], mu, &v[1], mv, &f[1], &mf, s, nuest, 
+	    nvest, &tol, &maxit, &nc, nu, &tu[1], nv, &tv[1], &c__[1], fp, &
+	    wrk[1], &wrk[2], &wrk[3], &wrk[4], &wrk[lfpu], &wrk[lfpv], &iwrk[
+	    1], &iwrk[2], &iwrk[3], &iwrk[knru], &iwrk[knrv], &iwrk[kndu], &
+	    iwrk[kndv], &wrk[lww], &jwrk, ier);
+L200:
+    return 0;
+} /* parsur_ */
+
+/* Subroutine */ int percur_(iopt, m, x, y, w, k, s, nest, n, t, c__, fp, wrk,
+	 lwrk, iwrk, ier)
+integer *iopt, *m;
+real *x, *y, *w;
+integer *k;
+real *s;
+integer *nest, *n;
+real *t, *c__, *fp, *wrk;
+integer *lwrk, *iwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer nmin, i__, maxit, i1, i2, j1, j2, k1, k2, lwest, m1, ib, 
+	    iq, iz;
+    extern /* Subroutine */ int fpchep_(), fpperi_();
+    static integer ia1, ia2, ig1, ig2, ifp;
+    static real per, tol;
+
+/*  given the set of data points (x(i),y(i)) and the set of positive */
+/*  numbers w(i),i=1,2,...,m-1, subroutine percur determines a smooth */
+/*  periodic spline approximation of degree k with period per=x(m)-x(1). */
+/*  if iopt=-1 percur calculates the weighted least-squares periodic */
+/*  spline according to a given set of knots. */
+/*  if iopt>=0 the number of knots of the spline s(x) and the position */
+/*  t(j),j=1,2,...,n is chosen automatically by the routine. the smooth- */
+/*  ness of s(x) is then achieved by minimalizing the discontinuity */
+/*  jumps of the k-th derivative of s(x) at the knots t(j),j=k+2,k+3,..., */
+/*  n-k-1. the amount of smoothness is determined by the condition that */
+/*  f(p)=sum((w(i)*(y(i)-s(x(i))))**2) be <= s, with s a given non- */
+/*  negative constant, called the smoothing factor. */
+/*  the fit s(x) is given in the b-spline representation (b-spline coef- */
+/*  ficients c(j),j=1,2,...,n-k-1) and can be evaluated by means of */
+/*  subroutine splev. */
+
+/*  calling sequence: */
+/*     call percur(iopt,m,x,y,w,k,s,nest,n,t,c,fp,wrk, */
+/*    * lwrk,iwrk,ier) */
+
+/*  parameters: */
+/*   iopt  : integer flag. on entry iopt must specify whether a weighted */
+/*           least-squares spline (iopt=-1) or a smoothing spline (iopt= */
+/*           0 or 1) must be determined. if iopt=0 the routine will start */
+/*           with an initial set of knots t(i)=x(1)+(x(m)-x(1))*(i-k-1), */
+/*           i=1,2,...,2*k+2. if iopt=1 the routine will continue with */
+/*           the knots found at the last call of the routine. */
+/*           attention: a call with iopt=1 must always be immediately */
+/*           preceded by another call with iopt=1 or iopt=0. */
+/*           unchanged on exit. */
+/*   m     : integer. on entry m must specify the number of data points. */
+/*           m > 1. unchanged on exit. */
+/*   x     : real array of dimension at least (m). before entry, x(i) */
+/*           must be set to the i-th value of the independent variable x, */
+/*           for i=1,2,...,m. these values must be supplied in strictly */
+/*           ascending order. x(m) only indicates the length of the */
+/*           period of the spline, i.e per=x(m)-x(1). */
+/*           unchanged on exit. */
+/*   y     : real array of dimension at least (m). before entry, y(i) */
+/*           must be set to the i-th value of the dependent variable y, */
+/*           for i=1,2,...,m-1. the element y(m) is not used. */
+/*           unchanged on exit. */
+/*   w     : real array of dimension at least (m). before entry, w(i) */
+/*           must be set to the i-th value in the set of weights. the */
+/*           w(i) must be strictly positive. w(m) is not used. */
+/*           see also further comments. unchanged on exit. */
+/*   k     : integer. on entry k must specify the degree of the spline. */
+/*           1<=k<=5. it is recommended to use cubic splines (k=3). */
+/*           the user is strongly dissuaded from choosing k even,together */
+/*           with a small s-value. unchanged on exit. */
+/*   s     : real.on entry (in case iopt>=0) s must specify the smoothing */
+/*           factor. s >=0. unchanged on exit. */
+/*           for advice on the choice of s see further comments. */
+/*   nest  : integer. on entry nest must contain an over-estimate of the */
+/*           total number of knots of the spline returned, to indicate */
+/*           the storage space available to the routine. nest >=2*k+2. */
+/*           in most practical situation nest=m/2 will be sufficient. */
+/*           always large enough is nest=m+2*k,the number of knots needed */
+/*           for interpolation (s=0). unchanged on exit. */
+/*   n     : integer. */
+/*           unless ier = 10 (in case iopt >=0), n will contain the */
+/*           total number of knots of the spline approximation returned. */
+/*           if the computation mode iopt=1 is used this value of n */
+/*           should be left unchanged between subsequent calls. */
+/*           in case iopt=-1, the value of n must be specified on entry. */
+/*   t     : real array of dimension at least (nest). */
+/*           on succesful exit, this array will contain the knots of the */
+/*           spline,i.e. the position of the interior knots t(k+2),t(k+3) */
+/*           ...,t(n-k-1) as well as the position of the additional knots */
+/*           t(1),t(2),...,t(k+1)=x(1) and t(n-k)=x(m),..,t(n) needed for */
+/*           the b-spline representation. */
+/*           if the computation mode iopt=1 is used, the values of t(1), */
+/*           t(2),...,t(n) should be left unchanged between subsequent */
+/*           calls. if the computation mode iopt=-1 is used, the values */
+/*           t(k+2),...,t(n-k-1) must be supplied by the user, before */
+/*           entry. see also the restrictions (ier=10). */
+/*   c     : real array of dimension at least (nest). */
+/*           on succesful exit, this array will contain the coefficients */
+/*           c(1),c(2),..,c(n-k-1) in the b-spline representation of s(x) */
+/*   fp    : real. unless ier = 10, fp contains the weighted sum of */
+/*           squared residuals of the spline approximation returned. */
+/*   wrk   : real array of dimension at least (m*(k+1)+nest*(8+5*k)). */
+/*           used as working space. if the computation mode iopt=1 is */
+/*           used, the values wrk(1),...,wrk(n) should be left unchanged */
+/*           between subsequent calls. */
+/*   lwrk  : integer. on entry,lwrk must specify the actual dimension of */
+/*           the array wrk as declared in the calling (sub)program. lwrk */
+/*           must not be too small (see wrk). unchanged on exit. */
+/*   iwrk  : integer array of dimension at least (nest). */
+/*           used as working space. if the computation mode iopt=1 is */
+/*           used,the values iwrk(1),...,iwrk(n) should be left unchanged */
+/*           between subsequent calls. */
+/*   ier   : integer. unless the routine detects an error, ier contains a */
+/*           non-positive value on exit, i.e. */
+/*    ier=0  : normal return. the spline returned has a residual sum of */
+/*             squares fp such that abs(fp-s)/s <= tol with tol a relat- */
+/*             ive tolerance set to 0.001 by the program. */
+/*    ier=-1 : normal return. the spline returned is an interpolating */
+/*             periodic spline (fp=0). */
+/*    ier=-2 : normal return. the spline returned is the weighted least- */
+/*             squares constant. in this extreme case fp gives the upper */
+/*             bound fp0 for the smoothing factor s. */
+/*    ier=1  : error. the required storage space exceeds the available */
+/*             storage space, as specified by the parameter nest. */
+/*             probably causes : nest too small. if nest is already */
+/*             large (say nest > m/2), it may also indicate that s is */
+/*             too small */
+/*             the approximation returned is the least-squares periodic */
+/*             spline according to the knots t(1),t(2),...,t(n). (n=nest) */
+/*             the parameter fp gives the corresponding weighted sum of */
+/*             squared residuals (fp>s). */
+/*    ier=2  : error. a theoretically impossible result was found during */
+/*             the iteration proces for finding a smoothing spline with */
+/*             fp = s. probably causes : s too small. */
+/*             there is an approximation returned but the corresponding */
+/*             weighted sum of squared residuals does not satisfy the */
+/*             condition abs(fp-s)/s < tol. */
+/*    ier=3  : error. the maximal number of iterations maxit (set to 20 */
+/*             by the program) allowed for finding a smoothing spline */
+/*             with fp=s has been reached. probably causes : s too small */
+/*             there is an approximation returned but the corresponding */
+/*             weighted sum of squared residuals does not satisfy the */
+/*             condition abs(fp-s)/s < tol. */
+/*    ier=10 : error. on entry, the input data are controlled on validity */
+/*             the following restrictions must be satisfied. */
+/*             -1<=iopt<=1, 1<=k<=5, m>1, nest>2*k+2, w(i)>0,i=1,...,m-1 */
+/*             x(1)<x(2)<...<x(m), lwrk>=(k+1)*m+nest*(8+5*k) */
+/*             if iopt=-1: 2*k+2<=n<=min(nest,m+2*k) */
+/*                         x(1)<t(k+2)<t(k+3)<...<t(n-k-1)<x(m) */
+/*                       the schoenberg-whitney conditions, i.e. there */
+/*                       must be a subset of data points xx(j) with */
+/*                       xx(j) = x(i) or x(i)+(x(m)-x(1)) such that */
+/*                         t(j) < xx(j) < t(j+k+1), j=k+1,...,n-k-1 */
+/*             if iopt>=0: s>=0 */
+/*                         if s=0 : nest >= m+2*k */
+/*             if one of these conditions is found to be violated,control */
+/*             is immediately repassed to the calling program. in that */
+/*             case there is no approximation returned. */
+
+/*  further comments: */
+/*   by means of the parameter s, the user can control the tradeoff */
+/*   between closeness of fit and smoothness of fit of the approximation. */
+/*   if s is too large, the spline will be too smooth and signal will be */
+/*   lost ; if s is too small the spline will pick up too much noise. in */
+/*   the extreme cases the program will return an interpolating periodic */
+/*   spline if s=0 and the weighted least-squares constant if s is very */
+/*   large. between these extremes, a properly chosen s will result in */
+/*   a good compromise between closeness of fit and smoothness of fit. */
+/*   to decide whether an approximation, corresponding to a certain s is */
+/*   satisfactory the user is highly recommended to inspect the fits */
+/*   graphically. */
+/*   recommended values for s depend on the weights w(i). if these are */
+/*   taken as 1/d(i) with d(i) an estimate of the standard deviation of */
+/*   y(i), a good s-value should be found in the range (m-sqrt(2*m),m+ */
+/*   sqrt(2*m)). if nothing is known about the statistical error in y(i) */
+/*   each w(i) can be set equal to one and s determined by trial and */
+/*   error, taking account of the comments above. the best is then to */
+/*   start with a very large value of s ( to determine the least-squares */
+/*   constant and the corresponding upper bound fp0 for s) and then to */
+/*   progressively decrease the value of s ( say by a factor 10 in the */
+/*   beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the */
+/*   approximation shows more detail) to obtain closer fits. */
+/*   to economize the search for a good s-value the program provides with */
+/*   different modes of computation. at the first call of the routine, or */
+/*   whenever he wants to restart with the initial set of knots the user */
+/*   must set iopt=0. */
+/*   if iopt=1 the program will continue with the set of knots found at */
+/*   the last call of the routine. this will save a lot of computation */
+/*   time if percur is called repeatedly for different values of s. */
+/*   the number of knots of the spline returned and their location will */
+/*   depend on the value of s and on the complexity of the shape of the */
+/*   function underlying the data. but, if the computation mode iopt=1 */
+/*   is used, the knots returned may also depend on the s-values at */
+/*   previous calls (if these were smaller). therefore, if after a number */
+/*   of trials with different s-values and iopt=1, the user can finally */
+/*   accept a fit as satisfactory, it may be worthwhile for him to call */
+/*   percur once more with the selected value for s but now with iopt=0. */
+/*   indeed, percur may then return an approximation of the same quality */
+/*   of fit but with fewer knots and therefore better if data reduction */
+/*   is also an important objective for the user. */
+
+/*  other subroutines required: */
+/*    fpbacp,fpbspl,fpchep,fpperi,fpdisc,fpgivs,fpknot,fprati,fprota */
+
+/*  references: */
+/*   dierckx p. : algorithms for smoothing data with periodic and */
+/*                parametric splines, computer graphics and image */
+/*                processing 20 (1982) 171-184. */
+/*   dierckx p. : algorithms for smoothing data with periodic and param- */
+/*                etric splines, report tw55, dept. computer science, */
+/*                k.u.leuven, 1981. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*    p.dierckx */
+/*    dept. computer science, k.u. leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : may 1979 */
+/*  latest update : march 1987 */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..subroutine references.. */
+/*    perper,pcheck */
+/*  .. */
+/*  we set up the parameters tol and maxit */
+    /* Parameter adjustments */
+    --w;
+    --y;
+    --x;
+    --iwrk;
+    --c__;
+    --t;
+    --wrk;
+
+    /* Function Body */
+    maxit = 20;
+    tol = (float).001;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*k <= 0 || *k > 5) {
+	goto L50;
+    }
+    k1 = *k + 1;
+    k2 = k1 + 1;
+    if (*iopt < -1 || *iopt > 1) {
+	goto L50;
+    }
+    nmin = k1 << 1;
+    if (*m < 2 || *nest < nmin) {
+	goto L50;
+    }
+    lwest = *m * k1 + *nest * (*k * 5 + 8);
+    if (*lwrk < lwest) {
+	goto L50;
+    }
+    m1 = *m - 1;
+    i__1 = m1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (x[i__] >= x[i__ + 1] || w[i__] <= (float)0.) {
+	    goto L50;
+	}
+/* L10: */
+    }
+    if (*iopt >= 0) {
+	goto L30;
+    }
+    if (*n <= nmin || *n > *nest) {
+	goto L50;
+    }
+    per = x[*m] - x[1];
+    j1 = k1;
+    t[j1] = x[1];
+    i1 = *n - *k;
+    t[i1] = x[*m];
+    j2 = j1;
+    i2 = i1;
+    i__1 = *k;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	++i1;
+	--i2;
+	++j1;
+	--j2;
+	t[j2] = t[i2] - per;
+	t[i1] = t[j1] + per;
+/* L20: */
+    }
+    fpchep_(&x[1], m, &t[1], n, k, ier);
+    if (*ier != 0) {
+	goto L50;
+    } else {
+	goto L40;
+    }
+L30:
+    if (*s < (float)0.) {
+	goto L50;
+    }
+    if (*s == (float)0. && *nest < *m + (*k << 1)) {
+	goto L50;
+    }
+    *ier = 0;
+/* we partition the working space and determine the spline approximation. */
+L40:
+    ifp = 1;
+    iz = ifp + *nest;
+    ia1 = iz + *nest;
+    ia2 = ia1 + *nest * k1;
+    ib = ia2 + *nest * *k;
+    ig1 = ib + *nest * k2;
+    ig2 = ig1 + *nest * k2;
+    iq = ig2 + *nest * k1;
+    fpperi_(iopt, &x[1], &y[1], &w[1], m, k, s, nest, &tol, &maxit, &k1, &k2, 
+	    n, &t[1], &c__[1], fp, &wrk[ifp], &wrk[iz], &wrk[ia1], &wrk[ia2], 
+	    &wrk[ib], &wrk[ig1], &wrk[ig2], &wrk[iq], &iwrk[1], ier);
+L50:
+    return 0;
+} /* percur_ */
+
+/* Subroutine */ int pogrid_(iopt, ider, mu, u, mv, v, z__, z0, r__, s, nuest,
+	 nvest, nu, tu, nv, tv, c__, fp, wrk, lwrk, iwrk, kwrk, ier)
+integer *iopt, *ider, *mu;
+real *u;
+integer *mv;
+real *v, *z__, *z0, *r__, *s;
+integer *nuest, *nvest, *nu;
+real *tu;
+integer *nv;
+real *tv, *c__, *fp, *wrk;
+integer *lwrk, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Builtin functions */
+    double atan2();
+
+    /* Local variables */
+    static real half;
+    static integer kndu, kndv, lfpu, lfpv;
+    static real zmin, zmax;
+    static integer jwrk, knru, knrv, i__, j, l, m, maxit, mumin, i1, i2, j1, 
+	    j2, kwest, lwest, nc;
+    extern /* Subroutine */ int fpchec_();
+    static real pi, ve, zb, rn;
+    extern /* Subroutine */ int fpchep_();
+    static real uu;
+    extern /* Subroutine */ int fppogr_();
+    static real one, per;
+    static integer ldz;
+    static real tol;
+    static integer muu, lww;
+
+/*  subroutine pogrid fits a function f(x,y) to a set of data points */
+/*  z(i,j) given at the nodes (x,y)=(u(i)*cos(v(j)),u(i)*sin(v(j))), */
+/*  i=1,...,mu ; j=1,...,mv , of a radius-angle grid over a disc */
+/*    x ** 2  +  y ** 2  <=  r ** 2 . */
+
+/*  this approximation problem is reduced to the determination of a */
+/*  bicubic spline s(u,v) smoothing the data (u(i),v(j),z(i,j)) on the */
+/*  rectangle 0<=u<=r, v(1)<=v<=v(1)+2*pi */
+/*  in order to have continuous partial derivatives */
+/*              i+j */
+/*             d   f(0,0) */
+/*    g(i,j) = ---------- */
+/*                i   j */
+/*              dx  dy */
+
+/*  s(u,v)=f(x,y) must satisfy the following conditions */
+
+/*    (1) s(0,v) = g(0,0)   v(1)<=v<= v(1)+2*pi */
+
+/*        d s(0,v) */
+/*    (2) -------- = cos(v)*g(1,0)+sin(v)*g(0,1)  v(1)<=v<= v(1)+2*pi */
+/*        d u */
+
+/*  moreover, s(u,v) must be periodic in the variable v, i.e. */
+
+/*         j            j */
+/*        d s(u,vb)   d s(u,ve) */
+/*    (3) ---------- = ---------   0 <=u<= r, j=0,1,2 , vb=v(1), */
+/*           j            j                             ve=vb+2*pi */
+/*        d v          d v */
+
+/*  the number of knots of s(u,v) and their position tu(i),i=1,2,...,nu; */
+/*  tv(j),j=1,2,...,nv, is chosen automatically by the routine. the */
+/*  smoothness of s(u,v) is achieved by minimalizing the discontinuity */
+/*  jumps of the derivatives of the spline at the knots. the amount of */
+/*  smoothness of s(u,v) is determined by the condition that */
+/*  fp=sumi=1,mu(sumj=1,mv((z(i,j)-s(u(i),v(j)))**2))+(z0-g(0,0))**2<=s, */
+/*  with s a given non-negative constant. */
+/*  the fit s(u,v) is given in its b-spline representation and can be */
+/*  evaluated by means of routine bispev. f(x,y) = s(u,v) can also be */
+/*  evaluated by means of function program evapol. */
+
+/* calling sequence: */
+/*     call pogrid(iopt,ider,mu,u,mv,v,z,z0,r,s,nuest,nvest,nu,tu, */
+/*    *  ,nv,tv,c,fp,wrk,lwrk,iwrk,kwrk,ier) */
+
+/* parameters: */
+/*  iopt  : integer array of dimension 3, specifying different options. */
+/*          unchanged on exit. */
+/*  iopt(1):on entry iopt(1) must specify whether a least-squares spline */
+/*          (iopt(1)=-1) or a smoothing spline (iopt(1)=0 or 1) must be */
+/*          determined. */
+/*          if iopt(1)=0 the routine will start with an initial set of */
+/*          knots tu(i)=0,tu(i+4)=r,i=1,...,4;tv(i)=v(1)+(i-4)*2*pi,i=1,. */
+/*          ...,8. */
+/*          if iopt(1)=1 the routine will continue with the set of knots */
+/*          found at the last call of the routine. */
+/*          attention: a call with iopt(1)=1 must always be immediately */
+/*          preceded by another call with iopt(1) = 1 or iopt(1) = 0. */
+/*  iopt(2):on entry iopt(2) must specify the requested order of conti- */
+/*          nuity for f(x,y) at the origin. */
+/*          if iopt(2)=0 only condition (1) must be fulfilled and */
+/*          if iopt(2)=1 conditions (1)+(2) must be fulfilled. */
+/*  iopt(3):on entry iopt(3) must specify whether (iopt(3)=1) or not */
+/*          (iopt(3)=0) the approximation f(x,y) must vanish at the */
+/*          boundary of the approximation domain. */
+/*  ider  : integer array of dimension 2, specifying different options. */
+/*          unchanged on exit. */
+/*  ider(1):on entry ider(1) must specify whether (ider(1)=0 or 1) or not */
+/*          (ider(1)=-1) there is a data value z0 at the origin. */
+/*          if ider(1)=1, z0 will be considered to be the right function */
+/*          value, and it will be fitted exactly (g(0,0)=z0=c(1)). */
+/*          if ider(1)=0, z0 will be considered to be a data value just */
+/*          like the other data values z(i,j). */
+/*  ider(2):on entry ider(2) must specify whether (ider(2)=1) or not */
+/*          (ider(2)=0) f(x,y) must have vanishing partial derivatives */
+/*          g(1,0) and g(0,1) at the origin. (in case iopt(2)=1) */
+/*  mu    : integer. on entry mu must specify the number of grid points */
+/*          along the u-axis. unchanged on exit. */
+/*          mu >= mumin where mumin=4-iopt(3)-ider(2) if ider(1)<0 */
+/*                                 =3-iopt(3)-ider(2) if ider(1)>=0 */
+/*  u     : real array of dimension at least (mu). before entry, u(i) */
+/*          must be set to the u-co-ordinate of the i-th grid point */
+/*          along the u-axis, for i=1,2,...,mu. these values must be */
+/*          positive and supplied in strictly ascending order. */
+/*          unchanged on exit. */
+/*  mv    : integer. on entry mv must specify the number of grid points */
+/*          along the v-axis. mv > 3 . unchanged on exit. */
+/*  v     : real array of dimension at least (mv). before entry, v(j) */
+/*          must be set to the v-co-ordinate of the j-th grid point */
+/*          along the v-axis, for j=1,2,...,mv. these values must be */
+/*          supplied in strictly ascending order. unchanged on exit. */
+/*          -pi <= v(1) < pi , v(mv) < v(1)+2*pi. */
+/*  z     : real array of dimension at least (mu*mv). */
+/*          before entry, z(mv*(i-1)+j) must be set to the data value at */
+/*          the grid point (u(i),v(j)) for i=1,...,mu and j=1,...,mv. */
+/*          unchanged on exit. */
+/*  z0    : real value. on entry (if ider(1) >=0 ) z0 must specify the */
+/*          data value at the origin. unchanged on exit. */
+/*  r     : real value. on entry r must specify the radius of the disk. */
+/*          r>=u(mu) (>u(mu) if iopt(3)=1). unchanged on exit. */
+/*  s     : real. on entry (if iopt(1)>=0) s must specify the smoothing */
+/*          factor. s >=0. unchanged on exit. */
+/*          for advice on the choice of s see further comments */
+/*  nuest : integer. unchanged on exit. */
+/*  nvest : integer. unchanged on exit. */
+/*          on entry, nuest and nvest must specify an upper bound for the */
+/*          number of knots required in the u- and v-directions respect. */
+/*          these numbers will also determine the storage space needed by */
+/*          the routine. nuest >= 8, nvest >= 8. */
+/*          in most practical situation nuest = mu/2, nvest=mv/2, will */
+/*          be sufficient. always large enough are nuest=mu+5+iopt(2)+ */
+/*          iopt(3), nvest = mv+7, the number of knots needed for */
+/*          interpolation (s=0). see also further comments. */
+/*  nu    : integer. */
+/*          unless ier=10 (in case iopt(1)>=0), nu will contain the total */
+/*          number of knots with respect to the u-variable, of the spline */
+/*          approximation returned. if the computation mode iopt(1)=1 is */
+/*          used, the value of nu should be left unchanged between sub- */
+/*          sequent calls. in case iopt(1)=-1, the value of nu should be */
+/*          specified on entry. */
+/*  tu    : real array of dimension at least (nuest). */
+/*          on succesful exit, this array will contain the knots of the */
+/*          spline with respect to the u-variable, i.e. the position of */
+/*          the interior knots tu(5),...,tu(nu-4) as well as the position */
+/*          of the additional knots tu(1)=...=tu(4)=0 and tu(nu-3)=...= */
+/*          tu(nu)=r needed for the b-spline representation. */
+/*          if the computation mode iopt(1)=1 is used,the values of tu(1) */
+/*          ...,tu(nu) should be left unchanged between subsequent calls. */
+/*          if the computation mode iopt(1)=-1 is used, the values tu(5), */
+/*          ...tu(nu-4) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  nv    : integer. */
+/*          unless ier=10 (in case iopt(1)>=0), nv will contain the total */
+/*          number of knots with respect to the v-variable, of the spline */
+/*          approximation returned. if the computation mode iopt(1)=1 is */
+/*          used, the value of nv should be left unchanged between sub- */
+/*          sequent calls. in case iopt(1) = -1, the value of nv should */
+/*          be specified on entry. */
+/*  tv    : real array of dimension at least (nvest). */
+/*          on succesful exit, this array will contain the knots of the */
+/*          spline with respect to the v-variable, i.e. the position of */
+/*          the interior knots tv(5),...,tv(nv-4) as well as the position */
+/*          of the additional knots tv(1),...,tv(4) and tv(nv-3),..., */
+/*          tv(nv) needed for the b-spline representation. */
+/*          if the computation mode iopt(1)=1 is used,the values of tv(1) */
+/*          ...,tv(nv) should be left unchanged between subsequent calls. */
+/*          if the computation mode iopt(1)=-1 is used, the values tv(5), */
+/*          ...tv(nv-4) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  c     : real array of dimension at least (nuest-4)*(nvest-4). */
+/*          on succesful exit, c contains the coefficients of the spline */
+/*          approximation s(u,v) */
+/*  fp    : real. unless ier=10, fp contains the sum of squared */
+/*          residuals of the spline approximation returned. */
+/*  wrk   : real array of dimension (lwrk). used as workspace. */
+/*          if the computation mode iopt(1)=1 is used the values of */
+/*          wrk(1),...,wrk(8) should be left unchanged between subsequent */
+/*          calls. */
+/*  lwrk  : integer. on entry lwrk must specify the actual dimension of */
+/*          the array wrk as declared in the calling (sub)program. */
+/*          lwrk must not be too small. */
+/*           lwrk >= 8+nuest*(mv+nvest+3)+nvest*21+4*mu+6*mv+q */
+/*           where q is the larger of (mv+nvest) and nuest. */
+/*  iwrk  : integer array of dimension (kwrk). used as workspace. */
+/*          if the computation mode iopt(1)=1 is used the values of */
+/*          iwrk(1),.,iwrk(4) should be left unchanged between subsequent */
+/*          calls. */
+/*  kwrk  : integer. on entry kwrk must specify the actual dimension of */
+/*          the array iwrk as declared in the calling (sub)program. */
+/*          kwrk >= 4+mu+mv+nuest+nvest. */
+/*  ier   : integer. unless the routine detects an error, ier contains a */
+/*          non-positive value on exit, i.e. */
+/*   ier=0  : normal return. the spline returned has a residual sum of */
+/*            squares fp such that abs(fp-s)/s <= tol with tol a relat- */
+/*            ive tolerance set to 0.001 by the program. */
+/*   ier=-1 : normal return. the spline returned is an interpolating */
+/*            spline (fp=0). */
+/*   ier=-2 : normal return. the spline returned is the least-squares */
+/*            constrained polynomial. in this extreme case fp gives the */
+/*            upper bound for the smoothing factor s. */
+/*   ier=1  : error. the required storage space exceeds the available */
+/*            storage space, as specified by the parameters nuest and */
+/*            nvest. */
+/*            probably causes : nuest or nvest too small. if these param- */
+/*            eters are already large, it may also indicate that s is */
+/*            too small */
+/*            the approximation returned is the least-squares spline */
+/*            according to the current set of knots. the parameter fp */
+/*            gives the corresponding sum of squared residuals (fp>s). */
+/*   ier=2  : error. a theoretically impossible result was found during */
+/*            the iteration proces for finding a smoothing spline with */
+/*            fp = s. probably causes : s too small. */
+/*            there is an approximation returned but the corresponding */
+/*            sum of squared residuals does not satisfy the condition */
+/*            abs(fp-s)/s < tol. */
+/*   ier=3  : error. the maximal number of iterations maxit (set to 20 */
+/*            by the program) allowed for finding a smoothing spline */
+/*            with fp=s has been reached. probably causes : s too small */
+/*            there is an approximation returned but the corresponding */
+/*            sum of squared residuals does not satisfy the condition */
+/*            abs(fp-s)/s < tol. */
+/*   ier=10 : error. on entry, the input data are controlled on validity */
+/*            the following restrictions must be satisfied. */
+/*            -1<=iopt(1)<=1, 0<=iopt(2)<=1, 0<=iopt(3)<=1, */
+/*            -1<=ider(1)<=1, 0<=ider(2)<=1, ider(2)=0 if iopt(2)=0. */
+/*            mu >= mumin (see above), mv >= 4, nuest >=8, nvest >= 8, */
+/*            kwrk>=4+mu+mv+nuest+nvest, */
+/*            lwrk >= 8+nuest*(mv+nvest+3)+nvest*21+4*mu+6*mv+ */
+/*             max(nuest,mv+nvest) */
+/*            0< u(i-1)<u(i)<=r,i=2,..,mu, (< r if iopt(3)=1) */
+/*            -pi<=v(1)< pi, v(1)<v(i-1)<v(i)<v(1)+2*pi, i=3,...,mv */
+/*            if iopt(1)=-1: 8<=nu<=min(nuest,mu+5+iopt(2)+iopt(3)) */
+/*                           0<tu(5)<tu(6)<...<tu(nu-4)<r */
+/*                           8<=nv<=min(nvest,mv+7) */
+/*                           v(1)<tv(5)<tv(6)<...<tv(nv-4)<v(1)+2*pi */
+/*                    the schoenberg-whitney conditions, i.e. there must */
+/*                    be subset of grid co-ordinates uu(p) and vv(q) such */
+/*                    that   tu(p) < uu(p) < tu(p+4) ,p=1,...,nu-4 */
+/*                     (iopt(2)=1 and iopt(3)=1 also count for a uu-value */
+/*                           tv(q) < vv(q) < tv(q+4) ,q=1,...,nv-4 */
+/*                     (vv(q) is either a value v(j) or v(j)+2*pi) */
+/*            if iopt(1)>=0: s>=0 */
+/*                       if s=0: nuest>=mu+5+iopt(2)+iopt(3), nvest>=mv+7 */
+/*            if one of these conditions is found to be violated,control */
+/*            is immediately repassed to the calling program. in that */
+/*            case there is no approximation returned. */
+
+/* further comments: */
+/*   pogrid does not allow individual weighting of the data-values. */
+/*   so, if these were determined to widely different accuracies, then */
+/*   perhaps the general data set routine polar should rather be used */
+/*   in spite of efficiency. */
+/*   by means of the parameter s, the user can control the tradeoff */
+/*   between closeness of fit and smoothness of fit of the approximation. */
+/*   if s is too large, the spline will be too smooth and signal will be */
+/*   lost ; if s is too small the spline will pick up too much noise. in */
+/*   the extreme cases the program will return an interpolating spline if */
+/*   s=0 and the constrained least-squares polynomial(degrees 3,0)if s is */
+/*   very large. between these extremes, a properly chosen s will result */
+/*   in a good compromise between closeness of fit and smoothness of fit. */
+/*   to decide whether an approximation, corresponding to a certain s is */
+/*   satisfactory the user is highly recommended to inspect the fits */
+/*   graphically. */
+/*   recommended values for s depend on the accuracy of the data values. */
+/*   if the user has an idea of the statistical errors on the data, he */
+/*   can also find a proper estimate for s. for, by assuming that, if he */
+/*   specifies the right s, pogrid will return a spline s(u,v) which */
+/*   exactly reproduces the function underlying the data he can evaluate */
+/*   the sum((z(i,j)-s(u(i),v(j)))**2) to find a good estimate for this s */
+/*   for example, if he knows that the statistical errors on his z(i,j)- */
+/*   values is not greater than 0.1, he may expect that a good s should */
+/*   have a value not larger than mu*mv*(0.1)**2. */
+/*   if nothing is known about the statistical error in z(i,j), s must */
+/*   be determined by trial and error, taking account of the comments */
+/*   above. the best is then to start with a very large value of s (to */
+/*   determine the least-squares polynomial and the corresponding upper */
+/*   bound fp0 for s) and then to progressively decrease the value of s */
+/*   ( say by a factor 10 in the beginning, i.e. s=fp0/10,fp0/100,... */
+/*   and more carefully as the approximation shows more detail) to */
+/*   obtain closer fits. */
+/*   to economize the search for a good s-value the program provides with */
+/*   different modes of computation. at the first call of the routine, or */
+/*   whenever he wants to restart with the initial set of knots the user */
+/*   must set iopt(1)=0. */
+/*   if iopt(1) = 1 the program will continue with the knots found at */
+/*   the last call of the routine. this will save a lot of computation */
+/*   time if pogrid is called repeatedly for different values of s. */
+/*   the number of knots of the spline returned and their location will */
+/*   depend on the value of s and on the complexity of the shape of the */
+/*   function underlying the data. if the computation mode iopt(1) = 1 */
+/*   is used, the knots returned may also depend on the s-values at */
+/*   previous calls (if these were smaller). therefore, if after a number */
+/*   of trials with different s-values and iopt(1)=1,the user can finally */
+/*   accept a fit as satisfactory, it may be worthwhile for him to call */
+/*   pogrid once more with the chosen value for s but now with iopt(1)=0. */
+/*   indeed, pogrid may then return an approximation of the same quality */
+/*   of fit but with fewer knots and therefore better if data reduction */
+/*   is also an important objective for the user. */
+/*   the number of knots may also depend on the upper bounds nuest and */
+/*   nvest. indeed, if at a certain stage in pogrid the number of knots */
+/*   in one direction (say nu) has reached the value of its upper bound */
+/*   (nuest), then from that moment on all subsequent knots are added */
+/*   in the other (v) direction. this may indicate that the value of */
+/*   nuest is too small. on the other hand, it gives the user the option */
+/*   of limiting the number of knots the routine locates in any direction */
+/*   for example, by setting nuest=8 (the lowest allowable value for */
+/*   nuest), the user can indicate that he wants an approximation which */
+/*   is a simple cubic polynomial in the variable u. */
+
+/*  other subroutines required: */
+/*    fppogr,fpchec,fpchep,fpknot,fpopdi,fprati,fpgrdi,fpsysy,fpback, */
+/*    fpbacp,fpbspl,fpcyt1,fpcyt2,fpdisc,fpgivs,fprota */
+
+/*  references: */
+/*   dierckx p. : fast algorithms for smoothing data over a disc or a */
+/*                sphere using tensor product splines, in "algorithms */
+/*                for approximation", ed. j.c.mason and m.g.cox, */
+/*                clarendon press oxford, 1987, pp. 51-65 */
+/*   dierckx p. : fast algorithms for smoothing data over a disc or a */
+/*                sphere using tensor product splines, report tw73, dept. */
+/*                computer science,k.u.leuven, 1985. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*    p.dierckx */
+/*    dept. computer science, k.u. leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : july 1985 */
+/*  latest update : march 1989 */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpchec,fpchep,fppogr */
+/*  .. */
+/*  set constants */
+    /* Parameter adjustments */
+    --iopt;
+    --ider;
+    --u;
+    --z__;
+    --v;
+    --tu;
+    --c__;
+    --tv;
+    --wrk;
+    --iwrk;
+
+    /* Function Body */
+    one = (float)1.;
+    half = (float).5;
+    pi = atan2((float)0., -one);
+    per = pi + pi;
+    ve = v[1] + per;
+/*  we set up the parameters tol and maxit. */
+    maxit = 20;
+    tol = (float).001;
+/*  before starting computations, a data check is made. if the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (iopt[1] < -1 || iopt[1] > 1) {
+	goto L200;
+    }
+    if (iopt[2] < 0 || iopt[2] > 1) {
+	goto L200;
+    }
+    if (iopt[3] < 0 || iopt[3] > 1) {
+	goto L200;
+    }
+    if (ider[1] < -1 || ider[1] > 1) {
+	goto L200;
+    }
+    if (ider[2] < 0 || ider[2] > 1) {
+	goto L200;
+    }
+    if (ider[2] == 1 && iopt[2] == 0) {
+	goto L200;
+    }
+    mumin = 4 - iopt[3] - ider[2];
+    if (ider[1] >= 0) {
+	--mumin;
+    }
+    if (*mu < mumin || *mv < 4) {
+	goto L200;
+    }
+    if (*nuest < 8 || *nvest < 8) {
+	goto L200;
+    }
+    m = *mu * *mv;
+    nc = (*nuest - 4) * (*nvest - 4);
+/* Computing MAX */
+    i__1 = *nuest, i__2 = *mv + *nvest;
+    lwest = *nuest * (*mv + *nvest + 3) + 8 + *nvest * 21 + (*mu << 2) + *mv *
+	     6 + max(i__1,i__2);
+    kwest = *mu + 4 + *mv + *nuest + *nvest;
+    if (*lwrk < lwest || *kwrk < kwest) {
+	goto L200;
+    }
+    if (u[1] <= (float)0. || u[*mu] > *r__) {
+	goto L200;
+    }
+    if (iopt[3] == 0) {
+	goto L10;
+    }
+    if (u[*mu] == *r__) {
+	goto L200;
+    }
+L10:
+    if (*mu == 1) {
+	goto L30;
+    }
+    i__1 = *mu;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (u[i__ - 1] >= u[i__]) {
+	    goto L200;
+	}
+/* L20: */
+    }
+L30:
+    if (v[1] < -pi || v[1] >= pi) {
+	goto L200;
+    }
+    if (v[*mv] >= v[1] + per) {
+	goto L200;
+    }
+    i__1 = *mv;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (v[i__ - 1] >= v[i__]) {
+	    goto L200;
+	}
+/* L40: */
+    }
+    if (iopt[1] > 0) {
+	goto L140;
+    }
+/*  if not given, we compute an estimate for z0. */
+    if (ider[1] < 0) {
+	goto L50;
+    }
+    zb = *z0;
+    goto L70;
+L50:
+    zb = (float)0.;
+    i__1 = *mv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	zb += z__[i__];
+/* L60: */
+    }
+    rn = (real) (*mv);
+    zb /= rn;
+/*  we determine the range of z-values. */
+L70:
+    zmin = zb;
+    zmax = zb;
+    i__1 = m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (z__[i__] < zmin) {
+	    zmin = z__[i__];
+	}
+	if (z__[i__] > zmax) {
+	    zmax = z__[i__];
+	}
+/* L80: */
+    }
+    wrk[5] = zb;
+    wrk[6] = (float)0.;
+    wrk[7] = (float)0.;
+    wrk[8] = zmax - zmin;
+    iwrk[4] = *mu;
+    if (iopt[1] == 0) {
+	goto L140;
+    }
+    if (*nu < 8 || *nu > *nuest) {
+	goto L200;
+    }
+    if (*nv < 11 || *nv > *nvest) {
+	goto L200;
+    }
+    j = *nu;
+    for (i__ = 1; i__ <= 4; ++i__) {
+	tu[i__] = (float)0.;
+	tu[j] = *r__;
+	--j;
+/* L90: */
+    }
+    l = 9;
+    wrk[l] = (float)0.;
+    if (iopt[2] == 0) {
+	goto L100;
+    }
+    ++l;
+    uu = u[1];
+    if (uu > tu[5]) {
+	uu = tu[5];
+    }
+    wrk[l] = uu * half;
+L100:
+    i__1 = *mu;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	++l;
+	wrk[l] = u[i__];
+/* L110: */
+    }
+    if (iopt[3] == 0) {
+	goto L120;
+    }
+    ++l;
+    wrk[l] = *r__;
+L120:
+    muu = l - 8;
+    fpchec_(&wrk[9], &muu, &tu[1], nu, &c__3, ier);
+    if (*ier != 0) {
+	goto L200;
+    }
+    j1 = 4;
+    tv[j1] = v[1];
+    i1 = *nv - 3;
+    tv[i1] = ve;
+    j2 = j1;
+    i2 = i1;
+    for (i__ = 1; i__ <= 3; ++i__) {
+	++i1;
+	--i2;
+	++j1;
+	--j2;
+	tv[j2] = tv[i2] - per;
+	tv[i1] = tv[j1] + per;
+/* L130: */
+    }
+    l = 9;
+    i__1 = *mv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	wrk[l] = v[i__];
+	++l;
+/* L135: */
+    }
+    wrk[l] = ve;
+    i__1 = *mv + 1;
+    fpchep_(&wrk[9], &i__1, &tv[1], nv, &c__3, ier);
+    if (*ier != 0) {
+	goto L200;
+    } else {
+	goto L150;
+    }
+L140:
+    if (*s < (float)0.) {
+	goto L200;
+    }
+    if (*s == (float)0. && (*nuest < *mu + 5 + iopt[2] + iopt[3] || *nvest < *
+	    mv + 7)) {
+	goto L200;
+    }
+/*  we partition the working space and determine the spline approximation */
+L150:
+    ldz = 5;
+    lfpu = 9;
+    lfpv = lfpu + *nuest;
+    lww = lfpv + *nvest;
+    jwrk = *lwrk - 8 - *nuest - *nvest;
+    knru = 5;
+    knrv = knru + *mu;
+    kndu = knrv + *mv;
+    kndv = kndu + *nuest;
+    fppogr_(&iopt[1], &ider[1], &u[1], mu, &v[1], mv, &z__[1], &m, &zb, r__, 
+	    s, nuest, nvest, &tol, &maxit, &nc, nu, &tu[1], nv, &tv[1], &c__[
+	    1], fp, &wrk[1], &wrk[2], &wrk[3], &wrk[4], &wrk[lfpu], &wrk[lfpv]
+	    , &wrk[ldz], &wrk[8], &iwrk[1], &iwrk[2], &iwrk[3], &iwrk[4], &
+	    iwrk[knru], &iwrk[knrv], &iwrk[kndu], &iwrk[kndv], &wrk[lww], &
+	    jwrk, ier);
+L200:
+    return 0;
+} /* pogrid_ */
+
+/* Subroutine */ int polar_(iopt, m, x, y, z__, w, rad, s, nuest, nvest, eps, 
+	nu, tu, nv, tv, u, v, c__, fp, wrk1, lwrk1, wrk2, lwrk2, iwrk, kwrk, 
+	ier)
+integer *iopt, *m;
+real *x, *y, *z__, *w;
+doublereal (*rad) ();
+real *s;
+integer *nuest, *nvest;
+real *eps;
+integer *nu;
+real *tu;
+integer *nv;
+real *tv, *u, *v, *c__, *fp, *wrk1;
+integer *lwrk1;
+real *wrk2;
+integer *lwrk2, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+    real r__1, r__2;
+
+    /* Builtin functions */
+    double atan2(), sqrt();
+
+    /* Local variables */
+    static integer nreg, ipar;
+    static real dist;
+    static integer iopt1, iopt2, iopt3, i__, j;
+    static real r__;
+    static integer ncest, maxit, nvmin, nrint, kwest, lwest, la, lf, ki, lh;
+    static real pi;
+    static integer kn, lq;
+    extern /* Subroutine */ int fppola_();
+    static integer ib1, ib3, nu4, nv4, lcc, ncc, lff, lco;
+    static real one;
+    static integer lbu, lcs, lfp, lbv, lro;
+    static real tol;
+    static integer lsu, lsv, nuu, nvv;
+
+/*  subroutine polar fits a smooth function f(x,y) to a set of data */
+/*  points (x(i),y(i),z(i)) scattered arbitrarily over an approximation */
+/*  domain  x**2+y**2 <= rad(atan(y/x))**2. through the transformation */
+/*    x = u*rad(v)*cos(v) , y = u*rad(v)*sin(v) */
+/*  the approximation problem is reduced to the determination of a bi- */
+/*  cubic spline s(u,v) fitting a corresponding set of data points */
+/*  (u(i),v(i),z(i)) on the rectangle 0<=u<=1,-pi<=v<=pi. */
+/*  in order to have continuous partial derivatives */
+/*              i+j */
+/*             d   f(0,0) */
+/*    g(i,j) = ---------- */
+/*                i   j */
+/*              dx  dy */
+
+/*  s(u,v)=f(x,y) must satisfy the following conditions */
+
+/*    (1) s(0,v) = g(0,0)   -pi <=v<= pi. */
+
+/*        d s(0,v) */
+/*    (2) -------- = rad(v)*(cos(v)*g(1,0)+sin(v)*g(0,1)) */
+/*        d u */
+/*                                                    -pi <=v<= pi */
+/*         2 */
+/*        d s(0,v)         2       2             2 */
+/*    (3) -------- = rad(v)*(cos(v)*g(2,0)+sin(v)*g(0,2)+sin(2*v)*g(1,1)) */
+/*           2 */
+/*        d u                                         -pi <=v<= pi */
+
+/*  moreover, s(u,v) must be periodic in the variable v, i.e. */
+
+/*         j            j */
+/*        d s(u,-pi)   d s(u,pi) */
+/*    (4) ---------- = ---------   0 <=u<= 1, j=0,1,2 */
+/*           j           j */
+/*        d v         d v */
+
+/*  if iopt(1) < 0 circle calculates a weighted least-squares spline */
+/*  according to a given set of knots in u- and v- direction. */
+/*  if iopt(1) >=0, the number of knots in each direction and their pos- */
+/*  ition tu(j),j=1,2,...,nu ; tv(j),j=1,2,...,nv are chosen automatical- */
+/*  ly by the routine. the smoothness of s(u,v) is then achieved by mini- */
+/*  malizing the discontinuity jumps of the derivatives of the spline */
+/*  at the knots. the amount of smoothness of s(u,v) is determined  by */
+/*  the condition that fp = sum((w(i)*(z(i)-s(u(i),v(i))))**2) be <= s, */
+/*  with s a given non-negative constant. */
+/*  the bicubic spline is given in its standard b-spline representation */
+/*  and the corresponding function f(x,y) can be evaluated by means of */
+/*  function program evapol. */
+
+/* calling sequence: */
+/*     call polar(iopt,m,x,y,z,w,rad,s,nuest,nvest,eps,nu,tu, */
+/*    *  nv,tv,u,v,wrk1,lwrk1,wrk2,lwrk2,iwrk,kwrk,ier) */
+
+/* parameters: */
+/*  iopt  : integer array of dimension 3, specifying different options. */
+/*          unchanged on exit. */
+/*  iopt(1):on entry iopt(1) must specify whether a weighted */
+/*          least-squares polar spline (iopt(1)=-1) or a smoothing */
+/*          polar spline (iopt(1)=0 or 1) must be determined. */
+/*          if iopt(1)=0 the routine will start with an initial set of */
+/*          knots tu(i)=0,tu(i+4)=1,i=1,...,4;tv(i)=(2*i-9)*pi,i=1,...,8. */
+/*          if iopt(1)=1 the routine will continue with the set of knots */
+/*          found at the last call of the routine. */
+/*          attention: a call with iopt(1)=1 must always be immediately */
+/*          preceded by another call with iopt(1) = 1 or iopt(1) = 0. */
+/*  iopt(2):on entry iopt(2) must specify the requested order of conti- */
+/*          nuity for f(x,y) at the origin. */
+/*          if iopt(2)=0 only condition (1) must be fulfilled, */
+/*          if iopt(2)=1 conditions (1)+(2) must be fulfilled and */
+/*          if iopt(2)=2 conditions (1)+(2)+(3) must be fulfilled. */
+/*  iopt(3):on entry iopt(3) must specify whether (iopt(3)=1) or not */
+/*          (iopt(3)=0) the approximation f(x,y) must vanish at the */
+/*          boundary of the approximation domain. */
+/*  m     : integer. on entry m must specify the number of data points. */
+/*          m >= 4-iopt(2)-iopt(3) unchanged on exit. */
+/*  x     : real array of dimension at least (m). */
+/*  y     : real array of dimension at least (m). */
+/*  z     : real array of dimension at least (m). */
+/*          before entry, x(i),y(i),z(i) must be set to the co-ordinates */
+/*          of the i-th data point, for i=1,...,m. the order of the data */
+/*          points is immaterial. unchanged on exit. */
+/*  w     : real array of dimension at least (m). before entry, w(i) must */
+/*          be set to the i-th value in the set of weights. the w(i) must */
+/*          be strictly positive. unchanged on exit. */
+/*  rad   : real function subprogram defining the boundary of the approx- */
+/*          imation domain, i.e   x = rad(v)*cos(v) , y = rad(v)*sin(v), */
+/*          -pi <= v <= pi. */
+/*          must be declared external in the calling (sub)program. */
+/*  s     : real. on entry (in case iopt(1) >=0) s must specify the */
+/*          smoothing factor. s >=0. unchanged on exit. */
+/*          for advice on the choice of s see further comments */
+/*  nuest : integer. unchanged on exit. */
+/*  nvest : integer. unchanged on exit. */
+/*          on entry, nuest and nvest must specify an upper bound for the */
+/*          number of knots required in the u- and v-directions resp. */
+/*          these numbers will also determine the storage space needed by */
+/*          the routine. nuest >= 8, nvest >= 8. */
+/*          in most practical situation nuest = nvest = 8+sqrt(m/2) will */
+/*          be sufficient. see also further comments. */
+/*  eps   : real. */
+/*          on entry, eps must specify a threshold for determining the */
+/*          effective rank of an over-determined linear system of equat- */
+/*          ions. 0 < eps < 1.  if the number of decimal digits in the */
+/*          computer representation of a real number is q, then 10**(-q) */
+/*          is a suitable value for eps in most practical applications. */
+/*          unchanged on exit. */
+/*  nu    : integer. */
+/*          unless ier=10 (in case iopt(1) >=0),nu will contain the total */
+/*          number of knots with respect to the u-variable, of the spline */
+/*          approximation returned. if the computation mode iopt(1)=1 */
+/*          is used, the value of nu should be left unchanged between */
+/*          subsequent calls. */
+/*          in case iopt(1)=-1,the value of nu must be specified on entry */
+/*  tu    : real array of dimension at least nuest. */
+/*          on succesful exit, this array will contain the knots of the */
+/*          spline with respect to the u-variable, i.e. the position */
+/*          of the interior knots tu(5),...,tu(nu-4) as well as the */
+/*          position of the additional knots tu(1)=...=tu(4)=0 and */
+/*          tu(nu-3)=...=tu(nu)=1 needed for the b-spline representation */
+/*          if the computation mode iopt(1)=1 is used,the values of */
+/*          tu(1),...,tu(nu) should be left unchanged between subsequent */
+/*          calls. if the computation mode iopt(1)=-1 is used,the values */
+/*          tu(5),...tu(nu-4) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  nv    : integer. */
+/*          unless ier=10 (in case iopt(1)>=0), nv will contain the total */
+/*          number of knots with respect to the v-variable, of the spline */
+/*          approximation returned. if the computation mode iopt(1)=1 */
+/*          is used, the value of nv should be left unchanged between */
+/*          subsequent calls. in case iopt(1)=-1, the value of nv should */
+/*          be specified on entry. */
+/*  tv    : real array of dimension at least nvest. */
+/*          on succesful exit, this array will contain the knots of the */
+/*          spline with respect to the v-variable, i.e. the position of */
+/*          the interior knots tv(5),...,tv(nv-4) as well as the position */
+/*          of the additional knots tv(1),...,tv(4) and tv(nv-3),..., */
+/*          tv(nv) needed for the b-spline representation. */
+/*          if the computation mode iopt(1)=1 is used, the values of */
+/*          tv(1),...,tv(nv) should be left unchanged between subsequent */
+/*          calls. if the computation mode iopt(1)=-1 is used,the values */
+/*          tv(5),...tv(nv-4) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  u     : real array of dimension at least (m). */
+/*  v     : real array of dimension at least (m). */
+/*          on succesful exit, u(i),v(i) contains the co-ordinates of */
+/*          the i-th data point with respect to the transformed rectan- */
+/*          gular approximation domain, for i=1,2,...,m. */
+/*          if the computation mode iopt(1)=1 is used the values of */
+/*          u(i),v(i) should be left unchanged between subsequent calls. */
+/*  c     : real array of dimension at least (nuest-4)*(nvest-4). */
+/*          on succesful exit, c contains the coefficients of the spline */
+/*          approximation s(u,v). */
+/*  fp    : real. unless ier=10, fp contains the weighted sum of */
+/*          squared residuals of the spline approximation returned. */
+/*  wrk1  : real array of dimension (lwrk1). used as workspace. */
+/*          if the computation mode iopt(1)=1 is used the value of */
+/*          wrk1(1) should be left unchanged between subsequent calls. */
+/*          on exit wrk1(2),wrk1(3),...,wrk1(1+ncof) will contain the */
+/*          values d(i)/max(d(i)),i=1,...,ncof=1+iopt(2)*(iopt(2)+3)/2+ */
+/*          (nv-7)*(nu-5-iopt(2)-iopt(3)) with d(i) the i-th diagonal el- */
+/*          ement of the triangular matrix for calculating the b-spline */
+/*          coefficients.it includes those elements whose square is < eps */
+/*          which are treated as 0 in the case of rank deficiency(ier=-2) */
+/*  lwrk1 : integer. on entry lwrk1 must specify the actual dimension of */
+/*          the array wrk1 as declared in the calling (sub)program. */
+/*          lwrk1 must not be too small. let */
+/*            k = nuest-7, l = nvest-7, p = 1+iopt(2)*(iopt(2)+3)/2, */
+/*            q = k+2-iopt(2)-iopt(3) then */
+/*          lwrk1 >= 129+10*k+21*l+k*l+(p+l*q)*(1+8*l+p)+8*m */
+/*  wrk2  : real array of dimension (lwrk2). used as workspace, but */
+/*          only in the case a rank deficient system is encountered. */
+/*  lwrk2 : integer. on entry lwrk2 must specify the actual dimension of */
+/*          the array wrk2 as declared in the calling (sub)program. */
+/*          lwrk2 > 0 . a save upper bound  for lwrk2 = (p+l*q+1)*(4*l+p) */
+/*          +p+l*q where p,l,q are as above. if there are enough data */
+/*          points, scattered uniformly over the approximation domain */
+/*          and if the smoothing factor s is not too small, there is a */
+/*          good chance that this extra workspace is not needed. a lot */
+/*          of memory might therefore be saved by setting lwrk2=1. */
+/*          (see also ier > 10) */
+/*  iwrk  : integer array of dimension (kwrk). used as workspace. */
+/*  kwrk  : integer. on entry kwrk must specify the actual dimension of */
+/*          the array iwrk as declared in the calling (sub)program. */
+/*          kwrk >= m+(nuest-7)*(nvest-7). */
+/*  ier   : integer. unless the routine detects an error, ier contains a */
+/*          non-positive value on exit, i.e. */
+/*   ier=0  : normal return. the spline returned has a residual sum of */
+/*            squares fp such that abs(fp-s)/s <= tol with tol a relat- */
+/*            ive tolerance set to 0.001 by the program. */
+/*   ier=-1 : normal return. the spline returned is an interpolating */
+/*            spline (fp=0). */
+/*   ier=-2 : normal return. the spline returned is the weighted least- */
+/*            squares constrained polynomial . in this extreme case */
+/*            fp gives the upper bound for the smoothing factor s. */
+/*   ier<-2 : warning. the coefficients of the spline returned have been */
+/*            computed as the minimal norm least-squares solution of a */
+/*            (numerically) rank deficient system. (-ier) gives the rank. */
+/*            especially if the rank deficiency which can be computed as */
+/*            1+iopt(2)*(iopt(2)+3)/2+(nv-7)*(nu-5-iopt(2)-iopt(3))+ier */
+/*            is large the results may be inaccurate. */
+/*            they could also seriously depend on the value of eps. */
+/*   ier=1  : error. the required storage space exceeds the available */
+/*            storage space, as specified by the parameters nuest and */
+/*            nvest. */
+/*            probably causes : nuest or nvest too small. if these param- */
+/*            eters are already large, it may also indicate that s is */
+/*            too small */
+/*            the approximation returned is the weighted least-squares */
+/*            polar spline according to the current set of knots. */
+/*            the parameter fp gives the corresponding weighted sum of */
+/*            squared residuals (fp>s). */
+/*   ier=2  : error. a theoretically impossible result was found during */
+/*            the iteration proces for finding a smoothing spline with */
+/*            fp = s. probably causes : s too small or badly chosen eps. */
+/*            there is an approximation returned but the corresponding */
+/*            weighted sum of squared residuals does not satisfy the */
+/*            condition abs(fp-s)/s < tol. */
+/*   ier=3  : error. the maximal number of iterations maxit (set to 20 */
+/*            by the program) allowed for finding a smoothing spline */
+/*            with fp=s has been reached. probably causes : s too small */
+/*            there is an approximation returned but the corresponding */
+/*            weighted sum of squared residuals does not satisfy the */
+/*            condition abs(fp-s)/s < tol. */
+/*   ier=4  : error. no more knots can be added because the dimension */
+/*            of the spline 1+iopt(2)*(iopt(2)+3)/2+(nv-7)*(nu-5-iopt(2) */
+/*            -iopt(3)) already exceeds the number of data points m. */
+/*            probably causes : either s or m too small. */
+/*            the approximation returned is the weighted least-squares */
+/*            polar spline according to the current set of knots. */
+/*            the parameter fp gives the corresponding weighted sum of */
+/*            squared residuals (fp>s). */
+/*   ier=5  : error. no more knots can be added because the additional */
+/*            knot would (quasi) coincide with an old one. */
+/*            probably causes : s too small or too large a weight to an */
+/*            inaccurate data point. */
+/*            the approximation returned is the weighted least-squares */
+/*            polar spline according to the current set of knots. */
+/*            the parameter fp gives the corresponding weighted sum of */
+/*            squared residuals (fp>s). */
+/*   ier=10 : error. on entry, the input data are controlled on validity */
+/*            the following restrictions must be satisfied. */
+/*            -1<=iopt(1)<=1 , 0<=iopt(2)<=2 , 0<=iopt(3)<=1 , */
+/*            m>=4-iopt(2)-iopt(3) , nuest>=8 ,nvest >=8, 0<eps<1, */
+/*            0<=teta(i)<=pi, 0<=phi(i)<=2*pi, w(i)>0, i=1,...,m */
+/*            lwrk1 >= 129+10*k+21*l+k*l+(p+l*q)*(1+8*l+p)+8*m */
+/*            kwrk >= m+(nuest-7)*(nvest-7) */
+/*            if iopt(1)=-1:9<=nu<=nuest,9+iopt(2)*(iopt(2)+1)<=nv<=nvest */
+/*                          0<tu(5)<tu(6)<...<tu(nu-4)<1 */
+/*                          -pi<tv(5)<tv(6)<...<tv(nv-4)<pi */
+/*            if iopt(1)>=0: s>=0 */
+/*            if one of these conditions is found to be violated,control */
+/*            is immediately repassed to the calling program. in that */
+/*            case there is no approximation returned. */
+/*   ier>10 : error. lwrk2 is too small, i.e. there is not enough work- */
+/*            space for computing the minimal least-squares solution of */
+/*            a rank deficient system of linear equations. ier gives the */
+/*            requested value for lwrk2. there is no approximation re- */
+/*            turned but, having saved the information contained in nu, */
+/*            nv,tu,tv,wrk1,u,v and having adjusted the value of lwrk2 */
+/*            and the dimension of the array wrk2 accordingly, the user */
+/*            can continue at the point the program was left, by calling */
+/*            polar with iopt(1)=1. */
+
+/* further comments: */
+/*  by means of the parameter s, the user can control the tradeoff */
+/*   between closeness of fit and smoothness of fit of the approximation. */
+/*   if s is too large, the spline will be too smooth and signal will be */
+/*   lost ; if s is too small the spline will pick up too much noise. in */
+/*   the extreme cases the program will return an interpolating spline if */
+/*   s=0 and the constrained weighted least-squares polynomial if s is */
+/*   very large. between these extremes, a properly chosen s will result */
+/*   in a good compromise between closeness of fit and smoothness of fit. */
+/*   to decide whether an approximation, corresponding to a certain s is */
+/*   satisfactory the user is highly recommended to inspect the fits */
+/*   graphically. */
+/*   recommended values for s depend on the weights w(i). if these are */
+/*   taken as 1/d(i) with d(i) an estimate of the standard deviation of */
+/*   z(i), a good s-value should be found in the range (m-sqrt(2*m),m+ */
+/*   sqrt(2*m)). if nothing is known about the statistical error in z(i) */
+/*   each w(i) can be set equal to one and s determined by trial and */
+/*   error, taking account of the comments above. the best is then to */
+/*   start with a very large value of s ( to determine the least-squares */
+/*   polynomial and the corresponding upper bound fp0 for s) and then to */
+/*   progressively decrease the value of s ( say by a factor 10 in the */
+/*   beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the */
+/*   approximation shows more detail) to obtain closer fits. */
+/*   to choose s very small is strongly discouraged. this considerably */
+/*   increases computation time and memory requirements. it may also */
+/*   cause rank-deficiency (ier<-2) and endager numerical stability. */
+/*   to economize the search for a good s-value the program provides with */
+/*   different modes of computation. at the first call of the routine, or */
+/*   whenever he wants to restart with the initial set of knots the user */
+/*   must set iopt(1)=0. */
+/*   if iopt(1)=1 the program will continue with the set of knots found */
+/*   at the last call of the routine. this will save a lot of computation */
+/*   time if polar is called repeatedly for different values of s. */
+/*   the number of knots of the spline returned and their location will */
+/*   depend on the value of s and on the complexity of the shape of the */
+/*   function underlying the data. if the computation mode iopt(1)=1 */
+/*   is used, the knots returned may also depend on the s-values at */
+/*   previous calls (if these were smaller). therefore, if after a number */
+/*   of trials with different s-values and iopt(1)=1,the user can finally */
+/*   accept a fit as satisfactory, it may be worthwhile for him to call */
+/*   polar once more with the selected value for s but now with iopt(1)=0 */
+/*   indeed, polar may then return an approximation of the same quality */
+/*   of fit but with fewer knots and therefore better if data reduction */
+/*   is also an important objective for the user. */
+/*   the number of knots may also depend on the upper bounds nuest and */
+/*   nvest. indeed, if at a certain stage in polar the number of knots */
+/*   in one direction (say nu) has reached the value of its upper bound */
+/*   (nuest), then from that moment on all subsequent knots are added */
+/*   in the other (v) direction. this may indicate that the value of */
+/*   nuest is too small. on the other hand, it gives the user the option */
+/*   of limiting the number of knots the routine locates in any direction */
+
+/*  other subroutines required: */
+/*    fpback,fpbspl,fppola,fpdisc,fpgivs,fprank,fprati,fprota,fporde, */
+/*    fprppo */
+
+/*  references: */
+/*   dierckx p.: an algorithm for fitting data over a circle using tensor */
+/*               product splines,j.comp.appl.maths 15 (1986) 161-173. */
+/*   dierckx p.: an algorithm for fitting data on a circle using tensor */
+/*               product splines, report tw68, dept. computer science, */
+/*               k.u.leuven, 1984. */
+/*   dierckx p.: curve and surface fitting with splines, monographs on */
+/*               numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*    p.dierckx */
+/*    dept. computer science, k.u. leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : june 1984 */
+/*  latest update : march 1989 */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..user specified function */
+/*  ..local scalars.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fppola */
+/*  .. */
+/*  set up constants */
+    /* Parameter adjustments */
+    --iopt;
+    --v;
+    --u;
+    --w;
+    --z__;
+    --y;
+    --x;
+    --tu;
+    --c__;
+    --tv;
+    --wrk1;
+    --wrk2;
+    --iwrk;
+
+    /* Function Body */
+    one = (float)1.;
+/*  we set up the parameters tol and maxit. */
+    maxit = 20;
+    tol = (float).001;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid,control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*eps <= (float)0. || *eps >= (float)1.) {
+	goto L60;
+    }
+    iopt1 = iopt[1];
+    if (iopt1 < -1 || iopt1 > 1) {
+	goto L60;
+    }
+    iopt2 = iopt[2];
+    if (iopt2 < 0 || iopt2 > 2) {
+	goto L60;
+    }
+    iopt3 = iopt[3];
+    if (iopt3 < 0 || iopt3 > 1) {
+	goto L60;
+    }
+    if (*m < 4 - iopt2 - iopt3) {
+	goto L60;
+    }
+    if (*nuest < 8 || *nvest < 8) {
+	goto L60;
+    }
+    nu4 = *nuest - 4;
+    nv4 = *nvest - 4;
+    ncest = nu4 * nv4;
+    nuu = *nuest - 7;
+    nvv = *nvest - 7;
+    ipar = iopt2 * (iopt2 + 3) / 2 + 1;
+    ncc = ipar + nvv * (*nuest - 5 - iopt2 - iopt3);
+    nrint = nuu + nvv;
+    nreg = nuu * nvv;
+    ib1 = nvv << 2;
+    ib3 = ib1 + ipar;
+    lwest = ncc * (ib1 + 1 + ib3) + (nrint << 1) + ncest + (*m << 3) + ib3 + *
+	    nuest * 5 + *nvest * 12;
+    kwest = *m + nreg;
+    if (*lwrk1 < lwest || *kwrk < kwest) {
+	goto L60;
+    }
+    if (iopt1 > 0) {
+	goto L40;
+    }
+    i__1 = *m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (w[i__] <= (float)0.) {
+	    goto L60;
+	}
+/* Computing 2nd power */
+	r__1 = x[i__];
+/* Computing 2nd power */
+	r__2 = y[i__];
+	dist = r__1 * r__1 + r__2 * r__2;
+	u[i__] = (float)0.;
+	v[i__] = (float)0.;
+	if (dist <= (float)0.) {
+	    goto L10;
+	}
+	v[i__] = atan2(y[i__], x[i__]);
+	r__ = (*rad)(&v[i__]);
+	if (r__ <= (float)0.) {
+	    goto L60;
+	}
+	u[i__] = sqrt(dist) / r__;
+	if (u[i__] > one) {
+	    goto L60;
+	}
+L10:
+	;
+    }
+    if (iopt1 == 0) {
+	goto L40;
+    }
+    nuu = *nu - 8;
+    if (nuu < 1 || *nu > *nuest) {
+	goto L60;
+    }
+    tu[4] = (float)0.;
+    i__1 = nuu;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	j = i__ + 4;
+	if (tu[j] <= tu[j - 1] || tu[j] >= one) {
+	    goto L60;
+	}
+/* L20: */
+    }
+    nvv = *nv - 8;
+    nvmin = iopt2 * (iopt2 + 1) + 9;
+    if (*nv < nvmin || *nv > *nvest) {
+	goto L60;
+    }
+    pi = atan2((float)0., -one);
+    tv[4] = -pi;
+    i__1 = nvv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	j = i__ + 4;
+	if (tv[j] <= tv[j - 1] || tv[j] >= pi) {
+	    goto L60;
+	}
+/* L30: */
+    }
+    goto L50;
+L40:
+    if (*s < (float)0.) {
+	goto L60;
+    }
+L50:
+    *ier = 0;
+/*  we partition the working space and determine the spline approximation */
+    kn = 1;
+    ki = kn + *m;
+    lq = 2;
+    la = lq + ncc * ib3;
+    lf = la + ncc * ib1;
+    lff = lf + ncc;
+    lfp = lff + ncest;
+    lco = lfp + nrint;
+    lh = lco + nrint;
+    lbu = lh + ib3;
+    lbv = lbu + *nuest * 5;
+    lro = lbv + *nvest * 5;
+    lcc = lro + *nvest;
+    lcs = lcc + *nvest;
+    lsu = lcs + *nvest * 5;
+    lsv = lsu + (*m << 2);
+    fppola_(&iopt1, &iopt2, &iopt3, m, &u[1], &v[1], &z__[1], &w[1], rad, s, 
+	    nuest, nvest, eps, &tol, &maxit, &ib1, &ib3, &ncest, &ncc, &nrint,
+	     &nreg, nu, &tu[1], nv, &tv[1], &c__[1], fp, &wrk1[1], &wrk1[lfp],
+	     &wrk1[lco], &wrk1[lf], &wrk1[lff], &wrk1[lro], &wrk1[lcc], &wrk1[
+	    lcs], &wrk1[la], &wrk1[lq], &wrk1[lbu], &wrk1[lbv], &wrk1[lsu], &
+	    wrk1[lsv], &wrk1[lh], &iwrk[ki], &iwrk[kn], &wrk2[1], lwrk2, ier);
+L60:
+    return 0;
+} /* polar_ */
+
+/* Subroutine */ int profil_(iopt, tx, nx, ty, ny, c__, kx, ky, u, nu, cu, 
+	ier)
+integer *iopt;
+real *tx;
+integer *nx;
+real *ty;
+integer *ny;
+real *c__;
+integer *kx, *ky;
+real *u;
+integer *nu;
+real *cu;
+integer *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static real h__[6];
+    static integer i__, j, l, m, l1, m0;
+    extern /* Subroutine */ int fpbspl_();
+    static integer kx1, ky1;
+    static real sum;
+    static integer nkx1, nky1;
+
+/*  if iopt=0 subroutine profil calculates the b-spline coefficients of */
+/*  the univariate spline f(y) = s(u,y) with s(x,y) a bivariate spline of */
+/*  degrees kx and ky, given in the b-spline representation. */
+/*  if iopt = 1 it calculates the b-spline coefficients of the univariate */
+/*  spline g(x) = s(x,u) */
+
+/*  calling sequence: */
+/*     call profil(iopt,tx,nx,ty,ny,c,kx,ky,u,nu,cu,ier) */
+
+/*  input parameters: */
+/*   iopt  : integer flag, specifying whether the profile f(y) (iopt=0) */
+/*           or the profile g(x) (iopt=1) must be determined. */
+/*   tx    : real array, length nx, which contains the position of the */
+/*           knots in the x-direction. */
+/*   nx    : integer, giving the total number of knots in the x-direction */
+/*   ty    : real array, length ny, which contains the position of the */
+/*           knots in the y-direction. */
+/*   ny    : integer, giving the total number of knots in the y-direction */
+/*   c     : real array, length (nx-kx-1)*(ny-ky-1), which contains the */
+/*           b-spline coefficients. */
+/*   kx,ky : integer values, giving the degrees of the spline. */
+/*   u     : real value, specifying the requested profile. */
+/*           tx(kx+1)<=u<=tx(nx-kx), if iopt=0. */
+/*           ty(ky+1)<=u<=ty(ny-ky), if iopt=1. */
+/*   nu    : on entry nu must specify the dimension of the array cu. */
+/*           nu >= ny if iopt=0, nu >= nx if iopt=1. */
+
+/*  output parameters: */
+/*   cu    : real array of dimension (nu). */
+/*           on succesful exit this array contains the b-spline */
+/*   ier   : integer error flag */
+/*    ier=0 : normal return */
+/*    ier=10: invalid input data (see restrictions) */
+
+/*  restrictions: */
+/*   if iopt=0 : tx(kx+1) <= u <= tx(nx-kx), nu >=ny. */
+/*   if iopt=1 : ty(ky+1) <= u <= ty(ny-ky), nu >=nx. */
+
+/*  other subroutines required: */
+/*    fpbspl */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1987 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local array */
+/*  .. */
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid control is immediately repassed to the calling program. */
+    /* Parameter adjustments */
+    --tx;
+    --ty;
+    --c__;
+    --cu;
+
+    /* Function Body */
+    kx1 = *kx + 1;
+    ky1 = *ky + 1;
+    nkx1 = *nx - kx1;
+    nky1 = *ny - ky1;
+    *ier = 10;
+    if (*iopt != 0) {
+	goto L200;
+    }
+    if (*nu < *ny) {
+	goto L300;
+    }
+    if (*u < tx[kx1] || *u > tx[nkx1 + 1]) {
+	goto L300;
+    }
+/*  the b-splinecoefficients of f(y) = s(u,y). */
+    *ier = 0;
+    l = kx1;
+    l1 = l + 1;
+L110:
+    if (*u < tx[l1] || l == nkx1) {
+	goto L120;
+    }
+    l = l1;
+    l1 = l + 1;
+    goto L110;
+L120:
+    fpbspl_(&tx[1], nx, kx, u, &l, h__);
+    m0 = (l - kx1) * nky1 + 1;
+    i__1 = nky1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	m = m0;
+	sum = (float)0.;
+	i__2 = kx1;
+	for (j = 1; j <= i__2; ++j) {
+	    sum += h__[j - 1] * c__[m];
+	    m += nky1;
+/* L130: */
+	}
+	cu[i__] = sum;
+	++m0;
+/* L140: */
+    }
+    goto L300;
+L200:
+    if (*nu < *nx) {
+	goto L300;
+    }
+    if (*u < ty[ky1] || *u > ty[nky1 + 1]) {
+	goto L300;
+    }
+/*  the b-splinecoefficients of g(x) = s(x,u). */
+    *ier = 0;
+    l = ky1;
+    l1 = l + 1;
+L210:
+    if (*u < ty[l1] || l == nky1) {
+	goto L220;
+    }
+    l = l1;
+    l1 = l + 1;
+    goto L210;
+L220:
+    fpbspl_(&ty[1], ny, ky, u, &l, h__);
+    m0 = l - *ky;
+    i__1 = nkx1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	m = m0;
+	sum = (float)0.;
+	i__2 = ky1;
+	for (j = 1; j <= i__2; ++j) {
+	    sum += h__[j - 1] * c__[m];
+	    ++m;
+/* L230: */
+	}
+	cu[i__] = sum;
+	m0 += nky1;
+/* L240: */
+    }
+L300:
+    return 0;
+} /* profil_ */
+
+/* Subroutine */ int regrid_(iopt, mx, x, my, y, z__, xb, xe, yb, ye, kx, ky, 
+	s, nxest, nyest, nx, tx, ny, ty, c__, fp, wrk, lwrk, iwrk, kwrk, ier)
+integer *iopt, *mx;
+real *x;
+integer *my;
+real *y, *z__, *xb, *xe, *yb, *ye;
+integer *kx, *ky;
+real *s;
+integer *nxest, *nyest, *nx;
+real *tx;
+integer *ny;
+real *ty, *c__, *fp, *wrk;
+integer *lwrk, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer kndx, kndy, lfpx, lfpy, jwrk, knrx, knry, i__, j, maxit, 
+	    nminx, nminy, kwest, lwest, nc;
+    extern /* Subroutine */ int fpchec_();
+    static integer mz;
+    extern /* Subroutine */ int fpregr_();
+    static integer kx1, kx2, ky1, ky2;
+    static real tol;
+    static integer lww;
+
+/* given the set of values z(i,j) on the rectangular grid (x(i),y(j)), */
+/* i=1,...,mx;j=1,...,my, subroutine regrid determines a smooth bivar- */
+/* iate spline approximation s(x,y) of degrees kx and ky on the rect- */
+/* angle xb <= x <= xe, yb <= y <= ye. */
+/* if iopt = -1 regrid calculates the least-squares spline according */
+/* to a given set of knots. */
+/* if iopt >= 0 the total numbers nx and ny of these knots and their */
+/* position tx(j),j=1,...,nx and ty(j),j=1,...,ny are chosen automatic- */
+/* ally by the routine. the smoothness of s(x,y) is then achieved by */
+/* minimalizing the discontinuity jumps in the derivatives of s(x,y) */
+/* across the boundaries of the subpanels (tx(i),tx(i+1))*(ty(j),ty(j+1). */
+/* the amounth of smoothness is determined by the condition that f(p) = */
+/* sum ((z(i,j)-s(x(i),y(j))))**2) be <= s, with s a given non-negative */
+/* constant, called the smoothing factor. */
+/* the fit is given in the b-spline representation (b-spline coefficients */
+/* c((ny-ky-1)*(i-1)+j),i=1,...,nx-kx-1;j=1,...,ny-ky-1) and can be eval- */
+/* uated by means of subroutine bispev. */
+
+/* calling sequence: */
+/*     call regrid(iopt,mx,x,my,y,z,xb,xe,yb,ye,kx,ky,s,nxest,nyest, */
+/*    *  nx,tx,ny,ty,c,fp,wrk,lwrk,iwrk,kwrk,ier) */
+
+/* parameters: */
+/*  iopt  : integer flag. on entry iopt must specify whether a least- */
+/*          squares spline (iopt=-1) or a smoothing spline (iopt=0 or 1) */
+/*          must be determined. */
+/*          if iopt=0 the routine will start with an initial set of knots */
+/*          tx(i)=xb,tx(i+kx+1)=xe,i=1,...,kx+1;ty(i)=yb,ty(i+ky+1)=ye,i= */
+/*          1,...,ky+1. if iopt=1 the routine will continue with the set */
+/*          of knots found at the last call of the routine. */
+/*          attention: a call with iopt=1 must always be immediately pre- */
+/*                     ceded by another call with iopt=1 or iopt=0 and */
+/*                     s.ne.0. */
+/*          unchanged on exit. */
+/*  mx    : integer. on entry mx must specify the number of grid points */
+/*          along the x-axis. mx > kx . unchanged on exit. */
+/*  x     : real array of dimension at least (mx). before entry, x(i) */
+/*          must be set to the x-co-ordinate of the i-th grid point */
+/*          along the x-axis, for i=1,2,...,mx. these values must be */
+/*          supplied in strictly ascending order. unchanged on exit. */
+/*  my    : integer. on entry my must specify the number of grid points */
+/*          along the y-axis. my > ky . unchanged on exit. */
+/*  y     : real array of dimension at least (my). before entry, y(j) */
+/*          must be set to the y-co-ordinate of the j-th grid point */
+/*          along the y-axis, for j=1,2,...,my. these values must be */
+/*          supplied in strictly ascending order. unchanged on exit. */
+/*  z     : real array of dimension at least (mx*my). */
+/*          before entry, z(my*(i-1)+j) must be set to the data value at */
+/*          the grid point (x(i),y(j)) for i=1,...,mx and j=1,...,my. */
+/*          unchanged on exit. */
+/*  xb,xe : real values. on entry xb,xe,yb and ye must specify the bound- */
+/*  yb,ye   aries of the rectangular approximation domain. */
+/*          xb<=x(i)<=xe,i=1,...,mx; yb<=y(j)<=ye,j=1,...,my. */
+/*          unchanged on exit. */
+/*  kx,ky : integer values. on entry kx and ky must specify the degrees */
+/*          of the spline. 1<=kx,ky<=5. it is recommended to use bicubic */
+/*          (kx=ky=3) splines. unchanged on exit. */
+/*  s     : real. on entry (in case iopt>=0) s must specify the smoothing */
+/*          factor. s >=0. unchanged on exit. */
+/*          for advice on the choice of s see further comments */
+/*  nxest : integer. unchanged on exit. */
+/*  nyest : integer. unchanged on exit. */
+/*          on entry, nxest and nyest must specify an upper bound for the */
+/*          number of knots required in the x- and y-directions respect. */
+/*          these numbers will also determine the storage space needed by */
+/*          the routine. nxest >= 2*(kx+1), nyest >= 2*(ky+1). */
+/*          in most practical situation nxest = mx/2, nyest=my/2, will */
+/*          be sufficient. always large enough are nxest=mx+kx+1, nyest= */
+/*          my+ky+1, the number of knots needed for interpolation (s=0). */
+/*          see also further comments. */
+/*  nx    : integer. */
+/*          unless ier=10 (in case iopt >=0), nx will contain the total */
+/*          number of knots with respect to the x-variable, of the spline */
+/*          approximation returned. if the computation mode iopt=1 is */
+/*          used, the value of nx should be left unchanged between sub- */
+/*          sequent calls. */
+/*          in case iopt=-1, the value of nx should be specified on entry */
+/*  tx    : real array of dimension nmax. */
+/*          on succesful exit, this array will contain the knots of the */
+/*          spline with respect to the x-variable, i.e. the position of */
+/*          the interior knots tx(kx+2),...,tx(nx-kx-1) as well as the */
+/*          position of the additional knots tx(1)=...=tx(kx+1)=xb and */
+/*          tx(nx-kx)=...=tx(nx)=xe needed for the b-spline representat. */
+/*          if the computation mode iopt=1 is used, the values of tx(1), */
+/*          ...,tx(nx) should be left unchanged between subsequent calls. */
+/*          if the computation mode iopt=-1 is used, the values tx(kx+2), */
+/*          ...tx(nx-kx-1) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  ny    : integer. */
+/*          unless ier=10 (in case iopt >=0), ny will contain the total */
+/*          number of knots with respect to the y-variable, of the spline */
+/*          approximation returned. if the computation mode iopt=1 is */
+/*          used, the value of ny should be left unchanged between sub- */
+/*          sequent calls. */
+/*          in case iopt=-1, the value of ny should be specified on entry */
+/*  ty    : real array of dimension nmax. */
+/*          on succesful exit, this array will contain the knots of the */
+/*          spline with respect to the y-variable, i.e. the position of */
+/*          the interior knots ty(ky+2),...,ty(ny-ky-1) as well as the */
+/*          position of the additional knots ty(1)=...=ty(ky+1)=yb and */
+/*          ty(ny-ky)=...=ty(ny)=ye needed for the b-spline representat. */
+/*          if the computation mode iopt=1 is used, the values of ty(1), */
+/*          ...,ty(ny) should be left unchanged between subsequent calls. */
+/*          if the computation mode iopt=-1 is used, the values ty(ky+2), */
+/*          ...ty(ny-ky-1) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  c     : real array of dimension at least (nxest-kx-1)*(nyest-ky-1). */
+/*          on succesful exit, c contains the coefficients of the spline */
+/*          approximation s(x,y) */
+/*  fp    : real. unless ier=10, fp contains the sum of squared */
+/*          residuals of the spline approximation returned. */
+/*  wrk   : real array of dimension (lwrk). used as workspace. */
+/*          if the computation mode iopt=1 is used the values of wrk(1), */
+/*          ...,wrk(4) should be left unchanged between subsequent calls. */
+/*  lwrk  : integer. on entry lwrk must specify the actual dimension of */
+/*          the array wrk as declared in the calling (sub)program. */
+/*          lwrk must not be too small. */
+/*           lwrk >= 4+nxest*(my+2*kx+5)+nyest*(2*ky+5)+mx*(kx+1)+ */
+/*            my*(ky+1) +u */
+/*           where u is the larger of my and nxest. */
+/*  iwrk  : integer array of dimension (kwrk). used as workspace. */
+/*          if the computation mode iopt=1 is used the values of iwrk(1), */
+/*          ...,iwrk(3) should be left unchanged between subsequent calls */
+/*  kwrk  : integer. on entry kwrk must specify the actual dimension of */
+/*          the array iwrk as declared in the calling (sub)program. */
+/*          kwrk >= 3+mx+my+nxest+nyest. */
+/*  ier   : integer. unless the routine detects an error, ier contains a */
+/*          non-positive value on exit, i.e. */
+/*   ier=0  : normal return. the spline returned has a residual sum of */
+/*            squares fp such that abs(fp-s)/s <= tol with tol a relat- */
+/*            ive tolerance set to 0.001 by the program. */
+/*   ier=-1 : normal return. the spline returned is an interpolating */
+/*            spline (fp=0). */
+/*   ier=-2 : normal return. the spline returned is the least-squares */
+/*            polynomial of degrees kx and ky. in this extreme case fp */
+/*            gives the upper bound for the smoothing factor s. */
+/*   ier=1  : error. the required storage space exceeds the available */
+/*            storage space, as specified by the parameters nxest and */
+/*            nyest. */
+/*            probably causes : nxest or nyest too small. if these param- */
+/*            eters are already large, it may also indicate that s is */
+/*            too small */
+/*            the approximation returned is the least-squares spline */
+/*            according to the current set of knots. the parameter fp */
+/*            gives the corresponding sum of squared residuals (fp>s). */
+/*   ier=2  : error. a theoretically impossible result was found during */
+/*            the iteration proces for finding a smoothing spline with */
+/*            fp = s. probably causes : s too small. */
+/*            there is an approximation returned but the corresponding */
+/*            sum of squared residuals does not satisfy the condition */
+/*            abs(fp-s)/s < tol. */
+/*   ier=3  : error. the maximal number of iterations maxit (set to 20 */
+/*            by the program) allowed for finding a smoothing spline */
+/*            with fp=s has been reached. probably causes : s too small */
+/*            there is an approximation returned but the corresponding */
+/*            sum of squared residuals does not satisfy the condition */
+/*            abs(fp-s)/s < tol. */
+/*   ier=10 : error. on entry, the input data are controlled on validity */
+/*            the following restrictions must be satisfied. */
+/*            -1<=iopt<=1, 1<=kx,ky<=5, mx>kx, my>ky, nxest>=2*kx+2, */
+/*            nyest>=2*ky+2, kwrk>=3+mx+my+nxest+nyest, */
+/*            lwrk >= 4+nxest*(my+2*kx+5)+nyest*(2*ky+5)+mx*(kx+1)+ */
+/*             my*(ky+1) +max(my,nxest), */
+/*            xb<=x(i-1)<x(i)<=xe,i=2,..,mx,yb<=y(j-1)<y(j)<=ye,j=2,..,my */
+/*            if iopt=-1: 2*kx+2<=nx<=min(nxest,mx+kx+1) */
+/*                        xb<tx(kx+2)<tx(kx+3)<...<tx(nx-kx-1)<xe */
+/*                        2*ky+2<=ny<=min(nyest,my+ky+1) */
+/*                        yb<ty(ky+2)<ty(ky+3)<...<ty(ny-ky-1)<ye */
+/*                    the schoenberg-whitney conditions, i.e. there must */
+/*                    be subset of grid co-ordinates xx(p) and yy(q) such */
+/*                    that   tx(p) < xx(p) < tx(p+kx+1) ,p=1,...,nx-kx-1 */
+/*                           ty(q) < yy(q) < ty(q+ky+1) ,q=1,...,ny-ky-1 */
+/*            if iopt>=0: s>=0 */
+/*                        if s=0 : nxest>=mx+kx+1, nyest>=my+ky+1 */
+/*            if one of these conditions is found to be violated,control */
+/*            is immediately repassed to the calling program. in that */
+/*            case there is no approximation returned. */
+
+/* further comments: */
+/*   regrid does not allow individual weighting of the data-values. */
+/*   so, if these were determined to widely different accuracies, then */
+/*   perhaps the general data set routine surfit should rather be used */
+/*   in spite of efficiency. */
+/*   by means of the parameter s, the user can control the tradeoff */
+/*   between closeness of fit and smoothness of fit of the approximation. */
+/*   if s is too large, the spline will be too smooth and signal will be */
+/*   lost ; if s is too small the spline will pick up too much noise. in */
+/*   the extreme cases the program will return an interpolating spline if */
+/*   s=0 and the least-squares polynomial (degrees kx,ky) if s is */
+/*   very large. between these extremes, a properly chosen s will result */
+/*   in a good compromise between closeness of fit and smoothness of fit. */
+/*   to decide whether an approximation, corresponding to a certain s is */
+/*   satisfactory the user is highly recommended to inspect the fits */
+/*   graphically. */
+/*   recommended values for s depend on the accuracy of the data values. */
+/*   if the user has an idea of the statistical errors on the data, he */
+/*   can also find a proper estimate for s. for, by assuming that, if he */
+/*   specifies the right s, regrid will return a spline s(x,y) which */
+/*   exactly reproduces the function underlying the data he can evaluate */
+/*   the sum((z(i,j)-s(x(i),y(j)))**2) to find a good estimate for this s */
+/*   for example, if he knows that the statistical errors on his z(i,j)- */
+/*   values is not greater than 0.1, he may expect that a good s should */
+/*   have a value not larger than mx*my*(0.1)**2. */
+/*   if nothing is known about the statistical error in z(i,j), s must */
+/*   be determined by trial and error, taking account of the comments */
+/*   above. the best is then to start with a very large value of s (to */
+/*   determine the least-squares polynomial and the corresponding upper */
+/*   bound fp0 for s) and then to progressively decrease the value of s */
+/*   ( say by a factor 10 in the beginning, i.e. s=fp0/10,fp0/100,... */
+/*   and more carefully as the approximation shows more detail) to */
+/*   obtain closer fits. */
+/*   to economize the search for a good s-value the program provides with */
+/*   different modes of computation. at the first call of the routine, or */
+/*   whenever he wants to restart with the initial set of knots the user */
+/*   must set iopt=0. */
+/*   if iopt=1 the program will continue with the set of knots found at */
+/*   the last call of the routine. this will save a lot of computation */
+/*   time if regrid is called repeatedly for different values of s. */
+/*   the number of knots of the spline returned and their location will */
+/*   depend on the value of s and on the complexity of the shape of the */
+/*   function underlying the data. if the computation mode iopt=1 */
+/*   is used, the knots returned may also depend on the s-values at */
+/*   previous calls (if these were smaller). therefore, if after a number */
+/*   of trials with different s-values and iopt=1, the user can finally */
+/*   accept a fit as satisfactory, it may be worthwhile for him to call */
+/*   regrid once more with the selected value for s but now with iopt=0. */
+/*   indeed, regrid may then return an approximation of the same quality */
+/*   of fit but with fewer knots and therefore better if data reduction */
+/*   is also an important objective for the user. */
+/*   the number of knots may also depend on the upper bounds nxest and */
+/*   nyest. indeed, if at a certain stage in regrid the number of knots */
+/*   in one direction (say nx) has reached the value of its upper bound */
+/*   (nxest), then from that moment on all subsequent knots are added */
+/*   in the other (y) direction. this may indicate that the value of */
+/*   nxest is too small. on the other hand, it gives the user the option */
+/*   of limiting the number of knots the routine locates in any direction */
+/*   for example, by setting nxest=2*kx+2 (the lowest allowable value for */
+/*   nxest), the user can indicate that he wants an approximation which */
+/*   is a simple polynomial of degree kx in the variable x. */
+
+/*  other subroutines required: */
+/*    fpback,fpbspl,fpregr,fpdisc,fpgivs,fpgrre,fprati,fprota,fpchec, */
+/*    fpknot */
+
+/*  references: */
+/*   dierckx p. : a fast algorithm for smoothing data on a rectangular */
+/*                grid while using spline functions, siam j.numer.anal. */
+/*                19 (1982) 1286-1304. */
+/*   dierckx p. : a fast algorithm for smoothing data on a rectangular */
+/*                grid while using spline functions, report tw53, dept. */
+/*                computer science,k.u.leuven, 1980. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*    p.dierckx */
+/*    dept. computer science, k.u. leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : may 1979 */
+/*  latest update : march 1989 */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpregr,fpchec */
+/*  .. */
+/*  we set up the parameters tol and maxit. */
+    /* Parameter adjustments */
+    --x;
+    --z__;
+    --y;
+    --tx;
+    --c__;
+    --ty;
+    --wrk;
+    --iwrk;
+
+    /* Function Body */
+    maxit = 20;
+    tol = (float).001;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*kx <= 0 || *kx > 5) {
+	goto L70;
+    }
+    kx1 = *kx + 1;
+    kx2 = kx1 + 1;
+    if (*ky <= 0 || *ky > 5) {
+	goto L70;
+    }
+    ky1 = *ky + 1;
+    ky2 = ky1 + 1;
+    if (*iopt < -1 || *iopt > 1) {
+	goto L70;
+    }
+    nminx = kx1 << 1;
+    if (*mx < kx1 || *nxest < nminx) {
+	goto L70;
+    }
+    nminy = ky1 << 1;
+    if (*my < ky1 || *nyest < nminy) {
+	goto L70;
+    }
+    mz = *mx * *my;
+    nc = (*nxest - kx1) * (*nyest - ky1);
+    lwest = *nxest * (*my + (kx2 << 1) + 1) + 4 + *nyest * ((ky2 << 1) + 1) + 
+	    *mx * kx1 + *my * ky1 + max(*nxest,*my);
+    kwest = *mx + 3 + *my + *nxest + *nyest;
+    if (*lwrk < lwest || *kwrk < kwest) {
+	goto L70;
+    }
+    if (*xb > x[1] || *xe < x[*mx]) {
+	goto L70;
+    }
+    i__1 = *mx;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (x[i__ - 1] >= x[i__]) {
+	    goto L70;
+	}
+/* L10: */
+    }
+    if (*yb > y[1] || *ye < y[*my]) {
+	goto L70;
+    }
+    i__1 = *my;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (y[i__ - 1] >= y[i__]) {
+	    goto L70;
+	}
+/* L20: */
+    }
+    if (*iopt >= 0) {
+	goto L50;
+    }
+    if (*nx < nminx || *nx > *nxest) {
+	goto L70;
+    }
+    j = *nx;
+    i__1 = kx1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	tx[i__] = *xb;
+	tx[j] = *xe;
+	--j;
+/* L30: */
+    }
+    fpchec_(&x[1], mx, &tx[1], nx, kx, ier);
+    if (*ier != 0) {
+	goto L70;
+    }
+    if (*ny < nminy || *ny > *nyest) {
+	goto L70;
+    }
+    j = *ny;
+    i__1 = ky1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	ty[i__] = *yb;
+	ty[j] = *ye;
+	--j;
+/* L40: */
+    }
+    fpchec_(&y[1], my, &ty[1], ny, ky, ier);
+    if (*ier != 0) {
+	goto L70;
+    } else {
+	goto L60;
+    }
+L50:
+    if (*s < (float)0.) {
+	goto L70;
+    }
+    if (*s == (float)0. && (*nxest < *mx + kx1 || *nyest < *my + ky1)) {
+	goto L70;
+    }
+    *ier = 0;
+/*  we partition the working space and determine the spline approximation */
+L60:
+    lfpx = 5;
+    lfpy = lfpx + *nxest;
+    lww = lfpy + *nyest;
+    jwrk = *lwrk - 4 - *nxest - *nyest;
+    knrx = 4;
+    knry = knrx + *mx;
+    kndx = knry + *my;
+    kndy = kndx + *nxest;
+    fpregr_(iopt, &x[1], mx, &y[1], my, &z__[1], &mz, xb, xe, yb, ye, kx, ky, 
+	    s, nxest, nyest, &tol, &maxit, &nc, nx, &tx[1], ny, &ty[1], &c__[
+	    1], fp, &wrk[1], &wrk[2], &wrk[3], &wrk[4], &wrk[lfpx], &wrk[lfpy]
+	    , &iwrk[1], &iwrk[2], &iwrk[3], &iwrk[knrx], &iwrk[knry], &iwrk[
+	    kndx], &iwrk[kndy], &wrk[lww], &jwrk, ier);
+L70:
+    return 0;
+} /* regrid_ */
+
+/* Subroutine */ int spalde_(t, n, c__, k1, x, d__, ier)
+real *t;
+integer *n;
+real *c__;
+integer *k1;
+real *x, *d__;
+integer *ier;
+{
+    static integer l;
+    extern /* Subroutine */ int fpader_();
+    static integer nk1;
+
+/*  subroutine spalde evaluates at a point x all the derivatives */
+/*              (j-1) */
+/*      d(j) = s     (x) , j=1,2,...,k1 */
+/*  of a spline s(x) of order k1 (degree k=k1-1), given in its b-spline */
+/*  representation. */
+
+/*  calling sequence: */
+/*     call spalde(t,n,c,k1,x,d,ier) */
+
+/*  input parameters: */
+/*    t    : array,length n, which contains the position of the knots. */
+/*    n    : integer, giving the total number of knots of s(x). */
+/*    c    : array,length n, which contains the b-spline coefficients. */
+/*    k1   : integer, giving the order of s(x) (order=degree+1) */
+/*    x    : real, which contains the point where the derivatives must */
+/*           be evaluated. */
+
+/*  output parameters: */
+/*    d    : array,length k1, containing the derivative values of s(x). */
+/*    ier  : error flag */
+/*      ier = 0 : normal return */
+/*      ier =10 : invalid input data (see restrictions) */
+
+/*  restrictions: */
+/*    t(k1) <= x <= t(n-k1+1) */
+
+/*  further comments: */
+/*    if x coincides with a knot, right derivatives are computed */
+/*    ( left derivatives if x = t(n-k1+1) ). */
+
+/*  other subroutines required: fpader. */
+
+/*  references : */
+/*    de boor c : on calculating with b-splines, j. approximation theory */
+/*                6 (1972) 50-62. */
+/*    cox m.g.  : the numerical evaluation of b-splines, j. inst. maths */
+/*                applics 10 (1972) 134-149. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1987 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid control is immediately repassed to the calling program. */
+    /* Parameter adjustments */
+    --c__;
+    --t;
+    --d__;
+
+    /* Function Body */
+    *ier = 10;
+    nk1 = *n - *k1;
+    if (*x < t[*k1] || *x > t[nk1 + 1]) {
+	goto L300;
+    }
+/*  search for knot interval t(l) <= x < t(l+1) */
+    l = *k1;
+L100:
+    if (*x < t[l + 1] || l == nk1) {
+	goto L200;
+    }
+    ++l;
+    goto L100;
+L200:
+    if (t[l] >= t[l + 1]) {
+	goto L300;
+    }
+    *ier = 0;
+/*  calculate the derivatives. */
+    fpader_(&t[1], n, &c__[1], k1, x, &l, &d__[1]);
+L300:
+    return 0;
+} /* spalde_ */
+
+/* Subroutine */ int spgrid_(iopt, ider, mu, u, mv, v, r__, r0, r1, s, nuest, 
+	nvest, nu, tu, nv, tv, c__, fp, wrk, lwrk, iwrk, kwrk, ier)
+integer *iopt, *ider, *mu;
+real *u;
+integer *mv;
+real *v, *r__, *r0, *r1, *s;
+integer *nuest, *nvest, *nu;
+real *tu;
+integer *nv;
+real *tv, *c__, *fp, *wrk;
+integer *lwrk, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Builtin functions */
+    double atan2();
+
+    /* Local variables */
+    static real half;
+    static integer kndu, kndv;
+    static real rmin;
+    static integer lfpu;
+    static real rmax;
+    static integer lfpv, jwrk, knru, knrv, i__, j, l, m, maxit, mumin, i1, i2,
+	     j1, j2, kwest, lwest, nc;
+    static real rb, re;
+    extern /* Subroutine */ int fpchec_();
+    static real pi, ve, rn;
+    extern /* Subroutine */ int fpchep_();
+    static real uu;
+    extern /* Subroutine */ int fpspgr_();
+    static real one;
+    static integer ldr;
+    static real per, tol;
+    static integer muu, lww;
+
+/*  given the function values r(i,j) on the latitude-longitude grid */
+/*  (u(i),v(j)), i=1,...,mu ; j=1,...,mv , spgrid determines a smooth */
+/*  bicubic spline approximation on the rectangular domain 0<=u<=pi, */
+/*  vb<=v<=ve (vb = v(1), ve=vb+2*pi). */
+/*  this approximation s(u,v) will satisfy the properties */
+
+/*    (1) s(0,v) = s(0,0) = dr(1) */
+
+/*        d s(0,v)           d s(0,0)           d s(0,pi/2) */
+/*    (2) -------- = cos(v)* -------- + sin(v)* ----------- */
+/*        d u                d u                d u */
+
+/*                 = cos(v)*dr(2)+sin(v)*dr(3) */
+/*                                                     vb <= v <= ve */
+/*    (3) s(pi,v) = s(pi,0) = dr(4) */
+
+/*        d s(pi,v)           d s(pi,0)           d s(pi,pi/2) */
+/*    (4) -------- = cos(v)*  --------- + sin(v)* ------------ */
+/*        d u                 d u                 d u */
+
+/*                 = cos(v)*dr(5)+sin(v)*dr(6) */
+
+/*  and will be periodic in the variable v, i.e. */
+
+/*         j           j */
+/*        d s(u,vb)   d s(u,ve) */
+/*    (5) --------- = ---------   0 <=u<= pi , j=0,1,2 */
+/*           j           j */
+/*        d v         d v */
+
+/*  the number of knots of s(u,v) and their position tu(i),i=1,2,...,nu; */
+/*  tv(j),j=1,2,...,nv, is chosen automatically by the routine. the */
+/*  smoothness of s(u,v) is achieved by minimalizing the discontinuity */
+/*  jumps of the derivatives of the spline at the knots. the amount of */
+/*  smoothness of s(u,v) is determined by the condition that */
+/*  fp=sumi=1,mu(sumj=1,mv((r(i,j)-s(u(i),v(j)))**2))+(r0-s(0,v))**2 */
+/*  + (r1-s(pi,v))**2 <= s, with s a given non-negative constant. */
+/*  the fit s(u,v) is given in its b-spline representation and can be */
+/*  evaluated by means of routine bispev */
+
+/* calling sequence: */
+/*     call spgrid(iopt,ider,mu,u,mv,v,r,r0,r1,s,nuest,nvest,nu,tu, */
+/*    *  ,nv,tv,c,fp,wrk,lwrk,iwrk,kwrk,ier) */
+
+/* parameters: */
+/*  iopt  : integer array of dimension 3, specifying different options. */
+/*          unchanged on exit. */
+/*  iopt(1):on entry iopt(1) must specify whether a least-squares spline */
+/*          (iopt(1)=-1) or a smoothing spline (iopt(1)=0 or 1) must be */
+/*          determined. */
+/*          if iopt(1)=0 the routine will start with an initial set of */
+/*          knots tu(i)=0,tu(i+4)=pi,i=1,...,4;tv(i)=v(1)+(i-4)*2*pi, */
+/*          i=1,...,8. */
+/*          if iopt(1)=1 the routine will continue with the set of knots */
+/*          found at the last call of the routine. */
+/*          attention: a call with iopt(1)=1 must always be immediately */
+/*          preceded by another call with iopt(1) = 1 or iopt(1) = 0. */
+/*  iopt(2):on entry iopt(2) must specify the requested order of conti- */
+/*          nuity at the pole u=0. */
+/*          if iopt(2)=0 only condition (1) must be fulfilled and */
+/*          if iopt(2)=1 conditions (1)+(2) must be fulfilled. */
+/*  iopt(3):on entry iopt(3) must specify the requested order of conti- */
+/*          nuity at the pole u=pi. */
+/*          if iopt(3)=0 only condition (3) must be fulfilled and */
+/*          if iopt(3)=1 conditions (3)+(4) must be fulfilled. */
+/*  ider  : integer array of dimension 4, specifying different options. */
+/*          unchanged on exit. */
+/*  ider(1):on entry ider(1) must specify whether (ider(1)=0 or 1) or not */
+/*          (ider(1)=-1) there is a data value r0 at the pole u=0. */
+/*          if ider(1)=1, r0 will be considered to be the right function */
+/*          value, and it will be fitted exactly (s(0,v)=r0). */
+/*          if ider(1)=0, r0 will be considered to be a data value just */
+/*          like the other data values r(i,j). */
+/*  ider(2):on entry ider(2) must specify whether (ider(2)=1) or not */
+/*          (ider(2)=0) the approximation has vanishing derivatives */
+/*          dr(2) and dr(3) at the pole u=0  (in case iopt(2)=1) */
+/*  ider(3):on entry ider(3) must specify whether (ider(3)=0 or 1) or not */
+/*          (ider(3)=-1) there is a data value r1 at the pole u=pi. */
+/*          if ider(3)=1, r1 will be considered to be the right function */
+/*          value, and it will be fitted exactly (s(pi,v)=r1). */
+/*          if ider(3)=0, r1 will be considered to be a data value just */
+/*          like the other data values r(i,j). */
+/*  ider(4):on entry ider(4) must specify whether (ider(4)=1) or not */
+/*          (ider(4)=0) the approximation has vanishing derivatives */
+/*          dr(5) and dr(6) at the pole u=pi (in case iopt(3)=1) */
+/*  mu    : integer. on entry mu must specify the number of grid points */
+/*          along the u-axis. unchanged on exit. */
+/*          mu >= 1, mu >=mumin=4-i0-i1-ider(2)-ider(4) with */
+/*            i0=min(1,ider(1)+1), i1=min(1,ider(3)+1) */
+/*  u     : real array of dimension at least (mu). before entry, u(i) */
+/*          must be set to the u-co-ordinate of the i-th grid point */
+/*          along the u-axis, for i=1,2,...,mu. these values must be */
+/*          supplied in strictly ascending order. unchanged on exit. */
+/*          0 < u(i) < pi. */
+/*  mv    : integer. on entry mv must specify the number of grid points */
+/*          along the v-axis. mv > 3 . unchanged on exit. */
+/*  v     : real array of dimension at least (mv). before entry, v(j) */
+/*          must be set to the v-co-ordinate of the j-th grid point */
+/*          along the v-axis, for j=1,2,...,mv. these values must be */
+/*          supplied in strictly ascending order. unchanged on exit. */
+/*          -pi <= v(1) < pi , v(mv) < v(1)+2*pi. */
+/*  r     : real array of dimension at least (mu*mv). */
+/*          before entry, r(mv*(i-1)+j) must be set to the data value at */
+/*          the grid point (u(i),v(j)) for i=1,...,mu and j=1,...,mv. */
+/*          unchanged on exit. */
+/*  r0    : real value. on entry (if ider(1) >=0 ) r0 must specify the */
+/*          data value at the pole u=0. unchanged on exit. */
+/*  r1    : real value. on entry (if ider(1) >=0 ) r1 must specify the */
+/*          data value at the pole u=pi. unchanged on exit. */
+/*  s     : real. on entry (if iopt(1)>=0) s must specify the smoothing */
+/*          factor. s >=0. unchanged on exit. */
+/*          for advice on the choice of s see further comments */
+/*  nuest : integer. unchanged on exit. */
+/*  nvest : integer. unchanged on exit. */
+/*          on entry, nuest and nvest must specify an upper bound for the */
+/*          number of knots required in the u- and v-directions respect. */
+/*          these numbers will also determine the storage space needed by */
+/*          the routine. nuest >= 8, nvest >= 8. */
+/*          in most practical situation nuest = mu/2, nvest=mv/2, will */
+/*          be sufficient. always large enough are nuest=mu+6+iopt(2)+ */
+/*          iopt(3), nvest = mv+7, the number of knots needed for */
+/*          interpolation (s=0). see also further comments. */
+/*  nu    : integer. */
+/*          unless ier=10 (in case iopt(1)>=0), nu will contain the total */
+/*          number of knots with respect to the u-variable, of the spline */
+/*          approximation returned. if the computation mode iopt(1)=1 is */
+/*          used, the value of nu should be left unchanged between sub- */
+/*          sequent calls. in case iopt(1)=-1, the value of nu should be */
+/*          specified on entry. */
+/*  tu    : real array of dimension at least (nuest). */
+/*          on succesful exit, this array will contain the knots of the */
+/*          spline with respect to the u-variable, i.e. the position of */
+/*          the interior knots tu(5),...,tu(nu-4) as well as the position */
+/*          of the additional knots tu(1)=...=tu(4)=0 and tu(nu-3)=...= */
+/*          tu(nu)=pi needed for the b-spline representation. */
+/*          if the computation mode iopt(1)=1 is used,the values of tu(1) */
+/*          ...,tu(nu) should be left unchanged between subsequent calls. */
+/*          if the computation mode iopt(1)=-1 is used, the values tu(5), */
+/*          ...tu(nu-4) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  nv    : integer. */
+/*          unless ier=10 (in case iopt(1)>=0), nv will contain the total */
+/*          number of knots with respect to the v-variable, of the spline */
+/*          approximation returned. if the computation mode iopt(1)=1 is */
+/*          used, the value of nv should be left unchanged between sub- */
+/*          sequent calls. in case iopt(1) = -1, the value of nv should */
+/*          be specified on entry. */
+/*  tv    : real array of dimension at least (nvest). */
+/*          on succesful exit, this array will contain the knots of the */
+/*          spline with respect to the v-variable, i.e. the position of */
+/*          the interior knots tv(5),...,tv(nv-4) as well as the position */
+/*          of the additional knots tv(1),...,tv(4) and tv(nv-3),..., */
+/*          tv(nv) needed for the b-spline representation. */
+/*          if the computation mode iopt(1)=1 is used,the values of tv(1) */
+/*          ...,tv(nv) should be left unchanged between subsequent calls. */
+/*          if the computation mode iopt(1)=-1 is used, the values tv(5), */
+/*          ...tv(nv-4) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  c     : real array of dimension at least (nuest-4)*(nvest-4). */
+/*          on succesful exit, c contains the coefficients of the spline */
+/*          approximation s(u,v) */
+/*  fp    : real. unless ier=10, fp contains the sum of squared */
+/*          residuals of the spline approximation returned. */
+/*  wrk   : real array of dimension (lwrk). used as workspace. */
+/*          if the computation mode iopt(1)=1 is used the values of */
+/*          wrk(1),..,wrk(12) should be left unchanged between subsequent */
+/*          calls. */
+/*  lwrk  : integer. on entry lwrk must specify the actual dimension of */
+/*          the array wrk as declared in the calling (sub)program. */
+/*          lwrk must not be too small. */
+/*           lwrk >= 12+nuest*(mv+nvest+3)+nvest*24+4*mu+8*mv+q */
+/*           where q is the larger of (mv+nvest) and nuest. */
+/*  iwrk  : integer array of dimension (kwrk). used as workspace. */
+/*          if the computation mode iopt(1)=1 is used the values of */
+/*          iwrk(1),.,iwrk(5) should be left unchanged between subsequent */
+/*          calls. */
+/*  kwrk  : integer. on entry kwrk must specify the actual dimension of */
+/*          the array iwrk as declared in the calling (sub)program. */
+/*          kwrk >= 5+mu+mv+nuest+nvest. */
+/*  ier   : integer. unless the routine detects an error, ier contains a */
+/*          non-positive value on exit, i.e. */
+/*   ier=0  : normal return. the spline returned has a residual sum of */
+/*            squares fp such that abs(fp-s)/s <= tol with tol a relat- */
+/*            ive tolerance set to 0.001 by the program. */
+/*   ier=-1 : normal return. the spline returned is an interpolating */
+/*            spline (fp=0). */
+/*   ier=-2 : normal return. the spline returned is the least-squares */
+/*            constrained polynomial. in this extreme case fp gives the */
+/*            upper bound for the smoothing factor s. */
+/*   ier=1  : error. the required storage space exceeds the available */
+/*            storage space, as specified by the parameters nuest and */
+/*            nvest. */
+/*            probably causes : nuest or nvest too small. if these param- */
+/*            eters are already large, it may also indicate that s is */
+/*            too small */
+/*            the approximation returned is the least-squares spline */
+/*            according to the current set of knots. the parameter fp */
+/*            gives the corresponding sum of squared residuals (fp>s). */
+/*   ier=2  : error. a theoretically impossible result was found during */
+/*            the iteration proces for finding a smoothing spline with */
+/*            fp = s. probably causes : s too small. */
+/*            there is an approximation returned but the corresponding */
+/*            sum of squared residuals does not satisfy the condition */
+/*            abs(fp-s)/s < tol. */
+/*   ier=3  : error. the maximal number of iterations maxit (set to 20 */
+/*            by the program) allowed for finding a smoothing spline */
+/*            with fp=s has been reached. probably causes : s too small */
+/*            there is an approximation returned but the corresponding */
+/*            sum of squared residuals does not satisfy the condition */
+/*            abs(fp-s)/s < tol. */
+/*   ier=10 : error. on entry, the input data are controlled on validity */
+/*            the following restrictions must be satisfied. */
+/*            -1<=iopt(1)<=1, 0<=iopt(2)<=1, 0<=iopt(3)<=1, */
+/*            -1<=ider(1)<=1, 0<=ider(2)<=1, ider(2)=0 if iopt(2)=0. */
+/*            -1<=ider(3)<=1, 0<=ider(4)<=1, ider(4)=0 if iopt(3)=0. */
+/*            mu >= mumin (see above), mv >= 4, nuest >=8, nvest >= 8, */
+/*            kwrk>=5+mu+mv+nuest+nvest, */
+/*            lwrk >= 12+nuest*(mv+nvest+3)+nvest*24+4*mu+8*mv+ */
+/*             max(nuest,mv+nvest) */
+/*            0< u(i-1)<u(i)< pi,i=2,..,mu, */
+/*            -pi<=v(1)< pi, v(1)<v(i-1)<v(i)<v(1)+2*pi, i=3,...,mv */
+/*            if iopt(1)=-1: 8<=nu<=min(nuest,mu+6+iopt(2)+iopt(3)) */
+/*                           0<tu(5)<tu(6)<...<tu(nu-4)< pi */
+/*                           8<=nv<=min(nvest,mv+7) */
+/*                           v(1)<tv(5)<tv(6)<...<tv(nv-4)<v(1)+2*pi */
+/*                    the schoenberg-whitney conditions, i.e. there must */
+/*                    be subset of grid co-ordinates uu(p) and vv(q) such */
+/*                    that   tu(p) < uu(p) < tu(p+4) ,p=1,...,nu-4 */
+/*                     (iopt(2)=1 and iopt(3)=1 also count for a uu-value */
+/*                           tv(q) < vv(q) < tv(q+4) ,q=1,...,nv-4 */
+/*                     (vv(q) is either a value v(j) or v(j)+2*pi) */
+/*            if iopt(1)>=0: s>=0 */
+/*                       if s=0: nuest>=mu+6+iopt(2)+iopt(3), nvest>=mv+7 */
+/*            if one of these conditions is found to be violated,control */
+/*            is immediately repassed to the calling program. in that */
+/*            case there is no approximation returned. */
+
+/* further comments: */
+/*   spgrid does not allow individual weighting of the data-values. */
+/*   so, if these were determined to widely different accuracies, then */
+/*   perhaps the general data set routine sphere should rather be used */
+/*   in spite of efficiency. */
+/*   by means of the parameter s, the user can control the tradeoff */
+/*   between closeness of fit and smoothness of fit of the approximation. */
+/*   if s is too large, the spline will be too smooth and signal will be */
+/*   lost ; if s is too small the spline will pick up too much noise. in */
+/*   the extreme cases the program will return an interpolating spline if */
+/*   s=0 and the constrained least-squares polynomial(degrees 3,0)if s is */
+/*   very large. between these extremes, a properly chosen s will result */
+/*   in a good compromise between closeness of fit and smoothness of fit. */
+/*   to decide whether an approximation, corresponding to a certain s is */
+/*   satisfactory the user is highly recommended to inspect the fits */
+/*   graphically. */
+/*   recommended values for s depend on the accuracy of the data values. */
+/*   if the user has an idea of the statistical errors on the data, he */
+/*   can also find a proper estimate for s. for, by assuming that, if he */
+/*   specifies the right s, spgrid will return a spline s(u,v) which */
+/*   exactly reproduces the function underlying the data he can evaluate */
+/*   the sum((r(i,j)-s(u(i),v(j)))**2) to find a good estimate for this s */
+/*   for example, if he knows that the statistical errors on his r(i,j)- */
+/*   values is not greater than 0.1, he may expect that a good s should */
+/*   have a value not larger than mu*mv*(0.1)**2. */
+/*   if nothing is known about the statistical error in r(i,j), s must */
+/*   be determined by trial and error, taking account of the comments */
+/*   above. the best is then to start with a very large value of s (to */
+/*   determine the least-squares polynomial and the corresponding upper */
+/*   bound fp0 for s) and then to progressively decrease the value of s */
+/*   ( say by a factor 10 in the beginning, i.e. s=fp0/10,fp0/100,... */
+/*   and more carefully as the approximation shows more detail) to */
+/*   obtain closer fits. */
+/*   to economize the search for a good s-value the program provides with */
+/*   different modes of computation. at the first call of the routine, or */
+/*   whenever he wants to restart with the initial set of knots the user */
+/*   must set iopt(1)=0. */
+/*   if iopt(1) = 1 the program will continue with the knots found at */
+/*   the last call of the routine. this will save a lot of computation */
+/*   time if spgrid is called repeatedly for different values of s. */
+/*   the number of knots of the spline returned and their location will */
+/*   depend on the value of s and on the complexity of the shape of the */
+/*   function underlying the data. if the computation mode iopt(1) = 1 */
+/*   is used, the knots returned may also depend on the s-values at */
+/*   previous calls (if these were smaller). therefore, if after a number */
+/*   of trials with different s-values and iopt(1)=1,the user can finally */
+/*   accept a fit as satisfactory, it may be worthwhile for him to call */
+/*   spgrid once more with the chosen value for s but now with iopt(1)=0. */
+/*   indeed, spgrid may then return an approximation of the same quality */
+/*   of fit but with fewer knots and therefore better if data reduction */
+/*   is also an important objective for the user. */
+/*   the number of knots may also depend on the upper bounds nuest and */
+/*   nvest. indeed, if at a certain stage in spgrid the number of knots */
+/*   in one direction (say nu) has reached the value of its upper bound */
+/*   (nuest), then from that moment on all subsequent knots are added */
+/*   in the other (v) direction. this may indicate that the value of */
+/*   nuest is too small. on the other hand, it gives the user the option */
+/*   of limiting the number of knots the routine locates in any direction */
+/*   for example, by setting nuest=8 (the lowest allowable value for */
+/*   nuest), the user can indicate that he wants an approximation which */
+/*   is a simple cubic polynomial in the variable u. */
+
+/*  other subroutines required: */
+/*    fpspgr,fpchec,fpchep,fpknot,fpopsp,fprati,fpgrsp,fpsysy,fpback, */
+/*    fpbacp,fpbspl,fpcyt1,fpcyt2,fpdisc,fpgivs,fprota */
+
+/*  references: */
+/*   dierckx p. : fast algorithms for smoothing data over a disc or a */
+/*                sphere using tensor product splines, in "algorithms */
+/*                for approximation", ed. j.c.mason and m.g.cox, */
+/*                clarendon press oxford, 1987, pp. 51-65 */
+/*   dierckx p. : fast algorithms for smoothing data over a disc or a */
+/*                sphere using tensor product splines, report tw73, dept. */
+/*                computer science,k.u.leuven, 1985. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*    p.dierckx */
+/*    dept. computer science, k.u. leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : july 1985 */
+/*  latest update : march 1989 */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpchec,fpchep,fpspgr */
+/*  .. */
+/*  set constants */
+    /* Parameter adjustments */
+    --iopt;
+    --ider;
+    --u;
+    --r__;
+    --v;
+    --tu;
+    --c__;
+    --tv;
+    --wrk;
+    --iwrk;
+
+    /* Function Body */
+    one = (float)1.;
+    half = (float).5;
+    pi = atan2((float)0., -one);
+    per = pi + pi;
+    ve = v[1] + per;
+/*  we set up the parameters tol and maxit. */
+    maxit = 20;
+    tol = (float).001;
+/*  before starting computations, a data check is made. if the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (iopt[1] < -1 || iopt[1] > 1) {
+	goto L200;
+    }
+    if (iopt[2] < 0 || iopt[2] > 1) {
+	goto L200;
+    }
+    if (iopt[3] < 0 || iopt[3] > 1) {
+	goto L200;
+    }
+    if (ider[1] < -1 || ider[1] > 1) {
+	goto L200;
+    }
+    if (ider[2] < 0 || ider[2] > 1) {
+	goto L200;
+    }
+    if (ider[2] == 1 && iopt[2] == 0) {
+	goto L200;
+    }
+    if (ider[3] < -1 || ider[3] > 1) {
+	goto L200;
+    }
+    if (ider[4] < 0 || ider[4] > 1) {
+	goto L200;
+    }
+    if (ider[4] == 1 && iopt[3] == 0) {
+	goto L200;
+    }
+    mumin = 4;
+    if (ider[1] >= 0) {
+	--mumin;
+    }
+    if (iopt[2] == 1 && ider[2] == 1) {
+	--mumin;
+    }
+    if (ider[3] >= 0) {
+	--mumin;
+    }
+    if (iopt[3] == 1 && ider[4] == 1) {
+	--mumin;
+    }
+    if (mumin == 0) {
+	mumin = 1;
+    }
+    if (*mu < mumin || *mv < 4) {
+	goto L200;
+    }
+    if (*nuest < 8 || *nvest < 8) {
+	goto L200;
+    }
+    m = *mu * *mv;
+    nc = (*nuest - 4) * (*nvest - 4);
+/* Computing MAX */
+    i__1 = *nuest, i__2 = *mv + *nvest;
+    lwest = *nuest * (*mv + *nvest + 3) + 12 + *nvest * 24 + (*mu << 2) + (*
+	    mv << 3) + max(i__1,i__2);
+    kwest = *mu + 5 + *mv + *nuest + *nvest;
+    if (*lwrk < lwest || *kwrk < kwest) {
+	goto L200;
+    }
+    if (u[1] <= (float)0. || u[*mu] >= pi) {
+	goto L200;
+    }
+    if (*mu == 1) {
+	goto L30;
+    }
+    i__1 = *mu;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (u[i__ - 1] >= u[i__]) {
+	    goto L200;
+	}
+/* L20: */
+    }
+L30:
+    if (v[1] < -pi || v[1] >= pi) {
+	goto L200;
+    }
+    if (v[*mv] >= v[1] + per) {
+	goto L200;
+    }
+    i__1 = *mv;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (v[i__ - 1] >= v[i__]) {
+	    goto L200;
+	}
+/* L40: */
+    }
+    if (iopt[1] > 0) {
+	goto L140;
+    }
+/*  if not given, we compute an estimate for r0. */
+    rn = (real) (*mv);
+    if (ider[1] < 0) {
+	goto L45;
+    }
+    rb = *r0;
+    goto L55;
+L45:
+    rb = (float)0.;
+    i__1 = *mv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	rb += r__[i__];
+/* L50: */
+    }
+    rb /= rn;
+/*  if not given, we compute an estimate for r1. */
+L55:
+    if (ider[3] < 0) {
+	goto L60;
+    }
+    re = *r1;
+    goto L70;
+L60:
+    re = (float)0.;
+    j = m;
+    i__1 = *mv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	re += r__[j];
+	--j;
+/* L65: */
+    }
+    re /= rn;
+/*  we determine the range of r-values. */
+L70:
+    rmin = rb;
+    rmax = re;
+    i__1 = m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (r__[i__] < rmin) {
+	    rmin = r__[i__];
+	}
+	if (r__[i__] > rmax) {
+	    rmax = r__[i__];
+	}
+/* L80: */
+    }
+    wrk[5] = rb;
+    wrk[6] = (float)0.;
+    wrk[7] = (float)0.;
+    wrk[8] = re;
+    wrk[9] = (float)0.;
+    wrk[10] = (float)0.;
+    wrk[11] = rmax - rmin;
+    wrk[12] = wrk[11];
+    iwrk[4] = *mu;
+    iwrk[5] = *mu;
+    if (iopt[1] == 0) {
+	goto L140;
+    }
+    if (*nu < 8 || *nu > *nuest) {
+	goto L200;
+    }
+    if (*nv < 11 || *nv > *nvest) {
+	goto L200;
+    }
+    j = *nu;
+    for (i__ = 1; i__ <= 4; ++i__) {
+	tu[i__] = (float)0.;
+	tu[j] = pi;
+	--j;
+/* L90: */
+    }
+    l = 13;
+    wrk[l] = (float)0.;
+    if (iopt[2] == 0) {
+	goto L100;
+    }
+    ++l;
+    uu = u[1];
+    if (uu > tu[5]) {
+	uu = tu[5];
+    }
+    wrk[l] = uu * half;
+L100:
+    i__1 = *mu;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	++l;
+	wrk[l] = u[i__];
+/* L110: */
+    }
+    if (iopt[3] == 0) {
+	goto L120;
+    }
+    ++l;
+    uu = u[*mu];
+    if (uu < tu[*nu - 4]) {
+	uu = tu[*nu - 4];
+    }
+    wrk[l] = uu + (pi - uu) * half;
+L120:
+    ++l;
+    wrk[l] = pi;
+    muu = l - 12;
+    fpchec_(&wrk[13], &muu, &tu[1], nu, &c__3, ier);
+    if (*ier != 0) {
+	goto L200;
+    }
+    j1 = 4;
+    tv[j1] = v[1];
+    i1 = *nv - 3;
+    tv[i1] = ve;
+    j2 = j1;
+    i2 = i1;
+    for (i__ = 1; i__ <= 3; ++i__) {
+	++i1;
+	--i2;
+	++j1;
+	--j2;
+	tv[j2] = tv[i2] - per;
+	tv[i1] = tv[j1] + per;
+/* L130: */
+    }
+    l = 13;
+    i__1 = *mv;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	wrk[l] = v[i__];
+	++l;
+/* L135: */
+    }
+    wrk[l] = ve;
+    i__1 = *mv + 1;
+    fpchep_(&wrk[13], &i__1, &tv[1], nv, &c__3, ier);
+    if (*ier != 0) {
+	goto L200;
+    } else {
+	goto L150;
+    }
+L140:
+    if (*s < (float)0.) {
+	goto L200;
+    }
+    if (*s == (float)0. && (*nuest < *mu + 6 + iopt[2] + iopt[3] || *nvest < *
+	    mv + 7)) {
+	goto L200;
+    }
+/*  we partition the working space and determine the spline approximation */
+L150:
+    ldr = 5;
+    lfpu = 13;
+    lfpv = lfpu + *nuest;
+    lww = lfpv + *nvest;
+    jwrk = *lwrk - 12 - *nuest - *nvest;
+    knru = 6;
+    knrv = knru + *mu;
+    kndu = knrv + *mv;
+    kndv = kndu + *nuest;
+    fpspgr_(&iopt[1], &ider[1], &u[1], mu, &v[1], mv, &r__[1], &m, &rb, &re, 
+	    s, nuest, nvest, &tol, &maxit, &nc, nu, &tu[1], nv, &tv[1], &c__[
+	    1], fp, &wrk[1], &wrk[2], &wrk[3], &wrk[4], &wrk[lfpu], &wrk[lfpv]
+	    , &wrk[ldr], &wrk[11], &iwrk[1], &iwrk[2], &iwrk[3], &iwrk[4], &
+	    iwrk[5], &iwrk[knru], &iwrk[knrv], &iwrk[kndu], &iwrk[kndv], &wrk[
+	    lww], &jwrk, ier);
+L200:
+    return 0;
+} /* spgrid_ */
+
+/* Subroutine */ int sphere_(iopt, m, teta, phi, r__, w, s, ntest, npest, eps,
+	 nt, tt, np, tp, c__, fp, wrk1, lwrk1, wrk2, lwrk2, iwrk, kwrk, ier)
+integer *iopt, *m;
+real *teta, *phi, *r__, *w, *s;
+integer *ntest, *npest;
+real *eps;
+integer *nt;
+real *tt;
+integer *np;
+real *tp, *c__, *fp, *wrk1;
+integer *lwrk1;
+real *wrk2;
+integer *lwrk2, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Builtin functions */
+    double atan();
+
+    /* Local variables */
+    static integer ncof, nreg, i__, j, ncest, maxit, nrint, kwest, lwest, la, 
+	    lf, ki, lh;
+    static real pi;
+    static integer kn, lq;
+    extern /* Subroutine */ int fpsphe_();
+    static integer ib1, ib3;
+    static real pi2;
+    static integer np4, nt4, lcc, ncc, lff, lco, lbp;
+    static real one;
+    static integer lbt, lcs, lfp, lro, npp;
+    static real tol;
+    static integer lsp, lst, ntt;
+
+/*  subroutine sphere determines a smooth bicubic spherical spline */
+/*  approximation s(teta,phi), 0 <= teta <= pi ; 0 <= phi <= 2*pi */
+/*  to a given set of data points (teta(i),phi(i),r(i)),i=1,2,...,m. */
+/*  such a spline has the following specific properties */
+
+/*    (1) s(0,phi)  = constant   0 <=phi<= 2*pi. */
+
+/*    (2) s(pi,phi) = constant   0 <=phi<= 2*pi */
+
+/*         j             j */
+/*        d s(teta,0)   d s(teta,2*pi) */
+/*    (3) ----------- = ------------   0 <=teta<=pi, j=0,1,2 */
+/*             j             j */
+/*        d phi         d phi */
+
+/*        d s(0,phi)    d s(0,0)             d s(0,pi/2) */
+/*    (4) ----------  = -------- *cos(phi) + ----------- *sin(phi) */
+/*        d teta        d teta               d teta */
+
+/*        d s(pi,phi)   d s(pi,0)            d s(pi,pi/2) */
+/*    (5) ----------- = ---------*cos(phi) + ------------*sin(phi) */
+/*        d teta        d teta               d teta */
+
+/*  if iopt =-1 sphere calculates a weighted least-squares spherical */
+/*  spline according to a given set of knots in teta- and phi- direction. */
+/*  if iopt >=0, the number of knots in each direction and their position */
+/*  tt(j),j=1,2,...,nt ; tp(j),j=1,2,...,np are chosen automatically by */
+/*  the routine. the smoothness of s(teta,phi) is then achieved by mini- */
+/*  malizing the discontinuity jumps of the derivatives of the spline */
+/*  at the knots. the amount of smoothness of s(teta,phi) is determined */
+/*  by the condition that fp = sum((w(i)*(r(i)-s(teta(i),phi(i))))**2) */
+/*  be <= s, with s a given non-negative constant. */
+/*  the spherical spline is given in the standard b-spline representation */
+/*  of bicubic splines and can be evaluated by means of subroutine bispev */
+
+/* calling sequence: */
+/*     call sphere(iopt,m,teta,phi,r,w,s,ntest,npest,eps, */
+/*    *  nt,tt,np,tp,c,fp,wrk1,lwrk1,wrk2,lwrk2,iwrk,kwrk,ier) */
+
+/* parameters: */
+/*  iopt  : integer flag. on entry iopt must specify whether a weighted */
+/*          least-squares spherical spline (iopt=-1) or a smoothing */
+/*          spherical spline (iopt=0 or 1) must be determined. */
+/*          if iopt=0 the routine will start with an initial set of knots */
+/*          tt(i)=0,tt(i+4)=pi,i=1,...,4;tp(i)=0,tp(i+4)=2*pi,i=1,...,4. */
+/*          if iopt=1 the routine will continue with the set of knots */
+/*          found at the last call of the routine. */
+/*          attention: a call with iopt=1 must always be immediately pre- */
+/*                     ceded by another call with iopt=1 or iopt=0. */
+/*          unchanged on exit. */
+/*  m     : integer. on entry m must specify the number of data points. */
+/*          m >= 2. unchanged on exit. */
+/*  teta  : real array of dimension at least (m). */
+/*  phi   : real array of dimension at least (m). */
+/*  r     : real array of dimension at least (m). */
+/*          before entry,teta(i),phi(i),r(i) must be set to the spherical */
+/*          co-ordinates of the i-th data point, for i=1,...,m.the order */
+/*          of the data points is immaterial. unchanged on exit. */
+/*  w     : real array of dimension at least (m). before entry, w(i) must */
+/*          be set to the i-th value in the set of weights. the w(i) must */
+/*          be strictly positive. unchanged on exit. */
+/*  s     : real. on entry (in case iopt>=0) s must specify the smoothing */
+/*          factor. s >=0. unchanged on exit. */
+/*          for advice on the choice of s see further comments */
+/*  ntest : integer. unchanged on exit. */
+/*  npest : integer. unchanged on exit. */
+/*          on entry, ntest and npest must specify an upper bound for the */
+/*          number of knots required in the teta- and phi-directions. */
+/*          these numbers will also determine the storage space needed by */
+/*          the routine. ntest >= 8, npest >= 8. */
+/*          in most practical situation ntest = npest = 8+sqrt(m/2) will */
+/*          be sufficient. see also further comments. */
+/*  eps   : real. */
+/*          on entry, eps must specify a threshold for determining the */
+/*          effective rank of an over-determined linear system of equat- */
+/*          ions. 0 < eps < 1.  if the number of decimal digits in the */
+/*          computer representation of a real number is q, then 10**(-q) */
+/*          is a suitable value for eps in most practical applications. */
+/*          unchanged on exit. */
+/*  nt    : integer. */
+/*          unless ier=10 (in case iopt >=0), nt will contain the total */
+/*          number of knots with respect to the teta-variable, of the */
+/*          spline approximation returned. if the computation mode iopt=1 */
+/*          is used, the value of nt should be left unchanged between */
+/*          subsequent calls. */
+/*          in case iopt=-1, the value of nt should be specified on entry */
+/*  tt    : real array of dimension at least ntest. */
+/*          on succesful exit, this array will contain the knots of the */
+/*          spline with respect to the teta-variable, i.e. the position */
+/*          of the interior knots tt(5),...,tt(nt-4) as well as the */
+/*          position of the additional knots tt(1)=...=tt(4)=0 and */
+/*          tt(nt-3)=...=tt(nt)=pi needed for the b-spline representation */
+/*          if the computation mode iopt=1 is used, the values of tt(1), */
+/*          ...,tt(nt) should be left unchanged between subsequent calls. */
+/*          if the computation mode iopt=-1 is used, the values tt(5), */
+/*          ...tt(nt-4) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  np    : integer. */
+/*          unless ier=10 (in case iopt >=0), np will contain the total */
+/*          number of knots with respect to the phi-variable, of the */
+/*          spline approximation returned. if the computation mode iopt=1 */
+/*          is used, the value of np should be left unchanged between */
+/*          subsequent calls. */
+/*          in case iopt=-1, the value of np (>=9) should be specified */
+/*          on entry. */
+/*  tp    : real array of dimension at least npest. */
+/*          on succesful exit, this array will contain the knots of the */
+/*          spline with respect to the phi-variable, i.e. the position of */
+/*          the interior knots tp(5),...,tp(np-4) as well as the position */
+/*          of the additional knots tp(1),...,tp(4) and tp(np-3),..., */
+/*          tp(np) needed for the b-spline representation. */
+/*          if the computation mode iopt=1 is used, the values of tp(1), */
+/*          ...,tp(np) should be left unchanged between subsequent calls. */
+/*          if the computation mode iopt=-1 is used, the values tp(5), */
+/*          ...tp(np-4) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  c     : real array of dimension at least (ntest-4)*(npest-4). */
+/*          on succesful exit, c contains the coefficients of the spline */
+/*          approximation s(teta,phi). */
+/*  fp    : real. unless ier=10, fp contains the weighted sum of */
+/*          squared residuals of the spline approximation returned. */
+/*  wrk1  : real array of dimension (lwrk1). used as workspace. */
+/*          if the computation mode iopt=1 is used the value of wrk1(1) */
+/*          should be left unchanged between subsequent calls. */
+/*          on exit wrk1(2),wrk1(3),...,wrk1(1+ncof) will contain the */
+/*          values d(i)/max(d(i)),i=1,...,ncof=6+(np-7)*(nt-8) */
+/*          with d(i) the i-th diagonal element of the reduced triangular */
+/*          matrix for calculating the b-spline coefficients. it includes */
+/*          those elements whose square is less than eps,which are treat- */
+/*          ed as 0 in the case of presumed rank deficiency (ier<-2). */
+/*  lwrk1 : integer. on entry lwrk1 must specify the actual dimension of */
+/*          the array wrk1 as declared in the calling (sub)program. */
+/*          lwrk1 must not be too small. let */
+/*            u = ntest-7, v = npest-7, then */
+/*          lwrk1 >= 185+52*v+10*u+14*u*v+8*(u-1)*v**2+8*m */
+/*  wrk2  : real array of dimension (lwrk2). used as workspace, but */
+/*          only in the case a rank deficient system is encountered. */
+/*  lwrk2 : integer. on entry lwrk2 must specify the actual dimension of */
+/*          the array wrk2 as declared in the calling (sub)program. */
+/*          lwrk2 > 0 . a save upper bound  for lwrk2 = 48+21*v+7*u*v+ */
+/*          4*(u-1)*v**2 where u,v are as above. if there are enough data */
+/*          points, scattered uniformly over the approximation domain */
+/*          and if the smoothing factor s is not too small, there is a */
+/*          good chance that this extra workspace is not needed. a lot */
+/*          of memory might therefore be saved by setting lwrk2=1. */
+/*          (see also ier > 10) */
+/*  iwrk  : integer array of dimension (kwrk). used as workspace. */
+/*  kwrk  : integer. on entry kwrk must specify the actual dimension of */
+/*          the array iwrk as declared in the calling (sub)program. */
+/*          kwrk >= m+(ntest-7)*(npest-7). */
+/*  ier   : integer. unless the routine detects an error, ier contains a */
+/*          non-positive value on exit, i.e. */
+/*   ier=0  : normal return. the spline returned has a residual sum of */
+/*            squares fp such that abs(fp-s)/s <= tol with tol a relat- */
+/*            ive tolerance set to 0.001 by the program. */
+/*   ier=-1 : normal return. the spline returned is a spherical */
+/*            interpolating spline (fp=0). */
+/*   ier=-2 : normal return. the spline returned is the weighted least- */
+/*            squares constrained polynomial . in this extreme case */
+/*            fp gives the upper bound for the smoothing factor s. */
+/*   ier<-2 : warning. the coefficients of the spline returned have been */
+/*            computed as the minimal norm least-squares solution of a */
+/*            (numerically) rank deficient system. (-ier) gives the rank. */
+/*            especially if the rank deficiency which can be computed as */
+/*            6+(nt-8)*(np-7)+ier, is large the results may be inaccurate */
+/*            they could also seriously depend on the value of eps. */
+/*   ier=1  : error. the required storage space exceeds the available */
+/*            storage space, as specified by the parameters ntest and */
+/*            npest. */
+/*            probably causes : ntest or npest too small. if these param- */
+/*            eters are already large, it may also indicate that s is */
+/*            too small */
+/*            the approximation returned is the weighted least-squares */
+/*            spherical spline according to the current set of knots. */
+/*            the parameter fp gives the corresponding weighted sum of */
+/*            squared residuals (fp>s). */
+/*   ier=2  : error. a theoretically impossible result was found during */
+/*            the iteration proces for finding a smoothing spline with */
+/*            fp = s. probably causes : s too small or badly chosen eps. */
+/*            there is an approximation returned but the corresponding */
+/*            weighted sum of squared residuals does not satisfy the */
+/*            condition abs(fp-s)/s < tol. */
+/*   ier=3  : error. the maximal number of iterations maxit (set to 20 */
+/*            by the program) allowed for finding a smoothing spline */
+/*            with fp=s has been reached. probably causes : s too small */
+/*            there is an approximation returned but the corresponding */
+/*            weighted sum of squared residuals does not satisfy the */
+/*            condition abs(fp-s)/s < tol. */
+/*   ier=4  : error. no more knots can be added because the dimension */
+/*            of the spherical spline 6+(nt-8)*(np-7) already exceeds */
+/*            the number of data points m. */
+/*            probably causes : either s or m too small. */
+/*            the approximation returned is the weighted least-squares */
+/*            spherical spline according to the current set of knots. */
+/*            the parameter fp gives the corresponding weighted sum of */
+/*            squared residuals (fp>s). */
+/*   ier=5  : error. no more knots can be added because the additional */
+/*            knot would (quasi) coincide with an old one. */
+/*            probably causes : s too small or too large a weight to an */
+/*            inaccurate data point. */
+/*            the approximation returned is the weighted least-squares */
+/*            spherical spline according to the current set of knots. */
+/*            the parameter fp gives the corresponding weighted sum of */
+/*            squared residuals (fp>s). */
+/*   ier=10 : error. on entry, the input data are controlled on validity */
+/*            the following restrictions must be satisfied. */
+/*            -1<=iopt<=1,  m>=2, ntest>=8 ,npest >=8, 0<eps<1, */
+/*            0<=teta(i)<=pi, 0<=phi(i)<=2*pi, w(i)>0, i=1,...,m */
+/*            lwrk1 >= 185+52*v+10*u+14*u*v+8*(u-1)*v**2+8*m */
+/*            kwrk >= m+(ntest-7)*(npest-7) */
+/*            if iopt=-1: 8<=nt<=ntest , 9<=np<=npest */
+/*                        0<tt(5)<tt(6)<...<tt(nt-4)<pi */
+/*                        0<tp(5)<tp(6)<...<tp(np-4)<2*pi */
+/*            if iopt>=0: s>=0 */
+/*            if one of these conditions is found to be violated,control */
+/*            is immediately repassed to the calling program. in that */
+/*            case there is no approximation returned. */
+/*   ier>10 : error. lwrk2 is too small, i.e. there is not enough work- */
+/*            space for computing the minimal least-squares solution of */
+/*            a rank deficient system of linear equations. ier gives the */
+/*            requested value for lwrk2. there is no approximation re- */
+/*            turned but, having saved the information contained in nt, */
+/*            np,tt,tp,wrk1, and having adjusted the value of lwrk2 and */
+/*            the dimension of the array wrk2 accordingly, the user can */
+/*            continue at the point the program was left, by calling */
+/*            sphere with iopt=1. */
+
+/* further comments: */
+/*  by means of the parameter s, the user can control the tradeoff */
+/*   between closeness of fit and smoothness of fit of the approximation. */
+/*   if s is too large, the spline will be too smooth and signal will be */
+/*   lost ; if s is too small the spline will pick up too much noise. in */
+/*   the extreme cases the program will return an interpolating spline if */
+/*   s=0 and the constrained weighted least-squares polynomial if s is */
+/*   very large. between these extremes, a properly chosen s will result */
+/*   in a good compromise between closeness of fit and smoothness of fit. */
+/*   to decide whether an approximation, corresponding to a certain s is */
+/*   satisfactory the user is highly recommended to inspect the fits */
+/*   graphically. */
+/*   recommended values for s depend on the weights w(i). if these are */
+/*   taken as 1/d(i) with d(i) an estimate of the standard deviation of */
+/*   r(i), a good s-value should be found in the range (m-sqrt(2*m),m+ */
+/*   sqrt(2*m)). if nothing is known about the statistical error in r(i) */
+/*   each w(i) can be set equal to one and s determined by trial and */
+/*   error, taking account of the comments above. the best is then to */
+/*   start with a very large value of s ( to determine the least-squares */
+/*   polynomial and the corresponding upper bound fp0 for s) and then to */
+/*   progressively decrease the value of s ( say by a factor 10 in the */
+/*   beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the */
+/*   approximation shows more detail) to obtain closer fits. */
+/*   to choose s very small is strongly discouraged. this considerably */
+/*   increases computation time and memory requirements. it may also */
+/*   cause rank-deficiency (ier<-2) and endager numerical stability. */
+/*   to economize the search for a good s-value the program provides with */
+/*   different modes of computation. at the first call of the routine, or */
+/*   whenever he wants to restart with the initial set of knots the user */
+/*   must set iopt=0. */
+/*   if iopt=1 the program will continue with the set of knots found at */
+/*   the last call of the routine. this will save a lot of computation */
+/*   time if sphere is called repeatedly for different values of s. */
+/*   the number of knots of the spline returned and their location will */
+/*   depend on the value of s and on the complexity of the shape of the */
+/*   function underlying the data. if the computation mode iopt=1 */
+/*   is used, the knots returned may also depend on the s-values at */
+/*   previous calls (if these were smaller). therefore, if after a number */
+/*   of trials with different s-values and iopt=1, the user can finally */
+/*   accept a fit as satisfactory, it may be worthwhile for him to call */
+/*   sphere once more with the selected value for s but now with iopt=0. */
+/*   indeed, sphere may then return an approximation of the same quality */
+/*   of fit but with fewer knots and therefore better if data reduction */
+/*   is also an important objective for the user. */
+/*   the number of knots may also depend on the upper bounds ntest and */
+/*   npest. indeed, if at a certain stage in sphere the number of knots */
+/*   in one direction (say nt) has reached the value of its upper bound */
+/*   (ntest), then from that moment on all subsequent knots are added */
+/*   in the other (phi) direction. this may indicate that the value of */
+/*   ntest is too small. on the other hand, it gives the user the option */
+/*   of limiting the number of knots the routine locates in any direction */
+/*   for example, by setting ntest=8 (the lowest allowable value for */
+/*   ntest), the user can indicate that he wants an approximation which */
+/*   is a cubic polynomial in the variable teta. */
+
+/*  other subroutines required: */
+/*    fpback,fpbspl,fpsphe,fpdisc,fpgivs,fprank,fprati,fprota,fporde, */
+/*    fprpsp */
+
+/*  references: */
+/*   dierckx p. : algorithms for smoothing data on the sphere with tensor */
+/*                product splines, computing 32 (1984) 319-342. */
+/*   dierckx p. : algorithms for smoothing data on the sphere with tensor */
+/*                product splines, report tw62, dept. computer science, */
+/*                k.u.leuven, 1983. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*    p.dierckx */
+/*    dept. computer science, k.u. leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : july 1983 */
+/*  latest update : march 1989 */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpsphe */
+/*  .. */
+/*  set constants */
+    /* Parameter adjustments */
+    --w;
+    --r__;
+    --phi;
+    --teta;
+    --tt;
+    --c__;
+    --tp;
+    --wrk1;
+    --wrk2;
+    --iwrk;
+
+    /* Function Body */
+    one = (float)1.;
+/*  we set up the parameters tol and maxit. */
+    maxit = 20;
+    tol = (float).001;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid,control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*eps <= (float)0. || *eps >= (float)1.) {
+	goto L80;
+    }
+    if (*iopt < -1 || *iopt > 1) {
+	goto L80;
+    }
+    if (*m < 2) {
+	goto L80;
+    }
+    if (*ntest < 8 || *npest < 8) {
+	goto L80;
+    }
+    nt4 = *ntest - 4;
+    np4 = *npest - 4;
+    ncest = nt4 * np4;
+    ntt = *ntest - 7;
+    npp = *npest - 7;
+    ncc = npp * (ntt - 1) + 6;
+    nrint = ntt + npp;
+    nreg = ntt * npp;
+    ncof = npp * 3 + 6;
+    ib1 = npp << 2;
+    ib3 = ib1 + 3;
+    if (ncof > ib1) {
+	ib1 = ncof;
+    }
+    if (ncof > ib3) {
+	ib3 = ncof;
+    }
+/* Computing 2nd power */
+    i__1 = npp;
+    lwest = npp * 52 + 185 + ntt * 10 + ntt * 14 * npp + (*m + (ntt - 1) * (
+	    i__1 * i__1) << 3);
+    kwest = *m + nreg;
+    if (*lwrk1 < lwest || *kwrk < kwest) {
+	goto L80;
+    }
+    if (*iopt > 0) {
+	goto L60;
+    }
+    pi = atan(one) * 4;
+    pi2 = pi + pi;
+    i__1 = *m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (w[i__] <= (float)0.) {
+	    goto L80;
+	}
+	if (teta[i__] < (float)0. || teta[i__] > pi) {
+	    goto L80;
+	}
+	if (phi[i__] < (float)0. || phi[i__] > pi2) {
+	    goto L80;
+	}
+/* L20: */
+    }
+    if (*iopt == 0) {
+	goto L60;
+    }
+    ntt = *nt - 8;
+    if (ntt < 0 || *nt > *ntest) {
+	goto L80;
+    }
+    if (ntt == 0) {
+	goto L40;
+    }
+    tt[4] = (float)0.;
+    i__1 = ntt;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	j = i__ + 4;
+	if (tt[j] <= tt[j - 1] || tt[j] >= pi) {
+	    goto L80;
+	}
+/* L30: */
+    }
+L40:
+    npp = *np - 8;
+    if (npp < 1 || *np > *npest) {
+	goto L80;
+    }
+    tp[4] = (float)0.;
+    i__1 = npp;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	j = i__ + 4;
+	if (tp[j] <= tp[j - 1] || tp[j] >= pi2) {
+	    goto L80;
+	}
+/* L50: */
+    }
+    goto L70;
+L60:
+    if (*s < (float)0.) {
+	goto L80;
+    }
+L70:
+    *ier = 0;
+/*  we partition the working space and determine the spline approximation */
+    kn = 1;
+    ki = kn + *m;
+    lq = 2;
+    la = lq + ncc * ib3;
+    lf = la + ncc * ib1;
+    lff = lf + ncc;
+    lfp = lff + ncest;
+    lco = lfp + nrint;
+    lh = lco + nrint;
+    lbt = lh + ib3;
+    lbp = lbt + *ntest * 5;
+    lro = lbp + *npest * 5;
+    lcc = lro + *npest;
+    lcs = lcc + *npest;
+    lst = lcs + *npest;
+    lsp = lst + (*m << 2);
+    fpsphe_(iopt, m, &teta[1], &phi[1], &r__[1], &w[1], s, ntest, npest, eps, 
+	    &tol, &maxit, &ib1, &ib3, &ncest, &ncc, &nrint, &nreg, nt, &tt[1],
+	     np, &tp[1], &c__[1], fp, &wrk1[1], &wrk1[lfp], &wrk1[lco], &wrk1[
+	    lf], &wrk1[lff], &wrk1[lro], &wrk1[lcc], &wrk1[lcs], &wrk1[la], &
+	    wrk1[lq], &wrk1[lbt], &wrk1[lbp], &wrk1[lst], &wrk1[lsp], &wrk1[
+	    lh], &iwrk[ki], &iwrk[kn], &wrk2[1], lwrk2, ier);
+L80:
+    return 0;
+} /* sphere_ */
+
+/* Subroutine */ int splder_(t, n, c__, k, nu, x, y, m, wrk, ier)
+real *t;
+integer *n;
+real *c__;
+integer *k, *nu;
+real *x, *y;
+integer *m;
+real *wrk;
+integer *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static real h__[6];
+    static integer i__, j, l, k1, k2, l1, l2;
+    static real ak;
+    static integer kk;
+    static real tb;
+    static integer ll;
+    static real te;
+    static integer nn;
+    static real sp;
+    extern /* Subroutine */ int fpbspl_();
+    static integer nk1, nk2;
+    static real fac, arg;
+
+/*  subroutine splder evaluates in a number of points x(i),i=1,2,...,m */
+/*  the derivative of order nu of a spline s(x) of degree k,given in */
+/*  its b-spline representation. */
+
+/*  calling sequence: */
+/*     call splder(t,n,c,k,nu,x,y,m,wrk,ier) */
+
+/*  input parameters: */
+/*    t    : array,length n, which contains the position of the knots. */
+/*    n    : integer, giving the total number of knots of s(x). */
+/*    c    : array,length n, which contains the b-spline coefficients. */
+/*    k    : integer, giving the degree of s(x). */
+/*    nu   : integer, specifying the order of the derivative. 0<=nu<=k */
+/*    x    : array,length m, which contains the points where the deriv- */
+/*           ative of s(x) must be evaluated. */
+/*    m    : integer, giving the number of points where the derivative */
+/*           of s(x) must be evaluated */
+/*    wrk  : real array of dimension n. used as working space. */
+
+/*  output parameters: */
+/*    y    : array,length m, giving the value of the derivative of s(x) */
+/*           at the different points. */
+/*    ier  : error flag */
+/*      ier = 0 : normal return */
+/*      ier =10 : invalid input data (see restrictions) */
+
+/*  restrictions: */
+/*    0 <= nu <= k */
+/*    m >= 1 */
+/*    t(k+1) <= x(i) <= x(i+1) <= t(n-k) , i=1,2,...,m-1. */
+
+/*  other subroutines required: fpbspl */
+
+/*  references : */
+/*    de boor c : on calculating with b-splines, j. approximation theory */
+/*                6 (1972) 50-62. */
+/*    cox m.g.  : the numerical evaluation of b-splines, j. inst. maths */
+/*                applics 10 (1972) 134-149. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1987 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local arrays .. */
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid control is immediately repassed to the calling program. */
+    /* Parameter adjustments */
+    --wrk;
+    --c__;
+    --t;
+    --y;
+    --x;
+
+    /* Function Body */
+    *ier = 10;
+    if (*nu < 0 || *nu > *k) {
+	goto L200;
+    }
+    if ((i__1 = *m - 1) < 0) {
+	goto L200;
+    } else if (i__1 == 0) {
+	goto L30;
+    } else {
+	goto L10;
+    }
+L10:
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (x[i__] < x[i__ - 1]) {
+	    goto L200;
+	}
+/* L20: */
+    }
+L30:
+    *ier = 0;
+/*  fetch tb and te, the boundaries of the approximation interval. */
+    k1 = *k + 1;
+    nk1 = *n - k1;
+    tb = t[k1];
+    te = t[nk1 + 1];
+/*  the derivative of order nu of a spline of degree k is a spline of */
+/*  degree k-nu,the b-spline coefficients wrk(i) of which can be found */
+/*  using the recurrence scheme of de boor. */
+    l = 1;
+    kk = *k;
+    nn = *n;
+    i__1 = nk1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	wrk[i__] = c__[i__];
+/* L40: */
+    }
+    if (*nu == 0) {
+	goto L100;
+    }
+    nk2 = nk1;
+    i__1 = *nu;
+    for (j = 1; j <= i__1; ++j) {
+	ak = (real) kk;
+	--nk2;
+	l1 = l;
+	i__2 = nk2;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    ++l1;
+	    l2 = l1 + kk;
+	    fac = t[l2] - t[l1];
+	    if (fac <= (float)0.) {
+		goto L50;
+	    }
+	    wrk[i__] = ak * (wrk[i__ + 1] - wrk[i__]) / fac;
+L50:
+	    ;
+	}
+	++l;
+	--kk;
+/* L60: */
+    }
+    if (kk != 0) {
+	goto L100;
+    }
+/*  if nu=k the derivative is a piecewise constant function */
+    j = 1;
+    i__1 = *m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	arg = x[i__];
+L70:
+	if (arg < t[l + 1] || l == nk1) {
+	    goto L80;
+	}
+	++l;
+	++j;
+	goto L70;
+L80:
+	y[i__] = wrk[j];
+/* L90: */
+    }
+    goto L200;
+L100:
+    l = k1;
+    l1 = l + 1;
+    k2 = k1 - *nu;
+/*  main loop for the different points. */
+    i__1 = *m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+/*  fetch a new x-value arg. */
+	arg = x[i__];
+	if (arg < tb) {
+	    arg = tb;
+	}
+	if (arg > te) {
+	    arg = te;
+	}
+/*  search for knot interval t(l) <= arg < t(l+1) */
+L140:
+	if (arg < t[l1] || l == nk1) {
+	    goto L150;
+	}
+	l = l1;
+	l1 = l + 1;
+	goto L140;
+/*  evaluate the non-zero b-splines of degree k-nu at arg. */
+L150:
+	fpbspl_(&t[1], n, &kk, &arg, &l, h__);
+/*  find the value of the derivative at x=arg. */
+	sp = (float)0.;
+	ll = l - k1;
+	i__2 = k2;
+	for (j = 1; j <= i__2; ++j) {
+	    ++ll;
+	    sp += wrk[ll] * h__[j - 1];
+/* L160: */
+	}
+	y[i__] = sp;
+/* L180: */
+    }
+L200:
+    return 0;
+} /* splder_ */
+
+/* Subroutine */ int splev_(t, n, c__, k, x, y, m, ier)
+real *t;
+integer *n;
+real *c__;
+integer *k;
+real *x, *y;
+integer *m, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static real h__[6];
+    static integer i__, j, l, k1, l1;
+    static real tb;
+    static integer ll;
+    static real te, sp;
+    extern /* Subroutine */ int fpbspl_();
+    static integer nk1;
+    static real arg;
+
+/*  subroutine splev evaluates in a number of points x(i),i=1,2,...,m */
+/*  a spline s(x) of degree k, given in its b-spline representation. */
+
+/*  calling sequence: */
+/*     call splev(t,n,c,k,x,y,m,ier) */
+
+/*  input parameters: */
+/*    t    : array,length n, which contains the position of the knots. */
+/*    n    : integer, giving the total number of knots of s(x). */
+/*    c    : array,length n, which contains the b-spline coefficients. */
+/*    k    : integer, giving the degree of s(x). */
+/*    x    : array,length m, which contains the points where s(x) must */
+/*           be evaluated. */
+/*    m    : integer, giving the number of points where s(x) must be */
+/*           evaluated. */
+
+/*  output parameter: */
+/*    y    : array,length m, giving the value of s(x) at the different */
+/*           points. */
+/*    ier  : error flag */
+/*      ier = 0 : normal return */
+/*      ier =10 : invalid input data (see restrictions) */
+
+/*  restrictions: */
+/*    m >= 1 */
+/*    t(k+1) <= x(i) <= x(i+1) <= t(n-k) , i=1,2,...,m-1. */
+
+/*  other subroutines required: fpbspl. */
+
+/*  references : */
+/*    de boor c  : on calculating with b-splines, j. approximation theory */
+/*                 6 (1972) 50-62. */
+/*    cox m.g.   : the numerical evaluation of b-splines, j. inst. maths */
+/*                 applics 10 (1972) 134-149. */
+/*    dierckx p. : curve and surface fitting with splines, monographs on */
+/*                 numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1987 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local array.. */
+/*  .. */
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid control is immediately repassed to the calling program. */
+    /* Parameter adjustments */
+    --c__;
+    --t;
+    --y;
+    --x;
+
+    /* Function Body */
+    *ier = 10;
+    if ((i__1 = *m - 1) < 0) {
+	goto L100;
+    } else if (i__1 == 0) {
+	goto L30;
+    } else {
+	goto L10;
+    }
+L10:
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (x[i__] < x[i__ - 1]) {
+	    goto L100;
+	}
+/* L20: */
+    }
+L30:
+    *ier = 0;
+/*  fetch tb and te, the boundaries of the approximation interval. */
+    k1 = *k + 1;
+    nk1 = *n - k1;
+    tb = t[k1];
+    te = t[nk1 + 1];
+    l = k1;
+    l1 = l + 1;
+/*  main loop for the different points. */
+    i__1 = *m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+/*  fetch a new x-value arg. */
+	arg = x[i__];
+	if (arg < tb) {
+	    arg = tb;
+	}
+	if (arg > te) {
+	    arg = te;
+	}
+/*  search for knot interval t(l) <= arg < t(l+1) */
+L40:
+	if (arg < t[l1] || l == nk1) {
+	    goto L50;
+	}
+	l = l1;
+	l1 = l + 1;
+	goto L40;
+/*  evaluate the non-zero b-splines at arg. */
+L50:
+	fpbspl_(&t[1], n, k, &arg, &l, h__);
+/*  find the value of s(x) at x=arg. */
+	sp = (float)0.;
+	ll = l - k1;
+	i__2 = k1;
+	for (j = 1; j <= i__2; ++j) {
+	    ++ll;
+	    sp += c__[ll] * h__[j - 1];
+/* L60: */
+	}
+	y[i__] = sp;
+/* L80: */
+    }
+L100:
+    return 0;
+} /* splev_ */
+
+doublereal splint_(t, n, c__, k, a, b, wrk)
+real *t;
+integer *n;
+real *c__;
+integer *k;
+real *a, *b, *wrk;
+{
+    /* System generated locals */
+    integer i__1;
+    real ret_val;
+
+    /* Local variables */
+    static integer i__;
+    extern /* Subroutine */ int fpintb_();
+    static integer nk1;
+
+/*  function splint calculates the integral of a spline function s(x) */
+/*  of degree k, which is given in its normalized b-spline representation */
+
+/*  calling sequence: */
+/*     aint = splint(t,n,c,k,a,b,wrk) */
+
+/*  input parameters: */
+/*    t    : array,length n,which contains the position of the knots */
+/*           of s(x). */
+/*    n    : integer, giving the total number of knots of s(x). */
+/*    c    : array,length n, containing the b-spline coefficients. */
+/*    k    : integer, giving the degree of s(x). */
+/*    a,b  : real values, containing the end points of the integration */
+/*           interval. s(x) is considered to be identically zero outside */
+/*           the interval (t(k+1),t(n-k)). */
+
+/*  output parameter: */
+/*    aint : real, containing the integral of s(x) between a and b. */
+/*    wrk  : real array, length n.  used as working space */
+/*           on output, wrk will contain the integrals of the normalized */
+/*           b-splines defined on the set of knots. */
+
+/*  other subroutines required: fpintb. */
+
+/*  references : */
+/*    gaffney p.w. : the calculation of indefinite integrals of b-splines */
+/*                   j. inst. maths applics 17 (1976) 37-41. */
+/*    dierckx p. : curve and surface fitting with splines, monographs on */
+/*                 numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1987 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+    /* Parameter adjustments */
+    --wrk;
+    --c__;
+    --t;
+
+    /* Function Body */
+    nk1 = *n - *k - 1;
+/*  calculate the integrals wrk(i) of the normalized b-splines */
+/*  ni,k+1(x), i=1,2,...nk1. */
+    fpintb_(&t[1], n, &wrk[1], &nk1, a, b);
+/*  calculate the integral of s(x). */
+    ret_val = (float)0.;
+    i__1 = nk1;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	ret_val += c__[i__] * wrk[i__];
+/* L10: */
+    }
+    return ret_val;
+} /* splint_ */
+
+/* Subroutine */ int sproot_(t, n, c__, zero, mest, m, ier)
+real *t;
+integer *n;
+real *c__, *zero;
+integer *mest, *m, *ier;
+{
+    /* System generated locals */
+    integer i__1, i__2;
+
+    /* Local variables */
+    static integer i__, j, l;
+    static real y[3], three, a0, a1, a2, a3, b0, b1, c1, c2, c3, c4;
+    static integer j1;
+    static real c5, d4, d5, h1, h2;
+    static integer n4;
+    static real t1, t2, t3, t4, t5;
+    static logical z0, z1, z2, z3, z4;
+    static real ah, bh, zz;
+    extern /* Subroutine */ int fpcuro_();
+    static logical nz0, nz1, nz2, nz3, nz4;
+    static real two;
+
+/*  subroutine sproot finds the zeros of a cubic spline s(x),which is */
+/*  given in its normalized b-spline representation. */
+
+/*  calling sequence: */
+/*     call sproot(t,n,c,zero,mest,m,ier) */
+
+/*  input parameters: */
+/*    t    : real array,length n, containing the knots of s(x). */
+/*    n    : integer, containing the number of knots.  n>=8 */
+/*    c    : real array,length n, containing the b-spline coefficients. */
+/*    mest : integer, specifying the dimension of array zero. */
+
+/*  output parameters: */
+/*    zero : real array,lenth mest, containing the zeros of s(x). */
+/*    m    : integer,giving the number of zeros. */
+/*    ier  : error flag: */
+/*      ier = 0: normal return. */
+/*      ier = 1: the number of zeros exceeds mest. */
+/*      ier =10: invalid input data (see restrictions). */
+
+/*  other subroutines required: fpcuro */
+
+/*  restrictions: */
+/*    1) n>= 8. */
+/*    2) t(4) < t(5) < ... < t(n-4) < t(n-3). */
+/*       t(1) <= t(2) <= t(3) <= t(4) */
+/*       t(n-3) <= t(n-2) <= t(n-1) <= t(n) */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1987 */
+
+/* .. */
+/* ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..local array.. */
+/*  .. */
+/*  set some constants */
+    /* Parameter adjustments */
+    --c__;
+    --t;
+    --zero;
+
+    /* Function Body */
+    two = (float)2.;
+    three = (float)3.;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid, control is immediately repassed to the calling program. */
+    n4 = *n - 4;
+    *ier = 10;
+    if (*n < 8) {
+	goto L800;
+    }
+    j = *n;
+    for (i__ = 1; i__ <= 3; ++i__) {
+	if (t[i__] > t[i__ + 1]) {
+	    goto L800;
+	}
+	if (t[j] < t[j - 1]) {
+	    goto L800;
+	}
+	--j;
+/* L10: */
+    }
+    i__1 = n4;
+    for (i__ = 4; i__ <= i__1; ++i__) {
+	if (t[i__] >= t[i__ + 1]) {
+	    goto L800;
+	}
+/* L20: */
+    }
+/*  the problem considered reduces to finding the zeros of the cubic */
+/*  polynomials pl(x) which define the cubic spline in each knot */
+/*  interval t(l)<=x<=t(l+1). a zero of pl(x) is also a zero of s(x) on */
+/*  the condition that it belongs to the knot interval. */
+/*  the cubic polynomial pl(x) is determined by computing s(t(l)), */
+/*  s'(t(l)),s(t(l+1)) and s'(t(l+1)). in fact we only have to compute */
+/*  s(t(l+1)) and s'(t(l+1)); because of the continuity conditions of */
+/*  splines and their derivatives, the value of s(t(l)) and s'(t(l)) */
+/*  is already known from the foregoing knot interval. */
+    *ier = 0;
+/*  evaluate some constants for the first knot interval */
+    h1 = t[4] - t[3];
+    h2 = t[5] - t[4];
+    t1 = t[4] - t[2];
+    t2 = t[5] - t[3];
+    t3 = t[6] - t[4];
+    t4 = t[5] - t[2];
+    t5 = t[6] - t[3];
+/*  calculate a0 = s(t(4)) and ah = s'(t(4)). */
+    c1 = c__[1];
+    c2 = c__[2];
+    c3 = c__[3];
+    c4 = (c2 - c1) / t4;
+    c5 = (c3 - c2) / t5;
+    d4 = (h2 * c1 + t1 * c2) / t4;
+    d5 = (t3 * c2 + h1 * c3) / t5;
+    a0 = (h2 * d4 + h1 * d5) / t2;
+    ah = three * (h2 * c4 + h1 * c5) / t2;
+    z1 = TRUE_;
+    if (ah < (float)0.) {
+	z1 = FALSE_;
+    }
+    nz1 = ! z1;
+    *m = 0;
+/*  main loop for the different knot intervals. */
+    i__1 = n4;
+    for (l = 4; l <= i__1; ++l) {
+/*  evaluate some constants for the knot interval t(l) <= x <= t(l+1). */
+	h1 = h2;
+	h2 = t[l + 2] - t[l + 1];
+	t1 = t2;
+	t2 = t3;
+	t3 = t[l + 3] - t[l + 1];
+	t4 = t5;
+	t5 = t[l + 3] - t[l];
+/*  find a0 = s(t(l)), ah = s'(t(l)), b0 = s(t(l+1)) and bh = s'(t(l+1)). */
+	c1 = c2;
+	c2 = c3;
+	c3 = c__[l];
+	c4 = c5;
+	c5 = (c3 - c2) / t5;
+	d4 = (h2 * c1 + t1 * c2) / t4;
+	d5 = (h1 * c3 + t3 * c2) / t5;
+	b0 = (h2 * d4 + h1 * d5) / t2;
+	bh = three * (h2 * c4 + h1 * c5) / t2;
+/*  calculate the coefficients a0,a1,a2 and a3 of the cubic polynomial */
+/*  pl(x) = ql(y) = a0+a1*y+a2*y**2+a3*y**3 ; y = (x-t(l))/(t(l+1)-t(l)). */
+	a1 = ah * h1;
+	b1 = bh * h1;
+	a2 = three * (b0 - a0) - b1 - two * a1;
+	a3 = two * (a0 - b0) + b1 + a1;
+/*  test whether or not pl(x) could have a zero in the range */
+/*  t(l) <= x <= t(l+1). */
+	z3 = TRUE_;
+	if (b1 < (float)0.) {
+	    z3 = FALSE_;
+	}
+	nz3 = ! z3;
+	if (a0 * b0 <= (float)0.) {
+	    goto L100;
+	}
+	z0 = TRUE_;
+	if (a0 < (float)0.) {
+	    z0 = FALSE_;
+	}
+	nz0 = ! z0;
+	z2 = TRUE_;
+	if (a2 < (float)0.) {
+	    z2 = FALSE_;
+	}
+	nz2 = ! z2;
+	z4 = TRUE_;
+	if (a3 * (float)3. + a2 < (float)0.) {
+	    z4 = FALSE_;
+	}
+	nz4 = ! z4;
+	if (! (z0 && (nz1 && (z3 || z2 && nz4) || nz2 && z3 && z4) || nz0 && (
+		z1 && (nz3 || nz2 && z4) || z2 && nz3 && nz4))) {
+	    goto L200;
+	}
+/*  find the zeros of ql(y). */
+L100:
+	fpcuro_(&a3, &a2, &a1, &a0, y, &j);
+	if (j == 0) {
+	    goto L200;
+	}
+/*  find which zeros of pl(x) are zeros of s(x). */
+	i__2 = j;
+	for (i__ = 1; i__ <= i__2; ++i__) {
+	    if (y[i__ - 1] < (float)0. || y[i__ - 1] > (float)1.) {
+		goto L150;
+	    }
+/*  test whether the number of zeros of s(x) exceeds mest. */
+	    if (*m >= *mest) {
+		goto L700;
+	    }
+	    ++(*m);
+	    zero[*m] = t[l] + h1 * y[i__ - 1];
+L150:
+	    ;
+	}
+L200:
+	a0 = b0;
+	ah = bh;
+	z1 = z3;
+	nz1 = nz3;
+/* L300: */
+    }
+/*  the zeros of s(x) are arranged in increasing order. */
+    if (*m < 2) {
+	goto L800;
+    }
+    i__1 = *m;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	j = i__;
+L350:
+	j1 = j - 1;
+	if (j1 == 0) {
+	    goto L400;
+	}
+	if (zero[j] >= zero[j1]) {
+	    goto L400;
+	}
+	zz = zero[j];
+	zero[j] = zero[j1];
+	zero[j1] = zz;
+	j = j1;
+	goto L350;
+L400:
+	;
+    }
+    j = *m;
+    *m = 1;
+    i__1 = j;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (zero[i__] == zero[*m]) {
+	    goto L500;
+	}
+	++(*m);
+	zero[*m] = zero[i__];
+L500:
+	;
+    }
+    goto L800;
+L700:
+    *ier = 1;
+L800:
+    return 0;
+} /* sproot_ */
+
+/* Subroutine */ int surev_(idim, tu, nu, tv, nv, c__, u, mu, v, mv, f, mf, 
+	wrk, lwrk, iwrk, kwrk, ier)
+integer *idim;
+real *tu;
+integer *nu;
+real *tv;
+integer *nv;
+real *c__, *u;
+integer *mu;
+real *v;
+integer *mv;
+real *f;
+integer *mf;
+real *wrk;
+integer *lwrk, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer i__;
+    extern /* Subroutine */ int fpsuev_();
+    static integer muv;
+
+/*  subroutine surev evaluates on a grid (u(i),v(j)),i=1,...,mu; j=1,... */
+/*  ,mv a bicubic spline surface of dimension idim, given in the */
+/*  b-spline representation. */
+
+/*  calling sequence: */
+/*     call surev(idim,tu,nu,tv,nv,c,u,mu,v,mv,f,mf,wrk,lwrk, */
+/*    * iwrk,kwrk,ier) */
+
+/*  input parameters: */
+/*   idim  : integer, specifying the dimension of the spline surface. */
+/*   tu    : real array, length nu, which contains the position of the */
+/*           knots in the u-direction. */
+/*   nu    : integer, giving the total number of knots in the u-direction */
+/*   tv    : real array, length nv, which contains the position of the */
+/*           knots in the v-direction. */
+/*   nv    : integer, giving the total number of knots in the v-direction */
+/*   c     : real array, length (nu-4)*(nv-4)*idim, which contains the */
+/*           b-spline coefficients. */
+/*   u     : real array of dimension (mu). */
+/*           before entry u(i) must be set to the u co-ordinate of the */
+/*           i-th grid point along the u-axis. */
+/*           tu(4)<=u(i-1)<=u(i)<=tu(nu-3), i=2,...,mu. */
+/*   mu    : on entry mu must specify the number of grid points along */
+/*           the u-axis. mu >=1. */
+/*   v     : real array of dimension (mv). */
+/*           before entry v(j) must be set to the v co-ordinate of the */
+/*           j-th grid point along the v-axis. */
+/*           tv(4)<=v(j-1)<=v(j)<=tv(nv-3), j=2,...,mv. */
+/*   mv    : on entry mv must specify the number of grid points along */
+/*           the v-axis. mv >=1. */
+/*   mf    : on entry, mf must specify the dimension of the array f. */
+/*           mf >= mu*mv*idim */
+/*   wrk   : real array of dimension lwrk. used as workspace. */
+/*   lwrk  : integer, specifying the dimension of wrk. */
+/*           lwrk >= 4*(mu+mv) */
+/*   iwrk  : integer array of dimension kwrk. used as workspace. */
+/*   kwrk  : integer, specifying the dimension of iwrk. kwrk >= mu+mv. */
+
+/*  output parameters: */
+/*   f     : real array of dimension (mf). */
+/*           on succesful exit f(mu*mv*(l-1)+mv*(i-1)+j) contains the */
+/*           l-th co-ordinate of the bicubic spline surface at the */
+/*           point (u(i),v(j)),l=1,...,idim,i=1,...,mu;j=1,...,mv. */
+/*   ier   : integer error flag */
+/*    ier=0 : normal return */
+/*    ier=10: invalid input data (see restrictions) */
+
+/*  restrictions: */
+/*   mu >=1, mv >=1, lwrk>=4*(mu+mv), kwrk>=mu+mv , mf>=mu*mv*idim */
+/*   tu(4) <= u(i-1) <= u(i) <= tu(nu-3), i=2,...,mu */
+/*   tv(4) <= v(j-1) <= v(j) <= tv(nv-3), j=2,...,mv */
+
+/*  other subroutines required: */
+/*    fpsuev,fpbspl */
+
+/*  references : */
+/*    de boor c : on calculating with b-splines, j. approximation theory */
+/*                6 (1972) 50-62. */
+/*    cox m.g.  : the numerical evaluation of b-splines, j. inst. maths */
+/*                applics 10 (1972) 134-149. */
+/*    dierckx p. : curve and surface fitting with splines, monographs on */
+/*                 numerical analysis, oxford university press, 1993. */
+
+/*  author : */
+/*    p.dierckx */
+/*    dept. computer science, k.u.leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  latest update : march 1987 */
+
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  .. */
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid control is immediately repassed to the calling program. */
+    /* Parameter adjustments */
+    --tu;
+    --c__;
+    --tv;
+    --u;
+    --v;
+    --f;
+    --wrk;
+    --iwrk;
+
+    /* Function Body */
+    *ier = 10;
+    if (*mf < *mu * *mv * *idim) {
+	goto L100;
+    }
+    muv = *mu + *mv;
+    if (*lwrk < muv << 2) {
+	goto L100;
+    }
+    if (*kwrk < muv) {
+	goto L100;
+    }
+    if ((i__1 = *mu - 1) < 0) {
+	goto L100;
+    } else if (i__1 == 0) {
+	goto L30;
+    } else {
+	goto L10;
+    }
+L10:
+    i__1 = *mu;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (u[i__] < u[i__ - 1]) {
+	    goto L100;
+	}
+/* L20: */
+    }
+L30:
+    if ((i__1 = *mv - 1) < 0) {
+	goto L100;
+    } else if (i__1 == 0) {
+	goto L60;
+    } else {
+	goto L40;
+    }
+L40:
+    i__1 = *mv;
+    for (i__ = 2; i__ <= i__1; ++i__) {
+	if (v[i__] < v[i__ - 1]) {
+	    goto L100;
+	}
+/* L50: */
+    }
+L60:
+    *ier = 0;
+    fpsuev_(idim, &tu[1], nu, &tv[1], nv, &c__[1], &u[1], mu, &v[1], mv, &f[1]
+	    , &wrk[1], &wrk[(*mu << 2) + 1], &iwrk[1], &iwrk[*mu + 1]);
+L100:
+    return 0;
+} /* surev_ */
+
+/* Subroutine */ int surfit_(iopt, m, x, y, z__, w, xb, xe, yb, ye, kx, ky, s,
+	 nxest, nyest, nmax, eps, nx, tx, ny, ty, c__, fp, wrk1, lwrk1, wrk2, 
+	lwrk2, iwrk, kwrk, ier)
+integer *iopt, *m;
+real *x, *y, *z__, *w, *xb, *xe, *yb, *ye;
+integer *kx, *ky;
+real *s;
+integer *nxest, *nyest, *nmax;
+real *eps;
+integer *nx;
+real *tx;
+integer *ny;
+real *ty, *c__, *fp, *wrk1;
+integer *lwrk1;
+real *wrk2;
+integer *lwrk2, *iwrk, *kwrk, *ier;
+{
+    /* System generated locals */
+    integer i__1;
+
+    /* Local variables */
+    static integer nreg, kmax, nest, i__, ncest, maxit, nminx, nminy, nrint, 
+	    kwest, lwest, la, lf, ki, lh, kn, lq, ib1, jb1, ib3;
+    extern /* Subroutine */ int fpsurf_();
+    static integer km1, km2, kx1, ky1, lff, lco, nek, lfp, lbx, lby;
+    static real tol;
+    static integer nxk, nyk, nmx, nmy, lsx, lsy;
+
+/* given the set of data points (x(i),y(i),z(i)) and the set of positive */
+/* numbers w(i),i=1,...,m, subroutine surfit determines a smooth bivar- */
+/* iate spline approximation s(x,y) of degrees kx and ky on the rect- */
+/* angle xb <= x <= xe, yb <= y <= ye. */
+/* if iopt = -1 surfit calculates the weighted least-squares spline */
+/* according to a given set of knots. */
+/* if iopt >= 0 the total numbers nx and ny of these knots and their */
+/* position tx(j),j=1,...,nx and ty(j),j=1,...,ny are chosen automatic- */
+/* ally by the routine. the smoothness of s(x,y) is then achieved by */
+/* minimalizing the discontinuity jumps in the derivatives of s(x,y) */
+/* across the boundaries of the subpanels (tx(i),tx(i+1))*(ty(j),ty(j+1). */
+/* the amounth of smoothness is determined by the condition that f(p) = */
+/* sum ((w(i)*(z(i)-s(x(i),y(i))))**2) be <= s, with s a given non-neg- */
+/* ative constant, called the smoothing factor. */
+/* the fit is given in the b-spline representation (b-spline coefficients */
+/* c((ny-ky-1)*(i-1)+j),i=1,...,nx-kx-1;j=1,...,ny-ky-1) and can be eval- */
+/* uated by means of subroutine bispev. */
+
+/* calling sequence: */
+/*     call surfit(iopt,m,x,y,z,w,xb,xe,yb,ye,kx,ky,s,nxest,nyest, */
+/*    *  nmax,eps,nx,tx,ny,ty,c,fp,wrk1,lwrk1,wrk2,lwrk2,iwrk,kwrk,ier) */
+
+/* parameters: */
+/*  iopt  : integer flag. on entry iopt must specify whether a weighted */
+/*          least-squares spline (iopt=-1) or a smoothing spline (iopt=0 */
+/*          or 1) must be determined. */
+/*          if iopt=0 the routine will start with an initial set of knots */
+/*          tx(i)=xb,tx(i+kx+1)=xe,i=1,...,kx+1;ty(i)=yb,ty(i+ky+1)=ye,i= */
+/*          1,...,ky+1. if iopt=1 the routine will continue with the set */
+/*          of knots found at the last call of the routine. */
+/*          attention: a call with iopt=1 must always be immediately pre- */
+/*                     ceded by another call with iopt=1 or iopt=0. */
+/*          unchanged on exit. */
+/*  m     : integer. on entry m must specify the number of data points. */
+/*          m >= (kx+1)*(ky+1). unchanged on exit. */
+/*  x     : real array of dimension at least (m). */
+/*  y     : real array of dimension at least (m). */
+/*  z     : real array of dimension at least (m). */
+/*          before entry, x(i),y(i),z(i) must be set to the co-ordinates */
+/*          of the i-th data point, for i=1,...,m. the order of the data */
+/*          points is immaterial. unchanged on exit. */
+/*  w     : real array of dimension at least (m). before entry, w(i) must */
+/*          be set to the i-th value in the set of weights. the w(i) must */
+/*          be strictly positive. unchanged on exit. */
+/*  xb,xe : real values. on entry xb,xe,yb and ye must specify the bound- */
+/*  yb,ye   aries of the rectangular approximation domain. */
+/*          xb<=x(i)<=xe,yb<=y(i)<=ye,i=1,...,m. unchanged on exit. */
+/*  kx,ky : integer values. on entry kx and ky must specify the degrees */
+/*          of the spline. 1<=kx,ky<=5. it is recommended to use bicubic */
+/*          (kx=ky=3) splines. unchanged on exit. */
+/*  s     : real. on entry (in case iopt>=0) s must specify the smoothing */
+/*          factor. s >=0. unchanged on exit. */
+/*          for advice on the choice of s see further comments */
+/*  nxest : integer. unchanged on exit. */
+/*  nyest : integer. unchanged on exit. */
+/*          on entry, nxest and nyest must specify an upper bound for the */
+/*          number of knots required in the x- and y-directions respect. */
+/*          these numbers will also determine the storage space needed by */
+/*          the routine. nxest >= 2*(kx+1), nyest >= 2*(ky+1). */
+/*          in most practical situation nxest = kx+1+sqrt(m/2), nyest = */
+/*          ky+1+sqrt(m/2) will be sufficient. see also further comments. */
+/*  nmax  : integer. on entry nmax must specify the actual dimension of */
+/*          the arrays tx and ty. nmax >= nxest, nmax >=nyest. */
+/*          unchanged on exit. */
+/*  eps   : real. */
+/*          on entry, eps must specify a threshold for determining the */
+/*          effective rank of an over-determined linear system of equat- */
+/*          ions. 0 < eps < 1.  if the number of decimal digits in the */
+/*          computer representation of a real number is q, then 10**(-q) */
+/*          is a suitable value for eps in most practical applications. */
+/*          unchanged on exit. */
+/*  nx    : integer. */
+/*          unless ier=10 (in case iopt >=0), nx will contain the total */
+/*          number of knots with respect to the x-variable, of the spline */
+/*          approximation returned. if the computation mode iopt=1 is */
+/*          used, the value of nx should be left unchanged between sub- */
+/*          sequent calls. */
+/*          in case iopt=-1, the value of nx should be specified on entry */
+/*  tx    : real array of dimension nmax. */
+/*          on succesful exit, this array will contain the knots of the */
+/*          spline with respect to the x-variable, i.e. the position of */
+/*          the interior knots tx(kx+2),...,tx(nx-kx-1) as well as the */
+/*          position of the additional knots tx(1)=...=tx(kx+1)=xb and */
+/*          tx(nx-kx)=...=tx(nx)=xe needed for the b-spline representat. */
+/*          if the computation mode iopt=1 is used, the values of tx(1), */
+/*          ...,tx(nx) should be left unchanged between subsequent calls. */
+/*          if the computation mode iopt=-1 is used, the values tx(kx+2), */
+/*          ...tx(nx-kx-1) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  ny    : integer. */
+/*          unless ier=10 (in case iopt >=0), ny will contain the total */
+/*          number of knots with respect to the y-variable, of the spline */
+/*          approximation returned. if the computation mode iopt=1 is */
+/*          used, the value of ny should be left unchanged between sub- */
+/*          sequent calls. */
+/*          in case iopt=-1, the value of ny should be specified on entry */
+/*  ty    : real array of dimension nmax. */
+/*          on succesful exit, this array will contain the knots of the */
+/*          spline with respect to the y-variable, i.e. the position of */
+/*          the interior knots ty(ky+2),...,ty(ny-ky-1) as well as the */
+/*          position of the additional knots ty(1)=...=ty(ky+1)=yb and */
+/*          ty(ny-ky)=...=ty(ny)=ye needed for the b-spline representat. */
+/*          if the computation mode iopt=1 is used, the values of ty(1), */
+/*          ...,ty(ny) should be left unchanged between subsequent calls. */
+/*          if the computation mode iopt=-1 is used, the values ty(ky+2), */
+/*          ...ty(ny-ky-1) must be supplied by the user, before entry. */
+/*          see also the restrictions (ier=10). */
+/*  c     : real array of dimension at least (nxest-kx-1)*(nyest-ky-1). */
+/*          on succesful exit, c contains the coefficients of the spline */
+/*          approximation s(x,y) */
+/*  fp    : real. unless ier=10, fp contains the weighted sum of */
+/*          squared residuals of the spline approximation returned. */
+/*  wrk1  : real array of dimension (lwrk1). used as workspace. */
+/*          if the computation mode iopt=1 is used the value of wrk1(1) */
+/*          should be left unchanged between subsequent calls. */
+/*          on exit wrk1(2),wrk1(3),...,wrk1(1+(nx-kx-1)*(ny-ky-1)) will */
+/*          contain the values d(i)/max(d(i)),i=1,...,(nx-kx-1)*(ny-ky-1) */
+/*          with d(i) the i-th diagonal element of the reduced triangular */
+/*          matrix for calculating the b-spline coefficients. it includes */
+/*          those elements whose square is less than eps,which are treat- */
+/*          ed as 0 in the case of presumed rank deficiency (ier<-2). */
+/*  lwrk1 : integer. on entry lwrk1 must specify the actual dimension of */
+/*          the array wrk1 as declared in the calling (sub)program. */
+/*          lwrk1 must not be too small. let */
+/*            u = nxest-kx-1, v = nyest-ky-1, km = max(kx,ky)+1, */
+/*            ne = max(nxest,nyest), bx = kx*v+ky+1, by = ky*u+kx+1, */
+/*            if(bx.le.by) b1 = bx, b2 = b1+v-ky */
+/*            if(bx.gt.by) b1 = by, b2 = b1+u-kx  then */
+/*          lwrk1 >= u*v*(2+b1+b2)+2*(u+v+km*(m+ne)+ne-kx-ky)+b2+1 */
+/*  wrk2  : real array of dimension (lwrk2). used as workspace, but */
+/*          only in the case a rank deficient system is encountered. */
+/*  lwrk2 : integer. on entry lwrk2 must specify the actual dimension of */
+/*          the array wrk2 as declared in the calling (sub)program. */
+/*          lwrk2 > 0 . a save upper boundfor lwrk2 = u*v*(b2+1)+b2 */
+/*          where u,v and b2 are as above. if there are enough data */
+/*          points, scattered uniformly over the approximation domain */
+/*          and if the smoothing factor s is not too small, there is a */
+/*          good chance that this extra workspace is not needed. a lot */
+/*          of memory might therefore be saved by setting lwrk2=1. */
+/*          (see also ier > 10) */
+/*  iwrk  : integer array of dimension (kwrk). used as workspace. */
+/*  kwrk  : integer. on entry kwrk must specify the actual dimension of */
+/*          the array iwrk as declared in the calling (sub)program. */
+/*          kwrk >= m+(nxest-2*kx-1)*(nyest-2*ky-1). */
+/*  ier   : integer. unless the routine detects an error, ier contains a */
+/*          non-positive value on exit, i.e. */
+/*   ier=0  : normal return. the spline returned has a residual sum of */
+/*            squares fp such that abs(fp-s)/s <= tol with tol a relat- */
+/*            ive tolerance set to 0.001 by the program. */
+/*   ier=-1 : normal return. the spline returned is an interpolating */
+/*            spline (fp=0). */
+/*   ier=-2 : normal return. the spline returned is the weighted least- */
+/*            squares polynomial of degrees kx and ky. in this extreme */
+/*            case fp gives the upper bound for the smoothing factor s. */
+/*   ier<-2 : warning. the coefficients of the spline returned have been */
+/*            computed as the minimal norm least-squares solution of a */
+/*            (numerically) rank deficient system. (-ier) gives the rank. */
+/*            especially if the rank deficiency which can be computed as */
+/*            (nx-kx-1)*(ny-ky-1)+ier, is large the results may be inac- */
+/*            curate. they could also seriously depend on the value of */
+/*            eps. */
+/*   ier=1  : error. the required storage space exceeds the available */
+/*            storage space, as specified by the parameters nxest and */
+/*            nyest. */
+/*            probably causes : nxest or nyest too small. if these param- */
+/*            eters are already large, it may also indicate that s is */
+/*            too small */
+/*            the approximation returned is the weighted least-squares */
+/*            spline according to the current set of knots. */
+/*            the parameter fp gives the corresponding weighted sum of */
+/*            squared residuals (fp>s). */
+/*   ier=2  : error. a theoretically impossible result was found during */
+/*            the iteration proces for finding a smoothing spline with */
+/*            fp = s. probably causes : s too small or badly chosen eps. */
+/*            there is an approximation returned but the corresponding */
+/*            weighted sum of squared residuals does not satisfy the */
+/*            condition abs(fp-s)/s < tol. */
+/*   ier=3  : error. the maximal number of iterations maxit (set to 20 */
+/*            by the program) allowed for finding a smoothing spline */
+/*            with fp=s has been reached. probably causes : s too small */
+/*            there is an approximation returned but the corresponding */
+/*            weighted sum of squared residuals does not satisfy the */
+/*            condition abs(fp-s)/s < tol. */
+/*   ier=4  : error. no more knots can be added because the number of */
+/*            b-spline coefficients (nx-kx-1)*(ny-ky-1) already exceeds */
+/*            the number of data points m. */
+/*            probably causes : either s or m too small. */
+/*            the approximation returned is the weighted least-squares */
+/*            spline according to the current set of knots. */
+/*            the parameter fp gives the corresponding weighted sum of */
+/*            squared residuals (fp>s). */
+/*   ier=5  : error. no more knots can be added because the additional */
+/*            knot would (quasi) coincide with an old one. */
+/*            probably causes : s too small or too large a weight to an */
+/*            inaccurate data point. */
+/*            the approximation returned is the weighted least-squares */
+/*            spline according to the current set of knots. */
+/*            the parameter fp gives the corresponding weighted sum of */
+/*            squared residuals (fp>s). */
+/*   ier=10 : error. on entry, the input data are controlled on validity */
+/*            the following restrictions must be satisfied. */
+/*            -1<=iopt<=1, 1<=kx,ky<=5, m>=(kx+1)*(ky+1), nxest>=2*kx+2, */
+/*            nyest>=2*ky+2, 0<eps<1, nmax>=nxest, nmax>=nyest, */
+/*            xb<=x(i)<=xe, yb<=y(i)<=ye, w(i)>0, i=1,...,m */
+/*            lwrk1 >= u*v*(2+b1+b2)+2*(u+v+km*(m+ne)+ne-kx-ky)+b2+1 */
+/*            kwrk >= m+(nxest-2*kx-1)*(nyest-2*ky-1) */
+/*            if iopt=-1: 2*kx+2<=nx<=nxest */
+/*                        xb<tx(kx+2)<tx(kx+3)<...<tx(nx-kx-1)<xe */
+/*                        2*ky+2<=ny<=nyest */
+/*                        yb<ty(ky+2)<ty(ky+3)<...<ty(ny-ky-1)<ye */
+/*            if iopt>=0: s>=0 */
+/*            if one of these conditions is found to be violated,control */
+/*            is immediately repassed to the calling program. in that */
+/*            case there is no approximation returned. */
+/*   ier>10 : error. lwrk2 is too small, i.e. there is not enough work- */
+/*            space for computing the minimal least-squares solution of */
+/*            a rank deficient system of linear equations. ier gives the */
+/*            requested value for lwrk2. there is no approximation re- */
+/*            turned but, having saved the information contained in nx, */
+/*            ny,tx,ty,wrk1, and having adjusted the value of lwrk2 and */
+/*            the dimension of the array wrk2 accordingly, the user can */
+/*            continue at the point the program was left, by calling */
+/*            surfit with iopt=1. */
+
+/* further comments: */
+/*  by means of the parameter s, the user can control the tradeoff */
+/*   between closeness of fit and smoothness of fit of the approximation. */
+/*   if s is too large, the spline will be too smooth and signal will be */
+/*   lost ; if s is too small the spline will pick up too much noise. in */
+/*   the extreme cases the program will return an interpolating spline if */
+/*   s=0 and the weighted least-squares polynomial (degrees kx,ky)if s is */
+/*   very large. between these extremes, a properly chosen s will result */
+/*   in a good compromise between closeness of fit and smoothness of fit. */
+/*   to decide whether an approximation, corresponding to a certain s is */
+/*   satisfactory the user is highly recommended to inspect the fits */
+/*   graphically. */
+/*   recommended values for s depend on the weights w(i). if these are */
+/*   taken as 1/d(i) with d(i) an estimate of the standard deviation of */
+/*   z(i), a good s-value should be found in the range (m-sqrt(2*m),m+ */
+/*   sqrt(2*m)). if nothing is known about the statistical error in z(i) */
+/*   each w(i) can be set equal to one and s determined by trial and */
+/*   error, taking account of the comments above. the best is then to */
+/*   start with a very large value of s ( to determine the least-squares */
+/*   polynomial and the corresponding upper bound fp0 for s) and then to */
+/*   progressively decrease the value of s ( say by a factor 10 in the */
+/*   beginning, i.e. s=fp0/10, fp0/100,...and more carefully as the */
+/*   approximation shows more detail) to obtain closer fits. */
+/*   to choose s very small is strongly discouraged. this considerably */
+/*   increases computation time and memory requirements. it may also */
+/*   cause rank-deficiency (ier<-2) and endager numerical stability. */
+/*   to economize the search for a good s-value the program provides with */
+/*   different modes of computation. at the first call of the routine, or */
+/*   whenever he wants to restart with the initial set of knots the user */
+/*   must set iopt=0. */
+/*   if iopt=1 the program will continue with the set of knots found at */
+/*   the last call of the routine. this will save a lot of computation */
+/*   time if surfit is called repeatedly for different values of s. */
+/*   the number of knots of the spline returned and their location will */
+/*   depend on the value of s and on the complexity of the shape of the */
+/*   function underlying the data. if the computation mode iopt=1 */
+/*   is used, the knots returned may also depend on the s-values at */
+/*   previous calls (if these were smaller). therefore, if after a number */
+/*   of trials with different s-values and iopt=1, the user can finally */
+/*   accept a fit as satisfactory, it may be worthwhile for him to call */
+/*   surfit once more with the selected value for s but now with iopt=0. */
+/*   indeed, surfit may then return an approximation of the same quality */
+/*   of fit but with fewer knots and therefore better if data reduction */
+/*   is also an important objective for the user. */
+/*   the number of knots may also depend on the upper bounds nxest and */
+/*   nyest. indeed, if at a certain stage in surfit the number of knots */
+/*   in one direction (say nx) has reached the value of its upper bound */
+/*   (nxest), then from that moment on all subsequent knots are added */
+/*   in the other (y) direction. this may indicate that the value of */
+/*   nxest is too small. on the other hand, it gives the user the option */
+/*   of limiting the number of knots the routine locates in any direction */
+/*   for example, by setting nxest=2*kx+2 (the lowest allowable value for */
+/*   nxest), the user can indicate that he wants an approximation which */
+/*   is a simple polynomial of degree kx in the variable x. */
+
+/*  other subroutines required: */
+/*    fpback,fpbspl,fpsurf,fpdisc,fpgivs,fprank,fprati,fprota,fporde */
+
+/*  references: */
+/*   dierckx p. : an algorithm for surface fitting with spline functions */
+/*                ima j. numer. anal. 1 (1981) 267-283. */
+/*   dierckx p. : an algorithm for surface fitting with spline functions */
+/*                report tw50, dept. computer science,k.u.leuven, 1980. */
+/*   dierckx p. : curve and surface fitting with splines, monographs on */
+/*                numerical analysis, oxford university press, 1993. */
+
+/*  author: */
+/*    p.dierckx */
+/*    dept. computer science, k.u. leuven */
+/*    celestijnenlaan 200a, b-3001 heverlee, belgium. */
+/*    e-mail : Paul.Dierckx at cs.kuleuven.ac.be */
+
+/*  creation date : may 1979 */
+/*  latest update : march 1987 */
+
+/*  .. */
+/*  ..scalar arguments.. */
+/*  ..array arguments.. */
+/*  ..local scalars.. */
+/*  ..function references.. */
+/*  ..subroutine references.. */
+/*    fpsurf */
+/*  .. */
+/*  we set up the parameters tol and maxit. */
+    /* Parameter adjustments */
+    --w;
+    --z__;
+    --y;
+    --x;
+    --c__;
+    --ty;
+    --tx;
+    --wrk1;
+    --wrk2;
+    --iwrk;
+
+    /* Function Body */
+    maxit = 20;
+    tol = (float).001;
+/*  before starting computations a data check is made. if the input data */
+/*  are invalid,control is immediately repassed to the calling program. */
+    *ier = 10;
+    if (*eps <= (float)0. || *eps >= (float)1.) {
+	goto L70;
+    }
+    if (*kx <= 0 || *kx > 5) {
+	goto L70;
+    }
+    kx1 = *kx + 1;
+    if (*ky <= 0 || *ky > 5) {
+	goto L70;
+    }
+    ky1 = *ky + 1;
+    kmax = max(*kx,*ky);
+    km1 = kmax + 1;
+    km2 = km1 + 1;
+    if (*iopt < -1 || *iopt > 1) {
+	goto L70;
+    }
+    if (*m < kx1 * ky1) {
+	goto L70;
+    }
+    nminx = kx1 << 1;
+    if (*nxest < nminx || *nxest > *nmax) {
+	goto L70;
+    }
+    nminy = ky1 << 1;
+    if (*nyest < nminy || *nyest > *nmax) {
+	goto L70;
+    }
+    nest = max(*nxest,*nyest);
+    nxk = *nxest - kx1;
+    nyk = *nyest - ky1;
+    ncest = nxk * nyk;
+    nmx = *nxest - nminx + 1;
+    nmy = *nyest - nminy + 1;
+    nrint = nmx + nmy;
+    nreg = nmx * nmy;
+    ib1 = *kx * nyk + ky1;
+    jb1 = *ky * nxk + kx1;
+    ib3 = kx1 * nyk + 1;
+    if (ib1 <= jb1) {
+	goto L10;
+    }
+    ib1 = jb1;
+    ib3 = ky1 * nxk + 1;
+L10:
+    lwest = ncest * (ib1 + 2 + ib3) + (nrint + nest * km2 + *m * km1 << 1) + 
+	    ib3;
+    kwest = *m + nreg;
+    if (*lwrk1 < lwest || *kwrk < kwest) {
+	goto L70;
+    }
+    if (*xb >= *xe || *yb >= *ye) {
+	goto L70;
+    }
+    i__1 = *m;
+    for (i__ = 1; i__ <= i__1; ++i__) {
+	if (w[i__] <= (float)0.) {
+	    goto L70;
+	}
+	if (x[i__] < *xb || x[i__] > *xe) {
+	    goto L70;
+	}
+	if (y[i__] < *yb || y[i__] > *ye) {
+	    goto L70;
+	}
+/* L20: */
+    }
+    if (*iopt >= 0) {
+	goto L50;
+    }
+    if (*nx < nminx || *nx > *nxest) {
+	goto L70;
+    }
+    nxk = *nx - kx1;
+    tx[kx1] = *xb;
+    tx[nxk + 1] = *xe;
+    i__1 = nxk;
+    for (i__ = kx1; i__ <= i__1; ++i__) {
+	if (tx[i__ + 1] <= tx[i__]) {
+	    goto L70;
+	}
+/* L30: */
+    }
+    if (*ny < nminy || *ny > *nyest) {
+	goto L70;
+    }
+    nyk = *ny - ky1;
+    ty[ky1] = *yb;
+    ty[nyk + 1] = *ye;
+    i__1 = nyk;
+    for (i__ = ky1; i__ <= i__1; ++i__) {
+	if (ty[i__ + 1] <= ty[i__]) {
+	    goto L70;
+	}
+/* L40: */
+    }
+    goto L60;
+L50:
+    if (*s < (float)0.) {
+	goto L70;
+    }
+L60:
+    *ier = 0;
+/*  we partition the working space and determine the spline approximation */
+    kn = 1;
+    ki = kn + *m;
+    lq = 2;
+    la = lq + ncest * ib3;
+    lf = la + ncest * ib1;
+    lff = lf + ncest;
+    lfp = lff + ncest;
+    lco = lfp + nrint;
+    lh = lco + nrint;
+    lbx = lh + ib3;
+    nek = nest * km2;
+    lby = lbx + nek;
+    lsx = lby + nek;
+    lsy = lsx + *m * km1;
+    fpsurf_(iopt, m, &x[1], &y[1], &z__[1], &w[1], xb, xe, yb, ye, kx, ky, s, 
+	    nxest, nyest, eps, &tol, &maxit, &nest, &km1, &km2, &ib1, &ib3, &
+	    ncest, &nrint, &nreg, nx, &tx[1], ny, &ty[1], &c__[1], fp, &wrk1[
+	    1], &wrk1[lfp], &wrk1[lco], &wrk1[lf], &wrk1[lff], &wrk1[la], &
+	    wrk1[lq], &wrk1[lbx], &wrk1[lby], &wrk1[lsx], &wrk1[lsy], &wrk1[
+	    lh], &iwrk[ki], &iwrk[kn], &wrk2[1], lwrk2, ier);
+L70:
+    return 0;
+} /* surfit_ */
+
+
diff --git a/bioimagesuite30_src/numerics/fitpack.h b/bioimagesuite30_src/numerics/fitpack.h
new file mode 100644
index 0000000..88618dc
--- /dev/null
+++ b/bioimagesuite30_src/numerics/fitpack.h
@@ -0,0 +1,213 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------------------------------------
+//
+//  This is the .h file for fitpack as produced by f2c
+//
+//---------------------------------------------------------------------------------------------------------
+
+#ifndef FITPACK_INCLUDE
+#define FITPACK_INCLUDE
+#include "bio_f2c.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int bispev_(real *tx, integer *nx, real *ty, integer *ny, real *c__, integer *kx, integer *ky, real *x, integer *mx, real *y, integer *my, real *z__, real *wrk, integer *lwrk, integer *iwrk, integer *kwrk, integer *ier);
+
+extern int clocur_(integer *iopt, integer *ipar, integer *idim, integer *m, real *u, integer *mx, real *x, real *w, integer *k, real *s, integer *nest, integer *n, real *t, integer *nc, real *c__, real *fp, real *wrk, integer *lwrk, integer *iwrk, integer *ier);
+
+extern int cocosp_(integer *m, real *x, real *y, real *w, integer *n, real *t, real *e, integer *maxtr, integer *maxbin, real *c__, real *sq, real *sx, logical *bind, real *wrk, integer *lwrk, integer *iwrk, integer *kwrk, integer *ier);
+
+extern int concon_(integer *iopt, integer *m, real *x, real *y, real *w, real *v, real *s, integer *nest, integer *maxtr, integer *maxbin, integer *n, real *t, real *c__, real *sq, real *sx, logical *bind, real *wrk, integer *lwrk, integer *iwrk, integer *kwrk, integer *ier);
+
+extern int concur_(integer *iopt, integer *idim, integer *m, real *u, integer *mx, real *x, real *xx, real *w, integer *ib, real *db, integer *nb, integer *ie, real *de, integer *ne, integer *k, real *s, integer *nest, integer *n, real *t, integer *nc, real *c__, integer *np, real *cp, real *fp, real *wrk, integer *lwrk, integer *iwrk, integer *ier);
+
+extern int cualde_(integer *idim, real *t, integer *n, real *c__, integer *nc, integer *k1, real *u, real *d__, integer *nd, integer *ier);
+
+extern int curev_(integer *idim, real *t, integer *n, real *c__, integer *nc, integer *k, real *u, integer *m, real *x, integer *mx, integer *ier);
+
+extern int curfit_(integer *iopt, integer *m, real *x, real *y, real *w, real *xb, real *xe, integer *k, real *s, integer *nest, integer *n, real *t, real *c__, real *fp, real *wrk, integer *lwrk, integer *iwrk, integer *ier);
+
+extern E_f dblint_(real *tx, integer *nx, real *ty, integer *ny, real *c__, integer *kx, integer *ky, real *xb, real *xe, real *yb, real *ye, real *wrk);
+
+extern E_f evapol_(real *tu, integer *nu, real *tv, integer *nv, real *c__, E_fp rad, real *x, real *y);
+
+extern int fourco_(real *t, integer *n, real *c__, real *alfa, integer *m, real *ress, real *resc, real *wrk1, real *wrk2, integer *ier);
+
+extern int fpader_(real *t, integer *n, real *c__, integer *k1, real *x, integer *l, real *d__);
+
+extern int fpadno_(integer *maxtr, integer *up, integer *left, integer *right, integer *info, integer *count, integer *merk, integer *jbind, integer *n1, integer *ier);
+
+extern int fpadpo_(integer *idim, real *t, integer *n, real *c__, integer *nc, integer *k, real *cp, integer *np, real *cc, real *t1, real *t2);
+
+extern int fpback_(real *a, real *z__, integer *n, integer *k, real *c__, integer *nest);
+
+extern int fpbacp_(real *a, real *b, real *z__, integer *n, integer *k, real *c__, integer *k1, integer *nest);
+
+extern int fpbfou_(real *t, integer *n, real *par, real *ress, real *resc);
+
+extern int fpbisp_(real *tx, integer *nx, real *ty, integer *ny, real *c__, integer *kx, integer *ky, real *x, integer *mx, real *y, integer *my, real *z__, real *wx, real *wy, integer *lx, integer *ly);
+
+extern int fpbspl_(real *t, integer *n, integer *k, real *x, integer *l, real *h__);
+
+extern int fpchec_(real *x, integer *m, real *t, integer *n, integer *k, integer *ier);
+
+extern int fpched_(real *x, integer *m, real *t, integer *n, integer *k, integer *ib, integer *ie, integer *ier);
+
+extern int fpchep_(real *x, integer *m, real *t, integer *n, integer *k, integer *ier);
+
+extern int fpclos_(integer *iopt, integer *idim, integer *m, real *u, integer *mx, real *x, real *w, integer *k, real *s, integer *nest, real *tol, integer *maxit, integer *k1, integer *k2, integer *n, real *t, integer *nc, real *c__, real *fp, real *fpint, real *z__, real *a1, real *a2, real *b, real *g1, real *g2, real *q, integer *nrdata, integer *ier);
+
+extern int fpcoco_(integer *iopt, integer *m, real *x, real *y, real *w, real *v, real *s, integer *nest, integer *maxtr, integer *maxbin, integer *n, real *t, real *c__, real *sq, real *sx, logical *bind, real *e, real *wrk, integer *lwrk, integer *iwrk, integer *kwrk, integer *ier);
+
+extern int fpcons_(integer *iopt, integer *idim, integer *m, real *u, integer *mx, real *x, real *w, integer *ib, integer *ie, integer *k, real *s, integer *nest, real *tol, integer *maxit, integer *k1, integer *k2, integer *n, real *t, integer *nc, real *c__, real *fp, real *fpint, real *z__, real *a, real *b, real *g, real *q, integer *nrdata, integer *ier);
+
+extern int fpcosp_(integer *m, real *x, real *y, real *w, integer *n, real *t, real *e, integer *maxtr, integer *maxbin, real *c__, real *sq, real *sx, logical *bind, integer *nm, integer *mb, real *a, real *b, real *const__, real *z__, real *zz, real *u, real *q, integer *info, integer *up, integer *left, integer *right, integer *jbind, integer *ibind, integer *ier);
+
+extern int fpcsin_(real *a, real *b, real *par, real *sia, real *coa, real *sib, real *cob, real *ress, real *resc);
+
+extern int fpcurf_(integer *iopt, real *x, real *y, real *w, integer *m, real *xb, real *xe, integer *k, real *s, integer *nest, real *tol, integer *maxit, integer *k1, integer *k2, integer *n, real *t, real *c__, real *fp, real *fpint, real *z__, real *a, real *b, real *g, real *q, integer *nrdata, integer *ier);
+
+extern int fpcuro_(real *a, real *b, real *c__, real *d__, real *x, integer *n);
+
+extern int fpcyt1_(real *a, integer *n, integer *nn);
+
+extern int fpcyt2_(real *a, integer *n, real *b, real *c__, integer *nn);
+
+extern int fpdeno_(integer *maxtr, integer *up, integer *left, integer *right, integer *nbind, integer *merk);
+
+extern int fpdisc_(real *t, integer *n, integer *k2, real *b, integer *nest);
+
+extern int fpfrno_(integer *maxtr, integer *up, integer *left, integer *right, integer *info, integer *point, integer *merk, integer *n1, integer *count, integer *ier);
+
+extern int fpgivs_(real *piv, real *ww, real *cos__, real *sin__);
+
+extern int fpgrdi_(integer *ifsu, integer *ifsv, integer *ifbu, integer *ifbv, integer *iback, real *u, integer *mu, real *v, integer *mv, real *z__, integer *mz, real *dz, integer *iop0, integer *iop1, real *tu, integer *nu, real *tv, integer *nv, real *p, real *c__, integer *nc, real *sq, real *fp, real *fpu, real *fpv, integer *mm, integer *mvnu, real *spu, real *spv, real *right, real *q, real *au, real *av1, real *av2, real *bu, real *bv, real *aa, real *bb, real *cc, real *cosi, in [...]
+
+extern int fpgrpa_(integer *ifsu, integer *ifsv, integer *ifbu, integer *ifbv, integer *idim, integer *ipar, real *u, integer *mu, real *v, integer *mv, real *z__, integer *mz, real *tu, integer *nu, real *tv, integer *nv, real *p, real *c__, integer *nc, real *fp, real *fpu, real *fpv, integer *mm, integer *mvnu, real *spu, real *spv, real *right, real *q, real *au, real *au1, real *av, real *av1, real *bu, real *bv, integer *nru, integer *nrv);
+
+extern int fpgrre_(integer *ifsx, integer *ifsy, integer *ifbx, integer *ifby, real *x, integer *mx, real *y, integer *my, real *z__, integer *mz, integer *kx, integer *ky, real *tx, integer *nx, real *ty, integer *ny, real *p, real *c__, integer *nc, real *fp, real *fpx, real *fpy, integer *mm, integer *mynx, integer *kx1, integer *kx2, integer *ky1, integer *ky2, real *spx, real *spy, real *right, real *q, real *ax, real *ay, real *bx, real *by, integer *nrx, integer *nry);
+
+extern int fpgrsp_(integer *ifsu, integer *ifsv, integer *ifbu, integer *ifbv, integer *iback, real *u, integer *mu, real *v, integer *mv, real *r__, integer *mr, real *dr, integer *iop0, integer *iop1, real *tu, integer *nu, real *tv, integer *nv, real *p, real *c__, integer *nc, real *sq, real *fp, real *fpu, real *fpv, integer *mm, integer *mvnu, real *spu, real *spv, real *right, real *q, real *au, real *av1, real *av2, real *bu, real *bv, real *a0, real *a1, real *b0, real *b1, real [...]
+
+extern int fpinst_(integer *iopt, real *t, integer *n, real *c__, integer *k, real *x, integer *l, real *tt, integer *nn, real *cc, integer *nest);
+
+extern int fpintb_(real *t, integer *n, real *bint, integer *nk1, real *x, real *y);
+
+extern int fpknot_(real *x, integer *m, real *t, integer *n, real *fpint, integer *nrdata, integer *nrint, integer *nest, integer *istart);
+
+extern int fpopdi_(integer *ifsu, integer *ifsv, integer *ifbu, integer *ifbv, real *u, integer *mu, real *v, integer *mv, real *z__, integer *mz, real *z0, real *dz, integer *iopt, integer *ider, real *tu, integer *nu, real *tv, integer *nv, integer *nuest, integer *nvest, real *p, real *step, real *c__, integer *nc, real *fp, real *fpu, real *fpv, integer *nru, integer *nrv, real *wrk, integer *lwrk);
+
+extern int fpopsp_(integer *ifsu, integer *ifsv, integer *ifbu, integer *ifbv, real *u, integer *mu, real *v, integer *mv, real *r__, integer *mr, real *r0, real *r1, real *dr, integer *iopt, integer *ider, real *tu, integer *nu, real *tv, integer *nv, integer *nuest, integer *nvest, real *p, real *step, real *c__, integer *nc, real *fp, real *fpu, real *fpv, integer *nru, integer *nrv, real *wrk, integer *lwrk);
+
+extern int fporde_(real *x, real *y, integer *m, integer *kx, integer *ky, real *tx, integer *nx, real *ty, integer *ny, integer *nummer, integer *index, integer *nreg);
+
+extern int fppara_(integer *iopt, integer *idim, integer *m, real *u, integer *mx, real *x, real *w, real *ub, real *ue, integer *k, real *s, integer *nest, real *tol, integer *maxit, integer *k1, integer *k2, integer *n, real *t, integer *nc, real *c__, real *fp, real *fpint, real *z__, real *a, real *b, real *g, real *q, integer *nrdata, integer *ier);
+
+extern int fppasu_(integer *iopt, integer *ipar, integer *idim, real *u, integer *mu, real *v, integer *mv, real *z__, integer *mz, real *s, integer *nuest, integer *nvest, real *tol, integer *maxit, integer *nc, integer *nu, real *tu, integer *nv, real *tv, real *c__, real *fp, real *fp0, real *fpold, real *reducu, real *reducv, real *fpintu, real *fpintv, integer *lastdi, integer *nplusu, integer *nplusv, integer *nru, integer *nrv, integer *nrdatu, integer *nrdatv, real *wrk, integer  [...]
+
+extern int fpperi_(integer *iopt, real *x, real *y, real *w, integer *m, integer *k, real *s, integer *nest, real *tol, integer *maxit, integer *k1, integer *k2, integer *n, real *t, real *c__, real *fp, real *fpint, real *z__, real *a1, real *a2, real *b, real *g1, real *g2, real *q, integer *nrdata, integer *ier);
+
+extern int fppocu_(integer *idim, integer *k, real *a, real *b, integer *ib, real *db, integer *nb, integer *ie, real *de, integer *ne, real *cp, integer *np);
+
+extern int fppogr_(integer *iopt, integer *ider, real *u, integer *mu, real *v, integer *mv, real *z__, integer *mz, real *z0, real *r__, real *s, integer *nuest, integer *nvest, real *tol, integer *maxit, integer *nc, integer *nu, real *tu, integer *nv, real *tv, real *c__, real *fp, real *fp0, real *fpold, real *reducu, real *reducv, real *fpintu, real *fpintv, real *dz, real *step, integer *lastdi, integer *nplusu, integer *nplusv, integer *lasttu, integer *nru, integer *nrv, integer  [...]
+
+extern int fppola_(integer *iopt1, integer *iopt2, integer *iopt3, integer *m, real *u, real *v, real *z__, real *w, E_fp rad, real *s, integer *nuest, integer *nvest, real *eta, real *tol, integer *maxit, integer *ib1, integer *ib3, integer *nc, integer *ncc, integer *intest, integer *nrest, integer *nu, real *tu, integer *nv, real *tv, real *c__, real *fp, real *sup, real *fpint, real *coord, real *f, real *ff, real *row, real *cs, real *cosi, real *a, real *q, real *bu, real *bv, real [...]
+
+extern int fprank_(real *a, real *f, integer *n, integer *m, integer *na, real *tol, real *c__, real *sq, integer *rank, real *aa, real *ff, real *h__);
+
+extern E_f fprati_(real *p1, real *f1, real *p2, real *f2, real *p3, real *f3);
+
+extern int fpregr_(integer *iopt, real *x, integer *mx, real *y, integer *my, real *z__, integer *mz, real *xb, real *xe, real *yb, real *ye, integer *kx, integer *ky, real *s, integer *nxest, integer *nyest, real *tol, integer *maxit, integer *nc, integer *nx, real *tx, integer *ny, real *ty, real *c__, real *fp, real *fp0, real *fpold, real *reducx, real *reducy, real *fpintx, real *fpinty, integer *lastdi, integer *nplusx, integer *nplusy, integer *nrx, integer *nry, integer *nrdatx,  [...]
+
+extern int fprota_(real *cos__, real *sin__, real *a, real *b);
+
+extern int fprppo_(integer *nu, integer *nv, integer *if1, integer *if2, real *cosi, real *ratio, real *c__, real *f, integer *ncoff);
+
+extern int fprpsp_(integer *nt, integer *np, real *co, real *si, real *c__, real *f, integer *ncoff);
+
+extern int fpseno_(integer *maxtr, integer *up, integer *left, integer *right, integer *info, integer *merk, integer *ibind, integer *nbind);
+
+extern int fpspgr_(integer *iopt, integer *ider, real *u, integer *mu, real *v, integer *mv, real *r__, integer *mr, real *r0, real *r1, real *s, integer *nuest, integer *nvest, real *tol, integer *maxit, integer *nc, integer *nu, real *tu, integer *nv, real *tv, real *c__, real *fp, real *fp0, real *fpold, real *reducu, real *reducv, real *fpintu, real *fpintv, real *dr, real *step, integer *lastdi, integer *nplusu, integer *nplusv, integer *lastu0, integer *lastu1, integer *nru, intege [...]
+
+extern int fpsphe_(integer *iopt, integer *m, real *teta, real *phi, real *r__, real *w, real *s, integer *ntest, integer *npest, real *eta, real *tol, integer *maxit, integer *ib1, integer *ib3, integer *nc, integer *ncc, integer *intest, integer *nrest, integer *nt, real *tt, integer *np, real *tp, real *c__, real *fp, real *sup, real *fpint, real *coord, real *f, real *ff, real *row, real *coco, real *cosi, real *a, real *q, real *bt, real *bp, real *spt, real *spp, real *h__, integer [...]
+
+extern int fpsuev_(integer *idim, real *tu, integer *nu, real *tv, integer *nv, real *c__, real *u, integer *mu, real *v, integer *mv, real *f, real *wu, real *wv, integer *lu, integer *lv);
+
+extern int fpsurf_(integer *iopt, integer *m, real *x, real *y, real *z__, real *w, real *xb, real *xe, real *yb, real *ye, integer *kxx, integer *kyy, real *s, integer *nxest, integer *nyest, real *eta, real *tol, integer *maxit, integer *nmax, integer *km1, integer *km2, integer *ib1, integer *ib3, integer *nc, integer *intest, integer *nrest, integer *nx0, real *tx, integer *ny0, real *ty, real *c__, real *fp, real *fp0, real *fpint, real *coord, real *f, real *ff, real *a, real *q, r [...]
+
+extern int fpsysy_(real *a, integer *n, real *g);
+
+extern int fptrnp_(integer *m, integer *mm, integer *idim, integer *n, integer *nr, real *sp, real *p, real *b, real *z__, real *a, real *q, real *right);
+
+extern int fptrpe_(integer *m, integer *mm, integer *idim, integer *n, integer *nr, real *sp, real *p, real *b, real *z__, real *a, real *aa, real *q, real *right);
+
+extern int insert_(integer *iopt, real *t, integer *n, real *c__, integer *k, real *x, real *tt, integer *nn, real *cc, integer *nest, integer *ier);
+
+extern int parcur_(integer *iopt, integer *ipar, integer *idim, integer *m, real *u, integer *mx, real *x, real *w, real *ub, real *ue, integer *k, real *s, integer *nest, integer *n, real *t, integer *nc, real *c__, real *fp, real *wrk, integer *lwrk, integer *iwrk, integer *ier);
+
+extern int parder_(real *tx, integer *nx, real *ty, integer *ny, real *c__, integer *kx, integer *ky, integer *nux, integer *nuy, real *x, integer *mx, real *y, integer *my, real *z__, real *wrk, integer *lwrk, integer *iwrk, integer *kwrk, integer *ier);
+
+extern int parsur_(integer *iopt, integer *ipar, integer *idim, integer *mu, real *u, integer *mv, real *v, real *f, real *s, integer *nuest, integer *nvest, integer *nu, real *tu, integer *nv, real *tv, real *c__, real *fp, real *wrk, integer *lwrk, integer *iwrk, integer *kwrk, integer *ier);
+
+extern int percur_(integer *iopt, integer *m, real *x, real *y, real *w, integer *k, real *s, integer *nest, integer *n, real *t, real *c__, real *fp, real *wrk, integer *lwrk, integer *iwrk, integer *ier);
+
+extern int pogrid_(integer *iopt, integer *ider, integer *mu, real *u, integer *mv, real *v, real *z__, real *z0, real *r__, real *s, integer *nuest, integer *nvest, integer *nu, real *tu, integer *nv, real *tv, real *c__, real *fp, real *wrk, integer *lwrk, integer *iwrk, integer *kwrk, integer *ier);
+
+extern int polar_(integer *iopt, integer *m, real *x, real *y, real *z__, real *w, E_fp rad, real *s, integer *nuest, integer *nvest, real *eps, integer *nu, real *tu, integer *nv, real *tv, real *u, real *v, real *c__, real *fp, real *wrk1, integer *lwrk1, real *wrk2, integer *lwrk2, integer *iwrk, integer *kwrk, integer *ier);
+
+extern int profil_(integer *iopt, real *tx, integer *nx, real *ty, integer *ny, real *c__, integer *kx, integer *ky, real *u, integer *nu, real *cu, integer *ier);
+
+extern int regrid_(integer *iopt, integer *mx, real *x, integer *my, real *y, real *z__, real *xb, real *xe, real *yb, real *ye, integer *kx, integer *ky, real *s, integer *nxest, integer *nyest, integer *nx, real *tx, integer *ny, real *ty, real *c__, real *fp, real *wrk, integer *lwrk, integer *iwrk, integer *kwrk, integer *ier);
+
+extern int spalde_(real *t, integer *n, real *c__, integer *k1, real *x, real *d__, integer *ier);
+
+extern int spgrid_(integer *iopt, integer *ider, integer *mu, real *u, integer *mv, real *v, real *r__, real *r0, real *r1, real *s, integer *nuest, integer *nvest, integer *nu, real *tu, integer *nv, real *tv, real *c__, real *fp, real *wrk, integer *lwrk, integer *iwrk, integer *kwrk, integer *ier);
+
+extern int sphere_(integer *iopt, integer *m, real *teta, real *phi, real *r__, real *w, real *s, integer *ntest, integer *npest, real *eps, integer *nt, real *tt, integer *np, real *tp, real *c__, real *fp, real *wrk1, integer *lwrk1, real *wrk2, integer *lwrk2, integer *iwrk, integer *kwrk, integer *ier);
+
+extern int splder_(real *t, integer *n, real *c__, integer *k, integer *nu, real *x, real *y, integer *m, real *wrk, integer *ier);
+
+extern int splev_(real *t, integer *n, real *c__, integer *k, real *x, real *y, integer *m, integer *ier);
+
+extern E_f splint_(real *t, integer *n, real *c__, integer *k, real *a, real *b, real *wrk);
+
+extern int sproot_(real *t, integer *n, real *c__, real *zero, integer *mest, integer *m, integer *ier);
+
+extern int surev_(integer *idim, real *tu, integer *nu, real *tv, integer *nv, real *c__, real *u, integer *mu, real *v, integer *mv, real *f, integer *mf, real *wrk, integer *lwrk, integer *iwrk, integer *kwrk, integer *ier);
+
+extern int surfit_(integer *iopt, integer *m, real *x, real *y, real *z__, real *w, real *xb, real *xe, real *yb, real *ye, integer *kx, integer *ky, real *s, integer *nxest, integer *nyest, integer *nmax, real *eps, integer *nx, real *tx, integer *ny, real *ty, real *c__, real *fp, real *wrk1, integer *lwrk1, real *wrk2, integer *lwrk2, integer *iwrk, integer *kwrk, integer *ier);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/linsystems.cpp b/bioimagesuite30_src/numerics/linsystems.cpp
new file mode 100644
index 0000000..c43cc88
--- /dev/null
+++ b/bioimagesuite30_src/numerics/linsystems.cpp
@@ -0,0 +1,761 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//
+//
+//
+//  This File contains the following Numerical Recipes derived code that
+//  will need to be removed prior to it becoming open source
+//
+//  ludcmp needs to be replaced, so does tridiag, and cyclictridiag
+//
+//---------------------------------------------------------------------------------------------------------
+#include <math.h>
+#include <stdio.h>
+#include "nr.h"
+#include "nrutil.h"
+#include <stdlib.h>
+#include "bioimagesuite_settings.h"
+
+#define TINY 1.0e-20;
+
+// ---------------------------------------------------------------------
+// 1. LU decomposition from Numerical Recipes
+// ---------------------------------------------------------------------
+
+void ludcmp(double **a,int n,int* indx,double* d,int& singular)
+{
+  vtkMath_LUFactorLinearSystem(a,indx,n,singular);
+  return;
+
+  //The following code is commented out, 
+  //It is left there for Legacy purposes only
+
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+}
+
+void lubksb(double **a,int n,int *indx,double b[])
+{
+  vtkMath_LUSolveLinearSystem(a,indx,b,n);
+  return;
+
+  //The following code is commented out, 
+  //It is left there for Legacy purposes only
+
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+}
+
+// This is replacement code from vtkMath .... the names are kept
+// Code Changed to reflect 1..N as opposed to 0..N-1 range!
+
+#define VTK_SMALL_NUMBER 1.0e-12
+
+// Factor linear equations Ax = b using LU decompostion A = LU where L is
+// lower triangular matrix and U is upper triangular matrix. Input is 
+// square matrix A, integer array of pivot indices index[0->n-1], and size
+// of square matrix n. Output factorization LU is in matrix A. If error is 
+// found, method returns 0. 
+void vtkMath_LUFactorLinearSystem(double **A, int *index, int size,int &singular)
+{
+  double scratch[12];
+  double *scale = (size<10 ? scratch : new double[size+1]);
+  singular=0;
+
+  int i, j, k;
+  int maxI = 0;
+  double largest, temp1, temp2, sum;
+
+  //
+  // Loop over rows to get implicit scaling information
+  //
+  for ( i = 1; i <= size; i++ ) 
+    {
+      for ( largest = 0.0, j = 0; j < size; j++ ) 
+	{
+	  if ( (temp2 = fabs(A[i][j])) > largest )
+	    {
+	      largest = temp2;
+	    }
+	}
+      
+      if ( largest == 0.0 )
+	{
+	  singular=1;
+	  return;
+	}
+      scale[i] = 1.0 / largest;
+    }
+  //
+  // Loop over all columns using Crout's method
+  //
+  for ( j = 1; j <= size; j++ ) 
+    {
+      for (i = 1; i < j; i++) 
+	{
+	  sum = A[i][j];
+	  for ( k = 1; k < i; k++ )
+	    {
+	      sum -= A[i][k] * A[k][j];
+	    }
+	  A[i][j] = sum;
+	}
+      //
+      // Begin search for largest pivot element
+      //
+      for ( largest = 0.0, i = j; i <= size; i++ ) 
+	{
+	  sum = A[i][j];
+	  for ( k = 1; k < j; k++ )
+	    {
+	      sum -= A[i][k] * A[k][j];
+	    }
+	  A[i][j] = sum;
+	  
+	  if ( (temp1 = scale[i]*fabs(sum)) >= largest ) 
+	    {
+	      largest = temp1;
+	      maxI = i;
+	    }
+	}
+      //
+      // Check for row interchange
+      //
+      if ( j != maxI ) 
+	{
+	  for ( k = 1; k <= size; k++ ) 
+	    {
+	      temp1 = A[maxI][k];
+	      A[maxI][k] = A[j][k];
+	      A[j][k] = temp1;
+	    }
+	  scale[maxI] = scale[j];
+	}
+      //
+      // Divide by pivot element and perform elimination
+      //
+      index[j] = maxI;
+      
+      if ( fabs(A[j][j]) <= VTK_SMALL_NUMBER )
+	{
+	  singular=1;
+	  return;
+	}
+      
+      if ( j != (size) ) 
+	{
+	  temp1 = 1.0 / A[j][j];
+	  for ( i = j + 1; i <= size; i++ )
+	    {
+	      A[i][j] *= temp1;
+	    }
+	}
+    }
+  
+  if (size >= 10 ) delete [] scale;
+  
+  singular=0;
+}
+
+
+// Solve linear equations Ax = b using LU decompostion A = LU where L is
+// lower triangular matrix and U is upper triangular matrix. Input is 
+// factored matrix A=LU, integer array of pivot indices index[0->n-1],
+// load vector x[0->n-1], and size of square matrix n. Note that A=LU and
+// index[] are generated from method LUFactorLinearSystem). Also, solution
+// vector is written directly over input load vector.
+void vtkMath_LUSolveLinearSystem(double **A, int *index,double *x, int size)
+{
+  int i, j, ii, idx;
+  double sum;
+  //
+  // Proceed with forward and backsubstitution for L and U
+  // matrices.  First, forward substitution.
+  //
+  for ( ii = 0, i = 1; i <= size; i++ ) 
+    {
+      idx = index[i];
+      sum = x[idx];
+      x[idx] = x[i];
+      
+      if ( ii >= 1 )
+	{
+	  for ( j = ii; j <= (i-1); j++ )
+	    {
+	      sum -= A[i][j]*x[j];
+	    }
+	}
+      else if (sum)
+	{
+	  ii = i;
+	}
+      
+      x[i] = sum;
+    }
+  //
+  // Now, back substitution
+  //
+  for ( i = size; i >= 1; i-- ) 
+    {
+      sum = x[i];
+      for ( j = i + 1; j <= size; j++ )
+	{
+	  sum -= A[i][j]*x[j];
+	}
+      x[i] = sum / A[i][i];
+    }
+}
+#undef VTK_SMALL_NUMBER 
+// ---------------------------------------------------------------------
+// 2. SOR -- code written for ME340 class
+// ---------------------------------------------------------------------
+
+int sor(double **a,int n, double *b,double *oldx,
+	 double thr,double omega)
+     
+{
+  //     matrix a is nxn  vector b is nx1
+  const int MAXITER=100;
+  int maxiter=MAXITER*n;
+  int row,col,iter=0;
+  double moddif,modx,res;
+  double *newx,r;
+  newx=dvector(1,n);
+  res=thr+1.0;
+  
+  while ( res>thr && iter < maxiter) 
+    {
+      iter++;
+      for (row=1;row<=n;row++)
+	{
+	  r=0.0;
+	  
+	  //     form gaus-seidel best estimate;
+	  //     for elements before leading diagonal;
+	  for (col=1;col<row;col++)
+            r=r+a[row][col]*newx[col];
+
+	  //     for elements after leading diagonal;
+
+	  for (col=row+1;col<=n;col++)
+            r=r+a[row][col]*oldx[col];
+
+	  //     form sor (gaus seidel omega=1);
+
+	  newx[row]=omega*((b[row]-r)/a[row][row]);
+	  newx[row]=newx[row]+(1-omega)*oldx[row];
+	}
+
+      //     calculate ||x(k+1)-x(k)||(inf) moddif and ||x(k)||(inf)=modx;
+      //     also do oldx=x to prepare for next iteration;
+      
+      moddif=0.0;
+      modx=0.0;
+      
+      for (row=1;row<=n;row ++)
+	{
+	  if (fabs(oldx[row]-newx[row]) > moddif) 
+	    moddif=fabs(oldx[row]-newx[row]);
+	  if (fabs(newx[row]) > modx) 
+	    modx=fabs(newx[row]);
+	  oldx[row]=newx[row];
+	}
+      res=moddif/modx;
+
+    }
+
+  free_dvector(newx,1,n);
+  return iter;
+}
+
+// ---------------------------------------------------------------------
+// 3. Conjugate Gradient Descent -- code written for ME340 class
+// ---------------------------------------------------------------------
+int conjugate(double** a,int n,double* b,double* oldx,double thr)
+
+{
+
+  //     matrix a is nxn  vector b is nx1
+
+  double moddif,modx,res,betak,rkrk,pkapk,alphak;
+  double *newx=dvector(1,n);
+  double *rk=dvector(1,n);
+  double *rkm2=dvector(1,n);
+  double *rkm1=dvector(1,n);
+  double *pk=dvector(1,n);
+  double *apk=dvector(1,n);
+  double *rold=dvector(1,n);
+  
+  int i,j,iter=0;
+
+  for (i=1;i<=n;i++)
+    rold[i]=b[i];
+  
+  res=thr+1.0;
+
+  while (res>thr && iter<=n) 
+    {
+      iter++;
+      if (iter==1)
+	{
+	  rkrk=0;
+	  for (i=1;i<=n;i++)
+	    {
+	      pk[i]=rold[i];
+	      rkrk=rkrk+rold[i]*rold[i];
+	      rkm1[i]=rold[i];
+	    }
+	}
+      else
+	{
+	  rkrk=0;
+	  betak=0;
+	  for (i=1;i<=n;i++)
+	    {
+	      rkrk =rkrk +rkm1[i]*rkm1[i];
+	      betak=betak+rkm2[i]*rkm2[i];
+	    }
+	  betak=rkrk/betak;
+	  for (i=1;i<=n;i++)
+	    pk[i]=rkm1[i]+betak*pk[i];
+	}
+      
+      //     form a*pk and pk*a*pk;
+      for (i=1;i<=n;i++)
+	{
+	  apk[i]=0;
+	  for (j=1;j<=n;j++)
+	    apk[i]=apk[i]+a[i][j]*pk[j];
+	}  
+      
+      pkapk=0;
+      for (i=1;i<=n;i++)
+	pkapk=pkapk+pk[i]*apk[i];
+      
+      alphak=rkrk/pkapk;
+      
+      for(i=1;i<=n;i++)
+	{
+	  newx[i]=oldx[i]+alphak*pk[i];
+	  rk[i]=rkm1[i]-alphak*apk[i];
+	}
+      
+      modx=0;
+      moddif=0;
+      
+      
+      for(i=1;i<=n;i++)
+	{
+	  if (fabs(oldx[i]-newx[i]) >moddif) 
+	    moddif=fabs(oldx[i]-newx[i]);
+	  if (fabs(newx[i]) > modx) 
+	    modx=fabs(newx[i]);
+	}
+      
+      //     print*, 'moddif ',moddif ,'modx', modx;
+      res=moddif/modx;
+      
+      for (i=1;i<=n;i++)
+	{
+	  rkm2[i]=rkm1[i];
+	  rkm1[i]=rk[i];
+	  oldx[i]=newx[i];
+	}
+    }
+  free_dvector(newx,1,n);
+  free_dvector(rk,1,n);
+  free_dvector(rkm2,1,n);
+  free_dvector(rkm1,1,n);
+  free_dvector(pk,1,n);
+  free_dvector(apk,1,n);
+  free_dvector(rold,1,n);
+  return iter;
+}
+
+
+// ---------------------------------------------------------------------
+// 4. Pre-Conjugate Gradient Descent -- code written for ME340 class
+// ---------------------------------------------------------------------
+int precondconjugate(double** a,int n,double* b,double* oldx,double thr)
+
+{
+
+  //     matrix a is nxn  vector b is nx1
+
+  double *newx=dvector(1,n);
+  double *rkm2=dvector(1,n);
+  double *rkm1=dvector(1,n);
+  double *pk=dvector(1,n);
+  double *zkm1=dvector(1,n);
+  double *zkm2=dvector(1,n);
+  double *rk=dvector(1,n);
+  double *apk=dvector(1,n);
+
+  double  moddif,modx,res=0.0,betak=0.0,rkzk=0.0,pkapk=0.0,alphak=0.0;
+  int i,j,iter=0;
+
+  for (i=1;i<=n;i++)
+    {
+      rkm1[i]=b[i];
+      zkm1[i]=rkm1[i]/a[i][i];
+      pk[i]=0.0;
+    }
+  res=thr+1;
+
+  while(res>thr && iter<=n)
+    {
+      iter++;
+      if (iter==1) 
+	{
+	  rkzk=0;
+	  for (i=1;i<=n;i++)
+	    {
+	      pk[i]=zkm1[i];
+	      rkzk =rkzk+rkm1[i]*zkm1[i];
+	    }
+	}
+      else
+	{
+	  rkzk=0;
+	  betak=0;
+	  for (i=1;i<=n;i++)
+	    {
+	      rkzk =rkzk +rkm1[i]*zkm1[i];
+	      betak=betak+rkm2[i]*zkm2[i];
+	    }
+	  betak=rkzk/betak;
+
+	  for (i=1;i<=n;i++)
+            pk[i]=zkm1[i]+betak*pk[i];
+	}
+	
+      //     form a*pk and pk*a*pk;
+      
+      pkapk=0;
+      for (i=1;i<=n;i++)
+	{
+	  apk[i]=0;
+	  for (j=1;j<=n;j++)
+	    {
+	      apk[i]=apk[i]+a[i][j]*pk[j];
+	    }
+	  pkapk=pkapk+pk[i]*apk[i];
+	}
+      
+      alphak=rkzk/pkapk;
+      
+      for (i=1;i<=n;i++)
+	{
+	  newx[i]=oldx[i]+alphak*pk[i];
+	  rk[i]=rkm1[i]-alphak*apk[i];
+	}
+      
+      modx=0;      moddif=0;
+      
+      for (i=1;i<=n;i++)
+	{
+	  
+	  if (fabs(oldx[i]-newx[i]) > moddif) 
+	    moddif=fabs(oldx[i]-newx[i]);
+	  if (fabs(newx[i]) > modx)
+	    modx=fabs(newx[i]);
+	}
+      
+      res=moddif/modx;
+      
+      for (i=1;i<=n;i++)
+	{
+	  zkm2[i]=zkm1[i];
+	  rkm2[i]=rkm1[i];
+	  rkm1[i]=rk[i];
+	  zkm1[i]=rkm1[i]/a[i][i];
+	  oldx[i]=newx[i];
+	}
+    }
+
+   free_dvector(newx,1,n);
+   free_dvector(rkm2,1,n);
+   free_dvector(rkm1,1,n);
+   free_dvector(pk,1,n);
+   free_dvector(zkm1,1,n);
+   free_dvector(zkm2,1,n);
+   free_dvector(rk,1,n);
+   free_dvector(apk,1,n);
+
+  return iter;
+}
+
+// ------------------------------------------------------------
+//  [5]	Routine from Numerical Recipes for solving 3-diag sys  
+// ------------------------------------------------------------
+// These should be replaced by code from the GSL, in particular
+// tridiag.c
+
+/*
+void tridag(float a[], float b[], float c[], float r[], float u[],
+	    long n)
+{
+#ifdef BIS_USE_NR
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+#endif
+}
+
+// -------------------------------------------------------------------------
+//  [5b]	Routine from Numerical Recipes for cyclic solving 3-diag sys  
+// -------------------------------------------------------------------------
+
+void cyclictridiag(float a[],float b[],float c[], 
+		   float alpha, float beta, 
+		   float r[],float x[], long n)
+{
+#ifdef BIS_USE_NR
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+#else
+  cyclictridiag_gsl(a,b,c,alpha,beta,r,x,n);
+#endif
+}
+
+void cyclictridiag_gsl(float a[],float b[],float c[], 
+		       float alpha, float beta, 
+		       float r[],float x[], long n)
+{
+  // Reroute to GSL ...
+  // a = belowdiag
+  // b = diag
+  // c = above diag 
+
+  // belowdiag counting is different !!!!
+  float* anew=new float[n+1];
+
+  for (int i=1;i<n;i++)
+    anew[i]=a[i+1];
+  anew[n]=a[1];
+
+  solve_cyc_tridiag_nonsym_gsl(b,c,anew,r,x,n);
+  delete [] anew;
+}
+*/
+
+/*
+The following code is edited from below
+
+ * 
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2004 Gerard Jungman,
+ * Brian Gough, David Necas
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+
+/* solve following system w/o the corner elements and then use
+ * Sherman-Morrison formula to compensate for them
+ *
+ *        diag[0]  abovediag[0]             0   .....  belowdiag[N-1]
+ *   belowdiag[0]       diag[1]  abovediag[1]   .....
+ *              0  belowdiag[1]       diag[2]
+ *              0             0  belowdiag[2]   .....
+ *            ...           ...
+ * abovediag[N-1]           ...
+ */
+int solve_cyc_tridiag_nonsym_gsl( float in_diag[],
+				  float in_abovediag[], 
+				  float in_belowdiag[], 
+				  float in_rhs[], 
+				 float in_x[], 
+				 int    N)
+{
+  int status;
+  float *alpha = (float *) malloc (N * sizeof (float));
+  float *zb = (float *) malloc (N * sizeof (float));
+  float *zu = (float *) malloc (N * sizeof (float));
+  float *w = (float *) malloc (N * sizeof (float));
+
+  int a_stride=1, d_stride=1, b_stride=1, r_stride=1, x_stride=1;
+
+  // Next Step is to move stuff by 1 to use 0-offset, remember input is 1-offset
+  //
+  float* diag=&in_diag[0]; diag++;
+  float* abovediag=&in_abovediag[0]; abovediag++;
+  float* belowdiag=&in_belowdiag[0]; belowdiag++;
+  float* rhs=&in_rhs[0]; rhs++;
+  float* x=&in_x[0];  x++;
+  
+  /*  fprintf(stderr,"\n bg \t dg \t ad \t rh \t x \n");
+  for (int i=0;i<N;i++)
+    fprintf(stderr,"%.2f \t %.2f \t %.2f \t %.2f \t %.2f\n",
+	    belowdiag[i],diag[i],abovediag[i],rhs[i],x[i]);
+	    fprintf(stderr,"\n\n");*/
+  
+
+  float beta;
+
+  if (alpha == 0 || zb == 0 || zu == 0 || w == 0)
+    {
+      status = 0;
+    }
+  else
+    {
+      /* Bidiagonalization (eliminating belowdiag)
+         & rhs update
+         diag' = alpha
+         rhs' = zb
+         rhs' for Aq=u is zu
+       */
+      zb[0] = rhs[0];
+      if (diag[0] != 0) beta = -diag[0]; else beta = 1;
+      {
+        const float q = 1 - abovediag[0]*belowdiag[0]/(diag[0]*diag[d_stride]);
+        if (fabs(q/beta) > 0.5 && fabs(q/beta) < 2) {
+          beta *= (fabs(q/beta) < 1) ? 0.5 : 2;
+        }
+      }
+      zu[0] = beta;
+      alpha[0] = diag[0] - beta;
+
+
+      { 
+        size_t i;
+        for (i = 1; i+1 < N; i++)
+        {
+          const float t = belowdiag[b_stride*(i - 1)]/alpha[i-1];
+          alpha[i] = diag[d_stride*i] - t*abovediag[a_stride*(i - 1)];
+          zb[i] = rhs[r_stride*i] - t*zb[i-1];
+          zu[i] = -t*zu[i-1];
+          /* FIXME!!! */
+          if (alpha[i] == 0) {
+            status = 0;
+            goto solve_cyc_tridiag_nonsym_END;
+          }
+        }
+      }
+
+      {
+        const size_t i = N-1;
+        const float t = belowdiag[b_stride*(i - 1)]/alpha[i-1];
+        alpha[i] = diag[d_stride*i]
+                   - abovediag[a_stride*i]*belowdiag[b_stride*i]/beta
+                   - t*abovediag[a_stride*(i - 1)];
+        zb[i] = rhs[r_stride*i] - t*zb[i-1];
+        zu[i] = abovediag[a_stride*i] - t*zu[i-1];
+        /* FIXME!!! */
+        if (alpha[i] == 0) {
+          status = 0;
+          goto solve_cyc_tridiag_nonsym_END;
+        }
+      }
+
+
+      /* backsubstitution */
+      {
+        size_t i, j;
+        w[N-1] = zu[N-1]/alpha[N-1];
+        x[N-1] = zb[N-1]/alpha[N-1];
+        for (i = N - 2, j = 0; j <= N - 2; j++, i--)
+          {
+            w[i] = (zu[i] - abovediag[a_stride*i] * w[i+1])/alpha[i];
+            x[i*x_stride] = (zb[i] - abovediag[a_stride*i] * x[x_stride*(i + 1)])/alpha[i];
+          }
+      }
+      
+      /* Sherman-Morrison */
+      {
+        const float vw = w[0] + belowdiag[b_stride*(N - 1)]/beta * w[N-1];
+        const float vx = x[0] + belowdiag[b_stride*(N - 1)]/beta * x[x_stride*(N - 1)];
+        /* FIXME!!! */
+        if (vw + 1 == 0) {
+          status = 0;
+          goto solve_cyc_tridiag_nonsym_END;
+        }
+
+        {
+          size_t i;
+          for (i = 0; i < N; i++)
+            x[i] -= vx/(1 + vw)*w[i];
+        }
+      }
+
+      status = 1;
+    }
+
+solve_cyc_tridiag_nonsym_END:
+  if (zb != 0)
+    free (zb);
+  if (zu != 0)
+    free (zu);
+  if (w != 0)
+    free (w);
+  if (alpha != 0)
+    free (alpha);
+
+  return status;
+}
+
+#undef TINY
+
diff --git a/bioimagesuite30_src/numerics/nr.h b/bioimagesuite30_src/numerics/nr.h
new file mode 100644
index 0000000..e76db77
--- /dev/null
+++ b/bioimagesuite30_src/numerics/nr.h
@@ -0,0 +1,92 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//  This File contains the following Numerical Recipes derived code that
+//  will need to be removed prior to it becoming open source
+//
+//  Headers are OK .. but functions lubksb, ludcmp, cyclictridiag, tridiag are bad!
+//
+//---------------------------------------------------------------------------------------------------------
+// Modified Header 26th December 1995 - ANSI C only to comply with C++
+
+#include <math.h>
+#include "nrutil.h"
+
+#ifndef _NUM_RECIPES_FIXED
+#define _NUM_RECIPES_FIXED
+// Defining namespace for old code
+
+
+//  *--*  *--*  *--*  *--*  *--*  *--*  *--*  *--*  *--*  *--*  *--* 
+//  linsystems.cc  
+//  *--*  *--*  *--*  *--*  *--*  *--*  *--*  *--*  *--*  *--*  *--* 
+
+void  lubksb(double **a, int n, int *indx, double *b);
+void  ludcmp(double **a, int n, int *indx, double *d,int& singular);
+
+void vtkMath_LUFactorLinearSystem(double **A, int *index, int size,int& singular);
+void vtkMath_LUSolveLinearSystem(double **A, int *index,double *x, int size);
+
+
+int   sor(double **a,int n, double *b,double *oldx,
+	  double thr,double omega);
+int   conjugate(double** a,int n,double* b,double* oldx,double thr);
+int   precondconjugate(double** a,int n,double* b,double* oldx,double thr);
+
+
+/*void cyclictridiag(float a[],float b[],float c[], 
+	    float alpha, float beta, 
+	    float r[],float x[], long n);
+void cyclictridiag_gsl(float a[],float b[],float c[], 
+	    float alpha, float beta, 
+	    float r[],float x[], long n);
+void tridag(float a[], float b[], float c[], float r[], float u[],
+long n);*/
+
+
+int solve_cyc_tridiag_nonsym_gsl(float diag[],
+				 float abovediag[], 
+				 float belowdiag[], 
+				 float rhs[], 
+				 float x[], 
+				 int    N);
+
+
+
+
+
+
+
+
+#endif  /* _NUM_RECIPES */
+
+
+
diff --git a/bioimagesuite30_src/numerics/nrutil.cpp b/bioimagesuite30_src/numerics/nrutil.cpp
new file mode 100644
index 0000000..9295eb5
--- /dev/null
+++ b/bioimagesuite30_src/numerics/nrutil.cpp
@@ -0,0 +1,813 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+// While this file contains a ton of NR-derived code, all of this has been placed in the public domain
+//       hence no issues here!
+//
+//---------------------------------------------------------------------------------------------------------
+
+// New Version of nrutil.c(c) with proper ANSI C 
+// Uses header nrutil.h
+// April 3rd 1995
+
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include "nrutil.h"
+
+#define NR_END 1
+#define FREE_ARG char*
+
+// --------------------------------------------------------
+// Error Handling or not as the case may be -- exit(1)
+// --------------------------------------------------------
+void nrerror(const char* error_text)
+{
+  fprintf(stderr,"Numerical Recipes run-time error...\n");
+  fprintf(stderr,"%s\n",error_text);
+  fprintf(stderr,"...now exiting to system...\n");
+  //  exit(1);
+}
+
+// ------------------------------------------------------------------
+// Original Numerical Recipes Code for allocating and releasing data
+// ------------------------------------------------------------------
+float *vector(long nl, long nh)
+/* allocate a float vector with subscript range v[nl..nh] */
+{
+	float *v;
+
+	v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float)));
+	if (!v) nrerror("allocation failure in vector()");
+	return v-nl+NR_END;
+}
+
+int *ivector(long nl, long nh)
+/* allocate an int vector with subscript range v[nl..nh] */
+{
+	int *v;
+
+	v=(int *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(int)));
+	if (!v) nrerror("allocation failure in ivector()");
+	return v-nl+NR_END;
+}
+
+unsigned char *cvector(long nl, long nh)
+/* allocate an unsigned char vector with subscript range v[nl..nh] */
+{
+	unsigned char *v;
+
+	v=(unsigned char *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(unsigned char)));
+	if (!v) nrerror("allocation failure in cvector()");
+	return v-nl+NR_END;
+}
+
+unsigned long *lvector(long nl, long nh)
+/* allocate an unsigned long vector with subscript range v[nl..nh] */
+{
+	unsigned long *v;
+
+	v=(unsigned long *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(long)));
+	if (!v) nrerror("allocation failure in lvector()");
+	return v-nl+NR_END;
+}
+
+double *dvector(long nl, long nh)
+/* allocate a double vector with subscript range v[nl..nh] */
+{
+	double *v;
+
+	v=(double *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(double)));
+	if (!v) nrerror("allocation failure in dvector()");
+	return v-nl+NR_END;
+}
+
+float **matrix(long nrl, long nrh, long ncl, long nch)
+/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */
+{
+	long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
+	float **m;
+
+	/* allocate pointers to rows */
+	m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*)));
+	if (!m) nrerror("allocation failure 1 in matrix()");
+	m += NR_END;
+	m -= nrl;
+
+	/* allocate rows and set pointers to them */
+	m[nrl]=(float *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(float)));
+	if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
+	m[nrl] += NR_END;
+	m[nrl] -= ncl;
+
+	for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
+
+	/* return pointer to array of pointers to rows */
+	return m;
+}
+
+double **dmatrix(long nrl, long nrh, long ncl, long nch)
+/* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */
+{
+	long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
+	double **m;
+
+	/* allocate pointers to rows */
+	m=(double **) malloc((size_t)((nrow+NR_END)*sizeof(double*)));
+	if (!m) nrerror("allocation failure 1 in matrix()");
+	m += NR_END;
+	m -= nrl;
+
+	/* allocate rows and set pointers to them */
+	m[nrl]=(double *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(double)));
+	if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
+	m[nrl] += NR_END;
+	m[nrl] -= ncl;
+
+	for(i=nrl+1;i<=nrh;i++) 
+	    m[i]=m[i-1]+ncol;
+
+	/* return pointer to array of pointers to rows */
+	return m;
+}
+
+int **imatrix(long nrl, long nrh, long ncl, long nch)
+/* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */
+{
+	long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
+	int **m;
+
+	/* allocate pointers to rows */
+	m=(int **) malloc((size_t)((nrow+NR_END)*sizeof(int*)));
+	if (!m) nrerror("allocation failure 1 in matrix()");
+	m += NR_END;
+	m -= nrl;
+
+
+	/* allocate rows and set pointers to them */
+	m[nrl]=(int *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(int)));
+	if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
+	m[nrl] += NR_END;
+	m[nrl] -= ncl;
+
+	for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
+
+	/* return pointer to array of pointers to rows */
+	return m;
+}
+
+float **submatrix(float **a, long oldrl, long oldrh, long oldcl, long /*oldch*/,
+	long newrl, long newcl)
+/* point a submatrix [newrl..][newcl..] to a[oldrl..oldrh][oldcl..oldch] */
+{
+	long i,j,nrow=oldrh-oldrl+1,ncol=oldcl-newcl;
+	float **m;
+
+	/* allocate array of pointers to rows */
+	m=(float **) malloc((size_t) ((nrow+NR_END)*sizeof(float*)));
+	if (!m) nrerror("allocation failure in submatrix()");
+	m += NR_END;
+	m -= newrl;
+
+	/* set pointers to rows */
+	for(i=oldrl,j=newrl;i<=oldrh;i++,j++) m[j]=a[i]+ncol;
+
+	/* return pointer to array of pointers to rows */
+	return m;
+}
+
+float **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch)
+/* allocate a float matrix m[nrl..nrh][ncl..nch] that points to the matrix
+declared in the standard C manner as a[nrow][ncol], where nrow=nrh-nrl+1
+and ncol=nch-ncl+1. The routine should be called with the address
+&a[0][0] as the first argument. */
+{
+	long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1;
+	float **m;
+
+	/* allocate pointers to rows */
+	m=(float **) malloc((size_t) ((nrow+NR_END)*sizeof(float*)));
+	if (!m) nrerror("allocation failure in convert_matrix()");
+	m += NR_END;
+	m -= nrl;
+
+	/* set pointers to rows */
+	m[nrl]=a-ncl;
+	for(i=1,j=nrl+1;i<nrow;i++,j++) m[j]=m[j-1]+ncol;
+	/* return pointer to array of pointers to rows */
+	return m;
+}
+
+float ***f3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh)
+/* allocate a float 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
+{
+	long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
+	float ***t;
+
+	/* allocate pointers to pointers to rows */
+	t=(float ***) malloc((size_t)((nrow+NR_END)*sizeof(float**)));
+	if (!t) nrerror("allocation failure 1 in f3tensor()");
+	t += NR_END;
+	t -= nrl;
+
+	/* allocate pointers to rows and set pointers to them */
+	t[nrl]=(float **) malloc((size_t)((nrow*ncol+NR_END)*sizeof(float*)));
+	if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
+	t[nrl] += NR_END;
+	t[nrl] -= ncl;
+
+	/* allocate rows and set pointers to them */
+	t[nrl][ncl]=(float *) malloc((size_t)((nrow*ncol*ndep+NR_END)*sizeof(float)));
+	if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
+	t[nrl][ncl] += NR_END;
+	t[nrl][ncl] -= ndl;
+
+	for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
+	for(i=nrl+1;i<=nrh;i++) {
+		t[i]=t[i-1]+ncol;
+		t[i][ncl]=t[i-1][ncl]+ncol*ndep;
+		for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
+	}
+
+	/* return pointer to array of pointers to rows */
+	return t;
+}
+
+void free_vector(float *v, long nl, long /*nh*/)
+/* free a float vector allocated with vector() */
+{
+	free((FREE_ARG) (v+nl-NR_END));
+}
+
+void free_ivector(int *v, long nl, long /*nh*/)
+/* free an int vector allocated with ivector() */
+{
+	free((FREE_ARG) (v+nl-NR_END));
+}
+
+void free_cvector(unsigned char *v, long nl, long /*nh*/)
+/* free an unsigned char vector allocated with cvector() */
+{
+	free((FREE_ARG) (v+nl-NR_END));
+}
+
+void free_lvector(unsigned long *v, long nl, long /*nh*/)
+/* free an unsigned long vector allocated with lvector() */
+{
+	free((FREE_ARG) (v+nl-NR_END));
+}
+
+void free_dvector(double *v, long nl, long /*nh*/)
+/* free a double vector allocated with dvector() */
+{
+	free((FREE_ARG) (v+nl-NR_END));
+}
+
+void free_matrix(float **m, long nrl, long /* nrh */, long ncl, long /* nch */)
+/* free a float matrix allocated by matrix() */
+{
+	free((FREE_ARG) (m[nrl]+ncl-NR_END));
+	free((FREE_ARG) (m+nrl-NR_END));
+}
+
+void free_dmatrix(double **m, long nrl, long /* nrh */, long ncl, long /* nch */)
+/* free a double matrix allocated by dmatrix() */
+{
+  free((FREE_ARG) (m[nrl]+ncl-NR_END));
+  free((FREE_ARG) (m+nrl-NR_END));
+}
+
+void free_imatrix(int **m, long nrl, long /* nrh */, long ncl, long /* nch */)
+/* free an int matrix allocated by imatrix() */
+{
+	free((FREE_ARG) (m[nrl]+ncl-NR_END));
+	free((FREE_ARG) (m+nrl-NR_END));
+}
+
+void free_submatrix(float **b, long nrl, long /* nrh */, long /* ncl */, long /* nch */)
+/* free a submatrix allocated by submatrix() */
+{
+	free((FREE_ARG) (b+nrl-NR_END));
+}
+
+void free_convert_matrix(float **b, long nrl, long /* nrh */, long /*ncl*/, long /* nch */)
+/* free a matrix allocated by convert_matrix() */
+{
+	free((FREE_ARG) (b+nrl-NR_END));
+}
+
+void free_f3tensor(float ***t, long nrl, long /* nrh */, long ncl, long /* nch */,
+	long ndl, long /* ndh */)
+/* free a float f3tensor allocated by f3tensor() */
+{
+	free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
+	free((FREE_ARG) (t[nrl]+ncl-NR_END));
+	free((FREE_ARG) (t+nrl-NR_END));
+}
+
+// ------------------ Added Utilities  ------------------------------
+// Copy and Symmetric Operations
+// ------------------------------------------------------------------
+
+void copyvector(float *a,float *b,int rows)
+{
+  for (int i=1;i<=rows;i++)
+    a[i]=b[i];
+}
+
+void copydvector(double *a,double *b,int rows)
+
+{
+  for (int i=1;i<=rows;i++)
+    a[i]=b[i];
+}
+
+void copyivector(int *a,int *b,int rows)
+
+{
+  for (int i=1;i<=rows;i++)
+    a[i]=b[i];
+}
+
+
+// ------------------ Matrices -----------------------------
+void symmetric(float **a, int n)
+// Assume top half including leading diagonal filled
+{
+for (int i=2; i<=n;i++)
+  for (int j=1; j<i; j++)
+    a[i][j]=a[j][i];
+}
+
+void copymatrix(float **a,float **b,int rows,int columns)
+
+{
+for (int i=1;i<=rows;i++)
+  for (int j=1;j<=columns;j++)
+    a[i][j]=b[i][j];
+}
+
+void dsymmetric(double **a, int n)
+// Assume top half including leading diagonal filled
+{
+for (int i=2; i<=n;i++)
+  for (int j=1; j<i; j++)
+    a[i][j]=a[j][i];
+}
+
+void copydmatrix(double **a,double **b,int rows,int columns)
+
+{
+for (int i=1;i<=rows;i++)
+  for (int j=1;j<=columns;j++)
+    a[i][j]=b[i][j];
+}
+
+
+
+void isymmetric(int **a, int n)
+// Assume top half including leading diagonal filled
+{
+for (int i=2; i<=n;i++)
+  for (int j=1; j<i; j++)
+    a[i][j]=a[j][i];
+}
+
+void copyimatrix(int **a,int **b,int rows,int columns)
+
+{
+for (int i=1;i<=rows;i++)
+  for (int j=1;j<=columns;j++)
+    a[i][j]=b[i][j];
+}
+
+
+// -----------------------------------------------------------------
+//           Print Operations
+// -----------------------------------------------------------------
+
+void printivector(int* v,int n,const char* fmt,const char* name,int wd)
+{
+  printdvector((double*)v,n,fmt,name,wd);  
+}
+
+void printvector(float* v,int n,const char* fmt,const char* name,int wd)
+{
+  printdvector((double*)v,n,fmt,name,wd);  
+}
+
+void printdvector(double* v,int n,const char* fmt,const char* name,int wd)
+{
+  char ll[200];
+  int cnt=0;
+  
+  fprintf(stdout,"%s = [ ",name);
+  //  printf(" =  [ ");
+  for (int i=1;i<=n;i++)
+    {
+      if (fabs(v[i])<1e-10) v[i]=0.0;
+
+      if (fabs(v[i])<1e+6)
+	sprintf(ll,fmt,v[i]);
+      else
+	sprintf(ll," ###### ");
+
+      fprintf(stdout,"%s",ll);
+      cnt++;
+      if (cnt==wd) 
+	{
+	  fprintf(stdout,"\n\t\t");
+	  cnt=0;
+	}
+    }
+  fprintf(stdout," ]\n");
+}
+// -----------------------------------------------------------------
+
+void printmatrix(float** a,int row,int col,const char* fmt,const char* name,int wd,int off)
+{
+  printdmatrix((double**)a,row,col,fmt,name,wd,off);  
+}
+
+void printimatrix(int** a,int row,int col,const char* fmt,const char* name,int wd,int off)
+{
+  printdmatrix((double**)a,row,col,fmt,name,wd,off);  
+}
+
+void printdmatrix(double** a,int row,int col,const char* fmt,const char* name,int wd,int off)
+{
+  //  char ll[20];
+  int cnt=0;
+  
+  for (int j=off;j<row+off;j++)
+    {
+      if (j==off) 
+	  fprintf(stderr,"%s = ",name);
+      else
+	  for(int k=1;k<=(int)strlen(name)+3;k++)
+	      fprintf(stderr," ");
+      fprintf(stderr," [ ");
+      for (int i=off;i<col+off;i++)
+	{
+	  //	  sprintf(ll,
+	  fprintf(stderr,fmt,a[j][i]);
+	  cnt++;
+	  if (cnt==wd) 
+	    {
+	      fprintf(stderr,"\n\t\t");
+	      cnt=0;
+	    }
+	}
+      cnt=0;
+      fprintf(stderr," ]\n");
+    }
+  fprintf(stderr,"\n");
+}
+// -------------------------------------------------------------
+void shiftdvector(double* v,int shift,int np)
+{
+
+  if (shift==0)
+      return;
+  
+  if (shift>0)
+      {
+	for (int j=1;j<=shift;j++)
+	    {
+	      float vnp=v[np];
+	      for (int i=np;i>1;i=i-1)
+		  v[i]=v[i-1];
+	      v[1]=vnp;
+	    }
+      }
+  if (shift<0)
+      {
+	for (int j=1;j<=abs(shift);j++)
+	    {
+	      float v1=v[1];
+	      for (int i=1;i<np;i++)
+		  v[i]=v[i+1];
+	      v[np]=v1;
+	    }
+      }
+}
+// -------------------------------------------------------------
+void shiftvector(float* v,int shift,int np)
+{
+
+  if (shift==0)
+      return;
+  
+  if (shift>0)
+      {
+	for (int j=1;j<=shift;j++)
+	    {
+	      float vnp=v[np];
+	      for (int i=np;i>1;i=i-1)
+		  v[i]=v[i-1];
+	      v[1]=vnp;
+	    }
+      }
+  if (shift<0)
+      {
+	for (int j=1;j<=abs(shift);j++)
+	    {
+	      float v1=v[1];
+	      for (int i=1;i<np;i++)
+		  v[i]=v[i+1];
+	      v[np]=v1;
+	    }
+      }
+}
+// -------------------------------------------------------------
+void shiftivector(int* v,int shift,int np)
+{
+
+  if (shift==0)
+      return;
+  
+  if (shift>0)
+      {
+	for (int j=1;j<=shift;j++)
+	    {
+	      int vnp=v[np];
+	      for (int i=np;i>1;i=i-1)
+		  v[i]=v[i-1];
+	      v[1]=vnp;
+	    }
+      }
+  if (shift<0)
+      {
+	for (int j=1;j<=abs(shift);j++)
+	    {
+	      int v1=v[1];
+	      for (int i=1;i<np;i++)
+		  v[i]=v[i+1];
+	      v[np]=v1;
+	    }
+      }
+}
+// -------------------------------------------------------------
+
+
+#define VTK_J_ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);\
+        a[k][l]=h+s*(g-h*tau)
+
+#define VTK_J_MAX_ROTATIONS 20
+
+//#undef VTK_J_MAX_ROTATIONS
+
+//#define VTK_J_MAX_ROTATIONS 50
+
+// Jacobi iteration for the solution of eigenvectors/eigenvalues of a nxn
+// real symmetric matrix. Square nxn matrix a; size of matrix in n;
+// output eigenvalues in w; and output eigenvectors in v. Resulting
+// eigenvalues/vectors are sorted in decreasing order; eigenvectors are
+// normalized.
+template<class T>
+static inline int vtk_JacobiN(T **a, int n, T *w, T **v)
+{
+  int i, j, k, iq, ip, numPos;
+  T tresh, theta, tau, t, sm, s, h, g, c, tmp;
+  T bspace[4], zspace[4];
+  T *b = bspace;
+  T *z = zspace;
+
+  // only allocate memory if the matrix is large
+  if (n > 4)
+    {
+    b = new T[n];
+    z = new T[n]; 
+    }
+
+  // initialize
+  for (ip=0; ip<n; ip++) 
+    {
+    for (iq=0; iq<n; iq++)
+      {
+      v[ip][iq] = 0.0;
+      }
+    v[ip][ip] = 1.0;
+    }
+  for (ip=0; ip<n; ip++) 
+    {
+    b[ip] = w[ip] = a[ip][ip];
+    z[ip] = 0.0;
+    }
+
+  // begin rotation sequence
+  for (i=0; i<VTK_J_MAX_ROTATIONS; i++) 
+    {
+    sm = 0.0;
+    for (ip=0; ip<n-1; ip++) 
+      {
+      for (iq=ip+1; iq<n; iq++)
+        {
+        sm += fabs(a[ip][iq]);
+        }
+      }
+    if (sm == 0.0)
+      {
+      break;
+      }
+
+    if (i < 3)                                // first 3 sweeps
+      {
+      tresh = 0.2*sm/(n*n);
+      }
+    else
+      {
+      tresh = 0.0;
+      }
+
+    for (ip=0; ip<n-1; ip++) 
+      {
+      for (iq=ip+1; iq<n; iq++) 
+        {
+        g = 100.0*fabs(a[ip][iq]);
+
+        // after 4 sweeps
+        if (i > 3 && (fabs(w[ip])+g) == fabs(w[ip])
+        && (fabs(w[iq])+g) == fabs(w[iq]))
+          {
+          a[ip][iq] = 0.0;
+          }
+        else if (fabs(a[ip][iq]) > tresh) 
+          {
+          h = w[iq] - w[ip];
+          if ( (fabs(h)+g) == fabs(h))
+            {
+            t = (a[ip][iq]) / h;
+            }
+          else 
+            {
+            theta = 0.5*h / (a[ip][iq]);
+            t = 1.0 / (fabs(theta)+sqrt(1.0+theta*theta));
+            if (theta < 0.0)
+              {
+              t = -t;
+              }
+            }
+          c = 1.0 / sqrt(1+t*t);
+          s = t*c;
+          tau = s/(1.0+c);
+          h = t*a[ip][iq];
+          z[ip] -= h;
+          z[iq] += h;
+          w[ip] -= h;
+          w[iq] += h;
+          a[ip][iq]=0.0;
+
+          // ip already shifted left by 1 unit
+          for (j = 0;j <= ip-1;j++) 
+            {
+            VTK_J_ROTATE(a,j,ip,j,iq);
+            }
+          // ip and iq already shifted left by 1 unit
+          for (j = ip+1;j <= iq-1;j++) 
+            {
+            VTK_J_ROTATE(a,ip,j,j,iq);
+            }
+          // iq already shifted left by 1 unit
+          for (j=iq+1; j<n; j++) 
+            {
+            VTK_J_ROTATE(a,ip,j,iq,j);
+            }
+          for (j=0; j<n; j++) 
+            {
+            VTK_J_ROTATE(v,j,ip,j,iq);
+            }
+          }
+        }
+      }
+
+    for (ip=0; ip<n; ip++) 
+      {
+      b[ip] += z[ip];
+      w[ip] = b[ip];
+      z[ip] = 0.0;
+      }
+    }
+
+  //// this is NEVER called
+  if ( i >= VTK_J_MAX_ROTATIONS )
+    {
+      fprintf(stderr,"vtkMath_Jacobi: Error extracting eigenfunctions\n");
+    return 0;
+    }
+
+  // sort eigenfunctions                 these changes do not affect accuracy 
+  for (j=0; j<n-1; j++)                  // boundary incorrect
+    {
+    k = j;
+    tmp = w[k];
+    for (i=j+1; i<n; i++)                // boundary incorrect, shifted already
+      {
+      if (w[i] >= tmp)                   // why exchage if same?
+        {
+        k = i;
+        tmp = w[k];
+        }
+      }
+    if (k != j) 
+      {
+      w[k] = w[j];
+      w[j] = tmp;
+      for (i=0; i<n; i++) 
+        {
+        tmp = v[i][j];
+        v[i][j] = v[i][k];
+        v[i][k] = tmp;
+        }
+      }
+    }
+  // insure eigenvector consistency (i.e., Jacobi can compute vectors that
+  // are negative of one another (.707,.707,0) and (-.707,-.707,0). This can
+  // reek havoc in hyperstreamline/other stuff. We will select the most
+  // positive eigenvector.
+  int ceil_half_n = (n >> 1) + (n & 1);
+  for (j=0; j<n; j++)
+    {
+    for (numPos=0, i=0; i<n; i++)
+      {
+      if ( v[i][j] >= 0.0 )
+        {
+        numPos++;
+        }
+      }
+//    if ( numPos < ceil(double(n)/double(2.0)) )
+    if ( numPos < ceil_half_n)
+      {
+      for(i=0; i<n; i++)
+        {
+        v[i][j] *= -1.0;
+        }
+      }
+    }
+
+  if (n > 4)
+    {
+    delete [] b;
+    delete [] z;
+    }
+  return 1;
+}
+
+#undef VTK_J_ROTATE
+#undef VTK_J_MAX_ROTATIONS
+
+int vtkMath_JacobiN(float **a, int n, float *w, float **v)
+{
+  return vtk_JacobiN(a,n,w,v);
+}
+
+int vtkMath_JacobiN(double **a, int n, double *w, double **v)
+{
+  return vtk_JacobiN(a,n,w,v);
+}
+// Jacobi iteration for the solution of eigenvectors/eigenvalues of a 3x3
+// real symmetric matrix. Square 3x3 matrix a; output eigenvalues in w;
+// and output eigenvectors in v. Resulting eigenvalues/vectors are sorted
+// in decreasing order; eigenvectors are normalized.
+int vtkMath_Jacobi(float **a, float *w, float **v)
+{
+  return vtkMath_JacobiN(a, 3, w, v);
+}
+
+int vtkMath_Jacobi(double **a, double *w, double **v)
+{
+  return vtkMath_JacobiN(a, 3, w, v);
+}
+
+
diff --git a/bioimagesuite30_src/numerics/nrutil.h b/bioimagesuite30_src/numerics/nrutil.h
new file mode 100644
index 0000000..5b708bf
--- /dev/null
+++ b/bioimagesuite30_src/numerics/nrutil.h
@@ -0,0 +1,181 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+// The top 90% is slightly tweaked from public domain Numerical Recipes Code
+// The bottom 10% is from Pengcheng Shi's code (peng_cheng_util.cpp) and needs to be eliminated
+// (The header file is fine!)
+//
+//---------------------------------------------------------------------------------------------------------
+// New version of nrutil.h function prototypes for use with ANSI C
+// April 3rd 1995
+
+#ifndef _NUM_UTILITIES
+#define _NUM_UTILITIES
+
+#include <math.h>
+
+#ifndef M_PI
+#define M_PI 3.1415927
+#endif
+
+typedef struct FCOMPLEX {float r,i;} fcomplex;
+typedef struct IMMENSE {unsigned long l,r;} immense;
+typedef struct GREAT {unsigned short l,c,r;} great;
+
+void nrerror(const char* error_text);
+
+// Allocation and Freeing of matrices and Vectors
+// ----------------------------------------------
+float  *vector(long nl,long nh);
+double *dvector(long nl,long nh);
+int    *ivector(long nl,long nh);
+
+unsigned char *cvector(long nl, long nh);
+unsigned long *lvector(long nl, long nh);
+
+float **matrix(long nrl, long nrh,long ncl,long nch);
+double **dmatrix(long nrl,long nrh,long ncl,long nch);
+int **imatrix(long nrl,long nrh,long ncl,long nch);
+
+float **submatrix(float a,int oldrl,int oldrh,int oldcl,int oldch,
+		  long newrl,long newcl);
+double **subdmatrix(double a,int oldrl,int oldrh,int oldcl,int oldch,
+		  long newrl,long newcl);
+
+float **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch);
+float ***f3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh);
+
+void free_vector(float* v,long nl,long nh);
+void free_dvector(double* v,long nl,long nh);
+void free_ivector(int *v,long nl,long nh);
+void free_cvector(unsigned char *v, long nl, long nh);
+void free_lvector(unsigned long *v, long nl, long nh);
+
+void free_matrix(float **m,long nrl,long nrh,long ncl,long nch);
+void free_dmatrix(double **m,long nrl,long nrh,long ncl,long nch);
+void free_imatrix(int **m,long nrl,long nrh,long ncl,long nch);
+void free_submatrix(float** b,long nrl,long nrh,long ncl,long nch);
+
+
+void free_convert_matrix(float **b,long nrl,long nrh,long ncl,long nch);
+void free_subdmatrix(double** b,long nrl,long nrh,long ncl,long nch);
+double **convert_dmatrix(double* a,long nrl,long nrh,long ncl,long nch);
+void free_convert_dmatrix(double **b,long nrl,long nrh,long ncl,long nch);
+void free_f3tensor(float ***t, long nrl, long nrh, long ncl, long nch,
+	long ndl, long ndh);
+
+// ---------------------------------------------------------
+// Copy Vectrors and make matrices symmetric (upper triangular = input)
+// ---------------------------------------------------------
+
+void  symmetric(float **a, int n);
+void  copymatrix(float **a,float **b,int rows,int columns);
+void  copyvector(float *a,float *b,int rows);
+
+void  dsymmetric(double **a, int n);
+void  copydmatrix(double **a,double **b,int rows,int columns);
+void  copydvector(double *a,double *b,int rows);
+
+void  isymmetric(int **a, int n);
+void  copyimatrix(int **a,int **b,int rows,int columns);
+void  copyivector(int *a,int *b,int rows);
+
+
+// -----------------------------------------------------------
+//  Diagnostic Routines - print formatted vectors and matrices
+// -----------------------------------------------------------
+void printvector(float* v,int n,const char* fmt,const char* name,int wd=8);
+void printivector(int*  v,int n,const char* fmt,const char* name,int wd=8);
+void printdvector(double* v,int n,const char* fmt,const char* name,int wd=8);
+void printmatrix(float** a,int row,int col,const char* fmt,const char* name,int wd=8,int off=1);
+void printimatrix(int** a,int row,int col,const char* fmt,const char* name,int wd=8,int off=1);
+void printdmatrix(double** a,int row,int col,const char* fmt,const char* name,int wd=8,int off=1);
+
+// -------------------------------------------------------------
+// Shift Vectors
+// -------------------------------------------------------------
+void shiftdvector(double* v,int shift,int np);
+void shiftvector(float* v,int shift,int np);
+void shiftivector(int* v,int shift,int np);
+
+// -------------------------------------------------------------
+// Peng-Cheng Utilities 
+// -------------------------------------------------------------
+
+typedef struct {              
+      	double x;          	/* position 		*/
+      	double y;
+      	double z;
+      	double K;		/* gaussian curvature   */
+      	double H;		/* mean curvature	*/
+      	double k1;		/* principal curvatures */
+      	double k2;      
+      	double k1x;		/* principal directions */
+      	double k1y;
+	double k1z;
+	double k2x;
+	double k2y;
+	double k2z;
+	double nx;		/* normal direction 	*/
+	double ny;
+	double nz;
+}Vertex_3d;
+
+
+typedef struct {              
+      	double x;          	/* position   */
+      	double y;
+	double z;
+}Node_3d;
+
+void matrix_transpose(double** a,double** b, int rowsize,int colsize);
+void matrix_product(double** p, double** a, int rowsize_a, int colsize_a, 
+		    double** b,int /*rowsize_b*/,int colsize_b);
+void matrix_inverse(double** a,double** b, int n);
+void get_eigenvalues_vectors(double** a,int n,double d[],double** v,int* nrot);
+void sort_eigenvalues_vectors(double* d,double** v, int n);
+void lubksb0(double **a,int n,int *indx,double b[]);
+void ludcmp0(double **a,int n,int* indx,double* d,int& singular);
+
+
+
+// This came out of vtkMath, and placed here to eliminate dependency on VTK for px.. files which are
+// also needed for abaqus
+int vtkMath_JacobiN(float **a, int n, float *w, float **v);
+int vtkMath_JacobiN(double **a, int n, double *w, double **v);
+int vtkMath_Jacobi(float **a, float *w, float **v);
+int vtkMath_Jacobi(double **a, double *w, double **v);
+
+#endif /* _NUM_UTILITIES */
+
+
+
+
diff --git a/bioimagesuite30_src/numerics/peng_cheng_util.cpp b/bioimagesuite30_src/numerics/peng_cheng_util.cpp
new file mode 100644
index 0000000..129c016
--- /dev/null
+++ b/bioimagesuite30_src/numerics/peng_cheng_util.cpp
@@ -0,0 +1,588 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//
+//
+//
+//  This File contains the following Numerical Recipes derived code that
+//  will need to be removed prior to it becoming open source
+//
+//  Most of this file needs to be replaced!
+//---------------------------------------------------------------------------------------------------------
+/*
+	This file contains the useful functions which manipulate the
+	various matrix operation.
+
+	Pengcheng Shi
+	April, 1993(revised)
+*/
+
+#include "math.h"
+#include "nrutil.h"
+#include <stdio.h>
+
+
+
+
+/* type definition */
+typedef unsigned char uc;
+
+/* structure definition */
+typedef struct {              
+      	double x;          	/* direction   */
+      	double y;
+}Vector_2d;
+
+typedef struct {              
+      	double x;          	/* direction   */
+      	double y;
+	double z;
+}Vector_3d;
+
+
+typedef struct {              
+      	double x;          	/* position   */
+      	double y;
+	double z;
+	double v;		/* grey value */
+}Image_3d;
+
+typedef struct {              
+      	double x;          	/* position   */
+      	double y;
+}Node_2d;
+
+typedef struct {              
+      	int node1; 
+      	int node2;
+	int node3;
+}Element_2d;
+
+typedef struct {              
+      	int node1; 
+      	int node2;
+	int node3;
+	int node4;
+}Element_3d;
+
+typedef struct {              
+      	int node1; 
+      	int node2;
+	int node3;
+	int node4;
+      	int node5; 
+      	int node6;
+	int node7;
+	int node8;	
+}Element_Cube;
+
+typedef struct {              
+      	double xx;          	
+      	double yy;
+	double zz;
+	double xy;
+      	double yz;
+	double zx;		
+}Strain_3d;
+
+typedef struct {              
+      	double p1;          	
+      	double p2;
+	double p3;
+	double p1x;
+      	double p1y;
+	double p1z;
+	double p2x;
+      	double p2y;
+	double p2z;
+	double p3x;
+      	double p3y;
+	double p3z;		
+}Principal_Strain_3d;
+
+
+typedef struct {              
+      	int link12; 
+      	int link13;
+	int link14;
+      	int link23; 
+      	int link24;
+	int link34;	
+}Type_3d;
+
+
+typedef struct {		
+	double x;		/* position 		*/
+	double y;
+	double z;
+	double e1;
+	double e2;
+	double e3;
+	double nx;		/* principal axis	*/
+	double ny;
+	double nz;
+	double t1x;
+	double t1y;
+	double t1z;
+	double t2x;
+	double t2y;
+	double t2z;
+	double residual;
+}fit_eigens;
+
+
+// ---------------------------------------------------------
+// Code from vtkMath to eliminate some linking dependencies
+// ---------------------------------------------------------
+#define VTK_SMALL_NUMBER 1.0e-12
+
+
+// Factor linear equations Ax = b using LU decompostion A = LU where L is
+// lower triangular matrix and U is upper triangular matrix. Input is 
+// square matrix A, integer array of pivot indices index[0->n-1], and size
+// of square matrix n. Output factorization LU is in matrix A. If error is 
+// found, method returns 0.
+//------------------------------------------------------------------
+// For thread safe, temporary memory array tmpSize of length size
+// must be passed in.
+int vtkMath_pc_LUFactorLinearSystem(double **A, int *index, int size,
+                                  double *tmpSize)
+{
+  int i, j, k;
+  int maxI = 0;
+  double largest, temp1, temp2, sum;
+
+  //
+  // Loop over rows to get implicit scaling information
+  //
+  for ( i = 0; i < size; i++ ) 
+    {
+    for ( largest = 0.0, j = 0; j < size; j++ ) 
+      {
+      if ( (temp2 = fabs(A[i][j])) > largest )
+        {
+        largest = temp2;
+        }
+      }
+
+    if ( largest == 0.0 )
+      {
+      return 0;
+      }
+      tmpSize[i] = 1.0 / largest;
+    }
+  //
+  // Loop over all columns using Crout's method
+  //
+  for ( j = 0; j < size; j++ ) 
+    {
+    for (i = 0; i < j; i++) 
+      {
+      sum = A[i][j];
+      for ( k = 0; k < i; k++ )
+        {
+        sum -= A[i][k] * A[k][j];
+        }
+      A[i][j] = sum;
+      }
+    //
+    // Begin search for largest pivot element
+    //
+    for ( largest = 0.0, i = j; i < size; i++ ) 
+      {
+      sum = A[i][j];
+      for ( k = 0; k < j; k++ )
+        {
+        sum -= A[i][k] * A[k][j];
+        }
+      A[i][j] = sum;
+
+      if ( (temp1 = tmpSize[i]*fabs(sum)) >= largest ) 
+        {
+        largest = temp1;
+        maxI = i;
+        }
+      }
+    //
+    // Check for row interchange
+    //
+    if ( j != maxI ) 
+      {
+      for ( k = 0; k < size; k++ ) 
+        {
+        temp1 = A[maxI][k];
+        A[maxI][k] = A[j][k];
+        A[j][k] = temp1;
+        }
+      tmpSize[maxI] = tmpSize[j];
+      }
+    //
+    // Divide by pivot element and perform elimination
+    //
+    index[j] = maxI;
+
+    if ( fabs(A[j][j]) <= VTK_SMALL_NUMBER )
+      {
+      return 0;
+      }
+
+    if ( j != (size-1) ) 
+      {
+      temp1 = 1.0 / A[j][j];
+      for ( i = j + 1; i < size; i++ )
+        {
+        A[i][j] *= temp1;
+        }
+      }
+    }
+
+  return 1;
+}
+
+
+
+int vtkMath_pc_LUFactorLinearSystem(double **A, int *index, int size)
+{
+  double scratch[10];
+  double *scale = (size<10 ? scratch : new double[size]);
+
+  int i, j, k;
+  int maxI = 0;
+  double largest, temp1, temp2, sum;
+
+  //
+  // Loop over rows to get implicit scaling information
+  //
+  for ( i = 0; i < size; i++ ) 
+    {
+    for ( largest = 0.0, j = 0; j < size; j++ ) 
+      {
+      if ( (temp2 = fabs(A[i][j])) > largest )
+        {
+        largest = temp2;
+        }
+      }
+
+    if ( largest == 0.0 )
+      {
+      return 0;
+      }
+      scale[i] = 1.0 / largest;
+    }
+  //
+  // Loop over all columns using Crout's method
+  //
+  for ( j = 0; j < size; j++ ) 
+    {
+    for (i = 0; i < j; i++) 
+      {
+      sum = A[i][j];
+      for ( k = 0; k < i; k++ )
+        {
+        sum -= A[i][k] * A[k][j];
+        }
+      A[i][j] = sum;
+      }
+    //
+    // Begin search for largest pivot element
+    //
+    for ( largest = 0.0, i = j; i < size; i++ ) 
+      {
+      sum = A[i][j];
+      for ( k = 0; k < j; k++ )
+        {
+        sum -= A[i][k] * A[k][j];
+        }
+      A[i][j] = sum;
+
+      if ( (temp1 = scale[i]*fabs(sum)) >= largest ) 
+        {
+        largest = temp1;
+        maxI = i;
+        }
+      }
+    //
+    // Check for row interchange
+    //
+    if ( j != maxI ) 
+      {
+      for ( k = 0; k < size; k++ ) 
+        {
+        temp1 = A[maxI][k];
+        A[maxI][k] = A[j][k];
+        A[j][k] = temp1;
+        }
+      scale[maxI] = scale[j];
+      }
+    //
+    // Divide by pivot element and perform elimination
+    //
+    index[j] = maxI;
+
+    if ( fabs(A[j][j]) <= VTK_SMALL_NUMBER )
+      {
+      return 0;
+      }
+
+    if ( j != (size-1) ) 
+      {
+      temp1 = 1.0 / A[j][j];
+      for ( i = j + 1; i < size; i++ )
+        {
+        A[i][j] *= temp1;
+        }
+      }
+    }
+
+  if (size >= 10 ) delete [] scale;
+
+  return 1;
+}
+
+
+// Solve linear equations Ax = b using LU decompostion A = LU where L is
+// lower triangular matrix and U is upper triangular matrix. Input is 
+// factored matrix A=LU, integer array of pivot indices index[0->n-1],
+// load vector x[0->n-1], and size of square matrix n. Note that A=LU and
+// index[] are generated from method LUFactorLinearSystem). Also, solution
+// vector is written directly over input load vector.
+void vtkMath_pc_LUSolveLinearSystem(double **A, int *index, 
+                                  double *x, int size)
+{
+  int i, j, ii, idx;
+  double sum;
+//
+// Proceed with forward and backsubstitution for L and U
+// matrices.  First, forward substitution.
+//
+  for ( ii = -1, i = 0; i < size; i++ ) 
+    {
+    idx = index[i];
+    sum = x[idx];
+    x[idx] = x[i];
+
+    if ( ii >= 0 )
+      {
+      for ( j = ii; j <= (i-1); j++ )
+        {
+        sum -= A[i][j]*x[j];
+        }
+      }
+    else if (sum)
+      {
+      ii = i;
+      }
+
+    x[i] = sum;
+  }
+//
+// Now, back substitution
+//
+  for ( i = size-1; i >= 0; i-- ) 
+    {
+    sum = x[i];
+    for ( j = i + 1; j < size; j++ )
+      {
+      sum -= A[i][j]*x[j];
+      }
+    x[i] = sum / A[i][i];
+    }
+}
+
+// Invert input square matrix A into matrix AI. Note that A is modified during
+// the inversion. The size variable is the dimension of the matrix. Returns 0
+// if inverse not computed.
+// -----------------------
+// For thread safe behavior, temporary arrays tmp1SIze and tmp2Size
+// of length size must be passsed in.
+int vtkMath_pc_InvertMatrix(double **A, double **AI, int size,
+                          int *tmp1Size, double *tmp2Size)
+{
+  int i, j;
+
+  //
+  // Factor matrix; then begin solving for inverse one column at a time.
+  // Note: tmp1Size returned value is used later, tmp2Size is just working
+  // memory whose values are not used in LUSolveLinearSystem
+  //
+  if ( vtkMath_pc_LUFactorLinearSystem(A, tmp1Size, size, tmp2Size) == 0 )
+    {
+    return 0;
+    }
+  
+  for ( j=0; j < size; j++ )
+    {
+    for ( i=0; i < size; i++ )
+      {
+      tmp2Size[i] = 0.0;
+      }
+    tmp2Size[j] = 1.0;
+
+    vtkMath_pc_LUSolveLinearSystem(A,tmp1Size,tmp2Size,size);
+
+    for ( i=0; i < size; i++ )
+      {
+      AI[i][j] = tmp2Size[i];
+      }
+    }
+
+  return 1;
+}
+
+
+// Invert input square matrix A into matrix AI. Note that A is modified during
+// the inversion. The size variable is the dimension of the matrix. Returns 0
+// if inverse not computed.
+int vtkMath_pc_InvertMatrix(double **A, double **AI, int size)
+{
+  int *index=NULL, iScratch[10];
+  double *column=NULL, dScratch[10];
+
+  // Check on allocation of working vectors
+  //
+  if ( size < 10 ) 
+    {
+    index = iScratch;
+    column = dScratch;
+    } 
+
+  int retVal = vtkMath_pc_InvertMatrix(A, AI, size, index, column);
+
+  if ( size >= 10 ) 
+    {
+    delete [] index;
+    delete [] column;
+    } 
+  
+  return retVal;
+}
+
+
+
+
+#undef VTK_SMALL_NUMBER
+
+
+/* given a matrix a[rowsize][colsize], get   */
+/* its transpose matrix  b[colsize][rowsize] */
+void matrix_transpose(double** a,double** b, int rowsize,int colsize)
+{
+  for(int i=0; i<rowsize; i++)
+    for(int j=0; j<colsize; j++)
+      b[j][i] = a[i][j];
+}
+
+
+/* given two matrices a[rowsize_a][colsize_a] and b[rowsize_b][colsize_b], */
+/* get the product matrix p[rowsize_a][colsize_b]			   */
+void matrix_product(double** p, double** a, int rowsize_a, int colsize_a, 
+		    double** b,int /*rowsize_b*/,int colsize_b)
+{
+  for(int i=0; i<rowsize_a; i++)
+    for(int j=0; j<colsize_b; j++)
+      {
+	p[i][j]=0.0;
+	for(int m=0; m<colsize_a; m++)
+	  p[i][j] += a[i][m] * b[m][j];
+      }
+}
+
+
+// --------------------------------------------------------------------------------
+//
+//                  End of VTK Derived Code Here
+//                
+// --------------------------------------------------------------------------------
+
+
+
+/* given matrix a[n][n], get the inverse matrix b[n][n] */
+
+void matrix_inverse(double** a,double** b, int n)
+{
+  vtkMath_pc_InvertMatrix(a,b,n);
+  return;
+
+  //The following code is commented out, 
+  //It is left there for Legacy purposes only
+
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+}
+
+
+
+
+
+void ludcmp0(double **a,int n,int* indx,double* d,int& singular)
+{
+
+  singular=vtkMath_pc_LUFactorLinearSystem(a,indx,n);
+  return;
+
+
+  //The following code is commented out, 
+  //It is left there for Legacy purposes only
+
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+}
+
+void lubksb0(double **a,int n,int *indx,double b[])
+{
+  vtkMath_pc_LUSolveLinearSystem(a,indx,b,n);
+  return;
+  //The following code is commented out, 
+  //It is left there for Legacy purposes only
+
+  //This code derives from Numerical Recipes in C
+		//BEGIN OMITTED
+		// Some lines of  code have been removed as they
+		// derive/depend on the presence of code from the book Numerical Recipes in C
+		// which can not be distributed in source form.
+		// We have REPLACED the missing code with an alternative version
+		// ... see below. The missing code is not mostly OBSOLETE.
+		//END OMITTED
+
+}
+
+
+
diff --git a/bioimagesuite30_src/numerics/px3dimage.cpp b/bioimagesuite30_src/numerics/px3dimage.cpp
new file mode 100644
index 0000000..60aaf81
--- /dev/null
+++ b/bioimagesuite30_src/numerics/px3dimage.cpp
@@ -0,0 +1,832 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+#include "px3dimage.h"
+#include "bis_znzlib.h"
+
+//-----------------------------------------------------------------------
+PX3DImage::PX3DImage(int x ,int y,int z,
+		     int wd):PXImage(x*wd,y*((z+wd-1)/wd)) 
+{
+  init();
+  zsize=z;
+  norows=(z+wd-1)/wd;
+  nocolumns=wd;
+  partwidth=x;
+  partheight=y;
+}
+
+//-----------------------------------------------------------------------
+PX3DImage::PX3DImage(const char* f,int cwidth):PXImage()
+{
+  init();
+  xsize=0;   ysize=0;  maxgrayscale=0;    status=0;		
+  zsize=0;   partheight=0; partwidth=0; nocolumns=cwidth;
+
+  filename=new char[1];
+  setfilename(f);
+  CheckAnaFilename(1);                // Check Files Present;
+  if (status==1)
+    {
+      Anagetparams(f,partwidth,partheight,zsize,numbytes);
+      if (nocolumns==-1)
+	{
+	  nocolumns=(int)sqrt(float(zsize));
+	  if (zsize>nocolumns*nocolumns) nocolumns++;
+	}
+      if (nocolumns==0)
+	nocolumns=zsize;
+      
+      norows=(zsize+nocolumns-1)/nocolumns;
+      xsize=partwidth*nocolumns;
+      ysize=partheight*norows;
+      Load();
+      fprintf(stderr,"Size = %d*%d*%d numbytes=%d\n",partwidth,partheight,zsize,numbytes);
+    }
+
+}
+
+//-----------------------------------------------------------------------
+PX3DImage::PX3DImage(const char* f,int first,int last,int increment,
+		     int cwidth):PXImage()
+	
+{
+  init();
+  filename=new char[1];
+  status=0;		
+  nocolumns=cwidth;
+  setfilename(f);
+  CheckAnaFilename(1);                // Check  File Names First;
+
+  if (status==1)
+    {
+      Anagetparams(filename,partwidth,partheight,zsize,numbytes);
+      if (last>zsize) last=zsize;
+      if (first<1) first=1;
+      if (last<first) last=first;
+      if (increment>(last-first)) increment=last-first;
+      if (increment<1) increment=1;      
+
+      zsize=(last-first+increment)/increment;
+
+      if (nocolumns==-1)
+	{
+	  nocolumns=(int)sqrt(float(zsize));
+	  if (zsize>nocolumns*nocolumns) nocolumns++;
+	}
+      if (nocolumns==0)
+	nocolumns=zsize;
+      
+      norows=(zsize+nocolumns-1)/nocolumns;
+      xsize=partwidth*nocolumns;
+      ysize=partheight*((zsize+nocolumns-1)/nocolumns);
+      
+      if (status==1) LoadPart(first,last,increment);
+    }
+}
+//-----------------------------------------------------------------------
+PX3DImage::PX3DImage(PX3DImage *Sequence[],int n)  // 3D Stack Constructor
+{
+  init();
+  filename=new char[1];
+  partwidth= Sequence[0]->get3dsizex();
+  partheight=Sequence[0]->get3dsizey();
+  zsize=n*Sequence[0]->get3dsizez();
+
+  if (partwidth>0 && partheight>0 && zsize>0)
+      {
+	xsize=partwidth;
+	ysize=partheight;
+	
+	image=new unsigned short[get3dsizex()*get3dsizey()*get3dsizez()];
+	
+	for (int fr=0;fr<n;fr++)
+	    {
+	      for(int k=0;k<Sequence[0]->get3dsizez();k++)
+		  for(int i=0;i<get3dsizex();i++)
+		      for(int j=0;j<get3dsizey();j++)
+			  setvoxel(i,j,k+fr*Sequence[0]->get3dsizez(),
+				   Sequence[k]->getvoxel(i,j,k)
+				   );
+	    }
+	status=1;
+      }
+  else
+      {
+	partwidth=0;
+	partheight=0;
+	status=0;
+      }
+}
+//-----------------------------------------------------------------------
+PX3DImage::PX3DImage(PXImage *Sequence[],int length,int cwidth,
+		     int x0,int y0,int x1,int y1):PXImage()
+{
+  init();
+  filename=new char[1];
+  
+  if (x0==0 && y0==0 && x1==-1 && y1==-1)
+      {
+	for (int i=0;i<length;i++)
+	    {
+	      x1=Imax(x1,Sequence[i]->getsizex());
+	      y1=Imax(y1,Sequence[i]->getsizey());
+	    }
+	x1-=1;
+	y1-=1;
+      }
+  else
+      {
+	if (x1==-1 || x1>=Sequence[0]->getsizex()) x1=Sequence[0]->getsizex()-1;
+	if (y1==-1 || y1>=Sequence[0]->getsizey()) y1=Sequence[0]->getsizey()-1;
+      }
+  partheight=y1-y0+1;
+  partwidth =x1-x0+1;
+  nocolumns=cwidth;
+  zsize=length;   
+  if (nocolumns==-1)
+    {
+      nocolumns=(int)sqrt(float(zsize));
+      if (zsize>nocolumns*nocolumns) nocolumns++;
+    }
+  if (nocolumns==0)
+    nocolumns=zsize;
+
+  norows=(zsize+nocolumns-1)/nocolumns;
+  xsize=partwidth*nocolumns;   
+  ysize=partheight*norows;
+
+  maxgrayscale=0;    
+  status=0;		
+  char* ff=new char[500];
+  sprintf(ff,"%s_st",eatsuffix(Sequence[0]->getfilename()));
+  setfilename(ff);
+  delete [] ff;
+
+  if (zsize>0 && xsize>0 && ysize>0)
+    {
+      image=new unsigned short[get3dsizex()*get3dsizey()*get3dsizez()];
+
+      for(int k=0;k<get3dsizez();k++)
+	  {
+	    if (get3dsizex()==Sequence[k]->getsizex() && get3dsizey()==Sequence[k]->getsizey())
+		{
+		  for(int i=0;i<get3dsizex();i++)
+		      for(int j=0;j<get3dsizey();j++)
+			setvoxel(i,j,k,Sequence[k]->getpixel(x0+i,y0+j));
+		}
+	    else
+		{
+		  int dx=(get3dsizex()-Sequence[k]->getsizex())/2;
+		  int dy=(get3dsizey()-Sequence[k]->getsizey())/2;
+		  fprintf(stderr,"Frame = %d , sizes = %d*%d , %d*%d offsets=%d,%d\n",
+			  k,get3dsizex(),get3dsizey(),Sequence[k]->getsizex(),Sequence[k]->getsizey(),
+			  dx,dy);
+		  for (int i=0;i<get3dsizex();i++)
+		      for (int j=0;j<get3dsizey();j++)
+			  {
+			    if (i>=dx && i<Sequence[k]->getsizex()+dx && 
+				j>=dy && j<Sequence[k]->getsizey()+dy)
+				setvoxel(i,j,k,Sequence[k]->getpixel(x0+i-dx,y0+j-dy));
+			    else
+				setvoxel(i,j,k,Sequence[k]->getmaxgrayscale());
+			  }
+		}
+	    status=1;
+	    SetMaxgrayscale();
+	    fprintf(stderr,"size = %d * %d , max=%d \n",partwidth,partheight,getmaxgrayscale());
+	  }
+    }
+}
+//-----------------------------------------------------------------------
+
+PX3DImage::PX3DImage(PX3DImage* OldImage)
+
+{
+  init();
+  // ****  Copy 2d - Sizes ****;
+  filename=new char[1];
+  xsize=OldImage->getsizex();
+  ysize=OldImage->getsizey();
+
+
+  // **** Copy 3d - Sizes ****;
+
+  zsize=OldImage->get3dsizez();
+  partwidth=OldImage->get3dsizex();
+  partheight=OldImage->get3dsizey();
+
+  // **** Copy 2.5 D - Sizes ****;
+
+  norows=OldImage->getnorows();
+  nocolumns=OldImage->getnocolumns();
+
+  // **** Copy Graylevel maximum ****;
+
+  maxgrayscale=OldImage->getmaxgrayscale();
+
+  // **** Copy Filename related ****;
+
+  setfilename(OldImage->getfilename());
+  
+  // **** Copy Actual Image ****;
+
+  image=new unsigned short[xsize*ysize];
+  for(int i=0;i<partwidth;i++)
+    for(int j=0;j<partheight;j++) 
+      for(int k=0;k<zsize;k++)
+	setvoxel(i,j,k,OldImage->getvoxel(i,j,k));
+
+  // **** Copy Status ****;
+
+  status=OldImage->isvalid();
+  
+  polarmode=OldImage->getpolarmode();
+  outplanescale=OldImage->getoutplanescale();
+}
+
+//-----------------------------------------------------------------------
+PX3DImage::~PX3DImage()
+{
+
+}
+//-----------------------------------------------------------------------
+void PX3DImage::init()
+{
+  polarmode=0;
+  outplanescale=1.0;
+}
+//-----------------------------------------------------------------------
+float PX3DImage::get3dinterp(float x,float y,float z)
+{	 
+  z=z/outplanescale;
+
+  x=Frange(x,0.0,float(get3dsizex()-1));
+  y=Frange(y,0.0,float(get3dsizey()-1));
+  z=Frange(z,0.0,float(get3dsizez()-1));
+
+  int x1=(int)x;
+  int y1=(int)y;
+  int z1=(int)z;
+
+  int x2=x1+1;
+  int y2=y1+1;
+  int z2=z1+1;
+
+  if (x2>=get3dsizex())
+      x2=get3dsizex()-2;
+  if (y2>=get3dsizey())
+      y2=get3dsizey()-2;
+  if (z2>=get3dsizez())
+      z2=get3dsizez()-2;
+
+  return ((float)getvoxel(x1,y1,z1)*(x2-x)*(y2-y)*(z2-z)+
+	  (float)getvoxel(x1,y2,z1)*(x2-x)*(y-y1)*(z2-z)+
+	  (float)getvoxel(x2,y1,z1)*(x-x1)*(y2-y)*(z2-z)+
+	  (float)getvoxel(x2,y2,z1)*(x-x1)*(y-y1)*(z2-z)+
+	  (float)getvoxel(x1,y1,z2)*(x2-x)*(y2-y)*(z-z1)+
+	  (float)getvoxel(x1,y2,z2)*(x2-x)*(y-y1)*(z-z1)+
+	  (float)getvoxel(x2,y1,z2)*(x-x1)*(y2-y)*(z-z1)+
+	  (float)getvoxel(x2,y2,z2)*(x-x1)*(y-y1)*(z-z1));
+}
+//-----------------------------------------------------------------------
+//  I/O Related Code
+//-----------------------------------------------------------------------
+/*
+   Analyse Format .hdr in `filename' and .img in `comment'
+*/
+//-----------------------------------------------------------------------
+
+int PX3DImage::LoadBin(const char* fname,int numbytes,int offset)
+{
+  int n=0,nu=0,i=0,j=0,k=0;
+  gzFile fp;
+  unsigned short *pp=NULL;
+  unsigned char  *ppchar=NULL;
+  fprintf(stderr,"LoadBin %s\n",fname);
+
+  fp=gzsuffixopen(fname,"rb");
+  if (fp)
+      {
+	if (offset>0)
+	    n +=gzseek (fp,offset,0);
+	
+	int sz=partheight*partwidth;
+	if (numbytes==2)
+	    pp=new unsigned short[sz];
+	else
+	    ppchar=new unsigned char[sz];
+	
+	image=new unsigned short[xsize*ysize];
+	for(int imageno=0;imageno<get3dsizez();imageno++)
+	    {
+	      if (numbytes==2)
+		  {
+		    nu +=gzread(fp,&pp[0],sz*2);
+		    for (j=0;j<partheight;j++)
+			for (i=0;i<partwidth;i++)
+			    setvoxel(i,j,k,pp[j*partwidth+i]);
+		    
+		  }
+	      else
+		  {
+		    nu +=gzread(fp,&ppchar[0],sz);
+		    for (j=0;j<partheight;j++)
+			for (i=0;i<partwidth;i++)
+			    setvoxel(i,j,k,ppchar[j*partwidth+i]);
+		    
+		  }
+	      k++;
+	    }
+	SetMaxgrayscale();
+	gzclose(fp);
+	if (numbytes==2)
+	    delete [] pp;
+	else
+	    delete [] ppchar;
+	status=1;
+      }
+  else
+      {
+	fprintf(stderr," LoadBin:: Could not open file %s\n", fname);
+	status=(0);
+      }
+  return status;
+}
+//-----------------------------------------------------------------------
+int PX3DImage::Load()
+{
+  return LoadPart(1,zsize,1);
+}
+
+//-----------------------------------------------------------------------
+
+int PX3DImage::LoadPart(int start,int end,int increment)
+{
+  int n=0,nu=0,i=0,j=0,k=0,sz=0;
+  unsigned short *pp=NULL;
+  unsigned char  *ppchar=NULL;
+
+  char* fname=anacreateimagefilename(filename);
+  gzFile fp=gzsuffixopen(fname,"r");
+  
+  if (fp!=Z_NULL)
+      {
+	if (start>1)
+	    {
+	      sz=(start-1)*partheight*partwidth;
+	      n +=gzseek (fp,sz*numbytes,0);
+	    }
+	sz=partheight*partwidth;
+	if (numbytes==2)
+	    pp=new unsigned short[sz];
+	else
+	    ppchar=new unsigned char[sz];
+	
+	image=new unsigned short[xsize*ysize];
+	for(int imageno=start;imageno<=end;imageno=imageno+increment)
+	    {
+	      if (numbytes==2)
+		  {
+		    nu +=gzread(fp,&pp[0],sz*2);
+		    for (j=0;j<partheight;j++)
+			for (i=0;i<partwidth;i++)
+			    setvoxel(i,j,k,pp[j*partwidth+i]);
+		    
+		  }
+	      else
+		  {
+		    nu +=gzread(fp,&ppchar[0],sz);
+		    for (j=0;j<partheight;j++)
+			for (i=0;i<partwidth;i++)
+			    setvoxel(i,j,k,ppchar[j*partwidth+i]);
+		    
+		  }
+	      k++;
+	      if (increment>1)
+		  n += gzseek(fp,sz*numbytes*(increment-1),1);
+	    }
+	SetMaxgrayscale();
+	gzclose(fp);
+	if (numbytes==2)
+	    delete [] pp;
+	else
+	    delete [] ppchar;
+	status=1;
+      }
+  else
+      {
+	fprintf(stderr," LoadPart:: Could not open file %s\n", fname);
+	status=(0);
+      }
+  delete [] fname;
+  return status;
+}
+
+//-----------------------------------------------------------------------
+int PX3DImage::Save(const char* fname)
+{
+  setfilename(fname);
+  return Save();
+}
+
+int PX3DImage::Save()
+{
+  SetMaxgrayscale();
+  anaimagedata *hdr=new anaimagedata;
+  hdr->zsize=zsize;
+  hdr->xsize=partwidth;
+  hdr->ysize=partheight;
+  hdr->zasp=outplanescale; hdr->yasp=1.0;hdr->xasp=1.0;
+  hdr->zpix=1; hdr->ypix=1;hdr->xpix=1;
+  hdr->minpix=0;hdr->maxpix=getmaxgrayscale();
+  hdr->trueminpix=0; hdr->truemaxpix=getmaxgrayscale();
+  hdr->orient=polarmode*5;
+  int bits=16;
+  if (getmaxgrayscale()<256)
+      bits=8;
+  writeanahdr(filename,hdr,bits);
+  delete hdr;
+  return SaveImg();
+}
+
+//-----------------------------------------------------------------------
+
+int PX3DImage::SaveImg(int bits)
+{
+  if (bits!=8 && bits!=16)
+      {
+	if (getmaxgrayscale()<256)
+	    bits=8;
+	else
+	    bits=16;
+      }
+  char* fname=anacreateimagefilename(filename);
+  int sz=get3dsizex()*get3dsizey();
+  long bytes=0;
+  gzFile fdf=gzsuffixopen(fname,"wb");
+  if (fdf)
+      {
+	if (bits==8) 
+	    {
+	      unsigned char* temp=new unsigned char[sz];
+	      for (int k=0;k<get3dsizez();k++)
+		  {
+		    for (int j=0;j<get3dsizey();j++)
+			for (int i=0;i<get3dsizex();i++)
+			    temp[j*get3dsizex()+i]=getvoxel(i,j,k);
+		    bytes += gzwrite(fdf,&temp[0],sz);
+		  }
+	      delete [] temp;
+	    }
+	else
+	    {
+	      unsigned short* temp=new unsigned short[sz];
+	      for (int k=0;k<get3dsizez();k++)
+		  {
+		    for (int j=0;j<get3dsizey();j++)
+			for (int i=0;i<get3dsizex();i++)
+			    temp[j*get3dsizex()+i]=getvoxel(i,j,k);
+		    bytes += gzwrite(fdf,&temp[0],sz*2);
+		  }
+	      delete [] temp;
+	    }
+	fprintf(stderr,"Image saved in : %s (%d,%d)\n", fname , int(bytes) , bits);
+      }
+  else 
+      {
+	fprintf(stderr,"SaveImg :: Could not write file %s\n" , fname);
+      }
+  gzclose(fdf);
+  delete [] fname;
+  return (bytes>0);
+}
+
+//-----------------------------------------------------------------------
+void PX3DImage::CheckAnaFilename(int mode)
+{
+  status=1;
+  switch (mode) 
+      {
+      case 1 :
+	{
+	  char* fname=anacreateheaderfilename(filename);
+	  gzFile fin=gzsuffixopen(fname,"r");
+	  if (fin==Z_NULL) 
+	      status=0;
+	  else
+	      gzclose(fin);
+	  delete [] fname;
+	  
+	  if (status==1)
+	      {
+		char* fname2=anacreateimagefilename(filename);
+		fin=gzsuffixopen(fname2,"r");
+		if (!fin) 
+		    status=0;
+		else
+		    gzclose(fin);
+		delete [] fname2;
+	      }
+	  break;
+	}
+      case 2 :
+	{
+	  char* fname=anacreateheaderfilename(filename);
+	  FILE* fout=fopen(fname,"w");
+	  if (!fout) status=0;
+	  fclose(fout);
+	  delete [] fname;
+	  break;
+	}
+      }
+}
+
+//-----------------------------------------------------------------------
+void PX3DImage::Add3DContour(PXContour* contour,unsigned short grl,
+			     unsigned char touching,
+			     int offx,int offy,int offz)
+{
+  int px=getpixelx(offx,offy,offz);
+  int py=getpixely(offx,offy,offz);
+  AddContour(contour,grl,touching,px,py);
+}
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+
+void PX3DImage::Scale(float scale)
+{
+  PXImage::Scale(scale);
+  partheight=int(partheight*scale);
+  partwidth=int(partwidth*scale);
+}
+//-----------------------------------------------------------------------
+// [D] Get Slices 
+//
+//      getslicex(int x0) -- returns plane x=x0
+//     
+// ----------------------------------------------------------------------
+
+unsigned char* PX3DImage::getslicex(int x,float gamma,int numbytes)
+{
+  numbytes=Irange(numbytes,1,2);
+  unsigned char *imageyz=new unsigned char[get3dsizey()*get3dsizez()*numbytes];
+  for (int iz=0;iz<get3dsizez();iz++)
+      for (int iy=0;iy<get3dsizey();iy++)
+	  {
+	    imageyz[iy*numbytes+iz*get3dsizey()*numbytes]=adjust(float(getvoxel(x,iy,iz)),gamma);
+	    if (numbytes==2)
+		imageyz[iy*numbytes+iz*get3dsizey()*numbytes+1]=255;
+	  }
+
+  return imageyz;
+}
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+unsigned char* PX3DImage::getslicey(int y,float gamma,int numbytes)
+{
+  numbytes=Irange(numbytes,1,2);
+  unsigned char *imagexz=new unsigned char[get3dsizex()*get3dsizez()*numbytes];
+  for (int iz=0;iz<get3dsizez();iz++)
+      for (int ix=0;ix<get3dsizex();ix++)
+	  {
+	    imagexz[ix*numbytes+iz*get3dsizex()*numbytes]=adjust(float(getvoxel(ix,y,iz)),gamma);
+	    if (numbytes==2)
+		imagexz[ix*numbytes+iz*get3dsizex()*numbytes+1]=255;
+	  }
+  return imagexz;
+}
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+unsigned char* PX3DImage::getslicez(int z,float gamma,int numbytes) 
+{
+  numbytes=Irange(numbytes,1,2);
+  unsigned char *imagexy=new unsigned char[get3dsizex()*get3dsizey()*numbytes];
+  for (int iy=0;iy<get3dsizey();iy++)
+      for (int ix=0;ix<get3dsizex();ix++)
+	  {
+	    imagexy[ix*numbytes+iy*get3dsizex()*numbytes]=adjust(float(getvoxel(ix,iy,z)),gamma);
+	    if (numbytes==2)
+		imagexy[ix*numbytes+iy*get3dsizex()*numbytes+1]=255;
+	  }
+
+  return imagexy;
+}
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+unsigned char* PX3DImage::getinterpslicex(float x,float gamma,int numbytes)
+{
+  numbytes=Irange(numbytes,1,2);
+  unsigned char *imageyz=new unsigned char[get3dsizey()*get3dsizez()*numbytes];
+  for (int iz=0;iz<get3dsizez();iz++)
+      for (int iy=0;iy<get3dsizey();iy++)
+	  {
+	    imageyz[iy*numbytes+iz*get3dsizey()*numbytes]=
+		adjust(get3dinterp(x,float(iy),float(iz)),gamma);
+	    if (numbytes==2)
+		imageyz[iy*numbytes+iz*get3dsizey()*numbytes+1]=255;
+	  }
+  return imageyz;
+}
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+unsigned char* PX3DImage::getinterpslicey(float y,float gamma,int numbytes)
+{
+  numbytes=Irange(numbytes,1,2);
+  unsigned char *imagexz=new unsigned char[get3dsizex()*get3dsizez()*numbytes];
+  for (int iz=0;iz<get3dsizez();iz++)
+      for (int ix=0;ix<get3dsizex();ix++)
+	  {
+	    imagexz[ix*numbytes+iz*get3dsizex()*numbytes]=adjust(get3dinterp(float(ix),y,float(iz)),gamma);
+	    if (numbytes==2)
+		imagexz[ix*numbytes+iz*get3dsizex()*numbytes+1]=255;
+	  }
+  return imagexz;
+}
+//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
+unsigned char* PX3DImage::getinterpslicez(float z,float gamma,int numbytes) 
+{
+  numbytes=Irange(numbytes,1,2);
+  unsigned char *imagexy=new unsigned char[get3dsizex()*get3dsizey()*numbytes];
+  for (int iy=0;iy<get3dsizey();iy++)
+      for (int ix=0;ix<get3dsizex();ix++)
+	  {
+	    imagexy[ix*numbytes+iy*get3dsizex()*numbytes]=adjust(get3dinterp(float(ix),float(iy),z),gamma);
+	    if (numbytes==2)
+		{
+		  imagexy[ix*numbytes+iy*get3dsizex()*numbytes+1]=255;
+		}
+	  }
+  return imagexy;
+}
+//-----------------------------------------------------------------------
+// Ultrasound images related code 
+//-----------------------------------------------------------------------
+unsigned short PX3DImage::get3dechovoxel(float x,float y,float z,float middlex)
+{
+  if (middlex<0.0) middlex=(get3dsizex())/2.0;
+  float slice_y=Frange(z,0.0,(float)get3dsizey()-1);
+
+  float px=float(x)-middlex;
+  float py=float(y)-middlex;
+
+  float radius=sqrt(px*px+py*py);
+  float theta=atan2(py,px)*180.0/M_PI;
+  if (theta< (000.0-0.5*outplanescale)) theta+=180.0;
+  if (theta>=(180.0-0.5*outplanescale)) theta-=180.0;
+  float slice_z=fabs(theta)/outplanescale;
+  
+  int slice_no=int(slice_z+0.5);
+	    
+  if (py<0.0 && slice_no!=0)  radius=-radius;
+  if (slice_no==0 && px<0.0)  radius=-radius;
+  slice_no=Irange(slice_no,0,get3dsizez()-1);
+  float slice_x=radius+middlex;
+  if (slice_x>=0 && slice_x<get3dsizex())
+      return getvoxel(int(slice_x+0.5),int(slice_y+0.5),slice_no);
+  else
+      return 0;
+}
+//-----------------------------------------------------------------------
+unsigned char* PX3DImage::getechoslicexy(float zlevel,float gamma,int numbytes,float middlex)
+{
+  if (middlex<0.0)   middlex=(get3dsizex())/2.0;
+  numbytes=Irange(numbytes,1,2);
+
+  unsigned char *imagexy=new unsigned char[get3dsizex()*get3dsizex()*numbytes];
+
+  
+  for (int iy=0;iy<get3dsizex();iy++)
+      for (int ix=0;ix<get3dsizex();ix++)
+	  {
+	    imagexy[iy*get3dsizex()*numbytes+ix*numbytes]=
+		adjust(get3dechovoxel(float(ix),float(iy),zlevel,middlex),gamma);
+	    if (numbytes==2)
+		{
+		  float radius=sqrt(pow(float(ix)-middlex,float(2.0))+
+				    pow(float(iy)-middlex,float(2.0)));
+		  if (fabs(radius)<middlex-5)
+		      imagexy[iy*get3dsizex()*numbytes+ix*numbytes+1]=255;
+		  else
+		      imagexy[iy*get3dsizex()*numbytes+ix*numbytes+1]=0;
+		}
+	  }
+  return imagexy;
+}
+//-----------------------------------------------------------------------
+unsigned char* PX3DImage::getechoslicetheta(int slice,float gamma,int numbytes)
+{
+  unsigned char* texture=getslicez(slice,gamma,numbytes);
+  
+  if (numbytes==2)
+      {
+	for (int iy=0;iy<get3dsizey();iy++)
+	    for (int ix=0;ix<get3dsizex();ix++)
+		{
+		  unsigned char a=texture[iy*get3dsizex()*2+ix*2];
+		  if (a>250)
+		      texture[iy*get3dsizex()*2+ix*2+1]=0;
+		  else
+		      texture[iy*get3dsizex()*2+ix*2+1]=255;
+		}
+      }
+  return texture;
+}
+//-----------------------------------------------------------------------
+int PX3DImage::saveArray(const char* filename,PX3DImage** sequence,int numf)
+{
+
+  int maxg=0;
+  for (int i=0;i<numf;i++)
+      {
+	sequence[i]->SetMaxgrayscale();
+	maxg=Imax(maxg,sequence[i]->getmaxgrayscale());
+      }
+
+  anaimagedata *hdr=new anaimagedata;
+  hdr->zsize=sequence[0]->get3dsizez()*numf;
+  hdr->xsize=sequence[0]->get3dsizex();
+  hdr->ysize=sequence[0]->get3dsizey();
+
+  hdr->zasp=sequence[0]->getoutplanescale();
+  hdr->yasp=1.0;hdr->xasp=1.0;
+  hdr->zpix=1; hdr->ypix=1;hdr->xpix=1;
+  hdr->minpix=0;hdr->maxpix=maxg;
+  hdr->trueminpix=0; hdr->truemaxpix=maxg;
+  hdr->orient=sequence[0]->getpolarmode()*5;
+  int bits=16;
+  if (maxg<256)
+      bits=8;
+  writeanahdr(filename,hdr,bits);
+  
+  char* fname=anacreateimagefilename(filename);
+  int sz=sequence[0]->get3dsizex()*sequence[0]->get3dsizey();
+  long bytes=0;
+
+  gzFile fdf=gzsuffixopen(fname,"wb");
+  if (fdf)
+      {
+	if (bits==8) 
+	    {
+	      unsigned char* temp=new unsigned char[sz];
+	      for (int t=0;t<numf;t++)
+		  for (int k=0;k<sequence[0]->get3dsizez();k++)
+		      {
+			for (int j=0;j<sequence[0]->get3dsizey();j++)
+			    for (int i=0;i<sequence[0]->get3dsizex();i++)
+				temp[j*sequence[0]->get3dsizex()+i]=sequence[t]->getvoxel(i,j,k);
+			bytes += gzwrite(fdf,&temp[0],sz);
+		      }
+	      delete [] temp;
+	    }
+	else
+	    {
+	      unsigned short* temp=new unsigned short[sz];
+	      for (int t=0;t<numf;t++)
+		  for (int k=0;k<sequence[0]->get3dsizez();k++)
+		      {
+			for (int j=0;j<sequence[0]->get3dsizey();j++)
+			    for (int i=0;i<sequence[0]->get3dsizex();i++)
+				temp[j*sequence[0]->get3dsizex()+i]=sequence[t]->getvoxel(i,j,k);
+			bytes += gzwrite(fdf,&temp[0],sz*2);
+		      }
+	      delete [] temp;
+	    }
+	fprintf(stderr,"Image saved in : %s (%d,%d) frames=%d\n",fname,int(bytes),bits , numf);
+      }
+  else 
+      {
+	fprintf(stderr,"SaveImg :: Could not write file %s\n" , fname);
+      }
+  gzclose(fdf);
+  delete [] fname;
+  delete hdr;
+  return (bytes>0);
+}
+
diff --git a/bioimagesuite30_src/numerics/px3dimage.h b/bioimagesuite30_src/numerics/px3dimage.h
new file mode 100644
index 0000000..f2a6c54
--- /dev/null
+++ b/bioimagesuite30_src/numerics/px3dimage.h
@@ -0,0 +1,258 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// px3dimage.h
+// Definition of Class PX3DImage
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris September 1995 papad at noodle.med.yale.edu
+
+
+_Module_Name : PX3DImage 
+
+_Description : This class can be used to store objects which are 3D images.
+               Derived class from PXImage --> see pximage.h
+	       
+	       
+_Call :   
+  (1) PX3DImage(int x,int y,int z,int wd=1);        // Specify Column Width   
+  (2) PX3DImage(const char*,int,int,int,int wd=1);  // Checks for filename too;
+  (3) PX3DImage(const char*,int wd=1);                    // Load Constructors int=cwidth
+  (4) PX3DImage(const char*,int,int,int in=1,int wd=1);   // Load Co  int=f:l:i:cwd
+  (5) PX3DImage(PXImage *Sequence[],int ,int wd=1); // Stack Constructor;
+  (6) PX3DImage(PX3DImage *)                        // Copy Constructor
+
+_References : None
+              
+	      
+_I/O : Analyse Format (16-bit)
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 22nd September 1995 - tested OK
+                    2. Added Copy Constructor 7th October 1995
+		    3. Reduced number of constructors by adding default arguments
+		       and added getslice? functions 2nd Sep 1996
+		    4. Cleaned up 3d interpolation  25th Aug 1997
+		    5. Cleaned Save Bug to account for unequal height/width also automatic 8-bit save 
+		       if (max<256)
+		    6. Set Code for using signed short read/write 7th Jan 1997
+		       getsvoxel(x,y,z) and setsvoxel(x,y,z,p) and gets3dinterp(x,y,z)
+		    7. Added code to generate slices from echo data (with transparency enabled)
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#--#-#-#-#-#-#-#-#  */
+
+#ifndef _PX3DImage
+#define  _PX3DImage
+
+#include "pximage.h"
+
+class PX3DImage : public PXImage {
+  
+  // -----------------------------------------------------------------------;
+  // Class Fields;
+  // -----------------------------------------------------------------------;
+
+protected:	
+
+  int   zsize,norows,nocolumns;         // Size in z and arrangement in matrix;
+  int   partwidth,partheight;           // Component Images Size;
+  int   numbytes;
+  int   polarmode;
+  float outplanescale;
+
+  // ******************************************************************************
+  //          PUBLIC INTERFACE
+  // ******************************************************************************
+  
+public:
+
+  PX3DImage(int x,int y,int z,int wd=1);     
+  PX3DImage(const char* fname,int wd=1);            // Load Constructors int=cwidth
+  PX3DImage(const char* fname,int first,int last ,int increment =1,int wd=1);  
+                                                  // Load Constructors int=PXIm_?;
+  PX3DImage(PXImage *Sequence[],int n,int wd=1,int x0=0,int y0=0,
+	                                       int x1=-1,int y1=-1);  // Stack Constructor;
+  PX3DImage(PX3DImage *Sequence[],int n);  // 3D Stack Constructor;
+
+  PX3DImage(PX3DImage *OldImage);                 // Copy Constructor;
+  virtual ~PX3DImage();				
+  virtual void init();
+
+  // [A] Voxel Manipulation
+  // ----------------------
+  virtual void setvoxel(int x,int y,int z,unsigned short g)
+    { int row=z/nocolumns;      int column=z-row*nocolumns;
+      image[x+column*partwidth+xsize*(y+row*partheight)]=g;  }
+  virtual unsigned short getvoxel(int x,int y,int z)
+    { int row=z/nocolumns;     int column=z-row*nocolumns;
+      return image[x+column*partwidth+xsize*(y+row*partheight)]; }
+  unsigned short get3dechovoxel(float x,float y,float z,float middlex);
+  
+  virtual short  getsvoxel(int x,int y,int z)
+      {	unsigned short a=getvoxel(x,y,z);
+	return (short)(a-(65536*(a>32767))); }
+  virtual void setsvoxel(int x,int y,int z,short p)
+      {	unsigned short px=p+65536*(p>0);
+	setvoxel(x,y,z,px); }
+  virtual float gets3dinterp(float x,float y,float z)
+      { float a=get3dinterp(x,y,z);
+	return a-(65536.0*(a>32767.5)); }
+  
+  float get3dinterp(float x,float y,float z);
+
+
+
+  // [B] Get 3D sizes
+  // ----------------
+  virtual int get3dsizez()    {return zsize;}
+  virtual int get3dsizex()    {return partwidth;}
+  virtual int get3dsizey()    {return partheight;}
+
+  virtual int	getwidth()    {return get3dsizex();}		
+  virtual int	getheight()   {return get3dsizey();}		
+  virtual int	getdepth()    {return get3dsizez();}		
+
+  virtual void Scale(float scale);
+
+  virtual void  setpolarmode(int mode,int )        { polarmode=mode>0;}
+  virtual int   getpolarmode()                { return polarmode;}
+  virtual int   setoutplanescale(float scale,int fo=0) { outplanescale=fabs(scale); return 1; }
+  virtual float getoutplanescale()            { return outplanescale;}
+
+  // [C] I/O Related Code
+  // --------------------
+  virtual int	Save(const char* fname);
+  virtual int	Save();
+  virtual int	SaveImg(int bits=-1);
+
+  // [D] Get Slices 
+  // ---------------
+  unsigned char* getslicex(int x,float gamma=1.0,int numbytes=1);    // No-interpolation
+  unsigned char* getslicey(int y,float gamma=1.0,int numbytes=1);
+  unsigned char* getslicez(int z,float gamma=1.0,int numbytes=1);
+
+  unsigned char* getinterpslicex(float x,float gamma=1.0,int numbytes=1);  // Interpolate
+  unsigned char* getinterpslicey(float y,float gamma=1.0,int numbytes=1);
+  unsigned char* getinterpslicez(float z,float gamma=1.0,int numbytes=1);
+
+  unsigned char* getechoslicetheta(int slice,float gamma=1.0,int numbytes=1);
+  unsigned char* getechoslicexy(float zlevel,float gamma=1.0,int numbytes=1,float middlex=-1.0);
+
+  // [E] Other Code
+  // --------------
+  virtual void Add3DContour(PXContour* contour,unsigned short grl,
+			    unsigned char touching,
+			    int offx,int offy,int offz);
+  
+  // **** 3D -> 2D  Conversion ****
+
+  virtual int getpixelx(int x,int ,int z)
+    { int row=z/nocolumns;  int column=z-row*nocolumns;
+      return x+column*partwidth; }
+  virtual int getpixely(int ,int y,int z)
+    { int row=z/nocolumns;     return (y+row*partheight);  }
+
+  // **** 2D -> 3D  Conversion ****
+  virtual int getvoxelx(int x,int)
+      { int column=(x/partwidth);  return x-column*partwidth; }
+  
+  virtual int getvoxely(int ,int y)
+      { int row=(y/partheight);    return y-row*partheight;  }
+  
+  virtual int getvoxelz(int x,int y)
+      { int column=(x/partwidth);  int row=(y/partheight);
+	return column+row*nocolumns; }
+  
+  virtual int getopt(int z)
+      {
+	int b=(int)sqrt((float)(z));
+	if (b==0) return 1;
+	if (b*b+1>z) return b;
+	else return b+1;
+      }
+   
+  int  LoadBin(const char* fname,int numbytes=2,int offset=0);
+
+
+  static int saveArray(const char* filename,PX3DImage** sequence,int n);
+
+
+protected:
+
+  // ******************************************************************************
+  //          IMPLEMENTATION SPECIFIC
+  // ******************************************************************************
+
+  virtual int  Load();
+  virtual int  LoadPart(int first,int last,int increment);
+  virtual void CheckAnaFilename(int mode);
+  
+
+  // **** 2.5D Sizes ****
+
+  virtual int getnorows()    { return norows;}
+  virtual int getnocolumns() { return nocolumns;}
+
+  virtual int get3dbilinear(float x,float y,int z)
+    { int row=z/nocolumns;      int column=z-row*nocolumns;
+      return getbilinear(x+(float)(column*partwidth),
+			 y+(float)(row*partheight));  }
+  
+
+  //  virtual void getechovoxel(float x,float y,float z,float middlex);
+
+};
+
+#endif /*  _PX3DImage */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/numerics/pxabaqussolid.cpp b/bioimagesuite30_src/numerics/pxabaqussolid.cpp
new file mode 100644
index 0000000..ace5b6b
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxabaqussolid.cpp
@@ -0,0 +1,4647 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+#include "pxabaqussolid.h"
+#include "pxmarkerclass.h"
+#include "pxutil.h"
+#include "nrutil.h"
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July 1995   papad at noodle.med.yale.edu
+
+   see PXBSplineStackSolid.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+// --------------------------------------------------------------------------
+int  PXAbaqusSolid::debugmode=0;
+// --------------------------------------------------------------------------
+//    Access Functions 
+// ------------------------------------------------------------------------- 
+void     PXAbaqusSolid::setOrientationMode(int ormode) { orientationMode=Irange(ormode,-1,3);}
+int      PXAbaqusSolid::getelementtype() { return elementtype;}
+int      PXAbaqusSolid::getelementmode() { return elementmode;}
+
+int      PXAbaqusSolid::getenforcementmode()  { return enforcementMode;}
+int      PXAbaqusSolid::getorientationmode()  { return orientationMode;}
+float    PXAbaqusSolid::getspringmulitplier() { return springMultiplier;}
+
+int      PXAbaqusSolid::hasstacks()           { return hasStacks;}
+int      PXAbaqusSolid::hasfemdata()          { return hasFemData;}
+int      PXAbaqusSolid::hasnodes()            { return hasNodes;}
+int      PXAbaqusSolid::haselements()         { return hasElements;}
+int      PXAbaqusSolid::hasspringelements()   { return hasSpringElements;}
+int      PXAbaqusSolid::hasspringnodes()      { return hasSpringNodes;}
+int      PXAbaqusSolid::hasmaterial()         { return hasMaterial;}
+int      PXAbaqusSolid::hasvolumes()          { return hasVolumes;}
+float*   PXAbaqusSolid::getvolumes()          { return volume;}
+int      PXAbaqusSolid::getnumvolumes()       { return numvolumes;}
+float    PXAbaqusSolid::getoutputstep()       { return outputStep;}
+int      PXAbaqusSolid::getoutputinc()        { return outputInc;}
+int      PXAbaqusSolid::getnumlayers()        { return numlayers;}
+int      PXAbaqusSolid::getnumpointscontour() { return numpointscontour;}
+
+
+
+PXNeighboursList*    PXAbaqusSolid::getelements()       { return elements;}
+PXNeighboursList*    PXAbaqusSolid::getspringelements() { return springElements;}
+PXSolidNodes*        PXAbaqusSolid::getnodes()          { return nodes;}
+PXSolidNodes*        PXAbaqusSolid::getspringnodes()    { return springNodes;}
+PXAbaqusMaterialModel*     PXAbaqusSolid::getmaterial()       { return material;}
+PXAbaqusOutputData*           PXAbaqusSolid::getfemdata()        { return femData;}
+
+PXTriangulatedStack* PXAbaqusSolid::getstack(int i)    { return tstack[Irange(i,0,1)];}
+
+void PXAbaqusSolid::setorientationmode(int m)
+{
+  orientationMode=Irange(m,0,6);
+}
+
+void PXAbaqusSolid::sethybridmode(int h)
+{
+  if (h>0 && elementmode<100)
+      elementmode=elementmode+100;
+  if (h<1 && elementmode>100)
+      elementmode=elementmode-100;
+}
+// ------------------------------------------------------------------------- 
+
+PXAbaqusSolid::PXAbaqusSolid()
+{
+  init();
+}
+
+PXAbaqusSolid::PXAbaqusSolid(PXAbaqusSolid* old)
+{
+  init();
+  Copy(old);
+}
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::Copy(PXAbaqusSolid* other)
+{
+  cleanup();
+  init();
+
+  if (other->hasstacks())
+      {
+	for (int i=0;i<=1;i++)
+	    tstack[i]=new PXTriangulatedStack(other->getstack(i));
+	hasStacks=1;
+      }
+
+  elementtype=other->getelementtype();
+  elementmode=other->getelementmode();
+
+  if (other->haselements())
+      {
+	elements=new PXNeighboursList();
+	elements->Copy(other->getelements());
+	hasElements=1;
+      }
+  
+  if (other->hasspringelements())
+      {
+	springElements=new PXNeighboursList();
+	springElements->Copy(other->getspringelements());
+	hasSpringElements=1;
+      }
+
+  if (other->hasnodes())
+      {
+	nodes=new PXSolidNodes(other->getnodes());
+	hasNodes=1;
+      }
+
+  if (other->hasspringnodes())
+      {
+	springNodes=new PXSolidNodes(other->getspringnodes());
+	hasSpringNodes=1;
+      }
+  
+  if (other->hasmaterial())
+      {
+	material=new PXAbaqusMaterialModel(other->getmaterial());
+	hasMaterial=1;
+      }
+
+  springMultiplier=other->getspringmulitplier();
+  numlayers=other->getnumlayers();
+
+  if (other->hasvolumes())
+      {
+	numvolumes=other->getnumvolumes();
+	volume=new float[numvolumes];
+	float* ovol=other->getvolumes();
+	for (int ia=0;ia<numvolumes;ia++)
+	    volume[ia]=ovol[ia];
+	hasVolumes=1;
+      }
+
+  outputStep=other->getoutputstep();
+  outputInc=other->getoutputinc();
+  enforcementMode=other->getenforcementmode();
+  orientationMode=other->getorientationmode();
+
+  if (other->hasfemdata())
+      {
+	femData=new PXAbaqusOutputData(other->getfemdata());
+	hasFemData=1;
+      }
+}
+// --------------------------------------------------------------------------
+PXAbaqusSolid::PXAbaqusSolid(const char* fname1,const char* fname2)
+{
+  init();
+  tstack[0]=new PXTriangulatedStack();
+  tstack[1]=new PXTriangulatedStack();
+  int ok=tstack[0]->Load(fname1);
+  ok+=2*tstack[1]->Load(fname2);
+  if (ok<3)
+      {
+	fprintf(stderr,"I/O Error reading from %s and %s (%d)\n",fname1,fname2,ok);
+	delete tstack[0];
+	delete tstack[1];
+      }
+  else
+      {
+	if (debugmode)
+	    fprintf(stderr,"Read from %s and %s (%d)\n",fname1,fname2,ok);
+	hasStacks=1;
+      }
+}
+// --------------------------------------------------------------------------
+PXAbaqusSolid::PXAbaqusSolid(PXTriangulatedStack* stack1,
+			     PXTriangulatedStack* stack2)
+{
+  init();
+  tstack[0]=new PXTriangulatedStack(stack1);
+  tstack[1]=new PXTriangulatedStack(stack2);
+  hasStacks=1;
+
+/*  if (totalnumstacks>2)
+      {
+	PXContourStack* cst[ABAQUSSOLIDMAXLEVELS];
+	PXContourStack* cst1=tstack[0]->exporttocontourstack();
+	cst1->Equispace(0.5);
+	PXContourStack* cst2=tstack[numstacks-1]->exporttocontourstack();
+	cst2->Equispace(0.5);
+
+	if (debugmode)
+	    fprintf(stderr,"Slowly ...");
+	
+	for (int i=1;i<numstacks-1;i++)
+	    cst[i-1]=new PXContourStack(cst1->getnumcontours());
+	
+	// Create Inbetween Stacks 
+	if (debugmode)
+	    fprintf(stderr,"Going to stackset\n");
+	int flag=PXContourStack::createstackset(cst1,cst2,cst,tetra,totalnumstacks-2,bias);
+	if (flag==0)
+	    {
+	      fprintf(stderr,"Unequal number of slices, check surfaces, exiting\n");
+	      for (int i=1;i<numstacks-1;i++)
+		  delete cst[i-1];
+	      delete tstack[0];
+	      delete tstack[numstacks-1];
+	      numstacks=0;
+	      delete cst1;
+	      delete cst2;
+	      return;
+	    }
+	for (i=1;i<numstacks-1;i++)
+	    {
+	      cst[i-1]->Equispace(sample/5.0);
+	      cst[i-1]->Smooth();
+	      if (tetra)
+		  cst[i-1]->Equispace(sample);
+	      tstack[i]=new PXTriangulatedStack(cst[i-1],0);
+	      if (tetra)
+		  tstack[i]->nonShrinkSmooth(0.33,-0.34,20);
+	    }
+
+	if (tetra)
+	    {
+	      cst1->Equispace(sample);
+	      cst2->Equispace(sample);
+	      tstack[0]->setfromcontourstack(cst1,0);
+	      tstack[numstacks-1]->setfromcontourstack(cst2,0);
+	    }
+
+	// Cleanup at end 
+	// --------------
+	for (i=0;i<numstacks-2;i++)
+	    delete cst[i];
+	delete cst1;
+	delete cst2;
+      }*/
+}
+// --------------------------------------------------------------------------
+
+void PXAbaqusSolid::init()
+{
+  elementtype=8; hasmidwallnodes=0; hasmidwallelements=0;
+  springMultiplier=1.0; numlayers=1; numpointscontour=-1;
+  outputStep=1.0; outputInc=40; enforcementMode=0;  orientationMode=-1;
+  hasElements=0;  hasNodes=0;   hasMaterial=0; hasFemData=0;
+  hasVolumes=0;   hasSpringNodes=0; hasSpringElements=0; hasStacks=0;
+
+}
+// --------------------------------------------------------------------------
+PXAbaqusSolid::~PXAbaqusSolid()
+{
+  cleanup();
+}
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::cleanup()
+{
+  cleanupElementSpace();
+  cleanupNodeSpace();
+  cleanupMaterial();
+
+  if (hasstacks())
+      {
+	for (int i=0;i<=1;i++)
+	    delete tstack[i];
+      }
+
+  if (hasvolumes())
+      delete [] volume;
+
+
+  if (hasspringelements() || hasspringnodes())
+      cleanupSpringSpace();
+
+  if (hasfemdata())
+      cleanupFemData();
+
+}
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::cleanupMaterial()
+{
+  if (hasmaterial())
+      {
+	delete material;
+	hasMaterial=0;
+      }
+}
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::allocateMaterial()
+{
+  if (hasmaterial())
+      cleanupMaterial();
+  material=new PXAbaqusMaterialModel(0);
+  hasMaterial=1;
+}
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::cleanupSpringSpace()
+{
+  /*  fprintf(stderr,"Cleaning up hasel=%d hasnd=%d\n",
+      hasspringelements(),hasspringnodes());*/
+  if (hasspringelements())
+      {
+	delete springElements;
+	hasSpringElements=0;
+      }
+  if (hasspringnodes())
+      {
+	delete springNodes;
+	hasSpringNodes=0;
+      }
+}
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::cleanupFemData()
+{
+  if (hasfemdata())
+      delete femData;
+  hasFemData=0;
+}
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::cleanupElementSpace()
+{
+  if (haselements())
+      delete elements;
+  hasElements=0;
+}
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::cleanupNodeSpace()
+{
+  if (hasnodes())
+      delete nodes;
+  hasNodes=0;
+}
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::allocateFemData()
+{
+  if (hasfemdata())
+      cleanupFemData();
+  
+  if (!haselements() || !hasnodes())
+      return;
+  femData=new PXAbaqusOutputData(nodes->getnumnodes(),elements->getnumnodes());
+  hasFemData=1;
+}
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::allocateSpringSpace(int order)
+{
+  if (!hasnodes() || !haselements())
+      return;
+
+
+  order=Irange(order,0,1);
+  int np=0;
+
+  
+  /* Need to generate an
+    PXIntegerList* array to store connectivity on walls for tracked points to
+	apply data to. Then things become very easy.
+	
+	Also need a temperature field for the nodes and the spring nodes otherwise
+	things will get confused if temperature is used to model both
+	1. active contraction and
+	2. varying spring stiffness
+	
+	*/	
+  
+  // Generating Neighbours 
+  elements->Rewind();
+  for (int el=0;el<elements->getnumnodes();el++)
+      {
+	if (debugmode)
+	    {
+	      if (100*int(el/100)==el)
+		  fprintf(stderr,"%d/%d ",el,elements->getnumnodes());
+	    }
+	
+	PXIntegerList* intList=((elements->getcurrentnode())->points);
+	intList->Rewind();
+	if (intList->getnumnodes()<12)
+	    {
+	      int elpt[12];
+	      for (int k=0;k<intList->getnumnodes();k++)
+		  {
+		    elpt[k]=intList->getcurrent();
+		    intList->Next();
+		  }
+	      
+	      {
+		for(int k=0;k<intList->getnumnodes();k++)
+		    {
+		      int st=nodes->getindex(elpt[k],0);
+		      for (int j=0;j<intList->getnumnodes();j++)
+			  {
+			    int st2=nodes->getindex(elpt[j],0);
+			    if (j!=k && (st==st2) && (st==0 || st==100))
+				nodes->getneighbours(elpt[k])->AddNonDuplicate(elpt[j],-1);
+			  }
+		    }
+	      }
+	    }
+	elements->Next();
+      }
+
+  //nodes->Save("nodes.list");
+  
+  for (int pt=0;pt<nodes->getnumnodes();pt++)
+      {
+	int st=nodes->getindex(pt,0);
+	if (st==0 || st==100)
+	    {
+	      np++;
+	      if (order==1)
+		  {
+		    PXIntegerList* nei=nodes->getneighbours(pt);
+		    np+=nei->getnumnodes();
+		  }
+	    }
+      }
+
+  //fprintf(stderr,"np=%d\n",np);
+
+  int baseel=elements->getnumnodes();
+  int baseno=nodes->getnumnodes();
+
+  int p[2];
+
+  const float Lengthfactor=0.01;
+  cleanupSpringSpace();
+  if (np>0)
+      {
+	springNodes=new PXSolidNodes(np);
+	springElements=new PXNeighboursList();
+	hasSpringNodes=1;
+	hasSpringElements=1;
+
+	int springnodeno=0;
+	
+	for (int pt=0;pt<nodes->getnumnodes();pt++)
+	    {
+	      int st=nodes->getindex(pt,0);
+	      if (st==0 || st==100)
+		  {
+		    for (int ia=0;ia<=2;ia++)
+			{
+			  float nx=(nodes->getpoint(pt))->nx[ia];
+			  springNodes->getpoint(springnodeno)->x[ia]=nodes->getpoint(pt)->x[ia]+Lengthfactor*nx;
+			}
+		    springNodes->setindex(springnodeno,0,pt);
+		    springNodes->setindex(springnodeno,1,0);
+
+		    p[0]=pt;  
+		    p[1]=springnodeno+baseno;
+		    springElements->AddN(p,2,baseel);
+		    ++baseel;
+		    ++springnodeno;
+
+		    if (order==1)
+			{
+			  PXIntegerList* nei=nodes->getneighbours(pt);
+			  nei->Rewind();
+			  for (int n=0;n<nei->getnumnodes();n++)
+			      {
+				int op=nei->getcurrent();
+				if (op==pt)
+				    {
+				      fprintf(stderr,"Error\n Zero Length Spring %d %d %d %d\n",
+					      pt,nodes->getnumnodes(),n,nei->getnumnodes());
+				    }
+				else
+				    {
+				      PX3Vector vp;
+				      vp.setvector(nodes->getpoint(op)->x[0]-nodes->getpoint(pt)->x[0],
+						   nodes->getpoint(op)->x[1]-nodes->getpoint(pt)->x[1],
+						   nodes->getpoint(op)->x[2]-nodes->getpoint(pt)->x[2]);
+				      
+				      vp.normalize();
+				      /*for (int ib=0;ib<=2;ib++)
+					  vp.x[ib]+=nodes->getpoint(pt)->nx[ib];
+				      vp.normalize();*/
+				      
+				      for (int ia=0;ia<=2;ia++)
+					  springNodes->getpoint(springnodeno)->x[ia]=nodes->getpoint(pt)->x[ia]+
+					  Lengthfactor*vp.x[ia];
+				      
+				      /*for (int ia=0;ia<=2;ia++)
+					  {
+					    float nx=(nodes->getpoint(pt))->nx[ia];
+					    springNodes->getpoint(springnodeno)->x[ia]=
+						nodes->getpoint(pt)->x[ia]+Lengthfactor*nx;
+						}*/
+
+				      springNodes->setindex(springnodeno,0,op);
+				      springNodes->setindex(springnodeno,1,1);
+				      
+				      p[0]=pt;
+				      p[1]=springnodeno+baseno;
+				      springElements->AddN(p,2,baseel);
+				      ++baseel;
+				      ++springnodeno;
+				    }
+				nei->Next();
+			      }
+			}
+		  }
+	    }
+      }
+}
+
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::allocateNodeSpace(int numnode)
+{
+  if (hasnodes())
+      cleanupNodeSpace();
+  
+  nodes=new PXSolidNodes(numnode);
+  hasNodes=1;
+  
+}
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::allocateElementSpace()
+{
+  if (haselements())
+      cleanupElementSpace();
+
+  elements=new PXNeighboursList();
+  hasElements=1;
+}
+// --------------------------------------------------------------------------
+// Geometry Related
+// ----------------
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::generateTetrahedralSolid(float spacing,int bias)
+{
+  spacing++; bias++;
+  /*
+     elementtype=4;
+  char line[200];
+  PXNeighboursList* tetra=new PXNeighboursList();
+  PXTriangulatedStack::save2qhull("test.qhull",tstack,2);
+  sprintf(line,"qhull < test.qhull d QJ o Qs > test.geom");
+  if (debugmode)
+      fprintf(stderr,"%s \n",line);
+  system(line);
+  int nt;
+  PXTriangulatedStack::loadqhull("test.geom",tstack,2,tetra,nt);
+
+  // Point Based Cleaning up
+  // -----------------------
+  PXTriangulatedStack::cleanup(tstack,2,tetra,nt);
+  
+  int total=0;
+  for (int i=0;i<2;i++)
+      total+=tstack[i]->getnumpoints();
+
+  allocateElementSpace();
+  allocateNodeSpace(total);
+  
+  // 2. Add Original Nodes
+  // ---------------------
+  int* totals=PXTriangulatedStack::gettotal(tstack,2);
+  
+  for ( i=0;i<total;i++)
+      {
+	PXTriangulatedStackPoint* point=getpoint(i,totals);
+	for (int ia=0;ia<=2;ia++)
+	    nodes->getpoint(i)->x[ia]=point->x[ia];
+	for (int ib=0;ib<=2;ib++)
+	    nodes->getpoint(i)->x[ib]=point->k[ib];
+	nodes->setindex(i,0,PXTriangulatedStack::whichstack(i,totals,2));
+	nodes->setindex(i,1,i-totals[nodes->getindex(i,0)]);
+      }
+
+  //3. Add Elements
+  // ---------------
+
+  tetra->Rewind();
+  int p[4],elno=0;
+  for (i=0;i<tetra->getnumnodes();i++)
+      {
+	if (debugmode)
+	    {
+	      if (int(i/50)*50==i && debugmode)
+		  fprintf(stderr,"%d ",i);
+	    }
+	if (tetra->getcurrentindex()>=0)
+	    {
+	      if (debugmode)
+		  {
+		    if (int(i/50)*50==i && debugmode)
+			fprintf(stderr,"-- %d ",i);
+		  }
+
+	      PXIntegerList* intList=((tetra->getcurrentnode())->points);
+	      intList->Rewind();
+	      for (int ia=0;ia<=3;ia++)
+		  {
+		    p[ia]=intList->getcurrent();
+		    intList->Next();
+		  }
+	      elements->AddN(p,4,elno);
+	      elno++;
+	    }
+	tetra->Next();
+      }
+
+  if (debugmode)
+      {
+	fprintf(stderr,"Done\n");
+	elements->Save("elements.list");
+      }
+  delete tetra;
+  return elements->getnumnodes();*/
+  return 0;
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::generateHexahedralSolid(int nodespercontour,int totalnumstacks,int bias,
+					   float sample,int skipslices)
+{
+  elementtype=8;
+  elementmode=8;
+  nodespercontour=Irange(nodespercontour,10,200);
+  if (debugmode)
+    fprintf(stderr,"Nodes per contour = %d sample=%.1f numstacks=%d\n",nodespercontour,sample,totalnumstacks);
+  char line[100];
+  // Part 1, export to contourstacks and align contours properly
+  // -----------------------------------------------------------
+  PXContourStack* cstack[ABAQUSSOLIDMAXLEVELS-1];
+
+  int numstacks=Irange(totalnumstacks,2,ABAQUSSOLIDMAXLEVELS-1);
+
+  sample=Frange(sample,1.0,20.0);
+  float isample=1.0/sample;
+  tstack[0]->scalepoints(isample,isample);
+  tstack[1]->scalepoints(isample,isample);
+
+  cstack[0]=tstack[0]->exporttocontourstack(skipslices);
+  cstack[numstacks-1]=tstack[1]->exporttocontourstack(skipslices);
+  
+  if (numstacks>2)
+    {
+      cstack[0]->Equispace(0.5);
+      cstack[numstacks-1]->Equispace(0.5);
+      
+      if (debugmode)
+	fprintf(stderr,"Slowly ...");
+      
+      int i;
+      for (i=1;i<numstacks-1;i++)
+	cstack[i]=new PXContourStack(cstack[0]->getnumcontours());
+      
+      // Create Inbetween Stacks 
+      if (debugmode)
+	fprintf(stderr,"Going to stackset\n");
+      
+      
+      int flag=PXContourStack::createstackset(cstack,numstacks,bias);
+      
+      
+      if (flag==0)
+	{
+	  fprintf(stderr,"Unequal number of slices, check surfaces, exiting %d %d\n",cstack[0]->getnumcontours(),cstack[numstacks-1]->getnumcontours());
+	  for (int i=0;i<numstacks;i++)
+	    delete cstack[i];
+	  return 0;
+	}
+      
+      for (i=1;i<numstacks;i++)
+	{
+	  cstack[i]->Equispace(0.5);
+	  cstack[i]->Smooth();
+	}
+    }
+  
+  numlayers=numstacks;
+
+  FILE* fout=NULL;
+
+  if (debugmode)
+      {
+	fout=fopen("script.gpl","w");
+	//fprintf(fout,"set xrange[30:75]\nset yrange[30:75]\n");
+	fprintf(fout,"set grid\n");
+      }
+  int numslices=cstack[0]->getnumcontours();
+  int mid=numslices/2;
+  int direction=1;
+  int sl=mid;
+
+
+
+  for (int j=0;j<numstacks;j++)
+    for (int i=0;i<numslices;i++)
+      (cstack[j]->getcontour(i))->ensureAnticlockwise();
+
+  if (debugmode)
+    {
+      fprintf(stderr,"Done with creating stacks\n");
+      for (int i=0;i<numstacks;i++)
+	{
+	  fprintf(stderr,"Stack %d :",i);
+	  for (int j=0;j<numslices;j++)
+	    fprintf(stderr," %d(%d,%.1f) ",j,cstack[i]->getcontour(j)->getnumpoints(),
+		    cstack[i]->getcontour(j)->getcontourlength());
+	  fprintf(stderr,"\n");
+	}
+    }
+		    
+  
+  while(sl>=0)
+    {
+      if (sl==mid)
+	{
+	  (cstack[0]->getcontour(mid))->setclosed(1);
+	  (cstack[0]->getcontour(mid))->Equisample(nodespercontour+1);
+	  (cstack[0]->getcontour(mid))->RemovePoint();
+	  if (debugmode)
+	    fprintf(stderr,"Number of points = %d\n",(cstack[0]->getcontour(mid))->getnumpoints());
+	}
+      else
+	{
+	  PXContour* cntr2=PXContour::mapContours(cstack[0]->getcontour(sl-direction),
+						  cstack[0]->getcontour(sl),1);
+	  cntr2->ensureAnticlockwise();
+	  cstack[0]->getcontour(sl)->copypoints(cntr2);
+	  delete cntr2;
+	  if (debugmode)
+	    fprintf(stderr,"**** Generated stack 0 slice=%d points=%d length=%.1f\n",sl,cstack[0]->getcontour(sl)->getnumpoints(),cstack[0]->getcontour(sl)->getcontourlength());
+	}
+      
+      if (debugmode)
+	{
+	  fprintf(fout,"plot ");
+	  /*sprintf(line,"level%02d.%02di",sl,0);
+	    (cstack[0]->getcontour(sl))->Save(line);
+	    fprintf(stderr,"%s\n",line);
+	    fprintf(fout," '%s' w p ,",line);*/
+	}
+      
+      for (int cn=0;cn<numstacks-1;cn++)
+	{
+	  /*if (debugmode)
+	    {
+	    sprintf(line,"level%02d.%02di",sl,cn+1);
+	    (cstack[cn+1]->getcontour(sl))->Save(line);
+	    fprintf(stderr,"%s\n",line);
+	    fprintf(fout,"'%s' w p, ",line);
+	    }*/
+	  
+	  PXContour* cntr=PXContour::mapContours(cstack[cn]->getcontour(sl),
+						 cstack[cn+1]->getcontour(sl));
+	  cntr->ensureAnticlockwise();
+
+	  if (debugmode)
+	    {
+	      sprintf(line,"level%02d.%02d",sl,cn);
+	      PXContour::saveContourPair(line,cstack[cn]->getcontour(sl),cntr);
+	      fprintf(stderr,"\n------------\n%s",line);
+	      fprintf(fout,"'%s' w l ",line);
+	      
+	      if (cn<numstacks-2)
+		fprintf(fout," ,");
+	      else
+		fprintf(fout,"\n");
+	      
+	    }
+	  cstack[cn+1]->getcontour(sl)->copypoints(cntr);
+ 	  if (debugmode)
+	    fprintf(stderr,"**** Generated stack %d slice=%d points=%d length=%.1f\n",cn+1,sl,cstack[cn+1]->getcontour(sl)->getnumpoints(),cstack[cn+1]->getcontour(sl)->getcontourlength());
+
+	  delete cntr;
+	  
+	}
+      if (debugmode)
+	fprintf(fout,"\npause -1\n");
+      
+      sl+=direction;
+      if (sl>=numslices)
+	{
+	  sl=mid-1;
+	  direction=-1;
+	}
+    }
+  if (debugmode && fout!=NULL)
+    fclose(fout);
+
+
+  tstack[0]->scalepoints(sample,sample);
+  tstack[1]->scalepoints(sample,sample);
+  
+  // Part 2, parse stacks to create elements
+  // ---------------------------------------
+  allocateElementSpace();
+  allocateNodeSpace(nodespercontour*numstacks*numslices);
+  
+  numpointscontour=nodespercontour;
+
+
+
+  // Do Nodes first 
+  // --------------
+  for (int layer=0;layer<numstacks;layer++)
+    for (int slice=0;slice<numslices;slice++)
+      {
+	PXContourPoint *pts2=(cstack[layer]->getcontour(slice))->gettoppoint();
+	for (int pt=0;pt<nodespercontour;pt++)
+	  {
+	    int i=layer*numslices*nodespercontour+slice*nodespercontour+pt;
+	    nodes->getpoint(i)->x[0]=pts2->x*sample; 
+	    nodes->getpoint(i)->x[1]=pts2->y*sample;
+	    nodes->getpoint(i)->x[2]=cstack[layer]->getzlevel(slice);
+	    
+	    // Add Curvatures
+	    if (layer==0 || layer==numstacks-1)
+	      {
+		int index=0;
+		float x=nodes->getpoint(i)->x[0];
+		float y=nodes->getpoint(i)->x[1];
+		float z=nodes->getpoint(i)->x[2];
+		
+		tstack[layer>0]->findnearestpoint(x,y,z,index,0,0.2);
+		nodes->getpoint(i)->k[0]=(tstack[layer>0]->getpoint(index))->k[0];
+		nodes->getpoint(i)->k[1]=(tstack[layer>0]->getpoint(index))->k[1];
+		for (int ia=0;ia<=2;ia++)
+		  nodes->getpoint(i)->nx[ia]=tstack[layer>0]->getpoint(index)->nx[ia];
+		
+		if (layer==0)
+		  nodes->setindex(i,0,0);
+		else if (layer==numstacks-1)
+		  nodes->setindex(i,0,100);
+	      }
+	    else
+	      {
+		if (bias==1 && layer==1)
+		  {
+		    nodes->setindex(i,0,int(100*(layer)/(numstacks)));
+		  }
+		else
+		  nodes->setindex(i,0,int((100*layer)/(numstacks-1)));
+	      }
+	    pts2=pts2->next;
+	  }
+      }
+  
+  tstack[0]->setfromcontourstack(cstack[0],0);
+  tstack[1]->setfromcontourstack(cstack[numstacks-1],0);
+  int i;
+  for (i=0;i<numstacks;i++)
+      delete cstack[i];
+   
+  for (i=0;i<nodes->getnumnodes();i++)
+    {
+      int st=nodes->getindex(i,0);
+      if (st==0 || st==100)
+	{
+	  float x=nodes->getpoint(i)->x[0];
+	  float y=nodes->getpoint(i)->x[1];
+	  float z=nodes->getpoint(i)->x[2];
+	  int index=0;
+	  tstack[st>0]->findnearestpoint(x,y,z,index,0,0.02);
+	  nodes->setindex(i,1,index);
+	}
+    }
+  
+  // Elements Next
+  // -------------
+  int p[8];
+  int numlevels=numslices-1;
+  int sliceoffset=(numslices*nodespercontour);
+  for (int st=0;st<numstacks-1;st++)
+    for (int sl=0;sl<numlevels;sl++)
+      for(int pt=0;pt<nodespercontour;pt++)
+	{
+	  int pp=pt+1;
+	  if (pp>=nodespercontour)
+	    pp-=(nodespercontour);
+	  int elno=st*numlevels*nodespercontour+sl*nodespercontour+pt;
+	  p[0]=sliceoffset*st    +nodespercontour*sl    +pt;
+	  p[1]=sliceoffset*(st+1)+nodespercontour*sl    +pt;
+	  p[2]=sliceoffset*(st+1)+nodespercontour*sl    +pp;
+	  p[3]=sliceoffset*st    +nodespercontour*sl    +pp;
+	  p[4]=sliceoffset*st    +nodespercontour*(sl+1)+pt;
+	  p[5]=sliceoffset*(st+1)+nodespercontour*(sl+1)+pt;
+	  p[6]=sliceoffset*(st+1)+nodespercontour*(sl+1)+pp;
+	  p[7]=sliceoffset*st    +nodespercontour*(sl+1)+pp;
+	  elements->AddN(p,8,elno);
+	}
+  
+  hasmidwallnodes=numstacks>2;
+  hasmidwallelements=numstacks>3;
+  return elements->getnumnodes();
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::\
+setCurvaturesFromDenserStacks(PXTriangulatedStack* denseInner,PXTriangulatedStack*  denseOuter)
+{
+  if (!hasnodes())
+      return 0;
+  
+  tstack[0]->updateCurvaturesFromStack(denseInner);
+  tstack[1]->updateCurvaturesFromStack(denseOuter);
+  
+  for (int i=0;i<nodes->getnumnodes();i++)
+      {
+	int st=nodes->getindex(i,0);
+	if (st>=0)
+	    {
+	      st=st>0;
+	      int pt=nodes->getindex(i,1);
+	      PXTriangulatedStackPoint* point=tstack[st]->getpoint(pt);
+	      for (int ia=0;ia<=1;ia++)
+		  nodes->getpoint(i)->k[ia]=point->k[ia];
+	    }
+      }
+  
+  return 1;
+}
+// --------------------------------------------------------------------------
+// AbaqusRelated
+// -------------
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::setSpringParameters(int enfMode,float springk)
+{
+  while(enfMode>=10)
+      enfMode-=10;
+
+  enforcementMode=Irange(enfMode,-1,5);
+  //             =-1 straight enforcement of surface displacements
+  // Where enfMode=0 straight enforcement of ALL Displacements
+  //              =1 enforcement of spring displacments
+  //              =2 2-step dance with passive
+  //              =3 echo 2d
+  //              =4 2-step active
+  //              =5 3-step actve with LL correction
+
+
+  springMultiplier=springk;
+}
+// --------------------------------------------------------------------------
+
+void PXAbaqusSolid::setNumericalParameters(float stepSize,int numInc)
+{
+  outputStep=stepSize;
+  outputInc=numInc;
+}
+
+// -------------------------------------------------------------------
+
+void px_createstring(FILE* fout,const char* newname,const char* input)
+{
+  fprintf(fout,"       CHARACTER*%d %s\n",strlen(input)+5,newname);         
+}
+
+void px_setstring(FILE* fout,const char* name,const char* input)
+{
+  fprintf(fout,"       %s='%s '\n",name,input);         
+}
+
+
+
+
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::saveAbaqusFortran(const char* fortranfile,const char* jobname,
+				     const char* solidname,const char* endostem,const char* epistem,const char* priorstem,
+				     int curvmode,float lamda,int frameoffset)
+{
+
+  if (enforcementMode==-1)
+      {
+	if (curvmode>=0)
+	    curvmode=0;
+	else
+	    curvmode=-1;
+      }
+
+  if (jobname[0]=='/')
+      {
+	fprintf(stderr,"Absolute Path name error in jobname=%s\n",jobname);
+	return(0);
+      }
+  if (solidname[0]=='/')
+      {
+	fprintf(stderr,"Absolute Path name error in solidname=%s\n",solidname);
+	return(0);
+      }
+  if (endostem[0]=='/')
+      {
+	fprintf(stderr,"Absolute Path name error in endostem=%s\n",endostem);
+	return(0);
+      }
+  if (epistem[0]=='/')
+      {
+	fprintf(stderr,"Absolute Path name error in epistem=%s\n",epistem);
+	return(0);
+      }
+
+  if (priorstem[0]=='/')
+      {
+	fprintf(stderr,"Absolute Path name error in priorstem=%s\n",priorstem);
+	return(0);
+      }
+
+
+  char* tmpname=new char[200],*command=new char[200],*path=new char[200];
+  sprintf(tmpname,"/tmp/tempdir");
+
+
+  sprintf(command,"pwd > %s",tmpname);
+  //  fprintf(stderr,"executing: %s\n",command);
+  system(command);
+
+  fprintf(stderr,"Reading: %s\n",command);
+  FILE *fin=fopen(tmpname,"r");
+  if (fin)
+      {
+	fscanf(fin,"%s\n",path);
+	sprintf(path,"%s/",path);
+	fclose(fin);
+      }
+  else
+      sprintf(path,"./");
+
+  sprintf(command,"rm %s",tmpname);
+  //  fprintf(stderr,"executing: %s\n",command);
+  system(command);
+
+  fprintf(stderr,"Step 1: Path=%s\n",path);
+
+  FILE* fout=fopen(fortranfile,"w");
+  if (!fout)
+      return 0;
+
+  char orient[10];
+  if (orientationMode>=0)
+      {
+	orientationMode=Irange(orientationMode,0,6);
+	switch(orientationMode)
+	    {
+	    case 6:
+	      strcpy(orient,"FIBRESPL");
+	      break;
+	    case 5:
+	      strcpy(orient,"XYZ123");
+	      break;
+	    case 4:
+	      strcpy(orient,"FIBRESEP");
+	      break;
+	    case 3:
+	      strcpy(orient,"CARDIACEP");
+	      break;
+	    case 2:
+	      strcpy(orient,"FIBRES");
+	      break;
+	    case 1:
+	      strcpy(orient,"CARDIAC");
+	      break;
+	    default:
+	      strcpy(orient,"XYZ");
+	      break;
+	    }
+      }
+
+  float bias=0.0;
+  // Fortran indentation 
+  char space[10];
+  strcpy(space,"     ");
+
+
+  //  fprintf(fout,"*USER SUBROUTINES\n");
+  fprintf(fout,"C%sAutomatically Generated Code by pxabaqusSolid.cc\nC\n",space);
+  fprintf(fout,"C%s this  file   =%s\nC\n",space,fortranfile);
+  fprintf(fout,"C%s path         =%s\n",space,path);
+  fprintf(fout,"C%s solid file   =%s\n",space,solidname);
+  fprintf(fout,"C%s endo stem    =%s\n",space,endostem);
+  fprintf(fout,"C%s epi stem     =%s\nC\n",space,epistem);
+  fprintf(fout,"C%s prior stem     =%s\nC\n",space,priorstem);
+  fprintf(fout,"C%s curv mode    =%d\nC\n",space,curvmode);
+  fprintf(fout,"C%s smooth lamda =%5.3f\nC\n",space,lamda);
+  fprintf(fout,"C%s frame offset =%d\nC\n",space,frameoffset);
+
+  // ----------------------------------------------------------------------------------
+
+  fprintf(fout,"%s SUBROUTINE DISP(U,KSTEP,KINC,TIME,NODE,NOEL,JDOF,COORDS)\n\n",space); 
+  fprintf(fout,"%s INCLUDE 'aba_param.inc'\n\n",space);
+  fprintf(fout,"%s external kabsodisp\n\n",space);
+  fprintf(fout,"%s DIMENSION U(3),TIME(2),COORDS(3)\n\n",space);
+
+  fprintf(fout,"C%s Define strings new style\n",space);
+  px_createstring(fout,"SS_PATHNAME",path);
+  px_createstring(fout,"SS_SOLIDNAME",solidname);
+  px_createstring(fout,"SS_JOBNAME",jobname);
+  px_createstring(fout,"SS_ENDOSTEM",endostem);
+  px_createstring(fout,"SS_EPISTEM",epistem);
+  px_createstring(fout,"SS_PRIORSTEM",priorstem);
+
+  fprintf(fout,"\n%s DOUBLE PRECISION F_BIAS,F_LAMBDA\n",space);
+  fprintf(fout,"%s INTEGER I_FOFFSET,I_ENFMODE,I_CURVMODE\n\n",space);
+
+  //  fprintf(fout,"\n%s CHARACTER*256 OUTDIR\n",space);
+  //  fprintf(fout,"%s CALL GETOUTDIR(OUTDIR,LENOUTDIR)\n",space);
+  //  fprintf(fout,"%s PRINT*,'OUTDIR=',OUTDIR,LENOUTDIR\n\n",space);
+
+  px_setstring(fout,"SS_PATHNAME",path);
+  px_setstring(fout,"SS_SOLIDNAME",solidname);
+  px_setstring(fout,"SS_JOBNAME",jobname);
+  px_setstring(fout,"SS_ENDOSTEM",endostem);
+  px_setstring(fout,"SS_EPISTEM",epistem);
+  px_setstring(fout,"SS_PRIORSTEM",priorstem);
+  fprintf(fout,"\n\n");
+
+
+  fprintf(fout,"%s F_BIAS=%f\n",space,bias);
+  fprintf(fout,"%s I_FOFFSET=%d\n",space,frameoffset);
+  fprintf(fout,"%s I_ENFMODE=%d\n",space,abs(enforcementMode));
+  fprintf(fout,"%s I_CURVMODE=%d\n",space,curvmode);
+  fprintf(fout,"%s F_LAMBDA=%f\n",space,lamda);
+  fprintf(fout,"\n\n");
+  
+  /*  fprintf(fout,"%s PRINT*,'#  DISP---------------------------------------------'\n",space);
+  fprintf(fout,"%s PRINT*,'ENFMODE=',I_ENFMODE\n",space);
+  fprintf(fout,"%s PRINT*,'FOFFSET=',I_OFFSET\n",space);
+  fprintf(fout,"%s PRINT*,'BIAS=',F_BIAS\n",space);
+  fprintf(fout,"%s PRINT*,'CURVMODE=',I_CURVMODE\n",space);
+  fprintf(fout,"%s PRINT*,'LAMBDA=',F_LAMBDA\n",space);
+  fprintf(fout,"%s PRINT*,'NODE=',NODE\n",space);
+  fprintf(fout,"%s PRINT*,'SS_PATHNAME=',SS_PATHNAME\n",space);
+  fprintf(fout,"%s U(1)=2.0\n",space);*/
+  
+
+
+  fprintf(fout,"%s CALL kabsodisp(U(1),TIME(1),TIME(2),KSTEP,KINC,NODE,JDOF,\n",space);
+  fprintf(fout,"%s1I_FOFFSET,I_ENFMODE,I_CURVMODE,F_BIAS,F_LAMBDA,\n",space);
+  fprintf(fout,"%s1SS_PATHNAME,SS_SOLIDNAME,\n",space);
+  fprintf(fout,"%s1SS_JOBNAME,SS_ENDOSTEM,\n",space);
+  fprintf(fout,"%s1SS_EPISTEM,SS_PRIORSTEM)\n",space,path,solidname);
+    //fprintf(fout,"%s U(1)=0.0\n",space);
+  //  fprintf(fout,"%s PRINT*,'#  DISP DONE=',U(1)\n",space);
+  fprintf(fout,"%s RETURN\n\n%s END\n\n\n",space,space);
+
+  // ----------------------------------------------------------------------------------
+  if (orientationMode>=0)
+      {
+	fprintf(fout,"%s SUBROUTINE ORIENT(T,NOEL,NPT,LAYER,KSPT,COORDS,BASIS,\n"
+		"%s1ORNAME,NNODES,CNODES,JNNUM)\n\n",space,space);
+	fprintf(fout,"%s INCLUDE 'aba_param.inc'\n\n",space);
+	fprintf(fout,"%s external kabsoorient\n\n",space);
+	fprintf(fout,"%s CHARACTER*80 ORNAME\n\n",space);         
+	fprintf(fout,"%s DIMENSION T(3,3),COORDS(3),BASIS(3,3),CNODES(3,NNODES)\n\n",space);
+
+	fprintf(fout,"C%s Define strings new style\n",space);
+	px_createstring(fout,"SS_ORIENTNAME",orient);
+	px_createstring(fout,"SS_PATHNAME",path);
+	px_createstring(fout,"SS_SOLIDNAME",solidname);
+
+	px_setstring(fout,"SS_ORIENTNAME",orient);
+	px_setstring(fout,"SS_PATHNAME",path);
+	px_setstring(fout,"SS_SOLIDNAME",solidname);
+	fprintf(fout,"\n\n");
+
+	fprintf(fout,"%s CALL kabsoorient(T(1,1),T(2,1),T(3,1),T(1,2),T(2,2),T(3,2),\n",space);
+	fprintf(fout,"%s1T(1,3),T(2,3),T(3,3),NOEL,SS_ORIENTNAME,\n",space);
+	fprintf(fout,"%s1SS_PATHNAME,SS_SOLIDNAME)\n\n",space);
+
+	//	fprintf(fout,"%s PRINT*,'Orientation=', T(1,1),T(2,2),T(3,3)\n",space);
+
+	fprintf(fout,"%s RETURN\n\n%s END\n\n\n",space,space);
+      }
+  
+  if (enforcementMode>0 || material->getactive())
+      {
+	fprintf(stderr,"EnforcementMode=%d\n",enforcementMode);
+
+	fprintf(fout,"%s SUBROUTINE UTEMP(TEMP,NSECPT,KSTEP,KINC,TIME,NODE,COORDS)\n\n",space);
+	fprintf(fout,"%s INCLUDE 'aba_param.inc'\n\n",space);
+	fprintf(fout,"%s external kabsotemp\n\n",space);
+	fprintf(fout,"%s DIMENSION TEMP(NSECPT),TIME(2),COORDS(3)\n\n",space);
+
+	fprintf(fout,"C%s Define strings new style\n",space);
+	px_createstring(fout,"SS_PATHNAME",path);
+	px_createstring(fout,"SS_SOLIDNAME",solidname);
+	px_createstring(fout,"SS_JOBNAME",jobname);
+	px_createstring(fout,"SS_ENDOSTEM",endostem);
+	px_createstring(fout,"SS_EPISTEM",epistem);
+	px_createstring(fout,"SS_PRIORSTEM",priorstem);
+	
+	fprintf(fout,"%s DOUBLE PRECISION F_LAMBDA\n",space);
+	fprintf(fout,"%s INTEGER I_FOFFSET,I_ENFMODE,I_CURVMODE\n",space);
+
+
+	px_setstring(fout,"SS_PATHNAME",path);
+	px_setstring(fout,"SS_SOLIDNAME",solidname);
+	px_setstring(fout,"SS_JOBNAME",jobname);
+	px_setstring(fout,"SS_ENDOSTEM",endostem);
+	px_setstring(fout,"SS_EPISTEM",epistem);
+	px_setstring(fout,"SS_PRIORSTEM",priorstem);
+	fprintf(fout,"\n\n");
+
+	fprintf(fout,"%s I_FOFFSET=%d\n",space,frameoffset);
+	fprintf(fout,"%s I_ENFMODE=%d\n",space,abs(enforcementMode));
+	fprintf(fout,"%s I_CURVMODE=%d\n",space,curvmode);
+	fprintf(fout,"%s F_LAMBDA=%f\n",space,lamda);
+	fprintf(fout,"\n\n");
+
+	fprintf(fout,"%s CALL kabsotemp(TEMP(1),KSTEP,KINC,TIME(1),TIME(2),NODE,\n",space);
+	fprintf(fout,"%s1 I_ENF_MODE,I_FOFFSET,I_CURVMODE,F_LAMBDA,\n",space);
+	fprintf(fout,"%s1SS_PATHNAME,SS_SOLIDNAME,\n",space);
+	fprintf(fout,"%s1SS_JOBNAME,SS_ENDOSTEM,\n",space);
+	fprintf(fout,"%s1SS_EPISTEM,SS_PRIORSTEM)\n",space,path,solidname);
+	fprintf(fout,"%s RETURN\n\n%s END\n\n\n",space,space);
+
+	if (material->getactive())
+	    {
+	      fprintf(stderr,"ACTIVE MATERIAL\n\n\n");
+	      fprintf(fout,"%s SUBROUTINE UEXPAN(EXPAN,DEPXANDT,TEMP,TIME,DTIME,PREDEF,\n",space);
+	      fprintf(fout,"%s1 DPRED,STATEV,CMNAME,NSTATV,NOEL)\n",space);
+	      fprintf(fout,"%s INCLUDE 'aba_param.inc'\n\n",space);
+	      fprintf(fout,"%s external kabsoexpand\n\n",space);
+	      fprintf(fout,"%s CHARACTER*80 CMNAME\n\n",space);
+	      fprintf(fout,"%s DIMENSION EXPAN(*),DEPXANDT(*),TEMP(2),TIME(2),PREDEF(*),\n",space);
+	      fprintf(fout,"%s1 DPRED(*),STATEV(NSTATV)\n\n",space);
+
+	      fprintf(fout,"%s I_ENFMODE=%d\n",space,abs(enforcementMode));
+
+	      //	      fprintf(fout,"%s PRINT*,'NOEL=',NOEL\n",space);
+	      //	      fprintf(fout,"%s PRINT*,'TIME=',TIME(1),TIME(2)\n",space);
+
+	      
+	      fprintf(fout,"%s CALL kabsoexpand(TEMP(1),TEMP(2),TIME(1),TIME(2),NOEL,I_ENFMODE,\n",space);
+	      fprintf(fout,"%s1 EXPAN(1),EXPAN(2),EXPAN(3),EXPAN(4),EXPAN(5),EXPAN(6))\n",space);
+	      //	      fprintf(fout,"%s1 DEPXANDT(1),DEPXANDT(2),DEPXANDT(3),\n",space);
+	      //	      fprintf(fout,"%s1 DEPXANDT(4),DEPXANDT(5),DEPXANDT(6))\n\n",space);
+
+	      //fprintf(fout,"%s PRINT*,'NOEL=',NOEL\n",space);
+	      //	      fprintf(fout,"%s PRINT*,'EXPAN(2)=',EXPAN(2)\n",space);
+	      //	      fprintf(fout,"%s PRINT*,'------------------------------------ DONE'\n",space);
+	      fprintf(fout,"%s RETURN\n\n%s END\n\n\n",space,space);
+
+	      // --------------------------------------------------------------------------------------
+	      
+	      /*fprintf(fout,"%s SUBROUTINE UFIELD(FIELD,KFIELD,NSECPT,KSTEP,KINC,TIME,NODE,\n",space);
+	      fprintf(fout,"%s1 COORDS,TEMP,DTEMP,NFIELD)\n\n",space);
+	      fprintf(fout,"%s INCLUDE 'ABA_PARAM.INC'\n\n",space);
+	      fprintf(fout,"%s external kabsofield\n\n",space);
+	      fprintf(fout,"%s DIMENSION  FIELD(NSECPT,NFIELD), TIME(2), COORDS(3),\n",space);
+	      fprintf(fout,"%s1 TEMP(NSECPT), DTEMP(NSECPT)\n\n",space);
+
+	      fprintf(fout,"%s DOUBLE PRECISION F_LAMBDA\n",space);
+	      fprintf(fout,"%s INTEGER I_FOFFSET,I_ENFMODE,I_CURVMODE\n",space);
+
+
+	      fprintf(fout,"C%s Define strings new style\n",space);
+	      px_createstring(fout,"SS_PATHNAME",path);
+	      px_createstring(fout,"SS_SOLIDNAME",solidname);
+	      px_createstring(fout,"SS_JOBNAME",jobname);
+	      px_createstring(fout,"SS_ENDOSTEM",endostem);
+	      px_createstring(fout,"SS_EPISTEM",epistem);
+	      px_createstring(fout,"SS_PRIORSTEM",priorstem);
+	      
+	      px_setstring(fout,"SS_PATHNAME",path);
+	      px_setstring(fout,"SS_SOLIDNAME",solidname);
+	      px_setstring(fout,"SS_JOBNAME",jobname);
+	      px_setstring(fout,"SS_ENDOSTEM",endostem);
+	      px_setstring(fout,"SS_EPISTEM",epistem);
+	      px_setstring(fout,"SS_PRIORSTEM",priorstem);
+	      fprintf(fout,"\n\n");
+	      
+	      fprintf(fout,"%s I_FOFFSET=%d\n",space,frameoffset);
+	      fprintf(fout,"%s I_ENFMODE=%d\n",space,abs(enforcementMode));
+	      fprintf(fout,"%s I_CURVMODE=%d\n",space,curvmode);
+	      fprintf(fout,"%s F_LAMBDA=%f\n",space,lamda);
+	      fprintf(fout,"\n\n");
+
+	      fprintf(fout,"%s CALL kabsofield(TEMP(1),TIME(1),TIME(2),NODE,NFIELD,\n",space);
+	      fprintf(fout,"%s1 KFIELD,FIELD(1,1),\n",space);
+	      fprintf(fout,"%s1 KSTEP,KINC,\n",space);
+	      fprintf(fout,"%s1 I_ENFMODE,I_FOFFSET,I_CURVMODE,F_LAMBDA,\n",space);
+	      fprintf(fout,"%s1 SS_PATHNAME,SS_SOLIDNAME,SS_JOBNAME,\n",space);
+	      fprintf(fout,"%s1 SS_ENDONAME,SS_EPINAME,SS_PRIORSTEM)\n",space);
+	      fprintf(fout,"%s RETURN\n\n%s END\n\n\n",space,space);      */
+	    }
+      }
+
+
+  // ----------------------------------------------------------------------------------
+  fclose(fout);
+
+  delete [] tmpname;
+  delete [] path;
+  delete [] command;
+
+  return 1;
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::insertKinematicConstraints(FILE* fout,int mode)
+{
+  if (!haselements() || !hasnodes() )
+      return 0;
+
+  if (mode<1 || hasmidwallnodes==0)
+      return 0;
+
+  if (numpointscontour==-1)
+      {
+	float botz=1000.0;//,topz=-1000.0;
+	for (int i=0;i<nodes->getnumnodes();i++)
+	    botz=Fmin(botz,nodes->getpoint(i)->x[2]);
+	
+	numpointscontour=0;
+	{
+	  for (int i=0;i<nodes->getnumnodes();i++)
+	      if (nodes->getindex(i,0)==0 && nodes->getpoint(i)->x[2]<botz+0.1)
+		  ++numpointscontour;
+	}
+	fprintf(stderr,"Botz=%7.4f numpoints=%d\n",botz,numpointscontour);
+      }
+
+  int numslices=nodes->getnumnodes()/(numpointscontour*numlayers);
+  if (debugmode)
+      fprintf(stderr,"Adding Kinematic Constraints mode=%d\n",mode);
+  int added=0;
+
+  fprintf(fout,"** ---------- Kinematic Constraints------------------------------------\n");
+
+  for (int pt=0;pt<nodes->getnumnodes();pt++)
+      {
+	int la=pt/(numslices*numpointscontour);
+	int sl=(pt-la*(numslices*numpointscontour))/numpointscontour;
+	int pi=pt-la*(numslices*numpointscontour)-sl*numpointscontour;
+
+	if (la>0 && la<numlayers-1)
+	    {
+	      if ( (sl==0 && (mode==1 || mode==3)) || (sl==numslices-1 && (mode==2 || mode==3)) )
+		  {
+		    ++added;
+		    float w2=float(la)/float(numlayers-1);
+		    float w1=1.0-w2;
+		    
+		    int in0=Icyclic(pi-1,numpointscontour)+sl*numpointscontour;
+		    int in1=Icyclic(pi-0,numpointscontour)+sl*numpointscontour;
+		    int in2=Icyclic(pi+1,numpointscontour)+sl*numpointscontour;
+		    int ou0=in0+(numlayers-1)*numpointscontour*numslices;
+		    int ou1=in1+(numlayers-1)*numpointscontour*numslices;
+		    int ou2=in2+(numlayers-1)*numpointscontour*numslices;
+		    fprintf(fout,"*EQUATION\n%d\n",7);
+		    fprintf(fout,"%d,%d,%5.3f,\n" ,PXABAQUSOFFSET+pt ,3,-1.0);
+		    fprintf(fout,"%d,%d,%5.3f, "  ,PXABAQUSOFFSET+in0,3,w1*0.25);
+		    fprintf(fout,"%d,%d,%5.3f, "  ,PXABAQUSOFFSET+in1,3,w1*0.50);
+		    fprintf(fout,"%d,%d,%5.3f,\n", PXABAQUSOFFSET+in2,3,w1*0.25);
+		    fprintf(fout,"%d,%d,%5.3f, "  ,PXABAQUSOFFSET+ou0,3,w2*0.25);
+		    fprintf(fout,"%d,%d,%5.3f, "  ,PXABAQUSOFFSET+ou1,3,w2*0.50);
+		    fprintf(fout,"%d,%d,%5.3f\n"  ,PXABAQUSOFFSET+ou2,3,w2*0.25);
+		  }
+	    }
+      }
+  fprintf(stderr,"Added %d constraints\n",added);
+  return (added);
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::fixApexorBase(FILE* fout,int md)
+{
+
+  int mode;
+  int user=0;
+  fprintf(stderr,"FixApexorBase mode=%d user=%d\n",md,user);
+  if (md<0)
+      {
+	md=-md;
+	user=1;
+      }
+
+  //if (debugmode)
+  fprintf(stderr,"FixApexorBase mode=%d user=%d\n",md,user);
+
+
+
+  if (md>=12)
+      mode=3;
+  else if (md>=8)
+      mode=2;
+  else if (md>=4)
+      mode=1;
+  else
+      mode=0;
+    
+  if (mode==1 || mode==3)
+      fprintf(stderr,"Fixing Apex ..... ");
+  if (mode==2 || mode==3)
+      fprintf(stderr,"fixing base ..... ");
+  if (user==1)
+      fprintf(stderr,"User");
+  fprintf(stderr,"\n");
+
+  if (!haselements() || !hasnodes() )
+      return 0;
+
+  if (mode<1 || hasmidwallnodes==0)
+      return 0;
+
+  if (numpointscontour==-1)
+      {
+	float botz=1000.0;//,topz=-1000.0;
+	for (int i=0;i<nodes->getnumnodes();i++)
+	    botz=Fmin(botz,nodes->getpoint(i)->x[2]);
+	
+	numpointscontour=0;
+	{
+	  for (int i=0;i<nodes->getnumnodes();i++)
+	      if (nodes->getindex(i,0)==0 && nodes->getpoint(i)->x[2]<botz+0.1)
+		  ++numpointscontour;
+	}
+	fprintf(stderr,"Botz=%7.4f numpoints=%d\n",botz,numpointscontour);
+      }
+
+  int numslices=nodes->getnumnodes()/(numpointscontour*numlayers);
+  if (debugmode)
+      fprintf(stderr,"Fixing Apex and/or Base mode=%d\n",mode);
+  int added=0;
+
+  
+  fprintf(fout,"**\n** Fixing Apex or Base\n**\n");
+  if (user)
+      fprintf(fout,"*BOUNDARY,USER,OP=NEW\n");
+  else
+      fprintf(fout,"*BOUNDARY,OP=NEW\n");
+  for (int pt=0;pt<nodes->getnumnodes();pt++)
+      {
+	int la=pt/(numslices*numpointscontour);
+	int sl=(pt-la*(numslices*numpointscontour))/numpointscontour;
+
+	if (la==0 || la==numlayers-1)
+	    {
+	      if ( (sl==0 && (mode==1 || mode==3)) || (sl==numslices-1 && (mode==2 || mode==3)) )
+		  {
+		    if (user)
+			{
+			fprintf(fout," %d , 3 , 3 \n",pt+PXABAQUSOFFSET);
+			}
+		    else
+			fprintf(fout," %d , 3 , 3 , 0.0\n",pt+PXABAQUSOFFSET);
+		    ++added;
+		  }
+	    }
+      }
+
+  fprintf(stderr,"Fixed z  %d nodes\n",added);
+  return (added);
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::CreateJobBase(FILE* fout,const char* includefile,int springmode)
+{
+  fprintf(fout,"*HEADING\nMyocardium Model\n");
+  fprintf(fout,"** numnodes=%d, numelements=%d\n",nodes->getnumnodes(),elements->getnumnodes());
+  fprintf(fout,"** ----------------------------------------------------\n");
+  //  fprintf(fout,"** Shrink .dat file\n*PREPRINT,ECHO=NO,MODEL=NO,HISTORY=NO\n**\n");
+
+  if (includefile!=NULL)
+      {
+	fprintf(fout,"** ------------ Fortran Code ---------------------------\n");
+	fprintf(fout,"**INCLUDE,INPUT=%s\n",includefile);
+      }
+
+  fprintf(fout,"** ----------Material Model --------------------------------------\n");
+  
+  material->SaveAbaqus(fout,"TISSUE");
+  
+  fprintf(fout,"** ---------- Nodes  --------------------------------------\n");
+  for (int pass=0;pass<=2;pass++)
+      {
+	switch (pass)
+	    {
+	    case 0:
+	      fprintf(fout,"*NODE,NSET=N_ENDO\n");
+	      break;
+	    case 1:
+	      if (hasmidwallnodes)
+		  fprintf(fout,"*NODE,NSET=N_MID\n");
+	      break;
+	    case 2:
+	      fprintf(fout,"*NODE,NSET=N_EPI\n");
+	      break;
+	    }
+	for (int i=0;i<nodes->getnumnodes();i++)
+	    {
+	      int pa=nodes->getindex(i,0);
+	      
+	      if (
+		  (pa==0   && pass==0) || 
+		  (pa==100 && pass==2) ||
+		  (pass==1 && pa!=0 && pa!=100 && hasmidwallnodes) 
+		  )
+	    fprintf(fout," %5d , %7.3f , %7.3f , %7.3f \n",
+		    i+PXABAQUSOFFSET,
+		    nodes->getpoint(i)->x[0],
+		    nodes->getpoint(i)->x[1],
+		    nodes->getpoint(i)->x[2]);
+	    }
+      }
+  
+  if (springmode>0)
+      {
+	// Add Nodes to attach springs to
+	fprintf(fout,"*NODE,NSET=EXTRA\n");
+	for (int i=0;i<springNodes->getnumnodes();i++)
+	    {
+	      fprintf(fout," %6d , %7.4f , %7.4f, %7.4f\n",
+		      i+nodes->getnumnodes()+PXABAQUSOFFSET,
+		      springNodes->getpoint(i)->x[0],
+		      springNodes->getpoint(i)->x[1],
+		      springNodes->getpoint(i)->x[2]);
+	    }
+      }
+  else
+      fprintf(stderr,"Ignoring springNodes\n");
+  
+  fprintf(fout,"**\n");
+  fprintf(fout,"*NSET, NSET=ALLNODES\n");
+  fprintf(fout,"N_ENDO,N_EPI");
+  if (hasmidwallnodes)
+      fprintf(fout,",N_MID");
+  fprintf(fout,"\n*NSET, NSET=N_DUMMY\n1000\n");
+  
+  
+  fprintf(fout,"** ---------- Elements --------------------------------------\n");  
+  char elementname[20];
+  int inco=(elementmode>100);
+  int numnodes=elementmode-inco*100;
+  sprintf(elementname,"C3D%d",numnodes);
+  if (inco)
+      sprintf(elementname,"%sH",elementname);
+
+  fprintf(stderr,"Using element type=%s\n",elementname);
+
+  
+  
+  for (int layer=0;layer<numlayers-1;layer++)
+      {
+	fprintf(fout,"** layer=%d/%d\n",layer,numlayers);
+	if (layer==0)
+	  fprintf(fout,"*ELEMENT, TYPE=%s, ELSET=E_ENDO\n",elementname);
+	else if (layer==numlayers-2)
+	  fprintf(fout,"*ELEMENT, TYPE=%s, ELSET=E_EPI\n",elementname);
+	else 
+	  fprintf(fout,"*ELEMENT, TYPE=%s, ELSET=E_MID_%d\n",elementname,layer);
+	
+	elements->Rewind();
+	int elno=PXABAQUSOFFSET;
+	for (int el=0;el<elements->getnumnodes();el++)
+	  {
+	    PXIntegerList* intList=((elements->getcurrentnode())->points);
+	    intList->Rewind();
+	    int first=intList->getcurrent();
+	    intList->Next();
+	    int second=intList->getcurrent();
+	    intList->Rewind();
+
+	    int printelement=0;
+	    int node1l=nodes->getindex(first,0);
+	    int node2l=nodes->getindex(second,0);
+
+	    if (node1l==0 && layer==0)
+	      printelement=1;
+	    else if (node2l==100 && layer==(numlayers-2))
+	      printelement=1;
+	    else if (node1l!=0 && node2l !=100 && layer!=0 && layer!=(numlayers-2))
+	      printelement=1;
+
+	    if (printelement)
+	      {
+		fprintf(fout,"%d,",elno);
+		for (int i=0;i<intList->getnumnodes();i++)
+		  {
+		    fprintf(fout,"%d",intList->getcurrent()+PXABAQUSOFFSET);
+		    if (i!=intList->getnumnodes()-1)
+		      fprintf(fout,",");
+		    else
+		      fprintf(fout,"\n");
+		    intList->Next();
+		  }
+	      }
+	    elements->Next();
+	    elno++;
+	  }
+      }
+  fprintf(fout,"** \n");
+
+  if (springmode>0)
+      {
+	fprintf(fout,"*ELEMENT,TYPE=SPRINGA,ELSET=ENFSET\n");
+	springElements->Rewind();
+	for (int i=0;i<springElements->getnumnodes();i++)
+	    {
+	      PXIntegerList* intList=((springElements->getcurrentnode())->points);
+	      intList->Rewind();
+	      int ep1=intList->getcurrent();
+	      intList->Next();
+	      int ep2=intList->getcurrent();
+	      fprintf(fout,"%d , %d, %d\n",
+		      elements->getnumnodes()+i+PXABAQUSOFFSET,
+		      ep1+PXABAQUSOFFSET,ep2+PXABAQUSOFFSET);
+	      springElements->Next();
+	    }
+	fprintf(fout,"** \n");
+	fprintf(fout,"*SPRING,ELSET=ENFSET,DEPENDENCIES=2\n\n");
+	fprintf(fout," %5.2f , 0.0 ,  0.0\n",0.01);
+	fprintf(fout," %5.2f , 1.0 ,  0.0\n",0.01);
+	fprintf(fout," %5.2f , 0.0 ,  1.0\n",springMultiplier);
+	fprintf(fout," %5.2f , 1.0 ,  1.0\n",springMultiplier);
+	fprintf(fout,"** \n");
+      }
+
+  
+  fprintf(fout,"*ELSET, ELSET=HWALL\n");
+
+  fprintf(fout,"E_ENDO");
+  
+  if (numlayers>2)
+    {
+      for (int ia=1;ia<numlayers-2;ia++)
+	fprintf(fout,",E_MID_%d",ia);
+    }
+  if (numlayers>1)
+    fprintf(fout,",E_EPI");
+
+
+
+  fprintf(fout,"\n**\n");
+  fprintf(fout,"*ELSET, ELSET=E_DUMMY\n1000\n**\n");
+  
+  fprintf(fout,"** ---------- Solid  --------------------------------------\n");
+  char orient[10];
+  orientationMode=Irange(orientationMode,0,4);
+  if (orientationMode>=0)
+      {
+	switch(orientationMode)
+	    {
+	    case 6:
+	      strcpy(orient,"FIBRESPL");
+	      break;
+	    case 4:
+	      strcpy(orient,"FIBRESEP");
+	      break;
+	    case 3:
+	      strcpy(orient,"CARDIACEP");
+	      break;
+	    case 2:
+	      strcpy(orient,"FIBRES");
+	      break;
+	    case 1:
+	      strcpy(orient,"CARDIAC");
+	      break;
+	    default:
+	      strcpy(orient,"XYZ");
+	      break;
+	    }
+	fprintf(fout,"*ORIENTATION,SYSTEM=USER,NAME=%s\n",orient);
+	fprintf(fout,"*SOLID SECTION, ELSET=HWALL,MATERIAL=TISSUE,ORIENTATION=%s\n",orient);
+      }
+  else
+      fprintf(fout,"*SOLID SECTION, ELSET=HWALL,MATERIAL=TISSUE\n");
+
+  return 1;
+
+}
+// --------------------------------------------------------------------------
+int  PXAbaqusSolid::CreateStepHeader(FILE* fout)
+{
+  fprintf(fout,"*STEP");
+  if (material->getgeometry()==1)
+      fprintf(fout,",NLGEOM");
+  fprintf(fout,",AMPLITUDE=RAMP,INC=%d\n",outputInc);
+  fprintf(fout,"*STATIC\n %f,1.0,0.00005,1.0\n",Frange(outputStep,0.05,1.0));
+  fprintf(fout,"**\n");
+  fprintf(fout,"** Accuracy Controls\n*CONTROLS,PARAMETERS=FIELD,FIELD=DISPLACEMENT\n");
+  fprintf(fout,"0.01,1.0,10.0,  ,  , 1.E-3\n");
+  return 1;
+}
+// --------------------------------------------------------------------------
+int  PXAbaqusSolid::CreateStepFooter(FILE* fout,int resout,int fieldout)
+{
+
+  if (fieldout)
+      {
+	fprintf(fout,"**\n*EL PRINT,POSITION=CENTROIDAL,ELSET=HWALL\nFV\n");
+	fprintf(fout,"*EL PRINT,POSITION=CENTROIDAL,ELSET=HWALL\nTHE\n");
+	fprintf(fout,"*EL PRINT,POSITION=CENTROIDAL,ELSET=HWALL\nEE\n");
+	fprintf(fout,"*EL PRINT,POSITION=CENTROIDAL,ELSET=HWALL\nE\n");
+	fprintf(fout,"*NODE PRINT,NSET=ALLNODES\nU\n");
+	fprintf(fout,"*NODE PRINT,NSET=EXTRA\nU\n");
+	fprintf(fout,"*NODE PRINT,NSET=ALLNODES\nNT\n");
+	fprintf(fout,"*NODE PRINT,NSET=EXTRA\nNT\n");
+      }
+  else
+      {
+	fprintf(fout,"**\n*EL PRINT,POSITION=CENTROIDAL,ELSET=E_DUMMY\nEP1\n");
+	fprintf(fout,"*NODE PRINT,NSET=N_DUMMY\nU1\n");
+	fprintf(fout,"*NODE PRINT,NSET=N_DUMMY\nNT\n");
+      }
+  fprintf(fout,"*EL FILE,POSITION=CENTROIDAL,ELSET=HWALL\nE\n");
+  fprintf(fout,"*EL FILE,ELSET=HWALL\nEVOL\n*NODE FILE,NSET=ALLNODES\nU\n");
+  //  fprintf(fout,"*EL FILE,ELSET=HWALL\nCOORD\n");
+  fprintf(fout,"*NODE FILE,NSET=ALLNODES\nCOORD\n");
+
+
+  if (resout>0)
+      fprintf(fout,"*RESTART,WRITE\n");
+  fprintf(fout,"*END STEP\n");
+  return 1;
+}
+
+// --------------------------------------------------------------------------
+int  PXAbaqusSolid::CreateSteps2DEcho(FILE* fout,int numframes,int resout)
+{
+  int upper=numframes*2;
+  
+  for (int fr=0;fr<upper;fr++)
+      {
+	int odd=1;
+	if (2*int(fr/2)==fr)
+	    odd=0;
+	
+	fprintf(fout,"** -------------------- Frame %d Part %d---------------------\n**\n",
+		fr/2+1,odd+1);
+	CreateStepHeader(fout);
+	
+	if (odd==1)
+	    {
+	      fprintf(fout,"*BOUNDARY,USER,OP=NEW\n");
+	      fprintf(fout,"EXTRA,1,2\n");
+	      fprintf(fout,"N_ENDO,1,2\nN_EPI,1,2\n");
+	      fprintf(fout,"*BOUNDARY,OP=NEW\n");
+	      fprintf(fout,"EXTRA,3,3,0.0\n");
+	      fprintf(fout,"N_ENDO,3,3,0.0\nN_EPI,3,3,0.0\n");
+	    }
+	else
+	    {
+	      fprintf(fout,"*BOUNDARY,USER,OP=NEW\n");
+	      fprintf(fout,"EXTRA,1,2\n");
+	      fprintf(fout,"*BOUNDARY,OP=NEW\n");
+	      fprintf(fout,"EXTRA,3,3,0.0\n");
+
+	      if (material->getactive()>0)
+		  {
+		    fprintf(fout,"*TEMPERATURE,USER,OP=NEW\n");
+		    fprintf(fout,"EXTRA,\n");
+		    fprintf(fout,"N_ENDO,\n");
+		    if (hasmidwallnodes)
+			fprintf(fout,"N_MID,\n");
+		    fprintf(fout,"N_EPI\n");
+		  }
+	    }
+	CreateStepFooter(fout,resout,0);
+      }
+  return 1;
+}
+// --------------------------------------------------------------------------
+int  PXAbaqusSolid::CreateStepsPassive3D(FILE* fout,int numframes,int resout,int flattopbottom)
+{
+  int upper=numframes*2;
+  
+  for (int fr=0;fr<upper;fr++)
+      {
+	int odd=1;
+	if (2*int(fr/2)==fr)
+	    odd=0;
+	
+	fprintf(fout,"** -------------------- Frame %d Part %d---------------------\n**\n",
+		fr/2+1,odd+1);
+
+	CreateStepHeader(fout);
+
+	if (odd==1)
+	    {
+	      fprintf(fout,"*BOUNDARY,USER,OP=NEW\n");
+	      fprintf(fout,"EXTRA,1,3\n");
+	      fprintf(fout,"N_ENDO,1,3\nN_EPI,1,3\n");
+	    }
+	else
+	    {
+	      fprintf(fout,"*BOUNDARY,USER,OP=NEW\n");
+	      fprintf(fout,"EXTRA,1,3\n");
+	      /*if (flattopbottom>3)
+		  fixApexorBase(fout,flattopbottom);*/
+	      
+	      fprintf(fout,"*TEMPERATURE,USER,OP=NEW\n");
+	      fprintf(fout,"EXTRA,\n");
+	      fprintf(fout,"N_ENDO,\n");
+	      if (hasmidwallnodes)
+		  fprintf(fout,"N_MID,\n");
+	      fprintf(fout,"N_EPI\n");
+	    }
+
+	CreateStepFooter(fout,resout,0);
+      }
+  return 1;
+}
+// --------------------------------------------------------------------------
+int  PXAbaqusSolid::CreateStepsActive3D(FILE* fout,int numframes,int resout,int flattopbottom)
+{
+  int numsteps=2;
+  if (enforcementMode==5)
+      numsteps=3;
+
+  for (int fr=0;fr<numframes;fr++)
+      {
+	for (int substep=0;substep<numsteps;substep++)
+	    {
+	      fprintf(fout,"** -------------------- Frame %d Part %d---------------------\n**\n",
+		      fr+1,substep+1);
+	      fprintf(stderr,"** -------------------- Frame %d Part %d---------------------\n**\n",
+		      fr+1,substep+1);
+	      
+	      float old=outputStep;
+	      if (substep<2)
+		  outputStep=1.0;
+	      CreateStepHeader(fout);
+	      outputStep=old;
+
+	      if (enforcementMode==5)
+		  {
+		    if (substep==0)
+			fprintf(fout,"*MODEL CHANGE,REMOVE,TYPE=ELEMENT\nENFSET,\n");
+		    if (substep==2)
+			fprintf(fout,"*MODEL CHANGE,ADD,TYPE=ELEMENT\nENFSET,\n");
+		  }
+		    
+	      if (substep==0)
+		  {
+		    fprintf(fout,"*BOUNDARY,USER,OP=NEW\n");
+		    if (enforcementMode==4)
+			fprintf(fout,"EXTRA,1,3\n");
+		    fprintf(fout,"N_ENDO,1,3\nN_EPI,1,3\n");
+		  }
+	      
+	      if (substep==1)
+		  {
+		    fprintf(fout,"*BOUNDARY,USER,OP=NEW\n");
+		    if (enforcementMode==5)
+			{
+			  for (float s=0.0;s<=0.667;s+=0.333)
+			      {
+				int nd=getnodenofromfractionalcoordinates(0.0,0,s);
+				fprintf(fout,"%d , 1  ,3 \n",nd+PXABAQUSOFFSET);
+			      }
+			}
+		    else
+			fprintf(fout,"EXTRA,1,3\n");
+		    
+		    if (flattopbottom>3)
+			fixApexorBase(fout,-flattopbottom);
+		  }
+		   
+	      if (substep==2)
+		  {
+		    fprintf(fout,"*BOUNDARY,USER,OP=NEW\n");
+		    fprintf(fout,"EXTRA,1,3\n");
+		    if (flattopbottom>3)
+			fixApexorBase(fout,flattopbottom);
+		  }
+
+	      if (substep==1 || substep==2)
+		  {
+		    /*		    for (int kk=1;kk<=4;kk++)
+			{
+			  fprintf(fout,"*FIELD,VARIABLE=%d,USER,OP=NEW\n",kk);
+			  fprintf(fout,"ALLNODES,0.0\n");
+			  }*/
+		    fprintf(fout,"*TEMPERATURE,USER,OP=NEW\n");
+		    if ((substep==1 && enforcementMode==5) || enforcementMode==4)
+			fprintf(fout,"EXTRA,\n");
+		    fprintf(fout,"N_ENDO,\n");
+		    if (hasmidwallnodes)
+			fprintf(fout,"N_MID,\n");
+		    fprintf(fout,"N_EPI\n");
+		  }
+	      CreateStepFooter(fout,resout,0);
+	    }
+      }
+  return 1;
+}
+// --------------------------------------------------------------------------
+int  PXAbaqusSolid::CreateStepsSinglePass(FILE* fout,int numframes,int springmode,int resout,
+					  int flattopbottom)
+{
+
+  float old=outputStep;
+  if (springmode<=0)
+      outputStep=1.0;
+
+  for (int fr=0;fr<numframes;fr++)
+      {
+	fprintf(fout,"** -------------------- Frame %d ---------------------------\n**\n",fr+1);
+	CreateStepHeader(fout);
+	
+	switch(springmode)
+	    {
+	      case 0:
+	      fprintf(fout,"*BOUNDARY,USER,OP=NEW\n");
+	      fprintf(fout,"ALLNODES,1,3\n");
+	      break;
+	    case -1:
+	      fprintf(fout,"*BOUNDARY,USER,OP=NEW\n");
+	      fprintf(fout,"N_ENDO,1,3\n");
+	      fprintf(fout,"N_EPI,1,3\n");
+	      break;
+	    default:
+	      fprintf(fout,"*BOUNDARY,USER,OP=NEW\n");
+	      fprintf(fout,"EXTRA,1,3\n");
+	      if (flattopbottom>3)
+		  fixApexorBase(fout,flattopbottom);
+	      fprintf(fout,"*TEMPERATURE,USER,OP=NEW\n");
+	      fprintf(fout,"EXTRA,\n");
+	      fprintf(fout,"N_ENDO,\n");
+	      if (hasmidwallnodes)
+		  fprintf(fout,"N_MID,\n");
+	      fprintf(fout,"N_EPI\n");
+	    }
+	CreateStepFooter(fout,resout,0);
+      }
+      outputStep=old;
+  return 1;
+}
+// --------------------------------------------------------------------------
+
+int PXAbaqusSolid::saveAbaqus(const char* fname,int resout,int numframes,const char* includefile,
+			      int flattopbottom)
+{
+  if (!hasnodes() || !hasmaterial() || !haselements())
+      {
+	fprintf(stderr,"No nodes,elements or material\n");
+	return 0;
+      }
+
+  if (numframes==-1)
+      numframes=0;
+
+  // [1] Open File with proper filename
+  // ----------------------------------
+  char* abname=anacreatefilename(fname,".inp",".sld");
+  fprintf(stderr,"%s --> %s (%d)\n",fname,abname,numframes);
+
+  FILE* fout=fopen(abname,"w");
+  if (!fout)
+      {
+	delete [] abname;
+	return 0;
+      }
+
+  // [2] Add Nodes and Elements and Material Props etc
+  // -------------------------------------------------
+  int springmode=1; // 1--> creates springs 
+  if (enforcementMode<=0)
+      springmode=0;
+  
+  
+  CreateJobBase(fout,includefile,springmode);
+
+  // [3] Add Kinematic Constraints to keep bottom and top smooth
+  // -----------------------------------------------------------
+  int flat=flattopbottom;
+  if (flat>=8) flat-=8;
+  if (flat>=4) flat-=4;
+  int kin=insertKinematicConstraints(fout,flat);
+  fprintf(stderr,"Number of kinematic constraints=%d (mode=%d)\n",kin,flat);
+
+  // [4] Add Initial Conditions for temperature and fields (if active)
+  // -----------------------------------------------------------------
+  fprintf(fout,"** -------------------- Initial Conditions --------------\n**\n");  
+  fprintf(fout,"*INITIAL CONDITIONS,TYPE=TEMPERATURE\n");
+  if (springmode>0)
+      fprintf(fout,"EXTRA , 1.0\n");
+  fprintf(fout,"ALLNODES , 1.0\n");
+  
+  /*  if (material->getactive())
+         {
+	for (int kk=1;kk<=4;kk++)
+	    {
+	      fprintf(fout,"*INITIAL CONDITIONS,TYPE=FIELD,VARIABLE=%d\n",kk);
+	      fprintf(fout,"ALLNODES , 0.0\n");
+	    }
+	    }*/
+  
+  // [5] Create a dummy step just to make sure of everything
+  // -------------------------------------------------------
+  fprintf(fout,"** -------------------- Dummy Step ---------------------------\n**\n");
+  fprintf(fout,"** Dummy Step\n");
+  fprintf(fout,"*STEP");
+  if (material->getgeometry()==1)
+      fprintf(fout,",NLGEOM");
+  fprintf(fout,",INC=50\n*STATIC\n*BOUNDARY\nN_ENDO,1,3,0.0\nN_EPI,1,3,0.0\n");
+  if (springmode>0 && enforcementMode!=0)
+      fprintf(fout,"EXTRA,1,3,0.0\n");
+  fprintf(fout,"*EL PRINT,POSITION=CENTROIDAL,ELSET=E_DUMMY\nEP1\n");
+   
+  fprintf(fout,"*NODE PRINT,NSET=N_DUMMY\nU1\n");
+  fprintf(fout,"*EL FILE,POSITION=CENTROIDAL,ELSET=HWALL\nE\n");
+  fprintf(fout,"*EL FILE,ELSET=HWALL\nEVOL\n*NODE FILE,NSET=ALLNODES\nU\n");
+  //  fprintf(fout,"*EL FILE,ELSET=HWALL\nCOORD\n");
+  fprintf(fout,"*NODE FILE,NSET=ALLNODES\nCOORD\n");
+  if (resout>0)
+      fprintf(fout,"*RESTART,WRITE\n");
+  fprintf(fout,"*END STEP\n");
+  
+  /* enforcement Modes
+     All Displacements Specified via *USER option and all temperatures via *USER
+     
+     First two modes 
+     Mode 0= Simply enforce displacements on all nodes
+     Mode-1=Enforce displacements of boundary nodes;
+     Mode 1= Attach Springs and enforce displacements on outer spring node via user
+     Mode 2= Two Step Process first enforce outer then both (passive)
+     Mode 3= 2D Echo
+     Mode 4= 3-step active
+
+     */
+
+  // [6] Create real steps depending on enforcementMode
+  // --------------------------------------------------
+
+  fprintf(fout,"** -------------------- Real Steps ---------------------------\n**\n");
+  fprintf(stderr,"*** ---- Creating Real Steps (enfMode=%d , resout=%d)\n",enforcementMode,resout);
+  switch (enforcementMode)
+      {
+      case 2:
+	CreateStepsPassive3D(fout,numframes,resout,flattopbottom);
+	break;
+      case 3:
+	CreateSteps2DEcho(fout,numframes,resout);
+	break;
+      case 4:
+	CreateStepsActive3D(fout,numframes,resout,flattopbottom);
+	break;
+      case 5:
+	CreateStepsActive3D(fout,numframes,resout,flattopbottom);
+	break;
+      default:
+	CreateStepsSinglePass(fout,numframes,enforcementMode,resout,flattopbottom);
+	break;
+      }
+  
+  fprintf(fout,"** End of File\n");
+  fclose(fout);
+  return 1;
+}
+// --------------------------------------------------------------------------
+PXTriangulatedStackPoint* PXAbaqusSolid::getpoint(int index,int *total,int numstacks)
+{
+  int st=PXTriangulatedStack::whichstack(index,total,numstacks);
+  int pt=index-total[st];
+  return tstack[st]->getpoint(pt);
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::Save(const char* fname)
+{
+  if (!haselements() || !hasnodes())
+      return 0;
+  
+  FILE* fout=fopen(fname,"w");
+  if (fout!=NULL)
+      {
+	int st=Save(fout);
+	fclose(fout);
+	return st;
+      }
+  return 0;
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::Save(FILE* fout)
+{
+  if (!haselements() || !hasnodes())
+      return 0;
+
+  fprintf(fout,"#NewAbaqusSolid3\n");
+  fprintf(fout,"#Number of layers,points per slice \n");
+  fprintf(fout,"%d\n",numlayers);
+  fprintf(fout,"%d\n",numpointscontour);
+  for (int t=0;t<2;t++)
+      tstack[t]->Save(fout);
+  fprintf(fout,"# ---------------------------------------------------\n");
+  fprintf(fout,"#Material Model\n");
+  if (!hasmaterial())
+      fprintf(fout,"# No Material\n");
+  else
+      material->Save(fout);
+  fprintf(fout,"# ---------------------------------------------------\n");
+  fprintf(fout,"# Solid Nodes\n");
+  nodes->Save(fout);
+  fprintf(fout,"# ---------------------------------------------------\n");
+  fprintf(fout,"# Spring Nodes\n");
+  if (hasspringnodes())
+      springNodes->Save(fout);
+  else
+      fprintf(fout,"#No Spring Nodes\n");
+
+  fprintf(fout,"# ---------------------------------------------------\n");
+  fprintf(fout,"# Solid Elements\n");
+  elements->Save(fout);
+
+  fprintf(fout,"# ---------------------------------------------------\n");
+  fprintf(fout,"# Spring Elements\n"); 
+  if (hasspringelements())
+      springElements->Save(fout);
+  else
+      fprintf(fout,"#No Spring Elements\n"); 
+  fprintf(fout,"# ---------------------------------------------------\n");
+  fprintf(fout,"#Numerical Constants\n");
+  fprintf(fout,"#Element Mode\n%d\n",elementmode);
+  fprintf(fout,"#Output Step\n%6.3f\n",outputStep);
+  fprintf(fout,"#Output Inc\n%d\n",outputInc);
+  fprintf(fout,"#Enforcement Strategy\n%d\n",enforcementMode);
+  fprintf(fout,"#Spring Multiplier\n%5.3f\n",springMultiplier);
+  fprintf(fout,"#Orientation\n%d\n",orientationMode);
+  return 1;
+  
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::Load(const char* filename)
+{
+
+  //fprintf(stderr,"In solid loading filename %s\n",filename);
+
+  gzFile fin=gzsuffixopen(filename,"r");
+  //fprintf(stderr,"After gzFile\n");
+  if (!fin)
+      {
+	if (debugmode)
+	    fprintf(stderr,"File: %s not found\n",filename);
+	return 0;
+      }
+  int st=Load(fin);
+  gzclose(fin);
+
+  return st;
+}
+// ------------------------------------------------------------------------
+int PXAbaqusSolid::Load(gzFile fin)
+{
+  char line[200];
+  gzgets(fin,line,200);
+  //fprintf(stderr,"Line=%s\n",line);
+  int mode=0;
+  if (gzfindstringinstring(line, "#NewAbaqusSolid3"))
+      mode=3;
+  else
+      {
+	if (gzfindstringinstring(line, "#NewAbaqusSolid2"))
+	    mode=2;
+	else 
+	    {
+	      if (gzfindstringinstring(line, "#NewAbaqusSolid"))
+		  mode=1;
+	    }
+      }
+
+  if (debugmode)
+      fprintf(stderr,"Line=%s\n",line);
+  if (mode==0)
+      return 0;
+  
+  // Step 1: Read in Stacks
+  // ----------------------
+  cleanup();
+  init();
+  
+  int numstacks=2;
+  gzgets(fin,line,200);   gzgets(fin,line,200);
+  sscanf(line,"%d",&numlayers);
+  if (debugmode)
+      fprintf(stderr,"Numstacks=%d\n",numlayers);
+
+  if (mode==3)
+      {
+	gzgets(fin,line,200);
+	sscanf(line,"%d",&numpointscontour);
+      }
+  hasmidwallnodes=numlayers>1;
+  hasmidwallelements=numlayers>2;
+
+  tstack[0]=new PXTriangulatedStack();
+  tstack[1]=new PXTriangulatedStack();
+  
+  if (mode==1)
+      numstacks=numlayers;
+
+  for (int i=0;i<numstacks;i++)
+      {
+	if (debugmode)
+	    fprintf(stderr,"Reading stack %d ... ",i);
+
+	int ok=tstack[i>0]->Load(fin);
+	if (debugmode)
+	    fprintf(stderr,"status %d\n",ok);
+      }
+  
+  if (debugmode)
+      fprintf(stderr,"Done Stacks\n");
+  
+  // Step 2: Read in Material Model
+  // ------------------------------
+  gzgets(fin,line,200);   gzgets(fin,line,200);
+  if (debugmode)
+    fprintf(stderr,"%s",line);
+  allocateMaterial();
+  if (material->Load(fin)==0)
+      cleanupMaterial();
+  
+  // Step 3: Read in Nodes and Elements
+  // ----------------------------------
+  gzgets(fin,line,200);   gzgets(fin,line,200);
+  if (debugmode) fprintf(stderr,"%s",line);
+  allocateNodeSpace(1);
+
+  springNodes=new PXSolidNodes(1);
+  springElements=new PXNeighboursList();
+  hasSpringNodes=1;
+  hasSpringElements=1;
+
+  if (nodes->Load(fin)==0)
+      {
+	cleanupNodeSpace();
+	return 0;
+      }
+
+  allocateElementSpace();
+
+  gzgets(fin,line,200);   gzgets(fin,line,200);
+  if (debugmode) fprintf(stderr,"%s",line);
+  int spN=springNodes->Load(fin);
+  if (debugmode)
+      if (spN>0)
+	  fprintf(stderr,"Numspr nd =%d \n",springNodes->getnumnodes());
+      else
+	  fprintf(stderr,"No Spring Nodes\n");
+
+  gzgets(fin,line,200);   gzgets(fin,line,200);
+  if (debugmode) fprintf(stderr,"%s",line);
+  elements->Load(fin);
+  if (debugmode) fprintf(stderr,"Numelements=%d\n",elements->getnumnodes());
+
+  gzgets(fin,line,200);   gzgets(fin,line,200);
+  if (debugmode) 
+      fprintf(stderr,"%s",line);
+  int spS=springElements->Load(fin);
+  if (debugmode)
+      if (spS>0)
+	  fprintf(stderr,"Numspr el =%d \n",springElements->getnumnodes());
+      else
+	  fprintf(stderr,"No Spring Elements \n");
+
+  if (spS==0 || spN==0)
+      cleanupSpringSpace();	
+
+
+  if (debugmode)
+    {
+      fprintf(stderr,"Stats nodes=%d hasnodes=%d, elements=%d, haselements=%d\n",
+	      nodes->getnumnodes(),
+	      hasnodes(),
+	      elements->getnumnodes(),
+	      haselements());
+      
+      if (hasspringnodes() && hasspringelements())
+	fprintf(stderr,"\tspringnodes=%d hasspringnodes=%d, springelements=%d, hasspringelements=%d\n",
+		springNodes->getnumnodes(),
+		hasspringnodes(),
+		springElements->getnumnodes(),
+		hasspringelements());
+    }
+  
+  // Step 4: Read in Constants
+  // -------------------------
+  gzgets(fin,line,200);   gzgets(fin,line,200);
+  if (debugmode) fprintf(stderr,"%s",line);
+  gzgets(fin,line,200);   gzgets(fin,line,200); sscanf(line,"%d",&elementmode);
+  gzgets(fin,line,200);   gzgets(fin,line,200); sscanf(line,"%f",&outputStep);
+  gzgets(fin,line,200);   gzgets(fin,line,200); sscanf(line,"%d",&outputInc);
+  gzgets(fin,line,200);   gzgets(fin,line,200); sscanf(line,"%d",&enforcementMode);
+  gzgets(fin,line,200);   gzgets(fin,line,200); sscanf(line,"%f",&springMultiplier);
+
+  if (gzgets(fin,line,200))
+      {
+	gzgets(fin,line,200);
+	sscanf(line,"%d",&orientationMode);
+      }
+  else
+      orientationMode=0;
+  
+  // Step 5: Cleanup up all the rest
+  // -------------------------------
+  cleanupFemData();
+  if (hasvolumes())
+      {
+	delete [] volume;
+	hasVolumes=0;
+      }
+  
+  if (mode!=3)
+      {
+	float botz=1000.0;
+	for (int i=0;i<nodes->getnumnodes();i++)
+	    botz=Fmin(botz,nodes->getpoint(i)->x[2]);
+	numpointscontour=0;
+	{
+	  for (int i=0;i<nodes->getnumnodes();i++)
+	    if (nodes->getindex(i,0)==0 && nodes->getpoint(i)->x[2]<botz+0.1)
+		++numpointscontour;
+	}
+	//fprintf(stderr,"Load:: Botz=%7.4f numpoints=%d\n",botz,numpointscontour);
+      }
+  return mode;
+}
+// ------------------------------------------------------------------------
+void PXAbaqusSolid::getdirections(PXIntegerList* element,
+				  float& nx1,float& ny1,float& nz1,
+				  float& nx2,float& ny2,float& nz2,
+				  float& nx3,float& ny3,float& nz3,
+				  int movetoepi)
+{
+  if (!haselements() || !hasnodes() || element->getnumnodes()!=8)
+      return;
+  
+  element->Rewind();
+  
+  PX3Vector c0(0.0 ,0.0,0.0);
+  PX3Vector c1(0.0 ,0.0,0.0);
+  PX3Vector r0(0.0 ,0.0,0.0);
+  PX3Vector r1(0.0 ,0.0,0.0);
+
+  int nodeoffset=0;
+  if (movetoepi && numlayers>1)
+      {
+	int offsetmult=nodes->getnumnodes()/numlayers;
+	int basest=int(0.5+float(numlayers)*
+		       float(nodes->getindex(element->getcurrent(),0))/float(100.0));
+	nodeoffset=((numlayers-2)-basest)*offsetmult;
+      }
+    
+
+  for (int localnode=1;localnode<=8;localnode++)
+      {
+	int index=element->getcurrent()+nodeoffset;
+
+	if (localnode==1 || localnode==2 || localnode==5 || localnode==6)
+	    { // Anticlockwise-most face
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    c0.x[ia]+=nodes->getpoint(index)->x[ia]; 
+		    if (hasfemdata())
+			c0.x[ia]+=femData->getdispcomponent(index,ia);
+		  }
+	    }
+	else
+	    { // Clockwisemost face  
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    c1.x[ia]+=nodes->getpoint(index)->x[ia]; 
+		    if (hasfemdata())
+			c1.x[ia]+=femData->getdispcomponent(index,ia);
+		  }
+	    }
+
+	if (localnode==1 || localnode==4 || localnode==5 || localnode==8)
+	    { // Anticlockwise-most face
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    r0.x[ia]+=nodes->getpoint(index)->x[ia]; 
+		    if (hasfemdata())
+			r0.x[ia]+=femData->getdispcomponent(index,ia);
+		  }
+	    }
+	else
+	    { // Clockwisemost face  
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    r1.x[ia]+=nodes->getpoint(index)->x[ia]; 
+		    if (hasfemdata())
+			r1.x[ia]+=femData->getdispcomponent(index,ia);
+		  }
+	    }
+
+	element->Next();
+      }
+
+  
+  // Store circumferential direction in c1
+  // -------------------------------------
+
+  /*if (count==0)
+      {
+	fprintf(stderr,"\nc1= %6.3f %6.3f %6.3f  -",
+		c1.x[0],c1.x[1],c1.x[2]);
+	fprintf(stderr,"c0= %6.3f %6.3f %6.3f  =",
+		c0.x[0],c0.x[1],c0.x[2]);
+      }*/
+  c1.subtract(&c0);  
+  c1.normalize();   
+  /*if (count==0)
+      fprintf(stderr,"c1= %6.3f %6.3f %6.3f  \n",
+	      c1.x[0],c1.x[1],c1.x[2]);*/
+  
+  // Store initial radial direction in r1
+  // ------------------------------------
+  /*if (count==0)
+      {
+	fprintf(stderr,"r1= %6.3f %6.3f %6.3f  -",
+		r1.x[0],r1.x[1],r1.x[2]);
+	fprintf(stderr,"r0= %6.3f %6.3f %6.3f  =",
+		r0.x[0],r0.x[1],r0.x[2]);
+      }*/
+
+  r1.subtract(&r0);
+  r1.normalize();
+
+  /*if (count==0)
+      fprintf(stderr,"r1= %6.3f %6.3f %6.3f  \n",
+	      r1.x[0],r1.x[1],r1.x[2]);*/
+  
+  // Find component of r1 along c1 and subtract if from r1
+  // -----------------------------------------------------
+  float dotp=c1.dotwith(&r1);
+  r1.subtract(&c1,dotp);
+  r1.normalize();
+
+  /*if (count==0)
+      fprintf(stderr,"dot=%5.2f r1= %6.3f %6.3f %6.3f  \n",
+	      dotp,r1.x[0],r1.x[1],r1.x[2]);*/
+
+  // Find l1 as c1 * r1 
+  // ------------------
+  PX3Vector l1;
+  l1.copy(&r1);
+  l1.crosswithoverwrite(&c1);
+  l1.normalize();
+  
+
+  /*if (count==0)
+      {
+	fprintf(stderr,"\n Vectors\n----------\n");
+	fprintf(stderr,"r1= %6.3f %6.3f %6.3f  \n",
+		r1.x[0],r1.x[1],r1.x[2]);
+	fprintf(stderr,"c1= %6.3f %6.3f %6.3f  \n",
+		c1.x[0],c1.x[1],c1.x[2]);
+	fprintf(stderr,"l1= %6.3f %6.3f %6.3f  \n",
+		l1.x[0],l1.x[1],l1.x[2]);
+	count=1;
+      }*/
+
+  // Copy over the vectors
+  // ---------------------
+  nx1=r1.x[0]; ny1=r1.x[1]; nz1=r1.x[2];
+  nx2=c1.x[0]; ny2=c1.x[1]; nz2=c1.x[2];
+  nx3=l1.x[0]; ny3=l1.x[1]; nz3=l1.x[2];
+  
+}
+// -------------------------------------------------------------------------
+void PXAbaqusSolid::getElementCentroid(PXIntegerList* element,float&x,float&y,float& z)
+{
+  float cx[3];
+  for (int ia=0;ia<=2;ia++)
+      cx[ia]=0.0;
+
+  if (!hasnodes() || !haselements())
+      return;
+
+  element->Rewind();
+  for (int i=0;i<element->getnumnodes();i++)
+      {
+	int nd=element->getcurrent();
+	for (int ia=0;ia<=2;ia++)
+	    {
+	      cx[ia]+=nodes->getpoint(nd)->x[ia];
+	      if (hasfemdata())
+		  cx[ia]+=femData->getdispcomponent(nd,ia);
+	    }
+	element->Next();
+      }
+  
+  x=cx[0]/float(element->getnumnodes());
+  y=cx[1]/float(element->getnumnodes());
+  z=cx[2]/float(element->getnumnodes());
+
+}
+// ------------------------------------------------------------------------
+int PXAbaqusSolid::modifyStacksFromNodes()
+{
+  if (!hasnodes() || !haselements())
+      return 0;
+
+  for (int i=0;i<nodes->getnumnodes();i++)
+      {
+	int st=nodes->getindex(i,0);
+	int pt=nodes->getindex(i,1);
+	PXTriangulatedStackPoint* point=tstack[st]->getpoint(pt);
+	for (int ia=0;ia<=2;ia++)
+	    point->x[ia]=nodes->getpoint(i)->x[ia]+nodes->getdetails(i)->dx[ia];
+      }
+  return 1;
+}
+// ------------------------------------------------------------------------
+int PXAbaqusSolid::updateFromOutputStructures(int position)
+{
+  if (!hasfemdata() || !hasnodes())
+      return 0;
+
+  for (int i=0;i<nodes->getnumnodes();i++)
+      {
+	if (position==0)
+	    {
+	      for (int ia=0;ia<=2;ia++)
+		  nodes->getdetails(i)->dx[ia]=femData->getdispcomponent(i,ia);
+	    }
+	else
+	    {
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    nodes->getpoint(i)->x[ia]+=femData->getdispcomponent(i,ia);
+		    nodes->getdetails(i)->dx[ia]=0.0;
+		  }
+	    }
+
+	int st=nodes->getindex(i,0);
+	if (st==0 || st==100)
+	    {
+	      int pt=nodes->getindex(i,1);
+	      PXTriangulatedStackPoint* point=tstack[st>0]->getpoint(pt);
+	      if (i==0)
+		  fprintf(stderr,"Point 0 = (%6.3f %6.3f %6.3f) + (%5.3f %5.3f %5.3f) ---> ",
+			  point->x[0],
+			  point->x[1],
+			  point->x[2],
+			  femData->getdispcomponent(i,0),
+			  femData->getdispcomponent(i,1),
+			  femData->getdispcomponent(i,2));
+	      for (int ia=0;ia<=2;ia++)
+		  point->x[ia]=nodes->getpoint(i)->x[ia]+nodes->getdetails(i)->dx[ia];
+	      if (i==0)
+		  fprintf(stderr,"%6.3f %6.3f %6.3f\n",point->x[0],
+			  point->x[1],point->x[2]);
+
+	    }
+      }
+
+  for (int sur=0;sur<=1;sur++)
+      {
+	//fprintf(stderr,"Updating tstack[%d] zlevels\n",sur+1);
+	tstack[sur]->updateStackIndexZlevels();
+      }
+
+  return 1;
+}
+// ------------------------------------------------------------------------- 
+int PXAbaqusSolid::correctForIncormpressibility(PXAbaqusOutputData* baseData)
+{
+  if (!hasnodes() || !haselements() || !hasfemdata())
+      return 0;
+  if (elements->getnumnodes()!=baseData->getnumelements())
+      return 0;
+
+  fprintf(stderr,"+.+.+.+. Correcting for Volume by shifting down z-coordinate\n");
+  int numslices=nodes->getnumnodes()/(numpointscontour*numlayers);
+  int elpointslayer=(numslices-1)*numpointscontour;
+
+  // Store current positions in details 
+  for (int nd=0;nd<nodes->getnumnodes();nd++)
+      for(int ia=0;ia<=2;ia++)
+	  nodes->getdetails(nd)->dx[ia]=nodes->getpoint(nd)->x[ia];
+    
+  float maxvolf=-1000.0,minvolf=1000.0;
+
+  for (int slice=0;slice<numslices-1;slice++)
+      {
+	float oldvol=0.0,newvol=0.0;
+	
+	for (int lb=0;lb<numlayers-1;lb++)
+	    for (int pt=0;pt<numpointscontour;pt++)
+		{
+		  int el=(lb-1)*elpointslayer+(slice-1)*numpointscontour+pt;
+		  oldvol+=baseData->getvolume(el);
+		  newvol+=femData->getvolume(el);
+		}
+	
+	float volf=oldvol/newvol-1.0;
+	maxvolf=Fmax(volf,maxvolf);
+	minvolf=Fmin(volf,minvolf);
+	fprintf(stderr,"Slice: %2d oldvol=%10.2f newvol=%10.2f volf=%6.4f\n",slice,oldvol,newvol,volf);
+	
+	// Adjust Nodes
+	for (int la=0;la<numlayers;la++)
+	    for (int pt=0;pt<numpointscontour;pt++)
+		{
+		  int nd=la*(numslices*numpointscontour)+(slice+1)*numpointscontour+pt;
+		  int nd0=la*(numslices*numpointscontour)+(slice)*numpointscontour+pt;
+		  
+		  for (int ia=0;ia<=2;ia++)
+		      {
+			float x=(nodes->getpoint(nd)->x[ia]-nodes->getpoint(nd0)->x[ia]);
+			nodes->getpoint(nd)->x[ia]+=volf*x;
+			for (int slplus=slice+2;slplus<numslices;slplus++)
+			    {
+			      int nd1=la*(numslices*numpointscontour)+(slplus)*numpointscontour+pt;
+			      nodes->getpoint(nd1)->x[ia]+=volf*x;
+			    }
+		      }
+
+		  int st=nodes->getindex(nd,0);
+		  if (st==0 || st==100)
+		      {
+			int pt=nodes->getindex(nd,1);
+			PXTriangulatedStackPoint* point=tstack[st>0]->getpoint(pt);
+			for (int ia=0;ia<=2;ia++)
+			    point->x[ia]=nodes->getpoint(nd)->x[ia];
+		      }
+		}
+      }
+  
+  {
+    for (int nd=0;nd<nodes->getnumnodes();nd++)
+	{
+	  float x[3];
+	  for(int ia=0;ia<=2;ia++)
+	      {
+		x[ia]=nodes->getpoint(nd)->x[ia]-nodes->getdetails(nd)->dx[ia];
+		x[ia]+=femData->getdispcomponent(nd,ia);
+		nodes->getdetails(nd)->dx[ia]=0.0;
+	      }
+	  femData->setNodeInfo(nd,x[0],x[1],x[2]);
+	}
+  }
+
+  fprintf(stderr,"\n Maximum Ratios min=%f max=%f\n",minvolf,maxvolf);
+  return 1;
+}
+// ------------------------------------------------------------------------- 
+
+int PXAbaqusSolid::updateCurvaturesFromStacks()
+{
+  if (!hasnodes() || !haselements() || !hasfemdata())
+      return 0;
+
+  for (int i=0;i<nodes->getnumnodes();i++)
+      {
+	for (int ia=0;ia<=2;ia++)
+	    nodes->getdetails(i)->dx[ia]=femData->getdispcomponent(i,ia);
+
+	int st=nodes->getindex(i,0);
+	if (st>=0)
+	    {
+	      int pt=nodes->getindex(i,1);
+	      PXTriangulatedStackPoint* point=tstack[st]->getpoint(pt);
+	      for (int ia=0;ia<=1;ia++)
+		  nodes->getpoint(i)->k[ia]=point->k[ia];
+	    }
+      }
+  return 1;
+}
+// ------------------------------------------------------------------------- 
+void PXAbaqusSolid::rotateFibreAngle(float& nx1,float& ny1,float& nz1,
+						float& nx2,float& ny2,float& nz2,
+						float nx3,float ny3,float nz3,
+						float angle)
+{
+  /* 
+     Assume Circumferential nx1,ny1,nz1
+            Longitudinal    nx2,ny2,nz2
+            Radial          nx3,ny3,nz3
+     
+	    Rotate about radial axis using Formulation in Graig Introduction to Robotics p.52
+	    */
+  
+  // convert to radians
+  angle=M_PI*angle/180.0;
+  float kx=nx3,ky=ny3,kz=nz3;
+  float ct=cos(angle),st=sin(angle),vt=1-cos(angle);
+
+  float R[3][3];
+  R[0][0]=kx*kx*vt+ct;          R[0][1]=kx*ky*vt-kz*st;    R[0][2]=kx*kz*vt+ky*st;
+  R[1][0]=kx*ky*vt+kz*st;       R[1][1]=ky*ky*vt+ct;       R[1][2]=ky*kz*vt-kx*st;
+  R[2][0]=kx*kz*vt-ky*st;       R[2][1]=ky*kz*vt+kx*st;    R[2][2]=kz*kz*vt+ct;
+
+  float tx1=nx1,tx2=nx2;
+  float ty1=ny1,ty2=ny2;
+  float tz1=nz1,tz2=nz2;
+
+  nx1=R[0][0]*tx1+R[0][1]*ty1+R[0][2]*tz1;
+  ny1=R[1][0]*tx1+R[1][1]*ty1+R[1][2]*tz1;
+  nz1=R[2][0]*tx1+R[2][1]*ty1+R[2][2]*tz1;
+
+  nx2=R[0][0]*tx2+R[0][1]*ty2+R[0][2]*tz2;
+  ny2=R[1][0]*tx2+R[1][1]*ty2+R[1][2]*tz2;
+  nz2=R[2][0]*tx2+R[2][1]*ty2+R[2][2]*tz2;
+
+}
+// -------------------------------------------------------------------------   
+//  This is the key routine for specifying fibre orientation 
+// -------------------------------------------------------------------------
+float PXAbaqusSolid::getFibreAngle(float z,int layer,float bottomz,float topz)
+
+{
+  // Define Base z=bottomz
+  // Define Top  z=topz
+  
+  /*
+     Fibre Angle Distribution from Guccione and McCulloch 
+     in Finite Element Modelling of Ventricular Mechanics Chapter  of Theory of Heart
+     page 136 Figure 6.7 */
+
+  if (!haselements() || !hasnodes())
+      return 0.0;
+  
+  float zperc=(z-bottomz)/(topz-bottomz);
+  zperc=Frange(zperc,0.0,1.0);
+  float lperc=float(layer)/float(100.0);
+
+  float aendo=-zperc*15.0+97.0;
+  float aepi = zperc*10.0-53.0;
+
+  return lperc*(aepi-aendo)+aendo;
+
+}
+// ------------------------------------------------------------------------- 
+float PXAbaqusSolid::temperatureForVolChange(float vol1,float vol2,
+							int nlgeom)
+{
+  float strainratio=pow(vol2/vol1,float(1.0/3.0));
+  if (nlgeom)
+      return log(strainratio);
+  else
+      return strainratio;
+}
+// -------------------------------------------------------------------------   
+int  PXAbaqusSolid::generateVolumes(const char* fnameendo,const char* fnameepi,
+				    int end,int begin)
+{
+  if (hasvolumes())
+      {
+	delete [] volume;
+      }
+  hasVolumes=1;
+  volume=PXTriangulatedStack::generateVolumes(fnameendo,fnameepi,end,begin);
+  return 1;
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::saveInventor(const char* fname,int mode,int cmode,float* params)
+{
+  if (!haselements() || !hasnodes())
+      return 0;
+
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+      return 0;
+  int st=saveInventor(fout,mode,cmode,params);
+  fclose(fout);
+  return st;
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::saveInventor(FILE* fout,int mode,int cmode,float* params)
+{
+  if (hasfemdata())
+      cmode=Irange(cmode,0,11);
+  else 
+      cmode=-1;
+  if (!haselements() || !hasnodes())
+      return 0;
+
+  fprintf(fout, "#Inventor V2.0 ascii\n\n");
+  fprintf(fout, "Separator {\n");		    
+  fprintf(fout, "ShapeHints { \n");	
+  fprintf(fout, "  vertexOrdering  COUNTERCLOCKWISE \n");	
+  fprintf(fout, "  faceType CONVEX \n");	
+  fprintf(fout, " }\n");	
+
+  int index[8],i=0,j=0;
+  PXTriangle triangle[12];
+  int numt=12;
+
+  int nel=elements->getnumnodes();
+
+  if (hasFemData)
+      {
+	for(i=0; i<nodes->getnumnodes(); i++)
+	    {
+	      nodes->getpoint(i)->x[0]+=(femData->getdisplacement(i))->x[0]; 
+	      nodes->getpoint(i)->x[1]+=(femData->getdisplacement(i))->x[1];
+	      nodes->getpoint(i)->x[2]+=(femData->getdisplacement(i))->x[2];
+	    }
+      }
+
+
+  fprintf(fout, "\tCoordinate3 { point [ ");
+  for(i=0; i<nodes->getnumnodes()-1; i++)
+      fprintf(fout, "\n\t\t %4.2f %4.2f %4.2f,", 
+	      nodes->getpoint(i)->x[0], nodes->getpoint(i)->x[1], nodes->getpoint(i)->x[2]);		
+  i = nodes->getnumnodes()-1;
+  fprintf(fout, "\n\t\t %4.2f %4.2f %4.2f]\n\t}\n", 
+	  nodes->getpoint(i)->x[0], nodes->getpoint(i)->x[1], nodes->getpoint(i)->x[2]);		  
+  if (mode>=0 && cmode>=0)
+      {
+	/* write out the material (color) of each triangular facet */
+	
+	fprintf(fout, "\tMaterial { diffuseColor [ ");		
+	elements->Rewind();
+	for(i=0; i<nel; i++)
+	    {
+	      PX3Vector color;
+	      if (mode>0)
+		  color_lookup(color,femData->getstraincomponent(i,cmode),params,mode);
+	      else
+		  {
+		    int pi=Icyclic(femData->getpieindex(i),3);
+		    switch(pi)
+			{
+			case 0:
+			  color.x[0]=1.0; color.x[1]=0.0; color.x[2]=0.0; break;
+			case 1:
+			  color.x[0]=0.0; color.x[1]=1.0; color.x[2]=0.0; break;
+			case 2:
+			  color.x[0]=0.8; color.x[1]=0.8; color.x[2]=0.0; break;
+			}
+		  }
+	      PXIntegerList* intList=((elements->getcurrentnode())->points);
+	      intList->Rewind();
+	      if (intList->getnumnodes()==8)
+		  numt=12;
+	      else
+		  numt=4;
+	      elements->Next();
+	      
+	      for(j=0; j<numt; j++)
+		  {
+		    if (j<(numt-1) || i<nel-1)
+			fprintf(fout, "\n\t\t %4.2f %4.2f %4.2f,", 
+				color.x[0], color.x[1], color.x[2]);
+		    else
+			fprintf(fout, "\n\t\t %4.2f %4.2f %4.2f]\n\t}\n",
+				color.x[0], color.x[1], color.x[2]);
+		  }
+	    }
+	fprintf(fout, "MaterialBinding {\n\tvalue PER_FACE\n}\n");
+      }
+
+  /* write out the facet index */ 
+  fprintf(fout, "\tIndexedFaceSet {\n\t coordIndex  [ \n");
+  elements->Rewind();
+  for(i=0; i<nel; i++)
+      {
+	PXIntegerList* intList=((elements->getcurrentnode())->points);
+	intList->Rewind();
+	if (intList->getnumnodes()==8)
+	    {
+	      numt=12;
+	      index[0] = intList->getcurrent();  intList->Next(); 
+	      index[1] = intList->getcurrent();  intList->Next(); 
+	      index[2] = intList->getcurrent();  intList->Next(); 
+	      index[3] = intList->getcurrent();  intList->Next(); 
+	      index[4] = intList->getcurrent();  intList->Next(); 
+	      index[5] = intList->getcurrent();  intList->Next(); 
+	      index[6] = intList->getcurrent();  intList->Next(); 
+	      index[7] = intList->getcurrent(); 
+	      
+	      triangle[0].p[0]  = index[0]; triangle[0].p[1]  = index[1]; triangle[0].p[2]  = index[2];  
+	      triangle[1].p[0]  = index[3]; triangle[1].p[1]  = index[3]; triangle[1].p[2]  = index[0];  
+	      triangle[2].p[0]  = index[1]; triangle[2].p[1]  = index[5]; triangle[2].p[2]  = index[6];  
+	      triangle[3].p[0]  = index[2]; triangle[3].p[1]  = index[6]; triangle[3].p[2]  = index[2];  
+	      triangle[4].p[0]  = index[4]; triangle[4].p[1]  = index[7]; triangle[4].p[2]  = index[6];  
+	      triangle[5].p[0]  = index[5]; triangle[5].p[1]  = index[4]; triangle[5].p[2]  = index[6];  
+	      triangle[6].p[0]  = index[0]; triangle[6].p[1]  = index[4]; triangle[6].p[2]  = index[7];  
+	      triangle[7].p[0]  = index[3]; triangle[7].p[1]  = index[3]; triangle[7].p[2]  = index[7];  
+	      triangle[8].p[0]  = index[3]; triangle[8].p[1]  = index[2]; triangle[8].p[2]  = index[6];  
+	      triangle[9].p[0]  = index[7]; triangle[9].p[1]  = index[7]; triangle[9].p[2]  = index[3];  
+	      triangle[10].p[0] = index[4]; triangle[10].p[1] = index[5]; triangle[10].p[2] = index[1];  
+	      triangle[11].p[0] = index[0]; triangle[11].p[1] = index[0]; triangle[11].p[2] = index[4];
+	    }
+	else
+	    {
+	      numt=4;
+	      index[0] = intList->getcurrent();  intList->Next(); 
+	      index[1] = intList->getcurrent();  intList->Next(); 
+	      index[2] = intList->getcurrent();  intList->Next(); 
+	      index[3] = intList->getcurrent(); 
+	      
+	      /* the twelve triangles */
+	      triangle[0].p[0]  = index[0]; triangle[0].p[1]  = index[1]; triangle[0].p[2]  = index[2];  
+	      triangle[1].p[0]  = index[0]; triangle[1].p[1]  = index[1]; triangle[1].p[2]  = index[3];  
+	      triangle[2].p[0]  = index[0]; triangle[2].p[1]  = index[2]; triangle[2].p[2]  = index[3];  
+	      triangle[3].p[0]  = index[1]; triangle[3].p[1]  = index[2]; triangle[3].p[2]  = index[3];  
+	    }
+	
+	for(j=0; j<numt; j++)
+	    {
+	      if (numt==4)
+		  {
+		    if (j<(numt-1) || i<nel-1)
+			fprintf(fout, "\t\t%d,%d,%d,%d, \n", 
+				triangle[j].p[0], triangle[j].p[1], triangle[j].p[2],-1);
+		    else
+			fprintf(fout,"\t\t%d,%d,%d,%d] \n", 
+				triangle[j].p[0], triangle[j].p[1], triangle[j].p[2],-1);
+		  }
+	      else
+		  {
+		    if (j<(numt-2) || i<nel-1)
+			fprintf(fout, "\t\t%d,%d,%d,%d,%d, \n", 
+				triangle[j].p[0], triangle[j].p[1], triangle[j].p[2],
+				triangle[j+1].p[0],-1);
+		    else
+			fprintf(fout,"\t\t%d,%d,%d,%d,%d] \n", 
+				triangle[j].p[0], triangle[j].p[1], triangle[j].p[2],
+				triangle[j+1].p[0],-1);
+		    j++;
+		  } 
+	    }
+	elements->Next();
+      }
+  
+  /* the last line */
+  fprintf(fout, "}\n}\n# End of file.\n");
+  if (hasFemData)
+      {
+	for(i=0; i<nodes->getnumnodes(); i++)
+	    {
+	      nodes->getpoint(i)->x[0]-=(femData->getdisplacement(i))->x[0]; 
+	      nodes->getpoint(i)->x[1]-=(femData->getdisplacement(i))->x[1];
+	      nodes->getpoint(i)->x[2]-=(femData->getdisplacement(i))->x[2];
+	    }
+      }
+  return 1;
+}
+// -------------------------------------------------------------------------
+void PXAbaqusSolid::color_lookup(PX3Vector& output,float val,float* params,int mode)
+{
+  if (mode==1)
+      {
+	// Standard Peng-Cheng Color Scheme
+	if(val > 0.325)       output.x[0]=(0.75);
+	else if(val > 0.275)  output.x[0]=(1.00);	
+	else if(val > 0.225)  output.x[0]=(1.00);
+	else if(val > 0.175)  output.x[0]=(1.00);	
+	else if(val > 0.125)  output.x[0]=(1.00);	
+	else if(val > 0.075)  output.x[0]=(1.00);	
+	else if(val > 0.025)  output.x[0]=(1.00);	
+	else if(val > -0.025) output.x[0]=(1.00);	
+	else if(val > -0.075) output.x[0]=(0.80);	
+	else if(val > -0.125) output.x[0]=(0.40);	
+	else if(val > -0.175) output.x[0]=(0.0);	
+	else if(val > -0.225) output.x[0]=(0.60);	
+	else if(val > -0.275) output.x[0]=(0.20);	
+	else if(val > -0.325) output.x[0]=(0.0);	
+	else                  output.x[0]=(0.0);	
+
+	if(val > 0.325)       output.x[1]=(0.0);
+	else if(val > 0.275)  output.x[1]=(0.2);	
+	else if(val > 0.225)  output.x[1]=(0.5);
+	else if(val > 0.175)  output.x[1]=(0.8);	
+	else if(val > 0.125)  output.x[1]=(0.8);	
+	else if(val > 0.075)  output.x[1]=(1.00);	
+	else if(val > 0.025)  output.x[1]=(1.00);	
+	else if(val > -0.025) output.x[1]=(1.00);	
+	else if(val > -0.075) output.x[1]=(1.00);	
+	else if(val > -0.125) output.x[1]=(1.00);	
+	else if(val > -0.175) output.x[1]=(0.5);	
+	else if(val > -0.225) output.x[1]=(1.00);	
+	else if(val > -0.275) output.x[1]=(0.50);	
+	else if(val > -0.325) output.x[1]=(0.0);	
+	else                  output.x[1]=(0.0);	
+
+	if(val > 0.325)       output.x[2]=(0.15);
+	else if(val > 0.275)  output.x[2]=(0.3);	
+	else if(val > 0.225)  output.x[2]=(0.55);
+	else if(val > 0.175)  output.x[2]=(0.8);	
+	else if(val > 0.125)  output.x[2]=(0.0);	
+	else if(val > 0.075)  output.x[2]=(0.00);	
+	else if(val > 0.025)  output.x[2]=(0.75);	
+	else if(val > -0.025) output.x[2]=(1.00);	
+	else if(val > -0.075) output.x[2]=(0.6);	
+	else if(val > -0.125) output.x[2]=(0.2);	
+	else if(val > -0.175) output.x[2]=(0.0);	
+	else if(val > -0.225) output.x[2]=(1.00);	
+	else if(val > -0.275) output.x[2]=(1.0);	
+	else if(val > -0.325) output.x[2]=(1.0);	
+	else                  output.x[2]=(0.5);	
+
+	return;
+      }
+  else if (mode==2)
+      {
+	if (params!=NULL)
+	    {
+	      if(val > params[1])      
+		  {
+		    output.x[0]=0.7;
+		    output.x[1]=0.0;
+		    output.x[2]=0.0;
+		  }
+	      else if (val>params[0])
+		  {
+		    output.x[0]=1.0;
+		    output.x[1]=1.0;
+		    output.x[2]=1.0;
+		  }
+	      else
+		  {
+		    output.x[0]=0.0;
+		    output.x[1]=0.0;
+		    output.x[2]=0.7;
+		  }
+	    }
+	return;
+      }
+  else if (mode==3)
+      {
+	float v=0.0;
+	if (val>0.3)
+	    v=1.0;
+	else if (val<=0.3 && val>=-0.3)
+	    v=(val+0.3)*(1.666667);
+	else
+	    v=-1.0;
+
+	for (int ia=0;ia<=2;ia++)
+	    output.x[ia]=v;
+      }
+  else if (mode==4 || mode==5)
+      {
+	
+	float h=0.60,s=0.0;
+	
+	if (mode==5)
+	    {
+	      // Spect Data
+	      h=0.58;
+	      s=Frange(val/100.0,0.0,1.0);
+	    }
+	else
+	    {
+	      h=0.60;
+	      if (val>0.0)
+		  h=0.00;
+	      s=3.0*Frange(fabs(val),0.0,0.33);
+	    }
+	    
+	float v=0.8;
+
+	h*=6.0;
+	int i=int(h);
+	float aa,bb,cc,f,r=0,g=0,b=0;
+	
+	f=h-float(i);
+	
+	aa= v*(1.0-s);
+	bb= v*(1.0- (s*f));
+	cc= v*(1.0- (s* (1.0-f)));
+	switch (i)
+	    {
+	    case 0: 
+	      r=v; g=cc; b=aa; 
+	      break;
+	    case 1: 
+	      r=bb; g=v; b=aa;
+	      break;
+	    case 2:
+	      r=aa; g=v; b=cc;
+	      break;
+	    case 3:
+	      r=aa; g=bb; b=v;
+	      break;
+	    case 4:
+	      r=cc; g=aa; b=v;
+	      break;
+	    case 5:
+	      r=v;  g=aa; b=bb;
+	      break;
+	    }
+	output.x[0]=r;
+	output.x[1]=g;
+	output.x[2]=b;
+      }
+  else
+      {
+	output.x[0]=0.1;
+	output.x[1]=0.1;
+	output.x[2]=0.1;
+      }
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::loadJobIntoSolidArray(const char* fname,PXAbaqusSolid** solids,
+					 int maxsolids,int numslices,int numsectors,int rotate)
+{
+  gzFile fin=gzsuffixopen(fname,"r");
+  if (fin==NULL)
+      return 0;
+  
+  char line[400];
+  gzgets(fin,line,200);
+  int mode=0;
+  
+  if (gzfindstringinstring(line, "#XPResults File Set"))
+      mode=1;
+  else
+      {
+	if (gzfindstringinstring(line, "#AbaqusResults File Set"))
+	    mode=2;
+      }
+
+  if (mode==0)
+      {
+	gzclose(fin);
+	fprintf(stderr,"Not a .stat file\n");
+	return 0;
+      }
+  
+  int numframes,numel,numnodes;
+  gzgets(fin,line,200); sscanf(line,"%d",&numframes);
+  gzgets(fin,line,200); sscanf(line,"%d",&numnodes);
+  gzgets(fin,line,200); sscanf(line,"%d",&numel);
+  
+  char solidname[100];  
+  gzgets(fin,line,200);     gzgets(fin,line,200);  
+  sscanf(line,"%s\n",&solidname[0]);
+  char jobname[100]; 
+  gzgets(fin,line,200);     gzgets(fin,line,200);  
+  sscanf(line,"%s\n",&jobname[0]);
+
+  fprintf(stderr,"Reading set file %s \n",fname);
+  fprintf(stderr,"Job stem =`%s' solid name=`%s' frames=%d nodes=%d elements=%d\n",
+	  jobname,solidname,numframes,numnodes,numel);
+
+  gzclose(fin);
+
+  char* path=anaextractpath(fname);
+
+
+  sprintf(line,"%s%s",path,solidname);
+  int ok=solids[0]->Load(line);
+
+  if (ok==0)
+      {
+	fprintf(stderr,"Failed to Load solid from %s \n",line);
+	return 0;
+      }
+
+  if (numel!=(solids[0]->getelements())->getnumnodes() || numnodes!=(solids[0]->getnodes()->getnumnodes()))
+      {
+	fprintf(stderr,"Not correct numnodes or numelements\n");
+	return 0;
+      }
+
+  if (numframes>maxsolids)
+      {
+	fprintf(stderr,"Real num frames=%d, using only %d\n",numframes,maxsolids);
+	numframes=maxsolids;
+      }
+
+  for (int ii=1;ii<numframes;ii++)
+      solids[ii]->Copy(solids[0]);
+
+  fprintf(stderr,".. Strain data from %s%s : (or=%d,rot=%d) mode=%d,",path,jobname,
+	  solids[0]->getorientationmode(),rotate,mode);
+  
+  for (int i=0;i<numframes;i++)
+      {
+	solids[i]->allocateFemData();
+	if (mode==1)
+	    {
+	      sprintf(line,"%s%s_%02d",path,jobname,i+1);
+	      if (debugmode)
+		  fprintf(stderr,"Reading old %s\n",line);
+	      else
+		  fprintf(stderr,"(%d) ",i+1);
+	      (solids[i]->getfemdata())->LoadOld(line,1);
+	    }
+	else if (mode>1)
+	    {
+	      sprintf(line,"%s%s.%02d.dat",path,jobname,i+1);
+	      if (debugmode)
+		  fprintf(stderr,"Reading new data: %s\n",line);
+	      else
+		  fprintf(stderr,"%d ",i+1);
+	      (solids[i]->getfemdata())->Load(line,0,1);
+	    } 
+      }
+  
+  if (debugmode)
+      fprintf(stderr,"Done Reading\n");
+
+  float rx=0.0,ry=0.0,rz=0.0;
+  if (solids[0]->getnodes()->getnumnodes()>100)
+      {
+	sprintf(line,"%s%s.ref",path,jobname);
+	if (debugmode)
+	    fprintf(stderr,"Opening %s ... ",line);
+	else
+	    fprintf(stderr,"\n");
+	
+	fin=gzsuffixopen(line,"r");
+	if (fin)
+	    {
+	      gzgets(fin,line,100);
+	      sscanf(line,"%f %f %f",&rx,&ry,&rz);
+	      gzclose(fin);
+	    }
+	else
+	    fprintf(stderr,"Failed to load junction point from %s: using ",line);
+	fprintf(stderr,"Junction Point (%5.2f %5.2f %5.2f)\n",rx,ry,rz);
+	averageStrainsInSolidArray(solids,numframes,rx,ry,rz,numslices,numsectors);
+      }
+  else
+      {
+	sprintf(line,"%s%s.pieindex",path,jobname);
+	if (debugmode)
+	    fprintf(stderr,"Opening pineindex file %s ... ",line);
+	else
+	    fprintf(stderr,"\n");
+	
+	if (solids[0]->getfemdata()->loadPieDivision(line))
+	    {
+	      fprintf(stderr,"Loaded pies ok\n");
+	      averageStrainsInSolidArray(solids,numframes);
+	    }
+	else
+	    {
+	      fprintf(stderr,"Failed...Using Junction Point (%5.2f %5.2f %5.2f)\n",rx,ry,rz);
+	      averageStrainsInSolidArray(solids,numframes,rx,ry,rz,numslices,numsectors);
+	    }
+      }
+  
+  delete [] path;
+  return numframes;
+}
+// --------------------------------------------------------------------------
+int  PXAbaqusSolid::averageStrainsInSolidArray(PXAbaqusSolid** solids,int numframes)
+{
+  fprintf(stderr,"In the non-bothersome averaging\n");
+  for (int i=0;i<numframes;i++)
+    {
+      if (i==0)
+	{
+	  (solids[0]->getfemdata())->averagestrains(solids[0]->getfemdata());
+	}
+      else
+	{
+	  (solids[i]->getfemdata())->copypieindex(solids[0]->getfemdata());
+	  (solids[i]->getfemdata())->averagestrains(solids[0]->getfemdata());
+	}
+    }
+  return 1;
+}
+// --------------------------------------------------------------------------
+int  PXAbaqusSolid::averageStrainsInSolidArray(PXAbaqusSolid** solids,int numframes,
+					       float rx,float ry,float rz,
+					       int numslices,int numsectors,int anticlockwise)
+{
+  int oldnum=numslices;
+  numslices=Irange(numslices,1,(solids[0]->getstack(0))->getstackindex().numcontours-1);
+  anticlockwise=anticlockwise>0;
+  if (numslices!=oldnum)
+      fprintf(stderr,"Reduced numslices to %d (from %d) to avoid empty slices\n",numslices,oldnum);
+
+  fprintf(stderr,"In the bothersome averaging\n");
+
+  for (int i=0;i<numframes;i++)
+      {
+	if (i==0)
+	    {
+	      (solids[0]->getfemdata())->subdivideinpies(rx,ry,rz,numslices,numsectors,anticlockwise);
+	      (solids[0]->getfemdata())->averagestrains(solids[0]->getfemdata());
+	    }
+	else
+	    {
+	      (solids[i]->getfemdata())->copypieindex(solids[0]->getfemdata());
+	      (solids[i]->getfemdata())->averagestrains(solids[0]->getfemdata());
+	    }
+	//sprintf(line,"/tmp/ave.%02d.data",i+1);
+	//solids[i]->getfemdata()->Save(line);
+      }
+  fprintf(stderr,"Done with averageStrainsIn\n");
+  return 1;
+}
+// --------------------------------------------------------------------------
+int  PXAbaqusSolid::savePies(const char* fname,PXAbaqusSolid** solids,int numframes,int mode,int skipframes)
+{
+  if (!solids[0]->hasfemdata())
+      return 0;
+
+  int numpies=solids[0]->getfemdata()->getnumpies();
+  FILE* fout=fopen(fname,"w");
+  if (fout==NULL)
+    return 0;
+  
+  fprintf(fout,"# Pie data \n");
+  int orient=solids[0]->getorientationmode();
+  {
+    if (orient==1 || orient==3 )
+      fprintf(fout,"# Strains defined in Cardiac Coordinate Space\n");
+    else if (orient==5)
+      fprintf(fout,"# Principal Strains\n");
+    else
+      fprintf(fout,"# Strains defined in Fibre-Specific Coordinate Space\n");
+  }
+  
+  fprintf(fout,"# LV-RV Junction Defined as (%6.2f,%6.2f,%6.2f)\n#\n",
+	  solids[0]->getfemdata()->getjunctionpoint()->x[0],
+	  solids[0]->getfemdata()->getjunctionpoint()->x[1],
+	  solids[0]->getfemdata()->getjunctionpoint()->x[2]);
+  
+  float** piesmat=matrix(0,numpies-1,0,numframes-1);
+  float *ave=new float[numpies];
+  float *vol=new float[numpies];
+  float *vol0=new float[numpies];
+  int numel=solids[0]->getelements()->getnumnodes();
+  
+  int start=-1;
+  if (mode>0)
+      start=0;
+
+  int maxstrain=5;
+  if (orient==5)
+    maxstrain=2;
+  
+  for (int strain=start;strain<=maxstrain;strain++)
+    {
+      for (int f=0;f<numframes;f++)
+	{
+	  for (int j=0;j<numpies;j++)
+	    {
+	      ave[j]=0.0;
+	      vol[j]=0.0;
+	      vol0[j]=0.0;
+	    }
+	  
+	  for (int i=0;i<numel;i++)
+	    {
+	      int p=Irange((solids[f]->getfemdata())->getpieindex(i),0,numpies-1);
+	      float v=(solids[f]->getfemdata())->getvolume(i);
+	      vol[p]+=v;
+	      vol0[p]+=(solids[0]->getfemdata())->getvolume(i);
+	      if (strain>=0)
+		{
+		  v=(solids[0]->getfemdata())->getvolume(i);
+		  ave[p]+=(solids[f]->getfemdata())->getstraincomponent(i,strain)*v;
+		}
+	    }
+	  
+	  if (strain>=0)
+	    {
+	      for (int i=0;i<numpies;i++)
+		{
+		  if (vol0[i]<0.001)
+		    ave[i]=0.0;
+		  else
+		    ave[i]/=vol0[i];
+		}
+	      
+	      for (int j=0;j<numpies;j++)
+		piesmat[j][f]=ave[j];
+	    }
+	  else
+	    {
+	      for (int j=0;j<numpies;j++)
+		piesmat[j][f]=vol[j];
+	    } 
+	}
+      fprintf(fout,"\n");
+      
+      if (orient<2 || orient==3 || strain<0)
+	{
+	  switch(strain)
+	    {
+	    case -1:
+	      fprintf(fout,"#\n\t\t Volume \n"); break;
+	    case 0:
+	      fprintf(fout,"#\n\t\t Radial Strain RR\n"); break;
+	    case 1:
+	      fprintf(fout,"#\n\t\t Circumferential Strain CC\n"); break;
+	    case 2:
+	      fprintf(fout,"#\n\t\t Longitudinal Strain LL\n"); break;
+	    case 3:
+	      fprintf(fout,"#\n\t\t Radial-Circumferential Shear Strain RC\n"); break;
+	    case 4:
+	      fprintf(fout,"#\n\t\t Radial-Longitudinal Strain RL\n"); break;
+	    case 5:
+	      fprintf(fout,"#\n\t\t Circumferential-Longitudinal Strain CL\n"); break;
+	    }
+	}
+      else if (orient==5)
+	{
+	  fprintf(fout,"#\n\t\t Principal Strain %d\n",strain+1);
+	}
+      else
+	{
+	  switch(strain)
+	    {
+	    case 0:
+	      fprintf(fout,"#\n\t\t Circumferential Cross-Fibre Strain XX\n"); break;
+	    case 1:
+	      fprintf(fout,"#\n\t\t Radial Strain RR\n"); break;
+	    case 2:
+	      fprintf(fout,"#\n\t\t Fibre Strain FF\n"); break;
+	    case 3:
+	      fprintf(fout,"#\n\t\t Circumferential-Radial Shear Strain XR\n"); break;
+	    case 4:
+	      fprintf(fout,"#\n\t\t Circumferential-Fibre Strain XF\n"); break;
+	    case 5:
+	      fprintf(fout,"#\n\t\t Radial-Fibre Strain RF\n"); break;
+	      
+	    }
+	}
+      
+      fprintf(fout,"Pie/Frame ");
+      {
+	for (int f=0;f<numframes;f+=skipframes)
+	  fprintf(fout," %7d",f+1);
+      }
+      fprintf(fout,"\n");
+      int minj=0;
+      if (solids[0]->getnodes()->getnumnodes()<100)
+	minj=2;
+      for (int j=minj;j<numpies;j++)
+	{
+	  fprintf(fout,"  %7d   ",j+1);
+	  for (int f=0;f<numframes;f+=skipframes)
+	    if (strain==-1)
+	      fprintf(fout," %6.1f ",piesmat[j][f]);
+	    else
+	      fprintf(fout," %6.3f ",piesmat[j][f]);
+	  
+	  fprintf(fout,"\n");
+	}
+    }
+  
+  if (solids[0]->getnodes()->getnumnodes()<100)
+    {
+      fprintf(fout, "\n\nPie division for each elements\nElement\tPie\n");
+      for (int i=0;i<numel;i++)
+	{
+	  int p=solids[0]->getfemdata()->getpieindex(i);
+	  fprintf(fout,"%d \t%d\n!",i+1,p);
+	}
+    }
+  
+  fclose(fout);
+  free_matrix(piesmat,0,numpies-1,0,numframes-1);
+  delete [] ave;
+  delete [] vol;
+  delete [] vol0;
+  return 1;
+}
+// --------------------------------------------------------------------------
+void  PXAbaqusSolid::getElementRange(PXIntegerList* element,PXSolidNodes* nodes,
+				     float cx,float cy,float phase_ref,
+				     float& minz,float& maxz,
+				     float& minangle,float& maxangle,
+				     float& mintrans,float& maxtrans)
+{
+  static int test=0;
+  test++;
+  minangle=0.0,maxangle=0.0;
+  minz=100000.0,maxz=-100000.0;
+  mintrans=200.0; maxtrans=-1.0;
+
+  float oldmin=0.0,oldmax=0.0;
+  element->Rewind();
+  for (int i=0;i<element->getnumnodes();i++)
+    {
+      int index=element->getcurrent();       element->Next();
+      float x=nodes->getpoint(index)->x[0]-cx;
+      float y=nodes->getpoint(index)->x[1]-cy;
+      float z=nodes->getpoint(index)->x[2];
+      float t=float(nodes->getindex(index,0));
+      minz=Fmin(minz,z);
+      maxz=Fmax(maxz,z);
+      mintrans=Fmin(mintrans,t);
+      maxtrans=Fmax(maxtrans,t);
+      
+      float phase=Fcyclic(atan2(y,x)*180/M_PI-phase_ref,360.0);
+      
+      if (i==0 || i==1 || i==4 || i==5)
+	{
+	  if (fabs(phase-oldmin)>180.0 && i!=0)
+	    {
+	      if (phase>oldmin)
+		phase-=360.0;
+	      else
+		phase+=360.0;
+	    }
+	  minangle+=0.25*phase;
+	  oldmin=phase;
+	}
+      else
+	{
+	  if (fabs(phase-oldmax)>180.0 && i!=2)
+	    {
+	      if (phase>oldmax)
+		phase-=360.0;
+	      else
+		phase+=360.0;
+	    }
+	  maxangle+=0.25*phase;
+	  oldmax=phase;
+	}
+    }
+  
+  minangle=Fcyclic(minangle,360.0);
+  maxangle=Fcyclic(maxangle,360.0);
+
+  if (maxangle-minangle>180.0)
+    {
+      float temp=maxangle;
+      maxangle=minangle;
+      minangle=temp;
+    }
+}
+// --------------------------------------------------------------------------
+float PXAbaqusSolid::returnElementFraction(float elementminz,float elementmaxz,float globalminz,
+					   float globalmaxz,int slice,int numslices,int debug)
+{
+  float dz=(globalmaxz-globalminz)/float(numslices);
+
+  // Pie has z_extent z0--z1
+  float z1=dz*float(slice+1)+globalminz;
+  float z0=dz*float(slice)+globalminz;
+
+
+  float frac=0.0;
+
+  if (elementmaxz<z0 || elementminz>z1)
+      frac=0.0;
+  else
+      {
+	// Option 1 -- Element Fully Enclosed in slice
+	if (z1>=elementmaxz && z0<=elementminz)
+	    frac=1.0;
+      else
+	  {
+	    // Option 2 -- Slice Fully Enclosed in element
+	    if (z1<=elementmaxz && z0>=elementminz)
+		frac=(z1-z0)/(elementmaxz-elementminz);
+	    else
+		{
+		  // Option 3 -- Element extends below slice
+		  if (z0>=elementminz && z1>=elementmaxz)
+		      frac=(elementmaxz-z0)/(elementmaxz-elementminz);
+		  else
+		      {
+			// Option 4 -- Element extends above slice 
+			if (z0<=elementminz && z1<=elementmaxz)
+			    frac=(z1-elementminz)/(elementmaxz-elementminz);
+			else
+			    {
+			      fprintf(stderr,"Error*\n");
+			      frac=0.0;
+			    }
+		      }
+		}
+	  }
+      }
+
+  if (debug)
+      {
+	fprintf(stderr,"\nIn element fraction elmin=%6.2f elmax=%6.2f, globmin=%6.2f globmax=%6.2f\n",
+		elementminz,elementmaxz,globalminz,globalmaxz);
+	fprintf(stderr,"z1=%6.2f z2=%6.2f dz=%7.3f Fraction=%6.4f\n",z0,z1,dz,frac);
+      }
+  return frac;
+}
+			    
+// --------------------------------------------------------------------------
+int  PXAbaqusSolid::subdivideandSavePies(const char* fname,PXAbaqusSolid** solids,int numframes,int mode,
+					 float rx,float ry,float rz,int numslices,int numsectors,
+					 int numtransmural,
+					 int anticlockwise,int skipframes)
+{
+  numslices=Irange(numslices,1,100);
+  numsectors=Irange(numsectors,1,100);
+  numtransmural=Irange(numtransmural,1,3);
+
+  int numpies=numslices*numsectors*numtransmural;
+  fprintf(stderr,"Numpies=%d\n",numpies);
+  fprintf(stderr,"++++++++++++++ Subdivide and Save in `%s' (anti=%d) \n",fname,anticlockwise);
+
+  if (!solids[0]->hasfemdata())
+      return 0;
+
+  FILE* fout=fopen(fname,"w");
+  if (fout==NULL)
+      return 0;
+
+
+  fprintf(fout,"# Pie data \n");
+  int orient=solids[0]->getorientationmode();
+  {
+    if (orient==1 || orient==3)
+      fprintf(fout,"# Strains defined in Cardiac Coordinate Space\n");
+    else if (orient==5)
+      fprintf(fout,"# Strains defined in Principal Directions\n");
+    else
+      fprintf(fout,"# Strains defined in Fibre-Specific Coordinate Space\n");
+  }
+  
+  // Precompute some stuff 
+  // Global Solid Stuff
+  float globalminz=100000.0,globalmaxz=-1000000.0,cx=0.0,cy=0.0,tvol=0.0;
+  {
+    for (int i=0;i<solids[0]->getnodes()->getnumnodes();i++)
+      {
+	float z=solids[0]->getnodes()->getpoint(i)->x[2];
+	globalminz=Fmin(globalminz,z);
+	globalmaxz=Fmax(globalmaxz,z);
+      }
+    
+    
+    {
+      for (int i=0;i<solids[0]->getelements()->getnumnodes();i++)
+	{
+	  float v=solids[0]->getfemdata()->getvolume(i);
+	  if (v<0.01)
+	    v=1.0;
+	  cx+=(solids[0]->getfemdata()->getcentroid(i))->x[0]*v;
+	  cy+=(solids[0]->getfemdata()->getcentroid(i))->x[1]*v;
+	  tvol+=v;
+	}
+    }
+    cx/=tvol; cy/=tvol;
+    fprintf(fout,"# Total volume= %9.3f\n",tvol);
+  }
+  
+  // For all elements stuff
+  // ----------------------
+  float* elementZmin=new float[solids[0]->getelements()->getnumnodes()];
+  float* elementZmax=new float[solids[0]->getelements()->getnumnodes()];
+  float* elementPmin=new float[solids[0]->getelements()->getnumnodes()];
+  float* elementPmax=new float[solids[0]->getelements()->getnumnodes()];
+  float* elementTmin=new float[solids[0]->getelements()->getnumnodes()];
+  float* elementTmax=new float[solids[0]->getelements()->getnumnodes()];
+
+  float phase_ref=atan2(ry-cy,rx-cx)*180/M_PI;
+
+  fprintf(stderr,"Phase_ref=%f\n",phase_ref);
+  
+
+  fprintf(fout,"# LV-RV Junction Defined as (%6.2f,%6.2f,%6.2f)\n",rx,ry,rz);
+  fprintf(fout,"# Phase_ref =%6.3f degrees (cx=%6.2f,cy=%6.2f)\n",phase_ref,cx,cy);
+  fprintf(fout,"# Number of slices=%d, sectors=%d\n",numslices,numsectors);
+
+  solids[0]->getelements()->Rewind();
+  for (int el=0;el<solids[0]->getelements()->getnumnodes();el++)
+      {
+	getElementRange(solids[0]->getelements()->getcurrentnode()->points,
+			solids[0]->getnodes(),
+			cx,cy,phase_ref,
+			elementZmin[el],elementZmax[el],elementPmin[el],elementPmax[el],
+			elementTmin[el],elementTmax[el]);
+	/*	if (10*int(el/10)==el)
+	    fprintf(stderr,"Element el=%d %f:%f\n",el,elementTmin[el],elementTmax[el]);*/
+	solids[0]->getelements()->Next();
+      }
+  
+  float** piesmat=matrix(0,numpies-1,0,numframes-1);
+  float *ave=new float[numpies];
+  float *vol=new float[numpies];
+  float *vol0=new float[numpies];
+  int numel=solids[0]->getelements()->getnumnodes();
+
+  int start=-1;
+  if (mode>0)
+      start=0;
+  
+  int maxstrain=5;
+  if (orient==5)
+      maxstrain=2;
+  
+  for (int strain=start;strain<=maxstrain;strain++)
+      {
+	for (int f=0;f<numframes;f++)
+	    {
+	      for (int j=0;j<numpies;j++)
+		  {
+		    ave[j]=0.0;
+		    vol[j]=0.0;
+		    if (f==0)
+			vol0[j]=0.0;
+		  }
+	      
+	      if (strain==start)
+		  (solids[f]->getfemdata())->setPieStats(numslices*numsectors*numtransmural,
+							 numsectors*numtransmural,numslices);
+
+	      for (int el=0;el<solids[0]->getelements()->getnumnodes();el++)
+		  {
+		    float elvol0=(solids[0]->getfemdata())->getvolume(el);
+		    float elvol =(solids[f]->getfemdata())->getvolume(el);
+		    
+		    int bestpie=0;
+		    float maxfr=0.0;
+		    for (int slice=0;slice<numslices;slice++)
+			{
+			  float zfr=1.0;
+			  if (numslices>1)
+			      zfr=returnElementFraction(elementZmin[el],elementZmax[el],
+							globalminz,globalmaxz,slice,numslices);
+			  
+			  for (int sector=0;sector<numsectors;sector++)
+			      {
+				int realsector=(numsectors)-sector;
+				if (anticlockwise==1)
+				    realsector=sector+1;
+
+				if (realsector==numsectors)
+				    realsector=0;
+
+				float secfr=1.0;
+				if (numsectors>1)
+				    {
+				      float elminangle= elementPmin[el];
+				      float elmaxangle= elementPmax[el];
+				      
+				      if (sector<numsectors-1)
+					  {
+					    if (elminangle>elmaxangle)
+						elminangle-=360.0;
+					  }
+				      else
+					  {
+					    if (elminangle>elmaxangle)
+						elmaxangle+=360.0;
+					  }
+				      
+				      secfr=returnElementFraction(elminangle,elmaxangle,
+								  0.0,360.0,
+								  sector,numsectors);
+				    }
+				for (int subsector=0;subsector<numtransmural;subsector++)
+				    {
+				      int   pie=subsector+realsector*numtransmural+
+					  slice*numsectors*numtransmural;
+				      
+				      float wedfr=1.0;
+				      if (numtransmural>1)
+					  {
+					    wedfr=returnElementFraction(elementTmin[el],
+									elementTmax[el],
+									0,100,subsector,numtransmural);
+					  }
+				      float frac=secfr*zfr*wedfr;
+				
+				      if (frac>maxfr)
+					  {
+					    maxfr=frac;
+					    bestpie=pie;
+					  }
+				      vol[pie]+=frac*elvol;
+				      if (f==0)
+					  vol0[pie]+=frac*elvol0;
+				      if (strain>=0)
+					  {
+					    float stcomp=
+						(solids[f]->getfemdata())->getstraincomponent(el,strain);
+					    ave[pie]+=stcomp*frac*elvol0;
+					  }
+				    }
+			      }
+			}
+		    if (strain==start)
+			(solids[f]->getfemdata())->setElementPieIndex(el,bestpie);
+		  }
+	      if (strain>=0)
+		  {
+		    for (int i=0;i<numpies;i++)
+			{
+			  if (vol0[i]<0.001)
+			      ave[i]=0.0;
+			  else
+			      ave[i]/=vol0[i];
+			}
+		    for (int j=0;j<numpies;j++)
+			piesmat[j][f]=ave[j];
+		  }
+	      else
+		  {
+		    for (int j=0;j<numpies;j++)
+			piesmat[j][f]=vol[j];
+		  } 
+	    }
+	fprintf(fout,"\n");
+	
+	if (orient<2 || orient==3 || strain<0)
+	    {
+	      switch(strain)
+		  {
+		  case -1:
+		    fprintf(fout,"#\n\t\t Volume \n"); break;
+		  case 0:
+		    fprintf(fout,"#\n\t\t Radial Strain RR\n"); break;
+		  case 1:
+		    fprintf(fout,"#\n\t\t Circumferential Strain CC\n"); break;
+		  case 2:
+		    fprintf(fout,"#\n\t\t Longitudinal Strain LL\n"); break;
+		  case 3:
+		    fprintf(fout,"#\n\t\t Radial-Circumferential Shear Strain RC\n"); break;
+		  case 4:
+		    fprintf(fout,"#\n\t\t Radial-Longitudinal Strain RL\n"); break;
+		  case 5:
+		    fprintf(fout,"#\n\t\t Circumferential-Longitudinal Strain CL\n"); break;
+		  }
+	    }
+	else if (orient==5)
+	    {
+	      fprintf(fout,"#\n\t\t Principal Strain %d\n",strain+1);
+	    }
+	else
+	    {
+	      switch(strain)
+		  {
+		  case 0:
+		    fprintf(fout,"#\n\t\t Circumferential Cross-Fibre Strain XX\n"); break;
+		  case 1:
+		    fprintf(fout,"#\n\t\t Radial Strain RR\n"); break;
+		  case 2:
+		    fprintf(fout,"#\n\t\t Fibre Strain FF\n"); break;
+		  case 3:
+		    fprintf(fout,"#\n\t\t Circumferential-Radial Shear Strain XR\n"); break;
+		  case 4:
+		    fprintf(fout,"#\n\t\t Circumferential-Fibre Strain XF\n"); break;
+		  case 5:
+		    fprintf(fout,"#\n\t\t Radial-Fibre Strain RF\n"); break;
+		  }
+	    }
+	
+	fprintf(fout,"Pie/Frame ");
+	{
+	  for (int f=0;f<numframes;f+=skipframes)
+	      fprintf(fout," %7d",f+1);
+	}
+	fprintf(fout,"\n");
+	int minj=0;
+	if (solids[0]->getnodes()->getnumnodes()<100)
+	    minj=2;
+	for (int j=minj;j<numpies;j++)
+	    {
+	      fprintf(fout,"  %7d   ",j+1);
+	      for (int f=0;f<numframes;f+=skipframes)
+		  if (strain==-1)
+		      fprintf(fout," %6.1f ",piesmat[j][f]);
+		  else
+		      fprintf(fout," %6.3f ",piesmat[j][f]);
+	      fprintf(fout,"\n");
+	    }
+      }
+  
+  if (solids[0]->getnodes()->getnumnodes()<100)
+      {
+	fprintf(fout, "\n\nPie division for each elements\nElement\tPie\n");
+	for (int i=0;i<numel;i++)
+	    {
+	      int p=solids[0]->getfemdata()->getpieindex(i);
+	      fprintf(fout,"%d \t%d\n!",i+1,p);
+	    }
+      }
+  
+  fclose(fout);
+  char line[200];
+  sprintf(line,"%s.pieindex",fname);
+  solids[0]->getfemdata()->savePieDivision(line);
+
+  free_matrix(piesmat,0,numpies-1,0,numframes-1);
+  delete [] ave;
+  delete [] vol;
+  delete [] vol0;
+  delete [] elementZmin;
+  delete [] elementZmax;
+  delete [] elementPmin;
+  delete [] elementPmax;
+  delete [] elementTmin;
+  delete [] elementTmax;
+  return 1;
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::updateFemDataDirections(int centroidsonly)
+{
+  if (!hasfemdata() || !hasnodes() || !haselements())
+      return 0;
+  
+  femData->setPieStats(1,1,1);
+  elements->Rewind();
+  for (int i=0;i<elements->getnumnodes();i++)
+      {
+	float x,y,z;
+	getElementCentroid((elements->getcurrentnode())->points,x,y,z);
+	femData->setCentroid(i,x,y,z);
+	if (centroidsonly==0)
+	    {
+	       float nx1,ny1,nz1,nx2,ny2,nz2,nx3,ny3,nz3;
+	       getdirections((elements->getcurrentnode())->points,
+			     nx1,ny1,nz1,nx2,ny2,nz2,nx3,ny3,nz3,0);
+
+	       femData->setRadial(i,nx1,ny1,nz1);
+	       femData->setCircum(i,nx2,ny2,nz2);
+	     }
+	 else
+	     {
+	       femData->setCircum(i,0,1,0);
+	       femData->setRadial(i,1,0,0);
+	     }
+	femData->setElementPieIndex(i,0);
+	elements->Next();
+       }
+  //fprintf(stderr,"Directions cent=%d, numnodes=%d\n",centroidsonly,nodes->getnumnodes());
+  return 1;
+ }
+ // --------------------------------------------------------------------------
+ int PXAbaqusSolid::getforcingnode(int nodeno,int offset)
+ {
+   nodeno-=offset;
+   int forcingnode=0;
+   if (nodeno<nodes->getnumnodes())
+       forcingnode=nodeno;
+   else if (nodeno>=nodes->getnumnodes() && hasspringnodes())
+       {
+	 nodeno-=nodes->getnumnodes();
+	 forcingnode=springNodes->getindex(nodeno,0);
+       }
+   return forcingnode;
+ }
+ // --------------------------------------------------------------------------
+ int PXAbaqusSolid::updateTemperaturesFromDisplacements(PXNodalDisplacements* disp,int mode)
+ {
+   int active=mode>0;
+   if (mode<0)
+       mode=-mode;
+   double factor=double(mode)/(100.0);
+   fprintf(stderr,"Weight Factor =%6.3f mode=%d\n",factor,mode);
+
+   // Part 1 Interior 
+   if (!hasnodes())
+       return 0;
+
+   if (disp->getsolidnodes()->getnumnodes() != nodes->getnumnodes())
+       {
+	 fprintf(stderr,"Incompatible Displacement Structure\n");
+	 return 0;
+       }
+
+   if (active>0)
+       {
+	 fprintf(stderr,"Assuming all myocardium healthy T=1.0\n");
+	 for (int i=0;i<nodes->getnumnodes();i++)
+	     nodes->settemperature(i,1.0);
+       }
+
+   // Part 2 Spring Nodes
+   if  (hasspringnodes())
+       {
+
+	 for (int i=0;i<springNodes->getnumnodes();i++)
+	     {
+	       int nd=springNodes->getindex(i,0);
+	       float v0=factor*disp->getconfidence(nd);
+	       float t1=nodes->gettemperature(nd);
+	       float wgt=pow(float(0.5),float(springNodes->getindex(i,1)));
+
+	       // spring : v0 = wgt*(t1+t2)/2.0
+	       // t2= 2.0*(v0-t1)/(wgt);
+	       float t2=(2.0*v0-t1)/(wgt);
+	       
+	       if (i==0)
+		   fprintf(stderr,"Node i =%d(t=%5.2f), Real Node=%d(t=%5.2f) conf=%5.3f \n",i,t2,nd,t1,wgt);
+
+	       springNodes->settemperature(i,t2);
+	     }
+       }
+   return 1;
+ }
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::getnodecoordinates(int node,int& layer,int& slice,int& point)
+{
+  layer=0; slice=0; point=0;
+  if (numpointscontour==-1 || !haselements() || !hasnodes())
+      return -1;
+
+  int numslices=nodes->getnumnodes()/(numpointscontour*numlayers);
+  
+  layer=node/(numslices*numpointscontour);
+  slice=(node-layer*(numslices*numpointscontour))/numpointscontour;
+  point=node-layer*(numslices*numpointscontour)-slice*numpointscontour;
+  return 1;
+}  
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::getelementcoordinates(int elno,float& layer,float& slice,float& point)
+{
+  layer=0.0;  slice=0.0;  point=0.0;
+
+  if (numpointscontour==-1 || !haselements() || !hasnodes())
+      return -1;
+  
+  int ellayers=numlayers-1;
+  int elpercontour=numpointscontour;
+  int elslices=elements->getnumnodes()/(elpercontour*ellayers);
+
+  //return la*(elslices*elpercontour)+sl*elpercontour+pt;
+
+  int la=int(elno/(elslices*elpercontour));
+  int sl=int((elno-la*elpercontour*elslices)/elpercontour);
+  int pt=int(elno-la*elpercontour*elslices-sl*elpercontour);
+  
+  layer=float(la)/float(numlayers-1);
+  slice=float(sl)/float(elslices-1);
+  point=float(pt)/float(elpercontour-1);
+  return 1;
+
+
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::getnodenofromfractionalcoordinates(float layer,float slice,float point)
+{
+  int numslices=nodes->getnumnodes()/(numpointscontour*numlayers);
+  
+  int la=Irange(int(layer*float(numlayers)),0,numlayers-1);
+  int sl=Irange(int(slice*float(numslices)),0,numslices-1);
+  int pt=Irange(int(point*float(numpointscontour)),0,numpointscontour-1);
+
+  return la*(numslices*numpointscontour)+sl*numpointscontour+pt;
+} 
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::getelementno(double layer,double slice,double point)
+{
+  if (numpointscontour==-1  || !haselements() || !hasnodes())
+      return -1;
+  
+  int ellayers=numlayers-1;
+  int elpercontour=numpointscontour;
+  int elslices=elements->getnumnodes()/(elpercontour*ellayers);
+
+  int la=int(layer);
+  int sl=int(slice);
+  int pt=int(point);
+
+  return la*(elslices*elpercontour)+sl*elpercontour+pt;
+}
+
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::rotateStrainsFiberToCardiac(int inverse)
+{
+  if (!hasfemdata()  || !haselements() || !hasnodes())
+      return -1;
+
+  
+  float** R	 = matrix(0, 2, 0, 2);
+  float** R1	 = matrix(0, 2, 0, 2);
+  float** R2	 = matrix(0, 2, 0, 2);
+  float** E	 = matrix(0, 2, 0, 2);
+  float** E2	 = matrix(0, 2, 0, 2);
+
+  if (inverse==0)
+      fprintf(stderr,"Rotating strains Fiber --> Cardiac (%d)\n",inverse);
+  else
+      fprintf(stderr,"Rotating strains Cardiac --> Fibre (%d)\n",inverse);
+  
+  elements->Rewind();
+  for (int el=0;el<elements->getnumnodes();el++)
+      {
+	PXIntegerList* intList=((elements->getcurrentnode())->points);
+	elements->Next();
+
+	float cx,cy,cz;
+	int layer=0;
+	getElementCentroid(intList,cx,cy,cz);
+	for (int ka=0;ka<intList->getnumnodes();ka++)
+	    {
+	      layer+=nodes->getindex(intList->getcurrent(),0); 
+	      intList->Next();
+	    }
+	layer=layer/intList->getnumnodes();
+
+	float x1,x2,x3,y1,y2,y3,z1,z2,z3;
+	
+	intList->Rewind();
+	getdirections(intList,
+		      x2,y2,z2,x3,y3,z3,x1,y1,z1,0);
+
+	R1[0][0]=x2; R1[1][0]=y2; R1[2][0]=z2; // Radial
+	R1[0][1]=x3; R1[1][1]=y3; R1[2][1]=z3; // Radial
+	R1[0][2]=x1; R1[1][2]=y1; R1[2][2]=z1; // Radial
+	
+	float angle=getFibreAngle(cz,layer);
+	
+	rotateFibreAngle(x3,y3,z3,  
+			 x1,y1,z1,
+			 x2,y2,z2, // Keep Radial Fixed
+			 angle);
+	
+	
+	R2[0][0]=x1; R2[1][0]=y1; R2[2][0]=z1; // Cross
+	R2[0][1]=x2; R2[1][1]=y2; R2[2][1]=z2; // Radial
+	R2[0][2]=x3; R2[1][2]=y3; R2[2][2]=z3; // Fibre
+	
+
+
+	if (inverse==0)
+	    {
+	      // R=R1'*R2
+	      for(int i=0; i<=2; i++)
+		  for(int j=0; j<=2; j++)
+		      {
+			R[i][j]=0.0;
+			for(int m=0; m<=2; m++)
+			    R[i][j] += R1[m][i] * R2[m][j];
+		      }
+	    }
+	else
+	    {
+	      // R=R2'*R1
+	      for(int i=0; i<=2; i++)
+		  for(int j=0; j<=2; j++)
+		      {
+			R[i][j]=0.0;
+			for(int m=0; m<=2; m++)
+			    R[i][j] += R2[m][i] * R1[m][j];
+		      }
+	    }
+
+
+	/*if (el==0)
+	    {
+	      fprintf(stderr,"\n\n C=(%5.2f %5.2f %5.2f) an=%6.3f\n",cx,cy,cz,angle);
+	      fprintf(stderr," R= %5.2f %5.2f %5.2f\n    %5.2f, %5.2f %5.2f\n    %5.2f %5.2f %5.2f\n\n",
+		      R[0][0],R[0][1],R[0][2],R[1][0],R[1][1],R[1][2],R[2][0],R[2][1],R[2][2]);
+	      fprintf(stderr,"R1= %5.2f %5.2f %5.2f\n    %5.2f, %5.2f %5.2f\n    %5.2f %5.2f %5.2f\n\n",
+		      R1[0][0],R1[0][1],R1[0][2],R1[1][0],R1[1][1],R1[1][2],R1[2][0],R1[2][1],R1[2][2]);
+	      fprintf(stderr,"R2= %5.2f %5.2f %5.2f\n    %5.2f, %5.2f %5.2f\n    %5.2f %5.2f %5.2f\n\n",
+		      R2[0][0],R2[0][1],R2[0][2],R2[1][0],R2[1][1],R2[1][2],R2[2][0],R2[2][1],R2[2][2]);
+	    }*/
+	
+	
+	E[0][0] = femData->getstraincomponent(el,0); 
+	E[0][1] = femData->getstraincomponent(el,3); 
+	E[0][2] = femData->getstraincomponent(el,4); 
+
+	E[1][0] = femData->getstraincomponent(el,3); 
+	E[1][1] = femData->getstraincomponent(el,1); 
+	E[1][2] = femData->getstraincomponent(el,5); 
+
+	E[2][0] = femData->getstraincomponent(el,4); 
+	E[2][1] = femData->getstraincomponent(el,5);
+	E[2][2] = femData->getstraincomponent(el,2); 
+
+	
+	// E2=R*E*R' --> E2(i,j)=R(i,k)*E(k,m)*R'(m,j)
+	for (int i=0;i<=2;i++)
+	    for (int j=0;j<=2;j++)
+		{
+		  E2[i][j]=0.0;
+		  for (int k=0;k<=2;k++)
+		      for (int m=0;m<=2;m++)
+			  E2[i][j] += R[i][k]*E[k][m]*R[j][m];
+		}
+
+	femData->setElementInfo(el,1,-1.0,
+				E2[0][0],E2[1][1],E2[2][2],E2[0][1],E2[0][2],E2[1][2]);
+
+
+	/*if (el==0)
+	    {
+	      fprintf(stderr," E= %5.2f %5.2f %5.2f\n    %5.2f, %5.2f %5.2f\n    %5.2f %5.2f %5.2f\n\n",
+		       E[0][0], E[0][1], E[0][2], E[1][0], E[1][1], E[1][2], E[2][0], E[2][1], E[2][2]);
+	      fprintf(stderr,"E2= %5.2f %5.2f %5.2f\n    %5.2f, %5.2f %5.2f\n    %5.2f %5.2f %5.2f\n\n",
+		      E2[0][0],E2[0][1],E2[0][2],E2[1][0],E2[1][1],E2[1][2],E2[2][0],E2[2][1],E2[2][2]);
+	      E[0][0] = femData->getstraincomponent(el,0); 
+	      E[0][1] = femData->getstraincomponent(el,3); 
+	      E[0][2] = femData->getstraincomponent(el,4); 
+	      
+	      E[1][0] = femData->getstraincomponent(el,3); 
+	      E[1][1] = femData->getstraincomponent(el,1); 
+	      E[1][2] = femData->getstraincomponent(el,5); 
+	      
+	      E[2][0] = femData->getstraincomponent(el,4); 
+	      E[2][1] = femData->getstraincomponent(el,5);
+	      E[2][2] = femData->getstraincomponent(el,2); 
+	      fprintf(stderr,"+E= %5.2f %5.2f %5.2f\n    %5.2f, %5.2f %5.2f\n    %5.2f %5.2f %5.2f\n\n",
+		      E[0][0], E[0][1], E[0][2], E[1][0], E[1][1], E[1][2], E[2][0], E[2][1], E[2][2]);
+	    }*/
+	
+	
+      }
+
+  free_matrix(R,0,2,0,2); free_matrix(R1,0,2,0,2); free_matrix(R2,0,2,0,2);
+  free_matrix(E,0,2,0,2); free_matrix(E2,0,2,0,2);
+
+  return 1;
+}
+// --------------------------------------------------------------------------
+int PXAbaqusSolid::makeIncompressibleLL()
+{
+  if (!hasfemdata()  || !haselements() || !hasnodes())
+      return -1;
+
+  float E[3][3];
+
+  fprintf(stderr,"Adjusting LL for incompressibility\n");
+
+  rotateStrainsFiberToCardiac(0);
+  for (int el=0;el<elements->getnumnodes();el++)
+      {
+	E[0][0] = femData->getstraincomponent(el,0); 
+	E[0][1] = femData->getstraincomponent(el,3); 
+	E[0][2] = femData->getstraincomponent(el,4); 
+	E[1][1] = femData->getstraincomponent(el,1); 
+	E[1][2] = femData->getstraincomponent(el,5); 
+	E[2][2] = femData->getstraincomponent(el,2); 
+
+
+	float e22= -(E[0][0]+E[1][1]);
+
+	
+
+	if (int(el/10)*10 == el)
+	    fprintf(stderr,"EL=%d RR=%5.2f CC=%5.2f LL=%5.2f RC=%5.2f , RL=%5.2f CL=%5.2f\te22=%5.2f\n",
+		    el,E[0][0],E[1][1],E[2][2],E[0][1],E[0][2],E[1][2],e22);
+	
+
+	E[2][2]=0.5*e22+0.5*E[2][2];
+	
+	femData->setElementInfo(el,1,-1.0,
+				E[0][0],E[1][1],E[2][2],E[0][1],E[0][2],E[1][2]);
+      }
+
+  rotateStrainsFiberToCardiac(1);
+  return 1;
+}
+// --------------------------------------------------------------------------
+/*
+   Strain Comparison Stuff
+*/
+// --------------------------------------------------------------------------
+void PXAbaqusSolid::generatePoints(PXIntegerList* element,PX3Vector* vec,int& maxp)
+{
+  PX3Vector nd[8];
+    for (int i=0;i<element->getnumnodes();i++)
+      {
+	int index=element->getcurrent();
+	float x=getnodes()->getpoint(index)->x[0];
+	float y=getnodes()->getpoint(index)->x[1];
+	float z=getnodes()->getpoint(index)->x[2];
+	nd[i].setvector(x,y,z);
+	element->Next();
+      }
+  
+  switch (element->getnumnodes())
+      {
+      case 4:
+	if (maxp>=5)
+	    {
+	      vec[4].setvector(0.0,0.0,0.0);
+	      for (int i=0;i<=3;i++)
+		  {
+		    vec[i].copy(&nd[i]);
+		    vec[4].add(&nd[i],0.25);
+		  }
+	      maxp=5;
+	    }
+	else
+	    maxp=0;
+	break;
+      case 6:
+	if (maxp>=30)
+	    {
+	      for (int ii=0;ii<30;ii++)
+		  vec[ii].setvector(0.0,0.0,0.0);
+	      for (int i=0;i<=1;i++)
+		  {
+		    vec[i*6+0].copy(&nd[i*3+0]);
+		    vec[i*6+1].add(&nd[i*3+0],0.5);  vec[i*6+1].add(&nd[i*3+1],0.5);
+		    vec[i*6+2].copy(&nd[i*3+1]);
+		    vec[i*6+3].add(&nd[i*3+0],0.5);  vec[i*6+3].add(&nd[i*3+2],0.5);
+		    vec[i*6+4].add(&nd[i*3+2],0.5);  vec[i*6+1].add(&nd[i*3+1],0.5);
+		    vec[i*6+5].copy(&nd[i*3+2]);
+		  }
+	      for (int j=1;j<=3;j++)
+		  {
+		    float f2=float(j)*0.25;
+		    for (int i=0;i<=5;i++)
+			{
+			  int index=i+(j+1)*6;
+			  vec[index].add(&vec[i],1.0-f2);
+			  vec[index].add(&vec[i+6],f2);
+			}
+		  }
+	      maxp=24;
+	    }
+	else
+	    maxp=0;
+	break;
+      case 8:
+	if (maxp>=65)
+	    {
+	      for (int ii=0;ii<65;ii++)
+		  vec[ii].setvector(0.0,0.0,0.0);
+	      
+	      for (int i=0;i<=1;i++)
+		  {
+		    int offset=i*13;
+		    vec[offset+0].copy(&nd[i*4+0]);
+		    vec[offset+2].copy(&nd[i*4+1]);
+		    vec[offset+8].copy(&nd[i*4+2]);
+		    vec[offset+6].copy(&nd[i*4+3]);
+		    
+		    vec[offset+1].add(&vec[offset+0],0.5); vec[offset+1].add(&vec[offset+2],0.5);
+		    
+		    vec[offset+3].add(&vec[offset+0],0.5); vec[offset+3].add(&vec[offset+6],0.5);
+		    vec[offset+5].add(&vec[offset+2],0.5); vec[offset+5].add(&vec[offset+8],0.5);
+		    vec[offset+7].add(&vec[offset+6],0.5); vec[offset+7].add(&vec[offset+8],0.5);
+		    
+		    vec[offset+4].add(&vec[offset+1],0.25); vec[offset+4].add(&vec[offset+3],0.25);
+		    vec[offset+4].add(&vec[offset+5],0.25); vec[offset+4].add(&vec[offset+7],0.25);
+		    
+		    vec[offset+9].add(&vec[offset+0],0.25); vec[offset+9].add(&vec[offset+1],0.25);
+		    vec[offset+9].add(&vec[offset+3],0.25); vec[offset+9].add(&vec[offset+4],0.25);
+
+		    vec[offset+10].add(&vec[offset+1],0.25); vec[offset+10].add(&vec[offset+2],0.25);
+		    vec[offset+10].add(&vec[offset+4],0.25); vec[offset+10].add(&vec[offset+5],0.25);
+		    
+		    vec[offset+11].add(&vec[offset+6],0.25); vec[offset+11].add(&vec[offset+7],0.25);
+		    vec[offset+11].add(&vec[offset+4],0.25); vec[offset+11].add(&vec[offset+3],0.25);
+
+		    vec[offset+12].add(&vec[offset+7],0.25); vec[offset+12].add(&vec[offset+8],0.25);
+		    vec[offset+12].add(&vec[offset+4],0.25); vec[offset+12].add(&vec[offset+5],0.25);
+
+
+		  }
+	      
+	      for (int j=1;j<=3;j++)
+		  {
+		    float f2=0.25*float(j);
+		    for (int i=0;i<=12;i++)
+			{
+			  int index=i+(j+1)*13;
+			  vec[index].add(&vec[i],1.0-f2);
+			  vec[index].add(&vec[i+13],f2);
+			}
+		  }
+	      maxp=65;
+	    }
+	else
+	    maxp=0;
+	break;
+      }
+}
+// --------------------------------------------------------------------------
+void PXAbaqusSolid:: getElementZThetaRange(PXIntegerList* element,
+					   float cx,float cy,
+					   float& minz,float& maxz,
+					   float& minangle,float& maxangle)
+{
+  minangle=10000.0,maxangle=-100000.0;
+  minz=100000.0,maxz=-100000.0;
+
+  element->Rewind();
+  for (int i=0;i<element->getnumnodes();i++)
+      {
+	int index=element->getcurrent();
+	element->Next();
+	float x=getnodes()->getpoint(index)->x[0]-cx;
+	float y=getnodes()->getpoint(index)->x[1]-cy;
+	float z=getnodes()->getpoint(index)->x[2];
+	minz=Fmin(minz,z);
+	maxz=Fmax(maxz,z);
+	float phase=Fcyclic(atan2(y,x)*180/M_PI,360.0);
+	minangle=Fmin(phase,minangle);
+	maxangle=Fmax(phase,maxangle);
+	fprintf(stderr,"Node %d (%5.2f ,%5.2f) Phase=%6.3f\n",i,x,y,phase);
+      }
+
+  minangle=Fcyclic(minangle,360.0);
+  maxangle=Fcyclic(maxangle,360.0);
+
+
+  /*if (maxangle-minangle>180.0)
+      {
+	float temp=maxangle;
+	maxangle=minangle;
+	minangle=temp;
+      } */
+}
+// --------------------------------------------------------------------------  
+int PXAbaqusSolid::compareWithOtherSolid(PXAbaqusSolid* sld,const char* fname,float mindist)
+{
+  fprintf(stderr,"++++++++++++++ Compare Strains and Save in %s \n",fname);
+
+  if (!sld->hasfemdata() || !hasfemdata())
+      {
+	fprintf(stderr,"No strains in one or other solid\n");
+	return 0;
+      }
+
+
+
+  /*if (sld->getorientationmode() !=getorientationmode())
+      {
+	fprintf(stderr,"Orientations are different\n");
+	//return 0;
+      }*/
+
+  sld->getfemdata()->converttoprincipal();
+  getfemdata()->converttoprincipal();
+
+  setorientationmode(5);
+  sld->setorientationmode(5);
+
+  FILE* fout=fopen(fname,"w");
+  if (fout==NULL)
+      return 0;
+
+  fprintf(fout,"# Comparison data \n");
+  int orient=sld->getorientationmode();
+      {
+	 if (orient==1 || orient==3)
+	     fprintf(fout,"# Strains defined in Cardiac Coordinate Space\n");
+	 else if (orient==5)
+	     fprintf(fout,"# Strains defined in Principal Directions\n");
+	 else
+	     fprintf(fout,"# Strains defined in Fibre-Specific Coordinate Space\n");
+      }
+
+  // Precompute some stuff 
+  // Global Solid Stuff
+  float globalminz=100000.0,globalmaxz=-1000000.0,cx=0.0,cy=0.0,tvol=0.0;
+  {
+    {
+      for (int i=0;i<getnodes()->getnumnodes();i++)
+	  {
+	    float z=getnodes()->getpoint(i)->x[2];
+	    globalminz=Fmin(globalminz,z);
+	    globalmaxz=Fmax(globalmaxz,z);
+	  }
+    }
+
+    for (int i=0;i<getelements()->getnumnodes();i++)
+	{
+	  cx+=(getfemdata()->getcentroid(i))->x[0]*
+	      getfemdata()->getvolume(i);
+	  cy+=(getfemdata()->getcentroid(i))->x[1]*
+	      getfemdata()->getvolume(i);
+	  tvol+=(getfemdata())->getvolume(i);
+	}
+    cx/=tvol; cy/=tvol;
+    fprintf(fout,"# Total volume= %9.3f\n",tvol);
+  }
+
+  fprintf(fout,"# Centroid (cx=%6.2f,cy=%6.2f)\n",cx,cy);
+  
+  // For all elements stuff
+  // ----------------------
+  /*float* elementZ=new float[getelements()->getnumnodes()];
+  float* elementA=new float[getelements()->getnumnodes()];
+  getelements()->Rewind();
+  for (int el=0;el<getelements()->getnumnodes();el++)
+      {
+	float x,y,z;
+	getElementCentroid(getelements()->getcurrentnode()->points,x,y,z);
+	elementA[el]=Fcyclic(atan2(y-cy,x-cx)*180/M_PI,360.0);
+	elementZ[el]=z;
+	getelements()->Next();
+      }*/
+  
+  int nummarkerpies=sld->getelements()->getnumnodes(); 
+  float *ave=new float[nummarkerpies];
+  float *vol=new float[nummarkerpies];
+
+  //int    numel=getelements()->getnumnodes();
+
+  int start=-1;
+  int maxstrain=5;
+  if (orient==5)
+      maxstrain=2;
+  getfemdata()->setPieStats(2,2,1);
+
+  PX3Vector* vec=new PX3Vector[65];
+
+  for (int strain=start;strain<=maxstrain;strain++)
+      {
+	sld->getelements()->Rewind();
+	for (int pie=0;pie<sld->getelements()->getnumnodes();pie++)
+	    {
+	      // Get Range for Marker Element and Set Ave, vol=0 
+	      PXIntegerList* markerElement=sld->getelements()->getcurrentnode()->points;
+	      sld->getelements()->Next();
+	      /*float zmin,zmax,pmin,pmax;
+	      sld->getElementZThetaRange(markerElement,cx,cy,zmin,zmax,pmin,pmax);*/
+	      
+	      int maxp=65;
+	      sld->generatePoints(markerElement,vec,maxp);
+
+	      ave[pie]=0.0; 	
+	      vol[pie]=0.0;
+	      //fprintf(stderr,"Processing pie %d/%d\n",pie,sld->getelements()->getnumnodes());
+	      /*fprintf(stderr,"\t Zrange %5.2f:%5.2f Arange %6.2f:%6.2f\n",
+		      zmin,zmax,pmin,pmax);*/
+
+	      elements->Rewind();
+	      
+	      for (int el=0;el<getelements()->getnumnodes();el++)
+		  {
+		    float x,y,z;
+		    getElementCentroid(getelements()->getcurrentnode()->points,x,y,z);
+		    float elvol=(getfemdata())->getvolume(el);
+		    
+		    PX3Vector cent;
+		    cent.setvector(x,y,z);
+		    int i=0;
+		    int found=0;
+		    while (i<maxp && found==0)
+			{
+			  float dist=cent.getdistance(&vec[i]);
+			  if (dist<=mindist)
+			      found=1;
+			  i++;
+			}
+		    if (found==1)
+			{
+			  if (strain>=0)
+			      ave[pie]+=getfemdata()->getstraincomponent(el,strain)*elvol;
+			  vol[pie]+=elvol;
+			  getfemdata()->setElementPieIndex(el,1);
+			}
+		    else
+			getfemdata()->setElementPieIndex(el,0);
+		    elements->Next();
+	    
+		  }
+	      if (strain==0)
+		  {
+		    char line[400];
+		    sprintf(line,"Pie%d.pieindex",pie+1);
+		    getfemdata()->savePieDivision(line);
+		    PXMarkerCollection* markers=new PXMarkerCollection(maxp,1);
+		    sprintf(line,"Pie%d.mark",pie+1);
+		    for (int m=0;m<maxp;m++)
+			{
+			  markers->getmarker(m)->getclickedpoints(0)->addpoint(vec[m].x[0],
+									       vec[m].x[1],
+									       vec[m].x[2],0.0);
+			  markers->getmarker(m)->setposition(0,vec[m].x[0],vec[m].x[1],vec[m].x[2]);
+			}
+		    markers->savemarkercollection(line);
+		    delete markers;
+		  }
+	    }
+	if (strain>=0)
+	    {
+	      for (int i=0;i<nummarkerpies;i++)
+		  {
+		    if (vol[i]<0.001)
+			ave[i]=0.0;
+		    else
+			ave[i]/=vol[i];
+		  }
+	    }
+	if (orient<2 || orient==3 || strain<0)
+	    {
+	      switch(strain)
+		  {
+		  case -1:
+		    fprintf(fout,"#\n\t Volume \n\n"); break;
+		  case 0:
+		    fprintf(fout,"#\n\t Radial Strain RR\n\n"); break;
+		  case 1:
+		    fprintf(fout,"#\n\t Circumferential Strain CC\n\n"); break;
+		  case 2:
+		    fprintf(fout,"#\n\t Longitudinal Strain LL\n\n"); break;
+		  case 3:
+		    fprintf(fout,"#\n\t Radial-Circumferential Shear Strain RC\n\n"); break;
+		  case 4:
+		    fprintf(fout,"#\n\t Radial-Longitudinal Strain RL\n\n"); break;
+		  case 5:
+		    fprintf(fout,"#\n\t Circumferential-Longitudinal Strain CL\n\n"); break;
+		  }
+	    }
+	else if (orient==5)
+	    {
+	      fprintf(fout,"#\n\t Principal Strain %d\n\n",strain+1);
+	    }
+	else
+	    {
+	      switch(strain)
+		  {
+		  case 0:
+		    fprintf(fout,"#\n\t Circumferential Cross-Fibre Strain XX\n\n"); break;
+		  case 1:
+		    fprintf(fout,"#\n\t Radial Strain RR\n\n"); break;
+		  case 2:
+		    fprintf(fout,"#\n\t Fibre Strain FF\n\n"); break;
+		  case 3:
+		    fprintf(fout,"#\n\t Circumferential-Radial Shear Strain XR\n\n"); break;
+		  case 4:
+		    fprintf(fout,"#\n\t Circumferential-Fibre Strain XF\n\n"); break;
+		  case 5:
+		    fprintf(fout,"#\n\t Radial-Fibre Strain RF\n\n"); break;
+		  }
+	    }
+	
+	fprintf(fout,"Pie\tSolid\tMarker \n");
+	for (int j=0;j<nummarkerpies;j++)
+	    {
+	      fprintf(fout,"%2d\t",j+1);
+	      if (strain==-1)
+		  fprintf(fout,"%6.1f\t %6.1f ",vol[j],sld->getfemdata()->getvolume(j));
+	      else
+		  fprintf(fout,"%6.3f\t %6.3f ",ave[j],sld->getfemdata()->getstraincomponent(j,strain));
+	      fprintf(fout,"\n");
+	    }
+
+      }
+  fclose(fout);
+
+  delete [] ave;
+  delete [] vol;
+  delete [] vec;
+  /*delete [] elementZ;
+  delete [] elementA;*/
+  return 1;
+}
+
diff --git a/bioimagesuite30_src/numerics/pxabaqussolid.h b/bioimagesuite30_src/numerics/pxabaqussolid.h
new file mode 100644
index 0000000..8d6c8de
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxabaqussolid.h
@@ -0,0 +1,322 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pxAbaqusSolid.h
+// -----------------------------------------------------------------
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+_Module_Name : PxAbaqusSolid 
+
+_Description : A structures which stores a triangulated StackSolid
+               
+
+_Call : 
+  PxAbaqusSolid();
+  PxAbaqusSolid(PXContourStackSolid *old);
+
+_References :
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 14th August 1998
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PxAbaqusSolid
+#define _PxAbaqusSolid
+#include "pxgeometrystruct.h"
+#include "pxabaqusstructures.h"
+#include "pxtriangulatedstack.h"
+
+
+const int ABAQUSSOLIDMAXLEVELS=20;
+const int ABAQUSSOLIDMAXFRAMES=30;
+const int PXABAQUSOFFSET=1000;
+
+class PXAbaqusSolid {
+  
+protected:
+
+  // Original Inputs 
+  PXTriangulatedStack*      tstack[2];
+
+  // Geometrical Parameters 
+  int                       elementtype,elementmode,hasmidwallnodes,hasmidwallelements;
+  int                       numlayers,numpointscontour;
+  PXNeighboursList*         elements,*springElements;
+  PXSolidNodes*             nodes,*springNodes;
+
+  // Mechanical  Model Parameters
+  PXAbaqusMaterialModel*    material;
+  float                     springMultiplier;
+
+  // Boundary Conditions
+  float                     *volume;
+  int                       hasVolumes,numvolumes;
+
+  // Numerical Solution
+  float                     outputStep;
+  int                       outputInc;
+  int                       enforcementMode,orientationMode;
+
+  // Finite Element Data Postprocessing
+  PXAbaqusOutputData*      femData;
+
+  // Verify Existence
+  int                       hasElements,hasNodes,hasMaterial,hasStacks;
+  int                       hasFemData,hasSpringElements,hasSpringNodes;
+
+public:
+  
+  PXAbaqusSolid();
+  PXAbaqusSolid(PXAbaqusSolid* old);
+  PXAbaqusSolid(PXTriangulatedStack* stack1,PXTriangulatedStack* stack2);
+  PXAbaqusSolid(const char* fname1,const char* fname2);
+ 
+  virtual ~PXAbaqusSolid();
+  void init();
+  void cleanup();
+
+  void Copy(PXAbaqusSolid* other);
+
+  // Access Functions
+  // ----------------
+  int      getelementtype(); 
+  int      getelementmode(); 
+  int      getnumlayers();
+  int      getnumpointscontour();
+
+  float    getoutputstep();  
+  int      getoutputinc();   
+  int      getenforcementmode(); 
+  int      getorientationmode(); 
+  float    getspringmulitplier();
+
+  int      hasstacks();
+  int      hasfemdata();
+  int      hasnodes();           
+  int      haselements();        
+  int      hasspringnodes();        
+  int      hasspringelements();     
+
+  int      hasmaterial();        
+  int      hasvolumes();
+  float*   getvolumes();
+  int      getnumvolumes();
+
+  PXAbaqusOutputData*  getfemdata();
+  PXNeighboursList*    getelements();
+  PXNeighboursList*    getspringelements();
+  PXSolidNodes*        getnodes();   
+  PXSolidNodes*        getspringnodes();   
+  PXAbaqusMaterialModel* getmaterial();
+  PX3Vector*           getnodeoutput();
+
+  PXTriangulatedStack* getstack(int i);
+
+  // Geometry Related
+  // ----------------
+  int generateTetrahedralSolid(float spacing,int bias);
+  int generateHexahedralSolid(int nodespercontour,int totalnumstacks,int bias,float sample,int skipslices=0);
+  int  saveInventor(const char* fname,int mode=-1,int cmode=-1,float* params=NULL);
+  int  saveInventor(FILE* fout,int mode=1,int cmode=-1,float* params=NULL);
+
+  // I/O Related
+  // -----------
+  int Save(const char* fname);
+  int Save(FILE* fout);
+  int Load(const char* fname);
+  int Load(gzFile fin);
+
+  // Element Stuff
+  // -------------
+  void getdirections(PXIntegerList* element,
+		     float& nx1,float& ny1,float& nz1,
+		     float& nx2,float& ny2,float& nz2,
+		     float& nx3,float& ny3,float& nz3,
+		     int movetoepi=1);
+
+  void rotateFibreAngle(float& nx1,float& ny1,float& nz1,
+			float& nx2,float& ny2,float& nz2,
+			float  nx3,float  ny3,float  nz3,
+			float angle); 
+
+  int  rotateStrainsFiberToCardiac(int inverse=0);
+
+  float getFibreAngle(float z,int layer,float bottomz=1.5,float topz=36.0);
+  void  getElementCentroid(PXIntegerList* element,float&x,float&y,float& z);
+  int   getforcingnode(int nodeno,int offset=1000);
+
+  // Stacks and Nodes Connection
+  // ---------------------------
+  int modifyStacksFromNodes();
+  int updateCurvaturesFromStacks();
+  int updateFromOutputStructures(int position=0);
+  int correctForIncormpressibility(PXAbaqusOutputData* baseData);
+  int updateTemperaturesFromDisplacements(PXNodalDisplacements* disp,int mode=0);
+  int setCurvaturesFromDenserStacks(PXTriangulatedStack* denseInner,PXTriangulatedStack* denseOuter);
+  void setorientationmode(int m=0); 
+  void sethybridmode(int h=0); 
+
+  // FemData Related
+  // ---------------
+  int updateFemDataDirections(int centroidsonly=0);
+  
+  // AbaqusRelated
+  // -------------
+  void setSpringParameters(int enfMode=1,float springk=0.5);
+  void setOrientationMode(int ormode=0);
+  void setNumericalParameters(float stepSize=1.0,int numInc=40);
+  int  insertKinematicConstraints(FILE* fout,int mode=0);
+  int  fixApexorBase(FILE* fout,int md=4);
+  int  CreateJobBase(FILE* fout,const char* includefile,int springmode);
+  int  CreateStepHeader(FILE* fout);
+  int  CreateStepFooter(FILE* fout,int resout=0,int fieldout=0);
+  int  CreateSteps2DEcho(FILE* fout,int numframes,int resout);
+  int  CreateStepsPassive3D(FILE* fout,int numframes,int resout,int flattopbottom);
+  int  CreateStepsActive3D(FILE* fout,int numframes,int resout,int flattopbottom);
+  int  CreateStepsSinglePass(FILE* fout,int numframes,int springmode,int resout,int flattopbottom);
+
+  int  saveAbaqus(const char* fname,int resout=1,int numframes=-1,const char* includefile=NULL,int flattopbottom=0);
+  int  saveAbaqusFortran(const char* fortranfile,const char* jobname,
+                         const char* solidname,const char* endostem,const char* epistem,const char* priorstem,
+			 int curvmode=-1,float lamda=0.5,int frameoffset=0);
+
+
+  // Volume Stuff
+  // --------------
+  int  generateVolumes(const char* fnameendo,const char* fnameepi,int end,int begin=1);
+  int  makeIncompressibleLL();
+
+
+  // Allocation Related
+  // ------------------
+
+  void allocateMaterial();
+  void allocateFemData();
+  void allocateSpringSpace(int order=0);
+
+  // Location in solid related (for 8 element ordered solids)
+  // --------------------------------------------------------
+  int getnodecoordinates(int node,int& layer,int& slice,int& point);
+  int getelementcoordinates(int element,float& layer,float& slice,float& point);
+  int getelementno(double layer,double slice,double point);
+  int getnodenofromfractionalcoordinates(float layer,float slice,float point);
+
+  // Compare with other solid
+  // ------------------------
+
+  void  getElementZThetaRange(PXIntegerList* element,
+			      float cx,float cy,
+			      float& minz,float& maxz,
+			      float& minangle,float& maxangle);
+
+
+  void generatePoints(PXIntegerList* element,PX3Vector* vec,int& maxp);
+  int compareWithOtherSolid(PXAbaqusSolid* sld,const char* fname,float dist=1.0);
+				   
+
+
+protected:
+
+  // Solid Generation
+  // ----------------
+  PXTriangulatedStackPoint* getpoint(int index,int *total,int numstacks);
+
+  // Cleanup Operations
+  // ------------------
+  void cleanupFemData();
+  void cleanupNodeSpace();
+  void cleanupElementSpace();
+  void cleanupSpringSpace();
+  void cleanupMaterial();
+
+
+  // More Allocation Stuff
+  // ---------------------
+  void allocateNodeSpace(int numnode);
+  void allocateElementSpace();
+
+
+public:
+
+  // Static Functions mainly to do with postprocessing fem data
+  // ----------------------------------------------------------
+  static int debugmode;  
+  static void color_lookup(PX3Vector& output,float value,float* params=NULL,int mode=1);
+
+
+  static int  loadJobIntoSolidArray(const char* fname,PXAbaqusSolid** solids,int maxsolids,
+				    int numslices=3,int numsectors=8,int rotate=1);
+  static int  averageStrainsInSolidArray(PXAbaqusSolid** solids,int numframes,
+					 float jx,float jy,float jz,int numslices=3,int numsectors=8,
+					 int anticlockwise=1);
+  static int  averageStrainsInSolidArray(PXAbaqusSolid** solids,int numframes);
+  static int  savePies(const char* fname,PXAbaqusSolid** solids,int numframes,int mode=0,int skip=1);
+
+
+  // Sub-slice subdivision code 
+  static float returnElementFraction(float elementminz,float elementmaxz,float globalminz,float globalmaxz,
+				     int slice,int numslices,int debug=0);
+  static void  getElementRange(PXIntegerList* element,PXSolidNodes* nodes,float cx,float cy,float phase_ref,
+			       float& minz,float& maxz,
+			       float& minangle,float& maxangle,
+			       float& mintransmural,float& maxtransmural);
+  static int subdivideandSavePies(const char* fname,PXAbaqusSolid** solids,int numframes,int mode,
+				  float rx,float ry,float rz,int numslices,int numsectors,
+				  int numtransmural,
+				  int anticlockwise,int skipframes);
+
+
+
+  
+  // For temperature adjusted points 
+  // -------------------------------
+  static float temperatureForVolChange(float vol1,float vol2,int nlgeom=1);
+  
+};
+
+  
+  
+#endif  
+
diff --git a/bioimagesuite30_src/numerics/pxabaqusstructures.cpp b/bioimagesuite30_src/numerics/pxabaqusstructures.cpp
new file mode 100644
index 0000000..e78d0ad
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxabaqusstructures.cpp
@@ -0,0 +1,2208 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//
+//
+//  Uses a little bit of trivial eigenvector/eigenvalue code ... should be easy to remove
+//
+//---------------------------------------------------------------------------------------------------------
+
+
+#include "pxabaqusstructures.h"
+#include "pxutil.h"
+#include "nrutil.h"
+
+
+
+
+
+// ************************************************
+// Solid Nodes 
+// ************************************************
+
+PXSolidNodes::PXSolidNodes(int numn)
+{
+ init(numn);
+}
+
+PXSolidNodes::PXSolidNodes(PXSolidNodes* oldnodes)
+{
+ init(oldnodes->getnumnodes());
+ Copy(oldnodes);
+}
+
+PXSolidNodes::PXSolidNodes(PXSolidNodes* oldnodes1,PXSolidNodes* oldnodes2)
+{
+  init(oldnodes1->getnumnodes()+oldnodes2->getnumnodes());
+  Copy(oldnodes1,0,0);
+  Copy(oldnodes2,0,oldnodes1->getnumnodes());
+}
+
+void PXSolidNodes::init(int numn)
+{
+ numnodes=Irange(numn,2,100000);
+ points=new PXTriangulatedStackPoint[numnodes];
+ pointDetails=new PXNodeAuxiliary[numnodes];
+ for (int ii=0;ii<numnodes;ii++)
+     pointDetails[ii].neighbours=new PXIntegerList();
+
+ for (int i=0;i<numnodes;i++)
+     {
+       points[i].index=i;
+       for (int ia=0;ia<=2;ia++)
+	   {
+	     points[i].x[ia]=0.0;
+	     points[i].nx[ia]=0.0;
+	     pointDetails[i].dx[ia]=0.0;
+	   }
+       
+       for (int iia=0;iia<=1;iia++)
+	   {
+	     points[i].k[iia]=0.0;
+	     pointDetails[i].index[iia]=-1;
+	   }
+       pointDetails[i].temperature=0.0;
+     }
+ 
+}
+// ************************************************
+PXSolidNodes::~PXSolidNodes()
+{
+  cleanup();
+}
+// ************************************************
+void PXSolidNodes::cleanup()
+{
+  for (int i=0;i<numnodes;i++)
+      delete pointDetails[i].neighbours;
+  delete [] pointDetails;
+  delete [] points;
+}
+// ************************************************
+int PXSolidNodes::getnumnodes()
+{
+  return numnodes;
+}
+// ************************************************
+PXTriangulatedStackPoint* PXSolidNodes::getpoint(int pointidx)
+{
+  //  fprintf(stderr,"getting %d < %d ",pointidx,numnodes);
+  pointidx=Irange(pointidx,0,numnodes-1);
+  return &points[pointidx];
+}
+// ************************************************
+PXNodeAuxiliary* PXSolidNodes::getdetails(int pointidx)
+{
+  pointidx=Irange(pointidx,0,numnodes-1);
+  return &pointDetails[pointidx];
+}
+// ************************************************
+int PXSolidNodes::getindex(int pointidx,int index)
+{
+  pointidx=Irange(pointidx,0,numnodes-1);
+  index=Irange(index,0,1);
+  return pointDetails[pointidx].index[index];
+}
+// ************************************************
+void  PXSolidNodes::settemperature(int pointidx,float val)
+{
+  pointidx=Irange(pointidx,0,numnodes-1);
+  pointDetails[pointidx].temperature=val;
+}
+// ************************************************
+float PXSolidNodes::gettemperature(int pointidx)
+{
+  pointidx=Irange(pointidx,0,numnodes-1);
+  return pointDetails[pointidx].temperature;
+}
+// ************************************************
+void PXSolidNodes::setindex(int pointidx,int index,int val)
+{
+  pointidx=Irange(pointidx,0,numnodes-1);
+  index=Irange(index,0,1);
+  pointDetails[pointidx].index[index]=val;
+}
+// ************************************************
+PXIntegerList* PXSolidNodes::getneighbours(int pointidx)
+{
+  pointidx=Irange(pointidx,0,numnodes-1);
+  return pointDetails[pointidx].neighbours;
+}
+// ************************************************---
+int PXSolidNodes::Save(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout!=NULL)
+      {
+       int st=Save(fout);
+       fclose(fout);
+       return st;
+     }
+ return 0;
+}
+// ************************************************---
+int PXSolidNodes::Load(const char* fname)
+{
+ gzFile fin=gzsuffixopen(fname,"r");
+ if (fin)
+     {
+       int st=Load(fin);
+       gzclose(fin);
+       return st;
+     }
+ return 0;
+}
+// ************************************************---
+int PXSolidNodes::Save(FILE* fout)
+{
+  fprintf(fout,"#SolidNodesList\n");
+  fprintf(fout,"%d\n",numnodes);
+  int ia=0;
+  
+ for (int i=0;i<numnodes;i++)
+   {
+       fprintf(fout,"%6d ",points[i].index+1000);
+       for (ia=0;ia<=2;ia++)
+	   fprintf(fout," %7.3f ",points[i].x[ia]);
+       for (ia=0;ia<=2;ia++)
+	   fprintf(fout," %7.3f ",points[i].nx[ia]);
+       for (ia=0;ia<=1;ia++)
+	   fprintf(fout," %7.3f ",points[i].k[ia]);
+       fprintf(fout,"\n ");
+       for (ia=0;ia<=2;ia++)
+	   fprintf(fout," %7.3f ",pointDetails[i].dx[ia]);
+       for (ia=0;ia<=1;ia++)
+	   fprintf(fout," %5d ",pointDetails[i].index[ia]);
+       fprintf(fout,"%7.3f\n",pointDetails[i].temperature);
+       
+       fprintf(fout," %3d ",pointDetails[i].neighbours->getnumnodes());
+       for(int j=0;j<pointDetails[i].neighbours->getnumnodes();j++)
+	   {
+	     fprintf(fout,"\t%d",pointDetails[i].neighbours->getcurrent());
+	     pointDetails[i].neighbours->Next();
+	   }
+       fprintf(fout,"\n");
+     }
+ return 1;
+}
+
+// ************************************************---
+int PXSolidNodes::Load(gzFile fin)
+{
+ char* line=new char[400];
+ gzgets(fin,line,200);
+ if (gzfindstringinstring(line,"#SolidNodesList")==0)
+     {
+       //fprintf(stderr,"line=%s Failed\n",line);
+       delete [] line;
+       return 0;
+     }
+ //fprintf(stderr,"line=%s OK\n",line);
+     
+ int num2;
+
+ gzgets(fin,line,200);
+ sscanf(line,"%d\n",&num2);
+ cleanup();
+ init(num2);
+ 
+ for (int i=0;i<numnodes;i++)
+     {
+       gzgets(fin,line,200);
+       sscanf(line,"%d %f %f %f %f %f %f %f %f",
+	      &points[i].index,
+	      &points[i].x[0],
+	      &points[i].x[1],
+	      &points[i].x[2],
+	      &points[i].nx[0],
+	      &points[i].nx[1],
+	      &points[i].nx[2],
+	      &points[i].k[0],
+	      &points[i].k[1]);
+       points[i].index-=1000;
+
+       //fscanf(fin,"%d",&points[i].index);
+       //points[i].index-=1000;
+       
+       //for (int ia=0;ia<=2;ia++)
+	 //  fscanf(fin,"%f",&points[i].x[ia]);
+       //for (ia=0;ia<=2;ia++)
+	 //  fscanf(fin,"%f",&points[i].nx[ia]);
+       //for (ia=0;ia<=1;ia++)
+	 //  fscanf(fin,"%f",&points[i].k[ia]);
+       // fscanf(fin,"\n");
+       gzgets(fin,line,200);
+       sscanf(line,"%f %f %f %d %d %f",
+	      &pointDetails[i].dx[0],
+	      &pointDetails[i].dx[1],
+	      &pointDetails[i].dx[2],
+	      &pointDetails[i].index[0],
+	      &pointDetails[i].index[1],
+	      &pointDetails[i].temperature);
+	      
+       //for (ia=0;ia<=2;ia++)
+       //	   fscanf(fin," %f",&pointDetails[i].dx[ia]);
+       //     for (ia=0;ia<=1;ia++)
+       //   fscanf(fin," %d",&pointDetails[i].index[ia]);
+       //fscanf(fin,"%f\n ",&pointDetails[i].temperature);
+       
+       gzgets(fin,line,400);
+       int num;
+       sscanf(line,"%d ",&num);
+
+       int po=0;
+       po=stringskipspace(line,po);
+       po=stringskipnumber(line,po);
+       for(int j=0;j<num;j++)
+	   {
+	     int temp;
+	     po=stringskipspace(line,po);
+	     sscanf(&line[po],"%d",&temp);
+	     po=stringskipnumber(line,po);
+	     pointDetails[i].neighbours->Add(temp);
+	   }
+     }
+ delete [] line;
+ 
+ return 1;
+}
+// ************************************************
+void PXSolidNodes::Copy(PXSolidNodes* other,int check,int offset)
+{
+  if (check)
+      {
+	if (other->getnumnodes()!=numnodes)
+	    {
+	      cleanup();
+	      init(other->numnodes);
+	    }
+      }
+  
+  for (int i=offset;i<other->getnumnodes()+offset;i++)
+      {
+	int j=i-offset;
+	//	fprintf(stderr,"Copying node %d --> %d offset=%d \n",j,i);
+	points[i].index=other->getpoint(j)->index+offset;
+	int ia=0;
+	for (ia=0;ia<=2;ia++)
+	    {
+	      points[i].x[ia] =other->getpoint(j)->x[ia];
+	      points[i].nx[ia]=other->getpoint(j)->nx[ia];
+	      pointDetails[i].dx[ia]=other->getdetails(j)->dx[ia];
+	    }
+	
+	for (ia=0;ia<=1;ia++)
+	    points[i].k[ia]=other->getpoint(j)->k[ia];
+	
+	pointDetails[i].index[0]=other->getindex(j,0);
+	pointDetails[i].index[1]=other->getindex(j,1);
+	pointDetails[i].temperature=other->getdetails(j)->temperature;
+      }
+}
+// ************************************************
+void PXSolidNodes::setfromnodecollection(PXNodeCollection* oldnodes,int scale)
+{
+  if (scale==0)
+      scale=-1;
+  cleanup();
+  init(oldnodes->numnodes);
+  for (int i=0;i<numnodes;i++)
+      {
+	points[i].index=i;
+	int ia=0;
+	for (ia=0;ia<=2;ia++)
+	    {
+	      points[i].x[ia]=oldnodes->x[i].x[ia];
+	      points[i].nx[ia]=sqrt(1.0/3.0);
+	      pointDetails[i].dx[ia]=oldnodes->dx[i].x[ia];
+	    }
+	
+	for (ia=0;ia<=1;ia++)
+	    points[i].k[ia]=oldnodes->k[i].x[ia];
+
+	pointDetails[i].index[1]=oldnodes->pointno[i];
+	if (scale==-1)
+	    {
+	      pointDetails[i].index[0]=oldnodes->stackno[i];
+	    }
+	else
+	    {
+	      pointDetails[i].index[0]=(100*oldnodes->stackno[i]/scale);
+	      if  (pointDetails[i].index[0]!=0 && pointDetails[i].index[0]!=100)
+		  pointDetails[i].index[1]=-1;
+	    }
+
+	pointDetails[i].temperature=0.0;
+      }
+}
+// --------------------------------------------------------------------------
+// Displacement Related 
+// --------------------
+PXNodalDisplacements::PXNodalDisplacements(PXSolidNodes* nodes,int endo,int epi)
+{
+  init(nodes->getnumnodes());
+  endoindex=endo;
+  epiindex=epi;
+  solidNodes=nodes;
+}
+
+PXNodalDisplacements::PXNodalDisplacements(PXNodalDisplacements *other)
+{
+  init(other->getsolidnodes()->getnumnodes());
+  solidNodes=other->getsolidnodes();
+  Copy(other);
+}
+// --------------------------------------------------------------------------
+void PXNodalDisplacements::init(int n)
+{
+  //fprintf(stderr,"Nodal Displacements :: Number of Nodes = %d\n",n);
+  disp=new PX3Vector[n];
+  conf=new float[n];
+  valid=new int[n];
+  
+  for (int i=0;i<n;i++)
+      {
+	valid[i]=0;
+	disp[i].setvector(0.0,0.0,0.0);
+	conf[i]=1.0;
+      }
+}
+// --------------------------------------------------------------------------
+PXNodalDisplacements::~PXNodalDisplacements()
+{
+  cleanup();
+}
+// --------------------------------------------------------------------------
+void PXNodalDisplacements::cleanup()
+{
+  delete [] disp;
+  delete [] conf;
+  delete [] valid;
+}
+// --------------------------------------------------------------------------
+int PXNodalDisplacements::loadDisplacementsSingle(const char* filename,int all)
+{
+  fprintf(stderr,"Reading Displacements from %s \n",filename);
+  fprintf(stderr,"--------------------------------------------\n");
+  
+  PXAbaqusOutputData* outputStructures=new PXAbaqusOutputData(solidNodes->getnumnodes(),1);
+  int ok=outputStructures->loadNodeDetails(filename);
+  if (ok==0)
+      return 0;
+  
+  int count=0;
+  for (int i=0;i<solidNodes->getnumnodes();i++)
+      {
+	if (all==1 || solidNodes->getindex(i,0)==endoindex || solidNodes->getindex(i,0)==epiindex)
+	    {
+	      for (int ia=0;ia<=2;ia++)
+		  disp[i].x[ia]=outputStructures->getdispcomponent(i,ia);
+	      conf[i]=1.0;
+	      valid[i]=1;
+	      count++;
+	    }
+      }
+  fprintf(stderr,"Num Displacements= %d\n",count);
+  delete outputStructures;
+  return count;
+}
+// --------------------------------------------------------------------------
+int PXNodalDisplacements::\
+setfromshapetrackingclassnosearch(PXShapeTrackingClass* shapeTr,int index0)
+{
+  if (!shapeTr->hasdisplacements())
+      return 0;
+
+  int ng=0;
+  for (int i=0;i<solidNodes->getnumnodes();i++)
+      {
+	if (solidNodes->getindex(i,0)==index0)
+	    {
+	      ++ng;
+	      int index=solidNodes->getindex(i,1);
+	      for (int ia=0;ia<=2;ia++)
+		  disp[i].x[ia]=shapeTr->getdisplacement(index)->x[ia];
+	      setconfidence(i,shapeTr->getconfidence(index));
+	      if (i==0)
+		  {
+		    fprintf(stderr,"setfromshns:: disp=(%5.3f %5.3f %5.3f) conf=%5.3f --->",
+			    disp[i].x[0],disp[i].x[1],disp[i].x[2],conf[i]);
+		    PXTriangulatedStackPoint* pt2=shapeTr->getstack(1)->getpoint(shapeTr->getcorrespondence(i));
+		    fprintf(stderr," (%6.2f %6.2f %6.2f)\n",pt2->x[0],pt2->x[1],pt2->x[2]);
+		  }
+	      valid[i]=1;
+	    }
+      }
+  return ng;
+}
+// --------------------------------------------------------------------------
+int PXNodalDisplacements::\
+setfromshapetrackingclass(PXShapeTrackingClass* shapeTr,int index,float tolerance)
+{
+  if (!shapeTr->hasdisplacements() || !shapeTr->hasstack(0))
+      return 0;
+  
+  int ng=0;
+  PXTriangulatedStack* tstack=shapeTr->getstack(0);
+  //  PXIntegerList* searchPoints=new PXIntegerList();
+  for (int i=0;i<solidNodes->getnumnodes();i++)
+      {
+	if (solidNodes->getindex(i,0)==index)
+	    {
+	      ++ng;
+	      float x[3],xp[3];
+	      PXNodeAuxiliary* details=solidNodes->getdetails(i);
+	      int ia=0;
+	      for (ia=0;ia<=2;ia++)
+		  {
+		    x[ia]=solidNodes->getpoint(i)->x[ia]+details->dx[ia];
+		    xp[ia]=x[ia];
+		  }
+	      
+	      if (i==0 || i==200)
+		  fprintf(stderr,"setfromsh : Point 0 (%6.3f %6.3f %6.3f) + (%5.3f %5.3f %5.3f) ="
+			  "(%6.3f %6.3f %6.3f)\n\t\t",
+			  solidNodes->getpoint(i)->x[0],
+			  solidNodes->getpoint(i)->x[1],
+			  solidNodes->getpoint(i)->x[2],
+			  details->dx[0],details->dx[1],details->dx[2],
+			  x[0],x[1],x[2]);
+			  
+			  
+	      int corr=0;
+	      tstack->findnearestpoint(x[0],x[1],x[2],corr,0,tolerance);
+	      
+	      float mindist[3];
+	      int   pt[3];
+	      for (ia=0;ia<=1;ia++)
+		  {
+		    mindist[ia]=10000000.0;
+		    pt[ia]=-1;
+		  }
+	      
+	      mindist[2]=Fdist(x[0],x[1],x[2],xp[0],xp[1],xp[2]);
+	      pt[2]=corr;
+	      
+	      PXIntegerList* nei=tstack->getneighbours(corr);
+	      nei->Rewind();
+	      for (int ic=0;ic<nei->getnumnodes();ic++)
+		  {
+		    int p=nei->getcurrent();
+		    float dist=Fdist(xp[0],xp[1],xp[2],
+				     tstack->getpoint(p)->x[0],
+				     tstack->getpoint(p)->x[1],
+				     tstack->getpoint(p)->x[2]);
+
+		    if (dist<mindist[0])
+			{
+			  mindist[1]=mindist[0];
+			  pt[1]=pt[0];
+			  mindist[0]=dist;
+			  pt[0]=p;
+			}
+		    else
+			{
+			  if (dist<mindist[1])
+			      {
+				mindist[1]=dist;
+				pt[1]=p;
+			      }
+			}
+		    nei->Next();
+		  }
+	      
+	      for (ia=0;ia<=1;ia++)
+		  {
+		    if (pt[ia]==-1)
+			{
+			  pt[ia]=corr;
+			  mindist[ia]=mindist[2];
+			}
+		  }
+	      
+	      
+	      disp[i].setvector(0.0,0.0,0.0);
+	      conf[i]=0.0;
+	      
+	      float sum=0.0;
+	      for (ia=0;ia<=2;ia++)
+		  {
+		    mindist[ia]=1.0/Fmax(mindist[ia],0.01);
+		    sum+=mindist[ia];
+		  }
+	      
+	      for (ia=0;ia<=2;ia++)
+		  {
+		    mindist[ia]/=sum;
+		    conf[i]+=mindist[ia]*shapeTr->getconfidence(pt[ia]);
+		    for (int ib=0;ib<=2;ib++)
+			disp[i].x[ib]+=mindist[ia]*shapeTr->getdisplacement(pt[ia])->x[ib];
+		  }
+	      
+	      if (i==0 || i==200)
+		  {
+		    fprintf(stderr," ---> (%6.3f %6.3f %6.3f) , disp=(%5.3f %5.3f %5.3f) conf=%5.3f \n",
+			    x[0],x[1],x[2],
+			    disp[i].x[0],disp[i].x[1],disp[i].x[2],conf[i]);
+		    fprintf(stderr," pt[0]=%d(%5.2f), pt[1]=%d(%5.2f) pt[2]=%d(%5.2f) \n",
+			    pt[0],mindist[0],pt[1],mindist[1],pt[2],mindist[2]);
+		  }
+	      
+	      /*int np2=tstack->collectNeighbours(corr,0,searchPoints);
+	      
+	      disp[i].setvector(0.0,0.0,0.0);
+	      conf[i]=0.0;
+	      float wgt=1.0/float(np2+1);
+	      searchPoints->Rewind();
+	      for (int j=0;j<np2;j++)
+		  {
+		    int ind=searchPoints->getcurrent();
+		    searchPoints->Next();
+		    float wgt2=wgt;
+		    if (j==0)
+			wgt2*=2.0;
+		    for (int ia=0;ia<=2;ia++)
+			disp[i].x[ia]=wgt2*shapeTr->getdisplacement(ind)->x[ia];
+		    conf[i]+=wgt2*shapeTr->getconfidence(ind);
+		  }
+
+	      if (i==0)
+		  fprintf(stderr," ---> (%6.3f %6.3f %6.3f) , disp=(%5.3f %5.3f %5.3f) conf=%5.3f np2=%d\n",
+			  x[0],x[1],x[2],
+			  disp[i].x[0],disp[i].x[1],disp[i].x[2],conf[i],np2);
+			  */
+	      valid[i]=1;
+	    }
+      }
+  return ng;
+}
+// --------------------------------------------------------------------------
+int PXNodalDisplacements::Save(const char* fname)
+{
+FILE* fout=fopen(fname,"w");
+ if (fout)
+     {
+       int st=Save(fout);
+       fclose(fout);
+       return st;
+     }
+ return 0;
+}
+// --------------------------------------------------------------------------
+int PXNodalDisplacements::Load(const char* fname)
+{
+ gzFile fin=gzsuffixopen(fname,"r");
+ if (fin)
+     {
+       int st=Load(fin);
+       gzclose(fin);
+       return st;
+     }
+ return 0;
+}
+// --------------------------------------------------------------------------
+int PXNodalDisplacements::Save(FILE* fout)
+{
+  fprintf(fout,"#PXNodalDisplacements File\n");
+  fprintf(fout,"#Numnodes\n%d\n",solidNodes->getnumnodes());
+  fprintf(fout,"#Endoindex\n%d\n#Epiindex\n%d\n",endoindex,epiindex);
+  int numvalid=0;
+  for (int ia=0;ia<solidNodes->getnumnodes();ia++)
+      if (valid[ia])
+	  numvalid++;
+  
+  fprintf(fout,"#Numdisplacements\n%d\n",numvalid);
+  for (int i=0;i<solidNodes->getnumnodes();i++)
+      {
+	if (valid[i])
+	    fprintf(fout,"%6d %6.3f %6.3f %6.3f  %5.3f \n",
+		    i,disp[i].x[0],disp[i].x[1],disp[i].x[2],conf[i]);
+      }
+  return 1;
+}
+// --------------------------------------------------------------------------
+int PXNodalDisplacements::Load(gzFile fin)
+{
+  char* line=new char[200];
+  
+
+  gzgets(fin,line,200);
+  if (gzfindstringinstring(line,"#PXNodalDisplacements File")==0)
+      {
+	delete [] line;
+	return 0;
+      }
+  gzgets(fin,line,200);
+  int num=0;
+  gzgets(fin,line,200);
+  sscanf(line,"%d",&num);
+  if (num!=solidNodes->getnumnodes())
+      {
+	fprintf(stderr,"Wrong number of nodes %d vs %d line=%s\n\n\n\n",num,solidNodes->getnumnodes(),line);
+	delete [] line;
+	return 0;
+      }
+  gzgets(fin,line,200);  gzgets(fin,line,200);
+  sscanf(line,"%d",&endoindex);
+  gzgets(fin,line,200);  gzgets(fin,line,200);
+  sscanf(line,"%d\n",&epiindex);
+  gzgets(fin,line,200);  gzgets(fin,line,200);
+  int numvalid=0;
+  sscanf(line,"%d\n",&numvalid);
+  int index;
+
+
+  for (int ia=0;ia<num;ia++)
+      {
+	valid[ia]=0; disp[ia].setvector(0.0,0.0,0.0); conf[ia]=1.0;
+      }
+
+  for (int i=0;i<numvalid;i++)
+      {
+	int tmp=0;
+	gzgets(fin,line,200);
+	sscanf(line,"%d ",&index);
+	valid[index]=1;
+	sscanf(line,"%d %f %f %f  %f",&tmp,
+	       &disp[index].x[0],&disp[index].x[1],&disp[index].x[2],&conf[index]);
+      }
+  delete [] line;
+  return 1;
+}
+// --------------------------------------------------------------------------
+int PXNodalDisplacements::\
+loadPengChengDisplacementsSingle(const char* endofile,const char* epifile,float tolerance)
+{
+  FILE *dispfile[2];
+  const char* filename[2];
+  
+  filename[0]=endofile;
+  filename[1]=epifile;
+  
+  fprintf(stderr,"Reading Peng-Cheng Displacements from %s,%s\n",filename[0],filename[1]);
+  
+  for (int ii=0;ii<=1;ii++)
+      dispfile[ii]=fopen(filename[ii],"r");
+  
+  if (dispfile[0]==NULL || dispfile[1]==NULL)
+      {
+	for (int i=0;i<=1;i++)
+	    {
+	      if (dispfile[i]!=NULL)
+		  fclose(dispfile[i]);
+	    }
+	return 0;
+      }
+  
+  char line[200];
+  float *pointsx[2],*pointsy[2],*pointsz[2];
+  int numdisppoints[2],sur;
+  
+  // Count Lines in file
+  // -------------------
+  for (sur=0;sur<=1;sur++)
+      {
+	numdisppoints[sur]=0;
+	
+	while ( fgets(line,100,dispfile[sur])!=NULL ) 
+	    numdisppoints[sur]++;
+	fclose(dispfile[sur]);
+	dispfile[sur]=fopen(filename[sur],"r");
+	fprintf(stderr,"Number of points in %s = %d\n",filename[sur],numdisppoints[sur]);
+      }
+  
+  
+  
+  // Allocate Data and Read Rest of Files 
+  // ------------------------------------
+  for (sur=0;sur<=1;sur++)
+      {
+	pointsx[sur]=new float[numdisppoints[sur]*2];
+	pointsy[sur]=new float[numdisppoints[sur]*2];
+	pointsz[sur]=new float[numdisppoints[sur]*2];
+	for (int i=0;i<numdisppoints[sur];i++)
+	    {
+	      for (int j=0;j<2;j++)
+		  {
+		    int index=i*2+j;
+		    fscanf(dispfile[sur],"%f %f %f ",
+			   &pointsx[sur][index],
+			   &pointsy[sur][index],
+			   &pointsz[sur][index]);
+		  }
+	    }
+	
+	fprintf(stderr,"\tStack %d, Points=%d\n",sur+1,numdisppoints[sur]);
+	fclose(dispfile[sur]);
+      } 
+  
+  // Create Structures for Solid to find and store displacements
+  // -----------------------------------------------------------
+  int numd[2],numtest=0;
+  numd[0]=0,numd[1]=0;
+  int numdisplacements=0;
+  tolerance*=tolerance;
+  
+  for (int i=0;i<solidNodes->getnumnodes();i++)
+      {
+	int sur=0;
+	if (solidNodes->getindex(i,0)==endoindex || solidNodes->getindex(i,0)==epiindex)
+	    {
+	      numtest++;
+	      if (solidNodes->getindex(i,0)==epiindex)
+		  sur=1;
+	      int pt=0,found=0;
+	      int bestpt=0;
+	      float mindist=10000.0;
+	      while(pt<numdisppoints[sur] && found==0)
+		  {
+		    int po_index=pt*2;
+		    float x=pointsx[sur][po_index];
+		    float y=pointsy[sur][po_index];
+		    float z=pointsz[sur][po_index];
+		    float dist=Fsqdist(x,y,z,
+				       solidNodes->getpoint(i)->x[0]+solidNodes->getdetails(i)->dx[0],
+				       solidNodes->getpoint(i)->x[1]+solidNodes->getdetails(i)->dx[1],
+				       solidNodes->getpoint(i)->x[2]+solidNodes->getdetails(i)->dx[2]);
+		    if (dist<mindist)
+			{
+			  mindist=dist;
+			  bestpt=pt;
+			}
+		    
+		    if (mindist<tolerance)
+			found=1;
+		    else
+			pt++;
+		    
+		  }
+	      int po_index=bestpt*2;			
+	      numdisplacements++;
+	      numd[sur]++;
+	      disp[i].setvector(pointsx[sur][po_index+1]-pointsx[sur][po_index],
+				pointsy[sur][po_index+1]-pointsy[sur][po_index],
+				pointsz[sur][po_index+1]-pointsz[sur][po_index]);
+	      conf[i]=1.0;
+	      valid[i]=1;
+	      
+	      
+	      if (i==10 || i==200)
+		  {
+		    fprintf(stderr,"Original Node %d \n (%6.3f %6.3f %6.3f ) ",i,
+			    solidNodes->getpoint(i)->x[0],
+			    solidNodes->getpoint(i)->x[1],
+			    solidNodes->getpoint(i)->x[2]);
+		    fprintf(stderr," +dx (%6.3f %6.3f %6.3f ) =",
+			    solidNodes->getdetails(i)->dx[0],
+			    solidNodes->getdetails(i)->dx[1],
+			    solidNodes->getdetails(i)->dx[2]);
+		    fprintf(stderr," (%6.3f %6.3f %6.3f ) \n",
+			    solidNodes->getdetails(i)->dx[0]+solidNodes->getpoint(i)->x[0],
+			    solidNodes->getdetails(i)->dx[1]+solidNodes->getpoint(i)->x[1],
+			    solidNodes->getdetails(i)->dx[2]+solidNodes->getpoint(i)->x[2]);
+		    fprintf(stderr,"Closest Point %d \n (%6.3f %6.3f %6.3f ) -->",bestpt,
+			    pointsx[sur][po_index],
+			    pointsy[sur][po_index],
+			    pointsz[sur][po_index]);
+		    fprintf(stderr,"(%d) (%6.3f %6.3f %6.3f ) \n",bestpt,
+			    pointsx[sur][po_index+1],
+			    pointsy[sur][po_index+1],
+			    pointsz[sur][po_index+1]);
+		    fprintf(stderr,"Displacement = (%5.3f %5.3f %5.3f)\n",
+			    disp[i].x[0], disp[i].x[1], disp[i].x[2]);
+		  }
+	    }
+      }
+  
+  fprintf(stderr,"\tDone with surfaces, found %d,%d displacements (%d)\n",numd[0],numd[1],numtest);
+  
+  delete [] pointsx[0]; delete [] pointsx[1]; delete [] pointsy[0];
+  delete [] pointsy[1]; delete [] pointsz[0]; delete [] pointsz[1];
+  return numdisplacements;
+}
+// --------------------------------------------------------------------------
+void PXNodalDisplacements::Copy(PXNodalDisplacements *other)
+{
+  if (other->getsolidnodes()->getnumnodes() !=solidNodes->getnumnodes())
+      {
+	cleanup();
+	init(other->getsolidnodes()->getnumnodes());
+      }
+  solidNodes=other->getsolidnodes(); 
+  endoindex=other->getendoindex(); epiindex=other->getepiindex();
+  
+  for (int i=0;i<solidNodes->getnumnodes();i++)
+      {
+	valid[i]=other->getvalid(i);
+	disp[i].copy(other->getdisplacement(i));
+	conf[i]=(other->getconfidence(i));
+      }
+}
+// --------------------------------------------------------------------------
+PX3Vector* PXNodalDisplacements::getdisplacement(int i)
+{
+  i=Irange(i,0,solidNodes->getnumnodes());
+  return &disp[i];
+}
+
+float PXNodalDisplacements::getdispcomponent(int i,int j)
+{
+  i=Irange(i,0,solidNodes->getnumnodes());
+  j=Irange(j,0,2);
+  return disp[i].x[j];
+}
+
+float PXNodalDisplacements::getconfidence(int i)
+{
+  i=Irange(i,0,solidNodes->getnumnodes());
+  return conf[i];
+}
+
+void PXNodalDisplacements::setdisplacement(int i,float x,float y,float z)
+{
+  i=Irange(i,0,solidNodes->getnumnodes());
+  disp[i].setvector(x,y,z);
+  valid[i]=1;
+}
+
+void PXNodalDisplacements::setdispcomponent(int i,int j,float x)
+{
+  i=Irange(i,0,solidNodes->getnumnodes());
+  j=Irange(j,0,2);
+  disp[i].x[j]=x;
+}
+
+void PXNodalDisplacements::setdisplacement(int i,PX3Vector* vec)
+{
+  i=Irange(i,0,solidNodes->getnumnodes());
+  disp[i].copy(vec);
+  valid[i]=1;
+}
+ 
+void PXNodalDisplacements::setconfidence(int i,float cnf)
+{
+  i=Irange(i,0,solidNodes->getnumnodes());
+  conf[i]=cnf;
+}
+
+int PXNodalDisplacements::getvalid(int i)
+{
+  i=Irange(i,0,solidNodes->getnumnodes());
+  return valid[i];
+}
+
+int PXNodalDisplacements::getendoindex()
+{
+  return endoindex;
+}
+
+int PXNodalDisplacements::getepiindex()
+{
+  return epiindex;
+}
+
+PXSolidNodes* PXNodalDisplacements::getsolidnodes()
+{
+  return solidNodes;
+}
+// --------------------------------------------------------------------------
+/*
+ Definition of PXAbaqusMaterialModel
+ */
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+PXAbaqusMaterialModel::PXAbaqusMaterialModel(int mode)
+{
+  init(mode);
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+PXAbaqusMaterialModel::PXAbaqusMaterialModel(PXAbaqusMaterialModel* old)
+{
+  init(old->getmodeltype());
+  Copy(old);
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+PXAbaqusMaterialModel::~PXAbaqusMaterialModel()
+{
+  cleanup();
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+void PXAbaqusMaterialModel::init(int mode)
+{
+ modeltype=Irange(mode,0,2);
+ switch(modeltype)
+     {
+     case 0:
+       numparameters=2; break;
+     case 1:
+       numparameters=9; break;
+     case 2:
+       numparameters=2; break;
+     }
+ active=0;
+ parameter=new float[numparameters];
+ setgeometry(1);
+ setheatcoeff();
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+void PXAbaqusMaterialModel::cleanup()
+{
+  numparameters=0;
+  delete [] parameter;
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+void PXAbaqusMaterialModel::setgeometry(int nl)
+{
+  nlgeom=nl>0;
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+int PXAbaqusMaterialModel::getgeometry()
+{
+  return nlgeom;
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+void PXAbaqusMaterialModel::setactive(int av)
+{
+  active=av>0;
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+int PXAbaqusMaterialModel::getactive()
+{
+  return active;
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_ 
+void PXAbaqusMaterialModel::setHyperelastic(float incompressibility)
+{
+  if (numparameters!=2)
+      {
+	cleanup();
+	init(2);
+      }
+  else
+      modeltype=2;
+  
+  parameter[0]=1.0;
+  parameter[1]=incompressibility;
+  setgeometry(1);
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+void PXAbaqusMaterialModel::setElastic(float Modulus,float Poisson)
+{
+  if (numparameters!=2)
+      {
+	cleanup();
+	init(0);
+      }
+  else 
+      modeltype=0;
+  parameter[0]=Modulus;
+  parameter[1]=Poisson;
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+void PXAbaqusMaterialModel::setTransverseIsotropy(float Ep,float vp,float Et,float vtp)
+{
+  if (numparameters!=9)
+      {
+	cleanup();
+	init(1);
+      }
+  else 
+      modeltype=1;
+  
+  parameter[0]=Ep;
+  parameter[1]=Ep;
+  parameter[2]=Et;
+  parameter[3]=vp;
+  parameter[4]=vtp;
+  parameter[5]=vtp*(Ep/Et);;
+  parameter[6]=Ep/(2.0*(1+vp));
+  parameter[7]=Et/(2.0*(1+vp));
+  parameter[8]=Et/(2.0*(1+vp));
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+int PXAbaqusMaterialModel::getmodeltype()
+{
+  return modeltype;
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+float PXAbaqusMaterialModel::getparameter(int i)
+{
+  return parameter[Irange(i,0,numparameters-1)];
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+void PXAbaqusMaterialModel::setheatcoeff(float a,float b,float c)
+{
+  heatcoeff[0]=a;
+  heatcoeff[1]=b;
+  heatcoeff[2]=c;
+
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+float PXAbaqusMaterialModel::getheatcoeff(int i)
+{
+  return heatcoeff[Irange(i,0,2)];
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+void PXAbaqusMaterialModel::Copy(PXAbaqusMaterialModel* other)
+{
+  if (other->getmodeltype() !=modeltype)
+      {
+	cleanup();
+	init(other->getmodeltype());
+      }
+  
+  setgeometry(other->getgeometry());
+  for (int i=0;i<numparameters;i++)
+      parameter[i]=other->getparameter(i);
+  for (int j=0;j<=2;j++)
+      heatcoeff[j]=other->getheatcoeff(j);
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+void PXAbaqusMaterialModel::setfrommaterialmodel(PXMaterialModel* old)
+{
+  cleanup();
+  init(old->modeltype);
+  setgeometry(old->nlgeom);
+  for (int i=0;i<numparameters;i++)
+      parameter[i]=old->parameter[i];
+  setheatcoeff();
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+void PXAbaqusMaterialModel::SaveAbaqus(FILE* fout,const char* name)
+{
+  switch(modeltype)
+      {
+      case 0:
+	fprintf(fout,"*MATERIAL,NAME=%s\n*ELASTIC\n",name);
+	fprintf(fout,"%8.2f,%8.2f\n",parameter[0],parameter[1]);
+	break;
+      case 1:
+	fprintf(fout,"*MATERIAL,NAME=TISSUE\n*ELASTIC,TYPE=ENGINEERING CONSTANTS\n");
+	{
+	  for (int i=0;i<=8;i++)
+	      {
+		fprintf(fout,"%8.2f",parameter[i]);
+		if (i<7)
+		    fprintf(fout,",");
+		else
+		    fprintf(fout,"\n");
+	      }
+	}
+	break;
+      case 2:
+	fprintf(fout,"*MATERIAL,NAME=TISSUE\n*HYPERELASTIC,N=1,OGDEN\n");
+	fprintf(fout,"%7.3f,2,%7.3f\n",parameter[0],parameter[1]);
+	break;
+      }
+  if (active)
+      {
+	//fprintf(fout,"*EXPANSION,TYPE=ORTHO\n%7.3f,%7.3f,%7.3f\n",heatcoeff[0],heatcoeff[1],heatcoeff[2]);
+	fprintf(fout,"*EXPANSION,TYPE=ANISO,USER,ZERO=0.0\n");
+      }
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+int PXAbaqusMaterialModel::Save(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout)
+      {
+	int st=Save(fout);
+	fclose(fout);
+	return st;
+      }
+  return 0;
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+int PXAbaqusMaterialModel::Load(const char* fname)
+{
+ gzFile fin=gzsuffixopen(fname,"r");
+ if (fin)
+     {
+       int st=Load(fin);
+       gzclose(fin);
+       return st;
+     }
+ return 0;
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+int PXAbaqusMaterialModel::Save(FILE* fout)
+{
+  fprintf(fout,"#AbaqusMaterialModel\n");
+  fprintf(fout,"%d\n",modeltype);
+  fprintf(fout,"%d\n",nlgeom);
+  fprintf(fout,"%d\n",active);
+  for (int i=0;i<numparameters;i++)
+      fprintf(fout,"%7.3f ",parameter[i]);
+  fprintf(fout,"\n");
+  active=active>0;
+  if (active==1)
+      {
+	for (int i=0;i<3;i++)
+	    fprintf(fout,"%7.3f ",heatcoeff[i]);
+	fprintf(fout,"\n");
+      }
+  return 1;
+}
+// _-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-__-_-_
+int PXAbaqusMaterialModel::Load(gzFile fin)
+{
+  char* line=new char[400];
+  gzgets(fin,line,200);
+  if (gzfindstringinstring(line,"#AbaqusMaterialModel")==0)
+      {
+	delete [] line;
+	return 0;
+      }
+  int temp;
+  gzgets(fin,line,200);
+  sscanf(line,"%d",&temp);
+  cleanup();
+  init(temp);
+  gzgets(fin,line,200);
+  sscanf(line,"%d",&nlgeom);
+  gzgets(fin,line,200);
+  sscanf(line,"%d",&active);
+  gzgets(fin,line,400);
+  int po=0;
+  
+  for (int i=0;i<numparameters;i++)
+      {
+	po=stringskipspace(line,po);
+	sscanf(&line[po],"%f ",&parameter[i]);
+	po=stringskipnumber(line,po);
+      }
+  if (active)
+      {
+	gzgets(fin,line,400);
+	po=0;
+	for (int i=0;i<3;i++)
+	    {
+	      po=stringskipspace(line,po);
+	      sscanf(&line[po],"%f",&heatcoeff[i]);
+	      po=stringskipnumber(line,po);
+	    }
+      }
+
+  delete [] line;
+  return 1;
+}
+// _+_-__+_-__+_-__+_-__+_-__+_-__+_-__+_-__+_-__+_-__+_-__+_-__+_-__+_-_
+/*
+ Definition of PXAbaqusOutputData
+
+ */
+// ----------------------------------------
+PXAbaqusOutputData::PXAbaqusOutputData(int numn,int numel)
+{
+  init(numn,numel);
+}
+// ----------------------------------------
+PXAbaqusOutputData::PXAbaqusOutputData(PXAbaqusOutputData* other)
+{
+  init(other->getnumnodes(),other->getnumelements());
+  Copy(other);
+}
+// ----------------------------------------
+PXAbaqusOutputData::~PXAbaqusOutputData()
+{
+  cleanup();
+}
+// ----------------------------------------
+void PXAbaqusOutputData::init(int numno,int numel)
+{
+  numnodes=numno;
+  numelements=numel;
+
+  for (int ia=0;ia<=11;ia++)
+      {
+	strain[ia]=new float[numelements];
+	for (int i=0;i<numelements;i++)
+	    strain[ia][i]=0.0;
+      }
+  
+  elementVolumes=new float[numelements];
+  elementCentroids=new PX3Vector[numelements];
+  nodalDisplacements=new PX3Vector[numnodes];
+  radial=new PX3Vector[numnodes];
+  circum=new PX3Vector[numnodes];
+  for (int i=0;i<numnodes;i++)
+      {
+	radial[i].setvector(1.0,0.0,0.0);
+	circum[i].setvector(0.0,1.0,0.0);
+      }
+
+  numpies=1; 
+  numsectors=1; 
+  numslices=1;
+  numtransmural=1;
+  junctionpoint.x[0]=0.0; 
+  junctionpoint.x[1]=0.0; 
+  junctionpoint.x[2]=0.0;
+  pieindex=new int[numelements];
+  {
+    for (int i=0;i<numelements;i++)
+	pieindex[i]=0;
+  }
+}
+// ----------------------------------------
+void PXAbaqusOutputData::cleanup()
+{
+ for (int ia=0;ia<=11;ia++)
+     delete [] strain[ia];
+ 
+ delete [] elementVolumes;
+ delete [] elementCentroids;
+ delete [] nodalDisplacements;
+ delete [] pieindex;
+ delete [] radial;
+ delete [] circum;
+}
+// ----------------------------------------
+float PXAbaqusOutputData::getvolume(int el)
+{
+  el=Irange(el,0,numelements-1);
+  return elementVolumes[el];
+}
+// ----------------------------------------
+float PXAbaqusOutputData::getstraincomponent(int el,int stra)
+{
+  el=Irange(el,0,numelements-1);
+  stra=Irange(stra,0,11);
+  return strain[stra][el];
+}
+// ----------------------------------------
+void PXAbaqusOutputData::setstraincomponent(int el,int stra,float v)
+{
+  el=Irange(el,0,numelements-1);
+  stra=Irange(stra,0,11);
+  strain[stra][el]=v;
+}
+// ----------------------------------------
+PX3Vector* PXAbaqusOutputData::getdisplacement(int nd)
+{
+  nd=Irange(nd,0,numnodes-1);
+  return &nodalDisplacements[nd];
+}
+// ----------------------------------------
+float PXAbaqusOutputData::getdispcomponent(int nd,int comp)
+{
+ nd=Irange(nd,0,numnodes-1);
+ comp=Irange(comp,0,2);
+ return nodalDisplacements[nd].x[comp];
+}
+// ----------------------------------------
+PX3Vector* PXAbaqusOutputData::getcentroid(int el)
+{
+ el=Irange(el,0,numelements-1);
+ return &elementCentroids[el];
+}
+// ----------------------------------------
+PX3Vector* PXAbaqusOutputData::getradial(int el)
+{
+ el=Irange(el,0,numelements-1);
+ return &radial[el];
+
+}
+// ----------------------------------------
+
+PX3Vector* PXAbaqusOutputData::getcircumeferential(int el)
+{
+ el=Irange(el,0,numelements-1);
+ return &circum[el];
+}
+// ----------------------------------------
+int PXAbaqusOutputData::getpieindex(int el)
+{
+ el=Irange(el,0,numelements-1);
+ return pieindex[el];
+}
+// ----------------------------------------
+int PXAbaqusOutputData::getnumpies()
+{
+ return numpies;
+}
+// ----------------------------------------
+
+int PXAbaqusOutputData::getnumsectors()
+{
+ return numsectors;
+}
+// ----------------------------------------
+
+int PXAbaqusOutputData::getnumslices()
+{
+ return numslices;
+}
+// ----------------------------------------
+int PXAbaqusOutputData::getnumtransmural()
+{
+ return numtransmural;
+}
+// ----------------------------------------
+PX3Vector* PXAbaqusOutputData::getjunctionpoint()
+{
+ return &junctionpoint;
+}
+// ----------------------------------------
+void PXAbaqusOutputData::converttoprincipal()
+{
+
+  double** a1    = dmatrix(0,2, 0,2);
+  double*  d1    = dvector(0,2);
+  double** v1    = dmatrix(0,2, 0,2);
+  int nrot=0;
+
+  
+
+  
+  for (int ia=0;ia<numelements;ia++)
+      {
+	a1[1][1] = strain[0][ia]; a1[1][2] = strain[3][ia]; a1[1][3] = strain[4][ia]; 
+	a1[2][1] = strain[3][ia]; a1[2][2] = strain[1][ia]; a1[2][3] = strain[5][ia]; 
+	a1[3][3] = strain[4][ia]; a1[3][2] = strain[5][ia]; a1[3][3] = strain[2][ia];
+	/*get_eigenvalues_vectors(a1, 3, d1, v1, &nrot);
+	  sort_eigenvalues_vectors(d1, v1, 3);*/
+	vtkMath_Jacobi(a1,d1,v1);
+	strain[0][ia]=d1[0];
+	strain[1][ia]=d1[1];
+	strain[2][ia]=d1[2];
+	strain[3][ia]=0.0;
+	strain[4][ia]=0.0;
+	strain[5][ia]=0.0;
+      }
+  free_dmatrix(v1,0,2,0,2);  
+  free_dmatrix(a1,0,2,0,2);
+  free_dvector(d1,0,2);    
+
+}
+// ----------------------------------------
+int PXAbaqusOutputData::subdivideinpies(float junctionx,float junctiony,float junctionz,
+					int numsl,int numse,int anticlockwise,int nump)
+{
+  if (numslices==-1)
+      numslices=1;
+  
+  anticlockwise=anticlockwise>0;
+  junctionpoint.setvector(junctionx,junctiony,junctionz);
+  
+  numsectors=Irange(numse,1,32);
+  numslices=Irange(numsl,1,32);
+
+  if (nump<numsectors*numslices)
+      numpies=numsectors*numslices;
+  else
+      numpies=nump;
+  
+  fprintf(stderr,"Subviding numslices=%d, numsectors=%d numpies=%d\n",numslices,numsectors,numpies);
+  
+  PX3Vector ce;
+  float minz=10000.0,maxz=-10000.0,vol=0.0;
+  for (int i=0;i<numelements;i++)
+      {
+	maxz=Fmax(maxz,elementCentroids[i].x[2]);
+	minz=Fmin(minz,elementCentroids[i].x[2]);
+	for (int ia=0;ia<=2;ia++)
+	    ce.x[ia]+=elementCentroids[i].x[ia]*elementVolumes[i];
+	vol+=elementVolumes[i];
+      }
+  for (int ia=0;ia<=2;ia++)
+      ce.x[ia]/=vol;
+ 
+
+  /*fprintf(stderr,"ElementCentroids = %5.2f %5.2f %5.2f Vol=%5.2f\n",
+    ce.x[0],ce.x[1],ce.x[2],vol);*/
+  
+  float dv=0.5*pow(double(vol)/double(numelements),double(1.0/3.0));
+  minz-=dv;
+  maxz+=dv;
+  
+  junctionx-=ce.x[0]; junctiony-=ce.x[1]; junctionz-=ce.x[2];
+  
+  float phase_ref=atan2(junctiony,junctionx)*180/M_PI;
+  fprintf(stderr,"phase_ref=%6.3f (cx=%6.2f,cy=%5.2f)\n",phase_ref,ce.x[0],ce.x[1]);
+
+  //float angleint=360.0/float(numsectors);
+  
+  float dz=1.0/float(numslices);
+  float zr=maxz-minz;
+  
+  for (int i=0;i<numelements;i++)
+      {
+	// Slice no
+	float frac=Frange((elementCentroids[i].x[2]-minz)/(zr),0,0.99);
+	
+	int sliceno=int(frac/dz);
+	
+	// Sector no
+	float cx=elementCentroids[i].x[0]-ce.x[0];
+	float cy=elementCentroids[i].x[1]-ce.x[1];
+	float phase=atan2(cy,cx)*180/M_PI;
+
+	
+	/*float dphase=Fcyclic(phase-phase_ref,360.0);
+	
+	int sectorno=int(dphase/angleint);
+	if (anticlockwise==0)
+	    sectorno=(numsectors-1)-sectorno; // i.e. if 8 sectors 0->7 7->0 etc */
+	int sectorno=getsectorno(phase,phase_ref,numsectors,anticlockwise);
+	pieindex[i]=sectorno+sliceno*numsectors;
+	pieindex[i]=Irange(pieindex[i],0,numslices*numsectors-1);
+	if (pieindex[i]>numsectors*numslices)
+	    {
+	      fprintf(stderr,"centroid = %5.1f %5.1f %5.1f\n",elementCentroids[i].x[0],
+		      elementCentroids[i].x[1],elementCentroids[i].x[2]);
+	      fprintf(stderr,"junction = %5.1f %5.1f %5.1f\n",junctionx,junctiony,0.0);
+	      //fprintf(stderr,"phase=%5.1f phase_ref=%5.1f dphase=%5.1f \n",phase,phase_ref,dphase);
+	      fprintf(stderr,"minz=%5.1f zr=%5.1f dz=%5.1f ",minz,zr,dz);		 
+	      fprintf(stderr,"sector =%d sliceno=%d, coords[i]=%d\n",sectorno,sliceno,pieindex[i]);
+	    }
+      }
+  return 1;
+}
+// ----------------------------------------
+int PXAbaqusOutputData::averagestrains(PXAbaqusOutputData* ref)
+{
+  //fprintf(stderr,"In average strains numpies=%d\n",numpies);
+  /*{
+    for (int i=0;i<numelements;i++)
+	fprintf(stderr,"%d ",pieindex[i]);
+    fprintf(stderr,"\n");
+  }*/
+
+  float *ave=new float[numpies+1];
+  float *vol0=new float[numpies+1];
+
+  for (int index=0;index<=5;index++)
+      {
+	//fprintf(stderr,"Index =%d\n",index);
+	for (int j=0;j<numpies;j++)
+	  {
+	    ave[j]=0.0;
+	    vol0[j]=0.0;
+	  }
+	
+	int i;
+	for (i=0;i<numelements;i++)
+	  {
+	    int p=Irange(pieindex[i],0,numpies-1);
+	    vol0[p]+=ref->getvolume(i);
+	    //vol[p]+=elementVolumes[i];
+	    ave[p]+=strain[index][i]*ref->getvolume(i);//elementVolumes[i];
+	  }
+	for (i=0;i<numpies;i++)
+	  {
+	    if (vol0[i]<0.001)
+	      ave[i]=0.0;
+	    else
+	      ave[i]/=vol0[i];
+	  }
+	
+	for (i=0;i<numelements;i++)
+	  {
+	    strain[index+6][i]=ave[Irange(pieindex[i],0,numpies-1)];
+	  }
+      }
+  
+  delete [] ave;
+  delete [] vol0;
+  return 1;
+}
+
+// ----------------------------------------
+int PXAbaqusOutputData::LoadOld(const char* fnamestem,int rotate)
+{
+ char dispname[200],elname[200],strainname[200];
+ int nd=numnodes;
+ int numel=numelements;
+
+ sprintf(dispname,"%s.disp",fnamestem);
+ sprintf(elname,"%s.element",fnamestem);
+ sprintf(strainname,"%s.strain",fnamestem);
+
+ FILE* fin;
+ 
+ //fprintf(stderr,"Filenames = `%s' , `%s' , `%s', nel=%d, nd=%d\n",dispname,elname,strainname,numel,nd);
+
+ fin=fopen(dispname,"r");
+ if(fin!=NULL)
+     {
+       int temp;
+       for (int ia=0;ia<nd;ia++)
+	   {
+	     fscanf(fin,"%d %f %f %f\n",&temp,
+		    &nodalDisplacements[ia].x[0],
+		    &nodalDisplacements[ia].x[1],
+		    &nodalDisplacements[ia].x[2]);
+	   }
+       fclose(fin);
+     }
+ else
+     {
+       for (int ia=0;ia<nd;ia++)
+	   {
+	     for (int ib=0;ib<=2;ib++)
+		 nodalDisplacements[ia].x[ib]=0.0;
+	   }
+     }
+ 
+ fin=fopen(elname,"r");
+ if (fin!=NULL)
+     {
+       int temp;
+       for (int ia=0;ia<numel;ia++)
+	 {
+	   fscanf(fin,"%d %f %f %f %f %f %f %f %f %f %f\n",&temp,
+		  &elementCentroids[ia].x[0],
+		  &elementCentroids[ia].x[1],
+		  &elementCentroids[ia].x[2],
+		  &elementVolumes[ia],
+		  &circum[ia].x[0],&circum[ia].x[1],&circum[ia].x[2],
+		  &radial[ia].x[0],&radial[ia].x[1],&radial[ia].x[2]);
+	   if (elementVolumes[ia]<0.01)
+	     elementVolumes[ia]=0.01;
+	 }
+       fclose(fin);
+     }
+ else
+     {
+       for (int ia=0;ia<numel;ia++)
+	   {
+	     for (int ib=0;ib<=2;ib++)
+		 elementCentroids[ia].x[ib]=0.0;
+	     elementVolumes[ia]=0.01;
+	   }
+     }
+ 
+ fin=fopen(strainname,"r");
+ if (fin!=NULL)
+     {
+       int temp;
+       for (int ia=0;ia<numel;ia++)
+	   {
+	     fscanf(fin,"%d %f %f %f %f %f %f\n",&temp,
+		    &strain[0][ia],
+		    &strain[1][ia],
+		    &strain[2][ia],
+		    &strain[3][ia],
+		    &strain[4][ia],
+		    &strain[5][ia]);
+	   }
+       fclose(fin);
+     }
+ 
+ if (rotate)
+     rotatestrains();
+ else
+     {
+       for (int ia=0;ia<numel;ia++)
+	   for (int ib=0;ib<=11;ib++)
+	       strain[ib][ia]=0.0;
+     }
+ 
+ return 1;
+}
+// --------------------------------------------------------------------------
+int PXAbaqusOutputData::rotatestrains()
+{
+  fprintf(stderr," (rot)");
+  double** R	 = dmatrix(0, 2, 0, 2);
+  double** Rt	 = dmatrix(0, 2, 0, 2);
+  double** E	 = dmatrix(0, 2, 0, 2);
+  double** E1	 = dmatrix(0, 2, 0, 2);
+  double** E2	 = dmatrix(0, 2, 0, 2);
+  
+  PX3Vector longit;
+  
+  for (int ia=0;ia<numelements;ia++)
+      {
+	E[0][0] = strain[0][ia]; E[0][1] = strain[3][ia]; E[0][2] = strain[4][ia]; 
+	E[1][0] = strain[3][ia]; E[1][1] = strain[1][ia]; E[1][2] = strain[5][ia]; 
+	E[2][2] = strain[4][ia]; E[2][1] = strain[5][ia]; E[2][2] = strain[2][ia];
+	
+	R[0][0] = radial[ia].x[0]; R[0][1] = radial[ia].x[1]; R[0][2] = radial[ia].x[2]; 
+	R[1][0] = circum[ia].x[0]; R[1][1] = circum[ia].x[1]; R[1][2] = circum[ia].x[2]; 	 	 
+
+	longit.copy(&radial[ia]);
+	longit.crosswith(&circum[ia]);
+
+	R[2][0] = longit.x[0]; R[2][1] = longit.x[1]; R[2][2] = longit.x[2];
+	
+	matrix_transpose(R, Rt, 3, 3);
+	matrix_product(E1, R, 3, 3, E, 3, 3);
+	matrix_product(E2, E1, 3, 3, Rt, 3, 3);
+	
+	strain[0][ia] = E2[0][0]; strain[3][ia] = E2[0][1]; strain[4][ia] = E2[0][2];
+	strain[1][ia] = E2[1][1]; strain[5][ia] = E2[1][2]; strain[2][ia] = E2[2][2];
+	
+	for (int ib=0;ib<=5;ib++)
+	    strain[ib+6][ia]=strain[ib][ia];
+	
+	setRadial(ia,1.0,0.0,0.0);
+	setCircum(ia,0.0,1.0,0.0);
+      }
+  free_dmatrix(R,0,2,0,2); free_dmatrix(Rt,0,2,0,2);
+  free_dmatrix(E,0,2,0,2); free_dmatrix(E1,0,2,0,2); free_dmatrix(E2,0,2,0,2);
+  
+  return 1;
+}
+// --------------------------------------------------------------------------
+int PXAbaqusOutputData::getnumelements()
+{
+  return numelements;
+}
+// --------------------------------------------------------------------------
+int PXAbaqusOutputData::getnumnodes()
+{
+ return numnodes;
+}
+// --------------------------------------------------------------------------
+int PXAbaqusOutputData::copypieindex(PXAbaqusOutputData* other)
+{
+ if (numelements!=other->getnumelements())
+     return 0;
+
+ numpies=other->getnumpies();
+ numsectors=other->getnumsectors();
+ numslices=other->getnumslices();
+ numtransmural=other->getnumtransmural();
+ junctionpoint.copy(other->getjunctionpoint());
+
+ for (int i=0;i<numelements;i++)
+     pieindex[i]=Irange(other->getpieindex(i),0,numpies-1);
+ return 1;
+}
+// --------------------------------------------------------------------------
+void PXAbaqusOutputData::setOutputStepInc(int os,int oi)
+{
+ outputStepNo=os; 
+ outputIncNo=oi;
+}
+// ------------------------------------------------------------------------ 
+int PXAbaqusOutputData::getoutputstep()
+{
+ return outputStepNo;
+}
+
+int PXAbaqusOutputData::getoutputinc()
+{
+ return outputIncNo;
+}
+// ------------------------------------------------------------------------ 
+int PXAbaqusOutputData::Save(const char* fname,int nodirections)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+     return 0;
+  
+ if (nodirections)
+     fprintf(fout,"#PXAbaqusOutputDataNoDirections\n");
+ else
+     fprintf(fout,"#PXAbaqusOutputData\n");
+ fprintf(fout,"Numnodes\n%d\n",numnodes);
+ fprintf(fout,"Numelements\n%d\n",numelements);
+ fprintf(fout,"Pie stats\n%d %d %d\n",numpies,numslices,numsectors);
+ fprintf(fout,"Junction Point\n%6.2f %6.2f %6.2f\n",
+	 junctionpoint.x[0],junctionpoint.x[1],junctionpoint.x[2]);
+ fprintf(fout,"Time Points\n%d %d\n",outputStepNo,outputIncNo);
+ fprintf(fout,"Nodes\n");
+
+
+
+ {
+   for (int i=0;i<numnodes;i++)
+       {
+	 fprintf(fout,"%5d %6.3f %6.3f %6.3f\n",i+1000,
+		  nodalDisplacements[i].x[0],nodalDisplacements[i].x[1],nodalDisplacements[i].x[2]);
+       }
+ }
+ // fprintf(stderr,"Done with nodes\n");
+ fprintf(fout,"Elements\n");
+ for (int i=0;i<numelements;i++)
+     {
+       fprintf(fout,"%5d ",i+1000);
+       fprintf(fout,"%10.6f %10.6f %10.6f"
+	       "%10.6f %10.6f %10.6f\n",
+	       strain[0][i],strain[1][i],strain[2][i],strain[3][i],strain[4][i],strain[5][i]);
+       if (nodirections)
+	   {
+	     fprintf(fout," %10.6f %10.6f %10.6f %10.6f %3d\n",
+		     elementVolumes[i],elementCentroids[i].x[0],elementCentroids[i].x[1],
+		     elementCentroids[i].x[2],
+		     Irange(pieindex[i],0,numpies-1));
+	   }
+       else
+	   {
+	     fprintf(fout," %10.6f %10.6f %10.6f %10.6f %5.3f %5.3f %5.3f %5.3f %5.3f %5.3f %3d\n",
+		     elementVolumes[i],
+		     elementCentroids[i].x[0],elementCentroids[i].x[1],elementCentroids[i].x[2],
+		     radial[i].x[0],radial[i].x[1],radial[i].x[2],
+		     circum[i].x[0],circum[i].x[1],circum[i].x[2],pieindex[i]);
+	   }
+     }
+ fclose(fout);
+ return 1;
+}
+// ------------------------------------------------------------------------
+int PXAbaqusOutputData::Load(const char* fname,int rotate,int check,int integrate)
+{
+ gzFile fin=gzsuffixopen(fname,"r");
+ if (!fin)
+     return 0;
+ 
+ char line[200];
+ gzgets(fin,line,200);
+ 
+ int nodirections=1;
+
+ if (gzfindstringinstring(line, "#PXAbaqusOutputDataNoDirections")==0)
+     {
+       if (gzfindstringinstring(line, "#PXAbaqusOutputData")==0)
+	   {
+	     gzclose(fin);
+	     return LoadOld(fname,rotate);
+	   }
+       else
+	   nodirections=0;
+     }
+ 
+ 
+ int np,ne;
+ 
+ gzgets(fin,line,200);  gzgets(fin,line,200);
+ sscanf(line,"%d",&np);
+ gzgets(fin,line,200);  gzgets(fin,line,200);
+ sscanf(line,"%d",&ne);
+
+  if (np!=numnodes || ne!=numelements)
+      {
+	if (check)
+	    {
+	      fprintf(stderr,"Wrong number of nodes (%d vs %d) or elements (%d vs %d)\n",
+		      np,numnodes, ne,numelements);
+	      gzclose(fin);
+	      return(0);
+	    }
+	else
+	    {
+	      cleanup();
+	      init(np,ne);
+	    }
+      }
+ /*else
+   fprintf(stderr,"All OK no new allocations numelements=%d,numnodes=%d\n",
+   numelements,numnodes);*/
+ 
+ gzgets(fin,line,200);  gzgets(fin,line,200);
+ sscanf(line,"%d %d %d",&numpies,&numslices,&numsectors);
+ gzgets(fin,line,200);  gzgets(fin,line,200); 
+ sscanf(line,"%f %f %f",&junctionpoint.x[0],&junctionpoint.x[1],&junctionpoint.x[2]);
+ gzgets(fin,line,200);  gzgets(fin,line,200); 
+ sscanf(line,"%d %d ",&outputStepNo,&outputIncNo);
+ gzgets(fin,line,200);  
+
+ int temp;
+ if (integrate==0)
+     {
+       for (int i=0;i<numnodes;i++)
+	   {
+	     gzgets(fin,line,200);
+	     sscanf(line,"%d %f %f %f",&temp,
+		    &nodalDisplacements[i].x[0],
+		    &nodalDisplacements[i].x[1],
+		    &nodalDisplacements[i].x[2]);
+	   }
+     }
+ else
+     {
+       fprintf(stderr,"Reading and integrating displacements\n");
+       float x,y,z;
+       for (int i=0;i<numnodes;i++)
+	   {
+	     gzgets(fin,line,200);
+	     sscanf(line,"%d %f %f %f",&temp,&x,&y,&z);
+	     nodalDisplacements[i].x[0]+=x;
+	     nodalDisplacements[i].x[1]+=y;
+	     nodalDisplacements[i].x[2]+=z;
+	   }
+       gzclose(fin);
+       return 1;
+     }
+ 
+ gzgets(fin,line,200);
+ // fprintf(stderr,"Separator : `%s'\n",line);
+
+ for (int i=0;i<numelements;i++)
+     {
+       gzgets(fin,line,200);
+       sscanf(line,"%d %f %f %f %f %f %f",&temp,
+	      &strain[0][i],&strain[1][i],&strain[2][i],&strain[3][i],&strain[4][i],&strain[5][i]);
+       if (nodirections)
+	   {
+	     gzgets(fin,line,200);
+	     sscanf(line," %f %f %f %f  %d",
+		    &elementVolumes[i],
+		    &elementCentroids[i].x[0],&elementCentroids[i].x[1],&elementCentroids[i].x[2],
+		    &pieindex[i]);
+	     radial[i].setvector(1.0,0.0,0.0);
+	     circum[i].setvector(0.0,1.0,0.0);
+	   }
+       else
+	   {
+	     gzgets(fin,line,200);
+	     sscanf(line,"%f %f %f %f %f %f %f %f %f %f %d",
+		    &elementVolumes[i],
+		    &elementCentroids[i].x[0],&elementCentroids[i].x[1],&elementCentroids[i].x[2],
+		    &radial[i].x[0],&radial[i].x[1],&radial[i].x[2],
+		    &circum[i].x[0],&circum[i].x[1],&circum[i].x[2],&pieindex[i]);
+	   }
+       /*if (i<15)
+	   fprintf(stderr,"\ni=%d, strains=(%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f)\n"
+		   "vol=%10.5f centroid=(%6.2f %6.2f %6.2f)\n"
+		   "directions (%5.2f %5.2f %5.2f) (%5.2f %5.2f %5.2f) pie=%d)\n",i,
+		   strain[0][i],strain[1][i],strain[2][i],strain[3][i],strain[4][i],strain[5][i],
+		   elementVolumes[i],
+		   elementCentroids[i].x[0],elementCentroids[i].x[1],elementCentroids[i].x[2],
+		   radial[i].x[0],radial[i].x[1],radial[i].x[2],
+		   circum[i].x[0],circum[i].x[1],circum[i].x[2],
+		   pieindex[i]);*/
+     }
+ //fprintf(stderr,"pieindex[5]=%02d ",pieindex[5]);
+ gzclose(fin); 
+ 
+ /*if (rotate)
+   {
+       fprintf(stderr,"Going to rotate strains\n");
+       rotatestrains();
+       }*/
+ 
+ /*if (numpies==1)
+   fprintf(stderr,"Numpies=1\n");*/
+ /* for (i=0;i<numelements;i++)
+    fprintf(stderr,"%d ",pieindex[i]);
+    fprintf(stderr,"Going to average strains\n");*/
+ // averagestrains();
+ 
+ return 1;
+ 
+}
+// ------------------------------------------------------------------------
+void PXAbaqusOutputData::setRadial(int el,float x,float y,float z)
+{
+ el=Irange(el,0,numelements-1);
+ radial[el].setvector(x,y,z);
+}
+void PXAbaqusOutputData::setCircum(int el,float x,float y,float z)
+{
+ el=Irange(el,0,numelements-1);
+ circum[el].setvector(x,y,z);
+}
+void PXAbaqusOutputData::setCentroid(int el,float x,float y,float z)
+{
+ el=Irange(el,0,numelements-1);
+ elementCentroids[el].setvector(x,y,z);
+}
+// ------------------------------------------------------------------------
+void PXAbaqusOutputData::setPieStats(int nump,int numse,int numsl,int numt)
+{
+  numpies=nump;
+  numsectors=numse;
+  numslices=numsl;
+  numtransmural=numt;
+}
+// ------------------------------------------------------------------------
+int PXAbaqusOutputData::getElementPieIndex(int elno)
+{
+  elno=Irange(elno,0,numelements-1);
+  return pieindex[elno];
+}
+
+void PXAbaqusOutputData::setElementPieIndex(int elno,int pieind)
+{
+  elno=Irange(elno,0,numelements-1);
+  pieind=Irange(pieind,0,numpies-1);
+  pieindex[elno]=pieind;
+}
+// ------------------------------------------------------------------------
+void PXAbaqusOutputData::setElementInfo(int elno,int mode,float evol,
+					float e11,float e22,float e33,
+						 float e12,float e13,float e23)
+{
+ elno=Irange(elno,0,numelements-1);
+ mode=Irange(mode,0,2);
+ 
+ if (mode==0 || mode==2)
+     elementVolumes[elno]=evol;
+ 
+ if (mode==1 || mode==2)
+     {
+       strain[0][elno]=e11;	strain[1][elno]=e22;	strain[2][elno]=e33;
+       strain[3][elno]=e12;	strain[4][elno]=e13;	strain[5][elno]=e23;
+     }
+}
+// ------------------------------------------------------------------------- 
+// Node Output Info referes to last calculated displacement
+// ------------------------------------------------------------------------- 
+void PXAbaqusOutputData::setNodeInfo(int nodeno,float du,float dv,float dw)
+{
+ nodeno=Irange(nodeno,0,numnodes-1);
+ nodalDisplacements[nodeno].x[0]=du;
+ nodalDisplacements[nodeno].x[1]=dv;
+ nodalDisplacements[nodeno].x[2]=dw;
+}
+// ------------------------------------------------------------------------- 
+int PXAbaqusOutputData::saveNodeDetails(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+      return 0;
+  
+  fprintf(fout,"Numnodes\n%d\n",numnodes);
+  for (int i=0;i<numnodes;i++)
+      fprintf(fout,"%5d %6.3f %6.3f %6.3f\n",i+1000,
+	      nodalDisplacements[i].x[0],nodalDisplacements[i].x[1],
+	      nodalDisplacements[i].x[2]);
+ 
+  fclose(fout);
+  return(1);
+}
+// ------------------------------------------------------------------------- 
+int PXAbaqusOutputData::loadNodeDetails(const char* fname)
+{
+ gzFile fin=gzsuffixopen(fname,"r");
+ if (!fin)
+     return 0;
+ 
+ char line[200];
+ gzgets(fin,line,200);  gzgets(fin,line,200);
+ int np;
+ sscanf(line,"%d",&np);
+ if (np!=numnodes)
+     {
+       fprintf(stderr,"Wrong number of nodes\n");
+       gzclose(fin);
+       return(0);
+     }
+ 
+ int temp;
+ for (int i=0;i<np;i++)
+     {
+       gzgets(fin,line,200);
+       sscanf(line,"%d %f %f %f",&temp,
+	      &nodalDisplacements[i].x[0],
+	      &nodalDisplacements[i].x[1],
+	      &nodalDisplacements[i].x[2]);
+     }
+ gzclose(fin);
+ return(1);
+}
+// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 
+int PXAbaqusOutputData::modifyFromDisplacements(PXSolidNodes* nodes,int inner,int outer,
+					 PX3Vector* dispinner,PX3Vector* dispouter)
+{
+ for (int i=0;i<nodes->getnumnodes();i++)
+     {
+       int st=nodes->getindex(i,0);
+       int pt=nodes->getindex(i,1);
+       if (st==inner)
+	   setNodeInfo(i,
+		       dispinner[pt].x[0]+nodes->getdetails(i)->dx[0],
+		       dispinner[pt].x[1]+nodes->getdetails(i)->dx[1],
+		       dispinner[pt].x[2]+nodes->getdetails(i)->dx[2]);
+       else if (st==outer)
+	   setNodeInfo(i,
+		       dispouter[pt].x[0]+nodes->getdetails(i)->dx[0],
+		       dispouter[pt].x[1]+nodes->getdetails(i)->dx[1],
+		       dispouter[pt].x[2]+nodes->getdetails(i)->dx[2]);
+     }
+ return 1;
+}
+// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 
+void PXAbaqusOutputData::Copy(PXAbaqusOutputData* other)
+{
+ if (other->getnumnodes()!=numnodes || other->getnumelements()!=numelements)
+     {
+       cleanup();
+       init(other->getnumnodes(),other->getnumelements());
+     }
+ 
+ // Pie Stuff 
+ junctionpoint.copy(other->getjunctionpoint());
+ numpies=other->getnumpies();
+ numsectors=other->getnumsectors();
+ numslices=other->getnumslices();
+
+ // Node Stuff
+ {
+   for (int i=0;i<numnodes;i++)
+       nodalDisplacements[i].copy(other->getdisplacement(i));
+ }
+
+
+ // Element Stuff
+ for (int i=0;i<numelements;i++)
+     {
+       for (int ia=0;ia<12;ia++)
+	   strain[ia][i]=other->getstraincomponent(i,ia);
+       elementVolumes[i]=other->getvolume(i);
+       elementCentroids[i].copy(other->getcentroid(i));
+       radial[i].copy(other->getradial(i));
+       circum[i].copy(other->getcircumeferential(i));
+       pieindex[i]=Irange(other->getpieindex(i),0,numpies);
+     }
+}
+// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 
+int PXAbaqusOutputData::savePieDivision(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+      return 0;
+  
+  fprintf(fout,"#PXAbaqusOutputDataPieIndex2\n");
+  fprintf(fout,"Numelements\n%d\n",numelements);
+  fprintf(fout,"Pie stats\n%d %d %d %d\n",numpies,numslices,numsectors,numtransmural);
+  fprintf(fout,"# Element  Pie \n");
+  for (int i=0;i<numelements;i++)
+      fprintf(fout,"%5d %3d\n",i+1000,pieindex[i]);
+  fclose(fout);
+  return 1;
+}
+// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 
+int PXAbaqusOutputData::loadPieDivision(const char* fname)
+{
+  gzFile fin=gzsuffixopen(fname,"r");
+  if (!fin)
+      return 0;
+  char* line=new char[200];
+  gzgets(fin,line,200);
+  int mode=1;
+
+  if (gzfindstringinstring(line,"#PXAbaqusOutputDataPieIndex2")==0)
+    {
+      if (gzfindstringinstring(line,"#PXAbaqusOutputDataPieIndex")==0)
+	{
+	  delete [] line;
+	  return 0;
+	} 
+    } 
+  else 
+    {
+      mode =2;
+    }
+  
+  gzgets(fin,line,200);   gzgets(fin,line,200);
+  int ne;
+  sscanf(line,"%d",&ne);
+  
+  if (ne!=numelements)
+      {
+	fprintf(stderr,"Wrong number of elements in read pies (%d vs %d)\n",
+		ne,numelements);
+	gzclose(fin);
+	delete [] line;
+	return(0);
+      }
+  
+  gzgets(fin,line,200);   gzgets(fin,line,200);
+  if (mode == 1) 
+    {
+      sscanf(line,"%d %d %d",&numpies,&numslices,&numsectors);
+      numtransmural=1;
+    }
+  else 
+    {
+      sscanf(line,"%d %d %d %d",&numpies,&numslices,&numsectors,&numtransmural);
+    }
+  gzgets(fin,line,200);
+  
+  int temp;
+  for (int i=0;i<numelements;i++)
+      {
+	gzgets(fin,line,200);
+	sscanf(line,"%d %d",&temp,&pieindex[i]);
+	pieindex[i]=Irange(pieindex[i],0,numpies-1);
+      }
+  gzclose(fin);
+  return 1;
+}
+// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 
+int PXAbaqusOutputData::getsectorno(float phase,float phase_ref,int numsectors,int mode)
+{
+  float da=360.0/float(numsectors);
+  float angle=Fcyclic(phase-phase_ref,360.0);
+  int   sector=int(angle/da);
+
+  if (mode==0)
+      {
+	sector=numsectors-sector;
+	if (sector==numsectors)
+	    sector=0;
+      }
+  else if (mode==1)
+      {
+	sector+=1;
+	if (sector==numsectors)
+	    sector=0;
+      }
+      
+
+  if (sector<0 || sector>=numsectors)
+      fprintf(stderr,"Error sector=%d, numsectors=%d mode=%d da=%f angle=%f\n",sector,numsectors,mode,da,angle);
+  return sector;
+}
+// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 
+int PXAbaqusOutputData::combineWithOtherScale(PXAbaqusOutputData* other,float scaleother,float scalethis)
+{
+   if (other->getnumnodes()!=numnodes || other->getnumelements()!=numelements)
+     {
+       fprintf(stderr,"Wrong Number of Nodes and or elements\n");
+       return 0;
+     }
+ 
+ // Pie Stuff does not change 
+
+ // Node Stuff
+   {
+     for (int i=0;i<numnodes;i++)
+	 nodalDisplacements[i].add(other->getdisplacement(i),scaleother,scalethis);
+   }
+   
+ // Element Stuff
+ for (int i=0;i<numelements;i++)
+     {
+       for (int ia=0;ia<12;ia++)
+	   strain[ia][i]=scaleother*other->getstraincomponent(i,ia)+scalethis*strain[ia][i];
+       elementVolumes[i]=scaleother*other->getvolume(i)+scalethis*elementVolumes[i];
+       elementCentroids[i].add(other->getcentroid(i),scaleother,scalethis);
+       radial[i].add(other->getradial(i),scaleother,scalethis);
+       circum[i].add(other->getcircumeferential(i),scaleother,scalethis);
+       //  pieindex[i]=Irange(other->getpieindex(i),0,numpies);
+     }
+   return 1;
+} 
+// -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 
+
+
+
diff --git a/bioimagesuite30_src/numerics/pxabaqusstructures.h b/bioimagesuite30_src/numerics/pxabaqusstructures.h
new file mode 100644
index 0000000..92438fc
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxabaqusstructures.h
@@ -0,0 +1,320 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pxabaqusstructures.h 
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : pxabaqusstructures.h
+
+_Description : Various Utility Routines for Geometrical Entities like points,neighbours,triangles,
+               tetrahedra
+
+	       
+	       
+
+_Call : 
+
+     
+_References : 
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in May 22nd 1995
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+#ifndef _PXAbaqusstructures
+#define  _PXAbaqusstructures
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include "pxgeometrystruct.h"
+#include "pxshapetrackingclass.h"
+// ---------------------------------------------------
+//  Basic Data Stuctures 
+// ---------------------------------------------------
+
+struct PXNodeAuxiliary
+{
+  int index[2];
+  float dx[3];
+  float temperature;
+  PXIntegerList* neighbours;
+};
+
+class PXSolidNodes 
+{
+protected:
+  
+  int numnodes;
+  PXTriangulatedStackPoint* points;
+  PXNodeAuxiliary* pointDetails;
+
+public:
+  
+  PXSolidNodes(int numnodes);
+  PXSolidNodes(PXSolidNodes* oldnodes);
+  PXSolidNodes(PXSolidNodes* oldnodes1,PXSolidNodes* oldnodes2);
+  virtual ~PXSolidNodes();
+
+  void init(int numnodes);
+  void cleanup();
+
+  int getnumnodes();
+  PXTriangulatedStackPoint* getpoint(int pointidx);
+  PXNodeAuxiliary* getdetails(int pointidx);
+
+  // Further utility functions
+  int getindex(int point,int index);
+  void setindex(int point,int index,int val);
+  PXIntegerList* getneighbours(int point);
+
+
+  virtual void  settemperature(int node,float val=0.0);
+  virtual float gettemperature(int node);
+
+  // Old Code
+  // -------
+  void setfromnodecollection(PXNodeCollection* oldnodes,int scale=-1);
+  void Copy(PXSolidNodes* other,int check=1,int offset=0);
+
+  // I/O Stuff
+  int  Save(FILE* fout);
+  int  Save(const char* fname);
+  int  Load(gzFile fout);
+  int  Load(const char* fname);
+
+  
+};
+
+// ---------------------------------------------------
+
+class PXNodalDisplacements 
+{
+protected:
+
+  int endoindex,epiindex;
+  int *valid;
+  PX3Vector* disp;
+  float* conf;
+  PXSolidNodes* solidNodes;
+
+public:
+  PXNodalDisplacements(PXSolidNodes* nodes,int endo=0,int epi=100);
+  PXNodalDisplacements(PXNodalDisplacements* other);
+  virtual ~PXNodalDisplacements();
+
+  void init(int num);
+  void cleanup();
+
+  PX3Vector* getdisplacement(int i);
+  float      getdispcomponent(int i,int j);
+  float getconfidence(int i);
+
+  void setdisplacement(int i,PX3Vector* vec);
+  void setdisplacement(int i,float x,float y,float z);
+  void setdispcomponent(int i,int j,float x);
+  
+  void setconfidence(int i,float cnf);
+
+  int           getvalid(int i);
+  int           getendoindex();
+  int           getepiindex();
+  PXSolidNodes* getsolidnodes();
+
+  int  setfromshapetrackingclass(PXShapeTrackingClass* shapeTr,int index,float tolerance=0.05);
+  int  setfromshapetrackingclassnosearch(PXShapeTrackingClass* shapeTr,int index);
+  int  loadPengChengDisplacementsSingle(const char* endofile,const char* epifile,float tolerance=0.05);
+  int  loadDisplacementsSingle(const char* file,int all=0);
+  void Copy(PXNodalDisplacements* other);
+
+  // I/O Stuff
+  int  Save(FILE* fout);
+  int  Save(const char* fname);
+  int  Load(gzFile fout);
+  int  Load(const char* fname);
+
+};
+// ---------------------------------------------------
+class PXAbaqusMaterialModel {
+  
+protected:
+  int modeltype;
+  int nlgeom;
+  int active;
+  int numparameters;
+  float *parameter,heatcoeff[3];
+
+public:
+  PXAbaqusMaterialModel(int mode);
+  PXAbaqusMaterialModel(PXAbaqusMaterialModel *other);
+  virtual ~PXAbaqusMaterialModel();
+
+  void init(int mode);
+  void cleanup();
+  
+  void setgeometry(int nl=1);
+  int  getgeometry();
+
+  void setactive(int av=1);
+  int  getactive();
+
+  int   getmodeltype();
+  float getparameter(int i);
+
+  float getheatcoeff(int i);
+  void setheatcoeff(float a=-0.01,float b=0.03,float c=-0.02);
+
+  void setHyperelastic(float incompressibility=20.0);
+  void setElastic(float Modulus=1.0,float Poisson=0.45);
+  void setTransverseIsotropy(float Ep=1.0,float vp=0.4,float Et=3.5,float vtp=0.4);
+
+  void setfrommaterialmodel(PXMaterialModel* old);
+  void Copy(PXAbaqusMaterialModel* other);
+
+  void SaveAbaqus(FILE* fout,const char* name);
+  
+  int Save(const char* fname);
+  int Save(FILE* fout);
+  int Load(const char* fname);
+  int Load(gzFile fin);
+
+};
+// ---------------------------------------------------
+
+class PXAbaqusOutputData {
+
+protected:
+  int                       numnodes,numelements;
+  int                       numpies,numsectors,numslices,numtransmural;
+  PX3Vector                 junctionpoint;
+
+  PX3Vector                 *nodalDisplacements; 
+  float                     *strain[12];
+  float*                    elementVolumes;
+  PX3Vector*                elementCentroids;
+  PX3Vector*                radial,*circum;
+  int*                      pieindex;
+
+  int                       outputStepNo,outputIncNo;
+
+public:
+  PXAbaqusOutputData(int numnodes,int numelements);
+  PXAbaqusOutputData(PXAbaqusOutputData* other);
+  virtual ~PXAbaqusOutputData();
+
+  void       cleanup();
+  void       init(int numno,int numel);
+  void       Copy(PXAbaqusOutputData* other);
+
+  float      getvolume(int el);
+
+  float      getstraincomponent(int el,int str);
+  void       setstraincomponent(int el,int str,float v);
+
+  float      getdispcomponent(int node,int comp);
+
+  int        getnumelements();
+  int        getnumnodes();
+
+  PX3Vector* getdisplacement(int nd);
+  PX3Vector* getcentroid(int el);
+  PX3Vector* getradial(int el);
+  PX3Vector* getcircumeferential(int el);
+
+  int        getpieindex(int el);
+  int        copypieindex(PXAbaqusOutputData* other);
+  int        getnumpies();
+  int        getnumsectors();
+  int        getnumslices();
+  int        getnumtransmural();
+  PX3Vector* getjunctionpoint();
+
+  int getoutputstep();
+  int getoutputinc();
+
+
+  void setRadial(int el,float x,float y,float z);
+  void setCircum(int el,float x,float y,float z);
+  void setCentroid(int el,float x,float y,float z);
+  void setNodeInfo(int nodeno,float du,float dv,float dw);
+  void setElementInfo(int elno,int mode,float evol,
+		      float e11,float e22,float e33,
+		      float e12,float e13,float e23);
+
+  int  getElementPieIndex(int elno);
+  void setElementPieIndex(int elno,int pieindex);
+  void setPieStats(int nump=1,int nunse=1,int numsl=1,int numt=1);
+  void setOutputStepInc(int os,int oi);
+
+
+  void converttoprincipal();
+
+  int saveNodeDetails(const char* fname);
+  int loadNodeDetails(const char* fname);
+
+  int savePieDivision(const char* fname);
+  int loadPieDivision(const char* fname);
+
+  int Save(const char* fname,int nodirections=1);
+  int Load(const char* fname,int rotate=1,int check=1,int integrate=0);
+  int LoadOld(const char* fnamestem,int rotate=1);
+
+  int rotatestrains();
+  int subdivideinpies(float junctionx=0.0,float junctiony=0.0,float junctionz=0.0,
+		      int numslices=3,int numsectors=8,int anticlockwise=1,int nump=-1);
+  int averagestrains(PXAbaqusOutputData *ref);
+  int modifyFromDisplacements(PXSolidNodes* nodes,int inner,int outer,
+			      PX3Vector* dispinner,PX3Vector* dispouter);
+
+  
+  int combineWithOtherScale(PXAbaqusOutputData* other,float scaleother,float scalethis);
+
+  static int getsectorno(float angle,float phase_ref,int numsectors,int mode=0);
+};
+// ---------------------------------------------------
+
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/pxchamferdistancemap.cpp b/bioimagesuite30_src/numerics/pxchamferdistancemap.cpp
new file mode 100644
index 0000000..bd39850
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxchamferdistancemap.cpp
@@ -0,0 +1,867 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+#include "pxchamferdistancemap.h"
+
+short PXChamferDistanceMap::pixel_size=100;
+short PXChamferDistanceMap::obj_gray=30000;
+short PXChamferDistanceMap::out_gray=-30000;
+short PXChamferDistanceMap::margin=30;
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+PXChamferDistanceMap::PXChamferDistanceMap(PXContour* cnt,int filter_mode,int subpxl,
+					   int imsizex,int imsizey)
+{
+  initializemembers();
+  contour=new PXContour(cnt);
+  contour->setclosed(1);
+  init(filter_mode,subpxl,imsizex,imsizey);
+}
+
+PXChamferDistanceMap::PXChamferDistanceMap(PXContour* cntr,int filter_mode,
+					   int subpxl,PXChamferDistanceMap* clone)
+{
+  initializemembers();
+  contour=new PXContour(cntr);
+  contour->setclosed(1);
+  subpixel=(subpxl>0);
+
+  int np=contour->getnumpoints();
+  if (np==0)
+    {
+      fprintf(stderr,"pxchamferdistancemap::Bad Contour\n");
+      return;
+    }
+  offsetx=clone->getoffsetx();
+  offsety=clone->getoffsety();
+  min_x=clone->getminx();
+  min_y=clone->getminy();
+  max_x=clone->getmaxx();
+  max_y=clone->getmaxy();
+
+  int imsizex=clone->getDistanceMap()->getsizex();
+  int imsizey=clone->getDistanceMap()->getsizey();
+
+    
+  image=new PXImage(imsizex,imsizey);
+  hasmap=0;
+  
+  if (filter_mode>0)
+    generateMap(filter_mode);
+}
+
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+PXChamferDistanceMap::PXChamferDistanceMap(PXContour* cntr1,PXContour* cntr2,
+					   int fraction1,int fraction2)
+{
+  initializemembers();
+  PXChamferDistanceMap* map1=new PXChamferDistanceMap(cntr1); 
+  PXChamferDistanceMap* map2=new PXChamferDistanceMap(cntr2); 
+  lininterpolate(map1,map2,fraction1,fraction2);
+  delete map1;
+  delete map2;
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+PXChamferDistanceMap::PXChamferDistanceMap(PXContour* cntr0,PXContour* cntr1,
+					   PXContour* cntr2,PXContour* cntr3,
+					   float spc)
+{
+  initializemembers();
+  PXChamferDistanceMap* map0=new PXChamferDistanceMap(cntr0); 
+  PXChamferDistanceMap* map1=new PXChamferDistanceMap(cntr1); 
+  PXChamferDistanceMap* map2=new PXChamferDistanceMap(cntr2); 
+  PXChamferDistanceMap* map3=new PXChamferDistanceMap(cntr3); 
+  catsplineinterpolate(map0,map1,map2,map3,spc);
+  delete map0;
+  delete map1;
+  delete map2;
+  delete map3;
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+
+PXChamferDistanceMap::PXChamferDistanceMap(PXChamferDistanceMap* map1,
+					   PXChamferDistanceMap* map2,
+					   int fraction1,int fraction2,
+					   int imsizex,int imsizey)
+{
+  initializemembers();
+  lininterpolate(map1,map2,fraction1,fraction2,imsizex,imsizey);
+}
+PXChamferDistanceMap::PXChamferDistanceMap(PXChamferDistanceMap* map0,
+					   PXChamferDistanceMap* map1,
+					   PXChamferDistanceMap* map2,
+					   PXChamferDistanceMap* map3,
+					   float spc)
+{
+  initializemembers();
+  catsplineinterpolate(map0,map1,map2,map3,spc);
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+void PXChamferDistanceMap::initializemembers()
+{
+  image=NULL;
+  contour=NULL;
+  offsetx=0; offsety=0; subpixel=0; hasmap=0; min_x=0; max_x=0; min_y=0;max_y=0;
+}
+
+
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+void PXChamferDistanceMap::init(int filter_mode,int subpxl,int input_imagesizex,int input_imagesizey)
+{
+  subpixel=(subpxl>0);
+
+  int np=contour->getnumpoints();
+  if (np==0)
+    {
+      fprintf(stderr,"pxchamferdistancemap::Bad Contour\n");
+      return;
+    }
+
+  PXContourPoint *pts=contour->gettoppoint();
+  min_x=int(pts->x+0.5),max_x=int(pts->x+0.5);
+  min_y=int(pts->y+0.5),max_y=int(pts->y+0.5);
+
+  for (int pt=0;pt<np;pt++)
+    { 
+      float x=pts->x;	        float y=pts->y;	
+      int i=int(x+0.5);	int j = int(y+0.5);
+      pts=pts->next;      
+      min_x = Imin( min_x, i );	 min_y = Imin( min_y, j );
+      max_x = Imax( max_x, i );  max_y = Imax( max_y, j );
+    }
+  
+  offsetx=0;   offsety=0;
+  max_x+=margin;    min_x-=margin;
+  max_y+=margin;    min_y-=margin;
+
+  int imsizex=max_x-min_x+1;	offsetx=min_x; 
+
+  if (input_imagesizex>imsizex)
+    {
+      offsetx=-(input_imagesizex-imsizex)/2;
+      imsizex=input_imagesizex;
+    }
+
+  int imsizey=max_y-min_y+1;  offsety=min_y; 
+  if (input_imagesizey>imsizey)
+    {
+      offsety=-(input_imagesizey-imsizey)/2;
+      imsizey=input_imagesizey;
+    }
+  
+  //contour->Save("imagecontour.cntr");
+  
+  image=new PXImage(imsizex,imsizey);
+  hasmap=0;
+  
+  if (filter_mode>0)
+    generateMap(filter_mode);
+  
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+PXChamferDistanceMap::~PXChamferDistanceMap()
+{
+  if (image!=NULL)
+    delete image;
+  if (contour!=NULL)
+    delete contour;
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+void PXChamferDistanceMap::lininterpolate(PXChamferDistanceMap* map1,
+					  PXChamferDistanceMap* map2,
+					  int fraction1,int fraction2,
+					  int imsizex,int imsizey)
+{
+  if (imsizex<=0)
+    {
+      min_x=Imin(map1->getminx(),map2->getminx());
+      max_x=Imax(map1->getmaxx(),map2->getmaxx());
+      imsizex=max_x-min_x+1;
+      offsetx=min_x;
+    }
+  else
+    {
+      offsetx=0;
+      min_x=0;
+      max_x=imsizex-1;
+    }
+  
+  if (imsizey<=0)
+    {
+      min_y=Imin(map1->getminy(),map2->getminy());
+      max_y=Imax(map1->getmaxy(),map2->getmaxy());
+      imsizey=max_y-min_y+1;
+      offsety=min_y;
+    }
+  else
+    {
+      offsety=0;
+      min_y=0;
+      max_y=imsizey-1;
+    }
+
+  image=new PXImage(imsizex,imsizey);
+  
+  for (int i=min_x;i<=max_x;i++)
+    for (int j=min_y;j<=max_y;j++)
+      {
+	short p1=map1->getvalue(i,j);    
+	short p2=map2->getvalue(i,j);
+	short p=out_gray;
+	
+	if (p1*p2<=0)
+	  p=(fraction1*p1+fraction2*p2)/(fraction1+fraction2);
+	else if (p1>0)
+	  p=obj_gray;
+	
+	if (p==0)
+	  p++;
+	image->setspixel(i-offsetx,j-offsety,p);
+      }
+  contour=new PXContour();
+  hasmap=1;
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+void PXChamferDistanceMap::catsplineinterpolate(PXChamferDistanceMap* map0,
+						PXChamferDistanceMap* map1,
+						PXChamferDistanceMap* map2,
+						PXChamferDistanceMap* map3,
+						float fr)
+{
+  min_x=Imin(map0->getminx(),map1->getminx());
+  min_x=Imin(min_x,map2->getminx());
+  min_x=Imin(min_x,map3->getminx());
+
+  min_y=Imin(map0->getminy(),map1->getminy());
+  min_y=Imin(min_y,map2->getminy());
+  min_y=Imin(min_y,map3->getminy());
+
+  max_x=Imax(map0->getmaxx(),map1->getmaxx());
+  max_x=Imax(max_x,map2->getmaxx());
+  max_x=Imax(max_x,map3->getmaxx());
+
+  max_y=Imax(map0->getmaxy(),map1->getmaxy());
+  max_y=Imax(max_y,map2->getmaxy());
+  max_y=Imax(max_y,map3->getmaxy());
+  
+  int imsizex=max_x-min_x+1;
+  offsetx=min_x;
+  int imsizey=max_y-min_y+1;
+  offsety=min_y;
+  image=new PXImage(imsizex,imsizey);
+  
+  for (int i=min_x;i<=max_x;i++)
+    for (int j=min_y;j<=max_y;j++)
+      {
+	short p0=map1->getvalue(i,j);
+	short p1=map1->getvalue(i,j);
+	short p2=map2->getvalue(i,j);
+	short p3=map2->getvalue(i,j);
+	
+	float d=float(p1);
+	float c=float(p2-p0)/2.0;
+	float e=float(p2);
+	float f=float(p3-p1)/2.0;
+	
+	float a=(f-2*e)+c+2.0*d;
+	float b=e-a-c-d;
+	short p=short(a*pow(fr,float(3.0))+b*pow(fr,float(2.0))+c*fr+d+0.5);
+	
+	if (p==0)
+	  p++;
+	image->setspixel(i-offsetx,j-offsety,p);
+      }
+  contour=new PXContour();
+  hasmap=1;
+}
+
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+void PXChamferDistanceMap::setlevels(short obj,short out)
+{
+  if (obj<0)
+    obj_gray=-obj;
+  else
+    obj_gray=obj;
+  
+  if (obj_gray>30000)
+    obj_gray=30000;
+  
+  
+  if (out>0)
+    out_gray=-out;
+  else
+    out_gray=out;
+  
+  if (out_gray<-30000)
+    out_gray=-30000;
+  
+  //  fprintf(stderr,"Levels : = obj_gray=%d, out_gray=%d\n",obj_gray,out_gray);
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+short PXChamferDistanceMap::getvalue(int i,int j)
+{
+  i=i-offsetx; j=j-offsety;
+  
+  if (i<0 || i>=image->getsizex() || j<0 || j>=image->getsizey())
+    return out_gray;
+  else
+    return image->getspixel(i,j);
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+PXImage* PXChamferDistanceMap::getEnergyMap()
+{
+  short ps=1;
+  PXImage* energy=new PXImage(image->getsizex(),image->getsizey());
+  for (int i=0;i<image->getsizex();i++)
+    for (int j=0;j<image->getsizey();j++)
+      {
+	short a=image->getspixel(i,j);
+	if (a<-ps)
+	  energy->setpixel(i,j,0);
+	else if (a>ps)
+	  energy->setpixel(i,j,2*ps);
+	else 
+	  energy->setpixel(i,j,a+ps);
+      }
+  return energy;
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+void PXChamferDistanceMap::initial_contour(int perturb,float pert_amount,int debug)
+{
+  if (debug)
+    contour->Save("initial_contour.cntr");
+  // 1. Make all points=obj_gray
+  for(int ia=0;ia<image->getsizex();ia++)
+    for(int ib=0;ib<image->getsizey();ib++)
+      image->setspixel(ia,ib,obj_gray);
+  
+  // 2. Put Distance map for points on contour 
+  if (!subpixel)
+    {
+      if (debug)
+	fprintf(stderr,"Not sub-pixel\n");
+      PXContourPoint *pts=contour->gettoppoint();
+      while(pts->next !=NULL)
+	{ 
+	  float x=pts->x;	float y=pts->y;	
+	  int i = int(x+0.5);	int j = int(y+0.5);
+	  image->setspixel(i-offsetx,j-offsety,0);
+	  pts=pts->next;      
+	}
+      return;
+    }
+  
+  // SubPixel
+  // Check whether contour is clockwise or anticlockwise
+  // ---------------------------------------------------
+  int np=contour->getnumpoints();
+  int i=0;
+  float xold,yold, v1x=0,v1y=0,v2x=0,v2y=0;
+  PXContourPoint *pts=contour->gettoppoint();
+  xold=pts->x;  yold=pts->y;
+
+  if (debug)
+    fprintf(stderr,"Doing sub-pixel\n");
+  
+  
+  while(pts->next!=NULL)
+    {
+      i++;
+      if (i==int(np/3))
+	{
+	  v1x=pts->x-xold;   v1y=pts->y-yold;
+	  xold=pts->x; 	     yold=pts->y;
+	}
+      if (i==2*int(np/3))
+	{
+	  v2x=pts->x-xold;   v2y=pts->y-yold;
+	}
+      if (i==(np-1))
+	{
+	  xold=pts->x; yold=pts->y;
+	}
+      pts=pts->next;
+    }
+  
+  float zz=(v1x*v2y-v2x*v1y);
+  float anti=-1.0;
+  if (zz>0.0) anti=1.0;
+  float edge=float(pixel_size);
+
+  pts=contour->gettoppoint();
+  while(pts->next !=NULL)
+    { 
+      int lowx=0,highx=0,lowy=0,highy=0;
+      float x=pts->x;	float y=pts->y;	
+      if (x==float(int(x)) && y==float(int(y)))
+	if(perturb==1)
+	  {
+	    double xnext,ynext;
+	    if ((pts->next)->next == NULL)
+	      { xnext=(contour->gettoppoint())->x;
+	      ynext=(contour->gettoppoint())->y;
+	      }
+	    else
+	      { xnext=(pts->next)->x;
+	      ynext=(pts->next)->y;
+	      }
+	    double ny=xnext-xold;
+	    double nx=yold-ynext;
+	    double mag=sqrt(nx*nx+ny*ny);
+	    if (mag>0.0)
+	      { nx = nx/mag; ny=ny/mag; }    		    
+	    if (debug)
+	      fprintf(stderr,"(%5.2f,%5.2f)->",x,y);
+	    x=x-pert_amount*anti*nx; y=y-pert_amount*anti*ny;
+	    if (debug)
+	      fprintf(stderr,"  (%5.2f,%5.2f)\n",x,y);
+	    
+	    pts->x=x; pts->y=y;
+	  }
+	else
+	  {
+	    if (x==float(int(x)))
+	      lowx=1;
+	    if (y==float(int(y)))
+	      lowy=1;
+	  }
+      
+      xold=x;yold=y;
+      
+      int x0=int(x);  int x1=int(x+1);
+      int y0=int(y);  int y1=int(y+1);
+      
+      for(int i=x0-offsetx-lowx;i<=x1-offsetx+highx;i++)
+	for (int j=y0-offsety-lowy;j<=y1-offsety+highy;j++)
+	  {
+	    if (debug)
+	      {
+		if (i<0 || j<0 || i>=image->getsizex() || j>=image->getsizey())
+		  {
+		    fprintf(stderr," Original (%d,%d) to (%d,%d) Current(%d,%d)\n",
+			    x0,y0,x1,y1,i,j);
+		    fprintf(stderr,"(Highs %d:%d) (Lows %d:%d) offsets(%d:%d)\n"
+			    ,highx,highy,lowx,lowy,offsetx,offsety);
+		  }
+	      }
+	    short val=image->getspixel(i,j);
+	    short dist=short(0.5+edge*sqrt(pow(x-float(i+offsetx),float(2.0))+
+					   pow(y-float(j+offsety),float(2.0))));
+	    if (dist<abs(val))
+	      {
+		if (contour->IsInside(float(i+offsetx),float(j+offsety)))
+		  {
+		    image->setspixel(i,j,dist);
+		    if (debug>1)
+		      fprintf(stderr,"\t(%2d,%2d) %3d(%3d)",i+offsetx,j+offsety,
+			      image->getspixel(i,j),dist);
+		  }
+		else
+		  {
+		    image->setspixel(i,j,-dist);
+		    short a=image->getspixel(i,j);
+		    if (debug>1)
+		      fprintf(stderr,"\t(%2d,%2d) %3d(%3d)",i+offsetx,j+offsety,
+			      a,-dist);
+		    
+		  }
+	      }
+	  }
+      if (debug)
+	fprintf(stderr,"\n");
+      pts=pts->next;
+    } 
+  if (debug)
+    contour->Save("shifted.cntr");
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+int PXChamferDistanceMap::initial_outside(int x,int y)
+{ 
+  int 	retval_x,retval_y;
+  if ( x<0 || x>=image->getsizex() || y<0 || y>=image->getsizey())
+    {
+      return(0);
+    }
+  
+  short val = image->getspixel(x,y);
+
+  if ( abs(val)>(2*pixel_size)  && val!=out_gray)
+    {
+      image->setspixel(x,y,out_gray);
+      for (int i=-1; i <= 1; i += 2) 
+	{
+	  x += i;
+	  retval_x = initial_outside(x,y);
+	  x -= i;
+	  y += i;
+	  retval_y = initial_outside(x,y);
+	  y -= i;
+	}
+    }
+  else 
+    {
+      return(1);
+    }
+  
+  return(retval_x && retval_y);
+  
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+void PXChamferDistanceMap::generateMap(int filtermode,int perturb,float per_amount)
+{
+  //fprintf(stderr,"Generating Map\n");
+  initial_contour(perturb,per_amount,0);
+  //  fprintf(stderr,"Initial Done\n");
+  initial_outside();
+  //  fprintf(stderr,"Outside Done\n");
+  
+  if (filtermode>=1)
+    chamferfilter();
+}
+
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+// Original Code by Lei Zhang 
+// Modified and corrected for sub-pixel
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+short makedistplus(short val,short add)
+{
+  if (val>0)
+    return val+add;
+  else
+    return 32767;
+}
+  
+short makedistminus(short val,short add)
+{
+  if (val<0)
+    return val+add;
+  else
+    return -32767;
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - - 
+void PXChamferDistanceMap::chamferfilter()
+{
+  //  fprintf(stderr,"Filter 3x3\n");
+  short         temp[10];
+  short         px1=pixel_size;
+  short         px2=short(0.5+float(pixel_size)*sqrt(2.0)); 
+  PXImage* tempimage=new PXImage(image);
+  
+  // Filter 1 Top-Right to Bottom Left 
+  // saveImage("step0.pgm",1);
+  int j;
+  
+  for (j=2; j<tempimage->getheight()-2; j++ ) 
+    for (int i=2; i<tempimage->getwidth()-2 ; i++) 
+      { 
+	if ( tempimage->getspixel(i,j) > px2 )
+	  {	
+	    short immin=image->getspixel(i,j);
+	    temp[0]=makedistplus(image->getspixel(i-1,j-1),px2);
+	    temp[1]=makedistplus(image->getspixel(i  ,j-1),px1);
+	    temp[2]=makedistplus(image->getspixel(i+1,j-1),px2);
+	    temp[3]=makedistplus(image->getspixel(i-1,j  ),px1);
+	    
+	    for (int r=0;r<=3;r++)
+	      {
+		if (temp[r]<immin)
+		  immin=temp[r];
+	      }
+	    image->setspixel(i,j,immin);
+	  }
+	else if ( tempimage->getspixel(i,j) < -px1 ) 
+	  {
+	    short immax=image->getspixel(i,j);
+	    temp[0]=makedistminus(image->getspixel(i-1,j  ),-px1);
+	    temp[1]=makedistminus(image->getspixel(i-1,j-1),-px2);
+	    temp[2]=makedistminus(image->getspixel(i  ,j-1),-px1);
+	    temp[3]=makedistminus(image->getspixel(i+1,j-1),-px2);
+	    
+	    for(int r=0;r<=3;r++)
+	      {
+		if (temp[r]>immax)
+		  immax=temp[r];
+	      }
+	    image->setspixel(i,j,immax);
+	  }
+      }
+  
+  // Filter 2 from bottom right to top left
+  // --------------------------------------
+  //  fprintf(stderr,"Chamfer Step 2 %d %d\n",px1,px2);
+  for (j=tempimage->getheight()-2; j>=2; j-- ) 
+    for (int i=tempimage->getwidth()-2; i>=2; i-- ) 
+      { 
+	if ( tempimage->getspixel(i,j) > px2 )
+	  {
+	    short immin=image->getspixel(i,j);
+	    temp[0]=makedistplus(image->getspixel(i-1,j+1),px2);
+	    temp[1]=makedistplus(image->getspixel(i  ,j+1),px1);
+	    temp[2]=makedistplus(image->getspixel(i+1,j+1),px2);
+	    temp[3]=makedistplus(image->getspixel(i+1,j  ),px1);
+	    
+	    for (int r=0;r<=3;r++)
+	      {
+		if (temp[r]<immin)
+		  immin=temp[r];
+	      }
+	    //immin=Imin(temp[r],immin);
+	    image->setspixel(i,j,immin);
+	  }
+	else if ( tempimage->getspixel(i,j) < -px1 ) 
+	  {
+	    short immax=image->getspixel(i,j);
+	    temp[0]=makedistminus(image->getspixel(i-1,j+1),-px2);
+	    temp[1]=makedistminus(image->getspixel(i  ,j+1),-px1);
+	    temp[2]=makedistminus(image->getspixel(i+1,j+1),-px2);
+	    temp[3]=makedistminus(image->getspixel(i+1,j  ),-px1);
+	    
+	    for(int r=0;r<=3;r++)
+	      {
+		if (temp[r]>immax)
+		  immax=temp[r];
+	      }
+	    //    immax=Imax(temp[r],immax);
+	    image->setspixel(i,j,immax);
+	  }
+      }
+  // saveImage("step2.pgm",1);
+  delete tempimage;
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+int PXChamferDistanceMap::findexit(int m,int n,float xin,float yin,
+				   float& xout,float& yout,
+				   int& mout,int& nout,int )
+{
+  int edge=1,found=0;
+
+  // Determine Starting Edge , Clockwise
+  // -----------------------------------
+  if (xin==float(m))
+      edge=1;
+  else if(yin==float(n))
+      edge=2;
+  else if(xin==float(m+1))
+      edge=3;
+  else 
+      edge=4;
+
+
+  while(edge <=4 && found==0)
+    {
+      
+      int i=0,j=0,ip=0,jp=0,shifti=0,shiftj=0;
+      switch(edge)
+	{
+	case 1:  
+	  i=0;j=0;ip=1;jp=0; shifti=0;shiftj=-1;    
+	  break;
+	case 2:  
+	  i=1;j=0;ip=1;jp=1; shifti=1;shiftj=0;
+	  break;
+	case 3:  
+	  i=1;j=1;ip=0;jp=1; shifti=0;shiftj=1;
+	  break;
+	case 4:  
+	  i=0;j=1;ip=0;jp=0; shifti=-1;shiftj=0;
+	  break;
+	}
+      
+      short v0=image->getspixel(m+i ,n+j);
+      short v1=image->getspixel(m+ip,n+jp);
+      
+      if (v0*v1 < 0)
+	{
+	  // Change of Sign Indicates zero crossing 
+	  
+	  float xm,ym;
+	  float x0=float(m+i), x1=float(m+ip);
+	  float y0=float(n+j), y1=float(n+jp);	
+	  
+	  xm=( x1*v0-x0*v1)/(v0-v1);
+	  ym=( y1*v0-y0*v1)/(v0-v1);
+	  
+	  if (xm!=xin || ym!=yin)
+	    {
+	      xout=xm;		    yout=ym;
+	      mout=m+shifti;	    nout=n+shiftj;
+	      found=1;
+	    }
+	}
+      edge++;
+      if (edge>4)
+	edge=1;
+    }
+  if (found==0)
+    fprintf(stderr, "Error\n");
+  
+  return found;
+}
+
+int  PXChamferDistanceMap::validcell(int x,int y,int )
+{
+  // Cell is Valid is some +ve and some -ve
+
+  int positive=0,negative=0;
+  for(int i=0;i<=1;i++)
+    for(int j=0;j<=1;j++)
+      {
+	short px=image->getspixel(x+i,y+j);
+	if (px<0)
+	  negative++;
+	if (px>0)
+	  positive++;
+      }
+
+  if (positive>0 && negative>0)
+    return(1);
+
+  return(0);
+
+
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+PXContour* PXChamferDistanceMap::extractContour()
+{
+  //static int no=1;
+
+  int starti=0,startj=0,i=0,found=0;
+  // Find First Point in cell to make sense 
+  while(i<image->getsizex()-1 && found==0)
+    {
+      int j=0;
+      while(j<image->getsizey()-1 && found==0)
+	{
+	  if (validcell(i,j)==1)
+	    {
+	      starti=i;startj=j;
+	      found=1;
+	    }
+	  j++;
+	}
+      i++;
+    }
+  
+  PXContour* cntr=new PXContour;
+  if (found==0)
+    {
+      fprintf(stderr,"No Contour Found ... \n");
+      return cntr;
+    }
+  float startx=0.0,starty=0.0,oldx=0.0,oldy=0.0,newx=0.0,newy=0.0;
+  int   oldi=0,oldj=0,newi=0,newj=0;
+  
+  if (!findexit(starti,startj,0.0,0.0,startx,starty,newi,newj,0))
+    {
+      fprintf(stderr,"No Contour Found ... \n");
+      return cntr;
+    }
+  cntr->Add(startx+float(offsetx),starty+float(offsety));
+  int stop=0; 
+  newx=startx;
+  newy=starty;
+  
+  while(stop==0)
+    {
+      oldx=newx; oldy=newy;
+      oldi=newi; oldj=newj;
+      if(!findexit(oldi,oldj,oldx,oldy,newx,newy,newi,newj,0))
+	{
+	  fprintf(stderr,"No Contour Found ... \n");
+	  return cntr;
+	}
+      if (newx==startx && newy==starty)
+	stop=1;
+      else
+	cntr->Add(newx+float(offsetx),newy+float(offsety));
+    }
+  
+  // cerr << "Closing : " << startx << "," << starty << ":" << newx << " " << newy << "\n";
+  
+  /*  char line[100];
+      sprintf(line,"extract%02d.cntr",no);
+      no++;
+      cntr->Save(line);
+      fprintf(stderr,"Saved in %s (%d)\n",line,cntr->getnumpoints());*/
+  
+  return cntr;
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
+void PXChamferDistanceMap::saveImage(const char* fname,int binary)
+{
+  PXImage* im2=new PXImage(image);
+  
+  if (binary==1)
+    {
+      for(int i=0;i<im2->getsizex();i++)
+	for(int j=0;j<im2->getsizey();j++)
+	  {
+	    short px=im2->getspixel(i,j);
+	    if (px<-1280)
+	      im2->setpixel(i,j,0);
+	    else if (px>1280)
+	      im2->setpixel(i,j,255);
+	    else
+	      {
+		short a=128+px/10;
+		im2->setpixel(i,j,a);
+	      }
+	  }
+      im2->SavePgm(fname);
+    }
+  else
+    {
+      FILE* fout=fopen(fname,"w");
+      if (fout!=NULL)
+	{
+	  for(int j=0;j<im2->getsizey();j++)
+	    {
+	      fprintf(fout,"%4d  ",j-offsety);
+	      if (binary==-1)
+		{
+		  for(int i=0;i<im2->getsizex();i++)
+		    fprintf(fout,"%5d  ",image->getspixel(i,j));
+		  fprintf(fout, "\n");
+		}
+	      else
+		{
+		  
+		  fprintf(fout,"%5d\n",image->getspixel(image->getsizex()/2,j));
+		}
+	    }
+	}
+      fclose(fout);
+    }
+  delete im2;
+}
+
diff --git a/bioimagesuite30_src/numerics/pxchamferdistancemap.h b/bioimagesuite30_src/numerics/pxchamferdistancemap.h
new file mode 100644
index 0000000..14b0045
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxchamferdistancemap.h
@@ -0,0 +1,150 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pxchamferdistancemap.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris  papad at noodle.med.yale.edu
+
+
+_Module_Name : 1. PXChamferDistanceMap
+
+_Description : 
+               
+	       
+	       
+_Call : 
+        
+_References : Computational Geometry, Preparata and Shamos              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in November 14th 1997
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PX_CHAMFERDISTANCEMAP
+#define _PX_CHAMFERDISTANCEMAP
+
+#include "pxutil.h"
+#include "px3dimage.h"
+#include "pxcontour.h"
+
+class PXChamferDistanceMap {
+  PXImage* image;
+  PXContour* contour;
+  int offsetx,offsety;
+  int subpixel,hasmap;
+  int min_x,max_x,min_y,max_y;
+  
+public:
+  // Global Control Parameters
+  static short pixel_size;
+  static short obj_gray,out_gray;
+  static short margin;
+  
+  // --------------------------
+  // Functions
+  // --------------------------
+  PXChamferDistanceMap(PXContour* cntr,int auto_mode=1,
+		       int subpixel=1,int imsizex=-1,int imsizey=-1);
+
+
+  PXChamferDistanceMap(PXContour* cntr,int auto_mode,
+		       int subpixel,PXChamferDistanceMap* clone);
+
+
+  PXChamferDistanceMap(PXContour* cntr1,PXContour* cntr2,
+		       int fraction1=1,int fraction2=1);
+
+  PXChamferDistanceMap(PXContour* spl0,PXContour* spl1,
+		       PXContour* spl2,PXContour* spl3,
+		       float spc=0.5);
+
+  PXChamferDistanceMap(PXChamferDistanceMap* map1,PXChamferDistanceMap* map2,
+		       int fraction1=1,int fraction2=1,int imsizex=-1,int imsizey=-1);
+  PXChamferDistanceMap(PXChamferDistanceMap* map0,PXChamferDistanceMap* map1,
+		       PXChamferDistanceMap* map2,PXChamferDistanceMap* map3,
+		       float spc=0.5); 
+  ~PXChamferDistanceMap();
+
+
+  void generateMap(int filtermode=1,int perturb=1,float per_amount=0.1);
+  int  hasMap() { return hasmap; }
+  
+  void init(int auto_mode,int subpixel,int imsizex,int imsizey);
+  void lininterpolate(PXChamferDistanceMap* map1,PXChamferDistanceMap* map2,
+		      int fraction1=1,int fraction2=1,int imsizex=-1,int imsizey=-1);
+  void catsplineinterpolate(PXChamferDistanceMap* map0,PXChamferDistanceMap* map1,
+			    PXChamferDistanceMap* map2,PXChamferDistanceMap* map3,
+			    float fr=0.0);
+  void setlevels(short obj=32767,int short=-32767);
+  void saveImage(const char* fname,int binary=1);
+
+  short getvalue(int i,int j);
+  int getminx() { return min_x;}
+  int getminy() { return min_y;}
+  int getmaxx() { return max_x;}
+  int getmaxy() { return max_y;}
+  int getoffsetx() { return offsetx;}
+  int getoffsety() { return offsety;}
+
+  PXContour* extractContour();
+  PXImage*   getDistanceMap() { return image; }
+  PXImage*   getEnergyMap();
+
+  void chamferfilter();
+
+protected:
+
+  int findexit(int i,int j,float xin,float yin,
+	       float& xout,float& yout,int& iout,int& jout,int debug=0);
+  int  validcell(int i,int j,int debug=0);
+  
+  void initial_contour(int perturb=1,float pert_dist=0.1,int debug=0);
+  int  initial_outside(int x=1,int y=1);
+  void initializemembers();
+
+
+};
+
+#endif   
+
diff --git a/bioimagesuite30_src/numerics/pxcontour.cpp b/bioimagesuite30_src/numerics/pxcontour.cpp
new file mode 100644
index 0000000..bffe20f
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxcontour.cpp
@@ -0,0 +1,1979 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//
+//
+// Calls ludcmp to compute matrrix linear system solution
+//
+//---------------------------------------------------------------------------------------------------------
+
+#include "pxcontour.h"
+#include "pxutil.h"
+#include "nr.h"
+#include "nrutil.h"
+// Defining namespace for old code
+
+
+//-----------------------------------------------------------------------
+float PXContour::Break_const = 11.111;
+//-----------------------------------------------------------------------
+
+PXContour::PXContour()
+{
+  status=1;
+  numpoints=0;
+  closed=0;
+  isolated=0;
+  lastpoint=new PXContourPoint;
+  lastpoint->next=NULL;
+  lastpoint->previous=NULL;
+  realnextpoint=NULL;
+  toppoint=lastpoint;
+  gradient=0;
+  contourhascache=0;
+  px=NULL;py=NULL;
+}
+
+// --------------------------------------------------------------------------
+PXContour::PXContour(PXContour *oldcontour)
+{
+  status=1;
+  numpoints=0;
+  closed=0;
+  isolated=0;
+  lastpoint=new PXContourPoint;
+  lastpoint->next=NULL;
+  lastpoint->previous=NULL;
+  realnextpoint=NULL;
+  toppoint=lastpoint;
+  gradient=0;
+  contourhascache=0;
+  px=NULL;py=NULL;
+  PXContourPoint* temp=oldcontour->gettoppoint();
+  for (int i=0;i<oldcontour->getnumpoints();i++)
+    {
+      Add(temp->x,temp->y);
+      temp=temp->next;
+    }
+}
+// --------------------------------------------------------------------------
+PXContour::~PXContour()
+{
+  PXContourPoint* pts=gettoppoint();
+  /*fprintf(stderr,"\n pts\t pts->p\t pts->n\t in\t np\t x\t y\n"); 
+    int index=0;*/
+  while (pts!=NULL)
+    {
+      /*fprintf(stderr," %9d \t %9d \t %9d \t %5d \t %5d \t %6.2f \t %6.2f \n",
+	      pts,pts->previous,pts->next,index,(index<np),pts->x,pts->y);
+	      ++index;*/
+      PXContourPoint* old=pts;
+      if (pts==lastpoint)
+	pts=realnextpoint;
+      else
+	pts=pts->next;
+      delete old;
+    }
+  return;
+}
+// --------------------------------------------------------------------------
+void PXContour::RemovePoint()
+{
+  if (numpoints==0)
+    return;
+
+  lastpoint->next=realnextpoint;
+  realnextpoint=lastpoint;
+  
+  lastpoint=lastpoint->previous;
+  lastpoint->next=NULL;
+  numpoints=numpoints-1;
+  RemoveGrad();
+
+  /*int rn=-1;
+  if (realnextpoint!=NULL)
+    rn=(int)realnextpoint->next;
+  int pt=-1;
+  if (lastpoint->previous!=NULL)
+    pt=(int)lastpoint->previous->next;
+
+  fprintf(stderr,"Removed (lastpoint=%d, lastpoint->next=%d l->p->n=%d, realnextpoint=%d (r->n=%d) toppoint=%d)\n",
+  lastpoint,lastpoint->next,pt,realnextpoint,rn,toppoint);*/
+
+  
+  closed=0;
+}
+// --------------------------------------------------------------------------
+void PXContour::DeleteAll()
+{
+  if (numpoints<1)
+    return;
+
+  /*  fprintf(stderr,"DeleteA  (lastpoint=%d, lastpoint->next=%d , realnextpoint=%d)\n",
+      lastpoint,lastpoint->next,realnextpoint);*/
+  
+  lastpoint->next=realnextpoint;
+  realnextpoint=toppoint->next;
+  if (realnextpoint!=NULL)
+    realnextpoint->previous=toppoint;
+  toppoint->next=NULL;
+  lastpoint=toppoint;
+  
+  DeleteGrad();
+  closed=0;
+  numpoints=0;
+  /*  fprintf(stderr,"\t Done  (lastpoint=%d, lastpoint->next=%d , realnextpoint=%d toppoint=%d)\n",
+      lastpoint,lastpoint->next,realnextpoint,toppoint);*/
+
+}
+
+// --------------------------------------------------------------------------
+void PXContour::Add(float xx,float yy)
+{
+  lastpoint->x=xx;
+  lastpoint->y=yy;
+  if (realnextpoint==NULL)
+    {
+      lastpoint->next=new PXContourPoint;
+      (lastpoint->next)->previous=lastpoint;
+      (lastpoint->next->next)=NULL;
+      lastpoint=lastpoint->next;
+      lastpoint->x=-1.0;
+      lastpoint->y=-1.0;
+    }
+  else
+    {
+      lastpoint->next=realnextpoint;
+      lastpoint=realnextpoint;
+      realnextpoint=realnextpoint->next;
+      if (realnextpoint!=NULL)
+	realnextpoint->previous=lastpoint;
+      lastpoint->next=NULL;
+    }
+  numpoints++;
+  DeleteGrad();
+  closed=0;
+
+  /*int pt=-1;
+  if (lastpoint->previous!=NULL)
+    pt=(int)lastpoint->previous->next;
+
+  fprintf(stderr,"Added  (lastpoint=%d, lastpoint->next=%d l->p->n=%d, realnextpoint=%d toppoint=%d) %.1f %.1f\n",
+    lastpoint,lastpoint->next,pt,realnextpoint,toppoint,xx,yy);*/
+
+}
+
+// --------------------------------------------------------------------------
+
+void PXContour::AddP(unsigned long xx,unsigned long yy)
+{
+  Add(float(xx),float(yy));
+}
+
+// --------------------------------------------------------------------------
+void PXContour::copypoints(PXContour *oldcontour)
+{
+  DeleteAll();
+  PXContourPoint* temp=oldcontour->gettoppoint(); 
+  for (int i=0;i<oldcontour->getnumpoints();i++)
+      {
+	Add(temp->x,temp->y);
+	temp=temp->next;
+      }
+
+}
+// --------------------------------------------------------------------------
+void PXContour::setcircle(int np,float radius,float x,float y)
+{
+  DeleteAll();
+  for (int j=1;j<=np;j++)
+      {
+	float t=3.141592*2.0*(float(j-1)/float(np));
+	float xx=radius*cos(t)+x;
+	float yy=radius*sin(t)+y;
+	Add(xx,yy);
+      }
+  closed=1;
+}
+// --------------------------------------------------------------------------
+void PXContour::AddGrad(float xx,float yy,float kk)
+{
+  lastgradient->x=xx;
+  lastgradient->y=yy;
+  lastgradient->k=kk;
+  lastgradient->next=new PXContourGrad;
+  (lastgradient->next)->previous=lastgradient;
+  lastgradient=lastgradient->next;
+  lastgradient->next=NULL;
+}
+
+// --------------------------------------------------------------------------
+
+void PXContour::DeleteGrad()
+{
+  cleanupCache();
+  if (gradient>0)
+    {
+      while (lastgradient->previous !=NULL)
+	{
+	  lastgradient=lastgradient->previous;
+	  if (lastgradient->next!=NULL)
+	    {
+	      delete lastgradient->next;
+	      lastgradient->next=NULL;
+	    }
+	}
+      delete topgradient;
+      gradient=0;
+    }
+
+}
+// --------------------------------------------------------------------------
+
+
+void PXContour::RemoveGrad()
+{
+  cleanupCache();
+  if (gradient>0)
+    {
+      if (lastgradient->previous !=NULL)
+	{
+	  lastgradient=lastgradient->previous;
+	  delete lastgradient->next;
+	  lastgradient->next=NULL;
+	}
+    }
+  gradient=0;
+}
+
+// --------------------------------------------------------------------------
+
+int PXContour::Load(const char* fname)
+{
+  FILE* fin;
+  char line[200];
+  status=0;
+  fin=fopen(fname,"r");
+  if (fin!=NULL)
+    {
+      numpoints=0;
+      while ( fgets(line,100,fin)!=NULL ) 
+	  numpoints++;
+      fclose(fin);
+
+      if (numpoints<1)
+	  {
+	    status=0;
+	    return(status);
+	  }
+
+      fin=fopen(fname,"r");
+      float x,y;
+      fscanf(fin,"%f %f", &x,&y);
+
+      if (fabs(x)>10000.0 || fabs(y) > 10000)
+	  {
+	    status=0;
+	    return(0);
+	  }
+      else
+	{
+	  DeleteAll();
+	  Add(x,y);
+	}
+
+      
+      for(int i=1;i<numpoints;i++)
+	{
+	  fscanf(fin,"%f %f",&x,&y);
+	  if (fabs(x)>10000.0 || fabs(y) > 10000)
+	      {
+		status=0;
+		DeleteAll();
+		return(0);
+	      }
+	  Add(x,y);
+	}
+      fclose(fin);
+      status=1;
+      return(1);
+    }
+  status=0;
+  return(0);
+}
+
+// -----------------------------------------------------------------
+int PXContour::Save(const char* fname)
+{
+  FILE* fout;
+  fout=fopen(fname,"w");
+  if (fout!=NULL)
+    {
+      PXContourPoint* pts=gettoppoint();
+      int np=getnumpoints();
+      for (int ib=1;ib<=np;ib++)
+	{
+	  fprintf(fout,"%6.2f  %6.2f \n",pts->x,pts->y);
+	  pts=pts->next;
+	}
+      fclose(fout);
+      return(1);
+    }
+  return(0);
+}
+// -----------------------------------------------------------------
+void PXContour::SaveStream(FILE* fout,int in2d,int opencurve,float z)
+{
+  PXContourPoint* temp=gettoppoint();
+  int np=getnumpoints();
+  for (int ib=1;ib<=np;ib++)
+      {
+	if (in2d)
+	    fprintf(fout,"%6.2f %6.2f \n",temp->x,temp->y);
+	else
+	    fprintf(fout,"%12.8f %12.8f %12.8f\n",temp->x,temp->y,z);
+	temp=temp->next;
+      }
+  if (!opencurve && isclosed())
+      {
+	temp=gettoppoint();
+	/*if (in2d)
+	  fprintf(fout,"%6.2f %6.2f \n",temp->x,temp->y);
+	  else
+	  fprintf(fout,"%12.8f %12.8f %12.8f\n",temp->x,temp->y,z);*/
+      }	
+}
+// -----------------------------------------------------------------
+int PXContour::SaveIGES(const char* filename,float z)
+{
+  int flag=0;
+  FILE* fout=fopen(filename,"w");
+  if (fout!=NULL)
+      {
+	// IGES Start Section
+	// ------------------
+	fprintf(fout,"%72sS      1\n",filename);
+	fprintf(fout,",,,,,,32,38,6,308,15,,1.0D0,1,2HIN,1,0.0D0,13H960202.170136,            G      1\n"
+	        "2.22044604925031D-16,0.0D0,,,9,0,13H960202.170136;                      G      2\n");
+	for (int pass=0;pass<2;pass++)
+	    {
+	      int index=0;
+	      PXContourPoint* temp=gettoppoint();
+	      for (int ib=0;ib<getnumpoints();ib++)
+		  {
+		    index++;
+		    switch(pass)
+			{
+			case 0:
+			  fprintf(fout,"%8d%8d%8d%8d",116,index,2,2);
+			  fprintf(fout,"%8d%8d%8d%8d%08dD%7d\n",0,0,
+				  0,0,0,1);
+			  fprintf(fout,"%8d%8d%8d%8d",116,0,0,1);
+			  fprintf(fout,"%8d%8d%8d%8s%8dD%7d\n",0,0,0,
+				  "POINT",index,2);
+			  break;
+			case 1:
+			  fprintf(fout,"116, %15.4e, %15.4e, %15.4f;          %7dP%7d\n",
+				  temp->x,temp->y,z,(index*2)-1,index);
+			  temp=temp->next;
+			  break;
+			}
+		  }
+	      fprintf(fout,"S%7dG%7dD%7dP%7d                                        T%7d\n",
+		      1,2,index*2,index,1);
+	    }
+	flag=1;
+      }
+  fclose(fout);
+  return flag;
+}
+// -----------------------------------------------------------------
+int PXContour::SaveInteger(const char* fname,int sc)
+{
+  FILE* fout=fopen(fname,"w");
+  int xx,yy;
+  if (fout!=NULL)
+    {
+       // fout << numpoints << "\n";
+      PXContourPoint* pts=toppoint;
+      while (pts->next !=NULL)
+	{
+	    xx=int(pts->x*sc+0.5);
+	    yy=int(pts->y*sc+0.5);
+	    fprintf(fout,"%5d  %5d \n",xx,yy);
+	    pts=pts->next;
+	}
+      fclose(fout);
+      return(1);
+    }
+  return(0);
+}
+
+// -----------------------------------------------------------------
+
+int PXContour::Save4Mesh(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout!=NULL)
+    {
+      PXContourPoint* pts=toppoint;
+      while ((pts->next)->next !=NULL)
+	{
+	  fprintf(fout,"%d %d %d %d \n", 
+		  (int)pts->x,(int)pts->y,
+		  (int)pts->next->x,(int)pts->next->y);
+	  pts=pts->next;
+	}
+
+      // Ensure Closed Curve !! ;
+      
+      fprintf(fout,"%d %d %d %d \n",
+	      (int)pts->x,(int)pts->y,
+	      (int)toppoint->x,(int)toppoint->y);
+      fclose(fout);
+      return(1);
+    }
+  return(0);
+}
+
+// --------------------------------------------------------------------------
+int PXContour::getcardinal(int ii,int np,unsigned char cl)
+{
+  if (cl>0)
+    return (ii % np)*(ii>=0)+ (ii+np)*(ii<0);
+  else
+    return ii*(ii>=0)*(ii<np)+(np-1)*(ii>=np);
+}
+
+// --------------------------------------------------------------------------
+
+void  PXContour::copy2vector(double* x,double *y,int& np)
+{
+  PXContourPoint *pts=toppoint;
+  np=0;
+  while(pts->next !=NULL)
+    { 
+      x[np]=pts->x;
+      y[np]=pts->y;
+      np++;	  
+      pts=pts->next; 
+    }
+  if (closed>0)
+    {  
+      x[np]=x[0];
+      y[np]=y[0];  
+      np++;	
+    }
+}
+
+// -----------------------------------------------------------------
+
+void  PXContour::copy2vector(float* x,float *y,int& np)
+{
+  PXContourPoint *pts=toppoint;
+  np=0;
+  while(pts->next !=NULL)
+    { 
+      x[np]=pts->x;
+      y[np]=pts->y;
+      np++;	  
+      pts=pts->next; 
+    }
+  if (closed>0)
+    {  
+      x[np]=x[0];
+      y[np]=y[0];  
+      np++;	
+    }
+}
+
+// -----------------------------------------------------------------
+
+void PXContour::Smooth(float sigma,int width)
+{
+  cleanupCache();
+  float factor,scale,a,b;
+  unsigned char wasclosed=closed;
+  if (numpoints>2*width)
+    {
+      float* temppointx=new float[numpoints+2];
+      float* temppointy=new float[numpoints+2];
+      int np=0;
+      copy2vector(temppointx,temppointy,np);
+
+      int p=0;
+      DeleteAll();
+      for(int i=0;i<np;i++)
+	{
+	  scale=0.0; a=0.0; b=0.0;
+	  for(int j=-width;j<=width;j++)
+	    {
+	      factor=(1/(sqrt(sigma*2*M_PI))*
+		      exp(-0.5*(pow(float(j),float(2.0)))/pow(sigma,float(2.0))));
+	      scale=scale+factor;
+	      p=getcardinal(i+j,np,wasclosed);
+	      a=a+factor*temppointx[p];
+	      b=b+factor*temppointy[p];
+	    }
+	  Add(a/scale,b/scale);
+	}
+      delete [] temppointx;
+      delete [] temppointy;
+      if (wasclosed>0) 
+	RemovePoint();
+      closedcontour(wasclosed);
+    }
+}
+// --------------------------------------------------------------------------
+void PXContour::Touching()
+{
+  cleanupCache();
+  if (numpoints>1)
+      {
+	unsigned char wasclosed=closed;
+	float *temppointx=new float[numpoints+2];
+	float *temppointy=new float[numpoints+2];
+	
+	int np=0;
+	copy2vector(temppointx,temppointy,np);
+	DeleteAll();
+	
+	float dist1,dist2;
+	for(int i=0;i<(np-1);i++)
+	  {
+	    Add(temppointx[i],temppointy[i]);
+	    dist1=(temppointx[i+1]-temppointx[i]);
+	    dist2=(temppointy[i+1]-temppointy[i]);
+	    
+	    // Check for non-Touching Points i.e |x|>1 and |y|>1
+	    
+	    if ( fabs(dist2)>1.0 || fabs(dist1)>1.0)
+	      {
+		if (fabs(dist2)>fabs(dist1))
+		  {
+		    int dt=int(fabs(dist2)+0.9999);
+		    for(int xx=1;xx<dt;xx++)
+		      {
+			float fr=(float(xx)/float(dt));
+			float spx=fr*dist1;
+			float spy=fr*dist2;
+			Add(temppointx[i]+spx,temppointy[i]+spy);
+		      }
+		  }
+		else
+		  {
+		    int dt=int(fabs(dist1)+0.9999);
+		    for(int yy=1;yy<dt;yy++)
+		      {
+			float fr=(float(yy)/float(dt));
+			float spy=fr*dist2;
+			float spx=fr*dist1;
+			Add(temppointx[i]+spx,temppointy[i]+spy);
+		      }
+		  }
+	      }
+	    else
+	      if (dist1<1.0 && dist2<1.0)
+		i=i+1;  // Skip next Point -- Same as this one;
+	  }
+	
+	// Get Last-Point to be added
+	float x0=lastpoint->previous->x;
+	float y0=lastpoint->previous->y;
+	
+	dist1=fabs(temppointx[np-1]-x0);
+	dist2=fabs(temppointy[np-1]-y0);
+	
+	if (dist1>=1.0 || dist2>=1.0)
+	    Add(temppointx[np-1],temppointy[np-1]);
+	
+	if (wasclosed>0)
+	    RemovePoint();
+	closedcontour(wasclosed);
+	
+	delete [] temppointx;
+	delete [] temppointy;
+      }
+}
+
+
+// --------------------------------------------------------------------------
+void PXContour::Sample(int maxratio)
+{
+  Equisample((int)(numpoints/maxratio));
+}
+
+// --------------------------------------------------------------------------
+void PXContour::Subsample(int maxratio)
+{
+
+  //  Alternatively use equisample aka
+  //  Equisample((int)(numpoints*maxratio));
+  //  return;
+  cleanupCache();
+  float ratio1,ratio2,a,b;
+  int np=numpoints;
+  unsigned char wasclosed;
+  
+  wasclosed=closed;
+  
+  if (numpoints>0)
+      {
+	if (maxratio>1)
+	    {
+	      float *temppointx=new float[maxratio*numpoints+1];
+	      float *temppointy=new float[maxratio*numpoints+1];
+	      PXContourPoint *pts=toppoint;
+	      int i=0;
+	      while(pts->next !=NULL)
+		  {
+		    temppointx[i]=pts->x;
+		    temppointy[i]=pts->y;
+		    i++;
+		    pts=pts->next;
+		  }
+	      if (wasclosed>0)
+		  {
+		    numpoints++;
+		    temppointx[numpoints-1]=temppointx[0];
+		    temppointy[numpoints-1]=temppointy[0];
+		  }
+	      DeleteAll();
+	      
+	      for(i=0;i<(np-1);i++)
+		  for(int j=0;j<maxratio;j++)
+		      {
+			ratio2=((float)j)/((float)maxratio);
+			ratio1=1-ratio2;
+			a=(((float)temppointx[i])  *ratio1+
+			   ((float)temppointx[i+1])*ratio2);
+			b=(((float)temppointy[i])  *ratio1+
+			   ((float)temppointy[i+1])*ratio2);
+			//newindex=i*maxratio+j;
+			Add(a,b);
+		      }
+	      Add(temppointx[np-1],temppointy[np-1]);
+	      np=(np-1)*maxratio+1;
+	      if (wasclosed>0) 
+		  {
+		    RemovePoint();
+		    closedcontour(1);
+		  }
+	      
+	      delete [] temppointx;
+	      delete [] temppointy;
+	    }
+      }
+  
+}
+
+// --------------------------------------------------------------------------
+
+void PXContour::Equisample(int npoints)
+{
+  if (npoints>1)
+    {
+      float np=(float)npoints;
+      float l=getcontourlength();
+      float sp=l/np;
+      Equispace(sp);
+    }
+}
+
+// --------------------------------------------------------------------------
+
+void PXContour::Equispace(float spacing)
+{
+  cleanupCache();
+  if (numpoints<2)
+    return;
+  
+  float sz=getcontourlength()/spacing;
+  int ss=int(sz)+1;
+
+  if (ss<4)
+      {
+	ss=4;
+	spacing=getcontourlength()/float(ss-1);
+      }
+
+  if (spacing<0.01)
+      return;
+
+  ss+=5;
+
+  float *temppointx=new float[ss];
+  float *temppointy=new float[ss];
+  
+  unsigned char wasclosed=0;
+  int i=0,np=0;
+  float x1=0.0,x2=0.0,y1=0.0,y2=0.0;
+  float x0=0.0,y0=0.0,segment=0.0,part=0.0,ratio=0.0;
+      
+  PXContourPoint *pts=gettoppoint();
+  
+  x0=pts->x; y0=pts->y;
+  x1=x0;     y1=y0;
+  pts=pts->next;
+  temppointx[i]=x0;
+  temppointy[i]=y0;
+  
+  while(pts->next !=NULL)
+    {
+      x2=pts->x;
+      y2=pts->y;
+      part=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
+      segment=segment+part;
+      while (segment>=spacing)
+	{
+	  i++;
+	  ratio=1.0-(segment-spacing)/part;
+	  segment=segment-spacing;
+	  temppointx[i]=(1.0-ratio)*x1+ratio*x2;
+	  temppointy[i]=(1.0-ratio)*y1+ratio*y2;
+	}
+      x1=x2;
+      y1=y2;
+      pts=pts->next;
+    }
+  
+  if (closed>0)
+    {
+      wasclosed=1;
+      part=sqrt((x0-x2)*(x0-x2)+(y0-y2)*(y0-y2));
+      segment=segment+part;
+      while (segment>=spacing)
+	{
+	  i++;
+	  ratio=1.0-(segment-spacing)/part;
+	  segment=segment-spacing;
+	  temppointx[i]=(1.0-ratio)*x2+ratio*x0;
+	  temppointy[i]=(1.0-ratio)*y2+ratio*y0;
+	}
+    }
+
+  if (i>=ss)
+    fprintf(stderr,"*****\n Error %d %d\n",i,ss);
+
+  if (temppointx[i]==x0 && temppointy[i]==y0)
+    i=i-1;
+  
+  np=i;
+  DeleteAll();
+  for(i=0;i<=np;i++)
+    Add(temppointx[i],temppointy[i]);
+  
+  delete [] temppointx;
+  delete [] temppointy;
+  closedcontour(wasclosed);
+}
+// --------------------------------------------------------------------------
+void PXContour::CalculateGradients(int scale)
+{
+  if (numpoints>2*scale+1)
+      {
+	//    cerr << "calculating gradient .. ";
+	// Copy points out
+	//-----------------
+	unsigned char wasclosed=closed;
+	double *pointx=new double[numpoints+2];
+	double *pointy=new double[numpoints+2];
+	
+	int np=0;
+	copy2vector(pointx,pointy,np);
+	if (closed>0) np=np-1;  
+	
+	// cerr << "Finding orientation\n";
+	
+	// find Orientation by cross product
+	//----------------------------------
+	
+	double v1x=pointx[np/3]-pointx[0];
+	double v1y=pointy[np/3]-pointy[0];
+	double v2x=pointx[2*np/3]-pointx[np/3];
+	double v2y=pointy[2*np/3]-pointy[np/3];
+	double zz=(v1x*v2y-v2x*v1y);
+	double anticlockwise=-1.0;
+	if (zz>0.0) anticlockwise=1.0;
+	//    cerr << "anticlockwise " << anticlockwise << "\n";
+	
+	// Estimate number of neighbours scale =1,2,3
+	// -----------------------------
+	if (scale<1) scale=1;
+	if (scale>5) scale=5;
+	int neighbours = scale;
+	int vectsize  = 2*scale+1;
+	
+	// cerr << "Preparing to add Gradients\n";
+	
+	// Prepare to Add Gradients
+	//--------------------------
+	DeleteGrad();
+	gradient=1;
+	lastgradient=new PXContourGrad;
+	lastgradient->next=NULL;
+	lastgradient->previous=NULL;
+	topgradient=lastgradient;
+	
+	// cerr << "Preparing Least Square Matrices \n";
+	
+	// Prepare Least Square Matrices
+	// ------------------------------
+	
+	double **A     = dmatrix(1, vectsize, 1, 3);
+	double **AtA   = dmatrix(1, 3, 1, 3);
+	
+	double *tempx  =  dvector(1,vectsize);
+	double *tempy  =  dvector(1,vectsize);
+	double *aty    =  dvector(1,3);
+	int   *indx   =   ivector(1,3);
+	
+	// First Calculate Gradients for internal
+	// Find  First Estimate of Normal -- fit quadratic
+	// -----------------------------------------------
+	
+	double tx,ty,nx,ny,mag;
+	
+	int k1,k_1;
+	for(int i=0;i<np;i++)
+	    {
+	      k_1=getcardinal(i-1,np,wasclosed);
+	      k1=getcardinal(i+1,np,wasclosed);
+	      tx=pointx[k1]-pointx[k_1];
+	      ty=pointy[k1]-pointy[k_1];
+	      mag=sqrt(tx*tx+ty*ty);
+	      if (mag>0.0)
+		  {
+		    tx =   tx/mag;
+		    ty =   ty/mag;
+		  }
+	      nx=-ty;
+	      ny= tx;
+	      
+	      
+	      /* transform the neighbor points, such the     */
+	      /* the k point becomes the origin,             */
+	      /* the normal direction N becomes the y-axis,  */
+	      /* the tangent directions T becomes the x-axis */
+	      
+	      double xx,yy;
+	      int k,count=1;
+	      for(int j=-neighbours ; j<=neighbours; j++)
+		  {
+		    k=getcardinal(i+j,np,wasclosed);
+		    xx = pointx[k] - pointx[i];
+		    yy = pointy[k] - pointy[i];
+		    tempx[count]= xx * tx + yy * ty;
+		    tempy[count]= xx * nx + yy * ny;
+		    count++;
+		    
+		  }
+	      
+	      // Effectively Solve A'Ax=A'y ;
+	      // Fit the local quadric curve using least square method 
+	      // Step 1 == Form A
+	      
+	      for(int l=1; l<=vectsize; l++)
+		  {
+		    A[l][1] = 1.0;
+		    A[l][2] = tempx[l];
+		    A[l][3] = tempx[l]*tempx[l];
+		  }
+	      
+	      // Step 2 Form A'A and form LU decomposition
+	      
+	      for (int mrow=1;mrow<=3;mrow++)
+		  for (int mcol=1;mcol<=3;mcol++)
+		      {
+			AtA[mrow][mcol]=0.0;
+			for (int mdummy=1;mdummy<=vectsize;mdummy++)
+			    {
+			      AtA[mrow][mcol]=AtA[mrow][mcol]+
+				  A[mdummy][mrow]*A[mdummy][mcol];
+			    }
+		      }
+	      
+	      double det,curv;
+	      int singular;
+	      ludcmp(AtA,3,indx,&det,singular);
+	      
+	      if(singular!=1)
+		  {
+		    // Step 3 -- Form RHS A'y
+		    
+		    for (int vrow=1;vrow<=3;vrow++)
+			{
+			  aty[vrow]=0.0;
+			  for (int vdummy=1;vdummy<=vectsize;vdummy++)
+			      aty[vrow]=aty[vrow]+A[vdummy][vrow]*tempy[vdummy];
+			}
+		    
+		    lubksb(AtA,3,indx,aty);
+		    
+		    // compute the curvatures -- at point (0,0) 
+		    double xt  = 1.0;
+		    double yt  = aty[2];
+		    double ytt = aty[3] * 2.0; 
+		    
+		    curv= sqrt( (xt*xt+yt*yt)*(xt*xt+yt*yt)*(xt*xt+yt*yt) );
+		    if (fabs(curv)>0.01)
+			curv= xt*ytt / curv;
+		    else
+			{
+			  curv=1e+5;
+			  // cerr << "big \n";
+			}
+		    
+		  }
+	      else curv=0.0;
+	      
+	      AddGrad(nx*anticlockwise,ny*anticlockwise,curv);
+	    }
+	//    cerr << "...........done \n";
+	
+	free_dmatrix(A,1, vectsize, 1, 3);
+	free_dmatrix(AtA,1, 3, 1, 3);
+	free_dvector(tempx,1,vectsize);
+	free_dvector(tempy,1,vectsize);
+	free_dvector(aty,1,3);
+	free_ivector(indx,1,3);
+	delete [] pointx;
+	delete [] pointy;
+	
+	gradient=1;
+      }
+}
+
+// ***********************************************************************
+void PXContour::AddSpline(double** x,int n,int np)
+{
+  cleanupCache();
+  int i,j,k;
+  double** z=dmatrix(1,n,1,2);
+  double** R=dmatrix(1,2,1,2);
+  
+  int flag=-1;
+  double theta=0.0;
+  // Find theta which puts these in increasing order
+  // First guess is tangent of line joining first and last
+
+  while (flag== -1 )
+    {
+      R[1][1]=cos(theta); R[1][2]=-sin(theta);
+      R[2][1]=sin(theta); R[2][2]= cos(theta);
+
+      for(int pnt=1;pnt<=n;pnt++)
+	{
+	  z[pnt][1]=R[1][1]*x[pnt][1]+R[1][2]*x[pnt][2];
+	  z[pnt][2]=R[2][1]*x[pnt][1]+R[2][2]*x[pnt][2];
+	}
+
+      flag=1;
+      double r1=z[2][1]-z[1][1];
+      for(i=2;i<n;i++)
+	if ((z[i+1][1]-z[i][1])*r1 <= 0) flag=-1;
+      
+      if (theta==0.0) 
+	theta=1.51;
+      else 
+	theta=theta+0.5;
+    }
+
+  double** A=dmatrix(1,n,1,n);
+  double*  b=dvector(1,3);
+
+  for(i=1;i<=n;i++)
+    {
+      for(j=1;j<=n;j++)
+	A[i][j]=pow(z[i][1],j-1.0);
+      b[i]=z[i][2];
+    }
+  
+  double det;
+  int singular,*indx=ivector(1,n);
+  ludcmp(A,n,indx,&det,singular);
+  lubksb(A,n,indx,b);
+
+  double xn[3],z1,z2,gap;  
+  for(i=1;i<n;i++)
+    {
+      gap=z[i+1][1]-z[i][1];
+      for (k=0;k<=np;k++)
+	{
+	  z1=z[i][1]+(float(k)/float(np+1.0))*gap;
+	  z2=0.0;
+	  for (j=1;j<=n;j++)
+	    z2=z2+pow(z1,j-1.0)*b[j];
+
+	  xn[1]=R[1][1]*z1+R[2][1]*z2;
+	  xn[2]=R[1][2]*z1+R[2][2]*z2;
+	  Add((float)xn[1],(float)xn[2]);      
+	}
+      Add((float)x[i+1][1],(float)x[i+1][2]);      
+    }
+
+  
+  free_ivector(indx,1,n);      free_dmatrix(A,1,n,1,n);
+  free_dvector(b,1,n);         free_dmatrix(z,1,n,1,2);    
+  free_dmatrix(R,1,2,1,2);     
+}
+
+
+// ***********************************************************************
+//  Routines adapted from Francois' code
+// ***********************************************************************
+
+int PXContour::Intersect (float x1,float y1, 
+			  float x2,float y2, 
+			  float x,float y)
+{
+  float xint;			// co-ordinate of the intersection 
+  
+  int intersect=0;	       	// 1 if line l intersects the edge      
+  int ToTheLeft=0;	       	// 1 if the intersection is on the left 
+				//      of z = (x, y)                           
+
+  if (y1 < y2) 
+      {
+	if ((y1 <= y)  && (y  <  y2)) 
+	    {	
+	      // l intersects edge 
+	      intersect = 1;
+	      xint = x1 + (y - y1) * (x2 - x1) /(y2 - y1);
+	      ToTheLeft = (xint <= x);
+	    }
+	else 
+	    intersect = 0;
+      }
+  else 
+      if (y2 < y1) 
+	  {
+	    if ((y2 <= y) && (y  <  y1)) 
+		{
+		  // l intersects edge 
+		  intersect = 1;
+		  xint = x1 + (y - y1) * (x2 - x1) /(y2 - y1);
+		  ToTheLeft = (xint <= x);
+		}
+	    else 
+		intersect = 0;
+	  }
+      else				// horizontal edge   
+	  intersect = 0;
+  
+  return ((intersect) && (ToTheLeft));
+}
+    
+/*
+ *--------------------------------------------------------------------------
+ *_Subject : Test wether a point z = (x,y) is internal to a simple N-gon.
+ *           
+ *_Author: Francois G. Meyer 
+ *_History  :                 Initial Key-In
+ *
+ *_Reference : Computational Geometry, Preparata and Shamos
+ *--------------------------------------------------------------------------
+ */
+int PXContour::IsInside(float testpointx,float testpointy)
+{
+  int  count=0;
+
+  PXContourPoint* top=toppoint;
+  float x2 = top->x;
+  float y2 = top->y;
+  
+  PXContourPoint* pts=top->next;
+
+  while (pts->next !=NULL)
+      {
+	float x1 = x2;
+	float y1 = y2;
+	x2 = pts->x;
+	y2 = pts->y;
+	if (Intersect (x1, y1, x2, y2, testpointx, testpointy))
+	    count ++;
+	pts=pts->next;
+      }
+
+  if (Intersect (x2, y2, top->x,top->y,testpointx, testpointy))
+      count ++;
+
+  int isodd=count%2;
+  return isodd;
+}
+
+int PXContour::IsInside(float testpointx,float testpointy,
+			float *pointx,float* pointy,
+			int numberofpoints)
+{
+  
+  int  index=0,count=0;
+  float x1, y1,x2, y2;
+
+  x2 = pointx[index];
+  y2 = pointy[index];
+
+  while (index<numberofpoints) 
+      {
+	index++;
+	x1 = x2;
+	y1 = y2;
+	x2 = pointx [index];
+	y2 = pointy [index];
+
+	if (Intersect (x1, y1, x2, y2, testpointx, testpointy))
+	    count ++;
+      }
+
+  int isodd=count%2;
+  return isodd;
+}
+
+// ***********************************************************************
+int PXContour::ensureAnticlockwise()
+{
+  return setDirection(1);
+}
+
+// ***********************************************************************
+int PXContour::ensureClockwise()
+{
+  return setDirection(-1);
+}
+// ***********************************************************************
+int PXContour::setDirection(int dir)
+{
+  int  flag=0;
+  if (numpoints>2)
+      {
+	int np=numpoints;
+	unsigned char wasclosed=closed;
+	float px0,px1,px2,py0,py1,py2;
+
+	PXContourPoint* pts=gettoppoint();
+	px0=pts->x; py0=pts->y;
+	
+	int i;
+	for(i=0;i<np/3;i++)
+	    pts=pts->next;
+	px1=pts->x; py1=pts->y;
+
+	for(i=0;i<np/3;i++)
+	    pts=pts->next;
+	px2=pts->x; py2=pts->y;
+
+	// Find Orientation by cross product
+	//----------------------------------
+	
+	float v1x=px1-px0;
+	float v1y=py1-py0;
+	float v2x=px2-px1;
+	float v2y=py2-py1;
+	float zz=(v1x*v2y-v2x*v1y);
+
+	int flag=0;
+	if (dir>0 && zz<0.0)
+	    flag=1;
+	if (dir<=0 && zz>0.0) 
+	    flag=1;
+
+	if (flag)
+	    {
+	      int np;
+	      double *pointx=new double[numpoints+2];
+	      double *pointy=new double[numpoints+2];
+	      copy2vector(pointx,pointy,np);
+	      if (closed>0) 
+		np=np-1;  
+	      DeleteAll();
+	      for (int i=np-1;i>=0;i=i-1)
+		Add(pointx[i],pointy[i]);
+	      delete [] pointx;
+	      delete [] pointy;
+	      closed=wasclosed;
+	      cleanupCache();
+	    }
+      }
+  return flag;
+}
+// ------------------------------------------------------------------------------------
+void PXContour::cleanupCache()
+{
+  if (hascache())
+    {
+      delete [] px;
+      delete [] py;
+      contourhascache=0;
+    }
+  
+}
+// ------------------------------------------------------------------------------------
+int PXContour::getcyclicindex(int pt,int np)
+{
+  while (pt<0)
+      pt=pt+np;
+  while (pt>=np)
+      pt=pt-np;
+  return pt;
+}
+// ------------------------------------------------------------------------------------
+void PXContour::generateCache(int forceClosed)
+{
+  if (forceClosed)
+      setclosed(1);
+
+  cleanupCache();
+
+  px=new float[numpoints+1];
+  py=new float[numpoints+1];
+  int np;
+  copy2vector(px,py,np);
+  contourhascache=1;
+}
+// ------------------------------------------------------------------------------------
+float PXContour::findnearestneighbour(float&x,float& y,float dt,int )
+{
+  if (dt<1.0 && !hascache())
+      generateCache();
+      
+  int np=getnumpoints(),index=0;
+  float x0=0,y0=0,mindist=10000000.0;
+
+  int step=int(np/20)+1;
+
+  // One pass at 20 points /contour
+  for (int ib=0;ib<np;ib+=step)
+      {
+	float dist=pow(px[ib]-x,float(2.0))+pow(py[ib]-y,float(2.0));
+	if (dist<mindist)
+	    {
+	      index=ib;
+	      x0=px[ib];
+	      y0=py[ib];
+	      mindist=dist;
+	    }
+
+      }
+
+  // Second Pass at pixel-resolution around last solution
+  if (step>1)
+      {
+	for (int ib=index-step*2;ib<index+step*2;ib++)
+	    {
+	      int ia=getcyclicindex(ib,np);
+	      float dist=pow(px[ia]-x,float(2.0))+pow(py[ia]-y,float(2.0));
+	      if (dist<mindist)
+		  {
+		    index=ia;
+		    x0=px[ia];
+		    y0=py[ia];
+		    mindist=dist;
+		  }
+	    }
+      }
+
+  // If needed do subpixel also
+  if (dt>0.0 && dt<1.0)
+      {
+	float ds=0.5;
+	while (ds>dt)
+	    ds=0.5*ds;
+
+	for (int st=0;st<=1;st++)
+	    {
+	      float tx0=px[getcyclicindex(index-1+st,np)];
+	      float ty0=py[getcyclicindex(index-1+st,np)];
+	      float tx1=px[getcyclicindex(index+st  ,np)];
+	      float ty1=py[getcyclicindex(index+st  ,np)];
+
+	      for (float s=ds;s<1.0;s+=ds)
+		  {
+		    float tx=s*tx1+(1-s)*tx0;
+		    float ty=s*ty1+(1-s)*ty0;
+		    float dist=pow(tx-x,float(2.0))+pow(ty-y,float(2.0));
+
+		    if (dist<mindist)
+			{
+			  x0=tx;
+			  y0=ty;
+			  mindist=dist;
+			}
+		  }
+	    }
+	
+      }
+  x=x0;
+  y=y0;
+  return sqrt(mindist);
+}
+// ------------------------------------------------------------------------------------
+void  PXContour::nonShrinkSmooth(float sigma,int iterations,
+				 float alpha,float beta,int width)
+
+{
+  iterations=Irange(iterations,1,1000);
+  sigma=Frange(sigma,0.0,10.0);
+  int wd=int(sigma*2.0+1);
+  if (wd<3) wd=3;
+  int wd2=19;
+  if (wd>wd2) wd2=wd+2;
+  width=Irange(width,wd,wd2);
+  cleanupCache();
+  float factor,scale,a,b;
+  unsigned char wasclosed=closed;
+  if (numpoints>2*width)
+    {
+      float* temppointx=new float[numpoints+2];
+      float* temppointy=new float[numpoints+2];
+      for (int iter=0;iter<iterations;iter++)
+	  {
+	    for(int pass=0;pass<=1;pass++)
+		{
+		  int np=0;
+		  copy2vector(temppointx,temppointy,np);
+		  int p=0;
+		  DeleteAll();
+		  for(int i=0;i<np;i++)
+		      {
+			scale=0.0; a=0.0; b=0.0;
+			for(int j=-width;j<=width;j++)
+			    {
+			      factor=(1/(sqrt(sigma*2*M_PI))*
+				      exp(-0.5*(pow(float(j),float(2.0)))/pow(sigma,float(2.0))));
+			      scale=scale+factor;
+			      p=getcardinal(i+j,np,wasclosed);
+			      a=a+factor*temppointx[p];
+			      b=b+factor*temppointy[p];
+			    }
+			float newx=a/scale; 	  float newy=b/scale;
+			float oldx=temppointx[i]; float oldy=temppointy[i];
+			if (pass==0)
+			    Add((1-alpha)*oldx+alpha*newx,(1-alpha)*oldy+alpha*newy);
+			else
+			    Add((1-beta)*oldx+beta*newx,(1-beta)*oldy+beta*newy);
+		      }
+		}
+	  }
+      delete [] temppointx;
+      delete [] temppointy;
+      if (wasclosed>0) 
+	  RemovePoint();
+      closedcontour(wasclosed);
+    }
+}
+// --------------------------------------------------------------------------
+int  PXContour::saveContourPair(const char* fname,PXContour* cntr1,PXContour* cntr2)
+{
+  if (cntr1->getnumpoints() !=cntr2->getnumpoints())
+      return 0;
+  FILE* fout=fopen(fname,"w");
+  if (fout)
+      {
+	PXContourPoint *pts2=cntr2->gettoppoint();
+	while(pts2->next !=NULL)
+	    { 
+	      fprintf(fout,"%6.3f %6.3f\n",pts2->x,pts2->y);
+	      pts2=pts2->next; 
+	    }
+	pts2=cntr2->gettoppoint();
+	fprintf(fout,"%6.3f %6.3f\n",pts2->x,pts2->y);
+	PXContourPoint *pts1=cntr1->gettoppoint();
+	while(pts2->next !=NULL)
+	    {
+	      fprintf(fout,"%6.3f %6.3f\n",pts1->x,pts1->y);
+	      if (pts1!=cntr1->gettoppoint())
+		  {
+		    fprintf(fout,"%6.3f %6.3f\n",pts2->x,pts2->y);
+		    fprintf(fout,"%6.3f %6.3f\n",pts1->x,pts1->y);
+		  }
+	      pts2=pts2->next; 
+	      pts1=pts1->next;
+	    }
+	pts1=cntr1->gettoppoint();
+	fprintf(fout,"%6.3f %6.3f\n",pts1->x,pts1->y);
+	fclose(fout);
+	return 1;
+      }
+  return 0;
+}
+// --------------------------------------------------------------------------
+int  PXContour::saveContourPair(const char* fname,
+				float* px1,float* py1,
+				float* px2,float* py2,
+				int np1,int np2,
+				int* used,int* corr)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout)
+      {
+	int done=0,deb=0,link=0;
+	while(deb<np1 && done==0)
+	    {
+	      if (used[deb]==1)
+		  done=1;
+	      else
+		  deb++;
+	    }
+	for (int j=0;j<=np2;j++)
+	    {
+	      int ind=Icyclic(corr[deb]+j,np2);
+	      fprintf(fout,"%6.3f %6.3f %d\n",px2[ind],py2[ind],ind);
+	    }
+	for (int i=0;i<=np1;i++)
+	    {
+	      int ind=Icyclic(deb+i,np1);
+	      fprintf(fout,"%6.3f %6.3f %d\n",px1[ind],py1[ind],ind);
+	      if (used[ind]==1)
+		  {
+		    link++;
+		    fprintf(fout,"%6.3f %6.3f %d\n",px2[corr[ind]],py2[corr[ind]],corr[ind]);
+		    fprintf(fout,"%6.3f %6.3f %d\n",px1[ind],py1[ind],ind);
+		  }
+	    }
+//	fprintf(stderr,"Saved in %s (links=%d)\n",fname,link);
+	fclose(fout);
+	return 1;
+      }
+  return 0;
+}
+// --------------------------------------------------------------------------
+int PXContour::cyclicDistance(int p1,int p2,int np)
+{
+  int half=np/2;
+  int dist=0;
+  if (abs(p1-p2)<half)
+      {
+	dist=p1-p2;
+      }
+  else
+      {
+	if (p1>p2)
+	    dist=p2+np-p1;
+	else
+	    dist=p1+np-p2;
+      }
+
+  return abs(dist);  
+}
+// --------------------------------------------------------------------------
+PXContour*  PXContour::mapContours(PXContour* cntr1,PXContour* cntr2,int resample)
+{
+  /*static int count_map=0;
+  ++count_map;
+  fprintf(stderr,"\n Beginning Points =%d (%.1f),%d(%.1f) count=%d\n",
+	  cntr1->getnumpoints(),
+	  cntr1->getcontourlength(),
+	  cntr2->getnumpoints(),
+	  cntr2->getcontourlength(),
+	  count_map);*/
+  int debug=0;
+  /*  PXContour* cntr2=new PXContour(cnt2);*/
+
+  if (resample)
+    {
+      cntr2->setclosed(1);
+      int np2=cntr1->getnumpoints()*8;
+      if (np2>3998)
+	np2=3998;
+	
+      cntr2->Equisample(np2);
+      cntr2->Smooth();
+    }
+
+
+  static float px1[4000], py1[4000], px2[4000], py2[4000];
+  int np1=cntr1->getnumpoints();
+  int np2=cntr2->getnumpoints();
+
+  if (np1 >3999 || np2>3999)
+    {
+      fprintf(stderr,"Can only handle contours with 4000 points or less\n");
+      exit(1);
+    }
+
+  static int corr[4000], used[4000], fixed[4000];
+  int np0;
+  cntr2->setclosed(1);
+  cntr1->setclosed(1);
+  cntr1->copy2vector(px1,py1,np0);
+  cntr2->copy2vector(px2,py2,np0);
+    
+  // Pass 1 --- Find all points that have symmetric neighbours
+  // ---------------------------------------------------------
+  int numgood=0;
+  for (int p1=0;p1<np1;p1++)
+      {
+	used[p1]=0;
+	fixed[p1]=0;
+	corr[p1]=-1;
+	float mindist=10000000.0;
+	int   besti=0;
+	for (int i=0;i<np2;i++)
+	    {
+	      float dist=Fsqdist(px1[p1],py1[p1],0.0,px2[i],py2[i],0.0);
+	      if (dist<mindist)
+		  {
+		    mindist=dist;
+		    besti=i;
+		  }
+	    }
+
+	//mindist=10000000.0;
+	int bestj=p1;
+	for (int j=0;j<np1;j++)
+	    {
+	      float dist=Fsqdist(px1[j],py1[j],0.0,px2[besti],py2[besti],0.0);
+	      if (dist<mindist)
+		{
+		  bestj=j;
+		  mindist=dist;
+		}
+	    }
+	
+	if (bestj==p1)
+	    {
+	      used[p1]=1;
+	      fixed[p1]=1;
+	      corr[p1]=besti;
+	      ++numgood;
+	    }
+      }
+
+  if (debug==1)
+      PXContour::saveContourPair("part0.cnt",px1,py1,px2,py2,np1,np2,used,corr);
+
+
+  if (numgood<2)
+    {
+      for (int i=0;i<np1;i++)
+	fprintf(stderr,"i=%d/%d px1[%d]=%.2f py1[%d]=%.2f\n",i,np1,i,px1[i],i,py1[i]);
+      for (int j=0;j<np2;j++)
+	fprintf(stderr,"j=%d/%d px1[%d]=%.2f py1[%d]=%.2f\n",j,np2,j,px2[j],j,py2[j]);
+    }
+
+  // Pass 2: Fill in by averaging 
+  int notdone=1;
+  while (notdone==1)
+      {
+	notdone=0; 
+	int p1;
+	for (p1=0;p1<np1;p1++)
+	    {
+	      if (used[p1]==0)
+		  {
+		    int p0=Icyclic(p1-1,np1);
+		    while (used[p0]==0)
+			p0=Icyclic(p0-1,np1);
+		    int p2=Icyclic(p1+1,np1);
+		    while (used[p2]==0)
+			p2=Icyclic(p2+1,np1);
+
+		    int dist0=PXContour::cyclicDistance(p0,p1,np1);
+		    int dist2=PXContour::cyclicDistance(p1,p2,np1);
+		    float frac=(float(dist0)/float(dist0+dist2));
+
+		    int c1=0;
+		    if (corr[p2]<corr[p0])
+			c1=int(float(corr[p2]+np2-corr[p0])*frac+corr[p0]);
+		    else
+			c1=int(float(corr[p2]-corr[p0])*frac+corr[p0]);
+		    corr[p1]=Icyclic(c1,np2);
+		  }
+	    }
+	for (p1=0;p1<np1;p1++)
+	    {
+	      if (corr[p1]>=0)
+		  used[p1]=1;
+	    }
+      }
+
+  if (debug==1)
+      PXContour::saveContourPair("part1.cnt",px1,py1,px2,py2,np1,np2,used,corr);
+
+  // Pass 3: Smoothing Iterations
+  // ----------------------------
+
+  int nummoved=1,iter=1;
+  while(nummoved>0 && iter<500)
+      {
+	nummoved=0;
+	for (int p=0;p<np1;p++)
+	    {
+	      int p1=p;
+	      if (fixed[p1]==0 || iter>0)
+		  {
+		    int bestdist=1000000000;
+		    int shift=0;
+		    for (int s=0;s<=2;s++)
+			{
+			  int sh=s;
+			  if (s==2)
+			      sh=-1;
+			  int maxd=0,mind=100000000;
+			  int ptest=Icyclic(corr[p1]+sh,np2);
+			  for (int k=-1;k<=1;k+=2)
+			      {
+				int p2=Icyclic(p1+k,np1);
+				int dist=PXContour::cyclicDistance(corr[p2],ptest,np2);
+				maxd=Imax(maxd,dist);
+				mind=Imin(mind,dist);
+			      }
+			  if (maxd<bestdist)
+			      {
+				bestdist=maxd;
+				shift=sh;
+			      }
+			}
+		    if (shift!=0)
+			{
+			  nummoved++;
+			  corr[p1]=Icyclic(corr[p1]+shift,np2);
+			}
+		  }
+	    }
+	
+	//for (int p1=0;p1<np1;p1++)
+	  //  corr[p1]=Icyclic(corr[p1]+shifts[p1],np2);
+
+	if (debug==2)
+	    {
+	      fprintf(stderr,"Smoothing Iteration %d moved=%d\n",iter,nummoved);
+	      char line[100];
+	      sprintf(line,"iter.%02d",iter);
+	      PXContour::saveContourPair(line,px1,py1,px2,py2,np1,np2,used,corr);
+	    }
+	iter++;
+      }
+  if (debug)
+    fprintf(stderr,"Iterations %d\n",iter);
+
+
+  // Cleanup
+  // -------
+  PXContour* out=new PXContour();
+  for (int i=0;i<np1;i++)
+      out->Add(px2[corr[i]],py2[corr[i]]);
+      
+  if (debug==1)
+      out->Save("final.cnt");
+
+
+  /*  delete [] px1;  delete [] px2;  delete [] py1;  delete [] py1; 
+      delete [] corr; delete [] used; delete [] fixed;*/
+
+  //cnt2->DeleteAll();
+  //cnt2->copypoints(cntr2);
+  //delete cntr2;
+  return out;
+
+}
+// ***********************************************************************
+//
+//      Contour Statistics 
+//
+// ***********************************************************************
+float PXContour::getarea()
+{
+  if (numpoints<3)
+      return 0.0;
+
+  if (isclosed()>0)
+      {
+	float area=0.0;
+	PXContourPoint* temp=toppoint;
+	
+	//	2 A( P ) = sum_{i=0}^{n-1} (x_i y_{i+1} - y_i x_{i+1}).
+
+	for (int i=0;i<numpoints;i++)
+	    {
+	      float xi=temp->x;
+	      float yi=temp->y;
+	      float xip,yip;
+	      if (i!=numpoints-1)
+		  {
+		    xip=temp->next->x;
+		    yip=temp->next->y;
+		  }
+	      else
+		  {
+		    xip=toppoint->x;
+		    yip=toppoint->y;
+		  }
+	      area+= xi*yip-yi*xip;
+	      temp=temp->next;
+	    }
+	return fabs(area*0.5);
+      }
+  else
+      return -1.0;
+  
+}
+// ***********************************************************************
+void PXContour::getcentroid(float& x,float& y)
+{
+  int np=0;
+  float sumx=0.0,sumy=0.0;
+  PXContourPoint* pts=toppoint;
+  while (pts->next !=NULL)
+      {
+	sumx+=pts->x;
+	sumy+=pts->y;
+	np++;
+	pts=pts->next;
+      }
+  x=sumx/float(np);
+  y=sumy/float(np);
+}
+// ***********************************************************************
+void PXContour::getextent(float &xmin,float& xmax,float& ymin,float& ymax)
+{
+  PXContourPoint* pts=toppoint;
+  xmin=pts->x;  xmax=pts->x;
+  ymin=pts->y;  ymax=pts->y;
+  //  fprintf(stderr,"pt (%.2f \t %>2f)\n",pts->x,pts->y);
+  pts=pts->next;
+  while (pts->next !=NULL)
+      {
+	xmin=Fmin(pts->x,xmin); 	ymin=Fmin(pts->y,ymin);
+	xmax=Fmax(pts->x,xmax); 	ymax=Fmax(pts->y,ymax);
+	//	fprintf(stderr,"pt (%.2f \t %.2f)\n",pts->x,pts->y);
+	pts=pts->next;
+      }
+  //  fprintf(stderr,"Bounds x=%.2f:%.2f y=%.2f:%.2f\n",xmin,xmax,ymin,ymax);
+}
+// ***********************************************************************
+void PXContour::getextrema(int direction,int min,float& x,float& y)
+{
+  min=min>0;
+  direction=Irange(direction,1,2);
+  float xmin,xmax,ymin,ymax;
+  getextent(xmin,xmax,ymin,ymax);
+  
+  PXContourPoint* pts=toppoint;
+  int found=0;
+  while (pts->next !=NULL && found==0)
+      {
+	if (min==1 && direction==1)
+	    {
+	      if (fabs(xmin-pts->x)<0.01)
+		  found=1;
+	    }
+
+	if (min==1 && direction==2)
+	    {
+	      if (fabs(ymin-pts->y)<0.01)
+		  found=1;
+	    }
+	if (min==0 && direction==1)
+	    {
+	      if (fabs(xmin-pts->x)<0.01)
+		  found=1;
+	    }
+	if (min==0 && direction==2)
+	    {
+	      if (fabs(ymax-pts->y)<0.01)
+		  found=1;
+	    }
+	if (found!=1)
+	    pts=pts->next;
+      }
+  x=pts->x;
+  y=pts->y;
+}
+// ***********************************************************************
+void PXContour::calcStats(float& mean,float& max,float& min,int& nsegm,int opencurve)
+{
+  PXContourPoint* temp=gettoppoint();
+  int np=getnumpoints();
+  float x0=0,y0=0,dist=0.0;
+  
+  min=1000.0,max=-10000.0;
+  int numdist=0;
+  for (int ib=1;ib<=np;ib++)
+      {
+	if (ib>1)
+	    {
+	      float d=sqrt( pow(temp->x-x0,float(2.0)) + pow(temp->y-y0,float(2.0)) );
+	      dist+=d;
+	      min=Fmin(min,d);
+	      max=Fmax(max,d);
+	      numdist++;
+	    }
+	x0=temp->x;
+	y0=temp->y;
+	temp=temp->next;
+      }
+  if (!opencurve)
+      {
+	temp=gettoppoint();
+	float d=sqrt(pow(temp->x-x0,float(2.0))+pow(temp->y-y0,float(2.0)));
+	dist+=d;
+	min=Fmin(min,d);
+	max=Fmax(max,d);
+	numdist++;
+	x0=temp->x;
+	y0=temp->y;
+	numdist++;
+      } 
+  mean=dist/float(numdist);
+  nsegm=numdist;
+}
+// ***********************************************************************
+float PXContour::getcontourlength()
+{
+  float length=0.0;
+  float x1=0.0,x2=0.0,y1=0.0,y2=0.0;
+  float x0=0.0,y0=0.0;
+
+  if (numpoints>1)
+    {
+      PXContourPoint *pts=toppoint;
+      x0=pts->x; y0=pts->y;
+      x1=x0;     y1=y0;
+      pts=pts->next;
+
+      while(pts->next !=NULL)
+	{
+	  x2=pts->x;
+	  y2=pts->y;
+	  length+=sqrt(pow(x1-x2,float(2.0))+pow(y1-y2,float(2.0)));
+	  x1=x2;
+	  y1=y2;
+	  pts=pts->next;
+	}
+      
+      if (closed>0)
+	length=length+sqrt((x0-x2)*(x0-x2)+(y0-y2)*(y0-y2));
+    }
+  return length;
+}
+// ***********************************************************************
+void  PXContour::getmajoraxis(float& nx,float& ny)
+{
+  float *px=new float[getnumpoints()+1];
+  float *py=new float[getnumpoints()+1];
+  int wasclosed=isclosed();
+  setclosed(0);
+  int np=0;
+  copy2vector(px,py,np);
+  setclosed(wasclosed);
+  getmajoraxis(px,py,np,nx,ny);
+  delete [] px;
+  delete [] py;
+
+}
+// ***********************************************************************  
+void  PXContour::getdualcentroid(PXContour* other,float& x,float& y)
+{
+  float x1=0.0,y1=0.0,l1=0.0;
+  float x2=0.0,y2=0.0,l2=0.0;
+  getcentroid(x1,y1); other->getcentroid(x2,y2);
+  l1=getcontourlength(); l2=other->getcontourlength();
+
+  x= (x1*l1+x2*l2)/(l1+l2);
+  y= (y1*l1+y2*l2)/(l1+l2);
+}
+// ***********************************************************************  
+void PXContour::getdualmajoraxis(PXContour* other,float& nx,float& ny)
+{
+  int nptot=getnumpoints()+other->getnumpoints();
+  float *px=new float[nptot];
+  float *py=new float[nptot];
+  int wasclosed=isclosed();
+  setclosed(0);
+  int np=0;
+  copy2vector(px,py,np);
+  setclosed(wasclosed);
+  int np2=0;
+  wasclosed=other->isclosed();
+  other->setclosed(0);
+  copy2vector(&px[np],&py[np],np2);
+  other->setclosed(wasclosed);
+  np+=np2;
+  getmajoraxis(px,py,np,nx,ny);
+  delete [] px;
+  delete [] py;
+
+}
+// ***********************************************************************  
+void PXContour::getmajoraxis(float* x,float* y,int np,float& nx,float& ny)
+{
+  
+  float cx=0.0,cy=0.0,scale=1.0/float(np);
+  float sxx=0.0,syy=0.0,sxy=0.0;
+  int i;
+  for (i=0;i<np;i++)
+    {
+      cx+=x[i]; cy+=y[i];
+    }
+  cx*=scale; cy*=scale;
+  
+  for (i=0;i<np;i++)
+    {
+      x[i]-=cx;
+      y[i]-=cy;
+    }
+  
+  for (i=0;i<np;i++)
+    {
+      sxx+=x[i]*x[i];
+      syy+=y[i]*y[i];
+      sxy+=x[i]*y[i];
+    }
+  
+  sxx*=scale; syy*=scale; sxy*=scale;
+
+  double** a1    = dmatrix(0,1,0,1);
+  double*  d1    = dvector(0,1);
+  double** v1    = dmatrix(0,1,0,1);
+
+  a1[0][0]=sxx;   a1[0][1]=sxy;
+  a1[1][0]=sxy;   a1[1][1]=syy;
+  
+  vtkMath_JacobiN(a1,2,d1,v1);
+
+  if (d1[0]>d1[1])
+    {
+      nx=v1[0][0]; ny=v1[1][0];
+    }
+  else
+    {
+      nx=v1[0][1]; ny=v1[1][1];
+    }
+  
+  float mag=sqrt(nx*nx+ny*ny);
+  nx/=mag;
+  ny/=mag;
+  
+  free_dmatrix(v1,0,1,0,1);  
+  free_dmatrix(a1,0,1,0,1);  
+  free_dvector(d1,0,1);      
+}
+// ***********************************************************************  
+
+
+
diff --git a/bioimagesuite30_src/numerics/pxcontour.h b/bioimagesuite30_src/numerics/pxcontour.h
new file mode 100644
index 0000000..079b346
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxcontour.h
@@ -0,0 +1,281 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pxcontour.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : 1. PXContour
+
+_Description : A class which stores contour with options for
+               Subsampling and forming closed contour
+	       Smoothing and Sampling and Equispacing
+	       
+_Call : 
+  PXContour();
+  PXContour(PXContour *oldcontour);
+        
+_References : Computational Geometry, Preparata and Shamos              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 25th Sep 1995
+                    2. Added Centroid + Moment Calculation 2nd Oct 1995
+		    3. Added Sampling and Smoothing Options 6th Oct 1995
+		    4. Provision for isolated points-draw  16th Oct 1995
+		    5. Conversion to floating point to allow greater accuracy
+		    6. Added equispacing and length calculation
+                       also potential for normal/curvature storage
+		    7. Change load/save Format to conform to IPAG standards 
+		       (i.e. no header) 11th Jul 1996
+		    8. Chenged Load/Save Stack to read PengCheng's stack format 11/07/96
+		    9. Tidied-up 2nd Sep 1996
+		   10. Added SaveFloatStack to save stack as floats
+		   11. Added area calculation for closed contours
+		       (4th November 1996 -- from Francois code)
+		   12. Fixed Touching function 13th Nov 1997 (JC)
+		   13. Fixed Load function to be less crashable
+		   14. Eliminated `filename' and added a copypoints routine (1/14/98)
+		   15. Eliminated all references to contour stack, created new pxcontourstack class
+		       5th Feb 1998
+		   16. Created new anticlockwise function, ensure contour is anticlockwise
+		   17. Added cache and sub-pixel search 21st April 1998
+		   18. Added non-shrinking smoothing
+		   19. Added 3D Option to Contour
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PX_CONTOUR
+#define _PX_CONTOUR
+
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+#include "bis_znzlib.h"
+
+class PXImage;
+
+struct PXContourPoint {
+  float        x;
+  float        y;
+  PXContourPoint* previous;
+  PXContourPoint* next;
+};
+
+struct PXContourGrad {
+  float          x;          // Normal componenets (x,y)
+  float          y;
+  float          k;          // Curvature k
+  PXContourGrad* previous;
+  PXContourGrad* next;
+};
+
+
+
+
+class PXContour {
+
+  // ************** Class Fields *************************************
+
+  protected :
+  unsigned char  status,closed,isolated,gradient,contourhascache;
+  unsigned short numpoints;
+  PXContourPoint *lastpoint,*toppoint,*realnextpoint;
+  PXContourGrad  *lastgradient,*topgradient;
+  float *px,*py;
+
+  // ******************************************************************************
+  //          PUBLIC INTERFACE
+  // ******************************************************************************
+
+ public:
+
+  PXContour();
+  PXContour(PXContour *oldcontour);
+  virtual ~PXContour();
+
+  // [A] General Contour Status
+  // ---------------------------
+
+  virtual int  isvalid()     { return status;}
+  virtual void suspend()     { status=0;}
+  virtual void reinstate()   { status=1;}
+
+  virtual void closedcontour(unsigned char flag)    
+      { closed=flag;}
+
+  virtual void setclosed(unsigned char flag)
+      { closedcontour(flag);}
+  virtual unsigned char isclosed()
+    {return closed;}
+
+  virtual void isolatedcontour(unsigned char flag)
+    { isolated=flag;}
+  virtual unsigned char isisolated()
+    {return isolated;}
+
+  virtual void gradientcontour(unsigned char flag)
+    { gradient=flag;}
+  virtual unsigned char hasgradient()
+    {return gradient;}
+
+  virtual unsigned char hascache() { return contourhascache;}
+
+  // [B] Contour Parameters
+  // ----------------------
+
+  virtual unsigned short  getnumpoints()   {return numpoints;}
+  virtual PXContourPoint* gettoppoint()   {return toppoint;}
+  virtual PXContourPoint* getlastpoint()  {return lastpoint;} 
+  virtual PXContourGrad*  gettopgradient() {return topgradient;}
+  virtual float*          getcachex()      {return px;}
+  virtual float*          getcachey()      {return py;}
+  
+  //[C] Add Remove Point functions
+  //------------------------------
+
+  virtual int  ensureAnticlockwise();
+  virtual int  ensureClockwise();
+  virtual int  setDirection(int dir=1); // + = Anti , -1 =Clock
+  virtual void setcircle(int np=10,float radius=5.0,float x=50.0,float y=50.0);
+  virtual void AddP(unsigned long xx,unsigned long yy);
+  virtual void Add(float xx,float yy);
+  virtual void AddSpline(double** x,int n,int np);
+  virtual void RemovePoint();
+  virtual void DeleteAll();
+
+  virtual void AddGrad(float xx,float yy,float kk);
+  virtual void RemoveGrad(); 
+  virtual void DeleteGrad();
+
+  
+  //[D]Contour Manipulation
+  //------------------------
+  /*
+    Sample    - averages width points to  get one 
+    Subsample - adds maxratio points between each pair of points
+    Touching  - subsamples contour until points are touching
+    Moments   - finds moments of contour
+    */
+
+
+
+  virtual void  copypoints(PXContour *oldcontour);
+  virtual void  CalculateGradients(int scale);
+
+  virtual void  Smooth(float sigma=1.0,int width=5);
+  virtual void  nonShrinkSmooth(float sigma=1.0,int iterations=10,
+				float alpha=0.33,float beta=-0.34,int width=5);
+  virtual void  Sample(int width);
+  virtual void  Subsample(int maxratio);
+  virtual void  Touching();
+
+  virtual void  Equispace(float spacing);
+  virtual void  Equisample(int npoints);
+
+  virtual float findnearestneighbour(float&x,float& y,float dt=0.01,int dbg=0);
+
+  virtual void  generateCache(int forceClosed=1);
+  virtual void  cleanupCache();
+
+
+  // [E] I/O Related Routines
+  // ------------------------
+  virtual int  Load(const char* filename);
+  virtual int  Save(const char* filename);
+  virtual void SaveStream(FILE* fout,int in2d=1,int opencurve=1,float z=0.0);
+  virtual int  SaveInteger(const char* filename,int scale=1);
+  virtual int  Save4Mesh(const char* filename);
+  virtual int  SaveIGES(const char* filename,float z=0.0);
+
+  // [F] Check Inside or Outside 
+  // ---------------------------
+  virtual int   IsInside (float testpointx,float testpointy);
+
+  // [G] Contour Statistics
+  // ----------------------
+  virtual float getarea();  
+  virtual float getcontourlength();
+  virtual void  getcentroid(float& x,float& y);
+  virtual void  calcStats(float& mean,float& max,float& min,int& nsegm,int opencurve);
+  virtual void  getmajoraxis(float& nx,float& ny);
+  virtual void  getextent(float &xmin,float& xmax,float& ymin,float& ymax);
+  virtual void  getextrema(int direction,int min,float& x,float& y);
+
+  virtual void  getdualcentroid(PXContour* other,float& x,float& y);
+  virtual void  getdualmajoraxis(PXContour* other,float& nx,float& ny);
+  virtual void  getmajoraxis(float* x,float* y,int np,float& nx,float& ny);
+
+  // ******************************************************************************
+  //          IMPLEMENTATION SPECIFIC
+  // ******************************************************************************
+
+  virtual void  copy2vector(double* x,double *y,int& np);
+  virtual void  copy2vector(float* x,float *y,int& np);
+
+  protected :
+
+  virtual int   getcardinal(int ii,int np,unsigned char cl);
+  virtual int   getcyclicindex(int pt,int np);
+  virtual int   IsInside (float testpointx,float testpointy,
+			  float *pointx,float* pointy,
+			  int numberofpoints);
+public:
+  static float Break_const;
+  static  int   Intersect (float x1,float y1, 
+			   float x2,float y2, 
+			   float x,float y); 
+  static int  saveContourPair(const char* fname,
+			      float* px1,float* py1,
+			      float* px2,float* py2,
+			      int np1,int np2,
+			      int* used,int* corr);
+  static int  cyclicDistance(int p1,int p2,int np);
+  static int  saveContourPair(const char* fname,PXContour* cntr1,PXContour* cntr2);
+
+  static PXContour*  mapContours(PXContour* cnt1,PXContour* cntr2,int resample=1);
+
+  
+};
+#endif   /* _PX_CONTROUR */
+
diff --git a/bioimagesuite30_src/numerics/pxcontourstack.cpp b/bioimagesuite30_src/numerics/pxcontourstack.cpp
new file mode 100644
index 0000000..c5ec581
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxcontourstack.cpp
@@ -0,0 +1,1275 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+#include "pxcontourstack.h"
+#include "pxchamferdistancemap.h"
+#include "pxtriangulatedstack.h"
+
+
+// --------------------------------------------------------------------------
+PXContourStack::PXContourStack(PXContourStack *old,int zbetween,int mode)
+{
+  initfromold(old,zbetween,mode);
+  //  fprintf(stderr,"Done\n");
+}
+// --------------------------------------------------------------------------
+PXContourStack::PXContourStack(PXContourStack* old,int zbetween,int mode,
+			       int closedbottom,int closedtop,
+			       float apexdz,float basedz)
+{
+  closedbottom=(closedbottom>0);
+  closedtop=(closedtop>0);
+
+  if ( closedbottom>0 || closedtop >0 )
+      {
+	int newnumcontours=old->getnumcontours()+closedbottom+closedtop;
+	fprintf(stderr,"Closed Bottom =%d, CLosed top=%d\n",closedbottom,closedtop);
+	fprintf(stderr,"Old Contours =%d, new=%d\n",old->getnumcontours(),newnumcontours);
+
+	PXContourStack* temp=new PXContourStack(newnumcontours);
+
+	int index=0;
+	for (int i=closedbottom;i<=old->getnumcontours()+closedbottom;i++)
+	    {
+	      (temp->getcontour(i))->copypoints(old->getcontour(index));
+	      temp->setzlevel(i,old->getzlevel(index));
+	      index++;
+	    }
+
+	float x,y;
+	if (closedbottom==1)
+	    {
+	      float zsize=fabs(old->getzlevel(1)-old->getzlevel(0));
+	      if (apexdz>0.0)
+		  temp->setzlevel(0,old->getzlevel(0)-apexdz);
+	      else
+		  temp->setzlevel(0,old->getzlevel(0)-0.3*zsize);
+	      (old->getcontour(0))->getcentroid(x,y);
+	      (temp->getcontour(0))->setcircle(4,0.02,x,y);
+	    }
+	
+	if (closedtop==1)
+	    {
+	      float zsize=fabs(old->getzlevel(old->getnumcontours()-1)-
+			       old->getzlevel(old->getnumcontours()-2));
+	      if (basedz>0.0)
+		  temp->setzlevel(newnumcontours-1,old->getzlevel(old->getnumcontours()-1)+apexdz);
+	      else
+		  temp->setzlevel(newnumcontours-1,old->getzlevel(old->getnumcontours()-1)+0.3*zsize);
+
+	      (old->getcontour(old->getnumcontours()-1))->getcentroid(x,y);
+	      (temp->getcontour(newnumcontours-1))->setcircle(4,0.02,x,y);
+	    } 	     
+
+
+	initfromold(temp,zbetween,mode);
+	delete temp;
+      }
+  else
+      initfromold(old,zbetween,mode);
+}
+// --------------------------------------------------------------------------
+PXContourStack::PXContourStack(int numberofcontours)
+{
+  numcontours=numberofcontours;
+  if (numcontours<2)
+      numcontours=2;
+  if (numcontours>=PXCONTOURSTACK_MAXLEVELS)
+      numcontours=PXCONTOURSTACK_MAXLEVELS-1;
+  for (int i=0;i<numcontours;i++)
+      {
+	contour[i]=new PXContour();
+	zlevel[i]=float(i);
+      }
+}
+
+// --------------------------------------------------------------------------
+void PXContourStack::initfromold(PXContourStack* old,int zbetween,int mode)
+{
+  if (zbetween==0)
+      {
+	numcontours=old->getnumcontours();
+	for (int i=0;i<old->getnumcontours();i++)
+	    {
+	      // fprintf(stderr,"%d ",i);
+	      contour[i]=new PXContour(old->getcontour(i));
+	      zlevel[i]=old->getzlevel(i);
+	    }
+	return;
+      }
+
+  mode=Irange(mode,0,2);
+  int index=0;
+  int base=0;
+  
+  float zsize=fabs(old->getzlevel(old->getnumcontours()-1)-old->getzlevel(old->getnumcontours()-2));
+  if (zsize<0.1)
+      zsize=1.0;
+
+  // Apex First 
+  if ((old->getcontour(0))->getnumpoints()==1)
+      {
+	contour[0]=new PXContour(old->getcontour(0));
+	contour[0]->setclosed(1);
+	zlevel[0]=old->getzlevel(0);
+
+	index++;
+	base=1;
+	float meandist=0.0;
+	PXContourPoint* pts0=old->getcontour(0)->gettoppoint();
+	PXContourPoint* pts1=old->getcontour(1)->gettoppoint();
+	float z0=old->getzlevel(0);
+	float z1=old->getzlevel(1);
+	int np1=old->getcontour(1)->getnumpoints();
+	int pt;
+	for (pt=0;pt<np1;pt++)
+	    {
+	      meandist+=Fdist(pts0->x,pts0->y,z0,pts1->x,pts1->y,z1)/float(np1);
+	      pts1=pts1->next;
+	    }
+	float xh=sqrt((-1.0+sqrt(1.0+4.0*meandist*meandist))/2.0);
+	float uh=1.0+xh; // asinh not defined !!! asinh(2.0*xh);
+	float dtrue=0.125*(2.0*uh+sinh(2.0*uh));
+	
+	int upper=int(0.5+float(zbetween)*(dtrue/zsize));
+	upper=Irange(upper,1,20);
+
+	for (int m=1;m<=upper;m++)
+	    {
+	      
+	      float dx=float(m)/float(upper+1);
+	      float n0=-(dx-1.0)*(dx+1.0);
+	      float n1=0.5*(dx+1.0)*dx;
+	      float n2=0.5*(dx-1.0)*dx;
+	      zlevel[index]=n0*z0+(n1+n2)*z1;
+	      
+	      contour[index]=new PXContour();
+	      pts1=old->getcontour(1)->gettoppoint();
+	      PXContourPoint* pts2=pts1;
+	      int pthalf=np1/2;
+	      for (pt=0;pt<pthalf;pt++)
+		  pts2=pts2->next;
+	      
+	      for (pt=0;pt<np1;pt++)
+		  {
+		    contour[index]->Add(n0*pts0->x+n1*pts1->x+n2*pts2->x,
+					n0*pts0->y+n1*pts1->y+n2*pts2->y);
+		    pts1=pts1->next;
+		    if (pts2->next->next==NULL)
+			pts2=old->getcontour(1)->gettoppoint();
+		    else
+			pts2=pts2->next;
+		  }
+	      contour[index]->setclosed(1);
+	      contour[index]->Equispace(0.8);
+	      contour[index]->Smooth(1);
+	      index++;
+	    }
+      }
+
+  if (mode>0)
+      {
+	for (int i=base;i<old->getnumcontours();i++)
+	    {
+	      contour[index]=new PXContour(old->getcontour(i));
+	      contour[index]->setclosed(1);
+	      zlevel[index]=old->getzlevel(i);
+	      index++;
+	      if (i!=old->getnumcontours()-1)
+		  {
+		    float znewsize=fabs(old->getzlevel(i+1)-old->getzlevel(i));
+		    int upper=int(0.5+float(zbetween)*(znewsize/zsize));
+		    for(int m=1;m<=upper;m++)
+			{
+			  PXChamferDistanceMap* map;
+			  int f1=(upper+1-m);
+			  int f2=m;
+			  float z=float(f1)*old->getzlevel(i)+float(f2)*old->getzlevel(i+1);
+			  z=z/float(f1+f2);
+			  if (i==0 || i==(old->getnumcontours()-1) || mode==1 || numcontours<4)
+			      map=new PXChamferDistanceMap(old->getcontour(i),
+							   old->getcontour(i+1)
+							   ,f1,f2);
+			  else
+			      map=new PXChamferDistanceMap(old->getcontour(i-1),old->getcontour(i),
+							   old->getcontour(i+1),old->getcontour(i+2),
+							   float(m)/float(zbetween+1));
+			  contour[index]=map->extractContour();
+			  zlevel[index]=z;
+			  contour[index]->setclosed(1);
+			  contour[index]->Smooth(1);
+			  contour[index]->Equispace(0.8);
+			  index++;
+			}
+		  }
+	    }
+	numcontours=index;
+      }
+  else
+      {
+	int npmax=0;
+	int i;
+	for (i=base;i<old->getnumcontours();i++)
+	    npmax=Imax(npmax,old->getcontour(i)->getnumpoints());
+	float *x[2],*y[2];
+	x[0]=new float[npmax];     y[0]=new float[npmax];
+	x[1]=new float[npmax];     y[1]=new float[npmax];
+	
+	for (i=base;i<old->getnumcontours();i++)
+	    {
+	      contour[index]=new PXContour(old->getcontour(i));
+	      contour[index]->setclosed(1);
+	      zlevel[index]=old->getzlevel(i);
+	      index++;
+	      int np[2];
+	      float znewsize=fabs(old->getzlevel(i+1)-old->getzlevel(i));
+	      int upper=int(0.5+float(zbetween)*(znewsize/zsize));
+	      np[0]=old->getcontour(i)->getnumpoints();
+	      np[1]=old->getcontour(i+1)->getnumpoints();
+	      for (int c=0;c<=1;c++)
+		  {
+		    PXContourPoint* pts=old->getcontour(i+c)->gettoppoint();
+		    np[c]=old->getcontour(i+c)->getnumpoints();
+		    for(int ia=0;ia<np[c];ia++)
+			{
+			  x[c][ia]=pts->x;  y[c][ia]=pts->y;
+			  pts=pts->next;
+			}
+		  }
+	      
+	      // Find Origin
+	      // -----------
+	      int origin[2];
+	      PXTriangulatedStack::findorigin2D(np,x,y,origin);
+	      
+	      // Triangulation Algorithm
+	      // -----------------------
+	      int m;
+	      for(m=1;m<=upper;m++)
+		  {
+		    float f1=float(upper+1-m),f2=float(m);
+		    float sum=f1+f2;
+		    f1=f1/(sum);f2=f2/(sum);
+		    float z=f1*old->getzlevel(i)+f2*old->getzlevel(i+1);
+		    contour[index+m-1]=new PXContour();
+		    zlevel[index+m-1]=z;
+		    contour[index+m-1]->Add(f1*x[0][origin[0]]+f2*x[1][origin[1]],
+					    f1*y[0][origin[0]]+f2*y[1][origin[1]]);
+		  }
+	      
+	      int done=0,cend[2],current[2],next[2];
+	      float dist[2];
+	      cend[0]=0; cend[1]=0;
+	      current[0]=origin[0];  current[1]=origin[1];
+	      
+	      while(done==0)
+		  {
+		    for (int c=0;c<=1;c++)
+			{
+			  if (cend[c]==0)
+			      {
+				next[c]=Icyclic(current[c]+1,np[c]);
+				int other=current[1-c];
+				dist[c]=Fsqdist(x[c][next[c]],y[c][next[c]],0.0,
+						x[1-c][other],y[1-c][other],0.0);
+			      }
+			  else
+			      dist[c]=100000000.0;
+			}
+		    
+		    if (dist[0]<dist[1])
+			{
+			  current[0]=next[0];
+			  for (int m=1;m<=upper;m++)
+			      {
+				float f1=float(upper+1-m),f2=float(m);
+				float sum=f1+f2;
+				f1=f1/(sum);f2=f2/(sum);
+				contour[index+m-1]->Add(f1*x[0][current[0]]+f2*x[1][current[1]],
+							f1*y[0][current[0]]+f2*y[1][current[1]]);
+			      }
+			  if (current[0]==origin[0]) 
+			      cend[0]=1;
+			}
+		    else
+			{
+			  current[1]=next[1];
+			  for (int m=1;m<=upper;m++)
+			      {
+				float f1=float(upper+1-m),f2=float(m);
+				float sum=f1+f2;
+				f1=f1/(sum);f2=f2/(sum);
+				contour[index+m-1]->Add(f1*x[0][current[0]]+f2*x[1][current[1]],
+							f1*y[0][current[0]]+f2*y[1][current[1]]);
+			      }
+			  if (current[1]==origin[1]) 
+			      cend[1]=1;
+			}
+		    
+		    if (cend[0]==1 && cend[1]==1)
+			done=1;
+		    
+			}
+	      for (m=1;m<=upper;m++)
+		  {
+		    contour[index]->setclosed(1);
+		    contour[index]->Equispace(0.8);
+		    contour[index]->Smooth(1);
+		    index++;
+		  }
+	    }
+	delete [] x[0]; delete [] x[1];
+	delete [] y[0]; delete [] y[1];
+	numcontours=index;
+      }
+}
+// --------------------------------------------------------------------------
+PXContourStack::~PXContourStack()
+{
+  for (int i=0;i<numcontours;i++)
+      delete contour[i];
+}
+
+// --------------------------------------------------------------
+int PXContourStack::getnumpoints()
+{
+  int np=0;
+  for (int i=0;i<numcontours;i++)
+      np+=contour[i]->getnumpoints();
+  return np;
+}
+
+// --------------------------------------------------------------
+// Copy control points from another surface
+// --------------------------------------------------------------
+void PXContourStack::copypoints(PXContourStack* other)
+{
+  int oldnumcontours=numcontours;
+  numcontours=other->getnumcontours();
+
+  if (oldnumcontours!=numcontours)
+      {
+	if (oldnumcontours>numcontours)
+	    {
+	      for (int i=numcontours;i<oldnumcontours;i++)
+		  delete contour[i];
+	    }
+	else
+	    {
+	      for (int i=oldnumcontours;i<numcontours;i++)
+		  contour[i]=new PXContour();
+	    }
+	
+      }
+  
+  for (int i=0;i<numcontours;i++)
+      {
+	contour[i]->copypoints(other->getcontour(i));
+	zlevel[i]=other->getzlevel(i);
+      }
+  
+}
+// --------------------------------------------------------------
+void PXContourStack::setcontour(int index,PXContour* spl)
+{
+  index=indexbounded(index);  
+  if (index>=0 && index<numcontours)
+      {
+	contour[index]->copypoints(spl);
+      }
+}
+// ------------------------------------------------------------------
+void PXContourStack::setzlevel(int index,float zl)
+{
+  index=indexbounded(index);  
+  if (index>=0 && index<numcontours)
+      {
+	zlevel[index]=zl;
+      }
+}
+// --------------------------------------------------------------
+int  PXContourStack::getzbetween(float zdist)
+{
+  if (zdist<0.0)
+      return 0;
+  
+  int middle=numcontours/2;
+  float zsize=fabs(zlevel[middle]-zlevel[middle-1]);
+  zdist=zdist/zsize; 
+  int zbetween;
+  if (zdist<0.1)  zdist=0.1;
+  if (zdist>=1.0) 
+      zbetween=0;
+  else
+      zbetween=int(0.5+1.0/zdist)-1;
+
+  return zbetween;
+}
+// --------------------------------------------------------------
+void PXContourStack::setellipticalcylinder(int np,float rx,float ry,float cx,float cy)
+{
+  int i;
+  for (i=0;i<numcontours;i++)
+      contour[i]->DeleteAll();
+  
+  for (int j=0;j<np;j++)
+      {
+	float t=M_PI*2.0*(float(j-0)/float(np));
+	float xx=rx*cos(t)+cx;
+	float yy=ry*sin(t)+cy;
+	for (int i=0;i<numcontours;i++)
+	    contour[i]->Add(xx,yy);
+      }
+  for (i=0;i<numcontours;i++)
+      contour[i]->setclosed(1);
+  
+}
+// --------------------------------------------------------------
+void  PXContourStack::Smooth(float sigma,int width)
+{
+  for (int i=0;i<numcontours;i++)
+      {
+	contour[i]->setclosed(1);
+	contour[i]->Smooth(sigma,width);
+      }
+}
+// --------------------------------------------------------------
+void  PXContourStack::Equispace(float dist)
+{
+  if (dist>0.0)
+      {
+	for (int i=0;i<numcontours;i++)
+	    {
+	      contour[i]->setclosed(1);
+	      contour[i]->Equispace(dist);
+	    }
+      }
+}
+void  PXContourStack::Equisample(int npoints)
+{
+  if (npoints>0)
+      {
+	for (int i=0;i<numcontours;i++)
+	    {
+	      contour[i]->setclosed(1);
+	      contour[i]->Equisample(npoints);
+	    }
+      }
+}
+// ------------------------------------------------------------------
+//           I/O Functions
+//
+//        Load & Save -->              Surface Format (Control Points)
+// ------------------------------------------------------------------
+int PXContourStack::Load(const char* filename)
+{
+  char line[200];
+  float x,y,z;
+  int npoints;
+
+
+  gzFile fin=gzsuffixopen(filename,"r");
+  if (fin!=Z_NULL)
+      {
+	npoints=0; 
+	gzgets(fin,line,100);
+	
+	if (line[0]=='s')
+	    {
+	      // Test Nuages Format Found 
+	      gzclose(fin);
+	      return LoadNuages(filename);
+	    }
+	
+	int i;
+	for(i=0;i<numcontours;i++)
+	    delete contour[i];
+
+	while ( gzgets(fin,line,100)!=NULL )    
+	    npoints++;
+	gzclose(fin);
+	// Read File
+	fin=gzsuffixopen(filename,"r");
+	
+	// Eat First line x-y-z
+	gzgets(fin,line,100);
+	
+	numcontours=0;
+	contour[numcontours]=new PXContour();
+	
+	for(i=0;i<npoints;i++)
+	    {
+	      gzgets(fin,line,100);
+	      sscanf(line,"%f %f %f\n",&x,&y,&z);
+	      if (i==0)
+		  zlevel[numcontours]=z;
+	      
+	      if (zlevel[numcontours]==z)
+		  {
+		    contour[numcontours]->Add(x,y);
+		  }
+	      else
+		  {
+		    numcontours++;
+		    zlevel[numcontours]=z;
+		    contour[numcontours]=new PXContour();
+		    contour[numcontours]->Add(x,y);
+		  }
+	    }
+	gzclose(fin);
+	numcontours++;
+	//fprintf(stderr,"Loading from %s as contourstack (numcontours=%2d,npoints=%d)\n",filename,numcontours,npoints);
+	return 1;
+      }
+  //fprintf(stderr,"Failed to open %s\n",filename);
+  return 0;
+}
+// --------------------------------------------------------------
+int PXContourStack::Save(const char* filename,float dist,float zdist,int mode,int clb,int clt)
+{
+  int zbet=0;
+  if (zdist>0.0)
+      zbet=getzbetween(zdist);
+  PXContourStack* stack=new PXContourStack(this,zbet,mode,clb,clt);
+  if (dist>0.0)  stack->Equispace(dist);
+
+  int flag=stack->Save(filename);
+  delete stack;
+  return flag;
+}
+// --------------------------------------------------------------
+int  PXContourStack::Save(const char* filename,int complevel)
+{
+  FILE* fout=fopen(filename,"w");
+  if (fout!=NULL)
+      {
+	fprintf(fout,"# x  y  z\n");
+	for (int i=0;i<numcontours;i++)
+	  contour[i]->SaveStream(fout,0,1,zlevel[i]);
+	fclose(fout);
+	return(1);
+      }
+  return(0);
+}
+// --------------------------------------------------------------
+int PXContourStack::SaveIGES(const char* filename,float dist,float zdist,int mode,int clb,int clt)
+{
+  PXContourStack* stack=new PXContourStack(this,getzbetween(zdist),mode,clb,clt);
+  if (dist>0.0)
+      stack->Equispace(dist);
+  int flag=stack->SaveIGES(filename);
+  delete stack;
+  return flag;
+}
+// --------------------------------------------------------------
+int PXContourStack::SaveIGES(const char* filename)
+{
+  int flag=0;
+  FILE* fout=fopen(filename,"w");
+  if (fout!=NULL)
+      {
+	// IGES Start Section
+	// ------------------
+	fprintf(fout,"%72sS      1\n",filename);
+	fprintf(fout,",,,,,,32,38,6,308,15,,1.0D0,1,2HIN,1,0.0D0,13H960202.170136,            G      1\n"
+	        "2.22044604925031D-16,0.0D0,,,9,0,13H960202.170136;                      G      2\n");
+	for (int pass=0;pass<2;pass++)
+	    {
+	      int index=0;
+	      for(int c=0;c<numcontours;c++)
+		  {
+		    PXContourPoint* temp=contour[c]->gettoppoint();
+		    for (int ib=0;ib<contour[c]->getnumpoints();ib++)
+			{
+			  index++;
+			  switch(pass)
+			      {
+			      case 0:
+				fprintf(fout,"%8d%8d%8d%8d",116,index,2,2);
+				fprintf(fout,"%8d%8d%8d%8d%08dD%7d\n",0,0,
+					0,0,0,1);
+				fprintf(fout,"%8d%8d%8d%8d",116,0,0,1);
+				fprintf(fout,"%8d%8d%8d%8s%8dD%7d\n",0,0,0,
+					"POINT",index,2);
+				break;
+			      case 1:
+				fprintf(fout,"116, %15.4e, %15.4e, %15.4f;          %7dP%7d\n",
+					temp->x,temp->y,zlevel[c],(index*2)-1,index);
+				temp=temp->next;
+				break;
+			      }
+			}
+		  }
+	      fprintf(fout,"S%7dG%7dD%7dP%7d                                        T%7d\n",
+		      1,2,index*2,index,1);
+	    }
+	flag=1;
+      }
+  fclose(fout);
+  return flag;
+}
+// --------------------------------------------------------------
+int PXContourStack::SaveNuages(const char* filename,float dist,float zdist,int mode,
+			       int clbottom,int cltop)
+{
+  int zbet=0;
+  if (zdist>0.0) zbet=getzbetween(zdist);
+
+  PXContourStack* stack=new PXContourStack(this,zbet,mode,clbottom,cltop);
+  if (dist>0.0) stack->Equispace(dist);
+
+  int flag=stack->SaveNuages(filename);
+  delete stack;
+  return flag;
+}
+// --------------------------------------------------------------
+int  PXContourStack::SaveNuages(FILE* fout)
+{
+  fprintf(fout,"s %d\n", numcontours);
+
+  float totaldist=0.0,maxdist=-10000.0,mindist=100000.0,mean,max,min;
+  int   totalsegm=0, nsegm;
+
+
+  for(int j=0;j<numcontours;j++)
+    {
+      if (contour[j]->getnumpoints()>1)
+	{
+	  fprintf(fout,"v %d z %5.2f \n{\n",contour[j]->getnumpoints(),zlevel[j]);
+	  contour[j]->calcStats(mean,max,min,nsegm,0);
+	  totaldist+=float(nsegm)*mean;
+	  totalsegm+=nsegm;
+	  mindist=Fmin(mindist,min);
+	  maxdist=Fmax(maxdist,max);
+	  contour[j]->ensureClockwise();
+	  contour[j]->SaveStream(fout,1,1);
+	  fprintf(fout,"}\n");
+	}
+      else if (contour[j]->getnumpoints()==1)
+	{
+	  fprintf(fout,"v %d z %5.2f \n{\n",4,zlevel[j]);
+	  PXContourPoint* pts=contour[j]->gettoppoint();
+	  fprintf(fout,"%6.2f %6.2f \n",pts->x-0.01,pts->y-0.01);
+	  fprintf(fout,"%6.2f %6.2f \n",pts->x-0.01,pts->y+0.01);
+	  fprintf(fout,"%6.2f %6.2f \n",pts->x+0.01,pts->y+0.01);
+	  fprintf(fout,"%6.2f %6.2f \n",pts->x+0.01,pts->y-0.01);
+	  fprintf(fout,"}\n");
+	}
+      else
+	{
+	  fprintf(fout,"v %d z %5.2f \n{\n",0,zlevel[j]);
+	  fprintf(fout,"}\n");
+	}
+      
+    }
+  fprintf(fout,"# Stats : nsegm=%d Mean=%5.3f Range=%5.3f:%5.3f\n",
+	  totalsegm,totaldist/float(totalsegm),mindist,maxdist);
+  return(1);
+  
+}
+// --------------------------------------------------------------
+int PXContourStack::SaveNuages(const char* filename,int complevel)
+{
+  int flag=0;
+  FILE* fout=fopen(filename,"w");
+  if (fout!=NULL)
+      {
+	flag=SaveNuages(fout);
+	fclose(fout);
+      }
+  return flag;
+}
+// --------------------------------------------------------------------------
+int  PXContourStack::LoadNuages(gzFile fin)
+{
+  for(int i=0;i<numcontours;i++)
+      delete contour[i];
+
+  char* line=new char[100];
+  gzgets(fin,line,100);
+  sscanf(line,"s %d", &numcontours);
+  if (numcontours<0 || numcontours>1000)
+      return 0;
+  //  fprintf(stderr,"Numcontours=%d\n",numcontours);
+
+  for(int j=0;j<numcontours;j++)
+      {
+	contour[j]=new PXContour();
+	int np;
+	float zl,x,y;
+	//fscanf(fin,"v %d z %f \n{\n",&np,&zl);
+	gzgets(fin,line,100);
+	sscanf(line,"v %d z %f",&np,&zl);
+	gzgets(fin,line,100);
+	zlevel[j]=zl;
+	for (int pt=0;pt<np;pt++)
+	    {
+	      //fscanf(fin,"%f %f\n",&x,&y);
+	      gzgets(fin,line,100);
+	      sscanf(line,"%f %f",&x,&y);
+	      contour[j]->Add(x,y);
+	    }
+
+	if (np==4)
+	    {
+	      // Detect 1 point section artificially inflated for visualization
+	      PXContourPoint* pts1=contour[j]->gettoppoint();
+	      PXContourPoint* pts2=pts1->next;
+	      PXContourPoint* pts3=pts2->next;
+	      PXContourPoint* pts4=pts3->next;
+	      /*fprintf(stderr,"Checking for single point mess (%5.2f,%5.2f) (%5.2f,%5.2f) (%5.2f,%5.2f) (%5.2f,%5.2f)\n",
+		      pts1->x,pts1->y,
+		      pts2->x,pts2->y,
+		      pts3->x,pts3->y,
+		      pts4->x,pts4->y);*/
+	      /*v 4 z  0.00 
+		{
+		44.31  23.21 
+		44.31  23.23 
+		44.33  23.23 
+		44.33  23.21 
+		}*/
+
+	      if  ((pts1->x==pts2->x && pts3->x==pts4->x && fabs(pts3->x - pts1->x - 0.02)<0.001) &&
+		   (pts1->y==pts4->y && pts3->y==pts2->y && fabs(pts3->y - pts1->y - 0.02)<0.001))
+		      {
+			//			fprintf(stderr,"Single Point");
+			float x=pts1->x+0.001;
+			float y=pts1->y+0.001;
+			contour[j]->DeleteAll();
+			contour[j]->Add(x,y);
+		      }
+	    }
+	contour[j]->setclosed(1);
+	gzgets(fin,line,100);
+	//fscanf(fin,"}\n");
+      }
+  delete [] line;
+  return(1);
+}
+// --------------------------------------------------------------
+int PXContourStack::LoadNuages(const char* filename)
+{
+  int flag=0;
+  gzFile fin=gzsuffixopen(filename,"rb");
+  if (fin!=NULL)
+      {
+	flag=LoadNuages(fin);
+	gzclose(fin);
+      }
+  return flag;
+}
+// --------------------------------------------------------------------------
+//           Index Conversion
+// --------------------------------------------------------------------------
+int PXContourStack::indexbounded(int v,int np)
+{
+  if (np<0) 
+      np=numcontours;
+
+  if(v<0)       v=0;
+  if(v>=np)     v=np-1;
+
+  return v;
+}
+
+int PXContourStack::indexcyclic(int v,int np)
+{
+  while (v<0) v+=np;
+  while (v>=np) v-=np;
+  return v;
+}
+// --------------------------------------------------------------
+float PXContourStack::getsqdist(float x1,float x2,float y1,float y2)
+{
+  return pow(x1-x2,float(2.0))+pow(y1-y2,float(2.0));
+}
+// --------------------------------------------------------------
+int PXContourStack::aligncontours(PXContour* cntr1,PXContour* cntr2)
+{
+  int np1=cntr1->getnumpoints(),np2=cntr2->getnumpoints();
+  int i=0;
+
+  float* x1=new float[np1+1];   float* y1=new float[np1+1];
+  cntr1->copy2vector(x1,y1,i);
+
+  float* x2=new float[np2+1];   float* y2=new float[np2+1];
+  cntr2->copy2vector(x2,y2,i);
+
+  float dist=0.0,mindist=10000000.0;
+  int shift=0;
+  
+  int j;
+  for(j=0;j<np2;j++)
+      {
+	dist=0;
+	for (i=0;i<np1;i++)
+	    {
+	      int index=int(0.5+float(np2)/float(np1)*float(i));
+	      int sj=indexcyclic(j+index,np2);
+	      dist+=getsqdist(x1[i],x2[sj],y1[i],y2[sj]);
+	    }
+	if (dist<mindist)
+	    {
+	      mindist=dist; 
+	      shift=j;
+	    }
+      }
+  
+  if (shift!=0)
+      {
+	cntr2->DeleteAll();
+	for (j=0;j<np2;j++)
+	    {
+	      int sj=indexcyclic(j+shift,np2);
+	      cntr2->Add(x2[sj],y2[sj]);
+	    }
+      }
+  
+  delete [] x1;  delete [] y1;  delete [] x2;  delete [] y2;
+  return shift; 
+}
+// --------------------------------------------------------------
+int PXContourStack::align2basecontours(PXContour* cntr0,PXContour* cntr1,PXContour* cntr2)
+{
+  int np0=cntr0->getnumpoints(),np1=cntr1->getnumpoints(),np2=cntr2->getnumpoints();
+  int i=0;
+
+  float* x0=new float[np0+1];   float* y0=new float[np0+1];
+  cntr0->copy2vector(x0,y0,i);
+
+  float* x1=new float[np1+1];   float* y1=new float[np1+1];
+  cntr1->copy2vector(x1,y1,i);
+
+  float* x2=new float[np2+1];   float* y2=new float[np2+1];
+  cntr2->copy2vector(x2,y2,i);
+
+  float dist=0.0,mindist=10000000.0;
+  int shift=0,j;
+  
+  for(j=0;j<np2;j++)
+      {
+	dist=0.0;
+	for (i=0;i<np0;i++)
+	    {
+	      int index=int(0.5+float(np2)/float(np0)*float(i));
+	      int sj=indexcyclic(j+index,np2);
+	      dist+=getsqdist(x0[i],x2[sj],y0[i],y2[sj]);
+	    }
+	for (i=0;i<np1;i++)
+	    {
+	      int index=int(0.5+float(np2)/float(np1)*float(i));
+	      int sj=indexcyclic(j+index,np2);
+	      dist+=getsqdist(x1[i],x2[sj],y1[i],y2[sj]);
+	    }
+	
+	if (dist<mindist)
+	    {
+	      mindist=dist; 
+	      shift=j;
+	    }
+      }
+  
+  if (shift!=0)
+      {
+	cntr2->DeleteAll();
+	for (j=0;j<np2;j++)
+	    {
+	      int sj=indexcyclic(j+shift,np2);
+	      cntr2->Add(x2[sj],y2[sj]);
+	    }
+      }
+  
+  delete [] x0; delete [] y0; delete [] x1;  delete [] y1;  delete [] x2;  delete [] y2;
+  return shift; 
+}
+// --------------------------------------------------------------
+void PXContourStack::selfalign()
+{
+  for (int i=0;i<numcontours-1;i++)
+	aligncontours(contour[i],contour[i+1]);
+
+}
+// --------------------------------------------------------------
+int PXContourStack::aligntocontourstack(PXContourStack* other)
+{
+  float z1=zlevel[0],z2=z1-1.0;
+  int j=-1;
+  while(j<other->getnumcontours() && z2!=z1)
+      {
+	j++;
+	z2=other->getzlevel(j);
+      }
+
+  if (z2!=z1)
+      return 0;
+
+  aligncontours(other->getcontour(j),contour[0]);
+  selfalign();
+  return 1;
+}
+// --------------------------------------------------------------
+void PXContourStack::shiftandscalez(float shift,float scale)
+{
+  for (int i=0;i<getnumcontours();i++)
+      {
+	float z=getzlevel(i);
+	z=scale*(z+shift);
+	setzlevel(i,z);
+      }
+}
+// --------------------------------------------------------------
+void PXContourStack::getPositionAndOrientation(float& cx,float& cy,float& cz,
+					       float& sx2,float& sy2,float& sxy,
+					       float& vol)
+{
+  cx=0.0;cy=0.0;cz=0.0;
+  sx2=0.0;sy2=0.0;sxy=0.0;
+  vol=0.0;
+
+  int middle=numcontours/2;
+  float zsize=fabs(zlevel[middle]-zlevel[middle-1]);
+  int numpoints=0;
+
+  for (int pass=0;pass<=1;pass++)
+      {
+	for (int i=0;i<getnumcontours();i++)
+	    {
+	      int np=(getcontour(i))->getnumpoints();
+	      if (pass==0)
+		  {
+		    float z=getzlevel(i);
+		    float c1,c2;
+		    (getcontour(i))->getcentroid(c1,c2);
+		    float area=fabs((getcontour(i))->getarea());
+		    //fprintf(stderr,"cntr %d , area=%5.2f c1=%5.2f, c2=%5.2f\n",i+1,area,c1,c2);
+
+		    vol+=area*zsize;
+		    cx+=(c1*area*zsize);
+		    cy+=(c2*area*zsize);
+		    cz+=(z*area*zsize);
+		  }
+	      if (pass==1)
+		  {
+		    PXContourPoint* temp=(getcontour(i))->gettoppoint();
+		    for (int ib=1;ib<=np;ib++)
+			{
+			  numpoints++;
+			  float x=temp->x,y=temp->y;
+			  sx2+=pow(x-cx,float(2.0)); sy2+=pow(y-cy,float(2.0)); sxy+=(x-cx)*(y-cy);
+			  temp=temp->next;
+			}
+		  }
+	    }
+	if (pass==0)
+	    {
+	      cx=cx/vol;
+	      cy=cy/vol;
+	      cz=cz/vol;
+	    }
+	else
+	    {
+	      sx2=sx2/float(numpoints);
+	      sy2=sy2/float(numpoints);
+	      sxy=sxy/float(numpoints);
+	    }
+      }
+}
+// --------------------------------------------------------------
+float PXContourStack::findnearestneighbour(float& xn,float& yn,float &zn,float dt,int dbg)
+{
+  float dist=0.0;
+  if (zn<=getzlevel(0))
+      {
+	dist=contour[0]->findnearestneighbour(xn,yn,dt,0);
+      }
+  else if (zn>=getzlevel(getnumcontours()-1))
+      {
+	dist=contour[getnumcontours()-1]->findnearestneighbour(xn,yn,dt);
+      }
+  else
+      {
+	int i=0;
+	int found=0;
+	while (found==0 && i<getnumcontours()-1)
+	    {
+	      if (zn==zlevel[i])
+		  {
+		    dist=contour[i]->findnearestneighbour(xn,yn,dt);
+		    found=1;
+		  }
+	      if (zn>getzlevel(i) && zn<=getzlevel(i+1))
+		  {
+		    float x0=xn,y0=yn,x1=xn,y1=yn,d0=1.0,d1=1.0;
+		    float dz=(zlevel[i+1]-zlevel[i]);
+		    float w0=(zlevel[i+1]-zn)/dz;
+		    float w1=(zn-zlevel[i])/dz;
+		    
+		    d0=contour[i]->findnearestneighbour(x0,y0,dt,dbg);
+		    d1=contour[i+1]->findnearestneighbour(x1,y1,dt,dbg);
+
+		    float xf=(w1*x1+w0*x0);
+		    float yf=(w1*y1+w0*y0);
+		    float zf=(w1*zlevel[i+1]+w0*zlevel[i]);
+		    dist=sqrt(pow(xn-xf,float(2.0))+pow(yn-yf,float(2.0))+pow(zn-zf,float(2.0)));
+		    if (dbg==1)
+			{
+			  fprintf(stderr," Point (%5.2f %5.2f %5.2f)\n",xn,yn,zn);
+			  fprintf(stderr," Neighbours (%5.2f,%5.2f,%5.2f) and (%5.2f,%5.2f,%5.2f)\n",
+				  x0,y0,zlevel[i],x1,y1,zlevel[i+1]);
+			  fprintf(stderr," Distances %5.2f %5.2f , Weight %5.2f %5.2f \n",
+				  d0,d1,w0,w1);
+			  fprintf(stderr," Result (%5.2f,%5.2f,%5.2f) dist=%5.2f\n",xf,yf,zf,dist);
+			}
+
+		    xn=xf; yn=yf; zn=zf;
+		  }
+	      i++;
+	    }
+      }
+  return dist;
+}
+// --------------------------------------------------------------
+int PXContourStack::SaveAbaqusRigid(const char* filename,int offset,int index)
+{
+  char line1[40],line2[40],line[150];
+  sprintf(line1,"/tmp/splstack.cnt");
+  sprintf(line2,"/tmp/splstack.off");
+  SaveNuages(line1);
+  sprintf(line,"nuages %s -tri %s -off -prepros > /dev/null",line1,line2);
+  system(line);
+  FILE* fin=fopen(line2,"r");
+  if (fin)
+      {
+	FILE* fout=fopen(filename,"w");
+	fprintf(fout,"*NODE,NSET=NSURF_%02d\n",index);
+	int i;
+	for (i=1;i<=5;i++)
+	    fgets(line,100,fin);
+
+	int npoints,ntriangles,temp;
+	fscanf(fin,"%d %d %d\n",&npoints,&ntriangles,&temp);
+	for (i=0;i<npoints;i++)
+	    {
+	      float x,y,z,nx,ny,nz;
+	      fscanf(fin,"%f %f %f %f %f %f\n",&x,&y,&z,&nx,&ny,&nz);
+	      fprintf(fout,"%6d, %6.3f, %6.3f, %6.3f\n",i+offset,x,y,z);
+	    }
+	fprintf(fout,"*ELEMENT, TYPE=R3D3,ELSET=ESURF_%02d\n",index);
+	for (i=0;i<ntriangles;i++)
+	    {
+	      int dummy,n1,n2,n3;
+	      fscanf(fin,"%d %d %d %d\n",&dummy,&n1,&n2,&n3);
+	      fprintf(fout,"%6d, %6d, %6d, %6d\n",
+		      i+offset,n1+offset,n2+offset,n3+offset);
+	    }
+	fprintf(fout,"*RIGID BODY,ELSET=ESURF_%02d,REF NODE=%d\n",index,offset);
+	fprintf(fout,"*SURFACE DEFINITION,NAME=RGDS_%02d\n",index);
+	fprintf(fout,"ESURF_%02d,SPOS\n",index);
+	fclose(fout);
+	fclose(fin);
+	sprintf(line,"rm %s %s ",line1,line2);
+	system(line);
+	return 1;
+      }
+  
+  fprintf(stderr,"Error in creating surfacefile\n");
+  return 0;
+  
+}
+// --------------------------------------------------------------
+int PXContourStack::nonShrinkSmooth(float alpha,float beta,int iterations)
+{
+  char name[300],name2[300],command[400];
+  sprintf(name,"/tmp/tmpsur05d");
+  sprintf(name2,"%s.cnt",name);
+  fprintf(stderr,"Saving in %s\n",name2);
+  fprintf(stderr,"Status =%d\n",SaveNuages(name2));
+  sprintf(command,"nuages %s.cnt -tri %s.idx -prepros",name,name);
+  fprintf(stderr,"%s\n",command); 	system(command);
+  sprintf(command,"patch2index %s.idx %s.myidx /tmp/extent 1 >/dev/null",name,name);
+  fprintf(stderr,"%s\n",command); 	system(command);
+  sprintf(command,"surface_smooth %s.myidx %s.stack %6.2f %6.2f %d >/dev/null",name,name,
+	  alpha,beta,iterations);
+  fprintf(stderr,"%s\n",command); 	system(command);
+  sprintf(name2,"%s.stack",name);
+  PXContourStack* stack2=new PXContourStack();
+  int status=stack2->Load(name2);
+  if (status)
+      copypoints(stack2);
+  delete stack2;
+  //Load(name2);
+  sprintf(command,"/usr/bin/rm %s*\n",name);
+  system(command);
+  return status;
+}
+// --------------------------------------------------------------
+int PXContourStack::nonShrinkSmooth2D(float ds,float sigma,int iterations)
+{
+  fprintf(stderr,"Smoothing Contours (%d) ",getnumcontours());
+  for (int k=0;k<getnumcontours();k++)
+      {
+        PXContour* cntr=getcontour(k);
+	fprintf(stderr,"%d ",k);
+        cntr->setclosed(1);
+	//cntr->Subsample(3);
+        cntr->nonShrinkSmooth(sigma,iterations);
+        cntr->Subsample(5);
+        cntr->Equispace(ds);
+      }
+  fprintf(stderr,"\n");
+  return 1;
+}
+// ------------------------------------------------------------------------- 
+int PXContourStack::createstackset(PXContourStack** stack,
+				   int totalnumstacks,int bias)
+
+{
+  if (stack[0]->getnumcontours()!=stack[totalnumstacks-1]->getnumcontours())
+    {
+      fprintf(stderr,"Unequal number of contours");
+      return 0;
+    }
+  
+  int numslices=stack[0]->getnumcontours(),i;
+  for (i=1;i<totalnumstacks-1;i++)
+    stack[i]->copypoints(stack[0]);
+	
+  int numbetween=totalnumstacks-2;
+
+  // Proceed with Chamfer Interpolation
+  for ( i=0;i<numslices;i++)
+    {
+      PXChamferDistanceMap* map2=new PXChamferDistanceMap(stack[totalnumstacks-1]->getcontour(i),1);
+      //int xs=map2->getmaxx()-map2->getminx()+1;
+      //      int ys=map2->getmaxy()-map2->getminy()+1;
+      
+
+
+      PXChamferDistanceMap* map1=new PXChamferDistanceMap(stack[0]->getcontour(i),1,1,map2);//1,1,xs,ys);
+
+      for (int j=0;j<numbetween;j++)
+	{
+	  int fraction1=numbetween-j;
+	  int fraction2=j+1;
+	  if (j==0 && bias>0)
+	    fraction1++;
+	  
+	  PXChamferDistanceMap* map=new PXChamferDistanceMap(map1,map2,fraction1,fraction2);
+	  PXContour* cntr=map->extractContour();
+	  (stack[j+1]->getcontour(i))->copypoints(cntr);
+	  stack[j+1]->setzlevel(i,stack[0]->getzlevel(i));
+	  delete map;
+	  delete cntr;
+	}
+      delete map1;
+      delete map2;
+    }
+
+  /*  char line[200];
+  for (i=0;i<totalnumstacks;i++)
+    {
+      sprintf(line,"stack%d.cnt",i);
+      //stack[i]->SaveNuages(line);
+      }    */
+
+  return numbetween;
+}
+// --------------------------------------------------------------------------
+int PXContourStack::ensureAnticlockwise()
+{
+  return setDirection(1);
+}
+// ***********************************************************************
+int PXContourStack::ensureClockwise()
+{
+  return setDirection(-1);
+}
+// ***********************************************************************
+int PXContourStack::setDirection(int dir)
+{
+  for (int i=0;i<numcontours;i++)
+    contour[i]->setDirection(dir);
+  return 1;
+}
+// ***********************************************************************
+int PXContourStack::cleancopypoints(PXContourStack* other)
+{
+  int oldnumcontours=numcontours;
+  numcontours=other->getnumcontours();
+
+  int i;
+  for (i=0;i<other->getnumcontours();i++)
+    {
+      int np=other->getcontour(i)->getnumpoints();
+      if (np<3)
+	numcontours-=1;
+    }
+
+
+  if (numcontours==0)
+    return 0;
+  
+  if (oldnumcontours!=numcontours)
+      {
+	if (oldnumcontours>numcontours)
+	    {
+	      for (int i=numcontours;i<oldnumcontours;i++)
+		  delete contour[i];
+	    }
+	else
+	    {
+	      for (int i=oldnumcontours;i<numcontours;i++)
+		  contour[i]=new PXContour();
+	    }
+	
+      }
+  
+  int index=-1;
+  for (i=0;i<numcontours;i++)
+      {
+	int np=0;
+	while (np<3)
+	  {
+	    ++index;
+	    np=other->getcontour(index)->getnumpoints();
+	  }
+
+	contour[i]->copypoints(other->getcontour(index));
+	zlevel[i]=other->getzlevel(index);
+      }
+  return numcontours;
+}
+// ***********************************************************************
+
diff --git a/bioimagesuite30_src/numerics/pxcontourstack.h b/bioimagesuite30_src/numerics/pxcontourstack.h
new file mode 100644
index 0000000..d0e8ab2
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxcontourstack.h
@@ -0,0 +1,177 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pxcontourstack.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+_Module_Name : PXContourStack 
+
+_Description : A collection class which stores splines which are the XY cross-sections of a surface
+               
+
+_Call : 
+  PXContourStack();
+  PXContourStack(PXContourStack *old);
+
+_References : see pxcontour.h
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 19th December 1997
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXContourStack
+#define _PXContourStack
+#include "pxcontour.h"
+#include "pxgeometrystruct.h"
+#include "bis_znzlib.h"
+
+const int PXCONTOURSTACK_MAXLEVELS=1000;
+
+class PXContourStack  {
+
+  protected :
+
+  PXContour* contour[PXCONTOURSTACK_MAXLEVELS];
+  float      zlevel[PXCONTOURSTACK_MAXLEVELS];
+  int numcontours;
+
+  // ******************************************************************************
+  //          PUBLIC INTERFACE
+  // ******************************************************************************
+
+  public :
+
+  PXContourStack(PXContourStack *old,int zbetween,int mode);
+  PXContourStack(PXContourStack* old,int zbetween,int mode,int closedbottom,int closedtop,
+		 float apexdz=-1.0,float basedz=-1.0);
+  PXContourStack(int numberofcontours=2);
+
+  virtual ~PXContourStack();
+
+  // [A] Access Contours
+  // ------------------
+  virtual int  getnumpoints();
+  virtual int  getnumcontours()    { return numcontours; }
+  virtual int   getzbetween(float zdist);
+
+  // [B] Set / Get individual contours whole point sets
+  // -------------------------------------------------
+  virtual void copypoints(PXContourStack* other);
+  virtual int  cleancopypoints(PXContourStack* other);
+  virtual void initfromold(PXContourStack*,int zbetween,int mode);
+  virtual PXContour*   getcontour(int i)  { return contour[indexbounded(i)];}
+  virtual float        getzlevel(int i)   { return zlevel[indexbounded(i)];}
+
+  virtual void setellipticalcylinder(int np=12,float rx=5.0,float ry=5.0,float cx=50.0,float cy=50.0);
+
+  virtual void setcontour(int i,PXContour* spl);
+  virtual void setzlevel(int i,float zl);
+  virtual void shiftandscalez(float shift,float scale);
+  virtual int  ensureAnticlockwise();
+  virtual int  ensureClockwise();
+  virtual int  setDirection(int dir=1); // + = Anti , -1 =Clock
+  // [C] I/O Functions
+  // -----------------------------
+  virtual int Load(const char* filename);
+  virtual int Save(const char* filename,int complevel=0);
+
+  virtual int Save(const char* filename,float dist,float zdist,int mode=1,
+		   int clbottom=0,int cltop=0);
+  virtual int SaveIGES(const char* filename);
+  virtual int SaveIGES(const char* filename,float dist,float zdist,int mode=1,
+			 int clbottom=0,int cltop=0);
+  
+  virtual int SaveNuages(const char* filename,int complevel=0);
+  virtual int SaveNuages(const char* filename,float dist,float zdist,int mode=1,
+			 int clbottom=0,int cltop=0);
+  virtual int SaveNuages(FILE* fout);
+
+  virtual int SaveAbaqusRigid(const char* filename,int nodeoffset=200000,int index=1);
+
+  virtual int LoadNuages(gzFile fin);
+  virtual int LoadNuages(const char* filename);
+  
+
+  // [D] Alignment/Adjustment Operators
+  // ----------------------------------
+  virtual void  Equispace(float dist);
+  virtual void  Equisample(int npoints);
+
+  virtual void  selfalign();
+  virtual int   aligntocontourstack(PXContourStack* other);   
+
+  virtual void  Smooth(float sigma=1.0,int width=5);
+  int nonShrinkSmooth(float alpha,float beta,int iterations);
+  int nonShrinkSmooth2D(float ds,float sigma,int iterations);
+
+  // [E] Stack Statistics
+  // ---------------------------------
+  virtual void getPositionAndOrientation(float& cx,float& cy,float& cz,
+					 float& sx2,float& sy2,float& sxy,
+					 float& vol);
+
+  virtual float findnearestneighbour(float&x,float& y,float &z,float dt=0.01,int dbg=0);
+
+
+  protected :
+  virtual int   indexbounded(int v,int np=-1);
+
+  static  int   indexcyclic(int v,int np);
+  static  float getsqdist(float x1,float x2,float y1,float y2);
+
+  public :
+  static int aligncontours(PXContour* cntr1,PXContour* cntr2);
+  static int align2basecontours(PXContour* cntr0,PXContour* cntr1,PXContour* cntr2);
+  static int createstackset(PXContourStack** outputStacks,int totalnum=3,int bias=1);
+
+
+};
+
+
+
+#endif  
+
diff --git a/bioimagesuite30_src/numerics/pxcrystalabaqus.cpp b/bioimagesuite30_src/numerics/pxcrystalabaqus.cpp
new file mode 100644
index 0000000..0edb9ff
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxcrystalabaqus.cpp
@@ -0,0 +1,2232 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+#include "pxcrystalabaqus.h"
+#include "pxabaqussolid.h"
+#include "pxmarkerclass.h"
+#include "pxutil.h"
+
+
+// --------------------------------------------------------------------------
+int  PXCrystalAbaqus::debugmode=0;
+// --------------------------------------------------------------------------
+//    Access Functions 
+// ------------------------------------------------------------------------- 
+
+int      PXCrystalAbaqus::getnumframes()        { return numframes;}
+int      PXCrystalAbaqus::getnumgroups()        { return numgroups;}
+
+int      PXCrystalAbaqus::hasfemdata()          { return hasFemData;}
+int      PXCrystalAbaqus::hasdisplacements()    { return hasDisplacements;}
+int      PXCrystalAbaqus::hasnodes()            { return hasNodes;}
+int      PXCrystalAbaqus::hasextranodes()            { return hasExtraNodes;}
+int      PXCrystalAbaqus::haselements()         { return hasElements;}
+
+PXNeighboursList*     PXCrystalAbaqus::getelements()       { return elements;}
+PXSolidNodes*         PXCrystalAbaqus::getnodes()          { return nodes;}
+PXSolidNodes*         PXCrystalAbaqus::getextranodes()          { return extraNodes;}
+
+PXNodalDisplacements* PXCrystalAbaqus::getdisplacements(int i)  
+{ return displacements[Irange(i,0,numframes-1)];}
+PXAbaqusOutputData*   PXCrystalAbaqus::getfemdata()        { return femData;}
+
+// ------------------------------------------------------------------------- 
+
+PXCrystalAbaqus::PXCrystalAbaqus()
+{
+  init();
+}
+
+PXCrystalAbaqus::PXCrystalAbaqus(PXCrystalAbaqus* old)
+{
+  init();
+  Copy(old);
+}
+// --------------------------------------------------------------------------
+PXCrystalAbaqus::PXCrystalAbaqus(PXMarkerCollection* markers)
+{
+  init();
+  numframes=markers->getmarker(0)->getnumframes();
+  nodes=new PXSolidNodes(markers->getnummarkers());
+  int i;
+  for (i=0;i<markers->getnummarkers();i++)
+      {
+	nodes->setindex(i,0,i);
+	nodes->setindex(i,1,0);
+	for (int ia=0;ia<=2;ia++)
+	    nodes->getpoint(i)->x[ia]=markers->getmarker(i)->getcomponent(0,ia);
+      }
+  hasNodes=1;
+  for (i=0;i<numframes;i++)
+      displacements[i]=new PXNodalDisplacements(nodes,0,100);
+  hasDisplacements=1;
+
+  for (int j=0;j<nodes->getnumnodes();j++)
+      for (int i=0;i<numframes;i++)
+	  for (int ia=0;ia<=2;ia++)
+	      displacements[i]->setdispcomponent(j,ia,
+						 markers->getmarker(j)->getcomponent(i,ia)-
+						 markers->getmarker(j)->getcomponent(0,ia));
+}
+// --------------------------------------------------------------------------
+PXCrystalAbaqus::PXCrystalAbaqus(PXMarkerCollection* markers,int frameinc,int maxframes)
+{
+  init();
+  int actualframes=markers->getmarker(0)->getnumframes();
+  
+  fprintf(stderr,"Numframes=%d actualframes=%d\n",numframes,actualframes);
+
+  if (actualframes<2)
+      return;
+
+  if (maxframes==-1)
+      maxframes=actualframes;
+  else
+      maxframes=Irange(maxframes,2,actualframes);
+  
+  fprintf(stderr,"Maxframes=%d actualframes=%d\n",maxframes,actualframes);
+  frameinc=Irange(frameinc,1,actualframes);
+
+  if (frameinc>1)
+      {
+	numframes=0;
+	for (int j=0;j<maxframes;j+=frameinc)
+	    ++numframes;
+      }
+  else
+      numframes=actualframes;
+  
+  nodes=new PXSolidNodes(markers->getnummarkers());
+  int i;
+  for (i=0;i<markers->getnummarkers();i++)
+      {
+	nodes->setindex(i,0,i);
+	nodes->setindex(i,1,0);
+	for (int ia=0;ia<=2;ia++)
+	    nodes->getpoint(i)->x[ia]=markers->getmarker(i)->getcomponent(0,ia);
+      }
+  hasNodes=1;
+  for (i=0;i<numframes;i++)
+      displacements[i]=new PXNodalDisplacements(nodes,0,100);
+  hasDisplacements=1;
+
+  int fr=0;
+  fprintf(stderr,"Numframes=%d actualframes=%d\n",numframes,actualframes);
+  for (i=0;i<maxframes;i+=frameinc)
+      {
+	fprintf(stderr,"Actual frame %d, Analysis frame %d\n",i,fr);
+	for (int j=0;j<nodes->getnumnodes();j++)
+	    {
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    if (fabs(markers->getmarker(j)->getcomponent(i,ia))>0.01)
+			displacements[fr]->setdispcomponent(j,ia,
+							    markers->getmarker(j)->getcomponent(i,ia)-
+							    markers->getmarker(j)->getcomponent(0,ia));
+		    else
+			displacements[fr]->setdispcomponent(j,ia,0.0);
+		    if (j==0)
+			fprintf(stderr,"Mark=%d Frame=%d,Comp=%d %f (%f-%f)\n",
+				j,i,ia,displacements[fr]->getdispcomponent(j,ia),
+				markers->getmarker(j)->getcomponent(i,ia),
+				markers->getmarker(j)->getcomponent(0,ia));
+		  }
+	    }
+	fr++;
+      }
+  numframes=fr;
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::Copy(PXCrystalAbaqus* other)
+{
+  cleanup();
+  init();
+
+  numframes=other->getnumframes();
+
+  if (other->haselements())
+      {
+	elements=new PXNeighboursList();
+	elements->Copy(other->getelements());
+	hasElements=1;
+      }
+  
+  if (other->hasnodes())
+      {
+	nodes=new PXSolidNodes(other->getnodes());
+	hasNodes=1;
+      }
+
+  if (other->hasextranodes())
+      {
+	extraNodes=new PXSolidNodes(other->getextranodes());
+	hasExtraNodes=1;
+      }
+
+  if (other->hasfemdata())
+      {
+	femData=new PXAbaqusOutputData(other->getfemdata());
+	hasFemData=1;
+      }
+
+  if (other->hasdisplacements())
+      {
+	for (int i=0;i<numframes;i++)
+	    displacements[i]=new PXNodalDisplacements(other->getdisplacements(i));
+      }
+}
+// --------------------------------------------------------------------------
+PXCrystalAbaqus::PXCrystalAbaqus(const char* fname1,const char* fname2)
+{
+  init();
+  createFromCrystalFiles(fname1,fname2);
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::init()
+{
+  numframes=0;    numgroups=0;  
+  hasElements=0;  hasNodes=0;   hasDisplacements=0; hasFemData=0; hasExtraNodes=0;
+}
+// --------------------------------------------------------------------------
+PXCrystalAbaqus::~PXCrystalAbaqus()
+{
+  cleanup();
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::cleanup()
+{
+  cleanupElementSpace();
+  cleanupNodeSpace();
+  
+  if (hasfemdata())
+      cleanupFemData();
+
+  if (hasdisplacements())
+      cleanupDisplacements();
+
+  if (hasextranodes())
+      {
+	delete extraNodes;
+	hasExtraNodes=0;
+      }
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::cleanupDisplacements()
+{
+  if (hasdisplacements())
+      {
+	for (int i=0;i<numframes;i++)
+	    delete displacements[i];
+	hasDisplacements=0;
+      }
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::allocateDisplacements()
+{
+  if (hasdisplacements())
+      cleanupDisplacements();
+  if (numframes>0 && hasnodes())
+      {
+	for (int i=0;i<numframes;i++)
+	    displacements[i]=new PXNodalDisplacements(nodes,0,100);
+	hasDisplacements=1;
+      }
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::cleanupFemData()
+{
+  if (hasfemdata())
+      delete femData;
+  hasFemData=0;
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::cleanupElementSpace()
+{
+  if (haselements())
+      delete elements;
+  hasElements=0;
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::cleanupNodeSpace()
+{
+  if (hasnodes())
+      delete nodes;
+
+  hasNodes=0;
+
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::allocateFemData()
+{
+  if (hasfemdata())
+      cleanupFemData();
+  
+  if (!haselements() || !hasnodes())
+      return;
+  femData=new PXAbaqusOutputData(nodes->getnumnodes(),elements->getnumnodes());
+  hasFemData=1;
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::allocateNodeSpace(int numnode)
+{
+  if (hasnodes())
+      cleanupNodeSpace();
+  
+  nodes=new PXSolidNodes(numnode);
+  hasNodes=1;
+  
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::allocateElementSpace()
+{
+  if (haselements())
+      cleanupElementSpace();
+
+  elements=new PXNeighboursList();
+  hasElements=1;
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::setorientations(int group,PX3Vector& radial,PX3Vector& circum,PX3Vector& longit)
+{
+  // Only do real groups
+  int debug=1;
+
+  group=Irange(group,2,numgroups-1);
+  if (debug) fprintf(stderr,"---------Orientation group %d----------------------------\n\n",group);  
+  // First the radial direction
+  
+  elements->Rewind();
+
+  // Max of 10 lines 0--9
+  int* point1=new int[10];
+  int* point2=new int[10];
+
+  int i;
+  for (i=0;i<10;i++)
+      {
+	point1[i]=-1;
+	point2[i]=-1;
+      }
+
+  for (i=0;i<nodes->getnumnodes();i++)
+      {
+	if (nodes->getindex(i,0)==group)
+	    {
+	      int index2=nodes->getindex(i,1);
+	      if (index2<10)
+		    point1[index2]=i;
+	      else if (index2>=100)
+		  point2[index2-100]=i;
+	    }
+      }
+  
+  radial.setvector(0.0,0.0,0.0);
+  int flag=1;
+  if (debug) fprintf(stderr,"Cube = %d \n Radial Direction\n",group);
+  for (i=0;i<10;i++)
+      {
+	if (point1[i]>=0 && point2[i]>=0)
+	    {
+	      if (debug) fprintf(stderr,"i=%d endo =%d epi=%d\n",i,point1[i]+1,point2[i]+1);
+	      radial.setvector(radial.x[0]+nodes->getpoint(point1[i])->x[0]-nodes->getpoint(point2[i])->x[0],
+			       radial.x[1]+nodes->getpoint(point1[i])->x[1]-nodes->getpoint(point2[i])->x[1],
+			       radial.x[2]+nodes->getpoint(point1[i])->x[2]-nodes->getpoint(point2[i])->x[2]);
+	      flag++;
+	    }
+      }
+  if (flag>0)
+      radial.normalize();
+  else
+      radial.setvector(1.0,0.0,0.0);
+
+  delete [] point1;  delete [] point2;
+
+
+  // Longitudinal Next 
+  // -----------------
+  longit.setvector(0.0,0.0,1.0);
+  // Find second element internal reference
+  if (debug) fprintf(stderr,"Cube = %d \n Long Direction\n",group);
+  elements->Rewind(); 
+  PXIntegerList* intList=new PXIntegerList;
+  for (int e=0;e<elements->getnumnodes();e++)
+      {
+	if (elements->getcurrentnode()->index==1)
+	    {
+	      PXIntegerList* intList2=((elements->getcurrentnode())->points);
+	      intList2->Rewind();
+	      for (int ia=0;ia<intList2->getnumnodes();ia++)
+		  {
+		    intList->AddNonDuplicate(intList2->getcurrent(),-1);
+		    intList2->Next();
+		  }
+	    }
+	elements->Next();
+      }
+  int* pt=new int[intList->getnumnodes()];
+  intList->Rewind();
+  for (i=0;i<intList->getnumnodes();i++)
+      {
+	pt[i]=intList->getcurrent();
+	intList->Next();
+      }
+
+  if (intList->getnumnodes()==2)
+      {
+	longit.setvector(nodes->getpoint(pt[1])->x[0]-nodes->getpoint(pt[0])->x[0],
+			 nodes->getpoint(pt[1])->x[1]-nodes->getpoint(pt[0])->x[1],
+			 nodes->getpoint(pt[1])->x[2]-nodes->getpoint(pt[0])->x[2]);
+      }
+  else if (intList->getnumnodes()==3)
+      {
+	if (debug) fprintf(stderr,"Using nodes pt[1]=%d, pt[2]=%d and apex(pt[0])=%d\n",pt[1]+1,pt[2]+1,pt[0]+1);
+	longit.setvector(0.5*(
+			      nodes->getpoint(pt[1])->x[0]+nodes->getpoint(pt[2])->x[0])
+			 -nodes->getpoint(pt[0])->x[0],
+			 0.5*(
+			      nodes->getpoint(pt[1])->x[1]+nodes->getpoint(pt[2])->x[1])
+			 -nodes->getpoint(pt[0])->x[1],
+			 0.5*(nodes->getpoint(pt[1])->x[2]+nodes->getpoint(pt[2])->x[2])
+			 -nodes->getpoint(pt[0])->x[2]);
+      }
+
+  delete [] pt;
+  delete intList;
+
+  // Orthogonalization Step
+  longit.normalize();
+  
+  /* This assumes radial correct
+  float dotp=longit.dotwith(&radial);
+  longit.subtract(&radial,dotp);  
+  longit.normalize();*/
+
+  // This assumes long correct
+  float dotp=longit.dotwith(&radial);
+  radial.subtract(&longit,dotp);  
+  radial.normalize();
+
+
+  /* Iterate over both 
+  for (int k=0;k<=9;k++)
+      {
+	float dotp=longit.dotwith(&radial);
+	longit.subtract(&radial,dotp*0.2);  
+	longit.normalize();
+	float dotp2=longit.dotwith(&radial);
+	radial.subtract(&longit,dotp*0.2);
+	radial.normalize();
+	fprintf(stderr,"dotp=%6.2f dotp2=%6.2f\n",dotp,dotp2);
+      }
+  float dotp=longit.dotwith(&radial);
+  longit.subtract(&radial,dotp*0.5);  
+  longit.normalize();*/
+  float dotp2=longit.dotwith(&radial);
+  fprintf(stderr,"dotp=%6.2f dotp2=%6.2f\n",dotp,dotp2);
+	
+  // Circumferential Vector
+  circum.copy(&radial);  
+  circum.crosswithoverwrite(&longit); 
+  circum.normalize();
+
+  if (debug) fprintf(stderr,"-----------------------%d----------------------------------\n\n",group);  
+}
+// --------------------------------------------------------------------------
+int PXCrystalAbaqus::saveAbaqus(const char* fname,int resout,int usenumframes,int skipframes)
+{
+  if (!hasnodes() ||  !hasdisplacements() || !haselements())
+      {
+	fprintf(stderr,"No nodes,elements or displacements\n");
+	return 0;
+      }
+
+  if (usenumframes==-1)
+      usenumframes=numframes;
+  skipframes=Irange(skipframes,1,usenumframes);
+
+  char* abname=anacreatefilename(fname,".inp",".crt");
+  fprintf(stderr,"%s --> %s (%d skip %d)\n",fname,abname,usenumframes,skipframes);
+
+  FILE* fout=fopen(abname,"w");
+
+  if (!fout)
+      {
+	delete [] abname;
+	return 0;
+      }
+
+  fprintf(fout,"*HEADING\nMyocardium Model\n");
+  fprintf(fout,"** Numsteps=%d numnodes=%d, numelements=%d\n",usenumframes,nodes->getnumnodes(),
+	  elements->getnumnodes());
+  fprintf(fout,"** ----------------------------------------------------\n");
+  fprintf(fout,"** Shrink .dat file\n*PREPRINT,ECHO=NO,MODEL=NO,HISTORY=NO\n**\n");
+
+  fprintf(fout,"** ----------Material Model --------------------------------------\n");
+  fprintf(fout,"*MATERIAL,NAME=TISSUE\n*ELASTIC\n");
+  fprintf(fout,"%7.3f,%7.3f\n",1.0,0.3);
+  
+  fprintf(fout,"** ---------- Nodes  --------------------------------------\n");
+  
+  fprintf(fout,"*NODE,NSET=ALLNODES\n");
+  
+  for (int i=0;i<nodes->getnumnodes();i++)
+      {
+	if (nodes->getindex(i,0)>=0)
+	    {
+	      fprintf(fout," %5d , %7.3f , %7.3f , %7.3f \n",
+		      i+1,
+		      nodes->getpoint(i)->x[0],
+		      nodes->getpoint(i)->x[1],
+		      nodes->getpoint(i)->x[2]);
+	    }
+      }
+
+  if (hasextranodes())
+      {
+	for (int i=0;i<extraNodes->getnumnodes();i++)
+	    {
+	      if (extraNodes->getindex(i,0)>=0)
+		  {
+		    fprintf(fout," %5d , %7.3f , %7.3f , %7.3f \n",
+			    i+1+nodes->getnumnodes(),
+			    extraNodes->getpoint(i)->x[0],
+			    extraNodes->getpoint(i)->x[1],
+			    extraNodes->getpoint(i)->x[2]);
+		  }
+	      
+	    }
+      }
+  fprintf(fout,"**\n*NSET, NSET=N_DUMMY\n1\n");
+  
+  fprintf(fout,"** ---------- Elements --------------------------------------\n");  
+  // This is trickier but
+  // 2 nodes --- Truss       T3D2
+  // 3 nodes --  3xT3D2
+  // 4 nodes --  Tetrahedron C3D4
+  // 6 nodes --  Prism       C3D6
+  // 8 nodes --  Hexahedron  C3D8
+
+  char line[100],orient[20];
+  int elno=1;
+
+  int numgood[10];
+
+  for (int gr=0;gr<numgroups;gr++)
+      {
+	if (gr>1)
+	    {
+	      PX3Vector rad,circ,longit;
+	      setorientations(gr,rad,circ,longit);
+	      sprintf(orient,"ORIENT%d",gr+1);
+	      fprintf(fout,"**\n*ORIENTATION,NAME=%s,SYSTEM=RECTANGULAR\n",orient);
+	      fprintf(fout,"%8.5f,%8.5f,%8.5f, %8.5f,%8.5f,%8.5f\n",
+		      rad.x[0],rad.x[1],rad.x[2],
+		      circ.x[0],circ.x[1],circ.x[2]);
+	    }
+	int numn;
+	for (numn=2;numn<8;numn++)
+	    numgood[numn]=0;
+
+	for (numn=2;numn<8;numn++)
+	    {
+	      if (numn==5)
+		  numn++;
+	      
+	      elements->Rewind();
+	      for (int el=0;el<elements->getnumnodes();el++)
+		  {
+		    PXIntegerList* intList=((elements->getcurrentnode())->points);
+		    if (intList->getnumnodes()==numn && elements->getcurrentnode()->index==gr)
+			{
+			  /*fprintf(stderr,"Element = %d ,  numnodes=%d , index=%d:group=%d\n",
+				  el, intList->getnumnodes(), elements->getcurrentnode()->index,gr);*/
+			  numgood[numn]++;
+			}
+		    elements->Next();
+		  }
+	      
+	      if (numgood[numn]>0)
+		  {
+		    sprintf(line,"E_E%02d%02d",numn,gr);
+		    switch (numn)
+			{
+			case 2:
+			  fprintf(fout,"*ELEMENT, TYPE=T3D2, ELSET=%s\n",line);
+			  break;
+			case 3:
+			  fprintf(fout,"*ELEMENT, TYPE=T3D2, ELSET=%s\n",line);
+			  break;
+			case 4:
+			  fprintf(fout,"*ELEMENT, TYPE=C3D4, ELSET=%s\n",line);
+			  break;
+			case 6:
+			  fprintf(fout,"*ELEMENT, TYPE=C3D6, ELSET=%s\n",line);
+			  break;
+			case 8:
+			  fprintf(fout,"*ELEMENT, TYPE=C3D8, ELSET=%s\n",line);
+			  break;
+			}
+		    
+		    elements->Rewind();
+		    for(int el=0;el<elements->getnumnodes();el++)
+			{
+			  PXIntegerList* intList=((elements->getcurrentnode())->points);
+			  if (intList->getnumnodes()==numn && elements->getcurrentnode()->index==gr)
+			      {
+				if (numn!=3)
+				    {
+				      fprintf(fout,"%d,",elno);
+				      PXIntegerList* intList=((elements->getcurrentnode())->points);
+				      for (int i=0;i<intList->getnumnodes();i++)
+					  {
+					    fprintf(fout,"%d",intList->getcurrent()+1);
+					    if (i!=intList->getnumnodes()-1)
+						fprintf(fout,",");
+					    else
+						fprintf(fout,"\n");
+					    intList->Next();
+					  }
+				      elno++;
+				    }
+				else
+				    {
+				      int pp[3];
+				      intList->Rewind();
+				      for (int ia=0;ia<=2;ia++)
+					  {
+					    pp[ia]=intList->getcurrent()+1;
+					    intList->Next();
+					  }
+				      fprintf(fout,"%d,%d,%d\n",elno,pp[0],pp[1]);
+				      elno++;
+				      fprintf(fout,"%d,%d,%d\n",elno,pp[1],pp[2]);
+				      elno++;
+					    fprintf(fout,"%d,%d,%d\n",elno,pp[0],pp[2]);
+				      elno++;
+				    }
+			      }
+			  elements->Next();
+			}
+		    if (gr<2)
+			{
+			  fprintf(fout,"*SOLID SECTION, ELSET=%s,MATERIAL=TISSUE\n**\n** End of group %d \n**\n",
+				  line,gr+1);
+			}
+		    else
+			{
+			  fprintf(fout,"*SOLID SECTION, ELSET=%s,MATERIAL=TISSUE,ORIENTATION=%s\n",
+				  line,orient);
+			  fprintf(fout,"**\n** End of group %d \n**\n",gr+1);
+			}
+		  }
+	    }
+      }
+  fprintf(fout,"**\n");
+  fprintf(fout,"*ELSET, ELSET=E_DUMMY\n1\n**\n");
+
+  for (int fr=0;fr<usenumframes;fr+=skipframes)
+      {
+	fprintf(fout,"** -------------------- Frame %d ---------------------------\n**\n",fr+1);
+	fprintf(fout,"*STEP,NLGEOM,AMPLITUDE=RAMP,INC=40\n");
+	fprintf(fout,"*STATIC\n %f,1.0,0.00005,1.0\n",1.0);
+	fprintf(fout,"**\n");
+	fprintf(fout,"** Accuracy Controls\n*CONTROLS,PARAMETERS=FIELD,FIELD=DISPLACEMENT\n");
+	fprintf(fout,"0.01,1.0,10.0,  ,  , 1.E-3\n");
+	fprintf(fout,"*BOUNDARY,OP=NEW\n");
+	for (int i=0;i<displacements[fr]->getsolidnodes()->getnumnodes();i++)
+	    {
+	      if (displacements[fr]->getsolidnodes()->getindex(i,0)>=0)
+		  {
+		    for (int j=0;j<3;j++)
+			fprintf(fout,"%d , %d , %d, %8.4f\n",i+1,j+1,j+1,
+				displacements[fr]->getdispcomponent(i,j));
+		  }
+	    }
+	fprintf(fout,"**\n*EL PRINT,POSITION=CENTROIDAL,ELSET=E_DUMMY\nE11\n");
+	fprintf(fout,"*NODE PRINT,NSET=N_DUMMY\nU1\n");
+	fprintf(fout,"*EL FILE,POSITION=CENTROIDAL\nE\n");
+	fprintf(fout,"*EL FILE\nEVOL\n*NODE FILE,NSET=ALLNODES\nU\n");
+	if (resout>0)
+	    fprintf(fout,"*RESTART,WRITE\n");
+	fprintf(fout,"*END STEP\n");
+      }
+  fprintf(stderr,"** Resout=%d\n",resout);
+  fclose(fout);
+  return 1;
+}
+// -------------------------------------------------------------------------
+void PXCrystalAbaqus::getElementCentroid(PXIntegerList* element,float&x,float&y,float& z)
+{
+  float cx[3];
+  for (int ia=0;ia<=2;ia++)
+      cx[ia]=0.0;
+
+  if (!hasnodes() || !haselements())
+      return;
+
+  element->Rewind();
+  for (int i=0;i<element->getnumnodes();i++)
+      {
+	int nd=element->getcurrent();
+	for (int ia=0;ia<=2;ia++)
+	    {
+	      cx[ia]+=nodes->getpoint(nd)->x[ia];
+	      if (hasfemdata())
+		  cx[ia]+=femData->getdispcomponent(nd,ia);
+	    }
+	element->Next();
+      }
+  
+  x=cx[0]/float(element->getnumnodes());
+  y=cx[1]/float(element->getnumnodes());
+  z=cx[2]/float(element->getnumnodes());
+}
+// --------------------------------------------------------------------------
+int PXCrystalAbaqus::saveInventor(const char* fname,int mode,int cmode,float* params)
+{
+  if (!haselements() || !hasnodes())
+      return 0;
+
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+      return 0;
+  int st=saveInventor(fout,mode,cmode,params);
+  fclose(fout);
+  return st;
+}
+// --------------------------------------------------------------------------
+int PXCrystalAbaqus::saveInventor(FILE* fout,int mode,int cmode,float* params)
+{
+  if (hasfemdata())
+      cmode=Irange(cmode,0,11);
+  else 
+      cmode=-1;
+  if (!haselements() || !hasnodes())
+      return 0;
+
+  fprintf(fout, "#Inventor V2.0 ascii\n\n");
+
+  int index[8],i=0,j=0;
+  PXTriangle triangle[12];
+  int numt=12;
+
+  int nel=elements->getnumnodes();
+  int bel=0;
+
+  if (hasfemdata())
+      {
+	for(i=0; i<nodes->getnumnodes(); i++)
+	    for (j=0;j<=2;j++)
+		nodes->getpoint(i)->x[j]+=(femData->getdisplacement(i))->x[j]; 
+	
+	if (hasextranodes())
+	    {
+	      for (i=0;i<extraNodes->getnumnodes();i++)
+		  for (j=0;j<=2;j++)
+		      extraNodes->getpoint(i)->x[j]+=(femData->getdisplacement(i+nodes->getnumnodes()))->x[j]; 
+	    }
+      }
+
+
+  fprintf(fout, "Coordinate3 { point [ ");
+  int a=1;
+  if (hasextranodes())
+      a=0;
+  for(i=0; i<nodes->getnumnodes()-a; i++)
+      fprintf(fout, "\n\t\t %4.2f %4.2f %4.2f,", 
+	      nodes->getpoint(i)->x[0], nodes->getpoint(i)->x[1], nodes->getpoint(i)->x[2]);		
+  if (!hasextranodes())
+      {
+	i = nodes->getnumnodes()-1;
+	fprintf(fout, "\n\t\t %4.2f %4.2f %4.2f]\n\t}\n", 
+		nodes->getpoint(i)->x[0], nodes->getpoint(i)->x[1], nodes->getpoint(i)->x[2]);		  
+      }
+  else
+      {
+	for(i=0; i<extraNodes->getnumnodes()-1; i++)
+	    fprintf(fout, "\n\t\t %4.2f %4.2f %4.2f,", 
+		    extraNodes->getpoint(i)->x[0], 
+		    extraNodes->getpoint(i)->x[1], 
+		    extraNodes->getpoint(i)->x[2]);		
+	i = extraNodes->getnumnodes()-1;
+	fprintf(fout, "\n\t\t %4.2f %4.2f %4.2f]\n\t}\n", 
+		extraNodes->getpoint(i)->x[0], 
+		extraNodes->getpoint(i)->x[1], 
+		extraNodes->getpoint(i)->x[2]);		  
+      }
+
+  int hasface=0,hasline=0;
+  elements->Rewind();
+  for (i=0;i<bel;i++)
+      elements->Next();
+  for (i=bel;i<nel;i++)
+      {
+	PXIntegerList* intList=((elements->getcurrentnode())->points);
+	if (intList->getnumnodes()>3)
+	    hasface++;
+	else
+	    hasline++;
+	elements->Next();
+      }
+
+  //  fprintf(stderr,"Hasface=%d hasline=%d\n",hasface,hasline);
+
+  if (hasface>0)
+      {
+	
+	fprintf(fout, "Separator {\n");		    
+	fprintf(fout, "\tShapeHints { \n");	
+	fprintf(fout, "\t  vertexOrdering  COUNTERCLOCKWISE \n");	
+	fprintf(fout, "\t  faceType CONVEX \n");	
+	fprintf(fout, "\t }\n");	
+	if (mode>=0 && cmode>=0)
+	    {
+	      /* write out the material (color) of each triangular facet */
+
+	      fprintf(fout, "\tMaterial { diffuseColor [ ");		
+	      elements->Rewind();
+	      for(i=0; i<bel; i++)
+		  elements->Next();
+	      for(i=bel; i<nel; i++)
+		  {
+		    PXIntegerList* intList=((elements->getcurrentnode())->points);
+		    intList->Rewind();
+		    int n=intList->getnumnodes();
+		    if (n>3)
+			{
+			  PX3Vector color;
+			  if (mode>0)
+			      PXAbaqusSolid::color_lookup(color,femData->getstraincomponent(i,cmode),params,mode);
+			  else
+			      {
+				int pi=Icyclic(femData->getpieindex(i),3);
+				switch(pi)
+				    {
+				    case 0:
+				      color.x[0]=1.0; color.x[1]=0.0; color.x[2]=0.0; break;
+				    case 1:
+				      color.x[0]=0.0; color.x[1]=1.0; color.x[2]=0.0; break;
+				    case 2:
+				      color.x[0]=0.8; color.x[1]=0.8; color.x[2]=0.0; break;
+				    }
+			      }
+			  switch(n)
+			      {
+			      case 4:
+				numt=4;
+			      case 6:
+				numt=8;
+			      case 8:
+				numt=4; /*12*/
+				break;
+			      }
+			  
+			  for(j=0; j<numt; j++)
+			      {
+				if (j<(numt-1) || i<nel-1)
+				    fprintf(fout, "\n\t\t %4.2f %4.2f %4.2f,", 
+					    color.x[0], color.x[1], color.x[2]);
+				else
+				    fprintf(fout, "\n\t\t %4.2f %4.2f %4.2f]\n\t}\n",
+					    color.x[0], color.x[1], color.x[2]);
+			      }
+			}
+		    elements->Next();
+		  }
+	      fprintf(fout, "\tMaterialBinding {\n\tvalue PER_FACE\n}\n");
+	    }
+
+
+	/* write out the facet index */ 
+	fprintf(fout, "\tIndexedFaceSet {\n\t coordIndex  [ \n");
+	elements->Rewind();
+	for(i=0; i<bel;i++)
+	    elements->Next();
+	for(i=bel; i<nel; i++)
+	    {
+	      PXIntegerList* intList=((elements->getcurrentnode())->points);
+	      if (intList->getnumnodes()>3)
+		  {
+		    intList->Rewind();
+		    for (int ia=0;ia<intList->getnumnodes();ia++)
+			{
+			  index[ia]=intList->getcurrent();
+			  intList->Next();
+			}
+		    switch(intList->getnumnodes())
+			{
+			case 8:
+			  numt=4;
+			  triangle[0].p[0]=index[0]; triangle[0].p[1]=index[1]; triangle[0].p[2]=index[2];  
+			  triangle[1].p[0]=index[0]; triangle[1].p[1]=index[2]; triangle[1].p[2]=index[3];  
+			  {
+			    for (int tr=2;tr<=3;tr++)
+				for (int p=0;p<=3;p++)
+				    triangle[tr].p[p]=triangle[tr-2].p[p]+4;
+			  }
+			  /*triangle[2].p[0]=index[1]; triangle[2].p[1]=index[5]; triangle[2].p[2]=index[6];  
+			    triangle[3].p[0]=index[2]; triangle[3].p[1]=index[6]; triangle[3].p[2]=index[2];  */
+			  
+			  triangle[4].p[0]=index[4]; triangle[4].p[1]=index[7]; triangle[4].p[2]=index[6];  
+			  triangle[5].p[0]=index[5]; triangle[5].p[1]=index[4]; triangle[5].p[2]=index[6];  
+			  triangle[6].p[0]=index[0]; triangle[6].p[1]=index[4]; triangle[6].p[2]=index[7];  
+			  triangle[7].p[0]=index[3]; triangle[7].p[1]=index[3]; triangle[7].p[2]=index[7];  
+			  triangle[8].p[0]=index[3]; triangle[8].p[1]=index[2]; triangle[8].p[2]=index[6];  
+			  triangle[9].p[0]=index[7]; triangle[9].p[1]=index[7]; triangle[9].p[2]=index[3];  
+			  triangle[10].p[0] = index[4]; triangle[10].p[1] = index[5]; triangle[10].p[2] = index[1];  
+			  triangle[11].p[0] = index[0]; triangle[11].p[1] = index[0]; triangle[11].p[2] = index[4];
+			  break;
+			  
+			case 6:
+			  numt=8;
+			  triangle[0].p[0]=index[0]; triangle[0].p[1]=index[1]; triangle[0].p[2]=index[2];  
+			  triangle[1].p[0]=index[0]; triangle[1].p[1]=index[1]; triangle[1].p[2]=index[3];  
+			  triangle[2].p[0]=index[1]; triangle[2].p[1]=index[3]; triangle[2].p[2]=index[4];  
+			  triangle[3].p[0]=index[1]; triangle[3].p[1]=index[4]; triangle[3].p[2]=index[5];  
+			  triangle[4].p[0]=index[1]; triangle[4].p[1]=index[5]; triangle[4].p[2]=index[2];  
+			  triangle[5].p[0]=index[0]; triangle[5].p[1]=index[3]; triangle[5].p[2]=index[2];  
+			  triangle[6].p[0]=index[5]; triangle[6].p[1]=index[3]; triangle[6].p[2]=index[2];  
+			  triangle[7].p[0]=index[3]; triangle[7].p[1]=index[4]; triangle[7].p[2]=index[5];  
+			  break;
+			  
+			case 4:
+			  numt=4;
+			  triangle[0].p[0]=index[0]; triangle[0].p[1]=index[1]; triangle[0].p[2]=index[2];  
+			  triangle[1].p[0]=index[0]; triangle[1].p[1]=index[1]; triangle[1].p[2]=index[3];  
+			  triangle[2].p[0]=index[0]; triangle[2].p[1]=index[2]; triangle[2].p[2]=index[3];  
+			  triangle[3].p[0]=index[1]; triangle[3].p[1]=index[2]; triangle[3].p[2]=index[3];  
+			}
+		    
+		    for(j=0; j<numt; j++)
+			{
+			  if (j<(numt-1) || i<nel-1)
+			      fprintf(fout, "\t\t%d,%d,%d,%d, \n", 
+				      triangle[j].p[0], triangle[j].p[1], triangle[j].p[2],-1);
+			  else
+			      fprintf(fout,"\t\t%d,%d,%d,%d \n", 
+				      triangle[j].p[0], triangle[j].p[1], triangle[j].p[2],-1);
+			}
+		  }
+	      elements->Next();
+	    }
+	fprintf(fout, "]}\n}\n");
+      }
+
+  if (hasline>0)
+      {
+	fprintf(fout, "Separator {\n");		    
+	fprintf(fout, "\tMaterial { diffuseColor [ 1.0 1.0 1.0 ]\n transparency [0.5 ] \n} ");		
+	fprintf(fout, "\tIndexedLineSet {\n\t coordIndex  [ \n");
+	elements->Rewind();
+	for(i=0; i<bel;i++)
+	    elements->Next();
+	for(i=bel; i<nel; i++)
+	    {
+	      PXIntegerList* intList=((elements->getcurrentnode())->points);
+	      if (intList->getnumnodes()<=3)
+		  {
+		    intList->Rewind();
+		    for (int ia=0;ia<intList->getnumnodes();ia++)
+			{
+			  index[ia]=intList->getcurrent();
+			  intList->Next();
+			}
+		    
+		    switch(intList->getnumnodes())
+			{
+			case 3:
+			  numt=3;
+			  triangle[0].p[0]=index[0]; triangle[0].p[1]=index[1];
+			  triangle[1].p[0]=index[0]; triangle[1].p[1]=index[2];
+			  triangle[2].p[0]=index[2]; triangle[2].p[1]=index[1];
+			  break;
+			  
+			case 2:
+			  numt=1;
+			  triangle[0].p[0]=index[0]; triangle[0].p[1]=index[1];
+			  break;
+			}
+		    
+		    for(j=0; j<numt; j++)
+			{
+			  if (j<(numt-1) || i<nel-1)
+			      fprintf(fout, "\t\t%d,%d,%d, \n", 
+				      triangle[j].p[0], triangle[j].p[1],-1);
+			  else
+			      fprintf(fout,"\t\t%d,%d,%d \n", 
+				      triangle[j].p[0], triangle[j].p[1],-1);
+			}
+		  }
+	      elements->Next();
+	    }
+	fprintf(fout, "]}\n}\n");
+      }
+
+  // Add Balls
+  if (nodes->getnumnodes()<32)
+      {
+	fprintf(fout, "Separator {\n");		    
+	
+	fprintf(fout, "\tMaterial { diffuseColor [ 1.0 1.0 0.0 ]\n transparency [0.5 ] \n} ");		
+	for (i=0;i<nodes->getnumnodes();i++)
+	    {
+	      fprintf(fout,"Separator {");
+	      fprintf(fout,"Transform {\n\ttranslation %6.2f %6.2f %6.2f\n  scaleFactor     1 1 1}\n",
+		      nodes->getpoint(i)->x[0],
+		      nodes->getpoint(i)->x[1],
+		      nodes->getpoint(i)->x[2]);
+	      fprintf(fout,"Sphere {  radius 1.0   }\n");
+	      fprintf(fout,"}");
+	    }
+	fprintf(fout,"}\n");
+      }
+
+
+  if (hasfemdata())
+      {
+	for(i=0; i<nodes->getnumnodes(); i++)
+	    {
+	      nodes->getpoint(i)->x[0]-=(femData->getdisplacement(i))->x[0]; 
+	      nodes->getpoint(i)->x[1]-=(femData->getdisplacement(i))->x[1];
+	      nodes->getpoint(i)->x[2]-=(femData->getdisplacement(i))->x[2];
+	    }
+	if (hasextranodes())
+	    {
+	      for (i=0;i<extraNodes->getnumnodes();i++)
+		  for (j=0;j<=2;j++)
+		      extraNodes->getpoint(i)->x[j]-=(femData->getdisplacement(i+nodes->getnumnodes()))->x[j]; 
+	    }
+	
+      }
+  return 1;
+}
+// --------------------------------------------------------------------------
+int PXCrystalAbaqus::createFromCrystalFiles(const char* classfile,const char* positionfile,float minvol,
+					    float minangle,int extra)
+{
+  int doextranodes=Irange(extra,0,2);
+  
+
+  FILE *fin;
+  fin=fopen(positionfile,"r");
+  if (!fin)
+      {
+	fprintf(stderr,"Cannot read %s\n",positionfile);
+	return(0);
+      }
+  
+  // Read the displacements file 
+  int numcrystals;
+  fscanf(fin,"%d\n%d\n",&numcrystals,&numframes);
+
+  if (numframes>0 && numframes<200 && numcrystals>0 && numcrystals<33)
+      {
+	nodes=new PXSolidNodes(numcrystals);
+	hasNodes=1;
+        allocateDisplacements();
+	fprintf(stderr,"Reading frames(%d) : crystals(%d)\n",numframes,numcrystals);
+      }
+  else
+      {
+	fprintf(stderr,"Invalid number of frames(%d) or crystals(%d)\n",numframes,numcrystals);
+	return 0;
+      }
+  
+  int fr;
+  for (fr=0;fr<numframes;fr++)
+      {
+	for (int cr=0;cr<numcrystals;cr++)
+	    {
+	      float tempx=0.0,tempy=0.0,tempz=0.0;
+	      fscanf(fin,"%f %f %f",&tempx,&tempy,&tempz);
+	      displacements[fr]->setdisplacement(cr,tempx,tempy,fabs(tempz));
+	    }
+	fscanf(fin,"\n");
+      }
+  fclose(fin);
+  
+  // Read the Class file and generate elements -- read once to count, second time to generate
+  
+  fin=fopen(classfile,"r");
+  if (!fin)
+      {
+	fprintf(stderr,"Cannot read %s\n",classfile);
+	cleanup();
+	return(0);
+      }
+
+  char line[200];
+  fgets(line,200,fin);
+  fprintf(stderr,"LIne=%s",line);
+  int st=strncmp(line, "#CRYSTAL CONFIGURATION",22);
+  if (st!=0)
+      {
+	fprintf(stderr,"Wrong header line %s in %s\n",line,classfile);
+	cleanup();
+	return(0);
+      }
+
+  fgets(line,200,fin);  fgets(line,200,fin); // Read 2 comment lines 
+
+  numgroups=0;
+  fscanf(fin,"%d\n",&numgroups);
+  
+  if (numgroups==0)
+      {
+	fprintf(stderr,"Bad number of groups %d in %s\n",numgroups,classfile);
+	cleanup();
+	return(0);
+      }
+
+  elements=new PXNeighboursList();
+  hasElements=1;
+  
+  // Make positions into real displacements
+  for (int c=0;c<numcrystals;c++)
+      for (int j=0;j<=2;j++)
+	  nodes->getpoint(c)->x[j]=displacements[0]->getdispcomponent(c,j);
+
+
+  for (fr=numframes-1;fr>=0;fr-=1)
+      for (int c=0;c<numcrystals;c++)
+	  for (int j=0;j<=2;j++)
+	      displacements[fr]->setdispcomponent(c,j,
+						  displacements[fr]->getdispcomponent(c,j)-
+						  displacements[0]->getdispcomponent(c,j));
+						    
+  int  points[100],pt2[10];
+ 
+  for (int k=0;k<=1;k++)
+      {
+	int numdepth=0;
+	fgets(line,200,fin);
+	fscanf(fin,"%d\n",&numdepth);
+	for (int j=0;j<numdepth;j++)
+	    {
+	      fscanf(fin,"%d",&points[j]);
+	      points[j]-=PXABCR_PT_OFFSET;
+	      nodes->setindex(points[j],0,k);
+	      nodes->setindex(points[j],1,j);
+	    }
+	if (numdepth==2)
+	    elements->AddN(points,numdepth,k);
+	else
+	    {
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    pt2[0]=points[ia];
+		    pt2[1]=points[Icyclic(ia+1,3)];
+		    elements->AddN(pt2,2,k);
+		  }
+	    }
+	fscanf(fin,"\n");
+      }
+  
+  // Data Groups
+
+  if (hasextranodes())
+      {
+	delete extraNodes;
+	hasExtraNodes=0;
+      }
+  if (doextranodes>0)
+      {
+	if (doextranodes==1)
+	    extraNodes=new PXSolidNodes( (numgroups-2));
+	if (doextranodes==2)
+	    extraNodes=new PXSolidNodes(5*4*(numgroups-2));
+	hasExtraNodes=1;
+      }
+
+  int usedqhull=0;
+  for (int group=2;group<numgroups;group++)
+      {
+	int nummid=0;
+	fgets(line,200,fin);
+	fprintf(stderr,"\nLine(%d)=%s",group,line);
+	int numdepth,numrows;
+	fscanf(fin,"%d %d\n",&numrows,&numdepth);
+	fprintf(stderr,"numrows=%d, numdepth=%d\n",numrows,numdepth);
+	int ind=0;
+	for (int i=0;i<numrows;i++)
+	    {
+	      for (int j=0;j<numdepth;j++)
+		  {
+		    int temp;
+		    fscanf(fin,"%d",&temp);
+		    if (temp>0)
+			{
+			  points[ind]=temp-PXABCR_PT_OFFSET;
+			  nodes->setindex(points[ind],0,group);
+			  if (j==0)
+			      nodes->setindex(points[ind],1,i);
+			  else if (j==numdepth-1)
+			      nodes->setindex(points[ind],1,100+i);
+			  else
+			      {
+				nodes->setindex(points[ind],1,j*25);
+				nummid++;
+			      }
+			  ind++;
+			}
+		  }
+	      fscanf(fin,"\n");
+	    }
+
+	if (doextranodes==1)
+	    {
+	      int pindex=(group-2);
+	      for (int j=0;j<=2;j++)
+		  {
+		    float temp=0.0;
+		    for (int i=0;i<ind;i++)
+			temp+=nodes->getpoint(points[i])->x[j];
+		    temp/=float(ind);
+		    extraNodes->getpoint(pindex)->x[j]=temp;
+		  }
+	      extraNodes->setindex(pindex,0,group);
+	      extraNodes->setindex(pindex,1,75);
+	      points[ind]=pindex+nodes->getnumnodes();
+	      ind++;
+	    }
+	else if (doextranodes==2)
+	    {
+	      int pointindex2[4];
+	      int pindex=5*4*(group-2);
+	      int nel0=elements->getnumnodes();
+
+	      doqhull(points,ind,group);
+	      
+	      int nel=elements->getnumnodes();
+	      float* vol=new float[nel-nel0+1];
+	      fprintf(stderr,"Nel=%d, nel0=%d\n",nel,nel0);
+
+	      elements->Rewind();
+	      int i;
+	      for (i=0;i<nel0;i++)
+		  elements->Next();      
+	      for (i=nel0;i<nel;i++)
+		  {
+		    PXIntegerList* intList=((elements->getcurrentnode())->points);
+		    intList->Rewind();
+		    for (int j=0;j<=3;j++)
+			{
+			  pointindex2[j]=intList->getcurrent();
+			  intList->Next();
+			}
+		    vol[i-nel0]=tetravolume(pointindex2);
+		    elements->Next();
+		  }
+	      
+	      for (int pass=0;pass<5;pass++)
+		  {
+		    float maxvol=0.0;
+		    int volindex=0;
+		    for (i=0;i<nel-nel0;i++)
+			{
+			  if (maxvol<vol[i])
+			      {
+				maxvol=vol[i];
+				volindex=i;
+			      }
+			}
+		    fprintf(stderr,"          -------------\n");
+		    fprintf(stderr,"Inserting centroids of tetra %d (%7.3f)\n",
+			    volindex+nel0+1,vol[volindex]);
+		    vol[volindex]=-1.0;
+		    elements->Rewind();
+		    for (int i=0;i<nel0+volindex;i++)
+			elements->Next();
+		    PXIntegerList* intList=((elements->getcurrentnode())->points);
+		    
+		    for (int count=0;count<=3;count++)
+			{
+			  for (int dim=0;dim<=2;dim++)
+			      {
+				intList->Rewind();
+				float tp=0.0;
+				for (int j=0;j<=3;j++)
+				    {
+				      int current=intList->getcurrent();
+				      intList->Next();
+				      float tp2=nodes->getpoint(current)->x[dim];
+				      fprintf(stderr,"(%d %6.2f) ",current,tp2);
+				      if (count==j)
+					  tp+=5.0*tp2;
+				      else
+					  tp+=tp2;
+				    }
+				tp*=0.125;
+				extraNodes->getpoint(pindex)->x[dim]=tp;
+				fprintf(stderr,"%6.2f \n",tp);
+			      }
+			  extraNodes->setindex(pindex,0,group);
+			  extraNodes->setindex(pindex,1,75);
+			  points[ind]=pindex+nodes->getnumnodes();
+			  ind++;
+			  pindex++;
+			  fprintf(stderr,")\n");
+			}
+		  }
+	      delete [] vol;
+	      elements->Rewind();
+	      for (i=0;i<elements->getnumnodes();i++)
+		  {
+		    if (elements->getcurrentnode()->index==group)
+			elements->getcurrentnode()->index=-1;
+		    elements->Next();
+		  }
+	      elements->RemoveInvalid();
+	    }
+	if (nummid==0 && doextranodes==0)
+	    {
+	      fprintf(stderr,"****** No midwall nodes\n");
+	      // Generate Elements by hand
+	      elements->AddN(points,ind,group);
+	    }
+	else
+	    {
+	      doqhull(points,ind,group);
+	      usedqhull=1;
+	    }
+      }
+  
+  if (usedqhull==1)
+      {
+	checkelements(minvol,minangle);
+	checkelements(minvol,minangle);
+	
+	int num=numcrystals;
+	if (hasextranodes())
+	    num+=extraNodes->getnumnodes();
+	int i;
+	for (i=0;i<num;i++)
+	    points[i]=0;
+	
+	elements->Rewind();  
+	for (int el=0;el<elements->getnumnodes();el++)
+	    {
+	      PXIntegerList* intList=((elements->getcurrentnode())->points);
+	      intList->Rewind();
+	      for (int pt=0;pt<intList->getnumnodes();pt++)
+		  {
+		    int nd=intList->getcurrent();
+		    points[nd]++;
+		    intList->Next();
+		  }
+	      elements->Next();
+	    }
+	
+	int bad=0;
+	
+	fprintf(stderr,"Bad crystals: ");
+	for (i=0;i<numcrystals;i++)
+	    {
+	      if (points[i]==0)
+		  {
+		    bad++;
+		    fprintf(stderr,"%d(%d:%d) , ",i+1,nodes->getindex(i,0),nodes->getindex(i,1));
+		    nodes->setindex(i,0,-1);
+		  }
+	    }
+	fprintf(stderr," number =%d \n",bad);
+      }
+  //elements->Save("elements.out");
+
+  return 1;
+}
+// --------------------------------------------------------------------------
+int PXCrystalAbaqus::saveSolid(const char* fname)
+{
+
+  char* abname=anacreatefilename(fname,".sld",".inp");
+  FILE* fout=fopen(abname,"w");
+  if (!fout)
+      return(0);
+
+  PXContourStack *c1=new PXContourStack(2);
+  c1->setellipticalcylinder(4,10.0,10.0,50.0,50.0);
+  PXTriangulatedStack* tstack[2];
+
+  tstack[0]=new PXTriangulatedStack(c1,0);
+  c1->setellipticalcylinder(4,15.0,15.0,50.0,50.0);
+  tstack[1]=new PXTriangulatedStack(c1,0);
+  delete c1;
+
+  if (!haselements() || !hasnodes())
+      return 0;
+
+  fprintf(fout,"#NewAbaqusSolid3\n");
+  fprintf(fout,"#Number of layers,points per slice \n");
+  fprintf(fout,"%d\n",2);
+  fprintf(fout,"%d\n",2);
+  for (int t=0;t<2;t++)
+      {
+	tstack[t]->Save(fout);
+	delete tstack[t];
+      }
+  fprintf(fout,"# ---------------------------------------------------\n");
+  fprintf(fout,"#Material Model\n");
+  fprintf(fout,"# No Material\n");
+  fprintf(fout,"# ---------------------------------------------------\n");
+  fprintf(fout,"# Solid Nodes\n");
+  if (hasextranodes())
+      {
+	PXSolidNodes* tempNodes=new PXSolidNodes(nodes,extraNodes);
+	tempNodes->Save(fout);
+	delete tempNodes;
+      }
+  else
+      nodes->Save(fout);
+  fprintf(fout,"# ---------------------------------------------------\n");
+  fprintf(fout,"# Spring Nodes\n");
+  fprintf(fout,"#No Spring Nodes\n");
+
+  fprintf(fout,"# ---------------------------------------------------\n");
+  fprintf(fout,"# Solid Elements\n");
+
+  elements->Save(fout);
+
+  fprintf(fout,"# ---------------------------------------------------\n");
+  fprintf(fout,"# Spring Elements\n"); 
+  fprintf(fout,"#No Spring Elements\n"); 
+  fprintf(fout,"# ---------------------------------------------------\n");
+  fprintf(fout,"#Numerical Constants\n");
+  fprintf(fout,"#Element Mode\n%d\n",8);
+  fprintf(fout,"#Output Step\n%6.3f\n",1.0);
+  fprintf(fout,"#Output Inc\n%d\n",40);
+  fprintf(fout,"#Enforcement Strategy\n%d\n",0);
+  fprintf(fout,"#Spring Multiplier\n%5.3f\n",1.0);
+  fprintf(fout,"#Orientation\n%d\n",1);
+  fclose(fout);
+  delete [] abname;
+  return 1;
+  
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::setPieIndices()
+{
+   if (!hasnodes() ||  !haselements())
+      {
+	fprintf(stderr,"No nodes orelements\n");
+	return ;
+      }
+  allocateFemData();
+  femData->setPieStats(numgroups,numgroups,1);
+  elements->Rewind();
+
+  for (int i=0;i<elements->getnumnodes();i++)
+      {
+	int pie=elements->getcurrentnode()->index;
+	femData->setElementPieIndex(i,pie);
+	elements->Next();
+      }
+}
+// --------------------------------------------------------------------------
+float PXCrystalAbaqus::trianglearea(int* points)
+{
+  PX3Vector v[3];
+  for (int i=0;i<=2;i++)
+      {
+	for (int j=0;j<=2;j++)
+	    v[i].x[j]=nodes->getpoint(points[i])->x[j];
+	if (i>0)
+	    v[i].subtract(&v[0]);
+      }
+  return 0.5*v[1].dotwith(&v[2]);
+  
+}
+// --------------------------------------------------------------------------
+float PXCrystalAbaqus::tetraminangle(int* points)
+{
+  PX3Vector v[4],normal[4];
+  int i;
+  for (i=0;i<=3;i++)
+      {
+	for (int j=0;j<=2;j++)
+	    v[i].x[j]=nodes->getpoint(points[i])->x[j];
+      }
+  
+  //  fprintf(stderr,"--------------------------------------------\n");
+  
+  for (i=0;i<=3;i++)
+      {
+	normal[3].setvector(0.0,0.0,0.0);
+	for (int j=1;j<=2;j++)
+	    {
+	      PX3Vector temp;
+	      int p0=i;
+	      int p1=Icyclic(i+j,4);
+	      int p2=Icyclic(i+j+1,4);
+
+	      normal[i].copy(&v[p1]);
+	      normal[i].subtract(&v[p0]);
+	      temp.copy(&v[p0]);
+	      temp.subtract(&v[p2]);
+
+	      normal[i].crosswithoverwrite(&temp); 
+	      normal[i].normalize();
+	    }
+      }
+
+  float minangle=180.0;
+  //fprintf(stderr,"Angles : ");
+  for (i=0;i<=2;i++)
+      for (int j=i+1;j<=3;j++)
+	  {
+	    float dotp=normal[i].dotwith(&normal[j]);
+	    float a=acos(dotp);
+	    a=a*180.0/M_PI;
+	    if (a>90.0)
+		a=180-a;
+	    //fprintf(stderr," %d:%d =%6.3f,",i,j,a);
+	    if (minangle>a)
+		minangle=a;
+	  }
+  //  fprintf(stderr," min=%6.3f\n",minangle);
+
+  return (minangle);
+}
+// --------------------------------------------------------------------------
+float PXCrystalAbaqus::tetravolume(int* points)
+{
+  PX3Vector v[4];
+  for (int i=0;i<=3;i++)
+      {
+	for (int j=0;j<=2;j++)
+	    {
+	      if (points[i]<nodes->getnumnodes())
+		  v[i].x[j]=nodes->getpoint(points[i])->x[j];
+	      else
+		  v[i].x[j]=extraNodes->getpoint(points[i]-nodes->getnumnodes())->x[j];
+	    }
+	if (i>0)
+	    v[i].subtract(&v[0]);
+      }
+  
+  v[2].crosswithoverwrite(&v[3]);
+  return v[2].dotwith(&v[1])/3.0;
+
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::saveqhull(const char* fname,int* points,int numpoints)
+{
+  fprintf(stderr,"In save qhull %s \n",fname);
+  FILE* fout=fopen(fname,"w");
+  if (fout)
+      {
+	// Write File out to qhull format
+	fprintf(fout,"3\n");
+	fprintf(fout,"%d\n",numpoints);
+	for (int j=0;j<numpoints;j++)
+	    {
+	      //	      fprintf(stderr,"%d ",points[j]);
+	      if (points[j]<nodes->getnumnodes())
+		  {
+		    fprintf(fout,"%6.3f %6.3f %6.3f\n",
+			    nodes->getpoint(points[j])->x[0],
+			    nodes->getpoint(points[j])->x[1],
+			    nodes->getpoint(points[j])->x[2]);
+		  }
+	      else
+		  {
+		    int nd=points[j]-nodes->getnumnodes();
+		    fprintf(fout,"%6.3f %6.3f %6.3f\n",
+			    extraNodes->getpoint(nd)->x[0],
+			    extraNodes->getpoint(nd)->x[1],
+			    extraNodes->getpoint(nd)->x[2]);
+		    //		    fprintf(stderr,"Point %d -->%d\n",points[j],nd);
+		  }
+	    }
+	fclose(fout);
+      }
+  fprintf(stderr,"Done save qhull\n");
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::checkelements(float minvol,float minangle,int start,int end)
+{
+  if (end==-1)
+      end=elements->getnumnodes();
+  
+  start=Irange(start,0,elements->getnumnodes()-2);
+  end=Irange(end,start+1,elements->getnumnodes());
+
+  elements->Rewind();
+  int i;
+  for (i=0;i<start;i++)
+      elements->Next();
+
+  fprintf(stderr,"\n\n-------------------------------------\n");
+  fprintf(stderr,"Checking Elements %d:%d (of total %d) minvol=%6.2f minangle=%5.3f\n",
+	  start,end,elements->getnumnodes(),minvol,minangle);
+  
+  for (i=start;i<end;i++)
+      {
+	PXIntegerList* intList=elements->getcurrentnode()->points;
+	if (intList->getnumnodes()==4)
+	    {
+	      int  points2[4];
+	      intList->Rewind();
+	      for (int j=0;j<=3;j++)
+		  {
+		    points2[j]=intList->getcurrent();
+		    intList->Next();
+		  }
+	      float vol=tetravolume(points2);
+	      float angle=tetraminangle(points2);
+	      int ok=1;
+	      
+	      if (vol<-minvol)
+		  {
+		    int tmp=points2[2];
+		    points2[2]=points2[1];
+		    points2[1]=tmp;
+		    vol=tetravolume(points2);
+		  }
+	      
+	      if (vol<minvol || angle<minangle)
+		  ok=0;
+	      
+	      if (ok>=1)
+		  {
+		    fprintf(stderr,"Accepting %d [%d,%d,%d,%d] vol=%5.3f ok=%d angle=%6.3f\n",
+			    i+1,
+			    points2[0]+1,points2[1]+1,
+			    points2[2]+1,points2[3]+1,vol,ok,angle);
+		  }
+	      else
+		  {
+		    fprintf(stderr,"Rejecting %d [%d %d %d %d ] vol=%5.3f angle=%6.3f\n",i+1,
+			    points2[0]+1,points2[1]+1,
+			    points2[2]+1,points2[3]+1,
+			    vol,angle);
+		    elements->getcurrentnode()->index=-1;
+		  }
+	    }
+	elements->Next();
+      }
+  elements->RemoveInvalid();
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::readqhull(const char* fname,int* points,int numpoints,int group)
+{
+  char command[200];
+  FILE* fin=fopen(fname,"r");
+  if (fin)
+      {
+	fgets(command,200,fin);
+	int np,temp,nt;
+	fscanf(fin,"%d %d %d\n",&np,&nt,&temp);
+	fprintf(stderr,"Reading %s points=%d, tetra=%d\n",fname,np,nt);
+	float x1,y1,z1,t1;
+	for (int j=0;j<numpoints;j++)
+	    fscanf(fin,"%f %f %f %f\n",&x1,&y1,&z1,&t1);
+	int points2[4];
+	for (int i=0;i<nt;i++)
+	    {
+	      int npt;
+	      fscanf(fin,"%d",&npt);
+	      for (int j=0;j<npt;j++)
+		  {
+		    fscanf(fin,"%d",&temp);
+		    points2[j]=points[temp];
+		  }
+	      elements->AddN(points2,npt,group);
+	    }
+      }
+}
+  /* 
+     Subject 5.21: How can the circumsphere of a tetrahedron be computed?
+
+     Let a, b, c, and d be the corners of the tetrahedron, with ax, ay, and az the components of a, and likewise for b, c, and d.  Let |a| denote the Euclidean
+     norm of a, and let a x b denote the cross product of a and b.  Then the center m and radius r of the circumsphere are given by
+     
+
+          |                                                                       |
+          | |d-a|^2 [(b-a)x(c-a)] + |c-a|^2 [(d-a)x(b-a)] + |b-a|^2 [(c-a)x(d-a)] |
+          |                                                                       |
+       r= -------------------------------------------------------------------------
+                                    | bx-ax  by-ay  bz-az |
+                                  2 | cx-ax  cy-ay  cz-az |
+                                    | dx-ax  dy-ay  dz-az |
+      
+
+    and
+
+              |d-a|^2 [(b-a)x(c-a)] + |c-a|^2 [(d-a)x(b-a)] + |b-a|^2 [(c-a)x(d-a)]
+       m= a + ---------------------------------------------------------------------
+                                      | bx-ax  by-ay  bz-az |
+                                    2 | cx-ax  cy-ay  cz-az |
+                                      | dx-ax  dy-ay  dz-az |
+				      
+
+int PXCrystalAbaqus::isinsidetetra(PX3Vector* pt,int npt,PXIntegerList* tetra,int testpoint)
+  
+  int index[4];
+  tetra->Rewind();
+  for (int i=0;i<=3;i++)
+      {
+	index[i]=tetra->getcurrent();
+	tetra->Next();
+      }
+
+  PX3Vector a,b,c,d;
+  a.copy(&pt[index[0]]);  b.copy(&pt[index[0]]);  c.copy(&pt[index[0]]);  d.copy(&pt[index[0]]);
+	 
+  PX3Vector bma,cma,dma;
+  bma.copy(&b); bma.subtract(&a);
+  cma.copy(&c); cma.subtract(&a);
+  dma.copy(&d); dma.subtract(&a);
+ 
+  PX3Vector temp;
+  temp.copy(&cma);
+  // FInd volume i.e bottom determinant
+  temp.crosswithoverwrite(&dma);
+  float det2=fabs(2.0*temp.dotwith(&bma));
+		  
+  PX3Vector bxc;  bxc.copy(&bma); bxc.crosswithoverwrite(&cma);
+  PX3Vector dxb;  dxb.copy(&dma);  dxb.crosswithoverwrite(&bma);
+  PX3Vector cxd;  bxc.copy(&cma);  bxc.crosswithoverwrite(&dma);
+
+
+  float magdma=pow(dma.getlength(),2.0);
+  float magcma=pow(cma.getlength(),2.0);
+  float magbma=pow(bma.getlength(),2.0);
+
+  PX3Vector center;
+  for (i=0;i<=2;i++)
+      center.x[i]=a.x[i]+ ((magdma*bxc.x[i]+magcma*dxb.x[i]+magbma*cxd.x[i])/det2);
+
+  temp.copy(&center);
+  temp.subtract(&a);
+
+  float radius=temp.getlength();
+
+  temp.copy(&pt[testpoint]);
+  temp.subtract(&center);
+  
+  float dist=temp.getlength();
+
+  return dist<radius;
+
+}*/
+
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::doqhull(int* points,int numpoints,int group)
+{
+  char line[50],command[150];
+  sprintf(line,"tmp%02d.qhull",group);
+
+  fprintf(stderr,"Group = %d Points = ",group);
+  for (int i=0;i<numpoints;i++)
+      fprintf(stderr,"%d ",points[i]);
+  fprintf(stderr,"\n");
+
+
+  saveqhull(line,points,numpoints);
+  
+  // Execute Qhull
+  sprintf(command,"qhull2 < %s d -Qbb -o  > %s.geom",line,line);
+  system(command);
+  sprintf(command,"/sbin/rm %s",line);
+  system(command);
+  
+  // Read Back output
+  sprintf(line,"%s.geom",line);
+  readqhull(line,points,numpoints,group);
+  sprintf(command,"/sbin/rm %s",line);
+  system(command);
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::savedistances(const char* fname1,const char* fname2,int crystal1,int crystal2)
+{
+  fprintf(stderr,"Comparing positions of %d and %d\n",crystal1,crystal2);
+  crystal1-=1;
+  crystal2-=1;
+  int numcr,numfr;
+  FILE* fin=fopen(fname1,"r");
+  if (!fin)
+      {
+	fprintf(stderr,"Cannot open %s\n",fname1);
+	return ;
+      }
+  
+  fscanf(fin,"%d\n%d\n",&numcr,&numfr);
+
+  if (numfr!=numframes)
+      {
+	fprintf(stderr,"Different number of frames!!!\n");
+	return;
+      }
+  
+  PXSolidNodes* tempnodes=new PXSolidNodes(numcr);
+  PXNodalDisplacements* disp[100];
+  int i;
+  for (i=0;i<numfr;i++)
+      disp[i]=new PXNodalDisplacements(tempnodes,1,100);
+
+  fprintf(stderr,"Reading frames(%d) : crystals(%d)\n",numfr,numcr);
+  
+  for (int fr=0;fr<numfr;fr++)
+      {
+	for (int cr=0;cr<numcr;cr++)
+	    {
+	      float tempx=0.0,tempy=0.0,tempz=0.0;
+	      fscanf(fin,"%f %f %f",&tempx,&tempy,&tempz);
+	      disp[fr]->setdisplacement(cr,tempx,tempy,tempz);
+	    }
+	fscanf(fin,"\n");
+      }
+  fclose(fin);
+  
+  FILE* fout=fopen(fname2,"w");
+  fprintf(fout,"#Distance between crystal pair %d-%d\n",crystal1+1,crystal2+1);
+
+
+  PX3Vector* pos01=disp[0]->getdisplacement(crystal1);
+  PX3Vector* pos02=disp[0]->getdisplacement(crystal2);
+
+  float dist012=pos01->getdistance(pos02);
+  
+  PX3Vector pos11,pos12;
+  for (int j=0;j<=2;j++)
+      {
+	pos11.x[j]=nodes->getpoint(crystal1)->x[j];
+	pos12.x[j]=nodes->getpoint(crystal2)->x[j];
+      }
+
+  float dist112=pos11.getdistance(&pos12);
+  
+  fprintf(fout,"#Original Positions 0 (%6.2f %6.2f %6.2f) and (%6.2f %6.2f %6.2f)\n",
+	  pos01->x[0],pos01->x[1],pos01->x[2],pos02->x[0],pos02->x[1],pos02->x[2]);
+  fprintf(fout,"#Original Positions 1 (%6.2f %6.2f %6.2f) and (%6.2f %6.2f %6.2f)\n",
+	  pos11.x[0],pos11.x[1],pos11.x[2],pos12.x[0],pos12.x[1],pos12.x[2]);
+  fprintf(fout,"#Frame distance1 distance2 strain1 strain2\n");
+  for (i=0;i<numframes;i++)
+      {
+	PX3Vector* pos01=disp[i]->getdisplacement(crystal1);
+	PX3Vector* pos02=disp[i]->getdisplacement(crystal2);
+
+	float dist0=pos01->getdistance(pos02);
+
+	PX3Vector pos11,pos12;
+	for (int j=0;j<=2;j++)
+	    {
+	      pos11.x[j]=nodes->getpoint(crystal1)->x[j]+displacements[i]->getdispcomponent(crystal1,j);
+	      pos12.x[j]=nodes->getpoint(crystal2)->x[j]+displacements[i]->getdispcomponent(crystal2,j);;
+	    }
+
+	float dist1=pos11.getdistance(&pos12);
+
+	fprintf(fout,"%5d %6.3f %6.3f %5.3f %5.3f \n",i+1,
+		dist0,dist1,(dist0-dist012)/dist012,(dist1-dist112)/dist112);
+      }
+  fclose(fout);
+
+  delete  tempnodes;
+  for ( i=0;i<numfr;i++)
+      delete disp[i];
+
+
+}
+// --------------------------------------------------------------------------
+int PXCrystalAbaqus::createTagMarkerSolid(float avevol,float anrange)
+{
+  if (!hasnodes())
+      return 0;
+
+  int* points=new int[nodes->getnumnodes()];  
+  int i;
+  for (i=0;i<nodes->getnumnodes();i++)
+      points[i]=i;
+  
+  if (hasElements==1)
+      delete elements;
+  
+  elements=new PXNeighboursList();
+  hasElements=1;
+  
+  doqhull(points,nodes->getnumnodes(),0);
+
+  fprintf(stderr,"nodes=%d elements=%d\n",nodes->getnumnodes(),elements->getnumnodes());
+  int bad=0;
+  elements->Rewind();
+  int el;
+  for (el=0;el<elements->getnumnodes();el++)
+      {
+	if (15*int(el/15)==el)
+	    fprintf(stderr,"El=%d/%d \t",el,elements->getnumnodes());
+	PXIntegerList* intList=((elements->getcurrentnode())->points);
+	int pt[4];
+	for (int count=0;count<=3;count++)
+	    {
+	      pt[count]=intList->getcurrent();
+	      intList->Next();
+	    }
+
+	float vol=fabs(tetravolume(pt));
+	float an=tetraminangle(pt);
+	//if (15*int(el/15)==el)
+	fprintf(stderr,"Volume =%6.2f angle=%6.2f\n",vol,an);
+	
+	vol/=avevol;
+
+	if (vol<0.2 || vol>2.4 || an<anrange || an>(180.0-anrange))
+	    {
+	      elements->getcurrentnode()->index=-1;
+	      bad++;
+	    }
+      	elements->Next();
+      }
+  
+  fprintf(stderr,"Bad=%d\n",bad);
+  elements->RemoveInvalid();
+  fprintf(stderr,"Good elements=%d\n",elements->getnumnodes());
+  
+  for (i=0;i<nodes->getnumnodes();i++)
+      points[i]=0;
+  
+  
+  elements->Rewind();  
+  for (el=0;el<elements->getnumnodes();el++)
+      {
+	PXIntegerList* intList=((elements->getcurrentnode())->points);
+	intList->Rewind();
+	for (int pt=0;pt<intList->getnumnodes();pt++)
+	    {
+	      int nd=intList->getcurrent();
+	      points[nd]++;
+	      intList->Next();
+	    }
+	elements->Next();
+      }
+	
+  bad=0;
+	
+ for (i=0;i<nodes->getnumnodes();i++)
+      {
+	if (points[i]==0)
+	    {
+	      bad++;
+	      nodes->setindex(i,0,-1);
+	    }
+      }
+  fprintf(stderr,"Number of bad markers=%d/%d \n",bad,nodes->getnumnodes());
+
+  delete [] points;
+
+  return elements->getnumnodes();
+}
+// --------------------------------------------------------------------------
+int PXCrystalAbaqus::createMarkerSolid(const char* fname)
+{
+  if (hasElements==1)
+      delete elements;
+  
+  elements=new PXNeighboursList();
+  int ok=elements->Load(fname);
+  if (ok==0)
+      {
+	fprintf(stderr,"Failed to read elements from %s\n",fname);
+	delete elements;
+	hasElements=0;
+	return 0;
+      }
+  else
+      fprintf(stderr,"Elements(%d) read  from %s\n",elements->getnumnodes(),fname);
+
+  hasElements=1;
+  int* points=new int[nodes->getnumnodes()];  
+  int i;
+  for (i=0;i<nodes->getnumnodes();i++)
+      points[i]=0;
+  
+  elements->Rewind();  
+  for (int el=0;el<elements->getnumnodes();el++)
+      {
+	PXIntegerList* intList=((elements->getcurrentnode())->points);
+	intList->Rewind();
+	for (int pt=0;pt<intList->getnumnodes();pt++)
+	    {
+	      int nd=intList->getcurrent();
+	      points[nd]++;
+	      intList->Next();
+	    }
+	elements->Next();
+      }
+  int bad=0;
+  for (i=0;i<nodes->getnumnodes();i++)
+      {
+	if (points[i]==0)
+	    {
+	      bad++;
+	      nodes->setindex(i,0,-1);
+	    }
+      }
+  fprintf(stderr,"Number of bad markers=%d/%d \n",bad,nodes->getnumnodes());
+  delete [] points;
+
+  elements->Save("elements.list");
+
+  return elements->getnumnodes();
+  
+}
+// --------------------------------------------------------------------------
+void PXCrystalAbaqus::getElementCentoid(PXIntegerList* element,float& x,float& y,float& z)
+{
+  float cx[3];
+  for (int ia=0;ia<=2;ia++)
+      cx[ia]=0.0;
+
+  if (!hasnodes() || !haselements())
+      return;
+  
+  element->Rewind();
+  for (int i=0;i<element->getnumnodes();i++)
+      {
+	int nd=element->getcurrent();
+	for (int ia=0;ia<=2;ia++)
+	    {
+	      cx[ia]+=nodes->getpoint(nd)->x[ia];
+	      if (hasfemdata())
+		  cx[ia]+=femData->getdispcomponent(nd,ia);
+	    }
+	element->Next();
+      }
+  
+  x=cx[0]/float(element->getnumnodes());
+  y=cx[1]/float(element->getnumnodes());
+  z=cx[2]/float(element->getnumnodes());
+
+}
+// --------------------------------------------------------------------------
+int PXCrystalAbaqus::createOrientations(PX3Vector* orient1,PX3Vector* orient2,PX3Vector* orient3,
+					PXAbaqusSolid* sld)
+{
+  if (!haselements() || !hasnodes() || !sld->haselements() || !sld->hasnodes())
+      return 0;
+
+  PXNeighboursList* sldElem=sld->getelements();
+  PXIntegerList* sldElements[20000];
+
+  sldElem->Rewind();
+  int i;
+  for (i=0;i<sldElem->getnumnodes();i++)
+      {
+	sldElements[i]=(sldElem->getcurrentnode())->points;
+	sldElem->Next();
+      }
+  
+  // Calculate Centroids 
+  PX3Vector* centroid=new PX3Vector[sldElem->getnumnodes()];
+  for (i=0;i<sldElem->getnumnodes();i++)
+      sld->getElementCentroid(sldElements[i],centroid[i].x[0],centroid[i].x[1],centroid[i].x[2]);
+	
+  elements->Rewind();
+  
+  PX3Vector cent;
+
+  for (i=0;i<elements->getnumnodes();i++)
+      {
+	getElementCentroid(elements->getcurrentnode()->points,cent.x[0],cent.x[1],cent.x[2]);
+	float mindist=1000000.0;
+	int best=0;
+	for (int j=0;j<sldElem->getnumnodes();j++)
+	    {
+	      float d=cent.getdistance(&centroid[j]);
+	      if (d<mindist)
+		  {
+		    mindist=d;
+		    best=j;
+		  }
+	    }
+	
+	sld->getdirections(sldElements[best],
+			   orient1[i].x[0],orient1[i].x[1],orient1[i].x[2],  // Radial
+			   orient2[i].x[0],orient2[i].x[1],orient2[i].x[2],  // Circumferential
+			   orient3[i].x[0],orient3[i].x[1],orient3[i].x[2],  // Longidutinal
+			   0);
+	if (25*int(i/25)==i)
+	    {
+	      fprintf(stderr,"Finding orientations for element %d/%d Best sld elem=%d dist=%6.2f\n",
+		      i,elements->getnumnodes(),best,mindist);
+	      fprintf(stderr,"\t Radial (%5.2f %5.2f %5.2f) Circ (%5.2f %5.2f %5.2f) Long (%5.2f %5.2f %5.2f)\n",
+		      orient1[i].x[0],orient1[i].x[1],orient1[i].x[2], 
+		      orient2[i].x[0],orient2[i].x[1],orient2[i].x[2], 
+		      orient3[i].x[0],orient3[i].x[1],orient3[i].x[2]);
+	    }
+	elements->Next();
+      }
+  delete [] centroid;
+  return 1;
+
+}
+
+// --------------------------------------------------------------------------
+int PXCrystalAbaqus::saveMarkerAbaqus(const char* fname,int resout,PXAbaqusSolid* sld,int useorientations)
+{
+
+
+  if (!hasnodes() ||  !hasdisplacements() || !haselements())
+      {
+	fprintf(stderr,"No nodes,elements or displacements\n");
+	return 0;
+      }
+
+  PX3Vector* orient1=new PX3Vector[getelements()->getnumnodes()];
+  PX3Vector* orient2=new PX3Vector[getelements()->getnumnodes()];
+  PX3Vector* orient3=new PX3Vector[getelements()->getnumnodes()];
+  if (useorientations==1)
+      createOrientations(orient1,orient2,orient3,sld);
+  else
+      {
+	for (int i=0;i<getelements()->getnumnodes();i++)
+	    {
+	      orient1[i].setvector(1.0,0.0,0.0);
+	      orient2[i].setvector(0.0,1.0,0.0);
+	      orient3[i].setvector(0.0,0.0,1.0);
+	    }
+      }
+	
+  char* abname=anacreatefilename(fname,".inp",".mark");
+  fprintf(stderr,"Creating Job %s --> %s \n",fname,abname);
+
+  FILE* fout=fopen(abname,"w");
+
+  if (!fout)
+      {
+	delete [] abname;
+	return 0;
+      }
+
+  fprintf(fout,"*HEADING\nMyocardium Model\n");
+  fprintf(fout,"** Numnodes=%d, numelements=%d\n",nodes->getnumnodes(),
+	  elements->getnumnodes());
+  fprintf(fout,"** ----------------------------------------------------\n");
+  fprintf(fout,"** Shrink .dat file\n*PREPRINT,ECHO=NO,MODEL=NO,HISTORY=NO\n**\n");
+
+  fprintf(fout,"** ----------Material Model --------------------------------------\n");
+  fprintf(fout,"*MATERIAL,NAME=TISSUE\n*ELASTIC\n");
+  fprintf(fout,"%7.3f,%7.3f\n",1.0,0.3);
+  
+  fprintf(fout,"** ---------- Nodes  --------------------------------------\n");
+  
+  fprintf(fout,"*NODE,NSET=ALLNODES\n");
+  
+  for (int i=0;i<nodes->getnumnodes();i++)
+      {
+	if (nodes->getindex(i,0)>=0)
+	    {
+	      fprintf(fout," %5d , %7.3f , %7.3f , %7.3f \n",
+		      i+1000,
+		      nodes->getpoint(i)->x[0],
+		      nodes->getpoint(i)->x[1],
+		      nodes->getpoint(i)->x[2]);
+	    }
+      }
+  
+
+  
+  fprintf(fout,"** ---------- Elements --------------------------------------\n");  
+
+  char line[100],orient[20];
+  
+  fprintf(stderr,"** \n** Orientations for each elements\n");
+  elements->Rewind();
+  for (int el=0;el<elements->getnumnodes();el++)
+      {
+	sprintf(orient,"ORT_%04d",el+1000);
+	fprintf(fout,"**\n*ORIENTATION,NAME=%s,SYSTEM=RECTANGULAR\n",orient);
+	fprintf(fout,"%8.5f,%8.5f,%8.5f, %8.5f,%8.5f,%8.5f\n",
+		orient1[el].x[0],orient1[el].x[1],orient1[el].x[2],
+		orient2[el].x[0],orient2[el].x[1],orient2[el].x[2]);
+
+	PXIntegerList* intList=((elements->getcurrentnode())->points);
+	int np=intList->getnumnodes();
+	sprintf(line,"E_E%04d",el+1000);
+	fprintf(fout,"*ELEMENT, TYPE=C3D%1d, ELSET=%s\n",np,line);
+	intList->Rewind();
+	fprintf(fout,"%d,",el+1000);
+	for (int i=0;i<intList->getnumnodes();i++)
+	    {
+	      fprintf(fout,"%d",intList->getcurrent()+1000);
+	      if (i!=intList->getnumnodes()-1)
+		  fprintf(fout,",");
+	      else
+		  fprintf(fout,"\n");
+	      intList->Next();
+	    }
+	fprintf(fout,"*SOLID SECTION, ELSET=%s,MATERIAL=TISSUE,ORIENTATION=%s\n",
+		line,orient);
+	elements->Next();
+      }
+  fprintf(fout,"**\n");
+  fprintf(fout,"*ELSET, ELSET=E_DUMMY\n1000\n**\n");
+
+  for (int fr=0;fr<numframes;fr+=1)
+      {
+	fprintf(fout,"** -------------------- Frame %d ---------------------------\n**\n",fr+1);
+	fprintf(fout,"*STEP,NLGEOM,AMPLITUDE=RAMP,INC=40\n");
+	fprintf(fout,"*STATIC\n %f,1.0,0.00005,1.0\n",1.0);
+	fprintf(fout,"**\n");
+	fprintf(fout,"** Accuracy Controls\n*CONTROLS,PARAMETERS=FIELD,FIELD=DISPLACEMENT\n");
+	fprintf(fout,"0.01,1.0,10.0,  ,  , 1.E-3\n");
+	fprintf(fout,"*BOUNDARY,OP=NEW\n");
+	for (int i=0;i<displacements[fr]->getsolidnodes()->getnumnodes();i++)
+	    {
+	      if (displacements[fr]->getsolidnodes()->getindex(i,0)>=0)
+		  {
+		    for (int j=0;j<3;j++)
+			fprintf(fout,"%d , %d , %d, %8.4f\n",i+1000,j+1,j+1,
+				displacements[fr]->getdispcomponent(i,j));
+		  }
+	    }
+	fprintf(fout,"**\n*EL PRINT,POSITION=CENTROIDAL,ELSET=E_DUMMY\nE11\n");
+	fprintf(fout,"*NODE PRINT,NSET=ALLNODES\nU1\n");
+	fprintf(fout,"*EL FILE,POSITION=CENTROIDAL\nE\n");
+	fprintf(fout,"*EL FILE\nEVOL\n*NODE FILE,NSET=ALLNODES\nU\n");
+	if (resout>0)
+	    fprintf(fout,"*RESTART,WRITE\n");
+	fprintf(fout,"*END STEP\n");
+      }
+  fprintf(stderr,"** Resout=%d\n",resout);
+  fclose(fout);
+
+  delete [] orient1;
+  delete [] orient2;
+  delete [] orient3;
+  return 1;
+}
+// --------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/numerics/pxcrystalabaqus.h b/bioimagesuite30_src/numerics/pxcrystalabaqus.h
new file mode 100644
index 0000000..a78b4fe
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxcrystalabaqus.h
@@ -0,0 +1,194 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pxCrystalAbaqus.h
+// -----------------------------------------------------------------
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+_Module_Name : PxCrystalAbaqus 
+
+_Description : A structures which stores crystal coordinates and generates Abaqus files for
+               strain computation
+               
+
+_Call : 
+  PxCrystalAbaqus();
+  PxCrystalAbaqus(PXContourStackSolid *old);
+
+_References :
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 16th March 1999
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PxCrystalAbaqus
+#define _PxCrystalAbaqus
+#include "pxgeometrystruct.h"
+#include "pxabaqusstructures.h"
+#include "pxabaqussolid.h"
+#include "pxmarkerclass.h"
+
+const int PXCRYSTALFRAMES=200;
+const int PXABCR_PT_OFFSET=1;
+
+class PXCrystalAbaqus {
+  
+protected:
+
+  PXNeighboursList*         elements;
+  PXSolidNodes*             nodes;
+  PXSolidNodes*             extraNodes;
+  int                       numframes,numgroups;
+
+  // Finite Element Data Postprocessing
+  PXAbaqusOutputData*      femData;
+  PXNodalDisplacements*    displacements[PXCRYSTALFRAMES];
+
+  // Verify Existence
+  int                       hasElements,hasNodes,hasDisplacements,hasFemData,hasExtraNodes;
+
+public:
+  
+  PXCrystalAbaqus();
+  PXCrystalAbaqus(PXCrystalAbaqus* old);
+  PXCrystalAbaqus(const char* fname1,const char* fname2);
+  PXCrystalAbaqus(PXMarkerCollection* markers);
+  PXCrystalAbaqus(PXMarkerCollection* markers,int frameinc=1,int maxframe=-1);
+ 
+  virtual ~PXCrystalAbaqus();
+  void init();
+  void cleanup();
+
+  void Copy(PXCrystalAbaqus* other);
+
+  int createFromCrystalFiles(const char* classfile,const char* positionfile,
+			     float minvol=50.0,float minangle=15.0,int extranodes=0);
+  
+  // Access Functions
+  // ----------------
+  int      hasfemdata();
+  int      hasdisplacements();
+  int      hasnodes();           
+  int      hasextranodes();           
+  int      haselements();        
+
+  int      getnumframes();
+  int      getnumgroups();
+
+  PXAbaqusOutputData*   getfemdata();
+  PXNeighboursList*     getelements();
+  PXSolidNodes*         getnodes();   
+  PXSolidNodes*         getextranodes();   
+  PXNodalDisplacements* getdisplacements(int i);
+
+  // Geometry Related
+  // ----------------
+  void getElementCentroid(PXIntegerList* element,float&x,float&y,float& z);
+  int  saveInventor(const char* fname,int mode=-1,int cmode=-1,float* params=NULL);
+  int  saveInventor(FILE* fout,int mode=1,int cmode=-1,float* params=NULL);
+
+  void savedistances(const char* fname1,const char* fname2,int crystal1,int crystal2);
+
+  // CrystalAbaqusRelated
+  // -------------
+  void setorientations(int group,PX3Vector& radial,PX3Vector& circum,PX3Vector& longit);
+  int  saveAbaqus(const char* fname,int resout=1,int numframes=-1,int skipframes=1);
+  int  saveSolid(const char* fname);
+  void setPieIndices();
+  // Allocation Related
+  // ------------------
+  void allocateFemData();
+  void allocateDisplacements();
+
+
+  // Qhull stuff
+  // -----------
+  float tetravolume(int* points);
+  void  getElementCentoid(PXIntegerList* elem,float& x,float& y,float& z);
+  float tetraminangle(int* points);
+  float trianglearea(int* points);
+  void  doqhull(int* points,int numpoints,int group);
+  void  saveqhull(const char* fname,int* points,int numpoints);
+  void  readqhull(const char* fname,int* points,int numpoints,int group);
+  void  checkelements(float minvol,float minangle,int start=0,int end=-1);
+
+
+  // Marker Solids
+  // -------------
+  int createTagMarkerSolid(float avevol=30.0,float anrange=30.0);
+  int createMarkerSolid(const char* fname);
+  int createOrientations(PX3Vector* orient1,PX3Vector* orient2,PX3Vector* orient3,PXAbaqusSolid* sld);
+  int saveMarkerAbaqus(const char* fname,int resout,PXAbaqusSolid* sld,int useorientations=1);
+  
+
+protected:
+
+  // Cleanup Operations
+  // ------------------
+  void cleanupFemData();
+  void cleanupNodeSpace();
+  void cleanupElementSpace();
+  void cleanupDisplacements();
+
+  // More Allocation Stuff
+  // ---------------------
+  void allocateNodeSpace(int numnode);
+  void allocateElementSpace();
+
+  
+  
+
+public:
+
+  // Static Functions mainly to do with postprocessing fem data
+  // ----------------------------------------------------------
+  static int debugmode;  
+  
+};
+
+  
+  
+#endif  
+
diff --git a/bioimagesuite30_src/numerics/pxfloatimage.cpp b/bioimagesuite30_src/numerics/pxfloatimage.cpp
new file mode 100644
index 0000000..486fbf8
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxfloatimage.cpp
@@ -0,0 +1,426 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+#include "pxfloatimage.h"
+#include "pximage.h"
+#include "pxfloatmatrix.h"
+
+//-----------------------------------------------------------------------
+float PXFloatImage::gradient_mask[5]={-1.0/12.0 , 8.0/12.0 ,0.0 ,-8.0/12.0 ,1.0/12.0};
+//-----------------------------------------------------------------------
+PXFloatImage::PXFloatImage(int x ,int y)
+{
+  xsize=x;
+  ysize=y;
+  image=new float[xsize*ysize]; 
+  if (image!=NULL) status=1;
+  else
+      status=0;
+}
+//-----------------------------------------------------------------------
+PXFloatImage::PXFloatImage(const char* f)
+     /* 
+	Normal constructor.If file f exists it is read into
+	the array.The fields are initialised to their default
+	values
+	*/
+{
+  xsize=0;
+  ysize=0;
+  maxgrayscale=0;
+  mingrayscale=0;
+  status=0;	      
+  if (status==1) 
+      Load(f);
+}
+
+//-----------------------------------------------------------------------
+PXFloatImage::PXFloatImage(PXImage* oldimage,PXFloatMatrix* kernel,
+			   int x1,int x2,int y1,int y2)
+     // Convolution Constructor
+{
+  int i,j;
+  if (x2==-1) x2=oldimage->getsizex();
+  if (y2==-1) y2=oldimage->getsizey();
+  
+  xsize=oldimage->getsizex();            ysize=oldimage->getsizey();
+  status=0;
+  image=new float[xsize*ysize]; 
+  if (image!=NULL) status=1;
+  else
+      status=0;
+  
+  if (status==1)
+      {
+	for(i=0;i<xsize;i++)
+	  for(j=0;j<ysize;j++)
+	      setpixel(i,j,0.0);
+	
+	float sum=0.0;
+	
+	for(i=kernel->getradiusx()+x1+1;
+	    i<(x2-kernel->getradiusx());i++)
+	    for(j=kernel->getradiusy()+1+y1;
+		j<(y2-kernel->getradiusy()-1);j++)
+		{
+		  sum=0.0;
+		  for(int column=-kernel->getradiusx();
+		      column<=kernel->getradiusx();column++)
+		      for(int row=-kernel->getradiusy();
+			  row<=kernel->getradiusy();row++)
+			  {
+			    sum=sum+((float)(oldimage->getpixel(i+column,j+row))*
+				     kernel->getpixel(kernel->getradiusx()-column,
+						      kernel->getradiusy()-row));
+			  }
+		  setpixel(i,j,sum);
+	      }
+	SetMaxMingrayscale();
+      }
+}
+
+//-----------------------------------------------------------------------
+PXFloatImage::PXFloatImage(PXFloatImage *oldimage)
+{
+  xsize=oldimage->getsizex();
+  ysize=oldimage->getsizey();
+  image=new float[xsize*ysize]; 
+  for (int i=0;i<xsize;i++)
+      for (int j=0;j<ysize;j++)
+	  setpixel(i,j,oldimage->getpixel(i,j));
+  status=oldimage->isvalid();
+}
+//-----------------------------------------------------------------------
+
+PXFloatImage::PXFloatImage(PXFloatImage* oldimage,PXFloatMatrix* kernel,
+			   int x1,int x2,int y1,int y2)
+     // Convolution Constructor
+{
+  int i,j;
+  if (x2==-1) x2=oldimage->getsizex();
+  if (y2==-1) y2=oldimage->getsizey();
+  
+  xsize=oldimage->getsizex();            ysize=oldimage->getsizey();
+  status=0;
+  image=new float[xsize*ysize]; 
+  if (image!=NULL) status=1;
+  else
+      status=0;
+  
+  if (status==1)
+      {
+	for(i=0;i<xsize;i++)
+	    for(j=0;j<ysize;j++)
+		setpixel(i,j,0.0);
+	
+	float sum=0.0;
+	
+	for(i=kernel->getradiusx()+x1+1;
+	    i<(x2-kernel->getradiusx());i++)
+	    for(j=kernel->getradiusy()+y1+1;
+		j<(y2-kernel->getradiusy()-1);j++)
+		{
+		  sum=0.0;
+		  for(int column=-kernel->getradiusx();
+		      column<=kernel->getradiusx();column++)
+		      for(int row=-kernel->getradiusy();
+			  row<=kernel->getradiusy();row++)
+			  {
+			    sum=sum+(oldimage->getpixel(i+column,j+row)*
+				     kernel->getpixel(kernel->getradiusx()-column,
+						      kernel->getradiusy()-row));
+			  }
+		  setpixel(i,j,sum);
+		}
+	SetMaxMingrayscale();
+      }
+}
+
+//-----------------------------------------------------------------------
+PXFloatImage::~PXFloatImage()
+{
+  delete [] image;
+}
+//-----------------------------------------------------------------------
+/*
+		The  Format used for Float Images .xbin
+
+Magic     Number  (4-byte float)    
+Number of Columns (4-byte float)
+Number of Rows    (4-byte float)
+Then data in 4-byte float
+*/
+//-----------------------------------------------------------------------
+void PXFloatImage::Load(const char* filename)
+{
+  int n=0;
+  float test;
+  
+  gzFile fp=gzsuffixopen(filename,"rb");
+  if (fp)
+      {
+	n += gzread(fp,&test,4);
+	if (test==PXFLIM)
+	    {
+	      n += gzread(fp,&ysize,4);
+	      n += gzread(fp,&xsize,4);
+	      image=new float[xsize*ysize]; // initialise image array 
+	      n +=gzread(fp,&image[0],4*xsize*ysize);
+	      gzclose(fp);
+	      SetMaxMingrayscale();
+	      status=1;
+	    }
+	else
+	    {
+	      //cerr << "Wrong File format : " << filename << "\n";
+	      status=0;
+	    }
+      }
+  else 
+      {
+	//cerr << "File " << filename <<" does not exist \n";
+	status=0;
+      }
+}
+//-----------------------------------------------------------------------
+void PXFloatImage::Save(const char* filename)
+{
+  int bytes=0;
+  gzFile fdf=gzsuffixopen(filename,"rb");
+  if (fdf)
+      {
+	float a=PXFLIM;
+	bytes +=gzwrite(fdf,&a,4);
+	bytes +=gzwrite(fdf,&ysize,4);
+	bytes +=gzwrite(fdf,&xsize,4);
+	bytes +=gzwrite(fdf,&image[0],4*xsize*ysize);
+      }
+  gzclose(fdf);
+}
+//-----------------------------------------------------------------------
+void PXFloatImage::LoadBin(const char* filename)
+{
+  int n=0;
+  
+
+  gzFile fp=gzsuffixopen(filename,"rb");
+  if (fp)
+      {
+	n +=gzread(fp,&image[0],xsize*ysize*4);
+	SetMaxMingrayscale();
+	status=1;
+	gzclose(fp);
+      }
+  else 
+      {
+	status=0;
+      }
+}
+//-----------------------------------------------------------------------
+
+void PXFloatImage::SaveBin(const char* filename)
+{
+  int bytes=0;
+  gzFile fdf=gzsuffixopen(filename,"wb");
+  if (fdf)
+      {
+	bytes += gzwrite(fdf,&image[0],4*xsize*ysize);
+      }
+  gzclose(fdf);
+}
+//-----------------------------------------------------------------------
+PXImage* PXFloatImage::getPXImage(int bytes)
+{
+  int maxpix=65535;
+  if (bytes==1)
+      maxpix=255;
+  PXImage* temp=new PXImage(xsize,ysize);
+  temp->nowisvalid();
+  SetMaxMingrayscale();
+  for (int i=0;i<xsize;i++)
+      for (int j=0;j<ysize;j++)
+	  temp->setpixel(i,j,int(maxpix*(getpixel(i,j)-mingrayscale)/getrange()));
+  return temp;
+}
+//-----------------------------------------------------------------------
+void PXFloatImage::SaveGrl(const char* filename)
+{
+  PXImage* temp=getPXImage();
+  temp=getPXImage(2);
+  temp->SaveGrl(filename,2);
+  delete temp;
+}
+//-----------------------------------------------------------------------
+void PXFloatImage::SavePgm(const char* filename)
+{
+  PXImage* temp=getPXImage(1);
+  temp->SavePgm(filename);
+  delete temp;
+}
+
+//-----------------------------------------------------------------------
+// Return texture mapping code
+//-----------------------------------------------------------------------
+unsigned char PXFloatImage::adjust(float px,float gamma)
+{ 
+  float max=maxgrayscale;
+  float xf=px/max;
+  xf=pow((double)xf,1.0/(double)gamma);
+  xf=xf*255.0;
+  return ((unsigned char)xf);
+}
+
+// ----------------------------------------------------------------------
+unsigned char* PXFloatImage::getslice(float gamma,int numbytes)
+{
+  PXImage* temp=getPXImage(1);
+  unsigned char* sl=temp->getslice(gamma,numbytes);
+  delete temp;
+  return sl;
+}
+//-----------------------------------------------------------------------
+void PXFloatImage::SetMaxMingrayscale()
+{
+  float max=0,min=1e+20;
+  
+  for (int i=0;i<(xsize*ysize);i++)
+      {
+	if (image[i]>max) max=image[i];
+	if (image[i]<min) min=image[i];
+      }
+  mingrayscale=min;
+  maxgrayscale=max;
+}
+
+//-----------------------------------------------------------------------
+void PXFloatImage::Invert()
+{
+  SetMaxMingrayscale();
+  float maxmin=maxgrayscale-mingrayscale;
+
+  for (int i=0;i<(xsize*ysize);i++)
+      image[i]=(maxmin-(image[i]-mingrayscale))+mingrayscale;
+}
+//-----------------------------------------------------------------------
+void PXFloatImage::AddContour(PXContour* contour,float grl,
+			      unsigned char touching,
+			      int offx,int offy)
+{
+  int x1,x2,y1,y2;
+  float w11,w12,w21,w22;
+
+  PXContour* modcontour=new PXContour(contour);
+  modcontour->closedcontour(contour->isclosed());
+  if (touching>0) modcontour->Touching();
+  PXContourPoint *pts=modcontour->gettoppoint();
+  while (pts->next !=NULL)
+    {
+      if ( (pts->x>0.0 && pts->x<xsize-1) &&
+	  (pts->y>0.0 && pts->y<ysize-1))
+	  {
+	    x1=int(pts->x); x2=x1+1;
+	    y1=int(pts->y); y2=x2+1;
+	    
+	    w11=(x2-pts->x)*(y2-pts->y)*grl;
+	    w12=(x2-pts->x)*(pts->y-y1)*grl;
+	    w21=(pts->x-x1)*(y2-pts->y)*grl;
+	    w22=(pts->x-x1)*(pts->y-y2)*grl;
+	    
+	    setpixel(offx+x1,offy+y1,w11);
+	    setpixel(offx+x2,offy+y1,w21);
+	    setpixel(offx+x1,offy+y2,w12);
+	    setpixel(offx+x2,offy+y2,w22);
+	  }
+      pts=pts->next;
+    }
+  delete modcontour;
+}
+
+//-----------------------------------------------------------------------
+float PXFloatImage::getinterp(float x,float y)
+{ 
+  int x1=(int)x,y1=(int)y;
+  int x2=x1+1,y2=y1+1;
+  if (x1>=0 && y1>=0 && x2<xsize && y2<ysize)
+      {
+	float a= (getpixel(x1,y1)*(x2-x)*(y2-y)+
+		  getpixel(x1,y2)*(x2-x)*(y-y1)+
+		  getpixel(x2,y1)*(x-x1)*(y2-y)+
+		  getpixel(x2,y2)*(x-x1)*(y-y1));
+	return a;
+      }
+  else
+      {
+	if (x2>=xsize) { x2=x1;}
+	if (y2>=ysize) { y2=y1;}
+	
+	if (x1==x2 && y1==y2)
+	    return getpixel(x1,y1);
+	if (x1==x2)
+	    return getpixel(x1,y1)*(y2-y)+getpixel(x1,y2)*(y-y1);
+	if (y1==y2)
+	    return getpixel(x1,y1)*(x2-x)+getpixel(x2,y1)*(x-x1);
+      }
+  return 0.0;
+}
+//-----------------------------------------------------------------------
+//  Gradient Related Code
+//-----------------------------------------------------------------------  
+float PXFloatImage::GradientX(int x,int y)
+{ 
+  return getpixel(x+1,y)-getpixel(x,y); 
+}
+
+float PXFloatImage::GradientY(int x,int y)
+{ 
+  return getpixel(x,y+1)-getpixel(x,y);  
+}
+  
+float PXFloatImage::GradientXMask(int x,int y)
+{
+  float sum=0;
+  for(int i=-2;i<=2;i++)
+      sum=sum+(gradient_mask[i+2]*getpixel(x+i,y));
+  return sum;
+}
+
+float PXFloatImage::GradientYMask(int x,int y)
+{
+  float sum=0;
+  for (int i=-2;i<=2;i++)
+      sum=sum+(gradient_mask[i+2]*getpixel(x,y+i));
+  return sum;
+}
+//-----------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/numerics/pxfloatimage.h b/bioimagesuite30_src/numerics/pxfloatimage.h
new file mode 100644
index 0000000..a219e75
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxfloatimage.h
@@ -0,0 +1,186 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pxfloatimage.h
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXFloatImage
+
+_Description : 
+  This class can be used to store objects which are images (float)
+               
+	       
+	       
+
+_Call : 
+  (1) PXFloatImage(xsize,ysize)      - used to generate temp image
+  (2) PXFloatImage(PXImage* oldimage,PXFloatMatrix* kernel)  
+                                  - convolution constructor
+
+_References : see pximage.h
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in July 1995
+                    2. Revision to include binary read 29th August 1995
+		    3. Added Magic number 31st August 1995
+		    4. Added Convolution Constructor PXImage**PXFloatMatrix
+		    5. Added Interpolation (Bilinear) 20th Nov 1995
+		    6. Added Save Grl    20th Nov 1995
+		    7. Added AddContour  30th Jan 1995
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+#ifndef _PXFloatImage
+#define _PXFloatImage
+
+#include <math.h>
+#include "pximage.h"
+const float PXFLIM = 2905.71;   // Magic Number for PXFloatImage Format
+
+class PXFloatImage {
+
+protected:	
+  
+  // Class fields self-explanatory;
+
+  static float    gradient_mask[5];             // store 5x1 mask for derivatives 
+  float  *image; 		  // image storage array;
+  int	 xsize,ysize;	          // size and properties;
+  float  maxgrayscale,mingrayscale;
+  int	 status;		  // 1=OK 0=problem;
+ 
+public:
+  
+  // These are the constructors and the destructor respectively
+  
+  PXFloatImage(int h,int w);
+  PXFloatImage(const char*);
+  PXFloatImage(PXImage* oldimage,PXFloatMatrix* kernel,
+	       int x1=0,int x2=-1,int y1=0,int y2=-1);
+  PXFloatImage(PXFloatImage* oldimage);
+  PXFloatImage(PXFloatImage* oldimage,PXFloatMatrix* kernel,
+	       int x1=0,int x2=-1,int y1=0,int y2=-1);
+  virtual ~PXFloatImage();				
+
+  // [A] Get/Set Pixel Values
+  // ------------------------
+  virtual void	setpixel(int x, int y, float g)	   
+    {image[y*xsize+x]=g;}
+  virtual float	getpixel(int x, int y)  
+    {return image[y*xsize+x]; }
+  float getinterp(float x,float y);
+
+  // [B] Get/Set Other Parameters
+  // ----------------------------
+  virtual int	getsizex()	
+    {return xsize;}		
+  virtual int	getsizey()	
+    {return ysize;}		
+  virtual float	getmaxgrayscale() 
+    {return maxgrayscale;}
+  virtual float	getmingrayscale() 
+    {return mingrayscale;}
+  virtual float getrange()
+    { return (maxgrayscale-mingrayscale)+1.0*( fabs(maxgrayscale-mingrayscale)<0.1); }
+  virtual float* getimage() 
+    {return image;}   
+  virtual int  isvalid()	
+    {return status;}	
+
+  unsigned char* getslice(float gamma=1.5,int numbytes=1);
+  unsigned char  adjust(float px,float gamma=1.5);
+  
+  // [C] I/O Related
+  //----------------
+  /*
+     Load and Save   read/write image to the .xbin format
+        4-byte float -- 
+        first magic no then width then height then data
+     
+     SaveGrl -- save in 16-bit grl format -- useful for display
+
+     LoadBin and SaveBin - read/write image to binary file
+       No dimension header again 4-byte float
+     
+     Invert          is a diagnostic test - simply inerts image
+     */
+
+  virtual void	Load(const char* f);
+  virtual void	Save(const char* f);		       
+  virtual void  LoadBin(const char* f);
+  virtual void  SaveBin(const char* f);
+  virtual void  SaveGrl(const char* f);
+  virtual void  SavePgm(const char* f);
+  virtual void  SetMaxMingrayscale();
+  virtual void	Invert();			
+  virtual void  AddContour(PXContour* contour,float grl,
+			   unsigned char touching,
+			   int offx,int offy);
+    
+  virtual PXImage* getPXImage(int bytes=2);
+  // [D] Gradient functions 
+  // ----------------------
+  float GradientX(int x,int y);
+  float GradientY(int x,int y);
+  float GradientXMask(int x,int y);
+  float GradientYMask(int x,int y);
+    
+};
+
+#endif /*  _PXFloatImage */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/numerics/pxfloatmatrix.cpp b/bioimagesuite30_src/numerics/pxfloatmatrix.cpp
new file mode 100644
index 0000000..31c86f7
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxfloatmatrix.cpp
@@ -0,0 +1,225 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+#include "pxfloatmatrix.h"
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July 1995   papad at noodle.med.yale.edu
+
+   see pxfloatmatrix.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+//-----------------------------------------------------------------------
+float PXFloatMatrix::gradient_mask[5]={-1.0/12.0 , 8.0/12.0 ,0.0 ,-8.0/12.0 ,1.0/12.0};
+//-----------------------------------------------------------------------
+PXFloatMatrix::PXFloatMatrix(int x ,int y)
+     //  Constructor for new matrixs
+{
+  if ((x/2)*2==x) x++;
+  if ((y/2)*2==y) y++;
+  xsize=x;
+  ysize=y;
+  centerx=x/2;
+  centery=y/2;
+  matrix=new float[xsize*ysize]; 
+}
+//-----------------------------------------------------------------------
+PXFloatMatrix::~PXFloatMatrix()
+{
+  delete [] matrix;
+}
+//-----------------------------------------------------------------------
+// Gradient functions 
+//-----------------------------------------------------------------------
+float PXFloatMatrix::GradientX(int x,int y)
+{ 
+  return getpixel(x+1,y)-getpixel(x,y); 
+}
+
+float PXFloatMatrix::GradientY(int x,int y)
+{ 
+  return getpixel(x,y+1)-getpixel(x,y);  
+}
+  
+float PXFloatMatrix::GradientXMask(int x,int y)
+{
+  float sum=0;
+  for(int i=-2;i<=2;i++)
+      sum=sum+(gradient_mask[i+2]*getpixel(x+i,y));
+  return sum;
+}
+
+float PXFloatMatrix::GradientYMask(int x,int y)
+{
+  float sum=0;
+  for (int i=-2;i<=2;i++)
+      sum=sum+(gradient_mask[i+2]*getpixel(x,y+i));
+  return sum;
+}
+//-----------------------------------------------------------------------
+//  Gaussian Generate Functions
+//-----------------------------------------------------------------------
+void PXFloatMatrix::GenGaussian(float sigma)
+{
+  if (sigma<0.1) sigma=0.11;
+  for (int i=0;i<xsize;i++)
+      for (int j=0;j<ysize;j++)
+	  {
+	    setpixel(i,j,(1/(sigma*2*3.1415926854)*
+			  exp(-0.5*((0.0+(i-centerx)*(i-centerx)+(j-centery)*(j-centery))
+				    /pow(sigma,float(2.0))))));
+	  }
+  Normalize(0);
+}
+//-----------------------------------------------------------------------
+void PXFloatMatrix::GenGaussian1Dx(float sigma) // all in X-Direction !;
+{
+  if (sigma<0.1) sigma=0.1;
+  for (int i=0;i<xsize;i++)
+      {
+	float temp=(1/(sqrt(sigma*2*3.1415926854))*
+		    exp(-0.5*(0.0+(i-centerx)*(i-centerx)/pow(sigma,float(2.0)))));
+	for (int j=0;j<ysize;j++)
+	    setpixel(i,j,temp);
+      }
+  Normalize(1);
+}
+//-----------------------------------------------------------------------
+void PXFloatMatrix::GenGaussian1Dy(float sigma) // all in Y-Direction !;
+{
+  if (sigma<0.1) sigma=0.1;
+  for (int i=0;i<ysize;i++)
+      {
+	float temp=(1/(sqrt(sigma*2*3.1415926854))*
+		    exp(-0.5*(0.0+(i-centery)*(i-centery)/pow(sigma,float(2.0)))));
+	for (int j=0;j<xsize;j++)
+	    setpixel(j,i,temp);
+      }
+  Normalize(1);
+}
+//-----------------------------------------------------------------------
+void PXFloatMatrix::GenGradGaussian1Dx(float sigma) // all in X-Direction !;
+{
+  if (sigma<0.01) sigma=0.01;
+  for (int i=0;i<xsize;i++)
+    {
+      float temp=(1/(sqrt(sigma*2*3.1415926854))*(float(centerx-i)/pow(sigma,float(2.0)))*
+		  exp(-0.5*(0.0+(i-centerx)*(i-centerx)/pow(sigma,float(2.0)))));
+      for (int j=0;j<ysize;j++)
+	  setpixel(i,j,temp);
+    }
+  Normalize(1);
+}
+//-----------------------------------------------------------------------
+void PXFloatMatrix::GenGradGaussian1Dy(float sigma) // all in Y-Direction !
+{
+  if (sigma<0.01) sigma=0.01;
+  for (int i=0;i<ysize;i++)
+      {
+	float temp=(1/(sqrt(sigma*2*3.1415926854))*(float(centery-i)/pow(sigma,float(2.0)))*
+	      exp(-0.5*(0.0+(i-centery)*(i-centery)/pow(sigma,float(2.0)))));
+	for (int j=0;j<xsize;j++)
+	    setpixel(j,i,temp);
+      }
+  Normalize(1);
+}
+//-----------------------------------------------------------------------
+void PXFloatMatrix::GenGrad2Gaussian1Dx(float sigma) // all in X-Direction !;
+{
+  if (sigma<0.1) sigma=0.1;
+  float A=1/( sqrt(2.0*3.1415926854) * pow(sigma,float(3.0)) );
+  float S2=pow( sigma, float(2.0) );
+  for (int i=0;i<xsize;i++)
+       {
+	float X2=pow( float(centerx-i), float(2.0) );
+	float temp= A*(X2/S2 - 1.0)*exp(-0.5*(X2/S2));
+	for (int j=0;j<ysize;j++)
+	    setpixel(i,j,temp);
+      }
+  Normalize(1);
+}
+
+//-----------------------------------------------------------------------
+void PXFloatMatrix::GenGrad2Gaussian1Dy(float sigma) // all in Y-Direction !
+{
+  if (sigma<0.1) sigma=0.1;
+  float A=1/( sqrt(2.0*3.1415926854) * pow(sigma,float(3.0)) );
+  float S2=pow( sigma, float(2.0) );
+  for (int i=0;i<ysize;i++)
+    {
+      float Y2=pow( float(centery-i), float(2.0) );
+      float temp= A*(Y2/S2 - 1.0)*exp(-0.5*(Y2/S2));
+      for (int j=0;j<xsize;j++)
+	  setpixel(j,i,temp);
+    }
+  Normalize(1);
+}
+//-----------------------------------------------------------------------
+void PXFloatMatrix::LapGaussian(float sigma)
+{
+  if (sigma<0.1) sigma=0.1;
+  for (int i=0;i<xsize;i++)
+      for (int j=0;j<ysize;j++)
+	  {
+	    float r=(float)((i-centerx)*(i-centerx)+(j-centery)*(j-centery));
+	    setpixel(i,j,(-1.0/(3.1415926854*pow(sigma,4))*(1-0.5*pow(r,float(2.0))/pow(sigma,float(2.0)))
+			  *exp(-0.5*pow(r,float(2.0))/pow(sigma,float(2.0)))));
+	  }
+  Normalize(1);
+}
+//-----------------------------------------------------------------------
+void PXFloatMatrix::Normalize(int absolutevalue)
+{
+  float sum=0.0;
+  int ia,ib;
+  for(ia=0;ia<xsize;ia++)
+      for(ib=0;ib<ysize;ib++)
+	  {
+	    if (absolutevalue)
+		sum=sum+fabs(getpixel(ia,ib));
+	    else
+		sum=sum+getpixel(ia,ib);
+	  }
+  for(ia=0;ia<xsize;ia++)
+      for(ib=0;ib<ysize;ib++)
+	  setpixel(ia,ib,getpixel(ia,ib)/sum);
+}
+
+//-----------------------------------------------------------------------
+
+
+
diff --git a/bioimagesuite30_src/numerics/pxfloatmatrix.h b/bioimagesuite30_src/numerics/pxfloatmatrix.h
new file mode 100644
index 0000000..5765718
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxfloatmatrix.h
@@ -0,0 +1,138 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pxfloatmatrix.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXFlotMatrix
+
+_Description : Class PXFloatMatrix - used to store matrixes of type float
+               
+_Call :   PXFloatMatrix(int,int);
+        
+_References : See pximage.h
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in July 1995
+                    2. Added Derivatives of Gaussian 20 Nov 95
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+#ifndef _PXFloatMatrix
+#define  _PXFloatMatrix
+
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <math.h>
+
+
+class PXFloatMatrix {
+
+ protected:	
+  
+  // Class fields self-explanatory;
+
+  static float gradient_mask[5]; // store 5x1 mask for derivatives 
+  float  *matrix; 		   // matrix storage array;
+  int	 xsize,ysize;	           // size and properties;
+  int    centerx,centery;          // radii
+  
+public:
+  
+  PXFloatMatrix(int,int);
+  virtual ~PXFloatMatrix();				
+  
+  // [A] Member Access
+  // -----------------
+  virtual void	setpixel(int x, int y, float g)	   
+      {matrix[y*xsize+x]=g;}
+  virtual float	getpixel(int x, int y)  
+      {return matrix[y*xsize+x]; }
+  virtual int	getsizex()	
+      {return xsize;}		
+  virtual int	getsizey()	
+      {return ysize;}		
+  virtual int	getradiusx()	
+      {return centerx;}		
+  virtual int	getradiusy()	
+      {return centery;}		
+  
+  // [B] Gradient functions 
+  // ----------------------
+  float GradientX(int x,int y);
+  float GradientY(int x,int y);
+  float GradientXMask(int x,int y);
+  float GradientYMask(int x,int y);
+  
+  // [C] Form Gaussian's for Scale-Space
+  // -----------------------------------
+  virtual void GenGaussian1Dx(float sigma);
+  virtual void GenGaussian1Dy(float sigma);
+  virtual void GenGaussian(float sigma);
+  virtual void GenGradGaussian1Dx(float sigma);
+  virtual void GenGradGaussian1Dy(float sigma);
+  virtual void GenGrad2Gaussian1Dx(float sigma);
+  virtual void GenGrad2Gaussian1Dy(float sigma);
+  virtual void LapGaussian(float sigma);
+
+protected:
+  void Normalize(int absolutevalue=0);
+
+};
+
+#endif /*  _PXFloatMatrix */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/numerics/pxfpbspline.cpp b/bioimagesuite30_src/numerics/pxfpbspline.cpp
new file mode 100644
index 0000000..f81de61
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxfpbspline.cpp
@@ -0,0 +1,2512 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+// This calls cyclictriadiag --  the only NR function called here. Snake functionality is obsolete and
+// can be eliminated
+//
+//---------------------------------------------------------------------------------------------------------
+
+#include "pxfpbspline.h"
+#include "pxutil.h"
+#include "nrutil.h"
+#include "nr.h"
+#include "pxregion.h"
+#include "pxfloatimage.h"
+#include "fitpack.h"
+#include "pxfloatmatrix.h"
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris Decemeber 1997   papad at noodle.med.yale.edu
+
+   see PXFPBSpline.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+// -------------------------------------------------------------------------
+int  PXFPBSpline::debugmode=0;
+real PXFPBSpline::lastfiterror=-1.0;
+// -------------------------------------------------------------------------
+PXFPBSpline::PXFPBSpline(PXFPBSpline *old)
+{
+  hasvectors=0;
+  hassnake=0;  ownsgradients=0;  ownsenergymap=0;
+  hasmatrices=0;
+  numknots=0;
+  numpoints=old->getnumpoints();
+  setclosed(old->isclosed());
+  setdegree(old->getdegree());
+  dimension=old->getdimension();
+  oldnumpoints=-1;
+  generatecontrolvectors();
+
+  int i;
+
+  for (i=0;i<old->getnumknots();i++)
+      setknot(i,old->getknot(i));
+
+  for (i=0;i<numknots*dimension;i++)
+      controlpoints[i]=old->getrawcontrol(i);
+  
+  zlevel=old->getzlevel();
+}
+// --------------------------------------------------------------------------
+PXFPBSpline::PXFPBSpline(int deg,int dim,real z,int closed)
+{
+  oldnumpoints=-1;
+  dimension=2+(dim>2);
+  hasvectors=0;
+  hassnake=0;  ownsgradients=0;  ownsenergymap=0;
+  hasmatrices=0;
+  numpoints=0;
+  numknots=0;
+  closedcurve=(closed>0);
+  setdegree(deg);
+  zlevel=z;
+}
+// --------------------------------------------------------------------------
+PXFPBSpline::~PXFPBSpline()
+{
+  if (hasvectors==1)
+      {
+	delete [] controlpoints;
+        delete [] knots;
+      }
+
+  if (hasmatrices)
+      free_dmatrix(invMatrix,1,matsize,1,matsize);
+
+  if (hassnake)
+      removesnake();
+
+}
+// --------------------------------------------------------------
+//  Vector Manipulation
+// --------------------------------------------------------------
+
+void PXFPBSpline::generatecontrolvectors()
+{
+  if (hasvectors==1)
+      {
+        delete [] knots;
+        delete [] controlpoints;
+      }
+
+  if (hasmatrices)
+      {
+	free_dmatrix(invMatrix,1,matsize,1,matsize);
+	matsize=0;
+	hasmatrices=0;
+      }
+
+  if (isclosed())
+      {
+	numknots=(numpoints+2*degree+1);
+	numcontrolpoints=(numpoints+degree);
+      }
+  else
+      {
+	numknots=(numpoints-2)+2*degree;   //	numknots=numpoints+2*degree;   
+	numcontrolpoints=numpoints;
+      }
+  
+  controlpoints=new real[numknots*dimension];
+  controlx=&controlpoints[0];
+  controly=&controlpoints[numknots];
+  if (dimension==3)
+      controlz=&controlpoints[numknots*2];
+  else
+      controlz=NULL;
+
+  knots        =new real[numknots];  
+  hasvectors   =1;
+}
+
+// --------------------------------------------------------------
+//   Set Spline degree 1=linear ,  3=cubic (FPBSpline=3)
+// --------------------------------------------------------------
+void PXFPBSpline::setdegree(integer deg)
+{
+  if (deg<1)
+      deg=1;
+  if (deg>1)
+      deg=3;
+
+  degree=deg;
+}
+
+void PXFPBSpline::setclosed(int c)
+{
+  closedcurve=(c>0);
+}
+// --------------------------------------------------------------
+real PXFPBSpline::getrawcontrol(int i) 
+{ 
+  if (hasvectors)
+      {
+	i=Irange(i,0,int(numknots*dimension-1));
+	return controlpoints[i];
+      }
+  else
+      return 0.0;
+}
+// --------------------------------------------------------------
+real PXFPBSpline::getcontrolx(int i) 
+{ 
+  if (hasvectors)
+      return controlx[indexbound(i,int(numcontrolpoints))];
+  else
+      return 0.0;
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+real PXFPBSpline::getcontroly(int i)       
+{ 
+  if (hasvectors) 
+      return controly[indexbound(i,int(numcontrolpoints))];
+  else
+      return 0.0;
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+real PXFPBSpline::getcontrolz(int i)       
+{ 
+  if (hasvectors && dimension==3) 
+      return controlz[indexbound(i,int(numcontrolpoints))];      
+  else
+      return zlevel;
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+void PXFPBSpline::setcontrol(int i,real x,real y,real z)
+{
+  if (hasvectors)
+      {
+	i=indexbound(i,int(numcontrolpoints));
+	controlx[i]=x;
+	controly[i]=y;
+	if (dimension==3)
+	    controlz[i]=z;
+      }
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+void PXFPBSpline::shiftcontrol(int i,real dx,real dy,real dz)
+{
+  if (hasvectors)
+    {
+      //int old=i;
+      i=indexbound(i,int(numcontrolpoints));
+      controlx[i]=controlx[i]+dx;
+      controly[i]=controly[i]+dy;
+      if (dimension==3)
+	controlz[i]=controlz[i]+dz;
+    }
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  
+void PXFPBSpline::setClosedControl(int i,real x,real y,real z,int off)
+{
+  if (!isclosed())
+    {
+      setcontrol(i,x,y,z);
+	return;
+      }
+  
+  if (hasvectors)
+    {
+      i=indexbound(i,int(numpoints))+off;
+      controlx[i]=x;
+      controly[i]=y;
+      if (dimension==3)
+	controlz[i]=z;
+      if (i<degree)
+	{
+	  controlx[i+numpoints]=x;
+	  controly[i+numpoints]=y;
+	  if (dimension==3)
+	    controlz[i+numpoints]=z;
+	}
+      if (i==numpoints)
+	{
+	  controlx[0]=x;
+	  controly[0]=y;
+	  if (dimension==3)
+	    controlz[0]=z;
+	}
+    }
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  
+void PXFPBSpline::shiftClosedControl(int i,real dx,real dy,real dz,int off)
+{
+  if (!isclosed())
+      {
+	shiftcontrol(i,dx,dy,dz);
+	return;
+      }
+
+  if (hasvectors)
+      {
+	i=indexbound(i,int(numpoints))+off;
+	controlx[i]+=dx;
+	controly[i]+=dy;
+	if (dimension==3)
+	    controlz[i]+=dz;
+	if (i<degree)
+	    {
+	      controlx[i+numpoints]+=dx;
+	      controly[i+numpoints]+=dy;
+	      if (dimension==3)
+		  controlz[i+numpoints]+=dz;
+	    }
+	if (i==numpoints)
+	    {
+	      controlx[0]+=dx;
+	      controly[0]+=dy;
+	      if (dimension==3)
+		  controlz[0]+=dz;
+	    }
+      }
+}
+     
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  
+real PXFPBSpline::getzlevel()
+{
+  return zlevel;
+}
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -     
+void  PXFPBSpline::setzlevel(real z)
+{
+  zlevel=z;
+  if (hasvectors && dimension==3) 
+      {
+	for(int i=0;i<numknots;i++)
+	    controlz[i]=z;
+      }
+}
+// --------------------------------------------------------------
+real PXFPBSpline::getknot(int i)
+{
+  if (hasvectors) 
+      {
+	int j=indexbound(i,int(numknots));
+	return knots[j];
+      }
+  else
+      return 0.0;
+}
+// --------------------------------------------------------------
+real PXFPBSpline::getcknot(int i)
+{
+  if (hasvectors) 
+      {
+	int j=indexbound(i,int(numcontrolpoints));
+	if (isclosed())
+	    return knots[j+degree];
+        
+	// Open Curve
+	if (j!=1 && j!=numpoints-2)
+	    return knots[j+degree-1];
+
+	if (j==1)
+	    return (1.0*knots[degree+1]+2.0*knots[degree])/3.0;
+	if (j==(numpoints-2))
+	    return (2.0*knots[degree+numpoints-3]+1.0*knots[degree+numpoints-4])/3.0;
+
+      }
+  return 0.0;
+}
+
+// --------------------------------------------------------------
+void PXFPBSpline::setknot(int i,real t)
+{
+  if (hasvectors)
+    {
+      i=indexbound(i,int(numknots));
+      knots[i]=t;
+    }
+}
+
+// --------------------------------------------------------------
+//       Set spline to be a circle or  an ellipse
+// --------------------------------------------------------------
+void PXFPBSpline::setcircle(int np,real radius,real x,real y,int dim)
+{
+  setellipse(np,radius,radius,x,y,dim);
+}
+// --------------------------------------------------------------
+void PXFPBSpline::setellipse(int npoints,real radiusx,real radiusy,
+			     real x,real y,int dim)
+{
+  int np2=int(float(Irange(npoints,4,40))*1.20);
+
+  dimension=Irange(dim,2,3);
+  closedcurve=1;
+  zlevel=0.0;  
+  degree=3;
+
+  integer  np       =np2+closedcurve; // Number of Knots 
+  integer  npm      =np*dimension;
+  real*    points   =new real[npm];
+  int      ret=0;
+
+  real zp=zlevel;
+  for (int k=0;k<np-closedcurve;k++)
+    {
+      int index=k*dimension;
+      real t=2.0*M_PI*(real(k)/real(np-closedcurve));
+      real xp=radiusx*cos(t)+x;
+      real yp=radiusy*sin(t)+y;
+      
+
+      points[index]  =xp;
+      points[index+1]=yp;
+      if (dimension==3)
+	points[index+2]=zp;
+    }
+  
+  if (isclosed())
+    {
+      points[(np-1)*dimension]=points[0];      
+      points[(np-1)*dimension+1]=points[1];
+      if (dimension==3)
+	points[(np-1)*dimension+2]=points[2];
+    }
+  
+  real*    W   =new real[np];
+  real*    U   =new real[np];
+  integer  IPAR=0;
+  integer  IOPT=-1;
+  
+  for(int i=0;i<np;i++)
+    W[i]=1.0;
+	
+  ret=fitpoints(np,W,U,npm,points,IOPT,IPAR,1.0,npoints);
+  
+  delete [] W;
+  delete [] U;
+  delete [] points;
+  return;
+}
+// --------------------------------------------------------------
+// Copy control points from another spline
+// --------------------------------------------------------------
+void PXFPBSpline::copypoints(PXFPBSpline* other)
+{
+  if (hasmatrices)
+      free_dmatrix(invMatrix,1,matsize,1,matsize);
+  hasmatrices=0;
+  
+  setclosed(other->isclosed());
+  dimension=(other->getdimension());
+  setdegree(other->getdegree());
+  numpoints=other->getnumpoints();
+  numknots=other->getnumknots();
+  generatecontrolvectors();
+  zlevel=other->getzlevel();
+
+  int i;
+  for (i=0;i<other->getnumknots();i++)
+      setknot(i,other->getknot(i));
+  for (i=0;i<numknots*dimension;i++)
+      controlpoints[i]=other->getrawcontrol(i);
+}
+// --------------------------------------------------------------
+//  Set control points to xcntrl[1:np] ycntr[1:np]  zcntrl[1:np] doz=1
+// --------------------------------------------------------------
+void PXFPBSpline::ResetUniformKnots()
+{
+  int i;
+  int order=int(degree)+1;
+
+  if (numpoints<1)
+      return;
+
+ if (isclosed())
+      {
+	for(i=int(degree)+1;i<=degree+numpoints;i++)
+	    {
+	      if (i<numknots)
+		  knots[i]=real(i-degree)/real(numpoints);
+	      else
+		  fprintf(stderr,"Overflow %d\n", i);
+	    }
+	
+	for (i=0;i<=degree;i++)
+	    {
+	      knots[i]=knots[i+numpoints]-1.0;
+	      knots[numknots-1-i]=knots[numknots-1-numpoints-i]+1.0;
+	    }
+      }
+  else
+      {
+		// First Exterior Knots 
+	for (i=0;i<order;i++)
+	    {
+	      knots[i]=0.0;
+	      knots[numknots-i-1]=1.0;
+	    }
+	// Then Interior Knots ---  uniform Parameterization
+	for (i=int(degree)+1;i<numpoints+degree-2;i++)
+	    {
+	      if (i<numknots)
+		  knots[i]=real(i-degree)/real(numpoints-3);
+	      else
+		  fprintf(stderr,"Overflow \n");
+	    }
+
+      }
+  
+}
+// ------------------------------------------------------------------
+int PXFPBSpline::indexbound(int t,int np,int off)
+{
+  if (np<0)   
+      np=int(getnumknots());
+  
+  if (t<off)    
+      t=off;
+  if (t>=np+off)  
+      t=np+off-1;
+  return t;
+}
+// ------------------------------------------------------------------
+int PXFPBSpline::indexcyclic(int t,int np,int off)
+{
+  if (np<0)   
+      np=int(getnumpoints());
+  
+  while(t<off)    
+      t=t+np;
+  while(t>=np+off)  
+      t=t-np;
+  return t;
+}
+// --------------------------------------------------------------------------
+real PXFPBSpline::arclengthcyclic(real t)
+{
+  if (isclosed())
+      {
+	while(t<0.0)  t=t+1.0;
+	while(t>=1.0) t=t-1.0;
+      }
+  else
+      {
+	if (t<=0.0)   t=0.001;
+	if (t>=1.0)   t=0.999;
+      }
+  return t;
+}
+
+
+// --------------------------------------------------------------------------
+PXContour* PXFPBSpline::storeincontour(int nodepoints)
+{
+  PXContour* cntr=new PXContour();
+  if (nodepoints==0)
+      {
+	for (int i=0;i<numpoints;i++)
+	    cntr->Add(getcontrolx(i),getcontroly(i));
+      }
+  else
+      {
+	real xp,yp;
+	for (int ib=0;ib<numpoints;ib++)
+	    {
+	      getposition(getcknot(ib),xp,yp);
+	      cntr->Add(xp,yp);
+	    }
+      }
+  return cntr;
+}
+// --------------------------------------------------------------------------
+void PXFPBSpline::getknotpoints(real* xp,real* yp,int np)
+{
+  for (int ib=0;ib<numpoints;ib++)
+      {
+	if (ib<np)
+	    getposition(getcknot(ib),xp[ib],yp[ib]);
+      }
+}
+// --------------------------------------------------------------------------
+void PXFPBSpline::getknotpoints(real* xp,real* yp,real* zp,int np)
+{
+  
+  for (int ib=0;ib<numpoints;ib++)
+      {
+	if (ib<np)
+	    getposition(getcknot(ib),xp[ib],yp[ib],zp[ib]);
+      }
+}
+// --------------------------------------------------------------------------
+PXContour* PXFPBSpline::exporttoNcontour(int np,int resample)
+{
+  PXContour* cntr=new PXContour();;
+  np=Irange(np,4,1000);
+  real x,y;
+  float step=1.0/(float(np)*5.0);
+
+  if (resample>0)
+      {
+	PXFPBSpline* temp=new PXFPBSpline(this);
+	//	fprintf(stderr,"In change Spacing np=%d step=%f closed=%d\n",np,step,this->isclosed());
+	temp->changespacing(0.5,-1,step);
+	//	fprintf(stderr,"In change Spacing Done\n");
+	for (int i=0;i<np;i++)
+	    {
+	      float s=float(i)/float(np);
+	      temp->getposition(s,x,y);
+	      cntr->Add(x,y);
+	    }
+	delete temp;
+      }
+  else
+      {
+	for (int i=0;i<np;i++)
+	    {
+	      float s=float(i)/float(np);
+	      getposition(s,x,y);
+	      cntr->Add(x,y);
+	    }
+      }
+  cntr->setclosed(this->isclosed());
+  return cntr;
+}
+
+// --------------------------------------------------------------------------
+PXContour* PXFPBSpline::exporttocontour(real dist)
+{
+  dist=Frange(dist,0.01,20.0);
+  float length=getlength(0.0,1.0,0.05);
+  int np=int(length/dist+0.5);
+
+  if (debugmode>1)
+      fprintf(stderr," Input Distance=%f, Length=%f (0.05) np=%d\n",dist,length,np);
+
+  float ds=1.0/float(2*np);
+  length=getlength(0.0,1.0,ds);
+  np=int(length/dist+0.5);
+      
+  if (debugmode>1)
+      fprintf(stderr," Input Distance=%f, Length=%f (%7.4f) np=%d\n",dist,length,ds,np);
+
+  if (np<3)
+      np=3;
+
+  // MAJOR CHANGE np,1 --> np,0   np,1 ---> major error!!!
+  PXContour* cntr=exporttoNcontour(np,0);
+  cntr->setclosed(this->isclosed());
+  return cntr;
+}
+// --------------------------------------------------------------------------
+int PXFPBSpline::sample(int sm,float step)
+{
+  return changespacing(0.5,int(numpoints)/sm,step);
+}
+// --------------------------------------------------------------------------
+int PXFPBSpline::subsample(int samples,float step)
+{
+  return changespacing(0.5,int(numpoints)*samples,step);
+}
+// --------------------------------------------------------------------------
+int PXFPBSpline::resample(float ds_step,int npoints)
+{
+  return changespacing(0.5,npoints,ds_step);
+}
+// --------------------------------------------------------------------------
+int PXFPBSpline::changespacing(real smth,int npoints,float step,float ,int iterations)
+{
+  float zl=zlevel;
+  if (dimension==3)
+      {
+	if (debugmode)
+	  fprintf(stderr, "Cannot resample 3-D curve sorry\n");
+	return 0;
+      }
+
+  int ret=0;
+
+  if (step<0)
+    {
+      real minstep=1.0;
+      for (int i=0;i<numknots-1;i++)
+	{
+	  real s=fabs(knots[i+1]-knots[i]);
+	  if (s<minstep)
+	    minstep=s;
+	}
+      step=minstep*0.05;
+    }
+  else
+    {
+      if (step>0.25)
+	step=0.25;
+      if (step<0.01)
+	step=0.01;
+    }
+
+  PXContour* cntr=new PXContour();
+  for (real s=0.0;s<1.0;s=s+step)
+      {
+	real x,y;
+	getposition(s,x,y);
+	cntr->Add(x,y);
+      }
+
+
+
+
+ 
+  if (npoints<degree)
+    {
+      //      fprintf(stderr,"+++ Points = %d,%d deg=%d\n",cntr->getnumpoints(),npoints,degree);
+      ret=fitcontour(cntr,smth,0.0,int(degree),isclosed(),0,-1,iterations);
+
+    }
+  else
+    {
+      //      fprintf(stderr,"** Points = %d,%d\n",cntr->getnumpoints(),npoints);
+      ret=fitcontour(cntr,smth,0.0,int(degree),isclosed(),1,npoints,iterations);
+    }
+  
+  delete cntr;
+  zlevel=zl;
+  return ret;
+}
+
+// --------------------------------------------------------------------------
+int PXFPBSpline::fittocontour(PXContour* cntr,real smooth,real csmooth,
+			      int numpoints,int closed,int iterations)
+{
+  int uniform=(numpoints>0);
+
+  if (numpoints==-2)
+    uniform=1;
+
+  return (fitcontour(cntr,smooth,csmooth,3,closed,uniform,numpoints,iterations)<=0);
+}
+// --------------------------------------------------------------------------
+
+int PXFPBSpline::fitcontour(PXContour* cnt_in,real smth,real cntrsmth,
+			    int deg,int cl,int uniform,int npoints,int iterations)
+{
+  PXContour* cntr=new PXContour(cnt_in);
+  if (debugmode)
+    fprintf(stderr,"Numberof Points %d uniform=%d npoints=%d\n",cnt_in->getnumpoints(),uniform,npoints);
+
+  // Set bspline parameters 
+  closedcurve=(cl>0);  dimension=2;  zlevel=0.0;  degree=deg;
+  integer  np       =cntr->getnumpoints()+closedcurve; // Number of Knots 
+  integer  npm      =np*dimension;
+  real*    points   =new real[npm];
+  int ret=0;
+
+  if (cntrsmth>=0.5)
+      {
+	//cntr->Smooth(cntrsmth);
+	cntr->nonShrinkSmooth(cntrsmth,iterations);
+      }
+  
+  PXContourPoint* temp=cntr->gettoppoint();
+  for (int k=0;k<np-closedcurve;k++)
+      {
+	int index=k*2;
+	points[index]  =temp->x;   
+	points[index+1]=temp->y;
+	temp=temp->next;
+      }
+  
+  if (isclosed())
+      {
+	points[(np-1)*2]=points[0];      
+	points[(np-1)*2+1]=points[1];
+      }
+  
+  if (cntrsmth<0.5 && uniform<1)
+      {
+	ret=fitpoints(np,npm,points,smth);
+      }
+  else
+      {
+	real*    W   =new real[np];
+	real*    U   =new real[np];
+	integer  IPAR=(cntrsmth>=0.5);
+	integer  IOPT=-1;
+	if (uniform==0)
+	  IOPT=0;
+	
+	
+	for(int i=0;i<np;i++)
+	    W[i]=1.0;
+	
+	if (IPAR==1)
+	    {
+	      U[0]=0.0;
+	      PXContourPoint* temp=cntr->gettoppoint();
+	      real x0=temp->x,y0=temp->y;
+	      
+	      for (int j=1;j<np-closedcurve;j++)
+		  {
+		    temp=temp->next;
+		    U[j]=U[j-1]+sqrt(pow(temp->x-x0,float(2.0))+
+				     pow(temp->y-y0,float(2.0)));
+		    x0=temp->x;
+		    y0=temp->y;
+		  }
+	      
+	      if (isclosed())
+		  {
+		    temp=cntr->gettoppoint();
+		    U[np-1]=U[np-2]+sqrt(pow(x0-temp->x,float(2.0))+pow(temp->y-y0,float(2.0)));
+		  }
+	      for(int l=0;l<np;l++)
+		  U[l]=U[l]/U[np-1];
+	    }
+
+	ret=fitpoints(np,W,U,npm,points,IOPT,IPAR,smth,npoints);
+
+	delete [] W;
+	delete [] U;
+      }
+
+  delete cntr;
+  delete [] points;
+  return ret;
+}
+// --------------------------------------------------------------------------
+int PXFPBSpline::fitpoints(integer m,integer mx,real* X,float smth)
+{  
+  real*    W   =new real[m];
+  real*    U   =new real[m];
+
+  for(int i=0;i<m;i++)
+      W[i]=1.0;
+
+  int ret=fitpoints(m,W,U,
+		    mx,X,
+		    0,0,smth);
+
+  delete [] W;
+  delete [] U;
+  return ret;
+}
+// ------------------------------------------------------------------
+int PXFPBSpline::fitpoints(integer m,real* W,real* U,integer mx,real* X,
+			   integer IOPT,integer IPAR,float smth,int npoints)
+{  
+  integer  M   =m;
+  integer  MX  =mx;
+  integer  K   =getdegree();
+  real     S   =smth;                // Smoothing Factor
+  integer  NEST=2*(M+K);             // Temporary Storage Space size
+  integer  N   =0;                   // Number of Knots
+  real*    T   =new real[NEST];      // Store Knots on Exit
+  integer  NC = NEST*dimension;
+  real*    C   =new real[NC];        // Store Weights on Exit
+
+  real     FP  =0.0;                 // Residual Error
+  integer  LWRK=M*(K+1)+NEST*(7+dimension+5*K);
+  real*    WRK =new real[LWRK];
+  integer* IWRK=new integer[NEST];
+  integer  IER =0;
+
+
+  if (IOPT==-1)
+      {
+	if (isclosed())
+	    N=(npoints+2*degree+1);
+	else
+	    N=(npoints-2)+2*degree;
+		
+	for (int i=0;i<npoints;i++)
+	    {
+	      T[i+degree]=real(i)/real(npoints-3*(1-closedcurve));
+	    }
+      }
+
+  if (isclosed())
+      {
+	// Calling FITPACK 
+	clocur_(&IOPT, &IPAR,&dimension,
+		&M, U,&MX,X,W,
+		&K,&S,&NEST,&N,T,&NC,C,
+		&FP,WRK,&LWRK,IWRK,&IER);
+      }
+  else
+      {
+	real UB,UM;
+	if (IPAR==1)
+	    {
+	      UB=U[0];
+	      UM=U[M-1];
+	    }
+		  
+	// Calling FITPACK 
+	parcur_(&IOPT, &IPAR,&dimension,
+		&M, U,&MX,X,W,&UB,&UM,
+		&K,&S,&NEST,&N,T,&NC,C,
+		&FP,WRK,&LWRK,IWRK,&IER);
+      }
+
+  
+  if (int(IER)<=0)
+      {
+	
+	if (isclosed())
+	    numpoints=N-2*K-1;
+	else
+	    numpoints=N-2*K+2;
+	generatecontrolvectors();
+	if (debugmode)
+	    fprintf(stderr,"Output :  Clocur(%1d)/Parcur(%1d)  IER=%d FP=%7.4f N=%d ,IOPT=%d , IPAR=%d\n",
+		    isclosed(),!isclosed(),
+		    int(IER),FP,int(N),int(IOPT),int(IPAR));
+	
+	for (int i=0;i<numknots;i++)
+	    knots[i]=T[i];
+	for (int j=0;j<numknots*dimension;j++)
+	    controlpoints[j]=C[j];
+      }
+  else
+      {
+	if (debugmode)
+	    {
+	      fprintf(stderr,"E R R O R   :  Clocur/Parcur output IER=%d FP=%7.4f N=%d ,IOPT=%d , IPAR=%d\n",int(IER),FP,int(N),int(IOPT),int(IPAR));
+	    }
+      }
+  lastfiterror=FP;
+  delete [] IWRK;
+  delete [] WRK;
+  delete [] C;
+  delete [] T;
+  return (int)IER;
+}
+// ------------------------------------------------------------------
+//           I/O Functions
+//
+//        Save & Load -->              Spline Format (Control Points)
+//        SaveContour & LoadContour    Contour Format
+// ------------------------------------------------------------------
+int  PXFPBSpline::Save(const char* filename)
+{
+  int ret=0;
+  FILE* fout=fopen(filename,"w");
+  if (fout!=NULL)
+    {
+      ret=Save(fout);
+      fclose(fout);
+    }
+  if (debugmode)
+      fprintf(stderr,"Saved in %s (Status=%1d)\n",filename,ret);
+  return(ret);
+}
+// ------------------------------------------------------------------
+int  PXFPBSpline::Save(FILE* fout )
+{
+  fprintf(fout, "#FPBSpline File header= dimension,zlevel,degree,closed,numpoints\n");
+  fprintf(fout, "#%d\n" , (int)dimension );
+  fprintf(fout, "#%f\n" , zlevel );
+  fprintf(fout, "#%d\n" , (int)degree );
+  fprintf(fout, "#%d\n" , closedcurve );
+  fprintf(fout, "#%d\n" , (int)numpoints );
+  fprintf(fout, "#----------------------\n");
+
+  int i;
+  fprintf(fout,"#");
+  for (i=0;i<numknots;i++)
+      fprintf(fout,"%8.5f ",real(knots[i]));
+
+  fprintf(fout,"\n"); 
+  for (i=0;i<numcontrolpoints;i++)
+      {
+	for (int j=0;j<dimension;j++)
+	    {
+	      fprintf(fout,"%6.2f ",controlpoints[i+j*numknots]);
+	    }
+	fprintf(fout,"\n");
+      }
+  return 1;
+}
+// --------------------------------------------------------------
+int PXFPBSpline::Load(const char* filename)
+{
+  int status=0;
+  gzFile fin=gzsuffixopen(filename,"r");
+  if (fin!=Z_NULL)
+      status=Load(fin);
+
+  gzclose(fin);
+
+  if (debugmode && status==1)
+      fprintf(stderr,"Loading from %s (numpoints=%2d) Status=%d\n",filename,
+	      int(numpoints),status);
+
+  if (debugmode && status==0)
+      fprintf(stderr,"Failed to Load from %s\n",filename);
+
+  return(status);
+}
+// --------------------------------------------------------------
+int PXFPBSpline::Load(gzFile fin)
+{
+  char line[200];
+  int status=0;
+  gzgets(fin,line,200);
+
+  if (gzfindstringinstring(line, "#FPBSpline File"))
+      {
+	int deg=3,clo=0,dim,np;
+	real kn;
+	gzgets(fin,line,100); sscanf(line,"#%d",&dim);
+	gzgets(fin,line,100); sscanf(line,"#%f",&zlevel);
+	gzgets(fin,line,100); sscanf(line,"#%d",&deg);
+	
+	gzgets(fin,line,100); sscanf(line,"#%d",&clo);
+	setclosed(clo);
+	setdegree(deg);
+	dimension=Irange(dim,2,3);
+	gzgets(fin,line,100); sscanf(line,"#%d",&np);
+	numpoints=np;
+	gzgets(fin,line,100);
+	if (numpoints>0 && numpoints<2048)
+	    {
+	      status=1;
+	      generatecontrolvectors();
+	      gzgetc(fin); // eat the leading #
+	      for (int i=0;i<numknots;i++)
+		{
+		  kn=getgzstreamfloat(fin);
+		  setknot(i,kn);
+		}
+	      if (isclosed())
+		{
+		  for (int i=0;i<degree;i++)
+		    {
+		      int ik=i+numpoints;
+
+		      double v=knots[ik]-1.0;
+		      if (fabs(knots[i]-v)>0.01)
+			{
+			  knots[i]=v;
+			  //  fprintf(stderr,"Mapping %d to %d (%.3f to %.3f)\n",
+			  //		  i,ik,knots[i],v);
+			}
+		      int ip=i+numpoints+int(degree)+1;
+		      int il=i+degree+1;
+		      double vv=knots[il]+1.0;
+		      if (fabs(knots[ip]-vv)>0.01)
+			{
+			  //  fprintf(stderr,"Mapping %d to %d (%.3f to %.3f)\n",
+			  //	  ip,il,knots[ip],vv);
+			  knots[ip]=vv;
+			}
+		    }
+		}
+
+	      //gzgets(fin,line,100);
+	      for(int i=0;i<numcontrolpoints;i++)
+		{
+		  for (int j=0;j<dimension;j++)
+		    {
+		      controlpoints[i+j*numknots]=getgzstreamfloat(fin);
+		      //  fprintf(stderr,"Ctrl %d val %f\n",i+j*numknots,controlpoints[i+j*numknots]);
+		    }
+		}
+	      gzgets(fin,line,100);
+	    }
+
+      }
+
+
+
+  return(status);
+}
+// --------------------------------------------------------------
+int PXFPBSpline::SaveContour(const char* filename,real dist)
+{
+  PXContour* tempcntr=exporttocontour(dist);
+  int r=tempcntr->Save(filename);
+  delete tempcntr;
+  if (debugmode)
+      fprintf(stderr,"Saved in %s as contour d=%5.2f (Status=%1d)\n",filename,dist,r);
+
+  return r;
+}
+// --------------------------------------------------------------
+//      Evaluate FPBSpline position and derivative info
+//             xpoint[] , ypoint[] contain the conrol points
+//                        use control2vector() to get these
+//
+//   getposition(real s,real& x,real &y)
+//   getderivative(real s,real &x,real &y)
+//   get2derivative(real s,real x,real &y)
+//   real  getcurvature(real s)
+//   real getlength(real s0,real s1,real ds_step)
+//   getmeanposition(real& x,real& y)
+//
+// --------------------------------------------------------------
+void  PXFPBSpline::getposition(real s,real& x,real& y)
+{
+  real z;
+  getposition(s,x,y,z);
+     
+}
+// --------------------------------------------------------------
+void  PXFPBSpline::getposition(real s,real& x,real& y,real& z)
+{
+  integer ier=0;
+  integer M=1;
+  integer K=3;
+  integer N=numknots;
+
+  integer NC=numknots*dimension;
+  integer mx=3;
+  real    X[3];
+  
+  s=arclengthcyclic(s);
+
+  // Calling FITPACK 
+  curev_(&dimension,
+	 knots,&N,
+	 controlpoints,&NC,
+	 &K,&s,&M,X,&mx,&ier);
+	
+  x=X[0]; y=X[1]; 
+  if (dimension==3)
+      z=X[2];
+  else
+      z=zlevel;
+
+}
+// --------------------------------------------------------------
+void PXFPBSpline::getallderivatives(integer n,real  s,real* xd,real* yd,real* zd)
+{
+  integer ier=0;
+  integer NC=numknots*dimension;
+  integer k1=degree+1;
+  integer nd=dimension*k1;
+  real    D[20];
+
+  // Calling FITPACK 
+  s=arclengthcyclic(s);
+  cualde_(&dimension,knots,&numknots,
+          controlpoints,&NC,
+          &k1,&s,
+          D,&nd,&ier);
+
+  for (int i=1;i<=n;i++)
+      {
+	xd[i-1]=D[dimension*i];
+	yd[i-1]=D[dimension*i+1];
+	if (dimension==3)
+	    zd[i-1]=D[dimension*i+2];
+      }
+}
+// --------------------------------------------------------------
+void  PXFPBSpline::getderivative(real s,real& x,real& y)
+{
+  real xd[3],yd[3],zd[3];
+  getallderivatives(3,s,xd,yd,zd);
+  x=xd[0];
+  y=yd[0];
+  
+}
+// --------------------------------------------------------------
+void  PXFPBSpline::getderivative(real s,real& x,real& y,real& z)
+{
+  real xd[3],yd[3],zd[3];
+  getallderivatives(3,s,xd,yd,zd);
+  x=xd[0];
+  y=yd[0];
+  z=zd[0];
+}
+// --------------------------------------------------------------
+void  PXFPBSpline::get2derivative(real s,real& x,real& y)
+{
+  real xd[3],yd[3],zd[3];
+  getallderivatives(3,s,xd,yd,zd);
+  x=xd[1];
+  y=yd[1];
+}
+
+// --------------------------------------------------------------
+void  PXFPBSpline::get2derivative(real s,real& x,real& y,real& z)
+{
+  real xd[3],yd[3],zd[3];
+  getallderivatives(3,s,xd,yd,zd);
+  x=xd[1];
+  y=yd[1];
+  z=zd[1];
+}
+
+// --------------------------------------------------------------
+real  PXFPBSpline::getcurvature(real s)
+{
+  real xd[3],yd[3],zd[3];
+  getallderivatives(3,s,xd,yd,zd);
+  real xder,yder,x2der,y2der;
+
+  xder =xd[0];
+  x2der=xd[1];
+  yder =yd[0];
+  y2der=yd[1];
+  real nom=pow(xder*y2der-x2der*yder,float(2.0));
+  real denom=pow(xder*xder+yder*yder,float(3.0));
+  if ( denom <= 0.000001 ) 
+      denom = 0.000001;
+  real curv=nom/denom;
+  // Round to 4 d.p. to reduce round-off errors
+  // -------------------------------------------
+  return quantize(curv,4);
+}
+
+// --------------------------------------------------------------
+real PXFPBSpline::getlength(real s0,real s1,real ds_step)
+{
+  real x0=0.0,x,y0=0.0,y,z0=zlevel,z=zlevel;
+  real length=0.0;
+
+  for (real t=s0;t<=s1;t=t+ds_step)
+      {
+	if (dimension==2)
+	      getposition(t,x,y);
+	else
+	    getposition(t,x,y,z);
+	if (t!=s0)
+	    length=length+sqrt(pow(x-x0,float(2.0))+pow(y-y0,float(2.0))+pow(z-z0,float(2.0)));
+	
+	x0=x;
+	y0=y;
+	z0=z;
+      }
+  return length;
+}
+// --------------------------------------------------------------
+// S N A K E  F U N C T I O N A L I T Y
+// --------------------------------------------------------------
+void PXFPBSpline::createsnake(PXImage* pimage,float img_coeff,float smooth_coeff,
+			      float timestep,float sigma,int niter,float baloon_coeff)
+{
+  if (hassnake)
+      removesnake();
+
+  if (getnumpoints()>0 && isclosed())
+      {
+	hassnake=1;
+      }
+  else
+      {
+	hassnake=0;
+	return;
+      }
+  
+  sn_offsetx=0;
+  sn_offsety=0;
+  sn_imweight=img_coeff;
+  sn_smweight=smooth_coeff;
+  sn_usrtstep=timestep/float(numpoints);
+  sn_numiter=niter;
+  sn_sigma=sigma;
+  sn_baloon=baloon_coeff;
+
+  
+  ownsgradients=0;
+  sn_maxgrad=calcpotential(pimage);
+  ownsenergymap=1;
+  ownsgradients=1;
+  
+
+  if (debugmode)
+      fprintf(stderr,"Creating Snake %d (%d)\n",int(numpoints),isclosed());
+}
+// --------------------------------------------------------------
+void PXFPBSpline::createsnake(PX2DRegion* region,
+			      float region_weight,float smooth_coeff,
+			      float timestep,float sigma,int niter,float baloon_coeff)
+{
+  createsnake(NULL,region,NULL,0.0,region_weight,0.0,smooth_coeff,timestep,
+	      sigma,niter,baloon_coeff);
+}
+// --------------------------------------------------------------
+void PXFPBSpline::createsnake(PXImage* pimage,PX2DRegion* region,
+			      float img_coeff,float region_weight,
+			      float smooth_coeff,
+			      float timestep,float sigma,int niter,float baloon_coeff)
+{
+  createsnake(pimage,region,NULL,img_coeff,region_weight,0.0,smooth_coeff,timestep,
+	      sigma,niter,baloon_coeff);
+}
+// --------------------------------------------------------------
+void PXFPBSpline::createsnake(PXImage* pimage,PXFloatImage* external,
+			      float img_coeff,float ext_weight,
+			      float smooth_coeff,
+			      float timestep,float sigma,int niter,float baloon_coeff)
+{
+  if (debugmode)
+    fprintf(stderr,"ext_weight2=%5.2f\n",ext_weight);
+  createsnake(pimage,NULL,external,img_coeff,0.0,ext_weight,smooth_coeff,timestep,
+	      sigma,niter,baloon_coeff);
+
+}
+// --------------------------------------------------------------
+void PXFPBSpline::createsnake(PX2DRegion* region,PXFloatImage* external,
+			      float region_weight,float ext_weight,
+			      float smooth_coeff,
+			      float timestep,float sigma,int niter,float baloon_coeff)
+{
+  if (debugmode)
+    fprintf(stderr,"ext_weight3=%5.2f\n",ext_weight);
+  createsnake(NULL,region,external,0.0,region_weight,ext_weight,smooth_coeff,timestep,
+	      sigma,niter,baloon_coeff);
+}
+
+// --------------------------------------------------------------
+
+void PXFPBSpline::createsnake(PXImage* pimage,PX2DRegion* region,PXFloatImage* external,
+			      float img_coeff,float region_weight,float ext_weight,
+			      float smooth_coeff,
+			      float timestep,float sigma,int niter,float baloon_coeff)
+{
+  if (debugmode)
+    fprintf(stderr,"ext_weight4=%5.2f\n",ext_weight);
+
+  if (hassnake)
+      removesnake();
+  
+  if (getnumpoints()>0 && isclosed())
+      {
+	hassnake=1;
+      }
+  else
+      {
+	hassnake=0;
+	return;
+      }
+  sn_offsetx=0;  sn_offsety=0;
+  sn_imweight=img_coeff+region_weight;  
+  sn_smweight=smooth_coeff;
+  sn_usrtstep=timestep/float(numpoints);
+  sn_numiter=niter;  sn_sigma=sigma;
+  sn_maxgrad=calc3potential(pimage,region,external,img_coeff,region_weight,ext_weight);
+  sn_baloon=baloon_coeff;
+  ownsgradients=1;  ownsenergymap=1; 
+}
+// --------------------------------------------------------------
+void PXFPBSpline::createsnake(PXFloatImage* pimage,
+			      float img_coeff,float smooth_coeff,
+			      float timestep,float sigma,int niter,float baloon_coeff)
+{
+  if (hassnake)
+      removesnake();
+  if (getnumpoints()>0 && isclosed())
+      {
+	hassnake=1;
+      }
+  else
+      {
+	hassnake=0;
+	return;
+      }
+  
+  sn_offsetx=0;  sn_offsety=0;
+  sn_imweight=img_coeff;  sn_smweight=smooth_coeff;
+  sn_usrtstep=timestep/float(numpoints);
+  sn_numiter=niter;  sn_sigma=sigma;
+
+  /*sn_energymap=pimage;
+  ownsenergymap=0;*/
+
+  sn_energymap=new PXFloatImage(pimage);
+  ownsenergymap=1;
+  sn_maxgrad=generategradients();
+
+}
+// --------------------------------------------------------------
+real PXFPBSpline::generategradients()
+{
+  int sg=int(sn_sigma*2.0+0.5)*2+1;
+  PXFloatMatrix* kernelx=new PXFloatMatrix(sg,1);
+  PXFloatMatrix* kernely=new PXFloatMatrix(1,sg);
+  kernelx->GenGradGaussian1Dx(fabs(sn_sigma)/2.0);
+  kernely->GenGradGaussian1Dy(fabs(sn_sigma)/2.0);
+  
+  int x1=2000,x2=0,y1=2000,y2=0,x,y;
+  
+  for (int kk=0;kk<getnumpoints();kk++)
+      {
+	x=(int)getcontrolx(kk);
+	y=(int)getcontroly(kk);
+	if (x<x1) x1=x;
+	if (x>x2) x2=x;
+	if (y<y1) y1=y;
+	if (y>y2) y2=y;
+      }
+  
+  x1=x1-10; x2=x2+10; y1=y1-10; y2=y2+10;
+  if (x1<1) x1=1; 	if (y1<1) y1=1;
+  if (x2>=sn_energymap->getsizex()-1) x2=sn_energymap->getsizex()-1;
+  if (y2>=sn_energymap->getsizey()-1) y2=sn_energymap->getsizey()-1;
+  
+  sn_energymap->SetMaxMingrayscale();
+  sn_gradx = new PXFloatImage(sn_energymap,kernelx,x1,x2,y1,y2);
+  sn_grady = new PXFloatImage(sn_energymap,kernely,x1,x2,y1,y2);
+  float maxg=Fmax(sn_energymap->getmaxgrayscale(),
+		  fabs(sn_energymap->getmingrayscale()));
+  
+  delete kernelx;
+  delete kernely;
+  ownsgradients=1;
+  return maxg;
+}
+// --------------------------------------------------------------
+real PXFPBSpline::updatesnake(real tolerance)
+{
+  if (!hassnake)
+      return 0.0;
+
+
+  real der_step=0.5*sn_sigma,max_move=0.0;
+  real fx=0.0,fy=0.0;
+  real sx=0.0,sy=0.0;
+  real bx=0.0,by=0.0;
+  
+  for(int n=0;n<sn_numiter;n++)
+      {
+	if (debugmode)
+	  fprintf(stderr,"\n Iteration:%d\n ",n);
+	max_move=0.0;
+	int shift=int(float(getnumpoints())*float(rand()/32768.0)+0.5);
+	for(int aj=0;aj<getnumpoints();aj++)
+	  {
+	    int j=indexcyclic(aj+shift,int(numpoints),0);
+	    if (debugmode)
+	      fprintf(stderr,"%2d ",j);
+	    controlexternalforce(fx,fy,j);
+	    controlbaloonforce(bx,by,j);
+	    splinechangeinternalenergy(j,der_step,sx,sy);
+	    
+    
+	    if (debugmode)
+	      fprintf(stderr,"Forces Ext(%f:%f) Baloon (%f,%f) Int (%f:%f)\n ",fx,fy,bx,by,sx,sy);
+	      
+	    real dx0=(-sn_smweight*sx*0.001 + sn_baloon*bx + sn_imweight*fx);
+	    real dy0=(-sn_smweight*sy*0.001 + sn_baloon*by + sn_imweight*fy);
+	      
+	    // adaptively estimate the time step size 
+	    real t_step = 2.0*sn_usrtstep,a_step=0.0;
+	    do
+	      {
+		t_step = t_step/2.0;
+		a_step = t_step*sqrt(dx0*dx0+dy0*dy0);
+	      }
+	    while( a_step > 3.0 );
+	    
+	    // Euler update 
+	    real dx= t_step*dx0;
+	    real dy= t_step*dy0;
+	    
+	    if (debugmode)
+	      fprintf(stderr,"Shift %f:%f",dx,dy);
+	    
+	    // Check for convergence
+	    // Make sure snake stays inside image
+	    if(checkbounds(j,			     
+			   sn_offsetx,sn_gradx->getsizex()+sn_offsetx,
+			   sn_offsety,sn_grady->getsizey()+sn_offsety))
+	      {
+		shiftClosedControl(j,dx,dy);
+		real ds=sqrt(dx*dx+dy*dy);
+		max_move=Fmax(ds,max_move);
+	      }
+	  }
+	if (debugmode)
+	  fprintf(stderr,"\n");
+	
+	if (max_move<tolerance)
+	  return max_move;
+      }
+  
+  return max_move;
+}
+// --------------------------------------------------------------
+PXFloatImage* PXFPBSpline::getenergymap()
+{ 
+  if (hassnake)
+      return sn_energymap;
+  else
+      return NULL;
+}
+// --------------------------------------------------------------
+unsigned char* PXFPBSpline::getenergytexturemap(float gamma,int numbytes) 
+{ 
+  if (hassnake)
+      return sn_energymap->getslice(gamma,numbytes);
+  else
+      return NULL;
+
+}
+// --------------------------------------------------------------
+void PXFPBSpline::removesnake()
+{
+  if (hassnake)
+      {
+	if (ownsgradients)
+	    {
+	      delete sn_gradx;
+	      delete sn_grady;
+	      ownsgradients=0;
+	    }
+	if (ownsenergymap)
+	    {
+	      delete sn_energymap;
+	      ownsenergymap=0;
+	    }
+	hassnake=0;
+      }
+}
+// --------------------------------------------------------------
+real PXFPBSpline::calc3potential(PXImage* pimage,PX2DRegion *region,PXFloatImage* external,
+				 float w_im,float w_r,float w_ext,
+				 int fullimage)
+{
+  if (debugmode)
+    fprintf(stderr,"W_im =%6.2f , w_r=%6.2f w_e=%6.3f\n",w_im,w_r,w_ext);
+
+  real mag,max=0.0;
+  sn_sigma=fabs(sn_sigma);
+  int sg=int(sn_sigma*2.0+0.5)*2+1;
+  
+  PXFloatMatrix* kernelx=new PXFloatMatrix(sg,1);
+  PXFloatMatrix* kernely=new PXFloatMatrix(1,sg);
+  kernelx->GenGradGaussian1Dx(fabs(sn_sigma)/2.0);
+  kernely->GenGradGaussian1Dy(fabs(sn_sigma)/2.0);
+
+  PXFloatImage *tempx1=NULL,*tempy1=NULL,*tempx2=NULL,*tempy2=NULL;
+
+  // Find derivatives of energy field by convolving with gaussian 
+  // *************************************************************
+  int x1=2000,x2=0,y1=2000,y2=0,x,y,xsize=0,ysize=0;
+
+  if (fullimage)
+      {
+	if (w_im>0.0)
+	    {
+	      x1=1; y1=1; x2=pimage->getsizex()-1; y2=pimage->getsizey()-1;
+	      xsize=pimage->getsizex(); ysize=pimage->getsizey();
+	    }
+	else if (w_ext>0.0)
+	    {
+	      x1=1; y1=1; x2=external->getsizex()-1; y2=external->getsizey()-1;
+	      xsize=external->getsizex(); ysize=external->getsizey();
+	    }
+	else if (w_r>0.0)
+	    {
+	      x1=1; y1=1; x2=region->getoutputimage()->getsizex()-1; y2=region->getoutputimage()->getsizey()-1;
+	      xsize=region->getoutputimage()->getsizex(); ysize=region->getoutputimage()->getsizey();
+	    }
+
+	if (w_im>0.0)
+	    {
+	      tempx1 = new PXFloatImage(pimage,kernelx);
+	      tempy1 = new PXFloatImage(pimage,kernely);
+	    }
+	else
+	    w_im=0.0;
+
+	if (w_r>0.0)
+	    {
+	      tempx2 = new PXFloatImage(region->getoutputimage(),kernelx);
+	      tempy2 = new PXFloatImage(region->getoutputimage(),kernely);
+	    }
+	else 
+	    w_r=0.0;
+	
+	if (w_ext<=0.0)
+	    w_ext=0.0;
+      }
+  else
+      {
+	for (int kk=0;kk<getnumpoints();kk++)
+	    {
+	      x=(int)getcontrolx(kk);
+	      y=(int)getcontroly(kk);
+	      if (x<x1) x1=x;
+	      if (x>x2) x2=x;
+	      if (y<y1) y1=y;
+	      if (y>y2) y2=y;
+	    }
+	
+	x1=x1-10; x2=x2+10; y1=y1-10; y2=y2+10;
+	
+	if (w_im>0.0)
+	    {
+	      xsize=pimage->getsizex(); ysize=pimage->getsizey();
+	    }
+	else if (w_ext>0.0)
+	    {
+	      xsize=external->getsizex(); ysize=external->getsizey();
+	    }
+	else if (w_r>0.0)
+	    {
+	      xsize=region->getoutputimage()->getsizex(); ysize=region->getoutputimage()->getsizey();
+	    }
+
+	x1=Irange(x1,1,xsize-2);	x2=Irange(x2,x1,xsize-1);
+	y1=Irange(y1,1,ysize-2);	y2=Irange(y2,y1,ysize-1);
+	if (w_im>0.0)
+	    {
+	      tempx1 = new PXFloatImage(pimage,kernelx,x1,x2,y1,y2);
+	      tempy1 = new PXFloatImage(pimage,kernely,x1,x2,y1,y2);
+	    }
+	if (w_r>0.0)
+	    {
+	      tempx2 = new PXFloatImage(region->getoutputimage(),kernelx,x1,x2,y1,y2);
+	      tempy2 = new PXFloatImage(region->getoutputimage(),kernely,x1,x2,y1,y2);
+	    }
+      }
+
+  //  fprintf(stderr,"Energymap %d*%d (%d:%d,%d:%d)\n",xsize,ysize,x1,x2,y1,y2);
+  sn_energymap = new PXFloatImage(xsize,ysize);
+  float max1=0.1,max2=0.1,max3=0.1;
+  for (int k=0;k<sn_energymap->getsizex();k++)
+      for(int j=0;j<sn_energymap->getsizey();j++)
+	  {
+	    if (k==0 || k==sn_energymap->getsizex()-1 || j==0 || j==sn_energymap->getsizey()-1)
+		sn_energymap->setpixel(k,j,255.0);
+	    else
+		sn_energymap->setpixel(k,j,0.0);
+	  }
+
+
+  if (w_im>0.0)
+      {
+	for (int k=0;k<sn_energymap->getsizex();k++)
+	    for(int j=0;j<sn_energymap->getsizey();j++)
+		max1=Fmax(max1,pow(tempx1->getpixel(k,j),float(2.0))+pow(tempy1->getpixel(k,j),float(2.0)));
+      }
+  
+  if (w_r>0.0)
+      {
+	for (int k=0;k<sn_energymap->getsizex();k++)
+	    for(int j=0;j<sn_energymap->getsizey();j++)
+		max2=Fmax(max2,pow(tempx2->getpixel(k,j),float(2.0))+pow(tempy2->getpixel(k,j),float(2.0)));
+      }
+  if (w_ext>0.0)
+      {
+	for (int k=0;k<sn_energymap->getsizex();k++)
+	    for(int j=0;j<sn_energymap->getsizey();j++)
+		max3=Fmax(max3,external->getpixel(k,j));
+      }
+
+  if (w_im>0.0)
+      {
+	w_r=(w_r/w_im)*max1/max2;
+	w_ext=(w_ext/w_im)*max1/max3;
+      }
+  else
+      {
+	if (w_r>0.0)
+	    w_ext=(w_ext/w_r)*max2/max3;
+      }
+  
+
+  if (debugmode)
+    fprintf(stderr," Weight/Max  Img=%f/%f Reg=%f/%f Prior =%f/%f\n",
+	    max1,w_im,max2,w_r,max3,w_ext);
+
+  float sum=w_im+w_r;
+
+  for (int i=x1;i<x2;i++)
+      for (int j=y1;j<y2;j++)
+	  {
+	    float magx=0.0,magy=0.0;
+	    if (w_im>0.0)
+		{
+		  magx+=w_im*tempx1->getpixel(i,j);
+		  magy+=w_im*tempy1->getpixel(i,j);
+		}
+	    if (w_r>0.0)
+		{
+		  magx+=w_r*tempx2->getpixel(i,j);
+		  magy+=w_r*tempy2->getpixel(i,j);
+		} 
+	    magx/=sum;
+	    magy/=sum;
+	    mag=sqrt(magx*magx+magy*magy);
+	    if (w_ext>0.0)
+		mag+=w_ext*external->getpixel(i,j);
+	    
+	    sn_energymap->setpixel(i,j,mag);
+	    if (max<mag) max=mag;
+	  }
+  
+  
+  sn_gradx = new PXFloatImage(sn_energymap,kernelx,x1,x2,y1,y2);
+  sn_grady = new PXFloatImage(sn_energymap,kernely,x1,x2,y1,y2);
+  
+  
+  if (w_im>0.0)
+      {
+	delete tempx1;  delete tempy1;
+      }
+  if (w_r>0.0)
+      {
+	delete tempx2;  delete tempy2;
+      }
+
+  delete kernelx;
+  delete kernely;
+  ownsgradients=1;
+  return max;
+}
+// --------------------------------------------------------------
+real PXFPBSpline::calcpotential(PXImage* pimage,int fullimage)
+{
+  real mag,max=0.0;
+  sn_sigma=fabs(sn_sigma);
+  int sg=int(sn_sigma*2.0+0.5)*2+1;
+
+  
+  PXFloatMatrix* kernelx=new PXFloatMatrix(sg,1);
+  PXFloatMatrix* kernely=new PXFloatMatrix(1,sg);
+  kernelx->GenGradGaussian1Dx(fabs(sn_sigma)/2.0);
+  kernely->GenGradGaussian1Dy(fabs(sn_sigma)/2.0);
+
+  PXFloatImage *tempx,*tempy;
+
+  // Find derivatives of energy field by convolving with gaussian st.dev 1.0
+  // ***********************************************************************
+  int x1=2000,x2=0,y1=2000,y2=0,x,y;
+
+  if (fullimage)
+      {
+	x1=1; y1=1; x2=pimage->getsizex()-1; y2=pimage->getsizey()-1;
+	tempx = new PXFloatImage(pimage,kernelx);
+	tempy = new PXFloatImage(pimage,kernely);
+      }
+  else
+      {
+	for (int kk=0;kk<getnumpoints();kk++)
+	    {
+	      x=(int)getcontrolx(kk);
+	      y=(int)getcontroly(kk);
+	      if (x<x1) x1=x;
+	      if (x>x2) x2=x;
+	      if (y<y1) y1=y;
+	      if (y>y2) y2=y;
+	    }
+	
+	x1=x1-15; x2=x2+15; y1=y1-15; y2=y2+15;
+	if (x1<1) x1=1; 
+	if (y1<1) y1=1;
+	if (x2>=pimage->getsizex()-1) x2=pimage->getsizex()-1;
+	if (y2>=pimage->getsizey()-1) y2=pimage->getsizey()-1;
+	tempx = new PXFloatImage(pimage,kernelx,x1,x2,y1,y2);
+	tempy = new PXFloatImage(pimage,kernely,x1,x2,y1,y2);
+      }
+  sn_energymap = new PXFloatImage(pimage->getsizex(),pimage->getsizey());
+  for (int k=0;k<sn_energymap->getsizex();k++)
+      for(int j=0;j<sn_energymap->getsizey();j++)
+	{
+	  if (k==0 || k==sn_energymap->getsizex()-1 || j==0 || j==sn_energymap->getsizey()-1)
+	    sn_energymap->setpixel(k,j,255.0);
+	  else
+	    sn_energymap->setpixel(k,j,0.0);
+	}
+  
+  for (int i=x1;i<x2;i++)
+    for (int j=y1;j<y2;j++)
+      {
+	float magx=tempx->getpixel(i,j);
+	float magy=tempy->getpixel(i,j);
+	mag=sqrt(magx*magx+magy*magy);
+	sn_energymap->setpixel(i,j,mag);
+	if (max<mag) max=mag;
+      }
+  delete tempx;
+  delete tempy;
+   
+  sn_gradx = new PXFloatImage(sn_energymap,kernelx,x1,x2,y1,y2);
+  sn_grady = new PXFloatImage(sn_energymap,kernely,x1,x2,y1,y2);
+
+  delete kernelx;
+  delete kernely;
+  ownsgradients=1;
+  return max;
+
+}
+// --------------------------------------------------------------
+
+int  PXFPBSpline::checkbounds(int j,int x0,int x1,int y0,int y1,int tol)
+{
+  j=indexbound(j,int(numpoints));
+  if (getcontrolx(j)<real(x0+tol)) 
+      return 0;
+
+  if (getcontrolx(j)>real(x1-tol)) 
+      return 0;
+			  
+  if (getcontroly(j)<real(y0+tol))
+      return 0;
+
+  if (getcontroly(j)>real(y1-tol)) 
+      return 0;
+
+  return 1;
+}
+// --------------------------------------------------------------
+
+real PXFPBSpline::splineinternalenergy(int k1,int k2)
+{
+  static int firsttime=0;
+
+
+  if (firsttime==0)
+      {
+	//fprintf(stderr,"Using proper internal energy\n");
+	firsttime=1;
+      }
+  real energy = 0.0;
+    
+  if (k1<0) k1=0;
+  if (k2<0) k2=int(getnumpoints()-1);
+
+  if (k1<k2)   {	int k3=k2; k2=k1; k1=k3;      }
+
+  real t0=getknot(k1+int(degree)-1);
+  real t1=getknot(k2+int(degree)+1);
+  real dt=(t1-t0)/50.0;
+
+  for (real s=t0+dt;s<t1-dt;s=s+2.0*dt)
+      {
+	real s1=s;
+	if (s1<0)
+	    s1=s1+1.0;
+	else if(s1>=1.0)
+	    s1=s1-1.0;
+	real x2,y2;
+	get2derivative(s1,x2,y2);
+	//	real ds=getlength(s1-dt,s1+dt,0.25*dt);
+	real kappa = sqrt(x2*x2 + y2*y2);
+	/*	if (debugmode)
+	    fprintf(stderr," At %f (%f,%f) (%f,%f) \n",s,x2,y2,ds,kappa);*/
+
+	energy = energy+kappa;
+      }
+  /*if (debugmode)
+      fprintf(stderr,"\n");*/
+
+  return(energy);
+}
+// --------------------------------------------------------------
+void PXFPBSpline::splinechangeinternalenergy(int j,float dr,real &sx,real& sy)
+{
+  // Control Distance 
+  // ----------------
+  /*  {
+    int jm=indexcyclic(j-1,numpoints);
+    int jp=indexcyclic(j-1,numpoints);
+    
+    real xm=getcontrolx(jm);
+    real xp=getcontrolx(jp);
+    real x =getcontroly(j);
+    real ym=getcontroly(jm);
+    real yp=getcontroly(jp);
+    real y =getcontroly(j);
+    
+    real ex1 = fabs(2.0*(x+dr)-xm-xp);
+    real ex2 = fabs(2.0*(x-dr)-xm-xp);
+    sx = (ex1-ex2)/(2.0*dr);
+    
+    real ey1 = fabs(2.0*(y+dr)-ym-yp);
+    real ey2 = fabs(2.0*(y-dr)-ym-yp);
+    sy = (ey1-ey2)/(2.0*dr);
+  } */
+  //Curvature Regularization 
+  shiftClosedControl(j,dr,0.0);
+  real ex1 = splineinternalenergy(j,j);
+  shiftClosedControl(j,-2.0*dr,0.0);
+  real ex2 = splineinternalenergy(j,j);
+  shiftClosedControl(j,dr,0.0);
+  sx += (ex1-ex2)/(2.0*dr);
+  
+  // y-direction
+  shiftClosedControl(j,0.0,dr);
+  real ey1 = splineinternalenergy(j,j);
+  shiftClosedControl(j,0.0,-2.0*dr);
+  real ey2 = splineinternalenergy(j,j);
+  shiftClosedControl(j,0.0,dr);
+  sy += (ey1-ey2)/(2.0*dr);
+
+}
+// --------------------------------------------------------------
+void PXFPBSpline::controlexternalforce(real& fx,real& fy,int k)
+{
+  fx = 0.0;
+  fy = 0.0;
+  
+  real t0=getknot(k+int(degree)-1);
+  real t1=getknot(k+int(degree)+2);
+  real dt=(t1-t0)/10.0;
+  for (real s=t0+dt;s<t1-dt;s=s+2.0*dt)
+    {
+      real x,y;
+      real s1=s;
+      if (s1<0)
+	s1=s1+1.0;
+      else if(s1>=1.0)
+	s1=s1-1.0;
+      
+      getposition(s1,x,y);
+      real ds=getlength(s1-dt,s1+dt,0.5*dt);
+      real wgt=evalweight(s1,k);
+      
+      fx+=sn_gradx->getinterp(x-float(sn_offsetx),y-float(sn_offsety))*ds*wgt/sn_maxgrad;
+      fy+=sn_grady->getinterp(x-float(sn_offsetx),y-float(sn_offsety))*ds*wgt/sn_maxgrad;
+    }
+}
+// --------------------------------------------------------------------------
+void PXFPBSpline::controlbaloonforce(real& fx,real& fy,int k)
+{
+  fx = 0.0;
+  fy = 0.0;
+  
+  real t0=getknot(k+int(degree)-1);
+  real t1=getknot(k+int(degree)+2);
+  real dt=(t1-t0)/10.0;
+  for (real s=t0+dt;s<t1-dt;s=s+2.0*dt)
+    {
+      real x,y;
+      real s1=s;
+      if (s1<0)
+	s1=s1+1.0;
+      else if(s1>=1.0)
+	s1=s1-1.0;
+      
+      getderivative(s1,x,y);
+      real ds=getlength(s1-dt,s1+dt,0.5*dt);
+      real wgt=evalweight(s1,k);
+      
+      fx+=y*ds*wgt/sn_maxgrad;
+      fy+=(-x)*ds*wgt/sn_maxgrad;
+    }
+}
+// --------------------------------------------------------------------------
+int PXFPBSpline::genmatrices(int msize)
+{
+  if (hasmatrices)
+      free_dmatrix(invMatrix,1,matsize,1,matsize);
+
+  if (msize<0)
+      matsize=int(numpoints);
+  else
+      matsize=msize;
+
+  invMatrix=dmatrix(1,matsize,1,matsize);
+  hasmatrices=1;
+
+  if (debugmode>1)
+      fprintf(stderr, "Generating Matrix : %d*%d\n", matsize,matsize);
+
+  for (int ia=1;ia<=matsize;ia++)
+      for (int ib=1;ib<=matsize;ib++)
+	{
+	  invMatrix[ia][ib]=float(ia==ib);
+	}
+  
+  real h[10];
+  float* a=vector(1,matsize);
+  float* b=vector(1,matsize);
+  float* c=vector(1,matsize);
+  
+  if (isclosed())
+      {
+	for (int i=0;i<matsize;i++)
+	  {
+	    real arg=getcknot(i);
+	    //int row=indexcyclic(i+1,matsize,1);
+	    integer l=evalbspl(arg,h);
+	    a[i+1]=evalweight(h,l,i-1);	
+	    b[i+1]=evalweight(h,l,i);	
+	    c[i+1]=evalweight(h,l,i+1);	
+	  }
+      }
+  else
+    {
+      a[1]=0.0;       b[1]=1.0;        c[1]=0.0;
+      a[matsize]=0.0; b[matsize]=1.0;  c[matsize]=0.0;
+      for (int i=2;i<matsize;i++)
+	{
+	  real arg=getcknot(i);
+	  integer l=evalbspl(arg,h);
+	  a[i+1]=evalweight(h,l,i-1);	
+	  b[i+1]=evalweight(h,l,i);	
+	  c[i+1]=evalweight(h,l,i+1);	
+	}
+    }
+  
+  // Next shift a ....
+  float aold=a[1];
+  for (int i=1;i<matsize;i++)
+    a[i]=a[i+1];
+  a[matsize]=aold;
+
+  // get the inverse column by column 
+  float* r=vector(1,matsize);
+  float* x=vector(1,matsize);
+  
+  for(int col=1;col<=matsize;col++)
+      {
+	for(int i=1;i<=matsize;i++) 
+	    r[i]=0.0;
+	r[col] = 1.0;
+	
+	// call the cylic tridiagonal routine 
+	//	cyclictridiag(a,b,c,alpha,beta,r,x,matsize);
+	solve_cyc_tridiag_nonsym_gsl(b,c,a,r,x,matsize);
+	
+	// store in back into the inverse matrix 
+	for(int j=1;j<=matsize;j++)
+	    invMatrix[j][col]=x[j];
+      }
+
+  if (debugmode>1)
+    {
+      int np=matsize;
+      printdmatrix(invMatrix,np,np,"%6.3f ","Inv",12);
+    }
+
+
+  free_vector(x,1,matsize);
+  free_vector(r,1,matsize);
+  free_vector(c,1,matsize);
+  free_vector(b,1,matsize);
+  free_vector(a,1,matsize);
+      
+  return 1;
+}
+// --------------------------------------------------------------------------
+integer PXFPBSpline::evalbspl(real x,real* h,integer l)
+{
+  real arg=x;
+  if (l<0)
+      {
+	l=0;
+	while (!(getknot(int(l))<=arg && getknot(int(l)+1)>arg))
+	    l++;
+	l=l+1;
+      }
+  fpbspl_(knots,&numknots,&degree,&x,&l,h);
+  return l;
+}
+// --------------------------------------------------------------------------
+real PXFPBSpline::evalweight(real* h,integer l, integer index)
+{
+  integer shift=5;
+  if (degree==1)
+      shift=2;
+
+  int m=int(index-l+shift);
+  if (m>=0 && m<=4)
+      return h[m];
+  else	
+      if (isclosed())
+	  {
+	    if (m>0)
+		index=index-getnumpoints();
+	    else
+		index=index+getnumpoints();
+	    
+	    m=int(index-l+shift);
+	    if (m>=0 && m<=4)
+		return h[m];
+	  }
+  return 0.0;
+}
+// --------------------------------------------------------------------------
+real PXFPBSpline::evalweight(real s, integer index)
+{
+  real h[5];
+  integer l=evalbspl(s,h);
+  return evalweight(h,l,index);
+}
+// --------------------------------------------------------------------------
+real PXFPBSpline::findnearestknot(int& index,real& mindist,
+				  real xn,real yn,real zn)
+{
+  mindist=10000000.0;
+  index=0;
+  for (int i=0;i<getnumpoints();i++)
+      {
+	float s=getcknot(i);
+	real x,y,z;
+	getposition(s,x,y,z);
+	real dist=(pow(x-xn,float(2.0))+pow(y-yn,float(2.0)));
+	if (dimension==3)
+	  {
+	    dist+=pow(z-zn,float(2.0));
+	  }
+	if (dist<mindist)
+	  {
+	    mindist=dist;
+	    index=i;
+	  }
+      }
+  mindist=sqrt(mindist);
+  return getcknot(index);
+}
+// --------------------------------------------------------------------------
+int PXFPBSpline::insertknot(real xn,real yn,real& mindist)
+{
+  if (mindist<0.01)
+    mindist=0.01;
+
+  real testdist=0.0;
+  if (debugmode)
+    fprintf(stderr,"Input mindist=%f (%f,%f)\n",mindist,xn,yn);
+  real s=findnearestneighbour(xn,yn,mindist,0);
+
+  int proceed=1;
+  if (mindist<testdist)
+    proceed=0;
+
+  if (debugmode)
+    fprintf(stderr,"Nearest Neighbor to %f,%f=%f (testdist=%f,mindist=%f) Proceed=%d\n",xn,yn,s,testdist,mindist,proceed);
+
+  if (proceed==0)
+    return 0;
+
+  int knot_index=0;
+  int flag=0;
+
+  while (knot_index<numknots && flag==0)
+    {
+      if ( (knots[knot_index]<= s) && ( knots[knot_index+1] >s ))
+	{
+	  s=0.5*(knots[knot_index]+knots[knot_index+1]);
+	  flag=1;
+	}
+      else
+	++knot_index;
+    }
+
+
+  this->setclosed(1);
+  PXFPBSpline* new_spl=new PXFPBSpline();
+  new_spl->setclosed(1);
+  new_spl->setellipse(numpoints+1,10.0,10.0,0.0,0.0,2);
+
+  real* xp=new real[numpoints+1];
+  real* yp=new real[numpoints+1];
+  float z=zlevel;
+
+  int k=0;
+  real x0,y0;
+  for (int i=degree;i<numpoints+degree;i++)
+    {
+      getposition(knots[i],x0,y0);
+      xp[k]=x0;
+      yp[k]=y0;
+      new_spl->setknot(k+degree,knots[i]);
+      ++k;
+
+      if (i==knot_index)
+	{
+	  getposition(s,x0,y0);
+	  xp[k]=x0;
+	  yp[k]=y0;
+	  new_spl->setknot(k+degree,s);
+	  ++k;
+	}
+    }
+
+  for (int ia=0;ia<degree;ia++)
+    {
+      new_spl->setknot(ia,new_spl->getknot(ia+numpoints+1)-1.0);
+      new_spl->setknot(ia+numpoints+degree+1,new_spl->getknot(ia+degree)+1.0);
+    }
+  new_spl->ResetPoints(this->numpoints+1,xp,yp);
+  this->copypoints(new_spl);
+  this->zlevel=z;
+  delete [] xp;
+  delete [] yp;
+  delete new_spl;
+
+
+  return 1;
+}
+// --------------------------------------------------------------------------
+
+void PXFPBSpline::getcentroid(real& x,real&y, real& z,float ds)
+{
+  float count=0.0;
+  if (numpoints<4)
+    return;
+
+  x=0.0;y=0.0;z=0.0;
+  real xt,yt,zt;
+  if (dimension==2)
+      {
+	for(float s=0.0;s<1.0;s+=ds)
+	  {
+	    count=count+1.0;
+	    getposition(s,xt,yt);
+	    x+=xt;
+	    y+=yt;
+	  }
+	x=x/count;
+	y=y/count;
+	z=zlevel;
+      }
+  else
+    {
+      for (float s=0.0;s<1.0;s+=ds)
+	{
+	  count=count+1.0;
+	  getposition(s,xt,yt,zt);
+	  x+=xt;
+	  y+=yt;
+	  z+=zt;
+	}
+    }
+}
+// --------------------------------------------------------------------------
+void PXFPBSpline::rigid2D(float tx,float ty,float xc,float yc,float angle,int reverse)
+{
+  if (dimension!=2)
+    return;
+  
+  if (fabs(angle)>0.2)
+    {
+	angle*=M_PI/180.0;
+	for(int i=0;i<getnumcontrolpoints();i++)
+	    {
+	      if (reverse==0)
+		  {
+		    // Eliminate center and translate 
+		    real x=getcontrolx(i)-xc+tx;
+		    real y=getcontroly(i)-yc+ty;
+		    // Rotate about center 
+		    real xn=x*cos(angle)-y*sin(angle);
+		    real yn=x*sin(angle)+y*cos(angle);
+		    // Add center 
+		    setcontrol(i,xn+xc,yn+yc);
+		  }
+	      else
+		  {
+		    real x=getcontrolx(i)-xc;
+		    real y=getcontroly(i)-yc;
+		    // Rotate about center 
+		    real xn=x*cos(angle)-y*sin(angle);
+		    real yn=x*sin(angle)+y*cos(angle);
+		    // Add center and then translation 
+		    setcontrol(i,xn+xc+tx,yn+yc+ty);
+		  }
+	    }
+      }
+  else
+      {
+	for(int i=0;i<getnumcontrolpoints();i++)
+	    shiftcontrol(i,tx,ty);
+      }
+  }
+// --------------------------------------------------------------------------
+void PXFPBSpline::rigid2D(float tx,float ty,float angle)
+{
+  if (dimension!=2)
+      return;
+
+  if (fabs(angle)>0.2)
+      {
+	angle=angle*M_PI/180.0;
+	real xc,yc,zc;
+	getcentroid(xc,yc,zc,0.02);
+	tx=tx+xc;
+	ty=ty+yc;
+	for(int i=0;i<getnumcontrolpoints();i++)
+	    {
+	      real x=getcontrolx(i)-xc;
+	      real y=getcontroly(i)-yc;
+	      setcontrol(i,x*cos(angle)-y*sin(angle)+tx,
+			 x*sin(angle)+y*cos(angle)+ty);
+	    }
+      }
+  else
+      for(int i=0;i<getnumcontrolpoints();i++)
+	  shiftcontrol(i,tx,ty);
+  
+}
+
+// --------------------------------------------------------------------------
+void PXFPBSpline::scaleshift2D(float tx,float ty,float sx,float sy)
+{
+  if (fabs(sx)<0.01)
+      sx=1.0;
+  if (fabs(sy)<0.01)
+      sy=1.0;
+      
+  if (sx==1.0 && sy==1.0 && tx==0.0 && ty==0.0)
+    return;
+
+  for(int i=0;i<getnumcontrolpoints();i++)
+    {
+      real x=getcontrolx(i)*sx+tx;
+      real y=getcontroly(i)*sy+ty;
+      setcontrol(i,x,y);
+    }
+}
+
+// --------------------------------------------------------------------------
+int PXFPBSpline::ensureAnticlockwise()
+{
+  int flag=0;
+  if (dimension==2)
+      {
+	real x0,x1,x2,y0,y1,y2;
+	getposition(0.0,x0,y0);
+	getposition(0.33,x1,y1);
+	getposition(0.66,x2,y2);
+	real v1x=x1-x0;
+	real v1y=y1-y0;
+	real v2x=x2-x1;
+	real v2y=y2-y1;
+	real zz=(v1x*v2y-v2x*v1y);
+	
+	if (zz<0.0) 
+	    {
+	      real* oldknots=new real[numknots];
+	      real* oldcontrol=new real[numknots*dimension];
+	      
+	      int i;
+	      for (i=0;i<numknots;i++)
+		  oldknots[i]=knots[i];
+	      for (i=0;i<numknots*dimension;i++)
+		  oldcontrol[i]=controlpoints[i];
+
+	      int numk=int(getnumknots()-1);
+	      int numc=int(getnumcontrolpoints()-1);
+	      for (i=0;i<=numk;i++)
+		  setknot(i,1.0-oldknots[numk-i]);
+	      for (i=0;i<=numc;i++)
+		  {
+		    int k=numc-i;
+		    for(int j=0;j<dimension;j++)
+			{
+			  controlpoints[i+j*numknots]=oldcontrol[k+j*numknots];
+			}
+		  }
+	      delete [] oldknots;
+	      delete [] oldcontrol;
+	      flag=1;
+	    }
+      }
+  return flag;
+}
+// --------------------------------------------------------------------------
+real PXFPBSpline::findIntersectY(real y,real minx,real maxx,
+				 real ds,real tol,int maxatt)
+{
+  int found=0;
+  real xintersect=-1111.0;
+  float s0=0.0;
+  while(s0<=(1.0-ds) && found==0)
+      {
+	real x1,y1,x2,y2;
+	getposition(s0,x1,y1);
+	getposition(s0+ds,x2,y2);
+	if ((y-y1)*(y-y2)<=0.0)
+	    {     
+	      real xp,yp;
+	      int att=0;
+	      float stest=0.0;
+	      real smin=s0;
+	      real smax=s0+ds;
+	      do
+		  {
+		    att++;
+		    stest=(smin+smax)*0.5;
+		    getposition(stest,xp,yp);
+		    if ((y-y1)*(y-yp)<=0.0)
+			smax=stest;
+		    else
+			smin=stest;
+		    getposition(stest,xp,yp);
+		  }
+	      while (att<maxatt && fabs(yp-y)>tol);
+			  
+	      getposition(stest,xp,yp);
+	      if (xp>=minx && xp<=maxx)
+		  {
+		    found=1;
+		    xintersect=xp;
+		  }
+	    }
+	s0+=ds;
+      }
+  return xintersect;
+}
+// --------------------------------------------------------------------------
+int PXFPBSpline::findIntersectX(real x,real& first,real& second,real ds,real tol,int maxatt)
+{
+  real slevels[20];
+  for (int pass=0;pass<=20;pass++)
+      slevels[pass]=-1111.0;
+
+  int found=0;
+  float s0=0.0;
+  while(s0<=(1.0-ds))
+      {
+	real x1,y1,x2,y2;
+	getposition(s0,x1,y1);
+	getposition(s0+ds,x2,y2);
+	if ((x-x1)*(x-x2)<=0.0)
+	    {     
+	      real xp,yp;
+	      int att=0;
+	      float stest=0.0;
+	      real smin=s0;
+	      real smax=s0+ds;
+	      do
+		  {
+		    att++;
+		    stest=(smin+smax)*0.5;
+		    getposition(stest,xp,yp);
+		    if ((x-x1)*(x-xp)<=0.0)
+			smax=stest;
+		    else
+			smin=stest;
+		    getposition(stest,xp,yp);
+		  }
+	      while (att<maxatt && fabs(xp-x)>tol);
+	      
+	      getposition(stest,xp,yp);
+	      found++;
+	      slevels[found]=stest;
+	    }
+	s0+=ds;
+      }
+  if (found==0)
+      {
+	first=0.0;
+	second=0.5;
+      }
+  else if (found==1)
+      {
+	first=slevels[0];
+	second=slevels[0]+0.5;
+	if (second>1.0)
+	    second-=1.0;
+      }
+  else if (found==2)
+      {
+	first=slevels[0];
+	second=slevels[1];
+      }
+  else
+      {
+	first=slevels[0];
+	second=slevels[found/2];
+      }
+  return found;
+}
+// --------------------------------------------------------------------------
+real PXFPBSpline::findnearestneighbour(real& xn,real& yn,real& mindist,int dbg)
+{
+  float bests=0.0;
+  real x,y;   getposition(0.0,x,y);
+  real bestdist=(pow(x-xn,float(2.0))+pow(y-yn,float(2.0)));
+
+
+  for (real s=0;s<1.0;s=s+0.02)
+    {
+      real x,y;    
+      getposition(s,x,y);
+      real dist=(pow(x-xn,float(2.0))+pow(y-yn,float(2.0)));
+      if (dist<bestdist)
+	{
+	  bestdist=dist;
+	  bests=s;
+	}
+    }
+  
+  mindist=sqrt(bestdist);
+  getposition(bests,xn,yn);
+  return bests;
+}
+// ------------------------------------------------------------------
+void PXFPBSpline::ResetPoints(int np,real* xp,real* yp)
+{
+  if (dimension!=2)
+      return;
+
+  if (np!=numpoints || !isclosed())
+    {
+      setclosed(1);
+      setellipse(np,10.0,10.0,0.0,0.0,2);
+    }
+
+  if (!hasmatrices)
+    genmatrices(np);
+  
+  for (int ia=0;ia<np;ia++)
+    {
+      real xc=0.0,yc=0.0;
+      for (int ib=0;ib<np;ib++)
+	{
+	  xc=xc+invMatrix[ia+1][ib+1]*xp[ib];
+	  yc=yc+invMatrix[ia+1][ib+1]*yp[ib];
+	}
+      setClosedControl(ia,xc,yc);
+    }
+}
+// ------------------------------------------------------------------
+void PXFPBSpline::ResetPoints(int np,real* xp,real* yp,real* zp)
+{
+  if (dimension!=3)
+      return;
+
+  if (np!=numpoints || !isclosed())
+      {
+	setclosed(1);
+	setellipse(np,10.0,10.0,0.0,0.0,3);
+      }
+  
+  if (!hasmatrices)
+    genmatrices(np);
+  
+  for (int ia=0;ia<np;ia++)
+    {
+      real xc=0.0,yc=0.0,zc=0.0;
+      for (int ib=0;ib<np;ib++)
+	{
+	  xc=xc+invMatrix[ia+1][ib+1]*xp[ib];
+	  yc=yc+invMatrix[ia+1][ib+1]*yp[ib];
+	  zc=zc+invMatrix[ia+1][ib+1]*zp[ib];
+	}
+      setClosedControl(ia,xc,yc,zc);
+    }
+}
+// ------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/numerics/pxfpbspline.h b/bioimagesuite30_src/numerics/pxfpbspline.h
new file mode 100644
index 0000000..a36a066
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxfpbspline.h
@@ -0,0 +1,334 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pxfpbspline.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXFPBSpline
+
+_Description : A class which stores control points
+               for a controlled continuity spline of variable degrees
+	       essentially a C++ Wrapper around routines in FITPACK
+               FITPACK Routines used
+	          1. clocur  -- fitting of closed curves
+		  2. parcur  -- fitting of open curves
+		  3. curev   -- evaluation of curve position
+		  4. cualde  -- evaluation of curve derivatives
+
+_Call : 
+  PXFPBSpline();
+  PXFPBSpline(PXFPBSpline *old);
+
+_References : 
+  Paul Dierckx "Curve and Surface Fitting with Splines" Oxford Science Publications
+  De Boor      "A Practical Guide to Splines"
+  Gerald Farin "Curves and Surfaces for Computer Aided Design", Academic Press
+  
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 8th December 1997
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXFPBSpline
+#define _PXFPBSpline
+class PXFloatImage;
+class PXContour;
+
+
+#include "pximage.h"
+#include "bio_f2c.h"
+
+class PX2DRegion;
+
+class PXFPBSpline {
+
+protected:
+
+  // Spline Parameters 
+  // -----------------
+  integer  degree,numpoints,numknots,numcontrolpoints,dimension;
+  real     *controlpoints,*knots;
+  real     *controlx,*controly,*controlz;
+  double** invMatrix;
+  int      hasvectors,closedcurve,hasmatrices,matsize,hassnake;
+  int      oldnumpoints;
+  real     zlevel;
+
+  // Snake Parameters
+  // ----------------
+
+  real         sn_imweight,sn_smweight,sn_usrtstep,sn_sigma,sn_maxgrad,sn_baloon;
+  int          sn_numiter,sn_offsetx,sn_offsety,ownsenergymap,ownsgradients;
+  PXFloatImage *sn_gradx,*sn_grady,*sn_energymap;
+
+  // Debug Parameters
+  // ----------------
+  public :
+  static   int      debugmode;
+  static   real     lastfiterror;
+
+  // ******************************************************************************
+  //          PUBLIC INTERFACE
+  // ******************************************************************************
+
+  public :
+
+  PXFPBSpline(int deg=3,int dimnsion=2,real zlevel=0.0,int closed=1);
+  PXFPBSpline(PXFPBSpline *old);
+  virtual ~PXFPBSpline();
+
+  //  [A] Set and Delete Individual Control Points 
+  // ---------------------------------------------
+  virtual int     isclosed()            { return closedcurve; }
+  virtual integer getdegree()           { return degree;}
+  virtual integer getdimension()        { return dimension;}
+  virtual integer getnumpoints()        { return numpoints;}
+  virtual integer getnumknots()         { return numknots;}
+  virtual integer getnumcontrolpoints() { return numcontrolpoints;}
+  virtual int     splinehassnake()      { return hassnake;}
+  virtual float*  getknotsarray()       { return (float*)knots;}
+
+  virtual real getcontrolx(int i);
+  virtual real getcontroly(int i);
+  virtual real getcontrolz(int i);
+  virtual real getrawcontrol(int i);
+  virtual void setcontrol(int i,real x,real y,real z=0.0);
+  virtual void shiftcontrol(int i,real dx,real dy,real dz=0.0);
+
+  virtual void getcentroid(real& x,real&y, real& z,float ds=0.1);
+  virtual real getknot(int i);
+  virtual real getcknot(int i);
+  virtual void setknot(int i,real t);
+  
+  virtual real getzlevel();
+  virtual void setzlevel(real z);
+
+  // [B] Manipulate Whole Spline
+  // ---------------------------
+  virtual void setcircle(int np,real radius=5.0,real x=50.0,real y=50.0,int dim=2);
+  virtual void setellipse(int np,real radiusx=10.0,real radiusy=5.0,
+			  real x=50.0,real y=50.0,int dim=2);
+
+  virtual void rigid2D(float tx,float ty,float angle=0.0);
+  virtual void rigid2D(float tx,float ty,float cx,float cy,float angle,int reverse=0);
+  virtual void scaleshift2D(float tx,float ty,float sx,float sy);
+ 
+  virtual int sample(int sm=2,float step=0.005);
+  virtual int subsample(int sm=2,float step=0.005);
+  virtual int resample(float ds_step=0.005,int npoints=-1);
+  virtual int changespacing(real smth=0.5,int npoints=-1,float step=0.005,float csmooth=0.0,
+			    int iterations=50);
+
+  // [C] Add/Remove Points
+  // ---------------------
+  virtual real findnearestneighbour(real& x,real& y,real& mindist,int dbg=0);
+  virtual real findnearestknot(int& index,real& dist,real x,real y,real z=0.0);
+  virtual int  insertknot(real x,real y,real& mindist);
+  
+  // [D] Interface to PXContour and other Splines
+  // --------------------------------------------
+  virtual void copypoints(PXFPBSpline* other);
+  virtual PXContour* storeincontour(int nodepoints=0);
+  virtual PXContour* exporttoNcontour(int numpoints=10,int resample=1);
+  virtual PXContour* exporttocontour(real dist=1.0);
+
+  virtual void getknotpoints(real* xp,real* yp,int np);
+  virtual void getknotpoints(real* xp,real* yp,real* zp,int np);
+
+  // [E] Curve Fitting
+  // -----------------
+  virtual int  fittocontour(PXContour* cntr,real smooth=2.0,real csmooth=0.0,
+			    int numpoints=-1,int closed=1,int iterations=100);
+  virtual int  fitcontour(PXContour* cntr,real smooth=2.0,real csmooth=0.0,
+			  int deg=-1,int cl=1,int uniform=0,int numpoints=10,int iterations=100);
+
+  virtual void ResetPoints(int np,real* xpt,real* ypt);
+  virtual void ResetPoints(int np,real* xpt,real* ypt,real *zpt);
+
+
+  // [F] Location Evaluation
+  // ------------------------------
+  virtual real evalweight(real x, integer index);
+
+  virtual void getposition(real s,real& x,real& y,real& z);
+  virtual void getallderivatives(integer n,real  s,real* xd,real* yd,real* zd);
+  virtual real getcurvature(real s);
+ 
+  virtual void getposition(real    s,real& x,real& y);
+  virtual void getderivative(real  s,real& x,real& y);
+  virtual void getderivative(real  s,real& x,real& y,real &z);
+  virtual void get2derivative(real s,real& x,real& y);
+  virtual void get2derivative(real s,real& x,real& y,real& z);
+  virtual real getlength(real s0,real s1,real ds_step=0.005);
+
+
+  // [G] I/O Functions
+  // -----------------------------
+  virtual int Save(const char* filename);
+  virtual int Save(FILE* fout);
+  virtual int Load(const char* filename);
+  virtual int Load(gzFile fin);
+  virtual int SaveContour(const char* filename,real dist=1.4);
+
+  // [H] Snake Related Functions
+  // ---------------------------
+  virtual void createsnake(PXFloatImage* potential,float img_coeff=5.0,
+			   float smooth_coeff=0.5,
+			   float timestep=0.05,float sigma=1.0,int niter=3,float baloon_coeff=0.0);
+
+  virtual void createsnake(PXImage* pimage,float img_coeff=5.0,
+			   float smooth_coeff=0.5,
+			   float timestep=0.05,float sigma=1.0,int niter=3,float baloon_coeff=0.0);
+  virtual void createsnake(PX2DRegion* region,
+			   float img_coeff=5.0,
+			   float smooth_coeff=0.5,
+			   float timestep=0.05,float sigma=1.0,int niter=3,float balooon_coeff=0.0);
+
+  virtual void createsnake(PXImage* pimage,PX2DRegion* region,
+			   float img_coeff=5.0,float region_weight=2.0,
+			   float smooth_coeff=0.5,
+			   float timestep=0.05,float sigma=1.0,int niter=3,float baloon_coeff=0.0);
+
+  virtual void createsnake(PXImage* pimage,PXFloatImage* external,
+			   float img_coeff=5.0,
+			   float ext_coeff=5.0,
+			   float smooth_coeff=0.5,
+			   float timestep=0.05,float sigma=1.0,int niter=3,float baloon_coeff=0.0);
+
+  virtual void createsnake(PX2DRegion* region,PXFloatImage* external,
+			   float img_coeff=5.0,
+			   float ext_coeff=5.0,
+			   float smooth_coeff=0.5,
+			   float timestep=0.05,float sigma=1.0,int niter=3,float baloon_coeff=0.0);
+
+  virtual void createsnake(PXImage* pimage,PX2DRegion* region,PXFloatImage* external,
+			   float img_coeff=5.0,float region_weight=2.0,
+			   float ext_coeff=5.0,
+			   float smooth_coeff=0.5,
+			   float timestep=0.05,float sigma=1.0,int niter=3,float baloon_coeff=0.0);
+
+
+  virtual void removesnake(); 
+  virtual real calcpotential(PXImage* pimage,int fullimage=0);
+  virtual real calc3potential(PXImage* pimage,PX2DRegion *region,PXFloatImage* ext,
+			      float w_im,float w_wr,float w_e,
+			      int fullimage=0);
+  virtual real generategradients();
+
+  virtual PXFloatImage*  getenergymap();
+  virtual unsigned char* getenergytexturemap(float gamma=1.0,int numbytes=1);
+  virtual real updatesnake(real tolerance=0.05);
+  
+  // [I] Ensure Anticlockwise
+  // ------------------------
+  virtual int ensureAnticlockwise();
+
+  // [J] Find Intersection with plane 
+  // --------------------------------
+  virtual real findIntersectY(real y,real minx=-100000.0,real maxx=100000.0,
+			      real ds=0.005,real tol=0.02,int maxatt=20);
+  virtual int  findIntersectX(real x,real& s1,real& s2,
+			      real ds=0.005,real tol=0.02,int maxatt=20);
+
+
+  // Move dual controlpoints
+  // -----------------------
+  virtual void setClosedControl(int i,real x,real y,real z=0.0,int off=1);
+  virtual void shiftClosedControl(int i,real dx,real dy,real dz=0.0,int off=1);
+  
+ protected:
+  virtual void ResetUniformKnots();
+
+  // Recuurence Relationship
+  // -----------------------
+  virtual integer evalbspl(real x,real* h,integer l=-1);
+  virtual real    evalweight(real* h,integer l, integer index);
+
+  
+
+  // Snake Part II
+  // -------------
+  virtual void  controlexternalforce(real& fx,real& fy,int k);
+  virtual void  controlbaloonforce(real& fx,real& fy,int k);
+  virtual int   checkbounds(int j,int x0,int x1,int y0,int y1,int tol=5);
+  virtual real  splineinternalenergy(int k1,int k2);
+  virtual void  splinechangeinternalenergy(int j,float ds,real &sx,real& sy);
+
+  // Other Stuff
+  // -----------
+  virtual void  generatecontrolvectors();
+  virtual int   genmatrices(int msize=-1);
+
+  virtual int   fitpoints(integer M,integer MX,real* X,float smth);
+  virtual int   fitpoints(integer M,real* W,real* U,integer MX,real* X,
+			  integer IOPT,integer IPAR,float smth,int numpoints=10);
+  
+  virtual int   indexbound(int t,int np=-1,int off=0);
+  virtual int   indexcyclic(int t,int np=-1,int off=0);
+  virtual real  arclengthcyclic(real t);
+
+
+  virtual void setdegree(integer deg=3);
+  virtual void setclosed(int c);
+
+
+public:
+  // Debugging Functions
+  // -------------------
+  static int   getdebugmode() { return debugmode;}
+  static void  setdebugmode(int d) { debugmode=(d>0);}
+  static float getlastfiterror()   { return lastfiterror; }
+
+
+  
+};
+
+
+
+
+
+#endif   
+
diff --git a/bioimagesuite30_src/numerics/pxfpbsplinestack.cpp b/bioimagesuite30_src/numerics/pxfpbsplinestack.cpp
new file mode 100644
index 0000000..ac47fa8
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxfpbsplinestack.cpp
@@ -0,0 +1,1426 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+#include "pxfpbsplinestack.h"
+#include "pxcontourstack.h"
+#include "pxchamferdistancemap.h"
+
+// --------------------------------------------------------------------------
+int  PXFPBSplineStack::debugmode=0;
+
+// --------------------------------------------------------------------------
+PXFPBSplineStack::PXFPBSplineStack(PXFPBSplineStack *old)
+{
+  numsplines =old->getnumsplines();
+  trim_bottom=old->gettrimbottom();
+  trim_top   =old->gettrimtop();
+  hasapex    =old->apexenabled();
+	
+  for (int i=0;i<old->getnumsplines();i++)
+      spline[i]=new PXFPBSpline(old->getspline(i));
+
+  PX3Vector* v=old->getapex();
+  for (int ia=0;ia<=2;ia++)
+      apex.x[ia]=v->x[ia];
+
+
+
+}
+// --------------------------------------------------------------------------
+PXFPBSplineStack::PXFPBSplineStack(PXFPBSplineStack *old,int zbetween,
+				   int mode,int resample_original)
+{
+  PX3Vector* v=old->getapex();
+  for (int ia=0;ia<=2;ia++)
+      apex.x[ia]=v->x[ia];
+
+  hasapex=old->apexenabled();
+
+  zbetween=Irange(zbetween,0,10); 
+  PXContourStack* cstack=old->exporttocontourstack(0.5);
+  if (debugmode)
+      fprintf(stderr,"Created: Normal stack:: First export step ok mode=%d\n",mode);
+  
+  PXContourStack* cstack2=new PXContourStack(cstack,zbetween,mode);
+  if (debugmode)
+      {
+	fprintf(stderr,"Created interpolated cstack (slices %d-->%d) (between=%d,zmode=%d)\n",
+		cstack->getnumcontours(),cstack2->getnumcontours(),zbetween,mode);
+      }
+  numsplines=0;
+  trim_bottom=0;
+  trim_top=0;
+
+  if (debugmode)
+    fprintf(stderr,"On to Fitting to ContourStack\n");
+  if (fittocontourstack(cstack2,0.05,0.5,-1,1))
+      {
+	if (debugmode)
+	    fprintf(stderr,"Fitting OK ...\n");
+	// Copy original splines over interpolated ones 
+	for (int i=trim_bottom;i<=trim_top;i++)
+	    {
+	      float z1=spline[i]->getzlevel();
+	      int found=0,j=old->gettrimbottom()-1;
+	      while(j<=old->gettrimtop() && found==0)
+		  {
+		    j++;
+		    PXFPBSpline* oldspline=old->getspline(j);
+		    float z2=oldspline->getzlevel();
+		    if (z1==z2)
+			{
+			  spline[i]->copypoints(oldspline);
+			  if (resample_original)
+			      spline[i]->changespacing(0.5,-1,0.01);
+			  found=1;
+			}
+		  }
+	    }
+      }
+  else
+      {
+	if (debugmode)
+	    fprintf(stderr,"Fitting Failed, just copying old BSPlineStack\n");
+
+	numsplines=old->getnumsplines();
+	settrimbottom(old->gettrimbottom());
+	settrimtop(old->gettrimtop());
+	
+	for (int i=0;i<old->getnumsplines();i++)
+	    spline[i]=new PXFPBSpline(old->getspline(i));
+      }
+
+  delete cstack2;
+  delete cstack;
+
+  if (debugmode)
+      fprintf(stderr,"\t done\n");
+
+}
+// --------------------------------------------------------------------------
+
+PXFPBSplineStack::PXFPBSplineStack(int numberofsplines)
+{
+  hasapex=0;
+  for (int ia=0;ia<=2;ia++)
+      apex.x[ia]=0.0;
+  numsplines=numberofsplines;
+  numsplines=Irange(numsplines,2,PXFPBSPLINESTACK_MAXLEVELS-1);
+  trim_bottom=0;
+  trim_top=numsplines-1;
+
+  for (int i=0;i<numsplines;i++)
+      spline[i]=new PXFPBSpline();
+
+}
+// --------------------------------------------------------------------------
+PXFPBSplineStack::PXFPBSplineStack(PXFPBSplineStack *old1,PXFPBSplineStack* old2,float ratio,
+				   float smooth,int doapex)
+{
+  ratio=Frange(ratio,0.001,0.999);
+  numsplines=Imax(old1->getnumsplines(),old2->getnumsplines());
+  trim_bottom=Imax(old1->gettrimbottom(),old2->gettrimbottom());
+  trim_top=Imin(old1->gettrimtop(),old2->gettrimtop());
+
+  if (trim_bottom>trim_top)
+      {
+	numsplines=0;
+	trim_bottom=0;
+	trim_top=0;
+      }
+  else
+      {
+	numsplines=Irange(numsplines,2,PXFPBSPLINESTACK_MAXLEVELS-1);
+	int i;
+	for (i=0;i<numsplines;i++)
+	    spline[i]=new PXFPBSpline();
+	
+	if (doapex==0 || trim_bottom!=old1->gettrimbottom() || trim_bottom!=old2->gettrimbottom() ||
+	    !old1->apexenabled() || !old2->apexenabled())
+	    {
+	      hasapex=0;
+	      for (int ia=0;ia<=2;ia++)
+		  apex.x[ia]=0.0;
+	    }
+	else
+	    {
+	      hasapex=1;
+	      PX3Vector* v1=old1->getapex();
+	      PX3Vector* v2=old2->getapex();
+	      for (int ia=0;ia<=2;ia++)
+		  apex.x[ia]=(1.0-ratio)*v1->x[ia]+ratio*v2->x[ia];
+	    }
+	
+	
+	int wgt1=int(0.5+1000.0*(1-ratio));
+	int wgt2=int(0.5+1000.0*(ratio));
+
+	fprintf(stderr,"Numsplines=%d trim_bottom=%d trim_top=%d wgt1=%d wgt2=%d\n",
+		numsplines,trim_bottom,trim_top,wgt1,wgt2);
+
+	fprintf(stderr,"Generating Spline :");
+	for (i=trim_bottom;i<=trim_top;i++)
+	    {
+	      fprintf(stderr," %d",i);
+	      PXContour* c1=old1->getspline(i)->exporttocontour(0.5);
+	      PXContour* c2=old2->getspline(i)->exporttocontour(0.5);
+	      
+	      PXChamferDistanceMap* map=new PXChamferDistanceMap(c1,c2,wgt1,wgt2);
+	      PXContour* cntr=map->extractContour();
+	      spline[i]->fittocontour(cntr,smooth,0.0);
+	      spline[i]->setzlevel((1.0-ratio)*old1->getspline(i)->getzlevel()+
+				    ratio*old2->getspline(i)->getzlevel());
+	      spline[i]->ensureAnticlockwise();
+	      delete map;      
+	      delete cntr;	      
+	      delete c1;
+	      delete c2;
+	    }
+	fprintf(stderr,"\n");
+      }
+}
+// --------------------------------------------------------------------------
+PXFPBSplineStack::~PXFPBSplineStack()
+{
+  for (int i=0;i<numsplines;i++)
+      delete spline[i];
+}
+// --------------------------------------------------------------
+void PXFPBSplineStack::settrimbottom(int tb)
+{
+  if (tb>=0 && tb<=trim_top)
+      trim_bottom=tb;
+}
+
+void PXFPBSplineStack::settrimtop(int tt)
+{
+  if (tt>=trim_bottom && tt<numsplines)
+      trim_top=tt;
+}
+// --------------------------------------------------------------
+void PXFPBSplineStack::autosettrims(float zmin,float zmax)
+{
+  int oldsl=this->gettrimbottom();
+  int sl=oldsl;
+  while(sl<=this->gettrimtop()-1)
+    {
+      if (this->getspline(sl)->getzlevel()<zmin)
+	this->settrimbottom(sl+1);
+      sl++;
+    }
+  
+  if (zmin>=0.0)
+    this->enableapex(0);
+		    
+  sl=this->gettrimtop();
+  while(sl>=this->gettrimbottom()+1)
+    {
+      if ((this->getspline(sl))->getzlevel()>zmax)
+	this->settrimtop(sl-1);
+      sl=sl-1;
+    }
+}
+// --------------------------------------------------------------
+void PXFPBSplineStack::adjustnumberofsplines(int newnumber)
+{
+  if (debugmode)
+    fprintf(stderr,"Adjusting %d (%d:%d) ---> %d \n",numsplines,trim_bottom,trim_top,newnumber);
+
+  int oldnumsplines=numsplines;
+  numsplines=newnumber;
+  if (oldnumsplines!=numsplines)
+    {
+      if (oldnumsplines>numsplines)
+	{
+	  for (int i=numsplines;i<oldnumsplines;i++)
+	    delete spline[i];
+	}
+      else
+	{
+	  float z=0.0;
+	  if (oldnumsplines>0)
+	    z=spline[oldnumsplines-1]->getzlevel()-spline[oldnumsplines-2]->getzlevel();
+	  else
+	    z=1.0;
+
+	  for (int i=oldnumsplines;i<numsplines;i++)
+	    {
+	      spline[i]=new PXFPBSpline();
+	      if (debugmode)
+		fprintf(stderr,"Coping %d ---> %d \n",trim_top,i);
+	      spline[i]->copypoints(spline[trim_top]);
+	      if (i>0)
+		spline[i]->setzlevel(spline[i-1]->getzlevel()+z);
+	      else
+		spline[i]->setzlevel(0.0);
+	    }
+	}
+    }
+
+  if (trim_top>numsplines)
+    trim_top=numsplines-1;
+
+  if (debugmode)
+    fprintf(stderr,"Done\n");
+}
+// --------------------------------------------------------------
+// Copy control points from another surface
+// --------------------------------------------------------------
+void PXFPBSplineStack::copypoints(PXFPBSplineStack* other,int ignoretrim)
+{
+  PX3Vector* v=other->getapex();
+  for (int ia=0;ia<=2;ia++)
+      apex.x[ia]=v->x[ia];
+  hasapex=other->apexenabled();
+
+  if (ignoretrim==0)
+      {
+	adjustnumberofsplines(other->getnumsplines()); 
+	settrimbottom(other->gettrimbottom());
+	settrimtop(other->gettrimtop());
+	
+	for (int i=0;i<numsplines;i++)
+	    {
+	      PXFPBSpline *spl= other->getspline(i);
+	      spline[i]->copypoints(spl);
+	    }
+      }
+  else
+      {
+	adjustnumberofsplines(other->gettrimtop()-other->gettrimbottom()+1);
+	settrimbottom(0);
+	settrimtop(numsplines-1);
+	for (int i=0;i<numsplines;i++)
+	    {
+	      PXFPBSpline *spl= other->getspline(i+other->gettrimbottom());
+	      spline[i]->copypoints(spl);
+	    }
+      }
+}
+// ------------------------------------------------------------------
+//           Index Conversion
+// --------------------------------------------------------------------------
+int PXFPBSplineStack::indexbounded(int v,int np)
+{
+  if (np<0) 
+      np=numsplines;
+
+  if(v<0)       v=0;
+  if(v>=np)     v=np-1;
+
+  return v;
+}
+
+int PXFPBSplineStack::indexcyclic(int v,int np)
+{
+  while (v<0) v+=np;
+  while (v>=np) v-=np;
+  return v;
+}
+// --------------------------------------------------------------
+void PXFPBSplineStack::setspline(PXFPBSpline* spl,int index)
+{
+  index=indexbounded(index);  
+  if (index>=gettrimbottom() && index<=gettrimtop())
+      spline[index]->copypoints(spl);
+
+}
+// --------------------------------------------------------------------------
+int PXFPBSplineStack::sample(int sm,float step)
+{
+  int k=0;
+  for (int i=trim_bottom;i<=trim_top;i++)
+      k+=spline[i]->sample(sm,step);
+  
+  return k;
+}
+// --------------------------------------------------------------------------
+int PXFPBSplineStack::subsample(int samples,float step)
+{
+  int k=0;
+  for (int i=trim_bottom;i<=trim_top;i++)
+      k+=spline[i]->subsample(samples,step);
+  return k;
+}
+// --------------------------------------------------------------------------
+int PXFPBSplineStack::resample(float ds_step,int npoints)
+{
+  int k=0;
+  for (int i=trim_bottom;i<=trim_top;i++)
+      k+=spline[i]->resample(ds_step,npoints);
+  return k;
+}
+// --------------------------------------------------------------------------
+int PXFPBSplineStack::changespacing(real smth,int npoints,float step)
+{
+  int k=0;
+  for (int i=trim_bottom;i<=trim_top;i++)
+      k+=spline[i]->changespacing(smth,npoints,step);
+  return k;
+}
+// ------------------------------------------------------------------
+//           I/O Functions
+//
+//        Save & Load -->              Surface Format (Control Points)
+// ------------------------------------------------------------------
+int  PXFPBSplineStack::Save(const char* filename)
+{
+  int ret=0;
+  FILE* fout=fopen(filename,"w");
+  if (fout!=NULL)
+    {
+      ret=Save(fout);
+      fclose(fout);
+    }
+  if (debugmode)
+      fprintf(stderr,"Saved in %s \n",filename);
+  return ret;
+}
+// --------------------------------------------------------------
+int  PXFPBSplineStack::Save(FILE* fout)
+{
+  fprintf(fout,  "#BFPSplineStackApex File , numsplines, has apex,trim_bottom,trim_top\n");
+  fprintf(fout,  "#%d\n", numsplines);
+  fprintf(fout,  "#%d\n", hasapex);
+  fprintf(fout,  "#%d\n", trim_bottom);
+  fprintf(fout,  "#%d\n", trim_top);
+  fprintf(fout,  "%6.2f %6.2f %6.2f\n",apex.x[0],apex.x[1],apex.x[2]);
+  fprintf(fout,  "#----------------------\n");
+  for (int i=trim_bottom;i<=trim_top;i++)
+      spline[i]->Save(fout);
+  return(1);
+}
+// --------------------------------------------------------------
+int PXFPBSplineStack::Load(const char* filename)
+{
+  int status=0;
+  gzFile fin;
+
+  fin=gzsuffixopen(filename,"r");
+  if (fin!=NULL)
+    {
+      status=Load(fin);
+      gzclose(fin);
+    }
+  
+  if (status>0)
+      {
+	if (debugmode)
+	  fprintf(stderr,"Loading from %s (numsplines=%2d) Trims=(%d:%d)\n",
+		  filename,numsplines,trim_bottom,trim_top);
+      }
+  
+  if (status)
+      adjusttrimmed();
+  
+  if (debugmode && status==0)
+      fprintf(stderr,"Failed to Load from %s\n",filename);
+
+  return (status);
+}
+
+// --------------------------------------------------------------
+int PXFPBSplineStack::Load(gzFile fin)
+{
+  char line[200];
+  int status=0;
+  int  filenumsplines;
+  int headerok=0;
+  int trimt,trimb;
+
+  gzgets(fin,line,100);
+  
+  if (gzfindstringinstring(line, "#BFPSplineStack File"))
+      {
+	gzgets(fin,line,100);	sscanf(line,"#%d",&filenumsplines);
+	gzgets(fin,line,100);	sscanf(line,"#%d",&trimb);
+	gzgets(fin,line,100);	sscanf(line,"#%d",&trimt);
+	gzgets(fin,line,100);
+	hasapex=0;
+	headerok=1;
+      }
+  else if (gzfindstringinstring(line,"#BFPSplineStackApex File"))
+      {
+	gzgets(fin,line,100); sscanf(line,"#%d",&filenumsplines);
+	gzgets(fin,line,100); sscanf(line,"#%d",&hasapex);
+	hasapex=hasapex>0;
+	gzgets(fin,line,100); sscanf(line,"#%d\n",&trimb);
+	gzgets(fin,line,100); sscanf(line,"#%d\n",&trimt);
+	gzgets(fin,line,100); sscanf(line,"%f %f %f\n",&apex.x[0],&apex.x[1],&apex.x[2]);
+	gzgets(fin,line,100);
+	headerok=1;
+      }
+
+  if (debugmode)
+    {
+      fprintf(stderr,"Headerok=%d, filenumsplines=%d \n",headerok,filenumsplines);
+      fprintf(stderr,"Trimbottom=%d, trimtop=%d\n",trimb,trimt);
+    }
+  
+  if (headerok==1)
+      {
+	adjustnumberofsplines(filenumsplines); 
+	settrimbottom(0);
+	settrimtop(trimt);
+	settrimbottom(trimb);
+	status=1;
+	
+	for (int i=trimb;i<=trimt;i++)
+	  {
+	    if (debugmode)
+	      fprintf(stderr,"Reading spline %d\n",i);
+	    spline[i]->Load(fin);
+	  }
+	
+	if (hasapex==0)
+	  autosetapex(0);
+      }
+  return(status);
+}
+// --------------------------------------------------------------
+int PXFPBSplineStack::fittocontourstack(PXContourStack* stack,float smooth,float csmooth,
+					int npoints,int closed)
+{  
+  float dz=stack->getzlevel(stack->getnumcontours()-1)-stack->getzlevel(stack->getnumcontours()-2);
+  
+  int offset=int(stack->getzlevel(0)/dz+0.5);
+
+  adjustnumberofsplines(stack->getnumcontours()+offset);
+  trim_bottom=offset;
+  trim_top=trim_bottom+stack->getnumcontours()-1;
+  int success=0;
+
+  /*  offset-=1;
+
+  if (offset<0)
+      offset=0;*/
+
+  fprintf(stderr,"offset=%d (dz=%6.2f) trim_bottom=%d trim_top=%d numsplines=%d\n",
+	  offset,dz,trim_bottom,trim_top,numsplines);
+
+  for (int kk=0;kk<stack->getnumcontours();kk++)
+      fprintf(stderr,"%5.2f ",stack->getzlevel(kk));
+  fprintf(stderr,"\n");
+
+
+  for(int spl=0;spl<stack->getnumcontours();spl++)
+      {
+	//	if (debugmode)
+	fprintf(stderr,"fitting Spl %d from Cntr %d (z=%5.2f)\t",spl+offset,spl,stack->getzlevel(spl));
+	success+=spline[spl+offset]->fittocontour(stack->getcontour(spl),
+						  smooth,csmooth,npoints,closed);
+	spline[spl+offset]->setzlevel(stack->getzlevel(spl));
+	spline[spl+offset]->ensureAnticlockwise();
+	fprintf(stderr," (nc=%d)\n", (int)spline[spl+offset]->getnumcontrolpoints());
+      }
+	
+  success=(success==stack->getnumcontours());
+  autosetapex(0);
+  hasapex=0;
+  return success;
+}
+// --------------------------------------------------------------
+void PXFPBSplineStack::adjusttrimmed()
+{
+  PXFPBSpline* tempspl=new PXFPBSpline();
+  tempspl->setcircle(4,5.0,50.0,50.0);
+  
+  if (gettrimbottom()>0)
+    {
+      float z1=spline[gettrimbottom()+1]->getzlevel()-spline[gettrimbottom()]->getzlevel();
+      for(int ia=gettrimbottom()-1;ia>=0;ia-=1)
+	{
+	  spline[ia]->copypoints(tempspl);
+	  spline[ia]->setzlevel(spline[ia+1]->getzlevel()-z1);
+	}
+    }
+  if (gettrimtop()<numsplines-1)
+    {
+      float z2=spline[gettrimtop()]->getzlevel()-spline[gettrimtop()-1]->getzlevel();
+      for (int ib=gettrimtop()+1;ib<numsplines-1;ib++)
+	{
+	  spline[ib]->copypoints(tempspl);
+	  spline[ib]->setzlevel(spline[ib-1]->getzlevel()+z2);
+	}
+    }
+  delete tempspl;
+}
+
+// --------------------------------------------------------------
+real PXFPBSplineStack::getsqdist(float x1,float x2,float y1,float y2)
+{
+  return pow(x1-x2,float(2.0))+pow(y1-y2,float(2.0));
+}
+// --------------------------------------------------------------
+PXContour* PXFPBSplineStack::compareSplines(PXFPBSpline* spl1,PXFPBSpline* spl2,int np)
+{
+  PXContour* cntr=new PXContour();
+  real  ds=1.0/float(np);
+  //  spl1->resample(np,ds/10.0);
+  //  spl2->resample(np,ds/10.0);
+  real* x1=new real[np]; real* y1=new real[np];
+  real* x2=new real[np]; real* y2=new real[np];
+  int* corresp1=new int[np];
+  int* corresp2=new int[np];
+
+  float s=0.0;
+  int i=0,j=0;
+  
+  // Copy Points in Arrays for speed 
+  for(i=0;i<np;i++)
+      {
+	spl1->getposition(s,x1[i],y1[i]);
+	spl2->getposition(s,x2[i],y2[i]);
+	s=s+ds;
+      }
+
+  real dist=0.0,mindist=10000000.0;
+  int shift=0;
+  
+  // Preliminary Test for range to look for rough shift
+  // --------------------------------------------
+  for(i=0;i<np;i+=2)
+      {
+	dist=0;
+	for (j=0;j<np;j+=2)
+	    {
+	      int sj=indexcyclic(j+i,np);
+	      dist+=getsqdist(x1[j],x2[sj],y1[j],y2[sj]);
+	    }
+	if (dist<mindist)
+	    {
+	      mindist=dist; 
+	      shift=i;
+	    }
+      }
+  
+  //  cerr << "Shift : " << shift << "(" << mindist << ")\n";
+
+  // Loop 1 from spline to spline2
+  // -----------------------------
+  for (i=0;i<np;i++)
+      {
+	real mindist1=100000000.0,mindist2=100000000.0;
+	int  i1=i+shift,i2=i-shift;
+	int  index1=i1,index2=i2;
+	for(j=-5;j<=5;j++)
+	    {
+	      int jp=indexcyclic(j+i1,np);
+	      int jm=indexcyclic(j+i2,np);
+	      
+	      real dist1=getsqdist(x1[i],x2[jp],y1[i],y2[jp]);
+	      if (dist1<mindist1)
+		  { index1=jp;  mindist1=dist1; }
+
+	      real dist2=getsqdist(x1[jm],x2[i],y1[jm],y2[i]);
+	      if (dist2<mindist2)
+		  { index2=jm;  mindist2=dist2; }
+	    }
+	corresp1[i]=index1; corresp2[i]=index2;
+	//	fprintf(stderr,"%2d: ( %3d %3d) (%5.2f %5.2f) \n ",i,corresp1[i],corresp2[i],mindist1,mindist2);
+      }
+
+  //  fprintf(stderr,"-------------------\n\n");
+  //  cerr << "Failed :" ;
+  int count=0;
+  for (i=0;i<np;i++)
+      {
+	int ind1=corresp1[i];
+	int ind2=corresp2[ind1];
+	if (ind2==i)
+	    count++;
+	else
+	    {
+	      //      cerr << i << " ";
+	      corresp1[i]=-1;
+	    }
+      }
+  //  cerr << "\n";
+  if (count<2)
+      {
+	fprintf(stderr,"Exiting \n");
+	exit(1);
+      }
+  else
+      {
+	int j1=0,j2=0;
+	for (i=0;i<count;i++)
+	    {
+	      while(corresp1[indexcyclic(j1,np)]<0)  j1++;
+	      j2=j1+1;
+       	      while(corresp1[indexcyclic(j2,np)]<0)  j2++;
+
+
+	      if (j2-j1>1)
+		  {
+		    // fprintf(stderr,"\t%2d, ***** , 1->2  *** %2d \t\t2->1  *** %2d\n",
+		    //indexcyclic(j1,np),corresp1[indexcyclic(j1,np)],corresp2[indexcyclic(j1,np)]);
+
+		    //  fprintf(stderr,"Interpolating in %d:%d\n",j1,j2);
+		    // DO for table 1 first
+		    for (j=j1+1;j<j2;j++)
+			{
+			  float fraction=float(j-j1)/float(j2-j1);
+			  float gap1=float(corresp1[indexcyclic(j2,np)]-corresp1[indexcyclic(j1,np)]);
+			  if (gap1<0) gap1+=float(np);
+			  float gap2=float(corresp2[indexcyclic(j2,np)]-corresp2[indexcyclic(j1,np)]);
+			  if (gap2<0) gap2+=float(np);
+
+
+			  int   c1=int(0.5+fraction*gap1)+corresp1[indexcyclic(j1,np)];
+			  corresp1[indexcyclic(j,np)]=indexcyclic(c1,np);
+			  // fprintf(stderr,"\t%2d, %5.2f , 1->2  %3.0f %2d\t",
+			  //indexcyclic(j,np),fraction,gap1,corresp1[indexcyclic(j,np)]);
+
+			  int   c2=int(0.5+fraction*gap2)+corresp2[indexcyclic(j1,np)];
+			  corresp2[indexcyclic(j,np)]=indexcyclic(c2,np);
+			  // fprintf(stderr,"\t2->1  %3.0f %2d\n",gap2,corresp2[indexcyclic(j,np)]);
+			}
+		    // fprintf(stderr,"\t%2d, ***** , 1->2  *** %2d \t\t2->1  *** %2d\n",
+		    //indexcyclic(j2,np),corresp1[indexcyclic(j2,np)],corresp2[indexcyclic(j2,np)]);
+		  }
+	      j1=j2;
+	    }
+	//	cerr << "+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_++_+_+_+_+_+_\n";
+	int index=1,old,current;
+	for (i=0;i<np;i++)
+	    {
+	      //fprintf(stderr,"Flag %2d: ( %3d %3d ) \n",i,corresp1[i],corresp2[i]);
+	      float s1=float(i*ds);
+	      current=corresp1[i];
+	      float s2=float(current*ds);
+	      if (i>0 && i<(np-1) && old!=(current-1))
+		  {
+		    for (j=old+1;j<current;j++)
+			{
+			  float s2a=float(j*ds);
+			  int cur2=corresp2[j];
+			  float s1a=float(cur2*ds);
+			  cntr->Add(s1a,s2a);
+			  // fprintf(stderr,"--> %2d %2d %2d ( %4.2f %4.2f )\n",index,cur2
+			  //,indexcyclic(j,np),s1a,s2a);
+			  index++;
+			}
+		  }
+	      cntr->Add(s1,s2);
+	      // fprintf(stderr,"    %2d %2d %2d ( %4.2f %4.2f )\n",index,i,current,s1,s2);
+	      old=current;
+	      index++;
+	      if (i==(np-1))
+		  {
+		    int add=1;
+		    
+		    if (current==corresp1[0]-1 || current==corresp1[0]-np)
+			add=0;
+		    else
+			{
+			  current=current=np;
+			  if (current==corresp1[0]-1 || current==corresp1[0]-np)
+			      add=0;
+			}
+		    if (add)
+			{
+			  for(j=current+1;j<corresp1[0];j++)
+			      {
+				int ja=indexcyclic(j,np);
+				float s2a=float(ja*ds);
+				int cur2=corresp2[ja];
+				float s1a=float(cur2*ds);
+				      cntr->Add(s1a,s2a);
+				// fprintf(stderr,"--> %2d %2d %2d ( %4.2f %4.2f )\n",index,cur2,ja,s1a,s2a);
+				index++;
+			      }
+			  
+			}
+		  }
+	    }
+	// fprintf(stderr,"Numpoints = %d \n",cntr->getnumpoints());
+      }
+  
+  // Deleting 
+  delete [] x1;delete [] x2;delete [] y1;delete [] y2;
+  delete [] corresp1; delete [] corresp2;
+  return cntr;
+}
+// --------------------------------------------------------------
+void PXFPBSplineStack::setellipticalcylinder(int np,int numslices,float radiusx,float radiusy,
+					     float x,float y,float zscale,float bottomz)
+{
+  PXFPBSpline* tmp=new PXFPBSpline();
+  tmp->setellipse(np,radiusx,radiusy,x,y);
+  numslices=Irange(numslices,2,PXFPBSPLINESTACK_MAXLEVELS);
+  adjustnumberofsplines(numslices);
+  
+  numsplines=numslices;
+  trim_bottom=0;
+  trim_top=numslices-1;
+  
+  for(int i=0;i<numsplines;i++)
+      {
+	if (debugmode)
+	    fprintf(stderr,"Spline %d\n",i);
+	//spline[i]=new PXFPBSpline();
+	spline[i]->copypoints(tmp);
+	spline[i]->setzlevel(bottomz+float(i)*zscale);
+      }
+  delete tmp;
+  autosetapex(0);
+}
+// --------------------------------------------------------------
+void PXFPBSplineStack::setfromboundingbox(int np,float zfactor,
+					float bx,float by,float bz,float bw,float bh,
+					float tx,float ty,float tz,float tw,float th)
+{
+  for (int i=0;i<numsplines;i++)
+      {
+	float zl=zfactor*float(i);
+	spline[i]->setzlevel(zl);
+
+	float ratio=((float(i)-bz)/(tz-bz));
+	float xl=bx+ratio*(tx-bx);
+	float yl=by+ratio*(ty-by);
+	float wl=bw+ratio*(tw-bw);
+	float hl=bh+ratio*(th-bh);
+	spline[i]->setellipse(np,wl,hl,xl,yl);
+      }
+  settrimbottom(int(bz));
+  settrimtop(int(tz));
+  autosetapex(0);
+}
+// --------------------------------------------------------------
+PXContourStack* PXFPBSplineStack::exporttocontourstack(real dist,real zdist,int mode)
+{
+  int zbet=0;
+  //  fprintf(stderr,"Exprting to Contour Stack (2) %.2f %.2f\n",dist,zdist);
+
+  if (gettrimbottom()<gettrimtop())
+    {
+      float zsize=((getspline(gettrimbottom()+1)->getzlevel())-
+		   (getspline(gettrimbottom()  )->getzlevel())
+		   );
+
+      if (fabs(zsize)<0.0001)
+	{
+	  zbet=1;
+	}
+      else
+	{
+	  zdist=zdist/zsize; 
+	  zbet=0;
+	  if (zdist<0.05)  zdist=0.05;
+
+	  if (zdist<1.0) 
+	    zbet=int(0.5+1.0/zdist)-1;
+	  //fprintf(stderr,"zdist=%.2f zbet=%d\n",zdist,zbet);
+	}
+
+      //fprintf(stderr,"dist=%.2f zbet=%d (zdist=%.3f zsize=%.3f) mode=%d\n",dist,zbet,zdist,zsize,mode);
+    }
+
+  return exporttocontourstack(dist,zbet,mode);
+}
+// --------------------------------------------------------------
+PXContourStack* PXFPBSplineStack::exporttocontourstack(real dist,int zbetween,int mode)
+{
+  
+  /*PXFPBSplineStack* temp=new PXFPBSplineStack(this,zbetween,mode,0);
+  PXContourStack* stack=temp->exporttocontourstack(dist);
+  delete temp; */
+  
+  PXContourStack* temp=exporttocontourstack(dist*0.2);
+  PXContourStack* stack=new PXContourStack(temp,zbetween,mode);
+  stack->Equispace(dist);
+  delete temp;   
+  return stack;
+}
+// --------------------------------------------------------------
+PXContourStack* PXFPBSplineStack::exporttocontourstack(real dist)
+{
+  PXContourStack* stack=new PXContourStack(gettrimtop()-gettrimbottom()+1+(hasapex>0));
+
+  if (hasapex>0)
+      {
+	PXContour* apexc=stack->getcontour(0);
+	apexc->Add(apex.x[0],apex.x[1]);
+	stack->setzlevel(0,apex.x[2]);
+      }
+
+  for(int j=gettrimbottom();j<=gettrimtop();j++)
+      {
+	if (debugmode)
+	    fprintf(stderr,"Exporting %d ",j);
+	PXContour* cntr=stack->getcontour(j-gettrimbottom()+(hasapex>0));
+	PXContour* tempcntr=spline[j]->exporttocontour(dist);
+	cntr->copypoints(tempcntr);
+	cntr->ensureAnticlockwise();
+	cntr->setclosed(1);
+	delete tempcntr;
+	stack->setzlevel(j-gettrimbottom()+(hasapex>0),spline[j]->getzlevel());
+	if (debugmode)
+	    fprintf(stderr,"(%5.2f) ",spline[j]->getzlevel());
+      }
+  if (debugmode)
+      fprintf(stderr,"Done\n");
+  return stack;
+}
+// --------------------------------------------------------------
+int PXFPBSplineStack::polarpoint(float zl,int slice,real middlex,int pass,
+				 real& x,real& y)
+{
+  int status=0;
+  PXFPBSpline* spl=getspline(slice);
+  float theta,radius,minx,maxx;
+  
+  switch(pass)
+      {
+      case 0:
+	theta=(getspline(slice))->getzlevel()-180.0;
+	minx=-1000000000.0;maxx=middlex-0.01;
+	break;
+      case 1:
+	theta=(getspline(slice))->getzlevel();
+	minx=middlex+0.01;
+	maxx=100000000000.0;
+	break;
+      }
+
+  radius=spl->findIntersectY(zl,minx,maxx);
+  float ds=0.05;  int att=0; float dy=0.05;
+  while(radius==-1111.0 && att<5)
+      {
+	ds=ds*0.5;
+	att++;
+	radius=spl->findIntersectY(zl,minx,maxx,ds,dy);
+	dy=dy*0.5;
+      }
+  float r=fabs(radius-middlex);
+  float t=theta*M_PI/180.0;
+  
+  if (radius!=-1111.0)
+      {
+	x=(middlex+r*cos(t));
+	y=(middlex+r*sin(t));
+	status=1;
+      }
+  return status;
+}
+
+// --------------------------------------------------------------
+float PXFPBSplineStack::getpolarbottomz()
+{
+  float bottomz=0.0;
+  
+  for (int i=gettrimbottom();i<=gettrimtop();i++)
+    {
+      float z=getspline(i)->getcontroly(0);
+      for (int j=1;j<spline[i]->getnumpoints();j++)
+	z=Fmin((spline[i])->getcontroly(j),z);
+      if (i==gettrimbottom())
+	bottomz=z;
+      else
+	bottomz=Fmax(z,bottomz);
+    }
+  return bottomz;
+
+}
+
+float PXFPBSplineStack::getpolartopz()
+{
+  float topz=0.0;
+  for (int i=gettrimbottom();i<=gettrimtop();i++)
+    {
+      float z=getspline(i)->getcontroly(0);
+      for (int j=1;j<spline[i]->getnumpoints();j++)
+	z=Fmax(z,(spline[i])->getcontroly(j));
+      if (i==gettrimbottom())
+	topz=z;
+      else
+	topz=Fmin(z,topz);
+    }
+  return topz;
+}
+// --------------------------------------------------------------
+PXContourStack* PXFPBSplineStack::polarexporttocontourstack(real middlex,float zsp,
+							    float bottomz,float topz)
+{
+  if (bottomz==-1000.0)
+    bottomz=getpolarbottomz()+3.0;
+  
+  if (topz==-1000.0)
+    topz=getpolartopz()-3.0;
+  
+  if (topz<bottomz)
+      {
+	real t=topz;
+	topz=bottomz;
+	bottomz=t;
+      }
+
+  bottomz=float(int(bottomz+0.5));
+  topz=float(int(topz+0.5));
+
+  int  numslices=int((topz-bottomz)/zsp);
+
+  PXContourStack* cstack=new PXContourStack(numslices);
+  numslices=cstack->getnumcontours();
+
+  fprintf(stderr,"\n\nBottomz=%6.2f, Topz=%6.2f, numslices=%d, zsp=%5.3f\n",
+	  bottomz,topz,numslices,zsp);
+
+  int i;
+  for (i=0;i<numslices;i++)
+      {
+	float zl=bottomz+float(i)*zsp;//(real(i)/real(numslices-1))*(topz-bottomz);
+	cstack->setzlevel(i,zl);
+	PXContour* cntr=cstack->getcontour(i);
+
+	fprintf(stderr,"i=%d zl=%6.3f , ",i,zl);
+
+
+	for (int pass=0;pass<=1;pass++)
+	    {
+	      for (int sl=gettrimbottom();sl<=gettrimtop();sl++)
+		  {
+		    real x,y;
+		    if (polarpoint(zl,sl,middlex,pass,x,y))
+			cntr->Add(x,y);
+		    else
+			{
+			  sl=gettrimtop()+1;
+			  pass=2;
+			}
+		  }
+	    }
+      }
+
+  int numgood=0;
+  int maxp=0;
+  for (i=0;i<cstack->getnumcontours();i++)
+      maxp=Imax((cstack->getcontour(i))->getnumpoints(),maxp);
+
+  for (i=0;i<cstack->getnumcontours();i++)
+      {
+	if ((cstack->getcontour(i))->getnumpoints()==maxp)
+	    numgood++;
+      }
+
+  if (numgood==cstack->getnumcontours())
+      {
+	fprintf(stderr,"Polar Contour OK\n");
+	return cstack;
+      }
+
+  PXContourStack* cstack2=new PXContourStack(numgood);
+
+  int index1=0,index2=0;
+  while (index1<numgood)
+      {
+	while((cstack->getcontour(index2))->getnumpoints()!=maxp)
+	    index2++;
+	
+	(cstack2->getcontour(index1))->copypoints(cstack->getcontour(index2));
+	cstack2->setzlevel(index1,cstack->getzlevel(index2));
+	index1++;
+	index2++;
+      }
+
+  fprintf(stderr," middlex=%5.2f,maxp=%d, old num contours %d returning %d\n",
+	  middlex,maxp,cstack->getnumcontours(),numgood);
+  delete cstack;
+  return cstack2;
+
+}
+// --------------------------------------------------------------
+float PXFPBSplineStack::findnearestneighbour(float& xn,float& yn,float &zn,float dt,int dbg)
+{
+  float dist=0.0;
+  if (zn<=spline[gettrimbottom()]->getzlevel())
+      {
+	dist=spline[gettrimbottom()]->findnearestneighbour(xn,yn,dt);
+      }
+  else if (zn>=spline[gettrimtop()]->getzlevel())
+      {
+	dist=spline[gettrimtop()]->findnearestneighbour(xn,yn,dt);
+      }
+  else
+      {
+	int i=gettrimbottom();
+	int found=0;
+	while (found==0 && i<gettrimtop())
+	    {
+	      if (zn==spline[i]->getzlevel())
+		  {
+		    dist=spline[i]->findnearestneighbour(xn,yn,dt);
+		    found=1;
+		  }
+	      if (zn>spline[i]->getzlevel() && zn<spline[i+1]->getzlevel())
+		  {
+		    real x0=xn,y0=yn,x1=xn,y1=yn,d0=1.0,d1=1.0;
+		    float dz=(spline[i+1]->getzlevel()-spline[i]->getzlevel());
+		    float w0=(spline[i+1]->getzlevel()-zn)/dz;
+		    float w1=(zn-spline[i]->getzlevel())/dz;
+
+		    d0=spline[i]->findnearestneighbour(x0,y0,dt,dbg);
+		    d1=spline[i+1]->findnearestneighbour(x1,y1,dt,dbg);
+
+		    float xf=(w1*x1+w0*x0);
+		    float yf=(w1*y1+w0*y0);
+		    float zf=(w1*spline[i+1]->getzlevel()+w0*spline[i]->getzlevel());
+		    if (dbg==1)
+			{
+			  fprintf(stderr," Point (%5.2f %5.2f %5.2f)\n",xn,yn,zn);
+			  fprintf(stderr," Neighbours (%5.2f,%5.2f,%5.2f) and (%5.2f,%5.2f,%5.2f)\n",
+				  x0,y0,spline[i]->getzlevel(),x1,y1,spline[i+1]->getzlevel());
+			  fprintf(stderr," Distances %5.2f %5.2f , Weight %5.2f %5.2f \n",
+				  d0,d1,w0,w1);
+			  fprintf(stderr," Result (%5.2f,%5.2f,%5.2f)\n",xf,yf,zf);
+			  spline[i]->SaveContour("/intdisk2b/experiments/papad/simulation/cylinder/splinei.cntr",0.1);
+			  spline[i+1]->SaveContour("/intdisk2b/experiments/papad/simulation/cylinder/splineip.cntr",0.1);
+			}
+
+		    dist=sqrt(pow(xn-xf,float(2.0))+pow(yn-yf,float(2.0))+pow(zn-zf,float(2.0)));
+		    xn=xf; yn=yf; zn=zf;
+		  }
+	      i++;
+	    }
+      }
+  return dist;
+}
+// --------------------------------------------------------------
+int PXFPBSplineStack::equitrimstacks(PXFPBSplineStack* stack1,PXFPBSplineStack* stack2,int trim[4])
+{
+  // Store Old Trims
+  trim[0]=stack1->gettrimbottom();
+  trim[1]=stack1->gettrimtop();
+  trim[2]=stack2->gettrimbottom();
+  trim[3]=stack2->gettrimtop();
+
+  int found=0,i=trim[0]-1;
+
+  while(i<=trim[1] && found==0)
+      {
+	i++;
+	float z1=(stack1->getspline(i))->getzlevel();
+	int j=trim[2]-1;
+	while (j<=trim[3] && found==0)
+	    {
+	      j++;
+	      float z2=(stack2->getspline(j))->getzlevel();
+	      if (z2==z1)
+		  {
+		    found=1;
+		    stack1->settrimbottom(i);
+		    stack2->settrimbottom(j);
+		    /*if (debugmode)
+			{
+			  fprintf(stderr,"Common Bot Z at Slice1=%2d , Slice2=%2d (z1=%5.2f z2=%5.2f )\n",
+				  i,j,z1,z2);
+			}*/
+		  }
+	    }
+      }
+
+  if (found==0)
+      return 0;
+
+  found=0;
+  i=trim[1]+1;
+ 
+  while(i>=stack1->gettrimbottom() && found==0)
+      {
+	i=i-1;
+	float z1=(stack1->getspline(i))->getzlevel();
+	int j=trim[3]+1;
+	while (j>=stack2->gettrimbottom() && found==0)
+	    {
+	      j=j-1;
+	      float z2=(stack2->getspline(j))->getzlevel();
+	      if (z2==z1)
+		  {
+		    found=1;
+		    stack1->settrimtop(i);
+		    stack2->settrimtop(j);
+		    /*if (debugmode)
+		      {
+		      fprintf(stderr,"Common Top Z at Slice1=%2d , Slice2=%2d (z1=%5.2f z2=%5.2f )\n",
+		      i,j,z1,z2);
+		      }*/
+		  }
+	    }
+      }
+  
+  return found;  	
+}
+// --------------------------------------------------------------
+void PXFPBSplineStack::untrimstacks(PXFPBSplineStack* stack1,PXFPBSplineStack* stack2,int trim[4])
+{
+  stack1->settrimbottom(trim[0]);
+  stack1->settrimtop(trim[1]);
+  stack2->settrimbottom(trim[2]);
+  stack2->settrimtop(trim[3]);
+
+}
+// --------------------------------------------------------------
+int PXFPBSplineStack::createstackset(PXFPBSplineStack* newstack[],
+				     PXFPBSplineStack *stack1,PXFPBSplineStack *stack2,
+				     int numstacks,int NP)
+{
+  int trims[4];
+  equitrimstacks(stack1,stack2,trims);
+  
+  int nsp=stack1->gettrimtop()-stack1->gettrimbottom()+1;
+
+  for (int ia=0;ia<numstacks;ia++)
+      newstack[ia]=new PXFPBSplineStack(nsp);
+  
+
+  char line[100];
+
+  for (int i=0;i<nsp;i++)
+      {
+	PXContour* cntr1=(stack1->getspline(i+stack1->gettrimbottom()))->exporttocontour(0.8);
+	PXContour* cntr2=(stack2->getspline(i+stack2->gettrimbottom()))->exporttocontour(0.8);
+	
+	PXChamferDistanceMap* map1=new PXChamferDistanceMap(cntr1,0);
+	map1->generateMap(1,0,0.0);
+	PXChamferDistanceMap* map2=new PXChamferDistanceMap(cntr2,0);
+	map2->generateMap(1,0,0.0);
+
+	/*	sprintf(line,"inner%02d.cntr",i+1);
+		stack1->getspline(i+stack1->gettrimbottom())->SaveContour(line,float(2.0));
+		fprintf(stderr,"%2d : %s ,",i+1,line);
+		sprintf(line,"outer%02d.cntr",i+1);
+		fprintf(stderr,"%s : ",line);
+		stack2->getspline(i+stack2->gettrimbottom())->SaveContour(line,float(2.0));*/
+	
+	for (int j=0;j<numstacks;j++)
+	    {
+	      int fraction1=numstacks-j;
+	      int fraction2=j+1;
+
+	      if (j==0)
+		  fraction1++;
+
+	      PXChamferDistanceMap* map=new PXChamferDistanceMap(map1,map2,fraction1,fraction2);
+	      PXContour* cntr=map->extractContour();
+	      
+	      (newstack[j]->getspline(i))->fittocontour(cntr,1.0,0.0);
+	      (newstack[j]->getspline(i))->setzlevel(stack1->getspline(i+stack1->gettrimbottom())->getzlevel());
+	      (newstack[j]->getspline(i))->ensureAnticlockwise();
+	      delete map;
+
+	      /*sprintf(line,"middle%02d%02d.cntr",i+1,j+1);
+		fprintf(stderr,"%s(%3d-->%3d), ",line,cntr->getnumpoints(),
+		(newstack[j]->getspline(i))->getnumpoints());
+		(newstack[j]->getspline(i))->SaveContour(line,float(2.0));
+		*/
+	      
+	      delete cntr;
+	    }
+	//	fprintf(stderr,"\n");
+
+	if (i>-1)
+	    {
+	      float* px1=new float[NP+1];   float* py1=new float[NP+1];
+	      float* px2=new float[NP+1];   float* py2=new float[NP+1];
+	      PXContour *mesh[10];
+	      
+	      mesh[0]=(stack1->getspline(i+stack1->gettrimbottom()))->exporttoNcontour(NP);
+	      for (int mm=1;mm<=numstacks;mm++)
+		  mesh[mm]=(newstack[mm-1]->getspline(i))->exporttoNcontour(NP);
+	      mesh[numstacks+1]=(stack2->getspline(i+stack2->gettrimbottom()))->exporttoNcontour(NP);
+	      
+	      
+	      for (int k=1;k<=numstacks+1;k++)
+		  PXContourStack::aligncontours(mesh[k-1],mesh[k]);
+	      
+	      if (i==8)
+		  {
+		    mesh[0]->Save4Mesh("in_curve");
+		    mesh[(numstacks+2)/2]->Save4Mesh("curve");
+		    mesh[numstacks+1]->Save4Mesh("out_curve");
+		  }
+
+	      FILE* fout;
+	      sprintf(line,"mesh.%02d",i);
+	      fout=fopen(line,"w");
+	      if (fout!=NULL)
+		  {
+		    fprintf(stderr,"Opened : %s\n",line);
+		    for (int ia=0;ia<=numstacks;ia++)
+			{
+			  fprintf(stderr,"Numpoints = %d,%d\n",
+				  mesh[ia]->getnumpoints(),mesh[ia+1]->getnumpoints());
+			  int npi;
+			  mesh[ia]->copy2vector(px1,py1,npi);
+			  mesh[ia+1]->copy2vector(px2,py2,npi);
+			  float x0,x1,x2,x3,y0,y1,y2,y3;			  
+			  for(int j=0;j<NP;j++)
+			      {
+				int jp=j+1;
+				if (jp==NP)
+				    jp=1;
+
+				
+				x0=px1[j];  y0=py1[j];
+				x1=px2[j];  y1=py2[j];
+				x2=px1[jp]; y2=py1[jp];
+				x3=px2[jp]; y3=py2[jp];
+				
+				fprintf(fout," %5.2f %5.2f \n",x0,y0);
+				fprintf(fout," %5.2f %5.2f \n",x1,y1);
+				fprintf(fout," %5.2f %5.2f \n",x3,y3);
+				fprintf(fout," %5.2f %5.2f \n",x2,y2);
+				fprintf(fout," %5.2f %5.2f \n",x0,y0);
+			      }
+			  fprintf(fout," %5.2f %5.2f \n",x1,y1);
+			  fprintf(fout," %5.2f %5.2f \n",x3,y3);
+			}
+		    fclose(fout);
+		    fprintf(stderr,"Saved in %s \n",line);
+		  }
+	      for (int l=0;l<=numstacks+1;l++)
+		  delete mesh[l];
+	      delete [] px1;   delete [] py1;
+	      delete [] px2;   delete [] py2;      
+	    }
+	delete map1;
+	delete map2;
+	delete cntr1;
+	delete cntr2;
+
+      }
+
+  untrimstacks(stack1,stack2,trims);
+  return nsp;
+}
+// --------------------------------------------------------------
+int PXFPBSplineStack::temporallySmoothApex(PXFPBSplineStack** stacks,int numstacks,
+					   int areacheck,float sigma,int closed)
+{
+  int doareas=(areacheck>0);
+  float* area,meanarea=0.0,maxarea=0.0001;
+
+  if (doareas)
+      {
+	area=new float[numstacks];
+	for (int ia=0;ia<numstacks;ia++)
+	    {
+	      int bo=stacks[ia]->gettrimbottom();
+	      PXContour* temp=stacks[ia]->getspline(bo)->exporttoNcontour(10,1);
+	      temp->setclosed(1);
+	      area[ia]=sqrt(temp->getarea());
+	      meanarea+=area[ia]/float(numstacks);
+	      maxarea=Fmax(maxarea,area[ia]);
+	      delete temp;
+	    }
+	maxarea=Fmax(maxarea,1.5*meanarea);
+      }
+
+  PXContour* cntr1=new PXContour();
+  PXContour* cntr2=new PXContour();
+  //fprintf(stderr,"Smoothing %d stack apexes\n",numstacks);
+
+  int i;
+  for (i=0;i<numstacks;i++)
+      {
+	if (!stacks[i]->apexenabled())
+	    stacks[i]->autosetapex();
+
+	PX3Vector* vec0=stacks[i]->getapex();
+	PX3Vector vec;
+	vec.copy(vec0);
+	
+
+	if (doareas)
+	    {
+	      float zp=stacks[i]->getspline(stacks[i]->gettrimbottom())->getzlevel();
+	      float zp2=stacks[i]->getspline(stacks[i]->gettrimbottom()+1)->getzlevel();
+	      fprintf(stderr,"Original z=%6.3f area=%6.3f maxarea=%5.3f newz=",
+		      vec.x[2],area[i],maxarea);
+	      vec.x[2]=zp-0.75*(zp2-zp)*(area[i]/maxarea);
+	      fprintf(stderr,"%6.3f\n",vec.x[2]);
+	    }
+
+	real x=vec.x[0];
+	real y=vec.x[1];
+	real z=vec.x[2];
+	cntr1->Add(z,z);
+	cntr2->Add(x,y);
+      }
+
+  cntr1->setclosed(closed);
+  cntr2->setclosed(closed);
+
+  cntr1->Smooth(sigma,3);
+  cntr2->Smooth(sigma,3);
+
+  PXContourPoint *pts1=cntr1->gettoppoint();
+  PXContourPoint *pts2=cntr2->gettoppoint();
+
+  for (i=0;i<numstacks;i++)
+      {
+	stacks[i]->enableapex(1);
+	stacks[i]->setapex(pts2->x,pts2->y,pts1->x);
+	pts2=pts2->next;
+	pts1=pts1->next;
+      }
+  
+  fprintf(stderr,"Smoothing %d stack apexes (area=%d) done\n",numstacks,doareas);
+  delete cntr1;
+  delete cntr2;
+
+  if (doareas)
+      delete [] area;
+  return 1;
+}
+
+// --------------------------------------------------------------
+void PXFPBSplineStack::autosetapex(int active)
+{
+  real cx,cy,cz;
+  PXFPBSpline* spl=getspline(gettrimbottom());
+  PXFPBSpline* spl2=getspline(gettrimbottom()+1);
+  spl->getcentroid(cx,cy,cz,0.1);
+  
+  cx=quantize(cx,1);
+  cy=quantize(cy,1);
+  cz=quantize(cz-0.5*(spl2->getzlevel()-cz),1);
+  setapex(cx,cy,cz);
+
+  if (active)
+    enableapex(1);
+}
+// --------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/numerics/pxfpbsplinestack.h b/bioimagesuite30_src/numerics/pxfpbsplinestack.h
new file mode 100644
index 0000000..29e668b
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxfpbsplinestack.h
@@ -0,0 +1,191 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pxfpbsplinestack.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+_Module_Name : PXFPBSplineStack 
+
+_Description : A collection class which stores splines which are the XY cross-sections of a surface
+               
+
+_Call : 
+  PXFPBSplineStack();
+  PXFPBSplineStack(PXFPBSplineStack *old);
+
+_References : see pxfpbspline.h
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 19th December 1997
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXFPBSplineStack
+#define _PXFPBSplineStack
+#include "pxfpbspline.h"
+#include "pxtriangulatedstack.h"
+#include "pxgeometrystruct.h"
+
+const int PXFPBSPLINESTACK_MAXLEVELS=600;
+
+class PXFPBSplineStack  {
+
+protected:
+
+  PXFPBSpline* spline[PXFPBSPLINESTACK_MAXLEVELS];
+  int numsplines,trim_bottom,trim_top,hasapex;
+  PX3Vector apex;
+
+  
+
+  // ******************************************************************************
+  //          PUBLIC INTERFACE
+  // ******************************************************************************
+
+ public:
+
+  PXFPBSplineStack(int numberofsplines=4);
+  PXFPBSplineStack(PXFPBSplineStack *old);
+  PXFPBSplineStack(PXFPBSplineStack *old,int zbetween,int mode=1,
+		   int resample_original=1);
+  PXFPBSplineStack(PXFPBSplineStack *old1,PXFPBSplineStack* old2,float ratio,
+		   float smooth=2.0,int doapex=0);
+
+  virtual ~PXFPBSplineStack();
+
+  // [A] Access Splines
+  // ------------------
+  virtual int  gettrimbottom() { return trim_bottom;}
+  virtual int  gettrimtop()    { return trim_top;}
+  virtual void settrimbottom(int tb);
+  virtual void settrimtop(int tt);
+  virtual void autosettrims(float zmin,float zmax);
+  virtual int  getnumsplines()    { return numsplines; }
+
+  virtual void setapex(float x,float y,float z) { apex.x[0]=x; apex.x[1]=y; apex.x[2]=z;}
+  virtual PX3Vector* getapex() { return &apex;}
+  virtual void enableapex(int enable=1) { hasapex=enable>0; }
+  virtual int  apexenabled() { return hasapex; }
+  virtual void autosetapex(int active=1);
+
+  // [B] Find Nearest Point
+  // ----------------------
+  virtual float findnearestneighbour(float&x,float& y,float &z,float dt=0.01,int dbg=0);
+
+  // [C] Set Original Shape
+  // ----------------------
+  virtual void setellipticalcylinder(int np,int numslices,float radiusx,float radiusy,float x,float y,
+				     float zscale=1.0,float bottomz=0.0);
+  virtual void setfromboundingbox(int np,float zfactor,
+			  float bx,float by,float bz,float bw,float bh,
+			  float tx,float ty,float tz,float tw,float th);
+
+  // [D] Set / Get individual splines whole point sets
+  // -------------------------------------------------
+  virtual void copypoints(PXFPBSplineStack* other,int ignoretrim=0);
+  virtual PXFPBSpline*   getspline(int i)  { return spline[indexbounded(i)];}
+  virtual void setspline(PXFPBSpline* spl,int ind);
+
+
+  virtual int sample(int sm=2,float step=0.05);
+  virtual int subsample(int sm=2,float step=0.05);
+  virtual int resample(float ds_step=0.05,int npoints=-1);
+  virtual int changespacing(real smth=1.0,int npoints=-1,float step=0.05);
+
+  // [E] I/O Functions
+  // -----------------------------
+  virtual int Save(const char*  filename);
+  virtual int Save(FILE* fout);
+  virtual int Load(const char*  filename);
+  virtual int Load(gzFile fout);
+
+  // [F] Interface to Older Code
+  // ---------------------------
+
+  virtual int fittocontourstack(PXContourStack* stack,float smooth=5.0,float csmooth=0.5,
+				int npoints=-1,int closed=1);
+
+
+  virtual PXContourStack* exporttocontourstack(real dist);
+  virtual PXContourStack* exporttocontourstack(real dist,real zdist,int mode=1);
+  virtual PXContourStack* exporttocontourstack(real dist,int zbetween,int mode=1);
+
+  virtual PXContourStack* polarexporttocontourstack(real middlex,float zspacing=2.0,
+						    float bottomz=-1000.0,float topz=-1000.0);
+  
+  virtual float getpolarbottomz();
+  virtual float getpolartopz();
+  virtual int polarpoint(float zl,int slice,real middlex,int pass,real& x,real& y);
+  virtual void adjustnumberofsplines(int newnumber);
+
+protected:
+
+  virtual void adjusttrimmed();
+  virtual int  indexbounded(int v,int np=-1);
+  static  int  indexcyclic(int v,int np);
+  static  real getsqdist(float x1,float x2,float y1,float y2);
+
+
+public:
+  static  PXContour* compareSplines(PXFPBSpline* spl1,PXFPBSpline* spl2,int np=20);
+  static  int   debugmode;
+  static  void  setdebugmode(int d) { debugmode=(d>0);}
+
+
+  static int  equitrimstacks(PXFPBSplineStack* stack1,PXFPBSplineStack* stack2,int trims[4]);
+  static void untrimstacks(PXFPBSplineStack* stack1,PXFPBSplineStack* stack2,int trims[4]);
+  static int  createstackset(PXFPBSplineStack* newstacks[],
+			     PXFPBSplineStack *stack1,PXFPBSplineStack *stack2,
+			     int numstacks=1,int NP=25);
+  static int  temporallySmoothApex(PXFPBSplineStack**  stacks,int numstacks,
+				   int areacheck,float sigma,int closed);
+
+};
+
+
+
+#endif  
+
diff --git a/bioimagesuite30_src/numerics/pxgeometrystruct.cpp b/bioimagesuite30_src/numerics/pxgeometrystruct.cpp
new file mode 100644
index 0000000..91dfa20
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxgeometrystruct.cpp
@@ -0,0 +1,1165 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+#include "pxgeometrystruct.h"
+#include "pxutil.h"
+
+
+// ---------------------------------------------------
+// Access Functions
+// ---------------------------------------------------
+PXIntegerNode*  PXIntegerList::getcurrentnode()  { return iterationnode;}
+// ---------------------------------------------------
+int PXIntegerList::getcurrent()  
+{
+  return iterationnode->value;
+}
+// ---------------------------------------------------
+int PXIntegerList::getnumnodes() 
+{ 
+  return numnodes;
+} 
+
+// ---------------------------------------------------
+PXIntegerList::PXIntegerList()
+{
+  init();
+}
+// ---------------------------------------------------
+PXIntegerList::~PXIntegerList()
+{
+  DeleteAll();
+  delete topnode;
+}
+// ---------------------------------------------------
+void PXIntegerList::init()
+{
+  numnodes=0;
+  lastnode=new PXIntegerNode;;
+  lastnode->next=NULL;
+  lastnode->previous=NULL;
+  lastnode->value=0;
+  topnode=lastnode;
+  iterationnode=lastnode;
+}
+// ---------------------------------------------------  
+void  PXIntegerList::Rewind()
+{
+  iterationnode=topnode;
+}
+// ---------------------------------------------------
+void  PXIntegerList::Next()
+{
+  if (iterationnode->next!=lastnode)
+      iterationnode=iterationnode->next;
+  else
+      iterationnode=topnode;
+}
+// ---------------------------------------------------
+void  PXIntegerList::Add(int pt)
+{
+  lastnode->value=pt;
+  lastnode->next=new PXIntegerNode;
+  (lastnode->next->previous)=lastnode;
+  lastnode=lastnode->next;
+  lastnode->next=NULL;
+  lastnode->value=0;
+  numnodes+=1;
+}
+// ---------------------------------------------------
+void  PXIntegerList::AddNonDuplicate(int pt,int exclude)
+{
+  if (pt==exclude)
+    return;
+  
+  int found=0,i=0;
+  Rewind();
+  while(i<numnodes && found==0)
+    {
+      if (getcurrent()==pt)
+	found=1;
+      ++i;
+      Next();
+    }
+  
+  if (found==0)
+    {
+      lastnode->value=pt;
+      lastnode->next=new PXIntegerNode;
+      (lastnode->next->previous)=lastnode;
+      lastnode=lastnode->next;
+      lastnode->next=NULL;
+      lastnode->value=0;
+      ++numnodes;
+    }
+}
+// ---------------------------------------------------
+void PXIntegerList::Sort(PXIntegerList* linked)
+{
+  if (numnodes<2)
+      return;
+  
+  int hasother=0;
+
+  if (linked!=NULL)
+      {
+	if (linked->getnumnodes()==numnodes)
+	    hasother=1;
+      }
+  
+  int* temp=new int[numnodes];
+  Rewind();
+
+  int* temp2=NULL;
+  if (hasother)
+      {
+	temp2=new int[numnodes];
+	linked->Rewind();
+      }
+  int i;
+  for (i=0;i<numnodes;i++)
+      {
+	temp[i]=getcurrent();
+	Next();
+	if (hasother)
+	    {
+	      temp2[i]=linked->getcurrent();
+	      linked->Next();
+	    }
+      }
+
+  int oldnumnodes=numnodes;
+  DeleteAll();
+  if (hasother)
+      linked->DeleteAll();
+
+  for (i=0;i<oldnumnodes;i++)
+      {
+	int minval=temp[i];
+	int minval2=0;
+	if (hasother)
+	    minval2=temp2[i];
+	int best=i;
+	for (int j=i+1;j<oldnumnodes;j++)
+	    {
+	      if (temp[j]<minval)
+		  {
+		    minval=temp[j];
+		    best=j;
+		    if (hasother)
+			minval2=temp2[j];
+		  }
+	    }
+	if (best!=i)
+	    {
+	      temp[best]=temp[i];
+	      if (hasother)
+		  temp2[best]=temp2[i];
+	    }
+	Add(minval);
+	if (hasother)
+	    linked->Add(minval2);
+      }
+  delete [] temp;
+
+  if (hasother)
+      delete [] temp2;
+}
+// ---------------------------------------------------
+int  PXIntegerList::isSame(PXIntegerList *other)
+{
+  if (numnodes==other->getnumnodes())
+      return (numberinCommon(other)==numnodes);
+  return 0;
+}
+// ---------------------------------------------------
+int  PXIntegerList::isSamePresorted(PXIntegerList* other)
+{
+  int same=1;
+  if (numnodes==other->getnumnodes())
+      {
+	Rewind();
+	other->Rewind();
+	int i=0;
+	while(i<numnodes && same==1)
+	    {
+	      if (getcurrent()!=other->getcurrent())
+		  same=0;
+	      other->Next();
+	      Next();
+	      i++;
+	    }
+      }
+  else
+      same=0;
+  return same;
+}
+// ---------------------------------------------------
+int  PXIntegerList::numberinCommon(int* points,int numpoints)
+{
+  Rewind();
+  int same=0;
+  for (int i=0;i<numnodes;i++)
+      {
+	int found=0,j=0;
+	while(j<numpoints && found==0)
+	    {
+	      if(getcurrent()==points[j])
+		  {
+		    same++;
+		    found=1;
+		  }
+	      j++;
+	    }
+	Next();
+      }
+  return same;
+}
+// ---------------------------------------------------
+int  PXIntegerList::numberinCommon(PXIntegerList* other)
+{
+  Rewind();
+  int same=0;
+  for (int i=0;i<numnodes;i++)
+      {
+	other->Rewind();
+	int found=0,j=0;
+	while(j<other->getnumnodes() && found==0)
+	    {
+	      if(getcurrent()==other->getcurrent())
+		  {
+		    same++;
+		    found=1;
+		  }
+	      other->Next();
+	      j++;
+	    }
+	Next();
+      }
+  return same;
+}
+// ---------------------------------------------------
+void  PXIntegerList::Copy(PXTriangle* tri)
+{
+  DeleteAll();
+  for (int j=0;j<=2;j++)
+      Add(tri->p[j]);
+}
+// ---------------------------------------------------
+int   PXIntegerList::CopyTo(PXTriangle* tri)
+{
+  if (numnodes!=3)
+      return 0;
+  Rewind();
+  for(int j=0;j<=2;j++)
+      {
+	tri->p[j]=getcurrent();
+	Next();
+      }
+  return 1;
+}
+// ---------------------------------------------------
+void  PXIntegerList::DeleteAll()
+{
+  if (numnodes==0)
+    return;
+  
+  while (lastnode->previous != 0)
+    {
+      lastnode=lastnode->previous;
+      delete lastnode->next;
+      lastnode->next=0;
+    }
+  lastnode=topnode;
+  iterationnode=lastnode;
+  numnodes=0;  
+}
+// ---------------------------------------------------  
+void  PXIntegerList::Copy(PXIntegerList* other)
+{
+  DeleteAll();
+  other->Rewind();
+  //  fprintf(stderr,"Numnodes = %d ",other->getnumnodes());
+
+  for (int i=0;i<other->getnumnodes();i++)
+      {
+	//fprintf(stderr,"[%d]",i);
+	Add(other->getcurrent());
+	other->Next();
+      }
+  //  fprintf(stderr,"\n");
+}
+// ---------------------------------------------------  
+void  PXIntegerList::eliminateDuplicates(int exclude)
+{
+  int  np=getnumnodes(),i;
+  int* buffer=new int[np];
+  Rewind();
+  for (i=0;i<np;i++)
+      {
+	buffer[i]=getcurrent();
+	Next();
+      }
+  DeleteAll();
+  
+  for (i=0;i<np-1;i++)
+      for (int j=i+1;j<np;j++)
+	  {
+	    if (buffer[j]==buffer[i] || buffer[j]==exclude)
+		buffer[j]=exclude;
+	  }
+  for (i=0;i<np;i++)
+      {
+	if (buffer[i]!=exclude)
+	    Add(buffer[i]);
+      }
+  delete [] buffer;
+}
+// ---------------------------------------------------  
+// ************************************************---
+//  Integer List Collection 
+// ************************************************---
+PXNeighboursList::PXNeighboursList(PXIntegerList* lists,int numlists)
+{
+  init();
+  for (int i=0;i<numlists;i++)
+    Add(&lists[i],i);
+}
+// ************************************************---
+PXNeighboursList::PXNeighboursList(PXNeighbours* neighbours,int numneighbours)
+{
+  init();
+  for (int i=0;i<numneighbours;i++)
+    Add(&neighbours[i],i);
+}
+// ************************************************---
+PXNeighboursList::PXNeighboursList()
+{
+  init();
+}
+// ************************************************---
+PXNeighboursList::~PXNeighboursList()
+{
+  DeleteAll();
+  delete topnode;
+}
+// ************************************************---
+void PXNeighboursList::init()
+{
+  numnodes=0;
+  lastnode=new PXNeighboursNode;
+  lastnode->next=NULL;
+  lastnode->previous=NULL;
+  lastnode->points=NULL;
+  lastnode->index=-1;
+  topnode=lastnode;
+  iterationnode=lastnode;
+  olditerationnode=lastnode;
+  hascache=0;
+}
+// ************************************************---
+void PXNeighboursList::DeleteAll()
+{
+  if (hascache)
+    cleanupCache();
+  if (numnodes==0)
+    return;
+  
+  numnodes=0;
+  while (lastnode->previous !=NULL)
+    {
+      if (lastnode->points!=NULL)
+	delete lastnode->points;
+      lastnode->index=-1;
+      lastnode->points=NULL;
+      lastnode=lastnode->previous;
+      if (lastnode->next!=NULL)
+	delete lastnode->next;
+      lastnode->next=NULL;
+    }
+  lastnode=topnode;
+  iterationnode=lastnode;
+  olditerationnode=lastnode;
+}
+// ************************************************---
+void PXNeighboursList::GotoEnd()
+{
+  iterationnode=lastnode->previous;
+}
+// ************************************************---
+void PXNeighboursList::Rewind()
+{
+  iterationnode=topnode;
+}
+// ************************************************---
+void PXNeighboursList::storeIterationPointer()
+{
+  olditerationnode=iterationnode;
+}
+// ************************************************---
+void PXNeighboursList::popIterationPointer()
+{
+  iterationnode=olditerationnode;
+}
+// ************************************************---
+void PXNeighboursList::Next()
+{
+  if (iterationnode->next!=lastnode)
+      iterationnode=iterationnode->next;
+  else
+      iterationnode=topnode;
+}
+// ************************************************---
+void PXNeighboursList::Add(PXNeighboursNode* node)
+{
+  cleanupCache();
+  lastnode->index=node->index;
+  lastnode->points=new PXIntegerList();
+  (lastnode->points)->Copy(node->points);
+
+  lastnode->next=new PXNeighboursNode;
+  (lastnode->next->previous)=lastnode;
+  lastnode=lastnode->next;
+  lastnode->next=NULL;
+  lastnode->points=NULL;
+  lastnode->index=-1;
+  numnodes++;
+}
+// ************************************************---
+void PXNeighboursList::Add2(int p1,int p2,int externalindex)
+{
+  cleanupCache();
+  if (externalindex>=0)
+      lastnode->index=externalindex;
+  else
+      lastnode->index=numnodes;
+  lastnode->points=new PXIntegerList();
+  (lastnode->points)->Add(p1);
+  (lastnode->points)->Add(p2);
+  lastnode->next=new PXNeighboursNode;
+  (lastnode->next->previous)=lastnode;
+  lastnode=lastnode->next;
+  lastnode->next=NULL;
+  lastnode->points=NULL;
+  lastnode->index=-1;
+  numnodes++;
+
+
+}
+// ************************************************---
+void PXNeighboursList::AddN(int *p,int np,int externalindex)
+{
+  cleanupCache();
+  if (externalindex>=0)
+      lastnode->index=externalindex;
+  else
+      lastnode->index=numnodes;
+  lastnode->points=new PXIntegerList();
+  for (int i=0;i<np;i++)
+      (lastnode->points)->Add(p[i]);
+  lastnode->next=new PXNeighboursNode;
+  (lastnode->next->previous)=lastnode;
+  lastnode=lastnode->next;
+  lastnode->next=NULL;
+  lastnode->points=NULL;
+  lastnode->index=-1;
+  numnodes++;
+}
+// ************************************************---
+void PXNeighboursList::Add3(int p1,int p2,int p3,int externalindex)
+{
+  cleanupCache();
+  if (externalindex>=0)
+      lastnode->index=externalindex;
+  else
+      lastnode->index=numnodes;
+  lastnode->points=new PXIntegerList();
+  (lastnode->points)->Add(p1);
+  (lastnode->points)->Add(p2);
+  (lastnode->points)->Add(p3);
+  lastnode->next=new PXNeighboursNode;
+  (lastnode->next->previous)=lastnode;
+  lastnode=lastnode->next;
+  lastnode->next=NULL;
+  lastnode->points=NULL;
+  lastnode->index=-1;
+  numnodes++;
+
+}
+// ************************************************---
+void  PXNeighboursList::Copy(PXNeighboursList* other)
+{
+  DeleteAll();
+  other->Rewind();
+  for (int i=0;i<other->getnumnodes();i++)
+      {
+	Add(other->getcurrentnode());
+	other->Next();
+      }
+}
+// ************************************************---
+void PXNeighboursList::Add(PXIntegerList* list,int externalindex)
+{
+  cleanupCache();
+  if (externalindex>=0)
+      lastnode->index=externalindex;
+  else
+      lastnode->index=numnodes;
+  lastnode->points=new PXIntegerList();
+  (lastnode->points)->Copy(list);
+  lastnode->next=new PXNeighboursNode;
+  (lastnode->next->previous)=lastnode;
+  lastnode=lastnode->next;
+  lastnode->next=NULL;
+  lastnode->points=NULL;
+  lastnode->index=-1;
+  numnodes++;
+}
+// ************************************************---
+void PXNeighboursList::Add(PXNeighbours* element,int externalindex)
+{
+  cleanupCache();
+  if (externalindex>=0)
+      lastnode->index=externalindex;
+  else
+      lastnode->index=numnodes;
+  lastnode->points=new PXIntegerList();
+  for(int j=0;j<element->num;j++)
+      (lastnode->points)->Add(element->pt[j]);
+
+  lastnode->next=new PXNeighboursNode;
+  (lastnode->next->previous)=lastnode;
+  lastnode=lastnode->next;
+  lastnode->next=NULL;
+  lastnode->points=NULL;
+  lastnode->index=-1;
+  numnodes++;
+}
+// ************************************************---
+int PXNeighboursList::Save(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout)
+    {
+      int st=Save(fout);
+      fclose(fout);
+      return st;
+    }
+  return 0;
+}
+// ************************************************---
+int PXNeighboursList::Load(const char* fname)
+{
+  gzFile fin=gzsuffixopen(fname,"r");
+  if (fin)
+      {
+	int st=Load(fin);
+	gzclose(fin);
+	return st;
+      }
+  return 0;
+}
+// ************************************************---
+int PXNeighboursList::Save(FILE* fout)
+{
+  fprintf(fout,"#NeighbourList****************************************---\n");
+  Rewind();
+  fprintf(fout,"%d\n",numnodes);
+
+  for (int i=0;i<numnodes;i++)
+      {
+	fprintf(fout,"%d\t%d",iterationnode->index,(iterationnode->points)->getnumnodes());
+	(iterationnode->points)->Rewind();
+	for(int j=0;j<(iterationnode->points)->getnumnodes();j++)
+	    {
+	      fprintf(fout,"\t%d",(iterationnode->points)->getcurrent());
+	      (iterationnode->points)->Next();
+	    }
+	fprintf(fout,"\n");
+	Next();
+      }
+  Rewind();  
+  return 1;
+}
+
+// ************************************************---
+int PXNeighboursList::Load(gzFile fin)
+{
+  DeleteAll();
+  char* line=new char[1000];
+  gzgets(fin,line,200);
+  if (gzfindstringinstring(line,"#NeighbourList")==0)
+      {
+	delete [] line;
+	return 0;
+      }
+  
+  PXNeighbours* a=new PXNeighbours();
+  a->pt=new int[1000]; // Can't have more than 1000 neighbours here 
+  int num2;
+  gzgets(fin,line,200);
+  sscanf(line,"%d",&num2);
+  //  fprintf(stderr,"NeighboursList::Numel=%d\n",num2);
+  for (int i=0;i<num2;i++)
+      {
+	int temp,num,ind;
+	gzgets(fin,line,1000);
+	sscanf(line,"%d %d",&ind,&num);
+	//	fprintf(stderr,"%d %d : ",ind ,num);
+	a->num=num;
+
+	// Skip the first two numbers 
+	int po=0;
+	for (int lp=0;lp<2;lp++)
+	    {
+	      po=stringskipspace(line,po);
+	      po=stringskipnumber(line,po);
+	    }
+	
+	for(int j=0;j<num;j++)
+	  {	
+	      // Skip spaces before number 
+	      po=stringskipspace(line,po);
+	      sscanf(&line[po],"%d ",&temp);
+	      po=stringskipnumber(line,po);
+	      a->pt[j]=temp;
+	    }
+	//fscanf(fin,"\n");
+	//fprintf(stderr,"\n");
+	Add(a,ind);
+      }
+  delete [] a->pt;
+  delete [] line;
+  delete a;
+  //  fprintf(stderr,"List::Numnodes=%d,%d\n",numnodes,getnumnodes());
+  return 1;
+}
+// ************************************************---
+void  PXNeighboursList::Sort()
+{
+  Rewind();
+  for (int i=0;i<getnumnodes();i++)
+      {
+	(getcurrentnode()->points)->Sort();
+	Next();
+      }
+}
+// ************************************************---
+void PXNeighboursList::RemoveInvalid()
+{
+  cleanupCache();
+  //  fprintf(stderr,"\n Removing Invalid\n");
+  Rewind();
+  if (numnodes<1)
+      return;
+  while (iterationnode!=lastnode)
+      {
+	//fprintf(stderr,"Scanning to delete index =%d (%d)\n",iterationnode->index,numnodes);
+	if (iterationnode->index<0)
+	    {
+	      PXNeighboursNode* temp=iterationnode;
+	      if (iterationnode==topnode)
+		  {
+		    if (numnodes>1)
+			{
+			  topnode=iterationnode->next;
+			  delete iterationnode->points;
+			  delete iterationnode;
+			  iterationnode=topnode;
+			}
+		  }
+	      else
+		  {
+		    (iterationnode->previous)->next=(iterationnode->next);
+		    (iterationnode->next)->previous=(iterationnode->previous);
+		    iterationnode=iterationnode->next;
+		    delete temp->points;
+		    delete temp;
+		  }
+	      numnodes=numnodes-1;
+	    }
+	else
+	    iterationnode=iterationnode->next;
+      }
+  Rewind();
+  storeIterationPointer();
+  //  fprintf(stderr,"\n Removing Invalid done=%d\n",numnodes);
+}
+// ************************************************---
+void PXNeighboursList::generateCache()
+{
+  if (hascache)
+      cleanupCache();
+
+  //  fprintf(stderr,"Generating Cache\n");
+  c_numnodes=numnodes;
+  c_index=new int[c_numnodes];
+  c_flag=new int[c_numnodes];
+  c_buffer=new int[c_numnodes];
+  c_neighbours=new PXNeighbours[c_numnodes];
+  
+  Rewind();
+  
+  for (int i=0;i<c_numnodes;i++)
+      {
+	c_index[i]=iterationnode->index;
+	c_neighbours[i].num=(iterationnode->points)->getnumnodes();
+	c_neighbours[i].pt=new int[c_neighbours[i].num];
+	(iterationnode->points)->Rewind();
+	for (int k=0;k<c_neighbours[i].num;k++)
+	    {
+	      c_neighbours[i].pt[k]=(iterationnode->points)->getcurrent();
+	      (iterationnode->points)->Next();
+	    }
+	c_flag[i]=0;
+	Next();
+      }
+  hascache=1;
+}
+// ************************************************---
+void PXNeighboursList::cleanupCache()
+{
+  if (!hascache)
+      return;
+
+  for (int i=0;i<c_numnodes;i++)
+      delete [] c_neighbours[i].pt;
+
+  delete [] c_neighbours;
+  delete [] c_index;
+  delete [] c_flag;
+  delete [] c_buffer;
+  c_numnodes=0;
+  hascache=0;
+}
+// ************************************************---
+void PXNeighboursList::updateCacheIndices()
+{
+  if (hascache && c_numnodes==numnodes)
+      {
+	Rewind();
+	for (int i=0;i<c_numnodes;i++)
+	    {
+	      c_index[i]=iterationnode->index;
+	      Next();
+	    }
+      }
+}
+// ************************************************---
+void PXNeighboursList::updateIndicesFromCache()
+{
+  if (hascache && c_numnodes==numnodes)
+      {
+	Rewind();
+	for (int i=0;i<c_numnodes;i++)
+	    {
+	      iterationnode->index=c_index[i];
+	      Next();
+	    }
+      }
+}
+// ************************************************---
+int  PXNeighboursList::cacheIndexConversion(int index)
+{
+  if (!hascache)
+      generateCache();
+
+  // In cases where all nodes is present this will give a hit first time
+  // else search 
+
+  if (index>=0 && index<c_numnodes)
+      if (c_index[index]==index)
+	  return index;
+
+  int i=0,found=0,ind=-1;
+  while(i<c_numnodes && found==0)
+      {
+	if (c_index[i]==index && c_index[i]!=-1)
+	    {
+	      found=1;
+	      ind=i;
+	    }
+	i++;
+      }
+  return ind;
+}
+// ************************************************---
+int PXNeighboursList::getrelationship(int pt1,int pt2,int max)
+{
+  // pt1, pt2 are internal indices i.e. 0..c_numnodes-1
+
+  if (!hascache)
+      generateCache();
+
+  // Trivial Case 
+  if (pt1==pt2)
+      return 0;
+
+  if (pt1<0 || pt1>=c_numnodes || pt2<0 || pt2>=c_numnodes)
+      return -1;
+
+  for (int i=0;i<c_numnodes;i++)
+      c_flag[i]=0;
+
+  int num_flagged=0,found=0;
+
+  // Starting Iteration 
+  int minbuffer=0,maxbuffer=1;
+  c_buffer[0]=pt1; // Start Looking from pt1;
+  c_flag[pt1]=1;
+  int distance=1;
+  num_flagged=1;
+  int debug=0;
+  /*if (pt1==0 && pt2==14)
+      debug=1;*/
+  int num_flaggedold=0;
+  
+  while(num_flagged<c_numnodes && found==0 && distance<max)
+      {
+	// Step 1 -- Look for pt2 in the neighbours of the points in numbuffer
+	int nextmaxbuffer=maxbuffer;
+	if (debug)
+	    fprintf(stderr,"\nBuffer %d:%d , num_flaggged=%d, distance=%d(%d)\n",
+		    minbuffer,maxbuffer,num_flagged,distance,max);
+	for(int j=minbuffer; j<maxbuffer; j++)
+	    {
+	      int current=c_buffer[j];
+	      if (debug)
+		  fprintf(stderr,"\t j=%d current=%d neighbours=%d\n",j,current,c_neighbours[current].num);
+
+	      for (int k=0;k<c_neighbours[current].num;k++)
+		  {
+		    int pt3=cacheIndexConversion(c_neighbours[current].pt[k]);
+		    if (debug)
+			fprintf(stderr,"\t\t found %d **** > %d \n",c_neighbours[current].pt[k],pt3);
+		    if (pt3!=-1)
+			{
+			  if (pt2==pt3)
+			      {
+				found=1;
+				// Break out of loops here 
+				k=c_neighbours[current].num;
+				j=maxbuffer;
+			      }
+			  else
+			      { // Add it to search array for next time 
+				if (c_flag[pt3]==0)
+				    {
+				      c_buffer[nextmaxbuffer]=pt3;
+				      c_flag[pt3]=-1;
+				      nextmaxbuffer++;
+				      num_flagged++;
+				    }
+			      }
+			}
+		  }
+	    }
+
+	if (!found)
+	    {
+	      distance++;            // Now looking one more scale 
+	      minbuffer=maxbuffer;
+	      maxbuffer=nextmaxbuffer;
+	      if (num_flagged==num_flaggedold)
+		  num_flagged=c_numnodes;
+	      else
+		  num_flaggedold=num_flagged;
+	      
+	    }
+      }
+  /*  fprintf(stderr,"pt1=%d, pt2=%d, distance=%d ,max=%d, num_flagged=%d\n",
+      pt1,pt2,distance,max,num_flagged);*/
+  
+  if (found==0 && distance!=max)
+      distance=-1;
+  
+  return distance;
+  
+}
+// ************************************************---
+int PXNeighboursList::tagconnectedto(int p,int maxrelationship)
+{
+  if (!hascache)
+      generateCache();
+  
+  p=cacheIndexConversion(p);
+  
+  if (p<0)
+      return -1;
+
+  int numconnected=0;
+  for (int i=0;i<c_numnodes;i++)
+      {
+	int dist=getrelationship(p,i,maxrelationship+1);
+	if (dist==-1 || dist>maxrelationship)
+	    c_index[i]=-1;
+	else
+	    numconnected++;
+	/*fprintf(stderr,"Distance from %-2d to %-2d (max=%2d) =%d index=%d\n",
+		p,i,maxrelationship+1,dist,c_index[i]);*/
+
+      }
+  //  updateIndicesFromCache();
+  return numconnected;
+}
+// ************************************************---
+int PXNeighboursList::getcentroid()
+{
+  if (!hascache)
+      generateCache();
+
+  int mindist=1000000000;
+  int bestnode=-1;
+
+  for (int i=0;i<c_numnodes;i++)
+      {
+	if (c_index[i]>=0)
+	    {
+	      int dist=0;
+	      for (int j=0;j<c_numnodes;j++)
+		  {
+		    if (c_index[j]>=0)
+			{
+			  int a=getrelationship(i,j);
+			  if (a<0)
+			      return -1;
+			  dist+=a;
+			}
+		  }
+	      if (dist<mindist)
+		  {
+		    mindist=dist;
+		    bestnode=i;
+		  }
+	    }
+      }
+  return c_index[bestnode];
+}
+// ************************************************---
+int PXNeighboursList::getcacheindex(int i)
+{
+  if (!hascache)
+      return -1;
+  
+  if (i<0 || i>=c_numnodes)
+      return -1;
+
+  return c_index[i];
+}
+
+// ************************************************---
+int PXNeighboursList::getcurrentindex()
+{ 
+  return iterationnode->index;
+}
+// ************************************************---
+int PXNeighboursList::getnumnodes()
+{ 
+  return numnodes;
+}
+// ************************************************---
+/*
+    Vector Classes
+
+
+*/
+// ************************************************---
+PX3Vector::PX3Vector()
+{
+  for (int ia=0;ia<=2;ia++)
+      x[ia]=0.0;
+}
+
+PX3Vector::PX3Vector(float a1,float a2,float a3)
+{
+  setvector(a1,a2,a3);
+}
+
+void PX3Vector::setvector(float a1,float a2,float a3)
+{
+  x[0]=a1; x[1]=a2; x[2]=a3;
+}
+
+float PX3Vector::getlength()
+{
+  float sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+      sum+=pow(x[ia],float(2.0));  
+  return sqrt(sum);
+}
+
+float PX3Vector::getdistance(PX3Vector* other)
+{
+  float sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+      sum+=pow(x[ia]-other->x[ia],float(2.0));  
+  return sqrt(sum);
+}
+
+void  PX3Vector::copy(PX3Vector* other)
+{
+  for (int ia=0;ia<=2;ia++)
+      x[ia]=other->x[ia];
+}
+ 
+float PX3Vector::normalize()
+{
+  float d=getlength();
+  if (d!=0.0)
+      {
+	for (int ia=0;ia<=2;ia++)
+	    x[ia]/=d;
+      }
+  return d;
+}
+  
+float PX3Vector::dotwith(PX3Vector* other)
+{
+  float sum=0.0;
+  for (int ia=0;ia<=2;ia++)
+      sum+=x[ia]*other->x[ia];
+  return sum;
+}
+
+PX3Vector* PX3Vector::crosswith(PX3Vector* other)
+{
+  PX3Vector* cross=new PX3Vector(0.0,0.0,0.0);
+
+  for (int ia=0;ia<=2;ia++)
+      {
+	int n1=Icyclic(ia+1,3);
+	int n2=Icyclic(ia+2,3);
+	cross->x[ia]=this->x[n1]*other->x[n2] - this->x[n2]*other->x[n1];
+      }
+  return cross;
+}
+
+void PX3Vector::crosswithoverwrite(PX3Vector* other)
+{
+  float cr[3];
+
+  for (int ia=0;ia<=2;ia++)
+      {
+	int n1=Icyclic(ia+1,3);
+	int n2=Icyclic(ia+2,3);
+	cr[ia]=this->x[n1]*other->x[n2] - this->x[n2]*other->x[n1];
+      }
+
+  setvector(cr[0],cr[1],cr[2]);
+}
+
+void PX3Vector::subtract(PX3Vector* other,float factor)
+{
+  for (int ia=0;ia<=2;ia++)
+      x[ia]=x[ia]-factor*other->x[ia];
+}
+
+void PX3Vector::add(PX3Vector* other,float factor,float thisfactor)
+{
+  for (int ia=0;ia<=2;ia++)
+      x[ia]=thisfactor*x[ia]+factor*other->x[ia];
+}
+
+// ------------------------------------------------------------------------------------------------
+PX2Vector::PX2Vector()
+{
+  for (int ia=0;ia<=1;ia++)
+      x[ia]=0.0;
+}
+
+PX2Vector::PX2Vector(float a1,float a2)
+{
+  setvector(a1,a2);
+}
+
+void PX2Vector::setvector(float a1,float a2)
+{
+  x[0]=a1; x[1]=a2; 
+}
+float PX2Vector::getlength()
+{
+  float sum=0.0;
+  for (int ia=0;ia<=1;ia++)
+      sum+=pow(x[ia],float(2.0));  
+  return sqrt(sum);
+}
+
+float PX2Vector::getdistance(PX2Vector* other)
+{
+  float sum=0.0;
+  for (int ia=0;ia<=1;ia++)
+      sum+=pow(x[ia]-other->x[ia],float(2.0));  
+  return sqrt(sum);
+}
+
+void  PX2Vector::copy(PX2Vector* other)
+{
+  for (int ia=0;ia<=1;ia++)
+      x[ia]=other->x[ia];
+}
+ 
+float PX2Vector::normalize()
+{
+  float d=getlength();
+  if (d!=0.0)
+      {
+	for (int ia=0;ia<=1;ia++)
+	    x[ia]/=d;
+      }
+  return d;
+}
+  
+float PX2Vector::dotwith(PX2Vector* other)
+{
+  float sum=0.0;
+  for (int ia=0;ia<=1;ia++)
+      sum+=x[ia]*other->x[ia];
+  return sum;
+}
+
+PX2Vector* PX2Vector::crosswith(PX2Vector* other)
+{
+  PX2Vector* cross=new PX2Vector(0.0,0.0);
+
+  for (int ia=0;ia<=1;ia++)
+      {
+	int n1=Icyclic(ia+1,3);
+	int n2=Icyclic(ia+2,3);
+	cross->x[ia]=this->x[n1]*other->x[n2] - this->x[n2]*other->x[n1];
+      }
+  return cross;
+}
+
+
+
diff --git a/bioimagesuite30_src/numerics/pxgeometrystruct.h b/bioimagesuite30_src/numerics/pxgeometrystruct.h
new file mode 100644
index 0000000..1b0ac7d
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxgeometrystruct.h
@@ -0,0 +1,315 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pxgeometrystruct.h 
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : pxgeometrystruct.h
+
+_Description : Various Utility Routines for Geometrical Entities like points,neighbours,triangles,
+               tetrahedra
+
+	       
+	       
+
+_Call : 
+
+     
+_References : 
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in May 22nd 1995
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+#ifndef _PXGeometryStruct
+#define  _PXGeometryStruct
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include "bis_znzlib.h"
+
+// -------------------------------------------
+//  Geometry Classes
+// -------------------------------------------
+
+class PX3Vector {
+
+public:
+  float x[3];
+  
+  PX3Vector();
+  PX3Vector(float a1,float a2,float a3);
+  void setvector(float a1,float a2,float a3);
+  float getlength();
+  float getdistance(PX3Vector* other);
+  void  copy(PX3Vector* other);
+  float normalize();
+  
+  float dotwith(PX3Vector* other);
+  PX3Vector* crosswith(PX3Vector* other);
+
+  void crosswithoverwrite(PX3Vector* other);
+  void subtract(PX3Vector* other,float factor=1.0);
+  void add(PX3Vector* other,float factor=1.0,float thisfactor=1.0);
+  
+};
+
+struct PX2Vector {
+  float x[2];
+  PX2Vector();
+  PX2Vector(float a1,float a2);
+  void setvector(float a1,float a2);
+  float getlength();
+  float getdistance(PX2Vector* other);
+  void copy(PX2Vector* other);
+  float normalize();
+  
+  float dotwith(PX2Vector* other);
+  PX2Vector* crosswith(PX2Vector* other);
+
+};
+
+
+// ---------------------------------------------------
+//  Basic Data Stuctures 
+// ---------------------------------------------------
+struct PXTriangulatedStackPoint {
+  int   index;   
+  float x[3];
+  float nx[3];
+  float k[2];
+};
+
+struct PXNeighbours {
+  int  num;
+  int* pt;
+};
+
+struct PXNodeCollection {
+  int numnodes;
+  int   *stackno,*pointno;
+  PX3Vector* x;
+  PX3Vector* dx;
+  PX2Vector* k;
+};
+
+struct PXDispPair {
+  float x1,y1,z1,x2,y2,z2;
+};
+
+struct PXDisplacementCollection {
+  int numframes;
+  int numdisplacements;
+  int *index;
+  float *x,*y,*z;
+  float *conf1,*conf2;
+  float *mag;
+};
+
+struct PXElementOutputInfo {
+  int numelement;
+  float e11,e12,e13,e22,e23,e33,evol;
+};
+
+struct PXMaterialModel {
+  int modeltype;
+  int nlgeom;
+  int numparameters;
+  float *parameter;
+};
+
+// Accessory Structures for on-line processing
+// -------------------------------------------
+struct PXElementOutput
+{
+  unsigned char flag;
+  float evol;
+  float e11,e22,e33,e12,e13,e23;
+};
+
+struct PXNodeOutput
+{
+  unsigned char flag;
+  float estu1,estu2,estu3;
+  float currentu1,currentu2,currentu3;
+  unsigned char cache;
+  float nx,ny,nz;
+};
+
+struct PXTetrahedron {
+  int index;
+  int p[4];
+};
+
+struct PXTriangle {
+  int   index;
+  float c[3];
+  int   p[3];
+};
+
+
+struct PXIntegerNode {
+  int value;
+  PXIntegerNode* next;
+  PXIntegerNode* previous;
+};
+
+// ---------------------------------------------------
+// Collection Classes
+// ---------------------------------------------------
+
+class PXIntegerList {
+
+protected:
+  
+  PXIntegerNode    *topnode,*lastnode,*iterationnode;
+  int  numnodes;
+
+
+public:
+  PXIntegerList();
+  ~PXIntegerList();
+  void init();
+  
+  void  Rewind();
+  void  Next(); // circular 
+  void  Add(int pt);
+  void  AddNonDuplicate(int pt,int exclude=-32767);
+  void  DeleteAll();
+  void  Copy(PXIntegerList* other);
+  void  Copy(PXTriangle* tri);
+  int   CopyTo(PXTriangle* tri);
+
+  void Sort(PXIntegerList* linked=NULL);
+
+  // Comparisons
+  int  isSame(PXIntegerList *other);
+  int  isSamePresorted(PXIntegerList* other);
+  int  numberinCommon(PXIntegerList* other);
+  int  numberinCommon(int* points,int numpoints);
+
+  void  eliminateDuplicates(int exclude=-32767);
+ 
+  PXIntegerNode*  getcurrentnode();
+  int   getcurrent();
+  int   getnumnodes();
+};
+
+
+struct PXNeighboursNode {
+  int  index;
+  PXIntegerList*    points;
+  PXNeighboursNode* next;
+  PXNeighboursNode* previous;
+};
+
+
+class PXNeighboursList {
+
+protected:
+  
+  PXNeighboursNode *topnode,*lastnode,*iterationnode,*olditerationnode;
+  int  numnodes;
+
+  int  hascache,*c_index,c_numnodes,*c_flag,*c_buffer;
+  PXNeighbours* c_neighbours;
+
+public:
+  PXNeighboursList();
+  PXNeighboursList(PXNeighbours* neighbours,int numneighbours);
+  PXNeighboursList(PXIntegerList* lists,int numlists);
+  ~PXNeighboursList();
+
+  void init();
+  
+  void  Rewind();
+  void  GotoEnd();
+  void  Next(); // circular 
+  void  Add(PXNeighbours* element,int externalindex);
+  void  Add(PXIntegerList* list,int externalindex);
+  void  Add2(int p1,int p2,int externalindex);
+  void  Add3(int p1,int p2,int p3,int externalindex);
+  void  AddN(int *p,int np,int externalindex);
+  void  Add(PXNeighboursNode* node);
+  void  DeleteAll();
+  void  RemoveInvalid();
+  void  Sort();
+
+  void  Copy(PXNeighboursList* other);
+  void  storeIterationPointer();
+  void  popIterationPointer();
+  
+  PXNeighboursNode* getcurrentnode()  { return iterationnode;}
+
+  int  getcurrentindex();
+  int  getnumnodes();    
+
+  int  Save(FILE* fout);
+  int  Save(const char* fname);
+  int  Load(gzFile fout);
+  int  Load(const char* fname);
+
+  // Connectivity Code, uses Cache
+  // -----------------------------
+  int  tagconnectedto(int p,int maxrelationship=1000);  
+  int  getcentroid();
+  int  getrelationship(int i,int j,int max=1000);
+  int  cacheIndexConversion(int index);
+  int  getcacheindex(int i);
+  void updateIndicesFromCache();
+  void updateCacheIndices();
+
+protected:
+  void generateCache();
+  void cleanupCache();
+
+  
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/pximage.cpp b/bioimagesuite30_src/numerics/pximage.cpp
new file mode 100644
index 0000000..d4534c9
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pximage.cpp
@@ -0,0 +1,1540 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+#include "pximage.h"
+#include <fcntl.h>
+#include <stdlib.h>
+#include "pxfloatmatrix.h"
+
+#ifndef _WIN32
+#include <unistd.h>
+#else
+#include <io.h>
+#endif
+
+#ifdef __CYGWIN__
+#include <unistd.h>
+#endif
+
+#ifdef __APPLE__
+ #include "/usr/include/unistd.h"
+#endif
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July 1995   papad at noodle.med.yale.edu
+
+   See pximage.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+//-----------------------------------------------------------------------
+float PXImage::gradient_mask[5]={-1.0/12.0 , 8.0/12.0 ,0.0 ,-8.0/12.0 ,1.0/12.0};
+//-----------------------------------------------------------------------
+PXImage::PXImage(int x ,int y)                
+{
+  xsize=x;   ysize=y;  status=0;
+  filename=new char[1];
+  setfilename("default.grl16"); 
+  image=new unsigned short[xsize*ysize]; 
+  status=1;
+}
+
+//-----------------------------------------------------------------------
+
+PXImage::PXImage(const char* f,int x ,int y)  // Normal Constructor II;
+{
+  xsize=x;  ysize=y;  status=0;
+  image=new unsigned short[xsize*ysize]; 
+  filename=new char[1];
+  setfilename(f);
+  CheckFilename(filename,2);
+}
+
+//-----------------------------------------------------------------------
+
+PXImage::PXImage(const char* f,int pxconst)           // Load Constrctor;
+	
+{
+  xsize=0;   ysize=0;  maxgrayscale=0;    status=0;		
+  filename=new char[1];
+
+  if (pxconst==PXIm_Scil)
+      {
+	char *test=new char[256];
+	setfilename(f,1);
+	sprintf(test,"%s.ics",filename);
+	CheckFilename(test,1);                // Check Header File First;
+	if (status==1)
+	    {
+	      sprintf(test,"%s.ids",filename); // Check Data File;
+	      CheckFilename(test,1);
+	      if (status==1) LoadScil();
+	    }
+	delete [] test;
+      }
+  else 
+      {
+	setfilename(f);
+	CheckFilename(filename,1);
+	if (status==1)
+	    {
+	      switch (pxconst)
+		  {
+		  case PXIm_Pgm:
+		    LoadPgm();   break;
+		  case PXIm_grl:
+		    LoadGrl(16); break;
+		  case PXIm_grl8:
+		    LoadGrl(8);  break;
+		  }
+	    }
+      }
+}
+
+//-----------------------------------------------------------------------
+
+PXImage::PXImage(PXImage* oldimage)
+{
+  filename=new char[1];
+  status=0;
+  xsize=oldimage->getsizex();    
+  ysize=oldimage->getsizey();
+  setfilename(oldimage->getfilename());
+  image=new unsigned short[xsize*ysize]; 
+  
+  for(int i=0;i<oldimage->getsizex();i++)
+      for(int j=0;j<oldimage->getsizey();j++)
+	  setpixel(i,j,oldimage->getpixel(i,j));
+  
+  SetMaxgrayscale();   
+  status=oldimage->isvalid();
+}
+ 
+//-----------------------------------------------------------------------
+
+PXImage::PXImage(PXImage* oldimage,PXFloatMatrix* kernel)
+     // Convolution Constructor
+
+{
+  filename=new char[1];
+  xsize=oldimage->getsizex();            
+  ysize=oldimage->getsizey();
+  PXFloatMatrix* ResultsImage= new PXFloatMatrix(oldimage->getsizex(),
+						 oldimage->getsizey());
+  for(int ia=0;ia<xsize;ia++)
+      for(int ja=0;ja<ysize;ja++)
+	  ResultsImage->setpixel(ia,ja,0.0);
+  
+  float sum=0.0;
+  
+  fprintf(stderr,"Doing convolution ...");
+  for(int i=kernel->getradiusx();
+      i<(ResultsImage->getsizex()-kernel->getradiusx());i++)
+      for(int j=kernel->getradiusy()+1;
+	  j<(ResultsImage->getsizey()-kernel->getradiusy()-1);j++)
+	  {
+	    sum=0.0;
+	    for(int column=-kernel->getradiusx();
+		column<=kernel->getradiusx();column++)
+		for(int row=-kernel->getradiusy();
+		    row<=kernel->getradiusy();row++)
+		    {
+		      sum=sum+((float)(oldimage->getpixel(i+column,j+row))*
+			       kernel->getpixel(kernel->getradiusx()-column,
+					kernel->getradiusy()-row));
+		    }
+	    ResultsImage->setpixel(i,j,sum);
+	  }
+  fprintf(stderr,"\n");
+  ConvFloat(ResultsImage);              delete ResultsImage;
+  setfilename(oldimage->getfilename());
+ }
+
+//-----------------------------------------------------------------------
+PXImage::PXImage(unsigned const char* img,int x ,int y)   
+{
+  filename=new char[1];
+  xsize=x;   ysize=y;  status=0;
+  setfilename("default.grl16"); 
+  image=new unsigned short[xsize*ysize]; 
+  for (int i=0;i<xsize;i++)
+      for (int j=0;j<ysize;j++)
+	  setpixel(i,j,img[i+j*xsize]);
+  status=1;
+}
+
+//-----------------------------------------------------------------------
+
+PXImage::~PXImage()
+
+{
+  delete [] image;
+  delete [] filename;
+}
+
+//-----------------------------------------------------------------------
+void PXImage::setfilename(const char * fname,int removesuffix)
+{
+  
+  if (filename)
+      delete [] filename;
+  
+  if (removesuffix)
+      {
+	filename=eatsuffix(fname);
+      }
+  else
+      {
+	filename=new char[strlen(fname)];
+	strcpy(filename,fname);
+      }
+}
+
+
+
+//-----------------------------------------------------------------------
+
+void PXImage::ConvFloat(PXFloatMatrix* fim)
+{
+  xsize=fim->getsizex();                 ysize=fim->getsizey();
+  float fmax=-1e+10,fmin=1e+10;
+  
+  for(int ii=0;ii<xsize;ii++)
+    for(int jj=0;jj<ysize;jj++)
+      {
+	if (fim->getpixel(ii,jj)>fmax) fmax=fim->getpixel(ii,jj);
+	if (fim->getpixel(ii,jj)<fmin) fmin=fim->getpixel(ii,jj);
+      }
+  
+  image=new unsigned short[xsize*ysize]; 
+  unsigned short temp;
+  for(int i=0;i<xsize;i++)
+    for(int j=0;j<ysize;j++)
+      {
+	temp=(unsigned short)((fim->getpixel(i,j)-fmin)*
+			      (65535.0/(fmax-fmin)));
+	setpixel(i,j,temp);
+      }
+  status=1;
+  SetMaxgrayscale();  
+}
+//-----------------------------------------------------------------------
+// Return texture mapping code
+//-----------------------------------------------------------------------
+
+unsigned char PXImage::adjust(float px,float gamma)
+{ 
+  float max=(float)maxgrayscale;
+  float xf=px/max;
+  xf=pow((double)xf,1.0/(double)gamma);
+  xf=xf*255.0;
+  return ((unsigned char)xf);
+}
+
+// ----------------------------------------------------------------------
+unsigned char* PXImage::getslice(float gamma,int numbytes)
+{
+  SetMaxgrayscale();
+  numbytes=Irange(numbytes,1,2);
+  unsigned char *imagexy=new unsigned char[getsizex()*getsizey()*numbytes];
+  for (int iy=0;iy<getsizey();iy++)
+      for (int ix=0;ix<getsizex();ix++)
+	  {
+	    imagexy[ix*numbytes+iy*getsizex()*numbytes]=adjust(float(getpixel(ix,iy)),gamma);
+	    if (numbytes==2)
+		imagexy[ix*numbytes+iy*getsizex()*numbytes+1]=255;
+	  }
+  return imagexy;
+}
+// ----------------------------------------------------------------------
+unsigned char* PXImage::getpaddedslice(int &width,int &height, float gamma)
+{
+  int xs=2;
+  while (xs<getsizex()) 
+      xs=2*xs;
+  
+  int ys=2;
+  while (ys<getsizey())
+      ys=2*ys;
+
+  unsigned char *oldslice=getslice(gamma);
+  unsigned char *texture=new unsigned char[xs*ys];
+  for (int j=0;j<ys;j++)
+      for (int i=0;i<xs;i++)
+	  {
+	    texture[i+j*xs]=0;
+	    if (j<getsizey() && i<getsizex())
+		texture[i+j*xs]=oldslice[i+j*getsizex()];
+	  }
+  delete [] oldslice;
+  width=xs;
+  height=ys;
+  return texture;
+}
+// ----------------------------------------------------------------------
+unsigned char* PXImage::scaleslice(int &width,int &height,unsigned char* oldslice,int numbytes,
+				   int scalex,int scaley)
+{
+  numbytes=Irange(numbytes,1,2);
+  scalex=Irange(scalex,1,3);
+  scaley=Irange(scaley,1,3);
+
+  if (scalex==3) scalex=4;
+  if (scaley==3) scaley=4;
+
+  int xs=2;
+  while (xs<width) 
+      xs=2*xs;
+  
+  int ys=2;
+  while (ys<height)
+      ys=2*ys;
+  
+  if (scalex==1 && scaley==1)
+      {
+	int shiftx=(xs-width)/2;
+	int shifty=(ys-height)/2;
+	unsigned char *texture=new unsigned char[xs*ys*numbytes];
+	for (int j=0;j<ys;j++)
+	    for (int i=0;i<xs;i++)
+		{
+		  if (numbytes==1)
+		      {
+			texture[i+j*xs]=0;
+			if (j>=shifty && j<(height+shifty) && 
+			    i>=shiftx && i<(width+shiftx))
+			    texture[i+j*xs]=oldslice[(i-shiftx)+(j-shifty)*width];
+		      }
+		  else
+		      {
+			texture[i*numbytes+j*xs*numbytes]=255;
+			if (j>=shifty && j<(height+shifty) && 
+			    i>=shiftx && i<(width+shiftx))
+			    {
+			      texture[i*numbytes+j*xs*numbytes]=
+				  oldslice[(i-shiftx)*numbytes+(j-shifty)*width*numbytes];
+			      texture[i*numbytes+j*xs*numbytes+1]=
+				  oldslice[(i-shiftx)*numbytes+(j-shifty)*width*numbytes+1];
+			    }
+			else
+			    texture[i*numbytes+j*xs*numbytes+1]=0;
+		      }
+		}
+	width=xs;
+	height=ys;
+	return texture;
+      }
+  else
+      {
+	int shiftx=(xs-width)/2;
+	int shifty=(ys-height)/2;
+
+	/*fprintf(stderr,"In xs=%d ys=%d scalex=%d scaley=%d shiftx=%d shifty=%d\n",
+		xs,ys,scalex,scaley,shiftx,shifty);*/
+
+	xs=xs/scalex; 
+	ys=ys/scaley;
+
+	unsigned char *texture=new unsigned char[xs*ys*numbytes];
+
+	/*fprintf(stderr,"Out xs=%d ys=%d scalex=%d scaley=%d shiftx=%d shifty=%d\n",
+		xs,ys,scalex,scaley,shiftx,shifty);*/
+
+	for (int j=0;j<ys;j++)
+	    {
+	      int tj=j*scaley;
+	      for (int i=0;i<xs;i++)
+		  {
+		    int ti=i*scalex;
+		    if (numbytes==1)
+			{
+			  texture[i+j*xs]=0;
+			  /*if (i==xs/2 && j==ys/2)
+			    fprintf(stderr,"Point: i,j=(%d,%d) ti,tj=(%d,%d)(xs=%d,ys=%d)\n",i,j,ti,tj,xs,ys);
+			    */
+			  if (tj>=shifty && tj<(height+shifty) && 
+			      ti>=shiftx && ti<(width+shiftx))
+			      {
+				int sum=0;
+				for (int ia=0;ia<scalex;ia++)
+				    for (int ib=0;ib<scaley;ib++)
+					{
+					  int ix=Irange(ti+ia-shiftx,0,width-1);
+					  int iy=Irange(tj+ib-shifty,0,height-1);
+					  /*if (i==xs/2 && j==ys/2)
+					    fprintf(stderr,"Adding (%d,%d)\n",ix,iy);*/
+					  sum+=oldslice[ix+iy*width];
+					}
+				texture[i+j*xs]=int(float(sum)/float(scalex*scaley));
+			      }
+			}
+		    else
+			{
+			  texture[i*numbytes+j*xs*numbytes]=255;
+			  if (tj>=shifty && tj<(height+shifty) && 
+			      ti>=shiftx && ti<(width+shiftx))
+			      {
+				int sum=0;
+				for (int ia=0;ia<scalex;ia++)
+				    for (int ib=0;ib<scaley;ib++)
+					{
+					  int ix=Irange(ti+ia-shiftx,0,width-1);
+					  int iy=Irange(tj+ib-shifty,0,height-1);
+					  sum+=oldslice[(ix+iy*width)*numbytes];
+					  if (ia==0 && ib==0)
+					      texture[i*numbytes+j*xs*numbytes+1]=
+						  oldslice[(ix+iy*width)*numbytes+1];
+					}
+				texture[i*numbytes+j*xs*numbytes]=int(float(sum)/float(scalex*scaley));
+			      }
+			  else
+			      texture[i*numbytes+j*xs*numbytes+1]=0;
+			}
+		  }
+	    }
+	width=xs;
+	height=ys;
+	return texture;
+      }
+}
+//-----------------------------------------------------------------------
+// Interpolation Code
+//-----------------------------------------------------------------------
+float PXImage::getinterp(float x,float y)
+{
+  int ok=1;
+
+  if (x<0.0) 
+      { x=0.0; ok=0; }
+  if (y<0.0) 
+      { y=0.0; ok=0; }
+  if (x>=xsize-1) 
+      {	x=float(xsize-1); ok=0; }
+  if (y>=ysize-1) 
+      { y=float(ysize-1); ok=0; }
+
+
+  int x1=(int)x;
+  int y1=(int)y;
+
+  if (ok==0)
+      return (float)getpixel(x1,y1);
+
+  int x2=x1+1;
+  int y2=y1+1;
+
+  return ((float)getpixel(x1,y1)*(x2-x)*(y2-y)+
+	  (float)getpixel(x1,y2)*(x2-x)*(y-y1)+
+	  (float)getpixel(x2,y1)*(x-x1)*(y2-y)+
+	  (float)getpixel(x2,y2)*(x-x1)*(y-y1));
+
+  
+}
+int PXImage::getbilinear(unsigned short* px,float x,float y)
+{ 
+  int x1=(int)x,y1=(int)y;
+  int x2=x1+1,y2=y1+1;
+  return (int)((float)getpixel(px,x1,y1)*(x2-x)*(y2-y)+
+	       (float)getpixel(px,x1,y2)*(x2-x)*(y-y1)+
+	       (float)getpixel(px,x2,y1)*(x-x1)*(y2-y)+
+	       (float)getpixel(px,x2,y2)*(x-x1)*(y-y1));
+}
+
+int PXImage::getbilinear(float x,float y)
+{ 
+  int x1=(int)x,y1=(int)y;
+  int x2=x1+1,y2=y1+1;
+  
+  if (x1>=0 && y1>=0 && x2<xsize && y2<ysize)
+      return (int)((float)getpixel(x1,y1)*(x2-x)*(y2-y)+
+		   (float)getpixel(x1,y2)*(x2-x)*(y-y1)+
+		   (float)getpixel(x2,y1)*(x-x1)*(y2-y)+
+		   (float)getpixel(x2,y2)*(x-x1)*(y-y1));
+  else
+      return 0;
+}
+
+//-----------------------------------------------------------------------
+//           Return image in unsigned char array -- this has many uses
+//-----------------------------------------------------------------------
+
+unsigned char*  PXImage::getimage()
+{
+  SetMaxgrayscale();
+  float conv8bit= (255.0)/(float)maxgrayscale;
+  if (maxgrayscale<256) conv8bit=1.0;
+  unsigned char* eightbit=new unsigned char[xsize*ysize];
+  for (int j=0;j<ysize;j++)
+      for (int i=0;i<xsize;i++)
+	  eightbit[j*xsize+i]=(unsigned char)(conv8bit*(float)getpixel(i,j));
+  return eightbit;
+}
+
+
+//-----------------------------------------------------------------------
+//  I/O Related Code
+//-----------------------------------------------------------------------
+void PXImage::CheckFilename(const char* f,int mode)
+
+{
+  status=1;
+  switch (mode) 
+    {
+    case 1 :
+      {
+	FILE* fin=fopen(f,"r");
+	if (!fin) status=0;
+	fclose(fin);
+	break;
+      }
+    case 2 :
+      {
+	FILE* fout=fopen(f,"w");
+	if (!fout) status=0;
+	fclose(fout);
+	break;
+      }
+    }
+}
+
+//-----------------------------------------------------------------------
+/*
+		The  Format used for Float Images .grl16
+
+Magic     Number  (2-byte unsigned short)
+Number of Columns (2-byte unsigned short)
+Number of Rows    (2-byte unsigned short)
+Then data in 2-byte unsigned short
+
+For 8-bit data in 1-byte unsigned short .grl
+*/
+
+//-----------------------------------------------------------------------
+int PXImage::Load()
+{ 
+  return LoadGrl(16); 
+}
+
+int PXImage::Save(const char* fname)
+{
+  setfilename(fname);
+  return Save();
+}
+
+int PXImage::Save()
+{
+  return SaveGrl(16); 
+}
+
+// ---------------------------------------------------------------------
+int PXImage::LoadGrl(int bits)
+{
+  long n=0;
+  unsigned short test;
+  bits=8+8*(bits>8);
+
+  gzFile fp=gzsuffixopen(filename,"rb");
+  if (fp)
+    {
+      n += gzread(fp,&test,2);
+      if (test==PXIM)
+	{
+	    n += gzread(fp,&ysize,4);
+	    n += gzread(fp,&xsize,4);
+	    image=new unsigned short[ysize*xsize];      
+	    if (bits==16)
+		{
+		    n +=gzread(fp,&image[0],xsize*ysize*2);
+		    if (n==(ysize*xsize*2+10))
+			{
+			  fprintf(stderr,"File %s read (%d,grl16)\n",filename ,(int)n);
+			  SetMaxgrayscale();
+			  status=1;
+			}
+		    else
+			{
+			    if (n==(ysize*xsize+10))
+				{
+				    // Rewind File
+				  n=(long)gzseek(fp,10,0);
+				  bits=8; // It was really an 8-bit file
+
+				}
+			    else
+				{
+				  status=0;
+				  fprintf(stderr,"Failed Reading 16-bit grl file\n");
+				}
+			}
+		}
+	    
+	    if (bits==8)
+		{
+		  unsigned char* temp=new unsigned char[xsize*ysize];
+		  n +=gzread(fp,&temp[0],xsize*ysize);
+		  if (n==xsize*ysize+10)
+		      {
+			for (int j=0;j<ysize;j++)
+			    for (int i=0;i<xsize;i++)
+				setpixel(i,j,temp[j*xsize+i]);
+			fprintf(stderr,"File %s read (%d,grl)\n",filename ,(int)n);
+			SetMaxgrayscale();
+			status=1;
+		      }
+		  else
+		      {
+			fprintf(stderr,"Failed Reading 8-bit grl file\n");
+			status=0;
+		      }
+		  delete [] temp;
+	      }
+	}
+      else
+	  fprintf(stderr, "Not a grl file \n");
+      
+      gzclose(fp);
+    }
+  else 
+      {
+	fprintf(stderr, "File %s does not exist \n",filename);
+	status=0;
+      }
+  return status;
+}
+
+//-----------------------------------------------------------------------
+int PXImage::SaveGrl(const char* fname,int bits)
+{
+  setfilename(fname);
+  return SaveGrl(bits);
+}
+
+int PXImage::SaveGrl(int bits)
+{
+  long bytes=0;
+  gzFile fdf=gzsuffixopen(filename,"wb");
+  if (fdf)
+      {
+	unsigned short a=PXIM;
+	bytes +=gzwrite(fdf,&a,2);
+	bytes +=gzwrite(fdf,&ysize,4);
+	bytes +=gzwrite(fdf,&xsize,4);
+	
+	if (bits==16)
+	    bytes += gzwrite(fdf,&image[0],2*xsize*ysize);
+	if (bits==8)
+	    {
+	      SetMaxgrayscale();
+	      float conv8bit= (255.0)/(float)maxgrayscale;
+	      if (maxgrayscale<256) conv8bit=1.0;
+	      unsigned char* temp=new unsigned char[xsize*ysize];
+	      for (int j=0;j<ysize;j++)
+		  for (int i=0;i<xsize;i++)
+		      temp[j*xsize+i]=(unsigned char)(conv8bit*(float)getpixel(i,j));
+	      bytes += gzwrite(fdf,&temp[0],xsize*ysize);
+	      delete [] temp;
+	    }
+	fprintf(stderr,"Image saved in : %s (%d)\n", filename,(int)bytes);
+      }
+  gzclose(fdf);
+  return (bytes>0);
+}
+
+// -----------------------------------------------------------------------------
+//
+//       Binary File Read and Write         -- can avoid skip values
+//     
+//       bits=8 or 16     skip = ignore first skip skip*bits/2 bytes
+// -----------------------------------------------------------------------------
+
+int PXImage::LoadBin(int bits,int skip)
+{
+  long n=0;
+  bits=8+8*(bits>8);
+
+  gzFile fp=gzsuffixopen(filename,"rb");
+  if (fp)
+    {
+      if (skip>0)
+	{
+	  n=(long)gzseek (fp,skip,0);
+	  n=0;
+	}
+
+      if (bits==16)
+	  {
+	    n +=gzread(fp,&image[0],xsize*ysize*2);
+	    if (n==(ysize*xsize*2))
+		{
+		  SetMaxgrayscale();
+		  status=1;
+		}
+	    else
+		status=0;
+	  }
+      
+      if (bits==8)
+	  {
+	    unsigned char* temp=new unsigned char[xsize*ysize];
+	    n +=gzread(fp,&temp[0],xsize*ysize);
+	    if (n==xsize*ysize)
+		{
+		  for (int j=0;j<ysize;j++)
+		      for (int i=0;i<xsize;i++)
+			  setpixel(i,j,temp[j*xsize+i]);
+		  SetMaxgrayscale();
+		  status=1;
+		}
+	    else 
+		status=0;
+	    
+	    delete [] temp;
+	}
+      gzclose(fp);
+    }
+  else 
+      {
+	fprintf(stderr, "File %s does not exist \n",filename);
+	status=0;
+      }
+  return status;
+}
+
+
+//-----------------------------------------------------------------------
+int PXImage::SaveBin(const char* fname,int bits)
+{
+  setfilename(fname);
+  return SaveBin(bits);
+}
+
+int PXImage::SaveBin(int bits)
+{
+  
+  long bytes=0;
+  gzFile fdf=gzsuffixopen(filename,"rb");
+  if (fdf)
+    {
+      switch (bits)
+	  {
+	  case 32:
+	    {
+	      float* temp32=new float(xsize*ysize);
+	      for (int j=0;j<ysize;j++)
+		  for (int i=0;i<xsize;i++)
+		      temp32[j*xsize+i]=float(getpixel(i,j));
+	      bytes += gzwrite(fdf,temp32,4*xsize*ysize);
+	      delete [] temp32;
+	    }
+	    break;
+	  case 16:
+	    bytes += gzwrite(fdf,&image[0],2*xsize*ysize);
+	    break;
+	  case 8:
+	    unsigned char* temp=getimage();
+	    bytes += gzwrite(fdf,temp,xsize*ysize);
+	    delete [] temp;
+	    break;
+	  }
+      fprintf(stderr,"Image saved in : %s(%d)", filename, (int)bytes);
+    }
+  gzclose(fdf);
+  return (bytes>0);
+}
+
+//-----------------------------------------------------------------------
+/*
+		The PGM Raw Format
+
+	The FIrst Line has the form :
+P5
+	This indicates the format code.
+	Then a number of comment lines follows.They all begin with a # i.e.
+#Creator XV.....
+	The next line contains the size in columns,rows for example
+640,480
+	The next line contains the maximum Graylevel value for example
+255
+	From there on the pixel Graylevel valus are stored in one
+	byte/pixel format, as they are scanned row by row
+
+*/
+//-----------------------------------------------------------------------
+int PXImage::LoadPgm()
+{
+  unsigned char c=0,d=0;
+  FILE* fin;
+  char line[200];
+  
+
+  // Get Header (Size)
+
+  fin=fopen(filename,"r");
+  fgets(line,100,fin);			// read in firstline
+  
+  int numpix=1;
+  int mode=-1;
+  status=0;
+
+  int st=strncmp(line, "P5",2);
+  if (st==0)
+      mode=1; // Normal PGM
+  else
+      {
+	st=strncmp(line, "P6",2);
+	if (st==0)
+	    {
+	      mode=3;
+	      numpix=3;
+	    }
+	else
+	    {
+	      st=strncmp(line,"P2",2);
+	      if (st==0)
+		  {
+		    mode=1;
+		    numpix=1;
+		  }
+	      else
+		  {
+		    st=strncmp(line,"P3",2);
+		    if (st==0)
+			{
+			  mode=2;
+			  numpix=3;
+			}
+		  }
+
+	    }
+      }
+  
+  if (mode>0)
+      {
+	do fgets(line,100,fin);		// read in comment lines
+	while ( line[0]=='#');
+	
+	while (c<255)
+	    {  c=line[d];
+	       ++d;
+	       if (c!=32) xsize=10*xsize+(c-48);
+	       else c=255; }	 
+	c=0;
+	while (c<255)
+	    { c=line[d];
+	      ++d;
+	      if ((c!='\n') && (c!=0) ) ysize=10*ysize+(c-48);
+	      else c=255;}
+	
+	fscanf(fin,"%d\n",&maxgrayscale);
+	
+	if (mode==1 || mode==3)
+	    {
+	      fclose(fin);
+
+	      if (ysize>0 && xsize>0 && maxgrayscale>0 && 
+		  xsize<2048 && ysize<2048 && maxgrayscale<256)
+		  {
+		    int n=0;
+		    gzFile fp=gzsuffixopen(filename,"rb");
+		    n=(int)gzseek (fp,0,2);
+		    n=n-xsize*ysize*numpix;
+		    unsigned char* pp=new unsigned char[xsize*ysize*numpix];
+		    
+		    // Rewind back to top of header
+		    n=(int)gzseek(fp,n,0);
+		    n=(int)gzread(fp,&pp[0],xsize*ysize*numpix);
+		    int ng=0;
+		    if (n==xsize*ysize*numpix)
+			{
+			  image=new unsigned short[xsize*ysize]; 
+			  for (int j=0;j<ysize;j++)
+			      for (int i=0;i<xsize;i++)
+				  {
+				    int offset=j*xsize*numpix+i*numpix;
+				    if (numpix==1)
+					{
+					  setpixel(i,j,pp[offset]);
+					}
+				    else
+					{ // Get intensity from color image 
+					  if (pp[offset]==pp[offset+1] && pp[offset]==pp[offset+2])
+					      setpixel(i,j,Irange(pp[offset],0,255));
+					  else
+					      setpixel(i,j,0);
+					}
+				  }
+			  if (numpix==1)
+			      fprintf(stderr,"Image read from %s (%d,.pgm)\n",filename,n);
+			  else
+			      fprintf(stderr,"Image read from %s (%d(%d,max=%d),.ppm)\n",filename,n,ng,
+				      maxgrayscale);
+			  SetMaxgrayscale();
+			  status=1;
+			}
+		    else 
+			status=0;
+		    delete [] pp;
+		  }
+	    }
+	else
+	    {
+	      if (ysize>0 && xsize>0 && maxgrayscale>0 && 
+		  xsize<2048 && ysize<2048 && maxgrayscale<65536)
+		  {
+		    int d[3],ng=0;
+		    image=new unsigned short[xsize*ysize]; 
+		    for (int j=0;j<ysize;j++)
+			for (int i=0;i<xsize;i++)
+			    {
+			      if (numpix==1)
+				  {
+				    fscanf(fin,"%d",&d[0]);
+				    setpixel(i,j,d[0]);
+				  }
+			      else
+				  {
+				    for (int k=0;k<3;k++)
+					fscanf(fin,"%d",&d[k]);
+				    if (d[0]==d[1] && d[0]==d[2])
+					{
+					  setpixel(i,j,d[0]);
+					  ng++;
+					}
+				    else
+					setpixel(i,j,0);
+				  }
+			    }
+		    if (maxgrayscale>255)
+			{
+			  for (int j=0;j<ysize;j++)
+			      for (int i=0;i<xsize;i++)
+				  setpixel(i,j,getpixel(i,j)/256);
+			  maxgrayscale/=256;
+			}
+
+		    if (numpix==1)
+			fprintf(stderr,"Image read from %s (%d,.pgm-ascii)\n",filename,xsize*ysize);
+		    else
+			fprintf(stderr,"Image read from %s (%d(%d),.ppm-ascii)\n",filename,xsize*ysize,ng);
+		    status=1;
+		  }
+	      fclose(fin);
+	    }
+      }
+  // If not try grl format first 16-bit then 8-bit
+  // ---------------------------------------------
+  if (status==0)
+      {
+	fprintf(stderr,"Not a pgm file, trying grl\n");
+	return LoadGrl(16); 
+      }
+
+  return status;
+}
+
+
+//-----------------------------------------------------------------------
+int PXImage::SavePgm(const char* fname)
+{
+  setfilename(fname);
+  return SavePgm();
+}
+
+int PXImage::SavePgm()
+{
+  int st=0;
+  SetMaxgrayscale();
+  FILE* fout=fopen(filename,"w");
+    
+  if (fout)
+      {
+	fprintf(fout,"P5\n");				// Write Header
+	fprintf(fout,"# Saved from PXImage::SavePgm\n");
+	fprintf(fout,"%d %d\n",xsize,ysize);
+	fprintf(fout,"255\n");
+	fclose(fout);
+	
+	
+	int fp=open(filename,O_RDWR,0);
+	lseek(fp,0,2);
+	unsigned char* temp=getimage();
+	int n=(int)write(fp,temp,xsize*ysize);
+	delete [] temp;
+	fprintf(stderr, "Image saved in : %s (%d,pgm)\n" , filename,n);
+	st=1;
+      }
+
+  return st;
+}
+
+//-----------------------------------------------------------------------
+/*
+		The ScilImage Format
+
+Header File .ics
+
+ics_version     1.0
+filename        exn2
+layout  parameters      3
+layout  order   bits    x       y
+layout  sizes   8       256     256
+layout  coordinates     video
+layout  significant_bits        8
+representation  format  integer
+representation  sign    unsigned
+representation  SCIL_TYPE       g2d
+
+Strategy for loading -- first pen header file name in comment field
+Extract bits,x,y
+Read in Data file
+
+*/
+//-----------------------------------------------------------------------
+int PXImage::LoadScil()
+{
+
+  char line[256],l1[25],l2[25];
+  int c=0,numbits=8,n=0;
+ 
+  sprintf(line,"%s.ics",filename);
+  FILE* fin=fopen(line,"r");
+  fgets(line,200,fin);			// read in firstline - blank;
+  fgets(line,200,fin);			// read in 2nd line ;
+  fgets(line,200,fin);			// read in 3rd line ;
+  fscanf(fin,"%20s %20s %d\n",l1,l2,&c);
+  status=0;
+  if (c==3)
+    {
+      fgets(line,200,fin);                 // layout order bits x y;
+      fscanf(fin,"%s %s %d %d %d",l1,l2,&numbits,&xsize,&ysize);
+      fclose(fin);
+      sprintf(line,"%s.ids",filename);
+      gzFile fp=gzsuffixopen(line,"rb");
+      if (fp)
+	{
+	  image=new unsigned short[xsize*ysize]; 
+	  
+	  if (numbits==8) 
+	    {
+	      unsigned char *bytedata=new unsigned char[xsize*ysize];
+	      n +=gzread(fp,&bytedata[0],xsize*ysize);
+	      for(int i=0;i<xsize;i++)
+		for(int j=0;j<ysize;j++)
+		  setpixel(i,j,bytedata[i*xsize+j]);
+	    delete [] bytedata;
+	      
+	    }
+	  if (numbits==16) 
+	    {
+	      unsigned short* worddata;
+	      worddata=new unsigned short[xsize*ysize];
+	      n +=gzread(fp,&worddata[0],xsize*ysize*2);
+	      for(int i=0;i<xsize;i++)
+		for(int j=0;j<ysize;j++)
+		  setpixel(i,j,worddata[i*xsize+j]);
+	      delete [] worddata;
+	    }
+	  
+	  gzclose(fp);
+	  SetMaxgrayscale();
+	  status=1;
+	}
+    }
+  else
+    {
+      fprintf(stderr, "Error! 3D - Scilimage file don't know how to handle it \n");
+    }
+  return status;
+}
+//-----------------------------------------------------------------------
+
+void PXImage::SetMaxgrayscale()
+{
+  unsigned short max=0;
+  
+  for (int i=0;i<(xsize*ysize);i++)
+    if (image[i]>max) max=image[i];
+  
+  maxgrayscale=max;
+}
+
+//-----------------------------------------------------------------------
+// Image Processing Related Code
+//-----------------------------------------------------------------------
+void PXImage::Invert()
+
+{
+  SetMaxgrayscale();  
+  for(int i=0;i<xsize;i++)
+      for(int j=0;j<ysize;j++)
+	  setpixel(i,j,getmaxgrayscale()-getpixel(i,j));
+}
+
+//-----------------------------------------------------------------------
+void PXImage::Grlscale(float grscale)
+
+{
+  long i;
+  SetMaxgrayscale();
+  float scaleby=(65535.0*grscale)/((float)maxgrayscale);
+
+  if ( scaleby<1.0 && grscale<1.0)
+    {
+      for (i=0;i<(xsize*ysize);i++)
+	image[i]=(int)((float)image[i]*scaleby);		
+    }
+  SetMaxgrayscale();
+
+}
+
+//-----------------------------------------------------------------------
+void PXImage::Zero(unsigned short px)
+
+{
+  for (long i=0;i<(xsize*ysize);i++)
+      image[i]=px;
+  SetMaxgrayscale();  
+
+}
+
+//-----------------------------------------------------------------------
+void PXImage::Threshold(float t)
+{
+  int threshold;
+  SetMaxgrayscale();
+  threshold=(int)(t*(float)maxgrayscale);
+
+  for (long i=0;i<(xsize*ysize);i++)
+    image[i]=maxgrayscale*(image[i]>threshold);
+  SetMaxgrayscale();  
+}
+
+//-----------------------------------------------------------------------
+
+void PXImage::Convolve(PXFloatMatrix* kernel)
+{
+  PXFloatMatrix* ResultsImage= new PXFloatMatrix(getsizex(),
+						 getsizey());
+  for(int ia=0;ia<xsize;ia++)
+    for(int ja=0;ja<ysize;ja++)
+      ResultsImage->setpixel(ia,ja,0.0);
+  
+  float sum=0.0;
+  
+  fprintf(stderr, "Doing convolution ...");
+  for(int i=kernel->getradiusx();
+      i<(ResultsImage->getsizex()-kernel->getradiusx());i++)
+    for(int j=kernel->getradiusy()+1;
+	j<(ResultsImage->getsizey()-kernel->getradiusy()-1);j++)
+      {
+	sum=0.0;
+	for(int column=-kernel->getradiusx();
+	    column<=kernel->getradiusx();column++)
+	  for(int row=-kernel->getradiusy();
+	      row<=kernel->getradiusy();row++)
+	    {
+	      sum=sum+((float)(getpixel(i+column,j+row))*
+		       kernel->getpixel(kernel->getradiusx()-column,
+					kernel->getradiusy()-row));
+	    }
+	ResultsImage->setpixel(i,j,sum);
+      }
+  fprintf(stderr, "done \n");
+  ConvFloat(ResultsImage);              
+  delete ResultsImage;
+}
+
+//-----------------------------------------------------------------------
+
+void PXImage::Median(int radius)
+{
+  unsigned short *old=new unsigned short[xsize*ysize];
+
+  for(long ii=0;ii<xsize*ysize;ii++)
+    old[ii]=image[ii];
+
+  int winsize=2*radius+1,max=0,position=0;
+  unsigned short* sorted=new unsigned short[winsize*winsize];
+
+  fprintf(stderr, "Median Filetring (%d)\n", winsize );
+
+  for(int i=radius;i<(xsize-radius-1);i++)
+    for(int j=radius;j<(ysize-radius-1);j++)
+      {
+	for(int countx=-radius;countx<=radius;countx++)
+	      for(int county=-radius;county<=radius;county++)
+		sorted[(radius+countx)+(radius+county)*winsize]=
+		  getpixel(old,i+countx,j+county);
+	    
+	    for(int outer=0;outer<=(winsize*winsize)/2;outer++)
+	      {
+		max=sorted[0];
+		position=0;
+		for(int inner=1;inner<(winsize*winsize);inner++)
+		  {
+		    if (sorted[inner]>max)
+		      {
+			max=sorted[inner];
+			position=inner;
+		      }
+		  }
+		sorted[position]=0;
+	      }
+	    setpixel(i,j,max);
+      }
+  delete [] old;
+  delete [] sorted;
+  status=1;
+}
+
+
+
+//-----------------------------------------------------------------------
+
+void PXImage::Scale(float scale)
+{
+  scale=fabs(scale);
+  if (scale>0.1)
+    {
+      unsigned short *old=new unsigned short[xsize*ysize];
+      for(long ii=0;ii<xsize*ysize;ii++)
+	  old[ii]=image[ii];
+      
+      int xs=(int)((float)xsize*scale);
+      int ys=(int)((float)ysize*scale);
+
+      delete [] image;
+      image=new unsigned short[xs*ys];
+      float a,b;
+      
+      for(int i=0;i<xs;i++)
+	  for(int j=0;j<ys;j++)
+	      {
+		a=((float)i/scale);
+		b=((float)j/scale);
+		image[j*xs+i]=getbilinear(old,a,b);
+	      }
+      xsize=xs;
+      ysize=ys;
+      delete [] old;
+      status=1;
+    }
+}
+
+//-----------------------------------------------------------------------
+
+void PXImage::AddContour(PXContour* contour,unsigned short grl,
+			 unsigned char touching,
+			 int offx,int offy)
+{
+  unsigned short a,b;
+  if (touching>0)
+    {
+      PXContour* modcontour=new PXContour(contour);
+      modcontour->closedcontour(1);
+      modcontour->Touching();
+      PXContourPoint *pts=modcontour->gettoppoint();
+      while (pts->next !=NULL)
+
+	{
+	  a=offx+(int)pts->x;
+	  b=offy+(int)pts->y;
+	  if (a>=xsize) a=xsize-1;
+	  if (b>=ysize) b=ysize-1;
+	  setpixel(a,b,grl);
+	  pts=pts->next;
+	}
+      delete modcontour;
+    }
+  else
+    {
+      PXContourPoint *pts=contour->gettoppoint();
+      while (pts->next !=NULL)
+	{
+	  a=offx+(int)pts->x;
+	  b=offy+(int)pts->y;
+	  if (a>=xsize) a=xsize-1;
+	  if (b>=ysize) b=ysize-1;
+	  setpixel(a,b,grl);
+	  pts=pts->next;
+	}
+    }
+}
+
+// ---------------------------------------------------------------------------
+//                  Gradient Related Code
+// ---------------------------------------------------------------------------
+float PXImage::GradientX(int x,int y)
+{ 
+  return getpixel(x+1,y)-getpixel(x,y); 
+}
+
+float PXImage::GradientY(int x,int y)
+{ 
+  return getpixel(x,y+1)-getpixel(x,y);  
+}
+  
+float PXImage::GradientXMask(int x,int y)
+{ 
+  float sum=0;
+  for(int i=-2;i<=2;i++)
+      sum=sum+(gradient_mask[i+2]*getpixel(x+i,y));
+  return sum;  
+}
+  
+float PXImage::GradientYMask(int x,int y)
+{ 
+  float sum=0;
+  for (int i=-2;i<=2;i++)
+      sum=sum+(gradient_mask[i+2]*getpixel(x,y+i));
+  return sum; 
+}
+
+float PXImage::Laplacian(int x,int y)
+{  
+  return 4*getpixel(x,y)-getpixel(x+1,y)-getpixel(x-1,y)-
+      getpixel(x,y+1)-getpixel(x,y-1);
+}
+
+// Get Sub-Pixel Gradients
+// -----------------------
+
+float PXImage::IntGradX(float x,float y)
+{ 
+  return getinterp(x+1.0,y)-getinterp(x,y); 
+}
+
+float PXImage::IntGradY(float x,float y)
+{ 
+  return getinterp(x,y+1.0)-getinterp(x,y);  
+}
+  
+float PXImage::Int5GradX(float x,float y)
+{ 
+  float sum=0;
+  for(int i=-2;i<=2;i++)
+      sum=sum+(gradient_mask[i+2]*getinterp(x+float(i),y));
+  return sum;  
+}
+  
+float PXImage::Int5GradY(float x,float y)
+{ 
+  float sum=0;
+  for (int i=-2;i<=2;i++)
+      sum=sum+(gradient_mask[i+2]*getinterp(x,y+float(i)));
+  return sum; 
+}
+  
+float PXImage::IntLaplacian(float x,float y)
+{
+  return 4.0*getinterp(x,y)-getinterp(x+1.0,y)-getinterp(x-1.0,y)-
+      getinterp(x,y+1.0)-getinterp(x,y-1.0);
+}
+
+/* ------------------------------------------------------------------------ 
+_Description : Trace the contour of region. The region is defined by a region
+               number. All the pixel of the region have the same region number.
+	       The algorithm computes the border of the region. It tracks the
+	       points of the border, one after the other. 
+
+_References : Geometrie Discrete/ J.M. Chassery/ A. Montanvert
+              Traite des Nouvelles Technologies
+	      HERMES 1991
+ 
+_Author : Francois G. Meyer
+_Revisions History:
+      7-AUG-1991                       Initial Key-in
+     22-AUG-1991           Add the corners to the contour. If (a,b)
+                   belongs to the contour we test for point derived 
+		   from (i,j) in direction dir +1 to belong to the 
+		   contour.
+
+------------------------------------------------------------------------ */
+PXContour* PXImage::tracefromimage(int value)
+{
+  PXContour* cntr=new PXContour;
+    
+  int keep_going;				/* loop controler */
+  int npoint = 0,  end = 0;
+  int i=0,j=0;           /* current point on the contour */
+  int a=0,b=0;           /* next point on the contour */
+  int abis=0, bbis=0;        /* point in direcion dir +1 form (i,j) */
+  int dir=1;         /* Freeman code to get (a,b) from (i,j) */
+  int dirbis=2;      /* dir +1 */
+  int dirprec=1;     /* Freeman code [from (a,b)!] of the point of the back- */
+  /* ground wich has been tested just before (a,b)        */
+  /* from (x,y)                                           */    
+
+  int P0x=0,P0y=0,P1x=0,P1y=0; /* two 1st point of the chain */
+  
+  /* scan the picture from top to down and left to right to get the 1st*/
+  /* point of the object */
+  
+  i = 0;   j  = 0;
+
+  while ( (i < getsizex()) && (getpixel( i, j) != value) )
+      {
+	j++;
+	if (j == getsizey()-1) 
+	    {
+	      j = 0;
+	      i ++;
+	    }
+      }
+
+  if (getpixel(i,j)!=value) 
+      {
+	return cntr;
+      }
+
+  /* (i,j) is the 1st point of the value */
+  /* in direction 4 you will find a point of the background */
+  /* record the 1st point in the chain */
+  
+  cntr->AddP( i,j);
+  P0x = i;
+  P0y = j;
+  
+  npoint++;
+  
+
+  /* set current pointer to the 1st point */
+  
+  dir = 4;
+  end = 0;
+  
+  /* get the other points */
+
+  while (!end)
+      {
+	/* search the following point belonging to the region */
+	do
+	    {
+	      dir = (dir+1) % 8;
+	      switch (dir)
+		  {
+		  case 0: a = i; b = j + 1; 	break;
+		  case 1: a = i - 1; b = j + 1; break;           
+		  case 2: a = i - 1; b = j;     break;            
+		  case 3: a = i - 1; b = j - 1; break;            
+		  case 4: a = i;     b = j - 1; break;            
+		  case 5: a = i + 1; b = j - 1; break;            
+		  case 6: a = i + 1; b = j;     break;
+		  case 7: a = i + 1; b = j + 1; break;
+		  }
+	      if ((i > 0) && (i < getsizex()-1) && 
+		  (j < getsizey()-1) && (j > 0))
+		  {
+		    keep_going = (getpixel( a, b) != value);
+		  }
+	      else
+		  {
+		    keep_going = 0;
+		  }
+	    }
+	while (keep_going);
+	
+	/* update the direction wich from (a,b) leads to */
+	/* a point of the background */
+	
+	switch (dir)
+	    {
+	    case 0:
+	    case 1: dirprec = 6;  break;
+	    case 2:
+	    case 3: dirprec = 0;  break;
+	    case 4:
+	    case 5: dirprec = 2;  break;
+	    case 6:
+	    case 7: dirprec = 4;  break;
+	    }
+	
+	/* if its the 2nd point, then save it in P1*/
+	if (npoint == 1)
+	    {
+	      P1x = a;
+	      P1y = b;
+	    }
+	else
+	    {
+	      /* if the current point and the next one fit with the */
+	      /* 1st and the 2nd points of the chain, then it' finished */
+	      
+	      if ((i == P0x) && (j == P0y) && (a == P1x) && (b == P1y)) 
+		  end = 1;
+	    }
+	
+	if (!end)
+	    {
+	      npoint++;
+	      
+	      /* if the contour is oblique */
+	      if (dir % 2 == 1)
+		  {
+		    /* add corner if it belongs to the image */
+		    
+		    dirbis = (dir+1) % 8;
+		    switch (dirbis)
+			{
+			case 0: abis = i;     bbis = j + 1; break;
+			case 1: abis = i - 1; bbis = j + 1; break;           
+			case 2: abis = i - 1; bbis = j;     break;            
+			case 3: abis = i - 1; bbis = j - 1; break;            
+			case 4: abis = i;     bbis = j - 1; break;            
+			case 5: abis = i + 1; bbis = j - 1; break;            
+			case 6: abis = i + 1; bbis = j;     break;
+			case 7: abis = i + 1; bbis = j + 1; break;
+			}
+		    
+		    if (getpixel( abis, bbis) == value)
+			cntr->AddP(abis,bbis);
+		  }
+	      
+	      /* process (a,b) */
+	      
+	      cntr->AddP(a,b);
+	      i = a;
+	      j = b;
+	      dir = dirprec;
+	    }
+      }
+  cntr->closedcontour(1);
+  return cntr;
+}
+
+
diff --git a/bioimagesuite30_src/numerics/pximage.h b/bioimagesuite30_src/numerics/pximage.h
new file mode 100644
index 0000000..0518334
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pximage.h
@@ -0,0 +1,261 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pximage.h
+// Definition of Class PXimage
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July 1995 papad at noodle.med.yale.edu
+
+_Module_Name : PXImage 
+
+_Description : This class can be used to store objects which are images.
+               Also a routine to read Analyse File Slices in pre-allocated
+	        PXImages.
+               
+_Call :   
+  (1) PXImage(filename,numbits) - used to load image from disk
+  (2) PXImage(filename)         - used to load ScilImage
+  (3) PXImage(xsize,ysize)      - used to generate temp image
+  (4) PXImage(filename,comment,xsize,ysize) - used to generate saveable image
+  (5) PXImage(PXImage*,PXFloatMatrix*) - convolution
+  (6) PXImage(PXImage*)          - Copy Constructor
+  (7) PXImage(unsigned char*, int x ,int y) -- construct from array
+     
+_References : None
+              
+_I/O : PGM, 8-bit and 16-bit binary (and binary+ grl grl16) 
+            for saving and loading
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in July 1995
+                    2. Added Gradient code & Convolution Code July 31st 1995
+		    3. Added ScilImage support August 22nd 1995 8/16 bit
+		    4. Added Median Filtering and Thresholding 30/8/95
+		    5. Added Binary I/O  and scaling 31/8/95 & Key Codes
+		    6. Eliminated PXFloatImage -> Constructor ...
+		    7. Shifted Median and added Convolution as functions 14/10/95
+		    8. Added getbilinear() - Bilinear Interpolation 14/10/95
+		    9. Added GrlScale() to scale greylevel below 65535*grscale
+		   10. Added Contour Addition 20th October 1995
+		   11. Auto-detected between pgm grl16 and grl8 3/11/95 
+		                      (specify .pgm)
+		   12. Split LoadGrl and LoadBin and added ability to skip 
+		           LoadBin 23 Feb 96
+		   13. getbilinear made private 
+		   14. Tidied-up .h file added clear protected/public divide
+		       added getimage() to  return unsigned char* array of image
+		       also added constructor for (unsigned char*) array
+		       2nd Sep 1996
+		   15. Tidied up filename mess add proper setfilename and added
+		       Save(filename) routines, eliminated comment field
+		   16. Added ability to trace contour from image
+		       (12th November 1997 -- from Francois code)
+		   17. Added facility for (signed storage and retrieval)
+                       13th Nov 1997 getspixel(i,j) setspixel(i,j,int)
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#--#-#-#-#-#-#-#-#  */
+
+#ifndef _PXImage
+#define  _PXImage
+
+class PXFloatMatrix;
+
+#include "pxcontour.h"
+#include "pxutil.h"
+#include <stdlib.h>
+// ********** Constructor Codes *******************************
+const int PXIm_Scil       =  0;        // Load Codes;
+const int PXIm_Pgm        =  8;
+const int PXIm_grl8      =  -8;
+const int PXIm_Bin        = 15;
+const int PXIm_grl       =  16;
+const unsigned short PXIM = 29571;    // Magic Number for PXImage Format;
+
+class PXImage {
+  
+  // ************** Class Fields *************************************
+
+protected:	
+
+  static float    gradient_mask[5];             // store 5x1 mask for derivatives 
+  unsigned short  *image; 			// image storage array;
+  int		  xsize,ysize,maxgrayscale;	// size and properties;
+  int		  status;			// 1=OK 0=problem;
+  char		  *filename;		  	// filename;
+
+  // ******************************************************************************
+  //          PUBLIC INTERFACE
+  // ******************************************************************************
+ 
+public:
+  
+  PXImage() {}                               // Dummy Constructor;
+  PXImage(int,int);                          // Plain Constructor x*y;
+  PXImage(const char*,int , int);                  // Checks for filename too;
+  PXImage(const char* fname,int c=PXIm_Pgm);       // Load Constructors int=PXIm_?;
+  PXImage(PXImage*);                         // Copy Constructor;
+  PXImage(PXImage*,PXFloatMatrix*);          // Convolution I**M;
+  PXImage(unsigned const char* img, int x ,int y); // construct from array
+  virtual ~PXImage();				
+
+
+
+  // [A] setpixel, getpixel getbilinear, getinterp  
+  // ---------------------------------------------
+
+  virtual void setpixel(int x, int y, unsigned short g)	   
+      {image[y*xsize+x]=g;}
+  virtual unsigned short getpixel(int x, int y)  
+      {return image[y*xsize+x]; }
+  virtual short  getspixel(int x,int y)
+      {	unsigned short a=getpixel(x,y);
+	return (short)a; }
+  virtual void setspixel(int x,int y,short p)
+      {	unsigned short px=(unsigned short)p;
+	setpixel(x,y,px); }
+  float getinterp(float x,float y);
+  
+  // [B] Access other fields
+  // -----------------------
+
+  virtual int getsize()    {return xsize*ysize;}
+  virtual int getsizex()   {return xsize;}		
+  virtual int getsizey()   {return ysize;}		
+  virtual int getwidth()   {return xsize;}		
+  virtual int getheight()  {return ysize;}		
+
+  virtual int	getmaxgrayscale()     {return maxgrayscale;}
+  virtual void  SetMaxgrayscale();   
+
+  virtual char*	getfilename()      {return filename;}	
+  virtual void setfilename(const char * fname,int removesuffix=0);
+  
+  virtual int	isvalid()          {return status;}	
+  virtual void  nowisvalid()       {status=1;}
+
+  virtual unsigned char* getimage();
+  virtual unsigned short* getimagepointer() { return image; }
+  unsigned char* getslice(float gamma=1.0,int numbytes=1); 
+  unsigned char* getpaddedslice(int &w,int &h,float gamma=1.0); 
+  unsigned char* scaleslice(int &w,int &h,unsigned char* slice,int numbytes=1,int sclaex=1,int scaley=1); 
+
+  // [C]  I/O Related Code;
+  //-----------------------
+  virtual int	Save(const char* fname);
+  virtual int   SavePgm(const char* fname);
+  virtual int	SaveGrl(const char* fname,int bits);
+  virtual int	SaveBin(const char* fname,int );
+
+  virtual int	Save();
+  virtual int   SavePgm();
+  virtual int	SaveGrl(int bits);
+  int    	LoadBin(int bits,int skip=0);
+  virtual int	SaveBin(int );
+
+  // [D] Image Processing Routines (Median,Convolutions) 
+  // ---------------------------------------------------
+  virtual void Zero(unsigned short px=0);
+  virtual void Threshold(float t);
+  virtual void Invert();			
+  virtual void Convolve(PXFloatMatrix* kernel);
+  virtual void Median(int radius);
+  virtual void Scale(float scale);
+  virtual void Grlscale(float grscale);
+
+  // [D] Insert and Extract Contours 
+  // ---------------------------------------------------
+  virtual void AddContour(PXContour* contour,unsigned short grl,
+			  unsigned char touching,
+			  int offx,int offy);
+  virtual PXContour* tracefromimage(int value);
+
+  // [E] GetGradients
+  // ----------------
+  float GradientX(int x,int y);
+  float GradientY(int x,int y);
+  float GradientXMask(int x,int y);
+  float GradientYMask(int x,int y);
+  float Laplacian(int x,int y);
+  
+  // [F] Get Sub-Pixel Gradients
+  // ---------------------------
+  float IntGradX(float x,float y);
+  float IntGradY(float x,float y);
+  float Int5GradX(float x,float y);
+  float Int5GradY(float x,float y);
+  float IntLaplacian(float x,float y);
+
+
+  // ******************************************************************************
+  //          IMPLEMENTATION SPECIFIC
+  // ******************************************************************************
+
+  protected :
+  
+  unsigned char adjust(float px,float gamma);
+  void ConvFloat(PXFloatMatrix*);
+  
+  virtual void setpixel(unsigned short* px,int x, int y, unsigned short g)	   
+      {px[y*xsize+x]=g;}
+
+  virtual int	getpixel(unsigned short* px,int x, int y)  
+      {return px[y*xsize+x]; }
+
+  virtual int getbilinear(unsigned short* px,float x,float y);
+  virtual int getbilinear(float x,float y);
+
+  // [C]  I/O Related Code;
+  //------------------------------------------------------------------------
+  virtual int  Load();
+  virtual int  LoadPgm();
+  virtual int  LoadGrl(int bits);
+  virtual int  LoadScil();                
+  virtual void	CheckFilename(const char*,int);		
+  virtual void	CheckFilename(int mode)    {  CheckFilename(filename,mode); }
+
+};
+
+#endif /*  _PXImage */
+
+
+
+
+
+
diff --git a/bioimagesuite30_src/numerics/pxmarkerclass.cpp b/bioimagesuite30_src/numerics/pxmarkerclass.cpp
new file mode 100644
index 0000000..dfe84f0
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxmarkerclass.cpp
@@ -0,0 +1,454 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+
+#include "pxmarkerclass.h"
+#include "pxutil.h"
+
+// ------------------------------------------------------------------------------------------------
+PXClickedPoints::PXClickedPoints()
+{
+  cntrxy=new PXContour();
+  cntrzt=new PXContour();
+}
+
+PXClickedPoints::~PXClickedPoints()
+{
+  delete cntrxy;
+  delete cntrzt;
+}
+
+void PXClickedPoints::removelast()
+{
+  cntrxy->RemovePoint();
+  cntrzt->RemovePoint();
+}
+
+void PXClickedPoints::addpoint(float x,float y,float z,float i,int remove)
+{
+  PXContourPoint* ptsxy=cntrxy->gettoppoint();
+  PXContourPoint* ptszt=cntrzt->gettoppoint();
+  int found=0,k=0;
+  while (k<cntrxy->getnumpoints() && found==0)
+      {
+	if (fabs(ptsxy->x-x)<0.1 && fabs(ptsxy->y-y)<0.1 && fabs(ptszt->x-z)<0.1)
+	    {
+	      //fprintf(stderr,"Found\n");
+	      found=1;
+	    }
+	else
+	    {
+	      ptsxy=ptsxy->next;
+	      ptszt=ptszt->next;
+	      k++;
+	    }
+      }
+
+  if (found==0)
+      {
+	cntrxy->Add(x,y);
+	cntrzt->Add(z,i);
+	//fprintf(stderr,"Adding point %d/%d \n",k,cntrxy->getnumpoints());
+      }
+  else if (remove==1)
+      {
+	//	fprintf(stderr,"Deleting point %d/%d \n",k,cntrxy->getnumpoints());
+	if (cntrxy->getnumpoints()>1)
+	    {
+	      PXContourPoint* lastxy=cntrxy->getlastpoint();
+	      PXContourPoint* lastzt=cntrzt->getlastpoint();
+	      ptsxy->x=lastxy->previous->x;     ptsxy->y=lastxy->previous->y;
+	      ptszt->x=lastzt->previous->x;	  ptszt->y=lastzt->previous->y;
+	    }
+	removelast();
+      }
+  /*else
+      {
+	fprintf(stderr,"Found point %d/%d Not adding\n",k,cntrxy->getnumpoints());
+      }*/
+}
+
+
+
+void PXClickedPoints::clearpoints()
+{
+  cntrxy->DeleteAll();
+  cntrzt->DeleteAll();
+}
+
+void PXClickedPoints::getcentroid(float& x,float& y,float &z,float max)
+{
+  x=0.0,y=0.0,z=0.0;
+  float total=0.0;
+
+  if (cntrxy->getnumpoints()==0)
+      return;
+
+  PXContourPoint* ptsxy=cntrxy->gettoppoint();
+  PXContourPoint* ptszt=cntrzt->gettoppoint();
+
+  for (int i=0;i<cntrxy->getnumpoints();i++)
+      {
+	float intensity=ptszt->y;
+	
+	if (max>0.0)
+	    {
+	      intensity=max-intensity;
+	    }
+
+	x+=intensity*ptsxy->x;
+	y+=intensity*ptsxy->y;
+	z+=intensity*ptszt->x;
+	total+=intensity;
+	ptsxy=ptsxy->next;
+	ptszt=ptszt->next;
+      }
+  x/=total;
+  y/=total;
+  z/=total;
+
+}
+PXContour* PXClickedPoints::getpositionxy()
+{
+  return cntrxy;
+}
+
+PXContour* PXClickedPoints::getpositionzintensity()
+{
+  return cntrzt;
+}
+// ------------------------------------------------------------------------------------------------
+PXMarker::PXMarker(int maxnum)
+{
+  numframes=Irange(maxnum,1,1000);
+  position=new PX3Vector[numframes];
+  points=new PXClickedPoints[numframes];
+  markerclass=0;
+  strcpy(name,"Mark");
+}
+
+PXMarker::~PXMarker()
+{
+  delete [] position;
+  delete [] points;
+}
+
+
+void PXMarker::setname(const char* nam)
+{
+  strncpy(name,nam,12);
+}
+
+char* PXMarker::getname()
+{
+  return name;
+}
+
+PXClickedPoints* PXMarker::getclickedpoints(int fr)
+{
+  fr=Irange(fr,0,numframes-1);
+  return &points[fr];
+}
+
+void PXMarker::setposition(int fr,float x,float y,float z)
+{
+  fr=Irange(fr,0,numframes-1);
+  position[fr].setvector(x,y,z);
+}
+
+void PXMarker::setposition(int fr,PX3Vector*  v)
+{
+  fr=Irange(fr,0,numframes-1);
+  position[fr].copy(v);
+}
+
+void PXMarker::setclass(int markclass)
+{
+  markerclass=Irange(markclass,0,2);
+}
+
+int PXMarker::getnumframes()
+{
+  return numframes;
+}
+
+int PXMarker::getclass()
+{
+  return markerclass;
+}
+
+PX3Vector* PXMarker::getposition(int fr)
+{
+  fr=Irange(fr,0,numframes-1);
+  return &position[fr];
+}
+
+float PXMarker::getcomponent(int fr,int comp)
+{
+  fr=Irange(fr,0,numframes-1);
+  comp=Irange(comp,0,2);
+  return position[fr].x[comp];
+}
+// ------------------------------------------------------------------------------------------------
+
+PXMarkerCollection::PXMarkerCollection(int num,int numframes)
+{
+  nummarkers=Irange(num,1,400);
+  fprintf(stderr,"In marker collection nummarkers=%d,numframes=%d\n",nummarkers,numframes);
+  for (int i=0;i<nummarkers;i++)
+      {
+	char line[13];
+	marker[i]=new PXMarker(numframes);
+	sprintf(line,"Marker %3d",i);
+	marker[i]->setname(line);
+      }
+}
+  
+PXMarkerCollection::~PXMarkerCollection()
+{
+  for (int i=0;i<nummarkers;i++)
+      delete marker[i];
+}
+
+PXMarker* PXMarkerCollection::getmarker(int markerno)
+{
+  markerno=Irange(markerno,0,nummarkers-1);
+  return marker[markerno];
+}
+
+int PXMarkerCollection::getnummarkers()
+{
+  return nummarkers;
+}
+
+int PXMarkerCollection::loadmarkercollection(const char* fname)
+{
+  FILE* fin=fopen(fname,"r");
+  if (!fin)
+      return 0;
+
+  char line[200];
+
+  fgets(line,200,fin);
+  int st=strncmp(line, "#PXMarkerCollection",19);
+  if (st!=0)
+      {
+	fclose(fin);
+	return 0;
+      }
+  
+  fprintf(stderr,"Old num markers=%d\n",nummarkers);
+
+  //fgets(line,200,fin);
+  int newnummark;
+  fscanf(fin,"%d\n",&newnummark);
+    // Clean up old markers
+  int i;
+  for (i=0;i<nummarkers;i++)
+      delete marker[i];
+
+  nummarkers=Irange(newnummark,1,399);
+  fgets(line,200,fin);
+
+  fprintf(stderr,"New num markers=%d\n",nummarkers);
+
+  for (i=0;i<nummarkers;i++)
+      {
+	// This could become a label
+	fgets(line,200,fin);
+	if (strlen(line)>0)
+	    line[strlen(line)-1]=(char)0;
+	int mc,mnum;
+	fscanf(fin,"%d\n%d\n",&mc,&mnum);
+	//	fprintf(stderr,"Creating marker %d class=%d frames=%d\n",i,mc,mnum);
+	marker[i]=new PXMarker(mnum);
+	marker[i]->setclass(mc);
+	marker[i]->setname(line);
+	for (int f=0;f<mnum;f++)
+	    {
+	      float x,y,z;
+	      fscanf(fin,"%f %f %f\n",&x,&y,&z);
+	      marker[i]->setposition(f,x,y,z);
+	      //fprintf(stderr,"Position %6.2f %6.2f %6.2f\n",x,y,z);
+	      int nump;
+	      fscanf(fin,"%d\n",&nump);
+	      PXClickedPoints* points=marker[i]->getclickedpoints(f);
+	      for (int p=0;p<nump;p++)
+		  {
+		    float t;
+		    fscanf(fin,"%f %f %f %f\n",&x,&y,&z,&t);
+		    points->addpoint(x,y,z,t);
+		  }
+	    }
+	fgets(line,200,fin);
+      }
+  fclose(fin);
+  return 1;
+}
+
+int PXMarkerCollection::savemarkercollection(const char* fname)
+{
+  FILE* fout=fopen(fname,"w");
+  if (!fout)
+      return 0;
+
+  fprintf(fout,"#PXMarkerCollection\n");
+  fprintf(fout,"%d\n",nummarkers);
+  fprintf(fout,"#------------------------------------------\n");
+  
+  for (int m=0;m<nummarkers;m++)
+      {
+	fprintf(fout,"%s\n",marker[m]->getname());
+	fprintf(fout,"%d\n",marker[m]->getclass());
+	fprintf(fout,"%d\n",marker[m]->getnumframes());
+	for (int fr=0;fr<marker[m]->getnumframes();fr++)
+	    {
+	      for (int k=0;k<=2;k++)
+		  fprintf(fout,"%6.2f ",marker[m]->getcomponent(fr,k));
+	      fprintf(fout,"\n");
+	      PXClickedPoints* point=marker[m]->getclickedpoints(fr);
+	      
+	      PXContourPoint* cnt1=point->getpositionxy()->gettoppoint();
+	      PXContourPoint* cnt2=point->getpositionzintensity()->gettoppoint();
+	      int np=point->getpositionxy()->getnumpoints();
+	      fprintf(fout,"%d\n",np);
+	      for (int ib=1;ib<=np;ib++)
+		  {
+		    fprintf(fout,"%6.2f %6.2f %6.2f %6.2f \n",cnt1->x,cnt1->y,cnt2->x,cnt2->y);
+		    cnt1=cnt1->next;
+		    cnt2=cnt2->next;
+		  }
+	    }
+	fprintf(fout,"# ---------------------- \n");
+      }
+  fclose(fout);
+  return 1;
+}
+
+int PXMarkerCollection::scalemarkerz(float zx)
+{
+  fprintf(stderr,"Scaling Marker z-coordinate by %f\n",zx);
+  for (int m=0;m<nummarkers;m++)
+      {
+	for (int fr=0;fr<marker[m]->getnumframes();fr++)
+	    {
+	      PXClickedPoints* point=marker[m]->getclickedpoints(fr);      
+	      PXContourPoint* cnt2=point->getpositionzintensity()->gettoppoint();
+	      int np=point->getpositionxy()->getnumpoints();
+	      for (int ib=1;ib<=np;ib++)
+		  {
+		    cnt2->x=zx*cnt2->x;
+		    cnt2=cnt2->next;
+		  }
+	      int c=marker[m]->getclass();
+	      float x,y,z;
+	      if (c==0)
+		  point->getcentroid(x,y,z,4096.0);
+	      else
+		  point->getcentroid(x,y,z);
+	      marker[m]->setposition(fr,x,y,z);
+	    }
+      }
+  return 1;
+}
+
+int PXMarkerCollection::loadmarkercollectiondon(const char* fname,int numframes)
+{
+  FILE* fin=fopen(fname,"r");
+  if (fin==NULL)
+      {
+	fprintf(stderr,"Failed to open %s\n",fname);
+	return 0;
+      }
+  
+  // Count total frames and points 
+  int nptsmark[100];
+  int i;
+  for (i=0;i<100;i++)
+      nptsmark[i]=0;
+
+
+  int oldt=-1,current=0,nummark=1;
+  int x,y,z,t,intensity;
+  while (fscanf(fin,"%d %d %d %d %d\n",&x,&y,&z,&t,&intensity)>0) 
+      {
+	if (t<oldt)
+	    {
+	      ++current;
+	      ++nummark;
+	    }
+	++nptsmark[current];
+	oldt=t;
+      }
+  fclose(fin);
+
+
+  fprintf(stderr,"Nummarkers=%d \n",nummarkers);
+  
+    for (i=0;i<nummarkers;i++)
+      delete marker[i];
+
+  nummarkers=Irange(nummark,1,399);
+  fprintf(stderr,"New num markers=%d\n",nummarkers);
+
+  fin=fopen(fname,"r");
+  for (i=0;i<nummarkers;i++)
+      {
+	marker[i]=new PXMarker(numframes);
+	marker[i]->setclass(0);
+	char line[12];
+	sprintf(line,"#Marker %d",i);
+	marker[i]->setname(line);
+	int j;
+	for (j=0;j<nptsmark[i];j++)
+	    {
+	      int x,y,z,t,intensity;
+	      fscanf(fin,"%d %d %d %d %d\n",&x,&y,&z,&t,&intensity);
+	      marker[i]->getclickedpoints(t-1)->addpoint(float(x),float(y),
+							 float(z)*1.5,
+							 float(intensity));
+	    }
+	for (j=0;j<numframes;j++)
+	    {
+	      PXClickedPoints* points=marker[i]->getclickedpoints(j);
+	      float x,y,z;
+	      points->getcentroid(x,y,z,4096.0);
+	      marker[i]->setposition(j,x,y,z);
+	    }
+      }
+  fclose(fin);
+  return nummarkers;
+}
+
+
diff --git a/bioimagesuite30_src/numerics/pxmarkerclass.h b/bioimagesuite30_src/numerics/pxmarkerclass.h
new file mode 100644
index 0000000..a0f5a31
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxmarkerclass.h
@@ -0,0 +1,150 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+// pxmarkerclass.h 
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : pxmarkerclass.h
+
+_Description : Various Utility Routines for keeping track of Markers
+
+	       	       
+
+_Call : 
+
+     
+_References : 
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in Sep 8th 1999
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+#ifndef _PXMarkerclass
+#define  _PXMarkerclass
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "pxcontour.h"
+#include "pxgeometrystruct.h"
+
+// ---------------------------------------------------
+// Marker Related Stuff
+// ---------------------------------------------------
+class PXClickedPoints {
+  
+protected:
+  PXContour* cntrxy;
+  PXContour* cntrzt;
+
+public:
+  
+  PXClickedPoints();
+  ~PXClickedPoints();
+
+  void getcentroid(float& x,float& y,float& z,float max=-1.0);
+  void addpoint(float x,float y,float z,float intensity,int remove=0);
+  void clearpoints();
+  void removelast();
+
+  PXContour* getpositionxy();
+  PXContour* getpositionzintensity();
+};
+
+
+class PXMarker {
+
+protected:
+
+  int numframes;
+  int markerclass;
+  PX3Vector *position;
+  PXClickedPoints* points;
+  char name[13];
+  
+public:
+
+  PXMarker(int numframes);
+  ~PXMarker();
+  
+  void setposition(int frame,float x,float y,float z);
+  void setposition(int frame,PX3Vector* v);
+  void setclass(int markclass);
+  int getclass();
+  PX3Vector* getposition(int frame);
+  float  getcomponent(int frame,int comp);
+
+  int getnumframes();
+  PXClickedPoints* getclickedpoints(int frame);
+
+  void setname(const char* name);
+  char* getname();
+};
+ 
+
+class PXMarkerCollection {
+protected:
+  PXMarker* marker[400];
+  int nummarkers;
+
+public:
+  PXMarkerCollection(int nummarkers,int numframes);
+  ~PXMarkerCollection();
+
+  PXMarker* getmarker(int markerno);
+  int getnummarkers();
+
+  int scalemarkerz(float zx=0.5);
+
+  int loadmarkercollection(const char* fname);
+  int loadmarkercollectiondon(const char* fname,int numframes=16);
+  int savemarkercollection(const char* fname);
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/pxregion.cpp b/bioimagesuite30_src/numerics/pxregion.cpp
new file mode 100644
index 0000000..5b9c8e1
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxregion.cpp
@@ -0,0 +1,756 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+//
+//
+//
+//
+//  This file derives from Amit Chakraborty's original work and is almost completely obsolete!
+//
+//---------------------------------------------------------------------------------------------------------
+
+
+#include "pxregion.h"
+#include "nrutil.h"
+#include "pxfloatmatrix.h"
+#include "pxfloatimage.h"
+#include "nr.h"
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris February 1996   papad at noodle.med.yale.edu
+
+   see pxregion.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+// Defining namespace for old code
+
+
+
+PX2DRegion::PX2DRegion()
+{
+  hasderivatives=0;
+  hasoutput=0;
+}
+// ***********************************************************************
+
+PX2DRegion::~PX2DRegion()
+{
+  if (hasoutput)
+      delete outputimage;
+  if (hasderivatives==1)
+      {
+	delete gradx;
+	delete grady;
+      }
+}
+// ***********************************************************************
+void PX2DRegion::CreateOutputStructures(PXImage* pximage)
+{
+  if (hasoutput)
+      delete outputimage;
+  outputimage=new PXImage(pximage->getwidth(),pximage->getheight());
+  outputimage->Zero();
+}
+// ***********************************************************************
+void PX2DRegion::GenerateDerivatives(float sigma)
+{
+  if (hasderivatives)
+      {
+	delete gradx;
+	delete grady;
+      }
+  
+  PXFloatImage* PotentialMapX=new PXFloatImage(outputimage->getsizex(),outputimage->getsizey());
+  PXFloatImage* PotentialMapY=new PXFloatImage(outputimage->getsizex(),outputimage->getsizey());
+  integrate(outputimage,PotentialMapX,PotentialMapY);
+
+  int size=7;
+  if (sigma>1.0) size=6*int(sigma+0.5)+1;
+  PXFloatMatrix* kernelx=new PXFloatMatrix(size,3);
+  PXFloatMatrix* kernely=new PXFloatMatrix(3,size);
+  kernelx->GenGradGaussian1Dx(sigma);
+  kernely->GenGradGaussian1Dy(sigma);
+		
+  gradx = new PXFloatImage(PotentialMapX,kernelx);
+  grady = new PXFloatImage(PotentialMapY,kernely);
+  delete kernelx;
+  delete kernely;
+  hasderivatives=1;
+  
+  delete PotentialMapX;
+  delete PotentialMapY;
+}
+// ***********************************************************************
+float PX2DRegion::getgradx(float x,float y)
+{
+  if (hasderivatives==1)
+      return gradx->getinterp(x,y);
+  else
+      return 0.0;
+}
+// ***********************************************************************
+float PX2DRegion::getgrady(float x,float y)
+{
+  if (hasderivatives==1)
+      return grady->getinterp(x,y);
+  else
+      return 0.0;
+}
+// ***********************************************************************
+//       ACTUAL BAYESIAN SEGMENTATION FOR 2 ZONES                               
+// ***********************************************************************
+
+void PX2DRegion::segment_two_regions(PXImage* in,int mi,
+				     float mean1,float mean2,
+				     float sig, float sm)
+{
+  CreateOutputStructures(in);
+  PXImage* out=outputimage;
+  PXFloatImage *arr2,*arrm, *arr;
+  
+  // Scale Parameters to be in Image range as opposed to 0-1
+  
+  /*mean1=mean1*float(in->getmaxgrayscale());
+  mean2=mean2*float(in->getmaxgrayscale());
+  sig=sig*float(in->getmaxgrayscale());
+  sm=sm*float(in->getmaxgrayscale());*/
+
+  int i,j;
+  int ii;
+
+  float mid;
+
+  float te,te1, te2, te3, te4, te5, te6, te7, test1, test2;
+  float t4,t5,t6,t7;
+  
+  int width=in->getsizex();
+  int height=in->getsizey();
+  
+  mid=(mean1+mean2)/2.0;
+
+  arr2 = new PXFloatImage(width,height);
+  arrm = new PXFloatImage(width,height);
+  arr  = new PXFloatImage(width,height);
+
+  for (i=0; i <width; i++)
+      for (j=0; j <height; j++)
+	  {
+	    arr->setpixel(i,j,float(in->getpixel(i,j)));
+	    arr2->setpixel(i,j,arr->getpixel(i,j));
+	  }
+  //  fprintf(stderr,"Done Initialization\n");
+  for(ii=1;ii<=(abs(mi));ii++)
+      {
+	//fprintf(stderr,"Iteration %d\n",ii);
+	
+	if(ii==1) 
+	    mid=(mean1+mean2)/2.0;
+	else 
+	    {
+	      mid=(100.0+200.0)/2.0;
+	      for (i=0; i < width; i++)
+		  for (j=0; j < height ; j++)
+		      arr->setpixel(i,j,arrm->getpixel(i,j));
+	    }
+	
+	for (i=1; i < width-1; i++)
+	    for (j=1; j <height-1; j++)
+		{
+		  arrm->setpixel(i,j,0.0);
+		  /*		  if(arr2->getpixel(i,j) != 0.0)
+		      {*/
+			te1=arr2->getpixel(i,j) - mean1;
+			te2=arr2->getpixel(i-1,j)+arr2->getpixel(i+1,j) - 2*mean1;
+			te3=arr2->getpixel(i,j-1)+arr2->getpixel(i,j+1) - 2*mean1;
+			te=te1-0.2*(te2+te3);
+			te=te*te/(2.0*sig*sig);
+			if( arr->getpixel(i-1,j) < mid) te4= -sm;
+			else te4=sm;
+			if( arr->getpixel(i+1,j) < mid) te5= -sm;
+			else te5=sm;
+			if( arr->getpixel(i,j-1) < mid) te6= -sm;
+			else te6=sm;
+			if( arr->getpixel(i,j+1) < mid) te7= -sm;
+			else te7=sm;
+			
+			if( arr->getpixel(i-1,j+1) < mid) t4= -sm;
+			else t4=sm;
+			if( arr->getpixel(i+1,j+1) < mid) t5= -sm;
+			else t5=sm;
+			if( arr->getpixel(i+1,j-1) < mid) t6= -sm;
+			else t6=sm;
+			if( arr->getpixel(i-1,j-1) < mid) t7= -sm;
+			else t7=sm;
+			if(ii==0) te4=te5=te6=te7=0.0; 
+			if(ii==0) t4=t5=t6=t7=0.0; 
+			test1=te+te4+te5+te6+te7+2.0*log(sig*sig);
+			test1=test1+t4+t5+t6+t7;
+			
+			
+			te1=arr2->getpixel(i,j) - mean2;
+			te2=arr2->getpixel(i-1,j)+arr2->getpixel(i+1,j) - 2*mean2;
+			te3=arr2->getpixel(i,j-1)+arr2->getpixel(i,j+1) - 2*mean2;
+			te=te1-0.2*(te2+te3);
+			te=te*te/(2.0*sig*sig);
+			if( arr->getpixel(i-1,j) > mid) te4= -sm;
+			else te4=sm;
+			if( arr->getpixel(i+1,j) > mid) te5= -sm;
+			else te5=sm;
+			if( arr->getpixel(i,j-1) > mid) te6= -sm;
+			else te6=sm;
+			if( arr->getpixel(i,j+1) > mid) te7= -sm;
+			else te7=sm;
+			
+			if( arr->getpixel(i-1,j+1) < mid) t4= -sm;
+			else t4=sm;
+			if( arr->getpixel(i+1,j+1) < mid) t5= -sm;
+			else t5=sm;
+			if( arr->getpixel(i+1,j-1) < mid) t6= -sm;
+			else t6=sm;
+			if( arr->getpixel(i-1,j-1) < mid) t7= -sm;
+			else t7=sm;
+			
+			if(ii==0) te4=te5=te6=te7=0.0; 
+			if(ii==0) t4=t5=t6=t7=0.0; 
+			test2=te+te4+te5+te6+te7+2.0*log(sig*sig);
+			test2=test2+t4+t5+t6+t7;
+			
+			if(test1 < test2) 
+			    arrm->setpixel(i,j,100.0);
+			else 
+			    arrm->setpixel(i,j,200.0);
+		      //}
+		}
+      }
+  
+  for (i=0;i<width;i++)
+      for (j=0;j<height;j++)
+	  out->setpixel(i,j,int(arrm->getpixel(i,j)));
+  
+  delete arrm;
+  delete arr2;
+  delete arr;
+}
+/* ----------------------------------------------------------------------- */
+void PX2DRegion::segment_three_regions(PXImage* image1,
+				       int mi,float mean1,float mean2,float mean3,float sig )
+
+/*PIXEL *in, *out;
+float mean1,mean2,mean3,sig;
+int width, height,mi;*/
+{
+  CreateOutputStructures(image1);
+  PXImage* image2=outputimage;
+
+  int width=image1->getwidth();
+  int height=image2->getheight();
+
+  PXImage* tempimage=new PXImage(image1);
+
+  unsigned short* in=tempimage->getimagepointer();
+  unsigned short* out=image2->getimagepointer();
+
+  float *arr2,*arrm, *arr;
+  int npl,nph,nrl,nrh;//ncl,nch;
+  int i,j;
+  int ii;
+
+  //int nn,xsize,ysize,zsize;
+
+  //float xsiz,ysiz,zsiz;
+  float te,te1, te2, te3, te4, te5, te6, te7, test1, test2,test3;
+  //float asp;
+  unsigned short *ptr1;
+  float *ptr2;
+  float mid1,mid2;
+
+  arr2 = new float[width*height];// (float *) calloc(width*height, sizeof(float));
+  arrm = new float[width*height];//(float *) calloc(width*height, sizeof(float));
+  arr =  new float[width*height];//(float *) calloc(width*height, sizeof(float));
+
+
+  npl = 2;
+  nph = height-2;
+  nrl = 2;
+  nrh = width-2;
+  //ncl = 0;
+  //nch = 123;
+  //asp = 1.0;
+  /*zsize = nch-ncl+1;
+  ysize = nrh-nrl+1;
+  xsize = nph-npl+1;
+  xsiz = width;
+  ysiz = height;
+  zsiz = 124.0;*/
+
+
+  // nn = 0;
+  //  int temp =0.0;
+
+  for (i=npl; i <= nph; i++)
+      for (j=nrl; j <= nrh; j++)
+	  {
+	    if (*(in+width*i+j) < 30 ) 
+		*(in+width*i+j)=0;
+	    *(arr2+width*i+j) = *(arr+width*i+j)=(float) *(in+width*i+j); 
+	  }
+  
+  for(ii=0;ii<=mi;ii++)
+      {
+	if(ii==0)
+	    {
+	      mid1=(mean1+mean2)/2.0;
+	      mid2=(mean2+mean3)/2.0;
+	    }
+	else
+	    {
+	      mid1=100.0; 
+	      mid2=150.0;
+	    }
+	
+    for (i=npl; i <= nph; i++)
+	for (j=nrl; j <= nrh; j++)
+	    *(arr+i*width+j)=*(arrm+i*width+j);
+	
+    for (i=npl; i <= nph; i++)
+	for (j=nrl; j <= nrh; j++)
+	    {
+	      *(arrm+i*width+j)=0.0;
+	      if(*(arr2+i*width+j) != 0.0)
+		  {
+		    te1=*(arr2+i*width+j) - mean1;
+		    te2=*(arr2+(i-1)*width+j)+*(arr2+(i+1)*width+j) - 2*mean1;
+		    te3=*(arr2+i*width+j-1)+*(arr2+i*width+j+1) - 2*mean1;
+		    te=te1-0.02*(te2+te3);
+		    te=te*te/(2.0*sig*sig);
+		    if(( *(arr+(i-1)*width+j) < mid1) && ( *(arr+(i-1)*width+j) > 61)) 
+			te4= -0.9;
+		    else 
+			te4=0.9;
+		    if((*(arr+(i+1)*width+j) < mid1) && ( *(arr+(i+1)*width+j) > 61)) 
+			te5= -0.9;
+		    else 
+			te5=0.9;
+		    if((*(arr+i*width+j-1) < mid1) && ( *(arr+i*width+j-1) >61)) 
+			te6= -0.9;
+		    else 
+			te6=0.9;
+		    if((*(arr+i*width+j+1) < mid1)  && ( *(arr+i*width+j-1) >61))
+			te7= -0.9;
+		    else 
+			te7=0.9;
+		    test1=te+te4+te5+te6+te7+2.0*log((double)(sig*sig));
+	
+		    te1=*(arr2+i*width+j) - mean2;
+		    te2=*(arr2+(i-1)*width+j)+*(arr2+(i+1)*width+j) - 2*mean2;
+		    te3=*(arr2+i*width+j-1)+*(arr2+i*width+j+1) - 2*mean2;
+		    te=te1-0.02*(te2+te3);
+		    te=te*te/(2.0*sig*sig);
+		    if(( *(arr+(i-1)*width+j) < mid2) && ( *(arr+(i-1)*width+j) > mid1)) 
+			te4= -0.9;
+		    else 
+			te4=0.9;
+		    if((*(arr+(i+1)*width+j) < mid2) && ( *(arr+(i+1)*width+j) > mid1)) 
+			te5= -0.9;
+		    else 
+			te5=0.9;
+		    if((*(arr+i*width+j-1) < mid2) && ( *(arr+i*width+j-1) >mid1)) 
+			te6= -0.9;
+		    else 
+			te6=0.9;
+		    if((*(arr+i*width+j+1) < mid2)  && ( *(arr+i*width+j-1) >mid1))
+			te7= -0.9;
+		    else 
+			te7=0.9;
+		    test2=te+te4+te5+te6+te7+2.0*log((double)(sig*sig));
+
+		    te1=*(arr2+i*width+j) - mean3;
+		    te2=*(arr2+(i-1)*width+j)+*(arr2+(i+1)*width+j) - 2*mean3;
+		    te3=*(arr2+i*width+j-1)+*(arr2+i*width+j+1) - 2*mean3;
+		    te=te1-0.02*(te2+te3);
+		    te=te*te/(2.0*sig*sig);
+		    if( *(arr+(i-1)*width+j) > mid2) 
+			te4= -0.9;
+		    else 
+			te4=0.9;
+		    if( *(arr+(i+1)*width+j) > mid2) 
+			te5= -0.9;
+		    else 
+			te5=0.9;
+		    if( *(arr+i*width+j-1) > mid2) 
+			te6= -0.9;
+		    else 
+			te6=0.9;
+		    if( *(arr+i*width+j+1) > mid2) 
+			te7= -0.9;
+		    else 
+			te7=0.9;
+
+		    test3=te+te4+te5+te6+te7+2.0*log((double)(sig*sig));
+		    
+		    if((test1 < test2) && (test1<test3)) 
+			*(arrm+i*width+j)=50.0;
+		    else
+			{
+			  if((test2 < test1) && (test2<test3)) 
+			      *(arrm+i*width+j)=130.0;
+			  else 
+			      *(arrm+i*width+j) = 200.0; }
+		  }
+	    }
+	ptr1 = out;
+	ptr2 = arrm;
+	for( i = 0; i < width * height; i++ )
+	    *ptr1++ = (unsigned short) *ptr2++;
+      }
+  delete [] arr2;
+  delete [] arrm;
+  delete [] arr;
+  delete tempimage;
+  
+}
+/* ----------------------------------------------------------------------- */
+void PX2DRegion::integrate(PXImage *im1,PXFloatImage* imx,PXFloatImage* imy)
+{
+  int i,j;
+  for(j=0;j<im1->getsizey();j++)
+      {
+      float sumx=32768.0;
+      for(i=0;i<im1->getsizex();i++)
+	{
+	  float temp=float(im1->getpixel(i,j));
+	  if (temp==200.0) 
+	    temp=1.0;
+	  else
+	    temp=-1.0;
+	  sumx=sumx+temp;
+	  imx->setpixel(i,j,sumx);
+	}	
+    }
+  
+
+  for (i=0;i<im1->getsizex();i++)
+    {
+      float sumy=32768.0;
+      for(j=0;j<im1->getsizey();j++)
+	  {
+	    float temp=float(im1->getpixel(i,j));
+	    if (temp==200.0) 
+		temp=1.0;
+	    else
+		temp=-1.0;
+	    sumy=sumy+temp;
+	    imy->setpixel(i,j,sumy);
+	  }	
+    }
+}
+/* ----------------------------------------------------------------------- */
+void PX2DRegion::texture_segment(PXImage* image1,float beta,int iter,int window,
+				 int numtext,int* xi ,int* yi)
+{
+  int width=image1->getwidth();
+  int height=image1->getheight();
+  CreateOutputStructures(image1);
+  PXImage* image2=outputimage;
+
+  unsigned short* in=image1->getimagepointer();
+  unsigned short* out=image2->getimagepointer();
+
+  float *x, *arr,*mx;
+  int i,j,k,l,i1,j1;
+  int N,Nm;
+  unsigned short  *temp, *arrm;
+  
+  unsigned short val[20];
+  float test[20];
+  float meanf, a1f, a2f, a3f, a4f, sigmaf;
+  float y1,y2,y3,y4,y0,si,sumn;
+
+  x = new float[width*height];
+  mx = new float[width*height];
+  arrm = new unsigned short[width*height];
+  arr = new float[width*height];
+  temp = new unsigned short[width*height];
+  
+  for(i=0;i<height;i++)
+      for(j=0;j<width;j++)
+	  *(arr+i*width+j)=(float)( *(in+i*width+j));
+  
+  for(i=0;i<height;i++)
+      for(j=0;j<width;j++)
+	  {
+	    sumn=0.0; Nm=0;
+	    for(i1=i-5;i1<=i+5;i1++)
+		for(j1=j-5;j1<=j+5;j1++){
+		  if((i1>0)&&(i1<height-1)&&(j1>0)&&(j1<width-1)){
+		    sumn=sumn+*(arr+i1*width+j1); Nm=Nm+1;}
+		}
+	    *(x+i*width+j)=*(arr+i*width+j)-sumn/((float)(Nm));
+	    *(mx+i*width+j)=sumn/((float)(Nm));
+	  }
+  
+  if (window>0)
+      {
+	N=numtext;
+	textureparams.numzones=N;
+	for(k=1;k<=N;k++)
+	    {
+	      fprintf(stderr,"----------------- Zone %d -(%d,%d)------------------\n",k,xi[k-1],yi[k-1]);
+	      for(i=0;i<height;i++)
+		  for(j=0;j<width;j++)
+		      {
+			temp[i*width+j]=0;
+			if(j>=xi[k-1]-window &&
+			   j<=xi[k-1]+window && 
+			   i>=yi[k-1]-window  && 
+			   i<=yi[k-1]+window )
+			    temp[i*width+j]=200;
+		      }
+	      l_Coeff(mx,temp,width,height,&meanf,&a1f,&a2f,&a3f,&a4f,&sigmaf);
+	      textureparams.mean[k]=meanf;
+	      l_Coeff(x, temp,width,height,&meanf,&a1f,&a2f,&a3f,&a4f,&sigmaf);
+	      textureparams.sigma[k]=sigmaf;
+	      textureparams.a1[k]=a1f; 
+	      textureparams.a2[k]=a2f; 
+	      textureparams.a3[k]=a3f; 
+	      textureparams.a4[k]=a4f;
+	    }
+      }
+  else
+      {
+	fprintf(stderr,"Using Previous Parameters\n");
+	N=textureparams.numzones;
+      } 
+
+  for(k=1;k<=N;k++)
+      val[k]=(unsigned short)(k*255/N);
+  
+  
+  for(l=1;l<=iter;l++)
+      {
+	fprintf(stderr,"----------------- Iteration %d -------------------\n",l);
+  	for(i=0;i<height;i++)
+	    for(j=0;j<width;j++)
+		{
+		  for(k=1;k<=N;k++)
+		      {
+			si=0.0;
+			for(i1=i-1;i1<=i+1;i1++)
+			    for(j1=j-1;j1<=j+1;j1++){
+			      if((i1>0)&&(i1<height-1)&&(j1>0)&&(j1<width-1))
+				  {
+				    y0=*(x+i1*width+j1);
+				    y1=*(x+i1*width+j1-1) + *(x+i1*width+j1+1) ;
+				    y2=*(x+(i1-1)*width+j1) + *(x+(i1+1)*width+j1) ;
+				    y3=*(x+(i1-1)*width+j1-1) + *(x+(i1+1)*width+j1+1) ;
+				    y4=*(x+(i1-1)*width+j1+1) + *(x+(i1+1)*width+j1-1) ;
+				    
+				    si= si + (y0 - 
+					      textureparams.a1[k] *y1 - textureparams.a2[k]*y2 - 
+					      textureparams.a3[k]*y3 -  textureparams.a4[k]*y4 )* y0 ;
+				    si= si + (*(arr+i1*width+j1)-
+					      textureparams.mean[k])*(*(arr+i1*width+j1)-
+								      textureparams.mean[k]);
+				  }
+			    }
+			
+			if((l==1)||(i==0)||(i==height-1)||(j==0)||(j==width-1))
+			    test[k]=si;
+			else
+			    {
+			      test[k]=si;
+			      if( *(arrm+i*width+j+1)==val[k] ) 
+				  test[k]=test[k] - beta;
+			      else 
+				  test[k]=test[k] + beta;
+			      if( *(arrm+i*width+j-1)==val[k] ) 
+				  test[k]=test[k] - beta;
+			      else 
+				  test[k]=test[k] + beta;
+			      if( *(arrm+(i+1)*width+j)==val[k] ) 
+				  test[k]=test[k] - beta;
+			      else 
+				  test[k]=test[k] + beta;
+			      if( *(arrm+(i-1)*width+j)==val[k] ) 
+				  test[k]=test[k] - beta;
+			      else 
+				  test[k]=test[k] + beta;
+			    }
+			
+		      }
+		  sort_least(test,N,&k);
+		  *(arrm+i*width+j)=val[k];
+		}
+	
+	for(i=0;i<height;i++)
+	    for(j=0;j<width;j++)
+		*(out+i*width+j)=*(arrm+i*width+j);
+      }
+  
+  delete [] x; 
+  delete [] mx;
+  delete [] arrm; 
+  delete [] arr;
+  delete [] temp;
+}
+/* ----------------------------------------------------------------------- */
+void PX2DRegion::sort_least(float* a,int n,int* k)
+{
+  int i;
+  float min;
+  *k=1; min=a[1];
+  for(i=2;i<=n;i++)
+      {
+	if(a[i]<=min)
+	    {
+	      min=a[i]; *k=i;
+	    }
+      }
+}
+// ----------------------------------------------------------------------------------
+void PX2DRegion::l_Coeff(float* in,unsigned short* in1,
+			 int width,int height,
+			 float* meanf,float* a1f,float* a2f,float* a3f,float* a4f,float *sigmaf)
+{
+  int i,j,k,l;
+  double *x,mean;
+  double sig,si,sigsq;
+  double sig1,si1,sigsq1;
+  double *y;
+  double sum;
+  double weight;
+  int N;
+  //double w;
+  double **A, *B,d;
+  int *indx;
+  int n=4;
+  
+  x=new double[height*width];
+  A=dmatrix(1,n,1,n);
+  B=dvector(1,n);
+  y=dvector(1,n);
+  indx=ivector(1,n);
+  
+  for(k=1;k<=n;k++)
+      for(l=1;l<=n;l++)
+	  A[k][l]=B[k]=0.0;
+  
+  for(i=0;i<height;i++)
+      for(j=0;j<width;j++)
+	  *(x+i*width+j)=(double)( *(in+i*width+j));
+
+  sum=0.0;
+  weight=0.0;
+  for(i=0;i<height;i++)
+      for(j=0;j<width;j++)
+	  {
+	    if( *(in1+i*width+j)!=0 )
+		{
+		  sum=sum+ *(x+i*width+j);
+		  weight=weight+1.0;
+		}
+	  }
+  mean=sum/weight;
+  printf("mean, num %f %f \n", mean,weight);
+  
+ 
+  for(i=0;i<height;i++)
+    for(j=0;j<width;j++)
+      {
+	if( *(in1+i*width+j)!=0 )
+	  {
+	    //w=1.0;
+	    
+	    y[1]=*(x+i*width+j-1) + *(x+i*width+j+1) ;
+	    y[2]=*(x+(i-1)*width+j) + *(x+(i+1)*width+j) ; 
+	    y[3]=*(x+(i-1)*width+j-1) + *(x+(i+1)*width+j+1) ; 
+	    y[4]=*(x+(i-1)*width+j+1) + *(x+(i+1)*width+j-1) ; 
+	    
+	    for(k=1;k<=n;k++)
+	      for(l=1;l<=n;l++)
+		A[k][l]=A[k][l] + y[k] * y[l];
+	    
+	    
+	    for(k=1;k<=n;k++)
+	      /*
+		B[k]=B[k] + y[k] * ( *(x+i*width+j) -mean);
+	      */
+	      B[k]=B[k] + y[k] * ( *(x+i*width+j) );
+	    
+	    
+	  }
+      }
+  
+  int singular;
+  ludcmp(A,n,indx,&d,singular);
+  lubksb(A,n,indx,B);
+  
+  if( ( fabs(B[1]) > 2.0)||( fabs(B[2]) > 2.0)||( fabs(B[3]) > 2.0)||( fabs(B[4]) > 2.0) )
+    B[1]=B[2]=B[3]=B[4]=0.0;
+  
+  printf("results %f   %f  %f   %f\n", B[1],B[2],B[3],B[4]);
+  
+  sigsq=0.0;
+  sigsq1=0.0;
+  N=0;
+  for(i=0;i<height;i++)
+    for(j=0;j<width;j++){
+      if( *(in1+i*width+j)!=0)
+	{
+	  si1=*(x+i*width+j)-mean;
+	  
+	  y[1]=*(x+i*width+j-1) + *(x+i*width+j+1) ;
+	  y[2]=*(x+(i-1)*width+j) + *(x+(i+1)*width+j) ; 
+	  y[3]=*(x+(i-1)*width+j-1) + *(x+(i+1)*width+j+1) ; 
+	  y[4]=*(x+(i-1)*width+j+1) + *(x+(i+1)*width+j-1) ; 
+	  si=*(x+i*width+j)  - B[1]*y[1] - B[2]*y[2] - B[3]*y[3] - B[4]*y[4];
+	  sigsq=sigsq+si*si; 
+	  sigsq1=sigsq1+si1*si1;
+	  N=N+1;
+	}
+    }
+  sig=sqrt(sigsq/((double)N)); 
+  sig1=sqrt(sigsq1/((double)N));
+  printf("sig,sig1 %f %f \n", sig,sig1);
+  
+  printf("st dev %f \n", sig); 
+  printf("st dev1 %f \n", sig1);
+  printf("mean %f \n", mean);
+  printf("%d \n", N); 
+  *meanf=mean; *sigmaf=sig;
+  *a1f=B[1]; *a2f=B[2]; *a3f=B[3]; *a4f=B[4];
+
+  free_dmatrix(A,1,n,1,n);
+  free_dvector(B,1,n);
+  free_dvector(y,1,n);
+  free_ivector(indx,1,n);
+  delete [] x;
+}
+
+
+
diff --git a/bioimagesuite30_src/numerics/pxregion.h b/bioimagesuite30_src/numerics/pxregion.h
new file mode 100644
index 0000000..87aea72
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxregion.h
@@ -0,0 +1,129 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+
+_Module_Name : pxsegment
+
+_Description : PX2DRegion Class 
+
+_Call : 1. PX2DRegion(PXImage* InputImage,int numiter,
+	              float mean1,float mean2,float sigma1,float sigma2);
+
+
+_References : Chakraborty et al (ICCV) 1995
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : This is `translated' from Amit's original code. 
+           mean1,mean2,sigma1,sigma2 in range 0..1 -- This are scaled by the max
+	   image brightness.
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 22nd Feb 1996
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PX_REGION
+#define _PX_REGION
+
+#include <math.h>
+#include "pxfloatimage.h"
+#include "pximage.h"
+// Defining namespace for old code
+
+// -------------------------------------------------------------------------
+//                      PX2DRegion Class
+// -------------------------------------------------------------------------
+
+
+struct FP_texture
+{
+  int   numzones;
+  float mean[10],a1[10],a2[10],a3[10],a4[10],sigma[10];
+};
+
+class PX2DRegion {
+
+  protected :  
+  FP_texture    textureparams;
+  PXImage       *outputimage;
+  PXFloatImage  *gradx,*grady;
+  unsigned char hasderivatives,hasoutput;
+
+public:
+  PX2DRegion();
+  virtual ~PX2DRegion();
+
+  // Access Functions
+  // ----------------
+  PXImage* getoutputimage()    { return outputimage; }
+  float    getgradx(float x,float y);
+  float    getgrady(float x,float y);
+
+  unsigned char derivativesOK() { return hasderivatives;}
+  unsigned char outputOK() { return hasoutput;}
+
+  void     GenerateDerivatives(float sigma);
+  void     CreateOutputStructures(PXImage* pximage);
+
+  // ------------------------
+  // Amit Chakraborty's Code 
+  // ------------------------
+  void segment_two_regions(PXImage* in,int mi,
+			   float mean1,float mean2,
+			   float sig, float sm);
+  void segment_three_regions(PXImage* image,
+			     int mi,float mean1,float mean2,float mean3,float sig);
+  
+  void texture_segment(PXImage* image,
+		       float beta,int iter,int window,
+		       int numtext,int* xi ,int* yi);
+  
+  // ----------------------------------------------------------------------
+  // Auxiliary Code
+  // ----------------------------------------------------------------------
+  static void integrate(PXImage *im1,PXFloatImage* imx,PXFloatImage* imy);  
+  
+  static void sort_least(float* a,int n,int* k);
+  static void  l_Coeff(float* in,unsigned short* in1,
+		       int width,int height,
+		       float* meanf,float* a1f,float* a2f,float* a3f,float* a4f,float *sigmaf);
+  
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/pxshapetrackingclass.cpp b/bioimagesuite30_src/numerics/pxshapetrackingclass.cpp
new file mode 100644
index 0000000..7a8512a
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxshapetrackingclass.cpp
@@ -0,0 +1,1665 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+// ---------------------------------------------------------------------------------------------------------
+#include "pxshapetrackingclass.h"
+#include "pxutil.h"
+
+//#include "nrutil.h"
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July 1995   papad at noodle.med.yale.edu
+
+   see pxshapetrackingclass.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+// --------------------------------------------------------------------------
+int  PXShapeTrackingClass::debugmode=1;
+// --------------------------------------------------------------------------
+PXTriangulatedStack*  PXShapeTrackingClass::getstack(int i)
+{
+  return tstack[Irange(i,0,1)];
+}
+
+PX3Vector* PXShapeTrackingClass::getdisplacement(int i)
+{
+  if (!hasdisplacements())
+      return NULL;
+  return &displacements[Irange(i,0,numpoints-1)];
+}
+
+float PXShapeTrackingClass::getconfidence(int i)
+{
+  if (!hasdisplacements())
+      return 0.0;
+  return confidences[Irange(i,0,numpoints-1)];
+}
+
+void PXShapeTrackingClass::setconfidence(int i,float s)
+{
+  if (hasdisplacements())
+      {
+	i=Irange(i,0,numpoints-1);
+	confidences[i]=s;
+      }
+}
+
+void PXShapeTrackingClass::setdisplacement(int i,int comp,float s)
+{
+  if (hasdisplacements())
+      {
+	i=Irange(i,0,numpoints-1);
+	comp=Irange(comp,0,2);
+	displacements[i].x[comp]=s;
+      }
+}
+
+int PXShapeTrackingClass::getused(int i)
+{
+  if (!hasdisplacements())
+      return 0;
+  return used[Irange(i,0,numpoints-1)];
+}
+
+int PXShapeTrackingClass::getcorrespondence(int i)
+{
+   if (!hasdisplacements())
+      return 0;
+   return correspondence[Irange(i,0,numpoints-1)];
+}
+
+int PXShapeTrackingClass::getfixed(int i)
+{
+  if (!hasdisplacements())
+      return 0;
+  return fixed[Irange(i,0,numpoints-1)];
+}
+
+int PXShapeTrackingClass::hasdisplacements()
+{
+  return hasDisplacements;
+}
+
+int PXShapeTrackingClass::hasstack(int i)
+{
+  return hasStack[Irange(i,0,1)];
+}
+
+int PXShapeTrackingClass::hasstacks()
+{
+  return hasStack[0]*hasStack[1];
+}
+
+int PXShapeTrackingClass::getnumpoints()
+{
+  return numpoints;
+}
+
+// --------------------------------------------------------------------------
+PXShapeTrackingClass::PXShapeTrackingClass()
+{
+  init(0);
+  hasStack[0]=0; hasStack[1]=0; 
+}
+
+// --------------------------------------------------------------------------
+PXShapeTrackingClass::PXShapeTrackingClass(PXShapeTrackingClass* old)
+{
+  init(0);
+  hasStack[0]=0; hasStack[1]=0; 
+  Copy(old);
+}
+// --------------------------------------------------------------------------
+PXShapeTrackingClass::PXShapeTrackingClass(const char* fname1,const char* fname2)
+{
+  tstack[0]=new PXTriangulatedStack();
+  int ok=tstack[0]->Load(fname1);
+  if (debugmode)
+      fprintf(stderr,"Loaded tstack[0] from %s (%d)\n",fname1,ok);
+  tstack[0]->generateNeighbours(1);
+  tstack[1]=new PXTriangulatedStack();
+  ok=tstack[1]->Load(fname2);
+  if (debugmode)
+      fprintf(stderr,"Loaded tstack[1] from %s (%d)\n",fname2,ok);
+  tstack[1]->generateNeighbours(1);
+  init(tstack[0]->getnumpoints());
+  hasStack[0]=1; hasStack[1]=1; 
+}
+// --------------------------------------------------------------------------
+PXShapeTrackingClass::PXShapeTrackingClass(PXTriangulatedStack* stack1,
+					   PXTriangulatedStack* stack2)
+{
+  tstack[0]=new PXTriangulatedStack(stack1);
+  tstack[0]->generateNeighbours(1);
+  tstack[1]=new PXTriangulatedStack(stack2);
+  tstack[1]->generateNeighbours(1);
+  init(tstack[0]->getnumpoints());
+  hasStack[0]=1; hasStack[1]=1; 
+}
+// --------------------------------------------------------------------------
+PXShapeTrackingClass::~PXShapeTrackingClass()
+{
+  cleanup();
+}
+// --------------------------------------------------------------------------
+void PXShapeTrackingClass::nextFrame(const char* newstack2fname,int deform)
+{
+  if (!hasstack(0))
+      {
+	fprintf(stderr,"Does not have stack 0\n");
+	return;
+      }
+
+  if (!hasstack(1))
+      tstack[1]=new PXTriangulatedStack();
+
+  int ok=tstack[1]->Load(newstack2fname);
+  if (ok)
+      tstack[1]->generateNeighbours(1);
+  if (debugmode)
+      fprintf(stderr,"Loaded tstack[1] from %s (%d)\n",newstack2fname,ok);
+  if (deform && hasdisplacements())
+      tstack[0]->deformUsingDisplacements(displacements,1.0,0);
+}
+// --------------------------------------------------------------------------
+void PXShapeTrackingClass::nextFrame(PXTriangulatedStack* newstack2,int deform)
+{
+  if (!hasstack(0))
+      {
+	fprintf(stderr,"Does not have stack 0\n");
+	return;
+      }
+
+  if (!hasstack(1))
+      tstack[1]=new PXTriangulatedStack();
+
+
+  tstack[1]->Copy(newstack2);
+  tstack[1]->generateNeighbours(1);
+  if (deform && hasdisplacements())
+      tstack[0]->deformUsingDisplacements(displacements,1.0,0);
+}
+// --------------------------------------------------------------------------
+void PXShapeTrackingClass::init(int np)
+{
+  numpoints=Irange(np,0,10000000);
+  if (numpoints>0)
+      {
+	displacements=new PX3Vector[numpoints];
+	confidences=new float[numpoints];
+	used=new int[numpoints];
+	correspondence=new int[numpoints];
+	fixed=new int[numpoints];
+	for (int i=0;i<numpoints;i++)
+	    {
+	      displacements[i].setvector(0.0,0.0,0.0);
+	      confidences[i]=1.0;
+	      used[i]=0; fixed[i]=0; correspondence[i]=0;
+	    }
+	hasDisplacements=1;
+      }
+  else
+      hasDisplacements=0;
+}
+// --------------------------------------------------------------------------
+void PXShapeTrackingClass::cleanup() 
+{
+  if (hasDisplacements)
+      {
+	delete [] displacements;
+	delete [] confidences;
+	delete [] used;
+	delete [] correspondence;
+	delete [] fixed;
+      }
+  for (int i=0;i<=1;i++)
+      {
+	if (hasstack(i))
+	    delete tstack[i];
+	hasStack[i]=0;
+      }
+  hasDisplacements=0;
+  numpoints=0;
+}
+// --------------------------------------------------------------------------
+void PXShapeTrackingClass::Copy(PXShapeTrackingClass* other)
+{
+  cleanup();
+  for (int ia=0;ia<=1;ia++)
+      {
+	if (other->hasstack(ia))
+	    {
+	      tstack[ia]=new PXTriangulatedStack(other->getstack(ia));
+	      hasStack[ia]=1;
+	    }
+	  }
+
+  int np=other->getnumpoints();
+  if (np>0)
+      {
+	init(np);
+	for (int i=0;i<np;i++)
+	    {
+	      displacements[i].copy(other->getdisplacement(i));
+	      confidences[i]=other->getconfidence(i);
+	      used[i]=other->getused(i);
+	      correspondence[i]=other->getcorrespondence(i);
+	      fixed[i]=other->getfixed(i);
+	    }
+      }
+}
+// --------------------------------------------------------------------------
+int PXShapeTrackingClass::saveStackInventor(const char* fname,int colormode)
+{
+  if (!hasstack(0) || !hasdisplacements())
+      {
+	fprintf(stderr,"Does not have stack 0 or displacements\n");
+	return 0;
+      }
+
+  colormode=Irange(colormode,0,2);
+  
+  if (debugmode)
+      fprintf(stderr,"Saving stack %d in %s (colormode=%d)\n",0,fname,colormode);
+  
+  if (colormode==0 || !hasdisplacements())
+      return tstack[0]->Save(fname);
+
+  PXColorPoint* colors=new PXColorPoint[numpoints];
+  float max=0.00001,v=0.0;
+ 
+  int i;
+  for (i=0;i<numpoints;i++)
+      {
+	if (colormode==1)
+	    v=displacements[i].getlength();
+	else
+	    v=confidences[i];
+	max=Fmax(v,max);
+      }
+  
+  for (i=0;i<numpoints;i++)
+      {
+	if (colormode==1)   
+	    v=displacements[i].getlength()/max;
+	else 
+	    v=confidences[i];
+
+	if (v<0.3)
+	    {
+	      colors[i].red  =0.0;
+	      colors[i].blue =0.0;
+	      colors[i].green=1.0;
+	    }
+	else if (v<0.7)
+	    {
+	      colors[i].red =0.5;
+	      colors[i].blue=1.0;
+	      colors[i].green=1.0;
+	    }
+	else
+	    {
+	      colors[i].red=  1.0;
+	      colors[i].blue=  0.0;
+	      colors[i].green =0.5;
+	    }
+      }
+  int ok=tstack[0]->SaveInventor(fname,colors);  
+  delete [] colors;
+  return ok;
+}
+// --------------------------------------------------------------------------
+int PXShapeTrackingClass::saveInventor(const char* fname,int number)
+{
+  if (!hasstacks() || !hasdisplacements())
+      {
+	fprintf(stderr,"Does not have stacks or displacements\n");
+	return 0;
+      }
+
+  char* line=new char[strlen(fname)+10];
+  sprintf(line,"%s.%02d.iv",fname,number);
+  int ok=saveInventor(line);
+  delete [] line;
+  return ok;
+}
+// --------------------------------------------------------------------------
+int PXShapeTrackingClass::saveDeformed(const char* base,int number)
+{
+  if (!hasstack(0) || !hasdisplacements())
+      {
+	fprintf(stderr,"Does not have stacks or displacements\n");
+	return 0;
+      }
+
+  char* line=new char[strlen(base)+10];
+  sprintf(line,"%s.%02d.iv",base,number);
+  tstack[0]->deformUsingDisplacements(displacements,1.0,0);
+  int ok=tstack[0]->SaveInventor(line);
+  tstack[0]->deformUsingDisplacements(displacements,-1.0,0);
+  delete [] line;
+  return ok;
+}
+// --------------------------------------------------------------------------
+int PXShapeTrackingClass::saveInventor(const char* fname)
+{
+  if (!hasstack(0) || !hasdisplacements())
+      {
+	fprintf(stderr,"Does not have stacks or displacements\n");
+	return 0;
+      }
+
+  int status=0;
+  FILE *fout=fopen(fname,"w");
+  if (fout)
+      {
+	status=1;
+	fprintf(fout,"#Inventor V2.0 ascii\nSeparator {\n");
+	fprintf(fout,"DrawStyle { lineWidth 0.25 }\n");
+	fprintf(fout,"Material {  diffuseColor 0.2 0.2 0.0 \n transparency 0.2}\n" );
+	tstack[0]->SaveInventor(fout);
+	if (hasstack(1))
+	    {
+	      fprintf(fout,"Material {  diffuseColor 0.0 0.0 0.2 \n transparency 0.4}\n" );
+	      tstack[1]->SaveInventor(fout);
+	    }
+
+	fprintf(fout,"DrawStyle { lineWidth 4.0 }\n");
+	fprintf(fout,"Coordinate3{ point[\n");
+	int i;
+	for (i=0;i<tstack[0]->getnumpoints();i++)
+	    fprintf(fout,"%6.3f %6.3f %6.3f,\n",
+		    (tstack[0]->getpoint(i))->x[0],
+		    (tstack[0]->getpoint(i))->x[1],
+		    (tstack[0]->getpoint(i))->x[2]);
+	float mult=1.0;
+	for (i=0;i<tstack[0]->getnumpoints();i++)
+	    fprintf(fout,"%6.3f %6.3f %6.3f,\n",
+		    (tstack[0]->getpoint(i))->x[0]+mult*displacements[i].x[0],
+		    (tstack[0]->getpoint(i))->x[1]+mult*displacements[i].x[1],
+		    (tstack[0]->getpoint(i))->x[2]+mult*displacements[i].x[2]);
+	
+	fprintf(fout,"]}\n");
+	
+	for (int pass=0;pass<=2;pass++)
+	    {
+	      switch(pass)
+		  {
+		  case 0:
+		    fprintf(fout,"Material {  emissiveColor 0.5 0.5 0.0 \n transparency 0.0 }\n");
+		    break;
+		  case 1:
+		    fprintf(fout,"Material {  emissiveColor 0.5 0.0 0.0 \n transparency 0.0}\n");
+		    break;
+		  case 2:
+		    fprintf(fout,"Material {  emissiveColor 0.0 0.5 0.0 \n transparency 0.0}\n" );
+		    break;
+		  }
+	      
+	      fprintf(fout,"IndexedLineSet{ coordIndex[\n");
+	      
+	      for (i=0;i<tstack[0]->getnumpoints();i++)
+		  {
+		    if (pass==fixed[i]+used[i])
+			fprintf(fout,"%d,%d,-1,\n",i,i+tstack[0]->getnumpoints());
+		  }
+	      fprintf(fout,"]}\n");
+	    }
+	fprintf(fout,"}\n");
+	fclose(fout);
+
+
+	if (debugmode)
+	    fprintf(stderr,"Saving in %s \n",fname);
+      }
+  return status;
+}
+// --------------------------------------------------------------------------
+int PXShapeTrackingClass::findSymmetricPair(PXNeighboursList* pairs,int seedt)
+{
+  if (!hasstacks())
+      return 0;
+
+  static int count=0;
+
+  if (debugmode && count==0)
+      {
+	fprintf(stderr,"Using Symmetric Nearest Neighbour (%d,%d)\n",
+		tstack[0]->getnumpoints(),tstack[1]->getnumpoints());
+	count=1;
+      }
+
+  int done=0,steps=0;
+  int seedpoint=Irange(seedt,0,tstack[0]->getnumpoints()-1);
+  int bestpoint=0,bestpoint2=0;
+  
+  while(!done && steps<10)
+      {
+	float x[3],x0[3];
+	int ia;
+	for (ia=0;ia<=2;ia++)
+	    x[ia]=(tstack[0]->getpoint(seedpoint))->x[ia];
+	tstack[1]->findnearestpoint(x[0],x[1],x[2],bestpoint,0,0.01);
+	
+	for (ia=0;ia<=2;ia++)
+	     x0[ia]=(tstack[1]->getpoint(bestpoint))->x[ia];
+
+	tstack[0]->findnearestpoint(x0[0],x0[1],x0[2],bestpoint2,0,0.01);
+	if (seedpoint==bestpoint2)
+	    done=1;
+	else
+	    seedpoint=bestpoint2;
+	
+	steps++;
+      }
+  
+  if (steps<10)
+      {
+	PXIntegerList* firstpairs=new PXIntegerList();
+	firstpairs->Add(seedpoint);
+	firstpairs->Add(bestpoint+tstack[0]->getnumpoints());
+	
+	if (pairs->getnumnodes()==0)
+	    {
+	      pairs->Add(firstpairs,pairs->getnumnodes()+1);
+	    }
+	else
+	    {
+	      pairs->Rewind();
+	      int found=0,i=0;
+	      while (i<pairs->getnumnodes() && found==0)
+		  {
+		    PXIntegerList* element=(pairs->getcurrentnode())->points;
+		    if (element->numberinCommon(firstpairs)==2)
+			found=1;
+		    i++;
+		    pairs->Next();
+		  }
+	      if (found==0)
+		  {
+		    pairs->Add(firstpairs,pairs->getnumnodes()+1);
+		  }
+	    }
+	delete firstpairs;
+	return 1;
+      }
+  return 0;
+}
+// --------------------------------------------------------------------------
+int PXShapeTrackingClass::smoothEuclidean(int movefixed,int subpixel)
+{
+  if (!hasdisplacements() || !hasstacks())
+      return 0;
+
+  if (debugmode)
+      fprintf(stderr,"\t1. Averaging step (moving fixed=%d,subpixel=%d)\n",
+	      movefixed,subpixel);
+  
+  int good=0,pt;
+  
+  PX3Vector* olddisp=new PX3Vector[numpoints];
+
+  for (pt=0;pt<tstack[0]->getnumpoints();pt++)
+      {
+	if (fixed[pt]==0 || movefixed>0)
+	    {
+	      olddisp[pt].copy(&displacements[pt]);
+	      good+=used[pt];
+	      PXIntegerList* neigh=tstack[0]->getneighbours(pt);
+	      neigh->Rewind();
+	      int numgood=0;
+	      float newx[3];
+	      for (int ia=0;ia<=2;ia++)
+		  newx[ia]=0.0;
+	      for (int n=0;n<neigh->getnumnodes();n++)
+		  {
+		    int ind=neigh->getcurrent();
+		    if (used[ind]==1)
+			{
+			  numgood++;
+			  for (int ia=0;ia<=2;ia++)
+			      newx[ia]+=olddisp[ind].x[ia];
+			}
+		    neigh->Next();
+		  }
+	      if (numgood>0)
+		  {
+		    int ia;
+		    for (ia=0;ia<=2;ia++)
+			newx[ia]=newx[ia]/float(numgood);
+		    float factor=0.75;
+		    if (used[pt]==0)
+			factor=1.0;
+		    for (ia=0;ia<=2;ia++)
+			displacements[pt].x[ia]=(1.0-factor)*olddisp[pt].x[ia]+factor*newx[ia];
+		    used[pt]=1;
+		  }
+	    }
+      }
+  delete [] olddisp;
+  good=0;
+  for( pt=0;pt<tstack[0]->getnumpoints();pt++)
+      {
+	used[pt]=abs(used[pt]);
+	good+=used[pt];
+      }
+  
+  if (debugmode)
+      {
+	fprintf(stderr,"\t\t (%d/%d) points have displacements\n",good,tstack[0]->getnumpoints());
+	fprintf(stderr,"\t2. Mapping step\n");
+      }
+
+
+  float dist=0.0,maxshift=0.0,maxdist=0.0;
+  int reverse=0;
+  for (pt=0;pt<tstack[0]->getnumpoints();pt++)
+      {
+	if (debugmode)
+	    {
+	      if (100*int(pt/100)==pt && pt>0)
+		  fprintf(stderr,"%d/%d ",pt,tstack[0]->getnumpoints());
+	      if (600*int(pt/600)==pt && pt>0)
+		  fprintf(stderr,"\n");
+	    }
+	PXTriangulatedStackPoint* point1=tstack[0]->getpoint(pt);
+	if ((used[pt]>0) && (fixed[pt]!=1 || good==tstack[0]->getnumpoints()))
+	    {
+	      float x[3];
+	      int ia;
+	      for (ia=0;ia<=2;ia++)
+		  x[ia]=point1->x[ia]+displacements[pt].x[ia]; 
+	      int mp;
+	      float d=tstack[1]->findnearestpoint(x[0],x[1],x[2],mp,subpixel,0.0);
+	      dist+=d;
+	      for (ia=0;ia<=2;ia++)
+		  {
+		    x[ia]=x[ia]-point1->x[ia]; 
+		    displacements[pt].x[ia]=x[ia];
+		  }
+	      maxdist=Fmax(maxdist,d);
+	      maxshift=Fmax(maxshift,Fsqdist( x[0],x[1],x[2],0.0,0.0,0.0));
+	      correspondence[pt]=mp;
+	    }
+      }
+  if (debugmode)
+      fprintf(stderr,"\t\taverage mapping distance %6.3f (max=%6.3f) maxshift=%6.3f rev=%d\n",
+	      dist/float(good),maxdist,sqrt(maxshift),reverse);
+
+  return good;
+}
+// --------------------------------------------------------------------------
+int PXShapeTrackingClass::smoothConnection(int movefixed)
+{
+  if (!hasdisplacements() || !hasstacks())
+      return 0;
+
+  if (debugmode)
+      fprintf(stderr,"\t1. Maxdistance minimizing step (moving fixed=%d)\n",movefixed);
+  int shift=0;
+
+  for (int pt=0;pt<tstack[0]->getnumpoints();pt++)
+      {
+	if (fixed[pt]==0 || movefixed==1)
+	    {
+	      PXIntegerList* neigh=tstack[0]->getneighbours(pt);
+	      neigh->Rewind();
+	      int bestcenter=correspondence[pt];
+	      int bestdist=0,bestmindist=100000000;
+	      for (int n=0;n<neigh->getnumnodes();n++)
+		  {
+		    int ind=neigh->getcurrent();
+		    int dist=tstack[1]->getrelationship(correspondence[pt],correspondence[ind],100);
+		    if (dist<0) 
+			dist=100;
+		    bestdist=Imax(dist,bestdist);
+		    bestmindist=Imin(dist,bestmindist);
+		    neigh->Next();
+		  }
+	      PXIntegerList* candidates=tstack[1]->getneighbours(correspondence[pt]);
+	      candidates->Rewind();
+	      for (int i=0;i<candidates->getnumnodes();i++)
+		  {
+		    int cand=candidates->getcurrent();
+		    neigh->Rewind();
+		    int maxd=0,mind=100000000;
+		    for (int j=0;j<neigh->getnumnodes();j++)
+			{
+			  int ind=neigh->getcurrent();
+			  int dist=tstack[1]->getrelationship(cand,correspondence[ind],100);
+			  if (dist<0)
+			      dist=101;
+			  maxd=Imax(maxd,dist);
+			  mind=Imin(mind,dist);
+			  neigh->Next();
+			}
+		    if (maxd<bestdist)
+			{
+			  bestdist=maxd;
+			  bestmindist=mind;
+			  bestcenter=cand;
+			}
+		    candidates->Next();
+		  }
+	      PXTriangulatedStackPoint* point1=tstack[0]->getpoint(pt);
+	      PXTriangulatedStackPoint* point2=tstack[1]->getpoint(bestcenter);
+	      if (bestcenter!=correspondence[pt])
+		  {
+		    correspondence[pt]=bestcenter;
+		    shift++;
+		  }
+	      for (int ia=0;ia<=2;ia++)
+		  displacements[pt].x[ia]=point2->x[ia]-point1->x[ia];
+	    }
+	
+	if (debugmode)
+	    {
+	      if (100*int(pt/100)==pt && pt>0)
+		  fprintf(stderr,"%d/%d (%d), ",pt,tstack[0]->getnumpoints(),shift);
+	      if (600*int(pt/600)==pt && pt>0)
+		  fprintf(stderr,"\n");
+	    }
+      }
+  if (debugmode)
+      fprintf(stderr,"   [ %d points shifted]\n",shift);
+
+  return shift;
+}
+// --------------------------------------------------------------------------
+int PXShapeTrackingClass::findSmoothMap(int mode,int iterations,int smoothiterations,int subdivide)
+{
+  if (!hasdisplacements() || !hasstacks())
+      return 0;
+
+  subdivide=Irange(subdivide,0,3);
+  for(int ip=0;ip<subdivide;ip++)
+      tstack[1]->subdivide();
+
+  int numiter=0;
+  int postmode=smoothiterations>0;
+  mode=Irange(mode,0,2);
+  int id=-1;
+
+  if (debugmode)
+      {
+	fprintf(stderr," Find Smooth Map:\n");
+	switch(mode)
+	    {
+	    case 2:
+	      fprintf(stderr," Using global `connection-based' nearest neighbour initialization (post=%d)\n",
+		      postmode);
+	      break;
+	    case 1:
+	      fprintf(stderr," Using global `euclidean-based' nearest neighbour initialization (post=%d)\n",
+		      postmode);
+	      break;
+	    default:
+	      fprintf(stderr," Using nearest neighbour initialization (post=%d)\n",postmode);
+	      break;
+	    }
+      }
+
+  if (mode>0) // One of the two fancy initialization algorithms 
+      {
+	for (int ia=0;ia<=1;ia++)
+	  {
+	    if (debugmode)
+	      fprintf(stderr,"Generating Neighbours for stack %d np=%d\n",ia,tstack[ia]->getnumpoints());
+	    tstack[ia]->generateNeighbours();
+	  }
+	//if (!tstack[ia]->hasneighbours())
+
+	int inc=1;//tstack[0]->getnumpoints()/400+1;
+	PXNeighboursList* tetra=new PXNeighboursList();
+
+	if (debugmode)
+	    fprintf(stderr,"\nStarting Symmetric Neighbour Search inc=%d points=%d\n",
+		    inc,tstack[0]->getnumpoints());
+
+	for (int pt=0;pt<tstack[0]->getnumpoints();pt+=inc)
+	    {
+	      if (debugmode)
+		  {
+		    if (100*int(pt/100)==pt && pt>0)
+		      fprintf(stderr,"%d/%d (%d)  ",pt,tstack[0]->getnumpoints(),tetra->getnumnodes());
+		    if (400*int(pt/400)==pt && pt>0)
+		      fprintf(stderr,"\n");
+		  }
+	      findSymmetricPair(tetra,pt);
+	    }
+	if (debugmode)
+	    {
+	      fprintf(stderr," done\n");
+	      fprintf(stderr,"\n Stack1 (numpoints) = %d , Stack 2 (numpoints) =%d \n",
+		      tstack[0]->getnumpoints(),tstack[1]->getnumpoints());
+	      fprintf(stderr,"Number of matches = %d \n", tetra->getnumnodes());
+	      fprintf(stderr,"----------------------------------\n");
+	    }
+
+	tetra->Rewind();
+	
+	// Find displacement vectors
+	for (int i=0;i<tetra->getnumnodes();i++)
+	    {
+	      PXIntegerList* pair=(tetra->getcurrentnode())->points;
+	      pair->Rewind();	      
+	      int index1=pair->getcurrent();
+	      pair->Next();
+	      int index2=pair->getcurrent();
+	      PXTriangulatedStackPoint* point1=tstack[0]->getpoint(index1);
+	      PXTriangulatedStackPoint* point2=tstack[1]->getpoint(index2-tstack[0]->getnumpoints());
+	      
+	      for (int ia=0;ia<=2;ia++)
+		  displacements[index1].x[ia]=point2->x[ia]-point1->x[ia];
+
+	      used[index1]=1;	fixed[index1]=1;
+	      correspondence[index1]=index2-tstack[0]->getnumpoints();
+	      tetra->Next();
+	    }
+	
+	int numgood=tetra->getnumnodes();
+	delete tetra;
+	if (debugmode>1)
+	    {
+	      saveInventor("/tmp/iter",1);
+	      saveDeformed("/tmp/deformed",1);
+	    }
+	
+	int nmode=0;
+
+	for (int iter=1;iter<=iterations;iter++)
+	    {
+	      numiter=iter;
+	      if (debugmode)
+		  {
+		    fprintf(stderr,"\n----------------------\n");
+		    fprintf(stderr,"Smoothing iteration %d\n",iter);
+		    if (debugmode>1)
+			  id=iter+1;
+		  }
+	      
+	      if (mode==1)
+		  {
+		    if (numgood==tstack[0]->getnumpoints())
+			numgood=smoothEuclidean(1,0);
+		    else
+			numgood=smoothEuclidean(0,0);
+		  }
+	      else
+		  {
+		    int mved=1;
+		    if (numgood<tstack[0]->getnumpoints())
+			{
+			  numgood=smoothEuclidean(0,0);
+			}
+		    else
+			{
+			  if (nmode==0)
+			      {
+				tstack[0]->generateNeighbours(1);
+				nmode=1;
+			      }
+			  if (debugmode)
+			      fprintf(stderr,"Smoothing Connection\n");
+			  mved=smoothConnection(1);
+			  if (mved==0)
+			      iter=iterations+1;
+			}
+		  }
+	      if (debugmode>1)
+		  {
+		    saveInventor("/tmp/iter",id);
+		    saveDeformed("/tmp/deformed",id);
+		  }
+	    }
+      }
+  else // Simple Euclidean Nearest Neighbour 
+      {
+	numiter=2;
+	for (int pt=0;pt<tstack[0]->getnumpoints();pt++)
+	    {
+	      if (debugmode)
+		  {
+		    if (100*int(pt/100)==pt && pt>0)
+			fprintf(stderr,"%d/%d ",pt,tstack[0]->getnumpoints());
+		    if (700*int(pt/700)==pt && pt>0)
+			fprintf(stderr,"\n");
+		  }
+	      PXTriangulatedStackPoint* point1=tstack[0]->getpoint(pt);
+	      float x[3];
+	      int ia;
+	      for (ia=0;ia<=2;ia++)
+		  x[ia]=point1->x[ia];
+	      int mp;
+	      tstack[1]->findnearestpoint(x[0],x[1],x[2],mp,0,0.0);
+	      correspondence[pt]=mp;
+	      fixed[pt]=0; used[pt]=1;
+	      for (ia=0;ia<=2;ia++)
+		  displacements[pt].x[ia]=x[ia]-point1->x[ia];
+	    }
+	id=1;
+	if (debugmode>1)
+	    {
+	      saveInventor("/tmp/iter",id);
+	      saveDeformed("/tmp/deformed",id);
+	    }
+      }
+  
+  if (postmode>0)
+      {
+	tstack[0]->generateNeighbours(1);
+	tstack[0]->deformUsingDisplacements(displacements,1.0,0);
+	PX3Vector* dp=tstack[0]->nonShrinkSmoothD(0.16,-0.165,
+						  Irange(smoothiterations,1,50),2);
+	tstack[0]->deformUsingDisplacements(dp,-1.0,0);
+	tstack[0]->deformUsingDisplacements(displacements,-1.0,0);
+	for (int i=0;i<tstack[0]->getnumpoints();i++)
+	    for (int ia=0;ia<=2;ia++)
+		displacements[i].x[ia]+=dp[i].x[ia];
+
+
+	delete [] dp;
+      }
+  
+  if (debugmode>1)
+      {
+	saveInventor("/tmp/iter",id+1);
+	saveDeformed("/tmp/deformed",id+1);
+      }
+  return (numiter);
+}
+// ------------------------------------------------------------------------
+int PXShapeTrackingClass::initialCurvatureTracking(int searchwindow)
+{
+  if (!hasdisplacements() || !hasstacks())
+      return 0;
+
+  searchwindow=Irange(searchwindow,0,20);
+  if (debugmode)
+      fprintf(stderr,"\n Initial Curvature Matching Step (window=%d)\n",searchwindow);
+
+  PXIntegerList* searchPoints=new PXIntegerList();
+  double min1=100000.0,min2=100000.0;
+  int nptot=0;
+  // conf=new PX3Vector[numpoints];
+  double* minMatchDist=new double[numpoints];
+  double* aveMatchDist=new double[numpoints];
+  double* sigMatchDist=new double[numpoints];
+  double* extraFactor =new double[numpoints];
+
+  // Find Initial Match 
+  int pt1;
+  for (pt1=0;pt1<tstack[0]->getnumpoints();pt1++)
+      {
+	PXTriangulatedStackPoint* point1=tstack[0]->getpoint(pt1);
+	int pt2=correspondence[pt1];
+	PXTriangulatedStackPoint* point2;//=tstack[1]->getpoint(pt2);
+	int np2=tstack[1]->collectNeighbours(pt2,searchwindow,searchPoints);
+	nptot+=np2;
+	int bestpt2=pt2;
+	searchPoints->Rewind();
+	
+	double minebe=100000.0,sumebe=0.0,sum2ebe=0.0;
+	for (pt2=0;pt2<np2;pt2++)
+	  {
+	    point2=tstack[1]->getpoint(searchPoints->getcurrent());
+	    double ebe=0.0;
+	    
+	    for (int ia=0;ia<=1;ia++)
+	      {
+		ebe+=pow(point2->k[ia]-point1->k[ia],float(2.0));
+	      }
+	    ebe*=0.5;
+
+	    if (ebe<minebe)
+	      {
+		minebe=ebe;
+		bestpt2=searchPoints->getcurrent();
+	      }
+	    
+
+			
+	    sumebe+=ebe;
+	    sum2ebe+=pow(ebe,double(2.0));
+	    searchPoints->Next();
+	  }
+	
+	point2=tstack[1]->getpoint(bestpt2);
+	
+	// This is the actual displacement estimate
+	for (int ia=0;ia<=2;ia++)
+	  displacements[pt1].x[ia]=point2->x[ia]-point1->x[ia];
+	
+
+	// Store min difference, mean difference and sigma for confidence estimation 
+	if (np2>1)
+	  {
+	    sumebe=(sumebe-minebe)/double(np2-1);
+	    sum2ebe=(sum2ebe-minebe*minebe)/double(np2-1);
+	    minMatchDist[pt1]=minebe;
+	    aveMatchDist[pt1]=sumebe;
+	    sigMatchDist[pt1]=(sum2ebe-pow(aveMatchDist[pt1],double(2.0)));
+	    double bend=pow(point1->k[0],float(2.0))+pow(point1->k[1],float(2.0));
+	    if (bend<0.001)
+	      bend=0.0001;
+	    extraFactor[pt1]=sqrt(bend);// *double(np2);
+	  }
+	else
+	  {
+	    // In this unlikely case let it blow up to large values low confidence 
+	    fprintf(stderr,"*np2=0*pt=%d\n",pt1);
+	    minMatchDist[pt1]=10000.1;
+	    aveMatchDist[pt1]=10000.0;
+	    sigMatchDist[pt1]=10000.0;
+	    extraFactor[pt1]=0.01;
+	  }
+	
+	
+	// This is needed for scaling
+	min1=Fmin(min1,minMatchDist[pt1]);
+	min2=Fmin(min2,minMatchDist[pt1]/(Fmax(aveMatchDist[pt1]-sigMatchDist[pt1],0.00001)));
+	
+	if (debugmode>1)
+	  {
+	    if (100*int(pt1/100)==pt1)
+	      {
+		fprintf(stderr,"%d/%d (np=%d,min=%10.8f ave=%10.8f sig=%10.8f)\n",
+			pt1,tstack[0]->getnumpoints(),np2,
+			minMatchDist[pt1],aveMatchDist[pt1],sigMatchDist[pt1]);
+		fprintf(stderr,"\t\t minebe=%f, sumebe=%f sum2ebe=%f\n",
+			minebe,sumebe,sum2ebe);
+		fprintf(stderr," pt1=%d k1=%7.5f k2=%7.5f \t pt2=%d k1=%7.5f k2=%7.5f\n",
+			pt1,point1->k[0],point1->k[1],bestpt2,point2->k[0],point2->k[1]);
+	      }
+	  }
+      }
+  
+  double K1 = 0.01 / Fmax(min1,0.0001);
+  double K2 = 0.01 / Fmax(min2,0.0001);
+  
+  float maxconf=0.0;
+  for(pt1=0; pt1<tstack[0]->getnumpoints(); pt1++)
+    {
+      double mg=minMatchDist[pt1];
+      double mu=minMatchDist[pt1]/Fmax(aveMatchDist[pt1]-sigMatchDist[pt1],0.00001);
+      confidences[pt1] = /*extraFactor[pt1]*/(1.0 / (  ( 1.0+ K1*mg)*(1.0+K2*mu)));
+      maxconf=Fmax(maxconf,confidences[pt1]);
+    }
+  
+  float sumconf=0.0;
+  for (pt1=0;pt1<tstack[0]->getnumpoints();pt1++)
+    {
+      confidences[pt1]/=maxconf;
+      sumconf+=confidences[pt1];
+    }
+  sumconf/=(float(tstack[0]->getnumpoints()));
+  // Do Gamma-like correction so that mean becomes 0.5
+  float gamma=log(0.5)/log(sumconf);
+  
+  if (debugmode)
+    fprintf(stderr,"Done with confidence values\n\t mean=%6.4f gamma=%6.4f \n",sumconf,gamma);
+  
+  sumconf=0.0; 
+  float sum2conf=0.0;
+  
+  for (pt1=0;pt1<tstack[0]->getnumpoints();pt1++)
+    {
+      confidences[pt1]=pow(confidences[pt1],gamma);
+      sumconf+=confidences[pt1];
+      sum2conf+=pow(confidences[pt1],float(2.0));
+      
+      if (debugmode>1)
+	if (100*int(pt1/100)==pt1 && pt1>0)
+	  fprintf(stderr,"%d/%d (min=%10.7f ave=%10.7f sig=%10.7f conf=%10.7f)\n",
+		  pt1,tstack[0]->getnumpoints(),
+		  minMatchDist[pt1],aveMatchDist[pt1],sigMatchDist[pt1],confidences[pt1]);
+    }
+  sumconf/=(float(tstack[0]->getnumpoints()));
+  sum2conf/=(float(tstack[0]->getnumpoints())); 
+  if (debugmode)
+    {
+      fprintf(stderr,"Done with adjusting confidence values\n\t mean=%6.4f std=%6.4f\n",
+	      sumconf,sqrt(sum2conf-sumconf*sumconf));
+      fprintf(stderr,"Total points compared =%d ave=%6.2f\n",nptot,
+	      float(nptot)/float(tstack[0]->getnumpoints()));
+    }
+  
+  if (debugmode>1)
+    {
+      tstack[0]->deformUsingDisplacements(displacements,1.0,0); 
+      tstack[0]->SaveInventor("/tmp/defcurv.01.iv");
+      tstack[0]->deformUsingDisplacements(displacements,-1.0,0); 
+    }
+  delete searchPoints;
+  delete [] minMatchDist;
+  delete [] aveMatchDist;
+  delete [] sigMatchDist;
+  delete [] extraFactor;
+  return 1;
+}
+// ------------------------------------------------------------------------
+int PXShapeTrackingClass::smoothCurvatureTracking(int iterations,float lambda)
+  {
+  if (!hasdisplacements() || !hasstacks())
+      return 0;
+
+  lambda=Frange(lambda,0.01,0.99);
+  iterations=Irange(iterations,1,1000);
+  const float EPS=1.e-4;
+
+  if (debugmode>1)
+      {
+	saveInventor("/tmp/curviter",1);
+	saveDeformed("/tmp/curvdeformed",1);
+      }
+
+  /* smoothing the initial matching vector */
+  /** the smoothing part **/
+  float* sm=new float[numpoints];
+  int k;
+  for(k=0; k<3; k++)
+      {
+	int i;
+	for(i=0; i<numpoints; i++)
+	    sm[i] = displacements[i].x[k];
+       
+       /*** set the converge rule */
+       float anormf = 0.0;
+       for(i=0; i<numpoints; i++)
+	   if(displacements[i].x[k]!=-1000.0)
+	       anormf += fabs(displacements[i].x[k]);
+       
+       if(k==0)
+	   printf("dx:  anormf = %f, EPS*anormf = %f\n",anormf,EPS*anormf);
+       if(k==1)
+	   printf("dy:  anormf = %f, EPS*anormf = %f\n",anormf,EPS*anormf);
+       if(k==2)
+	   printf("dz:  anormf = %f, EPS*anormf = %f\n",anormf,EPS*anormf);
+       
+       /*** smoothing iteration ***/
+       for(int m=0; m<iterations; m++)
+	   {
+	     if (debugmode)
+		 fprintf(stderr,"iteration no. %d:\n", m);
+	     
+	     float resid = 0.0;
+	     for(int i=0; i<numpoints; i++)
+		 {
+		   /**** compute the new value and residual ****/		
+		   float oldp = sm[i];
+		   float factor=confidences[i]*(1.0-lambda);
+		   float sumconf = factor;
+		   sm[i] = displacements[i].x[k] * factor;
+		   
+		   PXIntegerList* nlist=tstack[0]->getneighbours(i);
+		   nlist->Rewind();
+		   int n=nlist->getnumnodes();
+		   for(int j=0;j<nlist->getnumnodes();j++)
+		       {
+			 int p=nlist->getcurrent();
+			 nlist->Next();
+			 factor=lambda * 1.0/float(n+0.0001) * confidences[p];
+			 sumconf+=factor;
+			 sm[i] += sm[p] * factor;
+		       }
+		   
+		   sm[i] = sm[i] / sumconf;
+		   float newp = sm[i];
+		   resid += fabs(newp-oldp);
+		   
+		 }/* end of i loop */
+	     if (debugmode)
+		 fprintf(stderr,"resid = %f\n", resid);
+	     if(m>0 && resid<=EPS*anormf) 
+		 m = iterations;
+	   }/* end of iteration */
+       
+       /** get the smoothed dx/dy/dz **/
+       for(i=0; i<numpoints; i++)
+	   displacements[i].x[k]=sm[i];
+     }
+
+ delete [] sm;
+
+ float maxshift=0.0,dist=0.0,maxdist=0.0;
+ 
+ for (int pt=0;pt<tstack[0]->getnumpoints();pt++)
+     {
+       if (debugmode)
+	   {
+	     if (100*int(pt/100)==pt && pt>0)
+		 fprintf(stderr,"%d/%d ",pt,tstack[0]->getnumpoints());
+	     if (600*int(pt/600)==pt && pt>0)
+		 fprintf(stderr,"\n");
+	   }
+       PXTriangulatedStackPoint* point1=tstack[0]->getpoint(pt);
+       float x[3];
+       int ia;
+       for (ia=0;ia<=2;ia++)
+	   x[ia]=point1->x[ia]+displacements[pt].x[ia]; 
+       int mp;
+       float d=tstack[1]->findnearestpoint(x[0],x[1],x[2],mp,1,0.0);
+       dist+=d;
+       for (ia=0;ia<=2;ia++)
+	   {
+	     x[ia]=x[ia]-point1->x[ia]; 
+	     displacements[pt].x[ia]=x[ia];
+	   }
+       
+       maxdist=Fmax(maxdist,d);
+       maxshift=Fmax(maxshift,Fsqdist( x[0],x[1],x[2],0.0,0.0,0.0));
+       correspondence[pt]=mp;
+     }
+ if (debugmode)
+     fprintf(stderr,"\t\taverage mapping distance %6.3f (max=%6.3f) maxshift=%6.3f ",
+	     dist/float(numpoints),maxdist,sqrt(maxshift));
+
+  if (debugmode>1)
+      {
+	saveInventor("/tmp/curviter",2);
+	saveDeformed("/tmp/curvdeformed",2);
+      }
+ 
+ return 1;
+}
+// ------------------------------------------------------------------------
+int PXShapeTrackingClass::Save(const char* fname,int donotsavebothstacks,int complevel)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout!=NULL)
+    {
+      int st=Save(fout,donotsavebothstacks);
+      fclose(fout);
+      return st;
+    }
+ return 0;
+}
+// ---------------------------------------------------
+int PXShapeTrackingClass::Load(const char* fname,int donotloadbothstacks)
+{
+ gzFile fin=gzsuffixopen(fname,"r");
+ if (fin)
+   {
+     int st=Load(fin,donotloadbothstacks);
+     gzclose(fin);
+     return st;
+   }
+ return 0;
+}
+// ---------------------------------------------------
+int PXShapeTrackingClass::Save(FILE* fout,int donotsavebothstacks)
+{
+  fprintf(fout,"#PXShapeTrackingClass numstacks,hasdisplacements,numpoints\n");
+  if (donotsavebothstacks)
+      fprintf(fout,"%d\n",hasStack[0]);
+  else
+      fprintf(fout,"%d\n",hasStack[0]+hasStack[1]);
+  fprintf(fout,"%d\n",hasDisplacements);
+  fprintf(fout,"%d\n",numpoints);
+ 
+ if (hasDisplacements)
+     {
+       fprintf(fout,"#-----------------Displacements-------------------------\n");
+       for (int i=0;i<numpoints;i++)
+	   {
+	     for (int ia=0;ia<=2;ia++)
+		 fprintf(fout,"%6.3f ",displacements[i].x[ia]);
+	     fprintf(fout,"%5.3f %d %d %6d\n",confidences[i],used[i],fixed[i],correspondence[i]);
+	   }
+     }
+
+ if (hasstack(0))
+     tstack[0]->Save(fout);
+ 
+  if (hasstack(1) && !donotsavebothstacks)
+      tstack[1]->Save(fout);
+  
+  return 1;
+}
+
+// ---------------------------------------------------
+int PXShapeTrackingClass::Load(gzFile fin,int donotloadbothstacks)
+{
+  char* line=new char[200];
+  gzgets(fin,line,200);
+  if (gzfindstringinstring(line,"#PXShapeTrackingClass")==0)
+    {
+      delete [] line;
+      return 0;
+    }
+  
+  cleanup();
+  
+  int num2;
+  gzgets(fin,line,200); sscanf(line,"%d",&num2);
+  gzgets(fin,line,200); sscanf(line,"%d",&hasDisplacements);
+  gzgets(fin,line,200); sscanf(line,"%d",&numpoints);
+ 
+  fprintf(stderr,"num2=%d hasDisplacements=%d numpoints=%d\n",
+	  num2,hasDisplacements,numpoints);
+ init(numpoints);
+ if (hasDisplacements)
+     {
+       gzgets(fin,line,200); 
+       for (int i=0;i<numpoints;i++)
+	   {
+	     gzgets(fin,line,200); 
+	     sscanf(line," %f %f %f %f %d %d %d",
+		    &displacements[i].x[0],&displacements[i].x[1],&displacements[i].x[2],
+		    &confidences[i],&used[i],&fixed[i],&correspondence[i]);
+	   }
+     }
+  
+
+ if (num2>0)
+     {
+       if (num2>1 && donotloadbothstacks)
+	   num2=1;
+       for (int ia=0;ia<num2;ia++)
+	   {
+	     tstack[ia]=new PXTriangulatedStack();
+	     tstack[ia]->Load(fin);
+	     hasStack[ia]=1;
+	   }
+     }
+
+
+ delete [] line;
+ if (debugmode)
+   {
+     fprintf(stderr,"Loaded shapetrclass hasStacks=%d,%d hasdispl=%d numpoints=%d (donotloadbothflag=%d)\n",
+	     hasStack[0],hasStack[1],hasDisplacements,numpoints,donotloadbothstacks);
+     if (hasStack[0])
+       fprintf(stderr,"\t stack[0] numpoints=%d\n",tstack[0]->getnumpoints());
+     if (hasStack[1])
+       fprintf(stderr,"\t stack[1] numpoints=%d\n",tstack[1]->getnumpoints());
+   }
+
+ return 1;
+}
+
+// ---------------------------------------------------
+void PXShapeTrackingClass::translate(float px,float py,float pz)
+{
+  if (!hasdisplacements())
+      return;
+  for (int i=0;i<getnumpoints();i++)
+      {
+	displacements[i].setvector(px,py,pz);
+	confidences[i]=1.0;
+      }
+
+}
+// ---------------------------------------------------
+void PXShapeTrackingClass::expand(float factor1,float factor2,float factor3)
+{
+  if (!hasdisplacements() || !hasstack(0))
+      return;
+  for (int i=0;i<getnumpoints();i++)
+      {
+	displacements[i].setvector(tstack[0]->getpoint(i)->nx[0]*factor1,
+				   tstack[0]->getpoint(i)->nx[1]*factor2,
+				   tstack[0]->getpoint(i)->nx[2]*factor3);
+	confidences[i]=1.0;
+      }
+}
+// ---------------------------------------------------
+int PXShapeTrackingClass::volumePreserveZshift(PXShapeTrackingClass* other)
+{
+  if (!hasstack(1) || !hasstack(0))
+      return 0;
+  
+  if (!other->hasstack(1) || !other->hasstack(0))
+      return 0;
+  
+  if (!getstack(0)->hasstackindex() || !getstack(1)->hasstackindex())
+      return 0;
+
+  if (!other->getstack(0)->hasstackindex() || !other->getstack(1)->hasstackindex())
+      return 0;
+
+
+  PXTriangulatedStack* endo[2];
+  PXTriangulatedStack* epi[2];
+  endo[0]=getstack(0);
+  endo[1]=getstack(1);
+  epi[0]=other->getstack(0);
+  epi[1]=other->getstack(1);
+  
+  if (endo[0]->getstackindex().numcontours!=epi[0]->getstackindex().numcontours)
+      {
+	fprintf(stderr,"Unequal number of levels endo/epi 0 exiting\n");
+	return 0;
+      }
+
+  if (endo[1]->getstackindex().numcontours!=epi[1]->getstackindex().numcontours)
+      {
+	fprintf(stderr,"Unequal number of levels endo/epi 1 exiting\n");
+	return 0;
+      }
+
+  // This is a tough one 
+  /*if (endo[0]->getstackindex().numcontours!=endo[1]->getstackindex().numcontours)
+      {
+	fprintf(stderr,"Endo[0]!=Endo[1] exiting\n");
+      }*/
+
+
+  int numlevels[2];
+  float* area[2];
+  float* z[2];
+
+  for (int fr=0;fr<=1;fr++)
+      {
+	numlevels[fr]=endo[fr]->getstackindex().numcontours;
+	area[fr]=new float[numlevels[fr]];
+	z[fr]=new float[numlevels[fr]];
+      }
+  
+
+  for (int frame=0;frame<=1;frame++)
+      {
+	for (int level=0;level<numlevels[frame];level++)
+	    {
+	      int be0=endo[frame]->getstackindex().index[level];
+	      int ee0=endo[frame]->getstackindex().index[level+1];
+	      int be1=epi[frame]->getstackindex().index[level];
+	      int ee1=epi[frame]->getstackindex().index[level+1];
+	      int j=0;
+	      
+	      PXContour* cntr=new PXContour();
+	      for (j=be0;j<ee0;j++)
+		  cntr->Add(endo[frame]->getpoint(j)->x[0],endo[frame]->getpoint(j)->x[1]);
+	      cntr->setclosed(1);
+	      
+	      PXContour* cntr2=new PXContour();
+	      for (j=be1;j<ee1;j++)
+		  cntr2->Add(epi[frame]->getpoint(j)->x[0],epi[frame]->getpoint(j)->x[1]);
+	      cntr2->setclosed(1);
+	      
+	      area[frame][level]=fabs(cntr2->getarea()-cntr->getarea());
+	      z[frame][level]=endo[frame]->getstackindex().zlevel[level];
+	      delete cntr2;
+	      delete cntr;
+	    }
+      }
+  
+  fprintf(stderr,"Numlevels fr1=%d,fr2=%d\n",numlevels[0],numlevels[1]);
+  
+  for (int i=0;i<numlevels[0]-1;i++)
+      {
+	int corr[2];
+	float ar[2];
+	float zl[2];
+	float dz=0.0;
+	
+	for (int k=0;k<=1;k++)
+	    {
+	      corr[k]=0;
+	      while (z[0][i+k]<z[1][corr[k]] && corr[k]<numlevels[1])
+		  corr[k]++;
+	      
+	      dz=z[1][corr[k]+1]-z[1][corr[k]];
+	    
+	      float m1=(z[1][corr[k]+1]-z[0][i+k])/dz;
+	      float m2=1.0-m1;
+	
+	      ar[k]=m1*area[1][corr[k]]+m2*area[1][corr[k]+1];
+	      zl[k]=m1*z[1][corr[k]]+m2*z[1][corr[k]+1];
+	    }
+
+
+
+	float vol2=0.5*(zl[1]-zl[0])*(ar[1]+ar[0]);
+	float vol1=(z[0][i+1]-z[0][i])*0.5*(area[0][i]+area[0][i+1]);
+	
+	float dv=vol2-vol1;
+	float zshift=dv/(0.5*(ar[1]+ar[0]));
+	
+	//	if (int(i/7)*7==i || i==numlevels[0]-1)
+	fprintf(stderr,"level %02d , \tvol1=%4.0f(%5.2f:%5.2f)"
+		" vol2=%4.0f(%5.2f:%5.2f) \t z[0][i+1]:%6.2f-->%6.2f\n",
+		i,
+		vol1,z[0][i],z[0][i+1],
+		vol2,zl[0],zl[1],
+		z[0][i+1],z[0][i+1]-zshift);
+	
+	z[0][i+1]=z[0][i+1]-zshift;
+	
+	int j=0;
+	int be0=endo[0]->getstackindex().index[i+1];
+	int ee0=endo[0]->getstackindex().index[i+2];
+	for (j=be0;j<ee0;j++)
+	    endo[0]->getpoint(j)->x[2]-=zshift;
+	endo[0]->getstackindex().zlevel[i+1]-=zshift;
+	
+	int be1=epi[0]->getstackindex().index[i+1];
+	int ee1=epi[0]->getstackindex().index[i+2];
+	for (j=be1;j<ee1;j++)
+	    epi[0]->getpoint(j)->x[2]-=zshift;
+	epi[0]->getstackindex().zlevel[i+1]-=zshift;
+	/*if (int(i/7)*7==i || i==numlevels-1)
+	    fprintf(stderr,"\n(%d:%d, %d:%d)\n",be0,ee0,be1,ee1);*/
+      }
+
+  //endo[0]->Save("en.00.tstack");
+  //epi[0]->Save("ep.00.tstack");
+  return 1;
+
+}
+
+// ------------------------------------------------------------------------
+int PXShapeTrackingClass::initialDualCurvatureTracking(int searchwindow,PXShapeTrackingClass* other)
+{
+  if (!hasdisplacements() || !hasstacks() || !other->hasdisplacements() || !other->hasstacks())
+      return 0;
+
+  searchwindow=Irange(searchwindow,0,20);
+  if (debugmode)
+      fprintf(stderr,"\n Initial Curvature Matching Step (window=%d)\n",searchwindow);
+
+  PXIntegerList* searchPoints=new PXIntegerList();
+  double min1=100000.0,min2=100000.0;
+  int nptot=0;
+  // conf=new PX3Vector[numpoints];
+  int doublenumpoints=numpoints+other->getnumpoints();
+
+  double* minMatchDist=new double[doublenumpoints];
+  double* aveMatchDist=new double[doublenumpoints];
+  double* sigMatchDist=new double[doublenumpoints];
+  double* extraFactor =new double[doublenumpoints];
+
+  int baseindex=numpoints;
+
+  PXShapeTrackingClass* shapeTr[2];
+  shapeTr[0]=this;
+  shapeTr[1]=other;
+  
+  // Find Initial Match 
+  for (int pt1=0;pt1<doublenumpoints;pt1++)
+      {
+	PXTriangulatedStackPoint *point1,*point2;
+	int pt2,np2;
+	int sha=0,offset=0;
+
+	if (pt1>=baseindex)
+	    {
+	      sha=1;  offset=baseindex;
+	    }
+	
+	point1=shapeTr[sha]->getstack(0)->getpoint(pt1-offset);
+	pt2=shapeTr[sha]->getcorrespondence(pt1-offset);
+	np2=shapeTr[sha]->getstack(1)->collectNeighbours(pt2,searchwindow,searchPoints);
+	nptot+=np2;
+	
+	int bestpt2=pt2;
+	searchPoints->Rewind();
+	
+	double minebe=100000.0,sumebe=0.0,sum2ebe=0.0;
+	for (pt2=0;pt2<np2;pt2++)
+	    {
+	      point2=shapeTr[sha]->getstack(1)->getpoint(searchPoints->getcurrent());
+	      double ebe=0.0;
+	      for (int ia=0;ia<=1;ia++)
+		  ebe+=pow(point2->k[ia]-point1->k[ia],float(2.0));
+	      ebe*=0.5;
+	      if (ebe<minebe)
+		  {
+		    minebe=ebe;
+		    bestpt2=searchPoints->getcurrent();
+		  }
+	      sumebe+=ebe;
+	      sum2ebe+=pow(ebe,double(2.0));
+	      searchPoints->Next();
+	    }
+	
+	point2=shapeTr[sha]->getstack(1)->getpoint(bestpt2);
+	// This is the actual displacement estimate
+
+	for (int ia=0;ia<=2;ia++)
+	    shapeTr[sha]->setdisplacement(pt1-offset,ia,point2->x[ia]-point1->x[ia]);
+
+	// Store min difference, mean difference and sigma for confidence estimation 
+	if (np2>1)
+	    {
+	      sumebe=(sumebe-minebe)/double(np2-1);
+	      sum2ebe=(sum2ebe-minebe*minebe)/double(np2-1);
+	      minMatchDist[pt1]=minebe;
+	      aveMatchDist[pt1]=sumebe;
+	      sigMatchDist[pt1]=(sum2ebe-pow(aveMatchDist[pt1],double(2.0)));
+	      double bend=pow(point1->k[0],float(2.0))+pow(point1->k[1],float(2.0));
+	      if (bend<0.001)
+		  bend=0.0001;
+	      extraFactor[pt1]=sqrt(bend);// *double(np2);
+	    }
+	else
+	    {
+	      // In this unlikely case let it blow up to large values low confidence 
+	      fprintf(stderr,"*np2=0*pt=%d\n",pt1);
+	      minMatchDist[pt1]=10000.1;
+	      aveMatchDist[pt1]=10000.0;
+	      sigMatchDist[pt1]=10000.0;
+	      extraFactor[pt1]=0.01;
+	    }
+	
+	      
+	// This is needed for scaling
+	min1=Fmin(min1,minMatchDist[pt1]);
+	min2=Fmin(min2,minMatchDist[pt1]/(Fmax(aveMatchDist[pt1]-sigMatchDist[pt1],0.00001)));
+
+	if (debugmode>1)
+	    {
+	      if (100*int(pt1/100)==pt1)
+		  {
+		    fprintf(stderr,"%d/%d (np=%d,min=%10.8f ave=%10.8f sig=%10.8f)\n",
+			    pt1,doublenumpoints,np2,
+			    minMatchDist[pt1],aveMatchDist[pt1],sigMatchDist[pt1]);
+		    fprintf(stderr,"\t\t minebe=%f, sumebe=%f sum2ebe=%f\n",
+			    minebe,sumebe,sum2ebe);
+		    fprintf(stderr," pt1=%d k1=%7.5f k2=%7.5f \t pt2=%d k1=%7.5f k2=%7.5f\n",
+			    pt1,point1->k[0],point1->k[1],bestpt2,point2->k[0],point2->k[1]);
+		  }
+	    }
+      }
+  double K1 = 0.01 / Fmax(min1,0.0001);
+  double K2 = 0.01 / Fmax(min2,0.0001);
+  
+  float maxconf=0.0;
+  int sha;
+  for(sha=0;sha<=1;sha++)
+      for(int pt1=0; pt1<shapeTr[sha]->getstack(0)->getnumpoints(); pt1++)
+	  {
+	    int index=pt1;
+	    if (sha==1)
+		index+=baseindex;
+	    
+	    double mg=minMatchDist[index];
+	    double mu=minMatchDist[index]/Fmax(aveMatchDist[index]-sigMatchDist[index],0.00001);
+	    float cnf=(1.0 / (  ( 1.0+ K1*mg)*(1.0+K2*mu)));
+	    maxconf=Fmax(maxconf,cnf);
+	    shapeTr[sha]->setconfidence(pt1,cnf);
+	  }
+  
+  float sumconf=0.0,sum2conf=0.0;
+  for (sha=0;sha<=1;sha++)
+      for (int pt1=0;pt1<shapeTr[sha]->getstack(0)->getnumpoints();pt1++)
+	  {
+	    float cnf=shapeTr[sha]->getconfidence(pt1);
+	    cnf/=maxconf;
+	    sumconf+=cnf;
+	    sum2conf+=cnf*cnf;
+	    shapeTr[sha]->setconfidence(pt1,cnf);
+	  }
+  
+  sumconf/=float(doublenumpoints);
+  sum2conf/=float(doublenumpoints);
+  // Do Gamma-like correction so that mean becomes 0.5
+  //float gamma=log(0.5)/log(sumconf);
+  
+  /*if (debugmode)
+      fprintf(stderr,"Done with confidence values\n\t mean=%6.4f gamma=%6.4f \n",sumconf,gamma);
+  
+  sumconf=0.0; 
+  sum2conf=0.0;
+
+  for (sha=0;sha<=1;sha++)
+      for (int pt1=0;pt1<tstack[0]->getnumpoints();pt1++)
+      {
+	float cnf=shapeTr[sha]->getconfidence(pt1);
+	cnf=pow(cnf,gamma);
+	sumconf+=cnf;
+	sum2conf+=pow(cnf,float(2.0));
+	shapeTr[sha]->setconfidence(pt1,cnf);
+      }
+  
+  sumconf/=(float(doublenumpoints));
+  sum2conf/=(float(doublenumpoints));*/
+
+  if (debugmode)
+      {
+	fprintf(stderr,"Done with adjusting confidence values\n\t mean=%6.4f std=%6.4f\n",
+		sumconf,sqrt(sum2conf-sumconf*sumconf));
+	fprintf(stderr,"Total points compared =%d ave=%6.2f\n",nptot,
+		float(nptot)/float(doublenumpoints));
+      }
+  
+  
+  delete searchPoints;
+  delete [] minMatchDist;
+  delete [] aveMatchDist;
+  delete [] sigMatchDist;
+  delete [] extraFactor;
+  return 1;
+}
+// ------------------------------------------------------------------------
+
diff --git a/bioimagesuite30_src/numerics/pxshapetrackingclass.h b/bioimagesuite30_src/numerics/pxshapetrackingclass.h
new file mode 100644
index 0000000..f62916d
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxshapetrackingclass.h
@@ -0,0 +1,131 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+
+
+#ifndef _PxShapeTrackingClass
+#define _PxShapeTrackingClass
+#include "pxgeometrystruct.h"
+#include "pxtriangulatedstack.h"
+
+
+class PXShapeTrackingClass {
+  
+protected:
+
+  // Original Inputs 
+  PXTriangulatedStack*      tstack[2];
+
+  // Geometrical Parameters 
+  PX3Vector*                displacements;
+  float                     *confidences;
+  int                       *used,*correspondence,*fixed;
+  int                       hasDisplacements;
+  int                       numpoints,hasStack[2];
+
+public:
+  
+  PXShapeTrackingClass();
+  PXShapeTrackingClass(PXShapeTrackingClass* old);
+  PXShapeTrackingClass(PXTriangulatedStack* stack1,PXTriangulatedStack* stack2);
+  PXShapeTrackingClass(const char* fname1,const char* fname2);
+  
+  virtual ~PXShapeTrackingClass();
+  void init(int np);
+  void cleanup(); 
+  void Copy(PXShapeTrackingClass* other);
+  
+  void nextFrame(const char* newstack2fname,int deform=1);
+  void nextFrame(PXTriangulatedStack* newstack2,int deform=1);
+
+  // Access functions
+  // ----------------
+  PXTriangulatedStack* getstack(int i);
+  PX3Vector*           getdisplacement(int i);
+  float                getconfidence(int i);
+  
+  int                  getused(int i);
+  int                  getcorrespondence(int i);
+  int                  getfixed(int i);
+  int                  hasdisplacements();
+  int                  getnumpoints();
+  int                  hasstack(int i);
+  int                  hasstacks();
+
+  void setconfidence(int i,float s);
+  void setdisplacement(int i,int comp,float s);
+  // --------------------------------------------------------------
+  // Running algorithms
+  // --------------------------------------------------------------
+  int saveInventor(const char* fname);
+  int saveInventor(const char* fname,int number);
+  int saveDeformed(const char* base,int number);
+  int saveStackInventor(const char* fname,int colormode=0);
+
+  int findSmoothMap(int mode,int iterations,int smoothiterations,int subdivide=0);
+  int initialCurvatureTracking(int searchwindow);
+  int initialDualCurvatureTracking(int searchwindow,PXShapeTrackingClass* other);
+  int smoothCurvatureTracking(int iterations=100,float lambda=1.0);
+
+  int volumePreserveZshift(PXShapeTrackingClass* other);
+
+  // --------------------------------------------------------------
+  // I/O Stuff
+  // --------------------------------------------------------------
+  int  Save(FILE* fout,int doNotsavebothStacks=1);
+  int  Save(const char* fname,int doNotsavebothStacks=1,int complevel=0);
+  int  Load(gzFile fout,int doNotloadbothStacks=1);
+  int  Load(const char* fname,int doNotloadbothStacks=1);
+
+
+  //  Create default fields 
+  //  ---------------------
+  void translate(float px,float py,float pz);
+  void expand(float factor1,float factor2,float factor3); 
+      
+protected:
+  int findSymmetricPair(PXNeighboursList* pairs,int seedt);
+  int smoothEuclidean(int movefixed=1,int subpixel=1);
+  int smoothConnection(int movefixed=1);
+
+public:
+  static int debugmode;
+
+
+};
+
+  
+  
+#endif  
+
diff --git a/bioimagesuite30_src/numerics/pxtriangulatedstack.cpp b/bioimagesuite30_src/numerics/pxtriangulatedstack.cpp
new file mode 100644
index 0000000..826438d
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxtriangulatedstack.cpp
@@ -0,0 +1,4770 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+// Defining namespace for old code
+
+//
+//
+//
+//
+// ---------------------------------------------------------------------------------------------------------
+#include "pxutil.h"
+#include "pxcontourstack.h"
+#include "pxtriangulatedstack.h"
+#include "nrutil.h"
+
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July 1995   papad at noodle.med.yale.edu
+
+   see pxtriangulatedstack.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+// ------------------------------------------------------------------------
+float PXTriangulatedStack::max_curvature=-1000.0;
+float PXTriangulatedStack::min_curvature= 1000.0;
+int   PXTriangulatedStack::debugmode=0;
+// ------------------------------------------------------------------------
+// [A] Access Contours
+// ------------------------------------------------------------------------
+int   PXTriangulatedStack::haspoints()       { return haspointstructures; }
+int   PXTriangulatedStack::hastriangles()    { return hastrianglestructures;}
+int   PXTriangulatedStack::hasneighbours()   { return hasneighbourstructures;}
+int   PXTriangulatedStack::hasnormals()      { return normalsok;}
+int   PXTriangulatedStack::hascurvatures()   { return curvaturesok;}
+int   PXTriangulatedStack::hascentroids()    { return trianglecentroidsok;}
+int   PXTriangulatedStack::hasstackindex()   { return stackindexok; }
+
+int   PXTriangulatedStack::getmaxconnection() { return maxconnection;}
+int   PXTriangulatedStack::getnumpoints()     { return numpoints; }
+int   PXTriangulatedStack::getnumtriangles()  { return numtriangles;}
+
+PXStackIndex PXTriangulatedStack::getstackindex() { return stackIndex;}
+
+// ------------------------------------------------------------------------
+
+PXTriangulatedStack::PXTriangulatedStack(const char* stackfname,int mode)
+{
+  init();
+  if (mode==1)
+      {
+	char line2[40],line[150];
+	sprintf(line2,"/tmp/splstack.off");
+	
+	sprintf(line,"nuages %s -tri %s -off -prepros > /dev/null",stackfname,line2);
+	/*if (mode)
+	    fprintf(stderr,"Executing: %s\n",line);*/
+	
+	system(line);
+	int a=LoadOffset(line2);
+	if (debugmode)
+	    fprintf(stderr,"Read from %s (%d)\n",line2,a);
+	sprintf(line,"rm %s  ",line2);
+	system(line);
+      }
+  PXContourStack* cstack=new PXContourStack();
+  int ok=cstack->Load(stackfname);
+  if (ok)
+      {
+	if (mode==0)
+	    {
+	      setfromcontourstack(cstack,mode);
+	    }
+	else
+	    {
+	      // fprintf(stderr,"Reading Stack slices=%d\n",cstack->getnumcontours());
+	      initialiseStackIndex(cstack);
+	    }
+      }
+  delete cstack;
+}  
+// ------------------------------------------------------------------------
+PXTriangulatedStack::PXTriangulatedStack()
+{
+  init();
+}
+// ------------------------------------------------------------------------
+PXTriangulatedStack::PXTriangulatedStack(PXContourStack* old,int mode)
+{
+  init();
+  setfromcontourstack(old,mode);
+}
+// ------------------------------------------------------------------------
+PXTriangulatedStack::~PXTriangulatedStack()
+{
+  cleanup();
+}
+// ------------------------------------------------------------------------
+PXTriangulatedStack::PXTriangulatedStack(PXTriangulatedStack* old)
+{
+  init(0,0);
+  Copy(old);
+}
+
+// ------------------------------------------------------------------------
+void PXTriangulatedStack::Copy(PXTriangulatedStack* old)
+{
+  cleanup();
+  init(old->getnumpoints(),old->getnumtriangles());
+  if (haspoints())
+      {
+	for(int i=0;i<numpoints;i++)
+	    {
+	      PXTriangulatedStackPoint* other=old->getpoint(i);
+	      point[i].index=other->index;
+	      int ia;
+	      for (ia=0;ia<=2;ia++)
+		  {
+		    point[i].x[ia]=other->x[ia];
+		    point[i].nx[ia]=other->nx[ia];
+		  }
+	      for (ia=0;ia<=1;ia++)
+		  point[i].k[ia]=other->k[ia];
+	    }
+	normalsok=old->hasnormals();
+	curvaturesok=old->hascurvatures();
+      }
+      
+  if (hastriangles())
+      {
+	for (int i=0;i<numtriangles;i++)
+	    {
+	      PXTriangle* other=old->gettriangle(i);
+	      triangle[i].index=other->index;
+	      for (int j=0;j<=2;j++)
+		  {
+		    triangle[i].p[j]=other->p[j];
+		    triangle[i].c[j]=other->c[j];
+		  }
+	    }
+	trianglecentroidsok=old->hascentroids();
+      }
+
+  if (old->hasneighbours())
+      {
+	hasneighbourstructures=1;
+	neighboursList=new PXNeighboursList();
+	neighbours=new PXIntegerList[numpoints];
+	for (int i=0;i<numpoints;i++)
+	    {
+	      //	      fprintf(stderr,"Node =%d(%d)\n",i,numpoints);
+	      neighbours[i].Copy(old->getneighbours(i));
+	      neighboursList->Add(&neighbours[i],i);
+	    }
+      }
+  
+
+  if (old->hasstackindex())
+      {
+	stackindexok=1;
+	PXStackIndex st=old->getstackindex();
+	stackIndex.numcontours=st.numcontours;
+	stackIndex.index=new int[stackIndex.numcontours+1];
+	stackIndex.zlevel=new float[stackIndex.numcontours];
+	for (int i=0;i<=stackIndex.numcontours;i++)
+	    stackIndex.index[i]=st.index[i];
+	for (int j=0;j<stackIndex.numcontours;j++)
+	    stackIndex.zlevel[j]=st.zlevel[j];
+      } 
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::setfrompolarcontourstack(PXContourStack* cstack,float middlex)
+{
+  int npt=0,nt=0,i;
+  for (i=0;i<cstack->getnumcontours();i++)
+      {
+	npt+=cstack->getcontour(i)->getnumpoints();
+	if (i<cstack->getnumcontours()-1)
+	    {
+	      nt+=cstack->getcontour(i)->getnumpoints();
+	      if (cstack->getcontour(i)->getnumpoints()==1)
+		  nt=nt-1;
+	      nt+=cstack->getcontour(i+1)->getnumpoints();
+	    }
+      }
+
+  i=cstack->getnumcontours();
+  nt+=cstack->getcontour(i)->getnumpoints();
+  nt+=cstack->getcontour(0)->getnumpoints();
+  
+  init(npt,nt);
+
+  // Copy Points once and for all
+  int pt=0,maxp=0;
+  for (i=0;i<cstack->getnumcontours();i++)
+      {
+	maxp=Imax(maxp,cstack->getcontour(i)->getnumpoints());
+	float theta=cstack->getzlevel(i)*M_PI/180.0;
+	PXContourPoint* pts=cstack->getcontour(i)->gettoppoint();
+	for (int j=0;j<cstack->getcontour(i)->getnumpoints();j++)
+	    {
+	      float r=(pts->x-middlex);
+	      point[pt].index=pt;
+	      point[pt].x[0]=middlex+r*cos(theta);
+	      point[pt].x[1]=middlex+r*sin(theta);
+	      point[pt].x[2]=pts->y;
+	      pts=pts->next;
+	      pt++;
+	    }
+      }
+
+  int basetr=0,basept=0;
+  PXNeighboursList* facelist=new PXNeighboursList();
+  float *x[2],*y[2],*z[2];
+  int origin[2],np[2];
+  x[0]=new float[maxp];  y[0]=new float[maxp]; z[0]=new float[maxp];
+  x[1]=new float[maxp];  y[1]=new float[maxp]; z[1]=new float[maxp];
+  for(i=0;i<cstack->getnumcontours();i++)
+      {
+	for (int c=0;c<=1;c++)
+	    {
+	      np[c]=cstack->getcontour(Icyclic(i+c,cstack->getnumcontours()))->getnumpoints();
+	      PXContourPoint* pts=(cstack->getcontour(Icyclic(i+c,cstack->getnumcontours())))->gettoppoint();
+	      float theta=cstack->getzlevel(Icyclic(i+c,cstack->getnumcontours()))*M_PI/180.0;
+	      for(int ia=0;ia<np[c];ia++)
+		  {
+		    int ib=ia;
+		    // Flip over for last contour 
+		    if (c==1 && i==cstack->getnumcontours()-1)
+			ib=np[c]-1-ia;
+		    float r=(pts->x-middlex);
+		    x[c][ib]=(middlex+r*cos(theta));
+		    y[c][ib]=(middlex+r*sin(theta));
+		    z[c][ib]=pts->y;
+		    pts=pts->next;
+		  }    
+	    }
+	
+	PXTriangulatedStack::findorigin(np,x,y,z,origin);
+	int numfaces=PXTriangulatedStack::triangulate(np,x,y,z,origin,
+						      facelist,np[0]+np[1]+1);
+	      
+	for (int k=0;k<numfaces;k++)
+	    {
+	      PXNeighboursNode* current=facelist->getcurrentnode();
+	      PXIntegerList* list=(current->points);
+	      list->Rewind();
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    if (list->getcurrent()+basept < npt)
+			{
+			  triangle[k+basetr].p[ia]=list->getcurrent()+basept;
+			}
+		    else
+			{
+			  int p=list->getcurrent()-np[0];
+			  p=np[1]-1-p;
+			  triangle[k+basetr].p[ia]=p;
+			}
+		    list->Next();
+		  }
+	      facelist->Next();
+	    }
+	facelist->DeleteAll();
+	
+	basept+=np[0];
+	basetr+=numfaces;
+      }
+  delete [] x[0]; delete [] y[0]; delete [] z[0];
+  delete [] x[1]; delete [] y[1]; delete [] z[1];
+
+  delete facelist;
+  
+  generateNormals();
+  
+  return 1;
+}
+// --------------------------------------------------------------
+int PXTriangulatedStack::trimtstack(float zbot,float ztop)
+{
+  // First the points bussiness 
+  float zmin=+100000.0,zmax=-1000000.0;
+
+  for (int i=0;i<numpoints;i++)
+      {
+	zmin=Fmin(zmin,point[i].x[2]);
+	zmax=Fmax(zmax,point[i].x[2]);
+      }
+  
+  zbot=Frange(zbot,0.0,0.99);
+  ztop=Frange(ztop,zbot+0.005,1.0);
+
+  float bottomz=zmin+zbot*(zmax-zmin);
+  float topz   =zmin+ztop*(zmax-zmin);
+  return trimtstackz(bottomz,topz);
+}
+// --------------------------------------------------------------
+int PXTriangulatedStack::trimtstackz(float bottomz,float topz)
+{
+  int np=0,nt=0;
+  int *ok=new int[numpoints];
+  int *okt=new int[numtriangles];
+
+  if (topz==-1000.0)
+      topz=10000.0;
+  if (bottomz==-1000.0)
+      bottomz=-10000.0;
+  int i;
+  for (i=0;i<numpoints;i++)
+      {
+	if (point[i].x[2]>=bottomz && point[i].x[2]<=topz)
+	    ok[i]=1;
+	else
+	    ok[i]=0;
+	np+=ok[i];
+      }
+
+  for (i=0;i<numtriangles;i++)
+      {
+	int sum=0;
+	for (int ia=0;ia<=2;ia++)
+	    sum+=ok[triangle[i].p[ia]];
+	if (sum==3)
+	    okt[i]=1;
+	else
+	    okt[i]=0;
+	nt+=okt[i];
+      }
+
+  // fprintf(stderr,"Num good points=%d, good triangles=%d\n",np,nt);
+
+  PXTriangulatedStack* old=new PXTriangulatedStack(this); //OK 
+  init(np,nt);
+  
+  int *index=new int[old->getnumpoints()];
+  int base=0;
+  for (i=0;i<old->getnumpoints();i++)
+      {
+	//if (50*int(base/50)==base)
+	//	    fprintf(stderr,"Base pt=%d\n",base);
+	if (ok[i]==1)
+	    {
+	      PXTriangulatedStackPoint* other=old->getpoint(i);
+	      point[base].index=other->index;
+	      int ia;
+	      for (ia=0;ia<=2;ia++)
+		  {
+		    point[base].x[ia]=other->x[ia];
+		    point[base].nx[ia]=other->nx[ia];
+		  }
+	      for (ia=0;ia<=1;ia++)
+		  point[base].k[ia]=other->k[ia];
+	      index[i]=base;
+	      ++base;
+	    }
+      }
+
+  base=0;
+  for (i=0;i<old->getnumtriangles();i++)
+      {
+	//if (50*int(base/50)==base)
+	//  fprintf(stderr,"Base tr=%d\n",base);
+
+	if (okt[i]==1)
+	    {
+	      PXTriangle* other=old->gettriangle(i);
+	      triangle[base].index=other->index;
+	      for (int j=0;j<=2;j++)
+		  {
+		    triangle[base].p[j]=index[other->p[j]];
+		    triangle[base].c[j]=other->c[j];
+		  }
+	      ++base;
+	    }
+      }
+  
+  normalsok=old->hasnormals();
+  curvaturesok=old->hascurvatures();
+  trianglecentroidsok=old->hascentroids();
+  
+  delete [] ok;
+  delete [] okt;
+  delete [] index;
+
+  if (old->hasstackindex())
+      {
+	stackindexok=1;
+	PXStackIndex st=old->getstackindex();
+	int numc=0;
+	int minc=-1;
+	// fprintf(stderr,"Bottomz=%6.2f, topz=%7.2f\n",bottomz,topz);
+	int j;
+	for (j=0;j<st.numcontours;j++)
+	    {
+	      if (st.zlevel[j]>=bottomz && st.zlevel[j]<=topz)
+		  {
+		    if (minc==-1)
+			minc=j;
+		    numc++;
+		  }
+	    }
+	// fprintf(stderr,"  minc=%d good=%d \n",minc,numc);
+	
+	stackIndex.numcontours=numc;
+	stackIndex.index=new int[numc+1];
+	stackIndex.zlevel=new float[stackIndex.numcontours];
+	for (int i=0;i<=stackIndex.numcontours;i++)
+	    stackIndex.index[i]=st.index[i+minc]-st.index[minc];
+	for (j=0;j<stackIndex.numcontours;j++)
+	    stackIndex.zlevel[j]=st.zlevel[j+minc];
+	// fprintf(stderr,"Num good slices=%d\n",numc);
+      } 
+  else
+      // fprintf(stderr,"Old has no stackindex\n");
+
+  delete old;
+  return 1;
+}
+// --------------------------------------------------------------
+void PXTriangulatedStack::setfromcontourstack(PXContourStack* old,int mode)
+{
+  /*if (mode==1)
+      {
+	char line1[40],line2[40],line[150];
+	sprintf(line1,"/tmp/splstack.cnt");
+	sprintf(line2,"/tmp/splstack.off");
+	if (mode)
+	    // fprintf(stderr,"Saving in Nuages Format %s\n",line1);
+	old->SaveNuages(line1);
+	sprintf(line,"nuages %s -tri %s -off -prepros > /dev/null",line1,line2);
+	if (mode)
+	    // fprintf(stderr,"Executing: %s\n",line);
+	
+	system(line);
+	int a=LoadOffset(line2);
+	if (debugmode)
+	    fprintf(stderr,"Read from %s (%d)\n",line2,a);
+	sprintf(line,"rm %s %s ",line1,line2);
+	system(line);
+      }
+  else
+      {*/
+
+  // Forget about Nuages 
+  if (mode==1)
+      mode=0;
+
+  int npt=0,nt=0,i;
+  for (i=0;i<old->getnumcontours();i++)
+      {
+	npt+=old->getcontour(i)->getnumpoints();
+	if (i<old->getnumcontours()-1)
+	    {
+	      nt+=old->getcontour(i)->getnumpoints();
+	      if (old->getcontour(i)->getnumpoints()==1)
+		  nt=nt-1;
+	      nt+=old->getcontour(i+1)->getnumpoints();
+	    }
+      }
+  cleanup();
+  init(npt,nt);
+  
+  // Copy Points once and for all
+  int pt=0,maxp=0;
+  for (i=0;i<old->getnumcontours();i++)
+      {
+	maxp=Imax(maxp,old->getcontour(i)->getnumpoints());
+	      PXContourPoint* pts=old->getcontour(i)->gettoppoint();
+	for (int j=0;j<old->getcontour(i)->getnumpoints();j++)
+	    {
+	      point[pt].index=pt;
+	      point[pt].x[0]=pts->x; point[pt].x[1]=pts->y;
+	      point[pt].x[2]=old->getzlevel(i);
+	      pts=pts->next;
+	      pt++;
+	    }
+      }
+  
+  int basetr=0,basept=0;
+  PXNeighboursList* facelist=new PXNeighboursList();
+  
+  float *x[2],*y[2];
+  int origin[2],np[2];
+  x[0]=new float[maxp];  y[0]=new float[maxp];
+  x[1]=new float[maxp];  y[1]=new float[maxp];
+  for(i=0;i<old->getnumcontours()-1;i++)
+      {
+	int goahead=1;
+	int nextc=1;
+	
+	if (old->getcontour(i)->getnumpoints()==0)
+	    {
+	      goahead=0;
+	    }
+	else 
+	    {
+	      int j=i+1;
+	      goahead=0;
+	      while (j<old->getnumcontours() && goahead==0)
+		  {
+		    if (old->getcontour(j)->getnumpoints()==0)
+			j++;
+		    else
+			goahead=1;
+		  }
+	      nextc=j;
+	    }
+	
+	if (goahead==1)
+	    {
+	      for (int c=0;c<=1;c+=1)
+		  {
+		    int cnt=i;
+		    if (c==1)
+			cnt=nextc;
+		    np[c]=old->getcontour(cnt)->getnumpoints();
+		    PXContourPoint* pts=(old->getcontour(cnt))->gettoppoint();
+		    for(int ia=0;ia<np[c];ia++)
+			{
+			  x[c][ia]=pts->x;   y[c][ia]=pts->y; 
+				pts=pts->next;
+			}
+		  }
+	      
+	      PXTriangulatedStack::findorigin2D(np,x,y,origin);
+	      int numfaces=PXTriangulatedStack::triangulate2D(np,x,y,origin,
+							      facelist,np[0]+np[1]+1);
+		  for (int k=0;k<numfaces;k++)
+		      {
+			PXNeighboursNode* current=facelist->getcurrentnode();
+			PXIntegerList* list=(current->points);
+			list->Rewind();
+			for (int ia=0;ia<=2;ia++)
+			    {
+			      triangle[k+basetr].p[ia]=list->getcurrent()+basept;
+			      list->Next();
+			    }
+			facelist->Next();
+		      }
+	      facelist->DeleteAll();
+	      
+	      basept+=np[0];
+	      basetr+=numfaces;
+	    }
+      }
+  delete [] x[0]; delete [] y[0];
+  delete [] x[1]; delete [] y[1];
+  delete facelist;
+  generateNormals();
+  initialiseStackIndex(old);
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::generateNormals()
+{
+  if (!haspoints() || !hastriangles())
+      {
+	/*fprintf(stderr,"Cannot generate normals as points=%d , triangles=%d\n",
+		haspoints(),hastriangles());*/
+	return 0;
+      }
+  
+  PXIntegerList *belong=new PXIntegerList[numpoints];
+  for (int tr=0;tr<numtriangles;tr++)
+      for (int ia=0;ia<=2;ia++)
+	  belong[triangle[tr].p[ia]].Add(tr);
+  
+  for (int i=0;i<numpoints;i++)
+      {
+	float nx=0.0,ny=0.0,nz=0.0;
+	belong[i].Rewind();
+	for (int tr=0;tr<belong[i].getnumnodes();tr++)
+	    {
+	      int tri=belong[i].getcurrent();
+	      belong[i].Next();
+	      PXTriangulatedStackPoint* p0=getpoint(triangle[tri].p[0]);
+	      PXTriangulatedStackPoint* p1=getpoint(triangle[tri].p[1]);
+	      PXTriangulatedStackPoint* p2=getpoint(triangle[tri].p[2]);
+	      
+	      // Offset Coordinates
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    p2->x[ia]=p2->x[ia]-p1->x[ia];  p1->x[ia]=p1->x[ia]-p0->x[ia];
+		  }
+	      
+	      float lx=p2->x[1]*p1->x[2]-p1->x[1]*p2->x[2];
+	      float ly=p2->x[2]*p1->x[0]-p1->x[2]*p2->x[0];
+	      float lz=p2->x[0]*p1->x[1]-p1->x[0]*p2->x[1];
+	      float mag=sqrt(lx*lx+ly*ly+lz*lz)*float(belong[i].getnumnodes());
+	      
+	      nx-=lx/mag; ny-=ly/mag; nz-=lz/mag;
+	      
+	      for (int ib=0;ib<=2;ib++)
+		  {
+		    p1->x[ib]=p1->x[ib]+p0->x[ib];  p2->x[ib]=p2->x[ib]+p1->x[ib];
+		  }
+	    }
+	point[i].nx[0]=nx;  point[i].nx[1]=ny;     point[i].nx[2]=nz;
+      }
+  normalsok=1;
+  delete [] belong;
+  return 1;
+}
+// ------------------------------------------------------------------------
+PXContourStack* PXTriangulatedStack::exporttocontourstack(int skiplevels,int skipapex)
+{
+  if (!hasstackindex())
+    {
+      fprintf(stderr,"Failed to export \n");
+      return NULL;
+    }
+
+  if (debugmode)
+      fprintf(stderr,"skiplevels=%d\n",skiplevels);
+  skiplevels=Irange(skiplevels,0,stackIndex.numcontours);
+
+  int level=0;
+
+  if (skipapex)
+      {
+	// Find Apical bottom and cut out
+	// This is going to be a bug !!
+	if (debugmode)
+	    fprintf(stderr,"Cannot skip apex\n");
+      }
+  else
+      level=0;
+	
+  if (debugmode)
+      fprintf(stderr,"skiplevels=%d\n",skiplevels);
+  int numl=0,i;
+  for (i=level;i<stackIndex.numcontours;i+=skiplevels+1)
+      numl++;
+  
+  if(debugmode)
+      fprintf(stderr,"Tstack->Cstack Numlevels=%d\n",numl);
+  PXContourStack* stack=new PXContourStack(numl);
+
+  for (i=0;i<stack->getnumcontours();i++)
+      {
+	stack->setzlevel(i,stackIndex.zlevel[level]);
+	if (debugmode)
+	    fprintf(stderr,"Zlevels %d <--%d = %6.2f <-- %6.2f \n",i,level,stackIndex.zlevel[level],stack->getzlevel(i));
+	PXContour* cntr=stack->getcontour(i);
+	for (int j=stackIndex.index[level];j<stackIndex.index[level+1];j++)
+	    cntr->Add(getpoint(j)->x[0],getpoint(j)->x[1]);
+	cntr->setclosed(1);
+	level+=skiplevels+1;
+      }
+  return stack;
+}
+// ------------------------------------------------------------------------
+void PXTriangulatedStack::cleanup()
+{
+  //fprintf(stderr,"In Cleanup\n");
+
+  if (haspointstructures)
+      {
+	delete [] point;
+	haspointstructures=0;
+      }
+
+  //fprintf(stderr,"Done with Points\n");
+
+  if (hastrianglestructures)
+      {
+	delete [] triangle;
+	hastrianglestructures=0;
+      }
+  
+  //fprintf(stderr,"Done with Triangles\n");
+
+  if (hasneighbourstructures)
+      {
+	cleanupneighbours();
+	hasneighbourstructures=0;
+      }
+
+  //fprintf(stderr,"Done with Neighbours\n");
+
+  if (stackindexok)
+      {
+	if (stackIndex.index!=NULL)
+	    delete [] stackIndex.index;
+	if (stackIndex.zlevel!=NULL)
+	    delete [] stackIndex.zlevel;
+	stackindexok=0;
+      }
+  //fprintf(stderr,"Done with Stack\n");
+
+  init(0,0);
+
+  //fprintf(stderr,"Done with cleanup\n");
+
+
+}
+// ------------------------------------------------------------------------
+void PXTriangulatedStack::cleanupneighbours()
+{
+  if (hasneighbourstructures)
+      {
+	if (neighboursList!=NULL)
+	  {
+	    delete neighboursList;
+	  }
+	if (neighbours!=NULL)
+	  delete []  neighbours;
+      }
+  maxconnection=0;
+}
+// ------------------------------------------------------------------------
+void PXTriangulatedStack::init(int np,int nt)
+{
+  trianglecentroidsok=0; stackindexok=0; stackIndex.numcontours=0;
+  haspointstructures=0; hastrianglestructures=0; hasneighbourstructures=0; 
+  normalsok=0; curvaturesok=0; maxconnection=0;
+  numpoints=0; numtriangles=0; useindex=0; 
+  point=NULL;
+  triangle=NULL;
+  neighboursList=NULL;
+  stackIndex.index=NULL;
+  stackIndex.zlevel=NULL;
+  neighbours=NULL;
+
+  if (np>0)
+      {
+	numpoints=np;
+	point=new PXTriangulatedStackPoint[np];
+	for (int i=0;i<np;i++)
+	    {
+	      point[i].index=i;
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    point[i].x[ia]=0.0; 
+		    point[i].nx[ia]=0.0;
+		  }
+	      for (int ib=0;ib<=1;ib++)
+		  point[i].k[ib]=0.0;
+	    }
+	haspointstructures=1;
+      }
+  if (nt>0)
+      {
+	numtriangles=nt;
+	triangle=new PXTriangle[nt];
+	for (int i=0;i<nt;i++)
+	    {
+	      triangle[i].index=i;
+	      for (int j=0;j<=2;j++)
+		  {
+		    triangle[i].p[j]=-1;
+		    triangle[i].c[j]=0.0;
+		  }
+	    }
+	hastrianglestructures=1;
+      }
+}
+
+// ------------------------------------------------------------------------
+void PXTriangulatedStack::initialiseStackIndex(PXContourStack* old)
+{
+  if (hasstackindex())
+      {
+	//fprintf(stderr,"Cleaning ip stackIndex\n");
+	delete [] stackIndex.index;
+	delete [] stackIndex.zlevel;
+      }
+  else
+      stackindexok=1;
+  
+  stackIndex.numcontours=old->getnumcontours();
+  stackIndex.index=new int[stackIndex.numcontours+1];
+  stackIndex.zlevel=new float[stackIndex.numcontours];
+  stackIndex.index[0]=0;
+  for (int i=1;i<=stackIndex.numcontours;i++)
+      stackIndex.index[i]=stackIndex.index[i-1]+(old->getcontour(i-1))->getnumpoints();
+  for (int j=0;j<stackIndex.numcontours;j++)
+      stackIndex.zlevel[j]=old->getzlevel(j);
+}
+// ------------------------------------------------------------------------
+PXTriangulatedStackPoint* PXTriangulatedStack::getpoint(int pointidx)
+{
+  if (haspoints())
+      {
+	pointidx=Irange(pointidx,0,numpoints-1);
+	return &point[pointidx];
+      }
+  
+  return NULL;
+}
+// ------------------------------------------------------------------------
+PXIntegerList* PXTriangulatedStack::getneighbours(int idx)
+{
+  if (hasneighbours())
+      {
+	idx=Irange(idx,0,numpoints-1);
+	return &neighbours[idx];
+      }
+  
+  return NULL;
+}
+// ------------------------------------------------------------------------
+PXTriangle* PXTriangulatedStack::gettriangle(int triangleidx)
+{
+  if (hastriangles())
+      {
+	triangleidx=Irange(triangleidx,0,numtriangles-1);
+	return &triangle[triangleidx];
+      }
+
+  return NULL;
+
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::SaveAbaqusRigid(const char* filename,int offset,int index)
+{
+  int ok=0;
+  FILE* fout=fopen(filename,"w");
+  if (fout)
+      {
+	ok=SaveAbaqusRigid(fout,offset,index);
+	fclose(fout);
+      }
+  return ok;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::SaveAbaqusRigid(FILE* fout,int offset,int index)
+{
+  if (!fout)
+      return 0;
+  fprintf(fout,"*NODE,NSET=NSURF_%02d\n",index);
+  int i;
+  for (i=0;i<numpoints;i++)
+      {
+	fprintf(fout,"%6d, %6.3f, %6.3f, %6.3f\n",i+offset,
+		point[i].x[0],point[i].x[1],point[i].x[2]);
+      }
+  fprintf(fout,"*ELEMENT, TYPE=R3D3,ELSET=ESURF_%02d\n",index);
+  for (i=0;i<numtriangles;i++)
+      {
+	fprintf(fout,"%6d, %6d, %6d, %6d\n",
+		i+offset,
+		triangle[i].p[0]+offset,triangle[i].p[1]+offset,
+		triangle[i].p[2]+offset);
+      }
+  fprintf(fout,"*RIGID BODY,ELSET=ESURF_%02d,REF NODE=%d\n",index,offset);
+  fprintf(fout,"*SURFACE DEFINITION,NAME=RGDS_%02d\n",index);
+  fprintf(fout,"ESURF_%02d,SPOS\n",index);
+  return (1);
+}
+// ------------------------------------------------------------------------
+PX3Vector* PXTriangulatedStack::nonShrinkSmoothD(float alpha,float beta,int iterations,
+						 int movez,int )
+{
+  PX3Vector* disp=new PX3Vector[numpoints];
+  int i;
+  for (i=0;i<numpoints;i++)
+      for (int ia=0;ia<=2;ia++)
+	  disp[i].x[ia]=point[i].x[ia];  
+  
+  nonShrinkSmooth(alpha,beta,iterations,movez);
+  
+  for (i=0;i<numpoints;i++)
+      for (int ia=0;ia<=2;ia++)
+	  disp[i].x[ia]=point[i].x[ia]-disp[i].x[ia];  
+
+  return disp;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::nonShrinkSmooth(float alpha,float beta,int iterations,int movez,
+					 int uniform)
+{
+  int st=1;
+  if (!hasneighbourstructures)
+      st=generateNeighbours();
+
+  if (st==0)
+      return 0;
+
+  movez=Irange(movez,0,2);
+  uniform=Irange(uniform,0,1);
+
+  PX3Vector* temp=new PX3Vector[numpoints];
+  
+  float minz=point[0].x[2];
+  float maxz=point[0].x[2];
+
+  if (movez==1)
+      {
+	for (int i=0;i<numpoints;i++)
+	    {
+	      minz=Fmin(minz,point[i].x[2]);
+	      maxz=Fmax(maxz,point[i].x[2]);
+	    }
+      }
+
+  if (hasstackindex())
+      {
+	// If we have an apex smooth its z coordinate as well 
+	if (stackIndex.index[1]==1)
+	    minz-=1.0;
+      }
+
+	      
+  if (debugmode)
+      fprintf(stderr,"Smoothing , iterations (movez=%d,alpha=%5.3f,beta=%5.3f,iter=%d): ",
+	      movez,alpha,beta,iterations);
+  for (int iter=1;iter<=iterations;iter++)
+      {
+	if (debugmode)
+	    {
+	      if (20*int(iter/20)==iter)
+		  fprintf(stderr,"%d ",iter);
+	    }
+	for(int pass=0;pass<=1;pass++)
+	    {
+	      int i;
+	      for (i=0;i<numpoints;i++)
+		  {
+		    for (int ia=0;ia<=2;ia++)
+			temp[i].x[ia]=point[i].x[ia];  
+		  }
+	      
+	      for(i=0;i<numpoints;i++)
+		  {
+		    float oldx[3],newx[3];
+		    for (int ia=0;ia<=2;ia++)
+			{
+			  oldx[ia]=temp[i].x[ia];
+			  newx[ia]=0.0;
+			}
+		    float total=0.0;
+		    
+		    for(int j=0;j<(neighbours[i].getnumnodes());j++)
+			{
+			  int p=neighbours[i].getcurrent();
+			  for (int ia=0;ia<=2;ia++)
+			      newx[ia]+=temp[p].x[ia];
+			  total+=1.0;
+			  neighbours[i].Next();
+			}
+		    if (total>0.0)
+			{
+			  for (int ia=0;ia<=2;ia++)
+			      newx[ia]=newx[ia]/total;
+			  float factor;
+			  if(pass==0)
+			      factor=alpha;
+			  else
+			      factor=beta;
+
+			  for (int ib=0;ib<=1;ib++)
+			      point[i].x[ib]=(1.0-factor)*oldx[ib]+factor*newx[ib];
+
+			  switch(movez)
+			      {
+			      case 1:
+				if (point[i].x[2]>minz+0.01 && point[i].x[2]<maxz-0.01)
+				    point[i].x[2]=(1.0-factor)*oldx[2]+factor*newx[2];
+				break;
+			      case 2:
+				point[i].x[2]=(1.0-factor)*oldx[2]+factor*newx[2];
+				break;
+			      default:
+				point[i].x[2]=oldx[2];
+				break;
+			      }
+			}
+		  }
+	    }
+      }
+  delete [] temp;  
+
+  if (debugmode)
+      fprintf(stderr,"\n");
+  return 1;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::calculateCentroids()
+{
+  if (hastrianglestructures)
+      {
+	if (debugmode)
+	    fprintf(stderr,"Calculating Centroids\n");
+	for (int tr=0;tr<numtriangles;tr++)
+	    {
+	      float x=0.0,y=0.0,z=0.0;
+	      for (int pt=0;pt<=2;pt++)
+		  {
+		    int index=triangle[tr].p[pt];
+		    x+=point[index].x[0];
+		    y+=point[index].x[1];
+		    z+=point[index].x[2];
+		  }
+	      triangle[tr].c[0]=x/3.0;
+	      triangle[tr].c[1]=y/3.0;
+	      triangle[tr].c[2]=z/3.0;
+	    }
+	trianglecentroidsok=1;
+      }
+  return (trianglecentroidsok);
+}
+// ------------------------------------------------------------------------
+float PXTriangulatedStack::findnearestpoint(float&x,float& y,float &z,int &rpt,
+					    int interpolate,float maxdist)
+{
+
+  if (numpoints==0)
+      {
+	if (debugmode)
+	    fprintf(stderr,"No points in tstack\n");
+	exit(1);
+      }
+
+  rpt=0;
+  //  static int count=0;
+  float mindist2=200000.0;
+  float maxdist2=maxdist*maxdist;
+
+  //  count++;
+  if (interpolate<1)
+      {
+	int bestpt=0,pt=0,maxp=numpoints,minp=0;	
+	int besti=0;
+	int imin=0;
+	int imax=stackIndex.numcontours;
+	int above=0,below=0;
+
+	if (hasstackindex())
+	    {
+	      // Chances are good that we are looking within a slice or two 
+	      // Quickscan
+	      int found=0;
+	      if (z<point[0].x[2])
+		  {
+		    pt=0;
+		    maxp=stackIndex.index[1];
+		    found=1;
+		    below=1;
+		  }
+	      
+	      int i=0;
+	      while(i<stackIndex.numcontours-1 && found==0)
+		  {
+		    if (z>=stackIndex.zlevel[i] && z<stackIndex.zlevel[i+1])
+			found=1;
+		    else 
+			i++;
+		  }	      
+	      
+	      if (found==0)
+		  {
+		    above=1;
+		    i=stackIndex.numcontours-1;
+		    imin=i;
+		    imax=i+1;
+		  }
+	      else
+		  {
+		    besti=i;
+		    imin=Irange(besti,0,stackIndex.numcontours);
+		    imax=Irange(besti+1,imin+1,stackIndex.numcontours);
+		  }
+	    }
+	
+	pt=stackIndex.index[imin];
+	maxp=stackIndex.index[imax];
+	minp=pt;
+
+	
+	int done=0;
+	int oldpt=maxp+1;
+	int oldmaxp=maxp+1;
+	int iminold=imin;
+	int imaxold=imax;
+
+	
+
+	float zmin=point[Irange(minp-1,0,numpoints-1)].x[2];
+	float zmax=point[Irange(maxp,0,numpoints-1)].x[2];
+
+	//int first=0;
+	     
+	while(done==0)
+	    {
+	      /*first++;
+	      if (first>=5)
+		  {
+		    if (first==5)
+			fprintf(stderr,"----------above=%d,below=%d %6.3f %6.3f %6.3f\n",above,below,x,y,z);
+		    fprintf(stderr,"Expanding range from %d:%d to %d %d or %d:%d to %d:%d\n",
+			    iminold,imaxold,imin,imax,
+			    oldpt,oldmaxp,pt,maxp-1);
+		    fprintf(stderr,"\n\t Running in %d,%d (imin=%d,imax=%d) or z=%6.3f:%6.3f\n",
+			    pt,maxp-1,imin,imax,zmin,zmax);
+		  }*/
+	
+	      while (pt<maxp  && mindist2>maxdist2)
+		  {
+		    if (pt==oldpt)
+			{
+			  /*  if (first>=5)
+			      fprintf(stderr,"Skipping from %d to %d\n",oldpt,oldmaxp-1);*/
+			  pt=oldmaxp;
+			}
+		    float dist2=Fsqdist(x,y,z,
+					point[pt].x[0],point[pt].x[1],point[pt].x[2]);
+		    if (dist2<mindist2)
+			{
+			  bestpt=pt;
+			  mindist2=dist2;
+			}
+		    pt++;
+		  }
+	      
+	      float zminrange=Fmin(fabs(z-zmin),fabs(zmax-z));
+	      if (above==1)
+		  zminrange=z-zmin;
+	      else if (below==1)
+		  zminrange=zmax-z;
+
+	      /*if (first>=5)
+		  fprintf(stderr,"zrange=%6.3f, (zmin=%6.3f zmax=%6.3f z=%6.3f) mindist=%6.3f\n",zminrange,
+			  zmin,zmax,z,sqrt(mindist2));*/
+	      if (zminrange>sqrt(mindist2))
+		  {
+		    done=1;
+		  }
+	      else
+		  {
+		    iminold=imin;
+		    imaxold=imax;
+		    if ((fabs(z-zmin)<fabs(zmax-z)))
+			{
+			  imin=Irange(imin-1,0,stackIndex.numcontours);
+			  if (imin==iminold)
+			      {
+				imax=Irange(imax+1,imin+1,stackIndex.numcontours);
+				below=1;
+			      }
+			}
+		    else
+			{
+			  imax=Irange(imax+1,imin+1,stackIndex.numcontours);
+			  if (imax==imaxold)
+			      {
+				imin=Irange(imin-1,0,stackIndex.numcontours);
+				above=1;
+			      }
+			}
+		    
+		    if (imin==iminold && imax==imaxold)
+			{
+			  done=1;
+			}
+		    else
+			{
+			  oldpt=minp;
+			  oldmaxp=maxp;
+			  pt=stackIndex.index[imin];
+			  maxp=stackIndex.index[imax];
+			  zmin=point[Irange(pt-1,0,numpoints-1)].x[2];
+			  zmax=point[Irange(maxp,0,numpoints-1)].x[2];			  
+			}
+		  }
+	    }
+	//for (int ia=0;ia<=2;ia++)
+	//xp[ia]=point[bestpt].x[ia];
+	// rpt=bestpt;
+	//x=xp[0]; y=xp[1]; z=xp[2];
+	rpt=bestpt;
+	x=point[bestpt].x[0];	y=point[bestpt].x[1];	z=point[bestpt].x[2];
+      }
+  else
+      {
+	if (!hascentroids())
+	    calculateCentroids();
+
+	int tr=0,besttr=0;
+	while (tr<numtriangles && mindist2>maxdist2)
+	    {
+	      float dist2=Fsqdist(x,y,z,//p[0],xp[1],xp[2],
+				  triangle[tr].c[0],triangle[tr].c[1],triangle[tr].c[2]);
+	      if (dist2<mindist2)
+		  {
+		    besttr=tr;
+		    mindist2=dist2;
+		  }
+	      tr++;
+	    }
+	float dist[3],totaldist=0.0;
+	
+	int org=triangle[besttr].p[0],pt;
+	PX3Vector nod[3];
+	for (int ia=0;ia<=2;ia++)
+	    nod[ia].setvector(point[org].x[ia],point[org].x[ia],point[org].x[ia]);
+	PX3Vector vertex(x,y,z);//xp[0],xp[1],xp[2]);
+	for (pt=0;pt<=2;pt++)
+	    {
+	      int pt1=Icyclic(pt+1,3);
+	      int pt2=Icyclic(pt+2,3);
+
+	      PX3Vector leg1,leg2;
+	      leg1.copy(&nod[pt1]);       leg2.copy(&nod[pt2]);
+	      leg1.subtract(&vertex);     leg2.subtract(&vertex);
+	      leg1.crosswithoverwrite(&leg2);
+	      dist[pt]=leg1.getlength();
+	      totaldist+=dist[pt];
+	    }
+	float px[3];
+	for (int ib=0;ib<=2;ib++)
+	    px[ib]=0.0;
+	
+	for (pt=0;pt<=2;pt++)
+	    {
+	      int index=triangle[besttr].p[pt];
+	      for (int ia=0;ia<=2;ia++)
+		  px[ia]+=dist[pt]/totaldist*point[index].x[ia];
+	    }
+
+	// Find Closest Point as well 
+	float mindist=dist[0];
+	rpt=triangle[besttr].p[0];
+
+	for (int ic=1;ic<=2;ic++)
+	    {
+	      if(dist[ic]<mindist)
+		  {
+		    mindist=dist[ic];
+		    rpt=triangle[besttr].p[ic];
+		  }
+	    }
+	mindist2=Fdist(px[0],px[1],px[2],x,y,z);//xp[0],xp[1],xp[2]);
+	x=px[0];y=px[1];z=px[2];
+      }
+
+  //  if (count==50)      count=0;
+  return sqrt(mindist2);
+}
+// ------------------------------------------------------------------------
+void PXTriangulatedStack::deformUsingDisplacements(PX3Vector *dx,float factor,
+						   int smoothiter)
+{
+  PX3Vector *temp=NULL;
+  /*if (fabs(factor)<0.01)
+      factor=0.01;*/
+
+  if (smoothiter>0)
+      {
+	temp=new PX3Vector[numpoints];
+	for (int i=0;i<numpoints;i++)
+	    for (int ia=0;ia<=2;ia++)
+		temp[i].x[ia]=point[i].x[ia];  
+      }
+
+  for (int i=0;i<numpoints;i++)
+      for (int ia=0;ia<=2;ia++)
+	  point[i].x[ia]=point[i].x[ia]+factor*dx[i].x[ia];
+  
+  if (smoothiter>0)
+      {
+	if (debugmode)
+	    fprintf(stderr,"Smoothing Deformed Stack %d\n",smoothiter);
+	nonShrinkSmooth(0.33,-0.34,smoothiter,2);
+	for (int i=0;i<numpoints;i++)
+	    for (int ia=0;ia<=2;ia++)
+		dx[i].x[ia]=(point[i].x[ia]-temp[i].x[ia])/factor;
+
+	delete [] temp;
+      }
+
+  if (hascentroids())
+      calculateCentroids();
+
+}
+// ------------------------------------------------------------------------
+void PXTriangulatedStack::findbestpair(PXDispPair* pair,int npoints,
+				       float& x,float& y,float& z,float threshold)
+{
+  int i=0;
+  int found=0;
+  int ip=0;
+  float bestdist=10000000.0;
+
+  while(found==0 && i<npoints)
+      {
+	float d=Fsqdist(x,y,z,pair[i].x1,pair[i].y1,pair[i].z1);
+	if (d<bestdist)
+	    {
+	      ip=i;
+	      bestdist=d;
+	      if (Fsamepoint(x,y,z,pair[i].x1,pair[i].y1,pair[i].z1,threshold))
+		  found=1;
+	    }
+	i++;
+      }
+
+  x=pair[ip].x2;
+  y=pair[ip].y2;
+  z=pair[ip].z2;
+
+  /*  pair[ip].x1=-10000.0;
+      pair[ip].y1=-10000.0;
+      pair[ip].z1=-10000.0;*/
+}
+// ------------------------------------------------------------------------
+void PXTriangulatedStack::deformUsingShapeDisplacements(const char* dispname,float threshold)
+{
+  //  int debugmode=1;
+  PXDispPair* pairs;
+  int  npoints;
+  char line[100];
+
+  // Read in Displacements
+  // ---------------------
+  FILE* fin=fopen(dispname,"r");
+  if (fin!=NULL)
+      {
+	npoints=0; 
+	while ( fgets(line,100,fin)!=NULL )    
+	    npoints++;
+	fclose(fin);
+	/*	if (debugmode)
+		fprintf(stderr,"\t%s (np=%d) ",anaeatpath(dispname),npoints);*/
+	pairs=new PXDispPair[npoints];
+	
+	fin=fopen(dispname,"r");
+	for (int i=0;i<npoints;i++)
+	    fscanf(fin,"%f %f %f %f %f %f\n",
+		   &pairs[i].x1,&pairs[i].y1,&pairs[i].z1,
+		   &pairs[i].x2,&pairs[i].y2,&pairs[i].z2);
+	fclose(fin);
+      }
+  else
+      {
+	if (debugmode)
+	    fprintf(stderr,"Cannot Open %s\n",dispname);
+	return;
+      }
+  
+  if (debugmode)
+      fprintf(stderr,"\n");
+  
+  // Find Matching Pairs of Neighbours, 
+  // ---------------------------------------------------
+  int numn=0;
+  float dist=0.0;
+  
+  if (debugmode)
+      fprintf(stderr,"Finding Best Pair :: (%d)",numpoints);
+
+  for (int pt=0;pt<numpoints;pt++)
+      {
+	if (100*int(pt/100)==pt && debugmode)
+	    fprintf(stderr,"%2d ",pt);
+	float px=point[pt].x[0];
+	float py=point[pt].x[1];
+	float pz=point[pt].x[2];
+	float px0=px,py0=py,pz0=pz;
+	findbestpair(pairs,npoints,px,py,pz,threshold);
+	point[pt].x[0]=px;
+	point[pt].x[1]=py;
+	point[pt].x[2]=pz;
+	dist+=sqrt(pow(px-px0,float(2.0))+pow(py-py0,float(2.0))+pow(pz-pz0,float(2.0)));
+	numn++;
+      }
+  
+  if (numn==0)  numn++;
+
+  if (debugmode)
+      fprintf(stderr,"\n**Average Displacements=%6.4f(%d)\n",
+	      dist/float(numn),numn);
+	      
+  // Cleanup at end 
+  delete [] pairs;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::LoadOffset(const char* fname)
+{
+  int status=0;
+  char line[200];
+  FILE* fin=fopen(fname,"r");
+  if (fin)
+      {
+	do 
+	    {
+	      fgets(line,100,fin);
+	    }
+	while (line[0]=='#');
+	int st=strncmp(line, "NOFF",4);
+	if (st==0)
+	    {
+	      int npoints,ntriangles,temp;
+	      fscanf(fin,"%d %d %d\n",&npoints,&ntriangles,&temp);
+	      cleanup();
+	      init(npoints,ntriangles);
+	      int i;
+	      for (i=0;i<npoints;i++)
+		  {
+		    float x,y,z,nx,ny,nz;
+		    fscanf(fin,"%f %f %f %f %f %f\n",&x,&y,&z,&nx,&ny,&nz);
+		    point[i].index=i;
+		    point[i].x[0]=x;   point[i].x[1]=y;   point[i].x[2]=z; 
+		    point[i].nx[0]=nx; point[i].nx[1]=ny; point[i].nx[2]=nz; 
+		  }
+	      for (i=0;i<ntriangles;i++)
+		  {
+		    int dummy,n1,n2,n3;
+		    fscanf(fin,"%d %d %d %d\n",&dummy,&n1,&n2,&n3);
+		    triangle[i].index=i;
+		    triangle[i].p[0]=n1; triangle[i].p[1]=n2; triangle[i].p[2]=n3; 
+		  }
+	      trianglecentroidsok=0;
+	      normalsok=1;
+	      status=1;
+	    }
+	fclose(fin);
+      }
+  return status;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::LoadOffset2(const char* fname)
+{
+  int status=0;
+  FILE* fin=fopen(fname,"r");
+  if (fin)
+      {
+	int temp;
+	fscanf(fin,"%d\n",&temp);
+	if (temp==3)
+	    {
+	      int npoints,ntriangles,temp;
+	      fscanf(fin,"%d %d %d\n",&npoints,&ntriangles,&temp);
+	      cleanup();
+	      init(npoints,ntriangles);
+	      int i;
+	      for (i=0;i<npoints;i++)
+		  {
+		    float x,y,z;
+		    fscanf(fin,"%f %f %f\n",&x,&y,&z);
+		    point[i].index=i;
+		    point[i].x[0]=x;   point[i].x[1]=y;   point[i].x[2]=z; 
+		  }
+	      for (i=0;i<ntriangles;i++)
+		  {
+		    int dummy,n1,n2,n3;
+		    fscanf(fin,"%d %d %d %d\n",&dummy,&n1,&n2,&n3);
+		    triangle[i].index=i;
+		    triangle[i].p[0]=n1; triangle[i].p[1]=n2; triangle[i].p[2]=n3; 
+		  }
+	      trianglecentroidsok=0;
+	      normalsok=1;
+	      status=1;
+	    }
+	fclose(fin);
+      }
+  return status;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::Load(const char* filename)
+{
+  gzFile fin=gzsuffixopen(filename,"r");
+  if (!fin)
+    {
+      fprintf(stderr,"Failed to open %s\n",filename);
+      return 0;
+    }
+  int st=Load(fin);
+  gzclose(fin);
+  return st;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::Load(gzFile fin)
+{
+  char line[400];
+  gzgets(fin,line,200);
+  if (gzfindstringinstring(line, "#TriangulatedStack")==0)
+    return 0;
+
+  cleanup();
+
+  int npoints,ntriangles,connect,norm,curv,ncntr;
+  gzgets(fin,line,200); sscanf(line,"#%d\n",&ncntr);
+  gzgets(fin,line,200); sscanf(line,"#%d\n",&npoints);
+  gzgets(fin,line,200); sscanf(line,"#%d\n",&ntriangles);
+  gzgets(fin,line,200); sscanf(line,"#%d\n",&connect);
+  gzgets(fin,line,200); sscanf(line,"#%d\n",&norm);
+  gzgets(fin,line,200); sscanf(line,"#%d\n",&curv);
+
+  init(npoints,ntriangles);
+
+  stackindexok=ncntr>0;
+  stackIndex.numcontours=ncntr;
+
+  hasneighbourstructures=(connect>0);
+  maxconnection=connect;
+  curvaturesok=(curv>0);
+  normalsok=(norm>0);
+
+  if (hasstackindex())
+      {
+	//  stackindexok=ncntr>0;
+	stackIndex.index=new int[stackIndex.numcontours+1];
+	stackIndex.zlevel=new float[stackIndex.numcontours];
+	gzgets(fin,line,200); 
+	for (int i=0;i<stackIndex.numcontours;i++)
+	    {
+	      gzgets(fin,line,200);
+	      sscanf(line,"%d %f\n",&stackIndex.index[i],&stackIndex.zlevel[i]);
+	    }
+	stackIndex.index[stackIndex.numcontours]=numpoints;
+      }
+
+  
+
+  if (haspoints())
+      {
+	int i;
+	gzgets(fin,line,200); 
+	for (i=0;i<numpoints;i++)
+	    {
+	      gzgets(fin,line,200);
+	      sscanf(line,"%d %f %f %f %f %f %f %f %f\n",
+		     &point[i].index,&point[i].x[0],&point[i].x[1],&point[i].x[2],
+		     &point[i].nx[0],&point[i].nx[1],&point[i].nx[2],&point[i].k[0],&point[i].k[1]);
+	      if (curvaturesok==0)
+		  {
+		    for (int ia=0;ia<=1;ia++)
+			point[i].k[ia]=0.0;
+		  }
+	      if (normalsok==0)
+		  {
+		    for (int ia=0;ia<=2;ia++)
+			point[i].nx[ia]=1.0*(ia==0);
+		  }
+	    }
+	      
+	if (hastriangles())
+	    {
+	      gzgets(fin,line,200);
+	      for (i=0;i<numtriangles;i++)
+		  {
+		    gzgets(fin,line,200);
+		    sscanf(line,"%d %d %d %d\n",&triangle[i].index,
+			   &triangle[i].p[0],&triangle[i].p[1],&triangle[i].p[2]);
+		  }
+	      //fprintf(stderr,"Last Triangle = %s\n",line);
+	      if (hasneighbours())
+		  {
+		    neighbours=new PXIntegerList[numpoints];
+		    neighboursList=new PXNeighboursList();
+		    gzgets(fin,line,200);
+		    for (i=0;i<numpoints;i++)
+			{
+			  int temp,num;
+			  gzgets(fin,line,400);
+			  sscanf(line,"%d %d ",&temp,&num);
+			  int po=0;
+			  po=stringskipspace(line,po);
+			  po=stringskipnumber(line,po);
+			  po=stringskipspace(line,po);
+			  po=stringskipnumber(line,po);
+
+			  for(int j=0;j<num;j++)
+			    {
+				po=stringskipspace(line,po);
+				sscanf(&line[po],"%d ",&temp);
+				po=stringskipnumber(line,po);
+				neighbours[i].Add(temp);
+			    }
+
+			  /*if (i<30)
+			    {
+			      int num=neighbours[i].getnumnodes();
+			      neighbours[i].Rewind();
+			      fprintf(stderr,"pt=%d \n",i);
+			      for (int ii=0;ii<num;ii++)
+				{
+				  fprintf(stderr,"%d ",neighbours[i].getcurrent());
+				  neighbours[i].Next();
+				}
+			      fprintf(stderr,"\n");
+			      }*/
+
+			  neighboursList->Add(&neighbours[i],i);
+			}
+		  }
+	    }
+	else if (debugmode)
+	    fprintf(stderr,"No Triangles\n");
+      }
+  else if (debugmode)
+      fprintf(stderr,"Does not have any points\n");
+  return 1;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::Save(const char* filename)
+{
+  int st=0;
+  FILE* fout=fopen(filename,"w");
+  if (fout==NULL)
+    return 0;
+  st=Save(fout);
+  fclose(fout);
+  return st;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::Save(FILE* fout)
+{
+  fprintf(fout,"#TriangulatedStack File,numcontours,numpoints,numtriangles,maxconnection,hasnormals,hascurvatures\n");
+  fprintf(fout,"#%d\n",stackIndex.numcontours);
+  fprintf(fout,"#%d\n",numpoints);
+  fprintf(fout,"#%d\n",numtriangles);
+  fprintf(fout,"#%d\n",maxconnection);
+  fprintf(fout,"#%d\n",normalsok);
+  fprintf(fout,"#%d\n",curvaturesok);
+  
+  if (hasstackindex())
+      {
+	fprintf(fout,"#--------------Contour Indices-------------------------------------\n");
+	for (int i=0;i<stackIndex.numcontours;i++)
+	    fprintf(fout,"%-6d %-8.3f\n",stackIndex.index[i],stackIndex.zlevel[i]);
+      }
+
+  if (haspoints())
+      {
+	fprintf(fout,"#--------------Points-----------------------------------------------\n");
+	for (int i=0;i<numpoints;i++)
+	    {
+	      fprintf(fout,"%6d %7.3f %7.3f %7.3f  %5.3f %5.3f %5.3f %10.6f %10.6f\n",
+		      point[i].index,point[i].x[0],point[i].x[1],point[i].x[2],
+		      point[i].nx[0],point[i].nx[1],point[i].nx[2],
+		      point[i].k[0],point[i].k[1]);
+	    }
+
+	if (hastriangles())
+	    {
+	      fprintf(fout,"#--------------Triangles--------------------------------------------\n");
+	      for (int i=0;i<numtriangles;i++)
+		  {
+		    fprintf(fout,"%6d %6d %6d %6d\n",triangle[i].index,
+			    triangle[i].p[0],triangle[i].p[1],triangle[i].p[2]);
+		  }
+	      if (hasneighbours())
+		{
+		  fprintf(fout,"#--------------Neighbours-------------------------------------------\n");
+		  for (int i=0;i<numpoints;i++)
+		    {
+		      neighbours[i].Rewind();
+		      int numn=neighbours[i].getnumnodes();
+		      fprintf(fout,"%-6d %2d ",i,numn);
+		      //fprintf(stderr,"%-6d %2d ",i,numn);
+		      for(int j=0;j<numn;j++)
+			{
+			  int a=neighbours[i].getcurrent();
+			  //  fprintf(stderr,"%-6d ",a);
+			  fprintf(fout,"%-6d ",a);
+			  neighbours[i].Next();
+			}
+		      fprintf(fout,"\n");
+		      //fprintf(stderr,"\n");
+		    }
+		}
+	    }
+      }
+  return(1);
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::generateNeighbours(int openSurfaceMode)
+{
+
+  if (!haspoints() || !hastriangles())
+    {
+      if (debugmode)
+	fprintf(stderr,"Cannot generate neighbours as points=%d , triangles=%d\n",
+		haspoints(),hastriangles());
+      return 0;
+    }
+  //  int* buffer=new int[200];
+  maxconnection=0;
+
+  cleanupneighbours();
+  neighboursList=new PXNeighboursList();
+  neighbours=new PXIntegerList[numpoints];
+  
+  if (debugmode)
+    fprintf(stderr,"Generating Neighbours (pt=%d,tr=%d):: ",numpoints,numtriangles);
+  
+  openSurfaceMode=Irange(openSurfaceMode,0,1);
+  int bt=0,tp=0;
+  if (!hasstackindex())
+    {
+      openSurfaceMode=0;
+    }
+  else
+    {
+      bt=stackIndex.index[1];
+      // Accept apex, i.e. normal surface on bottom 
+      if (bt==1)
+	bt=0;
+      tp=stackIndex.index[stackIndex.numcontours-1];
+    }
+  
+  for (int tr=0;tr<numtriangles;tr++)
+    {
+      if (debugmode>0)
+	{
+	  if (100*int(tr/100)==tr)
+	    fprintf(stderr,"%d/%d ",tr,numtriangles);
+	}
+      
+      for (int k=0;k<=2;k++)
+	{
+	  int pt=triangle[tr].p[k];
+	  for (int j=0;j<=2;j++)
+	    {
+	      if (!openSurfaceMode)
+		{
+		  neighbours[pt].AddNonDuplicate(triangle[tr].p[j],pt);
+		}
+	      else
+		{
+		  if (pt>=bt && pt<tp)
+		    {
+		      neighbours[pt].AddNonDuplicate(triangle[tr].p[j],pt);
+		    }
+		  else if (pt<bt && triangle[tr].p[j]<bt)
+		    {
+		      neighbours[pt].AddNonDuplicate(triangle[tr].p[j],pt);
+		    }
+		  else if (pt>=tp && triangle[tr].p[j]>=tp)
+		    {
+		      neighbours[pt].AddNonDuplicate(triangle[tr].p[j],pt);
+		    }
+		}
+	    }
+	}
+    }
+  
+  for (int pt=0;pt<numpoints;pt++)
+    {
+      neighboursList->Add(&neighbours[pt],pt);
+      maxconnection=Imax(maxconnection,neighbours[pt].getnumnodes());
+    }
+  if (debugmode)
+    fprintf(stderr,"\n");
+  hasneighbourstructures=1;
+  return 1;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::calculateCurvatures(int scale)
+{
+  int mode=0;
+
+  if (scale==-1000)
+      {
+	// Debug mode
+	if (debugmode)
+	    fprintf(stderr,"Curvature external force mode\n");
+	curvaturesok=1;
+	normalsok=1;
+	return 0;
+      }
+
+  if (scale<0)
+      {
+	mode=1;
+	scale=-scale;
+      }
+
+  scale=Irange(scale,1,10);
+  if (mode==1 && debugmode)
+      fprintf(stderr,"Curvature mode=%d, scale=%d\n",mode,scale);
+  int st=1;
+  if (!hasneighbours())
+      st=generateNeighbours();
+
+  if (st==0)
+      {
+	curvaturesok=0;
+	return 0;
+      }
+
+  Vertex_3d neighbour_point[500],xformed_neighbour_point[500];
+  int neighbour_index[500];
+
+  Node_3d N, T1, T2, T;
+  double c[4], length;
+  double x, y, z;
+
+  double fx, fy, fxx, fxy, fyy;
+  //  Node_3d k1, k2;
+  double K1, K2;
+  int nrot;
+  
+  double** A     = dmatrix(0, 500-1, 0, 5);
+  double** At    = dmatrix(0, 5, 0, 500-1);
+  double** B     = dmatrix(0, 5, 0, 5);
+  double** B_1   = dmatrix(0, 5, 0, 5);
+  int*     indx  = ivector(0, 5);
+  double** C     = dmatrix(0, 5, 0, 0);
+  double** C2    = dmatrix(0, 5, 0, 0);
+  double*  coeff = dvector(0, 5);
+  double** data  = dmatrix(0, 500-1, 0, 0);
+  
+  double** g     = dmatrix(0, 1, 0, 1);
+  double** g_1   = dmatrix(0, 1, 0, 1);
+  double** b     = dmatrix(0, 1, 0, 1);
+  double** beta  = dmatrix(0, 1, 0, 1);
+  double ** a1_repl = new double*[2];
+  a1_repl[0] = new double[2];
+  a1_repl[1] = new double[2];
+
+  double ** v1_repl = new double*[2];
+  v1_repl[0] = new double[2];
+  v1_repl[1] = new double[2];
+
+  double* d1_repl=new double[2];
+
+
+  
+  
+  for(int i=0; i<numpoints; i++)
+    {
+      if (debugmode)
+	{
+	  if (100*int(i/100)==i)
+	    fprintf(stderr,"%d/%d ",i,numpoints);
+	}
+      int j;
+      for(j=0; j<500; j++)
+	{
+	  neighbour_point[j].x   = 0.0;  neighbour_point[j].y   = 0.0;
+	  neighbour_point[j].z   = 0.0;
+	  neighbour_point[j].K   = 0.0;   neighbour_point[j].H   = 0.0;
+	  neighbour_point[j].k1  = 0.0;  neighbour_point[j].k2  = 0.0;
+	  neighbour_point[j].k1x = 0.0;  neighbour_point[j].k1y = 0.0;
+	  neighbour_point[j].k1z = 0.0;
+	  neighbour_point[j].k2x = 0.0;  neighbour_point[j].k2y = 0.0;
+	  neighbour_point[j].k2z = 0.0;  neighbour_point[j].nx  = 0.0;
+	  neighbour_point[j].ny  = 0.0;  neighbour_point[j].nz  = 0.0;
+	}
+      
+      /* find the neighbouring points within the defined radius */
+      neighbour_index[0] = i;
+      int k = 1;
+      
+      /* run through the layers of neighbours */
+      int num1 = 0, num2 = k;
+      for(int s=1; s<=scale; s++)
+	{
+	  for(int j=num1; j<num2; j++)
+	    {
+	      neighbours[neighbour_index[j]].Rewind();
+	      for(int m=0; m<neighbours[neighbour_index[j]].getnumnodes(); m++)
+		{
+		  int index=neighbours[neighbour_index[j]].getcurrent();
+		  int flag = 0;
+		  for (int n=0;n<k;n++)
+		    {
+		      if (index==neighbour_index[n])
+			flag=1;
+		    }
+		  if (flag==0)
+		    {
+		      neighbour_index[k]=index;
+		      k++;
+		    }
+		  neighbours[neighbour_index[j]].Next();
+		}
+	    }
+	  num1 = num2;
+	  num2 = k;
+	}
+      int num_neighbours = k;
+      if (debugmode)
+	{
+	  if (100*int(i/100)==i)
+	    fprintf(stderr,"num_neighbours[%d] = %d\t", i, num_neighbours);
+	}
+      
+      /*for(j=0; j<num_neighbours; j++)
+	neighbour_point[j] = point[neighbour_index[j]];*/
+      for (j=0;j<num_neighbours;j++)
+	{
+	  neighbour_point[j].x =point[neighbour_index[j]].x[0];
+	  neighbour_point[j].y =point[neighbour_index[j]].x[1];
+	  neighbour_point[j].z =point[neighbour_index[j]].x[2];
+	  neighbour_point[j].nx=point[neighbour_index[j]].nx[0];
+	  neighbour_point[j].ny=point[neighbour_index[j]].nx[1];
+	  neighbour_point[j].nz=point[neighbour_index[j]].nx[2];
+	}
+      
+      if(num_neighbours<5)
+	{
+	  if (debugmode)
+	    {
+	      fprintf(stderr,"point no.%d: very few neighbours: %d\n", i, num_neighbours);
+	      fprintf(stderr,"add three interpolated points\n");
+	    }
+	  /* there are at least four neighbours (including myself) */
+	  /* add three neighbours from the interpolation between   */
+	  /* me and the three existing neighbours. 		*/
+	  /* (need at least five neighbours 			*/ 
+	  for(j=0; j<3; j++){
+	    neighbour_point[j+num_neighbours].x 
+	      = (neighbour_point[0].x + neighbour_point[j].x) / 2.0;
+	    neighbour_point[j+num_neighbours].y 
+	      = (neighbour_point[0].y + neighbour_point[j].y) / 2.0;
+	    neighbour_point[j+num_neighbours].z 
+	      = (neighbour_point[0].z + neighbour_point[j].z) / 2.0;
+	  }
+	}
+      if(num_neighbours>499 && debugmode)
+	{
+	  fprintf(stderr,"point no.%d: too many neighbours: %d\n", i, num_neighbours);
+	  fprintf(stderr,"do you really need that many neighbours??\n");
+	}
+      
+      
+      /* the normal vector at point[i] */
+      N.x = point[i].nx[0];
+      N.y = point[i].nx[1];
+      N.z = point[i].nx[2];
+      
+      /* the coeffs of the tangent plane at point[i] */
+      c[0] = N.x;
+      c[1] = N.y;
+      c[2] = N.z;
+      c[3] = c[0] * point[i].x[0] + c[1] * point[i].x[1] + c[2] * point[i].x[2];
+      
+      /* pick a random point T on the tangent plane */
+      if(c[0]==1.0 || c[0]==-1.0)
+	{
+	  T.x = 0.0; T.y = 1.0;  T.z = 0.0;
+	}
+      else if(c[1]==1.0 || c[1]==-1.0)
+	{
+	  T.x = 0.0;  T.y = 0.0;  T.z = 1.0;
+	}
+      else if(c[2]==1.0 || c[2]==-1.0)
+	{
+	  T.x = 1.0;  T.y = 0.0;  T.z = 0.0;
+	}
+      else if(c[0]!=0.0)
+	{
+	  T.x = c[3] / c[0];  T.y = 0.0;  T.z = 0.0;
+	}
+      else if(c[1]!=0.0)
+	{
+	  T.x = 0.0;  T.y = c[3] / c[2];T.z = 0.0;
+	}
+      else if(c[2]!=0.0)
+	{
+	  T.x = 0.0; T.y = 0.0; T.z = c[3] / c[2];
+	}
+      
+      /* the vector between point[i] and T is the first(x) tangent vector */ 
+      T1.x = point[i].x[0] - T.x;
+      T1.y = point[i].x[1] - T.y;
+      T1.z = point[i].x[2] - T.z;
+      length = T1.x * T1.x + T1.y * T1.y + T1.z * T1.z; 
+      length = sqrt(length);
+      T1.x /= length;
+      T1.y /= length;	    
+      T1.z /= length;
+      
+      /* the cross product N x T1 is the second(y) tangent vector */
+      T2.x = N.y * T1.z - T1.y * N.z;
+      T2.y = N.z * T1.x - T1.z * N.x;
+      T2.z = N.x * T1.y - T1.x * N.y;
+      /*
+	fprintf(stderr,"N:  (%4.2f, %4.2f, %4.2f)\n", N.x, N.y, N.z);	    
+	fprintf(stderr,"Ti: (%4.2f, %4.2f, %4.2f)\n", T1.x, T1.y, T1.z);	    
+	fprintf(stderr,"T2: (%4.2f, %4.2f, %4.2f)\n", T2.x, T2.y, T2.z);	    
+      */	    
+      /* transform the neighbour points, such that   */
+      /* the current point (I) becomes the origin,  */
+      /* the normal direction N becomes the z-axis, */
+      /* and the tangent directions T1/T2 becomes   */
+      /* the x/y-axes.	 			  */
+      int m;
+      for(m=0; m<num_neighbours; m++)
+	{
+	  x = neighbour_point[m].x - point[i].x[0];
+	  y = neighbour_point[m].y - point[i].x[1];
+	  z = neighbour_point[m].z - point[i].x[2];
+	  xformed_neighbour_point[m].x = x * T1.x + y * T1.y + z * T1.z;
+	  xformed_neighbour_point[m].y = x * T2.x + y * T2.y + z * T2.z;
+	  xformed_neighbour_point[m].z = x * N.x  + y * N.y  + z * N.z;
+	}
+      
+      
+      /* fit the local quadric surface */
+      /* using least square method     */
+      for(m=0; m<num_neighbours; m++)
+	data[m][0] = xformed_neighbour_point[m].z;
+      
+      for(m=0; m<num_neighbours; m++){
+	A[m][0] = xformed_neighbour_point[m].x
+	  * xformed_neighbour_point[m].x;
+	A[m][1] = xformed_neighbour_point[m].y
+	  * xformed_neighbour_point[m].y;
+	A[m][2] = xformed_neighbour_point[m].x
+	  * xformed_neighbour_point[m].y;
+	A[m][3] = xformed_neighbour_point[m].x;
+	A[m][4] = xformed_neighbour_point[m].y;
+	A[m][5] = 1.0;
+      }
+      
+      double det=0;
+      int sing=0;
+      
+      matrix_transpose(A, At, num_neighbours, 6);
+      matrix_product(B, At, 6, num_neighbours, A, num_neighbours, 6);
+      if (mode==0)
+	matrix_inverse(B, B_1, 6);
+      else
+	{
+	  ludcmp0(B,6,indx,&det,sing);
+	  //fprintf(stderr,"Det =%f, sing=%d ",det,sing);
+	}
+      
+      matrix_product(C, At, 6, num_neighbours, data, num_neighbours, 1);
+      
+      if (mode==0)
+	{
+	  matrix_product(C2, B_1, 6, 6, C, 6, 1);
+	  for (int ii=0;ii<6;ii++)
+	    coeff[ii]=C2[ii][0];
+	}
+      else
+	{
+	  for (int ii=0;ii<6;ii++)
+	    coeff[ii]=C[ii][0];
+	  lubksb0(B,6,indx,coeff);
+	}
+      /*
+	// compute the residual of the fit 
+	double residual = 0.0;
+	for(m=0; m<num_neighbours; m++)
+	residual += fabs(data[m]
+	- coeff[0] * A[m][0]
+	- coeff[1] * A[m][1]
+	- coeff[2] * A[m][2]
+	- coeff[3] * A[m][3]
+	- coeff[4] * A[m][4]
+	- coeff[5] * A[m][5]); 
+      */
+      /* compute the curvatures */
+      fx  = coeff[3];
+      fy  = coeff[4];
+      fxx = coeff[0] * 2.0;
+      fxy = coeff[2];
+      fyy = coeff[1] * 2.0;
+      
+      g[0][0] = 1.0 + fx*fx;
+      g[0][1] = fx * fy;
+      g[1][0] = fx * fy;
+      g[1][1] = 1.0 + fy*fy;
+      
+      matrix_inverse(g, g_1, 2);
+      
+      b[0][0] = fxx / ((1.0+fx*fx+fy*fy) * (1.0+fx*fx+fy*fy));
+      b[0][1] = fxy / ((1.0+fx*fx+fy*fy) * (1.0+fx*fx+fy*fy));
+      b[1][0] = fxy / ((1.0+fx*fx+fy*fy) * (1.0+fx*fx+fy*fy));
+      b[1][1] = fyy / ((1.0+fx*fx+fy*fy) * (1.0+fx*fx+fy*fy));
+      
+      matrix_product(beta, g_1, 2, 2, b, 2, 2);
+      
+      //point[i].K = beta[0][0] * beta[1][1] - beta[0][1] * beta[1][0];
+      //point[i].H = (beta[0][0] + beta[1][1]) / 2.0;
+      
+      
+      for(m=1; m<3; m++)
+	for(int n=1; n<3; n++)
+	  a1_repl[m-1][n-1] = beta[m-1][n-1];
+
+      vtkMath_JacobiN(a1_repl,2,d1_repl,v1_repl);
+
+      /*
+      get_eigenvalues_vectors(a1, 2, d1, v1, &nrot);
+      sort_eigenvalues_vectors(d1, v1, 2);*/
+      
+      K1 = d1_repl[0];
+      K2 = d1_repl[1];
+      
+      if (debugmode)
+	{
+	  if (100*int(i/100)==i)
+	    fprintf(stderr," k1=%6.3f, k2=%6.3f\n",K1,K2);
+	}
+      
+      /* the prinipal curvatures and directions in local space */
+      point[i].k[0] = K1;
+      point[i].k[1] = K2;
+      
+      //k1.x = v1[1][1]; k1.y = v1[2][1]; k1.z = 0.0;
+      //k2.x = v1[1][2]; k2.y = v1[2][2]; k2.z = 0.0;
+      
+      /* the two principal directions in global space */
+      /*point[i].k1x = T1.x*k1.x + T2.x*k1.y + N.x*k1.z;
+	point[i].k1y = T1.y*k1.x + T2.y*k1.y + N.y*k1.z;
+	point[i].k1z = T1.z*k1.x + T2.z*k1.y + N.z*k1.z;
+	point[i].k2x = T1.x*k2.x + T2.x*k2.y + N.x*k2.z;
+	point[i].k2y = T1.y*k2.x + T2.y*k2.y + N.y*k2.z;
+	point[i].k2z = T1.z*k2.x + T2.z*k2.y + N.z*k2.z;*/
+      
+      /* the normal vector in global space */
+      point[i].nx[0] = N.x;
+      point[i].nx[1] = N.y;
+      point[i].nx[2] = N.z;	
+    }
+  
+  free_dmatrix(A,     0,500-1,0,5);
+  free_dmatrix(At,    0,5,0,500-1);
+  free_dmatrix(B,     0,5,0,5);
+  free_dmatrix(B_1,   0,5,0,5);
+  free_ivector(indx  ,0,5);
+  free_dmatrix(C,     0,5,0,5);
+  free_dmatrix(C2,    0,5,0,5);
+  free_dvector(coeff, 0,5);
+  free_dmatrix(data,  0,500-1,0,0);
+  free_dmatrix(g,     0, 1, 0, 1);
+  free_dmatrix(g_1,   0, 1, 0, 1);
+  free_dmatrix(b,     0, 1, 0, 1);
+  free_dmatrix(beta,  0, 1, 0, 1);
+
+  delete [] a1_repl[1]; 
+  delete [] a1_repl[0]; 
+  delete [] a1_repl;
+
+
+  delete [] v1_repl[1]; 
+  delete [] v1_repl[0]; 
+  delete [] v1_repl;
+
+  delete [] d1_repl;
+
+  curvaturesok=1;
+  //  debugmode=0;
+  return 1;
+   
+}
+// ------------------------------------------------------------------------
+// Color Lookup Table Functions, from Peng-Cheng's shape_index
+// ------------------------------------------------------------------------
+float PXTriangulatedStack::curvature_lookup_red(float val)
+{
+
+  if(val < 0.0 || val > 1.0)
+      {
+	if (debugmode)
+	  fprintf(stderr,"error in red curvature value(%10.5f)\n",val);
+	val=Frange(val,0.0,1.0);
+      }
+  
+  if(val < 0.5)
+    return(1.0);
+  else if(val == 0.5)
+    return(1.0);
+
+  return(2.0 - 2.0*val);
+}
+
+float PXTriangulatedStack::curvature_lookup_green(float val)
+{
+  if(val < 0.0 || val > 1.0)
+      {
+	  if (debugmode)
+		fprintf(stderr,"error in green curvature value(%10.5f)\n",val);
+	val=Frange(val,0.0,1.0);
+      }
+  
+  if(val < 0.5)
+      return(2.0 * val);
+  else if(val == 0.5)
+      return(1.0);
+  
+  return(1.0);
+}
+
+float PXTriangulatedStack::curvature_lookup_blue(float val)
+     
+{
+  if(val < 0.0 || val > 1.0)
+      {
+		if (debugmode)
+		fprintf(stderr,"error in blue curvature value(%10.5f)\n",val);
+	val=Frange(val,0.0,1.0);
+      }
+
+  if(val < 0.5)
+      return(2.0 * val);
+  else if(val == 0.5)
+      return(1.0);
+  
+  return(2.0 - 2.0*val);
+}
+
+
+/* the follow three functions are for the bending energy rgb lookup table */ 
+float PXTriangulatedStack::bending_energy_lookup_red(float val)
+{
+  if(val < 0.0 || val > 1.0)
+      {
+		if (debugmode)
+		fprintf(stderr,"error in red bending energy value(%10.5f)\n",val);
+	val=Frange(val,0.0,1.0);
+      }
+
+  return(2.0 - 2.0*val);
+}
+
+float PXTriangulatedStack::bending_energy_lookup_green(float val)
+{
+  if(val < 0.0 || val > 1.0)
+      {
+		if (debugmode)
+		fprintf(stderr,"error in green bending energy value(%10.5f)\n",val);
+	val=Frange(val,0.0,1.0);
+      }
+ 
+  return(1.0);
+}
+
+float PXTriangulatedStack::bending_energy_lookup_blue(float val)
+{
+  if(val < 0.0 || val > 1.0)
+      {
+		if (debugmode)
+		fprintf(stderr,"error in blue bending energy value(%10.5f)\n",val);
+	val=Frange(val,0.0,1.0);
+      }
+
+  return(2.0 - 2.0*val);
+}
+
+
+/* the follow three functions are for the shape index rgb lookup table */
+float PXTriangulatedStack::shape_index_lookup_red(float val)
+{
+  if(val < -1.0 || val > 1.0)
+      {
+	if (debugmode)
+	  fprintf(stderr,"error in red shape index value(%10.5f)\n",val);
+	val=Frange(val,-1.0,1.0);
+      }
+  if(val < -7.0/8.0) 
+      return(0.0);
+  else if(val < -5.0/8.0) 
+      return(0.0);
+  else if(val < -3.0/8.0) 
+      return(0.0);
+  else if(val < -1.0/8.0) 
+      return(0.5);
+  else if(val < 1.0/8.0) 
+      return(1.0);
+  else if(val < 3.0/8.0) 
+      return(1.0);
+  else if(val < 5.0/8.0) 
+      return(1.0);
+  else if (val < 7.0/8.0) 
+      return(1.0);
+
+  return(1.0);
+}
+
+float PXTriangulatedStack::shape_index_lookup_green(float val)
+{
+  if(val < -1.0 || val > 1.0)
+      {
+	if (debugmode)
+	  fprintf(stderr,"error in green shape index value(%10.5f)\n",val);
+	val=Frange(val,-1.0,1.0);
+      }
+
+
+  if(val < -7.0/8.0) 
+      return(1.0);
+  else if(val < -5.0/8.0) 
+      return(1.0);
+  else if(val < -3.0/8.0) 
+      return(1.0);
+  else if(val < -1.0/8.0) 
+      return(1.0);
+  else if(val < 1.0/8.0) 
+      return(1.0);
+  else if(val < 3.0/8.0) 
+      return(1.0);
+  else if(val < 5.0/8.0) 
+      return(1.0);
+  else if (val < 7.0/8.0) 
+      return(0.5);
+
+  return(0.0);
+}
+
+float PXTriangulatedStack::shape_index_lookup_blue(float val)
+{
+  if(val < -1.0 || val > 1.0)
+    {
+      if (debugmode)
+	fprintf(stderr,"error in blue shape index value(%10.5f)\n",val);
+      val=Frange(val,-1.0,1.0);
+    }
+  
+  if(val < -7.0/8.0) 
+    return(0.0);
+  else if(val < -5.0/8.0) 
+    return(0.5);
+  else if(val < -3.0/8.0) 
+    return(1.0);
+  else if(val < -1.0/8.0) 
+    return(1.0);
+  else if(val < 1.0/8.0) 
+    return(1.0);
+  else if(val < 3.0/8.0) 
+    return(0.5);
+  else if(val < 5.0/8.0) 
+    return(0.0);
+  else if (val < 7.0/8.0) 
+    return(0.0);
+  
+  return(0.0);
+}
+// ------------------------------------------------------------------------
+//      Generating Lookup Table Colors
+// ------------------------------------------------------------------------
+PXColorPoint* PXTriangulatedStack::generateColors(int mode,float gamma)
+{
+  if (!curvaturesok)
+      return NULL;
+  
+  gamma=Frange(gamma,0.05,10.0);
+  
+  if (debugmode)
+      fprintf(stderr,"Allocating colors %d\n",numpoints);
+  PXColorPoint* colors=new PXColorPoint[numpoints];
+  float* value=new float[numpoints]; float max=0.00001;
+  mode=Irange(mode,0,5);
+  float amin=1000.0,amax=-1000.0;
+  int i;
+  for (i=0;i<numpoints;i++)
+      {
+	switch (mode)
+	    {  //(K=0, H=1, k1=2, k2=3, B=4, Index=5)
+	    case 0: // Gaussian
+	      value[i]=point[i].k[0]*point[i].k[1];
+	      break;
+	    case 1: // Mean Curvature
+	      value[i]=0.5*(point[i].k[0]+point[i].k[1]);
+	      break;
+	    case 2: // Principal Curvature 1
+	      value[i]=point[i].k[0];
+	      break;
+	    case 3: // Principal Curvature 2
+	      value[i]=point[i].k[1];
+	      break;
+	    case 4: // Bending Energy
+	      value[i]=sqrt(0.5*(pow(point[i].k[0],float(2.0))+pow(point[i].k[1],float(2.0))));
+	      break;
+	    case 5: // Shape Index 
+	      if(point[i].k[0]==point[i].k[1])
+		  {
+		    if(point[i].k[0]>0.0)  value[i] =  1.0;
+		    if(point[i].k[0]<0.0)  value[i] = -1.0;
+		    if(point[i].k[0]==0.0) value[i] =  0.0;
+		  }
+	      else
+		  value[i] = 2.0 / M_PI * atan((point[i].k[1]+point[i].k[0])/(point[i].k[1]-point[i].k[0]));
+	      break;
+	    }
+	if (mode<5)
+	    {
+	      max=Fmax(fabs(value[i]),max);
+	      amax=Fmax(amax,value[i]);
+	      amin=Fmin(amin,value[i]);
+	      if (mode<4)
+		  {
+		    max_curvature=Fmax((value[i]),max_curvature);
+		    min_curvature=Fmin((value[i]),min_curvature);
+		  }
+	    }
+      }
+  
+  for (i=0;i<numpoints;i++)
+      {
+
+	if (mode==4)
+	    {
+	      value[i]=value[i]/(max);
+	      value[i]=pow(value[i],float(1.0/gamma));
+	      colors[i].red=bending_energy_lookup_red(value[i]);
+	      colors[i].green=bending_energy_lookup_green(value[i]);
+	      colors[i].blue=bending_energy_lookup_blue(value[i]);
+	    }
+	else if (mode==5)
+	    {
+	      //value[i]=value[i]/(max);
+	      colors[i].red=shape_index_lookup_red(value[i]);
+	      colors[i].green=shape_index_lookup_green(value[i]);
+	      colors[i].blue=shape_index_lookup_blue(value[i]);
+	    }
+	else
+	    {
+	      max=Fmax(max_curvature,fabs(min_curvature));
+	      value[i]=value[i]/(2.0*max);
+	      float v=pow(fabs(value[i]),float(1.0/gamma));
+	      if (value[i]<0.0)
+		  v=0.5-v;
+	      else
+		  v=0.5+v;
+	      v=Frange(v,0.0,1.0);
+	      colors[i].red=curvature_lookup_red(v);
+	      colors[i].green=curvature_lookup_green(v);
+	      colors[i].blue=curvature_lookup_blue(v);
+	    }
+      }
+  delete [] value;
+  return colors;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::SaveInventor(const char* fname,PXColorPoint* colors)
+{
+  if (!haspoints() || !hastriangles())
+      {
+	  if (debugmode)
+		fprintf(stderr,"Cannot save inventor as points=%d , triangles=%d\n",
+			haspoints(),hastriangles());
+	return 0;
+      }
+  
+  int status=0;
+  FILE* fout=fopen(fname,"w");
+  if (fout)
+      {
+	fprintf(fout,"#Inventor V2.0 ascii\n");
+	status=SaveInventor(fout,colors);
+	if (debugmode && status)
+	    fprintf(stderr,"Saved inventor in %s\n",fname);
+
+	fclose(fout);
+      }
+  return(status);
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::SaveInventor(FILE* fout,PXColorPoint* colors)
+{
+  int status=0;
+  if (!haspoints() || !hastriangles())
+      {
+	  if (debugmode)
+		fprintf(stderr,"Cannot save inventor as points=%d , triangles=%d\n",
+			haspoints(),hastriangles());
+	return 0;
+      }
+  
+  if (fout)
+      {
+	fprintf(fout,"\tSeparator {\n");
+	fprintf(fout,"\t\tShapeHints {\n vertexOrdering  COUNTERCLOCKWISE\n  faceType CONVEX\n }\n\n");
+	fprintf(fout,"# %d Points,%d Triangles\n\n",numpoints,numtriangles);
+	fprintf(fout,"Coordinate3{ point[\n");
+	int i;
+	for (i=0;i<numpoints;i++)
+	    fprintf(fout,"%6.3f %6.3f %6.3f,\n",point[i].x[0],point[i].x[1],point[i].x[2]);
+	fprintf(fout,"]}\n");
+	if (normalsok)
+	    {
+	      fprintf(fout,"Normal { vector [\n");
+	      for (i=0;i<numpoints;i++)
+		  fprintf(fout,"%6.3f %6.3f %6.3f,\n",point[i].nx[0],point[i].nx[1],point[i].nx[2]);
+	      fprintf(fout,"]}\n");
+	    }
+	if (colors!=NULL)
+	    {
+	      fprintf(fout,"Material { diffuseColor [ \n");
+	      for (i=0;i<numpoints;i++)
+		  fprintf(fout,"%5.3f %5.3f %5.3f,\n",colors[i].red,colors[i].green,colors[i].blue);
+	      fprintf(fout,"]\n}\nMaterialBinding {\nvalue PER_VERTEX_INDEXED\n}\n");
+	    }
+
+	fprintf(fout,"IndexedFaceSet{ coordIndex[\n");
+	for (i=0;i<numtriangles;i++)
+	    fprintf(fout,"%d,%d,%d,-1,\n",triangle[i].p[0],triangle[i].p[1],triangle[i].p[2]);
+	fprintf(fout,"]\n");
+	if (normalsok)
+	    {
+	      fprintf(fout,"normalIndex  [\n");
+	      for (i=0;i<numtriangles;i++)
+		  fprintf(fout,"%d, %d, %d,-1,\n",triangle[i].p[0],triangle[i].p[1],triangle[i].p[2]);
+	      fprintf(fout,"]");
+	    }
+	fprintf(fout,"}\n}\n");
+	status=1;
+      }
+  return status;
+}
+// ------------------------------------------------------------------------
+void PXTriangulatedStack::findorigin(int np[2],float* x[2],float* y[2],float* z[2],
+				     int origin[2],int dimension)
+{
+
+  int found=0;
+  origin[0]=0;	  origin[1]=0;
+  int i=0;
+  while(!found && i<np[0])
+      {
+	origin[0]=i;
+	int bestj=0;
+	float mindist=10000000.0;
+	for(int j=0;j<np[1];j++)
+	    {
+	      float dist;
+	      if (dimension==3)
+		  dist=Fsqdist(x[0][i],y[0][i],z[0][i],x[1][j],y[1][j],z[1][j]);
+	      else
+		  dist=Fsqdist(x[0][i],y[0][i],0.0,x[1][j],y[1][j],0.0);
+	      if (dist<mindist)
+		  {
+		    mindist=dist;
+		    bestj=j;
+		  }
+	    }
+	mindist=10000000.0;
+	int besti=i;
+	for (int k=0;k<np[0];k++)
+	    {
+	      float dist;
+	      if (dimension==3)
+		  dist=Fsqdist(x[0][k],y[0][k],z[0][k],x[1][bestj],y[1][bestj],z[1][bestj]);
+	      else
+		  dist=Fsqdist(x[0][k],y[0][k],0.0,x[1][bestj],y[1][bestj],0.0);
+	      if (dist<mindist)
+		  {
+		     mindist=dist;
+		     besti=k;
+		   }
+	    }
+	if (besti==i)
+	    {
+	      found=1;
+	      origin[0]=besti;
+	      origin[1]=bestj;
+	    }
+	i++;
+      }
+  if (!found)
+      {
+	  if (debugmode)
+		fprintf(stderr,"Error in origin\n");
+	origin[0]=0;
+	origin[1]=0;
+      }
+}
+// --------------------------------------------------------------
+int PXTriangulatedStack::triangulate(int np[2],float* x[2],float* y[2],float* z[2],int origin[2],
+				     PXNeighboursList* faces,int maxfaces,int dimension)
+{
+  int faceindex=0,done=0,numfaces=0,cend[2],current[2];
+  cend[0]=0; cend[1]=0;
+  current[0]=origin[0];  current[1]=origin[1];
+
+  // Initialize Triangle Structure 
+  PXNeighbours* triangle=new PXNeighbours();
+  triangle->num=3;
+  triangle->pt=new int[3];
+
+  while(!done)
+      {
+	float dist[2];
+	int next[2];
+	
+	for (int c1=0;c1<=1;c1++)
+	    if (np[c1]==1)
+		cend[c1]=1;
+
+	for (int c=0;c<=1;c++)
+	    {
+	      if (cend[c]==0)
+		  {
+		    next[c]=Icyclic(current[c]+1,np[c]);
+		    int other=current[1-c];
+		    if (dimension==3)
+			dist[c]=Fsqdist(x[c][next[c]],y[c][next[c]],z[c][next[c]],
+					x[1-c][other],y[1-c][other],z[1-c][other]);
+		    else
+			dist[c]=Fsqdist(x[c][next[c]],y[c][next[c]],0.0,
+					x[1-c][other],y[1-c][other],0.0);
+		  }
+	      else
+		  dist[c]=100000000.0;
+	    }
+	
+	if (dist[0]<dist[1])
+	    {
+	      triangle->pt[0]=current[0];
+	      triangle->pt[1]=next[0];
+	      triangle->pt[2]=current[1]+np[0];
+	      faces->Add(triangle,faceindex);
+	      faceindex++;
+	      current[0]=next[0];
+	      if (current[0]==origin[0]) 
+		  cend[0]=1;
+	      
+	    }
+	else
+	    {
+	      triangle->pt[0]=current[0];
+	      triangle->pt[1]=next[1]+np[0];
+	      triangle->pt[2]=current[1]+np[0];
+	      faces->Add(triangle,faceindex);
+	      faceindex++;
+	      current[1]=next[1];
+	      if (current[1]==origin[1]) 
+		  cend[1]=1;
+	    }
+	numfaces++;
+	
+	if (cend[0]==1 && cend[1]==1)
+	    done=1;
+	
+	if (faceindex>=maxfaces)
+	    {
+		if (debugmode)
+	      fprintf(stderr,"\n\t\tError not closing in %d\n",maxfaces);
+	      done=1;
+	    }
+      }
+  delete [] triangle->pt;
+  delete triangle;
+  return faceindex;
+}
+// ------------------------------------------------------------------------
+void PXTriangulatedStack::findorigin2D(int np[2],float* x[2],float* y[2],
+				       int origin[2])
+{
+  findorigin(np,x,y,NULL,origin,2);
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::triangulate2D(int np[2],float* x[2],float* y[2],int origin[2],
+				       PXNeighboursList* faces,int maxfaces)
+{
+  return triangulate(np,x,y,NULL,origin,faces,maxfaces,2);
+}
+// ------------------------------------------------------------------------
+void PXTriangulatedStack::getstatistics(float mean[3],float var[6],PXTriangulatedStack* other)
+{
+  PXTriangulatedStack *st[2];
+  st[0]=this;
+  st[1]=other;
+
+  int numst=2,np=0;
+  if (other==NULL)
+      {
+	//fprintf(stderr,"Single Mode\n");
+	numst=1;
+      }
+  /*se 
+      fprintf(stderr,"Dual Mode\n");*/
+  int i;
+  for (i=0;i<3;i++)
+      mean[i]=0.0;
+  for (i=0;i<6;i++)
+      var[i]=0.0;
+
+  int k;
+  for (k=0;k<numst;k++)
+      {
+	for (int i=0;i<numpoints;i++)
+	    {
+	      PXTriangulatedStackPoint* pointtemp=st[k]->getpoint(i);
+	      for (int ia=0;ia<=2;ia++)
+		  mean[ia]+=pointtemp->x[ia];
+	    }
+	np+=st[k]->getnumpoints();
+      }
+  float scale=1.0/float(np);
+  if (np<1)
+      return;
+
+  for (i=0;i<=2;i++)
+      mean[i]=mean[i]*scale;
+  
+  for (k=0;k<numst;k++)
+      {
+	for (int i=0;i<numpoints;i++)
+	    {
+	      PXTriangulatedStackPoint* pointtemp=st[k]->getpoint(i);
+	      float x[3];
+	      for (int ia=0;ia<=2;ia++)
+		  x[ia]=pointtemp->x[ia]-mean[ia];
+	      
+	      var[0]+=x[0]*x[0];
+	      var[1]+=x[1]*x[1];
+	      var[2]+=x[2]*x[2];
+	      
+	      var[3]+=x[0]*x[1];
+	      var[4]+=x[0]*x[2];
+	      var[5]+=x[1]*x[2];
+	    }
+      }
+
+  for (i=0;i<=2;i++)
+      var[i]=scale*(var[i]);
+
+  var[3]=scale*(var[3]);
+  var[4]=scale*(var[4]);
+  var[5]=scale*(var[5]);
+  
+  if (debugmode)
+      fprintf(stderr,"\nPoints =%d (%8.5f)\nMean Position = (%6.2f,%6.2f,%6.2f)\n,\tVar= (%6.3f,%6.3f,%6.3f)\n"
+	      "\tCovariance = (%6.3f,%6.3f,%6.3f)\n",np,scale,
+	      mean[0],mean[1],mean[2],
+	      var[0],var[1],var[2],
+	      var[3],var[4],var[5]);
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::getrelationship(int p1,int p2,int max)
+{
+  if (!hasneighbours())
+      generateNeighbours();
+  
+  return (neighboursList->getrelationship(p1,p2,max));
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::findCentroid(int* p,int np,int iterations,int maxd)
+{
+  if (np<2)
+      return -1;
+  
+  PXIntegerList* list=new PXIntegerList();
+  for (int i=0;i<np;i++)
+      list->Add(p[i]);
+  int r=findCentroid(list,iterations,maxd);
+  delete list;
+  return r;
+
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::findCentroid(PXIntegerList* origList,int iterations,int maxd)
+{
+  if (origList->getnumnodes()<2)
+      return -1;
+  
+  // int a=getrelationship(0,1);
+  //  fprintf(stderr,"Relationship between 0 and 1 = %d\n",a);
+  //  neighboursList->Save("n.list");
+  PXIntegerList* intList=new PXIntegerList();
+  origList->Rewind();
+  int i;
+  for (i=0;i<origList->getnumnodes();i++)
+      {
+	intList->Add(origList->getcurrent());
+	origList->Next();
+      }
+
+  for (int iter=0;iter<=iterations;iter++)
+      {
+	origList->Rewind();
+	for (int pt=0;pt<origList->getnumnodes();pt++)
+	    {
+	      int ptr=origList->getcurrent();
+	      // fprintf(stderr,"Looking for point %d\n",ptr);
+	      neighbours[ptr].Rewind();
+
+	      for (int k=0;k<neighbours[ptr].getnumnodes();k++)
+		  {
+		    //fprintf(stderr," test against %d \n",neighbours[ptr].getcurrent());
+		    intList->AddNonDuplicate(neighbours[ptr].getcurrent(),-1);
+		    neighbours[ptr].Next();
+		  }
+	      origList->Next();
+	    }
+      }
+
+  // Compile Distance Table 
+  int mindist=1000000000;
+  int bestnode=-1;
+
+  origList->Rewind();
+  for( i=0;i<origList->getnumnodes();i++)
+      {
+	int dist=0;
+	intList->Rewind();
+	for (int j=0;j<intList->getnumnodes();j++)
+	    {
+	      int a=getrelationship(origList->getcurrent(),intList->getcurrent(),maxd);
+	      dist=Imax(dist,a);
+	      intList->Next();
+	    }
+	
+	if (dist<mindist)
+	    {
+	      mindist=dist;
+	      bestnode=origList->getcurrent();
+	    }
+	origList->Next();
+      }
+  delete intList;
+  return bestnode;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::saveTstackPair(const char *fname,
+					PXTriangulatedStack* stack1,PXTriangulatedStack* stack2,
+					PX3Vector* dx,int* used,int* fixed)
+{
+  int status=0;
+  FILE *fout=fopen(fname,"w");
+  if (fout)
+      {
+	status=1;
+	fprintf(fout,"#Inventor V2.0 ascii\nSeparator {\n");
+	fprintf(fout,"Coordinate3{ point[\n");
+	int i;
+	for (i=0;i<stack1->getnumpoints();i++)
+	    fprintf(fout,"%6.3f %6.3f %6.3f,\n",
+		    (stack1->getpoint(i))->x[0],
+		    (stack1->getpoint(i))->x[1],
+		    (stack1->getpoint(i))->x[2]);
+	float mult=1.0;
+	for (i=0;i<stack1->getnumpoints();i++)
+	    fprintf(fout,"%6.3f %6.3f %6.3f,\n",
+		    (stack1->getpoint(i))->x[0]+mult*dx[i].x[0],
+		    (stack1->getpoint(i))->x[1]+mult*dx[i].x[1],
+		    (stack1->getpoint(i))->x[2]+mult*dx[i].x[2]);
+	
+	fprintf(fout,"]}\n");
+	
+	int maxpas=0;
+	if (fixed!=NULL && used!=NULL)
+	    maxpas=2;
+	
+	for (int pass=0;pass<=maxpas;pass++)
+	    {
+	      switch(pass)
+		  {
+		  case 0:
+		    fprintf(fout,"Material {  diffuseColor 1.0 1.0 0.0 \n transparency 0.0 }\n");
+		    break;
+		  case 1:
+		    fprintf(fout,"Material {  diffuseColor 1 0.0 0.0 \n transparency 0.0}\n");
+		    break;
+		  case 2:
+		    fprintf(fout,"Material {  diffuseColor 0.0 1.0 0.0 \n transparency 0.0}\n" );
+		    break;
+		  }
+	      
+	      fprintf(fout,"IndexedLineSet{ coordIndex[\n");
+	      
+	      for (i=0;i<stack1->getnumpoints();i++)
+		  {
+		    int num1=0;
+		    if (maxpas>0)
+			num1=fixed[i]+used[i];
+		    
+		    if (pass==num1)
+			fprintf(fout,"%d,%d,-1,\n",i,i+stack1->getnumpoints());
+		  }
+	      fprintf(fout,"]}\n");
+	    }
+	fprintf(fout,"}\n");
+	//fprintf(fout,"DrawStyle {	style LINES	}\n");
+	fprintf(fout,"Material {  diffuseColor 0.2 0.2 0.2 \n transparency 0.0}\n" );
+	stack1->SaveInventor(fout);
+	fprintf(fout,"Material {  diffuseColor 0.0 0.0 1.0 \n transparency 0.2}\n" );
+	stack2->SaveInventor(fout);
+	fclose(fout);
+	if (debugmode)
+	    fprintf(stderr,"Saving in %s \n",fname);
+      }
+  return status;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::findSymmetricPair(PXTriangulatedStack* tstack1,PXTriangulatedStack* tstack2,
+					   PXNeighboursList* pairs,int seedt)
+{
+  static int count=0;
+
+  if (debugmode && count==0)
+      {
+	fprintf(stderr,"Using Symmetric Nearest Neighbour\n");
+	count=1;
+      }
+  int done=0,steps=0;
+  int seedpoint=Irange(seedt,0,tstack1->getnumpoints()-1);
+  int bestpoint=0;
+  int bestpoint2=0;
+  
+  while(!done && steps<10)
+      {
+	float x[3],x0[3];
+	for (int ia=0;ia<=2;ia++)
+	    x[ia]=(tstack1->getpoint(seedpoint))->x[ia];
+	tstack2->findnearestpoint(x[0],x[1],x[2],bestpoint,0,0.01);
+	
+	for (int ib=0;ib<=2;ib++)
+	     x0[ib]=(tstack2->getpoint(bestpoint))->x[ib];
+
+	tstack1->findnearestpoint(x0[0],x0[1],x0[2],bestpoint2,0,0.01);
+	
+	if (seedpoint==bestpoint2)
+	    done=1;
+	else
+	    seedpoint=bestpoint2;
+	
+	steps++;
+      }
+  
+  if (steps<10)
+      {
+	PXIntegerList* firstpairs=new PXIntegerList();
+	firstpairs->Add(seedpoint);
+	firstpairs->Add(bestpoint+tstack1->getnumpoints());
+	
+	if (pairs->getnumnodes()==0)
+	    {
+	      pairs->Add(firstpairs,pairs->getnumnodes()+1);
+	    }
+	else
+	    {
+	      pairs->Rewind();
+	      int found=0,i=0;
+	      while (i<pairs->getnumnodes() && found==0)
+		  {
+		    PXIntegerList* element=(pairs->getcurrentnode())->points;
+		    if (element->numberinCommon(firstpairs)==2)
+			found=1;
+		    i++;
+		    pairs->Next();
+		  }
+	      if (found==0)
+		  {
+		    pairs->Add(firstpairs,pairs->getnumnodes()+1);
+		  }
+	    }
+	delete firstpairs;
+	return 1;
+      }
+  return 0;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::smoothEuclidean(PXTriangulatedStack* tstack1,PXTriangulatedStack* tstack2,
+					 PX3Vector* newdisp,PX3Vector* olddisp,
+					 int* used,int* fixed,int* corr,
+					 int mode,int saveno,int smoothOutput)
+{
+  if (debugmode)
+      fprintf(stderr,"\t1. Averaging step (moving fixed=%d,subpixel=%d)\n",
+	      mode>=tstack1->getnumpoints(),mode>tstack1->getnumpoints());
+  int good=0;
+  //int mid=tstack1->getnumpoints()/2;
+  int pt;
+  for (pt=0;pt<tstack1->getnumpoints();pt++)
+      {
+	
+	if (fixed[pt]==0 || mode>=tstack1->getnumpoints())
+	    {
+	      good+=used[pt];
+	      PXIntegerList* neigh=tstack1->getneighbours(pt);
+	      neigh->Rewind();
+	      int numgood=0;
+	      float newx[3];
+	      for (int ia=0;ia<=2;ia++)
+		  newx[ia]=0.0;
+	      for (int n=0;n<neigh->getnumnodes();n++)
+		  {
+		    int ind=neigh->getcurrent();
+		    if (used[ind]==1)
+			{
+			  numgood++;
+			  for (int ia=0;ia<=2;ia++)
+			      newx[ia]+=olddisp[ind].x[ia];
+			}
+		    neigh->Next();
+		  }
+	      if (numgood>0)
+		  {
+		    for (int ia=0;ia<=2;ia++)
+			newx[ia]=newx[ia]/float(numgood);
+		    float factor=0.5;
+		    if (used[pt]==0)
+			factor=1.0;
+		    
+		    for (int ib=0;ib<=2;ib++)
+			newdisp[pt].x[ib]=(1.0-factor)*olddisp[pt].x[ib]+factor*newx[ib];
+		    used[pt]=1;
+		  }
+	    }
+      }
+  
+  good=0;
+  for( pt=0;pt<tstack1->getnumpoints();pt++)
+      {
+	used[pt]=abs(used[pt]);
+	good+=used[pt];
+      }
+
+  if (debugmode)
+      {
+	fprintf(stderr,"\t\t (%d/%d) points have displacements\n",good,tstack1->getnumpoints());
+	fprintf(stderr,"\t2. Mapping step\n");
+      }
+
+
+  float dist=0.0,maxshift=0.0,maxdist=0.0;
+  int reverse=0;
+  for (pt=0;pt<tstack1->getnumpoints();pt++)
+      {
+	if (100*int(pt/100)==pt && pt>0 && debugmode)
+	    fprintf(stderr,"%d/%d ",pt,tstack1->getnumpoints());
+	if (600*int(pt/600)==pt && pt>0 && debugmode)
+	    fprintf(stderr,"\n");
+
+	PXTriangulatedStackPoint* point1=tstack1->getpoint(pt);
+	if ((used[pt]>0) && (fixed[pt]!=1 || good==tstack1->getnumpoints()))
+	    {
+	      float x[3];
+	      for (int ia=0;ia<=2;ia++)
+		  x[ia]=point1->x[ia]+newdisp[pt].x[ia]; 
+	      int mp;
+	      float d=tstack2->findnearestpoint(x[0],x[1],x[2],mp,(mode>tstack1->getnumpoints()),0.0);
+	      dist+=d;
+	      for (int ib=0;ib<=2;ib++)
+		  {
+		    x[ib]=x[ib]-point1->x[ib]; 
+		    newdisp[pt].x[ib]=x[ib];
+		  }
+
+	      maxdist=Fmax(maxdist,d);
+	      maxshift=Fmax(maxshift,Fsqdist( x[0],x[1],x[2],0.0,0.0,0.0));
+	      corr[pt]=mp;
+	    }
+      }
+  if (debugmode)
+      fprintf(stderr,"\t\taverage mapping distance %6.3f (max=%6.3f) maxshift=%6.3f rev=%d\n",
+	      dist/float(good),maxdist,sqrt(maxshift),reverse);
+
+
+  for (pt=0;pt<tstack1->getnumpoints();pt++)
+      {
+	for (int ia=0;ia<=2;ia++)
+	    olddisp[pt].x[ia]=newdisp[pt].x[ia];
+      }
+  
+  char line[100];
+  /*  if (saveno>0)
+      {
+	sprintf(line,"/tmp/iter.%02d.iv",saveno);
+	saveTstackPair(line,tstack1,tstack2,newdisp,used,fixed);
+      }*/
+  if (smoothOutput>0 || saveno>0)
+      tstack1->deformUsingDisplacements(newdisp,1.0,0); //smoothOutput);
+  if (saveno>0)
+      {
+	  if (debugmode)
+		fprintf(stderr,"Saving smoothed output\n");
+	sprintf(line,"/tmp/deformed.%02d.iv",saveno);
+	tstack1->SaveInventor(line);
+      }
+  if (smoothOutput>0 || saveno>0)
+      tstack1->deformUsingDisplacements(newdisp,-1.0);
+  return good;
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::smoothConnection(PXTriangulatedStack* tstack1,PXTriangulatedStack* tstack2,
+					  PX3Vector* disp,
+					  int* /*used*/,int* fixed,int* corr,
+					  int mode,int saveno,int smoothOutput)
+{
+  if (debugmode)
+      fprintf(stderr,"\t1. Maxdistance minimizing step (moving fixed=%d)\n",mode==1);
+  int shift=0;
+  //int mid=tstack1->getnumpoints()/2;
+  for (int pt=0;pt<tstack1->getnumpoints();pt++)
+      {
+	if (fixed[pt]==0 || mode==1)
+	    {
+	      PXIntegerList* neigh=tstack1->getneighbours(pt);
+	      neigh->Rewind();
+	      int bestcenter=corr[pt];
+	      int bestdist=0,bestmindist=100000000;
+	      for (int n=0;n<neigh->getnumnodes();n++)
+		  {
+		    int ind=neigh->getcurrent();
+		    int dist=tstack2->getrelationship(corr[pt],corr[ind],100);
+		    if (dist<0) 
+			dist=100;
+		    bestdist=Imax(dist,bestdist);
+		    bestmindist=Imin(dist,bestmindist);
+		    neigh->Next();
+		  }
+	      PXIntegerList* candidates=tstack2->getneighbours(corr[pt]);
+	      candidates->Rewind();
+	      for (int i=0;i<candidates->getnumnodes();i++)
+		  {
+		    int cand=candidates->getcurrent();
+		    neigh->Rewind();
+		    int maxd=0,mind=100000000;
+		    for (int j=0;j<neigh->getnumnodes();j++)
+			{
+			  int ind=neigh->getcurrent();
+			  int dist=tstack2->getrelationship(cand,corr[ind],100);
+			  if (dist<0)
+			      dist=101;
+			  maxd=Imax(maxd,dist);
+			  mind=Imin(mind,dist);
+			  neigh->Next();
+			}
+		    if (maxd<bestdist)
+			{
+			  bestdist=maxd;
+			  bestmindist=mind;
+			  bestcenter=cand;
+			}
+		    candidates->Next();
+		  }
+	      PXTriangulatedStackPoint* point1=tstack1->getpoint(pt);
+	      PXTriangulatedStackPoint* point2=tstack2->getpoint(bestcenter);
+	      if (bestcenter!=corr[pt])
+		  {
+		    corr[pt]=bestcenter;
+		    shift++;
+		  }
+	      for (int ia=0;ia<=2;ia++)
+		  disp[pt].x[ia]=point2->x[ia]-point1->x[ia];
+
+	    }
+
+	if (100*int(pt/100)==pt && pt>0 && debugmode)
+	    fprintf(stderr,"%d/%d (%d), ",pt,tstack1->getnumpoints(),shift);
+	if (600*int(pt/600)==pt && pt>0 && debugmode)
+	    fprintf(stderr,"\n");
+      }
+  if (debugmode)
+      fprintf(stderr,"   [ %d points shifted]\n",shift);
+
+  char line[100];
+  
+  if (smoothOutput>0 || saveno>0)
+      tstack1->deformUsingDisplacements(disp,1.0,smoothOutput);
+  if (saveno>0)
+      {
+	sprintf(line,"/tmp/deformed.%02d.iv",saveno);
+	tstack1->SaveInventor(line);
+      }
+  if (smoothOutput>0 || saveno>0)
+      tstack1->deformUsingDisplacements(disp,-1.0,0);
+  return shift;
+}
+// -----------------------------------------------------------------------
+// Find Smooth Map
+// -----------------------------------------------------------------------
+int PXTriangulatedStack::findSmoothMap(PXTriangulatedStack* tstack1,PXTriangulatedStack* tstack2,
+				       int* corr,PX3Vector* dx,int mode,int iterations,
+				       int curvmode,float lamda)
+
+{
+  //  debugmode=1;
+  int numiter=0;
+  int postmode=0;
+
+  if (mode==3)
+      {
+	mode=1;
+	postmode=1;
+      }
+  if (mode>3)
+      {
+	mode=2;
+	postmode=1;
+      }
+
+  if (debugmode)
+      {
+	fprintf(stderr," Find Smooth Map ::: \n");
+	switch(mode)
+	    {
+	    case 2:
+	      fprintf(stderr," Using global `connection-based' nearest neighbour initialization (post=%d)\n",postmode);
+	      
+	      break;
+	    case 1:
+	      fprintf(stderr," Using global `euclidean-based' nearest neighbour initialization (post=%d)\n",postmode);
+	      break;
+	    default:
+	      fprintf(stderr," Using nearest neighbour initialization \n");
+	      break;
+	}
+	if (curvmode==0)
+	    fprintf(stderr," Using Shape Tracking no smoothing\n");
+	if (curvmode>0)
+	    fprintf(stderr," Using Shape Tracking and smoothing\n");
+	if (curvmode<0)
+	    fprintf(stderr," No shape tracking\n");
+	
+      }
+
+  if (!tstack2->hascurvatures())
+      {
+	tstack2->generateNeighbours(1);
+	tstack2->nonShrinkSmooth(0.33,-0.34,50,2);
+	tstack2->generateNeighbours();
+      }
+  
+  // Part 1 Initialization
+  // ---------------------
+
+  if (mode==1 || mode ==2 )
+      {
+	if (debugmode)
+	    fprintf(stderr,"Generating Neighbours\n");
+	if (!tstack1->hasneighbours())
+	    tstack1->generateNeighbours();
+	if (!tstack2->hasneighbours())
+	    tstack2->generateNeighbours();
+
+	int inc=1;//tstack1->getnumpoints()/400+1;
+	PXNeighboursList* tetra=new PXNeighboursList();
+
+	if (debugmode)
+	    fprintf(stderr,"\nStarting Symmetric Neighbour Search inc=%d points=%d\n",
+		    inc,tstack1->getnumpoints());
+
+	for (int pt=0;pt<tstack1->getnumpoints();pt+=inc)
+	    {
+	      if (debugmode)
+		  {
+		    if (100*int(pt/100)==pt && pt>0)
+			fprintf(stderr,"%d/%d (%d)  ",pt,
+				tstack1->getnumpoints(),
+				tetra->getnumnodes());
+		    if (700*int(pt/700)==pt && pt>0)
+			fprintf(stderr,"\n");
+		  }
+	      findSymmetricPair(tstack1,tstack2,tetra,pt);
+	    }
+	if (debugmode)
+	    fprintf(stderr," done\n");
+      
+  
+	if (debugmode)
+	    {
+	      fprintf(stderr,"\n Stack1 (numpoints) = %d , Stack 2 (numpoints) =%d \n",
+		      tstack1->getnumpoints(),tstack2->getnumpoints());
+	      fprintf(stderr,"Number of matches = %d \n", tetra->getnumnodes());
+	      fprintf(stderr,"----------------------------------\n");
+	    }
+
+	tetra->Rewind();
+	int* used=new int[tstack1->getnumpoints()];
+	int* fixed=new int[tstack1->getnumpoints()];
+	
+	PX3Vector *dx0=new PX3Vector[tstack1->getnumpoints()];
+	
+	for (int j=0;j<tstack1->getnumpoints();j++)
+	    {
+	      corr[j]=-1; used[j]=0;	fixed[j]=0;
+	      for (int ia=0;ia<=2;ia++)
+		  {
+		    dx0[j].x[ia]=0.0;
+		    dx[j].x[ia]=0.0;  
+		  }
+	    }
+	
+	// Find displacement vectors
+	for (int i=0;i<tetra->getnumnodes();i++)
+	    {
+	      PXIntegerList* pair=(tetra->getcurrentnode())->points;
+	      pair->Rewind();	      
+	      int index1=pair->getcurrent();
+	      pair->Next();
+	      int index2=pair->getcurrent();
+	      //fprintf(stderr," Point 1 = %d , Point 2 =%d \n",index1,index2);
+	      PXTriangulatedStackPoint* point1=tstack1->getpoint(index1);
+	      PXTriangulatedStackPoint* point2=tstack2->getpoint(index2-tstack1->getnumpoints());
+
+	      for (int ia=0;ia<=2;ia++)
+		  dx0[index1].x[ia]=point2->x[ia]-point1->x[ia];
+
+	      used[index1]=1;	fixed[index1]=1;
+	      corr[index1]=index2-tstack1->getnumpoints();
+	      tetra->Next();
+	    }
+	
+	int numgood=tetra->getnumnodes();
+	delete tetra;
+	if (debugmode>1)
+	    {
+	      saveTstackPair("/tmp/iter.01.iv",tstack1,tstack2,dx,used,fixed);
+	      tstack1->SaveInventor("/tmp/deformed.01.iv");
+	    }
+
+	int id=-1;
+	int nmode=0;
+
+	for (int iter=1;iter<=iterations;iter++)
+	    {
+	      numiter=iter;
+	      if (debugmode)
+		  {
+		    fprintf(stderr,"\n----------------------\n");
+		    fprintf(stderr,"Smoothing iteration %d\n",iter);
+		    if (debugmode>1)
+			  id=iter+1;
+		  }
+	      
+	      if (mode==1)
+		  {
+		    numgood=smoothEuclidean(tstack1,tstack2,dx,dx0,used,fixed,corr,
+					    (numgood+1),id);
+		    
+		  }
+	      else
+		  {
+		    int mved=1;
+		    if (numgood<tstack1->getnumpoints())
+			{
+			  numgood=smoothEuclidean(tstack1,tstack2,dx,dx0,used,fixed,corr,
+						  numgood,id);
+			}
+		    else
+			{
+			  if (nmode==0)
+			      {
+				tstack1->generateNeighbours(1);
+				nmode=1;
+			      }
+			  if (debugmode)
+			      fprintf(stderr,"Smoothing Connection\n");
+			  mved=smoothConnection(tstack1,tstack2,dx,used,fixed,corr,
+						1,id);
+			  if (mved==0)
+			      iter=iterations+1;
+			}
+		  }
+	    }
+	
+	if (postmode)
+	    {
+	      tstack1->generateNeighbours(1);
+	      tstack1->deformUsingDisplacements(dx,1.0,0);
+	      PX3Vector* dp=tstack1->nonShrinkSmoothD(0.16,-0.165,35,2);
+	      if (debugmode>1)
+		  {
+		    char line[100];
+		    sprintf(line,"/tmp/deformed.%02d.iv",id+1);
+		    tstack1->SaveInventor(line);
+		  }
+	      tstack1->deformUsingDisplacements(dx,-1.0,0);
+	      float meandp[3],maxdp[3];
+	      for (int p=0;p<=2;p++)
+		  {
+		    meandp[p]=0.0;  maxdp[p]=0.0;
+		  }
+	      for (int i=0;i<tstack1->getnumpoints();i++)
+		  {
+		    for (int ia=0;ia<=2;ia++)
+			{
+			  dx[i].x[ia]+=dp[i].x[ia];
+			  meandp[ia]+=dp[i].x[ia]*float(1.0/tstack1->getnumpoints());
+			  maxdp[ia]=Fmax(maxdp[ia],dp[i].x[ia]);
+			}
+		  }
+	      
+	      if (debugmode)
+		  {
+		    fprintf(stderr,"Mean dp (%6.3f %6.3f %6.3f)\n",
+			    meandp[0],meandp[1],meandp[2]);
+		    fprintf(stderr,"Max dp (%6.3f %6.3f %6.3f)\n",
+			    maxdp[0],maxdp[1],maxdp[2]);
+		  }
+	      delete [] dp;
+	    }
+	delete [] used; delete [] fixed; delete [] dx0;
+      }
+  else
+      {
+	numiter=2;
+	for (int pt=0;pt<tstack1->getnumpoints();pt++)
+	    {
+	      PXTriangulatedStackPoint* point1=tstack1->getpoint(pt);
+	      float x[3];
+	      for (int ia=0;ia<=2;ia++)
+		  x[ia]=point1->x[ia];
+	      int mp;
+	      tstack2->findnearestpoint(x[0],x[1],x[2],mp,1,0.0);
+	      corr[pt]=mp;
+	      for (int ib=0;ib<=2;ib++)
+		  dx[pt].x[ib]=x[ib]-point1->x[ib];
+	    }
+	if (debugmode>1)
+	    {
+	      saveTstackPair("/tmp/iter.02.iv",tstack1,tstack2,dx);
+	      tstack1->deformUsingDisplacements(dx,1.0,0);
+	      tstack1->SaveInventor("/tmp/deformed.02.iv");
+	      tstack1->deformUsingDisplacements(dx,-1.0);
+	    }
+      }
+
+  // Part 2 Shape-Tracking if needed
+  // -------------------------------
+
+  if (debugmode)
+      fprintf(stderr,"Curvmode =%d\n",curvmode);
+
+  if (curvmode>=0)
+      {
+	int smoothiter=curvmode;
+	PXTriangulatedStack::curvatureTracking(tstack1,tstack2,dx,corr,lamda,smoothiter);
+	for (int i=0;i<tstack1->getnumpoints();i++)
+	    for (int ib=0;ib<=1;ib++)
+		(tstack1->getpoint(i))->k[ib]=(tstack2->getpoint(corr[i]))->k[ib];
+      }
+
+  return (numiter);
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::collectNeighbours(int point,int distance,PXIntegerList* list)
+{
+  int st=1;
+  if (!hasneighbourstructures)
+    st=generateNeighbours();
+  
+  if (st==0)
+    return 0;
+  
+  list->DeleteAll();
+  distance=Irange(distance,0,10);
+  point=Irange(point,0,numpoints-1);
+  
+
+  list->Add(point);
+  
+  if (distance==0)
+    return list->getnumnodes();
+
+  neighbours[point].Rewind();  
+  for (int i=0;i<neighbours[point].getnumnodes();i++)
+    {
+      list->Add(neighbours[point].getcurrent());
+      neighbours[point].Next();
+    }
+  
+  if (distance==1)
+    return list->getnumnodes();
+  
+  int begin=1;
+  for (int sc=2;sc<=distance;sc++)
+    {
+      list->Rewind();
+      int end  =list->getnumnodes();
+      // Skip over previously examined points 
+      int k;
+      for (k=0;k<begin;k++)
+	list->Next();
+      for (k=begin;k<end;k++)
+	{
+	  int pt=list->getcurrent();
+	  neighbours[pt].Rewind();
+	  for (int i=0;i<neighbours[pt].getnumnodes();i++)
+	    {
+	      list->AddNonDuplicate(neighbours[pt].getcurrent(),-1);
+	      neighbours[pt].Next();
+	    }
+	}
+      begin=end;
+    }
+  return list->getnumnodes();
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::\
+curvatureTracking(PXTriangulatedStack* tstack1,PXTriangulatedStack* tstack2,
+		  PX3Vector* disp,int* corr,float lamda,int smoothIterations)
+{
+  /*float radius=3.0;
+
+  if (debugmode)
+      fprintf(stderr,"Estimating scale for radius=%6.3f\n",radius);
+
+  // 1. Estimate Spacing and scale for radius
+  // ----------------------------------------
+  float x1[3],x2[3];
+  int p1=tstack1->getnumpoints()/2;
+  PXIntegerList* nlist=tstack1->getneighbours(p1);
+  nlist->Rewind();
+  int p2=nlist->getcurrent();
+
+  for (int ia=0;ia<=2;ia++)
+      {
+	x1[ia]=(tstack1->getpoint(p1))->x[ia];
+	x2[ia]=(tstack1->getpoint(p2))->x[ia];
+      }
+	
+  float dist=Fdist(x1[0],x1[1],x1[2],x2[0],x2[1],x2[2])+0.01;
+  int scale=Irange(int(radius/dist+0.5),1,10);*/
+  int scale=3;
+
+  if (debugmode)
+      fprintf(stderr,"\t Scale = %d\n",scale);
+
+  // 2. Estimate Initial Matching
+  // ----------------------------
+  if (debugmode)
+      fprintf(stderr,"\n Initial matching step \n");
+
+  PX3Vector* conf=new PX3Vector[tstack1->getnumpoints()];
+  PXIntegerList* searchPoints=new PXIntegerList();
+  float globalmindist=100000.0;
+  // Find Initial Match 
+  for (int pt1=0;pt1<tstack1->getnumpoints();pt1++)
+      {
+	PXTriangulatedStackPoint* point1=tstack1->getpoint(pt1);
+	float bend1=sqrt(point1->k[0]*point1->k[0]+point1->k[1]*point1->k[1]);
+	float minbend=100000.0,sumbend=0.0,sum2bend=0.0;
+	int pt2=corr[pt1];
+	int np2=tstack2->collectNeighbours(pt2,scale,searchPoints);
+	if (debugmode)
+	    {
+	      if (100*int(pt1/100)==pt1 && pt1>0)
+		  fprintf(stderr,"%d/%d (np=%d)",pt1,tstack1->getnumpoints(),np2);
+	      if (700*int(pt1/700)==pt1 && pt1>0)
+		  fprintf(stderr,"\n");
+	    }
+
+	int bestpt2=pt2;
+	for (int pass=0;pass<=1;pass++)
+	    {
+	      searchPoints->Rewind();
+	      for (pt2=0;pt2<np2;pt2++)
+		  {
+		    PXTriangulatedStackPoint* point2=tstack2->getpoint(searchPoints->getcurrent());
+		    float bend2=sqrt(point2->k[0]*point2->k[0]+point2->k[1]*point2->k[1]);
+		    float bendist=sqrt(pow(bend2-bend1,float(2.0)));
+		    if (pass==0)
+			{
+			  if (bendist<minbend)
+			      {
+				minbend=bendist;
+				bestpt2=searchPoints->getcurrent();
+			      }
+			  sumbend+=bendist;
+			}
+		    else
+			sum2bend+=pow(bendist-conf[pt1].x[0],float(2.0));
+		    searchPoints->Next();
+		  }
+	      if (pass==0)
+		  {
+		    conf[pt1].x[0]=minbend;
+		    globalmindist=Fmin(globalmindist,minbend);
+		    conf[pt1].x[1]=sumbend/(float(np2)+0.0001);
+		    for (int ia=0;ia<=2;ia++)
+			disp[pt1].x[ia]=tstack2->getpoint(bestpt2)->x[ia]-point1->x[ia];
+		  }
+	      else
+		  conf[pt1].x[2]=sum2bend/(float(np2)+0.0001);
+	    }
+      }
+
+  char line[50];
+  if (debugmode>1)
+      {
+	fprintf(stderr,"\n Min match dist = %6.3f",globalmindist);
+	tstack1->deformUsingDisplacements(disp,1.0,0); 
+	sprintf(line,"/tmp/defcurv.01.iv");
+	tstack1->SaveInventor(line);
+	tstack1->deformUsingDisplacements(disp,-1.0,0); 
+      }
+
+
+  delete searchPoints;
+
+  // 3. Calculate confidence measures
+  // --------------------------------
+
+  if (smoothIterations>0)
+      {
+	tstack1->generateNeighbours(); 
+
+	if (debugmode)
+	    fprintf(stderr,"\n Calculating Confidence Values\n");
+	
+	float K1 = 0.01 / (globalmindist+0.000001);
+	float K2 = 0.01 / (globalmindist+0.000001);	
+	float mind = 100.0;
+	int i;
+	for(i=0; i<tstack1->getnumpoints(); i++)
+	    mind=Fmin(mind,conf[i].x[2]/(conf[i].x[1]-conf[i].x[0]));
+	
+
+	for(i=0; i<tstack1->getnumpoints(); i++)
+	    {
+	      float denom=(conf[i].x[1]-conf[i].x[0]);
+	      float denom2=(1.0+K1*conf[i].x[0]);
+	      
+	      if (denom <0.0001)	    denom =0.0001;
+	      if (denom2<0.0001)	    denom2=0.0001;
+	      
+	      conf[i].x[0] =  (1.0/denom2)/(1.0 + (K2*conf[i].x[2])/denom);
+	    }
+	if (debugmode)
+	    fprintf(stderr,"Done with confidence values\n");
+      }
+  
+  // 4. Smooth Output
+  // ----------------
+  if (smoothIterations>0)
+      {
+	PX3Vector* temp=new PX3Vector[tstack1->getnumpoints()];
+	for (int iter=0;iter<smoothIterations;iter++)
+	    {
+	      int i;
+	      for (i=0;i<tstack1->getnumpoints();i++)
+		  for (int ia=0;ia<=2;ia++)
+		      temp[i].x[ia]=disp[i].x[ia];  
+	      
+	      if (debugmode)
+		  fprintf(stderr,"\n\n Smoothing Iteration %d \n",iter+1);
+
+	      for(i=0;i<tstack1->getnumpoints();i++)
+		  {
+		    if (debugmode)
+			{
+			  if (100*int(i/100)==i && i>0)
+			      fprintf(stderr,"%d/%d ",i,tstack1->getnumpoints());
+			  if (700*int(i/700)==i && i>0)
+			      fprintf(stderr,"\n");
+			}
+
+		    float oldx[3],newx[3];
+		    for (int ia=0;ia<=2;ia++)
+			{
+			  oldx[ia]=temp[i].x[ia];
+			  newx[ia]=temp[i].x[ia];
+			}
+		    float total=conf[i].x[0];
+		    
+		    PXIntegerList* nlist=tstack1->getneighbours(i);
+		    
+		    for(int j=0;j<nlist->getnumnodes();j++)
+			{
+			  int p=nlist->getcurrent();
+			  for (int ia=0;ia<=2;ia++)
+			      newx[ia]+=temp[p].x[ia]*conf[p].x[0];
+			  total+=conf[p].x[0];
+			  nlist->Next();
+			}
+		    
+		    for (int ib=0;ib<=2;ib++)
+			{
+			  newx[ib]=newx[ib]/total;
+			  disp[i].x[ib]=(1.0-lamda)*oldx[ib]+lamda*newx[ib];
+			}
+		  }
+		    
+	      // Mapping to Boundary Step
+	      // ------------------------
+	      float dist=0.0,maxshift=0.0,maxdist=0.0;
+	      if (debugmode)
+		  fprintf(stderr,"\n\n Mapping Iteration %d \n",iter+1);
+	      
+	      for (int pt=0;pt<tstack1->getnumpoints();pt++)
+		  {
+		    if (debugmode)
+			{
+			  if (100*int(pt/100)==pt && pt>0)
+			      fprintf(stderr,"%d/%d ",pt,tstack1->getnumpoints());
+			  if (700*int(pt/700)==pt && pt>0)
+			      fprintf(stderr,"\n");
+			}
+		    
+		    
+		    //PXTriangulatedStackPoint* point1=tstack1->getpoint(pt);
+		    float x[3];
+		    for (int ia=0;ia<=2;ia++)
+			x[ia]=tstack1->getpoint(pt)->x[ia]+disp[pt].x[ia]; 
+		    int mp;
+		    float d=tstack2->findnearestpoint(x[0],x[1],x[2],mp,1,0.001);
+		    dist+=d;
+		    for (int ib=0;ib<=2;ib++)
+			{
+			  x[ib]=x[ib]-tstack1->getpoint(pt)->x[ib]; 
+			  disp[pt].x[ib]=x[ib];
+			}
+		    
+		    maxdist=Fmax(maxdist,d);
+		    maxshift=Fmax(maxshift,Fsqdist( x[0],x[1],x[2],0.0,0.0,0.0));
+		    corr[pt]=mp;
+		  }
+
+	      if (debugmode>1)
+		  {
+		    tstack1->deformUsingDisplacements(disp,1.0,0); 
+		    sprintf(line,"/tmp/defcurv.%02d.iv",iter+2);
+		    tstack1->SaveInventor(line);
+		    tstack1->deformUsingDisplacements(disp,-1.0,0); 
+		  }
+	    }
+	delete [] temp;
+      }
+
+  if (debugmode)
+      fprintf(stderr,"\nDone\n");
+	
+  delete [] conf;
+  return 1;
+	
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::loadPengChengDisplacementsSingle(const char* filename,
+							  PX3Vector* dx,
+							  float tolerance)
+{
+  if (debugmode)
+	fprintf(stderr,"Reading Peng-Cheng Displacements from %s\n",filename);
+
+  FILE* dispfile=fopen(filename,"r");
+  
+  if (dispfile==NULL)
+      {
+	fclose(dispfile);
+	return 0;
+      }
+  
+  char line[200];
+  float *pointsx,*pointsy,*pointsz;
+  // Count Lines in file
+  // -------------------
+  int numdispframes=2;
+  int numdisppoints=0;
+  
+  while ( fgets(line,100,dispfile)!=NULL )    
+      numdisppoints++;
+  fclose(dispfile);
+  dispfile=fopen(filename,"r");
+  if (debugmode)
+	fprintf(stderr,"Number of points in %s = %d\n",filename,numdisppoints);
+
+  
+  // Allocate Data and Read Rest of Files 
+  // ------------------------------------
+  pointsx=new float[numdisppoints*numdispframes];
+  pointsy=new float[numdisppoints*numdispframes];
+  pointsz=new float[numdisppoints*numdispframes];
+  int i;
+  for ( i=0;i<numdisppoints;i++)
+      {
+	for (int j=0;j<numdispframes;j++)
+	    {
+	      int index=i*numdispframes+j;
+	      fscanf(dispfile,"%f %f %f ",
+		     &pointsx[index],
+		     &pointsy[index],
+		     &pointsz[index]);
+	    }
+      }
+  
+  if (debugmode)
+      fprintf(stderr,"\tFrames=%d, Points=%d\n",numdispframes,numdisppoints);
+  fclose(dispfile);
+  
+  // Create Structures for Solid to find and store displacements
+  // -----------------------------------------------------------
+  
+  int numd=0,numtest=0;
+  tolerance*=tolerance;
+  
+  for (i=0;i<getnumpoints();i++)
+      {
+	numtest++;
+	int pt=0,found=0;
+	int bestpt=0;
+	float mindist=10000.0;
+	while(pt<numdisppoints && found==0)
+	    {
+	      int po_index=pt*numdispframes;
+	      float x=pointsx[po_index];
+	      float y=pointsy[po_index];
+	      float z=pointsz[po_index];
+	      float dist=Fsqdist(x,y,z,point[i].x[0],point[i].x[1],point[i].x[2]);
+	      if (dist<mindist)
+		  {
+		    mindist=dist;
+		    bestpt=pt;
+		  }
+	      
+	      if (mindist<tolerance)
+		  found=1;
+	      else
+		  pt++;
+	      
+	    }
+	int po_index=bestpt*numdispframes;			
+	numd++;
+	dx[i].x[0]=pointsx[po_index+1]-pointsx[po_index];
+	dx[i].x[1]=pointsy[po_index+1]-pointsy[po_index];
+	dx[i].x[2]=pointsz[po_index+1]-pointsz[po_index];
+
+	if (i==10 || i==200 && debugmode)
+	    {
+	      fprintf(stderr,"Original Node %d \n (%6.3f %6.3f %6.3f ) \n",i,
+		      point[i].x[0],point[i].x[1],point[i].x[2]);
+	      fprintf(stderr,"Closest Point %d \n (%6.3f %6.3f %6.3f ) \n",bestpt,
+		      pointsx[po_index],
+		      pointsy[po_index],
+		      pointsz[po_index]);
+	      fprintf(stderr,"Goes to %d \n (%6.3f %6.3f %6.3f ) \n",bestpt,
+		      pointsx[po_index+1],
+		      pointsy[po_index+1],
+		      pointsz[po_index+1]);
+	      fprintf(stderr,"Displacement = (%5.3f %5.3f %5.3f)\n",
+		      dx[i].x[0],dx[i].x[1],dx[i].x[2]);
+	    }
+      }
+
+  if (debugmode)
+	fprintf(stderr,"\tDone with surface, found %d displacements (%d)\n",numd,numtest);
+ 
+  delete [] pointsx;
+  delete [] pointsy;
+  delete [] pointsz;
+  return numd;
+}
+
+// ------------------------------------------------------------------------
+void setnode12(int* node1,int* node2,int index,int& current,int max)
+{
+  if (index<0 || index>=max || current<0 || current>=max)
+      {
+	fprintf(stderr,"************************** Error in node12");
+	exit(0);
+	// Error Message
+      }
+  else
+      {	
+	node2[current]=index;
+	node1[index]=current;
+	++current;
+      }
+}
+// ------------------------------------------------------------------------
+int PXTriangulatedStack::subdivide() // Stupid Algorithm -- but it works!!
+{
+  //  debugmode=1;
+
+  if (debugmode)
+    fprintf(stderr,"Subviding numpoints=%d\n",numpoints);
+  
+  if (!haspoints() || !hastriangles())
+    {
+      if (debugmode)
+	fprintf(stderr,"Cannot subdivide neighbours as points=%d , triangles=%d\n",
+		haspoints(),hastriangles());
+      return 0;
+    }
+  
+  generateNeighbours(0);
+  
+  // ---------------------------------------------------------------------
+  //  Preliminary Stuff --- add neighbours
+  // ---------------------------------------------------------------------
+  PXIntegerList* midpoint=new PXIntegerList[numpoints];     // OK
+  PXIntegerList* oldpoint=new PXIntegerList[numpoints];     // OK
+  PXIntegerList* newpoint1=new PXIntegerList();             // OK
+  PXIntegerList* newpoint2=new PXIntegerList();             // OK
+  
+  int tr;
+  int newpoint=numpoints;
+  
+  if (debugmode)
+    fprintf(stderr,"Step 1: find mid points \n");
+  
+  for (int pt=0;pt<numpoints;pt++)
+    {
+      if (debugmode)
+	if (100*int(pt/100)==pt)
+	  fprintf(stderr,"%d/%d ",pt,numpoints);
+      
+      neighbours[pt].Rewind();
+      for (int i=0;i<neighbours[pt].getnumnodes();i++)
+	{
+	  int pt2=neighbours[pt].getcurrent();
+	  neighbours[pt].Next();
+	  
+	  if (pt<pt2)
+	    {
+	      oldpoint[pt].Add(pt2);
+	      midpoint[pt].Add(newpoint);
+	      newpoint1->Add(pt);
+	      newpoint2->Add(pt2);
+	      newpoint++;
+	    }
+	}
+    }
+
+  if (debugmode)
+    fprintf(stderr,"\n Done --> New Points = %d \n",newpoint);
+
+  if (debugmode)
+    fprintf(stderr,"Step 2: Generate New Stack (Points)\n");
+
+  PXTriangulatedStack* old=new PXTriangulatedStack(this); //OK 
+  
+  // Save Stack Index 
+  PXStackIndex oldstackindex;
+  int hadstackindex=0;
+  if (hasstackindex())
+      {
+	hadstackindex=1;
+	oldstackindex.numcontours=stackIndex.numcontours;
+	oldstackindex.index=new int[stackIndex.numcontours+1]; // OK
+	oldstackindex.zlevel=new float[stackIndex.numcontours]; // OK
+	for (int i=0;i<=stackIndex.numcontours;i++)
+	  oldstackindex.index[i]=stackIndex.index[i];
+	for (int j=0;j<stackIndex.numcontours;j++)
+	  oldstackindex.zlevel[j]=stackIndex.zlevel[j];
+      }
+  
+  cleanup();
+
+  init(newpoint,old->getnumtriangles()*4);
+  
+  // First generate the points
+  newpoint1->Rewind();
+  newpoint2->Rewind();
+
+  for (int newpt=0;newpt<numpoints;newpt++)
+    {
+      if (newpt<old->getnumpoints())
+	{
+	  PXTriangulatedStackPoint* other=old->getpoint(newpt);
+	  point[newpt].index=other->index;
+	  for (int ia=0;ia<=2;ia++)
+	    {
+	      point[newpt].x[ia]=other->x[ia];
+	      point[newpt].nx[ia]=other->nx[ia];
+	    }
+	  for (int ib=0;ib<=1;ib++)
+	    point[newpt].k[ib]=other->k[ib];
+	}
+      else
+	{
+	  point[newpt].index=newpt;
+	  int base1=newpoint1->getcurrent();
+	  int base2=newpoint2->getcurrent();
+	  
+	  newpoint1->Next();
+	  newpoint2->Next();
+	  for (int ia=0;ia<=2;ia++)
+	    {
+	      point[newpt].x[ia]=0.5*(point[base1].x[ia]+point[base2].x[ia]);
+	      point[newpt].nx[ia]=0.5*(point[base1].nx[ia]+point[base2].nx[ia]);
+	    }
+	  
+	  point[newpt].k[0]=0.5*(point[base1].k[0]+point[base2].k[0]);
+	  point[newpt].k[1]=0.5*(point[base1].k[1]+point[base2].k[1]);
+
+
+	}
+      normalsok=old->hasnormals();
+      curvaturesok=old->hascurvatures();
+    }
+  delete newpoint1;
+  delete newpoint2;
+  
+  if (debugmode)
+    fprintf(stderr,"Step 3: Generate New Stack (Triangles)\n");
+  
+  for (tr=0;tr<old->getnumtriangles();tr++)
+    {
+      PXTriangle* other=old->gettriangle(tr);
+      int midpt[3];
+      for (int ia=0;ia<=2;ia++)
+	{
+	  int ib=Icyclic(ia+1,3);
+	  int p1=other->p[ia];
+	  int p2=other->p[ib];
+	  int test=Imin(p1,p2);
+	  int target=Imax(p1,p2);
+	  for (int k=0;k<oldpoint[test].getnumnodes();k++)
+	    {
+	      int t1=oldpoint[test].getcurrent();
+	      int t2=midpoint[test].getcurrent();
+	      
+	      if (target==t1)
+		{
+		  k=oldpoint[test].getnumnodes()+1;
+		  midpt[ia]=t2;
+		}
+	      midpoint[test].Next();
+	      oldpoint[test].Next();
+	    }
+	}
+      
+      for (int tr1=0;tr1<4;tr1++)
+	{
+	  int trno=tr*4+tr1;
+	  switch(tr1)
+	    {
+	    case 0:
+	      triangle[trno].p[0]=other->p[0];
+	      triangle[trno].p[1]=midpt[0];
+	      triangle[trno].p[2]=midpt[2];
+	      break;
+	    case 1:
+	      triangle[trno].p[0]=other->p[1];
+	      triangle[trno].p[1]=midpt[1];
+	      triangle[trno].p[2]=midpt[0];
+	      break;
+	    case 2:
+	      triangle[trno].p[0]=other->p[2];
+	      triangle[trno].p[1]=midpt[2];
+	      triangle[trno].p[2]=midpt[1];
+	      break;
+	    case 3:
+	      triangle[trno].p[0]=midpt[0];
+	      triangle[trno].p[1]=midpt[1];
+	      triangle[trno].p[2]=midpt[2];
+	      break;
+	    }
+	}
+    }
+  
+  delete old;
+
+  //this->Save("unsorted.tstack");
+
+  if (hadstackindex==1)
+      {
+	if (debugmode)
+	    fprintf(stderr,"Step 4: Sort to generate new Stackindex\n");
+
+	int* node1=new int[numpoints]; // OK
+	int* node2=new int[numpoints]; // OK 
+
+	for (int i=0;i<numpoints;i++)
+	    {
+	      node1[i]=-1; node2[i]=-2;
+	    }
+	stackindexok=1;
+	stackIndex.numcontours=1+2*(oldstackindex.numcontours-1);
+	stackIndex.index=new int[stackIndex.numcontours+1];
+	stackIndex.zlevel=new float[stackIndex.numcontours];
+	PXIntegerList* addList=new PXIntegerList(); // OK
+	stackIndex.index[0]=0;
+	int ind=0,current=0;
+
+	for (int base=0;base<oldstackindex.numcontours;base++)
+	    { 
+	      if (debugmode)
+		fprintf(stderr,"Base =%d\n",base);
+	      for (int pt=oldstackindex.index[base];pt<oldstackindex.index[base+1];pt++)
+		{
+		  //fprintf(stderr, "%d ",pt);
+		  setnode12(node1,node2,pt,current,numpoints);
+		  oldpoint[pt].Rewind();
+		  midpoint[pt].Rewind();
+		  for (int k=0;k<oldpoint[pt].getnumnodes();k++)
+		    {
+		      int pt2=oldpoint[pt].getcurrent();
+		      if (pt2<oldstackindex.index[base+1])
+			setnode12(node1,node2,midpoint[pt].getcurrent(),current,numpoints);
+		      oldpoint[pt].Next();
+		      midpoint[pt].Next();
+		    }
+		}
+	      //	      fprintf(stderr,"\n");
+	      stackIndex.index[ind+1]=current;
+	      stackIndex.zlevel[ind]=oldstackindex.zlevel[base];
+	      ind++;
+
+	      if (base!=oldstackindex.numcontours-1)
+		  {
+		    addList->DeleteAll();
+
+		    for (int pt=oldstackindex.index[base];pt<oldstackindex.index[base+1];pt++)
+			{
+			  //fprintf(stderr, "%d ",pt);
+			  oldpoint[pt].Rewind();
+			  midpoint[pt].Rewind();
+			  for (int k=0;k<oldpoint[pt].getnumnodes();k++)
+			    {
+			      int pt2=oldpoint[pt].getcurrent();
+			      if (pt2>=oldstackindex.index[base+1])
+				addList->AddNonDuplicate(midpoint[pt].getcurrent(),-1);
+			      oldpoint[pt].Next();
+			      midpoint[pt].Next();
+			    }
+			}
+		    //		    fprintf(stderr,"\n");
+		    addList->Rewind();
+		    for (int k=0;k<addList->getnumnodes();k++)
+		      {
+			setnode12(node1,node2,addList->getcurrent(),current,numpoints);
+			addList->Next();
+		      }
+		    stackIndex.index[ind+1]=current;
+		    stackIndex.zlevel[ind]=0.5*(oldstackindex.zlevel[base]+oldstackindex.zlevel[base+1]);
+		    ind++;
+		  }
+	    }
+
+	//stackIndex.index[stackIndex.numcontours]=numpoints;
+	// So all noded reindexed in node2 
+	// Re-index triangles first 
+	for (int tr=0;tr<numtriangles;tr++)
+	    for (int tp=0;tp<=2;tp++)
+		triangle[tr].p[tp]=node1[triangle[tr].p[tp]];
+	// Move points around also 
+	PXTriangulatedStackPoint* oldpoint=new PXTriangulatedStackPoint[numpoints]; // OK
+	int pt;
+	for (pt=0;pt<numpoints;pt++)
+	    {
+	      for (int ia=0;ia<=2;ia++)
+		{
+		  oldpoint[pt].x[ia]=point[pt].x[ia];
+		  oldpoint[pt].nx[ia]=point[pt].nx[ia];
+		}
+	      for (int ib=0;ib<=1;ib++)
+		oldpoint[pt].k[ib]=point[pt].k[ib];
+	    }
+	
+	for (pt=0;pt<numpoints;pt++)
+	    {
+	      point[pt].index=pt;
+	      for (int ia=0;ia<=2;ia++)
+		{
+		  point[pt].x[ia]=oldpoint[node2[pt]].x[ia];
+		  point[pt].nx[ia]=oldpoint[node2[pt]].nx[ia];
+		}
+	      for (int ib=0;ib<=1;ib++)
+		point[pt].k[ib]=oldpoint[node2[pt]].k[ib];
+	    }
+	
+	/*if (debugmode)
+	  {
+	    FILE* fout=fopen("indices.txt","w");
+	    for (int i=0;i<numpoints;i++)
+	      fprintf(fout,"%d \t %d \t %d\n",i,node1[i],node2[i]);
+	    fclose(fout);
+	    }*/
+
+
+	delete [] node1; delete [] node2;  
+	delete [] oldpoint; 
+	delete addList;     
+	delete [] oldstackindex.index; 
+	delete [] oldstackindex.zlevel;
+      }
+  else
+      {
+	stackindexok=1;
+	stackIndex.numcontours=2;
+	stackIndex.index=new int[stackIndex.numcontours+1];
+	stackIndex.zlevel=new float[stackIndex.numcontours];
+	stackIndex.index[0]=0;
+	stackIndex.index[1]=0;
+	stackIndex.index[2]=numpoints;
+	stackIndex.zlevel[0]=0.0;
+	stackIndex.zlevel[0]=1.0;
+      }
+  delete [] midpoint;
+  delete [] oldpoint;
+
+  //  Save("subdivide.tstak");
+  //  delete [] belongtoTri;
+  //  SaveInventor("sub.iv");
+  return 1;
+}
+// ---------------------------------------------------------------------
+// Generate Solid -- these are static
+// ----------------------------------
+// --------------------------------------------------------------------------
+int PXTriangulatedStack::save2qhull(const char* fname,PXTriangulatedStack** stack,int numstacks)
+{
+  FILE* fout=fopen(fname,"w");
+  if (fout)
+      {
+	fprintf(fout,"3\n");
+	int total=0;
+	for (int i=0;i<numstacks;i++)
+	    total+=stack[i]->getnumpoints();
+	fprintf(fout,"%d\n",total);
+	for (int j=0;j<numstacks;j++)
+	    for (int i=0;i<stack[j]->getnumpoints();i++)
+		fprintf(fout,"%6.3f %6.3f %6.3f\n",(stack[j]->getpoint(i))->x[0],
+			(stack[j]->getpoint(i))->x[1],(stack[j]->getpoint(i))->x[2]);
+	fclose(fout);
+	return 1;
+      }
+  return 0;
+}
+// --------------------------------------------------------------------------
+int PXTriangulatedStack::loadqhull(const char* fname, PXTriangulatedStack** stack,int numstacks,
+					PXNeighboursList* tetra,int& nt)
+{
+  char line[200];
+  int i;
+  for (i=0;i<numstacks;i++)
+      if (!stack[i]->hasneighbours())
+	  stack[i]->generateNeighbours();
+  FILE* fin=fopen(fname,"r");
+  if (!fin)
+      return 0;
+
+  int total=0;
+  for (i=0;i<numstacks;i++)
+      total+=stack[i]->getnumpoints();
+  
+  fgets(line,200,fin);
+  int np,temp;
+  fscanf(fin,"%d %d %d\n",&np,&nt,&temp);
+  if (debugmode)
+	fprintf(stderr,"Reading %s points=%d, tetra=%d\n",fname,np,nt);
+  if (np!=(total))
+      {
+	  if (debugmode)
+		fprintf(stderr,"Error, some points missing\n");
+	fclose(fin);
+	return (0);
+      }
+  
+  float x1,y1,z1,t1;
+  // Check Stack1 First, Then Stack2
+  for (int j=0;j<numstacks;j++)
+      for (int i=0;i<stack[j]->getnumpoints();i++)
+	  {
+	    fscanf(fin,"%f %f %f %f\n",&x1,&y1,&z1,&t1);
+	    if (!Fsamepoint((stack[j]->getpoint(i))->x[0],
+			    (stack[j]->getpoint(i))->x[1],
+			    (stack[j]->getpoint(i))->x[2],
+			    x1,y1,z1,0.05))
+		{
+		 if (debugmode)
+		  fprintf(stderr,"Points not matching\n");
+		  exit(1);
+		}
+	  }
+  
+  PXIntegerList* intList=new PXIntegerList();
+  for (i=0;i<nt;i++)
+      {
+	int points;
+	fscanf(fin,"%d",&points);
+	if (points==4)
+	    {
+	      intList->DeleteAll();
+	      int temp;
+	      for (int j=0;j<points;j++)
+		  {
+		    fscanf(fin,"%d",&temp);
+		    intList->Add(temp);
+		  }
+	      tetra->Add(intList,i);
+	    }
+	else
+	    {
+	      fgets(line,200,fin); // Bad triangle !!
+	      if (debugmode)
+		fprintf(stderr,"Error %d %s\n",points,line);
+	    }
+      }
+  nt=tetra->getnumnodes();
+  delete intList;
+  fclose(fin);
+  if (debugmode)
+	fprintf(stderr,"Done Reading\n");
+  return (1);
+
+}
+// --------------------------------------------------------------------------
+
+int PXTriangulatedStack::whichstack(int index,int* total,int numstacks)
+{
+  int done=0,i=0;
+  while (done==0 && i<numstacks)
+      {
+	if (index>=total[i] && index<total[i+1])
+	    done=1;
+	else
+	    i++;
+      }
+  if (done==0)
+      return numstacks-1;
+  else
+      return i;
+}
+// --------------------------------------------------------------------------
+
+int PXTriangulatedStack::cleanup(PXTriangulatedStack* tstack[],int numstacks,
+				      PXNeighboursList* tetra,int nt)
+{
+  int count=0,count1=0,count2=0,count3=0,tr=0,count4=0;
+  if (debugmode)
+      fprintf(stderr,"Checking Tetrahedra 1 : Planar\n\t");
+
+  int* total=new int[numstacks+1];
+  total[0]=0;
+  for (int i=0;i<numstacks;i++)
+      total[i+1]=total[i]+tstack[i]->getnumpoints();
+
+  /*for (i=0;i<total[numstacks];i+=25)
+      fprintf(stderr," i=%d, stack=%d \n",i,whichstack(i,total,numstacks));*/
+
+  if (debugmode)
+      fprintf(stderr,"Phase 1: Volume Check\n");
+  tetra->Rewind();
+  for ( tr=0;tr<nt;tr++)
+      {
+	float x[4],y[4],z[4];
+	if (100*int(tr/100)==tr && debugmode)
+	    fprintf(stderr," %d/%d",tr,nt);
+	
+	if (tetra->getcurrentindex()>0)
+	    {
+	      PXIntegerList* intList=((tetra->getcurrentnode())->points);
+	      intList->Rewind();
+	      int i;
+	      for (i=0;i<=3;i++)
+		  {
+		    int index=intList->getcurrent();
+		    intList->Next();
+		    int st=whichstack(index,total,numstacks);
+		    index=index-total[st];
+		    x[i]=(tstack[st]->getpoint(index))->x[0];
+		    y[i]=(tstack[st]->getpoint(index))->x[1];
+		    z[i]=(tstack[st]->getpoint(index))->x[2];
+		  }
+	      // Make point 0 the origin 
+	      for (i=1;i<=3;i++)
+		  {
+		    x[i]=x[i]-x[0]; y[i]=y[i]-y[0]; z[i]=z[i]-z[0];
+		  }
+	      
+	      float nx=(y[2]*z[1]-z[2]*y[1]);
+	      float ny=(z[2]*x[1]-x[2]*z[1]);
+	      float nz=(x[2]*y[1]-y[2]*x[1]);
+	      float vol=fabs(x[3]*nx+y[3]*ny+z[3]*nz);
+	      
+	      if (vol<=0.5)
+		  {
+		    (tetra->getcurrentnode())->index=-1;
+		    count1++;
+		    count++;
+		  }
+	    }
+	tetra->Next();
+      }
+  
+  if (debugmode)
+      fprintf(stderr,"\n\tDone Planar Rejected=%d\nChecking Tetrahedra 2: Surface Connectivity \n\t",count);
+  tetra->Rewind();
+
+  int sum[5];
+  sum[0]=0; sum[1]=0; sum[2]=0; sum[3]=0;
+  for ( tr=0;tr<nt;tr++)
+      {
+	if (100*int(tr/100)==tr && debugmode)
+	    fprintf(stderr," %d/%d",tr,nt);
+	if(tetra->getcurrentindex()>=0) // Otherwise already not valid 
+	    {
+	      PXIntegerList* intList=(tetra->getcurrentnode())->points;
+	      intList->Rewind();
+	      int ind[4],whst=0;
+	      for (int pt=0;pt<4;pt++)
+		  {
+		    ind[pt]=intList->getcurrent();
+		    whst+=whichstack(ind[pt],total,numstacks);
+		    intList->Next();
+		  }
+	      if (whst==0 || whst==(numstacks-1)*4)
+		  {
+		    int st=0;
+		    if (whst==0)
+			{
+			  st=0;
+			}
+		    else 
+			{
+			  st=numstacks-1;
+			  for (int j=0;j<4;j++)
+			      ind[j]-=total[numstacks-1];
+			}
+		    
+		    // Step One determine relationships <2
+		    int conn1=0,conn2=0;
+		    for (int k1=0;k1<=2;k1++)
+			for (int k2=k1+1;k2<=3;k2++)
+			    {
+			      int dist=tstack[st]->getrelationship(ind[k1],ind[k2],3);
+			      if (dist<=2)
+				  conn2++;
+			      if (dist<=1)
+				  conn1++;
+			    }
+
+		    if ((conn2+conn1)<3 || (conn1<2))
+			{
+			  (tetra->getcurrentnode())->index=-1;
+			  count++;
+			  count2++;
+			}
+		    else
+			{
+			  int suminside=0,sumoutside=0;
+			  float xm=0.0,ym=0.0,zm=0.0;
+			  int i;
+			  for (i=0;i<=3;i++)
+			      {
+				xm+=(tstack[st]->getpoint(ind[i]))->x[0];
+				ym+=(tstack[st]->getpoint(ind[i]))->x[1];
+				zm+=(tstack[st]->getpoint(ind[i]))->x[2];
+			      }
+			  xm/=4.0; ym/=4.0; zm/=4.0;
+			  
+			  for ( i=0;i<4;i++)
+			      {
+				float xp=(tstack[st]->getpoint(ind[i]))->x[0];
+				float yp=(tstack[st]->getpoint(ind[i]))->x[1];
+				float zp=(tstack[st]->getpoint(ind[i]))->x[2];
+				
+				float nx=(tstack[st]->getpoint(ind[i]))->nx[0];
+				float ny=(tstack[st]->getpoint(ind[i]))->nx[1];
+				float nz=(tstack[st]->getpoint(ind[i]))->nx[2];
+				float dt=(nx*(xp-xm)+ny*(yp-ym)+nz*(zp-zm));
+				
+				
+				if (st==0)
+				    dt=-dt;
+				//fprintf(stderr,"dt = %7.4f ",dt);
+				if (dt<0.01)
+				    suminside++;
+				else
+				    sumoutside++;
+			      }
+			  if (suminside<4)
+			      sum[suminside]++;
+			  if (suminside>0)
+			      {
+				(tetra->getcurrentnode())->index=-1;
+				count++;
+				count3++;
+			      }
+			  else
+			      {
+				count4++;
+			      }
+			}
+		  }
+	    }
+	tetra->Next();
+      }
+  if (debugmode)
+      {
+	fprintf(stderr,"\n\tDone Surface Connectivity Rejected=%d (connec=%d) (normal=%d(%d)) (vol=%d)\n",count,count2,count3,count4,count1);
+	
+	PXTriangulatedStack::save2inventor("part.01.iv",tstack,numstacks,tetra,nt);
+      }
+  /*
+  tetra->Rewind();
+  fprintf(stderr,"Peng-Cheng Ultimate Test\n");
+  int count5=0;
+  PXContourStack* cst1=tstack[0]->exporttocontourstack();
+  cst1->Equispace(1.0);
+  PXContourStack* cst2=tstack[numstacks-1]->exporttocontourstack();
+  cst2->Equispace(1.0);
+
+  for ( tr=0;tr<nt;tr++)
+      {
+	if (100*int(tr/100)==tr)
+	    fprintf(stderr," %d/%d",tr,nt);
+	if(tetra->getcurrentindex()>=0) // Otherwise already not valid 
+	    {
+	      float x=0.0,y=0.0,z=0.0;
+	      PXIntegerList* intList=(tetra->getcurrentnode())->points;
+	      intList->Rewind();
+	      for (int i=0;i<=3;i++)
+		  {
+		    int index=intList->getcurrent();
+		    intList->Next();
+		    int st=whichstack(index,total,numstacks);
+		    index=index-total[st];
+		    x+=0.25*(tstack[st]->getpoint(index))->x[0];
+		    y+=0.25*(tstack[st]->getpoint(index))->x[1];
+		    z+=0.25*(tstack[st]->getpoint(index))->x[2];
+		  }
+	      
+	      int le=0,found=0;
+	      while (found==0 && le<cst2->getnumcontours()-1)
+		  {
+		    if (z<cst2->getzlevel(le))
+			found=1;
+		    else
+			le++;
+		  }
+	      le=Irange(le,0,cst2->getnumcontours()-2);
+	      
+	      if (fabs(z-cst2->getzlevel(le+1))<fabs(z-cst2->getzlevel(le)))
+		  le++;
+	      
+	      PXContour* cntr1=cst1->getcontour(le);
+	      PXContour* cntr2=cst2->getcontour(le);
+	      
+	      if (cntr2->IsInside(x,y) && !cntr1->IsInside(x,y))
+		  {
+		    //
+		  }
+	      else
+		  {
+		    (tetra->getcurrentnode())->index=-1;
+		    count++;
+		    count5++;
+		  }
+	      tetra->Next();
+	    }
+      }
+  delete cst1;
+  delete cst2;
+  PXTriangulatedStack::save2inventor("part.02.iv",tstack,numstacks,tetra,nt);
+  fprintf(stderr,"\n\tDone Ult test Rejected=%d (connec=%d) (normal=%d(%d)) (vol=%d) ultra=%d\n",count,
+	  count2,count3,count4,count1,count5);
+	  */
+  return tetra->getnumnodes()-count;
+}
+// --------------------------------------------------------------------------
+int PXTriangulatedStack::save2inventor(const char *fname,PXTriangulatedStack** tstack,int numstacks,
+				       PXNeighboursList* tetra,int nt)
+{
+  FILE *fout=fopen(fname,"w");
+  if (!fout)
+      return 0;
+
+  int st=PXTriangulatedStack::save2inventor(fout,tstack,numstacks,tetra,nt);
+  if (st && debugmode)
+      fprintf(stderr,"\n\nSaving in %s \n",fname);
+  fclose(fout);
+  return st;
+}
+// --------------------------------------------------------------------------
+int PXTriangulatedStack::save2inventor(FILE* fout,PXTriangulatedStack** tstack,int numstacks,
+					    PXNeighboursList* tetra,int nt)
+{
+  int* total=new int[numstacks];
+  total[0]=0;
+  int i;
+  for (i=0;i<numstacks;i++)
+      total[i+1]=total[i]+tstack[i]->getnumpoints();
+  
+  fprintf(fout,"#Inventor V2.0 ascii\nSeparator {\n");
+  fprintf(fout,"ShapeHints {\n vertexOrdering  COUNTERCLOCKWISE\n  faceType CONVEX\n }\n\n");
+  fprintf(fout,"# %d Points,%d Triangles\n\n",total[numstacks],nt);
+  fprintf(fout,"# Hello\n");
+  fprintf(fout,"Coordinate3{ point[\n");
+  for (int j=0;j<numstacks;j++)
+      for (int i=0;i<tstack[j]->getnumpoints();i++)
+	  fprintf(fout,"%6.3f %6.3f %6.3f,\n",
+		  (tstack[j]->getpoint(i))->x[0]*1.0,
+		  (tstack[j]->getpoint(i))->x[1]*1.0,
+		  (tstack[j]->getpoint(i))->x[2]);
+  
+  fprintf(fout,"]}\n");
+  int valid=0;
+  
+  for (int pass=0;pass<numstacks-1;pass++)
+      {
+	
+	fprintf(fout,"Material {  diffuseColor    %4.2f %4.2f 0.0 \n}\n",
+		1.0-float(pass)/float(numstacks-1),
+		float(pass)/float(numstacks));
+
+	fprintf(fout,"IndexedFaceSet{ coordIndex[\n");
+	tetra->Rewind();
+	for (i=0;i<nt;i++)
+	    {
+	      if (tetra->getcurrentindex()>=0)
+		  {
+		    int num=0;
+		    PXIntegerList* intList=(tetra->getcurrentnode())->points;
+		    intList->Rewind();
+		    int index[4];
+		    for (int pt=0;pt<4;pt++)
+			{
+			  index[pt]=intList->getcurrent();
+			  num+=whichstack(index[pt],total,numstacks);
+			  intList->Next();
+			}
+		    if (pass==num/4)
+			{
+			  valid++;
+			  fprintf(fout,"%d,%d,%d,-1,\n",index[0],index[1],index[2]);
+			  fprintf(fout,"%d,%d,%d,-1,\n",index[1],index[2],index[3]);
+			  fprintf(fout,"%d,%d,%d,-1,\n",index[0],index[1],index[3]);
+			  fprintf(fout,"%d,%d,%d,-1,\n",index[0],index[2],index[3]);
+			}
+		  }
+	      tetra->Next();
+	    }
+	fprintf(fout,"]}\n");
+      }
+  fprintf(fout,"}\n");
+  fprintf(fout,"# Valid tetrahedra %d\n",valid);
+  fprintf(fout,"DrawStyle {	style LINES	}\n");
+  fprintf(fout,"Material {  diffuseColor 0.2 0.2 0.2 \n transparency 0.0}\n" );
+  tstack[0]->SaveInventor(fout);
+  fprintf(fout,"Material {  diffuseColor 0.0 0.0 1.0 \n transparency 0.0}\n" );
+  tstack[numstacks-1]->SaveInventor(fout);
+  //fclose(fout);
+  return 1;
+
+}
+// --------------------------------------------------------------------------
+int* PXTriangulatedStack::gettotal(PXTriangulatedStack** stack,int numstacks)
+{
+  int* total=new int[numstacks+1];
+  total[0]=0;
+  for (int i=0;i<numstacks;i++)
+      total[i+1]=total[i]+stack[i]->getnumpoints();
+  
+  return total;
+}
+// --------------------------------------------------------------------------
+float*  PXTriangulatedStack::generateVolumes(const char* fnameendo,const char* fnameepi,
+					     int end,int begin)
+{
+
+  PXTriangulatedStack* stack1=new PXTriangulatedStack();
+  PXTriangulatedStack* stack2=new PXTriangulatedStack();
+  if (end<begin)
+      return 0;
+  
+  float* volumes=new float[end-begin+1];
+  int ok=1;
+
+  for (int i=begin;i<=end;i++)
+      {
+	char line1[100],line2[100];
+	sprintf(line1,"%s.%02d.tstack",fnameendo,i);
+	int a1=stack1->Load(line1);
+	sprintf(line2,"%s.%02d.tstack",fnameepi,i);
+	int a2=stack2->Load(line2);
+	
+	if (a1+a2==2)
+	    {
+	      PXContourStack* cnt1=stack1->exporttocontourstack();
+	      PXContourStack* cnt2=stack2->exporttocontourstack();
+	      float cx,cy,cz,sx2,sy2,sxy,vol1,vol2;
+	      cnt1->getPositionAndOrientation(cx,cy,cz,sx2,sy2,sxy,vol1);
+	      cnt2->getPositionAndOrientation(cx,cy,cz,sx2,sy2,sxy,vol2);
+	      volumes[i-begin+1]=fabs(vol2-vol1);
+	      delete cnt1;
+	      delete cnt2;
+	    }
+	else
+	    {
+	      ok=0;
+	      i=end+1;
+	    }
+      }
+  
+  if (ok==0)
+      {
+	for (int i=0;i<end-begin+1;i++)
+	    volumes[i]=1.0;
+      }
+
+  delete stack1;  delete stack2;
+  return volumes;
+}
+// ------------------------------------------------------------------------------
+void PXTriangulatedStack::updateCurvaturesFromStack(PXTriangulatedStack* denser)
+{
+  if (!denser->hascurvatures() || !denser->hasnormals())
+      return;
+
+  for (int i=0;i<numpoints;i++)
+      {
+	float x[3];
+	int ia;
+	for (ia=0;ia<=2;ia++)
+	    x[ia]=point[i].x[ia];
+
+	int best;
+	denser->findnearestpoint(x[0],x[1],x[2],best,0,5.0);
+	PXTriangulatedStackPoint* other=denser->getpoint(best);
+
+	for (ia=0;ia<=2;ia++)
+	    point[i].nx[ia]=other->nx[ia];
+
+	for (ia=0;ia<=1;ia++)
+	    point[i].k[ia]=other->k[ia];
+      }
+  normalsok=denser->hasnormals();
+  curvaturesok=denser->hascurvatures();
+}
+// ------------------------------------------------------------------------------
+int PXTriangulatedStack::updateStackIndexZlevels()
+{
+  if (hasstackindex())
+      {
+	for (int i=0;i<stackIndex.numcontours;i++)
+	    {
+	      float z=0.0;
+	      int np=0;
+	      for (int j=stackIndex.index[i];j<stackIndex.index[i+1];j++)
+		  {
+		    z+=getpoint(j)->x[2];
+		    ++np;
+		  }
+	      if (np>0)
+		  {
+		    z=z/float(np);
+		    stackIndex.zlevel[i]=z;
+		  }
+	    }
+	return 1;
+      }
+  else
+      return 0;
+}
+// ------------------------------------------------------------------------------
+int PXTriangulatedStack::scalepoints(float sx,float sy,float sz)
+{
+  for (int i=0;i<numpoints;i++)
+    {
+      point[i].x[0]*=sx;
+      point[i].x[1]*=sy;
+      point[i].x[2]*=sz;
+    }
+
+  normalsok=0;
+  curvaturesok=0;
+  
+  if (hasstackindex())
+    {
+      for (int i=0;i<stackIndex.numcontours;i++)
+	stackIndex.zlevel[i]*=sz;
+    }
+
+  return 1;
+}
+
+// End of namespace
+
diff --git a/bioimagesuite30_src/numerics/pxtriangulatedstack.h b/bioimagesuite30_src/numerics/pxtriangulatedstack.h
new file mode 100644
index 0000000..d1a12ca
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxtriangulatedstack.h
@@ -0,0 +1,249 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//
+//
+//---------------------------------------------------------------------------------------------------------
+
+
+#ifndef _PXTriangulatedStack
+#define _PXTriangulatedStack
+#include "pxcontourstack.h"
+#include "pxgeometrystruct.h"
+
+
+
+
+struct PXColorPoint {
+  float red,green,blue;
+};
+
+struct PXStackIndex {
+  int   numcontours;
+  int   *index;
+  float *zlevel;
+};
+
+class PXTriangulatedStack  {
+
+  protected :
+
+  PXStackIndex stackIndex;
+  PXTriangulatedStackPoint* point;
+  PXIntegerList* neighbours;
+  PXNeighboursList* neighboursList;
+  PXTriangle* triangle;
+  int numpoints,numtriangles,maxconnection,useindex;
+  int haspointstructures,hastrianglestructures,hasneighbourstructures,normalsok,curvaturesok;
+  int stackindexok,trianglecentroidsok;
+
+  // ******************************************************************************
+  //          PUBLIC INTERFACE
+  // ******************************************************************************
+
+  public :
+  static float max_curvature,min_curvature;
+  static int   debugmode;
+
+  PXTriangulatedStack(PXTriangulatedStack* old);
+  PXTriangulatedStack(const char* nuagesfname,int mode);
+  PXTriangulatedStack(PXContourStack* old,int mode);
+  PXTriangulatedStack();
+  virtual ~PXTriangulatedStack();
+
+  void init(int np=0,int nt=0);
+  void cleanup();
+  void cleanupneighbours();
+
+  void Copy(PXTriangulatedStack* old);
+  void setfromcontourstack(PXContourStack* old,int mode);
+  int  setfrompolarcontourstack(PXContourStack* old,float middlex);
+  PXContourStack* exporttocontourstack(int skiplevels=0,int skipapex=0);
+  
+  
+
+  // [A] Access Contours
+  // ------------------
+  virtual int   haspoints();       
+  virtual int   hastriangles();    
+  virtual int   hasneighbours();   
+  virtual int   hasnormals();      
+  virtual int   hascurvatures();   
+  virtual int   hascentroids();    
+  virtual int   hasstackindex();   
+  				  
+  virtual int   getmaxconnection();
+  virtual int   getnumpoints();    
+  virtual int   getnumtriangles(); 
+
+  virtual PXTriangulatedStackPoint* getpoint(int pointidx);
+  virtual PXTriangle*     gettriangle(int triangleidx);
+  virtual PXIntegerList*  getneighbours(int idx);
+  virtual PXStackIndex    getstackindex();
+  
+
+  // [B] Internal Operations
+  // -----------------------
+  virtual int  generateNeighbours(int openSurfaceMode=0);
+  virtual int  generateNormals();
+  virtual int  calculateCurvatures(int scale);
+  virtual int  scalepoints(float sx,float sy,float sz=1.0);
+  virtual int  calculateCentroids();
+  virtual void initialiseStackIndex(PXContourStack* old);
+  virtual int  getrelationship(int p1,int p2,int max=1000);
+  virtual int  findCentroid(int* p,int np,int iterations=2,int max=5);
+  virtual int  findCentroid(PXIntegerList* origList,int iterations=2,int maxd=5);
+  virtual int  collectNeighbours(int point,int distance,PXIntegerList* list);
+
+  virtual int updateStackIndexZlevels();
+
+  // [C] I/O Functions
+  // -----------------------------
+  virtual int Load(const char* filename);
+  virtual int Load(gzFile fin);
+  virtual int LoadOffset(const char* filename);
+  virtual int LoadOffset2(const char* filename);
+  virtual int Save(const char* filename);
+  virtual int Save(FILE* fout);
+  virtual int SaveAbaqusRigid(const char* filename,int nodeoffset=200000,int index=1);
+  virtual int SaveAbaqusRigid(FILE* fout,int nodeoffset=200000,int index=1);
+
+
+  
+  // [D] Smoothing, Subdivision and Trimming Operations
+  // --------------------------------------------------
+  int subdivide();
+  int trimtstack(float zbot=-100.0,float ztop=100.0);
+  int trimtstackz(float zbot,float ztop);
+  int nonShrinkSmooth(float alpha,float beta,int iterations,int movez=0,int uniform=1);
+  PX3Vector* nonShrinkSmoothD(float alpha,float beta,int iterations,int movez=0,int uniform=1);
+
+  // [E] Shape Tracking Deformation
+  // ------------------------------
+  virtual float findnearestpoint(float&x,float& y,float &z,int& pt,int interpolate=1,float maxdist=0.1);
+  virtual void deformUsingDisplacements(PX3Vector* disp,float factor=1.0,int smoothiter=0);
+  virtual void updateCurvaturesFromStack(PXTriangulatedStack* otherstack);
+  
+
+  // [F] Triangulation Code
+  // ----------------------
+  static void findorigin2D(int np[2],float* x[2],float* y[2],
+			   int origin[2]);
+  static int  triangulate2D(int np[2],float* x[2],float* y[2],int origin[2],
+			    PXNeighboursList* faces,int maxfaces);
+
+  static void findorigin(int np[2],float* x[2],float* y[2],float* z[2],
+			 int origin[2],int dimension=3);
+  static int  triangulate(int np[2],float* x[2],float* y[2],float* z[2],int origin[2],
+			 PXNeighboursList* faces,int maxfaces,int dimension=3);
+
+  
+  // More Static Code
+  // ----------------
+  static int  saveTstackPair(const char *fname,
+			     PXTriangulatedStack* stack1,PXTriangulatedStack* stack2,
+			     PX3Vector* disp,int* used=NULL,int* fixed=NULL);
+
+  static int  findSymmetricPair(PXTriangulatedStack* tstack1,PXTriangulatedStack* tstack2,
+				PXNeighboursList* tetra,int seedt=0);
+
+  static int  smoothEuclidean(PXTriangulatedStack* tstack1,PXTriangulatedStack* tstack2,
+			      PX3Vector* newdisp,PX3Vector* olddisp,
+			      int* used,int* fixed,int* corr,
+			      int mode,int saveno=-1,int smoothOutput=0);
+
+  static int smoothConnection(PXTriangulatedStack* tstack1,PXTriangulatedStack* tstack2,
+			      PX3Vector* dx,
+			      int* used,int* fixed,int* corr,
+			      int mode,int saveno=-1,int smoothOutput=0);
+  static int curvatureTracking(PXTriangulatedStack* tstack1,PXTriangulatedStack* tstack2,
+			       PX3Vector* disp,int* corr,
+			       float lamda=0.3,int smoothIterations=10);
+      
+
+  static int findSmoothMap(PXTriangulatedStack* tstack1,PXTriangulatedStack* tstack2,
+			   int* index,PX3Vector* dx,int mode=2,int iterations=20,
+			   int curvmode=-1,float lamda=0.5);
+
+
+  // [F] Combatibility with old Peng-Cheng Displacements
+  // ---------------------------------------------------
+  void findbestpair(PXDispPair* pair,int npoints,
+		    float& x,float& y,float& z,float threshold);
+  void deformUsingShapeDisplacements(const char* dispname,float threshold=0.2);
+  int loadPengChengDisplacementsSingle(const char* filename,PX3Vector* dx,float tolerance=0.5);
+
+
+  // [G] Inventor Colormap Code 
+  // -----------------------------------
+  static float curvature_lookup_red(float val);
+  static float curvature_lookup_green(float val);
+  static float curvature_lookup_blue(float val);
+  static float bending_energy_lookup_red(float val);
+  static float bending_energy_lookup_green(float val);
+  static float bending_energy_lookup_blue(float val);
+  static float shape_index_lookup_red(float val);
+  static float shape_index_lookup_green(float val);
+  static float shape_index_lookup_blue(float val); 
+  PXColorPoint* generateColors(int mode,float gamma=1.5);
+  virtual int SaveInventor(const char* fname,PXColorPoint* colors=NULL);
+  virtual int SaveInventor(FILE* fout,PXColorPoint* colors=NULL);
+
+  // [H] Rigid Deformation Code
+  // --------------------------
+  virtual void getstatistics(float mean[3],float var[6],PXTriangulatedStack* other=NULL);
+
+
+
+  // [I] Solid related Code
+  // -----------------------
+  // Generate Solid -- these are static
+  // ----------------------------------
+  static int save2qhull(const char* fname,PXTriangulatedStack** stack,int numstakcs);
+  static int loadqhull(const char* fname, PXTriangulatedStack** stack,int numstacks,
+		       PXNeighboursList* tetra,int& nt);
+  static int* gettotal(PXTriangulatedStack** stack,int numstacks);
+  static int whichstack(int index,int* total,int numstacks);
+  static int cleanup(PXTriangulatedStack* tstack[],int numstacks,
+		     PXNeighboursList* tetra,int nt);
+  static int save2inventor(const char *fname,PXTriangulatedStack** tstack,int numstacks,
+			   PXNeighboursList* tetra,int nt);
+  static int save2inventor(FILE* fout,PXTriangulatedStack** tstack,int numstacks,
+			   PXNeighboursList* tetra,int nt);
+
+
+  static float* generateVolumes(const char* fnamename,const char* fnameepi,int end,int begin);
+
+
+};
+
+#endif
+
+
diff --git a/bioimagesuite30_src/numerics/pxutil.cpp b/bioimagesuite30_src/numerics/pxutil.cpp
new file mode 100644
index 0000000..29f9d16
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxutil.cpp
@@ -0,0 +1,1015 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+//  This is a catch all utility file that is mostly written by Xenios Papademetris with code
+//     from Larry Staib
+//
+// -------------------------------------------------------------------------------------------------------
+// pxutil.cc
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July 1995   papad at noodle.med.yale.edu
+
+   See pxutil.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxutil.h"
+
+/* Byte Swapping *************************************************************
+Byte Swap Stuff
+******************************************************************************/
+
+int pxanaswapint(int input)
+{
+  int a=input;
+  unsigned char* bytes=(unsigned char*)&a;
+  unsigned char tmp;
+
+  tmp=*bytes;
+  *bytes=*(bytes+3);
+  *(bytes+3)=tmp;
+
+  tmp=*(bytes+1);
+  *(bytes+1)=*(bytes+2);
+  *(bytes+2)=tmp;
+
+  //fprintf(stderr,"Swapping Int %d to %d\n",input,a);
+  return a;
+}
+
+float pxanaswapfloat(float input)
+{
+  float a=input;
+  unsigned char* bytes=(unsigned char*)&a;
+  unsigned char tmp;
+
+  tmp=*bytes;
+  *bytes=*(bytes+3);
+  *(bytes+3)=tmp;
+
+  tmp=*(bytes+1);
+  *(bytes+1)=*(bytes+2);
+  *(bytes+2)=tmp;
+
+  //fprintf(stderr,"Swapping Float %f to %f\n",input,a);
+  return a;
+}
+
+short pxanaswapshort(short input)
+{
+  short a=input;
+  unsigned char *bytes=(unsigned char*)&a;
+  unsigned char tmp;
+  tmp=*bytes;
+  *bytes=*(bytes+1);
+  *(bytes+1)=tmp;
+  //fprintf(stderr,"Swap %d to %d\n",input,a);
+  return a;
+
+}
+
+double pxanaswapdouble(double input)
+{
+  double a=input;
+  double b=input;
+  unsigned char* ap=(unsigned char*)&a;
+  unsigned char* bp=(unsigned char*)&b;
+
+  ap[0]=bp[7];
+  ap[1]=bp[6];
+  ap[2]=bp[5];
+  ap[3]=bp[4];
+  ap[4]=bp[3];
+  ap[5]=bp[2];
+  ap[6]=bp[1];
+  ap[7]=bp[0];
+
+  return a;
+}
+
+/* Writeanahdr ****************************************************************
+write ANALYZE .hdr file
+******************************************************************************/
+
+int writeanahdr(const char* filename,anaimagedata *imdata,int bits)
+{
+  char *hdrfile= anacreateheaderfilename(filename);
+
+  struct dsr hdr;
+  FILE *fp;
+  int dsize;
+
+  int realbits=abs(bits);
+  
+  if (realbits != 8 && realbits != 16 && realbits!=32 && realbits!=31 && realbits<128)  
+      {
+	printf("Writeanahdr: invalid bits per pixel\n");
+	return(0);
+      }
+
+
+  /*  fprintf(stderr,"Size of Header = %d\n" , sizeof(struct dsr));
+      fprintf(stderr,"Short Int = %d\n" , sizeof(short int));
+      fprintf(stderr,"Size of Header Key = %d\n" , sizeof(struct header_key));
+      fprintf(stderr,"Size of Image Dimension = %d\n" , sizeof(struct image_dimension));
+      fprintf(stderr,"Size of Data History = %d\n" , sizeof(struct data_history));*/
+
+  int swap=0;
+  if (bits<0)
+      swap=1;
+  
+  if((fp=fopen(hdrfile,"w"))==0) {
+    printf("Writeanahdr: unable to create: %s\n",hdrfile);
+    dsize = 0;
+  }
+    else {
+
+      memset(&hdr,0,sizeof(struct dsr)); 
+      hdr.hk.sizeof_hdr = sizeof(struct dsr);
+      hdr.hk.extents = 16384;
+      hdr.hk.regular = 'r';
+
+      if (imdata->tsize>1)
+	hdr.dime.dim[0] = 4;
+      else
+	hdr.dime.dim[0] = 3;
+      hdr.dime.dim[1] = imdata->xsize;
+      hdr.dime.dim[2] = imdata->ysize;
+      hdr.dime.dim[3] = imdata->zsize;
+      hdr.dime.dim[4] = imdata->tsize;
+      strcpy(hdr.dime.vox_units,"mm");
+      strcpy(hdr.dime.cal_units," ");
+
+
+
+      if (realbits>128)
+	{
+	  // Hack if > 128 subtract 128 and use as actual number
+	  hdr.dime.datatype=realbits-128;
+	}
+      else
+	{
+	  switch(realbits) 
+	    { 
+	    case 1:  hdr.dime.datatype = 1;   break;
+	    case 8:  hdr.dime.datatype = 2;   break; /* unsigned char */
+	    case 16: hdr.dime.datatype = 4;   break; /*    short      */
+	    case 31: hdr.dime.datatype = 8;   break; /*   signed int    */
+	    case 32: hdr.dime.datatype = 16;  break; /*    float *//* 8  for int */
+	    case 24: hdr.dime.datatype = 128; break; /*     rgb       */
+	    case 64: hdr.dime.datatype = 32;  break; /*   complex*//* 64 for dbl */
+	    }
+	}
+      
+      switch (hdr.dime.datatype)
+	{
+	case 1:
+	  hdr.dime.bitpix=1;
+	  break;
+	case 2:
+	  hdr.dime.bitpix=8;
+	  break;
+	case 4:
+	  hdr.dime.bitpix=16;
+	  break;
+	case 8:
+	  hdr.dime.bitpix=32;
+	  break;
+	case 16:
+	  hdr.dime.bitpix=32;
+	  break;
+	case 32:
+	  hdr.dime.bitpix=64;
+	  break;
+	}
+	  
+
+      fprintf(stderr,"Saving swap=%d, datatype=%d bitpix=%d\n",swap,hdr.dime.datatype,hdr.dime.bitpix);
+
+      hdr.dime.cal_max = 0.0;
+      hdr.dime.cal_min = 0.0;
+      hdr.dime.glmax  = imdata->maxpix;
+      hdr.dime.glmin  = imdata->minpix;
+      hdr.dime.pixdim[1] = imdata->xpix;
+      hdr.dime.pixdim[2] = imdata->ypix;
+      hdr.dime.pixdim[3] = imdata->zpix;
+      hdr.dime.pixdim[4] = 1.0;
+      hdr.dime.vox_offset = 0.0;
+      hdr.hist.orient = imdata->orient;
+
+      /*for (int ia=0;ia<=4;ia++)
+	hdr.hist.origin[ia]=0;*/
+
+      fprintf(stderr,"Saving swap=%d, datatype=%d %d,%d,%d\n",swap,hdr.dime.datatype,
+	      hdr.dime.dim[1],
+	      hdr.dime.dim[2],
+	      hdr.dime.dim[3],
+	      hdr.dime.dim[4]);
+
+      hdr.dime.funused1=1.0;
+      
+      if (swap==1)
+	  {
+	    for (int k=0;k<=4;k++)
+		{
+		  hdr.dime.dim[k]=pxanaswapshort(hdr.dime.dim[k]);
+		  //hdr.hist.origin[k]=pxanaswapshort(hdr.hist.origin[k]);
+		  if (k>0)
+		      hdr.dime.pixdim[k]=pxanaswapfloat(hdr.dime.pixdim[k]);
+		}
+
+	    hdr.dime.bitpix=pxanaswapshort(hdr.dime.bitpix);
+	    hdr.dime.datatype=pxanaswapshort(hdr.dime.datatype);
+	    hdr.dime.glmax=pxanaswapint(hdr.dime.glmax);
+	    hdr.dime.glmin=pxanaswapint(hdr.dime.glmin);
+	    hdr.dime.funused1=pxanaswapfloat(hdr.dime.funused1);
+	  }
+      
+      strcpy(hdr.hist.exp_date,"");
+      strcpy(hdr.hist.exp_time,"");
+      strcpy(hdr.hist.patient_id,"");
+      if (swap==0)
+	  strcpy(hdr.hist.descrip,"created by writeanahdr2");
+      else
+	  strcpy(hdr.hist.descrip,"created by writeanahdr2 swapped");
+      //fprintf(stderr,"Header=%s",hdr.hist.descrip);
+      fwrite(&hdr,sizeof(struct dsr),1,fp);
+      fclose(fp);
+      dsize = 1;
+    }
+  delete [] hdrfile;
+  return(dsize);
+}
+
+/* Readanahdr *****************************************************************
+read ANALYZE .hdr file
+******************************************************************************/
+
+int readanahdr(const char *filename, anaimagedata *imdata)
+
+{
+  //fprintf(stderr,"In read anahdr\n");
+  char *hdrfile=anacreateheaderfilename(filename);
+  //  fprintf(stderr,"Trying %s\n",hdrfile);
+  
+  gzFile fd=gzsuffixopen(hdrfile,"rb");
+  if ((long)fd==0)
+    {
+      char* hdrfile2=anacreatefilename(hdrfile,".HDR",".hdr");
+      //      fprintf(stderr,"Trying %s instead of %s\n",hdrfile2,hdrfile);
+      fd=gzsuffixopen(hdrfile2,"rb");
+      delete [] hdrfile2;
+    }
+
+  struct dsr hdr;
+  short psize=0;
+  if ((long)fd==0)
+    {
+      delete [] hdrfile;
+      return 0;
+    }
+  else
+    {
+      gzread(fd,&hdr,sizeof(struct dsr));
+      imdata->xsize  = hdr.dime.dim[1];
+      imdata->ysize  = hdr.dime.dim[2];
+      imdata->zsize  = hdr.dime.dim[3];
+      imdata->tsize  = hdr.dime.dim[4];
+      imdata->xpix   = hdr.dime.pixdim[1];
+      imdata->ypix   = hdr.dime.pixdim[2];
+      imdata->zpix   = hdr.dime.pixdim[3];
+      imdata->minpix = hdr.dime.glmin;
+      imdata->maxpix = hdr.dime.glmax;
+      imdata->orient = hdr.hist.orient;
+      psize          = hdr.dime.bitpix;
+      imdata->datatype=hdr.dime.datatype;
+      // Use 31 as flag for integer 
+      
+      gzclose(fd);
+      
+      //fprintf(stderr,"Sizes = %d x %d x %d \n",imdata->xsize,imdata->ysize,imdata->zsize);
+      // Check for swapped bytes
+      if (psize<0 || psize>64)
+	{
+	  imdata->xsize=pxanaswapshort(imdata->xsize);
+	  imdata->ysize=pxanaswapshort(imdata->ysize);
+	  imdata->zsize=pxanaswapshort(imdata->zsize);
+	  imdata->tsize=pxanaswapshort(imdata->tsize);
+	  
+	  //fprintf(stderr,"Swapped Sizes = %d x %d x %d \n",imdata->xsize,imdata->ysize,imdata->zsize);
+	  imdata->minpix=pxanaswapint(imdata->minpix);
+	  imdata->maxpix=pxanaswapint(imdata->maxpix);
+	  
+	  imdata->xpix=pxanaswapfloat(imdata->xpix);
+	  imdata->ypix=pxanaswapfloat(imdata->ypix);
+	  imdata->zpix=pxanaswapfloat(imdata->zpix);
+	  
+	  imdata->trueminpix=pxanaswapint(imdata->trueminpix);
+	  imdata->truemaxpix=pxanaswapint(imdata->truemaxpix);
+	  
+	  psize=-pxanaswapshort(psize);
+	  imdata->datatype=pxanaswapshort(hdr.dime.datatype);
+	}
+    }
+
+
+
+
+  delete [] hdrfile;
+
+
+  if ( psize == 32 )
+    {
+      if (hdr.dime.datatype==8)
+	psize=31;
+    }
+
+  return psize;
+}
+
+// ---------------------------------------------------------------------------
+
+int Anagetparams(const char* filename,int& x,int& y,int &z)
+{
+  anaimagedata *hdr=new anaimagedata;
+  int i=abs(readanahdr(filename,hdr));
+  z=hdr->zsize*hdr->tsize;
+  x=hdr->xsize;
+  y=hdr->ysize;
+  delete hdr;
+  return i;
+}
+
+int  Anagetparams(const char* filename,int& x,int& y,int &z,int &bytes)
+{
+  anaimagedata *hdr=new anaimagedata;
+  int i=abs(readanahdr(filename,hdr));
+  z=hdr->zsize*hdr->tsize;
+  x=hdr->xsize;
+  y=hdr->ysize;
+  bytes=int(i/8);
+  if (bytes<1)
+      bytes=1;
+
+  delete hdr;
+  return i;
+}
+
+int  Anagetparams(const char* filename,int& x,int& y,int &z,int &t,int &bytes)
+{
+  anaimagedata *hdr=new anaimagedata;
+  int i=abs(readanahdr(filename,hdr));
+  z=hdr->zsize;
+  t=hdr->tsize;
+  x=hdr->xsize;
+  y=hdr->ysize;
+  bytes=int(i/8);
+  if (bytes<1)
+      bytes=1;
+  delete hdr;
+  return i;
+}
+
+// ---------------------------------------------------------------------------
+// FILENAME UTILITIES Some by Larry Staib  staib at ipag.med.yale.edu
+// ---------------------------------------------------------------------------
+
+char *eatsuffix(const char *orig_filename)
+{
+  int   len = (int)strlen(orig_filename);
+  char* newname = new char[len+10];
+  char* filename= new char[len +10];
+  strcpy(newname,orig_filename);
+  strcpy(filename,orig_filename);
+
+  char* ext = strrchr(filename,'.');
+  char* sla = strrchr(filename,'/');
+
+  if (ext != NULL) 
+    {  
+      if ((sla == NULL) || (strlen(sla) >= strlen(ext))) 
+	{ /* file.ext or ../file.ext */
+	  int lenext = (int)strlen(ext);
+	  strncpy(newname,filename,len-lenext);
+	  newname[len-lenext] = '\0';
+	}
+    }
+  
+  delete [] filename;
+  return(newname);
+}
+
+/* nothisextension ************************************************************
+ 
+  Removes specific extension from filename if there is one.
+
+  Handles: file ../file.ext file.ext  ../file
+
+******************************************************************************/
+char *nothisextension(const char *orig_filename,const char *extension)
+
+{ 
+  char* filename=new char[strlen(orig_filename)+1 ];
+  strcpy(filename,orig_filename);
+
+  char *ext = strrchr(filename,'.');
+ 
+  if (ext == NULL) 
+    {
+      char *help2=new char[strlen(filename+1)];
+      strcpy(help2,filename);
+      delete [] filename;
+      return(help2);
+    }
+
+  if (strcmp(ext,extension) == 0) 
+    {
+      char* f=(eatsuffix(filename));
+      delete [] filename;
+      return f;
+    }
+
+  char *help2=new char[strlen(filename+1)];
+  strcpy(help2,filename);
+  delete [] filename;
+  return(help2);
+  
+}
+
+char* anaeatsuffix(const char* fname)
+{ 
+  char* newfname=new char[strlen(fname)+1];
+  strcpy(newfname,fname);
+  char* a=strtok(newfname,".");
+  char* outname=new char[strlen(fname)+1];
+  strcpy(outname,a);
+  delete [] newfname;
+  return outname;
+}
+     
+char* anaeatpath(const char* fname)
+{
+#ifdef _WIN32
+//  char* ffname=strrchr(fname,(int)'\\');          //This is ANSI-C
+    const char* ffname0=strrchr(fname,(int)'\\');	//This is ANSI-C++
+    char* ffname = (char*)ffname0;					//This is ANSI-C++//hirohito
+#else
+    char* ffname = strrchr((char*)fname,(int)'/');
+#endif
+
+  if (ffname==NULL) 
+    {
+      ffname=new char[strlen(fname)+1];
+      strcpy(ffname,fname);
+      return ffname;
+    }
+  
+  ffname++;
+  char* newname=new char[strlen(fname)+1];
+  strcpy(newname,ffname);
+  return newname;
+}    
+
+/******************************************************************************/
+char* anacreateheaderfilename(const char* fname)
+{
+
+  char* temp=anacreatefilename(fname,"",".gz");
+  char* temp1=anacreatefilename(temp,"",".HDR");
+  char* temp2=anacreatefilename(temp1,".hdr",".img");
+  delete [] temp;
+  delete [] temp1;
+  return temp2;
+}
+
+char* anacreateimagefilename(const char* fname)
+{
+  char* temp=anacreatefilename(fname,"",".gz");
+  char* temp2=anacreatefilename(temp,"",".HDR");
+  char* temp3=anacreatefilename(temp2,".img",".hdr");
+
+  delete [] temp;
+  delete [] temp2;
+  return temp3;
+
+}
+
+char* anacreatefilename(const char* orig_filename,const char* wanted,const char *unwanted)
+{
+  char* tmp,*hdrfile;
+  char* filename=new char[strlen(orig_filename)+1 ];
+  strcpy(filename,orig_filename);
+
+  char* ext = strrchr(filename,'.');
+ 
+  if (ext)
+    {
+      if ( (strcmp(ext,unwanted) == 0 ) ||  ( strcmp(ext,".") == 0 ) )
+	{
+	  tmp=eatsuffix(filename);
+	  hdrfile=new char[strlen(tmp)+strlen(wanted)+5];
+	  sprintf(hdrfile,"%s%s",tmp,wanted);
+	  delete [] tmp;
+	  delete [] filename;
+	  return hdrfile;
+	}
+      
+      if (strcmp(ext,wanted) == 0)
+	{
+	  hdrfile=new char[strlen(filename)+5];
+	  strcpy(hdrfile,filename);
+	  delete [] filename;
+	  return hdrfile;
+	}
+      
+      hdrfile=new char[strlen(filename)+strlen(wanted)+5];
+      sprintf(hdrfile,"%s%s",filename,wanted);
+      delete [] filename;
+      return hdrfile;
+    }
+  hdrfile=new char[strlen(filename)+strlen(wanted)+5];
+  sprintf(hdrfile,"%s%s",filename,wanted);
+  delete [] filename;
+  return hdrfile;
+}
+
+/******************************************************************************/
+char* anaextractpath(const char* fname)
+{
+  char* path;
+  int where=-1;
+  for (int c=0;c<(int)strlen(fname);c++)
+      {
+	if (fname[c]=='/')
+	  where=c;
+      }
+  if (where==-1)
+    {
+      path=new char[3];
+      strcpy(path,"./");
+    }
+  else
+    {
+      path=new char[where+2];
+      for (int c=0;c<=where;c++)
+	path[c]=fname[c];
+      path[where+1]=(char)0;
+    }
+  return path;
+}
+/******************************************************************************/
+int anabackupfile(const char* fname)
+{
+  FILE* fin=fopen(fname,"r");
+  if (fin)
+      {
+	fclose(fin);
+	char* command=new char[strlen(fname)*2+50];
+	char* temp=new char[strlen(fname)+2];
+	strcpy(command,fname);
+	strcpy(temp,fname);
+	char* path=anaextractpath(command);
+#ifndef _WIN32
+	sprintf(command,"/usr/bin/cp %s %s/backup_of_%s",fname,path,anaeatpath(temp));
+#else
+	sprintf(command,"copy %s %s\backup_of_%s",fname,path,anaeatpath(temp));
+#endif
+	delete [] path;
+	int ok=system(command);
+	delete [] command;
+	delete [] temp;
+	return ok;
+      }
+  else
+      return 0;
+}
+/******************************************************************************/
+int stringskipspace(const char* line,int po)
+{
+  // Ascii code 0=48,..,9=57, + = 43 - = 45 . = 46
+ 
+  int flag=0;
+  do
+      {
+	int p=(int)line[po];
+	if ((p<48 || p>57) && (p!=45 &&p!=46 && p!=43) && ( po<(int)strlen(line) ))
+	    po++;
+	else
+	    flag=1;
+      }
+  while (flag==0);
+  return po;
+}
+/******************************************************************************/
+int stringskipnumber(const char* line,int po)
+{
+  // Ascii code 0=48,..,9=57, + = 43 - = 45 . = 46
+
+  int flag=0;
+  do
+      {
+	int p=(int)line[po];
+	if ( ((p>=48 &&  p<=57) || (p==45 || p==46 || p==43)) && ( po<(int)strlen(line) ))
+	    po++;
+	else
+	    flag=1;
+      }
+  while (flag==0);
+  return po;
+}
+/******************************************************************************/
+float   getgzstreamfloat(gzFile fin)
+{
+  char line[26];
+  strcpy(line,"");
+  int po=0,flag=0;
+  
+  line[po]=(char)0;
+
+  int mode=0;
+  do
+      {
+	int p=gzgetc(fin);
+	if (p==-1)
+	    flag=1;
+	else
+	    {
+	      if( ((p>=48 &&  p<=57) || (p==45 || p==46 || p==43)))
+		  {
+		    line[po]=(char)p;
+		    line[po+1]=(char)0;
+		    po++;
+		    if (po==25)
+			flag=1;
+		    mode=1;
+		  }
+	      else 
+		  {
+		    if (mode==1)
+			flag=1;
+		  }
+	    }
+      }
+  while (flag==0);
+  return atof(line);
+  
+}
+
+int getgzstreaminteger(gzFile fin)
+{
+  return int(getgzstreamfloat(fin));
+
+}
+
+int gzfindstringinstring(const char* orig,const char* lookfor)
+{
+  if (strlen(lookfor)>strlen(orig))
+      return 0;
+
+  int i=0,found=0;
+  int maxi=int(strlen(orig)-strlen(lookfor))+1;
+
+  while(found==0 && i<maxi)
+      {
+	if (strncmp(&orig[i],lookfor,strlen(lookfor))==0)
+	    found=1;
+	i++;
+      }
+  
+  return found;
+}
+
+/******************************************************************************/
+gzFile ZEXPORT gzsuffixopen (const char* path, const char* mode,int complevel)
+{
+  // Default 
+
+  if (mode==NULL)
+      {
+	//fprintf(stderr,"Returning NULL\n");
+	return Z_NULL;
+      }
+
+  if (mode[0]=='r')
+      {
+	//fprintf(stderr,"Going to gz_open %s %s\n",path,mode);
+	gzFile s=gzopen (path, mode);
+	if (s!=Z_NULL)
+	    return s;
+	
+	// Take 2 check for .gz suffix if missing
+
+	char* newpath=new char[strlen(path)+5];
+	sprintf(newpath,"%s.gz",path);
+	s=gzopen(newpath,mode);
+	//fprintf(stderr,"Reading %s failed trying %s (status=%d)\n",path,newpath,int (s!=Z_NULL));
+	delete [] newpath;
+	return s;
+      }
+  
+  // Write or append 
+  char modestr[20];
+  int foundgz=0;
+
+  complevel=Irange(complevel,0,9);  
+  if (complevel==0)
+      {
+	if (gzfindstringinstring((char* )path,".gz")==1)
+	    {
+	      complevel=6;
+	      foundgz=1;
+	    }
+      }
+  
+  if (complevel>0)
+      sprintf(modestr,"%s%1d",mode,complevel);
+  else
+      sprintf(modestr,"%s0",mode);
+  
+  if (complevel==0 || foundgz==1)
+      return gzopen(path,modestr);
+  
+  char* newpath=anacreatefilename((char*)path,".gz",".gz");
+  gzFile s=gzopen(newpath,modestr);
+  //fprintf(stderr,"Since compressed not writing in %s but trying %s (status=%d)\n",path,newpath,int (s!=Z_NULL));
+  delete [] newpath;
+  return s;
+}
+
+/* Readanahdr *****************************************************************
+read SIGNA lx header from file
+******************************************************************************/
+int readlxhdr(const char* fname,anaimagedata* hdr)
+{
+  struct SUITEDATATYPE shdr;
+  struct EXAMDATATYPE ehdr;
+  struct SERIESDATATYPE sehdr;
+  struct MRIMAGEDATATYPE ihdr;
+  struct PixHdr phdr;
+  
+
+  int orient=0;
+  gzFile fd=gzsuffixopen(fname,"rb");
+  if (fd==0)
+    {
+      fprintf(stderr,"Cannot open lx header %s\n", fname);
+      return(0);
+    }
+
+  /* Read suite header */
+  gzread(fd,&shdr,sizeof(struct SUITEDATATYPE));
+
+  /* Read exam header */
+  gzread(fd,&ehdr,sizeof(struct EXAMDATATYPE));
+
+  /* swap condition: 1.5 Tesla */
+  int swap = (ehdr.magstrength != 15000);
+
+  /*if (swap) 
+    printf("Swapping to read\n");*/
+
+  gzread(fd,&sehdr,sizeof(struct SERIESDATATYPE));
+
+  /* Read MR image header */
+  gzread(fd,&ihdr,sizeof(struct MRIMAGEDATATYPE));
+      
+  /* Read pixel header */
+  gzread(fd,&phdr,sizeof(struct PixHdr));
+
+  /*printf("magic: %d hdr_length: %d \n",
+    lhs_byteswapint(phdr.img_magic,swap), 
+    lhs_byteswapint(phdr.img_hdr_length,swap));*/
+
+  int comp=phdr.img_compress;
+  int comp2=comp;
+  if (swap)
+    comp=pxanaswapint(comp);
+  
+  if (comp!=1)
+    {
+      fprintf(stderr,"mrstriplx: Error, Image compression not supported compression=%d,%d\n",comp,comp2);
+      return(0);
+    }
+  else
+    fprintf(stderr,"Image compression=%d,%d\n",comp,comp2);
+
+  gzclose(fd);
+  
+  short orn=ihdr.plane;
+  if (swap)
+    orn=pxanaswapshort(orn);
+  
+  switch (orn)
+    {
+    case 1:  
+    case 2:
+    case 16:
+    case 18:
+      orient = 0; 
+      break;
+      
+    case 4:  
+    case 20:
+      orient = 2; 
+      break;
+      
+    case 8: 
+    case 24:
+      orient = 1; 
+      break;
+      
+    default:
+      orient=0;
+      break;
+    }
+    
+
+      hdr->zsize = 1 ;
+      hdr->tsize = 1 ;    
+      hdr->orient = orient;
+
+
+  hdr->minpix=-32768;
+  hdr->maxpix=32767;
+
+  if (swap)
+    {
+      hdr->xsize = pxanaswapint(phdr.img_width);
+      hdr->ysize = pxanaswapint(phdr.img_height);
+      hdr->xpix  = pxanaswapfloat(ihdr.pixsize_X);
+      hdr->ypix  = pxanaswapfloat(ihdr.pixsize_Y);
+      hdr->zpix  = pxanaswapfloat(ihdr.slthick);
+      return -16;
+    }
+
+  hdr->xsize = phdr.img_width;
+  hdr->ysize = phdr.img_height;
+  hdr->xpix  = ihdr.pixsize_X;
+  hdr->ypix  = ihdr.pixsize_Y;
+  hdr->zpix  = ihdr.slthick;
+  return 16;
+
+}
+
+
+
+
+
+// -------------------------------------------------------------
+//  Quantization -- quantize numbers to specified decimal places 
+// -------------------------------------------------------------
+float  quantize(float a,int dp)
+{
+  float d=pow(float(10.0),float(dp));
+  return float(float(long(a*d+0.5))/d);
+}
+double quantize(double a,int dp)
+{
+  double d=pow(double(10.0),double(dp));
+  return double(double(long(a*d+0.5))/d);
+}
+
+// -------------------------------------------------------------
+float Fmin(float a,float b)
+{
+  if (a<b)
+      return a;
+  else
+      return b;
+}
+
+float Fmax(float a,float b)
+{
+  if (a>b)
+      return a;
+  else
+      return b;
+}
+
+int Imin(int a,int b)
+{
+  if (a<b)
+      return a;
+  else
+      return b;
+}
+
+int Imax(int a,int b)
+{
+  if (a>b)
+      return a;
+  else
+      return b;
+}
+// -------------------------------------------------------------
+float Frange(float a,float minv,float maxv)
+{
+  if (a<minv) a=minv;
+  if (a>maxv) a=maxv;
+  return a;
+}
+// -------------------------------------------------------------
+float FcyclicDistance(float p1,float p2,float circum)
+{
+  float half=circum/2.0;
+  float dist=0.0;
+  if (fabs(p1-p2)<half)
+      {
+	dist=p1-p2;
+      }
+  else
+      {
+	if (p1>p2)
+	    dist=p2+circum-p1;
+	else
+	    dist=p1+circum-p2;
+      }
+
+  return fabs(dist);  
+}
+// -------------------------------------------------------------
+int   Irange(int   a,int   minv,int   maxv)
+{
+  if (a<minv) a=minv;
+  if (a>maxv) a=maxv;
+  return a;
+}
+
+int  Icyclic(int v,int np)
+{
+  while (v<0) v+=np;
+  while (v>=np) v-=np;
+  return v;
+}
+
+int  Ipowerof2(int v)
+{
+  int i=2;
+  while(i<v)
+      i=i*2;
+  return i;
+}
+
+float   Fcyclic(float v, float maxv)
+{
+  while (v<0.0)
+      v+=maxv;
+  while (v>=maxv)
+      v-=maxv;
+  return v;
+}
+
+int Fsamepoint(float x1,float y1,float z1,float x2,float y2,float z2,float maxdist)
+{
+  float distx=fabs(x1-x2);
+  float disty=fabs(y1-y2);
+  float distz=fabs(z1-z2);
+  float dist=Fmax(distx,disty);
+  dist=Fmax(dist,distz);
+  return (dist<maxdist);
+}
+
+float Fdist(float x1,float y1,float z1,float x2,float y2,float z2)
+{
+  return sqrt(pow(x1-x2,float(2.0))+pow(y1-y2,float(2.0))+pow(z1-z2,float(2.0)));
+}
+
+float Fsqdist(float x1,float y1,float z1,float x2,float y2,float z2)
+{
+  return (pow(x1-x2,float(2.0))+pow(y1-y2,float(2.0))+pow(z1-z2,float(2.0)));
+}
+
+
+
+
+
diff --git a/bioimagesuite30_src/numerics/pxutil.h b/bioimagesuite30_src/numerics/pxutil.h
new file mode 100644
index 0000000..9275be9
--- /dev/null
+++ b/bioimagesuite30_src/numerics/pxutil.h
@@ -0,0 +1,1174 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+//
+//
+
+// pxutil .h 
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : pxxanalyse.h
+
+_Description : Various Utility Routines
+
+(1) Library routines to read analyse file headers
+(2) Filename parsing utilities etc                         
+	       
+	       
+
+_Call : 
+   int getparams(char* filename,int& x,int& y,int &z);
+     
+_References : 
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in August 22nd 1995
+                    2. Updated Binary File Reading 31 Aug 95
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+#ifndef _PXAnalyse
+#define  _PXAnalyse
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "bis_znzlib.h"
+#include <math.h>
+
+#ifndef _WIN32
+	#include <unistd.h>
+#endif
+
+#ifndef M_PI
+#define M_PI 3.1415926854
+#endif
+
+
+/*
+ *
+ * (c) Copyright, 1986-1993
+ * Biomedical Imaging Resource
+ * Mayo Foundation
+ *
+ * dbh.h
+ *
+ */
+
+struct header_key               /* header_key        */
+{                                   /* off + size*/
+  int sizeof_hdr;                 /* 0 + 4     */
+  char data_type[10];             /* 4 + 10    */
+  char db_name[18];               /* 14 + 18   */
+  int extents;                    /* 32 + 4    */
+  short int session_error;        /* 36 + 2    */
+  char regular;                   /* 38 + 1    */
+  char hkey_un0;                  /* 39 + 1    */
+};                                  /* total=40  */
+
+struct image_dimension          /* image_dimension   */
+{                                   /* off + size*/
+  short int dim[8];               /* 0 + 16    */
+  char vox_units[4];              /* 16 + 4    */
+  char cal_units[8];              /* 20 + 4    */
+  short int unused1;              /* 24 + 2    */
+  short int datatype;             /* 30 + 2    */
+  short int bitpix;               /* 32 + 2    */
+  short int dim_un0;              /* 34 + 2    */
+  float pixdim[8];                /* 36 + 32   */
+  /*
+     pixdim[] specifies the voxel dimensions:
+     pixdim[1] - voxel width
+     pixdim[2] - voxel height
+     pixdim[3] - interslice distance
+     ..etc
+	 */
+  float vox_offset;               /* 68 + 4    */
+  float funused1;                 /* 72 + 4    */
+  float funused2;                 /* 76 + 4    */
+  float funused3;                 /* 80 + 4    */
+  float cal_max;                  /* 84 + 4    */
+  float cal_min;                  /* 88 + 4    */
+  int compressed;                 /* 92 + 4    */
+  int verified;                   /* 96 + 4    */
+  int glmax, glmin;               /* 100 + 8   */
+};
+
+struct data_history             /* data_history       */
+{                                   /* off + size*/
+  char descrip[80];               /* 0 + 80    */
+  char aux_file[24];              /* 80 + 24   */
+  char orient;                    /* 104 + 1   */
+  short int origin[3];            /* 105 + 10  */
+  char generated[10];             /* 115 + 10  */
+  char scannum[10];               /* 125 + 10  */
+  char patient_id[10];            /* 135 + 10  */
+  char exp_date[10];              /* 145 + 10  */
+  char exp_time[10];              /* 155 + 10  */
+  char hist_un0[3];               /* 165 + 3   */
+  int views;                      /* 168 + 4   */
+  int vols_added;                 /* 172 + 4   */
+  int start_field;                /* 176 + 4   */
+  int field_skip;                 /* 180 + 4   */
+  int omax,omin;                  /* 184 + 8   */
+  int smax,smin;                  /* 192 + 8   */
+};                                  /* total=200 */
+
+struct dsr                      /* dsr               */
+{                                   /* off + size*/
+  struct header_key hk;           /* 0 + 40    */
+  struct image_dimension dime;    /* 40 + 108  */
+  struct data_history hist;       /* 148 + 200 */
+};                                  /* total=348 */
+
+/* Acceptable values for hdr.dime.datatype */
+
+#define DT_UNKNOWN              0
+#define DT_BINARY               1
+#define DT_UNSIGNED_CHAR        2
+#define DT_SIGNED_SHORT         4
+#define DT_SIGNED_INT           8
+#define DT_FLOAT                16
+#define DT_COMPLEX              32
+#define DT_DOUBLE               64
+#define DT_RGB                  128
+
+
+// -------------------------------------------------------------------
+// gelx.h
+// -------------------------------------------------------------------
+
+#define RASPOINT float
+#define REFCHANTYPE short int
+#define IMATRIXTYPE short int
+#define DIMXYTYPE float
+#define PIXSIZETYPE float
+#define BLOCK char /* not null terminated */
+
+/* long should be 4 bytes */
+#define LONG4 int
+/*#define ATOMIC long */
+#define ATOMIC int
+
+typedef struct LHS_VARTYP {
+unsigned LONG4 length; /* length of the data */
+char * data;
+/* pointer to the data */
+} LHS_VARTYPE;
+/* typedef struct LHS_VARTYP LHS_VARTYPE */
+
+typedef struct SUITEDATATYPE {
+BLOCK su_id [4]; /*Suite ID*/
+short int su_uniq; /*(internal use) Make Unique Flag*/
+char su_diskid; /*(internal use) Disk ID*/
+char prodid [13]; /*(internal use) Product ID*/
+BLOCK su_verscre [2]; /*(internal use) Genesis Version of Record*/
+BLOCK su_verscur [2]; /*(internal use) Genesis Version of Record*/
+unsigned LONG4 su_checksum; /*(internal use) Suite Record Checksum*/
+BLOCK su_padding [85]; /*(internal use) Spare Space*/
+} SUITEDATATYPE ;
+
+typedef struct EXAMDATATYPE {
+BLOCK ex_suid [4]; /*Suite ID for this Exam*/
+short int ex_uniq; /*(internal use) The Make� Unique Flag*/
+char ex_diskid; /*(internal use) Disk ID for this Exam*/
+unsigned short int ex_no; /*Exam Number*/
+char hospname [33]; /*Hospital Name*/
+short int detect; /*Detector Type*/
+int numcells; /*Number of cells in det*/
+float zerocell; /*Cell number at theta*/
+float cellspace; /*Cell spacing*/
+float srctodet; /*Distance from source to detector*/
+float srctoiso; /*Distance from source to iso*/
+short int tubetyp; /*Tube type*/
+short int dastyp; /*DAS type*/
+short int num_dcnk; /*Number of Decon Kernals*/
+short int dcn_len; /*Number of elements in Decon Kernal*/
+short int dcn_density; /*Decon Kernal density*/
+short int dcn_stepsize; /*Decon Kernal stepsize*/
+short int dcn_shiftcnt; /*Decon Kernal Shift Count*/
+int magstrength; /*Magnet strength (in gauss)*/
+char patid [13]; /*Patient ID for this Exam*/
+char patname [25]; /*Patient Name*/
+short int patage; /*Patient Age (years, months or days)*/
+short int patian; /*Patient Age Notation*/
+short int patsex; /*Patient Sex*/
+int patweight; /*Patient Weight*/
+short int trauma; /*Trauma Flag*/
+char hist [61]; /*Patient History*/
+char reqnum [13]; /*Requisition Number*/
+int ex_datetime; /*Exam date/time stamp*/
+char refphy [33]; /*Referring Physician*/
+char diagrad [33]; /*Diagnostician/Radiologist*/
+char op [4]; /*Operator*/
+char ex_desc [23]; /*Exam Description*/
+char ex_typ [3]; /*Exam Type*/
+short int ex_format; /*Exam Format*/
+char firstaxtime[20]; /*Start time(secs) of first axial in exam: double 
+		      doesn't work on linux */
+char ex_sysid [9]; /*Creator Suite and Host*/
+int ex_lastmod; /*Date/Time of Last Change*/
+short int protocolflag; /*Non� Zero indicates Protocol Exam*/
+char ex_alloc_key [13]; /*Process that allocated this record*/
+ATOMIC ex_delta_cnt; /*(internal use) Number of updates to header*/
+BLOCK ex_verscre [2]; /*Genesis Version � Created*/
+BLOCK ex_verscur [2]; /*Genesis Version � Now*/
+unsigned LONG4 ex_checksum; /*(internal use) Exam Record Checksum*/
+ATOMIC ex_complete; /*(internal use) Exam Complete Flag*/
+ATOMIC ex_seriesct; /*(internal use) Last Series Number Used*/
+ATOMIC ex_numarch; /*(internal use) Number of Series Archived*/
+ATOMIC ex_numseries; /*(internal use) Number of Series Existing*/
+LHS_VARTYPE ex_series; /*(internal use) Series Keys for this Exam*/
+ATOMIC ex_numunser; /*(internal use) Number of Unstored Series*/
+LHS_VARTYPE ex_unseries; /*(internal use) Unstored Sers Keys in Exam*/
+ATOMIC ex_toarchcnt; /*(internal use) # of Unarchived Series*/
+LHS_VARTYPE ex_toarchive; /*(internal use) Unarchived Sers Keys in Ex*/
+ATOMIC ex_prospcnt; /*(internal use) # of Prosp/Scout Series*/
+LHS_VARTYPE ex_prosp; /*(internal use) Prosp/Scout Sers Keys in Ex */
+ATOMIC ex_modelnum; /*(internal use) Last Model Number used*/
+ATOMIC ex_modelcnt; /*(internal use) Number of ThreeD Models*/
+LHS_VARTYPE ex_models; /*(internal use) ThreeD Model Keys for Exam*/
+short int ex_stat; /*Patient Status*/
+BLOCK uniq_sys_id [16]; /*Unique System ID*/
+BLOCK service_id [16]; /*Unique Service ID*/
+BLOCK mobile_loc [4]; /*Mobile Location Number*/
+BLOCK study_uid [32]; /*Study Entity Unique ID*/
+short int study_status; /*indicates if study has complete info (DICOM/genesis)*/
+BLOCK ex_padding [516]; /*Spare Space*/
+} EXAMDATATYPE ;
+
+typedef struct SERIESDATATYPE {
+BLOCK se_suid [4]; /*Suite ID for this Series*/
+short int se_uniq; /*(internal use) The Make� Unique Flag*/
+char se_diskid; /*(internal use) Disk ID for this Series*/
+unsigned short int se_exno; /*Exam Number*/
+short int se_no; /*Series Number*/
+int se_datetime; /*Allocation Series Data/Time stamp*/
+int se_actual_dt; /*Actual Series Data/Time stamp*/
+char se_desc [30]; /*Series Description*/
+char pr_sysid [9]; /*Primary Receiver Suite and Host*/
+char pansysid [9]; /*Archiver Suite and Host*/
+short int se_typ; /*Series Type*/
+short int se_source; /*Series from which prescribed*/
+short int se_plane; /*Most like Plane (for L/S)*/
+short int scan_type; /*Scout or Axial (for CT)*/
+int position; /*Patient Position*/
+int entry; /*Patient Entry*/
+char anref [3]; /*Anatomical reference*/
+float lmhor; /*Horizontal Landmark*/
+char prtcl [25]; /*Scan Protocol Name*/
+short int se_contrast; /*Non� zero if > 0 image used contrast(L/S)*/
+char start_ras; /*RAS letter for first scan location (L/S)*/
+float start_loc; /*First scan location (L/S)*/
+char end_ras; /*RAS letter for last scan location (L/S)*/
+float end_loc; /*Last scan location (L/S)*/
+short int se_pseq; /*Last Pulse Sequence Used (L/S)*/
+short int se_sortorder; /*(internal use) Image Sort Order (L/S)*/
+int se_lndmrkcnt; /*Landmark Counter*/
+short int se_nacq; /*Number of Acquisitions*/
+short int xbasest; /*Starting number for baselines*/
+short int xbaseend; /*Ending number for baselines*/
+short int xenhst; /*Starting number for enhanced scans*/
+short int xenhend; /*Ending number for enhanced scans*/
+int se_lastmod; /*Date/Time of Last Change*/
+char se_alloc_key [13]; /*Process that allocated this record*/
+ATOMIC se_delta_cnt; /*(internal use) # of updates to header*/
+BLOCK se_verscre [2]; /*Genesis Version � Created*/
+BLOCK se_verscur [2]; /*Genesis Version � Now*/
+float se_pds_a; /*PixelData size � as stored*/
+float se_pds_c; /*PixelData size � Compressed*/
+float se_pds_u; /*PixelData size � UnCompressed*/
+unsigned LONG4 se_checksum; /*(internal use) Series Record checksum*/
+ATOMIC se_complete; /*(internal use) Series Complete Flag*/
+ATOMIC se_numarch; /*(internal use) Number of Images Archived*/
+ATOMIC se_imagect; /*(internal use) Last Image Number Used*/
+ATOMIC se_numimages; /*(internal use) Number of Images Existing*/
+LHS_VARTYPE se_images; /*(internal use) Image Keys for this Series*/
+ATOMIC se_numunimg; /*(internal use) Number of Unstored Images*/
+LHS_VARTYPE se_unimages; /*(internal use) Unstored Img Keys in Series*/
+ATOMIC se_toarchcnt; /*(internal use) # of Unarchived Images*/
+LHS_VARTYPE se_toarchive; /*(internal use) Unarchived Img Keys in Sers*/
+float echo1_alpha; /*Echo 1 Alpha Value*/
+float echo1_beta; /*Echo 1 Beta Value*/
+unsigned short int echo1_window; /*Echo 1 Window Value*/
+short int echo1_level; /*Echo 1 Level Value*/
+float echo2_alpha; /*Echo 2 Alpha Value*/
+float echo2_beta; /*Echo 2 Beta Value*/
+unsigned short int echo2_window; /*Echo 2 Window Value*/
+short int echo2_level; /*Echo 2 Level Value*/
+float echo3_alpha; /*Echo 3 Alpha Value*/
+float echo3_beta; /*Echo 3 Beta Value*/
+unsigned short int echo3_window; /*Echo 3 Window Value*/
+short int echo3_level; /*Echo 3 Level Value*/
+float echo4_alpha; /*Echo 4 Alpha Value*/
+float echo4_beta; /*Echo 4 Beta Value*/
+unsigned short int echo4_window; /*Echo 4 Window Value*/
+short int echo4_level; /*Echo 4 Level Value*/
+float echo5_alpha; /*Echo 5 Alpha Value*/
+float echo5_beta; /*Echo 5 Beta Value*/
+unsigned short int echo5_window; /*Echo 5 Window Value*/
+short int echo5_level; /*Echo 5 Level Value*/
+float echo6_alpha; /*Echo 6 Alpha Value*/
+float echo6_beta; /*Echo 6 Beta Value*/
+unsigned short int echo6_window; /*Echo 6 Window Value*/
+short int echo6_level; /*Echo 6 Level Value*/
+float echo7_alpha; /*Echo 7 Alpha Value*/
+float echo7_beta; /*Echo 7 Beta Value*/
+unsigned short int echo7_window; /*Echo 7 Window Value*/
+short int echo7_level; /*Echo 7 Level Value*/
+float echo8_alpha; /*Echo 8 Alpha Value*/
+float echo8_beta; /*Echo 8 Beta Value*/
+unsigned short int echo8_window; /*Echo 8 Window Value*/
+short int echo8_level; /*Echo 8 Level Value*/
+BLOCK series_uid [32]; /*Series Entity Unique ID*/
+BLOCK landmark_uid [32]; /*Landmark Unique ID*/
+BLOCK equipmnt_uid [32]; /*Equipment Unique ID*/
+BLOCK se_padding [588]; /*Spare Space*/
+} SERIESDATATYPE ;
+
+typedef struct MRIMAGEDATATYPE {
+BLOCK im_suid [4]; /*Suite id for this image*/
+short int im_uniq; /*(internal use) The Make� Unique Flag*/
+char im_diskid; /*(internal use) Disk ID for this Image*/
+unsigned short int im_exno; /*Exam number for this image*/
+short int im_seno; /*Series Number for this image*/
+short int im_no; /*Image Number*/
+int im_datetime; /*Allocation Image date/time stamp*/
+int im_actual_dt; /*Actual Image date/time stamp*/
+float sctime; /*Duration of scan (secs)*/
+float slthick; /*Slice Thickness (mm)*/
+IMATRIXTYPE imatrix_X; /*Image matrix size � X*/
+IMATRIXTYPE imatrix_Y; /*Image matrix size � Y*/
+float dfov; /*Display field of view � X (mm)*/
+float dfov_rect; /*Display field of view � Y (if different)*/
+DIMXYTYPE dim_X; /*Image dimension � X*/
+DIMXYTYPE dim_Y; /*Image dimension � Y*/
+PIXSIZETYPE pixsize_X; /*Image pixel size � X*/
+PIXSIZETYPE pixsize_Y; /*Image pixel size � Y*/
+BLOCK pdid [14]; /*(internal use) Pixel Data ID*/
+char contrastIV [17]; /*IV Contrast Agent*/
+char contrastOral [17]; /*Oral Contrast Agent*/
+short int contmode; /*Image Contrast Mode*/
+short int serrx; /*Series from which prescribed*/
+short int imgrx; /*Image from which prescribed*/
+short int screenformat; /*Screen Format(8/16 bit)*/
+short int plane; /* Plane Type */
+float scanspacing; /*Spacing between scans (mm?)*/
+short int im_compress; /*Image compression type for allocation*/
+short int im_scouttype; /*Scout Type (AP or lateral)*/
+char loc_ras; /*RAS letter of image location*/
+float loc; /*Image location*/
+RASPOINT ctr_R; /*Center R coord of plane image*/
+RASPOINT ctr_A; /*Center A coord of plane image*/
+RASPOINT ctr_S; /*Center S coord of plane image*/
+RASPOINT norm_R; /*Normal R coord*/
+RASPOINT norm_A; /*Normal A coord*/
+RASPOINT norm_S; /*Normal S coord*/
+RASPOINT tlhc_R; /*R Coord of Top Left Hand Corner*/
+RASPOINT tlhc_A; /*A Coord of Top Left Hand Corner*/
+RASPOINT tlhc_S; /*S Coord of Top Left Hand Corner*/
+RASPOINT trhc_R; /*R Coord of Top Right Hand Corner*/
+RASPOINT trhc_A; /*A Coord of Top Right Hand Corner*/
+RASPOINT trhc_S; /*S Coord of Top Right Hand Corner*/
+RASPOINT brhc_R; /*R Coord of Bottom Right Hand Corner*/
+RASPOINT brhc_A; /*A Coord of Bottom Right Hand Corner*/
+RASPOINT brhc_S; /*S Coord of Bottom Right Hand Corner*/
+char forimgrev [4]; /*Foreign Image Revision*/
+int tr; /*Pulse repetition time(usec)*/
+int ti; /*Pulse inversion time(usec)*/
+int te; /*Pulse echo time(usec)*/
+int te2; /*Second echo echo (usec)*/
+short int numecho; /*Number of echoes*/
+short int echonum; /*Echo Number*/
+float tbldlta; /*Table Delta*/
+float nex; /*Number of Excitations*/
+short int contig; /*Continuous Slices Flag*/
+short int hrtrate; /*Cardiac Heart Rate (bpm)*/
+int tdel; /*Delay time after trigger (msec)*/
+float saravg; /*Average SAR*/
+float sarpeak; /*Peak SAR*/
+short int monsar; /*Monitor SAR flag*/
+short int trgwindow; /*Trigger window (% of R� R interval)*/
+float reptime; /*Cardiac repetition time*/
+short int imgpcyc; /*Images per cardiac cycle*/
+short int xmtgain; /*Actual Transmit Gain (.1 db)*/
+short int rcvgain1; /*Actual Receive Gain Analog (.1 db)*/
+short int rcvgain2; /*Actual Receive Gain Digital (.1 db)*/
+short int mr_flip; /*Flip Angle for GRASS scans (deg.)*/
+int mindat; /*Minimum Delay after Trigger (uSec)*/
+short int cphase; /*Total Cardiac Phase prescribed*/
+short int swappf; /*Swap Phase/Frequency Axis*/
+short int pauseint; /*Pause Interval (slices)*/
+float pausetime; /*Pause Time*/
+int obplane; /*Oblique Plane*/
+int slocfov; /*Slice Offsets on Freq axis*/
+int xmtfreq; /*Center Frequency (0.1 Hz)*/
+int autoxmtfreq; /*Auto Center Frequency (0.1 Hz)*/
+short int autoxmtgain; /*Auto Transmit Gain (0.1 dB)*/
+short int prescan_r1; /*PreScan R1 � Analog*/
+short int prescan_r2; /*PreScan R2 � Digital*/
+int user_bitmap; /*Bitmap defining user CVs*/
+short int cenfreq; /*Center Frequency Method*/
+short int imode; /*Imaging Mode*/
+int iopt; /*Imaging Options*/
+short int pseq; /*Pulse Sequence*/
+short int pseqmode; /*Pulse Sequence Mode*/
+char psdname [33]; /*Pulse Sequence Name*/
+int psd_datetime; /*PSD Creation Date and Time*/
+char psd_iname [13];/*PSD name from inside PSD*/
+short int ctyp; /*Coil Type*/
+char cname [17]; /*Coil Name*/
+short int surfctyp; /*Surface Coil Type*/
+short int surfcext; /*Extremity Coil Flag*/
+int rawrunnum; /*RawData Run Number*/
+unsigned LONG4 cal_fldstr; /*Calibrated Field Strength (x10 uGauss)*/
+short int supp_tech; /*SAT fat/water/none*/
+float vbw; /*Variable Bandwidth (Hz)*/
+short int slquant; /*Number of slices in this scan group*/
+short int gpre; /*Graphically prescribed*/
+int intr_del; /*Interimage/interloc delay (uSec)*/
+float user0; /*User Variable 0*/
+float user1; /*User Variable 1*/
+float user2; /*User Variable 2*/
+float user3; /*User Variable 3*/
+float user4; /*User Variable 4*/
+float user5; /*User Variable 5*/
+float user6; /*User Variable 6*/
+float user7; /*User Variable 7*/
+float user8; /*User Variable 8*/
+float user9; /*User Variable 9*/
+float user10; /*User Variable 10*/
+float user11; /*User Variable 11*/
+float user12; /*User Variable 12*/
+float user13; /*User Variable 13*/
+float user14; /*User Variable 14*/
+float user15; /*User Variable 15*/
+float user16; /*User Variable 16*/
+float user17; /*User Variable 17*/
+float user18; /*User Variable 18*/
+float user19; /*User Variable 19*/
+float user20; /*User Variable 20*/
+float user21; /*User Variable 21*/
+float user22; /*User Variable 22*/
+float user23; /*Projection Angle*/
+float user24; /*Concat Sat Type Flag*/
+char im_alloc_key [13]; /*Process that allocated this record*/
+int im_lastmod; /*Date/Time of Last Change*/
+BLOCK im_verscre [2]; /*Genesis Version � Created*/
+BLOCK im_verscur [2]; /*Genesis Version � Now*/
+int im_pds_a; /*PixelData size � as stored*/
+int im_pds_c; /*PixelData size � Compressed*/
+int im_pds_u; /*PixelData size � UnCompressed*/
+unsigned LONG4 im_checksum; /*(internal use) AcqRecon record checksum*/
+ATOMIC im_archived; /*(internal use) Image Archive Flag*/
+ATOMIC im_complete; /*(internal use) Image Complete Flag*/
+short int satbits; /*Bitmap of SAT selections*/
+short int scic; /*Surface Coil Intensity Correction Flag*/
+short int satxloc1; /*R� side SAT pulse loc rel to lndmrk*/
+short int satxloc2; /*L� side SAT pulse loc rel to lndmrk*/
+short int satyloc1; /*A� side SAT pulse loc rel to lndmrk*/
+short int satyloc2; /*P� side SAT pulse loc rel to lndmrk*/
+short int satzloc1; /*S� side SAT pulse loc rel to lndmrk*/
+short int satzloc2; /*I� side SAT pulse loc rel to lndmrk*/
+short int satxthick; /*Thickness of X� axis SAT pulse*/
+short int satythick; /*Thickness of Y� axis SAT pulse*/
+short int satzthick; /*Thickness of Z� axis SAT pulse*/
+short int flax; /*Phase contrast flow axis*/
+short int venc; /*Phase contrast velocity encoding*/
+short int thk_disclmr; /*Slice Thickness*/
+short int ps_flag; /*Auto/Manual Prescan flag*/
+short int ps_status; /*Bitmap of changed values*/
+short int image_type; /*Magnitude, Phase, Imaginary, or Real*/
+short int vas_collapse; /*Collapse Image*/
+float user23n; /*User Variable 23*/
+float user24n; /*User Variable 24*/
+short int proj_alg; /*Projection Algorithm*/
+char proj_name [13]; /*Projection Algorithm Name*/
+float x_axis_rot; /*X Axis Rotation*/
+float y_axis_rot; /*Y Axis Rotation*/
+float z_axis_rot; /*Z Axis Rotation*/
+int thresh_min1; /*Lower Range of Pixels 1*/
+int thresh_max1; /*Upper Range of Pixels 1*/
+int thresh_min2; /*Lower Range of Pixels 2*/
+int thresh_max2; /*Upper Range of Pixels 2*/
+short int echo_trn_len; /*Echo Train Length for Fast Spin Echo*/
+short int frac_echo; /*Fractional Echo � Effective TE Flag*/
+short int prep_pulse; /*Preparatory Pulse Option*/
+short int cphasenum; /*Cardiac Phase Number*/
+short int var_echo; /*Variable Echo Flag*/
+char ref_img; /*Reference Image Field*/
+char sum_img; /*Summary Image Field*/
+unsigned short int img_window; /*Window Value*/
+short int img_level; /*Level Value*/
+int slop_int_1; /*Integer Slop Field 1*/
+int slop_int_2; /*Integer Slop Field 2*/
+int slop_int_3; /*Integer Slop Field 3*/
+int slop_int_4; /*Integer Slop Field 4*/
+int slop_int_5; /*Integer Slop Field 5*/
+float slop_float_1; /*Float Slop Field 1*/
+float slop_float_2; /*Float Slop Field 2*/
+float slop_float_3; /*Float Slop Field 3*/
+float slop_float_4; /*Float Slop Field 4*/
+float slop_float_5; /*Float Slop Field 5*/
+char slop_str_1 [16]; /*String Slop Field 1*/
+char slop_str_2 [16]; /*String Slop Field 2*/
+short int scanactno; /*Scan Acquisition Number*/
+short int vasflags; /*Magnitude Weighting Flag*/
+float vencscale; /*Scale Weighted Venc*/
+short int integrity; /*GE Image Integrity*/
+int fphase; /*Number Of Phases*/
+short int freq_dir; /*Frequency Direction*/
+short int vas_mode; /*Vascular Mode*/
+BLOCK image_uid [32]; /*Image Unique ID*/
+BLOCK sop_uid [32]; /*Service Obj Class Unique ID*/
+short int dont_use_1; /*This field is not used*/
+short int dont_use_2; /*This field is not used*/
+short int dont_use_3; /*This field is not used*/
+short int pscopts; /*bitmap of prescan options*/
+short int asoffsetx; /*gradient offset in X� direction*/
+short int asoffsety; /*gradient offset in Y� direction*/
+short int asoffsetz; /*gradient offset in Z� direction*/
+short int unoriginal; /*identifies image as original or unoriginal*/
+short int interleaves; /*number of EPI shots*/
+short int effechospace; /*effective echo spacing for EPI*/
+short int viewsperseg; /*views per segment*/
+short int rbpm; /*respiratory rate, breaths per min*/
+short int rtpoint; /*respiratory trigger point as percent of max.*/
+short int rcvrtype; /*type of receiver used*/
+float dbdt; /*peak rate of change of gradient field, tesla/sec*/
+float dbdtper; /*limit in units of percent of theoretical curve*/
+float estdbdtper; /*PSD estimated limit in units of percent*/
+float estdbdtts; /*PSD estimated limit in Teslas/sec*/
+float saravghead; /*Avg head SAR*/
+float neg_scanspacing; /*Negative scan spacing for overlap slices*/
+int offsetfreq; /*Offset Frequency � Mag.Transfer*/
+unsigned LONG4 user_usage_tag; /*Defines how following user CVs are to be filled in*/
+/*Default value = 0x00000000*/
+/*GE range = 0x00000001 � 0x7fffffff*/
+/*Research = 0x80000000 � 0xffffffff*/
+unsigned LONG4 user_fill_mapMSW; /*Define what process fills in the user CVs, ifcc or TIR*/
+unsigned LONG4 user_fill_mapLSW; /*Define what process fills in the user CVs, ifcc or TIR*/
+float user25; /*User Variable 25*/
+float user26; /*User Variable 26*/
+float user27; /*User Variable 27*/
+float user28; /*User Variable 28*/
+float user29; /*User Variable 29*/
+float user30; /*User Variable 30*/
+float user31; /*User Variable 31*/
+float user32; /*User Variable 32*/
+float user33; /*User Variable 33*/
+float user34; /*User Variable 34*/
+float user35; /*User Variable 35*/
+float user36; /*User Variable 36*/
+float user37; /*User Variable 37*/
+float user38; /*User Variable 38*/
+float user39; /*User Variable 39*/
+float user40; /*User Variable 40*/
+float user41; /*User Variable 41*/
+float user42; /*User Variable 42*/
+float user43; /*User Variable 43*/
+float user44; /*User Variable 44*/
+float user45; /*User Variable 45*/
+float user46; /*User Variable 46*/
+float user47; /*User Variable 47*/
+float user48; /*User Variable 48*/
+int slop_int_6; /*Integer Slop Field 6*/
+int slop_int_7; /*Integer Slop Field 7*/
+int slop_int_8; /*Integer Slop Field 8*/
+int slop_int_9; /*Integer Slop Field 9*/
+BLOCK mr_padding [32]; /*Spare Space*/
+} MRIMAGEDATATYPE ;
+
+
+typedef struct PixHdr{
+int img_magic; /* magic number */
+int img_hdr_length; /* length of pixel header in bytes, can be used as
+a byte displacement to the pixel data from
+the start of the Pixel Header*/
+int img_width; /* width (pixels) of image */
+int img_height; /* height (pixels) of image */
+int img_depth; /* depth (1, 8, 16, or 24 bits) of pixel */
+int img_compress; /* type of compression; see IC_* below
+1=IC_RECT Non� compressed, normal rectangular image.
+2=IC_PACKED Image is line length map packed.
+3=IC_COMPRESSED Image compressed via DCPM only.
+4=IC_COMPACK Image is compressed and packed. */
+int img_dwindow; /* default window setting */
+int img_dlevel; /* default level setting */
+int img_bgshade; /* background shade to use for non� image */
+int img_ovrflow; /* overflow value */
+int img_undflow; /* underflow value */
+int img_top_offset; /* number of blank lines at image top */
+int img_bot_offset; /* number of blank lines at image bottom */
+short img_version; /* version of the header structure
+and a word to maintain 32 bit alignment */
+unsigned short img_checksum; /* 16 bit end_around_carry sum of pixels */
+int img_p_id; /* a byte disp to unique image identifier */
+int img_l_id; /* byte length of unique image identifier */
+int img_p_unpack; /* a byte disp to 'unpack control' */
+int img_l_unpack; /* byte length of 'unpack control' */
+int img_p_compress; /* a byte disp to 'compression control' */
+int img_l_compress; /* byte length of 'compression control' */
+int img_p_histo; /* a byte disp to 'histogram control' */
+int img_l_histo; /* byte length of 'histogram control' */
+int img_p_text; /* a byte disp to 'text plane data' */
+int img_l_text; /* byte length of 'text plane data' */
+int img_p_graphics; /* a byte disp to 'graphics plane data' */
+int img_l_graphics; /* byte length of 'graphics plane data' */
+int img_p_dbHdr; /* a byte disp to 'data base header data' */
+int img_l_dbHdr; /* byte length of 'data base header data' */
+int img_levelOffset;/* value to add to stored Pixel Data values
+to get the correct presentation value */
+int img_p_user; /* byte displacement to user defined data */
+int img_l_user; /* byte length of user defined data */
+} PixHdr;
+
+typedef struct ImgID {
+int id_version;
+/* version number of text area */
+char id_text[80]; /* 80 character descriptive text string */
+} ImgID;
+
+#define ID_VERSION 1 /* version number of this structure */
+
+#define V_ADIN(_x) (_x >= 1 && _x <= 2)
+/* 1 �> DAS Filter Card */
+/* 2 ->> Aux */
+#define V_AUTOSCANFLAG(_x) (_x >=0 && _x <= 2)
+/* 0 ->> Autoscan off */ 
+/* 1 ->> Autoscan second */
+/* 2 ->> Autoscan all */ 
+#define V_BIOP_POS(_x) (_x == 1 || _x == 2 || _x == 4)
+/* 1 ->> Superior */ 
+/* 2 ->> Centered */ 
+/* 4 ->> Inferior */
+#define V_CALFREQ(_x) (_x >= 0 && _x <= 1)
+#define V_CALMODE(_x) (_x >= 1 && _x <= 3)
+/* 1 ->> DC Das Cal */ 
+/* 2 ->> AC Das Cal */
+/* 3 ->> No Das Cal */ 
+#define V_COMPUTETYP(_x) (_x >= 1 && _x <= 5)
+/* 1 ->> axial */
+/* 2 ->> calcheck */ 
+/* 3 ->> scout */
+/* 4 ->> ppscan */ 
+/* 5 ->> viewsvschannels */
+#define V_CONTIG(_x) (_x >= 0 && _x <= 1)  */ 
+/*~ 0 ->> No:/I */ 
+/*~ 1 ->> Yes:/C */ 
+#define V_CONTMODE(_x) (_x >= 0 && _x <= 3)
+/* 0 ->> No Contrast: */
+/* 1 ->> oral: */ 
+/* 2 ->> intravenous:+C */
+/* 3 ->> oralandintravenous:+C */ 
+#define V_CTYP(_x) (_x >= 1 && _x <= 3)
+/* 1 ->> Head */
+/* 2 ->> Body */ 
+/* 3 ->> Surface */
+#define V_DASTYP(_x) (_x >= 1 && _x <= 2)
+/* 1 ->> CDAS */ 
+/* 2 ->> EDAS */
+#define V_DATAMOD(_x) (_x >= 1 && _x <= 3)
+/* 1 ->> Raw */ 
+/* 2 ->> Offset Corrected */
+/* 3 ->> Normalized */ 
+#define V_DETECT(_x) (_x >= 1 && _x <= 2)
+/* 1 ->> Xenon Det */
+/* 2 ->> Hilight Det */ 
+#define V_ENTRY(_x) (_x >= 1 && _x <= 2)
+/* 1 ->> Head First */
+/* 2 ->> Feet First */ 
+#define V_EX_FORMAT(_x) (_x >= 0 && _x <= 14)
+/* 0 ->> Foreign */
+/* 1 ->> Genesis Image */ 
+/* 2 ->> Technicare HPS1440 */
+/* 3 ->> Technicare Delta Scan 2010 */ 
+/* 4 ->> Technicare Delta Scan 2020 */
+/* 5 ->> Technicare Delta Scan 2060 */ 
+/* 6 ->> Signa */
+/* 7 ->> CT9800 */ 
+/* 8 ->> CT9800 Q */
+/* 9 ->> CT9800 QHL */ 
+/* 10 ->> EMI_9800 */
+/* 11 ->> CT_8800_9800 */ 
+/* 12 ->> CT9600 */
+/* 13 ->> Jupiter */ 
+/* 14 ->> Zeus:CT HiSpeed Adv */
+#define V_EX_NO(_x) (_x >= 1 && _x <= 65535)
+#define V_EX_STAT(_x) (_x >= 0 && _x <= 3)
+/* 0 ->> In Patient:IN */ 
+/* 1 ->> Out Patient:OUT */
+/* 2 ->> Emergency:EM */ 
+/* 3 ->> Referral:REF */
+#define V_FILTTYP(_x) (_x >= 1 && _x <= 5)
+/* 1 ->> Air Filter */ 
+/* 2 ->> Body Filter */
+/* 3 ->> Bowtie Flat Filter:Adult Head */ 
+/* 4 ->> Flat Filter */
+/* 5 ->> High Filter:Adult Head/HF */ 
+#define V_FLAX(_x) (_x >= 0 && _x <= 7)
+/* 0 ->> FLAX_NONE */
+/* 1 ->> FLAXSI:S/I */ 
+/* 2 ->> FLAXAP:A/P */
+/* 4 ->> FLAXRL:R/L */ 
+/* 7 ->> FLAXALL:ALL */
+#define V_FPAGAIN(_x) (_x == 0 || _x == 1 || _x == 8 || _x == 64)
+/* 0 ->> auto */ 
+/* 1 ->> X1 */
+/* 8 ->> X8 */ 
+/* 64 ->> X64 */
+#define V_FRAC_ECHO(_x) (_x >= 0 && _x <= 3)
+/* 0 ->> FRACT_ECHO_OFF: */ 
+/* 1 ->> FRACT_ECHO_FRACTIONAL:Fr */
+/* 2 ->> FRACT_ECHO_EFFECTIVE:Ef */ 
+/* 3 ->> FRACT_ECHO_FRACT_EFF:FE */
+#define V_GANDIR(_x) (_x >= 1 && _x <= 2)
+/* 1 ->> Clockwise:CW */ 
+/* 2 ->> Counter Clockwise:CCW */
+#define V_GENMODE(_x) (_x >= 1 && _x <= 3)
+/* 1 ->> Surface Only */ 
+/* 2 ->> Projection Only */
+/* 3 ->> Surface and Projection */ 
+#define V_GPRE(_x) (_x >= 0 && _x <= 2)
+/* 0 ->> No GRX */
+/* 1 ->> GRX 1 localizer */ 
+/* 2 ->> GRX 2 localizers */
+#define V_IBONEFLAG(_x) (_x >= 0 && _x <= 1)
+/*~ 0 ->> No: */ 
+/*~ 1 ->> Yes:/I */
+#define V_IMODE(_x) (_x >= 1 && _x <= 8)
+/* 1 ->> Two D:2D */ 
+/* 2 ->> Three D Volume:3D */
+/* 3 ->> Three D Fourier: */ 
+/* 4 ->> Cine:Cine */
+/* 5 ->> Angiography:ANGIO */ 
+/* 6 ->> Spectroscopy:SPECT */
+/* 7 ->> Fluoroscopy:FLUOR */ 
+/* 8 ->> Research IMode:RM */
+#define V_IMSCOUTTYPE(_x) (_x >= 1 && _x <= 2)
+/* 1 ->> Scout Vertical */ 
+/* 2 ->> Scout Horizontal */
+#define V_IM_NO(_x) (_x >= 1 && _x <= 999)
+#define V_IMAGE_TYPE(_x) (_x >= 0 && _x <= 3)
+/* 0 ->> IMAGE_TYPE_0 */ 
+/* 1 ->> IMAGE_TYPE_1:PHASE */
+/* 2 ->> IMAGE_TYPE_2:REAL */ 
+/* 3 ->> IMAGE_TYPE_3:IMAGINARY */
+#define V_IOPT(_x) (_x >= 0 && _x <= 1073741824)
+/*~ 0 ->> No: */ 
+/* 1 ->> EG */
+/* 2 ->> RESP */ 
+/* 4 ->> RC */
+/* 8 ->> FC */ 
+/* 16 ->> CL */
+/* 32 ->> ST */ 
+/* 64 ->> PG */
+/* 128 ->> NP */ 
+/* 256 ->> NF */
+/* 512 ->> RT */ 
+/* 1024 ->> VB */
+/* 2048 ->> ED */ 
+/* 4096 ->> PM */
+/* 8192 ->> SQ */ 
+/* 16384 ->> cs */
+/* 32768 ->> MP */ 
+/* 65536 ->> SQPIX */
+/* 131072 ->> MT */ 
+/* 262144 ->> RAMPED_SI */
+/* 524288 ->> RAMPED_IS */ 
+/* 1048576 ->> RAMPED_AP */
+/* 2097152 ->> RAMPED_PA */ 
+/* 4194304 ->> RAMPED_RL */
+/* 8388608 ->> RAMPED_LR */ 
+/* 16777216 ->> FC_FREQ_AXIS */
+/* 33554432 ->> FC_SLICE_AXIS */ 
+/* 67108864 ->> EPI */
+/* 134217728 ->> TRF */ 
+/* 268435456 ->> RTR */
+/* 536870912 ->> FT */ 
+/* 1073741824 ->> SS_FSE */
+#define V_OUTSRC(_x) (_x >= 1 && _x <= 2)
+/* 1 ->> AID */ 
+/* 2 ->> XM */
+#define V_OVERRNG_CORR(_x) (_x == 0 || _x == 1)
+/*~ 0 ->> No: */ 
+/*~ 1 ->> Yes: */
+#define V_PATIAN(_x) (_x >= 0 && _x <= 3)
+/* 0 ->> Years:Y */ 
+/* 1 ->> Months:M */
+/* 2 ->> Days:D */ 
+/* 3 ->> Weeks:W */
+#define V_PATSEX(_x) (_x >= 1 && _x <= 2)
+/* 1 ->> Male:M */ 
+/* 2 ->> Female:F */
+#define V_PERISFLAG(_x) (_x >= 0 && _x <= 1)
+/*~ 0 ->> No: */ 
+/*~ 1 ->> Yes:/P */
+#define V_PHANTSIZE(_x) (_x >= 1 && _x <= 4)
+/* 1 ->> No Psize */ 
+/* 2 ->> Small Psize */
+/* 3 ->> Medium Psize */ 
+/* 4 ->> Large Psize */
+#define V_PHANTTYP(_x) (_x >= 1 && _x <= 4)
+/* 1 ->> None */ 
+/* 2 ->> Air */
+/* 3 ->> Water */ 
+/* 4 ->> Poly */
+#define V_PLANE(_x) (_x == 1 || _x == 2 || _x == 4 || _x == 8 || _x == 16 || _x == 18 || _x == 20 || _x == 24 || _x == 32 || _x == 64 || _x == 128 || _x == 256)
+/* 1 ->> Scout Plane:SCT */ 
+/* 2 ->> Axial Plane:Ax */
+/* 4 ->> Sagittal Plane:Sag */ 
+/* 8 ->> Coronal Plane:Cor */
+/* 16 ->> Oblique Plane:O */ 
+/* 18 ->> Oblique Axial Plane:OAx */
+/* 20 ->> Oblique Sagittal Plane:OSag */ 
+/* 24 ->> Oblique Coronal Plane:OCor */
+/* 32 ->> ParAxial:PAX */ 
+/* 64 ->> Reformatted Plane:RFMT */
+/* 128 ->> Projected Plane:PJN */ 
+/* 256 ->> Mixed Plane:MIXED */
+#define V_POSITION(_x) (_x == 1 || _x == 2 || _x == 4 || _x == 8)
+/* 1 ->> Supine */ 
+/* 2 ->> Prone */
+/* 4 ->> Decubitus Left */ 
+/* 8 ->> Decubitus Right */
+#define V_PREP_PULSE(_x) (_x >= 0 && _x <= 2) 
+/* 0 ->> PREP_PULSE_NONE: */
+/* 1 ->> PREP_PULSE_IR:IR */ 
+/* 2 ->> PREP_PULSE_DE:DE */
+#define V_PROJ_ALG(_x) (_x >= 0 && _x <= 3)
+/* 0 ->> NO_PROJ_ALG: */ 
+/* 1 ->> PROTOTYPE_ALG: */
+/* 2 ->> MIN_PIXEL_ALG:Min */ 
+/* 3 ->> MAX_PIXEL_ALG:Max */
+#define V_PS_FLAG(_x) (_x >= 0 && _x <= 5)
+/* 0 ->> PS_FLAG_NONE: */ 
+/* 1 ->> PS_FLAG_AF:a */
+/* 2 ->> PS_FLAG_AS:A */ 
+/* 3 ->> PS_FLAG_M:M */
+/* 4 ->> PS_FLAG_AFM:aM */ 
+/* 5 ->> PS_FLAG_ASM:AM */
+#define V_PS_STATUS(_x) (_x == 1 || _x == 2 || _x == 4 || _x == 8)
+/* 1 ->> PS_STATUS_CF:CF */ 
+/* 2 ->> PS_STATUS_TA:TA */
+/* 4 ->> PS_STATUS_R1:R1 */ 
+/* 8 ->> PS_STATUS_R2:R2 */
+#define V_PSC(_x) (_x ==0 || _x ==1)
+/*~ 0 ->> No: */ 
+/*~ 1 ->> Yes: */
+#define V_PSEQ(_x) (_x >= 0 && _x <= 25)
+/* 0 ->> SE */ 
+/* 1 ->> IR */
+/* 2 ->> RM:RM: */ 
+/* 3 ->> RMGE: */
+/* 4 ->> GRE:GR */ 
+/* 5 ->> MPGR */
+/* 6 ->> MPIRS:IR/s */ 
+/* 7 ->> MPIRI:IR */
+/* 8 ->> VOGRE:3D/GR */ 
+/* 9 ->> CINEGRE:Cine/GR */
+/* 10 ->> SPGR */ 
+/* 11 ->> SSFP */
+/* 12 ->> TF:TOF */ 
+/* 13 ->> PC */
+/* 14 ->> CINSPGR:Cine/SPGR */ 
+/* 15 ->> TOFGR:TOF/GR */
+/* 16 ->> TOFSPGR:TOF/SPGR */ 
+/* 17 ->> PCGR:PC/GR */
+/* 18 ->> PCSPGR:PC/SPGR */ 
+/* 19 ->> FSE */
+/* 20 ->> FGR */ 
+/* 21 ->> FMPGR */
+/* 22 ->> FSPGR */ 
+/* 23 ->> FMPSPGR */
+/* 24 ->> SPECT */ 
+/* 25 ->> PSEQ_MIXED:MIXED */
+#define V_PSEQMODE(_x) (_x >= 1 && _x <= 3)
+/* 1 ->> Product */ 
+/* 2 ->> Research Mode */
+/* 3 ->> Research Mode GE */ 
+#define V_RECONALG(_x) (_x == 1 || _x == 2 || _x == 4 || _x == 8 || _x == 16 || _x == 32 || _x == 64 || _x == 128)
+/* 1 ->> smooth:SMTH */
+/* 2 ->> soft:SOFT */ 
+/* 4 ->> stand:STND */
+/* 8 ->> detail:DETL */ 
+/* 16 ->> bone:BONE */
+/* 32 ->> edge:EDGE */ 
+/* 64 ->> sharp:SHRP */
+/* 128 ->> experimental 2:EXP2 */ 
+#define V_RECONDATASET(_x) (_x == 1 || _x == 2 || _x == 4 || _x == 8)
+/* 1 ->> half scan views */
+/* 2 ->> normal scan views */ 
+/* 4 ->> over scan views */
+/* 8 ->> variable views */ 
+#define V_REF_CHAN(_x) (_x == 0 || _x == 1)
+/*~ 0 ->> no: */
+/*~ 1 ->> yes: */ 
+#define V_REGXM(_x) (_x >= 1 && _x <= 2)
+/* 1 ->> hold */
+/* 2 ->> shift */ 
+#define V_ROTTYP(_x) (_x == 1 || _x == 2 || _x == 4 || _x == 8)
+/* 1 ->> half scan:rotating */
+/* 2 ->> normal scan:rotating */ 
+/* 4 ->> over scan:rotating */
+/* 8 ->> stationary:stationary */ 
+#define V_ROTORSPEED(_x) (_x >= 1 && _x <= 4)
+/* 1 ->> Rotor off */
+/* 2 ->> Rotor low */ 
+/* 3 ->> Rotor medium */
+/* 4 ->> Rotor high */ 
+#define V_SATBITS(_x) (_x >= 0 && _x <= 11)
+/* 0 ->> SATBITS_S:S */
+/* 1 ->> SATBITS_I:I */ 
+/* 2 ->> SATBITS_R:R */
+/* 4 ->> Scout mode */ 
+/* 8 ->> Axial Xron mode */
+/* 16 ->> Axial Xroff mode */ 
+/* 32 ->> Static Xron mode */
+/* 64 ->> Static Xroff mode */ 
+/* 128 ->> Tube Heat mode */
+/* 256 ->> Das mode */ 
+/* 512 ->> Tube Cal mode */
+/* 1024 ->> Biopsy mode */ 
+/* 2048 ->> Cine mode */
+/* 4096 ->> Helical mode */ 
+/* 8192 ->> Rotgencal mode */
+#define V_SCAN_TYPE(_x) (_x >= 1 && _x <= 3)
+/* 1 ->> Scout Scan:SCT */ 
+/* 2 ->> Axial Scan:AX */
+/* 3 ->> Screensave Scan:SS */ 
+#define V_SCIC(_x) (_x == 0 || _x == 1)
+/* 0 ->> SCIC_OFF */
+/* 1 ->> SCIC_ON:IIC */ 
+#define V_SE_NO(_x) (_x >= 1 && _x <= 999)
+#define V_SE_TYP(_x) (_x >= 1 && _x <= 9)
+/* 1 ->> Prospective:PROSP */
+/* 2 ->> Retrospective:RETRO */ 
+/* 3 ->> Scout Series:SCOUT */
+/* 4 ->> Reformatted:REFMT */ 
+/* 5 ->> Scrnsave:SSAVE */
+/* 6 ->> Xenon:XENON */ 
+/* 7 ->> Three D:3D */
+/* 8 ->> Service:SERV */ 
+/* 9 ->> Projected:PJN */
+#define V_SFOVTYP(_x) (_x == 1 || _x == 2 || _x == 4 || _x == 8 || _x == 16 || _x == 32) 
+/* 1 ->> Ped Head */
+/* 2 ->> Adult Head */ 
+/* 4 ->> Small */
+/* 8 ->> Medium */ 
+/* 16 ->> Large */
+/* 32 ->> No Sfovtype */ 
+#define V_SPOT_POS(_x) (_x >= 1 && _x <= 3)
+/* 1 ->> spot left */
+/* 2 ->> spot center */ 
+/* 3 ->> spot right */
+#define V_SPOT_SIZE(_x) (_x >= 1 && _x <= 2) 
+/* 1 ->> small spot */
+/* 2 ->> large spot */ 
+#define V_SUPP_TECH(_x) (_x >= 0 && _x <= 2)
+/* 0 ->> SUPP_NONE: */
+/* 1 ->> SUPP_FAT:F */ 
+/* 2 ->> SUPP_WATER:W */
+#define V_SWAPPF(_x) (_x >= 0 && _x <= 1)
+/*~ 0 ->> No: */ 
+/*~ 1 ->> Yes:SPF */
+#define V_THK_DISCLMR(_x) (_x == 0 || _x == 1)
+/* 0 ->> THK_DISCLMR_NO: */ 
+/* 1 ->> THK_DISCLMR_YES:& */
+#define V_TRAUMA(_x) (_x == 0 || _x == 1)
+/* 0 ->> Trauma flag off */ 
+/* 1 ->> Trauma flag on */
+#define V_TRIGMODE(_x) (_x >= 1 && _x <= 4)
+/* 1 ->> Normal Trigger:XTTX */ 
+/* 2 ->> Xrayoff Trigger:TT */
+/* 3 ->> TXXT */ 
+/* 4 ->> XXTT */
+#define V_TRIGSRC(_x) (_x >= 1 && _x <= 2)
+/* 1 ->> internal */ 
+/* 2 ->> external */
+#define V_TUBETYP(_x) (_x >= 0 && _x <= 14)
+/* 0 ->> MX100_TUBE */ 
+/* 1 ->> MX125_TUBE */
+/* 2 ->> TT9800:9800_TUBE */ 
+/* 3 ->> TT9100:9100_TUBE */
+/* 4 ->> HPRI_TUBE */ 
+/* 5 ->> HPRII_TUBE */
+/* 6 ->> ADV_TUBE */ 
+/* 6 ->> ADV650_TUBE */
+/* 7 ->> ADV681_TUBE */ 
+/* 8 ->> ST2000CT_6_TUBE */
+/* 9 ->> ST2000CT_10_TUBE */ 
+/* 12 ->> MX_135CT_TUBE */
+/* 13 ->> MX_165CT_TUBE */ 
+/* 14 ->> MX_165CT_I_TUBE */
+#define V_VAR_ECHO(_x) (_x == 0 || _x == 1)
+/* 0 ->> VAR_ECHO_NO: */ 
+/* 1 ->> VAR_ECHO_YES:/V */
+#define V_VAS_COLLAPSE(_x) (_x >= 0 && _x <= 7)
+/* 0 ->> VAS_COLLAPSE_OFF */ 
+/* 1 ->> VAS_COLLAPSE_ON_1:COL */
+/* 2 ->> VAS_COLLAPSE_ON_2:MAG */ 
+/* 3 ->> VAS_COLLAPSE_ON_3:R/L */
+/* 4 ->> VAS_COLLAPSE_ON_4:A/P */ 
+/* 5 ->> VAS_COLLAPSE_ON_5:S/I */
+/* 6 ->> VAS_COLLAPSE_ON_6:PJN */ 
+/* 7 ->> VAS_COLLAPSE_ON_7:ALL */
+
+
+/******************************************************************************
+
+Utils  Lawrence Staib 10/90, 2/92
+
+******************************************************************************/
+
+struct anaimagedata{/* data associated with an image */
+  short zsize,ysize,xsize,tsize;
+  float zasp,yasp,xasp;
+  float zpix,ypix,xpix;
+  int minpix,maxpix;
+  int trueminpix,truemaxpix;
+  char orient;
+  int datatype;
+} ;
+
+
+int writeanahdr(const char* filename,anaimagedata *imdata,int bits);
+int readanahdr(const char* filename, anaimagedata *imdata);
+int readlxhdr(const char* filename, anaimagedata *imdata);
+char *eatsuffix(const char* filename);
+char *nothisextension(const char* filename,const char* extension);
+
+/******************************************************************************
+
+Xenios Papademetris 8/95 - Addition of PXImage code
+
+******************************************************************************/
+
+int  Anagetparams(const char* filename,int& x,int& y,int &z);
+int  Anagetparams(const char* filename,int& x,int& y,int &z,int &bytes);
+int  Anagetparams(const char* filename,int& x,int& y,int &z,int &t,int &bytes);
+
+/******************************************************************************
+
+Xenios Papademetris 8/95 - Addition of PXImage code
+
+Filename Manipulation Utilities
+
+******************************************************************************/
+
+char* anaextractpath(const char* fname);
+char* anaeatsuffix(const char* fname);
+char* anaeatpath(const char* fname);
+char* anacreateheaderfilename(const char* fname);
+char* anacreateimagefilename(const char* fname);
+char* anacreatefilename(const char* fname,const char* wanted,const char* unwanted);
+
+
+/* *****************************************************************
+
+String Stuff 4 Jan 2000 to accomodate zlib compression library
+
+***************************************************************** */
+
+// Definitions of Boolean Type
+#ifndef PXBOOL
+  #ifndef _WIN32
+    enum PXBool { PXFalse = 0, PXTrue };
+  #else
+    #define PXBool bool
+    #define PXFalse false
+    #define PXTrue true
+    #endif
+  #define PXBOOL 1
+#endif
+
+gzFile ZEXPORT gzsuffixopen (const char* path, const char* mode,int complevel=0);
+
+int gzfindstringinstring(const char* orig,const char* lookfor);
+int stringskipspace(const char* line,int startpos);
+int stringskipnumber(const char* line,int startpos);
+int   getgzstreaminteger(gzFile fin);
+float getgzstreamfloat(gzFile fin);
+
+ 
+// Create backup file for file in fname 
+int anabackupfile(const char* fname);
+
+
+// Byte-Swapping Stuff
+// --------------------
+int pxanaswapint(int input);
+float pxanaswapfloat(float input);
+double pxanaswapdouble(double input);
+short pxanaswapshort(short input);
+
+
+// -------------------------------------------------------------
+//  Quantization -- quantize numbers to specified decimal places 
+// -------------------------------------------------------------
+float  quantize(float a,int dp=4);
+double quantize(double a,int dp=4);
+
+// -------------------------
+//  Return Maxium or Minimum
+// -------------------------
+float Fmax(float a,float b);
+float Fmin(float a,float b);
+int   Imax(int a,int b);
+int   Imin(int a,int b);
+
+float Frange(float a,float minv,float maxv);
+float FcyclicDistance(float p1,float p2,float circum);
+int   Irange(int   a,int   minv,int   maxv);
+int   Icyclic(int v,int np);
+float Fcyclic(float v, float maxv);
+int   Ipowerof2(int v);
+// --------------------------
+// Point Comparisons
+// --------------------------
+float Fdist(float x1,float y1,float z1,float x2,float y2,float z2);
+float Fsqdist(float x1,float y1,float z1,float x2,float y2,float z2);
+int   Fsamepoint(float x1,float y1,float z1,float x2,float y2,float z2,float maxdist=0.01);
+
+namespace bioimagesuite_legacy
+{
+  // Empty for now
+}
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/tnt/jama_cholesky.h b/bioimagesuite30_src/numerics/tnt/jama_cholesky.h
new file mode 100644
index 0000000..b30f6fb
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/jama_cholesky.h
@@ -0,0 +1,286 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef JAMA_CHOLESKY_H
+#define JAMA_CHOLESKY_H
+
+#include "math.h"
+	/* needed for sqrt() below. */
+
+
+namespace JAMA
+{
+
+using namespace TNT;
+
+/** 
+   <P>
+   For a symmetric, positive definite matrix A, this function
+   computes the Cholesky factorization, i.e. it computes a lower 
+   triangular matrix L such that A = L*L'.
+   If the matrix is not symmetric or positive definite, the function
+   computes only a partial decomposition.  This can be tested with
+   the is_spd() flag.
+
+   <p>Typical usage looks like:
+   <pre>
+	Array2D<double> A(n,n);
+	Array2D<double> L;
+
+	 ... 
+
+	Cholesky<double> chol(A);
+
+	if (chol.is_spd())
+		L = chol.getL();
+		
+  	else
+		cout << "factorization was not complete.\n";
+
+	</pre>
+
+
+   <p>
+	(Adapted from JAMA, a Java Matrix Library, developed by jointly 
+	by the Mathworks and NIST; see  http://math.nist.gov/javanumerics/jama).
+
+   */
+
+template <class Real>
+class Cholesky
+{
+	Array2D<Real> L_;		// lower triangular factor
+	int isspd;				// 1 if matrix to be factored was SPD
+
+public:
+
+	Cholesky();
+	Cholesky(const Array2D<Real> &A);
+	Array2D<Real> getL() const;
+	Array1D<Real> solve(const Array1D<Real> &B);
+	Array2D<Real> solve(const Array2D<Real> &B);
+	int is_spd() const;
+
+};
+
+template <class Real>
+Cholesky<Real>::Cholesky() : L_(0,0), isspd(0) {}
+
+/**
+	@return 1, if original matrix to be factored was symmetric 
+		positive-definite (SPD).
+*/
+template <class Real>
+int Cholesky<Real>::is_spd() const
+{
+	return isspd;
+}
+
+/**
+	@return the lower triangular factor, L, such that L*L'=A.
+*/
+template <class Real>
+Array2D<Real> Cholesky<Real>::getL() const
+{
+	return L_;
+}
+
+/**
+	Constructs a lower triangular matrix L, such that L*L'= A.
+	If A is not symmetric positive-definite (SPD), only a
+	partial factorization is performed.  If is_spd()
+	evalutate true (1) then the factorizaiton was successful.
+*/
+template <class Real>
+Cholesky<Real>::Cholesky(const Array2D<Real> &A)
+{
+
+
+   	int m = A.dim1();
+	int n = A.dim2();
+	
+	isspd = (m == n);
+
+	if (m != n)
+	{
+		L_ = Array2D<Real>(0,0);
+		return;
+	}
+
+	L_ = Array2D<Real>(n,n);
+
+
+      // Main loop.
+     for (int j = 0; j < n; j++) 
+	 {
+        double d = 0.0;
+        for (int k = 0; k < j; k++) 
+		{
+            Real s = 0.0;
+            for (int i = 0; i < k; i++) 
+			{
+               s += L_[k][i]*L_[j][i];
+            }
+            L_[j][k] = s = (A[j][k] - s)/L_[k][k];
+            d = d + s*s;
+            isspd = isspd && (A[k][j] == A[j][k]); 
+         }
+         d = A[j][j] - d;
+         isspd = isspd && (d > 0.0);
+         L_[j][j] = sqrt(d > 0.0 ? d : 0.0);
+         for (int k = j+1; k < n; k++) 
+		 {
+            L_[j][k] = 0.0;
+         }
+	}
+}
+
+/**
+
+	Solve a linear system A*x = b, using the previously computed
+	cholesky factorization of A: L*L'.
+
+   @param  B   A Matrix with as many rows as A and any number of columns.
+   @return     x so that L*L'*x = b.  If b is nonconformat, or if A
+   				was not symmetric posidtive definite, a null (0x0)
+   						array is returned.
+*/
+template <class Real>
+Array1D<Real> Cholesky<Real>::solve(const Array1D<Real> &b)
+{
+	int n = L_.dim1();
+	if (b.dim1() != n)
+		return Array1D<Real>();
+
+
+	Array1D<Real> x = b.copy();
+
+
+      // Solve L*y = b;
+      for (int k = 0; k < n; k++) 
+	  {
+         for (int i = 0; i < k; i++) 
+               x[k] -= x[i]*L_[k][i];
+		 x[k] /= L_[k][k];
+		
+      }
+
+      // Solve L'*X = Y;
+      for (int k = n-1; k >= 0; k--) 
+	  {
+         for (int i = k+1; i < n; i++) 
+               x[k] -= x[i]*L_[i][k];
+         x[k] /= L_[k][k];
+      }
+
+	return x;
+}
+
+
+/**
+
+	Solve a linear system A*X = B, using the previously computed
+	cholesky factorization of A: L*L'.
+
+   @param  B   A Matrix with as many rows as A and any number of columns.
+   @return     X so that L*L'*X = B.  If B is nonconformat, or if A
+   				was not symmetric posidtive definite, a null (0x0)
+   						array is returned.
+*/
+template <class Real>
+Array2D<Real> Cholesky<Real>::solve(const Array2D<Real> &B)
+{
+	int n = L_.dim1();
+	if (B.dim1() != n)
+		return Array2D<Real>();
+
+
+	Array2D<Real> X = B.copy();
+	int nx = B.dim2();
+
+// Cleve's original code
+#if 0
+      // Solve L*Y = B;
+      for (int k = 0; k < n; k++) {
+         for (int i = k+1; i < n; i++) {
+            for (int j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*L_[k][i];
+            }
+         }
+         for (int j = 0; j < nx; j++) {
+            X[k][j] /= L_[k][k];
+         }
+      }
+
+      // Solve L'*X = Y;
+      for (int k = n-1; k >= 0; k--) {
+         for (int j = 0; j < nx; j++) {
+            X[k][j] /= L_[k][k];
+         }
+         for (int i = 0; i < k; i++) {
+            for (int j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*L_[k][i];
+            }
+         }
+      }
+#endif
+
+
+      // Solve L*y = b;
+  	  for (int j=0; j< nx; j++)
+	  {
+      	for (int k = 0; k < n; k++) 
+		{
+			for (int i = 0; i < k; i++) 
+               X[k][j] -= X[i][j]*L_[k][i];
+		    X[k][j] /= L_[k][k];
+		 }
+      }
+
+      // Solve L'*X = Y;
+     for (int j=0; j<nx; j++)
+	 {
+      	for (int k = n-1; k >= 0; k--) 
+	  	{
+         	for (int i = k+1; i < n; i++) 
+               X[k][j] -= X[i][j]*L_[i][k];
+         	X[k][j] /= L_[k][k];
+		}
+      }
+
+
+
+	return X;
+}
+
+
+}
+// namespace JAMA
+
+#endif
+// JAMA_CHOLESKY_H
+
diff --git a/bioimagesuite30_src/numerics/tnt/jama_eig.h b/bioimagesuite30_src/numerics/tnt/jama_eig.h
new file mode 100644
index 0000000..57e4a23
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/jama_eig.h
@@ -0,0 +1,1053 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef JAMA_EIG_H
+#define JAMA_EIG_H
+
+
+#include "tnt_array1d.h"
+#include "tnt_array2d.h"
+#include "tnt_math_utils.h"
+
+
+using namespace TNT;
+
+
+namespace JAMA
+{
+
+/** 
+
+    Computes eigenvalues and eigenvectors of a real (non-complex)
+    matrix. 
+<P>
+    If A is symmetric, then A = V*D*V' where the eigenvalue matrix D is
+    diagonal and the eigenvector matrix V is orthogonal. That is,
+	the diagonal values of D are the eigenvalues, and
+    V*V' = I, where I is the identity matrix.  The columns of V 
+    represent the eigenvectors in the sense that A*V = V*D.
+    
+<P>
+    If A is not symmetric, then the eigenvalue matrix D is block diagonal
+    with the real eigenvalues in 1-by-1 blocks and any complex eigenvalues,
+    a + i*b, in 2-by-2 blocks, [a, b; -b, a].  That is, if the complex
+    eigenvalues look like
+<pre>
+
+          u + iv     .        .          .      .    .
+            .      u - iv     .          .      .    .
+            .        .      a + ib       .      .    .
+            .        .        .        a - ib   .    .
+            .        .        .          .      x    .
+            .        .        .          .      .    y
+</pre>
+        then D looks like
+<pre>
+
+            u        v        .          .      .    .
+           -v        u        .          .      .    . 
+            .        .        a          b      .    .
+            .        .       -b          a      .    .
+            .        .        .          .      x    .
+            .        .        .          .      .    y
+</pre>
+    This keeps V a real matrix in both symmetric and non-symmetric
+    cases, and A*V = V*D.
+    
+    
+    
+    <p>
+    The matrix V may be badly
+    conditioned, or even singular, so the validity of the equation
+    A = V*D*inverse(V) depends upon the condition number of V.
+
+   <p>
+	(Adapted from JAMA, a Java Matrix Library, developed by jointly 
+	by the Mathworks and NIST; see  http://math.nist.gov/javanumerics/jama).
+**/
+
+template <class Real>
+class Eigenvalue
+{
+
+
+   /** Row and column dimension (square matrix).  */
+    int n;
+
+   int issymmetric; /* boolean*/
+
+   /** Arrays for internal storage of eigenvalues. */
+
+   TNT::Array1D<Real> d;         /* real part */
+   TNT::Array1D<Real> e;         /* img part */
+
+   /** Array for internal storage of eigenvectors. */
+    TNT::Array2D<Real> V;
+
+   /** Array for internal storage of nonsymmetric Hessenberg form.
+   @serial internal storage of nonsymmetric Hessenberg form.
+   */
+   TNT::Array2D<Real> H;
+   
+
+   /** Working storage for nonsymmetric algorithm.
+   @serial working storage for nonsymmetric algorithm.
+   */
+   TNT::Array1D<Real> ort;
+
+
+   // Symmetric Householder reduction to tridiagonal form.
+
+   void tred2() {
+
+   //  This is derived from the Algol procedures tred2 by
+   //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+   //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+   //  Fortran subroutine in EISPACK.
+
+      for (int j = 0; j < n; j++) {
+         d[j] = V[n-1][j];
+      }
+
+      // Householder reduction to tridiagonal form.
+   
+      for (int i = n-1; i > 0; i--) {
+   
+         // Scale to avoid under/overflow.
+   
+         Real scale = 0.0;
+         Real h = 0.0;
+         for (int k = 0; k < i; k++) {
+            scale = scale + abs(d[k]);
+         }
+         if (scale == 0.0) {
+            e[i] = d[i-1];
+            for (int j = 0; j < i; j++) {
+               d[j] = V[i-1][j];
+               V[i][j] = 0.0;
+               V[j][i] = 0.0;
+            }
+         } else {
+   
+            // Generate Householder vector.
+   
+            for (int k = 0; k < i; k++) {
+               d[k] /= scale;
+               h += d[k] * d[k];
+            }
+            Real f = d[i-1];
+            Real g = sqrt(h);
+            if (f > 0) {
+               g = -g;
+            }
+            e[i] = scale * g;
+            h = h - f * g;
+            d[i-1] = f - g;
+            for (int j = 0; j < i; j++) {
+               e[j] = 0.0;
+            }
+   
+            // Apply similarity transformation to remaining columns.
+   
+            for (int j = 0; j < i; j++) {
+               f = d[j];
+               V[j][i] = f;
+               g = e[j] + V[j][j] * f;
+               for (int k = j+1; k <= i-1; k++) {
+                  g += V[k][j] * d[k];
+                  e[k] += V[k][j] * f;
+               }
+               e[j] = g;
+            }
+            f = 0.0;
+            for (int j = 0; j < i; j++) {
+               e[j] /= h;
+               f += e[j] * d[j];
+            }
+            Real hh = f / (h + h);
+            for (int j = 0; j < i; j++) {
+               e[j] -= hh * d[j];
+            }
+            for (int j = 0; j < i; j++) {
+               f = d[j];
+               g = e[j];
+               for (int k = j; k <= i-1; k++) {
+                  V[k][j] -= (f * e[k] + g * d[k]);
+               }
+               d[j] = V[i-1][j];
+               V[i][j] = 0.0;
+            }
+         }
+         d[i] = h;
+      }
+   
+      // Accumulate transformations.
+   
+      for (int i = 0; i < n-1; i++) {
+         V[n-1][i] = V[i][i];
+         V[i][i] = 1.0;
+         Real h = d[i+1];
+         if (h != 0.0) {
+            for (int k = 0; k <= i; k++) {
+               d[k] = V[k][i+1] / h;
+            }
+            for (int j = 0; j <= i; j++) {
+               Real g = 0.0;
+               for (int k = 0; k <= i; k++) {
+                  g += V[k][i+1] * V[k][j];
+               }
+               for (int k = 0; k <= i; k++) {
+                  V[k][j] -= g * d[k];
+               }
+            }
+         }
+         for (int k = 0; k <= i; k++) {
+            V[k][i+1] = 0.0;
+         }
+      }
+      for (int j = 0; j < n; j++) {
+         d[j] = V[n-1][j];
+         V[n-1][j] = 0.0;
+      }
+      V[n-1][n-1] = 1.0;
+      e[0] = 0.0;
+   } 
+
+   // Symmetric tridiagonal QL algorithm.
+   
+   void tql2 () {
+
+   //  This is derived from the Algol procedures tql2, by
+   //  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+   //  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+   //  Fortran subroutine in EISPACK.
+   
+      for (int i = 1; i < n; i++) {
+         e[i-1] = e[i];
+      }
+      e[n-1] = 0.0;
+   
+      Real f = 0.0;
+      Real tst1 = 0.0;
+      Real eps = pow(2.0,-52.0);
+      for (int l = 0; l < n; l++) {
+
+         // Find small subdiagonal element
+   
+         tst1 = TNT::max(tst1,abs(d[l]) + abs(e[l]));
+         int m = l;
+
+        // Original while-loop from Java code
+         while (m < n) {
+            if (abs(e[m]) <= eps*tst1) {
+               break;
+            }
+            m++;
+         }
+
+   
+         // If m == l, d[l] is an eigenvalue,
+         // otherwise, iterate.
+   
+         if (m > l) {
+            int iter = 0;
+            do {
+               iter = iter + 1;  // (Could check iteration count here.)
+   
+               // Compute implicit shift
+   
+               Real g = d[l];
+               Real p = (d[l+1] - g) / (2.0 * e[l]);
+               Real r = hypot(p,1.0);
+               if (p < 0) {
+                  r = -r;
+               }
+               d[l] = e[l] / (p + r);
+               d[l+1] = e[l] * (p + r);
+               Real dl1 = d[l+1];
+               Real h = g - d[l];
+               for (int i = l+2; i < n; i++) {
+                  d[i] -= h;
+               }
+               f = f + h;
+   
+               // Implicit QL transformation.
+   
+               p = d[m];
+               Real c = 1.0;
+               Real c2 = c;
+               Real c3 = c;
+               Real el1 = e[l+1];
+               Real s = 0.0;
+               Real s2 = 0.0;
+               for (int i = m-1; i >= l; i--) {
+                  c3 = c2;
+                  c2 = c;
+                  s2 = s;
+                  g = c * e[i];
+                  h = c * p;
+                  r = hypot(p,e[i]);
+                  e[i+1] = s * r;
+                  s = e[i] / r;
+                  c = p / r;
+                  p = c * d[i] - s * g;
+                  d[i+1] = h + s * (c * g + s * d[i]);
+   
+                  // Accumulate transformation.
+   
+                  for (int k = 0; k < n; k++) {
+                     h = V[k][i+1];
+                     V[k][i+1] = s * V[k][i] + c * h;
+                     V[k][i] = c * V[k][i] - s * h;
+                  }
+               }
+               p = -s * s2 * c3 * el1 * e[l] / dl1;
+               e[l] = s * p;
+               d[l] = c * p;
+   
+               // Check for convergence.
+   
+            } while (abs(e[l]) > eps*tst1);
+         }
+         d[l] = d[l] + f;
+         e[l] = 0.0;
+      }
+     
+      // Sort eigenvalues and corresponding vectors.
+   
+      for (int i = 0; i < n-1; i++) {
+         int k = i;
+         Real p = d[i];
+         for (int j = i+1; j < n; j++) {
+            if (d[j] < p) {
+               k = j;
+               p = d[j];
+            }
+         }
+         if (k != i) {
+            d[k] = d[i];
+            d[i] = p;
+            for (int j = 0; j < n; j++) {
+               p = V[j][i];
+               V[j][i] = V[j][k];
+               V[j][k] = p;
+            }
+         }
+      }
+   }
+
+   // Nonsymmetric reduction to Hessenberg form.
+
+   void orthes () {
+   
+      //  This is derived from the Algol procedures orthes and ortran,
+      //  by Martin and Wilkinson, Handbook for Auto. Comp.,
+      //  Vol.ii-Linear Algebra, and the corresponding
+      //  Fortran subroutines in EISPACK.
+   
+      int low = 0;
+      int high = n-1;
+   
+      for (int m = low+1; m <= high-1; m++) {
+   
+         // Scale column.
+   
+         Real scale = 0.0;
+         for (int i = m; i <= high; i++) {
+            scale = scale + abs(H[i][m-1]);
+         }
+         if (scale != 0.0) {
+   
+            // Compute Householder transformation.
+   
+            Real h = 0.0;
+            for (int i = high; i >= m; i--) {
+               ort[i] = H[i][m-1]/scale;
+               h += ort[i] * ort[i];
+            }
+            Real g = sqrt(h);
+            if (ort[m] > 0) {
+               g = -g;
+            }
+            h = h - ort[m] * g;
+            ort[m] = ort[m] - g;
+   
+            // Apply Householder similarity transformation
+            // H = (I-u*u'/h)*H*(I-u*u')/h)
+   
+            for (int j = m; j < n; j++) {
+               Real f = 0.0;
+               for (int i = high; i >= m; i--) {
+                  f += ort[i]*H[i][j];
+               }
+               f = f/h;
+               for (int i = m; i <= high; i++) {
+                  H[i][j] -= f*ort[i];
+               }
+           }
+   
+           for (int i = 0; i <= high; i++) {
+               Real f = 0.0;
+               for (int j = high; j >= m; j--) {
+                  f += ort[j]*H[i][j];
+               }
+               f = f/h;
+               for (int j = m; j <= high; j++) {
+                  H[i][j] -= f*ort[j];
+               }
+            }
+            ort[m] = scale*ort[m];
+            H[m][m-1] = scale*g;
+         }
+      }
+   
+      // Accumulate transformations (Algol's ortran).
+
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            V[i][j] = (i == j ? 1.0 : 0.0);
+         }
+      }
+
+      for (int m = high-1; m >= low+1; m--) {
+         if (H[m][m-1] != 0.0) {
+            for (int i = m+1; i <= high; i++) {
+               ort[i] = H[i][m-1];
+            }
+            for (int j = m; j <= high; j++) {
+               Real g = 0.0;
+               for (int i = m; i <= high; i++) {
+                  g += ort[i] * V[i][j];
+               }
+               // Double division avoids possible underflow
+               g = (g / ort[m]) / H[m][m-1];
+               for (int i = m; i <= high; i++) {
+                  V[i][j] += g * ort[i];
+               }
+            }
+         }
+      }
+   }
+
+
+   // Complex scalar division.
+
+   Real cdivr, cdivi;
+   void cdiv(Real xr, Real xi, Real yr, Real yi) {
+      Real r,d;
+      if (abs(yr) > abs(yi)) {
+         r = yi/yr;
+         d = yr + r*yi;
+         cdivr = (xr + r*xi)/d;
+         cdivi = (xi - r*xr)/d;
+      } else {
+         r = yr/yi;
+         d = yi + r*yr;
+         cdivr = (r*xr + xi)/d;
+         cdivi = (r*xi - xr)/d;
+      }
+   }
+
+
+   // Nonsymmetric reduction from Hessenberg to real Schur form.
+
+   void hqr2 () {
+   
+      //  This is derived from the Algol procedure hqr2,
+      //  by Martin and Wilkinson, Handbook for Auto. Comp.,
+      //  Vol.ii-Linear Algebra, and the corresponding
+      //  Fortran subroutine in EISPACK.
+   
+      // Initialize
+   
+      int nn = this->n;
+      int n = nn-1;
+      int low = 0;
+      int high = nn-1;
+      Real eps = pow(2.0,-52.0);
+      Real exshift = 0.0;
+      Real p=0,q=0,r=0,s=0,z=0,t,w,x,y;
+   
+      // Store roots isolated by balanc and compute matrix norm
+   
+      Real norm = 0.0;
+      for (int i = 0; i < nn; i++) {
+         if ((i < low) || (i > high)) {
+            d[i] = H[i][i];
+            e[i] = 0.0;
+         }
+         for (int j = TNT::max(i-1,0); j < nn; j++) {
+            norm = norm + abs(H[i][j]);
+         }
+      }
+   
+      // Outer loop over eigenvalue index
+   
+      int iter = 0;
+      while (n >= low) {
+   
+         // Look for single small sub-diagonal element
+   
+         int l = n;
+         while (l > low) {
+            s = abs(H[l-1][l-1]) + abs(H[l][l]);
+            if (s == 0.0) {
+               s = norm;
+            }
+            if (abs(H[l][l-1]) < eps * s) {
+               break;
+            }
+            l--;
+         }
+       
+         // Check for convergence
+         // One root found
+   
+         if (l == n) {
+            H[n][n] = H[n][n] + exshift;
+            d[n] = H[n][n];
+            e[n] = 0.0;
+            n--;
+            iter = 0;
+   
+         // Two roots found
+   
+         } else if (l == n-1) {
+            w = H[n][n-1] * H[n-1][n];
+            p = (H[n-1][n-1] - H[n][n]) / 2.0;
+            q = p * p + w;
+            z = sqrt(abs(q));
+            H[n][n] = H[n][n] + exshift;
+            H[n-1][n-1] = H[n-1][n-1] + exshift;
+            x = H[n][n];
+   
+            // Real pair
+   
+            if (q >= 0) {
+               if (p >= 0) {
+                  z = p + z;
+               } else {
+                  z = p - z;
+               }
+               d[n-1] = x + z;
+               d[n] = d[n-1];
+               if (z != 0.0) {
+                  d[n] = x - w / z;
+               }
+               e[n-1] = 0.0;
+               e[n] = 0.0;
+               x = H[n][n-1];
+               s = abs(x) + abs(z);
+               p = x / s;
+               q = z / s;
+               r = sqrt(p * p+q * q);
+               p = p / r;
+               q = q / r;
+   
+               // Row modification
+   
+               for (int j = n-1; j < nn; j++) {
+                  z = H[n-1][j];
+                  H[n-1][j] = q * z + p * H[n][j];
+                  H[n][j] = q * H[n][j] - p * z;
+               }
+   
+               // Column modification
+   
+               for (int i = 0; i <= n; i++) {
+                  z = H[i][n-1];
+                  H[i][n-1] = q * z + p * H[i][n];
+                  H[i][n] = q * H[i][n] - p * z;
+               }
+   
+               // Accumulate transformations
+   
+               for (int i = low; i <= high; i++) {
+                  z = V[i][n-1];
+                  V[i][n-1] = q * z + p * V[i][n];
+                  V[i][n] = q * V[i][n] - p * z;
+               }
+   
+            // Complex pair
+   
+            } else {
+               d[n-1] = x + p;
+               d[n] = x + p;
+               e[n-1] = z;
+               e[n] = -z;
+            }
+            n = n - 2;
+            iter = 0;
+   
+         // No convergence yet
+   
+         } else {
+   
+            // Form shift
+   
+            x = H[n][n];
+            y = 0.0;
+            w = 0.0;
+            if (l < n) {
+               y = H[n-1][n-1];
+               w = H[n][n-1] * H[n-1][n];
+            }
+   
+            // Wilkinson's original ad hoc shift
+   
+            if (iter == 10) {
+               exshift += x;
+               for (int i = low; i <= n; i++) {
+                  H[i][i] -= x;
+               }
+               s = abs(H[n][n-1]) + abs(H[n-1][n-2]);
+               x = y = 0.75 * s;
+               w = -0.4375 * s * s;
+            }
+
+            // MATLAB's new ad hoc shift
+
+            if (iter == 30) {
+                s = (y - x) / 2.0;
+                s = s * s + w;
+                if (s > 0) {
+                    s = sqrt(s);
+                    if (y < x) {
+                       s = -s;
+                    }
+                    s = x - w / ((y - x) / 2.0 + s);
+                    for (int i = low; i <= n; i++) {
+                       H[i][i] -= s;
+                    }
+                    exshift += s;
+                    x = y = w = 0.964;
+                }
+            }
+   
+            iter = iter + 1;   // (Could check iteration count here.)
+   
+            // Look for two consecutive small sub-diagonal elements
+   
+            int m = n-2;
+            while (m >= l) {
+               z = H[m][m];
+               r = x - z;
+               s = y - z;
+               p = (r * s - w) / H[m+1][m] + H[m][m+1];
+               q = H[m+1][m+1] - z - r - s;
+               r = H[m+2][m+1];
+               s = abs(p) + abs(q) + abs(r);
+               p = p / s;
+               q = q / s;
+               r = r / s;
+               if (m == l) {
+                  break;
+               }
+               if (abs(H[m][m-1]) * (abs(q) + abs(r)) <
+                  eps * (abs(p) * (abs(H[m-1][m-1]) + abs(z) +
+                  abs(H[m+1][m+1])))) {
+                     break;
+               }
+               m--;
+            }
+   
+            for (int i = m+2; i <= n; i++) {
+               H[i][i-2] = 0.0;
+               if (i > m+2) {
+                  H[i][i-3] = 0.0;
+               }
+            }
+   
+            // Double QR step involving rows l:n and columns m:n
+   
+            for (int k = m; k <= n-1; k++) {
+               int notlast = (k != n-1);
+               if (k != m) {
+                  p = H[k][k-1];
+                  q = H[k+1][k-1];
+                  r = (notlast ? H[k+2][k-1] : 0.0);
+                  x = abs(p) + abs(q) + abs(r);
+                  if (x != 0.0) {
+                     p = p / x;
+                     q = q / x;
+                     r = r / x;
+                  }
+               }
+               if (x == 0.0) {
+                  break;
+               }
+               s = sqrt(p * p + q * q + r * r);
+               if (p < 0) {
+                  s = -s;
+               }
+               if (s != 0) {
+                  if (k != m) {
+                     H[k][k-1] = -s * x;
+                  } else if (l != m) {
+                     H[k][k-1] = -H[k][k-1];
+                  }
+                  p = p + s;
+                  x = p / s;
+                  y = q / s;
+                  z = r / s;
+                  q = q / p;
+                  r = r / p;
+   
+                  // Row modification
+   
+                  for (int j = k; j < nn; j++) {
+                     p = H[k][j] + q * H[k+1][j];
+                     if (notlast) {
+                        p = p + r * H[k+2][j];
+                        H[k+2][j] = H[k+2][j] - p * z;
+                     }
+                     H[k][j] = H[k][j] - p * x;
+                     H[k+1][j] = H[k+1][j] - p * y;
+                  }
+   
+                  // Column modification
+   
+                  for (int i = 0; i <= TNT::min(n,k+3); i++) {
+                     p = x * H[i][k] + y * H[i][k+1];
+                     if (notlast) {
+                        p = p + z * H[i][k+2];
+                        H[i][k+2] = H[i][k+2] - p * r;
+                     }
+                     H[i][k] = H[i][k] - p;
+                     H[i][k+1] = H[i][k+1] - p * q;
+                  }
+   
+                  // Accumulate transformations
+   
+                  for (int i = low; i <= high; i++) {
+                     p = x * V[i][k] + y * V[i][k+1];
+                     if (notlast) {
+                        p = p + z * V[i][k+2];
+                        V[i][k+2] = V[i][k+2] - p * r;
+                     }
+                     V[i][k] = V[i][k] - p;
+                     V[i][k+1] = V[i][k+1] - p * q;
+                  }
+               }  // (s != 0)
+            }  // k loop
+         }  // check convergence
+      }  // while (n >= low)
+      
+      // Backsubstitute to find vectors of upper triangular form
+
+      if (norm == 0.0) {
+         return;
+      }
+   
+      for (n = nn-1; n >= 0; n--) {
+         p = d[n];
+         q = e[n];
+   
+         // Real vector
+   
+         if (q == 0) {
+            int l = n;
+            H[n][n] = 1.0;
+            for (int i = n-1; i >= 0; i--) {
+               w = H[i][i] - p;
+               r = 0.0;
+               for (int j = l; j <= n; j++) {
+                  r = r + H[i][j] * H[j][n];
+               }
+               if (e[i] < 0.0) {
+                  z = w;
+                  s = r;
+               } else {
+                  l = i;
+                  if (e[i] == 0.0) {
+                     if (w != 0.0) {
+                        H[i][n] = -r / w;
+                     } else {
+                        H[i][n] = -r / (eps * norm);
+                     }
+   
+                  // Solve real equations
+   
+                  } else {
+                     x = H[i][i+1];
+                     y = H[i+1][i];
+                     q = (d[i] - p) * (d[i] - p) + e[i] * e[i];
+                     t = (x * s - z * r) / q;
+                     H[i][n] = t;
+                     if (abs(x) > abs(z)) {
+                        H[i+1][n] = (-r - w * t) / x;
+                     } else {
+                        H[i+1][n] = (-s - y * t) / z;
+                     }
+                  }
+   
+                  // Overflow control
+   
+                  t = abs(H[i][n]);
+                  if ((eps * t) * t > 1) {
+                     for (int j = i; j <= n; j++) {
+                        H[j][n] = H[j][n] / t;
+                     }
+                  }
+               }
+            }
+   
+         // Complex vector
+   
+         } else if (q < 0) {
+            int l = n-1;
+
+            // Last vector component imaginary so matrix is triangular
+   
+            if (abs(H[n][n-1]) > abs(H[n-1][n])) {
+               H[n-1][n-1] = q / H[n][n-1];
+               H[n-1][n] = -(H[n][n] - p) / H[n][n-1];
+            } else {
+               cdiv(0.0,-H[n-1][n],H[n-1][n-1]-p,q);
+               H[n-1][n-1] = cdivr;
+               H[n-1][n] = cdivi;
+            }
+            H[n][n-1] = 0.0;
+            H[n][n] = 1.0;
+            for (int i = n-2; i >= 0; i--) {
+               Real ra,sa,vr,vi;
+               ra = 0.0;
+               sa = 0.0;
+               for (int j = l; j <= n; j++) {
+                  ra = ra + H[i][j] * H[j][n-1];
+                  sa = sa + H[i][j] * H[j][n];
+               }
+               w = H[i][i] - p;
+   
+               if (e[i] < 0.0) {
+                  z = w;
+                  r = ra;
+                  s = sa;
+               } else {
+                  l = i;
+                  if (e[i] == 0) {
+                     cdiv(-ra,-sa,w,q);
+                     H[i][n-1] = cdivr;
+                     H[i][n] = cdivi;
+                  } else {
+   
+                     // Solve complex equations
+   
+                     x = H[i][i+1];
+                     y = H[i+1][i];
+                     vr = (d[i] - p) * (d[i] - p) + e[i] * e[i] - q * q;
+                     vi = (d[i] - p) * 2.0 * q;
+                     if ((vr == 0.0) && (vi == 0.0)) {
+                        vr = eps * norm * (abs(w) + abs(q) +
+                        abs(x) + abs(y) + abs(z));
+                     }
+                     cdiv(x*r-z*ra+q*sa,x*s-z*sa-q*ra,vr,vi);
+                     H[i][n-1] = cdivr;
+                     H[i][n] = cdivi;
+                     if (abs(x) > (abs(z) + abs(q))) {
+                        H[i+1][n-1] = (-ra - w * H[i][n-1] + q * H[i][n]) / x;
+                        H[i+1][n] = (-sa - w * H[i][n] - q * H[i][n-1]) / x;
+                     } else {
+                        cdiv(-r-y*H[i][n-1],-s-y*H[i][n],z,q);
+                        H[i+1][n-1] = cdivr;
+                        H[i+1][n] = cdivi;
+                     }
+                  }
+   
+                  // Overflow control
+
+                  t = TNT::max(abs(H[i][n-1]),abs(H[i][n]));
+                  if ((eps * t) * t > 1) {
+                     for (int j = i; j <= n; j++) {
+                        H[j][n-1] = H[j][n-1] / t;
+                        H[j][n] = H[j][n] / t;
+                     }
+                  }
+               }
+            }
+         }
+      }
+   
+      // Vectors of isolated roots
+   
+      for (int i = 0; i < nn; i++) {
+         if (i < low || i > high) {
+            for (int j = i; j < nn; j++) {
+               V[i][j] = H[i][j];
+            }
+         }
+      }
+   
+      // Back transformation to get eigenvectors of original matrix
+   
+      for (int j = nn-1; j >= low; j--) {
+         for (int i = low; i <= high; i++) {
+            z = 0.0;
+            for (int k = low; k <= TNT::min(j,high); k++) {
+               z = z + V[i][k] * H[k][j];
+            }
+            V[i][j] = z;
+         }
+      }
+   }
+
+public:
+
+
+   /** Check for symmetry, then construct the eigenvalue decomposition
+   @param A    Square real (non-complex) matrix
+   */
+
+   Eigenvalue(const TNT::Array2D<Real> &A) {
+      n = A.dim2();
+      V = Array2D<Real>(n,n);
+      d = Array1D<Real>(n);
+      e = Array1D<Real>(n);
+
+      issymmetric = 1;
+      for (int j = 0; (j < n) && issymmetric; j++) {
+         for (int i = 0; (i < n) && issymmetric; i++) {
+            issymmetric = (A[i][j] == A[j][i]);
+         }
+      }
+
+      if (issymmetric) {
+         for (int i = 0; i < n; i++) {
+            for (int j = 0; j < n; j++) {
+               V[i][j] = A[i][j];
+            }
+         }
+   
+         // Tridiagonalize.
+         tred2();
+   
+         // Diagonalize.
+         tql2();
+
+      } else {
+         H = TNT::Array2D<Real>(n,n);
+         ort = TNT::Array1D<Real>(n);
+         
+         for (int j = 0; j < n; j++) {
+            for (int i = 0; i < n; i++) {
+               H[i][j] = A[i][j];
+            }
+         }
+   
+         // Reduce to Hessenberg form.
+         orthes();
+   
+         // Reduce Hessenberg to real Schur form.
+         hqr2();
+      }
+   }
+
+
+   /** Return the eigenvector matrix
+   @return     V
+   */
+
+   void getV (TNT::Array2D<Real> &V_) {
+      V_ = V;
+      return;
+   }
+
+   /** Return the real parts of the eigenvalues
+   @return     real(diag(D))
+   */
+
+   void getRealEigenvalues (TNT::Array1D<Real> &d_) {
+      d_ = d;
+      return ;
+   }
+
+   /** Return the imaginary parts of the eigenvalues
+   in parameter e_.
+
+   @pararm e_: new matrix with imaginary parts of the eigenvalues.
+   */
+   void getImagEigenvalues (TNT::Array1D<Real> &e_) {
+      e_ = e;
+      return;
+   }
+
+   
+/** 
+	Computes the block diagonal eigenvalue matrix.
+    If the original matrix A is not symmetric, then the eigenvalue 
+	matrix D is block diagonal with the real eigenvalues in 1-by-1 
+	blocks and any complex eigenvalues,
+    a + i*b, in 2-by-2 blocks, [a, b; -b, a].  That is, if the complex
+    eigenvalues look like
+<pre>
+
+          u + iv     .        .          .      .    .
+            .      u - iv     .          .      .    .
+            .        .      a + ib       .      .    .
+            .        .        .        a - ib   .    .
+            .        .        .          .      x    .
+            .        .        .          .      .    y
+</pre>
+        then D looks like
+<pre>
+
+            u        v        .          .      .    .
+           -v        u        .          .      .    . 
+            .        .        a          b      .    .
+            .        .       -b          a      .    .
+            .        .        .          .      x    .
+            .        .        .          .      .    y
+</pre>
+    This keeps V a real matrix in both symmetric and non-symmetric
+    cases, and A*V = V*D.
+
+	@param D: upon return, the matrix is filled with the block diagonal 
+	eigenvalue matrix.
+	
+*/
+   void getD (TNT::Array2D<Real> &D) {
+      D = Array2D<Real>(n,n);
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            D[i][j] = 0.0;
+         }
+         D[i][i] = d[i];
+         if (e[i] > 0) {
+            D[i][i+1] = e[i];
+         } else if (e[i] < 0) {
+            D[i][i-1] = e[i];
+         }
+      }
+   }
+};
+
+} //namespace JAMA
+
+
+#endif
+// JAMA_EIG_H
+
diff --git a/bioimagesuite30_src/numerics/tnt/jama_lu.h b/bioimagesuite30_src/numerics/tnt/jama_lu.h
new file mode 100644
index 0000000..2b0e4e4
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/jama_lu.h
@@ -0,0 +1,347 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef JAMA_LU_H
+#define JAMA_LU_H
+
+#include "tnt.h"
+
+using namespace TNT;
+
+
+namespace JAMA
+{
+
+   /** LU Decomposition.
+   <P>
+   For an m-by-n matrix A with m >= n, the LU decomposition is an m-by-n
+   unit lower triangular matrix L, an n-by-n upper triangular matrix U,
+   and a permutation vector piv of length m so that A(piv,:) = L*U.
+   If m < n, then L is m-by-m and U is m-by-n.
+   <P>
+   The LU decompostion with pivoting always exists, even if the matrix is
+   singular, so the constructor will never fail.  The primary use of the
+   LU decomposition is in the solution of square systems of simultaneous
+   linear equations.  This will fail if isNonsingular() returns false.
+   */
+template <class Real>
+class LU
+{
+
+
+
+   /* Array for internal storage of decomposition.  */
+   Array2D<Real>  LU_;
+   int m, n, pivsign; 
+   Array1D<int> piv;
+
+
+   Array2D<Real> permute_copy(const Array2D<Real> &A, 
+   			const Array1D<int> &piv, int j0, int j1)
+	{
+		int piv_length = piv.dim();
+
+		Array2D<Real> X(piv_length, j1-j0+1);
+
+
+         for (int i = 0; i < piv_length; i++) 
+            for (int j = j0; j <= j1; j++) 
+               X[i][j-j0] = A[piv[i]][j];
+
+		return X;
+	}
+
+   Array1D<Real> permute_copy(const Array1D<Real> &A, 
+   		const Array1D<int> &piv)
+	{
+		int piv_length = piv.dim();
+		if (piv_length != A.dim())
+			return Array1D<Real>();
+
+		Array1D<Real> x(piv_length);
+
+
+         for (int i = 0; i < piv_length; i++) 
+               x[i] = A[piv[i]];
+
+		return x;
+	}
+
+
+	public :
+
+   /** LU Decomposition
+   @param  A   Rectangular matrix
+   @return     LU Decomposition object to access L, U and piv.
+   */
+
+    LU (const Array2D<Real> &A) : LU_(A.copy()), m(A.dim1()), n(A.dim2()), 
+		piv(A.dim1())
+	
+	{
+
+   // Use a "left-looking", dot-product, Crout/Doolittle algorithm.
+
+	  int i=0;
+	  int j=0;
+	  int k=0;
+
+      for (i = 0; i < m; i++) {
+         piv[i] = i;
+      }
+      pivsign = 1;
+      Real *LUrowi = 0;;
+      Array1D<Real> LUcolj(m);
+
+      // Outer loop.
+
+      for (j = 0; j < n; j++) {
+
+         // Make a copy of the j-th column to localize references.
+
+         for (i = 0; i < m; i++) {
+            LUcolj[i] = LU_[i][j];
+         }
+
+         // Apply previous transformations.
+
+         for (int i = 0; i < m; i++) {
+            LUrowi = LU_[i];
+
+            // Most of the time is spent in the following dot product.
+
+            int kmax = min(i,j);
+            double s = 0.0;
+            for (k = 0; k < kmax; k++) {
+               s += LUrowi[k]*LUcolj[k];
+            }
+
+            LUrowi[j] = LUcolj[i] -= s;
+         }
+   
+         // Find pivot and exchange if necessary.
+
+         int p = j;
+         for (int i = j+1; i < m; i++) {
+            if (abs(LUcolj[i]) > abs(LUcolj[p])) {
+               p = i;
+            }
+         }
+         if (p != j) {
+            for (k = 0; k < n; k++) {
+               double t = LU_[p][k]; 
+			   LU_[p][k] = LU_[j][k]; 
+			   LU_[j][k] = t;
+            }
+            k = piv[p]; 
+			piv[p] = piv[j]; 
+			piv[j] = k;
+            pivsign = -pivsign;
+         }
+
+         // Compute multipliers.
+         
+         if ((j < m) && (LU_[j][j] != 0.0)) {
+            for (i = j+1; i < m; i++) {
+               LU_[i][j] /= LU_[j][j];
+            }
+         }
+      }
+   }
+
+
+   /** Is the matrix nonsingular?
+   @return     1 (true)  if upper triangular factor U (and hence A) 
+   				is nonsingular, 0 otherwise.
+   */
+
+   int isNonsingular () {
+      for (int j = 0; j < n; j++) {
+         if (LU_[j][j] == 0)
+            return 0;
+      }
+      return 1;
+   }
+
+   /** Return lower triangular factor
+   @return     L
+   */
+
+   Array2D<Real> getL () {
+      Array2D<Real> L_(m,n);
+      for (int i = 0; i < m; i++) {
+         for (int j = 0; j < n; j++) {
+            if (i > j) {
+               L_[i][j] = LU_[i][j];
+            } else if (i == j) {
+               L_[i][j] = 1.0;
+            } else {
+               L_[i][j] = 0.0;
+            }
+         }
+      }
+      return L_;
+   }
+
+   /** Return upper triangular factor
+   @return     U portion of LU factorization.
+   */
+
+   Array2D<Real> getU () {
+   	  Array2D<Real> U_(n,n);
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            if (i <= j) {
+               U_[i][j] = LU_[i][j];
+            } else {
+               U_[i][j] = 0.0;
+            }
+         }
+      }
+      return U_;
+   }
+
+   /** Return pivot permutation vector
+   @return     piv
+   */
+
+   Array1D<int> getPivot () {
+      return p;
+   }
+
+
+   /** Compute determinant using LU factors.
+   @return     determinant of A, or 0 if A is not square.
+   */
+
+   Real det () {
+      if (m != n) {
+         return Real(0);
+      }
+      Real d = Real(pivsign);
+      for (int j = 0; j < n; j++) {
+         d *= LU_[j][j];
+      }
+      return d;
+   }
+
+   /** Solve A*X = B
+   @param  B   A Matrix with as many rows as A and any number of columns.
+   @return     X so that L*U*X = B(piv,:), if B is nonconformant, returns
+   					0x0 (null) array.
+   */
+
+   Array2D<Real> solve (const Array2D<Real> &B) 
+   {
+
+	  /* Dimensions: A is mxn, X is nxk, B is mxk */
+      
+      if (B.dim1() != m) {
+	  	return Array2D<Real>(0,0);
+      }
+      if (!isNonsingular()) {
+        return Array2D<Real>(0,0);
+      }
+
+      // Copy right hand side with pivoting
+      int nx = B.dim2();
+
+
+	  Array2D<Real> X = permute_copy(B, piv, 0, nx-1);
+
+      // Solve L*Y = B(piv,:)
+      for (int k = 0; k < n; k++) {
+         for (int i = k+1; i < n; i++) {
+            for (int j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*LU_[i][k];
+            }
+         }
+      }
+      // Solve U*X = Y;
+      for (int k = n-1; k >= 0; k--) {
+         for (int j = 0; j < nx; j++) {
+            X[k][j] /= LU_[k][k];
+         }
+         for (int i = 0; i < k; i++) {
+            for (int j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*LU_[i][k];
+            }
+         }
+      }
+      return X;
+   }
+
+
+   /** Solve A*x = b, where x and b are vectors of length equal	
+   		to the number of rows in A.
+
+   @param  b   a vector (Array1D> of length equal to the first dimension
+   						of A.
+   @return x a vector (Array1D> so that L*U*x = b(piv), if B is nonconformant,
+   					returns 0x0 (null) array.
+   */
+
+   Array1D<Real> solve (const Array1D<Real> &b) 
+   {
+
+	  /* Dimensions: A is mxn, X is nxk, B is mxk */
+      
+      if (b.dim1() != m) {
+	  	return Array1D<Real>();
+      }
+      if (!isNonsingular()) {
+        return Array1D<Real>();
+      }
+
+
+	  Array1D<Real> x = permute_copy(b, piv);
+
+      // Solve L*Y = B(piv)
+      for (int k = 0; k < n; k++) {
+         for (int i = k+1; i < n; i++) {
+               x[i] -= x[k]*LU_[i][k];
+            }
+         }
+      
+	  // Solve U*X = Y;
+      for (int k = n-1; k >= 0; k--) {
+            x[k] /= LU_[k][k];
+      		for (int i = 0; i < k; i++) 
+            	x[i] -= x[k]*LU_[i][k];
+      }
+     
+
+      return x;
+   }
+
+}; /* class LU */
+
+} /* namespace JAMA */
+
+#endif
+/* JAMA_LU_H */
+
diff --git a/bioimagesuite30_src/numerics/tnt/jama_qr.h b/bioimagesuite30_src/numerics/tnt/jama_qr.h
new file mode 100644
index 0000000..a0103be
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/jama_qr.h
@@ -0,0 +1,355 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef JAMA_QR_H
+#define JAMA_QR_H
+
+#include "tnt_array1d.h"
+#include "tnt_array2d.h"
+#include "tnt_math_utils.h"
+
+namespace JAMA
+{
+
+/** 
+<p>
+	Classical QR Decompisition:
+   for an m-by-n matrix A with m >= n, the QR decomposition is an m-by-n
+   orthogonal matrix Q and an n-by-n upper triangular matrix R so that
+   A = Q*R.
+<P>
+   The QR decompostion always exists, even if the matrix does not have
+   full rank, so the constructor will never fail.  The primary use of the
+   QR decomposition is in the least squares solution of nonsquare systems
+   of simultaneous linear equations.  This will fail if isFullRank()
+   returns 0 (false).
+
+<p>
+	The Q and R factors can be retrived via the getQ() and getR()
+	methods. Furthermore, a solve() method is provided to find the
+	least squares solution of Ax=b using the QR factors.  
+
+   <p>
+	(Adapted from JAMA, a Java Matrix Library, developed by jointly 
+	by the Mathworks and NIST; see  http://math.nist.gov/javanumerics/jama).
+*/
+
+template <class Real>
+class QR {
+
+
+   /** Array for internal storage of decomposition.
+   @serial internal array storage.
+   */
+   
+   TNT::Array2D<Real> QR_;
+
+   /** Row and column dimensions.
+   @serial column dimension.
+   @serial row dimension.
+   */
+   int m, n;
+
+   /** Array for internal storage of diagonal of R.
+   @serial diagonal of R.
+   */
+   TNT::Array1D<Real> Rdiag;
+
+
+public:
+	
+/**
+	Create a QR factorization object for A.
+
+	@param A rectangular (m>=n) matrix.
+*/
+	QR(const TNT::Array2D<Real> &A)		/* constructor */
+	{
+      QR_ = A.copy();
+      m = A.dim1();
+      n = A.dim2();
+      Rdiag = TNT::Array1D<Real>(n);
+	  int i=0, j=0, k=0;
+
+      // Main loop.
+      for (k = 0; k < n; k++) {
+         // Compute 2-norm of k-th column without under/overflow.
+         Real nrm = 0;
+         for (i = k; i < m; i++) {
+            nrm = hypot(nrm,QR_[i][k]);
+         }
+
+         if (nrm != 0.0) {
+            // Form k-th Householder vector.
+            if (QR_[k][k] < 0) {
+               nrm = -nrm;
+            }
+            for (i = k; i < m; i++) {
+               QR_[i][k] /= nrm;
+            }
+            QR_[k][k] += 1.0;
+
+            // Apply transformation to remaining columns.
+            for (j = k+1; j < n; j++) {
+               Real s = 0.0; 
+               for (i = k; i < m; i++) {
+                  s += QR_[i][k]*QR_[i][j];
+               }
+               s = -s/QR_[k][k];
+               for (i = k; i < m; i++) {
+                  QR_[i][j] += s*QR_[i][k];
+               }
+            }
+         }
+         Rdiag[k] = -nrm;
+      }
+   }
+
+
+/**
+	Flag to denote the matrix is of full rank.
+
+	@return 1 if matrix is full rank, 0 otherwise.
+*/
+	int isFullRank() const		
+	{
+      for (int j = 0; j < n; j++) 
+	  {
+         if (Rdiag[j] == 0)
+            return 0;
+      }
+      return 1;
+	}
+	
+	
+
+
+   /** 
+   
+   Retreive the Householder vectors from QR factorization
+   @returns lower trapezoidal matrix whose columns define the reflections
+   */
+
+   TNT::Array2D<Real> getHouseholder (void)  const
+   {
+   	  TNT::Array2D<Real> H(m,n);
+
+	  /* note: H is completely filled in by algorithm, so
+	     initializaiton of H is not necessary.
+	  */
+      for (int i = 0; i < m; i++) 
+	  {
+         for (int j = 0; j < n; j++) 
+		 {
+            if (i >= j) {
+               H[i][j] = QR_[i][j];
+            } else {
+               H[i][j] = 0.0;
+            }
+         }
+      }
+	  return H;
+   }
+
+
+
+   /** Return the upper triangular factor, R, of the QR factorization
+   @return     R
+   */
+
+	TNT::Array2D<Real> getR() const
+	{
+      TNT::Array2D<Real> R(n,n);
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            if (i < j) {
+               R[i][j] = QR_[i][j];
+            } else if (i == j) {
+               R[i][j] = Rdiag[i];
+            } else {
+               R[i][j] = 0.0;
+            }
+         }
+      }
+	  return R;
+   }
+	
+	
+
+
+
+   /** 
+   	Generate and return the (economy-sized) orthogonal factor
+   @param     Q the (ecnomy-sized) orthogonal factor (Q*R=A).
+   */
+
+	TNT::Array2D<Real> getQ() const
+	{
+	  int i=0, j=0, k=0;
+
+	  TNT::Array2D<Real> Q(m,n);
+      for (k = n-1; k >= 0; k--) {
+         for (i = 0; i < m; i++) {
+            Q[i][k] = 0.0;
+         }
+         Q[k][k] = 1.0;
+         for (j = k; j < n; j++) {
+            if (QR_[k][k] != 0) {
+               Real s = 0.0;
+               for (i = k; i < m; i++) {
+                  s += QR_[i][k]*Q[i][j];
+               }
+               s = -s/QR_[k][k];
+               for (i = k; i < m; i++) {
+                  Q[i][j] += s*QR_[i][k];
+               }
+            }
+         }
+      }
+	  return Q;
+   }
+
+
+   /** Least squares solution of A*x = b
+   @param B     m-length array (vector).
+   @return x    n-length array (vector) that minimizes the two norm of Q*R*X-B.
+   		If B is non-conformant, or if QR.isFullRank() is false,
+						the routine returns a null (0-length) vector.
+   */
+
+   TNT::Array1D<Real> solve(const TNT::Array1D<Real> &b) const
+   {
+   	  if (b.dim1() != m)		/* arrays must be conformant */
+	  	return TNT::Array1D<Real>();
+
+	  if ( !isFullRank() )		/* matrix is rank deficient */
+	  {
+	  	return TNT::Array1D<Real>();
+	  }
+
+	  TNT::Array1D<Real> x = b;
+	  int i=0, j=0, k=0;
+
+      // Compute Y = transpose(Q)*b
+      for (k = 0; k < n; k++) 
+	  {
+            Real s = 0.0; 
+            for (i = k; i < m; i++) 
+			{
+               s += QR_[i][k]*x[i];
+            }
+            s = -s/QR_[k][k];
+            for (i = k; i < m; i++) 
+			{
+               x[i] += s*QR_[i][k];
+            }
+      }
+      // Solve R*X = Y;
+      for (k = n-1; k >= 0; k--) 
+	  {
+         x[k] /= Rdiag[k];
+         for (i = 0; i < k; i++) {
+               x[i] -= x[k]*QR_[i][k];
+         }
+      }
+
+
+	  /* return n x nx portion of X */
+	  TNT::Array1D<Real> x_(n);
+	  for (i=0; i<n; i++)
+			x_[i] = x[i];
+
+	  return x_;
+   }
+
+   /** Least squares solution of A*X = B
+   @param B     m x k Array (must conform).
+   @return X     n x k Array that minimizes the two norm of Q*R*X-B. If
+   						B is non-conformant, or if QR.isFullRank() is false,
+						the routine returns a null (0x0) array.
+   */
+
+   TNT::Array2D<Real> solve(const TNT::Array2D<Real> &B) const
+   {
+   	  if (B.dim1() != m)		/* arrays must be conformant */
+	  	return TNT::Array2D<Real>(0,0);
+
+	  if ( !isFullRank() )		/* matrix is rank deficient */
+	  {
+	  	return TNT::Array2D<Real>(0,0);
+	  }
+
+      int nx = B.dim2(); 
+	  TNT::Array2D<Real> X = B;
+	  int i=0, j=0, k=0;
+
+      // Compute Y = transpose(Q)*B
+      for (k = 0; k < n; k++) {
+         for (j = 0; j < nx; j++) {
+            Real s = 0.0; 
+            for (i = k; i < m; i++) {
+               s += QR_[i][k]*X[i][j];
+            }
+            s = -s/QR_[k][k];
+            for (i = k; i < m; i++) {
+               X[i][j] += s*QR_[i][k];
+            }
+         }
+      }
+      // Solve R*X = Y;
+      for (k = n-1; k >= 0; k--) {
+         for (j = 0; j < nx; j++) {
+            X[k][j] /= Rdiag[k];
+         }
+         for (i = 0; i < k; i++) {
+            for (j = 0; j < nx; j++) {
+               X[i][j] -= X[k][j]*QR_[i][k];
+            }
+         }
+      }
+
+
+	  /* return n x nx portion of X */
+	  TNT::Array2D<Real> X_(n,nx);
+	  for (i=0; i<n; i++)
+	  	for (j=0; j<nx; j++)
+			X_[i][j] = X[i][j];
+
+	  return X_;
+   }
+
+
+};
+
+
+}
+// namespace JAMA
+
+#endif
+// JAMA_QR__H
+
+
diff --git a/bioimagesuite30_src/numerics/tnt/jama_svd.h b/bioimagesuite30_src/numerics/tnt/jama_svd.h
new file mode 100644
index 0000000..3239ff9
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/jama_svd.h
@@ -0,0 +1,561 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef JAMA_SVD_H
+#define JAMA_SVD_H
+
+
+#include "tnt_array1d.h"
+#include "tnt_array1d_utils.h"
+#include "tnt_array2d.h"
+#include "tnt_array2d_utils.h"
+#include "tnt_math_utils.h"
+
+
+using namespace TNT;
+
+namespace JAMA
+{
+   /** Singular Value Decomposition.
+   <P>
+   For an m-by-n matrix A with m >= n, the singular value decomposition is
+   an m-by-n orthogonal matrix U, an n-by-n diagonal matrix S, and
+   an n-by-n orthogonal matrix V so that A = U*S*V'.
+   <P>
+   The singular values, sigma[k] = S[k][k], are ordered so that
+   sigma[0] >= sigma[1] >= ... >= sigma[n-1].
+   <P>
+   The singular value decompostion always exists, so the constructor will
+   never fail.  The matrix condition number and the effective numerical
+   rank can be computed from this decomposition.
+
+   <p>
+	(Adapted from JAMA, a Java Matrix Library, developed by jointly 
+	by the Mathworks and NIST; see  http://math.nist.gov/javanumerics/jama).
+   */
+template <class Real>
+class SVD 
+{
+
+
+	Array2D<Real> U, V;
+	Array1D<Real> s;
+	int m, n;
+
+  public:
+
+
+   SVD (const Array2D<Real> &Arg) {
+
+
+      m = Arg.dim1();
+      n = Arg.dim2();
+      int nu = TNT::min(m,n);
+      s = Array1D<Real>(TNT::min(m+1,n)); 
+      U = Array2D<Real>(m, nu, Real(0));
+      V = Array2D<Real>(n,n);
+      Array1D<Real> e(n);
+      Array1D<Real> work(m);
+	  Array2D<Real> A(Arg.copy());
+      int wantu = 1;  					/* boolean */
+      int wantv = 1;  					/* boolean */
+	  int i=0, j=0, k=0;
+
+      // Reduce A to bidiagonal form, storing the diagonal elements
+      // in s and the super-diagonal elements in e.
+
+      int nct = TNT::min(m-1,n);
+      int nrt = TNT::max(0,TNT::min(n-2,m));
+      for (k = 0; k < TNT::max(nct,nrt); k++) {
+         if (k < nct) {
+
+            // Compute the transformation for the k-th column and
+            // place the k-th diagonal in s[k].
+            // Compute 2-norm of k-th column without under/overflow.
+            s[k] = 0;
+            for (i = k; i < m; i++) {
+               s[k] = hypot(s[k],A[i][k]);
+            }
+            if (s[k] != 0.0) {
+               if (A[k][k] < 0.0) {
+                  s[k] = -s[k];
+               }
+               for (i = k; i < m; i++) {
+                  A[i][k] /= s[k];
+               }
+               A[k][k] += 1.0;
+            }
+            s[k] = -s[k];
+         }
+         for (j = k+1; j < n; j++) {
+            if ((k < nct) && (s[k] != 0.0))  {
+
+            // Apply the transformation.
+
+               double t = 0;
+               for (i = k; i < m; i++) {
+                  t += A[i][k]*A[i][j];
+               }
+               t = -t/A[k][k];
+               for (i = k; i < m; i++) {
+                  A[i][j] += t*A[i][k];
+               }
+            }
+
+            // Place the k-th row of A into e for the
+            // subsequent calculation of the row transformation.
+
+            e[j] = A[k][j];
+         }
+         if (wantu & (k < nct)) {
+
+            // Place the transformation in U for subsequent back
+            // multiplication.
+
+            for (i = k; i < m; i++) {
+               U[i][k] = A[i][k];
+            }
+         }
+         if (k < nrt) {
+
+            // Compute the k-th row transformation and place the
+            // k-th super-diagonal in e[k].
+            // Compute 2-norm without under/overflow.
+            e[k] = 0;
+            for (i = k+1; i < n; i++) {
+               e[k] = hypot(e[k],e[i]);
+            }
+            if (e[k] != 0.0) {
+               if (e[k+1] < 0.0) {
+                  e[k] = -e[k];
+               }
+               for (i = k+1; i < n; i++) {
+                  e[i] /= e[k];
+               }
+               e[k+1] += 1.0;
+            }
+            e[k] = -e[k];
+            if ((k+1 < m) & (e[k] != 0.0)) {
+
+            // Apply the transformation.
+
+               for (i = k+1; i < m; i++) {
+                  work[i] = 0.0;
+               }
+               for (j = k+1; j < n; j++) {
+                  for (i = k+1; i < m; i++) {
+                     work[i] += e[j]*A[i][j];
+                  }
+               }
+               for (j = k+1; j < n; j++) {
+                  double t = -e[j]/e[k+1];
+                  for (i = k+1; i < m; i++) {
+                     A[i][j] += t*work[i];
+                  }
+               }
+            }
+            if (wantv) {
+
+            // Place the transformation in V for subsequent
+            // back multiplication.
+
+               for (i = k+1; i < n; i++) {
+                  V[i][k] = e[i];
+               }
+            }
+         }
+      }
+
+      // Set up the final bidiagonal matrix or order p.
+
+      int p = TNT::min(n,m+1);
+      if (nct < n) {
+         s[nct] = A[nct][nct];
+      }
+      if (m < p) {
+         s[p-1] = 0.0;
+      }
+      if (nrt+1 < p) {
+         e[nrt] = A[nrt][p-1];
+      }
+      e[p-1] = 0.0;
+
+      // If required, generate U.
+
+      if (wantu) {
+         for (j = nct; j < nu; j++) {
+            for (i = 0; i < m; i++) {
+               U[i][j] = 0.0;
+            }
+            U[j][j] = 1.0;
+         }
+         for (k = nct-1; k >= 0; k--) {
+            if (s[k] != 0.0) {
+               for (j = k+1; j < nu; j++) {
+                  double t = 0;
+                  for (i = k; i < m; i++) {
+                     t += U[i][k]*U[i][j];
+                  }
+                  t = -t/U[k][k];
+                  for (i = k; i < m; i++) {
+                     U[i][j] += t*U[i][k];
+                  }
+               }
+               for (i = k; i < m; i++ ) {
+                  U[i][k] = -U[i][k];
+               }
+               U[k][k] = 1.0 + U[k][k];
+               for (i = 0; i < k-1; i++) {
+                  U[i][k] = 0.0;
+               }
+            } else {
+               for (i = 0; i < m; i++) {
+                  U[i][k] = 0.0;
+               }
+               U[k][k] = 1.0;
+            }
+         }
+      }
+
+      // If required, generate V.
+
+      if (wantv) {
+         for (k = n-1; k >= 0; k--) {
+            if ((k < nrt) & (e[k] != 0.0)) {
+               for (j = k+1; j < nu; j++) {
+                  double t = 0;
+                  for (i = k+1; i < n; i++) {
+                     t += V[i][k]*V[i][j];
+                  }
+                  t = -t/V[k+1][k];
+                  for (i = k+1; i < n; i++) {
+                     V[i][j] += t*V[i][k];
+                  }
+               }
+            }
+            for (i = 0; i < n; i++) {
+               V[i][k] = 0.0;
+            }
+            V[k][k] = 1.0;
+         }
+      }
+
+      // Main iteration loop for the singular values.
+
+      int pp = p-1;
+      int iter = 0;
+      double eps = pow(2.0,-52.0);
+      while (p > 0) {
+         int k=0;
+		 int kase=0;
+
+         // Here is where a test for too many iterations would go.
+
+         // This section of the program inspects for
+         // negligible elements in the s and e arrays.  On
+         // completion the variables kase and k are set as follows.
+
+         // kase = 1     if s(p) and e[k-1] are negligible and k<p
+         // kase = 2     if s(k) is negligible and k<p
+         // kase = 3     if e[k-1] is negligible, k<p, and
+         //              s(k), ..., s(p) are not negligible (qr step).
+         // kase = 4     if e(p-1) is negligible (convergence).
+
+         for (k = p-2; k >= -1; k--) {
+            if (k == -1) {
+               break;
+            }
+            if (abs(e[k]) <= eps*(abs(s[k]) + abs(s[k+1]))) {
+               e[k] = 0.0;
+               break;
+            }
+         }
+         if (k == p-2) {
+            kase = 4;
+         } else {
+            int ks;
+            for (ks = p-1; ks >= k; ks--) {
+               if (ks == k) {
+                  break;
+               }
+               double t = (ks != p ? abs(e[ks]) : 0.) + 
+                          (ks != k+1 ? abs(e[ks-1]) : 0.);
+               if (abs(s[ks]) <= eps*t)  {
+                  s[ks] = 0.0;
+                  break;
+               }
+            }
+            if (ks == k) {
+               kase = 3;
+            } else if (ks == p-1) {
+               kase = 1;
+            } else {
+               kase = 2;
+               k = ks;
+            }
+         }
+         k++;
+
+         // Perform the task indicated by kase.
+
+         switch (kase) {
+
+            // Deflate negligible s(p).
+
+            case 1: {
+               double f = e[p-2];
+               e[p-2] = 0.0;
+               for (j = p-2; j >= k; j--) {
+                  double t = hypot(s[j],f);
+                  double cs = s[j]/t;
+                  double sn = f/t;
+                  s[j] = t;
+                  if (j != k) {
+                     f = -sn*e[j-1];
+                     e[j-1] = cs*e[j-1];
+                  }
+                  if (wantv) {
+                     for (i = 0; i < n; i++) {
+                        t = cs*V[i][j] + sn*V[i][p-1];
+                        V[i][p-1] = -sn*V[i][j] + cs*V[i][p-1];
+                        V[i][j] = t;
+                     }
+                  }
+               }
+            }
+            break;
+
+            // Split at negligible s(k).
+
+            case 2: {
+               double f = e[k-1];
+               e[k-1] = 0.0;
+               for (j = k; j < p; j++) {
+                  double t = hypot(s[j],f);
+                  double cs = s[j]/t;
+                  double sn = f/t;
+                  s[j] = t;
+                  f = -sn*e[j];
+                  e[j] = cs*e[j];
+                  if (wantu) {
+                     for (i = 0; i < m; i++) {
+                        t = cs*U[i][j] + sn*U[i][k-1];
+                        U[i][k-1] = -sn*U[i][j] + cs*U[i][k-1];
+                        U[i][j] = t;
+                     }
+                  }
+               }
+            }
+            break;
+
+            // Perform one qr step.
+
+            case 3: {
+
+               // Calculate the shift.
+   
+               double scale = TNT::max(TNT::max(TNT::max(TNT::max(
+                       abs(s[p-1]),abs(s[p-2])),abs(e[p-2])), 
+                       abs(s[k])),abs(e[k]));
+               double sp = s[p-1]/scale;
+               double spm1 = s[p-2]/scale;
+               double epm1 = e[p-2]/scale;
+               double sk = s[k]/scale;
+               double ek = e[k]/scale;
+               double b = ((spm1 + sp)*(spm1 - sp) + epm1*epm1)/2.0;
+               double c = (sp*epm1)*(sp*epm1);
+               double shift = 0.0;
+               if ((b != 0.0) | (c != 0.0)) {
+                  shift = sqrt(b*b + c);
+                  if (b < 0.0) {
+                     shift = -shift;
+                  }
+                  shift = c/(b + shift);
+               }
+               double f = (sk + sp)*(sk - sp) + shift;
+               double g = sk*ek;
+   
+               // Chase zeros.
+   
+               for (j = k; j < p-1; j++) {
+                  double t = hypot(f,g);
+                  double cs = f/t;
+                  double sn = g/t;
+                  if (j != k) {
+                     e[j-1] = t;
+                  }
+                  f = cs*s[j] + sn*e[j];
+                  e[j] = cs*e[j] - sn*s[j];
+                  g = sn*s[j+1];
+                  s[j+1] = cs*s[j+1];
+                  if (wantv) {
+                     for (i = 0; i < n; i++) {
+                        t = cs*V[i][j] + sn*V[i][j+1];
+                        V[i][j+1] = -sn*V[i][j] + cs*V[i][j+1];
+                        V[i][j] = t;
+                     }
+                  }
+                  t = hypot(f,g);
+                  cs = f/t;
+                  sn = g/t;
+                  s[j] = t;
+                  f = cs*e[j] + sn*s[j+1];
+                  s[j+1] = -sn*e[j] + cs*s[j+1];
+                  g = sn*e[j+1];
+                  e[j+1] = cs*e[j+1];
+                  if (wantu && (j < m-1)) {
+                     for (i = 0; i < m; i++) {
+                        t = cs*U[i][j] + sn*U[i][j+1];
+                        U[i][j+1] = -sn*U[i][j] + cs*U[i][j+1];
+                        U[i][j] = t;
+                     }
+                  }
+               }
+               e[p-2] = f;
+               iter = iter + 1;
+            }
+            break;
+
+            // Convergence.
+
+            case 4: {
+
+               // Make the singular values positive.
+   
+               if (s[k] <= 0.0) {
+                  s[k] = (s[k] < 0.0 ? -s[k] : 0.0);
+                  if (wantv) {
+                     for (i = 0; i <= pp; i++) {
+                        V[i][k] = -V[i][k];
+                     }
+                  }
+               }
+   
+               // Order the singular values.
+   
+               while (k < pp) {
+                  if (s[k] >= s[k+1]) {
+                     break;
+                  }
+                  double t = s[k];
+                  s[k] = s[k+1];
+                  s[k+1] = t;
+                  if (wantv && (k < n-1)) {
+                     for (i = 0; i < n; i++) {
+                        t = V[i][k+1]; V[i][k+1] = V[i][k]; V[i][k] = t;
+                     }
+                  }
+                  if (wantu && (k < m-1)) {
+                     for (i = 0; i < m; i++) {
+                        t = U[i][k+1]; U[i][k+1] = U[i][k]; U[i][k] = t;
+                     }
+                  }
+                  k++;
+               }
+               iter = 0;
+               p--;
+            }
+            break;
+         }
+      }
+   }
+
+
+   void getU (Array2D<Real> &A) 
+   {
+   	  int minm = TNT::min(m+1,n);
+
+	  A = Array2D<Real>(m, minm);
+
+	  for (int i=0; i<m; i++)
+	  	for (int j=0; j<minm; j++)
+			A[i][j] = U[i][j];
+   	
+   }
+
+   /* Return the right singular vectors */
+
+   void getV (Array2D<Real> &A) 
+   {
+   	  A = V;
+   }
+
+   /** Return the one-dimensional array of singular values */
+
+   void getSingularValues (Array1D<Real> &x) 
+   {
+      x = s;
+   }
+
+   /** Return the diagonal matrix of singular values
+   @return     S
+   */
+
+   void getS (Array2D<Real> &A) {
+   	  A = Array2D<Real>(n,n);
+      for (int i = 0; i < n; i++) {
+         for (int j = 0; j < n; j++) {
+            A[i][j] = 0.0;
+         }
+         A[i][i] = s[i];
+      }
+   }
+
+   /** Two norm  (max(S)) */
+
+   double norm2 () {
+      return s[0];
+   }
+
+   /** Two norm of condition number (max(S)/min(S)) */
+
+   double cond () {
+      return s[0]/s[TNT::min(m,n)-1];
+   }
+
+   /** Effective numerical matrix rank
+   @return     Number of nonnegligible singular values.
+   */
+
+   int rank () 
+   {
+      double eps = pow(2.0,-52.0);
+      double tol = TNT::max(m,n)*s[0]*eps;
+      int r = 0;
+      for (int i = 0; i < s.dim(); i++) {
+         if (s[i] > tol) {
+            r++;
+         }
+      }
+      return r;
+   }
+};
+
+}
+#endif
+// JAMA_SVD_H
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt.h b/bioimagesuite30_src/numerics/tnt/tnt.h
new file mode 100644
index 0000000..e7e9044
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt.h
@@ -0,0 +1,93 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Template Numerical Toolkit (TNT): Linear Algebra Module
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+
+#ifndef TNT_H
+#define TNT_H
+
+
+
+//---------------------------------------------------------------------
+// Define this macro if you want  TNT to track some of the out-of-bounds
+// indexing. This can encur a small run-time overhead, but is recommended 
+// while developing code.  It can be turned off for production runs.
+// 
+//       #define TNT_BOUNDS_CHECK
+//---------------------------------------------------------------------
+//
+
+//#define TNT_BOUNDS_CHECK
+
+
+#include "tnt_version.h"
+
+#include "tnt_array1d.h"
+#include "tnt_array2d.h"
+#include "tnt_array3d.h"
+#include "tnt_array1d_utils.h"
+#include "tnt_array2d_utils.h"
+#include "tnt_array3d_utils.h"
+
+#include "tnt_fortran_array1d.h"
+#include "tnt_fortran_array2d.h"
+#include "tnt_fortran_array3d.h"
+#include "tnt_fortran_array1d_utils.h"
+#include "tnt_fortran_array2d_utils.h"
+#include "tnt_fortran_array3d_utils.h"
+
+#include "tnt_sparse_matrix_csr.h"
+
+#include "tnt_stopwatch.h"
+#include "tnt_math_utils.h"
+
+#include "tnt_subscript.h"
+#include "tnt_vec.h"
+#include "tnt_cmat.h"
+
+
+#endif
+// TNT_H
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_array1d.h b/bioimagesuite30_src/numerics/tnt/tnt_array1d.h
new file mode 100644
index 0000000..199a9ae
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_array1d.h
@@ -0,0 +1,446 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Template Numerical Toolkit (TNT)
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+
+
+#ifndef TNT_ARRAY1D_H
+#define TNT_ARRAY1D_H
+
+#include <cstdlib>
+#include <iostream>
+
+#ifdef TNT_BOUNDS_CHECK
+#include <assert.h>
+#endif
+
+namespace TNT
+{
+
+/**
+	Tempplated one-dimensional, numerical array which
+	looks like a conventional C array. 
+	Elements are accessed via the familiar A[i] notation. 
+	
+	<p>
+	Array assignment is by reference (i.e. shallow assignment).
+	That is, B=A implies that the A and B point to the
+	same array, so modifications to the elements of A
+	will be reflected in B. If an independent copy
+	is required, then B = A.copy() can be used.  Note
+	that this facilitates returning arrays from functions
+	without relying on compiler optimizations to eliminate
+	extensive data copying.
+
+	<p>
+	The indexing and layout of this array object makes
+	it compatible with C and C++ algorithms that utilize
+	the familiar C[i] notation.  This includes numerous
+	textbooks, such as Numercial Recipes, and various
+	public domain codes.
+
+	<p>
+	This class employs its own garbage collection via
+	the use of reference counts.  That is, whenever
+	an internal array storage no longer has any references
+	to it, it is destoryed.
+*/
+template <class T>
+class Array1D 
+{
+
+
+  private:
+    T* v_;                  
+    int n_;
+    int *ref_count_;
+
+	void initialize_(int n);
+    void copy_(T* p, const T*  q, int len) const;
+    void set_(const T& val);
+    void destroy_();
+	inline const T* begin_() const;
+	inline T* begin_();
+
+  public:
+
+    typedef         T   value_type;
+
+	         Array1D();
+	explicit Array1D(int n);
+	         Array1D(int n,  T *a);
+	         Array1D(int n, const T &a);
+    inline   Array1D(const Array1D &A);
+	inline   Array1D & operator=(const T &a);
+	inline   Array1D & operator=(const Array1D &A);
+	inline   Array1D & ref(const Array1D &A);
+	         Array1D copy() const;
+		     Array1D & inject(const Array1D & A);
+	inline   T& operator[](int i);
+	inline   const T& operator[](int i) const;
+	inline 	 int dim1() const;
+	inline   int dim() const;
+	inline   int ref_count() const;
+               ~Array1D();
+
+
+};
+
+/**
+	Null constructor.  Creates a 0-length (NULL) array.
+	(Reference count is also zero.)
+*/
+
+template <class T>
+Array1D<T>::Array1D() : v_(0), n_(0), ref_count_(0) 
+{
+	ref_count_ = new int;
+	*ref_count_ = 1;
+}
+
+/**
+	Copy constructor. Array data is NOT copied, but shared.
+	Thus, in Array1D B(A), subsequent changes to A will
+	be reflected in B.  For an indepent copy of A, use
+	Array1D B(A.copy()), or B = A.copy(), instead.
+*/
+template <class T>
+Array1D<T>::Array1D(const Array1D<T> &A) : v_(A.v_),  
+	n_(A.n_), ref_count_(A.ref_count_)
+{
+	(*ref_count_)++;
+}
+
+
+
+/**
+	Create a new array (vector) of length <b>n</b>,  
+	WIHOUT initializing array elements.
+	To create an initialized array of constants, see Array1D(n,value).
+
+	<p>
+	This version avoids the O(n) initialization overhead and
+	is used just before manual assignment.
+
+	@param n the dimension (length) of the new matrix.
+*/
+template <class T>
+Array1D<T>::Array1D(int n) : v_(0), n_(n), ref_count_(0)
+{
+	initialize_(n);
+	ref_count_ = new int;
+	*ref_count_ = 1;
+}
+
+
+
+/**
+	Create a new array of length <b>n</b>,  initializing array elements to
+	constant specified by argument.  Most often used to
+	create an array of zeros, as in A(n, 0.0).
+
+	@param n the dimension (length) of the new matrix.  
+	@param val the constant value to set all elements of the new array to.
+*/
+template <class T>
+Array1D<T>::Array1D(int n, const T &val) : v_(0), n_(n) ,
+	ref_count_(0)
+{
+	initialize_(n);
+	set_(val);
+	ref_count_ = new int;
+	*ref_count_ = 1;
+
+}
+
+/**
+	Create a new n-length array,  as a view of an existing one-dimensional
+	C array.  (Note that the storage for this pre-existing array will
+	never be destroyed by the Aray1DRef class.)
+
+	@param n the dimension (length) of the new matrix.
+	@param a the one dimensional C array to use as data storage for
+		the array. 
+*/
+template <class T>
+Array1D<T>::Array1D(int n, T *a) : v_(a), n_(n) ,
+	ref_count_(0)
+{
+	ref_count_ = new int;
+	*ref_count_ = 2;		/* this avoid destorying original data. */
+
+}
+
+/**
+	A[i] indexes the ith element of A.  The first element is
+	A[0]. If TNT_BOUNDS_CHECK is defined, then the index is
+	checked that it falls within the array bounds.
+*/
+template <class T>
+inline T& Array1D<T>::operator[](int i) 
+{ 
+#ifdef TNT_BOUNDS_CHECK
+	assert(i>= 0);
+	assert(i < n_);
+#endif
+	return v_[i]; 
+}
+
+/**
+	A[i] indexes the ith element of A.  The first element is
+	A[0]. If TNT_BOUNDS_CHECK is defined, then the index is
+	checked that it fall within the array bounds.
+*/
+template <class T>
+inline const T& Array1D<T>::operator[](int i) const 
+{ 
+#ifdef TNT_BOUNDS_CHECK
+	assert(i>= 0);
+	assert(i < n_);
+#endif
+	return v_[i]; 
+}
+
+/**
+	Assign all elemnts of A to a constant scalar.
+*/
+template <class T>
+Array1D<T> & Array1D<T>::operator=(const T &a)
+{
+	set_(a);
+	return *this;
+}
+/**
+	Create a new of existing matrix.  Used in B = A.copy()
+	or in the construction of B, e.g. Array1D B(A.copy()), 
+	to create a new array that does not share data.
+
+*/
+template <class T>
+Array1D<T> Array1D<T>::copy() const
+{
+	Array1D A( n_);
+	copy_(A.begin_(), begin_(), n_);
+
+	return A;
+}
+
+
+/**
+	Copy the elements to from one array to another, in place.
+	That is B.inject(A), both A and B must conform (i.e. have
+	identical row and column dimensions).
+
+	This differs from B = A.copy() in that references to B
+	before this assignment are also affected.  That is, if
+	we have 
+	<pre>
+	Array1D A(n);
+	Array1D C(n);
+	Array1D B(C);        // elements of B and C are shared. 
+
+</pre>
+	then B.inject(A) affects both and C, while B=A.copy() creates
+	a new array B which shares no data with C or A.
+
+	@param A the array from which elements will be copied
+	@return an instance of the modifed array. That is, in B.inject(A),
+	it returns B.  If A and B are not conformat, no modifications to 
+	B are made.
+
+*/
+template <class T>
+Array1D<T> & Array1D<T>::inject(const Array1D &A)
+{
+	if (A.n_ == n_)
+		copy_(begin_(), A.begin_(), n_);
+
+	return *this;
+}
+
+
+
+
+
+/**
+	Create a reference (shallow assignment) to another existing array.
+	In B.ref(A), B and A shared the same data and subsequent changes
+	to the array elements of one will be reflected in the other.
+	<p>
+	This is what operator= calls, and B=A and B.ref(A) are equivalent
+	operations.
+
+	@return The new referenced array: in B.ref(A), it returns B.
+*/
+template <class T>
+Array1D<T> & Array1D<T>::ref(const Array1D<T> &A)
+{
+	if (this != &A)
+	{
+		(*ref_count_) --;
+		if ( *ref_count_ < 1)
+		{
+			destroy_();
+		}
+
+		n_ = A.n_;
+		v_ = A.v_;
+		ref_count_ = A.ref_count_;
+
+		(*ref_count_) ++ ;
+		
+	}
+	return *this;
+}
+
+/**
+	B = A is shorthand notation for B.ref(A).
+*/
+template <class T>
+Array1D<T> & Array1D<T>::operator=(const Array1D<T> &A)
+{
+	return ref(A);
+}
+
+/**
+	@return the dimension (number of elements) of the array.
+	This is equivalent to dim() and dim1().
+*/
+template <class T>
+inline int Array1D<T>::dim1() const { return n_; }
+
+/**
+	@return the dimension (number of elements) of the array.
+	This is equivalent to dim1() and dim1().
+*/
+template <class T>
+inline int Array1D<T>::dim() const { return n_; }
+
+
+
+/**
+	@return the number of arrays that share the same storage area
+	as this one.  (Must be at least one.)
+*/
+template <class T>
+inline int Array1D<T>::ref_count() const
+{
+	return *ref_count_;
+}
+
+template <class T>
+Array1D<T>::~Array1D()
+{
+	(*ref_count_) --;
+
+	if (*ref_count_ < 1)
+		destroy_();
+}
+
+/* private internal functions */
+
+template <class T>
+void Array1D<T>::initialize_(int n)
+{
+
+
+	v_ = new T[n];
+	n_ = n;
+}
+
+template <class T>
+void Array1D<T>::set_(const T& a)
+{
+	T *begin = &(v_[0]);
+	T *end = begin+ n_;
+
+	for (T* p=begin; p<end; p++)
+		*p = a;
+
+}
+
+template <class T>
+void Array1D<T>::copy_(T* p, const T* q, int len) const
+{
+	T *end = p + len;
+	while (p<end )
+		*p++ = *q++;
+
+}
+
+template <class T>
+void Array1D<T>::destroy_()
+{
+
+	if (v_ != 0)
+	{
+		delete[] (v_);
+	}
+
+	if (ref_count_ != 0)
+		delete ref_count_;
+}
+
+/**
+	@returns location of first element, i.e. A[0] (mutable).
+*/
+template <class T>
+const T* Array1D<T>::begin_() const { return &(v_[0]); }
+
+/**
+	@returns location of first element, i.e. A[0] (mutable).
+*/
+template <class T>
+T* Array1D<T>::begin_() { return &(v_[0]); }
+
+
+
+
+} /* namespace TNT */
+
+#endif
+/* TNT_ARRAY1D_H */
+
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_array1d_utils.h b/bioimagesuite30_src/numerics/tnt/tnt_array1d_utils.h
new file mode 100644
index 0000000..7f82e76
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_array1d_utils.h
@@ -0,0 +1,93 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#ifndef TNT_ARRAY1D_UTILS_H
+#define TNT_ARRAY1D_UTILS_H
+
+#include <cstdlib>
+#include <cassert>
+
+namespace TNT
+{
+
+
+/**
+	Write an array to a character outstream.  Output format is one that can
+	be read back in via the in-stream operator: one integer
+	denoting the array dimension (n), followed by n elements,
+	one per line.  
+
+*/
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Array1D<T> &A)
+{
+    int N=A.dim1();
+
+    s << N << "\n";
+    for (int j=0; j<N; j++)
+    {
+       s << A[j] << "\n";
+    }
+    s << "\n";
+
+    return s;
+}
+
+/**
+	Read an array from a character stream.  Input format
+	is one integer, denoting the dimension (n), followed
+	by n whitespace-separated elments.  Newlines are ignored
+
+	<p>
+	Note: the array being read into references new memory
+	storage. If the intent is to fill an existing conformant
+	array, use <code> cin >> B;  A.inject(B) ); </code>
+	instead or read the elements in one-a-time by hand.
+
+	@param s the charater to read from (typically <code>std::in</code>)
+	@param A the array to read into.
+*/
+template <class T>
+std::istream& operator>>(std::istream &s, Array1D<T> &A)
+{
+	int N;
+	s >> N;
+
+	Array1D<T> B(N);
+	for (int i=0; i<N; i++)
+		s >> B[i];
+	A = B;
+	return s;
+}
+
+
+
+} // namespace TNT
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_array2d.h b/bioimagesuite30_src/numerics/tnt/tnt_array2d.h
new file mode 100644
index 0000000..bf43e23
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_array2d.h
@@ -0,0 +1,463 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Template Numerical Toolkit (TNT): Two-dimensional numerical array
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+
+
+#ifndef TNT_ARRAY2D_H
+#define TNT_ARRAY2D_H
+
+#include <cstdlib>
+#include <iostream>
+#ifdef TNT_BOUNDS_CHECK
+#include <assert.h>
+#endif
+
+namespace TNT
+{
+
+/**
+	Tempplated two-dimensional, numerical array which
+	looks like a conventional C multiarray. 
+	Storage corresponds to C (row-major) ordering.
+	Elements are accessed via A[i][j] notation. 
+	
+	<p>
+	Array assignment is by reference (i.e. shallow assignment).
+	That is, B=A implies that the A and B point to the
+	same array, so modifications to the elements of A
+	will be reflected in B. If an independent copy
+	is required, then B = A.copy() can be used.  Note
+	that this facilitates returning arrays from functions
+	without relying on compiler optimizations to eliminate
+	extensive data copying.
+
+	<p>
+	The indexing and layout of this array object makes
+	it compatible with C and C++ algorithms that utilize
+	the familiar C[i][j] notation.  This includes numerous
+	textbooks, such as Numercial Recipes, and various
+	public domain codes.
+
+	<p>
+	This class employs its own garbage collection via
+	the use of reference counts.  That is, whenever
+	an internal array storage no longer has any references
+	to it, it is destoryed.
+*/
+template <class T>
+class Array2D 
+{
+
+
+  private:
+    T** v_;                  
+	int m_;
+    int n_;
+    int *ref_count_;
+
+	void initialize_(int m, int n);
+    void copy_(T* p, const T*  q, int len) const;
+    void set_(const T& val);
+    void destroy_();
+	inline const T* begin_() const;
+	inline T* begin_();
+
+  public:
+
+    typedef         T   value_type;
+
+	       Array2D();
+	       Array2D(int m, int n);
+	       Array2D(int m, int n,  T *a);
+	       Array2D(int m, int n, const T &a);
+    inline Array2D(const Array2D &A);
+	inline Array2D & operator=(const T &a);
+	inline Array2D & operator=(const Array2D &A);
+	inline Array2D & ref(const Array2D &A);
+	       Array2D copy() const;
+		   Array2D & inject(const Array2D & A);
+	inline T* operator[](int i);
+	inline const T* operator[](int i) const;
+	inline int dim1() const;
+	inline int dim2() const;
+	inline int ref_count() const;
+               ~Array2D();
+
+
+};
+
+
+/**
+	Copy constructor. Array data is NOT copied, but shared.
+	Thus, in Array2D B(A), subsequent changes to A will
+	be reflected in B.  For an indepent copy of A, use
+	Array2D B(A.copy()), or B = A.copy(), instead.
+*/
+template <class T>
+Array2D<T>::Array2D(const Array2D<T> &A) : v_(A.v_), m_(A.m_), 
+	n_(A.n_), ref_count_(A.ref_count_)
+{
+	(*ref_count_)++;
+}
+
+
+
+/**
+	Create a new (m x n) array, WIHOUT initializing array elements.
+	To create an initialized array of constants, see Array2D(m,n,value).
+
+	<p>
+	This version avoids the O(m*n) initialization overhead and
+	is used just before manual assignment.
+
+	@param m the first (row) dimension of the new matrix.
+	@param n the second (column) dimension of the new matrix.
+*/
+template <class T>
+Array2D<T>::Array2D(int m, int n) : v_(0), m_(m), n_(n), ref_count_(0)
+{
+	initialize_(m,n);
+	ref_count_ = new int;
+	*ref_count_ = 1;
+}
+
+
+
+/**
+	Create a new (m x n) array,  initializing array elements to
+	constant specified by argument.  Most often used to
+	create an array of zeros, as in A(m, n, 0.0).
+
+	@param m the first (row) dimension of the new matrix.
+	@param n the second (column) dimension of the new matrix.
+	@param val the constant value to set all elements of the new array to.
+*/
+template <class T>
+Array2D<T>::Array2D(int m, int n, const T &val) : v_(0), m_(m), n_(n) ,
+	ref_count_(0)
+{
+	initialize_(m,n);
+	set_(val);
+	ref_count_ = new int;
+	*ref_count_ = 1;
+
+}
+
+/**
+	Create a new (m x n) array,  as a view of an existing one-dimensional
+	array stored in <b>C order</b>, i.e. right-most dimension varying fastest.  
+	(Often referred to as "row-major" ordering.)
+	Note that the storage for this pre-existing array will
+	never be garbage collected by the Array2D class.
+
+	@param m the first (row) dimension of the new matrix.
+	@param n the second (column) dimension of the new matrix.
+	@param a the one dimensional C array to use as data storage for
+		the array. 
+*/
+template <class T>
+Array2D<T>::Array2D(int m, int n, T *a) : v_(0), m_(m), n_(n) ,
+	ref_count_(0)
+{
+	T* p = a;
+	v_ = new T*[m];
+	for (int i=0; i<m; i++)
+	{
+		v_[i] = p;
+		p += n;
+	}
+	ref_count_ = new int;
+	*ref_count_ = 2;		/* this avoid destorying original data. */
+
+}
+
+
+/**
+	Used for A[i][j] indexing.  The first [] operator returns
+	a conventional pointer which can be dereferenced using the
+	same [] notation.  
+	
+	If TNT_BOUNDS_CHECK macro is define, the left-most index (row index)
+	is checked that it falls within the array bounds (via the
+	assert() macro.) Note that bounds checking can occur in
+	the row dimension, but the not column, since
+	this is just a C pointer.
+*/
+template <class T>
+inline T* Array2D<T>::operator[](int i) 
+{ 
+#ifdef TNT_BOUNDS_CHECK
+	assert(i >= 0);
+	assert(i < m_);
+#endif
+
+return v_[i]; 
+
+}
+
+template <class T>
+inline const T* Array2D<T>::operator[](int i) const { return v_[i]; }
+
+/**
+	Assign all elemnts of A to a constant scalar.
+*/
+template <class T>
+Array2D<T> & Array2D<T>::operator=(const T &a)
+{
+	set_(a);
+	return *this;
+}
+/**
+	Create a new of existing matrix.  Used in B = A.copy()
+	or in the construction of B, e.g. Array2D B(A.copy()), 
+	to create a new array that does not share data.
+
+*/
+template <class T>
+Array2D<T> Array2D<T>::copy() const
+{
+	Array2D A(m_, n_);
+	copy_(A.begin_(), begin_(), m_*n_);
+
+	return A;
+}
+
+
+/**
+	Copy the elements to from one array to another, in place.
+	That is B.inject(A), both A and B must conform (i.e. have
+	identical row and column dimensions).
+
+	This differs from B = A.copy() in that references to B
+	before this assignment are also affected.  That is, if
+	we have 
+	<pre>
+	Array2D A(m,n);
+	Array2D C(m,n);
+	Array2D B(C);        // elements of B and C are shared. 
+
+</pre>
+	then B.inject(A) affects both and C, while B=A.copy() creates
+	a new array B which shares no data with C or A.
+
+	@param A the array from elements will be copied
+	@return an instance of the modifed array. That is, in B.inject(A),
+	it returns B.  If A and B are not conformat, no modifications to 
+	B are made.
+
+*/
+template <class T>
+Array2D<T> & Array2D<T>::inject(const Array2D &A)
+{
+	if (A.m_ == m_ &&  A.n_ == n_)
+		copy_(begin_(), A.begin_(), m_*n_);
+
+	return *this;
+}
+
+
+
+
+
+/**
+	Create a reference (shallow assignment) to another existing array.
+	In B.ref(A), B and A shared the same data and subsequent changes
+	to the array elements of one will be reflected in the other.
+	<p>
+	This is what operator= calls, and B=A and B.ref(A) are equivalent
+	operations.
+
+	@return The new referenced array: in B.ref(A), it returns B.
+*/
+template <class T>
+Array2D<T> & Array2D<T>::ref(const Array2D<T> &A)
+{
+	if (this != &A)
+	{
+		(*ref_count_) --;
+		if ( *ref_count_ < 1 )
+		{
+			destroy_();
+		}
+
+		m_ = A.m_;
+		n_ = A.n_;
+		v_ = A.v_;
+		ref_count_ = A.ref_count_;
+
+		(*ref_count_) ++ ;
+		
+	}
+	return *this;
+}
+
+/**
+	B = A is shorthand notation for B.ref(A).
+*/
+template <class T>
+Array2D<T> & Array2D<T>::operator=(const Array2D<T> &A)
+{
+	return ref(A);
+}
+
+/**
+	@return the size of the first dimension of the array, i.e.
+	the number of rows.
+*/
+template <class T>
+inline int Array2D<T>::dim1() const { return m_; }
+
+/**
+	@return the size of the second dimension of the array, i.e.
+	the number of columns.
+*/
+template <class T>
+inline int Array2D<T>::dim2() const { return n_; }
+
+
+/**
+	@return the number of arrays that share the same storage area
+	as this one.  (Must be at least one.)
+*/
+template <class T>
+inline int Array2D<T>::ref_count() const
+{
+	return *ref_count_;
+}
+
+template <class T>
+Array2D<T>::~Array2D()
+{
+	(*ref_count_) --;
+
+	if (*ref_count_ < 1)
+		destroy_();
+}
+
+/* private internal functions */
+
+template <class T>
+void Array2D<T>::initialize_(int m, int n)
+{
+
+
+	T* p = new T[m*n];
+	v_ = new T*[m];
+	for (int i=0; i<m; i++)
+	{
+		v_[i] = p;
+		p+=n;
+	}
+	m_ = m;
+	n_ = n;
+}
+
+template <class T>
+void Array2D<T>::set_(const T& a)
+{
+	T *begin = &v_[0][0];
+	T *end = begin+ m_*n_;
+
+	for (T* p=begin; p<end; p++)
+		*p = a;
+
+}
+
+template <class T>
+void Array2D<T>::copy_(T* p, const T* q, int len) const
+{
+	T *end = p + len;
+	while (p<end )
+		*p++ = *q++;
+
+}
+
+template <class T>
+void Array2D<T>::destroy_()
+{
+
+	if (v_ != 0)
+	{
+		delete[] (v_[0]);
+		delete[] (v_);
+	}
+
+	if (ref_count_ != 0)
+		delete ref_count_;
+}
+
+/**
+	@returns location of first element, i.e. A[0][0] (mutable).
+*/
+template <class T>
+const T* Array2D<T>::begin_() const { return &(v_[0][0]); }
+
+/**
+	@returns location of first element, i.e. A[0][0] (mutable).
+*/
+template <class T>
+T* Array2D<T>::begin_() { return &(v_[0][0]); }
+
+/**
+	Create a null (0x0) array.  
+*/
+template <class T>
+Array2D<T>::Array2D() : v_(0), m_(0), n_(0) 
+{
+	ref_count_ = new int;
+	*ref_count_ = 1;
+}
+
+
+
+
+
+} /* namespace TNT */
+
+#endif
+/* TNT_ARRAY2D_H */
+
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_array2d_utils.h b/bioimagesuite30_src/numerics/tnt/tnt_array2d_utils.h
new file mode 100644
index 0000000..8b44b29
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_array2d_utils.h
@@ -0,0 +1,150 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+#ifndef TNT_ARRAY2D_UTILS_H
+#define TNT_ARRAY2D_UTILS_H
+
+#include <cstdlib>
+#include <cassert>
+
+namespace TNT
+{
+
+
+/**
+	Write an array to a character outstream.  Output format is one that can
+	be read back in via the in-stream operator: two integers
+	denoting the array dimensions (m x n), followed by m
+	lines of n  elements.
+
+*/
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Array2D<T> &A)
+{
+    int M=A.dim1();
+    int N=A.dim2();
+
+    s << M << " " << N << "\n";
+
+    for (int i=0; i<M; i++)
+    {
+        for (int j=0; j<N; j++)
+        {
+            s << A[i][j] << " ";
+        }
+        s << "\n";
+    }
+
+
+    return s;
+}
+
+/**
+	Read an array from a character stream.  Input format
+	is two integers, denoting the dimensions (m x n), followed
+	by m*n whitespace-separated elments in "row-major" order
+	(i.e. right-most dimension varying fastest.)  Newlines
+	are ignored.
+
+	<p>
+	Note: the array being read into references new memory
+	storage. If the intent is to fill an existing conformant
+	array, use <code> cin >> B;  A.inject(B) ); </code>
+	instead or read the elements in one-a-time by hand.
+
+	@param s the charater to read from (typically <code>std::in</code>)
+	@param A the array to read into.
+*/
+template <class T>
+std::istream& operator>>(std::istream &s, Array2D<T> &A)
+{
+
+    int M, N;
+
+    s >> M >> N;
+
+	Array2D<T> B(M,N);
+
+    for (int i=0; i<M; i++)
+        for (int j=0; j<N; j++)
+        {
+            s >>  B[i][j];
+        }
+
+	A = B;
+    return s;
+}
+
+
+/**
+	Matrix Multiply:  compute C = A*B, where C[i][j]
+	is the dot-product of row i of A and column j of B.
+	
+
+	@param A an (m x n) array
+	@param B an (n x k) array
+	@return the (m x k) array A*B, or a null array (0x0)
+		if the matrices are non-conformant (i.e. the number 
+		of columns of A are different than the number of rows of B.)
+	
+
+*/
+template <class T>
+Array2D<T> matmult(const Array2D<T> &A, const Array2D<T> &B)
+{
+	if (A.dim2() != B.dim1())
+		return Array2D<T>();
+
+	int M = A.dim1();
+	int N = A.dim2();
+	int K = B.dim2();
+
+	Array2D<T> C(M,K);
+
+	for (int i=0; i<M; i++)
+		for (int j=0; j<K; j++)
+		{
+			T sum = 0;
+
+			for (int k=0; k<N; k++)
+				sum += A[i][k] * B [k][j];
+
+			C[i][j] = sum;
+		}
+
+	return C;
+
+}
+
+
+
+} // namespace TNT
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_array3d.h b/bioimagesuite30_src/numerics/tnt/tnt_array3d.h
new file mode 100644
index 0000000..d44abc5
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_array3d.h
@@ -0,0 +1,469 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Template Numerical Toolkit (TNT): Three-dimensional numerical array
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+
+
+#ifndef TNT_ARRAY3D_H
+#define TNT_ARRAY3D_H
+
+#include <cstdlib>
+#include <iostream>
+#ifdef TNT_BOUNDS_CHECK
+#include <assert.h>
+#endif
+
+namespace TNT
+{
+
+/**
+	Tempplated three-dimensional, numerical array which
+	looks like a conventional C multiarray. 
+	Storage corresponds to conventional C ordering.
+	That is the right-most dimension has contiguous
+	elements.  Indexing is via the A[i][j][k] notation. 
+	
+	<p>
+	Array assignment is by reference (i.e. shallow assignment).
+	That is, B=A implies that the A and B point to the
+	same array, so modifications to the elements of A
+	will be reflected in B. If an independent copy
+	is required, then B = A.copy() can be used.  Note
+	that this facilitates returning arrays from functions
+	without relying on compiler optimizations to eliminate
+	extensive data copying.
+
+	<p>
+	The indexing and layout of this array object makes
+	it compatible with C and C++ algorithms that utilize
+	the familiar C[i][j][k] notation.  This includes numerous
+	textbooks, such as Numercial Recipes, and various
+	public domain codes.
+
+	<p>
+	This class employs its own garbage collection via
+	the use of reference counts.  That is, whenever
+	an internal array storage no longer has any references
+	to it, it is destoryed.
+*/
+template <class T>
+class Array3D 
+{
+
+
+  private:
+    T*** v_;                  
+	int m_;
+    int n_;
+	int k_;
+    int *ref_count_;
+
+	void initialize_(T* data, int m, int n, int k);
+    void copy_(T* p, const T*  q, int len) const;
+    void set_(const T& val);
+    void destroy_();
+	inline const T* begin_() const;
+	inline T* begin_();
+
+  public:
+
+    typedef         T   value_type;
+
+	       Array3D();
+	       Array3D(int m, int n, int k);
+	       Array3D(int m, int n, int k,  T *a);
+	       Array3D(int m, int n, int k, const T &a);
+    inline Array3D(const Array3D &A);
+	inline Array3D & operator=(const T &a);
+	inline Array3D & operator=(const Array3D &A);
+	inline Array3D & ref(const Array3D &A);
+	       Array3D copy() const;
+		   Array3D & inject(const Array3D & A);
+	inline T** operator[](int i);
+	inline const T* const * operator[](int i) const;
+	inline int dim1() const;
+	inline int dim2() const;
+	inline int dim3() const;
+	inline int ref_count() const;
+               ~Array3D();
+
+
+};
+
+
+/**
+	Copy constructor. Array data is NOT copied, but shared.
+	Thus, in Array3D B(A), subsequent changes to A will
+	be reflected in B.  For an indepent copy of A, use
+	Array3D B(A.copy()), or B = A.copy(), instead.
+*/
+template <class T>
+Array3D<T>::Array3D(const Array3D<T> &A) : v_(A.v_), m_(A.m_), 
+	n_(A.n_), k_(A.k_), ref_count_(A.ref_count_)
+{
+	(*ref_count_)++;
+}
+
+
+
+/**
+	Create a new (m x n x k) array, WIHOUT initializing array elements.
+	To create an initialized array of constants, see Array3D(m,n,k, value).
+
+	<p>
+	This version avoids the O(m*n*k) initialization overhead and
+	is used just before manual assignment.
+
+	@param m the first dimension of the new matrix.
+	@param n the second dimension of the new matrix.
+	@param k the third dimension of the new matrix.
+*/
+template <class T>
+Array3D<T>::Array3D(int m, int n, int k) : v_(0), m_(m), n_(n), k_(k), ref_count_(0)
+{
+	initialize_(new T[m*n*k], m,n,k);
+	ref_count_ = new int;
+	*ref_count_ = 1;
+}
+
+
+
+/**
+	Create a new (m x n x k) array,  initializing array elements to
+	constant specified by argument.  Most often used to
+	create an array of zeros, as in A(m, n, k, 0.0).
+
+	@param m the first dimension of the new matrix.
+	@param n the second dimension of the new matrix.
+	@param k the third dimension of the new matrix.
+	@param val the constant value to set all elements of the new array to.
+*/
+template <class T>
+Array3D<T>::Array3D(int m, int n, int k, const T &val) : v_(0), m_(m), n_(n) ,
+	k_(k), ref_count_(0)
+{
+	initialize_(new T[m*n*k], m,n,k);
+	set_(val);
+	ref_count_ = new int;
+	*ref_count_ = 1;
+
+}
+
+/**
+
+	Create a new (m x n x k) array,  as a view of an existing one-dimensional
+	array stored in <b>C order</b>, i.e. right-most dimension varying fastest.  
+	(Often referred to as "row-major" ordering.)
+	Note that the storage for this pre-existing array will
+	never be garbage collected by the Array3D class.
+
+	@param m the first dimension of the new matrix.
+	@param n the second dimension of the new matrix.
+	@param k the third dimension of the new matrix.
+	@param a the one dimensional C array to use as data storage for
+		the array. 
+*/
+template <class T>
+Array3D<T>::Array3D(int m, int n, int k, T *a) : v_(0), m_(m), n_(n) ,
+	k_(k), ref_count_(0)
+{
+	initialize_(a, m, n, k);
+	ref_count_ = new int;
+	*ref_count_ = 2;		/* this avoids destorying original data. */
+
+}
+
+
+/**
+	Used for A[i][j][k] indexing.  The first [] operator returns
+	a conventional pointer which can be dereferenced using the
+	same [] notation.  
+	
+	If TNT_BOUNDS_CHECK macro is define, the left-most index 
+	is checked that it falls within the array bounds (via the
+	assert() macro.) 
+*/
+template <class T>
+inline T** Array3D<T>::operator[](int i) 
+{ 
+#ifdef TNT_BOUNDS_CHECK
+	assert(i >= 0);
+	assert(i < m_);
+#endif
+
+return v_[i]; 
+
+}
+
+template <class T>
+inline const T* const * Array3D<T>::operator[](int i) const { return v_[i]; }
+
+/**
+	Assign all elemnts of A to a constant scalar.
+*/
+template <class T>
+Array3D<T> & Array3D<T>::operator=(const T &a)
+{
+	set_(a);
+	return *this;
+}
+/**
+	Create a new of existing matrix.  Used in B = A.copy()
+	or in the construction of B, e.g. Array3D B(A.copy()), 
+	to create a new array that does not share data.
+
+*/
+template <class T>
+Array3D<T> Array3D<T>::copy() const
+{
+	Array3D A(m_, n_, k_);
+	copy_(A.begin_(), begin_(), m_*n_*k_);
+
+	return A;
+}
+
+
+/**
+	Copy the elements to from one array to another, in place.
+	That is B.inject(A), both A and B must conform (i.e. have
+	identical dimensions).
+
+	This differs from B = A.copy() in that references to B
+	before this assignment are also affected.  That is, if
+	we have 
+	<pre>
+	Array3D A(m,n,k);
+	Array3D C(m,n,k);
+	Array3D B(C);        // elements of B and C are shared. 
+
+</pre>
+	then B.inject(A) affects both and C, while B=A.copy() creates
+	a new array B which shares no data with C or A.
+
+	@param A the array from elements will be copied
+	@return an instance of the modifed array. That is, in B.inject(A),
+	it returns B.  If A and B are not conformat, no modifications to 
+	B are made.
+
+*/
+template <class T>
+Array3D<T> & Array3D<T>::inject(const Array3D &A)
+{
+	if (A.m_ == m_ &&  A.n_ == n_)
+		copy_(begin_(), A.begin_(), m_*n_);
+
+	return *this;
+}
+
+
+
+
+
+/**
+	Create a reference (shallow assignment) to another existing array.
+	In B.ref(A), B and A shared the same data and subsequent changes
+	to the array elements of one will be reflected in the other.
+	<p>
+	This is what operator= calls, and B=A and B.ref(A) are equivalent
+	operations.
+
+	@return The new referenced array: in B.ref(A), it returns B.
+*/
+template <class T>
+Array3D<T> & Array3D<T>::ref(const Array3D<T> &A)
+{
+	if (this != &A)
+	{
+		(*ref_count_) --;
+		if ( *ref_count_ < 1 )
+		{
+			destroy_();
+		}
+
+		m_ = A.m_;
+		n_ = A.n_;
+		k_ = A.k_;
+		v_ = A.v_;
+		ref_count_ = A.ref_count_;
+
+		(*ref_count_) ++ ;
+		
+	}
+	return *this;
+}
+
+/**
+	B = A is shorthand notation for B.ref(A).
+*/
+template <class T>
+Array3D<T> & Array3D<T>::operator=(const Array3D<T> &A)
+{
+	return ref(A);
+}
+
+/**
+	@return the size of the first dimension of the array.
+*/
+template <class T>
+inline int Array3D<T>::dim1() const { return m_; }
+
+/**
+	@return the size of the second dimension of the array.
+*/
+template <class T>
+inline int Array3D<T>::dim2() const { return n_; }
+
+/**
+	@return the size of the third (right-most) dimension of the array.
+*/
+template <class T>
+inline int Array3D<T>::dim3() const { return k_; }
+
+
+/**
+	@return the number of arrays that share the same storage area
+	as this one.  (Must be at least one.)
+*/
+template <class T>
+inline int Array3D<T>::ref_count() const
+{
+	return *ref_count_;
+}
+
+template <class T>
+Array3D<T>::~Array3D()
+{
+	(*ref_count_) --;
+
+	if (*ref_count_ < 1)
+		destroy_();
+}
+
+/* private internal functions */
+
+template <class T>
+void Array3D<T>::initialize_( T* data, int m, int n, int k)
+{
+
+	v_ = new T**[m];
+	v_[0] = new T*[m*n];
+	v_[0][0] = data;
+
+
+	for (int i=0; i<m; i++)
+	{
+		v_[i] = v_[0] + i * n;
+		for (int j=0; j<n; j++)
+			v_[i][j] = v_[0][0] + i * (n*k) + j * k;
+	}
+
+	m_ = m;
+	n_ = n;
+	k_ = k;
+}
+
+template <class T>
+void Array3D<T>::set_(const T& a)
+{
+	T *begin = &(v_[0][0][0]);
+	T *end = begin+ m_*n_*k_;
+
+	for (T* p=begin; p<end; p++)
+		*p = a;
+
+}
+
+template <class T>
+void Array3D<T>::copy_(T* p, const T* q, int len) const
+{
+	T *end = p + len;
+	while (p<end )
+		*p++ = *q++;
+
+}
+
+template <class T>
+void Array3D<T>::destroy_()
+{
+
+	if (v_ != 0)
+	{
+		delete[] (v_[0][0]);
+		delete[] (v_[0]);
+		delete[] (v_);
+	}
+
+	if (ref_count_ != 0)
+		delete ref_count_;
+}
+
+/**
+	@returns location of first element, i.e. A[0][0][0] (mutable).
+*/
+template <class T>
+const T* Array3D<T>::begin_() const { return &(v_[0][0][0]); }
+
+/**
+	@returns location of first element, i.e. A[0][0][0] (mutable).
+*/
+template <class T>
+T* Array3D<T>::begin_() { return &(v_[0][0][0]); }
+
+/**
+	Create a null (0x0x0) array.  
+*/
+template <class T>
+Array3D<T>::Array3D() : v_(0), m_(0), n_(0) 
+{
+	ref_count_ = new int;
+	*ref_count_ = 1;
+}
+
+} /* namespace TNT */
+
+#endif
+/* TNT_ARRAY3D_H */
+
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_array3d_utils.h b/bioimagesuite30_src/numerics/tnt/tnt_array3d_utils.h
new file mode 100644
index 0000000..433c32d
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_array3d_utils.h
@@ -0,0 +1,112 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+#ifndef TNT_ARRAY3D_UTILS_H
+#define TNT_ARRAY3D_UTILS_H
+
+#include <cstdlib>
+#include <cassert>
+
+namespace TNT
+{
+
+
+/**
+	Write an array to a character outstream.  Output format is one that can
+	be read back in via the in-stream operator: three integers
+	denoting the array dimensions (m x n x k), followed by m
+	(n x k) arrays.
+
+*/
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Array3D<T> &A)
+{
+    int M=A.dim1();
+    int N=A.dim2();
+    int K=A.dim3();
+
+    s << M << " " << N << " " << K << "\n";
+
+    for (int i=0; i<M; i++)
+    {
+        for (int j=0; j<N; j++)
+        {
+			for (int k=0; k<K; k++)
+            	s << A[i][j][k] << " ";
+			s << "\n";
+        }
+        s << "\n";
+    }
+
+
+    return s;
+}
+
+/**
+	Read an array from a character stream.  Input format
+	is three integers, denoting the dimensions (m x n x k), followed
+	by m*n*k whitespace-separated elments in "row-major" order
+	(i.e. right-most dimension varying fastest.)  Newlines
+	are ignored.
+
+	<p>
+	Note: the array being read into references new memory
+	storage. If the intent is to fill an existing conformant
+	array, use <code> cin >> B;  A.inject(B) ); </code>
+	instead or read the elements in one-a-time by hand.
+
+	@param s the charater to read from (typically <code>std::in</code>)
+	@param A the array to read into.
+*/
+template <class T>
+std::istream& operator>>(std::istream &s, Array3D<T> &A)
+{
+
+    int M, N, K;
+
+    s >> M >> N >> K;
+
+	Array3D<T> B(M,N,K);
+
+    for (int i=0; i<M; i++)
+        for (int j=0; j<N; j++)
+			for (int k=0; k<K; k++)
+            	s >>  B[i][j][k];
+
+	A = B;
+    return s;
+}
+
+
+
+
+} // namespace TNT
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_cmat.h b/bioimagesuite30_src/numerics/tnt/tnt_cmat.h
new file mode 100644
index 0000000..bbdc48b
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_cmat.h
@@ -0,0 +1,613 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Template Numerical Toolkit (TNT)
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+
+// C compatible matrix: row-oriented, 0-based [i][j] and 1-based (i,j) indexing
+//
+
+#ifndef TNT_CMAT_H
+#define TNT_CMAT_H
+
+#include "tnt_subscript.h"
+#include "tnt_vec.h"
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <strstream>
+
+namespace TNT
+{
+
+/**
+ <b>[Deprecatred]</b>  Value-based vector class from pre-1.0
+ 	TNT version.  Kept here for backward compatiblity, but should
+	use the newer TNT::Array2D classes instead.
+
+*/
+
+template <class T>
+class Matrix 
+{
+
+
+  public:
+
+    typedef Subscript   size_type;
+    typedef         T   value_type;
+    typedef         T   element_type;
+    typedef         T*  pointer;
+    typedef         T*  iterator;
+    typedef         T&  reference;
+    typedef const   T*  const_iterator;
+    typedef const   T&  const_reference;
+
+    Subscript lbound() const { return 1;}
+ 
+  protected:
+    Subscript m_;
+    Subscript n_;
+    Subscript mn_;      // total size
+    T* v_;                  
+    T** row_;           
+    T* vm1_ ;       // these point to the same data, but are 1-based 
+    T** rowm1_;
+
+    // internal helper function to create the array
+    // of row pointers
+
+    void initialize(Subscript M, Subscript N)
+    {
+        mn_ = M*N;
+        m_ = M;
+        n_ = N;
+
+        v_ = new T[mn_]; 
+        row_ = new T*[M];
+        rowm1_ = new T*[M];
+
+        assert(v_  != NULL);
+        assert(row_  != NULL);
+        assert(rowm1_ != NULL);
+
+        T* p = v_;              
+        vm1_ = v_ - 1;
+        for (Subscript i=0; i<M; i++)
+        {
+            row_[i] = p;
+            rowm1_[i] = p-1;
+            p += N ;
+            
+        }
+
+        rowm1_ -- ;     // compensate for 1-based offset
+    }
+   
+    void copy(const T*  v)
+    {
+        Subscript N = m_ * n_;
+        Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+        Subscript Nmod4 = N & 3;
+        Subscript N4 = N - Nmod4;
+
+        for (i=0; i<N4; i+=4)
+        {
+            v_[i] = v[i];
+            v_[i+1] = v[i+1];
+            v_[i+2] = v[i+2];
+            v_[i+3] = v[i+3];
+        }
+
+        for (i=N4; i< N; i++)
+            v_[i] = v[i];
+#else
+
+        for (i=0; i< N; i++)
+            v_[i] = v[i];
+#endif      
+    }
+
+    void set(const T& val)
+    {
+        Subscript N = m_ * n_;
+        Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+        Subscript Nmod4 = N & 3;
+        Subscript N4 = N - Nmod4;
+
+        for (i=0; i<N4; i+=4)
+        {
+            v_[i] = val;
+            v_[i+1] = val;
+            v_[i+2] = val;
+            v_[i+3] = val; 
+        }
+
+        for (i=N4; i< N; i++)
+            v_[i] = val;
+#else
+
+        for (i=0; i< N; i++)
+            v_[i] = val;
+        
+#endif      
+    }
+    
+
+    
+    void destroy()
+    {     
+        /* do nothing, if no memory has been previously allocated */
+        if (v_ == NULL) return ;
+
+        /* if we are here, then matrix was previously allocated */
+        if (v_ != NULL) delete [] (v_);     
+        if (row_ != NULL) delete [] (row_);
+
+        /* return rowm1_ back to original value */
+        rowm1_ ++;
+        if (rowm1_ != NULL ) delete [] (rowm1_);
+    }
+
+
+  public:
+
+    operator T**(){ return  row_; }
+    operator T**() const { return row_; }
+
+
+    Subscript size() const { return mn_; }
+
+    // constructors
+
+    Matrix() : m_(0), n_(0), mn_(0), v_(0), row_(0), vm1_(0), rowm1_(0) {};
+
+    Matrix(const Matrix<T> &A)
+    {
+        initialize(A.m_, A.n_);
+        copy(A.v_);
+    }
+
+    Matrix(Subscript M, Subscript N, const T& value = T())
+    {
+        initialize(M,N);
+        set(value);
+    }
+
+    Matrix(Subscript M, Subscript N, const T* v)
+    {
+        initialize(M,N);
+        copy(v);
+    }
+
+    Matrix(Subscript M, Subscript N, const char *s)
+    {
+        initialize(M,N);
+        std::istrstream ins(s);
+
+        Subscript i, j;
+
+        for (i=0; i<M; i++)
+            for (j=0; j<N; j++)
+                ins >> row_[i][j];
+    }
+
+    // destructor
+    //
+    ~Matrix()
+    {
+        destroy();
+    }
+
+
+    // reallocating
+    //
+    Matrix<T>& newsize(Subscript M, Subscript N)
+    {
+        if (num_rows() == M && num_cols() == N)
+            return *this;
+
+        destroy();
+        initialize(M,N);
+        
+        return *this;
+    }
+
+
+
+
+    // assignments
+    //
+    Matrix<T>& operator=(const Matrix<T> &A)
+    {
+        if (v_ == A.v_)
+            return *this;
+
+        if (m_ == A.m_  && n_ == A.n_)      // no need to re-alloc
+            copy(A.v_);
+
+        else
+        {
+            destroy();
+            initialize(A.m_, A.n_);
+            copy(A.v_);
+        }
+
+        return *this;
+    }
+        
+    Matrix<T>& operator=(const T& scalar)
+    { 
+        set(scalar); 
+        return *this;
+    }
+
+
+    Subscript dim(Subscript d) const 
+    {
+#ifdef TNT_BOUNDS_CHECK
+        assert( d >= 1);
+        assert( d <= 2);
+#endif
+        return (d==1) ? m_ : ((d==2) ? n_ : 0); 
+    }
+
+    Subscript num_rows() const { return m_; }
+    Subscript num_cols() const { return n_; }
+
+
+
+
+    inline T* operator[](Subscript i)
+    {
+#ifdef TNT_BOUNDS_CHECK
+        assert(0<=i);
+        assert(i < m_) ;
+#endif
+        return row_[i];
+    }
+
+    inline const T* operator[](Subscript i) const
+    {
+#ifdef TNT_BOUNDS_CHECK
+        assert(0<=i);
+        assert(i < m_) ;
+#endif
+        return row_[i];
+    }
+
+    inline reference operator()(Subscript i)
+    { 
+#ifdef TNT_BOUNDS_CHECK
+        assert(1<=i);
+        assert(i <= mn_) ;
+#endif
+        return vm1_[i]; 
+    }
+
+    inline const_reference operator()(Subscript i) const
+    { 
+#ifdef TNT_BOUNDS_CHECK
+        assert(1<=i);
+        assert(i <= mn_) ;
+#endif
+        return vm1_[i]; 
+    }
+
+
+
+    inline reference operator()(Subscript i, Subscript j)
+    { 
+#ifdef TNT_BOUNDS_CHECK
+        assert(1<=i);
+        assert(i <= m_) ;
+        assert(1<=j);
+        assert(j <= n_);
+#endif
+        return  rowm1_[i][j]; 
+    }
+
+
+    
+    inline const_reference operator() (Subscript i, Subscript j) const
+    {
+#ifdef TNT_BOUNDS_CHECK
+        assert(1<=i);
+        assert(i <= m_) ;
+        assert(1<=j);
+        assert(j <= n_);
+#endif
+        return rowm1_[i][j]; 
+    }
+
+
+
+
+};
+
+
+/* ***************************  I/O  ********************************/
+
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Matrix<T> &A)
+{
+    Subscript M=A.num_rows();
+    Subscript N=A.num_cols();
+
+    s << M << " " << N << "\n";
+
+    for (Subscript i=0; i<M; i++)
+    {
+        for (Subscript j=0; j<N; j++)
+        {
+            s << A[i][j] << " ";
+        }
+        s << "\n";
+    }
+
+
+    return s;
+}
+
+template <class T>
+std::istream& operator>>(std::istream &s, Matrix<T> &A)
+{
+
+    Subscript M, N;
+
+    s >> M >> N;
+
+    if ( !(M == A.num_rows() && N == A.num_cols() ))
+    {
+        A.newsize(M,N);
+    }
+
+
+    for (Subscript i=0; i<M; i++)
+        for (Subscript j=0; j<N; j++)
+        {
+            s >>  A[i][j];
+        }
+
+
+    return s;
+}
+
+// *******************[ basic matrix algorithms ]***************************
+
+
+template <class T>
+Matrix<T> operator+(const Matrix<T> &A, 
+    const Matrix<T> &B)
+{
+    Subscript M = A.num_rows();
+    Subscript N = A.num_cols();
+
+    assert(M==B.num_rows());
+    assert(N==B.num_cols());
+
+    Matrix<T> tmp(M,N);
+    Subscript i,j;
+
+    for (i=0; i<M; i++)
+        for (j=0; j<N; j++)
+            tmp[i][j] = A[i][j] + B[i][j];
+
+    return tmp;
+}
+
+template <class T>
+Matrix<T> operator-(const Matrix<T> &A, 
+    const Matrix<T> &B)
+{
+    Subscript M = A.num_rows();
+    Subscript N = A.num_cols();
+
+    assert(M==B.num_rows());
+    assert(N==B.num_cols());
+
+    Matrix<T> tmp(M,N);
+    Subscript i,j;
+
+    for (i=0; i<M; i++)
+        for (j=0; j<N; j++)
+            tmp[i][j] = A[i][j] - B[i][j];
+
+    return tmp;
+}
+
+template <class T>
+Matrix<T> mult_element(const Matrix<T> &A, 
+    const Matrix<T> &B)
+{
+    Subscript M = A.num_rows();
+    Subscript N = A.num_cols();
+
+    assert(M==B.num_rows());
+    assert(N==B.num_cols());
+
+    Matrix<T> tmp(M,N);
+    Subscript i,j;
+
+    for (i=0; i<M; i++)
+        for (j=0; j<N; j++)
+            tmp[i][j] = A[i][j] * B[i][j];
+
+    return tmp;
+}
+
+
+template <class T>
+Matrix<T> transpose(const Matrix<T> &A)
+{
+    Subscript M = A.num_rows();
+    Subscript N = A.num_cols();
+
+    Matrix<T> S(N,M);
+    Subscript i, j;
+
+    for (i=0; i<M; i++)
+        for (j=0; j<N; j++)
+            S[j][i] = A[i][j];
+
+    return S;
+}
+
+
+    
+template <class T>
+inline Matrix<T> matmult(const Matrix<T>  &A, 
+    const Matrix<T> &B)
+{
+
+#ifdef TNT_BOUNDS_CHECK
+    assert(A.num_cols() == B.num_rows());
+#endif
+
+    Subscript M = A.num_rows();
+    Subscript N = A.num_cols();
+    Subscript K = B.num_cols();
+
+    Matrix<T> tmp(M,K);
+    T sum;
+
+    for (Subscript i=0; i<M; i++)
+    for (Subscript k=0; k<K; k++)
+    {
+        sum = 0;
+        for (Subscript j=0; j<N; j++)
+            sum = sum +  A[i][j] * B[j][k];
+
+        tmp[i][k] = sum; 
+    }
+
+    return tmp;
+}
+
+template <class T>
+inline Matrix<T> operator*(const Matrix<T>  &A, 
+    const Matrix<T> &B)
+{
+    return matmult(A,B);
+}
+
+template <class T>
+inline int matmult(Matrix<T>& C, const Matrix<T>  &A, 
+    const Matrix<T> &B)
+{
+
+    assert(A.num_cols() == B.num_rows());
+
+    Subscript M = A.num_rows();
+    Subscript N = A.num_cols();
+    Subscript K = B.num_cols();
+
+    C.newsize(M,K);
+
+    T sum;
+
+    const T* row_i;
+    const T* col_k;
+
+    for (Subscript i=0; i<M; i++)
+    for (Subscript k=0; k<K; k++)
+    {
+        row_i  = &(A[i][0]);
+        col_k  = &(B[0][k]);
+        sum = 0;
+        for (Subscript j=0; j<N; j++)
+        {
+            sum  += *row_i * *col_k;
+            row_i++;
+            col_k += K;
+        }
+        C[i][k] = sum; 
+    }
+
+    return 0;
+}
+
+
+template <class T>
+Vector<T> matmult(const Matrix<T>  &A, const Vector<T> &x)
+{
+
+#ifdef TNT_BOUNDS_CHECK
+    assert(A.num_cols() == x.dim());
+#endif
+
+    Subscript M = A.num_rows();
+    Subscript N = A.num_cols();
+
+    Vector<T> tmp(M);
+    T sum;
+
+    for (Subscript i=0; i<M; i++)
+    {
+        sum = 0;
+        const T* rowi = A[i];
+        for (Subscript j=0; j<N; j++)
+            sum = sum +  rowi[j] * x[j];
+
+        tmp[i] = sum; 
+    }
+
+    return tmp;
+}
+
+template <class T>
+inline Vector<T> operator*(const Matrix<T>  &A, const Vector<T> &x)
+{
+    return matmult(A,x);
+}
+
+} // namespace TNT
+
+#endif
+// CMAT_H
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_fortran_array1d.h b/bioimagesuite30_src/numerics/tnt/tnt_fortran_array1d.h
new file mode 100644
index 0000000..9953213
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_fortran_array1d.h
@@ -0,0 +1,340 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Template Numerical Toolkit (TNT): One-dimensional Fortran numerical array
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+
+
+#ifndef TNT_FORTRAN_ARRAY1D_H
+#define TNT_FORTRAN_ARRAY1D_H
+
+#include <cstdlib>
+#include <iostream>
+#ifdef TNT_BOUNDS_CHECK
+#include <assert.h>
+#endif
+#include "tnt_array1d.h"
+
+namespace TNT
+{
+
+/**
+	Templated one-dimensional, numerical array which
+	looks like a conventional Fortran array.  This is 
+	useful when integrating with C/C++ codes translated
+	from Fortran.  Indexing is via the A(i) notation and A(1)
+	is the first element.
+	
+	<p>
+	Array assignment is by reference (i.e. shallow assignment).
+	That is, B=A implies that the A and B point to the
+	same array, so modifications to the elements of A
+	will be reflected in B. If an independent copy
+	is required, then B = A.copy() can be used.  Note
+	that this facilitates returning arrays from functions
+	without relying on compiler optimizations to eliminate
+	extensive data copying.
+
+	<p>
+	This class employs its own garbage collection via
+	the use of reference counts.  That is, whenever
+	an internal array storage no longer has any references
+	to it, it is destoryed.
+*/
+template <class T>
+class Fortran_Array1D 
+{
+
+
+  private: 
+  		Array1D<T> A_;
+
+  public:
+
+    typedef         T   value_type;
+
+	       Fortran_Array1D();
+	       Fortran_Array1D(int n);
+	       Fortran_Array1D(int n,  T *a);
+	       Fortran_Array1D(int n, const T &a);
+    inline Fortran_Array1D(const Fortran_Array1D &A);
+	inline Fortran_Array1D & operator=(const T &a);
+	inline Fortran_Array1D & operator=(const Fortran_Array1D &A);
+	inline Fortran_Array1D & ref(const Fortran_Array1D &A);
+	       Fortran_Array1D copy();
+		   Fortran_Array1D & inject(const Fortran_Array1D & A);
+	inline T& operator()(int i);
+	inline const T& operator()(int i) const ;
+	inline int dim() const;
+	inline int dim1() const;
+	inline int ref_count() const;
+               ~Fortran_Array1D();
+
+
+};
+
+/**
+	Create a null (0-length) array.  
+*/
+template <class T>
+Fortran_Array1D<T>::Fortran_Array1D() : A_() {}
+
+
+/**
+	Copy constructor. Array data is NOT copied, but shared.
+	Thus, in Fortran_Array1D B(A), subsequent changes to A will
+	be reflected in B.  For an indepent copy of A, use
+	Fortran_Array1D B(A.copy()), or B = A.copy(), instead.
+*/
+template <class T>
+Fortran_Array1D<T>::Fortran_Array1D(const Fortran_Array1D<T> &A) : A_(A.A_) {}
+
+
+
+/**
+	Create a new (n) array, WIHOUT initializing array elements.
+	To create an initialized array of constants, see Fortran_Array1D(n, value).
+
+	<p>
+	This version avoids the O(n) initialization overhead and
+	is used just before manual assignment.
+
+	@param m the dimension of the new matrix.
+*/
+template <class T>
+Fortran_Array1D<T>::Fortran_Array1D(int n) : A_(n) {}
+
+
+
+/**
+	Create a new n-length array,  initializing array elements to
+	constant specified by argument.  Most often used to
+	create an array of zeros, as in A(n, 0.0).
+
+	@param m the dimension of the new matrix.
+	@param val the constant value to set all elements of the new array to.
+*/
+template <class T>
+Fortran_Array1D<T>::Fortran_Array1D(int n, const T &val) : A_(n, val) {}
+
+
+/**
+	Create a new  n-length array,  as a view of an existing one-dimensional
+	C array.  (Note that the storage for this pre-existing array will
+	never be garbage collected by the Fortran_Array1D class.)
+
+	@param m the first dimension of the new matrix.
+	@param n the second dimension of the new matrix.
+	@param a the one dimensional C array to use as data storage for
+		the array. 
+*/
+template <class T>
+Fortran_Array1D<T>::Fortran_Array1D(int n, T *a) : A_(n, a) {}
+
+
+
+
+/**
+	Elements are accessed via A(i) indexing.  
+	
+	If TNT_BOUNDS_CHECK macro is defined, the indices 
+	are checked that they falls within the array bounds (via the
+	assert() macro.) 
+*/
+template <class T>
+inline T& Fortran_Array1D<T>::operator()(int i) 
+{ 
+#ifdef TNT_BOUNDS_CHECK
+	assert(i >= 1);
+	assert(i <= A_.dim1());
+#endif
+
+	return A_[i-1]; 
+
+}
+
+/**
+	Read-only version of A(i,j) indexing.  
+	
+	If TNT_BOUNDS_CHECK macro is defined, the indices 
+	are checked that they falls within the array bounds (via the
+	assert() macro.) 
+*/
+template <class T>
+inline const T& Fortran_Array1D<T>::operator()(int i)  const
+{ 
+#ifdef TNT_BOUNDS_CHECK
+	assert(i >= 1);
+	assert(i <= A_.dim1());
+#endif
+
+	return A_[i-1]; 
+
+}
+
+
+/**
+	Assign all elemnts of A to a constant scalar.
+*/
+template <class T>
+Fortran_Array1D<T> & Fortran_Array1D<T>::operator=(const T &a)
+{
+	A_ = a;
+	return *this;
+}
+/**
+	Create a new of existing matrix.  Used in B = A.copy()
+	or in the construction of B, e.g. Fortran_Array1D B(A.copy()), 
+	to create a new array that does not share data.
+
+*/
+template <class T>
+Fortran_Array1D<T> Fortran_Array1D<T>::copy()
+{
+
+	Fortran_Array1D B;
+	
+	B.A_= A_.copy();
+	return B;
+}
+
+
+/**
+	Copy the elements to from one array to another, in place.
+	That is B.inject(A), both A and B must conform (i.e. have
+	identical dimensions).
+
+	This differs from B = A.copy() in that references to B
+	before this assignment are also affected.  That is, if
+	we have 
+	<pre>
+	Fortran_Array1D A(n);
+	Fortran_Array1D C(n);
+	Fortran_Array1D B(C);        // elements of B and C are shared. 
+
+</pre>
+	then B.inject(A) affects both and C, while B=A.copy() creates
+	a new array B which shares no data with C or A.
+
+	@param A the array from elements will be copied
+	@return an instance of the modifed array. That is, in B.inject(A),
+	it returns B.  If A and B are not conformat, no modifications to 
+	B are made.
+
+*/
+template <class T>
+Fortran_Array1D<T> & Fortran_Array1D<T>::inject(const Fortran_Array1D &A)
+{
+	A_.inject(A.A_);
+
+	return *this;
+}
+
+
+
+
+
+/**
+	Create a reference (shallow assignment) to another existing array.
+	In B.ref(A), B and A shared the same data and subsequent changes
+	to the array elements of one will be reflected in the other.
+	<p>
+	This is what operator= calls, and B=A and B.ref(A) are equivalent
+	operations.
+
+	@return The new referenced array: in B.ref(A), it returns B.
+*/
+template <class T>
+Fortran_Array1D<T> & Fortran_Array1D<T>::ref(const Fortran_Array1D<T> &A)
+{
+	A_.ref(A.A_);
+	return *this;
+}
+
+/**
+	B = A is shorthand notation for B.ref(A).
+*/
+template <class T>
+Fortran_Array1D<T> & Fortran_Array1D<T>::operator=(const Fortran_Array1D<T> &A)
+{
+	return ref(A);
+}
+
+/**
+	@return the size (dimension of) the array.
+*/
+template <class T>
+inline int Fortran_Array1D<T>::dim1() const { return A_.dim1(); }
+
+
+/**
+	@return the size (dimension of) the array.
+*/
+template <class T>
+inline int Fortran_Array1D<T>::dim() const { return A_.dim(); }
+
+
+
+
+/**
+	@return the number of arrays that share the same storage area
+	as this one.  (Must be at least one.)
+*/
+template <class T>
+inline int Fortran_Array1D<T>::ref_count() const { return A_.ref_count(); }
+
+template <class T>
+Fortran_Array1D<T>::~Fortran_Array1D()
+{
+}
+
+
+
+
+} /* namespace TNT */
+
+#endif
+/* TNT_FORTRAN_ARRAY1D_H */
+
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_fortran_array1d_utils.h b/bioimagesuite30_src/numerics/tnt/tnt_fortran_array1d_utils.h
new file mode 100644
index 0000000..cd80919
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_fortran_array1d_utils.h
@@ -0,0 +1,92 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+#ifndef TNT_FORTRAN_ARRAY1D_UTILS_H
+#define TNT_FORTRAN_ARRAY1D_UTILS_H
+
+#include <iostream>
+
+namespace TNT
+{
+
+
+/**
+	Write an array to a character outstream.  Output format is one that can
+	be read back in via the in-stream operator: one integer
+	denoting the array dimension (n), followed by n elements,
+	one per line.  
+
+*/
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Fortran_Array1D<T> &A)
+{
+    int N=A.dim1();
+
+    s << N << "\n";
+    for (int j=1; j<=N; j++)
+    {
+       s << A(j) << "\n";
+    }
+    s << "\n";
+
+    return s;
+}
+
+/**
+	Read an array from a character stream.  Input format
+	is one integer, denoting the dimension (n), followed
+	by n whitespace-separated elments.  Newlines are ignored
+
+	<p>
+	Note: the array being read into references new memory
+	storage. If the intent is to fill an existing conformant
+	array, use <code> cin >> B;  A.inject(B) ); </code>
+	instead or read the elements in one-a-time by hand.
+
+	@param s the charater to read from (typically <code>std::in</code>)
+	@param A the array to read into.
+*/
+template <class T>
+std::istream& operator>>(std::istream &s, Fortran_Array1D<T> &A)
+{
+	int N;
+	s >> N;
+
+	Fortran_Array1D<T> B(N);
+	for (int i=1; i<=N; i++)
+		s >> B(i);
+	A = B;
+	return s;
+}
+
+
+
+} // namespace TNT
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_fortran_array2d.h b/bioimagesuite30_src/numerics/tnt/tnt_fortran_array2d.h
new file mode 100644
index 0000000..ad624cf
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_fortran_array2d.h
@@ -0,0 +1,356 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Template Numerical Toolkit (TNT): Two-dimensional Fortran numerical array
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+
+
+#ifndef TNT_FORTRAN_ARRAY2D_H
+#define TNT_FORTRAN_ARRAY2D_H
+
+#include <cstdlib>
+#include <iostream>
+
+#ifdef TNT_BOUNDS_CHECK
+#include <assert.h>
+#endif
+
+#include "tnt_array2d.h"
+
+namespace TNT
+{
+
+/**
+	Templated two-dimensional, numerical array which
+	looks like a conventional Fortran array.  This is 
+	useful when integrating with C/C++ codes translated
+	from Fortran.  Storage corresponds to conventional Fortran ordering.
+	That is, the left-most dimension varies fastest.
+	Indexing is via the A(i,j) notation and A(1,1)
+	is the first element.
+	
+	<p>
+	Array assignment is by reference (i.e. shallow assignment).
+	That is, B=A implies that the A and B point to the
+	same array, so modifications to the elements of A
+	will be reflected in B. If an independent copy
+	is required, then B = A.copy() can be used.  Note
+	that this facilitates returning arrays from functions
+	without relying on compiler optimizations to eliminate
+	extensive data copying.
+
+	<p>
+	This class employs its own garbage collection via
+	the use of reference counts.  That is, whenever
+	an internal array storage no longer has any references
+	to it, it is destoryed.
+*/
+template <class T>
+class Fortran_Array2D 
+{
+
+
+  private: 
+  		/* For an (mxn) array, we internally keep an (nxm) "transposed"
+		   C array and access A(i,j) as A[j-1][i-1].  The "-1" operation
+		   is inlined in a tight loop and should be easily optimized.
+		*/
+  		Array2D<T> A_;
+
+  public:
+
+    typedef         T   value_type;
+
+	       Fortran_Array2D();
+	       Fortran_Array2D(int m, int n);
+	       Fortran_Array2D(int m, int n,  T *a);
+	       Fortran_Array2D(int m, int n, const T &a);
+    inline Fortran_Array2D(const Fortran_Array2D &A);
+	inline Fortran_Array2D & operator=(const T &a);
+	inline Fortran_Array2D & operator=(const Fortran_Array2D &A);
+	inline Fortran_Array2D & ref(const Fortran_Array2D &A);
+	       Fortran_Array2D copy();
+		   Fortran_Array2D & inject(const Fortran_Array2D & A);
+	inline T& operator()(int i, int j);
+	inline const T& operator()(int i, int j) const ;
+	inline int dim1() const;
+	inline int dim2() const;
+	inline int ref_count() const;
+               ~Fortran_Array2D();
+
+
+};
+
+/**
+	Create a null (0x0x0) array.  
+*/
+template <class T>
+Fortran_Array2D<T>::Fortran_Array2D() : A_() {}
+
+
+/**
+	Copy constructor. Array data is NOT copied, but shared.
+	Thus, in Fortran_Array2D B(A), subsequent changes to A will
+	be reflected in B.  For an indepent copy of A, use
+	Fortran_Array2D B(A.copy()), or B = A.copy(), instead.
+*/
+template <class T>
+Fortran_Array2D<T>::Fortran_Array2D(const Fortran_Array2D<T> &A) : A_(A.A_) {}
+
+
+
+/**
+	Create a new (m x n) array, WIHOUT initializing array elements.
+	To create an initialized array of constants, see Fortran_Array2D(m,n, value).
+
+	<p>
+	This version avoids the O(m*n) initialization overhead and
+	is used just before manual assignment.
+
+	@param m the first dimension of the new matrix.
+	@param n the second dimension of the new matrix.
+*/
+template <class T>
+Fortran_Array2D<T>::Fortran_Array2D(int m, int n) : A_(n,m) {}
+
+
+
+/**
+	Create a new (m x n ) array,  initializing array elements to
+	constant specified by argument.  Most often used to
+	create an array of zeros, as in A(m, n, k, 0.0).
+
+	@param m the first dimension of the new matrix.
+	@param n the second dimension of the new matrix.
+	@param val the constant value to set all elements of the new array to.
+*/
+template <class T>
+Fortran_Array2D<T>::Fortran_Array2D(int m, int n, const T &val) : A_(n, m, val) {}
+
+
+/**
+
+	Create a new (m x n) array,  as a view of an existing one-dimensional
+	C array, with elements stored in <b>Fortran order</b>, i.e. right-most dimension
+	varying fastest. (Often referred to as "column-major" ordering.)
+	Note that the storage for this pre-existing array will
+	never be garbage collected by the Fortran_Array2D class.
+
+
+	@param m the first dimension of the new matrix.
+	@param n the second dimension of the new matrix.
+	@param a the one dimensional C array to use as data storage for
+		the array. 
+*/
+template <class T>
+Fortran_Array2D<T>::Fortran_Array2D(int m, int n, T *a) : A_(n, m, a) {}
+
+
+
+
+/**
+	Elements are accessed via A(i,j) indexing.  
+	
+	If TNT_BOUNDS_CHECK macro is defined, the indices 
+	are checked that they falls within the array bounds (via the
+	assert() macro.) 
+*/
+template <class T>
+inline T& Fortran_Array2D<T>::operator()(int i, int j) 
+{ 
+#ifdef TNT_BOUNDS_CHECK
+	assert(j >= 1);
+	assert(j <= A_.dim1());
+	assert(i >= 1);
+	assert(i <= A_.dim2());
+#endif
+
+	return A_[j-1][i-1]; 
+
+}
+
+/**
+	Read-only version of A(i,j) indexing.  
+	
+	If TNT_BOUNDS_CHECK macro is defined, the indices 
+	are checked that they falls within the array bounds (via the
+	assert() macro.) 
+*/
+template <class T>
+inline const T& Fortran_Array2D<T>::operator()(int i, int j)  const
+{ 
+#ifdef TNT_BOUNDS_CHECK
+	assert(j >= 1);
+	assert(j <= A_.dim1());
+	assert(i >= 1);
+	assert(i <= A_.dim2());
+#endif
+
+	return A_[j-1][i-1]; 
+
+}
+
+
+/**
+	Assign all elemnts of A to a constant scalar.
+*/
+template <class T>
+Fortran_Array2D<T> & Fortran_Array2D<T>::operator=(const T &a)
+{
+	A_ = a;
+	return *this;
+}
+/**
+	Create a new of existing matrix.  Used in B = A.copy()
+	or in the construction of B, e.g. Fortran_Array2D B(A.copy()), 
+	to create a new array that does not share data.
+
+*/
+template <class T>
+Fortran_Array2D<T> Fortran_Array2D<T>::copy()
+{
+
+	Fortran_Array2D B;
+	
+	B.A_= A_.copy();
+	return B;
+}
+
+
+/**
+	Copy the elements to from one array to another, in place.
+	That is B.inject(A), both A and B must conform (i.e. have
+	identical dimensions).
+
+	This differs from B = A.copy() in that references to B
+	before this assignment are also affected.  That is, if
+	we have 
+	<pre>
+	Fortran_Array2D A(m,n);
+	Fortran_Array2D C(m,n);
+	Fortran_Array2D B(C);        // elements of B and C are shared. 
+
+</pre>
+	then B.inject(A) affects both and C, while B=A.copy() creates
+	a new array B which shares no data with C or A.
+
+	@param A the array from elements will be copied
+	@return an instance of the modifed array. That is, in B.inject(A),
+	it returns B.  If A and B are not conformat, no modifications to 
+	B are made.
+
+*/
+template <class T>
+Fortran_Array2D<T> & Fortran_Array2D<T>::inject(const Fortran_Array2D &A)
+{
+	A_.inject(A.A_);
+
+	return *this;
+}
+
+
+
+
+
+/**
+	Create a reference (shallow assignment) to another existing array.
+	In B.ref(A), B and A shared the same data and subsequent changes
+	to the array elements of one will be reflected in the other.
+	<p>
+	This is what operator= calls, and B=A and B.ref(A) are equivalent
+	operations.
+
+	@return The new referenced array: in B.ref(A), it returns B.
+*/
+template <class T>
+Fortran_Array2D<T> & Fortran_Array2D<T>::ref(const Fortran_Array2D<T> &A)
+{
+	A_.ref(A.A_);
+	return *this;
+}
+
+/**
+	B = A is shorthand notation for B.ref(A).
+*/
+template <class T>
+Fortran_Array2D<T> & Fortran_Array2D<T>::operator=(const Fortran_Array2D<T> &A)
+{
+	return ref(A);
+}
+
+/**
+	@return the size of the first dimension of the array.
+*/
+template <class T>
+inline int Fortran_Array2D<T>::dim1() const { return A_.dim2(); }
+
+/**
+	@return the size of the second dimension of the array.
+*/
+template <class T>
+inline int Fortran_Array2D<T>::dim2() const { return A_.dim1(); }
+
+
+
+/**
+	@return the number of arrays that share the same storage area
+	as this one.  (Must be at least one.)
+*/
+template <class T>
+inline int Fortran_Array2D<T>::ref_count() const { return A_.ref_count(); }
+
+template <class T>
+Fortran_Array2D<T>::~Fortran_Array2D()
+{
+}
+
+
+
+
+} /* namespace TNT */
+
+#endif
+/* TNT_FORTRAN_ARRAY2D_H */
+
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_fortran_array2d_utils.h b/bioimagesuite30_src/numerics/tnt/tnt_fortran_array2d_utils.h
new file mode 100644
index 0000000..07c6b88
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_fortran_array2d_utils.h
@@ -0,0 +1,109 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+#ifndef TNT_FORTRAN_ARRAY2D_UTILS_H
+#define TNT_FORTRAN_ARRAY2D_UTILS_H
+
+#include <iostream>
+
+namespace TNT
+{
+
+
+/**
+	Write an array to a character outstream.  Output format is one that can
+	be read back in via the in-stream operator: two integers
+	denoting the array dimensions (m x n), followed by m
+	lines of n  elements.
+
+*/
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Fortran_Array2D<T> &A)
+{
+    int M=A.dim1();
+    int N=A.dim2();
+
+    s << M << " " << N << "\n";
+
+    for (int i=1; i<=M; i++)
+    {
+        for (int j=1; j<=N; j++)
+        {
+            s << A(i,j) << " ";
+        }
+        s << "\n";
+    }
+
+
+    return s;
+}
+
+/**
+	Read an array from a character stream.  Input format
+	is two integers, denoting the dimensions (m x n), followed
+	by m*n whitespace-separated elments in "row-major" order
+	(i.e. right-most dimension varying fastest.)  Newlines
+	are ignored.
+
+	<p>
+	Note: the array being read into references new memory
+	storage. If the intent is to fill an existing conformant
+	array, use <code> cin >> B;  A.inject(B) ); </code>
+	instead or read the elements in one-a-time by hand.
+
+	@param s the charater to read from (typically <code>std::in</code>)
+	@param A the array to read into.
+*/
+template <class T>
+std::istream& operator>>(std::istream &s, Fortran_Array2D<T> &A)
+{
+
+    int M, N;
+
+    s >> M >> N;
+
+	Fortran_Array2D<T> B(M,N);
+
+    for (int i=1; i<=M; i++)
+        for (int j=1; j<=N; j++)
+        {
+            s >>  B(i,j);
+        }
+
+	A = B;
+    return s;
+}
+
+
+
+
+} // namespace TNT
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_fortran_array3d.h b/bioimagesuite30_src/numerics/tnt/tnt_fortran_array3d.h
new file mode 100644
index 0000000..4affe3a
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_fortran_array3d.h
@@ -0,0 +1,367 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Template Numerical Toolkit (TNT): Three-dimensional Fortran numerical array
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+
+
+#ifndef TNT_FORTRAN_ARRAY3D_H
+#define TNT_FORTRAN_ARRAY3D_H
+
+#include <cstdlib>
+#include <iostream>
+#ifdef TNT_BOUNDS_CHECK
+#include <assert.h>
+#endif
+#include "tnt_array3d.h"
+
+namespace TNT
+{
+
+/**
+	Templated three-dimensional, numerical array which
+	looks like a conventional Fortran array.  This is 
+	useful when integrating with C/C++ codes translated
+	from Fortran.  Storage corresponds to conventional Fortran ordering.
+	That is, the left-most dimension varies fastest.
+	Indexing is via the A(i,j,k) notation and A(1,1,1)
+	is the first element.
+	
+	<p>
+	Array assignment is by reference (i.e. shallow assignment).
+	That is, B=A implies that the A and B point to the
+	same array, so modifications to the elements of A
+	will be reflected in B. If an independent copy
+	is required, then B = A.copy() can be used.  Note
+	that this facilitates returning arrays from functions
+	without relying on compiler optimizations to eliminate
+	extensive data copying.
+
+	<p>
+	This class employs its own garbage collection via
+	the use of reference counts.  That is, whenever
+	an internal array storage no longer has any references
+	to it, it is destoryed.
+*/
+template <class T>
+class Fortran_Array3D 
+{
+
+
+  private: 
+
+
+  		/* For an (mxnxk) array, we internally keep an (kxnxm) "transposed"
+		   C array and access A(i,j,k) as A[k-1][j-1][i-1].  The "-1" operation
+		   is inlined in a tight loop and should be easily optimized.
+		*/
+  		Array3D<T> A_;
+
+  public:
+
+    typedef         T   value_type;
+
+	       Fortran_Array3D();
+	       Fortran_Array3D(int m, int n, int k);
+	       Fortran_Array3D(int m, int n, int k,  T *a);
+	       Fortran_Array3D(int m, int n, int k, const T &a);
+    inline Fortran_Array3D(const Fortran_Array3D &A);
+	inline Fortran_Array3D & operator=(const T &a);
+	inline Fortran_Array3D & operator=(const Fortran_Array3D &A);
+	inline Fortran_Array3D & ref(const Fortran_Array3D &A);
+	       Fortran_Array3D copy();
+		   Fortran_Array3D & inject(const Fortran_Array3D & A);
+	inline T& operator()(int i, int j, int k);
+	inline const T& operator()(int i, int j, int k) const ;
+	inline int dim1() const;
+	inline int dim2() const;
+	inline int dim3() const;
+	inline int ref_count() const;
+               ~Fortran_Array3D();
+
+
+};
+
+/**
+	Create a null (0x0x0) array.  
+*/
+template <class T>
+Fortran_Array3D<T>::Fortran_Array3D() : A_() {}
+
+
+/**
+	Copy constructor. Array data is NOT copied, but shared.
+	Thus, in Fortran_Array3D B(A), subsequent changes to A will
+	be reflected in B.  For an indepent copy of A, use
+	Fortran_Array3D B(A.copy()), or B = A.copy(), instead.
+*/
+template <class T>
+Fortran_Array3D<T>::Fortran_Array3D(const Fortran_Array3D<T> &A) : A_(A.A_) {}
+
+
+
+/**
+	Create a new (m x n x k) array, WIHOUT initializing array elements.
+	To create an initialized array of constants, see Fortran_Array3D(m,n,k, value).
+
+	<p>
+	This version avoids the O(m*n*k) initialization overhead and
+	is used just before manual assignment.
+
+	@param m the first dimension of the new matrix.
+	@param n the second dimension of the new matrix.
+	@param k the third dimension of the new matrix.
+*/
+template <class T>
+Fortran_Array3D<T>::Fortran_Array3D(int m, int n, int k) : A_(k,n,m) {}
+
+
+
+/**
+	Create a new (m x n x k) array,  initializing array elements to
+	constant specified by argument.  Most often used to
+	create an array of zeros, as in A(m, n, k, 0.0).
+
+	@param m the first dimension of the new matrix.
+	@param n the second dimension of the new matrix.
+	@param k the third dimension of the new matrix.
+	@param val the constant value to set all elements of the new array to.
+*/
+template <class T>
+Fortran_Array3D<T>::Fortran_Array3D(int m, int n, int k, const T &val) : 
+	A_(k, n, m, val) {}
+
+
+/**
+	Create a new (m x n x k) array,  as a view of an existing one-dimensional
+	C array, with elements stored in <b>Fortran order</b>, i.e. right-most dimension
+	varying fastest. (Often referred to as "column-major" ordering.)
+	Note that the storage for this pre-existing array will
+	never be garbage collected by the Fortran_Array3D class.
+
+	@param m the first dimension of the new matrix.
+	@param n the second dimension of the new matrix.
+	@param k the third dimension of the new matrix.
+	@param a the one dimensional C array to use as data storage for
+		the array. 
+*/
+template <class T>
+Fortran_Array3D<T>::Fortran_Array3D(int m, int n, int k, T *a) : 
+	A_(k, n, m, a) {}
+
+
+
+
+/**
+	Elements are accessed via A(i,j,k) indexing.  
+	
+	If TNT_BOUNDS_CHECK macro is defined, the indices 
+	are checked that they falls within the array bounds (via the
+	assert() macro.) 
+*/
+template <class T>
+inline T& Fortran_Array3D<T>::operator()(int i, int j, int k) 
+{ 
+#ifdef TNT_BOUNDS_CHECK
+	assert(k >= 1);
+	assert(k <= A_.dim1());
+	assert(j >= 1);
+	assert(j <= A_.dim2());
+	assert(i >= 1);
+	assert(i <= A_.dim3());
+#endif
+
+	return A_[k-1][j-1][i-1]; 
+
+}
+
+/**
+	Read-only version of A(i,j,k) indexing.  
+	
+	If TNT_BOUNDS_CHECK macro is defined, the indices 
+	are checked that they falls within the array bounds (via the
+	assert() macro.) 
+*/
+template <class T>
+inline const T& Fortran_Array3D<T>::operator()(int i, int j, int k)  const
+{ 
+#ifdef TNT_BOUNDS_CHECK
+	assert(k >= 1);
+	assert(k <= A_.dim1());
+	assert(j >= 1);
+	assert(j <= A_.dim2());
+	assert(i >= 1);
+	assert(i <= A_.dim3());
+#endif
+
+	return A_[k-1][j-1][i-1]; 
+
+}
+
+
+/**
+	Assign all elemnts of A to a constant scalar.
+*/
+template <class T>
+Fortran_Array3D<T> & Fortran_Array3D<T>::operator=(const T &a)
+{
+	A_ = a;
+	return *this;
+}
+/**
+	Create a new of existing matrix.  Used in B = A.copy()
+	or in the construction of B, e.g. Fortran_Array3D B(A.copy()), 
+	to create a new array that does not share data.
+
+*/
+template <class T>
+Fortran_Array3D<T> Fortran_Array3D<T>::copy()
+{
+
+	Fortran_Array3D B;
+	
+	B.A_= A_.copy();
+	return B;
+}
+
+
+/**
+	Copy the elements to from one array to another, in place.
+	That is B.inject(A), both A and B must conform (i.e. have
+	identical dimensions).
+
+	This differs from B = A.copy() in that references to B
+	before this assignment are also affected.  That is, if
+	we have 
+	<pre>
+	Fortran_Array3D A(m,n,k);
+	Fortran_Array3D C(m,n,k);
+	Fortran_Array3D B(C);        // elements of B and C are shared. 
+
+</pre>
+	then B.inject(A) affects both and C, while B=A.copy() creates
+	a new array B which shares no data with C or A.
+
+	@param A the array from elements will be copied
+	@return an instance of the modifed array. That is, in B.inject(A),
+	it returns B.  If A and B are not conformat, no modifications to 
+	B are made.
+
+*/
+template <class T>
+Fortran_Array3D<T> & Fortran_Array3D<T>::inject(const Fortran_Array3D &A)
+{
+	A_.inject(A.A_);
+
+	return *this;
+}
+
+
+
+
+
+/**
+	Create a reference (shallow assignment) to another existing array.
+	In B.ref(A), B and A shared the same data and subsequent changes
+	to the array elements of one will be reflected in the other.
+	<p>
+	This is what operator= calls, and B=A and B.ref(A) are equivalent
+	operations.
+
+	@return The new referenced array: in B.ref(A), it returns B.
+*/
+template <class T>
+Fortran_Array3D<T> & Fortran_Array3D<T>::ref(const Fortran_Array3D<T> &A)
+{
+	A_.ref(A.A_);
+	return *this;
+}
+
+/**
+	B = A is shorthand notation for B.ref(A).
+*/
+template <class T>
+Fortran_Array3D<T> & Fortran_Array3D<T>::operator=(const Fortran_Array3D<T> &A)
+{
+	return ref(A);
+}
+
+/**
+	@return the size of the first dimension of the array.
+*/
+template <class T>
+inline int Fortran_Array3D<T>::dim1() const { return A_.dim3(); }
+
+/**
+	@return the size of the second dimension of the array.
+*/
+template <class T>
+inline int Fortran_Array3D<T>::dim2() const { return A_.dim2(); }
+
+/**
+	@return the size of the third (right-most) dimension of the array.
+*/
+template <class T>
+inline int Fortran_Array3D<T>::dim3() const { return A_.dim1(); }
+
+
+/**
+	@return the number of arrays that share the same storage area
+	as this one.  (Must be at least one.)
+*/
+template <class T>
+inline int Fortran_Array3D<T>::ref_count() const { return A_.ref_count(); }
+
+template <class T>
+Fortran_Array3D<T>::~Fortran_Array3D()
+{
+}
+
+
+} /* namespace TNT */
+
+#endif
+/* TNT_FORTRAN_ARRAY3D_H */
+
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_fortran_array3d_utils.h b/bioimagesuite30_src/numerics/tnt/tnt_fortran_array3d_utils.h
new file mode 100644
index 0000000..40da48c
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_fortran_array3d_utils.h
@@ -0,0 +1,112 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+#ifndef TNT_FORTRAN_ARRAY3D_UTILS_H
+#define TNT_FORTRAN_ARRAY3D_UTILS_H
+
+#include <cstdlib>
+#include <cassert>
+
+namespace TNT
+{
+
+
+/**
+	Write an array to a character outstream.  Output format is one that can
+	be read back in via the in-stream operator: three integers
+	denoting the array dimensions (m x n x k), followed by m
+	(n x k) arrays in "row-major" order.
+
+*/
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Fortran_Array3D<T> &A)
+{
+    int M=A.dim1();
+    int N=A.dim2();
+    int K=A.dim3();
+
+    s << M << " " << N << " " << K << "\n";
+
+    for (int i=1; i<=M; i++)
+    {
+        for (int j=1; j<=N; j++)
+        {
+			for (int k=1; k<=K; k++)
+            	s << A(i,j,k) << " ";
+			s << "\n";
+        }
+        s << "\n";
+    }
+
+
+    return s;
+}
+
+/**
+	Read an array from a character stream.  Input format
+	is three integers, denoting the dimensions (m x n x k), followed
+	by m*n*k whitespace-separated elments in "row-major" order
+	(i.e. right-most dimension varying fastest.)  Newlines
+	are ignored.
+
+	<p>
+	Note: the array being read into references new memory
+	storage. If the intent is to fill an existing conformant
+	array, use <code> cin >> B;  A.inject(B) ); </code>
+	instead or read the elements in one-a-time by hand.
+
+	@param s the charater to read from (typically <code>std::in</code>)
+	@param A the array to read into.
+*/
+template <class T>
+std::istream& operator>>(std::istream &s, Fortran_Array3D<T> &A)
+{
+
+    int M, N, K;
+
+    s >> M >> N >> K;
+
+	Fortran_Array3D<T> B(M,N,K);
+
+    for (int i=1; i<=M; i++)
+        for (int j=1; j<=N; j++)
+			for (int k=1; k<=K; k++)
+            	s >>  B(i,j,k);
+
+	A = B;
+    return s;
+}
+
+
+
+
+} // namespace TNT
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_math_utils.h b/bioimagesuite30_src/numerics/tnt/tnt_math_utils.h
new file mode 100644
index 0000000..6c3050e
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_math_utils.h
@@ -0,0 +1,85 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+#ifndef MATH_UTILS_H
+#define MATH_UTILS_H
+
+#include <math.h>
+/* needed for sqrt() below */
+
+namespace TNT
+{
+/**
+	@returns hypotenuse of real (non-complex) scalars a and b by 
+	avoiding underflow/overflow
+	using (a * sqrt( 1 + (b/a) * (b/a))), rather than
+	sqrt(a*a + b*b).
+*/
+template <class Real>
+Real hypot(const Real &a, const Real &b)
+{
+	
+	if (a== 0)
+		return abs(b);
+	else
+	{
+		Real c = b/a;
+		return a * sqrt(1 + c*c);
+	}
+}
+
+/**
+	@returns the minimum of scalars a and b.
+*/
+template <class Scalar>
+Scalar min(const Scalar &a, const Scalar &b)
+{
+	return  a < b ? a : b;
+}
+
+/**
+	@returns the maximum of scalars a and b.
+*/
+template <class Scalar>
+Scalar max(const Scalar &a, const Scalar &b)
+{
+	return  a > b ? a : b;
+}
+
+/**
+	@returns the absolute value of a real (no-complex) scalar.
+*/
+template <class Real>
+Real abs(const Real &a)
+{
+	return  (a > 0 ? a : -a);
+}
+
+}
+#endif
+/* MATH_UTILS_H */
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_sparse_matrix_csr.h b/bioimagesuite30_src/numerics/tnt/tnt_sparse_matrix_csr.h
new file mode 100644
index 0000000..d17e8b2
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_sparse_matrix_csr.h
@@ -0,0 +1,131 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Template Numerical Toolkit (TNT)
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+
+#ifndef TNT_SPARSE_MATRIX_CSR_H
+#define TNT_SPARSE_MATRIX_CSR_H
+
+#include "tnt_array1d.h"
+
+namespace TNT
+{
+
+
+/**
+	Read-only view of a sparse matrix in compressed-row storage
+	format.  Neither array elements (nonzeros) nor sparsity
+	structure can be modified.  If modifications are required,
+	create a new view.
+
+	<p>
+	Index values begin at 0.
+
+	<p>
+	<b>Storage requirements:</b> An (m x n) matrix with
+	nz nonzeros requires no more than  ((T+I)*nz + M*I)
+	bytes, where T is the size of data elements and
+	I is the size of integers.
+	
+
+*/
+template <class T>
+class Sparse_Matrix_CompRow {
+
+private:
+	Array1D<T>    val_;       // data values (nz_ elements)
+    Array1D<int>  rowptr_;    // row_ptr (dim_[0]+1 elements)
+    Array1D<int>  colind_;    // col_ind  (nz_ elements)
+
+    int dim1_;        // number of rows
+    int dim2_;        // number of cols
+  
+public:
+
+	Sparse_Matrix_CompRow(const Sparse_Matrix_CompRow &S);
+	Sparse_Matrix_CompRow(int M, int N, int nz, const T *val, 
+						const int *r, const int *c);
+    
+
+
+    inline   const T&      val(int i) const { return val_[i]; }
+    inline   const int&         row_ptr(int i) const { return rowptr_[i]; }
+    inline   const int&         col_ind(int i) const { return colind_[i];}
+
+    inline   int    dim1() const {return dim1_;}
+    inline   int    dim2() const {return dim2_;}
+       int          NumNonzeros() const {return val_.dim1();}
+
+
+    Sparse_Matrix_CompRow& operator=(
+					const Sparse_Matrix_CompRow &R);
+
+
+
+};
+
+/**
+	Construct a read-only view of existing sparse matrix in
+	compressed-row storage format.
+
+	@param M the number of rows of sparse matrix
+	@param N the  number of columns of sparse matrix
+	@param nz the number of nonzeros
+	@param val a contiguous list of nonzero values
+	@param r row-pointers: r[i] denotes the beginning position of row i
+		(i.e. the ith row begins at val[row[i]]).
+	@param c column-indices: c[i] denotes the column location of val[i]
+*/
+template <class T>
+Sparse_Matrix_CompRow<T>::Sparse_Matrix_CompRow(int M, int N, int nz,
+	const T *val, const int *r, const int *c) : val_(nz,val), 
+		rowptr_(M, r), colind_(nz, c), dim1_(M), dim2_(N) {}
+
+
+}
+// namespace TNT
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_stopwatch.h b/bioimagesuite30_src/numerics/tnt/tnt_stopwatch.h
new file mode 100644
index 0000000..ccf6c7d
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_stopwatch.h
@@ -0,0 +1,145 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain.  NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+
+
+#ifndef STOPWATCH_H
+#define STOPWATCH_H
+
+// for clock() and CLOCKS_PER_SEC
+#include <time.h>
+
+
+namespace TNT
+{
+
+inline static double seconds(void)
+{
+    const double secs_per_tick = 1.0 / CLOCKS_PER_SEC;
+    return ( (double) clock() ) * secs_per_tick;
+}
+
+/**
+	Performance Stopwatch  used for benchmarking codes.
+	Measure seconds elapsed.
+*/
+class Stopwatch {
+    private:
+        int running_;
+        double start_time_;
+        double total_;
+
+    public:
+        Stopwatch();
+        inline void start();
+        inline double stop();
+		inline double read();
+		inline void resume();
+		inline int running();
+};
+
+/**
+	Create an instance of a Stopwatch, with its own internal
+		counter.
+*/
+Stopwatch::Stopwatch() : running_(0), start_time_(0.0), total_(0.0) {}
+
+/**
+	Start timing from 0.00.  
+*/
+void Stopwatch::start() 
+{
+	running_ = 1;
+	total_ = 0.0;
+	start_time_ = seconds();
+}
+
+/**
+	
+	Stop timing and return elapsed time (in seconds).
+*/
+double Stopwatch::stop()  
+{
+	if (running_) 
+	{
+         total_ += (seconds() - start_time_); 
+         running_ = 0;
+    }
+    return total_; 
+}
+
+/**
+	Resume timing, if currently stopped.  Operation
+	has no effect if Stopwatch is already running_.
+*/
+inline void Stopwatch::resume()
+{
+	if (!running_)
+	{
+		start_time_ = seconds();
+		running_ = 1;
+	}
+}
+		
+
+/**
+	Read current time (in seconds).
+*/
+inline double Stopwatch::read()   
+{
+	if (running_)
+	{
+		stop();
+		resume();
+	}
+	return total_;
+}
+
+
+}
+#endif
+    
+
+            
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_subscript.h b/bioimagesuite30_src/numerics/tnt/tnt_subscript.h
new file mode 100644
index 0000000..679799e
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_subscript.h
@@ -0,0 +1,82 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Template Numerical Toolkit (TNT)
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+
+#ifndef TNT_SUBSCRPT_H
+#define TNT_SUBSCRPT_H
+
+
+//---------------------------------------------------------------------
+// This definition describes the default TNT data type used for
+// indexing into TNT matrices and vectors.  The data type should
+// be wide enough to index into large arrays.  It defaults to an
+// "int", but can be overriden at compile time redefining TNT_SUBSCRIPT_TYPE,
+// e.g.
+// 
+//      c++ -DTNT_SUBSCRIPT_TYPE='unsigned int'  ...
+//
+//---------------------------------------------------------------------
+//
+
+#ifndef TNT_SUBSCRIPT_TYPE
+#define TNT_SUBSCRIPT_TYPE int
+#endif
+
+namespace TNT
+{
+    typedef TNT_SUBSCRIPT_TYPE Subscript;
+}
+
+
+// () indexing in TNT means 1-offset, i.e. x(1) and A(1,1) are the
+// first elements.  This offset is left as a macro for future
+// purposes, but should not be changed in the current release.
+//
+//
+#define TNT_BASE_OFFSET (1)
+
+#endif
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_vec.h b/bioimagesuite30_src/numerics/tnt/tnt_vec.h
new file mode 100644
index 0000000..eccec2e
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_vec.h
@@ -0,0 +1,432 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Template Numerical Toolkit (TNT)
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+
+
+#ifndef TNT_VEC_H
+#define TNT_VEC_H
+
+#include "tnt_subscript.h"
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+#include <strstream>
+
+namespace TNT
+{
+
+/**
+ <b>[Deprecatred]</b>  Value-based vector class from pre-1.0
+ 	TNT version.  Kept here for backward compatiblity, but should
+	use the newer TNT::Array1D classes instead.
+
+*/
+
+template <class T>
+class Vector 
+{
+
+
+  public:
+
+    typedef Subscript   size_type;
+    typedef         T   value_type;
+    typedef         T   element_type;
+    typedef         T*  pointer;
+    typedef         T*  iterator;
+    typedef         T&  reference;
+    typedef const   T*  const_iterator;
+    typedef const   T&  const_reference;
+
+    Subscript lbound() const { return 1;}
+ 
+  protected:
+    T* v_;                  
+    T* vm1_;        // pointer adjustment for optimzied 1-offset indexing
+    Subscript n_;
+
+    // internal helper function to create the array
+    // of row pointers
+
+    void initialize(Subscript N)
+    {
+        // adjust pointers so that they are 1-offset:
+        // v_[] is the internal contiguous array, it is still 0-offset
+        //
+        assert(v_ == NULL);
+        v_ = new T[N];
+        assert(v_  != NULL);
+        vm1_ = v_-1;
+        n_ = N;
+    }
+   
+    void copy(const T*  v)
+    {
+        Subscript N = n_;
+        Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+        Subscript Nmod4 = N & 3;
+        Subscript N4 = N - Nmod4;
+
+        for (i=0; i<N4; i+=4)
+        {
+            v_[i] = v[i];
+            v_[i+1] = v[i+1];
+            v_[i+2] = v[i+2];
+            v_[i+3] = v[i+3];
+        }
+
+        for (i=N4; i< N; i++)
+            v_[i] = v[i];
+#else
+
+        for (i=0; i< N; i++)
+            v_[i] = v[i];
+#endif      
+    }
+
+    void set(const T& val)
+    {
+        Subscript N = n_;
+        Subscript i;
+
+#ifdef TNT_UNROLL_LOOPS
+        Subscript Nmod4 = N & 3;
+        Subscript N4 = N - Nmod4;
+
+        for (i=0; i<N4; i+=4)
+        {
+            v_[i] = val;
+            v_[i+1] = val;
+            v_[i+2] = val;
+            v_[i+3] = val; 
+        }
+
+        for (i=N4; i< N; i++)
+            v_[i] = val;
+#else
+
+        for (i=0; i< N; i++)
+            v_[i] = val;
+        
+#endif      
+    }
+    
+
+
+    void destroy()
+    {     
+        /* do nothing, if no memory has been previously allocated */
+        if (v_ == NULL) return ;
+
+        /* if we are here, then matrix was previously allocated */
+        delete [] (v_);     
+
+        v_ = NULL;
+        vm1_ = NULL;
+    }
+
+
+  public:
+
+    // access
+
+    iterator begin() { return v_;}
+    iterator end()   { return v_ + n_; }
+    const iterator begin() const { return v_;}
+    const iterator end() const  { return v_ + n_; }
+
+    // destructor
+
+    ~Vector() 
+    {
+        destroy();
+    }
+
+    // constructors
+
+    Vector() : v_(0), vm1_(0), n_(0)  {};
+
+    Vector(const Vector<T> &A) : v_(0), vm1_(0), n_(0)
+    {
+        initialize(A.n_);
+        copy(A.v_);
+    }
+
+    Vector(Subscript N, const T& value = T()) :  v_(0), vm1_(0), n_(0)
+    {
+        initialize(N);
+        set(value);
+    }
+
+    Vector(Subscript N, const T* v) :  v_(0), vm1_(0), n_(0)
+    {
+        initialize(N);
+        copy(v);
+    }
+
+    Vector(Subscript N, char *s) :  v_(0), vm1_(0), n_(0)
+    {
+        initialize(N);
+        std::istrstream ins(s);
+
+        Subscript i;
+
+        for (i=0; i<N; i++)
+                ins >> v_[i];
+    }
+
+
+    // methods
+    // 
+    Vector<T>& newsize(Subscript N)
+    {
+        if (n_ == N) return *this;
+
+        destroy();
+        initialize(N);
+
+        return *this;
+    }
+
+
+    // assignments
+    //
+    Vector<T>& operator=(const Vector<T> &A)
+    {
+        if (v_ == A.v_)
+            return *this;
+
+        if (n_ == A.n_)         // no need to re-alloc
+            copy(A.v_);
+
+        else
+        {
+            destroy();
+            initialize(A.n_);
+            copy(A.v_);
+        }
+
+        return *this;
+    }
+        
+    Vector<T>& operator=(const T& scalar)
+    { 
+        set(scalar);  
+        return *this;
+    }
+
+    inline Subscript dim() const 
+    {
+        return  n_; 
+    }
+
+    inline Subscript size() const 
+    {
+        return  n_; 
+    }
+
+
+    inline reference operator()(Subscript i)
+    { 
+#ifdef TNT_BOUNDS_CHECK
+        assert(1<=i);
+        assert(i <= n_) ;
+#endif
+        return vm1_[i]; 
+    }
+
+    inline const_reference operator() (Subscript i) const
+    {
+#ifdef TNT_BOUNDS_CHECK
+        assert(1<=i);
+        assert(i <= n_) ;
+#endif
+        return vm1_[i]; 
+    }
+
+    inline reference operator[](Subscript i)
+    { 
+#ifdef TNT_BOUNDS_CHECK
+        assert(0<=i);
+        assert(i < n_) ;
+#endif
+        return v_[i]; 
+    }
+
+    inline const_reference operator[](Subscript i) const
+    {
+#ifdef TNT_BOUNDS_CHECK
+        assert(0<=i);
+
+
+
+
+
+
+        assert(i < n_) ;
+#endif
+        return v_[i]; 
+    }
+
+
+
+};
+
+
+/* ***************************  I/O  ********************************/
+
+template <class T>
+std::ostream& operator<<(std::ostream &s, const Vector<T> &A)
+{
+    Subscript N=A.dim();
+
+    s <<  N << endl;
+
+    for (Subscript i=0; i<N; i++)
+        s   << A[i] << " " << endl;
+    s << endl;
+
+    return s;
+}
+
+template <class T>
+std::istream & operator>>(std::istream &s, Vector<T> &A)
+{
+
+    Subscript N;
+
+    s >> N;
+
+    if ( !(N == A.size() ))
+    {
+        A.newsize(N);
+    }
+
+
+    for (Subscript i=0; i<N; i++)
+            s >>  A[i];
+
+
+    return s;
+}
+
+// *******************[ basic matrix algorithms ]***************************
+
+
+template <class T>
+Vector<T> operator+(const Vector<T> &A, 
+    const Vector<T> &B)
+{
+    Subscript N = A.dim();
+
+    assert(N==B.dim());
+
+    Vector<T> tmp(N);
+    Subscript i;
+
+    for (i=0; i<N; i++)
+            tmp[i] = A[i] + B[i];
+
+    return tmp;
+}
+
+template <class T>
+Vector<T> operator-(const Vector<T> &A, 
+    const Vector<T> &B)
+{
+    Subscript N = A.dim();
+
+    assert(N==B.dim());
+
+    Vector<T> tmp(N);
+    Subscript i;
+
+    for (i=0; i<N; i++)
+            tmp[i] = A[i] - B[i];
+
+    return tmp;
+}
+
+template <class T>
+Vector<T> operator*(const Vector<T> &A, 
+    const Vector<T> &B)
+{
+    Subscript N = A.dim();
+
+    assert(N==B.dim());
+
+    Vector<T> tmp(N);
+    Subscript i;
+
+    for (i=0; i<N; i++)
+            tmp[i] = A[i] * B[i];
+
+    return tmp;
+}
+
+
+template <class T>
+T dot_prod(const Vector<T> &A, const Vector<T> &B)
+{
+    Subscript N = A.dim();
+    assert(N == B.dim());
+
+    Subscript i;
+    T sum = 0;
+
+    for (i=0; i<N; i++)
+        sum += A[i] * B[i];
+
+    return sum;
+}
+
+}   /* namespace TNT */
+
+#endif
+// TNT_VEC_H
+
diff --git a/bioimagesuite30_src/numerics/tnt/tnt_version.h b/bioimagesuite30_src/numerics/tnt/tnt_version.h
new file mode 100644
index 0000000..8e3489b
--- /dev/null
+++ b/bioimagesuite30_src/numerics/tnt/tnt_version.h
@@ -0,0 +1,67 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+/*
+*
+* Template Numerical Toolkit (TNT)
+*
+* Mathematical and Computational Sciences Division
+* National Institute of Technology,
+* Gaithersburg, MD USA
+*
+*
+* This software was developed at the National Institute of Standards and
+* Technology (NIST) by employees of the Federal Government in the course
+* of their official duties. Pursuant to title 17 Section 105 of the
+* United States Code, this software is not subject to copyright protection
+* and is in the public domain. NIST assumes no responsibility whatsoever for
+* its use by other parties, and makes no guarantees, expressed or implied,
+* about its quality, reliability, or any other characteristic.
+*
+*/
+
+#ifndef TNT_VERSION_H
+#define TNT_VERSION_H
+
+
+//---------------------------------------------------------------------
+//  current version 
+//---------------------------------------------------------------------
+
+
+#define TNT_MAJOR_VERSION    '1'
+#define TNT_MINOR_VERSION    '1'
+#define TNT_SUBMINOR_VERSION '1'
+#define TNT_VERSION_STRING "1.1.1"
+
+
+
+
+
+#endif
+// TNT_VERSION_H
+
diff --git a/bioimagesuite30_src/pxtklib/CMakeLists.txt b/bioimagesuite30_src/pxtklib/CMakeLists.txt
new file mode 100644
index 0000000..bee7480
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/CMakeLists.txt
@@ -0,0 +1,90 @@
+#BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+#BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+#BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+#BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+#BIOIMAGESUITE_LICENSE  Medicine, http:#www.bioimagesuite.org.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+#BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+#BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+#BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+#BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+#BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+#BIOIMAGESUITE_LICENSE  See also  http:#www.gnu.org/licenses/gpl.html
+#BIOIMAGESUITE_LICENSE  
+#BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+#BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+#BIOIMAGESUITE_LICENSE 
+#BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#
+# Source files
+#
+# Here is where you can add the name of your local imaging classes.
+#
+
+SET(KITBASE pxtklib)
+SET(KIT ${KITBASE})
+
+INCLUDE_DIRECTORIES(${BIOIMAGESUITE3_SOURCE_DIR}/${KITBASE})
+
+
+SET (KITSRCS
+  pxtkapp.cpp
+  pxtkbase.cpp
+  pxtkeventobj.cpp
+  pxtkdialog.cpp
+  pxtkgadget.cpp
+  pxtkframe.cpp
+  pxtktoplevel.cpp
+  pxtklabel.cpp
+  pxtkmessage.cpp
+  pxtkbutton.cpp
+  pxtkmenubutton.cpp
+  pxtkcheckbutton.cpp
+  pxtkradiobutton.cpp
+  pxtkentry.cpp
+  pxtktext.cpp
+  pxtkscale.cpp
+  pxtkscrollbar.cpp
+  pxtklistbox.cpp
+  pxtkmenu.cpp
+  pxtkoptionmenu.cpp
+  pxtkseldialog.cpp
+  pxtkinfodialog.cpp
+  pxtkwaitdialog.cpp
+  pxtkcomplexwidgets.cpp
+  pxitkcombobox.cpp
+  nrtk_iwidget_tabnotebook.cpp
+#  nrtkbutton.cpp
+#  nrtkentry.cpp
+#  nrtklabel.cpp
+#  nrtklistbox.cpp
+#  nrtktext.cpp
+)
+
+
+SET (KITEXTRAFILES
+pxtklib/pxtkgadgets.h
+)
+SET (KITTCLSRCS )
+
+# --------------------------------------------------------------------------
+# You probably do not need to modify anything below this line
+
+bis_static(${KIT})
+bis_sourcelist("pxtklib" ${KIT} ${FILELIST})
+
+
diff --git a/bioimagesuite30_src/pxtklib/nrtk_iwidget_tabnotebook.cpp b/bioimagesuite30_src/pxtklib/nrtk_iwidget_tabnotebook.cpp
new file mode 100644
index 0000000..d7cbb6f
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/nrtk_iwidget_tabnotebook.cpp
@@ -0,0 +1,136 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "nrtk_iwidget_tabnotebook.h"
+#include <stdlib.h>
+#include <ctype.h>
+
+
+/******************************************************************************/
+
+NRTkIWTabNotebook::NRTkIWTabNotebook(PXTkEventObj* evpar,PXTkGadget* par,
+                   const char* tab_pos, int width,int height):PXTkEventObj(evpar,par)
+{
+  num_items=0;
+  
+  initDisplay(tab_pos);
+
+  if (width>0)
+      rnotebook->configure("-width",width);
+  if (height>0)
+      rnotebook->configure("-height",height);
+}
+ 
+/******************************************************************************/
+
+int NRTkIWTabNotebook::initDisplay(const char *tab_pos)
+{
+
+   PXTkFrame* main = new PXTkFrame(this, gadget_parent);
+   main_window = main;
+
+   main->configure("-padx",8);
+   main->configure("-pady",8);
+   main->configure("-bg","lightgray");
+   main->configure("-relief","ridge");
+
+   sprintf(pxtk_buffer2,"%s.rn%d",main_window->getWidgetName(),object_id);
+
+   rnotebook = new PXTkGadget(this, pxtk_buffer2);
+
+   char tabpos = tolower((unsigned char) tab_pos[0]);
+   if(tabpos != 'n' && tabpos != 's' && tabpos != 'e' && tabpos != 'w') tabpos = 'n';
+   
+   sprintf(pxtk_buffer,"iwidgets::tabnotebook %s  -tabpos %c",rnotebook->getWidgetName(), tabpos);
+   PXTkApp::executeTclCommand(pxtk_buffer);
+
+/**
+   sprintf(pxtk_buffer,"iwidgets::tabnotebook %s  -tabpos %c",rnotebook->getWidgetName(), tabpos);
+   printf("iwidgets::tabnotebook %s  -tabpos %c",rnotebook->getWidgetName(), tabpos);
+   PXTkApp::executeTclCommand(pxtk_buffer);
+**/
+   ((PXTkFrame*)main_window)->addChildren(" -expand true -fill both -padx 5 -pady 5",rnotebook);
+/**
+   num_items=1;
+   sprintf(pxtk_buffer,"%s add -label %s", rnotebook->getWidgetName(), "Base");
+
+   PXTkApp::executeTclCommand(pxtk_buffer);
+
+   char* line = PXTkApp::getTclStringResult();
+   sub_manager[num_items-1] = new PXTkFrame(this,line);
+   **/
+   return TCL_OK;
+}
+ 
+/******************************************************************************/
+
+PXTkFrame* NRTkIWTabNotebook::getPage(int i)
+{
+  i=Irange(i,0,num_items-1);
+  return sub_manager[i];
+}
+ 
+/******************************************************************************/
+
+int NRTkIWTabNotebook::viewPage(const char *label)
+{
+   sprintf(pxtk_buffer,"%s view %s", rnotebook->getWidgetName(), label);
+
+   PXTkApp::executeTclCommand(pxtk_buffer);
+
+  return TCL_OK;
+}
+ 
+/******************************************************************************/
+
+PXTkFrame* NRTkIWTabNotebook::addPage(const char* label)
+{
+  num_items++;
+  // Create Frame and Tab
+  sprintf(pxtk_buffer, "%s add -label %s", rnotebook->getWidgetName(), label);
+  PXTkApp::executeTclCommand(pxtk_buffer);
+
+  char* tabFrame = PXTkApp::getTclStringResult();
+
+  sub_manager[num_items-1] = new PXTkFrame(this, tabFrame);
+
+  return sub_manager[num_items-1];
+}
+ 
+/******************************************************************************/
+
+int NRTkIWTabNotebook::getNumItems()
+{
+  return num_items;
+}
+ 
+/******************************************************************************/
+
diff --git a/bioimagesuite30_src/pxtklib/nrtk_iwidget_tabnotebook.h b/bioimagesuite30_src/pxtklib/nrtk_iwidget_tabnotebook.h
new file mode 100644
index 0000000..c2a08c3
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/nrtk_iwidget_tabnotebook.h
@@ -0,0 +1,68 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+#ifndef __NRTk_TABNOTEBOOK_H
+#define __NRTk_TABNOTEBOOK_H
+
+#include "pxtkgadgets.h"
+#include "pxtkeventobj.h"
+
+
+/******************************************************************************/
+
+
+class NRTkIWTabNotebook : public PXTkEventObj {
+  
+protected:
+  int num_items;
+  PXTkFrame*  sub_manager[15];
+  PXTkGadget* rnotebook;
+
+public:
+  
+  NRTkIWTabNotebook(PXTkEventObj* evpar, PXTkGadget* par, const char *tab_pos,
+                                             int width=-1,int height=-1);
+  
+  
+  virtual int          initDisplay(const char *tab_pos);
+  virtual int          viewPage(const char *label);
+  virtual PXTkFrame*   getPage(int i);
+  virtual PXTkFrame*   addPage(const char* label);
+  virtual int          getNumItems();
+  
+};
+
+
+/******************************************************************************/ 
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxitkcombobox.cpp b/bioimagesuite30_src/pxtklib/pxitkcombobox.cpp
new file mode 100644
index 0000000..ff056ea
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxitkcombobox.cpp
@@ -0,0 +1,191 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxitkcombobox.cpp
+#include "pxitkcombobox.h"
+#include "pxtkeventobj.h"
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxitkcombobox.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+/* ********************************************************************
+   
+   Definition of PXITkComboBox Class 
+   
+   ********************************************************************* */
+PXITkComboBox::PXITkComboBox(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* label,int moption,
+		   PXBool dodisplay):PXTkListBox(evpar,gadg_par,moption,PXFalse)
+{
+  int n=strlen(label);
+  labelname=new char[n+1]; 
+  sprintf(labelname,"%s",label);
+  
+  if (dodisplay)
+    {
+      call_no=moption;
+      initDisplay();
+    }
+}
+  
+int PXITkComboBox::addItem(const char* item,int index)
+{
+  if (index==-1)
+      sprintf(pxtk_buffer,"%s insert list end \"%s\" ",widget_name,item);
+  else
+      sprintf(pxtk_buffer,"%s insert list %d \"%s\" ",widget_name,index,item);
+
+  int ok=PXTkApp::executeTclCommand(pxtk_buffer);
+
+  if (this->getNumItems()==1)
+    return this->selectItem(0);
+  
+  return ok;
+}
+
+int PXITkComboBox::clearList()
+{
+  sprintf(pxtk_buffer,"%s delete list 0 end ",widget_name);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int PXITkComboBox::clearItem(int index)
+{
+  sprintf(pxtk_buffer,"%s delete list %d",widget_name,index);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int PXITkComboBox::changeItem(const char* item,int index)
+{
+  addItem(item,index);
+  return clearItem(index+1);
+}
+
+
+int PXITkComboBox::getIndex()
+{
+  sprintf(pxtk_buffer,"%s curselection",widget_name);
+  if (PXTkApp::executeTclCommand(pxtk_buffer)==TCL_OK)
+      return PXTkApp::getTclIntResult();
+
+  return 0;
+}
+
+int PXITkComboBox::setIndex(int index,PXBool callback)
+{
+  this->selectItem(index);
+  if (callback)
+    {
+      sprintf(pxtk_buffer,"pxtkcallback %d %d %ld",
+	      event_parent->getHandlerNo(),call_no,(long)this);
+      return PXTkApp::executeTclCommand(pxtk_buffer);
+    }
+  return TCL_OK;
+}
+
+int PXITkComboBox::selectItem(int index)
+{
+  sprintf(pxtk_buffer,"%s selection set %d",widget_name,index);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int PXITkComboBox::getNumItems()
+{
+  sprintf(pxtk_buffer,"%s index end",widget_name);
+  if (PXTkApp::executeTclCommand(pxtk_buffer)==TCL_OK)
+      return PXTkApp::getTclIntResult();
+  else
+      return 0;
+}
+
+int PXITkComboBox::getCurrentItem()
+{
+  sprintf(pxtk_buffer,"%s curselection",widget_name);
+  if (PXTkApp::executeTclCommand(pxtk_buffer)==TCL_OK)
+    {
+      char* line=PXTkApp::getTclStringResult();
+      if (strlen(line)==0)
+	return -1;
+      else
+	return PXTkApp::getTclIntResult();
+    }
+  else
+    return -1;
+}
+
+char* PXITkComboBox::getItem(int index)
+{
+  sprintf(pxtk_buffer,"%s get %d",widget_name,index);
+  if (PXTkApp::executeTclCommand(pxtk_buffer)==TCL_OK)
+      return PXTkApp::getTclStringResult();
+  else
+      return 0;
+}
+
+int PXITkComboBox::initDisplay()
+{
+  sprintf(pxtk_buffer,"iwidgets::combobox %s -labeltext %s -labelpos w ",widget_name,labelname);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  configure("-width",15);
+
+  if (call_no>0)
+      {
+	sprintf(pxtk_buffer,"%s configure -selectioncommand { pxtkcallback %d %d %ld }",
+		widget_name,event_parent->getHandlerNo(),call_no,(long)this);
+	a=PXTkApp::executeTclCommand(pxtk_buffer);
+      }
+  
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+
+  return a;
+
+}
+
+int PXITkComboBox::enableEntry(PXBool enab)
+{
+  if (enab)
+    sprintf(pxtk_buffer,"%s entry configure -state normal",widget_name);
+  else
+    sprintf(pxtk_buffer,"%s entry configure -state disabled",widget_name);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
diff --git a/bioimagesuite30_src/pxtklib/pxitkcombobox.h b/bioimagesuite30_src/pxtklib/pxitkcombobox.h
new file mode 100644
index 0000000..892b135
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxitkcombobox.h
@@ -0,0 +1,105 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxitkcombobox.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXITkComboBox
+
+_Description : Definition of class PXITkComboBox to warp Listbox TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtklistbox.h"
+
+#ifndef  _PXITkComboBox
+#define  _PXITkComboBox
+
+/* ---- Definition of PXITkComboBox Class  ---- */
+  
+class PXITkComboBox : public PXTkListBox
+{
+protected:
+  char* labelname;
+
+public:
+  PXITkComboBox(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* label,int moption=-1,PXBool dodisplay=PXTrue);
+  
+  virtual int initDisplay();
+
+  virtual int   enableEntry(PXBool enab=PXTrue);
+  
+  virtual char* getItem(int index);
+  virtual int   getNumItems();
+  virtual int   getCurrentItem();
+  virtual int   clearList();
+  virtual int   selectItem(int index);
+  virtual int   clearItem(int index);
+  virtual int   addItem(const char* item,int index=-1);
+  virtual int   changeItem(const char* item,int index);
+
+  // Combatibility with pxtkoptionmenu
+  // ---------------------------------
+  virtual int   getIndex();
+  virtual int   setIndex(int index,PXBool callback=PXFalse);
+  virtual int   addOption(const char* item,int ) { return this->addItem(item); }
+  virtual int   changeLabel(int ind,const char* name ) { return this->changeItem(name,ind); }
+			   
+  
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkapp.cpp b/bioimagesuite30_src/pxtklib/pxtkapp.cpp
new file mode 100644
index 0000000..e4b089f
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkapp.cpp
@@ -0,0 +1,704 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+// 	$Id: pxtkapp.cpp,v 1.3 2002/12/18 16:11:12 papad Exp $	
+
+
+#include "pxtkapp.h"
+#include "pxtkinfodialog.h"
+#include "vtkstd/string"
+#include "sstream"
+#include "iostream"
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+/* ********************************************************************
+
+   Definition of PXTkApp Class 
+
+********************************************************************* */
+
+ Tcl_Interp*       PXTkApp::tcl_interpreter; 
+ int               PXTkApp::num_arguments;
+ int               PXTkApp::initialized;
+ Tcl_Obj**         PXTkApp::arguments;
+ PXTkInfoDialog*   PXTkApp::console;
+ PXBool            PXTkApp::debug_tcl;  
+ int               PXTkApp::debug_mode;
+// -----------------------------------------------------------------------------
+int  PXTkApp::Irange(int   a,int   minv,int   maxv)
+{
+  if (a<minv) a=minv;
+  if (a>maxv) a=maxv;
+  return a;
+}
+
+
+float PXTkApp::Frange(float a,float minv,float maxv)
+{
+  if (a<minv) a=minv;
+  if (a>maxv) a=maxv;
+  return a;
+}
+
+int PXTkApp::initialize(Tcl_Interp* tclinterp)
+{
+  if (PXTkApp::initialized==1000 && PXTkApp::tcl_interpreter!=NULL)
+      return TCL_OK;
+
+  PXTkApp::num_arguments=0;
+  PXTkApp::arguments=NULL;
+  PXTkApp::tcl_interpreter=tclinterp;
+  PXTkApp::console=NULL;
+  PXTkApp::debug_tcl=PXFalse;
+  PXTkApp::debug_mode=0;
+
+  Tcl_CreateObjCommand(tclinterp, "pxtkcallback", PXTkApp::handleEvent,
+		       (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+  
+  Tcl_CreateObjCommand(tclinterp, "pxtkconsole", PXTkApp::consoleEvent,
+		       (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+  
+  Tcl_CreateObjCommand(tclinterp, "pxtkprint", PXTkApp::consolePrint,
+		       (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+
+  Tcl_CreateObjCommand(tclinterp, "pxtksetdebugmode", PXTkApp::setDebugMode,
+		       (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+
+  Tcl_CreateObjCommand(tclinterp, "pxtkexit", PXTkApp::exitCommand,
+		       (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
+
+  PXTkApp::initialized=1000;
+
+
+  return PXTkApp::createConsole();
+}
+
+int PXTkApp::startEventLoop()
+{
+/*   executeTclCommand("bind all <Control-a>  { pxtkcallback 0 0 }");
+     executeTclCommand("bind all <Control-q>  { pxtkcallback 0 1 }");
+     executeTclCommand("bind all <Control-d>  { pxtkcallback 0 1 }");
+     executeTclCommand("bind all <Control-w>  { pxtkcallback 0 4 }");*/
+   executeTclCommand("bind all <F1> { pxtkconsole }");
+   executeTclCommand("wm protocol . WM_DELETE_WINDOW { pxtkcallback 0 1} ");
+   executeTclCommand("update idletasks");
+   return executeTclCommand("vwait forever");
+}
+
+int    PXTkApp::getNumCommandLineArguments()
+{
+  PXTkApp::executeTclCommand("llength $argv");
+  return getTclIntResult()+1;
+}
+
+char*  PXTkApp::getCommandLineArgument(int i)
+{
+  if (i==0)
+    return getTclVariable("argv0");
+
+  std::stringstream s;
+  s << "lindex $argv ";
+  s << i-1;
+
+  PXTkApp::executeTclCommand(s.str().c_str());
+  return getTclStringResult();
+}
+
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+
+/*int PXTkApp::registerEventHandler(PXTkEventObj* newhandler)
+{
+  if (num_event_handlers< PXTK_NUMHANDLERS)
+      {
+	event_handlers[num_event_handlers]=newhandler;
+	newhandler->setHandlerNo(num_event_handlers);
+	num_event_handlers++;
+	return 1;
+      }
+  else
+      return 0;
+}
+
+int PXTkApp::getNumEventHandlers()
+{
+  return num_event_handlers;
+}*/
+
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+int PXTkApp::handleEventSetup(int objc,Tcl_Obj *CONST objv[],int& val1,int& val2)
+{
+  if (objc<3)
+      {
+	fprintf(stderr,"Num Parameters =%d\n",objc);
+	return TCL_ERROR;
+      }
+
+  num_arguments=objc-3;
+  arguments=(Tcl_Obj**)&objv[3];
+ 
+  Tcl_GetIntFromObj(tcl_interpreter, objv[1], &val1);
+  Tcl_GetIntFromObj(tcl_interpreter, objv[2], &val2);
+
+  return TCL_OK;
+}
+
+
+int PXTkApp::handleEvent(ClientData cl, Tcl_Interp *interp,
+			 int objc, Tcl_Obj *CONST objv[])
+{
+  tcl_interpreter=interp;
+  //  fprintf(stderr,"Num Parameters =%d\n",objc);
+
+  int val1=0,val2=0;
+  if (PXTkApp::handleEventSetup(objc,objv,val1,val2)==TCL_ERROR)
+      return TCL_ERROR;
+
+  if (val1==0 && val2==0)
+    return PXTkApp::exitCommand(cl,interp,objc,objv);
+
+  PXTkEventObj* handler=(PXTkEventObj*)val1;
+  if (handler!=NULL)
+      return handler->handleEvent(val2);
+  else
+      return TCL_ERROR;
+  //return event_handlers[val1]->handleEvent(val2);
+}
+
+int PXTkApp::getNumArguments()
+{
+  return num_arguments;
+}
+
+int  PXTkApp::getIntArgument(int i)
+{
+  i=Irange(i,0,num_arguments-1);
+  int v=0;
+  Tcl_GetIntFromObj(tcl_interpreter,arguments[i],&v);
+  return v;
+}
+
+float PXTkApp::getFloatArgument(int i)
+{
+  i=Irange(i,0,num_arguments-1);
+  double v=0.0;
+  Tcl_GetDoubleFromObj(tcl_interpreter,arguments[i],&v);
+  return (float)v;
+}
+
+char* PXTkApp::getStringArgument(int i)
+{
+  i=Irange(i,0,num_arguments-1);
+  return Tcl_GetString(arguments[i]);
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+
+char* PXTkApp::getTclVariable(const char* variablename)
+{
+  //return Tcl_GetVar(tcl_interpreter,variablename,0);
+  std::stringstream s; 
+  s << "set pxtk_dummy $";
+  s << variablename;
+  
+  PXTkApp::executeTclCommand(s.str().c_str());
+  //  char line[200];
+  //  sprintf(line,"set pxtk_dummy $%s",variablename);
+  //  fprintf(stderr,"new command \"%s\" vs \"%s\"\n",s.str().c_str(),line);
+  //  PXTkApp::executeTclCommand(line);
+  
+  return getTclStringResult();
+
+}
+
+int PXTkApp::deleteTclVariable(const char* variablename)
+{
+  return Tcl_UnsetVar(tcl_interpreter,variablename,TCL_GLOBAL_ONLY);
+}
+
+char* PXTkApp::setTclVariable(const char* variablename, const char* value)
+{
+  //return Tcl_SetVar(tcl_interpreter,variablename,value,TCL_GLOBAL_ONLY);
+  //  char pxtk_buffer[200];
+  //  sprintf(pxtk_buffer,"set %s \"%s\" ",variablename,value);
+  //  PXTkApp::executeTclCommand(pxtk_buffer);
+  std::stringstream s; //  char line[200];
+  s << "set ";
+  s << variablename;
+  s << " \"";
+  s << value;
+  s << "\"";
+  PXTkApp::executeTclCommand(s.str().c_str());
+  //fprintf(stderr,"new command \"%s\" vs \"%s\"\n",s.str().c_str(),pxtk_buffer);
+  return getTclStringResult();
+}
+
+int PXTkApp::executeTclCommand(const char* command)
+{
+  if (tcl_interpreter!=NULL)
+      {
+	if (PXTkApp::debug_tcl)
+	  {
+	    printToConsole(command);
+	    printToConsole("\n");
+	  }
+	//std::string command_buffer(command);
+	return Tcl_GlobalEval(tcl_interpreter,command);
+      }
+  else
+    {
+      fprintf(stderr,"Interpreter=NULL init=%d\n",  PXTkApp::initialized);
+      return TCL_ERROR;
+    }
+}
+
+char* PXTkApp::getTclStringResult()
+{
+  Tcl_Obj* obj=Tcl_GetObjResult(tcl_interpreter);
+  if (obj!=NULL) {
+      return Tcl_GetString(obj);
+  }
+  else
+      return NULL;
+
+}
+
+float PXTkApp::getTclFloatResult()
+{
+  Tcl_Obj* obj=Tcl_GetObjResult(tcl_interpreter);
+  if (obj!=NULL)
+      {
+	double v=0.0;
+	Tcl_GetDoubleFromObj(tcl_interpreter,obj,&v);
+	return (float)v;
+      }
+  else
+      return 0.0;
+}
+ 
+int PXTkApp::getTclIntResult()
+{
+  Tcl_Obj* obj=Tcl_GetObjResult(tcl_interpreter);
+  if (obj!=NULL)
+      {
+	int v=0;
+	Tcl_GetIntFromObj(tcl_interpreter,obj,&v);
+	return v;
+      }
+  else
+      return 0;
+
+}
+
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+
+Tk_Window PXTkApp::getWidgetPointer(const char* name)
+{
+  if (name!=NULL)
+      {
+	Tk_Window mainwind=Tk_MainWindow(PXTkApp::tcl_interpreter);
+	if (mainwind!=NULL)
+	    return Tk_NameToWindow(PXTkApp::tcl_interpreter,name,mainwind);
+      }
+  return NULL;
+}
+
+
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+
+int PXTkApp::createConsole()
+{
+  if (PXTkApp::console==NULL)
+    {
+      PXTkApp::console=new PXTkInfoDialog("PXTkConsole",500,200);
+      return PXTkApp::console->initDisplay();
+    }
+  return 0;
+}
+
+int PXTkApp::consoleEvent(ClientData, Tcl_Interp* ,int, Tcl_Obj *CONST objv[])
+{
+  return PXTkApp::popupConsole();
+}
+
+
+int PXTkApp::exitCommand(ClientData, Tcl_Interp* ,int, Tcl_Obj *CONST objv[])
+{
+
+#ifdef _WIN32
+  PXTkApp::executeTclCommand("destroy .");
+  PXTkApp::executeTclCommand("update idletasks");
+  PXTkApp::executeTclCommand("after idle exit");
+#endif
+  exit(0);
+
+  return TCL_OK;
+}
+
+
+int PXTkApp::setDebugMode(ClientData, Tcl_Interp* ,int objc, Tcl_Obj *CONST objv[] )
+{
+  if (objc<2)
+    return TCL_OK;
+  //  char line[250];
+  //  strncpy(line,Tcl_GetString(objv[1]),200);
+  std::string s(Tcl_GetString(objv[1]));
+
+  int a=atoi(s.c_str());
+  if (a>0)
+    PXTkApp::debug_mode=1;
+  else
+    PXTkApp::debug_mode=0;
+  return TCL_OK;
+}
+
+int PXTkApp::consolePrint(ClientData, Tcl_Interp* ,int objc, Tcl_Obj *CONST objv[])
+{
+  if (objc<2)
+      return TCL_OK;
+  //  char line[355];
+  std::string str(Tcl_GetString(objv[1]));
+  PXTkApp::printToConsole(str.c_str());
+  return TCL_OK;
+}
+
+int PXTkApp::popupConsole()
+{
+  if (PXTkApp::console!=NULL)
+    {
+      //char line[400];
+      //	sprintf(line,"wm geometry %s -5-5",PXTkApp::console->getMainWindow()->getWidgetName());
+      std::string s("wm geometry ");
+      s+=PXTkApp::console->getMainWindow()->getWidgetName();
+      s+=" -5-5 ";
+      //      fprintf(stderr,"executing %s\n",s.c_str());
+      executeTclCommand(s.c_str());
+      //sprintf(line,"wm deiconify %s",PXTkApp::console->getMainWindow()->getWidgetName());
+      std::string s2("wm deiconify "); s2 = s2 + PXTkApp::console->getMainWindow()->getWidgetName();
+
+      //      fprintf(stderr,"executing %s\n",s2.c_str());
+      executeTclCommand(s2.c_str());
+      return TCL_OK;
+    }
+  else
+    return 0;
+}
+
+PXTkInfoDialog* PXTkApp::GetConsole()
+{
+  return PXTkApp::console;
+}
+
+int PXTkApp::printToConsole(const char* line)
+{
+ if (PXTkApp::console!=NULL)
+   {
+     //     fprintf(stderr,"Printing to Console %s\n",line);
+     PXTkApp::console->addText(line);
+     if (PXTkApp::debug_mode>0)
+       fprintf(stderr,"*C*:%s",line);
+     executeTclCommand("update idletasks");
+     return 1;
+   }
+ else
+   {
+     fprintf(stderr,"%s\n",line);
+   }
+ return 0;
+}
+
+int PXTkApp::popdownConsole()
+{
+  if (PXTkApp::console!=NULL)
+      {
+	PXTkApp::console->popdownDialog();
+	return 1;
+      }
+  else
+      return 0;
+}
+
+int PXTkApp::autoArrangeWindows()
+{
+  return TCL_OK;
+/*  int x1=0,y1=0,w1=0,h1=0;
+  char app_buffer[200];
+  sprintf(app_buffer,"winfo geometry .");
+  if ( PXTkApp::executeTclCommand(app_buffer)==TCL_OK)
+      {
+	strcpy(app_buffer,PXTkApp::getTclStringResult());
+	sscanf(app_buffer,"%dx%d+%d+%d",&w1,&h1,&x1,&y1);
+	x1+=w1+25;
+      }
+  else
+      return 0;
+
+  //  int maxw=0;
+  
+  int id=0;
+  for (int i=1;i<num_event_handlers-1;i++)
+      {
+	if (event_handlers[i]->getClassId()==PXTkDialogId)
+	    {
+	      PXTkDialog* dlg=(PXTkDialog*)event_handlers[i];
+	      if (dlg->isOpen() && dlg->getObjectId()!=console->getObjectId() && !dlg->isInside())
+		  {
+		    id++;
+		    ((PXTkToplevel*)dlg->getMainWindow())->show(id);
+		  }
+	    }
+      }
+  return 1;*/
+}
+
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+int PXTkApp::popdownChildren(PXTkEventObj* closingparent)
+{
+  return TCL_OK;
+  /*for (int i=1;i<num_event_handlers-1;i++)
+      {
+	if (event_handlers[i]->getClassId()==PXTkDialogId)
+	    {
+	      PXTkDialog* dlg=(PXTkDialog*)event_handlers[i];
+	      if (dlg->isOpen() && dlg->getObjectId()!=console->getObjectId() && !dlg->isInside())
+		  {
+		    if (dlg->getEventParent() == closingparent)
+			dlg->popdownDialog();
+		  }
+	    }
+      }
+  return 1;*/
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+int PXTkApp::debugMessage(const char* msg)
+{
+  //  char line[400];
+  //  sprintf(line,"tk_messageBox -title \"Debug Message\" -type ok -message \"%s\" ",
+  //	  msg);
+  std::string s("tk_messageBox -title \"Debug Message\" -type ok -message \"");
+  s+=msg;
+  s+="\"";
+
+  return PXTkApp::executeTclCommand(s.c_str());
+}
+
+
+int PXTkApp::setWaitCursor(PXBool setwait)
+{
+  if (!setwait)
+      return executeTclCommand(". config -cursor top_left_arrow");
+  else
+      return executeTclCommand(". config -cursor watch");
+}
+
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+int PXTkApp:: getpid()
+{
+  executeTclCommand("pid");
+  return getTclIntResult();
+}
+ 
+char* PXTkApp::getpwd()
+{
+  executeTclCommand("pwd");
+  return getTclStringResult();
+}
+
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+void PXTkApp::fileOperation(const char* command, const char* fname1, const char* fname2)
+{
+  int n=5+strlen(command)+20+strlen(fname1)+2;
+  if (fname2!=NULL)
+    n+=strlen(fname2)+2;
+  
+  char* line=new char[n];
+  if (fname2==NULL)
+    sprintf(line,"file %s \"%s\"",command,fname1);
+  else
+    sprintf(line,"file %s \"%s\" \"%s\"",command,fname1,fname2);
+
+  executeTclCommand(line);
+  delete [] line;
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+void PXTkApp::deleteFile(const char* fname)
+{
+  fileOperation("delete",fname,NULL);
+}
+
+void PXTkApp::copyFile(const char* source,const char* dest)
+{
+  fileOperation("copy",source,dest);
+}
+
+void PXTkApp::renameFile(const char* source,const char* dest)
+{
+  fileOperation("rename",source,dest);
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+char* PXTkApp::getFilenameExtension(const char* fname)
+{
+  fileOperation("extension",fname,NULL);
+  return getTclStringResult();
+}
+
+char* PXTkApp::getFilenamePath(const char* fname)
+{
+  fileOperation("dirname",fname,NULL);
+  return getTclStringResult();
+}
+
+char* PXTkApp::getFilenameTail(const char* fname)
+{
+  fileOperation("tail",fname,NULL);
+  return getTclStringResult();
+}
+
+char* PXTkApp::getFilenameRoot(const char* fname)
+{
+  fileOperation("rootname",fname,NULL);
+  return getTclStringResult();
+}
+
+/******************************************************************************/
+
+int PXTkApp::fileExists(const char* fname)
+{
+  fileOperation("exists",fname,NULL);
+  return getTclIntResult();
+}
+
+/******************************************************************************/
+
+int PXTkApp::isFile(const char* fname)
+{
+  fileOperation("isfile",fname,NULL);
+  return getTclIntResult();
+}
+
+/******************************************************************************/
+
+int PXTkApp::isDirectory(const char* fname)
+{
+  fileOperation("isdirectory",fname,NULL);
+  return getTclIntResult();
+}
+
+/******************************************************************************/
+
+int PXTkApp::fileReadable(const char* fname)
+{
+  fileOperation("readable",fname,NULL);
+  return getTclIntResult();
+}
+
+/******************************************************************************/
+
+int PXTkApp::fileWritable(const char* fname)
+{
+  fileOperation("writable",fname,NULL);
+  return getTclIntResult();
+}
+
+/******************************************************************************/
+
+int PXTkApp::fileExecutable(const char* fname)
+{
+  fileOperation("executable",fname,NULL);
+  return getTclIntResult();
+}
+
+/******************************************************************************/
+
+char PXTkApp::getDirSeparator()
+{
+   char DirSeparator = '/';
+  
+#ifdef _WIN32
+      DirSeparator = '\\';
+#endif
+
+   return DirSeparator;
+}
+
+/******************************************************************************/
+
+int PXTkApp::createDirectory(const char* dirName)
+{
+   fileOperation("mkdir", dirName,NULL);
+   return getTclIntResult();
+}
+
+/******************************************************************************/
+
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+char* PXTkApp::getIPAddress()
+{
+  executeTclCommand("set me [socket -server garbage_word -myaddr [info hostname] 0];set ip [lindex [fconfigure $me -sockname] 0];close $me;return $ip");
+  return getTclStringResult();
+    
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+char* PXTkApp::getUserName()
+{
+  executeTclCommand("set $tcl_platform(user)");
+  return getTclStringResult();
+}
+// -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  
+#
+void pxtkapp_find_and_replace( std::string &source, const std::string find, std::string replace ) 
+{
+  size_t j=1,lastpos=0;
+  int ok=0;
+  while (j!=std::string::npos)
+    {
+      j=source.find(find,lastpos);
+      if (j!=std::string::npos)
+	{
+	  //	  std::cerr << "In = " << source.c_str() << "(len="<<source.length() << "-->";
+	  source.replace(j,find.length(),replace);
+	  lastpos=j+replace.length();
+	  ++ok;
+	  //	  std::cerr << source.c_str() << "(len="<< source.length() << "\n";
+	}
+    }
+}
+
+void PXTkApp::StringSanitize(std::string &s)
+{
+  pxtkapp_find_and_replace(s,std::string("\""),std::string("\\\""));
+  pxtkapp_find_and_replace(s,std::string("]"),std::string("\\]"));
+  pxtkapp_find_and_replace(s,std::string("["),std::string("\\["));
+  //  fprintf(stderr,"Sanitizing 3 %s\n",s.c_str());
+}
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkapp.h b/bioimagesuite30_src/pxtklib/pxtkapp.h
new file mode 100644
index 0000000..447bfe0
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkapp.h
@@ -0,0 +1,235 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+// 	$Id: pxtkapp.h,v 1.1 2002/02/20 18:04:13 Xenios Exp papad $	
+// pxtkapp.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTk
+
+_Description : Base Header Definitions and Abstract Classes
+               For C++ and TK interaction
+	       Definitions of basic abstraction mechanisms
+
+	       Definition of 
+	       
+	       PXTkApp                 --- static functions for implementing callbackmechanisms
+	                                   and Tcl/Tk Command Interface  
+
+
+_Call :   
+        
+	
+_References : 
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 11th May 2000
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXTkApp
+#define  _PXTkApp
+
+#include "tcl.h"
+#include "tk.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifndef _WIN32
+   #include <unistd.h>
+#endif
+
+
+#ifndef PXBOOL
+ #ifndef _WIN32
+   enum PXBool { PXFalse = 0, PXTrue };
+ #else
+   #define PXBool  bool
+   #define PXFalse false
+   #define PXTrue  true
+  #endif
+#define PXBOOL 1
+#endif
+
+
+class PXTkInfoDialog;
+class PXTkBase;
+class PXTkEventObj;
+#include <vtkstd/string>
+
+// Number of Event Handlers
+const int PXTK_NUMHANDLERS = 2000;
+
+#define PXTK_APP 1
+// Some functions were added by Rajeevan on 16th Feb, 2004
+
+#define PXTK_APP 1
+
+class   PXTkApp
+{
+private:
+  //  static int           num_event_handlers;
+  //  static PXTkEventObj* event_handlers[PXTK_NUMHANDLERS];
+  static int             num_arguments;
+  static int             initialized;
+  static Tcl_Obj         **arguments;
+  static PXTkInfoDialog  *console;
+  static int              debug_mode;
+
+public:
+  static Tcl_Interp*   tcl_interpreter;
+  static PXBool        debug_tcl;  
+
+  // Initialization Stuff
+  // --------------------
+  static int          initialize(Tcl_Interp* tclinterp);
+  static int          startEventLoop();
+  static int          getNumCommandLineArguments();
+  static char*  getCommandLineArgument(int i);
+
+  // Event Handler Stuff
+  // -------------------
+  //  static int          registerEventHandler(PXTkEventObj* newhandler);
+  //  static int          getNumEventHandlers();
+
+  // Event Loop Handling
+  // -------------------
+
+  static int          handleEventSetup(int objc,Tcl_Obj *CONST objv[],
+				       int& val1,int& val2);
+
+  static int          handleEvent(ClientData clientData, Tcl_Interp *interp,
+				  int objc, Tcl_Obj *CONST objv[]);
+
+
+  static int          getNumArguments();
+  static int          getIntArgument(int);
+  static float        getFloatArgument(int);
+  static char*  getStringArgument(int);
+  
+  // Tcl Command Execution
+  // ---------------------
+  static int          executeTclCommand(const char* command);
+  static char*        getTclStringResult();
+  static float        getTclFloatResult();
+  static int          getTclIntResult();
+
+  static char*         getTclVariable(const char* variablename);
+  static char*         setTclVariable(const char* variablename, const char* value);
+  static int           deleteTclVariable(const char* variablename);
+
+  // Tcl Pointer Stuff
+  // -----------------
+  static Tk_Window     getWidgetPointer(const char* name);
+
+  // Console Related
+  // ---------------
+  static int          consoleEvent(ClientData, Tcl_Interp* ,int, Tcl_Obj *CONST objv[] );
+  static int          consolePrint(ClientData, Tcl_Interp* ,int, Tcl_Obj *CONST objv[] );
+  static int          setDebugMode(ClientData, Tcl_Interp* ,int, Tcl_Obj *CONST objv[] );
+  static int          exitCommand(ClientData, Tcl_Interp* ,int, Tcl_Obj *CONST objv[] );
+  static int          createConsole();
+  static int          popupConsole();
+  static int          printToConsole(const char* line);
+  static int          popdownConsole();
+  static PXTkInfoDialog* GetConsole();
+
+  // Auto Arrange
+  // ------------
+  static int          autoArrangeWindows();
+  static int          popdownChildren(PXTkEventObj* parent);
+
+  // MessageRelated
+  // --------------
+  static int          debugMessage(const char* msg);
+
+  // Wait Cursor
+  static int          setWaitCursor(PXBool setwait);
+  
+  // System Related
+  // --------------
+  static int          getpid();
+  static char*        getpwd();
+
+  // File Processing
+  // -------------------
+  static void         fileOperation(const char* command, const char* fname1, const char* fname2=NULL);
+  static void         deleteFile(const char* fname);
+  static void         copyFile(const char* source,const char* dest);
+  static void         renameFile(const char* source,const char* dest);
+
+  static char*        getFilenameExtension(const char* fname);
+  static char*        getFilenamePath(const char* fname);
+  static char*        getFilenameTail(const char* fname);
+  static char*        getFilenameRoot(const char* fname);
+
+  // File functions added by rajeevan
+  static int          fileExists(const char* fname);
+  static int          isFile(const char* fname);
+  static int          isDirectory(const char* fname);
+  static int          fileReadable(const char* fname);
+  static int          fileWritable(const char* fname);
+  static int          fileExecutable(const char* fname);
+
+  static char         getDirSeparator();
+  static int          createDirectory(const char* dirName);
+
+  // Some Machine Information
+  // ------------------------
+  static char*        getIPAddress();
+  static char*        getUserName();
+  
+
+  static int   Irange(int   a,int   minv,int   maxv);
+  static float Frange(float a,float minv,float maxv);
+
+  // String Stuff
+  static void  StringSanitize(std::string& source);
+
+};
+
+
+#endif /*  _PXTkEventObj */
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkbase.cpp b/bioimagesuite30_src/pxtklib/pxtkbase.cpp
new file mode 100644
index 0000000..55c3431
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkbase.cpp
@@ -0,0 +1,150 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+#include "pxtkbase.h"
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtk.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+ /* ********************************************************************
+
+    Definition of PXTkBase Class 
+
+ ********************************************************************* */
+
+int    PXTkBase::num_objects=0;
+
+PXTkBase::PXTkBase(PXTkEventObj* par,PXTkGadget* gadg) 
+{
+  object_id=num_objects;
+  ++num_objects;
+  has_gadget_parent=PXFalse;
+  gadget_parent=NULL;
+  has_event_parent=PXFalse;
+  event_parent=NULL;
+
+  if (par!=NULL)
+      {
+	has_event_parent=PXTrue;
+	event_parent=par;
+      }
+
+  if (gadg!=NULL)
+      {
+	gadget_parent=gadg;
+	has_gadget_parent=PXTrue;
+      }
+
+  is_display_ok=PXFalse;
+}
+
+PXBool PXTkBase::isGadget() 
+{ 
+  return PXTrue;
+}
+
+PXTkClassId PXTkBase::getClassId() 
+{ 
+  return PXTkBaseId;
+}
+
+int PXTkBase::getObjectId() 
+{
+  return object_id;
+}
+
+PXTkEventObj* PXTkBase::getEventParent()
+{
+  return event_parent;
+}
+
+PXBool PXTkBase::hasEventParent()
+{
+  return has_event_parent;
+}
+
+PXTkGadget* PXTkBase::getGadgetParent()
+{
+  return gadget_parent;
+}
+
+PXBool PXTkBase::hasGadgetParent()
+{
+  return has_gadget_parent;
+}
+
+int PXTkBase::initDisplay() 
+{
+  return TCL_OK;
+}
+
+PXBool PXTkBase::isDisplayOk()
+{
+  return is_display_ok;
+}
+
+int PXTkBase::enable(PXBool )
+{
+  return TCL_OK;
+}
+
+int PXTkBase::disable()
+{
+  return enable(PXFalse);
+}
+
+int  PXTkBase::Irange(int   a,int   minv,int   maxv)
+{
+  if (a<minv) a=minv;
+  if (a>maxv) a=maxv;
+  return a;
+}
+
+
+float PXTkBase::Frange(float a,float minv,float maxv)
+{
+  if (a<minv) a=minv;
+  if (a>maxv) a=maxv;
+  return a;
+}
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkbase.h b/bioimagesuite30_src/pxtklib/pxtkbase.h
new file mode 100644
index 0000000..6cda21d
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkbase.h
@@ -0,0 +1,114 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkbase.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTk
+
+_Description : Definition of PXTkBase --- Abstract base class for all objects in this library
+
+_Call :   
+        
+	
+_References : 
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 11th May 2000
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXTkBase
+#define  _PXTkBase
+
+#include "pxtkapp.h"
+
+enum PXTkClassId { PXTkBaseId = 0 , PXTkGadgetId, PXTkObjId ,PXTkDialogId,PXTkFrameId,PXTkToplevelId,PXVTkComponentId};
+
+
+class PXTkEventObj;
+class PXTkGadget;
+
+class PXTkBase {
+
+protected:
+
+  static  int              num_objects;
+  int                      object_id;
+  PXTkEventObj*            event_parent;
+  PXBool                   has_event_parent;
+  PXTkGadget*              gadget_parent;
+  PXBool                   has_gadget_parent;
+  PXBool                   is_display_ok;
+
+public:
+  PXTkBase(PXTkEventObj* par=NULL,PXTkGadget* gadg=NULL);
+
+  virtual   PXBool         isGadget();
+  virtual   PXTkClassId    getClassId();
+  virtual   int            getObjectId();
+ 
+  virtual   PXTkEventObj*  getEventParent();
+  virtual   PXBool      hasEventParent();
+
+  virtual PXTkGadget*   getGadgetParent();
+  virtual PXBool        hasGadgetParent();
+
+  virtual int          initDisplay();
+  virtual PXBool       isDisplayOk();
+
+  virtual int          enable(PXBool enab=PXTrue);
+  virtual int          disable();
+
+  static int   Irange(int   a,int   minv,int   maxv);
+  static float Frange(float a,float minv,float maxv);
+
+};
+
+
+#endif /*  _PXTkBase */
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkbutton.cpp b/bioimagesuite30_src/pxtklib/pxtkbutton.cpp
new file mode 100644
index 0000000..55634af
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkbutton.cpp
@@ -0,0 +1,87 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkbutton.cpp
+#include "pxtkbutton.h"
+#include "pxtkeventobj.h"
+#include <stdlib.h>
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtkbutton.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+ /* ********************************************************************
+
+    Definition of PXTkButton Class 
+
+ ********************************************************************* */
+
+PXTkButton::PXTkButton(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* name,int callno,PXBool dodisplay):PXTkLabel(evpar,gadg_par,NULL,PXFalse)
+{
+  if (dodisplay)
+      {
+	initDisplay();
+	setText(name);
+	setCallback(callno);
+      }
+}
+
+int PXTkButton::setCallback(int callno)
+{
+  if (callno>=0)
+      {
+	sprintf(pxtk_buffer,"{pxtkcallback %d %d %ld}",event_parent->getHandlerNo(),callno,(long)this);
+	return configure("-command",pxtk_buffer);
+      }
+  else
+      return TCL_OK;
+}
+
+int PXTkButton::initDisplay()
+{
+  sprintf(pxtk_buffer,"button %s",widget_name);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+    return a;
+}
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkbutton.h b/bioimagesuite30_src/pxtklib/pxtkbutton.h
new file mode 100644
index 0000000..546f210
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkbutton.h
@@ -0,0 +1,85 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkbutton.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkButton
+
+_Description : Definition of class PXTkButton to warp Button TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtklabel.h"
+#include "pxtkeventobj.h"
+
+#ifndef _PXTkButton
+#define  _PXTkButton
+
+/* ----  Definition of PXTkButton Class  ---- */
+
+class PXTkButton: public PXTkLabel
+{
+public:
+  PXTkButton(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* name,int callno,
+	     PXBool dodisplay=PXTrue);
+  virtual int setCallback(int callno);
+  virtual int initDisplay();
+};   
+
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkcheckbutton.cpp b/bioimagesuite30_src/pxtklib/pxtkcheckbutton.cpp
new file mode 100644
index 0000000..318541b
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkcheckbutton.cpp
@@ -0,0 +1,107 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkcheckbutton.cpp
+#include "pxtkcheckbutton.h"
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtkcheckbutton.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+ /* ********************************************************************
+
+    Definition of PXTkCheckButton Class 
+
+ ********************************************************************* */
+
+PXTkCheckButton::PXTkCheckButton(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* name,int callno,
+				 PXBool dodisplay):PXTkButton(evpar,gadg_par,NULL,-1,PXFalse)
+{
+    if (dodisplay)
+      {
+	initDisplay();
+	setText(name);
+	setCallback(callno);
+	call_no=callno;
+      }
+}
+
+int PXTkCheckButton::initDisplay()
+{
+  setWidgetVariable("0");
+  sprintf(pxtk_buffer,"checkbutton %s -variable widgetvar%d",widget_name,object_id);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+  return a;
+}
+ 
+PXBool PXTkCheckButton::getState()
+{
+  char* line=getWidgetVariable();
+
+  if (line==NULL)
+    {
+      fprintf(stderr,"NULL checkButton getState %s widgetvar%d\n",widget_name,object_id);
+      return PXFalse;
+    }
+
+  int a=atoi(line);
+  if (a==1)
+      return PXTrue;
+  return PXFalse;
+}
+
+int  PXTkCheckButton::setState(PXBool state,PXBool callback)
+{
+  if (state)
+     setWidgetVariable("1");
+  else
+      setWidgetVariable("0");
+  
+  if (callback && call_no>0)
+      return event_parent->handleEvent(call_no);
+  else
+      return TCL_OK;
+}   
+
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkcheckbutton.h b/bioimagesuite30_src/pxtklib/pxtkcheckbutton.h
new file mode 100644
index 0000000..4f5eb2c
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkcheckbutton.h
@@ -0,0 +1,88 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkcheckbutton.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkCheckButton
+
+_Description : Definition of class PXTkCheckButton to warp CheckButton TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtkbutton.h"
+
+#ifndef _PXTkCheckButton
+#define  _PXTkCheckButton
+
+
+/* ----  Definition of PXTkCheckButton ---- */
+
+class PXTkCheckButton: public PXTkButton
+{
+protected:
+  int call_no;
+
+public:
+  PXTkCheckButton(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* name,int callno,PXBool dodisplay=PXTrue);
+
+  virtual int    initDisplay();
+  virtual PXBool getState();
+  virtual int    setState(PXBool state,PXBool callback=PXFalse);
+};   
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkcomplexwidgets.cpp b/bioimagesuite30_src/pxtklib/pxtkcomplexwidgets.cpp
new file mode 100644
index 0000000..c3b68fb
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkcomplexwidgets.cpp
@@ -0,0 +1,571 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+#include "pxtkcomplexwidgets.h"
+#include <stdlib.h>
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+
+   see pxtkcomplexwidgets.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+/* -------------------------------------------------------------------------*/
+/*                   PXGrArrowScale                                         */
+/* -------------------------------------------------------------------------*/
+ 
+PXTkArrowScale::PXTkArrowScale(PXTkEventObj* par,PXTkGadget* w,const char* wname,int moption,
+			       PXBool labelabove,PXBool showentry):PXTkEventObj(par,w)
+{
+  menu_option=moption;
+  label_above=labelabove;
+  show_entry=showentry;
+  label=NULL;
+  initDisplay();
+  setRange(0.0, 10.0);
+  setValue(5.0);
+
+  setDecimalPoints(0);
+  setIncrement(1.0);
+  setLengthWidth(70);
+  setLabel(wname);
+}
+
+void PXTkArrowScale::setLabel(const char* wname)
+{
+  if (label_above)
+      {
+	scale->setLabel(wname);
+      }
+  else
+      {
+	scale->setLabel("");
+	label->setText(wname);
+      }
+}
+
+// ----------------------------------------------------------------
+void PXTkArrowScale::setLengthWidth(int length,int width)
+{
+  if (!is_display_ok)
+      return;
+
+  if (length<20)      length=20;
+  if (length>300)     length=300;
+
+  if (show_entry)
+    length-=15;
+
+  scale->setLengthWidth(length,width);
+
+}
+
+void PXTkArrowScale::setRange(float min,float max)
+{
+  min_value=min;
+  max_value=max;
+  
+  if (min>max)
+      {
+	min_value=max;
+	max_value=min;
+      }
+
+  if (min==max)
+      max+=0.0001;
+
+  if (is_display_ok)
+      scale->setRange(min,max);
+
+}
+
+void PXTkArrowScale::setIncrement(float inc)
+{
+  increment=inc;
+}
+
+void PXTkArrowScale::setValue(float vl,PXBool callback)
+{
+  if (!is_display_ok)
+      return;
+
+  if (vl<min_value)      vl=min_value;
+  if (vl>max_value)      vl=max_value;
+  
+  scale->setValue(vl);
+  if (callback)
+      event_parent->handleEvent(menu_option);
+}
+
+
+void PXTkArrowScale::setDecimalPoints(int dp)
+{
+  if (!is_display_ok)
+      return;
+
+  if (dp<0) dp=0;
+  if (dp>8) dp=8;
+
+  
+  float a=fabs(min_value);
+  if (a<fabs(max_value))
+      a=fabs(max_value);
+  
+  int dig=int(log(a)/log(10.0)+0.5)+dp;
+  float res=pow(10.0,-(dig-1));
+
+
+  //  fprintf(stderr,"dp=%d dig=%d res=%.2f\n",dp,dig,res);
+
+  scale->setDigits(dig);
+  scale->setResolution(res);
+
+}
+
+void PXTkArrowScale::setResolution(float res)
+{
+  if (is_display_ok)
+      scale->setResolution(res);
+}
+
+float  PXTkArrowScale::getValue()       
+{ 
+  if (is_display_ok)
+      return scale->getValue();
+  else
+      return 0.0;
+}
+
+// ----------------------------------------------------------------
+int PXTkArrowScale::initDisplay()
+{
+  PXTkFrame* main=new PXTkFrame(this,gadget_parent);
+  main_window=main;
+
+  //main->configure("-relief","raised");
+  main->configure("-bd ","2");
+
+  if (!label_above)
+    {
+      label=new PXTkLabel(this,main,"Hello");
+      label->configure("relief","ridge");
+    }
+  
+  left=new PXTkDrawButton(this,main,1,101);
+  scale=new PXTkScale(this,main,"val",100);
+  right=new PXTkDrawButton(this,main,3,102);
+
+  scale->setLengthWidth(100,10);
+  scale->setValue(0.0);
+  scale->configure("-bd",0);
+
+  main->setPackMode(PXFalse);
+  if (!label_above)
+    main->addChildren("-row 0 -column 0 -sticky es",label);
+  
+  main->addChildren("-row 0 -column 1 -sticky s",left);
+  main->addChildren("-row 0 -column 2 -sticky nsew",scale);
+  main->addChildren("-row 0 -column 3 -sticky s",right);
+  
+  if (show_entry)
+    {
+      int id=scale->getObjectId();
+      sprintf(pxtk_buffer,
+	      "entry %s_e -textvariable widgetvar%d -width 6; grid %s_e -row 0 -column 4 -stick sw",scale->getWidgetName(),id,scale->getWidgetName());
+      PXTkApp::executeTclCommand(pxtk_buffer);
+    }
+
+  main->gridExpandColumnConfigure(0,0);
+  main->gridExpandColumnConfigure(1,0);
+  main->gridExpandColumnConfigure(2,1);
+  main->gridExpandColumnConfigure(3,0);
+
+  is_display_ok=PXTrue;
+  return TCL_OK;
+     
+}
+// ----------------------------------------------------------------
+int PXTkArrowScale::handleEvent(int n)
+{
+  float vl=getValue();
+
+  switch(n)
+      {
+      case 102:
+	setValue(vl+increment);
+	break;
+      case 101:
+	setValue(vl-increment);
+	break;
+      case 100:
+	// Round up or down
+	break;
+      }
+
+  return event_parent->handleEvent(menu_option);
+}
+
+int PXTkArrowScale::setMenuOption(int m)
+{
+  menu_option=m;
+  return TCL_OK;
+}
+
+PXTkScale* PXTkArrowScale::getScale()
+{
+  return scale;
+}
+
+int PXTkArrowScale::enable(PXBool enab)
+{
+  left->enable(enab);
+  right->enable(enab);
+  return scale->enable(enab);
+  return TCL_OK;
+}
+
+/* -------------------------------------------------------------------------*/
+/*                   PXTkSpinner                                         */
+/* -------------------------------------------------------------------------*/
+
+
+PXTkSpinner::PXTkSpinner(PXTkEventObj* par,PXTkGadget* w,const char* wname,int moption):PXTkEventObj(par,w)
+{
+  menu_option=moption;
+  initDisplay();
+  setRange(0.0,1.0);
+  setValue(0.5);
+  setDecimalPoints(1);
+  setIncrement((float)0.1);
+  label->setText(wname);
+}
+ 
+void PXTkSpinner::setRange(float min,float max)
+{
+  min_value=min;
+  max_value=max;
+  if (min_value>max_value)
+      {
+	min_value=max;
+	max_value=min;
+      }
+  if (min_value==max_value)
+      max_value+=1.0;
+
+  if (current_value<min_value || current_value>max_value)
+      setValue(current_value);
+}
+
+void PXTkSpinner::setIncrement(float inc)
+{
+  increment=inc;
+}
+
+void PXTkSpinner::setValue(float vl,PXBool callback)
+{
+  if (vl<min_value)
+      vl=min_value;
+  if (vl>max_value)
+      vl=max_value;
+
+  current_value=vl;
+  if (is_display_ok)
+      {
+	switch(decimal_points)
+	    {
+	    case 1:
+	      sprintf(pxtk_buffer2,"%4.1f",current_value);
+	      break;
+	    case 2:
+	      sprintf(pxtk_buffer2,"%5.2f",current_value);
+	      break;
+	    case 3:
+	      sprintf(pxtk_buffer2,"%6.3f",current_value);
+	      break;
+
+	    default:
+	      sprintf(pxtk_buffer2,"%3.0f",current_value);
+	      break;
+
+	    }
+	value_label->setText(pxtk_buffer2);
+	
+	if (callback)
+	    event_parent->handleEvent(menu_option);
+      }
+}
+
+void PXTkSpinner::setDecimalPoints(int dp)
+{
+  if (dp<0) dp=0;
+  if (dp>3) dp=3;
+  decimal_points=dp;
+}
+
+int PXTkSpinner::initDisplay()
+{
+  PXTkFrame* main=new PXTkFrame(this,gadget_parent);
+  main_window=main;
+  //main->configure("-relief","raised");
+  main->configure("-bd ","2");
+
+
+  label=new PXTkLabel(this,main,"Value");
+  //label->configure("relief","ridge");
+
+  left=new PXTkDrawButton(this,main,2,101);
+  value_label=new PXTkLabel(this,main,"0.0");
+  right=new PXTkDrawButton(this,main,0,102);
+  
+  main->setPackMode(PXFalse);
+  main->addChildren("-row 0 -column 0 -sticky ens",label);
+  main->addChildren("-row 0 -column 1 -sticky sw",left);
+  main->addChildren("-row 0 -column 2 -sticky sn",value_label);
+  main->addChildren("-row 0 -column 3 -sticky nw",right);
+
+
+  is_display_ok=PXTrue;
+  return TCL_OK;
+}
+
+int PXTkSpinner::handleEvent(int n)
+{
+  switch(n)
+      {
+      case 101:
+	setValue(current_value-increment);
+	break;
+      case 102:
+	setValue(current_value+increment);
+	break;
+      }
+  return event_parent->handleEvent(menu_option);
+}
+
+
+int PXTkSpinner::enable(PXBool enab)
+{
+  if (!is_display_ok)
+      return TCL_OK;
+  left->enable(enab);
+  return right->enable(enab);
+}
+ 
+
+/* --------------------------------------*/
+/*   PXTkLabelFrame Class                */
+/* --------------------------------------*/
+ 
+PXTkLabelFrame::PXTkLabelFrame(PXTkEventObj* evpar,PXTkGadget* par,const char* label,int width,
+			       int height):PXTkFrame(evpar,par,-1,-1,PXFalse)
+{
+  initializeLabelFrame();
+  initDisplay(label);
+  setDimensions(width,height);
+}
+
+int PXTkLabelFrame::initDisplay(const char *text)
+{
+  sprintf(pxtk_buffer,"LabelFrame:create %s -text \"%s\" -relief ridge",
+	  widget_base_name,text);
+
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  char* line=PXTkApp::getTclStringResult();
+
+  delete [] widget_name;
+  widget_name=new char[strlen(line)+1];
+  strcpy(widget_name,line);
+
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+  return a;
+}
+
+int PXTkLabelFrame::initializeLabelFrame()
+{
+  static int num=0;
+  num++;
+
+  if (num==1)
+      {
+	static char pxtk_rlabelframe[] = "package require Iwidgets;proc LabelFrame:create { w args } {    iwidgets::Labeledframe $w -labelpos nw;     foreach { tag value } $args { 	switch -- $tag { 	    -text { $w configure -labeltext $value }	    -width { [ $w childsite ] configure -width $value } } } ;    return [ $w childsite ]}";
+	return PXTkApp::executeTclCommand(pxtk_rlabelframe);
+      }
+  
+  return TCL_OK;
+}
+
+/* --------------------------------------*/
+/*   PXTkDrawButton Class               */
+/* --------------------------------------*/
+PXTkDrawButton::PXTkDrawButton(PXTkEventObj* evpar,PXTkGadget* gadg_par,
+				 int md,int callno,PXBool dodisplay):PXTkButton(evpar,gadg_par," ",callno,dodisplay)
+{
+  mode=Irange(md,0,6);
+  if (dodisplay)
+      {
+	initializeBimaps();
+	initDisplay();
+      }
+}
+
+int PXTkDrawButton::initDisplay()
+{
+  switch (mode)
+      {
+      case 0:
+	configure("-image","$pxtk_arrow_up");
+	break;
+      case 1:
+	configure("-image","$pxtk_arrow_left");
+	break;
+      case 2:
+	configure("-image","$pxtk_arrow_down");
+	break;
+      case 3:
+	configure("-image","$pxtk_arrow_right");
+	break;
+      case 4:
+	configure("-image","$pxtk_stop_button");
+	break;
+      case 5:
+	configure("-image","$pxtk_play_button");
+	configure("-fg","black");
+	configure("-bg","darkgray");
+	break;
+      case 6:
+	configure("-image","$pxtk_record_button");
+	configure("-fg","red");
+	configure("-bg","white");
+	break;
+
+      }
+  configure("-height",12);
+  configure("-width",12);
+  configure("-padx",3);
+  configure("-pady",3);
+  return TCL_OK;
+}
+
+int PXTkDrawButton::initializeBimaps()
+{
+  static int num=0;
+  num++;
+
+  if (num==1)
+      {
+	static char arrow_definitions1[] = "set pxtk_arrow_up [ image create bitmap -data { #define up_width 10\n #define up_height 10\n static unsigned char up_bits[] = {    0x30, 0x00, 0x30, 0x00, 0x78, 0x00, 0x78, 0x00, 0xfc, 0x00, 0xfc, 0x00,  0xfe, 0x01, 0xfe, 0x01, 0xff, 0x03, 0xff, 0x03;}}] ";
+
+	static char arrow_definitions2[]="set pxtk_arrow_down [ image create bitmap -data { #define down_width 10\n #define down_height 10\n static unsigned char down_bits[] = {   0xff, 0x03, 0xff, 0x03, 0xfe, 0x01, 0xfe, 0x01, 0xfc, 0x00, 0xfc, 0x00,   0x78, 0x00, 0x78, 0x00, 0x30, 0x00, 0x30, 0x00;}}]";
+
+	static char arrow_definitions3[]="set pxtk_arrow_right [ image create bitmap -data {#define right_width 10\n #define right_height 10\n static unsigned char right_bits[] = {   0x03, 0x00, 0x0f, 0x00, 0x3f, 0x00, 0xff, 0x00, 0xff, 0x03, 0xff, 0x03,   0xff, 0x00, 0x3f, 0x00, 0x0f, 0x00, 0x03, 0x00;}}]";
+
+	static char arrow_definitions4[]="set pxtk_arrow_left [ image create bitmap -data { #define left_width 10\n #define left_height 10\n static unsigned char left_bits[] = {   0x00, 0x03, 0xc0, 0x03, 0xf0, 0x03, 0xfc, 0x03, 0xff, 0x03, 0xff, 0x03,   0xfc, 0x03, 0xf0, 0x03, 0xc0, 0x03, 0x00, 0x03;}}]";
+
+	static char arrow_definitions5[]="set pxtk_stop_button [ image create bitmap -data {#define stop_width 10\n #define stop_height 10\n static unsigned char stop_bits[] = {   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00,   0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00;}}]";
+
+	static char arrow_definitions6[]="set pxtk_play_button [ image create bitmap -data {#define play_width 11\n #define play_height 11\n static unsigned char play_bits[] = {   0x00, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0xfc, 0x01, 0xfc, 0x03,   0xfc, 0x01, 0x7c, 0x00, 0x1c, 0x00, 0x04, 0x00, 0x00, 0x00;}}]";
+
+	static char arrow_definitions7[]="set pxtk_record_button [ image create bitmap -data {#define record_width 11\n #define record_height 11\n static unsigned char record_bits[] = {   0x00, 0x00, 0x20, 0x00, 0xf8, 0x00, 0xfc, 0x01, 0xfc, 0x01, 0xfe, 0x03,   0xfc, 0x01, 0xfc, 0x01, 0xf8, 0x00, 0x20, 0x00, 0x00, 0x00;}}]";
+
+	PXTkApp::executeTclCommand(arrow_definitions1);
+	PXTkApp::executeTclCommand(arrow_definitions2);
+	PXTkApp::executeTclCommand(arrow_definitions3);
+	PXTkApp::executeTclCommand(arrow_definitions3);
+	PXTkApp::executeTclCommand(arrow_definitions4);
+	PXTkApp::executeTclCommand(arrow_definitions5);
+	PXTkApp::executeTclCommand(arrow_definitions6);
+	return PXTkApp::executeTclCommand(arrow_definitions7);
+      }
+  else
+      return TCL_OK;
+}   
+
+/* --------------------------------------*/
+/*   PXTkDualArrowLabel Class            */
+/* --------------------------------------*/
+
+
+PXTkDualArrowLabel::PXTkDualArrowLabel(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* label,
+				       int upcall,int downcall,int orient,PXBool dodisplay):PXTkLabel(evpar,gadg_par,label,PXFalse)
+{
+  orientation=orient>0;
+  callback_up=upcall;
+  callback_down=downcall;
+  if (dodisplay)
+      {
+	initDisplay();
+	sprintf(pxtk_buffer,"%s configure -text \"%s\" ",widget_name,label);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+      }
+}
+
+int PXTkDualArrowLabel::initDisplay()
+{
+
+  sprintf(pxtk_buffer,"frame %s",widget_name);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  
+  if (a!=TCL_OK)
+      return TCL_ERROR;
+      
+  PXTkFrame* main=new PXTkFrame(event_parent,widget_name);
+  
+  int upmode=0,downmode=2;
+  if (orientation==0)
+      {
+	upmode=3;
+	downmode=1;
+      }
+
+  PXTkDrawButton* up=new PXTkDrawButton(event_parent,main,upmode,callback_up);
+  PXTkLabel* lab=new PXTkLabel(event_parent,main," ");
+  PXTkDrawButton* down=new PXTkDrawButton(event_parent,main,downmode,callback_down);
+  
+  if (orientation==0)
+      main->addChildren("-side left -expand true -fill x",down,lab,up);
+  else
+      main->addChildren("-side top -expand true -fill y",up,lab,down);
+  
+  delete [] widget_name;
+  widget_name=new char[strlen(lab->getWidgetName())+1];
+  strcpy(widget_name,lab->getWidgetName());
+  return TCL_OK;
+}
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkcomplexwidgets.h b/bioimagesuite30_src/pxtklib/pxtkcomplexwidgets.h
new file mode 100644
index 0000000..b5e6d5b
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkcomplexwidgets.h
@@ -0,0 +1,207 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkcomplexwidgets.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkComplexWidgets
+
+
+_Description : 
+
+_Call : (examples)
+  
+_References : 
+
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 12th May 2000
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXTk_WIDGETS
+#define _PXTk_WIDGETS
+
+#include "pxtkgadgets.h"
+#include "math.h"
+#include "pxtkeventobj.h"
+
+class PXTkDrawButton;
+
+// ****************************************
+// ******* PXTkArrowScale Class ************
+// ****************************************
+
+class PXTkArrowScale : public PXTkEventObj {
+  
+protected:
+  
+  PXTkDrawButton* left,*right;
+  PXTkScale* scale;
+  PXTkLabel* label;
+  float    min_value,max_value,increment;
+  int      menu_option;
+  PXBool   label_above;
+  PXBool   show_entry;
+
+public:
+  
+  PXTkArrowScale(PXTkEventObj* par,PXTkGadget* w,const char* name,int moption,PXBool labelabove=PXTrue,
+		 PXBool showentry=PXFalse);
+
+  float     getmin()         { return (min_value); }
+  float     getmax()         { return (max_value); }
+  float     getincrement()   { return (increment); }
+
+
+  void    setLabel(const char* label);
+  float   getValue();
+
+  PXTkScale* getScale();
+
+  void    setRange(float min,float max);
+  void    setIncrement(float inc);
+  void    setLengthWidth(int len,int wid=-1);
+  void    setValue(float vl,PXBool callBack=PXFalse);
+  void    setDecimalPoints(int dp);
+  void    setResolution(float res);
+
+  int     enable(PXBool enab=PXTrue);
+
+  virtual int initDisplay();
+  virtual int handleEvent(int);   
+  virtual int setMenuOption(int m);
+
+};
+
+// ****************************************
+// ******* PXTkSpinner Class ************
+// ****************************************
+
+class PXTkSpinner : public PXTkEventObj {
+  
+protected:
+  
+  float      min_value,max_value,increment,current_value;
+  int        decimal_points,menu_option;
+  PXTkLabel* label,*value_label;
+  PXTkDrawButton* left,*right;
+public:
+  
+  PXTkSpinner(PXTkEventObj* par,PXTkGadget* w,const char* name,int moption);
+
+  float     getValue()       { return current_value;  }
+
+  void    setRange(float min,float max);
+  void    setIncrement(float inc);
+  void    setValue(float vl,PXBool callBack=PXFalse);
+  void    setDecimalPoints(int dp);
+
+  virtual int initDisplay();
+  virtual int handleEvent(int);   
+
+  int     enable(PXBool enab=PXTrue);
+};
+
+/* ******************************************
+   *******  Class PXTkLabelFrame
+   ****************************************** */
+
+// Uses Iwidgets
+
+class PXTkLabelFrame : public PXTkFrame {
+
+public:
+
+  PXTkLabelFrame(PXTkEventObj*,PXTkGadget* par,const char* label,int width=-1,int height=-1);
+
+  virtual int initDisplay(const char* text);
+
+private:
+    static int initializeLabelFrame();
+};
+
+/* --------------------------------------*/
+/*   PXTkDrawButton Class               */
+/* --------------------------------------*/
+class PXTkDrawButton: public PXTkButton
+{
+  
+protected:
+  int mode;
+public:
+  PXTkDrawButton(PXTkEventObj* evpar,PXTkGadget* gadg_par,int mode,int callno,
+		  PXBool dodisplay=PXTrue);
+  virtual int initDisplay();
+  
+private:
+  static int initializeBimaps();
+};
+
+/* --------------------------------------*/
+/*   PXTkDualArrowLabel Class            */
+/* --------------------------------------*/
+
+class PXTkDualArrowLabel : public PXTkLabel
+{
+
+protected:
+  int callback_up,callback_down;
+  int orientation;
+
+public:
+  PXTkDualArrowLabel(PXTkEventObj* objpar,PXTkGadget* gadg_par,const char* label,
+		     int upcall,int downcall,int orient=0,PXBool dodisplay=PXTrue);
+  virtual int initDisplay();
+};   
+
+
+
+#endif   
+
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkdialog.cpp b/bioimagesuite30_src/pxtklib/pxtkdialog.cpp
new file mode 100644
index 0000000..90ecc9f
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkdialog.cpp
@@ -0,0 +1,256 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "pxtkdialog.h"
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris Mat 1995   papad at noodle.med.yale.edu
+
+   see pxtkdialog.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+/* -------------------------------------------------------------------------*/
+/*                   PXTkDialog                                          */
+/* -------------------------------------------------------------------------*/
+
+PXTkDialog::PXTkDialog(PXTkGadget* par, const char* title,PXBool insideparent):PXTkEventObj(NULL,par)
+{
+  init(title,insideparent);
+}
+
+/* -------------------------------------------------------------------------*/
+PXTkDialog::PXTkDialog(PXTkEventObj* objpar, const char* title,PXBool insideparent):PXTkEventObj(objpar,objpar->getMainWindow())
+{
+  init(title,insideparent);
+}
+/* -------------------------------------------------------------------------*/
+PXTkDialog::PXTkDialog(PXTkEventObj* objpar,PXTkGadget* w, const char* title,PXBool insideparent):PXTkEventObj(objpar,w)
+{
+  init(title,insideparent);
+}
+/* -------------------------------------------------------------------------*/
+PXTkDialog::~PXTkDialog()
+{
+  if (is_display_ok)
+      {
+	if (!create_inside_parent)
+	    popdownDialog();
+	sprintf(pxtk_buffer,"tkwait destroy %s",main_window->getWidgetName());
+	PXTkApp::executeTclCommand(pxtk_buffer);
+      }
+  delete [] dlg_title;
+}
+/* -------------------------------------------------------------------------*/
+void PXTkDialog::init(const char* title,PXBool inside)
+{
+  is_display_ok=PXFalse;
+   dlg_title=NULL;
+   setTitle(title);
+   height=300;
+   width=400;
+   create_inside_parent=inside;
+
+ }
+ /* -------------------------------------------------------------------------*/
+int PXTkDialog::initDisplay()
+{
+  width=Irange(width,64,1024);
+  height=Irange(height,64,1024);
+
+  if (create_inside_parent)
+      {
+	PXTkFrame *frame=new PXTkFrame(this,gadget_parent,width,height);
+	main_window=frame;
+	packMainWindow();
+       }
+  else
+      {
+	PXTkToplevel *dlg=new PXTkToplevel(this,gadget_parent,dlg_title,width,height);
+	main_window=dlg;
+	dlg->hide();
+	modality=PXFalse;
+      }
+  is_display_ok=PXTrue;
+  
+  return TCL_OK;
+}
+
+/* -------------------------------------------------------------------------*/
+void PXTkDialog::setModality(PXBool modal)
+{
+  if (create_inside_parent)
+      return;
+  
+  modality=modal;
+  if (isOpen() && is_display_ok)
+      ((PXTkToplevel*)main_window)->setGrab(modal);
+}
+/* -------------------------------------------------------------------------*/
+void PXTkDialog::setSize(int w,int h)
+{
+  width=Irange(w,64,1024); height=Irange(h,64,1024);
+  if (isOpen())
+      ((PXTkFrame*)main_window)->setDimensions(w,h);
+}
+/* -------------------------------------------------------------------------*/
+void PXTkDialog::popupDialog()
+{
+  if (create_inside_parent)
+      return;
+  
+  if (is_display_ok==PXFalse)
+      initDisplay();
+  
+  ((PXTkToplevel*)main_window)->show(1);
+  
+  if (modality)
+      ((PXTkToplevel*)main_window)->setGrab(PXTrue);
+}
+/* -------------------------------------------------------------------------*/
+void PXTkDialog::popdownDialog()
+{
+  //	printf("--->In PXTkDialog::popdownDialog... %d %d\n", create_inside_parent, modality);
+  // Makes no sense so ignore 
+  if (create_inside_parent)
+      return;
+
+  if (isOpen())
+      {
+	if (modality)
+	    ((PXTkToplevel*)main_window)->setGrab(PXFalse);
+	((PXTkToplevel*)main_window)->hide();
+      }
+}
+/* -------------------------------------------------------------------------*/
+void PXTkDialog::setTitle(const char* title)
+{
+  if (dlg_title!=NULL)
+      delete [] dlg_title;
+
+  dlg_title=new char[strlen(title)+2];
+  strcpy(dlg_title,title);
+  
+  if (is_display_ok)
+      {
+	if (create_inside_parent && !has_event_parent)
+	    {
+	      sprintf(pxtk_buffer,"wm title . \"%s\"",dlg_title);
+	      PXTkApp::executeTclCommand(pxtk_buffer);
+	    }
+	else
+	    {
+	      ((PXTkToplevel*)main_window)->setTitle(dlg_title);
+	    }
+      }
+}
+/* -------------------------------------------------------------------------*/
+void PXTkDialog::exitCallback(const char* line)
+{
+#ifndef _WIN32
+  exit(0);
+#else
+//  PXTkApp::executeTclCommand("destroy .");
+  PXTkApp::executeTclCommand("exit");
+#endif
+}
+/* -------------------------------------------------------------------------*/
+void PXTkDialog::aboutCallback(const char* line)
+{
+  if (line==NULL)
+      messageBox("This Application \n(c) X.Papademetris 1995-2000",
+		 "About this application");
+  else
+      messageBox(line,
+		 "About this application");
+}
+/* -------------------------------------------------------------------------*/
+PXTkClassId PXTkDialog::getClassId()
+{
+  return PXTkDialogId;
+}
+
+PXBool PXTkDialog::isInside()
+{
+  return create_inside_parent;
+}
+
+PXBool PXTkDialog::isOpen()
+{
+  if (!is_display_ok)
+      return PXFalse;
+
+  if (create_inside_parent)
+    return PXTrue;
+
+  sprintf(pxtk_buffer,"wm state %s",main_window->getWidgetName());
+  PXTkApp::executeTclCommand(pxtk_buffer);
+  char* a=PXTkApp::getTclStringResult();
+  if (a!=NULL)
+    {
+      if (strcmp(a,"normal")==0)
+	return PXTrue;
+    }
+  
+  return PXFalse;
+}
+/* -------------------------------------------------------------------------*/
+int PXTkDialog::handleEvent(int eventno)
+{
+  switch(eventno)
+      {
+      case 0:
+	aboutCallback();
+	break;
+      case 1:
+	{
+	  int ok=questionBox("Do you really want to exit?");
+	  if (ok)
+	      exitCallback();
+	}
+	break;
+      case 2:
+	PXTkApp::popupConsole();
+	break;
+      case 3:
+	popdownDialog();
+	break;
+      case 4:
+	PXTkApp::autoArrangeWindows();
+	break;
+      }
+  return TCL_OK;
+}
+
+/* -------------------------------------------------------------------------*/
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkdialog.h b/bioimagesuite30_src/pxtklib/pxtkdialog.h
new file mode 100644
index 0000000..78e45df
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkdialog.h
@@ -0,0 +1,117 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxgrinfodialog.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkDialog
+
+
+_Description : This is a abstract class to create popup-dialogs
+               And Base Windows 
+
+_Call : 
+  
+_References : 
+
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 11th May 2000
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXTk_DIALOG
+#define _PXTk_DIALOG
+
+#include "pxtkbase.h"
+#include "pxtkeventobj.h"
+#include "pxtkgadget.h"
+#include "pxtkframe.h"
+#include "pxtktoplevel.h"
+#include  <stdlib.h>
+
+// ****************************************
+// ******* PXTkDialog Class ************
+// ****************************************
+
+class PXTkDialog : public PXTkEventObj {
+  
+protected:
+  
+  PXBool          create_inside_parent,modality;
+  char*           dlg_title;
+
+  int             height,width;
+  
+public:
+
+  PXTkDialog(PXTkEventObj* par, const char* title,PXBool insideparent=PXFalse);
+  PXTkDialog(PXTkEventObj* par,PXTkGadget* w, const char* title,PXBool insideparent=PXFalse);
+  PXTkDialog(PXTkGadget*   par, const char* title,PXBool insideparent=PXFalse);
+  virtual ~PXTkDialog();
+
+  void init(const char* ttl,PXBool inside);
+  
+  virtual int  initDisplay();
+  virtual void setTitle(const char* title);
+
+  virtual void popupDialog();
+  virtual void popdownDialog();
+
+  virtual void exitCallback(const char* line=NULL);
+  virtual void aboutCallback(const char* line=NULL);
+
+  PXBool isOpen();
+  PXBool isInside();
+
+  virtual void setSize(int w,int h);
+  virtual void setModality(PXBool modal=PXTrue);
+
+  virtual int handleEvent(int eventno);
+
+  virtual   PXTkClassId    getClassId();
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkentry.cpp b/bioimagesuite30_src/pxtklib/pxtkentry.cpp
new file mode 100644
index 0000000..0c7b4bd
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkentry.cpp
@@ -0,0 +1,88 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkentry.cpp
+#include "pxtkentry.h"
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtkentry.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+ /* ********************************************************************
+
+    Definition of PXTkEntry Class 
+
+ ********************************************************************* */
+
+PXTkEntry::PXTkEntry(PXTkEventObj* evpar,PXTkGadget* gadg_par,PXBool dodisplay):PXTkLabel(evpar,gadg_par,NULL,PXFalse)
+{
+  if (dodisplay)
+      initDisplay();
+}
+
+PXTkEntry::~PXTkEntry()
+{
+  deleteWidgetVariable();
+}
+
+int PXTkEntry::initDisplay()
+{
+  sprintf(pxtk_buffer,"entry %s -textvariable widgetvar%d",widget_name,object_id);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+  return a;
+}
+
+int PXTkEntry::setText(const char* label)
+{
+  if (setWidgetVariable(label)!=NULL)
+      return TCL_OK;
+  else
+      return TCL_ERROR;
+	  
+}
+
+char* PXTkEntry::getText()
+{
+  return getWidgetVariable();
+}
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkentry.h b/bioimagesuite30_src/pxtklib/pxtkentry.h
new file mode 100644
index 0000000..83e2223
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkentry.h
@@ -0,0 +1,86 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkentry.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkEntry
+
+_Description : Definition of class PXTkEntry to warp Entry TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtklabel.h"
+
+#ifndef _PXTkEntry
+#define  _PXTkEntry
+
+
+/* ----  Definition of PXTkEntry ---- */
+class PXTkEntry : public PXTkLabel
+{
+public:
+  PXTkEntry(PXTkEventObj* evpar,PXTkGadget* gadg_par,PXBool dodisplay=PXTrue);
+  virtual ~PXTkEntry();
+
+  virtual int initDisplay();
+
+  virtual int   setText(const char* label);
+  virtual char* getText();
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkeventobj.cpp b/bioimagesuite30_src/pxtklib/pxtkeventobj.cpp
new file mode 100644
index 0000000..5a536b1
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkeventobj.cpp
@@ -0,0 +1,348 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtk.cc
+#include "pxtkeventobj.h"
+#include "pxtkgadget.h"
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtk.h for details
+
+// 	$Id: pxtkeventobj.cpp,v 1.1 2002/02/20 18:04:13 Xenios Exp $	
+
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+ /* ********************************************************************
+
+    Definition of PXTkEventObj Class 
+
+ ********************************************************************* */
+
+char   PXTkEventObj::pxtk_buffer[4000];
+char   PXTkEventObj::pxtk_buffer2[4000];
+
+// Do not use these variables; they are used for internal implementation
+// ---------------------------------------------------------------------
+char   PXTkEventObj::pxtk_intbuffer[4000];
+char   PXTkEventObj::pxtk_intbuffer2[4000];
+char   PXTkEventObj::pxtk_intbuffer3[4000];
+char   PXTkEventObj::pxtk_intbuffer4[4000];
+
+
+PXTkEventObj::PXTkEventObj(PXTkEventObj *p,PXTkGadget* gadg):PXTkBase(p,gadg)
+{
+ 
+  main_window=NULL;
+  //  PXTkApp::registerEventHandler(this);
+}
+
+PXTkEventObj::~PXTkEventObj() 
+{
+  if (main_window!=NULL)
+      delete main_window;
+}				
+
+
+PXBool PXTkEventObj::isGadget() 
+{ 
+return PXFalse;
+}
+
+PXTkClassId PXTkEventObj::getClassId()
+{
+  return PXTkObjId;
+}
+
+
+int PXTkEventObj::getHandlerNo()
+{
+  return long(this);
+  //return handler_no;
+}
+
+/*void PXTkEventObj::setHandlerNo(int h)
+{
+  handler_no=h;
+}*/
+
+PXTkGadget* PXTkEventObj::getMainWindow()
+{
+  return main_window;
+}
+
+int PXTkEventObj::handleEvent(int )
+{
+  return TCL_OK;
+}
+
+/* -------------------------------------------------------------------------*/
+//           Graphic Utility Code 
+/* -------------------------------------------------------------------------*/
+
+int PXTkEventObj::packMainWindow()
+{
+  sprintf(pxtk_intbuffer,"pack %s -fill both -expand true",main_window->getWidgetName());
+  return (PXTkApp::executeTclCommand(pxtk_intbuffer));
+}
+
+
+int PXTkEventObj::setWaitCursor(PXBool setwait)
+{
+  if (is_display_ok)
+      {
+	if (!setwait)
+	  sprintf(pxtk_intbuffer,"%s config -cursor \"\"",main_window->getWidgetName());
+	else
+	  sprintf(pxtk_intbuffer,"%s config -cursor watch",main_window->getWidgetName());
+	PXTkApp::executeTclCommand(pxtk_intbuffer);
+	return PXTkApp::executeTclCommand("update");
+      }
+  else
+      return TCL_ERROR;
+}
+
+int PXTkEventObj::messageBox(const char* message, const char *title, const char* mboxtype)
+{
+  strcpy(pxtk_intbuffer2,"ok");
+  if (mboxtype!=NULL)
+      strcpy(pxtk_intbuffer2,mboxtype);
+
+  strcpy(pxtk_intbuffer3,"For your information ...");
+  if (title!=NULL)
+      strcpy(pxtk_intbuffer3,title);
+
+  sprintf(pxtk_intbuffer,"tk_messageBox -title \"%s\" -type %s -message \"%s\" -parent %s",
+	  pxtk_intbuffer3,pxtk_intbuffer2,message,this->main_window->getWidgetName());
+  return PXTkApp::executeTclCommand(pxtk_intbuffer);
+}
+
+int PXTkEventObj::colorBox(const char* title,float& r,float& g,float& b)
+{
+  int c[3];
+  c[0]=int(Frange(r,0,1.0)*255.0);
+  c[1]=int(Frange(g,0,1.0)*255.0);
+  c[2]=int(Frange(b,0,1.0)*255.0);
+
+  strcpy(pxtk_buffer,"#");
+  for (int k=0;k<=2;k++)
+    {
+      for (int byte=0;byte<=1;byte++)
+	{
+	  int val=0;
+	  switch(byte)
+	    {
+	    case 0:
+	      val=c[k]/16;
+	      break;
+	    case 1:
+	      val=c[k]-16*int(c[k]/16);
+	      break;
+	    }
+	  
+	  if (val<10)
+	      {
+		sprintf(pxtk_buffer,"%s%1d",pxtk_buffer,val);
+	      }
+	  else
+	      {
+		switch (val)
+		    {
+		    case 10:
+		      strcat(pxtk_buffer,"A");
+		      break;
+		    case 11:
+		      strcat(pxtk_buffer,"B");
+		      break;
+		    case 12:
+		      strcat(pxtk_buffer,"C");
+		      break;
+		    case 13:
+		      strcat(pxtk_buffer,"D");
+		      break;
+		    case 14:
+		      strcat(pxtk_buffer,"E");
+		      break;
+		    case 15:
+		      strcat(pxtk_buffer,"F");
+		      break;
+		    }
+	      }
+	}
+    }
+
+  //  PXTkApp::printToConsole(pxtk_buffer);
+  sprintf(pxtk_buffer2,"tk_chooseColor -title \"%s\" -initialcolor %s -parent %s",
+	  title,pxtk_buffer,this->main_window->getWidgetName());
+  PXTkApp::executeTclCommand(pxtk_buffer2);
+  
+  char* line=PXTkApp::getTclStringResult();
+
+  if (line!=NULL)
+    {
+      if (strlen(line)>0)
+	{
+	  for (int i=0;i<=2;i++)
+	    {
+	      c[i]=0;
+	      for (int ib=0;ib<=1;ib++)
+		{
+		  int index=1+i*2+ib;
+		  int val=(int)line[index];
+		  if (val<65)
+		    val-=48;
+		  else if (val<70)
+		    val-=55;
+		  else 
+		    val-=87;
+		  
+		  if (ib==0)
+		    c[i]+=val*16;
+		  else
+		    c[i]+=val;
+		}
+	    }
+	  
+	  r=float(c[0])/255.0;
+	  g=float(c[1])/255.0;
+	  b=float(c[2])/255.0;
+	  /*sprintf(pxtk_buffer," --> %s ---> (%d,%d,%d) , (%f,%f,%f)\n",
+	    line,c[0],c[1],c[2],r,g,b);*/
+	  //PXTkApp::printToConsole(pxtk_buffer);
+	  return 1;
+	}
+    }
+  return 0;
+}
+
+int  PXTkEventObj::questionBox(const char* message)
+{
+  sprintf(pxtk_buffer,
+	  "tk_messageBox -type yesno -default no -title \"Think again ...\" -message \"%s\" -icon question -parent %s",
+	  message,this->main_window->getWidgetName());
+  PXTkApp::executeTclCommand(pxtk_buffer);
+  char* line=PXTkApp::getTclStringResult();
+
+  if (strncmp(line,"yes",3)==0)
+      return 1;
+  else
+      return 0;
+}
+
+char* PXTkEventObj::getOpenFilename(const char* title, const char *extname, const char* ext)
+{
+  if (extname!=NULL && ext!=NULL)
+    sprintf(pxtk_intbuffer2," {\"%s\" {\"%s\"}} {\"All Files\" {\"*\"}} ",extname,ext);
+  else 
+    sprintf(pxtk_intbuffer2," {\"All Files\" {\"*\"}} ");
+  
+  sprintf(pxtk_intbuffer,
+	  "tk_getOpenFile -title \"%s\" -filetypes { %s } -parent %s",
+	  title,pxtk_intbuffer2,this->main_window->getWidgetName());
+  PXTkApp::executeTclCommand(pxtk_intbuffer);
+  return PXTkApp::getTclStringResult();
+}
+
+char* PXTkEventObj::getOpenFilenameComplex(const char* title, const char* filetypes)
+{
+  sprintf(pxtk_intbuffer,
+	  "tk_getOpenFile -title \"%s\" -filetypes { %s } -parent %s",
+	  title,filetypes,this->main_window->getWidgetName());
+
+  PXTkApp::executeTclCommand(pxtk_intbuffer);
+  return PXTkApp::getTclStringResult();
+}
+
+char* PXTkEventObj::getSaveFilename(const char* title, const char* orig, const char* extname, const char* ext)
+{
+  if (extname!=NULL && ext!=NULL)
+    sprintf(pxtk_intbuffer2," {\"%s\" {\"%s\"}} {\"All Files\" {\"*\"}} ",extname,ext);
+  else 
+    sprintf(pxtk_intbuffer2," {\"All Files\" {\"*\"}} ");
+
+  if (orig!=NULL)
+    strcpy(pxtk_intbuffer3,orig);
+  else
+    strcpy(pxtk_intbuffer3,"");
+
+  sprintf(pxtk_intbuffer,"tk_getSaveFile -title \"%s\" -filetypes { %s } -initialfile \"%s\" -parent %s",
+	  title, pxtk_intbuffer2, pxtk_intbuffer3,this->main_window->getWidgetName());
+  PXTkApp::executeTclCommand(pxtk_intbuffer);
+  return PXTkApp::getTclStringResult();
+}
+
+
+char* PXTkEventObj::getSaveFilenameComplex(const char* title, const char* orig, const char* filetypes)
+{
+  sprintf(pxtk_intbuffer,"tk_getSaveFile -title \"%s\" -filetypes { %s } -initialfile \"%s\" -parent %s",
+	  title, filetypes, orig,this->main_window->getWidgetName());
+  PXTkApp::executeTclCommand(pxtk_intbuffer);
+  return PXTkApp::getTclStringResult();
+}
+
+/******************************************************************************/
+
+char* PXTkEventObj::chooseDirectory(const char* title)
+{
+   sprintf(pxtk_intbuffer,"tk_chooseDirectory -title \"%s\" -parent %s", 
+		   title, this->main_window->getWidgetName());
+   PXTkApp::executeTclCommand(pxtk_intbuffer);
+   return PXTkApp::getTclStringResult();
+}
+
+/******************************************************************************/
+
+int PXTkEventObj::handleMouseButtonEvent(int,int,int ,int,PXTkEventObj* )
+{
+  return 0;
+}
+
+/******************************************************************************/
+int PXTkEventObj::d_colorBox(const char* title,double& dr,double& dg,double& db)
+{
+  float r,b,g;
+  r=dr;
+  b=db;
+  g=dg;
+
+  int a=this->colorBox(title,r,g,b);
+  dr=r;
+  db=b;
+  dg=g;
+  return a;
+}
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkeventobj.h b/bioimagesuite30_src/pxtklib/pxtkeventobj.h
new file mode 100644
index 0000000..95e424a
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkeventobj.h
@@ -0,0 +1,120 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtkeventobj.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkEventObj
+
+_Description : Definition of PXTkEventObj -- base class for all classes that handle callbacks
+
+_Call :   
+        
+	
+_References : 
+              
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 11th May 2000
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXTkEventObj
+#define  _PXTkEventObj
+
+#include "pxtkbase.h"
+
+
+class PXTkEventObj : public PXTkBase
+{
+protected:	
+  // ***** Class Fields *******
+  //int                   handler_no;
+  PXTkGadget*           main_window;
+  static char           pxtk_buffer[4000], pxtk_buffer2[4000];
+
+private:
+  static char           pxtk_intbuffer[4000], pxtk_intbuffer2[4000],pxtk_intbuffer3[4000],pxtk_intbuffer4[4000];
+
+ public:
+  
+  // ****** Constructors & Destructor *****
+  PXTkEventObj(PXTkEventObj* parent,PXTkGadget* widget);
+
+  virtual              ~PXTkEventObj();	
+
+  // ****** Member Access *****    
+  virtual PXBool       isGadget();
+  virtual PXTkClassId   getClassId();
+
+  virtual int          getHandlerNo();
+  //virtual void         setHandlerNo(int h=0);
+  virtual PXTkGadget*  getMainWindow();
+
+
+  // ****** Callback related ******
+  virtual int           handleEvent(int eventno);
+  virtual int handleMouseButtonEvent(int nbutton,int state,int x,int y,PXTkEventObj* obj=NULL);
+
+  // ****** TCL Utility Code *****
+  virtual int   packMainWindow();
+  virtual int   setWaitCursor(PXBool setwait=PXTrue);
+
+  virtual int   messageBox(const char* message, const char* title=NULL, const char* mboxtype=NULL);
+  virtual int   questionBox(const char* message);
+  virtual int   colorBox(const char* title, float& r, float& g, float& b);
+  virtual int   d_colorBox(const char* title,double& dr,double& dg,double& db);  
+
+  virtual char* getOpenFilename(const char* title, const char* extname=NULL, const char *ext=NULL);
+  virtual char* getSaveFilename(const char* title, const char* orig=NULL, 
+		                const char* extname=NULL, const char* ext=NULL);
+
+  virtual char* getOpenFilenameComplex(const char* title, const char* filetypes);
+  virtual char* getSaveFilenameComplex(const char* title, const char* orig, const char* filetypes);
+
+  virtual char* chooseDirectory(const char* title);
+
+};
+
+
+#endif /*  _PXTkEventObj */
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkframe.cpp b/bioimagesuite30_src/pxtklib/pxtkframe.cpp
new file mode 100644
index 0000000..59f6eb7
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkframe.cpp
@@ -0,0 +1,256 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkgadgets.cc
+#include "pxtkframe.h"
+#include "pxtkeventobj.h"
+#include "pxtkdialog.h"
+#include <stdlib.h>
+#include <math.h>
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtkframe.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+ /* ********************************************************************
+
+    Definition of PXTkFrame Class 
+
+ ********************************************************************* */
+
+PXTkFrame::PXTkFrame(PXTkEventObj* evpar,PXTkGadget* gadg_par,int width,
+		     int height,PXBool dodisplay):PXTkGadget(evpar,gadg_par)
+{
+  //children=new PXTkBaseList;
+  pack_mode=PXTrue;
+  if (dodisplay)
+      {
+	initDisplay();
+	setDimensions(width,height);
+      }
+}
+
+PXTkFrame::PXTkFrame(PXTkEventObj* evpar,const char* name):PXTkGadget(evpar,name)
+{
+  pack_mode=PXTrue;
+  is_display_ok=PXTrue;
+}
+
+PXTkFrame::~PXTkFrame()
+{
+  //  delete children;
+}
+
+PXTkClassId PXTkFrame::getClassId()
+{
+  return PXTkFrameId;
+}
+
+
+int PXTkFrame::initDisplay()
+{
+  sprintf(pxtk_buffer,"frame %s",widget_name);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+  return a;
+}
+
+void PXTkFrame::setPackMode(PXBool pack)
+{
+  pack_mode=pack;
+}
+ 
+PXBool PXTkFrame::getPackMode()
+{
+  return pack_mode;
+}
+
+// Unmap Child
+
+int PXTkFrame::unmapChild(PXTkGadget* child)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  if (pack_mode)
+      sprintf(pxtk_buffer,"pack forget %s",child->getWidgetBaseName());
+  else
+      sprintf(pxtk_buffer,"grid forget %s",child->getWidgetBaseName());
+
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+  
+}
+
+int PXTkFrame::mapChild(PXTkGadget* child,const char* options)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  if (pack_mode)
+      sprintf(pxtk_buffer,"pack %s %s",child->getWidgetBaseName(),options);
+  else
+      sprintf(pxtk_buffer,"grid %s %s",child->getWidgetBaseName(),options);
+
+  
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+
+}
+
+
+  // UsefulOptions
+int PXTkFrame::setDimensions(int width,int height)
+{
+  int a=TCL_OK,b=TCL_OK;
+  if (width!=-1) 
+      a=configure("-width",width);
+  if (height!=-1) 
+      b=configure("-height",width);
+
+  if (a==TCL_OK && b==TCL_OK)
+      return TCL_OK;
+  else return TCL_ERROR;
+}
+
+int PXTkFrame::childConfigure(PXTkGadget* child,const char* option,const char* value)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  if (pack_mode)
+      sprintf(pxtk_buffer,"pack configure %s %s %s",child->getWidgetBaseName(),option,value);
+  else
+      sprintf(pxtk_buffer,"grid configure %s %s %s",child->getWidgetBaseName(),option,value);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+
+int PXTkFrame::gridRowColumnChild(PXTkGadget* child,int row,int column,int rowspan,int columnspan)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  sprintf(pxtk_buffer,"grid %s -column %d -row %d -columnspan %d -rowspan %d",child->getWidgetBaseName(),
+	  column,row,columnspan,rowspan);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int PXTkFrame::gridRowColumnConfigure(PXTkGadget* child,int row,int column,int rowspan,int columnspan)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+  
+  sprintf(pxtk_buffer,"grid configure %s -column %d -row %d -columnspan %d -rowspan %d",child->getWidgetBaseName(),
+	  column,row,columnspan,rowspan);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+
+int PXTkFrame::gridExpandRowConfigure(int row,int weight,int minsize,int pad)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+  
+  sprintf(pxtk_buffer,"grid rowconfigure %s %d -weight %d",widget_name,row,weight);
+  if (minsize!=-1)
+    sprintf(pxtk_buffer,"%s -minsize %d",pxtk_buffer,minsize);
+  if (pad!=-1)
+        sprintf(pxtk_buffer,"%s -pad %d",pxtk_buffer,pad);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int PXTkFrame::gridExpandColumnConfigure(int row,int weight,int minsize,int pad)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+  
+  sprintf(pxtk_buffer,"grid columnconfigure %s %d -weight %d",widget_name,row,weight);
+  if (minsize!=-1)
+    sprintf(pxtk_buffer,"%s -minsize %d",pxtk_buffer,minsize);
+  if (pad!=-1)
+        sprintf(pxtk_buffer,"%s -pad %d",pxtk_buffer,pad);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int PXTkFrame::addChildren(const char* options,PXTkGadget* child1,
+			    PXTkGadget* child2,PXTkGadget* child3,PXTkGadget* child4,PXTkGadget* child5)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  if (pack_mode)
+      sprintf(pxtk_buffer,"pack");
+  else
+      sprintf(pxtk_buffer,"grid");
+
+
+  sprintf(pxtk_buffer,"%s %s",pxtk_buffer,child1->getWidgetBaseName());
+  // children->add(child1);
+
+  if (child2!=NULL)
+      {
+	sprintf(pxtk_buffer,"%s %s",pxtk_buffer,child2->getWidgetBaseName());
+	// children->add(child2);
+      }
+  if (child3!=NULL)
+      {
+	sprintf(pxtk_buffer,"%s %s",pxtk_buffer,child3->getWidgetBaseName());
+	// children->add(child3);
+      }
+  if (child4!=NULL)
+      {
+	sprintf(pxtk_buffer,"%s %s",pxtk_buffer,child4->getWidgetBaseName());  
+	// children->add(child4);
+      }
+
+  if (child5!=NULL)
+      {
+	sprintf(pxtk_buffer,"%s %s",pxtk_buffer,child5->getWidgetBaseName());
+	// children->add(child5);
+      }
+  
+  sprintf(pxtk_buffer,"%s %s",pxtk_buffer,options);
+
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+
+}
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkframe.h b/bioimagesuite30_src/pxtklib/pxtkframe.h
new file mode 100644
index 0000000..4039271
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkframe.h
@@ -0,0 +1,115 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkframe.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkFrame
+
+_Description : Definition of class PXTkFrame to warp Frame TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtkgadget.h"
+
+#ifndef _PXTkFrame
+#define  _PXTkFrame
+
+/* ----  Definition of PXTkFrame Class  ---- */
+
+class PXTkFrame : public PXTkGadget
+{
+protected:
+  PXBool pack_mode;
+
+public:
+
+  PXTkFrame(PXTkEventObj* evpar,PXTkGadget* gadg_par,int width=-1,int height=-1,PXBool dodisplay=PXTrue);
+  PXTkFrame(PXTkEventObj* evpar,const char* name);
+
+  virtual ~PXTkFrame();
+
+  virtual int initDisplay();
+  virtual PXTkClassId   getClassId();
+
+  // Addition of Children 
+  virtual int addChildren(const char* options,PXTkGadget* child1,
+			  PXTkGadget* child2=NULL,PXTkGadget* child3=NULL,PXTkGadget* child4=NULL,PXTkGadget* child5=NULL);
+  virtual int childConfigure(PXTkGadget* child,const char* option,const char* value);
+
+
+  // Special Grid Options
+  virtual int gridRowColumnChild(PXTkGadget* child,int row,int column,int rowspan=1,int columnspan=1);
+  virtual int gridRowColumnConfigure(PXTkGadget* child,int row,int column,int rowspan=1,int columnspan=1);
+  virtual int gridExpandRowConfigure(int row,int weight=1,int minsize=-1,int pad=-1);
+  virtual int gridExpandColumnConfigure(int row,int weight=1,int minsize=-1,int pad=-1);
+
+  
+  // Unmap Child
+  virtual int   unmapChild(PXTkGadget* child);
+  virtual int   mapChild(PXTkGadget* child,const char* options);
+
+  // PackMode=PXTrue --> packer else grid
+  virtual void   setPackMode(PXBool pack);
+  virtual PXBool getPackMode();
+
+  // UsefulOptions
+  virtual int setDimensions(int width=-1,int height=-1);
+      
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkgadget.cpp b/bioimagesuite30_src/pxtklib/pxtkgadget.cpp
new file mode 100644
index 0000000..885a87b
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkgadget.cpp
@@ -0,0 +1,243 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtkgadgets.cc
+#include "pxtkgadgets.h"
+#include "pxtkeventobj.h"
+#include "pxtkdialog.h"
+#include <stdlib.h>
+#include <math.h>
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtk.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+ /* ********************************************************************
+
+    Definition of PXTkGadget Class 
+
+ ********************************************************************* */
+
+char PXTkGadget::pxtk_buffer[4000];
+char PXTkGadget::pxtk_buffer2[4000];
+
+
+// Do not use these variables; they are used for internal implementation
+// ---------------------------------------------------------------------
+char   PXTkGadget::pxtk_intbuffer[4000];
+
+PXTkGadget::PXTkGadget(PXTkEventObj* evpar,PXTkGadget* gadg_par):PXTkBase(evpar,gadg_par)
+{
+  if (!has_gadget_parent)
+      {
+	widget_name=new char[10];
+	sprintf(widget_name,".w%d",object_id);
+      }
+  else
+      {
+	widget_name=new char[strlen(gadget_parent->getWidgetName())+10];
+	if (strcmp(gadget_parent->getWidgetName(),".")==0)
+	    sprintf(widget_name,".w%d",object_id);
+	else
+	    sprintf(widget_name,"%s.w%d",gadget_parent->getWidgetName(),object_id);
+      }
+
+  widget_base_name=new char[strlen(widget_name)+1];
+  strcpy(widget_base_name,widget_name);
+}
+
+PXTkGadget::PXTkGadget(PXTkEventObj* evpar, const char* name):PXTkBase(evpar)
+{
+  widget_name=new char[strlen(name)+1];
+  strcpy(widget_name,name);
+  widget_base_name=new char[strlen(name)+1];
+  strcpy(widget_base_name,name);
+  is_display_ok=PXTrue;
+}
+
+PXTkGadget::~PXTkGadget()
+{
+  delete [] widget_name;
+  delete [] widget_base_name;
+}
+
+int PXTkGadget::wmconfigure(const char* option,const char* value,PXBool noquote)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+  
+  if (!noquote)
+      sprintf(pxtk_intbuffer,"wm %s %s \"%s\"",option,widget_name,value);
+  else
+      sprintf(pxtk_intbuffer,"wm %s %s %s",option,widget_name,value);
+
+  if (hasEventParent())
+      return PXTkApp::executeTclCommand(pxtk_intbuffer);
+  else
+      return TCL_ERROR;
+
+}
+
+int PXTkGadget::configure(const char* option,const char* value)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  sprintf(pxtk_intbuffer,"%s configure %s %s",widget_name,option,value);
+  if (hasEventParent())
+      return PXTkApp::executeTclCommand(pxtk_intbuffer);
+  else
+      return TCL_ERROR;
+}
+
+
+int PXTkGadget::configurequote(const char* option,const char* value)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  sprintf(pxtk_intbuffer,"%s configure %s \"%s\"",widget_name,option,value);
+
+  if (hasEventParent())
+      return PXTkApp::executeTclCommand(pxtk_intbuffer);
+  else
+      return TCL_ERROR;
+}
+
+int PXTkGadget::configure(const char* option,int value)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  sprintf(pxtk_intbuffer,"%s configure %s %d",widget_name,option,value);
+  if (hasEventParent())
+      return PXTkApp::executeTclCommand(pxtk_intbuffer);
+  else
+      return TCL_ERROR;
+}
+
+int PXTkGadget::configure(const char* option,float value)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  sprintf(pxtk_intbuffer,"%s configure %s %f",widget_name,option,value);
+  if (hasEventParent())
+      return PXTkApp::executeTclCommand(pxtk_intbuffer);
+  else
+      return TCL_ERROR;
+}
+
+
+
+char* PXTkGadget::cget(const char* option)
+{
+  if (!is_display_ok)
+      return NULL;
+
+  sprintf(pxtk_intbuffer,"%s cget %s ",widget_name,option);
+  if (PXTkApp::executeTclCommand(pxtk_intbuffer)==TCL_OK)
+      return PXTkApp::getTclStringResult();
+  else
+      return NULL;
+
+}
+
+char* PXTkGadget::setWidgetVariable(const char* value)
+{
+  sprintf(pxtk_intbuffer,"widgetvar%d",object_id);
+  char *line=PXTkApp::setTclVariable(pxtk_intbuffer,value);
+  if (PXTkApp::debug_tcl)
+      {
+	sprintf(pxtk_intbuffer,"%s=%s (orig=%s)\n",pxtk_intbuffer,line,value);
+	PXTkApp::printToConsole(pxtk_intbuffer);
+      }
+  return line;
+}
+
+
+char* PXTkGadget::getWidgetVariable()
+{
+  sprintf(pxtk_intbuffer,"widgetvar%d",object_id);
+  char* line=PXTkApp::getTclVariable(pxtk_intbuffer);
+  if (PXTkApp::debug_tcl)
+    {
+      sprintf(pxtk_intbuffer,"%s=%s\n",pxtk_intbuffer,line);
+      PXTkApp::printToConsole(pxtk_intbuffer);
+    }
+  return line;
+}
+
+
+int PXTkGadget::deleteWidgetVariable()
+{
+  sprintf(pxtk_intbuffer,"widgetvar%d",object_id);
+  return PXTkApp::deleteTclVariable(pxtk_intbuffer);
+}
+
+char* PXTkGadget::getWidgetBaseName()
+{
+  return widget_base_name;
+}
+
+
+char* PXTkGadget::getWidgetName()
+{
+  return widget_name;
+}
+
+PXTkClassId PXTkGadget::getClassId()
+{
+  return PXTkGadgetId;
+}
+
+int PXTkGadget::bindCallback(const char* event,int callno)
+{
+  sprintf(pxtk_buffer,"bind %s %s {pxtkcallback %d %d}",widget_name,event,
+	  event_parent->getHandlerNo(),callno);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int  PXTkGadget::enable(PXBool enab)
+{
+  if (enab)
+      return configure("-state","normal");
+  else
+      return configure("-state","disabled");
+}
+
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkgadget.h b/bioimagesuite30_src/pxtklib/pxtkgadget.h
new file mode 100644
index 0000000..1abdd72
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkgadget.h
@@ -0,0 +1,109 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtkgadgets.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkGadgets
+
+_Description : Definition of abstract class PXTkGadget
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 11th May 2000
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtkbase.h"
+#include "pxtkapp.h"
+
+class PXTkEventObj;
+
+#ifndef _PXTkGadget
+#define  _PXTkGadget
+
+/* ----  Definition of PXTkGadget Class  ---- */
+
+class PXTkGadget : public PXTkBase 
+{
+protected:
+  char*                 widget_name,*widget_base_name;
+  static                char pxtk_buffer[4000],pxtk_buffer2[4000];
+
+private:
+  static                char pxtk_intbuffer[4000];
+  
+public:
+  PXTkGadget(PXTkEventObj* evpar,PXTkGadget* gadg_par);
+  PXTkGadget(PXTkEventObj* evpar,const char* name);
+
+  virtual ~PXTkGadget();
+
+  virtual int           wmconfigure(const char* option,const char* value,PXBool noquote=PXTrue);
+
+  virtual int           configure(const char* option,const char* value);
+  virtual int           configurequote(const char* option, const char* value);
+  virtual int           configure(const char* option,int   value);
+  virtual int           configure(const char* option,float value);
+  virtual char*         cget(const char* option);
+
+  virtual char*         setWidgetVariable(const char* value);
+  virtual char*         getWidgetVariable();
+  virtual int           deleteWidgetVariable();
+
+  virtual char*         getWidgetName();
+  virtual char*         getWidgetBaseName();
+
+  virtual PXTkClassId   getClassId();
+  virtual int           bindCallback(const char* event,int callno);
+
+  virtual int           enable(PXBool enab=PXTrue);
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkgadgets.h b/bioimagesuite30_src/pxtklib/pxtkgadgets.h
new file mode 100644
index 0000000..eb7db23
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkgadgets.h
@@ -0,0 +1,121 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtkgadgets.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkGadgets
+
+_Description : Definition of abstract class PXTkGadget
+               and derived classes to wrap 15 original TK Widgets 
+
+PXTkGadget -+-> PXTkFrame (1)  ---> PXTkToplevel (2)   (done)
+	    |                
+	    |
+	    +-> PXTkLabel (3)  -+-> PXTkButton (4)  -+-> PXTkMenuButton  (5)        (done)
+            |     	        |                    |                                                
+            |                   |                    +-> PXTkCheckButton (6) ---> PXTkRadioButton  (7)  (done)
+            |     	        |                   	                                                  
+            |	                |                   	                           
+            |        	        |                   
+	    |                   |                   
+	    |                   |
+	    |                   +-> PXTkMessage (8)   (done 
+	    |                   |
+	    |                   +-> PXTkEntry (9)     (done)
+	    |                   |                                
+	    |                   +-> PXTkText (10)     (done)
+	    |                                  
+	    |                                  
+            |
+	    +-> PXTkScale (11)  (done)
+	    |
+	    +-> PXTkListBox (12) (done)
+	    |
+	    +-> PXTkScrollBar (13) (done)
+	    |
+	    +-> PXTkMenu (14) (done)  (Also PXTkOptionMenu (14a))
+	    |
+	    +-> PXTkCanvas (15)
+
+	    Not all implemented yet 
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 11th May 2000
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtkbase.h"
+#include "pxtkapp.h"
+
+class PXTkEventObj;
+
+#ifndef _PXTkGadgets
+#define  _PXTkGadgets
+
+
+#include "pxtkgadget.h"
+#include "pxtkframe.h"
+#include "pxtktoplevel.h"
+#include "pxtklabel.h"
+#include "pxtkmessage.h"
+#include "pxtkbutton.h"
+#include "pxtkmenubutton.h"
+#include "pxtkcheckbutton.h"
+#include "pxtkradiobutton.h"
+#include "pxtkentry.h"
+#include "pxtktext.h"
+#include "pxtkscale.h"
+#include "pxtkscrollbar.h"
+#include "pxtklistbox.h"
+#include "pxtkmenu.h"
+#include "pxtkoptionmenu.h"
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkinfodialog.cpp b/bioimagesuite30_src/pxtklib/pxtkinfodialog.cpp
new file mode 100644
index 0000000..9a741d4
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkinfodialog.cpp
@@ -0,0 +1,141 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "pxtkinfodialog.h"
+#include "pxtkgadgets.h"
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+
+   see pxtkinfodialog.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+/* -------------------------------------------------------------------------*/
+/*                   PXTkInfoDialog                                          */
+/* -------------------------------------------------------------------------*/
+
+/* -------------------------------------------------------------------------*/
+PXTkInfoDialog::PXTkInfoDialog(const char* title,int x,int y):PXTkDialog((PXTkGadget*)NULL,title)
+{
+  height=y;   width=x; 
+}
+/* -------------------------------------------------------------------------*/
+int PXTkInfoDialog::initDisplay()
+{
+  create_inside_parent=PXFalse;
+  PXTkToplevel *dlg=new PXTkToplevel(this,gadget_parent,dlg_title,width,height);
+  main_window=dlg;
+  dlg->hide();
+  modality=PXFalse;  
+  is_display_ok=PXTrue;
+   
+  PXTkFrame* manager=(PXTkFrame*)(main_window);
+
+  PXTkFrame* top_frame=new PXTkFrame(this,manager,width,height-70);
+  PXTkFrame* bottom_frame=new PXTkFrame(this,manager,width,70);
+
+  manager->addChildren("-side bottom -expand false -fill x  -pady 2",bottom_frame);
+  manager->addChildren("-side top -expand true -fill both",top_frame);
+
+  PXTkScrollbar* ybar=new PXTkScrollbar(this,top_frame,PXTrue);
+  PXTkScrollbar* xbar=new PXTkScrollbar(this,manager,PXFalse);
+  manager->addChildren("-side bottom -expand false -fill x",xbar);
+  
+  text_box=new PXTkText(this,top_frame);
+  ybar->attachGadget(text_box);
+  xbar->attachGadget(text_box);
+
+  text_box->configure("-width",150);
+  text_box->configure("-height",15);
+  //  text_box->configurequote("-font","{times 10}");
+  text_box->configure("-wrap","none");
+  text_box->configure("-relief","ridge");
+  text_box->setEditableState(PXFalse);
+
+
+  top_frame->addChildren("-side right -expand false -fill y",ybar);
+  top_frame->addChildren("-side left -expand true -fill both",text_box);
+
+  //  bottom_frame->addChildren("-side left -expand true -fill y",ybar);
+
+  PXTkButton *close_button=new PXTkButton(this,bottom_frame,"Close",3); 
+  PXTkButton *clear_button=new PXTkButton(this,bottom_frame,"Clear",101); 
+  PXTkCheckButton *edit_button=new PXTkCheckButton(this,bottom_frame,"Edit",102); 
+  edit_button->setState(PXFalse);
+
+  bottom_frame->addChildren("-side left -fill x -padx 10",close_button,clear_button,edit_button);
+  
+  addText("PXTk Console\n--------------------\n");
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+int PXTkInfoDialog::addText(const char *line)
+{
+  if (is_display_ok)
+      return text_box->addText(line);
+  else
+      return 0;
+}
+// -------------------------------------------------------------------------
+int PXTkInfoDialog::clearText()
+{
+  if (is_display_ok)
+      return text_box->clearText();
+  else
+      return 0;
+}
+// -------------------------------------------------------------------------
+int PXTkInfoDialog::handleEvent(int event)
+{
+  if (event==3)
+      {
+	this->popdownDialog();
+      }
+  if (event==101)
+      {
+	this->clearText();
+      }
+  if (event==102)
+      {
+	PXTkCheckButton* bt=(PXTkCheckButton*)PXTkApp::getIntArgument(0);
+	if (bt!=NULL)
+	    text_box->setEditableState(bt->getState());
+      }
+  return TCL_OK;
+}
+
+PXTkText* PXTkInfoDialog::GetTextBox()
+{
+  return text_box;
+}
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkinfodialog.h b/bioimagesuite30_src/pxtklib/pxtkinfodialog.h
new file mode 100644
index 0000000..2a66423
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkinfodialog.h
@@ -0,0 +1,93 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtkinfodialog.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkInfoDialog
+
+
+_Description : This is a dialog class to display info information to user
+
+_Call : 
+  PXTkInfoDialog(PXTkEventObj* par,char* title,int x=200,int y=200);
+  
+_References : 
+
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 21st March 1997
+                                
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXDRAW_INFO_DIALOG
+#define _PXDRAW_INFO_DIALOG
+
+#include "pxtkdialog.h"
+#include "pxtktext.h"
+
+// ****************************************
+// ******* PXTkInfoDialog Class ************
+// ****************************************
+
+class PXTkInfoDialog : public PXTkDialog {
+  
+protected:
+
+  PXTkText* text_box;
+  
+public:
+  
+  PXTkInfoDialog(const char* title,int x=200,int y=100);
+  
+  virtual int initDisplay();
+
+  virtual int addText(const char *text);  
+  virtual int clearText();
+  virtual int handleEvent(int eventno);
+  virtual PXTkText* GetTextBox();
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtklabel.cpp b/bioimagesuite30_src/pxtklib/pxtklabel.cpp
new file mode 100644
index 0000000..73a6d39
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtklabel.cpp
@@ -0,0 +1,103 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtkgadgets.cc
+#include "pxtklabel.h"
+#include <stdlib.h>
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtklabel.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+
+ /* ********************************************************************
+
+    Definition of PXTkLabel Class 
+
+ ********************************************************************* */
+
+PXTkLabel::PXTkLabel(PXTkEventObj* evpar,PXTkGadget* gadg_par, 
+           const char* label,PXBool dodisplay):PXTkGadget(evpar,gadg_par)
+{
+  if (dodisplay)
+      {
+	initDisplay();
+	setText(label);
+      }
+
+}
+
+int PXTkLabel::setText(const char* label)
+{
+  return configurequote("-text",label);
+}
+
+int PXTkLabel::initDisplay()
+{
+  sprintf(pxtk_buffer,"label %s",widget_name);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+  return a;
+}
+
+int PXTkLabel::setWidthHeight(int w,int h)
+{
+  int a=TCL_OK;
+  if (w>0)
+      a=configure("-width",w);
+  if (h>0 && a==TCL_OK)
+      a=configure("-height",w);
+  return a;
+}
+
+int PXTkLabel::setPadding(int bd,int padx,int pady)
+{
+  int a=TCL_OK;
+  if (bd>=0)
+      a=configure("-borderwidth",bd);
+  if (padx>=0 && a==TCL_OK)
+      a=configure("-padx",padx);
+  if (pady>=0 && a==TCL_OK)
+      a=configure("-pady",pady);
+  return a;
+}
+
+char *PXTkLabel::getText()
+{
+	  return cget("-text");
+}
+
diff --git a/bioimagesuite30_src/pxtklib/pxtklabel.h b/bioimagesuite30_src/pxtklib/pxtklabel.h
new file mode 100644
index 0000000..c5a5f69
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtklabel.h
@@ -0,0 +1,83 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtklabel.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkLabel
+
+_Description : Definition of class PXTkLabel to warp Label TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtkgadget.h"
+
+#ifndef _PXTkLabel
+#define  _PXTkLabel
+
+
+/* ----  Definition of PXTkLabel Class  ---- */
+
+class PXTkLabel : public PXTkGadget
+{
+public:
+  PXTkLabel(PXTkEventObj* evpar,PXTkGadget* gadg_par, const char* label,PXBool dodisplay=PXTrue);
+  virtual char *getText();
+  virtual int setText(const char* label);
+  virtual int initDisplay();
+  virtual int setWidthHeight(int w=-1,int h=-1);
+  virtual int setPadding(int bd=-1,int padx=-1,int pady=-1);
+
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtklistbox.cpp b/bioimagesuite30_src/pxtklib/pxtklistbox.cpp
new file mode 100644
index 0000000..fee05f3
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtklistbox.cpp
@@ -0,0 +1,160 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtklistbox.cpp
+#include "pxtklistbox.h"
+#include "pxtkeventobj.h"
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtklistbox.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+/* ********************************************************************
+   
+   Definition of PXTkListBox Class 
+   
+   ********************************************************************* */
+PXTkListBox::PXTkListBox(PXTkEventObj* evpar,PXTkGadget* gadg_par,int moption,
+		   PXBool dodisplay):PXTkGadget(evpar,gadg_par)
+{
+  if (dodisplay)
+      {
+	call_no=moption;
+	initDisplay();
+      }
+}
+  
+int PXTkListBox::addItem(const char* item,int index)
+{
+  if (index==-1)
+      sprintf(pxtk_buffer,"%s insert end \"%s\" ",widget_name,item);
+  else
+      sprintf(pxtk_buffer,"%s insert %d \"%s\" ",widget_name,index,item);
+
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int PXTkListBox::clearList()
+{
+  sprintf(pxtk_buffer,"%s delete 0 end ",widget_name);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int PXTkListBox::clearItem(int index)
+{
+  sprintf(pxtk_buffer,"%s delete %d",widget_name,index);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int PXTkListBox::selectItem(int index)
+{
+  int a=getCurrentItem();
+
+  if (a!=-1)
+      {
+	sprintf(pxtk_buffer,"%s selection clear %d %d",widget_name,a,a);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+      }
+  if (index!=-1)
+      {
+	//sprintf(pxtk_buffer,"%s selection set %d %d",widget_name,a,index);
+	sprintf(pxtk_buffer,"%s selection set %d %d",widget_name,index,index);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+	//sprintf(pxtk_buffer,"%s selection set %d %d",widget_name,index,index);
+	//sprintf(pxtk_buffer,"%s see %d",widget_name,index);
+	//PXTkApp::executeTclCommand(pxtk_buffer);
+      }
+
+  return TCL_OK;
+}
+
+int PXTkListBox::getNumItems()
+{
+  sprintf(pxtk_buffer,"%s index end",widget_name);
+  if (PXTkApp::executeTclCommand(pxtk_buffer)==TCL_OK)
+      return PXTkApp::getTclIntResult();
+  else
+      return 0;
+}
+
+int PXTkListBox::getCurrentItem()
+{
+  sprintf(pxtk_buffer,"%s curselection",widget_name);
+  if (PXTkApp::executeTclCommand(pxtk_buffer)==TCL_OK)
+      {
+	char* line=PXTkApp::getTclStringResult();
+	if (strlen(line)==0)
+	    return -1;
+	else
+	    return PXTkApp::getTclIntResult();
+      }
+  else
+      return -1;
+}
+
+char* PXTkListBox::getItem(int index)
+{
+  sprintf(pxtk_buffer,"%s get %d %d",widget_name,index,index);
+  if (PXTkApp::executeTclCommand(pxtk_buffer)==TCL_OK)
+      return PXTkApp::getTclStringResult();
+  else
+      return 0;
+}
+
+int PXTkListBox::initDisplay()
+{
+  sprintf(pxtk_buffer,"listbox %s -exportselection 0",widget_name);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  configure("-selectMode","single");
+  //configure("-exportselection","0");
+  configure("-width",15);
+
+  if (call_no>0)
+      {
+        sprintf(pxtk_buffer,"bind %s <ButtonRelease-1> { pxtkcallback %d %d %ld }",
+                widget_name,event_parent->getHandlerNo(),call_no,(long)this);
+        a=PXTkApp::executeTclCommand(pxtk_buffer);
+      }
+
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+
+  return a;
+
+}
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtklistbox.h b/bioimagesuite30_src/pxtklib/pxtklistbox.h
new file mode 100644
index 0000000..86d27e9
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtklistbox.h
@@ -0,0 +1,95 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtklistbox.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkListbox
+
+_Description : Definition of class PXTkListbox to warp Listbox TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtkgadget.h"
+
+#ifndef _PXTkListbox
+#define  _PXTkListbox
+
+
+/* ---- Definition of PXTkListBox Class  ---- */
+  
+class PXTkListBox : public PXTkGadget
+{
+protected:
+  int call_no;
+
+public:
+  PXTkListBox(PXTkEventObj* evpar,PXTkGadget* gadg_par,int moption=-1,PXBool dodisplay=PXTrue);
+  
+  virtual char* getItem(int index);
+  virtual int   getNumItems();
+  virtual int   getCurrentItem();
+
+  virtual int   clearList();
+  virtual int   selectItem(int index);
+  virtual int   clearItem(int index);
+  virtual int   addItem(const char* item,int index=-1);
+  
+  virtual int initDisplay();
+};
+
+
+
+
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkmenu.cpp b/bioimagesuite30_src/pxtklib/pxtkmenu.cpp
new file mode 100644
index 0000000..59e3d8e
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkmenu.cpp
@@ -0,0 +1,169 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+#include "pxtkmenu.h"
+#include "pxtkeventobj.h"
+#include <stdlib.h>
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+
+   see pxtkmenu.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+
+/* ********************************************************************
+   
+   Definition of PXTkMenu Class 
+   
+   ********************************************************************* */
+
+PXTkMenu::PXTkMenu(PXTkEventObj* evpar,PXTkMenuButton* gadg_par,PXBool tearoff,
+		   PXBool cascade):PXTkGadget(evpar,gadg_par)
+{
+  tear_off=tearoff;
+
+  if (cascade)
+      {
+	tear_off=PXFalse;
+      }
+  else // Not a cascade menu i.e. parent is a menubutton directly 
+      {
+	delete widget_name;
+	delete widget_base_name;
+	widget_name=new char[strlen(gadg_par->getWidgetName())+10];
+	widget_base_name=new char[strlen(gadg_par->getWidgetName())+10];
+	sprintf(widget_name,"%s.menu",gadg_par->getWidgetName());
+	sprintf(widget_base_name,"%s.menu",gadg_par->getWidgetName());
+      }
+
+  initDisplay();
+}
+
+int PXTkMenu::addSeparator()
+{
+  sprintf(pxtk_buffer,"%s add separator",widget_name);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int PXTkMenu::addCascade(const char* label,PXTkMenu* cascade)
+{
+  sprintf(pxtk_buffer,"%s add cascade -label \"%s\" -menu %s",widget_name,label,
+	  cascade->getWidgetName());
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+  
+  
+int  PXTkMenu::addButton(const char* label,int callno)
+{
+  sprintf(pxtk_buffer,"%s add command -label \"%s\" -command {pxtkcallback %d %d %ld}",widget_name,label,
+	  event_parent->getHandlerNo(),callno,(long)this);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int  PXTkMenu::addCheckBox(const char* label,int variable,PXBool state,int callno)
+{
+  sprintf(pxtk_buffer,"%s add check -label \"%s\" -variable widgetvar%d_%d -command {pxtkcallback %d %d %ld}",
+	  widget_name,label,
+	  object_id,variable,
+	  event_parent->getHandlerNo(),callno,(long)this);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  if (state)
+      setMenuWidgetVariable(variable,1);
+  return a;
+} 
+
+int PXTkMenu::addRadioButton(const char* label,int variable,int value,PXBool state,int callno)
+{
+  sprintf(pxtk_buffer,"%s add radio -label \"%s\" -variable widgetvar%d_%d -value %d -command {pxtkcallback %d %d %ld}",
+	  widget_name,label,
+	  object_id,variable,value,
+	  event_parent->getHandlerNo(),callno,(long)this);
+  //  fprintf(stderr,"%s\n",pxtk_buffer);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  
+  if (state)
+      setMenuWidgetVariable(variable,value);
+  return a;
+}
+
+int PXTkMenu::setMenuWidgetVariable(int var,int val)
+{
+  sprintf(pxtk_buffer,"widgetvar%d_%d",object_id,var);
+  char value[50];
+  sprintf(value,"%d",val);
+  //  fprintf(stderr,"**** Setting %s -> %s\n",pxtk_buffer,value);
+  char *line=PXTkApp::setTclVariable(pxtk_buffer,value);
+  if (PXTkApp::debug_tcl)
+    {
+      sprintf(pxtk_buffer,"%s=%s (orig=%s)\n",pxtk_buffer,line,value);
+      PXTkApp::printToConsole(pxtk_buffer);
+    }
+  return atoi(line);
+}
+
+int PXTkMenu::getMenuWidgetVariable(int var)
+{
+  sprintf(pxtk_buffer,"widgetvar%d_%d",object_id,var);
+  //  fprintf(stderr,"getting %s\n",pxtk_buffer);
+  char* line=PXTkApp::getTclVariable(pxtk_buffer);
+  if (PXTkApp::debug_tcl)
+    {
+      sprintf(pxtk_buffer,"%s=%s\n",pxtk_buffer,line);
+      PXTkApp::printToConsole(pxtk_buffer);
+    }
+  return atoi(line);
+}
+
+int PXTkMenu::initDisplay()
+{
+  Tk_MapWindow(PXTkApp::getWidgetPointer(gadget_parent->getWidgetName()));
+  
+  if (tear_off)
+      sprintf(pxtk_buffer,"menu %s -tearoff 1",widget_name);
+  else
+      sprintf(pxtk_buffer,"menu %s -tearoff 0",widget_name);
+
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+  return a;
+}
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkmenu.h b/bioimagesuite30_src/pxtklib/pxtkmenu.h
new file mode 100644
index 0000000..047bf08
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkmenu.h
@@ -0,0 +1,100 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkmenu.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkMenu
+
+
+_Description : 
+
+_Call : (examples)
+  
+_References : 
+
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 10th August 2000
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXTkMenu
+#define _PXTkMenu
+
+#include "pxtkgadget.h"
+#include "pxtkmenubutton.h"
+
+
+/* ---- Definition of PXTkMenu Class  ---- */
+  
+class PXTkMenu : public PXTkGadget
+{
+protected:
+  PXBool tear_off;
+
+public:
+  PXTkMenu(PXTkEventObj* evpar,PXTkMenuButton* gadg_par,
+	   PXBool tearoff=PXFalse,PXBool cascade=PXFalse);
+
+  virtual int   addSeparator();  
+  virtual int   addCascade(const char* label,PXTkMenu* cascade);
+  virtual int   addButton(const char* label,int callno);
+  virtual int   addCheckBox(const char* label,int variableindex,PXBool state,int callno);
+  virtual int   addRadioButton(const char* label,int variableindex,int value,PXBool state,int callno);
+
+  virtual int setMenuWidgetVariable(int var,int value);
+  virtual int getMenuWidgetVariable(int var);
+  
+  virtual int initDisplay();
+};
+
+
+#endif   
+
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkmenubutton.cpp b/bioimagesuite30_src/pxtklib/pxtkmenubutton.cpp
new file mode 100644
index 0000000..04d53e2
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkmenubutton.cpp
@@ -0,0 +1,77 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkmenubutton.cpp
+#include "pxtkmenubutton.h"
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtkmenubutton.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+
+ /* ********************************************************************
+
+    Definition of PXTkMenuButton Class 
+
+ ********************************************************************* */
+
+PXTkMenuButton::PXTkMenuButton(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* name,
+			       int callno,PXBool dodisplay):PXTkButton(evpar,gadg_par,NULL,-1,PXFalse)
+{
+  if (dodisplay)
+      {
+	initDisplay();
+	setText(name);
+	setCallback(callno);
+      }
+}
+
+
+int PXTkMenuButton::initDisplay()
+{
+  sprintf(pxtk_buffer,"menubutton %s -menu %s.menu",widget_name,widget_name);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+    return a;
+}
+
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkmenubutton.h b/bioimagesuite30_src/pxtklib/pxtkmenubutton.h
new file mode 100644
index 0000000..0f6f02c
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkmenubutton.h
@@ -0,0 +1,84 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkmenubutton.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkMenuButton
+
+_Description : Definition of class PXTkMenuButton to warp MenuButton TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtkbutton.h"
+
+#ifndef _PXTkMenuButton
+#define  _PXTkMenuButton
+
+
+/* ----  Definition of PXTkMenuButton ---- */
+
+class PXTkMenuButton : public PXTkButton
+{
+public:
+  PXTkMenuButton(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* name,
+		 int callno=-1,PXBool dodisplay=PXTrue);
+  
+  virtual int initDisplay();
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkmessage.cpp b/bioimagesuite30_src/pxtklib/pxtkmessage.cpp
new file mode 100644
index 0000000..4c0abb9
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkmessage.cpp
@@ -0,0 +1,75 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkgadgets.cc
+#include "pxtkmessage.h"
+#include <stdlib.h>
+#include <math.h>
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtkmessage.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+ /* ********************************************************************
+
+    Definition of PXTkMessage Class 
+
+ ********************************************************************* */
+
+PXTkMessage::PXTkMessage(PXTkEventObj* evpar,PXTkGadget* gadg_par,
+			 const char* label,PXBool dodisplay):PXTkLabel(evpar,gadg_par,NULL,PXFalse)
+{
+  if (dodisplay)
+      {
+	initDisplay();
+	setText(label);
+      }
+}
+
+int PXTkMessage::initDisplay()
+{
+  sprintf(pxtk_buffer,"message %s",widget_name);
+    int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+  return a;
+}
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkmessage.h b/bioimagesuite30_src/pxtklib/pxtkmessage.h
new file mode 100644
index 0000000..86193ec
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkmessage.h
@@ -0,0 +1,82 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkmessage.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkMessage
+
+_Description : Definition of class PXTkMessage to warp Message TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtklabel.h"
+
+#ifndef _PXTkMessage
+#define  _PXTkMessage
+
+
+/* ---- Definition of PXTkMessage Class  ---- */
+
+class PXTkMessage : public PXTkLabel
+{
+public:
+  PXTkMessage(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* label,PXBool dodisplay=PXTrue);
+  virtual int initDisplay();
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkoptionmenu.cpp b/bioimagesuite30_src/pxtklib/pxtkoptionmenu.cpp
new file mode 100644
index 0000000..76f3552
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkoptionmenu.cpp
@@ -0,0 +1,197 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+#include "pxtkoptionmenu.h"
+#include "pxtkeventobj.h"
+#include <stdlib.h>
+
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+
+   see pxtkoptionmenu.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+/* ********************************************************************
+   
+   Definition of PXTkOptionMenu Class 
+   
+   ********************************************************************* */
+
+PXTkOptionMenu::PXTkOptionMenu(PXTkEventObj* evpar,PXTkGadget* gadg_par,
+	       const char* label,int callno):PXTkGadget(evpar,gadg_par)
+{
+  initial_value=new char[strlen(label)+1];
+  callbackno=callno;
+  strcpy(initial_value,label);
+  initDisplay();
+}
+
+PXTkOptionMenu::~PXTkOptionMenu()
+{
+  // This should never be needed!
+  if (initial_value!=NULL)
+      delete [] initial_value;
+}
+
+char* PXTkOptionMenu::getLabel(int index)
+{
+  sprintf(pxtk_buffer,"%s.menu entrycget %d -label",widget_name,index);
+  if (PXTkApp::executeTclCommand(pxtk_buffer)==TCL_OK)
+      return PXTkApp::getTclStringResult();
+  else
+      return NULL;
+}
+
+int  PXTkOptionMenu::changeLabel(int index, const char* label)
+{
+  index=Irange(index,0,getNumOptions()-1);
+  /*sprintf(pxtk_buffer,"%s.menu entryconfigure %d -label \"%s\" -variable widgetvar%d",
+	  widget_name,index,label,object_id);
+  fprintf(stderr,"Command = %s\n",pxtk_buffer);
+  return PXTkApp::executeTclCommand(pxtk_buffer);*/
+
+  int oldIndex=getIndex();
+  deleteOption(index);
+  insertOption(label,index);
+  setIndex(oldIndex);
+  return TCL_OK;
+}
+
+int   PXTkOptionMenu::addOption(const char* label,int callno)
+{
+  if (callno==-1)
+      callno=callbackno;
+
+  sprintf(pxtk_buffer,"%s.menu add radio -label \"%s\" -variable widgetvar%d -command {pxtkcallback %d %d %ld}",
+	  widget_name,label,object_id,
+	  event_parent->getHandlerNo(),callno,(long)this);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+	  
+}
+
+int   PXTkOptionMenu::insertOption(const char* label,int index,int callno)
+{
+  if (callno==-1)
+      callno=callbackno;
+
+  if (index<0)
+      index=getNumOptions();
+
+  sprintf(pxtk_buffer,"%s.menu insert %d radio -label \"%s\" -variable widgetvar%d -command {pxtkcallback %d %d %ld}",
+	  widget_name,index,label,object_id,
+	  event_parent->getHandlerNo(),callno,(long)this);
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+int   PXTkOptionMenu::deleteOption(int index)
+{
+  PXBool cleanup=PXFalse;
+  if (index==getIndex())
+      cleanup=PXTrue;
+
+  sprintf(pxtk_buffer,"%s.menu delete %d ",widget_name,index);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+
+  if (cleanup)
+      setIndex(0);
+  return a;
+}
+  
+int   PXTkOptionMenu::getNumOptions()
+{
+  sprintf(pxtk_buffer,"%s.menu index last",widget_name);
+  if (PXTkApp::executeTclCommand(pxtk_buffer)==TCL_OK)
+      {
+	int a=PXTkApp::getTclIntResult();
+	return (a+1);
+      }
+  else
+      return 0;
+  
+}
+void  PXTkOptionMenu::setIndex(int index,PXBool callback)
+{
+  if (callback)
+      {
+	sprintf(pxtk_buffer,"%s.menu invoke %d",widget_name,index);
+	PXTkApp::executeTclCommand(pxtk_buffer);
+      }
+  else
+      {
+	sprintf(pxtk_buffer,"%s.menu entrycget %d -label",widget_name,index);
+	int a=PXTkApp::executeTclCommand(pxtk_buffer);
+	if (a==TCL_OK)
+	    {
+	      strcpy(pxtk_buffer2,PXTkApp::getTclStringResult());
+	      setWidgetVariable(pxtk_buffer2);
+	    }
+      }
+}
+
+int   PXTkOptionMenu::getIndex()
+{
+  sprintf(pxtk_buffer2,getValue());
+  sprintf(pxtk_buffer,"%s.menu index \"%s\"",widget_name,pxtk_buffer2);
+
+  if (PXTkApp::executeTclCommand(pxtk_buffer)==TCL_OK)
+      return PXTkApp::getTclIntResult();
+  else
+      return -1;
+}
+
+char* PXTkOptionMenu::getValue()
+{
+  return getWidgetVariable();
+}
+  
+int PXTkOptionMenu::initDisplay()
+{
+  sprintf(pxtk_buffer,"tk_optionMenu %s widgetvar%d \"%s\" ",widget_name,object_id,initial_value);
+  delete [] initial_value;
+  initial_value=NULL;
+  
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  if (a==TCL_OK)
+      {
+	is_display_ok=PXTrue;
+	sprintf(pxtk_buffer,"%s.menu entryconfigure 0 -command {pxtkcallback %d %d %ld}",
+		widget_name,
+		event_parent->getHandlerNo(),callbackno,(long)this);
+	return PXTkApp::executeTclCommand(pxtk_buffer);
+      }
+  return a;
+}
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkoptionmenu.h b/bioimagesuite30_src/pxtklib/pxtkoptionmenu.h
new file mode 100644
index 0000000..8f740b4
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkoptionmenu.h
@@ -0,0 +1,97 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtkmenu.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkOptionMenu
+
+
+_Description : 
+
+_Call : (examples)
+  
+_References : 
+
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXTkOptionMenu		
+#define _PXTkOptionMenu		
+
+#include "pxtkgadget.h"
+
+class PXTkOptionMenu : public PXTkGadget
+{
+  char* initial_value;
+  int   callbackno;
+
+public:
+  PXTkOptionMenu(PXTkEventObj* evpar,PXTkGadget* gadg_par, const char* label,int callno);
+  virtual ~PXTkOptionMenu();
+
+  virtual char* getLabel(int index);
+  virtual int   changeLabel(int index, const char* label);
+  virtual int   addOption(const char* label,int callno=-1);
+  virtual int   insertOption(const char* label,int index=-1,int callno=-1);
+  virtual int   deleteOption(int index);
+  
+  virtual int   getNumOptions();
+
+  virtual void  setIndex(int index,PXBool callback=PXFalse);
+  virtual int   getIndex();
+
+  virtual char* getValue();
+  
+  virtual int initDisplay();
+};
+
+
+
+#endif   
+
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkradiobutton.cpp b/bioimagesuite30_src/pxtklib/pxtkradiobutton.cpp
new file mode 100644
index 0000000..0c2f4c0
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkradiobutton.cpp
@@ -0,0 +1,104 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkradiobutton.cpp
+#include "pxtkradiobutton.h"
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtkradiobutton.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+ /* ********************************************************************
+
+    Definition of PXTkRadioButton Class 
+
+ ********************************************************************* */
+
+PXTkRadioButton::PXTkRadioButton(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* name,int callno,
+				 PXTkRadioButton* mster,PXBool dodisplay):PXTkCheckButton(evpar,gadg_par,NULL,-1,PXFalse)
+{
+  if (dodisplay)
+      {
+	master=mster;
+	if (master==NULL)
+	    master=this;
+	initDisplay();
+	setText(name);
+	setCallback(callno);
+	call_no=callno;
+      }
+}
+
+int PXTkRadioButton::initDisplay()
+{
+  sprintf(pxtk_buffer,"radiobutton %s -variable widgetvar%d -value %d",widget_name,master->getObjectId(),object_id);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+  return a;
+}
+
+PXBool PXTkRadioButton::getState()
+{
+  int a=atoi(master->getWidgetVariable());
+  if (a==object_id)
+      return PXTrue;
+  return PXFalse;
+}
+
+int  PXTkRadioButton::setState(PXBool state,PXBool callback)
+{
+  if (state)
+      sprintf(pxtk_buffer,"%s select",widget_name);
+  else
+      sprintf(pxtk_buffer,"%s deselect",widget_name);
+
+  PXTkApp::executeTclCommand(pxtk_buffer);
+
+  if (callback && call_no>0)
+      return event_parent->handleEvent(call_no);
+  else
+      return TCL_OK;
+}   
+
+
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkradiobutton.h b/bioimagesuite30_src/pxtklib/pxtkradiobutton.h
new file mode 100644
index 0000000..acc1cbb
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkradiobutton.h
@@ -0,0 +1,92 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkradiobutton.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkRadioButton
+
+_Description : Definition of class PXTkRadioButton to warp RadioButton TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtkcheckbutton.h"
+
+#ifndef _PXTkRadioButton
+#define  _PXTkRadioButton
+
+
+/* ----  Definition of PXTkRadioButton ---- */
+
+class PXTkRadioButton: public PXTkCheckButton
+{
+protected:
+
+  PXTkRadioButton* master;
+
+public:
+  PXTkRadioButton(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* name,int callno,
+		  PXTkRadioButton* master=NULL,PXBool dodisplay=PXTrue);
+
+  virtual int    initDisplay();
+  virtual PXBool getState();
+  virtual int    setState(PXBool state,PXBool callback=PXFalse);
+
+};   
+
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkscale.cpp b/bioimagesuite30_src/pxtklib/pxtkscale.cpp
new file mode 100644
index 0000000..d2405fe
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkscale.cpp
@@ -0,0 +1,198 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtkscale.cpp
+#include "pxtkscale.h"
+#include "pxtkeventobj.h"
+#include "math.h"
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtkscale.h for more details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- */
+
+/* ********************************************************************
+
+    Definition of PXTkScale Class 
+
+ ********************************************************************* */
+
+PXTkScale::PXTkScale(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* label,int moption,
+		     PXBool horizontal,PXBool dodisplay):PXTkGadget(evpar,gadg_par)
+{
+  if (dodisplay)
+      {
+	call_no=moption;
+	initDisplay();
+	setLabel(label);
+	setHorizontalOrient(horizontal);
+      }
+}
+  
+int PXTkScale::setLabel(const char* label)
+{
+  return (configurequote("-label",label));
+}
+
+
+float PXTkScale::getValue()
+{
+  char* line=getWidgetVariable();
+  if (line==NULL)
+    {
+      fprintf(stderr,"NULL scale::getValue %s widgetvar%d\n",widget_name,object_id);
+      return 0.0;
+    }
+  return atof(line);
+}
+
+/******************************************************************************/
+
+float PXTkScale::getMin()
+{
+  return atof(cget("-from"));
+}
+
+/******************************************************************************/
+
+float PXTkScale::getMax()
+{
+  return atof(cget("-to"));
+}
+
+/******************************************************************************/
+
+int PXTkScale::setValue(float val,PXBool callback)
+{
+  char line[20];
+  sprintf(line,"%f",val);
+  char* ll=setWidgetVariable(line);
+  if (ll!=NULL)
+      {
+	if (callback && call_no>0)
+	    return event_parent->handleEvent(call_no);
+	else
+	    return TCL_OK;
+      }
+  else
+      return TCL_ERROR;
+}
+
+int PXTkScale::setRange(float min,float max)
+{
+  configure("-from",min);
+  return configure("-to",max);
+  //return setResolution(fabs(max-min)/100.0);
+}
+
+int PXTkScale::setLengthWidth(int length,int width)
+{
+  if (width!=-1)
+      configure("-width",width);
+  return configure("-length",length);
+}
+
+int PXTkScale::showValue(PXBool show)
+{
+  if (show)
+      return configure("-showValue","true");
+  else
+      return configure("-showValue","false");
+}
+
+int PXTkScale::setResolution(float res)
+{
+ if (res==-1.0)
+   {
+     float min=atof(cget("-from"));
+     float max=atof(cget("-to"));
+     if (fabs(max-min)>1e-6)
+       res=(fabs(max-min))/50.0;
+     else
+       res=1.0;
+   }
+  return configure("-resolution",res);
+}
+
+int PXTkScale::setTickInterval(float tickInt)
+{
+  if (tickInt==-1.0)
+    {
+      float min=atof(cget("-from"));
+      float max=atof(cget("-to"));
+      if (fabs(max-min)>1e-6)
+	tickInt=(fabs(max-min))/2.0;
+      else
+	tickInt=1.0;
+    }
+  return configure("-tickInterval",tickInt);
+}
+
+int PXTkScale::setDigits(int digits)
+{
+  return configure("-digits",digits);
+}
+
+int PXTkScale::setHorizontalOrient(PXBool orient)
+{
+  if (orient)
+      return configure("-orient","horizontal");
+  else
+      return configure("-orient","vertical");
+}
+
+int PXTkScale::initDisplay()
+{
+  setWidgetVariable("0");
+
+  sprintf(pxtk_buffer,"scale %s -variable widgetvar%d ",widget_name,object_id);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+
+  if (call_no>0)
+      {
+	sprintf(pxtk_buffer,"bind %s <ButtonRelease> { pxtkcallback %d %d %ld $widgetvar%d}",
+		widget_name,event_parent->getHandlerNo(),call_no,(long)this,object_id);
+
+
+	a=PXTkApp::executeTclCommand(pxtk_buffer);
+      }
+
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+  return a;
+
+}
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkscale.h b/bioimagesuite30_src/pxtklib/pxtkscale.h
new file mode 100644
index 0000000..2601a14
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkscale.h
@@ -0,0 +1,95 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtkscale.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkScale
+
+_Description : Definition of class PXTkScale to warp Scale TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtkgadget.h"
+
+#ifndef _PXTkScale
+#define  _PXTkScale
+
+/* ---- Definition of PXTkScale Class  ---- */
+  
+class PXTkScale : public PXTkGadget
+{
+protected:
+  int call_no;
+
+public:
+  PXTkScale(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* label,int moption=-1,PXBool horizontal=PXTrue,PXBool dodisplay=PXTrue);
+  
+  virtual int setValue(float val,PXBool callback=PXFalse);
+  virtual float getValue();
+  virtual float getMin();
+  virtual float getMax();
+
+  virtual int setHorizontalOrient(PXBool orient=PXTrue);
+  virtual int setLabel(const char* label);
+  virtual int setRange(float min,float max);
+  virtual int setResolution(float res=-1.0);
+  virtual int setLengthWidth(int length,int width=-1);
+  virtual int showValue(PXBool show=PXTrue);
+  virtual int setTickInterval(float tickInt=-1.0);
+  virtual int setDigits(int digits);
+  virtual int initDisplay();
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkscrollbar.cpp b/bioimagesuite30_src/pxtklib/pxtkscrollbar.cpp
new file mode 100644
index 0000000..37a314a
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkscrollbar.cpp
@@ -0,0 +1,101 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkscrollbar.cpp
+#include "pxtkscrollbar.h"
+#include "pxtkeventobj.h"
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtkscrollbar.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+
+/* ********************************************************************
+   
+   Definition of PXTkScrollbar Class 
+   
+   ********************************************************************* */
+
+PXTkScrollbar::PXTkScrollbar(PXTkEventObj* evpar,PXTkGadget* gadg_par,PXBool vertical,
+			     PXBool dodisplay):PXTkGadget(evpar,gadg_par)
+{
+  orientation=vertical;
+  if (dodisplay)
+      initDisplay();
+}
+
+int PXTkScrollbar::initDisplay()
+{
+  if (orientation)
+      sprintf(pxtk_buffer,"scrollbar %s -orient vertical",widget_name);
+  else
+      sprintf(pxtk_buffer,"scrollbar %s -orient horizontal",widget_name);
+
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+  return a;
+}
+
+int PXTkScrollbar::attachGadget(PXTkGadget* gadget)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  char* othername=gadget->getWidgetBaseName();
+  char line[5];
+  if (orientation)
+      sprintf(line,"y");
+  else
+      sprintf(line,"x");
+	
+  sprintf(pxtk_buffer,"%s configure -command { %s %sview }",
+	  widget_name,othername,line);
+  PXTkApp::executeTclCommand(pxtk_buffer);
+
+  sprintf(pxtk_buffer,"%s configure -%sscrollcommand {%s set }",
+	  othername,line,widget_name);
+
+  return PXTkApp::executeTclCommand(pxtk_buffer);
+}
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkscrollbar.h b/bioimagesuite30_src/pxtklib/pxtkscrollbar.h
new file mode 100644
index 0000000..a885b13
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkscrollbar.h
@@ -0,0 +1,89 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkscrollbar.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkScrollbar
+
+_Description : Definition of class PXTkScrollbar to warp Scrollbar TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtkgadget.h"
+
+#ifndef _PXTkScrollbar
+#define  _PXTkScrollbar
+
+
+/* ----  Definition of PXTkScrollbar Class  ---- */
+
+class PXTkScrollbar : public PXTkGadget
+{
+protected:
+  PXBool orientation;
+
+public:
+  PXTkScrollbar(PXTkEventObj* evpar,PXTkGadget* gadg_par,PXBool vertical=PXTrue,PXBool dodisplay=PXTrue);
+
+  virtual int initDisplay();
+  virtual int attachGadget(PXTkGadget* gadget);
+};
+
+  
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkseldialog.cpp b/bioimagesuite30_src/pxtklib/pxtkseldialog.cpp
new file mode 100644
index 0000000..6c91c95
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkseldialog.cpp
@@ -0,0 +1,377 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+#include "pxtkseldialog.h"
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXx library 
+
+   Xenios Papademetris July 1995   papad at noodle.med.yale.edu
+
+   see pxgrseldialog.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+/* -------------------------------------------------------------------------*/
+/*                   PXGrSelDialog                                          */
+/* -------------------------------------------------------------------------*/
+
+/* -------------------------------------------------------------------------*/
+PXTkSelDialog::PXTkSelDialog(PXTkEventObj* objpar,PXTkGadget* w, int n):PXTkDialog(objpar,w,"Option Dialog",PXFalse)
+{
+  max_num_options=Irange(n,1,20);
+  num_options=max_num_options;
+  menu_option=-1;
+  debug_option=-1;
+  label_width=15;
+  entry_width=8;
+  pack_step=1;
+  debugbutton=NULL;
+  show_debug=0;
+}
+
+PXTkSelDialog::~PXTkSelDialog()
+{
+  if (is_display_ok)
+    {
+      delete message;
+      for (int i=0;i<num_options;i++)
+	{
+	  delete label[i];
+	  delete entry[i];
+	}
+    }
+}
+
+/* -------------------------------------------------------------------------*/
+
+int PXTkSelDialog::handleEvent(int n)
+{
+  switch (n) 
+    {
+    case 1:   // OK
+      popdownDialog();
+      if (has_event_parent && menu_option>0)
+	  event_parent->handleEvent(menu_option);
+      break;
+
+    case 2 : // Cancel
+      popdownDialog();
+      if (has_event_parent && menu_option>0)
+	  event_parent->handleEvent(menu_option+1);
+      break;
+
+    case 3 : // Debug
+      for (int i=0;i<num_options;i++)
+	  {
+	    sprintf(pxtk_buffer,"Value of Field %d (%s)\n",i,getoption(i));
+	    PXTkApp::printToConsole(pxtk_buffer);
+	  }
+      if (has_event_parent && menu_option>0)
+	  event_parent->handleEvent(menu_option+2);
+      break;
+    }
+  return TCL_OK;
+}
+/* -------------------------------------------------------------------------*/
+int PXTkSelDialog::setNumOptions(int newnumoptions)
+{
+  if (!is_display_ok)
+    return num_options;
+
+  if (isOpen())
+    return num_options;
+
+  newnumoptions=Irange(newnumoptions,1,max_num_options);
+  if (newnumoptions==num_options)
+    return num_options;
+
+
+  if (num_options<newnumoptions)
+    {
+      for (int i=num_options;i<newnumoptions;i++)
+	{
+	  optionFrame->gridRowColumnChild(label[i],this->getGridRow(i),this->getGridColumn(i));
+	  optionFrame->gridRowColumnChild(entry[i],this->getGridRow(i),this->getGridColumn(i)+1);
+	}
+    }
+  else
+    {
+      for (int i=newnumoptions;i<num_options;i++)
+	{
+	  optionFrame->unmapChild(label[i]);
+	  optionFrame->unmapChild(entry[i]);
+	}
+    }
+  
+  num_options=newnumoptions;
+  return num_options;
+}
+
+int PXTkSelDialog::initDisplay()
+{
+  int odd=0;
+  int pr=num_options;
+  if (pr>8)
+      {
+	if (2*int(num_options/2)<num_options) 
+	    odd=1;
+	else
+	    odd=0;
+	height=190+(int((odd+num_options)/2)*45);
+	width=280;
+      }
+  else
+      {
+	height=190+num_options*45;
+	width=220;
+      }
+
+  PXTkDialog::initDisplay();
+  PXTkFrame* manager=(PXTkFrame*)(main_window);
+  manager->setPackMode(PXTrue);
+  sprintf(pxtk_buffer,"%d %d,",width,height);
+  manager->wmconfigure("maxsize",pxtk_buffer);
+  manager->wmconfigure("minsize",pxtk_buffer);
+
+  PXTkFrame *desc=new PXTkFrame(this,manager,width,70);
+  desc->configure("-relief","sunken");
+
+  PXTkFrame *main=new PXTkFrame(this,manager,width,height-140);
+  main->configure("-relief","raised");
+
+  PXTkFrame *bot=new PXTkFrame(this,manager,width,70);
+
+  manager->addChildren("-fill both -expand true -padx 2 -pady 2",desc,main,bot);
+  
+  message=new PXTkMessage(this,desc,"Description");
+  message->configure("-relief","ridge");
+  message->configure("-width",width);
+  
+  desc->addChildren("-fill x -expand true",message);
+
+  pack_step=1;
+  if (pr>8) 
+      pack_step=2;
+
+  optionFrame=new PXTkFrame(this,main);
+  optionFrame->configure("-width",width);
+  optionFrame->configure("-height",height-140);
+  optionFrame->setPackMode(PXFalse);
+
+  main->addChildren("-fill x -expand true",optionFrame);
+  for (int i=0;i<num_options;i+=pack_step)
+      {
+	for (int k=0;k<pack_step;k++)
+	    {
+	      int ind=i+k;
+	      if (ind<num_options)
+		{
+		  label[ind]=new PXTkLabel(this,optionFrame,"Desc");
+		  label[ind]->configure("-width",15);
+		  optionFrame->gridRowColumnChild(label[ind],this->getGridRow(ind),this->getGridColumn(ind));
+		  
+		  entry[ind]=new PXTkEntry(this,optionFrame);
+		  entry[ind]->configure("-width",8);
+		  entry[ind]->configure("-relief","sunken");
+		  entry[ind]->setText("0.0");
+		  optionFrame->gridRowColumnChild(entry[ind],this->getGridRow(ind),this->getGridColumn(ind)+1);
+		}
+	    }
+      }
+
+  PXTkButton*     ok=new PXTkButton(this,bot,"OK",1);
+  PXTkButton* cancel=new PXTkButton(this,bot,"Cancel",2);
+  debugbutton=new PXTkButton(this,bot,"Info",3);
+  bot->addChildren("-fill x -expand f -side left",ok);
+  bot->addChildren("-fill x -expand f -side right",cancel);
+  bot->addChildren("-fill x -expand f -side left",debugbutton);
+  if (show_debug==0)
+    bot->unmapChild(debugbutton);
+  return TCL_OK;
+
+}
+
+/* -------------------------------------------------------------------------*/
+
+int PXTkSelDialog::getGridRow(int optionid)
+{
+  return int(optionid/pack_step);
+}
+// ----------------------------------------------------------
+int PXTkSelDialog::getGridColumn(int optionid)
+{
+  if (pack_step==1)
+    return 0;
+  
+  int row=int(optionid/2);
+  if (row*2 == optionid)
+    return 0;
+  
+  return 2;
+}
+// ----------------------------------------------------------
+// Parameter Setup
+// ----------------------------------------------------------
+
+void PXTkSelDialog::setfoption(int i,const char* lab,const char* fmt,float val)
+{ 
+  if (!is_display_ok)
+    return;
+
+
+  if (i>=0 || i<num_options)
+      {
+	label[i]->setText(lab);
+	sprintf(pxtk_buffer,fmt,val);
+	entry[i]->setText(pxtk_buffer);
+      }
+}
+
+void PXTkSelDialog::setoption(int i,const char* lab,const char* fmt,const char* val)
+{      
+  if (!is_display_ok)
+    return;
+
+  if (i>=0 || i<num_options)
+      {
+	label[i]->setText(lab);
+	sprintf(pxtk_buffer,fmt,val);
+	entry[i]->setText(pxtk_buffer);
+      }
+}
+
+void PXTkSelDialog::setioption(int i,const char* lab,const char* fmt,int val)
+{      
+  if (!is_display_ok)
+    return;
+
+
+  if (i>=0 || i<num_options)
+      {
+	label[i]->setText(lab);
+	sprintf(pxtk_buffer,fmt,val);
+	entry[i]->setText(pxtk_buffer);
+      }
+}
+// ----------------------------------------------------------
+
+char* PXTkSelDialog::getoption(int i)
+{ 
+  if (is_display_ok && i>=0 && i<num_options)
+      return entry[i]->getText();
+  else
+      return NULL;
+}
+
+float PXTkSelDialog::getfoption(int i)
+{ 
+  char *line=getoption(i);
+  if (line!=NULL)
+      return atof(line);
+  else 
+      return 0;
+}
+
+int PXTkSelDialog::getioption(int i)
+{ 
+  char *line=getoption(i);
+  if (line!=NULL)
+      return atoi(line);
+  else 
+      return 0;
+}
+// ----------------------------------------------------------
+
+int PXTkSelDialog::getNumOptions()
+{
+  return num_options;
+}
+
+void PXTkSelDialog::setDescription(const char* description)
+{
+   if (!is_display_ok)
+    return;
+
+ if (isOpen())
+    return;
+ 
+ message->setText(description);
+}
+  
+void PXTkSelDialog::setTitleDescription(const char* title,const char* description)
+{
+  this->setTitle(title);
+  this->setDescription(description);
+}
+
+
+
+void PXTkSelDialog::setMenuOption(int m)
+{
+   if (!is_display_ok)
+    return;
+
+ if (isOpen())
+    return;
+ 
+ menu_option=m;
+}
+
+void PXTkSelDialog::setDebugButton(const char* label,int option)
+{
+   if (!is_display_ok)
+    return;
+
+   debugbutton->setText(label);
+   debug_option=option;
+}
+
+void PXTkSelDialog::hideDebugButton()
+{
+   if (!is_display_ok)
+    return;
+
+   ((PXTkFrame*)(debugbutton->getGadgetParent()))->unmapChild(debugbutton);
+}
+
+void PXTkSelDialog::showDebugButton()
+{
+   if (!is_display_ok)
+    return;
+
+   ((PXTkFrame*)(debugbutton->getGadgetParent()))->addChildren("-fill x -expand f -side left",debugbutton);
+}
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkseldialog.h b/bioimagesuite30_src/pxtklib/pxtkseldialog.h
new file mode 100644
index 0000000..9111d7a
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkseldialog.h
@@ -0,0 +1,139 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxgrseldialog.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkSeldialog
+
+
+_Description : This is a dialog class to present options
+
+
+_Call : 
+
+_References : 
+
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 11th May 2000
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXDRAW_SEL_DIALOG
+#define _PXDRAW_SEL_DIALOG
+
+#include "pxtkdialog.h"
+#include "pxtkgadgets.h"
+
+// ****************************************
+// ******* PXTkSelDialog Class ************
+// ****************************************
+
+class PXTkSelDialog : public PXTkDialog {
+  
+protected:
+  
+  // GUI Related ;
+  
+  int  menu_option,max_num_options,label_width,entry_width,debug_option,show_debug;
+  int  num_options;
+  int  pack_step;
+  
+  PXTkFrame* optionFrame;
+
+
+
+public:
+  
+  PXTkSelDialog(PXTkEventObj* par,PXTkGadget* w,int n);
+  virtual ~PXTkSelDialog();
+
+  PXTkLabel* label[20];
+  PXTkEntry* entry[20];
+  PXTkMessage* message;
+  PXTkButton*  debugbutton;
+
+  // ----------------------------------------------------------
+  // Parameter Setup
+  // ----------------------------------------------------------
+
+  virtual  void  setfoption(int i,const char* lab,const char* fmt,float val);
+  virtual  void  setoption(int i,const char* lab,const char* fmt,const char* val);
+  virtual  void  setioption(int i,const char* lab,const char* fmt,int val);
+
+  virtual  char* getoption(int i);
+  virtual  float getfoption(int i);
+  virtual  int   getioption(int i);
+
+  virtual  int   getNumOptions();
+  virtual  int   setNumOptions(int newnumoptions);
+  virtual void   setDescription(const char* description);
+  virtual void   setTitleDescription(const char* title,const char* description);
+  virtual void   setMenuOption(int m);
+
+  // Third Button Options
+  virtual void   setDebugButton(const char* label,int option);
+  virtual void   hideDebugButton();
+  virtual void   showDebugButton();
+
+  // ----------------------------------------------------------
+  // GUI Related
+  // ----------------------------------------------------------
+  
+  virtual int  initDisplay();
+  virtual int  handleEvent(int);
+
+protected:
+  
+  virtual int getGridRow(int optionid);
+  virtual int getGridColumn(int optionid);
+};
+
+#endif   
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtktext.cpp b/bioimagesuite30_src/pxtklib/pxtktext.cpp
new file mode 100644
index 0000000..ff07487
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtktext.cpp
@@ -0,0 +1,149 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtktext.cpp
+#include "pxtktext.h"
+#include <vtkstd/string>
+#include "sstream"
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+   
+   see pxtktext.h for details
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+/* ********************************************************************
+   
+   Definition of PXTkText Class 
+   
+   ********************************************************************* */
+
+PXTkText::PXTkText(PXTkEventObj* evpar,PXTkGadget* gadg_par,
+		   PXBool dodisplay):PXTkLabel(evpar,gadg_par,NULL,PXFalse)
+{
+  if (dodisplay)
+      initDisplay();
+}
+
+int PXTkText::initDisplay()
+{
+  sprintf(pxtk_buffer,"text %s ",widget_name);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  if (a==TCL_OK)
+      is_display_ok=PXTrue;
+  return a;
+}
+
+int PXTkText::addText(const char* newtext)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  PXBool st=getEditableState();
+  if (st==PXFalse)
+    setEditableState(PXTrue);
+  
+  int a=this->addTextDirect(newtext);
+  if (a==TCL_OK)
+    {
+      std::stringstream s2;
+      s2 << widget_name << " see end";
+      a=PXTkApp::executeTclCommand(s2.str().c_str());
+    }
+  
+  if (st==PXFalse)
+      setEditableState(PXFalse);
+  return a;
+}
+
+int PXTkText::clearText()
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  PXBool st=getEditableState();
+  if (st==PXFalse)
+      setEditableState(PXTrue);
+
+  sprintf(pxtk_buffer,"%s delete 1.0  end  ",widget_name);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+
+  if (st==PXFalse)
+      setEditableState(PXFalse);
+  return a;
+
+}
+
+int PXTkText::addTextDirect(const char* newtext)
+{
+  if (!is_display_ok)
+    return TCL_ERROR;
+
+  std::string s(newtext);
+  PXTkApp::StringSanitize(s);
+  //  fprintf(stderr,"Sanitized = %s\n",s.c_str());
+  std::string s2(widget_name);
+  s2+= " insert end \"" + s + " \"";
+  //  fprintf(stderr,"Executing %s\n",s2.c_str());
+  return PXTkApp::executeTclCommand(s2.c_str());
+}
+
+
+int PXTkText::setEditableState(PXBool state)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+  
+  if (state)
+    return configure("-state","normal");
+  else
+    return configure("-state","disabled");
+}
+
+PXBool PXTkText::getEditableState()
+{
+  if (!is_display_ok)
+      return PXFalse;
+
+  char* line=cget("-state");
+  if (line==NULL)
+    return PXFalse;
+  
+  if (strcmp(line,"normal")==0)
+    return PXTrue;
+  else
+    return PXFalse;
+}
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtktext.h b/bioimagesuite30_src/pxtklib/pxtktext.h
new file mode 100644
index 0000000..5844f8c
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtktext.h
@@ -0,0 +1,83 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+// pxtktext.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkText
+
+_Description : Definition of class PXTkText to warp Text TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtklabel.h"
+
+#ifndef _PXTkText
+#define  _PXTkText
+
+/* ----  Definition of PXTkText ---- */
+class PXTkText : public PXTkLabel
+{
+public:
+  PXTkText(PXTkEventObj* evpar,PXTkGadget* gagd_par,PXBool dodisplay=PXTrue);
+
+  virtual int initDisplay();
+  virtual int addText(const char* line);
+  virtual int addTextDirect(const char* line);
+  virtual int clearText();
+  virtual int setEditableState(PXBool state=PXTrue);
+  virtual PXBool getEditableState();
+};
+
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtktoplevel.cpp b/bioimagesuite30_src/pxtklib/pxtktoplevel.cpp
new file mode 100644
index 0000000..5a5cca7
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtktoplevel.cpp
@@ -0,0 +1,166 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkgadgets.cc
+#include "pxtkframe.h"
+#include "pxtktoplevel.h"
+#include "pxtkdialog.h"
+#include <stdlib.h>
+#include <math.h>
+
+int  PXTkToplevel::num_top_levels=0;
+
+/***********************************************
+
+    Definition of PXTkToplevel Class 
+
+ ********************************************************************* */
+
+PXTkToplevel::PXTkToplevel(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* title,
+			   int width,int height):PXTkFrame(evpar,gadg_par,width,height,PXFalse)
+{
+  initDisplay();
+  setDimensions(width,height);
+  setTitle(title);
+  if (has_gadget_parent)
+      {
+	PXTkToplevel::num_top_levels++;
+	top_level_id=PXTkToplevel::num_top_levels;
+      }
+}
+
+PXTkClassId PXTkToplevel::getClassId()
+{
+  return PXTkToplevelId;
+}
+
+
+int PXTkToplevel::initDisplay()
+{
+  sprintf(pxtk_buffer,"toplevel %s",widget_name);
+  int a=PXTkApp::executeTclCommand(pxtk_buffer);
+  sprintf(pxtk_buffer,"wm protocol %s WM_DELETE_WINDOW { grab release %s ; wm withdraw %s} ",
+	widget_name,widget_name,widget_name);
+  PXTkApp::executeTclCommand(pxtk_buffer);
+  bindCallback("<Control-w>",3);
+
+  if (a==TCL_OK)
+    {
+      is_display_ok=PXTrue;
+      this->hide();
+    }
+  return a;
+}
+
+int PXTkToplevel::setGrab(PXBool grab)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+  if (grab)
+      {
+	sprintf(pxtk_buffer,"grab %s",widget_name);
+	return PXTkApp::executeTclCommand(pxtk_buffer);
+      }
+  else
+      {
+	sprintf(pxtk_buffer,"grab release %s",widget_name);
+	return PXTkApp::executeTclCommand(pxtk_buffer);
+      }
+  return TCL_OK;
+}
+ 
+int PXTkToplevel::show(int id)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  sprintf(pxtk_buffer," ::pxtclutil::ShowWindow %s  ",widget_name);
+  if (PXTkApp::executeTclCommand(pxtk_buffer)==TCL_OK)
+    return TCL_OK;
+
+  wmconfigure("deiconify","");
+  sprintf(pxtk_buffer,"raise %s",widget_name);
+  PXTkApp::executeTclCommand(pxtk_buffer);
+
+  int x1=0,y1=0,w1=0,h1=0;
+  sprintf(pxtk_buffer,"winfo parent %s",widget_name);
+  PXTkApp::executeTclCommand(pxtk_buffer);
+  strcpy(pxtk_buffer2,PXTkApp::getTclStringResult());
+  if (strlen(pxtk_buffer)>0)
+    {
+      sprintf(pxtk_buffer,"winfo geometry %s",pxtk_buffer2);
+      PXTkApp::executeTclCommand(pxtk_buffer);
+      strcpy(pxtk_buffer,PXTkApp::getTclStringResult());
+      sscanf(pxtk_buffer,"%dx%d+%d+%d",&w1,&h1,&x1,&y1);
+
+      sprintf(pxtk_buffer,"lsearch [ winfo children %s] %s",pxtk_buffer2,widget_name);
+      PXTkApp::executeTclCommand(pxtk_buffer);
+      int offset=PXTkApp::getTclIntResult();
+
+#ifdef _WIN32
+      sprintf(pxtk_buffer,"focus -force %s",widget_name);
+      PXTkApp::executeTclCommand(pxtk_buffer);
+#endif
+      sprintf(pxtk_buffer,"wm geometry %s +%d+%d",widget_name,x1+2*w1/3+20*offset,y1+h1/2+20*offset);
+      PXTkApp::executeTclCommand(pxtk_buffer);
+    }
+  return TCL_OK;
+}
+
+int PXTkToplevel::getToplevelId()
+{
+  return top_level_id;
+}
+
+int PXTkToplevel::hide()
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+
+  sprintf(pxtk_buffer," ::pxtclutil::HideWindow %s  ",widget_name);
+  if (PXTkApp::executeTclCommand(pxtk_buffer)==TCL_OK)
+    return TCL_OK;
+
+  return wmconfigure("withdraw","");
+}
+
+int PXTkToplevel::setTitle(const char* title)
+{
+  if (!is_display_ok)
+      return TCL_ERROR;
+  return wmconfigure("title",title,PXFalse);
+}
+
+
diff --git a/bioimagesuite30_src/pxtklib/pxtktoplevel.h b/bioimagesuite30_src/pxtklib/pxtktoplevel.h
new file mode 100644
index 0000000..a12401d
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtktoplevel.h
@@ -0,0 +1,94 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtktoplevel.h
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PxTk library 
+
+   Xenios Papademetris July papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkToplevel
+
+_Description : Definition of class PXTkToplevel to warp Toplevel TK Widget in C++
+
+
+_Call :   
+        
+	
+_References : Practical Programming in Tcl and Tk, Brent B. Welch (Prentice Hall 2nd Edition)
+             
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 2nd January 2001
+
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#include "pxtkgadget.h"
+
+#ifndef _PXTkToplevel
+#define  _PXTkToplevel
+
+
+/* ----  Definition of PXTkToplevel Class  ---- */
+
+class PXTkToplevel : public PXTkFrame {
+
+protected:
+  int        top_level_id;
+  static int num_top_levels;
+public:
+  
+  PXTkToplevel(PXTkEventObj* evpar,PXTkGadget* gadg_par,const char* title,int width=-1,int height=-1);
+
+  virtual int initDisplay();
+  virtual int setGrab(PXBool grab);
+  virtual int show(int id=-1);
+  virtual int hide();
+
+  virtual int setTitle(const char* title);
+  virtual PXTkClassId   getClassId();
+  virtual int           getToplevelId();
+};
+
+#endif
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkwaitdialog.cpp b/bioimagesuite30_src/pxtklib/pxtkwaitdialog.cpp
new file mode 100644
index 0000000..196c3b7
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkwaitdialog.cpp
@@ -0,0 +1,138 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+#include "pxtkwaitdialog.h"
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000   papad at noodle.med.yale.edu
+
+   see pxtkwaitdialog.h for details
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+/* -------------------------------------------------------------------------*/
+/*                   PXTkWaitDialog                                          */
+/* -------------------------------------------------------------------------*/
+
+/* -------------------------------------------------------------------------*/
+PXTkWaitDialog::PXTkWaitDialog(PXTkEventObj* objpar,const char* title,int moption,PXBool showstop,
+			       int x,int y):PXTkDialog(objpar,title)
+{
+  height=y;   width=x; showStop=showstop; menuoption=moption;
+  this->debugMode=PXFalse;
+}
+/* -------------------------------------------------------------------------*/
+int PXTkWaitDialog::initDisplay()
+{
+  PXTkDialog::initDisplay();
+  PXTkFrame* manager=(PXTkFrame*)(main_window);
+
+  PXTkFrame* desc=new PXTkFrame(this,manager,width,70);
+  desc->configure("-relief","sunken");
+
+  bottom_frame=new PXTkFrame(this,manager,width,70);
+
+  manager->addChildren("-side bottom -expand f -fill x -padx 5 -pady 5",bottom_frame);
+  manager->addChildren("-side top -expand true -fill both -padx 5 -pady 5",desc);
+
+  PXTkLabel* lab=new PXTkLabel(this,desc," ");
+  lab->configure("-bitmap","hourglass");
+
+  message=new PXTkMessage(this,desc,"Description");
+  message->configure("-width",width);
+  message->configure("-apsect",100*(width/65));
+
+  desc->addChildren("-side left -expand true ",lab,message);
+
+  stop_button=new PXTkButton(this,bottom_frame,"Stop",1); 
+  bottom_frame->addChildren(" ",stop_button);
+
+  setText("Please Wait");
+  showStopPrompt(showStop);
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+int PXTkWaitDialog::setText(const char *line)
+{
+  message->setText(line);
+  if (this->debugMode==PXTrue)
+    fprintf(stderr,"%s\n",line);
+  PXTkApp::executeTclCommand("update idletasks");
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+int PXTkWaitDialog::setText(const char *text,int d)
+{
+  sprintf(pxtk_buffer,"%s %d",text,d);
+  if (this->debugMode==PXTrue)
+    fprintf(stderr,"%s\n",pxtk_buffer);
+  message->setText(pxtk_buffer);
+  PXTkApp::executeTclCommand("update idletasks");
+  return TCL_OK;
+}
+// -------------------------------------------------------------------------
+void PXTkWaitDialog::showStopPrompt(PXBool shows)
+{
+  showStop=shows;
+  if (is_display_ok)
+    {
+      if (showStop)
+	bottom_frame->mapChild(stop_button, " ");
+      else
+	bottom_frame->unmapChild(stop_button);
+    }
+}
+
+int PXTkWaitDialog::handleEvent(int event)
+{
+  if (event==1)
+      {
+	setModality(PXTrue);
+	setWaitCursor(PXTrue);
+	if (this->debugMode==PXTrue)
+	  fprintf(stderr,"Stop Event Captured\n");
+	if (menuoption>=0)
+	    return event_parent->handleEvent(menuoption);
+      }
+
+  return TCL_OK;
+}
+
+void PXTkWaitDialog::setDebugMode(PXBool debugmode)
+{
+  this->debugMode=debugmode;
+}
+
diff --git a/bioimagesuite30_src/pxtklib/pxtkwaitdialog.h b/bioimagesuite30_src/pxtklib/pxtkwaitdialog.h
new file mode 100644
index 0000000..cdf70ba
--- /dev/null
+++ b/bioimagesuite30_src/pxtklib/pxtkwaitdialog.h
@@ -0,0 +1,102 @@
+//BIOIMAGESUITE_LICENSE  ---------------------------------------------------------------------------------
+//BIOIMAGESUITE_LICENSE  This file is part of the BioImage Suite Software Package.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
+//BIOIMAGESUITE_LICENSE  Staib. BioImage Suite: An integrated medical image analysis suite, Section
+//BIOIMAGESUITE_LICENSE  of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of
+//BIOIMAGESUITE_LICENSE  Medicine, http://www.bioimagesuite.org.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is free software; you can redistribute it and/or
+//BIOIMAGESUITE_LICENSE  modify it under the terms of the GNU General Public License version 2
+//BIOIMAGESUITE_LICENSE  as published by the Free Software Foundation.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  This program is distributed in the hope that it will be useful,
+//BIOIMAGESUITE_LICENSE  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//BIOIMAGESUITE_LICENSE  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//BIOIMAGESUITE_LICENSE  GNU General Public License for more details.
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  You should have received a copy of the GNU General Public License
+//BIOIMAGESUITE_LICENSE  along with this program; if not, write to the Free Software
+//BIOIMAGESUITE_LICENSE  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+//BIOIMAGESUITE_LICENSE  See also  http://www.gnu.org/licenses/gpl.html
+//BIOIMAGESUITE_LICENSE  
+//BIOIMAGESUITE_LICENSE  If this software is modified please retain this statement and add a notice
+//BIOIMAGESUITE_LICENSE  that it had been modified (and by whom).  
+//BIOIMAGESUITE_LICENSE 
+//BIOIMAGESUITE_LICENSE  -----------------------------------------------------------------------------------
+
+
+
+
+
+
+
+
+
+// pxtkwaitdialog.h
+// -----------------------------------------------------------------
+
+/* #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- 
+
+   This file is part of the PXTk library 
+
+   Xenios Papademetris May 2000 papad at noodle.med.yale.edu
+
+
+_Module_Name : PXTkWaitDialog
+
+
+_Description : This is a dialog class to display wait information to user
+
+_Call : 
+  PXTkWaitDialog(PXTkEventObj* par,char* title,int x=200,int y=200);
+  
+_References : 
+
+	      
+_I/O : 
+
+_System : Unix
+_Remarks : 
+ 
+_Author : X. Papademetris papad at noodle.med.yale.edu
+_Revisions History: 1. Key in 21st March 1997
+                                
+#-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#- #-#-#-#-  */
+
+#ifndef _PXDRAW_WAIT_DIALOG
+#define _PXDRAW_WAIT_DIALOG
+
+#include "pxtkdialog.h"
+#include "pxtkgadgets.h"
+
+// ****************************************
+// ******* PXTkWaitDialog Class ************
+// ****************************************
+
+class PXTkWaitDialog : public PXTkDialog {
+  
+protected:
+
+  PXBool    showStop,debugMode;
+  int       menuoption;
+  PXTkFrame* bottom_frame;
+  PXTkButton* stop_button;
+  PXTkMessage* message;
+  
+public:
+  
+  PXTkWaitDialog(PXTkEventObj* par,const char* title,int moption,PXBool showstop=PXFalse,int x=200,int y=40);
+
+  virtual int initDisplay();
+
+  virtual int setText(const char *text);  
+  virtual int setText(const char *text,int d);
+  virtual void showStopPrompt(PXBool show=PXTrue);
+  virtual int handleEvent(int eventno);
+  virtual void setDebugMode(PXBool debugmode=PXTrue);
+};
+
+#endif   
+
+
diff --git a/debian/bioimagesuite-data.dirs b/debian/bioimagesuite-data.dirs
deleted file mode 100644
index db64484..0000000
--- a/debian/bioimagesuite-data.dirs
+++ /dev/null
@@ -1 +0,0 @@
-usr/share/bioimagesuite/
diff --git a/debian/bioimagesuite-data.install b/debian/bioimagesuite-data.install
deleted file mode 100644
index 97ef45e..0000000
--- a/debian/bioimagesuite-data.install
+++ /dev/null
@@ -1 +0,0 @@
-images/		usr/share/bioimagesuite/
diff --git a/debian/bioimagesuite.dirs b/debian/bioimagesuite.dirs
deleted file mode 100644
index 75e34d8..0000000
--- a/debian/bioimagesuite.dirs
+++ /dev/null
@@ -1,3 +0,0 @@
-usr/bin
-usr/share/bioimagesuite
-#usr/share/lintian/overrides
diff --git a/debian/bioimagesuite.examples b/debian/bioimagesuite.examples
deleted file mode 100644
index 0bbe99e..0000000
--- a/debian/bioimagesuite.examples
+++ /dev/null
@@ -1 +0,0 @@
-example/*
diff --git a/debian/bioimagesuite.install b/debian/bioimagesuite.install
deleted file mode 100644
index d42af89..0000000
--- a/debian/bioimagesuite.install
+++ /dev/null
@@ -1,12 +0,0 @@
-apps/		usr/lib/bioimagesuite/
-base/		usr/lib/bioimagesuite/
-datatree/	usr/lib/bioimagesuite/
-#lib/		usr/lib/bioimagesuite/
-main/		usr/lib/bioimagesuite/
-mjack/		usr/lib/bioimagesuite/
-
-setpaths.sh		usr/lib/bioimagesuite/
-surfaceeditor	usr/lib/bioimagesuite/
-setpaths.csh	usr/lib/bioimagesuite/
-
-start_bioimagesuite		usr/lib/bioimagesuite/
diff --git a/debian/bioimagesuite.links b/debian/bioimagesuite.links
deleted file mode 100644
index 0c6c20a..0000000
--- a/debian/bioimagesuite.links
+++ /dev/null
@@ -1 +0,0 @@
-usr/lib/bioimagesuite/start_bioimagesuite usr/bin/bioimagesuite
diff --git a/debian/bioimagesuite.lintian-overrides b/debian/bioimagesuite.lintian-overrides
deleted file mode 100644
index 6ca3c7a..0000000
--- a/debian/bioimagesuite.lintian-overrides
+++ /dev/null
@@ -1,2 +0,0 @@
-#bioimagesuite: shell-script-fails-syntax-check ./usr/lib/bioimagesuite/datatree/packages/ImageDialog.tcl
-#bioimagesuite: shell-script-fails-syntax-check ./usr/lib/bioimagesuite/datatree/packages/chellyDB.tcl
diff --git a/debian/bioimagesuite.menu b/debian/bioimagesuite.menu
deleted file mode 100644
index e1224c7..0000000
--- a/debian/bioimagesuite.menu
+++ /dev/null
@@ -1,5 +0,0 @@
-?package(bioimagesuite):\
-	needs="X11" \
-	section="Applications/Science/Medicine" \
-	title="BioImageSuite" \
-	command="/usr/bin/bioimagesuite"
diff --git a/debian/changelog b/debian/changelog
deleted file mode 100644
index 5fe1241..0000000
--- a/debian/changelog
+++ /dev/null
@@ -1,8 +0,0 @@
-bioimagesuite (2.0-1) UNRELEASED; urgency=low
-
-  DOESN'T EVEN COMPILE. (Check dpkg-shlibs note in debian/rules)
-
-  * Initial release
-  * Updated to Standards-Version 3.7.3 (no changes needed)
-
- -- David Paleino <d.paleino at gmail.com>  Wed, 06 Feb 2008 13:11:50 +0100
diff --git a/debian/compat b/debian/compat
deleted file mode 100644
index 7ed6ff8..0000000
--- a/debian/compat
+++ /dev/null
@@ -1 +0,0 @@
-5
diff --git a/debian/control b/debian/control
deleted file mode 100644
index edd78a5..0000000
--- a/debian/control
+++ /dev/null
@@ -1,67 +0,0 @@
-Source: bioimagesuite
-Section: science
-Priority: optional
-Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.org>
-Uploaders: David Paleino <d.paleino at gmail.com>
-Build-Depends: debhelper (>= 9), quilt, chrpath
-Standards-Version: 3.9.3
-Vcs-Browser: https://anonscm.debian.org/cgit/debian-med/bioimagesuite.git
-Vcs-Git: https://anonscm.debian.org/git/debian-med/bioimagesuite.git
-Homepage: http://www.bioimagesuite.org
-
-Package: bioimagesuite
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, itk3.1, vtk-tcl, libmetakit-tcl,
- tcllib, iwidgets4, itcl3.1, libminc0, bioimagesuite-data, libxerces28,
- minc-tools, hdf5-tools, netcdf-bin, libbioimagesuite2
-Description: integrated image analysis software suite
- BioImage Suite has extensive capabilities for both neuro/cardiac
- and abdominal image analysis and state of the art visualization.
- Many packages are available that are highly extensible, and provide
- functionality for image visualization and registration, surface
- editing, cardiac 4D multi-slice editing, diffusion tensor image
- processing, mouse segmentation and registration, and much more. It
- can be integrated with other biomedical image processing software,
- such as FSL and SPM. This site provides information, downloads,
- documentation, and other resources for users of the software.
- .
- BioImage Suite was developed at Yale University and has been
- extensively used at different labs at Yale since 2004.
-
-Package: bioimagesuite-data
-Architecture: all
-Description: integrated image analysis software suite
- BioImage Suite has extensive capabilities for both neuro/cardiac
- and abdominal image analysis and state of the art visualization.
- Many packages are available that are highly extensible, and provide
- functionality for image visualization and registration, surface
- editing, cardiac 4D multi-slice editing, diffusion tensor image
- processing, mouse segmentation and registration, and much more. It
- can be integrated with other biomedical image processing software,
- such as FSL and SPM. This site provides information, downloads,
- documentation, and other resources for users of the software.
- .
- BioImage Suite was developed at Yale University and has been
- extensively used at different labs at Yale since 2004.
- .
- This package contains architecture-independent data files.
-
-Package: libbioimagesuite2
-Architecture: any
-Section: libs
-Depends: ${shlibs:Depends}
-Description: integrated image analysis software suite
- BioImage Suite has extensive capabilities for both neuro/cardiac
- and abdominal image analysis and state of the art visualization.
- Many packages are available that are highly extensible, and provide
- functionality for image visualization and registration, surface
- editing, cardiac 4D multi-slice editing, diffusion tensor image
- processing, mouse segmentation and registration, and much more. It
- can be integrated with other biomedical image processing software,
- such as FSL and SPM. This site provides information, downloads,
- documentation, and other resources for users of the software.
- .
- BioImage Suite was developed at Yale University and has been
- extensively used at different labs at Yale since 2004.
- .
- This package contains library files.
diff --git a/debian/copyright b/debian/copyright
deleted file mode 100644
index add3f8f..0000000
--- a/debian/copyright
+++ /dev/null
@@ -1,33 +0,0 @@
-Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Upstream-Name: BioImageSuite
-Source: http://www.bioimagesuite.org/public/Downloads.html
-Comment: You need to login to download the source
-
-Files: *
-Copyright: © 2001-2011 X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda,
-                       R.T. Constable, L.H. Staib,
-                       Section of Bioimaging Sciences, Dept. of Diagnostic Radiology,
-                       Yale School of Medicine
-License: GPL-2+
-
-Files: debian/*
-Copyright: © 2007 David Paleino <d.paleino at gmail.com>
-License: GPL-2+
-
-License: GPL-2+
-    This package is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
- .
-    This package is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
- .
-    You should have received a copy of the GNU General Public License
-    along with this package; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
- .
- On Debian systems, the complete text of the GNU General
- Public License can be found in `/usr/share/common-licenses/GPL'.
diff --git a/debian/get-orig-source b/debian/get-orig-source
deleted file mode 100755
index 833930e..0000000
--- a/debian/get-orig-source
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh -e
-# This will download the original source tarball to ../tarballs
-TARDIR=`pwd`/../tarballs
-TARNAME=bioimagesuite_latest_Linux_g++32.tar.gz
-NAME=bioimagesuite
-
-mkdir -p "$TARDIR"
-wget --user anonymous --password bioimagesuite \
-	http://www.bioimagesuite.org/download/linux_gcc32/${TARNAME} \
-	-P "$TARDIR"
-
-# Obtain upstream version number from changelog
-# Unfortunately upstream does not maintain version numbers in their
-# tarball.  So we have to relay on the correct version number in
-# debian/changelog
-version=`dpkg-parsechangelog | grep "^Version:" | sed -e "s/^Version:[[:space:]]\+\([\.0-9]\+\)-*[0-9]*[[:space:]]*/\1/"`
-
-# rebuild the tarball
-cd "$TARDIR"
-tar -xzf ${TARNAME}
-mv ${NAME} ${NAME}-${version}
-GZIP="--best --no-name" tar -czf ${NAME}_${version}.orig.tar.gz ${NAME}-${version}
-rm -rf ${NAME}-${version} ${TARNAME}
diff --git a/debian/libbioimagesuite2.dirs b/debian/libbioimagesuite2.dirs
deleted file mode 100644
index 28aa8e0..0000000
--- a/debian/libbioimagesuite2.dirs
+++ /dev/null
@@ -1,2 +0,0 @@
-usr/lib
-#usr/share/lintian/overrides
diff --git a/debian/libbioimagesuite2.install b/debian/libbioimagesuite2.install
deleted file mode 100644
index 51003b4..0000000
--- a/debian/libbioimagesuite2.install
+++ /dev/null
@@ -1 +0,0 @@
-lib/*	usr/lib/
diff --git a/debian/libbioimagesuite2.lintian-overrides b/debian/libbioimagesuite2.lintian-overrides
deleted file mode 100644
index af532dd..0000000
--- a/debian/libbioimagesuite2.lintian-overrides
+++ /dev/null
@@ -1,33 +0,0 @@
-#libbioimagesuite2: several-sonames-in-same-package libvtkmpjCommonTCL.so libvtkmpjDiffusionTCL.so libvtkmpjGraphicsTCL.so libvtkmpjLevelsetTCL.so libvtknrCommonTCL.so libvtknrGraphicsTCL.so libvtknrImagingTCL.so libvtknrNmrlibTCL.so libvtkpxClosedTCL.so libvtkpxCommonTCL.so libvtkpxGUITCL.so libvtkpxGraphicsTCL.so libvtkpxImagingTCL.so libvtkpxLegacyTCL.so libvtkpxLevelsetTCL.so libvtkpxNmrlibTCL.so libvtkpxRegistrationTCL.so libvtkpxSegmentationTCL.so
-
-#libbioimagesuite2: package-name-doesnt-match-sonames libvtkmpjCommonTCL libvtkmpjDiffusionTCL libvtkmpjGraphicsTCL libvtkmpjLevelsetTCL libvtknrCommonTCL libvtknrGraphicsTCL libvtknrImagingTCL libvtknrNmrlibTCL libvtkpxClosedTCL libvtkpxCommonTCL libvtkpxGUITCL libvtkpxGraphicsTCL libvtkpxImagingTCL libvtkpxLegacyTCL libvtkpxLevelsetTCL libvtkpxNmrlibTCL libvtkpxRegistrationTCL libvtkpxSegmentationTCL
-
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtknrCommonTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkpxLevelsetTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkpxLegacyTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkmpjCommonTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkmpjDiffusionTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtknrNmrlibTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkpxNmrlibTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtknrGraphicsTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkpxImagingTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkpxCommonTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkpxSegmentationTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkpxRegistrationTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkpxClosedTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkpxGraphicsTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkmpjGraphicsTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkmpjLevelsetTCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtkpxGUITCL.so
-#libbioimagesuite2: no-shlibs-control-file usr/lib/libvtknrImagingTCL.so
-
-#libbioimagesuite2: shlib-with-non-pic-code usr/lib/libvtknrCommonTCL.so
-#libbioimagesuite2: shlib-with-non-pic-code usr/lib/libvtkpxClosedTCL.so
-#libbioimagesuite2: shlib-with-non-pic-code usr/lib/libvtknrNmrlibTCL.so
-#libbioimagesuite2: shlib-with-non-pic-code usr/lib/libvtkpxNmrlibTCL.so
-#libbioimagesuite2: shlib-with-non-pic-code usr/lib/libvtkpxCommonTCL.so
-#libbioimagesuite2: shlib-with-non-pic-code usr/lib/libvtkpxRegistrationTCL.so
-#libbioimagesuite2: shlib-with-non-pic-code usr/lib/libvtkpxGUITCL.so
-
-#libbioimagesuite2: shlib-with-executable-stack usr/lib/libvtkpxClosedTCL.so
-#libbioimagesuite2: shlib-with-executable-stack usr/lib/libvtkpxCommonTCL.so
diff --git a/debian/libbioimagesuite2.postinst b/debian/libbioimagesuite2.postinst
deleted file mode 100644
index 5e337c3..0000000
--- a/debian/libbioimagesuite2.postinst
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/bin/sh
-# postinst script for bioimagesuite
-#
-# see: dh_installdeb(1)
-
-set -e
-
-case "$1" in
-    configure)
-    	 if [ -x /sbin/ldconfig ]
-    	 then
-    	 	/sbin/ldconfig
-    	 fi
-    ;;
-
-    *)
-        echo "postinst called with unknown argument \`$1'" >&2
-        exit 1
-    ;;
-esac
-
-#DEBHELPER#
-
-exit 0
-
-
diff --git a/debian/libbioimagesuite2.shlibs.local b/debian/libbioimagesuite2.shlibs.local
deleted file mode 100644
index 0d10b20..0000000
--- a/debian/libbioimagesuite2.shlibs.local
+++ /dev/null
@@ -1,19 +0,0 @@
-#libbioimagesuite2		2	bioimagesuite (>= 2.0-1)
-libvtkmpjCommonTCL		2	libbioimagesuite2 (>= 2.0-1)
-libvtkmpjDiffusionTCL	2	libbioimagesuite2 (>= 2.0-1)
-libvtkmpjGraphicsTCL	2	libbioimagesuite2 (>= 2.0-1)
-libvtkmpjLevelsetTCL	2	libbioimagesuite2 (>= 2.0-1)
-libvtknrCommonTCL		2	libbioimagesuite2 (>= 2.0-1)
-libvtknrGraphicsTCL		2	libbioimagesuite2 (>= 2.0-1)
-libvtknrImagingTCL		2	libbioimagesuite2 (>= 2.0-1)
-libvtknrNmrlibTCL		2	libbioimagesuite2 (>= 2.0-1)
-libvtkpxClosedTCL		2	libbioimagesuite2 (>= 2.0-1)
-libvtkpxCommonTCL		2	libbioimagesuite2 (>= 2.0-1)
-libvtkpxGUITCL			2	libbioimagesuite2 (>= 2.0-1)
-libvtkpxGraphicsTCL		2	libbioimagesuite2 (>= 2.0-1)
-libvtkpxImagingTCL		2	libbioimagesuite2 (>= 2.0-1)
-libvtkpxLegacyTCL		2	libbioimagesuite2 (>= 2.0-1)
-libvtkpxLevelsetTCL		2	libbioimagesuite2 (>= 2.0-1)
-libvtkpxNmrlibTCL		2	libbioimagesuite2 (>= 2.0-1)
-libvtkpxRegistrationTCL	2	libbioimagesuite2 (>= 2.0-1)
-libvtkpxSegmentationTCL	2	libbioimagesuite2 (>= 2.0-1)
diff --git a/debian/old/README.Debian b/debian/old/README.Debian
deleted file mode 100644
index 8d825a3..0000000
--- a/debian/old/README.Debian
+++ /dev/null
@@ -1,6 +0,0 @@
-bioimagesuite for Debian
-------------------------
-
-<possible notes regarding this package - if none, delete this file>
-
- -- David Paleino <d.paleino at gmail.com>  Fri, 26 Oct 2007 22:12:21 +0200
diff --git a/debian/old/bioimagesuite-dev.dirs b/debian/old/bioimagesuite-dev.dirs
deleted file mode 100644
index 4b49768..0000000
--- a/debian/old/bioimagesuite-dev.dirs
+++ /dev/null
@@ -1 +0,0 @@
-usr/include/bioimagesuite
diff --git a/debian/old/bioimagesuite-dev.install b/debian/old/bioimagesuite-dev.install
deleted file mode 100644
index d380444..0000000
--- a/debian/old/bioimagesuite-dev.install
+++ /dev/null
@@ -1 +0,0 @@
-include/* usr/include/bioimagesuite/
diff --git a/debian/old/control.old b/debian/old/control.old
deleted file mode 100644
index a5e2f39..0000000
--- a/debian/old/control.old
+++ /dev/null
@@ -1,63 +0,0 @@
-Source: bioimagesuite
-Section: science
-Priority: optional
-Maintainer: David Paleino <d.paleino at gmail.com>
-Build-Depends: debhelper (>= 5)
-Standards-Version: 3.7.2
-Homepage: http://www.bioimagesuite.org
-
-Package: bioimagesuite
-Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, itk3.1, libvtk5, libmetakit-tcl,
- tcllib, iwidgets4, itcl3.1, libminc0, bioimagesuite-dev
-Description: integrated image analysis suite
- BioImage Suite is an integrated image analysis software suite developed at
- Yale University.
- .
- BioImage Suite has been published as:
-  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
-  Staib. BioImage Suite: An integrated medical image analysis suite,
-  Section of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale
-  School of Medicine. http://www.bioimagesuite.org .
-
-Package: bioimagesuite-dev
-Architecture: any
-Description: integrated image analysis suite - development headers
- BioImage Suite is an integrated image analysis software suite developed at
- Yale University.
- .
- BioImage Suite has been published as:
-  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
-  Staib. BioImage Suite: An integrated medical image analysis suite,
-  Section of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale
-  School of Medicine. http://www.bioimagesuite.org .
- .
- This package contains the development header files.
-
-Package: bioimagesuite-data
-Architecture: all
-Description: integrated image analysis suite - common data files
- BioImage Suite is an integrated image analysis software suite developed at
- Yale University.
- .
- BioImage Suite has been published as:
-  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
-  Staib. BioImage Suite: An integrated medical image analysis suite,
-  Section of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale
-  School of Medicine. http://www.bioimagesuite.org .
- .
- This package contains architecture-independent data files.
-
-Package: bioimagesuite-libs
-Architecture: any
-Description: integrated image analysis suite - library files
- BioImage Suite is an integrated image analysis software suite developed at
- Yale University.
- .
- BioImage Suite has been published as:
-  X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H
-  Staib. BioImage Suite: An integrated medical image analysis suite,
-  Section of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale
-  School of Medicine. http://www.bioimagesuite.org .
- .
- This package contains library files.
diff --git a/debian/old/libbioimagesuite-dev.install b/debian/old/libbioimagesuite-dev.install
deleted file mode 100644
index 5f446b0..0000000
--- a/debian/old/libbioimagesuite-dev.install
+++ /dev/null
@@ -1 +0,0 @@
-lib/*.a	usr/lib/bioimagesuite/
diff --git a/debian/patches/edit_paths.patch b/debian/patches/edit_paths.patch
deleted file mode 100644
index 65e3515..0000000
--- a/debian/patches/edit_paths.patch
+++ /dev/null
@@ -1,88 +0,0 @@
-Index: bioimagesuite-2.0/setpaths.csh
-===================================================================
---- bioimagesuite-2.0.orig/setpaths.csh	2007-11-01 13:39:12.000000000 +0100
-+++ bioimagesuite-2.0/setpaths.csh	2007-11-01 13:40:21.000000000 +0100
-@@ -1,23 +1,14 @@
-+#!/bin/sh
- #Script file to set paths for bioimagesuite
- 
- # Temp fix
--setenv BASE /usr/local/bioimagesuite
-+setenv BASE /usr/lib/bioimagesuite
- setenv OS `uname`
- 
--if ( $OS == "Darwin") then
--    if (${?DISPLAY}) then
--	source /usr/local/vtk44_x11_yale/setvtk44.csh
--    else
--        source /usr/local/vtk44_carbon_yale/setvtk44.csh
--    endif
--else
--    source /usr/local/vtk44_yale/setvtk44.csh
--endif
-+source /usr/local/vtk44_yale/setvtk44.csh
- 
- source /usr/local/itk241_yale/setitk241.csh
- 
--if (-r /usr/local/bioimagesuite_extra/setextra.csh ) source /usr/local/bioimagesuite_extra/setextra.csh
--
- setenv FSLDIR /usr/local/fsl
- setenv FSLOUTPUTTYPE ANALYZE
- 
-Index: bioimagesuite-2.0/setpaths.sh
-===================================================================
---- bioimagesuite-2.0.orig/setpaths.sh	2007-11-01 13:39:12.000000000 +0100
-+++ bioimagesuite-2.0/setpaths.sh	2007-11-01 13:40:21.000000000 +0100
-@@ -1,25 +1,14 @@
-+#!/bin/sh
- #Script file to set paths for bioimagesuite
- 
--BASE=/usr/local/bioimagesuite
-+BASE=/usr/lib/bioimagesuite
- OS=`uname`
--if [ $OS == "Darwin" ]; then
--    if [ -n "$DISPLAY" ]; then
--	source /usr/local/vtk44_x11_yale/setvtk44.sh
--     else
--        source /usr/local/vtk44_carbon_yale/setvtk44.sh
--    fi
--else
--    source /usr/local/vtk44_yale/setvtk44.sh
--fi
--
- 
-+source /usr/local/vtk44_yale/setvtk44.sh
- 
- source /usr/local/itk241_yale/setitk241.sh
- 
- 
--if [ -r /usr/local/bioimagesuite_extra/setextra.sh ]; then
--	source /usr/local/bioimagesuite_extra/setextra.sh
--    fi
- 
- 
- FSLDIR=/usr/local/fsl
-Index: bioimagesuite-2.0/start_bioimagesuite
-===================================================================
---- bioimagesuite-2.0.orig/start_bioimagesuite	2007-11-01 13:39:12.000000000 +0100
-+++ bioimagesuite-2.0/start_bioimagesuite	2007-11-01 13:40:21.000000000 +0100
-@@ -1,6 +1,5 @@
- #!/bin/sh
- 
--BASE=/usr/local/bioimagesuite
-+BASE=/usr/lib/bioimagesuite
- source ${BASE}/setpaths.sh
- pxmenu.tcl
--
-Index: bioimagesuite-2.0/surfaceeditor
-===================================================================
---- bioimagesuite-2.0.orig/surfaceeditor	2007-11-02 18:58:54.000000000 +0100
-+++ bioimagesuite-2.0/surfaceeditor	2007-11-02 18:58:59.000000000 +0100
-@@ -1,6 +1,6 @@
- #!/bin/sh
- 
--BASE=/usr/local/bioimagesuite
-+BASE=/usr/lib/bioimagesuite
- source ${BASE}/setpaths.sh
- pxitclsurfaceeditor.tcl
- 
diff --git a/debian/patches/series b/debian/patches/series
deleted file mode 100644
index 98c61a6..0000000
--- a/debian/patches/series
+++ /dev/null
@@ -1 +0,0 @@
-edit_paths.patch
diff --git a/debian/rules b/debian/rules
deleted file mode 100755
index f5bf7ae..0000000
--- a/debian/rules
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/make -f
-# -*- makefile -*-
-
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-include /usr/share/quilt/quilt.make
-
-build: patch build-stamp
-build-stamp:
-	dh_testdir
-	touch $@
-
-clean: unpatch
-	dh_testdir
-	dh_testroot
-
-	dh_clean build-stamp
-
-install: build
-	dh_testdir
-	dh_testroot
-	dh_clean -k 
-	dh_installdirs
-	dh_install
-	
-	# Removing RPATH...
-	chrpath -d $(CURDIR)/debian/libbioimagesuite2/usr/lib/*.so
-	
-	# Fixing permissions...
-	chmod -R a-x $(CURDIR)/debian/bioimagesuite-data/usr/share/bioimagesuite/images/*
-	
-	# Installing Lintian overrides
-#	install -m 644 \
-#	debian/libbioimagesuite2.lintian-override \
-#	$(CURDIR)/debian/libbioimagesuite2/usr/share/lintian/overrides/libbioimagesuite2
-	
-#	install -m 644 \
-#	debian/bioimagesuite.lintian-override \
-#	$(CURDIR)/debian/bioimagesuite/usr/share/lintian/overrides/bioimagesuite
-
-binary-common: build install
-	dh_testdir
-	dh_testroot
-	dh_installchangelogs 
-	dh_installdocs
-	dh_installexamples
-#	dh_install
-	dh_installman
-	dh_link
-	dh_strip
-	dh_compress
-	dh_fixperms
-	dh_installdeb
-	dh_makeshlibs
-	# PLEASE FIX THIS:
-	# dpkg-shlibdeps: failure: couldn't find library libvtkCommonTCL.so
-	#  (note: only packages with 'shlibs' files are looked into).
-	#dh_shlibdeps
-	dh_gencontrol
-	dh_md5sums
-	dh_builddeb
-
-binary-indep: binary-common
-binary-arch: binary-common
-
-binary: binary-indep binary-arch
-
-get-orig-source:
-	# This will download the original source tarball
-	# to ../tarballs
-	sh debian/get-orig-source
-
-.PHONY: build clean binary-indep binary-arch binary install
diff --git a/debian/upstream/metadata b/debian/upstream/metadata
deleted file mode 100644
index 60b9202..0000000
--- a/debian/upstream/metadata
+++ /dev/null
@@ -1,30 +0,0 @@
-Reference:
- - Author: X. Papademetris and M. Jackowski and N. Rajeevan and R. T. Constable and L. Staib
-   Title: "BioImage Suite: An integrated medical image analysis suite"
-   Journal: Insight Journal
-   Year: 2005
-   URL: http://hdl.handle.net/1926/37
-   eprint: http://www.insight-journal.org/download/viewpdf/30/101/bitstream
- - Author: Alark Joshi and Dustin Scheinost and Hirohito Okuda and Dominique Belhachemi and Isabella Murphy and Lawrence H Staib and Xenophon Papademetris
-   Title: "Unified framework for development, deployment and robust testing of neuroimaging algorithms"
-   Journal: Neuroinformatics
-   Year: 2011
-   Volume: 9
-   Number: 1
-   Pages: 69-84
-   DOI: 10.1007/s12021-010-9092-8
-   PMID: 21249532
-   URL: http://www.springerlink.com/content/m763304211482j8r/?MUD=MP
-   eprint: http://www.springerlink.com/content/m763304211482j8r/fulltext.pdf
- - Author: Dustin Scheinost and Thomas Z Teisseyre and Marcello Distasio and Matthew N DeSalvo and Xenophon Papademetris and Hal Blumenfeld
-   Title: "New open-source ictal SPECT analysis method implemented in BioImage Suite"
-   Journal: Epilepsia
-   Year: 2010
-   Volume: 51
-   Number: 4
-   Pages: 703-7
-   DOI: 10.1111/j.1528-1167.2009.02425.x
-   PMID: 20074234
-   URL: http://onlinelibrary.wiley.com/doi/10.1111/j.1528-1167.2009.02425.x/abstract
-   eprint: http://onlinelibrary.wiley.com/doi/10.1111/j.1528-1167.2009.02425.x/pdf
-Other-References: http://www.bioimagesuite.org/public/Papers.html

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/bioimagesuite.git



More information about the debian-med-commit mailing list